From 32b4b2ec8acf8dc5e5eca4efbf6ed0ad6be3c3de Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 19 Jul 2024 12:28:27 +0800 Subject: [PATCH 0001/1908] Downgrade node 22(.5) unit tests to 22.4 (#63728) * Downgrade node 22 unit tests to 22.4 until https://github.com/npm/cli/issues/7657 is fixed * try again * Try using a stable name for the tests so that required jobs do not require an update --- .github/workflows/create-block.yml | 10 +++++++--- .github/workflows/unit-test.yml | 20 ++++++++++++++------ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/.github/workflows/create-block.yml b/.github/workflows/create-block.yml index 0de1b9ee6566ae..245b136ee22c18 100644 --- a/.github/workflows/create-block.yml +++ b/.github/workflows/create-block.yml @@ -14,13 +14,17 @@ concurrency: jobs: checks: - name: Checks w/Node.js ${{ matrix.node }} on ${{ matrix.os }} + name: Checks w/Node.js ${{ matrix.node.name }} on ${{ matrix.os }} runs-on: ${{ matrix.os }} if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} strategy: fail-fast: false matrix: - node: ['20', '22'] + node: + - name: 20 + version: 20 + - name: 22 + version: 22.4 os: ['macos-latest', 'ubuntu-latest', 'windows-latest'] steps: @@ -31,7 +35,7 @@ jobs: - name: Setup Node.js and install dependencies uses: ./.github/setup-node with: - node-version: ${{ matrix.node }} + node-version: ${{ matrix.node.version }} - name: Create block shell: bash diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 488f41c217e7c2..75a0d34ddc8d87 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -21,13 +21,17 @@ concurrency: jobs: unit-js: - name: JavaScript (Node.js ${{ matrix.node }}) ${{ matrix.shard }} + name: JavaScript (Node.js ${{ matrix.node.name }}) ${{ matrix.shard }} runs-on: ubuntu-latest if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} strategy: fail-fast: false matrix: - node: ['20', '22'] + node: + - name: 20 + version: 20 + - name: 22 + version: 22.4 shard: ['1/4', '2/4', '3/4', '4/4'] steps: @@ -39,7 +43,7 @@ jobs: - name: Setup Node.js and install dependencies uses: ./.github/setup-node with: - node-version: ${{ matrix.node }} + node-version: ${{ matrix.node.version }} - name: Determine the number of CPU cores uses: SimenB/github-actions-cpu-cores@97ba232459a8e02ff6121db9362b09661c875ab8 # v2.0.0 @@ -60,13 +64,17 @@ jobs: --cacheDirectory="$HOME/.jest-cache" unit-js-date: - name: JavaScript Date Tests (Node.js ${{ matrix.node }}) + name: JavaScript Date Tests (Node.js ${{ matrix.node.name }}) runs-on: ubuntu-latest if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} strategy: fail-fast: false matrix: - node: ['20', '22'] + node: + - name: 20 + version: 20 + - name: 22 + version: 22.4 steps: - name: Checkout repository @@ -77,7 +85,7 @@ jobs: - name: Setup Node.js and install dependencies uses: ./.github/setup-node with: - node-version: ${{ matrix.node }} + node-version: ${{ matrix.node.version }} - name: Determine the number of CPU cores uses: SimenB/github-actions-cpu-cores@97ba232459a8e02ff6121db9362b09661c875ab8 # v2.0.0 From 3053d39cc62a859e2320d9d7dcc3b0acb53f1ac2 Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Fri, 19 Jul 2024 07:19:21 +0200 Subject: [PATCH 0002/1908] Fix: DataViews: Layout resets for patterns each time a new pattern category is selected. (#63711) * Fix: DataViews: Layout resets for patterns each time a new pattern category is selected. * Use the state updater function Co-authored-by: jorgefilipecosta Co-authored-by: Mamaduka Co-authored-by: jameskoster Co-authored-by: aaronrobertshaw Co-authored-by: mrfoxtalbot Co-authored-by: talldan --- packages/edit-site/src/components/page-patterns/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index 6304c89d711fc6..a1b4f2a0912de4 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -351,7 +351,7 @@ export default function DataviewsPatterns() { // Reset the page number when the category changes. useEffect( () => { if ( previousCategoryId !== categoryId ) { - setView( DEFAULT_VIEW ); + setView( ( prevView ) => ( { ...prevView, page: 1 } ) ); } }, [ categoryId, previousCategoryId ] ); const { data, paginationInfo } = useMemo( () => { From ef198f9d3416dca97ebee84584652d8be0e87f4b Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 19 Jul 2024 13:41:15 +0800 Subject: [PATCH 0003/1908] Ensure root selector (body) is not wrapped in :root :where() (#63726) * Ensure root selector (body) is not wrapped in :root :where() to keep specificity at 0,0,1 * Fix PHP unit tests * Update editor root selector specificity * Update node structure unit test * Add backport changelog ---- Unlinked contributors: mleathem. Co-authored-by: talldan Co-authored-by: aaronrobertshaw Co-authored-by: andrewserong --- backport-changelog/6.6/7061.md | 3 +++ lib/class-wp-theme-json-gutenberg.php | 15 +++++++++----- .../test/use-global-styles-output.js | 3 ++- .../global-styles/use-global-styles-output.js | 3 +++ phpunit/class-wp-theme-json-test.php | 20 +++++++++---------- 5 files changed, 28 insertions(+), 16 deletions(-) create mode 100644 backport-changelog/6.6/7061.md diff --git a/backport-changelog/6.6/7061.md b/backport-changelog/6.6/7061.md new file mode 100644 index 00000000000000..307e6575cf38d8 --- /dev/null +++ b/backport-changelog/6.6/7061.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7061 + +* https://github.com/WordPress/gutenberg/pull/63726 diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index df46c3399a2a76..65a5e5fe4b9578 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2921,6 +2921,9 @@ static function ( $pseudo_selector ) use ( $selector ) { } /* + * Root selector (body) styles should not be wrapped in `:root where()` to keep + * specificity at (0,0,1) and maintain backwards compatibility. + * * Top-level element styles using element-only specificity selectors should * not get wrapped in `:root :where()` to maintain backwards compatibility. * @@ -2928,11 +2931,13 @@ static function ( $pseudo_selector ) use ( $selector ) { * still need to be wrapped in `:root :where` to cap specificity for nested * variations etc. Pseudo selectors won't match the ELEMENTS selector exactly. */ - $element_only_selector = $current_element && - isset( static::ELEMENTS[ $current_element ] ) && - // buttons, captions etc. still need `:root :where()` as they are class based selectors. - ! isset( static::__EXPERIMENTAL_ELEMENT_CLASS_NAMES[ $current_element ] ) && - static::ELEMENTS[ $current_element ] === $selector; + $element_only_selector = $is_root_selector || ( + $current_element && + isset( static::ELEMENTS[ $current_element ] ) && + // buttons, captions etc. still need `:root :where()` as they are class based selectors. + ! isset( static::__EXPERIMENTAL_ELEMENT_CLASS_NAMES[ $current_element ] ) && + static::ELEMENTS[ $current_element ] === $selector + ); // 2. Generate and append the rules that use the general selector. $general_selector = $element_only_selector ? $selector : ":root :where($selector)"; diff --git a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js index 066f7e3a28019c..525a8a1d53d072 100644 --- a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js @@ -107,6 +107,7 @@ describe( 'global styles renderer', () => { }, }, selector: ROOT_BLOCK_SELECTOR, + skipSelectorWrapper: true, }, { styles: { @@ -481,7 +482,7 @@ describe( 'global styles renderer', () => { }; expect( toStyles( tree, blockSelectors ) ).toEqual( - ':where(body) {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }:root :where(body){background-color: red;margin: 10px;padding: 10px;}a:where(:not(.wp-element-button)){color: blue;}:root :where(a:where(:not(.wp-element-button)):hover){color: orange;}:root :where(a:where(:not(.wp-element-button)):focus){color: orange;}h1{font-size: 42px;}:root :where(.wp-block-group){margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}:root :where(h1,h2,h3,h4,h5,h6){color: orange;}:root :where(h1 a:where(:not(.wp-element-button)),h2 a:where(:not(.wp-element-button)),h3 a:where(:not(.wp-element-button)),h4 a:where(:not(.wp-element-button)),h5 a:where(:not(.wp-element-button)),h6 a:where(:not(.wp-element-button))){color: hotpink;}:root :where(h1 a:where(:not(.wp-element-button)):hover,h2 a:where(:not(.wp-element-button)):hover,h3 a:where(:not(.wp-element-button)):hover,h4 a:where(:not(.wp-element-button)):hover,h5 a:where(:not(.wp-element-button)):hover,h6 a:where(:not(.wp-element-button)):hover){color: red;}:root :where(h1 a:where(:not(.wp-element-button)):focus,h2 a:where(:not(.wp-element-button)):focus,h3 a:where(:not(.wp-element-button)):focus,h4 a:where(:not(.wp-element-button)):focus,h5 a:where(:not(.wp-element-button)):focus,h6 a:where(:not(.wp-element-button)):focus){color: red;}:root :where(.wp-block-image img, .wp-block-image .wp-crop-area){border-radius: 9999px;}:root :where(.wp-block-image){color: red;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}h1.has-blue-color,h2.has-blue-color,h3.has-blue-color,h4.has-blue-color,h5.has-blue-color,h6.has-blue-color{color: var(--wp--preset--color--blue) !important;}h1.has-blue-background-color,h2.has-blue-background-color,h3.has-blue-background-color,h4.has-blue-background-color,h5.has-blue-background-color,h6.has-blue-background-color{background-color: var(--wp--preset--color--blue) !important;}h1.has-blue-border-color,h2.has-blue-border-color,h3.has-blue-border-color,h4.has-blue-border-color,h5.has-blue-border-color,h6.has-blue-border-color{border-color: var(--wp--preset--color--blue) !important;}' + ':where(body) {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }body{background-color: red;margin: 10px;padding: 10px;}a:where(:not(.wp-element-button)){color: blue;}:root :where(a:where(:not(.wp-element-button)):hover){color: orange;}:root :where(a:where(:not(.wp-element-button)):focus){color: orange;}h1{font-size: 42px;}:root :where(.wp-block-group){margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}:root :where(h1,h2,h3,h4,h5,h6){color: orange;}:root :where(h1 a:where(:not(.wp-element-button)),h2 a:where(:not(.wp-element-button)),h3 a:where(:not(.wp-element-button)),h4 a:where(:not(.wp-element-button)),h5 a:where(:not(.wp-element-button)),h6 a:where(:not(.wp-element-button))){color: hotpink;}:root :where(h1 a:where(:not(.wp-element-button)):hover,h2 a:where(:not(.wp-element-button)):hover,h3 a:where(:not(.wp-element-button)):hover,h4 a:where(:not(.wp-element-button)):hover,h5 a:where(:not(.wp-element-button)):hover,h6 a:where(:not(.wp-element-button)):hover){color: red;}:root :where(h1 a:where(:not(.wp-element-button)):focus,h2 a:where(:not(.wp-element-button)):focus,h3 a:where(:not(.wp-element-button)):focus,h4 a:where(:not(.wp-element-button)):focus,h5 a:where(:not(.wp-element-button)):focus,h6 a:where(:not(.wp-element-button)):focus){color: red;}:root :where(.wp-block-image img, .wp-block-image .wp-crop-area){border-radius: 9999px;}:root :where(.wp-block-image){color: red;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}h1.has-blue-color,h2.has-blue-color,h3.has-blue-color,h4.has-blue-color,h5.has-blue-color,h6.has-blue-color{color: var(--wp--preset--color--blue) !important;}h1.has-blue-background-color,h2.has-blue-background-color,h3.has-blue-background-color,h4.has-blue-background-color,h5.has-blue-background-color,h6.has-blue-background-color{background-color: var(--wp--preset--color--blue) !important;}h1.has-blue-border-color,h2.has-blue-border-color,h3.has-blue-border-color,h4.has-blue-border-color,h5.has-blue-border-color,h6.has-blue-border-color{border-color: var(--wp--preset--color--blue) !important;}' ); } ); diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 58c1fa35b600a2..63d6a2fb22dd7a 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -649,6 +649,9 @@ export const getNodesWithStyles = ( tree, blockSelectors ) => { nodes.push( { styles, selector: ROOT_BLOCK_SELECTOR, + // Root selector (body) styles should not be wrapped in `:root where()` to keep + // specificity at (0,0,1) and maintain backwards compatibility. + skipSelectorWrapper: true, } ); } diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index d76517091f44fb..2f76ec7a5d4739 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -552,7 +552,7 @@ public function test_get_stylesheet() { ); $variables = ':root{--wp--preset--color--grey: grey;--wp--preset--gradient--custom-gradient: linear-gradient(135deg,rgba(0,0,0) 0%,rgb(0,0,0) 100%);--wp--preset--font-size--small: 14px;--wp--preset--font-size--big: 41px;--wp--preset--font-family--arial: Arial, serif;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}'; - $styles = static::$base_styles . ':root :where(body){color: var(--wp--preset--color--grey);}a:where(:not(.wp-element-button)){background-color: #333;color: #111;}:root :where(.wp-element-button, .wp-block-button__link){box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.66);}:root :where(.wp-block-cover){min-height: unset;aspect-ratio: 16/9;}:root :where(.wp-block-group){background: var(--wp--preset--gradient--custom-gradient);border-radius: 10px;min-height: 50vh;padding: 24px;}:root :where(.wp-block-group a:where(:not(.wp-element-button))){color: #111;}:root :where(.wp-block-heading){color: #123456;}:root :where(.wp-block-heading a:where(:not(.wp-element-button))){background-color: #333;color: #111;font-size: 60px;}:root :where(.wp-block-media-text){text-align: center;}:root :where(.wp-block-post-date){color: #123456;}:root :where(.wp-block-post-date a:where(:not(.wp-element-button))){background-color: #777;color: #555;}:root :where(.wp-block-post-excerpt){column-count: 2;}:root :where(.wp-block-image){margin-bottom: 30px;}:root :where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-top-left-radius: 10px;border-bottom-right-radius: 1em;}:root :where(.wp-block-image img, .wp-block-image .components-placeholder){filter: var(--wp--preset--duotone--custom-duotone);}'; + $styles = static::$base_styles . 'body{color: var(--wp--preset--color--grey);}a:where(:not(.wp-element-button)){background-color: #333;color: #111;}:root :where(.wp-element-button, .wp-block-button__link){box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.66);}:root :where(.wp-block-cover){min-height: unset;aspect-ratio: 16/9;}:root :where(.wp-block-group){background: var(--wp--preset--gradient--custom-gradient);border-radius: 10px;min-height: 50vh;padding: 24px;}:root :where(.wp-block-group a:where(:not(.wp-element-button))){color: #111;}:root :where(.wp-block-heading){color: #123456;}:root :where(.wp-block-heading a:where(:not(.wp-element-button))){background-color: #333;color: #111;font-size: 60px;}:root :where(.wp-block-media-text){text-align: center;}:root :where(.wp-block-post-date){color: #123456;}:root :where(.wp-block-post-date a:where(:not(.wp-element-button))){background-color: #777;color: #555;}:root :where(.wp-block-post-excerpt){column-count: 2;}:root :where(.wp-block-image){margin-bottom: 30px;}:root :where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-top-left-radius: 10px;border-bottom-right-radius: 1em;}:root :where(.wp-block-image img, .wp-block-image .components-placeholder){filter: var(--wp--preset--duotone--custom-duotone);}'; $presets = '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-custom-gradient-gradient-background{background: var(--wp--preset--gradient--custom-gradient) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-big-font-size{font-size: var(--wp--preset--font-size--big) !important;}.has-arial-font-family{font-family: var(--wp--preset--font-family--arial) !important;}'; $all = $variables . $styles . $presets; @@ -1361,7 +1361,7 @@ public function test_get_stylesheet_generates_fluid_typography_values() { unregister_block_type( 'test/clamp-me' ); $this->assertSame( - ':root{--wp--preset--font-size--pickles: clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.156), 16px);--wp--preset--font-size--toast: clamp(14.642px, 0.915rem + ((1vw - 3.2px) * 0.575), 22px);}:root :where(body){font-size: clamp(0.875em, 0.875rem + ((1vw - 0.2em) * 0.156), 1em);}h1{font-size: clamp(50.171px, 3.136rem + ((1vw - 3.2px) * 3.893), 100px);}:root :where(.wp-block-test-clamp-me){font-size: clamp(27.894px, 1.743rem + ((1vw - 3.2px) * 1.571), 48px);}.has-pickles-font-size{font-size: var(--wp--preset--font-size--pickles) !important;}.has-toast-font-size{font-size: var(--wp--preset--font-size--toast) !important;}', + ':root{--wp--preset--font-size--pickles: clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.156), 16px);--wp--preset--font-size--toast: clamp(14.642px, 0.915rem + ((1vw - 3.2px) * 0.575), 22px);}body{font-size: clamp(0.875em, 0.875rem + ((1vw - 0.2em) * 0.156), 1em);}h1{font-size: clamp(50.171px, 3.136rem + ((1vw - 3.2px) * 3.893), 100px);}:root :where(.wp-block-test-clamp-me){font-size: clamp(27.894px, 1.743rem + ((1vw - 3.2px) * 1.571), 48px);}.has-pickles-font-size{font-size: var(--wp--preset--font-size--pickles) !important;}.has-toast-font-size{font-size: var(--wp--preset--font-size--toast) !important;}', $theme_json->get_stylesheet( array( 'styles', 'variables', 'presets' ), null, array( 'skip_root_layout_styles' => true ) ) ); } @@ -3418,7 +3418,7 @@ public function test_get_property_value_valid() { ) ); - $expected = ':root :where(body){background-color: #ffffff;color: #000000;}:root :where(.wp-element-button, .wp-block-button__link){background-color: #000000;color: #ffffff;}'; + $expected = 'body{background-color: #ffffff;color: #000000;}:root :where(.wp-element-button, .wp-block-button__link){background-color: #000000;color: #ffffff;}'; $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } @@ -3495,7 +3495,7 @@ public function test_get_property_value_loop() { ) ); - $expected = ':root :where(body){background-color: #ffffff;}:root :where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; + $expected = 'body{background-color: #ffffff;}:root :where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } @@ -3527,7 +3527,7 @@ public function test_get_property_value_recursion() { ) ); - $expected = ':root :where(body){background-color: #ffffff;color: #ffffff;}:root :where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; + $expected = 'body{background-color: #ffffff;color: #ffffff;}:root :where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } @@ -3550,7 +3550,7 @@ public function test_get_property_value_self() { ) ); - $expected = ':root :where(body){background-color: #ffffff;}'; + $expected = 'body{background-color: #ffffff;}'; $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } @@ -3579,7 +3579,7 @@ public function test_get_styles_for_block_with_padding_aware_alignments() { 'selector' => 'body', ); - $expected = ':where(body) { margin: 0; }.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }.has-global-padding :where(:not(.alignfull.is-layout-flow) > .has-global-padding:not(.wp-block-block, .alignfull)) { padding-right: 0; padding-left: 0; }.has-global-padding :where(:not(.alignfull.is-layout-flow) > .has-global-padding:not(.wp-block-block, .alignfull)) > .alignfull { margin-left: 0; margin-right: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:root :where(body){--wp--style--root--padding-top: 10px;--wp--style--root--padding-right: 12px;--wp--style--root--padding-bottom: 10px;--wp--style--root--padding-left: 12px;}'; + $expected = ':where(body) { margin: 0; }.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }.has-global-padding :where(:not(.alignfull.is-layout-flow) > .has-global-padding:not(.wp-block-block, .alignfull)) { padding-right: 0; padding-left: 0; }.has-global-padding :where(:not(.alignfull.is-layout-flow) > .has-global-padding:not(.wp-block-block, .alignfull)) > .alignfull { margin-left: 0; margin-right: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}body{--wp--style--root--padding-top: 10px;--wp--style--root--padding-right: 12px;--wp--style--root--padding-bottom: 10px;--wp--style--root--padding-left: 12px;}'; $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ); $style_rules = $theme_json->get_styles_for_block( $metadata ); $this->assertSame( $expected, $root_rules . $style_rules ); @@ -3607,7 +3607,7 @@ public function test_get_styles_for_block_without_padding_aware_alignments() { 'selector' => 'body', ); - $expected = static::$base_styles . ':root :where(body){padding-top: 10px;padding-right: 12px;padding-bottom: 10px;padding-left: 12px;}'; + $expected = static::$base_styles . 'body{padding-top: 10px;padding-right: 12px;padding-bottom: 10px;padding-left: 12px;}'; $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ); $style_rules = $theme_json->get_styles_for_block( $metadata ); $this->assertSame( $expected, $root_rules . $style_rules ); @@ -4782,7 +4782,7 @@ public function test_get_top_level_background_image_styles() { 'selector' => 'body', ); - $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:root :where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;background-attachment: fixed;}"; + $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}body{background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;background-attachment: fixed;}"; $this->assertSame( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background styles do not match expectations' ); $theme_json = new WP_Theme_JSON_Gutenberg( @@ -4800,7 +4800,7 @@ public function test_get_top_level_background_image_styles() { ) ); - $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:root :where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;background-attachment: fixed;}"; + $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}body{background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;background-attachment: fixed;}"; $this->assertSame( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background image as string type do not match expectations' ); } From dc41a6ee3e58fd9890a690a4514c2a1d415259ab Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Fri, 19 Jul 2024 09:56:10 +0400 Subject: [PATCH 0004/1908] Navigation Submenu: Remove user permission checks (#63720) Co-authored-by: Mamaduka Co-authored-by: tyxla --- .../block-library/src/navigation-submenu/edit.js | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/packages/block-library/src/navigation-submenu/edit.js b/packages/block-library/src/navigation-submenu/edit.js index 4decc2e68ffbbb..acc9510d0d3d30 100644 --- a/packages/block-library/src/navigation-submenu/edit.js +++ b/packages/block-library/src/navigation-submenu/edit.js @@ -29,7 +29,6 @@ import { import { isURL, prependHTTP } from '@wordpress/url'; import { useState, useEffect, useRef } from '@wordpress/element'; import { link as linkIcon, removeSubmenu } from '@wordpress/icons'; -import { useResourcePermissions } from '@wordpress/core-data'; import { speak } from '@wordpress/a11y'; import { createBlock } from '@wordpress/blocks'; import { useMergeRefs, usePrevious } from '@wordpress/compose'; @@ -134,7 +133,7 @@ export default function NavigationSubmenuEdit( { context, clientId, } ) { - const { label, type, url, description, rel, title } = attributes; + const { label, url, description, rel, title } = attributes; const { showSubmenuIcon, maxNestingLevel, openSubmenusOnClick } = context; @@ -154,9 +153,6 @@ export default function NavigationSubmenuEdit( { const itemLabelPlaceholder = __( 'Add text…' ); const ref = useRef(); - const pagesPermissions = useResourcePermissions( 'pages' ); - const postsPermissions = useResourcePermissions( 'posts' ); - const { parentCount, isParentOfSelectedBlock, @@ -264,13 +260,6 @@ export default function NavigationSubmenuEdit( { selection.addRange( range ); } - let userCanCreate = false; - if ( ! type || type === 'page' ) { - userCanCreate = pagesPermissions.canCreate; - } else if ( type === 'post' ) { - userCanCreate = postsPermissions.canCreate; - } - const { textColor, customTextColor, @@ -499,7 +488,6 @@ export default function NavigationSubmenuEdit( { } } } anchor={ popoverAnchor } - hasCreateSuggestion={ userCanCreate } onRemove={ () => { setAttributes( { url: '' } ); speak( __( 'Link removed.' ), 'assertive' ); From ed11e6fe975f335039362abc0c8bd2013f918be0 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 19 Jul 2024 09:12:36 +0300 Subject: [PATCH 0005/1908] Patterns: Render draggable only when enabled (#63715) Co-authored-by: tyxla Co-authored-by: Mamaduka --- .../components/inserter-draggable-blocks/index.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/inserter-draggable-blocks/index.js b/packages/block-editor/src/components/inserter-draggable-blocks/index.js index 7d20b5e53650bf..5a63535be3d3ce 100644 --- a/packages/block-editor/src/components/inserter-draggable-blocks/index.js +++ b/packages/block-editor/src/components/inserter-draggable-blocks/index.js @@ -43,6 +43,14 @@ const InserterDraggableBlocks = ( { useDispatch( blockEditorStore ) ); + if ( ! isEnabled ) { + return children( { + draggable: false, + onDragStart: undefined, + onDragEnd: undefined, + } ); + } + return ( { ( { onDraggableStart, onDraggableEnd } ) => { return children( { - draggable: isEnabled, - onDragStart: isEnabled ? onDraggableStart : undefined, - onDragEnd: isEnabled ? onDraggableEnd : undefined, + draggable: true, + onDragStart: onDraggableStart, + onDragEnd: onDraggableEnd, } ); } } From a2fb0fbf40b5556e23b5465ed4b8a859121fb376 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Fri, 19 Jul 2024 09:13:50 +0300 Subject: [PATCH 0006/1908] Fix patterns sorting by `title` (#63710) Co-authored-by: ntsekouras Co-authored-by: youknowriad --- packages/edit-site/src/components/page-patterns/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index a1b4f2a0912de4..27b75424e5f3b8 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -294,6 +294,7 @@ export default function DataviewsPatterns() { { header: __( 'Title' ), id: 'title', + getValue: ( { item } ) => item.title?.raw || item.title, render: ( { item } ) => , enableHiding: false, }, From 5d4bf270bf0abf21bb0eee8f92ddd4f2b35ef299 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Fri, 19 Jul 2024 09:14:10 +0300 Subject: [PATCH 0007/1908] Add post status icon in post summary (#63658) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../components/post-last-revision/index.js | 1 + .../src/components/post-panel-row/style.scss | 1 - .../src/components/post-status/index.js | 28 ++++++++++++------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/editor/src/components/post-last-revision/index.js b/packages/editor/src/components/post-last-revision/index.js index 73bcb7c0e026f9..d0f94e26048d77 100644 --- a/packages/editor/src/components/post-last-revision/index.js +++ b/packages/editor/src/components/post-last-revision/index.js @@ -64,6 +64,7 @@ export function PrivatePostLastRevision() { className="editor-private-post-last-revision__button" text={ revisionsCount } variant="tertiary" + size="compact" /> </PostPanelRow> </PostLastRevisionCheck> diff --git a/packages/editor/src/components/post-panel-row/style.scss b/packages/editor/src/components/post-panel-row/style.scss index 53e0c645f6f069..f76c586850500e 100644 --- a/packages/editor/src/components/post-panel-row/style.scss +++ b/packages/editor/src/components/post-panel-row/style.scss @@ -28,7 +28,6 @@ white-space: normal; text-wrap: balance; // Fallback for Safari. text-wrap: pretty; - height: auto; min-height: $button-size-compact; } diff --git a/packages/editor/src/components/post-status/index.js b/packages/editor/src/components/post-status/index.js index aacb933e1864ec..11b51bca80aa79 100644 --- a/packages/editor/src/components/post-status/index.js +++ b/packages/editor/src/components/post-status/index.js @@ -16,6 +16,13 @@ import { useState, useMemo } from '@wordpress/element'; import { store as coreStore } from '@wordpress/core-data'; import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor'; import { useInstanceId } from '@wordpress/compose'; +import { + drafts, + published, + scheduled, + pending, + notAllowed, +} from '@wordpress/icons'; /** * Internal dependencies @@ -31,13 +38,13 @@ import PostSticky from '../post-sticky'; import { PrivatePostSchedule } from '../post-schedule'; import { store as editorStore } from '../../store'; -const labels = { - 'auto-draft': __( 'Draft' ), - draft: __( 'Draft' ), - pending: __( 'Pending' ), - private: __( 'Private' ), - future: __( 'Scheduled' ), - publish: __( 'Published' ), +const postStatusesInfo = { + 'auto-draft': { label: __( 'Draft' ), icon: drafts }, + draft: { label: __( 'Draft' ), icon: drafts }, + pending: { label: __( 'Pending' ), icon: pending }, + private: { label: __( 'Private' ), icon: notAllowed }, + future: { label: __( 'Scheduled' ), icon: scheduled }, + publish: { label: __( 'Published' ), icon: published }, }; export const STATUS_OPTIONS = [ @@ -200,13 +207,14 @@ export default function PostStatus() { variant="tertiary" size="compact" onClick={ onToggle } + icon={ postStatusesInfo[ status ]?.icon } aria-label={ sprintf( // translators: %s: Current post status. __( 'Change post status: %s' ), - labels[ status ] + postStatusesInfo[ status ]?.label ) } > - { labels[ status ] } + { postStatusesInfo[ status ]?.label } </Button> ) } renderContent={ ( { onClose } ) => ( @@ -290,7 +298,7 @@ export default function PostStatus() { /> ) : ( <div className="editor-post-status is-read-only"> - { labels[ status ] } + { postStatusesInfo[ status ]?.label } </div> ) } </PostPanelRow> From 6b0b4e4d6e660f208bb73c92570e7b8bb7898145 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Fri, 19 Jul 2024 11:30:22 +0300 Subject: [PATCH 0008/1908] DataViews: Fix pattens list selection (#63733) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- packages/edit-site/src/components/page-patterns/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index 27b75424e5f3b8..65e79b406cf559 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -252,6 +252,7 @@ export default function DataviewsPatterns() { const { params: { postType, categoryId: categoryIdFromURL }, } = useLocation(); + const [ selection, setSelection ] = useState( [] ); const type = postType || PATTERN_TYPES.user; const categoryId = categoryIdFromURL || PATTERN_DEFAULT_CATEGORY; const [ view, setView ] = useState( DEFAULT_VIEW ); @@ -409,6 +410,8 @@ export default function DataviewsPatterns() { isLoading={ isResolving } view={ view } onChangeView={ setView } + selection={ selection } + onChangeSelection={ setSelection } defaultLayouts={ defaultLayouts } /> </Page> From 6a466a098650bb46154d0a293ae4bf0b88a1d3ef Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Fri, 19 Jul 2024 10:01:38 +0100 Subject: [PATCH 0009/1908] Zoom Out: Only show the inserters when a block is selected or hovered (#63668) * Zoom Out: Only show the inserters when a block is selected or hovered * Correct logic for rendering the zoom out inserters We want to show the inserters on hover, even if there is no selection. * Update shouldRenderInsertionPoint condition * Make the inserters always present and just toggle visibility * Update docs/reference-guides/data/data-core-block-editor.md * Update packages/block-editor/src/components/block-tools/zoom-out-mode-inserter-button.js * Update packages/block-editor/src/components/block-tools/zoom-out-mode-inserter-button.js * Update packages/block-editor/src/components/block-tools/zoom-out-mode-inserter-button.js * Update packages/block-editor/src/components/block-tools/zoom-out-mode-inserter-button.js * Update packages/block-editor/src/store/reducer.js * Update packages/block-editor/src/store/reducer.js * Update packages/block-editor/src/store/selectors.js * fix the property name * Reduce number of select calls by lifting useSelect calls to ZoomOutModeInserters --------- Co-authored-by: Jerry Jones <jones.jeremydavid@gmail.com> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> --- .../data/data-core-block-editor.md | 24 +++++++ .../block-list/use-block-props/index.js | 2 +- .../use-block-props/use-is-hovered.js | 37 +++++++---- .../src/components/block-tools/style.scss | 8 +++ .../zoom-out-mode-inserter-button.js | 47 ++++++++++++++ .../block-tools/zoom-out-mode-inserters.js | 63 ++++++++++++------- packages/block-editor/src/store/actions.js | 15 +++++ packages/block-editor/src/store/reducer.js | 18 ++++++ packages/block-editor/src/store/selectors.js | 10 +++ 9 files changed, 191 insertions(+), 33 deletions(-) create mode 100644 packages/block-editor/src/components/block-tools/zoom-out-mode-inserter-button.js diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index 4b66ad9eb6cb40..7eed5c8741288b 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -562,6 +562,18 @@ _Returns_ - `number`: Number of blocks in the post, or number of blocks with name equal to blockName. +### getHoveredBlockClientId + +Returns the currently hovered block. + +_Parameters_ + +- _state_ `Object`: Global application state. + +_Returns_ + +- `Object`: Client Id of the hovered block. + ### getInserterItems Determines the items that appear in the inserter. Includes both static items (e.g. a regular block type) and dynamic items (e.g. a reusable block). @@ -1257,6 +1269,18 @@ _Parameters_ Action that hides the insertion point. +### hoverBlock + +Returns an action object used in signalling that the block with the specified client ID has been hovered. + +_Parameters_ + +- _clientId_ `string`: Block client ID. + +_Returns_ + +- `Object`: Action object. + ### insertAfterBlock Action that inserts a default block after a given block. diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index 64e40559bb4735..6c44aa5c5d9705 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -115,7 +115,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { useFocusHandler( clientId ), useEventHandlers( { clientId, isSelected } ), useNavModeExit( clientId ), - useIsHovered(), + useIsHovered( { clientId } ), useIntersectionObserver(), useMovingAnimation( { triggerAnimationOnChange: index, clientId } ), useDisabled( { isDisabled: ! hasOverlay } ), diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-is-hovered.js b/packages/block-editor/src/components/block-list/use-block-props/use-is-hovered.js index 518ed583933acd..7c4b4aae8a70a1 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-is-hovered.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-is-hovered.js @@ -2,23 +2,37 @@ * WordPress dependencies */ import { useRefEffect } from '@wordpress/compose'; +import { useDispatch } from '@wordpress/data'; -function listener( event ) { - if ( event.defaultPrevented ) { - return; - } - - const action = event.type === 'mouseover' ? 'add' : 'remove'; - - event.preventDefault(); - event.currentTarget.classList[ action ]( 'is-hovered' ); -} +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../../../store'; /* * Adds `is-hovered` class when the block is hovered and in navigation or * outline mode. */ -export function useIsHovered() { +export function useIsHovered( { clientId } ) { + const { hoverBlock } = useDispatch( blockEditorStore ); + + function listener( event ) { + if ( event.defaultPrevented ) { + return; + } + + const action = event.type === 'mouseover' ? 'add' : 'remove'; + + event.preventDefault(); + event.currentTarget.classList[ action ]( 'is-hovered' ); + + if ( action === 'add' ) { + hoverBlock( clientId ); + } else { + hoverBlock( null ); + } + } + return useRefEffect( ( node ) => { node.addEventListener( 'mouseout', listener ); node.addEventListener( 'mouseover', listener ); @@ -29,6 +43,7 @@ export function useIsHovered() { // Remove class in case it lingers. node.classList.remove( 'is-hovered' ); + hoverBlock( null ); }; }, [] ); } diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index 20c0ab4104204b..6bf1f91cb08682 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -285,3 +285,11 @@ border: none; } } + +.block-editor-block-tools__zoom-out-mode-inserter-button { + visibility: hidden; + + &.is-visible { + visibility: visible; + } +} diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserter-button.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserter-button.js new file mode 100644 index 00000000000000..8ea80a53830135 --- /dev/null +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserter-button.js @@ -0,0 +1,47 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; +import { Button } from '@wordpress/components'; +import { plus } from '@wordpress/icons'; +import { _x } from '@wordpress/i18n'; + +function ZoomOutModeInserterButton( { isVisible, onClick } ) { + const [ + zoomOutModeInserterButtonHovered, + setZoomOutModeInserterButtonHovered, + ] = useState( false ); + + return ( + <Button + variant="primary" + icon={ plus } + size="compact" + className={ clsx( + 'block-editor-button-pattern-inserter__button', + 'block-editor-block-tools__zoom-out-mode-inserter-button', + { + 'is-visible': isVisible || zoomOutModeInserterButtonHovered, + } + ) } + onClick={ onClick } + onMouseOver={ () => { + setZoomOutModeInserterButtonHovered( true ); + } } + onMouseOut={ () => { + setZoomOutModeInserterButtonHovered( false ); + } } + label={ _x( + 'Add pattern', + 'Generic label for pattern inserter button' + ) } + /> + ); +} + +export default ZoomOutModeInserterButton; diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js index b64992cec44664..5f5b0401b512e0 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js @@ -3,28 +3,33 @@ */ import { useSelect } from '@wordpress/data'; import { useEffect, useRef, useState } from '@wordpress/element'; -import { Button } from '@wordpress/components'; -import { plus } from '@wordpress/icons'; -import { _x } from '@wordpress/i18n'; /** * Internal dependencies */ import BlockPopoverInbetween from '../block-popover/inbetween'; +import ZoomOutModeInserterButton from './zoom-out-mode-inserter-button'; import { store as blockEditorStore } from '../../store'; import { unlock } from '../../lock-unlock'; function ZoomOutModeInserters() { const [ isReady, setIsReady ] = useState( false ); const { + hasSelection, blockOrder, - sectionRootClientId, insertionPoint, setInserterIsOpened, - hasSelection, + sectionRootClientId, + selectedBlockClientId, + hoveredBlockClientId, } = useSelect( ( select ) => { - const { getSettings, getBlockOrder, getSelectionStart } = - select( blockEditorStore ); + const { + getSettings, + getBlockOrder, + getSelectionStart, + getSelectedBlockClientId, + getHoveredBlockClientId, + } = select( blockEditorStore ); const { sectionRootClientId: root } = unlock( getSettings() ); // To do: move ZoomOutModeInserters to core/editor. // Or we perhaps we should move the insertion point state to the @@ -40,6 +45,8 @@ function ZoomOutModeInserters() { sectionRootClientId: root, setInserterIsOpened: getSettings().__experimentalSetIsInserterOpened, + selectedBlockClientId: getSelectedBlockClientId(), + hoveredBlockClientId: getHoveredBlockClientId(), }; }, [] ); @@ -64,18 +71,39 @@ function ZoomOutModeInserters() { }; }, [] ); - if ( ! isReady || ! hasSelection ) { + if ( ! isReady ) { return null; } return [ undefined, ...blockOrder ].map( ( clientId, index ) => { + const shouldRenderInserter = insertionPoint.insertionIndex !== index; + + const shouldRenderInsertionPoint = + insertionPoint.insertionIndex === index; + + if ( ! shouldRenderInserter && ! shouldRenderInsertionPoint ) { + return null; + } + + const previousClientId = clientId; + const nextClientId = blockOrder[ index ]; + + const isSelected = + hasSelection && + ( selectedBlockClientId === previousClientId || + selectedBlockClientId === nextClientId ); + + const isHovered = + hoveredBlockClientId === previousClientId || + hoveredBlockClientId === nextClientId; + return ( <BlockPopoverInbetween key={ index } - previousClientId={ clientId } - nextClientId={ blockOrder[ index ] } + previousClientId={ previousClientId } + nextClientId={ nextClientId } > - { insertionPoint.insertionIndex === index && ( + { shouldRenderInsertionPoint && ( <div style={ { borderRadius: '0', @@ -87,12 +115,9 @@ function ZoomOutModeInserters() { className="block-editor-block-list__insertion-point-indicator" /> ) } - { insertionPoint.insertionIndex !== index && ( - <Button - variant="primary" - icon={ plus } - size="compact" - className="block-editor-button-pattern-inserter__button" + { shouldRenderInserter && ( + <ZoomOutModeInserterButton + isVisible={ isSelected || isHovered } onClick={ () => { setInserterIsOpened( { rootClientId: sectionRootClientId, @@ -101,10 +126,6 @@ function ZoomOutModeInserters() { category: 'all', } ); } } - label={ _x( - 'Add pattern', - 'Generic label for pattern inserter button' - ) } /> ) } </BlockPopoverInbetween> diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 170c5192f3bee9..f7da8fa14b382a 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -213,6 +213,21 @@ export function selectBlock( clientId, initialPosition = 0 ) { }; } +/** + * Returns an action object used in signalling that the block with the + * specified client ID has been hovered. + * + * @param {string} clientId Block client ID. + * + * @return {Object} Action object. + */ +export function hoverBlock( clientId ) { + return { + type: 'HOVER_BLOCK', + clientId, + }; +} + /** * Yields action objects used in signalling that the block preceding the given * clientId (or optionally, its first parent from bottom to top) diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 7c83887876919f..cd4569c45e5801 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -2068,6 +2068,23 @@ export function lastFocus( state = false, action ) { return state; } +/** + * Reducer setting currently hovered block. + * + * @param {boolean} state Current state. + * @param {Object} action Dispatched action. + * + * @return {boolean} Updated state. + */ +export function hoveredBlockClientId( state = false, action ) { + switch ( action.type ) { + case 'HOVER_BLOCK': + return action.clientId; + } + + return state; +} + const combinedReducers = combineReducers( { blocks, isDragging, @@ -2100,6 +2117,7 @@ const combinedReducers = combineReducers( { blockRemovalRules, openedBlockSettingsMenu, registeredInserterMediaCategories, + hoveredBlockClientId, } ); function withAutomaticChangeReset( reducer ) { diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index d78d75e4210c8e..d6d09b59106110 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2809,6 +2809,16 @@ export function isBlockVisible( state, clientId ) { return state.blockVisibility?.[ clientId ] ?? true; } +/** + * Returns the currently hovered block. + * + * @param {Object} state Global application state. + * @return {Object} Client Id of the hovered block. + */ +export function getHoveredBlockClientId( state ) { + return state.hoveredBlockClientId; +} + /** * Returns the list of all hidden blocks. * From e685f6871a2f2103fd7bdf0b376c7c1557b11cd4 Mon Sep 17 00:00:00 2001 From: Jeremy Herve <jeremy@jeremy.hu> Date: Fri, 19 Jul 2024 11:18:49 +0200 Subject: [PATCH 0010/1908] Social Links: update Facebook's color to match brand guidelines (#60424) See the guidelines defined here: https://about.meta.com/brand/resources/facebook/logo/ ---- Co-authored-by: jeherve <jeherve@git.wordpress.org> Co-authored-by: ankitguptaindia <ankit-k-gupta@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- packages/block-library/src/social-link/socials-with-bg.scss | 2 +- packages/block-library/src/social-link/socials-without-bg.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/social-link/socials-with-bg.scss b/packages/block-library/src/social-link/socials-with-bg.scss index 907e6bb98023d0..35420fc624c0e6 100644 --- a/packages/block-library/src/social-link/socials-with-bg.scss +++ b/packages/block-library/src/social-link/socials-with-bg.scss @@ -49,7 +49,7 @@ } .wp-social-link-facebook { - background-color: #1778f2; + background-color: #0866ff; color: #fff; } diff --git a/packages/block-library/src/social-link/socials-without-bg.scss b/packages/block-library/src/social-link/socials-without-bg.scss index 371310628c9b22..24538b29824b17 100644 --- a/packages/block-library/src/social-link/socials-without-bg.scss +++ b/packages/block-library/src/social-link/socials-without-bg.scss @@ -35,7 +35,7 @@ } .wp-social-link-facebook { - color: #1778f2; + color: #0866ff; } .wp-social-link-fivehundredpx { From d09b7ac428f8c7d2f2293c89e4b56840c3c63092 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Fri, 19 Jul 2024 13:15:45 +0300 Subject: [PATCH 0011/1908] DataViews: Fix uncontrolled selection (#63741) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/dataviews/src/dataviews.tsx | 2 +- packages/edit-site/src/components/page-patterns/index.js | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/dataviews/src/dataviews.tsx b/packages/dataviews/src/dataviews.tsx index 7ac09a990fa24b..ecefb6f0dccdca 100644 --- a/packages/dataviews/src/dataviews.tsx +++ b/packages/dataviews/src/dataviews.tsx @@ -81,7 +81,7 @@ export default function DataViews< Item >( { function setSelectionWithChange( value: SelectionOrUpdater ) { const newValue = typeof value === 'function' ? value( selection ) : value; - if ( ! isUncontrolled ) { + if ( isUncontrolled ) { setSelectionState( newValue ); } if ( onChangeSelection ) { diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index 65e79b406cf559..27b75424e5f3b8 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -252,7 +252,6 @@ export default function DataviewsPatterns() { const { params: { postType, categoryId: categoryIdFromURL }, } = useLocation(); - const [ selection, setSelection ] = useState( [] ); const type = postType || PATTERN_TYPES.user; const categoryId = categoryIdFromURL || PATTERN_DEFAULT_CATEGORY; const [ view, setView ] = useState( DEFAULT_VIEW ); @@ -410,8 +409,6 @@ export default function DataviewsPatterns() { isLoading={ isResolving } view={ view } onChangeView={ setView } - selection={ selection } - onChangeSelection={ setSelection } defaultLayouts={ defaultLayouts } /> </Page> From a0fb3c6d9bed0c1fc560677a0c58c7613bcf0744 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Fri, 19 Jul 2024 12:25:15 +0200 Subject: [PATCH 0012/1908] Block Bindings: Don't provide default `canUserEditValue` in reducer (#63628) * Remove default `canUserEditValue` * Call `canUserEditValue` conditionally Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: ockham <bernhard-reiter@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> --- packages/block-editor/src/components/rich-text/index.js | 2 +- packages/block-library/src/button/edit.js | 2 +- packages/block-library/src/image/edit.js | 2 +- packages/block-library/src/image/image.js | 6 +++--- packages/blocks/src/api/test/registration.js | 2 +- packages/blocks/src/store/reducer.js | 3 +-- 6 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index cc22c9b804130a..68f00ca1b5d149 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -188,7 +188,7 @@ export function RichTextWrapper( binding.source ); if ( - ! blockBindingsSource?.canUserEditValue( { + ! blockBindingsSource?.canUserEditValue?.( { select, context: blockContext, args: binding.args, diff --git a/packages/block-library/src/button/edit.js b/packages/block-library/src/button/edit.js index e5bd5e6b5f0643..3b2bb562e63c06 100644 --- a/packages/block-library/src/button/edit.js +++ b/packages/block-library/src/button/edit.js @@ -247,7 +247,7 @@ function ButtonEdit( props ) { return { lockUrlControls: !! metadata?.bindings?.url && - ! blockBindingsSource?.canUserEditValue( { + ! blockBindingsSource?.canUserEditValue?.( { select, context, args: metadata?.bindings?.url?.args, diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index df07fd0474eff1..9eba4dacb57c31 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -308,7 +308,7 @@ export function ImageEdit( { return { lockUrlControls: !! metadata?.bindings?.url && - ! blockBindingsSource?.canUserEditValue( { + ! blockBindingsSource?.canUserEditValue?.( { select, context, args: metadata?.bindings?.url?.args, diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 17a860fa5f47ce..5f376ffdac8629 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -479,7 +479,7 @@ export default function Image( { return { lockUrlControls: !! urlBinding && - ! urlBindingSource?.canUserEditValue( { + ! urlBindingSource?.canUserEditValue?.( { select, context, args: urlBinding?.args, @@ -494,7 +494,7 @@ export default function Image( { hasParentPattern, lockAltControls: !! altBinding && - ! altBindingSource?.canUserEditValue( { + ! altBindingSource?.canUserEditValue?.( { select, context, args: altBinding?.args, @@ -508,7 +508,7 @@ export default function Image( { : __( 'Connected to dynamic data' ), lockTitleControls: !! titleBinding && - ! titleBindingSource?.canUserEditValue( { + ! titleBindingSource?.canUserEditValue?.( { select, context, args: titleBinding?.args, diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index 26319253a13ab4..991b299c08abf6 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -1607,7 +1607,7 @@ describe( 'blocks', () => { expect( source.setValue ).toBeUndefined(); expect( source.setValues ).toBeUndefined(); expect( source.getPlaceholder ).toBeUndefined(); - expect( source.canUserEditValue() ).toBe( false ); + expect( source.canUserEditValue ).toBeUndefined(); unregisterBlockBindingsSource( 'core/valid-source' ); } ); diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 1b6d348fd9dddc..4237590f8887a4 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -382,8 +382,7 @@ export function blockBindingsSources( state = {}, action ) { setValue: action.setValue, setValues: action.setValues, getPlaceholder: action.getPlaceholder, - canUserEditValue: - action.canUserEditValue || ( () => false ), + canUserEditValue: action.canUserEditValue, }, }; case 'REMOVE_BLOCK_BINDINGS_SOURCE': From 43569d22c697bdfca2b48a7655e916c407ec7a96 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Fri, 19 Jul 2024 13:12:56 +0200 Subject: [PATCH 0013/1908] Block Bindings: Unify `getValue`/`getValues` and `setValue`/`setValues` APIs (#63185) * Rename to `setValuesInBatch` * Pass whole binding instead of just the new value * Use `setValuesInBatch` in post meta * Add support for `getValuesInBatch` * Use `getValuesInBatch` in post meta * Use `getValuesInBatch` in pattern overrides * Use only `getValues` and `setValues` * Fix pattern overrides * Check undefined instead of ! * Fix error after rebasing * Change registration checks * Use `bindings` param for the API * Use `blockBindingsBySource` name Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- .../src/hooks/use-bindings-attributes.js | 124 ++++++++++-------- packages/blocks/src/api/registration.js | 21 +-- packages/blocks/src/api/test/registration.js | 27 +--- packages/blocks/src/store/private-actions.js | 3 +- packages/blocks/src/store/reducer.js | 3 +- .../editor/src/bindings/pattern-overrides.js | 43 +++--- packages/editor/src/bindings/post-meta.js | 21 ++- 7 files changed, 123 insertions(+), 119 deletions(-) diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index a63f59b69ca21c..410ad93bd971a7 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -101,7 +101,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( const hasPatternOverridesDefaultBinding = props.attributes.metadata?.bindings?.[ DEFAULT_ATTRIBUTE ] ?.source === 'core/pattern-overrides'; - const bindings = useMemo( + const blockBindings = useMemo( () => replacePatternOverrideDefaultBindings( name, @@ -115,110 +115,120 @@ export const withBlockBindingSupport = createHigherOrderComponent( // there are attribute updates. // `source.getValues` may also call a selector via `registry.select`. const boundAttributes = useSelect( () => { - if ( ! bindings ) { + if ( ! blockBindings ) { return; } const attributes = {}; - for ( const [ attributeName, boundAttribute ] of Object.entries( - bindings + const blockBindingsBySource = new Map(); + + for ( const [ attributeName, binding ] of Object.entries( + blockBindings ) ) { - const source = sources[ boundAttribute.source ]; + const { source: sourceName, args: sourceArgs } = binding; + const source = sources[ sourceName ]; if ( - ! source?.getValue || + ! source?.getValues || ! canBindAttribute( name, attributeName ) ) { continue; } - const args = { - registry, - context, - clientId, - attributeName, - args: boundAttribute.args, - }; - - attributes[ attributeName ] = source.getValue( args ); + blockBindingsBySource.set( source, { + ...blockBindingsBySource.get( source ), + [ attributeName ]: { + args: sourceArgs, + }, + } ); + } - if ( attributes[ attributeName ] === undefined ) { - if ( attributeName === 'url' ) { - attributes[ attributeName ] = null; - } else { - attributes[ attributeName ] = - source.getPlaceholder?.( args ); + if ( blockBindingsBySource.size ) { + for ( const [ source, bindings ] of blockBindingsBySource ) { + // Get values in batch if the source supports it. + const values = source.getValues( { + registry, + context, + clientId, + bindings, + } ); + for ( const [ attributeName, value ] of Object.entries( + values + ) ) { + // Use placeholder when value is undefined. + if ( value === undefined ) { + if ( attributeName === 'url' ) { + attributes[ attributeName ] = null; + } else { + attributes[ attributeName ] = + source.getPlaceholder?.( { + registry, + context, + clientId, + attributeName, + args: bindings[ attributeName ].args, + } ); + } + } else { + attributes[ attributeName ] = value; + } } } } return attributes; - }, [ bindings, name, clientId, context, registry, sources ] ); + }, [ blockBindings, name, clientId, context, registry, sources ] ); const { setAttributes } = props; const _setAttributes = useCallback( ( nextAttributes ) => { registry.batch( () => { - if ( ! bindings ) { + if ( ! blockBindings ) { setAttributes( nextAttributes ); return; } const keptAttributes = { ...nextAttributes }; - const updatesBySource = new Map(); + const blockBindingsBySource = new Map(); // Loop only over the updated attributes to avoid modifying the bound ones that haven't changed. for ( const [ attributeName, newValue ] of Object.entries( keptAttributes ) ) { if ( - ! bindings[ attributeName ] || + ! blockBindings[ attributeName ] || ! canBindAttribute( name, attributeName ) ) { continue; } - const binding = bindings[ attributeName ]; + const binding = blockBindings[ attributeName ]; const source = sources[ binding?.source ]; - if ( ! source?.setValue && ! source?.setValues ) { + if ( ! source?.setValues ) { continue; } - updatesBySource.set( source, { - ...updatesBySource.get( source ), - [ attributeName ]: newValue, + blockBindingsBySource.set( source, { + ...blockBindingsBySource.get( source ), + [ attributeName ]: { + args: binding.args, + newValue, + }, } ); delete keptAttributes[ attributeName ]; } - if ( updatesBySource.size ) { + if ( blockBindingsBySource.size ) { for ( const [ source, - attributes, - ] of updatesBySource ) { - if ( source.setValues ) { - source.setValues( { - registry, - context, - clientId, - attributes, - } ); - } else { - for ( const [ - attributeName, - value, - ] of Object.entries( attributes ) ) { - const binding = bindings[ attributeName ]; - source.setValue( { - registry, - context, - clientId, - attributeName, - args: binding.args, - value, - } ); - } - } + bindings, + ] of blockBindingsBySource ) { + source.setValues( { + registry, + context, + clientId, + bindings, + } ); } } @@ -242,7 +252,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( }, [ registry, - bindings, + blockBindings, name, clientId, context, diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 2dd433bca383e9..78aab99b11b617 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -770,8 +770,7 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { * @param {Object} source Properties of the source to be registered. * @param {string} source.name The unique and machine-readable name. * @param {string} source.label Human-readable label. - * @param {Function} [source.getValue] Function to get the value of the source. - * @param {Function} [source.setValue] Function to update the value of the source. + * @param {Function} [source.getValues] Function to get the values from the source. * @param {Function} [source.setValues] Function to update multiple values connected to the source. * @param {Function} [source.getPlaceholder] Function to get the placeholder when the value is undefined. * @param {Function} [source.canUserEditValue] Function to determine if the user can edit the value. @@ -784,8 +783,7 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { * registerBlockBindingsSource( { * name: 'plugin/my-custom-source', * label: _x( 'My Custom Source', 'block bindings source' ), - * getValue: () => 'Value to place in the block attribute', - * setValue: () => updateMyCustomValue(), + * getValues: () => getSourceValues(), * setValues: () => updateMyCustomValuesInBatch(), * getPlaceholder: () => 'Placeholder text when the value is undefined', * canUserEditValue: () => true, @@ -796,8 +794,7 @@ export const registerBlockBindingsSource = ( source ) => { const { name, label, - getValue, - setValue, + getValues, setValues, getPlaceholder, canUserEditValue, @@ -857,15 +854,9 @@ export const registerBlockBindingsSource = ( source ) => { return; } - // Check the `getValue` property is correct. - if ( getValue && typeof getValue !== 'function' ) { - warning( 'Block bindings source getValue must be a function.' ); - return; - } - - // Check the `setValue` property is correct. - if ( setValue && typeof setValue !== 'function' ) { - warning( 'Block bindings source setValue must be a function.' ); + // Check the `getValues` property is correct. + if ( getValues && typeof getValues !== 'function' ) { + warning( 'Block bindings source getValues must be a function.' ); return; } diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index 991b299c08abf6..bc1057597bcd7a 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -1512,28 +1512,15 @@ describe( 'blocks', () => { expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); } ); - // Check the `getValue` callback is correct. - it( 'should reject invalid getValue callback', () => { + // Check the `getValues` callback is correct. + it( 'should reject invalid getValues callback', () => { registerBlockBindingsSource( { name: 'core/testing', label: 'testing', - getValue: 'should be a function', + getValues: 'should be a function', } ); expect( console ).toHaveWarnedWith( - 'Block bindings source getValue must be a function.' - ); - expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); - } ); - - // Check the `setValue` callback is correct. - it( 'should reject invalid setValue callback', () => { - registerBlockBindingsSource( { - name: 'core/testing', - label: 'testing', - setValue: 'should be a function', - } ); - expect( console ).toHaveWarnedWith( - 'Block bindings source setValue must be a function.' + 'Block bindings source getValues must be a function.' ); expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); } ); @@ -1581,8 +1568,7 @@ describe( 'blocks', () => { it( 'should register a valid source', () => { const sourceProperties = { label: 'Valid Source', - getValue: () => 'value', - setValue: () => 'new value', + getValues: () => 'value', setValues: () => 'new values', getPlaceholder: () => 'placeholder', canUserEditValue: () => true, @@ -1603,8 +1589,7 @@ describe( 'blocks', () => { label: 'Valid Source', } ); const source = getBlockBindingsSource( 'core/valid-source' ); - expect( source.getValue ).toBeUndefined(); - expect( source.setValue ).toBeUndefined(); + expect( source.getValues ).toBeUndefined(); expect( source.setValues ).toBeUndefined(); expect( source.getPlaceholder ).toBeUndefined(); expect( source.canUserEditValue ).toBeUndefined(); diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index a59ed157e98693..55cdb2128895f5 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -51,8 +51,7 @@ export function addBlockBindingsSource( source ) { type: 'ADD_BLOCK_BINDINGS_SOURCE', name: source.name, label: source.label, - getValue: source.getValue, - setValue: source.setValue, + getValues: source.getValues, setValues: source.setValues, getPlaceholder: source.getPlaceholder, canUserEditValue: source.canUserEditValue, diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 4237590f8887a4..fc386e7ea9f557 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -378,8 +378,7 @@ export function blockBindingsSources( state = {}, action ) { ...state, [ action.name ]: { label: action.label, - getValue: action.getValue, - setValue: action.setValue, + getValues: action.getValues, setValues: action.setValues, getPlaceholder: action.getPlaceholder, canUserEditValue: action.canUserEditValue, diff --git a/packages/editor/src/bindings/pattern-overrides.js b/packages/editor/src/bindings/pattern-overrides.js index 54ca77650a5fe9..b299211900095d 100644 --- a/packages/editor/src/bindings/pattern-overrides.js +++ b/packages/editor/src/bindings/pattern-overrides.js @@ -9,28 +9,32 @@ const CONTENT = 'content'; export default { name: 'core/pattern-overrides', label: _x( 'Pattern Overrides', 'block bindings source' ), - getValue( { registry, clientId, context, attributeName } ) { + getValues( { registry, clientId, context, bindings } ) { const patternOverridesContent = context[ 'pattern/overrides' ]; const { getBlockAttributes } = registry.select( blockEditorStore ); const currentBlockAttributes = getBlockAttributes( clientId ); - if ( ! patternOverridesContent ) { - return currentBlockAttributes[ attributeName ]; - } - - const overridableValue = - patternOverridesContent?.[ - currentBlockAttributes?.metadata?.name - ]?.[ attributeName ]; + const overridesValues = {}; + for ( const attributeName of Object.keys( bindings ) ) { + const overridableValue = + patternOverridesContent?.[ + currentBlockAttributes?.metadata?.name + ]?.[ attributeName ]; - // If there is no pattern client ID, or it is not overwritten, return the default value. - if ( overridableValue === undefined ) { - return currentBlockAttributes[ attributeName ]; + // If it has not been overriden, return the original value. + // Check undefined because empty string is a valid value. + if ( overridableValue === undefined ) { + overridesValues[ attributeName ] = + currentBlockAttributes[ attributeName ]; + continue; + } else { + overridesValues[ attributeName ] = + overridableValue === '' ? undefined : overridableValue; + } } - - return overridableValue === '' ? undefined : overridableValue; + return overridesValues; }, - setValues( { registry, clientId, attributes } ) { + setValues( { registry, clientId, bindings } ) { const { getBlockAttributes, getBlockParentsByBlockName, getBlocks } = registry.select( blockEditorStore ); const currentBlockAttributes = getBlockAttributes( clientId ); @@ -45,6 +49,15 @@ export default { true ); + // Extract the updated attributes from the source bindings. + const attributes = Object.entries( bindings ).reduce( + ( attrs, [ key, { newValue } ] ) => { + attrs[ key ] = newValue; + return attrs; + }, + {} + ); + // If there is no pattern client ID, sync blocks with the same name and same attributes. if ( ! patternClientId ) { const syncBlocksWithSameName = ( blocks ) => { diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index a2fb5964663978..f8161dd47b5c41 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -15,22 +15,29 @@ export default { getPlaceholder( { args } ) { return args.key; }, - getValue( { registry, context, args } ) { - return registry + getValues( { registry, context, bindings } ) { + const meta = registry .select( coreDataStore ) .getEditedEntityRecord( 'postType', context?.postType, context?.postId - ).meta?.[ args.key ]; + )?.meta; + const newValues = {}; + for ( const [ attributeName, source ] of Object.entries( bindings ) ) { + newValues[ attributeName ] = meta?.[ source.args.key ]; + } + return newValues; }, - setValue( { registry, context, args, value } ) { + setValues( { registry, context, bindings } ) { + const newMeta = {}; + Object.values( bindings ).forEach( ( { args, newValue } ) => { + newMeta[ args.key ] = newValue; + } ); registry .dispatch( coreDataStore ) .editEntityRecord( 'postType', context?.postType, context?.postId, { - meta: { - [ args.key ]: value, - }, + meta: newMeta, } ); }, canUserEditValue( { select, context, args } ) { From 6a2a1dbf2290f1a9c29cff11472106e974db5cc7 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Fri, 19 Jul 2024 13:35:16 +0200 Subject: [PATCH 0014/1908] DataViews: Refactor to prepare exposing the underlying UI pieces (#63694) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/base-styles/_z-index.scss | 3 +- .../dataform/index.tsx} | 4 +- .../dataviews-bulk-actions-toolbar/index.tsx} | 58 +- .../dataviews-bulk-actions-toolbar/style.scss | 45 + .../dataviews-bulk-actions/index.tsx} | 54 +- .../dataviews-bulk-actions/style.scss | 7 + .../src/components/dataviews-context/index.ts | 47 + .../dataviews-filters}/add-filter.tsx | 6 +- .../dataviews-filters}/filter-summary.tsx | 28 +- .../dataviews-filters/index.tsx} | 32 +- .../dataviews-filters}/reset-filters.tsx | 2 +- .../dataviews-filters}/search-widget.tsx | 28 +- .../components/dataviews-filters/style.scss | 252 +++++ .../dataviews-item-actions/index.tsx} | 4 +- .../dataviews-item-actions/style.scss | 3 + .../src/components/dataviews-layout/index.tsx | 49 + .../dataviews-pagination/index.tsx} | 28 +- .../dataviews-pagination/style.scss | 26 + .../dataviews-search/index.tsx} | 15 +- .../dataviews-selection-checkbox/index.tsx} | 12 +- .../dataviews-selection-checkbox/style.scss | 14 + .../dataviews-view-config/index.tsx} | 29 +- .../src/components/dataviews/index.tsx | 123 +++ .../src/components/dataviews/style.scss | 97 ++ packages/dataviews/src/dataviews.tsx | 178 ---- packages/dataviews/src/index.ts | 4 +- packages/dataviews/src/layouts/grid/index.tsx | 6 +- .../dataviews/src/layouts/grid/style.scss | 128 +++ packages/dataviews/src/layouts/list/index.tsx | 5 +- .../dataviews/src/layouts/list/style.scss | 189 ++++ .../dataviews/src/layouts/table/index.tsx | 6 +- .../dataviews/src/layouts/table/style.scss | 201 ++++ packages/dataviews/src/style.scss | 962 +----------------- 33 files changed, 1354 insertions(+), 1291 deletions(-) rename packages/dataviews/src/{dataform.tsx => components/dataform/index.tsx} (94%) rename packages/dataviews/src/{bulk-actions-toolbar.tsx => components/dataviews-bulk-actions-toolbar/index.tsx} (82%) create mode 100644 packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss rename packages/dataviews/src/{bulk-actions.tsx => components/dataviews-bulk-actions/index.tsx} (87%) create mode 100644 packages/dataviews/src/components/dataviews-bulk-actions/style.scss create mode 100644 packages/dataviews/src/components/dataviews-context/index.ts rename packages/dataviews/src/{ => components/dataviews-filters}/add-filter.tsx (92%) rename packages/dataviews/src/{ => components/dataviews-filters}/filter-summary.tsx (92%) rename packages/dataviews/src/{filters.tsx => components/dataviews-filters/index.tsx} (75%) rename packages/dataviews/src/{ => components/dataviews-filters}/reset-filters.tsx (94%) rename packages/dataviews/src/{ => components/dataviews-filters}/search-widget.tsx (88%) create mode 100644 packages/dataviews/src/components/dataviews-filters/style.scss rename packages/dataviews/src/{item-actions.tsx => components/dataviews-item-actions/index.tsx} (98%) create mode 100644 packages/dataviews/src/components/dataviews-item-actions/style.scss create mode 100644 packages/dataviews/src/components/dataviews-layout/index.tsx rename packages/dataviews/src/{pagination.tsx => components/dataviews-pagination/index.tsx} (83%) create mode 100644 packages/dataviews/src/components/dataviews-pagination/style.scss rename packages/dataviews/src/{search.tsx => components/dataviews-search/index.tsx} (77%) rename packages/dataviews/src/{single-selection-checkbox.tsx => components/dataviews-selection-checkbox/index.tsx} (80%) create mode 100644 packages/dataviews/src/components/dataviews-selection-checkbox/style.scss rename packages/dataviews/src/{view-actions.tsx => components/dataviews-view-config/index.tsx} (91%) create mode 100644 packages/dataviews/src/components/dataviews/index.tsx create mode 100644 packages/dataviews/src/components/dataviews/style.scss delete mode 100644 packages/dataviews/src/dataviews.tsx create mode 100644 packages/dataviews/src/layouts/grid/style.scss create mode 100644 packages/dataviews/src/layouts/list/style.scss create mode 100644 packages/dataviews/src/layouts/table/style.scss diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index a110c0052b56eb..b8a9088cfd72cc 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -131,6 +131,7 @@ $z-layers: ( ".block-editor-template-part__selection-modal": 1000001, ".block-editor-block-rename-modal": 1000001, ".edit-site-list__rename-modal": 1000001, + ".dataviews-bulk-actions__modal": 1000001, ".dataviews-action-modal": 1000001, ".editor-action-modal": 1000001, ".editor-post-template__swap-template-modal": 1000001, @@ -208,7 +209,7 @@ $z-layers: ( ".dataviews-view-table thead": 1, // Ensure quick actions toolbar appear above pagination - ".dataviews-bulk-actions": 2, + ".dataviews-bulk-actions-toolbar": 2, ); @function z-index( $key ) { diff --git a/packages/dataviews/src/dataform.tsx b/packages/dataviews/src/components/dataform/index.tsx similarity index 94% rename from packages/dataviews/src/dataform.tsx rename to packages/dataviews/src/components/dataform/index.tsx index b81e1c4ae83d37..e61fea075c9b5a 100644 --- a/packages/dataviews/src/dataform.tsx +++ b/packages/dataviews/src/components/dataform/index.tsx @@ -12,8 +12,8 @@ import { useCallback, useMemo } from '@wordpress/element'; /** * Internal dependencies */ -import type { Form, Field, NormalizedField } from './types'; -import { normalizeFields } from './normalize-fields'; +import type { Form, Field, NormalizedField } from '../../types'; +import { normalizeFields } from '../../normalize-fields'; type DataFormProps< Item > = { data: Item; diff --git a/packages/dataviews/src/bulk-actions-toolbar.tsx b/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/index.tsx similarity index 82% rename from packages/dataviews/src/bulk-actions-toolbar.tsx rename to packages/dataviews/src/components/dataviews-bulk-actions-toolbar/index.tsx index c62cd6a5ee9d44..c25328db6a108a 100644 --- a/packages/dataviews/src/bulk-actions-toolbar.tsx +++ b/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/index.tsx @@ -8,7 +8,7 @@ import { __unstableMotion as motion, __unstableAnimatePresence as AnimatePresence, } from '@wordpress/components'; -import { useMemo, useState, useRef } from '@wordpress/element'; +import { useMemo, useState, useRef, useContext } from '@wordpress/element'; import { _n, sprintf, __ } from '@wordpress/i18n'; import { closeSmall } from '@wordpress/icons'; import { useReducedMotion } from '@wordpress/compose'; @@ -17,10 +17,13 @@ import { useRegistry } from '@wordpress/data'; /** * Internal dependencies */ -import { ActionWithModal } from './item-actions'; -import type { Action } from './types'; -import type { ActionTriggerProps } from './item-actions'; -import type { SetSelection } from './private-types'; +import { useSomeItemHasAPossibleBulkAction } from '../dataviews-bulk-actions'; +import DataViewsContext from '../dataviews-context'; +import { ActionWithModal } from '../dataviews-item-actions'; +import { LAYOUT_GRID, LAYOUT_TABLE } from '../../constants'; +import type { Action } from '../../types'; +import type { ActionTriggerProps } from '../dataviews-item-actions'; +import type { SetSelection } from '../../private-types'; interface ActionButtonProps< Item > { action: Action< Item >; @@ -36,14 +39,6 @@ interface ToolbarContentProps< Item > { onChangeSelection: SetSelection; } -interface BulkActionsToolbarProps< Item > { - data: Item[]; - selection: string[]; - actions: Action< Item >[]; - onChangeSelection: SetSelection; - getItemId: ( item: Item ) => string; -} - const SNACKBAR_VARIANTS = { init: { bottom: -48, @@ -136,7 +131,7 @@ function renderToolbarContent< Item >( return ( <> <ToolbarGroup> - <div className="dataviews-bulk-actions__selection-count"> + <div className="dataviews-bulk-actions-toolbar__selection-count"> { selection.length === 1 ? __( '1 item selected' ) : sprintf( @@ -214,13 +209,14 @@ function ToolbarContent< Item >( { return buttons.current; } -export default function BulkActionsToolbar< Item >( { - data, - selection, - actions = EMPTY_ARRAY, - onChangeSelection, - getItemId, -}: BulkActionsToolbarProps< Item > ) { +function _BulkActionsToolbar() { + const { + data, + selection, + actions = EMPTY_ARRAY, + onChangeSelection, + getItemId, + } = useContext( DataViewsContext ); const isReducedMotion = useReducedMotion(); const selectedItems = useMemo( () => { return data.filter( ( item ) => @@ -258,10 +254,10 @@ export default function BulkActionsToolbar< Item >( { animate="open" exit="exit" variants={ isReducedMotion ? undefined : SNACKBAR_VARIANTS } - className="dataviews-bulk-actions" + className="dataviews-bulk-actions-toolbar" > <Toolbar label={ __( 'Bulk actions' ) }> - <div className="dataviews-bulk-actions-toolbar-wrapper"> + <div className="dataviews-bulk-actions-toolbar__wrapper"> <ToolbarContent selection={ selection } actionsToShow={ actionsToShow } @@ -274,3 +270,19 @@ export default function BulkActionsToolbar< Item >( { </AnimatePresence> ); } + +export default function BulkActionsToolbar() { + const { data, actions = [], view } = useContext( DataViewsContext ); + const hasPossibleBulkAction = useSomeItemHasAPossibleBulkAction( + actions, + data + ); + if ( + ! [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) || + ! hasPossibleBulkAction + ) { + return null; + } + + return <_BulkActionsToolbar />; +} diff --git a/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss b/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss new file mode 100644 index 00000000000000..21e6c2ad4d4d64 --- /dev/null +++ b/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss @@ -0,0 +1,45 @@ +.dataviews-bulk-actions-toolbar { + position: sticky; + display: flex; + flex-direction: column; + align-content: center; + flex-wrap: wrap; + width: fit-content; + margin-left: auto; + margin-right: auto; + bottom: $grid-unit-30; + z-index: z-index(".dataviews-bulk-actions-toolbar"); + + .components-accessible-toolbar { + border-color: $gray-300; + box-shadow: $shadow-popover; + + .components-toolbar-group { + border-color: $gray-200; + + &:last-child { + border: 0; + } + } + } + + .dataviews-bulk-actions-toolbar__selection-count { + display: flex; + align-items: center; + margin: 0 $grid-unit-10 0 $grid-unit-10; + } +} + +.dataviews-bulk-actions-toolbar__wrapper { + display: flex; + flex-grow: 1; + width: 100%; + + .components-toolbar-group { + align-items: center; + } + + .components-button.is-busy { + max-height: $button-size; + } +} diff --git a/packages/dataviews/src/bulk-actions.tsx b/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx similarity index 87% rename from packages/dataviews/src/bulk-actions.tsx rename to packages/dataviews/src/components/dataviews-bulk-actions/index.tsx index ff36d7f7bc2098..2047307bd7e90e 100644 --- a/packages/dataviews/src/bulk-actions.tsx +++ b/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx @@ -7,15 +7,16 @@ import { Modal, } from '@wordpress/components'; import { __, sprintf, _n } from '@wordpress/i18n'; -import { useMemo, useState, useCallback } from '@wordpress/element'; +import { useMemo, useState, useCallback, useContext } from '@wordpress/element'; import { useRegistry } from '@wordpress/data'; /** * Internal dependencies */ -import { unlock } from './lock-unlock'; -import type { Action, ActionModal } from './types'; -import type { SetSelection } from './private-types'; +import DataViewsContext from '../dataviews-context'; +import { LAYOUT_TABLE, LAYOUT_GRID } from '../../constants'; +import { unlock } from '../../lock-unlock'; +import type { Action, ActionModal } from '../../types'; const { DropdownMenuV2: DropdownMenu, @@ -43,14 +44,6 @@ interface ActionsMenuGroupProps< Item > { setActionWithModal: ( action?: ActionModal< Item > ) => void; } -interface BulkActionsProps< Item > { - data: Item[]; - actions: Action< Item >[]; - selection: string[]; - onChangeSelection: SetSelection; - getItemId: ( item: Item ) => string; -} - export function useHasAPossibleBulkAction< Item >( actions: Action< Item >[], item: Item @@ -105,7 +98,7 @@ function ActionWithModal< Item >( { title={ ! hideModalHeader ? label : undefined } __experimentalHideHeader={ !! hideModalHeader } onRequestClose={ onCloseModal } - overlayClassName="dataviews-action-modal" + overlayClassName="dataviews-bulk-actions__modal" > <RenderModal items={ eligibleItems } @@ -180,20 +173,21 @@ function ActionsMenuGroup< Item >( { ); } -export default function BulkActions< Item >( { - data, - actions, - selection, - onChangeSelection, - getItemId, -}: BulkActionsProps< Item > ) { +function _BulkActions() { + const { + data, + actions = [], + selection, + onChangeSelection, + getItemId, + } = useContext( DataViewsContext ); const bulkActions = useMemo( () => actions.filter( ( action ) => action.supportsBulk ), [ actions ] ); const [ isMenuOpen, onMenuOpenChange ] = useState( false ); const [ actionWithModal, setActionWithModal ] = useState< - ActionModal< Item > | undefined + ActionModal< any > | undefined >(); const selectableItems = useMemo( () => { return data.filter( ( item ) => { @@ -227,7 +221,7 @@ export default function BulkActions< Item >( { style={ { minWidth: '240px' } } trigger={ <Button - className="dataviews-bulk-edit-button" + className="dataviews-bulk-actions__edit-button" __next40pxDefaultSize variant="tertiary" size="compact" @@ -288,3 +282,19 @@ export default function BulkActions< Item >( { </> ); } + +export default function BulkActions() { + const { data, actions = [], view } = useContext( DataViewsContext ); + const hasPossibleBulkAction = useSomeItemHasAPossibleBulkAction( + actions, + data + ); + if ( + ! [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) || + ! hasPossibleBulkAction + ) { + return null; + } + + return <_BulkActions />; +} diff --git a/packages/dataviews/src/components/dataviews-bulk-actions/style.scss b/packages/dataviews/src/components/dataviews-bulk-actions/style.scss new file mode 100644 index 00000000000000..71f76ce9a6c16f --- /dev/null +++ b/packages/dataviews/src/components/dataviews-bulk-actions/style.scss @@ -0,0 +1,7 @@ +.dataviews-bulk-actions__modal { + z-index: z-index(".dataviews-bulk-actions__modal"); +} + +.dataviews-bulk-actions__edit-button.components-button { + flex-shrink: 0; +} diff --git a/packages/dataviews/src/components/dataviews-context/index.ts b/packages/dataviews/src/components/dataviews-context/index.ts new file mode 100644 index 00000000000000..39e5e09015658e --- /dev/null +++ b/packages/dataviews/src/components/dataviews-context/index.ts @@ -0,0 +1,47 @@ +/** + * WordPress dependencies + */ +import { createContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { View, Action, NormalizedField } from '../../types'; +import type { SetSelection } from '../../private-types'; +import { LAYOUT_TABLE } from '../../constants'; + +type DataViewsContextType< Item > = { + view: View; + onChangeView: ( view: View ) => void; + fields: NormalizedField< Item >[]; + actions?: Action< Item >[]; + data: Item[]; + isLoading?: boolean; + paginationInfo: { + totalItems: number; + totalPages: number; + }; + selection: string[]; + onChangeSelection: SetSelection; + openedFilter: string | null; + setOpenedFilter: ( openedFilter: string | null ) => void; + getItemId: ( item: Item ) => string; +}; + +const DataViewsContext = createContext< DataViewsContextType< any > >( { + view: { type: LAYOUT_TABLE }, + onChangeView: () => {}, + fields: [], + data: [], + paginationInfo: { + totalItems: 0, + totalPages: 0, + }, + selection: [], + onChangeSelection: () => {}, + setOpenedFilter: () => {}, + openedFilter: null, + getItemId: ( item ) => item.id, +} ); + +export default DataViewsContext; diff --git a/packages/dataviews/src/add-filter.tsx b/packages/dataviews/src/components/dataviews-filters/add-filter.tsx similarity index 92% rename from packages/dataviews/src/add-filter.tsx rename to packages/dataviews/src/components/dataviews-filters/add-filter.tsx index 095ca9c3a8425f..38dda38c96e70f 100644 --- a/packages/dataviews/src/add-filter.tsx +++ b/packages/dataviews/src/components/dataviews-filters/add-filter.tsx @@ -16,8 +16,8 @@ import { forwardRef } from '@wordpress/element'; /** * Internal dependencies */ -import { unlock } from './lock-unlock'; -import type { NormalizedFilter, View } from './types'; +import { unlock } from '../../lock-unlock'; +import type { NormalizedFilter, View } from '../../types'; const { DropdownMenuV2: DropdownMenu, @@ -46,7 +46,7 @@ function AddFilter( <Button accessibleWhenDisabled size="compact" - className="dataviews-filters-button" + className="dataviews-filters__button" variant="tertiary" disabled={ ! inactiveFilters.length } ref={ ref } diff --git a/packages/dataviews/src/filter-summary.tsx b/packages/dataviews/src/components/dataviews-filters/filter-summary.tsx similarity index 92% rename from packages/dataviews/src/filter-summary.tsx rename to packages/dataviews/src/components/dataviews-filters/filter-summary.tsx index 95b06324d95dba..7e4c7db9a29aa9 100644 --- a/packages/dataviews/src/filter-summary.tsx +++ b/packages/dataviews/src/components/dataviews-filters/filter-summary.tsx @@ -35,8 +35,14 @@ import { OPERATOR_IS_NONE, OPERATOR_IS_ALL, OPERATOR_IS_NOT_ALL, -} from './constants'; -import type { Filter, NormalizedFilter, Operator, Option, View } from './types'; +} from '../../constants'; +import type { + Filter, + NormalizedFilter, + Operator, + Option, + View, +} from '../../types'; interface FilterTextProps { activeElements: Option[]; @@ -65,8 +71,10 @@ const FilterText = ( { } const filterTextWrappers = { - Name: <span className="dataviews-filter-summary__filter-text-name" />, - Value: <span className="dataviews-filter-summary__filter-text-value" />, + Name: <span className="dataviews-filters__summary-filter-text-name" />, + Value: ( + <span className="dataviews-filters__summary-filter-text-value" /> + ), }; if ( filterInView?.operator === OPERATOR_IS_ANY ) { @@ -166,9 +174,9 @@ function OperatorSelector( { <HStack spacing={ 2 } justify="flex-start" - className="dataviews-filter-summary__operators-container" + className="dataviews-filters__summary-operators-container" > - <FlexItem className="dataviews-filter-summary__operators-filter-name"> + <FlexItem className="dataviews-filters__summary-operators-filter-name"> { filter.name } </FlexItem> @@ -239,13 +247,13 @@ export default function FilterSummary( { return ( <Dropdown defaultOpen={ openedFilter === filter.field } - contentClassName="dataviews-filter-summary__popover" + contentClassName="dataviews-filters__summary-popover" popoverProps={ { placement: 'bottom-start', role: 'dialog' } } onClose={ () => { toggleRef.current?.focus(); } } renderToggle={ ( { isOpen, onToggle } ) => ( - <div className="dataviews-filter-summary__chip-container"> + <div className="dataviews-filters__summary-chip-container"> <Tooltip text={ sprintf( /* translators: 1: Filter name. */ @@ -256,7 +264,7 @@ export default function FilterSummary( { > <div className={ clsx( - 'dataviews-filter-summary__chip', + 'dataviews-filters__summary-chip', { 'has-reset': canResetOrRemove, 'has-values': hasValues, @@ -289,7 +297,7 @@ export default function FilterSummary( { > <button className={ clsx( - 'dataviews-filter-summary__chip-remove', + 'dataviews-filters__summary-chip-remove', { 'has-values': hasValues } ) } onClick={ () => { diff --git a/packages/dataviews/src/filters.tsx b/packages/dataviews/src/components/dataviews-filters/index.tsx similarity index 75% rename from packages/dataviews/src/filters.tsx rename to packages/dataviews/src/components/dataviews-filters/index.tsx index ca3de9626b48e7..c35bb454b329f8 100644 --- a/packages/dataviews/src/filters.tsx +++ b/packages/dataviews/src/components/dataviews-filters/index.tsx @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { memo, useRef } from '@wordpress/element'; +import { memo, useContext, useRef } from '@wordpress/element'; import { __experimentalHStack as HStack } from '@wordpress/components'; /** @@ -10,25 +10,14 @@ import { __experimentalHStack as HStack } from '@wordpress/components'; import FilterSummary from './filter-summary'; import AddFilter from './add-filter'; import ResetFilters from './reset-filters'; -import { sanitizeOperators } from './utils'; -import { ALL_OPERATORS, OPERATOR_IS, OPERATOR_IS_NOT } from './constants'; -import type { NormalizedField, NormalizedFilter, View } from './types'; +import DataViewsContext from '../dataviews-context'; +import { sanitizeOperators } from '../../utils'; +import { ALL_OPERATORS, OPERATOR_IS, OPERATOR_IS_NOT } from '../../constants'; +import type { NormalizedFilter } from '../../types'; -interface FiltersProps< Item > { - fields: NormalizedField< Item >[]; - view: View; - onChangeView: ( view: View ) => void; - openedFilter: string | null; - setOpenedFilter: ( openedFilter: string | null ) => void; -} - -function _Filters< Item >( { - fields, - view, - onChangeView, - openedFilter, - setOpenedFilter, -}: FiltersProps< Item > ) { +function Filters() { + const { fields, view, onChangeView, openedFilter, setOpenedFilter } = + useContext( DataViewsContext ); const addFilterRef = useRef< HTMLButtonElement >( null ); const filters: NormalizedFilter[] = []; fields.forEach( ( field ) => { @@ -119,7 +108,4 @@ function _Filters< Item >( { ); } -// A type assertion is used here to keep the type argument. -const Filters = memo( _Filters ) as typeof _Filters; - -export default Filters; +export default memo( Filters ); diff --git a/packages/dataviews/src/reset-filters.tsx b/packages/dataviews/src/components/dataviews-filters/reset-filters.tsx similarity index 94% rename from packages/dataviews/src/reset-filters.tsx rename to packages/dataviews/src/components/dataviews-filters/reset-filters.tsx index 5c155ac7f05cca..4e4c44d8a1c311 100644 --- a/packages/dataviews/src/reset-filters.tsx +++ b/packages/dataviews/src/components/dataviews-filters/reset-filters.tsx @@ -7,7 +7,7 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import type { NormalizedFilter, View } from './types'; +import type { NormalizedFilter, View } from '../../types'; interface ResetFilterProps { filters: NormalizedFilter[]; diff --git a/packages/dataviews/src/search-widget.tsx b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx similarity index 88% rename from packages/dataviews/src/search-widget.tsx rename to packages/dataviews/src/components/dataviews-filters/search-widget.tsx index d65d58635405a3..3516ff23b28503 100644 --- a/packages/dataviews/src/search-widget.tsx +++ b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx @@ -21,8 +21,8 @@ import { SVG, Circle } from '@wordpress/primitives'; /** * Internal dependencies */ -import { unlock } from './lock-unlock'; -import type { Filter, NormalizedFilter, View } from './types'; +import { unlock } from '../../lock-unlock'; +import type { Filter, NormalizedFilter, View } from '../../types'; const { CompositeV2: Composite, @@ -101,7 +101,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) { <Composite store={ compositeStore } role="listbox" - className="dataviews-search-widget-listbox" + className="dataviews-filters__search-widget-listbox" aria-label={ sprintf( /* translators: List of items for a filter. 1: Filter name. e.g.: "List of: Author". */ __( 'List of: %1$s' ), @@ -124,7 +124,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) { <div aria-label={ element.label } role="option" - className="dataviews-search-widget-listitem" + className="dataviews-filters__search-widget-listitem" /> } onClick={ () => { @@ -174,7 +174,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) { /> } > - <span className="dataviews-search-widget-listitem-check"> + <span className="dataviews-filters__search-widget-listitem-check"> { filter.singleSelection && currentValue === element.value && ( <Icon icon={ radioCheck } /> @@ -187,7 +187,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) { <span> { element.label } { !! element.description && ( - <span className="dataviews-search-widget-listitem-description"> + <span className="dataviews-filters__search-widget-listitem-description"> { element.description } </span> ) } @@ -247,7 +247,7 @@ function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) { } } setValue={ setSearchValue } > - <div className="dataviews-search-widget-filter-combobox__wrapper"> + <div className="dataviews-filters__search-widget-filter-combobox__wrapper"> <Ariakit.ComboboxLabel render={ <VisuallyHidden> @@ -260,14 +260,14 @@ function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) { <Ariakit.Combobox autoSelect="always" placeholder={ __( 'Search' ) } - className="dataviews-search-widget-filter-combobox__input" + className="dataviews-filters__search-widget-filter-combobox__input" /> - <div className="dataviews-search-widget-filter-combobox__icon"> + <div className="dataviews-filters__search-widget-filter-combobox__icon"> <Icon icon={ search } /> </div> </div> <Ariakit.ComboboxList - className="dataviews-search-widget-filter-combobox-list" + className="dataviews-filters__search-widget-filter-combobox-list" alwaysVisible > { matches.map( ( element ) => { @@ -275,12 +275,12 @@ function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) { <Ariakit.ComboboxItem key={ element.value } value={ element.value } - className="dataviews-search-widget-listitem" + className="dataviews-filters__search-widget-listitem" hideOnClick={ false } setValueOnClick={ false } focusOnHover > - <span className="dataviews-search-widget-listitem-check"> + <span className="dataviews-filters__search-widget-listitem-check"> { filter.singleSelection && currentValue === element.value && ( <Icon icon={ radioCheck } /> @@ -292,11 +292,11 @@ function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) { </span> <span> <Ariakit.ComboboxItemValue - className="dataviews-search-widget-filter-combobox-item-value" + className="dataviews-filters__search-widget-filter-combobox-item-value" value={ element.label } /> { !! element.description && ( - <span className="dataviews-search-widget-listitem-description"> + <span className="dataviews-filters__search-widget-listitem-description"> { element.description } </span> ) } diff --git a/packages/dataviews/src/components/dataviews-filters/style.scss b/packages/dataviews/src/components/dataviews-filters/style.scss new file mode 100644 index 00000000000000..26e5e613fcbe44 --- /dev/null +++ b/packages/dataviews/src/components/dataviews-filters/style.scss @@ -0,0 +1,252 @@ +.dataviews-filters__button { + position: relative; +} + +.dataviews-filters__reset-button.dataviews-filters__reset-button[aria-disabled="true"] { + &, + &:hover { + opacity: 0; + } + + &:focus { + opacity: 1; + } +} + +.dataviews-filters__summary-popover { + .components-popover__content { + width: 230px; + padding: 0; + border-radius: $grid-unit-05; + } +} + +.dataviews-filters__summary-operators-container { + padding: $grid-unit-10 $grid-unit-10 0; + + &:has(+ .dataviews-filters__search-widget-listbox) { + border-bottom: 1px solid $gray-200; + padding-bottom: $grid-unit-10; + } + + &:empty { + display: none; + } + + .dataviews-filters__summary-operators-filter-name { + color: $gray-700; + } +} + +.dataviews-filters__summary-chip-container { + position: relative; + white-space: pre-wrap; + + .dataviews-filters__summary-chip { + border-radius: $grid-unit-20; + border: 1px solid transparent; + cursor: pointer; + padding: $grid-unit-05 $grid-unit-15; + min-height: $grid-unit-40; + background: $gray-100; + color: $gray-800; + position: relative; + display: flex; + align-items: center; + + &.has-reset { + padding-inline-end: $button-size-small + $grid-unit-05; + } + + &:hover, + &:focus-visible, + &[aria-expanded="true"] { + background: $gray-200; + color: $gray-900; + } + + &.has-values { + color: var(--wp-admin-theme-color); + background: rgba(var(--wp-admin-theme-color--rgb), 0.04); + + &:hover, + &[aria-expanded="true"] { + background: rgba(var(--wp-admin-theme-color--rgb), 0.12); + } + } + + &:focus-visible { + outline: none; + box-shadow: + 0 0 0 var(--wp-admin-border-width-focus) + var(--wp-admin-theme-color); + } + + .dataviews-filters-__summary-filter-text-name { + font-weight: 500; + } + } + + .dataviews-filters__summary-chip-remove { + width: $icon-size; + height: $icon-size; + border-radius: 50%; + border: 0; + padding: 0; + position: absolute; + right: $grid-unit-05; + top: 50%; + transform: translateY(-50%); + display: flex; + align-items: center; + justify-content: center; + background: transparent; + cursor: pointer; + + svg { + fill: $gray-700; + } + + &:hover, + &:focus { + background: $gray-200; + svg { + fill: $gray-900; + } + } + + &.has-values { + svg { + fill: var(--wp-admin-theme-color); + } + &:hover { + background: rgba(var(--wp-admin-theme-color--rgb), 0.08); + } + } + + &:focus-visible { + outline: none; + box-shadow: + 0 0 0 var(--wp-admin-border-width-focus) + var(--wp-admin-theme-color); + } + } +} + +.dataviews-filters__search-widget-filter-combobox-list { + max-height: $grid-unit * 23; + padding: $grid-unit-05; + overflow: auto; + border-top: 1px solid $gray-200; + + .dataviews-filters__search-widget-filter-combobox-item-value { + [data-user-value] { + font-weight: 600; + } + } +} + +.dataviews-filters__search-widget-listbox { + max-height: $grid-unit * 23; + padding: $grid-unit-05; + overflow: auto; +} + +.dataviews-filters__search-widget-listitem { + display: flex; + align-items: center; + gap: $grid-unit-10; + border-radius: $radius-block-ui; + box-sizing: border-box; + padding: $grid-unit-10 $grid-unit-15; + cursor: default; + margin-block-end: 2px; + + &:last-child { + margin-block-end: 0; + } + + &:hover, + &[data-active-item], + &:focus { + background-color: var(--wp-admin-theme-color); + color: $white; + + .dataviews-filters__search-widget-listitem-check { + fill: $white; + } + + .dataviews-filters__search-widget-listitem-description { + color: $white; + } + } + + .dataviews-filters__search-widget-listitem-check { + width: 24px; + height: 24px; + flex-shrink: 0; + } + + .dataviews-filters__search-widget-listitem-description { + display: block; + overflow: hidden; + text-overflow: ellipsis; + font-size: $helptext-font-size; + line-height: 16px; + color: $gray-700; + } +} + +.dataviews-filters__search-widget-filter-combobox__wrapper { + position: relative; + padding: $grid-unit-10; + + .dataviews-filters__search-widget-filter-combobox__input { + @include input-control; + display: block; + padding: 0 $grid-unit-40 0 $grid-unit-10; + background: $gray-100; + border: none; + width: 100%; + height: $grid-unit-40; + + // Unset inherited values. + margin-left: 0; + margin-right: 0; + + /* Fonts smaller than 16px causes mobile safari to zoom. */ + font-size: $mobile-text-min-font-size; + @include break-small { + font-size: $default-font-size; + } + + &:focus { + background: $white; + box-shadow: + inset 0 0 0 var(--wp-admin-border-width-focus) + var(--wp-admin-theme-color); + } + + &::placeholder { + color: $gray-700; + } + + &::-webkit-search-decoration, + &::-webkit-search-cancel-button, + &::-webkit-search-results-button, + &::-webkit-search-results-decoration { + -webkit-appearance: none; + } + } + + .dataviews-filters__search-widget-filter-combobox__icon { + position: absolute; + right: $grid-unit-15; + top: 50%; + transform: translateY(-50%); + display: flex; + align-items: center; + justify-content: center; + width: $icon-size; + } +} diff --git a/packages/dataviews/src/item-actions.tsx b/packages/dataviews/src/components/dataviews-item-actions/index.tsx similarity index 98% rename from packages/dataviews/src/item-actions.tsx rename to packages/dataviews/src/components/dataviews-item-actions/index.tsx index 08d82d060b74ca..53b468c1ab7d3e 100644 --- a/packages/dataviews/src/item-actions.tsx +++ b/packages/dataviews/src/components/dataviews-item-actions/index.tsx @@ -20,8 +20,8 @@ import { useRegistry } from '@wordpress/data'; /** * Internal dependencies */ -import { unlock } from './lock-unlock'; -import type { Action, ActionModal as ActionModalType } from './types'; +import { unlock } from '../../lock-unlock'; +import type { Action, ActionModal as ActionModalType } from '../../types'; const { DropdownMenuV2: DropdownMenu, diff --git a/packages/dataviews/src/components/dataviews-item-actions/style.scss b/packages/dataviews/src/components/dataviews-item-actions/style.scss new file mode 100644 index 00000000000000..9a0327ccb673ff --- /dev/null +++ b/packages/dataviews/src/components/dataviews-item-actions/style.scss @@ -0,0 +1,3 @@ +.dataviews-action-modal { + z-index: z-index(".dataviews-action-modal"); +} diff --git a/packages/dataviews/src/components/dataviews-layout/index.tsx b/packages/dataviews/src/components/dataviews-layout/index.tsx new file mode 100644 index 00000000000000..960dcf304c0180 --- /dev/null +++ b/packages/dataviews/src/components/dataviews-layout/index.tsx @@ -0,0 +1,49 @@ +/** + * External dependencies + */ +import type { ComponentType } from 'react'; + +/** + * WordPress dependencies + */ +import { useContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import DataViewsContext from '../dataviews-context'; +import { VIEW_LAYOUTS } from '../../layouts'; +import type { ViewBaseProps } from '../../types'; + +export default function DataViewsLayout() { + const { + actions = [], + data, + fields, + getItemId, + isLoading, + view, + onChangeView, + selection, + onChangeSelection, + setOpenedFilter, + } = useContext( DataViewsContext ); + + const ViewComponent = VIEW_LAYOUTS.find( ( v ) => v.type === view.type ) + ?.component as ComponentType< ViewBaseProps< any > >; + + return ( + <ViewComponent + actions={ actions } + data={ data } + fields={ fields } + getItemId={ getItemId } + isLoading={ isLoading } + onChangeView={ onChangeView } + onChangeSelection={ onChangeSelection } + selection={ selection } + setOpenedFilter={ setOpenedFilter } + view={ view } + /> + ); +} diff --git a/packages/dataviews/src/pagination.tsx b/packages/dataviews/src/components/dataviews-pagination/index.tsx similarity index 83% rename from packages/dataviews/src/pagination.tsx rename to packages/dataviews/src/components/dataviews-pagination/index.tsx index 99688e076e53be..f8ebf41469d949 100644 --- a/packages/dataviews/src/pagination.tsx +++ b/packages/dataviews/src/components/dataviews-pagination/index.tsx @@ -6,29 +6,21 @@ import { __experimentalHStack as HStack, SelectControl, } from '@wordpress/components'; -import { createInterpolateElement, memo } from '@wordpress/element'; +import { createInterpolateElement, memo, useContext } from '@wordpress/element'; import { sprintf, __, _x } from '@wordpress/i18n'; import { next, previous } from '@wordpress/icons'; /** * Internal dependencies */ -import type { View } from './types'; +import DataViewsContext from '../dataviews-context'; -interface PaginationProps { - view: View; - onChangeView: ( view: View ) => void; - paginationInfo: { - totalItems: number; - totalPages: number; - }; -} - -const Pagination = memo( function Pagination( { - view, - onChangeView, - paginationInfo: { totalItems = 0, totalPages }, -}: PaginationProps ) { +function DataViewsPagination() { + const { + view, + onChangeView, + paginationInfo: { totalItems = 0, totalPages }, + } = useContext( DataViewsContext ); if ( ! totalItems || ! totalPages ) { return null; } @@ -113,6 +105,6 @@ const Pagination = memo( function Pagination( { </HStack> ) ); -} ); +} -export default Pagination; +export default memo( DataViewsPagination ); diff --git a/packages/dataviews/src/components/dataviews-pagination/style.scss b/packages/dataviews/src/components/dataviews-pagination/style.scss new file mode 100644 index 00000000000000..4e754ab90fa54a --- /dev/null +++ b/packages/dataviews/src/components/dataviews-pagination/style.scss @@ -0,0 +1,26 @@ +.dataviews-pagination { + position: sticky; + bottom: 0; + left: 0; + background-color: $white; + padding: $grid-unit-15 $grid-unit-60; + border-top: $border-width solid $gray-100; + color: $gray-700; + flex-shrink: 0; + transition: padding ease-out 0.1s; + @include reduce-motion("transition"); +} + +.dataviews-pagination__page-selection { + font-size: 11px; + text-transform: uppercase; + font-weight: 500; + color: $gray-900; +} + +/* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ +@container (max-width: 430px) { + .dataviews-pagination { + padding: $grid-unit-15 $grid-unit-30; + } +} diff --git a/packages/dataviews/src/search.tsx b/packages/dataviews/src/components/dataviews-search/index.tsx similarity index 77% rename from packages/dataviews/src/search.tsx rename to packages/dataviews/src/components/dataviews-search/index.tsx index 7929a9bd0eb3cb..5e5ce705e11195 100644 --- a/packages/dataviews/src/search.tsx +++ b/packages/dataviews/src/components/dataviews-search/index.tsx @@ -2,26 +2,21 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { useEffect, useRef, memo } from '@wordpress/element'; +import { useEffect, useRef, memo, useContext } from '@wordpress/element'; import { SearchControl } from '@wordpress/components'; import { useDebouncedInput } from '@wordpress/compose'; /** * Internal dependencies */ -import type { View } from './types'; +import DataViewsContext from '../dataviews-context'; interface SearchProps { label?: string; - view: View; - onChangeView: ( view: View ) => void; } -const Search = memo( function Search( { - label, - view, - onChangeView, -}: SearchProps ) { +const DataViewsSearch = memo( function Search( { label }: SearchProps ) { + const { view, onChangeView } = useContext( DataViewsContext ); const [ search, setSearch, debouncedSearch ] = useDebouncedInput( view.search ); @@ -54,4 +49,4 @@ const Search = memo( function Search( { ); } ); -export default Search; +export default DataViewsSearch; diff --git a/packages/dataviews/src/single-selection-checkbox.tsx b/packages/dataviews/src/components/dataviews-selection-checkbox/index.tsx similarity index 80% rename from packages/dataviews/src/single-selection-checkbox.tsx rename to packages/dataviews/src/components/dataviews-selection-checkbox/index.tsx index 52f20d7a35f629..b81bdad9a54614 100644 --- a/packages/dataviews/src/single-selection-checkbox.tsx +++ b/packages/dataviews/src/components/dataviews-selection-checkbox/index.tsx @@ -7,10 +7,10 @@ import { CheckboxControl } from '@wordpress/components'; /** * Internal dependencies */ -import type { Field } from './types'; -import type { SetSelection } from './private-types'; +import type { Field } from '../../types'; +import type { SetSelection } from '../../private-types'; -interface SingleSelectionCheckboxProps< Item > { +interface DataViewsSelectionCheckboxProps< Item > { selection: string[]; onChangeSelection: SetSelection; item: Item; @@ -19,14 +19,14 @@ interface SingleSelectionCheckboxProps< Item > { disabled: boolean; } -export default function SingleSelectionCheckbox< Item >( { +export default function DataViewsSelectionCheckbox< Item >( { selection, onChangeSelection, item, getItemId, primaryField, disabled, -}: SingleSelectionCheckboxProps< Item > ) { +}: DataViewsSelectionCheckboxProps< Item > ) { const id = getItemId( item ); const checked = ! disabled && selection.includes( id ); let selectionLabel; @@ -44,7 +44,7 @@ export default function SingleSelectionCheckbox< Item >( { } return ( <CheckboxControl - className="dataviews-view-table-selection-checkbox" + className="dataviews-selection-checkbox" __nextHasNoMarginBottom aria-label={ selectionLabel } aria-disabled={ disabled } diff --git a/packages/dataviews/src/components/dataviews-selection-checkbox/style.scss b/packages/dataviews/src/components/dataviews-selection-checkbox/style.scss new file mode 100644 index 00000000000000..d2724cae3feb9b --- /dev/null +++ b/packages/dataviews/src/components/dataviews-selection-checkbox/style.scss @@ -0,0 +1,14 @@ +.dataviews-selection-checkbox { + // Experimental override for CheckboxControl size (fragile) + --checkbox-input-size: 24px; + @include break-small() { + --checkbox-input-size: 16px; + } + + line-height: 0; + flex-shrink: 0; + + .components-checkbox-control__input-container { + margin: 0; + } +} diff --git a/packages/dataviews/src/view-actions.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx similarity index 91% rename from packages/dataviews/src/view-actions.tsx rename to packages/dataviews/src/components/dataviews-view-config/index.tsx index 0493cfb5efea1f..6dca75fbe057a4 100644 --- a/packages/dataviews/src/view-actions.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -12,16 +12,17 @@ import { __experimentalHStack as HStack, } from '@wordpress/components'; import { __, _x } from '@wordpress/i18n'; -import { memo } from '@wordpress/element'; +import { memo, useContext } from '@wordpress/element'; import { cog } from '@wordpress/icons'; /** * Internal dependencies */ -import { unlock } from './lock-unlock'; -import { SORTING_DIRECTIONS, sortLabels } from './constants'; -import { VIEW_LAYOUTS, getMandatoryFields } from './layouts'; -import type { NormalizedField, View, SupportedLayouts } from './types'; +import { unlock } from '../../lock-unlock'; +import { SORTING_DIRECTIONS, sortLabels } from '../../constants'; +import { VIEW_LAYOUTS, getMandatoryFields } from '../../layouts'; +import type { NormalizedField, View, SupportedLayouts } from '../../types'; +import DataViewsContext from '../dataviews-context'; const { DropdownMenuV2: DropdownMenu, @@ -55,10 +56,7 @@ interface SortMenuProps< Item > { onChangeView: ( view: View ) => void; } -interface ViewActionsProps< Item > { - fields: NormalizedField< Item >[]; - view: View; - onChangeView: ( view: View ) => void; +interface ViewActionsProps { defaultLayouts?: SupportedLayouts; } @@ -282,12 +280,8 @@ function SortMenu< Item >( { ); } -function _ViewActions< Item >( { - fields, - view, - onChangeView, - defaultLayouts, -}: ViewActionsProps< Item > ) { +function _DataViewsViewConfig( { defaultLayouts }: ViewActionsProps ) { + const { view, fields, onChangeView } = useContext( DataViewsContext ); const activeView = VIEW_LAYOUTS.find( ( v ) => view.type === v.type ); return ( <> @@ -345,7 +339,6 @@ function _ViewActions< Item >( { ); } -// A type assertion is used here to keep the type argument. -const ViewActions = memo( _ViewActions ) as typeof _ViewActions; +const DataViewsViewConfig = memo( _DataViewsViewConfig ); -export default ViewActions; +export default DataViewsViewConfig; diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx new file mode 100644 index 00000000000000..618e04773c084e --- /dev/null +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -0,0 +1,123 @@ +/** + * WordPress dependencies + */ +import { __experimentalHStack as HStack } from '@wordpress/components'; +import { useMemo, useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { default as DataViewsBulkActions } from '../dataviews-bulk-actions'; +import DataViewsBulkActionsToolbar from '../dataviews-bulk-actions-toolbar'; +import DataViewsContext from '../dataviews-context'; +import DataViewsFilters from '../dataviews-filters'; +import DataViewsLayout from '../dataviews-layout'; +import DataviewsPagination from '../dataviews-pagination'; +import DataViewsSearch from '../dataviews-search'; +import DataViewsViewConfig from '../dataviews-view-config'; +import { normalizeFields } from '../../normalize-fields'; +import type { Action, Field, View, SupportedLayouts } from '../../types'; +import type { SelectionOrUpdater } from '../../private-types'; + +type ItemWithId = { id: string }; + +type DataViewsProps< Item > = { + view: View; + onChangeView: ( view: View ) => void; + fields: Field< Item >[]; + search?: boolean; + searchLabel?: string; + actions?: Action< Item >[]; + data: Item[]; + isLoading?: boolean; + paginationInfo: { + totalItems: number; + totalPages: number; + }; + defaultLayouts: SupportedLayouts; + selection?: string[]; + onChangeSelection?: ( items: string[] ) => void; +} & ( Item extends ItemWithId + ? { getItemId?: ( item: Item ) => string } + : { getItemId: ( item: Item ) => string } ); + +const defaultGetItemId = ( item: ItemWithId ) => item.id; + +export default function DataViews< Item >( { + view, + onChangeView, + fields, + search = true, + searchLabel = undefined, + actions = [], + data, + getItemId = defaultGetItemId, + isLoading = false, + paginationInfo, + defaultLayouts, + selection: selectionProperty, + onChangeSelection, +}: DataViewsProps< Item > ) { + const [ selectionState, setSelectionState ] = useState< string[] >( [] ); + const isUncontrolled = + selectionProperty === undefined || onChangeSelection === undefined; + const selection = isUncontrolled ? selectionState : selectionProperty; + const [ openedFilter, setOpenedFilter ] = useState< string | null >( null ); + function setSelectionWithChange( value: SelectionOrUpdater ) { + const newValue = + typeof value === 'function' ? value( selection ) : value; + if ( isUncontrolled ) { + setSelectionState( newValue ); + } + if ( onChangeSelection ) { + onChangeSelection( newValue ); + } + } + const _fields = useMemo( () => normalizeFields( fields ), [ fields ] ); + const _selection = useMemo( () => { + return selection.filter( ( id ) => + data.some( ( item ) => getItemId( item ) === id ) + ); + }, [ selection, data, getItemId ] ); + + return ( + <DataViewsContext.Provider + value={ { + view, + onChangeView, + fields: _fields, + actions, + data, + isLoading, + paginationInfo, + selection: _selection, + onChangeSelection: setSelectionWithChange, + openedFilter, + setOpenedFilter, + getItemId, + } } + > + <div className="dataviews-wrapper"> + <HStack + alignment="top" + justify="start" + className="dataviews__view-actions" + > + <HStack + justify="start" + className="dataviews-filters__container" + wrap + > + { search && <DataViewsSearch label={ searchLabel } /> } + <DataViewsFilters /> + </HStack> + <DataViewsBulkActions /> + <DataViewsViewConfig defaultLayouts={ defaultLayouts } /> + </HStack> + <DataViewsLayout /> + <DataviewsPagination /> + <DataViewsBulkActionsToolbar /> + </div> + </DataViewsContext.Provider> + ); +} diff --git a/packages/dataviews/src/components/dataviews/style.scss b/packages/dataviews/src/components/dataviews/style.scss new file mode 100644 index 00000000000000..6b8af6a90007dd --- /dev/null +++ b/packages/dataviews/src/components/dataviews/style.scss @@ -0,0 +1,97 @@ +.dataviews-wrapper { + height: 100%; + overflow: auto; + box-sizing: border-box; + scroll-padding-bottom: $grid-unit-80; + /* stylelint-disable-next-line property-no-unknown -- '@container' not globally permitted */ + container: dataviews-wrapper / inline-size; + display: flex; + flex-direction: column; +} + +.dataviews__view-actions { + box-sizing: border-box; + padding: $grid-unit-20 $grid-unit-60; + flex-shrink: 0; + position: sticky; + left: 0; + transition: padding ease-out 0.1s; + @include reduce-motion("transition"); + + .components-search-control { + .components-base-control__field { + max-width: 240px; + } + } +} + +.dataviews-view-list__primary-field, +.dataviews-view-grid__primary-field, +.dataviews-view-table__primary-field { + font-size: $default-font-size; + font-weight: 500; + color: $gray-700; + text-overflow: ellipsis; + white-space: nowrap; + width: 100%; + + a { + text-decoration: none; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + display: block; + flex-grow: 0; + color: $gray-900; + + &:hover { + color: var(--wp-admin-theme-color); + } + @include link-reset(); + } + + button.components-button.is-link { + text-decoration: none; + font-weight: inherit; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + display: block; + width: 100%; + color: $gray-900; + &:hover { + color: var(--wp-admin-theme-color); + } + } +} + +.dataviews-no-results, +.dataviews-loading { + padding: 0 $grid-unit-60; + flex-grow: 1; + display: flex; + align-items: center; + justify-content: center; + transition: padding ease-out 0.1s; + @include reduce-motion("transition"); +} + +/* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ +@container (max-width: 430px) { + .dataviews__view-actions { + padding: $grid-unit-15 $grid-unit-30; + + .components-search-control { + .components-base-control__field { + max-width: 112px; + } + } + } + + .dataviews-view-grid, + .dataviews-no-results, + .dataviews-loading { + padding-left: $grid-unit-30; + padding-right: $grid-unit-30; + } +} diff --git a/packages/dataviews/src/dataviews.tsx b/packages/dataviews/src/dataviews.tsx deleted file mode 100644 index ecefb6f0dccdca..00000000000000 --- a/packages/dataviews/src/dataviews.tsx +++ /dev/null @@ -1,178 +0,0 @@ -/** - * External dependencies - */ -import type { ComponentType } from 'react'; - -/** - * WordPress dependencies - */ -import { __experimentalHStack as HStack } from '@wordpress/components'; -import { useMemo, useState } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import Pagination from './pagination'; -import ViewActions from './view-actions'; -import Filters from './filters'; -import Search from './search'; -import { LAYOUT_TABLE, LAYOUT_GRID } from './constants'; -import { VIEW_LAYOUTS } from './layouts'; -import { - default as BulkActions, - useSomeItemHasAPossibleBulkAction, -} from './bulk-actions'; -import { normalizeFields } from './normalize-fields'; -import BulkActionsToolbar from './bulk-actions-toolbar'; -import type { - Action, - Field, - View, - ViewBaseProps, - SupportedLayouts, -} from './types'; -import type { SelectionOrUpdater } from './private-types'; - -type ItemWithId = { id: string }; - -type DataViewsProps< Item > = { - view: View; - onChangeView: ( view: View ) => void; - fields: Field< Item >[]; - search?: boolean; - searchLabel?: string; - actions?: Action< Item >[]; - data: Item[]; - isLoading?: boolean; - paginationInfo: { - totalItems: number; - totalPages: number; - }; - defaultLayouts: SupportedLayouts; - selection?: string[]; - onChangeSelection?: ( items: string[] ) => void; -} & ( Item extends ItemWithId - ? { getItemId?: ( item: Item ) => string } - : { getItemId: ( item: Item ) => string } ); - -const defaultGetItemId = ( item: ItemWithId ) => item.id; - -export default function DataViews< Item >( { - view, - onChangeView, - fields, - search = true, - searchLabel = undefined, - actions = [], - data, - getItemId = defaultGetItemId, - isLoading = false, - paginationInfo, - defaultLayouts, - selection: selectionProperty, - onChangeSelection, -}: DataViewsProps< Item > ) { - const [ selectionState, setSelectionState ] = useState< string[] >( [] ); - const isUncontrolled = - selectionProperty === undefined || onChangeSelection === undefined; - const selection = isUncontrolled ? selectionState : selectionProperty; - const [ openedFilter, setOpenedFilter ] = useState< string | null >( null ); - - function setSelectionWithChange( value: SelectionOrUpdater ) { - const newValue = - typeof value === 'function' ? value( selection ) : value; - if ( isUncontrolled ) { - setSelectionState( newValue ); - } - if ( onChangeSelection ) { - onChangeSelection( newValue ); - } - } - - const ViewComponent = VIEW_LAYOUTS.find( ( v ) => v.type === view.type ) - ?.component as ComponentType< ViewBaseProps< Item > >; - const _fields = useMemo( () => normalizeFields( fields ), [ fields ] ); - - const hasPossibleBulkAction = useSomeItemHasAPossibleBulkAction( - actions, - data - ); - const _selection = useMemo( () => { - return selection.filter( ( id ) => - data.some( ( item ) => getItemId( item ) === id ) - ); - }, [ selection, data, getItemId ] ); - return ( - <div className="dataviews-wrapper"> - <HStack - alignment="top" - justify="start" - className="dataviews-filters__view-actions" - > - <HStack - justify="start" - className="dataviews-filters__container" - wrap - > - { search && ( - <Search - label={ searchLabel } - view={ view } - onChangeView={ onChangeView } - /> - ) } - <Filters - fields={ _fields } - view={ view } - onChangeView={ onChangeView } - openedFilter={ openedFilter } - setOpenedFilter={ setOpenedFilter } - /> - </HStack> - { [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) && - hasPossibleBulkAction && ( - <BulkActions - actions={ actions } - data={ data } - onChangeSelection={ setSelectionWithChange } - selection={ _selection } - getItemId={ getItemId } - /> - ) } - <ViewActions - fields={ _fields } - view={ view } - onChangeView={ onChangeView } - defaultLayouts={ defaultLayouts } - /> - </HStack> - <ViewComponent - actions={ actions } - data={ data } - fields={ _fields } - getItemId={ getItemId } - isLoading={ isLoading } - onChangeView={ onChangeView } - onChangeSelection={ setSelectionWithChange } - selection={ _selection } - setOpenedFilter={ setOpenedFilter } - view={ view } - /> - <Pagination - view={ view } - onChangeView={ onChangeView } - paginationInfo={ paginationInfo } - /> - { [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) && - hasPossibleBulkAction && ( - <BulkActionsToolbar - data={ data } - actions={ actions } - selection={ _selection } - onChangeSelection={ setSelectionWithChange } - getItemId={ getItemId } - /> - ) } - </div> - ); -} diff --git a/packages/dataviews/src/index.ts b/packages/dataviews/src/index.ts index f4750bbbd2cd5d..8b6e53e1ff7293 100644 --- a/packages/dataviews/src/index.ts +++ b/packages/dataviews/src/index.ts @@ -1,5 +1,5 @@ -export { default as DataViews } from './dataviews'; +export { default as DataViews } from './components/dataviews'; +export { default as DataForm } from './components/dataform'; export { VIEW_LAYOUTS } from './layouts'; export { filterSortAndPaginate } from './filter-and-sort-data-view'; export type * from './types'; -export { default as DataForm } from './dataform'; diff --git a/packages/dataviews/src/layouts/grid/index.tsx b/packages/dataviews/src/layouts/grid/index.tsx index 7f1eda35e4a7cc..0e94843dd34e53 100644 --- a/packages/dataviews/src/layouts/grid/index.tsx +++ b/packages/dataviews/src/layouts/grid/index.tsx @@ -19,9 +19,9 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import ItemActions from '../../item-actions'; -import SingleSelectionCheckbox from '../../single-selection-checkbox'; -import { useHasAPossibleBulkAction } from '../../bulk-actions'; +import ItemActions from '../../components/dataviews-item-actions'; +import SingleSelectionCheckbox from '../../components/dataviews-selection-checkbox'; +import { useHasAPossibleBulkAction } from '../../components/dataviews-bulk-actions'; import type { Action, NormalizedField, ViewGridProps } from '../../types'; import type { SetSelection } from '../../private-types'; diff --git a/packages/dataviews/src/layouts/grid/style.scss b/packages/dataviews/src/layouts/grid/style.scss new file mode 100644 index 00000000000000..9e18c82a441702 --- /dev/null +++ b/packages/dataviews/src/layouts/grid/style.scss @@ -0,0 +1,128 @@ +.dataviews-view-grid { + margin-bottom: auto; + grid-template-columns: repeat(1, minmax(0, 1fr)) !important; + grid-template-rows: max-content; + padding: 0 $grid-unit-60 $grid-unit-30; + transition: padding ease-out 0.1s; + @include reduce-motion("transition"); + + @include break-mobile() { + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; // Todo: eliminate !important dependency + } + + @include break-xlarge() { + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; // Todo: eliminate !important dependency + } + + @include break-huge() { + grid-template-columns: repeat(4, minmax(0, 1fr)) !important; // Todo: eliminate !important dependency + } + + .dataviews-view-grid__card { + height: 100%; + justify-content: flex-start; + + .dataviews-view-grid__title-actions { + padding: $grid-unit-10 0 $grid-unit-05; + } + + .dataviews-view-grid__primary-field { + min-height: $grid-unit-40; // Preserve layout when there is no ellipsis button + } + + &.is-selected { + .dataviews-view-grid__fields .dataviews-view-grid__field .dataviews-view-grid__field-value { + color: $gray-900; + } + } + } + + .dataviews-view-grid__media { + width: 100%; + min-height: 200px; + aspect-ratio: 1/1; + background-color: $gray-100; + border-radius: $grid-unit-05; + position: relative; + + img { + object-fit: cover; + width: 100%; + height: 100%; + } + + &::after { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + box-shadow: inset 0 0 0 $border-width rgba(0, 0, 0, 0.1); + border-radius: $grid-unit-05; + pointer-events: none; + } + } + + .dataviews-view-grid__fields { + position: relative; + font-size: 12px; + line-height: 16px; + + &:not(:empty) { + padding: 0 0 $grid-unit-15; + } + + .dataviews-view-grid__field { + align-items: flex-start; + min-height: $grid-unit-30; + + &:not(.is-column) { + align-items: center; + + .dataviews-view-grid__field-name { + width: 35%; + } + + .dataviews-view-grid__field-value { + width: 65%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + + &.is-column { + & + .is-row { + margin-top: $grid-unit-05; + } + } + + .dataviews-view-grid__field-name { + color: $gray-700; + } + } + } + + .dataviews-view-grid__badge-fields { + &:not(:empty) { + padding-bottom: $grid-unit-15; + } + + .dataviews-view-grid__field-value { + width: fit-content; + background: $gray-100; + padding: 0 $grid-unit-10; + min-height: $grid-unit-30; + border-radius: $radius-block-ui; + display: flex; + align-items: center; + font-size: 12px; + } + } +} + +.dataviews-view-grid__field-value:empty, +.dataviews-view-grid__field:empty { + display: none; +} diff --git a/packages/dataviews/src/layouts/list/index.tsx b/packages/dataviews/src/layouts/list/index.tsx index 9cfe727c42b199..68d9f39f447f1e 100644 --- a/packages/dataviews/src/layouts/list/index.tsx +++ b/packages/dataviews/src/layouts/list/index.tsx @@ -33,7 +33,10 @@ import { useRegistry } from '@wordpress/data'; * Internal dependencies */ import { unlock } from '../../lock-unlock'; -import { ActionsDropdownMenuGroup, ActionModal } from '../../item-actions'; +import { + ActionsDropdownMenuGroup, + ActionModal, +} from '../../components/dataviews-item-actions'; import type { Action, NormalizedField, ViewListProps } from '../../types'; interface ListViewItemProps< Item > { diff --git a/packages/dataviews/src/layouts/list/style.scss b/packages/dataviews/src/layouts/list/style.scss new file mode 100644 index 00000000000000..09f29a73b74d2d --- /dev/null +++ b/packages/dataviews/src/layouts/list/style.scss @@ -0,0 +1,189 @@ +.dataviews-view-list { + margin: 0 0 auto; + + li { + margin: 0; + cursor: pointer; + border-top: 1px solid $gray-100; + + .dataviews-view-list__item-wrapper { + position: relative; + border-radius: $grid-unit-05; + + > * { + width: 100%; + } + } + + .dataviews-view-list__item-actions { + position: absolute; + top: $grid-unit-20; + right: 0; + + + > div { + height: $button-size-small; + } + + .components-button { + opacity: 0; + } + } + + &:has(.dataviews-view-list__fields:empty) { + .dataviews-view-list__item-actions { + top: 50%; + transform: translateY(-50%); + } + } + + &.is-selected, + &.is-hovered, + &:focus-within { + .dataviews-view-list__item-actions { + background: #f8f8f8; + padding-left: $grid-unit-10; + margin-right: $grid-unit-30; + box-shadow: -12px 0 8px 0 #f8f8f8; + + .components-button { + opacity: 1; + position: static; + } + } + } + + &.is-selected { + .dataviews-view-list__item-actions { + background-color: rgb(247 248 255); + box-shadow: -12px 0 8px 0 rgb(247 248 255); + } + } + + &.is-selected.is-selected { + border-top: 1px solid rgba(var(--wp-admin-theme-color--rgb), 0.12); + + & + li { + border-top: 1px solid rgba(var(--wp-admin-theme-color--rgb), 0.12); + } + } + + &:not(.is-selected) { + .dataviews-view-list__primary-field { + color: $gray-900; + } + &:hover, + &:focus-within { + color: var(--wp-admin-theme-color); + background-color: #f8f8f8; + + .dataviews-view-list__primary-field, + .dataviews-view-list__fields { + color: var(--wp-admin-theme-color); + } + } + } + + } + + li.is-selected, + li.is-selected:focus-within { + .dataviews-view-list__item-wrapper { + background-color: rgba(var(--wp-admin-theme-color--rgb), 0.04); + color: $gray-900; + + .dataviews-view-list__primary-field, + .dataviews-view-list__fields { + color: var(--wp-admin-theme-color); + } + } + } + + .dataviews-view-list__item { + padding: $grid-unit-20 $grid-unit-30; + width: 100%; + scroll-margin: $grid-unit-10 0; + + &:focus-visible { + &::before { + position: absolute; + content: ""; + top: calc(var(--wp-admin-border-width-focus) + 1px); + right: var(--wp-admin-border-width-focus); + bottom: var(--wp-admin-border-width-focus); + left: var(--wp-admin-border-width-focus); + box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + border-radius: $radius-block-ui; + } + } + .dataviews-view-list__primary-field { + min-height: $grid-unit-30; + line-height: $grid-unit-30; + overflow: hidden; + } + } + + .dataviews-view-list__media-wrapper { + width: $grid-unit-05 * 13; + height: $grid-unit-05 * 13; + overflow: hidden; + position: relative; + flex-shrink: 0; + background-color: $gray-100; + border-radius: $grid-unit-05; + + img { + width: 100%; + height: 100%; + object-fit: cover; + } + + &::after { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + box-shadow: inset 0 0 0 $border-width rgba(0, 0, 0, 0.1); + border-radius: $grid-unit-05; + } + } + + .dataviews-view-list__media-placeholder { + min-width: $grid-unit-40; + height: $grid-unit-40; + background-color: $gray-200; + } + + .dataviews-view-list__field-wrapper { + min-height: $grid-unit-05 * 13; // Ensures title is centrally aligned when all fields are hidden + } + + .dataviews-view-list__fields { + color: $gray-700; + display: flex; + gap: $grid-unit-15; + row-gap: $grid-unit-05; + flex-wrap: wrap; + font-size: 12px; + + &:empty { + display: none; + } + + .dataviews-view-list__field { + &:has(.dataviews-view-list__field-value:empty) { + display: none; + } + } + + .dataviews-view-list__field-value { + line-height: $grid-unit-05 * 6; + } + } + + & + .dataviews-pagination { + justify-content: space-between; + } +} diff --git a/packages/dataviews/src/layouts/table/index.tsx b/packages/dataviews/src/layouts/table/index.tsx index d1df60578a165d..934cff9e23affa 100644 --- a/packages/dataviews/src/layouts/table/index.tsx +++ b/packages/dataviews/src/layouts/table/index.tsx @@ -24,13 +24,13 @@ import { /** * Internal dependencies */ -import SingleSelectionCheckbox from '../../single-selection-checkbox'; -import ItemActions from '../../item-actions'; +import SingleSelectionCheckbox from '../../components/dataviews-selection-checkbox'; +import ItemActions from '../../components/dataviews-item-actions'; import { sortValues } from '../../constants'; import { useSomeItemHasAPossibleBulkAction, useHasAPossibleBulkAction, -} from '../../bulk-actions'; +} from '../../components/dataviews-bulk-actions'; import type { Action, NormalizedField, diff --git a/packages/dataviews/src/layouts/table/style.scss b/packages/dataviews/src/layouts/table/style.scss new file mode 100644 index 00000000000000..debec8afc63745 --- /dev/null +++ b/packages/dataviews/src/layouts/table/style.scss @@ -0,0 +1,201 @@ +.dataviews-view-table { + width: 100%; + text-indent: 0; + border-color: inherit; + border-collapse: collapse; + position: relative; + color: $gray-700; + margin-bottom: auto; + + a { + text-decoration: none; + color: $gray-900; + font-weight: 500; + } + th { + text-align: left; + color: $gray-900; + font-weight: normal; + font-size: $default-font-size; + } + td, + th { + padding: $grid-unit-15; + white-space: nowrap; + + &.dataviews-view-table__actions-column { + text-align: right; + } + + &.dataviews-view-table__checkbox-column { + padding-right: 0; + } + } + tr { + border-top: 1px solid $gray-100; + + .dataviews-view-table-header-button { + gap: $grid-unit-05; + } + + td:first-child, + th:first-child { + padding-left: $grid-unit-60; + + .dataviews-view-table-header-button, + .dataviews-view-table-header { + margin-left: - #{$grid-unit-10}; + } + } + + td:last-child, + th:last-child { + padding-right: $grid-unit-60; + } + + &:last-child { + border-bottom: 0; + } + + &.is-hovered { + background-color: #f8f8f8; + } + + .components-checkbox-control__input.components-checkbox-control__input { + opacity: 0; + + &:checked, + &:indeterminate, + &:focus { + opacity: 1; + } + } + + .dataviews-item-actions .components-button:not(.dataviews-all-actions-button) { + opacity: 0; + } + + &:focus-within, + &.is-hovered, + &:hover { + .components-checkbox-control__input, + .dataviews-item-actions .components-button:not(.dataviews-all-actions-button) { + opacity: 1; + } + } + + @media (hover: none) { + // Show checkboxes and quick-actions on devices that do not support hover. + .components-checkbox-control__input.components-checkbox-control__input, + .dataviews-item-actions .components-button:not(.dataviews-all-actions-button) { + opacity: 1; + } + } + + &.is-ed { + background-color: rgba(var(--wp-admin-theme-color--rgb), 0.04); + color: $gray-700; + + &, + & + tr { + border-top: 1px solid rgba(var(--wp-admin-theme-color--rgb), 0.12); + } + + &:hover { + background-color: rgba(var(--wp-admin-theme-color--rgb), 0.08); + } + } + } + thead { + position: sticky; + inset-block-start: 0; + z-index: z-index(".dataviews-view-table thead"); + + tr { + border: 0; + } + th { + background-color: $white; + padding-top: $grid-unit-10; + padding-bottom: $grid-unit-10; + padding-left: $grid-unit-15; + font-size: 11px; + text-transform: uppercase; + font-weight: 500; + + &:has(.dataviews-view-table-header-button):not(:first-child) { + padding-left: $grid-unit-05; + } + } + } + tbody { + td { + vertical-align: top; + } + .dataviews-view-table__cell-content-wrapper { + min-height: $grid-unit-40; + display: flex; + align-items: center; + } + + .components-v-stack > .dataviews-view-table__cell-content-wrapper:not(:first-child) { + min-height: 0; + } + } + .dataviews-view-table-header-button { + padding: $grid-unit-05 $grid-unit-10; + font-size: 11px; + text-transform: uppercase; + font-weight: 500; + + &:not(:hover) { + color: $gray-900; + } + + span { + speak: none; + + &:empty { + display: none; + } + } + } + + .dataviews-view-table-header { + padding-left: $grid-unit-05; + } + + .dataviews-view-table__actions-column { + width: 1%; + } + + &:has(tr.is-selected) { + .components-checkbox-control__input { + opacity: 1; + } + } +} + +.dataviews-view-table__cell-content-wrapper:empty { + display: none; +} + +/* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ +@container (max-width: 430px) { + .dataviews-view-table tr td:first-child, + .dataviews-view-table tr th:first-child { + padding-left: $grid-unit-30; + } + + .dataviews-view-table tr td:last-child, + .dataviews-view-table tr th:last-child { + padding-right: $grid-unit-30; + } +} + +.dataviews-view-table-selection-checkbox { + --checkbox-input-size: 24px; + @include break-small() { + --checkbox-input-size: 16px; + } +} diff --git a/packages/dataviews/src/style.scss b/packages/dataviews/src/style.scss index ce0e4c812ff03a..49d897d9cc4d97 100644 --- a/packages/dataviews/src/style.scss +++ b/packages/dataviews/src/style.scss @@ -1,951 +1,11 @@ -.dataviews-wrapper { - height: 100%; - overflow: auto; - box-sizing: border-box; - scroll-padding-bottom: $grid-unit-80; - /* stylelint-disable-next-line property-no-unknown -- '@container' not globally permitted */ - container: dataviews-wrapper / inline-size; - display: flex; - flex-direction: column; -} - -.dataviews-filters__view-actions { - box-sizing: border-box; - padding: $grid-unit-20 $grid-unit-60; - flex-shrink: 0; - position: sticky; - left: 0; - transition: padding ease-out 0.1s; - @include reduce-motion("transition"); - - .components-search-control { - .components-base-control__field { - max-width: 240px; - } - } -} - -.dataviews-filters__container { - .dataviews-filters__reset-button[aria-disabled="true"] { - &, - &:hover { - opacity: 0; - } - - &:focus { - opacity: 1; - } - } -} - -.dataviews-filters-button { - position: relative; -} - -.dataviews-pagination { - position: sticky; - bottom: 0; - left: 0; - background-color: $white; - padding: $grid-unit-15 $grid-unit-60; - border-top: $border-width solid $gray-100; - color: $gray-700; - flex-shrink: 0; - transition: padding ease-out 0.1s; - @include reduce-motion("transition"); -} - -.dataviews-pagination__page-selection { - font-size: 11px; - text-transform: uppercase; - font-weight: 500; - color: $gray-900; -} - -.dataviews-filters-options { - margin: $grid-unit-40 0 $grid-unit-20; -} - -.dataviews-view-table { - width: 100%; - text-indent: 0; - border-color: inherit; - border-collapse: collapse; - position: relative; - color: $gray-700; - margin-bottom: auto; - - a { - text-decoration: none; - color: $gray-900; - font-weight: 500; - } - th { - text-align: left; - color: $gray-900; - font-weight: normal; - font-size: $default-font-size; - } - td, - th { - padding: $grid-unit-15; - white-space: nowrap; - - &.dataviews-view-table__actions-column { - text-align: right; - } - - &.dataviews-view-table__checkbox-column { - padding-right: 0; - } - } - tr { - border-top: 1px solid $gray-100; - - .dataviews-view-table-header-button { - gap: $grid-unit-05; - } - - td:first-child, - th:first-child { - padding-left: $grid-unit-60; - - .dataviews-view-table-header-button, - .dataviews-view-table-header { - margin-left: - #{$grid-unit-10}; - } - } - - td:last-child, - th:last-child { - padding-right: $grid-unit-60; - } - - &:last-child { - border-bottom: 0; - } - - &.is-hovered { - background-color: #f8f8f8; - } - - .components-checkbox-control__input.components-checkbox-control__input { - opacity: 0; - - &:checked, - &:indeterminate, - &:focus { - opacity: 1; - } - } - - .dataviews-item-actions .components-button:not(.dataviews-all-actions-button) { - opacity: 0; - } - - &:focus-within, - &.is-hovered, - &:hover { - .components-checkbox-control__input, - .dataviews-item-actions .components-button:not(.dataviews-all-actions-button) { - opacity: 1; - } - } - - @media (hover: none) { - // Show checkboxes and quick-actions on devices that do not support hover. - .components-checkbox-control__input.components-checkbox-control__input, - .dataviews-item-actions .components-button:not(.dataviews-all-actions-button) { - opacity: 1; - } - } - - &.is-selected { - background-color: rgba(var(--wp-admin-theme-color--rgb), 0.04); - color: $gray-700; - - &, - & + tr { - border-top: 1px solid rgba(var(--wp-admin-theme-color--rgb), 0.12); - } - - &:hover { - background-color: rgba(var(--wp-admin-theme-color--rgb), 0.08); - } - } - } - thead { - position: sticky; - inset-block-start: 0; - z-index: z-index(".dataviews-view-table thead"); - - tr { - border: 0; - } - th { - background-color: $white; - padding-top: $grid-unit-10; - padding-bottom: $grid-unit-10; - padding-left: $grid-unit-15; - font-size: 11px; - text-transform: uppercase; - font-weight: 500; - - &:has(.dataviews-view-table-header-button):not(:first-child) { - padding-left: $grid-unit-05; - } - } - } - tbody { - td { - vertical-align: top; - } - .dataviews-view-table__cell-content-wrapper { - min-height: $grid-unit-40; - display: flex; - align-items: center; - } - - .components-v-stack > .dataviews-view-table__cell-content-wrapper:not(:first-child) { - min-height: 0; - } - } - .dataviews-view-table-header-button { - padding: $grid-unit-05 $grid-unit-10; - font-size: 11px; - text-transform: uppercase; - font-weight: 500; - - &:not(:hover) { - color: $gray-900; - } - - span { - speak: none; - - &:empty { - display: none; - } - } - } - - .dataviews-view-table-header { - padding-left: $grid-unit-05; - } - - .dataviews-view-table__actions-column { - width: 1%; - } - - &:has(tr.is-selected) { - .components-checkbox-control__input { - opacity: 1; - } - } -} - -.dataviews-view-table__cell-content-wrapper:empty, -.dataviews-view-grid__field-value:empty, -.dataviews-view-grid__field:empty { - display: none; -} - -.dataviews-view-list__primary-field, -.dataviews-view-grid__primary-field, -.dataviews-view-table__primary-field { - font-size: $default-font-size; - font-weight: 500; - color: $gray-700; - text-overflow: ellipsis; - white-space: nowrap; - width: 100%; - - a { - text-decoration: none; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - display: block; - flex-grow: 0; - color: $gray-900; - - &:hover { - color: var(--wp-admin-theme-color); - } - @include link-reset(); - } - - button.components-button.is-link { - text-decoration: none; - font-weight: inherit; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - display: block; - width: 100%; - color: $gray-900; - &:hover { - color: var(--wp-admin-theme-color); - } - } -} - -.dataviews-view-grid { - margin-bottom: auto; - grid-template-columns: repeat(1, minmax(0, 1fr)) !important; - grid-template-rows: max-content; - padding: 0 $grid-unit-60 $grid-unit-30; - transition: padding ease-out 0.1s; - @include reduce-motion("transition"); - - @include break-mobile() { - grid-template-columns: repeat(2, minmax(0, 1fr)) !important; // Todo: eliminate !important dependency - } - - @include break-xlarge() { - grid-template-columns: repeat(3, minmax(0, 1fr)) !important; // Todo: eliminate !important dependency - } - - @include break-huge() { - grid-template-columns: repeat(4, minmax(0, 1fr)) !important; // Todo: eliminate !important dependency - } - - .dataviews-view-grid__card { - height: 100%; - justify-content: flex-start; - - .dataviews-view-grid__title-actions { - padding: $grid-unit-10 0 $grid-unit-05; - } - - .dataviews-view-grid__primary-field { - min-height: $grid-unit-40; // Preserve layout when there is no ellipsis button - } - - &.is-selected { - .dataviews-view-grid__fields .dataviews-view-grid__field .dataviews-view-grid__field-value { - color: $gray-900; - } - } - } - - .dataviews-view-grid__media { - width: 100%; - min-height: 200px; - aspect-ratio: 1/1; - background-color: $gray-100; - border-radius: $grid-unit-05; - position: relative; - - img { - object-fit: cover; - width: 100%; - height: 100%; - } - - &::after { - content: ""; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - box-shadow: inset 0 0 0 $border-width rgba(0, 0, 0, 0.1); - border-radius: $grid-unit-05; - pointer-events: none; - } - } - - .dataviews-view-grid__fields { - position: relative; - font-size: 12px; - line-height: 16px; - - &:not(:empty) { - padding: 0 0 $grid-unit-15; - } - - .dataviews-view-grid__field { - align-items: flex-start; - min-height: $grid-unit-30; - - &:not(.is-column) { - align-items: center; - - .dataviews-view-grid__field-name { - width: 35%; - } - - .dataviews-view-grid__field-value { - width: 65%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - } - - &.is-column { - & + .is-row { - margin-top: $grid-unit-05; - } - } - - .dataviews-view-grid__field-name { - color: $gray-700; - } - } - } - - .dataviews-view-grid__badge-fields { - &:not(:empty) { - padding-bottom: $grid-unit-15; - } - - .dataviews-view-grid__field-value { - width: fit-content; - background: $gray-100; - padding: 0 $grid-unit-10; - min-height: $grid-unit-30; - border-radius: $radius-block-ui; - display: flex; - align-items: center; - font-size: 12px; - } - } -} - -.dataviews-view-list { - margin: 0 0 auto; - - li { - margin: 0; - cursor: pointer; - border-top: 1px solid $gray-100; - - .dataviews-view-list__item-wrapper { - position: relative; - border-radius: $grid-unit-05; - - > * { - width: 100%; - } - } - - .dataviews-view-list__item-actions { - position: absolute; - top: $grid-unit-20; - right: 0; - - - > div { - height: $button-size-small; - } - - .components-button { - opacity: 0; - } - } - - &:has(.dataviews-view-list__fields:empty) { - .dataviews-view-list__item-actions { - top: 50%; - transform: translateY(-50%); - } - } - - &.is-selected, - &.is-hovered, - &:focus-within { - .dataviews-view-list__item-actions { - background: #f8f8f8; - padding-left: $grid-unit-10; - margin-right: $grid-unit-30; - box-shadow: -12px 0 8px 0 #f8f8f8; - - .components-button { - opacity: 1; - position: static; - } - } - } - - &.is-selected { - .dataviews-view-list__item-actions { - background-color: rgb(247 248 255); - box-shadow: -12px 0 8px 0 rgb(247 248 255); - } - } - - &.is-selected.is-selected { - border-top: 1px solid rgba(var(--wp-admin-theme-color--rgb), 0.12); - - & + li { - border-top: 1px solid rgba(var(--wp-admin-theme-color--rgb), 0.12); - } - } - - &:not(.is-selected) { - .dataviews-view-list__primary-field { - color: $gray-900; - } - &:hover, - &:focus-within { - color: var(--wp-admin-theme-color); - background-color: #f8f8f8; - - .dataviews-view-list__primary-field, - .dataviews-view-list__fields { - color: var(--wp-admin-theme-color); - } - } - } - - } - - li.is-selected, - li.is-selected:focus-within { - .dataviews-view-list__item-wrapper { - background-color: rgba(var(--wp-admin-theme-color--rgb), 0.04); - color: $gray-900; - - .dataviews-view-list__primary-field, - .dataviews-view-list__fields { - color: var(--wp-admin-theme-color); - } - } - } - - .dataviews-view-list__item { - padding: $grid-unit-20 $grid-unit-30; - width: 100%; - scroll-margin: $grid-unit-10 0; - - &:focus-visible { - &::before { - position: absolute; - content: ""; - top: calc(var(--wp-admin-border-width-focus) + 1px); - right: var(--wp-admin-border-width-focus); - bottom: var(--wp-admin-border-width-focus); - left: var(--wp-admin-border-width-focus); - box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - border-radius: $radius-block-ui; - } - } - .dataviews-view-list__primary-field { - min-height: $grid-unit-30; - line-height: $grid-unit-30; - overflow: hidden; - } - } - - .dataviews-view-list__media-wrapper { - width: $grid-unit-05 * 13; - height: $grid-unit-05 * 13; - overflow: hidden; - position: relative; - flex-shrink: 0; - background-color: $gray-100; - border-radius: $grid-unit-05; - - img { - width: 100%; - height: 100%; - object-fit: cover; - } - - &::after { - content: ""; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - box-shadow: inset 0 0 0 $border-width rgba(0, 0, 0, 0.1); - border-radius: $grid-unit-05; - } - } - - .dataviews-view-list__media-placeholder { - min-width: $grid-unit-40; - height: $grid-unit-40; - background-color: $gray-200; - } - - .dataviews-view-list__field-wrapper { - min-height: $grid-unit-05 * 13; // Ensures title is centrally aligned when all fields are hidden - } - - .dataviews-view-list__fields { - color: $gray-700; - display: flex; - gap: $grid-unit-15; - row-gap: $grid-unit-05; - flex-wrap: wrap; - font-size: 12px; - - &:empty { - display: none; - } - - .dataviews-view-list__field { - &:has(.dataviews-view-list__field-value:empty) { - display: none; - } - } - - .dataviews-view-list__field-value { - line-height: $grid-unit-05 * 6; - } - } - - & + .dataviews-pagination { - justify-content: space-between; - } - -} - -.dataviews-action-modal { - z-index: z-index(".dataviews-action-modal"); -} - -.dataviews-no-results, -.dataviews-loading { - padding: 0 $grid-unit-60; - flex-grow: 1; - display: flex; - align-items: center; - justify-content: center; - transition: padding ease-out 0.1s; - @include reduce-motion("transition"); -} - -.dataviews-view-table-selection-checkbox { - // Experimental override for CheckboxControl size (fragile) - --checkbox-input-size: 24px; - @include break-small() { - --checkbox-input-size: 16px; - } - - line-height: 0; - flex-shrink: 0; - - .components-checkbox-control__input-container { - margin: 0; - } -} - -.dataviews-bulk-edit-button.components-button { - flex-shrink: 0; -} - -.dataviews-filter-summary__popover { - .components-popover__content { - width: 230px; - padding: 0; - border-radius: $grid-unit-05; - } -} - -.dataviews-search-widget-filter-combobox-list { - max-height: $grid-unit * 23; - padding: $grid-unit-05; - overflow: auto; - border-top: 1px solid $gray-200; - - .dataviews-search-widget-filter-combobox-item-value { - [data-user-value] { - font-weight: 600; - } - } -} - -.dataviews-search-widget-listbox { - max-height: $grid-unit * 23; - padding: $grid-unit-05; - overflow: auto; -} - -.dataviews-search-widget-listitem { - display: flex; - align-items: center; - gap: $grid-unit-10; - border-radius: $radius-block-ui; - box-sizing: border-box; - padding: $grid-unit-10 $grid-unit-15; - cursor: default; - margin-block-end: 2px; - - &:last-child { - margin-block-end: 0; - } - - &:hover, - &[data-active-item], - &:focus { - background-color: var(--wp-admin-theme-color); - color: $white; - - .dataviews-search-widget-listitem-check { - fill: $white; - } - - .dataviews-search-widget-listitem-description { - color: $white; - } - } - - .dataviews-search-widget-listitem-check { - width: 24px; - height: 24px; - flex-shrink: 0; - } - - .dataviews-search-widget-listitem-description { - display: block; - overflow: hidden; - text-overflow: ellipsis; - font-size: $helptext-font-size; - line-height: 16px; - color: $gray-700; - } -} - -.dataviews-search-widget-filter-combobox__wrapper { - position: relative; - padding: $grid-unit-10; - - .dataviews-search-widget-filter-combobox__input { - @include input-control; - display: block; - padding: 0 $grid-unit-40 0 $grid-unit-10; - background: $gray-100; - border: none; - width: 100%; - height: $grid-unit-40; - - // Unset inherited values. - margin-left: 0; - margin-right: 0; - - /* Fonts smaller than 16px causes mobile safari to zoom. */ - font-size: $mobile-text-min-font-size; - @include break-small { - font-size: $default-font-size; - } - - &:focus { - background: $white; - box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - } - - &::placeholder { - color: $gray-700; - } - - &::-webkit-search-decoration, - &::-webkit-search-cancel-button, - &::-webkit-search-results-button, - &::-webkit-search-results-decoration { - -webkit-appearance: none; - } - } - - .dataviews-search-widget-filter-combobox__icon { - position: absolute; - right: $grid-unit-15; - top: 50%; - transform: translateY(-50%); - display: flex; - align-items: center; - justify-content: center; - width: $icon-size; - } -} - -.dataviews-filter-summary__operators-container { - padding: $grid-unit-10 $grid-unit-10 0; - - &:has(+ .dataviews-search-widget-listbox) { - border-bottom: 1px solid $gray-200; - padding-bottom: $grid-unit-10; - } - - &:empty { - display: none; - } - - .dataviews-filter-summary__operators-filter-name { - color: $gray-700; - } -} - -.dataviews-filter-summary__chip-container { - position: relative; - white-space: pre-wrap; - - .dataviews-filter-summary__chip { - border-radius: $grid-unit-20; - border: 1px solid transparent; - cursor: pointer; - padding: $grid-unit-05 $grid-unit-15; - min-height: $grid-unit-40; - background: $gray-100; - color: $gray-800; - position: relative; - display: flex; - align-items: center; - - &.has-reset { - padding-inline-end: $button-size-small + $grid-unit-05; - } - - &:hover, - &:focus-visible, - &[aria-expanded="true"] { - background: $gray-200; - color: $gray-900; - } - - &.has-values { - color: var(--wp-admin-theme-color); - background: rgba(var(--wp-admin-theme-color--rgb), 0.04); - - &:hover, - &[aria-expanded="true"] { - background: rgba(var(--wp-admin-theme-color--rgb), 0.12); - } - } - - &:focus-visible { - outline: none; - box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - } - - .dataviews-filter-summary__filter-text-name { - font-weight: 500; - } - } - - .dataviews-filter-summary__chip-remove { - width: $icon-size; - height: $icon-size; - border-radius: 50%; - border: 0; - padding: 0; - position: absolute; - right: $grid-unit-05; - top: 50%; - transform: translateY(-50%); - display: flex; - align-items: center; - justify-content: center; - background: transparent; - cursor: pointer; - - svg { - fill: $gray-700; - } - - &:hover, - &:focus { - background: $gray-200; - svg { - fill: $gray-900; - } - } - - &.has-values { - svg { - fill: var(--wp-admin-theme-color); - } - &:hover { - background: rgba(var(--wp-admin-theme-color--rgb), 0.08); - } - } - - &:focus-visible { - outline: none; - box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - } - } -} - -/* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ -@container (max-width: 430px) { - .dataviews-pagination, - .dataviews-filters__view-actions { - padding: $grid-unit-15 $grid-unit-30; - } - - .dataviews-filters__view-actions { - .components-search-control { - .components-base-control__field { - max-width: 112px; - } - } - } - - .dataviews-view-table tr td:first-child, - .dataviews-view-table tr th:first-child { - padding-left: $grid-unit-30; - } - - .dataviews-view-table tr td:last-child, - .dataviews-view-table tr th:last-child { - padding-right: $grid-unit-30; - } - - .dataviews-view-grid, - .dataviews-no-results, - .dataviews-loading { - padding-left: $grid-unit-30; - padding-right: $grid-unit-30; - } -} - -.dataviews-bulk-actions-toolbar-wrapper { - display: flex; - flex-grow: 1; - width: 100%; - - .components-toolbar-group { - align-items: center; - } - - .components-button.is-busy { - max-height: $button-size; - } -} - -.dataviews-bulk-actions { - position: sticky; - display: flex; - flex-direction: column; - align-content: center; - flex-wrap: wrap; - width: fit-content; - margin-left: auto; - margin-right: auto; - bottom: $grid-unit-30; - z-index: z-index(".dataviews-bulk-actions"); - - .components-accessible-toolbar { - border-color: $gray-300; - box-shadow: $shadow-popover; - - .components-toolbar-group { - border-color: $gray-200; - - &:last-child { - border: 0; - } - } - } - - .dataviews-bulk-actions__selection-count { - display: flex; - align-items: center; - margin: 0 $grid-unit-10 0 $grid-unit-10; - } -} +@import "./components/dataviews/style.scss"; +@import "./components/dataviews-bulk-actions/style.scss"; +@import "./components/dataviews-bulk-actions-toolbar/style.scss"; +@import "./components/dataviews-filters/style.scss"; +@import "./components/dataviews-pagination/style.scss"; +@import "./components/dataviews-item-actions/style.scss"; +@import "./components/dataviews-selection-checkbox/style.scss"; + +@import "./layouts/grid/style.scss"; +@import "./layouts/list/style.scss"; +@import "./layouts/table/style.scss"; From 154f1aaeea73ba1ed2c17373814c8c3620dc9626 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Fri, 19 Jul 2024 04:40:48 -0700 Subject: [PATCH 0015/1908] Zoom Out: fix crash due to absence of selected block (#63642) Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../components/block-tools/use-show-block-tools.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/use-show-block-tools.js b/packages/block-editor/src/components/block-tools/use-show-block-tools.js index 83757790d11ea2..70a0b9f53a3421 100644 --- a/packages/block-editor/src/components/block-tools/use-show-block-tools.js +++ b/packages/block-editor/src/components/block-tools/use-show-block-tools.js @@ -29,10 +29,11 @@ export function useShowBlockTools() { const clientId = getSelectedBlockClientId() || getFirstMultiSelectedBlockClientId(); - const block = getBlock( clientId ) || { name: '', attributes: {} }; + const block = getBlock( clientId ); const editorMode = __unstableGetEditorMode(); - const hasSelectedBlock = clientId && block?.name; - const isEmptyDefaultBlock = isUnmodifiedDefaultBlock( block ); + const hasSelectedBlock = !! clientId && !! block; + const isEmptyDefaultBlock = + hasSelectedBlock && isUnmodifiedDefaultBlock( block ); const _showEmptyBlockSideInserter = clientId && ! isTyping() && @@ -43,8 +44,9 @@ export function useShowBlockTools() { ! hasMultiSelection() && editorMode === 'navigation'; + const isZoomOut = editorMode === 'zoom-out'; const _showBlockToolbarPopover = - editorMode !== 'zoom-out' && + ! isZoomOut && ! getSettings().hasFixedToolbar && ! _showEmptyBlockSideInserter && hasSelectedBlock && @@ -57,7 +59,8 @@ export function useShowBlockTools() { ! _showEmptyBlockSideInserter && maybeShowBreadcrumb, showBlockToolbarPopover: _showBlockToolbarPopover, showZoomOutToolbar: - editorMode === 'zoom-out' && + hasSelectedBlock && + isZoomOut && ! _showEmptyBlockSideInserter && ! maybeShowBreadcrumb && ! _showBlockToolbarPopover, From 91ea63230969c9d256054ed05909e3bbbaa4dfdf Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 19 Jul 2024 19:02:25 +0400 Subject: [PATCH 0016/1908] Widget Editor: Remove unused values returned from 'mapSelect' (#63738) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- .../src/components/widget-areas-block-editor-provider/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js b/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js index d3920f1103a334..6d014a589252d9 100644 --- a/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js +++ b/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js @@ -55,8 +55,6 @@ export default function WidgetAreasBlockEditorProvider( { ? getEntityRecord( 'root', 'site' ) : undefined; return { - widgetAreas: select( editWidgetsStore ).getWidgetAreas(), - widgets: select( editWidgetsStore ).getWidgets(), reusableBlocks: ALLOW_REUSABLE_BLOCKS ? getEntityRecords( 'postType', 'wp_block' ) : EMPTY_ARRAY, From dc93da08a38af14aef07906c63ec11a599d74582 Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Fri, 19 Jul 2024 16:31:25 +0100 Subject: [PATCH 0017/1908] Fix vertical toolbar position (#63745) Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> --- .../block-editor/src/components/block-tools/zoom-out-popover.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/components/block-tools/zoom-out-popover.js b/packages/block-editor/src/components/block-tools/zoom-out-popover.js index 7b6f29382a6f22..0a7ab6d31fab8f 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-popover.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-popover.js @@ -28,6 +28,7 @@ export default function ZoomOutPopover( { clientId, __unstableContentRef } ) { ...popoverProps, placement: 'left-start', flip: false, + shift: true, }; return ( From e63b8b8be7bdc5e9dd2781c597e918a7be212fe5 Mon Sep 17 00:00:00 2001 From: Gerardo Pacheco <gerardo.pacheco@automattic.com> Date: Fri, 19 Jul 2024 22:13:29 +0200 Subject: [PATCH 0018/1908] Mobile Release v1.121.0 (#63744) * Release script: Update react-native-editor version to 1.121.0 * Release script: Update CHANGELOG for version 1.121.0 * Release script: Update podfile --- package-lock.json | 6 +++--- packages/react-native-aztec/package.json | 2 +- packages/react-native-bridge/package.json | 2 +- packages/react-native-editor/CHANGELOG.md | 2 ++ packages/react-native-editor/ios/Podfile.lock | 8 ++++---- packages/react-native-editor/package.json | 2 +- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index e6e8687a475f5b..8785725ed594b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54269,7 +54269,7 @@ }, "packages/react-native-aztec": { "name": "@wordpress/react-native-aztec", - "version": "1.120.1", + "version": "1.121.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/element": "file:../element", @@ -54286,7 +54286,7 @@ }, "packages/react-native-bridge": { "name": "@wordpress/react-native-bridge", - "version": "1.120.1", + "version": "1.121.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/react-native-aztec": "file:../react-native-aztec" @@ -54301,7 +54301,7 @@ }, "packages/react-native-editor": { "name": "@wordpress/react-native-editor", - "version": "1.120.1", + "version": "1.121.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/packages/react-native-aztec/package.json b/packages/react-native-aztec/package.json index 9681423ec4506e..e2f5d5f425d869 100644 --- a/packages/react-native-aztec/package.json +++ b/packages/react-native-aztec/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-native-aztec", - "version": "1.120.1", + "version": "1.121.0", "description": "Aztec view for react-native.", "private": true, "author": "The WordPress Contributors", diff --git a/packages/react-native-bridge/package.json b/packages/react-native-bridge/package.json index e016e11a4682b5..925b83103dca00 100644 --- a/packages/react-native-bridge/package.json +++ b/packages/react-native-bridge/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-native-bridge", - "version": "1.120.1", + "version": "1.121.0", "description": "Native bridge library used to integrate the block editor into a native App.", "private": true, "author": "The WordPress Contributors", diff --git a/packages/react-native-editor/CHANGELOG.md b/packages/react-native-editor/CHANGELOG.md index 14aa5aa9c9f8bf..6031e402100c98 100644 --- a/packages/react-native-editor/CHANGELOG.md +++ b/packages/react-native-editor/CHANGELOG.md @@ -11,6 +11,8 @@ For each user feature we should also add a importance categorization label to i ## Unreleased + +## 1.121.0 - [internal] Fix Inserter items list filtering [#62334] - [*] Prevent hiding the keyboard when creating new list items [#62446] - [*] Fix issue when pasting HTML content [#62588] diff --git a/packages/react-native-editor/ios/Podfile.lock b/packages/react-native-editor/ios/Podfile.lock index 7e9fba1fa2b89a..67dd8345fe5ac7 100644 --- a/packages/react-native-editor/ios/Podfile.lock +++ b/packages/react-native-editor/ios/Podfile.lock @@ -13,7 +13,7 @@ PODS: - ReactCommon/turbomodule/core (= 0.73.3) - fmt (6.2.1) - glog (0.3.5) - - Gutenberg (1.120.1): + - Gutenberg (1.121.0): - React-Core (= 0.73.3) - React-CoreModules (= 0.73.3) - React-RCTImage (= 0.73.3) @@ -1109,7 +1109,7 @@ PODS: - React-Core - RNSVG (14.0.0): - React-Core - - RNTAztecView (1.120.1): + - RNTAztecView (1.121.0): - React-Core - WordPress-Aztec-iOS (= 1.19.11) - SDWebImage (5.11.1): @@ -1343,7 +1343,7 @@ SPEC CHECKSUMS: FBReactNativeSpec: 73b3972e2bd20b3235ff2014f06a3d3af675ed29 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: c5d68082e772fa1c511173d6b30a9de2c05a69a2 - Gutenberg: 1f3141594d15fc34e121ae5921676a49332e9009 + Gutenberg: 7ab890c59b6a4df2fc30d4cc0a468e46bc6e888e hermes-engine: 5420539d016f368cd27e008f65f777abd6098c56 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 libwebp: 60305b2e989864154bd9be3d772730f08fc6a59c @@ -1402,7 +1402,7 @@ SPEC CHECKSUMS: RNReanimated: 6936b41d8afb97175e7c0ab40425b53103f71046 RNScreens: 2b73f5eb2ac5d94fbd61fa4be0bfebd345716825 RNSVG: 255767813dac22db1ec2062c8b7e7b856d4e5ae6 - RNTAztecView: e7495baad7608c5e7e9e9a43ee537282dae7ccdc + RNTAztecView: 8a6e9336ee33bfa61e05e2cdb0b128f9005ab6c6 SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json index 788cdedde9677c..976ef742586c3a 100644 --- a/packages/react-native-editor/package.json +++ b/packages/react-native-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-native-editor", - "version": "1.120.1", + "version": "1.121.0", "description": "Mobile WordPress gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 5f9116e08353c4659128b485edfb4aac0a9e6693 Mon Sep 17 00:00:00 2001 From: Dennis Snell <dennis.snell@automattic.com> Date: Thu, 18 Jul 2024 16:50:30 -0700 Subject: [PATCH 0019/1908] HTML API: Backport updates from Core (#63723) Updates the HTML API files in the 6.7 compatability layer, bringing in code that has been merged into Core. Co-authored-by: Jon Surrell <sirreal@users.noreply.github.com> --- .../class-gutenberg-token-map-6-7.php | 820 ++++ ...rg-html-active-formatting-elements-6-7.php | 187 + ...ass-gutenberg-html-attribute-token-6-7.php | 116 + .../class-gutenberg-html-decoder-6-7.php | 461 +++ ...class-gutenberg-html-open-elements-6-7.php | 598 +++ .../class-gutenberg-html-processor-6-7.php | 3402 ++++++++++++++++ ...ass-gutenberg-html-processor-state-6-7.php | 417 ++ .../class-gutenberg-html-span-6-7.php | 56 + .../class-gutenberg-html-stack-event-6-7.php | 82 + ...class-gutenberg-html-tag-processor-6-7.php | 3521 +++++++++++++++++ ...ss-gutenberg-html-text-replacement-6-7.php | 64 + .../class-gutenberg-html-token-6-7.php | 106 + ...tenberg-html-unsupported-exception-6-7.php | 115 + lib/load.php | 17 +- packages/block-library/src/button/index.php | 4 +- 15 files changed, 9963 insertions(+), 3 deletions(-) create mode 100644 lib/compat/wordpress-6.7/class-gutenberg-token-map-6-7.php create mode 100644 lib/compat/wordpress-6.7/html-api/class-gutenberg-html-active-formatting-elements-6-7.php create mode 100644 lib/compat/wordpress-6.7/html-api/class-gutenberg-html-attribute-token-6-7.php create mode 100644 lib/compat/wordpress-6.7/html-api/class-gutenberg-html-decoder-6-7.php create mode 100644 lib/compat/wordpress-6.7/html-api/class-gutenberg-html-open-elements-6-7.php create mode 100644 lib/compat/wordpress-6.7/html-api/class-gutenberg-html-processor-6-7.php create mode 100644 lib/compat/wordpress-6.7/html-api/class-gutenberg-html-processor-state-6-7.php create mode 100644 lib/compat/wordpress-6.7/html-api/class-gutenberg-html-span-6-7.php create mode 100644 lib/compat/wordpress-6.7/html-api/class-gutenberg-html-stack-event-6-7.php create mode 100644 lib/compat/wordpress-6.7/html-api/class-gutenberg-html-tag-processor-6-7.php create mode 100644 lib/compat/wordpress-6.7/html-api/class-gutenberg-html-text-replacement-6-7.php create mode 100644 lib/compat/wordpress-6.7/html-api/class-gutenberg-html-token-6-7.php create mode 100644 lib/compat/wordpress-6.7/html-api/class-gutenberg-html-unsupported-exception-6-7.php diff --git a/lib/compat/wordpress-6.7/class-gutenberg-token-map-6-7.php b/lib/compat/wordpress-6.7/class-gutenberg-token-map-6-7.php new file mode 100644 index 00000000000000..a2142171ddc14f --- /dev/null +++ b/lib/compat/wordpress-6.7/class-gutenberg-token-map-6-7.php @@ -0,0 +1,820 @@ +<?php + +/** + * Class for efficiently looking up and mapping string keys to string values, with limits. + * + * @package WordPress + * @since 6.6.0 + */ + +/** + * WP_Token_Map class. + * + * Use this class in specific circumstances with a static set of lookup keys which map to + * a static set of transformed values. For example, this class is used to map HTML named + * character references to their equivalent UTF-8 values. + * + * This class works differently than code calling `in_array()` and other methods. It + * internalizes lookup logic and provides helper interfaces to optimize lookup and + * transformation. It provides a method for precomputing the lookup tables and storing + * them as PHP source code. + * + * All tokens and substitutions must be shorter than 256 bytes. + * + * Example: + * + * $smilies = WP_Token_Map::from_array( array( + * '8O' => '😯', + * ':(' => '🙁', + * ':)' => '🙂', + * ':?' => '😕', + * ) ); + * + * true === $smilies->contains( ':)' ); + * false === $smilies->contains( 'simile' ); + * + * '😕' === $smilies->read_token( 'Not sure :?.', 9, $length_of_smily_syntax ); + * 2 === $length_of_smily_syntax; + * + * ## Precomputing the Token Map. + * + * Creating the class involves some work sorting and organizing the tokens and their + * replacement values. In order to skip this, it's possible for the class to export + * its state and be used as actual PHP source code. + * + * Example: + * + * // Export with four spaces as the indent, only for the sake of this docblock. + * // The default indent is a tab character. + * $indent = ' '; + * echo $smilies->precomputed_php_source_table( $indent ); + * + * // Output, to be pasted into a PHP source file: + * WP_Token_Map::from_precomputed_table( + * array( + * "storage_version" => "6.6.0", + * "key_length" => 2, + * "groups" => "", + * "long_words" => array(), + * "small_words" => "8O\x00:)\x00:(\x00:?\x00", + * "small_mappings" => array( "😯", "🙂", "🙁", "😕" ) + * ) + * ); + * + * ## Large vs. small words. + * + * This class uses a short prefix called the "key" to optimize lookup of its tokens. + * This means that some tokens may be shorter than or equal in length to that key. + * Those words that are longer than the key are called "large" while those shorter + * than or equal to the key length are called "small." + * + * This separation of large and small words is incidental to the way this class + * optimizes lookup, and should be considered an internal implementation detail + * of the class. It may still be important to be aware of it, however. + * + * ## Determining Key Length. + * + * The choice of the size of the key length should be based on the data being stored in + * the token map. It should divide the data as evenly as possible, but should not create + * so many groups that a large fraction of the groups only contain a single token. + * + * For the HTML5 named character references, a key length of 2 was found to provide a + * sufficient spread and should be a good default for relatively large sets of tokens. + * + * However, for some data sets this might be too long. For example, a list of smilies + * may be too small for a key length of 2. Perhaps 1 would be more appropriate. It's + * best to experiment and determine empirically which values are appropriate. + * + * ## Generate Pre-Computed Source Code. + * + * Since the `WP_Token_Map` is designed for relatively static lookups, it can be + * advantageous to precompute the values and instantiate a table that has already + * sorted and grouped the tokens and built the lookup strings. + * + * This can be done with `WP_Token_Map::precomputed_php_source_table()`. + * + * Note that if there is a leading character that all tokens need, such as `&` for + * HTML named character references, it can be beneficial to exclude this from the + * token map. Instead, find occurrences of the leading character and then use the + * token map to see if the following characters complete the token. + * + * Example: + * + * $map = WP_Token_Map::from_array( array( 'simple_smile:' => '🙂', 'sob:' => '😭', 'soba:' => '🍜' ) ); + * echo $map->precomputed_php_source_table(); + * // Output + * WP_Token_Map::from_precomputed_table( + * array( + * "storage_version" => "6.6.0", + * "key_length" => 2, + * "groups" => "si\x00so\x00", + * "long_words" => array( + * // simple_smile:[🙂]. + * "\x0bmple_smile:\x04🙂", + * // soba:[🍜] sob:[😭]. + * "\x03ba:\x04🍜\x02b:\x04😭", + * ), + * "short_words" => "", + * "short_mappings" => array() + * } + * ); + * + * This precomputed value can be stored directly in source code and will skip the + * startup cost of generating the lookup strings. See `$html5_named_character_entities`. + * + * Note that any updates to the precomputed format should update the storage version + * constant. It would also be best to provide an update function to take older known + * versions and upgrade them in place when loading into `from_precomputed_table()`. + * + * ## Future Direction. + * + * It may be viable to dynamically increase the length limits such that there's no need to impose them. + * The limit appears because of the packing structure, which indicates how many bytes each segment of + * text in the lookup tables spans. If, however, care were taken to track the longest word length, then + * the packing structure could change its representation to allow for that. Each additional byte storing + * length, however, increases the memory overhead and lookup runtime. + * + * An alternative approach could be to borrow the UTF-8 variable-length encoding and store lengths of less + * than 127 as a single byte with the high bit unset, storing longer lengths as the combination of + * continuation bytes. + * + * Since it has not been shown during the development of this class that longer strings are required, this + * update is deferred until such a need is clear. + * + * @since 6.6.0 + */ +class Gutenberg_Token_Map_6_7 { + /** + * Denotes the version of the code which produces pre-computed source tables. + * + * This version will be used not only to verify pre-computed data, but also + * to upgrade pre-computed data from older versions. Choosing a name that + * corresponds to the WordPress release will help people identify where an + * old copy of data came from. + */ + const STORAGE_VERSION = '6.6.0-trunk'; + + /** + * Maximum length for each key and each transformed value in the table (in bytes). + * + * @since 6.6.0 + */ + const MAX_LENGTH = 256; + + /** + * How many bytes of each key are used to form a group key for lookup. + * This also determines whether a word is considered short or long. + * + * @since 6.6.0 + * + * @var int + */ + private $key_length = 2; + + /** + * Stores an optimized form of the word set, where words are grouped + * by a prefix of the `$key_length` and then collapsed into a string. + * + * In each group, the keys and lookups form a packed data structure. + * The keys in the string are stripped of their "group key," which is + * the prefix of length `$this->key_length` shared by all of the items + * in the group. Each word in the string is prefixed by a single byte + * whose raw unsigned integer value represents how many bytes follow. + * + * ┌────────────────┬───────────────┬─────────────────┬────────┐ + * │ Length of rest │ Rest of key │ Length of value │ Value │ + * │ of key (bytes) │ │ (bytes) │ │ + * ├────────────────┼───────────────┼─────────────────┼────────┤ + * │ 0x08 │ nterDot; │ 0x02 │ · │ + * └────────────────┴───────────────┴─────────────────┴────────┘ + * + * In this example, the key `CenterDot;` has a group key `Ce`, leaving + * eight bytes for the rest of the key, `nterDot;`, and two bytes for + * the transformed value `·` (or U+B7 or "\xC2\xB7"). + * + * Example: + * + * // Stores array( 'CenterDot;' => '·', 'Cedilla;' => '¸' ). + * $groups = "Ce\x00"; + * $large_words = array( "\x08nterDot;\x02·\x06dilla;\x02¸" ) + * + * The prefixes appear in the `$groups` string, each followed by a null + * byte. This makes for quick lookup of where in the group string the key + * is found, and then a simple division converts that offset into the index + * in the `$large_words` array where the group string is to be found. + * + * This lookup data structure is designed to optimize cache locality and + * minimize indirect memory reads when matching strings in the set. + * + * @since 6.6.0 + * + * @var array + */ + private $large_words = array(); + + /** + * Stores the group keys for sequential string lookup. + * + * The offset into this string where the group key appears corresponds with the index + * into the group array where the rest of the group string appears. This is an optimization + * to improve cache locality while searching and minimize indirect memory accesses. + * + * @since 6.6.0 + * + * @var string + */ + private $groups = ''; + + /** + * Stores an optimized row of small words, where every entry is + * `$this->key_size + 1` bytes long and zero-extended. + * + * This packing allows for direct lookup of a short word followed + * by the null byte, if extended to `$this->key_size + 1`. + * + * Example: + * + * // Stores array( 'GT', 'LT', 'gt', 'lt' ). + * "GT\x00LT\x00gt\x00lt\x00" + * + * @since 6.6.0 + * + * @var string + */ + private $small_words = ''; + + /** + * Replacements for the small words, in the same order they appear. + * + * With the position of a small word it's possible to index the translation + * directly, as its position in the `$small_words` string corresponds to + * the index of the replacement in the `$small_mapping` array. + * + * Example: + * + * array( '>', '<', '>', '<' ) + * + * @since 6.6.0 + * + * @var string[] + */ + private $small_mappings = array(); + + /** + * Create a token map using an associative array of key/value pairs as the input. + * + * Example: + * + * $smilies = WP_Token_Map::from_array( array( + * '8O' => '😯', + * ':(' => '🙁', + * ':)' => '🙂', + * ':?' => '😕', + * ) ); + * + * @since 6.6.0 + * + * @param array $mappings The keys transform into the values, both are strings. + * @param int $key_length Determines the group key length. Leave at the default value + * of 2 unless there's an empirical reason to change it. + * + * @return WP_Token_Map|null Token map, unless unable to create it. + */ + public static function from_array( array $mappings, int $key_length = 2 ): ?WP_Token_Map { + $map = new WP_Token_Map(); + $map->key_length = $key_length; + + // Start by grouping words. + + $groups = array(); + $shorts = array(); + foreach ( $mappings as $word => $mapping ) { + if ( + self::MAX_LENGTH <= strlen( $word ) || + self::MAX_LENGTH <= strlen( $mapping ) + ) { + _doing_it_wrong( + __METHOD__, + sprintf( + /* translators: 1: maximum byte length (a count) */ + __( 'Token Map tokens and substitutions must all be shorter than %1$d bytes.' ), + self::MAX_LENGTH + ), + '6.6.0' + ); + return null; + } + + $length = strlen( $word ); + + if ( $key_length >= $length ) { + $shorts[] = $word; + } else { + $group = substr( $word, 0, $key_length ); + + if ( ! isset( $groups[ $group ] ) ) { + $groups[ $group ] = array(); + } + + $groups[ $group ][] = array( substr( $word, $key_length ), $mapping ); + } + } + + /* + * Sort the words to ensure that no smaller substring of a match masks the full match. + * For example, `Cap` should not match before `CapitalDifferentialD`. + */ + usort( $shorts, 'WP_Token_Map::longest_first_then_alphabetical' ); + foreach ( $groups as $group_key => $group ) { + usort( + $groups[ $group_key ], + static function ( array $a, array $b ): int { + return self::longest_first_then_alphabetical( $a[0], $b[0] ); + } + ); + } + + // Finally construct the optimized lookups. + + foreach ( $shorts as $word ) { + $map->small_words .= str_pad( $word, $key_length + 1, "\x00", STR_PAD_RIGHT ); + $map->small_mappings[] = $mappings[ $word ]; + } + + $group_keys = array_keys( $groups ); + sort( $group_keys ); + + foreach ( $group_keys as $group ) { + $map->groups .= "{$group}\x00"; + + $group_string = ''; + + foreach ( $groups[ $group ] as $group_word ) { + list( $word, $mapping ) = $group_word; + + $word_length = pack( 'C', strlen( $word ) ); + $mapping_length = pack( 'C', strlen( $mapping ) ); + $group_string .= "{$word_length}{$word}{$mapping_length}{$mapping}"; + } + + $map->large_words[] = $group_string; + } + + return $map; + } + + /** + * Creates a token map from a pre-computed table. + * This skips the initialization cost of generating the table. + * + * This function should only be used to load data created with + * WP_Token_Map::precomputed_php_source_tag(). + * + * @since 6.6.0 + * + * @param array $state { + * Stores pre-computed state for directly loading into a Token Map. + * + * @type string $storage_version Which version of the code produced this state. + * @type int $key_length Group key length. + * @type string $groups Group lookup index. + * @type array $large_words Large word groups and packed strings. + * @type string $small_words Small words packed string. + * @type array $small_mappings Small word mappings. + * } + * + * @return WP_Token_Map Map with precomputed data loaded. + */ + public static function from_precomputed_table( $state ): ?WP_Token_Map { + $has_necessary_state = isset( + $state['storage_version'], + $state['key_length'], + $state['groups'], + $state['large_words'], + $state['small_words'], + $state['small_mappings'] + ); + + if ( ! $has_necessary_state ) { + _doing_it_wrong( + __METHOD__, + __( 'Missing required inputs to pre-computed WP_Token_Map.' ), + '6.6.0' + ); + return null; + } + + if ( self::STORAGE_VERSION !== $state['storage_version'] ) { + _doing_it_wrong( + __METHOD__, + /* translators: 1: version string, 2: version string. */ + sprintf( __( 'Loaded version \'%1$s\' incompatible with expected version \'%2$s\'.' ), $state['storage_version'], self::STORAGE_VERSION ), + '6.6.0' + ); + return null; + } + + $map = new WP_Token_Map(); + + $map->key_length = $state['key_length']; + $map->groups = $state['groups']; + $map->large_words = $state['large_words']; + $map->small_words = $state['small_words']; + $map->small_mappings = $state['small_mappings']; + + return $map; + } + + /** + * Indicates if a given word is a lookup key in the map. + * + * Example: + * + * true === $smilies->contains( ':)' ); + * false === $smilies->contains( 'simile' ); + * + * @since 6.6.0 + * + * @param string $word Determine if this word is a lookup key in the map. + * @param string $case_sensitivity Optional. Pass 'ascii-case-insensitive' to ignore ASCII case when matching. Default 'case-sensitive'. + * @return bool Whether there's an entry for the given word in the map. + */ + public function contains( string $word, string $case_sensitivity = 'case-sensitive' ): bool { + $ignore_case = 'ascii-case-insensitive' === $case_sensitivity; + + if ( $this->key_length >= strlen( $word ) ) { + if ( 0 === strlen( $this->small_words ) ) { + return false; + } + + $term = str_pad( $word, $this->key_length + 1, "\x00", STR_PAD_RIGHT ); + $word_at = $ignore_case ? stripos( $this->small_words, $term ) : strpos( $this->small_words, $term ); + if ( false === $word_at ) { + return false; + } + + return true; + } + + $group_key = substr( $word, 0, $this->key_length ); + $group_at = $ignore_case ? stripos( $this->groups, $group_key ) : strpos( $this->groups, $group_key ); + if ( false === $group_at ) { + return false; + } + $group = $this->large_words[ $group_at / ( $this->key_length + 1 ) ]; + $group_length = strlen( $group ); + $slug = substr( $word, $this->key_length ); + $length = strlen( $slug ); + $at = 0; + + while ( $at < $group_length ) { + $token_length = unpack( 'C', $group[ $at++ ] )[1]; + $token_at = $at; + $at += $token_length; + $mapping_length = unpack( 'C', $group[ $at++ ] )[1]; + $mapping_at = $at; + + if ( $token_length === $length && 0 === substr_compare( $group, $slug, $token_at, $token_length, $ignore_case ) ) { + return true; + } + + $at = $mapping_at + $mapping_length; + } + + return false; + } + + /** + * If the text starting at a given offset is a lookup key in the map, + * return the corresponding transformation from the map, else `false`. + * + * This function returns the translated string, but accepts an optional + * parameter `$matched_token_byte_length`, which communicates how many + * bytes long the lookup key was, if it found one. This can be used to + * advance a cursor in calling code if a lookup key was found. + * + * Example: + * + * false === $smilies->read_token( 'Not sure :?.', 0, $token_byte_length ); + * '😕' === $smilies->read_token( 'Not sure :?.', 9, $token_byte_length ); + * 2 === $token_byte_length; + * + * Example: + * + * while ( $at < strlen( $input ) ) { + * $next_at = strpos( $input, ':', $at ); + * if ( false === $next_at ) { + * break; + * } + * + * $smily = $smilies->read_token( $input, $next_at, $token_byte_length ); + * if ( false === $next_at ) { + * ++$at; + * continue; + * } + * + * $prefix = substr( $input, $at, $next_at - $at ); + * $at += $token_byte_length; + * $output .= "{$prefix}{$smily}"; + * } + * + * @since 6.6.0 + * + * @param string $text String in which to search for a lookup key. + * @param int $offset Optional. How many bytes into the string where the lookup key ought to start. Default 0. + * @param int|null &$matched_token_byte_length Optional. Holds byte-length of found token matched, otherwise not set. Default null. + * @param string $case_sensitivity Optional. Pass 'ascii-case-insensitive' to ignore ASCII case when matching. Default 'case-sensitive'. + * + * @return string|null Mapped value of lookup key if found, otherwise `null`. + */ + public function read_token( string $text, int $offset = 0, &$matched_token_byte_length = null, $case_sensitivity = 'case-sensitive' ): ?string { + $ignore_case = 'ascii-case-insensitive' === $case_sensitivity; + $text_length = strlen( $text ); + + // Search for a long word first, if the text is long enough, and if that fails, a short one. + if ( $text_length > $this->key_length ) { + $group_key = substr( $text, $offset, $this->key_length ); + + $group_at = $ignore_case ? stripos( $this->groups, $group_key ) : strpos( $this->groups, $group_key ); + if ( false === $group_at ) { + // Perhaps a short word then. + return strlen( $this->small_words ) > 0 + ? $this->read_small_token( $text, $offset, $matched_token_byte_length, $case_sensitivity ) + : null; + } + + $group = $this->large_words[ $group_at / ( $this->key_length + 1 ) ]; + $group_length = strlen( $group ); + $at = 0; + while ( $at < $group_length ) { + $token_length = unpack( 'C', $group[ $at++ ] )[1]; + $token = substr( $group, $at, $token_length ); + $at += $token_length; + $mapping_length = unpack( 'C', $group[ $at++ ] )[1]; + $mapping_at = $at; + + if ( 0 === substr_compare( $text, $token, $offset + $this->key_length, $token_length, $ignore_case ) ) { + $matched_token_byte_length = $this->key_length + $token_length; + return substr( $group, $mapping_at, $mapping_length ); + } + + $at = $mapping_at + $mapping_length; + } + } + + // Perhaps a short word then. + return strlen( $this->small_words ) > 0 + ? $this->read_small_token( $text, $offset, $matched_token_byte_length, $case_sensitivity ) + : null; + } + + /** + * Finds a match for a short word at the index. + * + * @since 6.6.0 + * + * @param string $text String in which to search for a lookup key. + * @param int $offset Optional. How many bytes into the string where the lookup key ought to start. Default 0. + * @param int|null &$matched_token_byte_length Optional. Holds byte-length of found lookup key if matched, otherwise not set. Default null. + * @param string $case_sensitivity Optional. Pass 'ascii-case-insensitive' to ignore ASCII case when matching. Default 'case-sensitive'. + * + * @return string|null Mapped value of lookup key if found, otherwise `null`. + */ + private function read_small_token( string $text, int $offset = 0, &$matched_token_byte_length = null, $case_sensitivity = 'case-sensitive' ): ?string { + $ignore_case = 'ascii-case-insensitive' === $case_sensitivity; + $small_length = strlen( $this->small_words ); + $search_text = substr( $text, $offset, $this->key_length ); + if ( $ignore_case ) { + $search_text = strtoupper( $search_text ); + } + $starting_char = $search_text[0]; + + $at = 0; + while ( $at < $small_length ) { + if ( + $starting_char !== $this->small_words[ $at ] && + ( ! $ignore_case || strtoupper( $this->small_words[ $at ] ) !== $starting_char ) + ) { + $at += $this->key_length + 1; + continue; + } + + for ( $adjust = 1; $adjust < $this->key_length; $adjust++ ) { + if ( "\x00" === $this->small_words[ $at + $adjust ] ) { + $matched_token_byte_length = $adjust; + return $this->small_mappings[ $at / ( $this->key_length + 1 ) ]; + } + + if ( + $search_text[ $adjust ] !== $this->small_words[ $at + $adjust ] && + ( ! $ignore_case || strtoupper( $this->small_words[ $at + $adjust ] !== $search_text[ $adjust ] ) ) + ) { + $at += $this->key_length + 1; + continue 2; + } + } + + $matched_token_byte_length = $adjust; + return $this->small_mappings[ $at / ( $this->key_length + 1 ) ]; + } + + return null; + } + + /** + * Exports the token map into an associate array of key/value pairs. + * + * Example: + * + * $smilies->to_array() === array( + * '8O' => '😯', + * ':(' => '🙁', + * ':)' => '🙂', + * ':?' => '😕', + * ); + * + * @return array The lookup key/substitution values as an associate array. + */ + public function to_array(): array { + $tokens = array(); + + $at = 0; + $small_mapping = 0; + $small_length = strlen( $this->small_words ); + while ( $at < $small_length ) { + $key = rtrim( substr( $this->small_words, $at, $this->key_length + 1 ), "\x00" ); + $value = $this->small_mappings[ $small_mapping++ ]; + $tokens[ $key ] = $value; + + $at += $this->key_length + 1; + } + + foreach ( $this->large_words as $index => $group ) { + $prefix = substr( $this->groups, $index * ( $this->key_length + 1 ), 2 ); + $group_length = strlen( $group ); + $at = 0; + while ( $at < $group_length ) { + $length = unpack( 'C', $group[ $at++ ] )[1]; + $key = $prefix . substr( $group, $at, $length ); + + $at += $length; + $length = unpack( 'C', $group[ $at++ ] )[1]; + $value = substr( $group, $at, $length ); + + $tokens[ $key ] = $value; + $at += $length; + } + } + + return $tokens; + } + + /** + * Export the token map for quick loading in PHP source code. + * + * This function has a specific purpose, to make loading of static token maps fast. + * It's used to ensure that the HTML character reference lookups add a minimal cost + * to initializing the PHP process. + * + * Example: + * + * echo $smilies->precomputed_php_source_table(); + * + * // Output. + * WP_Token_Map::from_precomputed_table( + * array( + * "storage_version" => "6.6.0", + * "key_length" => 2, + * "groups" => "", + * "long_words" => array(), + * "small_words" => "8O\x00:)\x00:(\x00:?\x00", + * "small_mappings" => array( "😯", "🙂", "🙁", "😕" ) + * ) + * ); + * + * @since 6.6.0 + * + * @param string $indent Optional. Use this string for indentation, or rely on the default horizontal tab character. Default "\t". + * @return string Value which can be pasted into a PHP source file for quick loading of table. + */ + public function precomputed_php_source_table( string $indent = "\t" ): string { + $i1 = $indent; + $i2 = $i1 . $indent; + $i3 = $i2 . $indent; + + $class_version = self::STORAGE_VERSION; + + $output = self::class . "::from_precomputed_table(\n"; + $output .= "{$i1}array(\n"; + $output .= "{$i2}\"storage_version\" => \"{$class_version}\",\n"; + $output .= "{$i2}\"key_length\" => {$this->key_length},\n"; + + $group_line = str_replace( "\x00", "\\x00", $this->groups ); + $output .= "{$i2}\"groups\" => \"{$group_line}\",\n"; + + $output .= "{$i2}\"large_words\" => array(\n"; + + $prefixes = explode( "\x00", $this->groups ); + foreach ( $prefixes as $index => $prefix ) { + if ( '' === $prefix ) { + break; + } + $group = $this->large_words[ $index ]; + $group_length = strlen( $group ); + $comment_line = "{$i3}//"; + $data_line = "{$i3}\""; + $at = 0; + while ( $at < $group_length ) { + $token_length = unpack( 'C', $group[ $at++ ] )[1]; + $token = substr( $group, $at, $token_length ); + $at += $token_length; + $mapping_length = unpack( 'C', $group[ $at++ ] )[1]; + $mapping = substr( $group, $at, $mapping_length ); + $at += $mapping_length; + + $token_digits = str_pad( dechex( $token_length ), 2, '0', STR_PAD_LEFT ); + $mapping_digits = str_pad( dechex( $mapping_length ), 2, '0', STR_PAD_LEFT ); + + $mapping = preg_replace_callback( + "~[\\x00-\\x1f\\x22\\x5c]~", + static function ( $match_result ) { + switch ( $match_result[0] ) { + case '"': + return '\\"'; + + case '\\': + return '\\\\'; + + default: + $hex = dechex( ord( $match_result[0] ) ); + return "\\x{$hex}"; + } + }, + $mapping + ); + + $comment_line .= " {$prefix}{$token}[{$mapping}]"; + $data_line .= "\\x{$token_digits}{$token}\\x{$mapping_digits}{$mapping}"; + } + $comment_line .= ".\n"; + $data_line .= "\",\n"; + + $output .= $comment_line; + $output .= $data_line; + } + + $output .= "{$i2}),\n"; + + $small_words = array(); + $small_length = strlen( $this->small_words ); + $at = 0; + while ( $at < $small_length ) { + $small_words[] = substr( $this->small_words, $at, $this->key_length + 1 ); + $at += $this->key_length + 1; + } + + $small_text = str_replace( "\x00", '\x00', implode( '', $small_words ) ); + $output .= "{$i2}\"small_words\" => \"{$small_text}\",\n"; + + $output .= "{$i2}\"small_mappings\" => array(\n"; + foreach ( $this->small_mappings as $mapping ) { + $output .= "{$i3}\"{$mapping}\",\n"; + } + $output .= "{$i2})\n"; + $output .= "{$i1})\n"; + $output .= ')'; + + return $output; + } + + /** + * Compares two strings, returning the longest, or whichever + * is first alphabetically if they are the same length. + * + * This is an important sort when building the token map because + * it should not form a match on a substring of a longer potential + * match. For example, it should not detect `Cap` when matching + * against the string `CapitalDifferentialD`. + * + * @since 6.6.0 + * + * @param string $a First string to compare. + * @param string $b Second string to compare. + * @return int -1 or lower if `$a` is less than `$b`; 1 or greater if `$a` is greater than `$b`, and 0 if they are equal. + */ + private static function longest_first_then_alphabetical( string $a, string $b ): int { + if ( $a === $b ) { + return 0; + } + + $length_a = strlen( $a ); + $length_b = strlen( $b ); + + // Longer strings are less-than for comparison's sake. + if ( $length_a !== $length_b ) { + return $length_b - $length_a; + } + + return strcmp( $a, $b ); + } +} diff --git a/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-active-formatting-elements-6-7.php b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-active-formatting-elements-6-7.php new file mode 100644 index 00000000000000..10f53fe82ce4e0 --- /dev/null +++ b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-active-formatting-elements-6-7.php @@ -0,0 +1,187 @@ +<?php +/** + * HTML API: WP_HTML_Active_Formatting_Elements class + * + * @package WordPress + * @subpackage HTML-API + * @since 6.4.0 + */ + +/** + * Core class used by the HTML processor during HTML parsing + * for managing the stack of active formatting elements. + * + * This class is designed for internal use by the HTML processor. + * + * > Initially, the list of active formatting elements is empty. + * > It is used to handle mis-nested formatting element tags. + * > + * > The list contains elements in the formatting category, and markers. + * > The markers are inserted when entering applet, object, marquee, + * > template, td, th, and caption elements, and are used to prevent + * > formatting from "leaking" into applet, object, marquee, template, + * > td, th, and caption elements. + * > + * > In addition, each element in the list of active formatting elements + * > is associated with the token for which it was created, so that + * > further elements can be created for that token if necessary. + * + * @since 6.4.0 + * + * @access private + * + * @see https://html.spec.whatwg.org/#list-of-active-formatting-elements + * @see WP_HTML_Processor + */ +class Gutenberg_HTML_Active_Formatting_Elements_6_7 { + /** + * Holds the stack of active formatting element references. + * + * @since 6.4.0 + * + * @var WP_HTML_Token[] + */ + private $stack = array(); + + /** + * Reports if a specific node is in the stack of active formatting elements. + * + * @since 6.4.0 + * + * @param WP_HTML_Token $token Look for this node in the stack. + * @return bool Whether the referenced node is in the stack of active formatting elements. + */ + public function contains_node( Gutenberg_HTML_Token_6_7 $token ) { + foreach ( $this->walk_up() as $item ) { + if ( $token->bookmark_name === $item->bookmark_name ) { + return true; + } + } + + return false; + } + + /** + * Returns how many nodes are currently in the stack of active formatting elements. + * + * @since 6.4.0 + * + * @return int How many node are in the stack of active formatting elements. + */ + public function count() { + return count( $this->stack ); + } + + /** + * Returns the node at the end of the stack of active formatting elements, + * if one exists. If the stack is empty, returns null. + * + * @since 6.4.0 + * + * @return WP_HTML_Token|null Last node in the stack of active formatting elements, if one exists, otherwise null. + */ + public function current_node() { + $current_node = end( $this->stack ); + + return $current_node ? $current_node : null; + } + + /** + * Pushes a node onto the stack of active formatting elements. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#push-onto-the-list-of-active-formatting-elements + * + * @param WP_HTML_Token $token Push this node onto the stack. + */ + public function push( Gutenberg_HTML_Token_6_7 $token ) { + /* + * > If there are already three elements in the list of active formatting elements after the last marker, + * > if any, or anywhere in the list if there are no markers, that have the same tag name, namespace, and + * > attributes as element, then remove the earliest such element from the list of active formatting + * > elements. For these purposes, the attributes must be compared as they were when the elements were + * > created by the parser; two elements have the same attributes if all their parsed attributes can be + * > paired such that the two attributes in each pair have identical names, namespaces, and values + * > (the order of the attributes does not matter). + * + * @todo Implement the "Noah's Ark clause" to only add up to three of any given kind of formatting elements to the stack. + */ + // > Add element to the list of active formatting elements. + $this->stack[] = $token; + } + + /** + * Removes a node from the stack of active formatting elements. + * + * @since 6.4.0 + * + * @param WP_HTML_Token $token Remove this node from the stack, if it's there already. + * @return bool Whether the node was found and removed from the stack of active formatting elements. + */ + public function remove_node( Gutenberg_HTML_Token_6_7 $token ) { + foreach ( $this->walk_up() as $position_from_end => $item ) { + if ( $token->bookmark_name !== $item->bookmark_name ) { + continue; + } + + $position_from_start = $this->count() - $position_from_end - 1; + array_splice( $this->stack, $position_from_start, 1 ); + return true; + } + + return false; + } + + /** + * Steps through the stack of active formatting elements, starting with the + * top element (added first) and walking downwards to the one added last. + * + * This generator function is designed to be used inside a "foreach" loop. + * + * Example: + * + * $html = '<em><strong><a>We are here'; + * foreach ( $stack->walk_down() as $node ) { + * echo "{$node->node_name} -> "; + * } + * > EM -> STRONG -> A -> + * + * To start with the most-recently added element and walk towards the top, + * see WP_HTML_Active_Formatting_Elements::walk_up(). + * + * @since 6.4.0 + */ + public function walk_down() { + $count = count( $this->stack ); + + for ( $i = 0; $i < $count; $i++ ) { + yield $this->stack[ $i ]; + } + } + + /** + * Steps through the stack of active formatting elements, starting with the + * bottom element (added last) and walking upwards to the one added first. + * + * This generator function is designed to be used inside a "foreach" loop. + * + * Example: + * + * $html = '<em><strong><a>We are here'; + * foreach ( $stack->walk_up() as $node ) { + * echo "{$node->node_name} -> "; + * } + * > A -> STRONG -> EM -> + * + * To start with the first added element and walk towards the bottom, + * see WP_HTML_Active_Formatting_Elements::walk_down(). + * + * @since 6.4.0 + */ + public function walk_up() { + for ( $i = count( $this->stack ) - 1; $i >= 0; $i-- ) { + yield $this->stack[ $i ]; + } + } +} diff --git a/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-attribute-token-6-7.php b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-attribute-token-6-7.php new file mode 100644 index 00000000000000..4ee369b795c84c --- /dev/null +++ b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-attribute-token-6-7.php @@ -0,0 +1,116 @@ +<?php +/** + * HTML API: WP_HTML_Attribute_Token class + * + * @package WordPress + * @subpackage HTML-API + * @since 6.2.0 + */ + +/** + * Core class used by the HTML tag processor as a data structure for the attribute token, + * allowing to drastically improve performance. + * + * This class is for internal usage of the WP_HTML_Tag_Processor class. + * + * @access private + * @since 6.2.0 + * @since 6.5.0 Replaced `end` with `length` to more closely match `substr()`. + * + * @see WP_HTML_Tag_Processor + */ +class Gutenberg_HTML_Attribute_Token_6_7 { + /** + * Attribute name. + * + * @since 6.2.0 + * + * @var string + */ + public $name; + + /** + * Attribute value. + * + * @since 6.2.0 + * + * @var int + */ + public $value_starts_at; + + /** + * How many bytes the value occupies in the input HTML. + * + * @since 6.2.0 + * + * @var int + */ + public $value_length; + + /** + * The string offset where the attribute name starts. + * + * @since 6.2.0 + * + * @var int + */ + public $start; + + /** + * Byte length of text spanning the attribute inside a tag. + * + * This span starts at the first character of the attribute name + * and it ends after one of three cases: + * + * - at the end of the attribute name for boolean attributes. + * - at the end of the value for unquoted attributes. + * - at the final single or double quote for quoted attributes. + * + * Example: + * + * <div class="post"> + * ------------ length is 12, including quotes + * + * <input type="checked" checked id="selector"> + * ------- length is 6 + * + * <a rel=noopener> + * ------------ length is 11 + * + * @since 6.5.0 Replaced `end` with `length` to more closely match `substr()`. + * + * @var int + */ + public $length; + + /** + * Whether the attribute is a boolean attribute with value `true`. + * + * @since 6.2.0 + * + * @var bool + */ + public $is_true; + + /** + * Constructor. + * + * @since 6.2.0 + * @since 6.5.0 Replaced `end` with `length` to more closely match `substr()`. + * + * @param string $name Attribute name. + * @param int $value_start Attribute value. + * @param int $value_length Number of bytes attribute value spans. + * @param int $start The string offset where the attribute name starts. + * @param int $length Byte length of the entire attribute name or name and value pair expression. + * @param bool $is_true Whether the attribute is a boolean attribute with true value. + */ + public function __construct( $name, $value_start, $value_length, $start, $length, $is_true ) { + $this->name = $name; + $this->value_starts_at = $value_start; + $this->value_length = $value_length; + $this->start = $start; + $this->length = $length; + $this->is_true = $is_true; + } +} diff --git a/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-decoder-6-7.php b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-decoder-6-7.php new file mode 100644 index 00000000000000..70f51151d86478 --- /dev/null +++ b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-decoder-6-7.php @@ -0,0 +1,461 @@ +<?php + +/** + * HTML API: WP_HTML_Decoder class + * + * Decodes spans of raw text found inside HTML content. + * + * @package WordPress + * @subpackage HTML-API + * @since 6.6.0 + */ +class Gutenberg_HTML_Decoder_6_7 { + /** + * Indicates if an attribute value starts with a given raw string value. + * + * Use this method to determine if an attribute value starts with a given string, regardless + * of how it might be encoded in HTML. For instance, `http:` could be represented as `http:` + * or as `http:` or as `http:` or as `http:`, or in many other ways. + * + * Example: + * + * $value = 'http://wordpress.org/'; + * true === WP_HTML_Decoder::attribute_starts_with( $value, 'http:', 'ascii-case-insensitive' ); + * false === WP_HTML_Decoder::attribute_starts_with( $value, 'https:', 'ascii-case-insensitive' ); + * + * @since 6.6.0 + * + * @param string $haystack String containing the raw non-decoded attribute value. + * @param string $search_text Does the attribute value start with this plain string. + * @param string $case_sensitivity Optional. Pass 'ascii-case-insensitive' to ignore ASCII case when matching. + * Default 'case-sensitive'. + * @return bool Whether the attribute value starts with the given string. + */ + public static function attribute_starts_with( $haystack, $search_text, $case_sensitivity = 'case-sensitive' ): bool { + $search_length = strlen( $search_text ); + $loose_case = 'ascii-case-insensitive' === $case_sensitivity; + $haystack_end = strlen( $haystack ); + $search_at = 0; + $haystack_at = 0; + + while ( $search_at < $search_length && $haystack_at < $haystack_end ) { + $chars_match = $loose_case + ? strtolower( $haystack[ $haystack_at ] ) === strtolower( $search_text[ $search_at ] ) + : $haystack[ $haystack_at ] === $search_text[ $search_at ]; + + $is_introducer = '&' === $haystack[ $haystack_at ]; + $next_chunk = $is_introducer + ? self::read_character_reference( 'attribute', $haystack, $haystack_at, $token_length ) + : null; + + // If there's no character reference and the characters don't match, the match fails. + if ( null === $next_chunk && ! $chars_match ) { + return false; + } + + // If there's no character reference but the character do match, then it could still match. + if ( null === $next_chunk && $chars_match ) { + ++$haystack_at; + ++$search_at; + continue; + } + + // If there is a character reference, then the decoded value must exactly match what follows in the search string. + if ( 0 !== substr_compare( $search_text, $next_chunk, $search_at, strlen( $next_chunk ), $loose_case ) ) { + return false; + } + + // The character reference matched, so continue checking. + $haystack_at += $token_length; + $search_at += strlen( $next_chunk ); + } + + return true; + } + + /** + * Returns a string containing the decoded value of a given HTML text node. + * + * Text nodes appear in HTML DATA sections, which are the text segments inside + * and around tags, excepting SCRIPT and STYLE elements (and some others), + * whose inner text is not decoded. Use this function to read the decoded + * value of such a text span in an HTML document. + * + * Example: + * + * '“😄”' === WP_HTML_Decode::decode_text_node( '“😄”' ); + * + * @since 6.6.0 + * + * @param string $text Text containing raw and non-decoded text node to decode. + * @return string Decoded UTF-8 value of given text node. + */ + public static function decode_text_node( $text ): string { + return static::decode( 'data', $text ); + } + + /** + * Returns a string containing the decoded value of a given HTML attribute. + * + * Text found inside an HTML attribute has different parsing rules than for + * text found inside other markup, or DATA segments. Use this function to + * read the decoded value of an HTML string inside a quoted attribute. + * + * Example: + * + * '“😄”' === WP_HTML_Decode::decode_attribute( '“😄”' ); + * + * @since 6.6.0 + * + * @param string $text Text containing raw and non-decoded attribute value to decode. + * @return string Decoded UTF-8 value of given attribute value. + */ + public static function decode_attribute( $text ): string { + return static::decode( 'attribute', $text ); + } + + /** + * Decodes a span of HTML text, depending on the context in which it's found. + * + * This is a low-level method; prefer calling WP_HTML_Decoder::decode_attribute() or + * WP_HTML_Decoder::decode_text_node() instead. It's provided for cases where this + * may be difficult to do from calling code. + * + * Example: + * + * '©' = WP_HTML_Decoder::decode( 'data', '©' ); + * + * @since 6.6.0 + * + * @access private + * + * @param string $context `attribute` for decoding attribute values, `data` otherwise. + * @param string $text Text document containing span of text to decode. + * @return string Decoded UTF-8 string. + */ + public static function decode( $context, $text ): string { + $decoded = ''; + $end = strlen( $text ); + $at = 0; + $was_at = 0; + + while ( $at < $end ) { + $next_character_reference_at = strpos( $text, '&', $at ); + if ( false === $next_character_reference_at ) { + break; + } + + $character_reference = self::read_character_reference( $context, $text, $next_character_reference_at, $token_length ); + if ( isset( $character_reference ) ) { + $at = $next_character_reference_at; + $decoded .= substr( $text, $was_at, $at - $was_at ); + $decoded .= $character_reference; + $at += $token_length; + $was_at = $at; + continue; + } + + ++$at; + } + + if ( 0 === $was_at ) { + return $text; + } + + if ( $was_at < $end ) { + $decoded .= substr( $text, $was_at, $end - $was_at ); + } + + return $decoded; + } + + /** + * Attempt to read a character reference at the given location in a given string, + * depending on the context in which it's found. + * + * If a character reference is found, this function will return the translated value + * that the reference maps to. It will then set `$match_byte_length` the + * number of bytes of input it read while consuming the character reference. This + * gives calling code the opportunity to advance its cursor when traversing a string + * and decoding. + * + * Example: + * + * null === WP_HTML_Decoder::read_character_reference( 'attribute', 'Ships…', 0 ); + * '…' === WP_HTML_Decoder::read_character_reference( 'attribute', 'Ships…', 5, $token_length ); + * 8 === $token_length; // `…` + * + * null === WP_HTML_Decoder::read_character_reference( 'attribute', '¬in', 0 ); + * '∉' === WP_HTML_Decoder::read_character_reference( 'attribute', '∉', 0, $token_length ); + * 7 === $token_length; // `∉` + * + * '¬' === WP_HTML_Decoder::read_character_reference( 'data', '¬in', 0, $token_length ); + * 4 === $token_length; // `¬` + * '∉' === WP_HTML_Decoder::read_character_reference( 'data', '∉', 0, $token_length ); + * 7 === $token_length; // `∉` + * + * @since 6.6.0 + * + * @param string $context `attribute` for decoding attribute values, `data` otherwise. + * @param string $text Text document containing span of text to decode. + * @param int $at Optional. Byte offset into text where span begins, defaults to the beginning (0). + * @param int &$match_byte_length Optional. Set to byte-length of character reference if provided and if a match + * is found, otherwise not set. Default null. + * @return string|false Decoded character reference in UTF-8 if found, otherwise `false`. + */ + public static function read_character_reference( $context, $text, $at = 0, &$match_byte_length = null ) { + /** + * Mappings for HTML5 named character references. + * + * @var WP_Token_Map $html5_named_character_references + */ + global $html5_named_character_references; + + $length = strlen( $text ); + if ( $at + 1 >= $length ) { + return null; + } + + if ( '&' !== $text[ $at ] ) { + return null; + } + + /* + * Numeric character references. + * + * When truncated, these will encode the code point found by parsing the + * digits that are available. For example, when `🅰` is truncated + * to `DZ` it will encode `DZ`. It does not: + * - know how to parse the original `🅰`. + * - fail to parse and return plaintext `DZ`. + * - fail to parse and return the replacement character `�` + */ + if ( '#' === $text[ $at + 1 ] ) { + if ( $at + 2 >= $length ) { + return null; + } + + /** Tracks inner parsing within the numeric character reference. */ + $digits_at = $at + 2; + + if ( 'x' === $text[ $digits_at ] || 'X' === $text[ $digits_at ] ) { + $numeric_base = 16; + $numeric_digits = '0123456789abcdefABCDEF'; + $max_digits = 6; // 􏿿 + ++$digits_at; + } else { + $numeric_base = 10; + $numeric_digits = '0123456789'; + $max_digits = 7; // 􏿿 + } + + // Cannot encode invalid Unicode code points. Max is to U+10FFFF. + $zero_count = strspn( $text, '0', $digits_at ); + $digit_count = strspn( $text, $numeric_digits, $digits_at + $zero_count ); + $after_digits = $digits_at + $zero_count + $digit_count; + $has_semicolon = $after_digits < $length && ';' === $text[ $after_digits ]; + $end_of_span = $has_semicolon ? $after_digits + 1 : $after_digits; + + // `&#` or `&#x` without digits returns into plaintext. + if ( 0 === $digit_count && 0 === $zero_count ) { + return null; + } + + // Whereas `&#` and only zeros is invalid. + if ( 0 === $digit_count ) { + $match_byte_length = $end_of_span - $at; + return '�'; + } + + // If there are too many digits then it's not worth parsing. It's invalid. + if ( $digit_count > $max_digits ) { + $match_byte_length = $end_of_span - $at; + return '�'; + } + + $digits = substr( $text, $digits_at + $zero_count, $digit_count ); + $code_point = intval( $digits, $numeric_base ); + + /* + * Noncharacters, 0x0D, and non-ASCII-whitespace control characters. + * + * > A noncharacter is a code point that is in the range U+FDD0 to U+FDEF, + * > inclusive, or U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, U+2FFFE, U+2FFFF, + * > U+3FFFE, U+3FFFF, U+4FFFE, U+4FFFF, U+5FFFE, U+5FFFF, U+6FFFE, + * > U+6FFFF, U+7FFFE, U+7FFFF, U+8FFFE, U+8FFFF, U+9FFFE, U+9FFFF, + * > U+AFFFE, U+AFFFF, U+BFFFE, U+BFFFF, U+CFFFE, U+CFFFF, U+DFFFE, + * > U+DFFFF, U+EFFFE, U+EFFFF, U+FFFFE, U+FFFFF, U+10FFFE, or U+10FFFF. + * + * A C0 control is a code point that is in the range of U+00 to U+1F, + * but ASCII whitespace includes U+09, U+0A, U+0C, and U+0D. + * + * These characters are invalid but still decode as any valid character. + * This comment is here to note and explain why there's no check to + * remove these characters or replace them. + * + * @see https://infra.spec.whatwg.org/#noncharacter + */ + + /* + * Code points in the C1 controls area need to be remapped as if they + * were stored in Windows-1252. Note! This transformation only happens + * for numeric character references. The raw code points in the byte + * stream are not translated. + * + * > If the number is one of the numbers in the first column of + * > the following table, then find the row with that number in + * > the first column, and set the character reference code to + * > the number in the second column of that row. + */ + if ( $code_point >= 0x80 && $code_point <= 0x9F ) { + $windows_1252_mapping = array( + 0x20AC, // 0x80 -> EURO SIGN (€). + 0x81, // 0x81 -> (no change). + 0x201A, // 0x82 -> SINGLE LOW-9 QUOTATION MARK (‚). + 0x0192, // 0x83 -> LATIN SMALL LETTER F WITH HOOK (ƒ). + 0x201E, // 0x84 -> DOUBLE LOW-9 QUOTATION MARK („). + 0x2026, // 0x85 -> HORIZONTAL ELLIPSIS (…). + 0x2020, // 0x86 -> DAGGER (†). + 0x2021, // 0x87 -> DOUBLE DAGGER (‡). + 0x02C6, // 0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT (ˆ). + 0x2030, // 0x89 -> PER MILLE SIGN (‰). + 0x0160, // 0x8A -> LATIN CAPITAL LETTER S WITH CARON (Š). + 0x2039, // 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK (‹). + 0x0152, // 0x8C -> LATIN CAPITAL LIGATURE OE (Œ). + 0x8D, // 0x8D -> (no change). + 0x017D, // 0x8E -> LATIN CAPITAL LETTER Z WITH CARON (Ž). + 0x8F, // 0x8F -> (no change). + 0x90, // 0x90 -> (no change). + 0x2018, // 0x91 -> LEFT SINGLE QUOTATION MARK (‘). + 0x2019, // 0x92 -> RIGHT SINGLE QUOTATION MARK (’). + 0x201C, // 0x93 -> LEFT DOUBLE QUOTATION MARK (“). + 0x201D, // 0x94 -> RIGHT DOUBLE QUOTATION MARK (”). + 0x2022, // 0x95 -> BULLET (•). + 0x2013, // 0x96 -> EN DASH (–). + 0x2014, // 0x97 -> EM DASH (—). + 0x02DC, // 0x98 -> SMALL TILDE (˜). + 0x2122, // 0x99 -> TRADE MARK SIGN (™). + 0x0161, // 0x9A -> LATIN SMALL LETTER S WITH CARON (š). + 0x203A, // 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (›). + 0x0153, // 0x9C -> LATIN SMALL LIGATURE OE (œ). + 0x9D, // 0x9D -> (no change). + 0x017E, // 0x9E -> LATIN SMALL LETTER Z WITH CARON (ž). + 0x0178, // 0x9F -> LATIN CAPITAL LETTER Y WITH DIAERESIS (Ÿ). + ); + + $code_point = $windows_1252_mapping[ $code_point - 0x80 ]; + } + + $match_byte_length = $end_of_span - $at; + return self::code_point_to_utf8_bytes( $code_point ); + } + + /** Tracks inner parsing within the named character reference. */ + $name_at = $at + 1; + // Minimum named character reference is two characters. E.g. `GT`. + if ( $name_at + 2 > $length ) { + return null; + } + + $name_length = 0; + $replacement = $html5_named_character_references->read_token( $text, $name_at, $name_length ); + if ( false === $replacement ) { + return null; + } + + $after_name = $name_at + $name_length; + + // If the match ended with a semicolon then it should always be decoded. + if ( ';' === $text[ $name_at + $name_length - 1 ] ) { + $match_byte_length = $after_name - $at; + return $replacement; + } + + /* + * At this point though there's a match for an entry in the named + * character reference table but the match doesn't end in `;`. + * It may be allowed if it's followed by something unambiguous. + */ + $ambiguous_follower = ( + $after_name < $length && + $name_at < $length && + ( + ctype_alnum( $text[ $after_name ] ) || + '=' === $text[ $after_name ] + ) + ); + + // It's non-ambiguous, safe to leave it in. + if ( ! $ambiguous_follower ) { + $match_byte_length = $after_name - $at; + return $replacement; + } + + // It's ambiguous, which isn't allowed inside attributes. + if ( 'attribute' === $context ) { + return null; + } + + $match_byte_length = $after_name - $at; + return $replacement; + } + + /** + * Encode a code point number into the UTF-8 encoding. + * + * This encoder implements the UTF-8 encoding algorithm for converting + * a code point into a byte sequence. If it receives an invalid code + * point it will return the Unicode Replacement Character U+FFFD `�`. + * + * Example: + * + * '🅰' === WP_HTML_Decoder::code_point_to_utf8_bytes( 0x1f170 ); + * + * // Half of a surrogate pair is an invalid code point. + * '�' === WP_HTML_Decoder::code_point_to_utf8_bytes( 0xd83c ); + * + * @since 6.6.0 + * + * @see https://www.rfc-editor.org/rfc/rfc3629 For the UTF-8 standard. + * + * @param int $code_point Which code point to convert. + * @return string Converted code point, or `�` if invalid. + */ + public static function code_point_to_utf8_bytes( $code_point ): string { + // Pre-check to ensure a valid code point. + if ( + $code_point <= 0 || + ( $code_point >= 0xD800 && $code_point <= 0xDFFF ) || + $code_point > 0x10FFFF + ) { + return '�'; + } + + if ( $code_point <= 0x7F ) { + return chr( $code_point ); + } + + if ( $code_point <= 0x7FF ) { + $byte1 = chr( ( $code_point >> 6 ) | 0xC0 ); + $byte2 = chr( $code_point & 0x3F | 0x80 ); + + return "{$byte1}{$byte2}"; + } + + if ( $code_point <= 0xFFFF ) { + $byte1 = chr( ( $code_point >> 12 ) | 0xE0 ); + $byte2 = chr( ( $code_point >> 6 ) & 0x3F | 0x80 ); + $byte3 = chr( $code_point & 0x3F | 0x80 ); + + return "{$byte1}{$byte2}{$byte3}"; + } + + // Any values above U+10FFFF are eliminated above in the pre-check. + $byte1 = chr( ( $code_point >> 18 ) | 0xF0 ); + $byte2 = chr( ( $code_point >> 12 ) & 0x3F | 0x80 ); + $byte3 = chr( ( $code_point >> 6 ) & 0x3F | 0x80 ); + $byte4 = chr( $code_point & 0x3F | 0x80 ); + + return "{$byte1}{$byte2}{$byte3}{$byte4}"; + } +} diff --git a/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-open-elements-6-7.php b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-open-elements-6-7.php new file mode 100644 index 00000000000000..fd2b252432455e --- /dev/null +++ b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-open-elements-6-7.php @@ -0,0 +1,598 @@ +<?php +/** + * HTML API: WP_HTML_Open_Elements class + * + * @package WordPress + * @subpackage HTML-API + * @since 6.4.0 + */ + +/** + * Core class used by the HTML processor during HTML parsing + * for managing the stack of open elements. + * + * This class is designed for internal use by the HTML processor. + * + * > Initially, the stack of open elements is empty. The stack grows + * > downwards; the topmost node on the stack is the first one added + * > to the stack, and the bottommost node of the stack is the most + * > recently added node in the stack (notwithstanding when the stack + * > is manipulated in a random access fashion as part of the handling + * > for misnested tags). + * + * @since 6.4.0 + * + * @access private + * + * @see https://html.spec.whatwg.org/#stack-of-open-elements + * @see WP_HTML_Processor + */ +class Gutenberg_HTML_Open_Elements_6_7 { + /** + * Holds the stack of open element references. + * + * @since 6.4.0 + * + * @var WP_HTML_Token[] + */ + public $stack = array(); + + /** + * Whether a P element is in button scope currently. + * + * This class optimizes scope lookup by pre-calculating + * this value when elements are added and removed to the + * stack of open elements which might change its value. + * This avoids frequent iteration over the stack. + * + * @since 6.4.0 + * + * @var bool + */ + private $has_p_in_button_scope = false; + + /** + * A function that will be called when an item is popped off the stack of open elements. + * + * The function will be called with the popped item as its argument. + * + * @since 6.6.0 + * + * @var Closure|null + */ + private $pop_handler = null; + + /** + * A function that will be called when an item is pushed onto the stack of open elements. + * + * The function will be called with the pushed item as its argument. + * + * @since 6.6.0 + * + * @var Closure|null + */ + private $push_handler = null; + + /** + * Sets a pop handler that will be called when an item is popped off the stack of + * open elements. + * + * The function will be called with the pushed item as its argument. + * + * @since 6.6.0 + * + * @param Closure $handler The handler function. + */ + public function set_pop_handler( Closure $handler ): void { + $this->pop_handler = $handler; + } + + /** + * Sets a push handler that will be called when an item is pushed onto the stack of + * open elements. + * + * The function will be called with the pushed item as its argument. + * + * @since 6.6.0 + * + * @param Closure $handler The handler function. + */ + public function set_push_handler( Closure $handler ): void { + $this->push_handler = $handler; + } + + /** + * Reports if a specific node is in the stack of open elements. + * + * @since 6.4.0 + * + * @param WP_HTML_Token $token Look for this node in the stack. + * @return bool Whether the referenced node is in the stack of open elements. + */ + public function contains_node( Gutenberg_HTML_Token_6_7 $token ): bool { + foreach ( $this->walk_up() as $item ) { + if ( $token->bookmark_name === $item->bookmark_name ) { + return true; + } + } + + return false; + } + + /** + * Returns how many nodes are currently in the stack of open elements. + * + * @since 6.4.0 + * + * @return int How many node are in the stack of open elements. + */ + public function count(): int { + return count( $this->stack ); + } + + /** + * Returns the node at the end of the stack of open elements, + * if one exists. If the stack is empty, returns null. + * + * @since 6.4.0 + * + * @return WP_HTML_Token|null Last node in the stack of open elements, if one exists, otherwise null. + */ + public function current_node(): ?Gutenberg_HTML_Token_6_7 { + $current_node = end( $this->stack ); + + return $current_node ? $current_node : null; + } + + /** + * Indicates if the current node is of a given type or name. + * + * It's possible to pass either a node type or a node name to this function. + * In the case there is no current element it will always return `false`. + * + * Example: + * + * // Is the current node a text node? + * $stack->current_node_is( '#text' ); + * + * // Is the current node a DIV element? + * $stack->current_node_is( 'DIV' ); + * + * // Is the current node any element/tag? + * $stack->current_node_is( '#tag' ); + * + * @see WP_HTML_Tag_Processor::get_token_type + * @see WP_HTML_Tag_Processor::get_token_name + * + * @since 6.7.0 + * + * @access private + * + * @param string $identity Check if the current node has this name or type (depending on what is provided). + * @return bool Whether there is a current element that matches the given identity, whether a token name or type. + */ + public function current_node_is( string $identity ): bool { + $current_node = end( $this->stack ); + if ( false === $current_node ) { + return false; + } + + $current_node_name = $current_node->node_name; + + return ( + $current_node_name === $identity || + ( '#doctype' === $identity && 'html' === $current_node_name ) || + ( '#tag' === $identity && ctype_upper( $current_node_name ) ) + ); + } + + /** + * Returns whether an element is in a specific scope. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#has-an-element-in-the-specific-scope + * + * @param string $tag_name Name of tag check. + * @param string[] $termination_list List of elements that terminate the search. + * @return bool Whether the element was found in a specific scope. + */ + public function has_element_in_specific_scope( string $tag_name, $termination_list ): bool { + foreach ( $this->walk_up() as $node ) { + if ( $node->node_name === $tag_name ) { + return true; + } + + if ( + '(internal: H1 through H6 - do not use)' === $tag_name && + in_array( $node->node_name, array( 'H1', 'H2', 'H3', 'H4', 'H5', 'H6' ), true ) + ) { + return true; + } + + switch ( $node->node_name ) { + case 'HTML': + return false; + } + + if ( in_array( $node->node_name, $termination_list, true ) ) { + return false; + } + } + + return false; + } + + /** + * Returns whether a particular element is in scope. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#has-an-element-in-scope + * + * @param string $tag_name Name of tag to check. + * @return bool Whether given element is in scope. + */ + public function has_element_in_scope( string $tag_name ): bool { + return $this->has_element_in_specific_scope( + $tag_name, + array( + + /* + * Because it's not currently possible to encounter + * one of the termination elements, they don't need + * to be listed here. If they were, they would be + * unreachable and only waste CPU cycles while + * scanning through HTML. + */ + ) + ); + } + + /** + * Returns whether a particular element is in list item scope. + * + * @since 6.4.0 + * @since 6.5.0 Implemented: no longer throws on every invocation. + * + * @see https://html.spec.whatwg.org/#has-an-element-in-list-item-scope + * + * @param string $tag_name Name of tag to check. + * @return bool Whether given element is in scope. + */ + public function has_element_in_list_item_scope( string $tag_name ): bool { + return $this->has_element_in_specific_scope( + $tag_name, + array( + // There are more elements that belong here which aren't currently supported. + 'OL', + 'UL', + ) + ); + } + + /** + * Returns whether a particular element is in button scope. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#has-an-element-in-button-scope + * + * @param string $tag_name Name of tag to check. + * @return bool Whether given element is in scope. + */ + public function has_element_in_button_scope( string $tag_name ): bool { + return $this->has_element_in_specific_scope( $tag_name, array( 'BUTTON' ) ); + } + + /** + * Returns whether a particular element is in table scope. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#has-an-element-in-table-scope + * + * @throws WP_HTML_Unsupported_Exception Always until this function is implemented. + * + * @param string $tag_name Name of tag to check. + * @return bool Whether given element is in scope. + */ + public function has_element_in_table_scope( string $tag_name ): bool { + throw new Gutenberg_HTML_Unsupported_Exception_6_7( 'Cannot process elements depending on table scope.' ); + + return false; // The linter requires this unreachable code until the function is implemented and can return. + } + + /** + * Returns whether a particular element is in select scope. + * + * This test differs from the others like it, in that its rules are inverted. + * Instead of arriving at a match when one of any tag in a termination group + * is reached, this one terminates if any other tag is reached. + * + * > The stack of open elements is said to have a particular element in select scope when it has + * > that element in the specific scope consisting of all element types except the following: + * > - optgroup in the HTML namespace + * > - option in the HTML namespace + * + * @since 6.4.0 Stub implementation (throws). + * @since 6.7.0 Full implementation. + * + * @see https://html.spec.whatwg.org/#has-an-element-in-select-scope + * + * @param string $tag_name Name of tag to check. + * @return bool Whether the given element is in SELECT scope. + */ + public function has_element_in_select_scope( string $tag_name ): bool { + foreach ( $this->walk_up() as $node ) { + if ( $node->node_name === $tag_name ) { + return true; + } + + if ( + 'OPTION' !== $node->node_name && + 'OPTGROUP' !== $node->node_name + ) { + return false; + } + } + + return false; + } + + /** + * Returns whether a P is in BUTTON scope. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#has-an-element-in-button-scope + * + * @return bool Whether a P is in BUTTON scope. + */ + public function has_p_in_button_scope(): bool { + return $this->has_p_in_button_scope; + } + + /** + * Pops a node off of the stack of open elements. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#stack-of-open-elements + * + * @return bool Whether a node was popped off of the stack. + */ + public function pop(): bool { + $item = array_pop( $this->stack ); + if ( null === $item ) { + return false; + } + + if ( 'context-node' === $item->bookmark_name ) { + $this->stack[] = $item; + return false; + } + + $this->after_element_pop( $item ); + return true; + } + + /** + * Pops nodes off of the stack of open elements until one with the given tag name has been popped. + * + * @since 6.4.0 + * + * @see WP_HTML_Open_Elements::pop + * + * @param string $tag_name Name of tag that needs to be popped off of the stack of open elements. + * @return bool Whether a tag of the given name was found and popped off of the stack of open elements. + */ + public function pop_until( string $tag_name ): bool { + foreach ( $this->walk_up() as $item ) { + if ( 'context-node' === $item->bookmark_name ) { + return true; + } + + $this->pop(); + + if ( + '(internal: H1 through H6 - do not use)' === $tag_name && + in_array( $item->node_name, array( 'H1', 'H2', 'H3', 'H4', 'H5', 'H6' ), true ) + ) { + return true; + } + + if ( $tag_name === $item->node_name ) { + return true; + } + } + + return false; + } + + /** + * Pushes a node onto the stack of open elements. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#stack-of-open-elements + * + * @param WP_HTML_Token $stack_item Item to add onto stack. + */ + public function push( Gutenberg_HTML_Token_6_7 $stack_item ): void { + $this->stack[] = $stack_item; + $this->after_element_push( $stack_item ); + } + + /** + * Removes a specific node from the stack of open elements. + * + * @since 6.4.0 + * + * @param WP_HTML_Token $token The node to remove from the stack of open elements. + * @return bool Whether the node was found and removed from the stack of open elements. + */ + public function remove_node( Gutenberg_HTML_Token_6_7 $token ): bool { + if ( 'context-node' === $token->bookmark_name ) { + return false; + } + + foreach ( $this->walk_up() as $position_from_end => $item ) { + if ( $token->bookmark_name !== $item->bookmark_name ) { + continue; + } + + $position_from_start = $this->count() - $position_from_end - 1; + array_splice( $this->stack, $position_from_start, 1 ); + $this->after_element_pop( $item ); + return true; + } + + return false; + } + + + /** + * Steps through the stack of open elements, starting with the top element + * (added first) and walking downwards to the one added last. + * + * This generator function is designed to be used inside a "foreach" loop. + * + * Example: + * + * $html = '<em><strong><a>We are here'; + * foreach ( $stack->walk_down() as $node ) { + * echo "{$node->node_name} -> "; + * } + * > EM -> STRONG -> A -> + * + * To start with the most-recently added element and walk towards the top, + * see WP_HTML_Open_Elements::walk_up(). + * + * @since 6.4.0 + */ + public function walk_down() { + $count = count( $this->stack ); + + for ( $i = 0; $i < $count; $i++ ) { + yield $this->stack[ $i ]; + } + } + + /** + * Steps through the stack of open elements, starting with the bottom element + * (added last) and walking upwards to the one added first. + * + * This generator function is designed to be used inside a "foreach" loop. + * + * Example: + * + * $html = '<em><strong><a>We are here'; + * foreach ( $stack->walk_up() as $node ) { + * echo "{$node->node_name} -> "; + * } + * > A -> STRONG -> EM -> + * + * To start with the first added element and walk towards the bottom, + * see WP_HTML_Open_Elements::walk_down(). + * + * @since 6.4.0 + * @since 6.5.0 Accepts $above_this_node to start traversal above a given node, if it exists. + * + * @param WP_HTML_Token|null $above_this_node Optional. Start traversing above this node, + * if provided and if the node exists. + */ + public function walk_up( ?Gutenberg_HTML_Token_6_7 $above_this_node = null ) { + $has_found_node = null === $above_this_node; + + for ( $i = count( $this->stack ) - 1; $i >= 0; $i-- ) { + $node = $this->stack[ $i ]; + + if ( ! $has_found_node ) { + $has_found_node = $node === $above_this_node; + continue; + } + + yield $node; + } + } + + /* + * Internal helpers. + */ + + /** + * Updates internal flags after adding an element. + * + * Certain conditions (such as "has_p_in_button_scope") are maintained here as + * flags that are only modified when adding and removing elements. This allows + * the HTML Processor to quickly check for these conditions instead of iterating + * over the open stack elements upon each new tag it encounters. These flags, + * however, need to be maintained as items are added and removed from the stack. + * + * @since 6.4.0 + * + * @param WP_HTML_Token $item Element that was added to the stack of open elements. + */ + public function after_element_push( Gutenberg_HTML_Token_6_7 $item ): void { + /* + * When adding support for new elements, expand this switch to trap + * cases where the precalculated value needs to change. + */ + switch ( $item->node_name ) { + case 'BUTTON': + $this->has_p_in_button_scope = false; + break; + + case 'P': + $this->has_p_in_button_scope = true; + break; + } + + if ( null !== $this->push_handler ) { + ( $this->push_handler )( $item ); + } + } + + /** + * Updates internal flags after removing an element. + * + * Certain conditions (such as "has_p_in_button_scope") are maintained here as + * flags that are only modified when adding and removing elements. This allows + * the HTML Processor to quickly check for these conditions instead of iterating + * over the open stack elements upon each new tag it encounters. These flags, + * however, need to be maintained as items are added and removed from the stack. + * + * @since 6.4.0 + * + * @param WP_HTML_Token $item Element that was removed from the stack of open elements. + */ + public function after_element_pop( Gutenberg_HTML_Token_6_7 $item ): void { + /* + * When adding support for new elements, expand this switch to trap + * cases where the precalculated value needs to change. + */ + switch ( $item->node_name ) { + case 'BUTTON': + $this->has_p_in_button_scope = $this->has_element_in_button_scope( 'P' ); + break; + + case 'P': + $this->has_p_in_button_scope = $this->has_element_in_button_scope( 'P' ); + break; + } + + if ( null !== $this->pop_handler ) { + ( $this->pop_handler )( $item ); + } + } + + /** + * Wakeup magic method. + * + * @since 6.6.0 + */ + public function __wakeup() { + throw new \LogicException( __CLASS__ . ' should never be unserialized' ); + } +} diff --git a/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-processor-6-7.php b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-processor-6-7.php new file mode 100644 index 00000000000000..15cbbdc6adda8c --- /dev/null +++ b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-processor-6-7.php @@ -0,0 +1,3402 @@ +<?php +/** + * HTML API: WP_HTML_Processor class + * + * @package WordPress + * @subpackage HTML-API + * @since 6.4.0 + */ + +/** + * Core class used to safely parse and modify an HTML document. + * + * The HTML Processor class properly parses and modifies HTML5 documents. + * + * It supports a subset of the HTML5 specification, and when it encounters + * unsupported markup, it aborts early to avoid unintentionally breaking + * the document. The HTML Processor should never break an HTML document. + * + * While the `WP_HTML_Tag_Processor` is a valuable tool for modifying + * attributes on individual HTML tags, the HTML Processor is more capable + * and useful for the following operations: + * + * - Querying based on nested HTML structure. + * + * Eventually the HTML Processor will also support: + * - Wrapping a tag in surrounding HTML. + * - Unwrapping a tag by removing its parent. + * - Inserting and removing nodes. + * - Reading and changing inner content. + * - Navigating up or around HTML structure. + * + * ## Usage + * + * Use of this class requires three steps: + * + * 1. Call a static creator method with your input HTML document. + * 2. Find the location in the document you are looking for. + * 3. Request changes to the document at that location. + * + * Example: + * + * $processor = WP_HTML_Processor::create_fragment( $html ); + * if ( $processor->next_tag( array( 'breadcrumbs' => array( 'DIV', 'FIGURE', 'IMG' ) ) ) ) { + * $processor->add_class( 'responsive-image' ); + * } + * + * #### Breadcrumbs + * + * Breadcrumbs represent the stack of open elements from the root + * of the document or fragment down to the currently-matched node, + * if one is currently selected. Call WP_HTML_Processor::get_breadcrumbs() + * to inspect the breadcrumbs for a matched tag. + * + * Breadcrumbs can specify nested HTML structure and are equivalent + * to a CSS selector comprising tag names separated by the child + * combinator, such as "DIV > FIGURE > IMG". + * + * Since all elements find themselves inside a full HTML document + * when parsed, the return value from `get_breadcrumbs()` will always + * contain any implicit outermost elements. For example, when parsing + * with `create_fragment()` in the `BODY` context (the default), any + * tag in the given HTML document will contain `array( 'HTML', 'BODY', … )` + * in its breadcrumbs. + * + * Despite containing the implied outermost elements in their breadcrumbs, + * tags may be found with the shortest-matching breadcrumb query. That is, + * `array( 'IMG' )` matches all IMG elements and `array( 'P', 'IMG' )` + * matches all IMG elements directly inside a P element. To ensure that no + * partial matches erroneously match it's possible to specify in a query + * the full breadcrumb match all the way down from the root HTML element. + * + * Example: + * + * $html = '<figure><img><figcaption>A <em>lovely</em> day outside</figcaption></figure>'; + * // ----- Matches here. + * $processor->next_tag( array( 'breadcrumbs' => array( 'FIGURE', 'IMG' ) ) ); + * + * $html = '<figure><img><figcaption>A <em>lovely</em> day outside</figcaption></figure>'; + * // ---- Matches here. + * $processor->next_tag( array( 'breadcrumbs' => array( 'FIGURE', 'FIGCAPTION', 'EM' ) ) ); + * + * $html = '<div><img></div><img>'; + * // ----- Matches here, because IMG must be a direct child of the implicit BODY. + * $processor->next_tag( array( 'breadcrumbs' => array( 'BODY', 'IMG' ) ) ); + * + * ## HTML Support + * + * This class implements a small part of the HTML5 specification. + * It's designed to operate within its support and abort early whenever + * encountering circumstances it can't properly handle. This is + * the principle way in which this class remains as simple as possible + * without cutting corners and breaking compliance. + * + * ### Supported elements + * + * If any unsupported element appears in the HTML input the HTML Processor + * will abort early and stop all processing. This draconian measure ensures + * that the HTML Processor won't break any HTML it doesn't fully understand. + * + * The following list specifies the HTML tags that _are_ supported: + * + * - Containers: ADDRESS, BLOCKQUOTE, DETAILS, DIALOG, DIV, FOOTER, HEADER, MAIN, MENU, SPAN, SUMMARY. + * - Custom elements: All custom elements are supported. :) + * - Form elements: BUTTON, DATALIST, FIELDSET, INPUT, LABEL, LEGEND, METER, OPTGROUP, OPTION, PROGRESS, SEARCH, SELECT. + * - Formatting elements: B, BIG, CODE, EM, FONT, I, PRE, SMALL, STRIKE, STRONG, TT, U, WBR. + * - Heading elements: H1, H2, H3, H4, H5, H6, HGROUP. + * - Links: A. + * - Lists: DD, DL, DT, LI, OL, UL. + * - Media elements: AUDIO, CANVAS, EMBED, FIGCAPTION, FIGURE, IMG, MAP, PICTURE, SOURCE, TRACK, VIDEO. + * - Paragraph: BR, P. + * - Phrasing elements: ABBR, AREA, BDI, BDO, CITE, DATA, DEL, DFN, INS, MARK, OUTPUT, Q, SAMP, SUB, SUP, TIME, VAR. + * - Sectioning elements: ARTICLE, ASIDE, HR, NAV, SECTION. + * - Templating elements: SLOT. + * - Text decoration: RUBY. + * - Deprecated elements: ACRONYM, BLINK, CENTER, DIR, ISINDEX, KEYGEN, LISTING, MULTICOL, NEXTID, PARAM, SPACER. + * + * ### Supported markup + * + * Some kinds of non-normative HTML involve reconstruction of formatting elements and + * re-parenting of mis-nested elements. For example, a DIV tag found inside a TABLE + * may in fact belong _before_ the table in the DOM. If the HTML Processor encounters + * such a case it will stop processing. + * + * The following list specifies HTML markup that _is_ supported: + * + * - Markup involving only those tags listed above. + * - Fully-balanced and non-overlapping tags. + * - HTML with unexpected tag closers. + * - Some unbalanced or overlapping tags. + * - P tags after unclosed P tags. + * - BUTTON tags after unclosed BUTTON tags. + * - A tags after unclosed A tags that don't involve any active formatting elements. + * + * @since 6.4.0 + * + * @see WP_HTML_Tag_Processor + * @see https://html.spec.whatwg.org/ + */ +class Gutenberg_HTML_Processor_6_7 extends Gutenberg_HTML_Tag_Processor_6_7 { + /** + * The maximum number of bookmarks allowed to exist at any given time. + * + * HTML processing requires more bookmarks than basic tag processing, + * so this class constant from the Tag Processor is overwritten. + * + * @since 6.4.0 + * + * @var int + */ + const MAX_BOOKMARKS = 100; + + /** + * Holds the working state of the parser, including the stack of + * open elements and the stack of active formatting elements. + * + * Initialized in the constructor. + * + * @since 6.4.0 + * + * @var WP_HTML_Processor_State + */ + private $state; + + /** + * Used to create unique bookmark names. + * + * This class sets a bookmark for every tag in the HTML document that it encounters. + * The bookmark name is auto-generated and increments, starting with `1`. These are + * internal bookmarks and are automatically released when the referring WP_HTML_Token + * goes out of scope and is garbage-collected. + * + * @since 6.4.0 + * + * @see WP_HTML_Processor::$release_internal_bookmark_on_destruct + * + * @var int + */ + private $bookmark_counter = 0; + + /** + * Stores an explanation for why something failed, if it did. + * + * @see self::get_last_error + * + * @since 6.4.0 + * + * @var string|null + */ + private $last_error = null; + + /** + * Stores context for why the parser bailed on unsupported HTML, if it did. + * + * @see self::get_unsupported_exception + * + * @since 6.7.0 + * + * @var WP_HTML_Unsupported_Exception|null + */ + private $unsupported_exception = null; + + /** + * Releases a bookmark when PHP garbage-collects its wrapping WP_HTML_Token instance. + * + * This function is created inside the class constructor so that it can be passed to + * the stack of open elements and the stack of active formatting elements without + * exposing it as a public method on the class. + * + * @since 6.4.0 + * + * @var Closure|null + */ + private $release_internal_bookmark_on_destruct = null; + + /** + * Stores stack events which arise during parsing of the + * HTML document, which will then supply the "match" events. + * + * @since 6.6.0 + * + * @var WP_HTML_Stack_Event[] + */ + private $element_queue = array(); + + /** + * Stores the current breadcrumbs. + * + * @since 6.7.0 + * + * @var string[] + */ + private $breadcrumbs = array(); + + /** + * Current stack event, if set, representing a matched token. + * + * Because the parser may internally point to a place further along in a document + * than the nodes which have already been processed (some "virtual" nodes may have + * appeared while scanning the HTML document), this will point at the "current" node + * being processed. It comes from the front of the element queue. + * + * @since 6.6.0 + * + * @var WP_HTML_Stack_Event|null + */ + private $current_element = null; + + /** + * Context node if created as a fragment parser. + * + * @var WP_HTML_Token|null + */ + private $context_node = null; + + /** + * Whether the parser has yet processed the context node, + * if created as a fragment parser. + * + * The context node will be initially pushed onto the stack of open elements, + * but when created as a fragment parser, this context element (and the implicit + * HTML document node above it) should not be exposed as a matched token or node. + * + * This boolean indicates whether the processor should skip over the current + * node in its initial search for the first node created from the input HTML. + * + * @var bool + */ + private $has_seen_context_node = false; + + /* + * Public Interface Functions + */ + + /** + * Creates an HTML processor in the fragment parsing mode. + * + * Use this for cases where you are processing chunks of HTML that + * will be found within a bigger HTML document, such as rendered + * block output that exists within a post, `the_content` inside a + * rendered site layout. + * + * Fragment parsing occurs within a context, which is an HTML element + * that the document will eventually be placed in. It becomes important + * when special elements have different rules than others, such as inside + * a TEXTAREA or a TITLE tag where things that look like tags are text, + * or inside a SCRIPT tag where things that look like HTML syntax are JS. + * + * The context value should be a representation of the tag into which the + * HTML is found. For most cases this will be the body element. The HTML + * form is provided because a context element may have attributes that + * impact the parse, such as with a SCRIPT tag and its `type` attribute. + * + * ## Current HTML Support + * + * - The only supported context is `<body>`, which is the default value. + * - The only supported document encoding is `UTF-8`, which is the default value. + * + * @since 6.4.0 + * @since 6.6.0 Returns `static` instead of `self` so it can create subclass instances. + * + * @param string $html Input HTML fragment to process. + * @param string $context Context element for the fragment, must be default of `<body>`. + * @param string $encoding Text encoding of the document; must be default of 'UTF-8'. + * @return static|null The created processor if successful, otherwise null. + */ + public static function create_fragment( $html, $context = '<body>', $encoding = 'UTF-8' ) { + if ( '<body>' !== $context || 'UTF-8' !== $encoding ) { + return null; + } + + $processor = new static( $html, self::CONSTRUCTOR_UNLOCK_CODE ); + $processor->state->context_node = array( 'BODY', array() ); + $processor->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_BODY; + + // @todo Create "fake" bookmarks for non-existent but implied nodes. + $processor->bookmarks['root-node'] = new Gutenberg_HTML_Span_6_7( 0, 0 ); + $processor->bookmarks['context-node'] = new Gutenberg_HTML_Span_6_7( 0, 0 ); + + $processor->state->stack_of_open_elements->push( + new Gutenberg_HTML_Token_6_7( + 'root-node', + 'HTML', + false + ) + ); + + $context_node = new Gutenberg_HTML_Token_6_7( + 'context-node', + $processor->state->context_node[0], + false + ); + + $processor->context_node = $context_node; + $processor->breadcrumbs = array( 'HTML', $context_node->node_name ); + + return $processor; + } + + /** + * Constructor. + * + * Do not use this method. Use the static creator methods instead. + * + * @access private + * + * @since 6.4.0 + * + * @see WP_HTML_Processor::create_fragment() + * + * @param string $html HTML to process. + * @param string|null $use_the_static_create_methods_instead This constructor should not be called manually. + */ + public function __construct( $html, $use_the_static_create_methods_instead = null ) { + parent::__construct( $html ); + + if ( self::CONSTRUCTOR_UNLOCK_CODE !== $use_the_static_create_methods_instead ) { + _doing_it_wrong( + __METHOD__, + sprintf( + /* translators: %s: WP_HTML_Processor::create_fragment(). */ + __( 'Call %s to create an HTML Processor instead of calling the constructor directly.' ), + '<code>WP_HTML_Processor::create_fragment()</code>' + ), + '6.4.0' + ); + } + + $this->state = new Gutenberg_HTML_Processor_State_6_7(); + + $this->state->stack_of_open_elements->set_push_handler( + function ( Gutenberg_HTML_Token_6_7 $token ): void { + $is_virtual = ! isset( $this->state->current_token ) || $this->is_tag_closer(); + $same_node = isset( $this->state->current_token ) && $token->node_name === $this->state->current_token->node_name; + $provenance = ( ! $same_node || $is_virtual ) ? 'virtual' : 'real'; + $this->element_queue[] = new Gutenberg_HTML_Stack_Event_6_7( $token, Gutenberg_HTML_Stack_Event_6_7::PUSH, $provenance ); + } + ); + + $this->state->stack_of_open_elements->set_pop_handler( + function ( Gutenberg_HTML_Token_6_7 $token ): void { + $is_virtual = ! isset( $this->state->current_token ) || ! $this->is_tag_closer(); + $same_node = isset( $this->state->current_token ) && $token->node_name === $this->state->current_token->node_name; + $provenance = ( ! $same_node || $is_virtual ) ? 'virtual' : 'real'; + $this->element_queue[] = new Gutenberg_HTML_Stack_Event_6_7( $token, Gutenberg_HTML_Stack_Event_6_7::POP, $provenance ); + } + ); + + /* + * Create this wrapper so that it's possible to pass + * a private method into WP_HTML_Token classes without + * exposing it to any public API. + */ + $this->release_internal_bookmark_on_destruct = function ( string $name ): void { + parent::release_bookmark( $name ); + }; + } + + /** + * Stops the parser and terminates its execution when encountering unsupported markup. + * + * @throws WP_HTML_Unsupported_Exception Halts execution of the parser. + * + * @since 6.7.0 + * + * @param string $message Explains support is missing in order to parse the current node. + */ + private function bail( string $message ) { + $here = $this->bookmarks[ $this->state->current_token->bookmark_name ]; + $token = substr( $this->html, $here->start, $here->length ); + + $open_elements = array(); + foreach ( $this->state->stack_of_open_elements->stack as $item ) { + $open_elements[] = $item->node_name; + } + + $active_formats = array(); + foreach ( $this->state->active_formatting_elements->walk_down() as $item ) { + $active_formats[] = $item->node_name; + } + + $this->last_error = self::ERROR_UNSUPPORTED; + + $this->unsupported_exception = new Gutenberg_HTML_Unsupported_Exception_6_7( + $message, + $this->state->current_token->node_name, + $here->start, + $token, + $open_elements, + $active_formats + ); + + throw $this->unsupported_exception; + } + + /** + * Returns the last error, if any. + * + * Various situations lead to parsing failure but this class will + * return `false` in all those cases. To determine why something + * failed it's possible to request the last error. This can be + * helpful to know to distinguish whether a given tag couldn't + * be found or if content in the document caused the processor + * to give up and abort processing. + * + * Example + * + * $processor = WP_HTML_Processor::create_fragment( '<template><strong><button><em><p><em>' ); + * false === $processor->next_tag(); + * WP_HTML_Processor::ERROR_UNSUPPORTED === $processor->get_last_error(); + * + * @since 6.4.0 + * + * @see self::ERROR_UNSUPPORTED + * @see self::ERROR_EXCEEDED_MAX_BOOKMARKS + * + * @return string|null The last error, if one exists, otherwise null. + */ + public function get_last_error(): ?string { + return $this->last_error; + } + + /** + * Returns context for why the parser aborted due to unsupported HTML, if it did. + * + * This is meant for debugging purposes, not for production use. + * + * @since 6.7.0 + * + * @see self::$unsupported_exception + * + * @return WP_HTML_Unsupported_Exception|null + */ + public function get_unsupported_exception() { + return $this->unsupported_exception; + } + + /** + * Finds the next tag matching the $query. + * + * @todo Support matching the class name and tag name. + * + * @since 6.4.0 + * @since 6.6.0 Visits all tokens, including virtual ones. + * + * @throws Exception When unable to allocate a bookmark for the next token in the input HTML document. + * + * @param array|string|null $query { + * Optional. Which tag name to find, having which class, etc. Default is to find any tag. + * + * @type string|null $tag_name Which tag to find, or `null` for "any tag." + * @type string $tag_closers 'visit' to pause at tag closers, 'skip' or unset to only visit openers. + * @type int|null $match_offset Find the Nth tag matching all search criteria. + * 1 for "first" tag, 3 for "third," etc. + * Defaults to first tag. + * @type string|null $class_name Tag must contain this whole class name to match. + * @type string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. + * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. + * } + * @return bool Whether a tag was matched. + */ + public function next_tag( $query = null ): bool { + $visit_closers = isset( $query['tag_closers'] ) && 'visit' === $query['tag_closers']; + + if ( null === $query ) { + while ( $this->next_token() ) { + if ( '#tag' !== $this->get_token_type() ) { + continue; + } + + if ( ! $this->is_tag_closer() || $visit_closers ) { + return true; + } + } + + return false; + } + + if ( is_string( $query ) ) { + $query = array( 'breadcrumbs' => array( $query ) ); + } + + if ( ! is_array( $query ) ) { + _doing_it_wrong( + __METHOD__, + __( 'Please pass a query array to this function.' ), + '6.4.0' + ); + return false; + } + + $needs_class = ( isset( $query['class_name'] ) && is_string( $query['class_name'] ) ) + ? $query['class_name'] + : null; + + if ( ! ( array_key_exists( 'breadcrumbs', $query ) && is_array( $query['breadcrumbs'] ) ) ) { + while ( $this->next_token() ) { + if ( '#tag' !== $this->get_token_type() ) { + continue; + } + + if ( isset( $query['tag_name'] ) && $query['tag_name'] !== $this->get_token_name() ) { + continue; + } + + if ( isset( $needs_class ) && ! $this->has_class( $needs_class ) ) { + continue; + } + + if ( ! $this->is_tag_closer() || $visit_closers ) { + return true; + } + } + + return false; + } + + $breadcrumbs = $query['breadcrumbs']; + $match_offset = isset( $query['match_offset'] ) ? (int) $query['match_offset'] : 1; + + while ( $match_offset > 0 && $this->next_token() ) { + if ( '#tag' !== $this->get_token_type() || $this->is_tag_closer() ) { + continue; + } + + if ( isset( $needs_class ) && ! $this->has_class( $needs_class ) ) { + continue; + } + + if ( $this->matches_breadcrumbs( $breadcrumbs ) && 0 === --$match_offset ) { + return true; + } + } + + return false; + } + + /** + * Ensures internal accounting is maintained for HTML semantic rules while + * the underlying Tag Processor class is seeking to a bookmark. + * + * This doesn't currently have a way to represent non-tags and doesn't process + * semantic rules for text nodes. For access to the raw tokens consider using + * WP_HTML_Tag_Processor instead. + * + * @since 6.5.0 Added for internal support; do not use. + * + * @access private + * + * @return bool + */ + public function next_token(): bool { + $this->current_element = null; + + if ( isset( $this->last_error ) ) { + return false; + } + + /* + * Prime the events if there are none. + * + * @todo In some cases, probably related to the adoption agency + * algorithm, this call to step() doesn't create any new + * events. Calling it again creates them. Figure out why + * this is and if it's inherent or if it's a bug. Looping + * until there are events or until there are no more + * tokens works in the meantime and isn't obviously wrong. + */ + while ( empty( $this->element_queue ) && $this->step() ) { + continue; + } + + // Process the next event on the queue. + $this->current_element = array_shift( $this->element_queue ); + if ( ! isset( $this->current_element ) ) { + return false; + } + + $is_pop = Gutenberg_HTML_Stack_Event_6_7::POP === $this->current_element->operation; + + /* + * The root node only exists in the fragment parser, and closing it + * indicates that the parse is complete. Stop before popping if from + * the breadcrumbs. + */ + if ( 'root-node' === $this->current_element->token->bookmark_name ) { + return ! $is_pop && $this->next_token(); + } + + // Adjust the breadcrumbs for this event. + if ( $is_pop ) { + array_pop( $this->breadcrumbs ); + } else { + $this->breadcrumbs[] = $this->current_element->token->node_name; + } + + // Avoid sending close events for elements which don't expect a closing. + if ( $is_pop && ! static::expects_closer( $this->current_element->token ) ) { + return $this->next_token(); + } + + return true; + } + + /** + * Indicates if the current tag token is a tag closer. + * + * Example: + * + * $p = WP_HTML_Processor::create_fragment( '<div></div>' ); + * $p->next_tag( array( 'tag_name' => 'div', 'tag_closers' => 'visit' ) ); + * $p->is_tag_closer() === false; + * + * $p->next_tag( array( 'tag_name' => 'div', 'tag_closers' => 'visit' ) ); + * $p->is_tag_closer() === true; + * + * @since 6.6.0 Subclassed for HTML Processor. + * + * @return bool Whether the current tag is a tag closer. + */ + public function is_tag_closer(): bool { + return $this->is_virtual() + ? ( Gutenberg_HTML_Stack_Event_6_7::POP === $this->current_element->operation && '#tag' === $this->get_token_type() ) + : parent::is_tag_closer(); + } + + /** + * Indicates if the currently-matched token is virtual, created by a stack operation + * while processing HTML, rather than a token found in the HTML text itself. + * + * @since 6.6.0 + * + * @return bool Whether the current token is virtual. + */ + private function is_virtual(): bool { + return ( + isset( $this->current_element->provenance ) && + 'virtual' === $this->current_element->provenance + ); + } + + /** + * Indicates if the currently-matched tag matches the given breadcrumbs. + * + * A "*" represents a single tag wildcard, where any tag matches, but not no tags. + * + * At some point this function _may_ support a `**` syntax for matching any number + * of unspecified tags in the breadcrumb stack. This has been intentionally left + * out, however, to keep this function simple and to avoid introducing backtracking, + * which could open up surprising performance breakdowns. + * + * Example: + * + * $processor = WP_HTML_Processor::create_fragment( '<div><span><figure><img></figure></span></div>' ); + * $processor->next_tag( 'img' ); + * true === $processor->matches_breadcrumbs( array( 'figure', 'img' ) ); + * true === $processor->matches_breadcrumbs( array( 'span', 'figure', 'img' ) ); + * false === $processor->matches_breadcrumbs( array( 'span', 'img' ) ); + * true === $processor->matches_breadcrumbs( array( 'span', '*', 'img' ) ); + * + * @since 6.4.0 + * + * @param string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. + * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. + * @return bool Whether the currently-matched tag is found at the given nested structure. + */ + public function matches_breadcrumbs( $breadcrumbs ): bool { + // Everything matches when there are zero constraints. + if ( 0 === count( $breadcrumbs ) ) { + return true; + } + + // Start at the last crumb. + $crumb = end( $breadcrumbs ); + + if ( '*' !== $crumb && $this->get_tag() !== strtoupper( $crumb ) ) { + return false; + } + + for ( $i = count( $this->breadcrumbs ) - 1; $i >= 0; $i-- ) { + $node = $this->breadcrumbs[ $i ]; + $crumb = strtoupper( current( $breadcrumbs ) ); + + if ( '*' !== $crumb && $node !== $crumb ) { + return false; + } + + if ( false === prev( $breadcrumbs ) ) { + return true; + } + } + + return false; + } + + /** + * Indicates if the currently-matched node expects a closing + * token, or if it will self-close on the next step. + * + * Most HTML elements expect a closer, such as a P element or + * a DIV element. Others, like an IMG element are void and don't + * have a closing tag. Special elements, such as SCRIPT and STYLE, + * are treated just like void tags. Text nodes and self-closing + * foreign content will also act just like a void tag, immediately + * closing as soon as the processor advances to the next token. + * + * @since 6.6.0 + * + * @todo When adding support for foreign content, ensure that + * this returns false for self-closing elements in the + * SVG and MathML namespace. + * + * @param WP_HTML_Token|null $node Optional. Node to examine, if provided. + * Default is to examine current node. + * @return bool|null Whether to expect a closer for the currently-matched node, + * or `null` if not matched on any token. + */ + public function expects_closer( $node = null ): ?bool { + $token_name = $node->node_name ?? $this->get_token_name(); + if ( ! isset( $token_name ) ) { + return null; + } + + return ! ( + // Comments, text nodes, and other atomic tokens. + '#' === $token_name[0] || + // Doctype declarations. + 'html' === $token_name || + // Void elements. + self::is_void( $token_name ) || + // Special atomic elements. + in_array( $token_name, array( 'IFRAME', 'NOEMBED', 'NOFRAMES', 'SCRIPT', 'STYLE', 'TEXTAREA', 'TITLE', 'XMP' ), true ) + ); + } + + /** + * Steps through the HTML document and stop at the next tag, if any. + * + * @since 6.4.0 + * + * @throws Exception When unable to allocate a bookmark for the next token in the input HTML document. + * + * @see self::PROCESS_NEXT_NODE + * @see self::REPROCESS_CURRENT_NODE + * + * @param string $node_to_process Whether to parse the next node or reprocess the current node. + * @return bool Whether a tag was matched. + */ + public function step( $node_to_process = self::PROCESS_NEXT_NODE ): bool { + // Refuse to proceed if there was a previous error. + if ( null !== $this->last_error ) { + return false; + } + + if ( self::REPROCESS_CURRENT_NODE !== $node_to_process ) { + /* + * Void elements still hop onto the stack of open elements even though + * there's no corresponding closing tag. This is important for managing + * stack-based operations such as "navigate to parent node" or checking + * on an element's breadcrumbs. + * + * When moving on to the next node, therefore, if the bottom-most element + * on the stack is a void element, it must be closed. + * + * @todo Once self-closing foreign elements and BGSOUND are supported, + * they must also be implicitly closed here too. BGSOUND is + * special since it's only self-closing if the self-closing flag + * is provided in the opening tag, otherwise it expects a tag closer. + */ + $top_node = $this->state->stack_of_open_elements->current_node(); + if ( isset( $top_node ) && ! static::expects_closer( $top_node ) ) { + $this->state->stack_of_open_elements->pop(); + } + } + + if ( self::PROCESS_NEXT_NODE === $node_to_process ) { + parent::next_token(); + } + + // Finish stepping when there are no more tokens in the document. + if ( + Gutenberg_HTML_Tag_Processor_6_7::STATE_INCOMPLETE_INPUT === $this->parser_state || + Gutenberg_HTML_Tag_Processor_6_7::STATE_COMPLETE === $this->parser_state + ) { + return false; + } + + $this->state->current_token = new Gutenberg_HTML_Token_6_7( + $this->bookmark_token(), + $this->get_token_name(), + $this->has_self_closing_flag(), + $this->release_internal_bookmark_on_destruct + ); + + try { + switch ( $this->state->insertion_mode ) { + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_INITIAL: + return $this->step_initial(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_BEFORE_HTML: + return $this->step_before_html(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_BEFORE_HEAD: + return $this->step_before_head(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_HEAD: + return $this->step_in_head(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_HEAD_NOSCRIPT: + return $this->step_in_head_noscript(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_AFTER_HEAD: + return $this->step_after_head(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_BODY: + return $this->step_in_body(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_TABLE: + return $this->step_in_table(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_TABLE_TEXT: + return $this->step_in_table_text(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_CAPTION: + return $this->step_in_caption(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_COLUMN_GROUP: + return $this->step_in_column_group(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_TABLE_BODY: + return $this->step_in_table_body(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_ROW: + return $this->step_in_row(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_CELL: + return $this->step_in_cell(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_SELECT: + return $this->step_in_select(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_SELECT_IN_TABLE: + return $this->step_in_select_in_table(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_TEMPLATE: + return $this->step_in_template(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_AFTER_BODY: + return $this->step_after_body(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_FRAMESET: + return $this->step_in_frameset(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_AFTER_FRAMESET: + return $this->step_after_frameset(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_AFTER_AFTER_BODY: + return $this->step_after_after_body(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_AFTER_AFTER_FRAMESET: + return $this->step_after_after_frameset(); + + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_FOREIGN_CONTENT: + return $this->step_in_foreign_content(); + + // This should be unreachable but PHP doesn't have total type checking on switch. + default: + $this->bail( "Unaware of the requested parsing mode: '{$this->state->insertion_mode}'." ); + } + } catch ( Gutenberg_HTML_Unsupported_Exception_6_7 $e ) { + /* + * Exceptions are used in this class to escape deep call stacks that + * otherwise might involve messier calling and return conventions. + */ + return false; + } + } + + /** + * Computes the HTML breadcrumbs for the currently-matched node, if matched. + * + * Breadcrumbs start at the outermost parent and descend toward the matched element. + * They always include the entire path from the root HTML node to the matched element. + * + * @todo It could be more efficient to expose a generator-based version of this function + * to avoid creating the array copy on tag iteration. If this is done, it would likely + * be more useful to walk up the stack when yielding instead of starting at the top. + * + * Example + * + * $processor = WP_HTML_Processor::create_fragment( '<p><strong><em><img></em></strong></p>' ); + * $processor->next_tag( 'IMG' ); + * $processor->get_breadcrumbs() === array( 'HTML', 'BODY', 'P', 'STRONG', 'EM', 'IMG' ); + * + * @since 6.4.0 + * + * @return string[]|null Array of tag names representing path to matched node, if matched, otherwise NULL. + */ + public function get_breadcrumbs(): ?array { + return $this->breadcrumbs; + } + + /** + * Returns the nesting depth of the current location in the document. + * + * Example: + * + * $processor = WP_HTML_Processor::create_fragment( '<div><p></p></div>' ); + * // The processor starts in the BODY context, meaning it has depth from the start: HTML > BODY. + * 2 === $processor->get_current_depth(); + * + * // Opening the DIV element increases the depth. + * $processor->next_token(); + * 3 === $processor->get_current_depth(); + * + * // Opening the P element increases the depth. + * $processor->next_token(); + * 4 === $processor->get_current_depth(); + * + * // The P element is closed during `next_token()` so the depth is decreased to reflect that. + * $processor->next_token(); + * 3 === $processor->get_current_depth(); + * + * @since 6.6.0 + * + * @return int Nesting-depth of current location in the document. + */ + public function get_current_depth(): int { + return count( $this->breadcrumbs ); + } + + /** + * Parses next element in the 'initial' insertion mode. + * + * This internal function performs the 'initial' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#the-initial-insertion-mode + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_initial(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'before html' insertion mode. + * + * This internal function performs the 'before html' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#the-before-html-insertion-mode + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_before_html(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'before head' insertion mode. + * + * This internal function performs the 'before head' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#the-before-head-insertion-mode + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_before_head(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'in head' insertion mode. + * + * This internal function performs the 'in head' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inhead + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_head(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'in head noscript' insertion mode. + * + * This internal function performs the 'in head noscript' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-inheadnoscript + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_head_noscript(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'after head' insertion mode. + * + * This internal function performs the 'after head' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#the-after-head-insertion-mode + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_after_head(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'in body' insertion mode. + * + * This internal function performs the 'in body' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.4.0 + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-inbody + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_body(): bool { + $token_name = $this->get_token_name(); + $token_type = $this->get_token_type(); + $op_sigil = '#tag' === $token_type ? ( parent::is_tag_closer() ? '-' : '+' ) : ''; + $op = "{$op_sigil}{$token_name}"; + + switch ( $op ) { + case '#comment': + case '#funky-comment': + case '#presumptuous-tag': + $this->insert_html_element( $this->state->current_token ); + return true; + + case '#text': + $this->reconstruct_active_formatting_elements(); + + $current_token = $this->bookmarks[ $this->state->current_token->bookmark_name ]; + + /* + * > A character token that is U+0000 NULL + * + * Any successive sequence of NULL bytes is ignored and won't + * trigger active format reconstruction. Therefore, if the text + * only comprises NULL bytes then the token should be ignored + * here, but if there are any other characters in the stream + * the active formats should be reconstructed. + */ + if ( + 1 <= $current_token->length && + "\x00" === $this->html[ $current_token->start ] && + strspn( $this->html, "\x00", $current_token->start, $current_token->length ) === $current_token->length + ) { + // Parse error: ignore the token. + return $this->step(); + } + + /* + * Whitespace-only text does not affect the frameset-ok flag. + * It is probably inter-element whitespace, but it may also + * contain character references which decode only to whitespace. + */ + $text = $this->get_modifiable_text(); + if ( strlen( $text ) !== strspn( $text, " \t\n\f\r" ) ) { + $this->state->frameset_ok = false; + } + + $this->insert_html_element( $this->state->current_token ); + return true; + + case 'html': + /* + * > A DOCTYPE token + * > Parse error. Ignore the token. + */ + return $this->step(); + + /* + * > A start tag whose tag name is "button" + */ + case '+BUTTON': + if ( $this->state->stack_of_open_elements->has_element_in_scope( 'BUTTON' ) ) { + // @todo Indicate a parse error once it's possible. This error does not impact the logic here. + $this->generate_implied_end_tags(); + $this->state->stack_of_open_elements->pop_until( 'BUTTON' ); + } + + $this->reconstruct_active_formatting_elements(); + $this->insert_html_element( $this->state->current_token ); + $this->state->frameset_ok = false; + + return true; + + /* + * > A start tag whose tag name is one of: "address", "article", "aside", + * > "blockquote", "center", "details", "dialog", "dir", "div", "dl", + * > "fieldset", "figcaption", "figure", "footer", "header", "hgroup", + * > "main", "menu", "nav", "ol", "p", "search", "section", "summary", "ul" + */ + case '+ADDRESS': + case '+ARTICLE': + case '+ASIDE': + case '+BLOCKQUOTE': + case '+CENTER': + case '+DETAILS': + case '+DIALOG': + case '+DIR': + case '+DIV': + case '+DL': + case '+FIELDSET': + case '+FIGCAPTION': + case '+FIGURE': + case '+FOOTER': + case '+HEADER': + case '+HGROUP': + case '+MAIN': + case '+MENU': + case '+NAV': + case '+OL': + case '+P': + case '+SEARCH': + case '+SECTION': + case '+SUMMARY': + case '+UL': + if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { + $this->close_a_p_element(); + } + + $this->insert_html_element( $this->state->current_token ); + return true; + + /* + * > An end tag whose tag name is one of: "address", "article", "aside", "blockquote", + * > "button", "center", "details", "dialog", "dir", "div", "dl", "fieldset", + * > "figcaption", "figure", "footer", "header", "hgroup", "listing", "main", + * > "menu", "nav", "ol", "pre", "search", "section", "summary", "ul" + */ + case '-ADDRESS': + case '-ARTICLE': + case '-ASIDE': + case '-BLOCKQUOTE': + case '-BUTTON': + case '-CENTER': + case '-DETAILS': + case '-DIALOG': + case '-DIR': + case '-DIV': + case '-DL': + case '-FIELDSET': + case '-FIGCAPTION': + case '-FIGURE': + case '-FOOTER': + case '-HEADER': + case '-HGROUP': + case '-LISTING': + case '-MAIN': + case '-MENU': + case '-NAV': + case '-OL': + case '-PRE': + case '-SEARCH': + case '-SECTION': + case '-SUMMARY': + case '-UL': + if ( ! $this->state->stack_of_open_elements->has_element_in_scope( $token_name ) ) { + // @todo Report parse error. + // Ignore the token. + return $this->step(); + } + + $this->generate_implied_end_tags(); + if ( ! $this->state->stack_of_open_elements->current_node_is( $token_name ) ) { + // @todo Record parse error: this error doesn't impact parsing. + } + $this->state->stack_of_open_elements->pop_until( $token_name ); + return true; + + /* + * > A start tag whose tag name is one of: "h1", "h2", "h3", "h4", "h5", "h6" + */ + case '+H1': + case '+H2': + case '+H3': + case '+H4': + case '+H5': + case '+H6': + if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { + $this->close_a_p_element(); + } + + if ( + in_array( + $this->state->stack_of_open_elements->current_node()->node_name, + array( 'H1', 'H2', 'H3', 'H4', 'H5', 'H6' ), + true + ) + ) { + // @todo Indicate a parse error once it's possible. + $this->state->stack_of_open_elements->pop(); + } + + $this->insert_html_element( $this->state->current_token ); + return true; + + /* + * > A start tag whose tag name is one of: "pre", "listing" + */ + case '+PRE': + case '+LISTING': + if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { + $this->close_a_p_element(); + } + $this->insert_html_element( $this->state->current_token ); + $this->state->frameset_ok = false; + return true; + + /* + * > An end tag whose tag name is one of: "h1", "h2", "h3", "h4", "h5", "h6" + */ + case '-H1': + case '-H2': + case '-H3': + case '-H4': + case '-H5': + case '-H6': + if ( ! $this->state->stack_of_open_elements->has_element_in_scope( '(internal: H1 through H6 - do not use)' ) ) { + /* + * This is a parse error; ignore the token. + * + * @todo Indicate a parse error once it's possible. + */ + return $this->step(); + } + + $this->generate_implied_end_tags(); + + if ( ! $this->state->stack_of_open_elements->current_node_is( $token_name ) ) { + // @todo Record parse error: this error doesn't impact parsing. + } + + $this->state->stack_of_open_elements->pop_until( '(internal: H1 through H6 - do not use)' ); + return true; + + /* + * > A start tag whose tag name is "li" + * > A start tag whose tag name is one of: "dd", "dt" + */ + case '+DD': + case '+DT': + case '+LI': + $this->state->frameset_ok = false; + $node = $this->state->stack_of_open_elements->current_node(); + $is_li = 'LI' === $token_name; + + in_body_list_loop: + /* + * The logic for LI and DT/DD is the same except for one point: LI elements _only_ + * close other LI elements, but a DT or DD element closes _any_ open DT or DD element. + */ + if ( $is_li ? 'LI' === $node->node_name : ( 'DD' === $node->node_name || 'DT' === $node->node_name ) ) { + $node_name = $is_li ? 'LI' : $node->node_name; + $this->generate_implied_end_tags( $node_name ); + if ( ! $this->state->stack_of_open_elements->current_node_is( $node_name ) ) { + // @todo Indicate a parse error once it's possible. This error does not impact the logic here. + } + + $this->state->stack_of_open_elements->pop_until( $node_name ); + goto in_body_list_done; + } + + if ( + 'ADDRESS' !== $node->node_name && + 'DIV' !== $node->node_name && + 'P' !== $node->node_name && + $this->is_special( $node->node_name ) + ) { + /* + * > If node is in the special category, but is not an address, div, + * > or p element, then jump to the step labeled done below. + */ + goto in_body_list_done; + } else { + /* + * > Otherwise, set node to the previous entry in the stack of open elements + * > and return to the step labeled loop. + */ + foreach ( $this->state->stack_of_open_elements->walk_up( $node ) as $item ) { + $node = $item; + break; + } + goto in_body_list_loop; + } + + in_body_list_done: + if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { + $this->close_a_p_element(); + } + + $this->insert_html_element( $this->state->current_token ); + return true; + + /* + * > An end tag whose tag name is "li" + * > An end tag whose tag name is one of: "dd", "dt" + */ + case '-DD': + case '-DT': + case '-LI': + if ( + /* + * An end tag whose tag name is "li": + * If the stack of open elements does not have an li element in list item scope, + * then this is a parse error; ignore the token. + */ + ( + 'LI' === $token_name && + ! $this->state->stack_of_open_elements->has_element_in_list_item_scope( 'LI' ) + ) || + /* + * An end tag whose tag name is one of: "dd", "dt": + * If the stack of open elements does not have an element in scope that is an + * HTML element with the same tag name as that of the token, then this is a + * parse error; ignore the token. + */ + ( + 'LI' !== $token_name && + ! $this->state->stack_of_open_elements->has_element_in_scope( $token_name ) + ) + ) { + /* + * This is a parse error, ignore the token. + * + * @todo Indicate a parse error once it's possible. + */ + return $this->step(); + } + + $this->generate_implied_end_tags( $token_name ); + + if ( ! $this->state->stack_of_open_elements->current_node_is( $token_name ) ) { + // @todo Indicate a parse error once it's possible. This error does not impact the logic here. + } + + $this->state->stack_of_open_elements->pop_until( $token_name ); + return true; + + /* + * > An end tag whose tag name is "p" + */ + case '-P': + if ( ! $this->state->stack_of_open_elements->has_p_in_button_scope() ) { + $this->insert_html_element( $this->state->current_token ); + } + + $this->close_a_p_element(); + return true; + + // > A start tag whose tag name is "a" + case '+A': + foreach ( $this->state->active_formatting_elements->walk_up() as $item ) { + switch ( $item->node_name ) { + case 'marker': + break; + + case 'A': + $this->run_adoption_agency_algorithm(); + $this->state->active_formatting_elements->remove_node( $item ); + $this->state->stack_of_open_elements->remove_node( $item ); + break; + } + } + + $this->reconstruct_active_formatting_elements(); + $this->insert_html_element( $this->state->current_token ); + $this->state->active_formatting_elements->push( $this->state->current_token ); + return true; + + /* + * > A start tag whose tag name is one of: "b", "big", "code", "em", "font", "i", + * > "s", "small", "strike", "strong", "tt", "u" + */ + case '+B': + case '+BIG': + case '+CODE': + case '+EM': + case '+FONT': + case '+I': + case '+S': + case '+SMALL': + case '+STRIKE': + case '+STRONG': + case '+TT': + case '+U': + $this->reconstruct_active_formatting_elements(); + $this->insert_html_element( $this->state->current_token ); + $this->state->active_formatting_elements->push( $this->state->current_token ); + return true; + + /* + * > An end tag whose tag name is one of: "a", "b", "big", "code", "em", "font", "i", + * > "nobr", "s", "small", "strike", "strong", "tt", "u" + */ + case '-A': + case '-B': + case '-BIG': + case '-CODE': + case '-EM': + case '-FONT': + case '-I': + case '-S': + case '-SMALL': + case '-STRIKE': + case '-STRONG': + case '-TT': + case '-U': + $this->run_adoption_agency_algorithm(); + return true; + + /* + * > An end tag whose tag name is "br" + * > Parse error. Drop the attributes from the token, and act as described in the next + * > entry; i.e. act as if this was a "br" start tag token with no attributes, rather + * > than the end tag token that it actually is. + */ + case '-BR': + $this->bail( 'Closing BR tags require unimplemented special handling.' ); + // This return required because PHPCS can't determine that the call to bail() throws. + return false; + + /* + * > A start tag whose tag name is one of: "area", "br", "embed", "img", "keygen", "wbr" + */ + case '+AREA': + case '+BR': + case '+EMBED': + case '+IMG': + case '+KEYGEN': + case '+WBR': + $this->reconstruct_active_formatting_elements(); + $this->insert_html_element( $this->state->current_token ); + $this->state->frameset_ok = false; + return true; + + /* + * > A start tag whose tag name is "input" + */ + case '+INPUT': + $this->reconstruct_active_formatting_elements(); + $this->insert_html_element( $this->state->current_token ); + $type_attribute = $this->get_attribute( 'type' ); + /* + * > If the token does not have an attribute with the name "type", or if it does, + * > but that attribute's value is not an ASCII case-insensitive match for the + * > string "hidden", then: set the frameset-ok flag to "not ok". + */ + if ( ! is_string( $type_attribute ) || 'hidden' !== strtolower( $type_attribute ) ) { + $this->state->frameset_ok = false; + } + return true; + + /* + * > A start tag whose tag name is "hr" + */ + case '+HR': + if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { + $this->close_a_p_element(); + } + $this->insert_html_element( $this->state->current_token ); + $this->state->frameset_ok = false; + return true; + + /* + * > A start tag whose tag name is one of: "param", "source", "track" + */ + case '+PARAM': + case '+SOURCE': + case '+TRACK': + $this->insert_html_element( $this->state->current_token ); + return true; + + /* + * > A start tag whose tag name is "select" + */ + case '+SELECT': + $this->reconstruct_active_formatting_elements(); + $this->insert_html_element( $this->state->current_token ); + $this->state->frameset_ok = false; + + switch ( $this->state->insertion_mode ) { + /* + * > If the insertion mode is one of "in table", "in caption", "in table body", "in row", + * > or "in cell", then switch the insertion mode to "in select in table". + */ + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_TABLE: + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_CAPTION: + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_TABLE_BODY: + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_ROW: + case Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_CELL: + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_SELECT_IN_TABLE; + break; + + /* + * > Otherwise, switch the insertion mode to "in select". + */ + default: + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_SELECT; + break; + } + return true; + + /* + * > A start tag whose tag name is one of: "optgroup", "option" + */ + case '+OPTGROUP': + case '+OPTION': + if ( $this->state->stack_of_open_elements->current_node_is( 'OPTION' ) ) { + $this->state->stack_of_open_elements->pop(); + } + $this->reconstruct_active_formatting_elements(); + $this->insert_html_element( $this->state->current_token ); + return true; + } + + /* + * These tags require special handling in the 'in body' insertion mode + * but that handling hasn't yet been implemented. + * + * As the rules for each tag are implemented, the corresponding tag + * name should be removed from this list. An accompanying test should + * help ensure this list is maintained. + * + * @see Tests_HtmlApi_WpHtmlProcessor::test_step_in_body_fails_on_unsupported_tags + * + * Since this switch structure throws a WP_HTML_Unsupported_Exception, it's + * possible to handle "any other start tag" and "any other end tag" below, + * as that guarantees execution doesn't proceed for the unimplemented tags. + * + * @see https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inbody + */ + switch ( $token_name ) { + case 'APPLET': + case 'BASE': + case 'BASEFONT': + case 'BGSOUND': + case 'BODY': + case 'CAPTION': + case 'COL': + case 'COLGROUP': + case 'FORM': + case 'FRAME': + case 'FRAMESET': + case 'HEAD': + case 'HTML': + case 'IFRAME': + case 'LINK': + case 'MARQUEE': + case 'MATH': + case 'META': + case 'NOBR': + case 'NOEMBED': + case 'NOFRAMES': + case 'NOSCRIPT': + case 'OBJECT': + case 'PLAINTEXT': + case 'RB': + case 'RP': + case 'RT': + case 'RTC': + case 'SARCASM': + case 'SCRIPT': + case 'STYLE': + case 'SVG': + case 'TABLE': + case 'TBODY': + case 'TD': + case 'TEMPLATE': + case 'TEXTAREA': + case 'TFOOT': + case 'TH': + case 'THEAD': + case 'TITLE': + case 'TR': + case 'XMP': + $this->bail( "Cannot process {$token_name} element." ); + } + + if ( ! parent::is_tag_closer() ) { + /* + * > Any other start tag + */ + $this->reconstruct_active_formatting_elements(); + $this->insert_html_element( $this->state->current_token ); + return true; + } else { + /* + * > Any other end tag + */ + + /* + * Find the corresponding tag opener in the stack of open elements, if + * it exists before reaching a special element, which provides a kind + * of boundary in the stack. For example, a `</custom-tag>` should not + * close anything beyond its containing `P` or `DIV` element. + */ + foreach ( $this->state->stack_of_open_elements->walk_up() as $node ) { + if ( $token_name === $node->node_name ) { + break; + } + + if ( self::is_special( $node->node_name ) ) { + // This is a parse error, ignore the token. + return $this->step(); + } + } + + $this->generate_implied_end_tags( $token_name ); + if ( $node !== $this->state->stack_of_open_elements->current_node() ) { + // @todo Record parse error: this error doesn't impact parsing. + } + + foreach ( $this->state->stack_of_open_elements->walk_up() as $item ) { + $this->state->stack_of_open_elements->pop(); + if ( $node === $item ) { + return true; + } + } + } + } + + /** + * Parses next element in the 'in table' insertion mode. + * + * This internal function performs the 'in table' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-intable + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_table(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'in table text' insertion mode. + * + * This internal function performs the 'in table text' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-intabletext + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_table_text(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'in caption' insertion mode. + * + * This internal function performs the 'in caption' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-incaption + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_caption(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'in column group' insertion mode. + * + * This internal function performs the 'in column group' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-incolgroup + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_column_group(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'in table body' insertion mode. + * + * This internal function performs the 'in table body' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-intbody + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_table_body(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'in row' insertion mode. + * + * This internal function performs the 'in row' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-intr + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_row(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'in cell' insertion mode. + * + * This internal function performs the 'in cell' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-intd + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_cell(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'in select' insertion mode. + * + * This internal function performs the 'in select' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inselect + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_select(): bool { + $token_name = $this->get_token_name(); + $token_type = $this->get_token_type(); + $op_sigil = '#tag' === $token_type ? ( parent::is_tag_closer() ? '-' : '+' ) : ''; + $op = "{$op_sigil}{$token_name}"; + + switch ( $op ) { + /* + * > Any other character token + */ + case '#text': + $current_token = $this->bookmarks[ $this->state->current_token->bookmark_name ]; + + /* + * > A character token that is U+0000 NULL + * + * If a text node only comprises null bytes then it should be + * entirely ignored and should not return to calling code. + */ + if ( + 1 <= $current_token->length && + "\x00" === $this->html[ $current_token->start ] && + strspn( $this->html, "\x00", $current_token->start, $current_token->length ) === $current_token->length + ) { + // Parse error: ignore the token. + return $this->step(); + } + + $this->insert_html_element( $this->state->current_token ); + return true; + + /* + * > A comment token + */ + case '#comment': + case '#funky-comment': + case '#presumptuous-tag': + $this->insert_html_element( $this->state->current_token ); + return true; + + /* + * > A DOCTYPE token + */ + case 'html': + // Parse error: ignore the token. + return $this->step(); + + /* + * > A start tag whose tag name is "html" + */ + case '+HTML': + return $this->step_in_body(); + + /* + * > A start tag whose tag name is "option" + */ + case '+OPTION': + if ( $this->state->stack_of_open_elements->current_node_is( 'OPTION' ) ) { + $this->state->stack_of_open_elements->pop(); + } + $this->insert_html_element( $this->state->current_token ); + return true; + + /* + * > A start tag whose tag name is "optgroup" + * > A start tag whose tag name is "hr" + * + * These rules are identical except for the treatment of the self-closing flag and + * the subsequent pop of the HR void element, all of which is handled elsewhere in the processor. + */ + case '+OPTGROUP': + case '+HR': + if ( $this->state->stack_of_open_elements->current_node_is( 'OPTION' ) ) { + $this->state->stack_of_open_elements->pop(); + } + + if ( $this->state->stack_of_open_elements->current_node_is( 'OPTGROUP' ) ) { + $this->state->stack_of_open_elements->pop(); + } + + $this->insert_html_element( $this->state->current_token ); + return true; + + /* + * > An end tag whose tag name is "optgroup" + */ + case '-OPTGROUP': + $current_node = $this->state->stack_of_open_elements->current_node(); + if ( $current_node && 'OPTION' === $current_node->node_name ) { + foreach ( $this->state->stack_of_open_elements->walk_up( $current_node ) as $parent ) { + break; + } + if ( $parent && 'OPTGROUP' === $parent->node_name ) { + $this->state->stack_of_open_elements->pop(); + } + } + + if ( $this->state->stack_of_open_elements->current_node_is( 'OPTGROUP' ) ) { + $this->state->stack_of_open_elements->pop(); + return true; + } + + // Parse error: ignore the token. + return $this->step(); + + /* + * > An end tag whose tag name is "option" + */ + case '-OPTION': + if ( $this->state->stack_of_open_elements->current_node_is( 'OPTION' ) ) { + $this->state->stack_of_open_elements->pop(); + return true; + } + + // Parse error: ignore the token. + return $this->step(); + + /* + * > An end tag whose tag name is "select" + * > A start tag whose tag name is "select" + * + * > It just gets treated like an end tag. + */ + case '-SELECT': + case '+SELECT': + if ( ! $this->state->stack_of_open_elements->has_element_in_select_scope( 'SELECT' ) ) { + // Parse error: ignore the token. + return $this->step(); + } + $this->state->stack_of_open_elements->pop_until( 'SELECT' ); + $this->reset_insertion_mode(); + return true; + + /* + * > A start tag whose tag name is one of: "input", "keygen", "textarea" + * + * All three of these tags are considered a parse error when found in this insertion mode. + */ + case '+INPUT': + case '+KEYGEN': + case '+TEXTAREA': + if ( ! $this->state->stack_of_open_elements->has_element_in_select_scope( 'SELECT' ) ) { + // Ignore the token. + return $this->step(); + } + $this->state->stack_of_open_elements->pop_until( 'SELECT' ); + $this->reset_insertion_mode(); + return $this->step( self::REPROCESS_CURRENT_NODE ); + + /* + * > A start tag whose tag name is one of: "script", "template" + * > An end tag whose tag name is "template" + */ + case '+SCRIPT': + case '+TEMPLATE': + case '-TEMPLATE': + return $this->step_in_head(); + } + + /* + * > Anything else + * > Parse error: ignore the token. + */ + return $this->step(); + } + + /** + * Parses next element in the 'in select in table' insertion mode. + * + * This internal function performs the 'in select in table' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-inselectintable + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_select_in_table(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'in template' insertion mode. + * + * This internal function performs the 'in template' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-intemplate + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_template(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'after body' insertion mode. + * + * This internal function performs the 'after body' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-afterbody + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_after_body(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'in frameset' insertion mode. + * + * This internal function performs the 'in frameset' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-inframeset + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_frameset(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'after frameset' insertion mode. + * + * This internal function performs the 'after frameset' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-afterframeset + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_after_frameset(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'after after body' insertion mode. + * + * This internal function performs the 'after after body' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#the-after-after-body-insertion-mode + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_after_after_body(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'after after frameset' insertion mode. + * + * This internal function performs the 'after after frameset' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#the-after-after-frameset-insertion-mode + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_after_after_frameset(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /** + * Parses next element in the 'in foreign content' insertion mode. + * + * This internal function performs the 'in foreign content' insertion mode + * logic for the generalized WP_HTML_Processor::step() function. + * + * @since 6.7.0 Stub implementation. + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#parsing-main-inforeign + * @see WP_HTML_Processor::step + * + * @return bool Whether an element was found. + */ + private function step_in_foreign_content(): bool { + $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." ); + } + + /* + * Internal helpers + */ + + /** + * Creates a new bookmark for the currently-matched token and returns the generated name. + * + * @since 6.4.0 + * @since 6.5.0 Renamed from bookmark_tag() to bookmark_token(). + * + * @throws Exception When unable to allocate requested bookmark. + * + * @return string|false Name of created bookmark, or false if unable to create. + */ + private function bookmark_token() { + if ( ! parent::set_bookmark( ++$this->bookmark_counter ) ) { + $this->last_error = self::ERROR_EXCEEDED_MAX_BOOKMARKS; + throw new Exception( 'could not allocate bookmark' ); + } + + return "{$this->bookmark_counter}"; + } + + /* + * HTML semantic overrides for Tag Processor + */ + + /** + * Returns the uppercase name of the matched tag. + * + * The semantic rules for HTML specify that certain tags be reprocessed + * with a different tag name. Because of this, the tag name presented + * by the HTML Processor may differ from the one reported by the HTML + * Tag Processor, which doesn't apply these semantic rules. + * + * Example: + * + * $processor = new WP_HTML_Tag_Processor( '<div class="test">Test</div>' ); + * $processor->next_tag() === true; + * $processor->get_tag() === 'DIV'; + * + * $processor->next_tag() === false; + * $processor->get_tag() === null; + * + * @since 6.4.0 + * + * @return string|null Name of currently matched tag in input HTML, or `null` if none found. + */ + public function get_tag(): ?string { + if ( null !== $this->last_error ) { + return null; + } + + if ( $this->is_virtual() ) { + return $this->current_element->token->node_name; + } + + $tag_name = parent::get_tag(); + + switch ( $tag_name ) { + case 'IMAGE': + /* + * > A start tag whose tag name is "image" + * > Change the token's tag name to "img" and reprocess it. (Don't ask.) + */ + return 'IMG'; + + default: + return $tag_name; + } + } + + /** + * Indicates if the currently matched tag contains the self-closing flag. + * + * No HTML elements ought to have the self-closing flag and for those, the self-closing + * flag will be ignored. For void elements this is benign because they "self close" + * automatically. For non-void HTML elements though problems will appear if someone + * intends to use a self-closing element in place of that element with an empty body. + * For HTML foreign elements and custom elements the self-closing flag determines if + * they self-close or not. + * + * This function does not determine if a tag is self-closing, + * but only if the self-closing flag is present in the syntax. + * + * @since 6.6.0 Subclassed for the HTML Processor. + * + * @return bool Whether the currently matched tag contains the self-closing flag. + */ + public function has_self_closing_flag(): bool { + return $this->is_virtual() ? false : parent::has_self_closing_flag(); + } + + /** + * Returns the node name represented by the token. + * + * This matches the DOM API value `nodeName`. Some values + * are static, such as `#text` for a text node, while others + * are dynamically generated from the token itself. + * + * Dynamic names: + * - Uppercase tag name for tag matches. + * - `html` for DOCTYPE declarations. + * + * Note that if the Tag Processor is not matched on a token + * then this function will return `null`, either because it + * hasn't yet found a token or because it reached the end + * of the document without matching a token. + * + * @since 6.6.0 Subclassed for the HTML Processor. + * + * @return string|null Name of the matched token. + */ + public function get_token_name(): ?string { + return $this->is_virtual() + ? $this->current_element->token->node_name + : parent::get_token_name(); + } + + /** + * Indicates the kind of matched token, if any. + * + * This differs from `get_token_name()` in that it always + * returns a static string indicating the type, whereas + * `get_token_name()` may return values derived from the + * token itself, such as a tag name or processing + * instruction tag. + * + * Possible values: + * - `#tag` when matched on a tag. + * - `#text` when matched on a text node. + * - `#cdata-section` when matched on a CDATA node. + * - `#comment` when matched on a comment. + * - `#doctype` when matched on a DOCTYPE declaration. + * - `#presumptuous-tag` when matched on an empty tag closer. + * - `#funky-comment` when matched on a funky comment. + * + * @since 6.6.0 Subclassed for the HTML Processor. + * + * @return string|null What kind of token is matched, or null. + */ + public function get_token_type(): ?string { + if ( $this->is_virtual() ) { + /* + * This logic comes from the Tag Processor. + * + * @todo It would be ideal not to repeat this here, but it's not clearly + * better to allow passing a token name to `get_token_type()`. + */ + $node_name = $this->current_element->token->node_name; + $starting_char = $node_name[0]; + if ( 'A' <= $starting_char && 'Z' >= $starting_char ) { + return '#tag'; + } + + if ( 'html' === $node_name ) { + return '#doctype'; + } + + return $node_name; + } + + return parent::get_token_type(); + } + + /** + * Returns the value of a requested attribute from a matched tag opener if that attribute exists. + * + * Example: + * + * $p = WP_HTML_Processor::create_fragment( '<div enabled class="test" data-test-id="14">Test</div>' ); + * $p->next_token() === true; + * $p->get_attribute( 'data-test-id' ) === '14'; + * $p->get_attribute( 'enabled' ) === true; + * $p->get_attribute( 'aria-label' ) === null; + * + * $p->next_tag() === false; + * $p->get_attribute( 'class' ) === null; + * + * @since 6.6.0 Subclassed for HTML Processor. + * + * @param string $name Name of attribute whose value is requested. + * @return string|true|null Value of attribute or `null` if not available. Boolean attributes return `true`. + */ + public function get_attribute( $name ) { + return $this->is_virtual() ? null : parent::get_attribute( $name ); + } + + /** + * Updates or creates a new attribute on the currently matched tag with the passed value. + * + * For boolean attributes special handling is provided: + * - When `true` is passed as the value, then only the attribute name is added to the tag. + * - When `false` is passed, the attribute gets removed if it existed before. + * + * For string attributes, the value is escaped using the `esc_attr` function. + * + * @since 6.6.0 Subclassed for the HTML Processor. + * + * @param string $name The attribute name to target. + * @param string|bool $value The new attribute value. + * @return bool Whether an attribute value was set. + */ + public function set_attribute( $name, $value ): bool { + return $this->is_virtual() ? false : parent::set_attribute( $name, $value ); + } + + /** + * Remove an attribute from the currently-matched tag. + * + * @since 6.6.0 Subclassed for HTML Processor. + * + * @param string $name The attribute name to remove. + * @return bool Whether an attribute was removed. + */ + public function remove_attribute( $name ): bool { + return $this->is_virtual() ? false : parent::remove_attribute( $name ); + } + + /** + * Gets lowercase names of all attributes matching a given prefix in the current tag. + * + * Note that matching is case-insensitive. This is in accordance with the spec: + * + * > There must never be two or more attributes on + * > the same start tag whose names are an ASCII + * > case-insensitive match for each other. + * - HTML 5 spec + * + * Example: + * + * $p = new WP_HTML_Tag_Processor( '<div data-ENABLED class="test" DATA-test-id="14">Test</div>' ); + * $p->next_tag( array( 'class_name' => 'test' ) ) === true; + * $p->get_attribute_names_with_prefix( 'data-' ) === array( 'data-enabled', 'data-test-id' ); + * + * $p->next_tag() === false; + * $p->get_attribute_names_with_prefix( 'data-' ) === null; + * + * @since 6.6.0 Subclassed for the HTML Processor. + * + * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive + * + * @param string $prefix Prefix of requested attribute names. + * @return array|null List of attribute names, or `null` when no tag opener is matched. + */ + public function get_attribute_names_with_prefix( $prefix ): ?array { + return $this->is_virtual() ? null : parent::get_attribute_names_with_prefix( $prefix ); + } + + /** + * Adds a new class name to the currently matched tag. + * + * @since 6.6.0 Subclassed for the HTML Processor. + * + * @param string $class_name The class name to add. + * @return bool Whether the class was set to be added. + */ + public function add_class( $class_name ): bool { + return $this->is_virtual() ? false : parent::add_class( $class_name ); + } + + /** + * Removes a class name from the currently matched tag. + * + * @since 6.6.0 Subclassed for the HTML Processor. + * + * @param string $class_name The class name to remove. + * @return bool Whether the class was set to be removed. + */ + public function remove_class( $class_name ): bool { + return $this->is_virtual() ? false : parent::remove_class( $class_name ); + } + + /** + * Returns if a matched tag contains the given ASCII case-insensitive class name. + * + * @since 6.6.0 Subclassed for the HTML Processor. + * + * @param string $wanted_class Look for this CSS class name, ASCII case-insensitive. + * @return bool|null Whether the matched tag contains the given class name, or null if not matched. + */ + public function has_class( $wanted_class ): ?bool { + return $this->is_virtual() ? null : parent::has_class( $wanted_class ); + } + + /** + * Generator for a foreach loop to step through each class name for the matched tag. + * + * This generator function is designed to be used inside a "foreach" loop. + * + * Example: + * + * $p = WP_HTML_Processor::create_fragment( "<div class='free <egg<\tlang-en'>" ); + * $p->next_tag(); + * foreach ( $p->class_list() as $class_name ) { + * echo "{$class_name} "; + * } + * // Outputs: "free <egg> lang-en " + * + * @since 6.6.0 Subclassed for the HTML Processor. + */ + public function class_list() { + return $this->is_virtual() ? null : parent::class_list(); + } + + /** + * Returns the modifiable text for a matched token, or an empty string. + * + * Modifiable text is text content that may be read and changed without + * changing the HTML structure of the document around it. This includes + * the contents of `#text` nodes in the HTML as well as the inner + * contents of HTML comments, Processing Instructions, and others, even + * though these nodes aren't part of a parsed DOM tree. They also contain + * the contents of SCRIPT and STYLE tags, of TEXTAREA tags, and of any + * other section in an HTML document which cannot contain HTML markup (DATA). + * + * If a token has no modifiable text then an empty string is returned to + * avoid needless crashing or type errors. An empty string does not mean + * that a token has modifiable text, and a token with modifiable text may + * have an empty string (e.g. a comment with no contents). + * + * @since 6.6.0 Subclassed for the HTML Processor. + * + * @return string + */ + public function get_modifiable_text(): string { + return $this->is_virtual() ? '' : parent::get_modifiable_text(); + } + + /** + * Indicates what kind of comment produced the comment node. + * + * Because there are different kinds of HTML syntax which produce + * comments, the Tag Processor tracks and exposes this as a type + * for the comment. Nominally only regular HTML comments exist as + * they are commonly known, but a number of unrelated syntax errors + * also produce comments. + * + * @see self::COMMENT_AS_ABRUPTLY_CLOSED_COMMENT + * @see self::COMMENT_AS_CDATA_LOOKALIKE + * @see self::COMMENT_AS_INVALID_HTML + * @see self::COMMENT_AS_HTML_COMMENT + * @see self::COMMENT_AS_PI_NODE_LOOKALIKE + * + * @since 6.6.0 Subclassed for the HTML Processor. + * + * @return string|null + */ + public function get_comment_type(): ?string { + return $this->is_virtual() ? null : parent::get_comment_type(); + } + + /** + * Removes a bookmark that is no longer needed. + * + * Releasing a bookmark frees up the small + * performance overhead it requires. + * + * @since 6.4.0 + * + * @param string $bookmark_name Name of the bookmark to remove. + * @return bool Whether the bookmark already existed before removal. + */ + public function release_bookmark( $bookmark_name ): bool { + return parent::release_bookmark( "_{$bookmark_name}" ); + } + + /** + * Moves the internal cursor in the HTML Processor to a given bookmark's location. + * + * Be careful! Seeking backwards to a previous location resets the parser to the + * start of the document and reparses the entire contents up until it finds the + * sought-after bookmarked location. + * + * In order to prevent accidental infinite loops, there's a + * maximum limit on the number of times seek() can be called. + * + * @throws Exception When unable to allocate a bookmark for the next token in the input HTML document. + * + * @since 6.4.0 + * + * @param string $bookmark_name Jump to the place in the document identified by this bookmark name. + * @return bool Whether the internal cursor was successfully moved to the bookmark's location. + */ + public function seek( $bookmark_name ): bool { + // Flush any pending updates to the document before beginning. + $this->get_updated_html(); + + $actual_bookmark_name = "_{$bookmark_name}"; + $processor_started_at = $this->state->current_token + ? $this->bookmarks[ $this->state->current_token->bookmark_name ]->start + : 0; + $bookmark_starts_at = $this->bookmarks[ $actual_bookmark_name ]->start; + $direction = $bookmark_starts_at > $processor_started_at ? 'forward' : 'backward'; + + /* + * If seeking backwards, it's possible that the sought-after bookmark exists within an element + * which has been closed before the current cursor; in other words, it has already been removed + * from the stack of open elements. This means that it's insufficient to simply pop off elements + * from the stack of open elements which appear after the bookmarked location and then jump to + * that location, as the elements which were open before won't be re-opened. + * + * In order to maintain consistency, the HTML Processor rewinds to the start of the document + * and reparses everything until it finds the sought-after bookmark. + * + * There are potentially better ways to do this: cache the parser state for each bookmark and + * restore it when seeking; store an immutable and idempotent register of where elements open + * and close. + * + * If caching the parser state it will be essential to properly maintain the cached stack of + * open elements and active formatting elements when modifying the document. This could be a + * tedious and time-consuming process as well, and so for now will not be performed. + * + * It may be possible to track bookmarks for where elements open and close, and in doing so + * be able to quickly recalculate breadcrumbs for any element in the document. It may even + * be possible to remove the stack of open elements and compute it on the fly this way. + * If doing this, the parser would need to track the opening and closing locations for all + * tokens in the breadcrumb path for any and all bookmarks. By utilizing bookmarks themselves + * this list could be automatically maintained while modifying the document. Finding the + * breadcrumbs would then amount to traversing that list from the start until the token + * being inspected. Once an element closes, if there are no bookmarks pointing to locations + * within that element, then all of these locations may be forgotten to save on memory use + * and computation time. + */ + if ( 'backward' === $direction ) { + /* + * Instead of clearing the parser state and starting fresh, calling the stack methods + * maintains the proper flags in the parser. + */ + foreach ( $this->state->stack_of_open_elements->walk_up() as $item ) { + if ( 'context-node' === $item->bookmark_name ) { + break; + } + + $this->state->stack_of_open_elements->remove_node( $item ); + } + + foreach ( $this->state->active_formatting_elements->walk_up() as $item ) { + if ( 'context-node' === $item->bookmark_name ) { + break; + } + + $this->state->active_formatting_elements->remove_node( $item ); + } + + parent::seek( 'context-node' ); + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_BODY; + $this->state->frameset_ok = true; + $this->element_queue = array(); + $this->current_element = null; + + if ( isset( $this->context_node ) ) { + $this->breadcrumbs = array_slice( $this->breadcrumbs, 0, 2 ); + } else { + $this->breadcrumbs = array(); + } + } + + // When moving forwards, reparse the document until reaching the same location as the original bookmark. + if ( $bookmark_starts_at === $this->bookmarks[ $this->state->current_token->bookmark_name ]->start ) { + return true; + } + + while ( $this->next_token() ) { + if ( $bookmark_starts_at === $this->bookmarks[ $this->state->current_token->bookmark_name ]->start ) { + while ( isset( $this->current_element ) && Gutenberg_HTML_Stack_Event_6_7::POP === $this->current_element->operation ) { + $this->current_element = array_shift( $this->element_queue ); + } + return true; + } + } + + return false; + } + + /** + * Sets a bookmark in the HTML document. + * + * Bookmarks represent specific places or tokens in the HTML + * document, such as a tag opener or closer. When applying + * edits to a document, such as setting an attribute, the + * text offsets of that token may shift; the bookmark is + * kept updated with those shifts and remains stable unless + * the entire span of text in which the token sits is removed. + * + * Release bookmarks when they are no longer needed. + * + * Example: + * + * <main><h2>Surprising fact you may not know!</h2></main> + * ^ ^ + * \-|-- this `H2` opener bookmark tracks the token + * + * <main class="clickbait"><h2>Surprising fact you may no… + * ^ ^ + * \-|-- it shifts with edits + * + * Bookmarks provide the ability to seek to a previously-scanned + * place in the HTML document. This avoids the need to re-scan + * the entire document. + * + * Example: + * + * <ul><li>One</li><li>Two</li><li>Three</li></ul> + * ^^^^ + * want to note this last item + * + * $p = new WP_HTML_Tag_Processor( $html ); + * $in_list = false; + * while ( $p->next_tag( array( 'tag_closers' => $in_list ? 'visit' : 'skip' ) ) ) { + * if ( 'UL' === $p->get_tag() ) { + * if ( $p->is_tag_closer() ) { + * $in_list = false; + * $p->set_bookmark( 'resume' ); + * if ( $p->seek( 'last-li' ) ) { + * $p->add_class( 'last-li' ); + * } + * $p->seek( 'resume' ); + * $p->release_bookmark( 'last-li' ); + * $p->release_bookmark( 'resume' ); + * } else { + * $in_list = true; + * } + * } + * + * if ( 'LI' === $p->get_tag() ) { + * $p->set_bookmark( 'last-li' ); + * } + * } + * + * Bookmarks intentionally hide the internal string offsets + * to which they refer. They are maintained internally as + * updates are applied to the HTML document and therefore + * retain their "position" - the location to which they + * originally pointed. The inability to use bookmarks with + * functions like `substr` is therefore intentional to guard + * against accidentally breaking the HTML. + * + * Because bookmarks allocate memory and require processing + * for every applied update, they are limited and require + * a name. They should not be created with programmatically-made + * names, such as "li_{$index}" with some loop. As a general + * rule they should only be created with string-literal names + * like "start-of-section" or "last-paragraph". + * + * Bookmarks are a powerful tool to enable complicated behavior. + * Consider double-checking that you need this tool if you are + * reaching for it, as inappropriate use could lead to broken + * HTML structure or unwanted processing overhead. + * + * @since 6.4.0 + * + * @param string $bookmark_name Identifies this particular bookmark. + * @return bool Whether the bookmark was successfully created. + */ + public function set_bookmark( $bookmark_name ): bool { + return parent::set_bookmark( "_{$bookmark_name}" ); + } + + /** + * Checks whether a bookmark with the given name exists. + * + * @since 6.5.0 + * + * @param string $bookmark_name Name to identify a bookmark that potentially exists. + * @return bool Whether that bookmark exists. + */ + public function has_bookmark( $bookmark_name ): bool { + return parent::has_bookmark( "_{$bookmark_name}" ); + } + + /* + * HTML Parsing Algorithms + */ + + /** + * Closes a P element. + * + * @since 6.4.0 + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#close-a-p-element + */ + private function close_a_p_element(): void { + $this->generate_implied_end_tags( 'P' ); + $this->state->stack_of_open_elements->pop_until( 'P' ); + } + + /** + * Closes elements that have implied end tags. + * + * @since 6.4.0 + * @since 6.7.0 Full spec support. + * + * @see https://html.spec.whatwg.org/#generate-implied-end-tags + * + * @param string|null $except_for_this_element Perform as if this element doesn't exist in the stack of open elements. + */ + private function generate_implied_end_tags( ?string $except_for_this_element = null ): void { + $elements_with_implied_end_tags = array( + 'DD', + 'DT', + 'LI', + 'OPTGROUP', + 'OPTION', + 'P', + 'RB', + 'RP', + 'RT', + 'RTC', + ); + + $no_exclusions = ! isset( $except_for_this_element ); + + while ( + ( $no_exclusions || ! $this->state->stack_of_open_elements->current_node_is( $except_for_this_element ) ) && + in_array( $this->state->stack_of_open_elements->current_node()->node_name, $elements_with_implied_end_tags, true ) + ) { + $this->state->stack_of_open_elements->pop(); + } + } + + /** + * Closes elements that have implied end tags, thoroughly. + * + * See the HTML specification for an explanation why this is + * different from generating end tags in the normal sense. + * + * @since 6.4.0 + * @since 6.7.0 Full spec support. + * + * @see WP_HTML_Processor::generate_implied_end_tags + * @see https://html.spec.whatwg.org/#generate-implied-end-tags + */ + private function generate_implied_end_tags_thoroughly(): void { + $elements_with_implied_end_tags = array( + 'CAPTION', + 'COLGROUP', + 'DD', + 'DT', + 'LI', + 'OPTGROUP', + 'OPTION', + 'P', + 'RB', + 'RP', + 'RT', + 'RTC', + 'TBODY', + 'TD', + 'TFOOT', + 'TH', + 'THEAD', + 'TR', + ); + + while ( in_array( $this->state->stack_of_open_elements->current_node()->node_name, $elements_with_implied_end_tags, true ) ) { + $this->state->stack_of_open_elements->pop(); + } + } + + /** + * Reconstructs the active formatting elements. + * + * > This has the effect of reopening all the formatting elements that were opened + * > in the current body, cell, or caption (whichever is youngest) that haven't + * > been explicitly closed. + * + * @since 6.4.0 + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#reconstruct-the-active-formatting-elements + * + * @return bool Whether any formatting elements needed to be reconstructed. + */ + private function reconstruct_active_formatting_elements(): bool { + /* + * > If there are no entries in the list of active formatting elements, then there is nothing + * > to reconstruct; stop this algorithm. + */ + if ( 0 === $this->state->active_formatting_elements->count() ) { + return false; + } + + $last_entry = $this->state->active_formatting_elements->current_node(); + if ( + + /* + * > If the last (most recently added) entry in the list of active formatting elements is a marker; + * > stop this algorithm. + */ + 'marker' === $last_entry->node_name || + + /* + * > If the last (most recently added) entry in the list of active formatting elements is an + * > element that is in the stack of open elements, then there is nothing to reconstruct; + * > stop this algorithm. + */ + $this->state->stack_of_open_elements->contains_node( $last_entry ) + ) { + return false; + } + + $this->bail( 'Cannot reconstruct active formatting elements when advancing and rewinding is required.' ); + } + + /** + * Runs the reset the insertion mode appropriately algorithm. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/multipage/parsing.html#reset-the-insertion-mode-appropriately + */ + public function reset_insertion_mode(): void { + // Set the first node. + $first_node = null; + foreach ( $this->state->stack_of_open_elements->walk_down() as $first_node ) { + break; + } + + /* + * > 1. Let _last_ be false. + */ + $last = false; + foreach ( $this->state->stack_of_open_elements->walk_up() as $node ) { + /* + * > 2. Let _node_ be the last node in the stack of open elements. + * > 3. _Loop_: If _node_ is the first node in the stack of open elements, then set _last_ + * > to true, and, if the parser was created as part of the HTML fragment parsing + * > algorithm (fragment case), set node to the context element passed to + * > that algorithm. + * > … + */ + if ( $node === $first_node ) { + $last = true; + if ( isset( $this->context_node ) ) { + $node = $this->context_node; + } + } + + switch ( $node->node_name ) { + /* + * > 4. If node is a `select` element, run these substeps: + * > 1. If _last_ is true, jump to the step below labeled done. + * > 2. Let _ancestor_ be _node_. + * > 3. _Loop_: If _ancestor_ is the first node in the stack of open elements, + * > jump to the step below labeled done. + * > 4. Let ancestor be the node before ancestor in the stack of open elements. + * > … + * > 7. Jump back to the step labeled _loop_. + * > 8. _Done_: Switch the insertion mode to "in select" and return. + */ + case 'SELECT': + if ( ! $last ) { + foreach ( $this->state->stack_of_open_elements->walk_up( $node ) as $ancestor ) { + switch ( $ancestor->node_name ) { + /* + * > 5. If _ancestor_ is a `template` node, jump to the step below + * > labeled _done_. + */ + case 'TEMPLATE': + break 2; + + /* + * > 6. If _ancestor_ is a `table` node, switch the insertion mode to + * > "in select in table" and return. + */ + case 'TABLE': + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_SELECT_IN_TABLE; + return; + } + } + } + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_SELECT; + return; + + /* + * > 5. If _node_ is a `td` or `th` element and _last_ is false, then switch the + * > insertion mode to "in cell" and return. + */ + case 'TD': + case 'TH': + if ( ! $last ) { + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_CELL; + return; + } + break; + + /* + * > 6. If _node_ is a `tr` element, then switch the insertion mode to "in row" + * > and return. + */ + case 'TR': + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_ROW; + return; + + /* + * > 7. If _node_ is a `tbody`, `thead`, or `tfoot` element, then switch the + * > insertion mode to "in table body" and return. + */ + case 'TBODY': + case 'THEAD': + case 'TFOOT': + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_TABLE_BODY; + return; + + /* + * > 8. If _node_ is a `caption` element, then switch the insertion mode to + * > "in caption" and return. + */ + case 'CAPTION': + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_CAPTION; + return; + + /* + * > 9. If _node_ is a `colgroup` element, then switch the insertion mode to + * > "in column group" and return. + */ + case 'COLGROUP': + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_COLUMN_GROUP; + return; + + /* + * > 10. If _node_ is a `table` element, then switch the insertion mode to + * > "in table" and return. + */ + case 'TABLE': + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_TABLE; + return; + + /* + * > 11. If _node_ is a `template` element, then switch the insertion mode to the + * > current template insertion mode and return. + */ + case 'TEMPLATE': + $this->state->insertion_mode = end( $this->state->stack_of_template_insertion_modes ); + return; + + /* + * > 12. If _node_ is a `head` element and _last_ is false, then switch the + * > insertion mode to "in head" and return. + */ + case 'HEAD': + if ( ! $last ) { + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_HEAD; + return; + } + break; + + /* + * > 13. If _node_ is a `body` element, then switch the insertion mode to "in body" + * > and return. + */ + case 'BODY': + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_BODY; + return; + + /* + * > 14. If _node_ is a `frameset` element, then switch the insertion mode to + * > "in frameset" and return. (fragment case) + */ + case 'FRAMESET': + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_FRAMESET; + return; + + /* + * > 15. If _node_ is an `html` element, run these substeps: + * > 1. If the head element pointer is null, switch the insertion mode to + * > "before head" and return. (fragment case) + * > 2. Otherwise, the head element pointer is not null, switch the insertion + * > mode to "after head" and return. + */ + case 'HTML': + $this->state->insertion_mode = isset( $this->state->head_element ) + ? Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_AFTER_HEAD + : Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_BEFORE_HEAD; + return; + } + } + + /* + * > 16. If _last_ is true, then switch the insertion mode to "in body" + * > and return. (fragment case) + * + * This is only reachable if `$last` is true, as per the fragment parsing case. + */ + $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_7::INSERTION_MODE_IN_BODY; + } + + /** + * Runs the adoption agency algorithm. + * + * @since 6.4.0 + * + * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. + * + * @see https://html.spec.whatwg.org/#adoption-agency-algorithm + */ + private function run_adoption_agency_algorithm(): void { + $budget = 1000; + $subject = $this->get_tag(); + $current_node = $this->state->stack_of_open_elements->current_node(); + + if ( + // > If the current node is an HTML element whose tag name is subject + $current_node && $subject === $current_node->node_name && + // > the current node is not in the list of active formatting elements + ! $this->state->active_formatting_elements->contains_node( $current_node ) + ) { + $this->state->stack_of_open_elements->pop(); + return; + } + + $outer_loop_counter = 0; + while ( $budget-- > 0 ) { + if ( $outer_loop_counter++ >= 8 ) { + return; + } + + /* + * > Let formatting element be the last element in the list of active formatting elements that: + * > - is between the end of the list and the last marker in the list, + * > if any, or the start of the list otherwise, + * > - and has the tag name subject. + */ + $formatting_element = null; + foreach ( $this->state->active_formatting_elements->walk_up() as $item ) { + if ( 'marker' === $item->node_name ) { + break; + } + + if ( $subject === $item->node_name ) { + $formatting_element = $item; + break; + } + } + + // > If there is no such element, then return and instead act as described in the "any other end tag" entry above. + if ( null === $formatting_element ) { + $this->bail( 'Cannot run adoption agency when "any other end tag" is required.' ); + } + + // > If formatting element is not in the stack of open elements, then this is a parse error; remove the element from the list, and return. + if ( ! $this->state->stack_of_open_elements->contains_node( $formatting_element ) ) { + $this->state->active_formatting_elements->remove_node( $formatting_element ); + return; + } + + // > If formatting element is in the stack of open elements, but the element is not in scope, then this is a parse error; return. + if ( ! $this->state->stack_of_open_elements->has_element_in_scope( $formatting_element->node_name ) ) { + return; + } + + /* + * > Let furthest block be the topmost node in the stack of open elements that is lower in the stack + * > than formatting element, and is an element in the special category. There might not be one. + */ + $is_above_formatting_element = true; + $furthest_block = null; + foreach ( $this->state->stack_of_open_elements->walk_down() as $item ) { + if ( $is_above_formatting_element && $formatting_element->bookmark_name !== $item->bookmark_name ) { + continue; + } + + if ( $is_above_formatting_element ) { + $is_above_formatting_element = false; + continue; + } + + if ( self::is_special( $item->node_name ) ) { + $furthest_block = $item; + break; + } + } + + /* + * > If there is no furthest block, then the UA must first pop all the nodes from the bottom of the + * > stack of open elements, from the current node up to and including formatting element, then + * > remove formatting element from the list of active formatting elements, and finally return. + */ + if ( null === $furthest_block ) { + foreach ( $this->state->stack_of_open_elements->walk_up() as $item ) { + $this->state->stack_of_open_elements->pop(); + + if ( $formatting_element->bookmark_name === $item->bookmark_name ) { + $this->state->active_formatting_elements->remove_node( $formatting_element ); + return; + } + } + } + + $this->bail( 'Cannot extract common ancestor in adoption agency algorithm.' ); + } + + $this->bail( 'Cannot run adoption agency when looping required.' ); + } + + /** + * Inserts an HTML element on the stack of open elements. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#insert-a-foreign-element + * + * @param WP_HTML_Token $token Name of bookmark pointing to element in original input HTML. + */ + private function insert_html_element( Gutenberg_HTML_Token_6_7 $token ): void { + $this->state->stack_of_open_elements->push( $token ); + } + + /* + * HTML Specification Helpers + */ + + /** + * Returns whether an element of a given name is in the HTML special category. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#special + * + * @param string $tag_name Name of element to check. + * @return bool Whether the element of the given name is in the special category. + */ + public static function is_special( $tag_name ): bool { + $tag_name = strtoupper( $tag_name ); + + return ( + 'ADDRESS' === $tag_name || + 'APPLET' === $tag_name || + 'AREA' === $tag_name || + 'ARTICLE' === $tag_name || + 'ASIDE' === $tag_name || + 'BASE' === $tag_name || + 'BASEFONT' === $tag_name || + 'BGSOUND' === $tag_name || + 'BLOCKQUOTE' === $tag_name || + 'BODY' === $tag_name || + 'BR' === $tag_name || + 'BUTTON' === $tag_name || + 'CAPTION' === $tag_name || + 'CENTER' === $tag_name || + 'COL' === $tag_name || + 'COLGROUP' === $tag_name || + 'DD' === $tag_name || + 'DETAILS' === $tag_name || + 'DIR' === $tag_name || + 'DIV' === $tag_name || + 'DL' === $tag_name || + 'DT' === $tag_name || + 'EMBED' === $tag_name || + 'FIELDSET' === $tag_name || + 'FIGCAPTION' === $tag_name || + 'FIGURE' === $tag_name || + 'FOOTER' === $tag_name || + 'FORM' === $tag_name || + 'FRAME' === $tag_name || + 'FRAMESET' === $tag_name || + 'H1' === $tag_name || + 'H2' === $tag_name || + 'H3' === $tag_name || + 'H4' === $tag_name || + 'H5' === $tag_name || + 'H6' === $tag_name || + 'HEAD' === $tag_name || + 'HEADER' === $tag_name || + 'HGROUP' === $tag_name || + 'HR' === $tag_name || + 'HTML' === $tag_name || + 'IFRAME' === $tag_name || + 'IMG' === $tag_name || + 'INPUT' === $tag_name || + 'KEYGEN' === $tag_name || + 'LI' === $tag_name || + 'LINK' === $tag_name || + 'LISTING' === $tag_name || + 'MAIN' === $tag_name || + 'MARQUEE' === $tag_name || + 'MENU' === $tag_name || + 'META' === $tag_name || + 'NAV' === $tag_name || + 'NOEMBED' === $tag_name || + 'NOFRAMES' === $tag_name || + 'NOSCRIPT' === $tag_name || + 'OBJECT' === $tag_name || + 'OL' === $tag_name || + 'P' === $tag_name || + 'PARAM' === $tag_name || + 'PLAINTEXT' === $tag_name || + 'PRE' === $tag_name || + 'SCRIPT' === $tag_name || + 'SEARCH' === $tag_name || + 'SECTION' === $tag_name || + 'SELECT' === $tag_name || + 'SOURCE' === $tag_name || + 'STYLE' === $tag_name || + 'SUMMARY' === $tag_name || + 'TABLE' === $tag_name || + 'TBODY' === $tag_name || + 'TD' === $tag_name || + 'TEMPLATE' === $tag_name || + 'TEXTAREA' === $tag_name || + 'TFOOT' === $tag_name || + 'TH' === $tag_name || + 'THEAD' === $tag_name || + 'TITLE' === $tag_name || + 'TR' === $tag_name || + 'TRACK' === $tag_name || + 'UL' === $tag_name || + 'WBR' === $tag_name || + 'XMP' === $tag_name || + + // MathML. + 'MI' === $tag_name || + 'MO' === $tag_name || + 'MN' === $tag_name || + 'MS' === $tag_name || + 'MTEXT' === $tag_name || + 'ANNOTATION-XML' === $tag_name || + + // SVG. + 'FOREIGNOBJECT' === $tag_name || + 'DESC' === $tag_name || + 'TITLE' === $tag_name + ); + } + + /** + * Returns whether a given element is an HTML Void Element + * + * > area, base, br, col, embed, hr, img, input, link, meta, source, track, wbr + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#void-elements + * + * @param string $tag_name Name of HTML tag to check. + * @return bool Whether the given tag is an HTML Void Element. + */ + public static function is_void( $tag_name ): bool { + $tag_name = strtoupper( $tag_name ); + + return ( + 'AREA' === $tag_name || + 'BASE' === $tag_name || + 'BASEFONT' === $tag_name || // Obsolete but still treated as void. + 'BGSOUND' === $tag_name || // Obsolete but still treated as void. + 'BR' === $tag_name || + 'COL' === $tag_name || + 'EMBED' === $tag_name || + 'FRAME' === $tag_name || + 'HR' === $tag_name || + 'IMG' === $tag_name || + 'INPUT' === $tag_name || + 'KEYGEN' === $tag_name || // Obsolete but still treated as void. + 'LINK' === $tag_name || + 'META' === $tag_name || + 'PARAM' === $tag_name || // Obsolete but still treated as void. + 'SOURCE' === $tag_name || + 'TRACK' === $tag_name || + 'WBR' === $tag_name + ); + } + + /* + * Constants that would pollute the top of the class if they were found there. + */ + + /** + * Indicates that the next HTML token should be parsed and processed. + * + * @since 6.4.0 + * + * @var string + */ + const PROCESS_NEXT_NODE = 'process-next-node'; + + /** + * Indicates that the current HTML token should be reprocessed in the newly-selected insertion mode. + * + * @since 6.4.0 + * + * @var string + */ + const REPROCESS_CURRENT_NODE = 'reprocess-current-node'; + + /** + * Indicates that the current HTML token should be processed without advancing the parser. + * + * @since 6.5.0 + * + * @var string + */ + const PROCESS_CURRENT_NODE = 'process-current-node'; + + /** + * Indicates that the parser encountered unsupported markup and has bailed. + * + * @since 6.4.0 + * + * @var string + */ + const ERROR_UNSUPPORTED = 'unsupported'; + + /** + * Indicates that the parser encountered more HTML tokens than it + * was able to process and has bailed. + * + * @since 6.4.0 + * + * @var string + */ + const ERROR_EXCEEDED_MAX_BOOKMARKS = 'exceeded-max-bookmarks'; + + /** + * Unlock code that must be passed into the constructor to create this class. + * + * This class extends the WP_HTML_Tag_Processor, which has a public class + * constructor. Therefore, it's not possible to have a private constructor here. + * + * This unlock code is used to ensure that anyone calling the constructor is + * doing so with a full understanding that it's intended to be a private API. + * + * @access private + */ + const CONSTRUCTOR_UNLOCK_CODE = 'Use WP_HTML_Processor::create_fragment() instead of calling the class constructor directly.'; +} diff --git a/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-processor-state-6-7.php b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-processor-state-6-7.php new file mode 100644 index 00000000000000..5a3941c415dd79 --- /dev/null +++ b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-processor-state-6-7.php @@ -0,0 +1,417 @@ +<?php +/** + * HTML API: WP_HTML_Processor_State class + * + * @package WordPress + * @subpackage HTML-API + * @since 6.4.0 + */ + +/** + * Core class used by the HTML processor during HTML parsing + * for managing the internal parsing state. + * + * This class is designed for internal use by the HTML processor. + * + * @since 6.4.0 + * + * @access private + * + * @see WP_HTML_Processor + */ +class Gutenberg_HTML_Processor_State_6_7 { + /* + * Insertion mode constants. + * + * These constants exist and are named to make it easier to + * discover and recognize the supported insertion modes in + * the parser. + * + * Out of all the possible insertion modes, only those + * supported by the parser are listed here. As support + * is added to the parser for more modes, add them here + * following the same naming and value pattern. + * + * @see https://html.spec.whatwg.org/#the-insertion-mode + */ + + /** + * Initial insertion mode for full HTML parser. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#the-initial-insertion-mode + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_INITIAL = 'insertion-mode-initial'; + + /** + * Before HTML insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#the-before-html-insertion-mode + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_BEFORE_HTML = 'insertion-mode-before-html'; + + /** + * Before head insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-beforehead + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_BEFORE_HEAD = 'insertion-mode-before-head'; + + /** + * In head insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-inhead + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_HEAD = 'insertion-mode-in-head'; + + /** + * In head noscript insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-inheadnoscript + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_HEAD_NOSCRIPT = 'insertion-mode-in-head-noscript'; + + /** + * After head insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-afterhead + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_AFTER_HEAD = 'insertion-mode-after-head'; + + /** + * In body insertion mode for full HTML parser. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-inbody + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_BODY = 'insertion-mode-in-body'; + + /** + * In table insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-intable + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_TABLE = 'insertion-mode-in-table'; + + /** + * In table text insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-intabletext + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_TABLE_TEXT = 'insertion-mode-in-table-text'; + + /** + * In caption insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-incaption + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_CAPTION = 'insertion-mode-in-caption'; + + /** + * In column group insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-incolumngroup + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_COLUMN_GROUP = 'insertion-mode-in-column-group'; + + /** + * In table body insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-intablebody + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_TABLE_BODY = 'insertion-mode-in-table-body'; + + /** + * In row insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-inrow + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_ROW = 'insertion-mode-in-row'; + + /** + * In cell insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-incell + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_CELL = 'insertion-mode-in-cell'; + + /** + * In select insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-inselect + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_SELECT = 'insertion-mode-in-select'; + + /** + * In select in table insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-inselectintable + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_SELECT_IN_TABLE = 'insertion-mode-in-select-in-table'; + + /** + * In template insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-intemplate + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_TEMPLATE = 'insertion-mode-in-template'; + + /** + * After body insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-afterbody + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_AFTER_BODY = 'insertion-mode-after-body'; + + /** + * In frameset insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-inframeset + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_FRAMESET = 'insertion-mode-in-frameset'; + + /** + * After frameset insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-afterframeset + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_AFTER_FRAMESET = 'insertion-mode-after-frameset'; + + /** + * After after body insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#the-after-after-body-insertion-mode + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_AFTER_AFTER_BODY = 'insertion-mode-after-after-body'; + + /** + * After after frameset insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#the-after-after-frameset-insertion-mode + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_AFTER_AFTER_FRAMESET = 'insertion-mode-after-after-frameset'; + + /** + * In foreign content insertion mode for full HTML parser. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-inforeign + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_FOREIGN_CONTENT = 'insertion-mode-in-foreign-content'; + + /** + * The stack of template insertion modes. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/#the-insertion-mode:stack-of-template-insertion-modes + * + * @var array<string> + */ + public $stack_of_template_insertion_modes = array(); + + /** + * Tracks open elements while scanning HTML. + * + * This property is initialized in the constructor and never null. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#stack-of-open-elements + * + * @var WP_HTML_Open_Elements + */ + public $stack_of_open_elements; + + /** + * Tracks open formatting elements, used to handle mis-nested formatting element tags. + * + * This property is initialized in the constructor and never null. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#list-of-active-formatting-elements + * + * @var WP_HTML_Active_Formatting_Elements + */ + public $active_formatting_elements; + + /** + * Refers to the currently-matched tag, if any. + * + * @since 6.4.0 + * + * @var WP_HTML_Token|null + */ + public $current_token = null; + + /** + * Tree construction insertion mode. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#insertion-mode + * + * @var string + */ + public $insertion_mode = self::INSERTION_MODE_INITIAL; + + /** + * Context node initializing fragment parser, if created as a fragment parser. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#concept-frag-parse-context + * + * @var [string, array]|null + */ + public $context_node = null; + + /** + * HEAD element pointer. + * + * @since 6.7.0 + * + * @see https://html.spec.whatwg.org/multipage/parsing.html#head-element-pointer + * + * @var WP_HTML_Token|null + */ + public $head_element = null; + + /** + * The frameset-ok flag indicates if a `FRAMESET` element is allowed in the current state. + * + * > The frameset-ok flag is set to "ok" when the parser is created. It is set to "not ok" after certain tokens are seen. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#frameset-ok-flag + * + * @var bool + */ + public $frameset_ok = true; + + /** + * Constructor - creates a new and empty state value. + * + * @since 6.4.0 + * + * @see WP_HTML_Processor + */ + public function __construct() { + $this->stack_of_open_elements = new Gutenberg_HTML_Open_Elements_6_7(); + $this->active_formatting_elements = new Gutenberg_HTML_Active_Formatting_Elements_6_7(); + } +} diff --git a/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-span-6-7.php b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-span-6-7.php new file mode 100644 index 00000000000000..5a55d9f5568746 --- /dev/null +++ b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-span-6-7.php @@ -0,0 +1,56 @@ +<?php +/** + * HTML API: WP_HTML_Span class + * + * @package WordPress + * @subpackage HTML-API + * @since 6.2.0 + */ + +/** + * Core class used by the HTML tag processor to represent a textual span + * inside an HTML document. + * + * This is a two-tuple in disguise, used to avoid the memory overhead + * involved in using an array for the same purpose. + * + * This class is for internal usage of the WP_HTML_Tag_Processor class. + * + * @access private + * @since 6.2.0 + * @since 6.5.0 Replaced `end` with `length` to more closely align with `substr()`. + * + * @see WP_HTML_Tag_Processor + */ +class Gutenberg_HTML_Span_6_7 { + /** + * Byte offset into document where span begins. + * + * @since 6.2.0 + * + * @var int + */ + public $start; + + /** + * Byte length of this span. + * + * @since 6.5.0 + * + * @var int + */ + public $length; + + /** + * Constructor. + * + * @since 6.2.0 + * + * @param int $start Byte offset into document where replacement span begins. + * @param int $length Byte length of span. + */ + public function __construct( int $start, int $length ) { + $this->start = $start; + $this->length = $length; + } +} diff --git a/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-stack-event-6-7.php b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-stack-event-6-7.php new file mode 100644 index 00000000000000..30a8024b1c07c5 --- /dev/null +++ b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-stack-event-6-7.php @@ -0,0 +1,82 @@ +<?php +/** + * HTML API: WP_HTML_Stack_Event class + * + * @package WordPress + * @subpackage HTML-API + * @since 6.6.0 + */ + +/** + * Core class used by the HTML Processor as a record for stack operations. + * + * This class is for internal usage of the WP_HTML_Processor class. + * + * @access private + * @since 6.6.0 + * + * @see WP_HTML_Processor + */ +class Gutenberg_HTML_Stack_Event_6_7 { + /** + * Refers to popping an element off of the stack of open elements. + * + * @since 6.6.0 + */ + const POP = 'pop'; + + /** + * Refers to pushing an element onto the stack of open elements. + * + * @since 6.6.0 + */ + const PUSH = 'push'; + + /** + * References the token associated with the stack push event, + * even if this is a pop event for that element. + * + * @since 6.6.0 + * + * @var WP_HTML_Token + */ + public $token; + + /** + * Indicates which kind of stack operation this event represents. + * + * May be one of the class constants. + * + * @since 6.6.0 + * + * @see self::POP + * @see self::PUSH + * + * @var string + */ + public $operation; + + /** + * Indicates if the stack element is a real or virtual node. + * + * @since 6.6.0 + * + * @var string + */ + public $provenance; + + /** + * Constructor function. + * + * @since 6.6.0 + * + * @param WP_HTML_Token $token Token associated with stack event, always an opening token. + * @param string $operation One of self::PUSH or self::POP. + * @param string $provenance "virtual" or "real". + */ + public function __construct( Gutenberg_HTML_Token_6_7 $token, string $operation, string $provenance ) { + $this->token = $token; + $this->operation = $operation; + $this->provenance = $provenance; + } +} diff --git a/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-tag-processor-6-7.php b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-tag-processor-6-7.php new file mode 100644 index 00000000000000..0377706d5eaa63 --- /dev/null +++ b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-tag-processor-6-7.php @@ -0,0 +1,3521 @@ +<?php +/** + * HTML API: WP_HTML_Tag_Processor class + * + * Scans through an HTML document to find specific tags, then + * transforms those tags by adding, removing, or updating the + * values of the HTML attributes within that tag (opener). + * + * Does not fully parse HTML or _recurse_ into the HTML structure + * Instead this scans linearly through a document and only parses + * the HTML tag openers. + * + * ### Possible future direction for this module + * + * - Prune the whitespace when removing classes/attributes: e.g. "a b c" -> "c" not " c". + * This would increase the size of the changes for some operations but leave more + * natural-looking output HTML. + * + * @package WordPress + * @subpackage HTML-API + * @since 6.2.0 + */ + +/** + * Core class used to modify attributes in an HTML document for tags matching a query. + * + * ## Usage + * + * Use of this class requires three steps: + * + * 1. Create a new class instance with your input HTML document. + * 2. Find the tag(s) you are looking for. + * 3. Request changes to the attributes in those tag(s). + * + * Example: + * + * $tags = new WP_HTML_Tag_Processor( $html ); + * if ( $tags->next_tag( 'option' ) ) { + * $tags->set_attribute( 'selected', true ); + * } + * + * ### Finding tags + * + * The `next_tag()` function moves the internal cursor through + * your input HTML document until it finds a tag meeting any of + * the supplied restrictions in the optional query argument. If + * no argument is provided then it will find the next HTML tag, + * regardless of what kind it is. + * + * If you want to _find whatever the next tag is_: + * + * $tags->next_tag(); + * + * | Goal | Query | + * |-----------------------------------------------------------|---------------------------------------------------------------------------------| + * | Find any tag. | `$tags->next_tag();` | + * | Find next image tag. | `$tags->next_tag( array( 'tag_name' => 'img' ) );` | + * | Find next image tag (without passing the array). | `$tags->next_tag( 'img' );` | + * | Find next tag containing the `fullwidth` CSS class. | `$tags->next_tag( array( 'class_name' => 'fullwidth' ) );` | + * | Find next image tag containing the `fullwidth` CSS class. | `$tags->next_tag( array( 'tag_name' => 'img', 'class_name' => 'fullwidth' ) );` | + * + * If a tag was found meeting your criteria then `next_tag()` + * will return `true` and you can proceed to modify it. If it + * returns `false`, however, it failed to find the tag and + * moved the cursor to the end of the file. + * + * Once the cursor reaches the end of the file the processor + * is done and if you want to reach an earlier tag you will + * need to recreate the processor and start over, as it's + * unable to back up or move in reverse. + * + * See the section on bookmarks for an exception to this + * no-backing-up rule. + * + * #### Custom queries + * + * Sometimes it's necessary to further inspect an HTML tag than + * the query syntax here permits. In these cases one may further + * inspect the search results using the read-only functions + * provided by the processor or external state or variables. + * + * Example: + * + * // Paint up to the first five DIV or SPAN tags marked with the "jazzy" style. + * $remaining_count = 5; + * while ( $remaining_count > 0 && $tags->next_tag() ) { + * if ( + * ( 'DIV' === $tags->get_tag() || 'SPAN' === $tags->get_tag() ) && + * 'jazzy' === $tags->get_attribute( 'data-style' ) + * ) { + * $tags->add_class( 'theme-style-everest-jazz' ); + * $remaining_count--; + * } + * } + * + * `get_attribute()` will return `null` if the attribute wasn't present + * on the tag when it was called. It may return `""` (the empty string) + * in cases where the attribute was present but its value was empty. + * For boolean attributes, those whose name is present but no value is + * given, it will return `true` (the only way to set `false` for an + * attribute is to remove it). + * + * #### When matching fails + * + * When `next_tag()` returns `false` it could mean different things: + * + * - The requested tag wasn't found in the input document. + * - The input document ended in the middle of an HTML syntax element. + * + * When a document ends in the middle of a syntax element it will pause + * the processor. This is to make it possible in the future to extend the + * input document and proceed - an important requirement for chunked + * streaming parsing of a document. + * + * Example: + * + * $processor = new WP_HTML_Tag_Processor( 'This <div is="a" partial="token' ); + * false === $processor->next_tag(); + * + * If a special element (see next section) is encountered but no closing tag + * is found it will count as an incomplete tag. The parser will pause as if + * the opening tag were incomplete. + * + * Example: + * + * $processor = new WP_HTML_Tag_Processor( '<style>// there could be more styling to come' ); + * false === $processor->next_tag(); + * + * $processor = new WP_HTML_Tag_Processor( '<style>// this is everything</style><div>' ); + * true === $processor->next_tag( 'DIV' ); + * + * #### Special elements + * + * Some HTML elements are handled in a special way; their start and end tags + * act like a void tag. These are special because their contents can't contain + * HTML markup. Everything inside these elements is handled in a special way + * and content that _appears_ like HTML tags inside of them isn't. There can + * be no nesting in these elements. + * + * In the following list, "raw text" means that all of the content in the HTML + * until the matching closing tag is treated verbatim without any replacements + * and without any parsing. + * + * - IFRAME allows no content but requires a closing tag. + * - NOEMBED (deprecated) content is raw text. + * - NOFRAMES (deprecated) content is raw text. + * - SCRIPT content is plaintext apart from legacy rules allowing `</script>` inside an HTML comment. + * - STYLE content is raw text. + * - TITLE content is plain text but character references are decoded. + * - TEXTAREA content is plain text but character references are decoded. + * - XMP (deprecated) content is raw text. + * + * ### Modifying HTML attributes for a found tag + * + * Once you've found the start of an opening tag you can modify + * any number of the attributes on that tag. You can set a new + * value for an attribute, remove the entire attribute, or do + * nothing and move on to the next opening tag. + * + * Example: + * + * if ( $tags->next_tag( array( 'class_name' => 'wp-group-block' ) ) ) { + * $tags->set_attribute( 'title', 'This groups the contained content.' ); + * $tags->remove_attribute( 'data-test-id' ); + * } + * + * If `set_attribute()` is called for an existing attribute it will + * overwrite the existing value. Similarly, calling `remove_attribute()` + * for a non-existing attribute has no effect on the document. Both + * of these methods are safe to call without knowing if a given attribute + * exists beforehand. + * + * ### Modifying CSS classes for a found tag + * + * The tag processor treats the `class` attribute as a special case. + * Because it's a common operation to add or remove CSS classes, this + * interface adds helper methods to make that easier. + * + * As with attribute values, adding or removing CSS classes is a safe + * operation that doesn't require checking if the attribute or class + * exists before making changes. If removing the only class then the + * entire `class` attribute will be removed. + * + * Example: + * + * // from `<span>Yippee!</span>` + * // to `<span class="is-active">Yippee!</span>` + * $tags->add_class( 'is-active' ); + * + * // from `<span class="excited">Yippee!</span>` + * // to `<span class="excited is-active">Yippee!</span>` + * $tags->add_class( 'is-active' ); + * + * // from `<span class="is-active heavy-accent">Yippee!</span>` + * // to `<span class="is-active heavy-accent">Yippee!</span>` + * $tags->add_class( 'is-active' ); + * + * // from `<input type="text" class="is-active rugby not-disabled" length="24">` + * // to `<input type="text" class="is-active not-disabled" length="24"> + * $tags->remove_class( 'rugby' ); + * + * // from `<input type="text" class="rugby" length="24">` + * // to `<input type="text" length="24"> + * $tags->remove_class( 'rugby' ); + * + * // from `<input type="text" length="24">` + * // to `<input type="text" length="24"> + * $tags->remove_class( 'rugby' ); + * + * When class changes are enqueued but a direct change to `class` is made via + * `set_attribute` then the changes to `set_attribute` (or `remove_attribute`) + * will take precedence over those made through `add_class` and `remove_class`. + * + * ### Bookmarks + * + * While scanning through the input HTMl document it's possible to set + * a named bookmark when a particular tag is found. Later on, after + * continuing to scan other tags, it's possible to `seek` to one of + * the set bookmarks and then proceed again from that point forward. + * + * Because bookmarks create processing overhead one should avoid + * creating too many of them. As a rule, create only bookmarks + * of known string literal names; avoid creating "mark_{$index}" + * and so on. It's fine from a performance standpoint to create a + * bookmark and update it frequently, such as within a loop. + * + * $total_todos = 0; + * while ( $p->next_tag( array( 'tag_name' => 'UL', 'class_name' => 'todo' ) ) ) { + * $p->set_bookmark( 'list-start' ); + * while ( $p->next_tag( array( 'tag_closers' => 'visit' ) ) ) { + * if ( 'UL' === $p->get_tag() && $p->is_tag_closer() ) { + * $p->set_bookmark( 'list-end' ); + * $p->seek( 'list-start' ); + * $p->set_attribute( 'data-contained-todos', (string) $total_todos ); + * $total_todos = 0; + * $p->seek( 'list-end' ); + * break; + * } + * + * if ( 'LI' === $p->get_tag() && ! $p->is_tag_closer() ) { + * $total_todos++; + * } + * } + * } + * + * ## Tokens and finer-grained processing. + * + * It's possible to scan through every lexical token in the + * HTML document using the `next_token()` function. This + * alternative form takes no argument and provides no built-in + * query syntax. + * + * Example: + * + * $title = '(untitled)'; + * $text = ''; + * while ( $processor->next_token() ) { + * switch ( $processor->get_token_name() ) { + * case '#text': + * $text .= $processor->get_modifiable_text(); + * break; + * + * case 'BR': + * $text .= "\n"; + * break; + * + * case 'TITLE': + * $title = $processor->get_modifiable_text(); + * break; + * } + * } + * return trim( "# {$title}\n\n{$text}" ); + * + * ### Tokens and _modifiable text_. + * + * #### Special "atomic" HTML elements. + * + * Not all HTML elements are able to contain other elements inside of them. + * For instance, the contents inside a TITLE element are plaintext (except + * that character references like & will be decoded). This means that + * if the string `<img>` appears inside a TITLE element, then it's not an + * image tag, but rather it's text describing an image tag. Likewise, the + * contents of a SCRIPT or STYLE element are handled entirely separately in + * a browser than the contents of other elements because they represent a + * different language than HTML. + * + * For these elements the Tag Processor treats the entire sequence as one, + * from the opening tag, including its contents, through its closing tag. + * This means that the it's not possible to match the closing tag for a + * SCRIPT element unless it's unexpected; the Tag Processor already matched + * it when it found the opening tag. + * + * The inner contents of these elements are that element's _modifiable text_. + * + * The special elements are: + * - `SCRIPT` whose contents are treated as raw plaintext but supports a legacy + * style of including JavaScript inside of HTML comments to avoid accidentally + * closing the SCRIPT from inside a JavaScript string. E.g. `console.log( '</script>' )`. + * - `TITLE` and `TEXTAREA` whose contents are treated as plaintext and then any + * character references are decoded. E.g. `1 < 2 < 3` becomes `1 < 2 < 3`. + * - `IFRAME`, `NOSCRIPT`, `NOEMBED`, `NOFRAME`, `STYLE` whose contents are treated as + * raw plaintext and left as-is. E.g. `1 < 2 < 3` remains `1 < 2 < 3`. + * + * #### Other tokens with modifiable text. + * + * There are also non-elements which are void/self-closing in nature and contain + * modifiable text that is part of that individual syntax token itself. + * + * - `#text` nodes, whose entire token _is_ the modifiable text. + * - HTML comments and tokens that become comments due to some syntax error. The + * text for these tokens is the portion of the comment inside of the syntax. + * E.g. for `<!-- comment -->` the text is `" comment "` (note the spaces are included). + * - `CDATA` sections, whose text is the content inside of the section itself. E.g. for + * `<![CDATA[some content]]>` the text is `"some content"` (with restrictions [1]). + * - "Funky comments," which are a special case of invalid closing tags whose name is + * invalid. The text for these nodes is the text that a browser would transform into + * an HTML comment when parsing. E.g. for `</%post_author>` the text is `%post_author`. + * - `DOCTYPE` declarations like `<DOCTYPE html>` which have no closing tag. + * - XML Processing instruction nodes like `<?wp __( "Like" ); ?>` (with restrictions [2]). + * - The empty end tag `</>` which is ignored in the browser and DOM. + * + * [1]: There are no CDATA sections in HTML. When encountering `<![CDATA[`, everything + * until the next `>` becomes a bogus HTML comment, meaning there can be no CDATA + * section in an HTML document containing `>`. The Tag Processor will first find + * all valid and bogus HTML comments, and then if the comment _would_ have been a + * CDATA section _were they to exist_, it will indicate this as the type of comment. + * + * [2]: XML allows a broader range of characters in a processing instruction's target name + * and disallows "xml" as a name, since it's special. The Tag Processor only recognizes + * target names with an ASCII-representable subset of characters. It also exhibits the + * same constraint as with CDATA sections, in that `>` cannot exist within the token + * since Processing Instructions do no exist within HTML and their syntax transforms + * into a bogus comment in the DOM. + * + * ## Design and limitations + * + * The Tag Processor is designed to linearly scan HTML documents and tokenize + * HTML tags and their attributes. It's designed to do this as efficiently as + * possible without compromising parsing integrity. Therefore it will be + * slower than some methods of modifying HTML, such as those incorporating + * over-simplified PCRE patterns, but will not introduce the defects and + * failures that those methods bring in, which lead to broken page renders + * and often to security vulnerabilities. On the other hand, it will be faster + * than full-blown HTML parsers such as DOMDocument and use considerably + * less memory. It requires a negligible memory overhead, enough to consider + * it a zero-overhead system. + * + * The performance characteristics are maintained by avoiding tree construction + * and semantic cleanups which are specified in HTML5. Because of this, for + * example, it's not possible for the Tag Processor to associate any given + * opening tag with its corresponding closing tag, or to return the inner markup + * inside an element. Systems may be built on top of the Tag Processor to do + * this, but the Tag Processor is and should be constrained so it can remain an + * efficient, low-level, and reliable HTML scanner. + * + * The Tag Processor's design incorporates a "garbage-in-garbage-out" philosophy. + * HTML5 specifies that certain invalid content be transformed into different forms + * for display, such as removing null bytes from an input document and replacing + * invalid characters with the Unicode replacement character `U+FFFD` (visually "�"). + * Where errors or transformations exist within the HTML5 specification, the Tag Processor + * leaves those invalid inputs untouched, passing them through to the final browser + * to handle. While this implies that certain operations will be non-spec-compliant, + * such as reading the value of an attribute with invalid content, it also preserves a + * simplicity and efficiency for handling those error cases. + * + * Most operations within the Tag Processor are designed to minimize the difference + * between an input and output document for any given change. For example, the + * `add_class` and `remove_class` methods preserve whitespace and the class ordering + * within the `class` attribute; and when encountering tags with duplicated attributes, + * the Tag Processor will leave those invalid duplicate attributes where they are but + * update the proper attribute which the browser will read for parsing its value. An + * exception to this rule is that all attribute updates store their values as + * double-quoted strings, meaning that attributes on input with single-quoted or + * unquoted values will appear in the output with double-quotes. + * + * ### Scripting Flag + * + * The Tag Processor parses HTML with the "scripting flag" disabled. This means + * that it doesn't run any scripts while parsing the page. In a browser with + * JavaScript enabled, for example, the script can change the parse of the + * document as it loads. On the server, however, evaluating JavaScript is not + * only impractical, but also unwanted. + * + * Practically this means that the Tag Processor will descend into NOSCRIPT + * elements and process its child tags. Were the scripting flag enabled, such + * as in a typical browser, the contents of NOSCRIPT are skipped entirely. + * + * This allows the HTML API to process the content that will be presented in + * a browser when scripting is disabled, but it offers a different view of a + * page than most browser sessions will experience. E.g. the tags inside the + * NOSCRIPT disappear. + * + * ### Text Encoding + * + * The Tag Processor assumes that the input HTML document is encoded with a + * text encoding compatible with 7-bit ASCII's '<', '>', '&', ';', '/', '=', + * "'", '"', 'a' - 'z', 'A' - 'Z', and the whitespace characters ' ', tab, + * carriage-return, newline, and form-feed. + * + * In practice, this includes almost every single-byte encoding as well as + * UTF-8. Notably, however, it does not include UTF-16. If providing input + * that's incompatible, then convert the encoding beforehand. + * + * @since 6.2.0 + * @since 6.2.1 Fix: Support for various invalid comments; attribute updates are case-insensitive. + * @since 6.3.2 Fix: Skip HTML-like content inside rawtext elements such as STYLE. + * @since 6.5.0 Pauses processor when input ends in an incomplete syntax token. + * Introduces "special" elements which act like void elements, e.g. TITLE, STYLE. + * Allows scanning through all tokens and processing modifiable text, where applicable. + */ +class Gutenberg_HTML_Tag_Processor_6_7 { + /** + * The maximum number of bookmarks allowed to exist at + * any given time. + * + * @since 6.2.0 + * @var int + * + * @see WP_HTML_Tag_Processor::set_bookmark() + */ + const MAX_BOOKMARKS = 10; + + /** + * Maximum number of times seek() can be called. + * Prevents accidental infinite loops. + * + * @since 6.2.0 + * @var int + * + * @see WP_HTML_Tag_Processor::seek() + */ + const MAX_SEEK_OPS = 1000; + + /** + * The HTML document to parse. + * + * @since 6.2.0 + * @var string + */ + protected $html; + + /** + * The last query passed to next_tag(). + * + * @since 6.2.0 + * @var array|null + */ + private $last_query; + + /** + * The tag name this processor currently scans for. + * + * @since 6.2.0 + * @var string|null + */ + private $sought_tag_name; + + /** + * The CSS class name this processor currently scans for. + * + * @since 6.2.0 + * @var string|null + */ + private $sought_class_name; + + /** + * The match offset this processor currently scans for. + * + * @since 6.2.0 + * @var int|null + */ + private $sought_match_offset; + + /** + * Whether to visit tag closers, e.g. </div>, when walking an input document. + * + * @since 6.2.0 + * @var bool + */ + private $stop_on_tag_closers; + + /** + * Specifies mode of operation of the parser at any given time. + * + * | State | Meaning | + * | ----------------|----------------------------------------------------------------------| + * | *Ready* | The parser is ready to run. | + * | *Complete* | There is nothing left to parse. | + * | *Incomplete* | The HTML ended in the middle of a token; nothing more can be parsed. | + * | *Matched tag* | Found an HTML tag; it's possible to modify its attributes. | + * | *Text node* | Found a #text node; this is plaintext and modifiable. | + * | *CDATA node* | Found a CDATA section; this is modifiable. | + * | *Comment* | Found a comment or bogus comment; this is modifiable. | + * | *Presumptuous* | Found an empty tag closer: `</>`. | + * | *Funky comment* | Found a tag closer with an invalid tag name; this is modifiable. | + * + * @since 6.5.0 + * + * @see WP_HTML_Tag_Processor::STATE_READY + * @see WP_HTML_Tag_Processor::STATE_COMPLETE + * @see WP_HTML_Tag_Processor::STATE_INCOMPLETE_INPUT + * @see WP_HTML_Tag_Processor::STATE_MATCHED_TAG + * @see WP_HTML_Tag_Processor::STATE_TEXT_NODE + * @see WP_HTML_Tag_Processor::STATE_CDATA_NODE + * @see WP_HTML_Tag_Processor::STATE_COMMENT + * @see WP_HTML_Tag_Processor::STATE_DOCTYPE + * @see WP_HTML_Tag_Processor::STATE_PRESUMPTUOUS_TAG + * @see WP_HTML_Tag_Processor::STATE_FUNKY_COMMENT + * + * @var string + */ + protected $parser_state = self::STATE_READY; + + /** + * What kind of syntax token became an HTML comment. + * + * Since there are many ways in which HTML syntax can create an HTML comment, + * this indicates which of those caused it. This allows the Tag Processor to + * represent more from the original input document than would appear in the DOM. + * + * @since 6.5.0 + * + * @var string|null + */ + protected $comment_type = null; + + /** + * How many bytes from the original HTML document have been read and parsed. + * + * This value points to the latest byte offset in the input document which + * has been already parsed. It is the internal cursor for the Tag Processor + * and updates while scanning through the HTML tokens. + * + * @since 6.2.0 + * @var int + */ + private $bytes_already_parsed = 0; + + /** + * Byte offset in input document where current token starts. + * + * Example: + * + * <div id="test">... + * 01234 + * - token starts at 0 + * + * @since 6.5.0 + * + * @var int|null + */ + private $token_starts_at; + + /** + * Byte length of current token. + * + * Example: + * + * <div id="test">... + * 012345678901234 + * - token length is 14 - 0 = 14 + * + * a <!-- comment --> is a token. + * 0123456789 123456789 123456789 + * - token length is 17 - 2 = 15 + * + * @since 6.5.0 + * + * @var int|null + */ + private $token_length; + + /** + * Byte offset in input document where current tag name starts. + * + * Example: + * + * <div id="test">... + * 01234 + * - tag name starts at 1 + * + * @since 6.2.0 + * + * @var int|null + */ + private $tag_name_starts_at; + + /** + * Byte length of current tag name. + * + * Example: + * + * <div id="test">... + * 01234 + * --- tag name length is 3 + * + * @since 6.2.0 + * + * @var int|null + */ + private $tag_name_length; + + /** + * Byte offset into input document where current modifiable text starts. + * + * @since 6.5.0 + * + * @var int + */ + private $text_starts_at; + + /** + * Byte length of modifiable text. + * + * @since 6.5.0 + * + * @var string + */ + private $text_length; + + /** + * Whether the current tag is an opening tag, e.g. <div>, or a closing tag, e.g. </div>. + * + * @var bool + */ + private $is_closing_tag; + + /** + * Lazily-built index of attributes found within an HTML tag, keyed by the attribute name. + * + * Example: + * + * // Supposing the parser is working through this content + * // and stops after recognizing the `id` attribute. + * // <div id="test-4" class=outline title="data:text/plain;base64=asdk3nk1j3fo8"> + * // ^ parsing will continue from this point. + * $this->attributes = array( + * 'id' => new WP_HTML_Attribute_Token( 'id', 9, 6, 5, 11, false ) + * ); + * + * // When picking up parsing again, or when asking to find the + * // `class` attribute we will continue and add to this array. + * $this->attributes = array( + * 'id' => new WP_HTML_Attribute_Token( 'id', 9, 6, 5, 11, false ), + * 'class' => new WP_HTML_Attribute_Token( 'class', 23, 7, 17, 13, false ) + * ); + * + * // Note that only the `class` attribute value is stored in the index. + * // That's because it is the only value used by this class at the moment. + * + * @since 6.2.0 + * @var WP_HTML_Attribute_Token[] + */ + private $attributes = array(); + + /** + * Tracks spans of duplicate attributes on a given tag, used for removing + * all copies of an attribute when calling `remove_attribute()`. + * + * @since 6.3.2 + * + * @var (WP_HTML_Span[])[]|null + */ + private $duplicate_attributes = null; + + /** + * Which class names to add or remove from a tag. + * + * These are tracked separately from attribute updates because they are + * semantically distinct, whereas this interface exists for the common + * case of adding and removing class names while other attributes are + * generally modified as with DOM `setAttribute` calls. + * + * When modifying an HTML document these will eventually be collapsed + * into a single `set_attribute( 'class', $changes )` call. + * + * Example: + * + * // Add the `wp-block-group` class, remove the `wp-group` class. + * $classname_updates = array( + * // Indexed by a comparable class name. + * 'wp-block-group' => WP_HTML_Tag_Processor::ADD_CLASS, + * 'wp-group' => WP_HTML_Tag_Processor::REMOVE_CLASS + * ); + * + * @since 6.2.0 + * @var bool[] + */ + private $classname_updates = array(); + + /** + * Tracks a semantic location in the original HTML which + * shifts with updates as they are applied to the document. + * + * @since 6.2.0 + * @var WP_HTML_Span[] + */ + protected $bookmarks = array(); + + const ADD_CLASS = true; + const REMOVE_CLASS = false; + const SKIP_CLASS = null; + + /** + * Lexical replacements to apply to input HTML document. + * + * "Lexical" in this class refers to the part of this class which + * operates on pure text _as text_ and not as HTML. There's a line + * between the public interface, with HTML-semantic methods like + * `set_attribute` and `add_class`, and an internal state that tracks + * text offsets in the input document. + * + * When higher-level HTML methods are called, those have to transform their + * operations (such as setting an attribute's value) into text diffing + * operations (such as replacing the sub-string from indices A to B with + * some given new string). These text-diffing operations are the lexical + * updates. + * + * As new higher-level methods are added they need to collapse their + * operations into these lower-level lexical updates since that's the + * Tag Processor's internal language of change. Any code which creates + * these lexical updates must ensure that they do not cross HTML syntax + * boundaries, however, so these should never be exposed outside of this + * class or any classes which intentionally expand its functionality. + * + * These are enqueued while editing the document instead of being immediately + * applied to avoid processing overhead, string allocations, and string + * copies when applying many updates to a single document. + * + * Example: + * + * // Replace an attribute stored with a new value, indices + * // sourced from the lazily-parsed HTML recognizer. + * $start = $attributes['src']->start; + * $length = $attributes['src']->length; + * $modifications[] = new WP_HTML_Text_Replacement( $start, $length, $new_value ); + * + * // Correspondingly, something like this will appear in this array. + * $lexical_updates = array( + * WP_HTML_Text_Replacement( 14, 28, 'https://my-site.my-domain/wp-content/uploads/2014/08/kittens.jpg' ) + * ); + * + * @since 6.2.0 + * @var WP_HTML_Text_Replacement[] + */ + protected $lexical_updates = array(); + + /** + * Tracks and limits `seek()` calls to prevent accidental infinite loops. + * + * @since 6.2.0 + * @var int + * + * @see WP_HTML_Tag_Processor::seek() + */ + protected $seek_count = 0; + + /** + * Constructor. + * + * @since 6.2.0 + * + * @param string $html HTML to process. + */ + public function __construct( $html ) { + $this->html = $html; + } + + /** + * Finds the next tag matching the $query. + * + * @since 6.2.0 + * @since 6.5.0 No longer processes incomplete tokens at end of document; pauses the processor at start of token. + * + * @param array|string|null $query { + * Optional. Which tag name to find, having which class, etc. Default is to find any tag. + * + * @type string|null $tag_name Which tag to find, or `null` for "any tag." + * @type int|null $match_offset Find the Nth tag matching all search criteria. + * 1 for "first" tag, 3 for "third," etc. + * Defaults to first tag. + * @type string|null $class_name Tag must contain this whole class name to match. + * @type string|null $tag_closers "visit" or "skip": whether to stop on tag closers, e.g. </div>. + * } + * @return bool Whether a tag was matched. + */ + public function next_tag( $query = null ): bool { + $this->parse_query( $query ); + $already_found = 0; + + do { + if ( false === $this->next_token() ) { + return false; + } + + if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { + continue; + } + + if ( $this->matches() ) { + ++$already_found; + } + } while ( $already_found < $this->sought_match_offset ); + + return true; + } + + /** + * Finds the next token in the HTML document. + * + * An HTML document can be viewed as a stream of tokens, + * where tokens are things like HTML tags, HTML comments, + * text nodes, etc. This method finds the next token in + * the HTML document and returns whether it found one. + * + * If it starts parsing a token and reaches the end of the + * document then it will seek to the start of the last + * token and pause, returning `false` to indicate that it + * failed to find a complete token. + * + * Possible token types, based on the HTML specification: + * + * - an HTML tag, whether opening, closing, or void. + * - a text node - the plaintext inside tags. + * - an HTML comment. + * - a DOCTYPE declaration. + * - a processing instruction, e.g. `<?xml version="1.0" ?>`. + * + * The Tag Processor currently only supports the tag token. + * + * @since 6.5.0 + * + * @return bool Whether a token was parsed. + */ + public function next_token(): bool { + return $this->base_class_next_token(); + } + + /** + * Internal method which finds the next token in the HTML document. + * + * This method is a protected internal function which implements the logic for + * finding the next token in a document. It exists so that the parser can update + * its state without affecting the location of the cursor in the document and + * without triggering subclass methods for things like `next_token()`, e.g. when + * applying patches before searching for the next token. + * + * @since 6.5.0 + * + * @access private + * + * @return bool Whether a token was parsed. + */ + private function base_class_next_token(): bool { + $was_at = $this->bytes_already_parsed; + $this->after_tag(); + + // Don't proceed if there's nothing more to scan. + if ( + self::STATE_COMPLETE === $this->parser_state || + self::STATE_INCOMPLETE_INPUT === $this->parser_state + ) { + return false; + } + + /* + * The next step in the parsing loop determines the parsing state; + * clear it so that state doesn't linger from the previous step. + */ + $this->parser_state = self::STATE_READY; + + if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { + $this->parser_state = self::STATE_COMPLETE; + return false; + } + + // Find the next tag if it exists. + if ( false === $this->parse_next_tag() ) { + if ( self::STATE_INCOMPLETE_INPUT === $this->parser_state ) { + $this->bytes_already_parsed = $was_at; + } + + return false; + } + + /* + * For legacy reasons the rest of this function handles tags and their + * attributes. If the processor has reached the end of the document + * or if it matched any other token then it should return here to avoid + * attempting to process tag-specific syntax. + */ + if ( + self::STATE_INCOMPLETE_INPUT !== $this->parser_state && + self::STATE_COMPLETE !== $this->parser_state && + self::STATE_MATCHED_TAG !== $this->parser_state + ) { + return true; + } + + // Parse all of its attributes. + while ( $this->parse_next_attribute() ) { + continue; + } + + // Ensure that the tag closes before the end of the document. + if ( + self::STATE_INCOMPLETE_INPUT === $this->parser_state || + $this->bytes_already_parsed >= strlen( $this->html ) + ) { + // Does this appropriately clear state (parsed attributes)? + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + $this->bytes_already_parsed = $was_at; + + return false; + } + + $tag_ends_at = strpos( $this->html, '>', $this->bytes_already_parsed ); + if ( false === $tag_ends_at ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + $this->bytes_already_parsed = $was_at; + + return false; + } + $this->parser_state = self::STATE_MATCHED_TAG; + $this->bytes_already_parsed = $tag_ends_at + 1; + $this->token_length = $this->bytes_already_parsed - $this->token_starts_at; + + /* + * For non-DATA sections which might contain text that looks like HTML tags but + * isn't, scan with the appropriate alternative mode. Looking at the first letter + * of the tag name as a pre-check avoids a string allocation when it's not needed. + */ + $t = $this->html[ $this->tag_name_starts_at ]; + if ( + $this->is_closing_tag || + ! ( + 'i' === $t || 'I' === $t || + 'n' === $t || 'N' === $t || + 's' === $t || 'S' === $t || + 't' === $t || 'T' === $t || + 'x' === $t || 'X' === $t + ) + ) { + return true; + } + + $tag_name = $this->get_tag(); + + /* + * Preserve the opening tag pointers, as these will be overwritten + * when finding the closing tag. They will be reset after finding + * the closing to tag to point to the opening of the special atomic + * tag sequence. + */ + $tag_name_starts_at = $this->tag_name_starts_at; + $tag_name_length = $this->tag_name_length; + $tag_ends_at = $this->token_starts_at + $this->token_length; + $attributes = $this->attributes; + $duplicate_attributes = $this->duplicate_attributes; + + // Find the closing tag if necessary. + $found_closer = false; + switch ( $tag_name ) { + case 'SCRIPT': + $found_closer = $this->skip_script_data(); + break; + + case 'TEXTAREA': + case 'TITLE': + $found_closer = $this->skip_rcdata( $tag_name ); + break; + + /* + * In the browser this list would include the NOSCRIPT element, + * but the Tag Processor is an environment with the scripting + * flag disabled, meaning that it needs to descend into the + * NOSCRIPT element to be able to properly process what will be + * sent to a browser. + * + * Note that this rule makes HTML5 syntax incompatible with XML, + * because the parsing of this token depends on client application. + * The NOSCRIPT element cannot be represented in the XHTML syntax. + */ + case 'IFRAME': + case 'NOEMBED': + case 'NOFRAMES': + case 'STYLE': + case 'XMP': + $found_closer = $this->skip_rawtext( $tag_name ); + break; + + // No other tags should be treated in their entirety here. + default: + return true; + } + + if ( ! $found_closer ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + $this->bytes_already_parsed = $was_at; + return false; + } + + /* + * The values here look like they reference the opening tag but they reference + * the closing tag instead. This is why the opening tag values were stored + * above in a variable. It reads confusingly here, but that's because the + * functions that skip the contents have moved all the internal cursors past + * the inner content of the tag. + */ + $this->token_starts_at = $was_at; + $this->token_length = $this->bytes_already_parsed - $this->token_starts_at; + $this->text_starts_at = $tag_ends_at; + $this->text_length = $this->tag_name_starts_at - $this->text_starts_at; + $this->tag_name_starts_at = $tag_name_starts_at; + $this->tag_name_length = $tag_name_length; + $this->attributes = $attributes; + $this->duplicate_attributes = $duplicate_attributes; + + return true; + } + + /** + * Whether the processor paused because the input HTML document ended + * in the middle of a syntax element, such as in the middle of a tag. + * + * Example: + * + * $processor = new WP_HTML_Tag_Processor( '<input type="text" value="Th' ); + * false === $processor->get_next_tag(); + * true === $processor->paused_at_incomplete_token(); + * + * @since 6.5.0 + * + * @return bool Whether the parse paused at the start of an incomplete token. + */ + public function paused_at_incomplete_token(): bool { + return self::STATE_INCOMPLETE_INPUT === $this->parser_state; + } + + /** + * Generator for a foreach loop to step through each class name for the matched tag. + * + * This generator function is designed to be used inside a "foreach" loop. + * + * Example: + * + * $p = new WP_HTML_Tag_Processor( "<div class='free <egg<\tlang-en'>" ); + * $p->next_tag(); + * foreach ( $p->class_list() as $class_name ) { + * echo "{$class_name} "; + * } + * // Outputs: "free <egg> lang-en " + * + * @since 6.4.0 + */ + public function class_list() { + if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { + return; + } + + /** @var string $class contains the string value of the class attribute, with character references decoded. */ + $class = $this->get_attribute( 'class' ); + + if ( ! is_string( $class ) ) { + return; + } + + $seen = array(); + + $at = 0; + while ( $at < strlen( $class ) ) { + // Skip past any initial boundary characters. + $at += strspn( $class, " \t\f\r\n", $at ); + if ( $at >= strlen( $class ) ) { + return; + } + + // Find the byte length until the next boundary. + $length = strcspn( $class, " \t\f\r\n", $at ); + if ( 0 === $length ) { + return; + } + + /* + * CSS class names are case-insensitive in the ASCII range. + * + * @see https://www.w3.org/TR/CSS2/syndata.html#x1 + */ + $name = strtolower( substr( $class, $at, $length ) ); + $at += $length; + + /* + * It's expected that the number of class names for a given tag is relatively small. + * Given this, it is probably faster overall to scan an array for a value rather + * than to use the class name as a key and check if it's a key of $seen. + */ + if ( in_array( $name, $seen, true ) ) { + continue; + } + + $seen[] = $name; + yield $name; + } + } + + + /** + * Returns if a matched tag contains the given ASCII case-insensitive class name. + * + * @since 6.4.0 + * + * @param string $wanted_class Look for this CSS class name, ASCII case-insensitive. + * @return bool|null Whether the matched tag contains the given class name, or null if not matched. + */ + public function has_class( $wanted_class ): ?bool { + if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { + return null; + } + + $wanted_class = strtolower( $wanted_class ); + + foreach ( $this->class_list() as $class_name ) { + if ( $class_name === $wanted_class ) { + return true; + } + } + + return false; + } + + + /** + * Sets a bookmark in the HTML document. + * + * Bookmarks represent specific places or tokens in the HTML + * document, such as a tag opener or closer. When applying + * edits to a document, such as setting an attribute, the + * text offsets of that token may shift; the bookmark is + * kept updated with those shifts and remains stable unless + * the entire span of text in which the token sits is removed. + * + * Release bookmarks when they are no longer needed. + * + * Example: + * + * <main><h2>Surprising fact you may not know!</h2></main> + * ^ ^ + * \-|-- this `H2` opener bookmark tracks the token + * + * <main class="clickbait"><h2>Surprising fact you may no… + * ^ ^ + * \-|-- it shifts with edits + * + * Bookmarks provide the ability to seek to a previously-scanned + * place in the HTML document. This avoids the need to re-scan + * the entire document. + * + * Example: + * + * <ul><li>One</li><li>Two</li><li>Three</li></ul> + * ^^^^ + * want to note this last item + * + * $p = new WP_HTML_Tag_Processor( $html ); + * $in_list = false; + * while ( $p->next_tag( array( 'tag_closers' => $in_list ? 'visit' : 'skip' ) ) ) { + * if ( 'UL' === $p->get_tag() ) { + * if ( $p->is_tag_closer() ) { + * $in_list = false; + * $p->set_bookmark( 'resume' ); + * if ( $p->seek( 'last-li' ) ) { + * $p->add_class( 'last-li' ); + * } + * $p->seek( 'resume' ); + * $p->release_bookmark( 'last-li' ); + * $p->release_bookmark( 'resume' ); + * } else { + * $in_list = true; + * } + * } + * + * if ( 'LI' === $p->get_tag() ) { + * $p->set_bookmark( 'last-li' ); + * } + * } + * + * Bookmarks intentionally hide the internal string offsets + * to which they refer. They are maintained internally as + * updates are applied to the HTML document and therefore + * retain their "position" - the location to which they + * originally pointed. The inability to use bookmarks with + * functions like `substr` is therefore intentional to guard + * against accidentally breaking the HTML. + * + * Because bookmarks allocate memory and require processing + * for every applied update, they are limited and require + * a name. They should not be created with programmatically-made + * names, such as "li_{$index}" with some loop. As a general + * rule they should only be created with string-literal names + * like "start-of-section" or "last-paragraph". + * + * Bookmarks are a powerful tool to enable complicated behavior. + * Consider double-checking that you need this tool if you are + * reaching for it, as inappropriate use could lead to broken + * HTML structure or unwanted processing overhead. + * + * @since 6.2.0 + * + * @param string $name Identifies this particular bookmark. + * @return bool Whether the bookmark was successfully created. + */ + public function set_bookmark( $name ): bool { + // It only makes sense to set a bookmark if the parser has paused on a concrete token. + if ( + self::STATE_COMPLETE === $this->parser_state || + self::STATE_INCOMPLETE_INPUT === $this->parser_state + ) { + return false; + } + + if ( ! array_key_exists( $name, $this->bookmarks ) && count( $this->bookmarks ) >= static::MAX_BOOKMARKS ) { + _doing_it_wrong( + __METHOD__, + __( 'Too many bookmarks: cannot create any more.' ), + '6.2.0' + ); + return false; + } + + $this->bookmarks[ $name ] = new Gutenberg_HTML_Span_6_7( $this->token_starts_at, $this->token_length ); + + return true; + } + + + /** + * Removes a bookmark that is no longer needed. + * + * Releasing a bookmark frees up the small + * performance overhead it requires. + * + * @param string $name Name of the bookmark to remove. + * @return bool Whether the bookmark already existed before removal. + */ + public function release_bookmark( $name ): bool { + if ( ! array_key_exists( $name, $this->bookmarks ) ) { + return false; + } + + unset( $this->bookmarks[ $name ] ); + + return true; + } + + /** + * Skips contents of generic rawtext elements. + * + * @since 6.3.2 + * + * @see https://html.spec.whatwg.org/#generic-raw-text-element-parsing-algorithm + * + * @param string $tag_name The uppercase tag name which will close the RAWTEXT region. + * @return bool Whether an end to the RAWTEXT region was found before the end of the document. + */ + private function skip_rawtext( string $tag_name ): bool { + /* + * These two functions distinguish themselves on whether character references are + * decoded, and since functionality to read the inner markup isn't supported, it's + * not necessary to implement these two functions separately. + */ + return $this->skip_rcdata( $tag_name ); + } + + /** + * Skips contents of RCDATA elements, namely title and textarea tags. + * + * @since 6.2.0 + * + * @see https://html.spec.whatwg.org/multipage/parsing.html#rcdata-state + * + * @param string $tag_name The uppercase tag name which will close the RCDATA region. + * @return bool Whether an end to the RCDATA region was found before the end of the document. + */ + private function skip_rcdata( string $tag_name ): bool { + $html = $this->html; + $doc_length = strlen( $html ); + $tag_length = strlen( $tag_name ); + + $at = $this->bytes_already_parsed; + + while ( false !== $at && $at < $doc_length ) { + $at = strpos( $this->html, '</', $at ); + $this->tag_name_starts_at = $at; + + // Fail if there is no possible tag closer. + if ( false === $at || ( $at + $tag_length ) >= $doc_length ) { + return false; + } + + $at += 2; + + /* + * Find a case-insensitive match to the tag name. + * + * Because tag names are limited to US-ASCII there is no + * need to perform any kind of Unicode normalization when + * comparing; any character which could be impacted by such + * normalization could not be part of a tag name. + */ + for ( $i = 0; $i < $tag_length; $i++ ) { + $tag_char = $tag_name[ $i ]; + $html_char = $html[ $at + $i ]; + + if ( $html_char !== $tag_char && strtoupper( $html_char ) !== $tag_char ) { + $at += $i; + continue 2; + } + } + + $at += $tag_length; + $this->bytes_already_parsed = $at; + + if ( $at >= strlen( $html ) ) { + return false; + } + + /* + * Ensure that the tag name terminates to avoid matching on + * substrings of a longer tag name. For example, the sequence + * "</textarearug" should not match for "</textarea" even + * though "textarea" is found within the text. + */ + $c = $html[ $at ]; + if ( ' ' !== $c && "\t" !== $c && "\r" !== $c && "\n" !== $c && '/' !== $c && '>' !== $c ) { + continue; + } + + while ( $this->parse_next_attribute() ) { + continue; + } + + $at = $this->bytes_already_parsed; + if ( $at >= strlen( $this->html ) ) { + return false; + } + + if ( '>' === $html[ $at ] ) { + $this->bytes_already_parsed = $at + 1; + return true; + } + + if ( $at + 1 >= strlen( $this->html ) ) { + return false; + } + + if ( '/' === $html[ $at ] && '>' === $html[ $at + 1 ] ) { + $this->bytes_already_parsed = $at + 2; + return true; + } + } + + return false; + } + + /** + * Skips contents of script tags. + * + * @since 6.2.0 + * + * @return bool Whether the script tag was closed before the end of the document. + */ + private function skip_script_data(): bool { + $state = 'unescaped'; + $html = $this->html; + $doc_length = strlen( $html ); + $at = $this->bytes_already_parsed; + + while ( false !== $at && $at < $doc_length ) { + $at += strcspn( $html, '-<', $at ); + + /* + * For all script states a "-->" transitions + * back into the normal unescaped script mode, + * even if that's the current state. + */ + if ( + $at + 2 < $doc_length && + '-' === $html[ $at ] && + '-' === $html[ $at + 1 ] && + '>' === $html[ $at + 2 ] + ) { + $at += 3; + $state = 'unescaped'; + continue; + } + + // Everything of interest past here starts with "<". + if ( $at + 1 >= $doc_length || '<' !== $html[ $at++ ] ) { + continue; + } + + /* + * Unlike with "-->", the "<!--" only transitions + * into the escaped mode if not already there. + * + * Inside the escaped modes it will be ignored; and + * should never break out of the double-escaped + * mode and back into the escaped mode. + * + * While this requires a mode change, it does not + * impact the parsing otherwise, so continue + * parsing after updating the state. + */ + if ( + $at + 2 < $doc_length && + '!' === $html[ $at ] && + '-' === $html[ $at + 1 ] && + '-' === $html[ $at + 2 ] + ) { + $at += 3; + $state = 'unescaped' === $state ? 'escaped' : $state; + continue; + } + + if ( '/' === $html[ $at ] ) { + $closer_potentially_starts_at = $at - 1; + $is_closing = true; + ++$at; + } else { + $is_closing = false; + } + + /* + * At this point the only remaining state-changes occur with the + * <script> and </script> tags; unless one of these appears next, + * proceed scanning to the next potential token in the text. + */ + if ( ! ( + $at + 6 < $doc_length && + ( 's' === $html[ $at ] || 'S' === $html[ $at ] ) && + ( 'c' === $html[ $at + 1 ] || 'C' === $html[ $at + 1 ] ) && + ( 'r' === $html[ $at + 2 ] || 'R' === $html[ $at + 2 ] ) && + ( 'i' === $html[ $at + 3 ] || 'I' === $html[ $at + 3 ] ) && + ( 'p' === $html[ $at + 4 ] || 'P' === $html[ $at + 4 ] ) && + ( 't' === $html[ $at + 5 ] || 'T' === $html[ $at + 5 ] ) + ) ) { + ++$at; + continue; + } + + /* + * Ensure that the script tag terminates to avoid matching on + * substrings of a non-match. For example, the sequence + * "<script123" should not end a script region even though + * "<script" is found within the text. + */ + if ( $at + 6 >= $doc_length ) { + continue; + } + $at += 6; + $c = $html[ $at ]; + if ( ' ' !== $c && "\t" !== $c && "\r" !== $c && "\n" !== $c && '/' !== $c && '>' !== $c ) { + ++$at; + continue; + } + + if ( 'escaped' === $state && ! $is_closing ) { + $state = 'double-escaped'; + continue; + } + + if ( 'double-escaped' === $state && $is_closing ) { + $state = 'escaped'; + continue; + } + + if ( $is_closing ) { + $this->bytes_already_parsed = $closer_potentially_starts_at; + $this->tag_name_starts_at = $closer_potentially_starts_at; + if ( $this->bytes_already_parsed >= $doc_length ) { + return false; + } + + while ( $this->parse_next_attribute() ) { + continue; + } + + if ( $this->bytes_already_parsed >= $doc_length ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + + return false; + } + + if ( '>' === $html[ $this->bytes_already_parsed ] ) { + ++$this->bytes_already_parsed; + return true; + } + } + + ++$at; + } + + return false; + } + + /** + * Parses the next tag. + * + * This will find and start parsing the next tag, including + * the opening `<`, the potential closer `/`, and the tag + * name. It does not parse the attributes or scan to the + * closing `>`; these are left for other methods. + * + * @since 6.2.0 + * @since 6.2.1 Support abruptly-closed comments, invalid-tag-closer-comments, and empty elements. + * + * @return bool Whether a tag was found before the end of the document. + */ + private function parse_next_tag(): bool { + $this->after_tag(); + + $html = $this->html; + $doc_length = strlen( $html ); + $was_at = $this->bytes_already_parsed; + $at = $was_at; + + while ( $at < $doc_length ) { + $at = strpos( $html, '<', $at ); + if ( false === $at ) { + break; + } + + if ( $at > $was_at ) { + /* + * A "<" normally starts a new HTML tag or syntax token, but in cases where the + * following character can't produce a valid token, the "<" is instead treated + * as plaintext and the parser should skip over it. This avoids a problem when + * following earlier practices of typing emoji with text, e.g. "<3". This + * should be a heart, not a tag. It's supposed to be rendered, not hidden. + * + * At this point the parser checks if this is one of those cases and if it is + * will continue searching for the next "<" in search of a token boundary. + * + * @see https://html.spec.whatwg.org/#tag-open-state + */ + if ( 1 !== strspn( $html, '!/?abcdefghijklmnopqrstuvwxyzABCEFGHIJKLMNOPQRSTUVWXYZ', $at + 1, 1 ) ) { + ++$at; + continue; + } + + $this->parser_state = self::STATE_TEXT_NODE; + $this->token_starts_at = $was_at; + $this->token_length = $at - $was_at; + $this->text_starts_at = $was_at; + $this->text_length = $this->token_length; + $this->bytes_already_parsed = $at; + return true; + } + + $this->token_starts_at = $at; + + if ( $at + 1 < $doc_length && '/' === $this->html[ $at + 1 ] ) { + $this->is_closing_tag = true; + ++$at; + } else { + $this->is_closing_tag = false; + } + + /* + * HTML tag names must start with [a-zA-Z] otherwise they are not tags. + * For example, "<3" is rendered as text, not a tag opener. If at least + * one letter follows the "<" then _it is_ a tag, but if the following + * character is anything else it _is not a tag_. + * + * It's not uncommon to find non-tags starting with `<` in an HTML + * document, so it's good for performance to make this pre-check before + * continuing to attempt to parse a tag name. + * + * Reference: + * * https://html.spec.whatwg.org/multipage/parsing.html#data-state + * * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state + */ + $tag_name_prefix_length = strspn( $html, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', $at + 1 ); + if ( $tag_name_prefix_length > 0 ) { + ++$at; + $this->parser_state = self::STATE_MATCHED_TAG; + $this->tag_name_starts_at = $at; + $this->tag_name_length = $tag_name_prefix_length + strcspn( $html, " \t\f\r\n/>", $at + $tag_name_prefix_length ); + $this->bytes_already_parsed = $at + $this->tag_name_length; + return true; + } + + /* + * Abort if no tag is found before the end of + * the document. There is nothing left to parse. + */ + if ( $at + 1 >= $doc_length ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + + return false; + } + + /* + * `<!` transitions to markup declaration open state + * https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state + */ + if ( ! $this->is_closing_tag && '!' === $html[ $at + 1 ] ) { + /* + * `<!--` transitions to a comment state – apply further comment rules. + * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state + */ + if ( 0 === substr_compare( $html, '--', $at + 2, 2 ) ) { + $closer_at = $at + 4; + // If it's not possible to close the comment then there is nothing more to scan. + if ( $doc_length <= $closer_at ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + + return false; + } + + // Abruptly-closed empty comments are a sequence of dashes followed by `>`. + $span_of_dashes = strspn( $html, '-', $closer_at ); + if ( '>' === $html[ $closer_at + $span_of_dashes ] ) { + /* + * @todo When implementing `set_modifiable_text()` ensure that updates to this token + * don't break the syntax for short comments, e.g. `<!--->`. Unlike other comment + * and bogus comment syntax, these leave no clear insertion point for text and + * they need to be modified specially in order to contain text. E.g. to store + * `?` as the modifiable text, the `<!--->` needs to become `<!--?-->`, which + * involves inserting an additional `-` into the token after the modifiable text. + */ + $this->parser_state = self::STATE_COMMENT; + $this->comment_type = self::COMMENT_AS_ABRUPTLY_CLOSED_COMMENT; + $this->token_length = $closer_at + $span_of_dashes + 1 - $this->token_starts_at; + + // Only provide modifiable text if the token is long enough to contain it. + if ( $span_of_dashes >= 2 ) { + $this->comment_type = self::COMMENT_AS_HTML_COMMENT; + $this->text_starts_at = $this->token_starts_at + 4; + $this->text_length = $span_of_dashes - 2; + } + + $this->bytes_already_parsed = $closer_at + $span_of_dashes + 1; + return true; + } + + /* + * Comments may be closed by either a --> or an invalid --!>. + * The first occurrence closes the comment. + * + * See https://html.spec.whatwg.org/#parse-error-incorrectly-closed-comment + */ + --$closer_at; // Pre-increment inside condition below reduces risk of accidental infinite looping. + while ( ++$closer_at < $doc_length ) { + $closer_at = strpos( $html, '--', $closer_at ); + if ( false === $closer_at ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + + return false; + } + + if ( $closer_at + 2 < $doc_length && '>' === $html[ $closer_at + 2 ] ) { + $this->parser_state = self::STATE_COMMENT; + $this->comment_type = self::COMMENT_AS_HTML_COMMENT; + $this->token_length = $closer_at + 3 - $this->token_starts_at; + $this->text_starts_at = $this->token_starts_at + 4; + $this->text_length = $closer_at - $this->text_starts_at; + $this->bytes_already_parsed = $closer_at + 3; + return true; + } + + if ( + $closer_at + 3 < $doc_length && + '!' === $html[ $closer_at + 2 ] && + '>' === $html[ $closer_at + 3 ] + ) { + $this->parser_state = self::STATE_COMMENT; + $this->comment_type = self::COMMENT_AS_HTML_COMMENT; + $this->token_length = $closer_at + 4 - $this->token_starts_at; + $this->text_starts_at = $this->token_starts_at + 4; + $this->text_length = $closer_at - $this->text_starts_at; + $this->bytes_already_parsed = $closer_at + 4; + return true; + } + } + } + + /* + * `<!DOCTYPE` transitions to DOCTYPE state – skip to the nearest > + * These are ASCII-case-insensitive. + * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state + */ + if ( + $doc_length > $at + 8 && + ( 'D' === $html[ $at + 2 ] || 'd' === $html[ $at + 2 ] ) && + ( 'O' === $html[ $at + 3 ] || 'o' === $html[ $at + 3 ] ) && + ( 'C' === $html[ $at + 4 ] || 'c' === $html[ $at + 4 ] ) && + ( 'T' === $html[ $at + 5 ] || 't' === $html[ $at + 5 ] ) && + ( 'Y' === $html[ $at + 6 ] || 'y' === $html[ $at + 6 ] ) && + ( 'P' === $html[ $at + 7 ] || 'p' === $html[ $at + 7 ] ) && + ( 'E' === $html[ $at + 8 ] || 'e' === $html[ $at + 8 ] ) + ) { + $closer_at = strpos( $html, '>', $at + 9 ); + if ( false === $closer_at ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + + return false; + } + + $this->parser_state = self::STATE_DOCTYPE; + $this->token_length = $closer_at + 1 - $this->token_starts_at; + $this->text_starts_at = $this->token_starts_at + 9; + $this->text_length = $closer_at - $this->text_starts_at; + $this->bytes_already_parsed = $closer_at + 1; + return true; + } + + /* + * Anything else here is an incorrectly-opened comment and transitions + * to the bogus comment state - skip to the nearest >. If no closer is + * found then the HTML was truncated inside the markup declaration. + */ + $closer_at = strpos( $html, '>', $at + 1 ); + if ( false === $closer_at ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + + return false; + } + + $this->parser_state = self::STATE_COMMENT; + $this->comment_type = self::COMMENT_AS_INVALID_HTML; + $this->token_length = $closer_at + 1 - $this->token_starts_at; + $this->text_starts_at = $this->token_starts_at + 2; + $this->text_length = $closer_at - $this->text_starts_at; + $this->bytes_already_parsed = $closer_at + 1; + + /* + * Identify nodes that would be CDATA if HTML had CDATA sections. + * + * This section must occur after identifying the bogus comment end + * because in an HTML parser it will span to the nearest `>`, even + * if there's no `]]>` as would be required in an XML document. It + * is therefore not possible to parse a CDATA section containing + * a `>` in the HTML syntax. + * + * Inside foreign elements there is a discrepancy between browsers + * and the specification on this. + * + * @todo Track whether the Tag Processor is inside a foreign element + * and require the proper closing `]]>` in those cases. + */ + if ( + $this->token_length >= 10 && + '[' === $html[ $this->token_starts_at + 2 ] && + 'C' === $html[ $this->token_starts_at + 3 ] && + 'D' === $html[ $this->token_starts_at + 4 ] && + 'A' === $html[ $this->token_starts_at + 5 ] && + 'T' === $html[ $this->token_starts_at + 6 ] && + 'A' === $html[ $this->token_starts_at + 7 ] && + '[' === $html[ $this->token_starts_at + 8 ] && + ']' === $html[ $closer_at - 1 ] && + ']' === $html[ $closer_at - 2 ] + ) { + $this->parser_state = self::STATE_COMMENT; + $this->comment_type = self::COMMENT_AS_CDATA_LOOKALIKE; + $this->text_starts_at += 7; + $this->text_length -= 9; + } + + return true; + } + + /* + * </> is a missing end tag name, which is ignored. + * + * This was also known as the "presumptuous empty tag" + * in early discussions as it was proposed to close + * the nearest previous opening tag. + * + * See https://html.spec.whatwg.org/#parse-error-missing-end-tag-name + */ + if ( '>' === $html[ $at + 1 ] ) { + // `<>` is interpreted as plaintext. + if ( ! $this->is_closing_tag ) { + ++$at; + continue; + } + + $this->parser_state = self::STATE_PRESUMPTUOUS_TAG; + $this->token_length = $at + 2 - $this->token_starts_at; + $this->bytes_already_parsed = $at + 2; + return true; + } + + /* + * `<?` transitions to a bogus comment state – skip to the nearest > + * See https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state + */ + if ( ! $this->is_closing_tag && '?' === $html[ $at + 1 ] ) { + $closer_at = strpos( $html, '>', $at + 2 ); + if ( false === $closer_at ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + + return false; + } + + $this->parser_state = self::STATE_COMMENT; + $this->comment_type = self::COMMENT_AS_INVALID_HTML; + $this->token_length = $closer_at + 1 - $this->token_starts_at; + $this->text_starts_at = $this->token_starts_at + 2; + $this->text_length = $closer_at - $this->text_starts_at; + $this->bytes_already_parsed = $closer_at + 1; + + /* + * Identify a Processing Instruction node were HTML to have them. + * + * This section must occur after identifying the bogus comment end + * because in an HTML parser it will span to the nearest `>`, even + * if there's no `?>` as would be required in an XML document. It + * is therefore not possible to parse a Processing Instruction node + * containing a `>` in the HTML syntax. + * + * XML allows for more target names, but this code only identifies + * those with ASCII-representable target names. This means that it + * may identify some Processing Instruction nodes as bogus comments, + * but it will not misinterpret the HTML structure. By limiting the + * identification to these target names the Tag Processor can avoid + * the need to start parsing UTF-8 sequences. + * + * > NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | + * [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | + * [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | + * [#x10000-#xEFFFF] + * > NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] + * + * @see https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-PITarget + */ + if ( $this->token_length >= 5 && '?' === $html[ $closer_at - 1 ] ) { + $comment_text = substr( $html, $this->token_starts_at + 2, $this->token_length - 4 ); + $pi_target_length = strspn( $comment_text, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:_' ); + + if ( 0 < $pi_target_length ) { + $pi_target_length += strspn( $comment_text, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:_-.', $pi_target_length ); + + $this->comment_type = self::COMMENT_AS_PI_NODE_LOOKALIKE; + $this->tag_name_starts_at = $this->token_starts_at + 2; + $this->tag_name_length = $pi_target_length; + $this->text_starts_at += $pi_target_length; + $this->text_length -= $pi_target_length + 1; + } + } + + return true; + } + + /* + * If a non-alpha starts the tag name in a tag closer it's a comment. + * Find the first `>`, which closes the comment. + * + * This parser classifies these particular comments as special "funky comments" + * which are made available for further processing. + * + * See https://html.spec.whatwg.org/#parse-error-invalid-first-character-of-tag-name + */ + if ( $this->is_closing_tag ) { + // No chance of finding a closer. + if ( $at + 3 > $doc_length ) { + return false; + } + + $closer_at = strpos( $html, '>', $at + 2 ); + if ( false === $closer_at ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + + return false; + } + + $this->parser_state = self::STATE_FUNKY_COMMENT; + $this->token_length = $closer_at + 1 - $this->token_starts_at; + $this->text_starts_at = $this->token_starts_at + 2; + $this->text_length = $closer_at - $this->text_starts_at; + $this->bytes_already_parsed = $closer_at + 1; + return true; + } + + ++$at; + } + + /* + * This does not imply an incomplete parse; it indicates that there + * can be nothing left in the document other than a #text node. + */ + $this->parser_state = self::STATE_TEXT_NODE; + $this->token_starts_at = $was_at; + $this->token_length = $doc_length - $was_at; + $this->text_starts_at = $was_at; + $this->text_length = $this->token_length; + $this->bytes_already_parsed = $doc_length; + return true; + } + + /** + * Parses the next attribute. + * + * @since 6.2.0 + * + * @return bool Whether an attribute was found before the end of the document. + */ + private function parse_next_attribute(): bool { + $doc_length = strlen( $this->html ); + + // Skip whitespace and slashes. + $this->bytes_already_parsed += strspn( $this->html, " \t\f\r\n/", $this->bytes_already_parsed ); + if ( $this->bytes_already_parsed >= $doc_length ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + + return false; + } + + /* + * Treat the equal sign as a part of the attribute + * name if it is the first encountered byte. + * + * @see https://html.spec.whatwg.org/multipage/parsing.html#before-attribute-name-state + */ + $name_length = '=' === $this->html[ $this->bytes_already_parsed ] + ? 1 + strcspn( $this->html, "=/> \t\f\r\n", $this->bytes_already_parsed + 1 ) + : strcspn( $this->html, "=/> \t\f\r\n", $this->bytes_already_parsed ); + + // No attribute, just tag closer. + if ( 0 === $name_length || $this->bytes_already_parsed + $name_length >= $doc_length ) { + return false; + } + + $attribute_start = $this->bytes_already_parsed; + $attribute_name = substr( $this->html, $attribute_start, $name_length ); + $this->bytes_already_parsed += $name_length; + if ( $this->bytes_already_parsed >= $doc_length ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + + return false; + } + + $this->skip_whitespace(); + if ( $this->bytes_already_parsed >= $doc_length ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + + return false; + } + + $has_value = '=' === $this->html[ $this->bytes_already_parsed ]; + if ( $has_value ) { + ++$this->bytes_already_parsed; + $this->skip_whitespace(); + if ( $this->bytes_already_parsed >= $doc_length ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + + return false; + } + + switch ( $this->html[ $this->bytes_already_parsed ] ) { + case "'": + case '"': + $quote = $this->html[ $this->bytes_already_parsed ]; + $value_start = $this->bytes_already_parsed + 1; + $end_quote_at = strpos( $this->html, $quote, $value_start ); + $end_quote_at = false === $end_quote_at ? $doc_length : $end_quote_at; + $value_length = $end_quote_at - $value_start; + $attribute_end = $end_quote_at + 1; + $this->bytes_already_parsed = $attribute_end; + break; + + default: + $value_start = $this->bytes_already_parsed; + $value_length = strcspn( $this->html, "> \t\f\r\n", $value_start ); + $attribute_end = $value_start + $value_length; + $this->bytes_already_parsed = $attribute_end; + } + } else { + $value_start = $this->bytes_already_parsed; + $value_length = 0; + $attribute_end = $attribute_start + $name_length; + } + + if ( $attribute_end >= $doc_length ) { + $this->parser_state = self::STATE_INCOMPLETE_INPUT; + + return false; + } + + if ( $this->is_closing_tag ) { + return true; + } + + /* + * > There must never be two or more attributes on + * > the same start tag whose names are an ASCII + * > case-insensitive match for each other. + * - HTML 5 spec + * + * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive + */ + $comparable_name = strtolower( $attribute_name ); + + // If an attribute is listed many times, only use the first declaration and ignore the rest. + if ( ! isset( $this->attributes[ $comparable_name ] ) ) { + $this->attributes[ $comparable_name ] = new Gutenberg_HTML_Attribute_Token_6_7( + $attribute_name, + $value_start, + $value_length, + $attribute_start, + $attribute_end - $attribute_start, + ! $has_value + ); + + return true; + } + + /* + * Track the duplicate attributes so if we remove it, all disappear together. + * + * While `$this->duplicated_attributes` could always be stored as an `array()`, + * which would simplify the logic here, storing a `null` and only allocating + * an array when encountering duplicates avoids needless allocations in the + * normative case of parsing tags with no duplicate attributes. + */ + $duplicate_span = new Gutenberg_HTML_Span_6_7( $attribute_start, $attribute_end - $attribute_start ); + if ( null === $this->duplicate_attributes ) { + $this->duplicate_attributes = array( $comparable_name => array( $duplicate_span ) ); + } elseif ( ! isset( $this->duplicate_attributes[ $comparable_name ] ) ) { + $this->duplicate_attributes[ $comparable_name ] = array( $duplicate_span ); + } else { + $this->duplicate_attributes[ $comparable_name ][] = $duplicate_span; + } + + return true; + } + + /** + * Move the internal cursor past any immediate successive whitespace. + * + * @since 6.2.0 + */ + private function skip_whitespace(): void { + $this->bytes_already_parsed += strspn( $this->html, " \t\f\r\n", $this->bytes_already_parsed ); + } + + /** + * Applies attribute updates and cleans up once a tag is fully parsed. + * + * @since 6.2.0 + */ + private function after_tag(): void { + /* + * There could be lexical updates enqueued for an attribute that + * also exists on the next tag. In order to avoid conflating the + * attributes across the two tags, lexical updates with names + * need to be flushed to raw lexical updates. + */ + $this->class_name_updates_to_attributes_updates(); + + /* + * Purge updates if there are too many. The actual count isn't + * scientific, but a few values from 100 to a few thousand were + * tests to find a practically-useful limit. + * + * If the update queue grows too big, then the Tag Processor + * will spend more time iterating through them and lose the + * efficiency gains of deferring applying them. + */ + if ( 1000 < count( $this->lexical_updates ) ) { + $this->get_updated_html(); + } + + foreach ( $this->lexical_updates as $name => $update ) { + /* + * Any updates appearing after the cursor should be applied + * before proceeding, otherwise they may be overlooked. + */ + if ( $update->start >= $this->bytes_already_parsed ) { + $this->get_updated_html(); + break; + } + + if ( is_int( $name ) ) { + continue; + } + + $this->lexical_updates[] = $update; + unset( $this->lexical_updates[ $name ] ); + } + + $this->token_starts_at = null; + $this->token_length = null; + $this->tag_name_starts_at = null; + $this->tag_name_length = null; + $this->text_starts_at = 0; + $this->text_length = 0; + $this->is_closing_tag = null; + $this->attributes = array(); + $this->comment_type = null; + $this->duplicate_attributes = null; + } + + /** + * Converts class name updates into tag attributes updates + * (they are accumulated in different data formats for performance). + * + * @since 6.2.0 + * + * @see WP_HTML_Tag_Processor::$lexical_updates + * @see WP_HTML_Tag_Processor::$classname_updates + */ + private function class_name_updates_to_attributes_updates(): void { + if ( count( $this->classname_updates ) === 0 ) { + return; + } + + $existing_class = $this->get_enqueued_attribute_value( 'class' ); + if ( null === $existing_class || true === $existing_class ) { + $existing_class = ''; + } + + if ( false === $existing_class && isset( $this->attributes['class'] ) ) { + $existing_class = substr( + $this->html, + $this->attributes['class']->value_starts_at, + $this->attributes['class']->value_length + ); + } + + if ( false === $existing_class ) { + $existing_class = ''; + } + + /** + * Updated "class" attribute value. + * + * This is incrementally built while scanning through the existing class + * attribute, skipping removed classes on the way, and then appending + * added classes at the end. Only when finished processing will the + * value contain the final new value. + + * @var string $class + */ + $class = ''; + + /** + * Tracks the cursor position in the existing + * class attribute value while parsing. + * + * @var int $at + */ + $at = 0; + + /** + * Indicates if there's any need to modify the existing class attribute. + * + * If a call to `add_class()` and `remove_class()` wouldn't impact + * the `class` attribute value then there's no need to rebuild it. + * For example, when adding a class that's already present or + * removing one that isn't. + * + * This flag enables a performance optimization when none of the enqueued + * class updates would impact the `class` attribute; namely, that the + * processor can continue without modifying the input document, as if + * none of the `add_class()` or `remove_class()` calls had been made. + * + * This flag is set upon the first change that requires a string update. + * + * @var bool $modified + */ + $modified = false; + + // Remove unwanted classes by only copying the new ones. + $existing_class_length = strlen( $existing_class ); + while ( $at < $existing_class_length ) { + // Skip to the first non-whitespace character. + $ws_at = $at; + $ws_length = strspn( $existing_class, " \t\f\r\n", $ws_at ); + $at += $ws_length; + + // Capture the class name – it's everything until the next whitespace. + $name_length = strcspn( $existing_class, " \t\f\r\n", $at ); + if ( 0 === $name_length ) { + // If no more class names are found then that's the end. + break; + } + + $name = substr( $existing_class, $at, $name_length ); + $at += $name_length; + + // If this class is marked for removal, start processing the next one. + $remove_class = ( + isset( $this->classname_updates[ $name ] ) && + self::REMOVE_CLASS === $this->classname_updates[ $name ] + ); + + // If a class has already been seen then skip it; it should not be added twice. + if ( ! $remove_class ) { + $this->classname_updates[ $name ] = self::SKIP_CLASS; + } + + if ( $remove_class ) { + $modified = true; + continue; + } + + /* + * Otherwise, append it to the new "class" attribute value. + * + * There are options for handling whitespace between tags. + * Preserving the existing whitespace produces fewer changes + * to the HTML content and should clarify the before/after + * content when debugging the modified output. + * + * This approach contrasts normalizing the inter-class + * whitespace to a single space, which might appear cleaner + * in the output HTML but produce a noisier change. + */ + if ( '' !== $class ) { + $class .= substr( $existing_class, $ws_at, $ws_length ); + } + $class .= $name; + } + + // Add new classes by appending those which haven't already been seen. + foreach ( $this->classname_updates as $name => $operation ) { + if ( self::ADD_CLASS === $operation ) { + $modified = true; + + $class .= strlen( $class ) > 0 ? ' ' : ''; + $class .= $name; + } + } + + $this->classname_updates = array(); + if ( ! $modified ) { + return; + } + + if ( strlen( $class ) > 0 ) { + $this->set_attribute( 'class', $class ); + } else { + $this->remove_attribute( 'class' ); + } + } + + /** + * Applies attribute updates to HTML document. + * + * @since 6.2.0 + * @since 6.2.1 Accumulates shift for internal cursor and passed pointer. + * @since 6.3.0 Invalidate any bookmarks whose targets are overwritten. + * + * @param int $shift_this_point Accumulate and return shift for this position. + * @return int How many bytes the given pointer moved in response to the updates. + */ + private function apply_attributes_updates( int $shift_this_point ): int { + if ( ! count( $this->lexical_updates ) ) { + return 0; + } + + $accumulated_shift_for_given_point = 0; + + /* + * Attribute updates can be enqueued in any order but updates + * to the document must occur in lexical order; that is, each + * replacement must be made before all others which follow it + * at later string indices in the input document. + * + * Sorting avoid making out-of-order replacements which + * can lead to mangled output, partially-duplicated + * attributes, and overwritten attributes. + */ + usort( $this->lexical_updates, array( self::class, 'sort_start_ascending' ) ); + + $bytes_already_copied = 0; + $output_buffer = ''; + foreach ( $this->lexical_updates as $diff ) { + $shift = strlen( $diff->text ) - $diff->length; + + // Adjust the cursor position by however much an update affects it. + if ( $diff->start < $this->bytes_already_parsed ) { + $this->bytes_already_parsed += $shift; + } + + // Accumulate shift of the given pointer within this function call. + if ( $diff->start <= $shift_this_point ) { + $accumulated_shift_for_given_point += $shift; + } + + $output_buffer .= substr( $this->html, $bytes_already_copied, $diff->start - $bytes_already_copied ); + $output_buffer .= $diff->text; + $bytes_already_copied = $diff->start + $diff->length; + } + + $this->html = $output_buffer . substr( $this->html, $bytes_already_copied ); + + /* + * Adjust bookmark locations to account for how the text + * replacements adjust offsets in the input document. + */ + foreach ( $this->bookmarks as $bookmark_name => $bookmark ) { + $bookmark_end = $bookmark->start + $bookmark->length; + + /* + * Each lexical update which appears before the bookmark's endpoints + * might shift the offsets for those endpoints. Loop through each change + * and accumulate the total shift for each bookmark, then apply that + * shift after tallying the full delta. + */ + $head_delta = 0; + $tail_delta = 0; + + foreach ( $this->lexical_updates as $diff ) { + $diff_end = $diff->start + $diff->length; + + if ( $bookmark->start < $diff->start && $bookmark_end < $diff->start ) { + break; + } + + if ( $bookmark->start >= $diff->start && $bookmark_end < $diff_end ) { + $this->release_bookmark( $bookmark_name ); + continue 2; + } + + $delta = strlen( $diff->text ) - $diff->length; + + if ( $bookmark->start >= $diff->start ) { + $head_delta += $delta; + } + + if ( $bookmark_end >= $diff_end ) { + $tail_delta += $delta; + } + } + + $bookmark->start += $head_delta; + $bookmark->length += $tail_delta - $head_delta; + } + + $this->lexical_updates = array(); + + return $accumulated_shift_for_given_point; + } + + /** + * Checks whether a bookmark with the given name exists. + * + * @since 6.3.0 + * + * @param string $bookmark_name Name to identify a bookmark that potentially exists. + * @return bool Whether that bookmark exists. + */ + public function has_bookmark( $bookmark_name ): bool { + return array_key_exists( $bookmark_name, $this->bookmarks ); + } + + /** + * Move the internal cursor in the Tag Processor to a given bookmark's location. + * + * In order to prevent accidental infinite loops, there's a + * maximum limit on the number of times seek() can be called. + * + * @since 6.2.0 + * + * @param string $bookmark_name Jump to the place in the document identified by this bookmark name. + * @return bool Whether the internal cursor was successfully moved to the bookmark's location. + */ + public function seek( $bookmark_name ): bool { + if ( ! array_key_exists( $bookmark_name, $this->bookmarks ) ) { + _doing_it_wrong( + __METHOD__, + __( 'Unknown bookmark name.' ), + '6.2.0' + ); + return false; + } + + if ( ++$this->seek_count > static::MAX_SEEK_OPS ) { + _doing_it_wrong( + __METHOD__, + __( 'Too many calls to seek() - this can lead to performance issues.' ), + '6.2.0' + ); + return false; + } + + // Flush out any pending updates to the document. + $this->get_updated_html(); + + // Point this tag processor before the sought tag opener and consume it. + $this->bytes_already_parsed = $this->bookmarks[ $bookmark_name ]->start; + $this->parser_state = self::STATE_READY; + return $this->next_token(); + } + + /** + * Compare two WP_HTML_Text_Replacement objects. + * + * @since 6.2.0 + * + * @param WP_HTML_Text_Replacement $a First attribute update. + * @param WP_HTML_Text_Replacement $b Second attribute update. + * @return int Comparison value for string order. + */ + private static function sort_start_ascending( Gutenberg_HTML_Text_Replacement_6_7 $a, Gutenberg_HTML_Text_Replacement_6_7 $b ): int { + $by_start = $a->start - $b->start; + if ( 0 !== $by_start ) { + return $by_start; + } + + $by_text = isset( $a->text, $b->text ) ? strcmp( $a->text, $b->text ) : 0; + if ( 0 !== $by_text ) { + return $by_text; + } + + /* + * This code should be unreachable, because it implies the two replacements + * start at the same location and contain the same text. + */ + return $a->length - $b->length; + } + + /** + * Return the enqueued value for a given attribute, if one exists. + * + * Enqueued updates can take different data types: + * - If an update is enqueued and is boolean, the return will be `true` + * - If an update is otherwise enqueued, the return will be the string value of that update. + * - If an attribute is enqueued to be removed, the return will be `null` to indicate that. + * - If no updates are enqueued, the return will be `false` to differentiate from "removed." + * + * @since 6.2.0 + * + * @param string $comparable_name The attribute name in its comparable form. + * @return string|boolean|null Value of enqueued update if present, otherwise false. + */ + private function get_enqueued_attribute_value( string $comparable_name ) { + if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { + return false; + } + + if ( ! isset( $this->lexical_updates[ $comparable_name ] ) ) { + return false; + } + + $enqueued_text = $this->lexical_updates[ $comparable_name ]->text; + + // Removed attributes erase the entire span. + if ( '' === $enqueued_text ) { + return null; + } + + /* + * Boolean attribute updates are just the attribute name without a corresponding value. + * + * This value might differ from the given comparable name in that there could be leading + * or trailing whitespace, and that the casing follows the name given in `set_attribute`. + * + * Example: + * + * $p->set_attribute( 'data-TEST-id', 'update' ); + * 'update' === $p->get_enqueued_attribute_value( 'data-test-id' ); + * + * Detect this difference based on the absence of the `=`, which _must_ exist in any + * attribute containing a value, e.g. `<input type="text" enabled />`. + * ¹ ² + * 1. Attribute with a string value. + * 2. Boolean attribute whose value is `true`. + */ + $equals_at = strpos( $enqueued_text, '=' ); + if ( false === $equals_at ) { + return true; + } + + /* + * Finally, a normal update's value will appear after the `=` and + * be double-quoted, as performed incidentally by `set_attribute`. + * + * e.g. `type="text"` + * ¹² ³ + * 1. Equals is here. + * 2. Double-quoting starts one after the equals sign. + * 3. Double-quoting ends at the last character in the update. + */ + $enqueued_value = substr( $enqueued_text, $equals_at + 2, -1 ); + return Gutenberg_HTML_Decoder_6_7::decode_attribute( $enqueued_value ); + } + + /** + * Returns the value of a requested attribute from a matched tag opener if that attribute exists. + * + * Example: + * + * $p = new WP_HTML_Tag_Processor( '<div enabled class="test" data-test-id="14">Test</div>' ); + * $p->next_tag( array( 'class_name' => 'test' ) ) === true; + * $p->get_attribute( 'data-test-id' ) === '14'; + * $p->get_attribute( 'enabled' ) === true; + * $p->get_attribute( 'aria-label' ) === null; + * + * $p->next_tag() === false; + * $p->get_attribute( 'class' ) === null; + * + * @since 6.2.0 + * + * @param string $name Name of attribute whose value is requested. + * @return string|true|null Value of attribute or `null` if not available. Boolean attributes return `true`. + */ + public function get_attribute( $name ) { + if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { + return null; + } + + $comparable = strtolower( $name ); + + /* + * For every attribute other than `class` it's possible to perform a quick check if + * there's an enqueued lexical update whose value takes priority over what's found in + * the input document. + * + * The `class` attribute is special though because of the exposed helpers `add_class` + * and `remove_class`. These form a builder for the `class` attribute, so an additional + * check for enqueued class changes is required in addition to the check for any enqueued + * attribute values. If any exist, those enqueued class changes must first be flushed out + * into an attribute value update. + */ + if ( 'class' === $name ) { + $this->class_name_updates_to_attributes_updates(); + } + + // Return any enqueued attribute value updates if they exist. + $enqueued_value = $this->get_enqueued_attribute_value( $comparable ); + if ( false !== $enqueued_value ) { + return $enqueued_value; + } + + if ( ! isset( $this->attributes[ $comparable ] ) ) { + return null; + } + + $attribute = $this->attributes[ $comparable ]; + + /* + * This flag distinguishes an attribute with no value + * from an attribute with an empty string value. For + * unquoted attributes this could look very similar. + * It refers to whether an `=` follows the name. + * + * e.g. <div boolean-attribute empty-attribute=></div> + * ¹ ² + * 1. Attribute `boolean-attribute` is `true`. + * 2. Attribute `empty-attribute` is `""`. + */ + if ( true === $attribute->is_true ) { + return true; + } + + $raw_value = substr( $this->html, $attribute->value_starts_at, $attribute->value_length ); + + return Gutenberg_HTML_Decoder_6_7::decode_attribute( $raw_value ); + } + + /** + * Gets lowercase names of all attributes matching a given prefix in the current tag. + * + * Note that matching is case-insensitive. This is in accordance with the spec: + * + * > There must never be two or more attributes on + * > the same start tag whose names are an ASCII + * > case-insensitive match for each other. + * - HTML 5 spec + * + * Example: + * + * $p = new WP_HTML_Tag_Processor( '<div data-ENABLED class="test" DATA-test-id="14">Test</div>' ); + * $p->next_tag( array( 'class_name' => 'test' ) ) === true; + * $p->get_attribute_names_with_prefix( 'data-' ) === array( 'data-enabled', 'data-test-id' ); + * + * $p->next_tag() === false; + * $p->get_attribute_names_with_prefix( 'data-' ) === null; + * + * @since 6.2.0 + * + * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive + * + * @param string $prefix Prefix of requested attribute names. + * @return array|null List of attribute names, or `null` when no tag opener is matched. + */ + public function get_attribute_names_with_prefix( $prefix ): ?array { + if ( + self::STATE_MATCHED_TAG !== $this->parser_state || + $this->is_closing_tag + ) { + return null; + } + + $comparable = strtolower( $prefix ); + + $matches = array(); + foreach ( array_keys( $this->attributes ) as $attr_name ) { + if ( str_starts_with( $attr_name, $comparable ) ) { + $matches[] = $attr_name; + } + } + return $matches; + } + + /** + * Returns the uppercase name of the matched tag. + * + * Example: + * + * $p = new WP_HTML_Tag_Processor( '<div class="test">Test</div>' ); + * $p->next_tag() === true; + * $p->get_tag() === 'DIV'; + * + * $p->next_tag() === false; + * $p->get_tag() === null; + * + * @since 6.2.0 + * + * @return string|null Name of currently matched tag in input HTML, or `null` if none found. + */ + public function get_tag(): ?string { + if ( null === $this->tag_name_starts_at ) { + return null; + } + + $tag_name = substr( $this->html, $this->tag_name_starts_at, $this->tag_name_length ); + + if ( self::STATE_MATCHED_TAG === $this->parser_state ) { + return strtoupper( $tag_name ); + } + + if ( + self::STATE_COMMENT === $this->parser_state && + self::COMMENT_AS_PI_NODE_LOOKALIKE === $this->get_comment_type() + ) { + return $tag_name; + } + + return null; + } + + /** + * Indicates if the currently matched tag contains the self-closing flag. + * + * No HTML elements ought to have the self-closing flag and for those, the self-closing + * flag will be ignored. For void elements this is benign because they "self close" + * automatically. For non-void HTML elements though problems will appear if someone + * intends to use a self-closing element in place of that element with an empty body. + * For HTML foreign elements and custom elements the self-closing flag determines if + * they self-close or not. + * + * This function does not determine if a tag is self-closing, + * but only if the self-closing flag is present in the syntax. + * + * @since 6.3.0 + * + * @return bool Whether the currently matched tag contains the self-closing flag. + */ + public function has_self_closing_flag(): bool { + if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { + return false; + } + + /* + * The self-closing flag is the solidus at the _end_ of the tag, not the beginning. + * + * Example: + * + * <figure /> + * ^ this appears one character before the end of the closing ">". + */ + return '/' === $this->html[ $this->token_starts_at + $this->token_length - 2 ]; + } + + /** + * Indicates if the current tag token is a tag closer. + * + * Example: + * + * $p = new WP_HTML_Tag_Processor( '<div></div>' ); + * $p->next_tag( array( 'tag_name' => 'div', 'tag_closers' => 'visit' ) ); + * $p->is_tag_closer() === false; + * + * $p->next_tag( array( 'tag_name' => 'div', 'tag_closers' => 'visit' ) ); + * $p->is_tag_closer() === true; + * + * @since 6.2.0 + * + * @return bool Whether the current tag is a tag closer. + */ + public function is_tag_closer(): bool { + return ( + self::STATE_MATCHED_TAG === $this->parser_state && + $this->is_closing_tag + ); + } + + /** + * Indicates the kind of matched token, if any. + * + * This differs from `get_token_name()` in that it always + * returns a static string indicating the type, whereas + * `get_token_name()` may return values derived from the + * token itself, such as a tag name or processing + * instruction tag. + * + * Possible values: + * - `#tag` when matched on a tag. + * - `#text` when matched on a text node. + * - `#cdata-section` when matched on a CDATA node. + * - `#comment` when matched on a comment. + * - `#doctype` when matched on a DOCTYPE declaration. + * - `#presumptuous-tag` when matched on an empty tag closer. + * - `#funky-comment` when matched on a funky comment. + * + * @since 6.5.0 + * + * @return string|null What kind of token is matched, or null. + */ + public function get_token_type(): ?string { + switch ( $this->parser_state ) { + case self::STATE_MATCHED_TAG: + return '#tag'; + + case self::STATE_DOCTYPE: + return '#doctype'; + + default: + return $this->get_token_name(); + } + } + + /** + * Returns the node name represented by the token. + * + * This matches the DOM API value `nodeName`. Some values + * are static, such as `#text` for a text node, while others + * are dynamically generated from the token itself. + * + * Dynamic names: + * - Uppercase tag name for tag matches. + * - `html` for DOCTYPE declarations. + * + * Note that if the Tag Processor is not matched on a token + * then this function will return `null`, either because it + * hasn't yet found a token or because it reached the end + * of the document without matching a token. + * + * @since 6.5.0 + * + * @return string|null Name of the matched token. + */ + public function get_token_name(): ?string { + switch ( $this->parser_state ) { + case self::STATE_MATCHED_TAG: + return $this->get_tag(); + + case self::STATE_TEXT_NODE: + return '#text'; + + case self::STATE_CDATA_NODE: + return '#cdata-section'; + + case self::STATE_COMMENT: + return '#comment'; + + case self::STATE_DOCTYPE: + return 'html'; + + case self::STATE_PRESUMPTUOUS_TAG: + return '#presumptuous-tag'; + + case self::STATE_FUNKY_COMMENT: + return '#funky-comment'; + } + + return null; + } + + /** + * Indicates what kind of comment produced the comment node. + * + * Because there are different kinds of HTML syntax which produce + * comments, the Tag Processor tracks and exposes this as a type + * for the comment. Nominally only regular HTML comments exist as + * they are commonly known, but a number of unrelated syntax errors + * also produce comments. + * + * @see self::COMMENT_AS_ABRUPTLY_CLOSED_COMMENT + * @see self::COMMENT_AS_CDATA_LOOKALIKE + * @see self::COMMENT_AS_INVALID_HTML + * @see self::COMMENT_AS_HTML_COMMENT + * @see self::COMMENT_AS_PI_NODE_LOOKALIKE + * + * @since 6.5.0 + * + * @return string|null + */ + public function get_comment_type(): ?string { + if ( self::STATE_COMMENT !== $this->parser_state ) { + return null; + } + + return $this->comment_type; + } + + /** + * Returns the modifiable text for a matched token, or an empty string. + * + * Modifiable text is text content that may be read and changed without + * changing the HTML structure of the document around it. This includes + * the contents of `#text` nodes in the HTML as well as the inner + * contents of HTML comments, Processing Instructions, and others, even + * though these nodes aren't part of a parsed DOM tree. They also contain + * the contents of SCRIPT and STYLE tags, of TEXTAREA tags, and of any + * other section in an HTML document which cannot contain HTML markup (DATA). + * + * If a token has no modifiable text then an empty string is returned to + * avoid needless crashing or type errors. An empty string does not mean + * that a token has modifiable text, and a token with modifiable text may + * have an empty string (e.g. a comment with no contents). + * + * @since 6.5.0 + * + * @return string + */ + public function get_modifiable_text(): string { + if ( null === $this->text_starts_at ) { + return ''; + } + + $text = substr( $this->html, $this->text_starts_at, $this->text_length ); + + // Comment data is not decoded. + if ( + self::STATE_CDATA_NODE === $this->parser_state || + self::STATE_COMMENT === $this->parser_state || + self::STATE_DOCTYPE === $this->parser_state || + self::STATE_FUNKY_COMMENT === $this->parser_state + ) { + return $text; + } + + $tag_name = $this->get_tag(); + if ( + // Script data is not decoded. + 'SCRIPT' === $tag_name || + + // RAWTEXT data is not decoded. + 'IFRAME' === $tag_name || + 'NOEMBED' === $tag_name || + 'NOFRAMES' === $tag_name || + 'STYLE' === $tag_name || + 'XMP' === $tag_name + ) { + return $text; + } + + $decoded = Gutenberg_HTML_Decoder_6_7::decode_text_node( $text ); + + /* + * TEXTAREA skips a leading newline, but this newline may appear not only as the + * literal character `\n`, but also as a character reference, such as in the + * following markup: `<textarea> Content</textarea>`. + * + * For these cases it's important to first decode the text content before checking + * for a leading newline and removing it. + */ + if ( + self::STATE_MATCHED_TAG === $this->parser_state && + 'TEXTAREA' === $tag_name && + strlen( $decoded ) > 0 && + "\n" === $decoded[0] + ) { + return substr( $decoded, 1 ); + } + + return $decoded; + } + + /** + * Updates or creates a new attribute on the currently matched tag with the passed value. + * + * For boolean attributes special handling is provided: + * - When `true` is passed as the value, then only the attribute name is added to the tag. + * - When `false` is passed, the attribute gets removed if it existed before. + * + * For string attributes, the value is escaped using the `esc_attr` function. + * + * @since 6.2.0 + * @since 6.2.1 Fix: Only create a single update for multiple calls with case-variant attribute names. + * + * @param string $name The attribute name to target. + * @param string|bool $value The new attribute value. + * @return bool Whether an attribute value was set. + */ + public function set_attribute( $name, $value ): bool { + if ( + self::STATE_MATCHED_TAG !== $this->parser_state || + $this->is_closing_tag + ) { + return false; + } + + /* + * WordPress rejects more characters than are strictly forbidden + * in HTML5. This is to prevent additional security risks deeper + * in the WordPress and plugin stack. Specifically the + * less-than (<) greater-than (>) and ampersand (&) aren't allowed. + * + * The use of a PCRE match enables looking for specific Unicode + * code points without writing a UTF-8 decoder. Whereas scanning + * for one-byte characters is trivial (with `strcspn`), scanning + * for the longer byte sequences would be more complicated. Given + * that this shouldn't be in the hot path for execution, it's a + * reasonable compromise in efficiency without introducing a + * noticeable impact on the overall system. + * + * @see https://html.spec.whatwg.org/#attributes-2 + * + * @todo As the only regex pattern maybe we should take it out? + * Are Unicode patterns available broadly in Core? + */ + if ( preg_match( + '~[' . + // Syntax-like characters. + '"\'>&</ =' . + // Control characters. + '\x{00}-\x{1F}' . + // HTML noncharacters. + '\x{FDD0}-\x{FDEF}' . + '\x{FFFE}\x{FFFF}\x{1FFFE}\x{1FFFF}\x{2FFFE}\x{2FFFF}\x{3FFFE}\x{3FFFF}' . + '\x{4FFFE}\x{4FFFF}\x{5FFFE}\x{5FFFF}\x{6FFFE}\x{6FFFF}\x{7FFFE}\x{7FFFF}' . + '\x{8FFFE}\x{8FFFF}\x{9FFFE}\x{9FFFF}\x{AFFFE}\x{AFFFF}\x{BFFFE}\x{BFFFF}' . + '\x{CFFFE}\x{CFFFF}\x{DFFFE}\x{DFFFF}\x{EFFFE}\x{EFFFF}\x{FFFFE}\x{FFFFF}' . + '\x{10FFFE}\x{10FFFF}' . + ']~Ssu', + $name + ) ) { + _doing_it_wrong( + __METHOD__, + __( 'Invalid attribute name.' ), + '6.2.0' + ); + + return false; + } + + /* + * > The values "true" and "false" are not allowed on boolean attributes. + * > To represent a false value, the attribute has to be omitted altogether. + * - HTML5 spec, https://html.spec.whatwg.org/#boolean-attributes + */ + if ( false === $value ) { + return $this->remove_attribute( $name ); + } + + if ( true === $value ) { + $updated_attribute = $name; + } else { + $comparable_name = strtolower( $name ); + + /* + * Escape URL attributes. + * + * @see https://html.spec.whatwg.org/#attributes-3 + */ + $escaped_new_value = in_array( $comparable_name, wp_kses_uri_attributes() ) ? esc_url( $value ) : esc_attr( $value ); + $updated_attribute = "{$name}=\"{$escaped_new_value}\""; + } + + /* + * > There must never be two or more attributes on + * > the same start tag whose names are an ASCII + * > case-insensitive match for each other. + * - HTML 5 spec + * + * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive + */ + $comparable_name = strtolower( $name ); + + if ( isset( $this->attributes[ $comparable_name ] ) ) { + /* + * Update an existing attribute. + * + * Example – set attribute id to "new" in <div id="initial_id" />: + * + * <div id="initial_id"/> + * ^-------------^ + * start end + * replacement: `id="new"` + * + * Result: <div id="new"/> + */ + $existing_attribute = $this->attributes[ $comparable_name ]; + $this->lexical_updates[ $comparable_name ] = new Gutenberg_HTML_Text_Replacement_6_7( + $existing_attribute->start, + $existing_attribute->length, + $updated_attribute + ); + } else { + /* + * Create a new attribute at the tag's name end. + * + * Example – add attribute id="new" to <div />: + * + * <div/> + * ^ + * start and end + * replacement: ` id="new"` + * + * Result: <div id="new"/> + */ + $this->lexical_updates[ $comparable_name ] = new Gutenberg_HTML_Text_Replacement_6_7( + $this->tag_name_starts_at + $this->tag_name_length, + 0, + ' ' . $updated_attribute + ); + } + + /* + * Any calls to update the `class` attribute directly should wipe out any + * enqueued class changes from `add_class` and `remove_class`. + */ + if ( 'class' === $comparable_name && ! empty( $this->classname_updates ) ) { + $this->classname_updates = array(); + } + + return true; + } + + /** + * Remove an attribute from the currently-matched tag. + * + * @since 6.2.0 + * + * @param string $name The attribute name to remove. + * @return bool Whether an attribute was removed. + */ + public function remove_attribute( $name ): bool { + if ( + self::STATE_MATCHED_TAG !== $this->parser_state || + $this->is_closing_tag + ) { + return false; + } + + /* + * > There must never be two or more attributes on + * > the same start tag whose names are an ASCII + * > case-insensitive match for each other. + * - HTML 5 spec + * + * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive + */ + $name = strtolower( $name ); + + /* + * Any calls to update the `class` attribute directly should wipe out any + * enqueued class changes from `add_class` and `remove_class`. + */ + if ( 'class' === $name && count( $this->classname_updates ) !== 0 ) { + $this->classname_updates = array(); + } + + /* + * If updating an attribute that didn't exist in the input + * document, then remove the enqueued update and move on. + * + * For example, this might occur when calling `remove_attribute()` + * after calling `set_attribute()` for the same attribute + * and when that attribute wasn't originally present. + */ + if ( ! isset( $this->attributes[ $name ] ) ) { + if ( isset( $this->lexical_updates[ $name ] ) ) { + unset( $this->lexical_updates[ $name ] ); + } + return false; + } + + /* + * Removes an existing tag attribute. + * + * Example – remove the attribute id from <div id="main"/>: + * <div id="initial_id"/> + * ^-------------^ + * start end + * replacement: `` + * + * Result: <div /> + */ + $this->lexical_updates[ $name ] = new Gutenberg_HTML_Text_Replacement_6_7( + $this->attributes[ $name ]->start, + $this->attributes[ $name ]->length, + '' + ); + + // Removes any duplicated attributes if they were also present. + foreach ( $this->duplicate_attributes[ $name ] ?? array() as $attribute_token ) { + $this->lexical_updates[] = new Gutenberg_HTML_Text_Replacement_6_7( + $attribute_token->start, + $attribute_token->length, + '' + ); + } + + return true; + } + + /** + * Adds a new class name to the currently matched tag. + * + * @since 6.2.0 + * + * @param string $class_name The class name to add. + * @return bool Whether the class was set to be added. + */ + public function add_class( $class_name ): bool { + if ( + self::STATE_MATCHED_TAG !== $this->parser_state || + $this->is_closing_tag + ) { + return false; + } + + $this->classname_updates[ $class_name ] = self::ADD_CLASS; + + return true; + } + + /** + * Removes a class name from the currently matched tag. + * + * @since 6.2.0 + * + * @param string $class_name The class name to remove. + * @return bool Whether the class was set to be removed. + */ + public function remove_class( $class_name ): bool { + if ( + self::STATE_MATCHED_TAG !== $this->parser_state || + $this->is_closing_tag + ) { + return false; + } + + if ( null !== $this->tag_name_starts_at ) { + $this->classname_updates[ $class_name ] = self::REMOVE_CLASS; + } + + return true; + } + + /** + * Returns the string representation of the HTML Tag Processor. + * + * @since 6.2.0 + * + * @see WP_HTML_Tag_Processor::get_updated_html() + * + * @return string The processed HTML. + */ + public function __toString(): string { + return $this->get_updated_html(); + } + + /** + * Returns the string representation of the HTML Tag Processor. + * + * @since 6.2.0 + * @since 6.2.1 Shifts the internal cursor corresponding to the applied updates. + * @since 6.4.0 No longer calls subclass method `next_tag()` after updating HTML. + * + * @return string The processed HTML. + */ + public function get_updated_html(): string { + $requires_no_updating = 0 === count( $this->classname_updates ) && 0 === count( $this->lexical_updates ); + + /* + * When there is nothing more to update and nothing has already been + * updated, return the original document and avoid a string copy. + */ + if ( $requires_no_updating ) { + return $this->html; + } + + /* + * Keep track of the position right before the current tag. This will + * be necessary for reparsing the current tag after updating the HTML. + */ + $before_current_tag = $this->token_starts_at ?? 0; + + /* + * 1. Apply the enqueued edits and update all the pointers to reflect those changes. + */ + $this->class_name_updates_to_attributes_updates(); + $before_current_tag += $this->apply_attributes_updates( $before_current_tag ); + + /* + * 2. Rewind to before the current tag and reparse to get updated attributes. + * + * At this point the internal cursor points to the end of the tag name. + * Rewind before the tag name starts so that it's as if the cursor didn't + * move; a call to `next_tag()` will reparse the recently-updated attributes + * and additional calls to modify the attributes will apply at this same + * location, but in order to avoid issues with subclasses that might add + * behaviors to `next_tag()`, the internal methods should be called here + * instead. + * + * It's important to note that in this specific place there will be no change + * because the processor was already at a tag when this was called and it's + * rewinding only to the beginning of this very tag before reprocessing it + * and its attributes. + * + * <p>Previous HTML<em>More HTML</em></p> + * ↑ │ back up by the length of the tag name plus the opening < + * └←─┘ back up by strlen("em") + 1 ==> 3 + */ + $this->bytes_already_parsed = $before_current_tag; + $this->base_class_next_token(); + + return $this->html; + } + + /** + * Parses tag query input into internal search criteria. + * + * @since 6.2.0 + * + * @param array|string|null $query { + * Optional. Which tag name to find, having which class, etc. Default is to find any tag. + * + * @type string|null $tag_name Which tag to find, or `null` for "any tag." + * @type int|null $match_offset Find the Nth tag matching all search criteria. + * 1 for "first" tag, 3 for "third," etc. + * Defaults to first tag. + * @type string|null $class_name Tag must contain this class name to match. + * @type string $tag_closers "visit" or "skip": whether to stop on tag closers, e.g. </div>. + * } + */ + private function parse_query( $query ) { + if ( null !== $query && $query === $this->last_query ) { + return; + } + + $this->last_query = $query; + $this->sought_tag_name = null; + $this->sought_class_name = null; + $this->sought_match_offset = 1; + $this->stop_on_tag_closers = false; + + // A single string value means "find the tag of this name". + if ( is_string( $query ) ) { + $this->sought_tag_name = $query; + return; + } + + // An empty query parameter applies no restrictions on the search. + if ( null === $query ) { + return; + } + + // If not using the string interface, an associative array is required. + if ( ! is_array( $query ) ) { + _doing_it_wrong( + __METHOD__, + __( 'The query argument must be an array or a tag name.' ), + '6.2.0' + ); + return; + } + + if ( isset( $query['tag_name'] ) && is_string( $query['tag_name'] ) ) { + $this->sought_tag_name = $query['tag_name']; + } + + if ( isset( $query['class_name'] ) && is_string( $query['class_name'] ) ) { + $this->sought_class_name = $query['class_name']; + } + + if ( isset( $query['match_offset'] ) && is_int( $query['match_offset'] ) && 0 < $query['match_offset'] ) { + $this->sought_match_offset = $query['match_offset']; + } + + if ( isset( $query['tag_closers'] ) ) { + $this->stop_on_tag_closers = 'visit' === $query['tag_closers']; + } + } + + + /** + * Checks whether a given tag and its attributes match the search criteria. + * + * @since 6.2.0 + * + * @return bool Whether the given tag and its attribute match the search criteria. + */ + private function matches(): bool { + if ( $this->is_closing_tag && ! $this->stop_on_tag_closers ) { + return false; + } + + // Does the tag name match the requested tag name in a case-insensitive manner? + if ( isset( $this->sought_tag_name ) && 0 !== substr_compare( $this->html, $this->sought_tag_name, $this->tag_name_starts_at, $this->tag_name_length, true ) ) { + return false; + } + + if ( null !== $this->sought_class_name && ! $this->has_class( $this->sought_class_name ) ) { + return false; + } + + return true; + } + + /** + * Parser Ready State. + * + * Indicates that the parser is ready to run and waiting for a state transition. + * It may not have started yet, or it may have just finished parsing a token and + * is ready to find the next one. + * + * @since 6.5.0 + * + * @access private + */ + const STATE_READY = 'STATE_READY'; + + /** + * Parser Complete State. + * + * Indicates that the parser has reached the end of the document and there is + * nothing left to scan. It finished parsing the last token completely. + * + * @since 6.5.0 + * + * @access private + */ + const STATE_COMPLETE = 'STATE_COMPLETE'; + + /** + * Parser Incomplete Input State. + * + * Indicates that the parser has reached the end of the document before finishing + * a token. It started parsing a token but there is a possibility that the input + * HTML document was truncated in the middle of a token. + * + * The parser is reset at the start of the incomplete token and has paused. There + * is nothing more than can be scanned unless provided a more complete document. + * + * @since 6.5.0 + * + * @access private + */ + const STATE_INCOMPLETE_INPUT = 'STATE_INCOMPLETE_INPUT'; + + /** + * Parser Matched Tag State. + * + * Indicates that the parser has found an HTML tag and it's possible to get + * the tag name and read or modify its attributes (if it's not a closing tag). + * + * @since 6.5.0 + * + * @access private + */ + const STATE_MATCHED_TAG = 'STATE_MATCHED_TAG'; + + /** + * Parser Text Node State. + * + * Indicates that the parser has found a text node and it's possible + * to read and modify that text. + * + * @since 6.5.0 + * + * @access private + */ + const STATE_TEXT_NODE = 'STATE_TEXT_NODE'; + + /** + * Parser CDATA Node State. + * + * Indicates that the parser has found a CDATA node and it's possible + * to read and modify its modifiable text. Note that in HTML there are + * no CDATA nodes outside of foreign content (SVG and MathML). Outside + * of foreign content, they are treated as HTML comments. + * + * @since 6.5.0 + * + * @access private + */ + const STATE_CDATA_NODE = 'STATE_CDATA_NODE'; + + /** + * Indicates that the parser has found an HTML comment and it's + * possible to read and modify its modifiable text. + * + * @since 6.5.0 + * + * @access private + */ + const STATE_COMMENT = 'STATE_COMMENT'; + + /** + * Indicates that the parser has found a DOCTYPE node and it's + * possible to read and modify its modifiable text. + * + * @since 6.5.0 + * + * @access private + */ + const STATE_DOCTYPE = 'STATE_DOCTYPE'; + + /** + * Indicates that the parser has found an empty tag closer `</>`. + * + * Note that in HTML there are no empty tag closers, and they + * are ignored. Nonetheless, the Tag Processor still + * recognizes them as they appear in the HTML stream. + * + * These were historically discussed as a "presumptuous tag + * closer," which would close the nearest open tag, but were + * dismissed in favor of explicitly-closing tags. + * + * @since 6.5.0 + * + * @access private + */ + const STATE_PRESUMPTUOUS_TAG = 'STATE_PRESUMPTUOUS_TAG'; + + /** + * Indicates that the parser has found a "funky comment" + * and it's possible to read and modify its modifiable text. + * + * Example: + * + * </%url> + * </{"wp-bit":"query/post-author"}> + * </2> + * + * Funky comments are tag closers with invalid tag names. Note + * that in HTML these are turn into bogus comments. Nonetheless, + * the Tag Processor recognizes them in a stream of HTML and + * exposes them for inspection and modification. + * + * @since 6.5.0 + * + * @access private + */ + const STATE_FUNKY_COMMENT = 'STATE_WP_FUNKY'; + + /** + * Indicates that a comment was created when encountering abruptly-closed HTML comment. + * + * Example: + * + * <!--> + * <!---> + * + * @since 6.5.0 + */ + const COMMENT_AS_ABRUPTLY_CLOSED_COMMENT = 'COMMENT_AS_ABRUPTLY_CLOSED_COMMENT'; + + /** + * Indicates that a comment would be parsed as a CDATA node, + * were HTML to allow CDATA nodes outside of foreign content. + * + * Example: + * + * <![CDATA[This is a CDATA node.]]> + * + * This is an HTML comment, but it looks like a CDATA node. + * + * @since 6.5.0 + */ + const COMMENT_AS_CDATA_LOOKALIKE = 'COMMENT_AS_CDATA_LOOKALIKE'; + + /** + * Indicates that a comment was created when encountering + * normative HTML comment syntax. + * + * Example: + * + * <!-- this is a comment --> + * + * @since 6.5.0 + */ + const COMMENT_AS_HTML_COMMENT = 'COMMENT_AS_HTML_COMMENT'; + + /** + * Indicates that a comment would be parsed as a Processing + * Instruction node, were they to exist within HTML. + * + * Example: + * + * <?wp __( 'Like' ) ?> + * + * This is an HTML comment, but it looks like a CDATA node. + * + * @since 6.5.0 + */ + const COMMENT_AS_PI_NODE_LOOKALIKE = 'COMMENT_AS_PI_NODE_LOOKALIKE'; + + /** + * Indicates that a comment was created when encountering invalid + * HTML input, a so-called "bogus comment." + * + * Example: + * + * <?nothing special> + * <!{nothing special}> + * + * @since 6.5.0 + */ + const COMMENT_AS_INVALID_HTML = 'COMMENT_AS_INVALID_HTML'; +} diff --git a/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-text-replacement-6-7.php b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-text-replacement-6-7.php new file mode 100644 index 00000000000000..1be784e6e84a53 --- /dev/null +++ b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-text-replacement-6-7.php @@ -0,0 +1,64 @@ +<?php +/** + * HTML API: WP_HTML_Text_Replacement class + * + * @package WordPress + * @subpackage HTML-API + * @since 6.2.0 + */ + +/** + * Core class used by the HTML tag processor as a data structure for replacing + * existing content from start to end, allowing to drastically improve performance. + * + * This class is for internal usage of the WP_HTML_Tag_Processor class. + * + * @access private + * @since 6.2.0 + * @since 6.5.0 Replace `end` with `length` to more closely match `substr()`. + * + * @see WP_HTML_Tag_Processor + */ +class Gutenberg_HTML_Text_Replacement_6_7 { + /** + * Byte offset into document where replacement span begins. + * + * @since 6.2.0 + * + * @var int + */ + public $start; + + /** + * Byte length of span being replaced. + * + * @since 6.5.0 + * + * @var int + */ + public $length; + + /** + * Span of text to insert in document to replace existing content from start to end. + * + * @since 6.2.0 + * + * @var string + */ + public $text; + + /** + * Constructor. + * + * @since 6.2.0 + * + * @param int $start Byte offset into document where replacement span begins. + * @param int $length Byte length of span in document being replaced. + * @param string $text Span of text to insert in document to replace existing content from start to end. + */ + public function __construct( int $start, int $length, string $text ) { + $this->start = $start; + $this->length = $length; + $this->text = $text; + } +} diff --git a/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-token-6-7.php b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-token-6-7.php new file mode 100644 index 00000000000000..95adb54f69b081 --- /dev/null +++ b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-token-6-7.php @@ -0,0 +1,106 @@ +<?php +/** + * HTML API: WP_HTML_Token class + * + * @package WordPress + * @subpackage HTML-API + * @since 6.4.0 + */ + +/** + * Core class used by the HTML processor during HTML parsing + * for referring to tokens in the input HTML string. + * + * This class is designed for internal use by the HTML processor. + * + * @since 6.4.0 + * + * @access private + * + * @see WP_HTML_Processor + */ +class Gutenberg_HTML_Token_6_7 { + /** + * Name of bookmark corresponding to source of token in input HTML string. + * + * Having a bookmark name does not imply that the token still exists. It + * may be that the source token and underlying bookmark was wiped out by + * some modification to the source HTML. + * + * @since 6.4.0 + * + * @var string + */ + public $bookmark_name = null; + + /** + * Name of node; lowercase names such as "marker" are not HTML elements. + * + * For HTML elements/tags this value should come from WP_HTML_Processor::get_tag(). + * + * @since 6.4.0 + * + * @see WP_HTML_Processor::get_tag() + * + * @var string + */ + public $node_name = null; + + /** + * Whether node contains the self-closing flag. + * + * A node may have a self-closing flag when it shouldn't. This value + * only reports if the flag is present in the original HTML. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#self-closing-flag + * + * @var bool + */ + public $has_self_closing_flag = false; + + /** + * Called when token is garbage-collected or otherwise destroyed. + * + * @var callable|null + */ + public $on_destroy = null; + + /** + * Constructor - creates a reference to a token in some external HTML string. + * + * @since 6.4.0 + * + * @param string $bookmark_name Name of bookmark corresponding to location in HTML where token is found. + * @param string $node_name Name of node token represents; if uppercase, an HTML element; if lowercase, a special value like "marker". + * @param bool $has_self_closing_flag Whether the source token contains the self-closing flag, regardless of whether it's valid. + * @param callable|null $on_destroy Optional. Function to call when destroying token, useful for releasing the bookmark. + */ + public function __construct( string $bookmark_name, string $node_name, bool $has_self_closing_flag, ?callable $on_destroy = null ) { + $this->bookmark_name = $bookmark_name; + $this->node_name = $node_name; + $this->has_self_closing_flag = $has_self_closing_flag; + $this->on_destroy = $on_destroy; + } + + /** + * Destructor. + * + * @since 6.4.0 + */ + public function __destruct() { + if ( is_callable( $this->on_destroy ) ) { + call_user_func( $this->on_destroy, $this->bookmark_name ); + } + } + + /** + * Wakeup magic method. + * + * @since 6.4.2 + */ + public function __wakeup() { + throw new \LogicException( __CLASS__ . ' should never be unserialized' ); + } +} diff --git a/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-unsupported-exception-6-7.php b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-unsupported-exception-6-7.php new file mode 100644 index 00000000000000..2de4c0b98d746c --- /dev/null +++ b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-unsupported-exception-6-7.php @@ -0,0 +1,115 @@ +<?php +/** + * HTML API: WP_HTML_Unsupported_Exception class + * + * @package WordPress + * @subpackage HTML-API + * @since 6.4.0 + */ + +/** + * Core class used by the HTML processor during HTML parsing + * for indicating that a given operation is unsupported. + * + * This class is designed for internal use by the HTML processor. + * + * The HTML API aims to operate in compliance with the HTML5 + * specification, but does not implement the full specification. + * In cases where it lacks support it should not cause breakage + * or unexpected behavior. In the cases where it recognizes that + * it cannot proceed, this class is used to abort from any + * operation and signify that the given HTML cannot be processed. + * + * @since 6.4.0 + * @since 6.7.0 Gained contextual information for use in debugging parse failures. + * + * @access private + * + * @see WP_HTML_Processor + */ +class Gutenberg_HTML_Unsupported_Exception_6_7 extends Exception { + /** + * Name of the matched token when the exception was raised, + * if matched on a token. + * + * This does not imply that the token itself was unsupported, but it + * may have been the case that the token triggered part of the HTML + * parsing that isn't supported, such as the adoption agency algorithm. + * + * @since 6.7.0 + * + * @var string + */ + public $token_name; + + /** + * Number of bytes into the input HTML document where the parser was + * parsing when the exception was raised. + * + * Use this to reconstruct context for the failure. + * + * @since 6.7.0 + * + * @var int + */ + public $token_at; + + /** + * Full raw text of the matched token when the exception was raised, + * if matched on a token. + * + * Whereas the `$token_name` will be normalized, this contains the full + * raw text of the token, including original casing, duplicated attributes, + * and other syntactic variations that are normally abstracted in the HTML API. + * + * @since 6.7.0 + * + * @var string + */ + public $token; + + /** + * Stack of open elements when the exception was raised. + * + * Use this to trace the parsing circumstances which led to the exception. + * + * @since 6.7.0 + * + * @var string[] + */ + public $stack_of_open_elements = array(); + + /** + * List of active formatting elements when the exception was raised. + * + * Use this to trace the parsing circumstances which led to the exception. + * + * @since 6.7.0 + * + * @var string[] + */ + public $active_formatting_elements = array(); + + /** + * Constructor function. + * + * @since 6.7.0 + * + * @param string $message Brief message explaining what is unsupported, the reason this exception was raised. + * @param string $token_name Normalized name of matched token when this exception was raised. + * @param int $token_at Number of bytes into source HTML document where matched token starts. + * @param string $token Full raw text of matched token when this exception was raised. + * @param string[] $stack_of_open_elements Stack of open elements when this exception was raised. + * @param string[] $active_formatting_elements List of active formatting elements when this exception was raised. + */ + public function __construct( string $message, string $token_name, int $token_at, string $token, array $stack_of_open_elements, array $active_formatting_elements ) { + parent::__construct( $message ); + + $this->token_name = $token_name; + $this->token_at = $token_at; + $this->token = $token; + + $this->stack_of_open_elements = $stack_of_open_elements; + $this->active_formatting_elements = $active_formatting_elements; + } +} diff --git a/lib/load.php b/lib/load.php index 47ce1011012970..a3ad2e5da2416e 100644 --- a/lib/load.php +++ b/lib/load.php @@ -78,10 +78,11 @@ function gutenberg_is_experiment_enabled( $name ) { // The Token Map was created during 6.6 in order to support the HTML API. It must be loaded before it. require __DIR__ . '/compat/wordpress-6.6/class-gutenberg-token-map-6-6.php'; +require __DIR__ . '/compat/wordpress-6.7/class-gutenberg-token-map-6-7.php'; /* * There are upstream updates to the Tag Processor that may not appear if Gutenberg is running - * a version of WordPress newer than 6.3 and older than the latest `trunk`. This file should + * a version of WordPress newer than 6.4 and older than the latest `trunk`. This file should * always be loaded so that Gutenberg code can run the newest version of the Tag Processor. */ require __DIR__ . '/compat/wordpress-6.4/html-api/class-gutenberg-html-tag-processor-6-4.php'; @@ -101,6 +102,20 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-state-6-6.php'; require __DIR__ . '/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-6-6.php'; +// Type annotations were added in 6.7 so every file is updated. +require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-active-formatting-elements-6-7.php'; +require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-attribute-token-6-7.php'; +require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-decoder-6-7.php'; +require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-open-elements-6-7.php'; +require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-span-6-7.php'; +require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-stack-event-6-7.php'; +require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-text-replacement-6-7.php'; +require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-token-6-7.php'; +require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-unsupported-exception-6-7.php'; +require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-tag-processor-6-7.php'; +require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-processor-state-6-7.php'; +require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-processor-6-7.php'; + /* * The HTML Processor appeared after WordPress 6.3. If Gutenberg is running on a version of * WordPress before it was introduced, these verbatim Core files will be missing. diff --git a/packages/block-library/src/button/index.php b/packages/block-library/src/button/index.php index 6550e50a8f21c0..4a53952ef537f7 100644 --- a/packages/block-library/src/button/index.php +++ b/packages/block-library/src/button/index.php @@ -26,8 +26,8 @@ function render_block_core_button( $attributes, $content ) { * conditional statement will be removed and the core class `WP_HTML_Tag_Processor` * should be used. */ - if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN && class_exists( 'Gutenberg_HTML_Tag_Processor_6_5' ) ) { - $p = new Gutenberg_HTML_Tag_Processor_6_5( $content ); + if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN && class_exists( 'Gutenberg_HTML_Tag_Processor_6_7' ) ) { + $p = new Gutenberg_HTML_Tag_Processor_6_7( $content ); } else { $p = new WP_HTML_Tag_Processor( $content ); } From 8e0a33cdc602b802b308cfde1939b971349246d0 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Sat, 20 Jul 2024 20:06:30 +0900 Subject: [PATCH 0020/1908] Polish create template part modal (#63617) * Polish create template part modal * Add focusOnMount prop Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../src/template-part/edit/title-modal.js | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/block-library/src/template-part/edit/title-modal.js b/packages/block-library/src/template-part/edit/title-modal.js index 0fe4cb08fb8b0d..e1f10c91a67da8 100644 --- a/packages/block-library/src/template-part/edit/title-modal.js +++ b/packages/block-library/src/template-part/edit/title-modal.js @@ -14,7 +14,7 @@ import { export default function TitleModal( { areaLabel, onClose, onSubmit } ) { // Restructure onCreate to set the blocks on local state. // Add modal to confirm title and trigger onCreate. - const [ title, setTitle ] = useState( __( 'Untitled Template Part' ) ); + const [ title, setTitle ] = useState( '' ); const submitForCreation = ( event ) => { event.preventDefault(); @@ -25,26 +25,40 @@ export default function TitleModal( { areaLabel, onClose, onSubmit } ) { <Modal title={ sprintf( // Translators: %s as template part area title ("Header", "Footer", etc.). - __( 'Name and create your new %s' ), + __( 'Create new %s' ), areaLabel.toLowerCase() ) } - overlayClassName="wp-block-template-part__placeholder-create-new__title-form" onRequestClose={ onClose } + focusOnMount="firstContentElement" + size="small" > <form onSubmit={ submitForCreation }> <VStack spacing="5"> <TextControl - __nextHasNoMarginBottom label={ __( 'Name' ) } value={ title } onChange={ setTitle } + placeholder={ __( 'Custom Template Part' ) } + __nextHasNoMarginBottom + __next40pxDefaultSize /> <HStack justify="right"> + <Button + __next40pxDefaultSize + variant="tertiary" + onClick={ () => { + onClose(); + setTitle( '' ); + } } + > + { __( 'Cancel' ) } + </Button> <Button variant="primary" type="submit" accessibleWhenDisabled disabled={ ! title.length } + __next40pxDefaultSize > { __( 'Create' ) } </Button> From 3099d18e430a70c905b429e4a8b5545daead823b Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Sat, 20 Jul 2024 22:42:45 +0900 Subject: [PATCH 0021/1908] Template Part: Add check if create action should be allowed (#63623) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/template-part/edit/placeholder.js | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/packages/block-library/src/template-part/edit/placeholder.js b/packages/block-library/src/template-part/edit/placeholder.js index ff43ee5644ad7c..c7e5e70c970e09 100644 --- a/packages/block-library/src/template-part/edit/placeholder.js +++ b/packages/block-library/src/template-part/edit/placeholder.js @@ -4,6 +4,8 @@ import { __, sprintf } from '@wordpress/i18n'; import { Placeholder, Button, Spinner } from '@wordpress/components'; import { useState } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies @@ -28,6 +30,21 @@ export default function TemplatePartPlaceholder( { templatePartId ); const blockPatterns = useAlternativeBlockPatterns( area, clientId ); + + const { isBlockBasedTheme, canCreateTemplatePart } = useSelect( + ( select ) => { + const { getCurrentTheme, canUser } = select( coreStore ); + return { + isBlockBasedTheme: getCurrentTheme()?.is_block_theme, + canCreateTemplatePart: canUser( 'create', { + kind: 'postType', + name: 'wp_template_part', + } ), + }; + }, + [] + ); + const [ showTitleModal, setShowTitleModal ] = useState( false ); const areaObject = useTemplatePartArea( area ); const createFromBlocks = useCreateTemplatePartFromBlocks( @@ -39,11 +56,19 @@ export default function TemplatePartPlaceholder( { <Placeholder icon={ areaObject.icon } label={ areaObject.label } - instructions={ sprintf( - // Translators: %s as template part area title ("Header", "Footer", etc.). - __( 'Choose an existing %s or create a new one.' ), - areaObject.label.toLowerCase() - ) } + instructions={ + isBlockBasedTheme + ? sprintf( + // Translators: %s as template part area title ("Header", "Footer", etc.). + __( 'Choose an existing %s or create a new one.' ), + areaObject.label.toLowerCase() + ) + : sprintf( + // Translators: %s as template part area title ("Header", "Footer", etc.). + __( 'Choose an existing %s.' ), + areaObject.label.toLowerCase() + ) + } > { isResolving && <Spinner /> } @@ -54,7 +79,7 @@ export default function TemplatePartPlaceholder( { </Button> ) } - { ! isResolving && ( + { ! isResolving && isBlockBasedTheme && canCreateTemplatePart && ( <Button variant="secondary" onClick={ () => { From 39e1abe0ce72adb5e8e1a6e4d98cef132d1536cb Mon Sep 17 00:00:00 2001 From: Amit Raj <77401999+amitraj2203@users.noreply.github.com> Date: Sat, 20 Jul 2024 22:09:33 +0530 Subject: [PATCH 0022/1908] Remove double shadow on Inserter category panel when zoomed out (#63516) * Remove double shadow on Inserter category panel when zoomed out * Add comment --------- Co-authored-by: Rich Tabor <hi@richtabor.com> --- packages/block-editor/src/components/inserter/style.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index d446340939c30e..c7398aadb56ba5 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -679,6 +679,12 @@ $block-inserter-tabs-height: 44px; height: 100%; } } + + // Remove doubled-up shadow that occurs when categories panel is opened, only in zoom out. + // Shadow cannot be removed from the source, as it is required when not zoomed out. + .block-editor-inserter__category-panel { + box-shadow: none; + } } .show-icon-labels { From 959e8e00c6464f7f9b4234622a581b89ae3f8e04 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Sun, 21 Jul 2024 12:27:19 +0530 Subject: [PATCH 0023/1908] Small Typo in Experiment Page (#63773) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> --- lib/experiments-page.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/experiments-page.php b/lib/experiments-page.php index ca5c87eec737be..74a133da05c976 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -184,7 +184,7 @@ function gutenberg_display_experiment_field( $args ) { */ function gutenberg_display_experiment_section() { ?> - <p><?php echo __( "The block editor includes experimental features that are useable while they're in development. Select the ones you'd like to enable. These features are likely to change, so avoid using them in production.", 'gutenberg' ); ?></p> + <p><?php echo __( "The block editor includes experimental features that are usable while they're in development. Select the ones you'd like to enable. These features are likely to change, so avoid using them in production.", 'gutenberg' ); ?></p> <?php } From 645c0e7d4156a0b7275d09791f656f65ac183efe Mon Sep 17 00:00:00 2001 From: Guido Scialfa <dev@guidoscialfa.com> Date: Sun, 21 Jul 2024 12:37:14 +0200 Subject: [PATCH 0024/1908] Fix Typo in Interactivity Api Reference (#63775) Replacing _reqired_ to _required_ Co-authored-by: widoz <wido@git.wordpress.org> Co-authored-by: juanmaguitar <juanmaguitar@git.wordpress.org> --- docs/reference-guides/interactivity-api/api-reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference-guides/interactivity-api/api-reference.md b/docs/reference-guides/interactivity-api/api-reference.md index 0f14906165160c..00030465415323 100644 --- a/docs/reference-guides/interactivity-api/api-reference.md +++ b/docs/reference-guides/interactivity-api/api-reference.md @@ -840,7 +840,7 @@ const { state } = store("myPlugin", { }); ``` -As mentioned above with [`wp-on`](#wp-on), [`wp-on-window`](#wp-on-window), and [`wp-on-document`](#wp-on-document), an async action should be used whenever the `async` versions of the aforementioned directives cannot be used due to the action requiring synchronous access to the `event` object. Synchronous access is reqired whenever the action needs to call `event.preventDefault()`, `event.stopPropagation()`, or `event.stopImmediatePropagation()`. To ensure that the action code does not contribute to a long task, you may manually yield to the main thread after calling the synchronous event API. For example: +As mentioned above with [`wp-on`](#wp-on), [`wp-on-window`](#wp-on-window), and [`wp-on-document`](#wp-on-document), an async action should be used whenever the `async` versions of the aforementioned directives cannot be used due to the action requiring synchronous access to the `event` object. Synchronous access is required whenever the action needs to call `event.preventDefault()`, `event.stopPropagation()`, or `event.stopImmediatePropagation()`. To ensure that the action code does not contribute to a long task, you may manually yield to the main thread after calling the synchronous event API. For example: ```js // Note: In WordPress 6.6 this splitTask function is exported by @wordpress/interactivity. From 1f72de9113786857bb2e2885660b69e1f9fbfa61 Mon Sep 17 00:00:00 2001 From: Robert Anderson <robert@noisysocks.com> Date: Mon, 22 Jul 2024 10:46:32 +1000 Subject: [PATCH 0025/1908] Move useSelectNearestEditableBlock out of src/hooks (#63730) Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- packages/editor/src/components/visual-editor/index.js | 2 +- .../visual-editor}/use-select-nearest-editable-block.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename packages/editor/src/{hooks => components/visual-editor}/use-select-nearest-editable-block.js (98%) diff --git a/packages/editor/src/components/visual-editor/index.js b/packages/editor/src/components/visual-editor/index.js index 17f983293f1d46..8b4877704f5f18 100644 --- a/packages/editor/src/components/visual-editor/index.js +++ b/packages/editor/src/components/visual-editor/index.js @@ -34,7 +34,7 @@ import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; import EditTemplateBlocksNotification from './edit-template-blocks-notification'; import ResizableEditor from '../resizable-editor'; -import useSelectNearestEditableBlock from '../../hooks/use-select-nearest-editable-block'; +import useSelectNearestEditableBlock from './use-select-nearest-editable-block'; import { NAVIGATION_POST_TYPE, PATTERN_POST_TYPE, diff --git a/packages/editor/src/hooks/use-select-nearest-editable-block.js b/packages/editor/src/components/visual-editor/use-select-nearest-editable-block.js similarity index 98% rename from packages/editor/src/hooks/use-select-nearest-editable-block.js rename to packages/editor/src/components/visual-editor/use-select-nearest-editable-block.js index f6e621a25bf43e..5cc84cb7fb5037 100644 --- a/packages/editor/src/hooks/use-select-nearest-editable-block.js +++ b/packages/editor/src/components/visual-editor/use-select-nearest-editable-block.js @@ -8,7 +8,7 @@ import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Internal dependencies */ -import { unlock } from '../lock-unlock'; +import { unlock } from '../../lock-unlock'; const DISTANCE_THRESHOLD = 500; From cd8d59fd351ba1a3e827218abede4c9086aae1c1 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Mon, 22 Jul 2024 05:55:27 +0200 Subject: [PATCH 0026/1908] Background tool: Fix double border. (#63559) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../block-editor/src/components/global-styles/style.scss | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/block-editor/src/components/global-styles/style.scss b/packages/block-editor/src/components/global-styles/style.scss index bbd1964b81cea2..f901506b6b188d 100644 --- a/packages/block-editor/src/components/global-styles/style.scss +++ b/packages/block-editor/src/components/global-styles/style.scss @@ -197,15 +197,22 @@ .components-toggle-control { margin-bottom: 0; } + .components-focal-point-picker-wrapper { background-color: $gray-100; width: 100%; border-radius: $radius-block-ui; border: $border-width solid $gray-300; } + .components-focal-point-picker__media--image { max-height: 180px; } + + // Override focal picker to avoid a double border. + .components-focal-point-picker::after { + content: none; + } } .block-editor-global-styles-background-panel__hidden-tools-panel-item { From 18c5c6ad31b7246c1843c385ed84a8b035394572 Mon Sep 17 00:00:00 2001 From: Robert Anderson <robert@noisysocks.com> Date: Mon, 22 Jul 2024 15:18:01 +1000 Subject: [PATCH 0027/1908] Sync backport changelog action: Use outputs instead of env (#63792) * Sync backport changelog action: Use outputs instead of env * Default empty issue body to '' Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- .github/workflows/sync-backport-changelog.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/sync-backport-changelog.yml b/.github/workflows/sync-backport-changelog.yml index 46465cdaab58ad..76a87f89ba7030 100644 --- a/.github/workflows/sync-backport-changelog.yml +++ b/.github/workflows/sync-backport-changelog.yml @@ -14,10 +14,11 @@ jobs: with: fetch-depth: 2 # Fetch the last two commits to compare changes - name: Check for changes in backport-changelog + id: check-for-changes run: | - git diff --quiet HEAD^ HEAD -- backport-changelog || echo "changes=true" >> $GITHUB_OUTPUT + git diff --quiet HEAD^ HEAD -- backport-changelog || echo "HAS_CHANGES=1" >> "$GITHUB_OUTPUT" - name: Sync Issue - if: env.changes == 'true' + if: steps.check-for-changes.outputs.HAS_CHANGES uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | @@ -52,18 +53,20 @@ jobs: const endDelimiter = '<!-- END TRUNK BACKPORT CHANGELOG -->'; const autoGeneratedContent = `${startDelimiter}\n${processedChangelog}\n${endDelimiter}`; - const regex = new RegExp(`${startDelimiter}[\\s\\S]*${endDelimiter}`); + const existingBody = latestIssue.body ?? ''; + let newBody; - if (regex.test(latestIssue.body)) { + const regex = new RegExp(`${startDelimiter}[\\s\\S]*${endDelimiter}`); + if (regex.test(existingBody)) { // If delimiters exist, replace the content between them - newBody = latestIssue.body.replace(regex, autoGeneratedContent); + newBody = existingBody.replace(regex, autoGeneratedContent); } else { // If delimiters don't exist, append the new content at the end - newBody = `${latestIssue.body}\n\n${autoGeneratedContent}`; + newBody = `${existingBody}\n\n${autoGeneratedContent}`; } - if (newBody.trim() !== latestIssue.body.trim()) { + if (newBody.trim() !== existingBody.trim()) { await github.rest.issues.update({ owner: context.repo.owner, repo: context.repo.repo, From d0b82dacfbb19ca23346bd56137ebd1ea4c9f923 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Mon, 22 Jul 2024 08:45:09 +0200 Subject: [PATCH 0028/1908] Improve the base control help prop documentation. (#63693) * Improve the base control help prop documentation. * Add changelog entry. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/base-control/README.md | 2 +- packages/components/src/base-control/types.ts | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 46e357a008b3f0..ec1736e3adafa9 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -28,6 +28,10 @@ - `Tabs`: Vertical Tabs should be 40px min height. ([#63446](https://github.com/WordPress/gutenberg/pull/63446)). - `ColorPicker`: Use `minimal` variant for `SelectControl` ([#63676](https://github.com/WordPress/gutenberg/pull/63676)). +### Documentation + +- `BaseControl`: Improve the base control help prop documentation. ([#63693](https://github.com/WordPress/gutenberg/pull/63693)). + ## 28.3.0 (2024-07-10) ### Enhancements diff --git a/packages/components/src/base-control/README.md b/packages/components/src/base-control/README.md index bc46629d2b6182..dc3d8c0e29c8e0 100644 --- a/packages/components/src/base-control/README.md +++ b/packages/components/src/base-control/README.md @@ -53,7 +53,7 @@ If true, the label will only be visible to screen readers. ### help -Additional description for the control. The element containing the description will be programmatically associated to the BaseControl by the means of an `aria-describedby` attribute. +Additional description for the control. Only use for meaningful description or instructions for the control. An element containing the description will be programmatically associated to the BaseControl by the means of an `aria-describedby` attribute. - Type: `ReactNode` - Required: No diff --git a/packages/components/src/base-control/types.ts b/packages/components/src/base-control/types.ts index eeb8736cf1b956..07a358d09c14b4 100644 --- a/packages/components/src/base-control/types.ts +++ b/packages/components/src/base-control/types.ts @@ -21,7 +21,7 @@ export type BaseControlProps = { /** * Additional description for the control. * - * The element containing the description will be programmatically associated to the BaseControl by the means of an `aria-describedby` attribute. + * Only use for meaningful description or instructions for the control. An element containing the description will be programmatically associated to the BaseControl by the means of an `aria-describedby` attribute. */ help?: ReactNode; /** From d10c20354457739615420581e27d214b674c17e2 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Mon, 22 Jul 2024 09:37:57 +0200 Subject: [PATCH 0029/1908] Block Bindings: Bootstrap sources defined in the server (#63470) * Move bindings registration to editor provider * Remove sources from editor provider * Create `registerCoreBlockBindingsSources` function * Add `updateBlockBindingsSource` action * Bootstrap sources defined in the server * Change registration to allow server bootstrap * Remove label from post meta and pattern overrides * Remove `updateBlockBindingsSource` * Use `bootstrapBlockBindingsSource` instead * Wrap server registration in the same function * Ensure label is provided when source is not bootstrapped * Remove old import * Add compat filter to expose server sources * Add e2e test * Check if the sources are already added * Change how label is managed * Remove type from object * Use blockBindingsSources name * Fixes from rebase * Add return back and warning * Add backport * Improve comments * Fix getValues/setValues after rebase * Adapt reducer and fixes * Revert args used in `addBlockBindingsSource` Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> --- backport-changelog/6.7/7020.md | 3 ++ lib/compat/wordpress-6.7/block-bindings.php | 40 +++++++++++++++++++ lib/load.php | 1 + packages/blocks/src/api/registration.js | 23 ++++++++--- packages/blocks/src/api/test/registration.js | 17 ++++++++ packages/blocks/src/store/private-actions.js | 14 +++++++ packages/blocks/src/store/reducer.js | 11 ++++- packages/e2e-tests/plugins/block-bindings.php | 16 ++++++-- packages/edit-post/src/index.js | 2 + packages/edit-site/src/index.js | 8 +++- packages/editor/src/bindings/api.js | 32 ++++++++++++++- .../editor/src/bindings/pattern-overrides.js | 2 - packages/editor/src/bindings/post-meta.js | 2 - packages/editor/src/private-apis.js | 6 ++- .../editor/various/block-bindings.spec.js | 29 ++++++++++++++ 15 files changed, 189 insertions(+), 17 deletions(-) create mode 100644 backport-changelog/6.7/7020.md create mode 100644 lib/compat/wordpress-6.7/block-bindings.php diff --git a/backport-changelog/6.7/7020.md b/backport-changelog/6.7/7020.md new file mode 100644 index 00000000000000..8eacb220d340e5 --- /dev/null +++ b/backport-changelog/6.7/7020.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7020 + +* https://github.com/WordPress/gutenberg/pull/63470 diff --git a/lib/compat/wordpress-6.7/block-bindings.php b/lib/compat/wordpress-6.7/block-bindings.php new file mode 100644 index 00000000000000..4c82dc6683f370 --- /dev/null +++ b/lib/compat/wordpress-6.7/block-bindings.php @@ -0,0 +1,40 @@ +<?php +/** + * Temporary compatibility code for new functionalitites/changes related to block bindings APIs present in Gutenberg. + * + * @package gutenberg + */ + +/** + * Adds the block bindings sources registered in the server to the editor settings. + * + * This allows them to be bootstrapped in the editor. + * + * @param array $settings The block editor settings from the `block_editor_settings_all` filter. + * @return array The editor settings including the block bindings sources. + */ +function gutenberg_add_server_block_bindings_sources_to_editor_settings( $editor_settings ) { + // Check if the sources are already exposed in the editor settings. + if ( isset( $editor_settings['blockBindingsSources'] ) ) { + return $editor_settings; + } + + $registered_block_bindings_sources = get_all_registered_block_bindings_sources(); + if ( ! empty( $registered_block_bindings_sources ) ) { + // Initialize array. + $editor_settings['blockBindingsSources'] = array(); + foreach ( $registered_block_bindings_sources as $source_name => $source_properties ) { + // Add source with the label to editor settings. + $editor_settings['blockBindingsSources'][ $source_name ] = array( + 'label' => $source_properties->label, + ); + // Add `usesContext` property if exists. + if ( ! empty( $source_properties->uses_context ) ) { + $editor_settings['blockBindingsSources'][ $source_name ]['usesContext'] = $source_properties->uses_context; + } + } + } + return $editor_settings; +} + +add_filter( 'block_editor_settings_all', 'gutenberg_add_server_block_bindings_sources_to_editor_settings', 10 ); diff --git a/lib/load.php b/lib/load.php index a3ad2e5da2416e..ef1b5cfe50b6a9 100644 --- a/lib/load.php +++ b/lib/load.php @@ -169,6 +169,7 @@ function gutenberg_is_experiment_enabled( $name ) { // WordPress 6.7 compat. require __DIR__ . '/compat/wordpress-6.7/blocks.php'; +require __DIR__ . '/compat/wordpress-6.7/block-bindings.php'; // Experimental features. require __DIR__ . '/experimental/block-editor-settings-mobile.php'; diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 78aab99b11b617..886309d8bd8f3e 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -769,7 +769,7 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { * * @param {Object} source Properties of the source to be registered. * @param {string} source.name The unique and machine-readable name. - * @param {string} source.label Human-readable label. + * @param {string} [source.label] Human-readable label. * @param {Function} [source.getValues] Function to get the values from the source. * @param {Function} [source.setValues] Function to update multiple values connected to the source. * @param {Function} [source.getPlaceholder] Function to get the placeholder when the value is undefined. @@ -800,11 +800,15 @@ export const registerBlockBindingsSource = ( source ) => { canUserEditValue, } = source; - // Check if the source is already registered. const existingSource = unlock( select( blocksStore ) ).getBlockBindingsSource( name ); - if ( existingSource ) { + + /* + * Check if the source has been already registered on the client. + * If the `getValues` property is defined, it could be assumed the source is already registered. + */ + if ( existingSource?.getValues ) { warning( 'Block bindings source "' + name + '" is already registered.' ); @@ -844,12 +848,21 @@ export const registerBlockBindingsSource = ( source ) => { } // Check the `label` property is correct. - if ( ! label ) { + if ( label && existingSource?.label ) { + warning( + 'Block bindings "' + + name + + '" source label is already defined in the server.' + ); + return; + } + + if ( ! label && ! existingSource?.label ) { warning( 'Block bindings source must contain a label.' ); return; } - if ( typeof label !== 'string' ) { + if ( label && typeof label !== 'string' ) { warning( 'Block bindings source label must be a string.' ); return; } diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index bc1057597bcd7a..d36abee2930bfa 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -1512,6 +1512,22 @@ describe( 'blocks', () => { expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); } ); + it( 'should not override label from the server', () => { + // Simulate bootstrapping a source from the server registration. + registerBlockBindingsSource( { + name: 'core/server', + label: 'Server label', + } ); + // Override the source with a different label in the client. + registerBlockBindingsSource( { + name: 'core/server', + label: 'Client label', + } ); + expect( console ).toHaveWarnedWith( + 'Block bindings "core/server" source label is already defined in the server.' + ); + } ); + // Check the `getValues` callback is correct. it( 'should reject invalid getValues callback', () => { registerBlockBindingsSource( { @@ -1600,6 +1616,7 @@ describe( 'blocks', () => { const source = { name: 'core/test-source', label: 'Test Source', + getValues: () => 'value', }; registerBlockBindingsSource( source ); registerBlockBindingsSource( source ); diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index 55cdb2128895f5..6f7581da53de36 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -69,3 +69,17 @@ export function removeBlockBindingsSource( name ) { name, }; } + +/** + * Add bootstrapped block bindings sources, usually initialized from the server. + * + * @param {string} source Name of the source to bootstrap. + */ +export function addBootstrappedBlockBindingsSource( source ) { + return { + type: 'ADD_BOOTSTRAPPED_BLOCK_BINDINGS_SOURCE', + name: source.name, + label: source.label, + usesContext: source.usesContext, + }; +} diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index fc386e7ea9f557..5cffb0abc91973 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -377,13 +377,22 @@ export function blockBindingsSources( state = {}, action ) { return { ...state, [ action.name ]: { - label: action.label, + // Don't override the label if it's already set. + label: state[ action.name ]?.label || action.label, getValues: action.getValues, setValues: action.setValues, getPlaceholder: action.getPlaceholder, canUserEditValue: action.canUserEditValue, }, }; + case 'ADD_BOOTSTRAPPED_BLOCK_BINDINGS_SOURCE': + return { + ...state, + [ action.name ]: { + label: action.label, + usesContext: action.usesContext, + }, + }; case 'REMOVE_BLOCK_BINDINGS_SOURCE': return omit( state, action.name ); } diff --git a/packages/e2e-tests/plugins/block-bindings.php b/packages/e2e-tests/plugins/block-bindings.php index 74aec2adb500fb..b2eb9d797610d5 100644 --- a/packages/e2e-tests/plugins/block-bindings.php +++ b/packages/e2e-tests/plugins/block-bindings.php @@ -8,9 +8,19 @@ */ /** -* Register custom fields. +* Register custom fields and custom block bindings sources. */ -function gutenberg_test_block_bindings_register_custom_fields() { +function gutenberg_test_block_bindings_registration() { + // Register custom block bindings sources. + register_block_bindings_source( + 'core/server-source', + array( + 'label' => 'Server Source', + 'get_value_callback' => function () {}, + ) + ); + + // Register custom fields. register_meta( 'post', 'text_custom_field', @@ -51,4 +61,4 @@ function gutenberg_test_block_bindings_register_custom_fields() { ) ); } -add_action( 'init', 'gutenberg_test_block_bindings_register_custom_fields' ); +add_action( 'init', 'gutenberg_test_block_bindings_registration' ); diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index 2cbf1958719c68..aa3473e6e55d45 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -29,6 +29,7 @@ const { BackButton: __experimentalMainDashboardButton, registerDefaultActions, registerCoreBlockBindingsSources, + bootstrapBlockBindingsSourcesFromServer, } = unlock( editorPrivateApis ); /** @@ -87,6 +88,7 @@ export function initializeEditor( } registerCoreBlocks(); + bootstrapBlockBindingsSourcesFromServer( settings?.blockBindingsSources ); registerCoreBlockBindingsSources(); registerLegacyWidgetBlock( { inserter: false } ); registerWidgetGroupBlock( { inserter: false } ); diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 02d974e037c045..922e2f6ab933ab 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -28,8 +28,11 @@ import { store as editSiteStore } from './store'; import { unlock } from './lock-unlock'; import App from './components/app'; -const { registerDefaultActions, registerCoreBlockBindingsSources } = - unlock( editorPrivateApis ); +const { + registerDefaultActions, + registerCoreBlockBindingsSources, + bootstrapBlockBindingsSourcesFromServer, +} = unlock( editorPrivateApis ); /** * Initializes the site editor screen. @@ -46,6 +49,7 @@ export function initializeEditor( id, settings ) { ( { name } ) => name !== 'core/freeform' ); registerCoreBlocks( coreBlocks ); + bootstrapBlockBindingsSourcesFromServer( settings?.blockBindingsSources ); registerCoreBlockBindingsSources(); dispatch( blocksStore ).setFreeformFallbackBlockName( 'core/html' ); registerLegacyWidgetBlock( { inserter: false } ); diff --git a/packages/editor/src/bindings/api.js b/packages/editor/src/bindings/api.js index 0037f3334215b8..2cfed5168a143e 100644 --- a/packages/editor/src/bindings/api.js +++ b/packages/editor/src/bindings/api.js @@ -1,7 +1,11 @@ /** * WordPress dependencies */ -import { privateApis as blocksPrivateApis } from '@wordpress/blocks'; +import { + privateApis as blocksPrivateApis, + store as blocksStore, +} from '@wordpress/blocks'; +import { dispatch } from '@wordpress/data'; /** * Internal dependencies @@ -25,3 +29,29 @@ export function registerCoreBlockBindingsSources() { registerBlockBindingsSource( patternOverrides ); registerBlockBindingsSource( postMeta ); } + +/** + * Function to bootstrap core block bindings sources defined in the server. + * + * @param {Object} sources Object containing the sources to bootstrap. + * + * @example + * ```js + * import { bootstrapBlockBindingsSourcesFromServer } from '@wordpress/editor'; + * + * bootstrapBlockBindingsSourcesFromServer( sources ); + * ``` + */ +export function bootstrapBlockBindingsSourcesFromServer( sources ) { + if ( sources ) { + const { addBootstrappedBlockBindingsSource } = unlock( + dispatch( blocksStore ) + ); + for ( const [ name, args ] of Object.entries( sources ) ) { + addBootstrappedBlockBindingsSource( { + name, + ...args, + } ); + } + } +} diff --git a/packages/editor/src/bindings/pattern-overrides.js b/packages/editor/src/bindings/pattern-overrides.js index b299211900095d..88c6c73bdc61c1 100644 --- a/packages/editor/src/bindings/pattern-overrides.js +++ b/packages/editor/src/bindings/pattern-overrides.js @@ -1,14 +1,12 @@ /** * WordPress dependencies */ -import { _x } from '@wordpress/i18n'; import { store as blockEditorStore } from '@wordpress/block-editor'; const CONTENT = 'content'; export default { name: 'core/pattern-overrides', - label: _x( 'Pattern Overrides', 'block bindings source' ), getValues( { registry, clientId, context, bindings } ) { const patternOverridesContent = context[ 'pattern/overrides' ]; const { getBlockAttributes } = registry.select( blockEditorStore ); diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index f8161dd47b5c41..aafc784a21bd4a 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -2,7 +2,6 @@ * WordPress dependencies */ import { store as coreDataStore } from '@wordpress/core-data'; -import { _x } from '@wordpress/i18n'; /** * Internal dependencies @@ -11,7 +10,6 @@ import { store as editorStore } from '../store'; export default { name: 'core/post-meta', - label: _x( 'Post Meta', 'block bindings source' ), getPlaceholder( { args } ) { return args.key; }, diff --git a/packages/editor/src/private-apis.js b/packages/editor/src/private-apis.js index 58688a9099e879..f949be8e9321fb 100644 --- a/packages/editor/src/private-apis.js +++ b/packages/editor/src/private-apis.js @@ -24,7 +24,10 @@ import { GlobalStylesProvider, } from './components/global-styles-provider'; import registerDefaultActions from './dataviews/actions'; -import { registerCoreBlockBindingsSources } from './bindings/api'; +import { + registerCoreBlockBindingsSources, + bootstrapBlockBindingsSourcesFromServer, +} from './bindings/api'; const { store: interfaceStore, ...remainingInterfaceApis } = interfaceApis; @@ -45,6 +48,7 @@ lock( privateApis, { ResizableEditor, registerDefaultActions, registerCoreBlockBindingsSources, + bootstrapBlockBindingsSourcesFromServer, // This is a temporary private API while we're updating the site editor to use EditorProvider. useBlockEditorSettings, diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index 222004c7c1bccc..1499e255482c63 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -2172,4 +2172,33 @@ test.describe( 'Block bindings', () => { } ); } ); } ); + + test.describe( 'Sources registration', () => { + test.beforeEach( async ( { admin } ) => { + await admin.createNewPost( { title: 'Test bindings' } ); + } ); + + test( 'should show the label of a source only registered in the server', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + metadata: { + bindings: { + content: { + source: 'core/server-source', + }, + }, + }, + }, + } ); + + const bindingLabel = page.locator( + '.components-item__block-bindings-source' + ); + await expect( bindingLabel ).toHaveText( 'Server Source' ); + } ); + } ); } ); From a0ed76b80193756a799777a376bf696d1e0cc3b7 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Mon, 22 Jul 2024 16:48:28 +0800 Subject: [PATCH 0030/1908] Discussions panel: Distinguish between verb and adjective form of open for internationalization (#63791) Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/editor/src/components/post-comments/index.js | 4 ++-- packages/editor/src/components/post-discussion/panel.js | 8 +++++--- packages/editor/src/components/site-discussion/index.js | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/editor/src/components/post-comments/index.js b/packages/editor/src/components/post-comments/index.js index 75ca1ec0ee016c..c8fac57d00e09d 100644 --- a/packages/editor/src/components/post-comments/index.js +++ b/packages/editor/src/components/post-comments/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; +import { __, _x } from '@wordpress/i18n'; import { RadioControl, __experimentalText as Text, @@ -18,7 +18,7 @@ const COMMENT_OPTIONS = [ { label: ( <> - { __( 'Open' ) } + { _x( 'Open', 'Adjective: e.g. "Comments are open"' ) } <Text variant="muted" size={ 12 }> { __( 'Visitors can add new comments and replies.' ) } </Text> diff --git a/packages/editor/src/components/post-discussion/panel.js b/packages/editor/src/components/post-discussion/panel.js index 718754d56857aa..c539791d404dec 100644 --- a/packages/editor/src/components/post-discussion/panel.js +++ b/packages/editor/src/components/post-discussion/panel.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; +import { __, _x } from '@wordpress/i18n'; import { Dropdown, Button, @@ -62,9 +62,11 @@ function PostDiscussionToggle( { isOpen, onClick } ) { let label; if ( commentStatus === 'open' ) { if ( pingStatus === 'open' ) { - label = __( 'Open' ); + label = _x( 'Open', 'Adjective: e.g. "Comments are open"' ); } else { - label = trackbacksSupported ? __( 'Comments only' ) : __( 'Open' ); + label = trackbacksSupported + ? __( 'Comments only' ) + : _x( 'Open', 'Adjective: e.g. "Comments are open"' ); } } else if ( pingStatus === 'open' ) { label = commentsSupported ? __( 'Pings only' ) : __( 'Pings enabled' ); diff --git a/packages/editor/src/components/site-discussion/index.js b/packages/editor/src/components/site-discussion/index.js index b80b44b1f59c13..b35ba9db476570 100644 --- a/packages/editor/src/components/site-discussion/index.js +++ b/packages/editor/src/components/site-discussion/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; +import { __, _x } from '@wordpress/i18n'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { @@ -25,7 +25,7 @@ const COMMENT_OPTIONS = [ { label: ( <> - { __( 'Open' ) } + { _x( 'Open', 'Adjective: e.g. "Comments are open"' ) } <Text variant="muted" size={ 12 }> { __( 'Visitors can add new comments and replies.' ) } </Text> From dc740601a2e7b48130e7cb595a98bc2c05223a7e Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Mon, 22 Jul 2024 14:26:01 +0530 Subject: [PATCH 0031/1908] Font Library: Improve 'No fonts installed' state when fonts are installed but not activated (#63533) * Change message when fonts are installed but not activated * Add custom installed fonts condition for message * Add installed fonts condition over button text and button action * Fix e2e test Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../components/global-styles/font-families.js | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-families.js b/packages/edit-site/src/components/global-styles/font-families.js index 811d4e66b27a0d..5119ca679e40ad 100644 --- a/packages/edit-site/src/components/global-styles/font-families.js +++ b/packages/edit-site/src/components/global-styles/font-families.js @@ -26,8 +26,14 @@ import { unlock } from '../../lock-unlock'; const { useGlobalSetting } = unlock( blockEditorPrivateApis ); function FontFamilies() { - const { modalTabOpen, setModalTabOpen } = useContext( FontLibraryContext ); + const { baseCustomFonts, modalTabOpen, setModalTabOpen } = + useContext( FontLibraryContext ); const [ fontFamilies ] = useGlobalSetting( 'typography.fontFamilies' ); + const [ baseFontFamilies ] = useGlobalSetting( + 'typography.fontFamilies', + undefined, + 'base' + ); const themeFonts = fontFamilies?.theme ? fontFamilies.theme .map( ( f ) => setUIValuesNeeded( f, { source: 'theme' } ) ) @@ -40,6 +46,11 @@ function FontFamilies() { : []; const hasFonts = 0 < customFonts.length || 0 < themeFonts.length; + const hasInstalledFonts = + hasFonts || + baseFontFamilies?.theme?.length > 0 || + baseCustomFonts?.length > 0; + return ( <> { !! modalTabOpen && ( @@ -89,7 +100,11 @@ function FontFamilies() { { ! hasFonts && ( <VStack> <Subtitle level={ 3 }>{ __( 'Fonts' ) }</Subtitle> - <Text as="p">{ __( 'No fonts installed.' ) }</Text> + <Text as="p"> + { hasInstalledFonts + ? __( 'No fonts activated.' ) + : __( 'No fonts installed.' ) } + </Text> </VStack> ) } <Button @@ -98,11 +113,15 @@ function FontFamilies() { __next40pxDefaultSize onClick={ () => setModalTabOpen( - hasFonts ? 'installed-fonts' : 'upload-fonts' + hasInstalledFonts + ? 'installed-fonts' + : 'upload-fonts' ) } > - { hasFonts ? __( 'Manage fonts' ) : __( 'Add fonts' ) } + { hasInstalledFonts + ? __( 'Manage fonts' ) + : __( 'Add fonts' ) } </Button> </VStack> </> From 47bde1a7696ceae94557dde3fa57cde3cfc9d84e Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 22 Jul 2024 11:22:08 +0200 Subject: [PATCH 0032/1908] Update HeightControl component to label inputs (#63761) * Update HeightControl component to label inputs The current method of using a fieldset for the HeightControl inputs leaves neither of them with a functioning accessible name. This change ensures both the text field and the range slider are named, and semantically linked (with the caveat that aria-controls has little support as of now). * Changelog entry. * Tweak instance ID prefix --------- Co-authored-by: alexstine <alexstine@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: andrewhayward <andrewhayward@git.wordpress.org> --- .../src/components/height-control/index.js | 15 ++++++++++++--- packages/components/CHANGELOG.md | 1 + packages/components/src/range-control/index.tsx | 15 +++++++++++---- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/height-control/index.js b/packages/block-editor/src/components/height-control/index.js index 71753a67beb021..4f5e17381728b3 100644 --- a/packages/block-editor/src/components/height-control/index.js +++ b/packages/block-editor/src/components/height-control/index.js @@ -1,6 +1,7 @@ /** * WordPress dependencies */ +import { useInstanceId } from '@wordpress/compose'; import { useMemo } from '@wordpress/element'; import { BaseControl, @@ -68,6 +69,10 @@ export default function HeightControl( { value, } ) { const customRangeValue = parseFloat( value ); + const id = useInstanceId( HeightControl, 'block-editor-height-control' ); + const labelId = `${ id }__label`; + const inputId = `${ id }__input`; + const rangeId = `${ id }__range`; const [ availableUnits ] = useSettings( 'spacing.units' ); const units = useCustomUnits( { @@ -144,13 +149,14 @@ export default function HeightControl( { }; return ( - <fieldset className="block-editor-height-control"> - <BaseControl.VisualLabel as="legend"> + <div className="block-editor-height-control" id={ id }> + <BaseControl.VisualLabel as="label" for={ inputId } id={ labelId }> { label } </BaseControl.VisualLabel> <Flex> <FlexItem isBlock> <UnitControl + id={ inputId } value={ value } units={ units } onChange={ onChange } @@ -164,6 +170,9 @@ export default function HeightControl( { <FlexItem isBlock> <Spacer marginX={ 2 } marginBottom={ 0 }> <RangeControl + aria-controls={ inputId } + aria-labelledby={ labelId } + id={ rangeId } value={ customRangeValue } min={ 0 } max={ @@ -183,6 +192,6 @@ export default function HeightControl( { </Spacer> </FlexItem> </Flex> - </fieldset> + </div> ); } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index ec1736e3adafa9..6e8250529edd81 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -18,6 +18,7 @@ - `CustomSelectControl`: Stabilize `__experimentalShowSelectedHint` and `options[]. __experimentalHint` props ([#63248](https://github.com/WordPress/gutenberg/pull/63248)). - `SelectControl`: Add `"minimal"` variant ([#63265](https://github.com/WordPress/gutenberg/pull/63265)). - `FontSizePicker`: tidy up internal logic ([#63553](https://github.com/WordPress/gutenberg/pull/63553)). +- `RangeControl`: Allow external `id` prop ([#63761](https://github.com/WordPress/gutenberg/pull/63761)). ### Internal diff --git a/packages/components/src/range-control/index.tsx b/packages/components/src/range-control/index.tsx index b5fff9f56b80d7..d12c1ca913612e 100644 --- a/packages/components/src/range-control/index.tsx +++ b/packages/components/src/range-control/index.tsx @@ -41,6 +41,15 @@ import { space } from '../utils/space'; const noop = () => {}; +function useUniqueId( idProp?: string ) { + const id = useInstanceId( + UnforwardedRangeControl, + 'inspector-range-control' + ); + + return idProp || id; +} + function UnforwardedRangeControl( props: WordPressComponentProps< RangeControlProps, 'input', false >, forwardedRef: ForwardedRef< HTMLInputElement > @@ -56,6 +65,7 @@ function UnforwardedRangeControl( disabled = false, help, hideLabelFromVision = false, + id: idProp, initialPosition, isShiftStepEnabled = true, label, @@ -123,10 +133,7 @@ function UnforwardedRangeControl( !! marks && 'is-marked' ); - const id = useInstanceId( - UnforwardedRangeControl, - 'inspector-range-control' - ); + const id = useUniqueId( idProp ); const describedBy = !! help ? `${ id }__help` : undefined; const enableTooltip = hasTooltip !== false && Number.isFinite( value ); From 8df860e92ff3bce7f515204ff9f9630b59a52232 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Mon, 22 Jul 2024 13:28:41 +0100 Subject: [PATCH 0033/1908] Update 'Front page' badge to 'Homepage' (#63752) --- packages/edit-site/src/components/post-list/index.js | 2 +- packages/edit-site/src/components/post-list/style.scss | 1 + packages/editor/src/components/post-card-panel/index.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 5c8ac934a63355..a614d603316a67 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -428,7 +428,7 @@ export default function PostList( { postType } ) { if ( item.id === frontPageId ) { suffix = ( <span className="edit-site-post-list__title-badge"> - { __( 'Front Page' ) } + { __( 'Homepage' ) } </span> ); } else if ( item.id === postsPageId ) { diff --git a/packages/edit-site/src/components/post-list/style.scss b/packages/edit-site/src/components/post-list/style.scss index c423c2e78d6505..a86783c163c83e 100644 --- a/packages/edit-site/src/components/post-list/style.scss +++ b/packages/edit-site/src/components/post-list/style.scss @@ -72,6 +72,7 @@ font-size: 12px; font-weight: 400; flex-shrink: 0; + line-height: $grid-unit-05 * 5; } .edit-site-post-list__status-icon { diff --git a/packages/editor/src/components/post-card-panel/index.js b/packages/editor/src/components/post-card-panel/index.js index 0d06ff0dca106b..df13f1c8b65a6b 100644 --- a/packages/editor/src/components/post-card-panel/index.js +++ b/packages/editor/src/components/post-card-panel/index.js @@ -104,7 +104,7 @@ export default function PostCardPanel( { actions } ) { { title ? decodeEntities( title ) : __( 'No Title' ) } { isFrontPage && ( <span className="editor-post-card-panel__title-badge"> - { __( 'Front Page' ) } + { __( 'Homepage' ) } </span> ) } { isPostsPage && ( From e78e4e38969933990bf5350295cc3bde6af00631 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Mon, 22 Jul 2024 15:32:49 +0200 Subject: [PATCH 0034/1908] Update: Grid layout: Allow users to adjust grid density (#63367) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> --- .../src/hooks/use-viewport-match/index.js | 4 +- .../src/components/dataviews-context/index.ts | 2 + .../src/components/dataviews-layout/index.tsx | 2 + .../src/components/dataviews/index.tsx | 10 ++ .../src/layouts/grid/density-picker.tsx | 136 ++++++++++++++++++ packages/dataviews/src/layouts/grid/index.tsx | 5 + .../dataviews/src/layouts/grid/style.scss | 36 +++-- packages/dataviews/src/types.ts | 1 + 8 files changed, 183 insertions(+), 13 deletions(-) create mode 100644 packages/dataviews/src/layouts/grid/density-picker.tsx diff --git a/packages/compose/src/hooks/use-viewport-match/index.js b/packages/compose/src/hooks/use-viewport-match/index.js index ebec934b480123..4186045f7d08c4 100644 --- a/packages/compose/src/hooks/use-viewport-match/index.js +++ b/packages/compose/src/hooks/use-viewport-match/index.js @@ -9,7 +9,7 @@ import { createContext, useContext } from '@wordpress/element'; import useMediaQuery from '../use-media-query'; /** - * @typedef {"huge" | "wide" | "large" | "medium" | "small" | "mobile"} WPBreakpoint + * @typedef {"xhuge" | "huge" | "wide" | "xlarge" | "large" | "medium" | "small" | "mobile"} WPBreakpoint */ /** @@ -20,8 +20,10 @@ import useMediaQuery from '../use-media-query'; * @type {Record<WPBreakpoint, number>} */ const BREAKPOINTS = { + xhuge: 1920, huge: 1440, wide: 1280, + xlarge: 1080, large: 960, medium: 782, small: 600, diff --git a/packages/dataviews/src/components/dataviews-context/index.ts b/packages/dataviews/src/components/dataviews-context/index.ts index 39e5e09015658e..3936288b3095b0 100644 --- a/packages/dataviews/src/components/dataviews-context/index.ts +++ b/packages/dataviews/src/components/dataviews-context/index.ts @@ -26,6 +26,7 @@ type DataViewsContextType< Item > = { openedFilter: string | null; setOpenedFilter: ( openedFilter: string | null ) => void; getItemId: ( item: Item ) => string; + density: number; }; const DataViewsContext = createContext< DataViewsContextType< any > >( { @@ -42,6 +43,7 @@ const DataViewsContext = createContext< DataViewsContextType< any > >( { setOpenedFilter: () => {}, openedFilter: null, getItemId: ( item ) => item.id, + density: 0, } ); export default DataViewsContext; diff --git a/packages/dataviews/src/components/dataviews-layout/index.tsx b/packages/dataviews/src/components/dataviews-layout/index.tsx index 960dcf304c0180..eac70763e143c1 100644 --- a/packages/dataviews/src/components/dataviews-layout/index.tsx +++ b/packages/dataviews/src/components/dataviews-layout/index.tsx @@ -27,6 +27,7 @@ export default function DataViewsLayout() { selection, onChangeSelection, setOpenedFilter, + density, } = useContext( DataViewsContext ); const ViewComponent = VIEW_LAYOUTS.find( ( v ) => v.type === view.type ) @@ -44,6 +45,7 @@ export default function DataViewsLayout() { selection={ selection } setOpenedFilter={ setOpenedFilter } view={ view } + density={ density } /> ); } diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index 618e04773c084e..5d45413f03b65a 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -18,6 +18,8 @@ import DataViewsViewConfig from '../dataviews-view-config'; import { normalizeFields } from '../../normalize-fields'; import type { Action, Field, View, SupportedLayouts } from '../../types'; import type { SelectionOrUpdater } from '../../private-types'; +import DensityPicker from '../../layouts/grid/density-picker'; +import { LAYOUT_GRID } from '../../constants'; type ItemWithId = { id: string }; @@ -59,6 +61,7 @@ export default function DataViews< Item >( { onChangeSelection, }: DataViewsProps< Item > ) { const [ selectionState, setSelectionState ] = useState< string[] >( [] ); + const [ density, setDensity ] = useState< number >( 0 ); const isUncontrolled = selectionProperty === undefined || onChangeSelection === undefined; const selection = isUncontrolled ? selectionState : selectionProperty; @@ -95,6 +98,7 @@ export default function DataViews< Item >( { openedFilter, setOpenedFilter, getItemId, + density, } } > <div className="dataviews-wrapper"> @@ -111,6 +115,12 @@ export default function DataViews< Item >( { { search && <DataViewsSearch label={ searchLabel } /> } <DataViewsFilters /> </HStack> + { view.type === LAYOUT_GRID && ( + <DensityPicker + density={ density } + setDensity={ setDensity } + /> + ) } <DataViewsBulkActions /> <DataViewsViewConfig defaultLayouts={ defaultLayouts } /> </HStack> diff --git a/packages/dataviews/src/layouts/grid/density-picker.tsx b/packages/dataviews/src/layouts/grid/density-picker.tsx new file mode 100644 index 00000000000000..df347507fb6340 --- /dev/null +++ b/packages/dataviews/src/layouts/grid/density-picker.tsx @@ -0,0 +1,136 @@ +/** + * WordPress dependencies + */ +import { RangeControl, Button } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { useViewportMatch } from '@wordpress/compose'; +import { plus, lineSolid } from '@wordpress/icons'; +import { useEffect } from '@wordpress/element'; + +const viewportBreaks = { + xhuge: { min: 3, max: 6, default: 5 }, + huge: { min: 2, max: 4, default: 4 }, + xlarge: { min: 2, max: 3, default: 3 }, + large: { min: 1, max: 2, default: 2 }, + mobile: { min: 1, max: 2, default: 2 }, +}; + +function useViewPortBreakpoint() { + const isXHuge = useViewportMatch( 'xhuge', '>=' ); + const isHuge = useViewportMatch( 'huge', '>=' ); + const isXlarge = useViewportMatch( 'xlarge', '>=' ); + const isLarge = useViewportMatch( 'large', '>=' ); + const isMobile = useViewportMatch( 'mobile', '>=' ); + + if ( isXHuge ) { + return 'xhuge'; + } + if ( isHuge ) { + return 'huge'; + } + if ( isXlarge ) { + return 'xlarge'; + } + if ( isLarge ) { + return 'large'; + } + if ( isMobile ) { + return 'mobile'; + } + return null; +} + +// Value is number from 0 to 100 representing how big an item is in the grid +// 100 being the biggest and 0 being the smallest. +// The size is relative to the viewport size, if one a given viewport the +// number of allowed items in a grid is 3 to 6 a 0 ( the smallest ) will mean that the grid will +// have 6 items in a row, a 100 ( the biggest ) will mean that the grid will have 3 items in a row. +// A value of 75 will mean that the grid will have 4 items in a row. +function getRangeValue( + density: number, + breakValues: { min: number; max: number; default: number } +) { + const inverseDensity = breakValues.max - density; + const max = breakValues.max - breakValues.min; + return Math.round( ( inverseDensity * 100 ) / max ); +} + +export default function DensityPicker( { + density, + setDensity, +}: { + density: number; + setDensity: React.Dispatch< React.SetStateAction< number > >; +} ) { + const viewport = useViewPortBreakpoint(); + useEffect( () => { + setDensity( ( _density ) => { + if ( ! viewport || ! _density ) { + return 0; + } + const breakValues = viewportBreaks[ viewport ]; + if ( _density < breakValues.min ) { + return breakValues.min; + } + if ( _density > breakValues.max ) { + return breakValues.max; + } + return _density; + } ); + }, [ setDensity, viewport ] ); + if ( ! viewport ) { + return null; + } + const breakValues = viewportBreaks[ viewport ]; + const densityToUse = density || breakValues.default; + const rangeValue = getRangeValue( densityToUse, breakValues ); + + const step = 100 / ( breakValues.max - breakValues.min + 1 ); + return ( + <> + <Button + size="compact" + icon={ lineSolid } + disabled={ rangeValue <= 0 } + accessibleWhenDisabled + label={ __( 'Decrease size' ) } + onClick={ () => { + setDensity( densityToUse + 1 ); + } } + /> + <RangeControl + __nextHasNoMarginBottom + showTooltip={ false } + className="dataviews-density-picker__range-control" + label={ __( 'Item size' ) } + hideLabelFromVision + value={ rangeValue } + min={ 0 } + max={ 100 } + withInputField={ false } + onChange={ ( value = 0 ) => { + const inverseValue = 100 - value; + setDensity( + Math.round( + ( inverseValue * + ( breakValues.max - breakValues.min ) ) / + 100 + + breakValues.min + ) + ); + } } + step={ step } + /> + <Button + size="compact" + icon={ plus } + disabled={ rangeValue >= 100 } + accessibleWhenDisabled + label={ __( 'Increase size' ) } + onClick={ () => { + setDensity( densityToUse - 1 ); + } } + /> + </> + ); +} diff --git a/packages/dataviews/src/layouts/grid/index.tsx b/packages/dataviews/src/layouts/grid/index.tsx index 0e94843dd34e53..c42b06f2a0ce60 100644 --- a/packages/dataviews/src/layouts/grid/index.tsx +++ b/packages/dataviews/src/layouts/grid/index.tsx @@ -172,6 +172,7 @@ export default function ViewGrid< Item >( { onChangeSelection, selection, view, + density, }: ViewGridProps< Item > ) { const mediaField = fields.find( ( field ) => field.id === view.layout?.mediaField @@ -202,6 +203,9 @@ export default function ViewGrid< Item >( { { visibleFields: [], badgeFields: [] } ); const hasData = !! data?.length; + const gridStyle = density + ? { gridTemplateColumns: `repeat(${ density }, minmax(0, 1fr))` } + : {}; return ( <> { hasData && ( @@ -210,6 +214,7 @@ export default function ViewGrid< Item >( { columns={ 2 } alignment="top" className="dataviews-view-grid" + style={ gridStyle } aria-busy={ isLoading } > { data.map( ( item ) => { diff --git a/packages/dataviews/src/layouts/grid/style.scss b/packages/dataviews/src/layouts/grid/style.scss index 9e18c82a441702..91f0e2b8a381c9 100644 --- a/packages/dataviews/src/layouts/grid/style.scss +++ b/packages/dataviews/src/layouts/grid/style.scss @@ -1,22 +1,10 @@ .dataviews-view-grid { margin-bottom: auto; - grid-template-columns: repeat(1, minmax(0, 1fr)) !important; grid-template-rows: max-content; padding: 0 $grid-unit-60 $grid-unit-30; transition: padding ease-out 0.1s; @include reduce-motion("transition"); - @include break-mobile() { - grid-template-columns: repeat(2, minmax(0, 1fr)) !important; // Todo: eliminate !important dependency - } - - @include break-xlarge() { - grid-template-columns: repeat(3, minmax(0, 1fr)) !important; // Todo: eliminate !important dependency - } - - @include break-huge() { - grid-template-columns: repeat(4, minmax(0, 1fr)) !important; // Todo: eliminate !important dependency - } .dataviews-view-grid__card { height: 100%; @@ -122,6 +110,30 @@ } } +.dataviews-view-grid.dataviews-view-grid { + grid-template-columns: repeat(1, minmax(0, 1fr)); + + @include break-mobile() { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + @include break-xlarge() { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + @include break-huge() { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + + @include break-xhuge() { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } +} + +.dataviews-density-picker__range-control { + width: 200px; +} + .dataviews-view-grid__field-value:empty, .dataviews-view-grid__field:empty { display: none; diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 4f0bfec3d1fcd7..014c25480852c0 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -434,6 +434,7 @@ export interface ViewBaseProps< Item > { selection: string[]; setOpenedFilter: ( fieldId: string ) => void; view: View; + density: number; } export interface ViewTableProps< Item > extends ViewBaseProps< Item > { From a23699c49f8602022fe94f9fb830322ddb90c1c2 Mon Sep 17 00:00:00 2001 From: Adam Silverstein <adamjs@google.com> Date: Mon, 22 Jul 2024 08:15:46 -0600 Subject: [PATCH 0035/1908] Lock post saving during image uploads (#41120) Co-authored-by: adamsilverstein <adamsilverstein@git.wordpress.org> Co-authored-by: ryanwelcher <welcher@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> --- package-lock.json | 10 ++--- packages/editor/package.json | 3 +- .../editor/src/utils/media-upload/index.js | 41 +++++++++++++++++-- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8785725ed594b1..2789eccbaafaa1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49484,7 +49484,6 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true, "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -53423,7 +53422,8 @@ "is-plain-object": "^5.0.0", "memize": "^2.1.0", "react-autosize-textarea": "^7.1.0", - "remove-accents": "^0.5.0" + "remove-accents": "^0.5.0", + "uuid": "^9.0.1" }, "engines": { "node": ">=18.12.0", @@ -68080,7 +68080,8 @@ "is-plain-object": "^5.0.0", "memize": "^2.1.0", "react-autosize-textarea": "^7.1.0", - "remove-accents": "^0.5.0" + "remove-accents": "^0.5.0", + "uuid": "^9.0.1" } }, "@wordpress/element": { @@ -93710,8 +93711,7 @@ "uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" }, "v8-compile-cache": { "version": "2.3.0", diff --git a/packages/editor/package.json b/packages/editor/package.json index 6ecc00e5dccc3f..76ac714a7338b6 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -75,7 +75,8 @@ "is-plain-object": "^5.0.0", "memize": "^2.1.0", "react-autosize-textarea": "^7.1.0", - "remove-accents": "^0.5.0" + "remove-accents": "^0.5.0", + "uuid": "^9.0.1" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/editor/src/utils/media-upload/index.js b/packages/editor/src/utils/media-upload/index.js index f1f60b7c1e99a0..6b39db2443cc33 100644 --- a/packages/editor/src/utils/media-upload/index.js +++ b/packages/editor/src/utils/media-upload/index.js @@ -1,7 +1,12 @@ +/** + * External dependencies + */ +import { v4 as uuid } from 'uuid'; + /** * WordPress dependencies */ -import { select } from '@wordpress/data'; +import { select, dispatch } from '@wordpress/data'; import { uploadMedia } from '@wordpress/media-utils'; /** @@ -32,7 +37,16 @@ export default function mediaUpload( { onFileChange, } ) { const { getCurrentPost, getEditorSettings } = select( editorStore ); + const { + lockPostAutosaving, + unlockPostAutosaving, + lockPostSaving, + unlockPostSaving, + } = dispatch( editorStore ); + const wpAllowedMimeTypes = getEditorSettings().allowedMimeTypes; + const lockKey = `image-upload-${ uuid() }`; + let imageIsUploading = false; maxUploadFileSize = maxUploadFileSize || getEditorSettings().maxUploadFileSize; const currentPost = getCurrentPost(); @@ -41,18 +55,39 @@ export default function mediaUpload( { typeof currentPost?.id === 'number' ? currentPost.id : currentPost?.wp_id; + const setSaveLock = () => { + lockPostSaving( lockKey ); + lockPostAutosaving( lockKey ); + imageIsUploading = true; + }; + const postData = currentPostId ? { post: currentPostId } : {}; + const clearSaveLock = () => { + unlockPostSaving( lockKey ); + unlockPostAutosaving( lockKey ); + imageIsUploading = false; + }; uploadMedia( { allowedTypes, filesList, - onFileChange, + onFileChange: ( file ) => { + if ( ! imageIsUploading ) { + setSaveLock(); + } else { + clearSaveLock(); + } + onFileChange( file ); + }, additionalData: { ...postData, ...additionalData, }, maxUploadFileSize, - onError: ( { message } ) => onError( message ), + onError: ( { message } ) => { + clearSaveLock(); + onError( message ); + }, wpAllowedMimeTypes, } ); } From 39edce550ab15a6029a35b873814d97f75f8c6be Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Mon, 22 Jul 2024 07:16:26 -0700 Subject: [PATCH 0036/1908] =?UTF-8?q?Fix=20canvas=20issues=20by=20removing?= =?UTF-8?q?=20VisualEditor=E2=80=99s=20height=20(#63724)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlinked contributors: wp-seopress. Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> --- packages/edit-post/src/components/layout/style.scss | 5 ----- packages/editor/src/components/editor-interface/style.scss | 4 ++++ packages/editor/src/components/visual-editor/style.scss | 1 - 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/edit-post/src/components/layout/style.scss b/packages/edit-post/src/components/layout/style.scss index b59009e80f0fd3..5fdaceaa002be9 100644 --- a/packages/edit-post/src/components/layout/style.scss +++ b/packages/edit-post/src/components/layout/style.scss @@ -1,8 +1,3 @@ -.edit-post-visual-editor:not(.is-iframed) { - flex: 1 0 auto; - height: auto; -} - .edit-post-layout__metaboxes { flex-shrink: 0; clear: both; diff --git a/packages/editor/src/components/editor-interface/style.scss b/packages/editor/src/components/editor-interface/style.scss index e7e0a93af20906..77f621acc93510 100644 --- a/packages/editor/src/components/editor-interface/style.scss +++ b/packages/editor/src/components/editor-interface/style.scss @@ -1,3 +1,7 @@ .editor-editor-interface .entities-saved-states__panel-header { height: $header-height + $border-width; } + +.editor-visual-editor { + flex: 1 0 auto; +} diff --git a/packages/editor/src/components/visual-editor/style.scss b/packages/editor/src/components/visual-editor/style.scss index b7fbf882a897ba..2d7ed665a957f3 100644 --- a/packages/editor/src/components/visual-editor/style.scss +++ b/packages/editor/src/components/visual-editor/style.scss @@ -1,6 +1,5 @@ .editor-visual-editor { position: relative; - height: 100%; display: block; background-color: $gray-300; // Make this a stacking context to contain the z-index of children elements. From bced5e0bebb322d6ddb47dafae52fedef9943315 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Mon, 22 Jul 2024 07:24:14 -0700 Subject: [PATCH 0037/1908] Editor: Improve Header layout (#62636) * Revise header for resilient centering * Better match existing responsiveness * Fix naming typo * Remove padding from header center to make just a bit more room * Revise style to add space before collapsible block toolbar * Account for potential lack of a back button * Post editor: Leave out the back button instead of hiding it * Hide post preview button at less than small breakpoint * Try keeping the Document Bar visible at less than mobile breakpoints * Revert change to display of post preview button * Revise mobile display of Document Bar * Revert conditional rendering changes * Remove has-back-button class name * Remove has-center class name Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../back-button/fullscreen-mode-close.js | 14 +-- .../src/components/back-button/style.scss | 4 - .../edit-post/src/components/layout/index.js | 9 +- .../collapsible-block-toolbar/index.js | 4 +- .../collapsible-block-toolbar/style.scss | 3 - .../src/components/document-bar/style.scss | 6 +- .../src/components/document-tools/style.scss | 8 +- .../src/components/header/back-button.js | 12 +-- .../editor/src/components/header/index.js | 51 +++++------ .../editor/src/components/header/style.scss | 85 ++++++++++++++----- 10 files changed, 113 insertions(+), 83 deletions(-) diff --git a/packages/edit-post/src/components/back-button/fullscreen-mode-close.js b/packages/edit-post/src/components/back-button/fullscreen-mode-close.js index 59694de16cb925..02eaceb3a35e50 100644 --- a/packages/edit-post/src/components/back-button/fullscreen-mode-close.js +++ b/packages/edit-post/src/components/back-button/fullscreen-mode-close.js @@ -19,23 +19,16 @@ import { store as editorStore } from '@wordpress/editor'; import { store as coreStore } from '@wordpress/core-data'; import { useReducedMotion } from '@wordpress/compose'; -/** - * Internal dependencies - */ -import { store as editPostStore } from '../../store'; - function FullscreenModeClose( { showTooltip, icon, href, initialPost } ) { - const { isActive, isRequestingSiteIcon, postType, siteIconUrl } = useSelect( + const { isRequestingSiteIcon, postType, siteIconUrl } = useSelect( ( select ) => { const { getCurrentPostType } = select( editorStore ); - const { isFeatureActive } = select( editPostStore ); const { getEntityRecord, getPostType, isResolving } = select( coreStore ); const siteData = getEntityRecord( 'root', '__unstableBase', undefined ) || {}; const _postType = initialPost?.type || getCurrentPostType(); return { - isActive: isFeatureActive( 'fullscreenMode' ), isRequestingSiteIcon: isResolving( 'getEntityRecord', [ 'root', '__unstableBase', @@ -50,7 +43,7 @@ function FullscreenModeClose( { showTooltip, icon, href, initialPost } ) { const disableMotion = useReducedMotion(); - if ( ! isActive || ! postType ) { + if ( ! postType ) { return null; } @@ -83,8 +76,7 @@ function FullscreenModeClose( { showTooltip, icon, href, initialPost } ) { buttonIcon = <Icon size="36px" icon={ icon } />; } - const classes = clsx( { - 'edit-post-fullscreen-mode-close': true, + const classes = clsx( 'edit-post-fullscreen-mode-close', { 'has-icon': siteIconUrl, } ); diff --git a/packages/edit-post/src/components/back-button/style.scss b/packages/edit-post/src/components/back-button/style.scss index d6455c707fb1d9..8ffae89e31e054 100644 --- a/packages/edit-post/src/components/back-button/style.scss +++ b/packages/edit-post/src/components/back-button/style.scss @@ -2,10 +2,6 @@ // They need to be updated in both places. .edit-post-fullscreen-mode-close.components-button { - // Do not show the toolbar icon on small screens, - // when Fullscreen Mode is not an option in the "More" menu. - display: none; - @include break-medium() { display: flex; align-items: center; diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index b6ab4629b9e213..9266cbbb10a557 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -37,6 +37,7 @@ import { addQueryArgs } from '@wordpress/url'; import { decodeEntities } from '@wordpress/html-entities'; import { store as coreStore } from '@wordpress/core-data'; import { SlotFillProvider } from '@wordpress/components'; +import { useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies @@ -327,6 +328,12 @@ function Layout( { id: initialPostId, }; }, [ initialPostType, initialPostId ] ); + + const backButton = + useViewportMatch( 'medium' ) && isFullscreenActive ? ( + <BackButton initialPost={ initialPost } /> + ) : null; + return ( <SlotFillProvider> <ErrorBoundary> @@ -373,7 +380,7 @@ function Layout( { <InitPatternModal /> <PluginArea onError={ onPluginAreaError } /> <PostEditorMoreMenu /> - <BackButton initialPost={ initialPost } /> + { backButton } <EditorSnackbars /> </Editor> </ErrorBoundary> diff --git a/packages/editor/src/components/collapsible-block-toolbar/index.js b/packages/editor/src/components/collapsible-block-toolbar/index.js index 87d9b6473d8b61..cafbfecb72516c 100644 --- a/packages/editor/src/components/collapsible-block-toolbar/index.js +++ b/packages/editor/src/components/collapsible-block-toolbar/index.js @@ -24,7 +24,7 @@ import { unlock } from '../../lock-unlock'; const { useHasBlockToolbar } = unlock( blockEditorPrivateApis ); -function CollapsableBlockToolbar( { isCollapsed, onToggle } ) { +export default function CollapsibleBlockToolbar( { isCollapsed, onToggle } ) { const { blockSelectionStart } = useSelect( ( select ) => { return { blockSelectionStart: @@ -73,5 +73,3 @@ function CollapsableBlockToolbar( { isCollapsed, onToggle } ) { </> ); } - -export default CollapsableBlockToolbar; diff --git a/packages/editor/src/components/collapsible-block-toolbar/style.scss b/packages/editor/src/components/collapsible-block-toolbar/style.scss index 18fdc556681449..f559e1a055cdcd 100644 --- a/packages/editor/src/components/collapsible-block-toolbar/style.scss +++ b/packages/editor/src/components/collapsible-block-toolbar/style.scss @@ -77,6 +77,3 @@ } } -.editor-collapsible-block-toolbar__toggle { - margin-left: 2px; // Allow focus ring to be fully visible -} diff --git a/packages/editor/src/components/document-bar/style.scss b/packages/editor/src/components/document-bar/style.scss index 7e51605ad30280..dedf05bc8e7d4f 100644 --- a/packages/editor/src/components/document-bar/style.scss +++ b/packages/editor/src/components/document-bar/style.scss @@ -10,7 +10,7 @@ min-width: 0; background: $gray-100; border-radius: $grid-unit-05; - width: min(100%, 416px); + width: min(100%, 450px); &:hover { background-color: $gray-200; @@ -25,10 +25,6 @@ background: $gray-200; } } - - @include break-large() { - width: min(100%, 450px); - } } .editor-document-bar__command { diff --git a/packages/editor/src/components/document-tools/style.scss b/packages/editor/src/components/document-tools/style.scss index 36c643bbaa027e..a1abfd5abd7aef 100644 --- a/packages/editor/src/components/document-tools/style.scss +++ b/packages/editor/src/components/document-tools/style.scss @@ -65,12 +65,12 @@ .editor-document-tools__left { display: inline-flex; align-items: center; - padding-left: $grid-unit-20; gap: $grid-unit-10; - // Some plugins add buttons here despite best practices. - // Push them a bit rightwards to fit the top toolbar. - margin-right: $grid-unit-10; + // Some plugins add buttons here despite best practices — accommodate them with a gap. + &:not(:last-child) { + margin-inline-end: $grid-unit-10; + } } .editor-document-tools .editor-document-tools__left > .editor-document-tools__inserter-toggle.has-icon { diff --git a/packages/editor/src/components/header/back-button.js b/packages/editor/src/components/header/back-button.js index 3ac689c8415264..a3d682f92970ed 100644 --- a/packages/editor/src/components/header/back-button.js +++ b/packages/editor/src/components/header/back-button.js @@ -9,16 +9,16 @@ import { // Keeping an old name for backward compatibility. const slotName = '__experimentalMainDashboardButton'; +export const useHasBackButton = () => { + const fills = useSlotFills( slotName ); + return Boolean( fills && fills.length ); +}; + const { Fill, Slot } = createSlotFill( slotName ); const BackButton = Fill; -const BackButtonSlot = ( { children } ) => { +const BackButtonSlot = () => { const fills = useSlotFills( slotName ); - const hasFills = Boolean( fills && fills.length ); - - if ( ! hasFills ) { - return children; - } return ( <Slot diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index 4cf28748b2d7a2..2a604229596005 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -1,13 +1,8 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - /** * WordPress dependencies */ import { useSelect } from '@wordpress/data'; -import { useViewportMatch } from '@wordpress/compose'; +import { useMediaQuery, useViewportMatch } from '@wordpress/compose'; import { __unstableMotion as motion } from '@wordpress/components'; import { store as preferencesStore } from '@wordpress/preferences'; import { useState } from '@wordpress/element'; @@ -17,8 +12,8 @@ import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Internal dependencies */ -import BackButton from './back-button'; -import CollapsableBlockToolbar from '../collapsible-block-toolbar'; +import BackButton, { useHasBackButton } from './back-button'; +import CollapsibleBlockToolbar from '../collapsible-block-toolbar'; import DocumentBar from '../document-bar'; import DocumentTools from '../document-tools'; import MoreMenu from '../more-menu'; @@ -55,6 +50,7 @@ function Header( { } ) { const isWideViewport = useViewportMatch( 'large' ); const isLargeViewport = useViewportMatch( 'medium' ); + const isTooNarrowForDocumentBar = useMediaQuery( '(max-width: 403px)' ); const { isTextEditor, isPublishSidebarOpened, @@ -82,21 +78,25 @@ function Header( { }; }, [] ); - const hasTopToolbar = isLargeViewport && hasFixedToolbar; - const [ isBlockToolsCollapsed, setIsBlockToolsCollapsed ] = useState( true ); + const hasCenter = isBlockToolsCollapsed && ! isTooNarrowForDocumentBar; + const hasBackButton = useHasBackButton(); + // The edit-post-header classname is only kept for backward compatibilty // as some plugins might be relying on its presence. return ( <div className="editor-header edit-post-header"> - <motion.div - variants={ backButtonVariations } - transition={ { type: 'tween' } } - > - <BackButton.Slot /> - </motion.div> + { hasBackButton && ( + <motion.div + className="editor-header__back-button" + variants={ backButtonVariations } + transition={ { type: 'tween' } } + > + <BackButton.Slot /> + </motion.div> + ) } <motion.div variants={ toolbarVariations } className="editor-header__toolbar" @@ -105,21 +105,22 @@ function Header( { <DocumentTools disableBlockTools={ forceDisableBlockTools || isTextEditor } /> - { hasTopToolbar && ( - <CollapsableBlockToolbar + { hasFixedToolbar && isLargeViewport && ( + <CollapsibleBlockToolbar isCollapsed={ isBlockToolsCollapsed } onToggle={ setIsBlockToolsCollapsed } /> ) } - <div - className={ clsx( 'editor-header__center', { - 'is-collapsed': - ! isBlockToolsCollapsed && hasTopToolbar, - } ) } + </motion.div> + { hasCenter && ( + <motion.div + className="editor-header__center" + variants={ toolbarVariations } + transition={ { type: 'tween' } } > <DocumentBar title={ title } icon={ icon } /> - </div> - </motion.div> + </motion.div> + ) } <motion.div variants={ toolbarVariations } transition={ { type: 'tween' } } diff --git a/packages/editor/src/components/header/style.scss b/packages/editor/src/components/header/style.scss index e2efba2e9375aa..de690d89a66ae4 100644 --- a/packages/editor/src/components/header/style.scss +++ b/packages/editor/src/components/header/style.scss @@ -1,8 +1,18 @@ .editor-header { height: $header-height; background: $white; - display: flex; - flex-wrap: wrap; + display: grid; + grid-auto-flow: row; + grid-template: auto / $header-height minmax(0, max-content) minmax(min-content, 1fr) $header-height; + &:has(> .editor-header__center) { + grid-template: auto / $header-height min-content 1fr min-content $header-height; + @include break-medium { + grid-template: auto / $header-height minmax(min-content, 1fr) 2fr minmax(min-content, 1fr) $header-height; + } + } + @include break-mobile { + gap: $grid-unit-20; + } align-items: center; // The header should never be wider than the viewport, or buttons might be hidden. Especially relevant at high zoom levels. Related to https://core.trac.wordpress.org/ticket/47603#ticket. max-width: 100vw; @@ -15,19 +25,32 @@ } .editor-header__toolbar { + grid-column: 1 / 3; + // When there is no back button or the viewport is <= mobile the margin keeps the content off + // the starting edge. + > :first-child { + margin-inline: $grid-unit-20 0; + } + + // This is the typical case, the back button takes up the first column. + .editor-header__back-button + & { + grid-column: 2 / 3; + + @include break-mobile { + // Clears the margin; at this breakpoint the parent’s `gap` takes its place. + > :first-child { + margin-inline: 0; + } + } + } display: flex; - // Allow this area to shrink to fit the toolbar buttons. - flex-shrink: 8; - // Take up the space of the toolbar so it can be justified to the left side of the toolbar. - flex-grow: 3; - // Hide the overflow so flex will limit its width. Block toolbar will allow scrolling on fixed toolbar. - overflow: hidden; - // Leave enough room for the focus ring to show. - padding: 2px 0; + // Make narrowing to less than content width possible. Block toolbar will hide overflow and allow scrolling on fixed toolbar. + min-width: 0; align-items: center; - // Allow focus ring to be fully visible on furthest right button. - @include break-medium() { - padding-right: var(--wp-admin-border-width-focus); + // Clip the box while leaving room for focus rings. + clip-path: inset(-2px); + @include break-mobile { + clip-path: none; } .table-of-contents { @@ -37,20 +60,35 @@ display: block; } } + + // Add a gap before the block toolbar or its toggle button when collapsed. + .editor-collapsible-block-toolbar { + margin-inline: $grid-unit 0; + + &.is-collapsed ~ .editor-collapsible-block-toolbar__toggle { + margin-inline: $grid-unit 0; + } + } } .editor-header__center { - flex-grow: 1; + grid-column: 3 / 4; display: flex; justify-content: center; - // Flex items will, by default, refuse to shrink below a minimum - // intrinsic width. In order to shrink this flexbox item, and - // subsequently truncate child text, we set an explicit min-width. - // See https://dev.w3.org/csswg/css-flexbox/#min-size-auto + align-items: center; + // To enable shrinking and truncating of child text, apply an explicit min-width. min-width: 0; - - &.is-collapsed { - display: none; + // Clip the box while leaving room for focus rings. + clip-path: inset(-2px); + // At less than mobile the header’s `gap` is zero so margins are added to create a smaller + // gap around the center’s contents. + @media (max-width: #{$break-mobile - 1}) { + > :first-child { + margin-inline-start: $grid-unit; + } + > :last-child { + margin-inline-end: $grid-unit; + } } } @@ -59,6 +97,11 @@ */ .editor-header__settings { + grid-column: 3 / -1; + .editor-header:has(> .editor-header__center) & { + grid-column: 4 / -1; + } + justify-self: end; display: inline-flex; align-items: center; flex-wrap: nowrap; From 859d48b64dfc10c997f093ebea1a25d557c2f9c4 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 22 Jul 2024 18:22:53 +0200 Subject: [PATCH 0038/1908] DataViews: Bootstrap Quick Edit (#63600) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- lib/experimental/editor-settings.php | 3 + lib/experiments-page.php | 12 + .../src/components/dataviews/index.tsx | 18 +- .../dataviews/src/layouts/table/index.tsx | 2 +- .../edit-site/src/components/layout/index.js | 11 + .../edit-site/src/components/layout/router.js | 12 +- .../src/components/post-edit/index.js | 86 ++++ .../src/components/post-edit/style.scss | 9 + .../src/components/post-fields/index.js | 345 ++++++++++++++++ .../src/components/post-list/index.js | 367 ++---------------- packages/edit-site/src/style.scss | 1 + 11 files changed, 531 insertions(+), 335 deletions(-) create mode 100644 packages/edit-site/src/components/post-edit/index.js create mode 100644 packages/edit-site/src/components/post-edit/style.scss create mode 100644 packages/edit-site/src/components/post-fields/index.js diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index 2af7cafb4838ca..09ac4b6990d919 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -31,6 +31,9 @@ function gutenberg_enable_experiments() { if ( $gutenberg_experiments && array_key_exists( 'gutenberg-zoomed-out-patterns-tab', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableZoomedOutPatternsTab = true', 'before' ); } + if ( $gutenberg_experiments && array_key_exists( 'gutenberg-quick-edit-dataviews', $gutenberg_experiments ) ) { + wp_add_inline_script( 'wp-block-editor', 'window.__experimentalQuickEditDataViews = true', 'before' ); + } } add_action( 'admin_init', 'gutenberg_enable_experiments' ); diff --git a/lib/experiments-page.php b/lib/experiments-page.php index 74a133da05c976..7cc4198c14ef91 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -151,6 +151,18 @@ function gutenberg_initialize_experiments_settings() { ) ); + add_settings_field( + 'gutenberg-quick-edit-dataviews', + __( 'Quick Edit in DataViews', 'gutenberg' ), + 'gutenberg_display_experiment_field', + 'gutenberg-experiments', + 'gutenberg_experiments_section', + array( + 'label' => __( 'Allow access to a quick edit panel in the pages data views.', 'gutenberg' ), + 'id' => 'gutenberg-quick-edit-dataviews', + ) + ); + register_setting( 'gutenberg-experiments', 'gutenberg-experiments' diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index 5d45413f03b65a..c2f75b9b32b1e8 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import type { ReactNode } from 'react'; + /** * WordPress dependencies */ @@ -39,6 +44,7 @@ type DataViewsProps< Item > = { defaultLayouts: SupportedLayouts; selection?: string[]; onChangeSelection?: ( items: string[] ) => void; + header?: ReactNode; } & ( Item extends ItemWithId ? { getItemId?: ( item: Item ) => string } : { getItemId: ( item: Item ) => string } ); @@ -59,6 +65,7 @@ export default function DataViews< Item >( { defaultLayouts, selection: selectionProperty, onChangeSelection, + header, }: DataViewsProps< Item > ) { const [ selectionState, setSelectionState ] = useState< string[] >( [] ); const [ density, setDensity ] = useState< number >( 0 ); @@ -122,7 +129,16 @@ export default function DataViews< Item >( { /> ) } <DataViewsBulkActions /> - <DataViewsViewConfig defaultLayouts={ defaultLayouts } /> + <HStack + spacing={ 1 } + expanded={ false } + style={ { flexShrink: 0 } } + > + <DataViewsViewConfig + defaultLayouts={ defaultLayouts } + /> + { header } + </HStack> </HStack> <DataViewsLayout /> <DataviewsPagination /> diff --git a/packages/dataviews/src/layouts/table/index.tsx b/packages/dataviews/src/layouts/table/index.tsx index 934cff9e23affa..df66f225988a7d 100644 --- a/packages/dataviews/src/layouts/table/index.tsx +++ b/packages/dataviews/src/layouts/table/index.tsx @@ -238,7 +238,7 @@ function TableRow< Item >( { onChangeSelection( selection.includes( id ) ? selection.filter( ( itemId ) => id !== itemId ) - : [ ...selection, id ] + : [ id ] ); } } } diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index a609f616471dbb..a4e4fa57a5bbf1 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -201,6 +201,17 @@ export default function Layout( { route } ) { </div> ) } + { ! isMobileViewport && areas.edit && ( + <div + className="edit-site-layout__area" + style={ { + maxWidth: widths?.edit, + } } + > + { areas.edit } + </div> + ) } + { ! isMobileViewport && areas.preview && ( <div className="edit-site-layout__canvas-container"> { canvasResizer } diff --git a/packages/edit-site/src/components/layout/router.js b/packages/edit-site/src/components/layout/router.js index b89c1a5f256937..3fd0cc560d9433 100644 --- a/packages/edit-site/src/components/layout/router.js +++ b/packages/edit-site/src/components/layout/router.js @@ -26,6 +26,7 @@ import { TEMPLATE_PART_POST_TYPE, TEMPLATE_POST_TYPE, } from '../../utils/constants'; +import { PostEdit } from '../post-edit'; const { useLocation, useHistory } = unlock( routerPrivateApis ); @@ -74,13 +75,15 @@ function useRedirectOldPaths() { export default function useLayoutAreas() { const { params } = useLocation(); - const { postType, postId, path, layout, isCustom, canvas } = params; + const { postType, postId, path, layout, isCustom, canvas, quickEdit } = + params; const hasEditCanvasMode = canvas === 'edit'; useRedirectOldPaths(); // Page list if ( postType === 'page' ) { const isListLayout = layout === 'list' || ! layout; + const showQuickEdit = quickEdit && ! isListLayout; return { key: 'pages', areas: { @@ -92,15 +95,20 @@ export default function useLayoutAreas() { /> ), content: <PostList postType={ postType } />, - preview: ( isListLayout || hasEditCanvasMode ) && <Editor />, + preview: ! showQuickEdit && + ( isListLayout || hasEditCanvasMode ) && <Editor />, mobile: hasEditCanvasMode ? ( <Editor /> ) : ( <PostList postType={ postType } /> ), + edit: showQuickEdit && ( + <PostEdit postType={ postType } postId={ postId } /> + ), }, widths: { content: isListLayout ? 380 : undefined, + edit: showQuickEdit ? 380 : undefined, }, }; } diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js new file mode 100644 index 00000000000000..6e556c56a9152c --- /dev/null +++ b/packages/edit-site/src/components/post-edit/index.js @@ -0,0 +1,86 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { DataForm } from '@wordpress/dataviews'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { store as coreDataStore } from '@wordpress/core-data'; +import { Button } from '@wordpress/components'; +import { useState, useMemo } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import Page from '../page'; +import usePostFields from '../post-fields'; + +function PostEditForm( { postType, postId } ) { + const { item } = useSelect( + ( select ) => { + return { + item: select( coreDataStore ).getEntityRecord( + 'postType', + postType, + postId + ), + }; + }, + [ postType, postId ] + ); + const { saveEntityRecord } = useDispatch( coreDataStore ); + const { fields } = usePostFields(); + const form = { + visibleFields: [ 'title' ], + }; + const [ edits, setEdits ] = useState( {} ); + const itemWithEdits = useMemo( () => { + return { + ...item, + ...edits, + }; + }, [ item, edits ] ); + const onSubmit = ( event ) => { + event.preventDefault(); + saveEntityRecord( 'postType', postType, itemWithEdits ); + setEdits( {} ); + }; + + if ( ! item ) { + return null; + } + + return ( + <form onSubmit={ onSubmit }> + <DataForm + data={ itemWithEdits } + fields={ fields } + form={ form } + onChange={ setEdits } + /> + <Button variant="primary" type="submit"> + { __( 'Update' ) } + </Button> + </form> + ); +} + +export function PostEdit( { postType, postId } ) { + return ( + <Page + className={ clsx( 'edit-site-post-edit', { + 'is-empty': ! postId, + } ) } + label={ __( 'Post Edit' ) } + > + { postId && ( + <PostEditForm postType={ postType } postId={ postId } /> + ) } + { ! postId && <p>{ __( 'Select a page to edit' ) }</p> } + </Page> + ); +} diff --git a/packages/edit-site/src/components/post-edit/style.scss b/packages/edit-site/src/components/post-edit/style.scss new file mode 100644 index 00000000000000..4eaa41b2e8ed70 --- /dev/null +++ b/packages/edit-site/src/components/post-edit/style.scss @@ -0,0 +1,9 @@ +.edit-site-post-edit { + padding: $grid-unit-30; + + &.is-empty .edit-site-page-content { + display: flex; + align-items: center; + justify-content: center; + } +} diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js new file mode 100644 index 00000000000000..5a94b60f5dde0f --- /dev/null +++ b/packages/edit-site/src/components/post-fields/index.js @@ -0,0 +1,345 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; +import { decodeEntities } from '@wordpress/html-entities'; +import { + createInterpolateElement, + useMemo, + useState, +} from '@wordpress/element'; +import { dateI18n, getDate, getSettings } from '@wordpress/date'; +import { + trash, + drafts, + published, + scheduled, + pending, + notAllowed, + commentAuthorAvatar as authorIcon, +} from '@wordpress/icons'; +import { __experimentalHStack as HStack, Icon } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; +import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ +import { + LAYOUT_GRID, + LAYOUT_TABLE, + LAYOUT_LIST, + OPERATOR_IS_ANY, +} from '../../utils/constants'; +import { default as Link, useLink } from '../routes/link'; +import Media from '../media'; + +// See https://github.com/WordPress/gutenberg/issues/55886 +// We do not support custom statutes at the moment. +const STATUSES = [ + { value: 'draft', label: __( 'Draft' ), icon: drafts }, + { value: 'future', label: __( 'Scheduled' ), icon: scheduled }, + { value: 'pending', label: __( 'Pending Review' ), icon: pending }, + { value: 'private', label: __( 'Private' ), icon: notAllowed }, + { value: 'publish', label: __( 'Published' ), icon: published }, + { value: 'trash', label: __( 'Trash' ), icon: trash }, +]; + +const getFormattedDate = ( dateToDisplay ) => + dateI18n( + getSettings().formats.datetimeAbbreviated, + getDate( dateToDisplay ) + ); + +function FeaturedImage( { item, viewType } ) { + const isDisabled = item.status === 'trash'; + const { onClick } = useLink( { + postId: item.id, + postType: item.type, + canvas: 'edit', + } ); + const hasMedia = !! item.featured_media; + const size = + viewType === LAYOUT_GRID + ? [ 'large', 'full', 'medium', 'thumbnail' ] + : [ 'thumbnail', 'medium', 'large', 'full' ]; + const media = hasMedia ? ( + <Media + className="edit-site-post-list__featured-image" + id={ item.featured_media } + size={ size } + /> + ) : null; + const renderButton = viewType !== LAYOUT_LIST && ! isDisabled; + return ( + <div + className={ `edit-site-post-list__featured-image-wrapper is-layout-${ viewType }` } + > + { renderButton ? ( + <button + className="edit-site-post-list__featured-image-button" + type="button" + onClick={ onClick } + aria-label={ item.title?.rendered || __( '(no title)' ) } + > + { media } + </button> + ) : ( + media + ) } + </div> + ); +} + +function PostStatusField( { item } ) { + const status = STATUSES.find( ( { value } ) => value === item.status ); + const label = status?.label || item.status; + const icon = status?.icon; + return ( + <HStack alignment="left" spacing={ 0 }> + { icon && ( + <div className="edit-site-post-list__status-icon"> + <Icon icon={ icon } /> + </div> + ) } + <span>{ label }</span> + </HStack> + ); +} + +function PostAuthorField( { item } ) { + const { text, imageUrl } = useSelect( + ( select ) => { + const { getUser } = select( coreStore ); + const user = getUser( item.author ); + return { + imageUrl: user?.avatar_urls?.[ 48 ], + text: user?.name, + }; + }, + [ item ] + ); + const [ isImageLoaded, setIsImageLoaded ] = useState( false ); + return ( + <HStack alignment="left" spacing={ 0 }> + { !! imageUrl && ( + <div + className={ clsx( 'page-templates-author-field__avatar', { + 'is-loaded': isImageLoaded, + } ) } + > + <img + onLoad={ () => setIsImageLoaded( true ) } + alt={ __( 'Author avatar' ) } + src={ imageUrl } + /> + </div> + ) } + { ! imageUrl && ( + <div className="page-templates-author-field__icon"> + <Icon icon={ authorIcon } /> + </div> + ) } + <span className="page-templates-author-field__name">{ text }</span> + </HStack> + ); +} + +function usePostFields( viewType ) { + const { records: authors, isResolving: isLoadingAuthors } = + useEntityRecords( 'root', 'user', { per_page: -1 } ); + + const { frontPageId, postsPageId } = useSelect( ( select ) => { + const { getEntityRecord } = select( coreStore ); + const siteSettings = getEntityRecord( 'root', 'site' ); + return { + frontPageId: siteSettings?.page_on_front, + postsPageId: siteSettings?.page_for_posts, + }; + }, [] ); + + const fields = useMemo( + () => [ + { + id: 'featured-image', + header: __( 'Featured Image' ), + getValue: ( { item } ) => item.featured_media, + render: ( { item } ) => ( + <FeaturedImage item={ item } viewType={ viewType } /> + ), + enableSorting: false, + }, + { + header: __( 'Title' ), + id: 'title', + type: 'text', + getValue: ( { item } ) => + typeof item.title === 'string' + ? item.title + : item.title?.raw, + render: ( { item } ) => { + const addLink = + [ LAYOUT_TABLE, LAYOUT_GRID ].includes( viewType ) && + item.status !== 'trash'; + const title = addLink ? ( + <Link + params={ { + postId: item.id, + postType: item.type, + canvas: 'edit', + } } + > + { decodeEntities( item.title?.rendered ) || + __( '(no title)' ) } + </Link> + ) : ( + <span> + { decodeEntities( item.title?.rendered ) || + __( '(no title)' ) } + </span> + ); + + let suffix = ''; + if ( item.id === frontPageId ) { + suffix = ( + <span className="edit-site-post-list__title-badge"> + { __( 'Homepage' ) } + </span> + ); + } else if ( item.id === postsPageId ) { + suffix = ( + <span className="edit-site-post-list__title-badge"> + { __( 'Posts Page' ) } + </span> + ); + } + + return ( + <HStack + className="edit-site-post-list__title" + alignment="center" + justify="flex-start" + > + { title } + { suffix } + </HStack> + ); + }, + enableHiding: false, + }, + { + header: __( 'Author' ), + id: 'author', + getValue: ( { item } ) => item._embedded?.author[ 0 ]?.name, + elements: + authors?.map( ( { id, name } ) => ( { + value: id, + label: name, + } ) ) || [], + render: PostAuthorField, + }, + { + header: __( 'Status' ), + id: 'status', + getValue: ( { item } ) => + STATUSES.find( ( { value } ) => value === item.status ) + ?.label ?? item.status, + elements: STATUSES, + render: PostStatusField, + enableSorting: false, + filterBy: { + operators: [ OPERATOR_IS_ANY ], + }, + }, + { + header: __( 'Date' ), + id: 'date', + render: ( { item } ) => { + const isDraftOrPrivate = [ 'draft', 'private' ].includes( + item.status + ); + if ( isDraftOrPrivate ) { + return createInterpolateElement( + sprintf( + /* translators: %s: page creation date */ + __( '<span>Modified: <time>%s</time></span>' ), + getFormattedDate( item.date ) + ), + { + span: <span />, + time: <time />, + } + ); + } + + const isScheduled = item.status === 'future'; + if ( isScheduled ) { + return createInterpolateElement( + sprintf( + /* translators: %s: page creation date */ + __( '<span>Scheduled: <time>%s</time></span>' ), + getFormattedDate( item.date ) + ), + { + span: <span />, + time: <time />, + } + ); + } + + // Pending & Published posts show the modified date if it's newer. + const dateToDisplay = + getDate( item.modified ) > getDate( item.date ) + ? item.modified + : item.date; + + const isPending = item.status === 'pending'; + if ( isPending ) { + return createInterpolateElement( + sprintf( + /* translators: %s: the newest of created or modified date for the page */ + __( '<span>Modified: <time>%s</time></span>' ), + getFormattedDate( dateToDisplay ) + ), + { + span: <span />, + time: <time />, + } + ); + } + + const isPublished = item.status === 'publish'; + if ( isPublished ) { + return createInterpolateElement( + sprintf( + /* translators: %s: the newest of created or modified date for the page */ + __( '<span>Published: <time>%s</time></span>' ), + getFormattedDate( dateToDisplay ) + ), + { + span: <span />, + time: <time />, + } + ); + } + + // Unknow status. + return <time>{ getFormattedDate( item.date ) }</time>; + }, + }, + ], + [ authors, viewType, frontPageId, postsPageId ] + ); + + return { + isLoading: isLoadingAuthors, + fields, + }; +} + +export default usePostFields; diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index a614d603316a67..7ca1be62f6d54b 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -1,74 +1,40 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - /** * WordPress dependencies */ -import { - Button, - __experimentalHStack as HStack, - Icon, -} from '@wordpress/components'; -import { __, sprintf } from '@wordpress/i18n'; +import { Button } from '@wordpress/components'; import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; -import { decodeEntities } from '@wordpress/html-entities'; -import { - createInterpolateElement, - useState, - useMemo, - useCallback, - useEffect, -} from '@wordpress/element'; -import { dateI18n, getDate, getSettings } from '@wordpress/date'; +import { useState, useMemo, useCallback, useEffect } from '@wordpress/element'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { useSelect, useDispatch } from '@wordpress/data'; import { DataViews } from '@wordpress/dataviews'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; -import { - trash, - drafts, - published, - scheduled, - pending, - notAllowed, - commentAuthorAvatar as authorIcon, -} from '@wordpress/icons'; +import { __ } from '@wordpress/i18n'; +import { drawerRight } from '@wordpress/icons'; /** * Internal dependencies */ import Page from '../page'; -import { default as Link, useLink } from '../routes/link'; import { useDefaultViews, defaultLayouts, } from '../sidebar-dataviews/default-views'; import { - LAYOUT_GRID, - LAYOUT_TABLE, - LAYOUT_LIST, OPERATOR_IS_ANY, OPERATOR_IS_NONE, + LAYOUT_LIST, } from '../../utils/constants'; import AddNewPostModal from '../add-new-post'; -import Media from '../media'; import { unlock } from '../../lock-unlock'; import { useEditPostAction } from '../dataviews-actions'; import { usePrevious } from '@wordpress/compose'; +import usePostFields from '../post-fields'; const { usePostActions } = unlock( editorPrivateApis ); const { useLocation, useHistory } = unlock( routerPrivateApis ); const EMPTY_ARRAY = []; -const getFormattedDate = ( dateToDisplay ) => - dateI18n( - getSettings().formats.datetimeAbbreviated, - getDate( dateToDisplay ) - ); - function useView( postType ) { const { params: { activeView = 'all', isCustom = 'false', layout }, @@ -165,138 +131,30 @@ function useView( postType ) { return [ DEFAULT_VIEWS[ postType ][ 0 ].view, setDefaultViewAndUpdateUrl ]; } -// See https://github.com/WordPress/gutenberg/issues/55886 -// We do not support custom statutes at the moment. -const STATUSES = [ - { value: 'draft', label: __( 'Draft' ), icon: drafts }, - { value: 'future', label: __( 'Scheduled' ), icon: scheduled }, - { value: 'pending', label: __( 'Pending Review' ), icon: pending }, - { value: 'private', label: __( 'Private' ), icon: notAllowed }, - { value: 'publish', label: __( 'Published' ), icon: published }, - { value: 'trash', label: __( 'Trash' ), icon: trash }, -]; const DEFAULT_STATUSES = 'draft,future,pending,private,publish'; // All but 'trash'. -function FeaturedImage( { item, viewType } ) { - const isDisabled = item.status === 'trash'; - const { onClick } = useLink( { - postId: item.id, - postType: item.type, - canvas: 'edit', - } ); - const hasMedia = !! item.featured_media; - const size = - viewType === LAYOUT_GRID - ? [ 'large', 'full', 'medium', 'thumbnail' ] - : [ 'thumbnail', 'medium', 'large', 'full' ]; - const media = hasMedia ? ( - <Media - className="edit-site-post-list__featured-image" - id={ item.featured_media } - size={ size } - /> - ) : null; - const renderButton = viewType !== LAYOUT_LIST && ! isDisabled; - return ( - <div - className={ `edit-site-post-list__featured-image-wrapper is-layout-${ viewType }` } - > - { renderButton ? ( - <button - className="edit-site-post-list__featured-image-button" - type="button" - onClick={ onClick } - aria-label={ item.title?.rendered || __( '(no title)' ) } - > - { media } - </button> - ) : ( - media - ) } - </div> - ); -} - function getItemId( item ) { return item.id.toString(); } -function PostStatusField( { item } ) { - const status = STATUSES.find( ( { value } ) => value === item.status ); - const label = status?.label || item.status; - const icon = status?.icon; - return ( - <HStack alignment="left" spacing={ 0 }> - { icon && ( - <div className="edit-site-post-list__status-icon"> - <Icon icon={ icon } /> - </div> - ) } - <span>{ label }</span> - </HStack> - ); -} - -function PostAuthorField( { item } ) { - const { text, imageUrl } = useSelect( - ( select ) => { - const { getUser } = select( coreStore ); - const user = getUser( item.author ); - return { - imageUrl: user?.avatar_urls?.[ 48 ], - text: user?.name, - }; - }, - [ item ] - ); - const [ isImageLoaded, setIsImageLoaded ] = useState( false ); - return ( - <HStack alignment="left" spacing={ 0 }> - { !! imageUrl && ( - <div - className={ clsx( 'page-templates-author-field__avatar', { - 'is-loaded': isImageLoaded, - } ) } - > - <img - onLoad={ () => setIsImageLoaded( true ) } - alt={ __( 'Author avatar' ) } - src={ imageUrl } - /> - </div> - ) } - { ! imageUrl && ( - <div className="page-templates-author-field__icon"> - <Icon icon={ authorIcon } /> - </div> - ) } - <span className="page-templates-author-field__name">{ text }</span> - </HStack> - ); -} - export default function PostList( { postType } ) { const [ view, setView ] = useView( postType ); const history = useHistory(); - const { - params: { postId }, - } = useLocation(); + const location = useLocation(); + const { postId, quickEdit = false } = location.params; const [ selection, setSelection ] = useState( [ postId ] ); const onChangeSelection = useCallback( ( items ) => { setSelection( items ); const { params } = history.getLocationWithParams(); - if ( - ( params.isCustom ?? 'false' ) === 'false' && - view?.type === LAYOUT_LIST - ) { + if ( ( params.isCustom ?? 'false' ) === 'false' ) { history.push( { ...params, postId: items.length === 1 ? items[ 0 ] : undefined, } ); } }, - [ history, view?.type ] + [ history ] ); const queryArgs = useMemo( () => { @@ -357,9 +215,6 @@ export default function PostList( { postType } ) { } }, [ postIdWasDeleted, history ] ); - const { records: authors, isResolving: isLoadingAuthors } = - useEntityRecords( 'root', 'user', { per_page: -1 } ); - const paginationInfo = useMemo( () => ( { totalItems, @@ -368,14 +223,10 @@ export default function PostList( { postType } ) { [ totalItems, totalPages ] ); - const { frontPageId, postsPageId, labels, canCreateRecord } = useSelect( + const { labels, canCreateRecord } = useSelect( ( select ) => { - const { getEntityRecord, getPostType, canUser } = - select( coreStore ); - const siteSettings = getEntityRecord( 'root', 'site' ); + const { getPostType, canUser } = select( coreStore ); return { - frontPageId: siteSettings?.page_on_front, - postsPageId: siteSettings?.page_for_posts, labels: getPostType( postType )?.labels, canCreateRecord: canUser( 'create', { kind: 'postType', @@ -386,175 +237,6 @@ export default function PostList( { postType } ) { [ postType ] ); - // TODO: this should be abstracted into a hook similar to `usePostActions`. - const fields = useMemo( - () => [ - { - id: 'featured-image', - header: __( 'Featured Image' ), - getValue: ( { item } ) => item.featured_media, - render: ( { item } ) => ( - <FeaturedImage item={ item } viewType={ view.type } /> - ), - enableSorting: false, - }, - { - header: __( 'Title' ), - id: 'title', - getValue: ( { item } ) => item.title?.rendered, - render: ( { item } ) => { - const addLink = - [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) && - item.status !== 'trash'; - const title = addLink ? ( - <Link - params={ { - postId: item.id, - postType: item.type, - canvas: 'edit', - } } - > - { decodeEntities( item.title?.rendered ) || - __( '(no title)' ) } - </Link> - ) : ( - <span> - { decodeEntities( item.title?.rendered ) || - __( '(no title)' ) } - </span> - ); - - let suffix = ''; - if ( item.id === frontPageId ) { - suffix = ( - <span className="edit-site-post-list__title-badge"> - { __( 'Homepage' ) } - </span> - ); - } else if ( item.id === postsPageId ) { - suffix = ( - <span className="edit-site-post-list__title-badge"> - { __( 'Posts Page' ) } - </span> - ); - } - - return ( - <HStack - className="edit-site-post-list__title" - alignment="center" - justify="flex-start" - > - { title } - { suffix } - </HStack> - ); - }, - enableHiding: false, - }, - { - header: __( 'Author' ), - id: 'author', - getValue: ( { item } ) => item._embedded?.author[ 0 ]?.name, - elements: - authors?.map( ( { id, name } ) => ( { - value: id, - label: name, - } ) ) || [], - render: PostAuthorField, - }, - { - header: __( 'Status' ), - id: 'status', - getValue: ( { item } ) => - STATUSES.find( ( { value } ) => value === item.status ) - ?.label ?? item.status, - elements: STATUSES, - render: PostStatusField, - enableSorting: false, - filterBy: { - operators: [ OPERATOR_IS_ANY ], - }, - }, - { - header: __( 'Date' ), - id: 'date', - render: ( { item } ) => { - const isDraftOrPrivate = [ 'draft', 'private' ].includes( - item.status - ); - if ( isDraftOrPrivate ) { - return createInterpolateElement( - sprintf( - /* translators: %s: page creation date */ - __( '<span>Modified: <time>%s</time></span>' ), - getFormattedDate( item.date ) - ), - { - span: <span />, - time: <time />, - } - ); - } - - const isScheduled = item.status === 'future'; - if ( isScheduled ) { - return createInterpolateElement( - sprintf( - /* translators: %s: page creation date */ - __( '<span>Scheduled: <time>%s</time></span>' ), - getFormattedDate( item.date ) - ), - { - span: <span />, - time: <time />, - } - ); - } - - // Pending & Published posts show the modified date if it's newer. - const dateToDisplay = - getDate( item.modified ) > getDate( item.date ) - ? item.modified - : item.date; - - const isPending = item.status === 'pending'; - if ( isPending ) { - return createInterpolateElement( - sprintf( - /* translators: %s: the newest of created or modified date for the page */ - __( '<span>Modified: <time>%s</time></span>' ), - getFormattedDate( dateToDisplay ) - ), - { - span: <span />, - time: <time />, - } - ); - } - - const isPublished = item.status === 'publish'; - if ( isPublished ) { - return createInterpolateElement( - sprintf( - /* translators: %s: the newest of created or modified date for the page */ - __( '<span>Published: <time>%s</time></span>' ), - getFormattedDate( dateToDisplay ) - ), - { - span: <span />, - time: <time />, - } - ); - } - - // Unknow status. - return <time>{ getFormattedDate( item.date ) }</time>; - }, - }, - ], - [ authors, view.type, frontPageId, postsPageId ] - ); const postTypeActions = usePostActions( { postType, context: 'list', @@ -577,6 +259,7 @@ export default function PostList( { postType } ) { } ); closeModal(); }; + const { isLoading: isLoadingFields, fields } = usePostFields( view.type ); return ( <Page @@ -608,13 +291,35 @@ export default function PostList( { postType } ) { fields={ fields } actions={ actions } data={ records || EMPTY_ARRAY } - isLoading={ isLoadingMainEntities || isLoadingAuthors } + isLoading={ isLoadingMainEntities || isLoadingFields } view={ view } onChangeView={ setView } selection={ selection } onChangeSelection={ onChangeSelection } getItemId={ getItemId } defaultLayouts={ defaultLayouts } + header={ + window.__experimentalQuickEditDataViews && + view.type !== LAYOUT_LIST && + postType === 'page' && ( + <Button + size="compact" + isPressed={ quickEdit } + icon={ drawerRight } + label={ + ! quickEdit + ? __( 'Show quick edit sidebar' ) + : __( 'Close quick edit sidebar' ) + } + onClick={ () => { + history.push( { + ...location.params, + quickEdit: quickEdit ? undefined : true, + } ); + } } + /> + ) + } /> </Page> ); diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 3a89c67627c9af..473deaeedc5908 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -28,6 +28,7 @@ @import "./components/site-icon/style.scss"; @import "./components/style-book/style.scss"; @import "./components/editor-canvas-container/style.scss"; +@import "./components/post-edit/style.scss"; @import "./components/post-list/style.scss"; @import "./components/resizable-frame/style.scss"; @import "./hooks/push-changes-to-global-styles/style.scss"; From f130e99ac69f4ce2cb9285363967975f96994e0f Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Mon, 22 Jul 2024 20:04:46 +0200 Subject: [PATCH 0039/1908] Update: Simplify and do not pass renderingMode on editor SidebarContent. (#63814) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/editor/src/components/sidebar/index.js | 7 ++----- .../editor/src/components/template-content-panel/index.js | 5 +++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/editor/src/components/sidebar/index.js b/packages/editor/src/components/sidebar/index.js index dbd33459b7f0f8..efca709e0eec75 100644 --- a/packages/editor/src/components/sidebar/index.js +++ b/packages/editor/src/components/sidebar/index.js @@ -51,7 +51,6 @@ const SIDEBAR_ACTIVE_BY_DEFAULT = Platform.select( { const SidebarContent = ( { tabName, keyboardShortcut, - renderingMode, onActionPerformed, extraPanels, } ) => { @@ -112,7 +111,7 @@ const SidebarContent = ( { <Tabs.TabPanel tabId={ sidebars.document } focusable={ false }> <PostSummary onActionPerformed={ onActionPerformed } /> <PluginDocumentSettingPanel.Slot /> - <TemplateContentPanel renderingMode={ renderingMode } /> + <TemplateContentPanel /> <TemplatePartContentPanel /> <PostTransformPanel /> <PostTaxonomiesPanel /> @@ -129,7 +128,7 @@ const SidebarContent = ( { const Sidebar = ( { extraPanels, onActionPerformed } ) => { useAutoSwitchEditorSidebars(); - const { tabName, keyboardShortcut, showSummary, renderingMode } = useSelect( + const { tabName, keyboardShortcut, showSummary } = useSelect( ( select ) => { const shortcut = select( keyboardShortcutsStore @@ -158,7 +157,6 @@ const Sidebar = ( { extraPanels, onActionPerformed } ) => { TEMPLATE_PART_POST_TYPE, NAVIGATION_POST_TYPE, ].includes( select( editorStore ).getCurrentPostType() ), - renderingMode: select( editorStore ).getRenderingMode(), }; }, [] @@ -185,7 +183,6 @@ const Sidebar = ( { extraPanels, onActionPerformed } ) => { tabName={ tabName } keyboardShortcut={ keyboardShortcut } showSummary={ showSummary } - renderingMode={ renderingMode } onActionPerformed={ onActionPerformed } extraPanels={ extraPanels } /> diff --git a/packages/editor/src/components/template-content-panel/index.js b/packages/editor/src/components/template-content-panel/index.js index 14532387ecd059..47d9ab9f2e4067 100644 --- a/packages/editor/src/components/template-content-panel/index.js +++ b/packages/editor/src/components/template-content-panel/index.js @@ -27,9 +27,9 @@ const PAGE_CONTENT_BLOCKS = [ const TEMPLATE_PART_BLOCK = 'core/template-part'; -export default function TemplateContentPanel( { renderingMode } ) { +export default function TemplateContentPanel() { const { enableComplementaryArea } = useDispatch( interfaceStore ); - const { clientIds, postType } = useSelect( ( select ) => { + const { clientIds, postType, renderingMode } = useSelect( ( select ) => { const { getBlocksByName } = select( blockEditorStore ); const { getCurrentPostType } = select( editorStore ); const _postType = getCurrentPostType(); @@ -40,6 +40,7 @@ export default function TemplateContentPanel( { renderingMode } ) { ? TEMPLATE_PART_BLOCK : PAGE_CONTENT_BLOCKS ), + renderingMode: select( editorStore ).getRenderingMode(), }; }, [] ); From 15b48c62b36614da0955c054e4750bbc5c29fcd1 Mon Sep 17 00:00:00 2001 From: Robert Anderson <robert@noisysocks.com> Date: Tue, 23 Jul 2024 11:55:08 +1000 Subject: [PATCH 0040/1908] Run sync when issue is labeled with Sync Backport Changelog (#63793) * Sync backport changelog action: Use outputs instead of env * Default empty issue body to '' * Run sync when issue is labeled with Sync Backport Changelog * Only checkout code on push * Use env again, only run 'Check for changes' on push Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- .github/workflows/sync-backport-changelog.yml | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/.github/workflows/sync-backport-changelog.yml b/.github/workflows/sync-backport-changelog.yml index 76a87f89ba7030..bbc5663cf715be 100644 --- a/.github/workflows/sync-backport-changelog.yml +++ b/.github/workflows/sync-backport-changelog.yml @@ -4,21 +4,33 @@ on: push: branches: - trunk + issues: + types: [labeled] jobs: sync-backport-changelog: name: Sync Core Backport Issue runs-on: ubuntu-latest + if: > + github.event_name == 'push' || + ( + github.event_name == 'issues' && + github.event.action == 'labeled' && + github.event.label.name == '🤖 Sync Backport Changelog' + ) steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 2 # Fetch the last two commits to compare changes - name: Check for changes in backport-changelog - id: check-for-changes + if: github.event_name == 'push' run: | - git diff --quiet HEAD^ HEAD -- backport-changelog || echo "HAS_CHANGES=1" >> "$GITHUB_OUTPUT" + if git diff --quiet HEAD^ HEAD -- backport-changelog; then + echo "skip_sync=true" >> "$GITHUB_ENV" + fi - name: Sync Issue - if: steps.check-for-changes.outputs.HAS_CHANGES + if: ${{ ! env.skip_sync }} uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | From 093fef8b1b1608c1184654ee7c44dc0b18162887 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 23 Jul 2024 15:17:51 +1000 Subject: [PATCH 0041/1908] Search: Prevent override of global button radii in editor (#63789) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> --- packages/block-library/src/search/editor.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/search/editor.scss b/packages/block-library/src/search/editor.scss index effa741249e919..35ccfc5e633fc2 100644 --- a/packages/block-library/src/search/editor.scss +++ b/packages/block-library/src/search/editor.scss @@ -7,7 +7,7 @@ } .wp-block-search { - .wp-block-search__button { + :where(.wp-block-search__button) { height: auto; border-radius: initial; display: flex; From d625b3d19d57e2cc165f4fa8c960e8f2667dce9a Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 23 Jul 2024 15:18:33 +1000 Subject: [PATCH 0042/1908] Comments: Allow button element shadows from theme.json (#63790) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> --- packages/block-library/src/post-comments-form/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/post-comments-form/style.scss b/packages/block-library/src/post-comments-form/style.scss index 7bb7e150e68246..b400849ba83bdb 100644 --- a/packages/block-library/src/post-comments-form/style.scss +++ b/packages/block-library/src/post-comments-form/style.scss @@ -38,7 +38,7 @@ } // Styles copied from button block styles. - input[type="submit"] { + :where(input[type="submit"]) { box-shadow: none; cursor: pointer; display: inline-block; From c7b263deb4a2adbc6e110413de3bbae8a3ae194b Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Tue, 23 Jul 2024 17:32:30 +1000 Subject: [PATCH 0043/1908] Backport docs: update and format (#63830) * updating docs surrounding backports and PHP changes * minor edits * Remove whitespace * Update backport-changelog/readme.md Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> --- backport-changelog/readme.md | 63 +++++++++++++++++++++++++++++++----- lib/README.md | 8 ++--- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/backport-changelog/readme.md b/backport-changelog/readme.md index 200cb9db404865..8066cc6a6fca24 100644 --- a/backport-changelog/readme.md +++ b/backport-changelog/readme.md @@ -1,16 +1,63 @@ # Core Backport Changelog -Any PR that makes changes to be backported to [core](https://github.com/WordPress/wordpress-develop) should log a core PR here. It's possible to have multiple Gutenberg PRs link to a single core backport PR. The core backport PR can remain open as long as wanted/needed. The entries are sorted by core release (in folders), and each entry should be an md file with the core PR number as the file name, and the link to the Gutenberg PR in the file content. The file content should start with the core PR URL, followed by a Markdown list of Gutenberg PRs (see example). Files are used to avoid rebase conflicts. +If you've changed or added files to the Gutenberg plugin, you'll need to confirm whether the changes are to be backported to [WordPress Core](https://github.com/WordPress/wordpress-develop), and therefore featured in the next release of WordPress. -If you think a file path is wrongly flagged as needing a core backport PR, you can add it to the list of exceptions in `.github/workflows/check-backport-changelog.yml`. +On open Gutenberg PRs, changes to certain files are flagged as requiring backporting to WordPress Core, for example, PHP files in `/lib` and PHP unit tests. -## Example +These changes must have a corresponding Core PR before they can be merged to Gutenberg trunk. + +To create a Core PR, first create a [new Trac ticket](https://core.trac.wordpress.org/newticket) and submit a pull request to the [WordPress Core GitHub repository](https://github.com/WordPress/wordpress-develop). + +The Core PR can remain open as long as is required. + +For more information on how to create a Core PR, see the [WordPress Core Handbook](https://make.wordpress.org/core/handbook/contribute/git/github-pull-requests-for-code-review/). + +## How to add a Core Backport PR to the changelog + +After you create Core PR, you'll need to create a corresponding markdown file, and place it within the appropriate release subdirectory. + +The filename is the Core PR number. + +For example, if your Core PR number is `1234` and is slated to be part of the WordPress 6.9 release, the filename will be `1234.md`, and will be placed in the `/backport-changelog/6.9` directory. + +The content of the markdown file should be the Github URL of the Core PR, followed by a list of Gutenberg PR Github URLs whose changes are backported in the Core PR. + +A single Core PR may contain changes from one or multiple Gutenberg PRs. + +### Examples + +Let's say the next WordPress release is 6.9. You have two Gutenberg PRs — `1111` and `2222` — whose changes are backported in a single Core PR, number `1234`. + +First you would create a file named `1234.md` in the `/6.9` folder. + +If the `/6.9` folder doesn't exist, create it. + +Then you would add the following content to your new file: -Path: `{wp-release-number-x.x}/{core-pr-number}.md`, e.g. `6.6/1234.md`. -File content: ```md -https://github.com/WordPress/wordpress-develop/pull/{core-pr-number} +https://github.com/WordPress/wordpress-develop/pull/1234 -* https://github.com/WordPress/gutenberg/pull/{first-gb-pr-number} -* https://github.com/WordPress/gutenberg/pull/{second-gb-pr-number} +* https://github.com/WordPress/gutenberg/pull/1111 +* https://github.com/WordPress/gutenberg/pull/2222 ``` + +If `1234.md` already exists, you would add the Gutenberg PRs to the list in the existing file. + +## Why use individual files? + +For the backport changelog, Gutenberg uses individual files as opposed to a single changelog file to avoid rebase conflicts. + +## Exceptions + +Some Gutenberg PRs may be flagged as needing a core backport PR when they don't, for example when the PR contains minor comment changes, or the changes already exist in Core. + +For individual PRs, there are two Github labels that can be used to exclude a PR from the backport changelog CI check: + +- `Backport from WordPress Core` - Indicates that the PR is a backport from WordPress Core and doesn't need a Core PR. +- `No Core Sync Required` - Indicates that any changes do not need to be synced to WordPress Core. + +If there are specific file or directory changes that should **never** be flagged as requiring a Core backport PR, you can add it to the list of exceptions in [.github/workflows/check-backport-changelog.yml](https://github.com/WordPress/gutenberg/tree/trunk/.github/workflows/check-backport-changelog.yml). + +## Where to get help + +If you're unsure, you can always ask the Gutenberg Core team for help on the Gutenberg PR `@WordPress/gutenberg-core` or via the #core-editor channel in [WordPress Slack](https://make.wordpress.org/chat/). diff --git a/lib/README.md b/lib/README.md index 8e22f676a153d2..9ee05efccffe98 100644 --- a/lib/README.md +++ b/lib/README.md @@ -192,12 +192,12 @@ Existing comments in `lib/load.php` should act as a guide. ## When to sync changes to Gutenberg PHP with Core and vice versa -If you've changed or added PHP files to the Gutenberg plugin, you'll need to confirm whether the changes are to be synced to WordPress Core, and therefore featured in the next release of WordPress. +On open Gutenberg PRs, changes to certain files are flagged as requiring syncing (also called "backporting") to WordPress Core, for example, PHP files in `/lib` and PHP unit tests. -The Gutenberg GitHub pull request in question should be labeled with the `Needs PHP backport` label if the changes are to be synced to Core. +The CI checks will indicate whether you need to create a Core PR. If you do, you'll need to create a corresponding markdown file and place it within the appropriate release subdirectory in the [Core backport changelog](https://github.com/WordPress/gutenberg/tree/trunk/backport-changelog/). -If so, it is recommended to create a [new Trac ticket](https://core.trac.wordpress.org/newticket) and submit a pull request to the [WordPress Core GitHub repository](https://github.com/WordPress/wordpress-develop) soon after your pull request is merged. +For more information, please refer to the [Core backport changelog documentation](https://github.com/WordPress/gutenberg/tree/trunk/backport-changelog/readme.md). -So too, if you've made changes in WordPress Core to code that also lives in the Gutenberg plugin, these changes will need to be synced (often called "backporting") to Gutenberg. The relevant Gutenberg GitHub pull request should be labeled with the `Backport from WordPress Core` label. +So too, if you've made changes in WordPress Core to code that also lives in the Gutenberg plugin, these changes will need to be synced to Gutenberg. The relevant Gutenberg GitHub pull request should be labeled with the `Backport from WordPress Core` label. If you're unsure, you can always ask for help in the #core-editor channel in [WordPress Slack](https://make.wordpress.org/chat/). From fd26970fc6842a1657da33e65d813b03221f2abb Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Tue, 23 Jul 2024 17:33:28 +1000 Subject: [PATCH 0044/1908] Block editor settings: add missing global styles links dependencies (#63823) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- .../editor/src/components/provider/use-block-editor-settings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 231e2df8f91e4d..1c1881bb00f405 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -353,6 +353,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { setIsInserterOpened, sectionRootClientId, globalStylesData, + globalStylesLinksData, ] ); } From acaffc15e1279a8889fb97560a11f1f814c128f3 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Tue, 23 Jul 2024 15:43:45 +0800 Subject: [PATCH 0045/1908] Avoid stripping attributes via group block migration when no layout is specified (#63837) Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> --- packages/block-library/src/group/deprecated.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/block-library/src/group/deprecated.js b/packages/block-library/src/group/deprecated.js index fcc2b249d2229f..ff7ed7e42d093b 100644 --- a/packages/block-library/src/group/deprecated.js +++ b/packages/block-library/src/group/deprecated.js @@ -109,15 +109,11 @@ const deprecated = [ ); }, isEligible: ( { layout } ) => - ! layout || - layout.inherit || - ( layout.contentSize && layout.type !== 'constrained' ), + layout?.inherit || + ( layout?.contentSize && layout?.type !== 'constrained' ), migrate: ( attributes ) => { const { layout = null } = attributes; - if ( ! layout ) { - return attributes; - } - if ( layout.inherit || layout.contentSize ) { + if ( layout?.inherit || layout?.contentSize ) { return { ...attributes, layout: { From 90a058f0457caf03e40a4b327bb18f0eb5aa0a5c Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 23 Jul 2024 16:54:39 +0900 Subject: [PATCH 0046/1908] Site Editor Navigation Commands: Add permission check (#63798) * Site Editor Navigation Commands: Add permission check * Replate `"wp_template"` with `templateType` Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: dlh01 <dlh@git.wordpress.org> --- packages/core-commands/src/hooks.js | 12 ----- .../src/site-editor-navigation-commands.js | 53 ++++++++++++++----- 2 files changed, 40 insertions(+), 25 deletions(-) delete mode 100644 packages/core-commands/src/hooks.js diff --git a/packages/core-commands/src/hooks.js b/packages/core-commands/src/hooks.js deleted file mode 100644 index 0622a970680c11..00000000000000 --- a/packages/core-commands/src/hooks.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * WordPress dependencies - */ -import { store as coreStore } from '@wordpress/core-data'; -import { useSelect } from '@wordpress/data'; - -export function useIsBlockBasedTheme() { - return useSelect( - ( select ) => select( coreStore ).getCurrentTheme()?.is_block_theme, - [] - ); -} diff --git a/packages/core-commands/src/site-editor-navigation-commands.js b/packages/core-commands/src/site-editor-navigation-commands.js index cb38ea2bb25532..4679d4d1523c89 100644 --- a/packages/core-commands/src/site-editor-navigation-commands.js +++ b/packages/core-commands/src/site-editor-navigation-commands.js @@ -23,7 +23,6 @@ import { decodeEntities } from '@wordpress/html-entities'; /** * Internal dependencies */ -import { useIsBlockBasedTheme } from './hooks'; import { unlock } from './lock-unlock'; import { orderEntityRecordsBySearch } from './utils/order-entity-records-by-search'; @@ -51,7 +50,19 @@ function useDebouncedValue( value ) { const getNavigationCommandLoaderPerPostType = ( postType ) => function useNavigationCommandLoader( { search } ) { const history = useHistory(); - const isBlockBasedTheme = useIsBlockBasedTheme(); + const { isBlockBasedTheme, canCreateTemplate } = useSelect( + ( select ) => { + return { + isBlockBasedTheme: + select( coreStore ).getCurrentTheme()?.is_block_theme, + canCreateTemplate: select( coreStore ).canUser( 'create', { + kind: 'postType', + name: 'wp_template', + } ), + }; + }, + [] + ); const delayedSearch = useDebouncedValue( search ); const { records, isLoading } = useSelect( ( select ) => { @@ -100,6 +111,7 @@ const getNavigationCommandLoaderPerPostType = ( postType ) => }; if ( + ! canCreateTemplate || postType === 'post' || ( postType === 'page' && ! isBlockBasedTheme ) ) { @@ -142,7 +154,7 @@ const getNavigationCommandLoaderPerPostType = ( postType ) => }, }; } ); - }, [ records, isBlockBasedTheme, history ] ); + }, [ canCreateTemplate, records, isBlockBasedTheme, history ] ); return { commands, @@ -153,7 +165,19 @@ const getNavigationCommandLoaderPerPostType = ( postType ) => const getNavigationCommandLoaderPerTemplate = ( templateType ) => function useNavigationCommandLoader( { search } ) { const history = useHistory(); - const isBlockBasedTheme = useIsBlockBasedTheme(); + const { isBlockBasedTheme, canCreateTemplate } = useSelect( + ( select ) => { + return { + isBlockBasedTheme: + select( coreStore ).getCurrentTheme()?.is_block_theme, + canCreateTemplate: select( coreStore ).canUser( 'create', { + kind: 'postType', + name: templateType, + } ), + }; + }, + [] + ); const { records, isLoading } = useSelect( ( select ) => { const { getEntityRecords } = select( coreStore ); const query = { per_page: -1 }; @@ -177,8 +201,8 @@ const getNavigationCommandLoaderPerTemplate = ( templateType ) => const commands = useMemo( () => { if ( - ! isBlockBasedTheme && - ! templateType === 'wp_template_part' + ! canCreateTemplate || + ( ! isBlockBasedTheme && ! templateType === 'wp_template_part' ) ) { return []; } @@ -243,7 +267,7 @@ const getNavigationCommandLoaderPerTemplate = ( templateType ) => } ); } return result; - }, [ isBlockBasedTheme, orderedRecords, history ] ); + }, [ canCreateTemplate, isBlockBasedTheme, orderedRecords, history ] ); return { commands, @@ -265,13 +289,16 @@ function useSiteEditorBasicNavigationCommands() { const isSiteEditor = getPath( window.location.href )?.includes( 'site-editor.php' ); - const canCreateTemplate = useSelect( ( select ) => { - return select( coreStore ).canUser( 'create', { - kind: 'postType', - name: 'wp_template', - } ); + const { isBlockBasedTheme, canCreateTemplate } = useSelect( ( select ) => { + return { + isBlockBasedTheme: + select( coreStore ).getCurrentTheme()?.is_block_theme, + canCreateTemplate: select( coreStore ).canUser( 'create', { + kind: 'postType', + name: 'wp_template', + } ), + }; }, [] ); - const isBlockBasedTheme = useIsBlockBasedTheme(); const commands = useMemo( () => { const result = []; From 150296950d4023aa722635fbca7786f8cab4f5d9 Mon Sep 17 00:00:00 2001 From: Alex Lende <alex+github.com@lende.xyz> Date: Tue, 23 Jul 2024 03:16:32 -0500 Subject: [PATCH 0047/1908] Update JSON Schemas to Draft 7 (#63583) * Run ajv-cli migrate on JSON schemas * Migrate additionalProperties to propertyNames where reuse is needed * Update tests to use Ajv Draft 7 * Remove ajv-draft-04 * Fix test string * Add tests for all propertyNames changes Unlinked contributors: DivyanshVinayak23. Co-authored-by: ajlende <ajlende@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- package-lock.json | 21 -- package.json | 1 - schemas/json/block.json | 2 +- schemas/json/font-collection.json | 2 +- schemas/json/theme.json | 293 ++++++++++-------- schemas/json/wp-env.json | 48 +-- test/integration/blocks-schema.test.js | 4 +- .../fixtures/schemas/settings.json | 7 + .../schemas/settingsPropertiesComplete.json | 11 + test/integration/fixtures/schemas/styles.json | 7 + ...ylesElementsPropertiesComplete_button.json | 11 + ...stylesElementsPropertiesComplete_link.json | 11 + .../stylesPropertiesAndElementsComplete.json | 11 + .../schemas/stylesPropertiesComplete.json | 13 + ...tylesVariationBlockPropertiesComplete.json | 15 + .../schemas/stylesVariationProperties.json | 11 + .../stylesVariationPropertiesComplete.json | 15 + test/integration/theme-schema.test.js | 17 +- 18 files changed, 317 insertions(+), 183 deletions(-) create mode 100644 test/integration/fixtures/schemas/settings.json create mode 100644 test/integration/fixtures/schemas/settingsPropertiesComplete.json create mode 100644 test/integration/fixtures/schemas/styles.json create mode 100644 test/integration/fixtures/schemas/stylesElementsPropertiesComplete_button.json create mode 100644 test/integration/fixtures/schemas/stylesElementsPropertiesComplete_link.json create mode 100644 test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete.json create mode 100644 test/integration/fixtures/schemas/stylesPropertiesComplete.json create mode 100644 test/integration/fixtures/schemas/stylesVariationBlockPropertiesComplete.json create mode 100644 test/integration/fixtures/schemas/stylesVariationProperties.json create mode 100644 test/integration/fixtures/schemas/stylesVariationPropertiesComplete.json diff --git a/package-lock.json b/package-lock.json index 2789eccbaafaa1..0318a97778e11e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -160,7 +160,6 @@ "@wordpress/scripts": "file:packages/scripts", "@wordpress/stylelint-config": "file:packages/stylelint-config", "ajv": "8.7.1", - "ajv-draft-04": "1.0.0", "appium": "2.0.0", "babel-jest": "29.7.0", "babel-loader": "9.1.3", @@ -17543,20 +17542,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ajv-draft-04": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", - "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", - "dev": true, - "peerDependencies": { - "ajv": "^8.5.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, "node_modules/ajv-errors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", @@ -69390,12 +69375,6 @@ } } }, - "ajv-draft-04": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", - "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", - "dev": true - }, "ajv-errors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", diff --git a/package.json b/package.json index fb6e473b0f6dc8..89d576e745aae7 100644 --- a/package.json +++ b/package.json @@ -172,7 +172,6 @@ "@wordpress/scripts": "file:packages/scripts", "@wordpress/stylelint-config": "file:packages/stylelint-config", "ajv": "8.7.1", - "ajv-draft-04": "1.0.0", "appium": "2.0.0", "babel-jest": "29.7.0", "babel-loader": "9.1.3", diff --git a/schemas/json/block.json b/schemas/json/block.json index 6a27447f7b4965..f142ddd0b490b4 100644 --- a/schemas/json/block.json +++ b/schemas/json/block.json @@ -1,6 +1,6 @@ { "title": "JSON schema for WordPress blocks", - "$schema": "http://json-schema.org/draft-04/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "//": { "reference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/", diff --git a/schemas/json/font-collection.json b/schemas/json/font-collection.json index e52455b220cdb5..97b0cdf8edae49 100644 --- a/schemas/json/font-collection.json +++ b/schemas/json/font-collection.json @@ -1,6 +1,6 @@ { "title": "JSON schema for WordPress Font Collections", - "$schema": "http://json-schema.org/draft-04/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "definitions": { "fontFace": { diff --git a/schemas/json/theme.json b/schemas/json/theme.json index e04c21cf4bd58e..1bcfd1335c64c7 100644 --- a/schemas/json/theme.json +++ b/schemas/json/theme.json @@ -1,6 +1,6 @@ { "title": "JSON schema for WordPress block theme global settings and styles", - "$schema": "http://json-schema.org/draft-04/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "//": { "explainer": "https://developer.wordpress.org/themes/advanced-topics/theme-json/", @@ -469,8 +469,7 @@ "increment": { "description": "The amount to increment each step by.", "type": "number", - "exclusiveMinimum": true, - "minimum": 0, + "exclusiveMinimum": 0, "default": 1.5 }, "steps": { @@ -483,8 +482,7 @@ "mediumStep": { "description": "The value to medium setting in the scale.", "type": "number", - "exclusiveMinimum": true, - "minimum": 0, + "exclusiveMinimum": 0, "default": 1.5 }, "unit": { @@ -813,6 +811,22 @@ { "$ref": "#/definitions/settingsPropertiesCustom" } ] }, + "settingsPropertyNames": { + "enum": [ + "appearanceTools", + "background", + "border", + "color", + "dimensions", + "layout", + "lightbox", + "position", + "shadow", + "spacing", + "typography", + "custom" + ] + }, "settingsPropertiesComplete": { "type": "object", "allOf": [ @@ -820,21 +834,9 @@ "$ref": "#/definitions/settingsProperties" }, { - "properties": { - "appearanceTools": {}, - "background": {}, - "border": {}, - "color": {}, - "dimensions": {}, - "layout": {}, - "lightbox": {}, - "position": {}, - "shadow": {}, - "spacing": {}, - "typography": {}, - "custom": {} - }, - "additionalProperties": false + "propertyNames": { + "$ref": "#/definitions/settingsPropertyNames" + } } ] }, @@ -1881,6 +1883,20 @@ } } }, + "stylesPropertyNames": { + "enum": [ + "background", + "border", + "color", + "dimensions", + "spacing", + "typography", + "filter", + "shadow", + "outline", + "css" + ] + }, "stylesPropertiesComplete": { "type": "object", "allOf": [ @@ -1888,19 +1904,9 @@ "$ref": "#/definitions/stylesProperties" }, { - "properties": { - "background": {}, - "border": {}, - "color": {}, - "dimensions": {}, - "spacing": {}, - "typography": {}, - "filter": {}, - "shadow": {}, - "outline": {}, - "css": {} - }, - "additionalProperties": false + "propertyNames": { + "$ref": "#/definitions/stylesPropertyNames" + } } ] }, @@ -1916,16 +1922,6 @@ }, { "properties": { - "border": {}, - "background": {}, - "color": {}, - "dimensions": {}, - "filter": {}, - "shadow": {}, - "outline": {}, - "spacing": {}, - "typography": {}, - "css": {}, ":hover": { "$ref": "#/definitions/stylesPropertiesComplete" }, @@ -1944,8 +1940,26 @@ ":any-link": { "$ref": "#/definitions/stylesPropertiesComplete" } - }, - "additionalProperties": false + } + }, + { + "propertyNames": { + "anyOf": [ + { + "$ref": "#/definitions/stylesPropertyNames" + }, + { + "enum": [ + ":hover", + ":focus", + ":active", + ":visited", + ":link", + ":any-link" + ] + } + ] + } } ] }, @@ -1957,16 +1971,6 @@ }, { "properties": { - "background": {}, - "border": {}, - "color": {}, - "dimensions": {}, - "spacing": {}, - "typography": {}, - "filter": {}, - "shadow": {}, - "outline": {}, - "css": {}, ":hover": { "$ref": "#/definitions/stylesPropertiesComplete" }, @@ -1985,8 +1989,26 @@ ":any-link": { "$ref": "#/definitions/stylesPropertiesComplete" } - }, - "additionalProperties": false + } + }, + { + "propertyNames": { + "anyOf": [ + { + "$ref": "#/definitions/stylesPropertyNames" + }, + { + "enum": [ + ":hover", + ":focus", + ":active", + ":visited", + ":link", + ":any-link" + ] + } + ] + } } ] }, @@ -2334,24 +2356,25 @@ }, { "properties": { - "background": {}, - "border": {}, - "color": {}, - "dimensions": {}, - "spacing": {}, - "typography": {}, - "filter": {}, - "shadow": {}, - "outline": {}, - "css": {}, "elements": { "$ref": "#/definitions/stylesElementsPropertiesComplete" }, "variations": { "$ref": "#/definitions/stylesVariationsPropertiesComplete" } - }, - "additionalProperties": false + } + }, + { + "propertyNames": { + "anyOf": [ + { + "$ref": "#/definitions/stylesPropertyNames" + }, + { + "enum": [ "elements", "variations" ] + } + ] + } } ] }, @@ -2371,24 +2394,25 @@ }, { "properties": { - "background": {}, - "border": {}, - "color": {}, - "dimensions": {}, - "spacing": {}, - "typography": {}, - "filter": {}, - "shadow": {}, - "outline": {}, - "css": {}, "elements": { "$ref": "#/definitions/stylesElementsPropertiesComplete" }, "blocks": { "$ref": "#/definitions/stylesVariationBlocksPropertiesComplete" } - }, - "additionalProperties": false + } + }, + { + "propertyNames": { + "anyOf": [ + { + "$ref": "#/definitions/stylesPropertyNames" + }, + { + "enum": [ "elements", "blocks" ] + } + ] + } } ] }, @@ -2408,24 +2432,25 @@ }, { "properties": { - "background": {}, - "border": {}, - "color": {}, - "dimensions": {}, - "spacing": {}, - "typography": {}, - "filter": {}, - "shadow": {}, - "outline": {}, - "css": {}, "elements": { "$ref": "#/definitions/stylesElementsPropertiesComplete" }, "blocks": { "$ref": "#/definitions/stylesVariationBlocksPropertiesComplete" } - }, - "additionalProperties": false + } + }, + { + "propertyNames": { + "anyOf": [ + { + "$ref": "#/definitions/stylesPropertyNames" + }, + { + "enum": [ "elements", "blocks" ] + } + ] + } } ] }, @@ -2742,21 +2767,22 @@ }, { "properties": { - "background": {}, - "border": {}, - "color": {}, - "dimensions": {}, - "spacing": {}, - "typography": {}, - "filter": {}, - "shadow": {}, - "outline": {}, - "css": {}, "elements": { "$ref": "#/definitions/stylesElementsPropertiesComplete" } - }, - "additionalProperties": false + } + }, + { + "propertyNames": { + "anyOf": [ + { + "$ref": "#/definitions/stylesPropertyNames" + }, + { + "enum": [ "elements" ] + } + ] + } } ] } @@ -2770,7 +2796,7 @@ "version": { "description": "Version of theme.json to use.", "type": "integer", - "enum": [ 3 ] + "const": 3 }, "title": { "type": "string", @@ -2800,26 +2826,28 @@ }, { "properties": { - "appearanceTools": {}, "useRootPaddingAwareAlignments": { "$ref": "#/definitions/settingsPropertiesUseRootPaddingAwareAlignments/properties/useRootPaddingAwareAlignments" }, - "background": {}, - "color": {}, - "layout": {}, - "lightbox": {}, - "spacing": {}, - "typography": {}, - "border": {}, - "shadow": {}, - "position": {}, - "dimensions": {}, - "custom": {}, "blocks": { "$ref": "#/definitions/settingsBlocksPropertiesComplete" } - }, - "additionalProperties": false + } + }, + { + "propertyNames": { + "anyOf": [ + { + "$ref": "#/definitions/settingsPropertyNames" + }, + { + "enum": [ + "useRootPaddingAwareAlignments", + "blocks" + ] + } + ] + } } ] }, @@ -2832,16 +2860,6 @@ }, { "properties": { - "background": {}, - "border": {}, - "color": {}, - "dimensions": {}, - "spacing": {}, - "typography": {}, - "filter": {}, - "shadow": {}, - "outline": {}, - "css": {}, "elements": { "$ref": "#/definitions/stylesElementsPropertiesComplete" }, @@ -2851,8 +2869,19 @@ "variations": { "$ref": "#/definitions/stylesVariationsProperties" } - }, - "additionalProperties": false + } + }, + { + "propertyNames": { + "anyOf": [ + { + "$ref": "#/definitions/stylesPropertyNames" + }, + { + "enum": [ "elements", "blocks", "variations" ] + } + ] + } } ] }, diff --git a/schemas/json/wp-env.json b/schemas/json/wp-env.json index b082c861e4b671..689eb5bc58e227 100644 --- a/schemas/json/wp-env.json +++ b/schemas/json/wp-env.json @@ -1,6 +1,6 @@ { "title": "JSON schema for WordPress wp-env configuration files", - "$schema": "http://json-schema.org/draft-04/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "//": { "reference": "https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/" @@ -63,6 +63,17 @@ "type": "object" } } + }, + "wpEnvPropertyNames": { + "enum": [ + "core", + "phpVersion", + "plugins", + "themes", + "port", + "config", + "mappings" + ] } }, "type": "object", @@ -85,16 +96,9 @@ "allOf": [ { "$ref": "#/definitions/wpEnvProperties" }, { - "properties": { - "core": {}, - "phpVersion": {}, - "plugins": {}, - "themes": {}, - "port": {}, - "config": {}, - "mappings": {} - }, - "additionalProperties": false + "propertyNames": { + "$ref": "#/definitions/wpEnvPropertyNames" + } } ] } @@ -103,18 +107,16 @@ } }, { - "properties": { - "$schema": {}, - "core": {}, - "phpVersion": {}, - "plugins": {}, - "themes": {}, - "port": {}, - "config": {}, - "mappings": {}, - "env": {} - }, - "additionalProperties": false + "propertyNames": { + "anyOf": [ + { + "$ref": "#/definitions/wpEnvPropertyNames" + }, + { + "enum": [ "$schema", "env" ] + } + ] + } } ] } diff --git a/test/integration/blocks-schema.test.js b/test/integration/blocks-schema.test.js index c9456efddc1ade..37137ddd09d211 100644 --- a/test/integration/blocks-schema.test.js +++ b/test/integration/blocks-schema.test.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import Ajv from 'ajv-draft-04'; +import Ajv from 'ajv'; import glob from 'fast-glob'; /** @@ -16,7 +16,7 @@ describe( 'block.json schema', () => { ); const ajv = new Ajv(); - test( 'strictly adheres to the draft-04 meta schema', () => { + test( 'strictly adheres to the draft-07 meta schema', () => { // Use ajv.compile instead of ajv.validateSchema to validate the schema // because validateSchema only checks syntax, whereas, compile checks // if the schema is semantically correct with strict mode. diff --git a/test/integration/fixtures/schemas/settings.json b/test/integration/fixtures/schemas/settings.json new file mode 100644 index 00000000000000..0ed0548aa7b0a2 --- /dev/null +++ b/test/integration/fixtures/schemas/settings.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "settings": { + "invalidAdditionalProperty": true + } +} diff --git a/test/integration/fixtures/schemas/settingsPropertiesComplete.json b/test/integration/fixtures/schemas/settingsPropertiesComplete.json new file mode 100644 index 00000000000000..e70019cc266977 --- /dev/null +++ b/test/integration/fixtures/schemas/settingsPropertiesComplete.json @@ -0,0 +1,11 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "settings": { + "blocks": { + "core/button": { + "invalidAdditionalProperty": true + } + } + } +} diff --git a/test/integration/fixtures/schemas/styles.json b/test/integration/fixtures/schemas/styles.json new file mode 100644 index 00000000000000..50635d3de7e929 --- /dev/null +++ b/test/integration/fixtures/schemas/styles.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "invalidAdditionalProperty": true + } +} diff --git a/test/integration/fixtures/schemas/stylesElementsPropertiesComplete_button.json b/test/integration/fixtures/schemas/stylesElementsPropertiesComplete_button.json new file mode 100644 index 00000000000000..8c596653abcb00 --- /dev/null +++ b/test/integration/fixtures/schemas/stylesElementsPropertiesComplete_button.json @@ -0,0 +1,11 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "elements": { + "button": { + "invalidAdditionalProperty": true + } + } + } +} diff --git a/test/integration/fixtures/schemas/stylesElementsPropertiesComplete_link.json b/test/integration/fixtures/schemas/stylesElementsPropertiesComplete_link.json new file mode 100644 index 00000000000000..b8bbd11910d506 --- /dev/null +++ b/test/integration/fixtures/schemas/stylesElementsPropertiesComplete_link.json @@ -0,0 +1,11 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "elements": { + "link": { + "invalidAdditionalProperty": true + } + } + } +} diff --git a/test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete.json b/test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete.json new file mode 100644 index 00000000000000..cf9e2c5689534f --- /dev/null +++ b/test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete.json @@ -0,0 +1,11 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "blocks": { + "core/button": { + "invalidAdditionalProperty": true + } + } + } +} diff --git a/test/integration/fixtures/schemas/stylesPropertiesComplete.json b/test/integration/fixtures/schemas/stylesPropertiesComplete.json new file mode 100644 index 00000000000000..0727fb2abdbe13 --- /dev/null +++ b/test/integration/fixtures/schemas/stylesPropertiesComplete.json @@ -0,0 +1,13 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "elements": { + "button": { + ":hover": { + "invalidAdditionalProperty": true + } + } + } + } +} diff --git a/test/integration/fixtures/schemas/stylesVariationBlockPropertiesComplete.json b/test/integration/fixtures/schemas/stylesVariationBlockPropertiesComplete.json new file mode 100644 index 00000000000000..42b3e4b2174f50 --- /dev/null +++ b/test/integration/fixtures/schemas/stylesVariationBlockPropertiesComplete.json @@ -0,0 +1,15 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "variations": { + "custom-variation": { + "blocks": { + "core/button": { + "invalidAdditionalProperty": true + } + } + } + } + } +} diff --git a/test/integration/fixtures/schemas/stylesVariationProperties.json b/test/integration/fixtures/schemas/stylesVariationProperties.json new file mode 100644 index 00000000000000..a8a28550dbeee1 --- /dev/null +++ b/test/integration/fixtures/schemas/stylesVariationProperties.json @@ -0,0 +1,11 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "variations": { + "custom-variation": { + "invalidAdditionalProperty": true + } + } + } +} diff --git a/test/integration/fixtures/schemas/stylesVariationPropertiesComplete.json b/test/integration/fixtures/schemas/stylesVariationPropertiesComplete.json new file mode 100644 index 00000000000000..4fc448a22a0165 --- /dev/null +++ b/test/integration/fixtures/schemas/stylesVariationPropertiesComplete.json @@ -0,0 +1,15 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "blocks": { + "core/button": { + "variations": { + "custom-variation": { + "invalidAdditionalProperty": true + } + } + } + } + } +} diff --git a/test/integration/theme-schema.test.js b/test/integration/theme-schema.test.js index df6ee29fbec1ec..01c95ddaefadce 100644 --- a/test/integration/theme-schema.test.js +++ b/test/integration/theme-schema.test.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import Ajv from 'ajv-draft-04'; +import Ajv from 'ajv'; import glob from 'fast-glob'; /** @@ -14,13 +14,17 @@ describe( 'theme.json schema', () => { [ 'packages/*/src/**/theme.json', '{lib,phpunit,test}/**/theme.json' ], { onlyFiles: true } ); + const invalidFiles = glob.sync( + [ 'test/integration/fixtures/schemas/*.json' ], + { onlyFiles: true } + ); const ajv = new Ajv( { // Used for matching unknown blocks without repeating core blocks names // with patternProperties in settings.blocks and settings.styles allowMatchingProperties: true, } ); - it( 'strictly adheres to the draft-04 meta schema', () => { + it( 'strictly adheres to the draft-07 meta schema', () => { // Use ajv.compile instead of ajv.validateSchema to validate the schema // because validateSchema only checks syntax, whereas, compile checks // if the schema is semantically correct with strict mode. @@ -45,4 +49,13 @@ describe( 'theme.json schema', () => { expect( result ).toBe( true ); } ); + + test.each( invalidFiles )( 'invalidates schema for `%s`', ( filepath ) => { + // We want to validate the theme.json file using the local schema. + const { $schema, ...metadata } = require( filepath ); + + const result = ajv.validate( themeSchema, metadata ); + + expect( result ).toBe( false ); + } ); } ); From 14be95a5699730ee0474344464851ce0d3c0f71c Mon Sep 17 00:00:00 2001 From: Maggie <maggie.cabrera@automattic.com> Date: Tue, 23 Jul 2024 10:52:56 +0200 Subject: [PATCH 0048/1908] Limit pattern shuffling to theme and user patterns only (#62677) * add consition to remove core patterns from shuffle * reworded comment * Update packages/block-editor/src/components/block-toolbar/shuffle.js Co-authored-by: Ben Dwyer <ben@scruffian.com> * linting --------- Co-authored-by: Ben Dwyer <ben@scruffian.com> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../block-editor/src/components/block-toolbar/shuffle.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/block-editor/src/components/block-toolbar/shuffle.js b/packages/block-editor/src/components/block-toolbar/shuffle.js index d86bfa82015699..e9101e76e65667 100644 --- a/packages/block-editor/src/components/block-toolbar/shuffle.js +++ b/packages/block-editor/src/components/block-toolbar/shuffle.js @@ -54,10 +54,16 @@ export default function Shuffle( { clientId, as = Container } ) { return EMPTY_ARRAY; } return patterns.filter( ( pattern ) => { + const isCorePattern = + pattern.source === 'core' || + ( pattern.source?.startsWith( 'pattern-directory' ) && + pattern.source !== 'pattern-directory/theme' ); return ( // Check if the pattern has only one top level block, // otherwise we may shuffle to pattern that will not allow to continue shuffling. pattern.blocks.length === 1 && + // We exclude the core patterns and pattern directory patterns that are not theme patterns. + ! isCorePattern && pattern.categories?.some( ( category ) => { return categories.includes( category ); } ) && From e05dfdadabea3de0a353dcc77f329997725c7958 Mon Sep 17 00:00:00 2001 From: Guido Scialfa <dev@guidoscialfa.com> Date: Tue, 23 Jul 2024 11:13:08 +0200 Subject: [PATCH 0049/1908] Remove unused useSplit after #54543 (#63826) Co-authored-by: widoz <wido@git.wordpress.org> --- .../src/list-item/hooks/index.js | 1 - .../src/list-item/hooks/use-split.js | 33 ------------------- 2 files changed, 34 deletions(-) delete mode 100644 packages/block-library/src/list-item/hooks/use-split.js diff --git a/packages/block-library/src/list-item/hooks/index.js b/packages/block-library/src/list-item/hooks/index.js index 1687adbe740d0a..6220f92851a327 100644 --- a/packages/block-library/src/list-item/hooks/index.js +++ b/packages/block-library/src/list-item/hooks/index.js @@ -2,5 +2,4 @@ export { default as useOutdentListItem } from './use-outdent-list-item'; export { default as useIndentListItem } from './use-indent-list-item'; export { default as useEnter } from './use-enter'; export { default as useSpace } from './use-space'; -export { default as useSplit } from './use-split'; export { default as useMerge } from './use-merge'; diff --git a/packages/block-library/src/list-item/hooks/use-split.js b/packages/block-library/src/list-item/hooks/use-split.js deleted file mode 100644 index 51ede7de45c453..00000000000000 --- a/packages/block-library/src/list-item/hooks/use-split.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * WordPress dependencies - */ -import { useCallback, useRef } from '@wordpress/element'; -import { useSelect } from '@wordpress/data'; -import { store as blockEditorStore } from '@wordpress/block-editor'; -import { cloneBlock, createBlock } from '@wordpress/blocks'; - -export default function useSplit( clientId ) { - // We can not rely on the isAfterOriginal parameter of the callback, - // because if the value after the split is empty isAfterOriginal is false - // while the value is in fact after the original. So to avoid that issue we use - // a flag where the first execution of the callback is false (it is the before value) - // and the second execution is true, it is the after value. - const isAfter = useRef( false ); - const { getBlock } = useSelect( blockEditorStore ); - return useCallback( - ( value ) => { - const block = getBlock( clientId ); - if ( isAfter.current ) { - return cloneBlock( block, { - content: value, - } ); - } - isAfter.current = true; - return createBlock( block.name, { - ...block.attributes, - content: value, - } ); - }, - [ clientId, getBlock ] - ); -} From fb1f9a9295c573dac04884d3e811ffb3b660caa8 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Tue, 23 Jul 2024 10:15:13 +0100 Subject: [PATCH 0050/1908] Align checkbox, radio, and toggle input design (#63490) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/base-styles/_mixins.scss | 15 ++++++++---- packages/base-styles/_variables.scss | 2 +- packages/components/CHANGELOG.md | 4 ++++ .../src/checkbox-control/style.scss | 4 +++- .../components/src/form-toggle/style.scss | 23 +++++++++++-------- .../components/src/radio-control/index.tsx | 2 +- .../components/src/radio-control/style.scss | 7 +++++- packages/components/src/style.scss | 1 + .../components/src/toggle-control/index.tsx | 15 +++++++++--- .../components/src/toggle-control/style.scss | 11 +++++++++ .../enable-custom-fields.js.snap | 8 +++---- .../__snapshots__/meta-boxes-section.js.snap | 6 ++--- .../preference-base-option/style.scss | 5 ---- 13 files changed, 70 insertions(+), 33 deletions(-) create mode 100644 packages/components/src/toggle-control/style.scss diff --git a/packages/base-styles/_mixins.scss b/packages/base-styles/_mixins.scss index 1930948052aae7..506d12af84b2ff 100644 --- a/packages/base-styles/_mixins.scss +++ b/packages/base-styles/_mixins.scss @@ -318,6 +318,7 @@ height: $radio-input-size-sm; min-width: $radio-input-size-sm; max-width: $radio-input-size-sm; + position: relative; @include break-small() { height: $radio-input-size; @@ -328,9 +329,12 @@ &:checked::before { box-sizing: inherit; - width: 8px; - height: 8px; - transform: translate(7px, 7px); + width: math.div($radio-input-size-sm, 2); + height: math.div($radio-input-size-sm, 2); + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); margin: 0; background-color: $white; @@ -338,7 +342,8 @@ border: 4px solid $white; @include break-small() { - transform: translate(5px, 5px); + width: math.div($radio-input-size, 2); + height: math.div($radio-input-size, 2); } } @@ -351,7 +356,7 @@ &:checked { background: var(--wp-admin-theme-color); - border-color: var(--wp-admin-theme-color); + border: none; } } diff --git a/packages/base-styles/_variables.scss b/packages/base-styles/_variables.scss index dfbc1e15ac2ffc..b10eeeb167dadf 100644 --- a/packages/base-styles/_variables.scss +++ b/packages/base-styles/_variables.scss @@ -93,7 +93,7 @@ $border-width-tab: 1.5px; $helptext-font-size: 12px; $radius-round: 50%; $radius-block-ui: 2px; -$radio-input-size: 20px; +$radio-input-size: 16px; $radio-input-size-sm: 24px; // Width & height for small viewports. // Deprecated, please avoid using these. diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 6e8250529edd81..d58d7db9828967 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -18,6 +18,10 @@ - `CustomSelectControl`: Stabilize `__experimentalShowSelectedHint` and `options[]. __experimentalHint` props ([#63248](https://github.com/WordPress/gutenberg/pull/63248)). - `SelectControl`: Add `"minimal"` variant ([#63265](https://github.com/WordPress/gutenberg/pull/63265)). - `FontSizePicker`: tidy up internal logic ([#63553](https://github.com/WordPress/gutenberg/pull/63553)). +- `ToggleControl`: Update spacing and appearance to adhere to 4px baseline, slightly reducing footprint. Make label treatment and focus styles consistent with `RadioControl` and `CheckboxControl`. ([#63490](https://github.com/WordPress/gutenberg/pull/63490)). +- `CheckboxControl`: Slightly reduced footprint. Make label treatment, focus styles, and spacing consistent with `ToggleControl` and `RadioControl`. ([#63490](https://github.com/WordPress/gutenberg/pull/63490)). +- `RadioControl`: Slightly reduced footprint. Make label treatment, focus styles, and spacing consistent with `ToggleControl` and `CheckboxControl`. ([#63490](https://github.com/WordPress/gutenberg/pull/63490)). +- `FormToggle`: Update spacing and appearance to adhere to 4px baseline, slightly reducing footprint. Make label treatment and focus styles consistent with `RadioControl` and `CheckboxControl`. ([#63490](https://github.com/WordPress/gutenberg/pull/63490)). - `RangeControl`: Allow external `id` prop ([#63761](https://github.com/WordPress/gutenberg/pull/63761)). ### Internal diff --git a/packages/components/src/checkbox-control/style.scss b/packages/components/src/checkbox-control/style.scss index 9fd563d85161fe..25394ba645ee80 100644 --- a/packages/components/src/checkbox-control/style.scss +++ b/packages/components/src/checkbox-control/style.scss @@ -3,7 +3,7 @@ --checkbox-input-size: 24px; // Width & height for small viewports. @include break-small() { - --checkbox-input-size: 20px; + --checkbox-input-size: 16px; } --checkbox-input-margin: #{$grid-unit-10}; @@ -12,6 +12,7 @@ .components-checkbox-control__label { // Ensure label is aligned with checkbox along X axis line-height: var(--checkbox-input-size); + cursor: pointer; } .components-checkbox-control__input[type="checkbox"] { @@ -61,6 +62,7 @@ vertical-align: middle; width: var(--checkbox-input-size); aspect-ratio: 1; + line-height: 1; // maintains proper height even with WP common.css flex-shrink: 0; } diff --git a/packages/components/src/form-toggle/style.scss b/packages/components/src/form-toggle/style.scss index d04ad4c651f862..6fd25590b56e41 100644 --- a/packages/components/src/form-toggle/style.scss +++ b/packages/components/src/form-toggle/style.scss @@ -1,15 +1,16 @@ @use "sass:math"; -$toggle-width: 36px; -$toggle-height: 18px; +$toggle-width: $grid-unit-40; +$toggle-height: $grid-unit-20; $toggle-border-width: 1px; -$thumb-size: $toggle-height - ($toggle-border-width * 6); +$toggle-thumb-size: $grid-unit-15; $transition-duration: 0.2s; .components-form-toggle { position: relative; display: inline-block; + height: $toggle-height; // Unchecked state. .components-form-toggle__track { @@ -19,7 +20,7 @@ $transition-duration: 0.2s; box-sizing: border-box; vertical-align: top; background-color: $white; - border: $toggle-border-width solid $gray-900; + border: $toggle-border-width solid $gray-600; width: $toggle-width; height: $toggle-height; border-radius: math.div($toggle-height, 2); @@ -49,10 +50,10 @@ $transition-duration: 0.2s; display: block; position: absolute; box-sizing: border-box; - top: $toggle-border-width * 3; - left: $toggle-border-width * 3; - width: $thumb-size; - height: $thumb-size; + top: math.div($toggle-thumb-size, 6); + left: math.div($toggle-thumb-size, 6); + width: $toggle-thumb-size; + height: $toggle-thumb-size; border-radius: 50%; transition: $transition-duration transform ease, @@ -61,7 +62,7 @@ $transition-duration: 0.2s; background-color: $gray-900; // Transparent border acts as a fill in Windows High Contrast Mode. - border: math.div($thumb-size, 2) solid transparent; + border: math.div($toggle-thumb-size, 2) solid transparent; } // Checked state. @@ -116,4 +117,8 @@ $transition-duration: 0.2s; &::before { content: ""; } + + &:not(:disabled, [aria-disabled="true"]) { + cursor: pointer; + } } diff --git a/packages/components/src/radio-control/index.tsx b/packages/components/src/radio-control/index.tsx index 11b9e32b9118b6..2a6f8e37cc8cb5 100644 --- a/packages/components/src/radio-control/index.tsx +++ b/packages/components/src/radio-control/index.tsx @@ -73,7 +73,7 @@ export function RadioControl( help={ help } className={ clsx( className, 'components-radio-control' ) } > - <VStack spacing={ 3 }> + <VStack spacing={ 2 }> { options.map( ( option, index ) => ( <div key={ `${ id }-${ index }` } diff --git a/packages/components/src/radio-control/style.scss b/packages/components/src/radio-control/style.scss index 239ef38e65cc3b..a3d4abeb630d0d 100644 --- a/packages/components/src/radio-control/style.scss +++ b/packages/components/src/radio-control/style.scss @@ -13,7 +13,7 @@ cursor: pointer; &:focus { - box-shadow: 0 0 0 ($border-width * 2) $components-color-background, 0 0 0 ($border-width * 2 + $border-width-focus-fallback) $components-color-accent; + @include button-style-outset__focus(var(--wp-admin-theme-color)); } &:checked { @@ -29,4 +29,9 @@ .components-radio-control__label { cursor: pointer; + line-height: $radio-input-size-sm; + + @include break-small() { + line-height: $radio-input-size; + } } diff --git a/packages/components/src/style.scss b/packages/components/src/style.scss index c73ee1cb639eed..70317f4a2d0e0b 100644 --- a/packages/components/src/style.scss +++ b/packages/components/src/style.scss @@ -49,6 +49,7 @@ @import "./tab-panel/style.scss"; @import "./text-control/style.scss"; @import "./tip/style.scss"; +@import "./toggle-control/style.scss"; @import "./toolbar/toolbar/style.scss"; @import "./toolbar/toolbar-button/style.scss"; @import "./toolbar/toolbar-group/style.scss"; diff --git a/packages/components/src/toggle-control/index.tsx b/packages/components/src/toggle-control/index.tsx index ed62aea7755cd9..89ef34f6d6e5e6 100644 --- a/packages/components/src/toggle-control/index.tsx +++ b/packages/components/src/toggle-control/index.tsx @@ -3,6 +3,7 @@ */ import type { ChangeEvent, ForwardedRef } from 'react'; import { css } from '@emotion/react'; +import clsx from 'clsx'; /** * WordPress dependencies @@ -87,11 +88,17 @@ export function ToggleControl( return ( <BaseControl id={ id } - help={ helpLabel } + help={ + helpLabel && ( + <span className="components-toggle-control__help"> + { helpLabel } + </span> + ) + } className={ classes } __nextHasNoMarginBottom > - <HStack justify="flex-start" spacing={ 3 }> + <HStack justify="flex-start" spacing={ 2 }> <FormToggle id={ id } checked={ checked } @@ -103,7 +110,9 @@ export function ToggleControl( <FlexBlock as="label" htmlFor={ id } - className="components-toggle-control__label" + className={ clsx( 'components-toggle-control__label', { + 'is-disabled': disabled, + } ) } > { label } </FlexBlock> diff --git a/packages/components/src/toggle-control/style.scss b/packages/components/src/toggle-control/style.scss new file mode 100644 index 00000000000000..263a372b00fe84 --- /dev/null +++ b/packages/components/src/toggle-control/style.scss @@ -0,0 +1,11 @@ +.components-toggle-control__label { + line-height: $toggle-height; + + &:not(.is-disabled) { + cursor: pointer; + } +} + +.components-toggle-control__help { + margin-left: $toggle-width + $grid-unit-10; +} diff --git a/packages/edit-post/src/components/preferences-modal/test/__snapshots__/enable-custom-fields.js.snap b/packages/edit-post/src/components/preferences-modal/test/__snapshots__/enable-custom-fields.js.snap index 1ecf664fa091f3..567b2bcbf8f885 100644 --- a/packages/edit-post/src/components/preferences-modal/test/__snapshots__/enable-custom-fields.js.snap +++ b/packages/edit-post/src/components/preferences-modal/test/__snapshots__/enable-custom-fields.js.snap @@ -29,7 +29,7 @@ exports[`EnableCustomFieldsOption renders a checked checkbox and a confirmation -webkit-flex-direction: row; -ms-flex-direction: row; flex-direction: row; - gap: calc(4px * 3); + gap: calc(4px * 2); -webkit-box-pack: start; -ms-flex-pack: start; -webkit-justify-content: flex-start; @@ -135,7 +135,7 @@ exports[`EnableCustomFieldsOption renders a checked checkbox when custom fields -webkit-flex-direction: row; -ms-flex-direction: row; flex-direction: row; - gap: calc(4px * 3); + gap: calc(4px * 2); -webkit-box-pack: start; -ms-flex-pack: start; -webkit-justify-content: flex-start; @@ -231,7 +231,7 @@ exports[`EnableCustomFieldsOption renders an unchecked checkbox and a confirmati -webkit-flex-direction: row; -ms-flex-direction: row; flex-direction: row; - gap: calc(4px * 3); + gap: calc(4px * 2); -webkit-box-pack: start; -ms-flex-pack: start; -webkit-justify-content: flex-start; @@ -338,7 +338,7 @@ exports[`EnableCustomFieldsOption renders an unchecked checkbox when custom fiel -webkit-flex-direction: row; -ms-flex-direction: row; flex-direction: row; - gap: calc(4px * 3); + gap: calc(4px * 2); -webkit-box-pack: start; -ms-flex-pack: start; -webkit-justify-content: flex-start; diff --git a/packages/edit-post/src/components/preferences-modal/test/__snapshots__/meta-boxes-section.js.snap b/packages/edit-post/src/components/preferences-modal/test/__snapshots__/meta-boxes-section.js.snap index a872e7e0c1945d..f9fb99199a3197 100644 --- a/packages/edit-post/src/components/preferences-modal/test/__snapshots__/meta-boxes-section.js.snap +++ b/packages/edit-post/src/components/preferences-modal/test/__snapshots__/meta-boxes-section.js.snap @@ -29,7 +29,7 @@ exports[`MetaBoxesSection renders a Custom Fields option 1`] = ` -webkit-flex-direction: row; -ms-flex-direction: row; flex-direction: row; - gap: calc(4px * 3); + gap: calc(4px * 2); -webkit-box-pack: start; -ms-flex-pack: start; -webkit-justify-content: flex-start; @@ -141,7 +141,7 @@ exports[`MetaBoxesSection renders a Custom Fields option and meta box options 1` -webkit-flex-direction: row; -ms-flex-direction: row; flex-direction: row; - gap: calc(4px * 3); + gap: calc(4px * 2); -webkit-box-pack: start; -ms-flex-pack: start; -webkit-justify-content: flex-start; @@ -337,7 +337,7 @@ exports[`MetaBoxesSection renders meta box options 1`] = ` -webkit-flex-direction: row; -ms-flex-direction: row; flex-direction: row; - gap: calc(4px * 3); + gap: calc(4px * 2); -webkit-box-pack: start; -ms-flex-pack: start; -webkit-justify-content: flex-start; diff --git a/packages/preferences/src/components/preference-base-option/style.scss b/packages/preferences/src/components/preference-base-option/style.scss index d3caa60f8c8037..32040d0c9093a6 100644 --- a/packages/preferences/src/components/preference-base-option/style.scss +++ b/packages/preferences/src/components/preference-base-option/style.scss @@ -2,9 +2,4 @@ & + & { margin-top: $grid-unit-20; } - - .components-base-control__help { - margin-top: 0; - margin-left: 48px; - } } From 4b28aca4e99b3aa2c24713ce164f41068b359cbb Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Tue, 23 Jul 2024 11:14:51 +0100 Subject: [PATCH 0051/1908] Fix selected row styles in table layout (#63811) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/dataviews/src/layouts/table/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataviews/src/layouts/table/style.scss b/packages/dataviews/src/layouts/table/style.scss index debec8afc63745..7bbd172c8c91b8 100644 --- a/packages/dataviews/src/layouts/table/style.scss +++ b/packages/dataviews/src/layouts/table/style.scss @@ -92,7 +92,7 @@ } } - &.is-ed { + &.is-selected { background-color: rgba(var(--wp-admin-theme-color--rgb), 0.04); color: $gray-700; From e9e27b90d3399a8a5bb2f73c11fce5cfc422b79d Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 23 Jul 2024 12:21:49 +0200 Subject: [PATCH 0052/1908] Tabs: keep full opacity of focus ring on disabled tabs (#63754) * Tabs: keep full opacity of focus ring on disabled tabs * CHANGELOG * Use lighter shade of gray, use semantic variable * Do not apply hover styles to disabled tabs * Update CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/tabs/styles.ts | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index d58d7db9828967..d7585353acb453 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -32,6 +32,7 @@ - `DropdownMenuV2`: invert animation direction. ([#63443](https://github.com/WordPress/gutenberg/pull/63443)). - `Tabs`: Vertical Tabs should be 40px min height. ([#63446](https://github.com/WordPress/gutenberg/pull/63446)). - `ColorPicker`: Use `minimal` variant for `SelectControl` ([#63676](https://github.com/WordPress/gutenberg/pull/63676)). +- `Tabs`: keep full opacity of focus ring and remove hover styles on disabled tabs ([#63754](https://github.com/WordPress/gutenberg/pull/63754)). ### Documentation diff --git a/packages/components/src/tabs/styles.ts b/packages/components/src/tabs/styles.ts index 7d67f462c7e87e..ddad0f7b2d767d 100644 --- a/packages/components/src/tabs/styles.ts +++ b/packages/components/src/tabs/styles.ts @@ -76,13 +76,14 @@ export const Tab = styled( Ariakit.Tab )` font-weight: 500; text-align: inherit; hyphens: auto; + color: ${ COLORS.theme.foreground }; &[aria-disabled='true'] { cursor: default; - opacity: 0.3; + color: ${ COLORS.ui.textDisabled }; } - &:hover { + &:not( [aria-disabled='true'] ):hover { color: ${ COLORS.theme.accent }; } From 6b2088a8925669d9d527578627c4b46ca31a126d Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 23 Jul 2024 14:33:50 +0400 Subject: [PATCH 0053/1908] Core Data: Remove leftover 'todo' comment (#63842) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/core-data/src/resolvers.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 0b0cc017086cc7..148988cf723199 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -407,7 +407,6 @@ export const canUser = resourcePath = entityConfig.baseURL + ( resource.id ? '/' + resource.id : '' ); } else { - // @todo: Maybe warn when detecting a legacy usage. resourcePath = `/wp/v2/${ resource }` + ( id ? '/' + id : '' ); } From 3f7b260b53e0fbc2db7cf7ea806361a17886728a Mon Sep 17 00:00:00 2001 From: Carolina Nymark <myazalea@hotmail.com> Date: Tue, 23 Jul 2024 12:39:09 +0200 Subject: [PATCH 0054/1908] Latest comments: Add color block support (#63419) Adds text, background, gradient, and link color support to the Latest comments block. Background, text and link are set to show by default. Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- packages/block-library/src/latest-comments/block.json | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 0b6e6aa3fd6769..3309a676dfc84a 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -396,7 +396,7 @@ Display a list of your most recent comments. ([Source](https://github.com/WordPr - **Name:** core/latest-comments - **Category:** widgets -- **Supports:** align, interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~ +- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~ - **Attributes:** commentsToShow, displayAvatar, displayDate, displayExcerpt ## Latest Posts diff --git a/packages/block-library/src/latest-comments/block.json b/packages/block-library/src/latest-comments/block.json index aee42f1d15b486..543512ddf3ce7c 100644 --- a/packages/block-library/src/latest-comments/block.json +++ b/packages/block-library/src/latest-comments/block.json @@ -29,6 +29,15 @@ }, "supports": { "align": true, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true, + "link": true + } + }, "html": false, "spacing": { "margin": true, From 5673cb44816125dc3451a1859473863d21501c02 Mon Sep 17 00:00:00 2001 From: Maggie <maggie.cabrera@automattic.com> Date: Tue, 23 Jul 2024 12:40:52 +0200 Subject: [PATCH 0055/1908] Zoom out: hide vertical toolbar when block is not full width (#63650) * hide toolbar when block is not full width * fix unwanted centering, show regular toolbars on non full width blocks Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> --- .../components/block-tools/use-show-block-tools.js | 14 +++++++------- .../src/components/iframe/content.scss | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/use-show-block-tools.js b/packages/block-editor/src/components/block-tools/use-show-block-tools.js index 70a0b9f53a3421..33807445b8da74 100644 --- a/packages/block-editor/src/components/block-tools/use-show-block-tools.js +++ b/packages/block-editor/src/components/block-tools/use-show-block-tools.js @@ -45,8 +45,13 @@ export function useShowBlockTools() { editorMode === 'navigation'; const isZoomOut = editorMode === 'zoom-out'; + const _showZoomOutToolbar = + isZoomOut && + block?.attributes?.align === 'full' && + ! _showEmptyBlockSideInserter && + ! maybeShowBreadcrumb; const _showBlockToolbarPopover = - ! isZoomOut && + ! _showZoomOutToolbar && ! getSettings().hasFixedToolbar && ! _showEmptyBlockSideInserter && hasSelectedBlock && @@ -58,12 +63,7 @@ export function useShowBlockTools() { showBreadcrumb: ! _showEmptyBlockSideInserter && maybeShowBreadcrumb, showBlockToolbarPopover: _showBlockToolbarPopover, - showZoomOutToolbar: - hasSelectedBlock && - isZoomOut && - ! _showEmptyBlockSideInserter && - ! maybeShowBreadcrumb && - ! _showBlockToolbarPopover, + showZoomOutToolbar: _showZoomOutToolbar, }; }, [] ); } diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss index caae348a0ab761..8c03d4224745af 100644 --- a/packages/block-editor/src/components/iframe/content.scss +++ b/packages/block-editor/src/components/iframe/content.scss @@ -54,7 +54,7 @@ display: flex; flex-direction: column; - > .is-root-container { + > .is-root-container:not(.wp-block-post-content) { flex: 1; display: flex; flex-direction: column; From 28fb8761160a3688f66640f1b929b2f344efee0f Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 23 Jul 2024 12:43:41 +0200 Subject: [PATCH 0056/1908] Revert "Update HeightControl component to label inputs" (#63839) This reverts commit 47bde1a7696ceae94557dde3fa57cde3cfc9d84e. --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/height-control/index.js | 15 +++------------ packages/components/CHANGELOG.md | 1 - packages/components/src/range-control/index.tsx | 15 ++++----------- 3 files changed, 7 insertions(+), 24 deletions(-) diff --git a/packages/block-editor/src/components/height-control/index.js b/packages/block-editor/src/components/height-control/index.js index 4f5e17381728b3..71753a67beb021 100644 --- a/packages/block-editor/src/components/height-control/index.js +++ b/packages/block-editor/src/components/height-control/index.js @@ -1,7 +1,6 @@ /** * WordPress dependencies */ -import { useInstanceId } from '@wordpress/compose'; import { useMemo } from '@wordpress/element'; import { BaseControl, @@ -69,10 +68,6 @@ export default function HeightControl( { value, } ) { const customRangeValue = parseFloat( value ); - const id = useInstanceId( HeightControl, 'block-editor-height-control' ); - const labelId = `${ id }__label`; - const inputId = `${ id }__input`; - const rangeId = `${ id }__range`; const [ availableUnits ] = useSettings( 'spacing.units' ); const units = useCustomUnits( { @@ -149,14 +144,13 @@ export default function HeightControl( { }; return ( - <div className="block-editor-height-control" id={ id }> - <BaseControl.VisualLabel as="label" for={ inputId } id={ labelId }> + <fieldset className="block-editor-height-control"> + <BaseControl.VisualLabel as="legend"> { label } </BaseControl.VisualLabel> <Flex> <FlexItem isBlock> <UnitControl - id={ inputId } value={ value } units={ units } onChange={ onChange } @@ -170,9 +164,6 @@ export default function HeightControl( { <FlexItem isBlock> <Spacer marginX={ 2 } marginBottom={ 0 }> <RangeControl - aria-controls={ inputId } - aria-labelledby={ labelId } - id={ rangeId } value={ customRangeValue } min={ 0 } max={ @@ -192,6 +183,6 @@ export default function HeightControl( { </Spacer> </FlexItem> </Flex> - </div> + </fieldset> ); } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index d7585353acb453..f6ac03e45d8138 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -22,7 +22,6 @@ - `CheckboxControl`: Slightly reduced footprint. Make label treatment, focus styles, and spacing consistent with `ToggleControl` and `RadioControl`. ([#63490](https://github.com/WordPress/gutenberg/pull/63490)). - `RadioControl`: Slightly reduced footprint. Make label treatment, focus styles, and spacing consistent with `ToggleControl` and `CheckboxControl`. ([#63490](https://github.com/WordPress/gutenberg/pull/63490)). - `FormToggle`: Update spacing and appearance to adhere to 4px baseline, slightly reducing footprint. Make label treatment and focus styles consistent with `RadioControl` and `CheckboxControl`. ([#63490](https://github.com/WordPress/gutenberg/pull/63490)). -- `RangeControl`: Allow external `id` prop ([#63761](https://github.com/WordPress/gutenberg/pull/63761)). ### Internal diff --git a/packages/components/src/range-control/index.tsx b/packages/components/src/range-control/index.tsx index d12c1ca913612e..b5fff9f56b80d7 100644 --- a/packages/components/src/range-control/index.tsx +++ b/packages/components/src/range-control/index.tsx @@ -41,15 +41,6 @@ import { space } from '../utils/space'; const noop = () => {}; -function useUniqueId( idProp?: string ) { - const id = useInstanceId( - UnforwardedRangeControl, - 'inspector-range-control' - ); - - return idProp || id; -} - function UnforwardedRangeControl( props: WordPressComponentProps< RangeControlProps, 'input', false >, forwardedRef: ForwardedRef< HTMLInputElement > @@ -65,7 +56,6 @@ function UnforwardedRangeControl( disabled = false, help, hideLabelFromVision = false, - id: idProp, initialPosition, isShiftStepEnabled = true, label, @@ -133,7 +123,10 @@ function UnforwardedRangeControl( !! marks && 'is-marked' ); - const id = useUniqueId( idProp ); + const id = useInstanceId( + UnforwardedRangeControl, + 'inspector-range-control' + ); const describedBy = !! help ? `${ id }__help` : undefined; const enableTooltip = hasTooltip !== false && Number.isFinite( value ); From 8446fc73d35b958cbc7f68feaacd7ca4519a4bce Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Tue, 23 Jul 2024 13:14:01 +0200 Subject: [PATCH 0057/1908] Fix: Error while Calling edit-site getCurrentTemplateTemplateParts selector (#63818) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../data/data-core-edit-site.md | 2 + packages/edit-site/src/store/selectors.js | 43 +++++++++++-- .../src}/utils/get-filtered-template-parts.js | 16 ++--- .../utils/test/get-filtered-template-parts.js | 64 +------------------ 4 files changed, 44 insertions(+), 81 deletions(-) rename packages/{editor/src/store => edit-site/src}/utils/get-filtered-template-parts.js (83%) rename packages/{editor/src/store => edit-site/src}/utils/test/get-filtered-template-parts.js (55%) diff --git a/docs/reference-guides/data/data-core-edit-site.md b/docs/reference-guides/data/data-core-edit-site.md index b22fd2238f3031..775dd66a821ef0 100644 --- a/docs/reference-guides/data/data-core-edit-site.md +++ b/docs/reference-guides/data/data-core-edit-site.md @@ -24,6 +24,8 @@ _Returns_ ### getCurrentTemplateTemplateParts +> **Deprecated** + Returns the template parts and their blocks for the current edited template. _Parameters_ diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js index 3980d08bbc27be..3f7bbea0be7d25 100644 --- a/packages/edit-site/src/store/selectors.js +++ b/packages/edit-site/src/store/selectors.js @@ -2,16 +2,19 @@ * WordPress dependencies */ import { store as coreDataStore } from '@wordpress/core-data'; -import { createRegistrySelector } from '@wordpress/data'; +import { createRegistrySelector, createSelector } from '@wordpress/data'; import deprecated from '@wordpress/deprecated'; import { Platform } from '@wordpress/element'; import { store as preferencesStore } from '@wordpress/preferences'; import { store as editorStore } from '@wordpress/editor'; +import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Internal dependencies */ import { unlock } from '../lock-unlock'; +import { TEMPLATE_PART_POST_TYPE } from '../utils/constants'; +import getFilteredTemplatePartBlocks from '../utils/get-filtered-template-parts'; /** * @typedef {'template'|'template_type'} TemplateType Template type. @@ -240,18 +243,46 @@ export function isSaveViewOpened( state ) { return state.saveViewPanel; } +function getBlocksAndTemplateParts( select ) { + const templateParts = select( coreDataStore ).getEntityRecords( + 'postType', + TEMPLATE_PART_POST_TYPE, + { per_page: -1 } + ); + + const { getBlocksByName, getBlocksByClientId } = select( blockEditorStore ); + + const clientIds = getBlocksByName( 'core/template-part' ); + const blocks = getBlocksByClientId( clientIds ); + return [ blocks, templateParts ]; +} + /** * Returns the template parts and their blocks for the current edited template. * + * @deprecated * @param {Object} state Global application state. * @return {Array} Template parts and their blocks in an array. */ export const getCurrentTemplateTemplateParts = createRegistrySelector( - ( select ) => () => { - return unlock( - select( editorStore ) - ).getCurrentTemplateTemplateParts(); - } + ( select ) => + createSelector( + () => { + deprecated( + `select( 'core/edit-site' ).getCurrentTemplateTemplateParts()`, + { + since: '6.7', + version: '6.9', + alternative: `select( 'core/block-editor' ).getBlocksByName( 'core/template-part' )`, + } + ); + + return getFilteredTemplatePartBlocks( + ...getBlocksAndTemplateParts( select ) + ); + }, + () => getBlocksAndTemplateParts( select ) + ) ); /** diff --git a/packages/editor/src/store/utils/get-filtered-template-parts.js b/packages/edit-site/src/utils/get-filtered-template-parts.js similarity index 83% rename from packages/editor/src/store/utils/get-filtered-template-parts.js rename to packages/edit-site/src/utils/get-filtered-template-parts.js index af24684ace615e..bba982c0717a71 100644 --- a/packages/editor/src/store/utils/get-filtered-template-parts.js +++ b/packages/edit-site/src/utils/get-filtered-template-parts.js @@ -1,8 +1,3 @@ -/** - * External dependencies - */ -import memoize from 'memize'; - /** * WordPress dependencies */ @@ -20,7 +15,10 @@ const EMPTY_ARRAY = []; * @param {?Array} templateParts Available template parts. * @return {Array} An array of template parts and their blocks. */ -function getFilteredTemplatePartBlocks( blocks = EMPTY_ARRAY, templateParts ) { +export default function getFilteredTemplatePartBlocks( + blocks = EMPTY_ARRAY, + templateParts +) { const templatePartsById = templateParts ? // Key template parts by their ID. templateParts.reduce( @@ -61,9 +59,3 @@ function getFilteredTemplatePartBlocks( blocks = EMPTY_ARRAY, templateParts ) { return result; } - -const memoizedGetFilteredTemplatePartBlocks = memoize( - getFilteredTemplatePartBlocks -); - -export { memoizedGetFilteredTemplatePartBlocks as getFilteredTemplatePartBlocks }; diff --git a/packages/editor/src/store/utils/test/get-filtered-template-parts.js b/packages/edit-site/src/utils/test/get-filtered-template-parts.js similarity index 55% rename from packages/editor/src/store/utils/test/get-filtered-template-parts.js rename to packages/edit-site/src/utils/test/get-filtered-template-parts.js index bf9fad5a1cf354..0d5c2836330213 100644 --- a/packages/editor/src/store/utils/test/get-filtered-template-parts.js +++ b/packages/edit-site/src/utils/test/get-filtered-template-parts.js @@ -1,7 +1,7 @@ /** * Internal dependencies */ -import { getFilteredTemplatePartBlocks } from '../get-filtered-template-parts'; +import getFilteredTemplatePartBlocks from '../get-filtered-template-parts'; const NESTED_BLOCKS = [ { @@ -98,16 +98,6 @@ const FLATTENED_BLOCKS = [ }, ]; -const SINGLE_TEMPLATE_PART_BLOCK = { - clientId: '1', - name: 'core/template-part', - innerBlocks: [], - attributes: { - slug: 'aside', - theme: 'my-theme', - }, -}; - const TEMPLATE_PARTS = [ { id: 'my-theme//header', @@ -134,56 +124,4 @@ describe( 'getFilteredTemplatePartBlocks', () => { ); expect( flattenedFilteredTemplateParts ).toEqual( FLATTENED_BLOCKS ); } ); - - it( 'returns a cached result when passed the same params', () => { - // Clear the cache and call the function twice. - getFilteredTemplatePartBlocks.clear(); - getFilteredTemplatePartBlocks( NESTED_BLOCKS, TEMPLATE_PARTS ); - expect( - getFilteredTemplatePartBlocks( NESTED_BLOCKS, TEMPLATE_PARTS ) - ).toEqual( FLATTENED_BLOCKS ); - - // The function has been called twice with the same params, so the cache size should be 1. - /** - * TODO what should be done about this? - * Can it be tested another way? - * Is it necessary? - */ - // const [ , , originalSize ] = - // getFilteredTemplatePartBlocks.getCache(); - // expect( originalSize ).toBe( 1 ); - - // Call the function again, with different params. - expect( - getFilteredTemplatePartBlocks( - [ SINGLE_TEMPLATE_PART_BLOCK ], - TEMPLATE_PARTS - ) - ).toEqual( [ - { - block: { - clientId: '1', - name: 'core/template-part', - attributes: { - slug: 'aside', - theme: 'my-theme', - }, - }, - templatePart: { - id: 'my-theme//aside', - slug: 'aside', - theme: 'my-theme', - }, - }, - ] ); - - // The function has been called with different params, so the cache size should now be 2. - /** - * TODO what should be done about this? - * Can it be tested another way? - * Is it necessary? - */ - // const [ , , finalSize ] = getFilteredTemplatePartBlocks.getCache(); - // expect( finalSize ).toBe( 2 ); - } ); } ); From fe0dcf47243685613e47fab1d7c1a746a46e2878 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 23 Jul 2024 14:25:27 +0200 Subject: [PATCH 0058/1908] DataViews: Rename the header property of fields to label (#63843) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- packages/dataviews/CHANGELOG.md | 1 + packages/dataviews/src/components/dataform/index.tsx | 4 ++-- .../src/components/dataviews-filters/index.tsx | 2 +- .../src/components/dataviews-view-config/index.tsx | 6 +++--- packages/dataviews/src/layouts/grid/index.tsx | 2 +- packages/dataviews/src/layouts/list/index.tsx | 2 +- .../src/layouts/table/column-header-menu.tsx | 6 +++--- packages/dataviews/src/normalize-fields.ts | 2 +- packages/dataviews/src/stories/fixtures.js | 12 ++++++------ packages/dataviews/src/types.ts | 6 +++--- .../edit-site/src/components/page-patterns/index.js | 8 ++++---- .../edit-site/src/components/page-templates/index.js | 10 +++++----- .../edit-site/src/components/post-fields/index.js | 10 +++++----- 13 files changed, 36 insertions(+), 35 deletions(-) diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 6efa4a8508239a..bf7f54f009522f 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -6,6 +6,7 @@ - `onSelectionChange` prop has been renamed to `onChangeSelection` and its argument has been updated to be a list of ids. - `setSelection` prop has been removed. Please use `onChangeSelection` instead. +- `header` field property has been renamed to `label`. ## 3.0.0 (2024-07-10) diff --git a/packages/dataviews/src/components/dataform/index.tsx b/packages/dataviews/src/components/dataform/index.tsx index e61fea075c9b5a..3f4af8e110c776 100644 --- a/packages/dataviews/src/components/dataform/index.tsx +++ b/packages/dataviews/src/components/dataform/index.tsx @@ -33,7 +33,7 @@ function DataFormTextControl< Item >( { field, onChange, }: DataFormControlProps< Item > ) { - const { id, header, placeholder } = field; + const { id, label, placeholder } = field; const value = field.getValue( { item: data } ); const onChangeControl = useCallback( @@ -47,7 +47,7 @@ function DataFormTextControl< Item >( { return ( <TextControl - label={ header } + label={ label } placeholder={ placeholder } value={ value } onChange={ onChangeControl } diff --git a/packages/dataviews/src/components/dataviews-filters/index.tsx b/packages/dataviews/src/components/dataviews-filters/index.tsx index c35bb454b329f8..449e0ff0323a8b 100644 --- a/packages/dataviews/src/components/dataviews-filters/index.tsx +++ b/packages/dataviews/src/components/dataviews-filters/index.tsx @@ -33,7 +33,7 @@ function Filters() { const isPrimary = !! field.filterBy?.isPrimary; filters.push( { field: field.id, - name: field.header, + name: field.label, elements: field.elements, singleSelection: operators.some( ( op ) => [ OPERATOR_IS, OPERATOR_IS_NOT ].includes( op ) diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index 6dca75fbe057a4..9f0cb87fa01a2e 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -183,7 +183,7 @@ function FieldsVisibilityMenu< Item >( { } } > <DropdownMenuItemLabel> - { field.header } + { field.label } </DropdownMenuItemLabel> </DropdownMenuCheckboxItem> ); @@ -212,7 +212,7 @@ function SortMenu< Item >( { <DropdownMenuItem suffix={ <span aria-hidden="true"> - { currentSortedField?.header } + { currentSortedField?.label } </span> } > @@ -230,7 +230,7 @@ function SortMenu< Item >( { trigger={ <DropdownMenuItem> <DropdownMenuItemLabel> - { field.header } + { field.label } </DropdownMenuItemLabel> </DropdownMenuItem> } diff --git a/packages/dataviews/src/layouts/grid/index.tsx b/packages/dataviews/src/layouts/grid/index.tsx index c42b06f2a0ce60..cbfccf5521a812 100644 --- a/packages/dataviews/src/layouts/grid/index.tsx +++ b/packages/dataviews/src/layouts/grid/index.tsx @@ -145,7 +145,7 @@ function GridItem< Item >( { > <> <FlexItem className="dataviews-view-grid__field-name"> - { field.header } + { field.label } </FlexItem> <FlexItem className="dataviews-view-grid__field-value" diff --git a/packages/dataviews/src/layouts/list/index.tsx b/packages/dataviews/src/layouts/list/index.tsx index 68d9f39f447f1e..00939a12984856 100644 --- a/packages/dataviews/src/layouts/list/index.tsx +++ b/packages/dataviews/src/layouts/list/index.tsx @@ -185,7 +185,7 @@ function ListItem< Item >( { as="span" className="dataviews-view-list__field-label" > - { field.header } + { field.label } </VisuallyHidden> <span className="dataviews-view-list__field-value"> <field.render item={ item } /> diff --git a/packages/dataviews/src/layouts/table/column-header-menu.tsx b/packages/dataviews/src/layouts/table/column-header-menu.tsx index 7224701798bbaf..d0288483327258 100644 --- a/packages/dataviews/src/layouts/table/column-header-menu.tsx +++ b/packages/dataviews/src/layouts/table/column-header-menu.tsx @@ -72,7 +72,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( ); const index = view.fields?.indexOf( fieldId ) as number; if ( !! combinedField ) { - return combinedField.header; + return combinedField.label; } const field = fields.find( ( f ) => f.id === fieldId ); if ( ! field ) { @@ -92,7 +92,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( !! operators.length && ! field.filterBy?.isPrimary; if ( ! isSortable && ! isHidable && ! canAddFilter ) { - return field.header; + return field.label; } return ( <DropdownMenu @@ -104,7 +104,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( ref={ ref } variant="tertiary" > - { field.header } + { field.label } { view.sort && isSorted && ( <span aria-hidden="true"> { sortArrows[ view.sort.direction ] } diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index a7a9a47734a961..b7407dfe522fb6 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -19,7 +19,7 @@ export function normalizeFields< Item >( return { ...field, - header: field.header || field.id, + label: field.label || field.id, getValue, render: field.render || getValue, }; diff --git a/packages/dataviews/src/stories/fixtures.js b/packages/dataviews/src/stories/fixtures.js index cb107e56969d17..1ab26af4ef14d0 100644 --- a/packages/dataviews/src/stories/fixtures.js +++ b/packages/dataviews/src/stories/fixtures.js @@ -160,7 +160,7 @@ export const actions = [ export const fields = [ { - header: 'Image', + label: 'Image', id: 'image', render: ( { item } ) => { return ( @@ -170,13 +170,13 @@ export const fields = [ enableSorting: false, }, { - header: 'Title', + label: 'Title', id: 'title', enableHiding: false, enableGlobalSearch: true, }, { - header: 'Type', + label: 'Type', id: 'type', enableHiding: false, elements: [ @@ -187,18 +187,18 @@ export const fields = [ ], }, { - header: 'Satellites', + label: 'Satellites', id: 'satellites', enableSorting: true, }, { - header: 'Description', + label: 'Description', id: 'description', enableSorting: false, enableGlobalSearch: true, }, { - header: 'Categories', + label: 'Categories', id: 'categories', elements: [ { value: 'Space', label: 'Space' }, diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 014c25480852c0..0b43740efc3f2d 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -63,7 +63,7 @@ export type Field< Item > = { /** * The label of the field. Defaults to the id. */ - header?: string; + label?: string; /** * Placeholder for the field. @@ -116,7 +116,7 @@ export type Field< Item > = { } ); export type NormalizedField< Item > = Field< Item > & { - header: string; + label: string; getValue: ( args: { item: Item } ) => any; render: ComponentType< { item: Item } >; }; @@ -242,7 +242,7 @@ interface ViewBase { export interface CombinedField { id: string; - header: string; + label: string; /** * The fields to use as columns. diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index 27b75424e5f3b8..a0f107e91601bd 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -284,7 +284,7 @@ export default function DataviewsPatterns() { const fields = useMemo( () => { const _fields = [ { - header: __( 'Preview' ), + label: __( 'Preview' ), id: 'preview', render: ( { item } ) => ( <Preview item={ item } viewType={ view.type } /> @@ -292,7 +292,7 @@ export default function DataviewsPatterns() { enableSorting: false, }, { - header: __( 'Title' ), + label: __( 'Title' ), id: 'title', getValue: ( { item } ) => item.title?.raw || item.title, render: ( { item } ) => <Title item={ item } />, @@ -302,7 +302,7 @@ export default function DataviewsPatterns() { if ( type === PATTERN_TYPES.user ) { _fields.push( { - header: __( 'Sync status' ), + label: __( 'Sync status' ), id: 'sync-status', render: ( { item } ) => { const syncStatus = @@ -333,7 +333,7 @@ export default function DataviewsPatterns() { } ); } else if ( type === TEMPLATE_PART_POST_TYPE ) { _fields.push( { - header: __( 'Author' ), + label: __( 'Author' ), id: 'author', getValue: ( { item } ) => item.author_text, render: ( { item } ) => { diff --git a/packages/edit-site/src/components/page-templates/index.js b/packages/edit-site/src/components/page-templates/index.js index ed1c8543865c19..9ec87ee8cca352 100644 --- a/packages/edit-site/src/components/page-templates/index.js +++ b/packages/edit-site/src/components/page-templates/index.js @@ -58,7 +58,7 @@ const defaultLayouts = { combinedFields: [ { id: 'template', - header: __( 'Template' ), + label: __( 'Template' ), children: [ 'title', 'description' ], direction: 'vertical', }, @@ -286,7 +286,7 @@ export default function PageTemplates() { const fields = useMemo( () => [ { - header: __( 'Preview' ), + label: __( 'Preview' ), id: 'preview', render: ( { item } ) => { return <Preview item={ item } viewType={ view.type } />; @@ -294,7 +294,7 @@ export default function PageTemplates() { enableSorting: false, }, { - header: __( 'Template' ), + label: __( 'Template' ), id: 'title', getValue: ( { item } ) => item.title?.rendered, render: ( { item } ) => ( @@ -304,7 +304,7 @@ export default function PageTemplates() { enableGlobalSearch: true, }, { - header: __( 'Description' ), + label: __( 'Description' ), id: 'description', render: ( { item } ) => { return ( @@ -319,7 +319,7 @@ export default function PageTemplates() { enableGlobalSearch: true, }, { - header: __( 'Author' ), + label: __( 'Author' ), id: 'author', getValue: ( { item } ) => item.author_text, render: ( { item } ) => { diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 5a94b60f5dde0f..f4e8e553c8fa47 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -167,7 +167,7 @@ function usePostFields( viewType ) { () => [ { id: 'featured-image', - header: __( 'Featured Image' ), + label: __( 'Featured Image' ), getValue: ( { item } ) => item.featured_media, render: ( { item } ) => ( <FeaturedImage item={ item } viewType={ viewType } /> @@ -175,7 +175,7 @@ function usePostFields( viewType ) { enableSorting: false, }, { - header: __( 'Title' ), + label: __( 'Title' ), id: 'title', type: 'text', getValue: ( { item } ) => @@ -233,7 +233,7 @@ function usePostFields( viewType ) { enableHiding: false, }, { - header: __( 'Author' ), + label: __( 'Author' ), id: 'author', getValue: ( { item } ) => item._embedded?.author[ 0 ]?.name, elements: @@ -244,7 +244,7 @@ function usePostFields( viewType ) { render: PostAuthorField, }, { - header: __( 'Status' ), + label: __( 'Status' ), id: 'status', getValue: ( { item } ) => STATUSES.find( ( { value } ) => value === item.status ) @@ -257,7 +257,7 @@ function usePostFields( viewType ) { }, }, { - header: __( 'Date' ), + label: __( 'Date' ), id: 'date', render: ( { item } ) => { const isDraftOrPrivate = [ 'draft', 'private' ].includes( From dd31d299c047cffed6ea862278ba0e05ccc8d6a8 Mon Sep 17 00:00:00 2001 From: Rich Tabor <hi@richtabor.com> Date: Tue, 23 Jul 2024 09:19:26 -0400 Subject: [PATCH 0059/1908] Make hover block outlines not present in Distraction Free (#63819) --- .../editor/src/components/provider/use-block-editor-settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 1c1881bb00f405..6aa2763cf9db06 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -311,7 +311,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { __experimentalUndo: undo, // Check whether we want all site editor frames to have outlines // including the navigation / pattern / parts editors. - outlineMode: postType === 'wp_template', + outlineMode: ! isDistractionFree && postType === 'wp_template', // Check these two properties: they were not present in the site editor. __experimentalCreatePageEntity: createPageEntity, __experimentalUserCanCreatePages: userCanCreatePages, From ae50345a6b8bbcb66932001b644fd1e7b76fb55d Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Tue, 23 Jul 2024 20:35:39 +0530 Subject: [PATCH 0060/1908] Add unit tests for the gutenberg_render_block_core_post_title() function. Add unit tests for the gutenberg_render_block_core_post_title() function. Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: spacedmonkey <spacedmonkey@git.wordpress.org> Co-authored-by: anton-vlasenko <antonvlasenko@git.wordpress.org> --- phpunit/blocks/renderBlockCorePostTitle.php | 185 ++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 phpunit/blocks/renderBlockCorePostTitle.php diff --git a/phpunit/blocks/renderBlockCorePostTitle.php b/phpunit/blocks/renderBlockCorePostTitle.php new file mode 100644 index 00000000000000..4c080a1c905ff6 --- /dev/null +++ b/phpunit/blocks/renderBlockCorePostTitle.php @@ -0,0 +1,185 @@ +<?php +/** + * Tests for the gutenberg_render_block_core_post_title() function. + * + * @package WordPress + * @subpackage Blocks + * + * @covers ::gutenberg_render_block_core_post_title + * @group blocks + */ +class Tests_Blocks_RenderBlockCorePostTitle extends WP_UnitTestCase { + /** + * Post object. + * + * @var WP_Post + */ + protected static $post; + + /** + * Array of attributes. + * + * @var array + */ + protected static $attributes; + + /** + * Block object. + * + * @var WP_Block + */ + protected static $block; + + /** + * Setup method. + * + * @param WP_UnitTest_Factory $factory Helper that lets us create fake data. + */ + public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { + self::$post = $factory->post->create_and_get( array( 'post_title' => 'Post title block Unit Test' ) ); + + self::$attributes = array( + 'textAlign' => '', + 'level' => 2, + 'isLink' => false, + 'linkTarget' => '', + 'rel' => '', + ); + + self::$block = new stdClass(); + + $block_args = array( + 'blockName' => 'core/post-title', + 'attrs' => array( + 'textColor' => 'red', + ), + 'innerBlock' => array(), + 'innerContent' => array(), + 'innerHTML' => array(), + ); + + WP_Block_Supports::init(); + WP_Block_Supports::$block_to_render = $block_args; + } + + /** + * Tear down method. + */ + public static function wpTearDownAfterClass() { + wp_delete_post( self::$post->ID, true ); + } + + /** + * Test if the function returns an empty string when the post title is empty. + * + * @param mixed $context Block context. + * @param string $failure_message Failure message. + * + * @dataProvider data_should_render_empty_string_when_title_is_empty + */ + public function test_should_render_empty_string_when_title_is_empty( $context, $failure_message ) { + if ( $context ) { + self::$block->context = $context; + } + $rendered = gutenberg_render_block_core_post_title( self::$attributes, '', self::$block ); + $this->assertSame( '', $rendered, $failure_message ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_should_render_empty_string_when_title_is_empty() { + return array( + 'empty block context' => array( null, 'Failed asserting that rendering result is an empty string when block context is not set.' ), + 'incorrect post ID' => array( array( 'postId' => 0 ), 'Failed asserting that rendering result is an empty string when post ID is incorrect.' ), + ); + } + + /** + * Test if the function returns correct titles. + */ + public function test_should_render_correct_title() { + + $GLOBALS['post'] = self::$post; + self::$block->context = array( 'postId' => self::$post->ID ); + + $rendered = gutenberg_render_block_core_post_title( self::$attributes, '', self::$block ); + $this->assertNotEmpty( + $rendered, + 'Failed to assert that $rendered is an non-empty string.' + ); + $this->assertStringContainsString( + 'Post title block Unit Test', + $rendered, + 'Failed to assert that $rendered contain the post title string.' + ); + $this->assertStringContainsString( + '</h2>', + $rendered, + 'Failed to assert that $rendered contain a closing html heading tag.' + ); + $this->assertStringNotContainsString( + get_permalink( self::$post->ID ), + $rendered, + 'Failed to assert that $rendered does not contain the post link.' + ); + $this->assertStringNotContainsString( + '<a href=', + $rendered, + 'Failed to assert that $rendered does not contain a html anchor tag.' + ); + $this->assertStringNotContainsString( + 'has-text-align-left', + $rendered, + 'Failed to assert that $rendered does not contain the has-text-align-left class.' + ); + + self::$attributes['level'] = '1'; + $rendered = gutenberg_render_block_core_post_title( self::$attributes, '', self::$block ); + $this->assertStringContainsString( + '<h1', + $rendered, + 'Failed to assert that $rendered contain the HTML heading tag.' + ); + $this->assertStringContainsString( + '</h1>', + $rendered, + 'Failed to assert that $rendered contain a closing HTML heading tag.' + ); + + self::$attributes['textAlign'] = 'left'; + $rendered = gutenberg_render_block_core_post_title( self::$attributes, '', self::$block ); + $this->assertStringContainsString( + 'has-text-align-left', + $rendered, + 'Failed to assert that $rendered contain the has-text-align-left class.' + ); + + self::$attributes['isLink'] = true; + self::$attributes['linkTarget'] = '_blank'; + self::$attributes['rel'] = 'no-relative'; + $rendered = gutenberg_render_block_core_post_title( self::$attributes, '', self::$block ); + $this->assertStringContainsString( + get_permalink( self::$post->ID ), + $rendered, + 'Failed to assert that $rendered contain the post link.' + ); + $this->assertStringContainsString( + '<a href=', + $rendered, + 'Failed to assert that $rendered contain html anchor tag.' + ); + $this->assertStringContainsString( + '_blank', + $rendered, + 'Failed to assert that $rendered contain the link target attribute.' + ); + $this->assertStringContainsString( + 'no-relative', + $rendered, + 'Failed to assert that $rendered contain the link relation attribute.' + ); + } +} From 2e967be9e1928809841761744b4ed8c768f0a417 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 11:10:18 -0400 Subject: [PATCH 0061/1908] Bump the github-actions group across 1 directory with 4 updates (#63808) Bumps the github-actions group with 4 updates in the / directory: [actions/setup-node](https://github.com/actions/setup-node), [actions/download-artifact](https://github.com/actions/download-artifact), [ruby/setup-ruby](https://github.com/ruby/setup-ruby) and [shivammathur/setup-php](https://github.com/shivammathur/setup-php). Updates `actions/setup-node` from 4.0.2 to 4.0.3 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/60edb5dd545a775178f52524783378180af0d1f8...1e60f620b9541d16bece96c5465dc8ee9832be0b) Updates `actions/download-artifact` from 4.1.7 to 4.1.8 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v4.1.7...v4.1.8) Updates `ruby/setup-ruby` from 1.180.1 to 1.188.0 - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb) - [Commits](https://github.com/ruby/setup-ruby/compare/3783f195e29b74ae398d7caca108814bbafde90e...50ba3386b050ad5b97a41fcb81240cbee1d1821f) Updates `shivammathur/setup-php` from 2.31.0 to 2.31.1 - [Release notes](https://github.com/shivammathur/setup-php/releases) - [Commits](https://github.com/shivammathur/setup-php/compare/2e947f1f6932d141d076ca441d0e1e881775e95b...c541c155eee45413f5b09a52248675b1a2575231) --- updated-dependencies: - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: shivammathur/setup-php dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/build-plugin-zip.yml | 8 ++++---- .github/workflows/bundle-size.yml | 2 +- .github/workflows/end2end-test.yml | 2 +- .github/workflows/publish-npm-packages.yml | 4 ++-- .github/workflows/pull-request-automation.yml | 2 +- .github/workflows/rnmobile-ios-runner.yml | 2 +- .github/workflows/static-checks.yml | 2 +- .github/workflows/unit-test.yml | 6 +++--- .github/workflows/upload-release-to-plugin-repo.yml | 4 ++-- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build-plugin-zip.yml b/.github/workflows/build-plugin-zip.yml index f9fa22d324d777..603d6123df1ea2 100644 --- a/.github/workflows/build-plugin-zip.yml +++ b/.github/workflows/build-plugin-zip.yml @@ -171,7 +171,7 @@ jobs: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Node.js - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 with: node-version-file: '.nvmrc' check-latest: true @@ -270,12 +270,12 @@ jobs: run: echo "version=$(echo $VERSION | cut -d / -f 3 | sed 's/-rc./ RC/' )" >> $GITHUB_OUTPUT - name: Download Plugin Zip Artifact - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: gutenberg-plugin - name: Download Release Notes Artifact - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: release-notes @@ -333,7 +333,7 @@ jobs: git config user.email gutenberg@wordpress.org - name: Setup Node.js - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 with: node-version-file: 'main/.nvmrc' registry-url: 'https://registry.npmjs.org' diff --git a/.github/workflows/bundle-size.yml b/.github/workflows/bundle-size.yml index a0b7d773f55497..6106eee492c32a 100644 --- a/.github/workflows/bundle-size.yml +++ b/.github/workflows/bundle-size.yml @@ -43,7 +43,7 @@ jobs: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Node.js - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 with: node-version-file: '.nvmrc' check-latest: true diff --git a/.github/workflows/end2end-test.yml b/.github/workflows/end2end-test.yml index 6233b36d435bf8..99166989cd68ca 100644 --- a/.github/workflows/end2end-test.yml +++ b/.github/workflows/end2end-test.yml @@ -107,7 +107,7 @@ jobs: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - uses: actions/download-artifact@v4.1.7 + - uses: actions/download-artifact@v4.1.8 # Don't fail the job if there isn't any flaky tests report. continue-on-error: true with: diff --git a/.github/workflows/publish-npm-packages.yml b/.github/workflows/publish-npm-packages.yml index 31df5a1575fa84..a24e5012474025 100644 --- a/.github/workflows/publish-npm-packages.yml +++ b/.github/workflows/publish-npm-packages.yml @@ -67,7 +67,7 @@ jobs: - name: Setup Node.js if: ${{ github.event.inputs.release_type != 'wp' }} - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 with: node-version-file: 'cli/.nvmrc' registry-url: 'https://registry.npmjs.org' @@ -75,7 +75,7 @@ jobs: - name: Setup Node.js (for WP major version) if: ${{ github.event.inputs.release_type == 'wp' && github.event.inputs.wp_version }} - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 with: node-version-file: 'publish/.nvmrc' registry-url: 'https://registry.npmjs.org' diff --git a/.github/workflows/pull-request-automation.yml b/.github/workflows/pull-request-automation.yml index d7177ab216b7ed..996bb1667ada57 100644 --- a/.github/workflows/pull-request-automation.yml +++ b/.github/workflows/pull-request-automation.yml @@ -18,7 +18,7 @@ jobs: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Node.js - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 with: node-version-file: '.nvmrc' check-latest: true diff --git a/.github/workflows/rnmobile-ios-runner.yml b/.github/workflows/rnmobile-ios-runner.yml index c25b3e17c54b12..2f515ce5148f8b 100644 --- a/.github/workflows/rnmobile-ios-runner.yml +++ b/.github/workflows/rnmobile-ios-runner.yml @@ -27,7 +27,7 @@ jobs: with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - uses: ruby/setup-ruby@3783f195e29b74ae398d7caca108814bbafde90e # v1.180.1 + - uses: ruby/setup-ruby@50ba3386b050ad5b97a41fcb81240cbee1d1821f # v1.188.0 with: # `.ruby-version` file location working-directory: packages/react-native-editor/ios diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml index 030e338ec81da5..1efd248bf7f306 100644 --- a/.github/workflows/static-checks.yml +++ b/.github/workflows/static-checks.yml @@ -27,7 +27,7 @@ jobs: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Node.js - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 with: node-version-file: '.nvmrc' check-latest: true diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 75a0d34ddc8d87..98764848ecd809 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -193,7 +193,7 @@ jobs: # dependency versions are installed and cached. ## - name: Set up PHP - uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b # v2.31.0 + uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1 with: php-version: '${{ matrix.php }}' ini-file: development @@ -217,7 +217,7 @@ jobs: custom-cache-suffix: $(/bin/date -u --date='last Mon' "+%F") - name: Download built JavaScript assets - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: build-assets path: ./build @@ -295,7 +295,7 @@ jobs: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Set up PHP - uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b # v2.31.0 + uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1 with: php-version: '7.4' coverage: none diff --git a/.github/workflows/upload-release-to-plugin-repo.yml b/.github/workflows/upload-release-to-plugin-repo.yml index 6f01a4f6ff12fd..81a9c4739ac19b 100644 --- a/.github/workflows/upload-release-to-plugin-repo.yml +++ b/.github/workflows/upload-release-to-plugin-repo.yml @@ -189,7 +189,7 @@ jobs: sed -i "s/$STABLE_TAG_PLACEHOLDER/Stable tag: $VERSION/g" ./trunk/readme.txt - name: Download Changelog Artifact - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: changelog trunk path: trunk @@ -247,7 +247,7 @@ jobs: sed -i "s/$STABLE_TAG_PLACEHOLDER/Stable tag: $VERSION/g" "$VERSION/readme.txt" - name: Download Changelog Artifact - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: changelog trunk path: ${{ github.event.release.name }} From cee2a71383bb9417d3b989d630cf38501c72902e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 23 Jul 2024 17:44:56 +0200 Subject: [PATCH 0062/1908] Update dataviews docs (#63860) --- packages/dataviews/README.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 10da0e364a4995..c82a748df98858 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -22,6 +22,7 @@ const Example = () => { fields={ fields } view={ view } onChangeView={ onChangeView } + defaultLayouts={ defaultLayouts } actions={ actions } paginationInfo={ paginationInfo } /> @@ -169,8 +170,10 @@ Properties: - `direction`: the direction to use for sorting, one of `asc` or `desc`. - `fields`: the `id` of the fields that are visible in the UI. - `layout`: config that is specific to a particular layout type. - - `mediaField`: used by the `grid` and `list` layouts. The `id` of the field to be used for rendering each card's media. - - `primaryField`: used by the `table`, `grid` and `list` layouts. The `id` of the field to be highlighted in each row/card/item. + - `primaryField`: used by the `table`, `grid` and `list` layouts. The `id` of the field to be highlighted in each row/card/item. This field is not hiddable. + - `mediaField`: used by the `grid` and `list` layouts. The `id` of the field to be used for rendering each card's media. This field is not hiddable. + - `badgeFields`: used by the `grid` layout. It renders these fields without a label and styled as badges. + - `columnFields`: used by the `grid` layout. It renders the label and the field data vertically stacked instead of horizontally (the default). ### `onChangeView`: `function` @@ -276,7 +279,19 @@ Whether the data is loading. `false` by default. ### `defaultLayouts`: `Record< string, view >` -Default layouts. By default, uses empty layouts: `table`, `grid`, `list`. +This property provides layout information about the view types that are active. If empty, enables all layout types (see "Layout Types") with empty layout data. + +For example, this is how you'd enable only the table view type: + +```js +const defaultLayouts = { + table: { + layout: { + primaryKey: 'my-key', + } + } +}; +``` ### `onChangeSelection`: `function` From 950600928d0ae15cbc4162e4fddabe4537000db6 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 23 Jul 2024 17:52:17 +0200 Subject: [PATCH 0063/1908] Quick Edit: Support bulk selection (#63841) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../src/components/dataform/index.tsx | 2 +- .../src/components/post-edit/index.js | 42 ++++++++++++------- .../src/components/post-list/index.js | 4 +- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/packages/dataviews/src/components/dataform/index.tsx b/packages/dataviews/src/components/dataform/index.tsx index 3f4af8e110c776..64196c685a9784 100644 --- a/packages/dataviews/src/components/dataform/index.tsx +++ b/packages/dataviews/src/components/dataform/index.tsx @@ -49,7 +49,7 @@ function DataFormTextControl< Item >( { <TextControl label={ label } placeholder={ placeholder } - value={ value } + value={ value ?? '' } onChange={ onChangeControl } __next40pxDefaultSize /> diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 6e556c56a9152c..21dbb10e514660 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -8,7 +8,7 @@ import clsx from 'clsx'; */ import { __ } from '@wordpress/i18n'; import { DataForm } from '@wordpress/dataviews'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { useDispatch, useSelect, useRegistry } from '@wordpress/data'; import { store as coreDataStore } from '@wordpress/core-data'; import { Button } from '@wordpress/components'; import { useState, useMemo } from '@wordpress/element'; @@ -20,18 +20,25 @@ import Page from '../page'; import usePostFields from '../post-fields'; function PostEditForm( { postType, postId } ) { - const { item } = useSelect( + const ids = useMemo( () => postId.split( ',' ), [ postId ] ); + const { initialEdits } = useSelect( ( select ) => { + if ( ids.length !== 1 ) { + } return { - item: select( coreDataStore ).getEntityRecord( - 'postType', - postType, - postId - ), + initialEdits: + ids.length === 1 + ? select( coreDataStore ).getEntityRecord( + 'postType', + postType, + ids[ 0 ] + ) + : null, }; }, - [ postType, postId ] + [ postType, ids ] ); + const registry = useRegistry(); const { saveEntityRecord } = useDispatch( coreDataStore ); const { fields } = usePostFields(); const form = { @@ -40,20 +47,23 @@ function PostEditForm( { postType, postId } ) { const [ edits, setEdits ] = useState( {} ); const itemWithEdits = useMemo( () => { return { - ...item, + ...initialEdits, ...edits, }; - }, [ item, edits ] ); - const onSubmit = ( event ) => { + }, [ initialEdits, edits ] ); + const onSubmit = async ( event ) => { event.preventDefault(); - saveEntityRecord( 'postType', postType, itemWithEdits ); + const { getEntityRecord } = registry.resolveSelect( coreDataStore ); + for ( const id of ids ) { + const item = await getEntityRecord( 'postType', postType, id ); + saveEntityRecord( 'postType', postType, { + ...item, + ...edits, + } ); + } setEdits( {} ); }; - if ( ! item ) { - return null; - } - return ( <form onSubmit={ onSubmit }> <DataForm diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 7ca1be62f6d54b..ff25fbcd1962fb 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -142,7 +142,7 @@ export default function PostList( { postType } ) { const history = useHistory(); const location = useLocation(); const { postId, quickEdit = false } = location.params; - const [ selection, setSelection ] = useState( [ postId ] ); + const [ selection, setSelection ] = useState( postId?.split( ',' ) ?? [] ); const onChangeSelection = useCallback( ( items ) => { setSelection( items ); @@ -150,7 +150,7 @@ export default function PostList( { postType } ) { if ( ( params.isCustom ?? 'false' ) === 'false' ) { history.push( { ...params, - postId: items.length === 1 ? items[ 0 ] : undefined, + postId: items.join( ',' ), } ); } }, From 271c0851fad76af84aa7e184e8c6554c3cdea576 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 23 Jul 2024 18:07:48 +0200 Subject: [PATCH 0064/1908] DataForm: Add a simple story for the DataForm component (#63840) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- .../dataform/stories/index.story.tsx | 42 +++++++++++++++++++ .../dataviews}/stories/fixtures.js | 2 +- .../dataviews}/stories/index.story.js | 6 +-- .../src/test/filter-and-sort-data-view.js | 2 +- 4 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 packages/dataviews/src/components/dataform/stories/index.story.tsx rename packages/dataviews/src/{ => components/dataviews}/stories/fixtures.js (98%) rename packages/dataviews/src/{ => components/dataviews}/stories/index.story.js (86%) diff --git a/packages/dataviews/src/components/dataform/stories/index.story.tsx b/packages/dataviews/src/components/dataform/stories/index.story.tsx new file mode 100644 index 00000000000000..2e288c8e11d41c --- /dev/null +++ b/packages/dataviews/src/components/dataform/stories/index.story.tsx @@ -0,0 +1,42 @@ +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import DataForm from '../index'; + +const meta = { + title: 'DataViews/DataForm', + component: DataForm, +}; +export default meta; + +const fields = [ + { + id: 'title', + label: 'Title', + type: 'text' as const, + }, +]; + +export const Default = () => { + const [ post, setPost ] = useState( { + title: 'Hello, World!', + } ); + + const form = { + visibleFields: [ 'title' ], + }; + + return ( + <DataForm + data={ post } + fields={ fields } + form={ form } + onChange={ setPost } + /> + ); +}; diff --git a/packages/dataviews/src/stories/fixtures.js b/packages/dataviews/src/components/dataviews/stories/fixtures.js similarity index 98% rename from packages/dataviews/src/stories/fixtures.js rename to packages/dataviews/src/components/dataviews/stories/fixtures.js index 1ab26af4ef14d0..01351b84848fc1 100644 --- a/packages/dataviews/src/stories/fixtures.js +++ b/packages/dataviews/src/components/dataviews/stories/fixtures.js @@ -12,7 +12,7 @@ import { /** * Internal dependencies */ -import { LAYOUT_TABLE } from '../constants'; +import { LAYOUT_TABLE } from '../../../constants'; export const data = [ { diff --git a/packages/dataviews/src/stories/index.story.js b/packages/dataviews/src/components/dataviews/stories/index.story.js similarity index 86% rename from packages/dataviews/src/stories/index.story.js rename to packages/dataviews/src/components/dataviews/stories/index.story.js index 8a5ccd83450237..9ce1c29573e55c 100644 --- a/packages/dataviews/src/stories/index.story.js +++ b/packages/dataviews/src/components/dataviews/stories/index.story.js @@ -6,10 +6,10 @@ import { useState, useMemo } from '@wordpress/element'; /** * Internal dependencies */ -import { DataViews } from '../index'; +import DataViews from '../index'; import { DEFAULT_VIEW, actions, data, fields } from './fixtures'; -import { LAYOUT_GRID, LAYOUT_TABLE } from '../constants'; -import { filterSortAndPaginate } from '../filter-and-sort-data-view'; +import { LAYOUT_GRID, LAYOUT_TABLE } from '../../../constants'; +import { filterSortAndPaginate } from '../../../filter-and-sort-data-view'; const meta = { title: 'DataViews/DataViews', diff --git a/packages/dataviews/src/test/filter-and-sort-data-view.js b/packages/dataviews/src/test/filter-and-sort-data-view.js index fd15f4ebcc8e72..5083648e46ebb3 100644 --- a/packages/dataviews/src/test/filter-and-sort-data-view.js +++ b/packages/dataviews/src/test/filter-and-sort-data-view.js @@ -2,7 +2,7 @@ * Internal dependencies */ import { filterSortAndPaginate } from '../filter-and-sort-data-view'; -import { data, fields } from '../stories/fixtures'; +import { data, fields } from '../components/dataviews/stories/fixtures'; describe( 'filters', () => { it( 'should return empty if the data is empty', () => { From e39dad5751b9457f4d66fe7df78e3065b2beb4df Mon Sep 17 00:00:00 2001 From: Alex Lende <alex+github.com@lende.xyz> Date: Tue, 23 Jul 2024 11:26:50 -0500 Subject: [PATCH 0065/1908] JSON Schema Reorganization and Fixes (#63591) Co-authored-by: ajlende <ajlende@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- bin/api-docs/gen-theme-reference.mjs | 2 +- .../theme-json-reference/theme-json-living.md | 115 +- schemas/json/block.json | 296 +++-- schemas/json/font-collection.json | 35 +- schemas/json/theme.json | 1022 +++++++---------- schemas/json/wp-env.json | 34 +- 6 files changed, 627 insertions(+), 877 deletions(-) diff --git a/bin/api-docs/gen-theme-reference.mjs b/bin/api-docs/gen-theme-reference.mjs index 051f23c3ea997d..a447948d4593c4 100644 --- a/bin/api-docs/gen-theme-reference.mjs +++ b/bin/api-docs/gen-theme-reference.mjs @@ -220,7 +220,7 @@ const formatType = ( prop ) => { // Settings const settings = Object.entries( themejson.definitions ) .filter( ( [ settingsKey ] ) => - /^settingsProperties(?!Complete)\w+$/.test( settingsKey ) + /^settings\w+Properties$/.test( settingsKey ) ) .reduce( ( settingsObj, [ , { properties } ] ) => diff --git a/docs/reference-guides/theme-json-reference/theme-json-living.md b/docs/reference-guides/theme-json-reference/theme-json-living.md index d3f0b111d994d2..0b9e3e9d187766 100644 --- a/docs/reference-guides/theme-json-reference/theme-json-living.md +++ b/docs/reference-guides/theme-json-reference/theme-json-living.md @@ -39,14 +39,14 @@ Setting that enables the following UI tools: --- -### useRootPaddingAwareAlignments - -_**Note:** Since WordPress 6.1._ - -Enables root padding (the values from `styles.spacing.padding`) to be applied to the contents of full-width blocks instead of the root block. +### background -Please note that when using this setting, `styles.spacing.padding` should always be set as an object with `top`, `right`, `bottom`, `left` values declared separately. +Settings related to background. +| Property | Type | Default | Props | +| --- | --- | --- |--- | +| backgroundImage | boolean | false | | +| backgroundSize | boolean | false | | --- @@ -63,17 +63,6 @@ Settings related to borders. --- -### shadow - -Settings related to shadows. - -| Property | Type | Default | Props | -| --- | --- | --- |--- | -| defaultPresets | boolean | true | | -| presets | array | | name, shadow, slug | - ---- - ### color Settings related to colors. @@ -98,17 +87,6 @@ Settings related to colors. --- -### background - -Settings related to background. - -| Property | Type | Default | Props | -| --- | --- | --- |--- | -| backgroundImage | boolean | false | | -| backgroundSize | boolean | false | | - ---- - ### dimensions Settings related to dimensions. @@ -156,6 +134,17 @@ Settings related to position. --- +### shadow + +Settings related to shadows. + +| Property | Type | Default | Props | +| --- | --- | --- |--- | +| defaultPresets | boolean | true | | +| presets | array | | name, shadow, slug | + +--- + ### spacing Settings related to spacing. @@ -249,56 +238,44 @@ Color styles. --- -### dimensions +### css -Dimensions styles +Sets custom CSS to apply styling not covered by other theme.json properties. -| Property | Type | Props | -| --- | --- |--- | -| aspectRatio | string, object | | -| minHeight | string, object | | --- -### spacing +### dimensions -Spacing styles. +Dimensions styles. | Property | Type | Props | | --- | --- |--- | -| blockGap | string, object | | -| margin | object | bottom, left, right, top | -| padding | object | bottom, left, right, top | +| aspectRatio | string, object | | +| minHeight | string, object | | --- -### typography +### filter -Typography styles. +CSS and SVG filter styles. | Property | Type | Props | | --- | --- |--- | -| fontFamily | string, object | | -| fontSize | string, object | | -| fontStyle | string, object | | -| fontWeight | string, object | | -| letterSpacing | string, object | | -| lineHeight | string, object | | -| textAlign | string | | -| textColumns | string | | -| textDecoration | string, object | | -| writingMode | string, object | | -| textTransform | string, object | | +| duotone | string, object | | --- -### filter +### outline -CSS and SVG filter styles. +Outline styles. | Property | Type | Props | | --- | --- |--- | -| duotone | string, object | | +| color | string, object | | +| offset | string, object | | +| style | string, object | | +| width | string, object | | --- @@ -309,23 +286,35 @@ Box shadow styles. --- -### outline +### spacing -Outline styles. +Spacing styles. | Property | Type | Props | | --- | --- |--- | -| color | string, object | | -| offset | string, object | | -| style | string, object | | -| width | string, object | | +| blockGap | string, object | | +| margin | object | bottom, left, right, top | +| padding | object | bottom, left, right, top | --- -### css +### typography -Sets custom CSS to apply styling not covered by other theme.json properties. +Typography styles. +| Property | Type | Props | +| --- | --- |--- | +| fontFamily | string, object | | +| fontSize | string, object | | +| fontStyle | string, object | | +| fontWeight | string, object | | +| letterSpacing | string, object | | +| lineHeight | string, object | | +| textAlign | string, object | | +| textColumns | string, object | | +| textDecoration | string, object | | +| writingMode | string, object | | +| textTransform | string, object | | --- ## customTemplates diff --git a/schemas/json/block.json b/schemas/json/block.json index f142ddd0b490b4..8e314a45ae1cff 100644 --- a/schemas/json/block.json +++ b/schemas/json/block.json @@ -16,15 +16,15 @@ "type": "string" }, "apiVersion": { - "type": "integer", "description": "The version of the Block API used by the block. The most recent version is 3 and it was introduced in WordPress 6.3.\n\n See the API versions documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-api-versions/ for more details.", - "default": 1, - "enum": [ 1, 2, 3 ] + "type": "integer", + "enum": [ 1, 2, 3 ], + "default": 1 }, "name": { + "description": "The name for a block is a unique string that identifies a block. Names have to be structured as `namespace/block-name`, where namespace is the name of your plugin or theme.", "type": "string", - "pattern": "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$", - "description": "The name for a block is a unique string that identifies a block. Names have to be structured as `namespace/block-name`, where namespace is the name of your plugin or theme." + "pattern": "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$" }, "__experimental": { "description": "The name of the experiment this block is a part of, or boolean true if there is no specific experiment name.", @@ -38,8 +38,8 @@ ] }, "title": { - "type": "string", - "description": "This is the display title for your block, which can be translated with our translation functions. The block inserter will show this name." + "description": "This is the display title for your block, which can be translated with our translation functions. The block inserter will show this name.", + "type": "string" }, "category": { "description": "Blocks are grouped into categories to help users browse and discover them.\n Core provided categories are: text, media, design, widgets, theme, embed\n\nPlugins and Themes can also register custom block categories.\n\nhttps://developer.wordpress.org/block-editor/reference-guides/filters/block-filters/#managing-block-categories", @@ -48,6 +48,7 @@ "type": "string" }, { + "type": "string", "enum": [ "text", "media", @@ -60,52 +61,52 @@ ] }, "parent": { - "type": "array", "description": "Setting parent lets a block require that it is only available when nested within the specified blocks. For example, you might want to allow an ‘Add to Cart’ block to only be available within a ‘Product’ block.", + "type": "array", "items": { "type": "string" } }, "ancestor": { - "type": "array", "description": "The `ancestor` property makes a block available inside the specified block types at any position of the ancestor block subtree. That allows, for example, to place a ‘Comment Content’ block inside a ‘Column’ block, as long as ‘Column’ is somewhere within a ‘Comment Template’ block.", + "type": "array", "items": { "type": "string" } }, "allowedBlocks": { - "type": "array", "description": "The `allowedBlocks` property specifies that only the listed block types can be the children of this block. For example, a ‘List’ block allows only ‘List Item’ blocks as direct children.", + "type": "array", "items": { "type": "string" } }, "icon": { - "type": "string", - "description": "An icon property should be specified to make it easier to identify a block. These can be any of WordPress’ Dashicons (slug serving also as a fallback in non-js contexts)." + "description": "An icon property should be specified to make it easier to identify a block. These can be any of WordPress’ Dashicons (slug serving also as a fallback in non-js contexts).", + "type": "string" }, "description": { - "type": "string", - "description": "This is a short description for your block, which can be translated with our translation functions. This will be shown in the block inspector." + "description": "This is a short description for your block, which can be translated with our translation functions. This will be shown in the block inspector.", + "type": "string" }, "keywords": { - "type": "array", "description": "Sometimes a block could have aliases that help users discover it while searching. For example, an image block could also want to be discovered by photo. You can do so by providing an array of unlimited terms (which are translated).", + "type": "array", "items": { "type": "string" } }, "version": { - "type": "string", - "description": "The current version number of the block, such as 1.0 or 1.0.3. It’s similar to how plugins are versioned. This field might be used with block assets to control cache invalidation, and when the block author omits it, then the installed version of WordPress is used instead." + "description": "The current version number of the block, such as 1.0 or 1.0.3. It’s similar to how plugins are versioned. This field might be used with block assets to control cache invalidation, and when the block author omits it, then the installed version of WordPress is used instead.", + "type": "string" }, "textdomain": { - "type": "string", - "description": "The gettext text domain of the plugin/block. More information can be found in the Text Domain section of the How to Internationalize your Plugin page.\n\nhttps://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/" + "description": "The gettext text domain of the plugin/block. More information can be found in the Text Domain section of the How to Internationalize your Plugin page.\n\nhttps://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/", + "type": "string" }, "attributes": { - "type": "object", "description": "Attributes provide the structured data needs of a block. They can exist in different forms when they are serialized, but they are declared together under a common interface.\n\nSee the attributes documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/ for more details.", + "type": "object", "patternProperties": { "[a-zA-Z]": { "type": "object", @@ -145,25 +146,19 @@ ] }, "enum": { - "type": "array", "description": "An attribute can be defined as one of a fixed set of values. This is specified by an enum, which contains an array of allowed values:", + "type": "array", "items": { "oneOf": [ - { - "type": "boolean" - }, - { - "type": "number" - }, - { - "type": "string" - } + { "type": "boolean" }, + { "type": "number" }, + { "type": "string" } ] } }, "source": { - "type": "string", "description": "Attribute sources are used to define how the attribute values are extracted from saved post content. They provide a mechanism to map from the saved markup to a JavaScript representation of a block.", + "type": "string", "enum": [ "attribute", "text", @@ -175,40 +170,36 @@ ] }, "selector": { - "type": "string", - "description": "The selector can be an HTML tag, or anything queryable with querySelector, such as a class or id attribute. Examples are given below.\n\nFor example, a selector of img will match an img element, and img.class will match an img element that has a class of class." + "description": "The selector can be an HTML tag, or anything queryable with querySelector, such as a class or id attribute. Examples are given below.\n\nFor example, a selector of img will match an img element, and img.class will match an img element that has a class of class.", + "type": "string" }, "attribute": { - "type": "string", - "description": "Use an attribute source to extract the value from an attribute in the markup. The attribute is specified by the attribute field, which must be supplied.\n\nExample: Extract the src attribute from an image found in the block’s markup." + "description": "Use an attribute source to extract the value from an attribute in the markup. The attribute is specified by the attribute field, which must be supplied.\n\nExample: Extract the src attribute from an image found in the block’s markup.", + "type": "string" }, "query": { - "type": "object", - "description": "Use query to extract an array of values from markup. Entries of the array are determined by the selector argument, where each matched element within the block will have an entry structured corresponding to the second argument, an object of attribute sources." + "description": "Use query to extract an array of values from markup. Entries of the array are determined by the selector argument, where each matched element within the block will have an entry structured corresponding to the second argument, an object of attribute sources.", + "type": "object" }, "meta": { - "type": "string", - "description": "Although attributes may be obtained from a post’s meta, meta attribute sources are considered deprecated; EntityProvider and related hook APIs should be used instead, as shown in the Create Meta Block how-to here:\n\nhttps://developer.wordpress.org/block-editor/how-to-guides/metabox/#step-2-add-meta-block" + "description": "Although attributes may be obtained from a post’s meta, meta attribute sources are considered deprecated; EntityProvider and related hook APIs should be used instead, as shown in the Create Meta Block how-to here:\n\nhttps://developer.wordpress.org/block-editor/how-to-guides/metabox/#step-2-add-meta-block", + "type": "string" }, "default": { "description": "A block attribute can contain a default value, which will be used if the type and source do not match anything within the block content.\n\nThe value is provided by the default field, and the value should match the expected format of the attribute." } }, "anyOf": [ - { - "required": [ "type" ] - }, - { - "required": [ "enum" ] - } + { "required": [ "type" ] }, + { "required": [ "enum" ] } ] } }, "additionalProperties": false }, "providesContext": { - "type": "object", "description": "Context provided for available access by descendants of blocks of this type, in the form of an object which maps a context name to one of the block’s own attribute.\n\nSee the block context documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/ for more details.", + "type": "object", "patternProperties": { "[a-zA-Z]": { "type": "string" @@ -216,23 +207,22 @@ } }, "usesContext": { - "type": "array", "description": "Array of the names of context values to inherit from an ancestor provider.\n\nSee the block context documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/ for more details.", + "type": "array", "items": { "type": "string" } }, "supports": { - "type": "object", "description": "It contains as set of options to control features used in the editor. See the supports documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/ for more details.", + "type": "object", "properties": { "anchor": { - "type": "boolean", "description": "Anchors let you link directly to a specific block on a page. This property adds a field to define an id for the block and a button to copy the direct link.", + "type": "boolean", "default": false }, "align": { - "default": false, "description": "This property adds block controls which allow to change block’s alignment.", "oneOf": [ { @@ -251,129 +241,129 @@ ] } } - ] + ], + "default": false }, "alignWide": { - "type": "boolean", "description": "This property allows to enable wide alignment for your theme. To disable this behavior for a single block, set this flag to false.", + "type": "boolean", "default": true }, "ariaLabel": { - "type": "boolean", "description": "ARIA-labels let you define an accessible label for elements. This property allows enabling the definition of an aria-label for the block, without exposing a UI field.", + "type": "boolean", "default": false }, "className": { - "type": "boolean", "description": "By default, the class .wp-block-your-block-name is added to the root element of your saved markup. This helps having a consistent mechanism for styling blocks that themes and plugins can rely on. If, for whatever reason, a class is not desired on the markup, this functionality can be disabled.", + "type": "boolean", "default": true }, "color": { - "type": "object", "description": "This value signals that a block supports some of the properties related to color. When it does, the block editor will show UI controls for the user to set their values.\n\nNote that the background and text keys have a default value of true, so if the color property is present they’ll also be considered enabled", + "type": "object", "properties": { "background": { - "type": "boolean", "description": "This property adds UI controls which allow the user to apply a solid background color to a block.\n\nWhen color support is declared, this property is enabled by default (along with text), so simply setting color will enable background color.\n\nTo disable background support while keeping other color supports enabled, set to false.\n\nWhen the block declares support for color.background, its attributes definition is extended to include two new attributes: backgroundColor and style", + "type": "boolean", "default": true }, "gradients": { - "type": "boolean", "description": "This property adds UI controls which allow the user to apply a gradient background to a block.\n\nGradient presets are sourced from editor-gradient-presets theme support.\n\nWhen the block declares support for color.gradient, its attributes definition is extended to include two new attributes: gradient and style", + "type": "boolean", "default": false }, "link": { - "type": "boolean", "description": "This property adds block controls which allow the user to set link color in a block, link color is disabled by default.\n\nLink color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.link, its attributes definition is extended to include the style attribute", + "type": "boolean", "default": false }, "text": { - "type": "boolean", "description": "This property adds block controls which allow the user to set text color in a block.\n\nWhen color support is declared, this property is enabled by default (along with background), so simply setting color will enable text color.\n\nText color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.text, its attributes definition is extended to include two new attributes: textColor and style", + "type": "boolean", "default": true }, "heading": { - "type": "boolean", "description": "This property adds block controls which allow the user to set heading colors in a block. Heading color is disabled by default.\n\nHeading color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.heading, its attributes definition is extended to include the style attribute", + "type": "boolean", "default": false }, "button": { - "type": "boolean", "description": "This property adds block controls which allow the user to set button colors in a block. Button color is disabled by default.\n\nButton color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.button, its attributes definition is extended to include the style attribute", + "type": "boolean", "default": false }, "enableContrastChecker": { - "type": "boolean", "description": "Determines whether the contrast checker widget displays in the block editor UI.\n\nThe contrast checker appears only if the block declares support for color. It tests the readability of color combinations and warns if there is a potential issue. The property is enabled by default.\n\nSet to `false` to explicitly disable.", + "type": "boolean", "default": true } } }, "customClassName": { - "type": "boolean", "description": "This property adds a field to define a custom className for the block’s wrapper.", + "type": "boolean", "default": true }, "dimensions": { - "type": "object", "description": "This value signals that a block supports some of the CSS style properties related to dimensions. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific dimensions property, its attributes definition is extended to include the style attribute.", + "type": "object", "properties": { "aspectRatio": { - "type": "boolean", "description": "Allow blocks to define an aspect ratio value.", + "type": "boolean", "default": false }, "minHeight": { - "type": "boolean", "description": "Allow blocks to define a minimum height value.", + "type": "boolean", "default": false } } }, "filter": { - "type": "object", "description": "This value signals that a block supports some of the properties related to filters. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific filter property, its attributes definition is extended to include the style attribute.", + "type": "object", "properties": { "duotone": { - "type": "boolean", "description": "Allow blocks to define a duotone filter.", + "type": "boolean", "default": false } } }, "background": { - "type": "object", "description": "This value signals that a block supports some of the CSS style properties related to background. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific background property, its attributes definition is extended to include the style attribute.", + "type": "object", "properties": { "backgroundImage": { - "type": "boolean", "description": "Allow blocks to define a background image.", + "type": "boolean", "default": false }, "backgroundSize": { - "type": "boolean", "description": "Allow blocks to define values related to the size of a background image, including size, position, and repeat controls", + "type": "boolean", "default": false } } }, "html": { - "type": "boolean", "description": "By default, a block’s markup can be edited individually. To disable this behavior, set html to false.", + "type": "boolean", "default": true }, "inserter": { - "type": "boolean", "description": "By default, all blocks will appear in the inserter, block transforms menu, Style Book, etc. To hide a block from all parts of the user interface so that it can only be inserted programmatically, set inserter to false.", + "type": "boolean", "default": true }, "renaming": { - "type": "boolean", "description": "By default, a block can be renamed by a user from the block 'Options' dropdown or the 'Advanced' panel. To disable this behavior, set renaming to false.", + "type": "boolean", "default": true }, "layout": { - "default": false, "description": "This value only applies to blocks that are containers for inner blocks. If set to `true` the layout type will be `flow`. For other layout types it's necessary to set the `type` explicitly inside the `default` object.", "oneOf": [ { "type": "boolean" }, @@ -381,12 +371,12 @@ "type": "object", "properties": { "default": { - "type": "object", "description": "Allows setting the `type` property to define what layout type is default for the block, and also default values for any properties inherent to that layout type, e.g., for a `flex` layout, a default value can be set for `flexWrap`.", + "type": "object", "properties": { "type": { - "type": "string", "description": "The layout type.", + "type": "string", "enum": [ "constrained", "grid", @@ -394,16 +384,16 @@ ] }, "contentSize": { - "type": "string", - "description": "The content size used on all children." + "description": "The content size used on all children.", + "type": "string" }, "wideSize": { - "type": "string", - "description": "The wide size used on alignwide children." + "description": "The wide size used on alignwide children.", + "type": "string" }, "justifyContent": { - "type": "string", "description": "Content justification value.", + "type": "string", "enum": [ "right", "center", @@ -413,18 +403,18 @@ ] }, "orientation": { - "type": "string", "description": "The orientation of the layout.", + "type": "string", "enum": [ "horizontal", "vertical" ] }, "flexWrap": { - "type": "string", "description": "The flex wrap value.", + "type": "string", "enum": [ "wrap", "nowrap" ] }, "verticalAlignment": { - "type": "string", "description": "The vertical alignment value.", + "type": "string", "enum": [ "top", "center", @@ -434,88 +424,89 @@ ] }, "minimumColumnWidth": { - "type": "string", - "description": "The minimum column width value." + "description": "The minimum column width value.", + "type": "string" }, "columnCount": { - "type": "number", - "description": "The column count value." + "description": "The column count value.", + "type": "number" } } }, "allowSwitching": { - "type": "boolean", "description": "Exposes a switcher control that allows toggling between all existing layout types.", + "type": "boolean", "default": false }, "allowEditing": { - "type": "boolean", "description": "Determines display of layout controls in the block sidebar. If set to false, layout controls will be hidden.", + "type": "boolean", "default": true }, "allowInheriting": { - "type": "boolean", "description": "For the `flow` layout type only, determines display of the `Inner blocks use content width` toggle.", + "type": "boolean", "default": true }, "allowSizingOnChildren": { - "type": "boolean", "description": "For the `flex` layout type only, determines display of sizing controls (Fit/Fill/Fixed) on all child blocks of the flex block.", + "type": "boolean", "default": false }, "allowVerticalAlignment": { - "type": "boolean", "description": "For the `flex` layout type only, determines display of vertical alignment controls in the block toolbar.", + "type": "boolean", "default": true }, "allowJustification": { - "type": "boolean", "description": "For the `flex` layout type, determines display of justification controls in the block toolbar and block sidebar. For the `constrained` layout type, determines display of justification control in the block sidebar.", + "type": "boolean", "default": true }, "allowOrientation": { - "type": "boolean", "description": "For the `flex` layout type only, determines display of the orientation control in the block toolbar.", + "type": "boolean", "default": true }, "allowCustomContentAndWideSize": { - "type": "boolean", "description": "For the `constrained` layout type only, determines display of the custom content and wide size controls in the block sidebar.", + "type": "boolean", "default": true } } } - ] + ], + "default": false }, "multiple": { - "type": "boolean", "description": "A non-multiple block can be inserted into each post, one time only. For example, the built-in ‘More’ block cannot be inserted again if it already exists in the post being edited. A non-multiple block’s icon is automatically dimmed (unclickable) to prevent multiple instances.", + "type": "boolean", "default": true }, "reusable": { - "type": "boolean", "description": "A block may want to disable the ability of being converted into a reusable block. By default all blocks can be converted to a reusable block. If supports reusable is set to false, the option to convert the block into a reusable block will not appear.", + "type": "boolean", "default": true }, "lock": { - "type": "boolean", "description": "A block may want to disable the ability to toggle the lock state. It can be locked/unlocked by a user from the block 'Options' dropdown by default. To disable this behavior, set lock to false.", + "type": "boolean", "default": true }, "position": { - "type": "object", "description": "This value signals that a block supports some of the CSS style properties related to position. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific position property, its attributes definition is extended to include the style attribute.", + "type": "object", "properties": { "sticky": { - "type": "boolean", "description": "Allow blocks to stick to their immediate parent when scrolling the page.", + "type": "boolean", "default": false } } }, "spacing": { - "type": "object", "description": "This value signals that a block supports some of the CSS style properties related to spacing. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific spacing property, its attributes definition is extended to include the style attribute.", + "type": "object", "properties": { "margin": { "oneOf": [ @@ -572,30 +563,30 @@ } }, "shadow": { - "default": false, "description": "Allow blocks to define a box shadow.", "oneOf": [ { - "type": "boolean", - "description": "Defines whether a box shadow is enabled or not." + "description": "Defines whether a box shadow is enabled or not.", + "type": "boolean" }, { "type": "object" } - ] + ], + "default": false }, "typography": { - "type": "object", "description": "This value signals that a block supports some of the CSS style properties related to typography. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific typography property, its attributes definition is extended to include the style attribute.", + "type": "object", "properties": { "fontSize": { - "type": "boolean", "description": "This value signals that a block supports the font-size CSS style property. When it does, the block editor will show an UI control for the user to set its value.\n\nThe values shown in this control are the ones declared by the theme via the editor-font-sizes theme support, or the default ones if none is provided.\n\nWhen the block declares support for fontSize, its attributes definition is extended to include two new attributes: fontSize and style", + "type": "boolean", "default": false }, "lineHeight": { - "type": "boolean", "description": "This value signals that a block supports the line-height CSS style property. When it does, the block editor will show an UI control for the user to set its value if the theme declares support.\n\nWhen the block declares support for lineHeight, its attributes definition is extended to include a new attribute style of object type with no default assigned. It stores the custom value set by the user. The block can apply a default style by specifying its own style attribute with a default", + "type": "boolean", "default": false }, "textAlign": { @@ -620,21 +611,21 @@ "description": "Indicates if the block is using Interactivity API features.", "oneOf": [ { - "type": "boolean", "description": "Indicates whether the block is using the Interactivity API directives.", + "type": "boolean", "default": false }, { "type": "object", "properties": { "clientNavigation": { - "type": "boolean", "description": "Indicates whether a block is compatible with the Interactivity API client-side navigation.\n\nSet it to true only if the block is not interactive or if it is interactive using the Interactivity API. Set it to false if the block is interactive but uses vanilla JS, jQuery or another JS framework/library other than the Interactivity API.", + "type": "boolean", "default": false }, "interactive": { - "type": "boolean", "description": "Indicates whether the block is using the Interactivity API directives.", + "type": "boolean", "default": false } } @@ -642,20 +633,20 @@ ] }, "splitting": { - "type": "boolean", "description": "This property indicates whether the block can split when the Enter key is pressed or when blocks are pasted.", + "type": "boolean", "default": false } }, "additionalProperties": true }, "selectors": { - "type": "object", "description": "Provides custom CSS selectors and mappings for the block. Selectors may be set for the block itself or per-feature e.g. typography. Custom selectors per feature or sub-feature, allow different block styles to be applied to different elements within the block.", + "type": "object", "properties": { "root": { - "type": "string", - "description": "The primary CSS class to apply to the block. This replaces the `.wp-block-name` class if set." + "description": "The primary CSS class to apply to the block. This replaces the `.wp-block-name` class if set.", + "type": "string" }, "border": { "description": "Custom CSS selector used to generate rules for the block's theme.json border styles.", @@ -749,8 +740,8 @@ } }, "styles": { - "type": "array", "description": "Block styles can be used to provide alternative styles to block. It works by adding a class name to the block’s wrapper. Using CSS, a theme developer can target the class name for the block style if it is selected.\n\nPlugins and Themes can also register custom block style for existing blocks.\n\nhttps://developer.wordpress.org/block-editor/reference-guides/block-api/block-styles", + "type": "array", "items": { "type": "object", "properties": { @@ -770,21 +761,21 @@ } }, "example": { - "type": "object", "description": "It provides structured example data for the block. This data is used to construct a preview for the block to be shown in the Inspector Help Panel when the user mouses over the block.\n\nSee the example documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#example-optional for more details.", + "type": "object", "properties": { "viewportWidth": { - "type": "number", "description": "The viewportWidth controls the width of the iFrame container in which the block preview will get rendered", + "type": "number", "default": 1200 }, "attributes": { - "type": "object", - "description": "Set the attributes for the block example" + "description": "Set the attributes for the block example", + "type": "object" }, "innerBlocks": { - "type": "array", - "description": "Set the inner blocks that should be used within the block example. The blocks should be defined as a nested array like this:\n\n[ { \"name\": \"core/heading\", \"attributes\": { \"content\": \"This is an Example\" } } ]\n\nWhere each block itself is an object that contains the block name, the block attributes, and the blocks inner blocks." + "description": "Set the inner blocks that should be used within the block example. The blocks should be defined as a nested array like this:\n\n[ { \"name\": \"core/heading\", \"attributes\": { \"content\": \"This is an Example\" } } ]\n\nWhere each block itself is an object that contains the block name, the block attributes, and the blocks inner blocks.", + "type": "array" } } }, @@ -793,6 +784,7 @@ "type": "object", "patternProperties": { "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": { + "type": "string", "enum": [ "before", "after", "firstChild", "lastChild" ] } }, @@ -900,28 +892,26 @@ "description": "Block Variations is the API that allows a block to have similar versions of it, but all these versions share some common functionality.", "oneOf": [ { - "type": "string", - "description": "The path to a PHP file that returns an array of block variations." + "description": "The path to a PHP file that returns an array of block variations.", + "type": "string" }, { - "type": "array", "description": "An array of block variations.", + "type": "array", "items": { "type": "object", - "required": [ "name", "title" ], - "additionalProperties": false, "properties": { "name": { - "type": "string", - "description": "The unique and machine-readable name." + "description": "The unique and machine-readable name.", + "type": "string" }, "title": { - "type": "string", - "description": "A human-readable variation title." + "description": "A human-readable variation title.", + "type": "string" }, "description": { - "type": "string", - "description": "A detailed variation description." + "description": "A detailed variation description.", + "type": "string" }, "category": { "description": "A category classification, used in search interfaces to arrange block types by category.", @@ -930,6 +920,7 @@ "type": "string" }, { + "type": "string", "enum": [ "text", "media", @@ -946,55 +937,58 @@ "type": "string" }, "isDefault": { + "description": "Indicates whether the current variation is the default one.", "type": "boolean", - "default": false, - "description": "Indicates whether the current variation is the default one." + "default": false }, "attributes": { - "type": "object", - "description": "Values that override block attributes." + "description": "Values that override block attributes.", + "type": "object" }, "innerBlocks": { + "description": "Initial configuration of nested blocks.", "type": "array", "items": { "type": "array" - }, - "description": "Initial configuration of nested blocks." + } }, "example": { - "type": "object", - "description": "Example provides structured data for the block preview. You can set to undefined to disable the preview shown for the block type." + "description": "Example provides structured data for the block preview. You can set to undefined to disable the preview shown for the block type.", + "type": "object" }, "scope": { - "type": "array", "description": "The list of scopes where the variation is applicable.", + "type": "array", "items": { + "type": "string", "enum": [ "inserter", "block", "transform" ] }, "default": [ "inserter", "block" ] }, "keywords": { - "type": "array", "description": "An array of terms (which can be translated) that help users discover the variation while searching.", + "type": "array", "items": { "type": "string" } }, "isActive": { + "description": "The list of attributes that should be compared. Each attributes will be matched and the variation will be active if all of them are matching.", "type": "array", "items": { "type": "string" - }, - "description": "The list of attributes that should be compared. Each attributes will be matched and the variation will be active if all of them are matching." + } } - } + }, + "required": [ "name", "title" ], + "additionalProperties": false } } ] }, "render": { - "type": "string", - "description": "Template file loaded on the server when rendering a block." + "description": "Template file loaded on the server when rendering a block.", + "type": "string" } }, "required": [ "name", "title" ], diff --git a/schemas/json/font-collection.json b/schemas/json/font-collection.json index 97b0cdf8edae49..7b5bd8f7979ba7 100644 --- a/schemas/json/font-collection.json +++ b/schemas/json/font-collection.json @@ -1,7 +1,6 @@ { "title": "JSON schema for WordPress Font Collections", "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", "definitions": { "fontFace": { "description": "Font face settings, with added preview property.", @@ -23,28 +22,19 @@ }, "fontWeight": { "description": "List of available font weights, separated by a space.", - "default": "400", - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] + "oneOf": [ { "type": "string" }, { "type": "integer" } ], + "default": "400" }, "fontDisplay": { "description": "CSS font-display value.", "type": "string", - "default": "fallback", - "enum": [ "auto", "block", "fallback", "swap", "optional" ] + "enum": [ "auto", "block", "fallback", "swap", "optional" ], + "default": "fallback" }, "src": { "description": "Paths or URLs to the font files.", "oneOf": [ - { - "type": "string" - }, + { "type": "string" }, { "type": "array", "items": { @@ -95,14 +85,15 @@ "additionalProperties": false } }, + "type": "object", "properties": { "$schema": { "description": "JSON schema URI for font-collection.json.", "type": "string" }, "font_families": { - "type": "array", "description": "Array of font families ready to be installed.", + "type": "array", "items": { "type": "object", "properties": { @@ -123,18 +114,14 @@ "type": "string" }, "preview": { - "type": "string", - "description": "URL to a preview image of the font family." + "description": "URL to a preview image of the font family.", + "type": "string" }, "fontFace": { "description": "Array of font-face definitions.", "type": "array", "items": { - "allOf": [ - { - "$ref": "#/definitions/fontFace" - } - ] + "$ref": "#/definitions/fontFace" } } }, @@ -142,8 +129,8 @@ "additionalProperties": false }, "categories": { - "type": "array", "description": "Array of category slugs.", + "type": "array", "items": { "type": "string" } diff --git a/schemas/json/theme.json b/schemas/json/theme.json index 1bcfd1335c64c7..a1f51ace920259 100644 --- a/schemas/json/theme.json +++ b/schemas/json/theme.json @@ -17,7 +17,7 @@ }, "additionalProperties": false }, - "settingsPropertiesAppearanceTools": { + "settingsAppearanceToolsProperties": { "type": "object", "properties": { "appearanceTools": { @@ -27,16 +27,29 @@ } } }, - "settingsPropertiesUseRootPaddingAwareAlignments": { + "settingsBackgroundProperties": { + "type": "object", "properties": { - "useRootPaddingAwareAlignments": { - "description": "_**Note:** Since WordPress 6.1._\n\nEnables root padding (the values from `styles.spacing.padding`) to be applied to the contents of full-width blocks instead of the root block.\n\nPlease note that when using this setting, `styles.spacing.padding` should always be set as an object with `top`, `right`, `bottom`, `left` values declared separately.", - "type": "boolean", - "default": false + "background": { + "description": "Settings related to background.", + "type": "object", + "properties": { + "backgroundImage": { + "description": "Allow users to set a background image.", + "type": "boolean", + "default": false + }, + "backgroundSize": { + "description": "Allow users to set values related to the size of a background image, including size, position, and repeat controls.", + "type": "boolean", + "default": false + } + }, + "additionalProperties": false } } }, - "settingsPropertiesBorder": { + "settingsBorderProperties": { "type": "object", "properties": { "border": { @@ -68,47 +81,7 @@ } } }, - "settingsPropertiesShadow": { - "type": "object", - "properties": { - "shadow": { - "description": "Settings related to shadows.", - "type": "object", - "properties": { - "defaultPresets": { - "description": "Allow users to choose shadows from the default shadow presets.", - "type": "boolean", - "default": true - }, - "presets": { - "description": "Shadow presets for the shadow picker.\nGenerates a single custom property (`--wp--preset--shadow--{slug}`) per preset value.", - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "description": "Name of the shadow preset, translatable.", - "type": "string" - }, - "slug": { - "description": "Kebab-case unique identifier for the shadow preset.", - "type": "string" - }, - "shadow": { - "description": "CSS box-shadow value", - "type": "string" - } - }, - "required": [ "name", "slug", "shadow" ], - "additionalProperties": false - } - } - }, - "additionalProperties": false - } - } - }, - "settingsPropertiesColor": { + "settingsColorProperties": { "type": "object", "properties": { "color": { @@ -253,29 +226,7 @@ } } }, - "settingsPropertiesBackground": { - "type": "object", - "properties": { - "background": { - "description": "Settings related to background.", - "type": "object", - "properties": { - "backgroundImage": { - "description": "Allow users to set a background image.", - "type": "boolean", - "default": false - }, - "backgroundSize": { - "description": "Allow users to set values related to the size of a background image, including size, position, and repeat controls.", - "type": "boolean", - "default": false - } - }, - "additionalProperties": false - } - } - }, - "settingsPropertiesDimensions": { + "settingsDimensionsProperties": { "type": "object", "properties": { "dimensions": { @@ -323,7 +274,7 @@ } } }, - "settingsPropertiesLayout": { + "settingsLayoutProperties": { "type": "object", "properties": { "layout": { @@ -353,7 +304,7 @@ } } }, - "settingsPropertiesLightbox": { + "settingsLightboxProperties": { "type": "object", "properties": { "lightbox": { @@ -373,7 +324,7 @@ } } }, - "settingsPropertiesPosition": { + "settingsPositionProperties": { "type": "object", "properties": { "position": { @@ -390,7 +341,47 @@ } } }, - "settingsPropertiesSpacing": { + "settingsShadowProperties": { + "type": "object", + "properties": { + "shadow": { + "description": "Settings related to shadows.", + "type": "object", + "properties": { + "defaultPresets": { + "description": "Allow users to choose shadows from the default shadow presets.", + "type": "boolean", + "default": true + }, + "presets": { + "description": "Shadow presets for the shadow picker.\nGenerates a single custom property (`--wp--preset--shadow--{slug}`) per preset value.", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "description": "Name of the shadow preset, translatable.", + "type": "string" + }, + "slug": { + "description": "Kebab-case unique identifier for the shadow preset.", + "type": "string" + }, + "shadow": { + "description": "CSS box-shadow value", + "type": "string" + } + }, + "required": [ "name", "slug", "shadow" ], + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + } + }, + "settingsSpacingProperties": { "type": "object", "properties": { "spacing": { @@ -421,8 +412,8 @@ "items": { "type": "string" }, - "default": [ "px", "em", "rem", "vh", "vw", "%" ], - "minItems": 1 + "minItems": 1, + "default": [ "px", "em", "rem", "vh", "vw", "%" ] }, "customSpacingSize": { "description": "Allow users to set custom space sizes.", @@ -528,7 +519,7 @@ } } }, - "settingsPropertiesTypography": { + "settingsTypographyProperties": { "type": "object", "properties": { "typography": { @@ -670,8 +661,8 @@ "description": "Font family presets for the font family selector.\nGenerates a single custom property (`--wp--preset--font-family--{slug}`) per preset value.", "type": "array", "items": { - "type": "object", "description": "Font family preset", + "type": "object", "properties": { "name": { "description": "Name of the font family preset, translatable.", @@ -689,7 +680,96 @@ "description": "Array of font-face declarations.", "type": "array", "items": { - "$ref": "#/definitions/fontFace" + "type": "object", + "properties": { + "fontFamily": { + "description": "CSS font-family value.", + "type": "string", + "default": "" + }, + "fontStyle": { + "description": "CSS font-style value.", + "type": "string", + "default": "normal" + }, + "fontWeight": { + "description": "List of available font weights, separated by a space.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ], + "default": "400" + }, + "fontDisplay": { + "description": "CSS font-display value.", + "type": "string", + "enum": [ + "auto", + "block", + "fallback", + "swap", + "optional" + ], + "default": "fallback" + }, + "src": { + "description": "Paths or URLs to the font files.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "default": [] + }, + "fontStretch": { + "description": "CSS font-stretch value.", + "type": "string" + }, + "ascentOverride": { + "description": "CSS ascent-override value.", + "type": "string" + }, + "descentOverride": { + "description": "CSS descent-override value.", + "type": "string" + }, + "fontVariant": { + "description": "CSS font-variant value.", + "type": "string" + }, + "fontFeatureSettings": { + "description": "CSS font-feature-settings value.", + "type": "string" + }, + "fontVariationSettings": { + "description": "CSS font-variation-settings value.", + "type": "string" + }, + "lineGapOverride": { + "description": "CSS line-gap-override value.", + "type": "string" + }, + "sizeAdjust": { + "description": "CSS size-adjust value.", + "type": "string" + }, + "unicodeRange": { + "description": "CSS unicode-range value.", + "type": "string" + } + }, + "required": [ "fontFamily", "src" ], + "additionalProperties": false } } }, @@ -701,93 +781,7 @@ } } }, - "fontFace": { - "type": "object", - "properties": { - "fontFamily": { - "description": "CSS font-family value.", - "type": "string", - "default": "" - }, - "fontStyle": { - "description": "CSS font-style value.", - "type": "string", - "default": "normal" - }, - "fontWeight": { - "description": "List of available font weights, separated by a space.", - "default": "400", - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - }, - "fontDisplay": { - "description": "CSS font-display value.", - "type": "string", - "default": "fallback", - "enum": [ "auto", "block", "fallback", "swap", "optional" ] - }, - "src": { - "description": "Paths or URLs to the font files.", - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "default": [] - }, - "fontStretch": { - "description": "CSS font-stretch value.", - "type": "string" - }, - "ascentOverride": { - "description": "CSS ascent-override value.", - "type": "string" - }, - "descentOverride": { - "description": "CSS descent-override value.", - "type": "string" - }, - "fontVariant": { - "description": "CSS font-variant value.", - "type": "string" - }, - "fontFeatureSettings": { - "description": "CSS font-feature-settings value.", - "type": "string" - }, - "fontVariationSettings": { - "description": "CSS font-variation-settings value.", - "type": "string" - }, - "lineGapOverride": { - "description": "CSS line-gap-override value.", - "type": "string" - }, - "sizeAdjust": { - "description": "CSS size-adjust value.", - "type": "string" - }, - "unicodeRange": { - "description": "CSS unicode-range value.", - "type": "string" - } - }, - "required": [ "fontFamily", "src" ], - "additionalProperties": false - }, - "settingsPropertiesCustom": { + "settingsCustomProperties": { "type": "object", "properties": { "custom": { @@ -797,18 +791,18 @@ }, "settingsProperties": { "allOf": [ - { "$ref": "#/definitions/settingsPropertiesAppearanceTools" }, - { "$ref": "#/definitions/settingsPropertiesBackground" }, - { "$ref": "#/definitions/settingsPropertiesBorder" }, - { "$ref": "#/definitions/settingsPropertiesColor" }, - { "$ref": "#/definitions/settingsPropertiesDimensions" }, - { "$ref": "#/definitions/settingsPropertiesShadow" }, - { "$ref": "#/definitions/settingsPropertiesLayout" }, - { "$ref": "#/definitions/settingsPropertiesLightbox" }, - { "$ref": "#/definitions/settingsPropertiesPosition" }, - { "$ref": "#/definitions/settingsPropertiesSpacing" }, - { "$ref": "#/definitions/settingsPropertiesTypography" }, - { "$ref": "#/definitions/settingsPropertiesCustom" } + { "$ref": "#/definitions/settingsAppearanceToolsProperties" }, + { "$ref": "#/definitions/settingsBackgroundProperties" }, + { "$ref": "#/definitions/settingsBorderProperties" }, + { "$ref": "#/definitions/settingsColorProperties" }, + { "$ref": "#/definitions/settingsDimensionsProperties" }, + { "$ref": "#/definitions/settingsLayoutProperties" }, + { "$ref": "#/definitions/settingsLightboxProperties" }, + { "$ref": "#/definitions/settingsPositionProperties" }, + { "$ref": "#/definitions/settingsShadowProperties" }, + { "$ref": "#/definitions/settingsSpacingProperties" }, + { "$ref": "#/definitions/settingsTypographyProperties" }, + { "$ref": "#/definitions/settingsCustomProperties" } ] }, "settingsPropertyNames": { @@ -828,12 +822,12 @@ ] }, "settingsPropertiesComplete": { - "type": "object", "allOf": [ { "$ref": "#/definitions/settingsProperties" }, { + "type": "object", "propertyNames": { "$ref": "#/definitions/settingsPropertyNames" } @@ -1173,10 +1167,8 @@ "backgroundImage": { "description": "Sets the `background-image` CSS property.", "oneOf": [ - { - "description": "A valid CSS value for the background-image CSS property.", - "type": "string" - }, + { "type": "string" }, + { "$ref": "#/definitions/refComplete" }, { "type": "object", "properties": { @@ -1186,54 +1178,35 @@ } }, "additionalProperties": false - }, - { - "$ref": "#/definitions/refComplete" } ] }, "backgroundPosition": { "description": "Sets the `background-position` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "backgroundRepeat": { "description": "Sets the `background-repeat` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "backgroundSize": { "description": "Sets the `background-size` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "backgroundAttachment": { "description": "Sets the `background-attachment` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] } }, @@ -1246,32 +1219,22 @@ "color": { "description": "Sets the `border-color` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "radius": { "description": "Sets the `border-radius` CSS property.", "anyOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - }, + { "type": "string" }, + { "$ref": "#/definitions/refComplete" }, { "type": "object", "properties": { "topLeft": { "description": "Sets the `border-top-left-radius` CSS property.", "oneOf": [ - { - "type": "string" - }, + { "type": "string" }, { "$ref": "#/definitions/refComplete" } @@ -1280,9 +1243,7 @@ "topRight": { "description": "Sets the `border-top-right-radius` CSS property.", "oneOf": [ - { - "type": "string" - }, + { "type": "string" }, { "$ref": "#/definitions/refComplete" } @@ -1291,9 +1252,7 @@ "bottomLeft": { "description": "Sets the `border-bottom-left-radius` CSS property.", "oneOf": [ - { - "type": "string" - }, + { "type": "string" }, { "$ref": "#/definitions/refComplete" } @@ -1302,9 +1261,7 @@ "bottomRight": { "description": "Sets the `border-bottom-right-radius` CSS property.", "oneOf": [ - { - "type": "string" - }, + { "type": "string" }, { "$ref": "#/definitions/refComplete" } @@ -1317,23 +1274,15 @@ "style": { "description": "Sets the `border-style` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "width": { "description": "Sets the `border-width` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "top": { @@ -1342,34 +1291,22 @@ "color": { "description": "Sets the `border-top-color` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "style": { "description": "Sets the `border-top-style` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "width": { "description": "Sets the `border-top-width` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] } }, @@ -1381,34 +1318,22 @@ "color": { "description": "Sets the `border-right-color` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "style": { "description": "Sets the `border-right-style` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "width": { "description": "Sets the `border-right-width` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] } }, @@ -1420,34 +1345,22 @@ "color": { "description": "Sets the `border-bottom-color` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "style": { "description": "Sets the `border-bottom-style` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "width": { "description": "Sets the `border-bottom-width` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] } }, @@ -1459,34 +1372,22 @@ "color": { "description": "Sets the `border-left-color` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "style": { "description": "Sets the `border-left-style` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "width": { "description": "Sets the `border-left-width` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] } }, @@ -1502,67 +1403,107 @@ "background": { "description": "Sets the `background-color` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "gradient": { "description": "Sets the `background` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "text": { "description": "Sets the `color` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] } }, "additionalProperties": false }, + "css": { + "description": "Sets custom CSS to apply styling not covered by other theme.json properties.", + "type": "string" + }, "dimensions": { - "description": "Dimensions styles", + "description": "Dimensions styles.", "type": "object", "properties": { "aspectRatio": { "description": "Sets the `aspect-ratio` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "minHeight": { "description": "Sets the `min-height` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] } } }, + "filter": { + "description": "CSS and SVG filter styles.", + "type": "object", + "properties": { + "duotone": { + "description": "Sets the duotone filter.", + "oneOf": [ + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } + ] + } + }, + "additionalProperties": false + }, + "outline": { + "description": "Outline styles.", + "type": "object", + "properties": { + "color": { + "description": "Sets the `outline-color` CSS property.", + "oneOf": [ + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } + ] + }, + "offset": { + "description": "Sets the `outline-offset` CSS property.", + "oneOf": [ + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } + ] + }, + "style": { + "description": "Sets the `outline-style` CSS property.", + "oneOf": [ + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } + ] + }, + "width": { + "description": "Sets the `outline-width` CSS property.", + "oneOf": [ + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } + ] + } + }, + "additionalProperties": false + }, + "shadow": { + "description": "Box shadow styles.", + "oneOf": [ + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } + ] + }, "spacing": { "description": "Spacing styles.", "type": "object", @@ -1570,12 +1511,8 @@ "blockGap": { "description": "Sets the `--wp--style--block-gap` CSS custom property when settings.spacing.blockGap is true.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "margin": { @@ -1585,45 +1522,29 @@ "top": { "description": "Sets the `margin-top` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "right": { "description": "Sets the `margin-right` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "bottom": { "description": "Sets the `margin-bottom` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "left": { "description": "Sets the `margin-left` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] } }, @@ -1636,45 +1557,29 @@ "top": { "description": "Sets the `padding-top` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "right": { "description": "Sets the `padding-right` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "bottom": { "description": "Sets the `padding-bottom` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "left": { "description": "Sets the `padding-left` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] } }, @@ -1690,196 +1595,82 @@ "fontFamily": { "description": "Sets the `font-family` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "fontSize": { "description": "Sets the `font-size` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "fontStyle": { "description": "Sets the `font-style` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "fontWeight": { "description": "Sets the `font-weight` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "letterSpacing": { "description": "Sets the `letter-spacing` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "lineHeight": { "description": "Sets the `line-height` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "textAlign": { "description": "Sets the `text-align` CSS property.", - "type": "string" + "oneOf": [ + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } + ] }, "textColumns": { "description": "Sets the `column-count` CSS property.", - "type": "string" + "oneOf": [ + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } + ] }, "textDecoration": { "description": "Sets the `text-decoration` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "writingMode": { "description": "Sets the `writing-mode` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] }, "textTransform": { "description": "Sets the `text-transform` CSS property.", "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } - ] - } - }, - "additionalProperties": false - }, - "filter": { - "description": "CSS and SVG filter styles.", - "type": "object", - "properties": { - "duotone": { - "description": "Sets the duotone filter.", - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } + { "type": "string" }, + { "$ref": "#/definitions/refComplete" } ] } }, "additionalProperties": false - }, - "shadow": { - "description": "Box shadow styles.", - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } - ] - }, - "outline": { - "description": "Outline styles.", - "type": "object", - "properties": { - "color": { - "description": "Sets the `outline-color` CSS property.", - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } - ] - }, - "offset": { - "description": "Sets the `outline-offset` CSS property.", - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } - ] - }, - "style": { - "description": "Sets the `outline-style` CSS property.", - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } - ] - }, - "width": { - "description": "Sets the `outline-width` CSS property.", - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/refComplete" - } - ] - } - }, - "additionalProperties": false - }, - "css": { - "description": "Sets custom CSS to apply styling not covered by other theme.json properties.", - "type": "string" } } }, @@ -1888,75 +1679,82 @@ "background", "border", "color", + "css", "dimensions", - "spacing", - "typography", "filter", - "shadow", "outline", - "css" + "shadow", + "spacing", + "typography" ] }, "stylesPropertiesComplete": { - "type": "object", "allOf": [ { "$ref": "#/definitions/stylesProperties" }, { + "type": "object", "propertyNames": { "$ref": "#/definitions/stylesPropertyNames" } } ] }, + "stylesElementsPseudoSelectorsProperties": { + "type": "object", + "properties": { + ":active": { + "$ref": "#/definitions/stylesPropertiesComplete" + }, + ":any-link": { + "$ref": "#/definitions/stylesPropertiesComplete" + }, + ":focus": { + "$ref": "#/definitions/stylesPropertiesComplete" + }, + ":hover": { + "$ref": "#/definitions/stylesPropertiesComplete" + }, + ":link": { + "$ref": "#/definitions/stylesPropertiesComplete" + }, + ":visited": { + "$ref": "#/definitions/stylesPropertiesComplete" + } + } + }, + "stylesElementsPseudoSelectorsPropertyNames": { + "enum": [ + ":active", + ":any-link", + ":focus", + ":hover", + ":link", + ":visited" + ] + }, "stylesElementsPropertiesComplete": { "description": "Styles defined on a per-element basis using the element's selector.", "type": "object", "properties": { "button": { - "type": "object", "allOf": [ { "$ref": "#/definitions/stylesProperties" }, { - "properties": { - ":hover": { - "$ref": "#/definitions/stylesPropertiesComplete" - }, - ":focus": { - "$ref": "#/definitions/stylesPropertiesComplete" - }, - ":active": { - "$ref": "#/definitions/stylesPropertiesComplete" - }, - ":visited": { - "$ref": "#/definitions/stylesPropertiesComplete" - }, - ":link": { - "$ref": "#/definitions/stylesPropertiesComplete" - }, - ":any-link": { - "$ref": "#/definitions/stylesPropertiesComplete" - } - } + "$ref": "#/definitions/stylesElementsPseudoSelectorsProperties" }, { + "type": "object", "propertyNames": { "anyOf": [ { "$ref": "#/definitions/stylesPropertyNames" }, { - "enum": [ - ":hover", - ":focus", - ":active", - ":visited", - ":link", - ":any-link" - ] + "$ref": "#/definitions/stylesElementsPseudoSelectorsPropertyNames" } ] } @@ -1964,48 +1762,22 @@ ] }, "link": { - "type": "object", "allOf": [ { "$ref": "#/definitions/stylesProperties" }, { - "properties": { - ":hover": { - "$ref": "#/definitions/stylesPropertiesComplete" - }, - ":focus": { - "$ref": "#/definitions/stylesPropertiesComplete" - }, - ":active": { - "$ref": "#/definitions/stylesPropertiesComplete" - }, - ":visited": { - "$ref": "#/definitions/stylesPropertiesComplete" - }, - ":link": { - "$ref": "#/definitions/stylesPropertiesComplete" - }, - ":any-link": { - "$ref": "#/definitions/stylesPropertiesComplete" - } - } + "$ref": "#/definitions/stylesElementsPseudoSelectorsProperties" }, { + "type": "object", "propertyNames": { "anyOf": [ { "$ref": "#/definitions/stylesPropertyNames" }, { - "enum": [ - ":hover", - ":focus", - ":active", - ":visited", - ":link", - ":any-link" - ] + "$ref": "#/definitions/stylesElementsPseudoSelectorsPropertyNames" } ] } @@ -2349,12 +2121,12 @@ "additionalProperties": false }, "stylesPropertiesAndElementsComplete": { - "type": "object", "allOf": [ { "$ref": "#/definitions/stylesProperties" }, { + "type": "object", "properties": { "elements": { "$ref": "#/definitions/stylesElementsPropertiesComplete" @@ -2365,6 +2137,7 @@ } }, { + "type": "object", "propertyNames": { "anyOf": [ { @@ -2387,12 +2160,12 @@ } }, "stylesVariationProperties": { - "type": "object", "allOf": [ { "$ref": "#/definitions/stylesProperties" }, { + "type": "object", "properties": { "elements": { "$ref": "#/definitions/stylesElementsPropertiesComplete" @@ -2403,6 +2176,7 @@ } }, { + "type": "object", "propertyNames": { "anyOf": [ { @@ -2425,12 +2199,12 @@ } }, "stylesVariationPropertiesComplete": { - "type": "object", "allOf": [ { "$ref": "#/definitions/stylesProperties" }, { + "type": "object", "properties": { "elements": { "$ref": "#/definitions/stylesElementsPropertiesComplete" @@ -2441,6 +2215,7 @@ } }, { + "type": "object", "propertyNames": { "anyOf": [ { @@ -2760,12 +2535,12 @@ "additionalProperties": false }, "stylesVariationBlockPropertiesComplete": { - "type": "object", "allOf": [ { "$ref": "#/definitions/stylesProperties" }, { + "type": "object", "properties": { "elements": { "$ref": "#/definitions/stylesElementsPropertiesComplete" @@ -2773,6 +2548,7 @@ } }, { + "type": "object", "propertyNames": { "anyOf": [ { @@ -2799,35 +2575,37 @@ "const": 3 }, "title": { - "type": "string", - "description": "Title of the global styles variation. If not defined, the file name will be used." + "description": "Title of the global styles variation. If not defined, the file name will be used.", + "type": "string" }, "slug": { - "type": "string", - "description": "Slug of the global styles variation. If not defined, the kebab-case title will be used." + "description": "Slug of the global styles variation. If not defined, the kebab-case title will be used.", + "type": "string" }, "description": { - "type": "string", - "description": "Description of the global styles variation." + "description": "Description of the global styles variation.", + "type": "string" }, "blockTypes": { - "type": "array", "description": "List of block types that can use the block style variation this theme.json file represents.", + "type": "array", "items": { "type": "string" } }, "settings": { "description": "Settings for the block editor and individual blocks. These include things like:\n- Which customization options should be available to the user. \n- The default colors, font sizes... available to the user. \n- CSS custom properties and class names used in styles.\n- And the default layout of the editor (widths and available alignments).", - "type": "object", "allOf": [ { "$ref": "#/definitions/settingsProperties" }, { + "type": "object", "properties": { "useRootPaddingAwareAlignments": { - "$ref": "#/definitions/settingsPropertiesUseRootPaddingAwareAlignments/properties/useRootPaddingAwareAlignments" + "description": "Enables root padding (the values from `styles.spacing.padding`) to be applied to the contents of full-width blocks instead of the root block.\n\nPlease note that when using this setting, `styles.spacing.padding` should always be set as an object with `top`, `right`, `bottom`, `left` values declared separately.", + "type": "boolean", + "default": false }, "blocks": { "$ref": "#/definitions/settingsBlocksPropertiesComplete" @@ -2835,6 +2613,7 @@ } }, { + "type": "object", "propertyNames": { "anyOf": [ { @@ -2853,12 +2632,12 @@ }, "styles": { "description": "Organized way to set CSS properties. Styles in the top-level will be added in the `body` selector.", - "type": "object", "allOf": [ { "$ref": "#/definitions/stylesProperties" }, { + "type": "object", "properties": { "elements": { "$ref": "#/definitions/stylesElementsPropertiesComplete" @@ -2872,6 +2651,7 @@ } }, { + "type": "object", "propertyNames": { "anyOf": [ { diff --git a/schemas/json/wp-env.json b/schemas/json/wp-env.json index 689eb5bc58e227..9208ff8e0661f2 100644 --- a/schemas/json/wp-env.json +++ b/schemas/json/wp-env.json @@ -6,10 +6,10 @@ "reference": "https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/" }, "wpEnvProperties": { + "type": "object", "properties": { "core": { "description": "The WordPress installation to use. If null is specified, wp-env will use the latest production release of WordPress.", - "default": null, "oneOf": [ { "type": "string" @@ -17,11 +17,11 @@ { "type": "null" } - ] + ], + "default": null }, "phpVersion": { "description": "The PHP version to use. If null is specified, wp-env will use the default version used with production release of WordPress.", - "default": null, "oneOf": [ { "type": "string" @@ -29,38 +29,39 @@ { "type": "null" } - ] + ], + "default": null }, "plugins": { "description": "A list of plugins to install and activate in the environment.", - "default": [], "type": "array", "items": { "type": "string" - } + }, + "default": [] }, "themes": { "description": "A list of themes to install in the environment.", - "default": [], "type": "array", "items": { "type": "string" - } + }, + "default": [] }, "port": { "description": "The primary port number to use for the installation. You'll access the instance through the port: 'http://localhost:8888'.", - "default": 8888, - "type": "integer" + "type": "integer", + "default": 8888 }, "config": { "description": "Mapping of wp-config.php constants to their desired values.", - "default": {}, - "type": "object" + "type": "object", + "default": {} }, "mappings": { "description": "Mapping of WordPress directories to local directories to be mounted in the WordPress instance.", - "default": {}, - "type": "object" + "type": "object", + "default": {} } } }, @@ -76,7 +77,6 @@ ] } }, - "type": "object", "allOf": [ { "$ref": "#/definitions/wpEnvProperties" @@ -89,7 +89,6 @@ "env": { "description": "The key env is available to override any of the above options on an individual-environment basis.", "type": "object", - "default": {}, "patternProperties": { "[a-zA-Z]": { "type": "object", @@ -102,7 +101,8 @@ } ] } - } + }, + "default": {} } } }, From 4cf4ec3f0d35bf9dabfb8f33c976e3626085e36d Mon Sep 17 00:00:00 2001 From: Alex Lende <alex+github.com@lende.xyz> Date: Tue, 23 Jul 2024 12:18:56 -0500 Subject: [PATCH 0066/1908] JSON Schema Docgen Rework (#63868) Co-authored-by: ajlende <ajlende@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- bin/api-docs/gen-theme-reference.mjs | 422 +++++++++--------- .../theme-json-reference/theme-json-living.md | 312 ++++++------- 2 files changed, 377 insertions(+), 357 deletions(-) diff --git a/bin/api-docs/gen-theme-reference.mjs b/bin/api-docs/gen-theme-reference.mjs index a447948d4593c4..6dc7791e288b9e 100644 --- a/bin/api-docs/gen-theme-reference.mjs +++ b/bin/api-docs/gen-theme-reference.mjs @@ -7,38 +7,31 @@ /** * External dependencies */ -import path from 'path'; -import fs from 'fs'; -import url from 'url'; +import fs from 'node:fs/promises'; import $RefParser from '@apidevtools/json-schema-ref-parser'; -const __dirname = path.dirname( url.fileURLToPath( import.meta.url ) ); - /** - * Path to root project directory. - * - * @type {string} + * @typedef {import('@apidevtools/json-schema-ref-parser').JSONSchema} JSONSchema */ -const ROOT_DIR = path.resolve( __dirname, '../..' ); /** * Path to theme json schema file. * - * @type {string} + * @type {URL} */ -const THEME_JSON_SCHEMA_FILE = path.resolve( - ROOT_DIR, - path.join( 'schemas', 'json', 'theme.json' ) +const THEME_JSON_SCHEMA_URL = new URL( + '../../schemas/json/theme.json', + import.meta.url ); /** * Path to docs file. * - * @type {string} + * @type {URL} */ -const THEME_JSON_REF_DOC = path.resolve( - ROOT_DIR, - 'docs/reference-guides/theme-json-reference/theme-json-living.md' +const REFERENCE_DOC_URL = new URL( + '../../docs/reference-guides/theme-json-reference/theme-json-living.md', + import.meta.url ); /** @@ -56,229 +49,248 @@ const START_TOKEN = '<!-- START TOKEN Autogenerated - DO NOT EDIT -->'; const END_TOKEN = '<!-- END TOKEN Autogenerated - DO NOT EDIT -->'; /** - * Regular expression using tokens for matching in doc file. - * Note: `.` does not match new lines, so [^] is used. - * - * @type {RegExp} + * @typedef {(schema: JSONSchema) => boolean} PredicateFunction */ -const TOKEN_PATTERN = new RegExp( START_TOKEN + '[^]*' + END_TOKEN ); -const themejson = await $RefParser.dereference( THEME_JSON_SCHEMA_FILE ); +/** + * @typedef {(schema: JSONSchema) => string} SerializerFunction + */ /** - * Convert object keys to an array. - * Gracefully handles non-object values. + * Create a serializer function for a type. Supports merging one level of anyOf and oneOf subschemas. * - * @param {*} maybeObject - * @return {Array} Object keys + * @see {@link https://json-schema.org/understanding-json-schema/reference/combining.html} + * + * @param {PredicateFunction} predicate Type predicate function to match a type. + * @param {SerializerFunction} serializer Serializer function to format a type. + * @return {SerializerFunction} Serializer function for the give type. */ -const keys = ( maybeObject ) => { - if ( typeof maybeObject !== 'object' ) { - return []; - } - return Object.keys( maybeObject ); -}; +function createSerializer( predicate, serializer ) { + return ( schema ) => { + const schemas = predicate( schema ) + ? [ schema ] + : schema.anyOf || schema.oneOf || []; + const formatted = schemas.filter( predicate ).map( serializer ); + return [ ...new Set( formatted ) ].join( ', ' ); + }; +} /** - * Convert settings properties to markup. + * Serialize primitive types. * - * @param {Object} struct - * @return {string} markup + * @type {SerializerFunction} */ -const getSettingsPropertiesMarkup = ( struct ) => { - if ( ! ( 'properties' in struct ) ) { - return ''; - } - const props = struct.properties; - const ks = keys( props ); - if ( ks.length < 1 ) { - return ''; - } - - let markup = '| Property | Type | Default | Props |\n'; - markup += '| --- | --- | --- |--- |\n'; - ks.forEach( ( key ) => { - const def = 'default' in props[ key ] ? props[ key ].default : ''; - let type = props[ key ].type || ''; - let ps = - props[ key ].type === 'array' - ? keys( props[ key ].items.properties ).sort().join( ', ' ) - : ''; - - /* - * Handle`oneOf` type definitions - extract the type and properties. - * See: https://json-schema.org/understanding-json-schema/reference/combining#oneOf - */ - if ( props[ key ].oneOf && Array.isArray( props[ key ].oneOf ) ) { - if ( ! type ) { - type = props[ key ].oneOf - .map( ( item ) => item.type ) - .join( ', ' ); - } - - if ( ! ps ) { - ps = props[ key ].oneOf - .map( ( item ) => - item?.type === 'object' && item?.properties - ? '_{' + - keys( item.properties ).sort().join( ', ' ) + - '}_' - : '' - ) - .join( ' ' ); - } - } - - markup += `| ${ key } | ${ type } | ${ def } | ${ ps } |\n`; - } ); - - return markup; -}; +const serializePrimitiveTypes = createSerializer( + ( schema ) => + schema.type && ! [ 'object', 'array' ].includes( schema.type ), + ( schema ) => `\`${ schema.type }\`` +); /** - * Convert style properties to markup. + * Serialize object types. * - * @param {Object} struct - * @return {string} markup + * @type {SerializerFunction} */ -const getStylePropertiesMarkup = ( struct ) => { - if ( ! ( 'properties' in struct ) ) { - return ''; - } - const props = struct.properties; - const ks = keys( props ); - if ( ks.length < 1 ) { - return ''; - } - - let markup = '| Property | Type | Props |\n'; - markup += '| --- | --- |--- |\n'; - ks.forEach( ( key ) => { - const ps = - props[ key ].type === 'object' - ? keys( props[ key ].properties ).sort().join( ', ' ) - : ''; - const type = formatType( props[ key ] ); - markup += `| ${ key } | ${ type } | ${ ps } |\n`; - } ); - - return markup; -}; +const serializeObjectTypes = createSerializer( + ( schema ) => schema.properties, + ( schema ) => `\`{ ${ Object.keys( schema.properties ).join( ', ' ) } }\`` +); /** - * Parses a section for description and properties and - * returns a marked up version. + * Serialize object array types. * - * @param {string} title - * @param {Object} data - * @param {string} type settings|style - * @return {string} markup + * @type {SerializerFunction} */ -const getSectionMarkup = ( title, data, type ) => { - const markupFn = - type === 'settings' - ? getSettingsPropertiesMarkup - : getStylePropertiesMarkup; - - return ` -### ${ title } - -${ data.description } - -${ markupFn( data ) } ---- -`; -}; - -let autogen = ''; +const serializeObjectArrayTypes = createSerializer( + ( schema ) => schema.items && schema.items.properties, + ( schema ) => + `\`[ { ${ Object.keys( schema.items.properties ).join( ', ' ) } } ]\`` +); /** - * Format list of types. + * Serialize primitive array types. * - * @param {Object} prop - * @return {string} type + * @type {SerializerFunction} */ -const formatType = ( prop ) => { - let type = prop.type || ''; +const serializePrimitiveArrayTypes = createSerializer( + ( schema ) => + schema.items && + schema.items.type && + ! [ 'object', 'array' ].includes( schema.items.type ), + ( schema ) => `\`[ ${ schema.items.type } ]\`` +); - if ( prop.hasOwnProperty( 'anyOf' ) || prop.hasOwnProperty( 'oneOf' ) ) { - const propTypes = prop.anyOf || prop.oneOf; - const types = []; +/** + * Generate types from schema. + * + * @param {JSONSchema} schema JSON schema + * @return {string} serialized types + */ +function generateTypes( schema ) { + return [ + serializePrimitiveTypes( schema ), + serializeObjectTypes( schema ), + serializePrimitiveArrayTypes( schema ), + serializeObjectArrayTypes( schema ), + ] + .filter( Boolean ) + .join( ', ' ); +} - propTypes.forEach( ( item ) => { - if ( item.type ) { - types.push( item.type ); +/** + * Generate documentation from theme.json schema. + * + * @param {JSONSchema} themeJson theme.json JSON schema + * @return {string} generated documentation + */ +function generateDocs( themeJson ) { + /** Markdown content. */ + let md = ''; + + /* --------------- * + * Settings * + * --------------- */ + md += '## settings\n\n'; + md += `${ themeJson.properties.settings.description }\n\n`; + const settings = [ + // Top-level only properties. + ...Object.entries( themeJson.properties.settings.allOf[ 1 ].properties ) + .filter( ( [ property ] ) => property !== 'blocks' ) + .map( ( [ property, subschema ] ) => [ + property, + { + ...subschema, + description: `${ subschema.description }\n\n**Note:** Top-level only property. Not available in blocks.`, + }, + ] ), + // Top-level and blocks properties. + ...themeJson.properties.settings.allOf[ 0 ].allOf.flatMap( + ( subschema ) => Object.entries( subschema.properties ) + ), + ]; + for ( const [ section, schema ] of settings ) { + md += `### ${ section }\n\n`; + md += `${ schema.description }\n\n`; + if ( schema.properties ) { + md += '| Property | Description | Type | Default |\n'; + md += '| -------- | ----------- | ---- | ------- |\n'; + const properties = Object.entries( schema.properties ); + for ( const [ property, subschema ] of properties ) { + const description = + subschema.description?.split( '\n', 1 )[ 0 ] ?? ''; + const types = generateTypes( subschema ); + const defaultValue = + 'default' in subschema + ? `\`${ JSON.stringify( subschema.default ) }\`` + : ''; + md += `| ${ property } | ${ description } | ${ types } | ${ defaultValue } |\n`; } - } ); - - type = [ ...new Set( types ) ].join( ', ' ); + md += '\n'; + } + md += `---\n\n`; } - return type; -}; + /* --------------- * + * Styles * + * --------------- */ + md += '## styles\n\n'; + md += `${ themeJson.properties.styles.description }\n\n`; + const styles = Object.entries( + themeJson.properties.styles.allOf[ 0 ].properties + ); + for ( const [ section, schema ] of styles ) { + md += `### ${ section }\n\n`; + md += `${ schema.description }\n\n`; + if ( schema.properties ) { + md += '| Property | Description | Type |\n'; + md += '| -------- | ----------- | ---- |\n'; + const properties = Object.entries( schema.properties ); + for ( const [ property, subschema ] of properties ) { + // Assuming that the first line of a description is a summary. + const description = + subschema.description?.split( '\n', 1 )[ 0 ] ?? ''; + const types = generateTypes( subschema ); + md += `| ${ property } | ${ description } | ${ types } |\n`; + } + md += '\n'; + } + md += `---\n\n`; + } -// Settings -const settings = Object.entries( themejson.definitions ) - .filter( ( [ settingsKey ] ) => - /^settings\w+Properties$/.test( settingsKey ) - ) - .reduce( - ( settingsObj, [ , { properties } ] ) => - Object.assign( settingsObj, properties ), - {} + /* --------------- * + * customTemplates * + * --------------- */ + md += '## customTemplates\n\n'; + md += `${ themeJson.properties.customTemplates.description }\n\n`; + md += '| Property | Description | Type |\n'; + md += '| -------- | ----------- | ---- |\n'; + const customTemplatesProperties = Object.entries( + themeJson.properties.customTemplates.items.properties ); -const settingSections = keys( settings ); -autogen += '## Settings' + '\n\n'; -settingSections.forEach( ( section ) => { - autogen += getSectionMarkup( section, settings[ section ], 'settings' ); -} ); + for ( const [ property, subschema ] of customTemplatesProperties ) { + const { description } = subschema; + const types = generateTypes( subschema ); + md += `| ${ property } | ${ description } | ${ types } |\n`; + } + md += '\n'; + + /* --------------- * + * templateParts * + * --------------- */ + md += '## templateParts\n\n'; + md += `${ themeJson.properties.templateParts.description }\n\n`; + md += '| Property | Description | Type |\n'; + md += '| -------- | ----------- | ---- |\n'; + const templatePartsProperties = Object.entries( + themeJson.properties.templateParts.items.properties + ); + for ( const [ property, subschema ] of templatePartsProperties ) { + const { description } = subschema; + const types = generateTypes( subschema ); + md += `| ${ property } | ${ description } | ${ types } |\n`; + } + md += '\n'; -// Styles -const styles = themejson.definitions.stylesProperties.properties; -const styleSections = keys( styles ); -autogen += '## Styles' + '\n\n'; -styleSections.forEach( ( section ) => { - autogen += getSectionMarkup( section, styles[ section ], 'styles' ); -} ); + /* --------------- * + * patterns * + * --------------- */ + md += '## patterns\n\n'; + md += themeJson.properties.patterns.description + '\n\n'; + md += `Type: ${ generateTypes( themeJson.properties.patterns ) }.\n`; -const templateTableGeneration = ( themeJson, context ) => { - let content = ''; - content += '## ' + context + '\n\n'; - content += themeJson.properties[ context ].description + '\n\n'; - content += - 'Type: `' + themeJson.properties[ context ].items.type + '`.\n\n'; - content += '| Property | Description | Type |\n'; - content += '| --- | --- | --- |\n'; - keys( themeJson.properties[ context ].items.properties ).forEach( - ( key ) => { - content += `| ${ key } | ${ themeJson.properties[ context ].items.properties[ key ].description } | ${ themeJson.properties[ context ].items.properties[ key ].type } |\n`; + return md; +} + +/** + * Main function. + */ +async function main() { + const themeJson = await $RefParser.dereference( + THEME_JSON_SCHEMA_URL.pathname, + { + parse: { binary: false, text: false, yaml: false }, + resolve: { external: false }, } ); - content += '\n\n'; - - return content; -}; -// customTemplates -autogen += templateTableGeneration( themejson, 'customTemplates' ); + const themeJsonReference = await fs.readFile( REFERENCE_DOC_URL, { + encoding: 'utf8', + flag: 'r', + } ); -// templateParts -autogen += templateTableGeneration( themejson, 'templateParts' ); + const generatedDocs = generateDocs( themeJson ); + const updatedThemeJsonReference = themeJsonReference.replace( + // `.` does not match new lines, but `[^]` will. + new RegExp( `${ START_TOKEN }[^]*${ END_TOKEN }` ), + `${ START_TOKEN }\n${ generatedDocs }\n${ END_TOKEN }` + ); -// Patterns -autogen += '## Patterns' + '\n\n'; -autogen += themejson.properties.patterns.description + '\n'; -autogen += 'Type: `' + themejson.properties.patterns.type + '`.\n\n'; + await fs.writeFile( REFERENCE_DOC_URL, updatedThemeJsonReference, { + encoding: 'utf8', + } ); +} -// Read existing file to wrap auto generated content. -let docsContent = fs.readFileSync( THEME_JSON_REF_DOC, { - encoding: 'utf8', - flag: 'r', +main().catch( ( error ) => { + console.error( error ); + process.exit( 1 ); } ); - -// Replace auto generated part with new generated docs. -autogen = START_TOKEN + '\n' + autogen + '\n' + END_TOKEN; -docsContent = docsContent.replace( TOKEN_PATTERN, autogen ); - -// Write back out. -fs.writeFileSync( THEME_JSON_REF_DOC, docsContent, { encoding: 'utf8' } ); diff --git a/docs/reference-guides/theme-json-reference/theme-json-living.md b/docs/reference-guides/theme-json-reference/theme-json-living.md index 0b9e3e9d187766..95f2e047dd0e31 100644 --- a/docs/reference-guides/theme-json-reference/theme-json-living.md +++ b/docs/reference-guides/theme-json-reference/theme-json-living.md @@ -21,8 +21,23 @@ For example, a schema for WordPress 5.8 is available at <code>https://schemas.wp See [Developing with theme.json](/docs/how-to-guides/themes/global-settings-and-styles.md#developing-with-themejson) for how to use the JSON schema in your editor. <!-- START TOKEN Autogenerated - DO NOT EDIT --> -## Settings +## settings +Settings for the block editor and individual blocks. These include things like: +- Which customization options should be available to the user. +- The default colors, font sizes... available to the user. +- CSS custom properties and class names used in styles. +- And the default layout of the editor (widths and available alignments). + +### useRootPaddingAwareAlignments + +Enables root padding (the values from `styles.spacing.padding`) to be applied to the contents of full-width blocks instead of the root block. + +Please note that when using this setting, `styles.spacing.padding` should always be set as an object with `top`, `right`, `bottom`, `left` values declared separately. + +**Note:** Top-level only property. Not available in blocks. + +--- ### appearanceTools @@ -36,17 +51,16 @@ Setting that enables the following UI tools: - spacing: blockGap, margin, padding - typography: lineHeight - --- ### background Settings related to background. -| Property | Type | Default | Props | -| --- | --- | --- |--- | -| backgroundImage | boolean | false | | -| backgroundSize | boolean | false | | +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| backgroundImage | Allow users to set a background image. | `boolean` | `false` | +| backgroundSize | Allow users to set values related to the size of a background image, including size, position, and repeat controls. | `boolean` | `false` | --- @@ -54,12 +68,12 @@ Settings related to background. Settings related to borders. -| Property | Type | Default | Props | -| --- | --- | --- |--- | -| color | boolean | false | | -| radius | boolean | false | | -| style | boolean | false | | -| width | boolean | false | | +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| color | Allow users to set custom border colors. | `boolean` | `false` | +| radius | Allow users to set custom border radius. | `boolean` | `false` | +| style | Allow users to set custom border styles. | `boolean` | `false` | +| width | Allow users to set custom border widths. | `boolean` | `false` | --- @@ -67,23 +81,23 @@ Settings related to borders. Settings related to colors. -| Property | Type | Default | Props | -| --- | --- | --- |--- | -| background | boolean | true | | -| custom | boolean | true | | -| customDuotone | boolean | true | | -| customGradient | boolean | true | | -| defaultDuotone | boolean | true | | -| defaultGradients | boolean | true | | -| defaultPalette | boolean | true | | -| duotone | array | | colors, name, slug | -| gradients | array | | gradient, name, slug | -| link | boolean | false | | -| palette | array | | color, name, slug | -| text | boolean | true | | -| heading | boolean | true | | -| button | boolean | true | | -| caption | boolean | true | | +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| background | Allow users to set background colors. | `boolean` | `true` | +| custom | Allow users to select custom colors. | `boolean` | `true` | +| customDuotone | Allow users to create custom duotone filters. | `boolean` | `true` | +| customGradient | Allow users to create custom gradients. | `boolean` | `true` | +| defaultDuotone | Allow users to choose filters from the default duotone filter presets. | `boolean` | `true` | +| defaultGradients | Allow users to choose colors from the default gradients. | `boolean` | `true` | +| defaultPalette | Allow users to choose colors from the default palette. | `boolean` | `true` | +| duotone | Duotone presets for the duotone picker. | `[ { name, slug, colors } ]` | | +| gradients | Gradient presets for the gradient picker. | `[ { name, slug, gradient } ]` | | +| link | Allow users to set link colors in a block. | `boolean` | `false` | +| palette | Color palette presets for the color picker. | `[ { name, slug, color } ]` | | +| text | Allow users to set text colors in a block. | `boolean` | `true` | +| heading | Allow users to set heading colors in a block. | `boolean` | `true` | +| button | Allow users to set button colors in a block. | `boolean` | `true` | +| caption | Allow users to set caption colors in a block. | `boolean` | `true` | --- @@ -91,12 +105,12 @@ Settings related to colors. Settings related to dimensions. -| Property | Type | Default | Props | -| --- | --- | --- |--- | -| aspectRatio | boolean | false | | -| defaultAspectRatios | boolean | true | | -| aspectRatios | array | | name, ratio, slug | -| minHeight | boolean | false | | +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| aspectRatio | Allow users to set an aspect ratio. | `boolean` | `false` | +| defaultAspectRatios | Allow users to choose aspect ratios from the default set of aspect ratios. | `boolean` | `true` | +| aspectRatios | Allow users to define aspect ratios for some blocks. | `[ { name, slug, ratio } ]` | | +| minHeight | Allow users to set custom minimum height. | `boolean` | `false` | --- @@ -104,12 +118,12 @@ Settings related to dimensions. Settings related to layout. -| Property | Type | Default | Props | -| --- | --- | --- |--- | -| contentSize | string | | | -| wideSize | string | | | -| allowEditing | boolean | true | | -| allowCustomContentAndWideSize | boolean | true | | +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| contentSize | Sets the max-width of the content. | `string` | | +| wideSize | Sets the max-width of wide (`.alignwide`) content. Also used as the maximum viewport when calculating fluid font sizes | `string` | | +| allowEditing | Disable the layout UI controls. | `boolean` | `true` | +| allowCustomContentAndWideSize | Enable or disable the custom content and wide size controls. | `boolean` | `true` | --- @@ -117,10 +131,10 @@ Settings related to layout. Settings related to the lightbox. -| Property | Type | Default | Props | -| --- | --- | --- |--- | -| enabled | boolean | | | -| allowEditing | boolean | | | +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| enabled | Defines whether the lightbox is enabled or not. | `boolean` | | +| allowEditing | Defines whether to show the Lightbox UI in the block editor. If set to `false`, the user won't be able to change the lightbox settings in the block editor. | `boolean` | | --- @@ -128,9 +142,9 @@ Settings related to the lightbox. Settings related to position. -| Property | Type | Default | Props | -| --- | --- | --- |--- | -| sticky | boolean | false | | +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| sticky | Allow users to set sticky position. | `boolean` | `false` | --- @@ -138,10 +152,10 @@ Settings related to position. Settings related to shadows. -| Property | Type | Default | Props | -| --- | --- | --- |--- | -| defaultPresets | boolean | true | | -| presets | array | | name, shadow, slug | +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| defaultPresets | Allow users to choose shadows from the default shadow presets. | `boolean` | `true` | +| presets | Shadow presets for the shadow picker. | `[ { name, slug, shadow } ]` | | --- @@ -149,16 +163,16 @@ Settings related to shadows. Settings related to spacing. -| Property | Type | Default | Props | -| --- | --- | --- |--- | -| blockGap | boolean, null | null | | -| margin | boolean | false | | -| padding | boolean | false | | -| units | array | px,em,rem,vh,vw,% | | -| customSpacingSize | boolean | true | | -| defaultSpacingSizes | boolean | true | | -| spacingSizes | array | | name, size, slug | -| spacingScale | object | | | +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| blockGap | Enables `--wp--style--block-gap` to be generated from styles.spacing.blockGap. | `boolean`, `null` | `null` | +| margin | Allow users to set a custom margin. | `boolean` | `false` | +| padding | Allow users to set a custom padding. | `boolean` | `false` | +| units | List of units the user can use for spacing values. | `[ string ]` | `["px","em","rem","vh","vw","%"]` | +| customSpacingSize | Allow users to set custom space sizes. | `boolean` | `true` | +| defaultSpacingSizes | Allow users to choose space sizes from the default space size presets. | `boolean` | `true` | +| spacingSizes | Space size presets for the space size selector. | `[ { name, slug, size } ]` | | +| spacingScale | Settings to auto-generate space size presets for the space size selector. | `{ operator, increment, steps, mediumStep, unit }` | | --- @@ -166,23 +180,23 @@ Settings related to spacing. Settings related to typography. -| Property | Type | Default | Props | -| --- | --- | --- |--- | -| defaultFontSizes | boolean | true | | -| customFontSize | boolean | true | | -| fontStyle | boolean | true | | -| fontWeight | boolean | true | | -| fluid | object, boolean | false | _{maxViewportWidth, minFontSize, minViewportWidth}_ | -| letterSpacing | boolean | true | | -| lineHeight | boolean | false | | -| textAlign | boolean | true | | -| textColumns | boolean | false | | -| textDecoration | boolean | true | | -| writingMode | boolean | false | | -| textTransform | boolean | true | | -| dropCap | boolean | true | | -| fontSizes | array | | fluid, name, size, slug | -| fontFamilies | array | | fontFace, fontFamily, name, slug | +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| defaultFontSizes | Allow users to choose font sizes from the default font size presets. | `boolean` | `true` | +| customFontSize | Allow users to set custom font sizes. | `boolean` | `true` | +| fontStyle | Allow users to set custom font styles. | `boolean` | `true` | +| fontWeight | Allow users to set custom font weights. | `boolean` | `true` | +| fluid | Enables fluid typography and allows users to set global fluid typography parameters. | `boolean`, `{ minFontSize, maxViewportWidth, minViewportWidth }` | `false` | +| letterSpacing | Allow users to set custom letter spacing. | `boolean` | `true` | +| lineHeight | Allow users to set custom line height. | `boolean` | `false` | +| textAlign | Allow users to set the text align. | `boolean` | `true` | +| textColumns | Allow users to set the number of text columns. | `boolean` | `false` | +| textDecoration | Allow users to set custom text decorations. | `boolean` | `true` | +| writingMode | Allow users to set the writing mode. | `boolean` | `false` | +| textTransform | Allow users to set custom text transforms. | `boolean` | `true` | +| dropCap | Enable drop cap. | `boolean` | `true` | +| fontSizes | Font size presets for the font size selector. | `[ { name, slug, size, fluid } ]` | | +| fontFamilies | Font family presets for the font family selector. | `[ { name, slug, fontFamily, fontFace } ]` | | --- @@ -190,22 +204,23 @@ Settings related to typography. Generate custom CSS custom properties of the form `--wp--custom--{key}--{nested-key}: {value};`. `camelCased` keys are transformed to `kebab-case` as to follow the CSS property naming schema. Keys at different depth levels are separated by `--`, so keys should not include `--` in the name. - --- -## Styles +## styles + +Organized way to set CSS properties. Styles in the top-level will be added in the `body` selector. ### background Background styles. -| Property | Type | Props | -| --- | --- |--- | -| backgroundImage | string, object | | -| backgroundPosition | string, object | | -| backgroundRepeat | string, object | | -| backgroundSize | string, object | | -| backgroundAttachment | string, object | | +| Property | Description | Type | +| -------- | ----------- | ---- | +| backgroundImage | Sets the `background-image` CSS property. | `string`, `{ ref }`, `{ url }` | +| backgroundPosition | Sets the `background-position` CSS property. | `string`, `{ ref }` | +| backgroundRepeat | Sets the `background-repeat` CSS property. | `string`, `{ ref }` | +| backgroundSize | Sets the `background-size` CSS property. | `string`, `{ ref }` | +| backgroundAttachment | Sets the `background-attachment` CSS property. | `string`, `{ ref }` | --- @@ -213,16 +228,16 @@ Background styles. Border styles. -| Property | Type | Props | -| --- | --- |--- | -| color | string, object | | -| radius | string, object | | -| style | string, object | | -| width | string, object | | -| top | object | color, style, width | -| right | object | color, style, width | -| bottom | object | color, style, width | -| left | object | color, style, width | +| Property | Description | Type | +| -------- | ----------- | ---- | +| color | Sets the `border-color` CSS property. | `string`, `{ ref }` | +| radius | Sets the `border-radius` CSS property. | `string`, `{ ref }`, `{ topLeft, topRight, bottomLeft, bottomRight }` | +| style | Sets the `border-style` CSS property. | `string`, `{ ref }` | +| width | Sets the `border-width` CSS property. | `string`, `{ ref }` | +| top | | `{ color, style, width }` | +| right | | `{ color, style, width }` | +| bottom | | `{ color, style, width }` | +| left | | `{ color, style, width }` | --- @@ -230,11 +245,11 @@ Border styles. Color styles. -| Property | Type | Props | -| --- | --- |--- | -| background | string, object | | -| gradient | string, object | | -| text | string, object | | +| Property | Description | Type | +| -------- | ----------- | ---- | +| background | Sets the `background-color` CSS property. | `string`, `{ ref }` | +| gradient | Sets the `background` CSS property. | `string`, `{ ref }` | +| text | Sets the `color` CSS property. | `string`, `{ ref }` | --- @@ -242,17 +257,16 @@ Color styles. Sets custom CSS to apply styling not covered by other theme.json properties. - --- ### dimensions Dimensions styles. -| Property | Type | Props | -| --- | --- |--- | -| aspectRatio | string, object | | -| minHeight | string, object | | +| Property | Description | Type | +| -------- | ----------- | ---- | +| aspectRatio | Sets the `aspect-ratio` CSS property. | `string`, `{ ref }` | +| minHeight | Sets the `min-height` CSS property. | `string`, `{ ref }` | --- @@ -260,9 +274,9 @@ Dimensions styles. CSS and SVG filter styles. -| Property | Type | Props | -| --- | --- |--- | -| duotone | string, object | | +| Property | Description | Type | +| -------- | ----------- | ---- | +| duotone | Sets the duotone filter. | `string`, `{ ref }` | --- @@ -270,12 +284,12 @@ CSS and SVG filter styles. Outline styles. -| Property | Type | Props | -| --- | --- |--- | -| color | string, object | | -| offset | string, object | | -| style | string, object | | -| width | string, object | | +| Property | Description | Type | +| -------- | ----------- | ---- | +| color | Sets the `outline-color` CSS property. | `string`, `{ ref }` | +| offset | Sets the `outline-offset` CSS property. | `string`, `{ ref }` | +| style | Sets the `outline-style` CSS property. | `string`, `{ ref }` | +| width | Sets the `outline-width` CSS property. | `string`, `{ ref }` | --- @@ -283,18 +297,17 @@ Outline styles. Box shadow styles. - --- ### spacing Spacing styles. -| Property | Type | Props | -| --- | --- |--- | -| blockGap | string, object | | -| margin | object | bottom, left, right, top | -| padding | object | bottom, left, right, top | +| Property | Description | Type | +| -------- | ----------- | ---- | +| blockGap | Sets the `--wp--style--block-gap` CSS custom property when settings.spacing.blockGap is true. | `string`, `{ ref }` | +| margin | Margin styles. | `{ top, right, bottom, left }` | +| padding | Padding styles. | `{ top, right, bottom, left }` | --- @@ -302,51 +315,46 @@ Spacing styles. Typography styles. -| Property | Type | Props | -| --- | --- |--- | -| fontFamily | string, object | | -| fontSize | string, object | | -| fontStyle | string, object | | -| fontWeight | string, object | | -| letterSpacing | string, object | | -| lineHeight | string, object | | -| textAlign | string, object | | -| textColumns | string, object | | -| textDecoration | string, object | | -| writingMode | string, object | | -| textTransform | string, object | | +| Property | Description | Type | +| -------- | ----------- | ---- | +| fontFamily | Sets the `font-family` CSS property. | `string`, `{ ref }` | +| fontSize | Sets the `font-size` CSS property. | `string`, `{ ref }` | +| fontStyle | Sets the `font-style` CSS property. | `string`, `{ ref }` | +| fontWeight | Sets the `font-weight` CSS property. | `string`, `{ ref }` | +| letterSpacing | Sets the `letter-spacing` CSS property. | `string`, `{ ref }` | +| lineHeight | Sets the `line-height` CSS property. | `string`, `{ ref }` | +| textAlign | Sets the `text-align` CSS property. | `string`, `{ ref }` | +| textColumns | Sets the `column-count` CSS property. | `string`, `{ ref }` | +| textDecoration | Sets the `text-decoration` CSS property. | `string`, `{ ref }` | +| writingMode | Sets the `writing-mode` CSS property. | `string`, `{ ref }` | +| textTransform | Sets the `text-transform` CSS property. | `string`, `{ ref }` | --- + ## customTemplates Additional metadata for custom templates defined in the templates folder. -Type: `object`. - | Property | Description | Type | -| --- | --- | --- | -| name | Filename, without extension, of the template in the templates folder. | string | -| title | Title of the template, translatable. | string | -| postTypes | List of post types that can use this custom template. | array | - +| -------- | ----------- | ---- | +| name | Filename, without extension, of the template in the templates folder. | `string` | +| title | Title of the template, translatable. | `string` | +| postTypes | List of post types that can use this custom template. | `[ string ]` | ## templateParts Additional metadata for template parts defined in the parts folder. -Type: `object`. - | Property | Description | Type | -| --- | --- | --- | -| name | Filename, without extension, of the template in the parts folder. | string | -| title | Title of the template, translatable. | string | -| area | The area the template part is used for. Block variations for `header` and `footer` values exist and will be used when the area is set to one of those. | string | - +| -------- | ----------- | ---- | +| name | Filename, without extension, of the template in the parts folder. | `string` | +| title | Title of the template, translatable. | `string` | +| area | The area the template part is used for. Block variations for `header` and `footer` values exist and will be used when the area is set to one of those. | `string` | -## Patterns +## patterns An array of pattern slugs to be registered from the Pattern Directory. -Type: `array`. +Type: `[ string ]`. <!-- END TOKEN Autogenerated - DO NOT EDIT --> From 626816ab7a4337c4a6679fb8e678baa9b0b10e07 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 24 Jul 2024 03:17:41 +0900 Subject: [PATCH 0067/1908] Add margin-bottom lint rules for RangeControl (#63821) * Add margin-bottom lint rules for RangeControl * Update docs Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .eslintrc.js | 1 + packages/block-editor/src/layouts/grid.js | 2 ++ packages/block-library/src/post-excerpt/edit.js | 1 + .../block-library/src/query-pagination-numbers/edit.js | 1 + packages/components/src/range-control/README.md | 8 ++++++++ packages/components/src/range-control/index.tsx | 1 + 6 files changed, 14 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index 4385f528f44dbb..01f6967e8fe947 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -293,6 +293,7 @@ module.exports = { 'CheckboxControl', 'ComboboxControl', 'FocalPointPicker', + 'RangeControl', 'SearchControl', 'TextareaControl', 'TreeSelect', diff --git a/packages/block-editor/src/layouts/grid.js b/packages/block-editor/src/layouts/grid.js index 975b79f4ba570e..395d0ca1e9d833 100644 --- a/packages/block-editor/src/layouts/grid.js +++ b/packages/block-editor/src/layouts/grid.js @@ -264,6 +264,7 @@ function GridLayoutMinimumWidthControl( { layout, onChange } ) { </FlexItem> <FlexItem isBlock> <RangeControl + __nextHasNoMarginBottom onChange={ handleSliderChange } value={ quantity || 0 } min={ 0 } @@ -367,6 +368,7 @@ function GridLayoutColumnsAndRowsControl( { /> ) : ( <RangeControl + __nextHasNoMarginBottom value={ columnCount ?? 0 } onChange={ ( value ) => onChange( { diff --git a/packages/block-library/src/post-excerpt/edit.js b/packages/block-library/src/post-excerpt/edit.js index 702219e06a9694..45d0a79a411d61 100644 --- a/packages/block-library/src/post-excerpt/edit.js +++ b/packages/block-library/src/post-excerpt/edit.js @@ -231,6 +231,7 @@ export default function PostExcerptEditor( { } /> <RangeControl + __nextHasNoMarginBottom label={ __( 'Max number of words' ) } value={ excerptLength } onChange={ ( value ) => { diff --git a/packages/block-library/src/query-pagination-numbers/edit.js b/packages/block-library/src/query-pagination-numbers/edit.js index eb83204b2cca2b..e495fe8529a07a 100644 --- a/packages/block-library/src/query-pagination-numbers/edit.js +++ b/packages/block-library/src/query-pagination-numbers/edit.js @@ -51,6 +51,7 @@ export default function QueryPaginationNumbersEdit( { <InspectorControls> <PanelBody title={ __( 'Settings' ) }> <RangeControl + __nextHasNoMarginBottom label={ __( 'Number of links' ) } help={ __( 'Specify how many links can appear before and after the current page number. Links to the first, current and last page are always visible.' diff --git a/packages/components/src/range-control/README.md b/packages/components/src/range-control/README.md index 1a0f1e6adef95a..3da335b9ecf6e8 100644 --- a/packages/components/src/range-control/README.md +++ b/packages/components/src/range-control/README.md @@ -90,6 +90,7 @@ const MyRangeControl = () => { return( <RangeControl + __nextHasNoMarginBottom label="Columns" value={ columns } onChange={ ( value ) => setColumns( value ) } @@ -361,6 +362,13 @@ Determines if the `input` number field will render next to the RangeControl. Thi - Required: No - Platform: Web +### `__nextHasNoMarginBottom`: `boolean` + +Start opting into the new margin-free styles that will become the default in a future version. + +- Required: No +- Default: `false` + ## Related components - To collect a numerical input in a text field, use the `TextControl` component. diff --git a/packages/components/src/range-control/index.tsx b/packages/components/src/range-control/index.tsx index b5fff9f56b80d7..5b4ecfa585679b 100644 --- a/packages/components/src/range-control/index.tsx +++ b/packages/components/src/range-control/index.tsx @@ -353,6 +353,7 @@ function UnforwardedRangeControl( * const [ isChecked, setChecked ] = useState( true ); * return ( * <RangeControl + * __nextHasNoMarginBottom * help="Please select how transparent you would like this." * initialPosition={50} * label="Opacity" From 40140e41dfc89185f23da6da7ce9d2343231d5bd Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 24 Jul 2024 03:24:02 +0900 Subject: [PATCH 0068/1908] SelectControl: Fix hover/focus color in wp-admin (#63855) * SelectControl: Fix hover/focus color in wp-admin * Add changelog * Update snapshot test Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../dimension-control/test/__snapshots__/index.test.js.snap | 4 ++++ .../src/select-control/styles/select-control-styles.ts | 1 + 3 files changed, 6 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index f6ac03e45d8138..aa11a7c90e2632 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -10,6 +10,7 @@ - `ComboboxControl`: Fix ComboboxControl reset button when using the keyboard. ([#63410](https://github.com/WordPress/gutenberg/pull/63410)) - `Button`: Never apply `aria-disabled` to anchor ([#63376](https://github.com/WordPress/gutenberg/pull/63376)). +- `SelectControl`: Fix hover/focus color in wp-admin ([#63855](https://github.com/WordPress/gutenberg/pull/63855)). ### Enhancements diff --git a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap index 1d3cd12a2aa316..5990fbbd4a3f5f 100644 --- a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap +++ b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap @@ -120,6 +120,7 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = ` box-sizing: border-box; border: none; box-shadow: none!important; + color: currentColor; cursor: inherit; display: block; font-family: inherit; @@ -405,6 +406,7 @@ exports[`DimensionControl rendering renders with defaults 1`] = ` box-sizing: border-box; border: none; box-shadow: none!important; + color: currentColor; cursor: inherit; display: block; font-family: inherit; @@ -700,6 +702,7 @@ exports[`DimensionControl rendering renders with icon and custom icon label 1`] box-sizing: border-box; border: none; box-shadow: none!important; + color: currentColor; cursor: inherit; display: block; font-family: inherit; @@ -1007,6 +1010,7 @@ exports[`DimensionControl rendering renders with icon and default icon label 1`] box-sizing: border-box; border: none; box-shadow: none!important; + color: currentColor; cursor: inherit; display: block; font-family: inherit; diff --git a/packages/components/src/select-control/styles/select-control-styles.ts b/packages/components/src/select-control/styles/select-control-styles.ts index 989c5fa62ecff7..780334c67e85e6 100644 --- a/packages/components/src/select-control/styles/select-control-styles.ts +++ b/packages/components/src/select-control/styles/select-control-styles.ts @@ -158,6 +158,7 @@ export const Select = styled.select< SelectProps >` box-sizing: border-box; border: none; box-shadow: none !important; + color: currentColor; // Overrides hover/focus styles in forms.css cursor: inherit; display: block; font-family: inherit; From db4bad4a2d6af15aa384f0f178eeb399921aea6c Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 24 Jul 2024 03:44:02 +0900 Subject: [PATCH 0069/1908] Update "Versions in WordPress" page (#63869) --- docs/contributors/versions-in-wordpress.md | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/docs/contributors/versions-in-wordpress.md b/docs/contributors/versions-in-wordpress.md index f95dbf479f3cb1..8c4debb8b696f6 100644 --- a/docs/contributors/versions-in-wordpress.md +++ b/docs/contributors/versions-in-wordpress.md @@ -6,23 +6,43 @@ If anything looks incorrect here, please bring it up in #core-editor in [WordPre | Gutenberg Versions | WordPress Version | | ------------------ | ----------------- | +| 17.8-18.5 | 6.6.1 | +| 17.8-18.5 | 6.6 | +| 16.8-17.7 | 6.5.5 | +| 16.8-17.7 | 6.5.4 | +| 16.8-17.7 | 6.5.3 | +| 16.8-17.7 | 6.5.2 | | 16.8-17.7 | 6.5 | +| 16.2-16.7 | 6.4.4 | +| 16.2-16.7 | 6.4.5 | | 16.2-16.7 | 6.4.3 | | 16.2-16.7 | 6.4.2 | | 16.2-16.7 | 6.4.1 | | 16.2-16.7 | 6.4 | +| 15.2-16.1 | 6.3.5 | +| 15.2-16.1 | 6.3.4 | +| 15.2-16.1 | 6.3.3 | | 15.2-16.1 | 6.3.2 | | 15.2-16.1 | 6.3.1 | | 15.2-16.1 | 6.3 | +| 14.2-15.1 | 6.2.6 | +| 14.2-15.1 | 6.2.5 | +| 14.2-15.1 | 6.2.4 | | 14.2-15.1 | 6.2.3 | | 14.2-15.1 | 6.2.2 | | 14.2-15.1 | 6.2.1 | | 14.2-15.1 | 6.2 | +| 13.1-14.1 | 6.1.7 | +| 13.1-14.1 | 6.1.6 | +| 13.1-14.1 | 6.1.5 | | 13.1-14.1 | 6.1.4 | | 13.1-14.1 | 6.1.3 | | 13.1-14.1 | 6.1.2 | | 13.1-14.1 | 6.1.1 | | 13.1-14.1 | 6.1 | +| 12.0-13.0 | 6.0.9 | +| 12.0-13.0 | 6.0.8 | +| 12.0-13.0 | 6.0.7 | | 12.0-13.0 | 6.0.6 | | 12.0-13.0 | 6.0.5 | | 12.0-13.0 | 6.0.4 | @@ -30,6 +50,8 @@ If anything looks incorrect here, please bring it up in #core-editor in [WordPre | 12.0-13.0 | 6.0.2 | | 12.0-13.0 | 6.0.1 | | 12.0-13.0 | 6.0 | +| 10.8-11.9 | 5.9.10 | +| 10.8-11.9 | 5.9.9 | | 10.8-11.9 | 5.9.8 | | 10.8-11.9 | 5.9.7 | | 10.8-11.9 | 5.9.6 | @@ -39,6 +61,8 @@ If anything looks incorrect here, please bring it up in #core-editor in [WordPre | 10.8-11.9 | 5.9.2 | | 10.8-11.9 | 5.9.1 | | 10.8-11.9 | 5.9 | +| 10.0-10.7 | 5.8.10 | +| 10.0-10.7 | 5.8.9 | | 10.0-10.7 | 5.8.8 | | 10.0-10.7 | 5.8.7 | | 10.0-10.7 | 5.8.6 | @@ -48,6 +72,8 @@ If anything looks incorrect here, please bring it up in #core-editor in [WordPre | 10.0-10.7 | 5.8.2 | | 10.0-10.7 | 5.8.1 | | 10.0-10.7 | 5.8 | +| 9.3-9.9 | 5.7.12 | +| 9.3-9.9 | 5.7.11 | | 9.3-9.9 | 5.7.10 | | 9.3-9.9 | 5.7.9 | | 9.3-9.9 | 5.7.8 | @@ -59,6 +85,8 @@ If anything looks incorrect here, please bring it up in #core-editor in [WordPre | 9.3-9.9 | 5.7.2 | | 9.3-9.9 | 5.7.1 | | 9.3-9.9 | 5.7 | +| 8.6-9.2 | 5.6.14 | +| 8.6-9.2 | 5.6.13 | | 8.6-9.2 | 5.6.12 | | 8.6-9.2 | 5.6.11 | | 8.6-9.2 | 5.6.10 | @@ -72,6 +100,8 @@ If anything looks incorrect here, please bring it up in #core-editor in [WordPre | 8.6-9.2 | 5.6.2 | | 8.6-9.2 | 5.6.1 | | 8.6-9.2 | 5.6 | +| 7.6-8.5 | 5.5.15 | +| 7.6-8.5 | 5.5.14 | | 7.6-8.5 | 5.5.13 | | 7.6-8.5 | 5.5.12 | | 7.6-8.5 | 5.5.11 | @@ -86,6 +116,8 @@ If anything looks incorrect here, please bring it up in #core-editor in [WordPre | 7.6-8.5 | 5.5.2 | | 7.6-8.5 | 5.5.1 | | 7.6-8.5 | 5.5 | +| 6.6-7.5 | 5.4.16 | +| 6.6-7.5 | 5.4.15 | | 6.6-7.5 | 5.4.14 | | 6.6-7.5 | 5.4.13 | | 6.6-7.5 | 5.4.12 | @@ -101,6 +133,8 @@ If anything looks incorrect here, please bring it up in #core-editor in [WordPre | 6.6-7.5 | 5.4.2 | | 6.6-7.5 | 5.4.1 | | 6.6-7.5 | 5.4 | +| 5.5-6.5 | 5.3.18 | +| 5.5-6.5 | 5.3.17 | | 5.5-6.5 | 5.3.16 | | 5.5-6.5 | 5.3.15 | | 5.5-6.5 | 5.3.14 | @@ -118,6 +152,8 @@ If anything looks incorrect here, please bring it up in #core-editor in [WordPre | 5.5-6.5 | 5.3.2 | | 5.5-6.5 | 5.3.1 | | 5.5-6.5 | 5.3 | +| 4.9-5.4 | 5.2.21 | +| 4.9-5.4 | 5.2.20 | | 4.9-5.4 | 5.2.19 | | 4.9-5.4 | 5.2.18 | | 4.9-5.4 | 5.2.17 | @@ -138,6 +174,8 @@ If anything looks incorrect here, please bring it up in #core-editor in [WordPre | 4.9-5.4 | 5.2.2 | | 4.9-5.4 | 5.2.1 | | 4.9-5.4 | 5.2 | +| 4.8 | 5.1.19 | +| 4.8 | 5.1.18 | | 4.8 | 5.1.17 | | 4.8 | 5.1.16 | | 4.8 | 5.1.15 | @@ -156,6 +194,8 @@ If anything looks incorrect here, please bring it up in #core-editor in [WordPre | 4.8 | 5.1.2 | | 4.8 | 5.1.1 | | 4.8 | 5.1 | +| 4.7.1 | 5.0.22 | +| 4.7.1 | 5.0.21 | | 4.7.1 | 5.0.20 | | 4.7.1 | 5.0.19 | | 4.7.1 | 5.0.18 | From da99073b4b3b309aed1d0063663305e8ed6bf0d3 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 24 Jul 2024 11:03:33 +0900 Subject: [PATCH 0070/1908] ImageURLInputUI: Make onSetLightbox and resetLightbox optional (#63573) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: michalczaplinski <czapla@git.wordpress.org> --- .../src/components/url-popover/image-url-input-ui.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/url-popover/image-url-input-ui.js b/packages/block-editor/src/components/url-popover/image-url-input-ui.js index a7b40b42f6dd78..8209ff1939f091 100644 --- a/packages/block-editor/src/components/url-popover/image-url-input-ui.js +++ b/packages/block-editor/src/components/url-popover/image-url-input-ui.js @@ -272,7 +272,7 @@ const ImageURLInputUI = ( { icon={ linkOff } label={ __( 'Disable expand on click' ) } onClick={ () => { - onSetLightbox( false ); + onSetLightbox?.( false ); } } size="compact" /> @@ -302,7 +302,7 @@ const ImageURLInputUI = ( { label={ __( 'Remove link' ) } onClick={ () => { onLinkRemove(); - resetLightbox(); + resetLightbox?.(); } } size="compact" /> @@ -366,7 +366,7 @@ const ImageURLInputUI = ( { LINK_DESTINATION_NONE, href: '', } ); - onSetLightbox( true ); + onSetLightbox?.( true ); stopEditLink(); } } > From 7ad06628647eeea1fc26cec761f33c69e3c8020f Mon Sep 17 00:00:00 2001 From: Kai Hao <kevin830726@gmail.com> Date: Wed, 24 Jul 2024 10:55:35 +0800 Subject: [PATCH 0071/1908] Fix user patterns disabling sync filter (#63828) Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../components/inserter/block-patterns-tab/patterns-filter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/patterns-filter.js b/packages/block-editor/src/components/inserter/block-patterns-tab/patterns-filter.js index 9e57f00b6b4661..c928012daae93b 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/patterns-filter.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/patterns-filter.js @@ -22,7 +22,8 @@ import { INSERTER_PATTERN_TYPES, } from './utils'; -const getShouldDisableSyncFilter = ( sourceFilter ) => sourceFilter !== 'all'; +const getShouldDisableSyncFilter = ( sourceFilter ) => + sourceFilter !== 'all' && sourceFilter !== 'user'; const getShouldDisableNonUserSources = ( category ) => { return category.name === myPatternsCategory.name; }; From acd36dbb04505b5f1cda1b2526d51abcd487c85c Mon Sep 17 00:00:00 2001 From: Robert Anderson <robert@noisysocks.com> Date: Wed, 24 Jul 2024 15:02:16 +1000 Subject: [PATCH 0072/1908] Image block: Show placeholder when uploading HEIC files (#63643) * Image block: Show placeholder when uploading HEIC files * Use Placeholder component * Increase placeholder opacity * Revert "Increase placeholder opacity" This reverts commit f5e8ac8249aad43c083e0cb7d222432be8115e2b. Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> --- packages/block-library/src/image/editor.scss | 7 +- packages/block-library/src/image/image.js | 84 ++++++++++++-------- 2 files changed, 58 insertions(+), 33 deletions(-) diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss index 18344eec9126e7..6aaa8e7491ed58 100644 --- a/packages/block-library/src/image/editor.scss +++ b/packages/block-library/src/image/editor.scss @@ -3,7 +3,7 @@ .wp-block-image.wp-block-image { // Show Placeholder style on-select. - &.is-selected .components-placeholder { + &.is-selected .block-editor-media-placeholder { // Block UI appearance. color: $gray-900; background-color: $white; @@ -70,6 +70,11 @@ figure.wp-block-image:not(.wp-block) { } } +// Shown while image is being uploded but cannot be previewed. +.wp-block-image__placeholder { + aspect-ratio: 4 / 3; +} + // This is necessary for the editor resize handles to accurately work on a non-floated, non-resized, small image. .wp-block-image .components-resizable-box__container { // Using "display: table" because: diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 5f376ffdac8629..7dd03a7fb5837c 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -14,6 +14,7 @@ import { __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, __experimentalUseCustomUnits as useCustomUnits, + Placeholder, } from '@wordpress/components'; import { useViewportMatch } from '@wordpress/compose'; import { useSelect, useDispatch } from '@wordpress/data'; @@ -176,6 +177,7 @@ export default function Image( { ] = useState( {} ); const [ isEditingImage, setIsEditingImage ] = useState( false ); const [ externalBlob, setExternalBlob ] = useState(); + const [ hasImageErrored, setHasImageErrored ] = useState( false ); const hasNonContentControls = blockEditingMode === 'default'; const isContentOnlyMode = blockEditingMode === 'contentOnly'; const isResizable = @@ -245,15 +247,24 @@ export default function Image( { } function onImageError() { + setHasImageErrored( true ); + // Check if there's an embed block that handles this URL, e.g., instagram URL. // See: https://github.com/WordPress/gutenberg/pull/11472 const embedBlock = createUpgradedEmbedBlock( { attributes: { url } } ); - if ( undefined !== embedBlock ) { onReplace( embedBlock ); } } + function onImageLoad( event ) { + setHasImageErrored( false ); + setLoadedNaturalSize( { + loadedNaturalWidth: event.target?.naturalWidth, + loadedNaturalHeight: event.target?.naturalHeight, + } ); + } + function onSetHref( props ) { setAttributes( props ); } @@ -815,37 +826,46 @@ export default function Image( { const shadowProps = getShadowClassesAndStyles( attributes ); const isRounded = attributes.className?.includes( 'is-style-rounded' ); - let img = ( - // Disable reason: Image itself is not meant to be interactive, but - // should direct focus to block. - /* eslint-disable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/click-events-have-key-events */ - <> - <img - src={ temporaryURL || url } - alt={ defaultedAlt } - onError={ () => onImageError() } - onLoad={ ( event ) => { - setLoadedNaturalSize( { - loadedNaturalWidth: event.target?.naturalWidth, - loadedNaturalHeight: event.target?.naturalHeight, - } ); - } } - ref={ imageRef } - className={ borderProps.className } - style={ { - width: - ( width && height ) || aspectRatio ? '100%' : undefined, - height: - ( width && height ) || aspectRatio ? '100%' : undefined, - objectFit: scale, - ...borderProps.style, - ...shadowProps.style, - } } - /> - { temporaryURL && <Spinner /> } - </> - /* eslint-enable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/click-events-have-key-events */ - ); + let img = + temporaryURL && hasImageErrored ? ( + // Show a placeholder during upload when the blob URL can't be loaded. This can + // happen when the user uploads a HEIC image in a browser that doesn't support them. + <Placeholder + className="wp-block-image__placeholder" + withIllustration + > + <Spinner /> + </Placeholder> + ) : ( + // Disable reason: Image itself is not meant to be interactive, but + // should direct focus to block. + /* eslint-disable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/click-events-have-key-events */ + <> + <img + src={ temporaryURL || url } + alt={ defaultedAlt } + onError={ onImageError } + onLoad={ onImageLoad } + ref={ imageRef } + className={ borderProps.className } + style={ { + width: + ( width && height ) || aspectRatio + ? '100%' + : undefined, + height: + ( width && height ) || aspectRatio + ? '100%' + : undefined, + objectFit: scale, + ...borderProps.style, + ...shadowProps.style, + } } + /> + { temporaryURL && <Spinner /> } + </> + /* eslint-enable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/click-events-have-key-events */ + ); if ( canEditImage && isEditingImage ) { img = ( From 85db58f2de6e6e353c4cad8b0c3a5e46e610409a Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:16:39 +1000 Subject: [PATCH 0073/1908] Global Styles: Remove unused global styles background screen (#63887) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../global-styles/screen-background.js | 29 ------------------- 1 file changed, 29 deletions(-) delete mode 100644 packages/edit-site/src/components/global-styles/screen-background.js diff --git a/packages/edit-site/src/components/global-styles/screen-background.js b/packages/edit-site/src/components/global-styles/screen-background.js deleted file mode 100644 index e6d338ffcbef1e..00000000000000 --- a/packages/edit-site/src/components/global-styles/screen-background.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; - -/** - * Internal dependencies - */ -import BackgroundPanel from './background-panel'; -import ScreenHeader from './header'; -import { unlock } from '../../lock-unlock'; - -const { useHasBackgroundPanel, useGlobalSetting } = unlock( - blockEditorPrivateApis -); - -function ScreenBackground() { - const [ settings ] = useGlobalSetting( '' ); - const hasBackgroundPanel = useHasBackgroundPanel( settings ); - return ( - <> - <ScreenHeader title={ __( 'Background image' ) } /> - { hasBackgroundPanel && <BackgroundPanel /> } - </> - ); -} - -export default ScreenBackground; From ab9e132609a318a19c31d871c8944cd42df453b5 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 24 Jul 2024 08:38:30 +0200 Subject: [PATCH 0074/1908] Block Bindings: Improve how the context needed by sources is extended in the editor (#63513) * Move bindings registration to editor provider * Remove sources from editor provider * Create `registerCoreBlockBindingsSources` function * Add `updateBlockBindingsSource` action * Bootstrap sources defined in the server * Change registration to allow server bootstrap * Remove label from post meta and pattern overrides * Remove `updateBlockBindingsSource` * Use `bootstrapBlockBindingsSource` instead * Wrap server registration in the same function * Change how label is managed * Remove type from object * Add usesContext to the store * Handle usesContext validation * Merge usesContext and add tests * Read `usesContext` during bindings processing * Adapt code after rebase * More changes after rebase * Adapt unit test * Adapt unit tests Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- .../src/hooks/use-bindings-attributes.js | 28 ++++++- packages/blocks/src/api/registration.js | 8 ++ packages/blocks/src/api/test/registration.js | 82 ++++++++++++++++++- packages/blocks/src/store/private-actions.js | 1 + packages/blocks/src/store/reducer.js | 12 +++ 5 files changed, 125 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index 410ad93bd971a7..54b5425bfc44a5 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -4,13 +4,14 @@ import { store as blocksStore } from '@wordpress/blocks'; import { createHigherOrderComponent } from '@wordpress/compose'; import { useRegistry, useSelect } from '@wordpress/data'; -import { useCallback, useMemo } from '@wordpress/element'; +import { useCallback, useMemo, useContext } from '@wordpress/element'; import { addFilter } from '@wordpress/hooks'; /** * Internal dependencies */ import { unlock } from '../lock-unlock'; +import BlockContext from '../components/block-context'; /** @typedef {import('@wordpress/compose').WPHigherOrderComponent} WPHigherOrderComponent */ /** @typedef {import('@wordpress/blocks').WPBlockSettings} WPBlockSettings */ @@ -93,10 +94,11 @@ export function canBindAttribute( blockName, attributeName ) { export const withBlockBindingSupport = createHigherOrderComponent( ( BlockEdit ) => ( props ) => { const registry = useRegistry(); + const blockContext = useContext( BlockContext ); const sources = useSelect( ( select ) => unlock( select( blocksStore ) ).getAllBlockBindingsSources() ); - const { name, clientId, context } = props; + const { name, clientId } = props; const hasParentPattern = !! props.context[ 'pattern/overrides' ]; const hasPatternOverridesDefaultBinding = props.attributes.metadata?.bindings?.[ DEFAULT_ATTRIBUTE ] @@ -145,6 +147,15 @@ export const withBlockBindingSupport = createHigherOrderComponent( if ( blockBindingsBySource.size ) { for ( const [ source, bindings ] of blockBindingsBySource ) { + // Populate context. + const context = {}; + + if ( source.usesContext?.length ) { + for ( const key of source.usesContext ) { + context[ key ] = blockContext[ key ]; + } + } + // Get values in batch if the source supports it. const values = source.getValues( { registry, @@ -177,7 +188,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( } return attributes; - }, [ blockBindings, name, clientId, context, registry, sources ] ); + }, [ blockBindings, name, clientId, blockContext, registry, sources ] ); const { setAttributes } = props; @@ -223,6 +234,15 @@ export const withBlockBindingSupport = createHigherOrderComponent( source, bindings, ] of blockBindingsBySource ) { + // Populate context. + const context = {}; + + if ( source.usesContext?.length ) { + for ( const key of source.usesContext ) { + context[ key ] = blockContext[ key ]; + } + } + source.setValues( { registry, context, @@ -255,7 +275,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( blockBindings, name, clientId, - context, + blockContext, setAttributes, sources, hasPatternOverridesDefaultBinding, diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 886309d8bd8f3e..7cce959c78cc80 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -770,6 +770,7 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { * @param {Object} source Properties of the source to be registered. * @param {string} source.name The unique and machine-readable name. * @param {string} [source.label] Human-readable label. + * @param {Array} [source.usesContext] Array of context needed by the source only in the editor. * @param {Function} [source.getValues] Function to get the values from the source. * @param {Function} [source.setValues] Function to update multiple values connected to the source. * @param {Function} [source.getPlaceholder] Function to get the placeholder when the value is undefined. @@ -794,6 +795,7 @@ export const registerBlockBindingsSource = ( source ) => { const { name, label, + usesContext, getValues, setValues, getPlaceholder, @@ -867,6 +869,12 @@ export const registerBlockBindingsSource = ( source ) => { return; } + // Check the `usesContext` property is correct. + if ( usesContext && ! Array.isArray( usesContext ) ) { + warning( 'Block bindings source usesContext must be an array.' ); + return; + } + // Check the `getValues` property is correct. if ( getValues && typeof getValues !== 'function' ) { warning( 'Block bindings source getValues must be a function.' ); diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index d36abee2930bfa..f4df432976bc12 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -1513,8 +1513,10 @@ describe( 'blocks', () => { } ); it( 'should not override label from the server', () => { - // Simulate bootstrapping a source from the server registration. - registerBlockBindingsSource( { + // Bootstrap source from the server. + unlock( + dispatch( blocksStore ) + ).addBootstrappedBlockBindingsSource( { name: 'core/server', label: 'Server label', } ); @@ -1528,6 +1530,80 @@ describe( 'blocks', () => { ); } ); + // Check the `usesContext` array is correct. + it( 'should reject invalid usesContext property', () => { + registerBlockBindingsSource( { + name: 'core/testing', + label: 'testing', + usesContext: 'should be an array', + } ); + expect( console ).toHaveWarnedWith( + 'Block bindings source usesContext must be an array.' + ); + } ); + + it( 'should add usesContext when only defined in the server', () => { + // Bootstrap source from the server. + unlock( + dispatch( blocksStore ) + ).addBootstrappedBlockBindingsSource( { + name: 'core/testing', + label: 'testing', + usesContext: [ 'postId', 'postType' ], + } ); + // Register source in the client without usesContext. + registerBlockBindingsSource( { + name: 'core/testing', + getValue: () => 'value', + } ); + const source = getBlockBindingsSource( 'core/testing' ); + unregisterBlockBindingsSource( 'core/testing' ); + expect( source.usesContext ).toEqual( [ 'postId', 'postType' ] ); + } ); + + it( 'should add usesContext when only defined in the client', () => { + // Bootstrap source from the server. + unlock( + dispatch( blocksStore ) + ).addBootstrappedBlockBindingsSource( { + name: 'core/testing', + label: 'testing', + } ); + // Register source in the client with usesContext. + registerBlockBindingsSource( { + name: 'core/testing', + usesContext: [ 'postId', 'postType' ], + getValue: () => 'value', + } ); + const source = getBlockBindingsSource( 'core/testing' ); + unregisterBlockBindingsSource( 'core/testing' ); + expect( source.usesContext ).toEqual( [ 'postId', 'postType' ] ); + } ); + + it( 'should merge usesContext from server and client without duplicates', () => { + // Bootstrap source from the server. + unlock( + dispatch( blocksStore ) + ).addBootstrappedBlockBindingsSource( { + name: 'core/testing', + label: 'testing', + usesContext: [ 'postId', 'postType' ], + } ); + // Register source in the client with usesContext. + registerBlockBindingsSource( { + name: 'core/testing', + usesContext: [ 'postType', 'clientContext' ], + getValue: () => 'value', + } ); + const source = getBlockBindingsSource( 'core/testing' ); + unregisterBlockBindingsSource( 'core/testing' ); + expect( source.usesContext ).toEqual( [ + 'postId', + 'postType', + 'clientContext', + ] ); + } ); + // Check the `getValues` callback is correct. it( 'should reject invalid getValues callback', () => { registerBlockBindingsSource( { @@ -1584,6 +1660,7 @@ describe( 'blocks', () => { it( 'should register a valid source', () => { const sourceProperties = { label: 'Valid Source', + usesContext: [ 'postId' ], getValues: () => 'value', setValues: () => 'new values', getPlaceholder: () => 'placeholder', @@ -1605,6 +1682,7 @@ describe( 'blocks', () => { label: 'Valid Source', } ); const source = getBlockBindingsSource( 'core/valid-source' ); + expect( source.usesContext ).toBeUndefined(); expect( source.getValues ).toBeUndefined(); expect( source.setValues ).toBeUndefined(); expect( source.getPlaceholder ).toBeUndefined(); diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index 6f7581da53de36..977270cf1d0c97 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -51,6 +51,7 @@ export function addBlockBindingsSource( source ) { type: 'ADD_BLOCK_BINDINGS_SOURCE', name: source.name, label: source.label, + usesContext: source.usesContext, getValues: source.getValues, setValues: source.setValues, getPlaceholder: source.getPlaceholder, diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 5cffb0abc91973..5e0714b6064fde 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -374,11 +374,23 @@ export function collections( state = {}, action ) { export function blockBindingsSources( state = {}, action ) { switch ( action.type ) { case 'ADD_BLOCK_BINDINGS_SOURCE': + // Merge usesContext with existing values, potentially defined in the server registration. + let mergedUsesContext = [ + ...( state[ action.name ]?.usesContext || [] ), + ...( action.usesContext || [] ), + ]; + // Remove duplicates. + mergedUsesContext = + mergedUsesContext.length > 0 + ? [ ...new Set( mergedUsesContext ) ] + : undefined; + return { ...state, [ action.name ]: { // Don't override the label if it's already set. label: state[ action.name ]?.label || action.label, + usesContext: mergedUsesContext, getValues: action.getValues, setValues: action.setValues, getPlaceholder: action.getPlaceholder, From 8a36fd49833ab6836e64aca45fefcf400925e585 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:47:46 +1000 Subject: [PATCH 0075/1908] Global Styles: Move background panel under color panel (#63888) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../components/global-styles/screen-block.js | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/screen-block.js b/packages/edit-site/src/components/global-styles/screen-block.js index a5358388e89c7f..a16a01956f5a88 100644 --- a/packages/edit-site/src/components/global-styles/screen-block.js +++ b/packages/edit-site/src/components/global-styles/screen-block.js @@ -264,6 +264,16 @@ function ScreenBlock( { name, variation } ) { settings={ settings } /> ) } + { hasBackgroundPanel && ( + <StylesBackgroundPanel + inheritedValue={ inheritedStyle } + value={ style } + onChange={ setStyle } + settings={ settings } + defaultValues={ BACKGROUND_BLOCK_DEFAULT_VALUES } + themeFileURIs={ _links?.[ 'wp:theme-file' ] } + /> + ) } { hasTypographyPanel && ( <StylesTypographyPanel inheritedValue={ inheritedStyle } @@ -306,17 +316,6 @@ function ScreenBlock( { name, variation } ) { /> ) } - { hasBackgroundPanel && ( - <StylesBackgroundPanel - inheritedValue={ inheritedStyle } - value={ style } - onChange={ setStyle } - settings={ settings } - defaultValues={ BACKGROUND_BLOCK_DEFAULT_VALUES } - themeFileURIs={ _links?.[ 'wp:theme-file' ] } - /> - ) } - { canEditCSS && ( <PanelBody title={ __( 'Advanced' ) } initialOpen={ false }> <p> From 368d0acd6a57debe5b1d5ea376e1ff17090ac7d4 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Wed, 24 Jul 2024 12:34:05 +0530 Subject: [PATCH 0076/1908] Font Library: Add 'No fonts installed' message on library tab when fonts aren't available (#63740) * Add message in library tab of font modal when fonts are not available * Reset notice on font library modal open * Add e2e test for no font installed state in font library modal Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../components/global-styles/font-families.js | 10 ++++++---- .../font-library-modal/installed-fonts.js | 6 ++++++ .../e2e/specs/site-editor/font-library.spec.js | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-families.js b/packages/edit-site/src/components/global-styles/font-families.js index 5119ca679e40ad..7a05a66c6efdfe 100644 --- a/packages/edit-site/src/components/global-styles/font-families.js +++ b/packages/edit-site/src/components/global-styles/font-families.js @@ -26,7 +26,7 @@ import { unlock } from '../../lock-unlock'; const { useGlobalSetting } = unlock( blockEditorPrivateApis ); function FontFamilies() { - const { baseCustomFonts, modalTabOpen, setModalTabOpen } = + const { baseCustomFonts, modalTabOpen, setModalTabOpen, setNotice } = useContext( FontLibraryContext ); const [ fontFamilies ] = useGlobalSetting( 'typography.fontFamilies' ); const [ baseFontFamilies ] = useGlobalSetting( @@ -111,13 +111,15 @@ function FontFamilies() { className="edit-site-global-styles-font-families__manage-fonts" variant="secondary" __next40pxDefaultSize - onClick={ () => + onClick={ () => { + // Reset notice when opening the modal. + setNotice( null ); setModalTabOpen( hasInstalledFonts ? 'installed-fonts' : 'upload-fonts' - ) - } + ); + } } > { hasInstalledFonts ? __( 'Manage fonts' ) diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js index f3c8d73eef307e..76618a54aeb92f 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js @@ -148,6 +148,7 @@ function InstalledFonts() { refreshLibrary(); }, [] ); + const hasFonts = baseThemeFonts.length > 0 || baseCustomFonts.length > 0; return ( <div className="font-library-modal__tabpanel-layout"> { isResolvingLibrary && ( @@ -173,6 +174,11 @@ function InstalledFonts() { { notice.message } </Notice> ) } + { ! hasFonts && ( + <Text as="p"> + { __( 'No fonts installed.' ) } + </Text> + ) } { baseThemeFonts.length > 0 && ( <VStack> <h2 className="font-library-modal__fonts-title"> diff --git a/test/e2e/specs/site-editor/font-library.spec.js b/test/e2e/specs/site-editor/font-library.spec.js index 36b12eaf186c65..3025e61303c22e 100644 --- a/test/e2e/specs/site-editor/font-library.spec.js +++ b/test/e2e/specs/site-editor/font-library.spec.js @@ -14,6 +14,24 @@ test.describe( 'Font Library', () => { await editor.canvas.locator( 'body' ).click(); } ); + test( 'should display the "no font installed." message', async ( { + page, + } ) => { + await page.getByRole( 'button', { name: 'Styles' } ).click(); + await page + .getByRole( 'button', { name: 'Typography Styles' } ) + .click(); + await page + .getByRole( 'button', { + name: 'Add fonts', + } ) + .click(); + await page.getByRole( 'tab', { name: 'Library' } ).click(); + await expect( + page.getByLabel( 'library' ).getByText( 'No fonts installed.' ) + ).toBeVisible(); + } ); + test( 'should display the "Add fonts" button', async ( { page } ) => { await page.getByRole( 'button', { name: 'Styles' } ).click(); await page From c07b37a545a16056ca3ac53dc37906cb9ebf9f9f Mon Sep 17 00:00:00 2001 From: Kai Hao <kevin830726@gmail.com> Date: Wed, 24 Jul 2024 16:38:30 +0800 Subject: [PATCH 0077/1908] Hide source filter in my patterns (#63831) Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> * Hide source filter in my patterns * Fix function name --- .../block-patterns-tab/patterns-filter.js | 81 +++++++++---------- 1 file changed, 38 insertions(+), 43 deletions(-) diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/patterns-filter.js b/packages/block-editor/src/components/inserter/block-patterns-tab/patterns-filter.js index c928012daae93b..fd7458a52bf331 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/patterns-filter.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/patterns-filter.js @@ -24,10 +24,29 @@ import { const getShouldDisableSyncFilter = ( sourceFilter ) => sourceFilter !== 'all' && sourceFilter !== 'user'; -const getShouldDisableNonUserSources = ( category ) => { +const getShouldHideSourcesFilter = ( category ) => { return category.name === myPatternsCategory.name; }; +const PATTERN_SOURCE_MENU_OPTIONS = [ + { + value: 'all', + label: _x( 'All', 'patterns' ), + }, + { + value: INSERTER_PATTERN_TYPES.directory, + label: __( 'Pattern Directory' ), + }, + { + value: INSERTER_PATTERN_TYPES.theme, + label: __( 'Theme & Plugins' ), + }, + { + value: INSERTER_PATTERN_TYPES.user, + label: __( 'User' ), + }, +]; + export function PatternsFilter( { setPatternSyncFilter, setPatternSourceFilter, @@ -51,10 +70,9 @@ export function PatternsFilter( { currentPatternSourceFilter ); - // We also need to disable the directory and theme source filter options if the category - // is `myPatterns` otherwise applying them will also just result in no patterns being shown. - const shouldDisableNonUserSources = - getShouldDisableNonUserSources( category ); + // We also hide the directory and theme source filter if the category is `myPatterns` + // otherwise there will only be one option available. + const shouldHideSourcesFilter = getShouldHideSourcesFilter( category ); const patternSyncMenuOptions = useMemo( () => [ @@ -76,31 +94,6 @@ export function PatternsFilter( { [ shouldDisableSyncFilter ] ); - const patternSourceMenuOptions = useMemo( - () => [ - { - value: 'all', - label: _x( 'All', 'patterns' ), - disabled: shouldDisableNonUserSources, - }, - { - value: INSERTER_PATTERN_TYPES.directory, - label: __( 'Pattern Directory' ), - disabled: shouldDisableNonUserSources, - }, - { - value: INSERTER_PATTERN_TYPES.theme, - label: __( 'Theme & Plugins' ), - disabled: shouldDisableNonUserSources, - }, - { - value: INSERTER_PATTERN_TYPES.user, - label: __( 'User' ), - }, - ], - [ shouldDisableNonUserSources ] - ); - function handleSetSourceFilterChange( newSourceFilter ) { setPatternSourceFilter( newSourceFilter ); if ( getShouldDisableSyncFilter( newSourceFilter ) ) { @@ -137,19 +130,21 @@ export function PatternsFilter( { > { () => ( <> - <MenuGroup label={ __( 'Source' ) }> - <MenuItemsChoice - choices={ patternSourceMenuOptions } - onSelect={ ( value ) => { - handleSetSourceFilterChange( value ); - scrollContainerRef.current?.scrollTo( - 0, - 0 - ); - } } - value={ currentPatternSourceFilter } - /> - </MenuGroup> + { ! shouldHideSourcesFilter && ( + <MenuGroup label={ __( 'Source' ) }> + <MenuItemsChoice + choices={ PATTERN_SOURCE_MENU_OPTIONS } + onSelect={ ( value ) => { + handleSetSourceFilterChange( value ); + scrollContainerRef.current?.scrollTo( + 0, + 0 + ); + } } + value={ currentPatternSourceFilter } + /> + </MenuGroup> + ) } <MenuGroup label={ __( 'Type' ) }> <MenuItemsChoice choices={ patternSyncMenuOptions } From e05fbc2101cc0bce3e06decad14fcaa75e0ba37b Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Wed, 24 Jul 2024 09:55:08 +0100 Subject: [PATCH 0078/1908] Font Library: Remove unused font library experiment (#63890) Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> --- .../src/components/global-styles/screen-typography.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/screen-typography.js b/packages/edit-site/src/components/global-styles/screen-typography.js index 6d1b69f0ddb5e5..a58802a204ce32 100644 --- a/packages/edit-site/src/components/global-styles/screen-typography.js +++ b/packages/edit-site/src/components/global-styles/screen-typography.js @@ -32,8 +32,7 @@ function ScreenTypography() { /> <div className="edit-site-global-styles-screen"> <VStack spacing={ 7 }> - { ! window.__experimentalDisableFontLibrary && - fontLibraryEnabled && <FontFamilies /> } + { fontLibraryEnabled && <FontFamilies /> } <TypographyElements /> <TypographyVariations title={ __( 'Presets' ) } /> <FontSizesCount /> From a15e048dccf3b4b9325a5349a8ef3233e35bb537 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Wed, 24 Jul 2024 14:36:53 +0530 Subject: [PATCH 0079/1908] Font Library: Include a "Select All" options to activate/deactivate all fonts (#63531) * Add function to activate all fonts on select all click * implement toggle to select all fonts * add style for select all option * Add style for select all lable * Removed unneccessory use of flex component * Remove new function added to context * Modified flow of select all toggle function * Removed extra spaces * Remove use of context * Update logic to choose all fonts on click in the indeterminate condition * Fix the issue of select all toggle for fonts without font faces * Remove ad hoc font style for select all label * Updated styles for select all toggle's checkbox to align with other checkboxes Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: creativecoder <grantmkin@git.wordpress.org> Co-authored-by: beafialho <beafialho@git.wordpress.org> --- .../font-library-modal/installed-fonts.js | 71 ++++++++++++++++++- .../font-library-modal/style.scss | 9 +++ 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js index 76618a54aeb92f..6602a778dc66c3 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js @@ -16,6 +16,7 @@ import { Flex, Notice, ProgressBar, + CheckboxControl, } from '@wordpress/components'; import { useEntityRecord, store as coreStore } from '@wordpress/core-data'; import { useSelect } from '@wordpress/data'; @@ -31,7 +32,12 @@ import { FontLibraryContext } from './context'; import FontCard from './font-card'; import LibraryFontVariant from './library-font-variant'; import { sortFontFaces } from './utils/sort-font-faces'; -import { setUIValuesNeeded } from './utils'; +import { + setUIValuesNeeded, + loadFontFaceInBrowser, + unloadFontFaceInBrowser, + getDisplaySrcFromFontFace, +} from './utils'; import { unlock } from '../../../lock-unlock'; const { useGlobalSetting } = unlock( blockEditorPrivateApis ); @@ -49,8 +55,11 @@ function InstalledFonts() { getFontFacesActivated, notice, setNotice, - fontFamilies, } = useContext( FontLibraryContext ); + + const [ fontFamilies, setFontFamilies ] = useGlobalSetting( + 'typography.fontFamilies' + ); const [ isConfirmDeleteOpen, setIsConfirmDeleteOpen ] = useState( false ); const [ baseFontFamilies ] = useGlobalSetting( 'typography.fontFamilies', @@ -61,7 +70,6 @@ function InstalledFonts() { const { __experimentalGetCurrentGlobalStylesId } = select( coreStore ); return __experimentalGetCurrentGlobalStylesId(); } ); - const globalStyles = useEntityRecord( 'root', 'globalStyles', @@ -148,6 +156,55 @@ function InstalledFonts() { refreshLibrary(); }, [] ); + // Get activated fonts count. + const activeFontsCount = libraryFontSelected + ? getFontFacesActivated( + libraryFontSelected.slug, + libraryFontSelected.source + ).length + : 0; + + const selectedFontsCount = + libraryFontSelected?.fontFace?.length ?? + ( libraryFontSelected?.fontFamily ? 1 : 0 ); + + // Check if any fonts are selected. + const isIndeterminate = + activeFontsCount > 0 && activeFontsCount !== selectedFontsCount; + + // Check if all fonts are selected. + const isSelectAllChecked = activeFontsCount === selectedFontsCount; + + // Toggle select all fonts. + const toggleSelectAll = () => { + const initialFonts = + fontFamilies?.[ libraryFontSelected.source ]?.filter( + ( f ) => f.slug !== libraryFontSelected.slug + ) ?? []; + const newFonts = isSelectAllChecked + ? initialFonts + : [ ...initialFonts, libraryFontSelected ]; + + setFontFamilies( { + ...fontFamilies, + [ libraryFontSelected.source ]: newFonts, + } ); + + if ( libraryFontSelected.fontFace ) { + libraryFontSelected.fontFace.forEach( ( face ) => { + if ( isSelectAllChecked ) { + unloadFontFaceInBrowser( face, 'all' ); + } else { + loadFontFaceInBrowser( + face, + getDisplaySrcFromFontFace( face?.src ), + 'all' + ); + } + } ); + } + }; + const hasFonts = baseThemeFonts.length > 0 || baseCustomFonts.length > 0; return ( <div className="font-library-modal__tabpanel-layout"> @@ -311,6 +368,14 @@ function InstalledFonts() { </Text> <Spacer margin={ 4 } /> <VStack spacing={ 0 }> + <CheckboxControl + className="font-library-modal__select-all" + label={ __( 'Select all' ) } + checked={ isSelectAllChecked } + onChange={ toggleSelectAll } + indeterminate={ isIndeterminate } + __nextHasNoMarginBottom + /> <Spacer margin={ 8 } /> { getFontFacesToDisplay( libraryFontSelected diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss index 5b9b595a1e6478..5cbb53a6296ccf 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss +++ b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss @@ -186,3 +186,12 @@ button.font-library-modal__upload-area { justify-content: center; } } + +.font-library-modal__select-all { + padding: $grid-unit-20 $grid-unit-20 $grid-unit-20 $grid-unit-20 + $border-width; + + .components-checkbox-control__label { + padding-left: $grid-unit-20; + } +} + From c5f3dd50867543cd08889f79627bbbac18a096c4 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Wed, 24 Jul 2024 04:10:38 -0500 Subject: [PATCH 0080/1908] Don't automatically show inserter when zoom out mode initiates (#63859) Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> --- .../block-tools/zoom-out-mode-inserters.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js index 5f5b0401b512e0..5d273a4f3f6d58 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { useSelect } from '@wordpress/data'; -import { useEffect, useRef, useState } from '@wordpress/element'; +import { useEffect, useState } from '@wordpress/element'; /** * Internal dependencies @@ -50,17 +50,6 @@ function ZoomOutModeInserters() { }; }, [] ); - const isMounted = useRef( false ); - - useEffect( () => { - if ( ! isMounted.current ) { - isMounted.current = true; - return; - } - // reset insertion point when the block order changes - setInserterIsOpened( true ); - }, [ blockOrder, setInserterIsOpened ] ); - // Defer the initial rendering to avoid the jumps due to the animation. useEffect( () => { const timeout = setTimeout( () => { From 0b94a19ca3307f98fc7124573e8be51cbe32cfd6 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 24 Jul 2024 12:18:36 +0200 Subject: [PATCH 0081/1908] List View: remove the sticky position icon tooltip (#63850) * List View: remove tooltip around the "position: sticky" icon * List view: add "position" information to the block accessible description text * Apply feedback --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../components/list-view/block-select-button.js | 16 +++------------- .../src/components/list-view/block.js | 13 ++++++++++--- .../src/components/list-view/style.scss | 3 ++- .../src/components/list-view/utils.js | 15 +++++++++++++-- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/packages/block-editor/src/components/list-view/block-select-button.js b/packages/block-editor/src/components/list-view/block-select-button.js index 605e22f226b25f..6755bb58e02569 100644 --- a/packages/block-editor/src/components/list-view/block-select-button.js +++ b/packages/block-editor/src/components/list-view/block-select-button.js @@ -10,12 +10,10 @@ import { Button, __experimentalHStack as HStack, __experimentalTruncate as Truncate, - Tooltip, } from '@wordpress/components'; import { forwardRef } from '@wordpress/element'; import { Icon, lockSmall as lock, pinSmall } from '@wordpress/icons'; import { SPACE, ENTER } from '@wordpress/keycodes'; -import { __, sprintf } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; /** @@ -65,14 +63,6 @@ function ListViewBlockSelectButton( const isSticky = blockInformation?.positionType === 'sticky'; const images = useListViewImages( { clientId, isExpanded } ); - const positionLabel = blockInformation?.positionLabel - ? sprintf( - // translators: 1: Position of selected block, e.g. "Sticky" or "Fixed". - __( 'Position: %1$s' ), - blockInformation.positionLabel - ) - : ''; - // The `href` attribute triggers the browser's native HTML drag operations. // When the link is dragged, the element's outerHTML is set in DataTransfer object as text/html. // We need to clear any HTML drag data to prevent `pasteHandler` from firing @@ -136,10 +126,10 @@ function ListViewBlockSelectButton( </Truncate> </span> ) } - { positionLabel && isSticky && ( - <Tooltip text={ positionLabel }> + { isSticky && ( + <span className="block-editor-list-view-block-select-button__sticky"> <Icon icon={ pinSmall } /> - </Tooltip> + </span> ) } { images.length ? ( <span diff --git a/packages/block-editor/src/components/list-view/block.js b/packages/block-editor/src/components/list-view/block.js index 0f6541f9f5b3b9..f4dcf8caef449d 100644 --- a/packages/block-editor/src/components/list-view/block.js +++ b/packages/block-editor/src/components/list-view/block.js @@ -465,8 +465,10 @@ function ListViewBlock( { level ); - const blockPropertiesDescription = - getBlockPropertiesDescription( isLocked ); + const blockPropertiesDescription = getBlockPropertiesDescription( + blockInformation, + isLocked + ); const hasSiblings = siblingBlockCount > 0; const hasRenderedMovers = showBlockMovers && hasSiblings; @@ -562,7 +564,12 @@ function ListViewBlock( { ariaDescribedBy={ descriptionId } /> <AriaReferencedText id={ descriptionId }> - { `${ blockPositionDescription } ${ blockPropertiesDescription }` } + { [ + blockPositionDescription, + blockPropertiesDescription, + ] + .filter( Boolean ) + .join( ' ' ) } </AriaReferencedText> </div> ) } diff --git a/packages/block-editor/src/components/list-view/style.scss b/packages/block-editor/src/components/list-view/style.scss index ea3cc5bb78cdf3..2dce32d535d881 100644 --- a/packages/block-editor/src/components/list-view/style.scss +++ b/packages/block-editor/src/components/list-view/style.scss @@ -416,7 +416,8 @@ background: rgba($black, 0.3); } - .block-editor-list-view-block-select-button__lock { + .block-editor-list-view-block-select-button__lock, + .block-editor-list-view-block-select-button__sticky { line-height: 0; } diff --git a/packages/block-editor/src/components/list-view/utils.js b/packages/block-editor/src/components/list-view/utils.js index d6ca4a1f2e005f..2b8454924c5135 100644 --- a/packages/block-editor/src/components/list-view/utils.js +++ b/packages/block-editor/src/components/list-view/utils.js @@ -13,8 +13,19 @@ export const getBlockPositionDescription = ( position, siblingCount, level ) => level ); -export const getBlockPropertiesDescription = ( isLocked ) => - isLocked ? __( 'This block is locked.' ) : ''; +export const getBlockPropertiesDescription = ( blockInformation, isLocked ) => + [ + blockInformation?.positionLabel + ? `${ sprintf( + // translators: %s: Position of selected block, e.g. "Sticky" or "Fixed". + __( 'Position: %s' ), + blockInformation.positionLabel + ) }.` + : undefined, + isLocked ? __( 'This block is locked.' ) : undefined, + ] + .filter( Boolean ) + .join( ' ' ); /** * Returns true if the client ID occurs within the block selection or multi-selection, From 6128ceae4fbfcdbb0afbf976c34418a7d5e432ad Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 24 Jul 2024 15:32:53 +0400 Subject: [PATCH 0082/1908] Core Data: Support entity queries in the 'useResourcePermissions' hook (#63653) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- package-lock.json | 2 + .../src/navigation-link/link-ui.js | 22 ++--- .../navigation/test/use-navigation-menu.js | 69 +++++++++++--- .../src/navigation/use-navigation-menu.js | 6 +- packages/core-data/README.md | 15 ++- packages/core-data/package.json | 1 + .../hooks/test/use-resource-permissions.js | 93 +++++++++++++++++++ .../src/hooks/use-resource-permissions.ts | 55 +++++++++-- packages/core-data/tsconfig.json | 3 +- .../index.js | 17 ++-- 10 files changed, 231 insertions(+), 52 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0318a97778e11e..44d5e1a7210ef2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52817,6 +52817,7 @@ "@wordpress/sync": "file:../sync", "@wordpress/undo-manager": "file:../undo-manager", "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", "change-case": "^4.1.2", "equivalent-key-map": "^0.2.2", "fast-deep-equal": "^3.1.3", @@ -67661,6 +67662,7 @@ "@wordpress/sync": "file:../sync", "@wordpress/undo-manager": "file:../undo-manager", "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", "change-case": "^4.1.2", "equivalent-key-map": "^0.2.2", "fast-deep-equal": "^3.1.3", diff --git a/packages/block-library/src/navigation-link/link-ui.js b/packages/block-library/src/navigation-link/link-ui.js index 6619c46253546e..deed35145d6dea 100644 --- a/packages/block-library/src/navigation-link/link-ui.js +++ b/packages/block-library/src/navigation-link/link-ui.js @@ -147,15 +147,18 @@ function LinkUIBlockInserter( { clientId, onBack, onSelectBlock } ) { } function UnforwardedLinkUI( props, ref ) { + const { label, url, opensInNewTab, type, kind } = props.link; + const postType = type || 'page'; + const [ addingBlock, setAddingBlock ] = useState( false ); const [ focusAddBlockButton, setFocusAddBlockButton ] = useState( false ); const { saveEntityRecord } = useDispatch( coreStore ); - const pagesPermissions = useResourcePermissions( 'pages' ); - const postsPermissions = useResourcePermissions( 'posts' ); + const permissions = useResourcePermissions( { + kind: 'postType', + name: postType, + } ); async function handleCreate( pageTitle ) { - const postType = props.link.type || 'page'; - const page = await saveEntityRecord( 'postType', postType, { title: pageTitle, status: 'draft', @@ -180,15 +183,6 @@ function UnforwardedLinkUI( props, ref ) { }; } - const { label, url, opensInNewTab, type, kind } = props.link; - - let userCanCreate = false; - if ( ! type || type === 'page' ) { - userCanCreate = pagesPermissions.canCreate; - } else if ( type === 'post' ) { - userCanCreate = postsPermissions.canCreate; - } - // Memoize link value to avoid overriding the LinkControl's internal state. // This is a temporary fix. See https://github.com/WordPress/gutenberg/issues/50976#issuecomment-1568226407. const link = useMemo( @@ -241,7 +235,7 @@ function UnforwardedLinkUI( props, ref ) { hasRichPreviews value={ link } showInitialSuggestions - withCreateSuggestion={ userCanCreate } + withCreateSuggestion={ permissions.canCreate } createSuggestion={ handleCreate } createSuggestionButtonText={ ( searchTerm ) => { let format; diff --git a/packages/block-library/src/navigation/test/use-navigation-menu.js b/packages/block-library/src/navigation/test/use-navigation-menu.js index eb7e90aff22d1a..7eaf648fab936e 100644 --- a/packages/block-library/src/navigation/test/use-navigation-menu.js +++ b/packages/block-library/src/navigation/test/use-navigation-menu.js @@ -9,6 +9,12 @@ import { store as coreStore } from '@wordpress/core-data'; */ import useNavigationMenu from '../use-navigation-menu'; +const BASE_ENTITY = { + kind: 'postType', + name: 'wp_navigation', + id: undefined, +}; + function createRegistryWithStores() { // Create a registry and register used stores. const registry = createRegistry(); @@ -63,37 +69,70 @@ function resolveRecords( registry, menus ) { function resolveReadPermission( registry, allowed ) { const dispatch = registry.dispatch( coreStore ); - dispatch.receiveUserPermission( 'create/navigation', allowed ); - dispatch.startResolution( 'canUser', [ 'read', 'navigation' ] ); - dispatch.finishResolution( 'canUser', [ 'read', 'navigation' ] ); + dispatch.receiveUserPermission( 'read/postType/wp_navigation', allowed ); + dispatch.startResolution( 'canUser', [ 'read', BASE_ENTITY ] ); + dispatch.finishResolution( 'canUser', [ 'read', BASE_ENTITY ] ); } function resolveReadRecordPermission( registry, ref, allowed ) { const dispatch = registry.dispatch( coreStore ); - dispatch.receiveUserPermission( 'create/navigation', allowed ); - dispatch.startResolution( 'canUser', [ 'read', 'navigation', ref ] ); - dispatch.finishResolution( 'canUser', [ 'read', 'navigation', ref ] ); + dispatch.receiveUserPermission( + `read/postType/wp_navigation/${ ref }`, + allowed + ); + dispatch.startResolution( 'canUser', [ + 'read', + { ...BASE_ENTITY, id: ref }, + ] ); + dispatch.finishResolution( 'canUser', [ + 'read', + { ...BASE_ENTITY, id: ref }, + ] ); } function resolveCreatePermission( registry, allowed ) { const dispatch = registry.dispatch( coreStore ); - dispatch.receiveUserPermission( 'create/navigation', allowed ); - dispatch.startResolution( 'canUser', [ 'create', 'navigation' ] ); - dispatch.finishResolution( 'canUser', [ 'create', 'navigation' ] ); + dispatch.receiveUserPermission( 'create/postType/wp_navigation', allowed ); + dispatch.startResolution( 'canUser', [ + 'create', + { kind: 'postType', name: 'wp_navigation' }, + ] ); + dispatch.finishResolution( 'canUser', [ + 'create', + { kind: 'postType', name: 'wp_navigation' }, + ] ); } function resolveUpdatePermission( registry, ref, allowed ) { const dispatch = registry.dispatch( coreStore ); - dispatch.receiveUserPermission( `update/navigation/${ ref }`, allowed ); - dispatch.startResolution( 'canUser', [ 'update', 'navigation', ref ] ); - dispatch.finishResolution( 'canUser', [ 'update', 'navigation', ref ] ); + dispatch.receiveUserPermission( + `update/postType/wp_navigation/${ ref }`, + allowed + ); + dispatch.startResolution( 'canUser', [ + 'update', + { ...BASE_ENTITY, id: ref }, + ] ); + dispatch.finishResolution( 'canUser', [ + 'update', + { ...BASE_ENTITY, id: ref }, + ] ); } function resolveDeletePermission( registry, ref, allowed ) { const dispatch = registry.dispatch( coreStore ); - dispatch.receiveUserPermission( `delete/navigation/${ ref }`, allowed ); - dispatch.startResolution( 'canUser', [ 'delete', 'navigation', ref ] ); - dispatch.finishResolution( 'canUser', [ 'delete', 'navigation', ref ] ); + dispatch.receiveUserPermission( + `delete/postType/wp_navigation/${ ref }`, + allowed + ); + dispatch.startResolution( 'canUser', [ + 'delete', + { ...BASE_ENTITY, id: ref }, + ] ); + dispatch.finishResolution( 'canUser', [ + 'delete', + { ...BASE_ENTITY, id: ref }, + ] ); } describe( 'useNavigationMenus', () => { diff --git a/packages/block-library/src/navigation/use-navigation-menu.js b/packages/block-library/src/navigation/use-navigation-menu.js index 3834661ed6101b..5fd942c485bf84 100644 --- a/packages/block-library/src/navigation/use-navigation-menu.js +++ b/packages/block-library/src/navigation/use-navigation-menu.js @@ -14,7 +14,11 @@ import { useSelect } from '@wordpress/data'; import { PRELOADED_NAVIGATION_MENUS_QUERY } from './constants'; export default function useNavigationMenu( ref ) { - const permissions = useResourcePermissions( 'navigation', ref ); + const permissions = useResourcePermissions( { + kind: 'postType', + name: 'wp_navigation', + id: ref, + } ); const { navigationMenu, diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 2f2094bed7f4d4..de28e4b86be4bf 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -1173,7 +1173,10 @@ _Usage_ import { useResourcePermissions } from '@wordpress/core-data'; function PagesList() { - const { canCreate, isResolving } = useResourcePermissions( 'pages' ); + const { canCreate, isResolving } = useResourcePermissions( { + kind: 'postType', + name: 'page', + } ); if ( isResolving ) { return 'Loading ...'; @@ -1196,7 +1199,11 @@ import { useResourcePermissions } from '@wordpress/core-data'; function Page( { pageId } ) { const { canCreate, canUpdate, canDelete, isResolving } = - useResourcePermissions( 'pages', pageId ); + useResourcePermissions( { + kind: 'postType', + name: 'page', + id: pageId, + } ); if ( isResolving ) { return 'Loading ...'; @@ -1222,8 +1229,8 @@ the store state using `canUser()`, or resolved if missing. _Parameters_ -- _resource_ `string`: The resource in question, e.g. media. -- _id_ `IdType`: ID of a specific resource entry, if needed, e.g. 10. +- _resource_ `string | EntityResource`: Entity resource to check. Accepts entity object `{ kind: 'root', name: 'media', id: 1 }` or REST base as a string - `media`. +- _id_ `IdType`: Optional ID of the resource to check, e.g. 10. Note: This argument is discouraged when using an entity object as a resource to check permissions and will be ignored. _Returns_ diff --git a/packages/core-data/package.json b/packages/core-data/package.json index d94eb375287250..bed2ca97791bc5 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -47,6 +47,7 @@ "@wordpress/sync": "file:../sync", "@wordpress/undo-manager": "file:../undo-manager", "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", "change-case": "^4.1.2", "equivalent-key-map": "^0.2.2", "fast-deep-equal": "^3.1.3", diff --git a/packages/core-data/src/hooks/test/use-resource-permissions.js b/packages/core-data/src/hooks/test/use-resource-permissions.js index bb6c3a85c191f6..b1c43b7947874d 100644 --- a/packages/core-data/src/hooks/test/use-resource-permissions.js +++ b/packages/core-data/src/hooks/test/use-resource-permissions.js @@ -93,4 +93,97 @@ describe( 'useResourcePermissions', () => { } ) ); } ); + + it( 'retrieves the relevant permissions for a id-less entity', async () => { + let data; + const TestComponent = () => { + data = useResourcePermissions( { + kind: 'root', + name: 'media', + } ); + return <div />; + }; + render( + <RegistryProvider value={ registry }> + <TestComponent /> + </RegistryProvider> + ); + expect( data ).toEqual( { + status: 'IDLE', + isResolving: false, + hasResolved: false, + canCreate: false, + canRead: false, + } ); + + await waitFor( () => + expect( data ).toEqual( { + status: 'SUCCESS', + isResolving: false, + hasResolved: true, + canCreate: true, + canRead: false, + } ) + ); + } ); + + it( 'retrieves the relevant permissions for an entity', async () => { + let data; + const TestComponent = () => { + data = useResourcePermissions( { + kind: 'root', + name: 'media', + id: 1, + } ); + return <div />; + }; + render( + <RegistryProvider value={ registry }> + <TestComponent /> + </RegistryProvider> + ); + expect( data ).toEqual( { + status: 'IDLE', + isResolving: false, + hasResolved: false, + canCreate: false, + canRead: false, + canUpdate: false, + canDelete: false, + } ); + + await waitFor( () => + expect( data ).toEqual( { + status: 'SUCCESS', + isResolving: false, + hasResolved: true, + canCreate: true, + canRead: false, + canUpdate: false, + canDelete: false, + } ) + ); + } ); + + it( 'should warn when called with incorrect arguments signature', () => { + const TestComponent = () => { + useResourcePermissions( + { + kind: 'root', + name: 'media', + }, + 1 + ); + return null; + }; + render( + <RegistryProvider value={ registry }> + <TestComponent /> + </RegistryProvider> + ); + + expect( console ).toHaveWarnedWith( + `When 'resource' is an entity object, passing 'id' as a separate argument isn't supported.` + ); + } ); } ); diff --git a/packages/core-data/src/hooks/use-resource-permissions.ts b/packages/core-data/src/hooks/use-resource-permissions.ts index 7da7189e2e5067..38dfc1ed77a3e6 100644 --- a/packages/core-data/src/hooks/use-resource-permissions.ts +++ b/packages/core-data/src/hooks/use-resource-permissions.ts @@ -2,6 +2,7 @@ * WordPress dependencies */ import deprecated from '@wordpress/deprecated'; +import warning from '@wordpress/warning'; /** * Internal dependencies @@ -41,20 +42,34 @@ type ResourcePermissionsResolution< IdType > = [ ( IdType extends void ? SpecificResourcePermissionsResolution : {} ), ]; +type EntityResource = { kind: string; name: string; id?: string | number }; + +function useResourcePermissions< IdType = void >( + resource: string, + id?: IdType +): ResourcePermissionsResolution< IdType >; + +function useResourcePermissions< IdType = void >( + resource: EntityResource, + id?: never +): ResourcePermissionsResolution< IdType >; + /** * Resolves resource permissions. * * @since 6.1.0 Introduced in WordPress core. * - * @param resource The resource in question, e.g. media. - * @param id ID of a specific resource entry, if needed, e.g. 10. + * @param resource Entity resource to check. Accepts entity object `{ kind: 'root', name: 'media', id: 1 }` + * or REST base as a string - `media`. + * @param id Optional ID of the resource to check, e.g. 10. Note: This argument is discouraged + * when using an entity object as a resource to check permissions and will be ignored. * * @example * ```js * import { useResourcePermissions } from '@wordpress/core-data'; * * function PagesList() { - * const { canCreate, isResolving } = useResourcePermissions( 'pages' ); + * const { canCreate, isResolving } = useResourcePermissions( { kind: 'postType', name: 'page' } ); * * if ( isResolving ) { * return 'Loading ...'; @@ -82,7 +97,7 @@ type ResourcePermissionsResolution< IdType > = [ * canUpdate, * canDelete, * isResolving - * } = useResourcePermissions( 'pages', pageId ); + * } = useResourcePermissions( { kind: 'postType', name: 'page', id: pageId } ); * * if ( isResolving ) { * return 'Loading ...'; @@ -109,15 +124,35 @@ type ResourcePermissionsResolution< IdType > = [ * @return Entity records data. * @template IdType */ -export default function useResourcePermissions< IdType = void >( - resource: string, +function useResourcePermissions< IdType = void >( + resource: string | EntityResource, id?: IdType ): ResourcePermissionsResolution< IdType > { + // Serialize `resource` to a string that can be safely used as a React dep. + // We can't just pass `resource` as one of the deps, because if it is passed + // as an object literal, then it will be a different object on each call even + // if the values remain the same. + const isEntity = typeof resource === 'object'; + const resourceAsString = isEntity ? JSON.stringify( resource ) : resource; + + if ( isEntity && typeof id !== 'undefined' ) { + warning( + `When 'resource' is an entity object, passing 'id' as a separate argument isn't supported.` + ); + } + return useQuerySelect( ( resolve ) => { + const hasId = isEntity ? !! resource.id : !! id; const { canUser } = resolve( coreStore ); - const create = canUser( 'create', resource ); - if ( ! id ) { + const create = canUser( + 'create', + isEntity + ? { kind: resource.kind, name: resource.name } + : resource + ); + + if ( ! hasId ) { const read = canUser( 'read', resource ); const isResolving = create.isResolving || read.isResolving; @@ -168,10 +203,12 @@ export default function useResourcePermissions< IdType = void >( canDelete: hasResolved && _delete.data, }; }, - [ resource, id ] + [ resourceAsString, id ] ); } +export default useResourcePermissions; + export function __experimentalUseResourcePermissions( resource: string, id?: unknown diff --git a/packages/core-data/tsconfig.json b/packages/core-data/tsconfig.json index 5db0de19f111e8..26602d82ab0c01 100644 --- a/packages/core-data/tsconfig.json +++ b/packages/core-data/tsconfig.json @@ -21,7 +21,8 @@ { "path": "../rich-text" }, { "path": "../sync" }, { "path": "../undo-manager" }, - { "path": "../url" } + { "path": "../url" }, + { "path": "../warning" } ], "include": [ "src/**/*" ] } diff --git a/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js b/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js index 6d014a589252d9..af844fe9da4fe9 100644 --- a/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js +++ b/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js @@ -5,11 +5,7 @@ import { SlotFillProvider } from '@wordpress/components'; import { useViewportMatch } from '@wordpress/compose'; import { uploadMedia } from '@wordpress/media-utils'; import { useDispatch, useSelect } from '@wordpress/data'; -import { - useEntityBlockEditor, - store as coreStore, - useResourcePermissions, -} from '@wordpress/core-data'; +import { useEntityBlockEditor, store as coreStore } from '@wordpress/core-data'; import { useMemo } from '@wordpress/element'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { privateApis as editPatternsPrivateApis } from '@wordpress/patterns'; @@ -37,9 +33,9 @@ export default function WidgetAreasBlockEditorProvider( { children, ...props } ) { - const mediaPermissions = useResourcePermissions( 'media' ); const isLargeViewport = useViewportMatch( 'medium' ); const { + hasUploadPermissions, reusableBlocks, isFixedToolbarActive, keepCaretInsideBlock, @@ -55,6 +51,11 @@ export default function WidgetAreasBlockEditorProvider( { ? getEntityRecord( 'root', 'site' ) : undefined; return { + hasUploadPermissions: + canUser( 'create', { + kind: 'root', + name: 'media', + } ) ?? true, reusableBlocks: ALLOW_REUSABLE_BLOCKS ? getEntityRecords( 'postType', 'wp_block' ) : EMPTY_ARRAY, @@ -74,7 +75,7 @@ export default function WidgetAreasBlockEditorProvider( { const settings = useMemo( () => { let mediaUploadBlockEditor; - if ( mediaPermissions.canCreate ) { + if ( hasUploadPermissions ) { mediaUploadBlockEditor = ( { onError, ...argumentsObject } ) => { uploadMedia( { wpAllowedMimeTypes: blockEditorSettings.allowedMimeTypes, @@ -95,11 +96,11 @@ export default function WidgetAreasBlockEditorProvider( { pageForPosts, }; }, [ + hasUploadPermissions, blockEditorSettings, isFixedToolbarActive, isLargeViewport, keepCaretInsideBlock, - mediaPermissions.canCreate, reusableBlocks, setIsInserterOpened, pageOnFront, From 9eb2cf92264b59253be73f618fb992d58add1efb Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 24 Jul 2024 23:20:58 +0900 Subject: [PATCH 0083/1908] Tweak Block Locking UI (#63881) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../block-editor/src/components/block-lock/modal.js | 12 ++++++++++-- .../src/components/block-lock/style.scss | 12 ++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/components/block-lock/modal.js b/packages/block-editor/src/components/block-lock/modal.js index 11a03c5aff4dd8..7d09f7b63f8cd0 100644 --- a/packages/block-editor/src/components/block-lock/modal.js +++ b/packages/block-editor/src/components/block-lock/modal.js @@ -217,12 +217,20 @@ export default function BlockLockModal( { clientId, onClose } ) { expanded={ false } > <FlexItem> - <Button variant="tertiary" onClick={ onClose }> + <Button + variant="tertiary" + onClick={ onClose } + __next40pxDefaultSize + > { __( 'Cancel' ) } </Button> </FlexItem> <FlexItem> - <Button variant="primary" type="submit"> + <Button + variant="primary" + type="submit" + __next40pxDefaultSize + > { __( 'Apply' ) } </Button> </FlexItem> diff --git a/packages/block-editor/src/components/block-lock/style.scss b/packages/block-editor/src/components/block-lock/style.scss index 0a43985a83847b..8dc6bfb2021f08 100644 --- a/packages/block-editor/src/components/block-lock/style.scss +++ b/packages/block-editor/src/components/block-lock/style.scss @@ -8,13 +8,9 @@ } } -.block-editor-block-lock-modal__options { - margin-top: $grid-unit-20; - - legend { - margin-bottom: $grid-unit-20; - padding: 0; - } +.block-editor-block-lock-modal__options legend { + margin-bottom: $grid-unit-20; + padding: 0; } .block-editor-block-lock-modal__checklist { @@ -52,7 +48,7 @@ .block-editor-block-lock-modal__template-lock { border-top: $border-width solid $gray-300; margin-top: $grid-unit-20; - padding: $grid-unit-15 0; + padding-top: $grid-unit-20; } .block-editor-block-lock-modal__actions { From c72bae05c497ef1294266b1501d2ad9fcf8435b3 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Wed, 24 Jul 2024 16:35:42 +0200 Subject: [PATCH 0084/1908] Update: Simplify some permission checks. (#63812) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> --- .../global-styles-provider/index.js | 38 ++++++------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js index 62e390cba25ae4..8ac292fb2ce0b2 100644 --- a/packages/editor/src/components/global-styles-provider/index.js +++ b/packages/editor/src/components/global-styles-provider/index.js @@ -33,24 +33,18 @@ export function mergeBaseAndUserConfigs( base, user ) { function useGlobalStylesUserConfig() { const { globalStylesId, isReady, settings, styles, _links } = useSelect( ( select ) => { - const { - getEditedEntityRecord, - hasFinishedResolution, - getUser, - getCurrentUser, - } = select( coreStore ); + const { getEditedEntityRecord, hasFinishedResolution, canUser } = + select( coreStore ); const _globalStylesId = select( coreStore ).__experimentalGetCurrentGlobalStylesId(); - // Doing canUser( 'read', 'global_styles' ) returns false even for users with the capability. - // See: https://github.com/WordPress/gutenberg/issues/63438 - // So we need to check the user capabilities directly. - const userId = getCurrentUser()?.id; - const canEditThemeOptions = - userId && getUser( userId )?.capabilities?.edit_theme_options; - const record = - _globalStylesId && canEditThemeOptions + _globalStylesId && + canUser( 'read', { + kind: 'root', + name: 'globalStyles', + id: _globalStylesId, + } ) ? getEditedEntityRecord( 'root', 'globalStyles', @@ -139,21 +133,11 @@ function useGlobalStylesUserConfig() { function useGlobalStylesBaseConfig() { const baseConfig = useSelect( ( select ) => { - const { - getCurrentUser, - getUser, - __experimentalGetCurrentThemeBaseGlobalStyles, - } = select( coreStore ); - - // Doing canUser( 'read', 'global_styles' ) returns false even for users with the capability. - // See: https://github.com/WordPress/gutenberg/issues/63438 - // So we need to check the user capabilities directly. - const userId = getCurrentUser()?.id; - const canEditThemeOptions = - userId && getUser( userId )?.capabilities?.edit_theme_options; + const { __experimentalGetCurrentThemeBaseGlobalStyles, canUser } = + select( coreStore ); return ( - canEditThemeOptions && + canUser( 'read', { kind: 'root', name: 'theme' } ) && __experimentalGetCurrentThemeBaseGlobalStyles() ); }, [] ); From bfffbe0ec4b67d76e90c691102cd74252594db33 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 24 Jul 2024 19:05:42 +0400 Subject: [PATCH 0085/1908] Font Library: Fix flaky e2e tests (#63904) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../specs/site-editor/font-library.spec.js | 71 ++++++++++++++----- 1 file changed, 52 insertions(+), 19 deletions(-) diff --git a/test/e2e/specs/site-editor/font-library.spec.js b/test/e2e/specs/site-editor/font-library.spec.js index 3025e61303c22e..6d699f4b02a63e 100644 --- a/test/e2e/specs/site-editor/font-library.spec.js +++ b/test/e2e/specs/site-editor/font-library.spec.js @@ -9,15 +9,21 @@ test.describe( 'Font Library', () => { await requestUtils.activateTheme( 'emptytheme' ); } ); - test.beforeEach( async ( { admin, editor } ) => { - await admin.visitSiteEditor(); - await editor.canvas.locator( 'body' ).click(); + test.beforeEach( async ( { admin } ) => { + await admin.visitSiteEditor( { + postId: 'emptytheme//index', + postType: 'wp_template', + canvas: 'edit', + } ); } ); test( 'should display the "no font installed." message', async ( { page, } ) => { - await page.getByRole( 'button', { name: 'Styles' } ).click(); + await page + .getByRole( 'region', { name: 'Editor top bar' } ) + .getByRole( 'button', { name: 'Styles' } ) + .click(); await page .getByRole( 'button', { name: 'Typography Styles' } ) .click(); @@ -33,7 +39,10 @@ test.describe( 'Font Library', () => { } ); test( 'should display the "Add fonts" button', async ( { page } ) => { - await page.getByRole( 'button', { name: 'Styles' } ).click(); + await page + .getByRole( 'region', { name: 'Editor top bar' } ) + .getByRole( 'button', { name: 'Styles' } ) + .click(); await page .getByRole( 'button', { name: 'Typography Styles' } ) .click(); @@ -49,15 +58,21 @@ test.describe( 'Font Library', () => { await requestUtils.activateTheme( 'twentytwentythree' ); } ); - test.beforeEach( async ( { admin, editor } ) => { - await admin.visitSiteEditor(); - await editor.canvas.locator( 'body' ).click(); + test.beforeEach( async ( { admin } ) => { + await admin.visitSiteEditor( { + postId: 'twentytwentythree//index', + postType: 'wp_template', + canvas: 'edit', + } ); } ); test( 'should display the "Manage fonts" button', async ( { page, } ) => { - await page.getByRole( 'button', { name: 'Styles' } ).click(); + await page + .getByRole( 'region', { name: 'Editor top bar' } ) + .getByRole( 'button', { name: 'Styles' } ) + .click(); await page .getByRole( 'button', { name: 'Typography Styles' } ) .click(); @@ -70,7 +85,10 @@ test.describe( 'Font Library', () => { test( 'should open the "Manage fonts" modal when clicking the "Manage fonts" button', async ( { page, } ) => { - await page.getByRole( 'button', { name: 'Styles' } ).click(); + await page + .getByRole( 'region', { name: 'Editor top bar' } ) + .getByRole( 'button', { name: 'Styles' } ) + .click(); await page .getByRole( 'button', { name: 'Typography Styles' } ) .click(); @@ -88,7 +106,10 @@ test.describe( 'Font Library', () => { test( 'should show font variant panel when clicking on a font family', async ( { page, } ) => { - await page.getByRole( 'button', { name: 'Styles' } ).click(); + await page + .getByRole( 'region', { name: 'Editor top bar' } ) + .getByRole( 'button', { name: 'Styles' } ) + .click(); await page .getByRole( 'button', { name: 'Typography Styles' } ) .click(); @@ -125,16 +146,22 @@ test.describe( 'Font Library', () => { ); } ); - test.beforeEach( async ( { admin, editor } ) => { - await admin.visitSiteEditor(); - await editor.canvas.locator( 'body' ).click(); + test.beforeEach( async ( { admin } ) => { + await admin.visitSiteEditor( { + postId: 'emptytheme//index', + postType: 'wp_template', + canvas: 'edit', + } ); } ); test( 'should allow user to add and remove multiple local font files', async ( { page, editor, } ) => { - await page.getByRole( 'button', { name: 'Styles' } ).click(); + await page + .getByRole( 'region', { name: 'Editor top bar' } ) + .getByRole( 'button', { name: 'Styles' } ) + .click(); await page .getByRole( 'button', { name: 'Typography Styles' } ) .click(); @@ -202,15 +229,21 @@ test.describe( 'Font Library', () => { await requestUtils.activateTheme( 'twentytwentyfour' ); } ); - test.beforeEach( async ( { admin, editor } ) => { - await admin.visitSiteEditor(); - await editor.canvas.locator( 'body' ).click(); + test.beforeEach( async ( { admin } ) => { + await admin.visitSiteEditor( { + postId: 'twentytwentyfour//home', + postType: 'wp_template', + canvas: 'edit', + } ); } ); test( 'clicking on a font in the global styles sidebar should activate the font in the overlay when switching Theme Style variation', async ( { page, } ) => { - await page.getByRole( 'button', { name: /styles/i } ).click(); + await page + .getByRole( 'region', { name: 'Editor top bar' } ) + .getByRole( 'button', { name: 'Styles' } ) + .click(); // Click "Browse styles" await page.getByRole( 'button', { name: 'Browse styles' } ).click(); From 0d493e859b96f408a82e73a347a04b3648ad0e2c Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 24 Jul 2024 17:13:56 +0000 Subject: [PATCH 0086/1908] Bump plugin version to 18.9.0-rc.1 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 0d21366bcc29d3..dfe3e6dc8a4285 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.4 * Requires PHP: 7.2 - * Version: 18.8.0 + * Version: 18.9.0-rc.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 44d5e1a7210ef2..869f07dbbc55c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "18.8.0", + "version": "18.9.0-rc.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "18.8.0", + "version": "18.9.0-rc.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 89d576e745aae7..412ff34b91d8c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "18.8.0", + "version": "18.9.0-rc.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From eb106f89e065551fc2e6618eba065ddb37215f5d Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 24 Jul 2024 17:27:13 +0000 Subject: [PATCH 0087/1908] Update changelog files --- packages/a11y/CHANGELOG.md | 2 ++ packages/a11y/package.json | 2 +- packages/annotations/CHANGELOG.md | 2 ++ packages/annotations/package.json | 2 +- packages/api-fetch/CHANGELOG.md | 2 ++ packages/api-fetch/package.json | 2 +- packages/autop/CHANGELOG.md | 2 ++ packages/autop/package.json | 2 +- packages/babel-plugin-import-jsx-pragma/CHANGELOG.md | 2 ++ packages/babel-plugin-import-jsx-pragma/package.json | 2 +- packages/babel-plugin-makepot/CHANGELOG.md | 2 ++ packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/CHANGELOG.md | 2 ++ packages/babel-preset-default/package.json | 2 +- packages/base-styles/CHANGELOG.md | 2 ++ packages/base-styles/package.json | 2 +- packages/blob/CHANGELOG.md | 2 ++ packages/blob/package.json | 2 +- packages/block-directory/CHANGELOG.md | 2 ++ packages/block-directory/package.json | 2 +- packages/block-editor/CHANGELOG.md | 2 ++ packages/block-editor/package.json | 2 +- packages/block-library/CHANGELOG.md | 2 ++ packages/block-library/package.json | 2 +- packages/block-serialization-default-parser/CHANGELOG.md | 2 ++ packages/block-serialization-default-parser/package.json | 2 +- packages/block-serialization-spec-parser/CHANGELOG.md | 2 ++ packages/block-serialization-spec-parser/package.json | 2 +- packages/blocks/CHANGELOG.md | 2 ++ packages/blocks/package.json | 2 +- packages/browserslist-config/CHANGELOG.md | 2 ++ packages/browserslist-config/package.json | 2 +- packages/commands/CHANGELOG.md | 2 ++ packages/commands/package.json | 2 +- packages/components/CHANGELOG.md | 2 ++ packages/components/package.json | 2 +- packages/compose/CHANGELOG.md | 2 ++ packages/compose/package.json | 2 +- packages/core-commands/CHANGELOG.md | 2 ++ packages/core-commands/package.json | 2 +- packages/core-data/CHANGELOG.md | 2 ++ packages/core-data/package.json | 2 +- packages/create-block-interactive-template/CHANGELOG.md | 2 ++ packages/create-block-interactive-template/package.json | 2 +- packages/create-block-tutorial-template/CHANGELOG.md | 2 ++ packages/create-block-tutorial-template/package.json | 2 +- packages/create-block/CHANGELOG.md | 2 ++ packages/create-block/package.json | 2 +- packages/customize-widgets/CHANGELOG.md | 2 ++ packages/customize-widgets/package.json | 2 +- packages/data-controls/CHANGELOG.md | 2 ++ packages/data-controls/package.json | 2 +- packages/data/CHANGELOG.md | 2 ++ packages/data/package.json | 2 +- packages/dataviews/CHANGELOG.md | 2 ++ packages/dataviews/package.json | 2 +- packages/date/CHANGELOG.md | 2 ++ packages/date/package.json | 2 +- packages/dependency-extraction-webpack-plugin/CHANGELOG.md | 2 ++ packages/dependency-extraction-webpack-plugin/package.json | 2 +- packages/deprecated/CHANGELOG.md | 2 ++ packages/deprecated/package.json | 2 +- packages/docgen/CHANGELOG.md | 2 ++ packages/docgen/package.json | 2 +- packages/dom-ready/CHANGELOG.md | 2 ++ packages/dom-ready/package.json | 2 +- packages/dom/CHANGELOG.md | 2 ++ packages/dom/package.json | 2 +- packages/e2e-test-utils-playwright/CHANGELOG.md | 2 ++ packages/e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/CHANGELOG.md | 2 ++ packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/CHANGELOG.md | 2 ++ packages/e2e-tests/package.json | 2 +- packages/edit-post/CHANGELOG.md | 2 ++ packages/edit-post/package.json | 2 +- packages/edit-site/CHANGELOG.md | 2 ++ packages/edit-site/package.json | 2 +- packages/edit-widgets/CHANGELOG.md | 2 ++ packages/edit-widgets/package.json | 2 +- packages/editor/CHANGELOG.md | 2 ++ packages/editor/package.json | 2 +- packages/element/CHANGELOG.md | 2 ++ packages/element/package.json | 2 +- packages/env/CHANGELOG.md | 2 ++ packages/env/package.json | 2 +- packages/escape-html/CHANGELOG.md | 2 ++ packages/escape-html/package.json | 2 +- packages/eslint-plugin/CHANGELOG.md | 2 ++ packages/eslint-plugin/package.json | 2 +- packages/format-library/CHANGELOG.md | 2 ++ packages/format-library/package.json | 2 +- packages/hooks/CHANGELOG.md | 2 ++ packages/hooks/package.json | 2 +- packages/html-entities/CHANGELOG.md | 2 ++ packages/html-entities/package.json | 2 +- packages/i18n/CHANGELOG.md | 2 ++ packages/i18n/package.json | 2 +- packages/icons/CHANGELOG.md | 2 ++ packages/icons/package.json | 2 +- packages/interactivity-router/CHANGELOG.md | 2 ++ packages/interactivity-router/package.json | 2 +- packages/interactivity/CHANGELOG.md | 2 ++ packages/interactivity/package.json | 2 +- packages/interface/CHANGELOG.md | 2 ++ packages/interface/package.json | 2 +- packages/is-shallow-equal/CHANGELOG.md | 2 ++ packages/is-shallow-equal/package.json | 2 +- packages/jest-console/CHANGELOG.md | 2 ++ packages/jest-console/package.json | 2 +- packages/jest-preset-default/CHANGELOG.md | 2 ++ packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/CHANGELOG.md | 2 ++ packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/CHANGELOG.md | 2 ++ packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/CHANGELOG.md | 2 ++ packages/keycodes/package.json | 2 +- packages/lazy-import/CHANGELOG.md | 2 ++ packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/CHANGELOG.md | 2 ++ packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/CHANGELOG.md | 2 ++ packages/media-utils/package.json | 2 +- packages/notices/CHANGELOG.md | 2 ++ packages/notices/package.json | 2 +- packages/npm-package-json-lint-config/CHANGELOG.md | 2 ++ packages/npm-package-json-lint-config/package.json | 2 +- packages/nux/CHANGELOG.md | 2 ++ packages/nux/package.json | 2 +- packages/patterns/CHANGELOG.md | 2 ++ packages/patterns/package.json | 2 +- packages/plugins/CHANGELOG.md | 2 ++ packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/CHANGELOG.md | 2 ++ packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/CHANGELOG.md | 2 ++ packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/CHANGELOG.md | 2 ++ packages/preferences-persistence/package.json | 2 +- packages/preferences/CHANGELOG.md | 2 ++ packages/preferences/package.json | 2 +- packages/prettier-config/CHANGELOG.md | 2 ++ packages/prettier-config/package.json | 2 +- packages/primitives/CHANGELOG.md | 2 ++ packages/primitives/package.json | 2 +- packages/priority-queue/CHANGELOG.md | 2 ++ packages/priority-queue/package.json | 2 +- packages/private-apis/CHANGELOG.md | 2 ++ packages/private-apis/package.json | 2 +- packages/project-management-automation/CHANGELOG.md | 2 ++ packages/project-management-automation/package.json | 2 +- packages/react-i18n/CHANGELOG.md | 2 ++ packages/react-i18n/package.json | 2 +- packages/readable-js-assets-webpack-plugin/CHANGELOG.md | 2 ++ packages/readable-js-assets-webpack-plugin/package.json | 2 +- packages/redux-routine/CHANGELOG.md | 2 ++ packages/redux-routine/package.json | 2 +- packages/reusable-blocks/CHANGELOG.md | 2 ++ packages/reusable-blocks/package.json | 2 +- packages/rich-text/CHANGELOG.md | 2 ++ packages/rich-text/package.json | 2 +- packages/router/CHANGELOG.md | 2 ++ packages/router/package.json | 2 +- packages/scripts/CHANGELOG.md | 2 ++ packages/scripts/package.json | 2 +- packages/server-side-render/CHANGELOG.md | 2 ++ packages/server-side-render/package.json | 2 +- packages/shortcode/CHANGELOG.md | 2 ++ packages/shortcode/package.json | 2 +- packages/style-engine/CHANGELOG.md | 2 ++ packages/style-engine/package.json | 2 +- packages/stylelint-config/CHANGELOG.md | 2 ++ packages/stylelint-config/package.json | 2 +- packages/sync/CHANGELOG.md | 2 ++ packages/sync/package.json | 2 +- packages/token-list/CHANGELOG.md | 2 ++ packages/token-list/package.json | 2 +- packages/undo-manager/CHANGELOG.md | 2 ++ packages/undo-manager/package.json | 2 +- packages/url/CHANGELOG.md | 2 ++ packages/url/package.json | 2 +- packages/viewport/CHANGELOG.md | 2 ++ packages/viewport/package.json | 2 +- packages/warning/CHANGELOG.md | 2 ++ packages/warning/package.json | 2 +- packages/widgets/CHANGELOG.md | 2 ++ packages/widgets/package.json | 2 +- packages/wordcount/CHANGELOG.md | 2 ++ packages/wordcount/package.json | 2 +- 190 files changed, 285 insertions(+), 95 deletions(-) diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index 21b652007a5054..3253a926865bd1 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 8490040f7cc038..8db1edd2968f98 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/CHANGELOG.md b/packages/annotations/CHANGELOG.md index cf66e51c07fd38..a8a78b900448f3 100644 --- a/packages/annotations/CHANGELOG.md +++ b/packages/annotations/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.4.0 (2024-07-24) + ## 3.3.0 (2024-07-10) ## 3.2.0 (2024-06-26) diff --git a/packages/annotations/package.json b/packages/annotations/package.json index dc02bda978dcf2..91521f18a31f34 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.3.0", + "version": "3.4.0-prerelease", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/CHANGELOG.md b/packages/api-fetch/CHANGELOG.md index cee6a82f04f24c..f55dea9482a288 100644 --- a/packages/api-fetch/CHANGELOG.md +++ b/packages/api-fetch/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.4.0 (2024-07-24) + ## 7.3.0 (2024-07-10) ## 7.2.0 (2024-06-26) diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 81c479cca7a02e..1a7a212179cab8 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.3.0", + "version": "7.4.0-prerelease", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/CHANGELOG.md b/packages/autop/CHANGELOG.md index 7c2d08b9121cc4..a039d571429dba 100644 --- a/packages/autop/CHANGELOG.md +++ b/packages/autop/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/autop/package.json b/packages/autop/package.json index 3a0e732001760a..32b03fd1e30f89 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md index 8503a9df98cb7b..f99035b53ad4f2 100644 --- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md +++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index 98612895b03d6f..b77eb8faf29cc3 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/CHANGELOG.md b/packages/babel-plugin-makepot/CHANGELOG.md index 9411389ef00995..4d876ac3629bc8 100644 --- a/packages/babel-plugin-makepot/CHANGELOG.md +++ b/packages/babel-plugin-makepot/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.4.0 (2024-07-24) + ## 6.3.0 (2024-07-10) ## 6.2.0 (2024-06-26) diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index aac782362c2226..f01f6d026faefd 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.3.0", + "version": "6.4.0-prerelease", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index d6ec60b7fd3d9a..ed74690aef3a17 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.4.0 (2024-07-24) + ## 8.3.0 (2024-07-10) ## 8.2.0 (2024-06-26) diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index a6beb303d0bc59..96f4ab4eb0046b 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.3.0", + "version": "8.4.0-prerelease", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/CHANGELOG.md b/packages/base-styles/CHANGELOG.md index 6bcaabfa640cef..48e715441a86ff 100644 --- a/packages/base-styles/CHANGELOG.md +++ b/packages/base-styles/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index 0e347ecbc8ad10..debf2cd5fe464a 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md index a103ab71a5cd87..9963ce05042c70 100644 --- a/packages/blob/CHANGELOG.md +++ b/packages/blob/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/blob/package.json b/packages/blob/package.json index 7e9965514570f5..ab711104b67407 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/CHANGELOG.md b/packages/block-directory/CHANGELOG.md index 1f1f3104764e61..99d27f9b06ca0d 100644 --- a/packages/block-directory/CHANGELOG.md +++ b/packages/block-directory/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 09d409d3f94ce4..388f4e97619326 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 02512ed4288abb..11cc15c15f0b05 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 13.4.0 (2024-07-24) + ## 13.3.0 (2024-07-10) ## 13.2.0 (2024-06-26) diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index e8c1f2cf063654..f2d521bb089a06 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "13.3.0", + "version": "13.4.0-prerelease", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index 8200d6005fe9a6..226183e04396ef 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.4.0 (2024-07-24) + ## 9.3.0 (2024-07-10) ## 9.2.0 (2024-06-26) diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 9102e822e59d1c..7a56e4ff6fddd2 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.3.0", + "version": "9.4.0-prerelease", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/CHANGELOG.md b/packages/block-serialization-default-parser/CHANGELOG.md index e03be10bf1ef88..e8c14374606de4 100644 --- a/packages/block-serialization-default-parser/CHANGELOG.md +++ b/packages/block-serialization-default-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index cecbecde177718..69c5ec82249947 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/CHANGELOG.md b/packages/block-serialization-spec-parser/CHANGELOG.md index d150b6a0333dfd..0b9d0e9922ecc6 100644 --- a/packages/block-serialization-spec-parser/CHANGELOG.md +++ b/packages/block-serialization-spec-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 6a9ca868a938fb..99ed5ecd2cbca1 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 618a6015ce00e2..1f77b933104583 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 13.4.0 (2024-07-24) + ## 13.3.0 (2024-07-10) ## 13.2.0 (2024-06-26) diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 89dad22f8041e3..109e7acebe527c 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.3.0", + "version": "13.4.0-prerelease", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/CHANGELOG.md b/packages/browserslist-config/CHANGELOG.md index 39283b8e3aa38e..538af854cef48f 100644 --- a/packages/browserslist-config/CHANGELOG.md +++ b/packages/browserslist-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.4.0 (2024-07-24) + ## 6.3.0 (2024-07-10) ## 6.2.0 (2024-06-26) diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index d5365f24c58b4f..11cddebd896488 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.3.0", + "version": "6.4.0-prerelease", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/CHANGELOG.md b/packages/commands/CHANGELOG.md index 0225c5b3697497..2a4b22bb9880a2 100644 --- a/packages/commands/CHANGELOG.md +++ b/packages/commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.4.0 (2024-07-24) + ## 1.3.0 (2024-07-10) ## 1.2.0 (2024-06-26) diff --git a/packages/commands/package.json b/packages/commands/package.json index c6e47a15f57c77..e05c2bb3d84eba 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.3.0", + "version": "1.4.0-prerelease", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index aa11a7c90e2632..a05ebab3783b8e 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 28.4.0 (2024-07-24) + ### Deprecations - `FormTokenField`: Deprecate bottom margin. Add a `__nextHasNoMarginBottom` prop to start opting into the margin-free styles that will become the default in a future version, currently scheduled to be WordPress 7.0 ([#63491](https://github.com/WordPress/gutenberg/pull/63491)). diff --git a/packages/components/package.json b/packages/components/package.json index 626b80d6ff7ac4..f3edc0ce1e48e8 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.3.0", + "version": "28.4.0-prerelease", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index f508fa376cbe8c..b5dd1d8712215d 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.4.0 (2024-07-24) + ## 7.3.0 (2024-07-10) ### Internal diff --git a/packages/compose/package.json b/packages/compose/package.json index 8a813ad58193d4..c3da5fb2a34ca9 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.3.0", + "version": "7.4.0-prerelease", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/CHANGELOG.md b/packages/core-commands/CHANGELOG.md index a8b6881e1e4b1e..aab5f1ea832f17 100644 --- a/packages/core-commands/CHANGELOG.md +++ b/packages/core-commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.4.0 (2024-07-24) + ## 1.3.0 (2024-07-10) ## 1.2.0 (2024-06-26) diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 50b31ca327b282..7fd829fb21ee14 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.3.0", + "version": "1.4.0-prerelease", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md index 5e5af54f0751e2..4712b66b8797b6 100644 --- a/packages/core-data/CHANGELOG.md +++ b/packages/core-data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.4.0 (2024-07-24) + ## 7.3.0 (2024-07-10) ## 7.2.0 (2024-06-26) diff --git a/packages/core-data/package.json b/packages/core-data/package.json index bed2ca97791bc5..14e90786e1482f 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.3.0", + "version": "7.4.0-prerelease", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/CHANGELOG.md b/packages/create-block-interactive-template/CHANGELOG.md index e4e54865beb6be..9f3b063c6fe9b3 100644 --- a/packages/create-block-interactive-template/CHANGELOG.md +++ b/packages/create-block-interactive-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.4.0 (2024-07-24) + ## 2.3.0 (2024-07-10) ## 2.2.0 (2024-06-26) diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index c1b10109ed226a..0afe56bd03d05c 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.3.0", + "version": "2.4.0-prerelease", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/CHANGELOG.md b/packages/create-block-tutorial-template/CHANGELOG.md index 1181037e73f392..a1ee507eb80163 100644 --- a/packages/create-block-tutorial-template/CHANGELOG.md +++ b/packages/create-block-tutorial-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index 095be8e8ca851f..ae126267debfdd 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index bcb86a1a377621..3d4cd14732192b 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.47.0 (2024-07-24) + ## 4.46.0 (2024-07-10) ## 4.45.0 (2024-06-26) diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 51f43884c54976..fff4b6bd1f5e7a 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.46.0", + "version": "4.47.0-prerelease", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/CHANGELOG.md b/packages/customize-widgets/CHANGELOG.md index 362f67c48ae39f..42bc3b04f4c0e1 100644 --- a/packages/customize-widgets/CHANGELOG.md +++ b/packages/customize-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index b68a9cf232a17a..0c175969c5bb25 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/CHANGELOG.md b/packages/data-controls/CHANGELOG.md index 5ea9633e90217d..e01b3f59bea50b 100644 --- a/packages/data-controls/CHANGELOG.md +++ b/packages/data-controls/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 6a6dfc2fc09395..54a97111edf4fa 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index 2de51f1f81539a..9789b91dfea0ea 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.4.0 (2024-07-24) + ## 10.3.0 (2024-07-10) ## 10.2.0 (2024-06-26) diff --git a/packages/data/package.json b/packages/data/package.json index a99cee1cc469e6..9a8efb07939327 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.3.0", + "version": "10.4.0-prerelease", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index bf7f54f009522f..2fc569b44f634c 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.0.0 (2024-07-24) + ### Breaking Changes - `onSelectionChange` prop has been renamed to `onChangeSelection` and its argument has been updated to be a list of ids. diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index f74bb3a8b06781..57ac21e01b750a 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "3.0.0", + "version": "4.0.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md index abdd53564ae393..b5177ac190c5d3 100644 --- a/packages/date/CHANGELOG.md +++ b/packages/date/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/date/package.json b/packages/date/package.json index 6f3c0635fd80b2..f84894b075b3c5 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index 7c4e8a2f11fc57..53e1853d8857b2 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.4.0 (2024-07-24) + ## 6.3.0 (2024-07-10) ## 6.2.0 (2024-06-26) diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index e6b87c139dfc7f..c9635d0d8da6ed 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.3.0", + "version": "6.4.0-prerelease", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/CHANGELOG.md b/packages/deprecated/CHANGELOG.md index 99bda5a0ebff78..89e574358a5225 100644 --- a/packages/deprecated/CHANGELOG.md +++ b/packages/deprecated/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 138157708832d4..52d28d2479da91 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/CHANGELOG.md b/packages/docgen/CHANGELOG.md index eb49321e39292e..5279dccdb4c51f 100644 --- a/packages/docgen/CHANGELOG.md +++ b/packages/docgen/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.4.0 (2024-07-24) + ## 2.3.0 (2024-07-10) ### Bug Fixes diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 1b146ca77e2a9c..3907cb28f2647c 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.3.0", + "version": "2.4.0-prerelease", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/CHANGELOG.md b/packages/dom-ready/CHANGELOG.md index 1f4eabcc342b1c..3e63c4440ae6fd 100644 --- a/packages/dom-ready/CHANGELOG.md +++ b/packages/dom-ready/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 9483e1b505934a..8198a36147b80f 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/CHANGELOG.md b/packages/dom/CHANGELOG.md index 07693c6749b387..cf5f09613f3154 100644 --- a/packages/dom/CHANGELOG.md +++ b/packages/dom/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/dom/package.json b/packages/dom/package.json index b32408660b4aee..3ce46947e4dcdd 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/CHANGELOG.md b/packages/e2e-test-utils-playwright/CHANGELOG.md index b94ad492dee910..e19452d1e49264 100644 --- a/packages/e2e-test-utils-playwright/CHANGELOG.md +++ b/packages/e2e-test-utils-playwright/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.4.0 (2024-07-24) + ## 1.3.0 (2024-07-10) ## 1.2.0 (2024-06-26) diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 0c65a81abe9cf2..d116dbdb35759f 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.3.0", + "version": "1.4.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index 631b79596b3f5b..fec97ba250f536 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 11.4.0 (2024-07-24) + ## 11.3.0 (2024-07-10) ## 11.2.0 (2024-06-26) diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index 7537a45e59fe51..118e396a83e5ef 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.3.0", + "version": "11.4.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md index 374df352694ed1..e89296d6606e15 100644 --- a/packages/e2e-tests/CHANGELOG.md +++ b/packages/e2e-tests/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.4.0 (2024-07-24) + ## 8.3.0 (2024-07-10) ## 8.2.0 (2024-06-26) diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 825119d324384b..e78c9143d07316 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.3.0", + "version": "8.4.0-prerelease", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index 4106e21a7afa6e..9542749c9d8463 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.4.0 (2024-07-24) + ## 8.3.0 (2024-07-10) ## 8.2.0 (2024-06-26) diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index a54d9fb9fa4f39..5d6d66588536f8 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.3.0", + "version": "8.4.0-prerelease", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/CHANGELOG.md b/packages/edit-site/CHANGELOG.md index 10c2706a8634a5..1990f26bce3ffb 100644 --- a/packages/edit-site/CHANGELOG.md +++ b/packages/edit-site/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.4.0 (2024-07-24) + ## 6.3.0 (2024-07-10) ## 6.2.0 (2024-06-26) diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 9e7b641aca96e3..9dfe4e82d66155 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.3.0", + "version": "6.4.0-prerelease", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/CHANGELOG.md b/packages/edit-widgets/CHANGELOG.md index 9eb8a706907639..edb26e6c38c1a8 100644 --- a/packages/edit-widgets/CHANGELOG.md +++ b/packages/edit-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.4.0 (2024-07-24) + ## 6.3.0 (2024-07-10) ## 6.2.0 (2024-06-26) diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index f3db642de980ea..f305e8439a823b 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.3.0", + "version": "6.4.0-prerelease", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index 61bc9b796768ba..a5fce0d1f736ad 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.4.0 (2024-07-24) + ### Deprecations - `PostTaxonomiesFlatTermSelector`: Deprecate bottom margin. Add a `__nextHasNoMarginBottom` prop to start opting into the margin-free styles that will become the default in a future version, currently scheduled to be WordPress 7.0 ([#63491](https://github.com/WordPress/gutenberg/pull/63491)). diff --git a/packages/editor/package.json b/packages/editor/package.json index 76ac714a7338b6..3c3b31729d9086 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.3.0", + "version": "14.4.0-prerelease", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/CHANGELOG.md b/packages/element/CHANGELOG.md index 9ee55cb98022ef..f81c95ef6eb24e 100644 --- a/packages/element/CHANGELOG.md +++ b/packages/element/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.4.0 (2024-07-24) + ## 6.3.0 (2024-07-10) ## 6.2.0 (2024-06-26) diff --git a/packages/element/package.json b/packages/element/package.json index 62a4d91692c545..fde27004b29f7d 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.3.0", + "version": "6.4.0-prerelease", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md index 25e554a1bec097..5e979941fb892d 100644 --- a/packages/env/CHANGELOG.md +++ b/packages/env/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.4.0 (2024-07-24) + ## 10.3.0 (2024-07-10) ### Bug Fixes diff --git a/packages/env/package.json b/packages/env/package.json index 90c434bdc9e29c..ff759ae9d01717 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.3.0", + "version": "10.4.0-prerelease", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/CHANGELOG.md b/packages/escape-html/CHANGELOG.md index 913c0d566911a6..02d7e2bf83a567 100644 --- a/packages/escape-html/CHANGELOG.md +++ b/packages/escape-html/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.4.0 (2024-07-24) + ## 3.3.0 (2024-07-10) ## 3.2.0 (2024-06-26) diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index d10551ea3b58dc..c781cf7baa232b 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.3.0", + "version": "3.4.0-prerelease", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 02f7c559d8e49a..fb9a16a011a9cf 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 20.1.0 (2024-07-24) + ## 20.0.0 (2024-07-10) ### Breaking Changes diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 166754c8b755ce..f646be5934c240 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "20.0.0", + "version": "20.1.0-prerelease", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/CHANGELOG.md b/packages/format-library/CHANGELOG.md index 27eb96102391cc..6d255d2b0b4b10 100644 --- a/packages/format-library/CHANGELOG.md +++ b/packages/format-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/format-library/package.json b/packages/format-library/package.json index 11e27b3c1859e8..7b152bdb3f2b9e 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/CHANGELOG.md b/packages/hooks/CHANGELOG.md index a72477e2adf785..cd6b23c1609bb3 100644 --- a/packages/hooks/CHANGELOG.md +++ b/packages/hooks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 28e6b3d1bf879c..9d28f5ebe8d276 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/CHANGELOG.md b/packages/html-entities/CHANGELOG.md index 6f159133f409e0..0e586385970454 100644 --- a/packages/html-entities/CHANGELOG.md +++ b/packages/html-entities/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 858bfd949ba8b9..7ab7c20bdc4511 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index 53c52849eef2c4..abe87d0edd1280 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/i18n/package.json b/packages/i18n/package.json index b2196f9a519aaf..b84beb270a9356 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index b3de660c72f1df..da4a4f1768fb19 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.4.0 (2024-07-24) + ## 10.3.0 (2024-07-10) ## 10.2.0 (2024-06-26) diff --git a/packages/icons/package.json b/packages/icons/package.json index 0bd6fd92b543c7..3d16c2b1673b24 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.3.0", + "version": "10.4.0-prerelease", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/CHANGELOG.md b/packages/interactivity-router/CHANGELOG.md index 21d37aa10323f4..97cd7f368bcbad 100644 --- a/packages/interactivity-router/CHANGELOG.md +++ b/packages/interactivity-router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.4.0 (2024-07-24) + ## 2.3.0 (2024-07-10) ## 2.2.0 (2024-06-26) diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index e0f940170a3c5a..4d22eb76c38d50 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.3.0", + "version": "2.4.0-prerelease", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index a8a5a5cd4c78bd..d592a5258c3c83 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.4.0 (2024-07-24) + ## 6.3.0 (2024-07-10) ## 6.2.0 (2024-06-26) diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 6e903400f4c9fc..08911a52b83dc4 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.3.0", + "version": "6.4.0-prerelease", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index 2ae331b934f239..18e36b68947b45 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.4.0 (2024-07-24) + ## 6.3.0 (2024-07-10) ## 6.2.0 (2024-06-26) diff --git a/packages/interface/package.json b/packages/interface/package.json index 949b67d41d1772..9875523a8562be 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "6.3.0", + "version": "6.4.0-prerelease", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/CHANGELOG.md b/packages/is-shallow-equal/CHANGELOG.md index 9ecfd8a34f18a2..92e7f633cd150a 100644 --- a/packages/is-shallow-equal/CHANGELOG.md +++ b/packages/is-shallow-equal/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index cf089d25a47606..64a429173834aa 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/CHANGELOG.md b/packages/jest-console/CHANGELOG.md index e1b003526d0a6c..3c85c40d1fe650 100644 --- a/packages/jest-console/CHANGELOG.md +++ b/packages/jest-console/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.4.0 (2024-07-24) + ## 8.3.0 (2024-07-10) ## 8.2.0 (2024-06-26) diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 76b8a336006897..2eeaa84f8cba24 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.3.0", + "version": "8.4.0-prerelease", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md index 0e5e91bc8f657e..726b351b71b529 100644 --- a/packages/jest-preset-default/CHANGELOG.md +++ b/packages/jest-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 12.4.0 (2024-07-24) + ## 12.3.0 (2024-07-10) ## 12.2.0 (2024-06-26) diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 9afd0cfe661e24..ecc866a78b55c3 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.3.0", + "version": "12.4.0-prerelease", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/CHANGELOG.md b/packages/jest-puppeteer-axe/CHANGELOG.md index c896ec074ddefd..14f2cf2e7ef525 100644 --- a/packages/jest-puppeteer-axe/CHANGELOG.md +++ b/packages/jest-puppeteer-axe/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.4.0 (2024-07-24) + ## 7.3.0 (2024-07-10) ## 7.2.0 (2024-06-26) diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index abb22fe7cf0159..a4fe8564e048b6 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.3.0", + "version": "7.4.0-prerelease", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/CHANGELOG.md b/packages/keyboard-shortcuts/CHANGELOG.md index 8e521528486c44..180e1af1be4a66 100644 --- a/packages/keyboard-shortcuts/CHANGELOG.md +++ b/packages/keyboard-shortcuts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 5e291239c0b016..3e5ee741281a1e 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/CHANGELOG.md b/packages/keycodes/CHANGELOG.md index fe4fdb6d428790..70d9c6065f1881 100644 --- a/packages/keycodes/CHANGELOG.md +++ b/packages/keycodes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 805472edec6fa6..80419873ba7958 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/CHANGELOG.md b/packages/lazy-import/CHANGELOG.md index 03b8020041d139..0db5de62639324 100644 --- a/packages/lazy-import/CHANGELOG.md +++ b/packages/lazy-import/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.4.0 (2024-07-24) + ## 2.3.0 (2024-07-10) ## 2.2.0 (2024-06-26) diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index e3d5765e3e2454..39a536376f4a09 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.3.0", + "version": "2.4.0-prerelease", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/CHANGELOG.md b/packages/list-reusable-blocks/CHANGELOG.md index 3261381bf62f28..c64693083af1f5 100644 --- a/packages/list-reusable-blocks/CHANGELOG.md +++ b/packages/list-reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 8295c1f955a433..7178c8559e0224 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/CHANGELOG.md b/packages/media-utils/CHANGELOG.md index 410e5199cc74a9..571fe227513ca6 100644 --- a/packages/media-utils/CHANGELOG.md +++ b/packages/media-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 24f1fc3df8ccd7..cf07686aed6d73 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/CHANGELOG.md b/packages/notices/CHANGELOG.md index 1dbe1fb9431202..8bd550869b8b34 100644 --- a/packages/notices/CHANGELOG.md +++ b/packages/notices/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/notices/package.json b/packages/notices/package.json index 31c7bcc4ad848e..7907826e4b4010 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/CHANGELOG.md b/packages/npm-package-json-lint-config/CHANGELOG.md index 727828442cc362..661d935ebab8b4 100644 --- a/packages/npm-package-json-lint-config/CHANGELOG.md +++ b/packages/npm-package-json-lint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index 851896019c7393..e20e726efd3a55 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/CHANGELOG.md b/packages/nux/CHANGELOG.md index 1e54a52b7dce2d..9c83baed0c0a80 100644 --- a/packages/nux/CHANGELOG.md +++ b/packages/nux/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.4.0 (2024-07-24) + ## 9.3.0 (2024-07-10) ## 9.2.0 (2024-06-26) diff --git a/packages/nux/package.json b/packages/nux/package.json index be907acc797cd5..b83b5b1d777bb6 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.3.0", + "version": "9.4.0-prerelease", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/CHANGELOG.md b/packages/patterns/CHANGELOG.md index c8eeedd7ae99cc..499b988bc66c98 100644 --- a/packages/patterns/CHANGELOG.md +++ b/packages/patterns/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.4.0 (2024-07-24) + ## 2.3.0 (2024-07-10) ## 2.2.0 (2024-06-26) diff --git a/packages/patterns/package.json b/packages/patterns/package.json index fceb55f0e79149..125a5d79f53c3f 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.3.0", + "version": "2.4.0-prerelease", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/CHANGELOG.md b/packages/plugins/CHANGELOG.md index 2d3de5542433e2..4135ab1b3a4b42 100644 --- a/packages/plugins/CHANGELOG.md +++ b/packages/plugins/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.4.0 (2024-07-24) + ## 7.3.0 (2024-07-10) ## 7.2.0 (2024-06-26) diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 53be8700309eb5..5c432d276e8239 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.3.0", + "version": "7.4.0-prerelease", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/CHANGELOG.md b/packages/postcss-plugins-preset/CHANGELOG.md index 4e5b1b682cd701..7a362b300fe71e 100644 --- a/packages/postcss-plugins-preset/CHANGELOG.md +++ b/packages/postcss-plugins-preset/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 897377b815d521..7fc10d3a5af80d 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/CHANGELOG.md b/packages/postcss-themes/CHANGELOG.md index 430ecbf6778c1c..5f200977e62ff4 100644 --- a/packages/postcss-themes/CHANGELOG.md +++ b/packages/postcss-themes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.4.0 (2024-07-24) + ## 6.3.0 (2024-07-10) ## 6.2.0 (2024-06-26) diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index d8f3ec25bbbc77..11c32e7ca3c044 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.3.0", + "version": "6.4.0-prerelease", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/CHANGELOG.md b/packages/preferences-persistence/CHANGELOG.md index 9bce8d892a7d41..b5bdc72282f80c 100644 --- a/packages/preferences-persistence/CHANGELOG.md +++ b/packages/preferences-persistence/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.4.0 (2024-07-24) + ## 2.3.0 (2024-07-10) ## 2.2.0 (2024-06-26) diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index 8c7c3cc2a3d60f..ed641d41897971 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.3.0", + "version": "2.4.0-prerelease", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/CHANGELOG.md b/packages/preferences/CHANGELOG.md index 8e11437def8997..2ebbd4ad386a9e 100644 --- a/packages/preferences/CHANGELOG.md +++ b/packages/preferences/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/preferences/package.json b/packages/preferences/package.json index ca0deefdbefb9d..5f504b79f1b2f5 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/CHANGELOG.md b/packages/prettier-config/CHANGELOG.md index b662a6ea503b2d..c3e02c3891f83a 100644 --- a/packages/prettier-config/CHANGELOG.md +++ b/packages/prettier-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 8e99f3a9a01167..6d0f54c1354221 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/CHANGELOG.md b/packages/primitives/CHANGELOG.md index a6788510a4cfdb..abba3f5140d3a6 100644 --- a/packages/primitives/CHANGELOG.md +++ b/packages/primitives/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/primitives/package.json b/packages/primitives/package.json index ed107037c8f68b..abac3521c5269b 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/CHANGELOG.md b/packages/priority-queue/CHANGELOG.md index 22527196f17c89..063fe05d667f08 100644 --- a/packages/priority-queue/CHANGELOG.md +++ b/packages/priority-queue/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.4.0 (2024-07-24) + ## 3.3.0 (2024-07-10) ## 3.2.0 (2024-06-26) diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index b342733a8a3a0f..76eaae09940835 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.3.0", + "version": "3.4.0-prerelease", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/CHANGELOG.md b/packages/private-apis/CHANGELOG.md index 76ba0b52193e63..169c9d8c4a588e 100644 --- a/packages/private-apis/CHANGELOG.md +++ b/packages/private-apis/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.4.0 (2024-07-24) + ## 1.3.0 (2024-07-10) ## 1.2.0 (2024-06-26) diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index de43e8aed09ebc..0bc8bd3dbb8bbb 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.3.0", + "version": "1.4.0-prerelease", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/CHANGELOG.md b/packages/project-management-automation/CHANGELOG.md index 2430748099fe1f..ca47a4ac381d9f 100644 --- a/packages/project-management-automation/CHANGELOG.md +++ b/packages/project-management-automation/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.4.0 (2024-07-24) + ## 2.3.0 (2024-07-10) ## 2.2.0 (2024-06-26) diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 09319250c968d2..47095d8700cda3 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.3.0", + "version": "2.4.0-prerelease", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/CHANGELOG.md b/packages/react-i18n/CHANGELOG.md index f50cefd3e3d82a..4907b55755640e 100644 --- a/packages/react-i18n/CHANGELOG.md +++ b/packages/react-i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 9f9af3992222fd..8b8a939d4a6f53 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md index b3c42bac7b5839..771067204bc156 100644 --- a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md +++ b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.4.0 (2024-07-24) + ## 3.3.0 (2024-07-10) ## 3.2.0 (2024-06-26) diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index aa8a7dacb6cedf..f804faf83d2411 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.3.0", + "version": "3.4.0-prerelease", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/CHANGELOG.md b/packages/redux-routine/CHANGELOG.md index adb0f764f5ed12..28f2162b322651 100644 --- a/packages/redux-routine/CHANGELOG.md +++ b/packages/redux-routine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 489c9ff75f72d4..d3747060f6deca 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/CHANGELOG.md b/packages/reusable-blocks/CHANGELOG.md index 0f460be3226b7a..37ae70f2cba977 100644 --- a/packages/reusable-blocks/CHANGELOG.md +++ b/packages/reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 756de894fa31eb..242f2f20280e46 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/CHANGELOG.md b/packages/rich-text/CHANGELOG.md index af5b2270d5aacc..25d2fe65213a50 100644 --- a/packages/rich-text/CHANGELOG.md +++ b/packages/rich-text/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.4.0 (2024-07-24) + ## 7.3.0 (2024-07-10) ## 7.2.0 (2024-06-26) diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 13d5404786ea2e..a2afcfc59c5321 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.3.0", + "version": "7.4.0-prerelease", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index a8b6881e1e4b1e..aab5f1ea832f17 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.4.0 (2024-07-24) + ## 1.3.0 (2024-07-10) ## 1.2.0 (2024-06-26) diff --git a/packages/router/package.json b/packages/router/package.json index 8df816f9dabdcb..14b8b9ca8a8884 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.3.0", + "version": "1.4.0-prerelease", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 0155cc24c1051c..2cb0cbbe408d65 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 28.4.0 (2024-07-24) + ### New Features - Update webpack configuration for the `build` and `start` commands to automatically copy PHP files listed in the `variations` field of `block.json` files from the source to the build folder ([#63098](https://github.com/WordPress/gutenberg/pull/63098)). diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 6f5218f7978f01..938ddddda69874 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "28.3.0", + "version": "28.4.0-prerelease", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/CHANGELOG.md b/packages/server-side-render/CHANGELOG.md index c54d277fc4ab43..a07a67682026e2 100644 --- a/packages/server-side-render/CHANGELOG.md +++ b/packages/server-side-render/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.4.0 (2024-07-24) + ## 5.3.0 (2024-07-10) ## 5.2.0 (2024-06-26) diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index add2de979fa33f..92dcbd97031f70 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.3.0", + "version": "5.4.0-prerelease", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/CHANGELOG.md b/packages/shortcode/CHANGELOG.md index abcd556a134ab8..ed64a536ee8df2 100644 --- a/packages/shortcode/CHANGELOG.md +++ b/packages/shortcode/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index 3e3899472bc9af..ca1377d80619b9 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md index 301583e4907314..aa2a6e8a62a7b9 100644 --- a/packages/style-engine/CHANGELOG.md +++ b/packages/style-engine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.4.0 (2024-07-24) + ## 2.3.0 (2024-07-10) ## 2.2.0 (2024-06-26) diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 5840efb5829871..966470c9195177 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.3.0", + "version": "2.4.0-prerelease", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/CHANGELOG.md b/packages/stylelint-config/CHANGELOG.md index 8c09b44c83e4b6..d2a5cba72d5ba3 100644 --- a/packages/stylelint-config/CHANGELOG.md +++ b/packages/stylelint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 22.4.0 (2024-07-24) + ## 22.3.0 (2024-07-10) ## 22.2.0 (2024-06-26) diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 16ae6b73089e0e..d4bb6c871bfa0e 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "22.3.0", + "version": "22.4.0-prerelease", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/CHANGELOG.md b/packages/sync/CHANGELOG.md index a862528c378168..dc4639d721cbd1 100644 --- a/packages/sync/CHANGELOG.md +++ b/packages/sync/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.4.0 (2024-07-24) + ## 1.3.0 (2024-07-10) ## 1.2.0 (2024-06-26) diff --git a/packages/sync/package.json b/packages/sync/package.json index 5e9309d4438387..74211bb271977a 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.3.0", + "version": "1.4.0-prerelease", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/CHANGELOG.md b/packages/token-list/CHANGELOG.md index c97123b4d1b9aa..7f70da2e813ee6 100644 --- a/packages/token-list/CHANGELOG.md +++ b/packages/token-list/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.4.0 (2024-07-24) + ## 3.3.0 (2024-07-10) ## 3.2.0 (2024-06-26) diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 74c2703f2cf970..9570e621482687 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.3.0", + "version": "3.4.0-prerelease", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/CHANGELOG.md b/packages/undo-manager/CHANGELOG.md index f60460fbadb469..2a8795039da055 100644 --- a/packages/undo-manager/CHANGELOG.md +++ b/packages/undo-manager/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.4.0 (2024-07-24) + ## 1.3.0 (2024-07-10) ## 1.2.0 (2024-06-26) diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 408a29486064bd..e60325dceb7139 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.3.0", + "version": "1.4.0-prerelease", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/CHANGELOG.md b/packages/url/CHANGELOG.md index b8be3e4a165c5d..46aeb33cd56d3a 100644 --- a/packages/url/CHANGELOG.md +++ b/packages/url/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/url/package.json b/packages/url/package.json index 0a811e11ec8d98..73e4d90a190286 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/CHANGELOG.md b/packages/viewport/CHANGELOG.md index 4edb8b45b7131d..5add422c56ebc2 100644 --- a/packages/viewport/CHANGELOG.md +++ b/packages/viewport/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.4.0 (2024-07-24) + ## 6.3.0 (2024-07-10) ## 6.2.0 (2024-06-26) diff --git a/packages/viewport/package.json b/packages/viewport/package.json index f40e83f6544012..649eea76d2e831 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.3.0", + "version": "6.4.0-prerelease", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/CHANGELOG.md b/packages/warning/CHANGELOG.md index b9b7baf8ed897f..9d0fea35fd7d82 100644 --- a/packages/warning/CHANGELOG.md +++ b/packages/warning/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.4.0 (2024-07-24) + ## 3.3.0 (2024-07-10) ## 3.2.0 (2024-06-26) diff --git a/packages/warning/package.json b/packages/warning/package.json index 1caf69bbf80d08..0bd319a2fb14f3 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.3.0", + "version": "3.4.0-prerelease", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/CHANGELOG.md b/packages/widgets/CHANGELOG.md index 4da550eb86f262..7ae2d9c4f32d22 100644 --- a/packages/widgets/CHANGELOG.md +++ b/packages/widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 0175fce56c12f0..effca125a027a2 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/CHANGELOG.md b/packages/wordcount/CHANGELOG.md index 4cdc465b01b221..58632ead7d0819 100644 --- a/packages/wordcount/CHANGELOG.md +++ b/packages/wordcount/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-07-24) + ## 4.3.0 (2024-07-10) ## 4.2.0 (2024-06-26) diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index 012d480d97f9ce..dae61d30010876 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From f28496737d503fb5395ba8543922596075485e4d Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 24 Jul 2024 17:28:58 +0000 Subject: [PATCH 0088/1908] chore(release): publish - @wordpress/a11y@4.4.0 - @wordpress/annotations@3.4.0 - @wordpress/api-fetch@7.4.0 - @wordpress/autop@4.4.0 - @wordpress/babel-plugin-import-jsx-pragma@5.4.0 - @wordpress/babel-plugin-makepot@6.4.0 - @wordpress/babel-preset-default@8.4.0 - @wordpress/base-styles@5.4.0 - @wordpress/blob@4.4.0 - @wordpress/block-directory@5.4.0 - @wordpress/block-editor@13.4.0 - @wordpress/block-library@9.4.0 - @wordpress/block-serialization-default-parser@5.4.0 - @wordpress/block-serialization-spec-parser@5.4.0 - @wordpress/blocks@13.4.0 - @wordpress/browserslist-config@6.4.0 - @wordpress/commands@1.4.0 - @wordpress/components@28.4.0 - @wordpress/compose@7.4.0 - @wordpress/core-commands@1.4.0 - @wordpress/core-data@7.4.0 - @wordpress/create-block@4.47.0 - @wordpress/create-block-interactive-template@2.4.0 - @wordpress/create-block-tutorial-template@4.4.0 - @wordpress/customize-widgets@5.4.0 - @wordpress/data@10.4.0 - @wordpress/data-controls@4.4.0 - @wordpress/dataviews@4.0.0 - @wordpress/date@5.4.0 - @wordpress/dependency-extraction-webpack-plugin@6.4.0 - @wordpress/deprecated@4.4.0 - @wordpress/docgen@2.4.0 - @wordpress/dom@4.4.0 - @wordpress/dom-ready@4.4.0 - @wordpress/e2e-test-utils@11.4.0 - @wordpress/e2e-test-utils-playwright@1.4.0 - @wordpress/e2e-tests@8.4.0 - @wordpress/edit-post@8.4.0 - @wordpress/edit-site@6.4.0 - @wordpress/edit-widgets@6.4.0 - @wordpress/editor@14.4.0 - @wordpress/element@6.4.0 - @wordpress/env@10.4.0 - @wordpress/escape-html@3.4.0 - @wordpress/eslint-plugin@20.1.0 - @wordpress/format-library@5.4.0 - @wordpress/hooks@4.4.0 - @wordpress/html-entities@4.4.0 - @wordpress/i18n@5.4.0 - @wordpress/icons@10.4.0 - @wordpress/interactivity@6.4.0 - @wordpress/interactivity-router@2.4.0 - @wordpress/interface@6.4.0 - @wordpress/is-shallow-equal@5.4.0 - @wordpress/jest-console@8.4.0 - @wordpress/jest-preset-default@12.4.0 - @wordpress/jest-puppeteer-axe@7.4.0 - @wordpress/keyboard-shortcuts@5.4.0 - @wordpress/keycodes@4.4.0 - @wordpress/lazy-import@2.4.0 - @wordpress/list-reusable-blocks@5.4.0 - @wordpress/media-utils@5.4.0 - @wordpress/notices@5.4.0 - @wordpress/npm-package-json-lint-config@5.4.0 - @wordpress/nux@9.4.0 - @wordpress/patterns@2.4.0 - @wordpress/plugins@7.4.0 - @wordpress/postcss-plugins-preset@5.4.0 - @wordpress/postcss-themes@6.4.0 - @wordpress/preferences@4.4.0 - @wordpress/preferences-persistence@2.4.0 - @wordpress/prettier-config@4.4.0 - @wordpress/primitives@4.4.0 - @wordpress/priority-queue@3.4.0 - @wordpress/private-apis@1.4.0 - @wordpress/project-management-automation@2.4.0 - @wordpress/react-i18n@4.4.0 - @wordpress/readable-js-assets-webpack-plugin@3.4.0 - @wordpress/redux-routine@5.4.0 - @wordpress/reusable-blocks@5.4.0 - @wordpress/rich-text@7.4.0 - @wordpress/router@1.4.0 - @wordpress/scripts@28.4.0 - @wordpress/server-side-render@5.4.0 - @wordpress/shortcode@4.4.0 - @wordpress/style-engine@2.4.0 - @wordpress/stylelint-config@22.4.0 - @wordpress/sync@1.4.0 - @wordpress/token-list@3.4.0 - @wordpress/undo-manager@1.4.0 - @wordpress/url@4.4.0 - @wordpress/viewport@6.4.0 - @wordpress/warning@3.4.0 - @wordpress/widgets@4.4.0 - @wordpress/wordcount@4.4.0 --- package-lock.json | 188 +++++++++--------- packages/a11y/package.json | 2 +- packages/annotations/package.json | 2 +- packages/api-fetch/package.json | 2 +- packages/autop/package.json | 2 +- .../package.json | 2 +- packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/package.json | 2 +- packages/base-styles/package.json | 2 +- packages/blob/package.json | 2 +- packages/block-directory/package.json | 2 +- packages/block-editor/package.json | 2 +- packages/block-library/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/blocks/package.json | 2 +- packages/browserslist-config/package.json | 2 +- packages/commands/package.json | 2 +- packages/components/package.json | 2 +- packages/compose/package.json | 2 +- packages/core-commands/package.json | 2 +- packages/core-data/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/create-block/package.json | 2 +- packages/customize-widgets/package.json | 2 +- packages/data-controls/package.json | 2 +- packages/data/package.json | 2 +- packages/dataviews/package.json | 2 +- packages/date/package.json | 2 +- .../package.json | 2 +- packages/deprecated/package.json | 2 +- packages/docgen/package.json | 2 +- packages/dom-ready/package.json | 2 +- packages/dom/package.json | 2 +- .../e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/package.json | 2 +- packages/edit-post/package.json | 2 +- packages/edit-site/package.json | 2 +- packages/edit-widgets/package.json | 2 +- packages/editor/package.json | 2 +- packages/element/package.json | 2 +- packages/env/package.json | 2 +- packages/escape-html/package.json | 2 +- packages/eslint-plugin/package.json | 2 +- packages/format-library/package.json | 2 +- packages/hooks/package.json | 2 +- packages/html-entities/package.json | 2 +- packages/i18n/package.json | 2 +- packages/icons/package.json | 2 +- packages/interactivity-router/package.json | 2 +- packages/interactivity/package.json | 2 +- packages/interface/package.json | 2 +- packages/is-shallow-equal/package.json | 2 +- packages/jest-console/package.json | 2 +- packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/package.json | 2 +- packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/package.json | 2 +- packages/notices/package.json | 2 +- .../npm-package-json-lint-config/package.json | 2 +- packages/nux/package.json | 2 +- packages/patterns/package.json | 2 +- packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/package.json | 2 +- packages/preferences/package.json | 2 +- packages/prettier-config/package.json | 2 +- packages/primitives/package.json | 2 +- packages/priority-queue/package.json | 2 +- packages/private-apis/package.json | 2 +- .../package.json | 2 +- packages/react-i18n/package.json | 2 +- .../package.json | 2 +- packages/redux-routine/package.json | 2 +- packages/reusable-blocks/package.json | 2 +- packages/rich-text/package.json | 2 +- packages/router/package.json | 2 +- packages/scripts/package.json | 2 +- packages/server-side-render/package.json | 2 +- packages/shortcode/package.json | 2 +- packages/style-engine/package.json | 2 +- packages/stylelint-config/package.json | 2 +- packages/sync/package.json | 2 +- packages/token-list/package.json | 2 +- packages/undo-manager/package.json | 2 +- packages/url/package.json | 2 +- packages/viewport/package.json | 2 +- packages/warning/package.json | 2 +- packages/widgets/package.json | 2 +- packages/wordcount/package.json | 2 +- 96 files changed, 189 insertions(+), 189 deletions(-) diff --git a/package-lock.json b/package-lock.json index 869f07dbbc55c1..6680025d768bef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52038,7 +52038,7 @@ }, "packages/a11y": { "name": "@wordpress/a11y", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52052,7 +52052,7 @@ }, "packages/annotations": { "name": "@wordpress/annotations", - "version": "3.3.0", + "version": "3.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52080,7 +52080,7 @@ }, "packages/api-fetch": { "name": "@wordpress/api-fetch", - "version": "7.3.0", + "version": "7.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52094,7 +52094,7 @@ }, "packages/autop": { "name": "@wordpress/autop", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52106,7 +52106,7 @@ }, "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.3.0", + "version": "5.4.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52119,7 +52119,7 @@ }, "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", - "version": "6.3.0", + "version": "6.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52137,7 +52137,7 @@ }, "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", - "version": "8.3.0", + "version": "8.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52160,7 +52160,7 @@ }, "packages/base-styles": { "name": "@wordpress/base-styles", - "version": "5.3.0", + "version": "5.4.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52170,7 +52170,7 @@ }, "packages/blob": { "name": "@wordpress/blob", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52182,7 +52182,7 @@ }, "packages/block-directory": { "name": "@wordpress/block-directory", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52217,7 +52217,7 @@ }, "packages/block-editor": { "name": "@wordpress/block-editor", - "version": "13.3.0", + "version": "13.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52314,7 +52314,7 @@ }, "packages/block-library": { "name": "@wordpress/block-library", - "version": "9.3.0", + "version": "9.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52380,7 +52380,7 @@ }, "packages/block-serialization-default-parser": { "name": "@wordpress/block-serialization-default-parser", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52392,7 +52392,7 @@ }, "packages/block-serialization-spec-parser": { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "pegjs": "^0.10.0", @@ -52405,7 +52405,7 @@ }, "packages/blocks": { "name": "@wordpress/blocks", - "version": "13.3.0", + "version": "13.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52459,7 +52459,7 @@ }, "packages/browserslist-config": { "name": "@wordpress/browserslist-config", - "version": "6.3.0", + "version": "6.4.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52469,7 +52469,7 @@ }, "packages/commands": { "name": "@wordpress/commands", - "version": "1.3.0", + "version": "1.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52642,7 +52642,7 @@ }, "packages/components": { "name": "@wordpress/components", - "version": "28.3.0", + "version": "28.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.3.12", @@ -52733,7 +52733,7 @@ }, "packages/compose": { "name": "@wordpress/compose", - "version": "7.3.0", + "version": "7.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52770,7 +52770,7 @@ }, "packages/core-commands": { "name": "@wordpress/core-commands", - "version": "1.3.0", + "version": "1.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52798,7 +52798,7 @@ }, "packages/core-data": { "name": "@wordpress/core-data", - "version": "7.3.0", + "version": "7.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52843,7 +52843,7 @@ }, "packages/create-block": { "name": "@wordpress/create-block", - "version": "4.46.0", + "version": "4.47.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52871,7 +52871,7 @@ }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", - "version": "4.3.0", + "version": "4.4.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52881,7 +52881,7 @@ }, "packages/customize-widgets": { "name": "@wordpress/customize-widgets", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52919,7 +52919,7 @@ }, "packages/data": { "name": "@wordpress/data", - "version": "10.3.0", + "version": "10.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52948,7 +52948,7 @@ }, "packages/data-controls": { "name": "@wordpress/data-controls", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52966,7 +52966,7 @@ }, "packages/dataviews": { "name": "@wordpress/dataviews", - "version": "3.0.0", + "version": "4.0.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.3.12", @@ -53027,7 +53027,7 @@ }, "packages/date": { "name": "@wordpress/date", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53042,7 +53042,7 @@ }, "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.3.0", + "version": "6.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53058,7 +53058,7 @@ }, "packages/deprecated": { "name": "@wordpress/deprecated", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53071,7 +53071,7 @@ }, "packages/docgen": { "name": "@wordpress/docgen", - "version": "2.3.0", + "version": "2.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53093,7 +53093,7 @@ }, "packages/dom": { "name": "@wordpress/dom", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53106,7 +53106,7 @@ }, "packages/dom-ready": { "name": "@wordpress/dom-ready", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53118,7 +53118,7 @@ }, "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", - "version": "11.3.0", + "version": "11.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53141,7 +53141,7 @@ }, "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.3.0", + "version": "1.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53169,7 +53169,7 @@ }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", - "version": "8.3.0", + "version": "8.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53209,7 +53209,7 @@ }, "packages/edit-post": { "name": "@wordpress/edit-post", - "version": "8.3.0", + "version": "8.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53256,7 +53256,7 @@ }, "packages/edit-site": { "name": "@wordpress/edit-site", - "version": "6.3.0", + "version": "6.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53318,7 +53318,7 @@ }, "packages/edit-widgets": { "name": "@wordpress/edit-widgets", - "version": "6.3.0", + "version": "6.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53361,7 +53361,7 @@ }, "packages/editor": { "name": "@wordpress/editor", - "version": "14.3.0", + "version": "14.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53422,7 +53422,7 @@ }, "packages/element": { "name": "@wordpress/element", - "version": "6.3.0", + "version": "6.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53441,7 +53441,7 @@ }, "packages/env": { "name": "@wordpress/env", - "version": "10.3.0", + "version": "10.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53583,7 +53583,7 @@ }, "packages/escape-html": { "name": "@wordpress/escape-html", - "version": "3.3.0", + "version": "3.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53595,7 +53595,7 @@ }, "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", - "version": "20.0.0", + "version": "20.1.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53638,7 +53638,7 @@ }, "packages/format-library": { "name": "@wordpress/format-library", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53666,7 +53666,7 @@ }, "packages/hooks": { "name": "@wordpress/hooks", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53678,7 +53678,7 @@ }, "packages/html-entities": { "name": "@wordpress/html-entities", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53690,7 +53690,7 @@ }, "packages/i18n": { "name": "@wordpress/i18n", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53710,7 +53710,7 @@ }, "packages/icons": { "name": "@wordpress/icons", - "version": "10.3.0", + "version": "10.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53724,7 +53724,7 @@ }, "packages/interactivity": { "name": "@wordpress/interactivity", - "version": "6.3.0", + "version": "6.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@preact/signals": "^1.2.2", @@ -53738,7 +53738,7 @@ }, "packages/interactivity-router": { "name": "@wordpress/interactivity-router", - "version": "2.3.0", + "version": "2.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/interactivity": "file:../interactivity" @@ -53799,7 +53799,7 @@ }, "packages/interface": { "name": "@wordpress/interface", - "version": "6.3.0", + "version": "6.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53828,7 +53828,7 @@ }, "packages/is-shallow-equal": { "name": "@wordpress/is-shallow-equal", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53840,7 +53840,7 @@ }, "packages/jest-console": { "name": "@wordpress/jest-console", - "version": "8.3.0", + "version": "8.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53857,7 +53857,7 @@ }, "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", - "version": "12.3.0", + "version": "12.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53875,7 +53875,7 @@ }, "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.3.0", + "version": "7.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53898,7 +53898,7 @@ }, "packages/keyboard-shortcuts": { "name": "@wordpress/keyboard-shortcuts", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53916,7 +53916,7 @@ }, "packages/keycodes": { "name": "@wordpress/keycodes", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53929,7 +53929,7 @@ }, "packages/lazy-import": { "name": "@wordpress/lazy-import", - "version": "2.3.0", + "version": "2.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53944,7 +53944,7 @@ }, "packages/list-reusable-blocks": { "name": "@wordpress/list-reusable-blocks", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53967,7 +53967,7 @@ }, "packages/media-utils": { "name": "@wordpress/media-utils", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53983,7 +53983,7 @@ }, "packages/notices": { "name": "@wordpress/notices", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54000,7 +54000,7 @@ }, "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.3.0", + "version": "5.4.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54013,7 +54013,7 @@ }, "packages/nux": { "name": "@wordpress/nux", - "version": "9.3.0", + "version": "9.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54036,7 +54036,7 @@ }, "packages/patterns": { "name": "@wordpress/patterns", - "version": "2.3.0", + "version": "2.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54066,7 +54066,7 @@ }, "packages/plugins": { "name": "@wordpress/plugins", - "version": "7.3.0", + "version": "7.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54089,7 +54089,7 @@ }, "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", - "version": "5.3.0", + "version": "5.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54106,7 +54106,7 @@ }, "packages/postcss-themes": { "name": "@wordpress/postcss-themes", - "version": "6.3.0", + "version": "6.4.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54119,7 +54119,7 @@ }, "packages/preferences": { "name": "@wordpress/preferences", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54145,7 +54145,7 @@ }, "packages/preferences-persistence": { "name": "@wordpress/preferences-persistence", - "version": "2.3.0", + "version": "2.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54158,7 +54158,7 @@ }, "packages/prettier-config": { "name": "@wordpress/prettier-config", - "version": "4.3.0", + "version": "4.4.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54171,7 +54171,7 @@ }, "packages/primitives": { "name": "@wordpress/primitives", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54185,7 +54185,7 @@ }, "packages/priority-queue": { "name": "@wordpress/priority-queue", - "version": "3.3.0", + "version": "3.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54198,7 +54198,7 @@ }, "packages/private-apis": { "name": "@wordpress/private-apis", - "version": "1.3.0", + "version": "1.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54210,7 +54210,7 @@ }, "packages/project-management-automation": { "name": "@wordpress/project-management-automation", - "version": "2.3.0", + "version": "2.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54240,7 +54240,7 @@ }, "packages/react-i18n": { "name": "@wordpress/react-i18n", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54396,7 +54396,7 @@ }, "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.3.0", + "version": "3.4.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54409,7 +54409,7 @@ }, "packages/redux-routine": { "name": "@wordpress/redux-routine", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54454,7 +54454,7 @@ }, "packages/reusable-blocks": { "name": "@wordpress/reusable-blocks", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54481,7 +54481,7 @@ }, "packages/rich-text": { "name": "@wordpress/rich-text", - "version": "7.3.0", + "version": "7.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54505,7 +54505,7 @@ }, "packages/router": { "name": "@wordpress/router", - "version": "1.3.0", + "version": "1.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54524,7 +54524,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "28.3.0", + "version": "28.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54978,7 +54978,7 @@ }, "packages/server-side-render": { "name": "@wordpress/server-side-render", - "version": "5.3.0", + "version": "5.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55004,7 +55004,7 @@ }, "packages/shortcode": { "name": "@wordpress/shortcode", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55017,7 +55017,7 @@ }, "packages/style-engine": { "name": "@wordpress/style-engine", - "version": "2.3.0", + "version": "2.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55030,7 +55030,7 @@ }, "packages/stylelint-config": { "name": "@wordpress/stylelint-config", - "version": "22.3.0", + "version": "22.4.0", "dev": true, "license": "MIT", "dependencies": { @@ -55047,7 +55047,7 @@ }, "packages/sync": { "name": "@wordpress/sync", - "version": "1.3.0", + "version": "1.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55068,7 +55068,7 @@ }, "packages/token-list": { "name": "@wordpress/token-list", - "version": "3.3.0", + "version": "3.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -55080,7 +55080,7 @@ }, "packages/undo-manager": { "name": "@wordpress/undo-manager", - "version": "1.3.0", + "version": "1.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55093,7 +55093,7 @@ }, "packages/url": { "name": "@wordpress/url", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55106,7 +55106,7 @@ }, "packages/viewport": { "name": "@wordpress/viewport", - "version": "6.3.0", + "version": "6.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55124,7 +55124,7 @@ }, "packages/warning": { "name": "@wordpress/warning", - "version": "3.3.0", + "version": "3.4.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55133,7 +55133,7 @@ }, "packages/widgets": { "name": "@wordpress/widgets", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55161,7 +55161,7 @@ }, "packages/wordcount": { "name": "@wordpress/wordcount", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 8db1edd2968f98..3af093baa98c91 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 91521f18a31f34..147b032d256498 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.4.0-prerelease", + "version": "3.4.0", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 1a7a212179cab8..ad48bede6c2029 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.4.0-prerelease", + "version": "7.4.0", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/package.json b/packages/autop/package.json index 32b03fd1e30f89..f96a7afc7887fe 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index b77eb8faf29cc3..2be402163fdffe 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index f01f6d026faefd..3ce5e4ac321f97 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.4.0-prerelease", + "version": "6.4.0", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 96f4ab4eb0046b..10792a258407f4 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.4.0-prerelease", + "version": "8.4.0", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index debf2cd5fe464a..ff59ac8cf960ed 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/package.json b/packages/blob/package.json index ab711104b67407..ca6820770afe08 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 388f4e97619326..20afdad09cb53b 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index f2d521bb089a06..aadf192f3016ec 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "13.4.0-prerelease", + "version": "13.4.0", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 7a56e4ff6fddd2..c1d27c8691f4fe 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.4.0-prerelease", + "version": "9.4.0", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 69c5ec82249947..de4f74925baf48 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 99ed5ecd2cbca1..84704630d117f7 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 109e7acebe527c..1d10cf69ec8926 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.4.0-prerelease", + "version": "13.4.0", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 11cddebd896488..2dd117762b9dbd 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.4.0-prerelease", + "version": "6.4.0", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/package.json b/packages/commands/package.json index e05c2bb3d84eba..53717ff871d2dc 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.4.0-prerelease", + "version": "1.4.0", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/package.json b/packages/components/package.json index f3edc0ce1e48e8..7c1b62f8bba22d 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.4.0-prerelease", + "version": "28.4.0", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/package.json b/packages/compose/package.json index c3da5fb2a34ca9..bc295a921bea5f 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.4.0-prerelease", + "version": "7.4.0", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 7fd829fb21ee14..bb9acc05139888 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.4.0-prerelease", + "version": "1.4.0", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 14e90786e1482f..3f4037f290a2c5 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.4.0-prerelease", + "version": "7.4.0", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index 0afe56bd03d05c..6f679fd47d90ea 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.4.0-prerelease", + "version": "2.4.0", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index ae126267debfdd..891fda996099eb 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/package.json b/packages/create-block/package.json index fff4b6bd1f5e7a..adaf06606d2550 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.47.0-prerelease", + "version": "4.47.0", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 0c175969c5bb25..ce53a53ea80dec 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 54a97111edf4fa..d3c670e5f0690a 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/package.json b/packages/data/package.json index 9a8efb07939327..a17b3cfd4f4b28 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.4.0-prerelease", + "version": "10.4.0", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index 57ac21e01b750a..238e2bdd5be8bc 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.0.0-prerelease", + "version": "4.0.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/package.json b/packages/date/package.json index f84894b075b3c5..d7ffeaa8417596 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index c9635d0d8da6ed..6146a8f562d05e 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.4.0-prerelease", + "version": "6.4.0", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 52d28d2479da91..515103487ca3cd 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 3907cb28f2647c..86ce19f84b4f9b 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.4.0-prerelease", + "version": "2.4.0", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 8198a36147b80f..76e2f12961a0e6 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/package.json b/packages/dom/package.json index 3ce46947e4dcdd..4b1f1ba634f9b5 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index d116dbdb35759f..d57f374cc979fa 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.4.0-prerelease", + "version": "1.4.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index 118e396a83e5ef..dee83cb79081c0 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.4.0-prerelease", + "version": "11.4.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index e78c9143d07316..b2ccca8dc14f2e 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.4.0-prerelease", + "version": "8.4.0", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 5d6d66588536f8..ee02f268ac1921 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.4.0-prerelease", + "version": "8.4.0", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 9dfe4e82d66155..f034b853c2cae1 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.4.0-prerelease", + "version": "6.4.0", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index f305e8439a823b..793e64f5d57caa 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.4.0-prerelease", + "version": "6.4.0", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/package.json b/packages/editor/package.json index 3c3b31729d9086..6c6a22cbbcd8c7 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.4.0-prerelease", + "version": "14.4.0", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/package.json b/packages/element/package.json index fde27004b29f7d..a5a85b145b51ba 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.4.0-prerelease", + "version": "6.4.0", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/package.json b/packages/env/package.json index ff759ae9d01717..354a41163c0ac2 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.4.0-prerelease", + "version": "10.4.0", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index c781cf7baa232b..0890a53b4e1743 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.4.0-prerelease", + "version": "3.4.0", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index f646be5934c240..77c9e2457b490e 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "20.1.0-prerelease", + "version": "20.1.0", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/package.json b/packages/format-library/package.json index 7b152bdb3f2b9e..5c5f80d1739b68 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 9d28f5ebe8d276..2bdf8ca3e5c933 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 7ab7c20bdc4511..313438e3b994c6 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/package.json b/packages/i18n/package.json index b84beb270a9356..96647dd7f64a40 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/package.json b/packages/icons/package.json index 3d16c2b1673b24..658e02ba74fa71 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.4.0-prerelease", + "version": "10.4.0", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 4d22eb76c38d50..212162a89ec6ed 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.4.0-prerelease", + "version": "2.4.0", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 08911a52b83dc4..835063ccc76992 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.4.0-prerelease", + "version": "6.4.0", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/package.json b/packages/interface/package.json index 9875523a8562be..cbc3a4229bd526 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "6.4.0-prerelease", + "version": "6.4.0", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 64a429173834aa..a92e70d21b6c7a 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 2eeaa84f8cba24..9775d4c7b7977d 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.4.0-prerelease", + "version": "8.4.0", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index ecc866a78b55c3..db5cf4cf8d7dd2 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.4.0-prerelease", + "version": "12.4.0", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index a4fe8564e048b6..2a16312d79764e 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.4.0-prerelease", + "version": "7.4.0", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 3e5ee741281a1e..d32cf232e17e5c 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 80419873ba7958..56a2c8dce89c97 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index 39a536376f4a09..6f0c5501387d47 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.4.0-prerelease", + "version": "2.4.0", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 7178c8559e0224..277ec1e991984c 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index cf07686aed6d73..59adc20770a5f8 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/package.json b/packages/notices/package.json index 7907826e4b4010..de6ba2f106e723 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index e20e726efd3a55..4c42423e14cd61 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/package.json b/packages/nux/package.json index b83b5b1d777bb6..c8bb71d1ce480f 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.4.0-prerelease", + "version": "9.4.0", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 125a5d79f53c3f..9f1a9c09fb405f 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.4.0-prerelease", + "version": "2.4.0", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 5c432d276e8239..7f2262c2487ed2 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.4.0-prerelease", + "version": "7.4.0", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 7fc10d3a5af80d..77e5e62a404631 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index 11c32e7ca3c044..51f78e5dc7d40d 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.4.0-prerelease", + "version": "6.4.0", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index ed641d41897971..81ff8d0a5452ef 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.4.0-prerelease", + "version": "2.4.0", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/package.json b/packages/preferences/package.json index 5f504b79f1b2f5..47c54e52512c28 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 6d0f54c1354221..33cd14c889db6c 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/package.json b/packages/primitives/package.json index abac3521c5269b..8536fa2fef3496 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 76eaae09940835..27eb90e14f5c44 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.4.0-prerelease", + "version": "3.4.0", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index 0bc8bd3dbb8bbb..4034d63c0a169b 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.4.0-prerelease", + "version": "1.4.0", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 47095d8700cda3..13aa49f5da6290 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.4.0-prerelease", + "version": "2.4.0", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 8b8a939d4a6f53..d3cb47c584dbb6 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index f804faf83d2411..fa04a7266d5d00 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.4.0-prerelease", + "version": "3.4.0", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index d3747060f6deca..2d43d16413efaf 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 242f2f20280e46..54985450b5dfb9 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index a2afcfc59c5321..5d62e30f06d1bc 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.4.0-prerelease", + "version": "7.4.0", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/package.json b/packages/router/package.json index 14b8b9ca8a8884..3173f0d51bbf7b 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.4.0-prerelease", + "version": "1.4.0", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 938ddddda69874..1ab69ea501be20 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "28.4.0-prerelease", + "version": "28.4.0", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index 92dcbd97031f70..1eaa215f097a70 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.4.0-prerelease", + "version": "5.4.0", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index ca1377d80619b9..b0db529cd58ec7 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 966470c9195177..54a340e50c2290 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.4.0-prerelease", + "version": "2.4.0", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index d4bb6c871bfa0e..5942073e683ce8 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "22.4.0-prerelease", + "version": "22.4.0", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/package.json b/packages/sync/package.json index 74211bb271977a..e4ecb8f39a5157 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.4.0-prerelease", + "version": "1.4.0", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 9570e621482687..1192c6f7103371 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.4.0-prerelease", + "version": "3.4.0", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index e60325dceb7139..2f945dbc53b653 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.4.0-prerelease", + "version": "1.4.0", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/package.json b/packages/url/package.json index 73e4d90a190286..c60ca2c661b9fa 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 649eea76d2e831..dbea04216570d9 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.4.0-prerelease", + "version": "6.4.0", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/package.json b/packages/warning/package.json index 0bd319a2fb14f3..980a1afcfb61c4 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.4.0-prerelease", + "version": "3.4.0", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/package.json b/packages/widgets/package.json index effca125a027a2..d302e63ee34cfb 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index dae61d30010876..e6579c01f2c5f9 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 69899cbb9485bec761a1a32506642ce37058bca7 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 24 Jul 2024 18:54:00 +0000 Subject: [PATCH 0089/1908] Update Changelog for 18.9.0-rc.1 --- changelog.txt | 422 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 422 insertions(+) diff --git a/changelog.txt b/changelog.txt index 8e63d9a2d1f44b..412d6184d76604 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,427 @@ == Changelog == += 18.9.0-rc.1 = + + +## Changelog + +### Features + +- change: Updated soundcloud icon for social link block. ([63504](https://github.com/WordPress/gutenberg/pull/63504)) + +#### Global Styles +- Adding Font size presets UI. ([63057](https://github.com/WordPress/gutenberg/pull/63057)) + + +### Enhancements + +- Background tool: Fix double border. ([63559](https://github.com/WordPress/gutenberg/pull/63559)) +- Core Data: Mark 'canUser' related actions resolvers as resolved. ([63435](https://github.com/WordPress/gutenberg/pull/63435)) +- Core Data: Resolve user capabilities when fetching an entity. ([63430](https://github.com/WordPress/gutenberg/pull/63430)) +- Core Data: Support entities in the 'canUser' selector. ([63322](https://github.com/WordPress/gutenberg/pull/63322)) +- Core Data: Support entity queries in the 'useResourcePermissions' hook. ([63653](https://github.com/WordPress/gutenberg/pull/63653)) +- DataViews: Update pagination icons. ([63594](https://github.com/WordPress/gutenberg/pull/63594)) +- Embeds: Add 'Embed' to title for clarity. ([63371](https://github.com/WordPress/gutenberg/pull/63371)) +- Polish "Delete" modal. ([63392](https://github.com/WordPress/gutenberg/pull/63392)) +- Run sync when issue is labeled with Sync Backport Changelog. ([63793](https://github.com/WordPress/gutenberg/pull/63793)) +- Update JSON Schemas to Draft 7. ([63583](https://github.com/WordPress/gutenberg/pull/63583)) +- Update: Grid layout: Allow users to adjust grid density. ([63367](https://github.com/WordPress/gutenberg/pull/63367)) +- Update: Include avatars on list view. ([63309](https://github.com/WordPress/gutenberg/pull/63309)) +- Update: List / Table layout – selected item stroke should be tinted blue. ([63312](https://github.com/WordPress/gutenberg/pull/63312)) +- Update: Make changing order an action on the ellipsis menu. ([62189](https://github.com/WordPress/gutenberg/pull/62189)) +- Update: Pages: Trash view should default to table layout try 2. ([63652](https://github.com/WordPress/gutenberg/pull/63652)) +- Update: Simplify some permission checks. ([63812](https://github.com/WordPress/gutenberg/pull/63812)) +- Use entity details when calling 'canUser' selectors. ([63415](https://github.com/WordPress/gutenberg/pull/63415)) + +#### Block Library +- Add Clear button for Overlay color option in Cover Block. ([63580](https://github.com/WordPress/gutenberg/pull/63580)) +- Columns block: Fix block preview. ([63609](https://github.com/WordPress/gutenberg/pull/63609)) +- Gallery: Add border block support. ([63428](https://github.com/WordPress/gutenberg/pull/63428)) +- Image block: Show placeholder when uploading HEIC files. ([63643](https://github.com/WordPress/gutenberg/pull/63643)) +- Latest comments: Add color block support. ([63419](https://github.com/WordPress/gutenberg/pull/63419)) +- Media Text: Add border support. ([63542](https://github.com/WordPress/gutenberg/pull/63542)) +- Polish create template part modal. ([63617](https://github.com/WordPress/gutenberg/pull/63617)) +- Post Author blocks: Add example and preview. ([62978](https://github.com/WordPress/gutenberg/pull/62978)) +- Post date block: Add a block example. ([63368](https://github.com/WordPress/gutenberg/pull/63368)) +- Post featured image: Add example of the block. ([63011](https://github.com/WordPress/gutenberg/pull/63011)) +- Post terms block: Add an example. ([63369](https://github.com/WordPress/gutenberg/pull/63369)) +- Query Loop Block: Remove Posts List variation. ([63404](https://github.com/WordPress/gutenberg/pull/63404)) +- Query Loop block: Convert the post content type setting to a ToggleGroupControl if there are few items. ([63375](https://github.com/WordPress/gutenberg/pull/63375)) +- Query Loop: Change default query loop variations. ([63353](https://github.com/WordPress/gutenberg/pull/63353)) +- Set query loop to have the inherit value by default. ([63362](https://github.com/WordPress/gutenberg/pull/63362)) +- Social Links: Add border block support. ([63629](https://github.com/WordPress/gutenberg/pull/63629)) +- Term Description: Add border block support. ([63630](https://github.com/WordPress/gutenberg/pull/63630)) + +#### Components +- CustomSelectControl V2 legacy adapter: Stabilize experimental props. ([63248](https://github.com/WordPress/gutenberg/pull/63248)) +- CustomSelectControl: Switch to ariakit-based implementation. ([63258](https://github.com/WordPress/gutenberg/pull/63258)) +- CustomSelectControlV2: Animate select popover appearance. ([63343](https://github.com/WordPress/gutenberg/pull/63343)) +- CustomSelectControlV2: Do not flip popover if legacy adapter. ([63357](https://github.com/WordPress/gutenberg/pull/63357)) +- DropdownMenuV2: Invert animation direction. ([63443](https://github.com/WordPress/gutenberg/pull/63443)) +- FontSizePicker: Tidy up internal logic. ([63553](https://github.com/WordPress/gutenberg/pull/63553)) +- FormTokenField: Deprecate bottom margin. ([63491](https://github.com/WordPress/gutenberg/pull/63491)) +- SelectControl: Add "minimal" variant. ([63265](https://github.com/WordPress/gutenberg/pull/63265)) +- Tabs: Hyphenate tab labels. ([63337](https://github.com/WordPress/gutenberg/pull/63337)) +- Tabs: Keep full opacity of focus ring on disabled tabs. ([63754](https://github.com/WordPress/gutenberg/pull/63754)) +- Update HeightControl component to label inputs. ([63761](https://github.com/WordPress/gutenberg/pull/63761)) + +#### Design Tools +- Background Image: Make panel appear in a consistent location. ([63551](https://github.com/WordPress/gutenberg/pull/63551)) +- Buttons: Add border, color, and padding block supports. ([63538](https://github.com/WordPress/gutenberg/pull/63538)) +- Heading: Add border support. ([63539](https://github.com/WordPress/gutenberg/pull/63539)) +- Image: Adopt margin block support. ([63546](https://github.com/WordPress/gutenberg/pull/63546)) +- Paragraph: Add border support. ([63543](https://github.com/WordPress/gutenberg/pull/63543)) +- Quote: Add border support. ([63544](https://github.com/WordPress/gutenberg/pull/63544)) +- Quote: Add spacing supports. ([63545](https://github.com/WordPress/gutenberg/pull/63545)) +- Search: Add margin support. ([63547](https://github.com/WordPress/gutenberg/pull/63547)) + +#### Data Views +- DataViews: Allow column re-ordering. ([63416](https://github.com/WordPress/gutenberg/pull/63416)) +- DataViews: Rename the header property of fields to label. ([63843](https://github.com/WordPress/gutenberg/pull/63843)) +- DataViews: Support combined fields. ([63236](https://github.com/WordPress/gutenberg/pull/63236)) +- Dataviews List: Update item layout. ([63299](https://github.com/WordPress/gutenberg/pull/63299)) +- Increase column-gap between fields in List layout. ([63603](https://github.com/WordPress/gutenberg/pull/63603)) +- Pages: Trash view should default to table layout. ([63138](https://github.com/WordPress/gutenberg/pull/63138)) +- Update 'Front page' badge. ([63752](https://github.com/WordPress/gutenberg/pull/63752)) + +#### Global Styles +- Add colors and typograpghy to the browse styles section. ([63173](https://github.com/WordPress/gutenberg/pull/63173)) +- Apply same styles to block previews on inserter and Global Styles. ([63177](https://github.com/WordPress/gutenberg/pull/63177)) +- Background: Add background attachment to top level styles. ([61382](https://github.com/WordPress/gutenberg/pull/61382)) +- Move background panel under color panel. ([63888](https://github.com/WordPress/gutenberg/pull/63888)) + +#### Block Editor +- Hide source filter in my patterns. ([63831](https://github.com/WordPress/gutenberg/pull/63831)) +- List View: Remove the sticky position icon tooltip. ([63850](https://github.com/WordPress/gutenberg/pull/63850)) +- Patterns: Render draggable only when enabled. ([63715](https://github.com/WordPress/gutenberg/pull/63715)) + +#### Post Editor +- Add post status icon in post summary. ([63658](https://github.com/WordPress/gutenberg/pull/63658)) +- Editor: Improve Header layout. ([62636](https://github.com/WordPress/gutenberg/pull/62636)) +- Post Actions: Use entity details for capability checks. ([63423](https://github.com/WordPress/gutenberg/pull/63423)) + +#### Font Library +- Group fonts by source. ([63211](https://github.com/WordPress/gutenberg/pull/63211)) +- Include a "Select All" options to activate/deactivate all fonts. ([63531](https://github.com/WordPress/gutenberg/pull/63531)) +- Reduce duplication of font library group headings. ([63532](https://github.com/WordPress/gutenberg/pull/63532)) + +#### Zoom Out +- Hide vertical toolbar when block is not full width. ([63650](https://github.com/WordPress/gutenberg/pull/63650)) +- Only show the inserters when a block is selected or hovered. ([63668](https://github.com/WordPress/gutenberg/pull/63668)) + +#### Block Locking +- Tweak Block Locking UI. ([63881](https://github.com/WordPress/gutenberg/pull/63881)) + +#### Icons +- Update close icon. ([63597](https://github.com/WordPress/gutenberg/pull/63597)) + +#### Block bindings +- Bootstrap sources defined in the server. ([63470](https://github.com/WordPress/gutenberg/pull/63470)) + +#### Site Editor +- Reduce navigation sidebar width. ([63431](https://github.com/WordPress/gutenberg/pull/63431)) + +#### Patterns +- Limit pattern shuffling to theme and user patterns only. ([62677](https://github.com/WordPress/gutenberg/pull/62677)) + + +### New APIs + +#### Block bindings +- Unify `getValue`/`getValues` and `setValue`/`setValues` APIs. ([63185](https://github.com/WordPress/gutenberg/pull/63185)) + + +### Bug Fixes + +- Add: Permission checks to avoid 403 errors on non admin roles. ([63296](https://github.com/WordPress/gutenberg/pull/63296)) +- DataViews: Do not render bulk actions Dropdown if no actions are available. ([63575](https://github.com/WordPress/gutenberg/pull/63575)) +- DataViews: Fix uncontrolled selection. ([63741](https://github.com/WordPress/gutenberg/pull/63741)) +- Disallow scrolling the block preview. ([63558](https://github.com/WordPress/gutenberg/pull/63558)) +- Discussions panel: Distinguish between verb and adjective form of open for internationalization. ([63791](https://github.com/WordPress/gutenberg/pull/63791)) +- Fix canvas issues by removing VisualEditor’s height. ([63724](https://github.com/WordPress/gutenberg/pull/63724)) +- Fix mobile styles for inserter pattern and media tab navigation. ([63451](https://github.com/WordPress/gutenberg/pull/63451)) +- Fix: Error while Calling edit-site getCurrentTemplateTemplateParts selector. ([63818](https://github.com/WordPress/gutenberg/pull/63818)) +- Footnotes: Register format within the init function. ([63554](https://github.com/WordPress/gutenberg/pull/63554)) +- InnerBlocks: Make sure blockType is set before trying to use it. ([63351](https://github.com/WordPress/gutenberg/pull/63351)) +- Prepare JSON schemas for Draft 7 update. ([63582](https://github.com/WordPress/gutenberg/pull/63582)) +- Revert "Pages: Trash view should default to table layout.". ([63481](https://github.com/WordPress/gutenberg/pull/63481)) +- Sync backport changelog action: Use outputs instead of env. ([63792](https://github.com/WordPress/gutenberg/pull/63792)) +- core-data: Fix `canUser` allowed methods handling. ([63615](https://github.com/WordPress/gutenberg/pull/63615)) +- useBlockElement: Return null until ref callback has time to clean up the old element. ([63565](https://github.com/WordPress/gutenberg/pull/63565)) + +#### Data Views +- DataViews: Fix default layouts in the pages data views. ([63427](https://github.com/WordPress/gutenberg/pull/63427)) +- DataViews: Fix featured image height regression. ([63424](https://github.com/WordPress/gutenberg/pull/63424)) +- DataViews: Fix field rendering. ([63452](https://github.com/WordPress/gutenberg/pull/63452)) +- DataViews: Fix pattens list selection. ([63733](https://github.com/WordPress/gutenberg/pull/63733)) +- DataViews: Only show elligible actions in the bulk editing menu. ([63473](https://github.com/WordPress/gutenberg/pull/63473)) +- Fix patterns sorting by `title`. ([63710](https://github.com/WordPress/gutenberg/pull/63710)) +- Fix selected row styles in table layout. ([63811](https://github.com/WordPress/gutenberg/pull/63811)) +- Fix: DataViews: Layout resets for patterns each time a new pattern category is selected. ([63711](https://github.com/WordPress/gutenberg/pull/63711)) +- Fix: Inconsistent field spacing in Grid layout. ([63363](https://github.com/WordPress/gutenberg/pull/63363)) +- Templates DataViews: Set the right context for the preview field. ([63488](https://github.com/WordPress/gutenberg/pull/63488)) + +#### Block Editor +- Fix user patterns disabling sync filter. ([63828](https://github.com/WordPress/gutenberg/pull/63828)) +- ImageURLInputUI: Make onSetLightbox and resetLightbox optional. ([63573](https://github.com/WordPress/gutenberg/pull/63573)) +- Pattern Inserter: Fix pagination layout when "Show button text labels" enabled. ([63466](https://github.com/WordPress/gutenberg/pull/63466)) +- Patterns inserter tabs: Temporary disable animated indicator. ([63352](https://github.com/WordPress/gutenberg/pull/63352)) +- Prevent empty void at the bottom of editor when block directory results are present. ([63397](https://github.com/WordPress/gutenberg/pull/63397)) +- Remove double shadow on Inserter category panel when zoomed out. ([63516](https://github.com/WordPress/gutenberg/pull/63516)) +- Tabs: Vertical Tabs should be 40px min height. ([63446](https://github.com/WordPress/gutenberg/pull/63446)) +- Zoom out mode: Translate toolbar delete button. ([63476](https://github.com/WordPress/gutenberg/pull/63476)) + +#### Block Library +- Avoid stripping attributes via group block migration when no layout is specified. ([63837](https://github.com/WordPress/gutenberg/pull/63837)) +- Fix default unit issue for tag cloud block. ([59122](https://github.com/WordPress/gutenberg/pull/59122)) +- Image lightbox: Remove duplicate image when lightbox is opened. ([63381](https://github.com/WordPress/gutenberg/pull/63381)) +- Query Loop: Fix 'block' scoped variations to get the `query` defaults. ([63477](https://github.com/WordPress/gutenberg/pull/63477)) +- Query Loop: Fix passing of `namespace` when selecting from suggested patterns. ([63402](https://github.com/WordPress/gutenberg/pull/63402)) +- Template Part: Add check if create action should be allowed. ([63623](https://github.com/WordPress/gutenberg/pull/63623)) +- Update Inherited Query Loop value from Template Settings changes. ([63358](https://github.com/WordPress/gutenberg/pull/63358)) + +#### Site Editor +- Fix error when duplicating a template part. ([63663](https://github.com/WordPress/gutenberg/pull/63663)) +- Fix: Add Template Modal layout in mobile view. ([63627](https://github.com/WordPress/gutenberg/pull/63627)) +- Make hover block outlines not present in Distraction Free. ([63819](https://github.com/WordPress/gutenberg/pull/63819)) +- Site Editor Navigation Commands: Add permission check. ([63798](https://github.com/WordPress/gutenberg/pull/63798)) +- fix: Wp icon focus issue. ([62675](https://github.com/WordPress/gutenberg/pull/62675)) + +#### Zoom Out +- Don't automatically show inserter when zoom out mode initiates. ([63859](https://github.com/WordPress/gutenberg/pull/63859)) +- Ensure that we only enter zoom out mode if the experiment is enabled. ([63417](https://github.com/WordPress/gutenberg/pull/63417)) +- Fix crash due to absence of selected block. ([63642](https://github.com/WordPress/gutenberg/pull/63642)) +- Fix vertical toolbar position. ([63745](https://github.com/WordPress/gutenberg/pull/63745)) + +#### Components +- Button: Never apply `aria-disabled` to anchor. ([63376](https://github.com/WordPress/gutenberg/pull/63376)) +- Revert "Update HeightControl component to label inputs". ([63839](https://github.com/WordPress/gutenberg/pull/63839)) +- SelectControl: Fix hover/focus color in wp-admin. ([63855](https://github.com/WordPress/gutenberg/pull/63855)) +- ToggleGroupControl: Support `disabled` options. ([63450](https://github.com/WordPress/gutenberg/pull/63450)) + +#### Global Styles +- Disable "Reset styles" button when there are no changes. ([63562](https://github.com/WordPress/gutenberg/pull/63562)) +- Ensure root selector (body) is not wrapped in :root :Where(). ([63726](https://github.com/WordPress/gutenberg/pull/63726)) +- Global styles block previews: Fix scaling. ([63596](https://github.com/WordPress/gutenberg/pull/63596)) +- Style variations: Don't display the default if its the only variation. ([63555](https://github.com/WordPress/gutenberg/pull/63555)) + +#### CSS & Styling +- Comments: Allow button element shadows from theme.json. ([63790](https://github.com/WordPress/gutenberg/pull/63790)) +- List: Prevent style bleed into non-List block lists. ([63537](https://github.com/WordPress/gutenberg/pull/63537)) +- Search: Prevent override of global button radii in editor. ([63789](https://github.com/WordPress/gutenberg/pull/63789)) + +#### Font Library +- Add 'No fonts installed' message on library tab when fonts aren't available. ([63740](https://github.com/WordPress/gutenberg/pull/63740)) +- Improve 'No fonts installed' state when fonts are installed but not activated. ([63533](https://github.com/WordPress/gutenberg/pull/63533)) + +#### Post Editor +- Allow editing of description only for custom templates. ([63664](https://github.com/WordPress/gutenberg/pull/63664)) + +#### Design Tools +- Background image block support: Fix dropzone size. ([63588](https://github.com/WordPress/gutenberg/pull/63588)) + +#### Layout +- Don't remount the block when rendering grid tools. ([63557](https://github.com/WordPress/gutenberg/pull/63557)) + +#### Block Transforms +- Block Switcher Preview: Adjust the position and enable pattern list preview in mobile viewport. ([63512](https://github.com/WordPress/gutenberg/pull/63512)) + +#### Block bindings +- Revert triggering multi-entity save panel in post with meta changes. ([63412](https://github.com/WordPress/gutenberg/pull/63412)) + +#### Block Directory +- Memoize store selectors. ([63346](https://github.com/WordPress/gutenberg/pull/63346)) + +#### Widgets Editor +- Widgets: Memoize 'getWidgets' store selector. ([63338](https://github.com/WordPress/gutenberg/pull/63338)) + +#### Synced Patterns +- Pattern overrides: Ensure "Reset" button always shows as last item and with border. ([63291](https://github.com/WordPress/gutenberg/pull/63291)) + +#### Patterns +- Fix: Removed shuffle button when only 1 pattern is present. ([63093](https://github.com/WordPress/gutenberg/pull/63093)) + +#### Media +- Lock post saving during image uploads. ([41120](https://github.com/WordPress/gutenberg/pull/41120)) + + +### Accessibility + +- Align checkbox, radio, and toggle input design. ([63490](https://github.com/WordPress/gutenberg/pull/63490)) + +#### Components +- Fix ComboboxControl reset button when using the keyboard. ([63410](https://github.com/WordPress/gutenberg/pull/63410)) + +#### Post Editor +- Add missing aria-haspopup attribute to the buttons to set and replace the featured image. ([63360](https://github.com/WordPress/gutenberg/pull/63360)) + +#### Block Library +- Show visual label for Categories block in dropdown mode. ([56364](https://github.com/WordPress/gutenberg/pull/56364)) + + +### Performance + +#### Components +- Storybook: Improve TypeScript performance for slow stories. ([63388](https://github.com/WordPress/gutenberg/pull/63388)) + + +### Experiments + +#### Layout +- Disable in-between inserter in Manual grids. ([63391](https://github.com/WordPress/gutenberg/pull/63391)) +- Don't display default appender inside Manual grid. ([63395](https://github.com/WordPress/gutenberg/pull/63395)) +- Fix responsive behaviour so both column start and column span are taken into account. ([63464](https://github.com/WordPress/gutenberg/pull/63464)) +- Grid: Better looking block movers. ([63394](https://github.com/WordPress/gutenberg/pull/63394)) +- Grid: Place new block after currently selected block when using slash inserter and splitting text. ([63333](https://github.com/WordPress/gutenberg/pull/63333)) +- Move visualizer popover to slot under the canvas. ([63389](https://github.com/WordPress/gutenberg/pull/63389)) + +#### Data Views +- Quick Edit: Support bulk selection. ([63841](https://github.com/WordPress/gutenberg/pull/63841)) + +#### Site Editor +- DataViews: Bootstrap Quick Edit. ([63600](https://github.com/WordPress/gutenberg/pull/63600)) + + +### Documentation + +- Add to code requirements install and import Interactivity API. ([63439](https://github.com/WordPress/gutenberg/pull/63439)) +- Alpine vs Preact extra explanations. ([63593](https://github.com/WordPress/gutenberg/pull/63593)) +- Backport docs: Update and format. ([63830](https://github.com/WordPress/gutenberg/pull/63830)) +- Create-block - fix - update default folder name to proper default. ([63530](https://github.com/WordPress/gutenberg/pull/63530)) +- DataForm: Add a simple story for the DataForm component. ([63840](https://github.com/WordPress/gutenberg/pull/63840)) +- Fix Typo in Interactivity Api Reference. ([63775](https://github.com/WordPress/gutenberg/pull/63775)) +- Fix typo in Autocomplete component README.md. ([63496](https://github.com/WordPress/gutenberg/pull/63496)) +- FontSizePicker: Fix documentation for default `units`. ([63577](https://github.com/WordPress/gutenberg/pull/63577)) +- Improve the base control help prop documentation. ([63693](https://github.com/WordPress/gutenberg/pull/63693)) +- JSON Schema Docgen Rework. ([63868](https://github.com/WordPress/gutenberg/pull/63868)) +- Mark unstable__bootstrapServerSideBlockDefinitions with @ignore. ([63673](https://github.com/WordPress/gutenberg/pull/63673)) +- Move entity-provider.js exports into hooks/index.ts so they are added to the documentation. ([63528](https://github.com/WordPress/gutenberg/pull/63528)) +- Small Typo in Experiment Page. ([63773](https://github.com/WordPress/gutenberg/pull/63773)) +- Storybook: Remove popover-related height buffers. ([63480](https://github.com/WordPress/gutenberg/pull/63480)) +- Update "Versions in WordPress" page. ([63869](https://github.com/WordPress/gutenberg/pull/63869)) +- Update dataviews documentation. ([63860](https://github.com/WordPress/gutenberg/pull/63860)) +- Update getContext() usage examples with namespace argument. ([63411](https://github.com/WordPress/gutenberg/pull/63411)) +- Update react reference links in developer documentation. ([62818](https://github.com/WordPress/gutenberg/pull/62818)) +- Update react reference links in package's readme and doc blocks. ([62704](https://github.com/WordPress/gutenberg/pull/62704)) +- Updated Useeffect URL. ([63494](https://github.com/WordPress/gutenberg/pull/63494)) + + +### Code Quality + +- Add margin-bottom lint rules for CheckboxControl, ComboboxControl, SearchControl. ([63679](https://github.com/WordPress/gutenberg/pull/63679)) +- Add margin-bottom lint rules for FocalPointPicker, TextareaControl, TreeSelect. ([63633](https://github.com/WordPress/gutenberg/pull/63633)) +- Add margin-bottom lint rules for RangeControl. ([63821](https://github.com/WordPress/gutenberg/pull/63821)) +- Block editor settings: Add missing global styles links dependencies. ([63823](https://github.com/WordPress/gutenberg/pull/63823)) +- Core Data: Remove leftover 'todo' comment. ([63842](https://github.com/WordPress/gutenberg/pull/63842)) +- Core Data: Use meta-store actions for resolution status. ([63469](https://github.com/WordPress/gutenberg/pull/63469)) +- DataViews: Move PostList component to its own folder. ([63334](https://github.com/WordPress/gutenberg/pull/63334)) +- JSON Schema Reorganization and Fixes. ([63591](https://github.com/WordPress/gutenberg/pull/63591)) +- Update: Simplify and do not pass renderingMode on editor SidebarContent. ([63814](https://github.com/WordPress/gutenberg/pull/63814)) +- Use Base Focus Styles for Region Focus. ([62881](https://github.com/WordPress/gutenberg/pull/62881)) +- Use static 'key' when filtering BlockEdit components. ([63590](https://github.com/WordPress/gutenberg/pull/63590)) + +#### Block Library +- Image block: Remove unnecessary variables on expand on click implementation. ([63290](https://github.com/WordPress/gutenberg/pull/63290)) +- Image lightbox: Move image data from context to state. ([63348](https://github.com/WordPress/gutenberg/pull/63348)) +- Navigation Submenu: Remove user permission checks. ([63720](https://github.com/WordPress/gutenberg/pull/63720)) +- Query Title block: Rely on the editor store to apply the right archive title placeholder. ([63478](https://github.com/WordPress/gutenberg/pull/63478)) +- Remove unused useSplit after #54543. ([63826](https://github.com/WordPress/gutenberg/pull/63826)) + +#### Data Views +- DataViews: Cleanup preview styles. ([63365](https://github.com/WordPress/gutenberg/pull/63365)) +- DataViews: Move the layouts into a dedicated folder. ([63409](https://github.com/WordPress/gutenberg/pull/63409)) +- DataViews: Refactor to prepare exposing the underlying UI pieces. ([63694](https://github.com/WordPress/gutenberg/pull/63694)) +- DataViews: Remove redundant setSelection prop. ([63648](https://github.com/WordPress/gutenberg/pull/63648)) +- DataViews: Rename `onSelectionChange` to `onChangeSelection`. ([63087](https://github.com/WordPress/gutenberg/pull/63087)) + +#### Components +- ColorPicker: Use `minimal` variant for SelectControl. ([63676](https://github.com/WordPress/gutenberg/pull/63676)) +- Rename Button describedBy prop to description and deprecate old name. ([63486](https://github.com/WordPress/gutenberg/pull/63486)) +- Tabs: Move animation-related utilities into separate utils file. ([62946](https://github.com/WordPress/gutenberg/pull/62946)) + +#### Block bindings +- Don't provide default `canUserEditValue` in reducer. ([63628](https://github.com/WordPress/gutenberg/pull/63628)) +- Improve how the context needed by sources is extended in the editor. ([63513](https://github.com/WordPress/gutenberg/pull/63513)) +- Improve the way block bindings sources are registered. ([63117](https://github.com/WordPress/gutenberg/pull/63117)) + +#### Post Editor +- Editor: Remove unused `setNestedValue` util. ([63620](https://github.com/WordPress/gutenberg/pull/63620)) +- Move useSelectNearestEditableBlock out of src/hooks. ([63730](https://github.com/WordPress/gutenberg/pull/63730)) + +#### Font Library +- Remove unused font library experiment. ([63890](https://github.com/WordPress/gutenberg/pull/63890)) + +#### Global Styles +- Remove unused global styles background screen. ([63887](https://github.com/WordPress/gutenberg/pull/63887)) + +#### Widgets Editor +- Widget Editor: Remove unused values returned from 'mapSelect'. ([63738](https://github.com/WordPress/gutenberg/pull/63738)) + +#### Block API +- Use `@wordpress/warning` during block registration instead of `console.error` and `console.warn`. ([63610](https://github.com/WordPress/gutenberg/pull/63610)) + +#### Synced Patterns +- Quality: Remove "reusable block name hint" code. ([63514](https://github.com/WordPress/gutenberg/pull/63514)) + +#### Commands +- Update cmdk. ([63465](https://github.com/WordPress/gutenberg/pull/63465)) + +#### Document Settings +- FlatTermSelector: Be more defensive about termIds. ([63461](https://github.com/WordPress/gutenberg/pull/63461)) + +#### Site Editor +- Deprecate 'getCanUserCreateMedia' selector. ([63413](https://github.com/WordPress/gutenberg/pull/63413)) + +#### Block Directory +- Remove 'edit-post' package dependency. ([63349](https://github.com/WordPress/gutenberg/pull/63349)) + + +### Tools + +- Bug: Eslint `recommended-with-formatting` allows for unnecessary spaces. ([63549](https://github.com/WordPress/gutenberg/pull/63549)) +- Issue template: Use checkboxes instead of dropdown. ([63523](https://github.com/WordPress/gutenberg/pull/63523)) +- Scripts: Include variations paths in build. ([63098](https://github.com/WordPress/gutenberg/pull/63098)) +- Scripts: Remove now-obsolete `getRenderPropPaths()`. ([63661](https://github.com/WordPress/gutenberg/pull/63661)) + +#### Testing +- Downgrade node 22(.5) unit tests to 22.4. ([63728](https://github.com/WordPress/gutenberg/pull/63728)) +- Font Library: Fix flaky end-to-end tests. ([63904](https://github.com/WordPress/gutenberg/pull/63904)) +- Upgrade Playwright to v1.45. ([61443](https://github.com/WordPress/gutenberg/pull/61443)) + +#### Build Tooling +- Fix broken license check script. ([61868](https://github.com/WordPress/gutenberg/pull/61868)) +- React: Restore umd builds. ([63602](https://github.com/WordPress/gutenberg/pull/63602)) + + +### Various + +- HTML API: Backport updates from Core. ([63723](https://github.com/WordPress/gutenberg/pull/63723)) +- Upgrade TypeScript to 5.5. ([63012](https://github.com/WordPress/gutenberg/pull/63012)) + +#### Block Editor +- Remove hint in the Settings tab. ([63515](https://github.com/WordPress/gutenberg/pull/63515)) + +#### Block Library +- Social Links: Update Facebook's color to match brand guidelines. ([60424](https://github.com/WordPress/gutenberg/pull/60424)) + + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @hectorjarquin: Add to code requirements install and import Interactivity API. ([63439](https://github.com/WordPress/gutenberg/pull/63439)) +- @Sourav61: Fix: Removed shuffle button when only 1 pattern is present. ([63093](https://github.com/WordPress/gutenberg/pull/63093)) +- @tomllobet: Create-block - fix - update default folder name to proper default. ([63530](https://github.com/WordPress/gutenberg/pull/63530)) +- @troychaplin: change: Updated soundcloud icon for social link block. ([63504](https://github.com/WordPress/gutenberg/pull/63504)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @adamsilverstein @afercia @ajlende @akasunil @amitraj2203 @andrewserong @artemiomorales @barryceelen @carolinan @ciampo @DaniGuardiola @dhananjaykuber @dmsnell @dsas @ellatrix @geriux @hectorjarquin @jameskoster @jasmussen @jeherve @jeryj @jorgefilipecosta @jsnajdr @juanmaguitar @kevin940726 @luisherranz @madhusudhand @MaggieCabrera @Mamaduka @matiasbenedetto @mattsherman @mirka @noisysocks @ntsekouras @oandregal @ockham @priethor @ramonjd @richtabor @ryanwelcher @SantosGuillamot @scruffian @shail-mehta @sirreal @Sourav61 @stokesman @StyleShit @swissspidy @t-hamano @talldan @tellthemachines @tomllobet @troychaplin @tyxla @up1512001 @widoz @youknowriad + + = 18.8.0 = ## Changelog From ddbfee374712287cd7de6bcf0b8af62441251688 Mon Sep 17 00:00:00 2001 From: Robert Anderson <robert@noisysocks.com> Date: Thu, 25 Jul 2024 11:11:06 +1000 Subject: [PATCH 0090/1908] TemplateContentPanel: Don't show content blocks that are in a Query Loop (#63732) * TemplateContentPanel: Don't show content blocks that are in a Query Loop * Make getBlocksByName private * No need to rename getBlockName * Use createSelector * Add tests * Call applyFilters within useMemo consistently --- .../disable-non-page-content-blocks.js | 47 +++++------ .../template-content-panel/index.js | 57 +++++++++----- .../editor/src/store/private-selectors.js | 33 ++++++++ .../src/store/test/private-selectors.js | 78 +++++++++++++++++++ 4 files changed, 172 insertions(+), 43 deletions(-) create mode 100644 packages/editor/src/store/test/private-selectors.js diff --git a/packages/editor/src/components/provider/disable-non-page-content-blocks.js b/packages/editor/src/components/provider/disable-non-page-content-blocks.js index 4ee3b9a8b2703c..35b060b096c069 100644 --- a/packages/editor/src/components/provider/disable-non-page-content-blocks.js +++ b/packages/editor/src/components/provider/disable-non-page-content-blocks.js @@ -3,14 +3,19 @@ */ import { useSelect, useRegistry } from '@wordpress/data'; import { store as blockEditorStore } from '@wordpress/block-editor'; -import { useEffect } from '@wordpress/element'; +import { useEffect, useMemo } from '@wordpress/element'; import { applyFilters } from '@wordpress/hooks'; -const DEFAULT_CONTENT_ONLY_BLOCKS = [ +/** + * Internal dependencies + */ +import { store as editorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; + +const POST_CONTENT_BLOCK_TYPES = [ 'core/post-title', 'core/post-featured-image', 'core/post-content', - 'core/template-part', ]; /** @@ -18,28 +23,26 @@ const DEFAULT_CONTENT_ONLY_BLOCKS = [ * page content to be edited. */ export default function DisableNonPageContentBlocks() { - const contentOnlyBlocks = applyFilters( - 'editor.postContentBlockTypes', - DEFAULT_CONTENT_ONLY_BLOCKS + const contentOnlyBlockTypes = useMemo( + () => [ + ...applyFilters( + 'editor.postContentBlockTypes', + POST_CONTENT_BLOCK_TYPES + ), + 'core/template-part', + ], + [] ); - // Note that there are two separate subscription because the result for each + // Note that there are two separate subscriptions because the result for each // returns a new array. - const contentOnlyIds = useSelect( ( select ) => { - const { getBlocksByName, getBlockParents, getBlockName } = - select( blockEditorStore ); - return getBlocksByName( contentOnlyBlocks ).filter( ( clientId ) => - getBlockParents( clientId ).every( ( parentClientId ) => { - const parentBlockName = getBlockName( parentClientId ); - return ( - // Ignore descendents of the query block. - parentBlockName !== 'core/query' && - // Enable only the top-most block. - ! contentOnlyBlocks.includes( parentBlockName ) - ); - } ) - ); - }, [] ); + const contentOnlyIds = useSelect( + ( select ) => { + const { getPostBlocksByName } = unlock( select( editorStore ) ); + return getPostBlocksByName( contentOnlyBlockTypes ); + }, + [ contentOnlyBlockTypes ] + ); const disabledIds = useSelect( ( select ) => { const { getBlocksByName, getBlockOrder } = select( blockEditorStore ); return getBlocksByName( [ 'core/template-part' ] ).flatMap( diff --git a/packages/editor/src/components/template-content-panel/index.js b/packages/editor/src/components/template-content-panel/index.js index 47d9ab9f2e4067..af9721dfdf2b32 100644 --- a/packages/editor/src/components/template-content-panel/index.js +++ b/packages/editor/src/components/template-content-panel/index.js @@ -2,13 +2,12 @@ * WordPress dependencies */ import { useSelect, useDispatch } from '@wordpress/data'; -import { - store as blockEditorStore, - privateApis as blockEditorPrivateApis, -} from '@wordpress/block-editor'; +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { PanelBody } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { store as interfaceStore } from '@wordpress/interface'; +import { applyFilters } from '@wordpress/hooks'; +import { useMemo } from '@wordpress/element'; /** * Internal dependencies @@ -19,30 +18,46 @@ import { store as editorStore } from '../../store'; const { BlockQuickNavigation } = unlock( blockEditorPrivateApis ); -const PAGE_CONTENT_BLOCKS = [ - 'core/post-content', - 'core/post-featured-image', +const POST_CONTENT_BLOCK_TYPES = [ 'core/post-title', + 'core/post-featured-image', + 'core/post-content', ]; const TEMPLATE_PART_BLOCK = 'core/template-part'; export default function TemplateContentPanel() { - const { enableComplementaryArea } = useDispatch( interfaceStore ); - const { clientIds, postType, renderingMode } = useSelect( ( select ) => { - const { getBlocksByName } = select( blockEditorStore ); - const { getCurrentPostType } = select( editorStore ); - const _postType = getCurrentPostType(); - return { - postType: _postType, - clientIds: getBlocksByName( - TEMPLATE_POST_TYPE === _postType - ? TEMPLATE_PART_BLOCK - : PAGE_CONTENT_BLOCKS + const postContentBlockTypes = useMemo( + () => + applyFilters( + 'editor.postContentBlockTypes', + POST_CONTENT_BLOCK_TYPES ), - renderingMode: select( editorStore ).getRenderingMode(), - }; - }, [] ); + [] + ); + + const { clientIds, postType, renderingMode } = useSelect( + ( select ) => { + const { + getCurrentPostType, + getPostBlocksByName, + getRenderingMode, + } = unlock( select( editorStore ) ); + const _postType = getCurrentPostType(); + return { + postType: _postType, + clientIds: getPostBlocksByName( + TEMPLATE_POST_TYPE === _postType + ? TEMPLATE_PART_BLOCK + : postContentBlockTypes + ), + renderingMode: getRenderingMode(), + }; + }, + [ postContentBlockTypes ] + ); + + const { enableComplementaryArea } = useDispatch( interfaceStore ); if ( renderingMode === 'post-only' && postType !== TEMPLATE_POST_TYPE ) { return null; diff --git a/packages/editor/src/store/private-selectors.js b/packages/editor/src/store/private-selectors.js index c635cbc816f92b..ed4672bc435cdc 100644 --- a/packages/editor/src/store/private-selectors.js +++ b/packages/editor/src/store/private-selectors.js @@ -160,3 +160,36 @@ export const hasPostMetaChanges = createRegistrySelector( export function getEntityActions( state, ...args ) { return _getEntityActions( state.dataviews, ...args ); } + +/** + * Similar to getBlocksByName in @wordpress/block-editor, but only returns the top-most + * blocks that aren't descendants of the query block. + * + * @param {Object} state Global application state. + * @param {Array|string} blockNames Block names of the blocks to retrieve. + * + * @return {Array} Block client IDs. + */ +export const getPostBlocksByName = createRegistrySelector( ( select ) => + createSelector( + ( state, blockNames ) => { + blockNames = Array.isArray( blockNames ) + ? blockNames + : [ blockNames ]; + const { getBlocksByName, getBlockParents, getBlockName } = + select( blockEditorStore ); + return getBlocksByName( blockNames ).filter( ( clientId ) => + getBlockParents( clientId ).every( ( parentClientId ) => { + const parentBlockName = getBlockName( parentClientId ); + return ( + // Ignore descendents of the query block. + parentBlockName !== 'core/query' && + // Enable only the top-most block. + ! blockNames.includes( parentBlockName ) + ); + } ) + ); + }, + () => [ select( blockEditorStore ).getBlocks() ] + ) +); diff --git a/packages/editor/src/store/test/private-selectors.js b/packages/editor/src/store/test/private-selectors.js new file mode 100644 index 00000000000000..bf2bc1f74065cb --- /dev/null +++ b/packages/editor/src/store/test/private-selectors.js @@ -0,0 +1,78 @@ +/** + * Internal dependencies + */ +import { getPostBlocksByName } from '../private-selectors'; + +describe( 'getPostBlocksByName', () => { + const state = { + blocks: { + byClientId: new Map( [ + [ 'block1', { name: 'core/paragraph' } ], + [ 'block2', { name: 'core/heading' } ], + [ 'block3', { name: 'core/paragraph' } ], + [ 'block4', { name: 'core/query' } ], + [ 'block5', { name: 'core/paragraph' } ], + [ 'block6', { name: 'core/heading' } ], + ] ), + order: new Map( [ + [ '', [ 'block1', 'block2', 'block3', 'block4' ] ], + [ 'block4', [ 'block5', 'block6' ] ], + ] ), + parents: new Map( [ + [ 'block1', '' ], + [ 'block2', '' ], + [ 'block3', '' ], + [ 'block4', '' ], + [ 'block5', 'block4' ], + [ 'block6', 'block4' ], + ] ), + }, + }; + + getPostBlocksByName.registry = { + select: () => ( { + getBlocksByName: ( blockNames ) => + Array.from( state.blocks.byClientId.keys() ).filter( + ( clientId ) => + blockNames.includes( + state.blocks.byClientId.get( clientId ).name + ) + ), + getBlockParents: ( clientId ) => { + const parents = []; + let parent = state.blocks.parents.get( clientId ); + while ( parent ) { + parents.push( parent ); + parent = state.blocks.parents.get( parent ); + } + return parents; + }, + getBlockName: ( clientId ) => + state.blocks.byClientId.get( clientId ).name, + getBlocks: () => [], + } ), + }; + + it( 'should return top-level blocks of the specified name', () => { + const result = getPostBlocksByName( state, 'core/paragraph' ); + expect( result ).toEqual( [ 'block1', 'block3' ] ); + } ); + + it( 'should return an empty array if no blocks match', () => { + const result = getPostBlocksByName( state, 'core/non-existent' ); + expect( result ).toEqual( [] ); + } ); + + it( 'should ignore blocks inside a query block', () => { + const result = getPostBlocksByName( state, 'core/paragraph' ); + expect( result ).toEqual( [ 'block1', 'block3' ] ); + } ); + + it( 'should handle multiple block names', () => { + const result = getPostBlocksByName( state, [ + 'core/paragraph', + 'core/heading', + ] ); + expect( result ).toEqual( [ 'block1', 'block2', 'block3' ] ); + } ); +} ); From ed4673b8175c10fb243f9f006c035517476a275a Mon Sep 17 00:00:00 2001 From: Rich Tabor <hi@richtabor.com> Date: Wed, 24 Jul 2024 22:39:46 -0400 Subject: [PATCH 0091/1908] Update MediaUpload button for site logo from "Add media" to "Choose logo" (#63498) --- packages/block-library/src/site-logo/edit.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index f3e2f9e13a11ac..45649ca8ce35cb 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -590,8 +590,6 @@ export default function LogoEdit( { const blockProps = useBlockProps( { className: classes } ); - const label = __( 'Add a site logo' ); - const mediaInspectorPanel = ( canUserEdit || logoUrl ) && ( <InspectorControls> <PanelBody title={ __( 'Media' ) }> @@ -631,7 +629,7 @@ export default function LogoEdit( { { isLoading ? ( <Spinner /> ) : ( - __( 'Add media' ) + __( 'Choose logo' ) ) } </Button> <DropZone onFilesDrop={ onFilesDrop } /> @@ -671,9 +669,9 @@ export default function LogoEdit( { <Button icon={ upload } variant="primary" - label={ label } + label={ __( 'Choose logo' ) } showTooltip - tooltipPosition="top center" + tooltipPosition="bottom center" onClick={ () => { open(); } } From 63728a5fa13bb0f52bb1f4d8748e88afd3265706 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Thu, 25 Jul 2024 09:43:04 +0530 Subject: [PATCH 0092/1908] Font Library: Include a "Select All" options for google fonts (#63893) * Add select all toggle for google fonts in font library * Remove styles Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> Co-authored-by: creativecoder <grantmkin@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: ghorivipul97 <ghorivipul97@git.wordpress.org> --- .../font-library-modal/font-collection.js | 28 +++++++++++++++++++ .../font-library-modal/style.scss | 1 - 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js index b6f8dc46aa5641..cf6857b30c59e6 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js @@ -25,6 +25,7 @@ import { DropdownMenu, SearchControl, ProgressBar, + CheckboxControl, } from '@wordpress/components'; import { debounce } from '@wordpress/compose'; import { sprintf, __, _x } from '@wordpress/i18n'; @@ -175,6 +176,25 @@ function FontCollection( { slug } ) { setFontsToInstall( [] ); }; + const selectFontCount = + fontsToInstall.length > 0 ? fontsToInstall[ 0 ]?.fontFace?.length : 0; + + // Check if any fonts are selected. + const isIndeterminate = + selectFontCount > 0 && + selectFontCount !== selectedFont?.fontFace?.length; + + // Check if all fonts are selected. + const isSelectAllChecked = + selectFontCount === selectedFont?.fontFace?.length; + + // Toggle select all fonts. + const toggleSelectAll = () => { + const newFonts = isSelectAllChecked ? [] : [ selectedFont ]; + + setFontsToInstall( newFonts ); + }; + const handleInstall = async () => { setNotice( null ); @@ -400,6 +420,14 @@ function FontCollection( { slug } ) { { __( 'Select font variants to install.' ) } </Text> <Spacer margin={ 4 } /> + <CheckboxControl + className="font-library-modal__select-all" + label={ __( 'Select all' ) } + checked={ isSelectAllChecked } + onChange={ toggleSelectAll } + indeterminate={ isIndeterminate } + __nextHasNoMarginBottom + /> <VStack spacing={ 0 }> <Spacer margin={ 8 } /> { getSortedFontFaces( selectedFont ).map( diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss index 5cbb53a6296ccf..10b5b816cb9bdc 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss +++ b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss @@ -194,4 +194,3 @@ button.font-library-modal__upload-area { padding-left: $grid-unit-20; } } - From ae831557eeaf7d9d7c68b952bb8dedcc39f645fe Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Thu, 25 Jul 2024 12:22:34 +0800 Subject: [PATCH 0093/1908] Fix block library and global styles stylesheet ordering when a block style variation is active (#63918) * Fix block library and global styles stylesheet ordering when a block style variation is active * Add backport changeglog * Update core backport ---- Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: eric-michel <ytfeldrawkcab@git.wordpress.org> --- backport-changelog/6.6/7088.md | 4 ++++ lib/block-supports/block-style-variations.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 backport-changelog/6.6/7088.md diff --git a/backport-changelog/6.6/7088.md b/backport-changelog/6.6/7088.md new file mode 100644 index 00000000000000..46bd1147464846 --- /dev/null +++ b/backport-changelog/6.6/7088.md @@ -0,0 +1,4 @@ +https://github.com/WordPress/wordpress-develop/pull/7088 + +* https://github.com/WordPress/gutenberg/pull/63918 + diff --git a/lib/block-supports/block-style-variations.php b/lib/block-supports/block-style-variations.php index d1a63915f12882..73e4f9fce25843 100644 --- a/lib/block-supports/block-style-variations.php +++ b/lib/block-supports/block-style-variations.php @@ -191,7 +191,7 @@ function gutenberg_render_block_style_variation_support_styles( $parsed_block ) return $parsed_block; } - wp_register_style( 'block-style-variation-styles', false, array( 'global-styles', 'wp-block-library' ) ); + wp_register_style( 'block-style-variation-styles', false, array( 'wp-block-library', 'global-styles' ) ); wp_add_inline_style( 'block-style-variation-styles', $variation_styles ); /* From 3dfdfef3eb5cf35abf67bdce9013cc8cef5927b7 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 25 Jul 2024 09:51:36 +0400 Subject: [PATCH 0094/1908] Block Editor: Update 'getBlocksByName' JSDoc (#63919) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- docs/reference-guides/data/data-core-block-editor.md | 2 +- packages/block-editor/src/store/selectors.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index 7eed5c8741288b..040a10f8f506c2 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -412,7 +412,7 @@ Returns all blocks that match a blockName. Results include nested blocks. _Parameters_ - _state_ `Object`: Global application state. -- _blockName_ `?string`: Optional block name, if not specified, returns an empty array. +- _blockName_ `string[]`: Block name(s) for which clientIds are to be returned. _Returns_ diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index d6d09b59106110..f06293dadf233c 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -334,8 +334,8 @@ export const getGlobalBlockCount = createSelector( /** * Returns all blocks that match a blockName. Results include nested blocks. * - * @param {Object} state Global application state. - * @param {?string} blockName Optional block name, if not specified, returns an empty array. + * @param {Object} state Global application state. + * @param {string[]} blockName Block name(s) for which clientIds are to be returned. * * @return {Array} Array of clientIds of blocks with name equal to blockName. */ @@ -362,8 +362,8 @@ export const getBlocksByName = createSelector( * * @deprecated * - * @param {Object} state Global application state. - * @param {?string} blockName Optional block name, if not specified, returns an empty array. + * @param {Object} state Global application state. + * @param {string[]} blockName Block name(s) for which clientIds are to be returned. * * @return {Array} Array of clientIds of blocks with name equal to blockName. */ From 1055e026d2713dd2902d11cc28d0c45b46d7ceff Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Thu, 25 Jul 2024 11:31:12 +0200 Subject: [PATCH 0095/1908] Block Bindings: Allow bindings bootstrap after registration (#63797) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add unit test * Keep existing properties in bootstrap * Update test description Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> * Reuse mergedContext * Improve `mergedUsesContext` definition --------- Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/blocks/src/api/test/registration.js | 37 ++++++++++++++++++++ packages/blocks/src/store/reducer.js | 27 +++++++------- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index f4df432976bc12..cc339e59d27053 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -1703,6 +1703,43 @@ describe( 'blocks', () => { 'Block bindings source "core/test-source" is already registered.' ); } ); + + it( 'should correctly merge properties when bootstrap happens after registration', () => { + // Register source in the client. + const clientOnlyProperties = { + getValues: () => 'values', + setValues: () => 'new values', + getPlaceholder: () => 'placeholder', + canUserEditValue: () => true, + }; + registerBlockBindingsSource( { + name: 'core/custom-source', + label: 'Client Label', + usesContext: [ 'postId', 'postType' ], + ...clientOnlyProperties, + } ); + + // Bootstrap source from the server. + unlock( + dispatch( blocksStore ) + ).addBootstrappedBlockBindingsSource( { + name: 'core/custom-source', + label: 'Server Label', + usesContext: [ 'postId', 'serverContext' ], + } ); + + // Check that the bootstrap values prevail and the client properties are still there. + expect( getBlockBindingsSource( 'core/custom-source' ) ).toEqual( { + // Should use the server label. + label: 'Server Label', + // Should merge usesContext from server and client. + usesContext: [ 'postId', 'postType', 'serverContext' ], + // Should keep client properties. + ...clientOnlyProperties, + } ); + + unregisterBlockBindingsSource( 'core/custom-source' ); + } ); } ); describe( 'unregisterBlockBindingsSource', () => { diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 5e0714b6064fde..2f141fb0cf9927 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -372,19 +372,17 @@ export function collections( state = {}, action ) { } export function blockBindingsSources( state = {}, action ) { + // Merge usesContext with existing values, potentially defined in the server registration. + const existingUsesContext = state[ action.name ]?.usesContext || []; + const newUsesContext = action.usesContext || []; + const mergedArrays = Array.from( + new Set( existingUsesContext.concat( newUsesContext ) ) + ); + const mergedUsesContext = + mergedArrays.length > 0 ? mergedArrays : undefined; + switch ( action.type ) { case 'ADD_BLOCK_BINDINGS_SOURCE': - // Merge usesContext with existing values, potentially defined in the server registration. - let mergedUsesContext = [ - ...( state[ action.name ]?.usesContext || [] ), - ...( action.usesContext || [] ), - ]; - // Remove duplicates. - mergedUsesContext = - mergedUsesContext.length > 0 - ? [ ...new Set( mergedUsesContext ) ] - : undefined; - return { ...state, [ action.name ]: { @@ -401,8 +399,13 @@ export function blockBindingsSources( state = {}, action ) { return { ...state, [ action.name ]: { + /* + * Keep the exisitng properties in case the source has been registered + * in the client before bootstrapping. + */ + ...state[ action.name ], label: action.label, - usesContext: action.usesContext, + usesContext: mergedUsesContext, }, }; case 'REMOVE_BLOCK_BINDINGS_SOURCE': From cdab04507b5d3dd923ff5a14aaba36d86f99ddab Mon Sep 17 00:00:00 2001 From: Rich Tabor <hi@richtabor.com> Date: Thu, 25 Jul 2024 06:23:02 -0400 Subject: [PATCH 0096/1908] Made SiteLogoReplaceFlow always available in the Site Logo block toolbar (#63499) Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../components/media-replace-flow/README.md | 7 ++++++ .../components/media-replace-flow/index.js | 4 +++- packages/block-library/src/site-logo/edit.js | 24 +++++++++++++++---- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/media-replace-flow/README.md b/packages/block-editor/src/components/media-replace-flow/README.md index 2f3cffde4b4a79..a5808ab9561980 100644 --- a/packages/block-editor/src/components/media-replace-flow/README.md +++ b/packages/block-editor/src/components/media-replace-flow/README.md @@ -91,3 +91,10 @@ Removes a media replace notice. - Required: No If passed, children are rendered inside the dropdown. + +### children + +- Type: `Element | func` +- Required: No + +If passed, children are rendered inside the dropdown. If a function is provided for this prop, it will receive an object with the `onClose` prop as an argument. diff --git a/packages/block-editor/src/components/media-replace-flow/index.js b/packages/block-editor/src/components/media-replace-flow/index.js index 318eb166734ee4..6a52e28c223671 100644 --- a/packages/block-editor/src/components/media-replace-flow/index.js +++ b/packages/block-editor/src/components/media-replace-flow/index.js @@ -202,7 +202,9 @@ const MediaReplaceFlow = ( { { __( 'Use featured image' ) } </MenuItem> ) } - { children } + { typeof children === 'function' + ? children( { onClose } ) + : children } </NavigableMenu> { onSelectURL && ( // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index 45649ca8ce35cb..ac74ac2aeb6eb4 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -348,14 +348,29 @@ const SiteLogo = ( { // This is a light wrapper around MediaReplaceFlow because the block has two // different MediaReplaceFlows, one for the inspector and one for the toolbar. -function SiteLogoReplaceFlow( { onRemoveLogo, ...mediaReplaceProps } ) { +function SiteLogoReplaceFlow( { + mediaURL, + onRemoveLogo, + ...mediaReplaceProps +} ) { return ( <MediaReplaceFlow { ...mediaReplaceProps } allowedTypes={ ALLOWED_MEDIA_TYPES } accept={ ACCEPT_MEDIA_STRING } > - <MenuItem onClick={ onRemoveLogo }>{ __( 'Reset' ) }</MenuItem> + { ( { onClose } ) => + mediaURL && ( + <MenuItem + onClick={ () => { + onRemoveLogo(); + onClose(); + } } + > + { __( 'Reset' ) } + </MenuItem> + ) + } </MediaReplaceFlow> ); } @@ -392,7 +407,6 @@ export default function LogoEdit( { isSelected, } ) { const { width, shouldSyncIcon } = attributes; - const { siteLogoId, canUserEdit, @@ -515,16 +529,18 @@ export default function LogoEdit( { onInitialSelectLogo( image ); }, onError: onUploadError, + onRemoveLogo, } ); }; const mediaReplaceFlowProps = { mediaURL: logoUrl, + name: ! logoUrl ? __( 'Choose logo' ) : __( 'Replace' ), onSelect: onSelectLogo, onError: onUploadError, onRemoveLogo, }; - const controls = canUserEdit && logoUrl && ! temporaryURL && ( + const controls = canUserEdit && ( <BlockControls group="other"> <SiteLogoReplaceFlow { ...mediaReplaceFlowProps } /> </BlockControls> From 32838e81a4d1e96da0c89226611ba43c527c7876 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 25 Jul 2024 12:24:43 +0200 Subject: [PATCH 0097/1908] DropdownMenuV2: break menu item help text on multiple lines for better truncation (#63916) * DropdownMenuV2: break text menu item help text on multiple lines for better truncation * CHANGELOG Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/dropdown-menu-v2/styles.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index a05ebab3783b8e..4a423eeb4a57df 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Internal + +- `DropdownMenuV2`: break menu item help text on multiple lines for better truncation. ([#63916](https://github.com/WordPress/gutenberg/pull/63916)). + ## 28.4.0 (2024-07-24) ### Deprecations diff --git a/packages/components/src/dropdown-menu-v2/styles.ts b/packages/components/src/dropdown-menu-v2/styles.ts index 91a3aaeec1147e..b36f69e62c5094 100644 --- a/packages/components/src/dropdown-menu-v2/styles.ts +++ b/packages/components/src/dropdown-menu-v2/styles.ts @@ -344,6 +344,7 @@ export const DropdownMenuItemHelpText = styled( Truncate )` font-size: ${ font( 'helpText.fontSize' ) }; line-height: 16px; color: ${ COLORS.gray[ '700' ] }; + word-break: break-all; [data-active-item]:not( [data-focus-visible] ) *:not( ${ DropdownMenu } ) &, [aria-disabled='true'] *:not( ${ DropdownMenu } ) & { From 877628cb8745930715379f41d012ccbc7b23cf13 Mon Sep 17 00:00:00 2001 From: Matias Benedetto <matias.benedetto@gmail.com> Date: Thu, 25 Jul 2024 15:41:41 +0400 Subject: [PATCH 0098/1908] Fix item font family item height in the sidebar (#63125) * fix item font family item height * Apply size="large" to custom fonts as well --------- Co-authored-by: Sarah Norris <sarah@sekai.co.uk> Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../edit-site/src/components/global-styles/font-families.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-families.js b/packages/edit-site/src/components/global-styles/font-families.js index 7a05a66c6efdfe..f6610d0457bbae 100644 --- a/packages/edit-site/src/components/global-styles/font-families.js +++ b/packages/edit-site/src/components/global-styles/font-families.js @@ -69,7 +69,7 @@ function FontFamilies() { _x( 'Theme', 'font source' ) } </Subtitle> - <ItemGroup isBordered isSeparated> + <ItemGroup size="large" isBordered isSeparated> { themeFonts.map( ( font ) => ( <FontFamilyItem key={ font.slug } @@ -87,7 +87,7 @@ function FontFamilies() { _x( 'Custom', 'font source' ) } </Subtitle> - <ItemGroup isBordered isSeparated> + <ItemGroup size="large" isBordered isSeparated> { customFonts.map( ( font ) => ( <FontFamilyItem key={ font.slug } From d77fe656e70e0816c5c1b4a6acc21b42db105211 Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Thu, 25 Jul 2024 13:54:17 +0100 Subject: [PATCH 0099/1908] Zoom Out: Use the block editor for insertion point data (#63934) * Zoom Out: Use the block editor for insertion point data * remove unlock Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../block-tools/zoom-out-mode-inserters.js | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js index 5d273a4f3f6d58..45b1cf0f64bd7d 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { useSelect } from '@wordpress/data'; +import { useSelect, useDispatch } from '@wordpress/data'; import { useEffect, useState } from '@wordpress/element'; /** @@ -16,8 +16,9 @@ function ZoomOutModeInserters() { const [ isReady, setIsReady ] = useState( false ); const { hasSelection, + blockInsertionPoint, blockOrder, - insertionPoint, + blockInsertionPointVisible, setInserterIsOpened, sectionRootClientId, selectedBlockClientId, @@ -25,23 +26,19 @@ function ZoomOutModeInserters() { } = useSelect( ( select ) => { const { getSettings, + getBlockInsertionPoint, getBlockOrder, getSelectionStart, getSelectedBlockClientId, getHoveredBlockClientId, + isBlockInsertionPointVisible, } = select( blockEditorStore ); const { sectionRootClientId: root } = unlock( getSettings() ); - // To do: move ZoomOutModeInserters to core/editor. - // Or we perhaps we should move the insertion point state to the - // block-editor store. I'm not sure what it was ever moved to the editor - // store, because all the inserter components all live in the - // block-editor package. - // eslint-disable-next-line @wordpress/data-no-store-string-literals - const editor = select( 'core/editor' ); return { hasSelection: !! getSelectionStart().clientId, + blockInsertionPoint: getBlockInsertionPoint(), blockOrder: getBlockOrder( root ), - insertionPoint: unlock( editor ).getInsertionPoint(), + blockInsertionPointVisible: isBlockInsertionPointVisible(), sectionRootClientId: root, setInserterIsOpened: getSettings().__experimentalSetIsInserterOpened, @@ -50,6 +47,8 @@ function ZoomOutModeInserters() { }; }, [] ); + const blockEditorDispatch = useDispatch( blockEditorStore ); + // Defer the initial rendering to avoid the jumps due to the animation. useEffect( () => { const timeout = setTimeout( () => { @@ -65,14 +64,8 @@ function ZoomOutModeInserters() { } return [ undefined, ...blockOrder ].map( ( clientId, index ) => { - const shouldRenderInserter = insertionPoint.insertionIndex !== index; - const shouldRenderInsertionPoint = - insertionPoint.insertionIndex === index; - - if ( ! shouldRenderInserter && ! shouldRenderInsertionPoint ) { - return null; - } + blockInsertionPointVisible && blockInsertionPoint.index === index; const previousClientId = clientId; const nextClientId = blockOrder[ index ]; @@ -86,6 +79,8 @@ function ZoomOutModeInserters() { hoveredBlockClientId === previousClientId || hoveredBlockClientId === nextClientId; + const { showInsertionPoint } = blockEditorDispatch; + return ( <BlockPopoverInbetween key={ index } @@ -104,7 +99,7 @@ function ZoomOutModeInserters() { className="block-editor-block-list__insertion-point-indicator" /> ) } - { shouldRenderInserter && ( + { ! shouldRenderInsertionPoint && ( <ZoomOutModeInserterButton isVisible={ isSelected || isHovered } onClick={ () => { @@ -114,6 +109,9 @@ function ZoomOutModeInserters() { tab: 'patterns', category: 'all', } ); + showInsertionPoint( sectionRootClientId, index, { + operation: 'insert', + } ); } } /> ) } From 4af798f2b4342e4f157103e528309e2d3a1cc572 Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Thu, 25 Jul 2024 14:02:50 +0100 Subject: [PATCH 0100/1908] Global Styles: Add a typesets section to Typography (#62539) * Global Styles: Add a typesets section to Typography Only show typesets if there are fonts * update typesets to contain font families * add variation name to typesets * add variation name to typesets * use variation titles for typeset button * Update packages/edit-site/src/components/global-styles/typeset-button.js Co-authored-by: Sarah Norris <1645628+mikachan@users.noreply.github.com> * Update packages/edit-site/src/components/global-styles/typeset-button.js Co-authored-by: Sarah Norris <1645628+mikachan@users.noreply.github.com> * Update packages/edit-site/src/components/global-styles/typeset-button.js Co-authored-by: Sarah Norris <1645628+mikachan@users.noreply.github.com> * Add fontLibraryEnabled to ScreenTypography * Remove window.__experimentalDisableFontLibrary * Check for themeFontFamilies and customFontFamilies --------- Co-authored-by: Sarah Norris <1645628+mikachan@users.noreply.github.com> Co-authored-by: Sarah Norris <sarah@sekai.co.uk> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../global-styles/screen-typeset.js | 42 +++++++++ .../global-styles/screen-typography.js | 8 +- .../global-styles/typeset-button.js | 93 +++++++++++++++++++ .../src/components/global-styles/typeset.js | 73 +++++++++++++++ .../src/components/global-styles/ui.js | 5 + .../src/components/global-styles/utils.js | 14 ++- 6 files changed, 230 insertions(+), 5 deletions(-) create mode 100644 packages/edit-site/src/components/global-styles/screen-typeset.js create mode 100644 packages/edit-site/src/components/global-styles/typeset-button.js create mode 100644 packages/edit-site/src/components/global-styles/typeset.js diff --git a/packages/edit-site/src/components/global-styles/screen-typeset.js b/packages/edit-site/src/components/global-styles/screen-typeset.js new file mode 100644 index 00000000000000..ce754121dfe1b5 --- /dev/null +++ b/packages/edit-site/src/components/global-styles/screen-typeset.js @@ -0,0 +1,42 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { store as editorStore } from '@wordpress/editor'; +import { __experimentalVStack as VStack } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import TypographyVariations from './variations/variations-typography'; +import ScreenHeader from './header'; +import FontFamilies from './font-families'; + +function ScreenTypeset() { + const fontLibraryEnabled = useSelect( + ( select ) => + select( editorStore ).getEditorSettings().fontLibraryEnabled, + [] + ); + + return ( + <> + <ScreenHeader + title={ __( 'Typesets' ) } + description={ __( + 'Fonts and typographic styling applied across the site.' + ) } + /> + <div className="edit-site-global-styles-screen"> + <VStack spacing={ 7 }> + <TypographyVariations /> + + { fontLibraryEnabled && <FontFamilies /> } + </VStack> + </div> + </> + ); +} + +export default ScreenTypeset; diff --git a/packages/edit-site/src/components/global-styles/screen-typography.js b/packages/edit-site/src/components/global-styles/screen-typography.js index a58802a204ce32..c23592c51a6a2a 100644 --- a/packages/edit-site/src/components/global-styles/screen-typography.js +++ b/packages/edit-site/src/components/global-styles/screen-typography.js @@ -3,17 +3,17 @@ */ import { __ } from '@wordpress/i18n'; import { __experimentalVStack as VStack } from '@wordpress/components'; -import { store as editorStore } from '@wordpress/editor'; import { useSelect } from '@wordpress/data'; +import { store as editorStore } from '@wordpress/editor'; /** * Internal dependencies */ import TypographyElements from './typography-elements'; -import TypographyVariations from './variations/variations-typography'; -import FontFamilies from './font-families'; import ScreenHeader from './header'; import FontSizesCount from './font-sizes/font-sizes-count'; +import TypesetButton from './typeset-button'; +import FontFamilies from './font-families'; function ScreenTypography() { const fontLibraryEnabled = useSelect( @@ -32,9 +32,9 @@ function ScreenTypography() { /> <div className="edit-site-global-styles-screen"> <VStack spacing={ 7 }> + <TypesetButton /> { fontLibraryEnabled && <FontFamilies /> } <TypographyElements /> - <TypographyVariations title={ __( 'Presets' ) } /> <FontSizesCount /> </VStack> </div> diff --git a/packages/edit-site/src/components/global-styles/typeset-button.js b/packages/edit-site/src/components/global-styles/typeset-button.js new file mode 100644 index 00000000000000..d66310f2ed8ff5 --- /dev/null +++ b/packages/edit-site/src/components/global-styles/typeset-button.js @@ -0,0 +1,93 @@ +/** + * WordPress dependencies + */ +import { isRTL, __ } from '@wordpress/i18n'; +import { + __experimentalItemGroup as ItemGroup, + __experimentalVStack as VStack, + __experimentalHStack as HStack, + FlexItem, +} from '@wordpress/components'; +import { store as coreStore } from '@wordpress/core-data'; +import { useSelect } from '@wordpress/data'; +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; +import { privateApis as editorPrivateApis } from '@wordpress/editor'; +import { useMemo, useContext } from '@wordpress/element'; +import { Icon, chevronLeft, chevronRight } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import FontLibraryProvider from './font-library-modal/context'; +import { getFontFamilies } from './utils'; +import { NavigationButtonAsItem } from './navigation-button'; +import Subtitle from './subtitle'; +import { unlock } from '../../lock-unlock'; +import { filterObjectByProperties } from '../../hooks/use-theme-style-variations/use-theme-style-variations-by-property'; + +const { GlobalStylesContext } = unlock( blockEditorPrivateApis ); +const { mergeBaseAndUserConfigs } = unlock( editorPrivateApis ); + +function TypesetButton() { + const { base } = useContext( GlobalStylesContext ); + const { user: userConfig } = useContext( GlobalStylesContext ); + const config = mergeBaseAndUserConfigs( base, userConfig ); + const allFontFamilies = getFontFamilies( config ); + const hasFonts = + allFontFamilies.filter( ( font ) => font !== null ).length > 0; + const variations = useSelect( ( select ) => { + return select( + coreStore + ).__experimentalGetCurrentThemeGlobalStylesVariations(); + }, [] ); + const userTypographyConfig = filterObjectByProperties( + userConfig, + 'typography' + ); + + const title = useMemo( () => { + if ( Object.keys( userTypographyConfig ).length === 0 ) { + return __( 'Default' ); + } + const activeVariation = variations.find( ( variation ) => { + return ( + JSON.stringify( + filterObjectByProperties( variation, 'typography' ) + ) === JSON.stringify( userTypographyConfig ) + ); + } ); + if ( activeVariation ) { + return activeVariation.title; + } + return allFontFamilies.map( ( font ) => font?.name ).join( ', ' ); + }, [ userTypographyConfig, variations ] ); + + return ( + hasFonts && ( + <VStack spacing={ 2 }> + <HStack justify="space-between"> + <Subtitle level={ 3 }>{ __( 'Typeset' ) }</Subtitle> + </HStack> + <ItemGroup isBordered isSeparated> + <NavigationButtonAsItem + path="/typography/typeset" + aria-label={ __( 'Typeset' ) } + > + <HStack direction="row"> + <FlexItem>{ title }</FlexItem> + <Icon + icon={ isRTL() ? chevronLeft : chevronRight } + /> + </HStack> + </NavigationButtonAsItem> + </ItemGroup> + </VStack> + ) + ); +} + +export default ( { ...props } ) => ( + <FontLibraryProvider> + <TypesetButton { ...props } /> + </FontLibraryProvider> +); diff --git a/packages/edit-site/src/components/global-styles/typeset.js b/packages/edit-site/src/components/global-styles/typeset.js new file mode 100644 index 00000000000000..e99e6a037500ad --- /dev/null +++ b/packages/edit-site/src/components/global-styles/typeset.js @@ -0,0 +1,73 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { + __experimentalItemGroup as ItemGroup, + __experimentalVStack as VStack, + __experimentalHStack as HStack, +} from '@wordpress/components'; +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; +import { privateApis as editorPrivateApis } from '@wordpress/editor'; +import { useContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import FontLibraryProvider, { + FontLibraryContext, +} from './font-library-modal/context'; +import FontLibraryModal from './font-library-modal'; +import FontFamilyItem from './font-family-item'; +import Subtitle from './subtitle'; +import { getFontFamilies } from './utils'; +import { unlock } from '../../lock-unlock'; + +const { GlobalStylesContext } = unlock( blockEditorPrivateApis ); +const { mergeBaseAndUserConfigs } = unlock( editorPrivateApis ); + +function Typesets() { + const { modalTabOpen, setModalTabOpen } = useContext( FontLibraryContext ); + const { base } = useContext( GlobalStylesContext ); + const { user: userConfig } = useContext( GlobalStylesContext ); + const config = mergeBaseAndUserConfigs( base, userConfig ); + const allFontFamilies = getFontFamilies( config ); + const hasFonts = + allFontFamilies.filter( ( font ) => font !== null ).length > 0; + + return ( + hasFonts && ( + <> + { !! modalTabOpen && ( + <FontLibraryModal + onRequestClose={ () => setModalTabOpen( null ) } + defaultTabId={ modalTabOpen } + /> + ) } + + <VStack spacing={ 2 }> + <HStack justify="space-between"> + <Subtitle level={ 3 }>{ __( 'Fonts' ) }</Subtitle> + </HStack> + <ItemGroup isBordered isSeparated> + { allFontFamilies.map( + ( font ) => + font && ( + <FontFamilyItem + key={ font.slug } + font={ font } + /> + ) + ) } + </ItemGroup> + </VStack> + </> + ) + ); +} + +export default ( { ...props } ) => ( + <FontLibraryProvider> + <Typesets { ...props } /> + </FontLibraryProvider> +); diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index 40d20bc1ec86f8..54bd4f97390a8f 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -32,6 +32,7 @@ import { } from './screen-block-list'; import ScreenBlock from './screen-block'; import ScreenTypography from './screen-typography'; +import ScreenTypeset from './screen-typeset'; import ScreenTypographyElement from './screen-typography-element'; import FontSize from './font-sizes/font-size'; import FontSizes from './font-sizes/font-sizes'; @@ -323,6 +324,10 @@ function GlobalStylesUI() { <FontSize /> </GlobalStylesNavigationScreen> + <GlobalStylesNavigationScreen path="/typography/typeset"> + <ScreenTypeset /> + </GlobalStylesNavigationScreen> + <GlobalStylesNavigationScreen path="/typography/text"> <ScreenTypographyElement element="text" /> </GlobalStylesNavigationScreen> diff --git a/packages/edit-site/src/components/global-styles/utils.js b/packages/edit-site/src/components/global-styles/utils.js index 6096b381fb2187..66a25854a06fe1 100644 --- a/packages/edit-site/src/components/global-styles/utils.js +++ b/packages/edit-site/src/components/global-styles/utils.js @@ -52,7 +52,19 @@ function getFontFamilyFromSetting( fontFamilies, setting ) { } export function getFontFamilies( themeJson ) { - const fontFamilies = themeJson?.settings?.typography?.fontFamilies?.theme; // TODO this could not be under theme. + const themeFontFamilies = + themeJson?.settings?.typography?.fontFamilies?.theme; + const customFontFamilies = + themeJson?.settings?.typography?.fontFamilies?.custom; + + let fontFamilies = []; + if ( themeFontFamilies && customFontFamilies ) { + fontFamilies = [ ...themeFontFamilies, ...customFontFamilies ]; + } else if ( themeFontFamilies ) { + fontFamilies = themeFontFamilies; + } else if ( customFontFamilies ) { + fontFamilies = customFontFamilies; + } const bodyFontFamilySetting = themeJson?.styles?.typography?.fontFamily; const bodyFontFamily = getFontFamilyFromSetting( fontFamilies, From 3336ee9bc3490dee6d6d843a8a83229df33bfccd Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 25 Jul 2024 17:04:10 +0400 Subject: [PATCH 0101/1908] Zoom out: Get store action outside the loop (#63936) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/block-tools/zoom-out-mode-inserters.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js index 45b1cf0f64bd7d..bb044f9479c024 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js @@ -47,7 +47,7 @@ function ZoomOutModeInserters() { }; }, [] ); - const blockEditorDispatch = useDispatch( blockEditorStore ); + const { showInsertionPoint } = useDispatch( blockEditorStore ); // Defer the initial rendering to avoid the jumps due to the animation. useEffect( () => { @@ -79,8 +79,6 @@ function ZoomOutModeInserters() { hoveredBlockClientId === previousClientId || hoveredBlockClientId === nextClientId; - const { showInsertionPoint } = blockEditorDispatch; - return ( <BlockPopoverInbetween key={ index } From 0c2704c848e688098ed4f2eb8f9fa0abb3114bb8 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Thu, 25 Jul 2024 15:23:08 +0100 Subject: [PATCH 0102/1908] Fix toggle help indentation (#63903) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: paaljoachim <paaljoachim@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/toggle-control/style.scss | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 4a423eeb4a57df..6c32534598fb5c 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -17,6 +17,7 @@ - `ComboboxControl`: Fix ComboboxControl reset button when using the keyboard. ([#63410](https://github.com/WordPress/gutenberg/pull/63410)) - `Button`: Never apply `aria-disabled` to anchor ([#63376](https://github.com/WordPress/gutenberg/pull/63376)). - `SelectControl`: Fix hover/focus color in wp-admin ([#63855](https://github.com/WordPress/gutenberg/pull/63855)). +- `ToggleControl`: Fix indentation ([#63903](https://github.com/WordPress/gutenberg/pull/63903)). ### Enhancements diff --git a/packages/components/src/toggle-control/style.scss b/packages/components/src/toggle-control/style.scss index 263a372b00fe84..68733b53a9bc94 100644 --- a/packages/components/src/toggle-control/style.scss +++ b/packages/components/src/toggle-control/style.scss @@ -7,5 +7,6 @@ } .components-toggle-control__help { - margin-left: $toggle-width + $grid-unit-10; + display: inline-block; + margin-inline-start: $toggle-width + $grid-unit-10; } From e434ec4bdce19d46d610bfd9d28924bdbe095a7e Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 25 Jul 2024 23:54:54 +0900 Subject: [PATCH 0103/1908] .wp-env.json schema: Fix schema and add unit tests (#63281) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> --- schemas/json/wp-env.json | 4 ++- test/integration/wp-env-schema.test.js | 38 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 test/integration/wp-env-schema.test.js diff --git a/schemas/json/wp-env.json b/schemas/json/wp-env.json index 9208ff8e0661f2..491d1f8cf73017 100644 --- a/schemas/json/wp-env.json +++ b/schemas/json/wp-env.json @@ -82,6 +82,7 @@ "$ref": "#/definitions/wpEnvProperties" }, { + "type": "object", "properties": { "$schema": { "type": "string" @@ -91,10 +92,10 @@ "type": "object", "patternProperties": { "[a-zA-Z]": { - "type": "object", "allOf": [ { "$ref": "#/definitions/wpEnvProperties" }, { + "type": "object", "propertyNames": { "$ref": "#/definitions/wpEnvPropertyNames" } @@ -107,6 +108,7 @@ } }, { + "type": "object", "propertyNames": { "anyOf": [ { diff --git a/test/integration/wp-env-schema.test.js b/test/integration/wp-env-schema.test.js new file mode 100644 index 00000000000000..48ef039a8fb0d5 --- /dev/null +++ b/test/integration/wp-env-schema.test.js @@ -0,0 +1,38 @@ +/** + * External dependencies + */ +import Ajv from 'ajv'; + +/** + * Internal dependencies + */ +import wpEnvSchema from '../../schemas/json/wp-env.json'; +import wpEnvJsonFile from '../../.wp-env.json'; + +describe( '.wp-env.json schema', () => { + const ajv = new Ajv( { + allowMatchingProperties: true, + } ); + + test( 'strictly adheres to the draft-07 meta schema', () => { + // Use ajv.compile instead of ajv.validateSchema to validate the schema + // because validateSchema only checks syntax, whereas, compile checks + // if the schema is semantically correct with strict mode. + // See https://github.com/ajv-validator/ajv/issues/1434#issuecomment-822982571 + const result = ajv.compile( wpEnvSchema ); + + expect( result.errors ).toBe( null ); + } ); + + test( 'validates schema for .wp-env.json', () => { + // We want to validate the .wp-env.json file using the local schema. + const { $schema, ...metadata } = wpEnvJsonFile; + + // we expect the $schema property to be present in the .wp-env.json file + expect( $schema ).toBeTruthy(); + + const result = ajv.validate( wpEnvSchema, metadata ) || ajv.errors; + + expect( result ).toBe( true ); + } ); +} ); From a5cb97671f9f4463fdb532585ed47c295298abd3 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 25 Jul 2024 17:16:40 +0200 Subject: [PATCH 0104/1908] DataViews: Optimize the templates dataviews by extracting the fields definition (#63929) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../src/components/page-templates/fields.js | 157 ++++++++++++++++ .../src/components/page-templates/index.js | 173 ++---------------- .../src/components/page-templates/style.scss | 6 +- 3 files changed, 172 insertions(+), 164 deletions(-) create mode 100644 packages/edit-site/src/components/page-templates/fields.js diff --git a/packages/edit-site/src/components/page-templates/fields.js b/packages/edit-site/src/components/page-templates/fields.js new file mode 100644 index 00000000000000..d26f1906a10664 --- /dev/null +++ b/packages/edit-site/src/components/page-templates/fields.js @@ -0,0 +1,157 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ +import { Icon, __experimentalHStack as HStack } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { useState, useMemo } from '@wordpress/element'; +import { decodeEntities } from '@wordpress/html-entities'; +import { parse } from '@wordpress/blocks'; +import { + BlockPreview, + privateApis as blockEditorPrivateApis, +} from '@wordpress/block-editor'; +import { EditorProvider } from '@wordpress/editor'; + +/** + * Internal dependencies + */ +import { Async } from '../async'; +import { default as Link, useLink } from '../routes/link'; +import { useAddedBy } from './hooks'; + +import usePatternSettings from '../page-patterns/use-pattern-settings'; +import { unlock } from '../../lock-unlock'; + +const { useGlobalStyle } = unlock( blockEditorPrivateApis ); + +function PreviewField( { item } ) { + const settings = usePatternSettings(); + const [ backgroundColor = 'white' ] = useGlobalStyle( 'color.background' ); + const blocks = useMemo( () => { + return parse( item.content.raw ); + }, [ item.content.raw ] ); + const { onClick } = useLink( { + postId: item.id, + postType: item.type, + canvas: 'edit', + } ); + + const isEmpty = ! blocks?.length; + // Wrap everything in a block editor provider to ensure 'styles' that are needed + // for the previews are synced between the site editor store and the block editor store. + // Additionally we need to have the `__experimentalBlockPatterns` setting in order to + // render patterns inside the previews. + // TODO: Same approach is used in the patterns list and it becomes obvious that some of + // the block editor settings are needed in context where we don't have the block editor. + // Explore how we can solve this in a better way. + return ( + <EditorProvider post={ item } settings={ settings }> + <div + className="page-templates-preview-field" + style={ { backgroundColor } } + > + <button + className="page-templates-preview-field__button" + type="button" + onClick={ onClick } + aria-label={ item.title?.rendered || item.title } + > + { isEmpty && __( 'Empty template' ) } + { ! isEmpty && ( + <Async> + <BlockPreview blocks={ blocks } /> + </Async> + ) } + </button> + </div> + </EditorProvider> + ); +} + +export const previewField = { + label: __( 'Preview' ), + id: 'preview', + render: PreviewField, + enableSorting: false, +}; + +function TitleField( { item } ) { + const linkProps = { + params: { + postId: item.id, + postType: item.type, + canvas: 'edit', + }, + }; + return ( + <Link { ...linkProps }> + { decodeEntities( item.title?.rendered ) || __( '(no title)' ) } + </Link> + ); +} + +export const titleField = { + label: __( 'Template' ), + id: 'title', + getValue: ( { item } ) => item.title?.rendered, + render: TitleField, + enableHiding: false, + enableGlobalSearch: true, +}; + +export const descriptionField = { + label: __( 'Description' ), + id: 'description', + render: ( { item } ) => { + return ( + item.description && ( + <span className="page-templates-description"> + { decodeEntities( item.description ) } + </span> + ) + ); + }, + enableSorting: false, + enableGlobalSearch: true, +}; + +function AuthorField( { item } ) { + const [ isImageLoaded, setIsImageLoaded ] = useState( false ); + const { text, icon, imageUrl } = useAddedBy( item.type, item.id ); + + return ( + <HStack alignment="left" spacing={ 0 }> + { imageUrl && ( + <div + className={ clsx( 'page-templates-author-field__avatar', { + 'is-loaded': isImageLoaded, + } ) } + > + <img + onLoad={ () => setIsImageLoaded( true ) } + alt="" + src={ imageUrl } + /> + </div> + ) } + { ! imageUrl && ( + <div className="page-templates-author-field__icon"> + <Icon icon={ icon } /> + </div> + ) } + <span className="page-templates-author-field__name">{ text }</span> + </HStack> + ); +} + +export const authorField = { + label: __( 'Author' ), + id: 'author', + getValue: ( { item } ) => item.author_text, + render: AuthorField, +}; diff --git a/packages/edit-site/src/components/page-templates/index.js b/packages/edit-site/src/components/page-templates/index.js index 9ec87ee8cca352..9c5db8fb1699d5 100644 --- a/packages/edit-site/src/components/page-templates/index.js +++ b/packages/edit-site/src/components/page-templates/index.js @@ -1,36 +1,18 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - /** * WordPress dependencies */ -import { Icon, __experimentalHStack as HStack } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useState, useMemo, useCallback, useEffect } from '@wordpress/element'; import { useEntityRecords } from '@wordpress/core-data'; -import { decodeEntities } from '@wordpress/html-entities'; -import { parse } from '@wordpress/blocks'; -import { - BlockPreview, - privateApis as blockEditorPrivateApis, -} from '@wordpress/block-editor'; import { DataViews, filterSortAndPaginate } from '@wordpress/dataviews'; import { privateApis as routerPrivateApis } from '@wordpress/router'; -import { - privateApis as editorPrivateApis, - EditorProvider, -} from '@wordpress/editor'; +import { privateApis as editorPrivateApis } from '@wordpress/editor'; /** * Internal dependencies */ -import { Async } from '../async'; import Page from '../page'; -import { default as Link, useLink } from '../routes/link'; import AddNewTemplate from '../add-new-template'; -import { useAddedBy } from './hooks'; import { TEMPLATE_POST_TYPE, OPERATOR_IS_ANY, @@ -38,14 +20,16 @@ import { LAYOUT_TABLE, LAYOUT_LIST, } from '../../utils/constants'; - -import usePatternSettings from '../page-patterns/use-pattern-settings'; import { unlock } from '../../lock-unlock'; import { useEditPostAction } from '../dataviews-actions'; +import { + authorField, + descriptionField, + previewField, + titleField, +} from './fields'; const { usePostActions } = unlock( editorPrivateApis ); - -const { useGlobalStyle } = unlock( blockEditorPrivateApis ); const { useHistory, useLocation } = unlock( routerPrivateApis ); const EMPTY_ARRAY = []; @@ -109,104 +93,6 @@ const DEFAULT_VIEW = { filters: [], }; -function Title( { item, viewType } ) { - if ( viewType === LAYOUT_LIST ) { - return decodeEntities( item.title?.rendered ) || __( '(no title)' ); - } - const linkProps = { - params: { - postId: item.id, - postType: item.type, - canvas: 'edit', - }, - }; - return ( - <Link { ...linkProps }> - { decodeEntities( item.title?.rendered ) || __( '(no title)' ) } - </Link> - ); -} - -function AuthorField( { item } ) { - const [ isImageLoaded, setIsImageLoaded ] = useState( false ); - const { text, icon, imageUrl } = useAddedBy( item.type, item.id ); - - return ( - <HStack alignment="left" spacing={ 0 }> - { imageUrl && ( - <div - className={ clsx( 'page-templates-author-field__avatar', { - 'is-loaded': isImageLoaded, - } ) } - > - <img - onLoad={ () => setIsImageLoaded( true ) } - alt="" - src={ imageUrl } - /> - </div> - ) } - { ! imageUrl && ( - <div className="page-templates-author-field__icon"> - <Icon icon={ icon } /> - </div> - ) } - <span className="page-templates-author-field__name">{ text }</span> - </HStack> - ); -} - -function Preview( { item, viewType } ) { - const settings = usePatternSettings(); - const [ backgroundColor = 'white' ] = useGlobalStyle( 'color.background' ); - const blocks = useMemo( () => { - return parse( item.content.raw ); - }, [ item.content.raw ] ); - const { onClick } = useLink( { - postId: item.id, - postType: item.type, - canvas: 'edit', - } ); - - const isEmpty = ! blocks?.length; - // Wrap everything in a block editor provider to ensure 'styles' that are needed - // for the previews are synced between the site editor store and the block editor store. - // Additionally we need to have the `__experimentalBlockPatterns` setting in order to - // render patterns inside the previews. - // TODO: Same approach is used in the patterns list and it becomes obvious that some of - // the block editor settings are needed in context where we don't have the block editor. - // Explore how we can solve this in a better way. - return ( - <EditorProvider post={ item } settings={ settings }> - <div - className={ `page-templates-preview-field is-viewtype-${ viewType }` } - style={ { backgroundColor } } - > - { viewType === LAYOUT_LIST && ! isEmpty && ( - <Async> - <BlockPreview blocks={ blocks } /> - </Async> - ) } - { viewType !== LAYOUT_LIST && ( - <button - className="page-templates-preview-field__button" - type="button" - onClick={ onClick } - aria-label={ item.title?.rendered || item.title } - > - { isEmpty && __( 'Empty template' ) } - { ! isEmpty && ( - <Async> - <BlockPreview blocks={ blocks } /> - </Async> - ) } - </button> - ) } - </div> - </EditorProvider> - ); -} - export default function PageTemplates() { const { params } = useLocation(); const { activeView = 'all', layout, postId } = params; @@ -285,50 +171,15 @@ export default function PageTemplates() { const fields = useMemo( () => [ + previewField, + titleField, + descriptionField, { - label: __( 'Preview' ), - id: 'preview', - render: ( { item } ) => { - return <Preview item={ item } viewType={ view.type } />; - }, - enableSorting: false, - }, - { - label: __( 'Template' ), - id: 'title', - getValue: ( { item } ) => item.title?.rendered, - render: ( { item } ) => ( - <Title item={ item } viewType={ view.type } /> - ), - enableHiding: false, - enableGlobalSearch: true, - }, - { - label: __( 'Description' ), - id: 'description', - render: ( { item } ) => { - return ( - item.description && ( - <span className="page-templates-description"> - { decodeEntities( item.description ) } - </span> - ) - ); - }, - enableSorting: false, - enableGlobalSearch: true, - }, - { - label: __( 'Author' ), - id: 'author', - getValue: ( { item } ) => item.author_text, - render: ( { item } ) => { - return <AuthorField viewType={ view.type } item={ item } />; - }, + ...authorField, elements: authors, }, ], - [ authors, view.type ] + [ authors ] ); const { data, paginationInfo } = useMemo( () => { diff --git a/packages/edit-site/src/components/page-templates/style.scss b/packages/edit-site/src/components/page-templates/style.scss index 725a3c4f89746c..f3d596cc90f18e 100644 --- a/packages/edit-site/src/components/page-templates/style.scss +++ b/packages/edit-site/src/components/page-templates/style.scss @@ -22,19 +22,19 @@ } } - &.is-viewtype-list { + .dataviews-view-list & { .block-editor-block-preview__container { height: 120px; } } - &.is-viewtype-grid { + .dataviews-view-grid & { .block-editor-block-preview__container { height: 100%; } } - &.is-viewtype-table { + .dataviews-view-table & { border-radius: $radius-block-ui; position: relative; From c460ed3a799302ce85dd4b8b17c1d8becb7a6a9d Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 25 Jul 2024 17:33:24 +0200 Subject: [PATCH 0105/1908] DataViews: Optimize the patterns dataviews by extracting the fields definition (#63927) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../src/components/page-patterns/fields.js | 251 +++++++++++++++++ .../src/components/page-patterns/index.js | 258 +----------------- .../src/components/page-patterns/style.scss | 166 ++++++----- 3 files changed, 346 insertions(+), 329 deletions(-) create mode 100644 packages/edit-site/src/components/page-patterns/fields.js diff --git a/packages/edit-site/src/components/page-patterns/fields.js b/packages/edit-site/src/components/page-patterns/fields.js new file mode 100644 index 00000000000000..eab6dbca32833a --- /dev/null +++ b/packages/edit-site/src/components/page-patterns/fields.js @@ -0,0 +1,251 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ +import { + __experimentalHStack as HStack, + Button, + Tooltip, + Flex, +} from '@wordpress/components'; +import { __, _x } from '@wordpress/i18n'; +import { useState, useMemo, useId } from '@wordpress/element'; +import { + BlockPreview, + privateApis as blockEditorPrivateApis, +} from '@wordpress/block-editor'; +import { Icon, lockSmall } from '@wordpress/icons'; +import { parse } from '@wordpress/blocks'; +import { decodeEntities } from '@wordpress/html-entities'; + +/** + * Internal dependencies + */ +import { Async } from '../async'; +import { + PATTERN_TYPES, + TEMPLATE_PART_POST_TYPE, + PATTERN_SYNC_TYPES, + OPERATOR_IS, +} from '../../utils/constants'; +import { unlock } from '../../lock-unlock'; +import { useLink } from '../routes/link'; +import { useAddedBy } from '../page-templates/hooks'; +import { defaultGetTitle } from './search-items'; + +const { useGlobalStyle } = unlock( blockEditorPrivateApis ); + +function PreviewWrapper( { item, onClick, ariaDescribedBy, children } ) { + return ( + <button + className="page-patterns-preview-field__button" + type="button" + onClick={ item.type !== PATTERN_TYPES.theme ? onClick : undefined } + aria-label={ item.title } + aria-describedby={ ariaDescribedBy } + aria-disabled={ item.type === PATTERN_TYPES.theme } + > + { children } + </button> + ); +} + +function PreviewField( { item } ) { + const descriptionId = useId(); + const description = item.description || item?.excerpt?.raw; + const isUserPattern = item.type === PATTERN_TYPES.user; + const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE; + const [ backgroundColor ] = useGlobalStyle( 'color.background' ); + const { onClick } = useLink( { + postType: item.type, + postId: isUserPattern || isTemplatePart ? item.id : item.name, + canvas: 'edit', + } ); + const blocks = useMemo( () => { + return ( + item.blocks ?? + parse( item.content.raw, { + __unstableSkipMigrationLogs: true, + } ) + ); + }, [ item?.content?.raw, item.blocks ] ); + const isEmpty = ! blocks?.length; + + return ( + <div + className="page-patterns-preview-field" + style={ { backgroundColor } } + > + <PreviewWrapper + item={ item } + onClick={ onClick } + ariaDescribedBy={ !! description ? descriptionId : undefined } + > + { isEmpty && isTemplatePart && __( 'Empty template part' ) } + { isEmpty && ! isTemplatePart && __( 'Empty pattern' ) } + { ! isEmpty && ( + <Async> + <BlockPreview + blocks={ blocks } + viewportWidth={ item.viewportWidth } + /> + </Async> + ) } + </PreviewWrapper> + { !! description && ( + <div hidden id={ descriptionId }> + { description } + </div> + ) } + </div> + ); +} + +export const previewField = { + label: __( 'Preview' ), + id: 'preview', + render: PreviewField, + enableSorting: false, +}; + +function TitleField( { item } ) { + const isUserPattern = item.type === PATTERN_TYPES.user; + const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE; + const { onClick } = useLink( { + postType: item.type, + postId: isUserPattern || isTemplatePart ? item.id : item.name, + canvas: 'edit', + } ); + const title = decodeEntities( defaultGetTitle( item ) ); + return ( + <HStack alignment="center" justify="flex-start" spacing={ 2 }> + <Flex + as="div" + gap={ 0 } + justify="left" + className="edit-site-patterns__pattern-title" + > + { item.type === PATTERN_TYPES.theme ? ( + title + ) : ( + <Button + variant="link" + onClick={ onClick } + // Required for the grid's roving tab index system. + // See https://github.com/WordPress/gutenberg/pull/51898#discussion_r1243399243. + tabIndex="-1" + > + { title } + </Button> + ) } + </Flex> + { item.type === PATTERN_TYPES.theme && ( + <Tooltip + placement="top" + text={ __( 'This pattern cannot be edited.' ) } + > + <Icon + className="edit-site-patterns__pattern-lock-icon" + icon={ lockSmall } + size={ 24 } + /> + </Tooltip> + ) } + </HStack> + ); +} + +export const titleField = { + label: __( 'Title' ), + id: 'title', + getValue: ( { item } ) => item.title?.raw || item.title, + render: TitleField, + enableHiding: false, +}; + +const SYNC_FILTERS = [ + { + value: PATTERN_SYNC_TYPES.full, + label: _x( 'Synced', 'pattern (singular)' ), + description: __( 'Patterns that are kept in sync across the site.' ), + }, + { + value: PATTERN_SYNC_TYPES.unsynced, + label: _x( 'Not synced', 'pattern (singular)' ), + description: __( + 'Patterns that can be changed freely without affecting the site.' + ), + }, +]; + +export const patternStatusField = { + label: __( 'Sync status' ), + id: 'sync-status', + render: ( { item } ) => { + const syncStatus = + 'wp_pattern_sync_status' in item + ? item.wp_pattern_sync_status || PATTERN_SYNC_TYPES.full + : PATTERN_SYNC_TYPES.unsynced; + // User patterns can have their sync statuses checked directly. + // Non-user patterns are all unsynced for the time being. + return ( + <span + className={ `edit-site-patterns__field-sync-status-${ syncStatus }` } + > + { + SYNC_FILTERS.find( ( { value } ) => value === syncStatus ) + .label + } + </span> + ); + }, + elements: SYNC_FILTERS, + filterBy: { + operators: [ OPERATOR_IS ], + isPrimary: true, + }, + enableSorting: false, +}; + +function AuthorField( { item } ) { + const [ isImageLoaded, setIsImageLoaded ] = useState( false ); + const { text, icon, imageUrl } = useAddedBy( item.type, item.id ); + + return ( + <HStack alignment="left" spacing={ 0 }> + { imageUrl && ( + <div + className={ clsx( 'page-templates-author-field__avatar', { + 'is-loaded': isImageLoaded, + } ) } + > + <img + onLoad={ () => setIsImageLoaded( true ) } + alt="" + src={ imageUrl } + /> + </div> + ) } + { ! imageUrl && ( + <div className="page-templates-author-field__icon"> + <Icon icon={ icon } /> + </div> + ) } + <span className="page-templates-author-field__name">{ text }</span> + </HStack> + ); +} + +export const templatePartAuthorField = { + label: __( 'Author' ), + id: 'author', + getValue: ( { item } ) => item.author_text, + render: AuthorField, + filterBy: { + isPrimary: true, + }, +}; diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index a0f107e91601bd..a8db73272c0ce7 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -1,59 +1,39 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - /** * WordPress dependencies */ -import { - __experimentalHStack as HStack, - Button, - Tooltip, - Flex, -} from '@wordpress/components'; -import { __, _x } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; import { useState, useMemo, useId, useEffect } from '@wordpress/element'; -import { - BlockPreview, - privateApis as blockEditorPrivateApis, -} from '@wordpress/block-editor'; +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { DataViews, filterSortAndPaginate } from '@wordpress/dataviews'; -import { Icon, lockSmall } from '@wordpress/icons'; import { usePrevious } from '@wordpress/compose'; import { useEntityRecords } from '@wordpress/core-data'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { privateApis as routerPrivateApis } from '@wordpress/router'; -import { parse } from '@wordpress/blocks'; -import { decodeEntities } from '@wordpress/html-entities'; /** * Internal dependencies */ -import { Async } from '../async'; import Page from '../page'; import { LAYOUT_GRID, LAYOUT_TABLE, - LAYOUT_LIST, PATTERN_TYPES, TEMPLATE_PART_POST_TYPE, - PATTERN_SYNC_TYPES, PATTERN_DEFAULT_CATEGORY, - OPERATOR_IS, } from '../../utils/constants'; import usePatternSettings from './use-pattern-settings'; import { unlock } from '../../lock-unlock'; import usePatterns from './use-patterns'; import PatternsHeader from './header'; -import { useLink } from '../routes/link'; -import { useAddedBy } from '../page-templates/hooks'; import { useEditPostAction } from '../dataviews-actions'; -import { defaultGetTitle } from './search-items'; +import { + patternStatusField, + previewField, + titleField, + templatePartAuthorField, +} from './fields'; -const { ExperimentalBlockEditorProvider, useGlobalStyle } = unlock( - blockEditorPrivateApis -); +const { ExperimentalBlockEditorProvider } = unlock( blockEditorPrivateApis ); const { usePostActions } = unlock( editorPrivateApis ); const { useLocation } = unlock( routerPrivateApis ); @@ -90,164 +70,6 @@ const DEFAULT_VIEW = { filters: [], }; -const SYNC_FILTERS = [ - { - value: PATTERN_SYNC_TYPES.full, - label: _x( 'Synced', 'pattern (singular)' ), - description: __( 'Patterns that are kept in sync across the site.' ), - }, - { - value: PATTERN_SYNC_TYPES.unsynced, - label: _x( 'Not synced', 'pattern (singular)' ), - description: __( - 'Patterns that can be changed freely without affecting the site.' - ), - }, -]; - -function PreviewWrapper( { item, onClick, ariaDescribedBy, children } ) { - return ( - <button - className="page-patterns-preview-field__button" - type="button" - onClick={ item.type !== PATTERN_TYPES.theme ? onClick : undefined } - aria-label={ item.title } - aria-describedby={ ariaDescribedBy } - aria-disabled={ item.type === PATTERN_TYPES.theme } - > - { children } - </button> - ); -} - -function Preview( { item, viewType } ) { - const descriptionId = useId(); - const description = item.description || item?.excerpt?.raw; - const isUserPattern = item.type === PATTERN_TYPES.user; - const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE; - const [ backgroundColor ] = useGlobalStyle( 'color.background' ); - const { onClick } = useLink( { - postType: item.type, - postId: isUserPattern || isTemplatePart ? item.id : item.name, - canvas: 'edit', - } ); - const blocks = useMemo( () => { - return ( - item.blocks ?? - parse( item.content.raw, { - __unstableSkipMigrationLogs: true, - } ) - ); - }, [ item?.content?.raw, item.blocks ] ); - const isEmpty = ! blocks?.length; - - return ( - <div - className={ `page-patterns-preview-field is-viewtype-${ viewType }` } - style={ { backgroundColor } } - > - <PreviewWrapper - item={ item } - onClick={ onClick } - ariaDescribedBy={ !! description ? descriptionId : undefined } - > - { isEmpty && isTemplatePart && __( 'Empty template part' ) } - { isEmpty && ! isTemplatePart && __( 'Empty pattern' ) } - { ! isEmpty && ( - <Async> - <BlockPreview - blocks={ blocks } - viewportWidth={ item.viewportWidth } - /> - </Async> - ) } - </PreviewWrapper> - { !! description && ( - <div hidden id={ descriptionId }> - { description } - </div> - ) } - </div> - ); -} - -function Author( { item, viewType } ) { - const [ isImageLoaded, setIsImageLoaded ] = useState( false ); - const { text, icon, imageUrl } = useAddedBy( item.type, item.id ); - const withIcon = viewType !== LAYOUT_LIST; - - return ( - <HStack alignment="left" spacing={ 0 }> - { withIcon && imageUrl && ( - <div - className={ clsx( 'page-templates-author-field__avatar', { - 'is-loaded': isImageLoaded, - } ) } - > - <img - onLoad={ () => setIsImageLoaded( true ) } - alt="" - src={ imageUrl } - /> - </div> - ) } - { withIcon && ! imageUrl && ( - <div className="page-templates-author-field__icon"> - <Icon icon={ icon } /> - </div> - ) } - <span className="page-templates-author-field__name">{ text }</span> - </HStack> - ); -} - -function Title( { item } ) { - const isUserPattern = item.type === PATTERN_TYPES.user; - const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE; - const { onClick } = useLink( { - postType: item.type, - postId: isUserPattern || isTemplatePart ? item.id : item.name, - canvas: 'edit', - } ); - const title = decodeEntities( defaultGetTitle( item ) ); - return ( - <HStack alignment="center" justify="flex-start" spacing={ 2 }> - <Flex - as="div" - gap={ 0 } - justify="left" - className="edit-site-patterns__pattern-title" - > - { item.type === PATTERN_TYPES.theme ? ( - title - ) : ( - <Button - variant="link" - onClick={ onClick } - // Required for the grid's roving tab index system. - // See https://github.com/WordPress/gutenberg/pull/51898#discussion_r1243399243. - tabIndex="-1" - > - { title } - </Button> - ) } - </Flex> - { item.type === PATTERN_TYPES.theme && ( - <Tooltip - placement="top" - text={ __( 'This pattern cannot be edited.' ) } - > - <Icon - className="edit-site-patterns__pattern-lock-icon" - icon={ lockSmall } - size={ 24 } - /> - </Tooltip> - ) } - </HStack> - ); -} - export default function DataviewsPatterns() { const { params: { postType, categoryId: categoryIdFromURL }, @@ -267,6 +89,7 @@ export default function DataviewsPatterns() { const { records } = useEntityRecords( 'postType', TEMPLATE_PART_POST_TYPE, { per_page: -1, } ); + const authors = useMemo( () => { if ( ! records ) { return EMPTY_ARRAY; @@ -282,72 +105,19 @@ export default function DataviewsPatterns() { }, [ records ] ); const fields = useMemo( () => { - const _fields = [ - { - label: __( 'Preview' ), - id: 'preview', - render: ( { item } ) => ( - <Preview item={ item } viewType={ view.type } /> - ), - enableSorting: false, - }, - { - label: __( 'Title' ), - id: 'title', - getValue: ( { item } ) => item.title?.raw || item.title, - render: ( { item } ) => <Title item={ item } />, - enableHiding: false, - }, - ]; + const _fields = [ previewField, titleField ]; if ( type === PATTERN_TYPES.user ) { - _fields.push( { - label: __( 'Sync status' ), - id: 'sync-status', - render: ( { item } ) => { - const syncStatus = - 'wp_pattern_sync_status' in item - ? item.wp_pattern_sync_status || - PATTERN_SYNC_TYPES.full - : PATTERN_SYNC_TYPES.unsynced; - // User patterns can have their sync statuses checked directly. - // Non-user patterns are all unsynced for the time being. - return ( - <span - className={ `edit-site-patterns__field-sync-status-${ syncStatus }` } - > - { - SYNC_FILTERS.find( - ( { value } ) => value === syncStatus - ).label - } - </span> - ); - }, - elements: SYNC_FILTERS, - filterBy: { - operators: [ OPERATOR_IS ], - isPrimary: true, - }, - enableSorting: false, - } ); + _fields.push( patternStatusField ); } else if ( type === TEMPLATE_PART_POST_TYPE ) { _fields.push( { - label: __( 'Author' ), - id: 'author', - getValue: ( { item } ) => item.author_text, - render: ( { item } ) => { - return <Author viewType={ view.type } item={ item } />; - }, + ...templatePartAuthorField, elements: authors, - filterBy: { - isPrimary: true, - }, } ); } return _fields; - }, [ view.type, type, authors ] ); + }, [ type, authors ] ); // Reset the page number when the category changes. useEffect( () => { diff --git a/packages/edit-site/src/components/page-patterns/style.scss b/packages/edit-site/src/components/page-patterns/style.scss index 2014d3b94fdae3..f457624d100c1f 100644 --- a/packages/edit-site/src/components/page-patterns/style.scss +++ b/packages/edit-site/src/components/page-patterns/style.scss @@ -1,118 +1,114 @@ -.edit-site-patterns__section-header { - .screen-reader-shortcut:focus { - top: 0; - } +.edit-site-patterns__delete-modal { + width: $modal-width-small; } -.edit-site-patterns__pattern-title { - .is-link { - text-decoration: none; - color: $gray-200; +.page-patterns-preview-field { + display: flex; + flex-direction: column; + height: 100%; - &:hover, - &:focus { - color: $white; + .dataviews-view-table & { + width: 96px; + flex-grow: 0; + border-radius: 2px; + + .page-patterns-preview-field__button { + border-radius: 2px; } } - .edit-site-patterns__pattern-icon { + .page-patterns-preview-field__button { + box-shadow: none; + border: none; + padding: 0; + background-color: unset; + box-sizing: border-box; + cursor: pointer; + overflow: hidden; + height: 100%; border-radius: $grid-unit-05; - background: var(--wp-block-synced-color); - fill: $white; - } - .edit-site-patterns__pattern-lock-icon { - fill: currentcolor; + &:focus-visible { + box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + // Windows High Contrast mode will show this outline, but not the box-shadow. + outline: 2px solid transparent; + } + + &[aria-disabled="true"] { + cursor: default; + } } } -.edit-site-patterns__delete-modal { - width: $modal-width-small; +.edit-site-patterns__pattern-icon { + fill: var(--wp-block-synced-color); + flex-shrink: 0; } -.edit-site-page-patterns-dataviews { - .page-patterns-preview-field { - display: flex; - flex-direction: column; - height: 100%; - - &.is-viewtype-table { - width: 96px; - flex-grow: 0; - border-radius: 2px; +.edit-site-patterns__pattern-lock-icon { + min-width: min-content; +} - .page-patterns-preview-field__button { - border-radius: 2px; - } - } +.edit-site-patterns__section-header { + border-bottom: 1px solid #f0f0f0; + padding: $grid-unit-20 $grid-unit-60; + position: sticky; + top: 0; + z-index: 2; + flex-shrink: 0; + transition: padding ease-out 0.1s; + @include reduce-motion("transition"); + min-height: $grid-unit-50; + + .edit-site-patterns__title { + min-height: $grid-unit-50; - .page-patterns-preview-field__button { - box-shadow: none; - border: none; - padding: 0; - background-color: unset; - box-sizing: border-box; - cursor: pointer; - overflow: hidden; - height: 100%; - border-radius: $grid-unit-05; - - &:focus-visible { - box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - // Windows High Contrast mode will show this outline, but not the box-shadow. - outline: 2px solid transparent; - } - - &[aria-disabled="true"] { - cursor: default; - } + .components-heading { + flex-grow: 1; + flex-basis: 0; + white-space: nowrap; } } - .edit-site-patterns__pattern-icon { - fill: var(--wp-block-synced-color); - flex-shrink: 0; + .edit-site-patterns__sub-title { + margin-bottom: $grid-unit-10; } - .edit-site-patterns__pattern-lock-icon { - min-width: min-content; + .screen-reader-shortcut:focus { + top: 0; } +} - .edit-site-patterns__section-header { - border-bottom: 1px solid #f0f0f0; - padding: $grid-unit-20 $grid-unit-60; - position: sticky; - top: 0; - z-index: 2; - flex-shrink: 0; - transition: padding ease-out 0.1s; - @include reduce-motion("transition"); - min-height: $grid-unit-50; +.edit-site-patterns__pattern-title { + display: block; + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + color: inherit; - .edit-site-patterns__title { - min-height: $grid-unit-50; + .is-link { + text-decoration: none; + color: $gray-200; - .components-heading { - flex-grow: 1; - flex-basis: 0; - white-space: nowrap; - } + &:hover, + &:focus { + color: $white; } + } - .edit-site-patterns__sub-title { - margin-bottom: $grid-unit-10; - } + .edit-site-patterns__pattern-icon { + border-radius: $grid-unit-05; + background: var(--wp-block-synced-color); + fill: $white; } - .edit-site-patterns__pattern-title { - display: block; - width: 100%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - color: inherit; + .edit-site-patterns__pattern-lock-icon { + fill: currentcolor; } +} +.edit-site-page-patterns-dataviews { .dataviews-pagination { z-index: z-index(".edit-site-patterns__dataviews-list-pagination"); } From 2fcba1b3d8f91ba067306f1701bf3968bf2df436 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Thu, 25 Jul 2024 19:22:26 +0200 Subject: [PATCH 0106/1908] Move logic outside reducer (#63941) Move bindings logic to merge usesContext outside reducer Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/blocks/src/store/reducer.js | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 2f141fb0cf9927..9fd97f0937b332 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -371,16 +371,21 @@ export function collections( state = {}, action ) { return state; } -export function blockBindingsSources( state = {}, action ) { - // Merge usesContext with existing values, potentially defined in the server registration. - const existingUsesContext = state[ action.name ]?.usesContext || []; - const newUsesContext = action.usesContext || []; +/** + * Merges usesContext with existing values, potentially defined in the server registration. + * + * @param {string[]} existingUsesContext Existing `usesContext`. + * @param {string[]} newUsesContext Newly added `usesContext`. + * @return {string[]|undefined} Merged `usesContext`. + */ +function getMergedUsesContext( existingUsesContext = [], newUsesContext = [] ) { const mergedArrays = Array.from( new Set( existingUsesContext.concat( newUsesContext ) ) ); - const mergedUsesContext = - mergedArrays.length > 0 ? mergedArrays : undefined; + return mergedArrays.length > 0 ? mergedArrays : undefined; +} +export function blockBindingsSources( state = {}, action ) { switch ( action.type ) { case 'ADD_BLOCK_BINDINGS_SOURCE': return { @@ -388,7 +393,10 @@ export function blockBindingsSources( state = {}, action ) { [ action.name ]: { // Don't override the label if it's already set. label: state[ action.name ]?.label || action.label, - usesContext: mergedUsesContext, + usesContext: getMergedUsesContext( + state[ action.name ]?.usesContext, + action.usesContext + ), getValues: action.getValues, setValues: action.setValues, getPlaceholder: action.getPlaceholder, @@ -405,7 +413,10 @@ export function blockBindingsSources( state = {}, action ) { */ ...state[ action.name ], label: action.label, - usesContext: mergedUsesContext, + usesContext: getMergedUsesContext( + state[ action.name ]?.usesContext, + action.usesContext + ), }, }; case 'REMOVE_BLOCK_BINDINGS_SOURCE': From cad81e428aed155fa3e490cc9c8d9673a170c3fd Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Thu, 25 Jul 2024 23:44:43 +0530 Subject: [PATCH 0107/1908] Small Typo Correction in Inline Document (#63952) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> --- lib/compat/wordpress-6.7/block-bindings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compat/wordpress-6.7/block-bindings.php b/lib/compat/wordpress-6.7/block-bindings.php index 4c82dc6683f370..398b53b340673b 100644 --- a/lib/compat/wordpress-6.7/block-bindings.php +++ b/lib/compat/wordpress-6.7/block-bindings.php @@ -1,6 +1,6 @@ <?php /** - * Temporary compatibility code for new functionalitites/changes related to block bindings APIs present in Gutenberg. + * Temporary compatibility code for new functionalities/changes related to block bindings APIs present in Gutenberg. * * @package gutenberg */ From d1a2f43d2cfe4039d6a72b3e0160cda2a0323881 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 26 Jul 2024 10:02:58 +1000 Subject: [PATCH 0108/1908] Tag Cloud: Prevent duplicate spacing in editor (#63832) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/block-library/src/editor.scss | 1 + packages/block-library/src/tag-cloud/editor.scss | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 packages/block-library/src/tag-cloud/editor.scss diff --git a/packages/block-library/src/editor.scss b/packages/block-library/src/editor.scss index c43137c632b73f..52f3aa64287fae 100644 --- a/packages/block-library/src/editor.scss +++ b/packages/block-library/src/editor.scss @@ -44,6 +44,7 @@ @import "./social-links/editor.scss"; @import "./spacer/editor.scss"; @import "./table/editor.scss"; +@import "./tag-cloud/editor.scss"; @import "./template-part/editor.scss"; @import "./text-columns/editor.scss"; @import "./video/editor.scss"; diff --git a/packages/block-library/src/tag-cloud/editor.scss b/packages/block-library/src/tag-cloud/editor.scss new file mode 100644 index 00000000000000..de2a95a386fa85 --- /dev/null +++ b/packages/block-library/src/tag-cloud/editor.scss @@ -0,0 +1,9 @@ +// The following styles are to prevent duplicate spacing for the tag cloud +// block in the editor given it uses server side rendering. The specificity +// must be higher than `0-1-0` to override global styles. Targeting the +// inner use of the .wp-block-tag-cloud class should minimize impact on +// other 3rd party styles targeting the block. +.wp-block-tag-cloud .wp-block-tag-cloud { + margin: 0; + padding: 0; +} From e98f358d82ef908f9d26be87c330a380ef799516 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Fri, 26 Jul 2024 11:58:30 +1000 Subject: [PATCH 0109/1908] Grid layout: Try moving resizer popover slot to fix an issue on mobile (#63920) Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-editor/src/components/grid/grid-item-resizer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/grid/grid-item-resizer.js b/packages/block-editor/src/components/grid/grid-item-resizer.js index 6f6fa655b35568..34bc1db6048067 100644 --- a/packages/block-editor/src/components/grid/grid-item-resizer.js +++ b/packages/block-editor/src/components/grid/grid-item-resizer.js @@ -98,7 +98,7 @@ function GridItemResizerInner( { <BlockPopoverCover className="block-editor-grid-item-resizer" clientId={ clientId } - __unstablePopoverSlot="block-toolbar" + __unstablePopoverSlot="__unstable-block-tools-after" additionalStyles={ styles } > <ResizableBox From eea7183c6b156610cd3daa538e98a8b4b5388c2e Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Fri, 26 Jul 2024 08:44:03 +0200 Subject: [PATCH 0110/1908] Fix unlabeled Spacer block controls (#63806) * Fix missing label for horizontal spacer. * Remove unnecessary BaseControl. * Add missing label to SpacingInputControl RangeControl. * Hide label from vision. * Use 40px size for the Unit control. * Try grid layout for the single unit control. * Remove Grid experiment and show single unit control full width. * Restore conditional that was changed for testing purposes. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: joedolson <joedolson@git.wordpress.org> --- .../components/child-layout-control/index.js | 2 ++ .../input-controls/spacing-input-control.js | 2 ++ packages/block-library/src/spacer/controls.js | 23 ++++++++----------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/block-editor/src/components/child-layout-control/index.js b/packages/block-editor/src/components/child-layout-control/index.js index 698ea2d2d74a42..022acf2e1074a4 100644 --- a/packages/block-editor/src/components/child-layout-control/index.js +++ b/packages/block-editor/src/components/child-layout-control/index.js @@ -174,6 +174,8 @@ function FlexControls( { } ); } } value={ flexSize } + label={ flexResetLabel } + hideLabelFromVision /> ) } </VStack> diff --git a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js index bec589f2ed9aa8..6605d2de502fe8 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js +++ b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js @@ -266,6 +266,8 @@ export default function SpacingInputControl( { onChange={ handleCustomValueSliderChange } className="spacing-sizes-control__custom-value-range" __nextHasNoMarginBottom + label={ ariaLabel } + hideLabelFromVision /> </> ) } diff --git a/packages/block-library/src/spacer/controls.js b/packages/block-library/src/spacer/controls.js index 160335fcc092e9..1e899e15aff0de 100644 --- a/packages/block-library/src/spacer/controls.js +++ b/packages/block-library/src/spacer/controls.js @@ -10,7 +10,6 @@ import { privateApis as blockEditorPrivateApis, } from '@wordpress/block-editor'; import { - BaseControl, PanelBody, __experimentalUseCustomUnits as useCustomUnits, __experimentalUnitControl as UnitControl, @@ -57,19 +56,17 @@ function DimensionInput( { label, onChange, isResizing, value = '' } ) { return ( <> { ( ! spacingSizes || spacingSizes?.length === 0 ) && ( - <BaseControl label={ label } id={ inputId }> - <UnitControl - id={ inputId } - isResetValueOnUnitChange - min={ MIN_SPACER_SIZE } - onChange={ handleOnChange } - style={ { maxWidth: 80 } } - value={ computedValue } - units={ units } - /> - </BaseControl> + <UnitControl + id={ inputId } + isResetValueOnUnitChange + min={ MIN_SPACER_SIZE } + onChange={ handleOnChange } + value={ computedValue } + units={ units } + label={ label } + __next40pxDefaultSize + /> ) } - { spacingSizes?.length > 0 && ( <View className="tools-panel-item-spacing"> <SpacingSizesControl From 9f7e26ff4be7e23baeb7afb56bc98a221efcf013 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 26 Jul 2024 11:36:21 +0400 Subject: [PATCH 0111/1908] TemplateContentPanel: Fix the 'getBlocksByName' selector call (#63922) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> --- .../components/provider/disable-non-page-content-blocks.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/provider/disable-non-page-content-blocks.js b/packages/editor/src/components/provider/disable-non-page-content-blocks.js index 35b060b096c069..9abb0e14079d5e 100644 --- a/packages/editor/src/components/provider/disable-non-page-content-blocks.js +++ b/packages/editor/src/components/provider/disable-non-page-content-blocks.js @@ -45,8 +45,8 @@ export default function DisableNonPageContentBlocks() { ); const disabledIds = useSelect( ( select ) => { const { getBlocksByName, getBlockOrder } = select( blockEditorStore ); - return getBlocksByName( [ 'core/template-part' ] ).flatMap( - ( clientId ) => getBlockOrder( clientId ) + return getBlocksByName( 'core/template-part' ).flatMap( ( clientId ) => + getBlockOrder( clientId ) ); }, [] ); From 654fef6f20cdb004b13efe5064175c297bf96150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 26 Jul 2024 10:58:38 +0200 Subject: [PATCH 0112/1908] DataForm: migrate order action modal and introduce form validation (#63895) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../src/components/dataform/index.tsx | 38 ++++++++++- .../dataform/stories/index.story.tsx | 8 ++- packages/dataviews/src/index.ts | 1 + packages/dataviews/src/test/validation.ts | 63 +++++++++++++++++++ packages/dataviews/src/types.ts | 7 ++- packages/dataviews/src/validation.ts | 33 ++++++++++ .../src/components/post-actions/actions.js | 49 ++++++++------- 7 files changed, 172 insertions(+), 27 deletions(-) create mode 100644 packages/dataviews/src/test/validation.ts create mode 100644 packages/dataviews/src/validation.ts diff --git a/packages/dataviews/src/components/dataform/index.tsx b/packages/dataviews/src/components/dataform/index.tsx index 64196c685a9784..42a6766813975e 100644 --- a/packages/dataviews/src/components/dataform/index.tsx +++ b/packages/dataviews/src/components/dataform/index.tsx @@ -6,13 +6,16 @@ import type { Dispatch, SetStateAction } from 'react'; /** * WordPress dependencies */ -import { TextControl } from '@wordpress/components'; +import { + TextControl, + __experimentalNumberControl as NumberControl, +} from '@wordpress/components'; import { useCallback, useMemo } from '@wordpress/element'; /** * Internal dependencies */ -import type { Form, Field, NormalizedField } from '../../types'; +import type { Form, Field, NormalizedField, FieldType } from '../../types'; import { normalizeFields } from '../../normalize-fields'; type DataFormProps< Item > = { @@ -56,12 +59,41 @@ function DataFormTextControl< Item >( { ); } +function DataFormNumberControl< Item >( { + data, + field, + onChange, +}: DataFormControlProps< Item > ) { + const { id, label, description } = field; + const value = field.getValue( { item: data } ); + + const onChangeControl = useCallback( + ( newValue: string | undefined ) => + onChange( ( prevItem: Item ) => ( { + ...prevItem, + [ id ]: newValue, + } ) ), + [ id, onChange ] + ); + + return ( + <NumberControl + label={ label } + help={ description } + value={ value } + onChange={ onChangeControl } + __next40pxDefaultSize + /> + ); +} + const controls: { - [ key: string ]: < Item >( + [ key in FieldType ]: < Item >( props: DataFormControlProps< Item > ) => JSX.Element; } = { text: DataFormTextControl, + integer: DataFormNumberControl, }; function getControlForField< Item >( field: NormalizedField< Item > ) { diff --git a/packages/dataviews/src/components/dataform/stories/index.story.tsx b/packages/dataviews/src/components/dataform/stories/index.story.tsx index 2e288c8e11d41c..a67eaa6b76f042 100644 --- a/packages/dataviews/src/components/dataform/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataform/stories/index.story.tsx @@ -20,15 +20,21 @@ const fields = [ label: 'Title', type: 'text' as const, }, + { + id: 'order', + label: 'Order', + type: 'integer' as const, + }, ]; export const Default = () => { const [ post, setPost ] = useState( { title: 'Hello, World!', + order: 2, } ); const form = { - visibleFields: [ 'title' ], + visibleFields: [ 'title', 'order' ], }; return ( diff --git a/packages/dataviews/src/index.ts b/packages/dataviews/src/index.ts index 8b6e53e1ff7293..95a8ab4c2e5e8d 100644 --- a/packages/dataviews/src/index.ts +++ b/packages/dataviews/src/index.ts @@ -3,3 +3,4 @@ export { default as DataForm } from './components/dataform'; export { VIEW_LAYOUTS } from './layouts'; export { filterSortAndPaginate } from './filter-and-sort-data-view'; export type * from './types'; +export { isItemValid } from './validation'; diff --git a/packages/dataviews/src/test/validation.ts b/packages/dataviews/src/test/validation.ts new file mode 100644 index 00000000000000..d90d4744ac3272 --- /dev/null +++ b/packages/dataviews/src/test/validation.ts @@ -0,0 +1,63 @@ +/** + * Internal dependencies + */ +import { isItemValid } from '../validation'; +import type { Field } from '../types'; + +describe( 'validation', () => { + it( 'fields not visible in form are not validated', () => { + const item = { id: 1, valid_order: 2, invalid_order: 'd' }; + const fields: Field< {} >[] = [ + { + id: 'valid_order', + type: 'integer', + }, + { + id: 'invalid_order', + type: 'integer', + }, + ]; + const form = { visibleFields: [ 'valid_order' ] }; + const result = isItemValid( item, fields, form ); + expect( result ).toBe( true ); + } ); + + it( 'integer field is valid if value is integer', () => { + const item = { id: 1, order: 2, title: 'hi' }; + const fields: Field< {} >[] = [ + { + type: 'integer', + id: 'order', + }, + ]; + const form = { visibleFields: [ 'order' ] }; + const result = isItemValid( item, fields, form ); + expect( result ).toBe( true ); + } ); + + it( 'integer field is invalid if value is not integer', () => { + const item = { id: 1, order: 'd' }; + const fields: Field< {} >[] = [ + { + id: 'order', + type: 'integer', + }, + ]; + const form = { visibleFields: [ 'order' ] }; + const result = isItemValid( item, fields, form ); + expect( result ).toBe( false ); + } ); + + it( 'integer field is invalid if value is empty', () => { + const item = { id: 1, order: '' }; + const fields: Field< {} >[] = [ + { + id: 'order', + type: 'integer', + }, + ]; + const form = { visibleFields: [ 'order' ] }; + const result = isItemValid( item, fields, form ); + expect( result ).toBe( false ); + } ); +} ); diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 0b43740efc3f2d..37c3efbde5cfb0 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -44,7 +44,7 @@ export type Operator = export type ItemRecord = Record< string, unknown >; -export type FieldType = 'text'; +export type FieldType = 'text' | 'integer'; /** * A dataview field for a specific property of a data type. @@ -65,6 +65,11 @@ export type Field< Item > = { */ label?: string; + /** + * A description of the field. + */ + description?: string; + /** * Placeholder for the field. */ diff --git a/packages/dataviews/src/validation.ts b/packages/dataviews/src/validation.ts new file mode 100644 index 00000000000000..5b20d094a41861 --- /dev/null +++ b/packages/dataviews/src/validation.ts @@ -0,0 +1,33 @@ +/** + * Internal dependencies + */ +import { normalizeFields } from './normalize-fields'; +import type { Field, Form } from './types'; + +export function isItemValid< Item >( + item: Item, + fields: Field< Item >[], + form: Form +): boolean { + const _fields = normalizeFields( + fields.filter( ( { id } ) => !! form.visibleFields?.includes( id ) ) + ); + return _fields.every( ( field ) => { + const value = field.getValue( { item } ); + + // TODO: this implicitely means the value is required. + if ( field.type === 'integer' && value === '' ) { + return false; + } + + if ( + field.type === 'integer' && + ! Number.isInteger( Number( value ) ) + ) { + return false; + } + + // Nothing to validate. + return true; + } ); +} diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 2a97e688eeedbe..190b8ea6ca32f5 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -11,14 +11,13 @@ import { store as noticesStore } from '@wordpress/notices'; import { useMemo, useState } from '@wordpress/element'; import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; import { parse } from '@wordpress/blocks'; -import { DataForm } from '@wordpress/dataviews'; +import { DataForm, isItemValid } from '@wordpress/dataviews'; import { Button, TextControl, __experimentalText as Text, __experimentalHStack as HStack, __experimentalVStack as VStack, - __experimentalNumberControl as NumberControl, } from '@wordpress/components'; /** @@ -39,21 +38,31 @@ import { getItemTitle } from '../../dataviews/actions/utils'; const { PATTERN_TYPES, CreatePatternModalContents, useDuplicatePatternProps } = unlock( patternsPrivateApis ); -// TODO: this should be shared with other components (page-pages). +// TODO: this should be shared with other components (see post-fields in edit-site). const fields = [ { type: 'text', - header: __( 'Title' ), id: 'title', + label: __( 'Title' ), placeholder: __( 'No title' ), getValue: ( { item } ) => item.title, }, + { + type: 'integer', + id: 'menu_order', + label: __( 'Order' ), + description: __( 'Determines the order of pages.' ), + }, ]; -const form = { +const formDuplicateAction = { visibleFields: [ 'title' ], }; +const formOrderAction = { + visibleFields: [ 'menu_order' ], +}; + /** * Check if a template is removable. * @@ -635,21 +644,20 @@ function useRenamePostAction( postType ) { } function ReorderModal( { items, closeModal, onActionPerformed } ) { - const [ item ] = items; + const [ item, setItem ] = useState( items[ 0 ] ); + const orderInput = item.menu_order; const { editEntityRecord, saveEditedEntityRecord } = useDispatch( coreStore ); const { createSuccessNotice, createErrorNotice } = useDispatch( noticesStore ); - const [ orderInput, setOrderInput ] = useState( item.menu_order ); async function onOrder( event ) { event.preventDefault(); - if ( - ! Number.isInteger( Number( orderInput ) ) || - orderInput?.trim?.() === '' - ) { + + if ( ! isItemValid( item, fields, formOrderAction ) ) { return; } + try { await editEntityRecord( 'postType', item.type, item.id, { menu_order: orderInput, @@ -673,9 +681,7 @@ function ReorderModal( { items, closeModal, onActionPerformed } ) { } ); } } - const saveIsDisabled = - ! Number.isInteger( Number( orderInput ) ) || - orderInput?.trim?.() === ''; + const isSaveDisabled = ! isItemValid( item, fields, formOrderAction ); return ( <form onSubmit={ onOrder }> <VStack spacing="5"> @@ -684,12 +690,11 @@ function ReorderModal( { items, closeModal, onActionPerformed } ) { 'Determines the order of pages. Pages with the same order value are sorted alphabetically. Negative order values are supported.' ) } </div> - <NumberControl - __next40pxDefaultSize - label={ __( 'Order' ) } - help={ __( 'Set the page order.' ) } - value={ orderInput } - onChange={ setOrderInput } + <DataForm + data={ item } + fields={ fields } + form={ formOrderAction } + onChange={ setItem } /> <HStack justify="right"> <Button @@ -706,7 +711,7 @@ function ReorderModal( { items, closeModal, onActionPerformed } ) { variant="primary" type="submit" accessibleWhenDisabled - disabled={ saveIsDisabled } + disabled={ isSaveDisabled } __experimentalIsFocusable > { __( 'Save' ) } @@ -873,7 +878,7 @@ const useDuplicatePostAction = ( postType ) => { <DataForm data={ item } fields={ fields } - form={ form } + form={ formDuplicateAction } onChange={ setItem } /> <HStack spacing={ 2 } justify="end"> From 1e28ca49aaedb395cd58abc2c11845ee97c05327 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Fri, 26 Jul 2024 10:58:53 +0200 Subject: [PATCH 0113/1908] Core Data: Add new useEntityRecordsWithPermissions hook (#63857) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> --- .../footnotes/get-rich-text-values-cached.js | 2 +- .../core-data/src/hooks/use-entity-records.ts | 50 +++++++++++++++++++ packages/core-data/src/index.js | 3 +- packages/core-data/src/lock-unlock.js | 10 ++++ packages/core-data/src/private-apis.js | 14 +++--- packages/core-data/src/private-selectors.ts | 23 +++++++++ .../src/components/post-list/index.js | 8 ++- 7 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 packages/core-data/src/lock-unlock.js diff --git a/packages/core-data/src/footnotes/get-rich-text-values-cached.js b/packages/core-data/src/footnotes/get-rich-text-values-cached.js index 06a01c5ef63fdd..a5c2d258108612 100644 --- a/packages/core-data/src/footnotes/get-rich-text-values-cached.js +++ b/packages/core-data/src/footnotes/get-rich-text-values-cached.js @@ -6,7 +6,7 @@ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; /** * Internal dependencies */ -import { unlock } from '../private-apis'; +import { unlock } from '../lock-unlock'; // TODO: The following line should have been: // diff --git a/packages/core-data/src/hooks/use-entity-records.ts b/packages/core-data/src/hooks/use-entity-records.ts index 5d643ab8896925..e2659b88bc0198 100644 --- a/packages/core-data/src/hooks/use-entity-records.ts +++ b/packages/core-data/src/hooks/use-entity-records.ts @@ -4,6 +4,7 @@ import { addQueryArgs } from '@wordpress/url'; import deprecated from '@wordpress/deprecated'; import { useSelect } from '@wordpress/data'; +import { useMemo } from '@wordpress/element'; /** * Internal dependencies @@ -12,6 +13,7 @@ import useQuerySelect from './use-query-select'; import { store as coreStore } from '../'; import type { Options } from './use-entity-record'; import type { Status } from './constants'; +import { unlock } from '../lock-unlock'; interface EntityRecordsResolution< RecordType > { /** The requested entity record */ @@ -152,3 +154,51 @@ export function __experimentalUseEntityRecords( } ); return useEntityRecords( kind, name, queryArgs, options ); } + +export function useEntityRecordsWithPermissions< RecordType >( + kind: string, + name: string, + queryArgs: Record< string, unknown > = {}, + options: Options = { enabled: true } +): EntityRecordsResolution< RecordType > { + const entityConfig = useSelect( + ( select ) => select( coreStore ).getEntityConfig( kind, name ), + [ kind, name ] + ); + const { records: data, ...ret } = useEntityRecords( + kind, + name, + queryArgs, + options + ); + const ids = useMemo( + () => + data?.map( + // @ts-ignore + ( record: RecordType ) => record[ entityConfig?.key ?? 'id' ] + ) ?? [], + [ data, entityConfig?.key ] + ); + + const permissions = useSelect( + ( select ) => { + const { getEntityRecordsPermissions } = unlock( + select( coreStore ) + ); + return getEntityRecordsPermissions( kind, name, ids ); + }, + [ ids, kind, name ] + ); + + const dataWithPermissions = useMemo( + () => + data?.map( ( record, index ) => ( { + // @ts-ignore + ...record, + permissions: permissions[ index ], + } ) ) ?? [], + [ data, permissions ] + ); + + return { records: dataWithPermissions, ...ret }; +} diff --git a/packages/core-data/src/index.js b/packages/core-data/src/index.js index bd25fa8de9902b..ad6adec0203c59 100644 --- a/packages/core-data/src/index.js +++ b/packages/core-data/src/index.js @@ -18,7 +18,7 @@ import { getMethodName, } from './entities'; import { STORE_NAME } from './name'; -import { unlock } from './private-apis'; +import { unlock } from './lock-unlock'; // The entity selectors/resolvers and actions are shortcuts to their generic equivalents // (getEntityRecord, getEntityRecords, updateEntityRecord, updateEntityRecords) @@ -86,3 +86,4 @@ export * from './entity-provider'; export * from './entity-types'; export * from './fetch'; export * from './hooks'; +export * from './private-apis'; diff --git a/packages/core-data/src/lock-unlock.js b/packages/core-data/src/lock-unlock.js new file mode 100644 index 00000000000000..91bf30792c970a --- /dev/null +++ b/packages/core-data/src/lock-unlock.js @@ -0,0 +1,10 @@ +/** + * WordPress dependencies + */ +import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; + +export const { lock, unlock } = + __dangerousOptInToUnstableAPIsOnlyForCoreModules( + 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', + '@wordpress/core-data' + ); diff --git a/packages/core-data/src/private-apis.js b/packages/core-data/src/private-apis.js index 91bf30792c970a..443db97957285d 100644 --- a/packages/core-data/src/private-apis.js +++ b/packages/core-data/src/private-apis.js @@ -1,10 +1,10 @@ /** - * WordPress dependencies + * Internal dependencies */ -import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; +import { useEntityRecordsWithPermissions } from './hooks/use-entity-records'; +import { lock } from './lock-unlock'; -export const { lock, unlock } = - __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', - '@wordpress/core-data' - ); +export const privateApis = {}; +lock( privateApis, { + useEntityRecordsWithPermissions, +} ); diff --git a/packages/core-data/src/private-selectors.ts b/packages/core-data/src/private-selectors.ts index 6280bb96319634..9a9b2ef5100784 100644 --- a/packages/core-data/src/private-selectors.ts +++ b/packages/core-data/src/private-selectors.ts @@ -50,3 +50,26 @@ export const getBlockPatternsForPostType = createRegistrySelector( () => [ select( STORE_NAME ).getBlockPatterns() ] ) ); + +/** + * Returns the entity records permissions for the given entity record ids. + */ +export const getEntityRecordsPermissions = createRegistrySelector( ( select ) => + createSelector( + ( state: State, kind: string, name: string, ids: string[] ) => { + return ids.map( ( id ) => ( { + delete: select( STORE_NAME ).canUser( 'delete', { + kind, + name, + id, + } ), + update: select( STORE_NAME ).canUser( 'update', { + kind, + name, + id, + } ), + } ) ); + }, + ( state ) => [ state.userPermissions ] + ) +); diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index ff25fbcd1962fb..68b8461929eb1d 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -2,7 +2,10 @@ * WordPress dependencies */ import { Button } from '@wordpress/components'; -import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; +import { + store as coreStore, + privateApis as coreDataPrivateApis, +} from '@wordpress/core-data'; import { useState, useMemo, useCallback, useEffect } from '@wordpress/element'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { useSelect, useDispatch } from '@wordpress/data'; @@ -33,6 +36,7 @@ import usePostFields from '../post-fields'; const { usePostActions } = unlock( editorPrivateApis ); const { useLocation, useHistory } = unlock( routerPrivateApis ); +const { useEntityRecordsWithPermissions } = unlock( coreDataPrivateApis ); const EMPTY_ARRAY = []; function useView( postType ) { @@ -199,7 +203,7 @@ export default function PostList( { postType } ) { isResolving: isLoadingMainEntities, totalItems, totalPages, - } = useEntityRecords( 'postType', postType, queryArgs ); + } = useEntityRecordsWithPermissions( 'postType', postType, queryArgs ); const ids = records?.map( ( record ) => getItemId( record ) ) ?? []; const prevIds = usePrevious( ids ) ?? []; From 1425f949a67ae96c31f68f2b7cc40bb4d3cc5c99 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Fri, 26 Jul 2024 11:26:25 +0100 Subject: [PATCH 0114/1908] Update field line height across grid / list layouts (#63945) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/dataviews/src/layouts/grid/style.scss | 6 ++++++ packages/dataviews/src/layouts/list/style.scss | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/dataviews/src/layouts/grid/style.scss b/packages/dataviews/src/layouts/grid/style.scss index 91f0e2b8a381c9..44841e7db0e19b 100644 --- a/packages/dataviews/src/layouts/grid/style.scss +++ b/packages/dataviews/src/layouts/grid/style.scss @@ -61,6 +61,12 @@ padding: 0 0 $grid-unit-15; } + .dataviews-view-grid__field-value:not(:empty) { + min-height: $grid-unit-30; + line-height: $grid-unit-05 * 5; + padding-top: $grid-unit-05 / 2; + } + .dataviews-view-grid__field { align-items: flex-start; min-height: $grid-unit-30; diff --git a/packages/dataviews/src/layouts/list/style.scss b/packages/dataviews/src/layouts/list/style.scss index 09f29a73b74d2d..5b8f764d012a22 100644 --- a/packages/dataviews/src/layouts/list/style.scss +++ b/packages/dataviews/src/layouts/list/style.scss @@ -179,7 +179,10 @@ } .dataviews-view-list__field-value { - line-height: $grid-unit-05 * 6; + min-height: $grid-unit-30; + line-height: $grid-unit-05 * 5; + display: flex; + align-items: center; } } From 3c53a6ad25400f9f42e947f06025c147929f63f0 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Fri, 26 Jul 2024 17:11:12 +0530 Subject: [PATCH 0115/1908] Add color support in Categories List block (#63950) Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> --- packages/block-library/src/categories/block.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/block-library/src/categories/block.json b/packages/block-library/src/categories/block.json index 7f74befa3b6816..f192087dfb4617 100644 --- a/packages/block-library/src/categories/block.json +++ b/packages/block-library/src/categories/block.json @@ -62,6 +62,18 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } }, "editorStyle": "wp-block-categories-editor", From 062efa7d6a1cff7bc290595ac35aea5353a05364 Mon Sep 17 00:00:00 2001 From: Karol Manijak <20098064+kmanijak@users.noreply.github.com> Date: Fri, 26 Jul 2024 15:55:46 +0200 Subject: [PATCH 0116/1908] Make Query Loop settings more intuitive with a ToggleGroup and simplified help text (#63739) * Replace Toggle with ToggleGroup for inherit control in Query Loop * Update a test based on Inherit query from template control * Simplify ternary operator * Update controls description in Queryn Loop block * remove const for labels used once * Add __next40pxDefaultSize --------- Co-authored-by: kmanijak <karolmanijak@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../query/edit/inspector-controls/index.js | 41 +++++++++++++------ .../specs/editor/various/is-typing.spec.js | 2 +- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index cd6b7a262c0081..81c21a236322ce 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -6,7 +6,6 @@ import { TextControl, SelectControl, RangeControl, - ToggleControl, __experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControlOption as ToggleGroupControlOption, Notice, @@ -103,9 +102,9 @@ export default function QueryInspectorControls( props ) { const showInheritControl = isControlAllowed( allowedControls, 'inherit' ); const showPostTypeControl = ! inherit && isControlAllowed( allowedControls, 'postType' ); - const postTypeControlLabel = __( 'Content type' ); + const postTypeControlLabel = __( 'Post type' ); const postTypeControlHelp = __( - 'WordPress contains different types of content you can filter by. Posts and pages are the default types, but plugins could add more.' + 'Select the type of content to display: posts, pages, or custom post types.' ); const showColumnsControl = false; const showOrderControl = @@ -146,17 +145,33 @@ export default function QueryInspectorControls( props ) { { showSettingsPanel && ( <PanelBody title={ __( 'Settings' ) }> { showInheritControl && ( - <ToggleControl - __nextHasNoMarginBottom - label={ __( 'Inherit query from template' ) } - help={ __( - 'Enable to use the global query context that is set with the current template, such as an archive or search. Disable to customize the settings independently.' - ) } - checked={ !! inherit } - onChange={ ( value ) => - setQuery( { inherit: !! value } ) + <ToggleGroupControl + __next40pxDefaultSize + label={ __( 'Query type' ) } + isBlock + onChange={ ( value ) => { + setQuery( { inherit: !! value } ); + } } + help={ + inherit + ? __( + 'Display a list of posts or custom post types based on the current template.' + ) + : __( + 'Display a list of posts or custom post types based on specific criteria.' + ) } - /> + value={ !! inherit } + > + <ToggleGroupControlOption + value + label={ __( 'Default' ) } + /> + <ToggleGroupControlOption + value={ false } + label={ __( 'Custom' ) } + /> + </ToggleGroupControl> ) } { showPostTypeControl && ( postTypesSelectOptions.length > 2 ? ( diff --git a/test/e2e/specs/editor/various/is-typing.spec.js b/test/e2e/specs/editor/various/is-typing.spec.js index e2c65f01928e04..10ac90d1084127 100644 --- a/test/e2e/specs/editor/various/is-typing.spec.js +++ b/test/e2e/specs/editor/various/is-typing.spec.js @@ -54,7 +54,7 @@ test.describe( 'isTyping', () => { .click(); await editor.openDocumentSettingsSidebar(); - await page.getByLabel( 'Inherit query from template' ).click(); + await page.getByLabel( 'Custom' ).click(); // Moving the mouse shows the toolbar. await editor.showBlockToolbar(); From 55e79d1736092ac14075463565076a4358a6c31b Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 26 Jul 2024 23:06:16 +0900 Subject: [PATCH 0117/1908] Fix deprecated sass usage (#63990) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/dataviews/src/layouts/grid/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataviews/src/layouts/grid/style.scss b/packages/dataviews/src/layouts/grid/style.scss index 44841e7db0e19b..6fe99642784dc9 100644 --- a/packages/dataviews/src/layouts/grid/style.scss +++ b/packages/dataviews/src/layouts/grid/style.scss @@ -64,7 +64,7 @@ .dataviews-view-grid__field-value:not(:empty) { min-height: $grid-unit-30; line-height: $grid-unit-05 * 5; - padding-top: $grid-unit-05 / 2; + padding-top: math.div($grid-unit-05, 2); } .dataviews-view-grid__field { From 688da865b12058239fb74ebab9f9af522d0ff517 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 26 Jul 2024 23:06:52 +0900 Subject: [PATCH 0118/1908] Image Block Lightbox: Fix warning error when resizing (#63995) * Image Block: Fix warning error when resizing * Try another approach Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: luisherranz <luisherranz@git.wordpress.org> --- packages/block-library/src/image/view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/image/view.js b/packages/block-library/src/image/view.js index 7010e9b7b2219e..0bc0dfaacea1a2 100644 --- a/packages/block-library/src/image/view.js +++ b/packages/block-library/src/image/view.js @@ -188,7 +188,7 @@ const { state, actions, callbacks } = store( }, callbacks: { setOverlayStyles() { - if ( ! state.currentImage.imageRef ) { + if ( ! state.overlayEnabled ) { return; } From 41d5ff2e221fe65529c2c6a437c422770e6c59d7 Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Fri, 26 Jul 2024 16:42:08 +0100 Subject: [PATCH 0119/1908] Remove an unnecessary wrapper component (#63989) Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- .../pattern-category-preview-panel.js | 25 ------------------- .../src/components/inserter/menu.js | 4 +-- 2 files changed, 2 insertions(+), 27 deletions(-) delete mode 100644 packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-preview-panel.js diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-preview-panel.js b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-preview-panel.js deleted file mode 100644 index 505f8d14863729..00000000000000 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-preview-panel.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Internal dependencies - */ -import { PatternCategoryPreviews } from './pattern-category-previews'; - -export function PatternCategoryPreviewPanel( { - rootClientId, - onInsert, - onHover, - category, - showTitlesAsTooltip, - patternFilter, -} ) { - return ( - <PatternCategoryPreviews - key={ category.name } - rootClientId={ rootClientId } - onInsert={ onInsert } - onHover={ onHover } - category={ category } - showTitlesAsTooltip={ showTitlesAsTooltip } - patternFilter={ patternFilter } - /> - ); -} diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index 17a98570843014..e0bc29d62e1b9a 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -26,7 +26,7 @@ import Tips from './tips'; import InserterPreviewPanel from './preview-panel'; import BlockTypesTab from './block-types-tab'; import BlockPatternsTab from './block-patterns-tab'; -import { PatternCategoryPreviewPanel } from './block-patterns-tab/pattern-category-preview-panel'; +import { PatternCategoryPreviews } from './block-patterns-tab/pattern-category-previews'; import { MediaTab, MediaCategoryPanel } from './media-tab'; import InserterSearchResults from './search-results'; import useInsertionPoint from './hooks/use-insertion-point'; @@ -246,7 +246,7 @@ function InserterMenu( selectedCategory={ selectedPatternCategory } > { showPatternPanel && ( - <PatternCategoryPreviewPanel + <PatternCategoryPreviews rootClientId={ destinationRootClientId } onInsert={ onInsertPattern } onHover={ onHoverPattern } From c2bf14fb0ae6e6f6aacf02eedadc5d84abe47215 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Sat, 27 Jul 2024 00:57:36 +0900 Subject: [PATCH 0120/1908] CustomSelectControl: Restore `describedBy` functionality (#63957) * CustomSelectControl: Restore `describedBy` functionality * Add default description * Add changelog Unlinked contributors: rohitmathur-7. Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++ .../src/custom-select-control/index.tsx | 68 +++++++++++++------ .../src/custom-select-control/test/index.tsx | 22 ++++++ 3 files changed, 74 insertions(+), 20 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 6c32534598fb5c..f8666e96a20a15 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- `CustomSelectControl`: Restore `describedBy` functionality ([#63957](https://github.com/WordPress/gutenberg/pull/63957)). + ### Internal - `DropdownMenuV2`: break menu item help text on multiple lines for better truncation. ([#63916](https://github.com/WordPress/gutenberg/pull/63916)). diff --git a/packages/components/src/custom-select-control/index.tsx b/packages/components/src/custom-select-control/index.tsx index 5bce6afc4d92b6..8735b8d320991e 100644 --- a/packages/components/src/custom-select-control/index.tsx +++ b/packages/components/src/custom-select-control/index.tsx @@ -4,6 +4,12 @@ import * as Ariakit from '@ariakit/react'; import clsx from 'clsx'; +/** + * WordPress dependencies + */ +import { useInstanceId } from '@wordpress/compose'; +import { __, sprintf } from '@wordpress/i18n'; + /** * Internal dependencies */ @@ -11,6 +17,7 @@ import _CustomSelect from '../custom-select-control-v2/custom-select'; import CustomSelectItem from '../custom-select-control-v2/item'; import * as Styled from '../custom-select-control-v2/styles'; import type { CustomSelectProps } from './types'; +import { VisuallyHidden } from '../visually-hidden'; function useDeprecatedProps( { __experimentalShowSelectedHint, @@ -35,6 +42,15 @@ function applyOptionDeprecations( { }; } +function getDescribedBy( currentValue: string, describedBy?: string ) { + if ( describedBy ) { + return describedBy; + } + + // translators: %s: The selected option. + return sprintf( __( 'Currently selected: %s' ), currentValue ); +} + function CustomSelectControl( props: CustomSelectProps ) { const { __next40pxDefaultSize = false, @@ -48,8 +64,13 @@ function CustomSelectControl( props: CustomSelectProps ) { ...restProps } = useDeprecatedProps( props ); + const descriptionId = useInstanceId( + CustomSelectControl, + 'custom-select-control__description' + ); + // Forward props + store from v2 implementation - const store = Ariakit.useSelectStore( { + const store = Ariakit.useSelectStore< string >( { async setValue( nextValue ) { const nextOption = options.find( ( item ) => item.name === nextValue @@ -117,9 +138,9 @@ function CustomSelectControl( props: CustomSelectProps ) { ); } ); - const renderSelectedValueHint = () => { - const { value: currentValue } = store.getState(); + const { value: currentValue } = store.getState(); + const renderSelectedValueHint = () => { const selectedOptionHint = options ?.map( applyOptionDeprecations ) ?.find( ( { name } ) => currentValue === name )?.hint; @@ -153,23 +174,30 @@ function CustomSelectControl( props: CustomSelectProps ) { } )(); return ( - <_CustomSelect - aria-describedby={ describedBy } - renderSelectedValue={ - showSelectedHint ? renderSelectedValueHint : undefined - } - size={ translatedSize } - store={ store } - className={ clsx( - // Keeping the classname for legacy reasons - 'components-custom-select-control', - classNameProp - ) } - isLegacy - { ...restProps } - > - { children } - </_CustomSelect> + <> + <_CustomSelect + aria-describedby={ descriptionId } + renderSelectedValue={ + showSelectedHint ? renderSelectedValueHint : undefined + } + size={ translatedSize } + store={ store } + className={ clsx( + // Keeping the classname for legacy reasons + 'components-custom-select-control', + classNameProp + ) } + isLegacy + { ...restProps } + > + { children } + </_CustomSelect> + <VisuallyHidden> + <span id={ descriptionId }> + { getDescribedBy( currentValue, describedBy ) } + </span> + </VisuallyHidden> + </> ); } diff --git a/packages/components/src/custom-select-control/test/index.tsx b/packages/components/src/custom-select-control/test/index.tsx index 73dcb039df3f1b..4bc96f318138c5 100644 --- a/packages/components/src/custom-select-control/test/index.tsx +++ b/packages/components/src/custom-select-control/test/index.tsx @@ -670,5 +670,27 @@ describe.each( [ expect( currentSelectedItem ).not.toHaveFocus(); expect( onBlurMock ).toHaveBeenCalledTimes( 1 ); } ); + + it( 'should render the describedBy text when specified', async () => { + const describedByText = 'My description.'; + + render( + <Component { ...props } describedBy={ describedByText } /> + ); + + expect( + screen.getByRole( 'combobox' ) + ).toHaveAccessibleDescription( describedByText ); + } ); + + it( 'should render the default ARIA description when describedBy is not specified', async () => { + render( <Component { ...props } /> ); + + expect( + screen.getByRole( 'combobox' ) + ).toHaveAccessibleDescription( + `Currently selected: ${ props.options[ 0 ].name }` + ); + } ); } ); } ); From 285a304e03ec895ca311cab15d81061d8a8c3a91 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Sat, 27 Jul 2024 06:29:36 +1000 Subject: [PATCH 0121/1908] Column: Add border radius support (#63924) Unlinked contributors: gabrieltogan, porg, bradhogan. Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: mikemcalister <mmcalister@git.wordpress.org> Co-authored-by: maurodf0 <maurodf@git.wordpress.org> Co-authored-by: bgardner <bgardner@git.wordpress.org> Co-authored-by: deryckoe <deryck@git.wordpress.org> --- packages/block-library/src/column/block.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/block-library/src/column/block.json b/packages/block-library/src/column/block.json index 0857abb47ffdc0..33bd528b356880 100644 --- a/packages/block-library/src/column/block.json +++ b/packages/block-library/src/column/block.json @@ -48,10 +48,12 @@ }, "__experimentalBorder": { "color": true, + "radius": true, "style": true, "width": true, "__experimentalDefaultControls": { "color": true, + "radius": true, "style": true, "width": true } From 93f80f67d81fe26895edc799f8c78a5970022dcc Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Sat, 27 Jul 2024 09:26:39 +0530 Subject: [PATCH 0122/1908] Corrected @deprecated doc Order (#64013) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- lib/experimental/script-modules.php | 9 ++++++--- .../block-editor/src/components/use-settings/index.js | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index 709ab322f63a3e..0093c2e974568f 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -165,11 +165,12 @@ function gutenberg_register_view_module_ids_rest_field() { * Registers the module if no module with that module identifier has already * been registered. * + * @deprecated 17.6.0 gutenberg_register_module is deprecated. Please use wp_register_script_module instead. + * * @param string $module_identifier The identifier of the module. Should be unique. It will be used in the final import map. * @param string $src Full URL of the module, or path of the script relative to the WordPress root directory. * @param array $dependencies Optional. An array of module identifiers of the dependencies of this module. The dependencies can be strings or arrays. If they are arrays, they need an `id` key with the module identifier, and can contain an `import` key with either `static` or `dynamic`. By default, dependencies that don't contain an import are considered static. * @param string|false|null $version Optional. String specifying module version number. Defaults to false. It is added to the URL as a query string for cache busting purposes. If $version is set to false, the version number is the currently installed WordPress version. If $version is set to null, no version is added. - * @deprecated 17.6.0 gutenberg_register_module is deprecated. Please use wp_register_script_module instead. */ function gutenberg_register_module( $module_identifier, $src = '', $dependencies = array(), $version = false ) { _deprecated_function( __FUNCTION__, 'Gutenberg 17.6.0', 'wp_register_script_module' ); @@ -179,8 +180,9 @@ function gutenberg_register_module( $module_identifier, $src = '', $dependencies /** * Marks the module to be enqueued in the page. * - * @param string $module_identifier The identifier of the module. * @deprecated 17.6.0 gutenberg_enqueue_module is deprecated. Please use wp_enqueue_script_module instead. + * + * @param string $module_identifier The identifier of the module. */ function gutenberg_enqueue_module( $module_identifier ) { _deprecated_function( __FUNCTION__, 'Gutenberg 17.6.0', 'wp_enqueue_script_module' ); @@ -190,8 +192,9 @@ function gutenberg_enqueue_module( $module_identifier ) { /** * Unmarks the module so it is not longer enqueued in the page. * - * @param string $module_identifier The identifier of the module. * @deprecated 17.6.0 gutenberg_dequeue_module is deprecated. Please use wp_dequeue_script_module instead. + * + * @param string $module_identifier The identifier of the module. */ function gutenberg_dequeue_module( $module_identifier ) { _deprecated_function( __FUNCTION__, 'Gutenberg 17.6.0', 'wp_dequeue_script_module' ); diff --git a/packages/block-editor/src/components/use-settings/index.js b/packages/block-editor/src/components/use-settings/index.js index b0410b404d5e98..e356260c2d6b38 100644 --- a/packages/block-editor/src/components/use-settings/index.js +++ b/packages/block-editor/src/components/use-settings/index.js @@ -43,9 +43,10 @@ export function useSettings( ...paths ) { * It looks up the setting first in the block instance hierarchy. * If none is found, it'll look it up in the block editor settings. * + * @deprecated 6.5.0 Use useSettings instead. + * * @param {string} path The path to the setting. * @return {any} Returns the value defined for the setting. - * @deprecated 6.5.0 Use useSettings instead. * @example * ```js * const isEnabled = useSetting( 'typography.dropCap' ); From 159d01a01b61ee76159ab67bc94d0d7cb3d90b35 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Sat, 27 Jul 2024 13:02:31 +0900 Subject: [PATCH 0123/1908] Post Editor: Prevent popover from being hidden by metabox (#63939) * Post Editor: Prevent popover from being hidden by metabox * Use `.interface-interface-skeleton__content` instead of `.interface-interface-skeleton__body` Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: Rishit30G <rishit30g@git.wordpress.org> Co-authored-by: dhananjaykuber <dhananjaykuber@git.wordpress.org> --- packages/editor/src/components/editor-interface/style.scss | 5 +++++ packages/editor/src/components/visual-editor/style.scss | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/editor-interface/style.scss b/packages/editor/src/components/editor-interface/style.scss index 77f621acc93510..05b23fe2304dd8 100644 --- a/packages/editor/src/components/editor-interface/style.scss +++ b/packages/editor/src/components/editor-interface/style.scss @@ -2,6 +2,11 @@ height: $header-height + $border-width; } +.editor-editor-interface .interface-interface-skeleton__content { + // Make this a stacking context to contain the z-index of children elements. + isolation: isolate; +} + .editor-visual-editor { flex: 1 0 auto; } diff --git a/packages/editor/src/components/visual-editor/style.scss b/packages/editor/src/components/visual-editor/style.scss index 2d7ed665a957f3..18a61827d573da 100644 --- a/packages/editor/src/components/visual-editor/style.scss +++ b/packages/editor/src/components/visual-editor/style.scss @@ -2,8 +2,6 @@ position: relative; display: block; background-color: $gray-300; - // Make this a stacking context to contain the z-index of children elements. - isolation: isolate; // Centralize the editor horizontally (flex-direction is column). align-items: center; From 313246a01f18e504dabd8313e7eacca728332bcd Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Sat, 27 Jul 2024 17:12:03 +0400 Subject: [PATCH 0124/1908] Fix 'Preferences' and 'Shortcuts' commands in StrictMode (#64019) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/editor/src/components/commands/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/commands/index.js b/packages/editor/src/components/commands/index.js index 460a595234e59b..b1471e25583415 100644 --- a/packages/editor/src/components/commands/index.js +++ b/packages/editor/src/components/commands/index.js @@ -89,7 +89,8 @@ function useEditorCommandLoader() { name: 'core/open-shortcut-help', label: __( 'Keyboard shortcuts' ), icon: keyboard, - callback: () => { + callback: ( { close } ) => { + close(); openModal( 'editor/keyboard-shortcut-help' ); }, } ); @@ -108,7 +109,8 @@ function useEditorCommandLoader() { commands.push( { name: 'core/open-preferences', label: __( 'Editor preferences' ), - callback: () => { + callback: ( { close } ) => { + close(); openModal( 'editor/preferences' ); }, } ); From e5130d934820b5830ba52b751709e23057ee92ed Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Sun, 28 Jul 2024 19:47:51 +0530 Subject: [PATCH 0125/1908] Several Typo Correction in Inline Doc (#64032) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- docs/reference-guides/data/data-core.md | 2 +- packages/core-data/README.md | 2 +- packages/core-data/src/actions.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/reference-guides/data/data-core.md b/docs/reference-guides/data/data-core.md index 0ddd3858c97603..a2bcf31b4d2e28 100644 --- a/docs/reference-guides/data/data-core.md +++ b/docs/reference-guides/data/data-core.md @@ -755,7 +755,7 @@ _Parameters_ ### receiveThemeSupports -> **Deprecated** since WP 5.9, this is not useful anymore, use the selector direclty. +> **Deprecated** since WP 5.9, this is not useful anymore, use the selector directly. Returns an action object used in signalling that the index has been received. diff --git a/packages/core-data/README.md b/packages/core-data/README.md index de28e4b86be4bf..89e7a201fe5e25 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -264,7 +264,7 @@ _Parameters_ ### receiveThemeSupports -> **Deprecated** since WP 5.9, this is not useful anymore, use the selector direclty. +> **Deprecated** since WP 5.9, this is not useful anymore, use the selector directly. Returns an action object used in signalling that the index has been received. diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index 6fca867ecaa6a5..d7cc4d708d3c68 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -200,7 +200,7 @@ export function __experimentalReceiveThemeGlobalStyleVariations( /** * Returns an action object used in signalling that the index has been received. * - * @deprecated since WP 5.9, this is not useful anymore, use the selector direclty. + * @deprecated since WP 5.9, this is not useful anymore, use the selector directly. * * @return {Object} Action object. */ From 982b68ce294854a9e6d77357ff12b1f802dd231b Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Mon, 29 Jul 2024 13:32:37 +1000 Subject: [PATCH 0126/1908] Style Book: clearly denote heading levels (#64038) * Use Heading descriptors to describe the heading variants. * Add Heading 6 Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> --- .../edit-site/src/components/style-book/index.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 0d699544613209..82b94504e63a9b 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -136,25 +136,29 @@ function getExamples() { category: 'text', blocks: [ createBlock( 'core/heading', { - content: __( 'Code Is Poetry' ), + content: __( 'Heading 1' ), level: 1, } ), createBlock( 'core/heading', { - content: __( 'Code Is Poetry' ), + content: __( 'Heading 2' ), level: 2, } ), createBlock( 'core/heading', { - content: __( 'Code Is Poetry' ), + content: __( 'Heading 3' ), level: 3, } ), createBlock( 'core/heading', { - content: __( 'Code Is Poetry' ), + content: __( 'Heading 4' ), level: 4, } ), createBlock( 'core/heading', { - content: __( 'Code Is Poetry' ), + content: __( 'Heading 5' ), level: 5, } ), + createBlock( 'core/heading', { + content: __( 'Heading 6' ), + level: 6, + } ), ], }; From 27fbbd8e9b57495339a077ef0c8ba67a18392699 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Mon, 29 Jul 2024 13:33:05 +1000 Subject: [PATCH 0127/1908] Global Styles: add tooltips to the heading level selectors (#64039) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> --- .../global-styles/screen-typography-element.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/edit-site/src/components/global-styles/screen-typography-element.js b/packages/edit-site/src/components/global-styles/screen-typography-element.js index 876baddd0ec7f0..8a8150e1578719 100644 --- a/packages/edit-site/src/components/global-styles/screen-typography-element.js +++ b/packages/edit-site/src/components/global-styles/screen-typography-element.js @@ -67,30 +67,44 @@ function ScreenTypographyElement( { element } ) { > <ToggleGroupControlOption value="heading" + showTooltip + aria-label={ __( 'All headings' ) } label={ _x( 'All', 'heading levels' ) } /> <ToggleGroupControlOption value="h1" + showTooltip + aria-label={ __( 'Heading 1' ) } label={ __( 'H1' ) } /> <ToggleGroupControlOption value="h2" + showTooltip + aria-label={ __( 'Heading 2' ) } label={ __( 'H2' ) } /> <ToggleGroupControlOption value="h3" + showTooltip + aria-label={ __( 'Heading 3' ) } label={ __( 'H3' ) } /> <ToggleGroupControlOption value="h4" + showTooltip + aria-label={ __( 'Heading 4' ) } label={ __( 'H4' ) } /> <ToggleGroupControlOption value="h5" + showTooltip + aria-label={ __( 'Heading 5' ) } label={ __( 'H5' ) } /> <ToggleGroupControlOption value="h6" + showTooltip + aria-label={ __( 'Heading 6' ) } label={ __( 'H6' ) } /> </ToggleGroupControl> From 4b873d66118aa94ba2166e1d743fa4379d265fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Mon, 29 Jul 2024 10:22:34 +0200 Subject: [PATCH 0128/1908] DataForm: add author to quick edit page/post list (#63983) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../src/components/dataform/index.tsx | 28 +++++++++++++++++-- .../dataform/stories/index.story.tsx | 12 +++++++- packages/dataviews/src/test/validation.ts | 17 +++++++++++ packages/dataviews/src/validation.ts | 7 +++++ .../src/components/post-edit/index.js | 17 +++++++++-- .../src/components/post-fields/index.js | 2 +- 6 files changed, 76 insertions(+), 7 deletions(-) diff --git a/packages/dataviews/src/components/dataform/index.tsx b/packages/dataviews/src/components/dataform/index.tsx index 42a6766813975e..bd38dca472af0e 100644 --- a/packages/dataviews/src/components/dataform/index.tsx +++ b/packages/dataviews/src/components/dataform/index.tsx @@ -9,7 +9,9 @@ import type { Dispatch, SetStateAction } from 'react'; import { TextControl, __experimentalNumberControl as NumberControl, + SelectControl, } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; import { useCallback, useMemo } from '@wordpress/element'; /** @@ -65,8 +67,7 @@ function DataFormNumberControl< Item >( { onChange, }: DataFormControlProps< Item > ) { const { id, label, description } = field; - const value = field.getValue( { item: data } ); - + const value = field.getValue( { item: data } ) ?? ''; const onChangeControl = useCallback( ( newValue: string | undefined ) => onChange( ( prevItem: Item ) => ( { @@ -76,6 +77,29 @@ function DataFormNumberControl< Item >( { [ id, onChange ] ); + if ( field.elements ) { + const elements = [ + /* + * Value can be undefined when: + * + * - the field is not required + * - in bulk editing + * + */ + { label: __( 'Select item' ), value: '' }, + ...field.elements, + ]; + + return ( + <SelectControl + label={ label } + value={ value } + options={ elements } + onChange={ onChangeControl } + /> + ); + } + return ( <NumberControl label={ label } diff --git a/packages/dataviews/src/components/dataform/stories/index.story.tsx b/packages/dataviews/src/components/dataform/stories/index.story.tsx index a67eaa6b76f042..f6f29d0e7f9ebd 100644 --- a/packages/dataviews/src/components/dataform/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataform/stories/index.story.tsx @@ -25,16 +25,26 @@ const fields = [ label: 'Order', type: 'integer' as const, }, + { + id: 'author', + label: 'Author', + type: 'integer' as const, + elements: [ + { value: 1, label: 'Jane' }, + { value: 2, label: 'John' }, + ], + }, ]; export const Default = () => { const [ post, setPost ] = useState( { title: 'Hello, World!', order: 2, + author: 1, } ); const form = { - visibleFields: [ 'title', 'order' ], + visibleFields: [ 'title', 'order', 'author' ], }; return ( diff --git a/packages/dataviews/src/test/validation.ts b/packages/dataviews/src/test/validation.ts index d90d4744ac3272..ded002e5bc042e 100644 --- a/packages/dataviews/src/test/validation.ts +++ b/packages/dataviews/src/test/validation.ts @@ -60,4 +60,21 @@ describe( 'validation', () => { const result = isItemValid( item, fields, form ); expect( result ).toBe( false ); } ); + + it( 'field is invalid if value is not one of the elements', () => { + const item = { id: 1, author: 3 }; + const fields: Field< {} >[] = [ + { + id: 'author', + type: 'integer', + elements: [ + { value: 1, label: 'Jane' }, + { value: 2, label: 'John' }, + ], + }, + ]; + const form = { visibleFields: [ 'author' ] }; + const result = isItemValid( item, fields, form ); + expect( result ).toBe( false ); + } ); } ); diff --git a/packages/dataviews/src/validation.ts b/packages/dataviews/src/validation.ts index 5b20d094a41861..a6d3515fe6e57e 100644 --- a/packages/dataviews/src/validation.ts +++ b/packages/dataviews/src/validation.ts @@ -27,6 +27,13 @@ export function isItemValid< Item >( return false; } + if ( field.elements ) { + const validValues = field.elements.map( ( f ) => f.value ); + if ( ! validValues.includes( Number( value ) ) ) { + return false; + } + } + // Nothing to validate. return true; } ); diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 21dbb10e514660..f8519470749a94 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -7,7 +7,7 @@ import clsx from 'clsx'; * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { DataForm } from '@wordpress/dataviews'; +import { DataForm, isItemValid } from '@wordpress/dataviews'; import { useDispatch, useSelect, useRegistry } from '@wordpress/data'; import { store as coreDataStore } from '@wordpress/core-data'; import { Button } from '@wordpress/components'; @@ -42,7 +42,7 @@ function PostEditForm( { postType, postId } ) { const { saveEntityRecord } = useDispatch( coreDataStore ); const { fields } = usePostFields(); const form = { - visibleFields: [ 'title' ], + visibleFields: [ 'title', 'author' ], }; const [ edits, setEdits ] = useState( {} ); const itemWithEdits = useMemo( () => { @@ -53,6 +53,11 @@ function PostEditForm( { postType, postId } ) { }, [ initialEdits, edits ] ); const onSubmit = async ( event ) => { event.preventDefault(); + + if ( ! isItemValid( itemWithEdits, fields, form ) ) { + return; + } + const { getEntityRecord } = registry.resolveSelect( coreDataStore ); for ( const id of ids ) { const item = await getEntityRecord( 'postType', postType, id ); @@ -64,6 +69,7 @@ function PostEditForm( { postType, postId } ) { setEdits( {} ); }; + const isUpdateDisabled = ! isItemValid( itemWithEdits, fields, form ); return ( <form onSubmit={ onSubmit }> <DataForm @@ -72,7 +78,12 @@ function PostEditForm( { postType, postId } ) { form={ form } onChange={ setEdits } /> - <Button variant="primary" type="submit"> + <Button + variant="primary" + type="submit" + accessibleWhenDisabled + disabled={ isUpdateDisabled } + > { __( 'Update' ) } </Button> </form> diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index f4e8e553c8fa47..52030fc70f54b7 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -235,7 +235,7 @@ function usePostFields( viewType ) { { label: __( 'Author' ), id: 'author', - getValue: ( { item } ) => item._embedded?.author[ 0 ]?.name, + type: 'integer', elements: authors?.map( ( { id, name } ) => ( { value: id, From d4bf95946f88b6f45f10977acfe0e7a7e88c45bf Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Mon, 29 Jul 2024 17:39:54 +0900 Subject: [PATCH 0129/1908] Style Book: Fix critical error when heading block is not registered (#64047) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/components/style-book/index.js | 63 ++++++++----------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 82b94504e63a9b..7ee8eed375f9a9 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -13,6 +13,7 @@ import { import { __, sprintf } from '@wordpress/i18n'; import { getCategories, + getBlockType, getBlockTypes, getBlockFromExample, createBlock, @@ -128,41 +129,7 @@ function isObjectEmpty( object ) { } function getExamples() { - // Use our own example for the Heading block so that we can show multiple - // heading levels. - const headingsExample = { - name: 'core/heading', - title: __( 'Headings' ), - category: 'text', - blocks: [ - createBlock( 'core/heading', { - content: __( 'Heading 1' ), - level: 1, - } ), - createBlock( 'core/heading', { - content: __( 'Heading 2' ), - level: 2, - } ), - createBlock( 'core/heading', { - content: __( 'Heading 3' ), - level: 3, - } ), - createBlock( 'core/heading', { - content: __( 'Heading 4' ), - level: 4, - } ), - createBlock( 'core/heading', { - content: __( 'Heading 5' ), - level: 5, - } ), - createBlock( 'core/heading', { - content: __( 'Heading 6' ), - level: 6, - } ), - ], - }; - - const otherExamples = getBlockTypes() + const nonHeadingBlockExamples = getBlockTypes() .filter( ( blockType ) => { const { name, example, supports } = blockType; return ( @@ -178,7 +145,31 @@ function getExamples() { blocks: getBlockFromExample( blockType.name, blockType.example ), } ) ); - return [ headingsExample, ...otherExamples ]; + const isHeadingBlockRegistered = !! getBlockType( 'core/heading' ); + + if ( ! isHeadingBlockRegistered ) { + return nonHeadingBlockExamples; + } + + // Use our own example for the Heading block so that we can show multiple + // heading levels. + const headingsExample = { + name: 'core/heading', + title: __( 'Headings' ), + category: 'text', + blocks: [ 1, 2, 3, 4, 5, 6 ].map( ( level ) => { + return createBlock( 'core/heading', { + content: sprintf( + // translators: %d: heading level e.g: "1", "2", "3" + __( 'Heading %d' ), + level + ), + level, + } ); + } ), + }; + + return [ headingsExample, ...nonHeadingBlockExamples ]; } function StyleBook( { From 05bf9bb569a8c672eeff6d8b1929fae22963d5e4 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:41:55 +0530 Subject: [PATCH 0130/1908] Add border support to post title block (#64024) Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/block-library/src/post-title/block.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/block-library/src/post-title/block.json b/packages/block-library/src/post-title/block.json index 796da166710eb7..9c3ba3e214e4b1 100644 --- a/packages/block-library/src/post-title/block.json +++ b/packages/block-library/src/post-title/block.json @@ -63,6 +63,18 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } }, "style": "wp-block-post-title" From 1eade38d4669fd91b89f7e472db9df2f66330f18 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:42:18 +0530 Subject: [PATCH 0131/1908] Add border support to post date block (#64023) Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/block-library/src/post-date/block.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/block-library/src/post-date/block.json b/packages/block-library/src/post-date/block.json index a57d45ceed1495..470bddae53bdfc 100644 --- a/packages/block-library/src/post-date/block.json +++ b/packages/block-library/src/post-date/block.json @@ -56,6 +56,18 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } } } From d803b3ff06e20ac9e8c5702dbf1d93949e6598d8 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Mon, 29 Jul 2024 15:09:09 +0530 Subject: [PATCH 0132/1908] Table of contents: Add border block support (#63578) * Add border support to table of contents block * Add box sizing style to table of contents block Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/block-library/src/style.scss | 1 + .../src/table-of-contents/block.json | 15 ++++++++++++++- .../src/table-of-contents/style.scss | 4 ++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 packages/block-library/src/table-of-contents/style.scss diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index 790e09535f4b69..5e33980badd76c 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -52,6 +52,7 @@ @import "./spacer/style.scss"; @import "./tag-cloud/style.scss"; @import "./table/style.scss"; +@import "./table-of-contents/style.scss"; @import "./term-description/style.scss"; @import "./text-columns/style.scss"; @import "./verse/style.scss"; diff --git a/packages/block-library/src/table-of-contents/block.json b/packages/block-library/src/table-of-contents/block.json index 0c9c4bb4a2868d..451d245d867b07 100644 --- a/packages/block-library/src/table-of-contents/block.json +++ b/packages/block-library/src/table-of-contents/block.json @@ -48,7 +48,20 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } }, - "example": {} + "example": {}, + "style": "wp-block-table-of-contents" } diff --git a/packages/block-library/src/table-of-contents/style.scss b/packages/block-library/src/table-of-contents/style.scss new file mode 100644 index 00000000000000..4a3fbb6108bee5 --- /dev/null +++ b/packages/block-library/src/table-of-contents/style.scss @@ -0,0 +1,4 @@ +:root :where(.wp-block-table-of-contents) { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; +} From 14816d2ff58699497be4ebcd8ac6e0e688d8c945 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 29 Jul 2024 12:05:25 +0200 Subject: [PATCH 0133/1908] DataViews: Use items with permissions and avoid hooks to register actions (#63923) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/core-data/src/private-selectors.ts | 19 ++++ .../components/page-patterns/use-patterns.js | 32 ++++++- .../src/components/page-templates/index.js | 12 +-- .../src/components/post-actions/actions.js | 95 ++++--------------- .../src/components/post-actions/index.js | 26 +++-- 5 files changed, 94 insertions(+), 90 deletions(-) diff --git a/packages/core-data/src/private-selectors.ts b/packages/core-data/src/private-selectors.ts index 9a9b2ef5100784..7eb67973c67281 100644 --- a/packages/core-data/src/private-selectors.ts +++ b/packages/core-data/src/private-selectors.ts @@ -73,3 +73,22 @@ export const getEntityRecordsPermissions = createRegistrySelector( ( select ) => ( state ) => [ state.userPermissions ] ) ); + +/** + * Returns the entity record permissions for the given entity record id. + * + * @param state Data state. + * @param kind Entity kind. + * @param name Entity name. + * @param id Entity record id. + * + * @return The entity record permissions. + */ +export function getEntityRecordPermissions( + state: State, + kind: string, + name: string, + id: string +) { + return getEntityRecordsPermissions( state, kind, name, [ id ] )[ 0 ]; +} diff --git a/packages/edit-site/src/components/page-patterns/use-patterns.js b/packages/edit-site/src/components/page-patterns/use-patterns.js index ecbc6adee75587..2947088bb19b5f 100644 --- a/packages/edit-site/src/components/page-patterns/use-patterns.js +++ b/packages/edit-site/src/components/page-patterns/use-patterns.js @@ -5,6 +5,7 @@ import { parse } from '@wordpress/blocks'; import { useSelect, createSelector } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { store as editorStore } from '@wordpress/editor'; +import { useMemo } from '@wordpress/element'; /** * Internal dependencies @@ -260,7 +261,7 @@ export const usePatterns = ( categoryId, { search = '', syncStatus } = {} ) => { - return useSelect( + const { patterns, ...rest } = useSelect( ( select ) => { if ( postType === TEMPLATE_PART_POST_TYPE ) { return selectTemplateParts( select, categoryId, search ); @@ -283,6 +284,35 @@ export const usePatterns = ( }, [ categoryId, postType, search, syncStatus ] ); + + const ids = useMemo( + () => patterns?.map( ( record ) => record.id ) ?? [], + [ patterns ] + ); + + const permissions = useSelect( + ( select ) => { + const { getEntityRecordsPermissions } = unlock( + select( coreStore ) + ); + return getEntityRecordsPermissions( 'postType', postType, ids ); + }, + [ ids, postType ] + ); + + const patternsWithPermissions = useMemo( + () => + patterns?.map( ( record, index ) => ( { + ...record, + permissions: permissions[ index ], + } ) ) ?? [], + [ patterns, permissions ] + ); + + return { + ...rest, + patterns: patternsWithPermissions, + }; }; export default usePatterns; diff --git a/packages/edit-site/src/components/page-templates/index.js b/packages/edit-site/src/components/page-templates/index.js index 9c5db8fb1699d5..05c3b9673eaf98 100644 --- a/packages/edit-site/src/components/page-templates/index.js +++ b/packages/edit-site/src/components/page-templates/index.js @@ -3,7 +3,7 @@ */ import { __ } from '@wordpress/i18n'; import { useState, useMemo, useCallback, useEffect } from '@wordpress/element'; -import { useEntityRecords } from '@wordpress/core-data'; +import { privateApis as corePrivateApis } from '@wordpress/core-data'; import { DataViews, filterSortAndPaginate } from '@wordpress/dataviews'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; @@ -31,6 +31,7 @@ import { const { usePostActions } = unlock( editorPrivateApis ); const { useHistory, useLocation } = unlock( routerPrivateApis ); +const { useEntityRecordsWithPermissions } = unlock( corePrivateApis ); const EMPTY_ARRAY = []; @@ -134,13 +135,10 @@ export default function PageTemplates() { } ) ); }, [ activeView ] ); - const { records, isResolving: isLoadingData } = useEntityRecords( - 'postType', - TEMPLATE_POST_TYPE, - { + const { records, isResolving: isLoadingData } = + useEntityRecordsWithPermissions( 'postType', TEMPLATE_POST_TYPE, { per_page: -1, - } - ); + } ); const history = useHistory(); const onChangeSelection = useCallback( ( items ) => { diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 190b8ea6ca32f5..47e49fb8f8f1da 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -3,7 +3,7 @@ */ import { external, trash, backup } from '@wordpress/icons'; import { addQueryArgs } from '@wordpress/url'; -import { useDispatch, useSelect, useRegistry } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import { decodeEntities } from '@wordpress/html-entities'; import { store as coreStore } from '@wordpress/core-data'; import { __, _n, sprintf, _x } from '@wordpress/i18n'; @@ -88,7 +88,10 @@ const trashPostAction = { isPrimary: true, icon: trash, isEligible( item ) { - return ! [ 'auto-draft', 'trash' ].includes( item.status ); + return ( + ! [ 'auto-draft', 'trash' ].includes( item.status ) && + item.permissions?.delete + ); }, supportsBulk: true, hideModalHeader: true, @@ -240,40 +243,12 @@ const trashPostAction = { }, }; -function useCanUserEligibilityCheckPostType( capability, postType, action ) { - const registry = useRegistry(); - return useMemo( - () => ( { - ...action, - isEligible( item ) { - return ( - action.isEligible( item ) && - registry.select( coreStore ).canUser( capability, { - kind: 'postType', - name: postType, - id: item.id, - } ) - ); - }, - } ), - [ action, registry, capability, postType ] - ); -} - -function useTrashPostAction( postType ) { - return useCanUserEligibilityCheckPostType( - 'delete', - postType, - trashPostAction - ); -} - const permanentlyDeletePostAction = { id: 'permanently-delete', label: __( 'Permanently delete' ), supportsBulk: true, - isEligible( { status } ) { - return status === 'trash'; + isEligible( { status, permissions } ) { + return status === 'trash' && permissions?.delete; }, async callback( posts, { registry, onActionPerformed } ) { const { createSuccessNotice, createErrorNotice } = @@ -359,22 +334,14 @@ const permanentlyDeletePostAction = { }, }; -function usePermanentlyDeletePostAction( postType ) { - return useCanUserEligibilityCheckPostType( - 'delete', - postType, - permanentlyDeletePostAction - ); -} - const restorePostAction = { id: 'restore', label: __( 'Restore' ), isPrimary: true, icon: backup, supportsBulk: true, - isEligible( { status } ) { - return status === 'trash'; + isEligible( { status, permissions } ) { + return status === 'trash' && permissions?.update; }, async callback( posts, { registry, onActionPerformed } ) { const { createSuccessNotice, createErrorNotice } = @@ -474,14 +441,6 @@ const restorePostAction = { }, }; -function useRestorePostAction( postType ) { - return useCanUserEligibilityCheckPostType( - 'update', - postType, - restorePostAction - ); -} - const viewPostAction = { id: 'view-post', label: __( 'View' ), @@ -548,11 +507,15 @@ const renamePostAction = { ...Object.values( PATTERN_TYPES ), ].includes( post.type ) ) { - return true; + return post.permissions?.update; } // In the case of templates, we can only rename custom templates. if ( post.type === TEMPLATE_POST_TYPE ) { - return isTemplateRemovable( post ) && post.is_custom; + return ( + isTemplateRemovable( post ) && + post.is_custom && + post.permissions?.update + ); } // Make necessary checks for template parts and patterns. const isTemplatePart = post.type === TEMPLATE_PART_POST_TYPE; @@ -564,7 +527,7 @@ const renamePostAction = { isUserPattern || ( isTemplatePart && post.source === TEMPLATE_ORIGINS.custom ); const hasThemeFile = post?.has_theme_file; - return isCustomPattern && ! hasThemeFile; + return isCustomPattern && ! hasThemeFile && post.permissions?.update; }, RenderModal: ( { items, closeModal, onActionPerformed } ) => { const [ item ] = items; @@ -635,14 +598,6 @@ const renamePostAction = { }, }; -function useRenamePostAction( postType ) { - return useCanUserEligibilityCheckPostType( - 'update', - postType, - renamePostAction - ); -} - function ReorderModal( { items, closeModal, onActionPerformed } ) { const [ item, setItem ] = useState( items[ 0 ] ); const orderInput = item.menu_order; @@ -1004,11 +959,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { ); const duplicatePostAction = useDuplicatePostAction( postType ); - const trashPostActionForPostType = useTrashPostAction( postType ); - const permanentlyDeletePostActionForPostType = - usePermanentlyDeletePostAction( postType ); - const renamePostActionForPostType = useRenamePostAction( postType ); - const restorePostActionForPostType = useRestorePostAction( postType ); const reorderPagesAction = useReorderPagesAction( postType ); const isTemplateOrTemplatePart = [ TEMPLATE_POST_TYPE, @@ -1035,14 +985,13 @@ export function usePostActions( { postType, onActionPerformed, context } ) { userCanCreatePostType && duplicateTemplatePartAction, isPattern && userCanCreatePostType && duplicatePatternAction, - supportsTitle && renamePostActionForPostType, + supportsTitle && renamePostAction, reorderPagesAction, - ! isTemplateOrTemplatePart && restorePostActionForPostType, + ! isTemplateOrTemplatePart && ! isPattern && restorePostAction, + ! isTemplateOrTemplatePart && ! isPattern && trashPostAction, ! isTemplateOrTemplatePart && ! isPattern && - trashPostActionForPostType, - ! isTemplateOrTemplatePart && - permanentlyDeletePostActionForPostType, + permanentlyDeletePostAction, ...defaultActions, ].filter( Boolean ); // Filter actions based on provided context. If not provided @@ -1117,10 +1066,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { postTypeObject?.viewable, duplicatePostAction, reorderPagesAction, - trashPostActionForPostType, - restorePostActionForPostType, - renamePostActionForPostType, - permanentlyDeletePostActionForPostType, onActionPerformed, isLoaded, supportsRevisions, diff --git a/packages/editor/src/components/post-actions/index.js b/packages/editor/src/components/post-actions/index.js index b2730e760c4270..5b023956178938 100644 --- a/packages/editor/src/components/post-actions/index.js +++ b/packages/editor/src/components/post-actions/index.js @@ -29,26 +29,38 @@ const { export default function PostActions( { onActionPerformed, buttonProps } ) { const [ isActionsMenuOpen, setIsActionsMenuOpen ] = useState( false ); - const { item, postType } = useSelect( ( select ) => { + const { item, permissions, postType } = useSelect( ( select ) => { const { getCurrentPostType, getCurrentPostId } = select( editorStore ); - const { getEditedEntityRecord } = select( coreStore ); + const { getEditedEntityRecord, getEntityRecordPermissions } = unlock( + select( coreStore ) + ); const _postType = getCurrentPostType(); + const _id = getCurrentPostId(); return { - item: getEditedEntityRecord( + item: getEditedEntityRecord( 'postType', _postType, _id ), + permissions: getEntityRecordPermissions( 'postType', _postType, - getCurrentPostId() + _id ), postType: _postType, }; }, [] ); + const itemWithPermissions = useMemo( () => { + return { + ...item, + permissions, + }; + }, [ item, permissions ] ); const allActions = usePostActions( { postType, onActionPerformed } ); const actions = useMemo( () => { return allActions.filter( ( action ) => { - return ! action.isEligible || action.isEligible( item ); + return ( + ! action.isEligible || action.isEligible( itemWithPermissions ) + ); } ); - }, [ allActions, item ] ); + }, [ allActions, itemWithPermissions ] ); return ( <DropdownMenu @@ -72,7 +84,7 @@ export default function PostActions( { onActionPerformed, buttonProps } ) { > <ActionsDropdownMenuGroup actions={ actions } - item={ item } + item={ itemWithPermissions } onClose={ () => { setIsActionsMenuOpen( false ); } } From ea91b6f156a821919b984095b012171d2c268d4e Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Mon, 29 Jul 2024 11:18:48 +0100 Subject: [PATCH 0134/1908] Update template description in table layout (#63942) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/base-styles/_variables.scss | 1 - .../edit-site/src/components/page-templates/style.scss | 8 +++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/base-styles/_variables.scss b/packages/base-styles/_variables.scss index b10eeeb167dadf..f5a9ec38824ff3 100644 --- a/packages/base-styles/_variables.scss +++ b/packages/base-styles/_variables.scss @@ -22,7 +22,6 @@ $text-editor-font-size: 15px; $editor-line-height: 1.8; $mobile-text-min-font-size: 16px; // Any font size below 16px will cause Mobile Safari to "zoom in". - /** * Grid System. * https://make.wordpress.org/design/2019/10/31/proposal-a-consistent-spacing-system-for-wordpress/ diff --git a/packages/edit-site/src/components/page-templates/style.scss b/packages/edit-site/src/components/page-templates/style.scss index f3d596cc90f18e..067720ad9a1e97 100644 --- a/packages/edit-site/src/components/page-templates/style.scss +++ b/packages/edit-site/src/components/page-templates/style.scss @@ -52,7 +52,13 @@ } .page-templates-description { - white-space: normal; + max-width: 50em; + text-wrap: balance; // Fallback for Safari + text-wrap: pretty; + + .dataviews-view-table & { + margin-bottom: $grid-unit-10; + } } .edit-site-page-templates { From 1cbf2cd9f5edfabef4955558ab744f0d0f35eb34 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 29 Jul 2024 21:59:38 +0900 Subject: [PATCH 0135/1908] ColorPalette: Remove extra bottom margin when `CircularOptionPicker` is unneeded (#63961) * ColorPalette: Hide CircularOptionPicker when unneeded * ShadowsEditPanel: Remove style override * Add changelog * ShadowsEditPanel: Remove heading * ShadowsEditPanel: Remove unnecessary divs Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: madhusudhand <madhudollu@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/color-palette/index.tsx | 42 +++--- .../global-styles/shadows-edit-panel.js | 139 +++++++++--------- .../src/components/global-styles/style.scss | 11 +- 4 files changed, 93 insertions(+), 100 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index f8666e96a20a15..6413a2fb4d7b44 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -4,6 +4,7 @@ ### Bug Fixes +- `ColorPalette`: Remove extra bottom margin when `CircularOptionPicker` is unneeded ([#63961](https://github.com/WordPress/gutenberg/pull/63961)). - `CustomSelectControl`: Restore `describedBy` functionality ([#63957](https://github.com/WordPress/gutenberg/pull/63957)). ### Internal diff --git a/packages/components/src/color-palette/index.tsx b/packages/components/src/color-palette/index.tsx index 1c1bb1204afef2..c744faee9b0c3f 100644 --- a/packages/components/src/color-palette/index.tsx +++ b/packages/components/src/color-palette/index.tsx @@ -335,26 +335,28 @@ function UnforwardedColorPalette( ) } /> ) } - <CircularOptionPicker - { ...metaProps } - actions={ actions } - options={ - hasMultipleColorOrigins ? ( - <MultiplePalettes - { ...paletteCommonProps } - headingLevel={ headingLevel } - colors={ colors as PaletteObject[] } - value={ value } - /> - ) : ( - <SinglePalette - { ...paletteCommonProps } - colors={ colors as ColorObject[] } - value={ value } - /> - ) - } - /> + { ( colors.length > 0 || actions ) && ( + <CircularOptionPicker + { ...metaProps } + actions={ actions } + options={ + hasMultipleColorOrigins ? ( + <MultiplePalettes + { ...paletteCommonProps } + headingLevel={ headingLevel } + colors={ colors as PaletteObject[] } + value={ value } + /> + ) : ( + <SinglePalette + { ...paletteCommonProps } + colors={ colors as ColorObject[] } + value={ value } + /> + ) + } + /> + ) } </VStack> ); } diff --git a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js index ece57f92237fb9..acca656428d187 100644 --- a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js +++ b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js @@ -11,7 +11,6 @@ import { __experimentalVStack as VStack, __experimentalSpacer as Spacer, __experimentalItemGroup as ItemGroup, - __experimentalHeading as Heading, __experimentalInputControl as InputControl, __experimentalUnitControl as UnitControl, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, @@ -395,13 +394,14 @@ function ShadowItem( { shadow, onChange, canRemove, onRemove } ) { ); } } renderContent={ () => ( - <DropdownContentWrapper paddingSize="none"> - <div className="edit-site-global-styles__shadow-editor__dropdown-content"> - <ShadowPopover - shadowObj={ shadowObj } - onChange={ onShadowChange } - /> - </div> + <DropdownContentWrapper + paddingSize="medium" + className="edit-site-global-styles__shadow-editor__dropdown-content" + > + <ShadowPopover + shadowObj={ shadowObj } + onChange={ onShadowChange } + /> </DropdownContentWrapper> ) } /> @@ -421,71 +421,64 @@ function ShadowPopover( { shadowObj, onChange } ) { }; return ( - <div className="edit-site-global-styles__shadow-editor-panel"> - <VStack spacing={ 2 }> - <Heading level={ 5 }>{ __( 'Shadow' ) }</Heading> - <div className="edit-site-global-styles__shadow-editor-color-palette"> - <ColorPalette - clearable={ false } - enableAlpha={ enableAlpha } - __experimentalIsRenderedInSidebar={ - __experimentalIsRenderedInSidebar - } - value={ shadowObj.color } - onChange={ ( value ) => - onShadowChange( 'color', value ) - } - /> - </div> - <ToggleGroupControl - value={ shadowObj.inset ? 'inset' : 'outset' } - isBlock - onChange={ ( value ) => - onShadowChange( 'inset', value === 'inset' ) - } - hideLabelFromVision - __next40pxDefaultSize - > - <ToggleGroupControlOption - value="outset" - label={ __( 'Outset' ) } - /> - <ToggleGroupControlOption - value="inset" - label={ __( 'Inset' ) } - /> - </ToggleGroupControl> - <Grid columns={ 2 } gap={ 4 }> - <ShadowInputControl - label={ __( 'X Position' ) } - value={ shadowObj.x } - hasNegativeRange - onChange={ ( value ) => onShadowChange( 'x', value ) } - /> - <ShadowInputControl - label={ __( 'Y Position' ) } - value={ shadowObj.y } - hasNegativeRange - onChange={ ( value ) => onShadowChange( 'y', value ) } - /> - <ShadowInputControl - label={ __( 'Blur' ) } - value={ shadowObj.blur } - onChange={ ( value ) => - onShadowChange( 'blur', value ) - } - /> - <ShadowInputControl - label={ __( 'Spread' ) } - value={ shadowObj.spread } - hasNegativeRange - onChange={ ( value ) => - onShadowChange( 'spread', value ) - } - /> - </Grid> - </VStack> - </div> + <VStack + spacing={ 4 } + className="edit-site-global-styles__shadow-editor-panel" + > + <ColorPalette + clearable={ false } + enableAlpha={ enableAlpha } + __experimentalIsRenderedInSidebar={ + __experimentalIsRenderedInSidebar + } + value={ shadowObj.color } + onChange={ ( value ) => onShadowChange( 'color', value ) } + /> + <ToggleGroupControl + __nextHasNoMarginBottom + value={ shadowObj.inset ? 'inset' : 'outset' } + isBlock + onChange={ ( value ) => + onShadowChange( 'inset', value === 'inset' ) + } + hideLabelFromVision + __next40pxDefaultSize + > + <ToggleGroupControlOption + value="outset" + label={ __( 'Outset' ) } + /> + <ToggleGroupControlOption + value="inset" + label={ __( 'Inset' ) } + /> + </ToggleGroupControl> + <Grid columns={ 2 } gap={ 4 }> + <ShadowInputControl + label={ __( 'X Position' ) } + value={ shadowObj.x } + hasNegativeRange + onChange={ ( value ) => onShadowChange( 'x', value ) } + /> + <ShadowInputControl + label={ __( 'Y Position' ) } + value={ shadowObj.y } + hasNegativeRange + onChange={ ( value ) => onShadowChange( 'y', value ) } + /> + <ShadowInputControl + label={ __( 'Blur' ) } + value={ shadowObj.blur } + onChange={ ( value ) => onShadowChange( 'blur', value ) } + /> + <ShadowInputControl + label={ __( 'Spread' ) } + value={ shadowObj.spread } + hasNegativeRange + onChange={ ( value ) => onShadowChange( 'spread', value ) } + /> + </Grid> + </VStack> ); } diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss index 48a12081e98178..f85d69ad864ad8 100644 --- a/packages/edit-site/src/components/global-styles/style.scss +++ b/packages/edit-site/src/components/global-styles/style.scss @@ -135,16 +135,13 @@ } } -.edit-site-global-styles__shadow-editor-panel { +.edit-site-global-styles__shadow-editor__dropdown-content { width: 280px; - padding: $grid-unit-20; +} + +.edit-site-global-styles__shadow-editor-panel { // because tooltip of the range control is too close to the edge and creates overflow margin-bottom: $grid-unit-05; - - & .edit-site-global-styles__shadow-editor-color-palette { - // color palette adds empty .components-circular-option-picker - margin-bottom: -1 * $grid-unit-05; - } } .edit-site-global-styles__shadow-editor__dropdown { From 9c50ac3c027e4ee10d35d2691603f390d6f266aa Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Mon, 29 Jul 2024 16:09:19 +0200 Subject: [PATCH 0136/1908] New useBlockElementRef hook for storing block element into a ref (#63799) * Element: export React types for refs * New useBlockElementRef hook for storing block element into a ref * Extract assignRef function outside the hook --- .../src/components/block-breadcrumb/index.js | 6 +- .../src/components/block-draggable/index.js | 6 +- .../use-block-props/use-block-refs.js | 70 +++++++------------ .../src/components/block-popover/cover.js | 2 +- .../src/components/block-popover/inbetween.js | 2 +- .../src/components/block-popover/index.js | 2 +- .../block-tools/block-selection-button.js | 2 +- .../use-block-toolbar-popover-props.js | 2 +- .../src/components/grid/grid-item-resizer.js | 2 +- .../src/components/grid/grid-visualizer.js | 2 +- .../skip-to-selected-block/index.js | 8 ++- .../src/hooks/contrast-checker.js | 14 ++-- packages/block-editor/src/hooks/duotone.js | 2 +- .../src/hooks/spacing-visualizer.js | 2 +- packages/element/src/react.js | 16 ++++- 15 files changed, 70 insertions(+), 68 deletions(-) diff --git a/packages/block-editor/src/components/block-breadcrumb/index.js b/packages/block-editor/src/components/block-breadcrumb/index.js index b3f2d3dee12013..8bd790c5c8fb21 100644 --- a/packages/block-editor/src/components/block-breadcrumb/index.js +++ b/packages/block-editor/src/components/block-breadcrumb/index.js @@ -5,6 +5,7 @@ import { Button } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { chevronRightSmall, Icon } from '@wordpress/icons'; +import { useRef } from '@wordpress/element'; /** * Internal dependencies @@ -12,7 +13,7 @@ import { chevronRightSmall, Icon } from '@wordpress/icons'; import BlockTitle from '../block-title'; import { store as blockEditorStore } from '../../store'; import { unlock } from '../../lock-unlock'; -import { __unstableUseBlockRef as useBlockRef } from '../block-list/use-block-props/use-block-refs'; +import { useBlockElementRef } from '../block-list/use-block-props/use-block-refs'; import getEditorRegion from '../../utils/get-editor-region'; /** @@ -41,7 +42,8 @@ function BlockBreadcrumb( { rootLabelText } ) { // We don't care about this specific ref, but this is a way // to get a ref within the editor canvas so we can focus it later. - const blockRef = useBlockRef( clientId ); + const blockRef = useRef(); + useBlockElementRef( clientId, blockRef ); /* * Disable reason: The `list` ARIA role is redundant but diff --git a/packages/block-editor/src/components/block-draggable/index.js b/packages/block-editor/src/components/block-draggable/index.js index 0ba2b857bc693e..e1afc1f2513841 100644 --- a/packages/block-editor/src/components/block-draggable/index.js +++ b/packages/block-editor/src/components/block-draggable/index.js @@ -13,7 +13,7 @@ import { throttle } from '@wordpress/compose'; import BlockDraggableChip from './draggable-chip'; import useScrollWhenDragging from './use-scroll-when-dragging'; import { store as blockEditorStore } from '../../store'; -import { __unstableUseBlockRef as useBlockRef } from '../block-list/use-block-props/use-block-refs'; +import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; import { isDropTargetValid } from '../use-block-drop-zone'; const BlockDraggable = ( { @@ -82,8 +82,8 @@ const BlockDraggable = ( { }, [] ); // Find the root of the editor iframe. - const blockRef = useBlockRef( clientIds[ 0 ] ); - const editorRoot = blockRef.current?.closest( 'body' ); + const blockEl = useBlockElement( clientIds[ 0 ] ); + const editorRoot = blockEl?.closest( 'body' ); /* * Add a dragover event listener to the editor root to track the blocks being dragged over. diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-block-refs.js b/packages/block-editor/src/components/block-list/use-block-props/use-block-refs.js index 056ade045d1654..16fd3ff1ca81dd 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-block-refs.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-block-refs.js @@ -1,13 +1,7 @@ /** * WordPress dependencies */ -import { - useContext, - useMemo, - useRef, - useState, - useLayoutEffect, -} from '@wordpress/element'; +import { useContext, useState, useLayoutEffect } from '@wordpress/element'; import { useRefEffect } from '@wordpress/compose'; /** @@ -16,7 +10,7 @@ import { useRefEffect } from '@wordpress/compose'; import { BlockRefs } from '../../provider/block-refs-provider'; /** @typedef {import('@wordpress/element').RefCallback} RefCallback */ -/** @typedef {import('@wordpress/element').RefObject} RefObject */ +/** @typedef {import('@wordpress/element').Ref} Ref */ /** * Provides a ref to the BlockRefs context. @@ -36,31 +30,33 @@ export function useBlockRefProvider( clientId ) { ); } +function assignRef( ref, value ) { + if ( typeof ref === 'function' ) { + ref( value ); + } else if ( ref ) { + ref.current = value; + } +} + /** - * Gets a ref pointing to the current block element. Continues to return the same - * stable ref object even if the `clientId` argument changes. This hook is not - * reactive, i.e., it won't trigger a rerender of the calling component if the - * ref value changes. For reactive use cases there is the `useBlockElement` hook. - * - * @param {string} clientId The client ID to get a ref for. + * Tracks the DOM element for the block identified by `clientId` and assigns it to the `ref` + * whenever it changes. * - * @return {RefObject} A ref containing the element. + * @param {string} clientId The client ID to track. + * @param {Ref} ref The ref object/callback to assign to. */ -function useBlockRef( clientId ) { +export function useBlockElementRef( clientId, ref ) { const { refsMap } = useContext( BlockRefs ); - const latestClientId = useRef(); - latestClientId.current = clientId; - - // Always return an object, even if no ref exists for a given client ID, so - // that `current` works at a later point. - return useMemo( - () => ( { - get current() { - return refsMap.get( latestClientId.current ) ?? null; - }, - } ), - [ refsMap ] - ); + useLayoutEffect( () => { + assignRef( ref, refsMap.get( clientId ) ); + const unsubscribe = refsMap.subscribe( clientId, () => + assignRef( ref, refsMap.get( clientId ) ) + ); + return () => { + unsubscribe(); + assignRef( ref, null ); + }; + }, [ refsMap, clientId, ref ] ); } /** @@ -71,20 +67,8 @@ function useBlockRef( clientId ) { * * @return {Element|null} The block's wrapper element. */ -function useBlockElement( clientId ) { - const { refsMap } = useContext( BlockRefs ); +export function useBlockElement( clientId ) { const [ blockElement, setBlockElement ] = useState( null ); - // Delay setting the resulting `blockElement` until an effect. If the block element - // changes (i.e., the block is unmounted and re-mounted), this allows enough time - // for the ref callbacks to clean up the old element and set the new one. - useLayoutEffect( () => { - setBlockElement( refsMap.get( clientId ) ); - return refsMap.subscribe( clientId, () => - setBlockElement( refsMap.get( clientId ) ) - ); - }, [ refsMap, clientId ] ); + useBlockElementRef( clientId, setBlockElement ); return blockElement; } - -export { useBlockRef as __unstableUseBlockRef }; -export { useBlockElement as __unstableUseBlockElement }; diff --git a/packages/block-editor/src/components/block-popover/cover.js b/packages/block-editor/src/components/block-popover/cover.js index caad2ddbb7ec56..401431defe4fd5 100644 --- a/packages/block-editor/src/components/block-popover/cover.js +++ b/packages/block-editor/src/components/block-popover/cover.js @@ -6,7 +6,7 @@ import { useEffect, useState, useMemo, forwardRef } from '@wordpress/element'; /** * Internal dependencies */ -import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs'; +import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; import { PrivateBlockPopover } from '.'; function BlockPopoverCover( diff --git a/packages/block-editor/src/components/block-popover/inbetween.js b/packages/block-editor/src/components/block-popover/inbetween.js index bc2eaeae0be603..2ed9ee0bcb284f 100644 --- a/packages/block-editor/src/components/block-popover/inbetween.js +++ b/packages/block-editor/src/components/block-popover/inbetween.js @@ -20,7 +20,7 @@ import { isRTL } from '@wordpress/i18n'; * Internal dependencies */ import { store as blockEditorStore } from '../../store'; -import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs'; +import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; import usePopoverScroll from './use-popover-scroll'; const MAX_POPOVER_RECOMPUTE_COUNTER = Number.MAX_SAFE_INTEGER; diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index cc8d832c31bc70..2413601a590e2e 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -18,7 +18,7 @@ import { /** * Internal dependencies */ -import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs'; +import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; import usePopoverScroll from './use-popover-scroll'; const MAX_POPOVER_RECOMPUTE_COUNTER = Number.MAX_SAFE_INTEGER; diff --git a/packages/block-editor/src/components/block-tools/block-selection-button.js b/packages/block-editor/src/components/block-tools/block-selection-button.js index 036aef4f135d3c..8d99b829a84bf4 100644 --- a/packages/block-editor/src/components/block-tools/block-selection-button.js +++ b/packages/block-editor/src/components/block-tools/block-selection-button.js @@ -37,7 +37,7 @@ import BlockTitle from '../block-title'; import BlockIcon from '../block-icon'; import { store as blockEditorStore } from '../../store'; import BlockDraggable from '../block-draggable'; -import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs'; +import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; /** * Block selection button component, displaying the label of the block. If the block diff --git a/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js b/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js index f99323dd5c80a7..0ca0f6e5a43dda 100644 --- a/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js +++ b/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js @@ -15,7 +15,7 @@ import { * Internal dependencies */ import { store as blockEditorStore } from '../../store'; -import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs'; +import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; import { hasStickyOrFixedPositionValue } from '../../hooks/position'; const COMMON_PROPS = { diff --git a/packages/block-editor/src/components/grid/grid-item-resizer.js b/packages/block-editor/src/components/grid/grid-item-resizer.js index 34bc1db6048067..28d9678772f76c 100644 --- a/packages/block-editor/src/components/grid/grid-item-resizer.js +++ b/packages/block-editor/src/components/grid/grid-item-resizer.js @@ -7,7 +7,7 @@ import { useState, useEffect } from '@wordpress/element'; /** * Internal dependencies */ -import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs'; +import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; import BlockPopoverCover from '../block-popover/cover'; import { getComputedCSS, getGridTracks, getClosestTrack } from './utils'; diff --git a/packages/block-editor/src/components/grid/grid-visualizer.js b/packages/block-editor/src/components/grid/grid-visualizer.js index 5e5e1e3bfa2f77..e1d35f012b4d81 100644 --- a/packages/block-editor/src/components/grid/grid-visualizer.js +++ b/packages/block-editor/src/components/grid/grid-visualizer.js @@ -13,7 +13,7 @@ import { __experimentalUseDropZone as useDropZone } from '@wordpress/compose'; /** * Internal dependencies */ -import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs'; +import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; import BlockPopoverCover from '../block-popover/cover'; import { range, GridRect, getGridInfo } from './utils'; import { store as blockEditorStore } from '../../store'; diff --git a/packages/block-editor/src/components/skip-to-selected-block/index.js b/packages/block-editor/src/components/skip-to-selected-block/index.js index 51062e32934f0b..2f78f706112c38 100644 --- a/packages/block-editor/src/components/skip-to-selected-block/index.js +++ b/packages/block-editor/src/components/skip-to-selected-block/index.js @@ -4,12 +4,13 @@ import { useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { Button } from '@wordpress/components'; +import { useRef } from '@wordpress/element'; /** * Internal dependencies */ import { store as blockEditorStore } from '../../store'; -import { __unstableUseBlockRef as useBlockRef } from '../block-list/use-block-props/use-block-refs'; +import { useBlockElementRef } from '../block-list/use-block-props/use-block-refs'; /** * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/skip-to-selected-block/README.md @@ -19,9 +20,10 @@ export default function SkipToSelectedBlock() { ( select ) => select( blockEditorStore ).getBlockSelectionStart(), [] ); - const ref = useBlockRef( selectedBlockClientId ); + const ref = useRef(); + useBlockElementRef( selectedBlockClientId, ref ); const onClick = () => { - ref.current.focus(); + ref.current?.focus(); }; return selectedBlockClientId ? ( diff --git a/packages/block-editor/src/hooks/contrast-checker.js b/packages/block-editor/src/hooks/contrast-checker.js index ef04da63e4946b..6e503ae8f3319d 100644 --- a/packages/block-editor/src/hooks/contrast-checker.js +++ b/packages/block-editor/src/hooks/contrast-checker.js @@ -7,7 +7,7 @@ import { useState, useEffect } from '@wordpress/element'; * Internal dependencies */ import ContrastChecker from '../components/contrast-checker'; -import { __unstableUseBlockRef as useBlockRef } from '../components/block-list/use-block-props/use-block-refs'; +import { useBlockElement } from '../components/block-list/use-block-props/use-block-refs'; function getComputedStyle( node ) { return node.ownerDocument.defaultView.getComputedStyle( node ); @@ -17,23 +17,23 @@ export default function BlockColorContrastChecker( { clientId } ) { const [ detectedBackgroundColor, setDetectedBackgroundColor ] = useState(); const [ detectedColor, setDetectedColor ] = useState(); const [ detectedLinkColor, setDetectedLinkColor ] = useState(); - const ref = useBlockRef( clientId ); + const blockEl = useBlockElement( clientId ); // There are so many things that can change the color of a block // So we perform this check on every render. // eslint-disable-next-line react-hooks/exhaustive-deps useEffect( () => { - if ( ! ref.current ) { + if ( ! blockEl ) { return; } - setDetectedColor( getComputedStyle( ref.current ).color ); + setDetectedColor( getComputedStyle( blockEl ).color ); - const firstLinkElement = ref.current?.querySelector( 'a' ); + const firstLinkElement = blockEl.querySelector( 'a' ); if ( firstLinkElement && !! firstLinkElement.innerText ) { setDetectedLinkColor( getComputedStyle( firstLinkElement ).color ); } - let backgroundColorNode = ref.current; + let backgroundColorNode = blockEl; let backgroundColor = getComputedStyle( backgroundColorNode ).backgroundColor; while ( @@ -48,7 +48,7 @@ export default function BlockColorContrastChecker( { clientId } ) { } setDetectedBackgroundColor( backgroundColor ); - } ); + }, [ blockEl ] ); return ( <ContrastChecker diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index c52cec46051e0c..88f2d6064046f9 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -35,7 +35,7 @@ import { scopeSelector } from '../components/global-styles/utils'; import { useBlockSettings, useStyleOverride } from './utils'; import { default as StylesFiltersPanel } from '../components/global-styles/filters-panel'; import { useBlockEditingMode } from '../components/block-editing-mode'; -import { __unstableUseBlockElement as useBlockElement } from '../components/block-list/use-block-props/use-block-refs'; +import { useBlockElement } from '../components/block-list/use-block-props/use-block-refs'; const EMPTY_ARRAY = []; diff --git a/packages/block-editor/src/hooks/spacing-visualizer.js b/packages/block-editor/src/hooks/spacing-visualizer.js index 7189b0f480d2cc..52141d87be7150 100644 --- a/packages/block-editor/src/hooks/spacing-visualizer.js +++ b/packages/block-editor/src/hooks/spacing-visualizer.js @@ -14,7 +14,7 @@ import isShallowEqual from '@wordpress/is-shallow-equal'; * Internal dependencies */ import BlockPopoverCover from '../components/block-popover/cover'; -import { __unstableUseBlockElement as useBlockElement } from '../components/block-list/use-block-props/use-block-refs'; +import { useBlockElement } from '../components/block-list/use-block-props/use-block-refs'; function SpacingVisualizer( { clientId, value, computeStyle, forceShow } ) { const blockElement = useBlockElement( clientId ); diff --git a/packages/element/src/react.js b/packages/element/src/react.js index dfe776370b2d32..cf2f9614bc3316 100644 --- a/packages/element/src/react.js +++ b/packages/element/src/react.js @@ -54,12 +54,26 @@ import { */ /** - * Object containing a React synthetic event. + * Object containing a React ref object. * * @template T * @typedef {import('react').RefObject<T>} RefObject<T> */ +/** + * Object containing a React ref callback. + * + * @template T + * @typedef {import('react').RefCallback<T>} RefCallback<T> + */ + +/** + * Object containing a React ref. + * + * @template T + * @typedef {import('react').Ref<T>} Ref<T> + */ + /** * Object that provides utilities for dealing with React children. */ From 6c26d0b92f797c5df39d32424c53e75c23f54bb9 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 29 Jul 2024 17:15:23 +0200 Subject: [PATCH 0137/1908] BaseControl: change label's display: block (#63911) * BaseControl: change label to `display: block` * Remove unnecessary font-weight override * Remove unnecessary display: block overrides * CHANGELOG * snapshots --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../color-palette/test/__snapshots__/control.js.snap | 2 +- packages/block-library/src/gallery/editor.scss | 1 - packages/block-library/src/latest-posts/editor.scss | 4 ---- packages/block-library/src/video/editor.scss | 4 ---- packages/components/CHANGELOG.md | 1 + .../src/base-control/styles/base-control-styles.ts | 2 +- packages/components/src/border-control/styles.ts | 5 ----- .../test/__snapshots__/index.tsx.snap | 8 ++++---- .../post-publish-panel/test/__snapshots__/index.js.snap | 4 ++-- 9 files changed, 9 insertions(+), 22 deletions(-) diff --git a/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap b/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap index 7a04f41a29b050..bd9175782a224a 100644 --- a/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap +++ b/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap @@ -45,7 +45,7 @@ exports[`ColorPaletteControl matches the snapshot 1`] = ` font-weight: 500; line-height: 1.4; text-transform: uppercase; - display: inline-block; + display: block; margin-bottom: calc(4px * 2); padding: 0; } diff --git a/packages/block-library/src/gallery/editor.scss b/packages/block-library/src/gallery/editor.scss index 9efaf88e5acc71..025e86277f7edc 100644 --- a/packages/block-library/src/gallery/editor.scss +++ b/packages/block-library/src/gallery/editor.scss @@ -70,7 +70,6 @@ .gallery-image-sizes { .components-base-control__label { - display: block; margin-bottom: 4px; } diff --git a/packages/block-library/src/latest-posts/editor.scss b/packages/block-library/src/latest-posts/editor.scss index d3f0b5275653e3..02651ee8495125 100644 --- a/packages/block-library/src/latest-posts/editor.scss +++ b/packages/block-library/src/latest-posts/editor.scss @@ -10,10 +10,6 @@ } .editor-latest-posts-image-alignment-control { - .components-base-control__label { - display: block; - } - .components-toolbar { border-radius: $radius-block-ui; } diff --git a/packages/block-library/src/video/editor.scss b/packages/block-library/src/video/editor.scss index bfdeadab4d3322..792939356b1de9 100644 --- a/packages/block-library/src/video/editor.scss +++ b/packages/block-library/src/video/editor.scss @@ -57,10 +57,6 @@ } .editor-video-poster-control { - .components-base-control__label { - display: block; - } - .components-button { margin-right: $grid-unit-10; } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 6413a2fb4d7b44..9611c1e5e60c3c 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -19,6 +19,7 @@ ### Bug Fixes +- `BaseControl`: change label's `display` to `block`. ([#63911](https://github.com/WordPress/gutenberg/pull/63911)) - `ComboboxControl`: Fix ComboboxControl reset button when using the keyboard. ([#63410](https://github.com/WordPress/gutenberg/pull/63410)) - `Button`: Never apply `aria-disabled` to anchor ([#63376](https://github.com/WordPress/gutenberg/pull/63376)). - `SelectControl`: Fix hover/focus color in wp-admin ([#63855](https://github.com/WordPress/gutenberg/pull/63855)). diff --git a/packages/components/src/base-control/styles/base-control-styles.ts b/packages/components/src/base-control/styles/base-control-styles.ts index 6ddfe10229fdbb..d633fcdd7e7a77 100644 --- a/packages/components/src/base-control/styles/base-control-styles.ts +++ b/packages/components/src/base-control/styles/base-control-styles.ts @@ -37,7 +37,7 @@ export const StyledField = styled.div` const labelStyles = css` ${ baseLabelTypography }; - display: inline-block; + display: block; margin-bottom: ${ space( 2 ) }; /** * Removes Chrome/Safari/Firefox user agent stylesheet padding from diff --git a/packages/components/src/border-control/styles.ts b/packages/components/src/border-control/styles.ts index 6a8892e78ef553..28669ebf3ccc78 100644 --- a/packages/components/src/border-control/styles.ts +++ b/packages/components/src/border-control/styles.ts @@ -16,10 +16,6 @@ import { import type { Border } from './types'; -const labelStyles = css` - font-weight: 500; -`; - const focusBoxShadow = css` box-shadow: inset ${ CONFIG.controlBoxShadowFocus }; `; @@ -140,7 +136,6 @@ export const borderControlPopoverControls = css` > div:first-of-type > ${ StyledLabel } { margin-bottom: 0; - ${ labelStyles } } && ${ StyledLabel } + button:not( .has-text ) { diff --git a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap index cdfa4b1883cc16..908e15927e3b86 100644 --- a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap +++ b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap @@ -33,7 +33,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = font-weight: 500; line-height: 1.4; text-transform: uppercase; - display: inline-block; + display: block; margin-bottom: calc(4px * 2); padding: 0; } @@ -369,7 +369,7 @@ exports[`ToggleGroupControl controlled should render correctly with text options font-weight: 500; line-height: 1.4; text-transform: uppercase; - display: inline-block; + display: block; margin-bottom: calc(4px * 2); padding: 0; } @@ -593,7 +593,7 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] font-weight: 500; line-height: 1.4; text-transform: uppercase; - display: inline-block; + display: block; margin-bottom: calc(4px * 2); padding: 0; } @@ -923,7 +923,7 @@ exports[`ToggleGroupControl uncontrolled should render correctly with text optio font-weight: 500; line-height: 1.4; text-transform: uppercase; - display: inline-block; + display: block; margin-bottom: calc(4px * 2); padding: 0; } diff --git a/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap b/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap index 7f31c97018d092..42fc0f7fe0f245 100644 --- a/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap +++ b/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap @@ -22,7 +22,7 @@ exports[`PostPublishPanel should render the post-publish panel if the post is pu font-weight: 500; line-height: 1.4; text-transform: uppercase; - display: inline-block; + display: block; margin-bottom: calc(4px * 2); padding: 0; } @@ -214,7 +214,7 @@ exports[`PostPublishPanel should render the post-publish panel if the post is sc font-weight: 500; line-height: 1.4; text-transform: uppercase; - display: inline-block; + display: block; margin-bottom: calc(4px * 2); padding: 0; } From 628d7a67187c6595ef6a15ff7ca0eebaae024681 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 30 Jul 2024 00:48:55 +0900 Subject: [PATCH 0138/1908] Add margin-bottom lint rules for ToggleGroupControl (#63960) * Add margin-bottom lint rules for ToggleGroupControl * BackgroundControlsPanel: Tangential fixes * Fix new violation in Query Loop block Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .eslintrc.js | 1 + .../block-editor/src/components/dimensions-tool/scale-tool.js | 1 + .../src/components/global-styles/background-panel.js | 3 +++ packages/block-editor/src/components/global-styles/style.scss | 4 ---- .../block-library/src/query/edit/inspector-controls/index.js | 1 + 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 01f6967e8fe947..0fc37713dce4d1 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -296,6 +296,7 @@ module.exports = { 'RangeControl', 'SearchControl', 'TextareaControl', + 'ToggleGroupControl', 'TreeSelect', ].map( ( componentName ) => ( { selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__nextHasNoMarginBottom"]))`, diff --git a/packages/block-editor/src/components/dimensions-tool/scale-tool.js b/packages/block-editor/src/components/dimensions-tool/scale-tool.js index 05a7d2f4d251a7..a23fad586d4705 100644 --- a/packages/block-editor/src/components/dimensions-tool/scale-tool.js +++ b/packages/block-editor/src/components/dimensions-tool/scale-tool.js @@ -105,6 +105,7 @@ export default function ScaleTool( { panelId={ panelId } > <ToggleGroupControl + __nextHasNoMarginBottom label={ __( 'Scale' ) } isBlock help={ scaleHelp[ displayValue ] } diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index 25ff5887eb5e65..7a99a46943dbc6 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -569,6 +569,7 @@ function BackgroundSizeControls( { onChange={ updateBackgroundPosition } /> <ToggleControl + __nextHasNoMarginBottom label={ __( 'Fixed background' ) } checked={ attachmentValue === 'fixed' } onChange={ toggleScrollWithPage } @@ -577,6 +578,7 @@ function BackgroundSizeControls( { ) } /> <ToggleGroupControl + __nextHasNoMarginBottom size="__unstable-large" label={ __( 'Size' ) } value={ currentValueForToggle } @@ -626,6 +628,7 @@ function BackgroundSizeControls( { } /> <ToggleControl + __nextHasNoMarginBottom label={ __( 'Repeat' ) } checked={ repeatCheckedValue } onChange={ toggleIsRepeated } diff --git a/packages/block-editor/src/components/global-styles/style.scss b/packages/block-editor/src/components/global-styles/style.scss index f901506b6b188d..0bab29a9a3f2ad 100644 --- a/packages/block-editor/src/components/global-styles/style.scss +++ b/packages/block-editor/src/components/global-styles/style.scss @@ -193,10 +193,6 @@ .block-editor-global-styles-background-panel__dropdown-content-wrapper { min-width: 260px; overflow-x: hidden; - .components-base-control__help, - .components-toggle-control { - margin-bottom: 0; - } .components-focal-point-picker-wrapper { background-color: $gray-100; diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index 81c21a236322ce..5e83ea3aaa9730 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -147,6 +147,7 @@ export default function QueryInspectorControls( props ) { { showInheritControl && ( <ToggleGroupControl __next40pxDefaultSize + __nextHasNoMarginBottom label={ __( 'Query type' ) } isBlock onChange={ ( value ) => { From e7664867bdaa02291dace9fb93892f4e49416119 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Mon, 29 Jul 2024 18:02:47 +0200 Subject: [PATCH 0139/1908] Fix: Interactivity API benefits of standard documentation link. (#64060) --- docs/reference-guides/interactivity-api/iapi-faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference-guides/interactivity-api/iapi-faq.md b/docs/reference-guides/interactivity-api/iapi-faq.md index 5e5036779baaeb..dea7bc1d4367be 100644 --- a/docs/reference-guides/interactivity-api/iapi-faq.md +++ b/docs/reference-guides/interactivity-api/iapi-faq.md @@ -66,7 +66,7 @@ To summarize, using the Interactivity API rather than just using React comes wit - If you use React, your interactive blocks must generate the same markup on the client as they do on the server in PHP. Using the Interactivity API, there is no such requirement as directives are added to server-rendered HTML. - The Interactivity API is PHP-friendlier. It works out of the box with WordPress hooks or other server functionalities such as internationalization. For example, with React, you can’t know which hooks are applied on the server, and their modifications would be overwritten after hydration. -- All the benefits of [using a standard](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/what-is-interactivity-api#why-a-standard). +- All the benefits of [using a standard](/docs/reference-guides/interactivity-api/iapi-about.md#why-a-standard). ## What are the benefits of Interactivity API over just using jQuery or vanilla JavaScript? From 417e28aac038c97da73e0479538f331f9bb1c1d9 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Mon, 29 Jul 2024 18:09:51 +0200 Subject: [PATCH 0140/1908] Fix: Non working link to an interactivity API example block. (#64061) --- docs/reference-guides/interactivity-api/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference-guides/interactivity-api/README.md b/docs/reference-guides/interactivity-api/README.md index 9648b0118a5aa1..f5d410a8439f45 100644 --- a/docs/reference-guides/interactivity-api/README.md +++ b/docs/reference-guides/interactivity-api/README.md @@ -119,7 +119,7 @@ Here you have some more resources to learn/read more about the Interactivity API - [Interactivity API Discussions](https://github.com/WordPress/gutenberg/discussions/52882), especially the [showcase](https://github.com/WordPress/gutenberg/discussions/55642#discussioncomment-9667164) discussions. - [wpmovies.dev](http://wpmovies.dev/) demo and its [wp-movies-demo](https://github.com/WordPress/wp-movies-demo) repo - Examples using the Interactivity API at [block-development-examples](https://github.com/WordPress/block-development-examples): - - [`interactivity-api-block-833d15`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/833d15) + - [`interactivity-api-block-833d15`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/interactivity-api-block-833d15) - [`interactivity-api-countdown-3cd73e`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/interactivity-api-countdown-3cd73e) - [`interactivity-api-quiz-1835fa`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/interactivity-api-quiz-1835fa) From b03d835bd1000e926df3f98ac91e5a3728f0f94d Mon Sep 17 00:00:00 2001 From: Nick Diego <nick.diego@automattic.com> Date: Mon, 29 Jul 2024 11:24:03 -0500 Subject: [PATCH 0141/1908] Add a levelOptions attribute to the Heading block. (#63535) Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: troychaplin <areziaal@git.wordpress.org> Co-authored-by: skorasaurus <skorasaurus@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- packages/block-library/src/heading/block.json | 3 +++ packages/block-library/src/heading/edit.js | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 3309a676dfc84a..e9818724b37271 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -360,7 +360,7 @@ Introduce new sections and organize content to help visitors (and search engines - **Name:** core/heading - **Category:** text - **Supports:** __unstablePasteTextInline, align (full, wide), anchor, className, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), splitting, typography (fontSize, lineHeight) -- **Attributes:** content, level, placeholder, textAlign +- **Attributes:** content, level, levelOptions, placeholder, textAlign ## Home Link diff --git a/packages/block-library/src/heading/block.json b/packages/block-library/src/heading/block.json index 0bbe19b01098ea..6e43a18cfba452 100644 --- a/packages/block-library/src/heading/block.json +++ b/packages/block-library/src/heading/block.json @@ -21,6 +21,9 @@ "type": "number", "default": 2 }, + "levelOptions": { + "type": "array" + }, "placeholder": { "type": "string" } diff --git a/packages/block-library/src/heading/edit.js b/packages/block-library/src/heading/edit.js index 86ac776b9b16e4..ea58a75d51cda5 100644 --- a/packages/block-library/src/heading/edit.js +++ b/packages/block-library/src/heading/edit.js @@ -32,7 +32,8 @@ function HeadingEdit( { style, clientId, } ) { - const { textAlign, content, level, placeholder, anchor } = attributes; + const { textAlign, content, level, levelOptions, placeholder, anchor } = + attributes; const tagName = 'h' + level; const blockProps = useBlockProps( { className: clsx( { @@ -95,6 +96,7 @@ function HeadingEdit( { <BlockControls group="block"> <HeadingLevelDropdown value={ level } + options={ levelOptions } onChange={ ( newLevel ) => setAttributes( { level: newLevel } ) } From ef1ee6ba0d7c0321a31506e32458e50094b434f9 Mon Sep 17 00:00:00 2001 From: Xinyu Liu <meteor.lxy@foxmail.com> Date: Tue, 30 Jul 2024 01:00:42 +0800 Subject: [PATCH 0142/1908] CustomSelectControl: support generic props type (#63985) * CustomSelectControl: support generic props type * chore: update changelog * chore: tweak changelog * chore: tweak ordering * chore: remove export Co-authored-by: meteorlxy <meteorlxy@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/custom-select-control/index.tsx | 12 +++++++----- .../components/src/custom-select-control/types.ts | 14 +++++++------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 9611c1e5e60c3c..327f80ba2468ed 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -10,6 +10,7 @@ ### Internal - `DropdownMenuV2`: break menu item help text on multiple lines for better truncation. ([#63916](https://github.com/WordPress/gutenberg/pull/63916)). +- `CustomSelectControl`: Support generic props type ([#63985](https://github.com/WordPress/gutenberg/pull/63985)). ## 28.4.0 (2024-07-24) diff --git a/packages/components/src/custom-select-control/index.tsx b/packages/components/src/custom-select-control/index.tsx index 8735b8d320991e..ecd9dc37a8f491 100644 --- a/packages/components/src/custom-select-control/index.tsx +++ b/packages/components/src/custom-select-control/index.tsx @@ -16,13 +16,13 @@ import { __, sprintf } from '@wordpress/i18n'; import _CustomSelect from '../custom-select-control-v2/custom-select'; import CustomSelectItem from '../custom-select-control-v2/item'; import * as Styled from '../custom-select-control-v2/styles'; -import type { CustomSelectProps } from './types'; +import type { CustomSelectProps, CustomSelectOption } from './types'; import { VisuallyHidden } from '../visually-hidden'; -function useDeprecatedProps( { +function useDeprecatedProps< T extends CustomSelectOption >( { __experimentalShowSelectedHint, ...otherProps -}: CustomSelectProps ) { +}: CustomSelectProps< T > ) { return { showSelectedHint: __experimentalShowSelectedHint, ...otherProps, @@ -35,7 +35,7 @@ function useDeprecatedProps( { function applyOptionDeprecations( { __experimentalHint, ...rest -}: CustomSelectProps[ 'options' ][ number ] ) { +}: CustomSelectOption ) { return { hint: __experimentalHint, ...rest, @@ -51,7 +51,9 @@ function getDescribedBy( currentValue: string, describedBy?: string ) { return sprintf( __( 'Currently selected: %s' ), currentValue ); } -function CustomSelectControl( props: CustomSelectProps ) { +function CustomSelectControl< T extends CustomSelectOption >( + props: CustomSelectProps< T > +) { const { __next40pxDefaultSize = false, describedBy, diff --git a/packages/components/src/custom-select-control/types.ts b/packages/components/src/custom-select-control/types.ts index 98e9633b02f1a8..e37ba349a2b843 100644 --- a/packages/components/src/custom-select-control/types.ts +++ b/packages/components/src/custom-select-control/types.ts @@ -6,7 +6,7 @@ import type { FocusEventHandler, MouseEventHandler } from 'react'; /** * The object structure for the options array. */ -type Option = { +export type CustomSelectOption = { key: string; name: string; style?: React.CSSProperties; @@ -24,15 +24,15 @@ type Option = { /** * The object returned from the onChange event. */ -type ChangeObject = { +type CustomSelectChangeObject< T extends CustomSelectOption > = { highlightedIndex?: number; inputValue?: string; isOpen?: boolean; type?: string; - selectedItem: Option; + selectedItem: T; }; -export type CustomSelectProps = { +export type CustomSelectProps< T extends CustomSelectOption > = { /** * Optional classname for the component. */ @@ -55,7 +55,7 @@ export type CustomSelectProps = { * Function called with the control's internal state changes. The `selectedItem` * property contains the next selected item. */ - onChange?: ( newValue: ChangeObject ) => void; + onChange?: ( newValue: CustomSelectChangeObject< T > ) => void; /** * A handler for `blur` events on the trigger button. * @@ -83,7 +83,7 @@ export type CustomSelectProps = { /** * The list of options that can be chosen from. */ - options: Array< Option >; + options: Array< T >; /** * The size of the control. * @@ -93,7 +93,7 @@ export type CustomSelectProps = { /** * Can be used to externally control the value of the control. */ - value?: Option; + value?: T; /** * Use the `showSelectedHint` property instead. * @deprecated From f50e045c1ce75acd026ab760891cd5bf57234fd3 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 30 Jul 2024 02:08:46 +0900 Subject: [PATCH 0143/1908] FormToggle, ToggleControl: Fix docgen in Storybook (#64065) * ToggleControl: Fix docgen in Storybook * FormToggle: Fix docgen in Storybook Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/src/form-toggle/index.tsx | 44 +++++++++--------- .../components/src/toggle-control/index.tsx | 46 ++++++++++--------- 2 files changed, 47 insertions(+), 43 deletions(-) diff --git a/packages/components/src/form-toggle/index.tsx b/packages/components/src/form-toggle/index.tsx index f0f800514a411f..8a90fe4561bff4 100644 --- a/packages/components/src/form-toggle/index.tsx +++ b/packages/components/src/form-toggle/index.tsx @@ -17,26 +17,7 @@ import type { WordPressComponentProps } from '../context'; export const noop = () => {}; -/** - * FormToggle switches a single setting on or off. - * - * ```jsx - * import { FormToggle } from '@wordpress/components'; - * import { useState } from '@wordpress/element'; - * - * const MyFormToggle = () => { - * const [ isChecked, setChecked ] = useState( true ); - * - * return ( - * <FormToggle - * checked={ isChecked } - * onChange={ () => setChecked( ( state ) => ! state ) } - * /> - * ); - * }; - * ``` - */ -export function FormToggle( +function UnforwardedFormToggle( props: WordPressComponentProps< FormToggleProps, 'input', false >, ref: ForwardedRef< HTMLInputElement > ) { @@ -71,4 +52,25 @@ export function FormToggle( ); } -export default forwardRef( FormToggle ); +/** + * FormToggle switches a single setting on or off. + * + * ```jsx + * import { FormToggle } from '@wordpress/components'; + * import { useState } from '@wordpress/element'; + * + * const MyFormToggle = () => { + * const [ isChecked, setChecked ] = useState( true ); + * + * return ( + * <FormToggle + * checked={ isChecked } + * onChange={ () => setChecked( ( state ) => ! state ) } + * /> + * ); + * }; + * ``` + */ +export const FormToggle = forwardRef( UnforwardedFormToggle ); + +export default FormToggle; diff --git a/packages/components/src/toggle-control/index.tsx b/packages/components/src/toggle-control/index.tsx index 89ef34f6d6e5e6..2c405352ab215f 100644 --- a/packages/components/src/toggle-control/index.tsx +++ b/packages/components/src/toggle-control/index.tsx @@ -23,27 +23,7 @@ import { HStack } from '../h-stack'; import { useCx } from '../utils'; import { space } from '../utils/space'; -/** - * ToggleControl is used to generate a toggle user interface. - * - * ```jsx - * import { ToggleControl } from '@wordpress/components'; - * import { useState } from '@wordpress/element'; - * - * const MyToggleControl = () => { - * const [ value, setValue ] = useState( false ); - * - * return ( - * <ToggleControl - * label="Fixed Background" - * checked={ value } - * onChange={ () => setValue( ( state ) => ! state ) } - * /> - * ); - * }; - * ``` - */ -export function ToggleControl( +function UnforwardedToggleControl( { __nextHasNoMarginBottom, label, @@ -121,4 +101,26 @@ export function ToggleControl( ); } -export default forwardRef( ToggleControl ); +/** + * ToggleControl is used to generate a toggle user interface. + * + * ```jsx + * import { ToggleControl } from '@wordpress/components'; + * import { useState } from '@wordpress/element'; + * + * const MyToggleControl = () => { + * const [ value, setValue ] = useState( false ); + * + * return ( + * <ToggleControl + * label="Fixed Background" + * checked={ value } + * onChange={ () => setValue( ( state ) => ! state ) } + * /> + * ); + * }; + * ``` + */ +export const ToggleControl = forwardRef( UnforwardedToggleControl ); + +export default ToggleControl; From b276a346369fc30dab61c25d3b8613b8c614ee57 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 30 Jul 2024 11:36:11 +1000 Subject: [PATCH 0144/1908] Group: Update block example (#63114) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: bgardner <bgardner@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- packages/block-library/src/group/index.js | 55 +++++++++--------- .../block-library/src/group/variations.js | 56 +++++++++++++++++++ 2 files changed, 82 insertions(+), 29 deletions(-) diff --git a/packages/block-library/src/group/index.js b/packages/block-library/src/group/index.js index 1ccfa4fa89c1aa..06ed4aa1001edf 100644 --- a/packages/block-library/src/group/index.js +++ b/packages/block-library/src/group/index.js @@ -22,56 +22,53 @@ export { metadata, name }; export const settings = { icon, example: { - innerBlocks: [ - { - name: 'core/paragraph', - attributes: { - customTextColor: '#cf2e2e', - fontSize: 'large', - content: __( 'One.' ), - }, + attributes: { + layout: { + type: 'constrained', + justifyContent: 'center', }, - { - name: 'core/paragraph', - attributes: { - customTextColor: '#ff6900', - fontSize: 'large', - content: __( 'Two.' ), + style: { + spacing: { + padding: { + top: '4em', + right: '3em', + bottom: '4em', + left: '3em', + }, }, }, + }, + innerBlocks: [ { - name: 'core/paragraph', + name: 'core/heading', attributes: { - customTextColor: '#fcb900', - fontSize: 'large', - content: __( 'Three.' ), + content: __( 'La Mancha' ), + textAlign: 'center', }, }, { name: 'core/paragraph', attributes: { - customTextColor: '#00d084', - fontSize: 'large', - content: __( 'Four.' ), + align: 'center', + content: __( + 'In a village of La Mancha, the name of which I have no desire to call to mind, there lived not long since one of those gentlemen that keep a lance in the lance-rack, an old buckler, a lean hack, and a greyhound for coursing.' + ), }, }, { - name: 'core/paragraph', + name: 'core/spacer', attributes: { - customTextColor: '#0693e3', - fontSize: 'large', - content: __( 'Five.' ), + height: '10px', }, }, { - name: 'core/paragraph', + name: 'core/button', attributes: { - customTextColor: '#9b51e0', - fontSize: 'large', - content: __( 'Six.' ), + text: __( 'Read more' ), }, }, ], + viewportWidth: 600, }, transforms, edit, diff --git a/packages/block-library/src/group/variations.js b/packages/block-library/src/group/variations.js index 8589b7f73fed43..5ded2c724bfa9b 100644 --- a/packages/block-library/src/group/variations.js +++ b/packages/block-library/src/group/variations.js @@ -4,6 +4,59 @@ import { __, _x } from '@wordpress/i18n'; import { group, row, stack, grid } from '@wordpress/icons'; +const example = { + innerBlocks: [ + { + name: 'core/paragraph', + attributes: { + customTextColor: '#cf2e2e', + fontSize: 'large', + content: __( 'One.' ), + }, + }, + { + name: 'core/paragraph', + attributes: { + customTextColor: '#ff6900', + fontSize: 'large', + content: __( 'Two.' ), + }, + }, + { + name: 'core/paragraph', + attributes: { + customTextColor: '#fcb900', + fontSize: 'large', + content: __( 'Three.' ), + }, + }, + { + name: 'core/paragraph', + attributes: { + customTextColor: '#00d084', + fontSize: 'large', + content: __( 'Four.' ), + }, + }, + { + name: 'core/paragraph', + attributes: { + customTextColor: '#0693e3', + fontSize: 'large', + content: __( 'Five.' ), + }, + }, + { + name: 'core/paragraph', + attributes: { + customTextColor: '#9b51e0', + fontSize: 'large', + content: __( 'Six.' ), + }, + }, + ], +}; + const variations = [ { name: 'group', @@ -30,6 +83,7 @@ const variations = [ ( ! blockAttributes.layout?.orientation || blockAttributes.layout?.orientation === 'horizontal' ), icon: row, + example, }, { name: 'group-stack', @@ -41,6 +95,7 @@ const variations = [ blockAttributes.layout?.type === 'flex' && blockAttributes.layout?.orientation === 'vertical', icon: stack, + example, }, { name: 'group-grid', @@ -51,6 +106,7 @@ const variations = [ isActive: ( blockAttributes ) => blockAttributes.layout?.type === 'grid', icon: grid, + example, }, ]; From dba69d0b8feb2e92fb852c781c05bfa20fb4f6fa Mon Sep 17 00:00:00 2001 From: Utsav Patel <75293077+up1512001@users.noreply.github.com> Date: Tue, 30 Jul 2024 08:46:06 +0530 Subject: [PATCH 0145/1908] Fix: accessibility issue of device preview options (#63958) * Fix: accessibility issue of menugroup * update: aria label when device type is selected * update: menuItem to MenuItemChoice * feature: added speak on device selection ---- Co-authored-by: up1512001 <up1512001@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: joedolson <joedolson@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> --- .../src/components/preview-dropdown/index.js | 83 ++++++++++++++----- 1 file changed, 64 insertions(+), 19 deletions(-) diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js index bc652ea4015c11..e8c48a739d29ba 100644 --- a/packages/editor/src/components/preview-dropdown/index.js +++ b/packages/editor/src/components/preview-dropdown/index.js @@ -6,11 +6,12 @@ import { DropdownMenu, MenuGroup, MenuItem, + MenuItemsChoice, VisuallyHidden, Icon, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { check, desktop, mobile, tablet, external } from '@wordpress/icons'; +import { desktop, mobile, tablet, external } from '@wordpress/icons'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { store as preferencesStore } from '@wordpress/preferences'; @@ -20,6 +21,7 @@ import { store as preferencesStore } from '@wordpress/preferences'; */ import { store as editorStore } from '../../store'; import PostPreviewButton from '../post-preview-button'; +import { speak } from '@wordpress/a11y'; export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { const { deviceType, homeUrl, isTemplate, isViewable, showIconLabels } = @@ -62,6 +64,61 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { desktop, }; + /** + * The choices for the device type. + * + * @type {Array} + */ + const choices = [ + { + value: 'Desktop', + label: __( 'Desktop' ), + icon: desktop, + }, + { + value: 'Tablet', + label: __( 'Tablet' ), + icon: tablet, + }, + { + value: 'Mobile', + label: __( 'Mobile' ), + icon: mobile, + }, + ]; + + /** + * The selected choice. + * + * @type {Object} + */ + let selectedChoice = choices.find( + ( choice ) => choice.value === deviceType + ); + + /** + * If no selected choice is found, default to the first + */ + if ( ! selectedChoice ) { + selectedChoice = choices[ 0 ]; + } + + /** + * Handles the selection of a device type. + * + * @param {string} value The device type. + */ + const onSelect = ( value ) => { + setDeviceType( value ); + if ( value === 'Desktop' ) { + speak( __( 'Desktop selected' ), 'assertive' ); + } else if ( value === 'Tablet' ) { + speak( __( 'Tablet selected' ), 'assertive' ); + } else { + speak( __( 'Mobile selected' ), 'assertive' ); + } + }; + return ( <DropdownMenu className="editor-preview-dropdown" @@ -75,24 +132,11 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { { ( { onClose } ) => ( <> <MenuGroup> - <MenuItem - onClick={ () => setDeviceType( 'Desktop' ) } - icon={ deviceType === 'Desktop' && check } - > - { __( 'Desktop' ) } - </MenuItem> - <MenuItem - onClick={ () => setDeviceType( 'Tablet' ) } - icon={ deviceType === 'Tablet' && check } - > - { __( 'Tablet' ) } - </MenuItem> - <MenuItem - onClick={ () => setDeviceType( 'Mobile' ) } - icon={ deviceType === 'Mobile' && check } - > - { __( 'Mobile' ) } - </MenuItem> + <MenuItemsChoice + choices={ choices } + value={ selectedChoice.value } + onSelect={ onSelect } + /> </MenuGroup> { isTemplate && ( <MenuGroup> @@ -118,6 +162,7 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { className="editor-preview-dropdown__button-external" role="menuitem" forceIsAutosaveable={ forceIsAutosaveable } + aria-label={ __( 'Preview in new tab' ) } textContent={ <> { __( 'Preview in new tab' ) } From e744018a96cc3ecd96772c1d951ffed93b801a3c Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Tue, 30 Jul 2024 10:08:30 +0530 Subject: [PATCH 0146/1908] Move gallery link controls to the block toolbar (#62762) * Move link dropdown to toolbar in gallery block * Update e2e test for gallery block's setting * Fix e2e test for gallery block images link setting * Fix unit test * Synced with trunk * Added ToolbarDropdownMenu component instead of DropdownMenu * remove remove extra padding around link icon * Remove unused components * Revert "Synced with trunk" This reverts commit 0c7a78b8569b436a73f1c8e43f2150a78f68601e. * Improve snackbar notices for gallery block link control select * Add constant for lightbox option in link control for gallery block * Update getHrefAndDestination function to handle Link control value change for lightbox option * Add lightbox option in link control of gallery block * Add info text for lightbox option in link control for gallery block * Set info text for lightbox option in single line * reverting expand of click option changes * add change to resolve conflict * fix: Avoid unsupported Gallery MenuGroup usage (#63953) The `MenuGroup` and `MenuItem` components are currently undefined for the native mobile editor. Therefore, we cannot render them in code shared between web and native without platform conditionals. Ideally, we add proper support for the native platform to avoid these conditionals, and their complexity and bundle size increase. * removing lightbox changes from edit component of gallery block * Removing unneccessory class * Update link control lable in gallery block * Update label in unit test * Update text in snapshot --------- Unlinked contributors: randomburner, RCNeil. Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: dcalhoun <dpcalhoun@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: madhusudhand <madhudollu@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> Co-authored-by: paaljoachim <paaljoachim@git.wordpress.org> Co-authored-by: luisherranz <luisherranz@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/block-library/src/gallery/edit.js | 88 ++++++++++++++++--- .../test/__snapshots__/index.native.js.snap | 2 +- .../src/gallery/test/index.native.js | 10 +-- 3 files changed, 81 insertions(+), 19 deletions(-) diff --git a/packages/block-library/src/gallery/edit.js b/packages/block-library/src/gallery/edit.js index e853e20f23319c..f2faa40110dd13 100644 --- a/packages/block-library/src/gallery/edit.js +++ b/packages/block-library/src/gallery/edit.js @@ -14,6 +14,9 @@ import { ToggleControl, RangeControl, Spinner, + MenuGroup, + MenuItem, + ToolbarDropdownMenu, withNotices, } from '@wordpress/components'; import { @@ -33,6 +36,12 @@ import { View } from '@wordpress/primitives'; import { createBlock } from '@wordpress/blocks'; import { createBlobURL } from '@wordpress/blob'; import { store as noticesStore } from '@wordpress/notices'; +import { + link as linkIcon, + customLink, + image as imageIcon, + linkOff, +} from '@wordpress/icons'; /** * Internal dependencies @@ -57,11 +66,23 @@ import GapStyles from './gap-styles'; const MAX_COLUMNS = 8; const linkOptions = [ - { value: LINK_DESTINATION_ATTACHMENT, label: __( 'Attachment Page' ) }, - { value: LINK_DESTINATION_MEDIA, label: __( 'Media File' ) }, { - value: LINK_DESTINATION_NONE, + icon: customLink, + label: __( 'Link images to attachment pages' ), + value: LINK_DESTINATION_ATTACHMENT, + noticeText: __( 'Attachment Pages' ), + }, + { + icon: imageIcon, + label: __( 'Link images to media files' ), + value: LINK_DESTINATION_MEDIA, + noticeText: __( 'Media Files' ), + }, + { + icon: linkOff, label: _x( 'None', 'Media item link option' ), + value: LINK_DESTINATION_NONE, + noticeText: __( 'None' ), }, ]; const ALLOWED_MEDIA_TYPES = [ 'image' ]; @@ -359,7 +380,7 @@ function GalleryEdit( props ) { sprintf( /* translators: %s: image size settings */ __( 'All gallery image links updated to: %s' ), - linkToText.label + linkToText.noticeText ), { id: 'gallery-attributes-linkTo', @@ -552,15 +573,17 @@ function GalleryEdit( props ) { size="__unstable-large" /> ) } - <SelectControl - __nextHasNoMarginBottom - label={ __( 'Link to' ) } - value={ linkTo } - onChange={ setLinkTo } - options={ linkOptions } - hideCancelButton - size="__unstable-large" - /> + { Platform.isNative ? ( + <SelectControl + __nextHasNoMarginBottom + label={ __( 'Link' ) } + value={ linkTo } + onChange={ setLinkTo } + options={ linkOptions } + hideCancelButton + size="__unstable-large" + /> + ) : null } <ToggleControl __nextHasNoMarginBottom label={ __( 'Crop images to fit' ) } @@ -594,6 +617,45 @@ function GalleryEdit( props ) { ) } </PanelBody> </InspectorControls> + { Platform.isWeb ? ( + <BlockControls group="block"> + <ToolbarDropdownMenu + icon={ linkIcon } + label={ __( 'Link' ) } + > + { ( { onClose } ) => ( + <MenuGroup> + { linkOptions.map( ( linkItem ) => { + const isOptionSelected = + linkTo === linkItem.value; + return ( + <MenuItem + key={ linkItem.value } + isSelected={ isOptionSelected } + className={ clsx( + 'components-dropdown-menu__menu-item', + { + 'is-active': + isOptionSelected, + } + ) } + iconPosition="left" + icon={ linkItem.icon } + onClick={ () => { + setLinkTo( linkItem.value ); + onClose(); + } } + role="menuitemradio" + > + { linkItem.label } + </MenuItem> + ); + } ) } + </MenuGroup> + ) } + </ToolbarDropdownMenu> + </BlockControls> + ) : null } { Platform.isWeb && ( <> { ! multiGallerySelection && ( diff --git a/packages/block-library/src/gallery/test/__snapshots__/index.native.js.snap b/packages/block-library/src/gallery/test/__snapshots__/index.native.js.snap index b79bd7c3877c7e..088a7d25282451 100644 --- a/packages/block-library/src/gallery/test/__snapshots__/index.native.js.snap +++ b/packages/block-library/src/gallery/test/__snapshots__/index.native.js.snap @@ -82,7 +82,7 @@ exports[`Gallery block inserts block 1`] = ` <!-- /wp:gallery -->" `; -exports[`Gallery block overrides "Link to" setting of gallery items 1`] = ` +exports[`Gallery block overrides "Link" setting of gallery items 1`] = ` "<!-- wp:gallery {"linkTo":"media"} --> <figure class="wp-block-gallery has-nested-images columns-default is-cropped"><!-- wp:image {"id":1,"linkDestination":"media"} --> <figure class="wp-block-image"><img src="file:///local-image-1.jpeg" alt="" class="wp-image-1"/></figure> diff --git a/packages/block-library/src/gallery/test/index.native.js b/packages/block-library/src/gallery/test/index.native.js index fd95053bea62c0..f294555e41f2c1 100644 --- a/packages/block-library/src/gallery/test/index.native.js +++ b/packages/block-library/src/gallery/test/index.native.js @@ -594,9 +594,9 @@ describe( 'Gallery block', () => { expect( getEditorHtml() ).toMatchSnapshot(); } ); - // Test case related to TC012 - Settings - Link to + // Test case related to TC012 - Settings - Link // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc012 - it( 'overrides "Link to" setting of gallery items', async () => { + it( 'overrides "Link" setting of gallery items', async () => { // Initialize with a gallery that contains two items, the latter includes "linkDestination" attribute const screen = await initializeWithGalleryBlock( { html: `<!-- wp:gallery {"linkTo":"none"} --> @@ -612,10 +612,10 @@ describe( 'Gallery block', () => { } ); const { getByText } = screen; - // Set "Link to" setting via Gallery block settings + // Set "Link" setting via Gallery block settings await openBlockSettings( screen ); - fireEvent.press( getByText( 'Link to' ) ); - fireEvent.press( getByText( 'Media File' ) ); + fireEvent.press( getByText( 'Link' ) ); + fireEvent.press( getByText( 'Link images to media files' ) ); expect( getEditorHtml() ).toMatchSnapshot(); } ); From 9186964684888b8385bdee11cb1c6dbcafedf8f2 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Tue, 30 Jul 2024 12:59:07 +0800 Subject: [PATCH 0147/1908] Remove unnecessary/incorrect `unlock` call in `setEditorMode` action (#64073) Co-authored-by: talldan <talldanwp@git.wordpress.org> --- packages/block-editor/src/store/actions.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index f7da8fa14b382a..3a209a1267e288 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -35,7 +35,6 @@ import { privateRemoveBlocks, } from './private-actions'; import { STORE_NAME } from './constants'; -import { unlock } from '../lock-unlock'; /** @typedef {import('../components/use-on-block-drop/types').WPDropOperation} WPDropOperation */ @@ -1674,9 +1673,9 @@ export const __unstableSetEditorMode = // When switching to zoom-out mode, we need to select the parent section if ( mode === 'zoom-out' ) { const firstSelectedClientId = select.getBlockSelectionStart(); - const { sectionRootClientId } = unlock( - registry.select( STORE_NAME ).getSettings() - ); + const { sectionRootClientId } = registry + .select( STORE_NAME ) + .getSettings(); if ( firstSelectedClientId ) { let sectionClientId; From a051fe7292b17659eb70b667330546b463dd0637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Juh=C3=A9=20Lluveras?= <contact@albertjuhe.com> Date: Tue, 30 Jul 2024 08:54:44 +0200 Subject: [PATCH 0148/1908] Fix typo in 'Verify Core Backport Changelog' job title (#64058) --- .github/workflows/check-backport-changelog.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-backport-changelog.yml b/.github/workflows/check-backport-changelog.yml index 606ca4c91683ce..366bad9fdbc247 100644 --- a/.github/workflows/check-backport-changelog.yml +++ b/.github/workflows/check-backport-changelog.yml @@ -1,4 +1,4 @@ -name: Verify Core Backport Changlog +name: Verify Core Backport Changelog on: pull_request: From dcd0bcd564ca27a1f243b3aa30df89f48309dacb Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:04:33 +0900 Subject: [PATCH 0149/1908] Grid Interactivity: Fix block mover layout and styles (#64021) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> --- .../src/components/block-mover/index.js | 6 +- .../src/components/grid/grid-item-movers.js | 90 ++++++++++--------- .../src/components/grid/style.scss | 70 ++++++++++++--- 3 files changed, 111 insertions(+), 55 deletions(-) diff --git a/packages/block-editor/src/components/block-mover/index.js b/packages/block-editor/src/components/block-mover/index.js index aaaf6c64b55953..3b7f25800095a5 100644 --- a/packages/block-editor/src/components/block-mover/index.js +++ b/packages/block-editor/src/components/block-mover/index.js @@ -69,7 +69,11 @@ function BlockMover( { [ clientIds ] ); - if ( ! canMove || ( isFirst && isLast && ! rootClientId ) ) { + if ( + ! canMove || + ( isFirst && isLast && ! rootClientId ) || + ( hideDragHandle && isManualGrid ) + ) { return null; } diff --git a/packages/block-editor/src/components/grid/grid-item-movers.js b/packages/block-editor/src/components/grid/grid-item-movers.js index adda11b7a45a62..fc9a3c5bf39955 100644 --- a/packages/block-editor/src/components/grid/grid-item-movers.js +++ b/packages/block-editor/src/components/grid/grid-item-movers.js @@ -55,28 +55,29 @@ export function GridItemMovers( { return ( <BlockControls group="parent"> <ToolbarGroup className="block-editor-grid-item-mover__move-button-container"> - <GridItemMover - className="is-left-button" - icon={ chevronLeft } - label={ __( 'Move left' ) } - description={ __( 'Move left' ) } - isDisabled={ columnStart <= 1 } - onClick={ () => { - onChange( { - columnStart: columnStart - 1, - } ); - __unstableMarkNextChangeAsNotPersistent(); - moveBlocksToPosition( - [ blockClientId ], - gridClientId, - gridClientId, - getNumberOfBlocksBeforeCell( - columnStart - 1, - rowStart - ) - ); - } } - /> + <div className="block-editor-grid-item-mover__move-horizontal-button-container is-left"> + <GridItemMover + icon={ chevronLeft } + label={ __( 'Move left' ) } + description={ __( 'Move left' ) } + isDisabled={ columnStart <= 1 } + onClick={ () => { + onChange( { + columnStart: columnStart - 1, + } ); + __unstableMarkNextChangeAsNotPersistent(); + moveBlocksToPosition( + [ blockClientId ], + gridClientId, + gridClientId, + getNumberOfBlocksBeforeCell( + columnStart - 1, + rowStart + ) + ); + } } + /> + </div> <div className="block-editor-grid-item-mover__move-vertical-button-container"> <GridItemMover className="is-up-button" @@ -123,28 +124,29 @@ export function GridItemMovers( { } } /> </div> - <GridItemMover - className="is-right-button" - icon={ chevronRight } - label={ __( 'Move right' ) } - description={ __( 'Move right' ) } - isDisabled={ columnCount && columnEnd >= columnCount } - onClick={ () => { - onChange( { - columnStart: columnStart + 1, - } ); - __unstableMarkNextChangeAsNotPersistent(); - moveBlocksToPosition( - [ blockClientId ], - gridClientId, - gridClientId, - getNumberOfBlocksBeforeCell( - columnStart + 1, - rowStart - ) - ); - } } - /> + <div className="block-editor-grid-item-mover__move-horizontal-button-container is-right"> + <GridItemMover + icon={ chevronRight } + label={ __( 'Move right' ) } + description={ __( 'Move right' ) } + isDisabled={ columnCount && columnEnd >= columnCount } + onClick={ () => { + onChange( { + columnStart: columnStart + 1, + } ); + __unstableMarkNextChangeAsNotPersistent(); + moveBlocksToPosition( + [ blockClientId ], + gridClientId, + gridClientId, + getNumberOfBlocksBeforeCell( + columnStart + 1, + rowStart + ) + ); + } } + /> + </div> </ToolbarGroup> </BlockControls> ); diff --git a/packages/block-editor/src/components/grid/style.scss b/packages/block-editor/src/components/grid/style.scss index 32f0cfc0c62dc2..6790d683ca7d03 100644 --- a/packages/block-editor/src/components/grid/style.scss +++ b/packages/block-editor/src/components/grid/style.scss @@ -105,7 +105,6 @@ .block-editor-grid-item-mover-button { width: $block-toolbar-height * 0.5; min-width: 0 !important; // overrides default button width. - overflow: hidden; padding-left: 0; padding-right: 0; @@ -155,7 +154,7 @@ justify-content: space-around; > .block-editor-grid-item-mover-button.block-editor-grid-item-mover-button { - height: $block-toolbar-height * 0.5 - $grid-unit-05; + height: $block-toolbar-height * 0.5 - $grid-unit-05 !important; // overrides toolbar button height. width: 100%; min-width: 0 !important; // overrides default button width. @@ -173,18 +172,53 @@ } } +.editor-collapsible-block-toolbar { + .block-editor-grid-item-mover__move-vertical-button-container { + // Move up a little to prevent the toolbar shift when focus is on the vertical movers. + @include break-small() { + height: $grid-unit-50; + position: relative; + top: -5px; // Should be -4px, but that causes scrolling when focus lands on the movers, in a 60px header. + } + } +} + .show-icon-labels { - .block-editor-grid-item-mover-button.block-editor-grid-item-mover-button.is-left-button { - border-right: 1px solid $gray-700; - padding-right: 12px; - } + .block-editor-grid-item-mover__move-horizontal-button-container { + position: relative; - .block-editor-grid-item-mover-button.block-editor-grid-item-mover-button.is-right-button { - border-left: 1px solid $gray-700; - padding-left: 12px; - } + &::before { + @include break-small() { + content: ""; + height: 100%; + width: $border-width; + background: $gray-200; + position: absolute; + top: 0; + } + + @include break-medium() { + background: $gray-900; + } + } + + &.is-left { + padding-right: 6px; + &::before { + right: 0; + } + } + + &.is-right { + padding-left: 6px; + + &::before { + left: 0; + } + } + } .block-editor-grid-item-mover__move-vertical-button-container { &::before { @@ -208,5 +242,21 @@ } } + .block-editor-grid-item-mover-button { + white-space: nowrap; + } + + .editor-collapsible-block-toolbar { + .block-editor-grid-item-mover__move-horizontal-button-container::before { + height: $grid-unit-30; + background: $gray-300; + top: $grid-unit-05; + } + + .block-editor-grid-item-mover__move-vertical-button-container::before { + background: $gray-300; + width: calc(100% - #{$grid-unit-30}); + } + } } From 08fbdab666e9d6d29edf808755617b84e0a85bfd Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:07:37 +0900 Subject: [PATCH 0150/1908] Format Library: Polish inline image format popover (#64016) * Polish inline image format popover * Change button size to 40px Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/format-library/src/image/index.js | 6 +++--- packages/format-library/src/image/style.scss | 13 +++---------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/packages/format-library/src/image/index.js b/packages/format-library/src/image/index.js index 627e1e966b655c..794af776c88e76 100644 --- a/packages/format-library/src/image/index.js +++ b/packages/format-library/src/image/index.js @@ -76,19 +76,19 @@ function InlineUI( { value, onChange, activeObjectAttributes, contentRef } ) { event.preventDefault(); } } > - <HStack alignment="bottom" spacing="0"> + <HStack alignment="bottom"> <NumberControl - className="block-editor-format-toolbar__image-container-value" label={ __( 'Width' ) } value={ width } min={ 1 } onChange={ ( newWidth ) => setWidth( newWidth ) } + size="__unstable-large" /> <Button - className="block-editor-format-toolbar__image-container-button" icon={ keyboardReturn } label={ __( 'Apply' ) } type="submit" + __next40pxDefaultSize /> </HStack> </form> diff --git a/packages/format-library/src/image/style.scss b/packages/format-library/src/image/style.scss index 639d1ccc5961e2..7e9809e52f3bf2 100644 --- a/packages/format-library/src/image/style.scss +++ b/packages/format-library/src/image/style.scss @@ -1,15 +1,8 @@ .block-editor-format-toolbar__image-popover { z-index: z-index(".block-editor-format-toolbar__image-popover"); - .block-editor-format-toolbar__image-container-value { - margin: $grid-unit-10 - $border-width; - min-width: 150px; - max-width: 500px; - } - - .block-editor-format-toolbar__image-container-button { - height: $grid-unit-10 * 4 - ($border-width * 2); - margin-bottom: $grid-unit-10; - margin-right: $grid-unit-10; + .block-editor-format-toolbar__image-container-content { + width: 200px; + padding: $grid-unit-20; } } From 5807c04922e211852a9c7d1e03035861fc6b801b Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Tue, 30 Jul 2024 10:20:38 +0200 Subject: [PATCH 0151/1908] Add stylelint rule to prevent usage of flex-direction reverse values (#63081) * Add Stylelint rule to prevent usage of flex-direction *-reverse values. * Add Stylelint disable comments for valid cases or cases that should be refactored later. * Remove row-reverse from experimental checkbox form input. * Add disable comment for the hooked blocks toggles. * Remove leftovers. * Fix typo. * Use regex. * Revert changes to `form-input/*` * Revert changes to `form-input/edit.js` * Update .stylelintrc.json Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com> --------- Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: aristath <aristath@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .stylelintrc.json | 10 +++++++++- packages/block-editor/src/hooks/block-hooks.scss | 1 + .../src/hooks/use-editor-wrapper-styles.native.scss | 1 + packages/block-library/src/form-input/style.scss | 1 + .../block-library/src/media-text/style.native.scss | 2 ++ 5 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.stylelintrc.json b/.stylelintrc.json index df01978222e632..663befa2e4ce06 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -4,6 +4,14 @@ "at-rule-empty-line-before": null, "at-rule-no-unknown": null, "comment-empty-line-before": null, + "declaration-property-value-allowed-list": [ + { + "flex-direction": "/^(?!(row|column)-reverse).*$/" + }, + { + "message": "Avoid the flex-direction reverse values. For accessibility reasons, visual, reading, and DOM order must match. Only use the reverse values when they do not affect reading order, meaning, and interaction." + } + ], "declaration-property-value-disallowed-list": [ { "/.*/": [ "/--wp-components-color-/" ] @@ -18,7 +26,7 @@ "property-disallowed-list": [ [ "order" ], { - "message": "Avoid the order property. For accessibility reasons, visual, reading, and DOM order must match. Only use the order property when it does not affect reading order, meaning, and interaction" + "message": "Avoid the order property. For accessibility reasons, visual, reading, and DOM order must match. Only use the order property when it does not affect reading order, meaning, and interaction." } ], "rule-empty-line-before": null, diff --git a/packages/block-editor/src/hooks/block-hooks.scss b/packages/block-editor/src/hooks/block-hooks.scss index 4d871233de482b..c8f2027483ccf3 100644 --- a/packages/block-editor/src/hooks/block-hooks.scss +++ b/packages/block-editor/src/hooks/block-hooks.scss @@ -4,6 +4,7 @@ * we need to right-align the toggle. */ .components-toggle-control .components-h-stack { + /* stylelint-disable-next-line declaration-property-value-allowed-list -- This should be refactored to not use the row-reverse value. */ flex-direction: row-reverse; } diff --git a/packages/block-editor/src/hooks/use-editor-wrapper-styles.native.scss b/packages/block-editor/src/hooks/use-editor-wrapper-styles.native.scss index c980253ee64251..2ae4ed8b86144c 100644 --- a/packages/block-editor/src/hooks/use-editor-wrapper-styles.native.scss +++ b/packages/block-editor/src/hooks/use-editor-wrapper-styles.native.scss @@ -5,6 +5,7 @@ } .use-editor-wrapper-styles--reversed { + /* stylelint-disable-next-line declaration-property-value-allowed-list -- This should be refactored to not use the column-reverse value. */ flex-direction: column-reverse; width: 100%; max-width: 580; diff --git a/packages/block-library/src/form-input/style.scss b/packages/block-library/src/form-input/style.scss index d45fc8d7f1f729..f9e1753cf0a7b7 100644 --- a/packages/block-library/src/form-input/style.scss +++ b/packages/block-library/src/form-input/style.scss @@ -24,6 +24,7 @@ */ &:has(input[type="checkbox"]) { width: fit-content; + /* stylelint-disable-next-line declaration-property-value-allowed-list -- This should be refactored to not use the row-reverse value. */ flex-direction: row-reverse; } } diff --git a/packages/block-library/src/media-text/style.native.scss b/packages/block-library/src/media-text/style.native.scss index 07b584059203ed..4c0f80a5008a8d 100644 --- a/packages/block-library/src/media-text/style.native.scss +++ b/packages/block-library/src/media-text/style.native.scss @@ -7,6 +7,7 @@ $media-to-text: 12px; } .has-media-on-the-right { + /* stylelint-disable-next-line declaration-property-value-allowed-list -- This should be refactored to not use the row-reverse value. */ flex-direction: row-reverse; } @@ -14,6 +15,7 @@ $media-to-text: 12px; flex-direction: column; &.has-media-on-the-right { + /* stylelint-disable-next-line declaration-property-value-allowed-list -- This should be refactored to not use the column-reverse value. */ flex-direction: column-reverse; } } From 0b546103e52a4e2f8b720b9504c8dbd3a670ce3b Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Tue, 30 Jul 2024 10:43:32 +0200 Subject: [PATCH 0152/1908] Fix: WampServer links. (#64062) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: shail-mehta <shailu25@git.wordpress.org> --- .../code/getting-started-with-code-contribution.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contributors/code/getting-started-with-code-contribution.md b/docs/contributors/code/getting-started-with-code-contribution.md index 921c8ad6ddc3e7..df6b305f35983e 100644 --- a/docs/contributors/code/getting-started-with-code-contribution.md +++ b/docs/contributors/code/getting-started-with-code-contribution.md @@ -16,7 +16,7 @@ We recommend using the [Node Version Manager](https://github.com/nvm-sh/nvm) (nv We recommend using the [wp-env package](/packages/env/README.md) for setting WordPress environment locally. You'll need to install Docker to use `wp-env`. See the [Development Environment tutorial for additional details](/docs/getting-started/devenv/README.md). > Note: To install Docker on Windows 10 Home Edition, follow the [install instructions from Docker for Windows with WSL2](https://docs.docker.com/docker-for-windows/wsl/). -As an alternative to Docker setup, you can use [Local](https://localwp.com/), [WampServer](http://www.wampserver.com/en/), or [MAMP](https://www.mamp.info/), or even use a remote server. +As an alternative to Docker setup, you can use [Local](https://localwp.com/), [WampServer](https://wampserver.aviatechno.net/), or [MAMP](https://www.mamp.info/), or even use a remote server. - GitHub CLI Although not a requirement, the [GitHub CLI](https://cli.github.com/) can be very useful in helping you checkout pull requests locally. Both from the Gutenberg repo and forked repos. This can be a major time saver while code reviewing and testing pull requests. @@ -134,7 +134,7 @@ If you run into an issue, check the [troubleshooting section in `wp-env` documen ### Using Local or MAMP -As an alternative to Docker and `wp-env`, you can also use [Local](https://localwp.com/), [WampServer](http://www.wampserver.com/en/), or [MAMP](https://www.mamp.info/) to run a local WordPress environment. To do so clone and install Gutenberg as a regular plugin in your installation by creating a symlink or copying the directory to the proper `wp-content/plugins` directory. +As an alternative to Docker and `wp-env`, you can also use [Local](https://localwp.com/), [WampServer](https://wampserver.aviatechno.net/), or [MAMP](https://www.mamp.info/) to run a local WordPress environment. To do so clone and install Gutenberg as a regular plugin in your installation by creating a symlink or copying the directory to the proper `wp-content/plugins` directory. You will also need some extra configuration to be able to run the e2e tests. From 55ddb6f93fd0281d916901a410760f5f630470c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 30 Jul 2024 10:50:25 +0200 Subject: [PATCH 0153/1908] Posts with publish status show the published date not the modified one (#64049) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../src/components/post-fields/index.js | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 52030fc70f54b7..ebd228dcf63aa0 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -292,19 +292,13 @@ function usePostFields( viewType ) { ); } - // Pending & Published posts show the modified date if it's newer. - const dateToDisplay = - getDate( item.modified ) > getDate( item.date ) - ? item.modified - : item.date; - - const isPending = item.status === 'pending'; - if ( isPending ) { + const isPublished = item.status === 'publish'; + if ( isPublished ) { return createInterpolateElement( sprintf( - /* translators: %s: the newest of created or modified date for the page */ - __( '<span>Modified: <time>%s</time></span>' ), - getFormattedDate( dateToDisplay ) + /* translators: %s: page creation time */ + __( '<span>Published: <time>%s</time></span>' ), + getFormattedDate( item.date ) ), { span: <span />, @@ -313,12 +307,18 @@ function usePostFields( viewType ) { ); } - const isPublished = item.status === 'publish'; - if ( isPublished ) { + // Pending posts show the modified date if it's newer. + const dateToDisplay = + getDate( item.modified ) > getDate( item.date ) + ? item.modified + : item.date; + + const isPending = item.status === 'pending'; + if ( isPending ) { return createInterpolateElement( sprintf( /* translators: %s: the newest of created or modified date for the page */ - __( '<span>Published: <time>%s</time></span>' ), + __( '<span>Modified: <time>%s</time></span>' ), getFormattedDate( dateToDisplay ) ), { From ad9708d505032ebd52f5859ce0ab15d593edcb5b Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Tue, 30 Jul 2024 14:59:25 +0530 Subject: [PATCH 0154/1908] Post Excerpt: Add border block support (#64022) * Add border support to post excerpt block * add box sizing style to excerpt block Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/block-library/src/post-excerpt/block.json | 12 ++++++++++++ packages/block-library/src/post-excerpt/style.scss | 3 +++ 2 files changed, 15 insertions(+) diff --git a/packages/block-library/src/post-excerpt/block.json b/packages/block-library/src/post-excerpt/block.json index 9809d10ab426b4..61888ced43e67d 100644 --- a/packages/block-library/src/post-excerpt/block.json +++ b/packages/block-library/src/post-excerpt/block.json @@ -56,6 +56,18 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } }, "editorStyle": "wp-block-post-excerpt-editor", diff --git a/packages/block-library/src/post-excerpt/style.scss b/packages/block-library/src/post-excerpt/style.scss index 1562bca962c1c9..b44108f67b5dd5 100644 --- a/packages/block-library/src/post-excerpt/style.scss +++ b/packages/block-library/src/post-excerpt/style.scss @@ -1,5 +1,8 @@ // Lowest specificity on wrapper margins to avoid overriding layout styles. :where(.wp-block-post-excerpt) { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; + margin-top: var(--wp--style--block-gap); margin-bottom: var(--wp--style--block-gap); } From d5af45e13e24d9c09bb7efdc89b4d8ce96f58cbb Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Tue, 30 Jul 2024 15:12:15 +0530 Subject: [PATCH 0155/1908] Site Tagline: Add border block support (#63778) * Add border support to site tagline block * Add box sizing style to site tagline block * Display border control as optional * Simplify the style for block Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/block-library/src/site-tagline/block.json | 9 ++++++++- packages/block-library/src/site-tagline/style.scss | 4 ++++ packages/block-library/src/style.scss | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 packages/block-library/src/site-tagline/style.scss diff --git a/packages/block-library/src/site-tagline/block.json b/packages/block-library/src/site-tagline/block.json index c2061726d62a94..25b3840cd663a0 100644 --- a/packages/block-library/src/site-tagline/block.json +++ b/packages/block-library/src/site-tagline/block.json @@ -56,7 +56,14 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true } }, - "editorStyle": "wp-block-site-tagline-editor" + "editorStyle": "wp-block-site-tagline-editor", + "style": "wp-block-site-tagline" } diff --git a/packages/block-library/src/site-tagline/style.scss b/packages/block-library/src/site-tagline/style.scss new file mode 100644 index 00000000000000..a22eeebb6e2777 --- /dev/null +++ b/packages/block-library/src/site-tagline/style.scss @@ -0,0 +1,4 @@ +.wp-block-site-tagline { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; +} diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index 5e33980badd76c..c14699b4576103 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -47,6 +47,7 @@ @import "./search/style.scss"; @import "./separator/style.scss"; @import "./site-logo/style.scss"; +@import "./site-tagline/style.scss"; @import "./site-title/style.scss"; @import "./social-links/style.scss"; @import "./spacer/style.scss"; From c2c8ceff8e7b6837e752184daefdb6da40bbcac9 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Tue, 30 Jul 2024 15:13:14 +0530 Subject: [PATCH 0156/1908] Time To Read: Add border block support (#63776) * Add border support to time to read block * Display border control as optional Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/block-library/src/post-time-to-read/block.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/block-library/src/post-time-to-read/block.json b/packages/block-library/src/post-time-to-read/block.json index d19c6e553046c8..ce0ab2be6c02f3 100644 --- a/packages/block-library/src/post-time-to-read/block.json +++ b/packages/block-library/src/post-time-to-read/block.json @@ -45,6 +45,12 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true } } } From 5f4c9c853b15092ed885d5280edefb973c37d9e9 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Tue, 30 Jul 2024 15:14:24 +0530 Subject: [PATCH 0157/1908] Site Title: Add border block support (#63631) * Add border support to site title block * Add box sizing style to site title block * Display border control as optional * Simplify the style for block * Restore specificity on inner link rule --------- Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- packages/block-library/src/site-title/block.json | 6 ++++++ packages/block-library/src/site-title/style.scss | 9 +++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/site-title/block.json b/packages/block-library/src/site-title/block.json index 518b458184e941..95d8deb1e43b9d 100644 --- a/packages/block-library/src/site-title/block.json +++ b/packages/block-library/src/site-title/block.json @@ -62,6 +62,12 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true } }, "editorStyle": "wp-block-site-title-editor", diff --git a/packages/block-library/src/site-title/style.scss b/packages/block-library/src/site-title/style.scss index 337c82f79ad354..f292326cc3259f 100644 --- a/packages/block-library/src/site-title/style.scss +++ b/packages/block-library/src/site-title/style.scss @@ -1,3 +1,8 @@ -:root :where(.wp-block-site-title a) { - color: inherit; +.wp-block-site-title { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; + + :where(a) { + color: inherit; + } } From 5e5897cbf05b07aa4bd5e82307e608c1adfe3591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Zi=C4=99ba?= <wojciech.zieba@protonmail.com> Date: Tue, 30 Jul 2024 11:53:29 +0200 Subject: [PATCH 0158/1908] Bump Gradle wrapper to 8.9 (#64042) * Bump Gradle wrapper to 8.9 in `react-native-bridge` * Bump Gradle wrapper to 8.9 in `react-native-aztec` * Bump Gradle wrapper to 8.8 in `react-native-editor` It's to 8.8 and not to 8.9 as some React Native dependencies are not yet compatible with Gradle 8.9 Script compilation errors: Line 10: import org.gradle.configurationcache.extensions.serviceOf ^ Unresolved reference: serviceOf Line 54: serviceOf<ModuleRegistry>() ^ Unresolved reference: serviceOf Co-authored-by: wzieba <wzieba@git.wordpress.org> --- .../android/gradle/wrapper/gradle-wrapper.jar | Bin 63375 -> 43504 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 ++- packages/react-native-aztec/android/gradlew | 22 +++++++++++------- .../react-native-aztec/android/gradlew.bat | 22 ++++++++++-------- .../android/gradle/wrapper/gradle-wrapper.jar | Bin 63375 -> 43504 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 ++- packages/react-native-bridge/android/gradlew | 22 +++++++++++------- .../react-native-bridge/android/gradlew.bat | 22 ++++++++++-------- .../gradle/wrapper/gradle-wrapper.properties | 3 ++- packages/react-native-editor/android/gradlew | 5 ++-- .../react-native-editor/android/gradlew.bat | 2 +- 11 files changed, 59 insertions(+), 45 deletions(-) diff --git a/packages/react-native-aztec/android/gradle/wrapper/gradle-wrapper.jar b/packages/react-native-aztec/android/gradle/wrapper/gradle-wrapper.jar index 033e24c4cdf41af1ab109bc7f253b2b887023340..2c3521197d7c4586c843d1d3e9090525f1898cde 100644 GIT binary patch literal 43504 zcma&N1CXTcmMvW9vTb(Rwr$&4wr$(C?dmSu>@vG-+vuvg^_??!{yS%8zW-#zn-LkA z5&1^$^{lnmUON?}LBF8_K|(?T0Ra(xUH{($5eN!MR#ZihR#HxkUPe+_R8Cn`RRs(P z_^*#_XlXmGv7!4;*Y%p4nw?{bNp@UZHv1?Um8r6)Fei3p@ClJn0ECfg1hkeuUU@Or zDaPa;U3fE=3L}DooL;8f;P0ipPt0Z~9P0)lbStMS)ag54=uL9ia-Lm3nh|@(Y?B`; zx_#arJIpXH!U{fbCbI^17}6Ri*H<>OLR%c|^mh8+)*h~K8Z<V--Q23O4&HBVn~<)q zmUaP7+TjluBM%#s1Ki#^GurGElkc7{cc6Skz+1nDVk%wAAQYx1^*wA%KSY>!9)DPf zR2h?lbDZQ`p9P;&DQ4F0sur@TMa!Y}S8irn(%d-gi0*WxxCSk*A?3lGh=gcYN?FGl z7D=Js!i~0=u3rox^e<cs4tSN~YA?c-d185$YFNA$Eq1&U{wh#b^OveuKoBPy0oYZ4 zAY2?B=x8yX9}pVM=cLrvugywt!e@Y3lH)i?7fvT*a`O;c)CJQ>O3i@$0=n{K1lPNU zwmfjRVmLOCRfe=seV&P*1Iq=^i`502keY8Uy-WNPwVNNtJFx?IwA<BCEY82WDKJP< zB^CxjFxi=mg*OyI?K3GoDfk;?-K<Z#JoxhYNeEUf896)l%7gL``44}zn)7|Rf;)SC z_EfJr4I+3i(GiHN`R+vHqf}1wXtH?65<wKlxV1BU(#3XgtH<$Fir3S(7QeRA3)u89 zID&66K{&mq$DsB}s&o?H60{cskfh*hvn8hQW#~Q!qM04QtZvx3JEpqeKWE6|+OZW= z(LB7}flr|t7va%>yR<KG!FYzS$bs7qXcpM&wV@~>PZo2<wCq%CszVO$mosTTuv*Mz zOLoi?e^7B~xS22~QW8Rmnt{(AtL<HGi<_P9`0pH;3)@S9Eg`gt2X<om7C^q}pKX|* zTy3X{nOr-xyt4=Qx1IjrzGb!_SyAv^SZcf;air&-;Ua+)5k0z=#R7@UW%)3oEjGA| zZ#DE3px@h1k7w%|4rVIO=0Aid2A%?nBZrupg^_z5J-$$YKeDZ&q8+k7zccb<dc4D; zz}+UYkl_eUNL3PW+reZ6UUB}=sHp~$z%Q}gZ-#ow+ffQIj|A3`B9LO*6%t@)0PV!x ziJ=9fw_>Wo1+S(xF37LJZ~%i)kpFQ3Fw=mXfd@>%+)RpYQLnr}B~~zoof(JVm^^&f zxKV^+3D3$A1G;qh4gPVjhrC8e(VYUHv#dy^)(RoUFM?o%W-EHxufuWf(l*@-l+7vt z=l`qmR56K~F|v<^Pd*p~1_y^P0P^aPC##d8+HqX4IR1gu+7w#~TBFphJxF)T$2WEa zxa?H&6=Qe7d(#tha?_1uQys2KtHQ{)Qco)qwGjrdNL7thd^G5i8Os)CHqc>iOidS} z%nFEDdm=GXBw=yXe1W-ShHHFb?Cc70+$W~z_+}nAoHFYI1MV1wZegw*0y^tC*s%3h zhD3tN8b=Gv&rj}!SUM6|ajSPp*58KR7MPpI{oAJCtY~JECm)*m_x>AZEu>DFgUcby z1Qaw8lU4jZpQ_$;*7RME+gq1Ky<fW-rh4ehZ;%u960Gt5OF)<y$00S=6tVE=%Pt~( z!&BP&2I%`@>SGG#Wql>aL~k9tLrSO()LWn*q&YxHE<sT^`N@Q|)S3y<ZACaLXO56z zncP$~M5K!npWqz?)C50MMw=XqFtDO!3JHI*t-^8Ga&lGPHX2F0pIGdZ3w5ewE+{kf z-&Ygi?@-h(ADD|ljIBw%VHHf1xuQ~}IeIQ5JqlA4#*Nlvd`IfDYzFa?PB=RCcFpZ4 z|HFmPZM=;^DQ_z<IPz$$+yG(H4803QQAA7vQF7;_gv|AD1bH*R-CP3f<<utDpH)Ht zI@{uO12adp{;132YoKPx?C9{&;MtHdHb*0F0;Z~D42}#*l+WD2u?r>uzmwd1?aAtI zBJ>P=&$=l1efe1CDU;`Fd+_;&wI07?V0aAIgc(<VS*?#8Zt!w88FJrjasA1!6>!{a z0Jg6Y=inXc3^n!U0Atk`iCFIQooHqcWhO(qrieUOW8X(x?(RD}iYDLMjSwffH2~tB z)oDgNBLB^AJBM1M^c5HdRx6fBfka`(LD-qrlh5jqH~);#nw|iyp)()xVYak3;Ybik z0j`(+69aK*B>)e_p%=wu8XC&9e{AO4c~O1U`5X9}?0mrd*m$_EUek{R?DNSh(=br# z#Q61gBzEpmy`$pA<eVn3dnmk^xq`=o2)~2c0ywsuTQsC?1WZZehsJYfK@LQ>*6!87 zSDD+=@fTY7<4A?GLqpA?Pb2z$pbCc4B4zL{BeZ?F-8`s$?>*lXXtn*NC61>|*w7J* z$?!iB{6R-0=KFmyp1nnEmLsA-H0a6l+1uaH^g%c(p{iT&YFrbQ$&PRb8Up#X3@Zsk zD^^&LK~111%cqlP%!_gFNa^dTYT?rhkGl}5=fL{a`UViaXWI$k-UcHJwmaH1s=S$4 z%4)PdWJX;hh5UoK?6aWoyLxX&NhNRqKam7tcOkLh{%j3K^4Mgx1@i|Pi&}<^5>hs5 zm8?uOS>%)NzT(%PjVPGa?X%`N2TQCKbeH2l;cTnHiHppPSJ<7y-yEIiC!P*ikl&!B z%+?>VttCOQM@ShFguHVjxX^?mHX^hSaO_;pnyh^v9EumqSZTi+#f&_Vaija0Q-e*| z7ulQj6Fs*bbmsWp{`auM04gGwsYYdNNZcg|ph0OgD>7O}Asn7^<IivRZw`Wa$`V6) zgX@^QL9j}-Od{q5<J*k0+1U=R5+PCYj(U}4VpX+BjfI~+dttS?HJ6uZSGH#H-twTo zaptG40+PAc$fs*zLFkOfGfc+xGs<T?rLGIA%SU7c%jh!E1SNN~*-`ccW8wo4gv2Sj zhify^C(ygi)uGwqXDLqVbH>Z=eI>`$2*v78;sj-}oMoEj&@)9+ycEOo92xSyY344^ z11Hb8^kdOvbf^GNAK++bYioknrpdN>+u8R?JxG=!2Kd9r=YWCOJYXYuM0cOq^FhEd zBg2puKy__7VT3-r*dG4c62Wgxi52EMCQ`bKgf*#*ou(D4-ZN$+m<X+=`m<r!lO%3T zMp}MJd(WDoQ2&6(LClZxpv<vZPPM3Ngkye2VhB=i|B12g5ouw(%`gbWtRq8~sU|o* z$kQ8Jb~6&{ak;r$7@?#t*q9RfAOj=^uAf1z5Y8`N%M`oM@?!~VqN{g%-u$XR1u1Im zGE&AzFpIcER(5jtCPR%RZ)!+|*rU~jZBiOKdqYjO(%yK3Lz;{##(@QEVo>g&7$u!! z-^<eVk1WtrWdvAzoBMHoB$s2RXJCv}%muyVFFJ``?>+Z%;-3IDwqZ|K=ah85OLwkO zKxNBh+4QHh)u9D?MFtpbl)<T1$eOrb4-+U|WDC2BesgFRlgt`klbeQ^1S`7`r+uZ8 zH&U=geA}Si;CUcKvBA&^@<o1GQ7`{1Y(cCHZv|73JIJOvVwLOMZP%Q|)y@^j2e<+z zWVo=#FL!4XNKS~-_1`gw*qi$0j6P7ym_LTvG>us}9+V!D%w9jfAMYEb>%$A;u)rrI zuBudh;5PN}_6J_}l55P3l_)&RMlH{m!)ai-i$g)&*M`eN$XQMw{v^r@-125^RRCF0 z^2>|DxhQw(mtNEI2Kj(;<s2pnue6O@?^QaAp;Ze6z9nX*w}4h7342+0lU$@;Knnve zqqY2Ci=`)@>KblC7x=JlK$@78`O~>V!`|1Lm-^JR$-5pUANAnb(5}B}JGjBsliK4& zk6y(;$e&h)lh2)L=bvZKbvh@>vLlreBdH8No2>$#%_Wp1U0N7Ank!6$dFSi#xzh|( zRi{U<eziQYNZ-=4ReK3@^LFvNQI~(Pdvp+X@J@g#bd~m0wFc+sW3Xf5tyA3xKp;T3 zy14<o-`F}$ET-DQ;B;yNy?d>w%-4W!{IXZ)fWx@XX6;&(m_F%c6~X8hx=BN1&q}*( zoaNjWabE{oUPb!Bt$eyd#$5j9rItB-h*5JiNi(v^e|XKAj*8(k<5-2$&ZBR5fF|JA z9&m4fbzNQnAU}r8ab>fFV%J0z5awe#UZ|bz?Ur)U9bCIKWEzi2%A+5CLqh?}K4JHi z4vtM;+u<SJ)DEVF_yZnTw01M`(s#^BNx+c|MQ6ogb50Jjul0L;!#OmrYCs)iE)7(t z?%I~O!zVNt#Bf3#O2WXsGz!B}&s@MfyDeaoqqf=GELN3g$+DA`&&GKy(`Ya~A@6vK zn|WZ-+tB`DH^+SjI&K3KekF%-QIP%R{F)inWc~@cEO-=3Or<lm9g9}|`|ky#v{5*; zKA5d<ecC{<o9p<U4UUK$m|+q#@(>PsVz{Lfr;78W78gC;z*yTch~4YkLr&m-7%-xc ztw6Mh2<b07B|^BQBjvq{FXx?kyJ);`+G*=&9PMD`1uf<{+pNnnsIQx~kaB?*5<-7a zqY)GyF_w$>d>_iO<o;tRi5=dcnU&wcur@4T5Z=-$xFUEsp-yX${|jSF|HMDPq3?MS zw;p9zjR`yYJOfJZsK~C-S=JQ?nX{z_y@06JFIpheAo-rOG|5&Gxv)%95gpu@ESfi| z7Auc&hjVL;&81Pc#L`^d9gJb`wEtLVH8q|h{>*$Rd8(-Cr1_V8EO1f*^@wRoSozS) zy1UoC@pruAaC8Z_7~_w4Q6n*&B0AjOmMWa;s<dwKr_&w<X$Z*rmLmKUI3S>Iav&gu z|J5&|{=a@vR!~k-OjKEgPFCzcJ>#A1uL&7xTDn;{X<DkOU(-L87#5hf4{m?aj!I6- zPEt$K07IXK8mI0TYf-jhke2QjQw3v?qN5h0-#Fel0)Krq1f)#^AFsfd|K$I={`Xs9 z{JIr8M>BdeM}V=l3B8fE1--DHjSaxoSjNKEM9|U9#m2<eS=8Og#NOG$&X&%|8sOyg zpZ6&%KPd&uh?v{hRMVvQjUL}gY3)Mk3{XQXF{><3>n{Iuo`r3UZp;>GkT2YBNAh|b z^jTq-hJp(ebZh#Lk8hVBP%qXwv-@vbvoREX$TqRGTgEi$%_F9tZES@z8Bx}$#5eeG zk^UsLBH{bc2VBW)*EdS({yw=?qmevwi?BL6*=12k9zM5gJv1>y#ML4!)iiPzVaH9% zgSImetD@dam~e>{LvVh!phhzpW+iFvWpGT#CVE5TQ40n%F|p(sP5mXxna+Ev7PDwA zamaV4m*^~*xV+&p;W749xhb_X=$|LD;FHuB&JL5?*Y2-oIT(wYY2;73<^#46S~Gx| z^cez%V7x$81}UWqS13Gz80379Rj;6~WdiXWOSsdmzY39L;Hg3MH43o*y8ib<ko|2T z<o~B%-$Y4Q9z_t97c`{g0veSfFt63Osbpe2Osn@<=nrAVk_JfMGt&lMGw9leshc#5 z*hkn0u>NBBH`(av4|u;YPq%{R;IuYow<+GEsf@R?=@tT@!}?#>zIIn0CoyV!hq3mw zHj>OOjfJM3F{RG#6ujzo?y32m^tgSXf@v=J$ELdJ+=5j|=F-~hP$G&}tDZsZE?5rX ztGj`!S>)CFmdkccxM9eGIcGnS2AfK#gXwj%esuIBNJQP1WV~b~+D7PJTmWGTSDrR` zEAu4B8l>NPuhsk5a`rReSya2nfV<T&F{)-N{)9$`9a!^D!-03RDN<TPH!aW46TC4L z>1EK01+G!x8aBdTs3Io$u5!6n6KX%uv@DxAp3F@{4UYg4SWJtQ-W~0MDb|j-$lwVn znAm*Pl!?Ps&3wO=R115RWKb*JKoexo*)uhhHBncEDMSVa_PyA>k{Zm2(wMQ(5NM3# z)jkza|GoWEQo4^s*wE(gHz?Xsg4`}HUAcs42cM1-qq_=+=!Gk^y710j=66(cSWqUe zklbm8+zB_<cF$~mH3zum`PN7rn^cr1XvcjzxFO{ms_482AyMFYi+#o7!*vecrNhft z48z<2q#fIw=ce!MXuptfT4+M8FP&|QfB3H@2)dceSR<*e5@hq<#7<$5tC^!RO8Zi< zd_Wl!>syQv5A2rj!Vbw8;|$@C!vfNmNV!yJ<MblqN@23-5g1<aeoul%Um5K((_QY} ze%_@BuNzay69}2PhmC<;m}2=FevDzrp!V!u4u|#h@B=rfKt+v!U`0k7>IWDQ>{+2x zKjuFX`~~HKG~^6h5FntRpnnHt=D&rq0>IJ9#F0eM)Y-)GpRjiN7gkA8wvnG#K=q{q z9dBn8_~wm4J<3J_vl|9H{7q6u2A!cW{bp#r*-f{gOV^e=8S{nc1DxMHFwuM$;aVI^ zz6A*}m8N-&x8;aunp1w7_vtB*pa+OYBw=TMc6Q<xVqo{NJ3h9-a)s5XuYMqZ=Y{7{ z$O63J`)FM-y*mko#!-UBa!3~eYtX1hjRQY2jMxAx=q5uKNm#uaKIak>K=mbA-|Cf* zvyh8D4LRJImooUaSb7t*fVfih<97Gf@VE0|z>NcBwBQze);Rh!k3K_sfunToZY;f2 z^HmC4KjHRVg+eKYj;PRN^|E0>Gj_zagfRbrki68I^#~6-HaHg3BUW%<xsJq4AotN+ zH6twFV=)FlAbs*F6vGws^==x5Tl0AIbcP{&2yxB=)*u+bvK^L6$Vp}U2{9nj{bK~d zee7tC)@DR<dI`D%cA(%7M9Ui3a)^iG?m=oJO0E^``<|5il2sf1fZHvy=D@e0<I)<l zI!|d{`X3u}lz2(4Vn>+clM1<yhZZgPANro5CwhUb>xQEdPYt_g<2K+z!$>*$9nQ>; zf9Bei{?zY^-e{q_*|W#2rJG`2fy@{%6u0i_VEWTq$*(ZN37|8lFFFt)nCG({r!q#9 z5VK_kkS<W$zJN%xs9<lngf<utn=i|I;bCdr-Lr<EzK)tkE-pYh-fc0wqKz?&U8TTN zh_eAdl<>J3?zOH)OezMT{!YkCuSSn!<oaxO4?NS?VufjhPn>K#-Rhl$uUM(bq*jY? zi1xbMVthJ`E>d>(f3)~fozjg^@eheMF6<)I`oeJYx4*+M&%c9VArn(OM-wp%M<-`x z7sLP1&3^%Nld9Dhm@$3f2}87!quhI<BVn6Upp<cc;cU|)&2W%nk!Ak8tXK8aT!m*5 z^9zmeeS|PCG$hgM&Uh}0wp+#$jK3YCwOT&nx$??=a@_oQemQ~hS6nx6fB5r~bFSPp z`alXuTYys4S5dCK)KDGR@7`I-JV^ewQ_BGM^o>@nwd@3~fZl_3LYW-B?Ia>ui`ELg z&Qfe!7<FViITCBP{rA>m6ze=mZ<W0bN&bq-0D3>`Ia9$z|ARSw|IdMpooY4YiPN8K z4B(ts3p%<w%rbophph+BzYj>2i(Td=<hfIaF6Ll8+9!48Ti=xpXB{FgJbk;>tgEHX z0UQ_>URBtG+-?0E;E7Ld^dyZ;jjw0}XZ(}-QzC6+NN=40oDb2^v!L1g9xRvE#@IBR zO!b-2N7wVfLV;mhEaXQ9XAU+>=XVA6f&T4Z-@AX!leJ8obP^P^wP0aICND?~w&N<u ztispy>ykJ#54x3_@r7IDMdRNy4Hh;h*!u(Ol(#0bJdwEo$5437-UBjQ+j=Ic>Q2z` zJNDf0yO6@mr6y1#n3)s(W|$iE_i8r@Gd@!DWD<Q)gT}bxTg_YpJQ5s|m8}+B)KBN6 zYnlzh>qZ7J&~gAm1#~maIGJ<sH@F<m!Fuh_fvrMbcDJNJ5~Yg;LF}NFN}&Y&LL76S zv)~8W2?_rx`P;4LB-=JqsI{I~4U8DnSSIHWU2rHf%vWsA2-d=78An8z4q|lvgQ2iB zhUUI!H+|C+_qp(Tjzu5usOu}cEoivZK&XA==sh0cD|Eg7eERXx?KwHI=}A9S_rx8S zd)VLh_s!Juqi^!0xv7jH)UdSkEY~N|;QMWvs;HN`dMsdK=Dw2mtAHHcK8_+kS%a_V zGgeQoaMM>1sls^gxL9LLG_Nh<XXk<>U!pTGty!TbhzQnu)I*S^54U6Yu%ZeCg`R>Q zhBv$n5j<?~h)Y%y=zErI?{tl!(JWSDXxco7X8WI-6K;9Z-h&~kIv?$!6<k(g(xee? z53>0v%O_j{QYWG!R9W?5_b&67KB$t}&e2LdMvd(PxN6Ir!H4>PNlerpBL>Zvyy!yw z-SOo8caEpDt(}|gKPBd$qND5#a5nju^O>V&;f890?yEOfkSG^HQVmEbM3Ugzu+UtH zC(INPDdraBN?P%kE;*Ae%Wto&sgw(crfZ#Qy(<4nk;S|hD3j{IQRI6Yq|f^basLY; z-HB&Je%Gg}Jt@={_C{L$!RM;$$|<j7k-g{75e!h)4SlFvEZ*AkqrJI;EWu$Zx+OwM zm{5Yk>iD6vu#3w?v?*;&()uB|I-XqEKqZPS!reW9JkLewLb!70T7n`i!gNtb1%vN- zySZj{8-1>6E%H&=V}LM#xmt`J3XQoaD|@XygXjdZ1+P77-=;=eYpoEQ01B@L*a(uW zrZeZz?HJsw_4g0vhUgkg@VF8<-X$B8pOqCuWAl28uB|@r`19DTUQQsb^pfqB6QtiT z*`_UZ`fT}vtUY#%sq2{rchyfu*pCg;uec2$-$N_xgjZcoumE5vSI{+s@iLWoz^Mf; zuI8kDP{!XY6OP~q5}%1&L}CtfH^N<3o4L@J@zg1-mt{9L`s^z$Vgb|mr{@WiwAqKg zp#t-lhrU>F8o0s1q_9y`gQNf~Vb!F%70f}$>i7o4ho<sjDlFD=G`r<7$U?bJN+x5S z@0&tQ=-XO1uDq(HCa$X)-l<u1!s<!W`30F78UcZaZKc8)G0af1Dsh%OOWh5)q+Q+n zySBnE+3;9^#)U#Gq);&Cu=mtjNpsS~S0yjE@m4{Kq525G&cO_+b-_B$LeXWt_@XTq z`)(;=^RDS@oh5dPjKyGAP?-Dbh507E5zZ=D2_C*6s^HXiA)B3f=65_M+rC&rMIUP6 zi4@u>$`uciNf=xgJ>&!gSt0g;M>*x4-`U)ysFW&Vs^Vk6m%?iuWU+o&m(2Jm26<Ea z?or_^bK_`R)hBTfrBqA3Y^o7$K~Nzo)sh-vT%yWcc1I5wF1nkvk%!X_Vl_MK1IHC= zt}Dt+sOmg0sH-?}kqNB|M_}ZXui7H;?;?xCCSIPSHh8@h^K8WU5X(!3W|>Y(3%TL; zA7T)BP{WS!&xmxNw%J=$MPfn(9*^*TV;$JwRy8Zl*yUZi8jWYF>==j~&S|Xinsb%c z2?B+kpet*muEW7@AzjBA^wAJBY8i|#C{WtO_or&Nj2{=6JTTX05}|H>N2B|Wf!*3_ z7hW*j6p3TvpghEc6-wufFiY!%-GvOx*bZrhZu+7?iSrZL5q9}igiF^*R3%DE4aCHZ zqu>xS8LkW+Auv%z-<1Xs92u23R$nk@Pk}MU5!gT|c7vGlEA%G^2th&Q*zfg%-D^=f z&J_}jskj|Q;73NP4<UD^T*M!yxMr=U!@&!rJfydk7CE7PGb<{)^=nM9Le#FQ=GkV~ z)_A$YPAn35??iNa@`g-wBX><4k*Y%pXPU2Thoqr+5uH1yEYM|VtBPW6lXaetokD0u z9qVek6Q&wk)tFbQ8(^HGf3Wp16gKmr>G;#G(HRBx?F`9AIRboK+;OfHaLJ(P>IP0w zyTbTkx_THEOs%Q&aPrxbZrJlio+hCC_HK<4%f3ZoSAyG7Dn`=X=&h@m*|UYO-4Hq0 z-Bq&+Ie!S##4A6OGoC~>ZW`Y5J)*ouaFl_e9GA*VSL!O_@xGiBw!AF}1{tB)z(w%c zS1Hmrb9OC8>0a_$BzeiN?rkPLc9%&;1CZW*4}CDDNr2gcl_3z+WC15&H1Zc2{o~i) z)LLW=WQ{?ricmC`G1GfJ0Yp4Dy~Ba;j6ZV4r{8xRs`13{dD!xXmr^Aga|C=iSmor% z8hi|pTXH)5Yf&v~exp3o+sY4B^^b*eYkkCYl*T{*=-0HniSA_1F53eCb{x~1k3*`W zr~};p1A`k{1DV9=UPnLDgz{aJH=-LQo<5%+Em!DNN252xwIf*wF_zS^!(XSm(9eoj z=*dXG&n0>)_)N5<wxn0{TP0tnD=JAzVUcIUoR85Xt>oc6v!>-bd(2ragD8O=M|wGW z!xJQS<)u70m&6OmrF0WSsr@I%T*c#Qo#Ha4d3COcX+9}hM5!7JIGF>7<~C(Ear^Sn zm^ZFkV6~Ula6+8S?oOROOA6$C&q&dp`>oR-2Ym3(HT@O7Sd5c~+kjrmM)YmgPH*tL zX+znN>`tv;5eOfX?h{AuX^LK~V#gPCu=)Tigtq9&?7Xh$qN|%A$?V*v=&-2F$zTUv z`C#WyIrChS5|Kgm_GeudCFf;)!WH7FI60j^0o#65o6`w*S7R@)88n$1nrgU(oU0M9 zx+EuMkC>(4j1;m6N<sS-ys^qbJhGY7%0ZoC7dK=j7bGdau`J`{>oGqEkpJYJ?vc|B zOlwT3<tNmX!mXZdsEW2s2`|?DC8;N?2tT*Lfq)F*|4vf>t&UgL!pX_P*6g36`ZXQ; z9~Cv}ANFnJGp(;ZhS(@FT;3e)0)Kp;h^x;$*xZn*k0U6-&Fw<BqOnDKEdld8!Qk{Z zjI1+R_ciEqL3CLOv$+J~YVpzIy`S&V{koIi$Lj}ZFEMN=!rL1?_EjSryIV+OBiiJ- zIqT$oSMA>I=uOGaODdrsp-!K$Ac32^c{+FhI-HkYd5v=`PGsg%6I`4d9Jy)uW0y%) zm&j^9WBAp*P8#kGJUhB!L?a%h$hJgQrx!6KCB_TRo%9{t0J7KW8!o1B!NC)VGLM5! zpZy5Jc{`r{1e(jd%jsG7k%I+m#C<kI0i<ajCqQC!(pKlSsMl7M2N^mP%W`BGKb?hm zBK`pddcg5+WhE#$46+K<Z!1CW-hZdo7hAw13ZUVqwW*}&ujL=eh{m~phuOy=JiBMN z7FaCUn6boJ!M=6PtLN6%cveGkd12|1B{)kEYGTx#IiMN&re0`}NP-_{E-#FxOo3*P zkAXSt{et292KfgGN`AR|C`p{MRpxF-I?+`ZY1Vsv>GS*BPA65ZVW~fLYw0dA-H_}O zrkGFL&P1PG9p2(%Qi<evvBkNEkQkM%A>EWm6x;U-U&I#;Em$nx-_I^wtgw3xUPVVu zqSuKnx&dIT-XT+T10p;yjo1Y)z(x1fb8Dzfn8e yu?e%!_ptzGB|8GrCfu%p?(_ zQccdaaVK$5bz;*rnyK{_SQYM>;aES6Qs^lj9lEs6_J+%nIiuQC*fN;z8md>r_~Mfl zU%p5Dt_YT>gQqfr@`cR!$NWr~+`CZb%dn;WtzrAOI>P_JtsB76<bUr7Lsb65vEd}g z5JhMCmn#UeH#6Cew?bxogM)$x5ed{E)%2nWY5rb@Clvh$(JzQ#!CsQ(2I4QnhDDJ^ zYL%2bf8?`y)Ro=x{(dw<4^)(H^z7~3nfYFh-r7yBBb=l3V8dE-Dr&a%qs<OYcajo2 z(4Nw|k5_OQ@6zHmcIK%waj!yoZT(S1YlEFN?8-_lp9nf>PYe*<%H(y>qx-`Kq!X_; z<{RpAqYhE=L1r*M<cT6p|4(5fVa-WIh|@AphR|cJ1`?N>)gNF3B8r(<%8mo*SR2hu zccLRZwGARt)H<F*kMvg%oJV~29ud_q>lo1euqTyM>^!HK*!Q2P;4UYry<i)yWXzKa zM^_qppY~vnIrhL_!;Z9msXMZTTwR{e`yH5t=HdD1Pni7?LqOpLoX}u5n5RfkGBvQ1 z@cdMeR4T6rp^S~>sje@;(<|$&%vQekbn|0Ruu_Io(w4#%p6ld2Yp7tlA`Y$cciThP zKzNGIMPXX%&Ud0uQh!uQZz|FB`4KGD?3!ND?wQt6!n*f4EmCoJUh&b?;B{|lxs#F- z31~HQ`SF4x$&v00@(P+j1pAaj5!s`)b2RDBp*PB=2IB>oBF!*6vwr7Dp%zpAx*dPr zb@Zjq^XjN?O4QcZ*O+8>)|HlrR>oD*?WQl5ri3R#2?*W6iJ>>kH%KnnME&TT<gNU{ zn$Veg044#l=Z-&wsmEZhnw7IwT7Cd}hiZ%ke)-GzAR-Dt6)8Cb6>@Z<Y-SEE^OC5H z=$M0HjdWR5p?n;s9OTXrEa1eGt}G;Eu)ifSop!$z#6V<>zrHS$Q%LC?n|e>V+D+8D zYc4)QddFz7I8#}y#Wj6>4P%34dZH<AWj}HgE@5&D9Ra@o(Km_Gm}5Zb61p%9mDz1% zya$Vd!_U~pDN*Y5%lo}-K~}4&F)rTjJ7uGyV@~kB-XNrIGRiB=UrNxJtX;JHb(EyQ z{!R%v{vC7m|L3bx6lCRb7!mP~Is!r!q&OXpE5nKnH3@l({o}PrL`o>~OUDb?uP%-E zwjXM(?Sg~1!|wI(RVu<h{6ESg9k500(D<HXwz52OGq(JEKS2CJR}8N&E-#%vhhaRN zL#Q6%yUcel+!a#~g&e7w4$3s62d$Dv;SxCxhT}>xbu)-rH+O=igSho_pDCw(c6b=P zKk4ATlB?bj9+HHlh<_!&z0rx13K3ZrAR8W)!@Y}o`?a*JJsD+twZIv`W)@Y?Amu_u zz``@-e2X}27$i(2=9rvIu5uTUOVhzwu%mNazS|lZb&PT;XE2|B&W1>=B58#*!~D&) zfVmJGg8UdP*fx(>Cj^?yS^zH#o-$Q-*$SnK(ZVFkw+er=>N^7!)FtP3y~Xxnu^nzY zikgB>Nj0%;WOltWIob|}%lo?_C7<``a5hEkx&1ku$|)i>Rh6@3h*`slY=9U}(Ql_< zaNG*J8vb&@zpdhAvv`?{=zDedJ23TD&Zg__snRAH4eh~^oawdYi6A3w8<<tS1{)`* zH!u#2_lf&B)x2)tE$?4|aMAYUFZ{|Se7->Ozh@Kw)<E~4fKYaJ{OS+>#bdktM^GVb zrG08?0bG?|NG+w^&JvD*7LAbjED{_Zkc`3H!My>0u5Q}m!+6VokMLXxl`Mkd=g&Xx z-a>m*#G3SLlhbKB!)tnzfWOBV;u;ftU}S!NdD5+YtOjLg?X}dl>7m^gOpihrf1;PY zvll&>dIuUGs{Q<Ww4SS<E23Sm*si$^C!!snD|AFym<+q$`*o0wokE?J{^g?f3>nd- zwIR3oIrct8Va^Tm0t#(bJD7c$Z7DO9*7NnRZorrSm`b`cxz>OI<bVZt$VQ!oMxCu0 zbb7D5OIXV5Ynn@Y6)HLT=1`a=nh7{ee{vr<=$>C;jSE3DO8`hX955ui`s%||YQtt2 z5DNA&pG-V+4oI2s*x^>-$6J?p=I>C|9wZF8z;VjR??Icg?1w2v5Me+FgAeGGa8(3S z4vg*$>zC-WIVZtJ7}o9{D-7d>zCe|z#<9>CFve-OPAYsneTb^JH!Enaza#j}^mXy1 z+ULn^10<XTm*l1Jg2Z;UvGEN!6Wq%I@OP4p{k`RNRKlKFWPt_of11^Gr%_Mg*mVP3 zm?)&3I719~aYcs)TY&q^$zmQ=xoC++VJH@~YG6>+rWLF6j2>Ya@@Kq?26>AqK{A_| zQKb*~F1>sE*=d?A?W7N2j?L09_7n+H<SF8|SM#pTc9|9|rf1w*m4Y0Vdj643qA#D| z!hJzb_-}IrrhkWr{zk_YC%(c-)UJl6Ma!mcbvj&~#yN-UhH?ZQ3TPq4hTVQ$(?eJ6 zNfJ_K+VJDBXN=l!7{2}lq?-$`fq|e&PEONfZDU<_SM+s2_3$vT_yqV<R&KG=K{zS} zKQF$?mYsg%vV|E_E=a*SL!`7*AeN6GMVDXC59yPgi$F2!7&8e}EyHVLwCm{i%<pN! zdc`SbZK}JQj7?6K&|261iHrsnVjdhxu_l_NKs&yy#;#^%8?Jlg`wcTlNZ3urUtEYd zsFE!K0}Eg39)z+J6mLW)#Kn<ok4*6AAE=n*vh*;TpgGnnM|npykFpO|a0`4#SjP^b z2<JG#Qk^#3FeFS`0eooK9|wEmCcvRKI*~6mamFTd^UW9Eg4!J4N9qz*C$3a#F;Sad zi#o9LaqNG5TsiT<`SDtY^`)zkYx$(C5;&K9#(Zj}HolT_st~#C`VS8q%#q1)HN+hT zz9IjVUdZNIp@;b88oR`~DvQL_zmsBy>Gi{VY;MoTGr_)G9)ot$p!-UY5zZ2Xtbm=t z@dpPSGw<TLTZo~Zyx(+AKWvR~{L4S^5I;5+QT9bcQ-4cC{QnLfRBf&Pov~kv@`W6V zA|h{EGx|7msvR1t`a-jF$JZ>gH=QtIcEulQNI>S-#ifbnO5EWkI;$A|pxJd885oM+ zGZ0_0gDvG8q2xebj+fbCHYfAXuZStH2j~|d^sBAzo46(K8n59+T6rzBwK)^rfPT+B zyIFw)9YC-V^rhtK`!3jrhmW-sTmM+tPH+;nwjL#-SjQPUZ53L@A>y*rt(#M(qsiB2 zx6B)dI}6Wlsw%bJ8h|(lhkJVogQZA&n<jl%@&gd%^X|lsDQwDHEiKLCz}r`kC^h0t z(!vYS%C)Ku?w$ti5R##9jSkNC#5)Juc{8XfEhczdGQy8yNrZL6+d0~%V=N|iF{V)E zLT(gH!$j8Mf(1>{?Vgs6gNSXzuZpEyu*xySy8ro07QZ7Vk1!3tJphN_5V7qOiyK8p z#@jcDD8nmtYi1^l8ml;AF<#IPK?!pqf9D4moYk>d99Im}Jtwj6c#+A;f)CQ*f-hZ< z=p_T86jog%!p)D&5g9taSwYi&e<jP@@Q_fbXtVO&n9{e#)jg+D#~q=hoZ<9PIa)>P z#JuEK%+NULWus;0w32-SYFku#i}d~+{Pkho&^{;RxzP&0!RCm3-9K6`>KZpnzS6?L z^H^V*s!8<>x8bomvD%rh>Zp3>Db%kyin;qtl+jAv8Oo~1g~mqGAC&Qi_wy|xEt2iz zWAJEfTV%cl2Cs<1L&DLRVVH05EDq`pH7Oh7sR<WSzBWU(MxAIA&4v~INVdLKA><BK zwCgTxJU0mM{;1UV<^ZRk0SQNNN(;SRZsH7^EDWVUu%^mFfvW{m5jOQuQWSy`f586I zTj}Z4e5WsvkNmBd`TJdfe=^>`NNkL%wi}8n>IXcO40hp+J+sC!W?!krJf!GJNE8uj zg-y~Ns-<~D?yqbzVRB}G>0A^f0!^N7l=$m0OdZuqA<e9rzV|ixGyk9uS=Vov2_ECA z^Sd0M$B)O&tv@%@UmTb%ngcl58ED9TyFp$y4JjFU+g+9EWUl?am<e#4uCGy9Tmt)z z2Y|kWUahugFHsF<J6o!<?X(Ncsy&Wg9<QLPD}g-`PWGHWDY5P6;<Y+5J1vz2Z|PSy zBN?Q^NkxnWq>OQq<EC8_d&#T2smn`YINd-HF@)Op)pBRHnx+Q|Hsv_BpWAPsT1>Lc zX?AEGr1Ht+inZ-Qiwnl@Z0qukd__a!C*CKuGdy5#nD7VUBM^6OCpxCa2A(X;e0&V4 zM&WR8+wErQ7UIc6LY~Q9x%Sn*Tn>>P`^t&idaOEnOd(Ufw#>NoR^1QdhJ8s`h^|R_ zXX`c5*O~Xdvh%q;7L!_!ohf$NfEBmCde|#uVZvEo>OfEq%+Ns7&_f$OR9xsihRpBb z+cjk8LyDm@U{YN>+r46?nn{7Gh(;WhFw6GAxtcKD+YWV?uge>;+q#Xx4!GpRkVZYu zzsF}1)7$?%s9g9CH=Zs+B%M_)+~*j3L0&Q9u7!|+T`^O{xE6qvAP?XWv9_MrZKdo& z%IyU)$Q95AB4!#hT!_dA>4e@zjOBD*Y=XjtMm)V|+IXzjuM;(l+8aA5#Kaz_$rR6! zj>#&^DidYD$nUY(D$mH`9eb|dtV0b{S>H6FBfq>t5`;OxA4Nn{J(+XihF(stSch<f zIn>e7$es&~N$epi&PDM_N`As;*9D^L==2Q7Z2zD+CiU(|+-kL*VG+&9!Yb3LgPy?A zm<g7T4Wx!m(zMlVE_2jX$1$$5DcfL6>7Z&^qRG_JIxK7-FBzZI3Q<;{`DIxtc48k> zc|0dmX;Z=W$+)qE)~`yn6MdoJ4co;%!`ddy+FV538Y)j(vg}5*k(WK)KWZ3WaOG!8 z!syGn=s{H$odtpqFrT#JGM*utN7B((abXnpDM6w56nhw}OY}0TiTG1#f*VFZr+^-g zbP10`$LPq_;PvrA1XXlyx2uM^mrjTzX}w{yuLo-cOClE8MMk47T25G8M!9Z5ypOSV zAJUBGEg5L2fY)ZGJb^E34R2z<C?_X1)4xsl9%Z|w&L9k!F(V>J?}Vf>{~gB!8=5Z) z9y$>5c)=;o0HeHHSuE4U)#vG&KF|I%-cF6f$~pdYJWk_dD}iOA>iA$O$+4%@>JU08 zS`ep)$XLPJ+n0_i@PkF#ri6T8?ZeAot$6JIYHm&P6EB=BiaNY|aA$W0I+nz*zkz_z zkEru!tj!QUffq%)8y0y`T&`fuus-1p>=^hnBiBqD^hXrPs`PY9tU3m0np~rISY09> z`P3s=-kt_cYcxWd{de@}TwSqg<T-v~${38)1dqT{JCO5}Gk$$yZP*X!5)RaGFqqkZ zeHhqUgXb37$91~LS-3Zi29CKKki0sBTh7unqEK$%FG?oo$Sp>*xVhp;E9zCsnXo6z z?f&Sv^U7n4`xr=mXle94HzOdN!2kB~4=%)u&N!+2;z6UYKUDqi-s6AZ!haB;@&B`? z_TRX0%@suz^TRdCb?!vNJYPY8L_}&07uySH9%W^Tc&1pia6y1q#?*Drf}GjGbPjBS zbOPcUY#*$3sL2x4v_i*Y=N7E<UbOmi3K%)5<dOJui+{^+b*shA_w8&X4_Icv*!}kT zW@BG{C%f{(K^kE?tjU`Led*kAj6wB_3f*UyIEV0T9TyMo4`NS;oA7Ec+71eFa;K|G zCyaKKi1bvX9fTLQ+uAgF*@ZR8fB%|JlT8A-jK$7FMyxW>$mR}J%|GUI(>WEr+28+V z%v5{#e!UF*6~G&%;l*q*$V?&r$Pp^sE^i-0$+RH3ERUUdQ0>rAq2(2QAbG}$y{de( z>{qD~GGuO<V3ijl7+~xmS#nUvH{qF0*%7G(r|}BSXsu}HwrFbXWzcYJouIY*34axA z(n@XsPrv%6;|GSbkH9Og>k559Y@%$?N^1ApVL_a704>8OD%8Y%8B;FCt%AoPu8*D1 zLB5X>b}Syz81pn;xnB}%0FnwazlWfUV<Vu@5P52pgIa+J{M)H4nAC<>)Z-~rZg6~b z6!9J$EcE&sEbzcy?CI~=boWA&eeIa%z(7SE^qgVLz??1Vbc1*aRvc%Mri)AJaAG!p z$X!_9Ds;Zz)f+;%s&d<S0a>RcJt2==P{^j3bf0M=nJd&xwUGlUFn?H=2W(*2I2Gdu zv!gYCwM10aeus)`RIZSrCK=&oKaO_Ry~D1B5!y0R=%!i2*KfXGYX&gNv_u+n9wiR5 z*e$Zjju&ODRW3phN925%S(jL+bCHv6rZtc?!*`1<n2%>TyYXT6%Ju=|X;6D@lq$8T zW{Y|e39ioPez(pBH%k)HzFITXHvnD6hw^lIoUMA;qAJ^CU?top1fo@s7xT13Fvn1H z6JWa-6+FJF#x>~+A;D~;VDs2<i>6>^oH0EI`IYT2iagy23?nyJ==i{g4%HrAf1-*v zK1)~@&(KkwR7TL}L(A@C_S0G;-GMDy=MJn2$FP5s<%wC)4jC5PXoxrQBFZ_k0P<n- z??iM<JF!BTjD>{{s@<jPT1+pTPdk3<izB+}jAtjokIz)aPR$L&4%}45Et}?jz0w{( zC4G}+Nu0D*w=ay`v91hMo+V&V8q(a!`~K-2<yR0H)sK+mcY?TAaSS8F<Q+!pSc;`* z*c@5)+ZpT%-!K3O=Z0(hI8LH7KqK>sz+gX`-!=T8rcB(=7vW}^K6oLWMmp(rwDh}b zwaGGd>yEy6fHv%jM$yJXo5oMAQ>c9j`**}F?MCry;T@47@r?&sKHgVe$MCqk#Z_3S z1GZI~nOEN*P~+UaFGnj{{Jo@16`(qVNtbU>O0Hf57-P>x8Jikp=`s8xWs^dAJ9lCQ z)GFm+=OV%AMVqVATtN@|vp61VVAHRn87}%PC^RAzJ%JngmZTasWBAWsoAqBU+8L8u z4A&Pe?fmTm0?mK-BL9t+{y7o(7jm+RpOhL9Kn<D3v{}Wpv2i&ghEZe;t&DmOA_QYc zM+NIUU}=*bkxOJsLKV3e^oGG8rufTpa8R~7Iki1y+fC(UT;;{l19@qfxO@0^!xMA? z#|<YBZ6;vAb>Y#E&qu^}B6=K_dB}*VlSEiC9fn)+V=J;OnN)Ta5v66ic1rG+dGAJ1 z1%Zb_+!$=tQ~lxQrzv3x#CPb?CekEkA}0MYSgx$Jdd}q8+R=ma$|&1a#)TQ=l$1tQ z=tL9&_^vJ)Pk}EDO-va`UCT1m#Uty1{v^A3P~83_#v^ozH}6*9mIjIr;t3Uv%@VeW zGL6(CwCUp)Jq%G0bIG%?{_*Y#5IHf*5M@wPo6A{$Um++Co$wLC=J1aoG93&T7Ho}P z=mGEPP7Gb<mBTnJH7dKM2CB)0*o-AW2E4i5R+rHU%4A2BTVwOqj4zmJqsb|5^*{DT zv^HFARK6@^_1|vU{>voG!uD$k(H3A$Z))+i{Hy?QHdk>3xSBXR0j!11O^mEe9RH<y zF3MI;^J1vHI9U>mw!pvzv?Ua~2_l2Yh~_!s1qS`|0~0)<BWX>YsbHSz8!mG)WiJE| z2<APmuYD%tKwB@0u<C~CKyaC}XX{?mylzkDSuLMkAoj?zp*zFF7q515SrGD~s}ATn z`Ded41yk>f($6TQtt6L_f~ApQYQKSb=`053LgrQq7G@98#igV>y#i==-nEjQ!XNu9 z<h*hnP2Pol+z>~;mE+gtj4IDDNQJ~JVk5Ux6&LCSFL!y=>79kE9=V}J7tD==Ga+IW zX)r7>VZ9dY=V&}DR))xUoV!u(Z|%3ciQi_2jl}3=$Agc<a_3#EUXJj<z2jVv6VHGT zV^v1FiRwA!kPmt}m$qdr&9#-6{QeZqtM3|tRl$sws3Gy`no`Kj@X-)O(^sv>(`RPb z8kEBpvY>1FGQ9W$n>Cq=DIpski};nE)`p3IUw1Oz0|wxll^)4dq3;CCY@RyJgFgc# zKouFh!`?Xuo{IMz^xi-h=StCis_M7y<P{h0$_I#EukRYag9%BMRXh|%Xl7C<>q$u) z?XHvw*HP0VgR+KR6wI)jEMX|ssqYvSf*_3W8zVTQzD?3>H!#>InzpSO)@SC8q*ii- z%%h}_#0{4JG;Jm`4zg};BPTGkYamx$Xo#O~lBirRY)q=5M45n{GCfV<Kqrcu9<z@R zSE>7h9qwyu1NxOMoP4)jjZMxmT|IQQh0U7C$EbnMN<3)Kk?fFHYq$d|ICu>KbY_hO zTZM+uKHe(cIZfEqyzyYSUBZa8;Fcut-GN!HSA9ius`lt<SmSV9vasBl&hE7ciOunD z?%e1Hl-5B3e+<+8CD{j5U*D3h89nV<zn^0g+t=uRKgZiGu)3h;vu#^y`HqWe_=jGm zW2p}*n<!QH%pQ2EV`&z|LD#BOpj0QS9R5#$q}3&-+@GL4F^wO-bcSo|J^I_{LATPF z2$`fUCOO=XxYVD!<7Yz4te$d-_>NebF46ZX_BbZNU}}ZOm{M2&nAN<H$fJIKS=j8q zwXlN!l^_4>L9@0qvih15(|`S~z}m&h!u4x~(%MAO$jHRWNfuxWF#B)E&g3ghSQ9|> z(MFaLQj)NE0lowyjvg8z0#m6FIuKE9lDO~Glg}nSb7`~^&#(Lw{}GVOS>U)m8bF}x zVjbXljBm<v)#bs=9p`s>34Cs-yM6TVusr+3kYFjr28STT3g056y3cH5Tmge~ASxBj z%|yb>$eF;WgrcOZf569sDZOVwoo%8>XO>XQOX1OyN9I-SQgrm;U;+#3OI(zrWyow3 zk==|{<m8xZ#>lt2xrQ%FIXOTejR>;wv(Pb8u8}BUpx?yd(Abh<shPyABw|Ens8m6@ zIg($GO4)<g4x5icbki?U&2%56@tYd`zRs}Nk6R~4!AjVAihB3r8oDhQ8f)v^r}|(y z4B&Q<ARRqYXKQGAeJa_KHe`)04jUO~B=%q#SUlU@pU?apz0v{Al@s`Cvzo)u;2>6? zsoO3VYWkeLnF43&@*#MQ9-i-d0t*xN-UEyNKeyNMHw|A(k(_6QKO=nKMCxD(W(Yop zsRQ)QeL4X3Lxp^L%wzi2-WVSsf61dqliPUM7srDB?Wm6Lzn0&{*}|IsKQW;02(Y&| zaTKv|`U(pSzuvR6Rduu$wzK_W-Y-7>7s?G$)U}&uK;<>vU}^^ns@Z!p+9?St1s)dG zK%y6xkPyyS1$~&6v{kl?Md6gwM|>mt6Upm>oa8RLD^8T{0?HC!Z>;(Bob7el(DV6x zi`I)$&E&ngwFS@bi4^xFLAn`=fzTC;aimE^!cMI2n@Vo%Ae-ne`RF((&5y6xsjjAZ zVguVoQ?Z9uk$2ON;ersE%PU*xGO@T*;j1BO5#TuZKEf(mB7|g7pcEA=nYJ{s3vlbg zd4-DUlD{*6o%Gc^N!Nptgay>j6E5;3psI+C3Q!1ZIbeCubW%w4pq9)MSDyB{HLm|k zxv-{$$A*pS@csolri$Ge<4VZ}e~78JOL-EVyrbxKra^d{?|NnPp86!q>t<&IP07?Z z^>~IK^k#OEKgRH+LjllZXk7iA>2cfH6+(e&9ku5poo~6y{GC5>(bRK7hwjiurqAiZ zg*DmtgY}v83IjE&AbiWgMyFbaRUPZ{lYiz$U^&Zt2YjG<%m((&_JUbZcfJ22(>bi5 z!J?<7AySj0JZ&<-qXX;mcV!f~>G=sB0KnjWca4}vrtunD^1TrpfeS^4dvFr!65knK zZh`d;*VOkPs4*-9kL>$GP0`<?hW@{z#_gXtp%=2VbN+$~z+M($Vf(dl@)t-*82<$( zHi{FrD1wO9L~*Rc0{A2WU%f?ar(T9V1JpQ?M0Q|&{UES|#Z~k2-mj@z)8Rw^(XeYc zomT(B0EF!##4dQq_*NN<%Bo5)&+gCXSGZo`b>(M!j~B;#x?Ba<KDM~HJ!|Zzy=p2e z8;av`GLw{_*RgO(W|UK-<iDeT!t_x1c=M3%wGk|fDk<e0lLe8-5ga6apKYJD`*a3G zBl?Ps)hDb7X`7bW5S=IHr0Mm?fr|$zCf+gmZUrit$5n+)JZG>~&s6CopvO86oM?-? zOw#dIRc;6A<R&%m3DDJhF+|tb*0Yw8mV{a-bf^E~gh66MdsMHkog<r9`fVIVE+h@O zi)iM`rmA-Fs^c=>6T?B`Qp%^<<Dyu<%Kg0H=lq;E!p&UHzSpD1)q%^v)Y8yQkp>U5 z19x(ywSH$_N+Io!6;e?`tWaM$`=D<O;$E>b!gzx|lQ${DG!zb1Zl&|{kX0y6xvO1o z220r<-oaS^^R2pEyY;=Qllqpmue|5yI~D|iI!IGt@iod{Opz@*ml^w2bNs)p`M(Io z|E;;m*Xpjd9l)4G#KaWfV(t8YUn@A;nK^#xgv=LtnArX|vWQVuw3}B${h+frU2>9^ z!l6)!Uo4`5k`<<;E(ido7M6lKTgWezNLq>U*=uz<KVOwgK<qq^3FEy1LAV}ep3|Zt z>&s=cc$1%>VrAeOoUtA|T6gO4>UNqsdK=NF*8|~*sl&wI=x9-EGiq*aqV!(VVXA57 zw9*o6Ir8Lj1npUXvlevtn(_+^X5rzdR>#(}4YcB9O50q97%rW2me5_L=%ffYPUSRc z!vv?Kv>dH994Qi>U(a<0KF6NH5b16enCp+mw^Hb3Xs1^tThFpz!3QuN#}KBbww`(h z7GO)1olDqy6?T$()R7y%NYx*B0k_2IBiZ14&8|JPFxeMF{vW>HF-ViB*%t0;Thq2} z+qP}n=Cp0wwr%5S+qN<7?r+``=l(h0z2`^8j;g2~Q4u?{cIL{JYY%l|iw&YH4FL(8 z1-*E#ANDHi+1f%<FEETVoPos>lMJbRfq*`nG)*#?EJEVoDH5XdfqwR-C{zmbQoh?E zhW!|TvYv~>R*OAnyZf@gC+=%}6N90yU@E;0b_OV#xL9B?GX(D&7BkujjFC@HVKFci zb_>I5e!yuHA1LC`xm&;wnn|3ht3h7|rDaOsh0ePhcg_^Wh8Bq|AGe`4t5Gk(9^F;M z8mFr{uCm{)Uq0Xa$Fw6+da`C4%)M_#jaX$xj;}&Lzc8wTc%r!Y#1akd|6FMf(a4I6 z`cQqS_{rm0iLnhMG~CfDZc96G3O=Tihnv8g;*w?)C4N4LE0m#H1?-P=4{KeC+o}8b zZX)x#(zEysFm$v9W8-4lkW%VJIjM~iQIVW)A*RCO{Oe_L;rQ3BmF*bhWa}!=wcu@# zaRWW{&7~V-e_$s)j!lJsa-J<VS<FyMLS`=mm2DyVkhoo@GUWHJSEvdPg7RxL3UHfy z*gs(_Q*VnSV{81NNpzoHc>?z;54!;KnU3vuhp~(9KRU2GKYfPj{qA?;#}H5f$Wv-_ zGrTb(EAnpR0*pKft3a}6$npzzq{}ApC&=C&9KoM3Ge@24D^8ZWJDiXq@r{hP=-02& z@Qrn-cbr2YFc$7XR0j7{jAyR;4LLBf_XNSrmd{dV3;ae;fsEjds*2DZ&@#e)Qcc}w zLgkfW=9Kz|eeM$E`-+=jQSt}*kAwbMBn7AZSAjkHUn4n||NBq*|2QPcKaceA6m)g5 z_}3?DX>90X|35eI7?n+>f9+hl5b>#q`2+`FXbOu9Q94UX-GWH;d*dpmSFd~7WM#H2 zvKNxjOtC)U_<K!UT4EWFJ`0%qla66gi)v;h2;>tx*0(J)eAI8xAD8SvhZ+VRUA?)| zeJjvg9)vi`Qx;;1QP!c_6<TaBw5yUTI?4(<(Ap023XRh}!HQ_3Fm-D8%`yp_x#8B! zN`-?}P}FCH(8@_>hJp1=J=*%!>ug}%O!CoSh-D_6LK0JyiY}rOaqSeja&jb#P|DR7 z_JannlfrFeaE$irfrRIiN|huXmQhQUN6VG*6`bzN4Z3!*G?FjN8!`ZTn6Wn4n=Ync z_|Sq=pO7+~{W2}599SfKz@umgRYj6LR9u0*BaHqdEw^i)dKo5HomT9zzB$I6w$r?6 zs2gu*wNOAMK`<Vwp^NK2&^tzKYH;5$ul;h083?OwlA%T%-S=_}dw4qW5+S+XO0ak! zevPUnu$QsnVyIYV{2~>+5yPBIxS<I@Dj|*;M}4yQ9m%YNUmuCMV>OJpL$@SN&iUaM zQ3%$EQt%zQBNd`+rl9R~utRDAH%7XP@2Z1s=)ks77I(>#FuwydE5>LzFx)8ye4ClM zb*e2i*E$Te%hTKh7`&rQXz;gvm4Dam(r-!FBEcw*b$U%Wo9DIPOwlC5Ywm3WRCM4{ zF42rnEbBzUP>o>MA){;KANhAW7=FKR<s?Q(b#6vUYUif4R6`g>=DKK&S1AqSxyP;k z;fp_GVuV}y6YqAd)5p=tJ~0KtaeRQv^nvO?*hZEK-qA;vuIo!}Xgec4QGW2ipf2HK z&G&ppF*1aC`C!FR9(j4&r|SHy74IiDky~3Ab)z@9r&vF+Bapx<{<G#FO>u~gb2?*J zSl{6YcZ$&m*X)X<A3nlHC|>?|8<2S}WDrWN3yhyY7wlf*q`n^z<p#C6Wwg0Lc^7yc z{k35LkK*(Ql>3LT4T$@$y``b{m953kfBBPpQ7hT;zs(Nme`Qw@{_p<uKf;<4btoSk zRm`706ZWQUJLyJS5NS(XVIk-1Qgl|?{JCQFalvu23h5}<#*fAfGk3F$41iz>UO0OG zfugi3N?l|jn-Du3Qn{Aa2#6w&qT+oof=YM!Zq~Xi`vlg<;^)Jreeb^x6_4HL-j}sU z1U^^;-WetwPLKMsdx4QZ$haq3)rA#ATpEh{NXto-tOXjCwO~nJ(Z9F%plZ{z(ZW!e zF>nv&4ViOTs58M+f+sGimF^9cB*9b(gAi<XFtFDIykkajehj!02m(2aL02PawRDy_ z*i~rdmXPeyi=)nB3g8Mx4Wi>zwyu5|--SLmBOP-uftqVnVBd$f7YrkJ8!jm*QQEQC zEQ+@T*AA1kV@SPF6H5sT%^$$6!e5;#N((^=OA5t}bqIdqf`PiMMFEDhnV#AQWSfLp zX=|ZEsbLt8Sk&wegQU0&kMC|cuY`&@<#r{t2*sq2$%epiTVpJxWm#OPC^wo_4p++U zU|%XFYs+ZCS4JHSRaVET)jV?lbYAd4ouXx0Ka6*wIFBRgvBgmg$kTNQEvs0=2s^sU z_909)3`Ut!m}}@sv<63E@aQx}-!qVdOjSOnAXTh~MKvr$0nr(1Fj-3uS{<m;+EJv+ z(b49OY^IhZ0b$bXM5E^i4)FWy3XukhWUP*i(QIB^`nJPbqZL6f!_ooB=w~NprhpQ4 zqPQCBat+sMcGd0B$rBNY{D(W1XU2RrsQ<DV;I7-88%iIY>U6-T9NG1Y(Ua)Nc}Mi< zOBQz^&^v*$BqmTIO^;r@kpaq3n!BI?L{#bw)pdFV&M?D0HKqC*YBxa;QD_4(RlawI z5wBK;7T^4dT7zt%%P<*-M~m?Et;S^tdNgQSn?4$mFvIHHL!`-@K~_Ar4vBnhy{xuy zigp!>UAwPyl!@~(bkOY;un&B~Evy@5#Y&cEmzGm+)L~4o4~|g0uu&9bh8N0`&{B2b zDj2>biRE1`iw}lv!rl$Smn(4Ob>j<{4dT^TfLe-`cm#S!w_9f;U)@aXWSU4}90LuR zVcbw;`2|6ra88#Cjf#u62xq?J)}I)_y{`@hzES(@mX~}cPWI8}SRoH-H;o~`>JWU$ zhLudK3ug%iS=xjv9tnmOdTXcq_?&o30O;(+VmC&p+%+pd_`V}RY4ibQM<T~=yiutj z8PY3n0uEtXb9>NE&N5O+hb3bQ8bxk^33Fu4DB2*~t1909gqoutQHx^plq~;@g<Tn< zGIy~gC#ZKTD#!!uxjrLk#?Tj4SA(prkyQk5LV8nE+cuzXv_@|$a5Y|l6wO*uhLx)e z4a4f>$d_+rzS0`2;}2UR2h#?p35B=B*f0BZS4ysiWC!kw?4B-dM%m6_BfRbey1Wh? zT1!@>-y=U}^fxH0A`u1)Mz90G6-<4aW^a@l_9L6Y;cd$3<#xIrhup)XLkFi$W&Ohu z8_j~-VeVXDf9b&6aGelt$g*BzEHgzh)KDgII_Y<!yt~^$ZjIYrUsiH!TWfQi@+75> zb$fcY8?XI6-GEGTZVWW%O;njZld)29a_&1QvNYJ@OpFrUH{er@mnh*}326TYAK7_Z zA={KnK_o3QLk|%m@bx3U#^tCChLxjPxMesOc5D4G+&mvp@Clicz^=kQlWp1|+z|V7 zkU#7l61m@^#`1`<I>{+m2L{sZC#j?#>0)2z4}}kqGhB{NX%~+3{5jOyij!e$5-OAs zDvq+>I2(XsY9%NNhNvKiF<%!6t^7&k{L7~FLdkP9!h%=2Kt$bUt(Zwp*&xq_+nco5 zK#5RCM_@b4WBK*~$CsWj!N!3sF>ijS=~$}_iw@vbKaSp5Jfg89?peR@51M5}xwcHW z(@1TK_kq$c4lmyb=aX3-JORe+JmuNkPP=bM*B?};c=_;h2gT-nt#qbriPkpaqoF@q z<)!80iKvTu`T-B3VT%qKO^lfPQ#m5Ei6Y%Fs@%Pt!8yX&C#tL$=|Ma8i?*^9;}Fk> zyzdQQC5YTBO&gx6kB~yhUUT&%q3a3o+zueh>5D7tdByYVcMz@>j<TXu&?x1p)Dnh4 zskNHSw3{&FN-50Bq2nx!SyUG4E$vH!z7_A#oMR)rO?_v?C8{JTwDkINn0II$m85#c z=Oz^^KRrLn$uotBRrtGqFhJj!f{G=XOZ**42DuGuDV6Abhb?6wWQOK{N<$^)G9JVq zt~tbaQV!u?NZzl7@GbKqp0ciBI=QTB*7T*H^m0C+Pgw-+N?f7g%v34xjXqwU!THzz zwM!z}e-39`DuQ;0;)(52iX5VSp8CeKy2w+ekh}=S)Tpqyj)`%7J^n-rd%;J%K3Gi} z%J>!C@Iyg{N1)veYl`SPshuH6Rk=O6pvVrI71rI5*%uU3u8<J<JbTb96qe0Z){uD! z(?jD_k*1=Jk;r`o{F1rd>1DpD%qmXsbKWMFR@2m4vO_^l6MMbO9a()DcWmYT&?0B_ zuY~tDiQ6*X7;9B*5pj?;xy_B}*{G}LjW*<O@op=u{qXpBL4WR|o`e}#yS2mt=`0;g zk*qCDShkd<mE}6<cHkR<36dq_>qU&%*QAyt30@-@O&NQTARZ+%VScr>`s^KX;M!p; z?8)|}P}L_CbOn!u(A{c5?g{s31Kn#7i)U@+_KNU-ZyVD$H7rtOjSht8%N(ST-)%r` z63;Hyp^KIm-?D;E-EnpAAWgz2#z{fawTx_;MR7)O6X~*jm*VUkam7>ueT^@+Gb3-Y zN3@wZls8ibbpaoR2xH=$b3x1Ng5Tai=LT2@_P&4JuBQ!r#Py3ew!ZVH4~T!^TcdyC ze#^@k4a(<cMT=zWd{@BY-TQaG5^m)U6v^8CU<UZ_h<X&S{e&<ef!K*nDS^u)sz!oF zv3GpwPwiz<Z+%$2K{duN*{|U`y!Fv~<V~KMYNpb%jaA|d%{RrZuC9RL9x}h~2mfw1 z&(5bE{Pi$T`3c }kCcXotNM^kKsx=!bNtXw@bPnpdnxv8U{@5jwl4iOuy*Ulv$E zRr*O)*pGI|*{;DjKY6EYGY$UA(CyZ^Mb{|X{&ULt(gt&t##t?F&^Ke41N>nNe~G+y zI~yXK@1HHWU4pj{gWT6v@$c(x){cLq*KlFeKy?f$_u##)hDu0X_mwL6uKei~oPd9( zRaF_k&<bAvtIGrfv>w(J3J8b_`F~?0(Ei_pH}U^c&r$uSYawB8Ybs-JZ|&;vKLWX! z|HFZ%-uBDaP*hMcQKf*|j5!b%H40SPD*#{A`kj|~esk@1?q}-O7WyAm3mD@-vHzw( zTSOlO(K9>GW;@?@xSwpk%<BKz8jI}jIy`hcjM+(B2?y5RU8)J_t<^5T@5q(eVqo~3 zBO68aBr!giDu{-&mRO;X`_kCOk)SVi<#mG97Yofg&i@{QaPtr9sJxfvm*9;H@SuqC z#w2yv`XkX1Fm#r#GTnk<zr=n4H&oj2trmnx;X0_I*?j3mQjbM7=91jZ%cM_@DOx<; zBe@nMc^$^rGU$*j_K!qihH$KrnG1{anC~y4rqtiuKPczy-nHp9ziDlM+nm{BSGIn0 zjn88Zt)ktBnnU9JS3+R3k%!$OX$-hyV?#RNtxr;3X|+ibRRJk|C)0tNBhCqmxt%~k zW?jp7e1}Enb4c}+LT;RXFHvB<;HU$-BkxGUpu}xuVnee$aH?Ht5a*=Bfi1cpjp1AR zW0AS6J<>X3Ui4<EIxkjj2rf49E}4o!{lom8bZats3e|!F%@Mv0>_Psm;c*HF<uwRu zX2v}!DHM6Kd-vD^RoMp^t<T_OS$tZpDzDxl@Nzk;J6quA5BF_A1kKnbiWC2T)kFlH z(V^D=L0ygiE7V2xzZuVegW~^zIRA&`lxRZvU>~RW+q+C#RO_VT5(x!5B#On-W`T|u z>>=t)W{=B-8wWZejxMaBC9sHzBZGv5uz_uu281kxHg2cll_sZBC&1AKD`CYh2vKeW zm#|MMdC}6A&^DX=>_(etx8f}9o}`(G?Y``M?D+aTPJbZqONmSs>y>WSbvs>7PE~cb zjO+1Y)<CO?dR1Cg5s4M@qpdPA5@SkWDB@mH^43~g;%513aUq^B5_>PMi*!=06^$%< z*{b^66BIl{7zKvz^jut7ylDQBt)ba_F*$UkDgJ2gSNfHB6+`OEiz@xs$Tcrl>X4?o zu9~~b&Xl0?w(7lJXu8-9Yh6V|A3f?)1|~+u-q&6#YV`U2i?XIqUw*lc-QTXwuf@8d zSjMe1BhBKY`Mo{$s%Ce~Hv(^B{K%w{yndEtvyYjjbvFY^rn<KGkLBo^m9vg?nW<6+ zPmh<G^yK&-NDUiC8Z6ast0*z8xPQ8$(*j>2>C1Lbi!3RV7F>&;zlSDSk}R>{twI}V zA~NK%T!z=^!qbw(OEgsmSj?#?GR&A$0&K>^(?^4iphc3rN_(xXA%joi)k~DmRLEXl zaWmwMolK%@YiyI|HvX{X$*Ei7y+zJ%m{b}$?N7_SN&p+FpeT%4Z_2`0CP=}Y3D-*@ zL|4W4ja#8*%SfkZzn5sfVknpJv&>glRk^oUqykedE8yCgIwCV)fC1iVwMr4hc#<Z- zL-+W<jR>KcV!|M-r_N|nQWw@`j+0(Ywct~kLXQ)Qyncmi{Q4`Ur7A{Ep)n`zCtm8D zVX`kxa8Syc`g$6$($Qc-(_|LtQKWZXDrTir5s*pSVmGhk#dKJzCYT?vqA9}N9DGv> zw}N$byrt?Mk*ZZbN5&zb>pv;rU}EH@Rp54)vhZ=330bLvrKPEPu!WqR%yeM3LB!(E zw|J05Y!tajnZ9Ml*-aX&5T8YtuWDq@on)_*FMhz-?m|>RT0~e3OHllrEMthVY(KwQ zu>ijTc4>Xz-q1(g!ESjaZ+C+Zk5FgmF)rFX29_RmU!`7Pw+0}>8xK^=pOxtUDV)ok zw-=p=OvEH&VO3wToRdI!hPHc`qX+_{T_mj!NxcA&<p<h=eBG647W~srCOJ%YnAZc= z_Nfs1f}E6YV&pASfTpH}9tbu)4{#Ba2MsPj-56upCP@MeA3PUmV6EQ*1z#*N^TEue zy@dbDn?Ia-I`54^Z~pl7(zVZ_pG(9*?1GC3@YUj}QeUNX!ITTXIG3PGU6uEwG;a^& zqj~LaL>xOgkEuvz`-Aa`ZlNv>qnD0`YT1T3USO0ec!%{KE~UOGPJX%I5_rZDGx@|w zVIMsRPP+}^Xxa&{x!q{hY1wat8jDO7YP0(8xHWeEdr<P*6`9ax>d79lUj<UfD%PK; z4Isv2N9v5&5n-oxF81zDR@cW8ecaSm>B8%)v{X1pQu|1dr*y9M&a(J`038}4>lK&K zIM~6wnX{XA?pFHz{hOmEq{oYBnB@56twXqEcFrFqvCy)sH9B{pQ`G50o{W^t&onwY z-l{ur<Ka?a_Vj#)=^e+nK%m4zzm%RZtDxs>4#8ylPV5YRLD%%j^d0&_WI>0nmfZ8! zaZ&vo@7D`!=?215+Vk181*U@^{U>VyoXh2F&ZNzZx5tDDtlLc)gi2=|o=GC`uaH;< zFuuF?Q9Q`>S#c(~2p|s49RA`3242`2P+)F)t2N!CIrcl^0#gN@MLRDQ2W4S#MXZJO z8<(9P>MvW;rf2qZ$6sHxCVIr0B-gP?G{5jEDn%W#{T#2_&eIjvlVqm8J$*8A#n`5r zs6PuC!JuZJ@<8cFbbP{cRnIZs>B`?`rPWWL*A?1C3QqGEG?*&!*S0|DgB~`vo_xIo z&n_Sa(>6<$P7%Py{R<>n6Jy?3W|mYYoxe5h^b6C#+UoKJ(zl?^WcBn#|7wMI5=?S# zRgk8l-J`oM%GV&jFc)9&h#9mAyowg^v%Fc-7_^ou5$*YvELa!1q>4tHfX7&PCGqW* zu8In~5`Q5qQvMdToE$w+RP^_cIS2xJjghjCTp6Z(za_D<$S;0Xjt?mAE8~Ym{)zfb zV62v9|59XOvR}wEpm~Cnhyr`=JfC$*o15k?T`3s-ZqF6Gy;Gm+_6H$%oJPywWA^Wl zzn$L=N%{VT8DkQba0|2LqGR#O2Pw!b%LV4#Ojcx<DkATQzZt2m)Z{XGHSSJVB)dEu z$k5uf0bru0;$A03ffmj4X4+w-#Ex!3zY<g3vy{Q-;>5`?Cm;+aLpkyZ=!r1z@E}V= z$2v6v%Ai)MMd`@IM&UD!%%(63VH8+m0Ebk<5Du#0=WeK(E<2~3@>8TceT$wy5F52n zRFtY>G9Gp~h#&R92{G{jLruZSNJ4)gN<n8RjXM9L<b|8XyoMl0^H+4(zB;w~SJ!kD zrVI|u0t_5@!H0jw+sQtegKy~|{2WS+${5Oz(JgLw!@`G#G?5)|&o4Ab&mtkFW6R;I zbIl_@SvfNAX(Na{b+@Q70a`Sk3lQIt*FDI<(O)!c#B&A(Q`95=aPuOdvOYD_Tbcm% z%D-4n{DMJ=hdY}r!%6RohhWRUg~J@(vFV$}5IJdXuC=~`w%u&<vo@A4ca>K+zg*$P zW@~Hf>_Do)tvfEAAMKE1nQ=8coTgog&S;wj(s?Xa0!r?UU5#2>18V#|tKvay1Ka53 zl$RxpMqrkv`Sv&#!_u8$8PMken`QL0_sD2)r&dZziefzSlAdKNKroVU;gRJE#o*}w zP_bO{F4g;|t!iroy^xf~(Q5qc8a3<+vBW%V<d`nS{lSj$4Nm}P5a}hnc(p%WzfvlG zT;H!5Z;n`VUd)l*N1r5XgtUc;QC!pff=V3Yc^2yBHlkn@&9nqcoHdJKJ=v^;^yV-f z<}BU(Bvrs_fCG)axqSM5flf2Ba{5fV)L3cPzWA?Q6se0a396m5Gr#_YQP8|uF0kH< zVB|z<#l1YCwIqxwN0n0`BRlP5TH;3I`~`BmZR!I&q>IOQ1!??d;yEn1at1wpt}*n- z0iQtfu}Isw4ZfH~8p~#RQU<wR$wNwXfz=BXCSL%flpWfABL6v7O5I*uK2pS}NYHvt zi`MA*@0*}k0)LtGV=asdz5UAs6ox*tjq2V>Kwf<$XeqUr-5?8TSqokdHL7tY|47R; z#d+4NS%Cqp>LQbvvAMIhcCX@|HozKXl)%*5o>P2ZegGuOerV&_MeA}|+o-3L!ZNJd z#1xB^(r!IfE~i>*5r{u;pIfCjhY^Oev$Y1MT16w8pJ0<E9%+ZY3k8rPYxm8wOPTy9 z@nZU~c*2|DKwp!jN;Um`8W><e2p}A{tG<hJX)A5!!YpV2>?9@&FH*`d;hS=c#F6fq z{mqsHd*xa;>Hg?j80MwZ%}anqc@&s&2v{vHQS68fueNi5Z(VD2eH>jmv4uvE|HEQm z^=b&?1R9?<@=kjtUfm*I!wPf5Xnma(4*DfPk}Es*H$%NGCIM1qt(LSvbl7&tV>e2$ zUqvZOTiwQyxDoxL(mn?n_x%Tre?L&!FYCOy0>o}#DTC3uSPnyGBv*}!<Y7tbCS^J_ z6*X7wjnZ%Q0s4^$g0<Mf0kC^>*Yv5IV)Bg_t%V+UrTXfr!Q8+eX}ANR*YLzwme7Rl z@q_*fP7wP2AZ(3WG*)4Z(q@)~c{Je&7?w^?&Wy3)v0{TvNQRGle9mIG>$M2TtQ(Vf z3*PV@1mX)}beRTPjoG#&&IO#Mn(DLGp}mn)_0e=9kXDewC8Pk@yo<8@XZjFP-_zic z{mocvT9Eo)H4Oj$>1->^#DbbiJn^M4?v7XbK>co+v=7g$hE{#HoG6ZEat!s~I<^_s zlFee93KDSbJKlv_+GPfC6P8b>(;dlJ5r9&Pc4kC2uR(0{Kjf+SMeUktef``iXD}8` zGufkM9*Sx4>+5WcK#Vqm$g#5z1DUhc_#gLGe4_icSzN5GKr|J&eB)LS;jTXWA$?(k zy?*%U9Q#Y88(blIlxrtKp6^jksNF>-K1?8=pmYAPj?qq}yO5L>_s8CAv=LQMe3J6? zOfWD>Kx_5A4jRoIU}&aICTgdYMqC|45}St;@0~7>Af+uK3vps9D!9qD)1;Y6Fz>4^ zR1X$s{QNZl7l%}Zwo2wXP+Cj-K|^wqZW?)s1WUw_APZLhH55g{wNW3liInD)WHh${ zOz&K>sB*4inVY3m)3z8w!yUz+CKF%_-s2KVr7DpwTUuZjPS9k-em^;>H4*?*B0Bg7 zLy2nfU=ac5N}x1+Tlq^lkNmB~Dj+t&l#fO&%|7~2iw*N!*xBy+ZBQ>#g_;I*+J{W* z=@*<AAG@ThQqLTS8LoW9hl8e8slgs|pH%Z@1|LXbEv=yEDaqvFtkgO0fm!oT;UD4I zgw!e(vKorcHj2>15><)Bh9f>>dgQrE<e-x!^l8zejAkt^^^`zlF;a1n;X-XLc~Fs% z=F|#T8rRX07v}A5%C@Bo>hkrr2FEJ;R2rH%`kda8sD-FY6e#7S-<)V*zQA>)Ps)L- zgUuu@5;Ych#jX_KZ+;qEJJbu{_Z9WSsLSo#XqLpCK$gFidk}gddW(9$v}iyGm_OoH ztn$pv81zROq686_7@avq2heXZnkRi4n(3{5jTDO?9iP%u8S4KEqGL?^uBeg(-ws#1 z9!!Y_2Q~D?gCL3MQZO!n$+Wy(Twr5AS3{F7ak2f)Bu0iG^k^x??0}b6l!>Vjp{e*F z8r*(Y?3ZDDoS1G?lz#J4`d9jAEc9YGq1LbpYoFl!W!(j8-33Ey)@yx+BVpDIVyvpZ zq5QgKy>P}LlV?Bgy@I)JvefCG)I69H1;q@{8E8Ytw^s-rC7m5>Q>ZO(`<rJD^N3)b zrY@XQ=`M~mXZ#s{XEHo_{Wul}Fs^7CdvbCX?LZ+OHC5%T;xFOXVwOJR8Lq}00$$<s z0m&M?Y3<bP7OrI_ENundw|clc`k>$`9@`49s2)q#{2eN0A?~qS8%wxh%P*99h*Sv` zW_z3<=iRZBQKaDsKw^TfN;6`mRck|6Yt&e$R~tMA0ix;qgw$n~fe=62aG2v0S`7mU zI}gR#W)f+Gn=e3mm*F^r^tcv&S`Rym`X`6K`i8g-a0!p|#69@Bl!*&)QJ9(E7ycxz z)5-m9v`~$N1zszFi^=m%vw}Y{ZyYub!-6^KIY@mwF|W+|t~bZ%@rifEZ-28I@s$C` z>E+k~R1JC-M>8iC_GR>V9f9+uL2wPRATL9bC(sxd;AMJ>v6c#PcG|Xx1N5^1>ISd0 z4%vf-SNOw+1%yQq1YP`>iqq>5Q590_pr?OxS|HbLjx=9~Y)QO37RihG%JrJ^=Nj>g zPTc<Z%(meLC3t3DA3mXspnPQXL*D!Ta65mfL8n5cTVeIXz1M&EvRvf~9Y&HGRe34j zC{Z<XTx+@;8#G)UDzJa=zNkJ)ZThO~AbC95=lEA9s93CKH~q`T0Lo^V<~2qE_P`rr zT8g<d&liKY6OZ@w#*&(eHNxz~{nnk+F?=TJnWu+d?Cct!$0t}FWu$tmDwPn{x}W3D z(#hW-J#P+zSREZaB(H<>O$6r{jdE_096b&L;W<UT0WXd-7EcYUKC#!}=R=zh^fQ!w zw^!4tduWEBa!eB6VD%8*Zm;lJUaOv3q&ftLM>m8vcxUVxF0mA%W`aZz4n6XtvOi($ zaL!{WUCh&{5ar=>u)!m<SP1r*2Q!B7!r%>it|&EkGY$|YG<_)ZD)I32uEIWwu`R-_ z<l-F2@T;+Rfp>`FVeKyrx3>8Ep#2~%VVrQ%u#exo!anPe`bc)-M=^IP1n1?L2UQ@# zpNjoq-0+XCfqXS!LwMgFvG$PkX}5^6yxW)6%`S8{r~BA2-c%-u5SE#%mQ~5JQ=o$c z%+qa0udVq9`|=2n=0k#M=yiEh_vp?(tB|{J{EhVLPM^<GU_9IW&W5r0EZfqfvqKJa zj$A!0V@^%^G*@LfCxnQBRsf!SFI>S@f-O*Lgb390BvwK7{wfdMKqUc0uIXKj5>g^z z#2`5^)>T73Eci+=E4n&jl42E@VYF2*UDiWLUOgF#p9`E4&-A#MJLUa&^hB@g7KL+n zr_bz+kfCcLIlAevILckIq~RCwh6dc5@%yN@#f3lh<g!DD;$~9!F?Umj0oq+-L;Pq3 zWBjyxUsn|F4v2<-tDya8_xD#3tf+Btl6xMKmQwU{uG^pCHy8%(g8{EzO=viuWMlpe zxaYI`vE-I~M7S(FL%W(!O9O@x5R%(RDcs<mY)UE+SKgn!vO!l5lVfKknb{^`9|ACm zFc>HIx4fZ_yT~o0#3@h#!HCN(rHHC6#0$+1AMq?bY~(3nn{o5g8{*e_#4RhW)xPmK zTYBEntuYd)`?`bzDksI9*MG$=^w!iiIcWg1lD&kM1NF@q<Uw8p<g_Dpnj9vN66UU6 z#Z3*p$ka?~sV+=@HS4)aShwh2%xUcFRzNG=CK_7wDr^y+Hym1XjM0Y)8#0I8xk*BJ z6~Y?ps>Kha0fDVz^W7JCam^!AQFxY@7*`a3tfBwN0uK_~YBQ18@^i%=YB}K0Iq(Q3 z=7hNZ#!N@YErE7{T|{kjVFZ+f9Hn($zih;f&q^wO)PJSF`K)|LdT>!^JLf=zXG>>G z15TmM=X`1%Ynk&dvu$Vic!XyFC(c=qM33v&SIl|p+z6Ah9(XQ0CWE^N-LgE#WF6Z+ zb_v`7^Rz8%KKg_@B>5*s-q*TVwu~MCRiXvVx&_3#r1<P_Vsg0r#|~)TS-_d=4M~cE z+&T48ska5zw)EmTXQm+ioQ#?!TAFgl6YGNnf^vvUGF8c#WveY-j?v>h&L+{rM&-H6 zrc<W1b?Kswwnc7D+{tF5OXqdbQIoE?`I?`AYOA|Nz_u97H4|;)Y(B#Jlx4%Vyq`C% z>gH@I>0eY8WBX#Qj}Vml+fpv?;EQXBbD0lx%L?E4)b-nvrmMQS^}p_CI3M24IK(f| zV?tWzkaJXH87MBz^HyVKT&oHB;A4DRhZy;fIC-TlvECK)nu4-3s7qJfF<RMe%2ki1 zTI6+Q&ku0Tf_}LhN9vYEpKLB63Apcx<A44C!(?Ku{@lPv1p=C*{NKQPqW?SoDrx8J zVrXOY|6`QKsKfYZo1*^sOJ;d{XYp>-ZZGt7+6C3xZt!ZX4`M{eN|q!y*d^B+cF5W- zc9C|FzL;$bAfh56fg&y0j!PF8mjBV!qA=z$=~r-orU-{0AcQUt4<urmeM_viOanZ> zNYC=_9(MOWe$Br9_50i#0z!*a1>U6ZvH>JYS9U$kkrCt7!mEUJR$W#Jt5vT?U&LCD zd@)kn%y|rkV|CijnZ((B2=j_rB;`b}F9+E1T46sg_aOPp+&*W~44r9t3AI}z)yUFJ z+}z5E6|oq+oPC3Jli)EPh9)o^B4KUYkk~AU9!g`OvC`a!#Q>JmDiMLTx>96<qgBn8 z5Yx>_iDD9h@nW%Je4%>URwY<khi%2<#7=1x6bKj`i+VNfqc83y4%c<DW8#bYi5YZb z$#9uBFd7dEOo$AJb4JZJO5H`_z^H7us>M%5YU1&Dcdulvv3IH3GSrA4$)QjlGwUt6 zsR6+PnyJ$1x{|R=ogz<jrS1DHwc3k9SyCRDme*{=6T#8t{oN}(u`b1y&NoUMw~k&i z-ZMT<e7mL5FWq(-nCv;nz!91AZl{NhC%CdljGG*{I`mQsTERle-US8eePrJIvi@(~ z7-9FHtjkeQ>Err~U|X!+b+F8=6y?Yi`E$yjWXsdmxZa^hIqa)YV9ubUqOj&IGY}bk zH4*DEn({py@MG5LQCI;J#6+98GaZYGW-K-&C`(r5#?R0Z){DlY8ZZk}lIi$xG}Q@2 z0LJhzuus-7dLAEpG1Lf+KOxn&NSwO{wn_~e0<P6hRP=HtV6GZO4BWR+u?s}P=mtR? z^s-q@iNL0$t&{z^w<8l8Gfidj9i;%JZjA&yE?EO$&aT3#)<VfKjT&xVy=ob6_fCQ1 z1ZANC@-v}}f_Ot^v6-^$=p`K1pzl0%@pT?@;VeuG3OCx<;!tLX(*FCgcF6%v6I-u+ zOtolW2R3pOY_+(+h`%+h#=|Jp1>=}dovX)T(|WRMTqacoW8;A>8tTDr+0yRa+U!LW z!H#Gnf^iCy$tTk3kBBC=r@xhskjf1}NOkEEM4*r+A4`yNAIjz`_JMUI#xTf$+{UA7 zpBO_aJkKz)iaKqRA{8a6AtpdUwtc#Y-hxtZnWz~i(sfj<Z|BkJ?5yNRyVr*CY(ck` zYBr4&*s>Mk`lq|kGea=`62V6y)TMPZw8q<PMu}{|F!lI=W@pt{Brl{lZ$Kvki;7jR zu5U<jQ;cdN982L5LwwYW4w)&epo>}tFDDHrW_n(Z84ZxWvRrntcw;F|Mv4ff9iaM% z4IM{=*zw}vIpbg=9%w&v`sA+a3UV@Rpn<6`c&5h+8a7izP>E@7CSsCv*AAvd-izwU z!sGJQ?fpCbt+LK`6m2Z3&cKtgcElAl){*m0b^0U#n<7?`8ktdIe#ytZTvaZy728o6 z3GDmw=vhh*U#hCo0gb9s#V5(IILXkw>(6a?BFdIb0%3~Y*5FiMh&JWHd2n(|y@?F8 zL$%!)uFu&n+1(6)oW6Hx*?{<Fve1i68O0|}VY@-CnZ2#qMDX4_TH5{a14Z!yY5Jyy zx~A7-X<-PE0WM<Tm|Nvc^ZEwz8GrqOWa`Z1*RZ}hIr1a1?laD~;emg18pAJ#9>d~y zBeR)N*Z{7*gMlhMOad#k4gf`37OzEJ&pH?h!Z4#mNNCfnDI@LbiU~&2Gd^q7<CQs0 z&asYoA!Bw(%<&`9zGMPFrBS@o$PG#iIU>ix8~Y6$a=B9bK(BaTEO0$Oh=VCkBPwt0 zf#QuB25&2!m7MWY5xV_~sf(0|Y*#Wf8+FQI(sl2wgdM5H7V{aH6|ntE+OcLsTC`u; zeyrlkJgzdIb5=n#SCH)+kjN)rYW7=rppN3Eb;q_^8Zi}6jtL@eZ2XO^w{mCwX(q!t ztM^`%`ndZ5c+2@?p>R*dDNeVk#v>rsn>vEo;cP2Ecp=@E>A#n0!jZACKZ1=D0`f|{ zZnF;Ocp;$j86m}Gt~N+Ch6CJo7+Wz<khC+niM3qr-iS&UBcHui{9XrK>v|nlsXBvm z?St-5Ke&6hbGAWoO!Z2Rd8ARJhOY|a1rm*sOif%Th`*<gwKLW?(Zk1#*ZOXQ`cojG zD13Ehmfi1VRcjC6^(x$Mr?4CrwnTiR=R5g=ptRC8<8eNz%nut#PS8c6u#;@$&2ey+ zdY<bNMhywpCa2S@h7Q3wbgCGuX_x#vX-yqzvPsMWe)TLqZo9uM5`ZDjRM95Ep@ZY3 z3!vbipe75C=xz+QTQ^*cq&P%8D{YFL0(rKe)l;OSVquh&DYX(RJ=S6F9Om4%x%qm8 z&MQBXRTf8OLdIIe4a>=^jlgWo%e9`3sS51n*>+Mh(9C7g@*mE|r%h*3k6I_uo;C!N z7CVMIX4kbA#gPZf_0%m18+BVeS4?D;U$QC`TT;X<fDeDKHK{v9^#caNvL$%M`~|e> zP#H}tMsa=zS6N7n#BA$Fy8#R7vOesiCLM@d1UO6Tsnwv^gb}Q9I}ZQLI?--C8ok&S z9Idy06+V(_aj?M78-*v<PSvKN>YBu|AaJ9mlEJpFEIP}{tRwm?G{ag>6u(ReBKAAx zDR6qe!3G88NQP$i99DZ~CW9lzz}iGynvGA4!yL}_9t`l*SZbEL-%N{n$%JgpDHJRn zvh<{AqR7z@ylV`kXdk+uEu-WWAt^=A4n(J=A1e8DpeLzAd;Nl#qlmp#KcHU!8`YJY zvBZy@>WiBZpx*wQ8JzKw?@k}8l99Wo&H>__<oxE+DvXhRO^f>vCFL}>m~MTmGvae% zPTn9?iR=@7NJ)?e+n-4kx$V#qS4tLpVUX*Je0@`f5LICdxLnph&Vjbxd*|+PbzS(l zBqqMlUeNoo8wL&_HKnM^8{iDI3IdzJAt32UupSr6XXh9KH2LjWD)Pz+`cmps%eHeD zU%i1SbPuSddp6?th;;DfUlxYnjRpd~i7vQ4V`cD%4+a9*!{+#QRBr5^Q$5Ec?gpju zv@dk9;G>d7QNEdRy}fgeA?i=~KFeibDtYffy)^OP?Ro~-X!onDpm+uGpe&6)*f@xJ zE1I3Qh}`1<7aFB@TS#}ee={<#9%1wOL%cuvOd($y4MC2?`1Nin=pVLXPkknn*0kx> z!9XHW${hYEV;r6F#iz7W=fg|a@GY0UG5>>9>$3Bj5@!N{nWDD`;JOdz_ZaZVVIUgH zo+<=+n8VGL*U%M|J$A~#ll__<`y+jL>bv;TpC!&|d=q%E2B|5p=)b-Q+ZrFO%+D_u z4%rc8BmOAO6{n(i(802yZW93?U;K^ZZlo0Gvs7B+<%}R;$%O}pe*Gi;!xP-M73W`k zXLv473Ex_VPcM-M^JO|H>KD;!sEGJ<HTW@*Usun3M)y1SZy-}aD>|E}Qepen;yNG2 zXqgD5sjQUDI(XLM+^8ZX1s_(X+PeyQ$Q5RukRt|Kwr-FSnW!^9?OG64UYX1^bU9d8 zJ}8K&UEYG+Je^cThf8W*^RqG07nSCm<CEe(KJqi=yo4Zu+%xm@?EsCwAe&T3j;YZ= z`fzz&jda9suA?ug-<)Lt|J!;C=m%2_6!M#s+o$=|h!UsUZze~j6B|oBnDcXoBo6s( znVOI7#2w)n`o&*71n0&}PmJ49=A^!uAEdr;5G1}y8xW=VO4p=PtZGRvI4Sg{DMqQq z%SIK&<Wa1Nqat-4s@X(z$m)__E$wOxmm~0!_GrS1d?bG*JLP%k;er00_>p*o5Z;#F zS?jochDWX@p+%CZ%dOKUl}q{9)^U@}qkQtA3zBF)`I&zyIKgb{mv)KtZ}?_h{r#VZ z%C+hwv&nB?we0^H+H`OKGw-&8FaF;=ei!tAclS5Q?qH9J$nt+YxdKkbRFLnWvn7GH zezC6<{mK0dd763JlLFqy&Oe|7UXII;K&2pye~yG4jldY~N;M9&rX}m76NsP=R#FEw zt(9h+=m9^zfl=6pH*D;JP~OVgbJkXh(+2MO_^;%F{V@pc2nGn~=U)Qx|JEV-e=vXk zPxA2J<9~IH{}29#X~KW$(1reJv}lc4_1JF31gdev>!CddVhf_62nsr6%w)?IWxz}{ z(}~~@w>c07!r=FZA<wFaiohRbKb~^?3q5?_zk?fqI0MHaAe;iY+em}3rG(ta;5O`r z;1)QPwN9vHyE)(@T!k}>Nq4R!F2Qi2?QGavZ{)PCq~X}3x;4ylsd&m;dQe;0GFSn5 zZ*J<=Xg1<rmtct^RD?`a5gOMC4L)d>fEGYYDZ0{Z4}Jh*xlXa}@412nlKSM#@wjMM z*0(k>Gfd1Mj)smUuX}EM6m)811%n5zzr}T?$ZzH~*3b`3q3gHSpA<3cbzTeRDi`SA zT{O)l3%bH(CN<IN>0EEF9ph1(Osw5y$SJolG&Db~uL!I3U{X`h(h%^KsL71`2B1Yn z7(xI+Fk?|xS_Y5)x?oqk$xmjG@_+JdErI(q95~UBTvOXTQaJs?lgrC6Wa@d0%O0cC zzvslIeWMo0|C0(<f+k5>{iEWX{=5F)t4Z*`rh@-t0ZTMse3VaJ`5`1zeUK0~F^KRY zj2z-gr%sR<(u0@SNEp%Lj38AB2v-+cd<8pKdtRU&8t3eYH#h7qH%bvKup4cnnrN>l z!5fve)~Y5_U9US`uXDFoOtx2gI&Z!t&VPIoqiv>&H(&1;J9b}kZhcO<PyO-o^uK1x z>X7EiW*Bujy#MaCl52%NO-l|<wz{;LglcbSGr9RqPoL*nYEN|Murl0Ya0<J_(ZpWZ zF)>@2$aRKvZ!YjwpXwC#nA(tJtd1p?jx&U|?&jcb!0MT6oBlWurVRyiSCX?sN3j}d zh3==XK$^*8#zr+U^wk(UkF}bta4bKVgr`elH^az{w(m}3%23;y7dsEnH*pp{HW$Uk zV9J^I9ea7vp_A}0F8qF{>|rj`CeHZ?lf%HImvEJF<@7cgc1Tw%vAUA47{Qe(sP^5M zT=z<~l%*ZjJvObcWtlN?0$b%NdAj&l`Cr|x((dFs-njsj9%IIqoN|Q?tYtJYlRNIu zY(LtC-F14)Og*_V@gjGH^tLV4uN?f^#=dscCFV~a`r8_o?$gj3HrSk=YK2k^UW)sJ z&=a&&JkMkWshp0sto$c6j8f$J!Bsn*MT<h8dS6cWTC2@)2)r~Q6P<?JMO=z=v6=h0 z{z0O{ZSMEdl||RciL2=bIRol$EQX%GoV#vmsfKn64QmInOxq%^Q3!={`}-O}OF!W# z=Hj!CX?@sGbF3Dtmb5z~EA>jC`3cv@l@7cINa!}fNcu(0XF7ZCAYbX|WJIL$iGx8l zGFFQsw}x|i!jOZIaP{@sw0BrV5Z5u!TGe@JGTzvH$}55Gf<;rieZlz+6E1}z_o3m2 z(t;Cp^Geen7iSt)ZVtC`+tzuv^<6--M`^5JXBeeLXV)>2;f7=l%(-4?+<5~;@<fp) z1Lui?ARVsm?nP~!ne9-FRx3JSEwwC5O{HygKy6`yWh?gVhS?YcW4+v5JWTeVDAmjv zCOtdeHV1%x2dOX@vq0y;J^p<!(r|O)vi|(<nvMWYjpI;<j^T#vi*<7po`Kd6FA;^r zmyETseWV1c90=BR0ZP&?D?U4l#rsfm+~24-c!J7PR{eD=x@cqZ#~<}g+~EX)E|2a$ z+gi~<mvHzfsze~C6NT^{GLC>=Th{1#>rK3+rLn(44TAFS@u(}dunUSYu}~))W*fr` zkBL}3k_@a4pXJ#u*_N|e#1gTqxE&WPsfDa=`@LL?PRR()9^HxG?~^SNmeO#^-5tMw zeGEW&CuX(Uz#-wZOEt8MmF}hQc%14L)0=ebo`e$$G6nVrb)afh!>+Nfa5P<oZ7>;N zCCOQ^NRel#saUVt$Ds0rGd%gkKP2LsQRxq6)g*`-r(FGM!Q51c|9lk!ha8Um3ys1{ zWpT7XDWYshQ{_F!8D8@3hvXhQDw;GlkUOzni&T1>^uD){WH3wRONgjh$u4u7?+$(Y zqTXEF>1aPNZCXP0nJ;z<N&&~t`L3v?GV)58KGTHHGL!swTJXxH{~NMLx(L72U7AvS zcP}RNT->s6_%6;+D&J_|ugcih**y(4ApT`RKAi5>SZe0Bz|+l7z>P14>0ljIH*LhK z@}2O#{?1RNa&!~sEPBvIkm-u<y&MCPHyI+!uRA$A&rl2a>It^Pt#%JnsbJ`-T0%pb ze}d;dzJFu7oQ=i`VHNt%Sv@?7$*oO`Rt*bRNhXh{FArB`9#f%ksG%q?Z`_<19;dBW z5pIoIo-JIK9N$IE1)g8@+4}_`sE7;Lus&WNAJ^H&=4rGjeAJP%Dw!tn*koQ&PrNZw zY88=H7qpHz11f}oTD!0lWO>pMI;i4sa<gbCHb*?!TW%nQ=Crc6PM8jDTh%vfNUoN9 z<Dyk7#UrltDltZCanZAJp~$Uj3z%^}HyR>uS`%_!zM!n@91sLH#rz1~iEAu#1b%LA zhB}7{<u6opdJcy2km#)#Y#n?t1euj>1(8{1{V8+SEs=*f=FcR<FV0_Ap!<#zSZ}~< zN7Q;-uIX)e5`ftQ>E^;`6Pxm$Hie~|aD~W1BYy#@Y$C?pxJh*cC!T@8C9{xx*T*8P zhbkRk3*6)Zbk%}u>^?ItOhxdmX$j9KyoxxN>NrYGKMkLF4*fLsL_PRjHNNHCyaUHN z7W8yEhf&ag07fc9FD>B{t0#Civsoy0hvVepDREX(NK1LbK0n*>UJp&1FygZMg7T^G z(02BS)g#qMOI{RJIh7}pGNS8WhSH@kG+4n=(8j<+gVfTur)s*hYus70A<L}puU}Lb zu200ys|`>HUBS2bN6Zp_GOHYxsbg{-Rcet{@0gzE`t$M0_!ZIqSAIW53j+Ln7N~8J zLZ0DOUjp^j`MvX#hq5dFixo^1szoQ=FTqa|@m>9F@%>7OuF9&_C_MDco&<yl?^CH) z_{m)+n(GUp{jz&DgTPmM1Ie32W;fO2o&4S0WHZRaK}sd;OrQE#_U&x0+&FI~40PuQ ze#9WlNf2()A6n%*=)0;D=cW$&=;s%|mjn+596d9azJX@ws^_agA9S@SqCb%5)Pt1$ zTuDQ#W)9rV*dI`OL>-{wfLKNrDMEN4pRUS8-SD6@GP`>_7$;r>dJo>KbeXm>GfQS? zjFS+Y6^%pDCaI0?9(z^ELsAE1`WhbhNv5DJ$Y<V<y8)GDQRyg3oc8D}R=a~^=C+bR zA8dliBl?zMD&C-Y1@r5^4sc0o&y-Oly%>}~r;>FynHjmjmA{bfDbseZXsKUv<S~ds z>`%Fekv)1@f%7ti;B5hhs}5db1dP+P0${1DgKtb(DvN}6H6;0*LP6blg*rpr;Z(7? zrve>M`x6ZI(wtQc4%lO?v5vr{0iTPl&JT!@k-7qUN8b$O9YuItu7zrQ*$?xJIN#~b z#@z|*5z&D7g5>!o(^v+3N?JnJns5O2W4EkF>re*q1uVjgT#6ROP5>Ho)XTJoHDNRC zuLC(Cd_ZM?FAFPoMw;3FM4Ln0=!+vgTYBx2TdXpM@EhDCorzTS6@2`swp4J^9C0)U zq?)H8)=D;i+H`EVYge>kPy8d*AxKl};iumYu^UeM+e_3>O+LY`D4?pD%;Vextj!(; zomJ(u+dR(0m>+-61HTV7!>03vqozyo@uY@Zh^KrW`w7^ENCYh86_P2VC|4}(ilMBe zwa&B|1a7%Qkd>d14}2*_yYr@8-N}^&?LfSwr)C~UUHr)ydENu=?ZHkvoLS~xTiBH= zD%A=OdoC+10l7@rXif~Z#^AvW+4M-(KQBj=Nhgts)>xmA--IJf1jSZF6>@Ns&nmv} zXRk`|`@P5_9W4O-SI|f^DCZ-n*yX@2gf6N)epc~lRWl7QgCyXdx|zr^gy>q`Vwn^y z&r3_zS}N=HmrVtTZhAQS`3$kBmVZDqr4+o(oNok?tqel9kn3;uUerFRti=k+&W{bb zT{ZtEf51Qf+|Jc*@(nyn#U+nr1SFpu4(I7<1a=)M_yPUAcKVF+(vK!|DTL2;P)yG~ zrI*7V)wN_92cM)j`PtAOFz_dO)jIfTeawh2{d@x0nd^#?pDkBTBzr0Oxgmvjt`U^$ zcTPl=iwuen=;7ExMVh7LLFSKUrTi<KY<!-61)q_{3{un*!3+ioAJ}ikykUEszqLUz z2y?(ZGd?cRqh9pYpRi`+24AatY4$_e?EUKUn3Jh7T4ApDTj(45gg+&t`;?Q{T~cbD zn|bNQZR|89v%#GpNPQYtE?(B#%uDIfpgsUsQ7<Fll~M$jRoZq6vmY&{1Nwz^qA#Go zc|+flUXyLCb2t)u-mzSXfB*oT%i$GD5BYWsfIs$wF8Vdij$+{>PJpMB&*Ml32>wl} zYn(H0N4+>MCrm2BC4p{meYPafDEX<uu8*GYOdb||1L86<D25;RK8@zd2kY<K`lVFV zWxW7%O)+izx>d4yf$i%ylWpC|9%R4XZBUQih<i`-uBppkqY;Qs*4ob$&^Iv0MXueR zs^9GZt9u)s2Cv^Z+@fi83jHq!9bj``t`2%W4X`>a(x%w<wBlpV>gQ5iJ?K_wQBRfw z+pYuKoIameAWV7Ex4$PCd>bYD7)A9J`ri&bwTRN*w~7DR0EeLXW|I2()Zkl6vxiw? zFBX){0zT@w_4YUT4~@TXa;nPb^Tu$DJ=vluc~9)mZ}uHd#4*V_eS7)^eZ9oI%Wws_ z`;97^W|?_Z6xHSsE!3EKHPN<3IZ^jTJW=Il{rMmlnR#OuoE6dqOO1KOMpW84Z<G}M zeQ$nWk@-Y@mRFFq;S1oSSbG(l@Q(aR3<%_F<)_uOg^z>tDHNn)(pYvs=frO`$X}sY zKY0At$G85&2>B|-{*+B*aqQn&Mqjt*DVH2kdwE<Y_7iHmg2Cm#(Sh<4J6@f<d1{0_ z2^3BA&qWOWztYY+Dypt+<A6#?mxDA)NDd$fk`6d@DK+ANbl1=*APv$f-5{MJAl-w2 zf`Uj$ONmlaBIq~c^Smzu4-fLL?_O&bi}~Ze&OUq2K4;(i?CV$8RrU!hsiuTc?&as1 z$PLg}c#@!R^fMP&Bo&)b(J0Hj)VzLLO?2JCM;a9lb|SKw_bcf&<Y?auTw*?8j}mKc zh;zbPoG-a*lTJF;cYTd>m5f}~Xwn9+tPt?EPwh8=8=VWA8rjt*bHEs1FJ92QohQ)Y z4sQH~AzB5!Pisyf?pVa0?L4gthx2;SKlrr?XRU`?Y>RJgUeJn!az#sNF7oDbzksrD zw8)f=f1t*UK&$}_ktf!yf4Rjt{56ffTA{A=9n})E7~iXaQkE+%GW4zqbmlYF(|hE@ z421q9`UQf$uA5y<hO3<CDipt9*4<dYT6T>DLx67`=EnS<JRni<euaZulyr%vyhnlr z#?Eu%Cbt&$Qh2GVuhims!t(sZtTn6DH+khMm(wy>TxdEaG!6C%9_obpb?;u-^QFX% zU1wQ}Li{PeT^fS;&S<Y5`Q3*lDsv9CPMdV}m~xen5jZ}thFa&>k2#$ZM#<B;v8g#V zrswx2FBXZ(;R=Gq-stwS$#c?AI-?_}zv5!~CV2?X(<s$x(_gxir@sm|Cja!_@{6`W zQl|YUi5DeUC0^oOBKvUvK18FLFqV>Zpxrn7jsd<@qhfWy*H)cw9q!I9!fDOCw~4zg zbW`EHsTp9IQUCETUse)!ZmuRICx}0Oe1KVoqdK+u>67A8v`*X*!*_i5`_<c9{Noqv zpU!p<<G8iqQns&0K%<D)4OON5-!m?A%hk(FPQ+Q?ws_ccLu7=PI@ag2GOfVp`$hQj z3;P~3wbX%$?}k-KCY{_e``4|)XjLi70dV={`^!vOAo$+G9c(WLP8o?{9YHP}4$KUz z(G1HPLl11DLU0Dcu^>qTzYRkbYXg#4vT5~A{lK#bA}Oc4ePu5hr-@;i%Z!4Y;-(yR z(1rHYTc7i1h1aipP4DaIY3g2kF#MX{XW7g&zL!39ohO98=eo5nZtq+nz}2E$OZpxx z&OFaOM1O;?mxq+`%k>YS<Yu?md-1GMIyZf&AQWvPmo6CZVe@@DU-|T6jR$5=yrKb4 zb&a8G6}6XioJBsL5hN?i*Dbi)&%CK4?m};2MCujIboR+QjHGiTDJfq5RGO0R9CX)u z0zU4#8R^dZ{jzr_AyfBOUorP{&S*A_6&UYnFI3&tm>!-=H7BB&WhqSTUC{S!x*k9E zcB;u0I!h%3nEchQwu1GnNkaQxuWnW0D@Xq5j@5WE@E(<QNfqn|w8mRlTQ7sX*U5L5 zX1c+-14vB<S>WlgDU;FLsT*eV|Bh)aH0;~@^yygFj<=+Vu3p)LlF%1AA%y5z-Oh`2 z$RDKk_6r+f#I`8fQ%y#Wx%~de1qkWL2(q^~veLKwht-dIcpt(@lc>`~@mISRIPKPm zD!Za&aX@7dy*CT!&Z7JC1jP2@8+ro8SmlH>_gzRte%ojgiwfd?TR+%Ny0`sp`QRLy zl5TiQkFh<S=sKi}DbZK?W%4)lIIs>IC!2aaJ&=Ua`c9UuOk9GkSFZ}!IGeMZ5MXrL zGtMj`m{(<sAcQ4XR^(Yx=+F5D_F|kGh4WcL`ge_pig{Vz@@q-k5QqEE>X9+l%=d|L zW2OY?8!_pyhvJ1@O!Chsf6}@3HmKq@)x;CFItPMpkSr@npO&8zMc_O?*|sqkuL^U? zV9+x3vbr|6;Ft0J^J>IH_xpa<{S5K?u-sQWC7FB9YFMwoCKK3<ooKkM@8CB4tWkc& zbMUGaZ4+o`OF+ekbFK0Bi13*;T8t4<3_}*h{=Fc^ee#H)>WZ*gvO-wAApF`K%#7@1 z^sEj4*%hH`f0@sRDGI|#Dl20o$Z*gttP$q(_?#~2!H9(!d=)I93-3)?e<kCJHws!1 z?TUS>%@$1^*F=t9t&OQ9!p84Z`+y<$yQ9wlamK~Hz2CRpS8dWJfBl@(M2qX!9d_F= zd|4A&U~8dX^M25wyC7$Swa22$G61V;fl{%Q4Lh!t_#=SP(sr_pvQ=wqOi`R)do~QX zk*_gsy75$xoi5XE&h7;-xVECk;DLoO0lJ3|6(Ba~ezi73_SYdCZPItS5MKaGE_1My zdQpx?h&RuoQ7I=UY{2Qf<WTgMg!V?k)r-qf)mjply2B4{@!80S6L@j%-&~1;m<Mv> ziGQ-FpR%piffR_4X{74~>Q!=i`)J@T415!{8e`AXy`J#ZK)5WWm3oH?x1PVvcAqE@ zWI|DEUgxyN({@Y99vCJVwiGyx@9)y2jNg`R{$s2o;`4!^6nDX_pb~fTuzf>ZoPV@X zXKe1ehcZ+3dxCB+vikgKz8pvH?>ZzlOEObd{(-aWY;F0XIbuIjSA+!%TNy87a>BoX zsae$}Fcw&+)z@n{Fvzo;SkAw0U*}?unSO)^-+sbpNRjD8&qyfp%GNH;YKdHlz^)4( z;n%`#2Pw&DPA8tc)R9FW7EBR3?GDWhf@0(u3G4ijQV;{qp3B)`Fd}kMV}gB2U%4Sy z3x>YU&`V^PU$xWc4J!OG{Jglti@E3rdYo62K31iu!BU&pdo}S66Ctq{NB<88P92Y9 zTOqX$h6HH_8fKH(I>MEJZl1_2GB~xI+!|BLvN;CnQrjHuh?grzUO7h;1AbzLi|_O= z2S=(0tX#nBjN92gRsv;7`rDCATA!o(ZA}6)+;g;T#+1~HXGFD1@3D#|Ky9!E@)u=h z3@zg3Us0BCYmq(pB`^QTp|RB9!lX*{;7r|Z(^>J+av(0-oUmIdR78c4(q%hP#=R@W ze{;yy$T^8kXr(oC*#NQMZSQlgU)aa=BrZDwpLUk5tm&(AkNt&Gel`=ydcL*<@Ypx{ z2uOxl>2vSY2g3%Si&JU<9D5#{_z{9PzJh=miNH;STk^;5#%8iMRfPe#G~T>^U_zt? zgSE)`UQhb!G$at%yCf5MU)<&(L73(hY3*%qqPbX;`%QDHed3ZaWw^k)8Vjd#ePg<i zcp5jVnE)b@51=ikxwz)bMOpsO;};uPB3dwwQb3K)6V1vE)dkj`sik^TzenJqS*D^y zgw2x@0s;B&1HiwmZ~VP26=BY3Y-ZwUr-w9aJXRieNAMmI&U<i^jQ+df?=BH#v)Ki@ zd*03PoC8I$#Gdb{^!AE~u&QgIg{~&nS;+EjfcEhk``bI)0Ul`LF|aD<+#FHMXau3{ zmyMIN@y>@;I&pMe+A18k+S+bou|QX?8eQ`{P-0vrm=uR;Y(bHV>d>Gen4LHILqcm_ z3peDMRE3JMA8wWgPkSthI^K<|8aal38qvIcEgL<!9d48_9(GR4^MhM(vJ|52p_y_O z-SJ$7ByWZitf#aD(-IW>jHAFB0P#IfqP2y}L>=8eBR}Fm^V*mw2Q4+o=exP@*#=Zs zIqHh@neG)Vy%v4cB1!L}w9J>IqAo}CsqbFPrUVc@;~Ld7t_2IIG=15mT7Itrjq#2~ zq<N^#v=@%=&M%|x1ULBCT7f|hQVQ#o?%1XMnY$$#3{&nv&0>X*&nwZP>vso$6W!#` z-YZ}jhBwQku-Qc>TIMpn%_z~`^u4v3Skyf)<h26Xm+@qv*!BTf&uZux3OH{&_Yv6F zjXaOTDs^(_X7i-8-U1PZ5HC8*b?lhzPL-f}lh*@pHE+;jbL+ZhqJgkss~Ko|6rU!p zVw}Ug?pzYfMOLRH+{j9|33K;uPIu6@A=kZj$(emVeVUmz%+Y*SIwik2sA{3iSbD7T z@z|AHO^y?MK_OJPT@E6|VWSHIT38zGTAg7KA0jE8>KA}V{`dr!Q;3x<!|BZNGP06J z!})YPd1l2)l)w1qu3OGp_}mnU13VCHq@N(!#BL%~WFM}YtU@0n7`~J=SvmZ$612JY zY}y%D+N@WuUy2kC&&{3GV|2?!k6dfO46(QIeiWTyT86Hgig~*U<Ch;jCQKMaQM*Ri zpA>K1TuGYdl}$sKF^9X!*a-R*Oq1#tLq!W)gO}{q`1HM;oh1-k4FU@8W(qe>P05$+ z`ud2&;4IW4vq8#2yA{G>OH=G+pS_jctJ*BqD$j-MI#avR+<>m-`H1@{3VgKYn2_Ih z0`2_1qUMRuzgj_V^*;5Ax_0s{_3tYR>|$i#c!F7)#`oVGmsD*M2?%930cBSI4Mj>P zTm&JmUrvDXlB%zeA_7$&ogjGK3>SOlV$ct{4)P0k)Kua%*fx9?)_fkvz<(G=F`KCp zE`0j*=FzH$^Y@iUI}MM2Hf#Yr@oQdlJMB5xe0$aGNk%tgex;0)NEuVYtLEvOt{}ti zL`o$K9HnnUnl*;DTGTNiwr&ydfDp@3Y)g5$pcY9l1-9g;yn6SBr_S9MV8Xl+RWgwb zXL%kZLE4#4rUO(Pj484!=`jy74tQxD0Zg>99vvQ}R$7~GW)-0DVJR@$5}drsp3IQG zlrJL}M{+SdWbrO@+g2BY^a}0VdQtuoml`jJ2s6GsG5D@(<cgPph;^-s;xpb_sl;c! z`2I{ZRZ2rKu`+#w`%eDfFL1(_+@w{9uIMXJzK1C)cC-5XhmFjdJ$J0AeVu{!qN~7C ztXoC%fqAJLH9pp5w$D@q4|(WtMQt<uBX$;F`+;c(GdppC^RGeVPhF-vsn=ih;u6jW zm6GF4%m_juV9>^$5pMi3$27psEIOe^n=<va#F%To3t%){5yLqKe^;S6k~-{X7FZ5` z8C8uLS+^b!l95lWbWj$NdkSG>*Nj|Ug7VXN0OrwMrRq&@sR&vdnsRlI%*$vfmJ~)s z^?lstAT$Ked`b&UZ@A6I<(uCHGZ9pLqNhD_g-kj*Sa#0%(=8j}4zd;@!o;#vJ+Bsd z4&K4RIP>6It9Ir)ey?M6Gi6@JzKNg;=jM=$)gs2#u_WhvuTRwm1x2^*!e%l&j02xz zYInQgI$_V7Epzf3*BU~gos}|EurFj8l}hsI(!5yX!~ECL%cnYMS-e<`AKDL%(G)62 zPU;uF1(~(YbH2444JGh58c<L!e)x87c-46Lp>oXT>(*CdEwaFuyvB|%CULgVQesH$ znB`vk3BMP<-QauWOZ0W6xB5y7?tE5cisG|V;bhY^8+*BH1T0ZLbn&gi12|a9Oa%;I zxvaxX_xe3<zJ5_;M)%eUc$b1qh*#3cy)NFgC88^2+a(k+Yl_LMWaIPd<}RY|!D0d{ z$uOrm$<_CFd@uE5uyxO5sHA5PAtZehPrhIp9e0Nsutu7#eGO!z!OxmFo&`&VCBFZL zmvMu$ka54jcn_SlzEGRg)E{&pt1bUyd5FSM(K?xHX-(;lwoBxm=G}pTsCynZ)GP5G z>@ng%;4C?zPHQ1v%dbhjA6Sl7w<*)Nr#F{Ahzj}%n9c&!g5HVrlvUO&R2C)_$x6M9 zahficAbeHL2%jILO>Pq&RPPxl;i{K5#O*Yt15AORTCvkjNfJ)LrN4K{sY7>tGuTQ@ z^?N*+xssG&sfp0c$^vV*H)U1O!fTHk8;Q7@42MT@z6UTd^&DKSxVcC-1OLjl7m63& zBb&goU!hes(GF^yc!107bkV6Pr%;A-WWd@DK2;&=zyiK*0i^0@f?fh2c)4&DRSjrI zk!W^=<E?~bQ>l^JKlPW9US{*yo?_XT@T2Bx+Cm^+r{*5LVcKVw*ll3+)lkebA-4)o z8f5xHWOx0!FDSs4nv@o@>mxTQrOeKzj@5uL`d>mXSp|#{FE54EE_!KtQNq>-G(&5) ztz?xkqPU16A-8@-quJ|SU^ClZ?bJ2kCJPB|6L>NTDYBprw$Wcw<Y;;ldx=&gJa}4H z@Wwakn*Q^&RVtHa47by$I4sxs2Xr6hO|}|b8g;8P+cdPU{P00GD^=yOpI@GzPh+l` zi(s|O;0{OV%*#9PT6u8IaQp6YbA~_!T`w03A?yq_T&YSRnqY&$9SIkVQol~v{2NC( zPEQSJOOmN%HRmJS_NUT3hVmC!EL}-VEM1@e^gDltyerz9=+0e`-3a5G4k0SZ7Fa!1 z#ag*v`7$GXC1L{lPUrk^`@3^20bjuUD_37Kxt!~92XMGK0w&T|F$%LSOP_R^>CH{B z5qlJ6wK_9sT@Kl6G|Q&$gsl@WT>hE;nDAbH#%f1ZwuOkvWLj{qV$m3LF423&l!^iV zhym*>R>Yyens++~6F5+uZQTCz9t~PEW+e?w)XF2g!^^%6k?@Jcu;MG0FG9!T+Gx{Z z<gaMF{iLoiR26S<6~t-k;EsdU7e_zysFg2SI^5;A;*}V9MU-Fs%r-t{&pmIK5IGAc zzNfdSinv>K;31y@(J{!-$k4E{5#Sv(2DGy3EZQY}G_*z*G&CZ_J?m&Fg4IBrvPx1w z1zAb3k}6nT?E)HNCi%}aR^?)%w-DcpBR*tD(r_c{QU6V&2vU-j0;{TVDN6los%YJZ z5C(*ZE#kv-Bvl<Em5rSV(B!w_4$#2T42Z%3LIBAftq?Y(2w!<4+Y_EtkGH%njwHbv zaUXw<csfQ_AP(a;(P=s-f<2BWH_U9H*Fq$(LKHrb*ong+Bt0$pUwAi0kTJsL`Y$2- zV-MWNm4at^033)WXd{RvNQ(Pm3?N=<`uEfIw~~aBv5g(Vg5S>GLDf<J@6-7QNmQgf zlDvHwc9+i}DSsA3<MC#qa=?!^vxEK&nrA`RAD2YsB_D03@6|I%{?&b;({ba+HBphg zND}j5^f8}V^RKQ&c%?fS{h=pOQLIOQrc>9>EO#RH_jtolA)iRJ>tSfJpF!#DO+tk% zBAKCwVZwO^p)(Rhk2en$XLfWjQQ`ix>K}Ru6-sn8Ih6k&$$y`zQ}}4dj~o@9gX9_= z#<!b)PJX7r5EUA7^jB6Od_>~EkchJqd5$**l}~~6mOl(q#GMIcFg&XCKO;$w>!K14 zko1egAORiG{r|8qj*FsN>?7d`han?*MD#xe^)sOqj;o;hgdaVnBH$BM{_73?znS+R z*G2VHM!Jw6#<<Msx_|T}KQ4vp{)aSZJ`7HUQ>FfJ-J%-9AuDW$@mc-Eyk~F{Jbvt` zn;(%DbBDnKIYr~|I>ZTvbH@cxUyw%bp*)OSs}lwO^HTJ2M#u5QsPF0?Jv*OVPfdKv z+t$Z5P!~jzZ~Y!d#iP?S{?M_g%Ua0Q)WawbIx+2uYpcf(7Im%W=rAu4dSceo7RZh# zN38=RmwOJQE$qbPXIuO^E`wSeJKCx3Q76irp~QS#19dusEVCWPrKhK9{7cbIMg9U} TZiJi*F`$tkW<p)b$p8Kiq>Ln) literal 63375 zcmb5VV{~QRw)Y#`wrv{~+qP{x72B%VwzFc}c2cp;N~)5ZbDrJayPv(!dGEd-##*zr z)#n-$y^sH|_dchh3@8{H5D*j;5D<{i*8l<n`R`94An31eIWbisdMSBvMo=KdzZu#! z2=IUVG7$V4U%UUmhH^skQsQDNstj`C4{}qJvNH4x^YAkCG&57PP0CD5tUr(Lr|8F| zrsbw-rRacR&cjU84vV#^0hr{ahs87@nB*8}#Ta+ach127GUL}I|L4%azP25lE&lDO z{@DihA2t@wMy9rA|5sDgzngkE8#y|fIse-(VW+DelrTU*`j|jKH2?E168}A!#$SIR zXJlp1U}9_J;*z5Y>5IFJ|DjL!e)upfGNX(kojugZ3I`oH1PvW`wFW_ske0j@lB9bX zO;2)`y+|!@X(fZ1<2n!Qx*)_^Ai@Cv-dF&(vnudG?0CsddG_&Wtae(n|K59ew)6St z#dj7_(Cfwzh$H$5M!$UDd8=4>IQsD3xV=lXUq($;(h*$0^yd+b{qq63f0r_de#!o_ zXDngc>zy`uor)4A^2M#U*DC~i+dc<)Tb1Tv&~Ev@oM)5iJ4Sn#8iRw16XXuV50BS7 zdBL5Mefch(&^{luE{*<o)$0CtHMXCiFaqU;N{t<$9@JbXquVr@cf{y~BNB(J5=Tji zlK?_g|E;1zl$VJ=#ZmElT~Y6jy-|?2PUv}kl<0irKUHY7@2t={_gVdY)lv8kM+ad9 zC<O%>5qtCZk$oFr3<io|2$Itc(&(T+V0vhN)K$Fl^c3u8y`}{@R7L#c1&Qu_+u$L| zkw6sZeUEd0xxV1r@X7Bj^XUCX<ecNL?GSk}zL!>RH=H!c3wGR=HJ(yKc_re_X9pD` zJ;uxPzUfVpgU>DSq?J;I@a+10l0ONXPcDkiYcihREt5~T<to{?YLB3#Ek~Bd_FRTK z3SVU)NWfW~bevBhSgga`J`3XaEJ;UR&tR-QNI#e+fX1mkLg(kYRIlBUeP!g)rVvkV zmBQF>5Gb}sT0+6Q;AWHl`<y=xe2MOa)>S5dV>lv%-p9l#xNNy7ZCr%cyqHY%TZ8Q4 zbp&#ov1*$#grNG#1vgfFOLJCaNG@K|2!W&HSh@3@Y%T?<RDDZ2kvE4KZX_tTk{8@Y z+1Qu}v&0qF!3ps~B5R6-#N&o4vQEcX3!~lWKK-JjRoUbPQR)>3YI75bJp!VP*$*!< z;(ffNS_;@RJ`=c7yX04!u3JP*<8jeqLHVJu#WV&v6wA!OYJS4h<_}^QI&97-;=ojW zQ-1t)7wnxG*5I%U4)9$wlv5Fr;cIizft@&N+3<m!sp`}{5>2O%B{R1POm$oap@&f| zh+5J{>U6ftv|vAeKGc|zC=kO(+l7_cLpV}-D#oUltScw})N>~JOZLU_0{Ka2e1evz z{^a*ZrLr+JUj;)K&u2CoCAXLC2=fVScI(m_p~0FmF>>&3DHziouln?;sxW`NB}cSX z8?I<poVWwH93~xX>sJB)Z=aYRz!X=yJn$kyOWK%rCYf-YarNqKzmWu$ZvkP12b4qH z<cj_@_^h^p^q&$rHm}tFrF$o@p+N@Luju~MbeZxq_WbMvMAonH{#8FcaQx#1Ex963 zthr*D;hp#t`U%;8Lw{en#r&PBH>hS9Q>j<}(*frr?z<%9hl*i^#@*O2q<G8@m-E{I z`}pP(W$_?tQz?qiq)AkeSb{O1HEI<O&IPY2fz^)h2U5WFf)$o|GVN9!>(Z^CN)c2c z>1B~D;@YpG?G!Yk+*yn4vM4sO-_!&m6+`k|3zd;8DJnxsBYtI;W3We+FN@|tQ5EW= z!VU>jtim0Mw#iaT8t_<+qKIEB-WwE04lBd%Letbml9N!?SLrEG$nmn7&W(W`VB@5S zaY=s<l}}fvx=2PUlRXVFqYw_pix_=MLAKV-vfffnNa-G}V}-DjqeGu81{_6c7DT4* zgNTK&HNdPkT}|m;Wopt-pwH(=vK!Mcs#L3p7EuhKtdS*$(gi7K6)2mt;vO}}@U2?@ zic8*RBj6lGpirRD%IH>Ew2}i@F_1P4OtEw?xj4@D6>_e=m=797#hg}f*l^`AB|Y0# z9=)o|%TZFCY$SzgSjS|8AI<m~)~<LWT=KD$snpvb;<|raYO=8NN=pEex{aVNGen|i z4hGyCiz+M`>-%J4x}J)!IMxY3_KYze`_I=c1nmrk@E8c9?MVRu)7+Ue79|<R7R(*W zmGI9WxS<;F_rj?)6ZJ2+&*@e<mlh^Wi>)rBX7tVB7U|w4*h(;Gi3D9le49B38`wuv zp7{4X^p<CFK*NrFla6?I(q;<C*K@ag4>+K4*$@gU(Tq3K1a#3SmYhvI42)GzG4f|u zwQFT1<JTz}_6=eHFU^e2CZtm7+S~2?G10jrHLa$Yc>n_=n|jpi=70-yE9LA+d*T8u z`=VmmXJ_f6WmZve<c3j)L*cT@L>ZPct$Cgu^~gFiyL>Lnpj*6ee>*0pz=t$IJ}+rE zsf@>jlcG%Wx;Cp5x)YSVvB<GcbWPQ65t~gc{a(L|Y**_KX&N^LV{4p;>1$yyY1l&o zvwX=D7k)Dn;ciX?Z)Pn8$flC8#m`nB&(8?RSdBvr?>T9?E$U3u<MGKL6<gI3+cigX zr2;7xjAPPdw|q3|5<Av+0yh@5pePF?so63EF4(f;!m<(9QF+GK>IX7T?$v4dWCa46 z+&`ot8ZTEgp7G+c52oHJ8nw5}a^dwb_l%MOh(ebVj9>_koQP^$2B~eUfSbw9RY$_< z&DDWf2LW;b0ZDOaZ&2^i^g+5uTd;GwO(-bbo|P^;CNL-<vp1D1$R<L}_zoyFQ(?^n zl`6VAFTjED$Nit=axARyg>%?9mRmxEw~5&z=X^Rvbo^WJW=n_%*7974RY}JhFv46> zd}`2|qkd;89l}R;i~9T)V-Q%K)O=yfVKNM4Gbacc7AOd>#^&W&)Xx!Uy5!BHnp9kh z`a(7MO6+Ren#>R^D0K)1sE{Bv>}s6Rb9MT14u!(NpZOe-?4V=>qZ>}uS)!y~;jEUK z&!U7Fj&{WdgU#L0%bM}SYXRtM5z!6M+kgaMKt%3FkjWYh=#QUpt$XX1!*XkpSq-pl zhMe{muh#<vd{NzT8hJO~2nwSu@|uKui`Q8EdXeGz4>knk{9_V3%qdDcWDv}v)m4t9 z<k^O7as2~K;#kz6&_j;+XcIB_r9LslJ=plZ802GD7!wKurp5N7C0N7MrBiyAL~c=u zE%@soR=E%Ksd7<Rzkb}c1=?E^tRZO%BD}eh;$H);oB)^Nt6e4N2J+}eE=O>Qhv{;} zc{}#V^N3H>9mFM8`i`0p+fN@GqX+kl|M94$BK3J-X`Hyj8r!#x6Vt(PXjn?N)qedP z=o1T^#<s;C9Ui_c^t!}2S-XqPF?-?4;fe4415B~F0>?1^a{;bZ&x`U{f?}TMo8ToN zkHj5<VbXBbPLm`saJ%OL;G18~%@f$_blKkP1#<P0FY;5DtZHS)$u-A?Yn3SA3J@bT zA1d!HbKV+f1Ugw07K&jwzua_~#;P<Rn>v|}r}wDEi7I@)Gj+S1aE<Lr;qg@51w32$ zyxn{bK>-GdnLN+$hw!=DzglMaj#{qjXi_dwpr|HL(gcCXwGLEmi|{4&4#OZ4ChceA zKVd4K!D>_N=_X;{poT~4Q+!Le+ZV>=H7v1*l%w`|`Dx8{)McN@NDlQyln&N3@bFpV z_1w~O4EH3fF@IzJ9kDk@7@QctFq8FbkbaH7K$iX=bV~o<VCiV&YRTZ}?C^!Fu2yC) zv{Vzb(sB&ct#XXgvg1<Aax>#gfh?2JD6lZf(XP>~DACF)fGFt)X%-h1yY~MJU{nA5 ze2zxWMs{YdX3q5XU*9hOH0!_S24DOBA5usB+Ws$6{|AMe*joJ?RxfV}*7AKN9V*~J zK+OMcE@bTD>TG1<D&k;gXJl_GYh`aH;$ZLob;4%Of6;ZSs-6Ri5E?%yZ1lwjNo$M0 zh+s;*GL1qh63T)l8*vTt!qBLZ)~cQ14>*yc?*qGqjBN8mgg@h1cJLDv)0!WRPIkC` zZrWXrceVw;fB%3`6kq=a!pq|hFIsQ%ZS<kf2ia2#pBvu`A3V%+`AJvHB*NUK3~nQF zw*gxnx7LCX(Z^1w*|SqdvT{$S%V#1K_mVQ7La-Aw%y<w}ejK@Lu|-CGm40~>lo~)D z|64!aCnw-?>}AG|*iOl44KVf8@|joXi&|)1rB;EQWgm+iHfVbgllP$f!$<xMKNPGw z75lQ-&s?W5309;y6gIrMn!YgKCh2h_t)HK6EcT@xYc0sgM!#>Wf42%NO5b(j9Bw6L z;0dpUUK$5GX4QbMlTmLM_jJt!u<VK-KUt7Z%d43gTkafnEz;tKrLF`kq7eb@)^GVH zVzlnCl^>r`_0~$b#BB7FL*%XFf<<YlClUogc56^3Yyh4jgqXW7(#Qu|X^(|f$!!nL zr<Jlyt{`j<%HJ7(Ibr+qi51D$ikY1it_}mi&OTSv%-y{FbY?e9I<zP))1O}CdnlMB z)E{0F(+ck9%;u_OGgFgau=Rw8qE6u}01y?;f@M5NLv*P|4@P3@#u%P9aWCL)&PJT| zX@dygu5XWA26#e~n6RWn&*Bl^^VBtoVJBn^bDnW4mHo4ME6_YI9>b__1o)Ao<oAII zl<ghkn)lbTvrX_mEpa~6_wy3!knhoEQy$s)O&Eje&DuVJ{~mIy!7WXiU&-a=SC+^7 zzq_L1{|UJN-6?C-bu@6*&_3i@#`~C#P@p9X(Ce2%iic!mTBMYuD`LZ<OM}*McxA(w zkj(d|!1fegueE#LwG9egYdYR8KktNowE4+1AfZ@IuxN3gT>3rlobbN8-(T!1d<VYe z=uu*dc`@_NH-vid1r!+qd!W<p6Hp2sR=vY4yh`?ujy)PePx7Y^!w{->-bR8D3S0@d zLI!*GMb5s~Q<&sjd}lBb8Nr0>PqE6_!3!2d(KAWFxa{hm`@u|a(%#i(#f8{BP2wbs zt+N_slWF4IF_O|{w`c~)Xvh&R{Au~CFmW#0+}MBd2~X}t9lz6*E7uAD`@EBDe$>7W zzPUkJx<`f$0VA$=>R57^(K^h86>09?>_@M(R4q($!Ck6GG@pnu-x*exAx1jOv|>KH zjNfG5pwm`E-=ydcb+3BJwuU;V&OS=6yM^4Jq{%AVqnTTLwV`AorIDD}T&<zk=U4_F z%akElkXp@CbeS<cl%y^#t}u_*o+Kw^Xa%!S>jWr8pB&j28fVtk_y*JRP^t@l*($UZ z6(B^-PBNZ+z!p?+e8@$&jCv^EWLb$WO=}Scr$6SM*&~B95El~;W_0(Bvoha|uQ1<y zI;g~pq<puh8JAZSg`e`{9Ul}WlQxSt?3%o&hA!;)cXW-;B<UPjMu}?EtHvVS7g>T< zO$%_oLAwf1bW*rKWmlD+@CP&$ObiDy=nh1b2ejz%LO9937N{LDe7gle4i!{}I$;&Y zkexJ9Ybr+lrCmKWg&}p=`2&Gf10orS?<wSRKh%(i*-EzBy^*(nk#EV0x%s+gVr5#i zF*^yn?NFz@z)jkaF%P~*zrnDtj18`Mit$=8TVU0_Xu0XQT-29W)`{}4Y{_WLO}la2 z3kum*Acd(?w(30MQ0iXECV4}56Baro5eg?Ji{&xv>4$Vr<ApIaAwLyRgnDz_63EnQ zb0F~DwJxa8Y6V&P@8Y;IWU23PX|5YXwRO5>zWidT=*6{KzOGMo?KI0>GL0{iFWc;C z+LPq%VH5g}6V@-tg2m{C!-$fapJ9y}c$U}aUmS{9#0CM*8pC|sfer!)nG7Ji>mfRh z+~6CxNb<thuojmgyDIx-O?L~|1OMp?{&5*5nw(NYRF76i1VE!yuFbdk^SXpYh9d!e zisi>>6eWKMHBz-w2{mLL<sWnSR{lp+GVAVGNcs2U?&%}ZbUT({ThKL33h5&godIvq z#4SFCl~dpzw{Kf9GWC*<(5@{J-YWs96Ulo#)6da2L@e?NLIhPLoWud(Gbix6rPhyM z+#ezG31H`whsp_@rDLe9hoK&0hz}tS!3q2%y1yY-p%>wdA7dA-qfTu^A2yG1+9s5k zcF=le_UPYG&q!t5Zd_*E_P3Cf5<i9lV%B>T6821bO<oZ<I;eq^g7*0L=5+o%xOyh3 zV}b+qIu^3vM+=S`g6~mUfaz2O^0b~+Y02%irk{L(|9!#otC{hV00sh*`O?q-K|B9x zc@lEAaI-VBcNOzAF>`daa`;DODm8Ih8k89=RN;-asHIigj`n=ux>*f!OC5#;X5i;Q z+V!GUy0|&Y_*8k_QRUA8$lHP;GJ3UUD08P|ALknng|YY13)}!!HW@0z$q+kCH%xet zlWf@BXQ=b=4}QO5eNnN~CzWBbHGUivG=`&eWK}<gH9L&>beuV*;?zt=P#pM*eTuy3 zP}c#}AXJ0OIaqXji78l;YrP4sQe#^pOqwZUiiN6^0RCd#D271XCbEKpk`HI0IsN^s zES7YtU#7=8gTn#lkrc~6)R9u&SX6*Jk4GFX7){E)WE?pT8a-%6P+zS6o&A#ml{$WX zABFz#i7`DDlo{34)oo?bOa4Z_lNH>n;f0nbt$JfAl~;4QY@}NH!X|A$KgMmEsd^&Y zt;pi=>AID7ROQfr;MsMtClr5b0)xo|fwhc=qk33wQ|}$@?{}qXcmECh>#kUQ-If0$ zseb{Wf4VFGLNc*Rax#P8ko*=`MwaR-DQ8L8V8r=2N{Gaips2_^cS|oC$+yScRo*uF zUO|5=?Q?{p$inDpx*t#Xyo6=s?bbN}y>NNVxj9NZCdtwRI70jxvm3!5R7yiWjREEd zDUjrsZhS|P&|Ng5r+f^kA6BNN#|Se}_GF>P6sy^e8kBrgMv3#vk%m}9PCwUWJg-AD zFnZ=}lbi*mN<K#(vlYbGZAX^KQmjvAYCRG*UOU`z2$j+74AdgXr3(r`Z*t~vhyGOF z)w@e8rCo#wjxU`Xq#TN0kURQy8Y45b@jCRNbbQi7ac)K;Y9F%JPMNFNffNKTTeU*T zHQTmYG^Gu1I@&Jv`71fu(BSKE_ZcDAC6eM{-i#Ce{raky!z_b9d|h7zARvnW>-AOm zCs)r=*YQAA!`e<R&0)*Xk7%|k&^;uv62@(5&ac_hW*F9=TfvBeS~Qh~EX`oba74cG z_zl_hTH19>#1N>aHF=bb*z*hXH#Wl$z^o}x##ZrUc=kh%OHWhp=7;?8%Xj||@V?1c ziWoaC$^&04;A|T)!Zd9sU<cT<Lad$0pGXX1w=fLRLa7aSLO9sinK2%NmW<mIFjiuc z-cT9?*>zE&$ODyJ<B|PnBKliB6c94vLSghm91pGb$1o^7rM2a&%c}D$u}j(J@zRz# zi%s0i4BD9?+o@$HB_##NjTPLR3oh&PgIxvX>aBpvqsw19Uiuq{i#VK1!htkdRWBnb z`{rat=nHArT%^R>u#CjjCkw-7%g53|&7z-;X<Ac^=g(0g1=gRkv{@6{)+2MuRw4?q zSyffm46G$5&03=o2M%0CNA&bH8`|Q+lj*sOSA!_VPI<qibefjTL~ySR5|HpXSu-Wk zjm)E}CNtR?XF>+ewb?OLWiV|#nuc8mp*LuGSi3IP<<*Wyo9GKV7l0Noa4Jr0g3p_$ z*R9{qn=?IXC#WU>48-k5V2Oc_>P;4_)J@bo1|pf=%Rcbgk=5m)CJZ`caHBTm3%!Z9 z_?7LHr_BXbKKr=JD!%?KhwdYSdu8XxPoA{n8^%_lh5cjRHuCY9Zlpz8g+$f@bw@0V z+6DRMT9c|>1^3D|$Vzc(C?M~iZurGH2pXPT%F!JSaAMdO%!5o0uc&iqHx?ImcX6fI zCApkzc~OOnfzAd_+-DcMp&AOQxE_EsMqKM{%dRMI5`5CT&%mQO?-@F6tE*xL?aEGZ z8^wH@wRl`Izx4sDmU>}Ym{ybUm@F83qqZPD<I_<D@SDBXpcm$%pP;@}1x+1rECR~6 z%mPO96ZtCMfz6TZL_tB_o<jX(0%{4O*=Jpf{(}rOT%n6FF#H{^%{gCRk)ccFmy zlAyZVmLT4N#~F)~@`1bcBU<gu4>6nFm?t?(7>h*?`fw)L3t*l%*iw0Qu#?$5eq!Qc zpQvqgSxrd83NsdO@lL6#{%lsYXWen~d3p4fGBb7&5xqNYJ)yn84!e1PmPo7ChVd%4 zHUsV0<QfI}<M8O`g)!{5VcjkDZIjCu8(aqo6;;=sPlL7o>Mh?VpzZD=A6%)Qrd~i7 z96*RPbid;BN{Wh?adeD_p8YU``kOrGkNox3D9~!K?w>#kFz!4lzOWR}puS(DmfjJD z`x0z|qB33*^0mZdM&6$|+T>fq>M%yoy(BEjuh9L0>{P&XJ3enGpoQRx`v6$txXt#c z0#N?b5%srj(4xmPvJxrlF3H%OM<X=kF451d5XRpaI3Rddya;o<MiVe63o}q9!6}_c zo)Za~rjO%XWDn6$-;t})ZmU#rhSPD)qiCJFwO-$XixQk0X*gbZ^iyuL^ft*8RskMZ z61oYTT##Iok;Rg+0anh212gV|jFfog*GZX}VV7x@cwuYn2k0l|CdXJ3M&=>B!jvfy z;wx8RzU~lb?h_}@V=bh6p8PSb-dG|-T#A?`c&H2`_!u+uenIZe`6f~A7r)`9m8atC zt(b|6Eg#!Q*DfRU=Ix`#B_dK)nnJ_+>Q<1d7W)eynaVn`FNuN~%B;uO2}vXr5^zi2 z!ifIF5@Zlo0^h~8+ixFBGqtweFc`C~JkSq}&*a3<b*AGX+4JAVcr=k1@(BfrL*bH3 zB2tsVQA!i($9n4x3TKj4fyB9v6dVeLF9ce$&KiuST#O+L;`7)j^T{2s!k-fHs3AFL z;*i&)+V}HhjAA_Rcq9bBAlY`@fUE4EXY~}ibwoho??7zC!;EPmIuC?iA|=eX-ry23 zydv?^AaCLg6^~XLVJgXk5t3-5-l5#+-WH4#R6H+-pH>C}L?b5Mh-bW=e)({F_g4O3 zb@SFTK3VD9QuFgFnK4Ve_pXc3{S$=+Z;;4+;*{<o#P)-O8F)a#4K`1Xm|~?q)i|U3 zYQ`j;(xom@I4xe9dA2S6y-d+xYe;^;M{B3B`KM&`C&=Gb<o8unUCEbv9DNO{|Er29 z8aca|Ig>H}Rc;845rP?DLK6G5Y-xdUKkA6E3Dz&5f{F^FjJQ(NSpZ8q-_!L3LL@H* zxbDF{gd^U3uD;)a)sJwAVi}7@%pRM&?5IaUH%+m{E)DlA_$IA1=&jr{KrhD5q&lTC zAa3c)A(K!{#nOvenH6XrR-y>*4M#DpTTOGQEO5Jr6kni9pDW`rvY*fs|ItV;CVITh z=`rxcH2nEJpkQ^(;1c^hfb8vGN;{{oR=qNyKtR1;J>CByul*+=`NydWnSWJR#I2lN zTvgnR|MBx*XFsfdA&;tr^dYaqRZp*2NwkAZE6kV@1f{76e56eUmGrZ>MDId)oqSWw z7d&r3qfazg+W2?bT}F)4jD6sWaw`_fXZGY&wnGm$FRPFL$HzVTH^MYBHWGCOk-89y zA+n+Q6EVSSCpgC~%uHfvyg@ufE^#u?JH?<73A}jj5iILz4Qqk5$+^U(SX(-qv5agK znUkfpke(KDn~dU0>gdKqjTkVk`0`9^0n_wzXO7R!0Thd<OO)*@xLj!dA|^KI{(+g5 z4&&;v3+^PaBya7Rnu#!)XYc}vIWqv)^MY!O)bd!?B<}^dB*bn^DfNh`{LBe@BaZ7K z79Vu@{$pu8y#gTfUJ?t()owinp0&lUvSWm~f6lhfPNSF&`a(>@S;U`y)VVP&mOd-2 z(hT(|$=>4FY;CBY9#_lB$;|Wd$aOMT5<N7HW=#J5xiuClp{tnl<jC$q#gWfwjqeAY zV;sA^S=5DG9oD|_sR@+2OPrAQibqT{OGVV96@Akgvd57K5T@^KQN}?9VsiR^`m+&4 z6Wo=&#vs$B<Y9Yj#aZVD^shN}siQ$PUDTmt>O_3}DYXEHn&Jrc3`2JiB`b6X@EUOD zVl0S{ijm65@n^19T3l%>*;F(?3r3s?zY{thc4%AD30CeL_4{8x6&cN}zN3fE+x<9; zt2j1RRVy5j22-8U8a6$pyT+<`f+x2l$fd_{qEp_bfxfzu>ORJsXaJn4>U6oNJ#|~p z`*ZC&NPXl&=vq2{Ne79AkQncuxvbOG+28*2wU$R=GOmns3W@HE%^r)Fu%Utj=r9t` zd;SVOnA(=MXgnOzI2@3SGKHz8HN~Vpx&!Ea+Df~`*n@8O=0!b4m?7cE^K*~@fqv9q zF*uk#1@6Re_<^9eElgJD!nTA@K9C732tV~;B`hzZ321Ph=^BH?zXddiu{Du5*IPg} zqDM=QxjT!Rp|#Bkp$(mL)aar)f(dOAXUiw81pX0DC|Y4;>Vz>>DMshoips^8Frdv} zlTD=cKa48M>dR<>(YlLPOW%rokJZNF2gp8fwc8b2sN+i6&-pHr?$rj|uFgktK@jg~ zIFS(%=r|QJ=$kvm_~@n=ai1lA{7Z}i+zj&yzY+!t$iGUy|9jH#&oTNJ;JW-3n>DF+ z3aCOzqn|$X-Olu_<wOD+V1cxb0Z}9)qPN6k=yG%7N(OXSN(!|;<~~&ZV7<|dWJ*$O zcc8BYF-@yY+0BQ2=@gx;O-;QS>p7brzn`uk1F*N4@=b=m;S_C?#hy{&NE#3Hk<sC+ z@RVY+px5c26lyz%OfzZTn@(3s>ATrg?enaVGT^$qIjvgc61y!T$9<1B@?_ibtDZ{G zeXInVr5?OD_nS_O|CK3|RzzMmu+8!#Zb8Ik;rkIAR%6?$pN@d<0dKD2c@k2quB%s( zQL^<_EM6ow8F6^wJN1QcPOm|ehA+dP(!>IX=Euz5qqIq}Y3;ibQtJnkDmZ8c8=Cf3 zu`mJ!Q6wI7EblC5RvP*@)j?}W=WxwCvF3*5Up_`3*a~z$`wHwCy)2risye=1mSp%p zu+tD6NAK3o@)4VBsM!@);qgsjgB$kkCZhaimHg&+k69~drbvRTacWKH;YCK(!rC?8 zP#cK5JPHSw;V;{Yji=55X~S+)%(8fuz}O>*F3)hR;STU`z6T1aM#Wd+FP(M5*@T1P z^06O;I20S<pPBYLx^KQ-E#4lJKf0#2<$Urm^J75xe^_~ooFOaniz#EWEnAqL5nl;d z;Y?#EUwvbZHb_{bP#Z+Xi6;``%`1xT4(Qh>k!bxW<-O;E081KRdHZrtsGJflFRRFS zdi5w<L%xAIZMaxEN{|sC`S2LX=HNoo7yNMxu?JQZn!#EHpMVSC`Z-rSU>9OVDGSL3 zNrC7GVsGN=b;YH9jp8Z2$^!K@h=r-xV(aEH@#JicPy;A0k1>g1g^XeR`YV2HfmqXY zYbRwaxHvf}OlCAwHoVI&QBLr5R|THf?nAevV-=~V8;gCsX>jndvNOcFA+DI+zbh~# zZ7<oMFIjT?dRB+;KT%*|Gjj)Lv;R$(lsDCpKH})P;^<HgAW$|Ic$UC!!9k_^)<VFb z+R-4(+=Oiwvgpt>`qNk&w+_+Yp!}j;OYxIfx_{f0-ONc?mHCiCUak=>j>~>YR4#w# zuKz~UhT!L~GfW^CPqG8Lg)&Rc6y^{%3H7iLa%^l}cw_8UuG;8nn9)kbPGXS}p3!L_ zd#9~5CrH8xtUd?{d2y^PJg+z(xIfRU;`}^=OlehGN2=?}9yH$4Rag}*+AWotyxfCJ zHx=r7ZH>j<rs-kbQ;s$ZI)B{YCAt<1f8=Z!C#+cW@(f}Vui2`~bhsJNt4X5FEVH#V zmS~5qafT)ZOfofB3RY^p$qiO+hKg5MB@4BiWOlTuD_ywdEG^^`73sk%6$@P{w!m`d zG%&#}O$F6xyMIL5Ey>2kV?%7WTtp+-HMa0)_*DBBmC{sd$)np&GEJ__kEd`xB5a2A z*J+yx>4o#ZxwA{;NjhU*1KT~=ZK~GAA;KZHDyBNTaWQ1+;tOFFthnD)DrCn`DjBZ% zk$N5B4^$`n^jNSOr=t(zi8TN4fpaccsb`zOPD~iY=UEK$0Y70bG{idLx@IL)7^(pL z{??Bnu=lDeguDrd%qW1)H)H`9otsOL-f4bSu};o9OXybo6J!Lek`a4ff>*O)BDT_g z<6@SrI|C9klY(>_PfA^qai7A_)VNE4c^ZjFcE$Isp>`e5fLc)rg@8Q_d^Uk24$2bn z9#}6kZ2ZxS9<C46&Y+Q7nYM#)S{~e<-0SXbx^w1jyAP0t!{t{i)+bD@w$9YAlUQVZ z1TZ|^=9cLiz;Bipmt#c?%u(c5s;}6EMb|KG%X+!BskufNDiLAbfcJAi-eKFCylmQ6 zcLgpiYS;T5u|4vj(43@Xs-;?LT?Reu-O1voTo*8Sg!T${N!fhDdj5F-jP4kcswNTc zUPNlqr9(p*&QkY(6{Uw9+-&ZY^AVhuru!iEZSXWk{J62Y8RTWl#jvm?@UsOLN*n1U z!!2c97^PYdYbw;1W(h-dY_NJ_bbOqzz80YwLA6En%W5F}=@a-dB;!cvFG55bE7@zZ zf}Zz=u;({6%w-qMyr7YLW0H?0K>sI(RqT7?El2@B+($>eBQrNi_k#CDJ8D9}8$mmm z4oSKO^F$i+NG)-HE$O6s1--6EzJa?C{x=QgK&c=)b(Q9OVoAXYEEH20G|q$}Hue%~ zO3B^bF=t7<z$Rj(z@}-%hhp0KDg5g-Vvj!qOr85&aqTpaaojC^CwQZHKk%N1&RJ@? z3@mmU8UkLd^u+>t48sN<h@~F@WN(LX`%4J3P$~sLqIq2q^WYYan1y*WKS{^KXRSVj zlRp2YD0*vmi}GIu(VMSMj`)AFtcV!7m`T~YnAy8nxmvlKskk~@*;{;3?|-#CT^;_> zWh_zA`w~|){-!^g<vJDMm4#3w(!Hhyj3dofOB57x=Mu^T@6Gt<KN~lv>?6Mqf6ieV zFx~aPUOJGR=4{KsW7I?<=J2|lY`NTU=lt=%JE9H1vBpkcn=uq(q~=?iBt_-r(PLBM zP-0dxljJO>4W<w&)Z{UhZ0!m()I68e=px8_4B`37AI|bCZuMk_SVKAQz?8+4(l0C) z<3()qDfD9UTW*wnelf4D7bR(}=TB;gs;ds+7QE~CAQ*jDKKADDC`3G?7kn$!=a5d& z?I(JT9>q-;stY)CLB4q`-r*T$!K2o}?E-w_i>3_aEbA^MB7P5piwt1dI-6o!qWCy0 ztYy<q;G5p>!x9arGTS?kabkkyv*yxvsPQ7Vx)twkS6z2T@kZ|kb8yjm+^$|sEBm<L zGtKcNM?a1<P1GHe%USdss^9iYmKI=GuiV`dL*Z(*)<W%!5IIDyJ!oJjHJOEa1m1VQ zKco1NMHn5?h{5SRY#VFF?T!bo5_IIEbO;WfqdSQACJa+&8o3bgw;L^BimN?NlN(v) zotn;%myS`DPUIQ+7RCnB)mY`2o&e;1Xh962y`p4wurO(bDXEWXms!a&F9;L0^G^Mo zh1W&LQdXhd1KHjKV}xwOkQ>vACeqbz)RmxkkDQX-A*K!YFziuhwb|ym>C$}U|J)4y z$(z#)GH%uV6{ec%Zy~AhK|+GtG8u@c884Nq%w`O^wv2#A(&xH@c5M`Vjk*SR_tJnq z0trB#aY)!EKW_}{#L3lph5ow=@|D5Lz<fcUCo&Ka|9|4HGWHH0_J4ujUnr>JYUFD6 z7XnUeo_V0DVSIKMFD_T0AqAO|#VFDc7c?c-Q%#u00F%!_TW1@JVn<z*P@k#}SDu4q z5BK|xV6S3>sfvm@_9HKWflBOUD~)RL``-!P;(bCON_4eVdduMO>?IrQ__*zE@7(OX zUtfH@AX*53&xJW*Pu9zcqxGiM>xol0I~QL5B%Toog3Jlenc^WbVgeBvV8C8AX^Vj& z^I}H})B=VboO%q1;aU5ACMh{yK4J;xlMc`jCnZR^!~LDs_MP&8;dd@4LDWw~*>#OT zeZHwdQWS!tt5MJQI~cw|Ka^b4c|qyd<d8BjG@CVcx~A0@_+-3ySS5}V#nYxqHn&dJ z3huaTsOBL$pM0~v6%?s%@?17;o|*#UY1tt-m0po1{B8Xt+V4%@*4l_1x6MTTu=i^t zEF!^0`A{SAgixqmbf=fe`Q#RQV7q0JEE%qC5Cl7U3dvP`CnnYy>_ly(+Ql2m&AAw^ zQeSXDOOH!!mAgzAp0z)DD>6Xo``b6QwzUV@w%h}Yo>)a|xRi$jGuHQhJVA%>)PUvK zBQ!l0hq<3VZ*RnrDODP)>&iS^wf64<Gan-0fT=xEEaI^H)!ok-sB8re6ozEmX5c@6 zvzFx43)HzN8|btxEr_+m_ES??hMpoBdA+u`<Ko)3jSDsJ<bNahp^L1kFKCk01nKG# zd~B+qtlfL5f8$8ToxOxz!oqk&<wEbF*v1K2QV8d>C;MGqDvx>|p;35%6(u+IHoNbK z;Gb;TneFo<v+>*`zUKS6kwF*&b!U8e5m4YAo03a_e^!5BP42+r)LFhEy?_7U1IR<; z^0v|DhCYMSj<-;MtY%R@Fg;9Kky^pz_t2nJfKWfh5Eu@_l{^ph%1z{jkg5jQrkvD< z#vdK!nku*RrH~TdN~`wDs;d>XY1PH?O<4^U4lmA|wUW{Crrv#r%N>7k#{Gc44Fr|t z@UZP}Y-TrAmnEZ39A*@6;ccsR>)$A)S>$-Cj!=x$rz7IvjHIPM(TB+JFf{ehuIvY$ zsDAwREg*%|=>Hw$`us~RP&3{QJg%}RjJKS^mC_!U;E5u>`X`jW$}P`Mf}?7G7FX#{ zE(9u1SO;3q@ZhDL9O({-RD+SqqPX)`0l5IQu4q)49TUTkxR(czeT}4`WV~pV*KY&i zAl3~X%D2cPVD^B43*~&f%+Op)wl<&|D{;=SZwImydWL6@_RJjxP2g)s=dH)u9Npki zs~z9A+3fj0l?yu4N0^4aC5x)O<N_(0*g4u)%5Tt4@gHE>snm0qrhz@?nwG_`h(71P znbIewljU%T*cC=~NJy|)#hT+lx#^5MuDDnkaMb*Efw9eThXo|*WOQzJ*#3dmRWm@! zfuSc@#kY{Um^gBc^_Xd<M_=Opb*sV>xnl!n&y&}R4yAbK&RMc+P<gSSGsa9{ngu3h za2rxBU6lA9Q9VAy<_CQ=#9?ge+|8rFr3YI44QC0@KPf?KG3#CkaUontfvoWcA#`fT zUZ-M@9-{1Ei|?wN2X<<LG$En}QHwMqs=8ZuZNc+NsKkIl=}k#BjOIG2xpH6pY<h{d zJ7c4SQ-wCPPp+Ave;R605<i{lO4KXOUo>^Ti;YIUh|C+K<WCtgj)+#X5!{~T0amf) zA{NO!xG0_A(b+3`Y%~$@K6*;z4@GJOlO9iW_I)Uf=v75p{Zaa%riIlQ1XqxqD1P*v zC_nl;^-H^oHskLi&AkX0pf_;|=*Q=gaUudCp%zN>1|=Z^{nZ}}rxH*v{xR!i%qO~o zTr`WDE@k$M9o0r4YUFFeQO7xCu_Zgy)==;fCJ94M_rLAv&~NhfvcLWCoaGg2ao~3e zBG?Ms9B+efMkp}7BhmISGWmJsKI@a8b}4lLI48oWKY|8<gk-*;t9-{k%FCJZFy<gM z@C~rOBUWWT##Z+g3*3Vzs8fuTtjp`u#+{x*gRagQ8={zUb)t|^B2y%Lt=XH5-VU*g zu-s*8g`Ceku&#kTTsG4pdKc+Q1?Ns^+`Anuzw^Kt@dXzw8(rtBy~EfPkytdOlMc6V z+PjsVo1fq23ba`d{M8JQ|H)T-V`Ygmnsk8K`>?zuuNc$lt5Npr+<T4KxJJ<bPDeY< zV$Y5gj%daxmn&XvpKy&xAedNSRNzj*+uARZbEwx*_BW(K#OMC!{`XgH-y>p7a#sWu zh!@2nnLBVJK!$S~>r<AjX6^_+fORZ96soQxKn~@)BfuHDd$;Hq1kJ%oj=cQPA05n| zlDech7|+hqRvU>2-pN||^w|fY`CT{TFnJy`B|e5;=+_v4l8O-fkN&UQbA4NKTyntd zqK{xEKh}U{NHoQUf!M=2(&w+eef77VtYr;xs%^cPfKLObyOV_9q<<ILDt_So;x8tA z{AwHiN2#Wqm5a+41^y+oU(NG>(%76-J%vR>w9!us-0c-~Y?_EVS<!Xa#y}`2>%v!* z15s2s3eTs$Osz$JayyH|5nPAIPEX=U;r&p;K14G<1)bvn@?bM5kC{am|C5%hyxv}a z(DeSKI5ZfZ1*%dl8frIX2?);R^^~LuDOpNpk-2R8U1w92HmG1m&|j&J{EK=|p$;f9 z7Rs5|jr4r8k5El&qcuM+YRlKny%t+1CgqEWO>3;BSRZi(LA3U%Jm{@{y+A+w(gzA< z7dBq6a1sEWa4cD0W7=Ld9z0H7RI^Z7vl(bfA;72j?SWCo`#5mVC$l1Q2--%V)-uN* z9ha*s-AdfbDZ8R8*fpwjzx=WvOtmSzGFjC#X)hD%Caeo^OWjS(3h|d9_*U)l%{Ab8 z<xdQ$23|WMjf-IqBJa@-|5QJamPBg?UmANYzk#NVaoTNbS)|8H20|;zb3-A+V#wVA z0O?V!?94t>fv$yoP{OuUl@$(-sEVNt{*=qi5P=lpxWVuz2?I7Dc%BRc+NGNw+323^ z5BXGfS71oP^%apUo(Y#xkxE)y?>BFzEBZ}UBbr~R4$%b7h3iZu3S(|A;&HqBR{nK& z$;GApNnz=kNO^FL&nYcfpB7Qg;hGJPsCW44CbkG1@l9pn0`~<fs1~obTx_FSX-JYV zGQWAl6QMe=gj$TPFe4r4b4Ol;Htq0ghUXm#FhLL;q=vj^?zll8F~1Y_ME5KlGBn?W zJLZAtGO*e1y^&@oxuzM@8GNx$4<>oKy5S777uH)l{irK!ru|X+;4&0D;VE*Ii|<3P zUx#xUqvZT5kVQxsF#~MwKnv7;1pR^0;PW@$@T7I?s`_rD1EGUdSA5Q(C<>5SzE!vw z;{L&kKFM-MO>hy#-8z`sdVx})^(Dc-dw;k-h*9O2_YZw}|9^y-|8RQ`BWJUJL(Cer zP5Z@fNc>p<r+olf3Wx4QNlGzhncc!S>TXABbTRY-B5*MphpZv6#i802giwV&SkFCR zGMETyUm(KJbh+&$8X*RB#+{surjr;8^REEt`2<qz>&Dubw3$mx>|~B5IKZJ`s_6fw zKAZx9&PwBqW1Oz0r0A4GtnZd7XTKViX2%kPfv+^X3|_}RrQ2e3l<T~g*|IE{P97HV zvf#Y<i{KPN_dP%1)NHb~ix&=&GH9>=KG_VyY`H?I5&CS+lAX5HbA%TD9u6&s#v!G> zzW9n4J%d5ye7x0y`*{KZvqyXUfMEE^ZIffzI=Hh|3J}^yx7eL=s+TPH(Q2GT-sJ~3 zI463C{(ag7-hS1ETtU;_&+49ABt5!A7C<XW?{o=2DnJxLDD~{m*zq$azI0t7>wLwe z=SoA8mYZIQeU;9txI=zcQVbuO%q@E)JI+6Q!3lMc=Gbj(ASg-<Uq;hB9d^p}DAXc~ zT?U|Ep>{V27u>z2e8n;Nc*pf}AqKz1D>p9G#QA+7mqqrEjGfw+85Uyh!=tTFTv3|O z+)-kFe_8FF_EkTw!YzwK^Hi^_dV5x-Ob*UWmD-})qKj9@aE8g240nUh=g|j28^?v7 zHRTBo{0KGaWBbyX2+lx$wgXW{3aUab6B<q-FjF>hm1G1{jTC7ota*JM6t+qy)c5<@ zpc&<Cv-}2TvNf)-u^)w4IR#IAb30P8NKX2F^|M`)t)gNvmzY$92){_sASc~#MG?G6 z01+~17JwM!JPSxaJJtTz7$&8s`H3FldxQ%9@~nj<<O#kvf=K=$4nLLmHGiFo3Mq&* ziIi#gQw#(**q&>(jVdTJf(q3xB=JotgF$X>cxh7k*(T`-V~AR+`%e?YOeALQ2Qud( zz35YizXt(aW3qndR}fTw1p()Ol4t!D1pitGNL95{SX4ywzh0SF;=!wf=?Q?_h6!f* zh7<+GFi)q|XBsvXZ^qVCY$LUa{5?!CgwY?EG;*)0ceFe&=A;!~o`ae}Z+6me#^sv- z<kA1n(=XTnu@rJsCenhu-Zv&%WBDK;wE+-m5)3gqDM=UJSV|IgE?>1F6=WNd6>M(~ z+092z>?Clrcp)lYNQl9jN-JF6n&Y0mp7|I0dpPx+4*RRK+VQI~>en0Dc;Zf<!>l+x z_e_b7s`t1_A`RP3$H}y7F9_na%D7EM+**G_Z0l_nwE+&d_kc35n$Fxkd4r=ltRZhh zr9zER8>j(EdV&Jgh(+i}ltESBK62m0nGH6tCBr90!4)-`HeBmz54p~QP#dsu%nb~W z7sS|(Iydi>C@6ZM(Us!jyIiszMkd)^u<1D+R@~O>HqZIW&kearPWmT>63%_t2B{_G zX{&a(gOYJx!Hq=!T$RZ&<8LDnxsmx9+TBL0gTk$|vz9O5GkK_Yx+55^R=2g!K}NJ3 zW?C;XQCHZl7H`K5^BF!Q5X2^Mj93&0l_O3Ea3!Ave|ixx+~bS@Iv18v2ctpSt4zO{ zp#7pj!AtDmti$T`e9{s^jf(ku&E|83JIJO5Qo9weT6g?@vX!{7)cNwymo1+u(YQ94 zopuz-L@|5=h8A!(g-<F;G9^=CwUG2BBM&6@esQFH4>MXgLJC0MA|CgQF8qlonnu#j z;uCeq9ny9QSD|p)9sp3ebgY3rk#y<wu$Scub#>0DA(SHdh$DUm^?GI<>%e1?&}w(b zd<n{_{wZL^#}W>ip1;P2Z=1wM+$q=TgLP$}svd!vk+BZ@h<^4R=GS2+sri7Z*2f`9 z5_?i)xj?m#pSVchk-SR!2&uNhzEi+#5t1Z$o0PoLGz*pT64%+|Wa+rd5Z}60(j?X= z{NLjtgRb|W?CUADqOS@(*MA-l|E342NxRaxLTDqsO<GMIr8u8#%dIQrz(r`Q(hkza zil8N-`Js{wU0Gy<JdGKt>yfWWe%N(jjBh}G<qND?0TH2WotV2BO}oGFXR`nNIoZPu zAYBqht4AIf6%UvOQWL(@v@#P!g?Z{m=yxdflhU-MrdJ3Lu4OwZ%yKkuPkk0$Ko)O* z;5yrsNkvYZsjZQILNsEr+ECa0P<^XyVVf2;%`lxDRkz-!;wa1;EB{emo`C=%{Gykq zq<4i~ETk#P9zK#gq4PdG1l$Vspzwyb@<LIRCp@UiYQvSVfg*oiL+eCZD0<3etyAQ> zm7WPel6jXijaTiNita+z(5GCO0NM=Melxud57P<u@R2P46Q9-DyjXBHUN>P^d_U## zbA;9iVi<@wr0DGB8<n8`yw;2Kv**CeqAs$L&plPhIa#v7(dTNoPt@&}ED@M*lxC!x z`6s~+J|uy;3o7Lq<uMmSEF9Dw$gP)!=7bwIZF}v$SuOexM&6SRtdGcL+`+Tm+leuz zpp$tX{Sz|>=T9Ab#2K_#zi=<XArhO6r_`n&7XSM212-MzWyRNG*!uO-#ecnE^8eXw z{A)4%t2FvosVP<UQ~s;l`0?z0m3m-lgN!65Mz=sfFM<3$$g-N5nIt_Q>$igy<I%16 z>K48@;V|W`fg~7;+!q8)aCOo{HA@vpSy-4`^!ze6-~8|QE||hC{ICKllG9fbg_Y7v z$jn{00!ob3!@~-Z%!rSZ0JO#@>|3k10mLK0JR<I1S>KP-Cc8UYFu>z93=Ab-r^oL2 zl`-&VBh#=-?{l1TatC;VweM^=M7-DUE>m+xO7Xi6vTEsReyLs8KJ+2GZ&rxw$d4IT zPXy6pu^4#e;;ZTsgmG+ZPx>piodegkx2n0}SM77+Y*j^~ICvp#2wj^BuqRY*&cjmL zcKp78aZt>e{3YBb4!J_2|K~A`lN=u&5j!byw`1itV(+Q_?RvV7&Z5XS1HF)L2v6ji z&kOEPmv+k_lSXb{$)of~(BkO^py&7oOzpjdG>vI1kcm_oPFHy38%D4&A4h_CSo#lX z2#oqMCTEP7UvUR3mwkPxbl8AMW(e{ARi@HCYLPSHE^L<1I}OgZD{I#YH#GKnpRmW3 z2jkz~Sa(D)f?V?$gNi?<F$5NpPo_(+mLu%j0uVGhEpW~}8A-6p@(iN<J78jy&84)} zW71~;kMKbRG+MZ(!>6)Y;Sm{&?~2p=0&BUl_(@hYeX8YjaRO=IqO7neK0RsSNdYjD zaw$g2sG(>JR=8Iz1<iqC50Fc?zkwnhu-?J#4v?gbo)h!toq+!EipMj&Dd=4)`^!2@ zL(!GW5QxLJO&{?1u~Q}Au)moY@9Q-~Yr01D0la`rUI3jK%5PxGU7;z+IlI=Bb;^2b zL|Kc&B2+#W3&e}l>SK4`*kqd_3-?;_BIcaaMd^}<@MYbYisWZm2C2<aQM85hCqTrH z{L!?Z_;my2c?%RMej)yS*$eqpa!UR3e9te>|Np_l|8r9yM|JkUngSo@?wci(7&O9a z%|V(4C1c9pps0xxzPbXH=}QTxc2rr7fXk$9`a6TbWKPCz&p=VsB8^W96W=BsB|7bc zf(QR8&Ktj*iz)wK&mW`#V%4XTM&jWNnDF56O+2bo<3|NyUhQ%#OZE8$Uv2a@J>D%t zMVMiHh?es!Ex19q&6eC&L=XDU_BA&uR^^w>fpz2_`U87q_?N2y;!Z!bjoeKrzfC)} z?m^PM=(z{%n9K`p|7Bz$LuC7!>tFOuN74MFELm}OD9?%jpT>38J;=1Y-VWtZAscaI z_8jUZ#GwWz{JqvGEUmL?G#l5E=*m>`cY?m*XOc*yOCNtpuIGD+Z|kn4Xww=BLrNYS zGO=wQh}Gtr|7DGXLF%|`G>J~l{k^*{;S-Zhq|&HO7rC_r;o`gTB7)uMZ|WWIn@e0( zX$MccUMv3ABg^$%_lNrgU{EVi8O^UyGHPNRt%R!1#MQJn41aD|_93NsBQhP80yP<9 zG4(&0u7AtJJXLPcqzjv`S~5;Q|5TVGccN=Uzm}K{v)?f7W!230C<``9(64}D2raRU zAW5bp%}VEo{4Rko`bD%Ehf=0voW?-4Mk#d3_pXTF!-TyIt6U+({6OXWVAa;s-`Ta5 zTqx&8msH3+DLrVmQOTBOAj=uoxKYT3DS1^zBXM?1W+7gI!aQNPYfUl{3;PzS9*F7g zWJN8x?KjBDx^V&6iCY8o_gslO16=kh(|Gp)kz8qlQ`dzxQv;)V&t+B}wwdi~uBs4? zu~G|}y!`3;8#vIMUdyC7YEx6bb^1o}G!Jky4cN?BV9ejBfN<&!4M)L&lRKiuMS#3} z_B}Nkv+zzxhy{dYCW$oGC&J(Ty&7%=5B$sD0bkuPmj7g>|962`(Q{ZZMDv%YMuT<n z1<0L@A~^*&C~fETTawHVh1kk4b*^p0vQ^7?+3dKBe<pM8Snh`k_7R%#IZRUEl1U~% z`#y5ddd+xk?tVQb4dNJ(7Ry%2!BTF1HzW?PK!2%Oj>^Kwe<oH3RpEUQV(1=JAftKZ zy};jv^`iGA^yoK}($W9zl~UM?CzovcbP5)_-K0QR<B0^>iRDvYTEop3IgFv#)(w>1 zSzH><Zx#DBcM*ETggCrIL|G$?#sL+^<gVn#xwx<>J`q!LK)c(AK>&Ib)A{g`<Y-)} z(@A>Fdykxqd`Yq@yB}E{gnQV$K!}RsgMGWqC3DKE(=!{}ekB3+(1?g}xF>^icEJbc z5bdxAPkW90atZT+&*7qoLqL#p=>t-(-lsnl2XMpZcYeW|o|a322&)yO_8p(&Sw{|b zn(tY$xn5yS$DD)UYS%sP?c|z>1dp!QUD)l;aW#`%qMtQJjE!s2z`+bTSZmLK7SvCR z=@I4|U^sCwZLQSfd*ACw9B@`1c1|&i^W_OD(570SDLK`MD0wTiR8|$7+%{cF&){$G zU~|$^Ed?TIxyw{1$e|D$050n8AjJvvOWhLtLHbSB|HIfhMpqVf>AF&}ZQHhOJ14Bz zww+XL+qP}nww+W`F>b!by|=&a(cM4JIDhsTXY8@|ntQG}-}jm0&Bcj|LV(#sc=BNS zRjh<Mlkf>;k9l>EdAFdd)=H!U`~$WP*}~^3HZ_?H>gKw>NB<D?df$IC%55Zl`EPwc zRF>a;tA8M1{>St|)yDF_=~{KEPAGkg3VB`QCHol!AQ0|?e^W?81f{@()Wy!vQ$bY; z0ctx)l<l3Egk{Ob>7VK83d6;dp!s{Nu=SwXZ8lHQHC*J2g@P0a={B8qHd<!Rx=U=y zZhU*Z!GA%uunxv9&4$#mX+|}S)urtQN=7La7qnsxu>v(+O3wV=4-t4HK1+smO#=S; z3cSI#Nh+N@AqM#6wPqjDmQM|x95<n5VlzgWRH&oDW?c}DT^%?B8C0l+B0<BSKyNf1 z@50z}-d3zrSn&7`r1tBSp<zb3^nhH#XuDC?R<KtB*VsyKR`dRh)&DkLIrq4o!?;Lk zondptVSwpbOiowRa-P*4A7o%#IYH#y*MPqzE9G%OcE;(l=a5Gbdc^<iHA{4$gMK2y zrcQ~;DrQl(Xod1}HF3{_dN{dd)Iq**zG_<1@e+8Q8+Oq;jgidKOGIuhBe_rBN^N(^ zH&yrkQqs47d>JG|l1<sF7&JuwXR&1!7b?5$CbRqF7%}I8mpCr(sj;K7IQl+Ud)#bZ zp7IC+SbpjPV~m#KY)1CSNeLmt63WJp#VvwlYf+=uB{p=aUnI`+`Y>#sAU|>I6<Rxv z+8ksxQP-bXJt|;JqZ0=Syg@fkr7?v9z=bM6Vn&}>NdF*G@bD?1t|ytHlkKD+z9}#j zbU+x_cR-j9yX4s{_y>@zk*ElG1yS({BInGJcIT>l4N-DUs6fufF#GlF2lVUNOAhJT zGZThq54GhwCG(h4?yWR&Ax8hU<*U)<g>?g+HY5-@{#ls5CVV(Wc>Bavs|l<}U|hZn z_%m+5i_gaakS*Pk7!v&w3&?R5Xb|AkCdytTY;r+Z7f#Id=q+W8cn)*9tEet=OG+Y} z58U&!%t9gYMx2N=8F?gZhIjtkH!`E*XrVJ?$2rRxLhV1z82QX~PZi8^N5z6~f-MUE zLKxnNoPc-SGl7{|Oh?ZM$jq67sSa)Wr&3)0YxlJt(vKf!-^L)a|HaPv*IYXb;QmWx zsqM>qY;tpK3RH-omtta+Xf2Qeu^$VKRq7`e$N-UCe1_2|1F{L3&}M0XbJ@^xRe&>P zRdKTgD6601x#fkDWkoYzRkxbn#*>${dX+UQ;FbGnTE-+kBJ9KPn)501#_L4O_k`P3 zm+$jI{|EC?8BXJY{P~^f-{**E53k%kVO$%p+=H5DiIdwMmUo>2euq0UzU90FWL!>; z{5@sd0ecqo5j!6AH@g6Mf3keTP$PFztq}@)^ZjK;H6Go$#SV2|2bAFI0%?aXgVH$t zb4Kl`$Xh8q<G488u@$4lX!B=3?g=wlC?}MC;F?H%YQrVNOwB#z7-f_|Wz?O!b4I~2 z^Qw&0hykWBc$}5NngS)c1*7`tH73!7vUHgRMs>LrMbZUS<2*7^F0^?lrOE=$DHW+O zvLdczsu0^TlA6RhDy3=@s!k^1D~Awulk!Iyo#}W$xq8{yTAK!CLl={H0@YGhg-g~+ z(u>pss4k#%8{J%~%8=H5!T`rqK6w^es-cNVE}=*lP^`i&K4R=peg1tdmT~UAbDKc& zg%Y*1E<jNK6bVo^5$q7Be!g@_B}<2f!MazAse=SHXka44U?M8cg8{iRQqX625kGny zEx>{hBf<)xO>HDWV7BaMWX6FW4ou1T2m^6{Jb!Su1UaCCYY8RR8hAV$7ho|FyEyP~ zEgK`<ybDN}WQ7ppf~i48Sp+j=w6UI16W6MuJXhL6VlQ|!lSyz6m|Gs@>@%a$-C2`p zV*~G>GOAs*3KN;~IY_UR$ISJxB(N~K>=2C2V6>xTmuX4<wHTgMVWGBYU0G4B(`;}2 zw_J6Ct{nL}*%nG0uk<t$To_fcVQEvXjtQYeWv?v&5m9S(NJkQnc)rvU7`Je&48A!8 z_->klRXdrJd&UPAw7&|KEwF8Zcy2j-*({gSNR1^p02Oj88GN9a_Hq;Skdp}kO0;<y ztR-y<(h)MzSR8PG`MEz?T1Lf{zq~R3i)I#s$y{Wn^A`t(9>FLbje%2ZvPiltDZgv^ z#pb4&m^!79;O8F+Wr9X71laPY!CdNXG?J6C9KvdAE2xWW1>U~3;0v≫L+crb^Bz zc+Nw%zg<eW;A}s=*P6+gF}bio8=x0TEl%l4pJ$tyY5b9sQ8QUf<CVb&IosSO?U)TS zqRaFVMB?L$Va^G<K_IKy<}kIfB`>pZ6>!A3%lau!Pw6`Y#WPVBtAfKSsqwYDWQK-~ zz(mx=nJ6-8t`YXB{6gaZ%G}Dmn&o500Y}2Rd?e&@=hBEmB1C=$OMBfxX__2<amvr< zXa%T~J;`~)wa6K9vLDPZ4GZLPS7oKSy)VETgG@jr+mViaX=%jwAwMaxuIET{i2|{P z=%Yb3&*b&m#ml+5FlJql5a}W%z?`C^MKY$$m`pDfNwvint?IO6amJ*PZQL1(52tL{ zJANajfD2`9E?S2iDE{r9w1H+KbS!7BR1@VophCkXHR`|fTeaGAB8za0A1K7kCS(bA z3^hY;UdsU90Qq(v&N0T9JSv}(7&&Gw+V%U6EH!}fv*RqA&zDLjkb!uv6idVcvDYv} z&BaSl7_k9>c2O4K2#(0ksclP$SHp*8jq-1&(<6(#=6&H`Nlc2RVC4->r6U}sTY<1? zn@tv7XwUs-c>Lcmrm5AE0jHI5={WgHIow6cX=UK)>602(=arbuAPZ37;{HT<bASz# zhpNmfwQSDBB;fIIk_gW5U{}19wURbn{If{5IyR->JSIO%9EL`Et5%J7$u_NaC(55x zH^qX^H}*RPDx)^c46x>js=%&?y?=iFs^#_rUl@*MgLD92E5y4B7#EDe9yyn*f-|pQ zi>(!bIg6zY5fLSn@;$*sN|D2A{}we*7+2(4&EhUV%Qqo5=uuN^xt_hll7=`*mJq6s zCWUB|s$)AuS&=)T&_$w>QXHqCWB&ndQ$y4-9fezybZb0bYD^zeuZ>WZF{rc>c4s`` zgKdppTB|o>L1I1hAbnW%H%EkFt%yWC|0~+o7mIyFCTyb?@*Ho)eu(x`PuO8pLikN> z6YeI`V?AUWD(~3=8>}a6nZTu~#QCK(H0+4!ql3yS`>JX;j4+YkeG$ZTm33~PLa3L} zksw7@%e-mBM*cGfz$tS4LC^SYVdBLsR}nAprwg8h2~+Cv*W0%izK+WPVK}^SsL5R_ zpA}~G?VNhJhqx2he2;2$>7>DUB$wN9_-adL@TqVLe=*F8Vsw-yho@#mTD6*2WAr6B zjtLUh`E(;#p0-&$FVw(r$hn+5^Z~9J0}k;j$jL1;?2GN9s?}LASm?*Rvo@?E+(}F& z+=&M-n`5EIz%%F^e)nnWjkQUdG|W^~O|YeY4Fz}>qH2juEere}vN$oJN~9_Th^&b{ z%IBbET*E8%C@jLTxV~h#mxoRrJCF{!CJOghjuKOyl_!Jr?@4Upo7u>fTGtfm|CH2v z&9F+>;6aFbYXLj3{yZ~Yn1J2%!)A3~j2$`jOy{XavW@t)g}}KUVjCWG0OUc7aBc=2 zR3^u=dT47=5SmT{K1aGaVZkOx|24T-J0O$b9dfB25J|7yb6frwS6wZ1^y%EWOm}S< zc1SdYhfsdLG*FB-;!QLV3D!d~hnXTGVQVck9x%=B(Kk8c3y%f0nR95_TbY;l=obSl zEE@fp0|8Q$b3(+DXh?d0FEloGhO0#11CLQT5qtEckBLe-VN-I>9ys}PVK0r;0!jIG zH_q$;a`3Xv9P_V2ekV1SMzd#SKo<1~Dq2?M{(V;AwhH_2x@mN$=|=cG0<3o^j_0OF z7|WJ-f2G=7sA4NVGU2X5`o*D2T7(MbmZ2(oipooE{R?9!{WxX!%ofhsrPAxoIk!Kr z>I$a{Zq=%KaLrDCIL^gmA3z{2z%Wkr)b$QHcNUA^QwydWMJmxymO0QS22?mo%4(Md zgME(zE}ub--3*wGjV`3eBMCQG-@Gel1NKZDGuqobN|mA<Orshs+Cll$u%OVm+m7$A zvobiM4A4uVtI2;EQ`is0JxPx9*53^imsz^x6`T%eO>t0{@ZC9goI|BSmGBTUZ(`Xt z^e2LiMg?6E?G*yw(~K8lO(c4)RY7UWxrXzW^iCg-P41dUiE(i+gDmmAoB?XOB}+Ln z_}rApiR$sqNaT4frw69Wh4W?v(27IlK$Toy<1o)GeF+sGzYVeJ`F)3`&2WDi^_v67 zg;@ehwl3=t+}(DJtOYO!s`jHyo-}t@X|U*9^sIfaZfh;YLqEFmZ^E;$_XK}%eq;>0 zl?+}*kh)5jGA}3daJ*v1knbW0GusR1+_xD`MFPZc3qqYMXd>6*5?%O5pC7UVs!E-` zuMHc6igdeFQ`plm+3HhP)+3I&?5bt|V8;#1epCsKnz0%7m9AyBmz06r90n~9o;K30 z=fo|*`Qq%dG#23bVV9Jar*zRcV~6fat9_w;x-quAwv@BkX0{9e@y0NB(>l3#>82H6 z^US2<`=M@6zX=Pz>kb8Yt4wmeEo%TZ=?h+KP2e3U9?^Nm+OTx5+mVGDvgFee%}~~M zK+uHmj44TVs}!A}0W-A92LWE%2=wIma(>jYx;eVB*%a>^WqC7IVN9{o?iw{e4c=CG zC#i=cRJZ#v3<OhgHFO)Yuf*wx=u8?KJAxfFal#c87qImw{QL+yd!UrcHEm`qaIWJ> zF^9V+7u?W=xCY%2dvV_0dCP%5)SH*Xm|c#rXhwEl*^{Ar{NVoK*H6f5qCSy`+|85e zjGaKqB)p7zKNKI)iWe6A9qkl=rTjs@W1Crh(<w{D@{wF@eAUdA<ecn!45g=nz<F8W zcHpM2OaZmr7hg(j>3G57qdT0w2ig^{*xerzm&U>YY{+fZbkQ<WiW=GrQ9?}ABlM?S z5yX^-T$QGSicUUT_;DBFofFw|X+^sREV>#;^<$JniUifmAuEd^_M(&?sTrd(a*cD! z<RfQp$HKS4nD)BZdWrVduooK{Y#BPyLM^%s#T9QaF#!BDh4*GS0;>F*;`m80MrZ^> zaF{}rDhEFLeH#`~rM`o903FLO?qw#_Wyb5}13|0agjSTVkSI6Uls)xAFZifu@N~PM zQ%o?$k)jbY0u|45WTLAirUg3Zi1E&=G#LnSa89F3t3>R?RPcmkF}EL-R!OF_r1ZN` z?x-uHH+4FEy>KrOD-$KHg3$-Xl{Cf0;UD4*@eb~G{CK<fax(qwwJBZTjQv;(6lwZ1 zN@y8!2Q~?JvR=^bgSD}Zo^iruSXBV}rzy#Y@LME2qAW4Y%O+imN5Xc_W5Fh#DBFe; zwY9`azQ@O1eUnX&7vS!|8z%OWQCo_Wg2|qd_%j<t?-<@AfA>-DXe3xpEEls?SCj^p z$Uix(-j|9f^{z0iUKXcZQen}*`Vhqq$T?^)Ab2i|joV;V-qw5reCqbh(8N)c%!aB< zVs+l#_)*qH_iSZ_32E~}>=wUO$G_~k0h@ch`<gt#cp1U1WgWwHf1zyQewkQH>a6Wa zsk;<)^y=)cPpHt@%~bwLBy;>TNrTf50BAHUOtt#9JRq1ro{w80^sm-~fT>a$QC;<| zZIN%&Uq>8`Js_E((_1sewXz3VlX|-n8XCfScO`eL|H&2|BPZhDn}UAf_6s}|<W$yZ z&kmrV`OAcyEk@5O_d1K`9ztw!LTQ)vi^7AY(b7$AK%X!8_!&bvrhLv@oFO}+TfU4o z!H9q63S!`o3%v<@B2F*Pz76V~n+@=u<2KM_4Yf4Tcil0U)}t=ASxe=Js$o)5^i~?< z5OqmfW6-dnOw9@{Aqq4vD4bN1OnS@+lTfgs?eN(FNn5Q#_veOlFdu3)IK$eB^Uo4t zj?l?=#xmRXU%L-sp<dhXj_~_D*FuOEC>!XpmUr90v|nCutzMjb9|&}#Y7fj_)$alC zM~~D6!dYxhQof{R;-Vp>XCh1AL@d-+)KOI&5uKupy8PryjMhTpCZnSIQ9^Aq+7=Mb zCYCRvm4;H=Q8nZWkiWdGspC_Wvggg|7N`iED~Eap)Th$~wsxc(>(KI>{i#-~Dd8iQ zzonqc9DW1w4a*}k`;rxykUk<ZJ`qoPZH+s1L|{7dJ03F>+~N)|*I?@0901<qh{Z9u zM(%*;?u7Tx@An5HnDFSwh~71l4~zl+IS3QFak$TAn}O;_&Yg6&yC;97-}}S=>R`xy zN{20p@Ls<%`1G1Bx87Vm6Z#CA`QR(x@t8Wc?tpaunyV^A*-9K9@P>hAWW9Ev)E$gb z<(t?T<I%q{eh<paBCgp(eNP1JC7j$cU&lqI%}1$+t<Xum)7-hy-(S~>e6GcJX2&0% z403pe>e)>m-^qlJU^kYIH)AutgOnq!J>FoMXhA-aEx-((7|(*snUyxa+5$wx8FNxS zKuVAVWAr<NYYOV+XC<zEq=BX*l6of(_0jkouf~Z}i)Pi;@oSKe*2S%Ot!8e9G()D^ zHCF=S(f7vqeckT}E9Gkn7-$v6Rolof1?4D(Ee6t+oZ0lsJ=UPx<vWKk)>lK#kDzEM zqR?&aXIdyvxq~wF?iYPho*(h<uGlq#b_^JO#6P~MgKdi{;dc6bOPRw@UTRu@s@>?k zD(SBpRDZ}z$A})*Qh!9&pZZRyNixD!8)B5{SK$PkVET(yd<8kImQ3ILe%jhx8Ga-1 zE}^k+Eo^?c4Y-t2_qXiVwW6i9o2qosBDj%DRPNT*UXI0=D9q{jB*22t4HHcd$T&Xi zT=Vte*Gz2E^qg%b7ev04Z&(;=I4IUtVJkg<`N6i7tjUn-lPE(Y4HPyJKcSjFnEzCH zPO(w%LmJ_=D~}PyfA91H4gCaf-qur3_KK}}>#9A}c5w@N<r?JvNjY~yQShiS4qY&3 zlEq{*4cG8TB8w?hxny#0kg_47TjeF0N4fFfRug<oQH4Q(9JenqW{)rACv`ezyz-yU zXWQaxZzc6w)o5k1X`jL!9euTR%&XzA(yX>;-#cHph=x}^mQ3`oo`Y$ope#)H9(kQK zGyt<7eNPuSAs$S%O>2ElZ{qtDIHJ!_THqTwcc-xfv<@1>IJ;YTv@!g-zDKBKAH<<p zBDDsGt$u2qMC-^a?PmMtEGv5Qjw-8`x+??EVCj)0tD5~cjb`<Ru8=Di2fXP=Xsa4y z&n#+a?$v9OkH1zuW`su>Zet1e^8c}8fE97XH}+lF{qbF<`Y%dU|I!~Y`ZrVfKX82i z)(%!Tcf~eE^%2_`{WBPGPU@1NB5SCXe1sAI<4&n1IwO{&S$ThWn37heGOSW%nW7*L zxh0WK!E7zh%6yF-7%~<m{+EMBci$fO&hv0iZf0iciMJ_<^l~es_{rqv)3kTa)Ak7+ z^Xo_#|0iZI&^uj#ODfeL#OGhjgkcd>l@I~b`2=*$;RYbi(I#zp$gL_d39U4A)KuB( zcS0bt48&%G<QI2DbY;&fyt@4p`kndvOAsyITmfiaVnddQPW><k4f~&M47%t~>_I~( zL(}w&2NA6#$=|g)J+-?ehHflD^lr77ngdz=dszFI;?~ZxeJv=gsm?4$$6#V==H{fa zqO!EkT>1-OQSJoX)cN}XsB;shvrHRwTH(I2^Ah4|rizn!V7T7fLh~Z<`Q+?zEMVxh z$=-x^RR*Pl<N5e(X;~A8VM_P?TZ%aBKgo&=4$TErD)@Yct1Rw?ng{l|AoY=?j%yN0 z{#cO{%|$VQvwftyGPCmDv`G|@hi=(&+FD`aH0@zL)mgk61`d7fWFI<9n5Stfh{y~| zVYivv;t1&zm<!4~89}Fc?b(Kg_9R40b-;<;G;xsNR2o!c=iwxzn4nij;=KC8R)gz3 z9{q)1S1P63>hkV_8mshTvs+zmZWY&Jk{9LX0Nx|<ldHT!kKyn#dbVMfBn9e@+8r+F zfUf&0TK=f&Dw}lCHqy=C!Y_ll#;7`Ni~dQ7*RF-@CT118I8||q-;pR+UUO=*ir<_t z#spc+WCC_&j^sM1My2U+FVEl;KnC$f^WTRS8%6rW@=8`+%Q<P=bTsD{BzbOLv4B=< znii$?HN+aTLVM;6Ry2|w16RXk8F{P;vF6P*>+NAEq-^+Rh|ZlinVZ=e8=`WQt;e@= zPU}^1cG*O;G7l<KDc2~6h#xMeWr-r0OAVri(64~%KI0R2+$-rI{tJE2uRmY>{Y#nl znp`y%CO_SC7gk0i0gY&phM04Y)~vU0!3$V$2T+h(1ZS<f8b%S8rz4-~;5aW>+cCgc zaC?3M;B48^faGo>h~--#FNFauH?0BJJ6_nG5qOlr>k~%DCSJaOfl%KWHusw>tG<g2 z$lo!8f^Xe%pj=Rq7%tJ{i>rTxAhlEVDxc8R2C-)LCt&$Rt9IKor=ml7jirX@?WW+M z^I{b<RO!Q<u)IU5t7<PW#57>}MD5r$s>^^sN@&g`cXD~S_u09xo;{;noKZatIuzqd zW1e7oTl9>g8opPBT(p+&fo0F#!c{NFYYpIZ6u8hOB{F#{nP)@}<EI#MDyucB{#6)L zh?JbpGIyYUsx1TNY%9e(fQxI4t~H%dE@^{WcxhZ!EGpG(z;pkdxe<EMwA+Lw4=;2g zYbi-SoGU)S_pwcYeS^ZA!|qTP6{pVI-|SNsgg%*BWh(Meg~tf-Q>)X20$3iJtG$cO zJ$Oxl_qH{sL5d?=D$2M4C3Ajc;GN0(B-HVT;@pJ-LvIrN%|SY?t}g!J>ufQrR%hoY z!nr$tq~N%)9}^tEip93XW=MQ1@XovSvn`PTqXeT9@_7hGv4%LK1M**Q%UKi|(v@1_ zKGe*@+1%Y4v&`;5vUL`C&{tc+_7HFs7*OtjY8@Gg`C4O&#An{0xOvgNSehTHS~_1V z=daxCMzI5b_ydM5$<?dgyKM^=r)Tc6U|s}2kynE;FGHeu-B988SO;&pB(e6Qh2P=z z3xHw_PzW_~dkx((DUd~Q2N1y~?HHrUe^BBMG0xxXk7M0LA9EBTCq5C@%1ysh#Z!@~ zeBSi(I#rmd%ndI2&VJ}2ohfjS@n({D#%pBmt^KT`Uq^dIUO)MO6sy=Co=$u5L%1ly zKrztx?JF?i3`s2H+UzoBhg0&Z9qMf`%Goy1(HZK-?+u=1^xjw2TbhuR=eMi!$6G>z zZl`a{mM}i@x;=QyaqJY&{Q^R*^1Yzq!dHH~UwCCga+Us~2wk59ArIYtSw9}tEmjbo z5!JA=`=HP*Ae~Z4Pf7sC^A3@Wfa0Ax!8@H_&?WVe*)9B2y!8#nBrP!t1fqhI9jNMd zM_5I)M5z6Ss5t*f$Eh{aH&HBeh3<g7^zLpu^Ry#)H8VHEiRW^liKzzBoM3#P@ytA< zA@5R;`2dqNGoWM#nC%jlTW~eu$^Qc*+dkom?FLAYw(n7mMai@*PO})<Dp$Ok0Hd|J z{nPfV$w6+Nq{4I+p~1*KT9hjW@0B__I&Mskiv;drVlpZ7bg1FkO*IdCid;LJ_4!7K zbfkj~O7n!d8(RlYcP}&ccfRG>10Q~tRl3wCEcZ>WCEq%3tnoHE)eD=)XFQ7NVG5kM zaUtbnq2LQomJSWK)>Zz1GBCIHL#2E>T8INWuN4O$fFOKe$L|msB3yTUlXES68nXRX zP6n*zB+kXqqkpQ3OaMc9GqepmV?Ny!T)R@DLd`|p5ToEvBn(~aZ%+0q&vK1)w4v0* zgW44F2ixZj0!oB~^3k|vni)wBh$F|xQN>~jNf-wFstgiAgB!=lWzM&7&&OYS=C{ce zRJw|)PDQ@3koZfm`RQ$^_hEN$GuTIwoTQID<d@J+C!*a#y8F@xM-Iy_j&S_v$*aHC z<^<1lMFmAQ6d)B9ppuP7+x{7e>b?W&wEo@c75$dW(ER6q)qhF`{#7UTuPH&)w`F!w z0EKs}=33m}_(cIkA2rBWvApydi0HSOgc>6tu&+hmRSB%)s`v_NujJNhKLS3r6hv~- z)Hm@?PU{zd<SuU^ZNqbh_hj?zhJVNRM{0ipOFcz-sswR>0Tga)cJWb2_!!9p3sP%Z zAFT|jy;k>4X)E>4f<s%$es?%H6q44Ym7Tg^bK_WZ>h^6=SxV5w6oo`mus&nWo*gJL zZH{SR!x)V)y=Qc7WEv-x<Rp}|n<G?y@SQ4XooI*D5H6|yT}sqCm#c1ra{^IYypH}c zm17W3XkTgz;cv-2Bkm9zj!KK~b{5nJs-w29PNOBOi7M%$)E08H=v6$}lUmUa(5>LR zhD4OcBwjW5r+}pays`o)i$rcJb2MHLGPmeOm<ly?oC3vz<dWPHJ2q*qSfdfjHs3pG z8wPe2f#fdLSh@|^lKvdXF_&GOvjikbVR#Qzr>t5XJDg@(O3PCbxdDn{6qqb09X44T zh6I|s=lM6Nr#cGaA5-eq*T=LQ6SlRq*`~`b+dVi5^>el1p;#si6}kK}<i{_X0}mow zhl0h@WibK^GtE>>w;1<WXe4=aU)VR4iAjHDbqV1&<YPjvBdJ|}-XxnB?Tstau<Hfq zCRRqz_iBQn`XqE$^y`!_by;iY`BF&pW5CL^OWe?LiOxoGT#Y$s(kmFjDXs&p?eit> z6B1dz{q_;PY{>DBQ+v@1pfXTd5a*^H9U*;qdj@XBF}MoSSQxVXeUpEM5Z0909&<Re zk3I+&OO%J-Z}&=p!z(}*pf~$i%5?5}NgAE2OZE4Z<X!Mwp;tlq>8$pRfR|B(t0<lD zFs$q_Z$Z*zi1c&2E;a}s$0i^wl);}>ox&xl8{8mUNd#(zWONW{oycv$VjP1>q;jU@ z@+8E~fjz*I54OFFaQ{A5jn1w>r;l!NRlI(8q3*%&+tM?lov_G3wB`<}bQ>1=&xUht zmti5VZzV1Cx006Yzt|%Vwid>QPX8Nfa8|sue7^un@C+!3h!?-YK>lSfNIHh|0kL8v zbv_BklQ4HOqje|@Fyxn%IvL$N&?m(KN;%`I$N|muStjSsgG;gP4Smgz$2u(mG;DXP z<GLhq%Frtu7l<`vL?~}D33W@?AQ|QM%-T&P!X7*@ooXAv3j4ICG}mO0p_It|>f~uQ z212x^l6!MW>V@ORUGSFLAAjz3i5zO$=UmD_zhIk2OXUz^LkDLWjla*PW?l;`LLos> z7FB<H#U>vCr)#)XBByDm(=n%{D>BcUq>0GOV9`i-(ZSI;RH1rdrAJ--f0uuAQ4odl z_^$^U_)0BBJwl@6R#&ZtJN+@a(4~@oYF)yG+G#3=)ll8O#Zv3SjV#zSXTW3h9kqn* z@AHL=vf~KMas}6{+u=}QFumr-!c=(BFP_dwvrdehzTyqco)m@xRc=6b#Dy+KD*-Bq zK=y*1VAPJ;d(b?$2cz{CUeG(0`k9_BIuUki@iRS5lp3=1#g)A5??1@|p=LOE|FNd; z-?5MLKd-5>yQ7n__5W^3C!_`hP(o%_E3BKEmo1h=H(7;{6$XRRW6{u+=oQX<((xAJ zNRY`Egtn#B1EBGHLy^eM5y}Jy0h!GAGhb7gZJoZI-9WuSRw)GVQAAcKd4Qm)pH`^3 zq6EI<JY+MFM(eM!0?iX661nT9c-t~th~b`G4v9)PjuBkKR2nRDgO!=Je!Yr0&>M}Q zxZGx%aLnNP1an=;o8p9+U^>_Bi`e23E^X|}MB&IkS+R``plrRzTE%ncmfvEW#AHJ~ znmJ<w+?(s0eKb5NC>`x&ez6<V)q+T?(ZD{dXt<5#hyU$KG!X$+$^9Yvvrs%2XHa28 z9mW3uNXoj}%%{F;7@vhx@XEris%fqkwras~!0d4n)^sr~-v)u>eT21aLnoI`%pYYj zzQ?f^ob&Il;>6Fe>HPhAtTZa*B*!;;foxS%NGYmg!#X%)RBFe-acahHs3nkV61(E= zhekiPp1d@ACtA=cntbjuv+r-Zd`+lwKFdqZuYba_ey`&H<<cYk$0c=kGPn9qVEX_6 zdd&agdUKm^NSclQfBqr<G?7flcPt3|cAET?xcXoI=>Psu;Tzwt;-LQxvv<_D5;ik7 zwETZe`+voUhk%$s2-7Rqfl`Ti_{(fydI(DAHKr<66;rYa6p8AD+NEc@Fd@%m`tiK% z=Mebzrtp=*Q%a}2UdK4J&5#tCN5PX>W=(9rUEXZ8yj<Mqef_Wl-7%VtnZS%Z2oI}3 zt4>Ru+7<Rn6ogv&Yd+l%+cl%5G3&xkOLP84>)mFpKh{6;n%!bI(qA9kfyOtstGtOl zX!@*O0fly*L4k##fsm&V0j9Lj<_vu1)i?!<L;E`x9lME^PJK;H0I38a2~ay-IQtaM zP*qOEwu?>#xTB7@2H&)$Kzt@r(GH=xRZlIimTDd_o(%9xO388LwC#;vQ?7OvRU_s< zDS@6@g}VnvQ+tn(C#sx0`J^T4WvFxYI17;uPs-Ub{R`J-NTdtBGl+Q>e81Z3#tDUr ztnVc*p{o|RNnMYts4pdw=P!uJkF@8~h)oV4dXu5F7-j0AW|=mt!QhP&ZV!!82*c7t zuOm>B*2gFtq;A8ynZ~Ms?!gEi5<{R_8tRN%aGM!saR4LJQ|?9w>Ff_61(+|ol_vL4 z-+N>fushRbkB4(e{{SQ}>6@m}s1L!-#20N&h%srA=L50?W9skMF9NGfQ5wU*+0<@> zLww8%f+E0Rc81H3e_5^DB@Dn~TWYk}3tqhO{7GDY;K7b*WIJ-tXnYM@z4rn(LGi?z z8%$wivs)fC#FiJh?(SbH-1bgdmHw&--rn7zBWe1xAhDdv#IRB@DGy}}zS%M0(F_3_ zLb-pWsdJ@xXE;=tpRAw?yj(Gz=i$;bsh&o2XN%24b6+?_gJ<Kq?WDXDfm(x!QEt~n zRKS&jm1iAmM3}~9QQzG(ufO3+`TI6D9BPg(#U0I6R;fichT{&%oANc!_k+QyVUA0X zJ;y~@dMky&r&t(&yTq9QF`8JqVvCIcJ)sePA7<JG&$d^_3Hci6_0j&Ey^t-_>DBeY zws3PE2u!#Cec>aFMk#ECxDlAs;|M7@LT8)Y4(`M}N6IQ{0YtcA*8e42!n^>`0$LFU zUCq2IR2(L`f++=85M;}~*E($nE&j;p<yY{=u)t50<zfGuPfQVrd32XaZr0TmMx8R* z@*(HUfN5jM$WN2oIfF}JMksU=KGZ1F5M)`z_dNIl$F|R02`>{l%xchiTau*tB9bI= zn~Ygd@<+9DrXxoGPq}@vI1Q3iEfKRleuy*)_$+hg?+GOg<A}r`+}E9+ehEFhD$oVf z7<m>f1r?d@Or42|s|D>XMa;ebr1uiTNUq@heusd6%WwJqyCCv!L*qou9l!B22H$bQ z)<)IA>Yo77S;|`fqBk!_PhLJEQb0wd1Z|`pCF;hol!34iQYtqu3K=<LO71guVa`H& zP~U?liGQ}(w`Ce;)(XleA+f1HnQZeuVKVi3e|?4RrOGyn8>$QxLW7(HFx~v>`vVRr zyqk^B4~!3F8t8Q_D|GLRrAbbQDf??D&Jd|mgw*t1YCd)CM2$76#Cqj1bD*vADwavp zS<`n@gLU4pwCqNPsIfHKl{5}g<GJ0o#1j?jNyIHMj<CvGpYQW1g$p7}ff8O1($ZwA zM5*w6_w!_W(47!a@lfhj-LO=sv{0AgO+p&pD7RH8U0ABe3klJGcA#Ocb>u9t-o+O< z??!fMqMrt$s}02pdBbOScUrc1T*{*-ideR<m2e=AZal*{t}%C93t*O6?ie5So=e1) z%(avX4jGAsQT|{)jC-)iD|Zh3MH`Qb&c4gk`a!C>6(1q4@oC6mxg8v8Y^h^^hfx6| z|Mld6Ax1CuSlmSJmHwdOix?$8emihK#&8&}u8m!#T1+c5u!H)>QW<7&R$eih)xkov zHvvEIJHbkt+2KQ<-bMR;2SY<W%^(e<vyQcTKPTbhPZ1>X?8SI=_<-J!GD5@P2FJ}K z5u82YFotCJF(dUeJFRX_3u8%iIYbRS??A?;iVO?84c}4Du9&jG<#urlZ_Unrcg8dR z!5I3%9F*`qwk#joKG_Q%5_xpU7|jm4h0+l$p;g%Tr>i74#3QnMXdz|1l2MQN$yw|5 zThMw15BxjWf2{KM)XtZ+e<wJY-!H0vjG6iWB)tDV08z-+*6I6c)VKS`B*Sk5{69vn z{5u6TN@?QT1&qSG(CW-s93-GMUJ%qgOA@PD3u_>#N)ihlkxPe=5ymT9>@Ym%_LF}o z1XhCP`3E1A{iVoHA#|O|&5=w;=j*Qf`;{mBAK3={y-YS$`!0UmtrvzHBfR*s{z<0m zW>4C=%N98hZlUhwAl1X`rR)oL0&A`gv5X79??p_==g*n4$$8o5g9V<)F^u7v0Vv^n z1sp8{W@g6eWv2;A31Rhf5j?KJhITYfXWZsl^`7z`C<F;2vYEX$)O-o}#)bE%Mbj#_ zXvXs}1>FtnFrHUWiD?$pwU6|PQjs|7RA0o9ARk^9$f`u3&C|#Z3iYdh<0R`l2`)6+ z6tiDj@xO;Q5PDTYSxsx6n>bj+$JK8IPJ=U5#dIOS-zwyK?+t^V`zChdW|jpZuReE_ z)e~ywgFe!0q|jzsBn&(H*N`%AKpR@qM^|@qFai0};6mG_TvXjJ`;qZ{lGDZHScZk( z>pO+%icp)SaPJUwtIPo1BvGyP8E@~w2y}=^PnFJ$iHod^JH%j1>nXl<3f!nY9K$e` zq-?XYl)K`u*cVXM=`ym{N?z=dHQNR23M8uA-(vsA$6(xn+#B-yY!CB2@`Uz({}}w+ z0sni*39>rMC!Ay|1B@;al%T&xE(wCf+`3w>N)*LxZZZYi{5sqiVWgbNd>W*X?V}C- zjQ4F7e_uC<rrMQOhnlaly82U^Bnjl*Ps^;dHP4)`o{y`Br!oGok57zV%6AfCzrx6b zRtkN#-_l5Q6R888F!*RBowS6c#F3(y>UOHbtewQkq?m$*#@ZvWbu{4i$`aeKM8tc^ zL5!GL8gX}c+qNUtUIcps1S)%Gsx*MQLlQeoZz2y2OQb(A<DL3;)MXXTQ`RBN=2Nqo zm|%J=&6B(G>73Jc3`LmlQf0N{RTt;wa`6h|ljX1V7UugML=W5-STDbeWT<mSwJhXL z!aS2TX&k8S`&e){@?u0)ndhS|I5*P`AXfL2^cmXY+Y4+;A$3^)gf$wPi}{Qvn3?Ry z7vEE&$5<Ru_Q#P8!_=cYOw%AF1OLsyT<5t8ut0pRH0SVIuwRf%vxrV$xV&O$O=zu4 zELRNs*8N_EW5BHpx`+}r&eA)WZcQ>iEMjPQ$({hn_s&NDXz<!=4N<vgMcI^yn~Zh` zwvKP>s6?PLySp$?L`0ilH3vCUO{JS0Dp`z;Ry$6}R@1NdY7rxccbm$+;ApSe=2q!0 z()3$vYN0S$Cs)#-OBs{_2uFf}L4h$;7^2w20=l%5r9ui&pTEgg4U!FoCqyA<B2GjD zdx)l4;&dHHVJdZ^Xw&qfECp24<|xWqw2<&|dxV~DnR~Oku@x1r5LF<ueYl&b5>6r2 zC5s72l}i*9y|KTjDE5gVlYe4I2gGZD)e`Py2gq7cK4at{bT~DSbQQ4Z4sl)kqXbbr zqvXtSqMrDdT2qt-%-HMoqeFEMsv~u)-NJ%Z*ipSJUm$)EJ+we|4*-Mi900K{K|e0; z1_j{X5)a%$+vM7;3j>skgrji92K1*Ip{SfM)=ob^E374JaF!C(cZ$R_E>Wv+?Iy9M z?@`#XDy#=z%3d9&)M=F8Xq5Zif%ldIT#wrlw(D_qOKo4wD(fyDHM5(wm1%7hy6euJ z%Edg!>Egs;ZC6%ktLFtyN0VvxN?*4C=*tOEw`{KQvS7;c514!FP98Nf#d#)+Y-wsl zP3N^-Pnk*{o(3~m=3DX$b76Clu=jMf9E?c^cbUk_h;zMF&EiVz*4I(rFoaHK7#5h0 zW7CQx+xhp}Ev+jw;SQ6P$QHINCxeF8_VX=F3&BWUd(|PVViKJl@-sYiUp@xLS2NuF z8W3JgUSQ&lUp@2E(7MG<OQ<1?G8Oxn1mPIGm|_f4YK>`sh4X!LQFa6;lInWqx}f#Q z4xhgK1%}b(Z*rZn=W{wBOe7YQ@1l|jQ|9ELiXx+}aZ(>{c7Ltv4d>PJf7f+qjR<fc zzR_{hk@QY1I>U8i%XZZFJkj&6D^s;!>`u%OwLa*V5Js9Y$b-mc!t@{C415$K38iVu zP7!{3Ff%i_e!^LzJWhBgQo=j5k<<($$b&%%Xm_f8RFC_(97&nk83KOy@I4k?(k<(6 zthO$3yl&0x!Pz#!79bv^?^85K<UzI_1JfNcJfpb(WrpN_?tYT4KP^sShAp~8Y=Yws zA@JeU`}g*o&VzCDoSv8w<0m@Te#}RYK=_*+uR+WvQh1{$#1D!v7brY3q!8^<WIBmB zlc38GyC2MM5lZ=XHVy=Dh?$PiUm%y}K+T{hTd#Tq;{u8ES9|k;|6DUQQ~dPK|Bj{e z-yh=tI;M(zBiyWP^^N}hb?O}{`wysi@QxX46O{{n0Q3r2R{;O6khWXEYRD>5e7uS$ zJ33yka2VzOGUhQXeD{;?%?NTYmN3{b0|AMtr(@bCx+c=F)&_>PXgAG}4gwi>g82n> zL3DlhdL|*^WTmn;XPo62HhH-e*XIPSTF_h{#u=NY8$B<fbww+h*xf==B0x6v(_G?& z!09&2Mgs&r58WroXO=@73B$sl<)3NA_!ZVqwBIT1>UW=5@PD{P5n~g5XDg?Fzvb_u ziK&CJqod4srfY2T?+4x@)g9%3%*(Q2%YdCA3yM{s=+QD0&IM`8k8N&-6%iIL3kon> z0>p3BUe!lrz&_ZX2FiP%MeuQY-xV<vshB><n!bv2W_v>V%K?=bGPOM&XM0XRd7or< zy}jn_eEzuQ>t2fM9ict#ZNxD7HUycsq76IavfoNl$G1|t*qpUSX;YgpmJrr_8yOJ2 z(AwL;Ugi{gJ29@!G-mD82Z)46T`E+s86Qw|YSPO*OoooraA!8x_jQXYq5vUw!5f_x zubF$}lHjIWxFar8<GeFf9-V5`nyfk8^M5y!M_OoGbS<;@bkn%`fT<BaStsh=v0+@5 zOcC73N9RyOeoa>)tTg8z-FEz)a=xa`xL~^)jIdezZsg4%ePL$^`VN#c!c6`NHQ9QU zkC^<0f|Ksp45+YoX!Sv>+57q}Rwk*2)f{j8`d8Ctz^S~me>RSakEvxUa^Pd~qe#fb zN7rnAQc4u$*Y9p~li!Itp#iU=*D4>d<Ci>vJ{Z~}kqAOBcL8ln3YjR{Sp!O`s=5yM zWRNP#;2K#+?I&?ZSLu)^z-|*$C}=0yi7&~vZE$s``IE^PY|dj^HcWI$9ZRm>3w(u` z-1%;;MJbzHFNd^!Ob!^PLO-xhhj@XrI81Y)x4@<gMtV_Y5Go*HbFejp#(E*>FdsI( za`o4Gy(`T$P?PB?s>o+eIOtuirMykbuAi65Y_UN1(?jTCy@J8Px`%;bcNmPm#Fr!= z5V!YViFJ!FBfEq>nJFk0^RAV1(7w+X<r55RW+Y)^S4T<DuFltq?k*3hd&xYsSj2B& zUGX;nxg;#xjm8VFJ3>`HRgP;nJHJdMa!}&vvduCMoslwHTes_I76|h>;(-9lbfGnt zoZom<C?fEb8E8pWCy|-@u{HxBzv)p1MMq};qNB?SI|@9&P6^gO<;M*Bytc@_K~04{ z;AwbRq5D5P(<L_6N9;<Uu?iTHtN4K;8c}I#KqwaH1qMUHKO}r&^w)OUAS0!WB?-XI zrh7E_KOqY}fSQ15Wq<fRKF}+ChGgSi!dwd$-K{x_m@y;3e?VEQrhW;@$QT-V1=~Rc zBoP7r3KOd#ifEufE=S{`jX+2nWI7w9J4?El&r6%hx-hp!CK|B^D%OJ?TF7K$mo!0< zB3|TLdvs$Z>akOt7<zd8GJ~gO+}ci6N;r4aCNk+Od?kJbIVo(1&oUbk)6HY`TXIq= zqUjdch<xQHvfMhy%lGY0+*M8unTxdt(vP2$mb?<CzZfCG?nUX4KnjU9MrRlaDN3vm zp_4jfRuMx5c+|-5^D1H-X8if1gpxo_C>59AuTX4b$)G8TzJ&m*BV8!vMs9#=e0tWa z%<kVjvU5}5jenPuQ3M}mcKL_0sC!*NdRI6Mjlj77o>)84R=3?tfh72~=Rc;fXwj+x z+25xapYK@2@;}6)@8IL+F6iuJ_B{&A-0=U=U6WMbY>~ykVFp$XkH)f**b>TE5)shN z39E2L@JPCSl!?pkvFeh@6dCv9oE}|{GbbVM!XIgByN#md&tXy@>QscU0#z!I&X4;d z&B&ZA4lbrHJ!x4lCN4KC-)u#gT^cE{Xnhu`0RXVKn|j$vz8m}v^%*cQ{(h%FW8_8a zFM{$PirSI8@#*xg2T){A+EKX(eTC66Fb})w{vg%Vw)hvV-$tttI^V5wvU?a{(G}{G z@ob7Urk1@hDN&C$N!Nio9YrkiUC{5qA`KH*7CriaB;2~2Od>2l=WytBRl#~j`<pdG z4M}tb<uU%2ridMFfC^+i<L~BM1~RL!4p+A^)XrawXV{TA-9EIXauS*Dg}JdVIEw4f z`Ulf7uYtc(vYyEo44G0z5l@5cL?;sbE&RWE2C2qxrkkaRYU_fPr>EYsj}jqK2xD*3 ztEUiPZzEJC??#Tj^?f)=sRXOJ_>5aO(|V#Yqro05p6)F$j5*wYr1zz|T4qz$0K(5! zr`6Pqd+)%a9Xq3aNKrY9843)O56F%=j_Yy_;|w8l&RU1+B4;pP*O_}X8!qD?IMiyT zLXBOOPg<*BZtT4LJ7DfyghK|_*mMP7a1>zS{8>?}#_XXaLoUBAz(Wi>$Q!L;oQ&cL z6O|T6%Dxq3E35$0g5areq9$2+R(911!Z9=wRPq-pju7DnN9LAfOu3%&onnfx^Px5( zT2^sU>Y)88F5#ATiVoS$jzC-M`vY8!{8#9O#3c&{7J1lo-rcNK7rlF0Zt*AKE(WN* z*o?Tv?Sdz<1v6gfCok8MG6Pz<GK)kM#Fa}sldEi&546xI(*0gn=!^c0Tb?>ecx9?C zrQG5j^2{V556Hj=xTiU-seOCr2ni@b<&<!)7uosgxZ*i0qYym72`j<}Tyrcivr8hF zTWq=6QQ);+$xc~E4QH2u0lmUt^J?RB2;UgtoqnRS3b?LRcZe%+5j^7dPEf<r=xdOY zyy(>!j><hqkK&LV11o%uPE<DDKhW(+;>GyHbv!&uBbHjH-U5Ai-UuXx0lcz$D7%=! z&zXD#Jqzro@R=hy8bv>D_CaOdqo6)v<Hr<wD^7>FjZldma5D+R;-)y1NGOFYqEr?h zd_mTwQ@K2veZTxh1aaV4F;YnaWA~|<8$p}-eFHashbWW6Dzj=3L=j-C5Ta`w-=QTw zA*k9!Ua~-?eC{Jc)xa;PzkUJ#$NfGJOfbiV^1au;`_Y8|{eJ(~W9pP9q?gLl5<hv` zq-R>E6|e{xkT@s|Ac;yk01+twk_3nuk|lRu{7-zOjLAGe!)j?g+@-;wC_=NPIhk(W zfEpQrdR<hjW6irILMx?a`MP52iT|l<EuL}y=FO+aN8oz%Xw$R#i}Pd~QvUs-FEq>y z^Q$YBs%>$=So>PAMkrm%yc28YPi%&%=c!<}a=)sVCM51j+x#<2wz?2l&UGHhOv-iu z64x*^E1$55$wZou`E=qjP1MYz0xErcpMiNYM4+Qnb+V4MbM;*7vM_Yp^uXUuf`}-* z_2CnbQ);j5;Rz?7q)@cGmwE^P>4_u9;K|BFlOz_|c^1n~%>!uO#nA?5o4A>XLO{X2 z=8M%*n=IdnXQ}^+`DXRKM;3juVrXdgv79;E=ovQa^?d7wuw~nbu%%l<Xf~?N3{;D$ zdjm^~#KJ}13CHdp-*t*f#IzP~WB3Yc+<O@T)t>sjUugE8HJ9zvZIM^nWvjLc-HKc2 zbj{paA}ub~4N4Vw5oY{wyop9SqPbWRq=i@Tbce`r?6e`?`iOoOF;~pRyJlKcIJf~G z)=BF$B>YF9>qV#dK^Ie#{0X(QPnOuu((_-u?(mxB7c9;LSS-DYJ8Wm4gz1&DPQ8;0 z=Wao(zb1RHXjwbu_Zv<=9n<XR?{HbR^Dll@oqz*Z3oqz|IZQaMx#n2R2moU-^D<z- zga}0seGM5-bTV&hZd771e5gI3t`$^>jK28sS}WssjOL!3-E5>d17Lfnq0V$+IU84N z-4i$~!$V-%Ik;`Z3MOqYZdiZ^3nqqzIjLE+zpfQC+LlomQu-uNCStj%MsH(hsimN# z%l4vpJBs_2t7C)x@6*-k_2v0FOk<1nIRO3F{<KiOBUP%D=G#h*?adbA>E?2DnS}w> z#%9Oa{`RB5FL5pKLkg59#x~)&I7GzfhiVC@LVFSmxZuiRUPVW*&2ToCGST0K`kRK) z02#c8W{o)w1|*YmjGSUO?`}ukX*rHIqGtFH#!5d1Jd}&%4Kc~Vz`S7_M;wtM|6PgI zNb-Dy-GI%dr3G3J?_yBX#NevuYzZgzZ!vN>$-aWOGXqX!3qzCIOzvA5PLC6GLIo|8 zQP^c)?NS29hPmk5WEP>cHV!6>u-2rR!tit<H6K<`F|-L2nvu=hj?^+`eij=B<V}b@ z@B)puoO3cGGxU^niF+;tL-h54X~zdAd5S??I#`w|&&6~3d&$7VkMDU-6b_LMwminU z$6hC<ZypQN)Rld1_YatN&gKL*aM%5O&gsK9^UqsYJ)vc9izs}?3Oc+6fuC6t9H`OC zokZOqyS@s3%8l{A-KTu#<)|R8KfY`!NKd>#F6`_;%4{q^6){_CHGhvAs=1X8Fok+l zt&mk>{4ARXVvE-{^tCO?inl{)o}8(48az1o=+Y^r*AIe%0|{D_5_e>nUu`S%zR6|1 zu0$ov7c`pQEKr0sIIdm7hm{4K_s0V%M-_Mh;^A0*=$V9G1&lzvN9(98PEo=Zh$`Vj zXh?fZ;9$d!6sJRSjTkOhb7@jgSV^2MOgU^s2Z|w*e*@;4h?A8?;v8JaLPCoKP_1l- z=Jp0PYDf(d2Z`;O7mb6(_X_~z0O2yq?H`^c=h|8%gfywg#}wIyv&_uW{-e8e)YmGR zI0NNSDoJWa%0ztGzkwl>IYW*DesPRY?oH+ow^(>(47XUm^F`fAa0B~ja-ae$e>4-A z64lb<us@kdtAYl$q}T24sw~n@T~wTnN38G!o-w}D+ML3`i~B`pnM`W>_;|W0ppKI+ zxu2VLZzv4?Mr~mi?WlS-1L4a^5k+qb5#C)ktAYGUE1H?Vbg9qsRDHAvwJUN=w~AuT zUXYioFg2Dx-W)}w9VdFK#vpjoSc!WcvRZ_;TgHu;LSY*i7K_>Px{%C4-IL?6q?Qa_ zL7l=EEo|@X&$gX;fYP02qJF~LN9?E-OL2G(Fo4hW)G{`q<UNTVyu{YECrRdQW8>nW zTIuc+-1VJvKgph0jAc(LzM);Pg$MPln?U|ek{_5nNJHfm-Y#ec+n#Yf_e>XfbL<Jj zC4<j?s_P+<9*S#zb-*>bN)eqHEDr0#?<;TskL5-0JGv|Ut{=$Xk8hlwbaMXdcI3GL zY-hykR{zX9liy$Z2F3!z346<C_U+V9&~+9_ThfF;_W=t2C&Z*UOnbsL(`lg7Y_9mJ z;x7x7msWl4Kb@@$yKgTE5^PM^6EXwa%=X!zvj`?R^UpwmF%I*&db9Mf*}H~d_$T0q zJoI|73QSz<E7i=;AOnv*#a{snA^{$tEWm9D%Wo|FR=1KqgS+BG;5mCU#nURc7oq_o z-O{0O`-W6(TF8B|;h9i-$1&@yllU>uu%9@-y6Gda`X2*ixlD_P@<}K?AoV?(%lM%* z(xNk=|A()443aGj)-~I<t=+b5+qP|cw{6?DZQHi(?%l@p+<VT%oIB@CM6Fs;Kk7%t z%J?!X^U3#ByqT%i5eJsK{B+>Df3J+UA2p2lh6ei^pG*HL#SiThnIr5WZDXebI)F7X zGmP-3bH$i$+(IwqgbM7h%G5oJ@4{Z~qZ#Zs*k7eXJIqg;@0kAGV|b=F#hZs)2BYu1 zr8sj#Zd+Iu^G}|@-dR5S*U-;DqzkX3V0@q-k8&VHW?h0b0?tJ-Atqmg^J8iF7DP6k z)W{g?5~F*$5x?6W)3YKcrNu8%%(DglnzMx5rsU{#AD+WPpRBf``*<8F-x75D$$13U zcaNXYC0|;r&(F@!+E=%+;bFKwKAB$?6R%E_QG5Yn5xX#h+zeI-=mdXD5+D+lEuM`M ze+*G!zX^xbnA?~LnPI=D2`825Ax8rM()i*{G0gcV5MATV?<7mh+HDA7-f6nc@95st zz<x3S-=O9@1Qx`EDk(L<enRy4$&H~91Dqvi*j`&df5YvnJ92?*;!1D{y*{vSKT#)! z`8&J6_mr>C_si$<QVr`<>{|&=$MUj@n<ZkLuF(toIVKp(6>Lxl_HwEXb2PDH+V?vg zA^DJ<z&3Iv0y>%dn069O9<Ouc(<|V99`h3|>TNK-jV}cQKh|$L4&Uh`?(z$}#d+{X zm&=KTJ$+KvLZv-1GaHJm{>v=zXW%NSDr8$0kSQx(DQ)6<U)@wRatQ0n^IU+=Y(tsk z>S?%sWSHUazXSEg_g3agt2@0nyD?A?B%9NYr(~CYX^&U#B4XwCg{%YMYo<flw!Uv7 zbJrd*bK4--;t<&j37ZT@jUbZ8-Qk8uL-t5+XilHP`7ykYb{?`@R8n-Wi%nqiF#0hx zPg@t)?pcqM%L}PMzv3OTb>%e68HVJ7`9KR`mE*Wl7&5t71*R3F>*&hVIaZXaI;<mI z|Ap3H0(aXS@X(VR*Ol`mi%np^ZEHYHRc@ElhxGOh`)3v}+0ls>2a$?;{Ew{e3Hr1* zbf$&Fyhnrq7^hNC+0#%}n^U2{ma&eS)7cWH$bA@)m59rXlh96piJu@lcKl<>+!1#s zW#6L5Ov%lS(?d66-(n`A%UuiIqs|J|Ulq0RYq-m&RR0>wfA1?<34tI?MBI#a8lY{m z{F2m|A@=`DpZpwdIH#4)9$#H3zr4kn2OX!UE=r8FEUFAwq6VB?DJ8h59z$GXud$#+ zjneIq8uSi&rnG0IR8}UEn5OcZC?@-;$&Ry9hG{-1ta`8aAcOe1|82R7EH`$Qd3sf* zbrOk@G%H7R`j;hOosRVIP_2_-TuyB@rdj?(+k-qQwnhV3niH+CMl>ELX(;X3VzZVJ ztRais0C^L*lmaE(nmhvep+peCqr!#|F?iVagZcL>NKvMS_=*Yl%*OASDl3(mMOY9! z=_J$@nWpA-@><43m4olSQV8(PwhsO@+7#qs@0*1fDj70^UfQ(ORV0N?H{ceLX4<43 zEn)3CGoF&b{t2hbIz;Og+$+WiGf+x5mdWASEWIA*HQ9K9a?-Pf9f1gO6LanVTls)t z^f6_SD|>2Kx8mdQuiJwc_SmZOZP|wD7(_ti#0u=io|w~gq*Odv>@8JBblRCzMKK_4 zM-uO0Ud9>VD>J;zZzueo#+jbS7k#?W%`AF1@ZPI&q%}beZ|ThISf-ly)}HsCS~b^g zktgqOZ@~}1h&x50UQD~!xsW-$K~whDQNntLW=$oZDClUJeSr2$r3}94Wk1>co3beS zoY-7t{rGv|6T?5PNk<Z}${YyAJWnFYd_(8lLGvKygk2|9Q-+MgjJ$&KDpf_$YQ?IV zR<<Gym6HGU;;bqndvCX&FnDKQ=}UsHCpxg@6}a(-T<EY&D8er_EV=18JTgdg;NT>Y zj*XjF()ybvnVz5=BFnLO=+1*jG>E7F%&vm6up*QgyNcJJPD|pHoZ!H6?o3Eig0>-! zt^i-H@bJ;^!$6ZSH}@quF#RO)j>7A5kq4e+7gK=@g;POXcGV28Zv$jybL1J`g@wC# z_DW1ck}3+n@h2LFQhwVfaV@D+-kff4cel<IcrWN-M5x8!Ow)bPrn9?d=kx(pB}Zxh zwSayS{c`WwwOA@rCTI0Jpf!LQ0BRAS&Yy^!S}_9)?rVFlb`0@yQL-u&w?3z@i}YtX z&orQmrCH2ERpv_}L+8*5x0r*ar=W0%g{;gnuf;Y%mP^vf>ZC0;0e<L_F@Y}Mun9fT z3*0k%P9JzWMDIiaJzHp78U80rEHg<Jm$kJ?b#g(IM#`$0x_Y_c_XAFK5m}j&*?B9q zSa0I1M-ZM%K;M9EzJ}%_K>f?pA#*PPd8Kk8sO1wza&BHQFblVU8P1=-qScHff^^fR zycH!hlHQs7iejITpc4UaBxzqTJ}Z#^lk{W(cr`qtW~Ap;HvuUf#MxgEG?tEU+B?G% znu<!7LIgR13M|s?%o25M!Ve^n&=M7iB|RnrBtHAJ6<h+az+`2J^UgIdUBonl2DJ}4 zu`>b0I(s@XvI(lva}$Z7<}Qg=rWd5n)}rX{nb+Aw;}?l9LZI-`N-*hts=c6XgjfJs ztp>-686v6ug{glEZ}K=jVG|N1WSWrU*&ue|4Q|O@;s0#L5P*U%Vx;)w7S0ZmLuvwA z@zs2Kut)n1K7qaywO#TbBR`Q~%mdr`V)D`|gN0!07C1!r3{+!PYf9*;h?;dE@#z(k z;o`g~<>P|Sy$ldHTUR3v=_X0Iw6F>3GllrFXVW?gU0q6|ocjd!glA)#f<BmJPFLB} zEhYST*M)esm5(_%C4PWZ`=77E`8iyIH2-_uviC}ybZBAkkU&oTXd<qb;^^X8)}WK^ zZ7VNp$iQ33bjEa{enF`vr_fcnpn5o$xWG}@)wW01agAanwm7U-_6$&kb?+oC`!H4+ z&pP-ziAbnW{HLL*!kOtg5&^#>0G7i20ly>qxRljgfO2)RVpvmg#BSrN)GbGsrIb}9 z1t+r;Q>?MGLk#LI5*vR*C8?<QWz^KoEAbUtRx5!VLSb(M>McB|=AoAjuDk&Pn`KQo z`!|mi{Cz@BGJ!TwMUUTkKXKNtS#OVNxfFI_Gfq3Kpw0`2AsJv9PZPq9x?~kNNR9BR zw#2jp%;FJNoOzW<aW@Re3s=7#KmRWefd}w)30vR+&FhD2(gU`Fzb()i9D)B9j6NR7 zkJkCe-V+Ma{GvGf>>tE#zskPICp>XSs?|B0E%DaJH)rtLA}$Y>?P+vEOvr#8=pylh zch;H3J`RE1{97O+1(1msdshZx$it^VfM$`-Gw>%NN`K|Tr$0}U`J?EBgR%bg=;et0 z_en)!x`~3so^V9-jffh3G*8Iy6sUq=uFq%=OkYvHaL~#3jHtr4sGM?&<HYL8mdfSx ztkF3uXPD7B%V!)xiIi#%hUfzhNcr^0s8kh=m867SDXDO+xe{k-jp8#%R!yLQpP$4P zf+D;?r|{x)(t_iuhw-Sf9iN(g5)W$qGm7jNa&s+!+UzY%8B+JZx+Aosvv8kXrU6rb zbQ18o1Dg{bl=D8~XI)Q-KVuC}csZdF-ol*J*r7G~M0*vV{!wbJm+#70TdwI4^jg?I z%o(r?JZMS5y2Jci`m?!x+iXdwln`R~M+kHX0;phyD<h&PZ%FP7M8{whE<vaSf=2n@ zL*m{)inJF%@r0tqzHPZthaV66%Yd~6StFWr<`uzSKz^t?FA@TuzVR~p6~1ziob2qD zQ%Zy{Gz{hEqc|tEc0|+7<RW>uY&U8N1G}QTMdqBM)#oLTLdKYOdOY%{5#Tgy$7QA! zWQmP!Wny$3YEm#Lt8TA^CUlTa{Cpp=x<{9W$A9fyKD0ApHfl__Dz4!HVVt(kseNzV z5Fb`|7Mo>YDTJ>g;7_MOpRi?kl>n(ydAf7~`Y6wBVEaxqK;l;}6x8(SD7}Tdhe2SR zncsdn&`eI}u}@^~_9(0^r!^wuKTKbs-MYjXy#-_#?F=@T*vUG@p4X+l^SgwF>TM}d zr2Ree{TP5x@ZtVcWd3++o|1`BCFK(ja-QP?zj6=ZOq)xf$CfSv{v;jCcNt4{r8f+m zz#dP|-~weHla%rsyYhB_&LHkwuj83RuCO0p;wyXsxW5o6{)zFAC~2%&NL?<TC?7g@ zfqoa;enQ6=kuI+FtDKTp*4K87i40xomn^i4?-U687)dVCvUn@i5Um!YDhz&=8zf3a z*UH64F1?04tzG*#1=sim1h4x8=I0_~0BivP+v+Lk^FOu&1AE%&=MCtDidMqo6t?0> z=mA}szjHKsVSSnH#hM|C%;r0D$7)T`HQ1K5vZGOyUbgXjxD%4xbs$DAEz)-;iO?3& zXcyU*Z8zm?pP}w&9ot_5I;x#jIn^Joi5jBDOBP1)+p@G1U)pL6;SIO>Nhw?9St2UN zMedM(m(T6bNcPPD`%|9dvXAB&IS=W4?*7-tqldqALH=*UapL!4`2TM_{`W&pm*{?| z0DcsaTdGA%RN={Ikvaa&6p=Ux5ycM){F1OgOh(^Yk-T}a5zHH|=%Jk)S^vv9dY~`x zG+!=lsDjp!<Zw<>D}7o94RSQ-o_g#^CnBJlJ@?saH&+j0P+o=eKqrIApyR7ttQu*0 z1f;xPyH2--)F9uP2#Mw}OQhOFqXF#)W#BAxGP8?an<=JBiokg;21gKG_G8X!&Hv;7 zP<bTe@P=slWtf9t{y!Y^e<ETc?nc%wPQRvkq88RB0!Bu^b6pt&TLZKI9P1{lZ8~AA zVgBH1ENoP|cw1DcPRqz@QgYQNgGokM3*xNG9!q77#Av0)In!jXVb{72TcVC`DP;(1 zk+-(Y$?Lo4!^1FLOIH%Rhdh-}(GOz7`~{5l*$>9Vpzm#@;^-lf=6POs>UrGm-F>-! zm;3qp!Uw?VuXW~*Fw@LC)M%cvbe9!F(Oa^Y6~mb=8%$lg=?a0KcGtC$5y?`L5}*-j z7KcU8WT<U{=H%2rUviZgG-R^Il^D(umJq{>>2PpKx<58`m((l9^aYa3uP{PMb)nvu zgt;ia9=ZofxkrW7TfSrQf4(2juZRBgcE1m;WF{v1Fbm}zqsK^>sj=yN(x}v9#_{+C zR4r7abT2cS%Wz$RVt!wp;9U7FEW&>T>YAjpIm6ZSM4Q<{Gy+aN`Vb2_#Q5g@62<R4 zMx$6~v*mbHZfPOwxp<OAlg!hqzrj>uR_>II@eiHaay+JU$J=#>DY9jX*2A=&y8G%b zIY6gcJ@q)uWU^mSK$Q}?#Arq;HfChnkAOZ6^002J>fjPyPGz^D5p<P8nMaP(*LAGP z#-zU2OJ^z3Db=`NZQ>}o;h2VLNTI{HGg!obo3K!*I~a7)p-2Z3hCV_hnY?|6i`29b zoszLpkmch$mJeupLbt4_u-<3k;VivU+ww)a^ekoIRj4IW4S<FRqdy{2RiwFY> z{z%4_dfc&HAtm(o`d{CZ^AAIE5XCMvwQSlkzx3cLi?`4q8;iFTzuBAddTSWjfcZp* zn{@Am!pl&fv#k|kj86e$2%NK1G4kU=E~z9L^`@%2<%Dx%1TKk_hb-K>tq8A9bCDfW z@;Dc3KqLafkhN6414^46Hl8Tcv1+$q_sYjj%oHz)bsoGLEY1)ia5p=#eii(5AM|TW zA8=;pt?+U~<O0(jQ4OX$<Sydbm#~h&)W7v$5#U`FsQ0@Df3>>`|J(B85BKE0cB4n> zWrgZ)Rbu}^A=_oz65LfebZ(1xMjcj_g~eeoj74-Ex@v-q9`Q{J;M!mITVEfk6cn!u zn;Mj8C&3^8Kn%<`Di^~Y%Z$0pb`Q3TA}$TiOnRd`P1XM=>5)JN9tyf4O_z}-cN|i> zwpp9g`n%~CEa!;)nW@WUkF&<|wcWqfL35A}<`YRxV~$IpHnPQs2?+Fg3)wOHqqAA* zPv<6F6s)c^o%@YqS%P{tB%(Lxm`hsKv-Hb}MM3=U|HFgh8R-|-K(3m(eU$L@sg=uW zB$vAK`@>E`iM_rSo;Cr*?&wss@UXi19B9*0m3t3q^<)>L%4j(F85Ql$i^;{3UIP0c z*BFId*_mb>SC)d#(WM1%I}YiKoleKqQs<A5DyhV`a20Ec$*bh4vW6b6#9lSmf~?r* zlcL&gHfFhvg{m>wkdhRt9%_dAnDaKM4IEJ|QK&BnQ@D;i-ame%MR5XbAfE0K1pcxt z{B5_&OhL2cx9@Sso@u2T56tE0KC`f4IXd_R3ymMZ%-!e^d}v`J?XC{nv1mAbaNJX| zXau+s`-`vAuf+&yi2bsd5%xdqyi&9o;h&fcO+W|XsKRFOD+pQw-p^pnwwYGu=hF7& z{cZj$O5I)4B1-dEuG*tU7wgYxNEhqAxH?p4Y1Naiu8Lt>FD%AxJ811`W5bveUp%*e z9H+S}!nLI;j$<*Dn~I*_H`zM^j;!rYf!Xf#X;UJW<0gic?y>NoFw}lBB6f#rl%t?k zm~}eCw{NR_%aosL*t$bmlf$u|U2hJ*_rTcTwgoi_N=wDhpimYnf5j!bj0lQ*Go`F& z6Wg+xRv55a(|?sCjOIshTEgM}2`dN-yV>)W<s8ZX^F)rd_eolw0O4mBB)~DVnQ5dX zh1MfhOJ9Pzd<LR=!m@e-i*a1>f$J58>lNVhjRagGZw?U9#2p!B5C3~Nc%S>p`H4PK z7vX@|Uo^*F4GXiFnMf4gwHB;Uk8X4TaLX4A>B&L?mw4&`XBnLCBrK2FYJLrA{*))0 z$*~X?2^Q0KS?Yp##T#ohH1B)y4P+rR7Ut^7(kCwS8QqgjP!aJ89dbv^XBbLhTO|=A z|3FNkH1{2Nh*j{p-58N=KA#6ZS}Ir&QWV0CU)a~{P%yhd-!ehF&~gkMh&Slo9gAT+ zM_&3ms;1Um8Uy0S|0r{{8xCB&Tg{@xotF!nU=YOpug~QlZRKR{DHGDuk(l{)d$1VD zj)3zgPeP%wb@6%$zYbD;Uhvy4(D|u{Q_R=fC+9z#sJ|I<$&j$|kkJiY?AY$ik9_|% z?Z;gOQG5I%{2{-*)Bk|Tia8n>TbrmjnK+8u*_cS%*;%>R|K|?urtIdgTM{&}Yn1;| zk`xq*Bn5HP5a`ANv`B$IKaqA4e-XC`sRn3Z{h!hN0=?x(kTP+fE1}-<3eL+QDFXN- z1JmcDt0|7lZN8sh^=$e;P*8;^33pN>?S7C0BqS)ow4{6ODm~%3018M6P^b~(Gos!k z2AYScAdQf36C)D`w&p}V89Lh1s88Dw@zd27Rv0iE7k#|U4jWDqo<pw`rT0F1=giby zSvwo-^K5P3?J)*t>UP;-He5cd4V7Ql)4S+t>u9W;R-8#aee-Ct1{fPD+jv&zV(L&k z)!65@R->DB?K6Aml57?psj5r;%w9Vc3?zzGs&kTA>J9CmtMp^Wm#1a@cCG!L46h-j z8ZUL4#HSfW;2DHyGD|cXHNARk*{ql-J2W`9DMxzI0V*($9{tr|O3c;^)V4jwp^RvW z2wzIi`B8cYISb;V5lK}@xtm3NB;88)Kn}2fCH(WRH1l@3<q>XaO7{R*Lc7<o&*hfu zA~y`eH5--g@QhTK;~V;@kFVlBwXL?-xOV}&0LvXLf@G+<_zX>{ZN1m+#&diI7_qzE z?BS+v<)xVMwt{IJ4yS2Q4(77II<>kqm$Jc3yWL42^gG6^Idg+y3)q$-(m2>E49-fV zyvsCzJ5EM4hyz1r#cOh5vgrzNGCBS}(Bupe`v6z{e<CcS{QzMUWAq_nFEe{Vru{6c z|KZrQ|J#+PLzqygyi=3m4BdhVKj0!NsG<U+fK<RKGUFER2&IV8$0<|`B#}lU^@ar> z)cP*a8VCbRuhPp%BUwIRvj-$`3vrbp;V3<u<D|$cxCAE}!0I%pPCYQ!e>wmAUt{?F z0OO?Mw`AS?y@>w%(pBO=0lohnxFWx`>Hs}V$j{XI2?}Btl<q&n{>vIl7!ZMZukDF7 z^6Rq2H*36KHxJ1xWm5uTy@%7;N0+|<>Up>MmxKhb;WbH1+=S94nOS-qN(IKDIw-yr zi`Ll^h%+%k`Yw?o3Z|ObJWtfO|AvPOc96m5AIw;4;USG|6jQKr#QP}+BLy*5%pnG2 zyN@VMHkD`(66oJ!GvsiA`UP;0kTmUST4|P>jTRfbf&Wii8~a`wMwVZoJ@waA{(t(V zwoc9l*4F>YUM8!aE1{?%{P4IM=;NUF|8YkmG0^Y_jTJtKClDV3D3~P7NSm7BO^r7& zWn!YrNc-ryEvh<l>N$$!P%l$Y_P$s8E>cdAe3=@!Igo^0diL6`y}enr`+mQD;RC?w zb8}gXT!aC`%rdxx2_!`Qps&&w4i0F95>;6;NQ-ys;?j#Gt~HXzG^6j=Pv{3l1x{0( z4~&GNUEbH=9_^f@%o&BADqxb54EAq=8rKA~4~A!iDp9%eFHeA1L!Bb8Lz#kF(p#)X zn`CglEJ(+tr=h4bIIHlLkxP>exGw~{Oe3@L^zA)|Vx~2yNuPKtF^cV6X^5lw8hU*b zK-w6x4l&YWVB%0S<MnSL9Gxa+tjTFHHk?^*)Ho+49c->mN<Omsv{<w{M_SX6FrRz& z-fl>{O|!`Sh6H45!7}oYPOc+a#a|n3f%G@eO)N>W!C|!FNXV3taFdpEK*A1TFGcRK zV$>xN<sb#LnQM_qFZRkIc7CDsZFN=(Q&<qDsEKW^u8J}ZvG!S9$V=Gpzacv2#nfBS znUI`V(%8<9w_O9dOzg3pg1KA|xV$L844HD=$^jD7e@tLXu{A?7Q&KD5PmJj(O0Rd} zJ53P3?S>%??ii7jx5D69O>W6O`$M)iQU7o!TPG*+>v6{TWI@p)Yg$;8+W<RxFU`e7 z{bfN`O;EWn(uTD$pTCdDU6G$G0Aqu7uvVLoob|0ph2_mnTUUK%nSix9lQosDs+mxO zQ)7`f=;AM4%2c=yc9`uhF*w;)zK;r4%XrPwRkIJ<^=paRRlSD`dwakGdwU2Bif{P} zfp7I1)Xq0-2F1I22il{2mmE@iA01-nprr3LANk0!$!7K|%&<;M;U1N}-LBaypIar} z*;k|TNIUoLrz6<fTjssa=J@&jpe!_)+(GwYVGQx4+*O=>yE<VTJM=nHJuCiK`4nKF zMjirx-t2fH2j+4NIlyJp!aruMd-O#Tg;Fk{xd%A`<awAfI*L)`XoGXH5K#itZ42AK z6MeknJlNNkn9oZo$LQFbqvB&R31geSNKB|Eazxv7`mmBaie>9DVBMB=vnONSQ6k1v z;u&C4wZ_C`J-M0MV&MpOHuVWbq)2LZGR0&@A!4fZwTM^i;GaN?xA%0)q*g(F0PIB( zwGrCC#}vtILC_irDXI5{vuVO-(`&lf2Q4MvmXuU8G0+oVvzZp0Y)zf}Co0D+mUEZz z<V<U=H+idKcZP;R9F0*dBIp}a_hqpooWwb4eC!W`xqypzPrNaJ>gwR+5y!d(V>s1} zji+mrd_6KG;$@Le2Ic&am6O+Rk1+QS?urB4$FQNyg2%9t%!*S5Ts{8j*&(H1+W;0~ z$frd%jJjlV;>bXD7!a-&!n52H^6Yp}2h3&v=}xyi>EXXZDtOIq@@&ljEJG{D`7Bjr zaibxip6B6M<AvX7F;}xji!{#20`v^r=IX+S_8&y7yMi<{TDCs{)lIgOhlB@q8PxV_ z^K_bV6}m&uNF?(jS7SzI3UW;N4K*THM7W(~LZca^z+Y~4W)ZN|d2h1>f3t#-*Tn7p z96y<T2y#Xcz~YB6wfpE5F$BO)&z2<@Hkm?h8Dj7m{B!BU^}>x1Qv<Gs5lPx{*#im% z@NUr_Fb3h-MOjdYw^i7AWS^$PJ|m%_P(XS98V&Mc6vKJ|E&RDN_MtQRDyP2`@M)J_ zzURj4(W!UW9FwQ-s0z`y>-&r3)4vg`)V~f8>>1_?E4&$bR~uR;$Nz=@U(-vyap|Jx zZ;6Ed+b#GXN+gN@ICTHx{=c@J|97TIPWs(_kjEIwZFHfc!rl8Ep-ZALBEZEr3^R-( z7ER1YXOg<RslpM>Z)&_=`WeHfWsWyzzF&a;AwTqzg~m1lOEJ0Su=C2<{pjK;{d#;E zr2~LgXN?ol2ua5Y*1)`(be0tpiFpKbRG+IK(`N?mIgdd9&e6vxzqxzaa`e7zKa3D_ zHi+c1<wCe5g7HXHML9sFeaTRzfx@YksC+U;4SZXG{&Uk|wK=e(Qcf1Yk{X&1fvGA* zw!EmqXRcWfc`4MVMT4jgS-d7w$hncxD<L9U8AGPq{DMW~K8Ri8c)Yn){n!`p;i$07 z#ata~vsn^kQ0&|_C{SUB&y|DBV~}>`|720|dn(z4Qo<?r+YfX=WYLIOGZslL+F?F4 zhi!IVb|o{L*e^>s^e7sn(PU%NYLv$&!|4kEse%DK;YAD06@XO3!EpKpz!^*?(?-Ip zC_Zlb(-_as+-D?0Ag9`|4?)bN)5o(J=&udAY|YgV(YuK9k=E>0z`$dSaL(wmxd!1f zME&3wwv@#{dgeMlZ4}GL!I`VZxtdQY$lmauCN_|mGXqEEj@i~du$|>5UvLjsbq!{; z@jEf;21iC1jFEmIPE^4gykHQzCMLj=2Ek4&Fvlpq<v&aTHa%PcF6hP3gHi&X2pI7? zRs|zI%My|qVvab#$}>TlS(0YT%*W<<E1qCRKj`*+qHfroZIGFt`*g(JJYczaOq1<p zKFt!ad?rQ1?xU$hd#Daf#$8YO%FRa8%7V3$gbumUdk9LKdg819bwG6c2wOBm-sRf3 zk9p-%EDe8@<aTLV-!^p3VBa}Sh*-o>>XgH$4ww`D`aihBGkPM(&EG};Cl&wzg8!jL z`rkqPzvH(0Kd{2n=?Bt8aAU&0IyiA+V-qnXVId^qG!SWZ7<H3`F5<$(bO%$Qp=Ouz z0`uw>%_f&i!D{R#7Jo$%tICxY%j)ebORE>3H_c|to}c#HX;HAC?~B;2mmQrMp2;8T zmzde!k7BYg^Z1r|DUvSD3@{6<?xk@V&RPeA-iM-8ZEsb)j#bG;>S<1kndb%Qt%GA# z+sB2&F5L`R&fLRdAlp<CTu!?rj!fsBt75|)qNds8l0~UU_sTAt#1ro9U9#V@t%v{g zS~p`@1`lqmQ7Xe0{$&iA%Cw=}sW$W@D1buwqZm@sDSrn29Opri1>U_pVsJsYDEz{^ zKGaAz#%W+MP<N-Fi>GT+D$+xowMY0=ipM)0p?zym&Aoi)qL(pO_weO(k?s|ELHl^W zviJiFUXRL&?`;3_;mvc02A@sbsW9}#{anvGafZ#ST;}za?XS3}ZG3B4m(SW{>w}Fh z)T5Yi*``Tstmi9SHXmuWSND@cj}qtY!`<ld8zkNC^o#qeE@rzNMw=d~@4{g2!$avC zQ^P%PHs572uWdpsxbgC-@j)P-ulQ-Gi|^22tfzZ#6yDtez%L9#=kCGySK)N@h~uhQ z0B`;+FV!{t9e(^#YQcK>tuD29Dpu+-D3$h<5FY>jE>YJvqBmhw?oll`x7Ono(}R~P zle_eBwYy0Rr7kmf_SEt_gn4)AO-r`}^Z5Y%Rm8)K-?X>rvDL+QT?#)QwDsQ2c$tc* z&#hbgkL6}GnBDH;+lREM6MGIskRa@r>5Iq(ll2IepuhW86w@14=E{<t<+{6ok<;kN z^T~21D{HM?r@qkFNVBvE4LX=Bh^3&vy`GF15gN?PGDEag7(}<dp%VeKx#ugmwCCu? zJ2V=NPDtxBDT2j?{(&iY)^Pt3oXGq86vkpxig;CR2_4!QWI79%k-zy;)N)gqK-|A4 zVb>6$cz*cBDQ)CT>}v-DLM-v8)xaPBnmGBKM63RgDGqh!<*j90tSE4|G^+r@#-7g2 zs8KE8eZPZhQuN>wBU%8CmkE9LH1%O;-*ty0&K~01>F3XB>6sAm*m3535)9T&Fz}A4 zwGjZYVea@Fesd=Rv?ROE#q=}yfvQEP8*4zoEw4@^Qvw54utUfaR1T6gLmq?c9sON> z>Np6|0hdP_VURy81;`8{ZYS)EpU9-3;huFq)N3r{yP1ZBCHH7=b?Ig6OFK~%!GwtQ z3`RLKe8O&%^V`x=J4%^Oqg4ZN9rW`UQN^rslcr_Utzd-@u-Sm{rphS-y}{k41)Y4E zfzu}IC=J0JmRCV6a3E38nWl1G495grsDDc^H0Fn%^E0FZ=CSHB4iG<6jW1dY`2gUr zF>nB!y@2%rouAUe9m0VQIg$KtA~k^(f{C*Af_tOl=>vz>$>7qh+fPrSD0YVUnTt)? z;@1E0a*#AT{?oUs#bol@SPm0U5g<`AEF^=b-~&4Er)MsNnPsLb^;fL2kwp|$dwiE3 zNc5VDOQ%Q8j*d5vY##)PGXx51s8`0}2_X9u&r(k?s7|AgtW0LYbtlh!KJ;C9QZuz< zq>??uxAI1YP|JpN$+{X=97Cdu^mkwlB={`aUp+Uyu1P139=t%pSVKo7ZGi_v(0z>l zHLGxV%0w&#xvev)KCQ{7GC$nc3H?1VOsYGgjTK;Px(;o0`ler<o<VsrVl1L=1LKM* zSr?}pX@JohF$RvbE)o+XPI{gtXbe>xB<+EJX9G9f8b+)VJdm(Ia)xjD&5ZL45Np?9 zB%oU;z05XN7zt{Q!#R~gcV^5~Y^gn+Lbad7C{UDX2Nznj8e{)TLH|zEc|{a#idm@z z6(zon+{a>FopmQsCXIs*4-<r1S$vw!O=S8eXuWVM4gE|O22Aim2fuC!E;^(N17hT} z{W>dLGgTc)iOhO3r=l?imNUR-pWl!ktO0r_a0Nqo@bu8MzyjSq9zkqPe*`Sxz75rZ zr9X%(=PVqCRB=zfX+_u&*k4#s1k4OV11YgkCrlr6V;vz<{99HKC@qQ+H8xv5)sc63 z69;U4O&{fb5(fN``jJH#3=GHsV56@{d@7`VhA$K^;GU+R-V%%cnmjYs?>c5^6Ugv} zn<}L&i;2`zzW@(kxf$$gVH@7nh}2%G%ciQ_B?r{13?Q@=Q+6msQGtnyY%Gkjeor?g z7F*tMqLdhcq+LCCo^D;CtOACCBhXgK-M&w{*dcUdmtv@XFTofmmpcWKtCn^`#?oZC zUOm<QC1a)+;H2Zve14RDpR!I0lk^dqc$N^fU^W~mk(jvhB`mqitWKRippxFqPzrU{ zcPfM6W;1_A@B+1@Q@wCoST-~IPavhxX0v(*iG^+o6rBoLe`MUfYuTRB;Z%+q%_7W9 zDL&?t%6o=@-GUYv&qOcCS7Jq%$^0c4k8~_XQ!KC59PkrIAYM@@%s1+f=IQR(V=LHC z%wM}Z{MQ%qgczfQV8NSMu%GZB7+oe2hF7{zwV*g7I@VXaE2gtl5Lew`?N7JwN`c#j zGJ#z(oQM*<PFAKf5l;#Zq5V=H`YZ^zv~o=QTq9#9<5}YZdauuPj}bbDb-O#h*W86q z{H+cAsE<L!pBR4fwL@@pOUY)4uiBz6R{Op7WryS&*zeY}8`$_01z%)k$5aDy6h>52 z7sK$hR|Vh6y&pfIUK&!`8HH*>12$nWA)Y<DeYN6}UOt4|m%_aJ%g>np+XwOj=jNLD z{QA4gezbe>wiP?`jJO;c&EId;=2u80s_r97;TX!6@*(<%WL+^bmxheMB3pKx0OpH^ zPs}knV+jpJ4TaD<VabV^SI2-ELJCb9;Wwo$^++$X&>@r^V`mTsjf`7!z^H}eHQ#Rp z72(>Dm<W>#QO!ZYR*O@yHic`3*T^t7jc=d`Jz6Lk@Y-bL%cOp_<QC7R+MIh7-+O%L zgkh=?9YCZ&fDC@~yOR%d8@e|4j>~=#xzIJl?`{Qu;$uC~NkePE+7wSW_FM`&V{gFN zl;lq@<h8DED3`q8CPI4MvbTi2f`4<t!PvyOM$}BRG$~#ym$=;0)Uz8BkP0g`d^lAB z9eZe|3-spiVr_U=XSM%rOw#PPMg8{~zoT9GxpHsrYSG5L6|SD*G{dhC;l6F~-YLy= zB?kglaDe&CNDBXTu}}wHUGw9c#~06I_<D528$Nj}tcO4&4f#Yc5Pxnklu5?5s<?JI zTX?X2b#fynjR<V^G7jfM0Jg$ROS--~{@zhH2B?r20y{JWsidw#>;FtAsl!h;tnOvj z#gYx!q$5MdZ0Jxjy=t*q)HFeeyI-vgaGdh1QNhqGRy8qS)|6S0QK7Gj9R?Co{Knh> za>xkQZ0}bBx!9@EUxRBYGm25^G}&j-`0VWX04E|J!kJ8^WoZ(jbhU_twFwWIH32fv zi=pg~(b#ajW=`)Vikwwe39lpML?|sY$?*6*kYBxku_<=#$gfTqQ_F!9F0=OkHnzBo zEwR!H_h|MNjuG$Tj6zaaouO}HYWCF8vN4C%EX-%Iu%ho;q$G#ErnafhXR*4J2Rp5* zhsi0;wlSwE*inVFO>{(8?N~82zijpt+9Y_-^>xnE%T*zk9gi|j7b@s<5{|qEquUD( zS;<Fbn&#?PgjjZVRL=q_J}F4-9UJe~sZk`O!nV1J6>-%RySZOCOEh*>!kvbsQ265* z>X8*_Wy&~FB@aDHz%glyiAujXq-|2kDUjFTn9Rafsl+XNyFP%PG|l&ZGWBcEXxy=9 zeDn2PIoVuL$gX0RgVK1O$x3%pOzS7x^U5Pi;mtT)%cY;&e&M7GLM}zP+IPbqLt=^5 z7qLfri8myf;~2psc@^cA6mG&{C%e_(M$$!wC^5p^T1QzrS%I?(U{qcd+oJJkQxe10 zON{Q*?iz%F4MbEsoEc+x3E?&2wVR^v<KUU%<3!et*S>3|Q0lDaMvgS<qzNZgY{&J_ zJ#Tdj1)AtN1=pq6h55{9v@1MyP`7ASP}AyRM+m39hYAl8mQ)&$DGj<r+ecC3#7Be? zWGo%S#WJ%U`uhf^QmjQriQHc6^wTJdf8k-8l4}Q1)_-x!L`3vV7HMb%LW$R1jTiA| z1PwYCHr{Bbfnyi}Nu{MaC-!}p2jdzNqLY)eivRGY9yqhnx@YUeM3`~hN3!}Yd~D;1 zL|a0`$=3U@Xqya5lz32gaS|&AT$~5P4l9f_<fuZ^#NZ$HFh;|sEXaw=`Qa5K$4pL+ zk`kG(wcD?O7{3Hu+25!(ip5h&(aJyZAcBGf8xfw(fBcby%j^P_hiUx#>7mNjI{2w! z9|~=!83T%GW*iaChSS!`Xd^beFp9N4%K+k*j#jFumk}U?=WKL_kJAltxnxp~+lZzT zp@&&kSPTg3oSGos`rVBhK0|4NdHM_hnKuw1#0JV{gi_dKDJLB+ix~~HpU9%jD)@YY zOK)L7kgbLyN2%Dx#fuY}8swh4ACk7%BpP-n5(RhDq{gEHP*Fo4IviX{C49|B5h~SC zFr`=0)=h2^F5UpCAgt?R5u{6V<a5ODjWDGfTC~$_FT}rgG8yDcak@wvkU5wL@;TeZ zPO`GR+!M%zf?lM1u-<{|;Q(fZw-gDSLQrBP73s%I4kriHo~I8%gb!B4r>vpUf#*nC zCQ`$!|C;L2lpjlG?(>T$(_$O3_YNNbPT~(?!j3aD8k=yu^ogw4bkjvgF|3BOq(hB& zG;^cPXmcUP$ox8zElCJ-zMbK9q^8{rri#8Cek5Y<n!J9a_;CLF!lX>dr0YT-KTh@J z6^AcB9ejew8BY5kzZUZX(7Po==eW<(;uV~E7(BY5c0^xr`cuRwn)47bN?zOb!0?cw z#v}R$z66&m#+AHfo@(^V2#S~bhoUkkTArg+6w>JzZ52r96^({1W!?>4$h0l|-jDfj z>7(<+%67#(A|4hZ3>Y;hd&S?}F;`Vtqz|pK&B>NJ=Faci;gkf-+GmfQR8^zo_vul2 zB!)kfu4Dq_g)8TBBo52*sB6F`qa&JCR=_A$QWgX_K}fZm{Cb2#1q`^S3+WaS>sS#@ z-4k*G=#?z6d_e7JJ+Z8^(t0tNdL{K5F;2nfQbXgld}a(X)Gr;WojOy`^?es~AClT$ z5^lD{WJek0!p-QEH5E7n6DKQ0%_ZBZ=|jfV_MM{VmL8y-Wd|>OmeemP=C@xI@@M~1 zW2S*im@Rc=O>V886_UJ@oh1!2H$Ku&U*Hh_oxd{32)vf1$cRiepv28ricM;}#p!+k zaK{z1I=9Y%3m4|Pj*BD*Fn5Vh?O@oD^1UcjyeNh0fbhh~V<H!nK^g9ls(UcBEXK%| za;U;8!rSm)=b{kqG>6xb#4njlGW8OehUe!MnoR(wn#nsoyL1m!Rov)Nv4~&JEVl7L z#^qYdTpNI#u`N0UbVMiDmD>g2VQcG3>4D6<e4?4s7RYh4$dWZU@g7b8WX0r`Y#b|8 z3YQ)JCB?6yErIG~7k5+q&+P!y)4{ysbsIkYV)dCA_K*X*S_YZv$~E$4z?0FEN&a#6 zu6U$Ha8ZSpZ{-B6MpRKG`<444i}FgV<SB1ctW;y>gErgddZnSQTs){BExxRJR<X^- zYm(Jvr!t=*AyjgTOAVJyQV$F^aXXDzoS{BdiAO*9ilg~q7RC`nC5|tGI_Uyg6q+Af z_~)U~w|4zdx*se%qb+sj)C^v1tN;D8ay1fxZE(V)?t(1s&9p6pA7Hdq5VZ|AI8!`5 z5hh!uE4{0FgUC<qp56l-r~_8&6{D*VzZZ@IkW;rUvjYN!wSrS{8xSFc>B?bIxTdZa z;!S8FHJPPiIDQ*FAUiW<aE@x^o9n9|8jmg@-NK{Bp?S^ASxTeiKt-d+p<~?wB~$$6 zYs~@-VparJ8G|Da)YdPaT|JZDM=~!q?}qMq3t-C^QrDKsI-lJX%$oxhq5C@Q^duDg z?4%^g!FG&#N~t%OMEM|YwNie=r=BomjT@p{jK5z0kxB5!-&Ti1a4@|(IkYUNy!rwm zA7fW)@@}CoPb~|!N)(&5w6qwth}CAD?fnX{S&nmHH}F{(r2k`Y>SYnjILFjDvxvSC zk<qtm;E%gFWTR}j-)ETL$1j7){*CDwtvowxb3c;!9Mg7Z#rbtWL$XeH?y~7uyQWbt z#a&HwZGqZSS}oy`aTL<nVm#5RN^Qv@JMl}plNYWNMy?VPsEuV%HksMQZ&M@BDCAq> z=j4Kx@Pg~&2Z?cmMDa;)#xVeorJrxDBqy{+`kG+ZPQqC@#ku-c3ucU+69$#q_*se` z-H#PFW^>-C0>++|6r=<$Z8)ZFaK=ZjwsNYXqRpl9G|yme@Eld5B-*I69Nx_TResHi z!5nm+>6zaJYQO#%D{~o-oOJ;q`fa5}l!<gWB)3)MwB=etSu|A)HNQp#HqArvXJ)-9 z_RMP3>8G*U-E$OM&7@dqciBCWtd}|SrDXz$TB($&m*=Epuolu2k`KUwO7maP3P0ok zmF57l<v@cb34lh%^P~cUHM{48n*rZ-qaEZ1MzzCoG~#m{7z+O*JPL)+yXEB9Q1-&3 z*Ms=?1?R8>Sh0Ba@&sO1iZ5^+3s8{B8t|M;Pg&O+{tZJCiLWd6H@{b~9{CLF9s3Kn zt5)Rs9ejne?o{%f><hmvi~%iy7ixeOmE*g3u@{kRhrlzjq(;E}*Ab<!Rkl&Tp<Nu$ zj_BI>B$Dl%X7fd~KY)I|(pxUeHj;gNsK6;ZR>`ciu;GxvhDUt!+31Knss2U(%ts8K z18)8;<2ax9RG?!|Lwdt^i5L^&O788roKmVAB)=EdK~HqR2Q=)H_VW}xY=95MP_Ov< zPEz3%DRK}+(aUBwsr83H8>`H^v~|A_t}0vPmRwKPt1{|qOY|PZu}j9+{ZhF&-H_TB zU9xWLpNTc`enI|)h9jQeqf5RfGLFk_vfX`40iMpd%KZF!lKbZTdBw$<^G6nuS+$fT zrbK)xo&;buPJcpOZ=x>n+bRXVFDs(23Xr=rDE&!)pVXZ;;A07NXGl_0m`{Z)DQIu$ zFDvY4xu-ifTe_$|n2B83eI;KUg6pVbw+N!nyLj~wnRi{4mNy{WDV)G1!6$y=+x6U{ z%4_9=Q^L!x_gAYp?J3+u5hA5cO8aHeI=6AC8^S{mzhqCBvBLYEutUC(X0>hKg|AvN zvkmJCQNA45_KjW{aEcyrBppcO6G0zTy%v1&@~+2!n?kA9?>0>AjFN|JdCnHQ8$hEU zw#mwGifHppLP?89LMb(Y3Li9iCPx7W%ek}2FgD2YSzjsR4Xj<=zN{Yo@7s7(k%mP4 znT2p&<j^yvFM2RSnHHwMMc(2UdoUNS2x4CzITQi_G`d@qyz~-_^u1>4EQ@q_chd-E z78uvD*C@oba`U3W2Iw`M#`5C8jOHv8^Li<|j^SI>>>`77Dp71Vtz=J?4Zck4SdRbd zfF}C_>Y(#)r@y!Q0`tMlG#b9>5`fAI$B&tWJfbGlYW$J4V+-s=HH!`+;1XeL@USdx zR0$G&&XBf9lQtkH5)p=U!8J!1{oc4E!N-~A<J>bxl<m&B1N64_9;PGPY(a-R^5$^; z$s$KcZ@+yaMM3@7vA!{XqU>6E;;=3-hMYZ+44?u}zabmCE)yB?*_w91m$n1Yskp&@ z;kxeJX-#ioX^{elyLu~gzx|_KxLpX62MF%Axq3$!Z_P`pBWR?zP8OI`PV~6Aa0Oi0 zv_Ot1m&plf-ZF{e(z(Ms3*S5q$e|j;gOwGrmWsCHf<WiXqr)_<#-^P7eUDy;3|#TD z>Li(h8y?g<J;67jdFW)*FQt@{ZRKdyHS;bpPDM~lC-|XQ#9ez=^9^R&ttvwy+?%aa zd%wnUga`n>c$(2H{884C1FvHQQ12tX=qFUsK~zM!W=K>;zaRsu4Xmcc@8nSs!vK+{ z?}bq}-m&p5jRSam67n>yG9ez=I^|J1O;Np8s=P~9MXYLxD+cFQK7PhG=bkjo{Naae zjp3NWWrlFWDb3Z5D07Q|WjZ=wOQ=aKA%en=O@hL$QCKpIXNZE=InFk|Fhq-&H!6&X z*MVy8=hL7Aw&pQjHrFf27C%3B<>FX{@f<FfR}de0cdavaWPgv)j@|tVyBnBmhay-w zr|b1WexK9-QI~=CyWk={v~fqpT~}natdz+o<7km0b~X=ETaH&3c8K+WenHsm4$JbO z(VV8XuzE|ddkZX9Jyu8q8}^_*l5MVd3l9D~ukx-7Zx-9b=)zAy5|=wv&fhoX&%tys z<My5<Y3f7yT__~Vfd_x|p0}LjxtDuS_R+I_`+x_Y&NM2$J?D-FRpnJiUe1#n@yYE< z`#UbDOlhY7rGj<NITWLL^jTkEme5XKSF5;^iIAxeZLh<I#Xa&Fa#{)+r@~mX3V$m$ zXDY{S!F{qy3{p^j=X3Noq`tM--g+jju*&(g*4VUGd0gwfGcUfw4^YPBCewnah2(*v z-_z~yyDrSMxMprKB^h|c)p!>OLNhUoxL4*@nY}&M3G*T-p6<k?^{(XrB}ewz#nq9x zUPaq7+HwSFFH3OhCiR(jMzu3;PQU~Zu~qxb%Akj9^%3YeC5M$cxT9h-$YV*Fr;>7a zo}~_&yGOB)#vbU|Q3FA8S^X)c-yBlmN(_%}`7Ha3uWFe?>9f=3hlO{^gv~$p`v?vk z_P*r43|(S{%ihs;)YH|jAMpP=-Ms7Ne75_YZZiL3CHVjSU`X1|?Ehh&gA=Xn7W7d@ zf8bM9Y>lG!`PWFDDA9G;x*{1Eh^55u66*9D+-4^dYZ{xXP@?sQ<?=<%4xst`@F(1J z6ft91q!t%X9cO;rXn#Eq`2GT#=V6M$v>LVrY%(azM;C^4FuN7CQ%$!3sr1JL=!Be& zuOZL^bLp$Qo2rL=WDzQIls%s<HhcsSZZlBdTXM6b%<%FtpBuLuS#4c8jK+EW&>!Go z{s}Q0b#+#8bKga|01t%^9Z=wEsevvXM_{$dCR97ed3@1kX)mtSS!JN^rtqKOj}p~> zfpCI@DX*DqcB6ZnBcl~}sGO~1s$AtfkX6fy3N8*ebvZc*KBW;dA=)?#BE&}-or74i zZUt5;{FBPnkZD8YUXDsx&2LvSziAlec3oc>&Lf1Doc3g?H9{OO_$M4B0qTat0UsWP zTlxUeQ3B;oJ%en4n?zQB6*Fb#wH7`$SQN5GI|=DnJKiYm{?-?#-H;#sIjz7kQ4&VW zN9d1(1$_W~S=<%qDD!mwRytas=eqX^iW}YSx3;wJ#)Xp_`Qk1DFiXac$-3;jQbCif zLA-T_s~5yP@Q@W>pXKl^gipQ>gp@HlBB>WDVpW199;V%?N1`U$ovLE;NI2?|_q2~5 zlg>xT9NADWkv5-*FjS~nP^7$k!N2z?dr!)&l0+4xDK7=-6Rkd$+_^`{bVx!5LgC#N z-dv-k@OlYCEvBfcr1*RsNwcV?QT0bm(q-IyJJ$hm2~mq{6zIn!D20k5)fe(+iM6DJ ze-w_*F|c%@)HREgpRrl@W5;_J5vB4c?UW8~<VA?`+oZOidfO>%o0)(A4`%-yNk1(H z5CGuzH(uHQ`&j+IRmTOKoJ?#Ct$+1grR|IitpDGt!~ZdqSJ?cOtw-R=EQ+q4UvclH zdX=xlK-fhQKoKCPBoFAZ*(~11O6-tXo>i0w!T$u{lg!#itEUX3V{$S*naW!C@%rll zS{L(1t%xz(*B`{1NL!*aMc<~fE=g;gXi&Gb$HpD!P)8?JzfN;4F&wv(5HH<=c>>)n z({271)xREH89=C(5YKL{mmJJ_d>qH<OHp%o7e!U>z;;gTvTlgM*vz9@YTTYZ#%_2A zS0G-t9oMQEpvfv(UjfQ8T$vAHi)zOj3>D*{xSRiu3acc=7cvLyD?_ZObdu$5@b*!y zaZ#u?7uF}SrHVQa=sTOhGW{6WUlq#RhPPm^GsRH#qlX8{Kq-i~98l;eq>KdCnWyKl zUu&UWBqu#Tt9jQ97U4}3)&(p2-eCLznXMEm!>i^EMpeVzPg%p;?@O;dJBQQY(vV;d z3v+-3oTPC!2LTUAx^S2t{v;S_h(EZ^0_dS5g^F*m{TEIy^Qal~%mu3h7*o`jWOH}i ztv8M)3X3a*+ry_KkYXYE4dB0?M|t}#Tp+(<S5$ESAA`34+{^ec&-g!{sOtG&>}6CQ zBbq;xhoHj}b@j-@koDB#XcCY~>_x&Y;i%MH|3tF^X2h{36UCVfQ-;oEA+4ZkJ`^Qi zQf^8}6eFO$Z+Dj-F1wkG##tTx>FjR2oOXFmbKFj6K3+=kePQ<4d7%z5R5cOB;zO6| zm9^m#U4lcA;7t&*=q|a-!`!)}SgY<L`cp6ihUK`T5NaMCSnyVawc!h~cVP~-UR^PE z4MN#_um@fSUU_pM4v~EORuYM9?;gwP-|v~>XT#i8hnxtx@kaoBF$QAS-hT7N5kH^l zB^i+})V>L;9_0Qqf-dyF%ky8Mp-dp#%!Nls3vCt}q3QLM3M-(Zs1k}1bqQ9PVU)U` ztE=?;^6=x}_VD%N@${>qhpkU*)AuUBu_cqYiY&@;O$HV*z@~#Tzh?#=CK`=KwBv+o zh%<IRE+<<<>z<y<Li4fUga&=eks@7Fc($mDQaoiTsNk~-jCT_fyXZ===ne-R{=1}# z@)Zj}aHGxc*4Yp=(AUu?Ad%}VMHZ6{+EWxG-I-*RlF4@3iI52=yLr3niln2yBwG|E z+Quaop&DhBKQ6j0s<UwrCJ)SEYGw-cEmF-mRxP&%FA{=PWg?q#>u%0xPKYtyC)DaQ zpDW}*86g%><OE5HGA5d)(L$h5ml-x8zbWQM`Usu*u?pH!q)+;)5&VPX!CDcez$S^* z#3`A2VXirbRluU7y}K%{L|b`exxi2p=v{|QX?!!pQb*3DwTJYF|E6O&c+-)AhCdJI z#WtL?K1Gc(hgV?HpCE`sYDRB-0=1T$6SlZYPla@aT7(IA{VSs|h5rHqb78I$L~Rg| z4q2vN5xOy5hgjbOJxZ~Ahpn5!J$QnDNDF8Hg-s^(<p1jII^e1P-v33)%-%Dy;*!00 z_R5xwgzRfwdq+aZ9)*k>BH3IcWMq`g$j()0kWE(qkIL8A&A0mf&+BzxpKF}=`#jG% z&*wa!&pGFLs5_b#QTZE4Bp+})qzyPQ7B4Z7Y*&?0PSX&|FIR;WBP1|coF9ZeP*$9w z!6aJ_3%Sh=HY3FAt8V144|y<cjLG9Ni0-bXG-mrKlbq21l|*9`mr`m%i0QIDabwaF zRh9o84|M8pD~Uba>fu}IAyYHr1OYKIZ51F>_uY^%N#!k~eU53at-_E-Gh?ahmM5y* z+BTIbeH;%v1}Cj<Ywo7o?8!D|Fk8}RR+oy{*(Dk3Rn>o{8d%UeSMWg(nphxEU`sL< zQR~LrTq>Da(FqSP2%&^1ZL#DTo5Sbl9;&57tQ-@U&I#lj)aNSkcfEJwQD!33?anVU z?pw2q7WtMvfji493`rSFnyp7{w87cW`ak=UEYlk5PCB1K6UDVKXyozOChH4yHh~Q< zv>yvKw6WLfi!PZUx60JZcTNM7jo{ww9b8Q+S7C3W<Q5t=K5`aem0H!-OWG!yq&T`w zL9<h?vUoP1(h&O({NHUvM6Rm5B+4?c%WJfg#dg+r^0_A|&}s~}*2gN7n?^0YW1}u& zu+)3AG_tNtFv-SSZ23m_(^8&B+xcNQwuoU>A5&llSwdwh$=Q(*(f3ofqcz=nwOmOy z(J!K=*wNoRU*${{Mbwapi9pTB(&VVKefqd-qrUb9*Eyr2E@oZ9Cgf}Mc;QP<0D)R4 zz=!*^VIG4T*7Xl=sJxrWv9hW^eJ%qYp5(d0?E6LZzJ}=7E+1{?GQA;z+!^VBD81}O z0kJ^dKy&WMw+1+aGVYY-v@i28@Gm+sX5=@U%F<J54B@9m<FVM{YitYR8zS_J_(KGH zt8{`dm2X@SVMym&+p@{eE({%0KP}+LIOe-)zv}kb!d%-4Z9+vnDB~Kg&+w<3bq2*5 z`u8M^L$Yr)vZG@|>=Z?W)oar}2~Rc&F|+3A)n-U2GF10+QdxDb^iA@7eL$c7yhBtL z>lABrh^qy9XZ${E1}Ss5!N4;ig0-pUh6@|RPCHOWvgG{|l}2enRgJftsN%D|ck0YO zuAQd2aMPSyGuJ~jm)aY=+p~mGudw4erwE%P^)5f<*$$2C-4^I=e8-}7##ZQ!8!Tep z+Z_!}CAI~sry$|XK$ktXaxP*x<_ijCPp`2=6sNLZU<@9Sz-rz7^BCE9yh0jV4(I!Z zxmA4d;>B-!vD}Xp*&*N%`b^e&R;D97WS}{~{O-EtXeZNfdf51tw!WR6Noo4hjHPv5 z?heYYRSBPjMc}tFEU^|U8a1CxxK%)WTcn9P%`wR^I$QSeMn6=w>Z9OoVvcrl`zYlZ z2y`mAu0bV(Scc>G_EmIo_<J`spJ!5|B|Nx9;jXDp(3RzE_|)z6Q%~Z%1o9xC($B>4 zm*~h`mxYZC&+U>C5G1FZH5L^U>Cq-9UDRQa35jz&NBj*0{uJKf<TrbDPJ6YBjYr1v z-Jp)`sw@0cJWU7};Ty(N`>Zs5=Fn@&)Xh6aX(H3w9m9BGLePqVotxTeSPh5-mc7$# z-80t6yB0$Nx<54ohdO*QL7<B#`%1`peiY3hz(Eg}A2Vu{-o!!7+HXL(jB^~|UR2zE z(mUX3-l7N{t&*hE;VVqitm`?PX7@QlCg39p2>m_(&+#*=eoNiYDB4rE<IeJ!x9fj{ zjh5~&GUJ|yRpJS6j=TELjk^ZSP2S(znUdT;wZzbXok^sLPJ}W@PuWC1dHEtmpa!Km z3ah8K`efW_!c7}=UaT8v)>4Cag@qfyZS};<ARP|HEzxy@RxNQ(L<I2*mst4CLjQWI zCLd4J2s{{^xsPthocP{NlAzfw7vFOtehv_S_h<$Yf;yR*!F%qq*m?ZC6w#tpX3UJJ zxHCzqZhQk*2K$ALGdFIUQNBtEWEm`HeM?iVXCp3VnX;`4F_)_*t4OTijK6{jewsfL znno67!eVKGzMaP*N})bFYHNt+IBLk8Gd8`YH`FIMYk!BRy|+C6o>Fx;Vf1;oync2k z9v#-<l4c@#!@Fz5xx(#=xAQ7-W_Ck69p*<vrAlz9czK2M-ZH3`lqAJT3Q#>w?d6R& zOI`CCS_d=tf3|?g3Z}b6-_Rdg3y~enQhmgkni0Cvf9m6%Ft8r;NC5|b%t&?lkl*4{ z8U<KR<Ur9&bCcU$L?%LSI)an9N5<hfOhXjYvzjrNO9}$J+=6Q1v3&e2R=fdgAB-ed zy@TM1<wV{=uxJ*j@8!?}Pn10LdmBTkgJo<_9x{X{H1*jMV^)Y~b@QZWUB~@&p`T|t z_QD>i^;Ds^gq6ti(1xB7y_$zA!i-M~#!!tl$ErTR>P~>T=Yky)8(uvPbvLmB=UfoD zrfl}8<1OQrm?8#j1!?s*T>AoectQl&m!o&*^JcIW`_&bk3tN}k^0rjl=HL$z*uIYt z?7l?^Dqr?q121<k)GkW4%te+ZZZ$}&Ojnh_9S<Ka*4g>0Sp$xoAy!&{2^{^Anl460 zI&7urrc&|Y{rjv04VOl{y7c82N6xzg5ueYmQ(q(zC3w_C#x*~%<llZF#S<oTCg{?d z-lJ;;SYXIrr7stvma)3=TXZim+stU&RurLEk>yf5j7MI{W`tsoxzA*PrmK)cTskU| zf2C}Bq$>S$-1JgIh0aW@LxI|-8(OGuD#^M01ghh}&#ObO>tZgSw_LW`zdf&IN$YO# z)|X_9m#JwLW5pErZB3ScggKcNzxA9(hyKkK9I#pR&79&*+SV_eu={00{HF=Bb+AEe znaSof+r1jZ!EL5XgqXWkckaFSSyEk}o!%p8XsD}O>borZ6x%X2b&q!s&1-O(>`kZ$ zB2l^5Cx9xQx9)PXN1xPM)@+LxACH_iZ8zGc(>wnFS_O|@hKsx<!FoZWaMg!u*IKF8 zW}P3`h~J%C%xvWQ&@r<W#x<X_L1egnQ)1Zd<|Iwp+BKV<KJ_VM&khB_(^t0WU)7r9 zw~$MVS2GGq-pxs9pKiybey+q<WAD!Wk#BF}Jbi0Er2eIIN;!cR(K%ri@<6p7aGCf0 z)PN@8U75jRa+mP5clupy75MxelnnFqiyW0>pMjXOzLEa7OvSlM&&G9ioQw9~RsD4F zK7Q+_&|Q6{eZ^8Rx@pKL`le6kH+(fLc{=V&{b%I5=n}VHV4)X_2Y!pYxgC8wU)yP! zPF3t$?(jsC>Ge=&{kmPGUEETpaw(QTAl)m#{qR3_aq9!wK%6XHfV4C>Y^>Z|%ns7j z{Ja?^IA{+@;kR#IjHx<p9h8LC6`To156^y!hJpG%ORFg>kar%3$eJT4?xNBKUVmoO z`A8Zo-{~_;vcikZ(p}EZzU4kO6W<oOs*`uO_hwi?s!j4Zh>PqkMyE{VvS?;44Z@lj zz^fKX9UL!8Wc(9VgI?P4*zpis8dzl};I>yr1>dtXU=FTAlx}Eht4-*7RACL^AflGh zyZb1hTf(~CkMo%#Q%NMgM9tE2D+)joqbtHYA89Ql1nqVTt+MxZ^*FRd&n5YlIi!8m z>$Ysd!l{+C)y;Wa<K2+e8*SV+PaB*>(ZV-=<+NZKV;v4mt}v2m>`v$-$3b;GsLxf= zd~f(rmfpl``{0aVwN7y!>eGyJFP`L+TxHjHTOS{K^$L2`@6(Rli`{EFwpH@R%eZ6g zwf7rc43<A*1Q;!xeUQ*$(tU17{YgRqr7_w2CmHs6jLPaaisvGfciLYJFL?|YL0TgF z)vZ}W3!dJ=e4h6Fj3j~#k6~XHm62*Z#MxeGCd5^o!4iAzf;j6aZXHVgbJ5<JT}HXC zMa@)$&VrHK+hx+OjZBn_Lg_G6kIcKz0^iE?ioO($_K(nSe_mQ_-#vFnWk>Yk!=k;{ z-Rn%~B3amGr}}SxfE$vS8FIPL=Qt57$|R#sSoFgdNUT?fYOYjPl%ZB<Dg>Fpi=<FR zh!tZQRv!qGd2w-d%|0vjpKqq$M?q}ig-a3Xw(1f+y*U>jq=DWby7Zxm@y;B<89!9= zbgEH*Uy)~iq5kJLX$+ps$kV`#6jW#|9BGz^`ivNeid(wVbk4jl)VBpW&~;eXNi{#` zwx?{DXR~*sqQcFhY0XCfQ4-*2aN1BGX>$_swtKEqnd>j6vcZ!#0)pXRi?<{!P?tGw z2x_`RD$W)qD{?z}VDPt?+)8*rqLWFIPQ(9-VbBdf{7ff?w9CZ{sIi_gnuC$I0(+P8 zms9XB%}VQ>>p<fUdl@Vy-yM%1V*%pfJY_Q@oq;8-!>ve##}jog6+cD?v~n4Pa9Vmc zg#K<TJpru+0smM0m_?9<3<lwQX+7Y#ZS<P77P$Ov_%Tq>$|+`adO=B7`uj35Y}6EZ z{dY`x@w8;R-7zrsr1O_~Jvl*|o-x%jF=Rr1C}GXP^|IYN`1sqmG-oI@R#%X66c#5W z$$tQB)sqwiVm;Y^`Dw3mo|firP{*HsOQJre5%Dm^H@we0FN88VWJ0dja?_U38z73f zrCV!b3qNP0kM#%9T!W5`ynGcg%BL28FW1J-J1_S`BJGCaReQ!am(2%qZ3lLgzq|ns z!!fF@`0=*z)J2BwZ*hO|Yu^cI_nF$9l-Pb3jE7=P8gZ#!xiuZ7-cSa`gb`6mxGTgg z-DLdID?M!Z%+hHB#{?&0$GFRpf+_}q<_wbzX6K?w;%6szz1RbySDSr2r^h_qi$khs zXdZ9A0!_Bf)TR2-^-K~q`FQ!#1x(U4VbV%AA@Ei{%cA(EwC{XfjRi?`&9rav5;Q5% zO1`Rn@OA_ZB@N*mC#)?d3P!}Eh;=NgpIKsy{(yr`hv=aouwt@r&P&}Z3DNWo9ro30 zX52~(aTV$*HHlgB66-4GQru!_AZ|)V*I5X=WG)`N@U&D>e@@C#V@JwEL*L`7#$yes z62C^5%Qniaow2$3HrAc7U{qzpb&FA*xLI1JSWR@`RF=JCcvTI)%dH7;sWInt9JLu# z|Ao|Q?K)cD<XIH`HHF$U*`>g_JKsym=joo5gR80wtv01N`um1nQ@Ms0Y*bVzxL34} zo?gizp?`=Y{*W>^Hy2%Jl)y?A+&7s1UVHFixuIy~sawXjcDCL`129cK7|ZQS0u;A} zTJC<n>#WNmqkIrnHpAhHVcM(U^vJA~dl@jf_bs*3?i+=&vuC?Aiy_pcB~=1syDni4 zw+FLuz>F773u#$;NUQ9WDtUPY@+rA3WBhQdKFKOyzkA(URa7;4tW>3jQIfi8v0h3g zJC_HVDXS#>DWb|&se7FHnr=q&<fFndMyX6ok|*VZ?$(NG!W2uXIh0KPUw36VxOJEs zWL55mPTHM6#qp$QRV3#jrg6AO-3EUqlT!W#^D7D+pA>l#xg9o02}}u=b-R>@sw={Z zHF*?t2FmhqZ=|qa>x=A!*$S+0T<RES(CQkwg0f!ut%n<5m;I9RK*Ok?E82=ogcAWX zVMf_PEhO%Ra)InLoTNnu*N)LQf?H;Ub+bfT-C6(^c<%)T42I|Z))X=BQ!8Ur_1gV| zIq@p0@`Lg#&@KI;S3rcoc+0%=cpeub%lgbGd}9$GOX8GXLMxQ<V2Z{eubf-2zA+uv zklCK%<D%OZPsbqt7)9|B#TjKk_;XlT@qi8gU;-qC#!y7fw){$5w)b;#tp!5kG=0`6 z9Ik64yvf9Ei%-l@D!sM^YDUjdS=D7mk|C%pMhoY!Y^d$mD?YDYA~!}WU*52Y%N5AI z@j_K9ct+crRE$scRft}ZVlh^m8$*08g%+MBg@9IR_jNa17qs|g2jAO8e#zebVs`5C z#M~6d^GVBMYaN$IhQCbj@Py)%Eu&FLw$AWyA`~pR7i~dfi4_-S+QVK5Mc%jA4e6e> zhO*D*M?NTf-eX`eO)9TIQu{7Dm77Acnj4b1jI9@c*ZL8wL%8kLEhd$KM8=Y!fbN@9 zC7B5#y>JM1n5M)!&im==EgHs2j+xCZG~+~QWCi?s!QyFo2kqx{%jE2n3^N*Ayz6Lp zhg5g^3#<s8**C}4WoKx|EauIJ1o&O{zsW4{WH^4j7~KJ<QRtxARB~N6G1=Cq2xytI z+zswgLp5jEXPYtIst)_svBi}Uvn(mbhG0wms7f!xihoPy$`YnO3OL=n<3dU={6=)> z+5FoJ@$u@9WJgPKpUWEd4}4AK9TJKU8W%ms!d0p%OIOX+bY+55zl!vIaz$XFI9Ep+ z<dS$zNm8TS5RixZJbxTR?cH|bfw~-cU9~alq(f12VSHQ>;bL_}7PDI2Y`Ng*XY(65 zh0%`@Lve%fc;)N4_g12bNrt6gH=N#OHtxO`$lpWlw=Z6MF+E@;>GkZ#lAZTn`aHwf z&I1|aV#b_VHMIgBN*RzU9i@Z@m}0i>o?({&%fpEfaOpFeaJ7V37;m0?kzd}}Lk@9$ zL}8TEo7WZAcRi%zFZxkr6<0k#X-;lTD`Oc~cDb@olwgWCewvk{GJ}hCXbF!AdiLpd z|Cck$ZTKI?Ack{34Lva7+k=H8K2HTZiurox6F+>dy+@R9T^awxj590D$|kXUg+Ygc z(f)jlRwN(4z$#%PnOVc;#Fv{nAi{#UcXPNcmP#5O{zh_*`=q^JCeia{sN4zHjk2*y zqUVh{Ya{j<IKA2W1mW}eeRalbF4<$oYZtObji4#>>SPmP^i#Qfcq_MTqo8g52Fi^F zKBc$$HVI!xFx*4Y9l+nt)$AoZORD}%5I10oI3kx`-N30QueiwIw#0VV2E*Fb-nKW% z=+r^hos`Y-7~{cA1FVbK$_=~*z53+Q8KGjg;>ztg((H12%QTf4OYU8y)C}h5yo#$% z&Q$`vMM*g?ZcatAn2j!hFv8KuN(dw)T*}sF#THDHxo8xC^?v<bx3iehloREh7QD>J zc`U6bVo~hOr6I!8*GTZ<^D~;unKjK<lSb>=!IR|<CLOcJa^Z#o;e`&fF86DiwTx_5 z^+xIq@90~tHVYK{W8uadIIL1Sm<$jPsUn0~E>GB4E>Mcvt*2GK);93jIDd<(nNjHO z4Hi@2^%Uyx<t6q~e7n*&BG#Xj>=^Z~5eZ!5rO5%4H|eFoNj<JnEw;I(G_8jWC@X^D zfeW5#XW8dOR29iCD{XUCxg!{eaZraMSGf#$B@EDq)OE7ovZ1oU#K|=2n|sW8oxhIE zriGbgdm8i0QQ$ne-@3gT)BMa$`%TF(rNHc$Z=9p67+syKBYVZ}V$K_l)P#)$nD^Ai z)i@@<Jsfy5s4!Mrlao<acWb{oBXF>D#+Kcu%_57zZb4Z@Ak#X6txD^{U3wBl^r+W- zLorkK;uc;NgTj7dGxHQS+@T*T>Q*j4^Ll$ejQqWrwcHyG9y%Mk%m8nBVG5hvSaYm5 zJN^#-Q46kZG)@T8n2^QCjxIwxUVi%s>EY`E?#@_(A~njFrTiDq;8v|W-1jT|ROlNI zU$h|YoD4PVTE^&NC6_m{EAFBVqsM`P*`-AcDGWQygURzM32Xeq2xng~XQsYeTZ5v$ zQLaa2M_Iplw}4eL6fLPu`6`PYcVMysO>`{8CB~glD=TX7?JZcHfHNmykBM?QD)#D) zGp>R*<^D?WhFQKRc^}22l6F=D2RPrxaX2ZF!b1X0XF*d4%=!sbNcS1q2WOUE(7e4$ z^L8f;F)__d3>&KQFE8%$I4h^y5FYBfB&f<E9*wxTo`y@*Y+nk_nU{tWTDqRgI^8*~ z?Bb3&J@i%}j?QgicjYnHi}D5zkFxgiu@3ghueSBgqa>Wzn71_OSrPe-DHV{O#Q;GP z+Tw!J?eVjX19RKH?*hKQWQt8r7B#lYX8xoSHFGCW-*DSQ4EM4M3Mw%gkSYNK18@(e zfzMF}WWaCyS@1y%-~Xg0ry~tkQkUmKuI5lGAua{{vn22V!2T()AU5FpKh@Nv)s^Js zv~@Vu<dG2$ssIa;-wW`<?Pob4z7KpqNIm(x8bBn6f7NLGS;Ojk%$46(Bs#1II-vS^ zyy8DgWk^a2ogemK!2*Fy$UvYA{{VnMupk;>UG;=CnLmQR{PeUBQf2;lAV!vG>^Z0N zL88rrjL-*J!43;7C=w9xhcw`yjRKq7o4L9=0SmR9PA-nX12@#h(iIu-0N_xm2OV)( zU_raT0y>$wm^oMi2|U3N;OhF9uy}`<-xVka#DV*l{O0yHzi9vUxa1Qtpi$buR*8cU zd4~lS1pT$L^!0=6qUKOpM+XPsy{f7W#1bjrEwaeN!Ik9(zySIT^pEHvHgJUneFN4) zk=k|$55(g8slmS|@+*4fr2urd3LwjIIZA**g+%l(SZNn4HwQ}y6o`vw>2&mR1X+&q zDa1Af0B;4rAMZMOlHbAqK|R_xuwJ7ANARtFE({-P2o{tJJR<>2KVp)ZK-M;)ejx zd*E~Mka<{OL7%CAhk4n|1qg?97-I!l0rOinjVi#arbgg4bi5;nY5oFL`UWtP<!xMC zq1tZOf2#jvtAo2;dyoxinHg9wKd`*R0t@mv_qRkp)Z=<G!5Q|(^Lv0KZh*~+9ijtQ zSP<m=Ul7Px-f(mQq9^`^C`%4Yga_mC3t#~9$C%oHj`{E2{n-<;X0Db%@C8eVs|^$g z*r*MpnTA*ax;wZt{PSu6xu3-HuvM@C)p-(tK;p+Zq3nObsR9A=9R5(>k5&L#grSxv zE3!}=1px!ZTLT90aYc^s`~{VojjJml&<`@e41dFP+XU6D0AOkbn2rlI3>^LcqauG& zc$m3Z{!u8LvUrm^fT{qX5<I5AabS1OUsC<4lTtYvXYzo%Ne(a!5BB^V7QjRS+xknA zKZ+vE!SeYLAW9W*Yd>yD9{?r(CCiUdck%!T`KIZd2oQJz1joB&M(Teg_>;yS<2<KE z2dLnHDFK7)p8^XSko^m)Kk8~M@mtUYfNuww&Vko-SYSb{faU&CSGo|p|G{vww;L8s z2|=I_z)Zq?$OK$rLD!Z3Om=c#P~Lej(Frsj1mGUWL^t{c^Se4Me%^);X7Q6Ty{6Ei zqkvN6fd1t;)=ol;KV$x|x|5NO+@H(%0tSE$7=XwzWC5#RkzE{ZEzP0-AFlwbM@amD zXBUt{_!tkC%`ZI2OUM7x&mX4o17v{Vd%^#C1%3CxCTx$<xIt~~e{sPMDje1ZqM7_G z2M#c<-LJK6AizutG5ZyU?iGV-9iY!};Ldg2+~t1@1Nf{uE@tkQF0N+w--G-du9hQD zE%M|^h2lU%&j2<kao9}Y3JcP5{7pN5`q}^9v8d}}{|AjCC%ZqSg9UwZKE`$UP$1*z z2t9C4oeunYU@CC|wDe!T3~~zfBk&d1zXm^fU?XP|K7y9_IuZIXhTng+6*+J35g?oQ z?*acRi!X8?Bd6v(qO0`(Jsn`4CnoAdW<X8`c*OAV=5HBJRycBq?;|+c<ln*p?L8r@ zF>-5>BWfSPpG`Rt{!j6>kqMAvl^zk0JUEfy$HVJMkxP-GkwZuxL62me2#pj_5*ZIU zP~#C^OZLfl$HO)v;~~c&JHivn|1I9H5y_CDkt0JLLGKm(4*KLVhJ2jh2#vJuM6`b& zE<kP?@_z3lu;%s?!H(?={;%EN$SlY^j*nP!JO9jbvKo+gUmamC_MV7|JfR-ji-p`` z<h=|>==-lvME^Oj022xF&IV*?<Ym_*=qDq;gFe0pdszh?m{|`Tb|Fw25ePIfbMVvu E0aA=+Q2+n{ diff --git a/packages/react-native-aztec/android/gradle/wrapper/gradle-wrapper.properties b/packages/react-native-aztec/android/gradle/wrapper/gradle-wrapper.properties index c747538fb38b53..efe2ff3449216a 100644 --- a/packages/react-native-aztec/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/react-native-aztec/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-all.zip +distributionSha256Sum=258e722ec21e955201e31447b0aed14201765a3bfbae296a46cf60b70e66db70 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/packages/react-native-aztec/android/gradlew b/packages/react-native-aztec/android/gradlew index fcb6fca147c0cd..f5feea6d6b116b 100755 --- a/packages/react-native-aztec/android/gradlew +++ b/packages/react-native-aztec/android/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,9 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -144,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -201,11 +205,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/packages/react-native-aztec/android/gradlew.bat b/packages/react-native-aztec/android/gradlew.bat index 6689b85beecde6..9b42019c7915b9 100644 --- a/packages/react-native-aztec/android/gradlew.bat +++ b/packages/react-native-aztec/android/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/packages/react-native-bridge/android/gradle/wrapper/gradle-wrapper.jar b/packages/react-native-bridge/android/gradle/wrapper/gradle-wrapper.jar index 033e24c4cdf41af1ab109bc7f253b2b887023340..2c3521197d7c4586c843d1d3e9090525f1898cde 100644 GIT binary patch literal 43504 zcma&N1CXTcmMvW9vTb(Rwr$&4wr$(C?dmSu>@vG-+vuvg^_??!{yS%8zW-#zn-LkA z5&1^$^{lnmUON?}LBF8_K|(?T0Ra(xUH{($5eN!MR#ZihR#HxkUPe+_R8Cn`RRs(P z_^*#_XlXmGv7!4;*Y%p4nw?{bNp@UZHv1?Um8r6)Fei3p@ClJn0ECfg1hkeuUU@Or zDaPa;U3fE=3L}DooL;8f;P0ipPt0Z~9P0)lbStMS)ag54=uL9ia-Lm3nh|@(Y?B`; zx_#arJIpXH!U{fbCbI^17}6Ri*H<>OLR%c|^mh8+)*h~K8Z<V--Q23O4&HBVn~<)q zmUaP7+TjluBM%#s1Ki#^GurGElkc7{cc6Skz+1nDVk%wAAQYx1^*wA%KSY>!9)DPf zR2h?lbDZQ`p9P;&DQ4F0sur@TMa!Y}S8irn(%d-gi0*WxxCSk*A?3lGh=gcYN?FGl z7D=Js!i~0=u3rox^e<cs4tSN~YA?c-d185$YFNA$Eq1&U{wh#b^OveuKoBPy0oYZ4 zAY2?B=x8yX9}pVM=cLrvugywt!e@Y3lH)i?7fvT*a`O;c)CJQ>O3i@$0=n{K1lPNU zwmfjRVmLOCRfe=seV&P*1Iq=^i`502keY8Uy-WNPwVNNtJFx?IwA<BCEY82WDKJP< zB^CxjFxi=mg*OyI?K3GoDfk;?-K<Z#JoxhYNeEUf896)l%7gL``44}zn)7|Rf;)SC z_EfJr4I+3i(GiHN`R+vHqf}1wXtH?65<wKlxV1BU(#3XgtH<$Fir3S(7QeRA3)u89 zID&66K{&mq$DsB}s&o?H60{cskfh*hvn8hQW#~Q!qM04QtZvx3JEpqeKWE6|+OZW= z(LB7}flr|t7va%>yR<KG!FYzS$bs7qXcpM&wV@~>PZo2<wCq%CszVO$mosTTuv*Mz zOLoi?e^7B~xS22~QW8Rmnt{(AtL<HGi<_P9`0pH;3)@S9Eg`gt2X<om7C^q}pKX|* zTy3X{nOr-xyt4=Qx1IjrzGb!_SyAv^SZcf;air&-;Ua+)5k0z=#R7@UW%)3oEjGA| zZ#DE3px@h1k7w%|4rVIO=0Aid2A%?nBZrupg^_z5J-$$YKeDZ&q8+k7zccb<dc4D; zz}+UYkl_eUNL3PW+reZ6UUB}=sHp~$z%Q}gZ-#ow+ffQIj|A3`B9LO*6%t@)0PV!x ziJ=9fw_>Wo1+S(xF37LJZ~%i)kpFQ3Fw=mXfd@>%+)RpYQLnr}B~~zoof(JVm^^&f zxKV^+3D3$A1G;qh4gPVjhrC8e(VYUHv#dy^)(RoUFM?o%W-EHxufuWf(l*@-l+7vt z=l`qmR56K~F|v<^Pd*p~1_y^P0P^aPC##d8+HqX4IR1gu+7w#~TBFphJxF)T$2WEa zxa?H&6=Qe7d(#tha?_1uQys2KtHQ{)Qco)qwGjrdNL7thd^G5i8Os)CHqc>iOidS} z%nFEDdm=GXBw=yXe1W-ShHHFb?Cc70+$W~z_+}nAoHFYI1MV1wZegw*0y^tC*s%3h zhD3tN8b=Gv&rj}!SUM6|ajSPp*58KR7MPpI{oAJCtY~JECm)*m_x>AZEu>DFgUcby z1Qaw8lU4jZpQ_$;*7RME+gq1Ky<fW-rh4ehZ;%u960Gt5OF)<y$00S=6tVE=%Pt~( z!&BP&2I%`@>SGG#Wql>aL~k9tLrSO()LWn*q&YxHE<sT^`N@Q|)S3y<ZACaLXO56z zncP$~M5K!npWqz?)C50MMw=XqFtDO!3JHI*t-^8Ga&lGPHX2F0pIGdZ3w5ewE+{kf z-&Ygi?@-h(ADD|ljIBw%VHHf1xuQ~}IeIQ5JqlA4#*Nlvd`IfDYzFa?PB=RCcFpZ4 z|HFmPZM=;^DQ_z<IPz$$+yG(H4803QQAA7vQF7;_gv|AD1bH*R-CP3f<<utDpH)Ht zI@{uO12adp{;132YoKPx?C9{&;MtHdHb*0F0;Z~D42}#*l+WD2u?r>uzmwd1?aAtI zBJ>P=&$=l1efe1CDU;`Fd+_;&wI07?V0aAIgc(<VS*?#8Zt!w88FJrjasA1!6>!{a z0Jg6Y=inXc3^n!U0Atk`iCFIQooHqcWhO(qrieUOW8X(x?(RD}iYDLMjSwffH2~tB z)oDgNBLB^AJBM1M^c5HdRx6fBfka`(LD-qrlh5jqH~);#nw|iyp)()xVYak3;Ybik z0j`(+69aK*B>)e_p%=wu8XC&9e{AO4c~O1U`5X9}?0mrd*m$_EUek{R?DNSh(=br# z#Q61gBzEpmy`$pA<eVn3dnmk^xq`=o2)~2c0ywsuTQsC?1WZZehsJYfK@LQ>*6!87 zSDD+=@fTY7<4A?GLqpA?Pb2z$pbCc4B4zL{BeZ?F-8`s$?>*lXXtn*NC61>|*w7J* z$?!iB{6R-0=KFmyp1nnEmLsA-H0a6l+1uaH^g%c(p{iT&YFrbQ$&PRb8Up#X3@Zsk zD^^&LK~111%cqlP%!_gFNa^dTYT?rhkGl}5=fL{a`UViaXWI$k-UcHJwmaH1s=S$4 z%4)PdWJX;hh5UoK?6aWoyLxX&NhNRqKam7tcOkLh{%j3K^4Mgx1@i|Pi&}<^5>hs5 zm8?uOS>%)NzT(%PjVPGa?X%`N2TQCKbeH2l;cTnHiHppPSJ<7y-yEIiC!P*ikl&!B z%+?>VttCOQM@ShFguHVjxX^?mHX^hSaO_;pnyh^v9EumqSZTi+#f&_Vaija0Q-e*| z7ulQj6Fs*bbmsWp{`auM04gGwsYYdNNZcg|ph0OgD>7O}Asn7^<IivRZw`Wa$`V6) zgX@^QL9j}-Od{q5<J*k0+1U=R5+PCYj(U}4VpX+BjfI~+dttS?HJ6uZSGH#H-twTo zaptG40+PAc$fs*zLFkOfGfc+xGs<T?rLGIA%SU7c%jh!E1SNN~*-`ccW8wo4gv2Sj zhify^C(ygi)uGwqXDLqVbH>Z=eI>`$2*v78;sj-}oMoEj&@)9+ycEOo92xSyY344^ z11Hb8^kdOvbf^GNAK++bYioknrpdN>+u8R?JxG=!2Kd9r=YWCOJYXYuM0cOq^FhEd zBg2puKy__7VT3-r*dG4c62Wgxi52EMCQ`bKgf*#*ou(D4-ZN$+m<X+=`m<r!lO%3T zMp}MJd(WDoQ2&6(LClZxpv<vZPPM3Ngkye2VhB=i|B12g5ouw(%`gbWtRq8~sU|o* z$kQ8Jb~6&{ak;r$7@?#t*q9RfAOj=^uAf1z5Y8`N%M`oM@?!~VqN{g%-u$XR1u1Im zGE&AzFpIcER(5jtCPR%RZ)!+|*rU~jZBiOKdqYjO(%yK3Lz;{##(@QEVo>g&7$u!! z-^<eVk1WtrWdvAzoBMHoB$s2RXJCv}%muyVFFJ``?>+Z%;-3IDwqZ|K=ah85OLwkO zKxNBh+4QHh)u9D?MFtpbl)<T1$eOrb4-+U|WDC2BesgFRlgt`klbeQ^1S`7`r+uZ8 zH&U=geA}Si;CUcKvBA&^@<o1GQ7`{1Y(cCHZv|73JIJOvVwLOMZP%Q|)y@^j2e<+z zWVo=#FL!4XNKS~-_1`gw*qi$0j6P7ym_LTvG>us}9+V!D%w9jfAMYEb>%$A;u)rrI zuBudh;5PN}_6J_}l55P3l_)&RMlH{m!)ai-i$g)&*M`eN$XQMw{v^r@-125^RRCF0 z^2>|DxhQw(mtNEI2Kj(;<s2pnue6O@?^QaAp;Ze6z9nX*w}4h7342+0lU$@;Knnve zqqY2Ci=`)@>KblC7x=JlK$@78`O~>V!`|1Lm-^JR$-5pUANAnb(5}B}JGjBsliK4& zk6y(;$e&h)lh2)L=bvZKbvh@>vLlreBdH8No2>$#%_Wp1U0N7Ank!6$dFSi#xzh|( zRi{U<eziQYNZ-=4ReK3@^LFvNQI~(Pdvp+X@J@g#bd~m0wFc+sW3Xf5tyA3xKp;T3 zy14<o-`F}$ET-DQ;B;yNy?d>w%-4W!{IXZ)fWx@XX6;&(m_F%c6~X8hx=BN1&q}*( zoaNjWabE{oUPb!Bt$eyd#$5j9rItB-h*5JiNi(v^e|XKAj*8(k<5-2$&ZBR5fF|JA z9&m4fbzNQnAU}r8ab>fFV%J0z5awe#UZ|bz?Ur)U9bCIKWEzi2%A+5CLqh?}K4JHi z4vtM;+u<SJ)DEVF_yZnTw01M`(s#^BNx+c|MQ6ogb50Jjul0L;!#OmrYCs)iE)7(t z?%I~O!zVNt#Bf3#O2WXsGz!B}&s@MfyDeaoqqf=GELN3g$+DA`&&GKy(`Ya~A@6vK zn|WZ-+tB`DH^+SjI&K3KekF%-QIP%R{F)inWc~@cEO-=3Or<lm9g9}|`|ky#v{5*; zKA5d<ecC{<o9p<U4UUK$m|+q#@(>PsVz{Lfr;78W78gC;z*yTch~4YkLr&m-7%-xc ztw6Mh2<b07B|^BQBjvq{FXx?kyJ);`+G*=&9PMD`1uf<{+pNnnsIQx~kaB?*5<-7a zqY)GyF_w$>d>_iO<o;tRi5=dcnU&wcur@4T5Z=-$xFUEsp-yX${|jSF|HMDPq3?MS zw;p9zjR`yYJOfJZsK~C-S=JQ?nX{z_y@06JFIpheAo-rOG|5&Gxv)%95gpu@ESfi| z7Auc&hjVL;&81Pc#L`^d9gJb`wEtLVH8q|h{>*$Rd8(-Cr1_V8EO1f*^@wRoSozS) zy1UoC@pruAaC8Z_7~_w4Q6n*&B0AjOmMWa;s<dwKr_&w<X$Z*rmLmKUI3S>Iav&gu z|J5&|{=a@vR!~k-OjKEgPFCzcJ>#A1uL&7xTDn;{X<DkOU(-L87#5hf4{m?aj!I6- zPEt$K07IXK8mI0TYf-jhke2QjQw3v?qN5h0-#Fel0)Krq1f)#^AFsfd|K$I={`Xs9 z{JIr8M>BdeM}V=l3B8fE1--DHjSaxoSjNKEM9|U9#m2<eS=8Og#NOG$&X&%|8sOyg zpZ6&%KPd&uh?v{hRMVvQjUL}gY3)Mk3{XQXF{><3>n{Iuo`r3UZp;>GkT2YBNAh|b z^jTq-hJp(ebZh#Lk8hVBP%qXwv-@vbvoREX$TqRGTgEi$%_F9tZES@z8Bx}$#5eeG zk^UsLBH{bc2VBW)*EdS({yw=?qmevwi?BL6*=12k9zM5gJv1>y#ML4!)iiPzVaH9% zgSImetD@dam~e>{LvVh!phhzpW+iFvWpGT#CVE5TQ40n%F|p(sP5mXxna+Ev7PDwA zamaV4m*^~*xV+&p;W749xhb_X=$|LD;FHuB&JL5?*Y2-oIT(wYY2;73<^#46S~Gx| z^cez%V7x$81}UWqS13Gz80379Rj;6~WdiXWOSsdmzY39L;Hg3MH43o*y8ib<ko|2T z<o~B%-$Y4Q9z_t97c`{g0veSfFt63Osbpe2Osn@<=nrAVk_JfMGt&lMGw9leshc#5 z*hkn0u>NBBH`(av4|u;YPq%{R;IuYow<+GEsf@R?=@tT@!}?#>zIIn0CoyV!hq3mw zHj>OOjfJM3F{RG#6ujzo?y32m^tgSXf@v=J$ELdJ+=5j|=F-~hP$G&}tDZsZE?5rX ztGj`!S>)CFmdkccxM9eGIcGnS2AfK#gXwj%esuIBNJQP1WV~b~+D7PJTmWGTSDrR` zEAu4B8l>NPuhsk5a`rReSya2nfV<T&F{)-N{)9$`9a!^D!-03RDN<TPH!aW46TC4L z>1EK01+G!x8aBdTs3Io$u5!6n6KX%uv@DxAp3F@{4UYg4SWJtQ-W~0MDb|j-$lwVn znAm*Pl!?Ps&3wO=R115RWKb*JKoexo*)uhhHBncEDMSVa_PyA>k{Zm2(wMQ(5NM3# z)jkza|GoWEQo4^s*wE(gHz?Xsg4`}HUAcs42cM1-qq_=+=!Gk^y710j=66(cSWqUe zklbm8+zB_<cF$~mH3zum`PN7rn^cr1XvcjzxFO{ms_482AyMFYi+#o7!*vecrNhft z48z<2q#fIw=ce!MXuptfT4+M8FP&|QfB3H@2)dceSR<*e5@hq<#7<$5tC^!RO8Zi< zd_Wl!>syQv5A2rj!Vbw8;|$@C!vfNmNV!yJ<MblqN@23-5g1<aeoul%Um5K((_QY} ze%_@BuNzay69}2PhmC<;m}2=FevDzrp!V!u4u|#h@B=rfKt+v!U`0k7>IWDQ>{+2x zKjuFX`~~HKG~^6h5FntRpnnHt=D&rq0>IJ9#F0eM)Y-)GpRjiN7gkA8wvnG#K=q{q z9dBn8_~wm4J<3J_vl|9H{7q6u2A!cW{bp#r*-f{gOV^e=8S{nc1DxMHFwuM$;aVI^ zz6A*}m8N-&x8;aunp1w7_vtB*pa+OYBw=TMc6Q<xVqo{NJ3h9-a)s5XuYMqZ=Y{7{ z$O63J`)FM-y*mko#!-UBa!3~eYtX1hjRQY2jMxAx=q5uKNm#uaKIak>K=mbA-|Cf* zvyh8D4LRJImooUaSb7t*fVfih<97Gf@VE0|z>NcBwBQze);Rh!k3K_sfunToZY;f2 z^HmC4KjHRVg+eKYj;PRN^|E0>Gj_zagfRbrki68I^#~6-HaHg3BUW%<xsJq4AotN+ zH6twFV=)FlAbs*F6vGws^==x5Tl0AIbcP{&2yxB=)*u+bvK^L6$Vp}U2{9nj{bK~d zee7tC)@DR<dI`D%cA(%7M9Ui3a)^iG?m=oJO0E^``<|5il2sf1fZHvy=D@e0<I)<l zI!|d{`X3u}lz2(4Vn>+clM1<yhZZgPANro5CwhUb>xQEdPYt_g<2K+z!$>*$9nQ>; zf9Bei{?zY^-e{q_*|W#2rJG`2fy@{%6u0i_VEWTq$*(ZN37|8lFFFt)nCG({r!q#9 z5VK_kkS<W$zJN%xs9<lngf<utn=i|I;bCdr-Lr<EzK)tkE-pYh-fc0wqKz?&U8TTN zh_eAdl<>J3?zOH)OezMT{!YkCuSSn!<oaxO4?NS?VufjhPn>K#-Rhl$uUM(bq*jY? zi1xbMVthJ`E>d>(f3)~fozjg^@eheMF6<)I`oeJYx4*+M&%c9VArn(OM-wp%M<-`x z7sLP1&3^%Nld9Dhm@$3f2}87!quhI<BVn6Upp<cc;cU|)&2W%nk!Ak8tXK8aT!m*5 z^9zmeeS|PCG$hgM&Uh}0wp+#$jK3YCwOT&nx$??=a@_oQemQ~hS6nx6fB5r~bFSPp z`alXuTYys4S5dCK)KDGR@7`I-JV^ewQ_BGM^o>@nwd@3~fZl_3LYW-B?Ia>ui`ELg z&Qfe!7<FViITCBP{rA>m6ze=mZ<W0bN&bq-0D3>`Ia9$z|ARSw|IdMpooY4YiPN8K z4B(ts3p%<w%rbophph+BzYj>2i(Td=<hfIaF6Ll8+9!48Ti=xpXB{FgJbk;>tgEHX z0UQ_>URBtG+-?0E;E7Ld^dyZ;jjw0}XZ(}-QzC6+NN=40oDb2^v!L1g9xRvE#@IBR zO!b-2N7wVfLV;mhEaXQ9XAU+>=XVA6f&T4Z-@AX!leJ8obP^P^wP0aICND?~w&N<u ztispy>ykJ#54x3_@r7IDMdRNy4Hh;h*!u(Ol(#0bJdwEo$5437-UBjQ+j=Ic>Q2z` zJNDf0yO6@mr6y1#n3)s(W|$iE_i8r@Gd@!DWD<Q)gT}bxTg_YpJQ5s|m8}+B)KBN6 zYnlzh>qZ7J&~gAm1#~maIGJ<sH@F<m!Fuh_fvrMbcDJNJ5~Yg;LF}NFN}&Y&LL76S zv)~8W2?_rx`P;4LB-=JqsI{I~4U8DnSSIHWU2rHf%vWsA2-d=78An8z4q|lvgQ2iB zhUUI!H+|C+_qp(Tjzu5usOu}cEoivZK&XA==sh0cD|Eg7eERXx?KwHI=}A9S_rx8S zd)VLh_s!Juqi^!0xv7jH)UdSkEY~N|;QMWvs;HN`dMsdK=Dw2mtAHHcK8_+kS%a_V zGgeQoaMM>1sls^gxL9LLG_Nh<XXk<>U!pTGty!TbhzQnu)I*S^54U6Yu%ZeCg`R>Q zhBv$n5j<?~h)Y%y=zErI?{tl!(JWSDXxco7X8WI-6K;9Z-h&~kIv?$!6<k(g(xee? z53>0v%O_j{QYWG!R9W?5_b&67KB$t}&e2LdMvd(PxN6Ir!H4>PNlerpBL>Zvyy!yw z-SOo8caEpDt(}|gKPBd$qND5#a5nju^O>V&;f890?yEOfkSG^HQVmEbM3Ugzu+UtH zC(INPDdraBN?P%kE;*Ae%Wto&sgw(crfZ#Qy(<4nk;S|hD3j{IQRI6Yq|f^basLY; z-HB&Je%Gg}Jt@={_C{L$!RM;$$|<j7k-g{75e!h)4SlFvEZ*AkqrJI;EWu$Zx+OwM zm{5Yk>iD6vu#3w?v?*;&()uB|I-XqEKqZPS!reW9JkLewLb!70T7n`i!gNtb1%vN- zySZj{8-1>6E%H&=V}LM#xmt`J3XQoaD|@XygXjdZ1+P77-=;=eYpoEQ01B@L*a(uW zrZeZz?HJsw_4g0vhUgkg@VF8<-X$B8pOqCuWAl28uB|@r`19DTUQQsb^pfqB6QtiT z*`_UZ`fT}vtUY#%sq2{rchyfu*pCg;uec2$-$N_xgjZcoumE5vSI{+s@iLWoz^Mf; zuI8kDP{!XY6OP~q5}%1&L}CtfH^N<3o4L@J@zg1-mt{9L`s^z$Vgb|mr{@WiwAqKg zp#t-lhrU>F8o0s1q_9y`gQNf~Vb!F%70f}$>i7o4ho<sjDlFD=G`r<7$U?bJN+x5S z@0&tQ=-XO1uDq(HCa$X)-l<u1!s<!W`30F78UcZaZKc8)G0af1Dsh%OOWh5)q+Q+n zySBnE+3;9^#)U#Gq);&Cu=mtjNpsS~S0yjE@m4{Kq525G&cO_+b-_B$LeXWt_@XTq z`)(;=^RDS@oh5dPjKyGAP?-Dbh507E5zZ=D2_C*6s^HXiA)B3f=65_M+rC&rMIUP6 zi4@u>$`uciNf=xgJ>&!gSt0g;M>*x4-`U)ysFW&Vs^Vk6m%?iuWU+o&m(2Jm26<Ea z?or_^bK_`R)hBTfrBqA3Y^o7$K~Nzo)sh-vT%yWcc1I5wF1nkvk%!X_Vl_MK1IHC= zt}Dt+sOmg0sH-?}kqNB|M_}ZXui7H;?;?xCCSIPSHh8@h^K8WU5X(!3W|>Y(3%TL; zA7T)BP{WS!&xmxNw%J=$MPfn(9*^*TV;$JwRy8Zl*yUZi8jWYF>==j~&S|Xinsb%c z2?B+kpet*muEW7@AzjBA^wAJBY8i|#C{WtO_or&Nj2{=6JTTX05}|H>N2B|Wf!*3_ z7hW*j6p3TvpghEc6-wufFiY!%-GvOx*bZrhZu+7?iSrZL5q9}igiF^*R3%DE4aCHZ zqu>xS8LkW+Auv%z-<1Xs92u23R$nk@Pk}MU5!gT|c7vGlEA%G^2th&Q*zfg%-D^=f z&J_}jskj|Q;73NP4<UD^T*M!yxMr=U!@&!rJfydk7CE7PGb<{)^=nM9Le#FQ=GkV~ z)_A$YPAn35??iNa@`g-wBX><4k*Y%pXPU2Thoqr+5uH1yEYM|VtBPW6lXaetokD0u z9qVek6Q&wk)tFbQ8(^HGf3Wp16gKmr>G;#G(HRBx?F`9AIRboK+;OfHaLJ(P>IP0w zyTbTkx_THEOs%Q&aPrxbZrJlio+hCC_HK<4%f3ZoSAyG7Dn`=X=&h@m*|UYO-4Hq0 z-Bq&+Ie!S##4A6OGoC~>ZW`Y5J)*ouaFl_e9GA*VSL!O_@xGiBw!AF}1{tB)z(w%c zS1Hmrb9OC8>0a_$BzeiN?rkPLc9%&;1CZW*4}CDDNr2gcl_3z+WC15&H1Zc2{o~i) z)LLW=WQ{?ricmC`G1GfJ0Yp4Dy~Ba;j6ZV4r{8xRs`13{dD!xXmr^Aga|C=iSmor% z8hi|pTXH)5Yf&v~exp3o+sY4B^^b*eYkkCYl*T{*=-0HniSA_1F53eCb{x~1k3*`W zr~};p1A`k{1DV9=UPnLDgz{aJH=-LQo<5%+Em!DNN252xwIf*wF_zS^!(XSm(9eoj z=*dXG&n0>)_)N5<wxn0{TP0tnD=JAzVUcIUoR85Xt>oc6v!>-bd(2ragD8O=M|wGW z!xJQS<)u70m&6OmrF0WSsr@I%T*c#Qo#Ha4d3COcX+9}hM5!7JIGF>7<~C(Ear^Sn zm^ZFkV6~Ula6+8S?oOROOA6$C&q&dp`>oR-2Ym3(HT@O7Sd5c~+kjrmM)YmgPH*tL zX+znN>`tv;5eOfX?h{AuX^LK~V#gPCu=)Tigtq9&?7Xh$qN|%A$?V*v=&-2F$zTUv z`C#WyIrChS5|Kgm_GeudCFf;)!WH7FI60j^0o#65o6`w*S7R@)88n$1nrgU(oU0M9 zx+EuMkC>(4j1;m6N<sS-ys^qbJhGY7%0ZoC7dK=j7bGdau`J`{>oGqEkpJYJ?vc|B zOlwT3<tNmX!mXZdsEW2s2`|?DC8;N?2tT*Lfq)F*|4vf>t&UgL!pX_P*6g36`ZXQ; z9~Cv}ANFnJGp(;ZhS(@FT;3e)0)Kp;h^x;$*xZn*k0U6-&Fw<BqOnDKEdld8!Qk{Z zjI1+R_ciEqL3CLOv$+J~YVpzIy`S&V{koIi$Lj}ZFEMN=!rL1?_EjSryIV+OBiiJ- zIqT$oSMA>I=uOGaODdrsp-!K$Ac32^c{+FhI-HkYd5v=`PGsg%6I`4d9Jy)uW0y%) zm&j^9WBAp*P8#kGJUhB!L?a%h$hJgQrx!6KCB_TRo%9{t0J7KW8!o1B!NC)VGLM5! zpZy5Jc{`r{1e(jd%jsG7k%I+m#C<kI0i<ajCqQC!(pKlSsMl7M2N^mP%W`BGKb?hm zBK`pddcg5+WhE#$46+K<Z!1CW-hZdo7hAw13ZUVqwW*}&ujL=eh{m~phuOy=JiBMN z7FaCUn6boJ!M=6PtLN6%cveGkd12|1B{)kEYGTx#IiMN&re0`}NP-_{E-#FxOo3*P zkAXSt{et292KfgGN`AR|C`p{MRpxF-I?+`ZY1Vsv>GS*BPA65ZVW~fLYw0dA-H_}O zrkGFL&P1PG9p2(%Qi<evvBkNEkQkM%A>EWm6x;U-U&I#;Em$nx-_I^wtgw3xUPVVu zqSuKnx&dIT-XT+T10p;yjo1Y)z(x1fb8Dzfn8e yu?e%!_ptzGB|8GrCfu%p?(_ zQccdaaVK$5bz;*rnyK{_SQYM>;aES6Qs^lj9lEs6_J+%nIiuQC*fN;z8md>r_~Mfl zU%p5Dt_YT>gQqfr@`cR!$NWr~+`CZb%dn;WtzrAOI>P_JtsB76<bUr7Lsb65vEd}g z5JhMCmn#UeH#6Cew?bxogM)$x5ed{E)%2nWY5rb@Clvh$(JzQ#!CsQ(2I4QnhDDJ^ zYL%2bf8?`y)Ro=x{(dw<4^)(H^z7~3nfYFh-r7yBBb=l3V8dE-Dr&a%qs<OYcajo2 z(4Nw|k5_OQ@6zHmcIK%waj!yoZT(S1YlEFN?8-_lp9nf>PYe*<%H(y>qx-`Kq!X_; z<{RpAqYhE=L1r*M<cT6p|4(5fVa-WIh|@AphR|cJ1`?N>)gNF3B8r(<%8mo*SR2hu zccLRZwGARt)H<F*kMvg%oJV~29ud_q>lo1euqTyM>^!HK*!Q2P;4UYry<i)yWXzKa zM^_qppY~vnIrhL_!;Z9msXMZTTwR{e`yH5t=HdD1Pni7?LqOpLoX}u5n5RfkGBvQ1 z@cdMeR4T6rp^S~>sje@;(<|$&%vQekbn|0Ruu_Io(w4#%p6ld2Yp7tlA`Y$cciThP zKzNGIMPXX%&Ud0uQh!uQZz|FB`4KGD?3!ND?wQt6!n*f4EmCoJUh&b?;B{|lxs#F- z31~HQ`SF4x$&v00@(P+j1pAaj5!s`)b2RDBp*PB=2IB>oBF!*6vwr7Dp%zpAx*dPr zb@Zjq^XjN?O4QcZ*O+8>)|HlrR>oD*?WQl5ri3R#2?*W6iJ>>kH%KnnME&TT<gNU{ zn$Veg044#l=Z-&wsmEZhnw7IwT7Cd}hiZ%ke)-GzAR-Dt6)8Cb6>@Z<Y-SEE^OC5H z=$M0HjdWR5p?n;s9OTXrEa1eGt}G;Eu)ifSop!$z#6V<>zrHS$Q%LC?n|e>V+D+8D zYc4)QddFz7I8#}y#Wj6>4P%34dZH<AWj}HgE@5&D9Ra@o(Km_Gm}5Zb61p%9mDz1% zya$Vd!_U~pDN*Y5%lo}-K~}4&F)rTjJ7uGyV@~kB-XNrIGRiB=UrNxJtX;JHb(EyQ z{!R%v{vC7m|L3bx6lCRb7!mP~Is!r!q&OXpE5nKnH3@l({o}PrL`o>~OUDb?uP%-E zwjXM(?Sg~1!|wI(RVu<h{6ESg9k500(D<HXwz52OGq(JEKS2CJR}8N&E-#%vhhaRN zL#Q6%yUcel+!a#~g&e7w4$3s62d$Dv;SxCxhT}>xbu)-rH+O=igSho_pDCw(c6b=P zKk4ATlB?bj9+HHlh<_!&z0rx13K3ZrAR8W)!@Y}o`?a*JJsD+twZIv`W)@Y?Amu_u zz``@-e2X}27$i(2=9rvIu5uTUOVhzwu%mNazS|lZb&PT;XE2|B&W1>=B58#*!~D&) zfVmJGg8UdP*fx(>Cj^?yS^zH#o-$Q-*$SnK(ZVFkw+er=>N^7!)FtP3y~Xxnu^nzY zikgB>Nj0%;WOltWIob|}%lo?_C7<``a5hEkx&1ku$|)i>Rh6@3h*`slY=9U}(Ql_< zaNG*J8vb&@zpdhAvv`?{=zDedJ23TD&Zg__snRAH4eh~^oawdYi6A3w8<<tS1{)`* zH!u#2_lf&B)x2)tE$?4|aMAYUFZ{|Se7->Ozh@Kw)<E~4fKYaJ{OS+>#bdktM^GVb zrG08?0bG?|NG+w^&JvD*7LAbjED{_Zkc`3H!My>0u5Q}m!+6VokMLXxl`Mkd=g&Xx z-a>m*#G3SLlhbKB!)tnzfWOBV;u;ftU}S!NdD5+YtOjLg?X}dl>7m^gOpihrf1;PY zvll&>dIuUGs{Q<Ww4SS<E23Sm*si$^C!!snD|AFym<+q$`*o0wokE?J{^g?f3>nd- zwIR3oIrct8Va^Tm0t#(bJD7c$Z7DO9*7NnRZorrSm`b`cxz>OI<bVZt$VQ!oMxCu0 zbb7D5OIXV5Ynn@Y6)HLT=1`a=nh7{ee{vr<=$>C;jSE3DO8`hX955ui`s%||YQtt2 z5DNA&pG-V+4oI2s*x^>-$6J?p=I>C|9wZF8z;VjR??Icg?1w2v5Me+FgAeGGa8(3S z4vg*$>zC-WIVZtJ7}o9{D-7d>zCe|z#<9>CFve-OPAYsneTb^JH!Enaza#j}^mXy1 z+ULn^10<XTm*l1Jg2Z;UvGEN!6Wq%I@OP4p{k`RNRKlKFWPt_of11^Gr%_Mg*mVP3 zm?)&3I719~aYcs)TY&q^$zmQ=xoC++VJH@~YG6>+rWLF6j2>Ya@@Kq?26>AqK{A_| zQKb*~F1>sE*=d?A?W7N2j?L09_7n+H<SF8|SM#pTc9|9|rf1w*m4Y0Vdj643qA#D| z!hJzb_-}IrrhkWr{zk_YC%(c-)UJl6Ma!mcbvj&~#yN-UhH?ZQ3TPq4hTVQ$(?eJ6 zNfJ_K+VJDBXN=l!7{2}lq?-$`fq|e&PEONfZDU<_SM+s2_3$vT_yqV<R&KG=K{zS} zKQF$?mYsg%vV|E_E=a*SL!`7*AeN6GMVDXC59yPgi$F2!7&8e}EyHVLwCm{i%<pN! zdc`SbZK}JQj7?6K&|261iHrsnVjdhxu_l_NKs&yy#;#^%8?Jlg`wcTlNZ3urUtEYd zsFE!K0}Eg39)z+J6mLW)#Kn<ok4*6AAE=n*vh*;TpgGnnM|npykFpO|a0`4#SjP^b z2<JG#Qk^#3FeFS`0eooK9|wEmCcvRKI*~6mamFTd^UW9Eg4!J4N9qz*C$3a#F;Sad zi#o9LaqNG5TsiT<`SDtY^`)zkYx$(C5;&K9#(Zj}HolT_st~#C`VS8q%#q1)HN+hT zz9IjVUdZNIp@;b88oR`~DvQL_zmsBy>Gi{VY;MoTGr_)G9)ot$p!-UY5zZ2Xtbm=t z@dpPSGw<TLTZo~Zyx(+AKWvR~{L4S^5I;5+QT9bcQ-4cC{QnLfRBf&Pov~kv@`W6V zA|h{EGx|7msvR1t`a-jF$JZ>gH=QtIcEulQNI>S-#ifbnO5EWkI;$A|pxJd885oM+ zGZ0_0gDvG8q2xebj+fbCHYfAXuZStH2j~|d^sBAzo46(K8n59+T6rzBwK)^rfPT+B zyIFw)9YC-V^rhtK`!3jrhmW-sTmM+tPH+;nwjL#-SjQPUZ53L@A>y*rt(#M(qsiB2 zx6B)dI}6Wlsw%bJ8h|(lhkJVogQZA&n<jl%@&gd%^X|lsDQwDHEiKLCz}r`kC^h0t z(!vYS%C)Ku?w$ti5R##9jSkNC#5)Juc{8XfEhczdGQy8yNrZL6+d0~%V=N|iF{V)E zLT(gH!$j8Mf(1>{?Vgs6gNSXzuZpEyu*xySy8ro07QZ7Vk1!3tJphN_5V7qOiyK8p z#@jcDD8nmtYi1^l8ml;AF<#IPK?!pqf9D4moYk>d99Im}Jtwj6c#+A;f)CQ*f-hZ< z=p_T86jog%!p)D&5g9taSwYi&e<jP@@Q_fbXtVO&n9{e#)jg+D#~q=hoZ<9PIa)>P z#JuEK%+NULWus;0w32-SYFku#i}d~+{Pkho&^{;RxzP&0!RCm3-9K6`>KZpnzS6?L z^H^V*s!8<>x8bomvD%rh>Zp3>Db%kyin;qtl+jAv8Oo~1g~mqGAC&Qi_wy|xEt2iz zWAJEfTV%cl2Cs<1L&DLRVVH05EDq`pH7Oh7sR<WSzBWU(MxAIA&4v~INVdLKA><BK zwCgTxJU0mM{;1UV<^ZRk0SQNNN(;SRZsH7^EDWVUu%^mFfvW{m5jOQuQWSy`f586I zTj}Z4e5WsvkNmBd`TJdfe=^>`NNkL%wi}8n>IXcO40hp+J+sC!W?!krJf!GJNE8uj zg-y~Ns-<~D?yqbzVRB}G>0A^f0!^N7l=$m0OdZuqA<e9rzV|ixGyk9uS=Vov2_ECA z^Sd0M$B)O&tv@%@UmTb%ngcl58ED9TyFp$y4JjFU+g+9EWUl?am<e#4uCGy9Tmt)z z2Y|kWUahugFHsF<J6o!<?X(Ncsy&Wg9<QLPD}g-`PWGHWDY5P6;<Y+5J1vz2Z|PSy zBN?Q^NkxnWq>OQq<EC8_d&#T2smn`YINd-HF@)Op)pBRHnx+Q|Hsv_BpWAPsT1>Lc zX?AEGr1Ht+inZ-Qiwnl@Z0qukd__a!C*CKuGdy5#nD7VUBM^6OCpxCa2A(X;e0&V4 zM&WR8+wErQ7UIc6LY~Q9x%Sn*Tn>>P`^t&idaOEnOd(Ufw#>NoR^1QdhJ8s`h^|R_ zXX`c5*O~Xdvh%q;7L!_!ohf$NfEBmCde|#uVZvEo>OfEq%+Ns7&_f$OR9xsihRpBb z+cjk8LyDm@U{YN>+r46?nn{7Gh(;WhFw6GAxtcKD+YWV?uge>;+q#Xx4!GpRkVZYu zzsF}1)7$?%s9g9CH=Zs+B%M_)+~*j3L0&Q9u7!|+T`^O{xE6qvAP?XWv9_MrZKdo& z%IyU)$Q95AB4!#hT!_dA>4e@zjOBD*Y=XjtMm)V|+IXzjuM;(l+8aA5#Kaz_$rR6! zj>#&^DidYD$nUY(D$mH`9eb|dtV0b{S>H6FBfq>t5`;OxA4Nn{J(+XihF(stSch<f zIn>e7$es&~N$epi&PDM_N`As;*9D^L==2Q7Z2zD+CiU(|+-kL*VG+&9!Yb3LgPy?A zm<g7T4Wx!m(zMlVE_2jX$1$$5DcfL6>7Z&^qRG_JIxK7-FBzZI3Q<;{`DIxtc48k> zc|0dmX;Z=W$+)qE)~`yn6MdoJ4co;%!`ddy+FV538Y)j(vg}5*k(WK)KWZ3WaOG!8 z!syGn=s{H$odtpqFrT#JGM*utN7B((abXnpDM6w56nhw}OY}0TiTG1#f*VFZr+^-g zbP10`$LPq_;PvrA1XXlyx2uM^mrjTzX}w{yuLo-cOClE8MMk47T25G8M!9Z5ypOSV zAJUBGEg5L2fY)ZGJb^E34R2z<C?_X1)4xsl9%Z|w&L9k!F(V>J?}Vf>{~gB!8=5Z) z9y$>5c)=;o0HeHHSuE4U)#vG&KF|I%-cF6f$~pdYJWk_dD}iOA>iA$O$+4%@>JU08 zS`ep)$XLPJ+n0_i@PkF#ri6T8?ZeAot$6JIYHm&P6EB=BiaNY|aA$W0I+nz*zkz_z zkEru!tj!QUffq%)8y0y`T&`fuus-1p>=^hnBiBqD^hXrPs`PY9tU3m0np~rISY09> z`P3s=-kt_cYcxWd{de@}TwSqg<T-v~${38)1dqT{JCO5}Gk$$yZP*X!5)RaGFqqkZ zeHhqUgXb37$91~LS-3Zi29CKKki0sBTh7unqEK$%FG?oo$Sp>*xVhp;E9zCsnXo6z z?f&Sv^U7n4`xr=mXle94HzOdN!2kB~4=%)u&N!+2;z6UYKUDqi-s6AZ!haB;@&B`? z_TRX0%@suz^TRdCb?!vNJYPY8L_}&07uySH9%W^Tc&1pia6y1q#?*Drf}GjGbPjBS zbOPcUY#*$3sL2x4v_i*Y=N7E<UbOmi3K%)5<dOJui+{^+b*shA_w8&X4_Icv*!}kT zW@BG{C%f{(K^kE?tjU`Led*kAj6wB_3f*UyIEV0T9TyMo4`NS;oA7Ec+71eFa;K|G zCyaKKi1bvX9fTLQ+uAgF*@ZR8fB%|JlT8A-jK$7FMyxW>$mR}J%|GUI(>WEr+28+V z%v5{#e!UF*6~G&%;l*q*$V?&r$Pp^sE^i-0$+RH3ERUUdQ0>rAq2(2QAbG}$y{de( z>{qD~GGuO<V3ijl7+~xmS#nUvH{qF0*%7G(r|}BSXsu}HwrFbXWzcYJouIY*34axA z(n@XsPrv%6;|GSbkH9Og>k559Y@%$?N^1ApVL_a704>8OD%8Y%8B;FCt%AoPu8*D1 zLB5X>b}Syz81pn;xnB}%0FnwazlWfUV<Vu@5P52pgIa+J{M)H4nAC<>)Z-~rZg6~b z6!9J$EcE&sEbzcy?CI~=boWA&eeIa%z(7SE^qgVLz??1Vbc1*aRvc%Mri)AJaAG!p z$X!_9Ds;Zz)f+;%s&d<S0a>RcJt2==P{^j3bf0M=nJd&xwUGlUFn?H=2W(*2I2Gdu zv!gYCwM10aeus)`RIZSrCK=&oKaO_Ry~D1B5!y0R=%!i2*KfXGYX&gNv_u+n9wiR5 z*e$Zjju&ODRW3phN925%S(jL+bCHv6rZtc?!*`1<n2%>TyYXT6%Ju=|X;6D@lq$8T zW{Y|e39ioPez(pBH%k)HzFITXHvnD6hw^lIoUMA;qAJ^CU?top1fo@s7xT13Fvn1H z6JWa-6+FJF#x>~+A;D~;VDs2<i>6>^oH0EI`IYT2iagy23?nyJ==i{g4%HrAf1-*v zK1)~@&(KkwR7TL}L(A@C_S0G;-GMDy=MJn2$FP5s<%wC)4jC5PXoxrQBFZ_k0P<n- z??iM<JF!BTjD>{{s@<jPT1+pTPdk3<izB+}jAtjokIz)aPR$L&4%}45Et}?jz0w{( zC4G}+Nu0D*w=ay`v91hMo+V&V8q(a!`~K-2<yR0H)sK+mcY?TAaSS8F<Q+!pSc;`* z*c@5)+ZpT%-!K3O=Z0(hI8LH7KqK>sz+gX`-!=T8rcB(=7vW}^K6oLWMmp(rwDh}b zwaGGd>yEy6fHv%jM$yJXo5oMAQ>c9j`**}F?MCry;T@47@r?&sKHgVe$MCqk#Z_3S z1GZI~nOEN*P~+UaFGnj{{Jo@16`(qVNtbU>O0Hf57-P>x8Jikp=`s8xWs^dAJ9lCQ z)GFm+=OV%AMVqVATtN@|vp61VVAHRn87}%PC^RAzJ%JngmZTasWBAWsoAqBU+8L8u z4A&Pe?fmTm0?mK-BL9t+{y7o(7jm+RpOhL9Kn<D3v{}Wpv2i&ghEZe;t&DmOA_QYc zM+NIUU}=*bkxOJsLKV3e^oGG8rufTpa8R~7Iki1y+fC(UT;;{l19@qfxO@0^!xMA? z#|<YBZ6;vAb>Y#E&qu^}B6=K_dB}*VlSEiC9fn)+V=J;OnN)Ta5v66ic1rG+dGAJ1 z1%Zb_+!$=tQ~lxQrzv3x#CPb?CekEkA}0MYSgx$Jdd}q8+R=ma$|&1a#)TQ=l$1tQ z=tL9&_^vJ)Pk}EDO-va`UCT1m#Uty1{v^A3P~83_#v^ozH}6*9mIjIr;t3Uv%@VeW zGL6(CwCUp)Jq%G0bIG%?{_*Y#5IHf*5M@wPo6A{$Um++Co$wLC=J1aoG93&T7Ho}P z=mGEPP7Gb<mBTnJH7dKM2CB)0*o-AW2E4i5R+rHU%4A2BTVwOqj4zmJqsb|5^*{DT zv^HFARK6@^_1|vU{>voG!uD$k(H3A$Z))+i{Hy?QHdk>3xSBXR0j!11O^mEe9RH<y zF3MI;^J1vHI9U>mw!pvzv?Ua~2_l2Yh~_!s1qS`|0~0)<BWX>YsbHSz8!mG)WiJE| z2<APmuYD%tKwB@0u<C~CKyaC}XX{?mylzkDSuLMkAoj?zp*zFF7q515SrGD~s}ATn z`Ded41yk>f($6TQtt6L_f~ApQYQKSb=`053LgrQq7G@98#igV>y#i==-nEjQ!XNu9 z<h*hnP2Pol+z>~;mE+gtj4IDDNQJ~JVk5Ux6&LCSFL!y=>79kE9=V}J7tD==Ga+IW zX)r7>VZ9dY=V&}DR))xUoV!u(Z|%3ciQi_2jl}3=$Agc<a_3#EUXJj<z2jVv6VHGT zV^v1FiRwA!kPmt}m$qdr&9#-6{QeZqtM3|tRl$sws3Gy`no`Kj@X-)O(^sv>(`RPb z8kEBpvY>1FGQ9W$n>Cq=DIpski};nE)`p3IUw1Oz0|wxll^)4dq3;CCY@RyJgFgc# zKouFh!`?Xuo{IMz^xi-h=StCis_M7y<P{h0$_I#EukRYag9%BMRXh|%Xl7C<>q$u) z?XHvw*HP0VgR+KR6wI)jEMX|ssqYvSf*_3W8zVTQzD?3>H!#>InzpSO)@SC8q*ii- z%%h}_#0{4JG;Jm`4zg};BPTGkYamx$Xo#O~lBirRY)q=5M45n{GCfV<Kqrcu9<z@R zSE>7h9qwyu1NxOMoP4)jjZMxmT|IQQh0U7C$EbnMN<3)Kk?fFHYq$d|ICu>KbY_hO zTZM+uKHe(cIZfEqyzyYSUBZa8;Fcut-GN!HSA9ius`lt<SmSV9vasBl&hE7ciOunD z?%e1Hl-5B3e+<+8CD{j5U*D3h89nV<zn^0g+t=uRKgZiGu)3h;vu#^y`HqWe_=jGm zW2p}*n<!QH%pQ2EV`&z|LD#BOpj0QS9R5#$q}3&-+@GL4F^wO-bcSo|J^I_{LATPF z2$`fUCOO=XxYVD!<7Yz4te$d-_>NebF46ZX_BbZNU}}ZOm{M2&nAN<H$fJIKS=j8q zwXlN!l^_4>L9@0qvih15(|`S~z}m&h!u4x~(%MAO$jHRWNfuxWF#B)E&g3ghSQ9|> z(MFaLQj)NE0lowyjvg8z0#m6FIuKE9lDO~Glg}nSb7`~^&#(Lw{}GVOS>U)m8bF}x zVjbXljBm<v)#bs=9p`s>34Cs-yM6TVusr+3kYFjr28STT3g056y3cH5Tmge~ASxBj z%|yb>$eF;WgrcOZf569sDZOVwoo%8>XO>XQOX1OyN9I-SQgrm;U;+#3OI(zrWyow3 zk==|{<m8xZ#>lt2xrQ%FIXOTejR>;wv(Pb8u8}BUpx?yd(Abh<shPyABw|Ens8m6@ zIg($GO4)<g4x5icbki?U&2%56@tYd`zRs}Nk6R~4!AjVAihB3r8oDhQ8f)v^r}|(y z4B&Q<ARRqYXKQGAeJa_KHe`)04jUO~B=%q#SUlU@pU?apz0v{Al@s`Cvzo)u;2>6? zsoO3VYWkeLnF43&@*#MQ9-i-d0t*xN-UEyNKeyNMHw|A(k(_6QKO=nKMCxD(W(Yop zsRQ)QeL4X3Lxp^L%wzi2-WVSsf61dqliPUM7srDB?Wm6Lzn0&{*}|IsKQW;02(Y&| zaTKv|`U(pSzuvR6Rduu$wzK_W-Y-7>7s?G$)U}&uK;<>vU}^^ns@Z!p+9?St1s)dG zK%y6xkPyyS1$~&6v{kl?Md6gwM|>mt6Upm>oa8RLD^8T{0?HC!Z>;(Bob7el(DV6x zi`I)$&E&ngwFS@bi4^xFLAn`=fzTC;aimE^!cMI2n@Vo%Ae-ne`RF((&5y6xsjjAZ zVguVoQ?Z9uk$2ON;ersE%PU*xGO@T*;j1BO5#TuZKEf(mB7|g7pcEA=nYJ{s3vlbg zd4-DUlD{*6o%Gc^N!Nptgay>j6E5;3psI+C3Q!1ZIbeCubW%w4pq9)MSDyB{HLm|k zxv-{$$A*pS@csolri$Ge<4VZ}e~78JOL-EVyrbxKra^d{?|NnPp86!q>t<&IP07?Z z^>~IK^k#OEKgRH+LjllZXk7iA>2cfH6+(e&9ku5poo~6y{GC5>(bRK7hwjiurqAiZ zg*DmtgY}v83IjE&AbiWgMyFbaRUPZ{lYiz$U^&Zt2YjG<%m((&_JUbZcfJ22(>bi5 z!J?<7AySj0JZ&<-qXX;mcV!f~>G=sB0KnjWca4}vrtunD^1TrpfeS^4dvFr!65knK zZh`d;*VOkPs4*-9kL>$GP0`<?hW@{z#_gXtp%=2VbN+$~z+M($Vf(dl@)t-*82<$( zHi{FrD1wO9L~*Rc0{A2WU%f?ar(T9V1JpQ?M0Q|&{UES|#Z~k2-mj@z)8Rw^(XeYc zomT(B0EF!##4dQq_*NN<%Bo5)&+gCXSGZo`b>(M!j~B;#x?Ba<KDM~HJ!|Zzy=p2e z8;av`GLw{_*RgO(W|UK-<iDeT!t_x1c=M3%wGk|fDk<e0lLe8-5ga6apKYJD`*a3G zBl?Ps)hDb7X`7bW5S=IHr0Mm?fr|$zCf+gmZUrit$5n+)JZG>~&s6CopvO86oM?-? zOw#dIRc;6A<R&%m3DDJhF+|tb*0Yw8mV{a-bf^E~gh66MdsMHkog<r9`fVIVE+h@O zi)iM`rmA-Fs^c=>6T?B`Qp%^<<Dyu<%Kg0H=lq;E!p&UHzSpD1)q%^v)Y8yQkp>U5 z19x(ywSH$_N+Io!6;e?`tWaM$`=D<O;$E>b!gzx|lQ${DG!zb1Zl&|{kX0y6xvO1o z220r<-oaS^^R2pEyY;=Qllqpmue|5yI~D|iI!IGt@iod{Opz@*ml^w2bNs)p`M(Io z|E;;m*Xpjd9l)4G#KaWfV(t8YUn@A;nK^#xgv=LtnArX|vWQVuw3}B${h+frU2>9^ z!l6)!Uo4`5k`<<;E(ido7M6lKTgWezNLq>U*=uz<KVOwgK<qq^3FEy1LAV}ep3|Zt z>&s=cc$1%>VrAeOoUtA|T6gO4>UNqsdK=NF*8|~*sl&wI=x9-EGiq*aqV!(VVXA57 zw9*o6Ir8Lj1npUXvlevtn(_+^X5rzdR>#(}4YcB9O50q97%rW2me5_L=%ffYPUSRc z!vv?Kv>dH994Qi>U(a<0KF6NH5b16enCp+mw^Hb3Xs1^tThFpz!3QuN#}KBbww`(h z7GO)1olDqy6?T$()R7y%NYx*B0k_2IBiZ14&8|JPFxeMF{vW>HF-ViB*%t0;Thq2} z+qP}n=Cp0wwr%5S+qN<7?r+``=l(h0z2`^8j;g2~Q4u?{cIL{JYY%l|iw&YH4FL(8 z1-*E#ANDHi+1f%<FEETVoPos>lMJbRfq*`nG)*#?EJEVoDH5XdfqwR-C{zmbQoh?E zhW!|TvYv~>R*OAnyZf@gC+=%}6N90yU@E;0b_OV#xL9B?GX(D&7BkujjFC@HVKFci zb_>I5e!yuHA1LC`xm&;wnn|3ht3h7|rDaOsh0ePhcg_^Wh8Bq|AGe`4t5Gk(9^F;M z8mFr{uCm{)Uq0Xa$Fw6+da`C4%)M_#jaX$xj;}&Lzc8wTc%r!Y#1akd|6FMf(a4I6 z`cQqS_{rm0iLnhMG~CfDZc96G3O=Tihnv8g;*w?)C4N4LE0m#H1?-P=4{KeC+o}8b zZX)x#(zEysFm$v9W8-4lkW%VJIjM~iQIVW)A*RCO{Oe_L;rQ3BmF*bhWa}!=wcu@# zaRWW{&7~V-e_$s)j!lJsa-J<VS<FyMLS`=mm2DyVkhoo@GUWHJSEvdPg7RxL3UHfy z*gs(_Q*VnSV{81NNpzoHc>?z;54!;KnU3vuhp~(9KRU2GKYfPj{qA?;#}H5f$Wv-_ zGrTb(EAnpR0*pKft3a}6$npzzq{}ApC&=C&9KoM3Ge@24D^8ZWJDiXq@r{hP=-02& z@Qrn-cbr2YFc$7XR0j7{jAyR;4LLBf_XNSrmd{dV3;ae;fsEjds*2DZ&@#e)Qcc}w zLgkfW=9Kz|eeM$E`-+=jQSt}*kAwbMBn7AZSAjkHUn4n||NBq*|2QPcKaceA6m)g5 z_}3?DX>90X|35eI7?n+>f9+hl5b>#q`2+`FXbOu9Q94UX-GWH;d*dpmSFd~7WM#H2 zvKNxjOtC)U_<K!UT4EWFJ`0%qla66gi)v;h2;>tx*0(J)eAI8xAD8SvhZ+VRUA?)| zeJjvg9)vi`Qx;;1QP!c_6<TaBw5yUTI?4(<(Ap023XRh}!HQ_3Fm-D8%`yp_x#8B! zN`-?}P}FCH(8@_>hJp1=J=*%!>ug}%O!CoSh-D_6LK0JyiY}rOaqSeja&jb#P|DR7 z_JannlfrFeaE$irfrRIiN|huXmQhQUN6VG*6`bzN4Z3!*G?FjN8!`ZTn6Wn4n=Ync z_|Sq=pO7+~{W2}599SfKz@umgRYj6LR9u0*BaHqdEw^i)dKo5HomT9zzB$I6w$r?6 zs2gu*wNOAMK`<Vwp^NK2&^tzKYH;5$ul;h083?OwlA%T%-S=_}dw4qW5+S+XO0ak! zevPUnu$QsnVyIYV{2~>+5yPBIxS<I@Dj|*;M}4yQ9m%YNUmuCMV>OJpL$@SN&iUaM zQ3%$EQt%zQBNd`+rl9R~utRDAH%7XP@2Z1s=)ks77I(>#FuwydE5>LzFx)8ye4ClM zb*e2i*E$Te%hTKh7`&rQXz;gvm4Dam(r-!FBEcw*b$U%Wo9DIPOwlC5Ywm3WRCM4{ zF42rnEbBzUP>o>MA){;KANhAW7=FKR<s?Q(b#6vUYUif4R6`g>=DKK&S1AqSxyP;k z;fp_GVuV}y6YqAd)5p=tJ~0KtaeRQv^nvO?*hZEK-qA;vuIo!}Xgec4QGW2ipf2HK z&G&ppF*1aC`C!FR9(j4&r|SHy74IiDky~3Ab)z@9r&vF+Bapx<{<G#FO>u~gb2?*J zSl{6YcZ$&m*X)X<A3nlHC|>?|8<2S}WDrWN3yhyY7wlf*q`n^z<p#C6Wwg0Lc^7yc z{k35LkK*(Ql>3LT4T$@$y``b{m953kfBBPpQ7hT;zs(Nme`Qw@{_p<uKf;<4btoSk zRm`706ZWQUJLyJS5NS(XVIk-1Qgl|?{JCQFalvu23h5}<#*fAfGk3F$41iz>UO0OG zfugi3N?l|jn-Du3Qn{Aa2#6w&qT+oof=YM!Zq~Xi`vlg<;^)Jreeb^x6_4HL-j}sU z1U^^;-WetwPLKMsdx4QZ$haq3)rA#ATpEh{NXto-tOXjCwO~nJ(Z9F%plZ{z(ZW!e zF>nv&4ViOTs58M+f+sGimF^9cB*9b(gAi<XFtFDIykkajehj!02m(2aL02PawRDy_ z*i~rdmXPeyi=)nB3g8Mx4Wi>zwyu5|--SLmBOP-uftqVnVBd$f7YrkJ8!jm*QQEQC zEQ+@T*AA1kV@SPF6H5sT%^$$6!e5;#N((^=OA5t}bqIdqf`PiMMFEDhnV#AQWSfLp zX=|ZEsbLt8Sk&wegQU0&kMC|cuY`&@<#r{t2*sq2$%epiTVpJxWm#OPC^wo_4p++U zU|%XFYs+ZCS4JHSRaVET)jV?lbYAd4ouXx0Ka6*wIFBRgvBgmg$kTNQEvs0=2s^sU z_909)3`Ut!m}}@sv<63E@aQx}-!qVdOjSOnAXTh~MKvr$0nr(1Fj-3uS{<m;+EJv+ z(b49OY^IhZ0b$bXM5E^i4)FWy3XukhWUP*i(QIB^`nJPbqZL6f!_ooB=w~NprhpQ4 zqPQCBat+sMcGd0B$rBNY{D(W1XU2RrsQ<DV;I7-88%iIY>U6-T9NG1Y(Ua)Nc}Mi< zOBQz^&^v*$BqmTIO^;r@kpaq3n!BI?L{#bw)pdFV&M?D0HKqC*YBxa;QD_4(RlawI z5wBK;7T^4dT7zt%%P<*-M~m?Et;S^tdNgQSn?4$mFvIHHL!`-@K~_Ar4vBnhy{xuy zigp!>UAwPyl!@~(bkOY;un&B~Evy@5#Y&cEmzGm+)L~4o4~|g0uu&9bh8N0`&{B2b zDj2>biRE1`iw}lv!rl$Smn(4Ob>j<{4dT^TfLe-`cm#S!w_9f;U)@aXWSU4}90LuR zVcbw;`2|6ra88#Cjf#u62xq?J)}I)_y{`@hzES(@mX~}cPWI8}SRoH-H;o~`>JWU$ zhLudK3ug%iS=xjv9tnmOdTXcq_?&o30O;(+VmC&p+%+pd_`V}RY4ibQM<T~=yiutj z8PY3n0uEtXb9>NE&N5O+hb3bQ8bxk^33Fu4DB2*~t1909gqoutQHx^plq~;@g<Tn< zGIy~gC#ZKTD#!!uxjrLk#?Tj4SA(prkyQk5LV8nE+cuzXv_@|$a5Y|l6wO*uhLx)e z4a4f>$d_+rzS0`2;}2UR2h#?p35B=B*f0BZS4ysiWC!kw?4B-dM%m6_BfRbey1Wh? zT1!@>-y=U}^fxH0A`u1)Mz90G6-<4aW^a@l_9L6Y;cd$3<#xIrhup)XLkFi$W&Ohu z8_j~-VeVXDf9b&6aGelt$g*BzEHgzh)KDgII_Y<!yt~^$ZjIYrUsiH!TWfQi@+75> zb$fcY8?XI6-GEGTZVWW%O;njZld)29a_&1QvNYJ@OpFrUH{er@mnh*}326TYAK7_Z zA={KnK_o3QLk|%m@bx3U#^tCChLxjPxMesOc5D4G+&mvp@Clicz^=kQlWp1|+z|V7 zkU#7l61m@^#`1`<I>{+m2L{sZC#j?#>0)2z4}}kqGhB{NX%~+3{5jOyij!e$5-OAs zDvq+>I2(XsY9%NNhNvKiF<%!6t^7&k{L7~FLdkP9!h%=2Kt$bUt(Zwp*&xq_+nco5 zK#5RCM_@b4WBK*~$CsWj!N!3sF>ijS=~$}_iw@vbKaSp5Jfg89?peR@51M5}xwcHW z(@1TK_kq$c4lmyb=aX3-JORe+JmuNkPP=bM*B?};c=_;h2gT-nt#qbriPkpaqoF@q z<)!80iKvTu`T-B3VT%qKO^lfPQ#m5Ei6Y%Fs@%Pt!8yX&C#tL$=|Ma8i?*^9;}Fk> zyzdQQC5YTBO&gx6kB~yhUUT&%q3a3o+zueh>5D7tdByYVcMz@>j<TXu&?x1p)Dnh4 zskNHSw3{&FN-50Bq2nx!SyUG4E$vH!z7_A#oMR)rO?_v?C8{JTwDkINn0II$m85#c z=Oz^^KRrLn$uotBRrtGqFhJj!f{G=XOZ**42DuGuDV6Abhb?6wWQOK{N<$^)G9JVq zt~tbaQV!u?NZzl7@GbKqp0ciBI=QTB*7T*H^m0C+Pgw-+N?f7g%v34xjXqwU!THzz zwM!z}e-39`DuQ;0;)(52iX5VSp8CeKy2w+ekh}=S)Tpqyj)`%7J^n-rd%;J%K3Gi} z%J>!C@Iyg{N1)veYl`SPshuH6Rk=O6pvVrI71rI5*%uU3u8<J<JbTb96qe0Z){uD! z(?jD_k*1=Jk;r`o{F1rd>1DpD%qmXsbKWMFR@2m4vO_^l6MMbO9a()DcWmYT&?0B_ zuY~tDiQ6*X7;9B*5pj?;xy_B}*{G}LjW*<O@op=u{qXpBL4WR|o`e}#yS2mt=`0;g zk*qCDShkd<mE}6<cHkR<36dq_>qU&%*QAyt30@-@O&NQTARZ+%VScr>`s^KX;M!p; z?8)|}P}L_CbOn!u(A{c5?g{s31Kn#7i)U@+_KNU-ZyVD$H7rtOjSht8%N(ST-)%r` z63;Hyp^KIm-?D;E-EnpAAWgz2#z{fawTx_;MR7)O6X~*jm*VUkam7>ueT^@+Gb3-Y zN3@wZls8ibbpaoR2xH=$b3x1Ng5Tai=LT2@_P&4JuBQ!r#Py3ew!ZVH4~T!^TcdyC ze#^@k4a(<cMT=zWd{@BY-TQaG5^m)U6v^8CU<UZ_h<X&S{e&<ef!K*nDS^u)sz!oF zv3GpwPwiz<Z+%$2K{duN*{|U`y!Fv~<V~KMYNpb%jaA|d%{RrZuC9RL9x}h~2mfw1 z&(5bE{Pi$T`3c }kCcXotNM^kKsx=!bNtXw@bPnpdnxv8U{@5jwl4iOuy*Ulv$E zRr*O)*pGI|*{;DjKY6EYGY$UA(CyZ^Mb{|X{&ULt(gt&t##t?F&^Ke41N>nNe~G+y zI~yXK@1HHWU4pj{gWT6v@$c(x){cLq*KlFeKy?f$_u##)hDu0X_mwL6uKei~oPd9( zRaF_k&<bAvtIGrfv>w(J3J8b_`F~?0(Ei_pH}U^c&r$uSYawB8Ybs-JZ|&;vKLWX! z|HFZ%-uBDaP*hMcQKf*|j5!b%H40SPD*#{A`kj|~esk@1?q}-O7WyAm3mD@-vHzw( zTSOlO(K9>GW;@?@xSwpk%<BKz8jI}jIy`hcjM+(B2?y5RU8)J_t<^5T@5q(eVqo~3 zBO68aBr!giDu{-&mRO;X`_kCOk)SVi<#mG97Yofg&i@{QaPtr9sJxfvm*9;H@SuqC z#w2yv`XkX1Fm#r#GTnk<zr=n4H&oj2trmnx;X0_I*?j3mQjbM7=91jZ%cM_@DOx<; zBe@nMc^$^rGU$*j_K!qihH$KrnG1{anC~y4rqtiuKPczy-nHp9ziDlM+nm{BSGIn0 zjn88Zt)ktBnnU9JS3+R3k%!$OX$-hyV?#RNtxr;3X|+ibRRJk|C)0tNBhCqmxt%~k zW?jp7e1}Enb4c}+LT;RXFHvB<;HU$-BkxGUpu}xuVnee$aH?Ht5a*=Bfi1cpjp1AR zW0AS6J<>X3Ui4<EIxkjj2rf49E}4o!{lom8bZats3e|!F%@Mv0>_Psm;c*HF<uwRu zX2v}!DHM6Kd-vD^RoMp^t<T_OS$tZpDzDxl@Nzk;J6quA5BF_A1kKnbiWC2T)kFlH z(V^D=L0ygiE7V2xzZuVegW~^zIRA&`lxRZvU>~RW+q+C#RO_VT5(x!5B#On-W`T|u z>>=t)W{=B-8wWZejxMaBC9sHzBZGv5uz_uu281kxHg2cll_sZBC&1AKD`CYh2vKeW zm#|MMdC}6A&^DX=>_(etx8f}9o}`(G?Y``M?D+aTPJbZqONmSs>y>WSbvs>7PE~cb zjO+1Y)<CO?dR1Cg5s4M@qpdPA5@SkWDB@mH^43~g;%513aUq^B5_>PMi*!=06^$%< z*{b^66BIl{7zKvz^jut7ylDQBt)ba_F*$UkDgJ2gSNfHB6+`OEiz@xs$Tcrl>X4?o zu9~~b&Xl0?w(7lJXu8-9Yh6V|A3f?)1|~+u-q&6#YV`U2i?XIqUw*lc-QTXwuf@8d zSjMe1BhBKY`Mo{$s%Ce~Hv(^B{K%w{yndEtvyYjjbvFY^rn<KGkLBo^m9vg?nW<6+ zPmh<G^yK&-NDUiC8Z6ast0*z8xPQ8$(*j>2>C1Lbi!3RV7F>&;zlSDSk}R>{twI}V zA~NK%T!z=^!qbw(OEgsmSj?#?GR&A$0&K>^(?^4iphc3rN_(xXA%joi)k~DmRLEXl zaWmwMolK%@YiyI|HvX{X$*Ei7y+zJ%m{b}$?N7_SN&p+FpeT%4Z_2`0CP=}Y3D-*@ zL|4W4ja#8*%SfkZzn5sfVknpJv&>glRk^oUqykedE8yCgIwCV)fC1iVwMr4hc#<Z- zL-+W<jR>KcV!|M-r_N|nQWw@`j+0(Ywct~kLXQ)Qyncmi{Q4`Ur7A{Ep)n`zCtm8D zVX`kxa8Syc`g$6$($Qc-(_|LtQKWZXDrTir5s*pSVmGhk#dKJzCYT?vqA9}N9DGv> zw}N$byrt?Mk*ZZbN5&zb>pv;rU}EH@Rp54)vhZ=330bLvrKPEPu!WqR%yeM3LB!(E zw|J05Y!tajnZ9Ml*-aX&5T8YtuWDq@on)_*FMhz-?m|>RT0~e3OHllrEMthVY(KwQ zu>ijTc4>Xz-q1(g!ESjaZ+C+Zk5FgmF)rFX29_RmU!`7Pw+0}>8xK^=pOxtUDV)ok zw-=p=OvEH&VO3wToRdI!hPHc`qX+_{T_mj!NxcA&<p<h=eBG647W~srCOJ%YnAZc= z_Nfs1f}E6YV&pASfTpH}9tbu)4{#Ba2MsPj-56upCP@MeA3PUmV6EQ*1z#*N^TEue zy@dbDn?Ia-I`54^Z~pl7(zVZ_pG(9*?1GC3@YUj}QeUNX!ITTXIG3PGU6uEwG;a^& zqj~LaL>xOgkEuvz`-Aa`ZlNv>qnD0`YT1T3USO0ec!%{KE~UOGPJX%I5_rZDGx@|w zVIMsRPP+}^Xxa&{x!q{hY1wat8jDO7YP0(8xHWeEdr<P*6`9ax>d79lUj<UfD%PK; z4Isv2N9v5&5n-oxF81zDR@cW8ecaSm>B8%)v{X1pQu|1dr*y9M&a(J`038}4>lK&K zIM~6wnX{XA?pFHz{hOmEq{oYBnB@56twXqEcFrFqvCy)sH9B{pQ`G50o{W^t&onwY z-l{ur<Ka?a_Vj#)=^e+nK%m4zzm%RZtDxs>4#8ylPV5YRLD%%j^d0&_WI>0nmfZ8! zaZ&vo@7D`!=?215+Vk181*U@^{U>VyoXh2F&ZNzZx5tDDtlLc)gi2=|o=GC`uaH;< zFuuF?Q9Q`>S#c(~2p|s49RA`3242`2P+)F)t2N!CIrcl^0#gN@MLRDQ2W4S#MXZJO z8<(9P>MvW;rf2qZ$6sHxCVIr0B-gP?G{5jEDn%W#{T#2_&eIjvlVqm8J$*8A#n`5r zs6PuC!JuZJ@<8cFbbP{cRnIZs>B`?`rPWWL*A?1C3QqGEG?*&!*S0|DgB~`vo_xIo z&n_Sa(>6<$P7%Py{R<>n6Jy?3W|mYYoxe5h^b6C#+UoKJ(zl?^WcBn#|7wMI5=?S# zRgk8l-J`oM%GV&jFc)9&h#9mAyowg^v%Fc-7_^ou5$*YvELa!1q>4tHfX7&PCGqW* zu8In~5`Q5qQvMdToE$w+RP^_cIS2xJjghjCTp6Z(za_D<$S;0Xjt?mAE8~Ym{)zfb zV62v9|59XOvR}wEpm~Cnhyr`=JfC$*o15k?T`3s-ZqF6Gy;Gm+_6H$%oJPywWA^Wl zzn$L=N%{VT8DkQba0|2LqGR#O2Pw!b%LV4#Ojcx<DkATQzZt2m)Z{XGHSSJVB)dEu z$k5uf0bru0;$A03ffmj4X4+w-#Ex!3zY<g3vy{Q-;>5`?Cm;+aLpkyZ=!r1z@E}V= z$2v6v%Ai)MMd`@IM&UD!%%(63VH8+m0Ebk<5Du#0=WeK(E<2~3@>8TceT$wy5F52n zRFtY>G9Gp~h#&R92{G{jLruZSNJ4)gN<n8RjXM9L<b|8XyoMl0^H+4(zB;w~SJ!kD zrVI|u0t_5@!H0jw+sQtegKy~|{2WS+${5Oz(JgLw!@`G#G?5)|&o4Ab&mtkFW6R;I zbIl_@SvfNAX(Na{b+@Q70a`Sk3lQIt*FDI<(O)!c#B&A(Q`95=aPuOdvOYD_Tbcm% z%D-4n{DMJ=hdY}r!%6RohhWRUg~J@(vFV$}5IJdXuC=~`w%u&<vo@A4ca>K+zg*$P zW@~Hf>_Do)tvfEAAMKE1nQ=8coTgog&S;wj(s?Xa0!r?UU5#2>18V#|tKvay1Ka53 zl$RxpMqrkv`Sv&#!_u8$8PMken`QL0_sD2)r&dZziefzSlAdKNKroVU;gRJE#o*}w zP_bO{F4g;|t!iroy^xf~(Q5qc8a3<+vBW%V<d`nS{lSj$4Nm}P5a}hnc(p%WzfvlG zT;H!5Z;n`VUd)l*N1r5XgtUc;QC!pff=V3Yc^2yBHlkn@&9nqcoHdJKJ=v^;^yV-f z<}BU(Bvrs_fCG)axqSM5flf2Ba{5fV)L3cPzWA?Q6se0a396m5Gr#_YQP8|uF0kH< zVB|z<#l1YCwIqxwN0n0`BRlP5TH;3I`~`BmZR!I&q>IOQ1!??d;yEn1at1wpt}*n- z0iQtfu}Isw4ZfH~8p~#RQU<wR$wNwXfz=BXCSL%flpWfABL6v7O5I*uK2pS}NYHvt zi`MA*@0*}k0)LtGV=asdz5UAs6ox*tjq2V>Kwf<$XeqUr-5?8TSqokdHL7tY|47R; z#d+4NS%Cqp>LQbvvAMIhcCX@|HozKXl)%*5o>P2ZegGuOerV&_MeA}|+o-3L!ZNJd z#1xB^(r!IfE~i>*5r{u;pIfCjhY^Oev$Y1MT16w8pJ0<E9%+ZY3k8rPYxm8wOPTy9 z@nZU~c*2|DKwp!jN;Um`8W><e2p}A{tG<hJX)A5!!YpV2>?9@&FH*`d;hS=c#F6fq z{mqsHd*xa;>Hg?j80MwZ%}anqc@&s&2v{vHQS68fueNi5Z(VD2eH>jmv4uvE|HEQm z^=b&?1R9?<@=kjtUfm*I!wPf5Xnma(4*DfPk}Es*H$%NGCIM1qt(LSvbl7&tV>e2$ zUqvZOTiwQyxDoxL(mn?n_x%Tre?L&!FYCOy0>o}#DTC3uSPnyGBv*}!<Y7tbCS^J_ z6*X7wjnZ%Q0s4^$g0<Mf0kC^>*Yv5IV)Bg_t%V+UrTXfr!Q8+eX}ANR*YLzwme7Rl z@q_*fP7wP2AZ(3WG*)4Z(q@)~c{Je&7?w^?&Wy3)v0{TvNQRGle9mIG>$M2TtQ(Vf z3*PV@1mX)}beRTPjoG#&&IO#Mn(DLGp}mn)_0e=9kXDewC8Pk@yo<8@XZjFP-_zic z{mocvT9Eo)H4Oj$>1->^#DbbiJn^M4?v7XbK>co+v=7g$hE{#HoG6ZEat!s~I<^_s zlFee93KDSbJKlv_+GPfC6P8b>(;dlJ5r9&Pc4kC2uR(0{Kjf+SMeUktef``iXD}8` zGufkM9*Sx4>+5WcK#Vqm$g#5z1DUhc_#gLGe4_icSzN5GKr|J&eB)LS;jTXWA$?(k zy?*%U9Q#Y88(blIlxrtKp6^jksNF>-K1?8=pmYAPj?qq}yO5L>_s8CAv=LQMe3J6? zOfWD>Kx_5A4jRoIU}&aICTgdYMqC|45}St;@0~7>Af+uK3vps9D!9qD)1;Y6Fz>4^ zR1X$s{QNZl7l%}Zwo2wXP+Cj-K|^wqZW?)s1WUw_APZLhH55g{wNW3liInD)WHh${ zOz&K>sB*4inVY3m)3z8w!yUz+CKF%_-s2KVr7DpwTUuZjPS9k-em^;>H4*?*B0Bg7 zLy2nfU=ac5N}x1+Tlq^lkNmB~Dj+t&l#fO&%|7~2iw*N!*xBy+ZBQ>#g_;I*+J{W* z=@*<AAG@ThQqLTS8LoW9hl8e8slgs|pH%Z@1|LXbEv=yEDaqvFtkgO0fm!oT;UD4I zgw!e(vKorcHj2>15><)Bh9f>>dgQrE<e-x!^l8zejAkt^^^`zlF;a1n;X-XLc~Fs% z=F|#T8rRX07v}A5%C@Bo>hkrr2FEJ;R2rH%`kda8sD-FY6e#7S-<)V*zQA>)Ps)L- zgUuu@5;Ych#jX_KZ+;qEJJbu{_Z9WSsLSo#XqLpCK$gFidk}gddW(9$v}iyGm_OoH ztn$pv81zROq686_7@avq2heXZnkRi4n(3{5jTDO?9iP%u8S4KEqGL?^uBeg(-ws#1 z9!!Y_2Q~D?gCL3MQZO!n$+Wy(Twr5AS3{F7ak2f)Bu0iG^k^x??0}b6l!>Vjp{e*F z8r*(Y?3ZDDoS1G?lz#J4`d9jAEc9YGq1LbpYoFl!W!(j8-33Ey)@yx+BVpDIVyvpZ zq5QgKy>P}LlV?Bgy@I)JvefCG)I69H1;q@{8E8Ytw^s-rC7m5>Q>ZO(`<rJD^N3)b zrY@XQ=`M~mXZ#s{XEHo_{Wul}Fs^7CdvbCX?LZ+OHC5%T;xFOXVwOJR8Lq}00$$<s z0m&M?Y3<bP7OrI_ENundw|clc`k>$`9@`49s2)q#{2eN0A?~qS8%wxh%P*99h*Sv` zW_z3<=iRZBQKaDsKw^TfN;6`mRck|6Yt&e$R~tMA0ix;qgw$n~fe=62aG2v0S`7mU zI}gR#W)f+Gn=e3mm*F^r^tcv&S`Rym`X`6K`i8g-a0!p|#69@Bl!*&)QJ9(E7ycxz z)5-m9v`~$N1zszFi^=m%vw}Y{ZyYub!-6^KIY@mwF|W+|t~bZ%@rifEZ-28I@s$C` z>E+k~R1JC-M>8iC_GR>V9f9+uL2wPRATL9bC(sxd;AMJ>v6c#PcG|Xx1N5^1>ISd0 z4%vf-SNOw+1%yQq1YP`>iqq>5Q590_pr?OxS|HbLjx=9~Y)QO37RihG%JrJ^=Nj>g zPTc<Z%(meLC3t3DA3mXspnPQXL*D!Ta65mfL8n5cTVeIXz1M&EvRvf~9Y&HGRe34j zC{Z<XTx+@;8#G)UDzJa=zNkJ)ZThO~AbC95=lEA9s93CKH~q`T0Lo^V<~2qE_P`rr zT8g<d&liKY6OZ@w#*&(eHNxz~{nnk+F?=TJnWu+d?Cct!$0t}FWu$tmDwPn{x}W3D z(#hW-J#P+zSREZaB(H<>O$6r{jdE_096b&L;W<UT0WXd-7EcYUKC#!}=R=zh^fQ!w zw^!4tduWEBa!eB6VD%8*Zm;lJUaOv3q&ftLM>m8vcxUVxF0mA%W`aZz4n6XtvOi($ zaL!{WUCh&{5ar=>u)!m<SP1r*2Q!B7!r%>it|&EkGY$|YG<_)ZD)I32uEIWwu`R-_ z<l-F2@T;+Rfp>`FVeKyrx3>8Ep#2~%VVrQ%u#exo!anPe`bc)-M=^IP1n1?L2UQ@# zpNjoq-0+XCfqXS!LwMgFvG$PkX}5^6yxW)6%`S8{r~BA2-c%-u5SE#%mQ~5JQ=o$c z%+qa0udVq9`|=2n=0k#M=yiEh_vp?(tB|{J{EhVLPM^<GU_9IW&W5r0EZfqfvqKJa zj$A!0V@^%^G*@LfCxnQBRsf!SFI>S@f-O*Lgb390BvwK7{wfdMKqUc0uIXKj5>g^z z#2`5^)>T73Eci+=E4n&jl42E@VYF2*UDiWLUOgF#p9`E4&-A#MJLUa&^hB@g7KL+n zr_bz+kfCcLIlAevILckIq~RCwh6dc5@%yN@#f3lh<g!DD;$~9!F?Umj0oq+-L;Pq3 zWBjyxUsn|F4v2<-tDya8_xD#3tf+Btl6xMKmQwU{uG^pCHy8%(g8{EzO=viuWMlpe zxaYI`vE-I~M7S(FL%W(!O9O@x5R%(RDcs<mY)UE+SKgn!vO!l5lVfKknb{^`9|ACm zFc>HIx4fZ_yT~o0#3@h#!HCN(rHHC6#0$+1AMq?bY~(3nn{o5g8{*e_#4RhW)xPmK zTYBEntuYd)`?`bzDksI9*MG$=^w!iiIcWg1lD&kM1NF@q<Uw8p<g_Dpnj9vN66UU6 z#Z3*p$ka?~sV+=@HS4)aShwh2%xUcFRzNG=CK_7wDr^y+Hym1XjM0Y)8#0I8xk*BJ z6~Y?ps>Kha0fDVz^W7JCam^!AQFxY@7*`a3tfBwN0uK_~YBQ18@^i%=YB}K0Iq(Q3 z=7hNZ#!N@YErE7{T|{kjVFZ+f9Hn($zih;f&q^wO)PJSF`K)|LdT>!^JLf=zXG>>G z15TmM=X`1%Ynk&dvu$Vic!XyFC(c=qM33v&SIl|p+z6Ah9(XQ0CWE^N-LgE#WF6Z+ zb_v`7^Rz8%KKg_@B>5*s-q*TVwu~MCRiXvVx&_3#r1<P_Vsg0r#|~)TS-_d=4M~cE z+&T48ska5zw)EmTXQm+ioQ#?!TAFgl6YGNnf^vvUGF8c#WveY-j?v>h&L+{rM&-H6 zrc<W1b?Kswwnc7D+{tF5OXqdbQIoE?`I?`AYOA|Nz_u97H4|;)Y(B#Jlx4%Vyq`C% z>gH@I>0eY8WBX#Qj}Vml+fpv?;EQXBbD0lx%L?E4)b-nvrmMQS^}p_CI3M24IK(f| zV?tWzkaJXH87MBz^HyVKT&oHB;A4DRhZy;fIC-TlvECK)nu4-3s7qJfF<RMe%2ki1 zTI6+Q&ku0Tf_}LhN9vYEpKLB63Apcx<A44C!(?Ku{@lPv1p=C*{NKQPqW?SoDrx8J zVrXOY|6`QKsKfYZo1*^sOJ;d{XYp>-ZZGt7+6C3xZt!ZX4`M{eN|q!y*d^B+cF5W- zc9C|FzL;$bAfh56fg&y0j!PF8mjBV!qA=z$=~r-orU-{0AcQUt4<urmeM_viOanZ> zNYC=_9(MOWe$Br9_50i#0z!*a1>U6ZvH>JYS9U$kkrCt7!mEUJR$W#Jt5vT?U&LCD zd@)kn%y|rkV|CijnZ((B2=j_rB;`b}F9+E1T46sg_aOPp+&*W~44r9t3AI}z)yUFJ z+}z5E6|oq+oPC3Jli)EPh9)o^B4KUYkk~AU9!g`OvC`a!#Q>JmDiMLTx>96<qgBn8 z5Yx>_iDD9h@nW%Je4%>URwY<khi%2<#7=1x6bKj`i+VNfqc83y4%c<DW8#bYi5YZb z$#9uBFd7dEOo$AJb4JZJO5H`_z^H7us>M%5YU1&Dcdulvv3IH3GSrA4$)QjlGwUt6 zsR6+PnyJ$1x{|R=ogz<jrS1DHwc3k9SyCRDme*{=6T#8t{oN}(u`b1y&NoUMw~k&i z-ZMT<e7mL5FWq(-nCv;nz!91AZl{NhC%CdljGG*{I`mQsTERle-US8eePrJIvi@(~ z7-9FHtjkeQ>Err~U|X!+b+F8=6y?Yi`E$yjWXsdmxZa^hIqa)YV9ubUqOj&IGY}bk zH4*DEn({py@MG5LQCI;J#6+98GaZYGW-K-&C`(r5#?R0Z){DlY8ZZk}lIi$xG}Q@2 z0LJhzuus-7dLAEpG1Lf+KOxn&NSwO{wn_~e0<P6hRP=HtV6GZO4BWR+u?s}P=mtR? z^s-q@iNL0$t&{z^w<8l8Gfidj9i;%JZjA&yE?EO$&aT3#)<VfKjT&xVy=ob6_fCQ1 z1ZANC@-v}}f_Ot^v6-^$=p`K1pzl0%@pT?@;VeuG3OCx<;!tLX(*FCgcF6%v6I-u+ zOtolW2R3pOY_+(+h`%+h#=|Jp1>=}dovX)T(|WRMTqacoW8;A>8tTDr+0yRa+U!LW z!H#Gnf^iCy$tTk3kBBC=r@xhskjf1}NOkEEM4*r+A4`yNAIjz`_JMUI#xTf$+{UA7 zpBO_aJkKz)iaKqRA{8a6AtpdUwtc#Y-hxtZnWz~i(sfj<Z|BkJ?5yNRyVr*CY(ck` zYBr4&*s>Mk`lq|kGea=`62V6y)TMPZw8q<PMu}{|F!lI=W@pt{Brl{lZ$Kvki;7jR zu5U<jQ;cdN982L5LwwYW4w)&epo>}tFDDHrW_n(Z84ZxWvRrntcw;F|Mv4ff9iaM% z4IM{=*zw}vIpbg=9%w&v`sA+a3UV@Rpn<6`c&5h+8a7izP>E@7CSsCv*AAvd-izwU z!sGJQ?fpCbt+LK`6m2Z3&cKtgcElAl){*m0b^0U#n<7?`8ktdIe#ytZTvaZy728o6 z3GDmw=vhh*U#hCo0gb9s#V5(IILXkw>(6a?BFdIb0%3~Y*5FiMh&JWHd2n(|y@?F8 zL$%!)uFu&n+1(6)oW6Hx*?{<Fve1i68O0|}VY@-CnZ2#qMDX4_TH5{a14Z!yY5Jyy zx~A7-X<-PE0WM<Tm|Nvc^ZEwz8GrqOWa`Z1*RZ}hIr1a1?laD~;emg18pAJ#9>d~y zBeR)N*Z{7*gMlhMOad#k4gf`37OzEJ&pH?h!Z4#mNNCfnDI@LbiU~&2Gd^q7<CQs0 z&asYoA!Bw(%<&`9zGMPFrBS@o$PG#iIU>ix8~Y6$a=B9bK(BaTEO0$Oh=VCkBPwt0 zf#QuB25&2!m7MWY5xV_~sf(0|Y*#Wf8+FQI(sl2wgdM5H7V{aH6|ntE+OcLsTC`u; zeyrlkJgzdIb5=n#SCH)+kjN)rYW7=rppN3Eb;q_^8Zi}6jtL@eZ2XO^w{mCwX(q!t ztM^`%`ndZ5c+2@?p>R*dDNeVk#v>rsn>vEo;cP2Ecp=@E>A#n0!jZACKZ1=D0`f|{ zZnF;Ocp;$j86m}Gt~N+Ch6CJo7+Wz<khC+niM3qr-iS&UBcHui{9XrK>v|nlsXBvm z?St-5Ke&6hbGAWoO!Z2Rd8ARJhOY|a1rm*sOif%Th`*<gwKLW?(Zk1#*ZOXQ`cojG zD13Ehmfi1VRcjC6^(x$Mr?4CrwnTiR=R5g=ptRC8<8eNz%nut#PS8c6u#;@$&2ey+ zdY<bNMhywpCa2S@h7Q3wbgCGuX_x#vX-yqzvPsMWe)TLqZo9uM5`ZDjRM95Ep@ZY3 z3!vbipe75C=xz+QTQ^*cq&P%8D{YFL0(rKe)l;OSVquh&DYX(RJ=S6F9Om4%x%qm8 z&MQBXRTf8OLdIIe4a>=^jlgWo%e9`3sS51n*>+Mh(9C7g@*mE|r%h*3k6I_uo;C!N z7CVMIX4kbA#gPZf_0%m18+BVeS4?D;U$QC`TT;X<fDeDKHK{v9^#caNvL$%M`~|e> zP#H}tMsa=zS6N7n#BA$Fy8#R7vOesiCLM@d1UO6Tsnwv^gb}Q9I}ZQLI?--C8ok&S z9Idy06+V(_aj?M78-*v<PSvKN>YBu|AaJ9mlEJpFEIP}{tRwm?G{ag>6u(ReBKAAx zDR6qe!3G88NQP$i99DZ~CW9lzz}iGynvGA4!yL}_9t`l*SZbEL-%N{n$%JgpDHJRn zvh<{AqR7z@ylV`kXdk+uEu-WWAt^=A4n(J=A1e8DpeLzAd;Nl#qlmp#KcHU!8`YJY zvBZy@>WiBZpx*wQ8JzKw?@k}8l99Wo&H>__<oxE+DvXhRO^f>vCFL}>m~MTmGvae% zPTn9?iR=@7NJ)?e+n-4kx$V#qS4tLpVUX*Je0@`f5LICdxLnph&Vjbxd*|+PbzS(l zBqqMlUeNoo8wL&_HKnM^8{iDI3IdzJAt32UupSr6XXh9KH2LjWD)Pz+`cmps%eHeD zU%i1SbPuSddp6?th;;DfUlxYnjRpd~i7vQ4V`cD%4+a9*!{+#QRBr5^Q$5Ec?gpju zv@dk9;G>d7QNEdRy}fgeA?i=~KFeibDtYffy)^OP?Ro~-X!onDpm+uGpe&6)*f@xJ zE1I3Qh}`1<7aFB@TS#}ee={<#9%1wOL%cuvOd($y4MC2?`1Nin=pVLXPkknn*0kx> z!9XHW${hYEV;r6F#iz7W=fg|a@GY0UG5>>9>$3Bj5@!N{nWDD`;JOdz_ZaZVVIUgH zo+<=+n8VGL*U%M|J$A~#ll__<`y+jL>bv;TpC!&|d=q%E2B|5p=)b-Q+ZrFO%+D_u z4%rc8BmOAO6{n(i(802yZW93?U;K^ZZlo0Gvs7B+<%}R;$%O}pe*Gi;!xP-M73W`k zXLv473Ex_VPcM-M^JO|H>KD;!sEGJ<HTW@*Usun3M)y1SZy-}aD>|E}Qepen;yNG2 zXqgD5sjQUDI(XLM+^8ZX1s_(X+PeyQ$Q5RukRt|Kwr-FSnW!^9?OG64UYX1^bU9d8 zJ}8K&UEYG+Je^cThf8W*^RqG07nSCm<CEe(KJqi=yo4Zu+%xm@?EsCwAe&T3j;YZ= z`fzz&jda9suA?ug-<)Lt|J!;C=m%2_6!M#s+o$=|h!UsUZze~j6B|oBnDcXoBo6s( znVOI7#2w)n`o&*71n0&}PmJ49=A^!uAEdr;5G1}y8xW=VO4p=PtZGRvI4Sg{DMqQq z%SIK&<Wa1Nqat-4s@X(z$m)__E$wOxmm~0!_GrS1d?bG*JLP%k;er00_>p*o5Z;#F zS?jochDWX@p+%CZ%dOKUl}q{9)^U@}qkQtA3zBF)`I&zyIKgb{mv)KtZ}?_h{r#VZ z%C+hwv&nB?we0^H+H`OKGw-&8FaF;=ei!tAclS5Q?qH9J$nt+YxdKkbRFLnWvn7GH zezC6<{mK0dd763JlLFqy&Oe|7UXII;K&2pye~yG4jldY~N;M9&rX}m76NsP=R#FEw zt(9h+=m9^zfl=6pH*D;JP~OVgbJkXh(+2MO_^;%F{V@pc2nGn~=U)Qx|JEV-e=vXk zPxA2J<9~IH{}29#X~KW$(1reJv}lc4_1JF31gdev>!CddVhf_62nsr6%w)?IWxz}{ z(}~~@w>c07!r=FZA<wFaiohRbKb~^?3q5?_zk?fqI0MHaAe;iY+em}3rG(ta;5O`r z;1)QPwN9vHyE)(@T!k}>Nq4R!F2Qi2?QGavZ{)PCq~X}3x;4ylsd&m;dQe;0GFSn5 zZ*J<=Xg1<rmtct^RD?`a5gOMC4L)d>fEGYYDZ0{Z4}Jh*xlXa}@412nlKSM#@wjMM z*0(k>Gfd1Mj)smUuX}EM6m)811%n5zzr}T?$ZzH~*3b`3q3gHSpA<3cbzTeRDi`SA zT{O)l3%bH(CN<IN>0EEF9ph1(Osw5y$SJolG&Db~uL!I3U{X`h(h%^KsL71`2B1Yn z7(xI+Fk?|xS_Y5)x?oqk$xmjG@_+JdErI(q95~UBTvOXTQaJs?lgrC6Wa@d0%O0cC zzvslIeWMo0|C0(<f+k5>{iEWX{=5F)t4Z*`rh@-t0ZTMse3VaJ`5`1zeUK0~F^KRY zj2z-gr%sR<(u0@SNEp%Lj38AB2v-+cd<8pKdtRU&8t3eYH#h7qH%bvKup4cnnrN>l z!5fve)~Y5_U9US`uXDFoOtx2gI&Z!t&VPIoqiv>&H(&1;J9b}kZhcO<PyO-o^uK1x z>X7EiW*Bujy#MaCl52%NO-l|<wz{;LglcbSGr9RqPoL*nYEN|Murl0Ya0<J_(ZpWZ zF)>@2$aRKvZ!YjwpXwC#nA(tJtd1p?jx&U|?&jcb!0MT6oBlWurVRyiSCX?sN3j}d zh3==XK$^*8#zr+U^wk(UkF}bta4bKVgr`elH^az{w(m}3%23;y7dsEnH*pp{HW$Uk zV9J^I9ea7vp_A}0F8qF{>|rj`CeHZ?lf%HImvEJF<@7cgc1Tw%vAUA47{Qe(sP^5M zT=z<~l%*ZjJvObcWtlN?0$b%NdAj&l`Cr|x((dFs-njsj9%IIqoN|Q?tYtJYlRNIu zY(LtC-F14)Og*_V@gjGH^tLV4uN?f^#=dscCFV~a`r8_o?$gj3HrSk=YK2k^UW)sJ z&=a&&JkMkWshp0sto$c6j8f$J!Bsn*MT<h8dS6cWTC2@)2)r~Q6P<?JMO=z=v6=h0 z{z0O{ZSMEdl||RciL2=bIRol$EQX%GoV#vmsfKn64QmInOxq%^Q3!={`}-O}OF!W# z=Hj!CX?@sGbF3Dtmb5z~EA>jC`3cv@l@7cINa!}fNcu(0XF7ZCAYbX|WJIL$iGx8l zGFFQsw}x|i!jOZIaP{@sw0BrV5Z5u!TGe@JGTzvH$}55Gf<;rieZlz+6E1}z_o3m2 z(t;Cp^Geen7iSt)ZVtC`+tzuv^<6--M`^5JXBeeLXV)>2;f7=l%(-4?+<5~;@<fp) z1Lui?ARVsm?nP~!ne9-FRx3JSEwwC5O{HygKy6`yWh?gVhS?YcW4+v5JWTeVDAmjv zCOtdeHV1%x2dOX@vq0y;J^p<!(r|O)vi|(<nvMWYjpI;<j^T#vi*<7po`Kd6FA;^r zmyETseWV1c90=BR0ZP&?D?U4l#rsfm+~24-c!J7PR{eD=x@cqZ#~<}g+~EX)E|2a$ z+gi~<mvHzfsze~C6NT^{GLC>=Th{1#>rK3+rLn(44TAFS@u(}dunUSYu}~))W*fr` zkBL}3k_@a4pXJ#u*_N|e#1gTqxE&WPsfDa=`@LL?PRR()9^HxG?~^SNmeO#^-5tMw zeGEW&CuX(Uz#-wZOEt8MmF}hQc%14L)0=ebo`e$$G6nVrb)afh!>+Nfa5P<oZ7>;N zCCOQ^NRel#saUVt$Ds0rGd%gkKP2LsQRxq6)g*`-r(FGM!Q51c|9lk!ha8Um3ys1{ zWpT7XDWYshQ{_F!8D8@3hvXhQDw;GlkUOzni&T1>^uD){WH3wRONgjh$u4u7?+$(Y zqTXEF>1aPNZCXP0nJ;z<N&&~t`L3v?GV)58KGTHHGL!swTJXxH{~NMLx(L72U7AvS zcP}RNT->s6_%6;+D&J_|ugcih**y(4ApT`RKAi5>SZe0Bz|+l7z>P14>0ljIH*LhK z@}2O#{?1RNa&!~sEPBvIkm-u<y&MCPHyI+!uRA$A&rl2a>It^Pt#%JnsbJ`-T0%pb ze}d;dzJFu7oQ=i`VHNt%Sv@?7$*oO`Rt*bRNhXh{FArB`9#f%ksG%q?Z`_<19;dBW z5pIoIo-JIK9N$IE1)g8@+4}_`sE7;Lus&WNAJ^H&=4rGjeAJP%Dw!tn*koQ&PrNZw zY88=H7qpHz11f}oTD!0lWO>pMI;i4sa<gbCHb*?!TW%nQ=Crc6PM8jDTh%vfNUoN9 z<Dyk7#UrltDltZCanZAJp~$Uj3z%^}HyR>uS`%_!zM!n@91sLH#rz1~iEAu#1b%LA zhB}7{<u6opdJcy2km#)#Y#n?t1euj>1(8{1{V8+SEs=*f=FcR<FV0_Ap!<#zSZ}~< zN7Q;-uIX)e5`ftQ>E^;`6Pxm$Hie~|aD~W1BYy#@Y$C?pxJh*cC!T@8C9{xx*T*8P zhbkRk3*6)Zbk%}u>^?ItOhxdmX$j9KyoxxN>NrYGKMkLF4*fLsL_PRjHNNHCyaUHN z7W8yEhf&ag07fc9FD>B{t0#Civsoy0hvVepDREX(NK1LbK0n*>UJp&1FygZMg7T^G z(02BS)g#qMOI{RJIh7}pGNS8WhSH@kG+4n=(8j<+gVfTur)s*hYus70A<L}puU}Lb zu200ys|`>HUBS2bN6Zp_GOHYxsbg{-Rcet{@0gzE`t$M0_!ZIqSAIW53j+Ln7N~8J zLZ0DOUjp^j`MvX#hq5dFixo^1szoQ=FTqa|@m>9F@%>7OuF9&_C_MDco&<yl?^CH) z_{m)+n(GUp{jz&DgTPmM1Ie32W;fO2o&4S0WHZRaK}sd;OrQE#_U&x0+&FI~40PuQ ze#9WlNf2()A6n%*=)0;D=cW$&=;s%|mjn+596d9azJX@ws^_agA9S@SqCb%5)Pt1$ zTuDQ#W)9rV*dI`OL>-{wfLKNrDMEN4pRUS8-SD6@GP`>_7$;r>dJo>KbeXm>GfQS? zjFS+Y6^%pDCaI0?9(z^ELsAE1`WhbhNv5DJ$Y<V<y8)GDQRyg3oc8D}R=a~^=C+bR zA8dliBl?zMD&C-Y1@r5^4sc0o&y-Oly%>}~r;>FynHjmjmA{bfDbseZXsKUv<S~ds z>`%Fekv)1@f%7ti;B5hhs}5db1dP+P0${1DgKtb(DvN}6H6;0*LP6blg*rpr;Z(7? zrve>M`x6ZI(wtQc4%lO?v5vr{0iTPl&JT!@k-7qUN8b$O9YuItu7zrQ*$?xJIN#~b z#@z|*5z&D7g5>!o(^v+3N?JnJns5O2W4EkF>re*q1uVjgT#6ROP5>Ho)XTJoHDNRC zuLC(Cd_ZM?FAFPoMw;3FM4Ln0=!+vgTYBx2TdXpM@EhDCorzTS6@2`swp4J^9C0)U zq?)H8)=D;i+H`EVYge>kPy8d*AxKl};iumYu^UeM+e_3>O+LY`D4?pD%;Vextj!(; zomJ(u+dR(0m>+-61HTV7!>03vqozyo@uY@Zh^KrW`w7^ENCYh86_P2VC|4}(ilMBe zwa&B|1a7%Qkd>d14}2*_yYr@8-N}^&?LfSwr)C~UUHr)ydENu=?ZHkvoLS~xTiBH= zD%A=OdoC+10l7@rXif~Z#^AvW+4M-(KQBj=Nhgts)>xmA--IJf1jSZF6>@Ns&nmv} zXRk`|`@P5_9W4O-SI|f^DCZ-n*yX@2gf6N)epc~lRWl7QgCyXdx|zr^gy>q`Vwn^y z&r3_zS}N=HmrVtTZhAQS`3$kBmVZDqr4+o(oNok?tqel9kn3;uUerFRti=k+&W{bb zT{ZtEf51Qf+|Jc*@(nyn#U+nr1SFpu4(I7<1a=)M_yPUAcKVF+(vK!|DTL2;P)yG~ zrI*7V)wN_92cM)j`PtAOFz_dO)jIfTeawh2{d@x0nd^#?pDkBTBzr0Oxgmvjt`U^$ zcTPl=iwuen=;7ExMVh7LLFSKUrTi<KY<!-61)q_{3{un*!3+ioAJ}ikykUEszqLUz z2y?(ZGd?cRqh9pYpRi`+24AatY4$_e?EUKUn3Jh7T4ApDTj(45gg+&t`;?Q{T~cbD zn|bNQZR|89v%#GpNPQYtE?(B#%uDIfpgsUsQ7<Fll~M$jRoZq6vmY&{1Nwz^qA#Go zc|+flUXyLCb2t)u-mzSXfB*oT%i$GD5BYWsfIs$wF8Vdij$+{>PJpMB&*Ml32>wl} zYn(H0N4+>MCrm2BC4p{meYPafDEX<uu8*GYOdb||1L86<D25;RK8@zd2kY<K`lVFV zWxW7%O)+izx>d4yf$i%ylWpC|9%R4XZBUQih<i`-uBppkqY;Qs*4ob$&^Iv0MXueR zs^9GZt9u)s2Cv^Z+@fi83jHq!9bj``t`2%W4X`>a(x%w<wBlpV>gQ5iJ?K_wQBRfw z+pYuKoIameAWV7Ex4$PCd>bYD7)A9J`ri&bwTRN*w~7DR0EeLXW|I2()Zkl6vxiw? zFBX){0zT@w_4YUT4~@TXa;nPb^Tu$DJ=vluc~9)mZ}uHd#4*V_eS7)^eZ9oI%Wws_ z`;97^W|?_Z6xHSsE!3EKHPN<3IZ^jTJW=Il{rMmlnR#OuoE6dqOO1KOMpW84Z<G}M zeQ$nWk@-Y@mRFFq;S1oSSbG(l@Q(aR3<%_F<)_uOg^z>tDHNn)(pYvs=frO`$X}sY zKY0At$G85&2>B|-{*+B*aqQn&Mqjt*DVH2kdwE<Y_7iHmg2Cm#(Sh<4J6@f<d1{0_ z2^3BA&qWOWztYY+Dypt+<A6#?mxDA)NDd$fk`6d@DK+ANbl1=*APv$f-5{MJAl-w2 zf`Uj$ONmlaBIq~c^Smzu4-fLL?_O&bi}~Ze&OUq2K4;(i?CV$8RrU!hsiuTc?&as1 z$PLg}c#@!R^fMP&Bo&)b(J0Hj)VzLLO?2JCM;a9lb|SKw_bcf&<Y?auTw*?8j}mKc zh;zbPoG-a*lTJF;cYTd>m5f}~Xwn9+tPt?EPwh8=8=VWA8rjt*bHEs1FJ92QohQ)Y z4sQH~AzB5!Pisyf?pVa0?L4gthx2;SKlrr?XRU`?Y>RJgUeJn!az#sNF7oDbzksrD zw8)f=f1t*UK&$}_ktf!yf4Rjt{56ffTA{A=9n})E7~iXaQkE+%GW4zqbmlYF(|hE@ z421q9`UQf$uA5y<hO3<CDipt9*4<dYT6T>DLx67`=EnS<JRni<euaZulyr%vyhnlr z#?Eu%Cbt&$Qh2GVuhims!t(sZtTn6DH+khMm(wy>TxdEaG!6C%9_obpb?;u-^QFX% zU1wQ}Li{PeT^fS;&S<Y5`Q3*lDsv9CPMdV}m~xen5jZ}thFa&>k2#$ZM#<B;v8g#V zrswx2FBXZ(;R=Gq-stwS$#c?AI-?_}zv5!~CV2?X(<s$x(_gxir@sm|Cja!_@{6`W zQl|YUi5DeUC0^oOBKvUvK18FLFqV>Zpxrn7jsd<@qhfWy*H)cw9q!I9!fDOCw~4zg zbW`EHsTp9IQUCETUse)!ZmuRICx}0Oe1KVoqdK+u>67A8v`*X*!*_i5`_<c9{Noqv zpU!p<<G8iqQns&0K%<D)4OON5-!m?A%hk(FPQ+Q?ws_ccLu7=PI@ag2GOfVp`$hQj z3;P~3wbX%$?}k-KCY{_e``4|)XjLi70dV={`^!vOAo$+G9c(WLP8o?{9YHP}4$KUz z(G1HPLl11DLU0Dcu^>qTzYRkbYXg#4vT5~A{lK#bA}Oc4ePu5hr-@;i%Z!4Y;-(yR z(1rHYTc7i1h1aipP4DaIY3g2kF#MX{XW7g&zL!39ohO98=eo5nZtq+nz}2E$OZpxx z&OFaOM1O;?mxq+`%k>YS<Yu?md-1GMIyZf&AQWvPmo6CZVe@@DU-|T6jR$5=yrKb4 zb&a8G6}6XioJBsL5hN?i*Dbi)&%CK4?m};2MCujIboR+QjHGiTDJfq5RGO0R9CX)u z0zU4#8R^dZ{jzr_AyfBOUorP{&S*A_6&UYnFI3&tm>!-=H7BB&WhqSTUC{S!x*k9E zcB;u0I!h%3nEchQwu1GnNkaQxuWnW0D@Xq5j@5WE@E(<QNfqn|w8mRlTQ7sX*U5L5 zX1c+-14vB<S>WlgDU;FLsT*eV|Bh)aH0;~@^yygFj<=+Vu3p)LlF%1AA%y5z-Oh`2 z$RDKk_6r+f#I`8fQ%y#Wx%~de1qkWL2(q^~veLKwht-dIcpt(@lc>`~@mISRIPKPm zD!Za&aX@7dy*CT!&Z7JC1jP2@8+ro8SmlH>_gzRte%ojgiwfd?TR+%Ny0`sp`QRLy zl5TiQkFh<S=sKi}DbZK?W%4)lIIs>IC!2aaJ&=Ua`c9UuOk9GkSFZ}!IGeMZ5MXrL zGtMj`m{(<sAcQ4XR^(Yx=+F5D_F|kGh4WcL`ge_pig{Vz@@q-k5QqEE>X9+l%=d|L zW2OY?8!_pyhvJ1@O!Chsf6}@3HmKq@)x;CFItPMpkSr@npO&8zMc_O?*|sqkuL^U? zV9+x3vbr|6;Ft0J^J>IH_xpa<{S5K?u-sQWC7FB9YFMwoCKK3<ooKkM@8CB4tWkc& zbMUGaZ4+o`OF+ekbFK0Bi13*;T8t4<3_}*h{=Fc^ee#H)>WZ*gvO-wAApF`K%#7@1 z^sEj4*%hH`f0@sRDGI|#Dl20o$Z*gttP$q(_?#~2!H9(!d=)I93-3)?e<kCJHws!1 z?TUS>%@$1^*F=t9t&OQ9!p84Z`+y<$yQ9wlamK~Hz2CRpS8dWJfBl@(M2qX!9d_F= zd|4A&U~8dX^M25wyC7$Swa22$G61V;fl{%Q4Lh!t_#=SP(sr_pvQ=wqOi`R)do~QX zk*_gsy75$xoi5XE&h7;-xVECk;DLoO0lJ3|6(Ba~ezi73_SYdCZPItS5MKaGE_1My zdQpx?h&RuoQ7I=UY{2Qf<WTgMg!V?k)r-qf)mjply2B4{@!80S6L@j%-&~1;m<Mv> ziGQ-FpR%piffR_4X{74~>Q!=i`)J@T415!{8e`AXy`J#ZK)5WWm3oH?x1PVvcAqE@ zWI|DEUgxyN({@Y99vCJVwiGyx@9)y2jNg`R{$s2o;`4!^6nDX_pb~fTuzf>ZoPV@X zXKe1ehcZ+3dxCB+vikgKz8pvH?>ZzlOEObd{(-aWY;F0XIbuIjSA+!%TNy87a>BoX zsae$}Fcw&+)z@n{Fvzo;SkAw0U*}?unSO)^-+sbpNRjD8&qyfp%GNH;YKdHlz^)4( z;n%`#2Pw&DPA8tc)R9FW7EBR3?GDWhf@0(u3G4ijQV;{qp3B)`Fd}kMV}gB2U%4Sy z3x>YU&`V^PU$xWc4J!OG{Jglti@E3rdYo62K31iu!BU&pdo}S66Ctq{NB<88P92Y9 zTOqX$h6HH_8fKH(I>MEJZl1_2GB~xI+!|BLvN;CnQrjHuh?grzUO7h;1AbzLi|_O= z2S=(0tX#nBjN92gRsv;7`rDCATA!o(ZA}6)+;g;T#+1~HXGFD1@3D#|Ky9!E@)u=h z3@zg3Us0BCYmq(pB`^QTp|RB9!lX*{;7r|Z(^>J+av(0-oUmIdR78c4(q%hP#=R@W ze{;yy$T^8kXr(oC*#NQMZSQlgU)aa=BrZDwpLUk5tm&(AkNt&Gel`=ydcL*<@Ypx{ z2uOxl>2vSY2g3%Si&JU<9D5#{_z{9PzJh=miNH;STk^;5#%8iMRfPe#G~T>^U_zt? zgSE)`UQhb!G$at%yCf5MU)<&(L73(hY3*%qqPbX;`%QDHed3ZaWw^k)8Vjd#ePg<i zcp5jVnE)b@51=ikxwz)bMOpsO;};uPB3dwwQb3K)6V1vE)dkj`sik^TzenJqS*D^y zgw2x@0s;B&1HiwmZ~VP26=BY3Y-ZwUr-w9aJXRieNAMmI&U<i^jQ+df?=BH#v)Ki@ zd*03PoC8I$#Gdb{^!AE~u&QgIg{~&nS;+EjfcEhk``bI)0Ul`LF|aD<+#FHMXau3{ zmyMIN@y>@;I&pMe+A18k+S+bou|QX?8eQ`{P-0vrm=uR;Y(bHV>d>Gen4LHILqcm_ z3peDMRE3JMA8wWgPkSthI^K<|8aal38qvIcEgL<!9d48_9(GR4^MhM(vJ|52p_y_O z-SJ$7ByWZitf#aD(-IW>jHAFB0P#IfqP2y}L>=8eBR}Fm^V*mw2Q4+o=exP@*#=Zs zIqHh@neG)Vy%v4cB1!L}w9J>IqAo}CsqbFPrUVc@;~Ld7t_2IIG=15mT7Itrjq#2~ zq<N^#v=@%=&M%|x1ULBCT7f|hQVQ#o?%1XMnY$$#3{&nv&0>X*&nwZP>vso$6W!#` z-YZ}jhBwQku-Qc>TIMpn%_z~`^u4v3Skyf)<h26Xm+@qv*!BTf&uZux3OH{&_Yv6F zjXaOTDs^(_X7i-8-U1PZ5HC8*b?lhzPL-f}lh*@pHE+;jbL+ZhqJgkss~Ko|6rU!p zVw}Ug?pzYfMOLRH+{j9|33K;uPIu6@A=kZj$(emVeVUmz%+Y*SIwik2sA{3iSbD7T z@z|AHO^y?MK_OJPT@E6|VWSHIT38zGTAg7KA0jE8>KA}V{`dr!Q;3x<!|BZNGP06J z!})YPd1l2)l)w1qu3OGp_}mnU13VCHq@N(!#BL%~WFM}YtU@0n7`~J=SvmZ$612JY zY}y%D+N@WuUy2kC&&{3GV|2?!k6dfO46(QIeiWTyT86Hgig~*U<Ch;jCQKMaQM*Ri zpA>K1TuGYdl}$sKF^9X!*a-R*Oq1#tLq!W)gO}{q`1HM;oh1-k4FU@8W(qe>P05$+ z`ud2&;4IW4vq8#2yA{G>OH=G+pS_jctJ*BqD$j-MI#avR+<>m-`H1@{3VgKYn2_Ih z0`2_1qUMRuzgj_V^*;5Ax_0s{_3tYR>|$i#c!F7)#`oVGmsD*M2?%930cBSI4Mj>P zTm&JmUrvDXlB%zeA_7$&ogjGK3>SOlV$ct{4)P0k)Kua%*fx9?)_fkvz<(G=F`KCp zE`0j*=FzH$^Y@iUI}MM2Hf#Yr@oQdlJMB5xe0$aGNk%tgex;0)NEuVYtLEvOt{}ti zL`o$K9HnnUnl*;DTGTNiwr&ydfDp@3Y)g5$pcY9l1-9g;yn6SBr_S9MV8Xl+RWgwb zXL%kZLE4#4rUO(Pj484!=`jy74tQxD0Zg>99vvQ}R$7~GW)-0DVJR@$5}drsp3IQG zlrJL}M{+SdWbrO@+g2BY^a}0VdQtuoml`jJ2s6GsG5D@(<cgPph;^-s;xpb_sl;c! z`2I{ZRZ2rKu`+#w`%eDfFL1(_+@w{9uIMXJzK1C)cC-5XhmFjdJ$J0AeVu{!qN~7C ztXoC%fqAJLH9pp5w$D@q4|(WtMQt<uBX$;F`+;c(GdppC^RGeVPhF-vsn=ih;u6jW zm6GF4%m_juV9>^$5pMi3$27psEIOe^n=<va#F%To3t%){5yLqKe^;S6k~-{X7FZ5` z8C8uLS+^b!l95lWbWj$NdkSG>*Nj|Ug7VXN0OrwMrRq&@sR&vdnsRlI%*$vfmJ~)s z^?lstAT$Ked`b&UZ@A6I<(uCHGZ9pLqNhD_g-kj*Sa#0%(=8j}4zd;@!o;#vJ+Bsd z4&K4RIP>6It9Ir)ey?M6Gi6@JzKNg;=jM=$)gs2#u_WhvuTRwm1x2^*!e%l&j02xz zYInQgI$_V7Epzf3*BU~gos}|EurFj8l}hsI(!5yX!~ECL%cnYMS-e<`AKDL%(G)62 zPU;uF1(~(YbH2444JGh58c<L!e)x87c-46Lp>oXT>(*CdEwaFuyvB|%CULgVQesH$ znB`vk3BMP<-QauWOZ0W6xB5y7?tE5cisG|V;bhY^8+*BH1T0ZLbn&gi12|a9Oa%;I zxvaxX_xe3<zJ5_;M)%eUc$b1qh*#3cy)NFgC88^2+a(k+Yl_LMWaIPd<}RY|!D0d{ z$uOrm$<_CFd@uE5uyxO5sHA5PAtZehPrhIp9e0Nsutu7#eGO!z!OxmFo&`&VCBFZL zmvMu$ka54jcn_SlzEGRg)E{&pt1bUyd5FSM(K?xHX-(;lwoBxm=G}pTsCynZ)GP5G z>@ng%;4C?zPHQ1v%dbhjA6Sl7w<*)Nr#F{Ahzj}%n9c&!g5HVrlvUO&R2C)_$x6M9 zahficAbeHL2%jILO>Pq&RPPxl;i{K5#O*Yt15AORTCvkjNfJ)LrN4K{sY7>tGuTQ@ z^?N*+xssG&sfp0c$^vV*H)U1O!fTHk8;Q7@42MT@z6UTd^&DKSxVcC-1OLjl7m63& zBb&goU!hes(GF^yc!107bkV6Pr%;A-WWd@DK2;&=zyiK*0i^0@f?fh2c)4&DRSjrI zk!W^=<E?~bQ>l^JKlPW9US{*yo?_XT@T2Bx+Cm^+r{*5LVcKVw*ll3+)lkebA-4)o z8f5xHWOx0!FDSs4nv@o@>mxTQrOeKzj@5uL`d>mXSp|#{FE54EE_!KtQNq>-G(&5) ztz?xkqPU16A-8@-quJ|SU^ClZ?bJ2kCJPB|6L>NTDYBprw$Wcw<Y;;ldx=&gJa}4H z@Wwakn*Q^&RVtHa47by$I4sxs2Xr6hO|}|b8g;8P+cdPU{P00GD^=yOpI@GzPh+l` zi(s|O;0{OV%*#9PT6u8IaQp6YbA~_!T`w03A?yq_T&YSRnqY&$9SIkVQol~v{2NC( zPEQSJOOmN%HRmJS_NUT3hVmC!EL}-VEM1@e^gDltyerz9=+0e`-3a5G4k0SZ7Fa!1 z#ag*v`7$GXC1L{lPUrk^`@3^20bjuUD_37Kxt!~92XMGK0w&T|F$%LSOP_R^>CH{B z5qlJ6wK_9sT@Kl6G|Q&$gsl@WT>hE;nDAbH#%f1ZwuOkvWLj{qV$m3LF423&l!^iV zhym*>R>Yyens++~6F5+uZQTCz9t~PEW+e?w)XF2g!^^%6k?@Jcu;MG0FG9!T+Gx{Z z<gaMF{iLoiR26S<6~t-k;EsdU7e_zysFg2SI^5;A;*}V9MU-Fs%r-t{&pmIK5IGAc zzNfdSinv>K;31y@(J{!-$k4E{5#Sv(2DGy3EZQY}G_*z*G&CZ_J?m&Fg4IBrvPx1w z1zAb3k}6nT?E)HNCi%}aR^?)%w-DcpBR*tD(r_c{QU6V&2vU-j0;{TVDN6los%YJZ z5C(*ZE#kv-Bvl<Em5rSV(B!w_4$#2T42Z%3LIBAftq?Y(2w!<4+Y_EtkGH%njwHbv zaUXw<csfQ_AP(a;(P=s-f<2BWH_U9H*Fq$(LKHrb*ong+Bt0$pUwAi0kTJsL`Y$2- zV-MWNm4at^033)WXd{RvNQ(Pm3?N=<`uEfIw~~aBv5g(Vg5S>GLDf<J@6-7QNmQgf zlDvHwc9+i}DSsA3<MC#qa=?!^vxEK&nrA`RAD2YsB_D03@6|I%{?&b;({ba+HBphg zND}j5^f8}V^RKQ&c%?fS{h=pOQLIOQrc>9>EO#RH_jtolA)iRJ>tSfJpF!#DO+tk% zBAKCwVZwO^p)(Rhk2en$XLfWjQQ`ix>K}Ru6-sn8Ih6k&$$y`zQ}}4dj~o@9gX9_= z#<!b)PJX7r5EUA7^jB6Od_>~EkchJqd5$**l}~~6mOl(q#GMIcFg&XCKO;$w>!K14 zko1egAORiG{r|8qj*FsN>?7d`han?*MD#xe^)sOqj;o;hgdaVnBH$BM{_73?znS+R z*G2VHM!Jw6#<<Msx_|T}KQ4vp{)aSZJ`7HUQ>FfJ-J%-9AuDW$@mc-Eyk~F{Jbvt` zn;(%DbBDnKIYr~|I>ZTvbH@cxUyw%bp*)OSs}lwO^HTJ2M#u5QsPF0?Jv*OVPfdKv z+t$Z5P!~jzZ~Y!d#iP?S{?M_g%Ua0Q)WawbIx+2uYpcf(7Im%W=rAu4dSceo7RZh# zN38=RmwOJQE$qbPXIuO^E`wSeJKCx3Q76irp~QS#19dusEVCWPrKhK9{7cbIMg9U} TZiJi*F`$tkW<p)b$p8Kiq>Ln) literal 63375 zcmb5VV{~QRw)Y#`wrv{~+qP{x72B%VwzFc}c2cp;N~)5ZbDrJayPv(!dGEd-##*zr z)#n-$y^sH|_dchh3@8{H5D*j;5D<{i*8l<n`R`94An31eIWbisdMSBvMo=KdzZu#! z2=IUVG7$V4U%UUmhH^skQsQDNstj`C4{}qJvNH4x^YAkCG&57PP0CD5tUr(Lr|8F| zrsbw-rRacR&cjU84vV#^0hr{ahs87@nB*8}#Ta+ach127GUL}I|L4%azP25lE&lDO z{@DihA2t@wMy9rA|5sDgzngkE8#y|fIse-(VW+DelrTU*`j|jKH2?E168}A!#$SIR zXJlp1U}9_J;*z5Y>5IFJ|DjL!e)upfGNX(kojugZ3I`oH1PvW`wFW_ske0j@lB9bX zO;2)`y+|!@X(fZ1<2n!Qx*)_^Ai@Cv-dF&(vnudG?0CsddG_&Wtae(n|K59ew)6St z#dj7_(Cfwzh$H$5M!$UDd8=4>IQsD3xV=lXUq($;(h*$0^yd+b{qq63f0r_de#!o_ zXDngc>zy`uor)4A^2M#U*DC~i+dc<)Tb1Tv&~Ev@oM)5iJ4Sn#8iRw16XXuV50BS7 zdBL5Mefch(&^{luE{*<o)$0CtHMXCiFaqU;N{t<$9@JbXquVr@cf{y~BNB(J5=Tji zlK?_g|E;1zl$VJ=#ZmElT~Y6jy-|?2PUv}kl<0irKUHY7@2t={_gVdY)lv8kM+ad9 zC<O%>5qtCZk$oFr3<io|2$Itc(&(T+V0vhN)K$Fl^c3u8y`}{@R7L#c1&Qu_+u$L| zkw6sZeUEd0xxV1r@X7Bj^XUCX<ecNL?GSk}zL!>RH=H!c3wGR=HJ(yKc_re_X9pD` zJ;uxPzUfVpgU>DSq?J;I@a+10l0ONXPcDkiYcihREt5~T<to{?YLB3#Ek~Bd_FRTK z3SVU)NWfW~bevBhSgga`J`3XaEJ;UR&tR-QNI#e+fX1mkLg(kYRIlBUeP!g)rVvkV zmBQF>5Gb}sT0+6Q;AWHl`<y=xe2MOa)>S5dV>lv%-p9l#xNNy7ZCr%cyqHY%TZ8Q4 zbp&#ov1*$#grNG#1vgfFOLJCaNG@K|2!W&HSh@3@Y%T?<RDDZ2kvE4KZX_tTk{8@Y z+1Qu}v&0qF!3ps~B5R6-#N&o4vQEcX3!~lWKK-JjRoUbPQR)>3YI75bJp!VP*$*!< z;(ffNS_;@RJ`=c7yX04!u3JP*<8jeqLHVJu#WV&v6wA!OYJS4h<_}^QI&97-;=ojW zQ-1t)7wnxG*5I%U4)9$wlv5Fr;cIizft@&N+3<m!sp`}{5>2O%B{R1POm$oap@&f| zh+5J{>U6ftv|vAeKGc|zC=kO(+l7_cLpV}-D#oUltScw})N>~JOZLU_0{Ka2e1evz z{^a*ZrLr+JUj;)K&u2CoCAXLC2=fVScI(m_p~0FmF>>&3DHziouln?;sxW`NB}cSX z8?I<poVWwH93~xX>sJB)Z=aYRz!X=yJn$kyOWK%rCYf-YarNqKzmWu$ZvkP12b4qH z<cj_@_^h^p^q&$rHm}tFrF$o@p+N@Luju~MbeZxq_WbMvMAonH{#8FcaQx#1Ex963 zthr*D;hp#t`U%;8Lw{en#r&PBH>hS9Q>j<}(*frr?z<%9hl*i^#@*O2q<G8@m-E{I z`}pP(W$_?tQz?qiq)AkeSb{O1HEI<O&IPY2fz^)h2U5WFf)$o|GVN9!>(Z^CN)c2c z>1B~D;@YpG?G!Yk+*yn4vM4sO-_!&m6+`k|3zd;8DJnxsBYtI;W3We+FN@|tQ5EW= z!VU>jtim0Mw#iaT8t_<+qKIEB-WwE04lBd%Letbml9N!?SLrEG$nmn7&W(W`VB@5S zaY=s<l}}fvx=2PUlRXVFqYw_pix_=MLAKV-vfffnNa-G}V}-DjqeGu81{_6c7DT4* zgNTK&HNdPkT}|m;Wopt-pwH(=vK!Mcs#L3p7EuhKtdS*$(gi7K6)2mt;vO}}@U2?@ zic8*RBj6lGpirRD%IH>Ew2}i@F_1P4OtEw?xj4@D6>_e=m=797#hg}f*l^`AB|Y0# z9=)o|%TZFCY$SzgSjS|8AI<m~)~<LWT=KD$snpvb;<|raYO=8NN=pEex{aVNGen|i z4hGyCiz+M`>-%J4x}J)!IMxY3_KYze`_I=c1nmrk@E8c9?MVRu)7+Ue79|<R7R(*W zmGI9WxS<;F_rj?)6ZJ2+&*@e<mlh^Wi>)rBX7tVB7U|w4*h(;Gi3D9le49B38`wuv zp7{4X^p<CFK*NrFla6?I(q;<C*K@ag4>+K4*$@gU(Tq3K1a#3SmYhvI42)GzG4f|u zwQFT1<JTz}_6=eHFU^e2CZtm7+S~2?G10jrHLa$Yc>n_=n|jpi=70-yE9LA+d*T8u z`=VmmXJ_f6WmZve<c3j)L*cT@L>ZPct$Cgu^~gFiyL>Lnpj*6ee>*0pz=t$IJ}+rE zsf@>jlcG%Wx;Cp5x)YSVvB<GcbWPQ65t~gc{a(L|Y**_KX&N^LV{4p;>1$yyY1l&o zvwX=D7k)Dn;ciX?Z)Pn8$flC8#m`nB&(8?RSdBvr?>T9?E$U3u<MGKL6<gI3+cigX zr2;7xjAPPdw|q3|5<Av+0yh@5pePF?so63EF4(f;!m<(9QF+GK>IX7T?$v4dWCa46 z+&`ot8ZTEgp7G+c52oHJ8nw5}a^dwb_l%MOh(ebVj9>_koQP^$2B~eUfSbw9RY$_< z&DDWf2LW;b0ZDOaZ&2^i^g+5uTd;GwO(-bbo|P^;CNL-<vp1D1$R<L}_zoyFQ(?^n zl`6VAFTjED$Nit=axARyg>%?9mRmxEw~5&z=X^Rvbo^WJW=n_%*7974RY}JhFv46> zd}`2|qkd;89l}R;i~9T)V-Q%K)O=yfVKNM4Gbacc7AOd>#^&W&)Xx!Uy5!BHnp9kh z`a(7MO6+Ren#>R^D0K)1sE{Bv>}s6Rb9MT14u!(NpZOe-?4V=>qZ>}uS)!y~;jEUK z&!U7Fj&{WdgU#L0%bM}SYXRtM5z!6M+kgaMKt%3FkjWYh=#QUpt$XX1!*XkpSq-pl zhMe{muh#<vd{NzT8hJO~2nwSu@|uKui`Q8EdXeGz4>knk{9_V3%qdDcWDv}v)m4t9 z<k^O7as2~K;#kz6&_j;+XcIB_r9LslJ=plZ802GD7!wKurp5N7C0N7MrBiyAL~c=u zE%@soR=E%Ksd7<Rzkb}c1=?E^tRZO%BD}eh;$H);oB)^Nt6e4N2J+}eE=O>Qhv{;} zc{}#V^N3H>9mFM8`i`0p+fN@GqX+kl|M94$BK3J-X`Hyj8r!#x6Vt(PXjn?N)qedP z=o1T^#<s;C9Ui_c^t!}2S-XqPF?-?4;fe4415B~F0>?1^a{;bZ&x`U{f?}TMo8ToN zkHj5<VbXBbPLm`saJ%OL;G18~%@f$_blKkP1#<P0FY;5DtZHS)$u-A?Yn3SA3J@bT zA1d!HbKV+f1Ugw07K&jwzua_~#;P<Rn>v|}r}wDEi7I@)Gj+S1aE<Lr;qg@51w32$ zyxn{bK>-GdnLN+$hw!=DzglMaj#{qjXi_dwpr|HL(gcCXwGLEmi|{4&4#OZ4ChceA zKVd4K!D>_N=_X;{poT~4Q+!Le+ZV>=H7v1*l%w`|`Dx8{)McN@NDlQyln&N3@bFpV z_1w~O4EH3fF@IzJ9kDk@7@QctFq8FbkbaH7K$iX=bV~o<VCiV&YRTZ}?C^!Fu2yC) zv{Vzb(sB&ct#XXgvg1<Aax>#gfh?2JD6lZf(XP>~DACF)fGFt)X%-h1yY~MJU{nA5 ze2zxWMs{YdX3q5XU*9hOH0!_S24DOBA5usB+Ws$6{|AMe*joJ?RxfV}*7AKN9V*~J zK+OMcE@bTD>TG1<D&k;gXJl_GYh`aH;$ZLob;4%Of6;ZSs-6Ri5E?%yZ1lwjNo$M0 zh+s;*GL1qh63T)l8*vTt!qBLZ)~cQ14>*yc?*qGqjBN8mgg@h1cJLDv)0!WRPIkC` zZrWXrceVw;fB%3`6kq=a!pq|hFIsQ%ZS<kf2ia2#pBvu`A3V%+`AJvHB*NUK3~nQF zw*gxnx7LCX(Z^1w*|SqdvT{$S%V#1K_mVQ7La-Aw%y<w}ejK@Lu|-CGm40~>lo~)D z|64!aCnw-?>}AG|*iOl44KVf8@|joXi&|)1rB;EQWgm+iHfVbgllP$f!$<xMKNPGw z75lQ-&s?W5309;y6gIrMn!YgKCh2h_t)HK6EcT@xYc0sgM!#>Wf42%NO5b(j9Bw6L z;0dpUUK$5GX4QbMlTmLM_jJt!u<VK-KUt7Z%d43gTkafnEz;tKrLF`kq7eb@)^GVH zVzlnCl^>r`_0~$b#BB7FL*%XFf<<YlClUogc56^3Yyh4jgqXW7(#Qu|X^(|f$!!nL zr<Jlyt{`j<%HJ7(Ibr+qi51D$ikY1it_}mi&OTSv%-y{FbY?e9I<zP))1O}CdnlMB z)E{0F(+ck9%;u_OGgFgau=Rw8qE6u}01y?;f@M5NLv*P|4@P3@#u%P9aWCL)&PJT| zX@dygu5XWA26#e~n6RWn&*Bl^^VBtoVJBn^bDnW4mHo4ME6_YI9>b__1o)Ao<oAII zl<ghkn)lbTvrX_mEpa~6_wy3!knhoEQy$s)O&Eje&DuVJ{~mIy!7WXiU&-a=SC+^7 zzq_L1{|UJN-6?C-bu@6*&_3i@#`~C#P@p9X(Ce2%iic!mTBMYuD`LZ<OM}*McxA(w zkj(d|!1fegueE#LwG9egYdYR8KktNowE4+1AfZ@IuxN3gT>3rlobbN8-(T!1d<VYe z=uu*dc`@_NH-vid1r!+qd!W<p6Hp2sR=vY4yh`?ujy)PePx7Y^!w{->-bR8D3S0@d zLI!*GMb5s~Q<&sjd}lBb8Nr0>PqE6_!3!2d(KAWFxa{hm`@u|a(%#i(#f8{BP2wbs zt+N_slWF4IF_O|{w`c~)Xvh&R{Au~CFmW#0+}MBd2~X}t9lz6*E7uAD`@EBDe$>7W zzPUkJx<`f$0VA$=>R57^(K^h86>09?>_@M(R4q($!Ck6GG@pnu-x*exAx1jOv|>KH zjNfG5pwm`E-=ydcb+3BJwuU;V&OS=6yM^4Jq{%AVqnTTLwV`AorIDD}T&<zk=U4_F z%akElkXp@CbeS<cl%y^#t}u_*o+Kw^Xa%!S>jWr8pB&j28fVtk_y*JRP^t@l*($UZ z6(B^-PBNZ+z!p?+e8@$&jCv^EWLb$WO=}Scr$6SM*&~B95El~;W_0(Bvoha|uQ1<y zI;g~pq<puh8JAZSg`e`{9Ul}WlQxSt?3%o&hA!;)cXW-;B<UPjMu}?EtHvVS7g>T< zO$%_oLAwf1bW*rKWmlD+@CP&$ObiDy=nh1b2ejz%LO9937N{LDe7gle4i!{}I$;&Y zkexJ9Ybr+lrCmKWg&}p=`2&Gf10orS?<wSRKh%(i*-EzBy^*(nk#EV0x%s+gVr5#i zF*^yn?NFz@z)jkaF%P~*zrnDtj18`Mit$=8TVU0_Xu0XQT-29W)`{}4Y{_WLO}la2 z3kum*Acd(?w(30MQ0iXECV4}56Baro5eg?Ji{&xv>4$Vr<ApIaAwLyRgnDz_63EnQ zb0F~DwJxa8Y6V&P@8Y;IWU23PX|5YXwRO5>zWidT=*6{KzOGMo?KI0>GL0{iFWc;C z+LPq%VH5g}6V@-tg2m{C!-$fapJ9y}c$U}aUmS{9#0CM*8pC|sfer!)nG7Ji>mfRh z+~6CxNb<thuojmgyDIx-O?L~|1OMp?{&5*5nw(NYRF76i1VE!yuFbdk^SXpYh9d!e zisi>>6eWKMHBz-w2{mLL<sWnSR{lp+GVAVGNcs2U?&%}ZbUT({ThKL33h5&godIvq z#4SFCl~dpzw{Kf9GWC*<(5@{J-YWs96Ulo#)6da2L@e?NLIhPLoWud(Gbix6rPhyM z+#ezG31H`whsp_@rDLe9hoK&0hz}tS!3q2%y1yY-p%>wdA7dA-qfTu^A2yG1+9s5k zcF=le_UPYG&q!t5Zd_*E_P3Cf5<i9lV%B>T6821bO<oZ<I;eq^g7*0L=5+o%xOyh3 zV}b+qIu^3vM+=S`g6~mUfaz2O^0b~+Y02%irk{L(|9!#otC{hV00sh*`O?q-K|B9x zc@lEAaI-VBcNOzAF>`daa`;DODm8Ih8k89=RN;-asHIigj`n=ux>*f!OC5#;X5i;Q z+V!GUy0|&Y_*8k_QRUA8$lHP;GJ3UUD08P|ALknng|YY13)}!!HW@0z$q+kCH%xet zlWf@BXQ=b=4}QO5eNnN~CzWBbHGUivG=`&eWK}<gH9L&>beuV*;?zt=P#pM*eTuy3 zP}c#}AXJ0OIaqXji78l;YrP4sQe#^pOqwZUiiN6^0RCd#D271XCbEKpk`HI0IsN^s zES7YtU#7=8gTn#lkrc~6)R9u&SX6*Jk4GFX7){E)WE?pT8a-%6P+zS6o&A#ml{$WX zABFz#i7`DDlo{34)oo?bOa4Z_lNH>n;f0nbt$JfAl~;4QY@}NH!X|A$KgMmEsd^&Y zt;pi=>AID7ROQfr;MsMtClr5b0)xo|fwhc=qk33wQ|}$@?{}qXcmECh>#kUQ-If0$ zseb{Wf4VFGLNc*Rax#P8ko*=`MwaR-DQ8L8V8r=2N{Gaips2_^cS|oC$+yScRo*uF zUO|5=?Q?{p$inDpx*t#Xyo6=s?bbN}y>NNVxj9NZCdtwRI70jxvm3!5R7yiWjREEd zDUjrsZhS|P&|Ng5r+f^kA6BNN#|Se}_GF>P6sy^e8kBrgMv3#vk%m}9PCwUWJg-AD zFnZ=}lbi*mN<K#(vlYbGZAX^KQmjvAYCRG*UOU`z2$j+74AdgXr3(r`Z*t~vhyGOF z)w@e8rCo#wjxU`Xq#TN0kURQy8Y45b@jCRNbbQi7ac)K;Y9F%JPMNFNffNKTTeU*T zHQTmYG^Gu1I@&Jv`71fu(BSKE_ZcDAC6eM{-i#Ce{raky!z_b9d|h7zARvnW>-AOm zCs)r=*YQAA!`e<R&0)*Xk7%|k&^;uv62@(5&ac_hW*F9=TfvBeS~Qh~EX`oba74cG z_zl_hTH19>#1N>aHF=bb*z*hXH#Wl$z^o}x##ZrUc=kh%OHWhp=7;?8%Xj||@V?1c ziWoaC$^&04;A|T)!Zd9sU<cT<Lad$0pGXX1w=fLRLa7aSLO9sinK2%NmW<mIFjiuc z-cT9?*>zE&$ODyJ<B|PnBKliB6c94vLSghm91pGb$1o^7rM2a&%c}D$u}j(J@zRz# zi%s0i4BD9?+o@$HB_##NjTPLR3oh&PgIxvX>aBpvqsw19Uiuq{i#VK1!htkdRWBnb z`{rat=nHArT%^R>u#CjjCkw-7%g53|&7z-;X<Ac^=g(0g1=gRkv{@6{)+2MuRw4?q zSyffm46G$5&03=o2M%0CNA&bH8`|Q+lj*sOSA!_VPI<qibefjTL~ySR5|HpXSu-Wk zjm)E}CNtR?XF>+ewb?OLWiV|#nuc8mp*LuGSi3IP<<*Wyo9GKV7l0Noa4Jr0g3p_$ z*R9{qn=?IXC#WU>48-k5V2Oc_>P;4_)J@bo1|pf=%Rcbgk=5m)CJZ`caHBTm3%!Z9 z_?7LHr_BXbKKr=JD!%?KhwdYSdu8XxPoA{n8^%_lh5cjRHuCY9Zlpz8g+$f@bw@0V z+6DRMT9c|>1^3D|$Vzc(C?M~iZurGH2pXPT%F!JSaAMdO%!5o0uc&iqHx?ImcX6fI zCApkzc~OOnfzAd_+-DcMp&AOQxE_EsMqKM{%dRMI5`5CT&%mQO?-@F6tE*xL?aEGZ z8^wH@wRl`Izx4sDmU>}Ym{ybUm@F83qqZPD<I_<D@SDBXpcm$%pP;@}1x+1rECR~6 z%mPO96ZtCMfz6TZL_tB_o<jX(0%{4O*=Jpf{(}rOT%n6FF#H{^%{gCRk)ccFmy zlAyZVmLT4N#~F)~@`1bcBU<gu4>6nFm?t?(7>h*?`fw)L3t*l%*iw0Qu#?$5eq!Qc zpQvqgSxrd83NsdO@lL6#{%lsYXWen~d3p4fGBb7&5xqNYJ)yn84!e1PmPo7ChVd%4 zHUsV0<QfI}<M8O`g)!{5VcjkDZIjCu8(aqo6;;=sPlL7o>Mh?VpzZD=A6%)Qrd~i7 z96*RPbid;BN{Wh?adeD_p8YU``kOrGkNox3D9~!K?w>#kFz!4lzOWR}puS(DmfjJD z`x0z|qB33*^0mZdM&6$|+T>fq>M%yoy(BEjuh9L0>{P&XJ3enGpoQRx`v6$txXt#c z0#N?b5%srj(4xmPvJxrlF3H%OM<X=kF451d5XRpaI3Rddya;o<MiVe63o}q9!6}_c zo)Za~rjO%XWDn6$-;t})ZmU#rhSPD)qiCJFwO-$XixQk0X*gbZ^iyuL^ft*8RskMZ z61oYTT##Iok;Rg+0anh212gV|jFfog*GZX}VV7x@cwuYn2k0l|CdXJ3M&=>B!jvfy z;wx8RzU~lb?h_}@V=bh6p8PSb-dG|-T#A?`c&H2`_!u+uenIZe`6f~A7r)`9m8atC zt(b|6Eg#!Q*DfRU=Ix`#B_dK)nnJ_+>Q<1d7W)eynaVn`FNuN~%B;uO2}vXr5^zi2 z!ifIF5@Zlo0^h~8+ixFBGqtweFc`C~JkSq}&*a3<b*AGX+4JAVcr=k1@(BfrL*bH3 zB2tsVQA!i($9n4x3TKj4fyB9v6dVeLF9ce$&KiuST#O+L;`7)j^T{2s!k-fHs3AFL z;*i&)+V}HhjAA_Rcq9bBAlY`@fUE4EXY~}ibwoho??7zC!;EPmIuC?iA|=eX-ry23 zydv?^AaCLg6^~XLVJgXk5t3-5-l5#+-WH4#R6H+-pH>C}L?b5Mh-bW=e)({F_g4O3 zb@SFTK3VD9QuFgFnK4Ve_pXc3{S$=+Z;;4+;*{<o#P)-O8F)a#4K`1Xm|~?q)i|U3 zYQ`j;(xom@I4xe9dA2S6y-d+xYe;^;M{B3B`KM&`C&=Gb<o8unUCEbv9DNO{|Er29 z8aca|Ig>H}Rc;845rP?DLK6G5Y-xdUKkA6E3Dz&5f{F^FjJQ(NSpZ8q-_!L3LL@H* zxbDF{gd^U3uD;)a)sJwAVi}7@%pRM&?5IaUH%+m{E)DlA_$IA1=&jr{KrhD5q&lTC zAa3c)A(K!{#nOvenH6XrR-y>*4M#DpTTOGQEO5Jr6kni9pDW`rvY*fs|ItV;CVITh z=`rxcH2nEJpkQ^(;1c^hfb8vGN;{{oR=qNyKtR1;J>CByul*+=`NydWnSWJR#I2lN zTvgnR|MBx*XFsfdA&;tr^dYaqRZp*2NwkAZE6kV@1f{76e56eUmGrZ>MDId)oqSWw z7d&r3qfazg+W2?bT}F)4jD6sWaw`_fXZGY&wnGm$FRPFL$HzVTH^MYBHWGCOk-89y zA+n+Q6EVSSCpgC~%uHfvyg@ufE^#u?JH?<73A}jj5iILz4Qqk5$+^U(SX(-qv5agK znUkfpke(KDn~dU0>gdKqjTkVk`0`9^0n_wzXO7R!0Thd<OO)*@xLj!dA|^KI{(+g5 z4&&;v3+^PaBya7Rnu#!)XYc}vIWqv)^MY!O)bd!?B<}^dB*bn^DfNh`{LBe@BaZ7K z79Vu@{$pu8y#gTfUJ?t()owinp0&lUvSWm~f6lhfPNSF&`a(>@S;U`y)VVP&mOd-2 z(hT(|$=>4FY;CBY9#_lB$;|Wd$aOMT5<N7HW=#J5xiuClp{tnl<jC$q#gWfwjqeAY zV;sA^S=5DG9oD|_sR@+2OPrAQibqT{OGVV96@Akgvd57K5T@^KQN}?9VsiR^`m+&4 z6Wo=&#vs$B<Y9Yj#aZVD^shN}siQ$PUDTmt>O_3}DYXEHn&Jrc3`2JiB`b6X@EUOD zVl0S{ijm65@n^19T3l%>*;F(?3r3s?zY{thc4%AD30CeL_4{8x6&cN}zN3fE+x<9; zt2j1RRVy5j22-8U8a6$pyT+<`f+x2l$fd_{qEp_bfxfzu>ORJsXaJn4>U6oNJ#|~p z`*ZC&NPXl&=vq2{Ne79AkQncuxvbOG+28*2wU$R=GOmns3W@HE%^r)Fu%Utj=r9t` zd;SVOnA(=MXgnOzI2@3SGKHz8HN~Vpx&!Ea+Df~`*n@8O=0!b4m?7cE^K*~@fqv9q zF*uk#1@6Re_<^9eElgJD!nTA@K9C732tV~;B`hzZ321Ph=^BH?zXddiu{Du5*IPg} zqDM=QxjT!Rp|#Bkp$(mL)aar)f(dOAXUiw81pX0DC|Y4;>Vz>>DMshoips^8Frdv} zlTD=cKa48M>dR<>(YlLPOW%rokJZNF2gp8fwc8b2sN+i6&-pHr?$rj|uFgktK@jg~ zIFS(%=r|QJ=$kvm_~@n=ai1lA{7Z}i+zj&yzY+!t$iGUy|9jH#&oTNJ;JW-3n>DF+ z3aCOzqn|$X-Olu_<wOD+V1cxb0Z}9)qPN6k=yG%7N(OXSN(!|;<~~&ZV7<|dWJ*$O zcc8BYF-@yY+0BQ2=@gx;O-;QS>p7brzn`uk1F*N4@=b=m;S_C?#hy{&NE#3Hk<sC+ z@RVY+px5c26lyz%OfzZTn@(3s>ATrg?enaVGT^$qIjvgc61y!T$9<1B@?_ibtDZ{G zeXInVr5?OD_nS_O|CK3|RzzMmu+8!#Zb8Ik;rkIAR%6?$pN@d<0dKD2c@k2quB%s( zQL^<_EM6ow8F6^wJN1QcPOm|ehA+dP(!>IX=Euz5qqIq}Y3;ibQtJnkDmZ8c8=Cf3 zu`mJ!Q6wI7EblC5RvP*@)j?}W=WxwCvF3*5Up_`3*a~z$`wHwCy)2risye=1mSp%p zu+tD6NAK3o@)4VBsM!@);qgsjgB$kkCZhaimHg&+k69~drbvRTacWKH;YCK(!rC?8 zP#cK5JPHSw;V;{Yji=55X~S+)%(8fuz}O>*F3)hR;STU`z6T1aM#Wd+FP(M5*@T1P z^06O;I20S<pPBYLx^KQ-E#4lJKf0#2<$Urm^J75xe^_~ooFOaniz#EWEnAqL5nl;d z;Y?#EUwvbZHb_{bP#Z+Xi6;``%`1xT4(Qh>k!bxW<-O;E081KRdHZrtsGJflFRRFS zdi5w<L%xAIZMaxEN{|sC`S2LX=HNoo7yNMxu?JQZn!#EHpMVSC`Z-rSU>9OVDGSL3 zNrC7GVsGN=b;YH9jp8Z2$^!K@h=r-xV(aEH@#JicPy;A0k1>g1g^XeR`YV2HfmqXY zYbRwaxHvf}OlCAwHoVI&QBLr5R|THf?nAevV-=~V8;gCsX>jndvNOcFA+DI+zbh~# zZ7<oMFIjT?dRB+;KT%*|Gjj)Lv;R$(lsDCpKH})P;^<HgAW$|Ic$UC!!9k_^)<VFb z+R-4(+=Oiwvgpt>`qNk&w+_+Yp!}j;OYxIfx_{f0-ONc?mHCiCUak=>j>~>YR4#w# zuKz~UhT!L~GfW^CPqG8Lg)&Rc6y^{%3H7iLa%^l}cw_8UuG;8nn9)kbPGXS}p3!L_ zd#9~5CrH8xtUd?{d2y^PJg+z(xIfRU;`}^=OlehGN2=?}9yH$4Rag}*+AWotyxfCJ zHx=r7ZH>j<rs-kbQ;s$ZI)B{YCAt<1f8=Z!C#+cW@(f}Vui2`~bhsJNt4X5FEVH#V zmS~5qafT)ZOfofB3RY^p$qiO+hKg5MB@4BiWOlTuD_ywdEG^^`73sk%6$@P{w!m`d zG%&#}O$F6xyMIL5Ey>2kV?%7WTtp+-HMa0)_*DBBmC{sd$)np&GEJ__kEd`xB5a2A z*J+yx>4o#ZxwA{;NjhU*1KT~=ZK~GAA;KZHDyBNTaWQ1+;tOFFthnD)DrCn`DjBZ% zk$N5B4^$`n^jNSOr=t(zi8TN4fpaccsb`zOPD~iY=UEK$0Y70bG{idLx@IL)7^(pL z{??Bnu=lDeguDrd%qW1)H)H`9otsOL-f4bSu};o9OXybo6J!Lek`a4ff>*O)BDT_g z<6@SrI|C9klY(>_PfA^qai7A_)VNE4c^ZjFcE$Isp>`e5fLc)rg@8Q_d^Uk24$2bn z9#}6kZ2ZxS9<C46&Y+Q7nYM#)S{~e<-0SXbx^w1jyAP0t!{t{i)+bD@w$9YAlUQVZ z1TZ|^=9cLiz;Bipmt#c?%u(c5s;}6EMb|KG%X+!BskufNDiLAbfcJAi-eKFCylmQ6 zcLgpiYS;T5u|4vj(43@Xs-;?LT?Reu-O1voTo*8Sg!T${N!fhDdj5F-jP4kcswNTc zUPNlqr9(p*&QkY(6{Uw9+-&ZY^AVhuru!iEZSXWk{J62Y8RTWl#jvm?@UsOLN*n1U z!!2c97^PYdYbw;1W(h-dY_NJ_bbOqzz80YwLA6En%W5F}=@a-dB;!cvFG55bE7@zZ zf}Zz=u;({6%w-qMyr7YLW0H?0K>sI(RqT7?El2@B+($>eBQrNi_k#CDJ8D9}8$mmm z4oSKO^F$i+NG)-HE$O6s1--6EzJa?C{x=QgK&c=)b(Q9OVoAXYEEH20G|q$}Hue%~ zO3B^bF=t7<z$Rj(z@}-%hhp0KDg5g-Vvj!qOr85&aqTpaaojC^CwQZHKk%N1&RJ@? z3@mmU8UkLd^u+>t48sN<h@~F@WN(LX`%4J3P$~sLqIq2q^WYYan1y*WKS{^KXRSVj zlRp2YD0*vmi}GIu(VMSMj`)AFtcV!7m`T~YnAy8nxmvlKskk~@*;{;3?|-#CT^;_> zWh_zA`w~|){-!^g<vJDMm4#3w(!Hhyj3dofOB57x=Mu^T@6Gt<KN~lv>?6Mqf6ieV zFx~aPUOJGR=4{KsW7I?<=J2|lY`NTU=lt=%JE9H1vBpkcn=uq(q~=?iBt_-r(PLBM zP-0dxljJO>4W<w&)Z{UhZ0!m()I68e=px8_4B`37AI|bCZuMk_SVKAQz?8+4(l0C) z<3()qDfD9UTW*wnelf4D7bR(}=TB;gs;ds+7QE~CAQ*jDKKADDC`3G?7kn$!=a5d& z?I(JT9>q-;stY)CLB4q`-r*T$!K2o}?E-w_i>3_aEbA^MB7P5piwt1dI-6o!qWCy0 ztYy<q;G5p>!x9arGTS?kabkkyv*yxvsPQ7Vx)twkS6z2T@kZ|kb8yjm+^$|sEBm<L zGtKcNM?a1<P1GHe%USdss^9iYmKI=GuiV`dL*Z(*)<W%!5IIDyJ!oJjHJOEa1m1VQ zKco1NMHn5?h{5SRY#VFF?T!bo5_IIEbO;WfqdSQACJa+&8o3bgw;L^BimN?NlN(v) zotn;%myS`DPUIQ+7RCnB)mY`2o&e;1Xh962y`p4wurO(bDXEWXms!a&F9;L0^G^Mo zh1W&LQdXhd1KHjKV}xwOkQ>vACeqbz)RmxkkDQX-A*K!YFziuhwb|ym>C$}U|J)4y z$(z#)GH%uV6{ec%Zy~AhK|+GtG8u@c884Nq%w`O^wv2#A(&xH@c5M`Vjk*SR_tJnq z0trB#aY)!EKW_}{#L3lph5ow=@|D5Lz<fcUCo&Ka|9|4HGWHH0_J4ujUnr>JYUFD6 z7XnUeo_V0DVSIKMFD_T0AqAO|#VFDc7c?c-Q%#u00F%!_TW1@JVn<z*P@k#}SDu4q z5BK|xV6S3>sfvm@_9HKWflBOUD~)RL``-!P;(bCON_4eVdduMO>?IrQ__*zE@7(OX zUtfH@AX*53&xJW*Pu9zcqxGiM>xol0I~QL5B%Toog3Jlenc^WbVgeBvV8C8AX^Vj& z^I}H})B=VboO%q1;aU5ACMh{yK4J;xlMc`jCnZR^!~LDs_MP&8;dd@4LDWw~*>#OT zeZHwdQWS!tt5MJQI~cw|Ka^b4c|qyd<d8BjG@CVcx~A0@_+-3ySS5}V#nYxqHn&dJ z3huaTsOBL$pM0~v6%?s%@?17;o|*#UY1tt-m0po1{B8Xt+V4%@*4l_1x6MTTu=i^t zEF!^0`A{SAgixqmbf=fe`Q#RQV7q0JEE%qC5Cl7U3dvP`CnnYy>_ly(+Ql2m&AAw^ zQeSXDOOH!!mAgzAp0z)DD>6Xo``b6QwzUV@w%h}Yo>)a|xRi$jGuHQhJVA%>)PUvK zBQ!l0hq<3VZ*RnrDODP)>&iS^wf64<Gan-0fT=xEEaI^H)!ok-sB8re6ozEmX5c@6 zvzFx43)HzN8|btxEr_+m_ES??hMpoBdA+u`<Ko)3jSDsJ<bNahp^L1kFKCk01nKG# zd~B+qtlfL5f8$8ToxOxz!oqk&<wEbF*v1K2QV8d>C;MGqDvx>|p;35%6(u+IHoNbK z;Gb;TneFo<v+>*`zUKS6kwF*&b!U8e5m4YAo03a_e^!5BP42+r)LFhEy?_7U1IR<; z^0v|DhCYMSj<-;MtY%R@Fg;9Kky^pz_t2nJfKWfh5Eu@_l{^ph%1z{jkg5jQrkvD< z#vdK!nku*RrH~TdN~`wDs;d>XY1PH?O<4^U4lmA|wUW{Crrv#r%N>7k#{Gc44Fr|t z@UZP}Y-TrAmnEZ39A*@6;ccsR>)$A)S>$-Cj!=x$rz7IvjHIPM(TB+JFf{ehuIvY$ zsDAwREg*%|=>Hw$`us~RP&3{QJg%}RjJKS^mC_!U;E5u>`X`jW$}P`Mf}?7G7FX#{ zE(9u1SO;3q@ZhDL9O({-RD+SqqPX)`0l5IQu4q)49TUTkxR(czeT}4`WV~pV*KY&i zAl3~X%D2cPVD^B43*~&f%+Op)wl<&|D{;=SZwImydWL6@_RJjxP2g)s=dH)u9Npki zs~z9A+3fj0l?yu4N0^4aC5x)O<N_(0*g4u)%5Tt4@gHE>snm0qrhz@?nwG_`h(71P znbIewljU%T*cC=~NJy|)#hT+lx#^5MuDDnkaMb*Efw9eThXo|*WOQzJ*#3dmRWm@! zfuSc@#kY{Um^gBc^_Xd<M_=Opb*sV>xnl!n&y&}R4yAbK&RMc+P<gSSGsa9{ngu3h za2rxBU6lA9Q9VAy<_CQ=#9?ge+|8rFr3YI44QC0@KPf?KG3#CkaUontfvoWcA#`fT zUZ-M@9-{1Ei|?wN2X<<LG$En}QHwMqs=8ZuZNc+NsKkIl=}k#BjOIG2xpH6pY<h{d zJ7c4SQ-wCPPp+Ave;R605<i{lO4KXOUo>^Ti;YIUh|C+K<WCtgj)+#X5!{~T0amf) zA{NO!xG0_A(b+3`Y%~$@K6*;z4@GJOlO9iW_I)Uf=v75p{Zaa%riIlQ1XqxqD1P*v zC_nl;^-H^oHskLi&AkX0pf_;|=*Q=gaUudCp%zN>1|=Z^{nZ}}rxH*v{xR!i%qO~o zTr`WDE@k$M9o0r4YUFFeQO7xCu_Zgy)==;fCJ94M_rLAv&~NhfvcLWCoaGg2ao~3e zBG?Ms9B+efMkp}7BhmISGWmJsKI@a8b}4lLI48oWKY|8<gk-*;t9-{k%FCJZFy<gM z@C~rOBUWWT##Z+g3*3Vzs8fuTtjp`u#+{x*gRagQ8={zUb)t|^B2y%Lt=XH5-VU*g zu-s*8g`Ceku&#kTTsG4pdKc+Q1?Ns^+`Anuzw^Kt@dXzw8(rtBy~EfPkytdOlMc6V z+PjsVo1fq23ba`d{M8JQ|H)T-V`Ygmnsk8K`>?zuuNc$lt5Npr+<T4KxJJ<bPDeY< zV$Y5gj%daxmn&XvpKy&xAedNSRNzj*+uARZbEwx*_BW(K#OMC!{`XgH-y>p7a#sWu zh!@2nnLBVJK!$S~>r<AjX6^_+fORZ96soQxKn~@)BfuHDd$;Hq1kJ%oj=cQPA05n| zlDech7|+hqRvU>2-pN||^w|fY`CT{TFnJy`B|e5;=+_v4l8O-fkN&UQbA4NKTyntd zqK{xEKh}U{NHoQUf!M=2(&w+eef77VtYr;xs%^cPfKLObyOV_9q<<ILDt_So;x8tA z{AwHiN2#Wqm5a+41^y+oU(NG>(%76-J%vR>w9!us-0c-~Y?_EVS<!Xa#y}`2>%v!* z15s2s3eTs$Osz$JayyH|5nPAIPEX=U;r&p;K14G<1)bvn@?bM5kC{am|C5%hyxv}a z(DeSKI5ZfZ1*%dl8frIX2?);R^^~LuDOpNpk-2R8U1w92HmG1m&|j&J{EK=|p$;f9 z7Rs5|jr4r8k5El&qcuM+YRlKny%t+1CgqEWO>3;BSRZi(LA3U%Jm{@{y+A+w(gzA< z7dBq6a1sEWa4cD0W7=Ld9z0H7RI^Z7vl(bfA;72j?SWCo`#5mVC$l1Q2--%V)-uN* z9ha*s-AdfbDZ8R8*fpwjzx=WvOtmSzGFjC#X)hD%Caeo^OWjS(3h|d9_*U)l%{Ab8 z<xdQ$23|WMjf-IqBJa@-|5QJamPBg?UmANYzk#NVaoTNbS)|8H20|;zb3-A+V#wVA z0O?V!?94t>fv$yoP{OuUl@$(-sEVNt{*=qi5P=lpxWVuz2?I7Dc%BRc+NGNw+323^ z5BXGfS71oP^%apUo(Y#xkxE)y?>BFzEBZ}UBbr~R4$%b7h3iZu3S(|A;&HqBR{nK& z$;GApNnz=kNO^FL&nYcfpB7Qg;hGJPsCW44CbkG1@l9pn0`~<fs1~obTx_FSX-JYV zGQWAl6QMe=gj$TPFe4r4b4Ol;Htq0ghUXm#FhLL;q=vj^?zll8F~1Y_ME5KlGBn?W zJLZAtGO*e1y^&@oxuzM@8GNx$4<>oKy5S777uH)l{irK!ru|X+;4&0D;VE*Ii|<3P zUx#xUqvZT5kVQxsF#~MwKnv7;1pR^0;PW@$@T7I?s`_rD1EGUdSA5Q(C<>5SzE!vw z;{L&kKFM-MO>hy#-8z`sdVx})^(Dc-dw;k-h*9O2_YZw}|9^y-|8RQ`BWJUJL(Cer zP5Z@fNc>p<r+olf3Wx4QNlGzhncc!S>TXABbTRY-B5*MphpZv6#i802giwV&SkFCR zGMETyUm(KJbh+&$8X*RB#+{surjr;8^REEt`2<qz>&Dubw3$mx>|~B5IKZJ`s_6fw zKAZx9&PwBqW1Oz0r0A4GtnZd7XTKViX2%kPfv+^X3|_}RrQ2e3l<T~g*|IE{P97HV zvf#Y<i{KPN_dP%1)NHb~ix&=&GH9>=KG_VyY`H?I5&CS+lAX5HbA%TD9u6&s#v!G> zzW9n4J%d5ye7x0y`*{KZvqyXUfMEE^ZIffzI=Hh|3J}^yx7eL=s+TPH(Q2GT-sJ~3 zI463C{(ag7-hS1ETtU;_&+49ABt5!A7C<XW?{o=2DnJxLDD~{m*zq$azI0t7>wLwe z=SoA8mYZIQeU;9txI=zcQVbuO%q@E)JI+6Q!3lMc=Gbj(ASg-<Uq;hB9d^p}DAXc~ zT?U|Ep>{V27u>z2e8n;Nc*pf}AqKz1D>p9G#QA+7mqqrEjGfw+85Uyh!=tTFTv3|O z+)-kFe_8FF_EkTw!YzwK^Hi^_dV5x-Ob*UWmD-})qKj9@aE8g240nUh=g|j28^?v7 zHRTBo{0KGaWBbyX2+lx$wgXW{3aUab6B<q-FjF>hm1G1{jTC7ota*JM6t+qy)c5<@ zpc&<Cv-}2TvNf)-u^)w4IR#IAb30P8NKX2F^|M`)t)gNvmzY$92){_sASc~#MG?G6 z01+~17JwM!JPSxaJJtTz7$&8s`H3FldxQ%9@~nj<<O#kvf=K=$4nLLmHGiFo3Mq&* ziIi#gQw#(**q&>(jVdTJf(q3xB=JotgF$X>cxh7k*(T`-V~AR+`%e?YOeALQ2Qud( zz35YizXt(aW3qndR}fTw1p()Ol4t!D1pitGNL95{SX4ywzh0SF;=!wf=?Q?_h6!f* zh7<+GFi)q|XBsvXZ^qVCY$LUa{5?!CgwY?EG;*)0ceFe&=A;!~o`ae}Z+6me#^sv- z<kA1n(=XTnu@rJsCenhu-Zv&%WBDK;wE+-m5)3gqDM=UJSV|IgE?>1F6=WNd6>M(~ z+092z>?Clrcp)lYNQl9jN-JF6n&Y0mp7|I0dpPx+4*RRK+VQI~>en0Dc;Zf<!>l+x z_e_b7s`t1_A`RP3$H}y7F9_na%D7EM+**G_Z0l_nwE+&d_kc35n$Fxkd4r=ltRZhh zr9zER8>j(EdV&Jgh(+i}ltESBK62m0nGH6tCBr90!4)-`HeBmz54p~QP#dsu%nb~W z7sS|(Iydi>C@6ZM(Us!jyIiszMkd)^u<1D+R@~O>HqZIW&kearPWmT>63%_t2B{_G zX{&a(gOYJx!Hq=!T$RZ&<8LDnxsmx9+TBL0gTk$|vz9O5GkK_Yx+55^R=2g!K}NJ3 zW?C;XQCHZl7H`K5^BF!Q5X2^Mj93&0l_O3Ea3!Ave|ixx+~bS@Iv18v2ctpSt4zO{ zp#7pj!AtDmti$T`e9{s^jf(ku&E|83JIJO5Qo9weT6g?@vX!{7)cNwymo1+u(YQ94 zopuz-L@|5=h8A!(g-<F;G9^=CwUG2BBM&6@esQFH4>MXgLJC0MA|CgQF8qlonnu#j z;uCeq9ny9QSD|p)9sp3ebgY3rk#y<wu$Scub#>0DA(SHdh$DUm^?GI<>%e1?&}w(b zd<n{_{wZL^#}W>ip1;P2Z=1wM+$q=TgLP$}svd!vk+BZ@h<^4R=GS2+sri7Z*2f`9 z5_?i)xj?m#pSVchk-SR!2&uNhzEi+#5t1Z$o0PoLGz*pT64%+|Wa+rd5Z}60(j?X= z{NLjtgRb|W?CUADqOS@(*MA-l|E342NxRaxLTDqsO<GMIr8u8#%dIQrz(r`Q(hkza zil8N-`Js{wU0Gy<JdGKt>yfWWe%N(jjBh}G<qND?0TH2WotV2BO}oGFXR`nNIoZPu zAYBqht4AIf6%UvOQWL(@v@#P!g?Z{m=yxdflhU-MrdJ3Lu4OwZ%yKkuPkk0$Ko)O* z;5yrsNkvYZsjZQILNsEr+ECa0P<^XyVVf2;%`lxDRkz-!;wa1;EB{emo`C=%{Gykq zq<4i~ETk#P9zK#gq4PdG1l$Vspzwyb@<LIRCp@UiYQvSVfg*oiL+eCZD0<3etyAQ> zm7WPel6jXijaTiNita+z(5GCO0NM=Melxud57P<u@R2P46Q9-DyjXBHUN>P^d_U## zbA;9iVi<@wr0DGB8<n8`yw;2Kv**CeqAs$L&plPhIa#v7(dTNoPt@&}ED@M*lxC!x z`6s~+J|uy;3o7Lq<uMmSEF9Dw$gP)!=7bwIZF}v$SuOexM&6SRtdGcL+`+Tm+leuz zpp$tX{Sz|>=T9Ab#2K_#zi=<XArhO6r_`n&7XSM212-MzWyRNG*!uO-#ecnE^8eXw z{A)4%t2FvosVP<UQ~s;l`0?z0m3m-lgN!65Mz=sfFM<3$$g-N5nIt_Q>$igy<I%16 z>K48@;V|W`fg~7;+!q8)aCOo{HA@vpSy-4`^!ze6-~8|QE||hC{ICKllG9fbg_Y7v z$jn{00!ob3!@~-Z%!rSZ0JO#@>|3k10mLK0JR<I1S>KP-Cc8UYFu>z93=Ab-r^oL2 zl`-&VBh#=-?{l1TatC;VweM^=M7-DUE>m+xO7Xi6vTEsReyLs8KJ+2GZ&rxw$d4IT zPXy6pu^4#e;;ZTsgmG+ZPx>piodegkx2n0}SM77+Y*j^~ICvp#2wj^BuqRY*&cjmL zcKp78aZt>e{3YBb4!J_2|K~A`lN=u&5j!byw`1itV(+Q_?RvV7&Z5XS1HF)L2v6ji z&kOEPmv+k_lSXb{$)of~(BkO^py&7oOzpjdG>vI1kcm_oPFHy38%D4&A4h_CSo#lX z2#oqMCTEP7UvUR3mwkPxbl8AMW(e{ARi@HCYLPSHE^L<1I}OgZD{I#YH#GKnpRmW3 z2jkz~Sa(D)f?V?$gNi?<F$5NpPo_(+mLu%j0uVGhEpW~}8A-6p@(iN<J78jy&84)} zW71~;kMKbRG+MZ(!>6)Y;Sm{&?~2p=0&BUl_(@hYeX8YjaRO=IqO7neK0RsSNdYjD zaw$g2sG(>JR=8Iz1<iqC50Fc?zkwnhu-?J#4v?gbo)h!toq+!EipMj&Dd=4)`^!2@ zL(!GW5QxLJO&{?1u~Q}Au)moY@9Q-~Yr01D0la`rUI3jK%5PxGU7;z+IlI=Bb;^2b zL|Kc&B2+#W3&e}l>SK4`*kqd_3-?;_BIcaaMd^}<@MYbYisWZm2C2<aQM85hCqTrH z{L!?Z_;my2c?%RMej)yS*$eqpa!UR3e9te>|Np_l|8r9yM|JkUngSo@?wci(7&O9a z%|V(4C1c9pps0xxzPbXH=}QTxc2rr7fXk$9`a6TbWKPCz&p=VsB8^W96W=BsB|7bc zf(QR8&Ktj*iz)wK&mW`#V%4XTM&jWNnDF56O+2bo<3|NyUhQ%#OZE8$Uv2a@J>D%t zMVMiHh?es!Ex19q&6eC&L=XDU_BA&uR^^w>fpz2_`U87q_?N2y;!Z!bjoeKrzfC)} z?m^PM=(z{%n9K`p|7Bz$LuC7!>tFOuN74MFELm}OD9?%jpT>38J;=1Y-VWtZAscaI z_8jUZ#GwWz{JqvGEUmL?G#l5E=*m>`cY?m*XOc*yOCNtpuIGD+Z|kn4Xww=BLrNYS zGO=wQh}Gtr|7DGXLF%|`G>J~l{k^*{;S-Zhq|&HO7rC_r;o`gTB7)uMZ|WWIn@e0( zX$MccUMv3ABg^$%_lNrgU{EVi8O^UyGHPNRt%R!1#MQJn41aD|_93NsBQhP80yP<9 zG4(&0u7AtJJXLPcqzjv`S~5;Q|5TVGccN=Uzm}K{v)?f7W!230C<``9(64}D2raRU zAW5bp%}VEo{4Rko`bD%Ehf=0voW?-4Mk#d3_pXTF!-TyIt6U+({6OXWVAa;s-`Ta5 zTqx&8msH3+DLrVmQOTBOAj=uoxKYT3DS1^zBXM?1W+7gI!aQNPYfUl{3;PzS9*F7g zWJN8x?KjBDx^V&6iCY8o_gslO16=kh(|Gp)kz8qlQ`dzxQv;)V&t+B}wwdi~uBs4? zu~G|}y!`3;8#vIMUdyC7YEx6bb^1o}G!Jky4cN?BV9ejBfN<&!4M)L&lRKiuMS#3} z_B}Nkv+zzxhy{dYCW$oGC&J(Ty&7%=5B$sD0bkuPmj7g>|962`(Q{ZZMDv%YMuT<n z1<0L@A~^*&C~fETTawHVh1kk4b*^p0vQ^7?+3dKBe<pM8Snh`k_7R%#IZRUEl1U~% z`#y5ddd+xk?tVQb4dNJ(7Ry%2!BTF1HzW?PK!2%Oj>^Kwe<oH3RpEUQV(1=JAftKZ zy};jv^`iGA^yoK}($W9zl~UM?CzovcbP5)_-K0QR<B0^>iRDvYTEop3IgFv#)(w>1 zSzH><Zx#DBcM*ETggCrIL|G$?#sL+^<gVn#xwx<>J`q!LK)c(AK>&Ib)A{g`<Y-)} z(@A>Fdykxqd`Yq@yB}E{gnQV$K!}RsgMGWqC3DKE(=!{}ekB3+(1?g}xF>^icEJbc z5bdxAPkW90atZT+&*7qoLqL#p=>t-(-lsnl2XMpZcYeW|o|a322&)yO_8p(&Sw{|b zn(tY$xn5yS$DD)UYS%sP?c|z>1dp!QUD)l;aW#`%qMtQJjE!s2z`+bTSZmLK7SvCR z=@I4|U^sCwZLQSfd*ACw9B@`1c1|&i^W_OD(570SDLK`MD0wTiR8|$7+%{cF&){$G zU~|$^Ed?TIxyw{1$e|D$050n8AjJvvOWhLtLHbSB|HIfhMpqVf>AF&}ZQHhOJ14Bz zww+XL+qP}nww+W`F>b!by|=&a(cM4JIDhsTXY8@|ntQG}-}jm0&Bcj|LV(#sc=BNS zRjh<Mlkf>;k9l>EdAFdd)=H!U`~$WP*}~^3HZ_?H>gKw>NB<D?df$IC%55Zl`EPwc zRF>a;tA8M1{>St|)yDF_=~{KEPAGkg3VB`QCHol!AQ0|?e^W?81f{@()Wy!vQ$bY; z0ctx)l<l3Egk{Ob>7VK83d6;dp!s{Nu=SwXZ8lHQHC*J2g@P0a={B8qHd<!Rx=U=y zZhU*Z!GA%uunxv9&4$#mX+|}S)urtQN=7La7qnsxu>v(+O3wV=4-t4HK1+smO#=S; z3cSI#Nh+N@AqM#6wPqjDmQM|x95<n5VlzgWRH&oDW?c}DT^%?B8C0l+B0<BSKyNf1 z@50z}-d3zrSn&7`r1tBSp<zb3^nhH#XuDC?R<KtB*VsyKR`dRh)&DkLIrq4o!?;Lk zondptVSwpbOiowRa-P*4A7o%#IYH#y*MPqzE9G%OcE;(l=a5Gbdc^<iHA{4$gMK2y zrcQ~;DrQl(Xod1}HF3{_dN{dd)Iq**zG_<1@e+8Q8+Oq;jgidKOGIuhBe_rBN^N(^ zH&yrkQqs47d>JG|l1<sF7&JuwXR&1!7b?5$CbRqF7%}I8mpCr(sj;K7IQl+Ud)#bZ zp7IC+SbpjPV~m#KY)1CSNeLmt63WJp#VvwlYf+=uB{p=aUnI`+`Y>#sAU|>I6<Rxv z+8ksxQP-bXJt|;JqZ0=Syg@fkr7?v9z=bM6Vn&}>NdF*G@bD?1t|ytHlkKD+z9}#j zbU+x_cR-j9yX4s{_y>@zk*ElG1yS({BInGJcIT>l4N-DUs6fufF#GlF2lVUNOAhJT zGZThq54GhwCG(h4?yWR&Ax8hU<*U)<g>?g+HY5-@{#ls5CVV(Wc>Bavs|l<}U|hZn z_%m+5i_gaakS*Pk7!v&w3&?R5Xb|AkCdytTY;r+Z7f#Id=q+W8cn)*9tEet=OG+Y} z58U&!%t9gYMx2N=8F?gZhIjtkH!`E*XrVJ?$2rRxLhV1z82QX~PZi8^N5z6~f-MUE zLKxnNoPc-SGl7{|Oh?ZM$jq67sSa)Wr&3)0YxlJt(vKf!-^L)a|HaPv*IYXb;QmWx zsqM>qY;tpK3RH-omtta+Xf2Qeu^$VKRq7`e$N-UCe1_2|1F{L3&}M0XbJ@^xRe&>P zRdKTgD6601x#fkDWkoYzRkxbn#*>${dX+UQ;FbGnTE-+kBJ9KPn)501#_L4O_k`P3 zm+$jI{|EC?8BXJY{P~^f-{**E53k%kVO$%p+=H5DiIdwMmUo>2euq0UzU90FWL!>; z{5@sd0ecqo5j!6AH@g6Mf3keTP$PFztq}@)^ZjK;H6Go$#SV2|2bAFI0%?aXgVH$t zb4Kl`$Xh8q<G488u@$4lX!B=3?g=wlC?}MC;F?H%YQrVNOwB#z7-f_|Wz?O!b4I~2 z^Qw&0hykWBc$}5NngS)c1*7`tH73!7vUHgRMs>LrMbZUS<2*7^F0^?lrOE=$DHW+O zvLdczsu0^TlA6RhDy3=@s!k^1D~Awulk!Iyo#}W$xq8{yTAK!CLl={H0@YGhg-g~+ z(u>pss4k#%8{J%~%8=H5!T`rqK6w^es-cNVE}=*lP^`i&K4R=peg1tdmT~UAbDKc& zg%Y*1E<jNK6bVo^5$q7Be!g@_B}<2f!MazAse=SHXka44U?M8cg8{iRQqX625kGny zEx>{hBf<)xO>HDWV7BaMWX6FW4ou1T2m^6{Jb!Su1UaCCYY8RR8hAV$7ho|FyEyP~ zEgK`<ybDN}WQ7ppf~i48Sp+j=w6UI16W6MuJXhL6VlQ|!lSyz6m|Gs@>@%a$-C2`p zV*~G>GOAs*3KN;~IY_UR$ISJxB(N~K>=2C2V6>xTmuX4<wHTgMVWGBYU0G4B(`;}2 zw_J6Ct{nL}*%nG0uk<t$To_fcVQEvXjtQYeWv?v&5m9S(NJkQnc)rvU7`Je&48A!8 z_->klRXdrJd&UPAw7&|KEwF8Zcy2j-*({gSNR1^p02Oj88GN9a_Hq;Skdp}kO0;<y ztR-y<(h)MzSR8PG`MEz?T1Lf{zq~R3i)I#s$y{Wn^A`t(9>FLbje%2ZvPiltDZgv^ z#pb4&m^!79;O8F+Wr9X71laPY!CdNXG?J6C9KvdAE2xWW1>U~3;0v≫L+crb^Bz zc+Nw%zg<eW;A}s=*P6+gF}bio8=x0TEl%l4pJ$tyY5b9sQ8QUf<CVb&IosSO?U)TS zqRaFVMB?L$Va^G<K_IKy<}kIfB`>pZ6>!A3%lau!Pw6`Y#WPVBtAfKSsqwYDWQK-~ zz(mx=nJ6-8t`YXB{6gaZ%G}Dmn&o500Y}2Rd?e&@=hBEmB1C=$OMBfxX__2<amvr< zXa%T~J;`~)wa6K9vLDPZ4GZLPS7oKSy)VETgG@jr+mViaX=%jwAwMaxuIET{i2|{P z=%Yb3&*b&m#ml+5FlJql5a}W%z?`C^MKY$$m`pDfNwvint?IO6amJ*PZQL1(52tL{ zJANajfD2`9E?S2iDE{r9w1H+KbS!7BR1@VophCkXHR`|fTeaGAB8za0A1K7kCS(bA z3^hY;UdsU90Qq(v&N0T9JSv}(7&&Gw+V%U6EH!}fv*RqA&zDLjkb!uv6idVcvDYv} z&BaSl7_k9>c2O4K2#(0ksclP$SHp*8jq-1&(<6(#=6&H`Nlc2RVC4->r6U}sTY<1? zn@tv7XwUs-c>Lcmrm5AE0jHI5={WgHIow6cX=UK)>602(=arbuAPZ37;{HT<bASz# zhpNmfwQSDBB;fIIk_gW5U{}19wURbn{If{5IyR->JSIO%9EL`Et5%J7$u_NaC(55x zH^qX^H}*RPDx)^c46x>js=%&?y?=iFs^#_rUl@*MgLD92E5y4B7#EDe9yyn*f-|pQ zi>(!bIg6zY5fLSn@;$*sN|D2A{}we*7+2(4&EhUV%Qqo5=uuN^xt_hll7=`*mJq6s zCWUB|s$)AuS&=)T&_$w>QXHqCWB&ndQ$y4-9fezybZb0bYD^zeuZ>WZF{rc>c4s`` zgKdppTB|o>L1I1hAbnW%H%EkFt%yWC|0~+o7mIyFCTyb?@*Ho)eu(x`PuO8pLikN> z6YeI`V?AUWD(~3=8>}a6nZTu~#QCK(H0+4!ql3yS`>JX;j4+YkeG$ZTm33~PLa3L} zksw7@%e-mBM*cGfz$tS4LC^SYVdBLsR}nAprwg8h2~+Cv*W0%izK+WPVK}^SsL5R_ zpA}~G?VNhJhqx2he2;2$>7>DUB$wN9_-adL@TqVLe=*F8Vsw-yho@#mTD6*2WAr6B zjtLUh`E(;#p0-&$FVw(r$hn+5^Z~9J0}k;j$jL1;?2GN9s?}LASm?*Rvo@?E+(}F& z+=&M-n`5EIz%%F^e)nnWjkQUdG|W^~O|YeY4Fz}>qH2juEere}vN$oJN~9_Th^&b{ z%IBbET*E8%C@jLTxV~h#mxoRrJCF{!CJOghjuKOyl_!Jr?@4Upo7u>fTGtfm|CH2v z&9F+>;6aFbYXLj3{yZ~Yn1J2%!)A3~j2$`jOy{XavW@t)g}}KUVjCWG0OUc7aBc=2 zR3^u=dT47=5SmT{K1aGaVZkOx|24T-J0O$b9dfB25J|7yb6frwS6wZ1^y%EWOm}S< zc1SdYhfsdLG*FB-;!QLV3D!d~hnXTGVQVck9x%=B(Kk8c3y%f0nR95_TbY;l=obSl zEE@fp0|8Q$b3(+DXh?d0FEloGhO0#11CLQT5qtEckBLe-VN-I>9ys}PVK0r;0!jIG zH_q$;a`3Xv9P_V2ekV1SMzd#SKo<1~Dq2?M{(V;AwhH_2x@mN$=|=cG0<3o^j_0OF z7|WJ-f2G=7sA4NVGU2X5`o*D2T7(MbmZ2(oipooE{R?9!{WxX!%ofhsrPAxoIk!Kr z>I$a{Zq=%KaLrDCIL^gmA3z{2z%Wkr)b$QHcNUA^QwydWMJmxymO0QS22?mo%4(Md zgME(zE}ub--3*wGjV`3eBMCQG-@Gel1NKZDGuqobN|mA<Orshs+Cll$u%OVm+m7$A zvobiM4A4uVtI2;EQ`is0JxPx9*53^imsz^x6`T%eO>t0{@ZC9goI|BSmGBTUZ(`Xt z^e2LiMg?6E?G*yw(~K8lO(c4)RY7UWxrXzW^iCg-P41dUiE(i+gDmmAoB?XOB}+Ln z_}rApiR$sqNaT4frw69Wh4W?v(27IlK$Toy<1o)GeF+sGzYVeJ`F)3`&2WDi^_v67 zg;@ehwl3=t+}(DJtOYO!s`jHyo-}t@X|U*9^sIfaZfh;YLqEFmZ^E;$_XK}%eq;>0 zl?+}*kh)5jGA}3daJ*v1knbW0GusR1+_xD`MFPZc3qqYMXd>6*5?%O5pC7UVs!E-` zuMHc6igdeFQ`plm+3HhP)+3I&?5bt|V8;#1epCsKnz0%7m9AyBmz06r90n~9o;K30 z=fo|*`Qq%dG#23bVV9Jar*zRcV~6fat9_w;x-quAwv@BkX0{9e@y0NB(>l3#>82H6 z^US2<`=M@6zX=Pz>kb8Yt4wmeEo%TZ=?h+KP2e3U9?^Nm+OTx5+mVGDvgFee%}~~M zK+uHmj44TVs}!A}0W-A92LWE%2=wIma(>jYx;eVB*%a>^WqC7IVN9{o?iw{e4c=CG zC#i=cRJZ#v3<OhgHFO)Yuf*wx=u8?KJAxfFal#c87qImw{QL+yd!UrcHEm`qaIWJ> zF^9V+7u?W=xCY%2dvV_0dCP%5)SH*Xm|c#rXhwEl*^{Ar{NVoK*H6f5qCSy`+|85e zjGaKqB)p7zKNKI)iWe6A9qkl=rTjs@W1Crh(<w{D@{wF@eAUdA<ecn!45g=nz<F8W zcHpM2OaZmr7hg(j>3G57qdT0w2ig^{*xerzm&U>YY{+fZbkQ<WiW=GrQ9?}ABlM?S z5yX^-T$QGSicUUT_;DBFofFw|X+^sREV>#;^<$JniUifmAuEd^_M(&?sTrd(a*cD! z<RfQp$HKS4nD)BZdWrVduooK{Y#BPyLM^%s#T9QaF#!BDh4*GS0;>F*;`m80MrZ^> zaF{}rDhEFLeH#`~rM`o903FLO?qw#_Wyb5}13|0agjSTVkSI6Uls)xAFZifu@N~PM zQ%o?$k)jbY0u|45WTLAirUg3Zi1E&=G#LnSa89F3t3>R?RPcmkF}EL-R!OF_r1ZN` z?x-uHH+4FEy>KrOD-$KHg3$-Xl{Cf0;UD4*@eb~G{CK<fax(qwwJBZTjQv;(6lwZ1 zN@y8!2Q~?JvR=^bgSD}Zo^iruSXBV}rzy#Y@LME2qAW4Y%O+imN5Xc_W5Fh#DBFe; zwY9`azQ@O1eUnX&7vS!|8z%OWQCo_Wg2|qd_%j<t?-<@AfA>-DXe3xpEEls?SCj^p z$Uix(-j|9f^{z0iUKXcZQen}*`Vhqq$T?^)Ab2i|joV;V-qw5reCqbh(8N)c%!aB< zVs+l#_)*qH_iSZ_32E~}>=wUO$G_~k0h@ch`<gt#cp1U1WgWwHf1zyQewkQH>a6Wa zsk;<)^y=)cPpHt@%~bwLBy;>TNrTf50BAHUOtt#9JRq1ro{w80^sm-~fT>a$QC;<| zZIN%&Uq>8`Js_E((_1sewXz3VlX|-n8XCfScO`eL|H&2|BPZhDn}UAf_6s}|<W$yZ z&kmrV`OAcyEk@5O_d1K`9ztw!LTQ)vi^7AY(b7$AK%X!8_!&bvrhLv@oFO}+TfU4o z!H9q63S!`o3%v<@B2F*Pz76V~n+@=u<2KM_4Yf4Tcil0U)}t=ASxe=Js$o)5^i~?< z5OqmfW6-dnOw9@{Aqq4vD4bN1OnS@+lTfgs?eN(FNn5Q#_veOlFdu3)IK$eB^Uo4t zj?l?=#xmRXU%L-sp<dhXj_~_D*FuOEC>!XpmUr90v|nCutzMjb9|&}#Y7fj_)$alC zM~~D6!dYxhQof{R;-Vp>XCh1AL@d-+)KOI&5uKupy8PryjMhTpCZnSIQ9^Aq+7=Mb zCYCRvm4;H=Q8nZWkiWdGspC_Wvggg|7N`iED~Eap)Th$~wsxc(>(KI>{i#-~Dd8iQ zzonqc9DW1w4a*}k`;rxykUk<ZJ`qoPZH+s1L|{7dJ03F>+~N)|*I?@0901<qh{Z9u zM(%*;?u7Tx@An5HnDFSwh~71l4~zl+IS3QFak$TAn}O;_&Yg6&yC;97-}}S=>R`xy zN{20p@Ls<%`1G1Bx87Vm6Z#CA`QR(x@t8Wc?tpaunyV^A*-9K9@P>hAWW9Ev)E$gb z<(t?T<I%q{eh<paBCgp(eNP1JC7j$cU&lqI%}1$+t<Xum)7-hy-(S~>e6GcJX2&0% z403pe>e)>m-^qlJU^kYIH)AutgOnq!J>FoMXhA-aEx-((7|(*snUyxa+5$wx8FNxS zKuVAVWAr<NYYOV+XC<zEq=BX*l6of(_0jkouf~Z}i)Pi;@oSKe*2S%Ot!8e9G()D^ zHCF=S(f7vqeckT}E9Gkn7-$v6Rolof1?4D(Ee6t+oZ0lsJ=UPx<vWKk)>lK#kDzEM zqR?&aXIdyvxq~wF?iYPho*(h<uGlq#b_^JO#6P~MgKdi{;dc6bOPRw@UTRu@s@>?k zD(SBpRDZ}z$A})*Qh!9&pZZRyNixD!8)B5{SK$PkVET(yd<8kImQ3ILe%jhx8Ga-1 zE}^k+Eo^?c4Y-t2_qXiVwW6i9o2qosBDj%DRPNT*UXI0=D9q{jB*22t4HHcd$T&Xi zT=Vte*Gz2E^qg%b7ev04Z&(;=I4IUtVJkg<`N6i7tjUn-lPE(Y4HPyJKcSjFnEzCH zPO(w%LmJ_=D~}PyfA91H4gCaf-qur3_KK}}>#9A}c5w@N<r?JvNjY~yQShiS4qY&3 zlEq{*4cG8TB8w?hxny#0kg_47TjeF0N4fFfRug<oQH4Q(9JenqW{)rACv`ezyz-yU zXWQaxZzc6w)o5k1X`jL!9euTR%&XzA(yX>;-#cHph=x}^mQ3`oo`Y$ope#)H9(kQK zGyt<7eNPuSAs$S%O>2ElZ{qtDIHJ!_THqTwcc-xfv<@1>IJ;YTv@!g-zDKBKAH<<p zBDDsGt$u2qMC-^a?PmMtEGv5Qjw-8`x+??EVCj)0tD5~cjb`<Ru8=Di2fXP=Xsa4y z&n#+a?$v9OkH1zuW`su>Zet1e^8c}8fE97XH}+lF{qbF<`Y%dU|I!~Y`ZrVfKX82i z)(%!Tcf~eE^%2_`{WBPGPU@1NB5SCXe1sAI<4&n1IwO{&S$ThWn37heGOSW%nW7*L zxh0WK!E7zh%6yF-7%~<m{+EMBci$fO&hv0iZf0iciMJ_<^l~es_{rqv)3kTa)Ak7+ z^Xo_#|0iZI&^uj#ODfeL#OGhjgkcd>l@I~b`2=*$;RYbi(I#zp$gL_d39U4A)KuB( zcS0bt48&%G<QI2DbY;&fyt@4p`kndvOAsyITmfiaVnddQPW><k4f~&M47%t~>_I~( zL(}w&2NA6#$=|g)J+-?ehHflD^lr77ngdz=dszFI;?~ZxeJv=gsm?4$$6#V==H{fa zqO!EkT>1-OQSJoX)cN}XsB;shvrHRwTH(I2^Ah4|rizn!V7T7fLh~Z<`Q+?zEMVxh z$=-x^RR*Pl<N5e(X;~A8VM_P?TZ%aBKgo&=4$TErD)@Yct1Rw?ng{l|AoY=?j%yN0 z{#cO{%|$VQvwftyGPCmDv`G|@hi=(&+FD`aH0@zL)mgk61`d7fWFI<9n5Stfh{y~| zVYivv;t1&zm<!4~89}Fc?b(Kg_9R40b-;<;G;xsNR2o!c=iwxzn4nij;=KC8R)gz3 z9{q)1S1P63>hkV_8mshTvs+zmZWY&Jk{9LX0Nx|<ldHT!kKyn#dbVMfBn9e@+8r+F zfUf&0TK=f&Dw}lCHqy=C!Y_ll#;7`Ni~dQ7*RF-@CT118I8||q-;pR+UUO=*ir<_t z#spc+WCC_&j^sM1My2U+FVEl;KnC$f^WTRS8%6rW@=8`+%Q<P=bTsD{BzbOLv4B=< znii$?HN+aTLVM;6Ry2|w16RXk8F{P;vF6P*>+NAEq-^+Rh|ZlinVZ=e8=`WQt;e@= zPU}^1cG*O;G7l<KDc2~6h#xMeWr-r0OAVri(64~%KI0R2+$-rI{tJE2uRmY>{Y#nl znp`y%CO_SC7gk0i0gY&phM04Y)~vU0!3$V$2T+h(1ZS<f8b%S8rz4-~;5aW>+cCgc zaC?3M;B48^faGo>h~--#FNFauH?0BJJ6_nG5qOlr>k~%DCSJaOfl%KWHusw>tG<g2 z$lo!8f^Xe%pj=Rq7%tJ{i>rTxAhlEVDxc8R2C-)LCt&$Rt9IKor=ml7jirX@?WW+M z^I{b<RO!Q<u)IU5t7<PW#57>}MD5r$s>^^sN@&g`cXD~S_u09xo;{;noKZatIuzqd zW1e7oTl9>g8opPBT(p+&fo0F#!c{NFYYpIZ6u8hOB{F#{nP)@}<EI#MDyucB{#6)L zh?JbpGIyYUsx1TNY%9e(fQxI4t~H%dE@^{WcxhZ!EGpG(z;pkdxe<EMwA+Lw4=;2g zYbi-SoGU)S_pwcYeS^ZA!|qTP6{pVI-|SNsgg%*BWh(Meg~tf-Q>)X20$3iJtG$cO zJ$Oxl_qH{sL5d?=D$2M4C3Ajc;GN0(B-HVT;@pJ-LvIrN%|SY?t}g!J>ufQrR%hoY z!nr$tq~N%)9}^tEip93XW=MQ1@XovSvn`PTqXeT9@_7hGv4%LK1M**Q%UKi|(v@1_ zKGe*@+1%Y4v&`;5vUL`C&{tc+_7HFs7*OtjY8@Gg`C4O&#An{0xOvgNSehTHS~_1V z=daxCMzI5b_ydM5$<?dgyKM^=r)Tc6U|s}2kynE;FGHeu-B988SO;&pB(e6Qh2P=z z3xHw_PzW_~dkx((DUd~Q2N1y~?HHrUe^BBMG0xxXk7M0LA9EBTCq5C@%1ysh#Z!@~ zeBSi(I#rmd%ndI2&VJ}2ohfjS@n({D#%pBmt^KT`Uq^dIUO)MO6sy=Co=$u5L%1ly zKrztx?JF?i3`s2H+UzoBhg0&Z9qMf`%Goy1(HZK-?+u=1^xjw2TbhuR=eMi!$6G>z zZl`a{mM}i@x;=QyaqJY&{Q^R*^1Yzq!dHH~UwCCga+Us~2wk59ArIYtSw9}tEmjbo z5!JA=`=HP*Ae~Z4Pf7sC^A3@Wfa0Ax!8@H_&?WVe*)9B2y!8#nBrP!t1fqhI9jNMd zM_5I)M5z6Ss5t*f$Eh{aH&HBeh3<g7^zLpu^Ry#)H8VHEiRW^liKzzBoM3#P@ytA< zA@5R;`2dqNGoWM#nC%jlTW~eu$^Qc*+dkom?FLAYw(n7mMai@*PO})<Dp$Ok0Hd|J z{nPfV$w6+Nq{4I+p~1*KT9hjW@0B__I&Mskiv;drVlpZ7bg1FkO*IdCid;LJ_4!7K zbfkj~O7n!d8(RlYcP}&ccfRG>10Q~tRl3wCEcZ>WCEq%3tnoHE)eD=)XFQ7NVG5kM zaUtbnq2LQomJSWK)>Zz1GBCIHL#2E>T8INWuN4O$fFOKe$L|msB3yTUlXES68nXRX zP6n*zB+kXqqkpQ3OaMc9GqepmV?Ny!T)R@DLd`|p5ToEvBn(~aZ%+0q&vK1)w4v0* zgW44F2ixZj0!oB~^3k|vni)wBh$F|xQN>~jNf-wFstgiAgB!=lWzM&7&&OYS=C{ce zRJw|)PDQ@3koZfm`RQ$^_hEN$GuTIwoTQID<d@J+C!*a#y8F@xM-Iy_j&S_v$*aHC z<^<1lMFmAQ6d)B9ppuP7+x{7e>b?W&wEo@c75$dW(ER6q)qhF`{#7UTuPH&)w`F!w z0EKs}=33m}_(cIkA2rBWvApydi0HSOgc>6tu&+hmRSB%)s`v_NujJNhKLS3r6hv~- z)Hm@?PU{zd<SuU^ZNqbh_hj?zhJVNRM{0ipOFcz-sswR>0Tga)cJWb2_!!9p3sP%Z zAFT|jy;k>4X)E>4f<s%$es?%H6q44Ym7Tg^bK_WZ>h^6=SxV5w6oo`mus&nWo*gJL zZH{SR!x)V)y=Qc7WEv-x<Rp}|n<G?y@SQ4XooI*D5H6|yT}sqCm#c1ra{^IYypH}c zm17W3XkTgz;cv-2Bkm9zj!KK~b{5nJs-w29PNOBOi7M%$)E08H=v6$}lUmUa(5>LR zhD4OcBwjW5r+}pays`o)i$rcJb2MHLGPmeOm<ly?oC3vz<dWPHJ2q*qSfdfjHs3pG z8wPe2f#fdLSh@|^lKvdXF_&GOvjikbVR#Qzr>t5XJDg@(O3PCbxdDn{6qqb09X44T zh6I|s=lM6Nr#cGaA5-eq*T=LQ6SlRq*`~`b+dVi5^>el1p;#si6}kK}<i{_X0}mow zhl0h@WibK^GtE>>w;1<WXe4=aU)VR4iAjHDbqV1&<YPjvBdJ|}-XxnB?Tstau<Hfq zCRRqz_iBQn`XqE$^y`!_by;iY`BF&pW5CL^OWe?LiOxoGT#Y$s(kmFjDXs&p?eit> z6B1dz{q_;PY{>DBQ+v@1pfXTd5a*^H9U*;qdj@XBF}MoSSQxVXeUpEM5Z0909&<Re zk3I+&OO%J-Z}&=p!z(}*pf~$i%5?5}NgAE2OZE4Z<X!Mwp;tlq>8$pRfR|B(t0<lD zFs$q_Z$Z*zi1c&2E;a}s$0i^wl);}>ox&xl8{8mUNd#(zWONW{oycv$VjP1>q;jU@ z@+8E~fjz*I54OFFaQ{A5jn1w>r;l!NRlI(8q3*%&+tM?lov_G3wB`<}bQ>1=&xUht zmti5VZzV1Cx006Yzt|%Vwid>QPX8Nfa8|sue7^un@C+!3h!?-YK>lSfNIHh|0kL8v zbv_BklQ4HOqje|@Fyxn%IvL$N&?m(KN;%`I$N|muStjSsgG;gP4Smgz$2u(mG;DXP z<GLhq%Frtu7l<`vL?~}D33W@?AQ|QM%-T&P!X7*@ooXAv3j4ICG}mO0p_It|>f~uQ z212x^l6!MW>V@ORUGSFLAAjz3i5zO$=UmD_zhIk2OXUz^LkDLWjla*PW?l;`LLos> z7FB<H#U>vCr)#)XBByDm(=n%{D>BcUq>0GOV9`i-(ZSI;RH1rdrAJ--f0uuAQ4odl z_^$^U_)0BBJwl@6R#&ZtJN+@a(4~@oYF)yG+G#3=)ll8O#Zv3SjV#zSXTW3h9kqn* z@AHL=vf~KMas}6{+u=}QFumr-!c=(BFP_dwvrdehzTyqco)m@xRc=6b#Dy+KD*-Bq zK=y*1VAPJ;d(b?$2cz{CUeG(0`k9_BIuUki@iRS5lp3=1#g)A5??1@|p=LOE|FNd; z-?5MLKd-5>yQ7n__5W^3C!_`hP(o%_E3BKEmo1h=H(7;{6$XRRW6{u+=oQX<((xAJ zNRY`Egtn#B1EBGHLy^eM5y}Jy0h!GAGhb7gZJoZI-9WuSRw)GVQAAcKd4Qm)pH`^3 zq6EI<JY+MFM(eM!0?iX661nT9c-t~th~b`G4v9)PjuBkKR2nRDgO!=Je!Yr0&>M}Q zxZGx%aLnNP1an=;o8p9+U^>_Bi`e23E^X|}MB&IkS+R``plrRzTE%ncmfvEW#AHJ~ znmJ<w+?(s0eKb5NC>`x&ez6<V)q+T?(ZD{dXt<5#hyU$KG!X$+$^9Yvvrs%2XHa28 z9mW3uNXoj}%%{F;7@vhx@XEris%fqkwras~!0d4n)^sr~-v)u>eT21aLnoI`%pYYj zzQ?f^ob&Il;>6Fe>HPhAtTZa*B*!;;foxS%NGYmg!#X%)RBFe-acahHs3nkV61(E= zhekiPp1d@ACtA=cntbjuv+r-Zd`+lwKFdqZuYba_ey`&H<<cYk$0c=kGPn9qVEX_6 zdd&agdUKm^NSclQfBqr<G?7flcPt3|cAET?xcXoI=>Psu;Tzwt;-LQxvv<_D5;ik7 zwETZe`+voUhk%$s2-7Rqfl`Ti_{(fydI(DAHKr<66;rYa6p8AD+NEc@Fd@%m`tiK% z=Mebzrtp=*Q%a}2UdK4J&5#tCN5PX>W=(9rUEXZ8yj<Mqef_Wl-7%VtnZS%Z2oI}3 zt4>Ru+7<Rn6ogv&Yd+l%+cl%5G3&xkOLP84>)mFpKh{6;n%!bI(qA9kfyOtstGtOl zX!@*O0fly*L4k##fsm&V0j9Lj<_vu1)i?!<L;E`x9lME^PJK;H0I38a2~ay-IQtaM zP*qOEwu?>#xTB7@2H&)$Kzt@r(GH=xRZlIimTDd_o(%9xO388LwC#;vQ?7OvRU_s< zDS@6@g}VnvQ+tn(C#sx0`J^T4WvFxYI17;uPs-Ub{R`J-NTdtBGl+Q>e81Z3#tDUr ztnVc*p{o|RNnMYts4pdw=P!uJkF@8~h)oV4dXu5F7-j0AW|=mt!QhP&ZV!!82*c7t zuOm>B*2gFtq;A8ynZ~Ms?!gEi5<{R_8tRN%aGM!saR4LJQ|?9w>Ff_61(+|ol_vL4 z-+N>fushRbkB4(e{{SQ}>6@m}s1L!-#20N&h%srA=L50?W9skMF9NGfQ5wU*+0<@> zLww8%f+E0Rc81H3e_5^DB@Dn~TWYk}3tqhO{7GDY;K7b*WIJ-tXnYM@z4rn(LGi?z z8%$wivs)fC#FiJh?(SbH-1bgdmHw&--rn7zBWe1xAhDdv#IRB@DGy}}zS%M0(F_3_ zLb-pWsdJ@xXE;=tpRAw?yj(Gz=i$;bsh&o2XN%24b6+?_gJ<Kq?WDXDfm(x!QEt~n zRKS&jm1iAmM3}~9QQzG(ufO3+`TI6D9BPg(#U0I6R;fichT{&%oANc!_k+QyVUA0X zJ;y~@dMky&r&t(&yTq9QF`8JqVvCIcJ)sePA7<JG&$d^_3Hci6_0j&Ey^t-_>DBeY zws3PE2u!#Cec>aFMk#ECxDlAs;|M7@LT8)Y4(`M}N6IQ{0YtcA*8e42!n^>`0$LFU zUCq2IR2(L`f++=85M;}~*E($nE&j;p<yY{=u)t50<zfGuPfQVrd32XaZr0TmMx8R* z@*(HUfN5jM$WN2oIfF}JMksU=KGZ1F5M)`z_dNIl$F|R02`>{l%xchiTau*tB9bI= zn~Ygd@<+9DrXxoGPq}@vI1Q3iEfKRleuy*)_$+hg?+GOg<A}r`+}E9+ehEFhD$oVf z7<m>f1r?d@Or42|s|D>XMa;ebr1uiTNUq@heusd6%WwJqyCCv!L*qou9l!B22H$bQ z)<)IA>Yo77S;|`fqBk!_PhLJEQb0wd1Z|`pCF;hol!34iQYtqu3K=<LO71guVa`H& zP~U?liGQ}(w`Ce;)(XleA+f1HnQZeuVKVi3e|?4RrOGyn8>$QxLW7(HFx~v>`vVRr zyqk^B4~!3F8t8Q_D|GLRrAbbQDf??D&Jd|mgw*t1YCd)CM2$76#Cqj1bD*vADwavp zS<`n@gLU4pwCqNPsIfHKl{5}g<GJ0o#1j?jNyIHMj<CvGpYQW1g$p7}ff8O1($ZwA zM5*w6_w!_W(47!a@lfhj-LO=sv{0AgO+p&pD7RH8U0ABe3klJGcA#Ocb>u9t-o+O< z??!fMqMrt$s}02pdBbOScUrc1T*{*-ideR<m2e=AZal*{t}%C93t*O6?ie5So=e1) z%(avX4jGAsQT|{)jC-)iD|Zh3MH`Qb&c4gk`a!C>6(1q4@oC6mxg8v8Y^h^^hfx6| z|Mld6Ax1CuSlmSJmHwdOix?$8emihK#&8&}u8m!#T1+c5u!H)>QW<7&R$eih)xkov zHvvEIJHbkt+2KQ<-bMR;2SY<W%^(e<vyQcTKPTbhPZ1>X?8SI=_<-J!GD5@P2FJ}K z5u82YFotCJF(dUeJFRX_3u8%iIYbRS??A?;iVO?84c}4Du9&jG<#urlZ_Unrcg8dR z!5I3%9F*`qwk#joKG_Q%5_xpU7|jm4h0+l$p;g%Tr>i74#3QnMXdz|1l2MQN$yw|5 zThMw15BxjWf2{KM)XtZ+e<wJY-!H0vjG6iWB)tDV08z-+*6I6c)VKS`B*Sk5{69vn z{5u6TN@?QT1&qSG(CW-s93-GMUJ%qgOA@PD3u_>#N)ihlkxPe=5ymT9>@Ym%_LF}o z1XhCP`3E1A{iVoHA#|O|&5=w;=j*Qf`;{mBAK3={y-YS$`!0UmtrvzHBfR*s{z<0m zW>4C=%N98hZlUhwAl1X`rR)oL0&A`gv5X79??p_==g*n4$$8o5g9V<)F^u7v0Vv^n z1sp8{W@g6eWv2;A31Rhf5j?KJhITYfXWZsl^`7z`C<F;2vYEX$)O-o}#)bE%Mbj#_ zXvXs}1>FtnFrHUWiD?$pwU6|PQjs|7RA0o9ARk^9$f`u3&C|#Z3iYdh<0R`l2`)6+ z6tiDj@xO;Q5PDTYSxsx6n>bj+$JK8IPJ=U5#dIOS-zwyK?+t^V`zChdW|jpZuReE_ z)e~ywgFe!0q|jzsBn&(H*N`%AKpR@qM^|@qFai0};6mG_TvXjJ`;qZ{lGDZHScZk( z>pO+%icp)SaPJUwtIPo1BvGyP8E@~w2y}=^PnFJ$iHod^JH%j1>nXl<3f!nY9K$e` zq-?XYl)K`u*cVXM=`ym{N?z=dHQNR23M8uA-(vsA$6(xn+#B-yY!CB2@`Uz({}}w+ z0sni*39>rMC!Ay|1B@;al%T&xE(wCf+`3w>N)*LxZZZYi{5sqiVWgbNd>W*X?V}C- zjQ4F7e_uC<rrMQOhnlaly82U^Bnjl*Ps^;dHP4)`o{y`Br!oGok57zV%6AfCzrx6b zRtkN#-_l5Q6R888F!*RBowS6c#F3(y>UOHbtewQkq?m$*#@ZvWbu{4i$`aeKM8tc^ zL5!GL8gX}c+qNUtUIcps1S)%Gsx*MQLlQeoZz2y2OQb(A<DL3;)MXXTQ`RBN=2Nqo zm|%J=&6B(G>73Jc3`LmlQf0N{RTt;wa`6h|ljX1V7UugML=W5-STDbeWT<mSwJhXL z!aS2TX&k8S`&e){@?u0)ndhS|I5*P`AXfL2^cmXY+Y4+;A$3^)gf$wPi}{Qvn3?Ry z7vEE&$5<Ru_Q#P8!_=cYOw%AF1OLsyT<5t8ut0pRH0SVIuwRf%vxrV$xV&O$O=zu4 zELRNs*8N_EW5BHpx`+}r&eA)WZcQ>iEMjPQ$({hn_s&NDXz<!=4N<vgMcI^yn~Zh` zwvKP>s6?PLySp$?L`0ilH3vCUO{JS0Dp`z;Ry$6}R@1NdY7rxccbm$+;ApSe=2q!0 z()3$vYN0S$Cs)#-OBs{_2uFf}L4h$;7^2w20=l%5r9ui&pTEgg4U!FoCqyA<B2GjD zdx)l4;&dHHVJdZ^Xw&qfECp24<|xWqw2<&|dxV~DnR~Oku@x1r5LF<ueYl&b5>6r2 zC5s72l}i*9y|KTjDE5gVlYe4I2gGZD)e`Py2gq7cK4at{bT~DSbQQ4Z4sl)kqXbbr zqvXtSqMrDdT2qt-%-HMoqeFEMsv~u)-NJ%Z*ipSJUm$)EJ+we|4*-Mi900K{K|e0; z1_j{X5)a%$+vM7;3j>skgrji92K1*Ip{SfM)=ob^E374JaF!C(cZ$R_E>Wv+?Iy9M z?@`#XDy#=z%3d9&)M=F8Xq5Zif%ldIT#wrlw(D_qOKo4wD(fyDHM5(wm1%7hy6euJ z%Edg!>Egs;ZC6%ktLFtyN0VvxN?*4C=*tOEw`{KQvS7;c514!FP98Nf#d#)+Y-wsl zP3N^-Pnk*{o(3~m=3DX$b76Clu=jMf9E?c^cbUk_h;zMF&EiVz*4I(rFoaHK7#5h0 zW7CQx+xhp}Ev+jw;SQ6P$QHINCxeF8_VX=F3&BWUd(|PVViKJl@-sYiUp@xLS2NuF z8W3JgUSQ&lUp@2E(7MG<OQ<1?G8Oxn1mPIGm|_f4YK>`sh4X!LQFa6;lInWqx}f#Q z4xhgK1%}b(Z*rZn=W{wBOe7YQ@1l|jQ|9ELiXx+}aZ(>{c7Ltv4d>PJf7f+qjR<fc zzR_{hk@QY1I>U8i%XZZFJkj&6D^s;!>`u%OwLa*V5Js9Y$b-mc!t@{C415$K38iVu zP7!{3Ff%i_e!^LzJWhBgQo=j5k<<($$b&%%Xm_f8RFC_(97&nk83KOy@I4k?(k<(6 zthO$3yl&0x!Pz#!79bv^?^85K<UzI_1JfNcJfpb(WrpN_?tYT4KP^sShAp~8Y=Yws zA@JeU`}g*o&VzCDoSv8w<0m@Te#}RYK=_*+uR+WvQh1{$#1D!v7brY3q!8^<WIBmB zlc38GyC2MM5lZ=XHVy=Dh?$PiUm%y}K+T{hTd#Tq;{u8ES9|k;|6DUQQ~dPK|Bj{e z-yh=tI;M(zBiyWP^^N}hb?O}{`wysi@QxX46O{{n0Q3r2R{;O6khWXEYRD>5e7uS$ zJ33yka2VzOGUhQXeD{;?%?NTYmN3{b0|AMtr(@bCx+c=F)&_>PXgAG}4gwi>g82n> zL3DlhdL|*^WTmn;XPo62HhH-e*XIPSTF_h{#u=NY8$B<fbww+h*xf==B0x6v(_G?& z!09&2Mgs&r58WroXO=@73B$sl<)3NA_!ZVqwBIT1>UW=5@PD{P5n~g5XDg?Fzvb_u ziK&CJqod4srfY2T?+4x@)g9%3%*(Q2%YdCA3yM{s=+QD0&IM`8k8N&-6%iIL3kon> z0>p3BUe!lrz&_ZX2FiP%MeuQY-xV<vshB><n!bv2W_v>V%K?=bGPOM&XM0XRd7or< zy}jn_eEzuQ>t2fM9ict#ZNxD7HUycsq76IavfoNl$G1|t*qpUSX;YgpmJrr_8yOJ2 z(AwL;Ugi{gJ29@!G-mD82Z)46T`E+s86Qw|YSPO*OoooraA!8x_jQXYq5vUw!5f_x zubF$}lHjIWxFar8<GeFf9-V5`nyfk8^M5y!M_OoGbS<;@bkn%`fT<BaStsh=v0+@5 zOcC73N9RyOeoa>)tTg8z-FEz)a=xa`xL~^)jIdezZsg4%ePL$^`VN#c!c6`NHQ9QU zkC^<0f|Ksp45+YoX!Sv>+57q}Rwk*2)f{j8`d8Ctz^S~me>RSakEvxUa^Pd~qe#fb zN7rnAQc4u$*Y9p~li!Itp#iU=*D4>d<Ci>vJ{Z~}kqAOBcL8ln3YjR{Sp!O`s=5yM zWRNP#;2K#+?I&?ZSLu)^z-|*$C}=0yi7&~vZE$s``IE^PY|dj^HcWI$9ZRm>3w(u` z-1%;;MJbzHFNd^!Ob!^PLO-xhhj@XrI81Y)x4@<gMtV_Y5Go*HbFejp#(E*>FdsI( za`o4Gy(`T$P?PB?s>o+eIOtuirMykbuAi65Y_UN1(?jTCy@J8Px`%;bcNmPm#Fr!= z5V!YViFJ!FBfEq>nJFk0^RAV1(7w+X<r55RW+Y)^S4T<DuFltq?k*3hd&xYsSj2B& zUGX;nxg;#xjm8VFJ3>`HRgP;nJHJdMa!}&vvduCMoslwHTes_I76|h>;(-9lbfGnt zoZom<C?fEb8E8pWCy|-@u{HxBzv)p1MMq};qNB?SI|@9&P6^gO<;M*Bytc@_K~04{ z;AwbRq5D5P(<L_6N9;<Uu?iTHtN4K;8c}I#KqwaH1qMUHKO}r&^w)OUAS0!WB?-XI zrh7E_KOqY}fSQ15Wq<fRKF}+ChGgSi!dwd$-K{x_m@y;3e?VEQrhW;@$QT-V1=~Rc zBoP7r3KOd#ifEufE=S{`jX+2nWI7w9J4?El&r6%hx-hp!CK|B^D%OJ?TF7K$mo!0< zB3|TLdvs$Z>akOt7<zd8GJ~gO+}ci6N;r4aCNk+Od?kJbIVo(1&oUbk)6HY`TXIq= zqUjdch<xQHvfMhy%lGY0+*M8unTxdt(vP2$mb?<CzZfCG?nUX4KnjU9MrRlaDN3vm zp_4jfRuMx5c+|-5^D1H-X8if1gpxo_C>59AuTX4b$)G8TzJ&m*BV8!vMs9#=e0tWa z%<kVjvU5}5jenPuQ3M}mcKL_0sC!*NdRI6Mjlj77o>)84R=3?tfh72~=Rc;fXwj+x z+25xapYK@2@;}6)@8IL+F6iuJ_B{&A-0=U=U6WMbY>~ykVFp$XkH)f**b>TE5)shN z39E2L@JPCSl!?pkvFeh@6dCv9oE}|{GbbVM!XIgByN#md&tXy@>QscU0#z!I&X4;d z&B&ZA4lbrHJ!x4lCN4KC-)u#gT^cE{Xnhu`0RXVKn|j$vz8m}v^%*cQ{(h%FW8_8a zFM{$PirSI8@#*xg2T){A+EKX(eTC66Fb})w{vg%Vw)hvV-$tttI^V5wvU?a{(G}{G z@ob7Urk1@hDN&C$N!Nio9YrkiUC{5qA`KH*7CriaB;2~2Od>2l=WytBRl#~j`<pdG z4M}tb<uU%2ridMFfC^+i<L~BM1~RL!4p+A^)XrawXV{TA-9EIXauS*Dg}JdVIEw4f z`Ulf7uYtc(vYyEo44G0z5l@5cL?;sbE&RWE2C2qxrkkaRYU_fPr>EYsj}jqK2xD*3 ztEUiPZzEJC??#Tj^?f)=sRXOJ_>5aO(|V#Yqro05p6)F$j5*wYr1zz|T4qz$0K(5! zr`6Pqd+)%a9Xq3aNKrY9843)O56F%=j_Yy_;|w8l&RU1+B4;pP*O_}X8!qD?IMiyT zLXBOOPg<*BZtT4LJ7DfyghK|_*mMP7a1>zS{8>?}#_XXaLoUBAz(Wi>$Q!L;oQ&cL z6O|T6%Dxq3E35$0g5areq9$2+R(911!Z9=wRPq-pju7DnN9LAfOu3%&onnfx^Px5( zT2^sU>Y)88F5#ATiVoS$jzC-M`vY8!{8#9O#3c&{7J1lo-rcNK7rlF0Zt*AKE(WN* z*o?Tv?Sdz<1v6gfCok8MG6Pz<GK)kM#Fa}sldEi&546xI(*0gn=!^c0Tb?>ecx9?C zrQG5j^2{V556Hj=xTiU-seOCr2ni@b<&<!)7uosgxZ*i0qYym72`j<}Tyrcivr8hF zTWq=6QQ);+$xc~E4QH2u0lmUt^J?RB2;UgtoqnRS3b?LRcZe%+5j^7dPEf<r=xdOY zyy(>!j><hqkK&LV11o%uPE<DDKhW(+;>GyHbv!&uBbHjH-U5Ai-UuXx0lcz$D7%=! z&zXD#Jqzro@R=hy8bv>D_CaOdqo6)v<Hr<wD^7>FjZldma5D+R;-)y1NGOFYqEr?h zd_mTwQ@K2veZTxh1aaV4F;YnaWA~|<8$p}-eFHashbWW6Dzj=3L=j-C5Ta`w-=QTw zA*k9!Ua~-?eC{Jc)xa;PzkUJ#$NfGJOfbiV^1au;`_Y8|{eJ(~W9pP9q?gLl5<hv` zq-R>E6|e{xkT@s|Ac;yk01+twk_3nuk|lRu{7-zOjLAGe!)j?g+@-;wC_=NPIhk(W zfEpQrdR<hjW6irILMx?a`MP52iT|l<EuL}y=FO+aN8oz%Xw$R#i}Pd~QvUs-FEq>y z^Q$YBs%>$=So>PAMkrm%yc28YPi%&%=c!<}a=)sVCM51j+x#<2wz?2l&UGHhOv-iu z64x*^E1$55$wZou`E=qjP1MYz0xErcpMiNYM4+Qnb+V4MbM;*7vM_Yp^uXUuf`}-* z_2CnbQ);j5;Rz?7q)@cGmwE^P>4_u9;K|BFlOz_|c^1n~%>!uO#nA?5o4A>XLO{X2 z=8M%*n=IdnXQ}^+`DXRKM;3juVrXdgv79;E=ovQa^?d7wuw~nbu%%l<Xf~?N3{;D$ zdjm^~#KJ}13CHdp-*t*f#IzP~WB3Yc+<O@T)t>sjUugE8HJ9zvZIM^nWvjLc-HKc2 zbj{paA}ub~4N4Vw5oY{wyop9SqPbWRq=i@Tbce`r?6e`?`iOoOF;~pRyJlKcIJf~G z)=BF$B>YF9>qV#dK^Ie#{0X(QPnOuu((_-u?(mxB7c9;LSS-DYJ8Wm4gz1&DPQ8;0 z=Wao(zb1RHXjwbu_Zv<=9n<XR?{HbR^Dll@oqz*Z3oqz|IZQaMx#n2R2moU-^D<z- zga}0seGM5-bTV&hZd771e5gI3t`$^>jK28sS}WssjOL!3-E5>d17Lfnq0V$+IU84N z-4i$~!$V-%Ik;`Z3MOqYZdiZ^3nqqzIjLE+zpfQC+LlomQu-uNCStj%MsH(hsimN# z%l4vpJBs_2t7C)x@6*-k_2v0FOk<1nIRO3F{<KiOBUP%D=G#h*?adbA>E?2DnS}w> z#%9Oa{`RB5FL5pKLkg59#x~)&I7GzfhiVC@LVFSmxZuiRUPVW*&2ToCGST0K`kRK) z02#c8W{o)w1|*YmjGSUO?`}ukX*rHIqGtFH#!5d1Jd}&%4Kc~Vz`S7_M;wtM|6PgI zNb-Dy-GI%dr3G3J?_yBX#NevuYzZgzZ!vN>$-aWOGXqX!3qzCIOzvA5PLC6GLIo|8 zQP^c)?NS29hPmk5WEP>cHV!6>u-2rR!tit<H6K<`F|-L2nvu=hj?^+`eij=B<V}b@ z@B)puoO3cGGxU^niF+;tL-h54X~zdAd5S??I#`w|&&6~3d&$7VkMDU-6b_LMwminU z$6hC<ZypQN)Rld1_YatN&gKL*aM%5O&gsK9^UqsYJ)vc9izs}?3Oc+6fuC6t9H`OC zokZOqyS@s3%8l{A-KTu#<)|R8KfY`!NKd>#F6`_;%4{q^6){_CHGhvAs=1X8Fok+l zt&mk>{4ARXVvE-{^tCO?inl{)o}8(48az1o=+Y^r*AIe%0|{D_5_e>nUu`S%zR6|1 zu0$ov7c`pQEKr0sIIdm7hm{4K_s0V%M-_Mh;^A0*=$V9G1&lzvN9(98PEo=Zh$`Vj zXh?fZ;9$d!6sJRSjTkOhb7@jgSV^2MOgU^s2Z|w*e*@;4h?A8?;v8JaLPCoKP_1l- z=Jp0PYDf(d2Z`;O7mb6(_X_~z0O2yq?H`^c=h|8%gfywg#}wIyv&_uW{-e8e)YmGR zI0NNSDoJWa%0ztGzkwl>IYW*DesPRY?oH+ow^(>(47XUm^F`fAa0B~ja-ae$e>4-A z64lb<us@kdtAYl$q}T24sw~n@T~wTnN38G!o-w}D+ML3`i~B`pnM`W>_;|W0ppKI+ zxu2VLZzv4?Mr~mi?WlS-1L4a^5k+qb5#C)ktAYGUE1H?Vbg9qsRDHAvwJUN=w~AuT zUXYioFg2Dx-W)}w9VdFK#vpjoSc!WcvRZ_;TgHu;LSY*i7K_>Px{%C4-IL?6q?Qa_ zL7l=EEo|@X&$gX;fYP02qJF~LN9?E-OL2G(Fo4hW)G{`q<UNTVyu{YECrRdQW8>nW zTIuc+-1VJvKgph0jAc(LzM);Pg$MPln?U|ek{_5nNJHfm-Y#ec+n#Yf_e>XfbL<Jj zC4<j?s_P+<9*S#zb-*>bN)eqHEDr0#?<;TskL5-0JGv|Ut{=$Xk8hlwbaMXdcI3GL zY-hykR{zX9liy$Z2F3!z346<C_U+V9&~+9_ThfF;_W=t2C&Z*UOnbsL(`lg7Y_9mJ z;x7x7msWl4Kb@@$yKgTE5^PM^6EXwa%=X!zvj`?R^UpwmF%I*&db9Mf*}H~d_$T0q zJoI|73QSz<E7i=;AOnv*#a{snA^{$tEWm9D%Wo|FR=1KqgS+BG;5mCU#nURc7oq_o z-O{0O`-W6(TF8B|;h9i-$1&@yllU>uu%9@-y6Gda`X2*ixlD_P@<}K?AoV?(%lM%* z(xNk=|A()443aGj)-~I<t=+b5+qP|cw{6?DZQHi(?%l@p+<VT%oIB@CM6Fs;Kk7%t z%J?!X^U3#ByqT%i5eJsK{B+>Df3J+UA2p2lh6ei^pG*HL#SiThnIr5WZDXebI)F7X zGmP-3bH$i$+(IwqgbM7h%G5oJ@4{Z~qZ#Zs*k7eXJIqg;@0kAGV|b=F#hZs)2BYu1 zr8sj#Zd+Iu^G}|@-dR5S*U-;DqzkX3V0@q-k8&VHW?h0b0?tJ-Atqmg^J8iF7DP6k z)W{g?5~F*$5x?6W)3YKcrNu8%%(DglnzMx5rsU{#AD+WPpRBf``*<8F-x75D$$13U zcaNXYC0|;r&(F@!+E=%+;bFKwKAB$?6R%E_QG5Yn5xX#h+zeI-=mdXD5+D+lEuM`M ze+*G!zX^xbnA?~LnPI=D2`825Ax8rM()i*{G0gcV5MATV?<7mh+HDA7-f6nc@95st zz<x3S-=O9@1Qx`EDk(L<enRy4$&H~91Dqvi*j`&df5YvnJ92?*;!1D{y*{vSKT#)! z`8&J6_mr>C_si$<QVr`<>{|&=$MUj@n<ZkLuF(toIVKp(6>Lxl_HwEXb2PDH+V?vg zA^DJ<z&3Iv0y>%dn069O9<Ouc(<|V99`h3|>TNK-jV}cQKh|$L4&Uh`?(z$}#d+{X zm&=KTJ$+KvLZv-1GaHJm{>v=zXW%NSDr8$0kSQx(DQ)6<U)@wRatQ0n^IU+=Y(tsk z>S?%sWSHUazXSEg_g3agt2@0nyD?A?B%9NYr(~CYX^&U#B4XwCg{%YMYo<flw!Uv7 zbJrd*bK4--;t<&j37ZT@jUbZ8-Qk8uL-t5+XilHP`7ykYb{?`@R8n-Wi%nqiF#0hx zPg@t)?pcqM%L}PMzv3OTb>%e68HVJ7`9KR`mE*Wl7&5t71*R3F>*&hVIaZXaI;<mI z|Ap3H0(aXS@X(VR*Ol`mi%np^ZEHYHRc@ElhxGOh`)3v}+0ls>2a$?;{Ew{e3Hr1* zbf$&Fyhnrq7^hNC+0#%}n^U2{ma&eS)7cWH$bA@)m59rXlh96piJu@lcKl<>+!1#s zW#6L5Ov%lS(?d66-(n`A%UuiIqs|J|Ulq0RYq-m&RR0>wfA1?<34tI?MBI#a8lY{m z{F2m|A@=`DpZpwdIH#4)9$#H3zr4kn2OX!UE=r8FEUFAwq6VB?DJ8h59z$GXud$#+ zjneIq8uSi&rnG0IR8}UEn5OcZC?@-;$&Ry9hG{-1ta`8aAcOe1|82R7EH`$Qd3sf* zbrOk@G%H7R`j;hOosRVIP_2_-TuyB@rdj?(+k-qQwnhV3niH+CMl>ELX(;X3VzZVJ ztRais0C^L*lmaE(nmhvep+peCqr!#|F?iVagZcL>NKvMS_=*Yl%*OASDl3(mMOY9! z=_J$@nWpA-@><43m4olSQV8(PwhsO@+7#qs@0*1fDj70^UfQ(ORV0N?H{ceLX4<43 zEn)3CGoF&b{t2hbIz;Og+$+WiGf+x5mdWASEWIA*HQ9K9a?-Pf9f1gO6LanVTls)t z^f6_SD|>2Kx8mdQuiJwc_SmZOZP|wD7(_ti#0u=io|w~gq*Odv>@8JBblRCzMKK_4 zM-uO0Ud9>VD>J;zZzueo#+jbS7k#?W%`AF1@ZPI&q%}beZ|ThISf-ly)}HsCS~b^g zktgqOZ@~}1h&x50UQD~!xsW-$K~whDQNntLW=$oZDClUJeSr2$r3}94Wk1>co3beS zoY-7t{rGv|6T?5PNk<Z}${YyAJWnFYd_(8lLGvKygk2|9Q-+MgjJ$&KDpf_$YQ?IV zR<<Gym6HGU;;bqndvCX&FnDKQ=}UsHCpxg@6}a(-T<EY&D8er_EV=18JTgdg;NT>Y zj*XjF()ybvnVz5=BFnLO=+1*jG>E7F%&vm6up*QgyNcJJPD|pHoZ!H6?o3Eig0>-! zt^i-H@bJ;^!$6ZSH}@quF#RO)j>7A5kq4e+7gK=@g;POXcGV28Zv$jybL1J`g@wC# z_DW1ck}3+n@h2LFQhwVfaV@D+-kff4cel<IcrWN-M5x8!Ow)bPrn9?d=kx(pB}Zxh zwSayS{c`WwwOA@rCTI0Jpf!LQ0BRAS&Yy^!S}_9)?rVFlb`0@yQL-u&w?3z@i}YtX z&orQmrCH2ERpv_}L+8*5x0r*ar=W0%g{;gnuf;Y%mP^vf>ZC0;0e<L_F@Y}Mun9fT z3*0k%P9JzWMDIiaJzHp78U80rEHg<Jm$kJ?b#g(IM#`$0x_Y_c_XAFK5m}j&*?B9q zSa0I1M-ZM%K;M9EzJ}%_K>f?pA#*PPd8Kk8sO1wza&BHQFblVU8P1=-qScHff^^fR zycH!hlHQs7iejITpc4UaBxzqTJ}Z#^lk{W(cr`qtW~Ap;HvuUf#MxgEG?tEU+B?G% znu<!7LIgR13M|s?%o25M!Ve^n&=M7iB|RnrBtHAJ6<h+az+`2J^UgIdUBonl2DJ}4 zu`>b0I(s@XvI(lva}$Z7<}Qg=rWd5n)}rX{nb+Aw;}?l9LZI-`N-*hts=c6XgjfJs ztp>-686v6ug{glEZ}K=jVG|N1WSWrU*&ue|4Q|O@;s0#L5P*U%Vx;)w7S0ZmLuvwA z@zs2Kut)n1K7qaywO#TbBR`Q~%mdr`V)D`|gN0!07C1!r3{+!PYf9*;h?;dE@#z(k z;o`g~<>P|Sy$ldHTUR3v=_X0Iw6F>3GllrFXVW?gU0q6|ocjd!glA)#f<BmJPFLB} zEhYST*M)esm5(_%C4PWZ`=77E`8iyIH2-_uviC}ybZBAkkU&oTXd<qb;^^X8)}WK^ zZ7VNp$iQ33bjEa{enF`vr_fcnpn5o$xWG}@)wW01agAanwm7U-_6$&kb?+oC`!H4+ z&pP-ziAbnW{HLL*!kOtg5&^#>0G7i20ly>qxRljgfO2)RVpvmg#BSrN)GbGsrIb}9 z1t+r;Q>?MGLk#LI5*vR*C8?<QWz^KoEAbUtRx5!VLSb(M>McB|=AoAjuDk&Pn`KQo z`!|mi{Cz@BGJ!TwMUUTkKXKNtS#OVNxfFI_Gfq3Kpw0`2AsJv9PZPq9x?~kNNR9BR zw#2jp%;FJNoOzW<aW@Re3s=7#KmRWefd}w)30vR+&FhD2(gU`Fzb()i9D)B9j6NR7 zkJkCe-V+Ma{GvGf>>tE#zskPICp>XSs?|B0E%DaJH)rtLA}$Y>?P+vEOvr#8=pylh zch;H3J`RE1{97O+1(1msdshZx$it^VfM$`-Gw>%NN`K|Tr$0}U`J?EBgR%bg=;et0 z_en)!x`~3so^V9-jffh3G*8Iy6sUq=uFq%=OkYvHaL~#3jHtr4sGM?&<HYL8mdfSx ztkF3uXPD7B%V!)xiIi#%hUfzhNcr^0s8kh=m867SDXDO+xe{k-jp8#%R!yLQpP$4P zf+D;?r|{x)(t_iuhw-Sf9iN(g5)W$qGm7jNa&s+!+UzY%8B+JZx+Aosvv8kXrU6rb zbQ18o1Dg{bl=D8~XI)Q-KVuC}csZdF-ol*J*r7G~M0*vV{!wbJm+#70TdwI4^jg?I z%o(r?JZMS5y2Jci`m?!x+iXdwln`R~M+kHX0;phyD<h&PZ%FP7M8{whE<vaSf=2n@ zL*m{)inJF%@r0tqzHPZthaV66%Yd~6StFWr<`uzSKz^t?FA@TuzVR~p6~1ziob2qD zQ%Zy{Gz{hEqc|tEc0|+7<RW>uY&U8N1G}QTMdqBM)#oLTLdKYOdOY%{5#Tgy$7QA! zWQmP!Wny$3YEm#Lt8TA^CUlTa{Cpp=x<{9W$A9fyKD0ApHfl__Dz4!HVVt(kseNzV z5Fb`|7Mo>YDTJ>g;7_MOpRi?kl>n(ydAf7~`Y6wBVEaxqK;l;}6x8(SD7}Tdhe2SR zncsdn&`eI}u}@^~_9(0^r!^wuKTKbs-MYjXy#-_#?F=@T*vUG@p4X+l^SgwF>TM}d zr2Ree{TP5x@ZtVcWd3++o|1`BCFK(ja-QP?zj6=ZOq)xf$CfSv{v;jCcNt4{r8f+m zz#dP|-~weHla%rsyYhB_&LHkwuj83RuCO0p;wyXsxW5o6{)zFAC~2%&NL?<TC?7g@ zfqoa;enQ6=kuI+FtDKTp*4K87i40xomn^i4?-U687)dVCvUn@i5Um!YDhz&=8zf3a z*UH64F1?04tzG*#1=sim1h4x8=I0_~0BivP+v+Lk^FOu&1AE%&=MCtDidMqo6t?0> z=mA}szjHKsVSSnH#hM|C%;r0D$7)T`HQ1K5vZGOyUbgXjxD%4xbs$DAEz)-;iO?3& zXcyU*Z8zm?pP}w&9ot_5I;x#jIn^Joi5jBDOBP1)+p@G1U)pL6;SIO>Nhw?9St2UN zMedM(m(T6bNcPPD`%|9dvXAB&IS=W4?*7-tqldqALH=*UapL!4`2TM_{`W&pm*{?| z0DcsaTdGA%RN={Ikvaa&6p=Ux5ycM){F1OgOh(^Yk-T}a5zHH|=%Jk)S^vv9dY~`x zG+!=lsDjp!<Zw<>D}7o94RSQ-o_g#^CnBJlJ@?saH&+j0P+o=eKqrIApyR7ttQu*0 z1f;xPyH2--)F9uP2#Mw}OQhOFqXF#)W#BAxGP8?an<=JBiokg;21gKG_G8X!&Hv;7 zP<bTe@P=slWtf9t{y!Y^e<ETc?nc%wPQRvkq88RB0!Bu^b6pt&TLZKI9P1{lZ8~AA zVgBH1ENoP|cw1DcPRqz@QgYQNgGokM3*xNG9!q77#Av0)In!jXVb{72TcVC`DP;(1 zk+-(Y$?Lo4!^1FLOIH%Rhdh-}(GOz7`~{5l*$>9Vpzm#@;^-lf=6POs>UrGm-F>-! zm;3qp!Uw?VuXW~*Fw@LC)M%cvbe9!F(Oa^Y6~mb=8%$lg=?a0KcGtC$5y?`L5}*-j z7KcU8WT<U{=H%2rUviZgG-R^Il^D(umJq{>>2PpKx<58`m((l9^aYa3uP{PMb)nvu zgt;ia9=ZofxkrW7TfSrQf4(2juZRBgcE1m;WF{v1Fbm}zqsK^>sj=yN(x}v9#_{+C zR4r7abT2cS%Wz$RVt!wp;9U7FEW&>T>YAjpIm6ZSM4Q<{Gy+aN`Vb2_#Q5g@62<R4 zMx$6~v*mbHZfPOwxp<OAlg!hqzrj>uR_>II@eiHaay+JU$J=#>DY9jX*2A=&y8G%b zIY6gcJ@q)uWU^mSK$Q}?#Arq;HfChnkAOZ6^002J>fjPyPGz^D5p<P8nMaP(*LAGP z#-zU2OJ^z3Db=`NZQ>}o;h2VLNTI{HGg!obo3K!*I~a7)p-2Z3hCV_hnY?|6i`29b zoszLpkmch$mJeupLbt4_u-<3k;VivU+ww)a^ekoIRj4IW4S<FRqdy{2RiwFY> z{z%4_dfc&HAtm(o`d{CZ^AAIE5XCMvwQSlkzx3cLi?`4q8;iFTzuBAddTSWjfcZp* zn{@Am!pl&fv#k|kj86e$2%NK1G4kU=E~z9L^`@%2<%Dx%1TKk_hb-K>tq8A9bCDfW z@;Dc3KqLafkhN6414^46Hl8Tcv1+$q_sYjj%oHz)bsoGLEY1)ia5p=#eii(5AM|TW zA8=;pt?+U~<O0(jQ4OX$<Sydbm#~h&)W7v$5#U`FsQ0@Df3>>`|J(B85BKE0cB4n> zWrgZ)Rbu}^A=_oz65LfebZ(1xMjcj_g~eeoj74-Ex@v-q9`Q{J;M!mITVEfk6cn!u zn;Mj8C&3^8Kn%<`Di^~Y%Z$0pb`Q3TA}$TiOnRd`P1XM=>5)JN9tyf4O_z}-cN|i> zwpp9g`n%~CEa!;)nW@WUkF&<|wcWqfL35A}<`YRxV~$IpHnPQs2?+Fg3)wOHqqAA* zPv<6F6s)c^o%@YqS%P{tB%(Lxm`hsKv-Hb}MM3=U|HFgh8R-|-K(3m(eU$L@sg=uW zB$vAK`@>E`iM_rSo;Cr*?&wss@UXi19B9*0m3t3q^<)>L%4j(F85Ql$i^;{3UIP0c z*BFId*_mb>SC)d#(WM1%I}YiKoleKqQs<A5DyhV`a20Ec$*bh4vW6b6#9lSmf~?r* zlcL&gHfFhvg{m>wkdhRt9%_dAnDaKM4IEJ|QK&BnQ@D;i-ame%MR5XbAfE0K1pcxt z{B5_&OhL2cx9@Sso@u2T56tE0KC`f4IXd_R3ymMZ%-!e^d}v`J?XC{nv1mAbaNJX| zXau+s`-`vAuf+&yi2bsd5%xdqyi&9o;h&fcO+W|XsKRFOD+pQw-p^pnwwYGu=hF7& z{cZj$O5I)4B1-dEuG*tU7wgYxNEhqAxH?p4Y1Naiu8Lt>FD%AxJ811`W5bveUp%*e z9H+S}!nLI;j$<*Dn~I*_H`zM^j;!rYf!Xf#X;UJW<0gic?y>NoFw}lBB6f#rl%t?k zm~}eCw{NR_%aosL*t$bmlf$u|U2hJ*_rTcTwgoi_N=wDhpimYnf5j!bj0lQ*Go`F& z6Wg+xRv55a(|?sCjOIshTEgM}2`dN-yV>)W<s8ZX^F)rd_eolw0O4mBB)~DVnQ5dX zh1MfhOJ9Pzd<LR=!m@e-i*a1>f$J58>lNVhjRagGZw?U9#2p!B5C3~Nc%S>p`H4PK z7vX@|Uo^*F4GXiFnMf4gwHB;Uk8X4TaLX4A>B&L?mw4&`XBnLCBrK2FYJLrA{*))0 z$*~X?2^Q0KS?Yp##T#ohH1B)y4P+rR7Ut^7(kCwS8QqgjP!aJ89dbv^XBbLhTO|=A z|3FNkH1{2Nh*j{p-58N=KA#6ZS}Ir&QWV0CU)a~{P%yhd-!ehF&~gkMh&Slo9gAT+ zM_&3ms;1Um8Uy0S|0r{{8xCB&Tg{@xotF!nU=YOpug~QlZRKR{DHGDuk(l{)d$1VD zj)3zgPeP%wb@6%$zYbD;Uhvy4(D|u{Q_R=fC+9z#sJ|I<$&j$|kkJiY?AY$ik9_|% z?Z;gOQG5I%{2{-*)Bk|Tia8n>TbrmjnK+8u*_cS%*;%>R|K|?urtIdgTM{&}Yn1;| zk`xq*Bn5HP5a`ANv`B$IKaqA4e-XC`sRn3Z{h!hN0=?x(kTP+fE1}-<3eL+QDFXN- z1JmcDt0|7lZN8sh^=$e;P*8;^33pN>?S7C0BqS)ow4{6ODm~%3018M6P^b~(Gos!k z2AYScAdQf36C)D`w&p}V89Lh1s88Dw@zd27Rv0iE7k#|U4jWDqo<pw`rT0F1=giby zSvwo-^K5P3?J)*t>UP;-He5cd4V7Ql)4S+t>u9W;R-8#aee-Ct1{fPD+jv&zV(L&k z)!65@R->DB?K6Aml57?psj5r;%w9Vc3?zzGs&kTA>J9CmtMp^Wm#1a@cCG!L46h-j z8ZUL4#HSfW;2DHyGD|cXHNARk*{ql-J2W`9DMxzI0V*($9{tr|O3c;^)V4jwp^RvW z2wzIi`B8cYISb;V5lK}@xtm3NB;88)Kn}2fCH(WRH1l@3<q>XaO7{R*Lc7<o&*hfu zA~y`eH5--g@QhTK;~V;@kFVlBwXL?-xOV}&0LvXLf@G+<_zX>{ZN1m+#&diI7_qzE z?BS+v<)xVMwt{IJ4yS2Q4(77II<>kqm$Jc3yWL42^gG6^Idg+y3)q$-(m2>E49-fV zyvsCzJ5EM4hyz1r#cOh5vgrzNGCBS}(Bupe`v6z{e<CcS{QzMUWAq_nFEe{Vru{6c z|KZrQ|J#+PLzqygyi=3m4BdhVKj0!NsG<U+fK<RKGUFER2&IV8$0<|`B#}lU^@ar> z)cP*a8VCbRuhPp%BUwIRvj-$`3vrbp;V3<u<D|$cxCAE}!0I%pPCYQ!e>wmAUt{?F z0OO?Mw`AS?y@>w%(pBO=0lohnxFWx`>Hs}V$j{XI2?}Btl<q&n{>vIl7!ZMZukDF7 z^6Rq2H*36KHxJ1xWm5uTy@%7;N0+|<>Up>MmxKhb;WbH1+=S94nOS-qN(IKDIw-yr zi`Ll^h%+%k`Yw?o3Z|ObJWtfO|AvPOc96m5AIw;4;USG|6jQKr#QP}+BLy*5%pnG2 zyN@VMHkD`(66oJ!GvsiA`UP;0kTmUST4|P>jTRfbf&Wii8~a`wMwVZoJ@waA{(t(V zwoc9l*4F>YUM8!aE1{?%{P4IM=;NUF|8YkmG0^Y_jTJtKClDV3D3~P7NSm7BO^r7& zWn!YrNc-ryEvh<l>N$$!P%l$Y_P$s8E>cdAe3=@!Igo^0diL6`y}enr`+mQD;RC?w zb8}gXT!aC`%rdxx2_!`Qps&&w4i0F95>;6;NQ-ys;?j#Gt~HXzG^6j=Pv{3l1x{0( z4~&GNUEbH=9_^f@%o&BADqxb54EAq=8rKA~4~A!iDp9%eFHeA1L!Bb8Lz#kF(p#)X zn`CglEJ(+tr=h4bIIHlLkxP>exGw~{Oe3@L^zA)|Vx~2yNuPKtF^cV6X^5lw8hU*b zK-w6x4l&YWVB%0S<MnSL9Gxa+tjTFHHk?^*)Ho+49c->mN<Omsv{<w{M_SX6FrRz& z-fl>{O|!`Sh6H45!7}oYPOc+a#a|n3f%G@eO)N>W!C|!FNXV3taFdpEK*A1TFGcRK zV$>xN<sb#LnQM_qFZRkIc7CDsZFN=(Q&<qDsEKW^u8J}ZvG!S9$V=Gpzacv2#nfBS znUI`V(%8<9w_O9dOzg3pg1KA|xV$L844HD=$^jD7e@tLXu{A?7Q&KD5PmJj(O0Rd} zJ53P3?S>%??ii7jx5D69O>W6O`$M)iQU7o!TPG*+>v6{TWI@p)Yg$;8+W<RxFU`e7 z{bfN`O;EWn(uTD$pTCdDU6G$G0Aqu7uvVLoob|0ph2_mnTUUK%nSix9lQosDs+mxO zQ)7`f=;AM4%2c=yc9`uhF*w;)zK;r4%XrPwRkIJ<^=paRRlSD`dwakGdwU2Bif{P} zfp7I1)Xq0-2F1I22il{2mmE@iA01-nprr3LANk0!$!7K|%&<;M;U1N}-LBaypIar} z*;k|TNIUoLrz6<fTjssa=J@&jpe!_)+(GwYVGQx4+*O=>yE<VTJM=nHJuCiK`4nKF zMjirx-t2fH2j+4NIlyJp!aruMd-O#Tg;Fk{xd%A`<awAfI*L)`XoGXH5K#itZ42AK z6MeknJlNNkn9oZo$LQFbqvB&R31geSNKB|Eazxv7`mmBaie>9DVBMB=vnONSQ6k1v z;u&C4wZ_C`J-M0MV&MpOHuVWbq)2LZGR0&@A!4fZwTM^i;GaN?xA%0)q*g(F0PIB( zwGrCC#}vtILC_irDXI5{vuVO-(`&lf2Q4MvmXuU8G0+oVvzZp0Y)zf}Co0D+mUEZz z<V<U=H+idKcZP;R9F0*dBIp}a_hqpooWwb4eC!W`xqypzPrNaJ>gwR+5y!d(V>s1} zji+mrd_6KG;$@Le2Ic&am6O+Rk1+QS?urB4$FQNyg2%9t%!*S5Ts{8j*&(H1+W;0~ z$frd%jJjlV;>bXD7!a-&!n52H^6Yp}2h3&v=}xyi>EXXZDtOIq@@&ljEJG{D`7Bjr zaibxip6B6M<AvX7F;}xji!{#20`v^r=IX+S_8&y7yMi<{TDCs{)lIgOhlB@q8PxV_ z^K_bV6}m&uNF?(jS7SzI3UW;N4K*THM7W(~LZca^z+Y~4W)ZN|d2h1>f3t#-*Tn7p z96y<T2y#Xcz~YB6wfpE5F$BO)&z2<@Hkm?h8Dj7m{B!BU^}>x1Qv<Gs5lPx{*#im% z@NUr_Fb3h-MOjdYw^i7AWS^$PJ|m%_P(XS98V&Mc6vKJ|E&RDN_MtQRDyP2`@M)J_ zzURj4(W!UW9FwQ-s0z`y>-&r3)4vg`)V~f8>>1_?E4&$bR~uR;$Nz=@U(-vyap|Jx zZ;6Ed+b#GXN+gN@ICTHx{=c@J|97TIPWs(_kjEIwZFHfc!rl8Ep-ZALBEZEr3^R-( z7ER1YXOg<RslpM>Z)&_=`WeHfWsWyzzF&a;AwTqzg~m1lOEJ0Su=C2<{pjK;{d#;E zr2~LgXN?ol2ua5Y*1)`(be0tpiFpKbRG+IK(`N?mIgdd9&e6vxzqxzaa`e7zKa3D_ zHi+c1<wCe5g7HXHML9sFeaTRzfx@YksC+U;4SZXG{&Uk|wK=e(Qcf1Yk{X&1fvGA* zw!EmqXRcWfc`4MVMT4jgS-d7w$hncxD<L9U8AGPq{DMW~K8Ri8c)Yn){n!`p;i$07 z#ata~vsn^kQ0&|_C{SUB&y|DBV~}>`|720|dn(z4Qo<?r+YfX=WYLIOGZslL+F?F4 zhi!IVb|o{L*e^>s^e7sn(PU%NYLv$&!|4kEse%DK;YAD06@XO3!EpKpz!^*?(?-Ip zC_Zlb(-_as+-D?0Ag9`|4?)bN)5o(J=&udAY|YgV(YuK9k=E>0z`$dSaL(wmxd!1f zME&3wwv@#{dgeMlZ4}GL!I`VZxtdQY$lmauCN_|mGXqEEj@i~du$|>5UvLjsbq!{; z@jEf;21iC1jFEmIPE^4gykHQzCMLj=2Ek4&Fvlpq<v&aTHa%PcF6hP3gHi&X2pI7? zRs|zI%My|qVvab#$}>TlS(0YT%*W<<E1qCRKj`*+qHfroZIGFt`*g(JJYczaOq1<p zKFt!ad?rQ1?xU$hd#Daf#$8YO%FRa8%7V3$gbumUdk9LKdg819bwG6c2wOBm-sRf3 zk9p-%EDe8@<aTLV-!^p3VBa}Sh*-o>>XgH$4ww`D`aihBGkPM(&EG};Cl&wzg8!jL z`rkqPzvH(0Kd{2n=?Bt8aAU&0IyiA+V-qnXVId^qG!SWZ7<H3`F5<$(bO%$Qp=Ouz z0`uw>%_f&i!D{R#7Jo$%tICxY%j)ebORE>3H_c|to}c#HX;HAC?~B;2mmQrMp2;8T zmzde!k7BYg^Z1r|DUvSD3@{6<?xk@V&RPeA-iM-8ZEsb)j#bG;>S<1kndb%Qt%GA# z+sB2&F5L`R&fLRdAlp<CTu!?rj!fsBt75|)qNds8l0~UU_sTAt#1ro9U9#V@t%v{g zS~p`@1`lqmQ7Xe0{$&iA%Cw=}sW$W@D1buwqZm@sDSrn29Opri1>U_pVsJsYDEz{^ zKGaAz#%W+MP<N-Fi>GT+D$+xowMY0=ipM)0p?zym&Aoi)qL(pO_weO(k?s|ELHl^W zviJiFUXRL&?`;3_;mvc02A@sbsW9}#{anvGafZ#ST;}za?XS3}ZG3B4m(SW{>w}Fh z)T5Yi*``Tstmi9SHXmuWSND@cj}qtY!`<ld8zkNC^o#qeE@rzNMw=d~@4{g2!$avC zQ^P%PHs572uWdpsxbgC-@j)P-ulQ-Gi|^22tfzZ#6yDtez%L9#=kCGySK)N@h~uhQ z0B`;+FV!{t9e(^#YQcK>tuD29Dpu+-D3$h<5FY>jE>YJvqBmhw?oll`x7Ono(}R~P zle_eBwYy0Rr7kmf_SEt_gn4)AO-r`}^Z5Y%Rm8)K-?X>rvDL+QT?#)QwDsQ2c$tc* z&#hbgkL6}GnBDH;+lREM6MGIskRa@r>5Iq(ll2IepuhW86w@14=E{<t<+{6ok<;kN z^T~21D{HM?r@qkFNVBvE4LX=Bh^3&vy`GF15gN?PGDEag7(}<dp%VeKx#ugmwCCu? zJ2V=NPDtxBDT2j?{(&iY)^Pt3oXGq86vkpxig;CR2_4!QWI79%k-zy;)N)gqK-|A4 zVb>6$cz*cBDQ)CT>}v-DLM-v8)xaPBnmGBKM63RgDGqh!<*j90tSE4|G^+r@#-7g2 zs8KE8eZPZhQuN>wBU%8CmkE9LH1%O;-*ty0&K~01>F3XB>6sAm*m3535)9T&Fz}A4 zwGjZYVea@Fesd=Rv?ROE#q=}yfvQEP8*4zoEw4@^Qvw54utUfaR1T6gLmq?c9sON> z>Np6|0hdP_VURy81;`8{ZYS)EpU9-3;huFq)N3r{yP1ZBCHH7=b?Ig6OFK~%!GwtQ z3`RLKe8O&%^V`x=J4%^Oqg4ZN9rW`UQN^rslcr_Utzd-@u-Sm{rphS-y}{k41)Y4E zfzu}IC=J0JmRCV6a3E38nWl1G495grsDDc^H0Fn%^E0FZ=CSHB4iG<6jW1dY`2gUr zF>nB!y@2%rouAUe9m0VQIg$KtA~k^(f{C*Af_tOl=>vz>$>7qh+fPrSD0YVUnTt)? z;@1E0a*#AT{?oUs#bol@SPm0U5g<`AEF^=b-~&4Er)MsNnPsLb^;fL2kwp|$dwiE3 zNc5VDOQ%Q8j*d5vY##)PGXx51s8`0}2_X9u&r(k?s7|AgtW0LYbtlh!KJ;C9QZuz< zq>??uxAI1YP|JpN$+{X=97Cdu^mkwlB={`aUp+Uyu1P139=t%pSVKo7ZGi_v(0z>l zHLGxV%0w&#xvev)KCQ{7GC$nc3H?1VOsYGgjTK;Px(;o0`ler<o<VsrVl1L=1LKM* zSr?}pX@JohF$RvbE)o+XPI{gtXbe>xB<+EJX9G9f8b+)VJdm(Ia)xjD&5ZL45Np?9 zB%oU;z05XN7zt{Q!#R~gcV^5~Y^gn+Lbad7C{UDX2Nznj8e{)TLH|zEc|{a#idm@z z6(zon+{a>FopmQsCXIs*4-<r1S$vw!O=S8eXuWVM4gE|O22Aim2fuC!E;^(N17hT} z{W>dLGgTc)iOhO3r=l?imNUR-pWl!ktO0r_a0Nqo@bu8MzyjSq9zkqPe*`Sxz75rZ zr9X%(=PVqCRB=zfX+_u&*k4#s1k4OV11YgkCrlr6V;vz<{99HKC@qQ+H8xv5)sc63 z69;U4O&{fb5(fN``jJH#3=GHsV56@{d@7`VhA$K^;GU+R-V%%cnmjYs?>c5^6Ugv} zn<}L&i;2`zzW@(kxf$$gVH@7nh}2%G%ciQ_B?r{13?Q@=Q+6msQGtnyY%Gkjeor?g z7F*tMqLdhcq+LCCo^D;CtOACCBhXgK-M&w{*dcUdmtv@XFTofmmpcWKtCn^`#?oZC zUOm<QC1a)+;H2Zve14RDpR!I0lk^dqc$N^fU^W~mk(jvhB`mqitWKRippxFqPzrU{ zcPfM6W;1_A@B+1@Q@wCoST-~IPavhxX0v(*iG^+o6rBoLe`MUfYuTRB;Z%+q%_7W9 zDL&?t%6o=@-GUYv&qOcCS7Jq%$^0c4k8~_XQ!KC59PkrIAYM@@%s1+f=IQR(V=LHC z%wM}Z{MQ%qgczfQV8NSMu%GZB7+oe2hF7{zwV*g7I@VXaE2gtl5Lew`?N7JwN`c#j zGJ#z(oQM*<PFAKf5l;#Zq5V=H`YZ^zv~o=QTq9#9<5}YZdauuPj}bbDb-O#h*W86q z{H+cAsE<L!pBR4fwL@@pOUY)4uiBz6R{Op7WryS&*zeY}8`$_01z%)k$5aDy6h>52 z7sK$hR|Vh6y&pfIUK&!`8HH*>12$nWA)Y<DeYN6}UOt4|m%_aJ%g>np+XwOj=jNLD z{QA4gezbe>wiP?`jJO;c&EId;=2u80s_r97;TX!6@*(<%WL+^bmxheMB3pKx0OpH^ zPs}knV+jpJ4TaD<VabV^SI2-ELJCb9;Wwo$^++$X&>@r^V`mTsjf`7!z^H}eHQ#Rp z72(>Dm<W>#QO!ZYR*O@yHic`3*T^t7jc=d`Jz6Lk@Y-bL%cOp_<QC7R+MIh7-+O%L zgkh=?9YCZ&fDC@~yOR%d8@e|4j>~=#xzIJl?`{Qu;$uC~NkePE+7wSW_FM`&V{gFN zl;lq@<h8DED3`q8CPI4MvbTi2f`4<t!PvyOM$}BRG$~#ym$=;0)Uz8BkP0g`d^lAB z9eZe|3-spiVr_U=XSM%rOw#PPMg8{~zoT9GxpHsrYSG5L6|SD*G{dhC;l6F~-YLy= zB?kglaDe&CNDBXTu}}wHUGw9c#~06I_<D528$Nj}tcO4&4f#Yc5Pxnklu5?5s<?JI zTX?X2b#fynjR<V^G7jfM0Jg$ROS--~{@zhH2B?r20y{JWsidw#>;FtAsl!h;tnOvj z#gYx!q$5MdZ0Jxjy=t*q)HFeeyI-vgaGdh1QNhqGRy8qS)|6S0QK7Gj9R?Co{Knh> za>xkQZ0}bBx!9@EUxRBYGm25^G}&j-`0VWX04E|J!kJ8^WoZ(jbhU_twFwWIH32fv zi=pg~(b#ajW=`)Vikwwe39lpML?|sY$?*6*kYBxku_<=#$gfTqQ_F!9F0=OkHnzBo zEwR!H_h|MNjuG$Tj6zaaouO}HYWCF8vN4C%EX-%Iu%ho;q$G#ErnafhXR*4J2Rp5* zhsi0;wlSwE*inVFO>{(8?N~82zijpt+9Y_-^>xnE%T*zk9gi|j7b@s<5{|qEquUD( zS;<Fbn&#?PgjjZVRL=q_J}F4-9UJe~sZk`O!nV1J6>-%RySZOCOEh*>!kvbsQ265* z>X8*_Wy&~FB@aDHz%glyiAujXq-|2kDUjFTn9Rafsl+XNyFP%PG|l&ZGWBcEXxy=9 zeDn2PIoVuL$gX0RgVK1O$x3%pOzS7x^U5Pi;mtT)%cY;&e&M7GLM}zP+IPbqLt=^5 z7qLfri8myf;~2psc@^cA6mG&{C%e_(M$$!wC^5p^T1QzrS%I?(U{qcd+oJJkQxe10 zON{Q*?iz%F4MbEsoEc+x3E?&2wVR^v<KUU%<3!et*S>3|Q0lDaMvgS<qzNZgY{&J_ zJ#Tdj1)AtN1=pq6h55{9v@1MyP`7ASP}AyRM+m39hYAl8mQ)&$DGj<r+ecC3#7Be? zWGo%S#WJ%U`uhf^QmjQriQHc6^wTJdf8k-8l4}Q1)_-x!L`3vV7HMb%LW$R1jTiA| z1PwYCHr{Bbfnyi}Nu{MaC-!}p2jdzNqLY)eivRGY9yqhnx@YUeM3`~hN3!}Yd~D;1 zL|a0`$=3U@Xqya5lz32gaS|&AT$~5P4l9f_<fuZ^#NZ$HFh;|sEXaw=`Qa5K$4pL+ zk`kG(wcD?O7{3Hu+25!(ip5h&(aJyZAcBGf8xfw(fBcby%j^P_hiUx#>7mNjI{2w! z9|~=!83T%GW*iaChSS!`Xd^beFp9N4%K+k*j#jFumk}U?=WKL_kJAltxnxp~+lZzT zp@&&kSPTg3oSGos`rVBhK0|4NdHM_hnKuw1#0JV{gi_dKDJLB+ix~~HpU9%jD)@YY zOK)L7kgbLyN2%Dx#fuY}8swh4ACk7%BpP-n5(RhDq{gEHP*Fo4IviX{C49|B5h~SC zFr`=0)=h2^F5UpCAgt?R5u{6V<a5ODjWDGfTC~$_FT}rgG8yDcak@wvkU5wL@;TeZ zPO`GR+!M%zf?lM1u-<{|;Q(fZw-gDSLQrBP73s%I4kriHo~I8%gb!B4r>vpUf#*nC zCQ`$!|C;L2lpjlG?(>T$(_$O3_YNNbPT~(?!j3aD8k=yu^ogw4bkjvgF|3BOq(hB& zG;^cPXmcUP$ox8zElCJ-zMbK9q^8{rri#8Cek5Y<n!J9a_;CLF!lX>dr0YT-KTh@J z6^AcB9ejew8BY5kzZUZX(7Po==eW<(;uV~E7(BY5c0^xr`cuRwn)47bN?zOb!0?cw z#v}R$z66&m#+AHfo@(^V2#S~bhoUkkTArg+6w>JzZ52r96^({1W!?>4$h0l|-jDfj z>7(<+%67#(A|4hZ3>Y;hd&S?}F;`Vtqz|pK&B>NJ=Faci;gkf-+GmfQR8^zo_vul2 zB!)kfu4Dq_g)8TBBo52*sB6F`qa&JCR=_A$QWgX_K}fZm{Cb2#1q`^S3+WaS>sS#@ z-4k*G=#?z6d_e7JJ+Z8^(t0tNdL{K5F;2nfQbXgld}a(X)Gr;WojOy`^?es~AClT$ z5^lD{WJek0!p-QEH5E7n6DKQ0%_ZBZ=|jfV_MM{VmL8y-Wd|>OmeemP=C@xI@@M~1 zW2S*im@Rc=O>V886_UJ@oh1!2H$Ku&U*Hh_oxd{32)vf1$cRiepv28ricM;}#p!+k zaK{z1I=9Y%3m4|Pj*BD*Fn5Vh?O@oD^1UcjyeNh0fbhh~V<H!nK^g9ls(UcBEXK%| za;U;8!rSm)=b{kqG>6xb#4njlGW8OehUe!MnoR(wn#nsoyL1m!Rov)Nv4~&JEVl7L z#^qYdTpNI#u`N0UbVMiDmD>g2VQcG3>4D6<e4?4s7RYh4$dWZU@g7b8WX0r`Y#b|8 z3YQ)JCB?6yErIG~7k5+q&+P!y)4{ysbsIkYV)dCA_K*X*S_YZv$~E$4z?0FEN&a#6 zu6U$Ha8ZSpZ{-B6MpRKG`<444i}FgV<SB1ctW;y>gErgddZnSQTs){BExxRJR<X^- zYm(Jvr!t=*AyjgTOAVJyQV$F^aXXDzoS{BdiAO*9ilg~q7RC`nC5|tGI_Uyg6q+Af z_~)U~w|4zdx*se%qb+sj)C^v1tN;D8ay1fxZE(V)?t(1s&9p6pA7Hdq5VZ|AI8!`5 z5hh!uE4{0FgUC<qp56l-r~_8&6{D*VzZZ@IkW;rUvjYN!wSrS{8xSFc>B?bIxTdZa z;!S8FHJPPiIDQ*FAUiW<aE@x^o9n9|8jmg@-NK{Bp?S^ASxTeiKt-d+p<~?wB~$$6 zYs~@-VparJ8G|Da)YdPaT|JZDM=~!q?}qMq3t-C^QrDKsI-lJX%$oxhq5C@Q^duDg z?4%^g!FG&#N~t%OMEM|YwNie=r=BomjT@p{jK5z0kxB5!-&Ti1a4@|(IkYUNy!rwm zA7fW)@@}CoPb~|!N)(&5w6qwth}CAD?fnX{S&nmHH}F{(r2k`Y>SYnjILFjDvxvSC zk<qtm;E%gFWTR}j-)ETL$1j7){*CDwtvowxb3c;!9Mg7Z#rbtWL$XeH?y~7uyQWbt z#a&HwZGqZSS}oy`aTL<nVm#5RN^Qv@JMl}plNYWNMy?VPsEuV%HksMQZ&M@BDCAq> z=j4Kx@Pg~&2Z?cmMDa;)#xVeorJrxDBqy{+`kG+ZPQqC@#ku-c3ucU+69$#q_*se` z-H#PFW^>-C0>++|6r=<$Z8)ZFaK=ZjwsNYXqRpl9G|yme@Eld5B-*I69Nx_TResHi z!5nm+>6zaJYQO#%D{~o-oOJ;q`fa5}l!<gWB)3)MwB=etSu|A)HNQp#HqArvXJ)-9 z_RMP3>8G*U-E$OM&7@dqciBCWtd}|SrDXz$TB($&m*=Epuolu2k`KUwO7maP3P0ok zmF57l<v@cb34lh%^P~cUHM{48n*rZ-qaEZ1MzzCoG~#m{7z+O*JPL)+yXEB9Q1-&3 z*Ms=?1?R8>Sh0Ba@&sO1iZ5^+3s8{B8t|M;Pg&O+{tZJCiLWd6H@{b~9{CLF9s3Kn zt5)Rs9ejne?o{%f><hmvi~%iy7ixeOmE*g3u@{kRhrlzjq(;E}*Ab<!Rkl&Tp<Nu$ zj_BI>B$Dl%X7fd~KY)I|(pxUeHj;gNsK6;ZR>`ciu;GxvhDUt!+31Knss2U(%ts8K z18)8;<2ax9RG?!|Lwdt^i5L^&O788roKmVAB)=EdK~HqR2Q=)H_VW}xY=95MP_Ov< zPEz3%DRK}+(aUBwsr83H8>`H^v~|A_t}0vPmRwKPt1{|qOY|PZu}j9+{ZhF&-H_TB zU9xWLpNTc`enI|)h9jQeqf5RfGLFk_vfX`40iMpd%KZF!lKbZTdBw$<^G6nuS+$fT zrbK)xo&;buPJcpOZ=x>n+bRXVFDs(23Xr=rDE&!)pVXZ;;A07NXGl_0m`{Z)DQIu$ zFDvY4xu-ifTe_$|n2B83eI;KUg6pVbw+N!nyLj~wnRi{4mNy{WDV)G1!6$y=+x6U{ z%4_9=Q^L!x_gAYp?J3+u5hA5cO8aHeI=6AC8^S{mzhqCBvBLYEutUC(X0>hKg|AvN zvkmJCQNA45_KjW{aEcyrBppcO6G0zTy%v1&@~+2!n?kA9?>0>AjFN|JdCnHQ8$hEU zw#mwGifHppLP?89LMb(Y3Li9iCPx7W%ek}2FgD2YSzjsR4Xj<=zN{Yo@7s7(k%mP4 znT2p&<j^yvFM2RSnHHwMMc(2UdoUNS2x4CzITQi_G`d@qyz~-_^u1>4EQ@q_chd-E z78uvD*C@oba`U3W2Iw`M#`5C8jOHv8^Li<|j^SI>>>`77Dp71Vtz=J?4Zck4SdRbd zfF}C_>Y(#)r@y!Q0`tMlG#b9>5`fAI$B&tWJfbGlYW$J4V+-s=HH!`+;1XeL@USdx zR0$G&&XBf9lQtkH5)p=U!8J!1{oc4E!N-~A<J>bxl<m&B1N64_9;PGPY(a-R^5$^; z$s$KcZ@+yaMM3@7vA!{XqU>6E;;=3-hMYZ+44?u}zabmCE)yB?*_w91m$n1Yskp&@ z;kxeJX-#ioX^{elyLu~gzx|_KxLpX62MF%Axq3$!Z_P`pBWR?zP8OI`PV~6Aa0Oi0 zv_Ot1m&plf-ZF{e(z(Ms3*S5q$e|j;gOwGrmWsCHf<WiXqr)_<#-^P7eUDy;3|#TD z>Li(h8y?g<J;67jdFW)*FQt@{ZRKdyHS;bpPDM~lC-|XQ#9ez=^9^R&ttvwy+?%aa zd%wnUga`n>c$(2H{884C1FvHQQ12tX=qFUsK~zM!W=K>;zaRsu4Xmcc@8nSs!vK+{ z?}bq}-m&p5jRSam67n>yG9ez=I^|J1O;Np8s=P~9MXYLxD+cFQK7PhG=bkjo{Naae zjp3NWWrlFWDb3Z5D07Q|WjZ=wOQ=aKA%en=O@hL$QCKpIXNZE=InFk|Fhq-&H!6&X z*MVy8=hL7Aw&pQjHrFf27C%3B<>FX{@f<FfR}de0cdavaWPgv)j@|tVyBnBmhay-w zr|b1WexK9-QI~=CyWk={v~fqpT~}natdz+o<7km0b~X=ETaH&3c8K+WenHsm4$JbO z(VV8XuzE|ddkZX9Jyu8q8}^_*l5MVd3l9D~ukx-7Zx-9b=)zAy5|=wv&fhoX&%tys z<My5<Y3f7yT__~Vfd_x|p0}LjxtDuS_R+I_`+x_Y&NM2$J?D-FRpnJiUe1#n@yYE< z`#UbDOlhY7rGj<NITWLL^jTkEme5XKSF5;^iIAxeZLh<I#Xa&Fa#{)+r@~mX3V$m$ zXDY{S!F{qy3{p^j=X3Noq`tM--g+jju*&(g*4VUGd0gwfGcUfw4^YPBCewnah2(*v z-_z~yyDrSMxMprKB^h|c)p!>OLNhUoxL4*@nY}&M3G*T-p6<k?^{(XrB}ewz#nq9x zUPaq7+HwSFFH3OhCiR(jMzu3;PQU~Zu~qxb%Akj9^%3YeC5M$cxT9h-$YV*Fr;>7a zo}~_&yGOB)#vbU|Q3FA8S^X)c-yBlmN(_%}`7Ha3uWFe?>9f=3hlO{^gv~$p`v?vk z_P*r43|(S{%ihs;)YH|jAMpP=-Ms7Ne75_YZZiL3CHVjSU`X1|?Ehh&gA=Xn7W7d@ zf8bM9Y>lG!`PWFDDA9G;x*{1Eh^55u66*9D+-4^dYZ{xXP@?sQ<?=<%4xst`@F(1J z6ft91q!t%X9cO;rXn#Eq`2GT#=V6M$v>LVrY%(azM;C^4FuN7CQ%$!3sr1JL=!Be& zuOZL^bLp$Qo2rL=WDzQIls%s<HhcsSZZlBdTXM6b%<%FtpBuLuS#4c8jK+EW&>!Go z{s}Q0b#+#8bKga|01t%^9Z=wEsevvXM_{$dCR97ed3@1kX)mtSS!JN^rtqKOj}p~> zfpCI@DX*DqcB6ZnBcl~}sGO~1s$AtfkX6fy3N8*ebvZc*KBW;dA=)?#BE&}-or74i zZUt5;{FBPnkZD8YUXDsx&2LvSziAlec3oc>&Lf1Doc3g?H9{OO_$M4B0qTat0UsWP zTlxUeQ3B;oJ%en4n?zQB6*Fb#wH7`$SQN5GI|=DnJKiYm{?-?#-H;#sIjz7kQ4&VW zN9d1(1$_W~S=<%qDD!mwRytas=eqX^iW}YSx3;wJ#)Xp_`Qk1DFiXac$-3;jQbCif zLA-T_s~5yP@Q@W>pXKl^gipQ>gp@HlBB>WDVpW199;V%?N1`U$ovLE;NI2?|_q2~5 zlg>xT9NADWkv5-*FjS~nP^7$k!N2z?dr!)&l0+4xDK7=-6Rkd$+_^`{bVx!5LgC#N z-dv-k@OlYCEvBfcr1*RsNwcV?QT0bm(q-IyJJ$hm2~mq{6zIn!D20k5)fe(+iM6DJ ze-w_*F|c%@)HREgpRrl@W5;_J5vB4c?UW8~<VA?`+oZOidfO>%o0)(A4`%-yNk1(H z5CGuzH(uHQ`&j+IRmTOKoJ?#Ct$+1grR|IitpDGt!~ZdqSJ?cOtw-R=EQ+q4UvclH zdX=xlK-fhQKoKCPBoFAZ*(~11O6-tXo>i0w!T$u{lg!#itEUX3V{$S*naW!C@%rll zS{L(1t%xz(*B`{1NL!*aMc<~fE=g;gXi&Gb$HpD!P)8?JzfN;4F&wv(5HH<=c>>)n z({271)xREH89=C(5YKL{mmJJ_d>qH<OHp%o7e!U>z;;gTvTlgM*vz9@YTTYZ#%_2A zS0G-t9oMQEpvfv(UjfQ8T$vAHi)zOj3>D*{xSRiu3acc=7cvLyD?_ZObdu$5@b*!y zaZ#u?7uF}SrHVQa=sTOhGW{6WUlq#RhPPm^GsRH#qlX8{Kq-i~98l;eq>KdCnWyKl zUu&UWBqu#Tt9jQ97U4}3)&(p2-eCLznXMEm!>i^EMpeVzPg%p;?@O;dJBQQY(vV;d z3v+-3oTPC!2LTUAx^S2t{v;S_h(EZ^0_dS5g^F*m{TEIy^Qal~%mu3h7*o`jWOH}i ztv8M)3X3a*+ry_KkYXYE4dB0?M|t}#Tp+(<S5$ESAA`34+{^ec&-g!{sOtG&>}6CQ zBbq;xhoHj}b@j-@koDB#XcCY~>_x&Y;i%MH|3tF^X2h{36UCVfQ-;oEA+4ZkJ`^Qi zQf^8}6eFO$Z+Dj-F1wkG##tTx>FjR2oOXFmbKFj6K3+=kePQ<4d7%z5R5cOB;zO6| zm9^m#U4lcA;7t&*=q|a-!`!)}SgY<L`cp6ihUK`T5NaMCSnyVawc!h~cVP~-UR^PE z4MN#_um@fSUU_pM4v~EORuYM9?;gwP-|v~>XT#i8hnxtx@kaoBF$QAS-hT7N5kH^l zB^i+})V>L;9_0Qqf-dyF%ky8Mp-dp#%!Nls3vCt}q3QLM3M-(Zs1k}1bqQ9PVU)U` ztE=?;^6=x}_VD%N@${>qhpkU*)AuUBu_cqYiY&@;O$HV*z@~#Tzh?#=CK`=KwBv+o zh%<IRE+<<<>z<y<Li4fUga&=eks@7Fc($mDQaoiTsNk~-jCT_fyXZ===ne-R{=1}# z@)Zj}aHGxc*4Yp=(AUu?Ad%}VMHZ6{+EWxG-I-*RlF4@3iI52=yLr3niln2yBwG|E z+Quaop&DhBKQ6j0s<UwrCJ)SEYGw-cEmF-mRxP&%FA{=PWg?q#>u%0xPKYtyC)DaQ zpDW}*86g%><OE5HGA5d)(L$h5ml-x8zbWQM`Usu*u?pH!q)+;)5&VPX!CDcez$S^* z#3`A2VXirbRluU7y}K%{L|b`exxi2p=v{|QX?!!pQb*3DwTJYF|E6O&c+-)AhCdJI z#WtL?K1Gc(hgV?HpCE`sYDRB-0=1T$6SlZYPla@aT7(IA{VSs|h5rHqb78I$L~Rg| z4q2vN5xOy5hgjbOJxZ~Ahpn5!J$QnDNDF8Hg-s^(<p1jII^e1P-v33)%-%Dy;*!00 z_R5xwgzRfwdq+aZ9)*k>BH3IcWMq`g$j()0kWE(qkIL8A&A0mf&+BzxpKF}=`#jG% z&*wa!&pGFLs5_b#QTZE4Bp+})qzyPQ7B4Z7Y*&?0PSX&|FIR;WBP1|coF9ZeP*$9w z!6aJ_3%Sh=HY3FAt8V144|y<cjLG9Ni0-bXG-mrKlbq21l|*9`mr`m%i0QIDabwaF zRh9o84|M8pD~Uba>fu}IAyYHr1OYKIZ51F>_uY^%N#!k~eU53at-_E-Gh?ahmM5y* z+BTIbeH;%v1}Cj<Ywo7o?8!D|Fk8}RR+oy{*(Dk3Rn>o{8d%UeSMWg(nphxEU`sL< zQR~LrTq>Da(FqSP2%&^1ZL#DTo5Sbl9;&57tQ-@U&I#lj)aNSkcfEJwQD!33?anVU z?pw2q7WtMvfji493`rSFnyp7{w87cW`ak=UEYlk5PCB1K6UDVKXyozOChH4yHh~Q< zv>yvKw6WLfi!PZUx60JZcTNM7jo{ww9b8Q+S7C3W<Q5t=K5`aem0H!-OWG!yq&T`w zL9<h?vUoP1(h&O({NHUvM6Rm5B+4?c%WJfg#dg+r^0_A|&}s~}*2gN7n?^0YW1}u& zu+)3AG_tNtFv-SSZ23m_(^8&B+xcNQwuoU>A5&llSwdwh$=Q(*(f3ofqcz=nwOmOy z(J!K=*wNoRU*${{Mbwapi9pTB(&VVKefqd-qrUb9*Eyr2E@oZ9Cgf}Mc;QP<0D)R4 zz=!*^VIG4T*7Xl=sJxrWv9hW^eJ%qYp5(d0?E6LZzJ}=7E+1{?GQA;z+!^VBD81}O z0kJ^dKy&WMw+1+aGVYY-v@i28@Gm+sX5=@U%F<J54B@9m<FVM{YitYR8zS_J_(KGH zt8{`dm2X@SVMym&+p@{eE({%0KP}+LIOe-)zv}kb!d%-4Z9+vnDB~Kg&+w<3bq2*5 z`u8M^L$Yr)vZG@|>=Z?W)oar}2~Rc&F|+3A)n-U2GF10+QdxDb^iA@7eL$c7yhBtL z>lABrh^qy9XZ${E1}Ss5!N4;ig0-pUh6@|RPCHOWvgG{|l}2enRgJftsN%D|ck0YO zuAQd2aMPSyGuJ~jm)aY=+p~mGudw4erwE%P^)5f<*$$2C-4^I=e8-}7##ZQ!8!Tep z+Z_!}CAI~sry$|XK$ktXaxP*x<_ijCPp`2=6sNLZU<@9Sz-rz7^BCE9yh0jV4(I!Z zxmA4d;>B-!vD}Xp*&*N%`b^e&R;D97WS}{~{O-EtXeZNfdf51tw!WR6Noo4hjHPv5 z?heYYRSBPjMc}tFEU^|U8a1CxxK%)WTcn9P%`wR^I$QSeMn6=w>Z9OoVvcrl`zYlZ z2y`mAu0bV(Scc>G_EmIo_<J`spJ!5|B|Nx9;jXDp(3RzE_|)z6Q%~Z%1o9xC($B>4 zm*~h`mxYZC&+U>C5G1FZH5L^U>Cq-9UDRQa35jz&NBj*0{uJKf<TrbDPJ6YBjYr1v z-Jp)`sw@0cJWU7};Ty(N`>Zs5=Fn@&)Xh6aX(H3w9m9BGLePqVotxTeSPh5-mc7$# z-80t6yB0$Nx<54ohdO*QL7<B#`%1`peiY3hz(Eg}A2Vu{-o!!7+HXL(jB^~|UR2zE z(mUX3-l7N{t&*hE;VVqitm`?PX7@QlCg39p2>m_(&+#*=eoNiYDB4rE<IeJ!x9fj{ zjh5~&GUJ|yRpJS6j=TELjk^ZSP2S(znUdT;wZzbXok^sLPJ}W@PuWC1dHEtmpa!Km z3ah8K`efW_!c7}=UaT8v)>4Cag@qfyZS};<ARP|HEzxy@RxNQ(L<I2*mst4CLjQWI zCLd4J2s{{^xsPthocP{NlAzfw7vFOtehv_S_h<$Yf;yR*!F%qq*m?ZC6w#tpX3UJJ zxHCzqZhQk*2K$ALGdFIUQNBtEWEm`HeM?iVXCp3VnX;`4F_)_*t4OTijK6{jewsfL znno67!eVKGzMaP*N})bFYHNt+IBLk8Gd8`YH`FIMYk!BRy|+C6o>Fx;Vf1;oync2k z9v#-<l4c@#!@Fz5xx(#=xAQ7-W_Ck69p*<vrAlz9czK2M-ZH3`lqAJT3Q#>w?d6R& zOI`CCS_d=tf3|?g3Z}b6-_Rdg3y~enQhmgkni0Cvf9m6%Ft8r;NC5|b%t&?lkl*4{ z8U<KR<Ur9&bCcU$L?%LSI)an9N5<hfOhXjYvzjrNO9}$J+=6Q1v3&e2R=fdgAB-ed zy@TM1<wV{=uxJ*j@8!?}Pn10LdmBTkgJo<_9x{X{H1*jMV^)Y~b@QZWUB~@&p`T|t z_QD>i^;Ds^gq6ti(1xB7y_$zA!i-M~#!!tl$ErTR>P~>T=Yky)8(uvPbvLmB=UfoD zrfl}8<1OQrm?8#j1!?s*T>AoectQl&m!o&*^JcIW`_&bk3tN}k^0rjl=HL$z*uIYt z?7l?^Dqr?q121<k)GkW4%te+ZZZ$}&Ojnh_9S<Ka*4g>0Sp$xoAy!&{2^{^Anl460 zI&7urrc&|Y{rjv04VOl{y7c82N6xzg5ueYmQ(q(zC3w_C#x*~%<llZF#S<oTCg{?d z-lJ;;SYXIrr7stvma)3=TXZim+stU&RurLEk>yf5j7MI{W`tsoxzA*PrmK)cTskU| zf2C}Bq$>S$-1JgIh0aW@LxI|-8(OGuD#^M01ghh}&#ObO>tZgSw_LW`zdf&IN$YO# z)|X_9m#JwLW5pErZB3ScggKcNzxA9(hyKkK9I#pR&79&*+SV_eu={00{HF=Bb+AEe znaSof+r1jZ!EL5XgqXWkckaFSSyEk}o!%p8XsD}O>borZ6x%X2b&q!s&1-O(>`kZ$ zB2l^5Cx9xQx9)PXN1xPM)@+LxACH_iZ8zGc(>wnFS_O|@hKsx<!FoZWaMg!u*IKF8 zW}P3`h~J%C%xvWQ&@r<W#x<X_L1egnQ)1Zd<|Iwp+BKV<KJ_VM&khB_(^t0WU)7r9 zw~$MVS2GGq-pxs9pKiybey+q<WAD!Wk#BF}Jbi0Er2eIIN;!cR(K%ri@<6p7aGCf0 z)PN@8U75jRa+mP5clupy75MxelnnFqiyW0>pMjXOzLEa7OvSlM&&G9ioQw9~RsD4F zK7Q+_&|Q6{eZ^8Rx@pKL`le6kH+(fLc{=V&{b%I5=n}VHV4)X_2Y!pYxgC8wU)yP! zPF3t$?(jsC>Ge=&{kmPGUEETpaw(QTAl)m#{qR3_aq9!wK%6XHfV4C>Y^>Z|%ns7j z{Ja?^IA{+@;kR#IjHx<p9h8LC6`To156^y!hJpG%ORFg>kar%3$eJT4?xNBKUVmoO z`A8Zo-{~_;vcikZ(p}EZzU4kO6W<oOs*`uO_hwi?s!j4Zh>PqkMyE{VvS?;44Z@lj zz^fKX9UL!8Wc(9VgI?P4*zpis8dzl};I>yr1>dtXU=FTAlx}Eht4-*7RACL^AflGh zyZb1hTf(~CkMo%#Q%NMgM9tE2D+)joqbtHYA89Ql1nqVTt+MxZ^*FRd&n5YlIi!8m z>$Ysd!l{+C)y;Wa<K2+e8*SV+PaB*>(ZV-=<+NZKV;v4mt}v2m>`v$-$3b;GsLxf= zd~f(rmfpl``{0aVwN7y!>eGyJFP`L+TxHjHTOS{K^$L2`@6(Rli`{EFwpH@R%eZ6g zwf7rc43<A*1Q;!xeUQ*$(tU17{YgRqr7_w2CmHs6jLPaaisvGfciLYJFL?|YL0TgF z)vZ}W3!dJ=e4h6Fj3j~#k6~XHm62*Z#MxeGCd5^o!4iAzf;j6aZXHVgbJ5<JT}HXC zMa@)$&VrHK+hx+OjZBn_Lg_G6kIcKz0^iE?ioO($_K(nSe_mQ_-#vFnWk>Yk!=k;{ z-Rn%~B3amGr}}SxfE$vS8FIPL=Qt57$|R#sSoFgdNUT?fYOYjPl%ZB<Dg>Fpi=<FR zh!tZQRv!qGd2w-d%|0vjpKqq$M?q}ig-a3Xw(1f+y*U>jq=DWby7Zxm@y;B<89!9= zbgEH*Uy)~iq5kJLX$+ps$kV`#6jW#|9BGz^`ivNeid(wVbk4jl)VBpW&~;eXNi{#` zwx?{DXR~*sqQcFhY0XCfQ4-*2aN1BGX>$_swtKEqnd>j6vcZ!#0)pXRi?<{!P?tGw z2x_`RD$W)qD{?z}VDPt?+)8*rqLWFIPQ(9-VbBdf{7ff?w9CZ{sIi_gnuC$I0(+P8 zms9XB%}VQ>>p<fUdl@Vy-yM%1V*%pfJY_Q@oq;8-!>ve##}jog6+cD?v~n4Pa9Vmc zg#K<TJpru+0smM0m_?9<3<lwQX+7Y#ZS<P77P$Ov_%Tq>$|+`adO=B7`uj35Y}6EZ z{dY`x@w8;R-7zrsr1O_~Jvl*|o-x%jF=Rr1C}GXP^|IYN`1sqmG-oI@R#%X66c#5W z$$tQB)sqwiVm;Y^`Dw3mo|firP{*HsOQJre5%Dm^H@we0FN88VWJ0dja?_U38z73f zrCV!b3qNP0kM#%9T!W5`ynGcg%BL28FW1J-J1_S`BJGCaReQ!am(2%qZ3lLgzq|ns z!!fF@`0=*z)J2BwZ*hO|Yu^cI_nF$9l-Pb3jE7=P8gZ#!xiuZ7-cSa`gb`6mxGTgg z-DLdID?M!Z%+hHB#{?&0$GFRpf+_}q<_wbzX6K?w;%6szz1RbySDSr2r^h_qi$khs zXdZ9A0!_Bf)TR2-^-K~q`FQ!#1x(U4VbV%AA@Ei{%cA(EwC{XfjRi?`&9rav5;Q5% zO1`Rn@OA_ZB@N*mC#)?d3P!}Eh;=NgpIKsy{(yr`hv=aouwt@r&P&}Z3DNWo9ro30 zX52~(aTV$*HHlgB66-4GQru!_AZ|)V*I5X=WG)`N@U&D>e@@C#V@JwEL*L`7#$yes z62C^5%Qniaow2$3HrAc7U{qzpb&FA*xLI1JSWR@`RF=JCcvTI)%dH7;sWInt9JLu# z|Ao|Q?K)cD<XIH`HHF$U*`>g_JKsym=joo5gR80wtv01N`um1nQ@Ms0Y*bVzxL34} zo?gizp?`=Y{*W>^Hy2%Jl)y?A+&7s1UVHFixuIy~sawXjcDCL`129cK7|ZQS0u;A} zTJC<n>#WNmqkIrnHpAhHVcM(U^vJA~dl@jf_bs*3?i+=&vuC?Aiy_pcB~=1syDni4 zw+FLuz>F773u#$;NUQ9WDtUPY@+rA3WBhQdKFKOyzkA(URa7;4tW>3jQIfi8v0h3g zJC_HVDXS#>DWb|&se7FHnr=q&<fFndMyX6ok|*VZ?$(NG!W2uXIh0KPUw36VxOJEs zWL55mPTHM6#qp$QRV3#jrg6AO-3EUqlT!W#^D7D+pA>l#xg9o02}}u=b-R>@sw={Z zHF*?t2FmhqZ=|qa>x=A!*$S+0T<RES(CQkwg0f!ut%n<5m;I9RK*Ok?E82=ogcAWX zVMf_PEhO%Ra)InLoTNnu*N)LQf?H;Ub+bfT-C6(^c<%)T42I|Z))X=BQ!8Ur_1gV| zIq@p0@`Lg#&@KI;S3rcoc+0%=cpeub%lgbGd}9$GOX8GXLMxQ<V2Z{eubf-2zA+uv zklCK%<D%OZPsbqt7)9|B#TjKk_;XlT@qi8gU;-qC#!y7fw){$5w)b;#tp!5kG=0`6 z9Ik64yvf9Ei%-l@D!sM^YDUjdS=D7mk|C%pMhoY!Y^d$mD?YDYA~!}WU*52Y%N5AI z@j_K9ct+crRE$scRft}ZVlh^m8$*08g%+MBg@9IR_jNa17qs|g2jAO8e#zebVs`5C z#M~6d^GVBMYaN$IhQCbj@Py)%Eu&FLw$AWyA`~pR7i~dfi4_-S+QVK5Mc%jA4e6e> zhO*D*M?NTf-eX`eO)9TIQu{7Dm77Acnj4b1jI9@c*ZL8wL%8kLEhd$KM8=Y!fbN@9 zC7B5#y>JM1n5M)!&im==EgHs2j+xCZG~+~QWCi?s!QyFo2kqx{%jE2n3^N*Ayz6Lp zhg5g^3#<s8**C}4WoKx|EauIJ1o&O{zsW4{WH^4j7~KJ<QRtxARB~N6G1=Cq2xytI z+zswgLp5jEXPYtIst)_svBi}Uvn(mbhG0wms7f!xihoPy$`YnO3OL=n<3dU={6=)> z+5FoJ@$u@9WJgPKpUWEd4}4AK9TJKU8W%ms!d0p%OIOX+bY+55zl!vIaz$XFI9Ep+ z<dS$zNm8TS5RixZJbxTR?cH|bfw~-cU9~alq(f12VSHQ>;bL_}7PDI2Y`Ng*XY(65 zh0%`@Lve%fc;)N4_g12bNrt6gH=N#OHtxO`$lpWlw=Z6MF+E@;>GkZ#lAZTn`aHwf z&I1|aV#b_VHMIgBN*RzU9i@Z@m}0i>o?({&%fpEfaOpFeaJ7V37;m0?kzd}}Lk@9$ zL}8TEo7WZAcRi%zFZxkr6<0k#X-;lTD`Oc~cDb@olwgWCewvk{GJ}hCXbF!AdiLpd z|Cck$ZTKI?Ack{34Lva7+k=H8K2HTZiurox6F+>dy+@R9T^awxj590D$|kXUg+Ygc z(f)jlRwN(4z$#%PnOVc;#Fv{nAi{#UcXPNcmP#5O{zh_*`=q^JCeia{sN4zHjk2*y zqUVh{Ya{j<IKA2W1mW}eeRalbF4<$oYZtObji4#>>SPmP^i#Qfcq_MTqo8g52Fi^F zKBc$$HVI!xFx*4Y9l+nt)$AoZORD}%5I10oI3kx`-N30QueiwIw#0VV2E*Fb-nKW% z=+r^hos`Y-7~{cA1FVbK$_=~*z53+Q8KGjg;>ztg((H12%QTf4OYU8y)C}h5yo#$% z&Q$`vMM*g?ZcatAn2j!hFv8KuN(dw)T*}sF#THDHxo8xC^?v<bx3iehloREh7QD>J zc`U6bVo~hOr6I!8*GTZ<^D~;unKjK<lSb>=!IR|<CLOcJa^Z#o;e`&fF86DiwTx_5 z^+xIq@90~tHVYK{W8uadIIL1Sm<$jPsUn0~E>GB4E>Mcvt*2GK);93jIDd<(nNjHO z4Hi@2^%Uyx<t6q~e7n*&BG#Xj>=^Z~5eZ!5rO5%4H|eFoNj<JnEw;I(G_8jWC@X^D zfeW5#XW8dOR29iCD{XUCxg!{eaZraMSGf#$B@EDq)OE7ovZ1oU#K|=2n|sW8oxhIE zriGbgdm8i0QQ$ne-@3gT)BMa$`%TF(rNHc$Z=9p67+syKBYVZ}V$K_l)P#)$nD^Ai z)i@@<Jsfy5s4!Mrlao<acWb{oBXF>D#+Kcu%_57zZb4Z@Ak#X6txD^{U3wBl^r+W- zLorkK;uc;NgTj7dGxHQS+@T*T>Q*j4^Ll$ejQqWrwcHyG9y%Mk%m8nBVG5hvSaYm5 zJN^#-Q46kZG)@T8n2^QCjxIwxUVi%s>EY`E?#@_(A~njFrTiDq;8v|W-1jT|ROlNI zU$h|YoD4PVTE^&NC6_m{EAFBVqsM`P*`-AcDGWQygURzM32Xeq2xng~XQsYeTZ5v$ zQLaa2M_Iplw}4eL6fLPu`6`PYcVMysO>`{8CB~glD=TX7?JZcHfHNmykBM?QD)#D) zGp>R*<^D?WhFQKRc^}22l6F=D2RPrxaX2ZF!b1X0XF*d4%=!sbNcS1q2WOUE(7e4$ z^L8f;F)__d3>&KQFE8%$I4h^y5FYBfB&f<E9*wxTo`y@*Y+nk_nU{tWTDqRgI^8*~ z?Bb3&J@i%}j?QgicjYnHi}D5zkFxgiu@3ghueSBgqa>Wzn71_OSrPe-DHV{O#Q;GP z+Tw!J?eVjX19RKH?*hKQWQt8r7B#lYX8xoSHFGCW-*DSQ4EM4M3Mw%gkSYNK18@(e zfzMF}WWaCyS@1y%-~Xg0ry~tkQkUmKuI5lGAua{{vn22V!2T()AU5FpKh@Nv)s^Js zv~@Vu<dG2$ssIa;-wW`<?Pob4z7KpqNIm(x8bBn6f7NLGS;Ojk%$46(Bs#1II-vS^ zyy8DgWk^a2ogemK!2*Fy$UvYA{{VnMupk;>UG;=CnLmQR{PeUBQf2;lAV!vG>^Z0N zL88rrjL-*J!43;7C=w9xhcw`yjRKq7o4L9=0SmR9PA-nX12@#h(iIu-0N_xm2OV)( zU_raT0y>$wm^oMi2|U3N;OhF9uy}`<-xVka#DV*l{O0yHzi9vUxa1Qtpi$buR*8cU zd4~lS1pT$L^!0=6qUKOpM+XPsy{f7W#1bjrEwaeN!Ik9(zySIT^pEHvHgJUneFN4) zk=k|$55(g8slmS|@+*4fr2urd3LwjIIZA**g+%l(SZNn4HwQ}y6o`vw>2&mR1X+&q zDa1Af0B;4rAMZMOlHbAqK|R_xuwJ7ANARtFE({-P2o{tJJR<>2KVp)ZK-M;)ejx zd*E~Mka<{OL7%CAhk4n|1qg?97-I!l0rOinjVi#arbgg4bi5;nY5oFL`UWtP<!xMC zq1tZOf2#jvtAo2;dyoxinHg9wKd`*R0t@mv_qRkp)Z=<G!5Q|(^Lv0KZh*~+9ijtQ zSP<m=Ul7Px-f(mQq9^`^C`%4Yga_mC3t#~9$C%oHj`{E2{n-<;X0Db%@C8eVs|^$g z*r*MpnTA*ax;wZt{PSu6xu3-HuvM@C)p-(tK;p+Zq3nObsR9A=9R5(>k5&L#grSxv zE3!}=1px!ZTLT90aYc^s`~{VojjJml&<`@e41dFP+XU6D0AOkbn2rlI3>^LcqauG& zc$m3Z{!u8LvUrm^fT{qX5<I5AabS1OUsC<4lTtYvXYzo%Ne(a!5BB^V7QjRS+xknA zKZ+vE!SeYLAW9W*Yd>yD9{?r(CCiUdck%!T`KIZd2oQJz1joB&M(Teg_>;yS<2<KE z2dLnHDFK7)p8^XSko^m)Kk8~M@mtUYfNuww&Vko-SYSb{faU&CSGo|p|G{vww;L8s z2|=I_z)Zq?$OK$rLD!Z3Om=c#P~Lej(Frsj1mGUWL^t{c^Se4Me%^);X7Q6Ty{6Ei zqkvN6fd1t;)=ol;KV$x|x|5NO+@H(%0tSE$7=XwzWC5#RkzE{ZEzP0-AFlwbM@amD zXBUt{_!tkC%`ZI2OUM7x&mX4o17v{Vd%^#C1%3CxCTx$<xIt~~e{sPMDje1ZqM7_G z2M#c<-LJK6AizutG5ZyU?iGV-9iY!};Ldg2+~t1@1Nf{uE@tkQF0N+w--G-du9hQD zE%M|^h2lU%&j2<kao9}Y3JcP5{7pN5`q}^9v8d}}{|AjCC%ZqSg9UwZKE`$UP$1*z z2t9C4oeunYU@CC|wDe!T3~~zfBk&d1zXm^fU?XP|K7y9_IuZIXhTng+6*+J35g?oQ z?*acRi!X8?Bd6v(qO0`(Jsn`4CnoAdW<X8`c*OAV=5HBJRycBq?;|+c<ln*p?L8r@ zF>-5>BWfSPpG`Rt{!j6>kqMAvl^zk0JUEfy$HVJMkxP-GkwZuxL62me2#pj_5*ZIU zP~#C^OZLfl$HO)v;~~c&JHivn|1I9H5y_CDkt0JLLGKm(4*KLVhJ2jh2#vJuM6`b& zE<kP?@_z3lu;%s?!H(?={;%EN$SlY^j*nP!JO9jbvKo+gUmamC_MV7|JfR-ji-p`` z<h=|>==-lvME^Oj022xF&IV*?<Ym_*=qDq;gFe0pdszh?m{|`Tb|Fw25ePIfbMVvu E0aA=+Q2+n{ diff --git a/packages/react-native-bridge/android/gradle/wrapper/gradle-wrapper.properties b/packages/react-native-bridge/android/gradle/wrapper/gradle-wrapper.properties index c747538fb38b53..efe2ff3449216a 100644 --- a/packages/react-native-bridge/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/react-native-bridge/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-all.zip +distributionSha256Sum=258e722ec21e955201e31447b0aed14201765a3bfbae296a46cf60b70e66db70 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/packages/react-native-bridge/android/gradlew b/packages/react-native-bridge/android/gradlew index fcb6fca147c0cd..f5feea6d6b116b 100755 --- a/packages/react-native-bridge/android/gradlew +++ b/packages/react-native-bridge/android/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,9 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -144,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -201,11 +205,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/packages/react-native-bridge/android/gradlew.bat b/packages/react-native-bridge/android/gradlew.bat index 6689b85beecde6..9b42019c7915b9 100644 --- a/packages/react-native-bridge/android/gradlew.bat +++ b/packages/react-native-bridge/android/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/packages/react-native-editor/android/gradle/wrapper/gradle-wrapper.properties b/packages/react-native-editor/android/gradle/wrapper/gradle-wrapper.properties index c747538fb38b53..515ab9d5f1822a 100644 --- a/packages/react-native-editor/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/react-native-editor/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-all.zip +distributionSha256Sum=f8b4f4772d302c8ff580bc40d0f56e715de69b163546944f787c87abf209c961 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/packages/react-native-editor/android/gradlew b/packages/react-native-editor/android/gradlew index 547ba0c2aa8ffc..fcb6fca147c0cd 100755 --- a/packages/react-native-editor/android/gradlew +++ b/packages/react-native-editor/android/gradlew @@ -83,8 +83,7 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -246,4 +245,4 @@ eval "set -- $( tr '\n' ' ' )" '"$@"' -exec "$JAVACMD" "$@" \ No newline at end of file +exec "$JAVACMD" "$@" diff --git a/packages/react-native-editor/android/gradlew.bat b/packages/react-native-editor/android/gradlew.bat index c138ebb7fb1835..6689b85beecde6 100644 --- a/packages/react-native-editor/android/gradlew.bat +++ b/packages/react-native-editor/android/gradlew.bat @@ -89,4 +89,4 @@ exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal -:omega \ No newline at end of file +:omega From 18484f474ac418164ef8b9813c189136d48ff95b Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 30 Jul 2024 12:05:52 +0200 Subject: [PATCH 0159/1908] DataViews Extensibility: Allow unregistering trash post action (#64087) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/post-actions/actions.js | 167 +-------------- .../editor/src/dataviews/actions/index.ts | 2 + .../src/dataviews/actions/trash-post.tsx | 196 ++++++++++++++++++ packages/editor/src/dataviews/types.ts | 7 + 4 files changed, 207 insertions(+), 165 deletions(-) create mode 100644 packages/editor/src/dataviews/actions/trash-post.tsx diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 47e49fb8f8f1da..d0020aed6408cd 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -1,12 +1,12 @@ /** * WordPress dependencies */ -import { external, trash, backup } from '@wordpress/icons'; +import { external, backup } from '@wordpress/icons'; import { addQueryArgs } from '@wordpress/url'; import { useDispatch, useSelect } from '@wordpress/data'; import { decodeEntities } from '@wordpress/html-entities'; import { store as coreStore } from '@wordpress/core-data'; -import { __, _n, sprintf, _x } from '@wordpress/i18n'; +import { __, sprintf, _x } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; import { useMemo, useState } from '@wordpress/element'; import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; @@ -15,7 +15,6 @@ import { DataForm, isItemValid } from '@wordpress/dataviews'; import { Button, TextControl, - __experimentalText as Text, __experimentalHStack as HStack, __experimentalVStack as VStack, } from '@wordpress/components'; @@ -82,167 +81,6 @@ function isTemplateRemovable( template ) { ); } -const trashPostAction = { - id: 'move-to-trash', - label: __( 'Move to Trash' ), - isPrimary: true, - icon: trash, - isEligible( item ) { - return ( - ! [ 'auto-draft', 'trash' ].includes( item.status ) && - item.permissions?.delete - ); - }, - supportsBulk: true, - hideModalHeader: true, - RenderModal: ( { items, closeModal, onActionPerformed } ) => { - const [ isBusy, setIsBusy ] = useState( false ); - const { createSuccessNotice, createErrorNotice } = - useDispatch( noticesStore ); - const { deleteEntityRecord } = useDispatch( coreStore ); - return ( - <VStack spacing="5"> - <Text> - { items.length === 1 - ? sprintf( - // translators: %s: The item's title. - __( - 'Are you sure you want to move to trash "%s"?' - ), - getItemTitle( items[ 0 ] ) - ) - : sprintf( - // translators: %d: The number of items (2 or more). - _n( - 'Are you sure you want to move to trash %d item?', - 'Are you sure you want to move to trash %d items?', - items.length - ), - items.length - ) } - </Text> - <HStack justify="right"> - <Button - variant="tertiary" - onClick={ closeModal } - disabled={ isBusy } - accessibleWhenDisabled - > - { __( 'Cancel' ) } - </Button> - <Button - variant="primary" - onClick={ async () => { - setIsBusy( true ); - const promiseResult = await Promise.allSettled( - items.map( ( item ) => - deleteEntityRecord( - 'postType', - item.type, - item.id, - {}, - { throwOnError: true } - ) - ) - ); - // If all the promises were fulfilled with success. - if ( - promiseResult.every( - ( { status } ) => status === 'fulfilled' - ) - ) { - let successMessage; - if ( promiseResult.length === 1 ) { - successMessage = sprintf( - /* translators: The item's title. */ - __( '"%s" moved to trash.' ), - getItemTitle( items[ 0 ] ) - ); - } else { - successMessage = sprintf( - /* translators: The number of items. */ - _n( - '%s item moved to trash.', - '%s items moved to trash.', - items.length - ), - items.length - ); - } - createSuccessNotice( successMessage, { - type: 'snackbar', - id: 'move-to-trash-action', - } ); - } else { - // If there was at least one failure. - let errorMessage; - // If we were trying to delete a single item. - if ( promiseResult.length === 1 ) { - if ( promiseResult[ 0 ].reason?.message ) { - errorMessage = - promiseResult[ 0 ].reason.message; - } else { - errorMessage = __( - 'An error occurred while moving to trash the item.' - ); - } - // If we were trying to delete multiple items. - } else { - const errorMessages = new Set(); - const failedPromises = promiseResult.filter( - ( { status } ) => status === 'rejected' - ); - for ( const failedPromise of failedPromises ) { - if ( failedPromise.reason?.message ) { - errorMessages.add( - failedPromise.reason.message - ); - } - } - if ( errorMessages.size === 0 ) { - errorMessage = __( - 'An error occurred while moving to trash the items.' - ); - } else if ( errorMessages.size === 1 ) { - errorMessage = sprintf( - /* translators: %s: an error message */ - __( - 'An error occurred while moving to trash the item: %s' - ), - [ ...errorMessages ][ 0 ] - ); - } else { - errorMessage = sprintf( - /* translators: %s: a list of comma separated error messages */ - __( - 'Some errors occurred while moving to trash the items: %s' - ), - [ ...errorMessages ].join( ',' ) - ); - } - } - createErrorNotice( errorMessage, { - type: 'snackbar', - } ); - } - if ( onActionPerformed ) { - onActionPerformed( items ); - } - setIsBusy( false ); - closeModal(); - } } - isBusy={ isBusy } - disabled={ isBusy } - accessibleWhenDisabled - > - { __( 'Trash' ) } - </Button> - </HStack> - </VStack> - ); - }, -}; - const permanentlyDeletePostAction = { id: 'permanently-delete', label: __( 'Permanently delete' ), @@ -988,7 +826,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { supportsTitle && renamePostAction, reorderPagesAction, ! isTemplateOrTemplatePart && ! isPattern && restorePostAction, - ! isTemplateOrTemplatePart && ! isPattern && trashPostAction, ! isTemplateOrTemplatePart && ! isPattern && permanentlyDeletePostAction, diff --git a/packages/editor/src/dataviews/actions/index.ts b/packages/editor/src/dataviews/actions/index.ts index 730edf323578ca..d6255b74be5d4a 100644 --- a/packages/editor/src/dataviews/actions/index.ts +++ b/packages/editor/src/dataviews/actions/index.ts @@ -9,6 +9,7 @@ import { type StoreDescriptor, dispatch } from '@wordpress/data'; import deletePost from './delete-post'; import exportPattern from './export-pattern'; import resetPost from './reset-post'; +import trashPost from './trash-post'; // @ts-ignore import { store as editorStore } from '../../store'; @@ -22,4 +23,5 @@ export default function registerDefaultActions() { registerEntityAction( 'postType', 'wp_block', exportPattern ); registerEntityAction( 'postType', '*', resetPost ); registerEntityAction( 'postType', '*', deletePost ); + registerEntityAction( 'postType', '*', trashPost ); } diff --git a/packages/editor/src/dataviews/actions/trash-post.tsx b/packages/editor/src/dataviews/actions/trash-post.tsx new file mode 100644 index 00000000000000..c6a265eba81f5a --- /dev/null +++ b/packages/editor/src/dataviews/actions/trash-post.tsx @@ -0,0 +1,196 @@ +/** + * WordPress dependencies + */ +import { trash } from '@wordpress/icons'; +import { useDispatch } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { __, _n, sprintf } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; +import { useState } from '@wordpress/element'; +import { + Button, + __experimentalText as Text, + __experimentalHStack as HStack, + __experimentalVStack as VStack, +} from '@wordpress/components'; +import type { Action } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import { getItemTitle, isTemplateOrTemplatePart } from './utils'; +import type { CoreDataError, PostWithPermissions } from '../types'; + +const trashPost: Action< PostWithPermissions > = { + id: 'move-to-trash', + label: __( 'Move to Trash' ), + isPrimary: true, + icon: trash, + isEligible( item ) { + if ( isTemplateOrTemplatePart( item ) || item.type === 'wp_block' ) { + return false; + } + + return ( + !! item.status && + ! [ 'auto-draft', 'trash' ].includes( item.status ) && + item.permissions?.delete + ); + }, + supportsBulk: true, + hideModalHeader: true, + RenderModal: ( { items, closeModal, onActionPerformed } ) => { + const [ isBusy, setIsBusy ] = useState( false ); + const { createSuccessNotice, createErrorNotice } = + useDispatch( noticesStore ); + const { deleteEntityRecord } = useDispatch( coreStore ); + return ( + <VStack spacing="5"> + <Text> + { items.length === 1 + ? sprintf( + // translators: %s: The item's title. + __( + 'Are you sure you want to move to trash "%s"?' + ), + getItemTitle( items[ 0 ] ) + ) + : sprintf( + // translators: %d: The number of items (2 or more). + _n( + 'Are you sure you want to move to trash %d item?', + 'Are you sure you want to move to trash %d items?', + items.length + ), + items.length + ) } + </Text> + <HStack justify="right"> + <Button + variant="tertiary" + onClick={ closeModal } + disabled={ isBusy } + accessibleWhenDisabled + > + { __( 'Cancel' ) } + </Button> + <Button + variant="primary" + onClick={ async () => { + setIsBusy( true ); + const promiseResult = await Promise.allSettled( + items.map( ( item ) => + deleteEntityRecord( + 'postType', + item.type, + item.id.toString(), + {}, + { throwOnError: true } + ) + ) + ); + // If all the promises were fulfilled with success. + if ( + promiseResult.every( + ( { status } ) => status === 'fulfilled' + ) + ) { + let successMessage; + if ( promiseResult.length === 1 ) { + successMessage = sprintf( + /* translators: The item's title. */ + __( '"%s" moved to trash.' ), + getItemTitle( items[ 0 ] ) + ); + } else { + successMessage = sprintf( + /* translators: The number of items. */ + _n( + '%s item moved to trash.', + '%s items moved to trash.', + items.length + ), + items.length + ); + } + createSuccessNotice( successMessage, { + type: 'snackbar', + id: 'move-to-trash-action', + } ); + } else { + // If there was at least one failure. + let errorMessage; + // If we were trying to delete a single item. + if ( promiseResult.length === 1 ) { + const typedError = promiseResult[ 0 ] as { + reason?: CoreDataError; + }; + if ( typedError.reason?.message ) { + errorMessage = + typedError.reason.message; + } else { + errorMessage = __( + 'An error occurred while moving to trash the item.' + ); + } + // If we were trying to delete multiple items. + } else { + const errorMessages = new Set(); + const failedPromises = promiseResult.filter( + ( { status } ) => status === 'rejected' + ); + for ( const failedPromise of failedPromises ) { + const typedError = failedPromise as { + reason?: CoreDataError; + }; + if ( typedError.reason?.message ) { + errorMessages.add( + typedError.reason.message + ); + } + } + if ( errorMessages.size === 0 ) { + errorMessage = __( + 'An error occurred while moving to trash the items.' + ); + } else if ( errorMessages.size === 1 ) { + errorMessage = sprintf( + /* translators: %s: an error message */ + __( + 'An error occurred while moving to trash the item: %s' + ), + [ ...errorMessages ][ 0 ] + ); + } else { + errorMessage = sprintf( + /* translators: %s: a list of comma separated error messages */ + __( + 'Some errors occurred while moving to trash the items: %s' + ), + [ ...errorMessages ].join( ',' ) + ); + } + } + createErrorNotice( errorMessage, { + type: 'snackbar', + } ); + } + if ( onActionPerformed ) { + onActionPerformed( items ); + } + setIsBusy( false ); + closeModal?.(); + } } + isBusy={ isBusy } + disabled={ isBusy } + accessibleWhenDisabled + > + { __( 'Trash' ) } + </Button> + </HStack> + </VStack> + ); + }, +}; + +export default trashPost; diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts index 9f57ecba6174aa..fd569aa21769c9 100644 --- a/packages/editor/src/dataviews/types.ts +++ b/packages/editor/src/dataviews/types.ts @@ -29,5 +29,12 @@ export interface Pattern extends BasePost { export type Post = TemplateOrTemplatePart | Pattern | BasePost; +export type PostWithPermissions = Post & { + permissions: { + delete: boolean; + update: boolean; + }; +}; + // Will be unnecessary after typescript 5.0 upgrade. export type CoreDataError = { message?: string; code?: string }; From dbae6a2c6aeaba98bf7900f41ca130841216952f Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 30 Jul 2024 12:43:59 +0200 Subject: [PATCH 0160/1908] DataViews Extensibility: Allow unregistering permanently delete post action (#64088) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/post-actions/actions.js | 94 -------------- .../editor/src/dataviews/actions/index.ts | 2 + .../actions/permanently-delete-post.tsx | 116 ++++++++++++++++++ 3 files changed, 118 insertions(+), 94 deletions(-) create mode 100644 packages/editor/src/dataviews/actions/permanently-delete-post.tsx diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index d0020aed6408cd..8d8b42435f084a 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -81,97 +81,6 @@ function isTemplateRemovable( template ) { ); } -const permanentlyDeletePostAction = { - id: 'permanently-delete', - label: __( 'Permanently delete' ), - supportsBulk: true, - isEligible( { status, permissions } ) { - return status === 'trash' && permissions?.delete; - }, - async callback( posts, { registry, onActionPerformed } ) { - const { createSuccessNotice, createErrorNotice } = - registry.dispatch( noticesStore ); - const { deleteEntityRecord } = registry.dispatch( coreStore ); - const promiseResult = await Promise.allSettled( - posts.map( ( post ) => { - return deleteEntityRecord( - 'postType', - post.type, - post.id, - { force: true }, - { throwOnError: true } - ); - } ) - ); - // If all the promises were fulfilled with success. - if ( promiseResult.every( ( { status } ) => status === 'fulfilled' ) ) { - let successMessage; - if ( promiseResult.length === 1 ) { - successMessage = sprintf( - /* translators: The posts's title. */ - __( '"%s" permanently deleted.' ), - getItemTitle( posts[ 0 ] ) - ); - } else { - successMessage = __( 'The posts were permanently deleted.' ); - } - createSuccessNotice( successMessage, { - type: 'snackbar', - id: 'permanently-delete-post-action', - } ); - onActionPerformed?.( posts ); - } else { - // If there was at lease one failure. - let errorMessage; - // If we were trying to permanently delete a single post. - if ( promiseResult.length === 1 ) { - if ( promiseResult[ 0 ].reason?.message ) { - errorMessage = promiseResult[ 0 ].reason.message; - } else { - errorMessage = __( - 'An error occurred while permanently deleting the post.' - ); - } - // If we were trying to permanently delete multiple posts - } else { - const errorMessages = new Set(); - const failedPromises = promiseResult.filter( - ( { status } ) => status === 'rejected' - ); - for ( const failedPromise of failedPromises ) { - if ( failedPromise.reason?.message ) { - errorMessages.add( failedPromise.reason.message ); - } - } - if ( errorMessages.size === 0 ) { - errorMessage = __( - 'An error occurred while permanently deleting the posts.' - ); - } else if ( errorMessages.size === 1 ) { - errorMessage = sprintf( - /* translators: %s: an error message */ - __( - 'An error occurred while permanently deleting the posts: %s' - ), - [ ...errorMessages ][ 0 ] - ); - } else { - errorMessage = sprintf( - /* translators: %s: a list of comma separated error messages */ - __( - 'Some errors occurred while permanently deleting the posts: %s' - ), - [ ...errorMessages ].join( ',' ) - ); - } - } - createErrorNotice( errorMessage, { - type: 'snackbar', - } ); - } - }, -}; - const restorePostAction = { id: 'restore', label: __( 'Restore' ), @@ -826,9 +735,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { supportsTitle && renamePostAction, reorderPagesAction, ! isTemplateOrTemplatePart && ! isPattern && restorePostAction, - ! isTemplateOrTemplatePart && - ! isPattern && - permanentlyDeletePostAction, ...defaultActions, ].filter( Boolean ); // Filter actions based on provided context. If not provided diff --git a/packages/editor/src/dataviews/actions/index.ts b/packages/editor/src/dataviews/actions/index.ts index d6255b74be5d4a..6679b2d7d1b8f1 100644 --- a/packages/editor/src/dataviews/actions/index.ts +++ b/packages/editor/src/dataviews/actions/index.ts @@ -10,6 +10,7 @@ import deletePost from './delete-post'; import exportPattern from './export-pattern'; import resetPost from './reset-post'; import trashPost from './trash-post'; +import permanentlyDeletePost from './permanently-delete-post'; // @ts-ignore import { store as editorStore } from '../../store'; @@ -24,4 +25,5 @@ export default function registerDefaultActions() { registerEntityAction( 'postType', '*', resetPost ); registerEntityAction( 'postType', '*', deletePost ); registerEntityAction( 'postType', '*', trashPost ); + registerEntityAction( 'postType', '*', permanentlyDeletePost ); } diff --git a/packages/editor/src/dataviews/actions/permanently-delete-post.tsx b/packages/editor/src/dataviews/actions/permanently-delete-post.tsx new file mode 100644 index 00000000000000..42efb8a32850f3 --- /dev/null +++ b/packages/editor/src/dataviews/actions/permanently-delete-post.tsx @@ -0,0 +1,116 @@ +/** + * WordPress dependencies + */ +import { store as coreStore } from '@wordpress/core-data'; +import { __, sprintf } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; +import type { Action } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import { getItemTitle, isTemplateOrTemplatePart } from './utils'; +import type { CoreDataError, PostWithPermissions } from '../types'; + +const permanentlyDeletePost: Action< PostWithPermissions > = { + id: 'permanently-delete', + label: __( 'Permanently delete' ), + supportsBulk: true, + isEligible( item ) { + if ( isTemplateOrTemplatePart( item ) || item.type === 'wp_block' ) { + return false; + } + const { status, permissions } = item; + return status === 'trash' && permissions?.delete; + }, + async callback( posts, { registry, onActionPerformed } ) { + const { createSuccessNotice, createErrorNotice } = + registry.dispatch( noticesStore ); + const { deleteEntityRecord } = registry.dispatch( coreStore ); + const promiseResult = await Promise.allSettled( + posts.map( ( post ) => { + return deleteEntityRecord( + 'postType', + post.type, + post.id, + { force: true }, + { throwOnError: true } + ); + } ) + ); + // If all the promises were fulfilled with success. + if ( promiseResult.every( ( { status } ) => status === 'fulfilled' ) ) { + let successMessage; + if ( promiseResult.length === 1 ) { + successMessage = sprintf( + /* translators: The posts's title. */ + __( '"%s" permanently deleted.' ), + getItemTitle( posts[ 0 ] ) + ); + } else { + successMessage = __( 'The posts were permanently deleted.' ); + } + createSuccessNotice( successMessage, { + type: 'snackbar', + id: 'permanently-delete-post-action', + } ); + onActionPerformed?.( posts ); + } else { + // If there was at lease one failure. + let errorMessage; + // If we were trying to permanently delete a single post. + if ( promiseResult.length === 1 ) { + const typedError = promiseResult[ 0 ] as { + reason?: CoreDataError; + }; + if ( typedError.reason?.message ) { + errorMessage = typedError.reason.message; + } else { + errorMessage = __( + 'An error occurred while permanently deleting the post.' + ); + } + // If we were trying to permanently delete multiple posts + } else { + const errorMessages = new Set(); + const failedPromises = promiseResult.filter( + ( { status } ) => status === 'rejected' + ); + for ( const failedPromise of failedPromises ) { + const typedError = failedPromise as { + reason?: CoreDataError; + }; + if ( typedError.reason?.message ) { + errorMessages.add( typedError.reason.message ); + } + } + if ( errorMessages.size === 0 ) { + errorMessage = __( + 'An error occurred while permanently deleting the posts.' + ); + } else if ( errorMessages.size === 1 ) { + errorMessage = sprintf( + /* translators: %s: an error message */ + __( + 'An error occurred while permanently deleting the posts: %s' + ), + [ ...errorMessages ][ 0 ] + ); + } else { + errorMessage = sprintf( + /* translators: %s: a list of comma separated error messages */ + __( + 'Some errors occurred while permanently deleting the posts: %s' + ), + [ ...errorMessages ].join( ',' ) + ); + } + } + createErrorNotice( errorMessage, { + type: 'snackbar', + } ); + } + }, +}; + +export default permanentlyDeletePost; From 02fe91afe7480d3b52ceefabeb28a111feefbc23 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 30 Jul 2024 15:04:34 +0400 Subject: [PATCH 0161/1908] Core Data: Fix 'getEntityRecordPermissions' memoization (#64091) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/core-data/src/private-selectors.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/core-data/src/private-selectors.ts b/packages/core-data/src/private-selectors.ts index 7eb67973c67281..841f4ee2ef460d 100644 --- a/packages/core-data/src/private-selectors.ts +++ b/packages/core-data/src/private-selectors.ts @@ -57,7 +57,8 @@ export const getBlockPatternsForPostType = createRegistrySelector( export const getEntityRecordsPermissions = createRegistrySelector( ( select ) => createSelector( ( state: State, kind: string, name: string, ids: string[] ) => { - return ids.map( ( id ) => ( { + const normalizedIds = Array.isArray( ids ) ? ids : [ ids ]; + return normalizedIds.map( ( id ) => ( { delete: select( STORE_NAME ).canUser( 'delete', { kind, name, @@ -90,5 +91,5 @@ export function getEntityRecordPermissions( name: string, id: string ) { - return getEntityRecordsPermissions( state, kind, name, [ id ] )[ 0 ]; + return getEntityRecordsPermissions( state, kind, name, id )[ 0 ]; } From 68ccfe33ba68d2d7f5660135306097a184cde067 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:51:18 +0530 Subject: [PATCH 0162/1908] Loginout : Add border and color block support (#63550) * Add border support to loginout block * Set border control to appear by default * Add box sizing style to loginout block * Add color support in loginout block * Display border control as optional * Simplify the style for block Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- packages/block-library/src/loginout/block.json | 15 ++++++++++++++- packages/block-library/src/loginout/style.scss | 4 ++++ packages/block-library/src/style.scss | 1 + 4 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 packages/block-library/src/loginout/style.scss diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index e9818724b37271..dfe0f224c8f360 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -435,7 +435,7 @@ Show login & logout links. ([Source](https://github.com/WordPress/gutenberg/tree - **Name:** core/loginout - **Category:** theme -- **Supports:** className, interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight) +- **Supports:** className, color (background, gradients, link, ~~text~~), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight) - **Attributes:** displayLoginAsForm, redirectToCurrent ## Media & Text diff --git a/packages/block-library/src/loginout/block.json b/packages/block-library/src/loginout/block.json index 52619b1a3ba8b2..f2aaafd60fde05 100644 --- a/packages/block-library/src/loginout/block.json +++ b/packages/block-library/src/loginout/block.json @@ -22,6 +22,12 @@ }, "supports": { "className": true, + "color": { + "background": true, + "text": false, + "gradients": true, + "link": true + }, "spacing": { "margin": true, "padding": true, @@ -43,8 +49,15 @@ "fontSize": true } }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + }, "interactivity": { "clientNavigation": true } - } + }, + "style": "wp-block-loginout" } diff --git a/packages/block-library/src/loginout/style.scss b/packages/block-library/src/loginout/style.scss new file mode 100644 index 00000000000000..f13bb5ded552dd --- /dev/null +++ b/packages/block-library/src/loginout/style.scss @@ -0,0 +1,4 @@ +.wp-block-loginout { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; +} diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index c14699b4576103..db9d033d915db8 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -22,6 +22,7 @@ @import "./latest-comments/style.scss"; @import "./latest-posts/style.scss"; @import "./list/style.scss"; +@import "./loginout/style.scss"; @import "./media-text/style.scss"; @import "./navigation/style.scss"; @import "./navigation-link/style.scss"; From 083bb9196e6d1c2b9079dabc9a6eaa01d94b9449 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 30 Jul 2024 14:30:40 +0200 Subject: [PATCH 0163/1908] `RadioControl`: add support for option help text (#63751) * Add support for help text * Alternative, help text is not part of the label and describes the option * More meaningful help text in example * CHANGELOG * Refactor existing usages from custom labels to using the `helpText` property * Use the Text component for the help text * helpText => description * Remove nested ternary * Reuse basecontrol help text styles * Tweak spacing * Rename Storybook example * Remove unused import * Move vertical spacing before help text from row-gap to padding * Increase horizontal gap between radio and label * Tweak spacing * Add unit tests * Rework calculating and assigning element IDs for labels and descriptions * Use correct classname modifier * Add test comment --- packages/components/CHANGELOG.md | 4 + .../components/src/radio-control/index.tsx | 55 +++- .../src/radio-control/stories/index.story.tsx | 23 ++ .../components/src/radio-control/style.scss | 28 +- .../src/radio-control/test/index.tsx | 274 ++++++++++++++++++ .../components/src/radio-control/types.ts | 4 + .../src/components/post-comments/index.js | 27 +- .../src/components/post-status/index.js | 51 +--- .../src/components/site-discussion/index.js | 26 +- 9 files changed, 403 insertions(+), 89 deletions(-) create mode 100644 packages/components/src/radio-control/test/index.tsx diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 327f80ba2468ed..7cef1112b6a7c9 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -7,6 +7,10 @@ - `ColorPalette`: Remove extra bottom margin when `CircularOptionPicker` is unneeded ([#63961](https://github.com/WordPress/gutenberg/pull/63961)). - `CustomSelectControl`: Restore `describedBy` functionality ([#63957](https://github.com/WordPress/gutenberg/pull/63957)). +### Enhancements + +- `RadioControl`: add support for option help text ([#63751](https://github.com/WordPress/gutenberg/pull/63751)). + ### Internal - `DropdownMenuV2`: break menu item help text on multiple lines for better truncation. ([#63916](https://github.com/WordPress/gutenberg/pull/63916)). diff --git a/packages/components/src/radio-control/index.tsx b/packages/components/src/radio-control/index.tsx index 2a6f8e37cc8cb5..c574e5af539def 100644 --- a/packages/components/src/radio-control/index.tsx +++ b/packages/components/src/radio-control/index.tsx @@ -16,6 +16,16 @@ import BaseControl from '../base-control'; import type { WordPressComponentProps } from '../context'; import type { RadioControlProps } from './types'; import { VStack } from '../v-stack'; +import { useBaseControlProps } from '../base-control/hooks'; +import { StyledHelp } from '../base-control/styles/base-control-styles'; + +function generateOptionDescriptionId( radioGroupId: string, index: number ) { + return `${ radioGroupId }-${ index }-option-description`; +} + +function generateOptionId( radioGroupId: string, index: number ) { + return `${ radioGroupId }-${ index }`; +} /** * Render a user interface to select the user type using radio inputs. @@ -53,13 +63,23 @@ export function RadioControl( onChange, hideLabelFromVision, options = [], + id: preferredId, ...additionalProps } = props; - const instanceId = useInstanceId( RadioControl ); - const id = `inspector-radio-control-${ instanceId }`; + const id = useInstanceId( + RadioControl, + 'inspector-radio-control', + preferredId + ); + const onChangeValue = ( event: ChangeEvent< HTMLInputElement > ) => onChange( event.target.value ); + // Use `useBaseControlProps` to get the id of the help text. + const { + controlProps: { 'aria-describedby': helpTextId }, + } = useBaseControlProps( { id, help } ); + if ( ! options?.length ) { return null; } @@ -73,14 +93,19 @@ export function RadioControl( help={ help } className={ clsx( className, 'components-radio-control' ) } > - <VStack spacing={ 2 }> + <VStack + spacing={ 3 } + className={ clsx( 'components-radio-control__group-wrapper', { + 'has-help': !! help, + } ) } + > { options.map( ( option, index ) => ( <div - key={ `${ id }-${ index }` } + key={ generateOptionId( id, index ) } className="components-radio-control__option" > <input - id={ `${ id }-${ index }` } + id={ generateOptionId( id, index ) } className="components-radio-control__input" type="radio" name={ id } @@ -88,16 +113,32 @@ export function RadioControl( onChange={ onChangeValue } checked={ option.value === selected } aria-describedby={ - !! help ? `${ id }__help` : undefined + clsx( [ + !! option.description && + generateOptionDescriptionId( + id, + index + ), + helpTextId, + ] ) || undefined } { ...additionalProps } /> <label className="components-radio-control__label" - htmlFor={ `${ id }-${ index }` } + htmlFor={ generateOptionId( id, index ) } > { option.label } </label> + { !! option.description ? ( + <StyledHelp + __nextHasNoMarginBottom + id={ generateOptionDescriptionId( id, index ) } + className="components-radio-control__option-description" + > + { option.description } + </StyledHelp> + ) : null } </div> ) ) } </VStack> diff --git a/packages/components/src/radio-control/stories/index.story.tsx b/packages/components/src/radio-control/stories/index.story.tsx index 7be398e77e17c7..dae00e57962f47 100644 --- a/packages/components/src/radio-control/stories/index.story.tsx +++ b/packages/components/src/radio-control/stories/index.story.tsx @@ -68,3 +68,26 @@ Default.args = { { label: 'Password Protected', value: 'password' }, ], }; + +export const WithOptionDescriptions: StoryFn< typeof RadioControl > = + Template.bind( {} ); +WithOptionDescriptions.args = { + ...Default.args, + options: [ + { + label: 'Public', + value: 'public', + description: 'Visible to everyone', + }, + { + label: 'Private', + value: 'private', + description: 'Only visible to you', + }, + { + label: 'Password Protected', + value: 'password', + description: 'Protected by a password', + }, + ], +}; diff --git a/packages/components/src/radio-control/style.scss b/packages/components/src/radio-control/style.scss index a3d4abeb630d0d..7444ea1343b842 100644 --- a/packages/components/src/radio-control/style.scss +++ b/packages/components/src/radio-control/style.scss @@ -1,13 +1,23 @@ +.components-radio-control__group-wrapper.has-help { + margin-block-end: $grid-unit-15; +} + .components-radio-control__option { - display: flex; + display: grid; + grid-template-columns: auto 1fr; + grid-template-rows: auto minmax(0, max-content); + column-gap: $grid-unit-10; align-items: center; } .components-radio-control__input[type="radio"] { + grid-column: 1; + grid-row: 1; + @include radio-control; display: inline-flex; - margin: 0 $grid-unit-10 0 0; + margin: 0; padding: 0; appearance: none; cursor: pointer; @@ -28,6 +38,9 @@ } .components-radio-control__label { + grid-column: 2; + grid-row: 1; + cursor: pointer; line-height: $radio-input-size-sm; @@ -35,3 +48,14 @@ line-height: $radio-input-size; } } + +.components-radio-control__option-description { + grid-column: 2; + grid-row: 2; + + padding-block-start: $grid-unit-05; + + // Override the top margin of the StyledHelp component from BaseControl. + // TODO: we should tweak the StyledHelp component to not have a top margin. + margin-top: 0; +} diff --git a/packages/components/src/radio-control/test/index.tsx b/packages/components/src/radio-control/test/index.tsx new file mode 100644 index 00000000000000..0be166513a9a4d --- /dev/null +++ b/packages/components/src/radio-control/test/index.tsx @@ -0,0 +1,274 @@ +/** + * External dependencies + */ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import RadioControl from '../'; + +const ControlledRadioControl = ( { + ...props +}: React.ComponentProps< typeof RadioControl > ) => { + const [ option, setOption ] = useState( props.selected ); + + return ( + <RadioControl + { ...props } + onChange={ ( newValue ) => { + setOption( newValue ); + props.onChange?.( newValue ); + } } + selected={ option } + /> + ); +}; + +const defaultProps = { + options: [ + { label: 'Mouse', value: 'mouse' }, + { label: 'Cat', value: 'cat' }, + { label: 'Dog', value: 'dog' }, + ], + label: 'Animal', +}; + +const defaultPropsWithDescriptions = { + ...defaultProps, + options: defaultProps.options.map( ( option, index ) => ( { + ...option, + description: `This is the option number ${ index + 1 }.`, + } ) ), +}; + +describe.each( [ + // TODO: `RadioControl` doesn't currently support uncontrolled mode. + // [ 'uncontrolled', RadioControl ], + [ 'controlled', ControlledRadioControl ], +] )( 'RadioControl %s', ( ...modeAndComponent ) => { + const [ , Component ] = modeAndComponent; + + describe( 'semantics and labelling', () => { + it( 'should render radio inputs with accessible labels', () => { + const onChangeSpy = jest.fn(); + render( + <Component { ...defaultProps } onChange={ onChangeSpy } /> + ); + + for ( const option of defaultProps.options ) { + const optionEl = screen.getByRole( 'radio', { + name: option.label, + } ); + expect( optionEl ).toBeVisible(); + expect( optionEl ).not.toBeChecked(); + } + } ); + + it( 'should not select have a selected value when the `selected` prop does not match any available options', () => { + const onChangeSpy = jest.fn(); + render( + <Component { ...defaultProps } onChange={ onChangeSpy } /> + ); + + expect( + screen.queryByRole( 'radio', { + checked: true, + } ) + ).not.toBeInTheDocument(); + } ); + + it( 'should render mutually exclusive radio inputs', () => { + const onChangeSpy = jest.fn(); + render( + <Component + { ...defaultProps } + onChange={ onChangeSpy } + selected={ defaultProps.options[ 1 ].value } + /> + ); + + expect( + screen.getByRole( 'radio', { + checked: true, + } ) + ).toHaveAccessibleName( defaultProps.options[ 1 ].label ); + } ); + + it( 'should use the group help text to describe individual options', () => { + const onChangeSpy = jest.fn(); + render( + <Component + { ...defaultProps } + onChange={ onChangeSpy } + selected={ defaultProps.options[ 1 ].value } + help="Select your favorite animal." + /> + ); + + for ( const option of defaultProps.options ) { + expect( + screen.getByRole( 'radio', { name: option.label } ) + ).toHaveAccessibleDescription( 'Select your favorite animal.' ); + } + } ); + + it( 'should use the option description text to describe individual options', () => { + const onChangeSpy = jest.fn(); + render( + <Component + { ...defaultPropsWithDescriptions } + onChange={ onChangeSpy } + selected={ defaultProps.options[ 1 ].value } + /> + ); + + let index = 1; + for ( const option of defaultProps.options ) { + expect( + screen.getByRole( 'radio', { name: option.label } ) + ).toHaveAccessibleDescription( + `This is the option number ${ index }.` + ); + index += 1; + } + } ); + + it( 'should use both the option description text and the group help text to describe individual options', () => { + const onChangeSpy = jest.fn(); + render( + <Component + { ...defaultPropsWithDescriptions } + onChange={ onChangeSpy } + selected={ defaultProps.options[ 1 ].value } + help="Select your favorite animal" + /> + ); + + let index = 1; + for ( const option of defaultProps.options ) { + expect( + screen.getByRole( 'radio', { name: option.label } ) + ).toHaveAccessibleDescription( + `This is the option number ${ index }. Select your favorite animal` + ); + index += 1; + } + } ); + } ); + + describe( 'interaction', () => { + it( 'should select a new value when clicking on the radio input', async () => { + const user = userEvent.setup(); + const onChangeSpy = jest.fn(); + render( + <Component { ...defaultProps } onChange={ onChangeSpy } /> + ); + + // Click on the third radio, make sure it's selected. + await user.click( + screen.getByRole( 'radio', { + name: defaultProps.options[ 2 ].label, + } ) + ); + expect( + screen.getByRole( 'radio', { + checked: true, + } ) + ).toHaveAccessibleName( defaultProps.options[ 2 ].label ); + + expect( onChangeSpy ).toHaveBeenCalledTimes( 1 ); + expect( onChangeSpy ).toHaveBeenLastCalledWith( + defaultProps.options[ 2 ].value + ); + } ); + + it( 'should select a new value when clicking on the radio label', async () => { + const user = userEvent.setup(); + const onChangeSpy = jest.fn(); + render( + <Component { ...defaultProps } onChange={ onChangeSpy } /> + ); + + // Click on the second radio's label, make sure it selects the associated radio. + await user.click( + screen.getByText( defaultProps.options[ 1 ].label ) + ); + expect( + screen.getByRole( 'radio', { + checked: true, + } ) + ).toHaveAccessibleName( defaultProps.options[ 1 ].label ); + + expect( onChangeSpy ).toHaveBeenCalledTimes( 1 ); + expect( onChangeSpy ).toHaveBeenLastCalledWith( + defaultProps.options[ 1 ].value + ); + } ); + + it( 'should select a new value when using the arrow keys', async () => { + const user = userEvent.setup(); + const onChangeSpy = jest.fn(); + render( + <Component { ...defaultProps } onChange={ onChangeSpy } /> + ); + + await user.tab(); + + expect( + screen.getByRole( 'radio', { + name: defaultProps.options[ 0 ].label, + } ) + ).toHaveFocus(); + + await user.keyboard( '{ArrowDown}' ); + + expect( + screen.getByRole( 'radio', { + checked: true, + name: defaultProps.options[ 1 ].label, + } ) + ).toHaveFocus(); + expect( onChangeSpy ).toHaveBeenCalledTimes( 2 ); + expect( onChangeSpy ).toHaveBeenLastCalledWith( + defaultProps.options[ 1 ].value + ); + + await user.keyboard( '{ArrowDown}' ); + await user.keyboard( '{ArrowDown}' ); + + // The selection wrap around. + expect( + screen.getByRole( 'radio', { + checked: true, + name: defaultProps.options[ 0 ].label, + } ) + ).toHaveFocus(); + // TODO: why called twice for every interaction? + expect( onChangeSpy ).toHaveBeenCalledTimes( 6 ); + expect( onChangeSpy ).toHaveBeenLastCalledWith( + defaultProps.options[ 0 ].value + ); + + await user.keyboard( '{ArrowUp}' ); + + expect( + screen.getByRole( 'radio', { + checked: true, + name: defaultProps.options[ 2 ].label, + } ) + ).toHaveFocus(); + + expect( onChangeSpy ).toHaveBeenCalledTimes( 8 ); + expect( onChangeSpy ).toHaveBeenLastCalledWith( + defaultProps.options[ 2 ].value + ); + } ); + } ); +} ); diff --git a/packages/components/src/radio-control/types.ts b/packages/components/src/radio-control/types.ts index 43c5e147f028d9..d1c3aa40d96481 100644 --- a/packages/components/src/radio-control/types.ts +++ b/packages/components/src/radio-control/types.ts @@ -24,6 +24,10 @@ export type RadioControlProps = Pick< * The internal value compared against select and passed to onChange */ value: string; + /** + * Optional help text to be shown in addition the label. + */ + description?: string; }[]; /** * The value property of the currently selected option. diff --git a/packages/editor/src/components/post-comments/index.js b/packages/editor/src/components/post-comments/index.js index c8fac57d00e09d..1d331811b46b26 100644 --- a/packages/editor/src/components/post-comments/index.js +++ b/packages/editor/src/components/post-comments/index.js @@ -4,7 +4,6 @@ import { __, _x } from '@wordpress/i18n'; import { RadioControl, - __experimentalText as Text, __experimentalVStack as VStack, } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; @@ -16,29 +15,17 @@ import { store as editorStore } from '../../store'; const COMMENT_OPTIONS = [ { - label: ( - <> - { _x( 'Open', 'Adjective: e.g. "Comments are open"' ) } - <Text variant="muted" size={ 12 }> - { __( 'Visitors can add new comments and replies.' ) } - </Text> - </> - ), + label: _x( 'Open', 'Adjective: e.g. "Comments are open"' ), value: 'open', + description: __( 'Visitors can add new comments and replies.' ), }, { - label: ( - <> - { __( 'Closed' ) } - <Text variant="muted" size={ 12 }> - { __( 'Visitors cannot add new comments or replies.' ) } - </Text> - <Text variant="muted" size={ 12 }> - { __( 'Existing comments remain visible.' ) } - </Text> - </> - ), + label: __( 'Closed' ), value: 'closed', + description: [ + __( 'Visitors cannot add new comments or replies.' ), + __( 'Existing comments remain visible.' ), + ].join( ' ' ), }, ]; diff --git a/packages/editor/src/components/post-status/index.js b/packages/editor/src/components/post-status/index.js index 11b51bca80aa79..d0b5ac93977330 100644 --- a/packages/editor/src/components/post-status/index.js +++ b/packages/editor/src/components/post-status/index.js @@ -5,7 +5,6 @@ import { Button, CheckboxControl, Dropdown, - __experimentalText as Text, __experimentalVStack as VStack, TextControl, RadioControl, @@ -49,59 +48,29 @@ const postStatusesInfo = { export const STATUS_OPTIONS = [ { - label: ( - <> - { __( 'Draft' ) } - <Text variant="muted" size={ 12 }> - { __( 'Not ready to publish.' ) } - </Text> - </> - ), + label: __( 'Draft' ), value: 'draft', + description: __( 'Not ready to publish.' ), }, { - label: ( - <> - { __( 'Pending' ) } - <Text variant="muted" size={ 12 }> - { __( 'Waiting for review before publishing.' ) } - </Text> - </> - ), + label: __( 'Pending' ), value: 'pending', + description: __( 'Waiting for review before publishing.' ), }, { - label: ( - <> - { __( 'Private' ) } - <Text variant="muted" size={ 12 }> - { __( 'Only visible to site admins and editors.' ) } - </Text> - </> - ), + label: __( 'Private' ), value: 'private', + description: __( 'Only visible to site admins and editors.' ), }, { - label: ( - <> - { __( 'Scheduled' ) } - <Text variant="muted" size={ 12 }> - { __( 'Publish automatically on a chosen date.' ) } - </Text> - </> - ), + label: __( 'Scheduled' ), value: 'future', + description: __( 'Publish automatically on a chosen date.' ), }, { - label: ( - <> - { __( 'Published' ) } - <Text variant="muted" size={ 12 }> - { __( 'Visible to everyone.' ) } - </Text> - </> - ), + label: __( 'Published' ), value: 'publish', + description: __( 'Visible to everyone.' ), }, ]; diff --git a/packages/editor/src/components/site-discussion/index.js b/packages/editor/src/components/site-discussion/index.js index b35ba9db476570..5b4d213148341d 100644 --- a/packages/editor/src/components/site-discussion/index.js +++ b/packages/editor/src/components/site-discussion/index.js @@ -23,29 +23,17 @@ import { store as editorStore } from '../../store'; const COMMENT_OPTIONS = [ { - label: ( - <> - { _x( 'Open', 'Adjective: e.g. "Comments are open"' ) } - <Text variant="muted" size={ 12 }> - { __( 'Visitors can add new comments and replies.' ) } - </Text> - </> - ), + label: _x( 'Open', 'Adjective: e.g. "Comments are open"' ), value: 'open', + description: __( 'Visitors can add new comments and replies.' ), }, { - label: ( - <> - { __( 'Closed' ) } - <Text variant="muted" size={ 12 }> - { __( 'Visitors cannot add new comments or replies.' ) } - </Text> - <Text variant="muted" size={ 12 }> - { __( 'Existing comments remain visible.' ) } - </Text> - </> - ), + label: __( 'Closed' ), value: '', + description: [ + __( 'Visitors cannot add new comments or replies.' ), + __( 'Existing comments remain visible.' ), + ].join( ' ' ), }, ]; From 78a3e71ec3ff85944324c99b4128d6cb5cac5542 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Tue, 30 Jul 2024 14:48:33 +0200 Subject: [PATCH 0164/1908] Block bindings: UI for connecting bindings (#62880) * Initial experiment * First experiment of raw custom field for P * use selectors * Use lists * Remove * Fix removing * Add new ui * Update attributes * Check binded number * Check binded number * Move bindings panel to editor * Move code * Move to utils * Use tools panel for connections * Add reset * Add bordered items * Fix some styles * Move utils back to component * Remove not needed comments * Some refactor * Prevent UI with no meta data * Add helper * Add helper * Add simple e2e * Add one more menuitem to the list * Update e2e tests now a new tab appears by default * Another test * Add e2e to check paragraph * Remove not needed experiment * Remove extra blank spaces * update e2e * Keep updating e2e * Remove css to the minimum * Less CSS * Abstract fields and move hooks back to block-editor * Return null when no bindableAttributes * Add checks to registration * Fix when the list of fields is empty * Properly filter footnotes * Update tests * Remove classes from component * Remove all components mention * Add ignore console error * Add icons and fix styling * Remove not needed as p * Remove icon * Remove icons, show label only if there are more than one source * Simplify style names * Adapt design * Use `ItemGroup` inside `ToolsPanel` * Use `Text` component * Use `getBlockBindingsSources` function * Revert change to popover max-width * Remove not used classes * Remove unused props * Add fallbacks for undefined keys * Try: Use `DropdownMenuV2` * Add button to remove the binding * Reduce truncate lines to 1 * Fix labels when multiple sources * Try: Add readOnly support when fields are undefined * Use RadioItem instead of Checkbox * Remove "Clear" button * Remove clear button CSS * Don't use DropdownItems outside Dropdown * Move separator inside menu group * Use onChange to better align with radio behavior * Add aria-hiddden to group heading * Update tests * Reduce custom styles * Properly add block context after latest changes * Adapt tests * Remove `numberOfLines` prop * Remove unused class * Fix mobile popover * Move Separator outside of `DropdownMenuGroup` * Remove empty sources from `fieldsList` * Move UI under experimental flag * Adapt e2e changes to experimental flag * Remove missing clicks in tests * Adapt another test --------- Unlinked contributors: jarekmorawski. Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: sc0ttkclark <sc0ttkclark@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: paaljoachim <paaljoachim@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: seifeldinio <seifradwane@git.wordpress.org> --- lib/experimental/editor-settings.php | 3 + lib/experiments-page.php | 12 + .../block-editor/src/hooks/block-bindings.js | 355 +++++++++++++++--- .../src/hooks/block-bindings.scss | 15 +- packages/block-editor/src/hooks/index.js | 2 +- .../src/hooks/use-bindings-attributes.js | 4 + packages/block-editor/src/style.scss | 2 +- packages/blocks/src/api/registration.js | 9 + packages/blocks/src/api/test/registration.js | 17 + packages/blocks/src/store/private-actions.js | 1 + packages/blocks/src/store/reducer.js | 1 + packages/editor/src/bindings/post-meta.js | 20 + .../editor/various/block-bindings.spec.js | 182 ++++++++- 13 files changed, 563 insertions(+), 60 deletions(-) diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index 09ac4b6990d919..065264fd124e8c 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -34,6 +34,9 @@ function gutenberg_enable_experiments() { if ( $gutenberg_experiments && array_key_exists( 'gutenberg-quick-edit-dataviews', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalQuickEditDataViews = true', 'before' ); } + if ( $gutenberg_experiments && array_key_exists( 'gutenberg-block-bindings-ui', $gutenberg_experiments ) ) { + wp_add_inline_script( 'wp-block-editor', 'window.__experimentalBlockBindingsUI = true', 'before' ); + } } add_action( 'admin_init', 'gutenberg_enable_experiments' ); diff --git a/lib/experiments-page.php b/lib/experiments-page.php index 7cc4198c14ef91..acb095b47fde30 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -163,6 +163,18 @@ function gutenberg_initialize_experiments_settings() { ) ); + add_settings_field( + 'gutenberg-block-bindings-ui', + __( 'UI to create block bindings', 'gutenberg' ), + 'gutenberg_display_experiment_field', + 'gutenberg-experiments', + 'gutenberg_experiments_section', + array( + 'label' => __( 'Add UI to create and update block bindings in block inspector controls.', 'gutenberg' ), + 'id' => 'gutenberg-block-bindings-ui', + ) + ); + register_setting( 'gutenberg-experiments', 'gutenberg-experiments' diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index c61f586575a530..ce3fdd2f327c40 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -2,42 +2,199 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { store as blocksStore } from '@wordpress/blocks'; +import { privateApis as blocksPrivateApis } from '@wordpress/blocks'; import { - BaseControl, - PanelBody, - __experimentalHStack as HStack, __experimentalItemGroup as ItemGroup, __experimentalItem as Item, + __experimentalText as Text, + __experimentalToolsPanel as ToolsPanel, + __experimentalToolsPanelItem as ToolsPanelItem, + __experimentalTruncate as Truncate, + __experimentalVStack as VStack, + privateApis as componentsPrivateApis, } from '@wordpress/components'; -import { useSelect } from '@wordpress/data'; +import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; +import { useContext, Fragment } from '@wordpress/element'; +import { useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies */ -import { canBindAttribute } from '../hooks/use-bindings-attributes'; +import { + canBindAttribute, + getBindableAttributes, +} from '../hooks/use-bindings-attributes'; +import { store as blockEditorStore } from '../store'; import { unlock } from '../lock-unlock'; import InspectorControls from '../components/inspector-controls'; +import BlockContext from '../components/block-context'; + +const { + DropdownMenuV2: DropdownMenu, + DropdownMenuGroupV2: DropdownMenuGroup, + DropdownMenuRadioItemV2: DropdownMenuRadioItem, + DropdownMenuItemLabelV2: DropdownMenuItemLabel, + DropdownMenuItemHelpTextV2: DropdownMenuItemHelpText, + DropdownMenuSeparatorV2: DropdownMenuSeparator, +} = unlock( componentsPrivateApis ); + +const useToolsPanelDropdownMenuProps = () => { + const isMobile = useViewportMatch( 'medium', '<' ); + return ! isMobile + ? { + popoverProps: { + placement: 'left-start', + // For non-mobile, inner sidebar width (248px) - button width (24px) - border (1px) + padding (16px) + spacing (20px) + offset: 259, + }, + } + : {}; +}; + +function BlockBindingsPanelDropdown( { + fieldsList, + addConnection, + attribute, + binding, +} ) { + const currentKey = binding?.args?.key; + return ( + <> + { Object.entries( fieldsList ).map( ( [ label, fields ], i ) => ( + <Fragment key={ label }> + <DropdownMenuGroup> + { Object.keys( fieldsList ).length > 1 && ( + <Text + className="block-editor-bindings__source-label" + upperCase + variant="muted" + aria-hidden + > + { label } + </Text> + ) } + { Object.entries( fields ).map( ( [ key, value ] ) => ( + <DropdownMenuRadioItem + key={ key } + onChange={ () => + addConnection( key, attribute ) + } + name={ attribute + '-binding' } + value={ key } + checked={ key === currentKey } + > + <DropdownMenuItemLabel> + { key } + </DropdownMenuItemLabel> + <DropdownMenuItemHelpText> + { value } + </DropdownMenuItemHelpText> + </DropdownMenuRadioItem> + ) ) } + </DropdownMenuGroup> + { i !== Object.keys( fieldsList ).length - 1 && ( + <DropdownMenuSeparator /> + ) } + </Fragment> + ) ) } + </> + ); +} + +function BlockBindingsAttribute( { attribute, binding } ) { + const { source: sourceName, args } = binding || {}; + const sourceProps = + unlock( blocksPrivateApis ).getBlockBindingsSource( sourceName ); + return ( + <VStack> + <Truncate>{ attribute }</Truncate> + { !! binding && ( + <Text + variant="muted" + className="block-editor-bindings__item-explanation" + > + <Truncate> + { args?.key || sourceProps?.label || sourceName } + </Truncate> + </Text> + ) } + </VStack> + ); +} + +function ReadOnlyBlockBindingsPanelItems( { bindings } ) { + return ( + <> + { Object.entries( bindings ).map( ( [ attribute, binding ] ) => ( + <Item key={ attribute }> + <BlockBindingsAttribute + attribute={ attribute } + binding={ binding } + /> + </Item> + ) ) } + </> + ); +} + +function EditableBlockBindingsPanelItems( { + attributes, + bindings, + fieldsList, + addConnection, + removeConnection, +} ) { + const isMobile = useViewportMatch( 'medium', '<' ); + return ( + <> + { attributes.map( ( attribute ) => { + const binding = bindings[ attribute ]; + return ( + <ToolsPanelItem + key={ attribute } + hasValue={ () => !! binding } + label={ attribute } + onDeselect={ () => { + removeConnection( attribute ); + } } + > + <DropdownMenu + placement={ + isMobile ? 'bottom-start' : 'left-start' + } + gutter={ isMobile ? 8 : 36 } + className="block-editor-bindings__popover" + trigger={ + <Item> + <BlockBindingsAttribute + attribute={ attribute } + binding={ binding } + /> + </Item> + } + > + <BlockBindingsPanelDropdown + fieldsList={ fieldsList } + addConnection={ addConnection } + attribute={ attribute } + binding={ binding } + /> + </DropdownMenu> + </ToolsPanelItem> + ); + } ) } + </> + ); +} export const BlockBindingsPanel = ( { name, metadata } ) => { + const registry = useRegistry(); + const blockContext = useContext( BlockContext ); const { bindings } = metadata || {}; - const { sources } = useSelect( ( select ) => { - const _sources = unlock( - select( blocksStore ) - ).getAllBlockBindingsSources(); - return { - sources: _sources, - }; - }, [] ); - - if ( ! bindings ) { - return null; - } + const bindableAttributes = getBindableAttributes( name ); + const dropdownMenuProps = useToolsPanelDropdownMenuProps(); - // Don't show not allowed attributes. - // Don't show the bindings connected to pattern overrides in the inspectors panel. - // TODO: Explore if this should be abstracted to let other sources decide. const filteredBindings = { ...bindings }; Object.keys( filteredBindings ).forEach( ( key ) => { if ( @@ -48,43 +205,137 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { } } ); - if ( Object.keys( filteredBindings ).length === 0 ) { + const { updateBlockAttributes } = useDispatch( blockEditorStore ); + + const { _id } = useSelect( ( select ) => { + const { getSelectedBlockClientId } = select( blockEditorStore ); + + return { + _id: getSelectedBlockClientId(), + }; + }, [] ); + + if ( ! bindableAttributes || bindableAttributes.length === 0 ) { + return null; + } + + const removeAllConnections = () => { + const newMetadata = { ...metadata }; + delete newMetadata.bindings; + updateBlockAttributes( _id, { + metadata: + Object.keys( newMetadata ).length === 0 + ? undefined + : newMetadata, + } ); + }; + + const addConnection = ( value, attribute ) => { + // Assuming the block expects a flat structure for its metadata attribute + const newMetadata = { + ...metadata, + // Adjust this according to the actual structure expected by your block + bindings: { + ...metadata?.bindings, + [ attribute ]: { + source: 'core/post-meta', + args: { key: value }, + }, + }, + }; + // Update the block's attributes with the new metadata + updateBlockAttributes( _id, { + metadata: newMetadata, + } ); + }; + + const removeConnection = ( key ) => { + const newMetadata = { ...metadata }; + if ( ! newMetadata.bindings ) { + return; + } + + delete newMetadata.bindings[ key ]; + if ( Object.keys( newMetadata.bindings ).length === 0 ) { + delete newMetadata.bindings; + } + updateBlockAttributes( _id, { + metadata: + Object.keys( newMetadata ).length === 0 + ? undefined + : newMetadata, + } ); + }; + + const fieldsList = {}; + const { getBlockBindingsSources } = unlock( blocksPrivateApis ); + const registeredSources = getBlockBindingsSources(); + Object.values( registeredSources ).forEach( + ( { getFieldsList, label, usesContext } ) => { + if ( getFieldsList ) { + // Populate context. + const context = {}; + if ( usesContext?.length ) { + for ( const key of usesContext ) { + context[ key ] = blockContext[ key ]; + } + } + const sourceList = getFieldsList( { + registry, + context, + } ); + // Only add source if the list is not empty. + if ( sourceList ) { + fieldsList[ label ] = { ...sourceList }; + } + } + } + ); + // Remove empty sources. + Object.entries( fieldsList ).forEach( ( [ key, value ] ) => { + if ( ! Object.keys( value ).length ) { + delete fieldsList[ key ]; + } + } ); + + // Lock the UI when the experiment is not enabled or there are no fields to connect to. + const readOnly = + ! window.__experimentalBlockBindingsUI || + ! Object.keys( fieldsList ).length; + + if ( readOnly && Object.keys( filteredBindings ).length === 0 ) { return null; } return ( <InspectorControls> - <PanelBody - title={ __( 'Attributes' ) } - className="components-panel__block-bindings-panel" + <ToolsPanel + label={ __( 'Attributes' ) } + resetAll={ () => { + removeAllConnections(); + } } + dropdownMenuProps={ dropdownMenuProps } + className="block-editor-bindings__panel" > - <BaseControl - help={ __( 'Attributes connected to various sources.' ) } - > - <ItemGroup isBordered isSeparated size="large"> - { Object.keys( filteredBindings ).map( ( key ) => { - return ( - <Item key={ key }> - <HStack> - <span>{ key }</span> - <span className="components-item__block-bindings-source"> - { sources[ - filteredBindings[ key ].source - ] - ? sources[ - filteredBindings[ key ] - .source - ].label - : filteredBindings[ key ] - .source } - </span> - </HStack> - </Item> - ); - } ) } - </ItemGroup> - </BaseControl> - </PanelBody> + <ItemGroup isBordered isSeparated> + { readOnly ? ( + <ReadOnlyBlockBindingsPanelItems + bindings={ filteredBindings } + /> + ) : ( + <EditableBlockBindingsPanelItems + attributes={ bindableAttributes } + bindings={ filteredBindings } + fieldsList={ fieldsList } + addConnection={ addConnection } + removeConnection={ removeConnection } + /> + ) } + </ItemGroup> + <Text variant="muted"> + { __( 'Attributes connected to various sources.' ) } + </Text> + </ToolsPanel> </InspectorControls> ); }; diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss index fd46674ad11426..73e7c490160d3e 100644 --- a/packages/block-editor/src/hooks/block-bindings.scss +++ b/packages/block-editor/src/hooks/block-bindings.scss @@ -1,3 +1,14 @@ -.components-panel__block-bindings-panel .components-item__block-bindings-source { - color: $gray-700; +div.block-editor-bindings__panel { + grid-template-columns: auto; + button:hover .block-editor-bindings__item-explanation { + color: inherit; + } +} + +.block-editor-bindings__popover { + // This won't be needed if `DropdownMenuGroup` component handles the label. + .block-editor-bindings__source-label { + grid-column: 2; + margin: $grid-unit-10 0; + } } diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index b58ede2e9d389d..2f74640ef4f633 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -37,7 +37,6 @@ import './grid-visualizer'; createBlockEditFilter( [ - blockBindingsPanel, align, textAlign, anchor, @@ -48,6 +47,7 @@ createBlockEditFilter( layout, contentLockUI, blockHooks, + blockBindingsPanel, childLayout, ].filter( Boolean ) ); diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index 54b5425bfc44a5..4cac29a8bc5e91 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -91,6 +91,10 @@ export function canBindAttribute( blockName, attributeName ) { ); } +export function getBindableAttributes( blockName ) { + return BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ]; +} + export const withBlockBindingSupport = createHigherOrderComponent( ( BlockEdit ) => ( props ) => { const registry = useRegistry(); diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index e7e4b75d0a30f0..47b87bb50918df 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -46,8 +46,8 @@ @import "./components/tool-selector/style.scss"; @import "./components/url-input/style.scss"; @import "./components/url-popover/style.scss"; -@import "./hooks/block-bindings.scss"; @import "./hooks/block-hooks.scss"; +@import "./hooks/block-bindings.scss"; @import "./hooks/border.scss"; @import "./hooks/color.scss"; @import "./hooks/dimensions.scss"; diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 7cce959c78cc80..e109a7e562f00e 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -775,6 +775,7 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { * @param {Function} [source.setValues] Function to update multiple values connected to the source. * @param {Function} [source.getPlaceholder] Function to get the placeholder when the value is undefined. * @param {Function} [source.canUserEditValue] Function to determine if the user can edit the value. + * @param {Function} [source.getFieldsList] Function to get the lists of fields to expose in the connections panel. * * @example * ```js @@ -800,6 +801,7 @@ export const registerBlockBindingsSource = ( source ) => { setValues, getPlaceholder, canUserEditValue, + getFieldsList, } = source; const existingSource = unlock( @@ -899,6 +901,13 @@ export const registerBlockBindingsSource = ( source ) => { return; } + // Check the `getFieldsList` property is correct. + if ( getFieldsList && typeof getFieldsList !== 'function' ) { + // eslint-disable-next-line no-console + warning( 'Block bindings source getFieldsList must be a function.' ); + return; + } + return unlock( dispatch( blocksStore ) ).addBlockBindingsSource( source ); }; diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index cc339e59d27053..874d664f139047 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -1656,6 +1656,19 @@ describe( 'blocks', () => { expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); } ); + // Check the `getFieldsList` callback is correct. + it( 'should reject invalid getFieldsList callback', () => { + registerBlockBindingsSource( { + name: 'core/testing', + label: 'testing', + getFieldsList: 'should be a function', + } ); + expect( console ).toHaveWarnedWith( + 'Block bindings source getFieldsList must be a function.' + ); + expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); + } ); + // Check correct sources are registered as expected. it( 'should register a valid source', () => { const sourceProperties = { @@ -1665,6 +1678,9 @@ describe( 'blocks', () => { setValues: () => 'new values', getPlaceholder: () => 'placeholder', canUserEditValue: () => true, + getFieldsList: () => { + return { field: 'value' }; + }, }; registerBlockBindingsSource( { name: 'core/valid-source', @@ -1687,6 +1703,7 @@ describe( 'blocks', () => { expect( source.setValues ).toBeUndefined(); expect( source.getPlaceholder ).toBeUndefined(); expect( source.canUserEditValue ).toBeUndefined(); + expect( source.getFieldsList ).toBeUndefined(); unregisterBlockBindingsSource( 'core/valid-source' ); } ); diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index 977270cf1d0c97..6d2f7598ef7838 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -56,6 +56,7 @@ export function addBlockBindingsSource( source ) { setValues: source.setValues, getPlaceholder: source.getPlaceholder, canUserEditValue: source.canUserEditValue, + getFieldsList: source.getFieldsList, }; } diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 9fd97f0937b332..0851fc2bede4ca 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -401,6 +401,7 @@ export function blockBindingsSources( state = {}, action ) { setValues: action.setValues, getPlaceholder: action.getPlaceholder, canUserEditValue: action.canUserEditValue, + getFieldsList: action.getFieldsList, }, }; case 'ADD_BOOTSTRAPPED_BLOCK_BINDINGS_SOURCE': diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index aafc784a21bd4a..298ec4d8ba1535 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -75,4 +75,24 @@ export default { return true; }, + getFieldsList( { registry, context } ) { + const metaFields = registry + .select( coreDataStore ) + .getEditedEntityRecord( + 'postType', + context?.postType, + context?.postId + ).meta; + + if ( ! metaFields || ! Object.keys( metaFields ).length ) { + return null; + } + + // Remove footnotes from the list of fields + return Object.fromEntries( + Object.entries( metaFields ).filter( + ( [ key ] ) => key !== 'footnotes' + ) + ); + }, }; diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index 1499e255482c63..d0e1f079ce8439 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -1390,6 +1390,70 @@ test.describe( 'Block bindings', () => { 'false' ); } ); + test( 'should show a selector for content', async ( { + editor, + page, + } ) => { + // Activate the block bindings UI experiment. + await page.evaluate( () => { + window.__experimentalBlockBindingsUI = true; + } ); + + await editor.insertBlock( { + name: 'core/paragraph', + } ); + await page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByLabel( 'Attributes options' ) + .click(); + const contentAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show content', + } ); + await expect( contentAttribute ).toBeVisible(); + } ); + test( 'should use a selector to update the content', async ( { + editor, + page, + } ) => { + // Activate the block bindings UI experiment. + await page.evaluate( () => { + window.__experimentalBlockBindingsUI = true; + } ); + + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'fallback value', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { key: 'undefined_field' }, + }, + }, + }, + }, + } ); + await page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByRole( 'button', { name: 'content' } ) + .click(); + + await page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'text_custom_field' } ) + .click(); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( + 'Value of the text_custom_field' + ); + } ); } ); test.describe( 'Heading', () => { @@ -1471,6 +1535,29 @@ test.describe( 'Block bindings', () => { await expect( newEmptyParagraph ).toHaveText( '' ); await expect( newEmptyParagraph ).toBeEditable(); } ); + test( 'should show a selector for content', async ( { + editor, + page, + } ) => { + // Activate the block bindings UI experiment. + await page.evaluate( () => { + window.__experimentalBlockBindingsUI = true; + } ); + + await editor.insertBlock( { + name: 'core/heading', + } ); + await page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByLabel( 'Attributes options' ) + .click(); + const contentAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show content', + } ); + await expect( contentAttribute ).toBeVisible(); + } ); } ); test.describe( 'Button', () => { @@ -1648,6 +1735,56 @@ test.describe( 'Block bindings', () => { await expect( newEmptyButton ).toHaveText( '' ); await expect( newEmptyButton ).toBeEditable(); } ); + test( 'should show a selector for url, text, linkTarget and rel', async ( { + editor, + page, + } ) => { + // Activate the block bindings UI experiment. + await page.evaluate( () => { + window.__experimentalBlockBindingsUI = true; + } ); + + await editor.insertBlock( { + name: 'core/buttons', + innerBlocks: [ + { + name: 'core/button', + }, + ], + } ); + await editor.canvas + .getByRole( 'document', { + name: 'Block: Button', + exact: true, + } ) + .getByRole( 'textbox' ) + .click(); + await page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByLabel( 'Attributes options' ) + .click(); + const urlAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show url', + } ); + await expect( urlAttribute ).toBeVisible(); + const textAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show text', + } ); + await expect( textAttribute ).toBeVisible(); + const linkTargetAttribute = page.getByRole( + 'menuitemcheckbox', + { + name: 'Show linkTarget', + } + ); + await expect( linkTargetAttribute ).toBeVisible(); + const relAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show rel', + } ); + await expect( relAttribute ).toBeVisible(); + } ); } ); test.describe( 'Image', () => { @@ -1933,6 +2070,41 @@ test.describe( 'Block bindings', () => { 'default title value' ); } ); + test( 'should show a selector for url, id, title and alt', async ( { + editor, + page, + } ) => { + // Activate the block bindings UI experiment. + await page.evaluate( () => { + window.__experimentalBlockBindingsUI = true; + } ); + + await editor.insertBlock( { + name: 'core/image', + } ); + await page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByLabel( 'Attributes options' ) + .click(); + const urlAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show url', + } ); + await expect( urlAttribute ).toBeVisible(); + const idAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show id', + } ); + await expect( idAttribute ).toBeVisible(); + const titleAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show title', + } ); + await expect( titleAttribute ).toBeVisible(); + const altAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show alt', + } ); + await expect( altAttribute ).toBeVisible(); + } ); } ); test.describe( 'Edit custom fields', () => { @@ -2195,10 +2367,12 @@ test.describe( 'Block bindings', () => { }, } ); - const bindingLabel = page.locator( - '.components-item__block-bindings-source' - ); - await expect( bindingLabel ).toHaveText( 'Server Source' ); + const bindingsPanel = page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .locator( '.block-editor-bindings__panel' ); + await expect( bindingsPanel ).toContainText( 'Server Source' ); } ); } ); } ); From f0700921483b2c580d32d261e403da829273a8c5 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 30 Jul 2024 17:47:46 +0400 Subject: [PATCH 0165/1908] Editor: Remove resolvers hack for post actions (#64094) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../src/components/post-actions/actions.js | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 8d8b42435f084a..0d5ac4764c37da 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -681,25 +681,17 @@ export const duplicateTemplatePartAction = { }; export function usePostActions( { postType, onActionPerformed, context } ) { - const { - defaultActions, - postTypeObject, - userCanCreatePostType, - cachedCanUserResolvers, - } = useSelect( + const { defaultActions, postTypeObject, userCanCreatePostType } = useSelect( ( select ) => { - const { getPostType, canUser, getCachedResolvers } = - select( coreStore ); + const { getPostType, canUser } = select( coreStore ); const { getEntityActions } = unlock( select( editorStore ) ); - const _postTypeObject = getPostType( postType ); return { - postTypeObject: _postTypeObject, + postTypeObject: getPostType( postType ), defaultActions: getEntityActions( 'postType', postType ), userCanCreatePostType: canUser( 'create', { kind: 'postType', name: postType, } ), - cachedCanUserResolvers: getCachedResolvers()?.canUser, }; }, [ postType ] @@ -798,9 +790,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { } return actions; - // We are making this use memo depend on cachedCanUserResolvers as a way to make the component using this hook re-render - // when user capabilities are resolved. This makes sure the isEligible functions of actions dependent on capabilities are re-evaluated. - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ defaultActions, userCanCreatePostType, @@ -814,6 +803,5 @@ export function usePostActions( { postType, onActionPerformed, context } ) { supportsRevisions, supportsTitle, context, - cachedCanUserResolvers, ] ); } From 1a1cf393f245e2984e73375c46aba97b75f1363e Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Tue, 30 Jul 2024 16:15:41 +0100 Subject: [PATCH 0166/1908] Add radius scale (#64007) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: hanneslsm <hanneslsm@git.wordpress.org> --- packages/base-styles/_variables.scss | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/base-styles/_variables.scss b/packages/base-styles/_variables.scss index f5a9ec38824ff3..b26d70b7299f9f 100644 --- a/packages/base-styles/_variables.scss +++ b/packages/base-styles/_variables.scss @@ -39,6 +39,17 @@ $grid-unit-60: 6 * $grid-unit; // 48px $grid-unit-70: 7 * $grid-unit; // 56px $grid-unit-80: 8 * $grid-unit; // 64px +/** + * Radius scale. + */ + +$radius-x-small: 1px; // Applied to elements like buttons nested within primitives like inputs. +$radius-small: 2px; // Applied to most primitives. +$radius-medium: 4px; // Applied to containers with smaller padding. +$radius-large: 8px; // Applied to containers with larger padding. +$radius-full: 9999px; // For lozenges. +$radius-round: 50%; // For circles and ovals. + /** * Dimensions. */ @@ -90,13 +101,12 @@ $border-width: 1px; $border-width-focus-fallback: 2px; // This exists as a fallback, and is ideally overridden by var(--wp-admin-border-width-focus) unless in some SASS math cases. $border-width-tab: 1.5px; $helptext-font-size: 12px; -$radius-round: 50%; -$radius-block-ui: 2px; $radio-input-size: 16px; $radio-input-size-sm: 24px; // Width & height for small viewports. // Deprecated, please avoid using these. $block-padding: 14px; // Used to define space between block footprint and surrouding borders. +$radius-block-ui: $radius-small; /** From 144f27cb7b98461eaab75825a24650ac04ed8a40 Mon Sep 17 00:00:00 2001 From: Adam Silverstein <adamjs@google.com> Date: Tue, 30 Jul 2024 09:28:05 -0600 Subject: [PATCH 0167/1908] Add User Timings for the Interactivity API (#60522) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * WIP add some user timings for interactivity API * return results, fix on wrapping * label cleanup * Update on handler from trunk * Use namespace for notations * Wrap insturmentation in SCRIPT_DEBUG check * Update packages/interactivity/src/directives.js Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> * Add check for globalThis.IS_GUTENBERG_PLUGIN * Simplify API calls * Simplify API calls, part 2 --------- Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> --- packages/interactivity/src/directives.tsx | 79 ++++++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/packages/interactivity/src/directives.tsx b/packages/interactivity/src/directives.tsx index fa59965607946f..60ddf13375a8a1 100644 --- a/packages/interactivity/src/directives.tsx +++ b/packages/interactivity/src/directives.tsx @@ -295,7 +295,33 @@ export default () => { // data-wp-watch--[name] directive( 'watch', ( { directives: { watch }, evaluate } ) => { watch.forEach( ( entry ) => { - useWatch( () => evaluate( entry ) ); + useWatch( () => { + let start; + if ( globalThis.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.SCRIPT_DEBUG ) { + // eslint-disable-next-line no-unused-vars + start = performance.now(); + } + } + const result = evaluate( entry ); + if ( globalThis.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.SCRIPT_DEBUG ) { + performance.measure( + `interactivity api watch ${ entry.namespace }`, + { + start, + end: performance.now(), + detail: { + devtools: { + track: `IA: watch ${ entry.namespace }`, + }, + }, + } + ); + } + } + return result; + } ); } ); } ); @@ -303,7 +329,33 @@ export default () => { directive( 'init', ( { directives: { init }, evaluate } ) => { init.forEach( ( entry ) => { // TODO: Replace with useEffect to prevent unneeded scopes. - useInit( () => evaluate( entry ) ); + useInit( () => { + let start; + if ( globalThis.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.SCRIPT_DEBUG ) { + start = performance.now(); + } + } + const result = evaluate( entry ); + if ( globalThis.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.SCRIPT_DEBUG ) { + performance.measure( + `interactivity api init ${ entry.namespace }`, + { + // eslint-disable-next-line no-undef + start, + end: performance.now(), + detail: { + devtools: { + track: `IA: init ${ entry.namespace }`, + }, + }, + } + ); + } + } + return result; + } ); } ); } ); @@ -327,7 +379,30 @@ export default () => { if ( existingHandler ) { existingHandler( event ); } + let start; + if ( globalThis.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.SCRIPT_DEBUG ) { + start = performance.now(); + } + } evaluate( entry, event ); + if ( globalThis.IS_GUTENBERG_PLUGIN ) { + if ( globalThis.SCRIPT_DEBUG ) { + performance.measure( + `interactivity api on ${ entry.namespace }`, + { + // eslint-disable-next-line no-undef + start, + end: performance.now(), + detail: { + devtools: { + track: `IA: on ${ entry.namespace }`, + }, + }, + } + ); + } + } } ); }; } ); From 8f053a63cd8a2ae51048714bbbd2a3e6cb126aa6 Mon Sep 17 00:00:00 2001 From: Amit Raj <77401999+amitraj2203@users.noreply.github.com> Date: Tue, 30 Jul 2024 21:03:52 +0530 Subject: [PATCH 0168/1908] DataViews: Conditionally shows the description field in Template Grid layout (#64043) Co-authored-by: amitraj2203 <amitraj2203@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/dataviews/src/layouts/grid/style.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/dataviews/src/layouts/grid/style.scss b/packages/dataviews/src/layouts/grid/style.scss index 6fe99642784dc9..a707401972cdab 100644 --- a/packages/dataviews/src/layouts/grid/style.scss +++ b/packages/dataviews/src/layouts/grid/style.scss @@ -71,6 +71,10 @@ align-items: flex-start; min-height: $grid-unit-30; + &:not(:has(.dataviews-view-grid__field-value:not(:empty))) { + display: none; + } + &:not(.is-column) { align-items: center; From 602b5fa34935a4d30cc554fa7e0ae962acd5c763 Mon Sep 17 00:00:00 2001 From: Tom J Nowell <contact@tomjn.com> Date: Tue, 30 Jul 2024 16:46:07 +0100 Subject: [PATCH 0169/1908] Fix a typo in use-image-sizes.js (#64100) Co-authored-by: tomjn <tjnowell@git.wordpress.org> --- packages/block-library/src/gallery/use-image-sizes.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/gallery/use-image-sizes.js b/packages/block-library/src/gallery/use-image-sizes.js index c96cd8dbaf5781..8dcc3eca61115f 100644 --- a/packages/block-library/src/gallery/use-image-sizes.js +++ b/packages/block-library/src/gallery/use-image-sizes.js @@ -4,10 +4,10 @@ import { useMemo } from '@wordpress/element'; /** - * Calculates the image sizes that are avaible for the current gallery images in order to + * Calculates the image sizes that are available for the current gallery images in order to * populate the 'Resolution' selector. * - * @param {Array} images Basic image block data taken from current gallery innerBlock + * @param {Array} images Basic image block data taken from current gallery innerBlock. * @param {boolean} isSelected Is the block currently selected in the editor. * @param {Function} getSettings Block editor store selector. * From 060d4ca57ab8441255db34e308c21a640adad2a6 Mon Sep 17 00:00:00 2001 From: Utsav Patel <75293077+up1512001@users.noreply.github.com> Date: Wed, 31 Jul 2024 00:36:38 +0530 Subject: [PATCH 0170/1908] remove speak from device menu selection (#64115) Co-authored-by: up1512001 <up1512001@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> --- .../src/components/preview-dropdown/index.js | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js index e8c48a739d29ba..b157c8cc1cfc3b 100644 --- a/packages/editor/src/components/preview-dropdown/index.js +++ b/packages/editor/src/components/preview-dropdown/index.js @@ -21,7 +21,6 @@ import { store as preferencesStore } from '@wordpress/preferences'; */ import { store as editorStore } from '../../store'; import PostPreviewButton from '../post-preview-button'; -import { speak } from '@wordpress/a11y'; export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { const { deviceType, homeUrl, isTemplate, isViewable, showIconLabels } = @@ -103,22 +102,6 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { selectedChoice = choices[ 0 ]; } - /** - * Handles the selection of a device type. - * - * @param {string} value The device type. - */ - const onSelect = ( value ) => { - setDeviceType( value ); - if ( value === 'Desktop' ) { - speak( __( 'Desktop selected' ), 'assertive' ); - } else if ( value === 'Tablet' ) { - speak( __( 'Tablet selected' ), 'assertive' ); - } else { - speak( __( 'Mobile selected' ), 'assertive' ); - } - }; - return ( <DropdownMenu className="editor-preview-dropdown" @@ -135,7 +118,7 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { <MenuItemsChoice choices={ choices } value={ selectedChoice.value } - onSelect={ onSelect } + onSelect={ setDeviceType } /> </MenuGroup> { isTemplate && ( From ddc5536dd36917a259dc8c3c987b227ee9960bcf Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Tue, 30 Jul 2024 23:24:39 +0200 Subject: [PATCH 0171/1908] Make useStyleOverride public (#63656) --- packages/block-editor/README.md | 10 ++++++++++ .../src/hooks/block-style-variation.js | 6 +++--- packages/block-editor/src/hooks/duotone.js | 6 +++--- packages/block-editor/src/hooks/index.js | 1 + packages/block-editor/src/hooks/utils.js | 15 ++++++++++++++- packages/block-editor/src/index.js | 1 + packages/block-editor/src/private-apis.js | 3 +-- packages/block-library/src/gallery/gap-styles.js | 9 +-------- 8 files changed, 34 insertions(+), 17 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 00951fb94c4a77..fec4f4c0dbe5c3 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -1029,6 +1029,16 @@ _Returns_ - `any[]`: Returns the values defined for the settings. +### useStyleOverride + +Override a block editor settings style. Leave the ID blank to create a new style. + +_Parameters_ + +- _override_ `Object`: Override object. +- _override.id_ `?string`: Id of the style override, leave blank to create a new style. +- _override.css_ `string`: CSS to apply. + ### useZoomOut A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode. diff --git a/packages/block-editor/src/hooks/block-style-variation.js b/packages/block-editor/src/hooks/block-style-variation.js index f302cf2aa3a2a2..65582d0c0cf948 100644 --- a/packages/block-editor/src/hooks/block-style-variation.js +++ b/packages/block-editor/src/hooks/block-style-variation.js @@ -13,7 +13,7 @@ import { toStyles, getBlockSelectors, } from '../components/global-styles'; -import { useStyleOverride } from './utils'; +import { usePrivateStyleOverride } from './utils'; import { getValueFromObjectPath } from '../utils/object'; import { store as blockEditorStore } from '../store'; import { globalStylesDataKey } from '../store/private-keys'; @@ -63,7 +63,7 @@ function getVariationNameFromClass( className, registeredStyles = [] ) { // A helper component to apply a style override using the useStyleOverride hook. function OverrideStyles( { override } ) { - useStyleOverride( override ); + usePrivateStyleOverride( override ); } /** @@ -351,7 +351,7 @@ function useBlockProps( { name, className, clientId } ) { ); }, [ variation, settings, styles, getBlockStyles, clientId ] ); - useStyleOverride( { + usePrivateStyleOverride( { id: `variation-${ clientId }`, css: variationStyles, __unstableType: 'variation', diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index 88f2d6064046f9..0a1d630d00de59 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -32,7 +32,7 @@ import { } from '../components/duotone/utils'; import { getBlockCSSSelector } from '../components/global-styles/get-block-css-selector'; import { scopeSelector } from '../components/global-styles/utils'; -import { useBlockSettings, useStyleOverride } from './utils'; +import { useBlockSettings, usePrivateStyleOverride } from './utils'; import { default as StylesFiltersPanel } from '../components/global-styles/filters-panel'; import { useBlockEditingMode } from '../components/block-editing-mode'; import { useBlockElement } from '../components/block-list/use-block-props/use-block-refs'; @@ -265,7 +265,7 @@ function useDuotoneStyles( { const isValidFilter = Array.isArray( colors ) || colors === 'unset'; - useStyleOverride( + usePrivateStyleOverride( isValidFilter ? { css: @@ -276,7 +276,7 @@ function useDuotoneStyles( { } : undefined ); - useStyleOverride( + usePrivateStyleOverride( isValidFilter ? { assets: diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index 2f74640ef4f633..66ff60b691b66f 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -91,3 +91,4 @@ export { useCachedTruthy } from './use-cached-truthy'; export { setBackgroundStyleDefaults } from './background'; export { useZoomOut } from './use-zoom-out'; export { __unstableBlockStyleVariationOverridesWithConfig } from './block-style-variation'; +export { useStyleOverride } from './utils'; diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index 26700ecf7b3fab..fa710fa7f08eba 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -135,7 +135,20 @@ export function shouldSkipSerialization( const pendingStyleOverrides = new WeakMap(); -export function useStyleOverride( { +/** + * Override a block editor settings style. Leave the ID blank to create a new + * style. + * + * @param {Object} override Override object. + * @param {?string} override.id Id of the style override, leave blank to create + * a new style. + * @param {string} override.css CSS to apply. + */ +export function useStyleOverride( { id, css } ) { + return usePrivateStyleOverride( { id, css } ); +} + +export function usePrivateStyleOverride( { id, css, assets, diff --git a/packages/block-editor/src/index.js b/packages/block-editor/src/index.js index 53ae7dfeb778fc..db1bc0a06ec6d1 100644 --- a/packages/block-editor/src/index.js +++ b/packages/block-editor/src/index.js @@ -14,6 +14,7 @@ export { getShadowClassesAndStyles as __experimentalGetShadowClassesAndStyles, useCachedTruthy, useZoomOut, + useStyleOverride, } from './hooks'; export * from './components'; export * from './elements'; diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index eaf699d5e69399..cf464cedf04175 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -16,7 +16,7 @@ import { import { PrivateListView } from './components/list-view'; import BlockInfo from './components/block-info-slot-fill'; import { useHasBlockToolbar } from './components/block-toolbar/use-has-block-toolbar'; -import { cleanEmptyObject, useStyleOverride } from './hooks/utils'; +import { cleanEmptyObject } from './hooks/utils'; import BlockQuickNavigation from './components/block-quick-navigation'; import { LayoutStyle } from './components/block-list/layout'; import { BlockRemovalWarningModal } from './components/block-removal-warning-modal'; @@ -68,7 +68,6 @@ lock( privateApis, { BlockInfo, useHasBlockToolbar, cleanEmptyObject, - useStyleOverride, BlockQuickNavigation, LayoutStyle, BlockRemovalWarningModal, diff --git a/packages/block-library/src/gallery/gap-styles.js b/packages/block-library/src/gallery/gap-styles.js index 4c2002d4b7ddc8..a1ad61f02b9955 100644 --- a/packages/block-library/src/gallery/gap-styles.js +++ b/packages/block-library/src/gallery/gap-styles.js @@ -3,16 +3,9 @@ */ import { __experimentalGetGapCSSValue as getGapCSSValue, - privateApis as blockEditorPrivateApis, + useStyleOverride, } from '@wordpress/block-editor'; -/** - * Internal dependencies - */ -import { unlock } from '../lock-unlock'; - -const { useStyleOverride } = unlock( blockEditorPrivateApis ); - export default function GapStyles( { blockGap, clientId } ) { // --gallery-block--gutter-size is deprecated. --wp--style--gallery-gap-default should be used by themes that want to set a default // gap on the gallery. From 86735cacf73a9a52f343e457406bb717dac6213f Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 31 Jul 2024 12:09:10 +1000 Subject: [PATCH 0172/1908] Patterns: enable cross-browser support for pattern uploading (#64123) * Uploading pattern JSON files was triggering an error in Firefox "categoryMap.values().find is not a function". categoryMap.values() method returns an iterator. Iterator.find() doesn't have wide browser support. It doesn't work in Firefox, Safari and others. Converting categoryMap.values() iterator to an array allow the use of find() Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- .../edit-site/src/components/add-new-pattern/index.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/edit-site/src/components/add-new-pattern/index.js b/packages/edit-site/src/components/add-new-pattern/index.js index e97cef1b2aa911..bb9e53da6a5660 100644 --- a/packages/edit-site/src/components/add-new-pattern/index.js +++ b/packages/edit-site/src/components/add-new-pattern/index.js @@ -173,9 +173,14 @@ export default function AddNewPattern() { // When we're not handling template parts, we should // add or create the proper pattern category. if ( postType !== TEMPLATE_PART_POST_TYPE ) { - const currentCategory = categoryMap - .values() - .find( ( term ) => term.name === categoryId ); + /* + * categoryMap.values() returns an iterator. + * Iterator.prototype.find() is not yet widely supported. + * Convert to array to use the Array.prototype.find method. + */ + const currentCategory = Array.from( + categoryMap.values() + ).find( ( term ) => term.name === categoryId ); if ( currentCategory ) { currentCategoryId = currentCategory.id || From c3afc376fc956676382e1f160ba3a65266fd6fbc Mon Sep 17 00:00:00 2001 From: Amit Raj <77401999+amitraj2203@users.noreply.github.com> Date: Wed, 31 Jul 2024 08:50:32 +0530 Subject: [PATCH 0173/1908] refactor: update flex property in document bar title style (#64092) Co-authored-by: amitraj2203 <amitraj2203@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: Rishit30G <rishit30g@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/editor/src/components/document-bar/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/document-bar/style.scss b/packages/editor/src/components/document-bar/style.scss index dedf05bc8e7d4f..bc39d68df338ac 100644 --- a/packages/editor/src/components/document-bar/style.scss +++ b/packages/editor/src/components/document-bar/style.scss @@ -34,7 +34,7 @@ } .editor-document-bar__title { - flex-grow: 1; + flex: 1; overflow: hidden; color: $gray-900; gap: $grid-unit-05; From 245248e8c1948806a826dcac4c8e07cf8234c879 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 31 Jul 2024 13:31:16 +1000 Subject: [PATCH 0174/1908] Global Styles: Fix block custom CSS pseudo element selectors (#63980) Unlinked contributors: harlet. Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: dballari <dballari@git.wordpress.org> Co-authored-by: wongjn <wongjn@git.wordpress.org> --- backport-changelog/6.6/7097.md | 3 ++ lib/class-wp-theme-json-gutenberg.php | 26 +++++++++++-- .../test/use-global-styles-output.js | 16 ++++++-- .../global-styles/use-global-styles-output.js | 37 +++++++++++++++++-- phpunit/class-wp-theme-json-test.php | 18 ++++++++- 5 files changed, 87 insertions(+), 13 deletions(-) create mode 100644 backport-changelog/6.6/7097.md diff --git a/backport-changelog/6.6/7097.md b/backport-changelog/6.6/7097.md new file mode 100644 index 00000000000000..e674d5ea76ba6f --- /dev/null +++ b/backport-changelog/6.6/7097.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7097 + +* https://github.com/WordPress/gutenberg/pull/63980 diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 65a5e5fe4b9578..cfe0c4d55ceed7 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -1443,9 +1443,16 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' protected function process_blocks_custom_css( $css, $selector ) { $processed_css = ''; + if ( empty( $css ) ) { + return $processed_css; + } + // Split CSS nested rules. $parts = explode( '&', $css ); foreach ( $parts as $part ) { + if ( empty( $part ) ) { + continue; + } $is_root_css = ( ! str_contains( $part, '{' ) ); if ( $is_root_css ) { // If the part doesn't contain braces, it applies to the root level. @@ -1458,11 +1465,24 @@ protected function process_blocks_custom_css( $css, $selector ) { } $nested_selector = $part[0]; $css_value = $part[1]; - $part_selector = str_starts_with( $nested_selector, ' ' ) + + /* + * Handle pseudo elements such as ::before, ::after etc. Regex will also + * capture any leading combinator such as >, +, or ~, as well as spaces. + * This allows pseudo elements as descendants e.g. `.parent ::before`. + */ + $matches = array(); + $has_pseudo_element = preg_match( '/([>+~\s]*::[a-zA-Z-]+)/', $nested_selector, $matches ); + $pseudo_part = $has_pseudo_element ? $matches[1] : ''; + $nested_selector = $has_pseudo_element ? str_replace( $pseudo_part, '', $nested_selector ) : $nested_selector; + + // Finalize selector and re-append pseudo element if required. + $part_selector = str_starts_with( $nested_selector, ' ' ) ? static::scope_selector( $selector, $nested_selector ) : static::append_to_selector( $selector, $nested_selector ); - $final_selector = ":root :where($part_selector)"; - $processed_css .= $final_selector . '{' . trim( $css_value ) . '}'; + $final_selector = ":root :where($part_selector)$pseudo_part"; + + $processed_css .= $final_selector . '{' . trim( $css_value ) . '}'; } } return $processed_css; diff --git a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js index 525a8a1d53d072..3f7fb5462e377c 100644 --- a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js @@ -1031,11 +1031,19 @@ describe( 'global styles renderer', () => { } ); describe( 'processCSSNesting', () => { + it( 'should return empty string when supplied css is empty', () => { + expect( processCSSNesting( '', '.foo' ) ).toEqual( '' ); + } ); it( 'should return processed CSS without any nested selectors', () => { expect( processCSSNesting( 'color: red; margin: auto;', '.foo' ) ).toEqual( ':root :where(.foo){color: red; margin: auto;}' ); } ); + it( 'should return processed CSS when there are no root selectors', () => { + expect( + processCSSNesting( '&::before{color: red;}', '.foo' ) + ).toEqual( ':root :where(.foo)::before{color: red;}' ); + } ); it( 'should return processed CSS with nested selectors', () => { expect( processCSSNesting( @@ -1049,21 +1057,21 @@ describe( 'global styles renderer', () => { it( 'should return processed CSS with pseudo elements', () => { expect( processCSSNesting( - 'color: red; margin: auto; &::before{color: blue;} & ::before{color: green;} &.one::before{color: yellow;} & .two::before{color: purple;}', + 'color: red; margin: auto; &::before{color: blue;} & ::before{color: green;} &.one::before{color: yellow;} & .two::before{color: purple;} & > ::before{color: darkseagreen;}', '.foo' ) ).toEqual( - ':root :where(.foo){color: red; margin: auto;}:root :where(.foo::before){color: blue;}:root :where(.foo ::before){color: green;}:root :where(.foo.one::before){color: yellow;}:root :where(.foo .two::before){color: purple;}' + ':root :where(.foo){color: red; margin: auto;}:root :where(.foo)::before{color: blue;}:root :where(.foo) ::before{color: green;}:root :where(.foo.one)::before{color: yellow;}:root :where(.foo .two)::before{color: purple;}:root :where(.foo) > ::before{color: darkseagreen;}' ); } ); it( 'should return processed CSS with multiple root selectors', () => { expect( processCSSNesting( - 'color: red; margin: auto; &.one{color: blue;} & .two{color: green;} &::before{color: yellow;} & ::before{color: purple;} &.three::before{color: orange;} & .four::before{color: skyblue;}', + 'color: red; margin: auto; &.one{color: blue;} & .two{color: green;} &::before{color: yellow;} & ::before{color: purple;} &.three::before{color: orange;} & .four::before{color: skyblue;} & > ::before{color: darkseagreen;}', '.foo, .bar' ) ).toEqual( - ':root :where(.foo, .bar){color: red; margin: auto;}:root :where(.foo.one, .bar.one){color: blue;}:root :where(.foo .two, .bar .two){color: green;}:root :where(.foo::before, .bar::before){color: yellow;}:root :where(.foo ::before, .bar ::before){color: purple;}:root :where(.foo.three::before, .bar.three::before){color: orange;}:root :where(.foo .four::before, .bar .four::before){color: skyblue;}' + ':root :where(.foo, .bar){color: red; margin: auto;}:root :where(.foo.one, .bar.one){color: blue;}:root :where(.foo .two, .bar .two){color: green;}:root :where(.foo, .bar)::before{color: yellow;}:root :where(.foo, .bar) ::before{color: purple;}:root :where(.foo.three, .bar.three)::before{color: orange;}:root :where(.foo .four, .bar .four)::before{color: skyblue;}:root :where(.foo, .bar) > ::before{color: darkseagreen;}' ); } ); } ); diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 63d6a2fb22dd7a..69adf221900a47 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -1327,9 +1327,17 @@ function updateConfigWithSeparator( config ) { export function processCSSNesting( css, blockSelector ) { let processedCSS = ''; + if ( ! css || css.trim() === '' ) { + return processedCSS; + } + // Split CSS nested rules. const parts = css.split( '&' ); parts.forEach( ( part ) => { + if ( ! part || part.trim() === '' ) { + return; + } + const isRootCss = ! part.includes( '{' ); if ( isRootCss ) { // If the part doesn't contain braces, it applies to the root level. @@ -1342,11 +1350,32 @@ export function processCSSNesting( css, blockSelector ) { } const [ nestedSelector, cssValue ] = splittedPart; - const combinedSelector = nestedSelector.startsWith( ' ' ) - ? scopeSelector( blockSelector, nestedSelector ) - : appendToSelector( blockSelector, nestedSelector ); - processedCSS += `:root :where(${ combinedSelector }){${ cssValue.trim() }}`; + // Handle pseudo elements such as ::before, ::after, etc. Regex will also + // capture any leading combinator such as >, +, or ~, as well as spaces. + // This allows pseudo elements as descendants e.g. `.parent ::before`. + const matches = nestedSelector.match( /([>+~\s]*::[a-zA-Z-]+)/ ); + const pseudoPart = matches ? matches[ 1 ] : ''; + const withoutPseudoElement = matches + ? nestedSelector.replace( pseudoPart, '' ).trim() + : nestedSelector.trim(); + + let combinedSelector; + if ( withoutPseudoElement === '' ) { + // Only contained a pseudo element to use the block selector to form + // the final `:root :where()` selector. + combinedSelector = blockSelector; + } else { + // If the nested selector is a descendant of the block scope it with the + // block selector. Otherwise append it to the block selector. + combinedSelector = nestedSelector.startsWith( ' ' ) + ? scopeSelector( blockSelector, withoutPseudoElement ) + : appendToSelector( blockSelector, withoutPseudoElement ); + } + + // Build final rule, re-adding any pseudo element outside the `:where()` + // to maintain valid CSS selector. + processedCSS += `:root :where(${ combinedSelector })${ pseudoPart }{${ cssValue.trim() }}`; } } ); return processedCSS; diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 2f76ec7a5d4739..36b8218785f216 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -5004,6 +5004,13 @@ public function test_process_blocks_custom_css( $input, $expected ) { public function data_process_blocks_custom_css() { return array( // Simple CSS without any nested selectors. + 'empty css' => array( + 'input' => array( + 'selector' => '.foo', + 'css' => '', + ), + 'expected' => '', + ), 'no nested selectors' => array( 'input' => array( 'selector' => '.foo', @@ -5011,6 +5018,13 @@ public function data_process_blocks_custom_css() { ), 'expected' => ':root :where(.foo){color: red; margin: auto;}', ), + 'no root styles' => array( + 'input' => array( + 'selector' => '.foo', + 'css' => '&::before{color: red;}', + ), + 'expected' => ':root :where(.foo)::before{color: red;}', + ), // CSS with nested selectors. 'with nested selector' => array( 'input' => array( @@ -5025,7 +5039,7 @@ public function data_process_blocks_custom_css() { 'selector' => '.foo', 'css' => 'color: red; margin: auto; &::before{color: blue;} & ::before{color: green;} &.one::before{color: yellow;} & .two::before{color: purple;}', ), - 'expected' => ':root :where(.foo){color: red; margin: auto;}:root :where(.foo::before){color: blue;}:root :where(.foo ::before){color: green;}:root :where(.foo.one::before){color: yellow;}:root :where(.foo .two::before){color: purple;}', + 'expected' => ':root :where(.foo){color: red; margin: auto;}:root :where(.foo)::before{color: blue;}:root :where(.foo) ::before{color: green;}:root :where(.foo.one)::before{color: yellow;}:root :where(.foo .two)::before{color: purple;}', ), // CSS with multiple root selectors. 'with multiple root selectors' => array( @@ -5033,7 +5047,7 @@ public function data_process_blocks_custom_css() { 'selector' => '.foo, .bar', 'css' => 'color: red; margin: auto; &.one{color: blue;} & .two{color: green;} &::before{color: yellow;} & ::before{color: purple;} &.three::before{color: orange;} & .four::before{color: skyblue;}', ), - 'expected' => ':root :where(.foo, .bar){color: red; margin: auto;}:root :where(.foo.one, .bar.one){color: blue;}:root :where(.foo .two, .bar .two){color: green;}:root :where(.foo::before, .bar::before){color: yellow;}:root :where(.foo ::before, .bar ::before){color: purple;}:root :where(.foo.three::before, .bar.three::before){color: orange;}:root :where(.foo .four::before, .bar .four::before){color: skyblue;}', + 'expected' => ':root :where(.foo, .bar){color: red; margin: auto;}:root :where(.foo.one, .bar.one){color: blue;}:root :where(.foo .two, .bar .two){color: green;}:root :where(.foo, .bar)::before{color: yellow;}:root :where(.foo, .bar) ::before{color: purple;}:root :where(.foo.three, .bar.three)::before{color: orange;}:root :where(.foo .four, .bar .four)::before{color: skyblue;}', ), ); } From b27ff6fd6ec900cb1e3ad78fed29338448c1e72b Mon Sep 17 00:00:00 2001 From: Robert Anderson <robert@noisysocks.com> Date: Wed, 31 Jul 2024 15:46:47 +1000 Subject: [PATCH 0175/1908] Image: Make Placeholder white when there is a <Spinner /> on top (#63885) * Update <Placeholder hasIllustration> design, remove unnecessary mixin * Update CHANGELOG.md * Overlay styles * Remove z-index * Remove blur * Only apply white placeholder styling when there is a spinner on top * Reduce opacity of diagonal stroke --------- Co-authored-by: James Koster <james@jameskoster.co.uk> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/base-styles/_mixins.scss | 16 ---------------- .../button-block-appender/content.scss | 2 +- packages/block-library/src/group/editor.scss | 2 +- packages/block-library/src/image/editor.scss | 12 ++++++++++++ .../block-library/src/navigation/editor.scss | 1 - packages/components/CHANGELOG.md | 1 + packages/components/src/placeholder/style.scss | 13 +++++++++++-- 7 files changed, 26 insertions(+), 21 deletions(-) diff --git a/packages/base-styles/_mixins.scss b/packages/base-styles/_mixins.scss index 506d12af84b2ff..69735d75aac71a 100644 --- a/packages/base-styles/_mixins.scss +++ b/packages/base-styles/_mixins.scss @@ -162,22 +162,6 @@ } } -@mixin placeholder-style() { - border-radius: $radius-block-ui; - - &::before { - content: ""; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - pointer-events: none; - background: currentColor; - opacity: 0.1; - } -} - /** * Allows users to opt-out of animations via OS-level preferences. */ diff --git a/packages/block-editor/src/components/button-block-appender/content.scss b/packages/block-editor/src/components/button-block-appender/content.scss index 87243ea9271826..4e3f32b3f4ffc3 100644 --- a/packages/block-editor/src/components/button-block-appender/content.scss +++ b/packages/block-editor/src/components/button-block-appender/content.scss @@ -52,7 +52,7 @@ left: 0; pointer-events: none; border: $border-width dashed currentColor; - @include placeholder-style(); + border-radius: $radius-block-ui; } .block-editor-inserter { diff --git a/packages/block-library/src/group/editor.scss b/packages/block-library/src/group/editor.scss index a2926c89ae8021..041a2f9f884e84 100644 --- a/packages/block-library/src/group/editor.scss +++ b/packages/block-library/src/group/editor.scss @@ -43,7 +43,7 @@ pointer-events: none; min-height: $grid-unit-60 - $border-width - $border-width; border: $border-width dashed currentColor; - @include placeholder-style(); + border-radius: $radius-block-ui; } // Let the parent be selectable in the placeholder area. diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss index 6aaa8e7491ed58..db6928766c0b72 100644 --- a/packages/block-library/src/image/editor.scss +++ b/packages/block-library/src/image/editor.scss @@ -67,12 +67,24 @@ figure.wp-block-image:not(.wp-block) { top: 50%; left: 50%; transform: translate(-50%, -50%); + margin: 0; } } // Shown while image is being uploded but cannot be previewed. .wp-block-image__placeholder { aspect-ratio: 4 / 3; + + // Make placeholder background white so that you can see the spinner on top of it. + &.has-illustration::before { + background: $white; + opacity: 0.8; + } + + // Reduce opacity of diagonal stroke so that it doesn't obscure the spinner. + .components-placeholder__illustration { + opacity: 0.1; + } } // This is necessary for the editor resize handles to accurately work on a non-floated, non-resized, small image. diff --git a/packages/block-library/src/navigation/editor.scss b/packages/block-library/src/navigation/editor.scss index c62cbe9614c916..b279dc08cfe6e7 100644 --- a/packages/block-library/src/navigation/editor.scss +++ b/packages/block-library/src/navigation/editor.scss @@ -287,7 +287,6 @@ $color-control-label-height: 20px; left: 0; pointer-events: none; border: $border-width dashed currentColor; - @include placeholder-style(); // Inherit border radius from style variations. border-radius: inherit; diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 7cef1112b6a7c9..7de4fcf90b0e95 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -51,6 +51,7 @@ - `Tabs`: Vertical Tabs should be 40px min height. ([#63446](https://github.com/WordPress/gutenberg/pull/63446)). - `ColorPicker`: Use `minimal` variant for `SelectControl` ([#63676](https://github.com/WordPress/gutenberg/pull/63676)). - `Tabs`: keep full opacity of focus ring and remove hover styles on disabled tabs ([#63754](https://github.com/WordPress/gutenberg/pull/63754)). +- `Placeholder`: Remove unnecssary `placeholder-style` Sass mixin ([#63885](https://github.com/WordPress/gutenberg/pull/63885)). ### Documentation diff --git a/packages/components/src/placeholder/style.scss b/packages/components/src/placeholder/style.scss index 0e9bfa0f86a0ce..e046ce1e3a427e 100644 --- a/packages/components/src/placeholder/style.scss +++ b/packages/components/src/placeholder/style.scss @@ -183,8 +183,17 @@ } } - // By painting the borders here, we enable them to be replaced by the Border control. - @include placeholder-style(); + &::before { + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + pointer-events: none; + background: currentColor; + opacity: 0.1; + } overflow: hidden; .is-selected & { From 0af7e1402ce2e8c04fd382f3de55449b74342b1c Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 31 Jul 2024 09:52:56 +0400 Subject: [PATCH 0176/1908] Plugin: Remove compat layers for WP 6.4 and 6.5 (#64096) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: hellofromtonya <hellofromtonya@git.wordpress.org> Co-authored-by: creativecoder <grantmkin@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: dmsnell <dmsnell@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- lib/block-supports/layout.php | 25 +- lib/compat/plugin/fonts.php | 43 + lib/compat/plugin/footnotes.php | 250 -- lib/compat/wordpress-6.4/block-hooks.php | 377 -- lib/compat/wordpress-6.4/blocks.php | 23 - ...tenberg-rest-block-patterns-controller.php | 46 - ...global-styles-revisions-controller-6-4.php | 164 - ...utenberg-rest-templates-controller-6-4.php | 75 - .../font-face/class-wp-font-face-resolver.php | 183 - .../fonts/font-face/class-wp-font-face.php | 435 -- lib/compat/wordpress-6.4/fonts/fonts.php | 78 - ...class-gutenberg-html-tag-processor-6-4.php | 2457 ------------ ...ass-wp-html-active-formatting-elements.php | 190 - .../html-api/class-wp-html-open-elements.php | 435 -- .../class-wp-html-processor-state.php | 146 - .../html-api/class-wp-html-processor.php | 1446 ------- .../html-api/class-wp-html-token.php | 109 - .../class-wp-html-unsupported-exception.php | 34 - lib/compat/wordpress-6.4/kses.php | 18 - lib/compat/wordpress-6.4/rest-api.php | 40 - lib/compat/wordpress-6.4/script-loader.php | 112 - lib/compat/wordpress-6.4/theme-previews.php | 27 - .../block-bindings/block-bindings.php | 89 - .../class-wp-block-bindings-registry.php | 288 -- .../class-wp-block-bindings-source.php | 99 - .../block-bindings/post-meta.php | 65 - lib/compat/wordpress-6.5/block-patterns.php | 79 - lib/compat/wordpress-6.5/blocks.php | 414 -- ...global-styles-revisions-controller-6-5.php | 111 - .../wordpress-6.5/class-wp-script-modules.php | 362 -- lib/compat/wordpress-6.5/compat.php | 92 - .../fonts/class-wp-font-collection.php | 298 -- .../fonts/class-wp-font-library.php | 145 - .../fonts/class-wp-font-utils.php | 260 -- ...ss-wp-rest-font-collections-controller.php | 326 -- .../class-wp-rest-font-faces-controller.php | 952 ----- ...class-wp-rest-font-families-controller.php | 567 --- lib/compat/wordpress-6.5/fonts/fonts.php | 485 --- ...ass-gutenberg-html-attribute-token-6-5.php | 116 - ...class-gutenberg-html-open-elements-6-5.php | 462 --- .../class-gutenberg-html-processor-6-5.php | 1929 --------- ...ass-gutenberg-html-processor-state-6-5.php | 143 - .../class-gutenberg-html-span-6-5.php | 56 - ...class-gutenberg-html-tag-processor-6-5.php | 3555 ----------------- ...ss-gutenberg-html-text-replacement-6-5.php | 64 - ...interactivity-api-directives-processor.php | 246 -- .../class-wp-interactivity-api.php | 992 ----- .../interactivity-api/interactivity-api.php | 205 - lib/compat/wordpress-6.5/kses.php | 18 - .../navigation-block-variations.php | 143 - lib/compat/wordpress-6.5/rest-api.php | 136 - lib/compat/wordpress-6.5/script-loader.php | 207 - lib/compat/wordpress-6.5/scripts-modules.php | 224 -- ...global-styles-revisions-controller-6-6.php | 2 +- ...utenberg-rest-templates-controller-6-6.php | 2 +- .../class-gutenberg-html-processor-6-6.php | 4 +- ...class-gutenberg-html-tag-processor-6-6.php | 12 +- lib/load.php | 92 +- packages/block-library/src/button/index.php | 15 +- ...lobal-styles-revisions-controller-test.php | 351 -- .../fontFamilyBackwardsCompatibility.php | 196 - 61 files changed, 59 insertions(+), 20456 deletions(-) create mode 100644 lib/compat/plugin/fonts.php delete mode 100644 lib/compat/plugin/footnotes.php delete mode 100644 lib/compat/wordpress-6.4/block-hooks.php delete mode 100644 lib/compat/wordpress-6.4/blocks.php delete mode 100644 lib/compat/wordpress-6.4/class-gutenberg-rest-block-patterns-controller.php delete mode 100644 lib/compat/wordpress-6.4/class-gutenberg-rest-global-styles-revisions-controller-6-4.php delete mode 100644 lib/compat/wordpress-6.4/class-gutenberg-rest-templates-controller-6-4.php delete mode 100644 lib/compat/wordpress-6.4/fonts/font-face/class-wp-font-face-resolver.php delete mode 100644 lib/compat/wordpress-6.4/fonts/font-face/class-wp-font-face.php delete mode 100644 lib/compat/wordpress-6.4/fonts/fonts.php delete mode 100644 lib/compat/wordpress-6.4/html-api/class-gutenberg-html-tag-processor-6-4.php delete mode 100644 lib/compat/wordpress-6.4/html-api/class-wp-html-active-formatting-elements.php delete mode 100644 lib/compat/wordpress-6.4/html-api/class-wp-html-open-elements.php delete mode 100644 lib/compat/wordpress-6.4/html-api/class-wp-html-processor-state.php delete mode 100644 lib/compat/wordpress-6.4/html-api/class-wp-html-processor.php delete mode 100644 lib/compat/wordpress-6.4/html-api/class-wp-html-token.php delete mode 100644 lib/compat/wordpress-6.4/html-api/class-wp-html-unsupported-exception.php delete mode 100644 lib/compat/wordpress-6.4/kses.php delete mode 100644 lib/compat/wordpress-6.4/rest-api.php delete mode 100644 lib/compat/wordpress-6.4/script-loader.php delete mode 100644 lib/compat/wordpress-6.4/theme-previews.php delete mode 100644 lib/compat/wordpress-6.5/block-bindings/block-bindings.php delete mode 100644 lib/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-registry.php delete mode 100644 lib/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-source.php delete mode 100644 lib/compat/wordpress-6.5/block-bindings/post-meta.php delete mode 100644 lib/compat/wordpress-6.5/block-patterns.php delete mode 100644 lib/compat/wordpress-6.5/blocks.php delete mode 100644 lib/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php delete mode 100644 lib/compat/wordpress-6.5/class-wp-script-modules.php delete mode 100644 lib/compat/wordpress-6.5/compat.php delete mode 100644 lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php delete mode 100644 lib/compat/wordpress-6.5/fonts/class-wp-font-library.php delete mode 100644 lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php delete mode 100644 lib/compat/wordpress-6.5/fonts/class-wp-rest-font-collections-controller.php delete mode 100644 lib/compat/wordpress-6.5/fonts/class-wp-rest-font-faces-controller.php delete mode 100644 lib/compat/wordpress-6.5/fonts/class-wp-rest-font-families-controller.php delete mode 100644 lib/compat/wordpress-6.5/fonts/fonts.php delete mode 100644 lib/compat/wordpress-6.5/html-api/class-gutenberg-html-attribute-token-6-5.php delete mode 100644 lib/compat/wordpress-6.5/html-api/class-gutenberg-html-open-elements-6-5.php delete mode 100644 lib/compat/wordpress-6.5/html-api/class-gutenberg-html-processor-6-5.php delete mode 100644 lib/compat/wordpress-6.5/html-api/class-gutenberg-html-processor-state-6-5.php delete mode 100644 lib/compat/wordpress-6.5/html-api/class-gutenberg-html-span-6-5.php delete mode 100644 lib/compat/wordpress-6.5/html-api/class-gutenberg-html-tag-processor-6-5.php delete mode 100644 lib/compat/wordpress-6.5/html-api/class-gutenberg-html-text-replacement-6-5.php delete mode 100644 lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api-directives-processor.php delete mode 100644 lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php delete mode 100644 lib/compat/wordpress-6.5/interactivity-api/interactivity-api.php delete mode 100644 lib/compat/wordpress-6.5/kses.php delete mode 100644 lib/compat/wordpress-6.5/navigation-block-variations.php delete mode 100644 lib/compat/wordpress-6.5/rest-api.php delete mode 100644 lib/compat/wordpress-6.5/script-loader.php delete mode 100644 lib/compat/wordpress-6.5/scripts-modules.php delete mode 100644 phpunit/class-gutenberg-rest-global-styles-revisions-controller-test.php delete mode 100644 phpunit/tests/fonts/font-library/fontFamilyBackwardsCompatibility.php diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php index 350d158cd6e24f..ddbd1917c30547 100644 --- a/lib/block-supports/layout.php +++ b/lib/block-supports/layout.php @@ -1019,27 +1019,10 @@ function gutenberg_restore_group_inner_container( $block_content, $block ) { $processor = new WP_HTML_Tag_Processor( $block_content ); if ( $processor->next_tag( array( 'class_name' => 'wp-block-group' ) ) ) { - if ( method_exists( $processor, 'class_list' ) ) { - foreach ( $processor->class_list() as $class_name ) { - if ( str_contains( $class_name, 'layout' ) ) { - array_push( $layout_classes, $class_name ); - $processor->remove_class( $class_name ); - } - } - } else { - /* - * The class_list method was only added in 6.4 so this needs a temporary fallback. - * This fallback should be removed when the minimum supported version is 6.4. - */ - $classes = $processor->get_attribute( 'class' ); - if ( $classes ) { - $classes = explode( ' ', $classes ); - foreach ( $classes as $class_name ) { - if ( str_contains( $class_name, 'is-layout-' ) ) { - array_push( $layout_classes, $class_name ); - $processor->remove_class( $class_name ); - } - } + foreach ( $processor->class_list() as $class_name ) { + if ( str_contains( $class_name, 'layout' ) ) { + array_push( $layout_classes, $class_name ); + $processor->remove_class( $class_name ); } } } diff --git a/lib/compat/plugin/fonts.php b/lib/compat/plugin/fonts.php new file mode 100644 index 00000000000000..f427f6110f610a --- /dev/null +++ b/lib/compat/plugin/fonts.php @@ -0,0 +1,43 @@ +<?php +/** + * A special compat layer for legacy font files upload directory. + * + * @see https://github.com/WordPress/gutenberg/pull/57688#issuecomment-2259037546 + * + * @package gutenberg + */ + +// @core-merge: Do not merge this function, it is for deleting fonts from the wp-content/fonts directory only used in Gutenberg. +/** + * Deletes associated font files from wp-content/fonts, when a font face is deleted. + * + * @param int $post_id Post ID. + * @param WP_Post $post Post object. + */ +function gutenberg_before_delete_font_face( $post_id, $post ) { + if ( 'wp_font_face' !== $post->post_type ) { + return; + } + + $font_files = get_post_meta( $post_id, '_wp_font_face_file', false ); + + if ( empty( $font_files ) ) { + return; + } + + $site_path = ''; + if ( is_multisite() && ! ( is_main_network() && is_main_site() ) ) { + $site_path = '/sites/' . get_current_blog_id(); + } + + $font_dir = path_join( WP_CONTENT_DIR, 'fonts' ) . $site_path; + + foreach ( $font_files as $font_file ) { + $font_path = $font_dir . '/' . $font_file; + + if ( file_exists( $font_path ) ) { + wp_delete_file( $font_path ); + } + } +} +add_action( 'before_delete_post', 'gutenberg_before_delete_font_face', 10, 2 ); diff --git a/lib/compat/plugin/footnotes.php b/lib/compat/plugin/footnotes.php deleted file mode 100644 index a3d89aba0ae96a..00000000000000 --- a/lib/compat/plugin/footnotes.php +++ /dev/null @@ -1,250 +0,0 @@ -<?php -/** - * Compatibility shim for the footnotes block to enable test passing while awaiting the tested code to be merged to core. - * - * See https://github.com/WordPress/gutenberg/pull/52988. - * - * Once merged, this shim can be removed. - * - * @package gutenberg - */ - -/** - * Remove footnote revision hooks when plugin is running on a version of core that already supports meta revisions. - */ -if ( function_exists( 'wp_post_revision_meta_keys' ) ) { - if ( has_action( 'rest_after_insert_post', 'wp_add_footnotes_revisions_to_post_meta' ) ) { - remove_action( 'rest_after_insert_post', 'wp_add_footnotes_revisions_to_post_meta' ); - } - if ( has_action( 'rest_after_insert_page', 'wp_add_footnotes_revisions_to_post_meta' ) ) { - remove_action( 'rest_after_insert_page', 'wp_add_footnotes_revisions_to_post_meta' ); - } - if ( has_action( 'wp_after_insert_post', 'wp_save_footnotes_meta' ) ) { - remove_action( 'wp_after_insert_post', 'wp_save_footnotes_meta' ); - } - if ( has_action( '_wp_put_post_revision', 'wp_keep_footnotes_revision_id' ) ) { - remove_action( '_wp_put_post_revision', 'wp_keep_footnotes_revision_id' ); - } - if ( has_action( 'wp_restore_post_revision', 'wp_restore_footnotes_from_revision' ) ) { - remove_action( 'wp_restore_post_revision', 'wp_restore_footnotes_from_revision' ); - } - if ( has_action( 'wp_creating_autosave', '_wp_rest_api_autosave_meta' ) ) { - remove_action( 'wp_creating_autosave', '_wp_rest_api_autosave_meta' ); - } - if ( has_action( '_wp_put_post_revision', '_wp_rest_api_autosave_meta' ) ) { - remove_action( '_wp_put_post_revision', '_wp_rest_api_autosave_meta' ); - } - if ( has_filter( 'rest_pre_insert_post', '_wp_rest_api_force_autosave_difference' ) ) { - remove_filter( 'rest_pre_insert_post', '_wp_rest_api_force_autosave_difference' ); - } -} else { - /** - * For versions of core that don't support meta revisions, use hooks to add. - */ - if ( ! function_exists( 'wp_save_footnotes_meta' ) ) { - /** - * Saves the footnotes meta value to the revision. - * - * @since 6.3.0 - * @since 6.4.0 Core added post meta revisions, so this is no longer needed. - * - * @param int $revision_id The revision ID. - */ - function wp_save_footnotes_meta( $revision_id ) { - $post_id = wp_is_post_revision( $revision_id ); - - if ( $post_id ) { - $footnotes = get_post_meta( $post_id, 'footnotes', true ); - - if ( $footnotes ) { - // Can't use update_post_meta() because it doesn't allow revisions. - update_metadata( 'post', $revision_id, 'footnotes', wp_slash( $footnotes ) ); - } - } - } - if ( ! function_exists( 'wp_post_revision_meta_keys' ) ) { - add_action( 'wp_after_insert_post', 'wp_save_footnotes_meta' ); - } - } - - if ( ! function_exists( 'wp_keep_footnotes_revision_id' ) ) { - /** - * Keeps track of the revision ID for "rest_after_insert_{$post_type}". - * - * @since 6.3.0 - * @since 6.4.0 Core added post meta revisions, so this is no longer needed. - * - * @global int $wp_temporary_footnote_revision_id The footnote revision ID. - * - * @param int $revision_id The revision ID. - */ - function wp_keep_footnotes_revision_id( $revision_id ) { - global $wp_temporary_footnote_revision_id; - $wp_temporary_footnote_revision_id = $revision_id; - } - if ( ! function_exists( 'wp_post_revision_meta_keys' ) ) { - add_action( '_wp_put_post_revision', 'wp_keep_footnotes_revision_id' ); - } - } - - if ( ! function_exists( 'wp_add_footnotes_revisions_to_post_meta' ) ) { - - /** - * This is a specific fix for the REST API. The REST API doesn't update - * the post and post meta in one go (through `meta_input`). While it - * does fix the `wp_after_insert_post` hook to be called correctly after - * updating meta, it does NOT fix hooks such as post_updated and - * save_post, which are normally also fired after post meta is updated - * in `wp_insert_post()`. Unfortunately, `wp_save_post_revision` is - * added to the `post_updated` action, which means the meta is not - * available at the time, so we have to add it afterwards through the - * `"rest_after_insert_{$post_type}"` action. - * - * @since 6.3.0 - * @since 6.4.0 Core added post meta revisions, so this is no longer needed. - * - * @global int $wp_temporary_footnote_revision_id The footnote revision ID. - * - * @param WP_Post $post The post object. - */ - function wp_add_footnotes_revisions_to_post_meta( $post ) { - global $wp_temporary_footnote_revision_id; - - if ( $wp_temporary_footnote_revision_id ) { - $revision = get_post( $wp_temporary_footnote_revision_id ); - - if ( ! $revision ) { - return; - } - - $post_id = $revision->post_parent; - - // Just making sure we're updating the right revision. - if ( $post->ID === $post_id ) { - $footnotes = get_post_meta( $post_id, 'footnotes', true ); - - if ( $footnotes ) { - // Can't use update_post_meta() because it doesn't allow revisions. - update_metadata( 'post', $wp_temporary_footnote_revision_id, 'footnotes', wp_slash( $footnotes ) ); - } - } - } - } - - if ( ! function_exists( 'wp_post_revision_meta_keys' ) ) { - add_action( 'rest_after_insert_post', 'wp_add_footnotes_revisions_to_post_meta' ); - add_action( 'rest_after_insert_page', 'wp_add_footnotes_revisions_to_post_meta' ); - } - } - - if ( ! function_exists( 'wp_restore_footnotes_from_revision' ) ) { - - /** - * Restores the footnotes meta value from the revision. - * - * @since 6.3.0 - * @since 6.4.0 Core added post meta revisions, so this is no longer needed. - * - * @param int $post_id The post ID. - * @param int $revision_id The revision ID. - */ - function wp_restore_footnotes_from_revision( $post_id, $revision_id ) { - $footnotes = get_post_meta( $revision_id, 'footnotes', true ); - - if ( $footnotes ) { - update_post_meta( $post_id, 'footnotes', wp_slash( $footnotes ) ); - } else { - delete_post_meta( $post_id, 'footnotes' ); - } - } - if ( ! function_exists( 'wp_post_revision_meta_keys' ) ) { - add_action( 'wp_restore_post_revision', 'wp_restore_footnotes_from_revision', 10, 2 ); - } - } - - if ( ! function_exists( '_wp_rest_api_autosave_meta' ) ) { - - /** - * The REST API autosave endpoint doesn't save meta, so we can use the - * `wp_creating_autosave` when it updates an exiting autosave, and - * `_wp_put_post_revision` when it creates a new autosave. - * - * @since 6.3.0 - * @since 6.4.0 Core added post meta revisions, so this is no longer needed. - * - * @param int|array $autosave The autosave ID or array. - */ - function _wp_rest_api_autosave_meta( $autosave ) { - // Ensure it's a REST API request. - if ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) { - return; - } - - $body = rest_get_server()->get_raw_data(); - $body = json_decode( $body, true ); - - if ( ! isset( $body['meta']['footnotes'] ) ) { - return; - } - - // `wp_creating_autosave` passes the array, - // `_wp_put_post_revision` passes the ID. - $id = is_int( $autosave ) ? $autosave : $autosave['ID']; - - if ( ! $id ) { - return; - } - - // Can't use update_post_meta() because it doesn't allow revisions. - update_metadata( 'post', $id, 'footnotes', wp_slash( $body['meta']['footnotes'] ) ); - } - - if ( ! function_exists( 'wp_post_revision_meta_keys' ) ) { - // See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L391C1-L391C1. - add_action( 'wp_creating_autosave', '_wp_rest_api_autosave_meta' ); - // See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L398. - // Then https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/revision.php#L367. - add_action( '_wp_put_post_revision', '_wp_rest_api_autosave_meta' ); - } - } - - if ( ! function_exists( '_wp_rest_api_force_autosave_difference' ) ) { - - /** - * This is a workaround for the autosave endpoint returning early if the - * revision field are equal. The problem is that "footnotes" is not real - * revision post field, so there's nothing to compare against. - * - * This trick sets the "footnotes" field (value doesn't matter), which will - * cause the autosave endpoint to always update the latest revision. That should - * be fine, it should be ok to update the revision even if nothing changed. Of - * course, this is temporary fix. - * - * @since 6.3.0 - * @since 6.4.0 Core added post meta revisions, so this is no longer needed. - * - * @param WP_Post $prepared_post The prepared post object. - * @param WP_REST_Request $request The request object. - * - * See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L365-L384. - * See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L219. - */ - function _wp_rest_api_force_autosave_difference( $prepared_post, $request ) { - // We only want to be altering POST requests. - if ( $request->get_method() !== 'POST' ) { - return $prepared_post; - } - - // Only alter requests for the '/autosaves' route. - if ( substr( $request->get_route(), -strlen( '/autosaves' ) ) !== '/autosaves' ) { - return $prepared_post; - } - - $prepared_post->footnotes = '[]'; - return $prepared_post; - } - if ( ! function_exists( 'wp_post_revision_meta_keys' ) ) { - add_filter( 'rest_pre_insert_post', '_wp_rest_api_force_autosave_difference', 10, 2 ); - } - } -} diff --git a/lib/compat/wordpress-6.4/block-hooks.php b/lib/compat/wordpress-6.4/block-hooks.php deleted file mode 100644 index f77582caf13454..00000000000000 --- a/lib/compat/wordpress-6.4/block-hooks.php +++ /dev/null @@ -1,377 +0,0 @@ -<?php -/** - * Block hooks. - * - * @package gutenberg - */ - -/** - * Register hooked blocks for automatic insertion, based on their block.json metadata. - * - * @param array $settings Array of determined settings for registering a block type. - * @param array $metadata Metadata provided for registering a block type. - * @return array Updated settings array. - */ -function gutenberg_add_hooked_blocks( $settings, $metadata ) { - if ( ! isset( $metadata['blockHooks'] ) ) { - return $settings; - } - $block_hooks = $metadata['blockHooks']; - - /** - * Map the camelCased position string from block.json to the snake_cased block type position - * used in the hooked block registration function. - * - * @var array - */ - $property_mappings = array( - 'before' => 'before', - 'after' => 'after', - 'firstChild' => 'first_child', - 'lastChild' => 'last_child', - ); - - $inserted_block_name = $metadata['name']; - foreach ( $block_hooks as $anchor_block_name => $position ) { - // Avoid infinite recursion (hooking to itself). - if ( $inserted_block_name === $anchor_block_name ) { - _doing_it_wrong( - __METHOD__, - __( 'Cannot hook block to itself.', 'gutenberg' ), - '6.4.0' - ); - continue; - } - - if ( ! isset( $property_mappings[ $position ] ) ) { - continue; - } - - $mapped_position = $property_mappings[ $position ]; - - gutenberg_add_hooked_block( $inserted_block_name, $mapped_position, $anchor_block_name ); - - $settings['block_hooks'][ $anchor_block_name ] = $mapped_position; - } - - // Copied from `get_block_editor_server_block_settings()`. - $fields_to_pick = array( - 'api_version' => 'apiVersion', - 'title' => 'title', - 'description' => 'description', - 'icon' => 'icon', - 'attributes' => 'attributes', - 'provides_context' => 'providesContext', - 'uses_context' => 'usesContext', - 'selectors' => 'selectors', - 'supports' => 'supports', - 'category' => 'category', - 'styles' => 'styles', - 'textdomain' => 'textdomain', - 'parent' => 'parent', - 'ancestor' => 'ancestor', - 'keywords' => 'keywords', - 'example' => 'example', - 'variations' => 'variations', - 'allowed_blocks' => 'allowedBlocks', - ); - // Add `block_hooks` to the list of fields to pick. - $fields_to_pick['block_hooks'] = 'blockHooks'; - - $exposed_settings = array_intersect_key( $settings, $fields_to_pick ); - - // TODO: Make work for blocks registered via direct call to gutenberg_add_hooked_block(). - wp_add_inline_script( - 'wp-blocks', - 'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( array( $inserted_block_name => $exposed_settings ) ) . ');' - ); - - return $settings; -} - -/** - * Register a hooked block for automatic insertion into a given block hook. - * - * A block hook is specified by a block type and a relative position. The hooked block - * will be automatically inserted in the given position next to the "anchor" block - * whenever the latter is encountered. This applies both to the frontend and to the markup - * returned by the templates and patterns REST API endpoints. - * - * This is currently done by filtering parsed blocks as obtained from a block template, - * template part, or pattern, and injecting the hooked block where applicable. - * - * @todo In the long run, we'd likely want some sort of registry for hooked blocks. - * - * @param string $hooked_block The name of the block to insert. - * @param string $position The desired position of the hooked block, relative to its anchor block. - * Can be 'before', 'after', 'first_child', or 'last_child'. - * @param string $anchor_block The name of the block to insert the hooked block next to. - * @return void - */ -function gutenberg_add_hooked_block( $hooked_block, $position, $anchor_block ) { - $hooked_block_array = array( - 'blockName' => $hooked_block, - 'attrs' => array(), - 'innerHTML' => '', - 'innerContent' => array(), - 'innerBlocks' => array(), - ); - - $inserter = gutenberg_insert_hooked_block( $hooked_block_array, $position, $anchor_block ); - add_filter( 'gutenberg_serialize_block', $inserter, 10, 1 ); - - /* - * The block-types REST API controller uses objects of the `WP_Block_Type` class, which are - * in turn created upon block type registration. However, that class does not contain - * a `block_hooks` property (and is not easily extensible), so we have to use a different - * mechanism to communicate to the controller which hooked blocks have been registered for - * automatic insertion. We're doing so here (i.e. upon block registration), by adding a filter to - * the controller's response. - */ - $controller_extender = gutenberg_add_block_hooks_field_to_block_type_controller( $hooked_block, $position, $anchor_block ); - add_filter( 'rest_prepare_block_type', $controller_extender, 10, 2 ); -} - -/** - * Return a function that auto-inserts a block next to a given "anchor" block. - * - * This is a helper function used in the implementation of block hooks. - * It is not meant for public use. - * - * The auto-inserted block can be inserted before or after the anchor block, - * or as the first or last child of the anchor block. - * - * Note that the returned function mutates the automatically inserted block's - * designated parent block by inserting into the parent's `innerBlocks` array, - * and by updating the parent's `innerContent` array accordingly. - * - * @param array $inserted_block The block to insert. - * @param string $relative_position The position relative to the given block. - * Can be 'before', 'after', 'first_child', or 'last_child'. - * @param string $anchor_block_type The automatically inserted block will be inserted next to instances of this block type. - * @return callable A function that accepts a block's content and returns the content with the inserted block. - */ -function gutenberg_insert_hooked_block( $inserted_block, $relative_position, $anchor_block_type ) { - return function ( $block ) use ( $inserted_block, $relative_position, $anchor_block_type ) { - if ( $anchor_block_type === $block['blockName'] ) { - if ( 'first_child' === $relative_position ) { - array_unshift( $block['innerBlocks'], $inserted_block ); - // Since WP_Block::render() iterates over `inner_content` (rather than `inner_blocks`) - // when rendering blocks, we also need to prepend a value (`null`, to mark a block - // location) to that array after HTML content for the inner blocks wrapper. - $chunk_index = 0; - for ( $index = $chunk_index; $index < count( $block['innerContent'] ); $index++ ) { - if ( is_null( $block['innerContent'][ $index ] ) ) { - $chunk_index = $index; - break; - } - } - array_splice( $block['innerContent'], $chunk_index, 0, array( null ) ); - } elseif ( 'last_child' === $relative_position ) { - array_push( $block['innerBlocks'], $inserted_block ); - // Since WP_Block::render() iterates over `inner_content` (rather than `inner_blocks`) - // when rendering blocks, we also need to correctly append a value (`null`, to mark a block - // location) to that array before the remaining HTML content for the inner blocks wrapper. - $chunk_index = count( $block['innerContent'] ); - for ( $index = count( $block['innerContent'] ); $index > 0; $index-- ) { - if ( is_null( $block['innerContent'][ $index - 1 ] ) ) { - $chunk_index = $index; - break; - } - } - array_splice( $block['innerContent'], $chunk_index, 0, array( null ) ); - } - return $block; - } - - $anchor_block_index = array_search( $anchor_block_type, array_column( $block['innerBlocks'], 'blockName' ), true ); - if ( false !== $anchor_block_index && ( 'after' === $relative_position || 'before' === $relative_position ) ) { - if ( 'after' === $relative_position ) { - ++$anchor_block_index; - } - array_splice( $block['innerBlocks'], $anchor_block_index, 0, array( $inserted_block ) ); - - // Find matching `innerContent` chunk index. - $chunk_index = 0; - while ( $anchor_block_index > 0 ) { - if ( ! is_string( $block['innerContent'][ $chunk_index ] ) ) { - --$anchor_block_index; - } - ++$chunk_index; - } - // Since WP_Block::render() iterates over `inner_content` (rather than `inner_blocks`) - // when rendering blocks, we also need to insert a value (`null`, to mark a block - // location) into that array. - array_splice( $block['innerContent'], $chunk_index, 0, array( null ) ); - } - return $block; - }; -} - -/** - * Add block hooks information to a block type's controller. - * - * @param array $inserted_block_type The type of block to insert. - * @param string $position The position relative to the anchor block. - * Can be 'before', 'after', 'first_child', or 'last_child'. - * @param string $anchor_block_type The hooked block will be inserted next to instances of this block type. - * @return callable A filter for the `rest_prepare_block_type` hook that adds a `block_hooks` field to the network response. - */ -function gutenberg_add_block_hooks_field_to_block_type_controller( $inserted_block_type, $position, $anchor_block_type ) { - return function ( $response, $block_type ) use ( $inserted_block_type, $position, $anchor_block_type ) { - if ( $block_type->name !== $inserted_block_type ) { - return $response; - } - - $data = $response->get_data(); - if ( ! isset( $data['block_hooks'] ) ) { - $data['block_hooks'] = array(); - } - $data['block_hooks'][ $anchor_block_type ] = $position; - $response->set_data( $data ); - return $response; - }; -} - -/** - * Parse and reserialize block templates to allow running filters. - * - * By parsing a block template's content and then reserializing it - * via `gutenberg_serialize_blocks()`, we are able to run filters - * on the parsed blocks. This allows us to modify (parsed) blocks during - * depth-first traversal already provided by the serialization process, - * rather than having to do so in a separate pass. - * - * @param WP_Block_Template[] $query_result Array of found block templates. - * @return WP_Block_Template[] Updated array of found block templates. - */ -function gutenberg_parse_and_serialize_block_templates( $query_result ) { - foreach ( $query_result as $block_template ) { - if ( empty( $block_template->content ) || 'custom' === $block_template->source ) { - continue; - } - $blocks = parse_blocks( $block_template->content ); - $block_template->content = gutenberg_serialize_blocks( $blocks ); - } - - return $query_result; -} - -/** - * Filters the block template object after it has been (potentially) fetched from the theme file. - * - * By parsing a block template's content and then reserializing it - * via `gutenberg_serialize_blocks()`, we are able to run filters - * on the parsed blocks. This allows us to modify (parsed) blocks during - * depth-first traversal already provided by the serialization process, - * rather than having to do so in a separate pass. - * - * @param WP_Block_Template|null $block_template The found block template, or null if there is none. - */ -function gutenberg_parse_and_serialize_blocks( $block_template ) { - if ( empty( $block_template->content ) ) { - return $block_template; - } - - $blocks = parse_blocks( $block_template->content ); - $block_template->content = gutenberg_serialize_blocks( $blocks ); - - return $block_template; -} - -/** - * Register the `block_hooks` field for the block-types REST API controller. - * - * @return void - */ -function gutenberg_register_block_hooks_rest_field() { - register_rest_field( - 'block-type', - 'block_hooks', - array( - 'schema' => array( - 'description' => __( 'This block is automatically inserted near any occurrence of the block types used as keys of this map, into a relative position given by the corresponding value.', 'gutenberg' ), - 'type' => 'object', - 'patternProperties' => array( - '^[a-zA-Z0-9-]+/[a-zA-Z0-9-]+$' => array( - 'type' => 'string', - 'enum' => array( 'before', 'after', 'first_child', 'last_child' ), - ), - ), - ), - ) - ); -} - -// Install the polyfill for Block Hooks only if it isn't already handled in WordPress core. -if ( ! function_exists( 'traverse_and_serialize_blocks' ) ) { - add_filter( 'block_type_metadata_settings', 'gutenberg_add_hooked_blocks', 10, 2 ); - add_filter( 'get_block_templates', 'gutenberg_parse_and_serialize_block_templates', 10, 1 ); - add_filter( 'get_block_file_template', 'gutenberg_parse_and_serialize_blocks', 10, 1 ); - add_action( 'rest_api_init', 'gutenberg_register_block_hooks_rest_field' ); -} - -// Helper functions. -// ----------------- -// The sole purpose of the following two functions (`gutenberg_serialize_block` -// and `gutenberg_serialize_blocks`), which are otherwise copies of their unprefixed -// counterparts (`serialize_block` and `serialize_blocks`) is to apply a filter -// (also called `gutenberg_serialize_block`) as an entry point for modifications -// to the parsed blocks. - -/** - * Filterable version of `serialize_block()`. - * - * This function is identical to `serialize_block()`, except that it applies - * the `gutenberg_serialize_block` filter to each block before it is serialized. - * - * @param array $block The block to be serialized. - * @return string The serialized block. - * - * @see serialize_block() - */ -function gutenberg_serialize_block( $block ) { - $block_content = ''; - - /** - * Filters a parsed block before it is serialized. - * - * @param array $block The block to be serialized. - */ - $block = apply_filters( 'gutenberg_serialize_block', $block ); - - $index = 0; - foreach ( $block['innerContent'] as $chunk ) { - if ( is_string( $chunk ) ) { - $block_content .= $chunk; - } else { // Compare to WP_Block::render(). - $inner_block = $block['innerBlocks'][ $index++ ]; - $block_content .= gutenberg_serialize_block( $inner_block ); - } - } - - if ( ! is_array( $block['attrs'] ) ) { - $block['attrs'] = array(); - } - - return get_comment_delimited_block_content( - $block['blockName'], - $block['attrs'], - $block_content - ); -} - -/** - * Filterable version of `serialize_blocks()`. - * - * This function is identical to `serialize_blocks()`, except that it applies - * the `gutenberg_serialize_block` filter to each block before it is serialized. - * - * @param array $blocks The blocks to be serialized. - * @return string[] The serialized blocks. - * - * @see serialize_blocks() - */ -function gutenberg_serialize_blocks( $blocks ) { - return implode( '', array_map( 'gutenberg_serialize_block', $blocks ) ); -} diff --git a/lib/compat/wordpress-6.4/blocks.php b/lib/compat/wordpress-6.4/blocks.php deleted file mode 100644 index 74fa9253e45d50..00000000000000 --- a/lib/compat/wordpress-6.4/blocks.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php -/** - * Temporary compatibility shims for block APIs present in Gutenberg. - * - * @package gutenberg - */ - -/** - * Adds delete_posts capabilities to the wp_block post type. - * - * @param array $args Register post type args. - * - * @return array Register post type args. - */ -function gutenberg_add_custom_capabilities_to_wp_block( $args ) { - if ( is_array( $args ) ) { - if ( ! isset( $args['capabilities'] ) || is_array( $args['capabilities'] ) ) { - $args['capabilities']['delete_posts'] = 'delete_posts'; - } - } - return $args; -} -add_filter( 'register_wp_block_post_type_args', 'gutenberg_add_custom_capabilities_to_wp_block', 10, 1 ); diff --git a/lib/compat/wordpress-6.4/class-gutenberg-rest-block-patterns-controller.php b/lib/compat/wordpress-6.4/class-gutenberg-rest-block-patterns-controller.php deleted file mode 100644 index d3c3431bae4b31..00000000000000 --- a/lib/compat/wordpress-6.4/class-gutenberg-rest-block-patterns-controller.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -/** - * REST API: Gutenberg_REST_Block_Patterns_Controller class - * - * @package Gutenberg - * @subpackage REST_API - */ - -/** - * Core class used to access block patterns via the REST API. - * - * @since 6.4.0 - * - * @see WP_REST_Controller - */ -class Gutenberg_REST_Block_Patterns_Controller extends WP_REST_Block_Patterns_Controller { - /** - * Prepare a raw block pattern before it gets output in a REST API response. - * - * @todo In the long run, we'd likely want to have a filter in the `WP_Block_Patterns_Registry` class - * instead to allow us plugging in code like this. - * - * @param array $item Raw pattern as registered, before any changes. - * @param WP_REST_Request $request Request object. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function prepare_item_for_response( $item, $request ) { - $response = parent::prepare_item_for_response( $item, $request ); - - // Run the polyfill for Block Hooks only if it isn't already handled in WordPress core. - if ( function_exists( 'traverse_and_serialize_blocks' ) ) { - return $response; - } - - $data = $response->get_data(); - - if ( empty( $data['content'] ) ) { - return $response; - } - - $blocks = parse_blocks( $data['content'] ); - $data['content'] = gutenberg_serialize_blocks( $blocks ); // Serialize or render? - - return rest_ensure_response( $data ); - } -} diff --git a/lib/compat/wordpress-6.4/class-gutenberg-rest-global-styles-revisions-controller-6-4.php b/lib/compat/wordpress-6.4/class-gutenberg-rest-global-styles-revisions-controller-6-4.php deleted file mode 100644 index 4c7df97c33e57c..00000000000000 --- a/lib/compat/wordpress-6.4/class-gutenberg-rest-global-styles-revisions-controller-6-4.php +++ /dev/null @@ -1,164 +0,0 @@ -<?php -/** - * REST API: Gutenberg_REST_Global_Styles_Revisions_Controller class, inspired by WP_REST_Revisions_Controller. - * - * @package WordPress - * @subpackage REST_API - * @since 6.3.0 - */ - -/** - * Core class used to access global styles revisions via the REST API. - * - * @since 6.3.0 - * - * @see WP_REST_Controller - */ -class Gutenberg_REST_Global_Styles_Revisions_Controller_6_4 extends WP_REST_Global_Styles_Revisions_Controller { - /** - * Prepares the revision for the REST response. - * - * @since 6.3.0 - * - * @param WP_Post $post Post revision object. - * @param WP_REST_Request $request Request object. - * @return WP_REST_Response|WP_Error Response object. - */ - public function prepare_item_for_response( $post, $request ) { - $parent = $this->get_parent( $request['parent'] ); - $global_styles_config = $this->get_decoded_global_styles_json( $post->post_content ); - - if ( is_wp_error( $global_styles_config ) ) { - return $global_styles_config; - } - - $fields = $this->get_fields_for_response( $request ); - $data = array(); - - if ( ! empty( $global_styles_config['styles'] ) || ! empty( $global_styles_config['settings'] ) ) { - $global_styles_config = ( new WP_Theme_JSON_Gutenberg( $global_styles_config, 'custom' ) )->get_raw_data(); - if ( rest_is_field_included( 'settings', $fields ) ) { - $data['settings'] = ! empty( $global_styles_config['settings'] ) ? $global_styles_config['settings'] : new stdClass(); - } - if ( rest_is_field_included( 'styles', $fields ) ) { - $data['styles'] = ! empty( $global_styles_config['styles'] ) ? $global_styles_config['styles'] : new stdClass(); - } - } - - if ( rest_is_field_included( 'author', $fields ) ) { - $data['author'] = (int) $post->post_author; - } - - if ( rest_is_field_included( 'date', $fields ) ) { - $data['date'] = $this->prepare_date_response( $post->post_date_gmt, $post->post_date ); - } - - if ( rest_is_field_included( 'date_gmt', $fields ) ) { - $data['date_gmt'] = $this->prepare_date_response( $post->post_date_gmt ); - } - - if ( rest_is_field_included( 'id', $fields ) ) { - $data['id'] = (int) $post->ID; - } - - if ( rest_is_field_included( 'modified', $fields ) ) { - $data['modified'] = $this->prepare_date_response( $post->post_modified_gmt, $post->post_modified ); - } - - if ( rest_is_field_included( 'modified_gmt', $fields ) ) { - $data['modified_gmt'] = $this->prepare_date_response( $post->post_modified_gmt ); - } - - if ( rest_is_field_included( 'parent', $fields ) ) { - $data['parent'] = (int) $parent->ID; - } - - $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; - $data = $this->add_additional_fields_to_object( $data, $request ); - $data = $this->filter_response_by_context( $data, $context ); - - return rest_ensure_response( $data ); - } - - /** - * Retrieves the revision's schema, conforming to JSON Schema. - * - * @since 6.3.0 - * - * @return array Item schema data. - */ - public function get_item_schema() { - if ( $this->schema ) { - return $this->add_additional_fields_schema( $this->schema ); - } - - $schema = array( - '$schema' => 'http://json-schema.org/draft-04/schema#', - 'title' => "{$this->parent_post_type}-revision", - 'type' => 'object', - // Base properties for every Revision. - 'properties' => array( - - /* - * Adds settings and styles from the WP_REST_Revisions_Controller item fields. - * Leaves out GUID as global styles shouldn't be accessible via URL. - */ - 'author' => array( - 'description' => __( 'The ID for the author of the revision.', 'gutenberg' ), - 'type' => 'integer', - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'date' => array( - 'description' => __( "The date the revision was published, in the site's timezone.", 'gutenberg' ), - 'type' => 'string', - 'format' => 'date-time', - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'date_gmt' => array( - 'description' => __( 'The date the revision was published, as GMT.', 'gutenberg' ), - 'type' => 'string', - 'format' => 'date-time', - 'context' => array( 'view', 'edit' ), - ), - 'id' => array( - 'description' => __( 'Unique identifier for the revision.', 'gutenberg' ), - 'type' => 'integer', - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'modified' => array( - 'description' => __( "The date the revision was last modified, in the site's timezone.", 'gutenberg' ), - 'type' => 'string', - 'format' => 'date-time', - 'context' => array( 'view', 'edit' ), - ), - 'modified_gmt' => array( - 'description' => __( 'The date the revision was last modified, as GMT.', 'gutenberg' ), - 'type' => 'string', - 'format' => 'date-time', - 'context' => array( 'view', 'edit' ), - ), - 'parent' => array( - 'description' => __( 'The ID for the parent of the revision.', 'gutenberg' ), - 'type' => 'integer', - 'context' => array( 'view', 'edit', 'embed' ), - ), - - // Adds settings and styles from the WP_REST_Global_Styles_Controller parent schema. - 'styles' => array( - 'description' => __( 'Global styles.', 'gutenberg' ), - 'type' => array( 'object' ), - 'context' => array( 'view', 'edit' ), - ), - 'settings' => array( - 'description' => __( 'Global settings.', 'gutenberg' ), - 'type' => array( 'object' ), - 'context' => array( 'view', 'edit' ), - ), - ), - ); - - $this->schema = $schema; - - return $this->add_additional_fields_schema( $this->schema ); - } -} diff --git a/lib/compat/wordpress-6.4/class-gutenberg-rest-templates-controller-6-4.php b/lib/compat/wordpress-6.4/class-gutenberg-rest-templates-controller-6-4.php deleted file mode 100644 index ec969519f9ac4f..00000000000000 --- a/lib/compat/wordpress-6.4/class-gutenberg-rest-templates-controller-6-4.php +++ /dev/null @@ -1,75 +0,0 @@ -<?php -/** - * REST API: Gutenberg_REST_Templates_Controller_6_4 class - * - * @package gutenberg - */ - -/** - * Gutenberg_REST_Templates_Controller_6_4 class - * - * Template revision changes are waiting on a core change to be merged. - * See: https://github.com/WordPress/gutenberg/pull/45215#issuecomment-1592704026 - * When merging into core, prepare_revision_links() should be merged with - * WP_REST_Templates_Controller::prepare_links(). - */ -class Gutenberg_REST_Templates_Controller_6_4 extends WP_REST_Templates_Controller { - /** - * Add revisions to the response. - * - * @param WP_Block_Template $item Template instance. - * @param WP_REST_Request $request Request object. - * @return WP_REST_Response Response object. - */ - public function prepare_item_for_response( $item, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable - $template = $item; - - $fields = $this->get_fields_for_response( $request ); - - $response = parent::prepare_item_for_response( $item, $request ); - - if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { - $links = $this->prepare_revision_links( $template ); - $response->add_links( $links ); - if ( ! empty( $links['self']['href'] ) ) { - $actions = $this->get_available_actions(); - $self = $links['self']['href']; - foreach ( $actions as $rel ) { - $response->add_link( $rel, $self ); - } - } - } - - return $response; - } - - /** - * Adds revisions to links. - * - * @param WP_Block_Template $template Template instance. - * @return array Links for the given post. - */ - protected function prepare_revision_links( $template ) { - $links = array(); - - if ( post_type_supports( $this->post_type, 'revisions' ) && (int) $template->wp_id ) { - $revisions = wp_get_latest_revision_id_and_total_count( (int) $template->wp_id ); - $revisions_count = ! is_wp_error( $revisions ) ? $revisions['count'] : 0; - $revisions_base = sprintf( '/%s/%s/%s/revisions', $this->namespace, $this->rest_base, $template->id ); - - $links['version-history'] = array( - 'href' => rest_url( $revisions_base ), - 'count' => $revisions_count, - ); - - if ( $revisions_count > 0 ) { - $links['predecessor-version'] = array( - 'href' => rest_url( $revisions_base . '/' . $revisions['latest_id'] ), - 'id' => $revisions['latest_id'], - ); - } - } - - return $links; - } -} diff --git a/lib/compat/wordpress-6.4/fonts/font-face/class-wp-font-face-resolver.php b/lib/compat/wordpress-6.4/fonts/font-face/class-wp-font-face-resolver.php deleted file mode 100644 index 556663b8813665..00000000000000 --- a/lib/compat/wordpress-6.4/fonts/font-face/class-wp-font-face-resolver.php +++ /dev/null @@ -1,183 +0,0 @@ -<?php -/** - * WP_Font_Face_Resolver class. - * - * @package WordPress - * @subpackage Fonts - * @since 6.4.0 - * - * @core-merge: this file is located in `wp-includes/fonts/`. - */ - -if ( ! class_exists( 'WP_Font_Face_Resolver' ) ) { - - /** - * The Font Face Resolver abstracts the processing of different data sources - * (such as theme.json) for processing within the Font Face. - * - * This class is for internal core usage and is not supposed to be used by - * extenders (plugins and/or themes). - * - * @access private - */ - class WP_Font_Face_Resolver { - - /** - * Gets fonts defined in theme.json. - * - * @since 6.4.0 - * - * @return array Returns the font-families, each with their font-face variations. - */ - public static function get_fonts_from_theme_json() { - $settings = gutenberg_get_global_settings(); - - // Bail out early if there are no font settings. - if ( empty( $settings['typography']['fontFamilies'] ) ) { - return array(); - } - - return static::parse_settings( $settings ); - } - - /** - * Parse theme.json settings to extract font definitions with variations grouped by font-family. - * - * @since 6.4.0 - * - * @param array $settings Font settings to parse. - * @return array Returns an array of fonts, grouped by font-family. - */ - private static function parse_settings( array $settings ) { - $fonts = array(); - - foreach ( $settings['typography']['fontFamilies'] as $font_families ) { - foreach ( $font_families as $definition ) { - - // Skip if "fontFace" is not defined, meaning there are no variations. - if ( empty( $definition['fontFace'] ) ) { - continue; - } - - // Skip if "fontFamily" is not defined. - if ( empty( $definition['fontFamily'] ) ) { - continue; - } - - $font_family_name = static::maybe_parse_name_from_comma_separated_list( $definition['fontFamily'] ); - - // Skip if no font family is defined. - if ( empty( $font_family_name ) ) { - continue; - } - - // Prepare the fonts array structure for this font-family. - if ( ! array_key_exists( $font_family_name, $fonts ) ) { - $fonts[ $font_family_name ] = array(); - } - - $fonts[ $font_family_name ] = static::convert_font_face_properties( $definition['fontFace'], $font_family_name ); - } - } - - return $fonts; - } - - /** - * Parse font-family name from comma-separated lists. - * - * If the given `fontFamily` is a comma-separated lists (example: "Inter, sans-serif" ), - * parse and return the fist font from the list. - * - * @since 6.4.0 - * - * @param string $font_family Font family `fontFamily' to parse. - * @return string Font-family name. - */ - private static function maybe_parse_name_from_comma_separated_list( $font_family ) { - if ( str_contains( $font_family, ',' ) ) { - $font_family = explode( ',', $font_family )[0]; - } - - return trim( $font_family, "\"'" ); - } - - /** - * Converts font-face properties from theme.json format. - * - * @since 6.4.0 - * - * @param array $font_face_definition The font-face definitions to convert. - * @param string $font_family_property The value to store in the font-face font-family property. - * @return array Converted font-face properties. - */ - private static function convert_font_face_properties( array $font_face_definition, $font_family_property ) { - $converted_font_faces = array(); - - foreach ( $font_face_definition as $font_face ) { - // Add the font-family property to the font-face. - $font_face['font-family'] = $font_family_property; - - // Converts the "file:./" src placeholder into a theme font file URI. - if ( ! empty( $font_face['src'] ) ) { - $font_face['src'] = static::to_theme_file_uri( (array) $font_face['src'] ); - } - - // Convert camelCase properties into kebab-case. - $font_face = static::to_kebab_case( $font_face ); - - $converted_font_faces[] = $font_face; - } - - return $converted_font_faces; - } - - /** - * Converts each 'file:./' placeholder into a URI to the font file in the theme. - * - * The 'file:./' is specified in the theme's `theme.json` as a placeholder to be - * replaced with the URI to the font file's location in the theme. When a "src" - * beings with this placeholder, it is replaced, converting the src into a URI. - * - * @since 6.4.0 - * - * @param array $src An array of font file sources to process. - * @return array An array of font file src URI(s). - */ - private static function to_theme_file_uri( array $src ) { - $placeholder = 'file:./'; - - foreach ( $src as $src_key => $src_url ) { - // Skip if the src doesn't start with the placeholder, as there's nothing to replace. - if ( ! str_starts_with( $src_url, $placeholder ) ) { - continue; - } - - $src_file = str_replace( $placeholder, '', $src_url ); - $src[ $src_key ] = get_theme_file_uri( $src_file ); - } - - return $src; - } - - /** - * Converts all first dimension keys into kebab-case. - * - * @since 6.4.0 - * - * @param array $data The array to process. - * @return array Data with first dimension keys converted into kebab-case. - */ - private static function to_kebab_case( array $data ) { - foreach ( $data as $key => $value ) { - $kebab_case = _wp_to_kebab_case( $key ); - $data[ $kebab_case ] = $value; - if ( $kebab_case !== $key ) { - unset( $data[ $key ] ); - } - } - - return $data; - } - } -} diff --git a/lib/compat/wordpress-6.4/fonts/font-face/class-wp-font-face.php b/lib/compat/wordpress-6.4/fonts/font-face/class-wp-font-face.php deleted file mode 100644 index 6bea6eb86cc714..00000000000000 --- a/lib/compat/wordpress-6.4/fonts/font-face/class-wp-font-face.php +++ /dev/null @@ -1,435 +0,0 @@ -<?php -/** - * WP_Font_Face class. - * - * @package WordPress - * @subpackage Fonts - * @since 6.4.0 - * - * @core-merge: this file is located in `wp-includes/fonts/`. - */ - -if ( ! class_exists( 'WP_Font_Face' ) ) { - - /** - * Font Face generates and prints `@font-face` styles for given fonts. - * - * @since 6.4.0 - */ - class WP_Font_Face { - - /** - * The font-face property defaults. - * - * @since 6.4.0 - * - * @var string[] - */ - private $font_face_property_defaults = array( - 'font-family' => '', - 'font-style' => 'normal', - 'font-weight' => '400', - 'font-display' => 'fallback', - ); - - /** - * Valid font-face property names. - * - * @since 6.4.0 - * - * @var string[] - */ - private $valid_font_face_properties = array( - 'ascent-override', - 'descent-override', - 'font-display', - 'font-family', - 'font-stretch', - 'font-style', - 'font-weight', - 'font-variant', - 'font-feature-settings', - 'font-variation-settings', - 'line-gap-override', - 'size-adjust', - 'src', - 'unicode-range', - ); - - /** - * Valid font-display values. - * - * @since 6.4.0 - * - * @var string[] - */ - private $valid_font_display = array( 'auto', 'block', 'fallback', 'swap', 'optional' ); - - /** - * Array of font-face style tag's attribute(s) - * where the key is the attribute name and the - * value is its value. - * - * @since 6.4.0 - * - * @var string[] - */ - private $style_tag_attrs = array(); - - /** - * Creates and initializes an instance of WP_Font_Face. - * - * @since 6.4.0 - */ - public function __construct() { - if ( - function_exists( 'is_admin' ) && ! is_admin() - && - function_exists( 'current_theme_supports' ) && ! current_theme_supports( 'html5', 'style' ) - ) { - $this->style_tag_attrs = array( 'type' => 'text/css' ); - } - } - - /** - * Generates and prints the `@font-face` styles for the given fonts. - * - * @since 6.4.0 - * - * @param array[][] $fonts Optional. The font-families and their font variations. - * See {@see wp_print_font_faces()} for the supported fields. - * Default empty array. - */ - public function generate_and_print( array $fonts ) { - $fonts = $this->validate_fonts( $fonts ); - - // Bail out if there are no fonts are given to process. - if ( empty( $fonts ) ) { - return; - } - - $css = $this->get_css( $fonts ); - - /* - * The font-face CSS is contained within <style> tags and can only be interpreted - * as CSS in the browser. Using wp_strip_all_tags() is sufficient escaping - * to avoid malicious attempts to close </style> and open a <script>. - */ - $css = wp_strip_all_tags( $css ); - - // Bail out if there is no CSS to print. - if ( empty( $css ) ) { - return; - } - - printf( $this->get_style_element(), $css ); - } - - /** - * Validates each of the font-face properties. - * - * @since 6.4.0 - * - * @param array $fonts The fonts to valid. - * @return array Prepared font-faces organized by provider and font-family. - */ - private function validate_fonts( array $fonts ) { - $validated_fonts = array(); - - foreach ( $fonts as $font_faces ) { - foreach ( $font_faces as $font_face ) { - $font_face = $this->validate_font_face_declarations( $font_face ); - // Skip if failed validation. - if ( false === $font_face ) { - continue; - } - - $validated_fonts[] = $font_face; - } - } - - return $validated_fonts; - } - - /** - * Validates each font-face declaration (property and value pairing). - * - * @since 6.4.0 - * - * @param array $font_face Font face property and value pairings to validate. - * @return array|false Validated font-face on success, or false on failure. - */ - private function validate_font_face_declarations( array $font_face ) { - $font_face = wp_parse_args( $font_face, $this->font_face_property_defaults ); - - // Check the font-family. - if ( empty( $font_face['font-family'] ) || ! is_string( $font_face['font-family'] ) ) { - // @todo replace with `wp_trigger_error()`. - _doing_it_wrong( - __METHOD__, - __( 'Font font-family must be a non-empty string.' ), - '6.4.0' - ); - return false; - } - - // Make sure that local fonts have 'src' defined. - if ( empty( $font_face['src'] ) || ( ! is_string( $font_face['src'] ) && ! is_array( $font_face['src'] ) ) ) { - // @todo replace with `wp_trigger_error()`. - _doing_it_wrong( - __METHOD__, - __( 'Font src must be a non-empty string or an array of strings.' ), - '6.4.0' - ); - return false; - } - - // Validate the 'src' property. - foreach ( (array) $font_face['src'] as $src ) { - if ( empty( $src ) || ! is_string( $src ) ) { - // @todo replace with `wp_trigger_error()`. - _doing_it_wrong( - __METHOD__, - __( 'Each font src must be a non-empty string.' ), - '6.4.0' - ); - return false; - } - } - - // Check the font-weight. - if ( ! is_string( $font_face['font-weight'] ) && ! is_int( $font_face['font-weight'] ) ) { - // @todo replace with `wp_trigger_error()`. - _doing_it_wrong( - __METHOD__, - __( 'Font font-weight must be a properly formatted string or integer.' ), - '6.4.0' - ); - return false; - } - - // Check the font-display. - if ( ! in_array( $font_face['font-display'], $this->valid_font_display, true ) ) { - $font_face['font-display'] = $this->font_face_property_defaults['font-display']; - } - - // Remove invalid properties. - foreach ( $font_face as $property => $value ) { - if ( ! in_array( $property, $this->valid_font_face_properties, true ) ) { - unset( $font_face[ $property ] ); - } - } - - return $font_face; - } - - /** - * Gets the style element for wrapping the `@font-face` CSS. - * - * @since 6.4.0 - * - * @return string The style element. - */ - private function get_style_element() { - $attributes = $this->generate_style_element_attributes(); - - return "<style id='wp-fonts-local'{$attributes}>\n%s\n</style>\n"; - } - - /** - * Gets the defined <style> element's attributes. - * - * @since 6.4.0 - * - * @return string A string of attribute=value when defined, else, empty string. - */ - private function generate_style_element_attributes() { - $attributes = ''; - foreach ( $this->style_tag_attrs as $name => $value ) { - $attributes .= " {$name}='{$value}'"; - } - return $attributes; - } - - /** - * Gets the `@font-face` CSS styles for locally-hosted font files. - * - * This method does the following processing tasks: - * 1. Orchestrates an optimized `src` (with format) for browser support. - * 2. Generates the `@font-face` for all its fonts. - * - * @since 6.4.0 - * - * @param array $font_faces The font-faces to generate @font-face CSS styles. - * @return string The `@font-face` CSS styles. - */ - private function get_css( $font_faces ) { - $css = ''; - - foreach ( $font_faces as $font_face ) { - // Order the font's `src` items to optimize for browser support. - $font_face = $this->order_src( $font_face ); - - // Build the @font-face CSS for this font. - $css .= '@font-face{' . $this->build_font_face_css( $font_face ) . '}' . "\n"; - } - - // Don't print the last newline character. - return rtrim( $css, "\n" ); - } - - /** - * Orders `src` items to optimize for browser support. - * - * @since 6.4.0 - * - * @param array $font_face Font face to process. - * @return array Font-face with ordered src items. - */ - private function order_src( array $font_face ) { - if ( ! is_array( $font_face['src'] ) ) { - $font_face['src'] = (array) $font_face['src']; - } - - $src = array(); - $src_ordered = array(); - - foreach ( $font_face['src'] as $url ) { - // Add data URIs first. - if ( str_starts_with( trim( $url ), 'data:' ) ) { - $src_ordered[] = array( - 'url' => $url, - 'format' => 'data', - ); - continue; - } - $format = pathinfo( $url, PATHINFO_EXTENSION ); - $src[ $format ] = $url; - } - - // Add woff2. - if ( ! empty( $src['woff2'] ) ) { - $src_ordered[] = array( - 'url' => $src['woff2'], - 'format' => 'woff2', - ); - } - - // Add woff. - if ( ! empty( $src['woff'] ) ) { - $src_ordered[] = array( - 'url' => $src['woff'], - 'format' => 'woff', - ); - } - - // Add ttf. - if ( ! empty( $src['ttf'] ) ) { - $src_ordered[] = array( - 'url' => $src['ttf'], - 'format' => 'truetype', - ); - } - - // Add eot. - if ( ! empty( $src['eot'] ) ) { - $src_ordered[] = array( - 'url' => $src['eot'], - 'format' => 'embedded-opentype', - ); - } - - // Add otf. - if ( ! empty( $src['otf'] ) ) { - $src_ordered[] = array( - 'url' => $src['otf'], - 'format' => 'opentype', - ); - } - $font_face['src'] = $src_ordered; - - return $font_face; - } - - /** - * Builds the font-family's CSS. - * - * @since 6.4.0 - * - * @param array $font_face Font face to process. - * @return string This font-family's CSS. - */ - private function build_font_face_css( array $font_face ) { - $css = ''; - - /* - * Wrap font-family in quotes if it contains spaces - * and is not already wrapped in quotes. - */ - if ( - str_contains( $font_face['font-family'], ' ' ) && - ! str_contains( $font_face['font-family'], '"' ) && - ! str_contains( $font_face['font-family'], "'" ) - ) { - $font_face['font-family'] = '"' . $font_face['font-family'] . '"'; - } - - foreach ( $font_face as $key => $value ) { - // Compile the "src" parameter. - if ( 'src' === $key ) { - $value = $this->compile_src( $value ); - } - - // If font-variation-settings is an array, convert it to a string. - if ( 'font-variation-settings' === $key && is_array( $value ) ) { - $value = $this->compile_variations( $value ); - } - - if ( ! empty( $value ) ) { - $css .= "$key:$value;"; - } - } - - return $css; - } - - /** - * Compiles the `src` into valid CSS. - * - * @since 6.4.0 - * - * @param array $value Value to process. - * @return string The CSS. - */ - private function compile_src( array $value ) { - $src = ''; - - foreach ( $value as $item ) { - $src .= ( 'data' === $item['format'] ) - ? ", url({$item['url']})" - : ", url('{$item['url']}') format('{$item['format']}')"; - } - - $src = ltrim( $src, ', ' ); - return $src; - } - - /** - * Compiles the font variation settings. - * - * @since 6.4.0 - * - * @param array $font_variation_settings Array of font variation settings. - * @return string The CSS. - */ - private function compile_variations( array $font_variation_settings ) { - $variations = ''; - - foreach ( $font_variation_settings as $key => $value ) { - $variations .= "$key $value"; - } - - return $variations; - } - } -} diff --git a/lib/compat/wordpress-6.4/fonts/fonts.php b/lib/compat/wordpress-6.4/fonts/fonts.php deleted file mode 100644 index 94aef51a440a1e..00000000000000 --- a/lib/compat/wordpress-6.4/fonts/fonts.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php -/** - * Fonts functions. - * - * @package WordPress - * @subpackage Fonts - * @since 6.4.0 - * - * @core-merge: this file is located in `wp-includes/fonts.php`. It will contain Font Face and Font Library functions. - */ - -if ( ! function_exists( 'wp_print_font_faces' ) ) { - // @core-merge: will merge into Core's `wp-includes/default-filters.php` file. - add_action( 'wp_head', 'wp_print_font_faces', 50 ); - // @core-merge: will merge into Core's `wp-admin/includes/admin-filters.php.` file. - add_action( 'admin_print_styles', 'wp_print_font_faces', 50 ); - - /** - * Generates and prints font-face styles for given fonts or theme.json fonts. - * - * @since 6.4.0 - * - * @param array[][] $fonts { - * Optional. The font-families and their font variations. Default empty array. - * - * @type string $font-family => array[] $variations { - * Optional. An associated array of font variations for this font-family. - * Each variation has the following structure. - * - * @type array $font_variation { - * @type string $font-family The font-family property. - * @type string|string[] $src The URL(s) to each resource containing the font data. - * @type string $font_style Optional. The font-style property. Default 'normal'. - * @type string $font-weight Optional. The font-weight property. Default '400'. - * @type string $font-display Optional. The font-display property. Default 'fallback'. - * @type string $ascent-override Optional. The ascent-override property. - * @type string $descent-override Optional. The descent-override property. - * @type string $font-stretch Optional. The font-stretch property. - * @type string $font-variant Optional. The font-variant property. - * @type string $font-feature-settings Optional. The font-feature-settings property. - * @type string $font-variation-settings Optional. The font-variation-settings property. - * @type string $line-gap-override Optional. The line-gap-override property. - * @type string $size-adjust Optional. The size-adjust property. - * @type string $unicode-range Optional. The unicode-range property. - * } - * } - * } - */ - function wp_print_font_faces( $fonts = array() ) { - - if ( empty( $fonts ) ) { - $fonts = WP_Font_Face_Resolver::get_fonts_from_theme_json(); - } - - if ( empty( $fonts ) ) { - return; - } - - $wp_font_face = new WP_Font_Face(); - $wp_font_face->generate_and_print( $fonts ); - } -} - -// @core-merge: do not merge this code into Core. -add_filter( - 'block_editor_settings_all', - static function ( $settings ) { - ob_start(); - // @core-merge: add only this line into Core's `_wp_get_iframed_editor_assets()` function after `wp_print_styles()`. - wp_print_font_faces(); - $styles = ob_get_clean(); - - // Add the font-face styles to iframed editor assets. - $settings['__unstableResolvedAssets']['styles'] .= $styles; - return $settings; - }, - 11 -); diff --git a/lib/compat/wordpress-6.4/html-api/class-gutenberg-html-tag-processor-6-4.php b/lib/compat/wordpress-6.4/html-api/class-gutenberg-html-tag-processor-6-4.php deleted file mode 100644 index 40e3ce425f8b05..00000000000000 --- a/lib/compat/wordpress-6.4/html-api/class-gutenberg-html-tag-processor-6-4.php +++ /dev/null @@ -1,2457 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Tag_Processor class - * - * Scans through an HTML document to find specific tags, then - * transforms those tags by adding, removing, or updating the - * values of the HTML attributes within that tag (opener). - * - * Does not fully parse HTML or _recurse_ into the HTML structure - * Instead this scans linearly through a document and only parses - * the HTML tag openers. - * - * ### Possible future direction for this module - * - * - Prune the whitespace when removing classes/attributes: e.g. "a b c" -> "c" not " c". - * This would increase the size of the changes for some operations but leave more - * natural-looking output HTML. - * - Decode HTML character references within class names when matching. E.g. match having - * class `1<"2` needs to recognize `class="1<"2"`. Currently the Tag Processor - * will fail to find the right tag if the class name is encoded as such. - * - Properly decode HTML character references in `get_attribute()`. PHP's - * `html_entity_decode()` is wrong in a couple ways: it doesn't account for the - * no-ambiguous-ampersand rule, and it improperly handles the way semicolons may - * or may not terminate a character reference. - * - * @package WordPress - * @subpackage HTML-API - * @since 6.2.0 - */ - -/** - * Core class used to modify attributes in an HTML document for tags matching a query. - * - * ## Usage - * - * Use of this class requires three steps: - * - * 1. Create a new class instance with your input HTML document. - * 2. Find the tag(s) you are looking for. - * 3. Request changes to the attributes in those tag(s). - * - * Example: - * - * $tags = new WP_HTML_Tag_Processor( $html ); - * if ( $tags->next_tag( 'option' ) ) { - * $tags->set_attribute( 'selected', true ); - * } - * - * ### Finding tags - * - * The `next_tag()` function moves the internal cursor through - * your input HTML document until it finds a tag meeting any of - * the supplied restrictions in the optional query argument. If - * no argument is provided then it will find the next HTML tag, - * regardless of what kind it is. - * - * If you want to _find whatever the next tag is_: - * - * $tags->next_tag(); - * - * | Goal | Query | - * |-----------------------------------------------------------|---------------------------------------------------------------------------------| - * | Find any tag. | `$tags->next_tag();` | - * | Find next image tag. | `$tags->next_tag( array( 'tag_name' => 'img' ) );` | - * | Find next image tag (without passing the array). | `$tags->next_tag( 'img' );` | - * | Find next tag containing the `fullwidth` CSS class. | `$tags->next_tag( array( 'class_name' => 'fullwidth' ) );` | - * | Find next image tag containing the `fullwidth` CSS class. | `$tags->next_tag( array( 'tag_name' => 'img', 'class_name' => 'fullwidth' ) );` | - * - * If a tag was found meeting your criteria then `next_tag()` - * will return `true` and you can proceed to modify it. If it - * returns `false`, however, it failed to find the tag and - * moved the cursor to the end of the file. - * - * Once the cursor reaches the end of the file the processor - * is done and if you want to reach an earlier tag you will - * need to recreate the processor and start over, as it's - * unable to back up or move in reverse. - * - * See the section on bookmarks for an exception to this - * no-backing-up rule. - * - * #### Custom queries - * - * Sometimes it's necessary to further inspect an HTML tag than - * the query syntax here permits. In these cases one may further - * inspect the search results using the read-only functions - * provided by the processor or external state or variables. - * - * Example: - * - * // Paint up to the first five DIV or SPAN tags marked with the "jazzy" style. - * $remaining_count = 5; - * while ( $remaining_count > 0 && $tags->next_tag() ) { - * if ( - * ( 'DIV' === $tags->get_tag() || 'SPAN' === $tags->get_tag() ) && - * 'jazzy' === $tags->get_attribute( 'data-style' ) - * ) { - * $tags->add_class( 'theme-style-everest-jazz' ); - * $remaining_count--; - * } - * } - * - * `get_attribute()` will return `null` if the attribute wasn't present - * on the tag when it was called. It may return `""` (the empty string) - * in cases where the attribute was present but its value was empty. - * For boolean attributes, those whose name is present but no value is - * given, it will return `true` (the only way to set `false` for an - * attribute is to remove it). - * - * ### Modifying HTML attributes for a found tag - * - * Once you've found the start of an opening tag you can modify - * any number of the attributes on that tag. You can set a new - * value for an attribute, remove the entire attribute, or do - * nothing and move on to the next opening tag. - * - * Example: - * - * if ( $tags->next_tag( array( 'class_name' => 'wp-group-block' ) ) ) { - * $tags->set_attribute( 'title', 'This groups the contained content.' ); - * $tags->remove_attribute( 'data-test-id' ); - * } - * - * If `set_attribute()` is called for an existing attribute it will - * overwrite the existing value. Similarly, calling `remove_attribute()` - * for a non-existing attribute has no effect on the document. Both - * of these methods are safe to call without knowing if a given attribute - * exists beforehand. - * - * ### Modifying CSS classes for a found tag - * - * The tag processor treats the `class` attribute as a special case. - * Because it's a common operation to add or remove CSS classes, this - * interface adds helper methods to make that easier. - * - * As with attribute values, adding or removing CSS classes is a safe - * operation that doesn't require checking if the attribute or class - * exists before making changes. If removing the only class then the - * entire `class` attribute will be removed. - * - * Example: - * - * // from `<span>Yippee!</span>` - * // to `<span class="is-active">Yippee!</span>` - * $tags->add_class( 'is-active' ); - * - * // from `<span class="excited">Yippee!</span>` - * // to `<span class="excited is-active">Yippee!</span>` - * $tags->add_class( 'is-active' ); - * - * // from `<span class="is-active heavy-accent">Yippee!</span>` - * // to `<span class="is-active heavy-accent">Yippee!</span>` - * $tags->add_class( 'is-active' ); - * - * // from `<input type="text" class="is-active rugby not-disabled" length="24">` - * // to `<input type="text" class="is-active not-disabled" length="24"> - * $tags->remove_class( 'rugby' ); - * - * // from `<input type="text" class="rugby" length="24">` - * // to `<input type="text" length="24"> - * $tags->remove_class( 'rugby' ); - * - * // from `<input type="text" length="24">` - * // to `<input type="text" length="24"> - * $tags->remove_class( 'rugby' ); - * - * When class changes are enqueued but a direct change to `class` is made via - * `set_attribute` then the changes to `set_attribute` (or `remove_attribute`) - * will take precedence over those made through `add_class` and `remove_class`. - * - * ### Bookmarks - * - * While scanning through the input HTMl document it's possible to set - * a named bookmark when a particular tag is found. Later on, after - * continuing to scan other tags, it's possible to `seek` to one of - * the set bookmarks and then proceed again from that point forward. - * - * Because bookmarks create processing overhead one should avoid - * creating too many of them. As a rule, create only bookmarks - * of known string literal names; avoid creating "mark_{$index}" - * and so on. It's fine from a performance standpoint to create a - * bookmark and update it frequently, such as within a loop. - * - * $total_todos = 0; - * while ( $p->next_tag( array( 'tag_name' => 'UL', 'class_name' => 'todo' ) ) ) { - * $p->set_bookmark( 'list-start' ); - * while ( $p->next_tag( array( 'tag_closers' => 'visit' ) ) ) { - * if ( 'UL' === $p->get_tag() && $p->is_tag_closer() ) { - * $p->set_bookmark( 'list-end' ); - * $p->seek( 'list-start' ); - * $p->set_attribute( 'data-contained-todos', (string) $total_todos ); - * $total_todos = 0; - * $p->seek( 'list-end' ); - * break; - * } - * - * if ( 'LI' === $p->get_tag() && ! $p->is_tag_closer() ) { - * $total_todos++; - * } - * } - * } - * - * ## Design and limitations - * - * The Tag Processor is designed to linearly scan HTML documents and tokenize - * HTML tags and their attributes. It's designed to do this as efficiently as - * possible without compromising parsing integrity. Therefore it will be - * slower than some methods of modifying HTML, such as those incorporating - * over-simplified PCRE patterns, but will not introduce the defects and - * failures that those methods bring in, which lead to broken page renders - * and often to security vulnerabilities. On the other hand, it will be faster - * than full-blown HTML parsers such as DOMDocument and use considerably - * less memory. It requires a negligible memory overhead, enough to consider - * it a zero-overhead system. - * - * The performance characteristics are maintained by avoiding tree construction - * and semantic cleanups which are specified in HTML5. Because of this, for - * example, it's not possible for the Tag Processor to associate any given - * opening tag with its corresponding closing tag, or to return the inner markup - * inside an element. Systems may be built on top of the Tag Processor to do - * this, but the Tag Processor is and should be constrained so it can remain an - * efficient, low-level, and reliable HTML scanner. - * - * The Tag Processor's design incorporates a "garbage-in-garbage-out" philosophy. - * HTML5 specifies that certain invalid content be transformed into different forms - * for display, such as removing null bytes from an input document and replacing - * invalid characters with the Unicode replacement character `U+FFFD` (visually "�"). - * Where errors or transformations exist within the HTML5 specification, the Tag Processor - * leaves those invalid inputs untouched, passing them through to the final browser - * to handle. While this implies that certain operations will be non-spec-compliant, - * such as reading the value of an attribute with invalid content, it also preserves a - * simplicity and efficiency for handling those error cases. - * - * Most operations within the Tag Processor are designed to minimize the difference - * between an input and output document for any given change. For example, the - * `add_class` and `remove_class` methods preserve whitespace and the class ordering - * within the `class` attribute; and when encountering tags with duplicated attributes, - * the Tag Processor will leave those invalid duplicate attributes where they are but - * update the proper attribute which the browser will read for parsing its value. An - * exception to this rule is that all attribute updates store their values as - * double-quoted strings, meaning that attributes on input with single-quoted or - * unquoted values will appear in the output with double-quotes. - * - * @since 6.2.0 - * @since 6.2.1 Fix: Support for various invalid comments; attribute updates are case-insensitive. - * @since 6.3.2 Fix: Skip HTML-like content inside rawtext elements such as STYLE. - */ -class Gutenberg_HTML_Tag_Processor_6_4 { - /** - * The maximum number of bookmarks allowed to exist at - * any given time. - * - * @since 6.2.0 - * @var int - * - * @see WP_HTML_Tag_Processor::set_bookmark() - */ - const MAX_BOOKMARKS = 10; - - /** - * Maximum number of times seek() can be called. - * Prevents accidental infinite loops. - * - * @since 6.2.0 - * @var int - * - * @see WP_HTML_Tag_Processor::seek() - */ - const MAX_SEEK_OPS = 1000; - - /** - * The HTML document to parse. - * - * @since 6.2.0 - * @var string - */ - protected $html; - - /** - * The last query passed to next_tag(). - * - * @since 6.2.0 - * @var array|null - */ - private $last_query; - - /** - * The tag name this processor currently scans for. - * - * @since 6.2.0 - * @var string|null - */ - private $sought_tag_name; - - /** - * The CSS class name this processor currently scans for. - * - * @since 6.2.0 - * @var string|null - */ - private $sought_class_name; - - /** - * The match offset this processor currently scans for. - * - * @since 6.2.0 - * @var int|null - */ - private $sought_match_offset; - - /** - * Whether to visit tag closers, e.g. </div>, when walking an input document. - * - * @since 6.2.0 - * @var bool - */ - private $stop_on_tag_closers; - - /** - * How many bytes from the original HTML document have been read and parsed. - * - * This value points to the latest byte offset in the input document which - * has been already parsed. It is the internal cursor for the Tag Processor - * and updates while scanning through the HTML tokens. - * - * @since 6.2.0 - * @var int - */ - private $bytes_already_parsed = 0; - - /** - * Byte offset in input document where current tag name starts. - * - * Example: - * - * <div id="test">... - * 01234 - * - tag name starts at 1 - * - * @since 6.2.0 - * @var int|null - */ - private $tag_name_starts_at; - - /** - * Byte length of current tag name. - * - * Example: - * - * <div id="test">... - * 01234 - * --- tag name length is 3 - * - * @since 6.2.0 - * @var int|null - */ - private $tag_name_length; - - /** - * Byte offset in input document where current tag token ends. - * - * Example: - * - * <div id="test">... - * 0 1 | - * 01234567890123456 - * --- tag name ends at 14 - * - * @since 6.2.0 - * @var int|null - */ - private $tag_ends_at; - - /** - * Whether the current tag is an opening tag, e.g. <div>, or a closing tag, e.g. </div>. - * - * @var bool - */ - private $is_closing_tag; - - /** - * Lazily-built index of attributes found within an HTML tag, keyed by the attribute name. - * - * Example: - * - * // Supposing the parser is working through this content - * // and stops after recognizing the `id` attribute. - * // <div id="test-4" class=outline title="data:text/plain;base64=asdk3nk1j3fo8"> - * // ^ parsing will continue from this point. - * $this->attributes = array( - * 'id' => new WP_HTML_Attribute_Match( 'id', null, 6, 17 ) - * ); - * - * // When picking up parsing again, or when asking to find the - * // `class` attribute we will continue and add to this array. - * $this->attributes = array( - * 'id' => new WP_HTML_Attribute_Match( 'id', null, 6, 17 ), - * 'class' => new WP_HTML_Attribute_Match( 'class', 'outline', 18, 32 ) - * ); - * - * // Note that only the `class` attribute value is stored in the index. - * // That's because it is the only value used by this class at the moment. - * - * @since 6.2.0 - * @var WP_HTML_Attribute_Token[] - */ - private $attributes = array(); - - /** - * Tracks spans of duplicate attributes on a given tag, used for removing - * all copies of an attribute when calling `remove_attribute()`. - * - * @since 6.3.2 - * - * @var (WP_HTML_Span[])[]|null - */ - private $duplicate_attributes = null; - - /** - * Which class names to add or remove from a tag. - * - * These are tracked separately from attribute updates because they are - * semantically distinct, whereas this interface exists for the common - * case of adding and removing class names while other attributes are - * generally modified as with DOM `setAttribute` calls. - * - * When modifying an HTML document these will eventually be collapsed - * into a single `set_attribute( 'class', $changes )` call. - * - * Example: - * - * // Add the `wp-block-group` class, remove the `wp-group` class. - * $classname_updates = array( - * // Indexed by a comparable class name. - * 'wp-block-group' => WP_HTML_Tag_Processor::ADD_CLASS, - * 'wp-group' => WP_HTML_Tag_Processor::REMOVE_CLASS - * ); - * - * @since 6.2.0 - * @var bool[] - */ - private $classname_updates = array(); - - /** - * Tracks a semantic location in the original HTML which - * shifts with updates as they are applied to the document. - * - * @since 6.2.0 - * @var WP_HTML_Span[] - */ - protected $bookmarks = array(); - - const ADD_CLASS = true; - const REMOVE_CLASS = false; - const SKIP_CLASS = null; - - /** - * Lexical replacements to apply to input HTML document. - * - * "Lexical" in this class refers to the part of this class which - * operates on pure text _as text_ and not as HTML. There's a line - * between the public interface, with HTML-semantic methods like - * `set_attribute` and `add_class`, and an internal state that tracks - * text offsets in the input document. - * - * When higher-level HTML methods are called, those have to transform their - * operations (such as setting an attribute's value) into text diffing - * operations (such as replacing the sub-string from indices A to B with - * some given new string). These text-diffing operations are the lexical - * updates. - * - * As new higher-level methods are added they need to collapse their - * operations into these lower-level lexical updates since that's the - * Tag Processor's internal language of change. Any code which creates - * these lexical updates must ensure that they do not cross HTML syntax - * boundaries, however, so these should never be exposed outside of this - * class or any classes which intentionally expand its functionality. - * - * These are enqueued while editing the document instead of being immediately - * applied to avoid processing overhead, string allocations, and string - * copies when applying many updates to a single document. - * - * Example: - * - * // Replace an attribute stored with a new value, indices - * // sourced from the lazily-parsed HTML recognizer. - * $start = $attributes['src']->start; - * $end = $attributes['src']->end; - * $modifications[] = new WP_HTML_Text_Replacement( $start, $end, $new_value ); - * - * // Correspondingly, something like this will appear in this array. - * $lexical_updates = array( - * WP_HTML_Text_Replacement( 14, 28, 'https://my-site.my-domain/wp-content/uploads/2014/08/kittens.jpg' ) - * ); - * - * @since 6.2.0 - * @var WP_HTML_Text_Replacement[] - */ - protected $lexical_updates = array(); - - /** - * Tracks and limits `seek()` calls to prevent accidental infinite loops. - * - * @since 6.2.0 - * @var int - * - * @see WP_HTML_Tag_Processor::seek() - */ - protected $seek_count = 0; - - /** - * Constructor. - * - * @since 6.2.0 - * - * @param string $html HTML to process. - */ - public function __construct( $html ) { - $this->html = $html; - } - - /** - * Finds the next tag matching the $query. - * - * @since 6.2.0 - * - * @param array|string|null $query { - * Optional. Which tag name to find, having which class, etc. Default is to find any tag. - * - * @type string|null $tag_name Which tag to find, or `null` for "any tag." - * @type int|null $match_offset Find the Nth tag matching all search criteria. - * 1 for "first" tag, 3 for "third," etc. - * Defaults to first tag. - * @type string|null $class_name Tag must contain this whole class name to match. - * @type string|null $tag_closers "visit" or "skip": whether to stop on tag closers, e.g. </div>. - * } - * @return bool Whether a tag was matched. - */ - public function next_tag( $query = null ) { - $this->parse_query( $query ); - $already_found = 0; - - do { - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - return false; - } - - // Find the next tag if it exists. - if ( false === $this->parse_next_tag() ) { - $this->bytes_already_parsed = strlen( $this->html ); - - return false; - } - - // Parse all of its attributes. - while ( $this->parse_next_attribute() ) { - continue; - } - - // Ensure that the tag closes before the end of the document. - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - return false; - } - - $tag_ends_at = strpos( $this->html, '>', $this->bytes_already_parsed ); - if ( false === $tag_ends_at ) { - return false; - } - $this->tag_ends_at = $tag_ends_at; - $this->bytes_already_parsed = $tag_ends_at; - - // Finally, check if the parsed tag and its attributes match the search query. - if ( $this->matches() ) { - ++$already_found; - } - - /* - * For non-DATA sections which might contain text that looks like HTML tags but - * isn't, scan with the appropriate alternative mode. Looking at the first letter - * of the tag name as a pre-check avoids a string allocation when it's not needed. - */ - $t = $this->html[ $this->tag_name_starts_at ]; - if ( - ! $this->is_closing_tag && - ( - 'i' === $t || 'I' === $t || - 'n' === $t || 'N' === $t || - 's' === $t || 'S' === $t || - 't' === $t || 'T' === $t - ) ) { - $tag_name = $this->get_tag(); - - if ( 'SCRIPT' === $tag_name && ! $this->skip_script_data() ) { - $this->bytes_already_parsed = strlen( $this->html ); - return false; - } elseif ( - ( 'TEXTAREA' === $tag_name || 'TITLE' === $tag_name ) && - ! $this->skip_rcdata( $tag_name ) - ) { - $this->bytes_already_parsed = strlen( $this->html ); - return false; - } elseif ( - ( - 'IFRAME' === $tag_name || - 'NOEMBED' === $tag_name || - 'NOFRAMES' === $tag_name || - 'NOSCRIPT' === $tag_name || - 'STYLE' === $tag_name - ) && - ! $this->skip_rawtext( $tag_name ) - ) { - /* - * "XMP" should be here too but its rules are more complicated and require the - * complexity of the HTML Processor (it needs to close out any open P element, - * meaning it can't be skipped here or else the HTML Processor will lose its - * place). For now, it can be ignored as it's a rare HTML tag in practice and - * any normative HTML should be using PRE instead. - */ - $this->bytes_already_parsed = strlen( $this->html ); - return false; - } - } - } while ( $already_found < $this->sought_match_offset ); - - return true; - } - - - /** - * Generator for a foreach loop to step through each class name for the matched tag. - * - * This generator function is designed to be used inside a "foreach" loop. - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( "<div class='free <egg<\tlang-en'>" ); - * $p->next_tag(); - * foreach ( $p->class_list() as $class_name ) { - * echo "{$class_name} "; - * } - * // Outputs: "free <egg> lang-en " - * - * @since 6.4.0 - */ - public function class_list() { - /** @var string $class contains the string value of the class attribute, with character references decoded. */ - $class = $this->get_attribute( 'class' ); - - if ( ! is_string( $class ) ) { - return; - } - - $seen = array(); - - $at = 0; - while ( $at < strlen( $class ) ) { - // Skip past any initial boundary characters. - $at += strspn( $class, " \t\f\r\n", $at ); - if ( $at >= strlen( $class ) ) { - return; - } - - // Find the byte length until the next boundary. - $length = strcspn( $class, " \t\f\r\n", $at ); - if ( 0 === $length ) { - return; - } - - /* - * CSS class names are case-insensitive in the ASCII range. - * - * @see https://www.w3.org/TR/CSS2/syndata.html#x1 - */ - $name = strtolower( substr( $class, $at, $length ) ); - $at += $length; - - /* - * It's expected that the number of class names for a given tag is relatively small. - * Given this, it is probably faster overall to scan an array for a value rather - * than to use the class name as a key and check if it's a key of $seen. - */ - if ( in_array( $name, $seen, true ) ) { - continue; - } - - $seen[] = $name; - yield $name; - } - } - - - /** - * Returns if a matched tag contains the given ASCII case-insensitive class name. - * - * @since 6.4.0 - * - * @param string $wanted_class Look for this CSS class name, ASCII case-insensitive. - * @return bool|null Whether the matched tag contains the given class name, or null if not matched. - */ - public function has_class( $wanted_class ) { - if ( ! $this->tag_name_starts_at ) { - return null; - } - - $wanted_class = strtolower( $wanted_class ); - - foreach ( $this->class_list() as $class_name ) { - if ( $class_name === $wanted_class ) { - return true; - } - } - - return false; - } - - - /** - * Sets a bookmark in the HTML document. - * - * Bookmarks represent specific places or tokens in the HTML - * document, such as a tag opener or closer. When applying - * edits to a document, such as setting an attribute, the - * text offsets of that token may shift; the bookmark is - * kept updated with those shifts and remains stable unless - * the entire span of text in which the token sits is removed. - * - * Release bookmarks when they are no longer needed. - * - * Example: - * - * <main><h2>Surprising fact you may not know!</h2></main> - * ^ ^ - * \-|-- this `H2` opener bookmark tracks the token - * - * <main class="clickbait"><h2>Surprising fact you may no… - * ^ ^ - * \-|-- it shifts with edits - * - * Bookmarks provide the ability to seek to a previously-scanned - * place in the HTML document. This avoids the need to re-scan - * the entire document. - * - * Example: - * - * <ul><li>One</li><li>Two</li><li>Three</li></ul> - * ^^^^ - * want to note this last item - * - * $p = new WP_HTML_Tag_Processor( $html ); - * $in_list = false; - * while ( $p->next_tag( array( 'tag_closers' => $in_list ? 'visit' : 'skip' ) ) ) { - * if ( 'UL' === $p->get_tag() ) { - * if ( $p->is_tag_closer() ) { - * $in_list = false; - * $p->set_bookmark( 'resume' ); - * if ( $p->seek( 'last-li' ) ) { - * $p->add_class( 'last-li' ); - * } - * $p->seek( 'resume' ); - * $p->release_bookmark( 'last-li' ); - * $p->release_bookmark( 'resume' ); - * } else { - * $in_list = true; - * } - * } - * - * if ( 'LI' === $p->get_tag() ) { - * $p->set_bookmark( 'last-li' ); - * } - * } - * - * Bookmarks intentionally hide the internal string offsets - * to which they refer. They are maintained internally as - * updates are applied to the HTML document and therefore - * retain their "position" - the location to which they - * originally pointed. The inability to use bookmarks with - * functions like `substr` is therefore intentional to guard - * against accidentally breaking the HTML. - * - * Because bookmarks allocate memory and require processing - * for every applied update, they are limited and require - * a name. They should not be created with programmatically-made - * names, such as "li_{$index}" with some loop. As a general - * rule they should only be created with string-literal names - * like "start-of-section" or "last-paragraph". - * - * Bookmarks are a powerful tool to enable complicated behavior. - * Consider double-checking that you need this tool if you are - * reaching for it, as inappropriate use could lead to broken - * HTML structure or unwanted processing overhead. - * - * @since 6.2.0 - * - * @param string $name Identifies this particular bookmark. - * @return bool Whether the bookmark was successfully created. - */ - public function set_bookmark( $name ) { - if ( null === $this->tag_name_starts_at ) { - return false; - } - - if ( ! array_key_exists( $name, $this->bookmarks ) && count( $this->bookmarks ) >= static::MAX_BOOKMARKS ) { - _doing_it_wrong( - __METHOD__, - __( 'Too many bookmarks: cannot create any more.' ), - '6.2.0' - ); - return false; - } - - $this->bookmarks[ $name ] = new WP_HTML_Span( - $this->tag_name_starts_at - ( $this->is_closing_tag ? 2 : 1 ), - $this->tag_ends_at - ); - - return true; - } - - - /** - * Removes a bookmark that is no longer needed. - * - * Releasing a bookmark frees up the small - * performance overhead it requires. - * - * @param string $name Name of the bookmark to remove. - * @return bool Whether the bookmark already existed before removal. - */ - public function release_bookmark( $name ) { - if ( ! array_key_exists( $name, $this->bookmarks ) ) { - return false; - } - - unset( $this->bookmarks[ $name ] ); - - return true; - } - - /** - * Skips contents of generic rawtext elements. - * - * @since 6.3.2 - * - * @see https://html.spec.whatwg.org/#generic-raw-text-element-parsing-algorithm - * - * @param string $tag_name The uppercase tag name which will close the RAWTEXT region. - * @return bool Whether an end to the RAWTEXT region was found before the end of the document. - */ - private function skip_rawtext( $tag_name ) { - /* - * These two functions distinguish themselves on whether character references are - * decoded, and since functionality to read the inner markup isn't supported, it's - * not necessary to implement these two functions separately. - */ - return $this->skip_rcdata( $tag_name ); - } - - /** - * Skips contents of RCDATA elements, namely title and textarea tags. - * - * @since 6.2.0 - * - * @see https://html.spec.whatwg.org/multipage/parsing.html#rcdata-state - * - * @param string $tag_name The uppercase tag name which will close the RCDATA region. - * @return bool Whether an end to the RCDATA region was found before the end of the document. - */ - private function skip_rcdata( $tag_name ) { - $html = $this->html; - $doc_length = strlen( $html ); - $tag_length = strlen( $tag_name ); - - $at = $this->bytes_already_parsed; - - while ( false !== $at && $at < $doc_length ) { - $at = strpos( $this->html, '</', $at ); - - // If there is no possible tag closer then fail. - if ( false === $at || ( $at + $tag_length ) >= $doc_length ) { - $this->bytes_already_parsed = $doc_length; - return false; - } - - $closer_potentially_starts_at = $at; - $at += 2; - - /* - * Find a case-insensitive match to the tag name. - * - * Because tag names are limited to US-ASCII there is no - * need to perform any kind of Unicode normalization when - * comparing; any character which could be impacted by such - * normalization could not be part of a tag name. - */ - for ( $i = 0; $i < $tag_length; $i++ ) { - $tag_char = $tag_name[ $i ]; - $html_char = $html[ $at + $i ]; - - if ( $html_char !== $tag_char && strtoupper( $html_char ) !== $tag_char ) { - $at += $i; - continue 2; - } - } - - $at += $tag_length; - $this->bytes_already_parsed = $at; - - /* - * Ensure that the tag name terminates to avoid matching on - * substrings of a longer tag name. For example, the sequence - * "</textarearug" should not match for "</textarea" even - * though "textarea" is found within the text. - */ - $c = $html[ $at ]; - if ( ' ' !== $c && "\t" !== $c && "\r" !== $c && "\n" !== $c && '/' !== $c && '>' !== $c ) { - continue; - } - - while ( $this->parse_next_attribute() ) { - continue; - } - $at = $this->bytes_already_parsed; - if ( $at >= strlen( $this->html ) ) { - return false; - } - - if ( '>' === $html[ $at ] || '/' === $html[ $at ] ) { - $this->bytes_already_parsed = $closer_potentially_starts_at; - return true; - } - } - - return false; - } - - /** - * Skips contents of script tags. - * - * @since 6.2.0 - * - * @return bool Whether the script tag was closed before the end of the document. - */ - private function skip_script_data() { - $state = 'unescaped'; - $html = $this->html; - $doc_length = strlen( $html ); - $at = $this->bytes_already_parsed; - - while ( false !== $at && $at < $doc_length ) { - $at += strcspn( $html, '-<', $at ); - - /* - * For all script states a "-->" transitions - * back into the normal unescaped script mode, - * even if that's the current state. - */ - if ( - $at + 2 < $doc_length && - '-' === $html[ $at ] && - '-' === $html[ $at + 1 ] && - '>' === $html[ $at + 2 ] - ) { - $at += 3; - $state = 'unescaped'; - continue; - } - - // Everything of interest past here starts with "<". - if ( $at + 1 >= $doc_length || '<' !== $html[ $at++ ] ) { - continue; - } - - /* - * Unlike with "-->", the "<!--" only transitions - * into the escaped mode if not already there. - * - * Inside the escaped modes it will be ignored; and - * should never break out of the double-escaped - * mode and back into the escaped mode. - * - * While this requires a mode change, it does not - * impact the parsing otherwise, so continue - * parsing after updating the state. - */ - if ( - $at + 2 < $doc_length && - '!' === $html[ $at ] && - '-' === $html[ $at + 1 ] && - '-' === $html[ $at + 2 ] - ) { - $at += 3; - $state = 'unescaped' === $state ? 'escaped' : $state; - continue; - } - - if ( '/' === $html[ $at ] ) { - $closer_potentially_starts_at = $at - 1; - $is_closing = true; - ++$at; - } else { - $is_closing = false; - } - - /* - * At this point the only remaining state-changes occur with the - * <script> and </script> tags; unless one of these appears next, - * proceed scanning to the next potential token in the text. - */ - if ( ! ( - $at + 6 < $doc_length && - ( 's' === $html[ $at ] || 'S' === $html[ $at ] ) && - ( 'c' === $html[ $at + 1 ] || 'C' === $html[ $at + 1 ] ) && - ( 'r' === $html[ $at + 2 ] || 'R' === $html[ $at + 2 ] ) && - ( 'i' === $html[ $at + 3 ] || 'I' === $html[ $at + 3 ] ) && - ( 'p' === $html[ $at + 4 ] || 'P' === $html[ $at + 4 ] ) && - ( 't' === $html[ $at + 5 ] || 'T' === $html[ $at + 5 ] ) - ) ) { - ++$at; - continue; - } - - /* - * Ensure that the script tag terminates to avoid matching on - * substrings of a non-match. For example, the sequence - * "<script123" should not end a script region even though - * "<script" is found within the text. - */ - if ( $at + 6 >= $doc_length ) { - continue; - } - $at += 6; - $c = $html[ $at ]; - if ( ' ' !== $c && "\t" !== $c && "\r" !== $c && "\n" !== $c && '/' !== $c && '>' !== $c ) { - ++$at; - continue; - } - - if ( 'escaped' === $state && ! $is_closing ) { - $state = 'double-escaped'; - continue; - } - - if ( 'double-escaped' === $state && $is_closing ) { - $state = 'escaped'; - continue; - } - - if ( $is_closing ) { - $this->bytes_already_parsed = $closer_potentially_starts_at; - if ( $this->bytes_already_parsed >= $doc_length ) { - return false; - } - - while ( $this->parse_next_attribute() ) { - continue; - } - - if ( '>' === $html[ $this->bytes_already_parsed ] ) { - $this->bytes_already_parsed = $closer_potentially_starts_at; - return true; - } - } - - ++$at; - } - - return false; - } - - /** - * Parses the next tag. - * - * This will find and start parsing the next tag, including - * the opening `<`, the potential closer `/`, and the tag - * name. It does not parse the attributes or scan to the - * closing `>`; these are left for other methods. - * - * @since 6.2.0 - * @since 6.2.1 Support abruptly-closed comments, invalid-tag-closer-comments, and empty elements. - * - * @return bool Whether a tag was found before the end of the document. - */ - private function parse_next_tag() { - $this->after_tag(); - - $html = $this->html; - $doc_length = strlen( $html ); - $at = $this->bytes_already_parsed; - - while ( false !== $at && $at < $doc_length ) { - $at = strpos( $html, '<', $at ); - if ( false === $at ) { - return false; - } - - if ( '/' === $this->html[ $at + 1 ] ) { - $this->is_closing_tag = true; - ++$at; - } else { - $this->is_closing_tag = false; - } - - /* - * HTML tag names must start with [a-zA-Z] otherwise they are not tags. - * For example, "<3" is rendered as text, not a tag opener. If at least - * one letter follows the "<" then _it is_ a tag, but if the following - * character is anything else it _is not a tag_. - * - * It's not uncommon to find non-tags starting with `<` in an HTML - * document, so it's good for performance to make this pre-check before - * continuing to attempt to parse a tag name. - * - * Reference: - * * https://html.spec.whatwg.org/multipage/parsing.html#data-state - * * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state - */ - $tag_name_prefix_length = strspn( $html, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', $at + 1 ); - if ( $tag_name_prefix_length > 0 ) { - ++$at; - $this->tag_name_length = $tag_name_prefix_length + strcspn( $html, " \t\f\r\n/>", $at + $tag_name_prefix_length ); - $this->tag_name_starts_at = $at; - $this->bytes_already_parsed = $at + $this->tag_name_length; - return true; - } - - /* - * Abort if no tag is found before the end of - * the document. There is nothing left to parse. - */ - if ( $at + 1 >= strlen( $html ) ) { - return false; - } - - /* - * <! transitions to markup declaration open state - * https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state - */ - if ( '!' === $html[ $at + 1 ] ) { - /* - * <!-- transitions to a bogus comment state – skip to the nearest --> - * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state - */ - if ( - strlen( $html ) > $at + 3 && - '-' === $html[ $at + 2 ] && - '-' === $html[ $at + 3 ] - ) { - $closer_at = $at + 4; - // If it's not possible to close the comment then there is nothing more to scan. - if ( strlen( $html ) <= $closer_at ) { - return false; - } - - // Abruptly-closed empty comments are a sequence of dashes followed by `>`. - $span_of_dashes = strspn( $html, '-', $closer_at ); - if ( '>' === $html[ $closer_at + $span_of_dashes ] ) { - $at = $closer_at + $span_of_dashes + 1; - continue; - } - - /* - * Comments may be closed by either a --> or an invalid --!>. - * The first occurrence closes the comment. - * - * See https://html.spec.whatwg.org/#parse-error-incorrectly-closed-comment - */ - --$closer_at; // Pre-increment inside condition below reduces risk of accidental infinite looping. - while ( ++$closer_at < strlen( $html ) ) { - $closer_at = strpos( $html, '--', $closer_at ); - if ( false === $closer_at ) { - return false; - } - - if ( $closer_at + 2 < strlen( $html ) && '>' === $html[ $closer_at + 2 ] ) { - $at = $closer_at + 3; - continue 2; - } - - if ( $closer_at + 3 < strlen( $html ) && '!' === $html[ $closer_at + 2 ] && '>' === $html[ $closer_at + 3 ] ) { - $at = $closer_at + 4; - continue 2; - } - } - } - - /* - * <![CDATA[ transitions to CDATA section state – skip to the nearest ]]> - * The CDATA is case-sensitive. - * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state - */ - if ( - strlen( $html ) > $at + 8 && - '[' === $html[ $at + 2 ] && - 'C' === $html[ $at + 3 ] && - 'D' === $html[ $at + 4 ] && - 'A' === $html[ $at + 5 ] && - 'T' === $html[ $at + 6 ] && - 'A' === $html[ $at + 7 ] && - '[' === $html[ $at + 8 ] - ) { - $closer_at = strpos( $html, ']]>', $at + 9 ); - if ( false === $closer_at ) { - return false; - } - - $at = $closer_at + 3; - continue; - } - - /* - * <!DOCTYPE transitions to DOCTYPE state – skip to the nearest > - * These are ASCII-case-insensitive. - * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state - */ - if ( - strlen( $html ) > $at + 8 && - ( 'D' === $html[ $at + 2 ] || 'd' === $html[ $at + 2 ] ) && - ( 'O' === $html[ $at + 3 ] || 'o' === $html[ $at + 3 ] ) && - ( 'C' === $html[ $at + 4 ] || 'c' === $html[ $at + 4 ] ) && - ( 'T' === $html[ $at + 5 ] || 't' === $html[ $at + 5 ] ) && - ( 'Y' === $html[ $at + 6 ] || 'y' === $html[ $at + 6 ] ) && - ( 'P' === $html[ $at + 7 ] || 'p' === $html[ $at + 7 ] ) && - ( 'E' === $html[ $at + 8 ] || 'e' === $html[ $at + 8 ] ) - ) { - $closer_at = strpos( $html, '>', $at + 9 ); - if ( false === $closer_at ) { - return false; - } - - $at = $closer_at + 1; - continue; - } - - /* - * Anything else here is an incorrectly-opened comment and transitions - * to the bogus comment state - skip to the nearest >. - */ - $at = strpos( $html, '>', $at + 1 ); - continue; - } - - /* - * </> is a missing end tag name, which is ignored. - * - * See https://html.spec.whatwg.org/#parse-error-missing-end-tag-name - */ - if ( '>' === $html[ $at + 1 ] ) { - ++$at; - continue; - } - - /* - * <? transitions to a bogus comment state – skip to the nearest > - * See https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state - */ - if ( '?' === $html[ $at + 1 ] ) { - $closer_at = strpos( $html, '>', $at + 2 ); - if ( false === $closer_at ) { - return false; - } - - $at = $closer_at + 1; - continue; - } - - /* - * If a non-alpha starts the tag name in a tag closer it's a comment. - * Find the first `>`, which closes the comment. - * - * See https://html.spec.whatwg.org/#parse-error-invalid-first-character-of-tag-name - */ - if ( $this->is_closing_tag ) { - $closer_at = strpos( $html, '>', $at + 3 ); - if ( false === $closer_at ) { - return false; - } - - $at = $closer_at + 1; - continue; - } - - ++$at; - } - - return false; - } - - /** - * Parses the next attribute. - * - * @since 6.2.0 - * - * @return bool Whether an attribute was found before the end of the document. - */ - private function parse_next_attribute() { - // Skip whitespace and slashes. - $this->bytes_already_parsed += strspn( $this->html, " \t\f\r\n/", $this->bytes_already_parsed ); - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - return false; - } - - /* - * Treat the equal sign as a part of the attribute - * name if it is the first encountered byte. - * - * @see https://html.spec.whatwg.org/multipage/parsing.html#before-attribute-name-state - */ - $name_length = '=' === $this->html[ $this->bytes_already_parsed ] - ? 1 + strcspn( $this->html, "=/> \t\f\r\n", $this->bytes_already_parsed + 1 ) - : strcspn( $this->html, "=/> \t\f\r\n", $this->bytes_already_parsed ); - - // No attribute, just tag closer. - if ( 0 === $name_length || $this->bytes_already_parsed + $name_length >= strlen( $this->html ) ) { - return false; - } - - $attribute_start = $this->bytes_already_parsed; - $attribute_name = substr( $this->html, $attribute_start, $name_length ); - $this->bytes_already_parsed += $name_length; - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - return false; - } - - $this->skip_whitespace(); - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - return false; - } - - $has_value = '=' === $this->html[ $this->bytes_already_parsed ]; - if ( $has_value ) { - ++$this->bytes_already_parsed; - $this->skip_whitespace(); - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - return false; - } - - switch ( $this->html[ $this->bytes_already_parsed ] ) { - case "'": - case '"': - $quote = $this->html[ $this->bytes_already_parsed ]; - $value_start = $this->bytes_already_parsed + 1; - $value_length = strcspn( $this->html, $quote, $value_start ); - $attribute_end = $value_start + $value_length + 1; - $this->bytes_already_parsed = $attribute_end; - break; - - default: - $value_start = $this->bytes_already_parsed; - $value_length = strcspn( $this->html, "> \t\f\r\n", $value_start ); - $attribute_end = $value_start + $value_length; - $this->bytes_already_parsed = $attribute_end; - } - } else { - $value_start = $this->bytes_already_parsed; - $value_length = 0; - $attribute_end = $attribute_start + $name_length; - } - - if ( $attribute_end >= strlen( $this->html ) ) { - return false; - } - - if ( $this->is_closing_tag ) { - return true; - } - - /* - * > There must never be two or more attributes on - * > the same start tag whose names are an ASCII - * > case-insensitive match for each other. - * - HTML 5 spec - * - * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive - */ - $comparable_name = strtolower( $attribute_name ); - - // If an attribute is listed many times, only use the first declaration and ignore the rest. - if ( ! array_key_exists( $comparable_name, $this->attributes ) ) { - $this->attributes[ $comparable_name ] = new WP_HTML_Attribute_Token( - $attribute_name, - $value_start, - $value_length, - $attribute_start, - $attribute_end, - ! $has_value - ); - - return true; - } - - /* - * Track the duplicate attributes so if we remove it, all disappear together. - * - * While `$this->duplicated_attributes` could always be stored as an `array()`, - * which would simplify the logic here, storing a `null` and only allocating - * an array when encountering duplicates avoids needless allocations in the - * normative case of parsing tags with no duplicate attributes. - */ - $duplicate_span = new WP_HTML_Span( $attribute_start, $attribute_end ); - if ( null === $this->duplicate_attributes ) { - $this->duplicate_attributes = array( $comparable_name => array( $duplicate_span ) ); - } elseif ( ! array_key_exists( $comparable_name, $this->duplicate_attributes ) ) { - $this->duplicate_attributes[ $comparable_name ] = array( $duplicate_span ); - } else { - $this->duplicate_attributes[ $comparable_name ][] = $duplicate_span; - } - - return true; - } - - /** - * Move the internal cursor past any immediate successive whitespace. - * - * @since 6.2.0 - */ - private function skip_whitespace() { - $this->bytes_already_parsed += strspn( $this->html, " \t\f\r\n", $this->bytes_already_parsed ); - } - - /** - * Applies attribute updates and cleans up once a tag is fully parsed. - * - * @since 6.2.0 - */ - private function after_tag() { - $this->get_updated_html(); - $this->tag_name_starts_at = null; - $this->tag_name_length = null; - $this->tag_ends_at = null; - $this->is_closing_tag = null; - $this->attributes = array(); - $this->duplicate_attributes = null; - } - - /** - * Converts class name updates into tag attributes updates - * (they are accumulated in different data formats for performance). - * - * @since 6.2.0 - * - * @see WP_HTML_Tag_Processor::$lexical_updates - * @see WP_HTML_Tag_Processor::$classname_updates - */ - private function class_name_updates_to_attributes_updates() { - if ( count( $this->classname_updates ) === 0 ) { - return; - } - - $existing_class = $this->get_enqueued_attribute_value( 'class' ); - if ( null === $existing_class || true === $existing_class ) { - $existing_class = ''; - } - - if ( false === $existing_class && isset( $this->attributes['class'] ) ) { - $existing_class = substr( - $this->html, - $this->attributes['class']->value_starts_at, - $this->attributes['class']->value_length - ); - } - - if ( false === $existing_class ) { - $existing_class = ''; - } - - /** - * Updated "class" attribute value. - * - * This is incrementally built while scanning through the existing class - * attribute, skipping removed classes on the way, and then appending - * added classes at the end. Only when finished processing will the - * value contain the final new value. - - * @var string $class - */ - $class = ''; - - /** - * Tracks the cursor position in the existing - * class attribute value while parsing. - * - * @var int $at - */ - $at = 0; - - /** - * Indicates if there's any need to modify the existing class attribute. - * - * If a call to `add_class()` and `remove_class()` wouldn't impact - * the `class` attribute value then there's no need to rebuild it. - * For example, when adding a class that's already present or - * removing one that isn't. - * - * This flag enables a performance optimization when none of the enqueued - * class updates would impact the `class` attribute; namely, that the - * processor can continue without modifying the input document, as if - * none of the `add_class()` or `remove_class()` calls had been made. - * - * This flag is set upon the first change that requires a string update. - * - * @var bool $modified - */ - $modified = false; - - // Remove unwanted classes by only copying the new ones. - $existing_class_length = strlen( $existing_class ); - while ( $at < $existing_class_length ) { - // Skip to the first non-whitespace character. - $ws_at = $at; - $ws_length = strspn( $existing_class, " \t\f\r\n", $ws_at ); - $at += $ws_length; - - // Capture the class name – it's everything until the next whitespace. - $name_length = strcspn( $existing_class, " \t\f\r\n", $at ); - if ( 0 === $name_length ) { - // If no more class names are found then that's the end. - break; - } - - $name = substr( $existing_class, $at, $name_length ); - $at += $name_length; - - // If this class is marked for removal, start processing the next one. - $remove_class = ( - isset( $this->classname_updates[ $name ] ) && - self::REMOVE_CLASS === $this->classname_updates[ $name ] - ); - - // If a class has already been seen then skip it; it should not be added twice. - if ( ! $remove_class ) { - $this->classname_updates[ $name ] = self::SKIP_CLASS; - } - - if ( $remove_class ) { - $modified = true; - continue; - } - - /* - * Otherwise, append it to the new "class" attribute value. - * - * There are options for handling whitespace between tags. - * Preserving the existing whitespace produces fewer changes - * to the HTML content and should clarify the before/after - * content when debugging the modified output. - * - * This approach contrasts normalizing the inter-class - * whitespace to a single space, which might appear cleaner - * in the output HTML but produce a noisier change. - */ - $class .= substr( $existing_class, $ws_at, $ws_length ); - $class .= $name; - } - - // Add new classes by appending those which haven't already been seen. - foreach ( $this->classname_updates as $name => $operation ) { - if ( self::ADD_CLASS === $operation ) { - $modified = true; - - $class .= strlen( $class ) > 0 ? ' ' : ''; - $class .= $name; - } - } - - $this->classname_updates = array(); - if ( ! $modified ) { - return; - } - - if ( strlen( $class ) > 0 ) { - $this->set_attribute( 'class', $class ); - } else { - $this->remove_attribute( 'class' ); - } - } - - /** - * Applies attribute updates to HTML document. - * - * @since 6.2.0 - * @since 6.2.1 Accumulates shift for internal cursor and passed pointer. - * @since 6.3.0 Invalidate any bookmarks whose targets are overwritten. - * - * @param int $shift_this_point Accumulate and return shift for this position. - * @return int How many bytes the given pointer moved in response to the updates. - */ - private function apply_attributes_updates( $shift_this_point = 0 ) { - if ( ! count( $this->lexical_updates ) ) { - return 0; - } - - $accumulated_shift_for_given_point = 0; - - /* - * Attribute updates can be enqueued in any order but updates - * to the document must occur in lexical order; that is, each - * replacement must be made before all others which follow it - * at later string indices in the input document. - * - * Sorting avoid making out-of-order replacements which - * can lead to mangled output, partially-duplicated - * attributes, and overwritten attributes. - */ - usort( $this->lexical_updates, array( self::class, 'sort_start_ascending' ) ); - - $bytes_already_copied = 0; - $output_buffer = ''; - foreach ( $this->lexical_updates as $diff ) { - $shift = strlen( $diff->text ) - ( $diff->end - $diff->start ); - - // Adjust the cursor position by however much an update affects it. - if ( $diff->start <= $this->bytes_already_parsed ) { - $this->bytes_already_parsed += $shift; - } - - // Accumulate shift of the given pointer within this function call. - if ( $diff->start <= $shift_this_point ) { - $accumulated_shift_for_given_point += $shift; - } - - $output_buffer .= substr( $this->html, $bytes_already_copied, $diff->start - $bytes_already_copied ); - $output_buffer .= $diff->text; - $bytes_already_copied = $diff->end; - } - - $this->html = $output_buffer . substr( $this->html, $bytes_already_copied ); - - /* - * Adjust bookmark locations to account for how the text - * replacements adjust offsets in the input document. - */ - foreach ( $this->bookmarks as $bookmark_name => $bookmark ) { - /* - * Each lexical update which appears before the bookmark's endpoints - * might shift the offsets for those endpoints. Loop through each change - * and accumulate the total shift for each bookmark, then apply that - * shift after tallying the full delta. - */ - $head_delta = 0; - $tail_delta = 0; - - foreach ( $this->lexical_updates as $diff ) { - if ( $bookmark->start < $diff->start && $bookmark->end < $diff->start ) { - break; - } - - if ( $bookmark->start >= $diff->start && $bookmark->end < $diff->end ) { - $this->release_bookmark( $bookmark_name ); - continue 2; - } - - $delta = strlen( $diff->text ) - ( $diff->end - $diff->start ); - - if ( $bookmark->start >= $diff->start ) { - $head_delta += $delta; - } - - if ( $bookmark->end >= $diff->end ) { - $tail_delta += $delta; - } - } - - $bookmark->start += $head_delta; - $bookmark->end += $tail_delta; - } - - $this->lexical_updates = array(); - - return $accumulated_shift_for_given_point; - } - - /** - * Checks whether a bookmark with the given name exists. - * - * @since 6.3.0 - * - * @param string $bookmark_name Name to identify a bookmark that potentially exists. - * @return bool Whether that bookmark exists. - */ - public function has_bookmark( $bookmark_name ) { - return array_key_exists( $bookmark_name, $this->bookmarks ); - } - - /** - * Move the internal cursor in the Tag Processor to a given bookmark's location. - * - * In order to prevent accidental infinite loops, there's a - * maximum limit on the number of times seek() can be called. - * - * @since 6.2.0 - * - * @param string $bookmark_name Jump to the place in the document identified by this bookmark name. - * @return bool Whether the internal cursor was successfully moved to the bookmark's location. - */ - public function seek( $bookmark_name ) { - if ( ! array_key_exists( $bookmark_name, $this->bookmarks ) ) { - _doing_it_wrong( - __METHOD__, - __( 'Unknown bookmark name.' ), - '6.2.0' - ); - return false; - } - - if ( ++$this->seek_count > static::MAX_SEEK_OPS ) { - _doing_it_wrong( - __METHOD__, - __( 'Too many calls to seek() - this can lead to performance issues.' ), - '6.2.0' - ); - return false; - } - - // Flush out any pending updates to the document. - $this->get_updated_html(); - - // Point this tag processor before the sought tag opener and consume it. - $this->bytes_already_parsed = $this->bookmarks[ $bookmark_name ]->start; - return $this->next_tag( array( 'tag_closers' => 'visit' ) ); - } - - /** - * Compare two WP_HTML_Text_Replacement objects. - * - * @since 6.2.0 - * - * @param WP_HTML_Text_Replacement $a First attribute update. - * @param WP_HTML_Text_Replacement $b Second attribute update. - * @return int Comparison value for string order. - */ - private static function sort_start_ascending( $a, $b ) { - $by_start = $a->start - $b->start; - if ( 0 !== $by_start ) { - return $by_start; - } - - $by_text = isset( $a->text, $b->text ) ? strcmp( $a->text, $b->text ) : 0; - if ( 0 !== $by_text ) { - return $by_text; - } - - /* - * This code should be unreachable, because it implies the two replacements - * start at the same location and contain the same text. - */ - return $a->end - $b->end; - } - - /** - * Return the enqueued value for a given attribute, if one exists. - * - * Enqueued updates can take different data types: - * - If an update is enqueued and is boolean, the return will be `true` - * - If an update is otherwise enqueued, the return will be the string value of that update. - * - If an attribute is enqueued to be removed, the return will be `null` to indicate that. - * - If no updates are enqueued, the return will be `false` to differentiate from "removed." - * - * @since 6.2.0 - * - * @param string $comparable_name The attribute name in its comparable form. - * @return string|boolean|null Value of enqueued update if present, otherwise false. - */ - private function get_enqueued_attribute_value( $comparable_name ) { - if ( ! isset( $this->lexical_updates[ $comparable_name ] ) ) { - return false; - } - - $enqueued_text = $this->lexical_updates[ $comparable_name ]->text; - - // Removed attributes erase the entire span. - if ( '' === $enqueued_text ) { - return null; - } - - /* - * Boolean attribute updates are just the attribute name without a corresponding value. - * - * This value might differ from the given comparable name in that there could be leading - * or trailing whitespace, and that the casing follows the name given in `set_attribute`. - * - * Example: - * - * $p->set_attribute( 'data-TEST-id', 'update' ); - * 'update' === $p->get_enqueued_attribute_value( 'data-test-id' ); - * - * Detect this difference based on the absence of the `=`, which _must_ exist in any - * attribute containing a value, e.g. `<input type="text" enabled />`. - * ¹ ² - * 1. Attribute with a string value. - * 2. Boolean attribute whose value is `true`. - */ - $equals_at = strpos( $enqueued_text, '=' ); - if ( false === $equals_at ) { - return true; - } - - /* - * Finally, a normal update's value will appear after the `=` and - * be double-quoted, as performed incidentally by `set_attribute`. - * - * e.g. `type="text"` - * ¹² ³ - * 1. Equals is here. - * 2. Double-quoting starts one after the equals sign. - * 3. Double-quoting ends at the last character in the update. - */ - $enqueued_value = substr( $enqueued_text, $equals_at + 2, -1 ); - return html_entity_decode( $enqueued_value ); - } - - /** - * Returns the value of a requested attribute from a matched tag opener if that attribute exists. - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( '<div enabled class="test" data-test-id="14">Test</div>' ); - * $p->next_tag( array( 'class_name' => 'test' ) ) === true; - * $p->get_attribute( 'data-test-id' ) === '14'; - * $p->get_attribute( 'enabled' ) === true; - * $p->get_attribute( 'aria-label' ) === null; - * - * $p->next_tag() === false; - * $p->get_attribute( 'class' ) === null; - * - * @since 6.2.0 - * - * @param string $name Name of attribute whose value is requested. - * @return string|true|null Value of attribute or `null` if not available. Boolean attributes return `true`. - */ - public function get_attribute( $name ) { - if ( null === $this->tag_name_starts_at ) { - return null; - } - - $comparable = strtolower( $name ); - - /* - * For every attribute other than `class` it's possible to perform a quick check if - * there's an enqueued lexical update whose value takes priority over what's found in - * the input document. - * - * The `class` attribute is special though because of the exposed helpers `add_class` - * and `remove_class`. These form a builder for the `class` attribute, so an additional - * check for enqueued class changes is required in addition to the check for any enqueued - * attribute values. If any exist, those enqueued class changes must first be flushed out - * into an attribute value update. - */ - if ( 'class' === $name ) { - $this->class_name_updates_to_attributes_updates(); - } - - // Return any enqueued attribute value updates if they exist. - $enqueued_value = $this->get_enqueued_attribute_value( $comparable ); - if ( false !== $enqueued_value ) { - return $enqueued_value; - } - - if ( ! isset( $this->attributes[ $comparable ] ) ) { - return null; - } - - $attribute = $this->attributes[ $comparable ]; - - /* - * This flag distinguishes an attribute with no value - * from an attribute with an empty string value. For - * unquoted attributes this could look very similar. - * It refers to whether an `=` follows the name. - * - * e.g. <div boolean-attribute empty-attribute=></div> - * ¹ ² - * 1. Attribute `boolean-attribute` is `true`. - * 2. Attribute `empty-attribute` is `""`. - */ - if ( true === $attribute->is_true ) { - return true; - } - - $raw_value = substr( $this->html, $attribute->value_starts_at, $attribute->value_length ); - - return html_entity_decode( $raw_value ); - } - - /** - * Gets lowercase names of all attributes matching a given prefix in the current tag. - * - * Note that matching is case-insensitive. This is in accordance with the spec: - * - * > There must never be two or more attributes on - * > the same start tag whose names are an ASCII - * > case-insensitive match for each other. - * - HTML 5 spec - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( '<div data-ENABLED class="test" DATA-test-id="14">Test</div>' ); - * $p->next_tag( array( 'class_name' => 'test' ) ) === true; - * $p->get_attribute_names_with_prefix( 'data-' ) === array( 'data-enabled', 'data-test-id' ); - * - * $p->next_tag() === false; - * $p->get_attribute_names_with_prefix( 'data-' ) === null; - * - * @since 6.2.0 - * - * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive - * - * @param string $prefix Prefix of requested attribute names. - * @return array|null List of attribute names, or `null` when no tag opener is matched. - */ - public function get_attribute_names_with_prefix( $prefix ) { - if ( $this->is_closing_tag || null === $this->tag_name_starts_at ) { - return null; - } - - $comparable = strtolower( $prefix ); - - $matches = array(); - foreach ( array_keys( $this->attributes ) as $attr_name ) { - if ( str_starts_with( $attr_name, $comparable ) ) { - $matches[] = $attr_name; - } - } - return $matches; - } - - /** - * Returns the uppercase name of the matched tag. - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( '<div class="test">Test</div>' ); - * $p->next_tag() === true; - * $p->get_tag() === 'DIV'; - * - * $p->next_tag() === false; - * $p->get_tag() === null; - * - * @since 6.2.0 - * - * @return string|null Name of currently matched tag in input HTML, or `null` if none found. - */ - public function get_tag() { - if ( null === $this->tag_name_starts_at ) { - return null; - } - - $tag_name = substr( $this->html, $this->tag_name_starts_at, $this->tag_name_length ); - - return strtoupper( $tag_name ); - } - - /** - * Indicates if the currently matched tag contains the self-closing flag. - * - * No HTML elements ought to have the self-closing flag and for those, the self-closing - * flag will be ignored. For void elements this is benign because they "self close" - * automatically. For non-void HTML elements though problems will appear if someone - * intends to use a self-closing element in place of that element with an empty body. - * For HTML foreign elements and custom elements the self-closing flag determines if - * they self-close or not. - * - * This function does not determine if a tag is self-closing, - * but only if the self-closing flag is present in the syntax. - * - * @since 6.3.0 - * - * @return bool Whether the currently matched tag contains the self-closing flag. - */ - public function has_self_closing_flag() { - if ( ! $this->tag_name_starts_at ) { - return false; - } - - return '/' === $this->html[ $this->tag_ends_at - 1 ]; - } - - /** - * Indicates if the current tag token is a tag closer. - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( '<div></div>' ); - * $p->next_tag( array( 'tag_name' => 'div', 'tag_closers' => 'visit' ) ); - * $p->is_tag_closer() === false; - * - * $p->next_tag( array( 'tag_name' => 'div', 'tag_closers' => 'visit' ) ); - * $p->is_tag_closer() === true; - * - * @since 6.2.0 - * - * @return bool Whether the current tag is a tag closer. - */ - public function is_tag_closer() { - return $this->is_closing_tag; - } - - /** - * Updates or creates a new attribute on the currently matched tag with the passed value. - * - * For boolean attributes special handling is provided: - * - When `true` is passed as the value, then only the attribute name is added to the tag. - * - When `false` is passed, the attribute gets removed if it existed before. - * - * For string attributes, the value is escaped using the `esc_attr` function. - * - * @since 6.2.0 - * @since 6.2.1 Fix: Only create a single update for multiple calls with case-variant attribute names. - * - * @param string $name The attribute name to target. - * @param string|bool $value The new attribute value. - * @return bool Whether an attribute value was set. - */ - public function set_attribute( $name, $value ) { - if ( $this->is_closing_tag || null === $this->tag_name_starts_at ) { - return false; - } - - /* - * WordPress rejects more characters than are strictly forbidden - * in HTML5. This is to prevent additional security risks deeper - * in the WordPress and plugin stack. Specifically the - * less-than (<) greater-than (>) and ampersand (&) aren't allowed. - * - * The use of a PCRE match enables looking for specific Unicode - * code points without writing a UTF-8 decoder. Whereas scanning - * for one-byte characters is trivial (with `strcspn`), scanning - * for the longer byte sequences would be more complicated. Given - * that this shouldn't be in the hot path for execution, it's a - * reasonable compromise in efficiency without introducing a - * noticeable impact on the overall system. - * - * @see https://html.spec.whatwg.org/#attributes-2 - * - * @TODO as the only regex pattern maybe we should take it out? are - * Unicode patterns available broadly in Core? - */ - if ( preg_match( - '~[' . - // Syntax-like characters. - '"\'>&</ =' . - // Control characters. - '\x{00}-\x{1F}' . - // HTML noncharacters. - '\x{FDD0}-\x{FDEF}' . - '\x{FFFE}\x{FFFF}\x{1FFFE}\x{1FFFF}\x{2FFFE}\x{2FFFF}\x{3FFFE}\x{3FFFF}' . - '\x{4FFFE}\x{4FFFF}\x{5FFFE}\x{5FFFF}\x{6FFFE}\x{6FFFF}\x{7FFFE}\x{7FFFF}' . - '\x{8FFFE}\x{8FFFF}\x{9FFFE}\x{9FFFF}\x{AFFFE}\x{AFFFF}\x{BFFFE}\x{BFFFF}' . - '\x{CFFFE}\x{CFFFF}\x{DFFFE}\x{DFFFF}\x{EFFFE}\x{EFFFF}\x{FFFFE}\x{FFFFF}' . - '\x{10FFFE}\x{10FFFF}' . - ']~Ssu', - $name - ) ) { - _doing_it_wrong( - __METHOD__, - __( 'Invalid attribute name.' ), - '6.2.0' - ); - - return false; - } - - /* - * > The values "true" and "false" are not allowed on boolean attributes. - * > To represent a false value, the attribute has to be omitted altogether. - * - HTML5 spec, https://html.spec.whatwg.org/#boolean-attributes - */ - if ( false === $value ) { - return $this->remove_attribute( $name ); - } - - if ( true === $value ) { - $updated_attribute = $name; - } else { - $comparable_name = strtolower( $name ); - - /* - * Escape URL attributes. - * - * @see https://html.spec.whatwg.org/#attributes-3 - */ - $escaped_new_value = in_array( $comparable_name, wp_kses_uri_attributes() ) ? esc_url( $value ) : esc_attr( $value ); - $updated_attribute = "{$name}=\"{$escaped_new_value}\""; - } - - /* - * > There must never be two or more attributes on - * > the same start tag whose names are an ASCII - * > case-insensitive match for each other. - * - HTML 5 spec - * - * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive - */ - $comparable_name = strtolower( $name ); - - if ( isset( $this->attributes[ $comparable_name ] ) ) { - /* - * Update an existing attribute. - * - * Example – set attribute id to "new" in <div id="initial_id" />: - * - * <div id="initial_id"/> - * ^-------------^ - * start end - * replacement: `id="new"` - * - * Result: <div id="new"/> - */ - $existing_attribute = $this->attributes[ $comparable_name ]; - $this->lexical_updates[ $comparable_name ] = new WP_HTML_Text_Replacement( - $existing_attribute->start, - $existing_attribute->end, - $updated_attribute - ); - } else { - /* - * Create a new attribute at the tag's name end. - * - * Example – add attribute id="new" to <div />: - * - * <div/> - * ^ - * start and end - * replacement: ` id="new"` - * - * Result: <div id="new"/> - */ - $this->lexical_updates[ $comparable_name ] = new WP_HTML_Text_Replacement( - $this->tag_name_starts_at + $this->tag_name_length, - $this->tag_name_starts_at + $this->tag_name_length, - ' ' . $updated_attribute - ); - } - - /* - * Any calls to update the `class` attribute directly should wipe out any - * enqueued class changes from `add_class` and `remove_class`. - */ - if ( 'class' === $comparable_name && ! empty( $this->classname_updates ) ) { - $this->classname_updates = array(); - } - - return true; - } - - /** - * Remove an attribute from the currently-matched tag. - * - * @since 6.2.0 - * - * @param string $name The attribute name to remove. - * @return bool Whether an attribute was removed. - */ - public function remove_attribute( $name ) { - if ( $this->is_closing_tag ) { - return false; - } - - /* - * > There must never be two or more attributes on - * > the same start tag whose names are an ASCII - * > case-insensitive match for each other. - * - HTML 5 spec - * - * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive - */ - $name = strtolower( $name ); - - /* - * Any calls to update the `class` attribute directly should wipe out any - * enqueued class changes from `add_class` and `remove_class`. - */ - if ( 'class' === $name && count( $this->classname_updates ) !== 0 ) { - $this->classname_updates = array(); - } - - /* - * If updating an attribute that didn't exist in the input - * document, then remove the enqueued update and move on. - * - * For example, this might occur when calling `remove_attribute()` - * after calling `set_attribute()` for the same attribute - * and when that attribute wasn't originally present. - */ - if ( ! isset( $this->attributes[ $name ] ) ) { - if ( isset( $this->lexical_updates[ $name ] ) ) { - unset( $this->lexical_updates[ $name ] ); - } - return false; - } - - /* - * Removes an existing tag attribute. - * - * Example – remove the attribute id from <div id="main"/>: - * <div id="initial_id"/> - * ^-------------^ - * start end - * replacement: `` - * - * Result: <div /> - */ - $this->lexical_updates[ $name ] = new WP_HTML_Text_Replacement( - $this->attributes[ $name ]->start, - $this->attributes[ $name ]->end, - '' - ); - - // Removes any duplicated attributes if they were also present. - if ( null !== $this->duplicate_attributes && array_key_exists( $name, $this->duplicate_attributes ) ) { - foreach ( $this->duplicate_attributes[ $name ] as $attribute_token ) { - $this->lexical_updates[] = new WP_HTML_Text_Replacement( - $attribute_token->start, - $attribute_token->end, - '' - ); - } - } - - return true; - } - - /** - * Adds a new class name to the currently matched tag. - * - * @since 6.2.0 - * - * @param string $class_name The class name to add. - * @return bool Whether the class was set to be added. - */ - public function add_class( $class_name ) { - if ( $this->is_closing_tag ) { - return false; - } - - if ( null !== $this->tag_name_starts_at ) { - $this->classname_updates[ $class_name ] = self::ADD_CLASS; - } - - return true; - } - - /** - * Removes a class name from the currently matched tag. - * - * @since 6.2.0 - * - * @param string $class_name The class name to remove. - * @return bool Whether the class was set to be removed. - */ - public function remove_class( $class_name ) { - if ( $this->is_closing_tag ) { - return false; - } - - if ( null !== $this->tag_name_starts_at ) { - $this->classname_updates[ $class_name ] = self::REMOVE_CLASS; - } - - return true; - } - - /** - * Returns the string representation of the HTML Tag Processor. - * - * @since 6.2.0 - * - * @see WP_HTML_Tag_Processor::get_updated_html() - * - * @return string The processed HTML. - */ - public function __toString() { - return $this->get_updated_html(); - } - - /** - * Returns the string representation of the HTML Tag Processor. - * - * @since 6.2.0 - * @since 6.2.1 Shifts the internal cursor corresponding to the applied updates. - * @since 6.4.0 No longer calls subclass method `next_tag()` after updating HTML. - * - * @return string The processed HTML. - */ - public function get_updated_html() { - $requires_no_updating = 0 === count( $this->classname_updates ) && 0 === count( $this->lexical_updates ); - - /* - * When there is nothing more to update and nothing has already been - * updated, return the original document and avoid a string copy. - */ - if ( $requires_no_updating ) { - return $this->html; - } - - /* - * Keep track of the position right before the current tag. This will - * be necessary for reparsing the current tag after updating the HTML. - */ - $before_current_tag = $this->tag_name_starts_at - 1; - - /* - * 1. Apply the enqueued edits and update all the pointers to reflect those changes. - */ - $this->class_name_updates_to_attributes_updates(); - $before_current_tag += $this->apply_attributes_updates( $before_current_tag ); - - /* - * 2. Rewind to before the current tag and reparse to get updated attributes. - * - * At this point the internal cursor points to the end of the tag name. - * Rewind before the tag name starts so that it's as if the cursor didn't - * move; a call to `next_tag()` will reparse the recently-updated attributes - * and additional calls to modify the attributes will apply at this same - * location, but in order to avoid issues with subclasses that might add - * behaviors to `next_tag()`, the internal methods should be called here - * instead. - * - * It's important to note that in this specific place there will be no change - * because the processor was already at a tag when this was called and it's - * rewinding only to the beginning of this very tag before reprocessing it - * and its attributes. - * - * <p>Previous HTML<em>More HTML</em></p> - * ↑ │ back up by the length of the tag name plus the opening < - * └←─┘ back up by strlen("em") + 1 ==> 3 - */ - $this->bytes_already_parsed = $before_current_tag; - $this->parse_next_tag(); - // Reparse the attributes. - while ( $this->parse_next_attribute() ) { - continue; - } - - $tag_ends_at = strpos( $this->html, '>', $this->bytes_already_parsed ); - $this->tag_ends_at = $tag_ends_at; - $this->bytes_already_parsed = $tag_ends_at; - - return $this->html; - } - - /** - * Parses tag query input into internal search criteria. - * - * @since 6.2.0 - * - * @param array|string|null $query { - * Optional. Which tag name to find, having which class, etc. Default is to find any tag. - * - * @type string|null $tag_name Which tag to find, or `null` for "any tag." - * @type int|null $match_offset Find the Nth tag matching all search criteria. - * 1 for "first" tag, 3 for "third," etc. - * Defaults to first tag. - * @type string|null $class_name Tag must contain this class name to match. - * @type string $tag_closers "visit" or "skip": whether to stop on tag closers, e.g. </div>. - * } - */ - private function parse_query( $query ) { - if ( null !== $query && $query === $this->last_query ) { - return; - } - - $this->last_query = $query; - $this->sought_tag_name = null; - $this->sought_class_name = null; - $this->sought_match_offset = 1; - $this->stop_on_tag_closers = false; - - // A single string value means "find the tag of this name". - if ( is_string( $query ) ) { - $this->sought_tag_name = $query; - return; - } - - // An empty query parameter applies no restrictions on the search. - if ( null === $query ) { - return; - } - - // If not using the string interface, an associative array is required. - if ( ! is_array( $query ) ) { - _doing_it_wrong( - __METHOD__, - __( 'The query argument must be an array or a tag name.' ), - '6.2.0' - ); - return; - } - - if ( isset( $query['tag_name'] ) && is_string( $query['tag_name'] ) ) { - $this->sought_tag_name = $query['tag_name']; - } - - if ( isset( $query['class_name'] ) && is_string( $query['class_name'] ) ) { - $this->sought_class_name = $query['class_name']; - } - - if ( isset( $query['match_offset'] ) && is_int( $query['match_offset'] ) && 0 < $query['match_offset'] ) { - $this->sought_match_offset = $query['match_offset']; - } - - if ( isset( $query['tag_closers'] ) ) { - $this->stop_on_tag_closers = 'visit' === $query['tag_closers']; - } - } - - - /** - * Checks whether a given tag and its attributes match the search criteria. - * - * @since 6.2.0 - * - * @return bool Whether the given tag and its attribute match the search criteria. - */ - private function matches() { - if ( $this->is_closing_tag && ! $this->stop_on_tag_closers ) { - return false; - } - - // Does the tag name match the requested tag name in a case-insensitive manner? - if ( null !== $this->sought_tag_name ) { - /* - * String (byte) length lookup is fast. If they aren't the - * same length then they can't be the same string values. - */ - if ( strlen( $this->sought_tag_name ) !== $this->tag_name_length ) { - return false; - } - - /* - * Check each character to determine if they are the same. - * Defer calls to `strtoupper()` to avoid them when possible. - * Calling `strcasecmp()` here tested slowed than comparing each - * character, so unless benchmarks show otherwise, it should - * not be used. - * - * It's expected that most of the time that this runs, a - * lower-case tag name will be supplied and the input will - * contain lower-case tag names, thus normally bypassing - * the case comparison code. - */ - for ( $i = 0; $i < $this->tag_name_length; $i++ ) { - $html_char = $this->html[ $this->tag_name_starts_at + $i ]; - $tag_char = $this->sought_tag_name[ $i ]; - - if ( $html_char !== $tag_char && strtoupper( $html_char ) !== $tag_char ) { - return false; - } - } - } - - if ( null !== $this->sought_class_name && ! $this->has_class( $this->sought_class_name ) ) { - return false; - } - - return true; - } -} diff --git a/lib/compat/wordpress-6.4/html-api/class-wp-html-active-formatting-elements.php b/lib/compat/wordpress-6.4/html-api/class-wp-html-active-formatting-elements.php deleted file mode 100644 index 4bf726bd39ec95..00000000000000 --- a/lib/compat/wordpress-6.4/html-api/class-wp-html-active-formatting-elements.php +++ /dev/null @@ -1,190 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Active_Formatting_Elements class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.4.0 - */ - -if ( ! class_exists( 'WP_HTML_Active_Formatting_Elements' ) ) { - - /** - * Core class used by the HTML processor during HTML parsing - * for managing the stack of active formatting elements. - * - * This class is designed for internal use by the HTML processor. - * - * > Initially, the list of active formatting elements is empty. - * > It is used to handle mis-nested formatting element tags. - * > - * > The list contains elements in the formatting category, and markers. - * > The markers are inserted when entering applet, object, marquee, - * > template, td, th, and caption elements, and are used to prevent - * > formatting from "leaking" into applet, object, marquee, template, - * > td, th, and caption elements. - * > - * > In addition, each element in the list of active formatting elements - * > is associated with the token for which it was created, so that - * > further elements can be created for that token if necessary. - * - * @since 6.4.0 - * - * @access private - * - * @see https://html.spec.whatwg.org/#list-of-active-formatting-elements - * @see WP_HTML_Processor - */ - class WP_HTML_Active_Formatting_Elements { - /** - * Holds the stack of active formatting element references. - * - * @since 6.4.0 - * - * @var WP_HTML_Token[] - */ - private $stack = array(); - - /** - * Reports if a specific node is in the stack of active formatting elements. - * - * @since 6.4.0 - * - * @param WP_HTML_Token $token Look for this node in the stack. - * @return bool Whether the referenced node is in the stack of active formatting elements. - */ - public function contains_node( $token ) { - foreach ( $this->walk_up() as $item ) { - if ( $token->bookmark_name === $item->bookmark_name ) { - return true; - } - } - - return false; - } - - /** - * Returns how many nodes are currently in the stack of active formatting elements. - * - * @since 6.4.0 - * - * @return int How many node are in the stack of active formatting elements. - */ - public function count() { - return count( $this->stack ); - } - - /** - * Returns the node at the end of the stack of active formatting elements, - * if one exists. If the stack is empty, returns null. - * - * @since 6.4.0 - * - * @return WP_HTML_Token|null Last node in the stack of active formatting elements, if one exists, otherwise null. - */ - public function current_node() { - $current_node = end( $this->stack ); - - return $current_node ? $current_node : null; - } - - /** - * Pushes a node onto the stack of active formatting elements. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#push-onto-the-list-of-active-formatting-elements - * - * @param WP_HTML_Token $token Push this node onto the stack. - */ - public function push( $token ) { - /* - * > If there are already three elements in the list of active formatting elements after the last marker, - * > if any, or anywhere in the list if there are no markers, that have the same tag name, namespace, and - * > attributes as element, then remove the earliest such element from the list of active formatting - * > elements. For these purposes, the attributes must be compared as they were when the elements were - * > created by the parser; two elements have the same attributes if all their parsed attributes can be - * > paired such that the two attributes in each pair have identical names, namespaces, and values - * > (the order of the attributes does not matter). - * - * @TODO: Implement the "Noah's Ark clause" to only add up to three of any given kind of formatting elements to the stack. - */ - // > Add element to the list of active formatting elements. - $this->stack[] = $token; - } - - /** - * Removes a node from the stack of active formatting elements. - * - * @since 6.4.0 - * - * @param WP_HTML_Token $token Remove this node from the stack, if it's there already. - * @return bool Whether the node was found and removed from the stack of active formatting elements. - */ - public function remove_node( $token ) { - foreach ( $this->walk_up() as $position_from_end => $item ) { - if ( $token->bookmark_name !== $item->bookmark_name ) { - continue; - } - - $position_from_start = $this->count() - $position_from_end - 1; - array_splice( $this->stack, $position_from_start, 1 ); - return true; - } - - return false; - } - - /** - * Steps through the stack of active formatting elements, starting with the - * top element (added first) and walking downwards to the one added last. - * - * This generator function is designed to be used inside a "foreach" loop. - * - * Example: - * - * $html = '<em><strong><a>We are here'; - * foreach ( $stack->walk_down() as $node ) { - * echo "{$node->node_name} -> "; - * } - * > EM -> STRONG -> A -> - * - * To start with the most-recently added element and walk towards the top, - * see WP_HTML_Active_Formatting_Elements::walk_up(). - * - * @since 6.4.0 - */ - public function walk_down() { - $count = count( $this->stack ); - - for ( $i = 0; $i < $count; $i++ ) { - yield $this->stack[ $i ]; - } - } - - /** - * Steps through the stack of active formatting elements, starting with the - * bottom element (added last) and walking upwards to the one added first. - * - * This generator function is designed to be used inside a "foreach" loop. - * - * Example: - * - * $html = '<em><strong><a>We are here'; - * foreach ( $stack->walk_up() as $node ) { - * echo "{$node->node_name} -> "; - * } - * > A -> STRONG -> EM -> - * - * To start with the first added element and walk towards the bottom, - * see WP_HTML_Active_Formatting_Elements::walk_down(). - * - * @since 6.4.0 - */ - public function walk_up() { - for ( $i = count( $this->stack ) - 1; $i >= 0; $i-- ) { - yield $this->stack[ $i ]; - } - } - } -} \ No newline at end of file diff --git a/lib/compat/wordpress-6.4/html-api/class-wp-html-open-elements.php b/lib/compat/wordpress-6.4/html-api/class-wp-html-open-elements.php deleted file mode 100644 index f8f6f43119390b..00000000000000 --- a/lib/compat/wordpress-6.4/html-api/class-wp-html-open-elements.php +++ /dev/null @@ -1,435 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Open_Elements class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.4.0 - */ - -if ( ! class_exists( 'WP_HTML_Open_Elements' ) ) { - - /** - * Core class used by the HTML processor during HTML parsing - * for managing the stack of open elements. - * - * This class is designed for internal use by the HTML processor. - * - * > Initially, the stack of open elements is empty. The stack grows - * > downwards; the topmost node on the stack is the first one added - * > to the stack, and the bottommost node of the stack is the most - * > recently added node in the stack (notwithstanding when the stack - * > is manipulated in a random access fashion as part of the handling - * > for misnested tags). - * - * @since 6.4.0 - * - * @access private - * - * @see https://html.spec.whatwg.org/#stack-of-open-elements - * @see WP_HTML_Processor - */ - class WP_HTML_Open_Elements { - /** - * Holds the stack of open element references. - * - * @since 6.4.0 - * - * @var WP_HTML_Token[] - */ - public $stack = array(); - - /** - * Whether a P element is in button scope currently. - * - * This class optimizes scope lookup by pre-calculating - * this value when elements are added and removed to the - * stack of open elements which might change its value. - * This avoids frequent iteration over the stack. - * - * @since 6.4.0 - * - * @var bool - */ - private $has_p_in_button_scope = false; - - /** - * Reports if a specific node is in the stack of open elements. - * - * @since 6.4.0 - * - * @param WP_HTML_Token $token Look for this node in the stack. - * @return bool Whether the referenced node is in the stack of open elements. - */ - public function contains_node( $token ) { - foreach ( $this->walk_up() as $item ) { - if ( $token->bookmark_name === $item->bookmark_name ) { - return true; - } - } - - return false; - } - - /** - * Returns how many nodes are currently in the stack of open elements. - * - * @since 6.4.0 - * - * @return int How many node are in the stack of open elements. - */ - public function count() { - return count( $this->stack ); - } - - /** - * Returns the node at the end of the stack of open elements, - * if one exists. If the stack is empty, returns null. - * - * @since 6.4.0 - * - * @return WP_HTML_Token|null Last node in the stack of open elements, if one exists, otherwise null. - */ - public function current_node() { - $current_node = end( $this->stack ); - - return $current_node ? $current_node : null; - } - - /** - * Returns whether an element is in a specific scope. - * - * ## HTML Support - * - * This function skips checking for the termination list because there - * are no supported elements which appear in the termination list. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-the-specific-scope - * - * @param string $tag_name Name of tag check. - * @param string[] $termination_list List of elements that terminate the search. - * @return bool Whether the element was found in a specific scope. - */ - public function has_element_in_specific_scope( $tag_name, $termination_list ) { - foreach ( $this->walk_up() as $node ) { - if ( $node->node_name === $tag_name ) { - return true; - } - - switch ( $node->node_name ) { - case 'HTML': - return false; - } - - if ( in_array( $node->node_name, $termination_list, true ) ) { - return true; - } - } - - return false; - } - - /** - * Returns whether a particular element is in scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-scope - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_scope( $tag_name ) { - return $this->has_element_in_specific_scope( - $tag_name, - array( - - /* - * Because it's not currently possible to encounter - * one of the termination elements, they don't need - * to be listed here. If they were, they would be - * unreachable and only waste CPU cycles while - * scanning through HTML. - */ - ) - ); - } - - /** - * Returns whether a particular element is in list item scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-list-item-scope - * - * @throws WP_HTML_Unsupported_Exception Always until this function is implemented. - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_list_item_scope( $tag_name ) { - throw new WP_HTML_Unsupported_Exception( 'Cannot process elements depending on list item scope.' ); - - return false; // The linter requires this unreachable code until the function is implemented and can return. - } - - /** - * Returns whether a particular element is in button scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-button-scope - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_button_scope( $tag_name ) { - return $this->has_element_in_specific_scope( $tag_name, array( 'BUTTON' ) ); - } - - /** - * Returns whether a particular element is in table scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-table-scope - * - * @throws WP_HTML_Unsupported_Exception Always until this function is implemented. - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_table_scope( $tag_name ) { - throw new WP_HTML_Unsupported_Exception( 'Cannot process elements depending on table scope.' ); - - return false; // The linter requires this unreachable code until the function is implemented and can return. - } - - /** - * Returns whether a particular element is in select scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-select-scope - * - * @throws WP_HTML_Unsupported_Exception Always until this function is implemented. - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_select_scope( $tag_name ) { - throw new WP_HTML_Unsupported_Exception( 'Cannot process elements depending on select scope.' ); - - return false; // The linter requires this unreachable code until the function is implemented and can return. - } - - /** - * Returns whether a P is in BUTTON scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-button-scope - * - * @return bool Whether a P is in BUTTON scope. - */ - public function has_p_in_button_scope() { - return $this->has_p_in_button_scope; - } - - /** - * Pops a node off of the stack of open elements. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#stack-of-open-elements - * - * @return bool Whether a node was popped off of the stack. - */ - public function pop() { - $item = array_pop( $this->stack ); - - if ( null === $item ) { - return false; - } - - $this->after_element_pop( $item ); - return true; - } - - /** - * Pops nodes off of the stack of open elements until one with the given tag name has been popped. - * - * @since 6.4.0 - * - * @see WP_HTML_Open_Elements::pop - * - * @param string $tag_name Name of tag that needs to be popped off of the stack of open elements. - * @return bool Whether a tag of the given name was found and popped off of the stack of open elements. - */ - public function pop_until( $tag_name ) { - foreach ( $this->walk_up() as $item ) { - $this->pop(); - - if ( $tag_name === $item->node_name ) { - return true; - } - } - - return false; - } - - /** - * Pushes a node onto the stack of open elements. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#stack-of-open-elements - * - * @param WP_HTML_Token $stack_item Item to add onto stack. - */ - public function push( $stack_item ) { - $this->stack[] = $stack_item; - $this->after_element_push( $stack_item ); - } - - /** - * Removes a specific node from the stack of open elements. - * - * @since 6.4.0 - * - * @param WP_HTML_Token $token The node to remove from the stack of open elements. - * @return bool Whether the node was found and removed from the stack of open elements. - */ - public function remove_node( $token ) { - foreach ( $this->walk_up() as $position_from_end => $item ) { - if ( $token->bookmark_name !== $item->bookmark_name ) { - continue; - } - - $position_from_start = $this->count() - $position_from_end - 1; - array_splice( $this->stack, $position_from_start, 1 ); - $this->after_element_pop( $item ); - return true; - } - - return false; - } - - - /** - * Steps through the stack of open elements, starting with the top element - * (added first) and walking downwards to the one added last. - * - * This generator function is designed to be used inside a "foreach" loop. - * - * Example: - * - * $html = '<em><strong><a>We are here'; - * foreach ( $stack->walk_down() as $node ) { - * echo "{$node->node_name} -> "; - * } - * > EM -> STRONG -> A -> - * - * To start with the most-recently added element and walk towards the top, - * see WP_HTML_Open_Elements::walk_up(). - * - * @since 6.4.0 - */ - public function walk_down() { - $count = count( $this->stack ); - - for ( $i = 0; $i < $count; $i++ ) { - yield $this->stack[ $i ]; - } - } - - /** - * Steps through the stack of open elements, starting with the bottom element - * (added last) and walking upwards to the one added first. - * - * This generator function is designed to be used inside a "foreach" loop. - * - * Example: - * - * $html = '<em><strong><a>We are here'; - * foreach ( $stack->walk_up() as $node ) { - * echo "{$node->node_name} -> "; - * } - * > A -> STRONG -> EM -> - * - * To start with the first added element and walk towards the bottom, - * see WP_HTML_Open_Elements::walk_down(). - * - * @since 6.4.0 - */ - public function walk_up() { - for ( $i = count( $this->stack ) - 1; $i >= 0; $i-- ) { - yield $this->stack[ $i ]; - } - } - - /* - * Internal helpers. - */ - - /** - * Updates internal flags after adding an element. - * - * Certain conditions (such as "has_p_in_button_scope") are maintained here as - * flags that are only modified when adding and removing elements. This allows - * the HTML Processor to quickly check for these conditions instead of iterating - * over the open stack elements upon each new tag it encounters. These flags, - * however, need to be maintained as items are added and removed from the stack. - * - * @since 6.4.0 - * - * @param WP_HTML_Token $item Element that was added to the stack of open elements. - */ - public function after_element_push( $item ) { - /* - * When adding support for new elements, expand this switch to trap - * cases where the precalculated value needs to change. - */ - switch ( $item->node_name ) { - case 'BUTTON': - $this->has_p_in_button_scope = false; - break; - - case 'P': - $this->has_p_in_button_scope = true; - break; - } - } - - /** - * Updates internal flags after removing an element. - * - * Certain conditions (such as "has_p_in_button_scope") are maintained here as - * flags that are only modified when adding and removing elements. This allows - * the HTML Processor to quickly check for these conditions instead of iterating - * over the open stack elements upon each new tag it encounters. These flags, - * however, need to be maintained as items are added and removed from the stack. - * - * @since 6.4.0 - * - * @param WP_HTML_Token $item Element that was removed from the stack of open elements. - */ - public function after_element_pop( $item ) { - /* - * When adding support for new elements, expand this switch to trap - * cases where the precalculated value needs to change. - */ - switch ( $item->node_name ) { - case 'BUTTON': - $this->has_p_in_button_scope = $this->has_element_in_button_scope( 'P' ); - break; - - case 'P': - $this->has_p_in_button_scope = $this->has_element_in_button_scope( 'P' ); - break; - } - } - } -} diff --git a/lib/compat/wordpress-6.4/html-api/class-wp-html-processor-state.php b/lib/compat/wordpress-6.4/html-api/class-wp-html-processor-state.php deleted file mode 100644 index 03443c2b3d3261..00000000000000 --- a/lib/compat/wordpress-6.4/html-api/class-wp-html-processor-state.php +++ /dev/null @@ -1,146 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Processor_State class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.4.0 - */ - -if ( ! class_exists( 'WP_HTML_Processor_State' ) ) { - - /** - * Core class used by the HTML processor during HTML parsing - * for managing the internal parsing state. - * - * This class is designed for internal use by the HTML processor. - * - * @since 6.4.0 - * - * @access private - * - * @see WP_HTML_Processor - */ - class WP_HTML_Processor_State { - /* - * Insertion mode constants. - * - * These constants exist and are named to make it easier to - * discover and recognize the supported insertion modes in - * the parser. - * - * Out of all the possible insertion modes, only those - * supported by the parser are listed here. As support - * is added to the parser for more modes, add them here - * following the same naming and value pattern. - * - * @see https://html.spec.whatwg.org/#the-insertion-mode - */ - - /** - * Initial insertion mode for full HTML parser. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#the-initial-insertion-mode - * @see WP_HTML_Processor_State::$insertion_mode - * - * @var string - */ - const INSERTION_MODE_INITIAL = 'insertion-mode-initial'; - - /** - * In body insertion mode for full HTML parser. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#parsing-main-inbody - * @see WP_HTML_Processor_State::$insertion_mode - * - * @var string - */ - const INSERTION_MODE_IN_BODY = 'insertion-mode-in-body'; - - /** - * Tracks open elements while scanning HTML. - * - * This property is initialized in the constructor and never null. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#stack-of-open-elements - * - * @var WP_HTML_Open_Elements - */ - public $stack_of_open_elements = null; - - /** - * Tracks open formatting elements, used to handle mis-nested formatting element tags. - * - * This property is initialized in the constructor and never null. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#list-of-active-formatting-elements - * - * @var WP_HTML_Active_Formatting_Elements - */ - public $active_formatting_elements = null; - - /** - * Refers to the currently-matched tag, if any. - * - * @since 6.4.0 - * - * @var WP_HTML_Token|null - */ - public $current_token = null; - - /** - * Tree construction insertion mode. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#insertion-mode - * - * @var string - */ - public $insertion_mode = self::INSERTION_MODE_INITIAL; - - /** - * Context node initializing fragment parser, if created as a fragment parser. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#concept-frag-parse-context - * - * @var [string, array]|null - */ - public $context_node = null; - - /** - * The frameset-ok flag indicates if a `FRAMESET` element is allowed in the current state. - * - * > The frameset-ok flag is set to "ok" when the parser is created. It is set to "not ok" after certain tokens are seen. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#frameset-ok-flag - * - * @var bool - */ - public $frameset_ok = true; - - /** - * Constructor - creates a new and empty state value. - * - * @since 6.4.0 - * - * @see WP_HTML_Processor - */ - public function __construct() { - $this->stack_of_open_elements = new WP_HTML_Open_Elements(); - $this->active_formatting_elements = new WP_HTML_Active_Formatting_Elements(); - } - } -} diff --git a/lib/compat/wordpress-6.4/html-api/class-wp-html-processor.php b/lib/compat/wordpress-6.4/html-api/class-wp-html-processor.php deleted file mode 100644 index 4a2714218229ef..00000000000000 --- a/lib/compat/wordpress-6.4/html-api/class-wp-html-processor.php +++ /dev/null @@ -1,1446 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Processor class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.4.0 - */ - -if ( ! class_exists( 'WP_HTML_Processor' ) ) { - - /** - * Core class used to safely parse and modify an HTML document. - * - * The HTML Processor class properly parses and modifies HTML5 documents. - * - * It supports a subset of the HTML5 specification, and when it encounters - * unsupported markup, it aborts early to avoid unintentionally breaking - * the document. The HTML Processor should never break an HTML document. - * - * While the `WP_HTML_Tag_Processor` is a valuable tool for modifying - * attributes on individual HTML tags, the HTML Processor is more capable - * and useful for the following operations: - * - * - Querying based on nested HTML structure. - * - * Eventually the HTML Processor will also support: - * - Wrapping a tag in surrounding HTML. - * - Unwrapping a tag by removing its parent. - * - Inserting and removing nodes. - * - Reading and changing inner content. - * - Navigating up or around HTML structure. - * - * ## Usage - * - * Use of this class requires three steps: - * - * 1. Call a static creator method with your input HTML document. - * 2. Find the location in the document you are looking for. - * 3. Request changes to the document at that location. - * - * Example: - * - * $processor = WP_HTML_Processor::create_fragment( $html ); - * if ( $processor->next_tag( array( 'breadcrumbs' => array( 'DIV', 'FIGURE', 'IMG' ) ) ) ) { - * $processor->add_class( 'responsive-image' ); - * } - * - * #### Breadcrumbs - * - * Breadcrumbs represent the stack of open elements from the root - * of the document or fragment down to the currently-matched node, - * if one is currently selected. Call WP_HTML_Processor::get_breadcrumbs() - * to inspect the breadcrumbs for a matched tag. - * - * Breadcrumbs can specify nested HTML structure and are equivalent - * to a CSS selector comprising tag names separated by the child - * combinator, such as "DIV > FIGURE > IMG". - * - * Since all elements find themselves inside a full HTML document - * when parsed, the return value from `get_breadcrumbs()` will always - * contain any implicit outermost elements. For example, when parsing - * with `create_fragment()` in the `BODY` context (the default), any - * tag in the given HTML document will contain `array( 'HTML', 'BODY', … )` - * in its breadcrumbs. - * - * Despite containing the implied outermost elements in their breadcrumbs, - * tags may be found with the shortest-matching breadcrumb query. That is, - * `array( 'IMG' )` matches all IMG elements and `array( 'P', 'IMG' )` - * matches all IMG elements directly inside a P element. To ensure that no - * partial matches erroneously match it's possible to specify in a query - * the full breadcrumb match all the way down from the root HTML element. - * - * Example: - * - * $html = '<figure><img><figcaption>A <em>lovely</em> day outside</figcaption></figure>'; - * // ----- Matches here. - * $processor->next_tag( array( 'breadcrumbs' => array( 'FIGURE', 'IMG' ) ) ); - * - * $html = '<figure><img><figcaption>A <em>lovely</em> day outside</figcaption></figure>'; - * // ---- Matches here. - * $processor->next_tag( array( 'breadcrumbs' => array( 'FIGURE', 'FIGCAPTION', 'EM' ) ) ); - * - * $html = '<div><img></div><img>'; - * // ----- Matches here, because IMG must be a direct child of the implicit BODY. - * $processor->next_tag( array( 'breadcrumbs' => array( 'BODY', 'IMG' ) ) ); - * - * ## HTML Support - * - * This class implements a small part of the HTML5 specification. - * It's designed to operate within its support and abort early whenever - * encountering circumstances it can't properly handle. This is - * the principle way in which this class remains as simple as possible - * without cutting corners and breaking compliance. - * - * ### Supported elements - * - * If any unsupported element appears in the HTML input the HTML Processor - * will abort early and stop all processing. This draconian measure ensures - * that the HTML Processor won't break any HTML it doesn't fully understand. - * - * The following list specifies the HTML tags that _are_ supported: - * - * - Links: A. - * - The formatting elements: B, BIG, CODE, EM, FONT, I, SMALL, STRIKE, STRONG, TT, U. - * - Containers: DIV, FIGCAPTION, FIGURE, SPAN. - * - Form elements: BUTTON. - * - Paragraph: P. - * - Void elements: IMG. - * - * ### Supported markup - * - * Some kinds of non-normative HTML involve reconstruction of formatting elements and - * re-parenting of mis-nested elements. For example, a DIV tag found inside a TABLE - * may in fact belong _before_ the table in the DOM. If the HTML Processor encounters - * such a case it will stop processing. - * - * The following list specifies HTML markup that _is_ supported: - * - * - Markup involving only those tags listed above. - * - Fully-balanced and non-overlapping tags. - * - HTML with unexpected tag closers. - * - Some unbalanced or overlapping tags. - * - P tags after unclosed P tags. - * - BUTTON tags after unclosed BUTTON tags. - * - A tags after unclosed A tags that don't involve any active formatting elements. - * - * @since 6.4.0 - * - * @see WP_HTML_Tag_Processor - * @see https://html.spec.whatwg.org/ - */ - class WP_HTML_Processor extends Gutenberg_HTML_Tag_Processor_6_4 { - /** - * The maximum number of bookmarks allowed to exist at any given time. - * - * HTML processing requires more bookmarks than basic tag processing, - * so this class constant from the Tag Processor is overwritten. - * - * @since 6.4.0 - * - * @var int - */ - const MAX_BOOKMARKS = 100; - - /** - * Static query for instructing the Tag Processor to visit every token. - * - * @access private - * - * @since 6.4.0 - * - * @var array - */ - const VISIT_EVERYTHING = array( 'tag_closers' => 'visit' ); - - /** - * Holds the working state of the parser, including the stack of - * open elements and the stack of active formatting elements. - * - * Initialized in the constructor. - * - * @since 6.4.0 - * - * @var WP_HTML_Processor_State - */ - private $state = null; - - /** - * Used to create unique bookmark names. - * - * This class sets a bookmark for every tag in the HTML document that it encounters. - * The bookmark name is auto-generated and increments, starting with `1`. These are - * internal bookmarks and are automatically released when the referring WP_HTML_Token - * goes out of scope and is garbage-collected. - * - * @since 6.4.0 - * - * @see WP_HTML_Processor::$release_internal_bookmark_on_destruct - * - * @var int - */ - private $bookmark_counter = 0; - - /** - * Stores an explanation for why something failed, if it did. - * - * @see self::get_last_error - * - * @since 6.4.0 - * - * @var string|null - */ - private $last_error = null; - - /** - * Releases a bookmark when PHP garbage-collects its wrapping WP_HTML_Token instance. - * - * This function is created inside the class constructor so that it can be passed to - * the stack of open elements and the stack of active formatting elements without - * exposing it as a public method on the class. - * - * @since 6.4.0 - * - * @var closure - */ - private $release_internal_bookmark_on_destruct = null; - - /* - * Public Interface Functions - */ - - /** - * Creates an HTML processor in the fragment parsing mode. - * - * Use this for cases where you are processing chunks of HTML that - * will be found within a bigger HTML document, such as rendered - * block output that exists within a post, `the_content` inside a - * rendered site layout. - * - * Fragment parsing occurs within a context, which is an HTML element - * that the document will eventually be placed in. It becomes important - * when special elements have different rules than others, such as inside - * a TEXTAREA or a TITLE tag where things that look like tags are text, - * or inside a SCRIPT tag where things that look like HTML syntax are JS. - * - * The context value should be a representation of the tag into which the - * HTML is found. For most cases this will be the body element. The HTML - * form is provided because a context element may have attributes that - * impact the parse, such as with a SCRIPT tag and its `type` attribute. - * - * ## Current HTML Support - * - * - The only supported context is `<body>`, which is the default value. - * - The only supported document encoding is `UTF-8`, which is the default value. - * - * @since 6.4.0 - * - * @param string $html Input HTML fragment to process. - * @param string $context Context element for the fragment, must be default of `<body>`. - * @param string $encoding Text encoding of the document; must be default of 'UTF-8'. - * @return WP_HTML_Processor|null The created processor if successful, otherwise null. - */ - public static function create_fragment( $html, $context = '<body>', $encoding = 'UTF-8' ) { - if ( '<body>' !== $context || 'UTF-8' !== $encoding ) { - return null; - } - - $p = new self( $html, self::CONSTRUCTOR_UNLOCK_CODE ); - $p->state->context_node = array( 'BODY', array() ); - $p->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_BODY; - - // @TODO: Create "fake" bookmarks for non-existent but implied nodes. - $p->bookmarks['root-node'] = new WP_HTML_Span( 0, 0 ); - $p->bookmarks['context-node'] = new WP_HTML_Span( 0, 0 ); - - $p->state->stack_of_open_elements->push( - new WP_HTML_Token( - 'root-node', - 'HTML', - false - ) - ); - - $p->state->stack_of_open_elements->push( - new WP_HTML_Token( - 'context-node', - $p->state->context_node[0], - false - ) - ); - - return $p; - } - - /** - * Constructor. - * - * Do not use this method. Use the static creator methods instead. - * - * @access private - * - * @since 6.4.0 - * - * @see WP_HTML_Processor::create_fragment() - * - * @param string $html HTML to process. - * @param string|null $use_the_static_create_methods_instead This constructor should not be called manually. - */ - public function __construct( $html, $use_the_static_create_methods_instead = null ) { - parent::__construct( $html ); - - if ( self::CONSTRUCTOR_UNLOCK_CODE !== $use_the_static_create_methods_instead ) { - _doing_it_wrong( - __METHOD__, - sprintf( - /* translators: %s: WP_HTML_Processor::create_fragment(). */ - __( 'Call %s to create an HTML Processor instead of calling the constructor directly.' ), - '<code>WP_HTML_Processor::create_fragment()</code>' - ), - '6.4.0' - ); - } - - $this->state = new WP_HTML_Processor_State(); - - /* - * Create this wrapper so that it's possible to pass - * a private method into WP_HTML_Token classes without - * exposing it to any public API. - */ - $this->release_internal_bookmark_on_destruct = function ( $name ) { - parent::release_bookmark( $name ); - }; - } - - /** - * Returns the last error, if any. - * - * Various situations lead to parsing failure but this class will - * return `false` in all those cases. To determine why something - * failed it's possible to request the last error. This can be - * helpful to know to distinguish whether a given tag couldn't - * be found or if content in the document caused the processor - * to give up and abort processing. - * - * Example - * - * $processor = WP_HTML_Processor::create_fragment( '<template><strong><button><em><p><em>' ); - * false === $processor->next_tag(); - * WP_HTML_Processor::ERROR_UNSUPPORTED === $processor->get_last_error(); - * - * @since 6.4.0 - * - * @see self::ERROR_UNSUPPORTED - * @see self::ERROR_EXCEEDED_MAX_BOOKMARKS - * - * @return string|null The last error, if one exists, otherwise null. - */ - public function get_last_error() { - return $this->last_error; - } - - /** - * Finds the next tag matching the $query. - * - * @TODO: Support matching the class name and tag name. - * - * @since 6.4.0 - * - * @throws Exception When unable to allocate a bookmark for the next token in the input HTML document. - * - * @param array|string|null $query { - * Optional. Which tag name to find, having which class, etc. Default is to find any tag. - * - * @type string|null $tag_name Which tag to find, or `null` for "any tag." - * @type int|null $match_offset Find the Nth tag matching all search criteria. - * 1 for "first" tag, 3 for "third," etc. - * Defaults to first tag. - * @type string|null $class_name Tag must contain this whole class name to match. - * @type string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. - * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. - * } - * @return bool Whether a tag was matched. - */ - public function next_tag( $query = null ) { - if ( null === $query ) { - while ( $this->step() ) { - if ( ! $this->is_tag_closer() ) { - return true; - } - } - - return false; - } - - if ( is_string( $query ) ) { - $query = array( 'breadcrumbs' => array( $query ) ); - } - - if ( ! is_array( $query ) ) { - _doing_it_wrong( - __METHOD__, - __( 'Please pass a query array to this function.' ), - '6.4.0' - ); - return false; - } - - if ( ! ( array_key_exists( 'breadcrumbs', $query ) && is_array( $query['breadcrumbs'] ) ) ) { - while ( $this->step() ) { - if ( ! $this->is_tag_closer() ) { - return true; - } - } - - return false; - } - - if ( isset( $query['tag_closers'] ) && 'visit' === $query['tag_closers'] ) { - _doing_it_wrong( - __METHOD__, - __( 'Cannot visit tag closers in HTML Processor.' ), - '6.4.0' - ); - return false; - } - - $breadcrumbs = $query['breadcrumbs']; - $match_offset = isset( $query['match_offset'] ) ? (int) $query['match_offset'] : 1; - - while ( $match_offset > 0 && $this->step() ) { - if ( $this->matches_breadcrumbs( $breadcrumbs ) && 0 === --$match_offset ) { - return true; - } - } - - return false; - } - - /** - * Indicates if the currently-matched tag matches the given breadcrumbs. - * - * A "*" represents a single tag wildcard, where any tag matches, but not no tags. - * - * At some point this function _may_ support a `**` syntax for matching any number - * of unspecified tags in the breadcrumb stack. This has been intentionally left - * out, however, to keep this function simple and to avoid introducing backtracking, - * which could open up surprising performance breakdowns. - * - * Example: - * - * $processor = WP_HTML_Processor::create_fragment( '<div><span><figure><img></figure></span></div>' ); - * $processor->next_tag( 'img' ); - * true === $processor->matches_breadcrumbs( array( 'figure', 'img' ) ); - * true === $processor->matches_breadcrumbs( array( 'span', 'figure', 'img' ) ); - * false === $processor->matches_breadcrumbs( array( 'span', 'img' ) ); - * true === $processor->matches_breadcrumbs( array( 'span', '*', 'img' ) ); - * - * @since 6.4.0 - * - * @param string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. - * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. - * @return bool Whether the currently-matched tag is found at the given nested structure. - */ - public function matches_breadcrumbs( $breadcrumbs ) { - if ( ! $this->get_tag() ) { - return false; - } - - // Everything matches when there are zero constraints. - if ( 0 === count( $breadcrumbs ) ) { - return true; - } - - // Start at the last crumb. - $crumb = end( $breadcrumbs ); - - if ( '*' !== $crumb && $this->get_tag() !== strtoupper( $crumb ) ) { - return false; - } - - foreach ( $this->state->stack_of_open_elements->walk_up() as $node ) { - $crumb = strtoupper( current( $breadcrumbs ) ); - - if ( '*' !== $crumb && $node->node_name !== $crumb ) { - return false; - } - - if ( false === prev( $breadcrumbs ) ) { - return true; - } - } - - return false; - } - - /** - * Steps through the HTML document and stop at the next tag, if any. - * - * @since 6.4.0 - * - * @throws Exception When unable to allocate a bookmark for the next token in the input HTML document. - * - * @see self::PROCESS_NEXT_NODE - * @see self::REPROCESS_CURRENT_NODE - * - * @param string $node_to_process Whether to parse the next node or reprocess the current node. - * @return bool Whether a tag was matched. - */ - public function step( $node_to_process = self::PROCESS_NEXT_NODE ) { - // Refuse to proceed if there was a previous error. - if ( null !== $this->last_error ) { - return false; - } - - if ( self::PROCESS_NEXT_NODE === $node_to_process ) { - /* - * Void elements still hop onto the stack of open elements even though - * there's no corresponding closing tag. This is important for managing - * stack-based operations such as "navigate to parent node" or checking - * on an element's breadcrumbs. - * - * When moving on to the next node, therefore, if the bottom-most element - * on the stack is a void element, it must be closed. - * - * @TODO: Once self-closing foreign elements and BGSOUND are supported, - * they must also be implicitly closed here too. BGSOUND is - * special since it's only self-closing if the self-closing flag - * is provided in the opening tag, otherwise it expects a tag closer. - */ - $top_node = $this->state->stack_of_open_elements->current_node(); - if ( $top_node && self::is_void( $top_node->node_name ) ) { - $this->state->stack_of_open_elements->pop(); - } - - parent::next_tag( self::VISIT_EVERYTHING ); - } - - // Finish stepping when there are no more tokens in the document. - if ( null === $this->get_tag() ) { - return false; - } - - $this->state->current_token = new WP_HTML_Token( - $this->bookmark_tag(), - $this->get_tag(), - $this->is_tag_closer(), - $this->release_internal_bookmark_on_destruct - ); - - try { - switch ( $this->state->insertion_mode ) { - case WP_HTML_Processor_State::INSERTION_MODE_IN_BODY: - return $this->step_in_body(); - - default: - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." ); - } - } catch ( WP_HTML_Unsupported_Exception $e ) { - /* - * Exceptions are used in this class to escape deep call stacks that - * otherwise might involve messier calling and return conventions. - */ - return false; - } - } - - /** - * Computes the HTML breadcrumbs for the currently-matched node, if matched. - * - * Breadcrumbs start at the outermost parent and descend toward the matched element. - * They always include the entire path from the root HTML node to the matched element. - * - * @TODO: It could be more efficient to expose a generator-based version of this function - * to avoid creating the array copy on tag iteration. If this is done, it would likely - * be more useful to walk up the stack when yielding instead of starting at the top. - * - * Example - * - * $processor = WP_HTML_Processor::create_fragment( '<p><strong><em><img></em></strong></p>' ); - * $processor->next_tag( 'IMG' ); - * $processor->get_breadcrumbs() === array( 'HTML', 'BODY', 'P', 'STRONG', 'EM', 'IMG' ); - * - * @since 6.4.0 - * - * @return string[]|null Array of tag names representing path to matched node, if matched, otherwise NULL. - */ - public function get_breadcrumbs() { - if ( ! $this->get_tag() ) { - return null; - } - - $breadcrumbs = array(); - foreach ( $this->state->stack_of_open_elements->walk_down() as $stack_item ) { - $breadcrumbs[] = $stack_item->node_name; - } - - return $breadcrumbs; - } - - /** - * Parses next element in the 'in body' insertion mode. - * - * This internal function performs the 'in body' insertion mode - * logic for the generalized WP_HTML_Processor::step() function. - * - * @since 6.4.0 - * - * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. - * - * @see https://html.spec.whatwg.org/#parsing-main-inbody - * @see WP_HTML_Processor::step - * - * @return bool Whether an element was found. - */ - private function step_in_body() { - $tag_name = $this->get_tag(); - $op_sigil = $this->is_tag_closer() ? '-' : '+'; - $op = "{$op_sigil}{$tag_name}"; - - switch ( $op ) { - /* - * > A start tag whose tag name is "button" - */ - case '+BUTTON': - if ( $this->state->stack_of_open_elements->has_element_in_scope( 'BUTTON' ) ) { - // @TODO: Indicate a parse error once it's possible. This error does not impact the logic here. - $this->generate_implied_end_tags(); - $this->state->stack_of_open_elements->pop_until( 'BUTTON' ); - } - - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - $this->state->frameset_ok = false; - - return true; - - /* - * > A start tag whose tag name is one of: "address", "article", "aside", - * > "blockquote", "center", "details", "dialog", "dir", "div", "dl", - * > "fieldset", "figcaption", "figure", "footer", "header", "hgroup", - * > "main", "menu", "nav", "ol", "p", "search", "section", "summary", "ul" - */ - case '+BLOCKQUOTE': - case '+DIV': - case '+FIGCAPTION': - case '+FIGURE': - case '+P': - if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { - $this->close_a_p_element(); - } - - $this->insert_html_element( $this->state->current_token ); - return true; - - /* - * > An end tag whose tag name is one of: "address", "article", "aside", "blockquote", - * > "button", "center", "details", "dialog", "dir", "div", "dl", "fieldset", - * > "figcaption", "figure", "footer", "header", "hgroup", "listing", "main", - * > "menu", "nav", "ol", "pre", "search", "section", "summary", "ul" - */ - case '-BLOCKQUOTE': - case '-BUTTON': - case '-DIV': - case '-FIGCAPTION': - case '-FIGURE': - if ( ! $this->state->stack_of_open_elements->has_element_in_scope( $tag_name ) ) { - // @TODO: Report parse error. - // Ignore the token. - return $this->step(); - } - - $this->generate_implied_end_tags(); - if ( $this->state->stack_of_open_elements->current_node()->node_name !== $tag_name ) { - // @TODO: Record parse error: this error doesn't impact parsing. - } - $this->state->stack_of_open_elements->pop_until( $tag_name ); - return true; - - /* - * > An end tag whose tag name is "p" - */ - case '-P': - if ( ! $this->state->stack_of_open_elements->has_p_in_button_scope() ) { - $this->insert_html_element( $this->state->current_token ); - } - - $this->close_a_p_element(); - return true; - - // > A start tag whose tag name is "a" - case '+A': - foreach ( $this->state->active_formatting_elements->walk_up() as $item ) { - switch ( $item->node_name ) { - case 'marker': - break; - - case 'A': - $this->run_adoption_agency_algorithm(); - $this->state->active_formatting_elements->remove_node( $item ); - $this->state->stack_of_open_elements->remove_node( $item ); - break; - } - } - - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - $this->state->active_formatting_elements->push( $this->state->current_token ); - return true; - - /* - * > A start tag whose tag name is one of: "b", "big", "code", "em", "font", "i", - * > "s", "small", "strike", "strong", "tt", "u" - */ - case '+B': - case '+BIG': - case '+CODE': - case '+EM': - case '+FONT': - case '+I': - case '+S': - case '+SMALL': - case '+STRIKE': - case '+STRONG': - case '+TT': - case '+U': - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - $this->state->active_formatting_elements->push( $this->state->current_token ); - return true; - - /* - * > An end tag whose tag name is one of: "a", "b", "big", "code", "em", "font", "i", - * > "nobr", "s", "small", "strike", "strong", "tt", "u" - */ - case '-A': - case '-B': - case '-BIG': - case '-CODE': - case '-EM': - case '-FONT': - case '-I': - case '-S': - case '-SMALL': - case '-STRIKE': - case '-STRONG': - case '-TT': - case '-U': - $this->run_adoption_agency_algorithm(); - return true; - - /* - * > A start tag whose tag name is one of: "area", "br", "embed", "img", "keygen", "wbr" - */ - case '+IMG': - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - return true; - - /* - * > Any other start tag - */ - case '+SPAN': - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - return true; - - /* - * Any other end tag - */ - case '-SPAN': - foreach ( $this->state->stack_of_open_elements->walk_up() as $item ) { - // > If node is an HTML element with the same tag name as the token, then: - if ( $item->node_name === $tag_name ) { - $this->generate_implied_end_tags( $tag_name ); - - // > If node is not the current node, then this is a parse error. - - $this->state->stack_of_open_elements->pop_until( $tag_name ); - return true; - } - - // > Otherwise, if node is in the special category, then this is a parse error; ignore the token, and return. - if ( self::is_special( $item->node_name ) ) { - return $this->step(); - } - } - // Execution should not reach here; if it does then something went wrong. - return false; - - default: - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( "Cannot process {$tag_name} element." ); - } - } - - /* - * Internal helpers - */ - - /** - * Creates a new bookmark for the currently-matched tag and returns the generated name. - * - * @since 6.4.0 - * - * @throws Exception When unable to allocate requested bookmark. - * - * @return string|false Name of created bookmark, or false if unable to create. - */ - private function bookmark_tag() { - if ( ! $this->get_tag() ) { - return false; - } - - if ( ! parent::set_bookmark( ++$this->bookmark_counter ) ) { - $this->last_error = self::ERROR_EXCEEDED_MAX_BOOKMARKS; - throw new Exception( 'could not allocate bookmark' ); - } - - return "{$this->bookmark_counter}"; - } - - /* - * HTML semantic overrides for Tag Processor - */ - - /** - * Returns the uppercase name of the matched tag. - * - * The semantic rules for HTML specify that certain tags be reprocessed - * with a different tag name. Because of this, the tag name presented - * by the HTML Processor may differ from the one reported by the HTML - * Tag Processor, which doesn't apply these semantic rules. - * - * Example: - * - * $processor = new WP_HTML_Tag_Processor( '<div class="test">Test</div>' ); - * $processor->next_tag() === true; - * $processor->get_tag() === 'DIV'; - * - * $processor->next_tag() === false; - * $processor->get_tag() === null; - * - * @since 6.4.0 - * - * @return string|null Name of currently matched tag in input HTML, or `null` if none found. - */ - public function get_tag() { - if ( null !== $this->last_error ) { - return null; - } - - $tag_name = parent::get_tag(); - - switch ( $tag_name ) { - case 'IMAGE': - /* - * > A start tag whose tag name is "image" - * > Change the token's tag name to "img" and reprocess it. (Don't ask.) - */ - return 'IMG'; - - default: - return $tag_name; - } - } - - /** - * Removes a bookmark that is no longer needed. - * - * Releasing a bookmark frees up the small - * performance overhead it requires. - * - * @since 6.4.0 - * - * @param string $bookmark_name Name of the bookmark to remove. - * @return bool Whether the bookmark already existed before removal. - */ - public function release_bookmark( $bookmark_name ) { - return parent::release_bookmark( "_{$bookmark_name}" ); - } - - /** - * Moves the internal cursor in the HTML Processor to a given bookmark's location. - * - * In order to prevent accidental infinite loops, there's a - * maximum limit on the number of times seek() can be called. - * - * @throws Exception When unable to allocate a bookmark for the next token in the input HTML document. - * - * @since 6.4.0 - * - * @param string $bookmark_name Jump to the place in the document identified by this bookmark name. - * @return bool Whether the internal cursor was successfully moved to the bookmark's location. - */ - public function seek( $bookmark_name ) { - $actual_bookmark_name = "_{$bookmark_name}"; - $processor_started_at = $this->state->current_token - ? $this->bookmarks[ $this->state->current_token->bookmark_name ]->start - : 0; - $bookmark_starts_at = $this->bookmarks[ $actual_bookmark_name ]->start; - $direction = $bookmark_starts_at > $processor_started_at ? 'forward' : 'backward'; - - switch ( $direction ) { - case 'forward': - // When moving forwards, re-parse the document until reaching the same location as the original bookmark. - while ( $this->step() ) { - if ( $bookmark_starts_at === $this->bookmarks[ $this->state->current_token->bookmark_name ]->start ) { - return true; - } - } - - return false; - - case 'backward': - /* - * When moving backwards, clear out all existing stack entries which appear after the destination - * bookmark. These could be stored for later retrieval, but doing so would require additional - * memory overhead and also demand that references and bookmarks are updated as the document - * changes. In time this could be a valuable optimization, but it's okay to give up that - * optimization in exchange for more CPU time to recompute the stack, to re-parse the - * document that may have already been parsed once. - */ - foreach ( $this->state->stack_of_open_elements->walk_up() as $item ) { - if ( $bookmark_starts_at >= $this->bookmarks[ $item->bookmark_name ]->start ) { - break; - } - - $this->state->stack_of_open_elements->remove_node( $item ); - } - - foreach ( $this->state->active_formatting_elements->walk_up() as $item ) { - if ( $bookmark_starts_at >= $this->bookmarks[ $item->bookmark_name ]->start ) { - break; - } - - $this->state->active_formatting_elements->remove_node( $item ); - } - - return parent::seek( $actual_bookmark_name ); - } - } - - /** - * Sets a bookmark in the HTML document. - * - * Bookmarks represent specific places or tokens in the HTML - * document, such as a tag opener or closer. When applying - * edits to a document, such as setting an attribute, the - * text offsets of that token may shift; the bookmark is - * kept updated with those shifts and remains stable unless - * the entire span of text in which the token sits is removed. - * - * Release bookmarks when they are no longer needed. - * - * Example: - * - * <main><h2>Surprising fact you may not know!</h2></main> - * ^ ^ - * \-|-- this `H2` opener bookmark tracks the token - * - * <main class="clickbait"><h2>Surprising fact you may no… - * ^ ^ - * \-|-- it shifts with edits - * - * Bookmarks provide the ability to seek to a previously-scanned - * place in the HTML document. This avoids the need to re-scan - * the entire document. - * - * Example: - * - * <ul><li>One</li><li>Two</li><li>Three</li></ul> - * ^^^^ - * want to note this last item - * - * $p = new WP_HTML_Tag_Processor( $html ); - * $in_list = false; - * while ( $p->next_tag( array( 'tag_closers' => $in_list ? 'visit' : 'skip' ) ) ) { - * if ( 'UL' === $p->get_tag() ) { - * if ( $p->is_tag_closer() ) { - * $in_list = false; - * $p->set_bookmark( 'resume' ); - * if ( $p->seek( 'last-li' ) ) { - * $p->add_class( 'last-li' ); - * } - * $p->seek( 'resume' ); - * $p->release_bookmark( 'last-li' ); - * $p->release_bookmark( 'resume' ); - * } else { - * $in_list = true; - * } - * } - * - * if ( 'LI' === $p->get_tag() ) { - * $p->set_bookmark( 'last-li' ); - * } - * } - * - * Bookmarks intentionally hide the internal string offsets - * to which they refer. They are maintained internally as - * updates are applied to the HTML document and therefore - * retain their "position" - the location to which they - * originally pointed. The inability to use bookmarks with - * functions like `substr` is therefore intentional to guard - * against accidentally breaking the HTML. - * - * Because bookmarks allocate memory and require processing - * for every applied update, they are limited and require - * a name. They should not be created with programmatically-made - * names, such as "li_{$index}" with some loop. As a general - * rule they should only be created with string-literal names - * like "start-of-section" or "last-paragraph". - * - * Bookmarks are a powerful tool to enable complicated behavior. - * Consider double-checking that you need this tool if you are - * reaching for it, as inappropriate use could lead to broken - * HTML structure or unwanted processing overhead. - * - * @since 6.4.0 - * - * @param string $bookmark_name Identifies this particular bookmark. - * @return bool Whether the bookmark was successfully created. - */ - public function set_bookmark( $bookmark_name ) { - return parent::set_bookmark( "_{$bookmark_name}" ); - } - - /* - * HTML Parsing Algorithms - */ - - /** - * Closes a P element. - * - * @since 6.4.0 - * - * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. - * - * @see https://html.spec.whatwg.org/#close-a-p-element - */ - private function close_a_p_element() { - $this->generate_implied_end_tags( 'P' ); - $this->state->stack_of_open_elements->pop_until( 'P' ); - } - - /** - * Closes elements that have implied end tags. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#generate-implied-end-tags - * - * @param string|null $except_for_this_element Perform as if this element doesn't exist in the stack of open elements. - */ - private function generate_implied_end_tags( $except_for_this_element = null ) { - $elements_with_implied_end_tags = array( - 'P', - ); - - $current_node = $this->state->stack_of_open_elements->current_node(); - while ( - $current_node && $current_node->node_name !== $except_for_this_element && - in_array( $this->state->stack_of_open_elements->current_node(), $elements_with_implied_end_tags, true ) - ) { - $this->state->stack_of_open_elements->pop(); - } - } - - /** - * Closes elements that have implied end tags, thoroughly. - * - * See the HTML specification for an explanation why this is - * different from generating end tags in the normal sense. - * - * @since 6.4.0 - * - * @see WP_HTML_Processor::generate_implied_end_tags - * @see https://html.spec.whatwg.org/#generate-implied-end-tags - */ - private function generate_implied_end_tags_thoroughly() { - $elements_with_implied_end_tags = array( - 'P', - ); - - while ( in_array( $this->state->stack_of_open_elements->current_node(), $elements_with_implied_end_tags, true ) ) { - $this->state->stack_of_open_elements->pop(); - } - } - - /** - * Reconstructs the active formatting elements. - * - * > This has the effect of reopening all the formatting elements that were opened - * > in the current body, cell, or caption (whichever is youngest) that haven't - * > been explicitly closed. - * - * @since 6.4.0 - * - * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. - * - * @see https://html.spec.whatwg.org/#reconstruct-the-active-formatting-elements - * - * @return bool Whether any formatting elements needed to be reconstructed. - */ - private function reconstruct_active_formatting_elements() { - /* - * > If there are no entries in the list of active formatting elements, then there is nothing - * > to reconstruct; stop this algorithm. - */ - if ( 0 === $this->state->active_formatting_elements->count() ) { - return false; - } - - $last_entry = $this->state->active_formatting_elements->current_node(); - if ( - - /* - * > If the last (most recently added) entry in the list of active formatting elements is a marker; - * > stop this algorithm. - */ - 'marker' === $last_entry->node_name || - - /* - * > If the last (most recently added) entry in the list of active formatting elements is an - * > element that is in the stack of open elements, then there is nothing to reconstruct; - * > stop this algorithm. - */ - $this->state->stack_of_open_elements->contains_node( $last_entry ) - ) { - return false; - } - - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( 'Cannot reconstruct active formatting elements when advancing and rewinding is required.' ); - } - - /** - * Runs the adoption agency algorithm. - * - * @since 6.4.0 - * - * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. - * - * @see https://html.spec.whatwg.org/#adoption-agency-algorithm - */ - private function run_adoption_agency_algorithm() { - $budget = 1000; - $subject = $this->get_tag(); - $current_node = $this->state->stack_of_open_elements->current_node(); - - if ( - // > If the current node is an HTML element whose tag name is subject - $current_node && $subject === $current_node->node_name && - // > the current node is not in the list of active formatting elements - ! $this->state->active_formatting_elements->contains_node( $current_node ) - ) { - $this->state->stack_of_open_elements->pop(); - return; - } - - $outer_loop_counter = 0; - while ( $budget-- > 0 ) { - if ( $outer_loop_counter++ >= 8 ) { - return; - } - - /* - * > Let formatting element be the last element in the list of active formatting elements that: - * > - is between the end of the list and the last marker in the list, - * > if any, or the start of the list otherwise, - * > - and has the tag name subject. - */ - $formatting_element = null; - foreach ( $this->state->active_formatting_elements->walk_up() as $item ) { - if ( 'marker' === $item->node_name ) { - break; - } - - if ( $subject === $item->node_name ) { - $formatting_element = $item; - break; - } - } - - // > If there is no such element, then return and instead act as described in the "any other end tag" entry above. - if ( null === $formatting_element ) { - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( 'Cannot run adoption agency when "any other end tag" is required.' ); - } - - // > If formatting element is not in the stack of open elements, then this is a parse error; remove the element from the list, and return. - if ( ! $this->state->stack_of_open_elements->contains_node( $formatting_element ) ) { - $this->state->active_formatting_elements->remove_node( $formatting_element->bookmark_name ); - return; - } - - // > If formatting element is in the stack of open elements, but the element is not in scope, then this is a parse error; return. - if ( ! $this->state->stack_of_open_elements->has_element_in_scope( $formatting_element->node_name ) ) { - return; - } - - /* - * > Let furthest block be the topmost node in the stack of open elements that is lower in the stack - * > than formatting element, and is an element in the special category. There might not be one. - */ - $is_above_formatting_element = true; - $furthest_block = null; - foreach ( $this->state->stack_of_open_elements->walk_down() as $item ) { - if ( $is_above_formatting_element && $formatting_element->bookmark_name !== $item->bookmark_name ) { - continue; - } - - if ( $is_above_formatting_element ) { - $is_above_formatting_element = false; - continue; - } - - if ( self::is_special( $item->node_name ) ) { - $furthest_block = $item; - break; - } - } - - /* - * > If there is no furthest block, then the UA must first pop all the nodes from the bottom of the - * > stack of open elements, from the current node up to and including formatting element, then - * > remove formatting element from the list of active formatting elements, and finally return. - */ - if ( null === $furthest_block ) { - foreach ( $this->state->stack_of_open_elements->walk_up() as $item ) { - $this->state->stack_of_open_elements->pop(); - - if ( $formatting_element->bookmark_name === $item->bookmark_name ) { - $this->state->active_formatting_elements->remove_node( $formatting_element ); - return; - } - } - } - - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( 'Cannot extract common ancestor in adoption agency algorithm.' ); - } - - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( 'Cannot run adoption agency when looping required.' ); - } - - /** - * Inserts an HTML element on the stack of open elements. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#insert-a-foreign-element - * - * @param WP_HTML_Token $token Name of bookmark pointing to element in original input HTML. - */ - private function insert_html_element( $token ) { - $this->state->stack_of_open_elements->push( $token ); - } - - /* - * HTML Specification Helpers - */ - - /** - * Returns whether an element of a given name is in the HTML special category. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#special - * - * @param string $tag_name Name of element to check. - * @return bool Whether the element of the given name is in the special category. - */ - public static function is_special( $tag_name ) { - $tag_name = strtoupper( $tag_name ); - - return ( - 'ADDRESS' === $tag_name || - 'APPLET' === $tag_name || - 'AREA' === $tag_name || - 'ARTICLE' === $tag_name || - 'ASIDE' === $tag_name || - 'BASE' === $tag_name || - 'BASEFONT' === $tag_name || - 'BGSOUND' === $tag_name || - 'BLOCKQUOTE' === $tag_name || - 'BODY' === $tag_name || - 'BR' === $tag_name || - 'BUTTON' === $tag_name || - 'CAPTION' === $tag_name || - 'CENTER' === $tag_name || - 'COL' === $tag_name || - 'COLGROUP' === $tag_name || - 'DD' === $tag_name || - 'DETAILS' === $tag_name || - 'DIR' === $tag_name || - 'DIV' === $tag_name || - 'DL' === $tag_name || - 'DT' === $tag_name || - 'EMBED' === $tag_name || - 'FIELDSET' === $tag_name || - 'FIGCAPTION' === $tag_name || - 'FIGURE' === $tag_name || - 'FOOTER' === $tag_name || - 'FORM' === $tag_name || - 'FRAME' === $tag_name || - 'FRAMESET' === $tag_name || - 'H1' === $tag_name || - 'H2' === $tag_name || - 'H3' === $tag_name || - 'H4' === $tag_name || - 'H5' === $tag_name || - 'H6' === $tag_name || - 'HEAD' === $tag_name || - 'HEADER' === $tag_name || - 'HGROUP' === $tag_name || - 'HR' === $tag_name || - 'HTML' === $tag_name || - 'IFRAME' === $tag_name || - 'IMG' === $tag_name || - 'INPUT' === $tag_name || - 'KEYGEN' === $tag_name || - 'LI' === $tag_name || - 'LINK' === $tag_name || - 'LISTING' === $tag_name || - 'MAIN' === $tag_name || - 'MARQUEE' === $tag_name || - 'MENU' === $tag_name || - 'META' === $tag_name || - 'NAV' === $tag_name || - 'NOEMBED' === $tag_name || - 'NOFRAMES' === $tag_name || - 'NOSCRIPT' === $tag_name || - 'OBJECT' === $tag_name || - 'OL' === $tag_name || - 'P' === $tag_name || - 'PARAM' === $tag_name || - 'PLAINTEXT' === $tag_name || - 'PRE' === $tag_name || - 'SCRIPT' === $tag_name || - 'SEARCH' === $tag_name || - 'SECTION' === $tag_name || - 'SELECT' === $tag_name || - 'SOURCE' === $tag_name || - 'STYLE' === $tag_name || - 'SUMMARY' === $tag_name || - 'TABLE' === $tag_name || - 'TBODY' === $tag_name || - 'TD' === $tag_name || - 'TEMPLATE' === $tag_name || - 'TEXTAREA' === $tag_name || - 'TFOOT' === $tag_name || - 'TH' === $tag_name || - 'THEAD' === $tag_name || - 'TITLE' === $tag_name || - 'TR' === $tag_name || - 'TRACK' === $tag_name || - 'UL' === $tag_name || - 'WBR' === $tag_name || - 'XMP' === $tag_name || - - // MathML. - 'MI' === $tag_name || - 'MO' === $tag_name || - 'MN' === $tag_name || - 'MS' === $tag_name || - 'MTEXT' === $tag_name || - 'ANNOTATION-XML' === $tag_name || - - // SVG. - 'FOREIGNOBJECT' === $tag_name || - 'DESC' === $tag_name || - 'TITLE' === $tag_name - ); - } - - /** - * Returns whether a given element is an HTML Void Element - * - * > area, base, br, col, embed, hr, img, input, link, meta, source, track, wbr - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#void-elements - * - * @param string $tag_name Name of HTML tag to check. - * @return bool Whether the given tag is an HTML Void Element. - */ - public static function is_void( $tag_name ) { - $tag_name = strtoupper( $tag_name ); - - return ( - 'AREA' === $tag_name || - 'BASE' === $tag_name || - 'BR' === $tag_name || - 'COL' === $tag_name || - 'EMBED' === $tag_name || - 'HR' === $tag_name || - 'IMG' === $tag_name || - 'INPUT' === $tag_name || - 'LINK' === $tag_name || - 'META' === $tag_name || - 'SOURCE' === $tag_name || - 'TRACK' === $tag_name || - 'WBR' === $tag_name - ); - } - - /* - * Constants that would pollute the top of the class if they were found there. - */ - - /** - * Indicates that the next HTML token should be parsed and processed. - * - * @since 6.4.0 - * - * @var string - */ - const PROCESS_NEXT_NODE = 'process-next-node'; - - /** - * Indicates that the current HTML token should be reprocessed in the newly-selected insertion mode. - * - * @since 6.4.0 - * - * @var string - */ - const REPROCESS_CURRENT_NODE = 'reprocess-current-node'; - - /** - * Indicates that the parser encountered unsupported markup and has bailed. - * - * @since 6.4.0 - * - * @var string - */ - const ERROR_UNSUPPORTED = 'unsupported'; - - /** - * Indicates that the parser encountered more HTML tokens than it - * was able to process and has bailed. - * - * @since 6.4.0 - * - * @var string - */ - const ERROR_EXCEEDED_MAX_BOOKMARKS = 'exceeded-max-bookmarks'; - - /** - * Unlock code that must be passed into the constructor to create this class. - * - * This class extends the WP_HTML_Tag_Processor, which has a public class - * constructor. Therefore, it's not possible to have a private constructor here. - * - * This unlock code is used to ensure that anyone calling the constructor is - * doing so with a full understanding that it's intended to be a private API. - * - * @access private - */ - const CONSTRUCTOR_UNLOCK_CODE = 'Use WP_HTML_Processor::create_fragment() instead of calling the class constructor directly.'; - } -} diff --git a/lib/compat/wordpress-6.4/html-api/class-wp-html-token.php b/lib/compat/wordpress-6.4/html-api/class-wp-html-token.php deleted file mode 100644 index 87446f4533572b..00000000000000 --- a/lib/compat/wordpress-6.4/html-api/class-wp-html-token.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Token class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.4.0 - */ - -if ( ! class_exists( 'WP_HTML_Token' ) ) { - - /** - * Core class used by the HTML processor during HTML parsing - * for referring to tokens in the input HTML string. - * - * This class is designed for internal use by the HTML processor. - * - * @since 6.4.0 - * - * @access private - * - * @see WP_HTML_Processor - */ - class WP_HTML_Token { - /** - * Name of bookmark corresponding to source of token in input HTML string. - * - * Having a bookmark name does not imply that the token still exists. It - * may be that the source token and underlying bookmark was wiped out by - * some modification to the source HTML. - * - * @since 6.4.0 - * - * @var string - */ - public $bookmark_name = null; - - /** - * Name of node; lowercase names such as "marker" are not HTML elements. - * - * For HTML elements/tags this value should come from WP_HTML_Processor::get_tag(). - * - * @since 6.4.0 - * - * @see WP_HTML_Processor::get_tag() - * - * @var string - */ - public $node_name = null; - - /** - * Whether node contains the self-closing flag. - * - * A node may have a self-closing flag when it shouldn't. This value - * only reports if the flag is present in the original HTML. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#self-closing-flag - * - * @var bool - */ - public $has_self_closing_flag = false; - - /** - * Called when token is garbage-collected or otherwise destroyed. - * - * @var callable|null - */ - public $on_destroy = null; - - /** - * Constructor - creates a reference to a token in some external HTML string. - * - * @since 6.4.0 - * - * @param string $bookmark_name Name of bookmark corresponding to location in HTML where token is found. - * @param string $node_name Name of node token represents; if uppercase, an HTML element; if lowercase, a special value like "marker". - * @param bool $has_self_closing_flag Whether the source token contains the self-closing flag, regardless of whether it's valid. - * @param callable $on_destroy Function to call when destroying token, useful for releasing the bookmark. - */ - public function __construct( $bookmark_name, $node_name, $has_self_closing_flag, $on_destroy = null ) { - $this->bookmark_name = $bookmark_name; - $this->node_name = $node_name; - $this->has_self_closing_flag = $has_self_closing_flag; - $this->on_destroy = $on_destroy; - } - - /** - * Destructor. - * - * @since 6.4.0 - */ - public function __destruct() { - if ( is_callable( $this->on_destroy ) ) { - call_user_func( $this->on_destroy, $this->bookmark_name ); - } - } - - /** - * Wakeup magic method. - * - * @since 6.4.2 - */ - public function __wakeup() { - throw new \LogicException( __CLASS__ . ' should never be unserialized' ); - } - } -} diff --git a/lib/compat/wordpress-6.4/html-api/class-wp-html-unsupported-exception.php b/lib/compat/wordpress-6.4/html-api/class-wp-html-unsupported-exception.php deleted file mode 100644 index 7a84a084b2e6ce..00000000000000 --- a/lib/compat/wordpress-6.4/html-api/class-wp-html-unsupported-exception.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Unsupported_Exception class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.4.0 - */ - -if ( ! class_exists( 'WP_HTML_Unsupported_Exception' ) ) { - - /** - * Core class used by the HTML processor during HTML parsing - * for indicating that a given operation is unsupported. - * - * This class is designed for internal use by the HTML processor. - * - * The HTML API aims to operate in compliance with the HTML5 - * specification, but does not implement the full specification. - * In cases where it lacks support it should not cause breakage - * or unexpected behavior. In the cases where it recognizes that - * it cannot proceed, this class is used to abort from any - * operation and signify that the given HTML cannot be processed. - * - * @since 6.4.0 - * - * @access private - * - * @see WP_HTML_Processor - */ - class WP_HTML_Unsupported_Exception extends Exception { - - } -} diff --git a/lib/compat/wordpress-6.4/kses.php b/lib/compat/wordpress-6.4/kses.php deleted file mode 100644 index 019d1cc9b06dbf..00000000000000 --- a/lib/compat/wordpress-6.4/kses.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php -/** - * Temporary compatibility shims for block APIs present in Gutenberg. - * - * @package gutenberg - */ - -/** - * Update allowed inline style attributes list. - * - * @param string[] $attrs Array of allowed CSS attributes. - * @return string[] CSS attributes. - */ -function gutenberg_safe_style_attrs_6_4( $attrs ) { - $attrs[] = 'writing-mode'; - return $attrs; -} -add_filter( 'safe_style_css', 'gutenberg_safe_style_attrs_6_4' ); diff --git a/lib/compat/wordpress-6.4/rest-api.php b/lib/compat/wordpress-6.4/rest-api.php deleted file mode 100644 index 1c62b1780d1e45..00000000000000 --- a/lib/compat/wordpress-6.4/rest-api.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php -/** - * PHP and WordPress configuration compatibility functions for the Gutenberg - * editor plugin changes related to REST API. - * - * @package gutenberg - */ - -if ( ! defined( 'ABSPATH' ) ) { - die( 'Silence is golden.' ); -} - -/** - * Registers the block patterns REST API routes. - */ -function gutenberg_register_rest_block_patterns_routes() { - $block_patterns = new Gutenberg_REST_Block_Patterns_Controller(); - $block_patterns->register_routes(); -} -add_action( 'rest_api_init', 'gutenberg_register_rest_block_patterns_routes' ); - - -if ( ! function_exists( 'wp_api_template_revision_args' ) ) { - /** - * Hook in to the template and template part post types and decorate - * the rest endpoint with the revision count. - * - * @param array $args Current registered post type args. - * @param string $post_type Name of post type. - * - * @return array - */ - function wp_api_template_revision_args( $args, $post_type ) { - if ( 'wp_template' === $post_type || 'wp_template_part' === $post_type ) { - $args['rest_controller_class'] = 'Gutenberg_REST_Templates_Controller_6_4'; - } - return $args; - } -} -add_filter( 'register_post_type_args', 'wp_api_template_revision_args', 10, 2 ); diff --git a/lib/compat/wordpress-6.4/script-loader.php b/lib/compat/wordpress-6.4/script-loader.php deleted file mode 100644 index 60de7785aaeb22..00000000000000 --- a/lib/compat/wordpress-6.4/script-loader.php +++ /dev/null @@ -1,112 +0,0 @@ -<?php -/** - * Updates the script-loader.php file - * - * @package gutenberg - */ - -/** - * Collect the block editor assets that need to be loaded into the editor's iframe. - * - * @since 6.0.0 - * @access private - * - * @global WP_Styles $wp_styles - * @global WP_Scripts $wp_scripts - * - * @return array { - * The block editor assets. - * - * @type string|false $styles String containing the HTML for styles. - * @type string|false $scripts String containing the HTML for scripts. - * } - */ -function _gutenberg_get_iframed_editor_assets_6_4() { - global $wp_styles, $wp_scripts; - - // Keep track of the styles and scripts instance to restore later. - $current_wp_styles = $wp_styles; - $current_wp_scripts = $wp_scripts; - - // Create new instances to collect the assets. - $wp_styles = new WP_Styles(); - $wp_scripts = new WP_Scripts(); - - // Register all currently registered styles and scripts. The actions that - // follow enqueue assets, but don't necessarily register them. - $wp_styles->registered = $current_wp_styles->registered; - $wp_scripts->registered = $current_wp_scripts->registered; - - // We generally do not need reset styles for the iframed editor. - // However, if it's a classic theme, margins will be added to every block, - // which is reset specifically for list items, so classic themes rely on - // these reset styles. - $wp_styles->done = - wp_theme_has_theme_json() ? array( 'wp-reset-editor-styles' ) : array(); - - wp_enqueue_script( 'wp-polyfill' ); - // Enqueue the `editorStyle` handles for all core block, and dependencies. - wp_enqueue_style( 'wp-edit-blocks' ); - - if ( current_theme_supports( 'wp-block-styles' ) ) { - wp_enqueue_style( 'wp-block-library-theme' ); - } - - // We don't want to load EDITOR scripts in the iframe, only enqueue - // front-end assets for the content. - add_filter( 'should_load_block_editor_scripts_and_styles', '__return_false' ); - do_action( 'enqueue_block_assets' ); - remove_filter( 'should_load_block_editor_scripts_and_styles', '__return_false' ); - - $block_registry = WP_Block_Type_Registry::get_instance(); - - // Additionally, do enqueue `editorStyle` assets for all blocks, which - // contains editor-only styling for blocks (editor content). - foreach ( $block_registry->get_all_registered() as $block_type ) { - if ( isset( $block_type->editor_style_handles ) && is_array( $block_type->editor_style_handles ) ) { - foreach ( $block_type->editor_style_handles as $style_handle ) { - wp_enqueue_style( $style_handle ); - } - } - } - - /** - * Remove the deprecated `print_emoji_styles` handler. - * It avoids breaking style generation with a deprecation message. - */ - $has_emoji_styles = has_action( 'wp_print_styles', 'print_emoji_styles' ); - if ( $has_emoji_styles ) { - remove_action( 'wp_print_styles', 'print_emoji_styles' ); - } - - ob_start(); - wp_print_styles(); - $styles = ob_get_clean(); - - if ( $has_emoji_styles ) { - add_action( 'wp_print_styles', 'print_emoji_styles' ); - } - - ob_start(); - wp_print_head_scripts(); - wp_print_footer_scripts(); - $scripts = ob_get_clean(); - - // Restore the original instances. - $wp_styles = $current_wp_styles; - $wp_scripts = $current_wp_scripts; - - return array( - 'styles' => $styles, - 'scripts' => $scripts, - ); -} - -add_filter( - 'block_editor_settings_all', - static function ( $settings ) { - // We must override what core is passing now. - $settings['__unstableResolvedAssets'] = _gutenberg_get_iframed_editor_assets_6_4(); - return $settings; - } -); diff --git a/lib/compat/wordpress-6.4/theme-previews.php b/lib/compat/wordpress-6.4/theme-previews.php deleted file mode 100644 index 5755fc992921d4..00000000000000 --- a/lib/compat/wordpress-6.4/theme-previews.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php -/** - * Enable theme previews in the Site Editor for block themes. - * - * @package gutenberg - */ - -/** - * Allow developers to customize the back to dashboard link in the Site Editor - * - * @param array $settings The editor settings. - * @return array The editor settings. - */ -function gutenberg_theme_preview_block_editor_settings_all( $settings ) { - $settings['__experimentalDashboardLink'] = 'themes.php'; - $settings['__experimentalDashboardLinkText'] = __( 'Go back to the theme showcase' ); - return $settings; -} - -/** - * Attaches filters to enable theme previews in the Site Editor. - * This would go inside of `initialize_theme_preview_hooks` - * to avoid the global scope when we port this to the core. - */ -if ( ! empty( $_GET['wp_theme_preview'] ) ) { - add_filter( 'block_editor_settings_all', 'gutenberg_theme_preview_block_editor_settings_all' ); -} diff --git a/lib/compat/wordpress-6.5/block-bindings/block-bindings.php b/lib/compat/wordpress-6.5/block-bindings/block-bindings.php deleted file mode 100644 index cc26fe50d02fd6..00000000000000 --- a/lib/compat/wordpress-6.5/block-bindings/block-bindings.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php -/** - * Block Bindings API - * - * Contains functions for managing block bindings in WordPress. - * - * @package WordPress - * @subpackage Block Bindings - * @since 6.5.0 - */ - -/** - * Registers a new block bindings source. - * - * Sources are used to override block's original attributes with a value - * coming from the source. Once a source is registered, it can be used by a - * block by setting its `metadata.bindings` attribute to a value that refers - * to the source. - * - * @since 6.5.0 - * - * @param string $source_name The name of the source. It must be a string containing a namespace prefix, i.e. - * `my-plugin/my-custom-source`. It must only contain lowercase alphanumeric - * characters, the forward slash `/` and dashes. - * @param array $source_properties { - * The array of arguments that are used to register a source. - * - * @type string $label The label of the source. - * @type callback $get_value_callback A callback executed when the source is processed during block rendering. - * The callback should have the following signature: - * - * `function ($source_args, $block_instance,$attribute_name): mixed` - * - @param array $source_args Array containing source arguments - * used to look up the override value, - * i.e. {"key": "foo"}. - * - @param WP_Block $block_instance The block instance. - * - @param string $attribute_name The name of an attribute . - * The callback has a mixed return type; it may return a string to override - * the block's original value, null, false to remove an attribute, etc. - * @type array $uses_context (optional) Array of values to add to block `uses_context` needed by the source. - * } - * @return WP_Block_Bindings_Source|false Source when the registration was successful, or `false` on failure. - */ -if ( ! function_exists( 'register_block_bindings_source' ) ) { - function register_block_bindings_source( string $source_name, array $source_properties ) { - return WP_Block_Bindings_Registry::get_instance()->register( $source_name, $source_properties ); - } -} - -/** - * Unregisters a block bindings source. - * - * @since 6.5.0 - * - * @param string $source_name Block bindings source name including namespace. - * @return WP_Block_Bindings_Source|false The unregistered block bindings source on success and `false` otherwise. - */ -if ( ! function_exists( 'unregister_block_bindings_source' ) ) { - function unregister_block_bindings_source( string $source_name ) { - return WP_Block_Bindings_Registry::get_instance()->unregister( $source_name ); - } -} - -/** - * Retrieves the list of all registered block bindings sources. - * - * @since 6.5.0 - * - * @return WP_Block_Bindings_Source The array of registered block bindings sources. - */ -if ( ! function_exists( 'get_all_registered_block_bindings_sources' ) ) { - function get_all_registered_block_bindings_sources() { - return WP_Block_Bindings_Registry::get_instance()->get_all_registered(); - } -} - -/** - * Retrieves a registered block bindings source. - * - * @since 6.5.0 - * - * @param string $source_name The name of the source. - * @return WP_Block_Bindings_Source|null The registered block bindings source, or `null` if it is not registered. - */ -if ( ! function_exists( 'get_block_bindings_source' ) ) { - function get_block_bindings_source( string $source_name ) { - return WP_Block_Bindings_Registry::get_instance()->get_registered( $source_name ); - } -} diff --git a/lib/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-registry.php b/lib/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-registry.php deleted file mode 100644 index 8eb6f5271adf69..00000000000000 --- a/lib/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-registry.php +++ /dev/null @@ -1,288 +0,0 @@ -<?php -/** - * Block Bindings API: WP_Block_Bindings_Registry class. - * - * Supports overriding content in blocks by connecting them to different sources. - * - * @package WordPress - * @subpackage Block Bindings - * @since 6.5.0 - */ - -/** - * Class used for interacting with block bindings sources. - * - * @since 6.5.0 - */ -if ( ! class_exists( 'WP_Block_Bindings_Registry' ) ) { - final class WP_Block_Bindings_Registry { - /** - * Holds the registered block bindings sources, keyed by source identifier. - * - * @since 6.5.0 - * @var WP_Block_Bindings_Source[] - */ - private $sources = array(); - - /** - * Container for the main instance of the class. - * - * @since 6.5.0 - * @var WP_Block_Bindings_Registry|null - */ - private static $instance = null; - - /** - * Supported source properties that can be passed to the registered source. - * - * @since 6.5.0 - * @var array - */ - private $allowed_source_properties = array( - 'label', - 'get_value_callback', - 'uses_context', - ); - - /** - * Supported blocks that can use the block bindings API. - * - * @since 6.5.0 - * @var array - */ - private $supported_blocks = array( - 'core/paragraph', - 'core/heading', - 'core/image', - 'core/button', - ); - - /** - * Registers a new block bindings source. - * - * Sources are used to override block's original attributes with a value - * coming from the source. Once a source is registered, it can be used by a - * block by setting its `metadata.bindings` attribute to a value that refers - * to the source. - * - * @since 6.5.0 - * - * @param string $source_name The name of the source. It must be a string containing a namespace prefix, i.e. - * `my-plugin/my-custom-source`. It must only contain lowercase alphanumeric - * characters, the forward slash `/` and dashes. - * @param array $source_properties { - * The array of arguments that are used to register a source. - * - * @type string $label The label of the source. - * @type callback $get_value_callback A callback executed when the source is processed during block rendering. - * The callback should have the following signature: - * - * `function ($source_args, $block_instance,$attribute_name): mixed` - * - @param array $source_args Array containing source arguments - * used to look up the override value, - * i.e. {"key": "foo"}. - * - @param WP_Block $block_instance The block instance. - * - @param string $attribute_name The name of the target attribute. - * The callback has a mixed return type; it may return a string to override - * the block's original value, null, false to remove an attribute, etc. - * @type array $uses_context (optional) Array of values to add to block `uses_context` needed by the source. - * } - * @return WP_Block_Bindings_Source|false Source when the registration was successful, or `false` on failure. - */ - public function register( string $source_name, array $source_properties ) { - if ( ! is_string( $source_name ) ) { - _doing_it_wrong( - __METHOD__, - __( 'Block bindings source name must be a string.' ), - '6.5.0' - ); - return false; - } - - if ( preg_match( '/[A-Z]+/', $source_name ) ) { - _doing_it_wrong( - __METHOD__, - __( 'Block bindings source names must not contain uppercase characters.' ), - '6.5.0' - ); - return false; - } - - $name_matcher = '/^[a-z0-9-]+\/[a-z0-9-]+$/'; - if ( ! preg_match( $name_matcher, $source_name ) ) { - _doing_it_wrong( - __METHOD__, - __( 'Block bindings source names must contain a namespace prefix. Example: my-plugin/my-custom-source' ), - '6.5.0' - ); - return false; - } - - if ( $this->is_registered( $source_name ) ) { - _doing_it_wrong( - __METHOD__, - /* translators: %s: Block bindings source name. */ - sprintf( __( 'Block bindings source "%s" already registered.' ), $source_name ), - '6.5.0' - ); - return false; - } - - // Validate that the source properties contain the label. - if ( ! isset( $source_properties['label'] ) ) { - _doing_it_wrong( - __METHOD__, - __( 'The $source_properties must contain a "label".' ), - '6.5.0' - ); - return false; - } - - // Validate that the source properties contain the get_value_callback. - if ( ! isset( $source_properties['get_value_callback'] ) ) { - _doing_it_wrong( - __METHOD__, - __( 'The $source_properties must contain a "get_value_callback".' ), - '6.5.0' - ); - return false; - } - - // Validate that the get_value_callback is a valid callback. - if ( ! is_callable( $source_properties['get_value_callback'] ) ) { - _doing_it_wrong( - __METHOD__, - __( 'The "get_value_callback" parameter must be a valid callback.' ), - '6.5.0' - ); - return false; - } - - // Validate that the uses_context parameter is an array. - if ( isset( $source_properties['uses_context'] ) && ! is_array( $source_properties['uses_context'] ) ) { - _doing_it_wrong( - __METHOD__, - __( 'The "uses_context" parameter must be an array.' ), - '6.5.0' - ); - return false; - } - - // Validate that the source properties contain only allowed properties. - if ( ! empty( array_diff( array_keys( $source_properties ), $this->allowed_source_properties ) ) ) { - _doing_it_wrong( - __METHOD__, - __( 'The $source_properties array contains invalid properties.' ), - '6.5.0' - ); - return false; - } - - $source = new WP_Block_Bindings_Source( - $source_name, - $source_properties - ); - - $this->sources[ $source_name ] = $source; - - // Add `uses_context` defined by block bindings sources. - add_filter( - 'register_block_type_args', - function ( $args, $block_name ) use ( $source ) { - if ( ! in_array( $block_name, $this->supported_blocks, true ) || empty( $source->uses_context ) ) { - return $args; - } - $original_use_context = isset( $args['uses_context'] ) ? $args['uses_context'] : array(); - // Use array_values to reset the array keys. - $args['uses_context'] = array_values( array_unique( array_merge( $original_use_context, $source->uses_context ) ) ); - - return $args; - }, - 10, - 2 - ); - return $source; - } - - /** - * Unregisters a block bindings source. - * - * @since 6.5.0 - * - * @param string $source_name Block bindings source name including namespace. - * @return WP_Block_Bindings_Source|false The unregistered block bindings source on success and `false` otherwise. - */ - public function unregister( string $source_name ) { - if ( ! $this->is_registered( $source_name ) ) { - _doing_it_wrong( - __METHOD__, - /* translators: %s: Block bindings source name. */ - sprintf( __( 'Block binding "%s" not found.' ), $source_name ), - '6.5.0' - ); - return false; - } - - $unregistered_source = $this->sources[ $source_name ]; - unset( $this->sources[ $source_name ] ); - - return $unregistered_source; - } - - /** - * Retrieves the list of all registered block bindings sources. - * - * @since 6.5.0 - * - * @return WP_Block_Bindings_Source[] The array of registered sources. - */ - public function get_all_registered() { - return $this->sources; - } - - /** - * Retrieves a registered block bindings source. - * - * @since 6.5.0 - * - * @param string $source_name The name of the source. - * @return WP_Block_Bindings_Source|null The registered block bindings source, or `null` if it is not registered. - */ - public function get_registered( string $source_name ) { - if ( ! $this->is_registered( $source_name ) ) { - return null; - } - - return $this->sources[ $source_name ]; - } - - /** - * Checks if a block bindings source is registered. - * - * @since 6.5.0 - * - * @param string $source_name The name of the source. - * @return bool `true` if the block bindings source is registered, `false` otherwise. - */ - public function is_registered( $source_name ) { - return isset( $this->sources[ $source_name ] ); - } - - /** - * Utility method to retrieve the main instance of the class. - * - * The instance will be created if it does not exist yet. - * - * @since 6.5.0 - * - * @return WP_Block_Bindings_Registry The main instance. - */ - public static function get_instance() { - if ( null === self::$instance ) { - self::$instance = new self(); - } - - return self::$instance; - } - } -} diff --git a/lib/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-source.php b/lib/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-source.php deleted file mode 100644 index 1862f2af8bb11c..00000000000000 --- a/lib/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-source.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php -/** - * Block Bindings API: WP_Block_Bindings_Source class. - * - * - * @package WordPress - * @subpackage Block Bindings - * @since 6.5.0 - */ - -/** - * Class representing block bindings source. - * - * This class is designed for internal use by the Block Bindings registry. - * - * @since 6.5.0 - * @access private - * - * @see WP_Block_Bindings_Registry - */ -if ( ! class_exists( 'WP_Block_Bindings_Source' ) ) { - final class WP_Block_Bindings_Source { - - /** - * The name of the source. - * - * @since 6.5.0 - * @var string - */ - public $name; - - /** - * The label of the source. - * - * @since 6.5.0 - * @var string - */ - public $label; - - - /** - * The function used to get the value from the source. - * - * @since 6.5.0 - * @var callable - */ - private $get_value_callback; - - /** - * The context added to the blocks needed by the source. - * - * @since 6.5.0 - * @var array|null - */ - public $uses_context = null; - - /** - * Constructor. - * - * Do not use this constructor directly. Instead, use the - * `WP_Block_Bindings_Registry::register` method or the `register_block_bindings_source` function. - * - * @since 6.5.0 - * - * @param string $name The name of the source. - * @param array $source_properties The properties of the source. - */ - public function __construct( string $name, array $source_properties ) { - $this->name = $name; - foreach ( $source_properties as $property_name => $property_value ) { - $this->$property_name = $property_value; - } - } - - /** - * Retrieves the value from the source. - * - * @since 6.5.0 - * - * @param array $source_args Array containing source arguments used to look up the override value, i.e. {"key": "foo"}. - * @param WP_Block $block_instance The block instance. - * @param string $attribute_name The name of the target attribute. - * - * @return mixed The value of the source. - */ - public function get_value( array $source_args, $block_instance, string $attribute_name ) { - return call_user_func_array( $this->get_value_callback, array( $source_args, $block_instance, $attribute_name ) ); - } - - /** - * Wakeup magic method. - * - * @since 6.5.0 - */ - public function __wakeup() { - throw new \LogicException( __CLASS__ . ' should never be unserialized' ); - } - } -} diff --git a/lib/compat/wordpress-6.5/block-bindings/post-meta.php b/lib/compat/wordpress-6.5/block-bindings/post-meta.php deleted file mode 100644 index 56298a7c4d4c50..00000000000000 --- a/lib/compat/wordpress-6.5/block-bindings/post-meta.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php -/** - * Post Meta source for the block bindings. - * - * @package gutenberg - */ - -/** - * Gets value for Post Meta source. - * - * @param array $source_args Array containing source arguments used to look up the override value. - * Example: array( "key" => "foo" ). - * @param WP_Block $block_instance The block instance. - * @return mixed The value computed for the source. - */ -function gutenberg_block_bindings_post_meta_callback( $source_attrs, $block_instance ) { - if ( empty( $source_attrs['key'] ) ) { - return null; - } - - if ( empty( $block_instance->context['postId'] ) ) { - return null; - } - $post_id = $block_instance->context['postId']; - // If a post isn't public, we need to prevent unauthorized users from accessing the post meta. - $post = get_post( $post_id ); - if ( ( ! is_post_publicly_viewable( $post ) && ! current_user_can( 'read_post', $post_id ) ) || post_password_required( $post ) ) { - return null; - } - - // Check if the meta field is protected. - if ( is_protected_meta( $source_attrs['key'], 'post' ) ) { - return null; - } - - // Check if the meta field is registered to be shown in REST. - $meta_keys = get_registered_meta_keys( 'post', $block_instance->context['postType'] ); - // Add fields registered for all subtypes. - $meta_keys = array_merge( $meta_keys, get_registered_meta_keys( 'post', '' ) ); - if ( empty( $meta_keys[ $source_attrs['key'] ]['show_in_rest'] ) ) { - return null; - } - - return get_post_meta( $post_id, $source_attrs['key'], true ); -} - -/** - * Registers Post Meta source in the block bindings registry. - */ -function gutenberg_register_block_bindings_post_meta_source() { - // Override the "core/post-meta" source from core. - if ( array_key_exists( 'core/post-meta', get_all_registered_block_bindings_sources() ) ) { - unregister_block_bindings_source( 'core/post-meta' ); - } - register_block_bindings_source( - 'core/post-meta', - array( - 'label' => _x( 'Post Meta', 'block bindings source' ), - 'get_value_callback' => 'gutenberg_block_bindings_post_meta_callback', - 'uses_context' => array( 'postId', 'postType' ), - ) - ); -} - -add_action( 'init', 'gutenberg_register_block_bindings_post_meta_source' ); diff --git a/lib/compat/wordpress-6.5/block-patterns.php b/lib/compat/wordpress-6.5/block-patterns.php deleted file mode 100644 index cce97cb19c6902..00000000000000 --- a/lib/compat/wordpress-6.5/block-patterns.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php -/** - * Extends Core's wp-includes/block-patterns.php to add new media related - * pattern categories for WP 6.5. - * - * @package gutenberg - */ - -/** - * Adds new pattern categories for better organization of media related patterns. - * - * Note: This should be removed when the minimum required WP version is >= 6.5. - * - * @return void - */ -function gutenberg_register_media_pattern_categories() { - // Register new categories. - register_block_pattern_category( - 'videos', - array( - 'label' => _x( 'Videos', 'Block pattern category' ), - 'description' => __( 'Different layouts containing videos.' ), - ) - ); - register_block_pattern_category( - 'audio', - array( - 'label' => _x( 'Audio', 'Block pattern category' ), - 'description' => __( 'Different layouts containing audio.' ), - ) - ); -} -add_action( 'init', 'gutenberg_register_media_pattern_categories' ); - -/** - * Adds a new taxonomy for organizing user created patterns. - * - * @see https://github.com/WordPress/gutenberg/pull/53163 - * - * @return void - */ -function gutenberg_register_taxonomy_patterns() { - $args = array( - 'public' => false, - 'publicly_queryable' => false, - 'hierarchical' => false, - 'labels' => array( - 'name' => _x( 'Pattern Categories', 'taxonomy general name' ), - 'singular_name' => _x( 'Pattern Category', 'taxonomy singular name' ), - 'add_new_item' => __( 'Add New Category' ), - 'add_or_remove_items' => __( 'Add or remove pattern categories' ), - 'back_to_items' => __( '← Go to Pattern Categories' ), - 'choose_from_most_used' => __( 'Choose from the most used pattern categories' ), - 'edit_item' => __( 'Edit Pattern Category' ), - 'item_link' => __( 'Pattern Category Link' ), - 'item_link_description' => __( 'A link to a pattern category.' ), - 'items_list' => __( 'Pattern Categories list' ), - 'items_list_navigation' => __( 'Pattern Categories list navigation' ), - 'new_item_name' => __( 'New Pattern Category Name' ), - 'no_terms' => __( 'No pattern categories' ), - 'not_found' => __( 'No pattern categories found.' ), - 'popular_items' => __( 'Popular Pattern Categories' ), - 'search_items' => __( 'Search Pattern Categories' ), - 'separate_items_with_commas' => __( 'Separate pattern categories with commas' ), - 'update_item' => __( 'Update Pattern Category' ), - 'view_item' => __( 'View Pattern Category' ), - ), - 'query_var' => false, - 'rewrite' => false, - 'show_ui' => true, - '_builtin' => true, - 'show_in_nav_menus' => false, - 'show_in_rest' => true, - 'show_admin_column' => true, - 'show_tagcloud' => false, - ); - register_taxonomy( 'wp_pattern_category', array( 'wp_block' ), $args ); -} -add_action( 'init', 'gutenberg_register_taxonomy_patterns' ); diff --git a/lib/compat/wordpress-6.5/blocks.php b/lib/compat/wordpress-6.5/blocks.php deleted file mode 100644 index b91e89103faa02..00000000000000 --- a/lib/compat/wordpress-6.5/blocks.php +++ /dev/null @@ -1,414 +0,0 @@ -<?php -/** - * Temporary compatibility shims for block APIs present in Gutenberg. - * - * @package gutenberg - */ - -/** - * Shim for the `variation_callback` block type argument. - * - * @param array $args The block type arguments. - * @return array The updated block type arguments. - */ -function gutenberg_register_block_type_args_shim( $args ) { - if ( isset( $args['variation_callback'] ) && is_callable( $args['variation_callback'] ) ) { - $args['variations'] = call_user_func( $args['variation_callback'] ); - unset( $args['variation_callback'] ); - } - return $args; -} - -if ( ! method_exists( 'WP_Block_Type', 'get_variations' ) ) { - add_filter( 'register_block_type_args', 'gutenberg_register_block_type_args_shim' ); -} - - -/** - * Registers the metadata block attribute for all block types. - * - * @param array $args Array of arguments for registering a block type. - * @return array $args - */ -function gutenberg_register_metadata_attribute( $args ) { - // Setup attributes if needed. - if ( ! isset( $args['attributes'] ) || ! is_array( $args['attributes'] ) ) { - $args['attributes'] = array(); - } - - if ( ! array_key_exists( 'metadata', $args['attributes'] ) ) { - $args['attributes']['metadata'] = array( - 'type' => 'object', - ); - } - - return $args; -} -add_filter( 'register_block_type_args', 'gutenberg_register_metadata_attribute' ); - -// Only process block bindings if they are not processed in core. -if ( ! class_exists( 'WP_Block_Bindings_Registry' ) ) { - /** - * Depending on the block attribute name, replace its value in the HTML based on the value provided. - * - * @param string $block_content Block Content. - * @param string $block_name The name of the block to process. - * @param string $attribute_name The attribute name to replace. - * @param mixed $source_value The value used to replace in the HTML. - * @return string The modified block content. - */ - function gutenberg_block_bindings_replace_html( $block_content, $block_name, string $attribute_name, $source_value ) { - $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block_name ); - if ( ! isset( $block_type->attributes[ $attribute_name ]['source'] ) ) { - return $block_content; - } - - // Depending on the attribute source, the processing will be different. - switch ( $block_type->attributes[ $attribute_name ]['source'] ) { - case 'html': - case 'rich-text': - $block_reader = new WP_HTML_Tag_Processor( $block_content ); - - // TODO: Support for CSS selectors whenever they are ready in the HTML API. - // In the meantime, support comma-separated selectors by exploding them into an array. - $selectors = explode( ',', $block_type->attributes[ $attribute_name ]['selector'] ); - // Add a bookmark to the first tag to be able to iterate over the selectors. - $block_reader->next_tag(); - $block_reader->set_bookmark( 'iterate-selectors' ); - - // TODO: This shouldn't be needed when the `set_inner_html` function is ready. - // Store the parent tag and its attributes to be able to restore them later in the button. - // The button block has a wrapper while the paragraph and heading blocks don't. - if ( 'core/button' === $block_name ) { - $button_wrapper = $block_reader->get_tag(); - $button_wrapper_attribute_names = $block_reader->get_attribute_names_with_prefix( '' ); - $button_wrapper_attrs = array(); - foreach ( $button_wrapper_attribute_names as $name ) { - $button_wrapper_attrs[ $name ] = $block_reader->get_attribute( $name ); - } - } - - foreach ( $selectors as $selector ) { - // If the parent tag, or any of its children, matches the selector, replace the HTML. - if ( strcasecmp( $block_reader->get_tag( $selector ), $selector ) === 0 || $block_reader->next_tag( - array( - 'tag_name' => $selector, - ) - ) ) { - $block_reader->release_bookmark( 'iterate-selectors' ); - - // TODO: Use `set_inner_html` method whenever it's ready in the HTML API. - // Until then, it is hardcoded for the paragraph, heading, and button blocks. - // Store the tag and its attributes to be able to restore them later. - $selector_attribute_names = $block_reader->get_attribute_names_with_prefix( '' ); - $selector_attrs = array(); - foreach ( $selector_attribute_names as $name ) { - $selector_attrs[ $name ] = $block_reader->get_attribute( $name ); - } - $selector_markup = "<$selector>" . wp_kses_post( $source_value ) . "</$selector>"; - $amended_content = new WP_HTML_Tag_Processor( $selector_markup ); - $amended_content->next_tag(); - foreach ( $selector_attrs as $attribute_key => $attribute_value ) { - $amended_content->set_attribute( $attribute_key, $attribute_value ); - } - if ( 'core/paragraph' === $block_name || 'core/heading' === $block_name ) { - return $amended_content->get_updated_html(); - } - if ( 'core/button' === $block_name ) { - $button_markup = "<$button_wrapper>{$amended_content->get_updated_html()}</$button_wrapper>"; - $amended_button = new WP_HTML_Tag_Processor( $button_markup ); - $amended_button->next_tag(); - foreach ( $button_wrapper_attrs as $attribute_key => $attribute_value ) { - $amended_button->set_attribute( $attribute_key, $attribute_value ); - } - return $amended_button->get_updated_html(); - } - } else { - $block_reader->seek( 'iterate-selectors' ); - } - } - $block_reader->release_bookmark( 'iterate-selectors' ); - return $block_content; - - case 'attribute': - $amended_content = new WP_HTML_Tag_Processor( $block_content ); - if ( ! $amended_content->next_tag( - array( - // TODO: build the query from CSS selector. - 'tag_name' => $block_type->attributes[ $attribute_name ]['selector'], - ) - ) ) { - return $block_content; - } - $amended_content->set_attribute( $block_type->attributes[ $attribute_name ]['attribute'], $source_value ); - return $amended_content->get_updated_html(); - - default: - return $block_content; - } - } - - /** - * Process the block bindings attribute. - * - * @param string $block_content Block Content. - * @param array $parsed_block The full block, including name and attributes. - * @param WP_Block $block_instance The block instance. - * @return string Block content with the bind applied. - */ - function gutenberg_process_block_bindings( $block_content, $parsed_block, $block_instance ) { - $supported_block_attrs = array( - 'core/paragraph' => array( 'content' ), - 'core/heading' => array( 'content' ), - 'core/image' => array( 'id', 'url', 'title', 'alt' ), - 'core/button' => array( 'url', 'text', 'linkTarget', 'rel' ), - ); - - // If the block doesn't have the bindings property or isn't one of the supported block types, return. - if ( - ! isset( $supported_block_attrs[ $block_instance->name ] ) || - empty( $parsed_block['attrs']['metadata']['bindings'] ) || - ! is_array( $parsed_block['attrs']['metadata']['bindings'] ) - ) { - return $block_content; - } - - /* - * Assuming the following format for the bindings property of the "metadata" attribute: - * - * "bindings": { - * "title": { - * "source": "core/post-meta", - * "args": { "key": "text_custom_field" } - * }, - * "url": { - * "source": "core/post-meta", - * "args": { "key": "url_custom_field" } - * } - * } - */ - - $modified_block_content = $block_content; - foreach ( $parsed_block['attrs']['metadata']['bindings'] as $attribute_name => $block_binding ) { - // If the attribute is not in the supported list, process next attribute. - if ( ! in_array( $attribute_name, $supported_block_attrs[ $block_instance->name ], true ) ) { - continue; - } - // If no source is provided, or that source is not registered, process next attribute. - if ( ! isset( $block_binding['source'] ) || ! is_string( $block_binding['source'] ) ) { - continue; - } - - $block_binding_source = get_block_bindings_source( $block_binding['source'] ); - if ( null === $block_binding_source ) { - continue; - } - - $source_args = ! empty( $block_binding['args'] ) && is_array( $block_binding['args'] ) ? $block_binding['args'] : array(); - $source_value = $block_binding_source->get_value( $source_args, $block_instance, $attribute_name ); - - // If the value is not null, process the HTML based on the block and the attribute. - if ( ! is_null( $source_value ) ) { - $modified_block_content = gutenberg_block_bindings_replace_html( $modified_block_content, $block_instance->name, $attribute_name, $source_value ); - } - } - - return $modified_block_content; - } - - add_filter( 'render_block', 'gutenberg_process_block_bindings', 20, 3 ); -} - -/** - * Enable the viewStyle block API for core versions < 6.5 - * - */ -if ( ! property_exists( 'WP_Block_Type', 'view_style_handles' ) ) { - /** - * Registers viewStyle assets on block type registration (=same moment core would do it). - * - * @param array $settings Array of determined settings for registering a block type. - * @param array $metadata Metadata provided for registering a block type. - * @return array The block type settings - */ - function gutenberg_filter_block_type_metadata_settings_register_view_styles( $settings, $metadata ) { - if ( empty( $metadata['viewStyle'] ) ) { - return $settings; - } - $styles = $metadata['viewStyle']; - $processed_styles = array(); - if ( is_array( $styles ) ) { - for ( $index = 0; $index < count( $styles ); $index++ ) { - $result = gutenberg_register_block_view_style_handle( - $metadata, - $index - ); - if ( $result ) { - $processed_styles[] = $result; - } - } - } else { - $result = gutenberg_register_block_view_style_handle( - $metadata - ); - if ( $result ) { - $processed_styles[] = $result; - } - } - - if ( ! empty( $processed_styles ) ) { - $settings['view_style_handles'] = $processed_styles; - } - return $settings; - } - - add_filter( 'block_type_metadata_settings', 'gutenberg_filter_block_type_metadata_settings_register_view_styles', 10, 2 ); - - /** - * Enqueue view styles associated with the block. - * - * @param string $block_content The block content. - * @param array $block The full block, including name and attributes. - * @param WP_Block $instance The block instance. - */ - function gutenberg_filter_render_block_enqueue_view_styles( $block_content, $parsed_block, $block_instance ) { - $block_type = $block_instance->block_type; - - if ( ! empty( $block_type->view_style_handles ) ) { - foreach ( $block_type->view_style_handles as $view_style_handle ) { - wp_enqueue_style( $view_style_handle ); - } - } - - return $block_content; - } - - add_filter( 'render_block', 'gutenberg_filter_render_block_enqueue_view_styles', 10, 3 ); - - - /** - * Registers a REST field for block types to provide view styles. - * - * Adds the `view_style_handles` field to block type objects in the REST API, which - * lists the style handles associated with the block's viewStyle key. - */ - function gutenberg_register_view_style_rest_field() { - register_rest_field( - 'block-type', - 'view_style_handles', - array( - 'get_callback' => function ( $item ) { - $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $item['name'] ); - if ( isset( $block_type->view_style_handles ) ) { - return $block_type->view_style_handles; - } - return array(); - }, - ) - ); - } - - add_action( 'rest_api_init', 'gutenberg_register_view_style_rest_field' ); - - /** - * A compat version of `register_block_style_handle()` to use the viewStyle handle. - * Required for core versions < 6.5, since a custom version of generate_block_asset_handle has to be used - * that supports the viewStyle property and correctly creates the handle - * - * @param array $metadata Block metadata. - * @param int $index Optional. Index of the style to register when multiple items passed. - * Default 0. - * @return string|false Style handle provided directly or created through - * style's registration, or false on failure. - */ - function gutenberg_register_block_view_style_handle( $metadata, $index = 0 ) { - $style_handle = $metadata['viewStyle']; - if ( is_array( $style_handle ) ) { - if ( empty( $style_handle[ $index ] ) ) { - return false; - } - $style_handle = $style_handle[ $index ]; - } - $style_handle_name = gutenberg_generate_view_style_block_asset_handle( $metadata['name'], $index ); - // If the style handle is already registered, skip re-registering. - if ( wp_style_is( $style_handle_name, 'registered' ) ) { - return $style_handle_name; - } - static $wpinc_path_norm = ''; - if ( ! $wpinc_path_norm ) { - $wpinc_path_norm = wp_normalize_path( realpath( ABSPATH . WPINC ) ); - } - $is_core_block = isset( $metadata['file'] ) && str_starts_with( $metadata['file'], $wpinc_path_norm ); - // Skip registering individual styles for each core block when a bundled version provided. - if ( $is_core_block && ! wp_should_load_separate_core_block_assets() ) { - return false; - } - $style_path = remove_block_asset_path_prefix( $style_handle ); - $is_style_handle = $style_handle === $style_path; - // Allow only passing style handles for core blocks. - if ( $is_core_block && ! $is_style_handle ) { - return false; - } - // Return the style handle unless it's the first item for every core block that requires special treatment. - if ( $is_style_handle && ! ( $is_core_block && 0 === $index ) ) { - return $style_handle; - } - // Check whether styles should have a ".min" suffix or not. - $suffix = SCRIPT_DEBUG ? '' : '.min'; - if ( $is_core_block ) { - $style_path = "view{$suffix}.css"; // Use view.css for viewStyle of core blocks - } - $style_path_norm = wp_normalize_path( realpath( dirname( $metadata['file'] ) . '/' . $style_path ) ); - $style_uri = get_block_asset_url( $style_path_norm ); - $version = ! $is_core_block && isset( $metadata['version'] ) ? $metadata['version'] : false; - $result = wp_register_style( - $style_handle_name, - $style_uri, - array(), - $version - ); - if ( ! $result ) { - return false; - } - if ( $style_uri ) { - wp_style_add_data( $style_handle_name, 'path', $style_path_norm ); - if ( $is_core_block ) { - $rtl_file = str_replace( "{$suffix}.css", "-rtl{$suffix}.css", $style_path_norm ); - } else { - $rtl_file = str_replace( '.css', '-rtl.css', $style_path_norm ); - } - if ( is_rtl() && file_exists( $rtl_file ) ) { - wp_style_add_data( $style_handle_name, 'rtl', 'replace' ); - wp_style_add_data( $style_handle_name, 'suffix', $suffix ); - wp_style_add_data( $style_handle_name, 'path', $rtl_file ); - } - } - return $style_handle_name; - } - - /** - * A compat version of `generate_block_asset_handle()` to use the viewStyle asset handle. - * - * @param string $block_name Name of the block. - * @param string $field_name Name of the metadata field. - * @param int $index Optional. Index of the asset when multiple items passed. - * Default 0. - * @return string Generated asset name for the block's field. - */ - function gutenberg_generate_view_style_block_asset_handle( $block_name, $index = 0 ) { - if ( str_starts_with( $block_name, 'core/' ) ) { - $asset_handle = str_replace( 'core/', 'wp-block-', $block_name ); - $asset_handle .= '-view'; - if ( $index > 0 ) { - $asset_handle .= '-' . ( $index + 1 ); - } - return $asset_handle; - } - - $asset_handle = str_replace( '/', '-', $block_name ) . '-view-style'; - if ( $index > 0 ) { - $asset_handle .= '-' . ( $index + 1 ); - } - return $asset_handle; - } -} diff --git a/lib/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php b/lib/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php deleted file mode 100644 index 74fa31d53199e0..00000000000000 --- a/lib/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php +++ /dev/null @@ -1,111 +0,0 @@ -<?php -/** - * REST API: Gutenberg_REST_Global_Styles_Revisions_Controller class, inspired by WP_REST_Revisions_Controller. - * - * @package WordPress - * @subpackage REST_API - * @since 6.3.0 - */ - -/** - * Core class used to access global styles revisions via the REST API. - * - * @since 6.3.0 - * - * @see WP_REST_Controller - */ -class Gutenberg_REST_Global_Styles_Revisions_Controller_6_5 extends Gutenberg_REST_Global_Styles_Revisions_Controller_6_4 { - /** - * Registers the controller's routes. - * - * @since 6.3.0 - * @since 6.5.0 Adds route to fetch individual global styles revisions. - */ - public function register_routes() { - register_rest_route( - $this->namespace, - '/' . $this->parent_base . '/(?P<parent>[\d]+)/' . $this->rest_base . '/(?P<id>[\d]+)', - array( - 'args' => array( - 'parent' => array( - 'description' => __( 'The ID for the parent of the global styles revision.' ), - 'type' => 'integer', - ), - 'id' => array( - 'description' => __( 'Unique identifier for the global styles revision.' ), - 'type' => 'integer', - ), - ), - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_item' ), - 'permission_callback' => array( $this, 'get_item_permissions_check' ), - 'args' => array( - 'context' => $this->get_context_param( array( 'default' => 'view' ) ), - ), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) - ); - parent::register_routes(); - } - - /** - * Retrieves one global styles revision from the collection. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_item( $request ) { - $parent = $this->get_parent( $request['parent'] ); - if ( is_wp_error( $parent ) ) { - return $parent; - } - - $revision = $this->get_revision( $request['id'] ); - if ( is_wp_error( $revision ) ) { - return $revision; - } - - if ( (int) $parent->ID !== (int) $revision->post_parent ) { - return new WP_Error( - 'rest_revision_parent_id_mismatch', - /* translators: %d: A post id. */ - sprintf( __( 'The revision does not belong to the specified parent with id of "%d"' ), $parent->ID ), - array( 'status' => 404 ) - ); - } - - $response = $this->prepare_item_for_response( $revision, $request ); - return rest_ensure_response( $response ); - } - - /** - * Get the global styles revision, if the ID is valid. - * - * @since 6.5.0 - * - * @param int $id Supplied ID. - * @return WP_Post|WP_Error Revision post object if ID is valid, WP_Error otherwise. - */ - protected function get_revision( $id ) { - $error = new WP_Error( - 'rest_post_invalid_id', - __( 'Invalid revision ID.' ), - array( 'status' => 404 ) - ); - - if ( (int) $id <= 0 ) { - return $error; - } - - $revision = get_post( (int) $id ); - if ( empty( $revision ) || empty( $revision->ID ) || 'revision' !== $revision->post_type ) { - return $error; - } - - return $revision; - } -} diff --git a/lib/compat/wordpress-6.5/class-wp-script-modules.php b/lib/compat/wordpress-6.5/class-wp-script-modules.php deleted file mode 100644 index 4d3280f1db0b97..00000000000000 --- a/lib/compat/wordpress-6.5/class-wp-script-modules.php +++ /dev/null @@ -1,362 +0,0 @@ -<?php -/** - * Script Modules API: WP_Script_Modules class. - * - * Native support for ES Modules and Import Maps. - * - * @package WordPress - * @subpackage Script Modules - */ - -if ( ! class_exists( 'WP_Script_Modules' ) ) { - /** - * Core class used to register script modules. - * - * @since 6.5.0 - */ - class WP_Script_Modules { - /** - * Holds the registered script modules, keyed by script module identifier. - * - * @since 6.5.0 - * @var array - */ - private $registered = array(); - - /** - * Holds the script module identifiers that were enqueued before registered. - * - * @since 6.5.0 - * @var array<string, true> - */ - private $enqueued_before_registered = array(); - - /** - * Registers the script module if no script module with that script module - * identifier has already been registered. - * - * @since 6.5.0 - * - * @param string $id The identifier of the script module. Should be unique. It will be used in the - * final import map. - * @param string $src Optional. Full URL of the script module, or path of the script module relative - * to the WordPress root directory. If it is provided and the script module has - * not been registered yet, it will be registered. - * @param array $deps { - * Optional. List of dependencies. - * - * @type string|array $0... { - * An array of script module identifiers of the dependencies of this script - * module. The dependencies can be strings or arrays. If they are arrays, - * they need an `id` key with the script module identifier, and can contain - * an `import` key with either `static` or `dynamic`. By default, - * dependencies that don't contain an `import` key are considered static. - * - * @type string $id The script module identifier. - * @type string $import Optional. Import type. May be either `static` or - * `dynamic`. Defaults to `static`. - * } - * } - * @param string|false|null $version Optional. String specifying the script module version number. Defaults to false. - * It is added to the URL as a query string for cache busting purposes. If $version - * is set to false, the version number is the currently installed WordPress version. - * If $version is set to null, no version is added. - */ - public function register( string $id, string $src, array $deps = array(), $version = false ) { - if ( ! isset( $this->registered[ $id ] ) ) { - $dependencies = array(); - foreach ( $deps as $dependency ) { - if ( is_array( $dependency ) ) { - if ( ! isset( $dependency['id'] ) ) { - _doing_it_wrong( __METHOD__, __( 'Missing required id key in entry among dependencies array.' ), '6.5.0' ); - continue; - } - $dependencies[] = array( - 'id' => $dependency['id'], - 'import' => isset( $dependency['import'] ) && 'dynamic' === $dependency['import'] ? 'dynamic' : 'static', - ); - } elseif ( is_string( $dependency ) ) { - $dependencies[] = array( - 'id' => $dependency, - 'import' => 'static', - ); - } else { - _doing_it_wrong( __METHOD__, __( 'Entries in dependencies array must be either strings or arrays with an id key.' ), '6.5.0' ); - } - } - - $this->registered[ $id ] = array( - 'src' => $src, - 'version' => $version, - 'enqueue' => isset( $this->enqueued_before_registered[ $id ] ), - 'dependencies' => $dependencies, - ); - } - } - - /** - * Marks the script module to be enqueued in the page. - * - * If a src is provided and the script module has not been registered yet, it - * will be registered. - * - * @since 6.5.0 - * - * @param string $id The identifier of the script module. Should be unique. It will be used in the - * final import map. - * @param string $src Optional. Full URL of the script module, or path of the script module relative - * to the WordPress root directory. If it is provided and the script module has - * not been registered yet, it will be registered. - * @param array $deps { - * Optional. List of dependencies. - * - * @type string|array $0... { - * An array of script module identifiers of the dependencies of this script - * module. The dependencies can be strings or arrays. If they are arrays, - * they need an `id` key with the script module identifier, and can contain - * an `import` key with either `static` or `dynamic`. By default, - * dependencies that don't contain an `import` key are considered static. - * - * @type string $id The script module identifier. - * @type string $import Optional. Import type. May be either `static` or - * `dynamic`. Defaults to `static`. - * } - * } - * @param string|false|null $version Optional. String specifying the script module version number. Defaults to false. - * It is added to the URL as a query string for cache busting purposes. If $version - * is set to false, the version number is the currently installed WordPress version. - * If $version is set to null, no version is added. - */ - public function enqueue( string $id, string $src = '', array $deps = array(), $version = false ) { - if ( isset( $this->registered[ $id ] ) ) { - $this->registered[ $id ]['enqueue'] = true; - } elseif ( $src ) { - $this->register( $id, $src, $deps, $version ); - $this->registered[ $id ]['enqueue'] = true; - } else { - $this->enqueued_before_registered[ $id ] = true; - } - } - - /** - * Unmarks the script module so it will no longer be enqueued in the page. - * - * @since 6.5.0 - * - * @param string $id The identifier of the script module. - */ - public function dequeue( string $id ) { - if ( isset( $this->registered[ $id ] ) ) { - $this->registered[ $id ]['enqueue'] = false; - } - unset( $this->enqueued_before_registered[ $id ] ); - } - - /** - * Removes a registered script module. - * - * @since 6.5.0 - * - * @param string $id The identifier of the script module. - */ - public function deregister( string $id ) { - unset( $this->registered[ $id ] ); - unset( $this->enqueued_before_registered[ $id ] ); - } - - /** - * Adds the hooks to print the import map, enqueued script modules and script - * module preloads. - * - * In classic themes, the script modules used by the blocks are not yet known - * when the `wp_head` actions is fired, so it needs to print everything in the - * footer. - * - * @since 6.5.0 - */ - public function add_hooks() { - $position = wp_is_block_theme() ? 'wp_head' : 'wp_footer'; - add_action( $position, array( $this, 'print_import_map' ) ); - add_action( $position, array( $this, 'print_enqueued_script_modules' ) ); - add_action( $position, array( $this, 'print_script_module_preloads' ) ); - } - - /** - * Prints the enqueued script modules using script tags with type="module" - * attributes. - * - * @since 6.5.0 - */ - public function print_enqueued_script_modules() { - foreach ( $this->get_marked_for_enqueue() as $id => $script_module ) { - wp_print_script_tag( - array( - 'type' => 'module', - 'src' => $this->get_versioned_src( $script_module ), - 'id' => $id . '-js-module', - ) - ); - } - } - - /** - * Prints the the static dependencies of the enqueued script modules using - * link tags with rel="modulepreload" attributes. - * - * If a script module is marked for enqueue, it will not be preloaded. - * - * @since 6.5.0 - */ - public function print_script_module_preloads() { - foreach ( $this->get_dependencies( array_keys( $this->get_marked_for_enqueue() ), array( 'static' ) ) as $id => $script_module ) { - // Don't preload if it's marked for enqueue. - if ( true !== $script_module['enqueue'] ) { - echo sprintf( - '<link rel="modulepreload" href="%s" id="%s">', - esc_url( $this->get_versioned_src( $script_module ) ), - esc_attr( $id . '-js-modulepreload' ) - ); - } - } - } - - /** - * Prints the import map using a script tag with a type="importmap" attribute. - * - * @since 6.5.0 - * - * @global WP_Scripts $wp_scripts The WP_Scripts object for printing the polyfill. - */ - public function print_import_map() { - $import_map = $this->get_import_map(); - if ( ! empty( $import_map['imports'] ) ) { - global $wp_scripts; - if ( isset( $wp_scripts ) ) { - /* - * In Core, the polyfill is registered with a different approach. - * See: https://github.com/WordPress/wordpress-develop/blob/4b23ba81ddb067110e41d05550de7f2a4f09dad3/src/wp-includes/script-loader.php#L99 - */ - wp_register_script( - 'wp-polyfill-importmap', - gutenberg_url( '/build/modules/importmap-polyfill.min.js' ), - array(), - '1.8.2', - true - ); - gutenberg_print_inline_script_tag( - wp_get_script_polyfill( - $wp_scripts, - array( - 'HTMLScriptElement.supports && HTMLScriptElement.supports("importmap")' => 'wp-polyfill-importmap', - ) - ), - array( - 'id' => 'wp-load-polyfill-importmap', - ) - ); - } - gutenberg_print_inline_script_tag( - wp_json_encode( $import_map, JSON_HEX_TAG | JSON_HEX_AMP ), - array( - 'type' => 'importmap', - 'id' => 'wp-importmap', - ) - ); - } - } - - /** - * Returns the import map array. - * - * @since 6.5.0 - * - * @return array Array with an `imports` key mapping to an array of script module identifiers and their respective - * URLs, including the version query. - */ - private function get_import_map(): array { - $imports = array(); - foreach ( $this->get_dependencies( array_keys( $this->get_marked_for_enqueue() ) ) as $id => $script_module ) { - $imports[ $id ] = $this->get_versioned_src( $script_module ); - } - return array( 'imports' => $imports ); - } - - /** - * Retrieves the list of script modules marked for enqueue. - * - * @since 6.5.0 - * - * @return array Script modules marked for enqueue, keyed by script module identifier. - */ - private function get_marked_for_enqueue(): array { - $enqueued = array(); - foreach ( $this->registered as $id => $script_module ) { - if ( true === $script_module['enqueue'] ) { - $enqueued[ $id ] = $script_module; - } - } - return $enqueued; - } - - /** - * Retrieves all the dependencies for the given script module identifiers, - * filtered by import types. - * - * It will consolidate an array containing a set of unique dependencies based - * on the requested import types: 'static', 'dynamic', or both. This method is - * recursive and also retrieves dependencies of the dependencies. - * - * @since 6.5.0 - * - - * @param string[] $ids The identifiers of the script modules for which to gather dependencies. - * @param array $import_types Optional. Import types of dependencies to retrieve: 'static', 'dynamic', or both. - * Default is both. - * @return array List of dependencies, keyed by script module identifier. - */ - private function get_dependencies( array $ids, array $import_types = array( 'static', 'dynamic' ) ) { - return array_reduce( - $ids, - function ( $dependency_script_modules, $id ) use ( $import_types ) { - $dependencies = array(); - foreach ( $this->registered[ $id ]['dependencies'] as $dependency ) { - if ( - in_array( $dependency['import'], $import_types, true ) && - isset( $this->registered[ $dependency['id'] ] ) && - ! isset( $dependency_script_modules[ $dependency['id'] ] ) - ) { - $dependencies[ $dependency['id'] ] = $this->registered[ $dependency['id'] ]; - } - } - return array_merge( $dependency_script_modules, $dependencies, $this->get_dependencies( array_keys( $dependencies ), $import_types ) ); - }, - array() - ); - } - - /** - * Gets the versioned URL for a script module src. - * - * If $version is set to false, the version number is the currently installed - * WordPress version. If $version is set to null, no version is added. - * Otherwise, the string passed in $version is used. - * - * @since 6.5.0 - * - * @param array $script_module The script module. - * @return string The script module src with a version if relevant. - */ - private function get_versioned_src( array $script_module ): string { - $args = array(); - if ( false === $script_module['version'] ) { - $args['ver'] = get_bloginfo( 'version' ); - } elseif ( null !== $script_module['version'] ) { - $args['ver'] = $script_module['version']; - } - if ( $args ) { - return add_query_arg( $args, $script_module['src'] ); - } - return $script_module['src']; - } - } -} diff --git a/lib/compat/wordpress-6.5/compat.php b/lib/compat/wordpress-6.5/compat.php deleted file mode 100644 index c41203e5d27b4e..00000000000000 --- a/lib/compat/wordpress-6.5/compat.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php -/** - * WordPress 6.5 compatibility functions. - * - * @package WordPress - */ - -if ( ! function_exists( 'array_is_list' ) ) { - /** - * Polyfill for `array_is_list()` function added in PHP 8.1. - * - * Determines if the given array is a list. - * - * An array is considered a list if its keys consist of consecutive numbers from 0 to count($array)-1. - * - * @see https://github.com/symfony/polyfill-php81/tree/main - * - * @since 6.5.0 - * - * @param array<mixed> $arr The array being evaluated. - * @return bool True if array is a list, false otherwise. - */ - function array_is_list( $arr ) { - if ( ( array() === $arr ) || ( array_values( $arr ) === $arr ) ) { - return true; - } - - $next_key = -1; - - foreach ( $arr as $k => $v ) { - if ( ++$next_key !== $k ) { - return false; - } - } - - return true; - } -} - -/** - * Sets a global JS variable used to flag whether to direct the Site Logo block's admin urls - * to the Customizer. This allows Gutenberg running on versions of WordPress < 6.5.0 to - * support the previous location for the Site Icon settings. This function should not be - * backported to core, and should be removed when the required WP core version for Gutenberg - * is >= 6.5.0. - */ -function gutenberg_add_use_customizer_site_logo_url_flag() { - if ( ! is_wp_version_compatible( '6.5' ) ) { - wp_add_inline_script( 'wp-block-editor', 'window.__experimentalUseCustomizerSiteLogoUrl = true', 'before' ); - } -} - -add_action( 'admin_init', 'gutenberg_add_use_customizer_site_logo_url_flag' ); - -/** - * Add a Patterns submenu (wp-admin/edit.php?post_type=wp_block) under the Appearance menu - * for the Classic theme. This function should not be backported to core, and should be - * removed when the required WP core version for Gutenberg is >= 6.5.0. - * - * @global array $submenu - */ -function gutenberg_add_patterns_page_submenu_item() { - if ( ! is_wp_version_compatible( '6.5' ) && ! wp_is_block_theme() ) { - // Move the Themes submenu forward and inject a Patterns submenu. - global $submenu; - $submenu['themes.php'][4] = $submenu['themes.php'][5]; - $submenu['themes.php'][5] = array( __( 'Patterns', 'gutenberg' ), 'edit_theme_options', 'edit.php?post_type=wp_block' ); - ksort( $submenu['themes.php'], SORT_NUMERIC ); - } -} -add_action( 'admin_init', 'gutenberg_add_patterns_page_submenu_item' ); - -/** - * Filter the `wp_die_handler` to allow access to the Site Editor's Patterns page - * (wp-admin/site-editor.php?path=%2Fpatterns) internally for the Classic theme. This - * function should not be backported to core, and should be removed when the required - * WP core version for Gutenberg is >= 6.5.0. - * - * @param callable $default_handler The default handler. - * @return callable The default handler or a custom handler. - */ -function gutenberg_patterns_page_wp_die_handler( $default_handler ) { - if ( ! is_wp_version_compatible( '6.5' ) && ! wp_is_block_theme() && str_contains( $_SERVER['REQUEST_URI'], 'site-editor.php' ) ) { - $is_patterns = isset( $_GET['postType'] ) && 'wp_block' === sanitize_key( $_GET['postType'] ); - $is_patterns_path = isset( $_GET['path'] ) && 'patterns' === sanitize_key( $_GET['path'] ); - if ( $is_patterns || $is_patterns_path ) { - return '__return_false'; - } - } - return $default_handler; -} -add_filter( 'wp_die_handler', 'gutenberg_patterns_page_wp_die_handler' ); diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php b/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php deleted file mode 100644 index 3ccbed6ed275e9..00000000000000 --- a/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php +++ /dev/null @@ -1,298 +0,0 @@ -<?php -/** - * Font Collection class. - * - * This file contains the Font Collection class definition. - * - * @package WordPress - * @subpackage Font Library - * @since 6.5.0 - */ - -if ( ! class_exists( 'WP_Font_Collection' ) ) { - - /** - * Font Collection class. - * - * @since 6.5.0 - * - * @see wp_register_font_collection() - */ - final class WP_Font_Collection { - /** - * The unique slug for the font collection. - * - * @since 6.5.0 - * @var string - */ - public $slug; - - /** - * Font collection data. - * - * @since 6.5.0 - * @var array|WP_Error|null - */ - private $data; - - /** - * Font collection JSON file path or URL. - * - * @since 6.5.0 - * @var string|null - */ - private $src; - - /** - * WP_Font_Collection constructor. - * - * @since 6.5.0 - * - * @param string $slug Font collection slug. May only contain alphanumeric characters, dashes, - * and underscores. See sanitize_title(). - * @param array $args Font collection data. See wp_register_font_collection() for information on accepted arguments. - */ - public function __construct( string $slug, array $args ) { - $this->slug = sanitize_title( $slug ); - if ( $this->slug !== $slug ) { - _doing_it_wrong( - __METHOD__, - /* translators: %s: Font collection slug. */ - sprintf( __( 'Font collection slug "%s" is not valid. Slugs must use only alphanumeric characters, dashes, and underscores.', 'gutenberg' ), $slug ), - '6.5.0' - ); - } - - $required_properties = array( 'name', 'font_families' ); - - if ( isset( $args['font_families'] ) && is_string( $args['font_families'] ) ) { - // JSON data is lazy loaded by ::get_data(). - $this->src = $args['font_families']; - unset( $args['font_families'] ); - - $required_properties = array( 'name' ); - } - - $this->data = $this->sanitize_and_validate_data( $args, $required_properties ); - } - - /** - * Retrieves the font collection data. - * - * @since 6.5.0 - * - * @return array|WP_Error An array containing the font collection data, or a WP_Error on failure. - */ - public function get_data() { - if ( is_wp_error( $this->data ) ) { - return $this->data; - } - - // If the collection uses JSON data, load it and cache the data/error. - if ( isset( $this->src ) ) { - $this->data = $this->load_from_json( $this->src ); - } - - if ( is_wp_error( $this->data ) ) { - return $this->data; - } - - // Set defaults for optional properties. - $defaults = array( - 'description' => '', - 'categories' => array(), - ); - - return wp_parse_args( $this->data, $defaults ); - } - - /** - * Loads font collection data from a JSON file or URL. - * - * @since 6.5.0 - * - * @param string $file_or_url File path or URL to a JSON file containing the font collection data. - * @return array|WP_Error An array containing the font collection data on success, - * else an instance of WP_Error on failure. - */ - private function load_from_json( $file_or_url ) { - $url = wp_http_validate_url( $file_or_url ); - $file = file_exists( $file_or_url ) ? wp_normalize_path( realpath( $file_or_url ) ) : false; - - if ( ! $url && ! $file ) { - // translators: %s: File path or URL to font collection JSON file. - $message = __( 'Font collection JSON file is invalid or does not exist.', 'gutenberg' ); - _doing_it_wrong( __METHOD__, $message, '6.5.0' ); - return new WP_Error( 'font_collection_json_missing', $message ); - } - - $data = $url ? $this->load_from_url( $url ) : $this->load_from_file( $file ); - - if ( is_wp_error( $data ) ) { - return $data; - } - - $data = array( - 'name' => $this->data['name'], - 'font_families' => $data['font_families'], - ); - - if ( isset( $this->data['description'] ) ) { - $data['description'] = $this->data['description']; - } - - if ( isset( $this->data['categories'] ) ) { - $data['categories'] = $this->data['categories']; - } - - return $data; - } - - /** - * Loads the font collection data from a JSON file path. - * - * @since 6.5.0 - * - * @param string $file File path to a JSON file containing the font collection data. - * @return array|WP_Error An array containing the font collection data on success, - * else an instance of WP_Error on failure. - */ - private function load_from_file( $file ) { - $data = wp_json_file_decode( $file, array( 'associative' => true ) ); - if ( empty( $data ) ) { - return new WP_Error( 'font_collection_decode_error', __( 'Error decoding the font collection JSON file contents.', 'gutenberg' ) ); - } - - return $this->sanitize_and_validate_data( $data, array( 'font_families' ) ); - } - - /** - * Loads the font collection data from a JSON file URL. - * - * @since 6.5.0 - * - * @param string $url URL to a JSON file containing the font collection data. - * @return array|WP_Error An array containing the font collection data on success, - * else an instance of WP_Error on failure. - */ - private function load_from_url( $url ) { - // Limit key to 167 characters to avoid failure in the case of a long URL. - $transient_key = substr( 'wp_font_collection_url_' . $url, 0, 167 ); - $data = get_site_transient( $transient_key ); - - if ( false === $data ) { - $response = wp_safe_remote_get( $url ); - if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { - return new WP_Error( - 'font_collection_request_error', - sprintf( - // translators: %s: Font collection URL. - __( 'Error fetching the font collection data from "%s".', 'gutenberg' ), - $url - ) - ); - } - - $data = json_decode( wp_remote_retrieve_body( $response ), true ); - if ( empty( $data ) ) { - return new WP_Error( 'font_collection_decode_error', __( 'Error decoding the font collection data from the HTTP response JSON.', 'gutenberg' ) ); - } - - // Make sure the data is valid before storing it in a transient. - $data = $this->sanitize_and_validate_data( $data, array( 'font_families' ) ); - if ( is_wp_error( $data ) ) { - return $data; - } - - set_site_transient( $transient_key, $data, DAY_IN_SECONDS ); - } - - return $data; - } - - /** - * Sanitizes and validates the font collection data. - * - * @since 6.5.0 - * - * @param array $data Font collection data to sanitize and validate. - * @param array $required_properties Required properties that must exist in the passed data. - * @return array|WP_Error Sanitized data if valid, otherwise a WP_Error instance. - */ - private function sanitize_and_validate_data( $data, $required_properties = array() ) { - $schema = self::get_sanitization_schema(); - $data = WP_Font_Utils::sanitize_from_schema( $data, $schema ); - - foreach ( $required_properties as $property ) { - if ( empty( $data[ $property ] ) ) { - $message = sprintf( - // translators: 1: Font collection slug, 2: Missing property name, e.g. "font_families". - __( 'Font collection "%1$s" has missing or empty property: "%2$s".', 'gutenberg' ), - $this->slug, - $property - ); - _doing_it_wrong( __METHOD__, $message, '6.5.0' ); - return new WP_Error( 'font_collection_missing_property', $message ); - } - } - - return $data; - } - - /** - * Retrieves the font collection sanitization schema. - * - * @since 6.5.0 - * - * @return array Font collection sanitization schema. - */ - private static function get_sanitization_schema() { - return array( - 'name' => 'sanitize_text_field', - 'description' => 'sanitize_text_field', - 'font_families' => array( - array( - 'font_family_settings' => array( - 'name' => 'sanitize_text_field', - 'slug' => static function ( $value ) { - return _wp_to_kebab_case( sanitize_title( $value ) ); - }, - 'fontFamily' => 'WP_Font_Utils::sanitize_font_family', - 'preview' => 'sanitize_url', - 'fontFace' => array( - array( - 'fontFamily' => 'sanitize_text_field', - 'fontStyle' => 'sanitize_text_field', - 'fontWeight' => 'sanitize_text_field', - 'src' => static function ( $value ) { - return is_array( $value ) - ? array_map( 'sanitize_text_field', $value ) - : sanitize_text_field( $value ); - }, - 'preview' => 'sanitize_url', - 'fontDisplay' => 'sanitize_text_field', - 'fontStretch' => 'sanitize_text_field', - 'ascentOverride' => 'sanitize_text_field', - 'descentOverride' => 'sanitize_text_field', - 'fontVariant' => 'sanitize_text_field', - 'fontFeatureSettings' => 'sanitize_text_field', - 'fontVariationSettings' => 'sanitize_text_field', - 'lineGapOverride' => 'sanitize_text_field', - 'sizeAdjust' => 'sanitize_text_field', - 'unicodeRange' => 'sanitize_text_field', - ), - ), - ), - 'categories' => array( 'sanitize_title' ), - ), - ), - 'categories' => array( - array( - 'name' => 'sanitize_text_field', - 'slug' => 'sanitize_title', - ), - ), - ); - } - } -} diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-font-library.php b/lib/compat/wordpress-6.5/fonts/class-wp-font-library.php deleted file mode 100644 index eb4a269b3a8068..00000000000000 --- a/lib/compat/wordpress-6.5/fonts/class-wp-font-library.php +++ /dev/null @@ -1,145 +0,0 @@ -<?php -/** - * Font Library class. - * - * This file contains the Font Library class definition. - * - * @package WordPress - * @subpackage Font Library - * @since 6.5.0 - */ - -if ( ! class_exists( 'WP_Font_Library' ) ) { - - /** - * Font Library class. - * - * @since 6.5.0 - */ - class WP_Font_Library { - - /** - * Font collections. - * - * @since 6.5.0 - * @var array - */ - private $collections = array(); - - /** - * Container for the main instance of the class. - * - * @since 6.5.0 - * @var WP_Font_Library|null - */ - private static $instance = null; - - /** - * Register a new font collection. - * - * @since 6.5.0 - * - * @param string $slug Font collection slug. May only contain alphanumeric characters, dashes, - * and underscores. See sanitize_title(). - * @param array $args Font collection data. See wp_register_font_collection() for information on accepted arguments. - * @return WP_Font_Collection|WP_Error A font collection if it was registered successfully, - * or WP_Error object on failure. - */ - public function register_font_collection( string $slug, array $args ) { - $new_collection = new WP_Font_Collection( $slug, $args ); - - if ( $this->is_collection_registered( $new_collection->slug ) ) { - $error_message = sprintf( - /* translators: %s: Font collection slug. */ - __( 'Font collection with slug: "%s" is already registered.', 'gutenberg' ), - $new_collection->slug - ); - _doing_it_wrong( - __METHOD__, - $error_message, - '6.5.0' - ); - return new WP_Error( 'font_collection_registration_error', $error_message ); - } - $this->collections[ $new_collection->slug ] = $new_collection; - return $new_collection; - } - - /** - * Unregisters a previously registered font collection. - * - * @since 6.5.0 - * - * @param string $slug Font collection slug. - * @return bool True if the font collection was unregistered successfully and false otherwise. - */ - public function unregister_font_collection( string $slug ) { - if ( ! $this->is_collection_registered( $slug ) ) { - _doing_it_wrong( - __METHOD__, - /* translators: %s: Font collection slug. */ - sprintf( __( 'Font collection "%s" not found.' ), $slug ), - '6.5.0' - ); - return false; - } - unset( $this->collections[ $slug ] ); - return true; - } - - /** - * Checks if a font collection is registered. - * - * @since 6.5.0 - * - * @param string $slug Font collection slug. - * @return bool True if the font collection is registered and false otherwise. - */ - private function is_collection_registered( string $slug ) { - return array_key_exists( $slug, $this->collections ); - } - - /** - * Gets all the font collections available. - * - * @since 6.5.0 - * - * @return array List of font collections. - */ - public function get_font_collections() { - return $this->collections; - } - - /** - * Gets a font collection. - * - * @since 6.5.0 - * - * @param string $slug Font collection slug. - * @return WP_Font_Collection|null Font collection object, or null if the font collection doesn't exist. - */ - public function get_font_collection( string $slug ) { - if ( $this->is_collection_registered( $slug ) ) { - return $this->collections[ $slug ]; - } - return null; - } - - /** - * Utility method to retrieve the main instance of the class. - * - * The instance will be created if it does not exist yet. - * - * @since 6.5.0 - * - * @return WP_Font_Library The main instance. - */ - public static function get_instance() { - if ( null === self::$instance ) { - self::$instance = new self(); - } - - return self::$instance; - } - } -} diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php b/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php deleted file mode 100644 index d794a2601f45d5..00000000000000 --- a/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php +++ /dev/null @@ -1,260 +0,0 @@ -<?php -/** - * Font Utils class. - * - * Provides utility functions for working with font families. - * - * @package WordPress - * @subpackage Font Library - * @since 6.5.0 - */ - -if ( ! class_exists( 'WP_Font_Utils' ) ) { - - /** - * A class of utilities for working with the Font Library. - * - * These utilities may change or be removed in the future and are intended for internal use only. - * - * @since 6.5.0 - * @access private - */ - class WP_Font_Utils { - - /** - * Adds surrounding quotes to font family names that contain special characters. - * - * It follows the recommendations from the CSS Fonts Module Level 4. - * @link https://www.w3.org/TR/css-fonts-4/#font-family-prop - * - * @since 6.5.0 - * - * @param string $item A font family name. - * @return string The font family name with surrounding quotes, if necessary. - */ - private static function maybe_add_quotes( $item ) { - // Matches strings that are not exclusively alphabetic characters or hyphens, and do not exactly follow the pattern generic(alphabetic characters or hyphens). - $regex = '/^(?!generic\([a-zA-Z\-]+\)$)(?!^[a-zA-Z\-]+$).+/'; - $item = trim( $item ); - if ( preg_match( $regex, $item ) ) { - $item = trim( $item, "\"'" ); - return '"' . $item . '"'; - } - return $item; - } - - /** - * Sanitizes and formats font family names. - * - * - Applies `sanitize_text_field`. - * - Adds surrounding quotes to names containing any characters that are not alphabetic or dashes. - * - * It follows the recommendations from the CSS Fonts Module Level 4. - * @link https://www.w3.org/TR/css-fonts-4/#font-family-prop - * - * @since 6.5.0 - * @access private - * - * @see sanitize_text_field() - * - * @param string $font_family Font family name(s), comma-separated. - * @return string Sanitized and formatted font family name(s). - */ - public static function sanitize_font_family( $font_family ) { - if ( ! $font_family ) { - return ''; - } - - $output = sanitize_text_field( $font_family ); - $formatted_items = array(); - if ( str_contains( $output, ',' ) ) { - $items = explode( ',', $output ); - foreach ( $items as $item ) { - $formatted_item = self::maybe_add_quotes( $item ); - if ( ! empty( $formatted_item ) ) { - $formatted_items[] = $formatted_item; - } - } - return implode( ', ', $formatted_items ); - } - return self::maybe_add_quotes( $output ); - } - - /** - * Generates a slug from font face properties, e.g. `open sans;normal;400;100%;U+0-10FFFF` - * - * Used for comparison with other font faces in the same family, to prevent duplicates - * that would both match according the CSS font matching spec. Uses only simple case-insensitive - * matching for fontFamily and unicodeRange, so does not handle overlapping font-family lists or - * unicode ranges. - * - * @since 6.5.0 - * @access private - * - * @link https://drafts.csswg.org/css-fonts/#font-style-matching - * - * @param array $settings { - * Font face settings. - * - * @type string $fontFamily Font family name. - * @type string $fontStyle Optional font style, defaults to 'normal'. - * @type string $fontWeight Optional font weight, defaults to 400. - * @type string $fontStretch Optional font stretch, defaults to '100%'. - * @type string $unicodeRange Optional unicode range, defaults to 'U+0-10FFFF'. - * } - * @return string Font face slug. - */ - public static function get_font_face_slug( $settings ) { - $defaults = array( - 'fontFamily' => '', - 'fontStyle' => 'normal', - 'fontWeight' => '400', - 'fontStretch' => '100%', - 'unicodeRange' => 'U+0-10FFFF', - ); - $settings = wp_parse_args( $settings, $defaults ); - - $font_family = mb_strtolower( $settings['fontFamily'] ); - $font_style = strtolower( $settings['fontStyle'] ); - $font_weight = strtolower( $settings['fontWeight'] ); - $font_stretch = strtolower( $settings['fontStretch'] ); - $unicode_range = strtoupper( $settings['unicodeRange'] ); - - // Convert weight keywords to numeric strings. - $font_weight = str_replace( array( 'normal', 'bold' ), array( '400', '700' ), $font_weight ); - - // Convert stretch keywords to numeric strings. - $font_stretch_map = array( - 'ultra-condensed' => '50%', - 'extra-condensed' => '62.5%', - 'condensed' => '75%', - 'semi-condensed' => '87.5%', - 'normal' => '100%', - 'semi-expanded' => '112.5%', - 'expanded' => '125%', - 'extra-expanded' => '150%', - 'ultra-expanded' => '200%', - ); - $font_stretch = str_replace( array_keys( $font_stretch_map ), array_values( $font_stretch_map ), $font_stretch ); - - $slug_elements = array( $font_family, $font_style, $font_weight, $font_stretch, $unicode_range ); - - $slug_elements = array_map( - function ( $elem ) { - // Remove quotes to normalize font-family names, and ';' to use as a separator. - $elem = trim( str_replace( array( '"', "'", ';' ), '', $elem ) ); - - // Normalize comma separated lists by removing whitespace in between items, - // but keep whitespace within items (e.g. "Open Sans" and "OpenSans" are different fonts). - // CSS spec for whitespace includes: U+000A LINE FEED, U+0009 CHARACTER TABULATION, or U+0020 SPACE, - // which by default are all matched by \s in PHP. - return preg_replace( '/,\s+/', ',', $elem ); - }, - $slug_elements - ); - - return sanitize_text_field( join( ';', $slug_elements ) ); - } - - /** - * Sanitizes a tree of data using a schema. - * - * The schema structure should mirror the data tree. Each value provided in the - * schema should be a callable that will be applied to sanitize the corresponding - * value in the data tree. Keys that are in the data tree, but not present in the - * schema, will be removed in the sanitized data. Nested arrays are traversed recursively. - * - * @since 6.5.0 - * - * @access private - * - * @param array $tree The data to sanitize. - * @param array $schema The schema used for sanitization. - * @return array The sanitized data. - */ - public static function sanitize_from_schema( $tree, $schema ) { - if ( ! is_array( $tree ) || ! is_array( $schema ) ) { - return array(); - } - - foreach ( $tree as $key => $value ) { - // Remove keys not in the schema or with null/empty values. - if ( ! array_key_exists( $key, $schema ) ) { - unset( $tree[ $key ] ); - continue; - } - - $is_value_array = is_array( $value ); - $is_schema_array = is_array( $schema[ $key ] ) && ! is_callable( $schema[ $key ] ); - - if ( $is_value_array && $is_schema_array ) { - if ( wp_is_numeric_array( $value ) ) { - // If indexed, process each item in the array. - foreach ( $value as $item_key => $item_value ) { - $tree[ $key ][ $item_key ] = isset( $schema[ $key ][0] ) && is_array( $schema[ $key ][0] ) - ? self::sanitize_from_schema( $item_value, $schema[ $key ][0] ) - : self::apply_sanitizer( $item_value, $schema[ $key ][0] ); - } - } else { - // If it is an associative or indexed array, process as a single object. - $tree[ $key ] = self::sanitize_from_schema( $value, $schema[ $key ] ); - } - } elseif ( ! $is_value_array && $is_schema_array ) { - // If the value is not an array but the schema is, remove the key. - unset( $tree[ $key ] ); - } elseif ( ! $is_schema_array ) { - // If the schema is not an array, apply the sanitizer to the value. - $tree[ $key ] = self::apply_sanitizer( $value, $schema[ $key ] ); - } - - // Remove keys with null/empty values. - if ( empty( $tree[ $key ] ) ) { - unset( $tree[ $key ] ); - } - } - - return $tree; - } - - /** - * Applies a sanitizer function to a value. - * - * @since 6.5.0 - * - * @param mixed $value The value to sanitize. - * @param mixed $sanitizer The sanitizer function to apply. - * @return mixed The sanitized value. - */ - private static function apply_sanitizer( $value, $sanitizer ) { - if ( null === $sanitizer ) { - return $value; - - } - return call_user_func( $sanitizer, $value ); - } - - /** - * Returns the expected mime-type values for font files, depending on PHP version. - * - * This is needed because font mime types vary by PHP version, so checking the PHP version - * is necessary until a list of valid mime-types for each file extension can be provided to - * the 'upload_mimes' filter. - * - * @since 6.5.0 - * - * @access private - * - * @return array A collection of mime types keyed by file extension. - */ - public static function get_allowed_font_mime_types() { - $php_7_ttf_mime_type = PHP_VERSION_ID >= 70300 ? 'application/font-sfnt' : 'application/x-font-ttf'; - - return array( - 'otf' => 'application/vnd.ms-opentype', - 'ttf' => PHP_VERSION_ID >= 70400 ? 'font/sfnt' : $php_7_ttf_mime_type, - 'woff' => PHP_VERSION_ID >= 80112 ? 'font/woff' : 'application/font-woff', - 'woff2' => PHP_VERSION_ID >= 80112 ? 'font/woff2' : 'application/font-woff2', - ); - } - } -} diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-collections-controller.php b/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-collections-controller.php deleted file mode 100644 index 5221fbd63834fb..00000000000000 --- a/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-collections-controller.php +++ /dev/null @@ -1,326 +0,0 @@ -<?php -/** - * Rest Font Collections Controller. - * - * This file contains the class for the REST API Font Collections Controller. - * - * @package WordPress - * @subpackage Font Library - * @since 6.5.0 - */ - -if ( ! class_exists( 'WP_REST_Font_Collections_Controller' ) ) { - - /** - * Font Library Controller class. - * - * @since 6.5.0 - */ - class WP_REST_Font_Collections_Controller extends WP_REST_Controller { - - /** - * Constructor. - * - * @since 6.5.0 - */ - public function __construct() { - $this->rest_base = 'font-collections'; - $this->namespace = 'wp/v2'; - } - - /** - * Registers the routes for the objects of the controller. - * - * @since 6.5.0 - */ - public function register_routes() { - register_rest_route( - $this->namespace, - '/' . $this->rest_base, - array( - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_items' ), - 'permission_callback' => array( $this, 'get_items_permissions_check' ), - 'args' => $this->get_collection_params(), - - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) - ); - - register_rest_route( - $this->namespace, - '/' . $this->rest_base . '/(?P<slug>[\/\w-]+)', - array( - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_item' ), - 'permission_callback' => array( $this, 'get_items_permissions_check' ), - 'args' => array( - 'context' => $this->get_context_param( array( 'default' => 'view' ) ), - ), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) - ); - } - - /** - * Gets the font collections available. - * - * @since 6.5.0 - * - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_items( $request ) { - $collections_all = WP_Font_Library::get_instance()->get_font_collections(); - - $page = $request['page']; - $per_page = $request['per_page']; - $total_items = count( $collections_all ); - $max_pages = ceil( $total_items / $per_page ); - - if ( $page > $max_pages && $total_items > 0 ) { - return new WP_Error( - 'rest_post_invalid_page_number', - __( 'The page number requested is larger than the number of pages available.' ), - array( 'status' => 400 ) - ); - } - - $collections_page = array_slice( $collections_all, ( $page - 1 ) * $per_page, $per_page ); - - $items = array(); - foreach ( $collections_page as $collection ) { - $item = $this->prepare_item_for_response( $collection, $request ); - - // If there's an error loading a collection, skip it and continue loading valid collections. - if ( is_wp_error( $item ) ) { - continue; - } - $item = $this->prepare_response_for_collection( $item ); - $items[] = $item; - } - - $response = rest_ensure_response( $items ); - - $response->header( 'X-WP-Total', (int) $total_items ); - $response->header( 'X-WP-TotalPages', $max_pages ); - - $request_params = $request->get_query_params(); - $collection_url = rest_url( $this->namespace . '/' . $this->rest_base ); - $base = add_query_arg( urlencode_deep( $request_params ), $collection_url ); - - if ( $page > 1 ) { - $prev_page = $page - 1; - - if ( $prev_page > $max_pages ) { - $prev_page = $max_pages; - } - - $prev_link = add_query_arg( 'page', $prev_page, $base ); - $response->link_header( 'prev', $prev_link ); - } - if ( $max_pages > $page ) { - $next_page = $page + 1; - $next_link = add_query_arg( 'page', $next_page, $base ); - - $response->link_header( 'next', $next_link ); - } - - return $response; - } - - /** - * Gets a font collection. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_item( $request ) { - $slug = $request->get_param( 'slug' ); - $collection = WP_Font_Library::get_instance()->get_font_collection( $slug ); - - // @todo remove `is_wp_error` check once WP trunk is updated to return null when a collection is not found. - if ( ! $collection || is_wp_error( $collection ) ) { - return new WP_Error( 'rest_font_collection_not_found', __( 'Font collection not found.' ), array( 'status' => 404 ) ); - } - - return $this->prepare_item_for_response( $collection, $request ); - } - - /** - * Prepare a single collection output for response. - * - * @since 6.5.0 - * - * @param WP_Font_Collection $item Font collection object. - * @param WP_REST_Request $request Request object. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function prepare_item_for_response( $item, $request ) { - $fields = $this->get_fields_for_response( $request ); - $data = array(); - - if ( rest_is_field_included( 'slug', $fields ) ) { - $data['slug'] = $item->slug; - } - - // If any data fields are requested, get the collection data. - $data_fields = array( 'name', 'description', 'font_families', 'categories' ); - if ( ! empty( array_intersect( $fields, $data_fields ) ) ) { - $collection_data = $item->get_data(); - if ( is_wp_error( $collection_data ) ) { - $collection_data->add_data( array( 'status' => 500 ) ); - return $collection_data; - } - - foreach ( $data_fields as $field ) { - if ( rest_is_field_included( $field, $fields ) ) { - $data[ $field ] = $collection_data[ $field ]; - } - } - } - - $response = rest_ensure_response( $data ); - - if ( rest_is_field_included( '_links', $fields ) ) { - $links = $this->prepare_links( $item ); - $response->add_links( $links ); - } - - $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; - $response->data = $this->add_additional_fields_to_object( $response->data, $request ); - $response->data = $this->filter_response_by_context( $response->data, $context ); - - /** - * Filters the font collection data for a REST API response. - * - * @since 6.5.0 - * - * @param WP_REST_Response $response The response object. - * @param WP_Font_Collection $item The font collection object. - * @param WP_REST_Request $request Request used to generate the response. - */ - return apply_filters( 'rest_prepare_font_collection', $response, $item, $request ); - } - - /** - * Retrieves the font collection's schema, conforming to JSON Schema. - * - * @since 6.5.0 - * - * @return array Item schema data. - */ - public function get_item_schema() { - if ( $this->schema ) { - return $this->add_additional_fields_schema( $this->schema ); - } - - $schema = array( - '$schema' => 'http://json-schema.org/draft-04/schema#', - 'title' => 'font-collection', - 'type' => 'object', - 'properties' => array( - 'slug' => array( - 'description' => __( 'Unique identifier for the font collection.', 'gutenberg' ), - 'type' => 'string', - 'context' => array( 'view', 'edit', 'embed' ), - 'readonly' => true, - ), - 'name' => array( - 'description' => __( 'The name for the font collection.', 'gutenberg' ), - 'type' => 'string', - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'description' => array( - 'description' => __( 'The description for the font collection.', 'gutenberg' ), - 'type' => 'string', - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'font_families' => array( - 'description' => __( 'The font families for the font collection.', 'gutenberg' ), - 'type' => 'array', - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'categories' => array( - 'description' => __( 'The categories for the font collection.', 'gutenberg' ), - 'type' => 'array', - 'context' => array( 'view', 'edit', 'embed' ), - ), - ), - ); - - $this->schema = $schema; - - return $this->add_additional_fields_schema( $this->schema ); - } - - /** - * Prepares links for the request. - * - * @since 6.5.0 - * - * @param WP_Font_Collection $collection Font collection data - * @return array Links for the given font collection. - */ - protected function prepare_links( $collection ) { - return array( - 'self' => array( - 'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $collection->slug ) ), - ), - 'collection' => array( - 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ), - ), - ); - } - - /** - * Retrieves the search params for the font collections. - * - * @since 6.5.0 - * - * @return array Collection parameters. - */ - public function get_collection_params() { - $query_params = parent::get_collection_params(); - - $query_params['context'] = $this->get_context_param( array( 'default' => 'view' ) ); - - unset( $query_params['search'] ); - - /** - * Filters REST API collection parameters for the font collections controller. - * - * @since 6.5.0 - * - * @param array $query_params JSON Schema-formatted collection parameters. - */ - return apply_filters( 'rest_font_collections_collection_params', $query_params ); - } - - /** - * Checks whether the user has permissions to use the Fonts Collections. - * - * @since 6.5.0 - * - * @return true|WP_Error True if the request has write access for the item, WP_Error object otherwise. - */ - public function get_items_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable - if ( current_user_can( 'edit_theme_options' ) ) { - return true; - } - - return new WP_Error( - 'rest_cannot_read', - __( 'Sorry, you are not allowed to access font collections.', 'gutenberg' ), - array( - 'status' => rest_authorization_required_code(), - ) - ); - } - } -} diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-faces-controller.php b/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-faces-controller.php deleted file mode 100644 index e844e7a8fe8730..00000000000000 --- a/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-faces-controller.php +++ /dev/null @@ -1,952 +0,0 @@ -<?php -/** - * REST API: WP_REST_Font_Faces_Controller class - * - * @package WordPress - * @subpackage REST_API - * @since 6.5.0 - */ - -if ( ! class_exists( 'WP_REST_Font_Faces_Controller' ) ) { - - /** - * Class to access font faces through the REST API. - */ - class WP_REST_Font_Faces_Controller extends WP_REST_Posts_Controller { - - /** - * The latest version of theme.json schema supported by the controller. - * - * @since 6.5.0 - * @var int - */ - const LATEST_THEME_JSON_VERSION_SUPPORTED = 2; - - /** - * Whether the controller supports batching. - * - * @since 6.5.0 - * @var false - */ - protected $allow_batch = false; - - /** - * Registers the routes for posts. - * - * @since 6.5.0 - * - * @see register_rest_route() - */ - public function register_routes() { - register_rest_route( - $this->namespace, - '/' . $this->rest_base, - array( - 'args' => array( - 'font_family_id' => array( - 'description' => __( 'The ID for the parent font family of the font face.', 'gutenberg' ), - 'type' => 'integer', - 'required' => true, - ), - ), - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_items' ), - 'permission_callback' => array( $this, 'get_items_permissions_check' ), - 'args' => $this->get_collection_params(), - ), - array( - 'methods' => WP_REST_Server::CREATABLE, - 'callback' => array( $this, 'create_item' ), - 'permission_callback' => array( $this, 'create_item_permissions_check' ), - 'args' => $this->get_create_params(), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) - ); - - register_rest_route( - $this->namespace, - '/' . $this->rest_base . '/(?P<id>[\d]+)', - array( - 'args' => array( - 'font_family_id' => array( - 'description' => __( 'The ID for the parent font family of the font face.', 'gutenberg' ), - 'type' => 'integer', - 'required' => true, - ), - 'id' => array( - 'description' => __( 'Unique identifier for the font face.', 'gutenberg' ), - 'type' => 'integer', - 'required' => true, - ), - ), - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_item' ), - 'permission_callback' => array( $this, 'get_item_permissions_check' ), - 'args' => array( - 'context' => $this->get_context_param( array( 'default' => 'view' ) ), - ), - ), - array( - 'methods' => WP_REST_Server::DELETABLE, - 'callback' => array( $this, 'delete_item' ), - 'permission_callback' => array( $this, 'delete_item_permissions_check' ), - 'args' => array( - 'force' => array( - 'type' => 'boolean', - 'default' => false, - 'description' => __( 'Whether to bypass Trash and force deletion.', 'default' ), - ), - ), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) - ); - } - - /** - * Checks if a given request has access to font faces. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return true|WP_Error True if the request has read access, WP_Error object otherwise. - */ - public function get_items_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- required by parent class - $post_type = get_post_type_object( $this->post_type ); - - if ( ! current_user_can( $post_type->cap->read ) ) { - return new WP_Error( - 'rest_cannot_read', - __( 'Sorry, you are not allowed to access font faces.', 'gutenberg' ), - array( 'status' => rest_authorization_required_code() ) - ); - } - - return true; - } - - /** - * Checks if a given request has access to a font face. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return true|WP_Error True if the request has read access, WP_Error object otherwise. - */ - public function get_item_permissions_check( $request ) { - $post = $this->get_post( $request['id'] ); - if ( is_wp_error( $post ) ) { - return $post; - } - - if ( ! current_user_can( 'read_post', $post->ID ) ) { - return new WP_Error( - 'rest_cannot_read', - __( 'Sorry, you are not allowed to access this font face.', 'gutenberg' ), - array( 'status' => rest_authorization_required_code() ) - ); - } - - return true; - } - - /** - * Validates settings when creating a font face. - * - * @since 6.5.0 - * - * @param string $value Encoded JSON string of font face settings. - * @param WP_REST_Request $request Request object. - * @return true|WP_Error True if the settings are valid, otherwise a WP_Error object. - */ - public function validate_create_font_face_settings( $value, $request ) { - $settings = json_decode( $value, true ); - - // Check settings string is valid JSON. - if ( null === $settings ) { - return new WP_Error( - 'rest_invalid_param', - __( 'font_face_settings parameter must be a valid JSON string.', 'gutenberg' ), - array( 'status' => 400 ) - ); - } - - // Check that the font face settings match the theme.json schema. - $schema = $this->get_item_schema()['properties']['font_face_settings']; - $has_valid_settings = rest_validate_value_from_schema( $settings, $schema, 'font_face_settings' ); - - if ( is_wp_error( $has_valid_settings ) ) { - $has_valid_settings->add_data( array( 'status' => 400 ) ); - return $has_valid_settings; - } - - // Check that none of the required settings are empty values. - $required = $schema['required']; - foreach ( $required as $key ) { - if ( isset( $settings[ $key ] ) && ! $settings[ $key ] ) { - return new WP_Error( - 'rest_invalid_param', - /* translators: %s: Name of the missing font face settings parameter, e.g. "font_face_settings[src]". */ - sprintf( __( '%s cannot be empty.', 'gutenberg' ), "font_face_setting[ $key ]" ), - array( 'status' => 400 ) - ); - } - } - - $srcs = is_array( $settings['src'] ) ? $settings['src'] : array( $settings['src'] ); - $files = $request->get_file_params(); - - foreach ( $srcs as $src ) { - // Check that each src is a non-empty string. - $src = ltrim( $src ); - if ( empty( $src ) ) { - return new WP_Error( - 'rest_invalid_param', - /* translators: %s: Font face source parameter name: "font_face_settings[src]". */ - sprintf( __( '%s values must be non-empty strings.', 'gutenberg' ), 'font_face_settings[src]' ), - array( 'status' => 400 ) - ); - } - - // Check that srcs are valid URLs or file references. - if ( false === wp_http_validate_url( $src ) && ! isset( $files[ $src ] ) ) { - return new WP_Error( - 'rest_invalid_param', - /* translators: 1: Font face source parameter name: "font_face_settings[src]", 2: The invalid src value. */ - sprintf( __( '%1$s value "%2$s" must be a valid URL or file reference.', 'gutenberg' ), 'font_face_settings[src]', $src ), - array( 'status' => 400 ) - ); - } - } - - // Check that each file in the request references a src in the settings. - foreach ( array_keys( $files ) as $file ) { - if ( ! in_array( $file, $srcs, true ) ) { - return new WP_Error( - 'rest_invalid_param', - /* translators: 1: File key (e.g. "file-0") in the request data, 2: Font face source parameter name: "font_face_settings[src]". */ - sprintf( __( 'File %1$s must be used in %2$s.', 'gutenberg' ), $file, 'font_face_settings[src]' ), - array( 'status' => 400 ) - ); - } - } - - return true; - } - - /** - * Sanitizes the font face settings when creating a font face. - * - * @since 6.5.0 - * - * @param string $value Encoded JSON string of font face settings. - * @return array Decoded and sanitized array of font face settings. - */ - public function sanitize_font_face_settings( $value ) { - // Settings arrive as stringified JSON, since this is a multipart/form-data request. - $settings = json_decode( $value, true ); - $schema = $this->get_item_schema()['properties']['font_face_settings']['properties']; - - // Sanitize settings based on callbacks in the schema. - foreach ( $settings as $key => $value ) { - $sanitize_callback = $schema[ $key ]['arg_options']['sanitize_callback']; - $settings[ $key ] = call_user_func( $sanitize_callback, $value ); - } - - return $settings; - } - - /** - * Retrieves a collection of font faces within the parent font family. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_items( $request ) { - $font_family = $this->get_parent_font_family_post( $request['font_family_id'] ); - if ( is_wp_error( $font_family ) ) { - return $font_family; - } - - return parent::get_items( $request ); - } - - /** - * Retrieves a single font face within the parent font family. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_item( $request ) { - $post = $this->get_post( $request['id'] ); - if ( is_wp_error( $post ) ) { - return $post; - } - - // Check that the font face has a valid parent font family. - $font_family = $this->get_parent_font_family_post( $request['font_family_id'] ); - if ( is_wp_error( $font_family ) ) { - return $font_family; - } - - if ( (int) $font_family->ID !== (int) $post->post_parent ) { - return new WP_Error( - 'rest_font_face_parent_id_mismatch', - /* translators: %d: A post id. */ - sprintf( __( 'The font face does not belong to the specified font family with id of "%d".', 'gutenberg' ), $font_family->ID ), - array( 'status' => 404 ) - ); - } - - return parent::get_item( $request ); - } - - /** - * Creates a font face for the parent font family. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function create_item( $request ) { - $font_family = $this->get_parent_font_family_post( $request['font_family_id'] ); - if ( is_wp_error( $font_family ) ) { - return $font_family; - } - - // Settings have already been decoded by ::sanitize_font_face_settings(). - $settings = $request->get_param( 'font_face_settings' ); - $file_params = $request->get_file_params(); - - // Check that the necessary font face properties are unique. - $query = new WP_Query( - array( - 'post_type' => $this->post_type, - 'posts_per_page' => 1, - 'title' => WP_Font_Utils::get_font_face_slug( $settings ), - 'update_post_meta_cache' => false, - 'update_post_term_cache' => false, - ) - ); - if ( ! empty( $query->posts ) ) { - return new WP_Error( - 'rest_duplicate_font_face', - __( 'A font face matching those settings already exists.', 'gutenberg' ), - array( 'status' => 400 ) - ); - } - - // Move the uploaded font asset from the temp folder to the fonts directory. - if ( ! function_exists( 'wp_handle_upload' ) ) { - require_once ABSPATH . 'wp-admin/includes/file.php'; - } - - $srcs = is_string( $settings['src'] ) ? array( $settings['src'] ) : $settings['src']; - $processed_srcs = array(); - $font_file_meta = array(); - - foreach ( $srcs as $src ) { - // If src not a file reference, use it as is. - if ( ! isset( $file_params[ $src ] ) ) { - $processed_srcs[] = $src; - continue; - } - - $file = $file_params[ $src ]; - $font_file = $this->handle_font_file_upload( $file ); - if ( is_wp_error( $font_file ) ) { - return $font_file; - } - - $processed_srcs[] = $font_file['url']; - $font_file_meta[] = $this->relative_fonts_path( $font_file['file'] ); - } - - // Store the updated settings for prepare_item_for_database to use. - $settings['src'] = count( $processed_srcs ) === 1 ? $processed_srcs[0] : $processed_srcs; - $request->set_param( 'font_face_settings', $settings ); - - // Ensure that $settings data is slashed, so values with quotes are escaped. - // WP_REST_Posts_Controller::create_item uses wp_slash() on the post_content. - $font_face_post = parent::create_item( $request ); - - if ( is_wp_error( $font_face_post ) ) { - return $font_face_post; - } - - $font_face_id = $font_face_post->data['id']; - - foreach ( $font_file_meta as $font_file_path ) { - add_post_meta( $font_face_id, '_wp_font_face_file', $font_file_path ); - } - - return $font_face_post; - } - - /** - * Deletes a single font face. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function delete_item( $request ) { - $post = $this->get_post( $request['id'] ); - if ( is_wp_error( $post ) ) { - return $post; - } - - $font_family = $this->get_parent_font_family_post( $request['font_family_id'] ); - if ( is_wp_error( $font_family ) ) { - return $font_family; - } - - if ( (int) $font_family->ID !== (int) $post->post_parent ) { - return new WP_Error( - 'rest_font_face_parent_id_mismatch', - /* translators: %d: A post id. */ - sprintf( __( 'The font face does not belong to the specified font family with id of "%d".', 'gutenberg' ), $font_family->ID ), - array( 'status' => 404 ) - ); - } - - $force = isset( $request['force'] ) ? (bool) $request['force'] : false; - - // We don't support trashing for font faces. - if ( ! $force ) { - return new WP_Error( - 'rest_trash_not_supported', - /* translators: %s: force=true */ - sprintf( __( 'Font faces do not support trashing. Set "%s" to delete.', 'gutenberg' ), 'force=true' ), - array( 'status' => 501 ) - ); - } - - return parent::delete_item( $request ); - } - - /** - * Prepares a single font face output for response. - * - * @since 6.5.0 - * - * @param WP_Post $item Post object. - * @param WP_REST_Request $request Request object. - * @return WP_REST_Response Response object. - */ - public function prepare_item_for_response( $item, $request ) { - $fields = $this->get_fields_for_response( $request ); - $data = array(); - - if ( rest_is_field_included( 'id', $fields ) ) { - $data['id'] = $item->ID; - } - if ( rest_is_field_included( 'theme_json_version', $fields ) ) { - $data['theme_json_version'] = static::LATEST_THEME_JSON_VERSION_SUPPORTED; - } - - if ( rest_is_field_included( 'parent', $fields ) ) { - $data['parent'] = $item->post_parent; - } - - if ( rest_is_field_included( 'font_face_settings', $fields ) ) { - $data['font_face_settings'] = $this->get_settings_from_post( $item ); - } - - $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; - $data = $this->add_additional_fields_to_object( $data, $request ); - $data = $this->filter_response_by_context( $data, $context ); - - $response = rest_ensure_response( $data ); - - if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { - $links = $this->prepare_links( $item ); - $response->add_links( $links ); - } - - /** - * Filters the font face data for a REST API response. - * - * @since 6.5.0 - * - * @param WP_REST_Response $response The response object. - * @param WP_Post $post Font face post object. - * @param WP_REST_Request $request Request object. - */ - return apply_filters( 'rest_prepare_wp_font_face', $response, $item, $request ); - } - - /** - * Retrieves the post's schema, conforming to JSON Schema. - * - * @since 6.5.0 - * - * @return array Item schema data. - */ - public function get_item_schema() { - if ( $this->schema ) { - return $this->add_additional_fields_schema( $this->schema ); - } - - $schema = array( - '$schema' => 'http://json-schema.org/draft-04/schema#', - 'title' => $this->post_type, - 'type' => 'object', - // Base properties for every Post. - 'properties' => array( - 'id' => array( - 'description' => __( 'Unique identifier for the post.', 'default' ), - 'type' => 'integer', - 'context' => array( 'view', 'edit', 'embed' ), - 'readonly' => true, - ), - 'theme_json_version' => array( - 'description' => __( 'Version of the theme.json schema used for the typography settings.', 'gutenberg' ), - 'type' => 'integer', - 'default' => static::LATEST_THEME_JSON_VERSION_SUPPORTED, - 'minimum' => 2, - 'maximum' => static::LATEST_THEME_JSON_VERSION_SUPPORTED, - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'parent' => array( - 'description' => __( 'The ID for the parent font family of the font face.', 'gutenberg' ), - 'type' => 'integer', - 'context' => array( 'view', 'edit', 'embed' ), - ), - // Font face settings come directly from theme.json schema - // See https://schemas.wp.org/trunk/theme.json - 'font_face_settings' => array( - 'description' => __( 'font-face declaration in theme.json format.', 'gutenberg' ), - 'type' => 'object', - 'context' => array( 'view', 'edit', 'embed' ), - 'properties' => array( - 'fontFamily' => array( - 'description' => __( 'CSS font-family value.', 'gutenberg' ), - 'type' => 'string', - 'default' => '', - 'arg_options' => array( - 'sanitize_callback' => array( 'WP_Font_Utils', 'sanitize_font_family' ), - ), - ), - 'fontStyle' => array( - 'description' => __( 'CSS font-style value.', 'gutenberg' ), - 'type' => 'string', - 'default' => 'normal', - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_text_field', - ), - ), - 'fontWeight' => array( - 'description' => __( 'List of available font weights, separated by a space.', 'gutenberg' ), - 'default' => '400', - // Changed from `oneOf` to avoid errors from loose type checking. - // e.g. a fontWeight of "400" validates as both a string and an integer due to is_numeric check. - 'type' => array( 'string', 'integer' ), - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_text_field', - ), - ), - 'fontDisplay' => array( - 'description' => __( 'CSS font-display value.', 'gutenberg' ), - 'type' => 'string', - 'default' => 'fallback', - 'enum' => array( - 'auto', - 'block', - 'fallback', - 'swap', - 'optional', - ), - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_text_field', - ), - ), - 'src' => array( - 'description' => __( 'Paths or URLs to the font files.', 'gutenberg' ), - // Changed from `oneOf` to `anyOf` due to rest_sanitize_array converting a string into an array, - // and causing a "matches more than one of the expected formats" error. - 'anyOf' => array( - array( - 'type' => 'string', - ), - array( - 'type' => 'array', - 'items' => array( - 'type' => 'string', - ), - ), - ), - 'default' => array(), - 'arg_options' => array( - 'sanitize_callback' => function ( $value ) { - return is_array( $value ) ? array_map( array( $this, 'sanitize_src' ), $value ) : $this->sanitize_src( $value ); - }, - ), - ), - 'fontStretch' => array( - 'description' => __( 'CSS font-stretch value.', 'gutenberg' ), - 'type' => 'string', - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_text_field', - ), - ), - 'ascentOverride' => array( - 'description' => __( 'CSS ascent-override value.', 'gutenberg' ), - 'type' => 'string', - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_text_field', - ), - ), - 'descentOverride' => array( - 'description' => __( 'CSS descent-override value.', 'gutenberg' ), - 'type' => 'string', - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_text_field', - ), - ), - 'fontVariant' => array( - 'description' => __( 'CSS font-variant value.', 'gutenberg' ), - 'type' => 'string', - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_text_field', - ), - ), - 'fontFeatureSettings' => array( - 'description' => __( 'CSS font-feature-settings value.', 'gutenberg' ), - 'type' => 'string', - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_text_field', - ), - ), - 'fontVariationSettings' => array( - 'description' => __( 'CSS font-variation-settings value.', 'gutenberg' ), - 'type' => 'string', - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_text_field', - ), - ), - 'lineGapOverride' => array( - 'description' => __( 'CSS line-gap-override value.', 'gutenberg' ), - 'type' => 'string', - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_text_field', - ), - ), - 'sizeAdjust' => array( - 'description' => __( 'CSS size-adjust value.', 'gutenberg' ), - 'type' => 'string', - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_text_field', - ), - ), - 'unicodeRange' => array( - 'description' => __( 'CSS unicode-range value.', 'gutenberg' ), - 'type' => 'string', - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_text_field', - ), - ), - 'preview' => array( - 'description' => __( 'URL to a preview image of the font face.', 'gutenberg' ), - 'type' => 'string', - 'format' => 'uri', - 'default' => '', - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_url', - ), - ), - ), - 'required' => array( 'fontFamily', 'src' ), - 'additionalProperties' => false, - ), - ), - ); - - $this->schema = $schema; - - return $this->add_additional_fields_schema( $this->schema ); - } - - /** - * Retrieves the item's schema for display / public consumption purposes. - * - * @since 6.5.0 - * - * @return array Public item schema data. - */ - public function get_public_item_schema() { - - $schema = parent::get_public_item_schema(); - - // Also remove `arg_options' from child font_family_settings properties, since the parent - // controller only handles the top level properties. - foreach ( $schema['properties']['font_face_settings']['properties'] as &$property ) { - unset( $property['arg_options'] ); - } - - return $schema; - } - - /** - * Retrieves the query params for the font face collection. - * - * @since 6.5.0 - * - * @return array Collection parameters. - */ - public function get_collection_params() { - $query_params = parent::get_collection_params(); - - // Remove unneeded params. - unset( - $query_params['after'], - $query_params['modified_after'], - $query_params['before'], - $query_params['modified_before'], - $query_params['search'], - $query_params['search_columns'], - $query_params['slug'], - $query_params['status'] - ); - - $query_params['orderby']['default'] = 'id'; - $query_params['orderby']['enum'] = array( 'id', 'include' ); - - /** - * Filters collection parameters for the font face controller. - * - * @since 6.5.0 - * - * @param array $query_params JSON Schema-formatted collection parameters. - */ - return apply_filters( 'rest_wp_font_face_collection_params', $query_params ); - } - - /** - * Get the params used when creating a new font face. - * - * @since 6.5.0 - * - * @return array Font face create arguments. - */ - public function get_create_params() { - $properties = $this->get_item_schema()['properties']; - return array( - 'theme_json_version' => $properties['theme_json_version'], - // When creating, font_face_settings is stringified JSON, to work with multipart/form-data used - // when uploading font files. - 'font_face_settings' => array( - 'description' => __( 'font-face declaration in theme.json format, encoded as a string.', 'gutenberg' ), - 'type' => 'string', - 'required' => true, - 'validate_callback' => array( $this, 'validate_create_font_face_settings' ), - 'sanitize_callback' => array( $this, 'sanitize_font_face_settings' ), - ), - ); - } - - /** - * Get the parent font family, if the ID is valid. - * - * @since 6.5.0 - * - * @param int $font_family_id Supplied ID. - * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise. - */ - protected function get_parent_font_family_post( $font_family_id ) { - $error = new WP_Error( - 'rest_post_invalid_parent', - __( 'Invalid post parent ID.', 'default' ), - array( 'status' => 404 ) - ); - - if ( (int) $font_family_id <= 0 ) { - return $error; - } - - $font_family_post = get_post( (int) $font_family_id ); - - if ( empty( $font_family_post ) || empty( $font_family_post->ID ) - || 'wp_font_family' !== $font_family_post->post_type - ) { - return $error; - } - - return $font_family_post; - } - - /** - * Prepares links for the request. - * - * @since 6.5.0 - * - * @param WP_Post $post Post object. - * @return array Links for the given post. - */ - protected function prepare_links( $post ) { - // Entity meta. - return array( - 'self' => array( - 'href' => rest_url( $this->namespace . '/font-families/' . $post->post_parent . '/font-faces/' . $post->ID ), - ), - 'collection' => array( - 'href' => rest_url( $this->namespace . '/font-families/' . $post->post_parent . '/font-faces' ), - ), - 'parent' => array( - 'href' => rest_url( $this->namespace . '/font-families/' . $post->post_parent ), - ), - ); - } - - /** - * Prepares a single font face post for creation. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Request object. - * @return stdClass Post object. - */ - protected function prepare_item_for_database( $request ) { - $prepared_post = new stdClass(); - - // Settings have already been decoded by ::sanitize_font_face_settings(). - $settings = $request->get_param( 'font_face_settings' ); - - // Store this "slug" as the post_title rather than post_name, since it uses the fontFamily setting, - // which may contain multibyte characters. - $title = WP_Font_Utils::get_font_face_slug( $settings ); - - $prepared_post->post_type = $this->post_type; - $prepared_post->post_parent = $request['font_family_id']; - $prepared_post->post_status = 'publish'; - $prepared_post->post_title = $title; - $prepared_post->post_name = sanitize_title( $title ); - $prepared_post->post_content = wp_json_encode( $settings ); - - return $prepared_post; - } - - /** - * Sanitizes a single src value for a font face. - * - * @since 6.5.0 - * - * @param string $value Font face src that is a URL or the key for a $_FILES array item. - * @return string Sanitized value. - */ - protected function sanitize_src( $value ) { - $value = ltrim( $value ); - return false === wp_http_validate_url( $value ) ? (string) $value : sanitize_url( $value ); - } - - /** - * Handles the upload of a font file using wp_handle_upload(). - * - * @since 6.5.0 - * - * @param array $file Single file item from $_FILES. - * @return array|WP_Error Array containing uploaded file attributes on success, or WP_Error object on failure. - */ - protected function handle_font_file_upload( $file ) { - add_filter( 'upload_mimes', array( 'WP_Font_Utils', 'get_allowed_font_mime_types' ) ); - // Filter the upload directory to return the fonts directory. - add_filter( 'upload_dir', '_wp_filter_font_directory' ); - - $overrides = array( - 'upload_error_handler' => array( $this, 'handle_font_file_upload_error' ), - // Not testing a form submission. - 'test_form' => false, - // Only allow uploading font files for this request. - 'mimes' => WP_Font_Utils::get_allowed_font_mime_types(), - ); - - // Bypasses is_uploaded_file() when running unit tests. - if ( defined( 'DIR_TESTDATA' ) && DIR_TESTDATA ) { - $overrides['action'] = 'wp_handle_mock_upload'; - } - - $uploaded_file = wp_handle_upload( $file, $overrides ); - remove_filter( 'upload_dir', '_wp_filter_font_directory' ); - remove_filter( 'upload_mimes', array( 'WP_Font_Utils', 'get_allowed_font_mime_types' ) ); - - return $uploaded_file; - } - - /** - * Handles file upload error. - * - * @since 6.5.0 - * - * @param array $file File upload data. - * @param string $message Error message from wp_handle_upload(). - * @return WP_Error WP_Error object. - */ - public function handle_font_file_upload_error( $file, $message ) { - $status = 500; - $code = 'rest_font_upload_unknown_error'; - - if ( __( 'Sorry, you are not allowed to upload this file type.' ) === $message ) { - $status = 400; - $code = 'rest_font_upload_invalid_file_type'; - } - - return new WP_Error( $code, $message, array( 'status' => $status ) ); - } - - /** - * Returns relative path to an uploaded font file. - * - * The path is relative to the current fonts directory. - * - * @since 6.5.0 - * @access private - * - * @param string $path Full path to the file. - * @return string Relative path on success, unchanged path on failure. - */ - protected function relative_fonts_path( $path ) { - $new_path = $path; - - $fonts_dir = wp_get_font_dir(); - if ( str_starts_with( $new_path, $fonts_dir['basedir'] ) ) { - $new_path = str_replace( $fonts_dir['basedir'], '', $new_path ); - $new_path = ltrim( $new_path, '/' ); - } - - return $new_path; - } - - /** - * Gets the font face's settings from the post. - * - * @since 6.5.0 - * - * @param WP_Post $post Font face post object. - * @return array Font face settings array. - */ - protected function get_settings_from_post( $post ) { - $settings = json_decode( $post->post_content, true ); - $properties = $this->get_item_schema()['properties']['font_face_settings']['properties']; - - // Provide required, empty settings if needed. - if ( null === $settings ) { - $settings = array( - 'fontFamily' => '', - 'src' => array(), - ); - } - - // Only return the properties defined in the schema. - return array_intersect_key( $settings, $properties ); - } - } -} diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-families-controller.php b/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-families-controller.php deleted file mode 100644 index 4cde4d636cf9ff..00000000000000 --- a/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-families-controller.php +++ /dev/null @@ -1,567 +0,0 @@ -<?php -/** - * REST API: WP_REST_Font_Families_Controller class - * - * @package WordPress - * @subpackage REST_API - * @since 6.5.0 - */ - -if ( ! class_exists( 'WP_REST_Font_Families_Controller' ) ) { - - /** - * Font Families Controller class. - * - * @since 6.5.0 - */ - class WP_REST_Font_Families_Controller extends WP_REST_Posts_Controller { - - /** - * The latest version of theme.json schema supported by the controller. - * - * @since 6.5.0 - * @var int - */ - const LATEST_THEME_JSON_VERSION_SUPPORTED = 2; - - /** - * Whether the controller supports batching. - * - * @since 6.5.0 - * @var false - */ - protected $allow_batch = false; - - /** - * Checks if a given request has access to font families. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return true|WP_Error True if the request has read access, WP_Error object otherwise. - */ - public function get_items_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- required by parent class - $post_type = get_post_type_object( $this->post_type ); - - if ( ! current_user_can( $post_type->cap->read ) ) { - return new WP_Error( - 'rest_cannot_read', - __( 'Sorry, you are not allowed to access font families.', 'gutenberg' ), - array( 'status' => rest_authorization_required_code() ) - ); - } - - return true; - } - - /** - * Checks if a given request has access to a font family. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return true|WP_Error True if the request has read access, WP_Error object otherwise. - */ - public function get_item_permissions_check( $request ) { - $post = $this->get_post( $request['id'] ); - if ( is_wp_error( $post ) ) { - return $post; - } - - if ( ! current_user_can( 'read_post', $post->ID ) ) { - return new WP_Error( - 'rest_cannot_read', - __( 'Sorry, you are not allowed to access this font family.', 'gutenberg' ), - array( 'status' => rest_authorization_required_code() ) - ); - } - - return true; - } - - /** - * Validates settings when creating or updating a font family. - * - * @since 6.5.0 - * - * @param string $value Encoded JSON string of font family settings. - * @param WP_REST_Request $request Request object. - * @return true|WP_Error True if the settings are valid, otherwise a WP_Error object. - */ - public function validate_font_family_settings( $value, $request ) { - $settings = json_decode( $value, true ); - - // Check settings string is valid JSON. - if ( null === $settings ) { - return new WP_Error( - 'rest_invalid_param', - /* translators: %s: Parameter name: "font_family_settings". */ - sprintf( __( '%s parameter must be a valid JSON string.', 'gutenberg' ), 'font_family_settings' ), - array( 'status' => 400 ) - ); - } - - $schema = $this->get_item_schema()['properties']['font_family_settings']; - $required = $schema['required']; - - if ( isset( $request['id'] ) ) { - // Allow sending individual properties if we are updating an existing font family. - unset( $schema['required'] ); - - // But don't allow updating the slug, since it is used as a unique identifier. - if ( isset( $settings['slug'] ) ) { - return new WP_Error( - 'rest_invalid_param', - /* translators: %s: Name of parameter being updated: font_family_settings[slug]". */ - sprintf( __( '%s cannot be updated.', 'gutenberg' ), 'font_family_settings[slug]' ), - array( 'status' => 400 ) - ); - } - } - - // Check that the font face settings match the theme.json schema. - $has_valid_settings = rest_validate_value_from_schema( $settings, $schema, 'font_family_settings' ); - - if ( is_wp_error( $has_valid_settings ) ) { - $has_valid_settings->add_data( array( 'status' => 400 ) ); - return $has_valid_settings; - } - - // Check that none of the required settings are empty values. - foreach ( $required as $key ) { - if ( isset( $settings[ $key ] ) && ! $settings[ $key ] ) { - return new WP_Error( - 'rest_invalid_param', - /* translators: %s: Name of the empty font family setting parameter, e.g. "font_family_settings[slug]". */ - sprintf( __( '%s cannot be empty.', 'gutenberg' ), "font_family_settings[ $key ]" ), - array( 'status' => 400 ) - ); - } - } - - return true; - } - - /** - * Sanitizes the font family settings when creating or updating a font family. - * - * @since 6.5.0 - * - * @param string $value Encoded JSON string of font family settings. - * @return array Decoded array of font family settings. - */ - public function sanitize_font_family_settings( $value ) { - // Settings arrive as stringified JSON, since this is a multipart/form-data request. - $settings = json_decode( $value, true ); - $schema = $this->get_item_schema()['properties']['font_family_settings']['properties']; - - // Sanitize settings based on callbacks in the schema. - foreach ( $settings as $key => $value ) { - $sanitize_callback = $schema[ $key ]['arg_options']['sanitize_callback']; - $settings[ $key ] = call_user_func( $sanitize_callback, $value ); - } - - return $settings; - } - - /** - * Creates a single font family. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function create_item( $request ) { - $settings = $request->get_param( 'font_family_settings' ); - - // Check that the font family slug is unique. - $query = new WP_Query( - array( - 'post_type' => $this->post_type, - 'posts_per_page' => 1, - 'name' => $settings['slug'], - 'update_post_meta_cache' => false, - 'update_post_term_cache' => false, - ) - ); - if ( ! empty( $query->posts ) ) { - return new WP_Error( - 'rest_duplicate_font_family', - /* translators: %s: Font family slug. */ - sprintf( __( 'A font family with slug "%s" already exists.', 'gutenberg' ), $settings['slug'] ), - array( 'status' => 400 ) - ); - } - - return parent::create_item( $request ); - } - - /** - * Deletes a single font family. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function delete_item( $request ) { - $force = isset( $request['force'] ) ? (bool) $request['force'] : false; - - // We don't support trashing for font families. - if ( ! $force ) { - return new WP_Error( - 'rest_trash_not_supported', - /* translators: %s: force=true */ - sprintf( __( 'Font faces do not support trashing. Set "%s" to delete.', 'gutenberg' ), 'force=true' ), - array( 'status' => 501 ) - ); - } - - return parent::delete_item( $request ); - } - - /** - * Prepares a single font family output for response. - * - * @since 6.5.0 - * - * @param WP_Post $item Post object. - * @param WP_REST_Request $request Request object. - * @return WP_REST_Response Response object. - */ - public function prepare_item_for_response( $item, $request ) { - $fields = $this->get_fields_for_response( $request ); - $data = array(); - - if ( rest_is_field_included( 'id', $fields ) ) { - $data['id'] = $item->ID; - } - - if ( rest_is_field_included( 'theme_json_version', $fields ) ) { - $data['theme_json_version'] = static::LATEST_THEME_JSON_VERSION_SUPPORTED; - } - - if ( rest_is_field_included( 'font_faces', $fields ) ) { - $data['font_faces'] = $this->get_font_face_ids( $item->ID ); - } - - if ( rest_is_field_included( 'font_family_settings', $fields ) ) { - $data['font_family_settings'] = $this->get_settings_from_post( $item ); - } - - $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; - $data = $this->add_additional_fields_to_object( $data, $request ); - $data = $this->filter_response_by_context( $data, $context ); - - $response = rest_ensure_response( $data ); - - if ( rest_is_field_included( '_links', $fields ) ) { - $links = $this->prepare_links( $item ); - $response->add_links( $links ); - } - - /** - * Filters the font family data for a REST API response. - * - * @since 6.5.0 - * - * @param WP_REST_Response $response The response object. - * @param WP_Post $post Font family post object. - * @param WP_REST_Request $request Request object. - */ - return apply_filters( 'rest_prepare_wp_font_family', $response, $item, $request ); - } - - /** - * Retrieves the post's schema, conforming to JSON Schema. - * - * @since 6.5.0 - * - * @return array Item schema data. - */ - public function get_item_schema() { - if ( $this->schema ) { - return $this->add_additional_fields_schema( $this->schema ); - } - - $schema = array( - '$schema' => 'http://json-schema.org/draft-04/schema#', - 'title' => $this->post_type, - 'type' => 'object', - // Base properties for every Post. - 'properties' => array( - 'id' => array( - 'description' => __( 'Unique identifier for the post.', 'default' ), - 'type' => 'integer', - 'context' => array( 'view', 'edit', 'embed' ), - 'readonly' => true, - ), - 'theme_json_version' => array( - 'description' => __( 'Version of the theme.json schema used for the typography settings.', 'gutenberg' ), - 'type' => 'integer', - 'default' => static::LATEST_THEME_JSON_VERSION_SUPPORTED, - 'minimum' => 2, - 'maximum' => static::LATEST_THEME_JSON_VERSION_SUPPORTED, - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'font_faces' => array( - 'description' => __( 'The IDs of the child font faces in the font family.', 'gutenberg' ), - 'type' => 'array', - 'context' => array( 'view', 'edit', 'embed' ), - 'items' => array( - 'type' => 'integer', - ), - ), - // Font family settings come directly from theme.json schema - // See https://schemas.wp.org/trunk/theme.json - 'font_family_settings' => array( - 'description' => __( 'font-face definition in theme.json format.', 'gutenberg' ), - 'type' => 'object', - 'context' => array( 'view', 'edit', 'embed' ), - 'properties' => array( - 'name' => array( - 'description' => __( 'Name of the font family preset, translatable.', 'gutenberg' ), - 'type' => 'string', - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_text_field', - ), - ), - 'slug' => array( - 'description' => __( 'Kebab-case unique identifier for the font family preset.', 'gutenberg' ), - 'type' => 'string', - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_title', - ), - ), - 'fontFamily' => array( - 'description' => __( 'CSS font-family value.', 'gutenberg' ), - 'type' => 'string', - 'arg_options' => array( - 'sanitize_callback' => array( 'WP_Font_Utils', 'sanitize_font_family' ), - ), - ), - 'preview' => array( - 'description' => __( 'URL to a preview image of the font family.', 'gutenberg' ), - 'type' => 'string', - 'format' => 'uri', - 'default' => '', - 'arg_options' => array( - 'sanitize_callback' => 'sanitize_url', - ), - ), - ), - 'required' => array( 'name', 'slug', 'fontFamily' ), - 'additionalProperties' => false, - ), - ), - ); - - $this->schema = $schema; - - return $this->add_additional_fields_schema( $this->schema ); - } - - /** - * Retrieves the item's schema for display / public consumption purposes. - * - * @since 6.5.0 - * - * @return array Public item schema data. - */ - public function get_public_item_schema() { - - $schema = parent::get_public_item_schema(); - - // Also remove `arg_options' from child font_family_settings properties, since the parent - // controller only handles the top level properties. - foreach ( $schema['properties']['font_family_settings']['properties'] as &$property ) { - unset( $property['arg_options'] ); - } - - return $schema; - } - - /** - * Retrieves the query params for the font family collection. - * - * @since 6.5.0 - * - * @return array Collection parameters. - */ - public function get_collection_params() { - $query_params = parent::get_collection_params(); - - // Remove unneeded params. - unset( - $query_params['after'], - $query_params['modified_after'], - $query_params['before'], - $query_params['modified_before'], - $query_params['search'], - $query_params['search_columns'], - $query_params['status'] - ); - - $query_params['orderby']['default'] = 'id'; - $query_params['orderby']['enum'] = array( 'id', 'include' ); - - /** - * Filters collection parameters for the font family controller. - * - * @since 6.5.0 - * - * @param array $query_params JSON Schema-formatted collection parameters. - */ - return apply_filters( 'rest_wp_font_family_collection_params', $query_params ); - } - - /** - * Get the arguments used when creating or updating a font family. - * - * @since 6.5.0 - * - * @return array Font family create/edit arguments. - */ - public function get_endpoint_args_for_item_schema( $method = WP_REST_Server::CREATABLE ) { - if ( WP_REST_Server::CREATABLE === $method || WP_REST_Server::EDITABLE === $method ) { - $properties = $this->get_item_schema()['properties']; - return array( - 'theme_json_version' => $properties['theme_json_version'], - // When creating or updating, font_family_settings is stringified JSON, to work with multipart/form-data. - // Font families don't currently support file uploads, but may accept preview files in the future. - 'font_family_settings' => array( - 'description' => __( 'font-family declaration in theme.json format, encoded as a string.', 'gutenberg' ), - 'type' => 'string', - 'required' => true, - 'validate_callback' => array( $this, 'validate_font_family_settings' ), - 'sanitize_callback' => array( $this, 'sanitize_font_family_settings' ), - ), - ); - } - - return parent::get_endpoint_args_for_item_schema( $method ); - } - - /** - * Get the child font face post IDs. - * - * @since 6.5.0 - * - * @param int $font_family_id Font family post ID. - * @return int[] Array of child font face post IDs. - */ - protected function get_font_face_ids( $font_family_id ) { - $query = new WP_Query( - array( - 'fields' => 'ids', - 'post_parent' => $font_family_id, - 'post_type' => 'wp_font_face', - 'posts_per_page' => 99, - 'order' => 'ASC', - 'orderby' => 'id', - 'update_post_meta_cache' => false, - 'update_post_term_cache' => false, - ) - ); - - return $query->posts; - } - - /** - * Prepares font family links for the request. - * - * @since 6.5.0 - * - * @param WP_Post $post Post object. - * @return array Links for the given post. - */ - protected function prepare_links( $post ) { - // Entity meta. - $links = parent::prepare_links( $post ); - - return array( - 'self' => $links['self'], - 'collection' => $links['collection'], - 'font_faces' => $this->prepare_font_face_links( $post->ID ), - ); - } - - /** - * Prepares child font face links for the request. - * - * @param int $font_family_id Font family post ID. - * @return array Links for the child font face posts. - */ - protected function prepare_font_face_links( $font_family_id ) { - $font_face_ids = $this->get_font_face_ids( $font_family_id ); - $links = array(); - foreach ( $font_face_ids as $font_face_id ) { - $links[] = array( - 'embeddable' => true, - 'href' => rest_url( sprintf( '%s/%s/%s/font-faces/%s', $this->namespace, $this->rest_base, $font_family_id, $font_face_id ) ), - ); - } - return $links; - } - - /** - * Prepares a single font family post for create or update. - * - * @since 6.5.0 - * - * @param WP_REST_Request $request Request object. - * @return stdClass|WP_Error Post object or WP_Error. - */ - protected function prepare_item_for_database( $request ) { - $prepared_post = new stdClass(); - // Settings have already been decoded by ::sanitize_font_family_settings(). - $settings = $request->get_param( 'font_family_settings' ); - - // This is an update and we merge with the existing font family. - if ( isset( $request['id'] ) ) { - $existing_post = $this->get_post( $request['id'] ); - if ( is_wp_error( $existing_post ) ) { - return $existing_post; - } - - $prepared_post->ID = $existing_post->ID; - $existing_settings = $this->get_settings_from_post( $existing_post ); - $settings = array_merge( $existing_settings, $settings ); - } - - $prepared_post->post_type = $this->post_type; - $prepared_post->post_status = 'publish'; - $prepared_post->post_title = $settings['name']; - $prepared_post->post_name = sanitize_title( $settings['slug'] ); - - // Remove duplicate information from settings. - unset( $settings['name'] ); - unset( $settings['slug'] ); - - $prepared_post->post_content = wp_json_encode( $settings ); - - return $prepared_post; - } - - /** - * Gets the font family's settings from the post. - * - * @since 6.5.0 - * - * @param WP_Post $post Font family post object. - * @return array Font family settings array. - */ - protected function get_settings_from_post( $post ) { - $settings_json = json_decode( $post->post_content, true ); - - // Default to empty strings if the settings are missing. - return array( - 'name' => isset( $post->post_title ) && $post->post_title ? $post->post_title : '', - 'slug' => isset( $post->post_name ) && $post->post_name ? $post->post_name : '', - 'fontFamily' => isset( $settings_json['fontFamily'] ) && $settings_json['fontFamily'] ? $settings_json['fontFamily'] : '', - 'preview' => isset( $settings_json['preview'] ) && $settings_json['preview'] ? $settings_json['preview'] : '', - ); - } - } -} diff --git a/lib/compat/wordpress-6.5/fonts/fonts.php b/lib/compat/wordpress-6.5/fonts/fonts.php deleted file mode 100644 index 8f61dc5750f53f..00000000000000 --- a/lib/compat/wordpress-6.5/fonts/fonts.php +++ /dev/null @@ -1,485 +0,0 @@ -<?php -/** - * Font Library initialization. - * - * This file contains Font Library init calls. - * - * @package WordPress - * @subpackage Font Library - * @since 6.5.0 - */ - -/** - * Registers the routes for the objects of the controller. - * - * This function will not be merged into Core. However, the - * code in the function will be. @core-merge annotation - * provides instructions on where the could needs to go - * in Core. - * - * @since 6.5.0 - */ -function gutenberg_create_initial_post_types() { - // @core-merge: This code will go into Core's `create_initial_post_types()`. - $args = array( - 'labels' => array( - 'name' => __( 'Font Families', 'gutenberg' ), - 'singular_name' => __( 'Font Family', 'gutenberg' ), - ), - 'public' => false, - '_builtin' => true, /* internal use only. don't use this when registering your own post type. */ - 'hierarchical' => false, - 'capabilities' => array( - 'read' => 'edit_theme_options', - 'read_private_posts' => 'edit_theme_options', - 'create_posts' => 'edit_theme_options', - 'publish_posts' => 'edit_theme_options', - 'edit_posts' => 'edit_theme_options', - 'edit_others_posts' => 'edit_theme_options', - 'edit_published_posts' => 'edit_theme_options', - 'delete_posts' => 'edit_theme_options', - 'delete_others_posts' => 'edit_theme_options', - 'delete_published_posts' => 'edit_theme_options', - ), - 'map_meta_cap' => true, - 'query_var' => false, - 'show_in_rest' => true, - 'rest_base' => 'font-families', - 'rest_controller_class' => 'WP_REST_Font_Families_Controller', - // Disable autosave endpoints for font families. - 'autosave_rest_controller_class' => 'stdClass', - ); - register_post_type( 'wp_font_family', $args ); - - register_post_type( - 'wp_font_face', - array( - 'labels' => array( - 'name' => __( 'Font Faces', 'gutenberg' ), - 'singular_name' => __( 'Font Face', 'gutenberg' ), - ), - 'public' => false, - '_builtin' => true, /* internal use only. don't use this when registering your own post type. */ - 'hierarchical' => false, - 'capabilities' => array( - 'read' => 'edit_theme_options', - 'read_private_posts' => 'edit_theme_options', - 'create_posts' => 'edit_theme_options', - 'publish_posts' => 'edit_theme_options', - 'edit_posts' => 'edit_theme_options', - 'edit_others_posts' => 'edit_theme_options', - 'edit_published_posts' => 'edit_theme_options', - 'delete_posts' => 'edit_theme_options', - 'delete_others_posts' => 'edit_theme_options', - 'delete_published_posts' => 'edit_theme_options', - ), - 'map_meta_cap' => true, - 'query_var' => false, - 'show_in_rest' => true, - 'rest_base' => 'font-families/(?P<font_family_id>[\d]+)/font-faces', - 'rest_controller_class' => 'WP_REST_Font_Faces_Controller', - // Disable autosave endpoints for font faces. - 'autosave_rest_controller_class' => 'stdClass', - ) - ); -} - -/** - * Initializes REST routes. - * - * @global string $wp_version The WordPress version string. - */ -function gutenberg_create_initial_rest_routes() { - global $wp_version; - - // Runs only if the Font Library is not available in core ( i.e. in core < 6.5-alpha ). - if ( version_compare( $wp_version, '6.5-alpha', '<' ) ) { - $font_collections_controller = new WP_REST_Font_Collections_Controller(); - $font_collections_controller->register_routes(); - } -} - -add_action( 'rest_api_init', 'gutenberg_create_initial_rest_routes' ); - -/** - * Initializes REST routes and post types. - * - * @global string $wp_version The WordPress version string. - */ -function gutenberg_init_font_library() { - global $wp_version; - - // Runs only if the Font Library is not available in core ( i.e. in core < 6.5-alpha ). - if ( version_compare( $wp_version, '6.5-alpha', '<' ) ) { - gutenberg_create_initial_post_types(); - } -} - -add_action( 'init', 'gutenberg_init_font_library' ); - - -if ( ! function_exists( 'wp_register_font_collection' ) ) { - /** - * Registers a new font collection in the font library. - * - * See {@link https://schemas.wp.org/trunk/font-collection.json} for the schema - * the font collection data must adhere to. - * - * @since 6.5.0 - * - * @param string $slug Font collection slug. May only contain alphanumeric characters, dashes, - * and underscores. See sanitize_title(). - * @param array $args { - * Font collection data. - * - * @type string $name Required. Name of the font collection shown in the Font Library. - * @type string $description Optional. A short descriptive summary of the font collection. Default empty. - * @type array|string $font_families Required. Array of font family definitions that are in the collection, - * or a string containing the path or URL to a JSON file containing the font collection. - * @type array $categories Optional. Array of categories, each with a name and slug, that are used by the - * fonts in the collection. Default empty. - * } - * @return WP_Font_Collection|WP_Error A font collection if it was registered - * successfully, or WP_Error object on failure. - */ - function wp_register_font_collection( string $slug, array $args ) { - return WP_Font_Library::get_instance()->register_font_collection( $slug, $args ); - } -} - -if ( ! function_exists( 'wp_unregister_font_collection' ) ) { - /** - * Unregisters a font collection from the Font Library. - * - * @since 6.5.0 - * - * @param string $slug Font collection slug. - * @return bool True if the font collection was unregistered successfully, else false. - */ - function wp_unregister_font_collection( string $slug ) { - return WP_Font_Library::get_instance()->unregister_font_collection( $slug ); - } -} - -function gutenberg_register_font_collections() { - if ( null !== WP_Font_Library::get_instance()->get_font_collection( 'google-fonts' ) ) { - return; - } - wp_register_font_collection( - 'google-fonts', - array( - 'name' => _x( 'Google Fonts', 'font collection name', 'gutenberg' ), - 'description' => __( 'Install from Google Fonts. Fonts are copied to and served from your site.', 'gutenberg' ), - 'font_families' => 'https://s.w.org/images/fonts/wp-6.5/collections/google-fonts-with-preview.json', - 'categories' => array( - array( - 'name' => _x( 'Sans Serif', 'font category', 'gutenberg' ), - 'slug' => 'sans-serif', - ), - array( - 'name' => _x( 'Display', 'font category', 'gutenberg' ), - 'slug' => 'display', - ), - array( - 'name' => _x( 'Serif', 'font category', 'gutenberg' ), - 'slug' => 'serif', - ), - array( - 'name' => _x( 'Handwriting', 'font category', 'gutenberg' ), - 'slug' => 'handwriting', - ), - array( - 'name' => _x( 'Monospace', 'font category', 'gutenberg' ), - 'slug' => 'monospace', - ), - ), - ) - ); -} -add_action( 'init', 'gutenberg_register_font_collections', 11 ); - -// @core-merge: This code should probably go into Core's src/wp-includes/fonts.php. -if ( ! function_exists( 'wp_get_font_dir' ) ) { - /** - * Retrieves font uploads directory information. - * - * Same as wp_font_dir() but "light weight" as it doesn't attempt to create the font uploads directory. - * Intended for use in themes, when only 'basedir' and 'baseurl' are needed, generally in all cases - * when not uploading files. - * - * @since 6.5.0 - * - * @see wp_font_dir() - * - * @return array See wp_font_dir() for description. - */ - function wp_get_font_dir() { - return wp_font_dir( false ); - } -} - -// @core-merge: This code should probably go into Core's src/wp-includes/fonts.php. -if ( ! function_exists( 'wp_font_dir' ) ) { - /** - * Returns an array containing the current fonts upload directory's path and URL. - * - * @since 6.5.0 - * - * @param bool $create_dir Optional. Whether to check and create the font uploads directory. Default true. - * @return array { - * Array of information about the font upload directory. - * - * @type string $path Base directory and subdirectory or full path to the fonts upload directory. - * @type string $url Base URL and subdirectory or absolute URL to the fonts upload directory. - * @type string $subdir Subdirectory - * @type string $basedir Path without subdir. - * @type string $baseurl URL path without subdir. - * @type string|false $error False or error message. - * } - */ - function wp_font_dir( $create_dir = true ) { - /* - * Allow extenders to manipulate the font directory consistently. - * - * Ensures the upload_dir filter is fired both when calling this function - * directly and when the upload directory is filtered in the Font Face - * REST API endpoint. - */ - add_filter( 'upload_dir', '_wp_filter_font_directory' ); - $font_dir = wp_upload_dir( null, $create_dir, false ); - remove_filter( 'upload_dir', '_wp_filter_font_directory' ); - return $font_dir; - } -} - -// @core-merge: This code should probably go into Core's src/wp-includes/fonts.php. -if ( ! function_exists( '_wp_filter_font_directory' ) ) { - /** - * Returns the font directory for use by the font library. - * - * This function is a callback for the {@see 'upload_dir'} filter. It is not - * intended to be called directly. Use wp_get_font_dir() instead. - * - * The function can be used when extending the font library to modify the upload - * destination for font files via the upload_dir filter. The recommended way to - * do this is: - * - * ```php - * add_filter( 'upload_dir', '_wp_filter_font_directory' ); - * // Your code to upload or sideload a font file. - * remove_filter( 'upload_dir', '_wp_filter_font_directory' ); - * ``` - * - * @since 6.5.0 - * @access private - * - * @param string $font_dir The font directory. - * @return string The modified font directory. - */ - function _wp_filter_font_directory( $font_dir ) { - if ( doing_filter( 'font_dir' ) ) { - // Avoid an infinite loop. - return $font_dir; - } - - $font_dir = array( - 'path' => untrailingslashit( $font_dir['basedir'] ) . '/fonts', - 'url' => untrailingslashit( $font_dir['baseurl'] ) . '/fonts', - 'subdir' => '', - 'basedir' => untrailingslashit( $font_dir['basedir'] ) . '/fonts', - 'baseurl' => untrailingslashit( $font_dir['baseurl'] ) . '/fonts', - 'error' => false, - ); - - /** - * Filters the fonts directory data. - * - * This filter allows developers to modify the fonts directory data. - * - * @since 6.5.0 - * - * @param array $font_dir { - * Array of information about the font upload directory. - * - * @type string $path Base directory and subdirectory or full path to the fonts upload directory. - * @type string $url Base URL and subdirectory or absolute URL to the fonts upload directory. - * @type string $subdir Subdirectory - * @type string $basedir Path without subdir. - * @type string $baseurl URL path without subdir. - * @type string|false $error False or error message. - * } - */ - return apply_filters( 'font_dir', $font_dir ); - } -} - -// @core-merge: Filters should go in `src/wp-includes/default-filters.php`, -// functions in a general file for font library. -if ( ! function_exists( '_wp_after_delete_font_family' ) ) { - /** - * Deletes child font faces when a font family is deleted. - * - * @access private - * @since 6.5.0 - * - * @param int $post_id Post ID. - * @param WP_Post $post Post object. - */ - function _wp_after_delete_font_family( $post_id, $post ) { - if ( 'wp_font_family' !== $post->post_type ) { - return; - } - - $font_faces = get_children( - array( - 'post_parent' => $post_id, - 'post_type' => 'wp_font_face', - ) - ); - - foreach ( $font_faces as $font_face ) { - wp_delete_post( $font_face->ID, true ); - } - } - add_action( 'deleted_post', '_wp_after_delete_font_family', 10, 2 ); -} - -if ( ! function_exists( '_wp_before_delete_font_face' ) ) { - /** - * Deletes associated font files when a font face is deleted. - * - * @access private - * @since 6.5.0 - * - * @param int $post_id Post ID. - * @param WP_Post $post Post object. - */ - function _wp_before_delete_font_face( $post_id, $post ) { - if ( 'wp_font_face' !== $post->post_type ) { - return; - } - - $font_files = get_post_meta( $post_id, '_wp_font_face_file', false ); - $font_dir = untrailingslashit( wp_get_font_dir()['basedir'] ); - - foreach ( $font_files as $font_file ) { - wp_delete_file( $font_dir . '/' . $font_file ); - } - } - add_action( 'before_delete_post', '_wp_before_delete_font_face', 10, 2 ); -} - -// @core-merge: Do not merge this function, it is for deleting fonts from the wp-content/fonts directory only used in Gutenberg. -/** - * Deletes associated font files from wp-content/fonts, when a font face is deleted. - * - * @param int $post_id Post ID. - * @param WP_Post $post Post object. - */ -function gutenberg_before_delete_font_face( $post_id, $post ) { - if ( 'wp_font_face' !== $post->post_type ) { - return; - } - - $font_files = get_post_meta( $post_id, '_wp_font_face_file', false ); - - if ( empty( $font_files ) ) { - return; - } - - $site_path = ''; - if ( is_multisite() && ! ( is_main_network() && is_main_site() ) ) { - $site_path = '/sites/' . get_current_blog_id(); - } - - $font_dir = path_join( WP_CONTENT_DIR, 'fonts' ) . $site_path; - - foreach ( $font_files as $font_file ) { - $font_path = $font_dir . '/' . $font_file; - - if ( file_exists( $font_path ) ) { - wp_delete_file( $font_path ); - } - } -} -add_action( 'before_delete_post', 'gutenberg_before_delete_font_face', 10, 2 ); - -// @core-merge: Do not merge this back compat function, it is for supporting a legacy font family format only in Gutenberg. -/** - * Convert legacy font family posts to the new format. - * - * @return void - */ -function gutenberg_convert_legacy_font_family_format() { - if ( get_option( 'gutenberg_font_family_format_converted' ) ) { - return; - } - - $font_families = new WP_Query( - array( - 'post_type' => 'wp_font_family', - // Set a maximum, but in reality there will be far less than this. - 'posts_per_page' => 999, - 'update_post_term_cache' => false, - ) - ); - - foreach ( $font_families->get_posts() as $font_family ) { - $already_converted = get_post_meta( $font_family->ID, '_gutenberg_legacy_font_family', true ); - if ( $already_converted ) { - continue; - } - - // Stash the old font family content in a meta field just in case we need it. - update_post_meta( $font_family->ID, '_gutenberg_legacy_font_family', $font_family->post_content ); - - $font_family_json = json_decode( $font_family->post_content, true ); - if ( ! $font_family_json ) { - continue; - } - - $font_faces = isset( $font_family_json['fontFace'] ) ? $font_family_json['fontFace'] : array(); - unset( $font_family_json['fontFace'] ); - - // Save wp_font_face posts within the family. - foreach ( $font_faces as $font_face ) { - $args = array(); - $args['post_type'] = 'wp_font_face'; - $args['post_title'] = WP_Font_Utils::get_font_face_slug( $font_face ); - $args['post_name'] = sanitize_title( $args['post_title'] ); - $args['post_status'] = 'publish'; - $args['post_parent'] = $font_family->ID; - $args['post_content'] = wp_json_encode( $font_face ); - - $font_face_id = wp_insert_post( wp_slash( $args ) ); - - $file_urls = (array) ( isset( $font_face['src'] ) ? $font_face['src'] : array() ); - - foreach ( $file_urls as $file_url ) { - // continue if the file is not local. - if ( false === strpos( $file_url, site_url() ) ) { - continue; - } - - $relative_path = basename( $file_url ); - update_post_meta( $font_face_id, '_wp_font_face_file', $relative_path ); - } - } - - // Update the font family post to remove the font face data. - $args = array(); - $args['ID'] = $font_family->ID; - $args['post_title'] = isset( $font_family_json['name'] ) ? $font_family_json['name'] : ''; - $args['post_name'] = sanitize_title( $font_family_json['slug'] ); - - unset( $font_family_json['name'] ); - unset( $font_family_json['slug'] ); - - $args['post_content'] = wp_json_encode( $font_family_json ); - - wp_update_post( wp_slash( $args ) ); - } - - update_option( 'gutenberg_font_family_format_converted', true ); -} -add_action( 'init', 'gutenberg_convert_legacy_font_family_format' ); diff --git a/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-attribute-token-6-5.php b/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-attribute-token-6-5.php deleted file mode 100644 index 70359ea339d669..00000000000000 --- a/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-attribute-token-6-5.php +++ /dev/null @@ -1,116 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Attribute_Token class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.2.0 - */ - -/** - * Core class used by the HTML tag processor as a data structure for the attribute token, - * allowing to drastically improve performance. - * - * This class is for internal usage of the WP_HTML_Tag_Processor class. - * - * @access private - * @since 6.2.0 - * @since 6.5.0 Replaced `end` with `length` to more closely match `substr()`. - * - * @see WP_HTML_Tag_Processor - */ -class Gutenberg_HTML_Attribute_Token_6_5 { - /** - * Attribute name. - * - * @since 6.2.0 - * - * @var string - */ - public $name; - - /** - * Attribute value. - * - * @since 6.2.0 - * - * @var int - */ - public $value_starts_at; - - /** - * How many bytes the value occupies in the input HTML. - * - * @since 6.2.0 - * - * @var int - */ - public $value_length; - - /** - * The string offset where the attribute name starts. - * - * @since 6.2.0 - * - * @var int - */ - public $start; - - /** - * Byte length of text spanning the attribute inside a tag. - * - * This span starts at the first character of the attribute name - * and it ends after one of three cases: - * - * - at the end of the attribute name for boolean attributes. - * - at the end of the value for unquoted attributes. - * - at the final single or double quote for quoted attributes. - * - * Example: - * - * <div class="post"> - * ------------ length is 12, including quotes - * - * <input type="checked" checked id="selector"> - * ------- length is 6 - * - * <a rel=noopener> - * ------------ length is 11 - * - * @since 6.5.0 Replaced `end` with `length` to more closely match `substr()`. - * - * @var int - */ - public $length; - - /** - * Whether the attribute is a boolean attribute with value `true`. - * - * @since 6.2.0 - * - * @var bool - */ - public $is_true; - - /** - * Constructor. - * - * @since 6.2.0 - * @since 6.5.0 Replaced `end` with `length` to more closely match `substr()`. - * - * @param string $name Attribute name. - * @param int $value_start Attribute value. - * @param int $value_length Number of bytes attribute value spans. - * @param int $start The string offset where the attribute name starts. - * @param int $length Byte length of the entire attribute name or name and value pair expression. - * @param bool $is_true Whether the attribute is a boolean attribute with true value. - */ - public function __construct( $name, $value_start, $value_length, $start, $length, $is_true ) { - $this->name = $name; - $this->value_starts_at = $value_start; - $this->value_length = $value_length; - $this->start = $start; - $this->length = $length; - $this->is_true = $is_true; - } -} diff --git a/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-open-elements-6-5.php b/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-open-elements-6-5.php deleted file mode 100644 index 0d8901225c792e..00000000000000 --- a/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-open-elements-6-5.php +++ /dev/null @@ -1,462 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Open_Elements class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.4.0 - */ - -/** - * Core class used by the HTML processor during HTML parsing - * for managing the stack of open elements. - * - * This class is designed for internal use by the HTML processor. - * - * > Initially, the stack of open elements is empty. The stack grows - * > downwards; the topmost node on the stack is the first one added - * > to the stack, and the bottommost node of the stack is the most - * > recently added node in the stack (notwithstanding when the stack - * > is manipulated in a random access fashion as part of the handling - * > for misnested tags). - * - * @since 6.4.0 - * - * @access private - * - * @see https://html.spec.whatwg.org/#stack-of-open-elements - * @see WP_HTML_Processor - */ -class Gutenberg_HTML_Open_Elements_6_5 { - /** - * Holds the stack of open element references. - * - * @since 6.4.0 - * - * @var WP_HTML_Token[] - */ - public $stack = array(); - - /** - * Whether a P element is in button scope currently. - * - * This class optimizes scope lookup by pre-calculating - * this value when elements are added and removed to the - * stack of open elements which might change its value. - * This avoids frequent iteration over the stack. - * - * @since 6.4.0 - * - * @var bool - */ - private $has_p_in_button_scope = false; - - /** - * Reports if a specific node is in the stack of open elements. - * - * @since 6.4.0 - * - * @param WP_HTML_Token $token Look for this node in the stack. - * @return bool Whether the referenced node is in the stack of open elements. - */ - public function contains_node( $token ) { - foreach ( $this->walk_up() as $item ) { - if ( $token->bookmark_name === $item->bookmark_name ) { - return true; - } - } - - return false; - } - - /** - * Returns how many nodes are currently in the stack of open elements. - * - * @since 6.4.0 - * - * @return int How many node are in the stack of open elements. - */ - public function count() { - return count( $this->stack ); - } - - /** - * Returns the node at the end of the stack of open elements, - * if one exists. If the stack is empty, returns null. - * - * @since 6.4.0 - * - * @return WP_HTML_Token|null Last node in the stack of open elements, if one exists, otherwise null. - */ - public function current_node() { - $current_node = end( $this->stack ); - - return $current_node ? $current_node : null; - } - - /** - * Returns whether an element is in a specific scope. - * - * ## HTML Support - * - * This function skips checking for the termination list because there - * are no supported elements which appear in the termination list. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-the-specific-scope - * - * @param string $tag_name Name of tag check. - * @param string[] $termination_list List of elements that terminate the search. - * @return bool Whether the element was found in a specific scope. - */ - public function has_element_in_specific_scope( $tag_name, $termination_list ) { - foreach ( $this->walk_up() as $node ) { - if ( $node->node_name === $tag_name ) { - return true; - } - - if ( - '(internal: H1 through H6 - do not use)' === $tag_name && - in_array( $node->node_name, array( 'H1', 'H2', 'H3', 'H4', 'H5', 'H6' ), true ) - ) { - return true; - } - - switch ( $node->node_name ) { - case 'HTML': - return false; - } - - if ( in_array( $node->node_name, $termination_list, true ) ) { - return false; - } - } - - return false; - } - - /** - * Returns whether a particular element is in scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-scope - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_scope( $tag_name ) { - return $this->has_element_in_specific_scope( - $tag_name, - array( - - /* - * Because it's not currently possible to encounter - * one of the termination elements, they don't need - * to be listed here. If they were, they would be - * unreachable and only waste CPU cycles while - * scanning through HTML. - */ - ) - ); - } - - /** - * Returns whether a particular element is in list item scope. - * - * @since 6.4.0 - * @since 6.5.0 Implemented: no longer throws on every invocation. - * - * @see https://html.spec.whatwg.org/#has-an-element-in-list-item-scope - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_list_item_scope( $tag_name ) { - return $this->has_element_in_specific_scope( - $tag_name, - array( - // There are more elements that belong here which aren't currently supported. - 'OL', - 'UL', - ) - ); - } - - /** - * Returns whether a particular element is in button scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-button-scope - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_button_scope( $tag_name ) { - return $this->has_element_in_specific_scope( $tag_name, array( 'BUTTON' ) ); - } - - /** - * Returns whether a particular element is in table scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-table-scope - * - * @throws WP_HTML_Unsupported_Exception Always until this function is implemented. - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_table_scope( $tag_name ) { - throw new WP_HTML_Unsupported_Exception( 'Cannot process elements depending on table scope.' ); - - return false; // The linter requires this unreachable code until the function is implemented and can return. - } - - /** - * Returns whether a particular element is in select scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-select-scope - * - * @throws WP_HTML_Unsupported_Exception Always until this function is implemented. - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_select_scope( $tag_name ) { - throw new WP_HTML_Unsupported_Exception( 'Cannot process elements depending on select scope.' ); - - return false; // The linter requires this unreachable code until the function is implemented and can return. - } - - /** - * Returns whether a P is in BUTTON scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-button-scope - * - * @return bool Whether a P is in BUTTON scope. - */ - public function has_p_in_button_scope() { - return $this->has_p_in_button_scope; - } - - /** - * Pops a node off of the stack of open elements. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#stack-of-open-elements - * - * @return bool Whether a node was popped off of the stack. - */ - public function pop() { - $item = array_pop( $this->stack ); - - if ( null === $item ) { - return false; - } - - $this->after_element_pop( $item ); - return true; - } - - /** - * Pops nodes off of the stack of open elements until one with the given tag name has been popped. - * - * @since 6.4.0 - * - * @see WP_HTML_Open_Elements::pop - * - * @param string $tag_name Name of tag that needs to be popped off of the stack of open elements. - * @return bool Whether a tag of the given name was found and popped off of the stack of open elements. - */ - public function pop_until( $tag_name ) { - foreach ( $this->walk_up() as $item ) { - $this->pop(); - - if ( - '(internal: H1 through H6 - do not use)' === $tag_name && - in_array( $item->node_name, array( 'H1', 'H2', 'H3', 'H4', 'H5', 'H6' ), true ) - ) { - return true; - } - - if ( $tag_name === $item->node_name ) { - return true; - } - } - - return false; - } - - /** - * Pushes a node onto the stack of open elements. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#stack-of-open-elements - * - * @param WP_HTML_Token $stack_item Item to add onto stack. - */ - public function push( $stack_item ) { - $this->stack[] = $stack_item; - $this->after_element_push( $stack_item ); - } - - /** - * Removes a specific node from the stack of open elements. - * - * @since 6.4.0 - * - * @param WP_HTML_Token $token The node to remove from the stack of open elements. - * @return bool Whether the node was found and removed from the stack of open elements. - */ - public function remove_node( $token ) { - foreach ( $this->walk_up() as $position_from_end => $item ) { - if ( $token->bookmark_name !== $item->bookmark_name ) { - continue; - } - - $position_from_start = $this->count() - $position_from_end - 1; - array_splice( $this->stack, $position_from_start, 1 ); - $this->after_element_pop( $item ); - return true; - } - - return false; - } - - - /** - * Steps through the stack of open elements, starting with the top element - * (added first) and walking downwards to the one added last. - * - * This generator function is designed to be used inside a "foreach" loop. - * - * Example: - * - * $html = '<em><strong><a>We are here'; - * foreach ( $stack->walk_down() as $node ) { - * echo "{$node->node_name} -> "; - * } - * > EM -> STRONG -> A -> - * - * To start with the most-recently added element and walk towards the top, - * see WP_HTML_Open_Elements::walk_up(). - * - * @since 6.4.0 - */ - public function walk_down() { - $count = count( $this->stack ); - - for ( $i = 0; $i < $count; $i++ ) { - yield $this->stack[ $i ]; - } - } - - /** - * Steps through the stack of open elements, starting with the bottom element - * (added last) and walking upwards to the one added first. - * - * This generator function is designed to be used inside a "foreach" loop. - * - * Example: - * - * $html = '<em><strong><a>We are here'; - * foreach ( $stack->walk_up() as $node ) { - * echo "{$node->node_name} -> "; - * } - * > A -> STRONG -> EM -> - * - * To start with the first added element and walk towards the bottom, - * see WP_HTML_Open_Elements::walk_down(). - * - * @since 6.4.0 - * @since 6.5.0 Accepts $above_this_node to start traversal above a given node, if it exists. - * - * @param ?WP_HTML_Token $above_this_node Start traversing above this node, if provided and if the node exists. - */ - public function walk_up( $above_this_node = null ) { - $has_found_node = null === $above_this_node; - - for ( $i = count( $this->stack ) - 1; $i >= 0; $i-- ) { - $node = $this->stack[ $i ]; - - if ( ! $has_found_node ) { - $has_found_node = $node === $above_this_node; - continue; - } - - yield $node; - } - } - - /* - * Internal helpers. - */ - - /** - * Updates internal flags after adding an element. - * - * Certain conditions (such as "has_p_in_button_scope") are maintained here as - * flags that are only modified when adding and removing elements. This allows - * the HTML Processor to quickly check for these conditions instead of iterating - * over the open stack elements upon each new tag it encounters. These flags, - * however, need to be maintained as items are added and removed from the stack. - * - * @since 6.4.0 - * - * @param WP_HTML_Token $item Element that was added to the stack of open elements. - */ - public function after_element_push( $item ) { - /* - * When adding support for new elements, expand this switch to trap - * cases where the precalculated value needs to change. - */ - switch ( $item->node_name ) { - case 'BUTTON': - $this->has_p_in_button_scope = false; - break; - - case 'P': - $this->has_p_in_button_scope = true; - break; - } - } - - /** - * Updates internal flags after removing an element. - * - * Certain conditions (such as "has_p_in_button_scope") are maintained here as - * flags that are only modified when adding and removing elements. This allows - * the HTML Processor to quickly check for these conditions instead of iterating - * over the open stack elements upon each new tag it encounters. These flags, - * however, need to be maintained as items are added and removed from the stack. - * - * @since 6.4.0 - * - * @param WP_HTML_Token $item Element that was removed from the stack of open elements. - */ - public function after_element_pop( $item ) { - /* - * When adding support for new elements, expand this switch to trap - * cases where the precalculated value needs to change. - */ - switch ( $item->node_name ) { - case 'BUTTON': - $this->has_p_in_button_scope = $this->has_element_in_button_scope( 'P' ); - break; - - case 'P': - $this->has_p_in_button_scope = $this->has_element_in_button_scope( 'P' ); - break; - } - } -} diff --git a/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-processor-6-5.php b/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-processor-6-5.php deleted file mode 100644 index 02879b72ea9cbb..00000000000000 --- a/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-processor-6-5.php +++ /dev/null @@ -1,1929 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Processor class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.4.0 - */ - -/** - * Core class used to safely parse and modify an HTML document. - * - * The HTML Processor class properly parses and modifies HTML5 documents. - * - * It supports a subset of the HTML5 specification, and when it encounters - * unsupported markup, it aborts early to avoid unintentionally breaking - * the document. The HTML Processor should never break an HTML document. - * - * While the `WP_HTML_Tag_Processor` is a valuable tool for modifying - * attributes on individual HTML tags, the HTML Processor is more capable - * and useful for the following operations: - * - * - Querying based on nested HTML structure. - * - * Eventually the HTML Processor will also support: - * - Wrapping a tag in surrounding HTML. - * - Unwrapping a tag by removing its parent. - * - Inserting and removing nodes. - * - Reading and changing inner content. - * - Navigating up or around HTML structure. - * - * ## Usage - * - * Use of this class requires three steps: - * - * 1. Call a static creator method with your input HTML document. - * 2. Find the location in the document you are looking for. - * 3. Request changes to the document at that location. - * - * Example: - * - * $processor = WP_HTML_Processor::create_fragment( $html ); - * if ( $processor->next_tag( array( 'breadcrumbs' => array( 'DIV', 'FIGURE', 'IMG' ) ) ) ) { - * $processor->add_class( 'responsive-image' ); - * } - * - * #### Breadcrumbs - * - * Breadcrumbs represent the stack of open elements from the root - * of the document or fragment down to the currently-matched node, - * if one is currently selected. Call WP_HTML_Processor::get_breadcrumbs() - * to inspect the breadcrumbs for a matched tag. - * - * Breadcrumbs can specify nested HTML structure and are equivalent - * to a CSS selector comprising tag names separated by the child - * combinator, such as "DIV > FIGURE > IMG". - * - * Since all elements find themselves inside a full HTML document - * when parsed, the return value from `get_breadcrumbs()` will always - * contain any implicit outermost elements. For example, when parsing - * with `create_fragment()` in the `BODY` context (the default), any - * tag in the given HTML document will contain `array( 'HTML', 'BODY', … )` - * in its breadcrumbs. - * - * Despite containing the implied outermost elements in their breadcrumbs, - * tags may be found with the shortest-matching breadcrumb query. That is, - * `array( 'IMG' )` matches all IMG elements and `array( 'P', 'IMG' )` - * matches all IMG elements directly inside a P element. To ensure that no - * partial matches erroneously match it's possible to specify in a query - * the full breadcrumb match all the way down from the root HTML element. - * - * Example: - * - * $html = '<figure><img><figcaption>A <em>lovely</em> day outside</figcaption></figure>'; - * // ----- Matches here. - * $processor->next_tag( array( 'breadcrumbs' => array( 'FIGURE', 'IMG' ) ) ); - * - * $html = '<figure><img><figcaption>A <em>lovely</em> day outside</figcaption></figure>'; - * // ---- Matches here. - * $processor->next_tag( array( 'breadcrumbs' => array( 'FIGURE', 'FIGCAPTION', 'EM' ) ) ); - * - * $html = '<div><img></div><img>'; - * // ----- Matches here, because IMG must be a direct child of the implicit BODY. - * $processor->next_tag( array( 'breadcrumbs' => array( 'BODY', 'IMG' ) ) ); - * - * ## HTML Support - * - * This class implements a small part of the HTML5 specification. - * It's designed to operate within its support and abort early whenever - * encountering circumstances it can't properly handle. This is - * the principle way in which this class remains as simple as possible - * without cutting corners and breaking compliance. - * - * ### Supported elements - * - * If any unsupported element appears in the HTML input the HTML Processor - * will abort early and stop all processing. This draconian measure ensures - * that the HTML Processor won't break any HTML it doesn't fully understand. - * - * The following list specifies the HTML tags that _are_ supported: - * - * - Containers: ADDRESS, BLOCKQUOTE, DETAILS, DIALOG, DIV, FOOTER, HEADER, MAIN, MENU, SPAN, SUMMARY. - * - Custom elements: All custom elements are supported. :) - * - Form elements: BUTTON, DATALIST, FIELDSET, INPUT, LABEL, LEGEND, METER, PROGRESS, SEARCH. - * - Formatting elements: B, BIG, CODE, EM, FONT, I, PRE, SMALL, STRIKE, STRONG, TT, U, WBR. - * - Heading elements: H1, H2, H3, H4, H5, H6, HGROUP. - * - Links: A. - * - Lists: DD, DL, DT, LI, OL, UL. - * - Media elements: AUDIO, CANVAS, EMBED, FIGCAPTION, FIGURE, IMG, MAP, PICTURE, SOURCE, TRACK, VIDEO. - * - Paragraph: BR, P. - * - Phrasing elements: ABBR, AREA, BDI, BDO, CITE, DATA, DEL, DFN, INS, MARK, OUTPUT, Q, SAMP, SUB, SUP, TIME, VAR. - * - Sectioning elements: ARTICLE, ASIDE, HR, NAV, SECTION. - * - Templating elements: SLOT. - * - Text decoration: RUBY. - * - Deprecated elements: ACRONYM, BLINK, CENTER, DIR, ISINDEX, KEYGEN, LISTING, MULTICOL, NEXTID, PARAM, SPACER. - * - * ### Supported markup - * - * Some kinds of non-normative HTML involve reconstruction of formatting elements and - * re-parenting of mis-nested elements. For example, a DIV tag found inside a TABLE - * may in fact belong _before_ the table in the DOM. If the HTML Processor encounters - * such a case it will stop processing. - * - * The following list specifies HTML markup that _is_ supported: - * - * - Markup involving only those tags listed above. - * - Fully-balanced and non-overlapping tags. - * - HTML with unexpected tag closers. - * - Some unbalanced or overlapping tags. - * - P tags after unclosed P tags. - * - BUTTON tags after unclosed BUTTON tags. - * - A tags after unclosed A tags that don't involve any active formatting elements. - * - * @since 6.4.0 - * - * @see WP_HTML_Tag_Processor - * @see https://html.spec.whatwg.org/ - */ -class Gutenberg_HTML_Processor_6_5 extends Gutenberg_HTML_Tag_Processor_6_5 { - /** - * The maximum number of bookmarks allowed to exist at any given time. - * - * HTML processing requires more bookmarks than basic tag processing, - * so this class constant from the Tag Processor is overwritten. - * - * @since 6.4.0 - * - * @var int - */ - const MAX_BOOKMARKS = 100; - - /** - * Holds the working state of the parser, including the stack of - * open elements and the stack of active formatting elements. - * - * Initialized in the constructor. - * - * @since 6.4.0 - * - * @var WP_HTML_Processor_State - */ - private $state = null; - - /** - * Used to create unique bookmark names. - * - * This class sets a bookmark for every tag in the HTML document that it encounters. - * The bookmark name is auto-generated and increments, starting with `1`. These are - * internal bookmarks and are automatically released when the referring WP_HTML_Token - * goes out of scope and is garbage-collected. - * - * @since 6.4.0 - * - * @see WP_HTML_Processor::$release_internal_bookmark_on_destruct - * - * @var int - */ - private $bookmark_counter = 0; - - /** - * Stores an explanation for why something failed, if it did. - * - * @see self::get_last_error - * - * @since 6.4.0 - * - * @var string|null - */ - private $last_error = null; - - /** - * Releases a bookmark when PHP garbage-collects its wrapping WP_HTML_Token instance. - * - * This function is created inside the class constructor so that it can be passed to - * the stack of open elements and the stack of active formatting elements without - * exposing it as a public method on the class. - * - * @since 6.4.0 - * - * @var closure - */ - private $release_internal_bookmark_on_destruct = null; - - /* - * Public Interface Functions - */ - - /** - * Creates an HTML processor in the fragment parsing mode. - * - * Use this for cases where you are processing chunks of HTML that - * will be found within a bigger HTML document, such as rendered - * block output that exists within a post, `the_content` inside a - * rendered site layout. - * - * Fragment parsing occurs within a context, which is an HTML element - * that the document will eventually be placed in. It becomes important - * when special elements have different rules than others, such as inside - * a TEXTAREA or a TITLE tag where things that look like tags are text, - * or inside a SCRIPT tag where things that look like HTML syntax are JS. - * - * The context value should be a representation of the tag into which the - * HTML is found. For most cases this will be the body element. The HTML - * form is provided because a context element may have attributes that - * impact the parse, such as with a SCRIPT tag and its `type` attribute. - * - * ## Current HTML Support - * - * - The only supported context is `<body>`, which is the default value. - * - The only supported document encoding is `UTF-8`, which is the default value. - * - * @since 6.4.0 - * - * @param string $html Input HTML fragment to process. - * @param string $context Context element for the fragment, must be default of `<body>`. - * @param string $encoding Text encoding of the document; must be default of 'UTF-8'. - * @return WP_HTML_Processor|null The created processor if successful, otherwise null. - */ - public static function create_fragment( $html, $context = '<body>', $encoding = 'UTF-8' ) { - if ( '<body>' !== $context || 'UTF-8' !== $encoding ) { - return null; - } - - $p = new self( $html, self::CONSTRUCTOR_UNLOCK_CODE ); - $p->state->context_node = array( 'BODY', array() ); - $p->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_BODY; - - // @todo Create "fake" bookmarks for non-existent but implied nodes. - $p->bookmarks['root-node'] = new WP_HTML_Span( 0, 0 ); - $p->bookmarks['context-node'] = new WP_HTML_Span( 0, 0 ); - - $p->state->stack_of_open_elements->push( - new WP_HTML_Token( - 'root-node', - 'HTML', - false - ) - ); - - $p->state->stack_of_open_elements->push( - new WP_HTML_Token( - 'context-node', - $p->state->context_node[0], - false - ) - ); - - return $p; - } - - /** - * Constructor. - * - * Do not use this method. Use the static creator methods instead. - * - * @access private - * - * @since 6.4.0 - * - * @see WP_HTML_Processor::create_fragment() - * - * @param string $html HTML to process. - * @param string|null $use_the_static_create_methods_instead This constructor should not be called manually. - */ - public function __construct( $html, $use_the_static_create_methods_instead = null ) { - parent::__construct( $html ); - - if ( self::CONSTRUCTOR_UNLOCK_CODE !== $use_the_static_create_methods_instead ) { - _doing_it_wrong( - __METHOD__, - sprintf( - /* translators: %s: WP_HTML_Processor::create_fragment(). */ - __( 'Call %s to create an HTML Processor instead of calling the constructor directly.' ), - '<code>WP_HTML_Processor::create_fragment()</code>' - ), - '6.4.0' - ); - } - - $this->state = new Gutenberg_HTML_Processor_State_6_5(); - - /* - * Create this wrapper so that it's possible to pass - * a private method into WP_HTML_Token classes without - * exposing it to any public API. - */ - $this->release_internal_bookmark_on_destruct = function ( $name ) { - parent::release_bookmark( $name ); - }; - } - - /** - * Returns the last error, if any. - * - * Various situations lead to parsing failure but this class will - * return `false` in all those cases. To determine why something - * failed it's possible to request the last error. This can be - * helpful to know to distinguish whether a given tag couldn't - * be found or if content in the document caused the processor - * to give up and abort processing. - * - * Example - * - * $processor = WP_HTML_Processor::create_fragment( '<template><strong><button><em><p><em>' ); - * false === $processor->next_tag(); - * WP_HTML_Processor::ERROR_UNSUPPORTED === $processor->get_last_error(); - * - * @since 6.4.0 - * - * @see self::ERROR_UNSUPPORTED - * @see self::ERROR_EXCEEDED_MAX_BOOKMARKS - * - * @return string|null The last error, if one exists, otherwise null. - */ - public function get_last_error() { - return $this->last_error; - } - - /** - * Finds the next tag matching the $query. - * - * @todo Support matching the class name and tag name. - * - * @since 6.4.0 - * - * @throws Exception When unable to allocate a bookmark for the next token in the input HTML document. - * - * @param array|string|null $query { - * Optional. Which tag name to find, having which class, etc. Default is to find any tag. - * - * @type string|null $tag_name Which tag to find, or `null` for "any tag." - * @type int|null $match_offset Find the Nth tag matching all search criteria. - * 1 for "first" tag, 3 for "third," etc. - * Defaults to first tag. - * @type string|null $class_name Tag must contain this whole class name to match. - * @type string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. - * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. - * } - * @return bool Whether a tag was matched. - */ - public function next_tag( $query = null ) { - if ( null === $query ) { - while ( $this->step() ) { - if ( '#tag' !== $this->get_token_type() ) { - continue; - } - - if ( ! $this->is_tag_closer() ) { - return true; - } - } - - return false; - } - - if ( is_string( $query ) ) { - $query = array( 'breadcrumbs' => array( $query ) ); - } - - if ( ! is_array( $query ) ) { - _doing_it_wrong( - __METHOD__, - __( 'Please pass a query array to this function.' ), - '6.4.0' - ); - return false; - } - - if ( ! ( array_key_exists( 'breadcrumbs', $query ) && is_array( $query['breadcrumbs'] ) ) ) { - while ( $this->step() ) { - if ( '#tag' !== $this->get_token_type() ) { - continue; - } - - if ( ! $this->is_tag_closer() ) { - return true; - } - } - - return false; - } - - if ( isset( $query['tag_closers'] ) && 'visit' === $query['tag_closers'] ) { - _doing_it_wrong( - __METHOD__, - __( 'Cannot visit tag closers in HTML Processor.' ), - '6.4.0' - ); - return false; - } - - $breadcrumbs = $query['breadcrumbs']; - $match_offset = isset( $query['match_offset'] ) ? (int) $query['match_offset'] : 1; - - while ( $match_offset > 0 && $this->step() ) { - if ( '#tag' !== $this->get_token_type() ) { - continue; - } - - if ( $this->matches_breadcrumbs( $breadcrumbs ) && 0 === --$match_offset ) { - return true; - } - } - - return false; - } - - /** - * Ensures internal accounting is maintained for HTML semantic rules while - * the underlying Tag Processor class is seeking to a bookmark. - * - * This doesn't currently have a way to represent non-tags and doesn't process - * semantic rules for text nodes. For access to the raw tokens consider using - * WP_HTML_Tag_Processor instead. - * - * @since 6.5.0 Added for internal support; do not use. - * - * @access private - * - * @return bool - */ - public function next_token() { - return $this->step(); - } - - /** - * Indicates if the currently-matched tag matches the given breadcrumbs. - * - * A "*" represents a single tag wildcard, where any tag matches, but not no tags. - * - * At some point this function _may_ support a `**` syntax for matching any number - * of unspecified tags in the breadcrumb stack. This has been intentionally left - * out, however, to keep this function simple and to avoid introducing backtracking, - * which could open up surprising performance breakdowns. - * - * Example: - * - * $processor = WP_HTML_Processor::create_fragment( '<div><span><figure><img></figure></span></div>' ); - * $processor->next_tag( 'img' ); - * true === $processor->matches_breadcrumbs( array( 'figure', 'img' ) ); - * true === $processor->matches_breadcrumbs( array( 'span', 'figure', 'img' ) ); - * false === $processor->matches_breadcrumbs( array( 'span', 'img' ) ); - * true === $processor->matches_breadcrumbs( array( 'span', '*', 'img' ) ); - * - * @since 6.4.0 - * - * @param string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. - * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. - * @return bool Whether the currently-matched tag is found at the given nested structure. - */ - public function matches_breadcrumbs( $breadcrumbs ) { - // Everything matches when there are zero constraints. - if ( 0 === count( $breadcrumbs ) ) { - return true; - } - - // Start at the last crumb. - $crumb = end( $breadcrumbs ); - - if ( '*' !== $crumb && $this->get_tag() !== strtoupper( $crumb ) ) { - return false; - } - - foreach ( $this->state->stack_of_open_elements->walk_up() as $node ) { - $crumb = strtoupper( current( $breadcrumbs ) ); - - if ( '*' !== $crumb && $node->node_name !== $crumb ) { - return false; - } - - if ( false === prev( $breadcrumbs ) ) { - return true; - } - } - - return false; - } - - /** - * Steps through the HTML document and stop at the next tag, if any. - * - * @since 6.4.0 - * - * @throws Exception When unable to allocate a bookmark for the next token in the input HTML document. - * - * @see self::PROCESS_NEXT_NODE - * @see self::REPROCESS_CURRENT_NODE - * - * @param string $node_to_process Whether to parse the next node or reprocess the current node. - * @return bool Whether a tag was matched. - */ - public function step( $node_to_process = self::PROCESS_NEXT_NODE ) { - // Refuse to proceed if there was a previous error. - if ( null !== $this->last_error ) { - return false; - } - - if ( self::REPROCESS_CURRENT_NODE !== $node_to_process ) { - /* - * Void elements still hop onto the stack of open elements even though - * there's no corresponding closing tag. This is important for managing - * stack-based operations such as "navigate to parent node" or checking - * on an element's breadcrumbs. - * - * When moving on to the next node, therefore, if the bottom-most element - * on the stack is a void element, it must be closed. - * - * @todo Once self-closing foreign elements and BGSOUND are supported, - * they must also be implicitly closed here too. BGSOUND is - * special since it's only self-closing if the self-closing flag - * is provided in the opening tag, otherwise it expects a tag closer. - */ - $top_node = $this->state->stack_of_open_elements->current_node(); - if ( - $top_node && ( - // Void elements. - self::is_void( $top_node->node_name ) || - // Comments, text nodes, and other atomic tokens. - '#' === $top_node->node_name[0] || - // Doctype declarations. - 'html' === $top_node->node_name - ) - ) { - $this->state->stack_of_open_elements->pop(); - } - } - - if ( self::PROCESS_NEXT_NODE === $node_to_process ) { - parent::next_token(); - } - - // Finish stepping when there are no more tokens in the document. - if ( - WP_HTML_Tag_Processor::STATE_INCOMPLETE_INPUT === $this->parser_state || - WP_HTML_Tag_Processor::STATE_COMPLETE === $this->parser_state - ) { - return false; - } - - $this->state->current_token = new WP_HTML_Token( - $this->bookmark_token(), - $this->get_token_name(), - $this->has_self_closing_flag(), - $this->release_internal_bookmark_on_destruct - ); - - try { - switch ( $this->state->insertion_mode ) { - case WP_HTML_Processor_State::INSERTION_MODE_IN_BODY: - return $this->step_in_body(); - - default: - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." ); - } - } catch ( WP_HTML_Unsupported_Exception $e ) { - /* - * Exceptions are used in this class to escape deep call stacks that - * otherwise might involve messier calling and return conventions. - */ - return false; - } - } - - /** - * Computes the HTML breadcrumbs for the currently-matched node, if matched. - * - * Breadcrumbs start at the outermost parent and descend toward the matched element. - * They always include the entire path from the root HTML node to the matched element. - * - * @todo It could be more efficient to expose a generator-based version of this function - * to avoid creating the array copy on tag iteration. If this is done, it would likely - * be more useful to walk up the stack when yielding instead of starting at the top. - * - * Example - * - * $processor = WP_HTML_Processor::create_fragment( '<p><strong><em><img></em></strong></p>' ); - * $processor->next_tag( 'IMG' ); - * $processor->get_breadcrumbs() === array( 'HTML', 'BODY', 'P', 'STRONG', 'EM', 'IMG' ); - * - * @since 6.4.0 - * - * @return string[]|null Array of tag names representing path to matched node, if matched, otherwise NULL. - */ - public function get_breadcrumbs() { - $breadcrumbs = array(); - foreach ( $this->state->stack_of_open_elements->walk_down() as $stack_item ) { - $breadcrumbs[] = $stack_item->node_name; - } - - return $breadcrumbs; - } - - /** - * Parses next element in the 'in body' insertion mode. - * - * This internal function performs the 'in body' insertion mode - * logic for the generalized WP_HTML_Processor::step() function. - * - * @since 6.4.0 - * - * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. - * - * @see https://html.spec.whatwg.org/#parsing-main-inbody - * @see WP_HTML_Processor::step - * - * @return bool Whether an element was found. - */ - private function step_in_body() { - $token_name = $this->get_token_name(); - $token_type = $this->get_token_type(); - $op_sigil = '#tag' === $token_type ? ( $this->is_tag_closer() ? '-' : '+' ) : ''; - $op = "{$op_sigil}{$token_name}"; - - switch ( $op ) { - case '#comment': - case '#funky-comment': - case '#presumptuous-tag': - $this->insert_html_element( $this->state->current_token ); - return true; - - case '#text': - $this->reconstruct_active_formatting_elements(); - - $current_token = $this->bookmarks[ $this->state->current_token->bookmark_name ]; - - /* - * > A character token that is U+0000 NULL - * - * Any successive sequence of NULL bytes is ignored and won't - * trigger active format reconstruction. Therefore, if the text - * only comprises NULL bytes then the token should be ignored - * here, but if there are any other characters in the stream - * the active formats should be reconstructed. - */ - if ( - 1 <= $current_token->length && - "\x00" === $this->html[ $current_token->start ] && - strspn( $this->html, "\x00", $current_token->start, $current_token->length ) === $current_token->length - ) { - // Parse error: ignore the token. - return $this->step(); - } - - /* - * Whitespace-only text does not affect the frameset-ok flag. - * It is probably inter-element whitespace, but it may also - * contain character references which decode only to whitespace. - */ - $text = $this->get_modifiable_text(); - if ( strlen( $text ) !== strspn( $text, " \t\n\f\r" ) ) { - $this->state->frameset_ok = false; - } - - $this->insert_html_element( $this->state->current_token ); - return true; - - case 'html': - /* - * > A DOCTYPE token - * > Parse error. Ignore the token. - */ - return $this->step(); - - /* - * > A start tag whose tag name is "button" - */ - case '+BUTTON': - if ( $this->state->stack_of_open_elements->has_element_in_scope( 'BUTTON' ) ) { - // @todo Indicate a parse error once it's possible. This error does not impact the logic here. - $this->generate_implied_end_tags(); - $this->state->stack_of_open_elements->pop_until( 'BUTTON' ); - } - - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - $this->state->frameset_ok = false; - - return true; - - /* - * > A start tag whose tag name is one of: "address", "article", "aside", - * > "blockquote", "center", "details", "dialog", "dir", "div", "dl", - * > "fieldset", "figcaption", "figure", "footer", "header", "hgroup", - * > "main", "menu", "nav", "ol", "p", "search", "section", "summary", "ul" - */ - case '+ADDRESS': - case '+ARTICLE': - case '+ASIDE': - case '+BLOCKQUOTE': - case '+CENTER': - case '+DETAILS': - case '+DIALOG': - case '+DIR': - case '+DIV': - case '+DL': - case '+FIELDSET': - case '+FIGCAPTION': - case '+FIGURE': - case '+FOOTER': - case '+HEADER': - case '+HGROUP': - case '+MAIN': - case '+MENU': - case '+NAV': - case '+OL': - case '+P': - case '+SEARCH': - case '+SECTION': - case '+SUMMARY': - case '+UL': - if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { - $this->close_a_p_element(); - } - - $this->insert_html_element( $this->state->current_token ); - return true; - - /* - * > An end tag whose tag name is one of: "address", "article", "aside", "blockquote", - * > "button", "center", "details", "dialog", "dir", "div", "dl", "fieldset", - * > "figcaption", "figure", "footer", "header", "hgroup", "listing", "main", - * > "menu", "nav", "ol", "pre", "search", "section", "summary", "ul" - */ - case '-ADDRESS': - case '-ARTICLE': - case '-ASIDE': - case '-BLOCKQUOTE': - case '-BUTTON': - case '-CENTER': - case '-DETAILS': - case '-DIALOG': - case '-DIR': - case '-DIV': - case '-DL': - case '-FIELDSET': - case '-FIGCAPTION': - case '-FIGURE': - case '-FOOTER': - case '-HEADER': - case '-HGROUP': - case '-LISTING': - case '-MAIN': - case '-MENU': - case '-NAV': - case '-OL': - case '-PRE': - case '-SEARCH': - case '-SECTION': - case '-SUMMARY': - case '-UL': - if ( ! $this->state->stack_of_open_elements->has_element_in_scope( $token_name ) ) { - // @todo Report parse error. - // Ignore the token. - return $this->step(); - } - - $this->generate_implied_end_tags(); - if ( $this->state->stack_of_open_elements->current_node()->node_name !== $token_name ) { - // @todo Record parse error: this error doesn't impact parsing. - } - $this->state->stack_of_open_elements->pop_until( $token_name ); - return true; - - /* - * > A start tag whose tag name is one of: "h1", "h2", "h3", "h4", "h5", "h6" - */ - case '+H1': - case '+H2': - case '+H3': - case '+H4': - case '+H5': - case '+H6': - if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { - $this->close_a_p_element(); - } - - if ( - in_array( - $this->state->stack_of_open_elements->current_node()->node_name, - array( 'H1', 'H2', 'H3', 'H4', 'H5', 'H6' ), - true - ) - ) { - // @todo Indicate a parse error once it's possible. - $this->state->stack_of_open_elements->pop(); - } - - $this->insert_html_element( $this->state->current_token ); - return true; - - /* - * > A start tag whose tag name is one of: "pre", "listing" - */ - case '+PRE': - case '+LISTING': - if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { - $this->close_a_p_element(); - } - $this->insert_html_element( $this->state->current_token ); - $this->state->frameset_ok = false; - return true; - - /* - * > An end tag whose tag name is one of: "h1", "h2", "h3", "h4", "h5", "h6" - */ - case '-H1': - case '-H2': - case '-H3': - case '-H4': - case '-H5': - case '-H6': - if ( ! $this->state->stack_of_open_elements->has_element_in_scope( '(internal: H1 through H6 - do not use)' ) ) { - /* - * This is a parse error; ignore the token. - * - * @todo Indicate a parse error once it's possible. - */ - return $this->step(); - } - - $this->generate_implied_end_tags(); - - if ( $this->state->stack_of_open_elements->current_node()->node_name !== $token_name ) { - // @todo Record parse error: this error doesn't impact parsing. - } - - $this->state->stack_of_open_elements->pop_until( '(internal: H1 through H6 - do not use)' ); - return true; - - /* - * > A start tag whose tag name is "li" - * > A start tag whose tag name is one of: "dd", "dt" - */ - case '+DD': - case '+DT': - case '+LI': - $this->state->frameset_ok = false; - $node = $this->state->stack_of_open_elements->current_node(); - $is_li = 'LI' === $token_name; - - in_body_list_loop: - /* - * The logic for LI and DT/DD is the same except for one point: LI elements _only_ - * close other LI elements, but a DT or DD element closes _any_ open DT or DD element. - */ - if ( $is_li ? 'LI' === $node->node_name : ( 'DD' === $node->node_name || 'DT' === $node->node_name ) ) { - $node_name = $is_li ? 'LI' : $node->node_name; - $this->generate_implied_end_tags( $node_name ); - if ( $node_name !== $this->state->stack_of_open_elements->current_node()->node_name ) { - // @todo Indicate a parse error once it's possible. This error does not impact the logic here. - } - - $this->state->stack_of_open_elements->pop_until( $node_name ); - goto in_body_list_done; - } - - if ( - 'ADDRESS' !== $node->node_name && - 'DIV' !== $node->node_name && - 'P' !== $node->node_name && - $this->is_special( $node->node_name ) - ) { - /* - * > If node is in the special category, but is not an address, div, - * > or p element, then jump to the step labeled done below. - */ - goto in_body_list_done; - } else { - /* - * > Otherwise, set node to the previous entry in the stack of open elements - * > and return to the step labeled loop. - */ - foreach ( $this->state->stack_of_open_elements->walk_up( $node ) as $item ) { - $node = $item; - break; - } - goto in_body_list_loop; - } - - in_body_list_done: - if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { - $this->close_a_p_element(); - } - - $this->insert_html_element( $this->state->current_token ); - return true; - - /* - * > An end tag whose tag name is "li" - * > An end tag whose tag name is one of: "dd", "dt" - */ - case '-DD': - case '-DT': - case '-LI': - if ( - /* - * An end tag whose tag name is "li": - * If the stack of open elements does not have an li element in list item scope, - * then this is a parse error; ignore the token. - */ - ( - 'LI' === $token_name && - ! $this->state->stack_of_open_elements->has_element_in_list_item_scope( 'LI' ) - ) || - /* - * An end tag whose tag name is one of: "dd", "dt": - * If the stack of open elements does not have an element in scope that is an - * HTML element with the same tag name as that of the token, then this is a - * parse error; ignore the token. - */ - ( - 'LI' !== $token_name && - ! $this->state->stack_of_open_elements->has_element_in_scope( $token_name ) - ) - ) { - /* - * This is a parse error, ignore the token. - * - * @todo Indicate a parse error once it's possible. - */ - return $this->step(); - } - - $this->generate_implied_end_tags( $token_name ); - - if ( $token_name !== $this->state->stack_of_open_elements->current_node()->node_name ) { - // @todo Indicate a parse error once it's possible. This error does not impact the logic here. - } - - $this->state->stack_of_open_elements->pop_until( $token_name ); - return true; - - /* - * > An end tag whose tag name is "p" - */ - case '-P': - if ( ! $this->state->stack_of_open_elements->has_p_in_button_scope() ) { - $this->insert_html_element( $this->state->current_token ); - } - - $this->close_a_p_element(); - return true; - - // > A start tag whose tag name is "a" - case '+A': - foreach ( $this->state->active_formatting_elements->walk_up() as $item ) { - switch ( $item->node_name ) { - case 'marker': - break; - - case 'A': - $this->run_adoption_agency_algorithm(); - $this->state->active_formatting_elements->remove_node( $item ); - $this->state->stack_of_open_elements->remove_node( $item ); - break; - } - } - - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - $this->state->active_formatting_elements->push( $this->state->current_token ); - return true; - - /* - * > A start tag whose tag name is one of: "b", "big", "code", "em", "font", "i", - * > "s", "small", "strike", "strong", "tt", "u" - */ - case '+B': - case '+BIG': - case '+CODE': - case '+EM': - case '+FONT': - case '+I': - case '+S': - case '+SMALL': - case '+STRIKE': - case '+STRONG': - case '+TT': - case '+U': - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - $this->state->active_formatting_elements->push( $this->state->current_token ); - return true; - - /* - * > An end tag whose tag name is one of: "a", "b", "big", "code", "em", "font", "i", - * > "nobr", "s", "small", "strike", "strong", "tt", "u" - */ - case '-A': - case '-B': - case '-BIG': - case '-CODE': - case '-EM': - case '-FONT': - case '-I': - case '-S': - case '-SMALL': - case '-STRIKE': - case '-STRONG': - case '-TT': - case '-U': - $this->run_adoption_agency_algorithm(); - return true; - - /* - * > An end tag whose tag name is "br" - * > Parse error. Drop the attributes from the token, and act as described in the next - * > entry; i.e. act as if this was a "br" start tag token with no attributes, rather - * > than the end tag token that it actually is. - */ - case '-BR': - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( 'Closing BR tags require unimplemented special handling.' ); - - /* - * > A start tag whose tag name is one of: "area", "br", "embed", "img", "keygen", "wbr" - */ - case '+AREA': - case '+BR': - case '+EMBED': - case '+IMG': - case '+KEYGEN': - case '+WBR': - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - $this->state->frameset_ok = false; - return true; - - /* - * > A start tag whose tag name is "input" - */ - case '+INPUT': - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - $type_attribute = $this->get_attribute( 'type' ); - /* - * > If the token does not have an attribute with the name "type", or if it does, - * > but that attribute's value is not an ASCII case-insensitive match for the - * > string "hidden", then: set the frameset-ok flag to "not ok". - */ - if ( ! is_string( $type_attribute ) || 'hidden' !== strtolower( $type_attribute ) ) { - $this->state->frameset_ok = false; - } - return true; - - /* - * > A start tag whose tag name is "hr" - */ - case '+HR': - if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { - $this->close_a_p_element(); - } - $this->insert_html_element( $this->state->current_token ); - $this->state->frameset_ok = false; - return true; - - /* - * > A start tag whose tag name is one of: "param", "source", "track" - */ - case '+PARAM': - case '+SOURCE': - case '+TRACK': - $this->insert_html_element( $this->state->current_token ); - return true; - } - - /* - * These tags require special handling in the 'in body' insertion mode - * but that handling hasn't yet been implemented. - * - * As the rules for each tag are implemented, the corresponding tag - * name should be removed from this list. An accompanying test should - * help ensure this list is maintained. - * - * @see Tests_HtmlApi_WpHtmlProcessor::test_step_in_body_fails_on_unsupported_tags - * - * Since this switch structure throws a WP_HTML_Unsupported_Exception, it's - * possible to handle "any other start tag" and "any other end tag" below, - * as that guarantees execution doesn't proceed for the unimplemented tags. - * - * @see https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inbody - */ - switch ( $token_name ) { - case 'APPLET': - case 'BASE': - case 'BASEFONT': - case 'BGSOUND': - case 'BODY': - case 'CAPTION': - case 'COL': - case 'COLGROUP': - case 'FORM': - case 'FRAME': - case 'FRAMESET': - case 'HEAD': - case 'HTML': - case 'IFRAME': - case 'LINK': - case 'MARQUEE': - case 'MATH': - case 'META': - case 'NOBR': - case 'NOEMBED': - case 'NOFRAMES': - case 'NOSCRIPT': - case 'OBJECT': - case 'OPTGROUP': - case 'OPTION': - case 'PLAINTEXT': - case 'RB': - case 'RP': - case 'RT': - case 'RTC': - case 'SARCASM': - case 'SCRIPT': - case 'SELECT': - case 'STYLE': - case 'SVG': - case 'TABLE': - case 'TBODY': - case 'TD': - case 'TEMPLATE': - case 'TEXTAREA': - case 'TFOOT': - case 'TH': - case 'THEAD': - case 'TITLE': - case 'TR': - case 'XMP': - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( "Cannot process {$token_name} element." ); - } - - if ( ! $this->is_tag_closer() ) { - /* - * > Any other start tag - */ - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - return true; - } else { - /* - * > Any other end tag - */ - - /* - * Find the corresponding tag opener in the stack of open elements, if - * it exists before reaching a special element, which provides a kind - * of boundary in the stack. For example, a `</custom-tag>` should not - * close anything beyond its containing `P` or `DIV` element. - */ - foreach ( $this->state->stack_of_open_elements->walk_up() as $node ) { - if ( $token_name === $node->node_name ) { - break; - } - - if ( self::is_special( $node->node_name ) ) { - // This is a parse error, ignore the token. - return $this->step(); - } - } - - $this->generate_implied_end_tags( $token_name ); - if ( $node !== $this->state->stack_of_open_elements->current_node() ) { - // @todo Record parse error: this error doesn't impact parsing. - } - - foreach ( $this->state->stack_of_open_elements->walk_up() as $item ) { - $this->state->stack_of_open_elements->pop(); - if ( $node === $item ) { - return true; - } - } - } - } - - /* - * Internal helpers - */ - - /** - * Creates a new bookmark for the currently-matched token and returns the generated name. - * - * @since 6.4.0 - * @since 6.5.0 Renamed from bookmark_tag() to bookmark_token(). - * - * @throws Exception When unable to allocate requested bookmark. - * - * @return string|false Name of created bookmark, or false if unable to create. - */ - private function bookmark_token() { - if ( ! parent::set_bookmark( ++$this->bookmark_counter ) ) { - $this->last_error = self::ERROR_EXCEEDED_MAX_BOOKMARKS; - throw new Exception( 'could not allocate bookmark' ); - } - - return "{$this->bookmark_counter}"; - } - - /* - * HTML semantic overrides for Tag Processor - */ - - /** - * Returns the uppercase name of the matched tag. - * - * The semantic rules for HTML specify that certain tags be reprocessed - * with a different tag name. Because of this, the tag name presented - * by the HTML Processor may differ from the one reported by the HTML - * Tag Processor, which doesn't apply these semantic rules. - * - * Example: - * - * $processor = new WP_HTML_Tag_Processor( '<div class="test">Test</div>' ); - * $processor->next_tag() === true; - * $processor->get_tag() === 'DIV'; - * - * $processor->next_tag() === false; - * $processor->get_tag() === null; - * - * @since 6.4.0 - * - * @return string|null Name of currently matched tag in input HTML, or `null` if none found. - */ - public function get_tag() { - if ( null !== $this->last_error ) { - return null; - } - - $tag_name = parent::get_tag(); - - switch ( $tag_name ) { - case 'IMAGE': - /* - * > A start tag whose tag name is "image" - * > Change the token's tag name to "img" and reprocess it. (Don't ask.) - */ - return 'IMG'; - - default: - return $tag_name; - } - } - - /** - * Removes a bookmark that is no longer needed. - * - * Releasing a bookmark frees up the small - * performance overhead it requires. - * - * @since 6.4.0 - * - * @param string $bookmark_name Name of the bookmark to remove. - * @return bool Whether the bookmark already existed before removal. - */ - public function release_bookmark( $bookmark_name ) { - return parent::release_bookmark( "_{$bookmark_name}" ); - } - - /** - * Moves the internal cursor in the HTML Processor to a given bookmark's location. - * - * Be careful! Seeking backwards to a previous location resets the parser to the - * start of the document and reparses the entire contents up until it finds the - * sought-after bookmarked location. - * - * In order to prevent accidental infinite loops, there's a - * maximum limit on the number of times seek() can be called. - * - * @throws Exception When unable to allocate a bookmark for the next token in the input HTML document. - * - * @since 6.4.0 - * - * @param string $bookmark_name Jump to the place in the document identified by this bookmark name. - * @return bool Whether the internal cursor was successfully moved to the bookmark's location. - */ - public function seek( $bookmark_name ) { - // Flush any pending updates to the document before beginning. - $this->get_updated_html(); - - $actual_bookmark_name = "_{$bookmark_name}"; - $processor_started_at = $this->state->current_token - ? $this->bookmarks[ $this->state->current_token->bookmark_name ]->start - : 0; - $bookmark_starts_at = $this->bookmarks[ $actual_bookmark_name ]->start; - $direction = $bookmark_starts_at > $processor_started_at ? 'forward' : 'backward'; - - /* - * If seeking backwards, it's possible that the sought-after bookmark exists within an element - * which has been closed before the current cursor; in other words, it has already been removed - * from the stack of open elements. This means that it's insufficient to simply pop off elements - * from the stack of open elements which appear after the bookmarked location and then jump to - * that location, as the elements which were open before won't be re-opened. - * - * In order to maintain consistency, the HTML Processor rewinds to the start of the document - * and reparses everything until it finds the sought-after bookmark. - * - * There are potentially better ways to do this: cache the parser state for each bookmark and - * restore it when seeking; store an immutable and idempotent register of where elements open - * and close. - * - * If caching the parser state it will be essential to properly maintain the cached stack of - * open elements and active formatting elements when modifying the document. This could be a - * tedious and time-consuming process as well, and so for now will not be performed. - * - * It may be possible to track bookmarks for where elements open and close, and in doing so - * be able to quickly recalculate breadcrumbs for any element in the document. It may even - * be possible to remove the stack of open elements and compute it on the fly this way. - * If doing this, the parser would need to track the opening and closing locations for all - * tokens in the breadcrumb path for any and all bookmarks. By utilizing bookmarks themselves - * this list could be automatically maintained while modifying the document. Finding the - * breadcrumbs would then amount to traversing that list from the start until the token - * being inspected. Once an element closes, if there are no bookmarks pointing to locations - * within that element, then all of these locations may be forgotten to save on memory use - * and computation time. - */ - if ( 'backward' === $direction ) { - /* - * Instead of clearing the parser state and starting fresh, calling the stack methods - * maintains the proper flags in the parser. - */ - foreach ( $this->state->stack_of_open_elements->walk_up() as $item ) { - if ( 'context-node' === $item->bookmark_name ) { - break; - } - - $this->state->stack_of_open_elements->remove_node( $item ); - } - - foreach ( $this->state->active_formatting_elements->walk_up() as $item ) { - if ( 'context-node' === $item->bookmark_name ) { - break; - } - - $this->state->active_formatting_elements->remove_node( $item ); - } - - parent::seek( 'context-node' ); - $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_BODY; - $this->state->frameset_ok = true; - } - - // When moving forwards, reparse the document until reaching the same location as the original bookmark. - if ( $bookmark_starts_at === $this->bookmarks[ $this->state->current_token->bookmark_name ]->start ) { - return true; - } - - while ( $this->step() ) { - if ( $bookmark_starts_at === $this->bookmarks[ $this->state->current_token->bookmark_name ]->start ) { - return true; - } - } - - return false; - } - - /** - * Sets a bookmark in the HTML document. - * - * Bookmarks represent specific places or tokens in the HTML - * document, such as a tag opener or closer. When applying - * edits to a document, such as setting an attribute, the - * text offsets of that token may shift; the bookmark is - * kept updated with those shifts and remains stable unless - * the entire span of text in which the token sits is removed. - * - * Release bookmarks when they are no longer needed. - * - * Example: - * - * <main><h2>Surprising fact you may not know!</h2></main> - * ^ ^ - * \-|-- this `H2` opener bookmark tracks the token - * - * <main class="clickbait"><h2>Surprising fact you may no… - * ^ ^ - * \-|-- it shifts with edits - * - * Bookmarks provide the ability to seek to a previously-scanned - * place in the HTML document. This avoids the need to re-scan - * the entire document. - * - * Example: - * - * <ul><li>One</li><li>Two</li><li>Three</li></ul> - * ^^^^ - * want to note this last item - * - * $p = new WP_HTML_Tag_Processor( $html ); - * $in_list = false; - * while ( $p->next_tag( array( 'tag_closers' => $in_list ? 'visit' : 'skip' ) ) ) { - * if ( 'UL' === $p->get_tag() ) { - * if ( $p->is_tag_closer() ) { - * $in_list = false; - * $p->set_bookmark( 'resume' ); - * if ( $p->seek( 'last-li' ) ) { - * $p->add_class( 'last-li' ); - * } - * $p->seek( 'resume' ); - * $p->release_bookmark( 'last-li' ); - * $p->release_bookmark( 'resume' ); - * } else { - * $in_list = true; - * } - * } - * - * if ( 'LI' === $p->get_tag() ) { - * $p->set_bookmark( 'last-li' ); - * } - * } - * - * Bookmarks intentionally hide the internal string offsets - * to which they refer. They are maintained internally as - * updates are applied to the HTML document and therefore - * retain their "position" - the location to which they - * originally pointed. The inability to use bookmarks with - * functions like `substr` is therefore intentional to guard - * against accidentally breaking the HTML. - * - * Because bookmarks allocate memory and require processing - * for every applied update, they are limited and require - * a name. They should not be created with programmatically-made - * names, such as "li_{$index}" with some loop. As a general - * rule they should only be created with string-literal names - * like "start-of-section" or "last-paragraph". - * - * Bookmarks are a powerful tool to enable complicated behavior. - * Consider double-checking that you need this tool if you are - * reaching for it, as inappropriate use could lead to broken - * HTML structure or unwanted processing overhead. - * - * @since 6.4.0 - * - * @param string $bookmark_name Identifies this particular bookmark. - * @return bool Whether the bookmark was successfully created. - */ - public function set_bookmark( $bookmark_name ) { - return parent::set_bookmark( "_{$bookmark_name}" ); - } - - /** - * Checks whether a bookmark with the given name exists. - * - * @since 6.5.0 - * - * @param string $bookmark_name Name to identify a bookmark that potentially exists. - * @return bool Whether that bookmark exists. - */ - public function has_bookmark( $bookmark_name ) { - return parent::has_bookmark( "_{$bookmark_name}" ); - } - - /* - * HTML Parsing Algorithms - */ - - /** - * Closes a P element. - * - * @since 6.4.0 - * - * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. - * - * @see https://html.spec.whatwg.org/#close-a-p-element - */ - private function close_a_p_element() { - $this->generate_implied_end_tags( 'P' ); - $this->state->stack_of_open_elements->pop_until( 'P' ); - } - - /** - * Closes elements that have implied end tags. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#generate-implied-end-tags - * - * @param string|null $except_for_this_element Perform as if this element doesn't exist in the stack of open elements. - */ - private function generate_implied_end_tags( $except_for_this_element = null ) { - $elements_with_implied_end_tags = array( - 'DD', - 'DT', - 'LI', - 'P', - ); - - $current_node = $this->state->stack_of_open_elements->current_node(); - while ( - $current_node && $current_node->node_name !== $except_for_this_element && - in_array( $this->state->stack_of_open_elements->current_node(), $elements_with_implied_end_tags, true ) - ) { - $this->state->stack_of_open_elements->pop(); - } - } - - /** - * Closes elements that have implied end tags, thoroughly. - * - * See the HTML specification for an explanation why this is - * different from generating end tags in the normal sense. - * - * @since 6.4.0 - * - * @see WP_HTML_Processor::generate_implied_end_tags - * @see https://html.spec.whatwg.org/#generate-implied-end-tags - */ - private function generate_implied_end_tags_thoroughly() { - $elements_with_implied_end_tags = array( - 'DD', - 'DT', - 'LI', - 'P', - ); - - while ( in_array( $this->state->stack_of_open_elements->current_node(), $elements_with_implied_end_tags, true ) ) { - $this->state->stack_of_open_elements->pop(); - } - } - - /** - * Reconstructs the active formatting elements. - * - * > This has the effect of reopening all the formatting elements that were opened - * > in the current body, cell, or caption (whichever is youngest) that haven't - * > been explicitly closed. - * - * @since 6.4.0 - * - * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. - * - * @see https://html.spec.whatwg.org/#reconstruct-the-active-formatting-elements - * - * @return bool Whether any formatting elements needed to be reconstructed. - */ - private function reconstruct_active_formatting_elements() { - /* - * > If there are no entries in the list of active formatting elements, then there is nothing - * > to reconstruct; stop this algorithm. - */ - if ( 0 === $this->state->active_formatting_elements->count() ) { - return false; - } - - $last_entry = $this->state->active_formatting_elements->current_node(); - if ( - - /* - * > If the last (most recently added) entry in the list of active formatting elements is a marker; - * > stop this algorithm. - */ - 'marker' === $last_entry->node_name || - - /* - * > If the last (most recently added) entry in the list of active formatting elements is an - * > element that is in the stack of open elements, then there is nothing to reconstruct; - * > stop this algorithm. - */ - $this->state->stack_of_open_elements->contains_node( $last_entry ) - ) { - return false; - } - - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( 'Cannot reconstruct active formatting elements when advancing and rewinding is required.' ); - } - - /** - * Runs the adoption agency algorithm. - * - * @since 6.4.0 - * - * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. - * - * @see https://html.spec.whatwg.org/#adoption-agency-algorithm - */ - private function run_adoption_agency_algorithm() { - $budget = 1000; - $subject = $this->get_tag(); - $current_node = $this->state->stack_of_open_elements->current_node(); - - if ( - // > If the current node is an HTML element whose tag name is subject - $current_node && $subject === $current_node->node_name && - // > the current node is not in the list of active formatting elements - ! $this->state->active_formatting_elements->contains_node( $current_node ) - ) { - $this->state->stack_of_open_elements->pop(); - return; - } - - $outer_loop_counter = 0; - while ( $budget-- > 0 ) { - if ( $outer_loop_counter++ >= 8 ) { - return; - } - - /* - * > Let formatting element be the last element in the list of active formatting elements that: - * > - is between the end of the list and the last marker in the list, - * > if any, or the start of the list otherwise, - * > - and has the tag name subject. - */ - $formatting_element = null; - foreach ( $this->state->active_formatting_elements->walk_up() as $item ) { - if ( 'marker' === $item->node_name ) { - break; - } - - if ( $subject === $item->node_name ) { - $formatting_element = $item; - break; - } - } - - // > If there is no such element, then return and instead act as described in the "any other end tag" entry above. - if ( null === $formatting_element ) { - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( 'Cannot run adoption agency when "any other end tag" is required.' ); - } - - // > If formatting element is not in the stack of open elements, then this is a parse error; remove the element from the list, and return. - if ( ! $this->state->stack_of_open_elements->contains_node( $formatting_element ) ) { - $this->state->active_formatting_elements->remove_node( $formatting_element ); - return; - } - - // > If formatting element is in the stack of open elements, but the element is not in scope, then this is a parse error; return. - if ( ! $this->state->stack_of_open_elements->has_element_in_scope( $formatting_element->node_name ) ) { - return; - } - - /* - * > Let furthest block be the topmost node in the stack of open elements that is lower in the stack - * > than formatting element, and is an element in the special category. There might not be one. - */ - $is_above_formatting_element = true; - $furthest_block = null; - foreach ( $this->state->stack_of_open_elements->walk_down() as $item ) { - if ( $is_above_formatting_element && $formatting_element->bookmark_name !== $item->bookmark_name ) { - continue; - } - - if ( $is_above_formatting_element ) { - $is_above_formatting_element = false; - continue; - } - - if ( self::is_special( $item->node_name ) ) { - $furthest_block = $item; - break; - } - } - - /* - * > If there is no furthest block, then the UA must first pop all the nodes from the bottom of the - * > stack of open elements, from the current node up to and including formatting element, then - * > remove formatting element from the list of active formatting elements, and finally return. - */ - if ( null === $furthest_block ) { - foreach ( $this->state->stack_of_open_elements->walk_up() as $item ) { - $this->state->stack_of_open_elements->pop(); - - if ( $formatting_element->bookmark_name === $item->bookmark_name ) { - $this->state->active_formatting_elements->remove_node( $formatting_element ); - return; - } - } - } - - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( 'Cannot extract common ancestor in adoption agency algorithm.' ); - } - - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( 'Cannot run adoption agency when looping required.' ); - } - - /** - * Inserts an HTML element on the stack of open elements. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#insert-a-foreign-element - * - * @param WP_HTML_Token $token Name of bookmark pointing to element in original input HTML. - */ - private function insert_html_element( $token ) { - $this->state->stack_of_open_elements->push( $token ); - } - - /* - * HTML Specification Helpers - */ - - /** - * Returns whether an element of a given name is in the HTML special category. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#special - * - * @param string $tag_name Name of element to check. - * @return bool Whether the element of the given name is in the special category. - */ - public static function is_special( $tag_name ) { - $tag_name = strtoupper( $tag_name ); - - return ( - 'ADDRESS' === $tag_name || - 'APPLET' === $tag_name || - 'AREA' === $tag_name || - 'ARTICLE' === $tag_name || - 'ASIDE' === $tag_name || - 'BASE' === $tag_name || - 'BASEFONT' === $tag_name || - 'BGSOUND' === $tag_name || - 'BLOCKQUOTE' === $tag_name || - 'BODY' === $tag_name || - 'BR' === $tag_name || - 'BUTTON' === $tag_name || - 'CAPTION' === $tag_name || - 'CENTER' === $tag_name || - 'COL' === $tag_name || - 'COLGROUP' === $tag_name || - 'DD' === $tag_name || - 'DETAILS' === $tag_name || - 'DIR' === $tag_name || - 'DIV' === $tag_name || - 'DL' === $tag_name || - 'DT' === $tag_name || - 'EMBED' === $tag_name || - 'FIELDSET' === $tag_name || - 'FIGCAPTION' === $tag_name || - 'FIGURE' === $tag_name || - 'FOOTER' === $tag_name || - 'FORM' === $tag_name || - 'FRAME' === $tag_name || - 'FRAMESET' === $tag_name || - 'H1' === $tag_name || - 'H2' === $tag_name || - 'H3' === $tag_name || - 'H4' === $tag_name || - 'H5' === $tag_name || - 'H6' === $tag_name || - 'HEAD' === $tag_name || - 'HEADER' === $tag_name || - 'HGROUP' === $tag_name || - 'HR' === $tag_name || - 'HTML' === $tag_name || - 'IFRAME' === $tag_name || - 'IMG' === $tag_name || - 'INPUT' === $tag_name || - 'KEYGEN' === $tag_name || - 'LI' === $tag_name || - 'LINK' === $tag_name || - 'LISTING' === $tag_name || - 'MAIN' === $tag_name || - 'MARQUEE' === $tag_name || - 'MENU' === $tag_name || - 'META' === $tag_name || - 'NAV' === $tag_name || - 'NOEMBED' === $tag_name || - 'NOFRAMES' === $tag_name || - 'NOSCRIPT' === $tag_name || - 'OBJECT' === $tag_name || - 'OL' === $tag_name || - 'P' === $tag_name || - 'PARAM' === $tag_name || - 'PLAINTEXT' === $tag_name || - 'PRE' === $tag_name || - 'SCRIPT' === $tag_name || - 'SEARCH' === $tag_name || - 'SECTION' === $tag_name || - 'SELECT' === $tag_name || - 'SOURCE' === $tag_name || - 'STYLE' === $tag_name || - 'SUMMARY' === $tag_name || - 'TABLE' === $tag_name || - 'TBODY' === $tag_name || - 'TD' === $tag_name || - 'TEMPLATE' === $tag_name || - 'TEXTAREA' === $tag_name || - 'TFOOT' === $tag_name || - 'TH' === $tag_name || - 'THEAD' === $tag_name || - 'TITLE' === $tag_name || - 'TR' === $tag_name || - 'TRACK' === $tag_name || - 'UL' === $tag_name || - 'WBR' === $tag_name || - 'XMP' === $tag_name || - - // MathML. - 'MI' === $tag_name || - 'MO' === $tag_name || - 'MN' === $tag_name || - 'MS' === $tag_name || - 'MTEXT' === $tag_name || - 'ANNOTATION-XML' === $tag_name || - - // SVG. - 'FOREIGNOBJECT' === $tag_name || - 'DESC' === $tag_name || - 'TITLE' === $tag_name - ); - } - - /** - * Returns whether a given element is an HTML Void Element - * - * > area, base, br, col, embed, hr, img, input, link, meta, source, track, wbr - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#void-elements - * - * @param string $tag_name Name of HTML tag to check. - * @return bool Whether the given tag is an HTML Void Element. - */ - public static function is_void( $tag_name ) { - $tag_name = strtoupper( $tag_name ); - - return ( - 'AREA' === $tag_name || - 'BASE' === $tag_name || - 'BASEFONT' === $tag_name || // Obsolete but still treated as void. - 'BGSOUND' === $tag_name || // Obsolete but still treated as void. - 'BR' === $tag_name || - 'COL' === $tag_name || - 'EMBED' === $tag_name || - 'FRAME' === $tag_name || - 'HR' === $tag_name || - 'IMG' === $tag_name || - 'INPUT' === $tag_name || - 'KEYGEN' === $tag_name || // Obsolete but still treated as void. - 'LINK' === $tag_name || - 'META' === $tag_name || - 'PARAM' === $tag_name || // Obsolete but still treated as void. - 'SOURCE' === $tag_name || - 'TRACK' === $tag_name || - 'WBR' === $tag_name - ); - } - - /* - * Constants that would pollute the top of the class if they were found there. - */ - - /** - * Indicates that the next HTML token should be parsed and processed. - * - * @since 6.4.0 - * - * @var string - */ - const PROCESS_NEXT_NODE = 'process-next-node'; - - /** - * Indicates that the current HTML token should be reprocessed in the newly-selected insertion mode. - * - * @since 6.4.0 - * - * @var string - */ - const REPROCESS_CURRENT_NODE = 'reprocess-current-node'; - - /** - * Indicates that the current HTML token should be processed without advancing the parser. - * - * @since 6.5.0 - * - * @var string - */ - const PROCESS_CURRENT_NODE = 'process-current-node'; - - /** - * Indicates that the parser encountered unsupported markup and has bailed. - * - * @since 6.4.0 - * - * @var string - */ - const ERROR_UNSUPPORTED = 'unsupported'; - - /** - * Indicates that the parser encountered more HTML tokens than it - * was able to process and has bailed. - * - * @since 6.4.0 - * - * @var string - */ - const ERROR_EXCEEDED_MAX_BOOKMARKS = 'exceeded-max-bookmarks'; - - /** - * Unlock code that must be passed into the constructor to create this class. - * - * This class extends the WP_HTML_Tag_Processor, which has a public class - * constructor. Therefore, it's not possible to have a private constructor here. - * - * This unlock code is used to ensure that anyone calling the constructor is - * doing so with a full understanding that it's intended to be a private API. - * - * @access private - */ - const CONSTRUCTOR_UNLOCK_CODE = 'Use WP_HTML_Processor::create_fragment() instead of calling the class constructor directly.'; -} diff --git a/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-processor-state-6-5.php b/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-processor-state-6-5.php deleted file mode 100644 index 890e19fb5da4d1..00000000000000 --- a/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-processor-state-6-5.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Processor_State class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.4.0 - */ - -/** - * Core class used by the HTML processor during HTML parsing - * for managing the internal parsing state. - * - * This class is designed for internal use by the HTML processor. - * - * @since 6.4.0 - * - * @access private - * - * @see WP_HTML_Processor - */ -class Gutenberg_HTML_Processor_State_6_5 { - /* - * Insertion mode constants. - * - * These constants exist and are named to make it easier to - * discover and recognize the supported insertion modes in - * the parser. - * - * Out of all the possible insertion modes, only those - * supported by the parser are listed here. As support - * is added to the parser for more modes, add them here - * following the same naming and value pattern. - * - * @see https://html.spec.whatwg.org/#the-insertion-mode - */ - - /** - * Initial insertion mode for full HTML parser. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#the-initial-insertion-mode - * @see WP_HTML_Processor_State::$insertion_mode - * - * @var string - */ - const INSERTION_MODE_INITIAL = 'insertion-mode-initial'; - - /** - * In body insertion mode for full HTML parser. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#parsing-main-inbody - * @see WP_HTML_Processor_State::$insertion_mode - * - * @var string - */ - const INSERTION_MODE_IN_BODY = 'insertion-mode-in-body'; - - /** - * Tracks open elements while scanning HTML. - * - * This property is initialized in the constructor and never null. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#stack-of-open-elements - * - * @var WP_HTML_Open_Elements - */ - public $stack_of_open_elements = null; - - /** - * Tracks open formatting elements, used to handle mis-nested formatting element tags. - * - * This property is initialized in the constructor and never null. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#list-of-active-formatting-elements - * - * @var WP_HTML_Active_Formatting_Elements - */ - public $active_formatting_elements = null; - - /** - * Refers to the currently-matched tag, if any. - * - * @since 6.4.0 - * - * @var WP_HTML_Token|null - */ - public $current_token = null; - - /** - * Tree construction insertion mode. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#insertion-mode - * - * @var string - */ - public $insertion_mode = self::INSERTION_MODE_INITIAL; - - /** - * Context node initializing fragment parser, if created as a fragment parser. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#concept-frag-parse-context - * - * @var [string, array]|null - */ - public $context_node = null; - - /** - * The frameset-ok flag indicates if a `FRAMESET` element is allowed in the current state. - * - * > The frameset-ok flag is set to "ok" when the parser is created. It is set to "not ok" after certain tokens are seen. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#frameset-ok-flag - * - * @var bool - */ - public $frameset_ok = true; - - /** - * Constructor - creates a new and empty state value. - * - * @since 6.4.0 - * - * @see WP_HTML_Processor - */ - public function __construct() { - $this->stack_of_open_elements = new Gutenberg_HTML_Open_Elements_6_5(); - $this->active_formatting_elements = new WP_HTML_Active_Formatting_Elements(); - } -} diff --git a/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-span-6-5.php b/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-span-6-5.php deleted file mode 100644 index ed596f1266ab5d..00000000000000 --- a/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-span-6-5.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Span class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.2.0 - */ - -/** - * Core class used by the HTML tag processor to represent a textual span - * inside an HTML document. - * - * This is a two-tuple in disguise, used to avoid the memory overhead - * involved in using an array for the same purpose. - * - * This class is for internal usage of the WP_HTML_Tag_Processor class. - * - * @access private - * @since 6.2.0 - * @since 6.5.0 Replaced `end` with `length` to more closely align with `substr()`. - * - * @see WP_HTML_Tag_Processor - */ -class Gutenberg_HTML_Span_6_5 { - /** - * Byte offset into document where span begins. - * - * @since 6.2.0 - * - * @var int - */ - public $start; - - /** - * Byte length of this span. - * - * @since 6.5.0 - * - * @var int - */ - public $length; - - /** - * Constructor. - * - * @since 6.2.0 - * - * @param int $start Byte offset into document where replacement span begins. - * @param int $length Byte length of span. - */ - public function __construct( $start, $length ) { - $this->start = $start; - $this->length = $length; - } -} diff --git a/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-tag-processor-6-5.php b/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-tag-processor-6-5.php deleted file mode 100644 index 3bbcc5047a076f..00000000000000 --- a/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-tag-processor-6-5.php +++ /dev/null @@ -1,3555 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Tag_Processor class - * - * Scans through an HTML document to find specific tags, then - * transforms those tags by adding, removing, or updating the - * values of the HTML attributes within that tag (opener). - * - * Does not fully parse HTML or _recurse_ into the HTML structure - * Instead this scans linearly through a document and only parses - * the HTML tag openers. - * - * ### Possible future direction for this module - * - * - Prune the whitespace when removing classes/attributes: e.g. "a b c" -> "c" not " c". - * This would increase the size of the changes for some operations but leave more - * natural-looking output HTML. - * - Properly decode HTML character references in `get_attribute()`. PHP's - * `html_entity_decode()` is wrong in a couple ways: it doesn't account for the - * no-ambiguous-ampersand rule, and it improperly handles the way semicolons may - * or may not terminate a character reference. - * - * @package WordPress - * @subpackage HTML-API - * @since 6.2.0 - */ - -/** - * Core class used to modify attributes in an HTML document for tags matching a query. - * - * ## Usage - * - * Use of this class requires three steps: - * - * 1. Create a new class instance with your input HTML document. - * 2. Find the tag(s) you are looking for. - * 3. Request changes to the attributes in those tag(s). - * - * Example: - * - * $tags = new WP_HTML_Tag_Processor( $html ); - * if ( $tags->next_tag( 'option' ) ) { - * $tags->set_attribute( 'selected', true ); - * } - * - * ### Finding tags - * - * The `next_tag()` function moves the internal cursor through - * your input HTML document until it finds a tag meeting any of - * the supplied restrictions in the optional query argument. If - * no argument is provided then it will find the next HTML tag, - * regardless of what kind it is. - * - * If you want to _find whatever the next tag is_: - * - * $tags->next_tag(); - * - * | Goal | Query | - * |-----------------------------------------------------------|---------------------------------------------------------------------------------| - * | Find any tag. | `$tags->next_tag();` | - * | Find next image tag. | `$tags->next_tag( array( 'tag_name' => 'img' ) );` | - * | Find next image tag (without passing the array). | `$tags->next_tag( 'img' );` | - * | Find next tag containing the `fullwidth` CSS class. | `$tags->next_tag( array( 'class_name' => 'fullwidth' ) );` | - * | Find next image tag containing the `fullwidth` CSS class. | `$tags->next_tag( array( 'tag_name' => 'img', 'class_name' => 'fullwidth' ) );` | - * - * If a tag was found meeting your criteria then `next_tag()` - * will return `true` and you can proceed to modify it. If it - * returns `false`, however, it failed to find the tag and - * moved the cursor to the end of the file. - * - * Once the cursor reaches the end of the file the processor - * is done and if you want to reach an earlier tag you will - * need to recreate the processor and start over, as it's - * unable to back up or move in reverse. - * - * See the section on bookmarks for an exception to this - * no-backing-up rule. - * - * #### Custom queries - * - * Sometimes it's necessary to further inspect an HTML tag than - * the query syntax here permits. In these cases one may further - * inspect the search results using the read-only functions - * provided by the processor or external state or variables. - * - * Example: - * - * // Paint up to the first five DIV or SPAN tags marked with the "jazzy" style. - * $remaining_count = 5; - * while ( $remaining_count > 0 && $tags->next_tag() ) { - * if ( - * ( 'DIV' === $tags->get_tag() || 'SPAN' === $tags->get_tag() ) && - * 'jazzy' === $tags->get_attribute( 'data-style' ) - * ) { - * $tags->add_class( 'theme-style-everest-jazz' ); - * $remaining_count--; - * } - * } - * - * `get_attribute()` will return `null` if the attribute wasn't present - * on the tag when it was called. It may return `""` (the empty string) - * in cases where the attribute was present but its value was empty. - * For boolean attributes, those whose name is present but no value is - * given, it will return `true` (the only way to set `false` for an - * attribute is to remove it). - * - * #### When matching fails - * - * When `next_tag()` returns `false` it could mean different things: - * - * - The requested tag wasn't found in the input document. - * - The input document ended in the middle of an HTML syntax element. - * - * When a document ends in the middle of a syntax element it will pause - * the processor. This is to make it possible in the future to extend the - * input document and proceed - an important requirement for chunked - * streaming parsing of a document. - * - * Example: - * - * $processor = new WP_HTML_Tag_Processor( 'This <div is="a" partial="token' ); - * false === $processor->next_tag(); - * - * If a special element (see next section) is encountered but no closing tag - * is found it will count as an incomplete tag. The parser will pause as if - * the opening tag were incomplete. - * - * Example: - * - * $processor = new WP_HTML_Tag_Processor( '<style>// there could be more styling to come' ); - * false === $processor->next_tag(); - * - * $processor = new WP_HTML_Tag_Processor( '<style>// this is everything</style><div>' ); - * true === $processor->next_tag( 'DIV' ); - * - * #### Special elements - * - * Some HTML elements are handled in a special way; their start and end tags - * act like a void tag. These are special because their contents can't contain - * HTML markup. Everything inside these elements is handled in a special way - * and content that _appears_ like HTML tags inside of them isn't. There can - * be no nesting in these elements. - * - * In the following list, "raw text" means that all of the content in the HTML - * until the matching closing tag is treated verbatim without any replacements - * and without any parsing. - * - * - IFRAME allows no content but requires a closing tag. - * - NOEMBED (deprecated) content is raw text. - * - NOFRAMES (deprecated) content is raw text. - * - SCRIPT content is plaintext apart from legacy rules allowing `</script>` inside an HTML comment. - * - STYLE content is raw text. - * - TITLE content is plain text but character references are decoded. - * - TEXTAREA content is plain text but character references are decoded. - * - XMP (deprecated) content is raw text. - * - * ### Modifying HTML attributes for a found tag - * - * Once you've found the start of an opening tag you can modify - * any number of the attributes on that tag. You can set a new - * value for an attribute, remove the entire attribute, or do - * nothing and move on to the next opening tag. - * - * Example: - * - * if ( $tags->next_tag( array( 'class_name' => 'wp-group-block' ) ) ) { - * $tags->set_attribute( 'title', 'This groups the contained content.' ); - * $tags->remove_attribute( 'data-test-id' ); - * } - * - * If `set_attribute()` is called for an existing attribute it will - * overwrite the existing value. Similarly, calling `remove_attribute()` - * for a non-existing attribute has no effect on the document. Both - * of these methods are safe to call without knowing if a given attribute - * exists beforehand. - * - * ### Modifying CSS classes for a found tag - * - * The tag processor treats the `class` attribute as a special case. - * Because it's a common operation to add or remove CSS classes, this - * interface adds helper methods to make that easier. - * - * As with attribute values, adding or removing CSS classes is a safe - * operation that doesn't require checking if the attribute or class - * exists before making changes. If removing the only class then the - * entire `class` attribute will be removed. - * - * Example: - * - * // from `<span>Yippee!</span>` - * // to `<span class="is-active">Yippee!</span>` - * $tags->add_class( 'is-active' ); - * - * // from `<span class="excited">Yippee!</span>` - * // to `<span class="excited is-active">Yippee!</span>` - * $tags->add_class( 'is-active' ); - * - * // from `<span class="is-active heavy-accent">Yippee!</span>` - * // to `<span class="is-active heavy-accent">Yippee!</span>` - * $tags->add_class( 'is-active' ); - * - * // from `<input type="text" class="is-active rugby not-disabled" length="24">` - * // to `<input type="text" class="is-active not-disabled" length="24"> - * $tags->remove_class( 'rugby' ); - * - * // from `<input type="text" class="rugby" length="24">` - * // to `<input type="text" length="24"> - * $tags->remove_class( 'rugby' ); - * - * // from `<input type="text" length="24">` - * // to `<input type="text" length="24"> - * $tags->remove_class( 'rugby' ); - * - * When class changes are enqueued but a direct change to `class` is made via - * `set_attribute` then the changes to `set_attribute` (or `remove_attribute`) - * will take precedence over those made through `add_class` and `remove_class`. - * - * ### Bookmarks - * - * While scanning through the input HTMl document it's possible to set - * a named bookmark when a particular tag is found. Later on, after - * continuing to scan other tags, it's possible to `seek` to one of - * the set bookmarks and then proceed again from that point forward. - * - * Because bookmarks create processing overhead one should avoid - * creating too many of them. As a rule, create only bookmarks - * of known string literal names; avoid creating "mark_{$index}" - * and so on. It's fine from a performance standpoint to create a - * bookmark and update it frequently, such as within a loop. - * - * $total_todos = 0; - * while ( $p->next_tag( array( 'tag_name' => 'UL', 'class_name' => 'todo' ) ) ) { - * $p->set_bookmark( 'list-start' ); - * while ( $p->next_tag( array( 'tag_closers' => 'visit' ) ) ) { - * if ( 'UL' === $p->get_tag() && $p->is_tag_closer() ) { - * $p->set_bookmark( 'list-end' ); - * $p->seek( 'list-start' ); - * $p->set_attribute( 'data-contained-todos', (string) $total_todos ); - * $total_todos = 0; - * $p->seek( 'list-end' ); - * break; - * } - * - * if ( 'LI' === $p->get_tag() && ! $p->is_tag_closer() ) { - * $total_todos++; - * } - * } - * } - * - * ## Tokens and finer-grained processing. - * - * It's possible to scan through every lexical token in the - * HTML document using the `next_token()` function. This - * alternative form takes no argument and provides no built-in - * query syntax. - * - * Example: - * - * $title = '(untitled)'; - * $text = ''; - * while ( $processor->next_token() ) { - * switch ( $processor->get_token_name() ) { - * case '#text': - * $text .= $processor->get_modifiable_text(); - * break; - * - * case 'BR': - * $text .= "\n"; - * break; - * - * case 'TITLE': - * $title = $processor->get_modifiable_text(); - * break; - * } - * } - * return trim( "# {$title}\n\n{$text}" ); - * - * ### Tokens and _modifiable text_. - * - * #### Special "atomic" HTML elements. - * - * Not all HTML elements are able to contain other elements inside of them. - * For instance, the contents inside a TITLE element are plaintext (except - * that character references like & will be decoded). This means that - * if the string `<img>` appears inside a TITLE element, then it's not an - * image tag, but rather it's text describing an image tag. Likewise, the - * contents of a SCRIPT or STYLE element are handled entirely separately in - * a browser than the contents of other elements because they represent a - * different language than HTML. - * - * For these elements the Tag Processor treats the entire sequence as one, - * from the opening tag, including its contents, through its closing tag. - * This means that the it's not possible to match the closing tag for a - * SCRIPT element unless it's unexpected; the Tag Processor already matched - * it when it found the opening tag. - * - * The inner contents of these elements are that element's _modifiable text_. - * - * The special elements are: - * - `SCRIPT` whose contents are treated as raw plaintext but supports a legacy - * style of including Javascript inside of HTML comments to avoid accidentally - * closing the SCRIPT from inside a Javascript string. E.g. `console.log( '</script>' )`. - * - `TITLE` and `TEXTAREA` whose contents are treated as plaintext and then any - * character references are decoded. E.g. `1 < 2 < 3` becomes `1 < 2 < 3`. - * - `IFRAME`, `NOSCRIPT`, `NOEMBED`, `NOFRAME`, `STYLE` whose contents are treated as - * raw plaintext and left as-is. E.g. `1 < 2 < 3` remains `1 < 2 < 3`. - * - * #### Other tokens with modifiable text. - * - * There are also non-elements which are void/self-closing in nature and contain - * modifiable text that is part of that individual syntax token itself. - * - * - `#text` nodes, whose entire token _is_ the modifiable text. - * - HTML comments and tokens that become comments due to some syntax error. The - * text for these tokens is the portion of the comment inside of the syntax. - * E.g. for `<!-- comment -->` the text is `" comment "` (note the spaces are included). - * - `CDATA` sections, whose text is the content inside of the section itself. E.g. for - * `<![CDATA[some content]]>` the text is `"some content"` (with restrictions [1]). - * - "Funky comments," which are a special case of invalid closing tags whose name is - * invalid. The text for these nodes is the text that a browser would transform into - * an HTML comment when parsing. E.g. for `</%post_author>` the text is `%post_author`. - * - `DOCTYPE` declarations like `<DOCTYPE html>` which have no closing tag. - * - XML Processing instruction nodes like `<?wp __( "Like" ); ?>` (with restrictions [2]). - * - The empty end tag `</>` which is ignored in the browser and DOM. - * - * [1]: There are no CDATA sections in HTML. When encountering `<![CDATA[`, everything - * until the next `>` becomes a bogus HTML comment, meaning there can be no CDATA - * section in an HTML document containing `>`. The Tag Processor will first find - * all valid and bogus HTML comments, and then if the comment _would_ have been a - * CDATA section _were they to exist_, it will indicate this as the type of comment. - * - * [2]: XML allows a broader range of characters in a processing instruction's target name - * and disallows "xml" as a name, since it's special. The Tag Processor only recognizes - * target names with an ASCII-representable subset of characters. It also exhibits the - * same constraint as with CDATA sections, in that `>` cannot exist within the token - * since Processing Instructions do no exist within HTML and their syntax transforms - * into a bogus comment in the DOM. - * - * ## Design and limitations - * - * The Tag Processor is designed to linearly scan HTML documents and tokenize - * HTML tags and their attributes. It's designed to do this as efficiently as - * possible without compromising parsing integrity. Therefore it will be - * slower than some methods of modifying HTML, such as those incorporating - * over-simplified PCRE patterns, but will not introduce the defects and - * failures that those methods bring in, which lead to broken page renders - * and often to security vulnerabilities. On the other hand, it will be faster - * than full-blown HTML parsers such as DOMDocument and use considerably - * less memory. It requires a negligible memory overhead, enough to consider - * it a zero-overhead system. - * - * The performance characteristics are maintained by avoiding tree construction - * and semantic cleanups which are specified in HTML5. Because of this, for - * example, it's not possible for the Tag Processor to associate any given - * opening tag with its corresponding closing tag, or to return the inner markup - * inside an element. Systems may be built on top of the Tag Processor to do - * this, but the Tag Processor is and should be constrained so it can remain an - * efficient, low-level, and reliable HTML scanner. - * - * The Tag Processor's design incorporates a "garbage-in-garbage-out" philosophy. - * HTML5 specifies that certain invalid content be transformed into different forms - * for display, such as removing null bytes from an input document and replacing - * invalid characters with the Unicode replacement character `U+FFFD` (visually "�"). - * Where errors or transformations exist within the HTML5 specification, the Tag Processor - * leaves those invalid inputs untouched, passing them through to the final browser - * to handle. While this implies that certain operations will be non-spec-compliant, - * such as reading the value of an attribute with invalid content, it also preserves a - * simplicity and efficiency for handling those error cases. - * - * Most operations within the Tag Processor are designed to minimize the difference - * between an input and output document for any given change. For example, the - * `add_class` and `remove_class` methods preserve whitespace and the class ordering - * within the `class` attribute; and when encountering tags with duplicated attributes, - * the Tag Processor will leave those invalid duplicate attributes where they are but - * update the proper attribute which the browser will read for parsing its value. An - * exception to this rule is that all attribute updates store their values as - * double-quoted strings, meaning that attributes on input with single-quoted or - * unquoted values will appear in the output with double-quotes. - * - * ### Scripting Flag - * - * The Tag Processor parses HTML with the "scripting flag" disabled. This means - * that it doesn't run any scripts while parsing the page. In a browser with - * JavaScript enabled, for example, the script can change the parse of the - * document as it loads. On the server, however, evaluating JavaScript is not - * only impractical, but also unwanted. - * - * Practically this means that the Tag Processor will descend into NOSCRIPT - * elements and process its child tags. Were the scripting flag enabled, such - * as in a typical browser, the contents of NOSCRIPT are skipped entirely. - * - * This allows the HTML API to process the content that will be presented in - * a browser when scripting is disabled, but it offers a different view of a - * page than most browser sessions will experience. E.g. the tags inside the - * NOSCRIPT disappear. - * - * ### Text Encoding - * - * The Tag Processor assumes that the input HTML document is encoded with a - * text encoding compatible with 7-bit ASCII's '<', '>', '&', ';', '/', '=', - * "'", '"', 'a' - 'z', 'A' - 'Z', and the whitespace characters ' ', tab, - * carriage-return, newline, and form-feed. - * - * In practice, this includes almost every single-byte encoding as well as - * UTF-8. Notably, however, it does not include UTF-16. If providing input - * that's incompatible, then convert the encoding beforehand. - * - * @since 6.2.0 - * @since 6.2.1 Fix: Support for various invalid comments; attribute updates are case-insensitive. - * @since 6.3.2 Fix: Skip HTML-like content inside rawtext elements such as STYLE. - * @since 6.5.0 Pauses processor when input ends in an incomplete syntax token. - * Introduces "special" elements which act like void elements, e.g. TITLE, STYLE. - * Allows scanning through all tokens and processing modifiable text, where applicable. - */ -class Gutenberg_HTML_Tag_Processor_6_5 { - /** - * The maximum number of bookmarks allowed to exist at - * any given time. - * - * @since 6.2.0 - * @var int - * - * @see WP_HTML_Tag_Processor::set_bookmark() - */ - const MAX_BOOKMARKS = 10; - - /** - * Maximum number of times seek() can be called. - * Prevents accidental infinite loops. - * - * @since 6.2.0 - * @var int - * - * @see WP_HTML_Tag_Processor::seek() - */ - const MAX_SEEK_OPS = 1000; - - /** - * The HTML document to parse. - * - * @since 6.2.0 - * @var string - */ - protected $html; - - /** - * The last query passed to next_tag(). - * - * @since 6.2.0 - * @var array|null - */ - private $last_query; - - /** - * The tag name this processor currently scans for. - * - * @since 6.2.0 - * @var string|null - */ - private $sought_tag_name; - - /** - * The CSS class name this processor currently scans for. - * - * @since 6.2.0 - * @var string|null - */ - private $sought_class_name; - - /** - * The match offset this processor currently scans for. - * - * @since 6.2.0 - * @var int|null - */ - private $sought_match_offset; - - /** - * Whether to visit tag closers, e.g. </div>, when walking an input document. - * - * @since 6.2.0 - * @var bool - */ - private $stop_on_tag_closers; - - /** - * Specifies mode of operation of the parser at any given time. - * - * | State | Meaning | - * | ----------------|----------------------------------------------------------------------| - * | *Ready* | The parser is ready to run. | - * | *Complete* | There is nothing left to parse. | - * | *Incomplete* | The HTML ended in the middle of a token; nothing more can be parsed. | - * | *Matched tag* | Found an HTML tag; it's possible to modify its attributes. | - * | *Text node* | Found a #text node; this is plaintext and modifiable. | - * | *CDATA node* | Found a CDATA section; this is modifiable. | - * | *Comment* | Found a comment or bogus comment; this is modifiable. | - * | *Presumptuous* | Found an empty tag closer: `</>`. | - * | *Funky comment* | Found a tag closer with an invalid tag name; this is modifiable. | - * - * @since 6.5.0 - * - * @see WP_HTML_Tag_Processor::STATE_READY - * @see WP_HTML_Tag_Processor::STATE_COMPLETE - * @see WP_HTML_Tag_Processor::STATE_INCOMPLETE_INPUT - * @see WP_HTML_Tag_Processor::STATE_MATCHED_TAG - * @see WP_HTML_Tag_Processor::STATE_TEXT_NODE - * @see WP_HTML_Tag_Processor::STATE_CDATA_NODE - * @see WP_HTML_Tag_Processor::STATE_COMMENT - * @see WP_HTML_Tag_Processor::STATE_DOCTYPE - * @see WP_HTML_Tag_Processor::STATE_PRESUMPTUOUS_TAG - * @see WP_HTML_Tag_Processor::STATE_FUNKY_COMMENT - * - * @var string - */ - protected $parser_state = self::STATE_READY; - - /** - * What kind of syntax token became an HTML comment. - * - * Since there are many ways in which HTML syntax can create an HTML comment, - * this indicates which of those caused it. This allows the Tag Processor to - * represent more from the original input document than would appear in the DOM. - * - * @since 6.5.0 - * - * @var string|null - */ - protected $comment_type = null; - - /** - * How many bytes from the original HTML document have been read and parsed. - * - * This value points to the latest byte offset in the input document which - * has been already parsed. It is the internal cursor for the Tag Processor - * and updates while scanning through the HTML tokens. - * - * @since 6.2.0 - * @var int - */ - private $bytes_already_parsed = 0; - - /** - * Byte offset in input document where current token starts. - * - * Example: - * - * <div id="test">... - * 01234 - * - token starts at 0 - * - * @since 6.5.0 - * - * @var int|null - */ - private $token_starts_at; - - /** - * Byte length of current token. - * - * Example: - * - * <div id="test">... - * 012345678901234 - * - token length is 14 - 0 = 14 - * - * a <!-- comment --> is a token. - * 0123456789 123456789 123456789 - * - token length is 17 - 2 = 15 - * - * @since 6.5.0 - * - * @var int|null - */ - private $token_length; - - /** - * Byte offset in input document where current tag name starts. - * - * Example: - * - * <div id="test">... - * 01234 - * - tag name starts at 1 - * - * @since 6.2.0 - * - * @var int|null - */ - private $tag_name_starts_at; - - /** - * Byte length of current tag name. - * - * Example: - * - * <div id="test">... - * 01234 - * --- tag name length is 3 - * - * @since 6.2.0 - * - * @var int|null - */ - private $tag_name_length; - - /** - * Byte offset into input document where current modifiable text starts. - * - * @since 6.5.0 - * - * @var int - */ - private $text_starts_at; - - /** - * Byte length of modifiable text. - * - * @since 6.5.0 - * - * @var string - */ - private $text_length; - - /** - * Whether the current tag is an opening tag, e.g. <div>, or a closing tag, e.g. </div>. - * - * @var bool - */ - private $is_closing_tag; - - /** - * Lazily-built index of attributes found within an HTML tag, keyed by the attribute name. - * - * Example: - * - * // Supposing the parser is working through this content - * // and stops after recognizing the `id` attribute. - * // <div id="test-4" class=outline title="data:text/plain;base64=asdk3nk1j3fo8"> - * // ^ parsing will continue from this point. - * $this->attributes = array( - * 'id' => new WP_HTML_Attribute_Token( 'id', 9, 6, 5, 11, false ) - * ); - * - * // When picking up parsing again, or when asking to find the - * // `class` attribute we will continue and add to this array. - * $this->attributes = array( - * 'id' => new WP_HTML_Attribute_Token( 'id', 9, 6, 5, 11, false ), - * 'class' => new WP_HTML_Attribute_Token( 'class', 23, 7, 17, 13, false ) - * ); - * - * // Note that only the `class` attribute value is stored in the index. - * // That's because it is the only value used by this class at the moment. - * - * @since 6.2.0 - * @var WP_HTML_Attribute_Token[] - */ - private $attributes = array(); - - /** - * Tracks spans of duplicate attributes on a given tag, used for removing - * all copies of an attribute when calling `remove_attribute()`. - * - * @since 6.3.2 - * - * @var (WP_HTML_Span[])[]|null - */ - private $duplicate_attributes = null; - - /** - * Which class names to add or remove from a tag. - * - * These are tracked separately from attribute updates because they are - * semantically distinct, whereas this interface exists for the common - * case of adding and removing class names while other attributes are - * generally modified as with DOM `setAttribute` calls. - * - * When modifying an HTML document these will eventually be collapsed - * into a single `set_attribute( 'class', $changes )` call. - * - * Example: - * - * // Add the `wp-block-group` class, remove the `wp-group` class. - * $classname_updates = array( - * // Indexed by a comparable class name. - * 'wp-block-group' => WP_HTML_Tag_Processor::ADD_CLASS, - * 'wp-group' => WP_HTML_Tag_Processor::REMOVE_CLASS - * ); - * - * @since 6.2.0 - * @var bool[] - */ - private $classname_updates = array(); - - /** - * Tracks a semantic location in the original HTML which - * shifts with updates as they are applied to the document. - * - * @since 6.2.0 - * @var WP_HTML_Span[] - */ - protected $bookmarks = array(); - - const ADD_CLASS = true; - const REMOVE_CLASS = false; - const SKIP_CLASS = null; - - /** - * Lexical replacements to apply to input HTML document. - * - * "Lexical" in this class refers to the part of this class which - * operates on pure text _as text_ and not as HTML. There's a line - * between the public interface, with HTML-semantic methods like - * `set_attribute` and `add_class`, and an internal state that tracks - * text offsets in the input document. - * - * When higher-level HTML methods are called, those have to transform their - * operations (such as setting an attribute's value) into text diffing - * operations (such as replacing the sub-string from indices A to B with - * some given new string). These text-diffing operations are the lexical - * updates. - * - * As new higher-level methods are added they need to collapse their - * operations into these lower-level lexical updates since that's the - * Tag Processor's internal language of change. Any code which creates - * these lexical updates must ensure that they do not cross HTML syntax - * boundaries, however, so these should never be exposed outside of this - * class or any classes which intentionally expand its functionality. - * - * These are enqueued while editing the document instead of being immediately - * applied to avoid processing overhead, string allocations, and string - * copies when applying many updates to a single document. - * - * Example: - * - * // Replace an attribute stored with a new value, indices - * // sourced from the lazily-parsed HTML recognizer. - * $start = $attributes['src']->start; - * $length = $attributes['src']->length; - * $modifications[] = new WP_HTML_Text_Replacement( $start, $length, $new_value ); - * - * // Correspondingly, something like this will appear in this array. - * $lexical_updates = array( - * WP_HTML_Text_Replacement( 14, 28, 'https://my-site.my-domain/wp-content/uploads/2014/08/kittens.jpg' ) - * ); - * - * @since 6.2.0 - * @var WP_HTML_Text_Replacement[] - */ - protected $lexical_updates = array(); - - /** - * Tracks and limits `seek()` calls to prevent accidental infinite loops. - * - * @since 6.2.0 - * @var int - * - * @see WP_HTML_Tag_Processor::seek() - */ - protected $seek_count = 0; - - /** - * Constructor. - * - * @since 6.2.0 - * - * @param string $html HTML to process. - */ - public function __construct( $html ) { - $this->html = $html; - } - - /** - * Finds the next tag matching the $query. - * - * @since 6.2.0 - * @since 6.5.0 No longer processes incomplete tokens at end of document; pauses the processor at start of token. - * - * @param array|string|null $query { - * Optional. Which tag name to find, having which class, etc. Default is to find any tag. - * - * @type string|null $tag_name Which tag to find, or `null` for "any tag." - * @type int|null $match_offset Find the Nth tag matching all search criteria. - * 1 for "first" tag, 3 for "third," etc. - * Defaults to first tag. - * @type string|null $class_name Tag must contain this whole class name to match. - * @type string|null $tag_closers "visit" or "skip": whether to stop on tag closers, e.g. </div>. - * } - * @return bool Whether a tag was matched. - */ - public function next_tag( $query = null ) { - $this->parse_query( $query ); - $already_found = 0; - - do { - if ( false === $this->next_token() ) { - return false; - } - - if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { - continue; - } - - if ( $this->matches() ) { - ++$already_found; - } - } while ( $already_found < $this->sought_match_offset ); - - return true; - } - - /** - * Finds the next token in the HTML document. - * - * An HTML document can be viewed as a stream of tokens, - * where tokens are things like HTML tags, HTML comments, - * text nodes, etc. This method finds the next token in - * the HTML document and returns whether it found one. - * - * If it starts parsing a token and reaches the end of the - * document then it will seek to the start of the last - * token and pause, returning `false` to indicate that it - * failed to find a complete token. - * - * Possible token types, based on the HTML specification: - * - * - an HTML tag, whether opening, closing, or void. - * - a text node - the plaintext inside tags. - * - an HTML comment. - * - a DOCTYPE declaration. - * - a processing instruction, e.g. `<?xml version="1.0" ?>`. - * - * The Tag Processor currently only supports the tag token. - * - * @since 6.5.0 - * - * @return bool Whether a token was parsed. - */ - public function next_token() { - return $this->base_class_next_token(); - } - - /** - * Internal method which finds the next token in the HTML document. - * - * This method is a protected internal function which implements the logic for - * finding the next token in a document. It exists so that the parser can update - * its state without affecting the location of the cursor in the document and - * without triggering subclass methods for things like `next_token()`, e.g. when - * applying patches before searching for the next token. - * - * @since 6.5.0 - * - * @access private - * - * @return bool Whether a token was parsed. - */ - private function base_class_next_token() { - $was_at = $this->bytes_already_parsed; - $this->after_tag(); - - // Don't proceed if there's nothing more to scan. - if ( - self::STATE_COMPLETE === $this->parser_state || - self::STATE_INCOMPLETE_INPUT === $this->parser_state - ) { - return false; - } - - /* - * The next step in the parsing loop determines the parsing state; - * clear it so that state doesn't linger from the previous step. - */ - $this->parser_state = self::STATE_READY; - - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - $this->parser_state = self::STATE_COMPLETE; - return false; - } - - // Find the next tag if it exists. - if ( false === $this->parse_next_tag() ) { - if ( self::STATE_INCOMPLETE_INPUT === $this->parser_state ) { - $this->bytes_already_parsed = $was_at; - } - - return false; - } - - /* - * For legacy reasons the rest of this function handles tags and their - * attributes. If the processor has reached the end of the document - * or if it matched any other token then it should return here to avoid - * attempting to process tag-specific syntax. - */ - if ( - self::STATE_INCOMPLETE_INPUT !== $this->parser_state && - self::STATE_COMPLETE !== $this->parser_state && - self::STATE_MATCHED_TAG !== $this->parser_state - ) { - return true; - } - - // Parse all of its attributes. - while ( $this->parse_next_attribute() ) { - continue; - } - - // Ensure that the tag closes before the end of the document. - if ( - self::STATE_INCOMPLETE_INPUT === $this->parser_state || - $this->bytes_already_parsed >= strlen( $this->html ) - ) { - // Does this appropriately clear state (parsed attributes)? - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - $this->bytes_already_parsed = $was_at; - - return false; - } - - $tag_ends_at = strpos( $this->html, '>', $this->bytes_already_parsed ); - if ( false === $tag_ends_at ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - $this->bytes_already_parsed = $was_at; - - return false; - } - $this->parser_state = self::STATE_MATCHED_TAG; - $this->token_length = $tag_ends_at - $this->token_starts_at; - $this->bytes_already_parsed = $tag_ends_at + 1; - - /* - * For non-DATA sections which might contain text that looks like HTML tags but - * isn't, scan with the appropriate alternative mode. Looking at the first letter - * of the tag name as a pre-check avoids a string allocation when it's not needed. - */ - $t = $this->html[ $this->tag_name_starts_at ]; - if ( - $this->is_closing_tag || - ! ( - 'i' === $t || 'I' === $t || - 'n' === $t || 'N' === $t || - 's' === $t || 'S' === $t || - 't' === $t || 'T' === $t || - 'x' === $t || 'X' === $t - ) - ) { - return true; - } - - $tag_name = $this->get_tag(); - - /* - * Preserve the opening tag pointers, as these will be overwritten - * when finding the closing tag. They will be reset after finding - * the closing to tag to point to the opening of the special atomic - * tag sequence. - */ - $tag_name_starts_at = $this->tag_name_starts_at; - $tag_name_length = $this->tag_name_length; - $tag_ends_at = $this->token_starts_at + $this->token_length; - $attributes = $this->attributes; - $duplicate_attributes = $this->duplicate_attributes; - - // Find the closing tag if necessary. - $found_closer = false; - switch ( $tag_name ) { - case 'SCRIPT': - $found_closer = $this->skip_script_data(); - break; - - case 'TEXTAREA': - case 'TITLE': - $found_closer = $this->skip_rcdata( $tag_name ); - break; - - /* - * In the browser this list would include the NOSCRIPT element, - * but the Tag Processor is an environment with the scripting - * flag disabled, meaning that it needs to descend into the - * NOSCRIPT element to be able to properly process what will be - * sent to a browser. - * - * Note that this rule makes HTML5 syntax incompatible with XML, - * because the parsing of this token depends on client application. - * The NOSCRIPT element cannot be represented in the XHTML syntax. - */ - case 'IFRAME': - case 'NOEMBED': - case 'NOFRAMES': - case 'STYLE': - case 'XMP': - $found_closer = $this->skip_rawtext( $tag_name ); - break; - - // No other tags should be treated in their entirety here. - default: - return true; - } - - if ( ! $found_closer ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - $this->bytes_already_parsed = $was_at; - return false; - } - - /* - * The values here look like they reference the opening tag but they reference - * the closing tag instead. This is why the opening tag values were stored - * above in a variable. It reads confusingly here, but that's because the - * functions that skip the contents have moved all the internal cursors past - * the inner content of the tag. - */ - $this->token_starts_at = $was_at; - $this->token_length = $this->bytes_already_parsed - $this->token_starts_at; - $this->text_starts_at = $tag_ends_at + 1; - $this->text_length = $this->tag_name_starts_at - $this->text_starts_at; - $this->tag_name_starts_at = $tag_name_starts_at; - $this->tag_name_length = $tag_name_length; - $this->attributes = $attributes; - $this->duplicate_attributes = $duplicate_attributes; - - return true; - } - - /** - * Whether the processor paused because the input HTML document ended - * in the middle of a syntax element, such as in the middle of a tag. - * - * Example: - * - * $processor = new WP_HTML_Tag_Processor( '<input type="text" value="Th' ); - * false === $processor->get_next_tag(); - * true === $processor->paused_at_incomplete_token(); - * - * @since 6.5.0 - * - * @return bool Whether the parse paused at the start of an incomplete token. - */ - public function paused_at_incomplete_token() { - return self::STATE_INCOMPLETE_INPUT === $this->parser_state; - } - - /** - * Generator for a foreach loop to step through each class name for the matched tag. - * - * This generator function is designed to be used inside a "foreach" loop. - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( "<div class='free <egg<\tlang-en'>" ); - * $p->next_tag(); - * foreach ( $p->class_list() as $class_name ) { - * echo "{$class_name} "; - * } - * // Outputs: "free <egg> lang-en " - * - * @since 6.4.0 - */ - public function class_list() { - if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { - return; - } - - /** @var string $class contains the string value of the class attribute, with character references decoded. */ - $class = $this->get_attribute( 'class' ); - - if ( ! is_string( $class ) ) { - return; - } - - $seen = array(); - - $at = 0; - while ( $at < strlen( $class ) ) { - // Skip past any initial boundary characters. - $at += strspn( $class, " \t\f\r\n", $at ); - if ( $at >= strlen( $class ) ) { - return; - } - - // Find the byte length until the next boundary. - $length = strcspn( $class, " \t\f\r\n", $at ); - if ( 0 === $length ) { - return; - } - - /* - * CSS class names are case-insensitive in the ASCII range. - * - * @see https://www.w3.org/TR/CSS2/syndata.html#x1 - */ - $name = strtolower( substr( $class, $at, $length ) ); - $at += $length; - - /* - * It's expected that the number of class names for a given tag is relatively small. - * Given this, it is probably faster overall to scan an array for a value rather - * than to use the class name as a key and check if it's a key of $seen. - */ - if ( in_array( $name, $seen, true ) ) { - continue; - } - - $seen[] = $name; - yield $name; - } - } - - - /** - * Returns if a matched tag contains the given ASCII case-insensitive class name. - * - * @since 6.4.0 - * - * @param string $wanted_class Look for this CSS class name, ASCII case-insensitive. - * @return bool|null Whether the matched tag contains the given class name, or null if not matched. - */ - public function has_class( $wanted_class ) { - if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { - return null; - } - - $wanted_class = strtolower( $wanted_class ); - - foreach ( $this->class_list() as $class_name ) { - if ( $class_name === $wanted_class ) { - return true; - } - } - - return false; - } - - - /** - * Sets a bookmark in the HTML document. - * - * Bookmarks represent specific places or tokens in the HTML - * document, such as a tag opener or closer. When applying - * edits to a document, such as setting an attribute, the - * text offsets of that token may shift; the bookmark is - * kept updated with those shifts and remains stable unless - * the entire span of text in which the token sits is removed. - * - * Release bookmarks when they are no longer needed. - * - * Example: - * - * <main><h2>Surprising fact you may not know!</h2></main> - * ^ ^ - * \-|-- this `H2` opener bookmark tracks the token - * - * <main class="clickbait"><h2>Surprising fact you may no… - * ^ ^ - * \-|-- it shifts with edits - * - * Bookmarks provide the ability to seek to a previously-scanned - * place in the HTML document. This avoids the need to re-scan - * the entire document. - * - * Example: - * - * <ul><li>One</li><li>Two</li><li>Three</li></ul> - * ^^^^ - * want to note this last item - * - * $p = new WP_HTML_Tag_Processor( $html ); - * $in_list = false; - * while ( $p->next_tag( array( 'tag_closers' => $in_list ? 'visit' : 'skip' ) ) ) { - * if ( 'UL' === $p->get_tag() ) { - * if ( $p->is_tag_closer() ) { - * $in_list = false; - * $p->set_bookmark( 'resume' ); - * if ( $p->seek( 'last-li' ) ) { - * $p->add_class( 'last-li' ); - * } - * $p->seek( 'resume' ); - * $p->release_bookmark( 'last-li' ); - * $p->release_bookmark( 'resume' ); - * } else { - * $in_list = true; - * } - * } - * - * if ( 'LI' === $p->get_tag() ) { - * $p->set_bookmark( 'last-li' ); - * } - * } - * - * Bookmarks intentionally hide the internal string offsets - * to which they refer. They are maintained internally as - * updates are applied to the HTML document and therefore - * retain their "position" - the location to which they - * originally pointed. The inability to use bookmarks with - * functions like `substr` is therefore intentional to guard - * against accidentally breaking the HTML. - * - * Because bookmarks allocate memory and require processing - * for every applied update, they are limited and require - * a name. They should not be created with programmatically-made - * names, such as "li_{$index}" with some loop. As a general - * rule they should only be created with string-literal names - * like "start-of-section" or "last-paragraph". - * - * Bookmarks are a powerful tool to enable complicated behavior. - * Consider double-checking that you need this tool if you are - * reaching for it, as inappropriate use could lead to broken - * HTML structure or unwanted processing overhead. - * - * @since 6.2.0 - * - * @param string $name Identifies this particular bookmark. - * @return bool Whether the bookmark was successfully created. - */ - public function set_bookmark( $name ) { - // It only makes sense to set a bookmark if the parser has paused on a concrete token. - if ( - self::STATE_COMPLETE === $this->parser_state || - self::STATE_INCOMPLETE_INPUT === $this->parser_state - ) { - return false; - } - - if ( ! array_key_exists( $name, $this->bookmarks ) && count( $this->bookmarks ) >= static::MAX_BOOKMARKS ) { - _doing_it_wrong( - __METHOD__, - __( 'Too many bookmarks: cannot create any more.' ), - '6.2.0' - ); - return false; - } - - $this->bookmarks[ $name ] = new Gutenberg_HTML_Span_6_5( $this->token_starts_at, $this->token_length ); - - return true; - } - - - /** - * Removes a bookmark that is no longer needed. - * - * Releasing a bookmark frees up the small - * performance overhead it requires. - * - * @param string $name Name of the bookmark to remove. - * @return bool Whether the bookmark already existed before removal. - */ - public function release_bookmark( $name ) { - if ( ! array_key_exists( $name, $this->bookmarks ) ) { - return false; - } - - unset( $this->bookmarks[ $name ] ); - - return true; - } - - /** - * Skips contents of generic rawtext elements. - * - * @since 6.3.2 - * - * @see https://html.spec.whatwg.org/#generic-raw-text-element-parsing-algorithm - * - * @param string $tag_name The uppercase tag name which will close the RAWTEXT region. - * @return bool Whether an end to the RAWTEXT region was found before the end of the document. - */ - private function skip_rawtext( $tag_name ) { - /* - * These two functions distinguish themselves on whether character references are - * decoded, and since functionality to read the inner markup isn't supported, it's - * not necessary to implement these two functions separately. - */ - return $this->skip_rcdata( $tag_name ); - } - - /** - * Skips contents of RCDATA elements, namely title and textarea tags. - * - * @since 6.2.0 - * - * @see https://html.spec.whatwg.org/multipage/parsing.html#rcdata-state - * - * @param string $tag_name The uppercase tag name which will close the RCDATA region. - * @return bool Whether an end to the RCDATA region was found before the end of the document. - */ - private function skip_rcdata( $tag_name ) { - $html = $this->html; - $doc_length = strlen( $html ); - $tag_length = strlen( $tag_name ); - - $at = $this->bytes_already_parsed; - - while ( false !== $at && $at < $doc_length ) { - $at = strpos( $this->html, '</', $at ); - $this->tag_name_starts_at = $at; - - // Fail if there is no possible tag closer. - if ( false === $at || ( $at + $tag_length ) >= $doc_length ) { - return false; - } - - $at += 2; - - /* - * Find a case-insensitive match to the tag name. - * - * Because tag names are limited to US-ASCII there is no - * need to perform any kind of Unicode normalization when - * comparing; any character which could be impacted by such - * normalization could not be part of a tag name. - */ - for ( $i = 0; $i < $tag_length; $i++ ) { - $tag_char = $tag_name[ $i ]; - $html_char = $html[ $at + $i ]; - - if ( $html_char !== $tag_char && strtoupper( $html_char ) !== $tag_char ) { - $at += $i; - continue 2; - } - } - - $at += $tag_length; - $this->bytes_already_parsed = $at; - - if ( $at >= strlen( $html ) ) { - return false; - } - - /* - * Ensure that the tag name terminates to avoid matching on - * substrings of a longer tag name. For example, the sequence - * "</textarearug" should not match for "</textarea" even - * though "textarea" is found within the text. - */ - $c = $html[ $at ]; - if ( ' ' !== $c && "\t" !== $c && "\r" !== $c && "\n" !== $c && '/' !== $c && '>' !== $c ) { - continue; - } - - while ( $this->parse_next_attribute() ) { - continue; - } - - $at = $this->bytes_already_parsed; - if ( $at >= strlen( $this->html ) ) { - return false; - } - - if ( '>' === $html[ $at ] ) { - $this->bytes_already_parsed = $at + 1; - return true; - } - - if ( $at + 1 >= strlen( $this->html ) ) { - return false; - } - - if ( '/' === $html[ $at ] && '>' === $html[ $at + 1 ] ) { - $this->bytes_already_parsed = $at + 2; - return true; - } - } - - return false; - } - - /** - * Skips contents of script tags. - * - * @since 6.2.0 - * - * @return bool Whether the script tag was closed before the end of the document. - */ - private function skip_script_data() { - $state = 'unescaped'; - $html = $this->html; - $doc_length = strlen( $html ); - $at = $this->bytes_already_parsed; - - while ( false !== $at && $at < $doc_length ) { - $at += strcspn( $html, '-<', $at ); - - /* - * For all script states a "-->" transitions - * back into the normal unescaped script mode, - * even if that's the current state. - */ - if ( - $at + 2 < $doc_length && - '-' === $html[ $at ] && - '-' === $html[ $at + 1 ] && - '>' === $html[ $at + 2 ] - ) { - $at += 3; - $state = 'unescaped'; - continue; - } - - // Everything of interest past here starts with "<". - if ( $at + 1 >= $doc_length || '<' !== $html[ $at++ ] ) { - continue; - } - - /* - * Unlike with "-->", the "<!--" only transitions - * into the escaped mode if not already there. - * - * Inside the escaped modes it will be ignored; and - * should never break out of the double-escaped - * mode and back into the escaped mode. - * - * While this requires a mode change, it does not - * impact the parsing otherwise, so continue - * parsing after updating the state. - */ - if ( - $at + 2 < $doc_length && - '!' === $html[ $at ] && - '-' === $html[ $at + 1 ] && - '-' === $html[ $at + 2 ] - ) { - $at += 3; - $state = 'unescaped' === $state ? 'escaped' : $state; - continue; - } - - if ( '/' === $html[ $at ] ) { - $closer_potentially_starts_at = $at - 1; - $is_closing = true; - ++$at; - } else { - $is_closing = false; - } - - /* - * At this point the only remaining state-changes occur with the - * <script> and </script> tags; unless one of these appears next, - * proceed scanning to the next potential token in the text. - */ - if ( ! ( - $at + 6 < $doc_length && - ( 's' === $html[ $at ] || 'S' === $html[ $at ] ) && - ( 'c' === $html[ $at + 1 ] || 'C' === $html[ $at + 1 ] ) && - ( 'r' === $html[ $at + 2 ] || 'R' === $html[ $at + 2 ] ) && - ( 'i' === $html[ $at + 3 ] || 'I' === $html[ $at + 3 ] ) && - ( 'p' === $html[ $at + 4 ] || 'P' === $html[ $at + 4 ] ) && - ( 't' === $html[ $at + 5 ] || 'T' === $html[ $at + 5 ] ) - ) ) { - ++$at; - continue; - } - - /* - * Ensure that the script tag terminates to avoid matching on - * substrings of a non-match. For example, the sequence - * "<script123" should not end a script region even though - * "<script" is found within the text. - */ - if ( $at + 6 >= $doc_length ) { - continue; - } - $at += 6; - $c = $html[ $at ]; - if ( ' ' !== $c && "\t" !== $c && "\r" !== $c && "\n" !== $c && '/' !== $c && '>' !== $c ) { - ++$at; - continue; - } - - if ( 'escaped' === $state && ! $is_closing ) { - $state = 'double-escaped'; - continue; - } - - if ( 'double-escaped' === $state && $is_closing ) { - $state = 'escaped'; - continue; - } - - if ( $is_closing ) { - $this->bytes_already_parsed = $closer_potentially_starts_at; - $this->tag_name_starts_at = $closer_potentially_starts_at; - if ( $this->bytes_already_parsed >= $doc_length ) { - return false; - } - - while ( $this->parse_next_attribute() ) { - continue; - } - - if ( $this->bytes_already_parsed >= $doc_length ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - if ( '>' === $html[ $this->bytes_already_parsed ] ) { - ++$this->bytes_already_parsed; - return true; - } - } - - ++$at; - } - - return false; - } - - /** - * Parses the next tag. - * - * This will find and start parsing the next tag, including - * the opening `<`, the potential closer `/`, and the tag - * name. It does not parse the attributes or scan to the - * closing `>`; these are left for other methods. - * - * @since 6.2.0 - * @since 6.2.1 Support abruptly-closed comments, invalid-tag-closer-comments, and empty elements. - * - * @return bool Whether a tag was found before the end of the document. - */ - private function parse_next_tag() { - $this->after_tag(); - - $html = $this->html; - $doc_length = strlen( $html ); - $was_at = $this->bytes_already_parsed; - $at = $was_at; - - while ( false !== $at && $at < $doc_length ) { - $at = strpos( $html, '<', $at ); - - /* - * This does not imply an incomplete parse; it indicates that there - * can be nothing left in the document other than a #text node. - */ - if ( false === $at ) { - $this->parser_state = self::STATE_TEXT_NODE; - $this->token_starts_at = $was_at; - $this->token_length = strlen( $html ) - $was_at; - $this->text_starts_at = $was_at; - $this->text_length = $this->token_length; - $this->bytes_already_parsed = strlen( $html ); - return true; - } - - if ( $at > $was_at ) { - /* - * A "<" normally starts a new HTML tag or syntax token, but in cases where the - * following character can't produce a valid token, the "<" is instead treated - * as plaintext and the parser should skip over it. This avoids a problem when - * following earlier practices of typing emoji with text, e.g. "<3". This - * should be a heart, not a tag. It's supposed to be rendered, not hidden. - * - * At this point the parser checks if this is one of those cases and if it is - * will continue searching for the next "<" in search of a token boundary. - * - * @see https://html.spec.whatwg.org/#tag-open-state - */ - if ( strlen( $html ) > $at + 1 ) { - $next_character = $html[ $at + 1 ]; - $at_another_node = ( - '!' === $next_character || - '/' === $next_character || - '?' === $next_character || - ( 'A' <= $next_character && $next_character <= 'Z' ) || - ( 'a' <= $next_character && $next_character <= 'z' ) - ); - if ( ! $at_another_node ) { - ++$at; - continue; - } - } - - $this->parser_state = self::STATE_TEXT_NODE; - $this->token_starts_at = $was_at; - $this->token_length = $at - $was_at; - $this->text_starts_at = $was_at; - $this->text_length = $this->token_length; - $this->bytes_already_parsed = $at; - return true; - } - - $this->token_starts_at = $at; - - if ( $at + 1 < $doc_length && '/' === $this->html[ $at + 1 ] ) { - $this->is_closing_tag = true; - ++$at; - } else { - $this->is_closing_tag = false; - } - - /* - * HTML tag names must start with [a-zA-Z] otherwise they are not tags. - * For example, "<3" is rendered as text, not a tag opener. If at least - * one letter follows the "<" then _it is_ a tag, but if the following - * character is anything else it _is not a tag_. - * - * It's not uncommon to find non-tags starting with `<` in an HTML - * document, so it's good for performance to make this pre-check before - * continuing to attempt to parse a tag name. - * - * Reference: - * * https://html.spec.whatwg.org/multipage/parsing.html#data-state - * * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state - */ - $tag_name_prefix_length = strspn( $html, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', $at + 1 ); - if ( $tag_name_prefix_length > 0 ) { - ++$at; - $this->parser_state = self::STATE_MATCHED_TAG; - $this->tag_name_starts_at = $at; - $this->tag_name_length = $tag_name_prefix_length + strcspn( $html, " \t\f\r\n/>", $at + $tag_name_prefix_length ); - $this->bytes_already_parsed = $at + $this->tag_name_length; - return true; - } - - /* - * Abort if no tag is found before the end of - * the document. There is nothing left to parse. - */ - if ( $at + 1 >= $doc_length ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - /* - * `<!` transitions to markup declaration open state - * https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state - */ - if ( '!' === $html[ $at + 1 ] ) { - /* - * `<!--` transitions to a comment state – apply further comment rules. - * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state - */ - if ( - $doc_length > $at + 3 && - '-' === $html[ $at + 2 ] && - '-' === $html[ $at + 3 ] - ) { - $closer_at = $at + 4; - // If it's not possible to close the comment then there is nothing more to scan. - if ( $doc_length <= $closer_at ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - // Abruptly-closed empty comments are a sequence of dashes followed by `>`. - $span_of_dashes = strspn( $html, '-', $closer_at ); - if ( '>' === $html[ $closer_at + $span_of_dashes ] ) { - /* - * @todo When implementing `set_modifiable_text()` ensure that updates to this token - * don't break the syntax for short comments, e.g. `<!--->`. Unlike other comment - * and bogus comment syntax, these leave no clear insertion point for text and - * they need to be modified specially in order to contain text. E.g. to store - * `?` as the modifiable text, the `<!--->` needs to become `<!--?-->`, which - * involves inserting an additional `-` into the token after the modifiable text. - */ - $this->parser_state = self::STATE_COMMENT; - $this->comment_type = self::COMMENT_AS_ABRUPTLY_CLOSED_COMMENT; - $this->token_length = $closer_at + $span_of_dashes + 1 - $this->token_starts_at; - - // Only provide modifiable text if the token is long enough to contain it. - if ( $span_of_dashes >= 2 ) { - $this->comment_type = self::COMMENT_AS_HTML_COMMENT; - $this->text_starts_at = $this->token_starts_at + 4; - $this->text_length = $span_of_dashes - 2; - } - - $this->bytes_already_parsed = $closer_at + $span_of_dashes + 1; - return true; - } - - /* - * Comments may be closed by either a --> or an invalid --!>. - * The first occurrence closes the comment. - * - * See https://html.spec.whatwg.org/#parse-error-incorrectly-closed-comment - */ - --$closer_at; // Pre-increment inside condition below reduces risk of accidental infinite looping. - while ( ++$closer_at < $doc_length ) { - $closer_at = strpos( $html, '--', $closer_at ); - if ( false === $closer_at ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - if ( $closer_at + 2 < $doc_length && '>' === $html[ $closer_at + 2 ] ) { - $this->parser_state = self::STATE_COMMENT; - $this->comment_type = self::COMMENT_AS_HTML_COMMENT; - $this->token_length = $closer_at + 3 - $this->token_starts_at; - $this->text_starts_at = $this->token_starts_at + 4; - $this->text_length = $closer_at - $this->text_starts_at; - $this->bytes_already_parsed = $closer_at + 3; - return true; - } - - if ( - $closer_at + 3 < $doc_length && - '!' === $html[ $closer_at + 2 ] && - '>' === $html[ $closer_at + 3 ] - ) { - $this->parser_state = self::STATE_COMMENT; - $this->comment_type = self::COMMENT_AS_HTML_COMMENT; - $this->token_length = $closer_at + 4 - $this->token_starts_at; - $this->text_starts_at = $this->token_starts_at + 4; - $this->text_length = $closer_at - $this->text_starts_at; - $this->bytes_already_parsed = $closer_at + 4; - return true; - } - } - } - - /* - * `<!DOCTYPE` transitions to DOCTYPE state – skip to the nearest > - * These are ASCII-case-insensitive. - * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state - */ - if ( - $doc_length > $at + 8 && - ( 'D' === $html[ $at + 2 ] || 'd' === $html[ $at + 2 ] ) && - ( 'O' === $html[ $at + 3 ] || 'o' === $html[ $at + 3 ] ) && - ( 'C' === $html[ $at + 4 ] || 'c' === $html[ $at + 4 ] ) && - ( 'T' === $html[ $at + 5 ] || 't' === $html[ $at + 5 ] ) && - ( 'Y' === $html[ $at + 6 ] || 'y' === $html[ $at + 6 ] ) && - ( 'P' === $html[ $at + 7 ] || 'p' === $html[ $at + 7 ] ) && - ( 'E' === $html[ $at + 8 ] || 'e' === $html[ $at + 8 ] ) - ) { - $closer_at = strpos( $html, '>', $at + 9 ); - if ( false === $closer_at ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - $this->parser_state = self::STATE_DOCTYPE; - $this->token_length = $closer_at + 1 - $this->token_starts_at; - $this->text_starts_at = $this->token_starts_at + 9; - $this->text_length = $closer_at - $this->text_starts_at; - $this->bytes_already_parsed = $closer_at + 1; - return true; - } - - /* - * Anything else here is an incorrectly-opened comment and transitions - * to the bogus comment state - skip to the nearest >. If no closer is - * found then the HTML was truncated inside the markup declaration. - */ - $closer_at = strpos( $html, '>', $at + 1 ); - if ( false === $closer_at ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - $this->parser_state = self::STATE_COMMENT; - $this->comment_type = self::COMMENT_AS_INVALID_HTML; - $this->token_length = $closer_at + 1 - $this->token_starts_at; - $this->text_starts_at = $this->token_starts_at + 2; - $this->text_length = $closer_at - $this->text_starts_at; - $this->bytes_already_parsed = $closer_at + 1; - - /* - * Identify nodes that would be CDATA if HTML had CDATA sections. - * - * This section must occur after identifying the bogus comment end - * because in an HTML parser it will span to the nearest `>`, even - * if there's no `]]>` as would be required in an XML document. It - * is therefore not possible to parse a CDATA section containing - * a `>` in the HTML syntax. - * - * Inside foreign elements there is a discrepancy between browsers - * and the specification on this. - * - * @todo Track whether the Tag Processor is inside a foreign element - * and require the proper closing `]]>` in those cases. - */ - if ( - $this->token_length >= 10 && - '[' === $html[ $this->token_starts_at + 2 ] && - 'C' === $html[ $this->token_starts_at + 3 ] && - 'D' === $html[ $this->token_starts_at + 4 ] && - 'A' === $html[ $this->token_starts_at + 5 ] && - 'T' === $html[ $this->token_starts_at + 6 ] && - 'A' === $html[ $this->token_starts_at + 7 ] && - '[' === $html[ $this->token_starts_at + 8 ] && - ']' === $html[ $closer_at - 1 ] && - ']' === $html[ $closer_at - 2 ] - ) { - $this->parser_state = self::STATE_COMMENT; - $this->comment_type = self::COMMENT_AS_CDATA_LOOKALIKE; - $this->text_starts_at += 7; - $this->text_length -= 9; - } - - return true; - } - - /* - * </> is a missing end tag name, which is ignored. - * - * This was also known as the "presumptuous empty tag" - * in early discussions as it was proposed to close - * the nearest previous opening tag. - * - * See https://html.spec.whatwg.org/#parse-error-missing-end-tag-name - */ - if ( '>' === $html[ $at + 1 ] ) { - $this->parser_state = self::STATE_PRESUMPTUOUS_TAG; - $this->token_length = $at + 2 - $this->token_starts_at; - $this->bytes_already_parsed = $at + 2; - return true; - } - - /* - * `<?` transitions to a bogus comment state – skip to the nearest > - * See https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state - */ - if ( '?' === $html[ $at + 1 ] ) { - $closer_at = strpos( $html, '>', $at + 2 ); - if ( false === $closer_at ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - $this->parser_state = self::STATE_COMMENT; - $this->comment_type = self::COMMENT_AS_INVALID_HTML; - $this->token_length = $closer_at + 1 - $this->token_starts_at; - $this->text_starts_at = $this->token_starts_at + 2; - $this->text_length = $closer_at - $this->text_starts_at; - $this->bytes_already_parsed = $closer_at + 1; - - /* - * Identify a Processing Instruction node were HTML to have them. - * - * This section must occur after identifying the bogus comment end - * because in an HTML parser it will span to the nearest `>`, even - * if there's no `?>` as would be required in an XML document. It - * is therefore not possible to parse a Processing Instruction node - * containing a `>` in the HTML syntax. - * - * XML allows for more target names, but this code only identifies - * those with ASCII-representable target names. This means that it - * may identify some Processing Instruction nodes as bogus comments, - * but it will not misinterpret the HTML structure. By limiting the - * identification to these target names the Tag Processor can avoid - * the need to start parsing UTF-8 sequences. - * - * > NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | - * [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | - * [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | - * [#x10000-#xEFFFF] - * > NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] - * - * @see https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-PITarget - */ - if ( $this->token_length >= 5 && '?' === $html[ $closer_at - 1 ] ) { - $comment_text = substr( $html, $this->token_starts_at + 2, $this->token_length - 4 ); - $pi_target_length = strspn( $comment_text, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:_' ); - - if ( 0 < $pi_target_length ) { - $pi_target_length += strspn( $comment_text, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:_-.', $pi_target_length ); - - $this->comment_type = self::COMMENT_AS_PI_NODE_LOOKALIKE; - $this->tag_name_starts_at = $this->token_starts_at + 2; - $this->tag_name_length = $pi_target_length; - $this->text_starts_at += $pi_target_length; - $this->text_length -= $pi_target_length + 1; - } - } - - return true; - } - - /* - * If a non-alpha starts the tag name in a tag closer it's a comment. - * Find the first `>`, which closes the comment. - * - * This parser classifies these particular comments as special "funky comments" - * which are made available for further processing. - * - * See https://html.spec.whatwg.org/#parse-error-invalid-first-character-of-tag-name - */ - if ( $this->is_closing_tag ) { - // No chance of finding a closer. - if ( $at + 3 > $doc_length ) { - return false; - } - - $closer_at = strpos( $html, '>', $at + 3 ); - if ( false === $closer_at ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - $this->parser_state = self::STATE_FUNKY_COMMENT; - $this->token_length = $closer_at + 1 - $this->token_starts_at; - $this->text_starts_at = $this->token_starts_at + 2; - $this->text_length = $closer_at - $this->text_starts_at; - $this->bytes_already_parsed = $closer_at + 1; - return true; - } - - ++$at; - } - - return false; - } - - /** - * Parses the next attribute. - * - * @since 6.2.0 - * - * @return bool Whether an attribute was found before the end of the document. - */ - private function parse_next_attribute() { - // Skip whitespace and slashes. - $this->bytes_already_parsed += strspn( $this->html, " \t\f\r\n/", $this->bytes_already_parsed ); - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - /* - * Treat the equal sign as a part of the attribute - * name if it is the first encountered byte. - * - * @see https://html.spec.whatwg.org/multipage/parsing.html#before-attribute-name-state - */ - $name_length = '=' === $this->html[ $this->bytes_already_parsed ] - ? 1 + strcspn( $this->html, "=/> \t\f\r\n", $this->bytes_already_parsed + 1 ) - : strcspn( $this->html, "=/> \t\f\r\n", $this->bytes_already_parsed ); - - // No attribute, just tag closer. - if ( 0 === $name_length || $this->bytes_already_parsed + $name_length >= strlen( $this->html ) ) { - return false; - } - - $attribute_start = $this->bytes_already_parsed; - $attribute_name = substr( $this->html, $attribute_start, $name_length ); - $this->bytes_already_parsed += $name_length; - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - $this->skip_whitespace(); - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - $has_value = '=' === $this->html[ $this->bytes_already_parsed ]; - if ( $has_value ) { - ++$this->bytes_already_parsed; - $this->skip_whitespace(); - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - switch ( $this->html[ $this->bytes_already_parsed ] ) { - case "'": - case '"': - $quote = $this->html[ $this->bytes_already_parsed ]; - $value_start = $this->bytes_already_parsed + 1; - $value_length = strcspn( $this->html, $quote, $value_start ); - $attribute_end = $value_start + $value_length + 1; - $this->bytes_already_parsed = $attribute_end; - break; - - default: - $value_start = $this->bytes_already_parsed; - $value_length = strcspn( $this->html, "> \t\f\r\n", $value_start ); - $attribute_end = $value_start + $value_length; - $this->bytes_already_parsed = $attribute_end; - } - } else { - $value_start = $this->bytes_already_parsed; - $value_length = 0; - $attribute_end = $attribute_start + $name_length; - } - - if ( $attribute_end >= strlen( $this->html ) ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - if ( $this->is_closing_tag ) { - return true; - } - - /* - * > There must never be two or more attributes on - * > the same start tag whose names are an ASCII - * > case-insensitive match for each other. - * - HTML 5 spec - * - * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive - */ - $comparable_name = strtolower( $attribute_name ); - - // If an attribute is listed many times, only use the first declaration and ignore the rest. - if ( ! array_key_exists( $comparable_name, $this->attributes ) ) { - $this->attributes[ $comparable_name ] = new Gutenberg_HTML_Attribute_Token_6_5( - $attribute_name, - $value_start, - $value_length, - $attribute_start, - $attribute_end - $attribute_start, - ! $has_value - ); - - return true; - } - - /* - * Track the duplicate attributes so if we remove it, all disappear together. - * - * While `$this->duplicated_attributes` could always be stored as an `array()`, - * which would simplify the logic here, storing a `null` and only allocating - * an array when encountering duplicates avoids needless allocations in the - * normative case of parsing tags with no duplicate attributes. - */ - $duplicate_span = new Gutenberg_HTML_Span_6_5( $attribute_start, $attribute_end - $attribute_start ); - if ( null === $this->duplicate_attributes ) { - $this->duplicate_attributes = array( $comparable_name => array( $duplicate_span ) ); - } elseif ( ! array_key_exists( $comparable_name, $this->duplicate_attributes ) ) { - $this->duplicate_attributes[ $comparable_name ] = array( $duplicate_span ); - } else { - $this->duplicate_attributes[ $comparable_name ][] = $duplicate_span; - } - - return true; - } - - /** - * Move the internal cursor past any immediate successive whitespace. - * - * @since 6.2.0 - */ - private function skip_whitespace() { - $this->bytes_already_parsed += strspn( $this->html, " \t\f\r\n", $this->bytes_already_parsed ); - } - - /** - * Applies attribute updates and cleans up once a tag is fully parsed. - * - * @since 6.2.0 - */ - private function after_tag() { - /* - * There could be lexical updates enqueued for an attribute that - * also exists on the next tag. In order to avoid conflating the - * attributes across the two tags, lexical updates with names - * need to be flushed to raw lexical updates. - */ - $this->class_name_updates_to_attributes_updates(); - - /* - * Purge updates if there are too many. The actual count isn't - * scientific, but a few values from 100 to a few thousand were - * tests to find a practially-useful limit. - * - * If the update queue grows too big, then the Tag Processor - * will spend more time iterating through them and lose the - * efficiency gains of deferring applying them. - */ - if ( 1000 < count( $this->lexical_updates ) ) { - $this->get_updated_html(); - } - - foreach ( $this->lexical_updates as $name => $update ) { - /* - * Any updates appearing after the cursor should be applied - * before proceeding, otherwise they may be overlooked. - */ - if ( $update->start >= $this->bytes_already_parsed ) { - $this->get_updated_html(); - break; - } - - if ( is_int( $name ) ) { - continue; - } - - $this->lexical_updates[] = $update; - unset( $this->lexical_updates[ $name ] ); - } - - $this->token_starts_at = null; - $this->token_length = null; - $this->tag_name_starts_at = null; - $this->tag_name_length = null; - $this->text_starts_at = 0; - $this->text_length = 0; - $this->is_closing_tag = null; - $this->attributes = array(); - $this->comment_type = null; - $this->duplicate_attributes = null; - } - - /** - * Converts class name updates into tag attributes updates - * (they are accumulated in different data formats for performance). - * - * @since 6.2.0 - * - * @see WP_HTML_Tag_Processor::$lexical_updates - * @see WP_HTML_Tag_Processor::$classname_updates - */ - private function class_name_updates_to_attributes_updates() { - if ( count( $this->classname_updates ) === 0 ) { - return; - } - - $existing_class = $this->get_enqueued_attribute_value( 'class' ); - if ( null === $existing_class || true === $existing_class ) { - $existing_class = ''; - } - - if ( false === $existing_class && isset( $this->attributes['class'] ) ) { - $existing_class = substr( - $this->html, - $this->attributes['class']->value_starts_at, - $this->attributes['class']->value_length - ); - } - - if ( false === $existing_class ) { - $existing_class = ''; - } - - /** - * Updated "class" attribute value. - * - * This is incrementally built while scanning through the existing class - * attribute, skipping removed classes on the way, and then appending - * added classes at the end. Only when finished processing will the - * value contain the final new value. - - * @var string $class - */ - $class = ''; - - /** - * Tracks the cursor position in the existing - * class attribute value while parsing. - * - * @var int $at - */ - $at = 0; - - /** - * Indicates if there's any need to modify the existing class attribute. - * - * If a call to `add_class()` and `remove_class()` wouldn't impact - * the `class` attribute value then there's no need to rebuild it. - * For example, when adding a class that's already present or - * removing one that isn't. - * - * This flag enables a performance optimization when none of the enqueued - * class updates would impact the `class` attribute; namely, that the - * processor can continue without modifying the input document, as if - * none of the `add_class()` or `remove_class()` calls had been made. - * - * This flag is set upon the first change that requires a string update. - * - * @var bool $modified - */ - $modified = false; - - // Remove unwanted classes by only copying the new ones. - $existing_class_length = strlen( $existing_class ); - while ( $at < $existing_class_length ) { - // Skip to the first non-whitespace character. - $ws_at = $at; - $ws_length = strspn( $existing_class, " \t\f\r\n", $ws_at ); - $at += $ws_length; - - // Capture the class name – it's everything until the next whitespace. - $name_length = strcspn( $existing_class, " \t\f\r\n", $at ); - if ( 0 === $name_length ) { - // If no more class names are found then that's the end. - break; - } - - $name = substr( $existing_class, $at, $name_length ); - $at += $name_length; - - // If this class is marked for removal, start processing the next one. - $remove_class = ( - isset( $this->classname_updates[ $name ] ) && - self::REMOVE_CLASS === $this->classname_updates[ $name ] - ); - - // If a class has already been seen then skip it; it should not be added twice. - if ( ! $remove_class ) { - $this->classname_updates[ $name ] = self::SKIP_CLASS; - } - - if ( $remove_class ) { - $modified = true; - continue; - } - - /* - * Otherwise, append it to the new "class" attribute value. - * - * There are options for handling whitespace between tags. - * Preserving the existing whitespace produces fewer changes - * to the HTML content and should clarify the before/after - * content when debugging the modified output. - * - * This approach contrasts normalizing the inter-class - * whitespace to a single space, which might appear cleaner - * in the output HTML but produce a noisier change. - */ - $class .= substr( $existing_class, $ws_at, $ws_length ); - $class .= $name; - } - - // Add new classes by appending those which haven't already been seen. - foreach ( $this->classname_updates as $name => $operation ) { - if ( self::ADD_CLASS === $operation ) { - $modified = true; - - $class .= strlen( $class ) > 0 ? ' ' : ''; - $class .= $name; - } - } - - $this->classname_updates = array(); - if ( ! $modified ) { - return; - } - - if ( strlen( $class ) > 0 ) { - $this->set_attribute( 'class', $class ); - } else { - $this->remove_attribute( 'class' ); - } - } - - /** - * Applies attribute updates to HTML document. - * - * @since 6.2.0 - * @since 6.2.1 Accumulates shift for internal cursor and passed pointer. - * @since 6.3.0 Invalidate any bookmarks whose targets are overwritten. - * - * @param int $shift_this_point Accumulate and return shift for this position. - * @return int How many bytes the given pointer moved in response to the updates. - */ - private function apply_attributes_updates( $shift_this_point = 0 ) { - if ( ! count( $this->lexical_updates ) ) { - return 0; - } - - $accumulated_shift_for_given_point = 0; - - /* - * Attribute updates can be enqueued in any order but updates - * to the document must occur in lexical order; that is, each - * replacement must be made before all others which follow it - * at later string indices in the input document. - * - * Sorting avoid making out-of-order replacements which - * can lead to mangled output, partially-duplicated - * attributes, and overwritten attributes. - */ - usort( $this->lexical_updates, array( self::class, 'sort_start_ascending' ) ); - - $bytes_already_copied = 0; - $output_buffer = ''; - foreach ( $this->lexical_updates as $diff ) { - $shift = strlen( $diff->text ) - $diff->length; - - // Adjust the cursor position by however much an update affects it. - if ( $diff->start < $this->bytes_already_parsed ) { - $this->bytes_already_parsed += $shift; - } - - // Accumulate shift of the given pointer within this function call. - if ( $diff->start <= $shift_this_point ) { - $accumulated_shift_for_given_point += $shift; - } - - $output_buffer .= substr( $this->html, $bytes_already_copied, $diff->start - $bytes_already_copied ); - $output_buffer .= $diff->text; - $bytes_already_copied = $diff->start + $diff->length; - } - - $this->html = $output_buffer . substr( $this->html, $bytes_already_copied ); - - /* - * Adjust bookmark locations to account for how the text - * replacements adjust offsets in the input document. - */ - foreach ( $this->bookmarks as $bookmark_name => $bookmark ) { - $bookmark_end = $bookmark->start + $bookmark->length; - - /* - * Each lexical update which appears before the bookmark's endpoints - * might shift the offsets for those endpoints. Loop through each change - * and accumulate the total shift for each bookmark, then apply that - * shift after tallying the full delta. - */ - $head_delta = 0; - $tail_delta = 0; - - foreach ( $this->lexical_updates as $diff ) { - $diff_end = $diff->start + $diff->length; - - if ( $bookmark->start < $diff->start && $bookmark_end < $diff->start ) { - break; - } - - if ( $bookmark->start >= $diff->start && $bookmark_end < $diff_end ) { - $this->release_bookmark( $bookmark_name ); - continue 2; - } - - $delta = strlen( $diff->text ) - $diff->length; - - if ( $bookmark->start >= $diff->start ) { - $head_delta += $delta; - } - - if ( $bookmark_end >= $diff_end ) { - $tail_delta += $delta; - } - } - - $bookmark->start += $head_delta; - $bookmark->length += $tail_delta - $head_delta; - } - - $this->lexical_updates = array(); - - return $accumulated_shift_for_given_point; - } - - /** - * Checks whether a bookmark with the given name exists. - * - * @since 6.3.0 - * - * @param string $bookmark_name Name to identify a bookmark that potentially exists. - * @return bool Whether that bookmark exists. - */ - public function has_bookmark( $bookmark_name ) { - return array_key_exists( $bookmark_name, $this->bookmarks ); - } - - /** - * Move the internal cursor in the Tag Processor to a given bookmark's location. - * - * In order to prevent accidental infinite loops, there's a - * maximum limit on the number of times seek() can be called. - * - * @since 6.2.0 - * - * @param string $bookmark_name Jump to the place in the document identified by this bookmark name. - * @return bool Whether the internal cursor was successfully moved to the bookmark's location. - */ - public function seek( $bookmark_name ) { - if ( ! array_key_exists( $bookmark_name, $this->bookmarks ) ) { - _doing_it_wrong( - __METHOD__, - __( 'Unknown bookmark name.' ), - '6.2.0' - ); - return false; - } - - if ( ++$this->seek_count > static::MAX_SEEK_OPS ) { - _doing_it_wrong( - __METHOD__, - __( 'Too many calls to seek() - this can lead to performance issues.' ), - '6.2.0' - ); - return false; - } - - // Flush out any pending updates to the document. - $this->get_updated_html(); - - // Point this tag processor before the sought tag opener and consume it. - $this->bytes_already_parsed = $this->bookmarks[ $bookmark_name ]->start; - $this->parser_state = self::STATE_READY; - return $this->next_token(); - } - - /** - * Compare two WP_HTML_Text_Replacement objects. - * - * @since 6.2.0 - * - * @param WP_HTML_Text_Replacement $a First attribute update. - * @param WP_HTML_Text_Replacement $b Second attribute update. - * @return int Comparison value for string order. - */ - private static function sort_start_ascending( $a, $b ) { - $by_start = $a->start - $b->start; - if ( 0 !== $by_start ) { - return $by_start; - } - - $by_text = isset( $a->text, $b->text ) ? strcmp( $a->text, $b->text ) : 0; - if ( 0 !== $by_text ) { - return $by_text; - } - - /* - * This code should be unreachable, because it implies the two replacements - * start at the same location and contain the same text. - */ - return $a->length - $b->length; - } - - /** - * Return the enqueued value for a given attribute, if one exists. - * - * Enqueued updates can take different data types: - * - If an update is enqueued and is boolean, the return will be `true` - * - If an update is otherwise enqueued, the return will be the string value of that update. - * - If an attribute is enqueued to be removed, the return will be `null` to indicate that. - * - If no updates are enqueued, the return will be `false` to differentiate from "removed." - * - * @since 6.2.0 - * - * @param string $comparable_name The attribute name in its comparable form. - * @return string|boolean|null Value of enqueued update if present, otherwise false. - */ - private function get_enqueued_attribute_value( $comparable_name ) { - if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { - return false; - } - - if ( ! isset( $this->lexical_updates[ $comparable_name ] ) ) { - return false; - } - - $enqueued_text = $this->lexical_updates[ $comparable_name ]->text; - - // Removed attributes erase the entire span. - if ( '' === $enqueued_text ) { - return null; - } - - /* - * Boolean attribute updates are just the attribute name without a corresponding value. - * - * This value might differ from the given comparable name in that there could be leading - * or trailing whitespace, and that the casing follows the name given in `set_attribute`. - * - * Example: - * - * $p->set_attribute( 'data-TEST-id', 'update' ); - * 'update' === $p->get_enqueued_attribute_value( 'data-test-id' ); - * - * Detect this difference based on the absence of the `=`, which _must_ exist in any - * attribute containing a value, e.g. `<input type="text" enabled />`. - * ¹ ² - * 1. Attribute with a string value. - * 2. Boolean attribute whose value is `true`. - */ - $equals_at = strpos( $enqueued_text, '=' ); - if ( false === $equals_at ) { - return true; - } - - /* - * Finally, a normal update's value will appear after the `=` and - * be double-quoted, as performed incidentally by `set_attribute`. - * - * e.g. `type="text"` - * ¹² ³ - * 1. Equals is here. - * 2. Double-quoting starts one after the equals sign. - * 3. Double-quoting ends at the last character in the update. - */ - $enqueued_value = substr( $enqueued_text, $equals_at + 2, -1 ); - return html_entity_decode( $enqueued_value ); - } - - /** - * Returns the value of a requested attribute from a matched tag opener if that attribute exists. - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( '<div enabled class="test" data-test-id="14">Test</div>' ); - * $p->next_tag( array( 'class_name' => 'test' ) ) === true; - * $p->get_attribute( 'data-test-id' ) === '14'; - * $p->get_attribute( 'enabled' ) === true; - * $p->get_attribute( 'aria-label' ) === null; - * - * $p->next_tag() === false; - * $p->get_attribute( 'class' ) === null; - * - * @since 6.2.0 - * - * @param string $name Name of attribute whose value is requested. - * @return string|true|null Value of attribute or `null` if not available. Boolean attributes return `true`. - */ - public function get_attribute( $name ) { - if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { - return null; - } - - $comparable = strtolower( $name ); - - /* - * For every attribute other than `class` it's possible to perform a quick check if - * there's an enqueued lexical update whose value takes priority over what's found in - * the input document. - * - * The `class` attribute is special though because of the exposed helpers `add_class` - * and `remove_class`. These form a builder for the `class` attribute, so an additional - * check for enqueued class changes is required in addition to the check for any enqueued - * attribute values. If any exist, those enqueued class changes must first be flushed out - * into an attribute value update. - */ - if ( 'class' === $name ) { - $this->class_name_updates_to_attributes_updates(); - } - - // Return any enqueued attribute value updates if they exist. - $enqueued_value = $this->get_enqueued_attribute_value( $comparable ); - if ( false !== $enqueued_value ) { - return $enqueued_value; - } - - if ( ! isset( $this->attributes[ $comparable ] ) ) { - return null; - } - - $attribute = $this->attributes[ $comparable ]; - - /* - * This flag distinguishes an attribute with no value - * from an attribute with an empty string value. For - * unquoted attributes this could look very similar. - * It refers to whether an `=` follows the name. - * - * e.g. <div boolean-attribute empty-attribute=></div> - * ¹ ² - * 1. Attribute `boolean-attribute` is `true`. - * 2. Attribute `empty-attribute` is `""`. - */ - if ( true === $attribute->is_true ) { - return true; - } - - $raw_value = substr( $this->html, $attribute->value_starts_at, $attribute->value_length ); - - return html_entity_decode( $raw_value ); - } - - /** - * Gets lowercase names of all attributes matching a given prefix in the current tag. - * - * Note that matching is case-insensitive. This is in accordance with the spec: - * - * > There must never be two or more attributes on - * > the same start tag whose names are an ASCII - * > case-insensitive match for each other. - * - HTML 5 spec - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( '<div data-ENABLED class="test" DATA-test-id="14">Test</div>' ); - * $p->next_tag( array( 'class_name' => 'test' ) ) === true; - * $p->get_attribute_names_with_prefix( 'data-' ) === array( 'data-enabled', 'data-test-id' ); - * - * $p->next_tag() === false; - * $p->get_attribute_names_with_prefix( 'data-' ) === null; - * - * @since 6.2.0 - * - * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive - * - * @param string $prefix Prefix of requested attribute names. - * @return array|null List of attribute names, or `null` when no tag opener is matched. - */ - public function get_attribute_names_with_prefix( $prefix ) { - if ( - self::STATE_MATCHED_TAG !== $this->parser_state || - $this->is_closing_tag - ) { - return null; - } - - $comparable = strtolower( $prefix ); - - $matches = array(); - foreach ( array_keys( $this->attributes ) as $attr_name ) { - if ( str_starts_with( $attr_name, $comparable ) ) { - $matches[] = $attr_name; - } - } - return $matches; - } - - /** - * Returns the uppercase name of the matched tag. - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( '<div class="test">Test</div>' ); - * $p->next_tag() === true; - * $p->get_tag() === 'DIV'; - * - * $p->next_tag() === false; - * $p->get_tag() === null; - * - * @since 6.2.0 - * - * @return string|null Name of currently matched tag in input HTML, or `null` if none found. - */ - public function get_tag() { - if ( null === $this->tag_name_starts_at ) { - return null; - } - - $tag_name = substr( $this->html, $this->tag_name_starts_at, $this->tag_name_length ); - - if ( self::STATE_MATCHED_TAG === $this->parser_state ) { - return strtoupper( $tag_name ); - } - - if ( - self::STATE_COMMENT === $this->parser_state && - self::COMMENT_AS_PI_NODE_LOOKALIKE === $this->get_comment_type() - ) { - return $tag_name; - } - - return null; - } - - /** - * Indicates if the currently matched tag contains the self-closing flag. - * - * No HTML elements ought to have the self-closing flag and for those, the self-closing - * flag will be ignored. For void elements this is benign because they "self close" - * automatically. For non-void HTML elements though problems will appear if someone - * intends to use a self-closing element in place of that element with an empty body. - * For HTML foreign elements and custom elements the self-closing flag determines if - * they self-close or not. - * - * This function does not determine if a tag is self-closing, - * but only if the self-closing flag is present in the syntax. - * - * @since 6.3.0 - * - * @return bool Whether the currently matched tag contains the self-closing flag. - */ - public function has_self_closing_flag() { - if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { - return false; - } - - /* - * The self-closing flag is the solidus at the _end_ of the tag, not the beginning. - * - * Example: - * - * <figure /> - * ^ this appears one character before the end of the closing ">". - */ - return '/' === $this->html[ $this->token_starts_at + $this->token_length - 1 ]; - } - - /** - * Indicates if the current tag token is a tag closer. - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( '<div></div>' ); - * $p->next_tag( array( 'tag_name' => 'div', 'tag_closers' => 'visit' ) ); - * $p->is_tag_closer() === false; - * - * $p->next_tag( array( 'tag_name' => 'div', 'tag_closers' => 'visit' ) ); - * $p->is_tag_closer() === true; - * - * @since 6.2.0 - * - * @return bool Whether the current tag is a tag closer. - */ - public function is_tag_closer() { - return ( - self::STATE_MATCHED_TAG === $this->parser_state && - $this->is_closing_tag - ); - } - - /** - * Indicates the kind of matched token, if any. - * - * This differs from `get_token_name()` in that it always - * returns a static string indicating the type, whereas - * `get_token_name()` may return values derived from the - * token itself, such as a tag name or processing - * instruction tag. - * - * Possible values: - * - `#tag` when matched on a tag. - * - `#text` when matched on a text node. - * - `#cdata-section` when matched on a CDATA node. - * - `#comment` when matched on a comment. - * - `#doctype` when matched on a DOCTYPE declaration. - * - `#presumptuous-tag` when matched on an empty tag closer. - * - `#funky-comment` when matched on a funky comment. - * - * @since 6.5.0 - * - * @return string|null What kind of token is matched, or null. - */ - public function get_token_type() { - switch ( $this->parser_state ) { - case self::STATE_MATCHED_TAG: - return '#tag'; - - case self::STATE_DOCTYPE: - return '#doctype'; - - default: - return $this->get_token_name(); - } - } - - /** - * Returns the node name represented by the token. - * - * This matches the DOM API value `nodeName`. Some values - * are static, such as `#text` for a text node, while others - * are dynamically generated from the token itself. - * - * Dynamic names: - * - Uppercase tag name for tag matches. - * - `html` for DOCTYPE declarations. - * - * Note that if the Tag Processor is not matched on a token - * then this function will return `null`, either because it - * hasn't yet found a token or because it reached the end - * of the document without matching a token. - * - * @since 6.5.0 - * - * @return string|null Name of the matched token. - */ - public function get_token_name() { - switch ( $this->parser_state ) { - case self::STATE_MATCHED_TAG: - return $this->get_tag(); - - case self::STATE_TEXT_NODE: - return '#text'; - - case self::STATE_CDATA_NODE: - return '#cdata-section'; - - case self::STATE_COMMENT: - return '#comment'; - - case self::STATE_DOCTYPE: - return 'html'; - - case self::STATE_PRESUMPTUOUS_TAG: - return '#presumptuous-tag'; - - case self::STATE_FUNKY_COMMENT: - return '#funky-comment'; - } - } - - /** - * Indicates what kind of comment produced the comment node. - * - * Because there are different kinds of HTML syntax which produce - * comments, the Tag Processor tracks and exposes this as a type - * for the comment. Nominally only regular HTML comments exist as - * they are commonly known, but a number of unrelated syntax errors - * also produce comments. - * - * @see self::COMMENT_AS_ABRUPTLY_CLOSED_COMMENT - * @see self::COMMENT_AS_CDATA_LOOKALIKE - * @see self::COMMENT_AS_INVALID_HTML - * @see self::COMMENT_AS_HTML_COMMENT - * @see self::COMMENT_AS_PI_NODE_LOOKALIKE - * - * @since 6.5.0 - * - * @return string|null - */ - public function get_comment_type() { - if ( self::STATE_COMMENT !== $this->parser_state ) { - return null; - } - - return $this->comment_type; - } - - /** - * Returns the modifiable text for a matched token, or an empty string. - * - * Modifiable text is text content that may be read and changed without - * changing the HTML structure of the document around it. This includes - * the contents of `#text` nodes in the HTML as well as the inner - * contents of HTML comments, Processing Instructions, and others, even - * though these nodes aren't part of a parsed DOM tree. They also contain - * the contents of SCRIPT and STYLE tags, of TEXTAREA tags, and of any - * other section in an HTML document which cannot contain HTML markup (DATA). - * - * If a token has no modifiable text then an empty string is returned to - * avoid needless crashing or type errors. An empty string does not mean - * that a token has modifiable text, and a token with modifiable text may - * have an empty string (e.g. a comment with no contents). - * - * @since 6.5.0 - * - * @return string - */ - public function get_modifiable_text() { - if ( null === $this->text_starts_at ) { - return ''; - } - - $text = substr( $this->html, $this->text_starts_at, $this->text_length ); - - // Comment data is not decoded. - if ( - self::STATE_CDATA_NODE === $this->parser_state || - self::STATE_COMMENT === $this->parser_state || - self::STATE_DOCTYPE === $this->parser_state || - self::STATE_FUNKY_COMMENT === $this->parser_state - ) { - return $text; - } - - $tag_name = $this->get_tag(); - if ( - // Script data is not decoded. - 'SCRIPT' === $tag_name || - - // RAWTEXT data is not decoded. - 'IFRAME' === $tag_name || - 'NOEMBED' === $tag_name || - 'NOFRAMES' === $tag_name || - 'STYLE' === $tag_name || - 'XMP' === $tag_name - ) { - return $text; - } - - $decoded = html_entity_decode( $text, ENT_QUOTES | ENT_HTML5 | ENT_SUBSTITUTE ); - - /* - * TEXTAREA skips a leading newline, but this newline may appear not only as the - * literal character `\n`, but also as a character reference, such as in the - * following markup: `<textarea> Content</textarea>`. - * - * For these cases it's important to first decode the text content before checking - * for a leading newline and removing it. - */ - if ( - self::STATE_MATCHED_TAG === $this->parser_state && - 'TEXTAREA' === $tag_name && - strlen( $decoded ) > 0 && - "\n" === $decoded[0] - ) { - return substr( $decoded, 1 ); - } - - return $decoded; - } - - /** - * Updates or creates a new attribute on the currently matched tag with the passed value. - * - * For boolean attributes special handling is provided: - * - When `true` is passed as the value, then only the attribute name is added to the tag. - * - When `false` is passed, the attribute gets removed if it existed before. - * - * For string attributes, the value is escaped using the `esc_attr` function. - * - * @since 6.2.0 - * @since 6.2.1 Fix: Only create a single update for multiple calls with case-variant attribute names. - * - * @param string $name The attribute name to target. - * @param string|bool $value The new attribute value. - * @return bool Whether an attribute value was set. - */ - public function set_attribute( $name, $value ) { - if ( - self::STATE_MATCHED_TAG !== $this->parser_state || - $this->is_closing_tag - ) { - return false; - } - - /* - * WordPress rejects more characters than are strictly forbidden - * in HTML5. This is to prevent additional security risks deeper - * in the WordPress and plugin stack. Specifically the - * less-than (<) greater-than (>) and ampersand (&) aren't allowed. - * - * The use of a PCRE match enables looking for specific Unicode - * code points without writing a UTF-8 decoder. Whereas scanning - * for one-byte characters is trivial (with `strcspn`), scanning - * for the longer byte sequences would be more complicated. Given - * that this shouldn't be in the hot path for execution, it's a - * reasonable compromise in efficiency without introducing a - * noticeable impact on the overall system. - * - * @see https://html.spec.whatwg.org/#attributes-2 - * - * @todo As the only regex pattern maybe we should take it out? - * Are Unicode patterns available broadly in Core? - */ - if ( preg_match( - '~[' . - // Syntax-like characters. - '"\'>&</ =' . - // Control characters. - '\x{00}-\x{1F}' . - // HTML noncharacters. - '\x{FDD0}-\x{FDEF}' . - '\x{FFFE}\x{FFFF}\x{1FFFE}\x{1FFFF}\x{2FFFE}\x{2FFFF}\x{3FFFE}\x{3FFFF}' . - '\x{4FFFE}\x{4FFFF}\x{5FFFE}\x{5FFFF}\x{6FFFE}\x{6FFFF}\x{7FFFE}\x{7FFFF}' . - '\x{8FFFE}\x{8FFFF}\x{9FFFE}\x{9FFFF}\x{AFFFE}\x{AFFFF}\x{BFFFE}\x{BFFFF}' . - '\x{CFFFE}\x{CFFFF}\x{DFFFE}\x{DFFFF}\x{EFFFE}\x{EFFFF}\x{FFFFE}\x{FFFFF}' . - '\x{10FFFE}\x{10FFFF}' . - ']~Ssu', - $name - ) ) { - _doing_it_wrong( - __METHOD__, - __( 'Invalid attribute name.' ), - '6.2.0' - ); - - return false; - } - - /* - * > The values "true" and "false" are not allowed on boolean attributes. - * > To represent a false value, the attribute has to be omitted altogether. - * - HTML5 spec, https://html.spec.whatwg.org/#boolean-attributes - */ - if ( false === $value ) { - return $this->remove_attribute( $name ); - } - - if ( true === $value ) { - $updated_attribute = $name; - } else { - $comparable_name = strtolower( $name ); - - /* - * Escape URL attributes. - * - * @see https://html.spec.whatwg.org/#attributes-3 - */ - $escaped_new_value = in_array( $comparable_name, wp_kses_uri_attributes() ) ? esc_url( $value ) : esc_attr( $value ); - $updated_attribute = "{$name}=\"{$escaped_new_value}\""; - } - - /* - * > There must never be two or more attributes on - * > the same start tag whose names are an ASCII - * > case-insensitive match for each other. - * - HTML 5 spec - * - * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive - */ - $comparable_name = strtolower( $name ); - - if ( isset( $this->attributes[ $comparable_name ] ) ) { - /* - * Update an existing attribute. - * - * Example – set attribute id to "new" in <div id="initial_id" />: - * - * <div id="initial_id"/> - * ^-------------^ - * start end - * replacement: `id="new"` - * - * Result: <div id="new"/> - */ - $existing_attribute = $this->attributes[ $comparable_name ]; - $this->lexical_updates[ $comparable_name ] = new Gutenberg_HTML_Text_Replacement_6_5( - $existing_attribute->start, - $existing_attribute->length, - $updated_attribute - ); - } else { - /* - * Create a new attribute at the tag's name end. - * - * Example – add attribute id="new" to <div />: - * - * <div/> - * ^ - * start and end - * replacement: ` id="new"` - * - * Result: <div id="new"/> - */ - $this->lexical_updates[ $comparable_name ] = new Gutenberg_HTML_Text_Replacement_6_5( - $this->tag_name_starts_at + $this->tag_name_length, - 0, - ' ' . $updated_attribute - ); - } - - /* - * Any calls to update the `class` attribute directly should wipe out any - * enqueued class changes from `add_class` and `remove_class`. - */ - if ( 'class' === $comparable_name && ! empty( $this->classname_updates ) ) { - $this->classname_updates = array(); - } - - return true; - } - - /** - * Remove an attribute from the currently-matched tag. - * - * @since 6.2.0 - * - * @param string $name The attribute name to remove. - * @return bool Whether an attribute was removed. - */ - public function remove_attribute( $name ) { - if ( - self::STATE_MATCHED_TAG !== $this->parser_state || - $this->is_closing_tag - ) { - return false; - } - - /* - * > There must never be two or more attributes on - * > the same start tag whose names are an ASCII - * > case-insensitive match for each other. - * - HTML 5 spec - * - * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive - */ - $name = strtolower( $name ); - - /* - * Any calls to update the `class` attribute directly should wipe out any - * enqueued class changes from `add_class` and `remove_class`. - */ - if ( 'class' === $name && count( $this->classname_updates ) !== 0 ) { - $this->classname_updates = array(); - } - - /* - * If updating an attribute that didn't exist in the input - * document, then remove the enqueued update and move on. - * - * For example, this might occur when calling `remove_attribute()` - * after calling `set_attribute()` for the same attribute - * and when that attribute wasn't originally present. - */ - if ( ! isset( $this->attributes[ $name ] ) ) { - if ( isset( $this->lexical_updates[ $name ] ) ) { - unset( $this->lexical_updates[ $name ] ); - } - return false; - } - - /* - * Removes an existing tag attribute. - * - * Example – remove the attribute id from <div id="main"/>: - * <div id="initial_id"/> - * ^-------------^ - * start end - * replacement: `` - * - * Result: <div /> - */ - $this->lexical_updates[ $name ] = new Gutenberg_HTML_Text_Replacement_6_5( - $this->attributes[ $name ]->start, - $this->attributes[ $name ]->length, - '' - ); - - // Removes any duplicated attributes if they were also present. - if ( null !== $this->duplicate_attributes && array_key_exists( $name, $this->duplicate_attributes ) ) { - foreach ( $this->duplicate_attributes[ $name ] as $attribute_token ) { - $this->lexical_updates[] = new Gutenberg_HTML_Text_Replacement_6_5( - $attribute_token->start, - $attribute_token->length, - '' - ); - } - } - - return true; - } - - /** - * Adds a new class name to the currently matched tag. - * - * @since 6.2.0 - * - * @param string $class_name The class name to add. - * @return bool Whether the class was set to be added. - */ - public function add_class( $class_name ) { - if ( - self::STATE_MATCHED_TAG !== $this->parser_state || - $this->is_closing_tag - ) { - return false; - } - - $this->classname_updates[ $class_name ] = self::ADD_CLASS; - - return true; - } - - /** - * Removes a class name from the currently matched tag. - * - * @since 6.2.0 - * - * @param string $class_name The class name to remove. - * @return bool Whether the class was set to be removed. - */ - public function remove_class( $class_name ) { - if ( - self::STATE_MATCHED_TAG !== $this->parser_state || - $this->is_closing_tag - ) { - return false; - } - - if ( null !== $this->tag_name_starts_at ) { - $this->classname_updates[ $class_name ] = self::REMOVE_CLASS; - } - - return true; - } - - /** - * Returns the string representation of the HTML Tag Processor. - * - * @since 6.2.0 - * - * @see WP_HTML_Tag_Processor::get_updated_html() - * - * @return string The processed HTML. - */ - public function __toString() { - return $this->get_updated_html(); - } - - /** - * Returns the string representation of the HTML Tag Processor. - * - * @since 6.2.0 - * @since 6.2.1 Shifts the internal cursor corresponding to the applied updates. - * @since 6.4.0 No longer calls subclass method `next_tag()` after updating HTML. - * - * @return string The processed HTML. - */ - public function get_updated_html() { - $requires_no_updating = 0 === count( $this->classname_updates ) && 0 === count( $this->lexical_updates ); - - /* - * When there is nothing more to update and nothing has already been - * updated, return the original document and avoid a string copy. - */ - if ( $requires_no_updating ) { - return $this->html; - } - - /* - * Keep track of the position right before the current tag. This will - * be necessary for reparsing the current tag after updating the HTML. - */ - $before_current_tag = $this->token_starts_at; - - /* - * 1. Apply the enqueued edits and update all the pointers to reflect those changes. - */ - $this->class_name_updates_to_attributes_updates(); - $before_current_tag += $this->apply_attributes_updates( $before_current_tag ); - - /* - * 2. Rewind to before the current tag and reparse to get updated attributes. - * - * At this point the internal cursor points to the end of the tag name. - * Rewind before the tag name starts so that it's as if the cursor didn't - * move; a call to `next_tag()` will reparse the recently-updated attributes - * and additional calls to modify the attributes will apply at this same - * location, but in order to avoid issues with subclasses that might add - * behaviors to `next_tag()`, the internal methods should be called here - * instead. - * - * It's important to note that in this specific place there will be no change - * because the processor was already at a tag when this was called and it's - * rewinding only to the beginning of this very tag before reprocessing it - * and its attributes. - * - * <p>Previous HTML<em>More HTML</em></p> - * ↑ │ back up by the length of the tag name plus the opening < - * └←─┘ back up by strlen("em") + 1 ==> 3 - */ - $this->bytes_already_parsed = $before_current_tag; - $this->base_class_next_token(); - - return $this->html; - } - - /** - * Parses tag query input into internal search criteria. - * - * @since 6.2.0 - * - * @param array|string|null $query { - * Optional. Which tag name to find, having which class, etc. Default is to find any tag. - * - * @type string|null $tag_name Which tag to find, or `null` for "any tag." - * @type int|null $match_offset Find the Nth tag matching all search criteria. - * 1 for "first" tag, 3 for "third," etc. - * Defaults to first tag. - * @type string|null $class_name Tag must contain this class name to match. - * @type string $tag_closers "visit" or "skip": whether to stop on tag closers, e.g. </div>. - * } - */ - private function parse_query( $query ) { - if ( null !== $query && $query === $this->last_query ) { - return; - } - - $this->last_query = $query; - $this->sought_tag_name = null; - $this->sought_class_name = null; - $this->sought_match_offset = 1; - $this->stop_on_tag_closers = false; - - // A single string value means "find the tag of this name". - if ( is_string( $query ) ) { - $this->sought_tag_name = $query; - return; - } - - // An empty query parameter applies no restrictions on the search. - if ( null === $query ) { - return; - } - - // If not using the string interface, an associative array is required. - if ( ! is_array( $query ) ) { - _doing_it_wrong( - __METHOD__, - __( 'The query argument must be an array or a tag name.' ), - '6.2.0' - ); - return; - } - - if ( isset( $query['tag_name'] ) && is_string( $query['tag_name'] ) ) { - $this->sought_tag_name = $query['tag_name']; - } - - if ( isset( $query['class_name'] ) && is_string( $query['class_name'] ) ) { - $this->sought_class_name = $query['class_name']; - } - - if ( isset( $query['match_offset'] ) && is_int( $query['match_offset'] ) && 0 < $query['match_offset'] ) { - $this->sought_match_offset = $query['match_offset']; - } - - if ( isset( $query['tag_closers'] ) ) { - $this->stop_on_tag_closers = 'visit' === $query['tag_closers']; - } - } - - - /** - * Checks whether a given tag and its attributes match the search criteria. - * - * @since 6.2.0 - * - * @return bool Whether the given tag and its attribute match the search criteria. - */ - private function matches() { - if ( $this->is_closing_tag && ! $this->stop_on_tag_closers ) { - return false; - } - - // Does the tag name match the requested tag name in a case-insensitive manner? - if ( null !== $this->sought_tag_name ) { - /* - * String (byte) length lookup is fast. If they aren't the - * same length then they can't be the same string values. - */ - if ( strlen( $this->sought_tag_name ) !== $this->tag_name_length ) { - return false; - } - - /* - * Check each character to determine if they are the same. - * Defer calls to `strtoupper()` to avoid them when possible. - * Calling `strcasecmp()` here tested slowed than comparing each - * character, so unless benchmarks show otherwise, it should - * not be used. - * - * It's expected that most of the time that this runs, a - * lower-case tag name will be supplied and the input will - * contain lower-case tag names, thus normally bypassing - * the case comparison code. - */ - for ( $i = 0; $i < $this->tag_name_length; $i++ ) { - $html_char = $this->html[ $this->tag_name_starts_at + $i ]; - $tag_char = $this->sought_tag_name[ $i ]; - - if ( $html_char !== $tag_char && strtoupper( $html_char ) !== $tag_char ) { - return false; - } - } - } - - if ( null !== $this->sought_class_name && ! $this->has_class( $this->sought_class_name ) ) { - return false; - } - - return true; - } - - /** - * Parser Ready State. - * - * Indicates that the parser is ready to run and waiting for a state transition. - * It may not have started yet, or it may have just finished parsing a token and - * is ready to find the next one. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_READY = 'STATE_READY'; - - /** - * Parser Complete State. - * - * Indicates that the parser has reached the end of the document and there is - * nothing left to scan. It finished parsing the last token completely. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_COMPLETE = 'STATE_COMPLETE'; - - /** - * Parser Incomplete Input State. - * - * Indicates that the parser has reached the end of the document before finishing - * a token. It started parsing a token but there is a possibility that the input - * HTML document was truncated in the middle of a token. - * - * The parser is reset at the start of the incomplete token and has paused. There - * is nothing more than can be scanned unless provided a more complete document. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_INCOMPLETE_INPUT = 'STATE_INCOMPLETE_INPUT'; - - /** - * Parser Matched Tag State. - * - * Indicates that the parser has found an HTML tag and it's possible to get - * the tag name and read or modify its attributes (if it's not a closing tag). - * - * @since 6.5.0 - * - * @access private - */ - const STATE_MATCHED_TAG = 'STATE_MATCHED_TAG'; - - /** - * Parser Text Node State. - * - * Indicates that the parser has found a text node and it's possible - * to read and modify that text. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_TEXT_NODE = 'STATE_TEXT_NODE'; - - /** - * Parser CDATA Node State. - * - * Indicates that the parser has found a CDATA node and it's possible - * to read and modify its modifiable text. Note that in HTML there are - * no CDATA nodes outside of foreign content (SVG and MathML). Outside - * of foreign content, they are treated as HTML comments. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_CDATA_NODE = 'STATE_CDATA_NODE'; - - /** - * Indicates that the parser has found an HTML comment and it's - * possible to read and modify its modifiable text. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_COMMENT = 'STATE_COMMENT'; - - /** - * Indicates that the parser has found a DOCTYPE node and it's - * possible to read and modify its modifiable text. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_DOCTYPE = 'STATE_DOCTYPE'; - - /** - * Indicates that the parser has found an empty tag closer `</>`. - * - * Note that in HTML there are no empty tag closers, and they - * are ignored. Nonetheless, the Tag Processor still - * recognizes them as they appear in the HTML stream. - * - * These were historically discussed as a "presumptuous tag - * closer," which would close the nearest open tag, but were - * dismissed in favor of explicitly-closing tags. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_PRESUMPTUOUS_TAG = 'STATE_PRESUMPTUOUS_TAG'; - - /** - * Indicates that the parser has found a "funky comment" - * and it's possible to read and modify its modifiable text. - * - * Example: - * - * </%url> - * </{"wp-bit":"query/post-author"}> - * </2> - * - * Funky comments are tag closers with invalid tag names. Note - * that in HTML these are turn into bogus comments. Nonetheless, - * the Tag Processor recognizes them in a stream of HTML and - * exposes them for inspection and modification. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_FUNKY_COMMENT = 'STATE_WP_FUNKY'; - - /** - * Indicates that a comment was created when encountering abruptly-closed HTML comment. - * - * Example: - * - * <!--> - * <!---> - * - * @since 6.5.0 - */ - const COMMENT_AS_ABRUPTLY_CLOSED_COMMENT = 'COMMENT_AS_ABRUPTLY_CLOSED_COMMENT'; - - /** - * Indicates that a comment would be parsed as a CDATA node, - * were HTML to allow CDATA nodes outside of foreign content. - * - * Example: - * - * <![CDATA[This is a CDATA node.]]> - * - * This is an HTML comment, but it looks like a CDATA node. - * - * @since 6.5.0 - */ - const COMMENT_AS_CDATA_LOOKALIKE = 'COMMENT_AS_CDATA_LOOKALIKE'; - - /** - * Indicates that a comment was created when encountering - * normative HTML comment syntax. - * - * Example: - * - * <!-- this is a comment --> - * - * @since 6.5.0 - */ - const COMMENT_AS_HTML_COMMENT = 'COMMENT_AS_HTML_COMMENT'; - - /** - * Indicates that a comment would be parsed as a Processing - * Instruction node, were they to exist within HTML. - * - * Example: - * - * <?wp __( 'Like' ) ?> - * - * This is an HTML comment, but it looks like a CDATA node. - * - * @since 6.5.0 - */ - const COMMENT_AS_PI_NODE_LOOKALIKE = 'COMMENT_AS_PI_NODE_LOOKALIKE'; - - /** - * Indicates that a comment was created when encountering invalid - * HTML input, a so-called "bogus comment." - * - * Example: - * - * <?nothing special> - * <!{nothing special}> - * - * @since 6.5.0 - */ - const COMMENT_AS_INVALID_HTML = 'COMMENT_AS_INVALID_HTML'; -} diff --git a/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-text-replacement-6-5.php b/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-text-replacement-6-5.php deleted file mode 100644 index 6409255833c818..00000000000000 --- a/lib/compat/wordpress-6.5/html-api/class-gutenberg-html-text-replacement-6-5.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Text_Replacement class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.2.0 - */ - -/** - * Core class used by the HTML tag processor as a data structure for replacing - * existing content from start to end, allowing to drastically improve performance. - * - * This class is for internal usage of the WP_HTML_Tag_Processor class. - * - * @access private - * @since 6.2.0 - * @since 6.5.0 Replace `end` with `length` to more closely match `substr()`. - * - * @see WP_HTML_Tag_Processor - */ -class Gutenberg_HTML_Text_Replacement_6_5 { - /** - * Byte offset into document where replacement span begins. - * - * @since 6.2.0 - * - * @var int - */ - public $start; - - /** - * Byte length of span being replaced. - * - * @since 6.5.0 - * - * @var int - */ - public $length; - - /** - * Span of text to insert in document to replace existing content from start to end. - * - * @since 6.2.0 - * - * @var string - */ - public $text; - - /** - * Constructor. - * - * @since 6.2.0 - * - * @param int $start Byte offset into document where replacement span begins. - * @param int $length Byte length of span in document being replaced. - * @param string $text Span of text to insert in document to replace existing content from start to end. - */ - public function __construct( $start, $length, $text ) { - $this->start = $start; - $this->length = $length; - $this->text = $text; - } -} diff --git a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api-directives-processor.php b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api-directives-processor.php deleted file mode 100644 index ba18307002d153..00000000000000 --- a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api-directives-processor.php +++ /dev/null @@ -1,246 +0,0 @@ -<?php -/** - * Interactivity API: WP_Interactivity_API_Directives_Processor class. - * - * @package WordPress - * @subpackage Interactivity API - * @since 6.5.0 - */ - -if ( ! class_exists( 'WP_Interactivity_API_Directives_Processor' ) ) { - /** - * Class used to iterate over the tags of an HTML string and help process the - * directive attributes. - * - * @since 6.5.0 - * - * @access private - */ - final class WP_Interactivity_API_Directives_Processor extends Gutenberg_HTML_Tag_Processor_6_5 { - /** - * List of tags whose closer tag is not visited by the WP_HTML_Tag_Processor. - * - * @since 6.5.0 - * @var string[] - */ - const TAGS_THAT_DONT_VISIT_CLOSER_TAG = array( - 'SCRIPT', - 'IFRAME', - 'NOEMBED', - 'NOFRAMES', - 'STYLE', - 'TEXTAREA', - 'TITLE', - 'XMP', - ); - - /** - * Returns the content between two balanced template tags. - * - * It positions the cursor in the closer tag of the balanced template tag, - * if it exists. - * - * @since 6.5.0 - * - * @access private - * - * @return string|null The content between the current opener template tag and its matching closer tag or null if it - * doesn't find the matching closing tag or the current tag is not a template opener tag. - */ - public function get_content_between_balanced_template_tags() { - if ( 'TEMPLATE' !== $this->get_tag() ) { - return null; - } - - $positions = $this->get_after_opener_tag_and_before_closer_tag_positions(); - if ( ! $positions ) { - return null; - } - list( $after_opener_tag, $before_closer_tag ) = $positions; - - return substr( $this->html, $after_opener_tag, $before_closer_tag - $after_opener_tag ); - } - - /** - * Sets the content between two balanced tags. - * - * @since 6.5.0 - * - * @access private - * - * @param string $new_content The string to replace the content between the matching tags. - * @return bool Whether the content was successfully replaced. - */ - public function set_content_between_balanced_tags( string $new_content ): bool { - $positions = $this->get_after_opener_tag_and_before_closer_tag_positions( true ); - if ( ! $positions ) { - return false; - } - list( $after_opener_tag, $before_closer_tag ) = $positions; - - $this->lexical_updates[] = new Gutenberg_HTML_Text_Replacement_6_5( - $after_opener_tag, - $before_closer_tag - $after_opener_tag, - esc_html( $new_content ) - ); - - return true; - } - - /** - * Appends content after the closing tag of a template tag. - * - * It positions the cursor in the closer tag of the balanced template tag, - * if it exists. - * - * @access private - * - * @param string $new_content The string to append after the closing template tag. - * @return bool Whether the content was successfully appended. - */ - public function append_content_after_template_tag_closer( string $new_content ): bool { - if ( empty( $new_content ) || 'TEMPLATE' !== $this->get_tag() || ! $this->is_tag_closer() ) { - return false; - } - - // Flushes any changes. - $this->get_updated_html(); - - $bookmark = 'append_content_after_template_tag_closer'; - $this->set_bookmark( $bookmark ); - $after_closing_tag = $this->bookmarks[ $bookmark ]->start + $this->bookmarks[ $bookmark ]->length + 1; - $this->release_bookmark( $bookmark ); - - // Appends the new content. - $this->lexical_updates[] = new Gutenberg_HTML_Text_Replacement_6_5( $after_closing_tag, 0, $new_content ); - - return true; - } - - /** - * Gets the positions right after the opener tag and right before the closer - * tag in a balanced tag. - * - * By default, it positions the cursor in the closer tag of the balanced tag. - * If $rewind is true, it seeks back to the opener tag. - * - * @since 6.5.0 - * - * @access private - * - * @param bool $rewind Optional. Whether to seek back to the opener tag after finding the positions. Defaults to false. - * @return array|null Start and end byte position, or null when no balanced tag bookmarks. - */ - private function get_after_opener_tag_and_before_closer_tag_positions( bool $rewind = false ) { - // Flushes any changes. - $this->get_updated_html(); - - $bookmarks = $this->get_balanced_tag_bookmarks(); - if ( ! $bookmarks ) { - return null; - } - list( $opener_tag, $closer_tag ) = $bookmarks; - - $after_opener_tag = $this->bookmarks[ $opener_tag ]->start + $this->bookmarks[ $opener_tag ]->length + 1; - $before_closer_tag = $this->bookmarks[ $closer_tag ]->start; - - if ( $rewind ) { - $this->seek( $opener_tag ); - } - - $this->release_bookmark( $opener_tag ); - $this->release_bookmark( $closer_tag ); - - return array( $after_opener_tag, $before_closer_tag ); - } - - /** - * Returns a pair of bookmarks for the current opener tag and the matching - * closer tag. - * - * It positions the cursor in the closer tag of the balanced tag, if it - * exists. - * - * @since 6.5.0 - * - * @return array|null A pair of bookmarks, or null if there's no matching closing tag. - */ - private function get_balanced_tag_bookmarks() { - static $i = 0; - $opener_tag = 'opener_tag_of_balanced_tag_' . ++$i; - - $this->set_bookmark( $opener_tag ); - if ( ! $this->next_balanced_tag_closer_tag() ) { - $this->release_bookmark( $opener_tag ); - return null; - } - - $closer_tag = 'closer_tag_of_balanced_tag_' . ++$i; - $this->set_bookmark( $closer_tag ); - - return array( $opener_tag, $closer_tag ); - } - - /** - * Finds the matching closing tag for an opening tag. - * - * When called while the processor is on an open tag, it traverses the HTML - * until it finds the matching closer tag, respecting any in-between content, - * including nested tags of the same name. Returns false when called on a - * closer tag, a tag that doesn't have a closer tag (void), a tag that - * doesn't visit the closer tag, or if no matching closing tag was found. - * - * @since 6.5.0 - * - * @access private - * - * @return bool Whether a matching closing tag was found. - */ - public function next_balanced_tag_closer_tag(): bool { - $depth = 0; - $tag_name = $this->get_tag(); - - if ( ! $this->has_and_visits_its_closer_tag() ) { - return false; - } - - while ( $this->next_tag( - array( - 'tag_name' => $tag_name, - 'tag_closers' => 'visit', - ) - ) ) { - if ( ! $this->is_tag_closer() ) { - ++$depth; - continue; - } - - if ( 0 === $depth ) { - return true; - } - - --$depth; - } - - return false; - } - - /** - * Checks whether the current tag has and will visit its matching closer tag. - * - * @since 6.5.0 - * - * @access private - * - * @return bool Whether the current tag has a closer tag. - */ - public function has_and_visits_its_closer_tag(): bool { - $tag_name = $this->get_tag(); - - return null !== $tag_name && ( - ! Gutenberg_HTML_Processor_6_5::is_void( $tag_name ) && - ! in_array( $tag_name, self::TAGS_THAT_DONT_VISIT_CLOSER_TAG, true ) - ); - } - } -} diff --git a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php deleted file mode 100644 index d0661d75857265..00000000000000 --- a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php +++ /dev/null @@ -1,992 +0,0 @@ -<?php -/** - * Interactivity API: WP_Interactivity_API class. - * - * @package WordPress - * @subpackage Interactivity API - * @since 6.5.0 - */ - -if ( ! class_exists( 'WP_Interactivity_API' ) ) { - /** - * Class used to process the Interactivity API on the server. - * - * @since 6.5.0 - */ - final class WP_Interactivity_API { - /** - * Holds the mapping of directive attribute names to their processor methods. - * - * @since 6.5.0 - * @var array - */ - private static $directive_processors = array( - 'data-wp-interactive' => 'data_wp_interactive_processor', - 'data-wp-router-region' => 'data_wp_router_region_processor', - 'data-wp-context' => 'data_wp_context_processor', - 'data-wp-bind' => 'data_wp_bind_processor', - 'data-wp-class' => 'data_wp_class_processor', - 'data-wp-style' => 'data_wp_style_processor', - 'data-wp-text' => 'data_wp_text_processor', - /* - * `data-wp-each` needs to be processed in the last place because it moves - * the cursor to the end of the processed items to prevent them to be - * processed twice. - */ - 'data-wp-each' => 'data_wp_each_processor', - ); - - /** - * Holds the initial state of the different Interactivity API stores. - * - * This state is used during the server directive processing. Then, it is - * serialized and sent to the client as part of the interactivity data to be - * recovered during the hydration of the client interactivity stores. - * - * @since 6.5.0 - * @var array - */ - private $state_data = array(); - - /** - * Holds the configuration required by the different Interactivity API stores. - * - * This configuration is serialized and sent to the client as part of the - * interactivity data and can be accessed by the client interactivity stores. - * - * @since 6.5.0 - * @var array - */ - private $config_data = array(); - - /** - * Flag that indicates whether the `data-wp-router-region` directive has - * been found in the HTML and processed. - * - * The value is saved in a private property of the WP_Interactivity_API - * instance instead of using a static variable inside the processor - * function, which would hold the same value for all instances - * independently of whether they have processed any - * `data-wp-router-region` directive or not. - * - * @since 6.5.0 - * @var bool - */ - private $has_processed_router_region = false; - - /** - * Gets and/or sets the initial state of an Interactivity API store for a - * given namespace. - * - * If state for that store namespace already exists, it merges the new - * provided state with the existing one. - * - * @since 6.5.0 - * - * @param string $store_namespace The unique store namespace identifier. - * @param array $state Optional. The array that will be merged with the existing state for the specified - * store namespace. - * @return array The current state for the specified store namespace. This will be the updated state if a $state - * argument was provided. - */ - public function state( string $store_namespace, array $state = array() ): array { - if ( ! isset( $this->state_data[ $store_namespace ] ) ) { - $this->state_data[ $store_namespace ] = array(); - } - if ( is_array( $state ) ) { - $this->state_data[ $store_namespace ] = array_replace_recursive( - $this->state_data[ $store_namespace ], - $state - ); - } - return $this->state_data[ $store_namespace ]; - } - - /** - * Gets and/or sets the configuration of the Interactivity API for a given - * store namespace. - * - * If configuration for that store namespace exists, it merges the new - * provided configuration with the existing one. - * - * @since 6.5.0 - * - * @param string $store_namespace The unique store namespace identifier. - * @param array $config Optional. The array that will be merged with the existing configuration for the - * specified store namespace. - * @return array The configuration for the specified store namespace. This will be the updated configuration if a - * $config argument was provided. - */ - public function config( string $store_namespace, array $config = array() ): array { - if ( ! isset( $this->config_data[ $store_namespace ] ) ) { - $this->config_data[ $store_namespace ] = array(); - } - if ( is_array( $config ) ) { - $this->config_data[ $store_namespace ] = array_replace_recursive( - $this->config_data[ $store_namespace ], - $config - ); - } - return $this->config_data[ $store_namespace ]; - } - - /** - * Prints the serialized client-side interactivity data. - * - * Encodes the config and initial state into JSON and prints them inside a - * script tag of type "application/json". Once in the browser, the state will - * be parsed and used to hydrate the client-side interactivity stores and the - * configuration will be available using a `getConfig` utility. - * - * @since 6.5.0 - */ - public function print_client_interactivity_data() { - if ( empty( $this->state_data ) && empty( $this->config_data ) ) { - return; - } - - $interactivity_data = array(); - - $config = array(); - foreach ( $this->config_data as $key => $value ) { - if ( ! empty( $value ) ) { - $config[ $key ] = $value; - } - } - if ( ! empty( $config ) ) { - $interactivity_data['config'] = $config; - } - - $state = array(); - foreach ( $this->state_data as $key => $value ) { - if ( ! empty( $value ) ) { - $state[ $key ] = $value; - } - } - if ( ! empty( $state ) ) { - $interactivity_data['state'] = $state; - } - - if ( ! empty( $interactivity_data ) ) { - wp_print_inline_script_tag( - wp_json_encode( - $interactivity_data, - JSON_HEX_TAG | JSON_HEX_AMP - ), - array( - 'type' => 'application/json', - 'id' => 'wp-interactivity-data', - ) - ); - } - } - - /** - * Registers the `@wordpress/interactivity` script modules. - * - * @since 6.5.0 - */ - public function register_script_modules() { - $suffix = wp_scripts_get_suffix(); - - wp_register_script_module( - '@wordpress/interactivity', - includes_url( "js/dist/interactivity$suffix.js" ) - ); - - wp_register_script_module( - '@wordpress/interactivity-router', - includes_url( "js/dist/interactivity-router$suffix.js" ), - array( '@wordpress/interactivity' ) - ); - } - - /** - * Adds the necessary hooks for the Interactivity API. - * - * @since 6.5.0 - */ - public function add_hooks() { - add_action( 'wp_enqueue_scripts', array( $this, 'register_script_modules' ) ); - add_action( 'wp_footer', array( $this, 'print_client_interactivity_data' ) ); - } - - /** - * Processes the interactivity directives contained within the HTML content - * and updates the markup accordingly. - * - * @since 6.5.0 - * - * @param string $html The HTML content to process. - * @return string The processed HTML content. It returns the original content when the HTML contains unbalanced tags. - */ - public function process_directives( string $html ): string { - if ( ! str_contains( $html, 'data-wp-' ) ) { - return $html; - } - $context_stack = array(); - $namespace_stack = array(); - $result = $this->process_directives_args( $html, $context_stack, $namespace_stack ); - return null === $result ? $html : $result; - } - - /** - * Processes the interactivity directives contained within the HTML content - * and updates the markup accordingly. - * - * It needs the context and namespace stacks to be passed by reference, and - * it returns null if the HTML contains unbalanced tags. - * - * @since 6.5.0 - * - * @param string $html The HTML content to process. - * @param array $context_stack The reference to the array used to keep track of contexts during processing. - * @param array $namespace_stack The reference to the array used to manage namespaces during processing. - * @return string|null The processed HTML content. It returns null when the HTML contains unbalanced tags. - */ - private function process_directives_args( string $html, array &$context_stack, array &$namespace_stack ) { - $p = new WP_Interactivity_API_Directives_Processor( $html ); - $tag_stack = array(); - $unbalanced = false; - - $directive_processor_prefixes = array_keys( self::$directive_processors ); - $directive_processor_prefixes_reversed = array_reverse( $directive_processor_prefixes ); - - while ( $p->next_tag( array( 'tag_closers' => 'visit' ) ) ) { - $tag_name = $p->get_tag(); - - if ( 'SVG' === $tag_name || 'MATH' === $tag_name ) { - $unbalanced = true; - break; - } - - if ( $p->is_tag_closer() ) { - list( $opening_tag_name, $directives_prefixes ) = end( $tag_stack ); - - if ( 0 === count( $tag_stack ) || $opening_tag_name !== $tag_name ) { - - /* - * If the tag stack is empty or the matching opening tag is not the - * same than the closing tag, it means the HTML is unbalanced and it - * stops processing it. - */ - $unbalanced = true; - break; - } else { - // Remove the last tag from the stack. - array_pop( $tag_stack ); - } - } else { - if ( 0 !== count( $p->get_attribute_names_with_prefix( 'data-wp-each-child' ) ) ) { - /* - * If the tag has a `data-wp-each-child` directive, jump to its closer - * tag because those tags have already been processed. - */ - $p->next_balanced_tag_closer_tag(); - continue; - } else { - $directives_prefixes = array(); - - // Checks if there is a server directive processor registered for each directive. - foreach ( $p->get_attribute_names_with_prefix( 'data-wp-' ) as $attribute_name ) { - list( $directive_prefix ) = $this->extract_prefix_and_suffix( $attribute_name ); - if ( array_key_exists( $directive_prefix, self::$directive_processors ) ) { - $directives_prefixes[] = $directive_prefix; - } - } - - /* - * If this tag will visit its closer tag, it adds it to the tag stack - * so it can process its closing tag and check for unbalanced tags. - */ - if ( $p->has_and_visits_its_closer_tag() ) { - $tag_stack[] = array( $tag_name, $directives_prefixes ); - } - } - } - /* - * If the matching opener tag didn't have any directives, it can skip the - * processing. - */ - if ( 0 === count( $directives_prefixes ) ) { - continue; - } - - // Directive processing might be different depending on if it is entering the tag or exiting it. - $modes = array( - 'enter' => ! $p->is_tag_closer(), - 'exit' => $p->is_tag_closer() || ! $p->has_and_visits_its_closer_tag(), - ); - foreach ( $modes as $mode => $should_run ) { - if ( ! $should_run ) { - continue; - } - - /* - * Sorts the attributes by the order of the `directives_processor` array - * and checks what directives are present in this element. - */ - $existing_directives_prefixes = array_intersect( - 'enter' === $mode ? $directive_processor_prefixes : $directive_processor_prefixes_reversed, - $directives_prefixes - ); - foreach ( $existing_directives_prefixes as $directive_prefix ) { - $func = is_array( self::$directive_processors[ $directive_prefix ] ) - ? self::$directive_processors[ $directive_prefix ] - : array( $this, self::$directive_processors[ $directive_prefix ] ); - - call_user_func_array( - $func, - array( $p, $mode, &$context_stack, &$namespace_stack, &$tag_stack ) - ); - } - } - } - - /* - * It returns null if the HTML is unbalanced because unbalanced HTML is - * not safe to process. In that case, the Interactivity API runtime will - * update the HTML on the client side during the hydration. - */ - return $unbalanced || 0 < count( $tag_stack ) ? null : $p->get_updated_html(); - } - - /** - * Evaluates the reference path passed to a directive based on the current - * store namespace, state and context. - * - * @since 6.5.0 - * - * @param string|true $directive_value The directive attribute value string or `true` when it's a boolean attribute. - * @param string $default_namespace The default namespace to use if none is explicitly defined in the directive - * value. - * @param array|false $context The current context for evaluating the directive or false if there is no - * context. - * @return mixed|null The result of the evaluation. Null if the reference path doesn't exist. - */ - private function evaluate( $directive_value, string $default_namespace, $context = false ) { - list( $ns, $path ) = $this->extract_directive_value( $directive_value, $default_namespace ); - if ( empty( $path ) ) { - return null; - } - - $store = array( - 'state' => $this->state_data[ $ns ] ?? array(), - 'context' => $context[ $ns ] ?? array(), - ); - - // Checks if the reference path is preceded by a negation operator (!). - $should_negate_value = '!' === $path[0]; - $path = $should_negate_value ? substr( $path, 1 ) : $path; - - // Extracts the value from the store using the reference path. - $path_segments = explode( '.', $path ); - $current = $store; - foreach ( $path_segments as $path_segment ) { - if ( isset( $current[ $path_segment ] ) ) { - $current = $current[ $path_segment ]; - } else { - return null; - } - } - - // Returns the opposite if it contains a negation operator (!). - return $should_negate_value ? ! $current : $current; - } - - /** - * Extracts the directive attribute name to separate and return the directive - * prefix and an optional suffix. - * - * The suffix is the string after the first double hyphen and the prefix is - * everything that comes before the suffix. - * - * Example: - * - * extract_prefix_and_suffix( 'data-wp-interactive' ) => array( 'data-wp-interactive', null ) - * extract_prefix_and_suffix( 'data-wp-bind--src' ) => array( 'data-wp-bind', 'src' ) - * extract_prefix_and_suffix( 'data-wp-foo--and--bar' ) => array( 'data-wp-foo', 'and--bar' ) - * - * @since 6.5.0 - * - * @param string $directive_name The directive attribute name. - * @return array An array containing the directive prefix and optional suffix. - */ - private function extract_prefix_and_suffix( string $directive_name ): array { - return explode( '--', $directive_name, 2 ); - } - - /** - * Parses and extracts the namespace and reference path from the given - * directive attribute value. - * - * If the value doesn't contain an explicit namespace, it returns the - * default one. If the value contains a JSON object instead of a reference - * path, the function tries to parse it and return the resulting array. If - * the value contains strings that represent booleans ("true" and "false"), - * numbers ("1" and "1.2") or "null", the function also transform them to - * regular booleans, numbers and `null`. - * - * Example: - * - * extract_directive_value( 'actions.foo', 'myPlugin' ) => array( 'myPlugin', 'actions.foo' ) - * extract_directive_value( 'otherPlugin::actions.foo', 'myPlugin' ) => array( 'otherPlugin', 'actions.foo' ) - * extract_directive_value( '{ "isOpen": false }', 'myPlugin' ) => array( 'myPlugin', array( 'isOpen' => false ) ) - * extract_directive_value( 'otherPlugin::{ "isOpen": false }', 'myPlugin' ) => array( 'otherPlugin', array( 'isOpen' => false ) ) - * - * @since 6.5.0 - * - * @param string|true $directive_value The directive attribute value. It can be `true` when it's a boolean - * attribute. - * @param string|null $default_namespace Optional. The default namespace if none is explicitly defined. - * @return array An array containing the namespace in the first item and the JSON, the reference path, or null on the - * second item. - */ - private function extract_directive_value( $directive_value, $default_namespace = null ): array { - if ( empty( $directive_value ) || is_bool( $directive_value ) ) { - return array( $default_namespace, null ); - } - - // Replaces the value and namespace if there is a namespace in the value. - if ( 1 === preg_match( '/^([\w\-_\/]+)::./', $directive_value ) ) { - list($default_namespace, $directive_value) = explode( '::', $directive_value, 2 ); - } - - /* - * Tries to decode the value as a JSON object. If it fails and the value - * isn't `null`, it returns the value as it is. Otherwise, it returns the - * decoded JSON or null for the string `null`. - */ - $decoded_json = json_decode( $directive_value, true ); - if ( null !== $decoded_json || 'null' === $directive_value ) { - $directive_value = $decoded_json; - } - - return array( $default_namespace, $directive_value ); - } - - /** - * Transforms a kebab-case string to camelCase. - * - * @param string $str The kebab-case string to transform to camelCase. - * @return string The transformed camelCase string. - */ - private function kebab_to_camel_case( string $str ): string { - return lcfirst( - preg_replace_callback( - '/(-)([a-z])/', - function ( $matches ) { - return strtoupper( $matches[2] ); - }, - strtolower( rtrim( $str, '-' ) ) - ) - ); - } - - /** - * Processes the `data-wp-interactive` directive. - * - * It adds the default store namespace defined in the directive value to the - * stack so that it's available for the nested interactivity elements. - * - * @since 6.5.0 - * - * @param WP_Interactivity_API_Directives_Processor $p The directives processor instance. - * @param string $mode Whether the processing is entering or exiting the tag. - * @param array $context_stack The reference to the context stack. - * @param array $namespace_stack The reference to the store namespace stack. - */ - private function data_wp_interactive_processor( WP_Interactivity_API_Directives_Processor $p, string $mode, array &$context_stack, array &$namespace_stack ) { - // When exiting tags, it removes the last namespace from the stack. - if ( 'exit' === $mode ) { - array_pop( $namespace_stack ); - return; - } - - // Tries to decode the `data-wp-interactive` attribute value. - $attribute_value = $p->get_attribute( 'data-wp-interactive' ); - - /* - * Pushes the newly defined namespace or the current one if the - * `data-wp-interactive` definition was invalid or does not contain a - * namespace. It does so because the function pops out the current namespace - * from the stack whenever it finds a `data-wp-interactive`'s closing tag, - * independently of whether the previous `data-wp-interactive` definition - * contained a valid namespace. - */ - $new_namespace = null; - if ( is_string( $attribute_value ) && ! empty( $attribute_value ) ) { - $decoded_json = json_decode( $attribute_value, true ); - if ( is_array( $decoded_json ) ) { - $new_namespace = $decoded_json['namespace'] ?? null; - } else { - $new_namespace = $attribute_value; - } - } - $namespace_stack[] = ( $new_namespace && 1 === preg_match( '/^([\w\-_\/]+)/', $new_namespace ) ) - ? $new_namespace - : end( $namespace_stack ); - } - - /** - * Processes the `data-wp-context` directive. - * - * It adds the context defined in the directive value to the stack so that - * it's available for the nested interactivity elements. - * - * @since 6.5.0 - * - * @param WP_Interactivity_API_Directives_Processor $p The directives processor instance. - * @param string $mode Whether the processing is entering or exiting the tag. - * @param array $context_stack The reference to the context stack. - * @param array $namespace_stack The reference to the store namespace stack. - */ - private function data_wp_context_processor( WP_Interactivity_API_Directives_Processor $p, string $mode, array &$context_stack, array &$namespace_stack ) { - // When exiting tags, it removes the last context from the stack. - if ( 'exit' === $mode ) { - array_pop( $context_stack ); - return; - } - - $attribute_value = $p->get_attribute( 'data-wp-context' ); - $namespace_value = end( $namespace_stack ); - - // Separates the namespace from the context JSON object. - list( $namespace_value, $decoded_json ) = is_string( $attribute_value ) && ! empty( $attribute_value ) - ? $this->extract_directive_value( $attribute_value, $namespace_value ) - : array( $namespace_value, null ); - - /* - * If there is a namespace, it adds a new context to the stack merging the - * previous context with the new one. - */ - if ( is_string( $namespace_value ) ) { - $context_stack[] = array_replace_recursive( - end( $context_stack ) !== false ? end( $context_stack ) : array(), - array( $namespace_value => is_array( $decoded_json ) ? $decoded_json : array() ) - ); - } else { - /* - * If there is no namespace, it pushes the current context to the stack. - * It needs to do so because the function pops out the current context - * from the stack whenever it finds a `data-wp-context`'s closing tag. - */ - $context_stack[] = end( $context_stack ); - } - } - - /** - * Processes the `data-wp-bind` directive. - * - * It updates or removes the bound attributes based on the evaluation of its - * associated reference. - * - * @since 6.5.0 - * - * @param WP_Interactivity_API_Directives_Processor $p The directives processor instance. - * @param string $mode Whether the processing is entering or exiting the tag. - * @param array $context_stack The reference to the context stack. - * @param array $namespace_stack The reference to the store namespace stack. - */ - private function data_wp_bind_processor( WP_Interactivity_API_Directives_Processor $p, string $mode, array &$context_stack, array &$namespace_stack ) { - if ( 'enter' === $mode ) { - $all_bind_directives = $p->get_attribute_names_with_prefix( 'data-wp-bind--' ); - - foreach ( $all_bind_directives as $attribute_name ) { - list( , $bound_attribute ) = $this->extract_prefix_and_suffix( $attribute_name ); - if ( empty( $bound_attribute ) ) { - return; - } - - $attribute_value = $p->get_attribute( $attribute_name ); - $result = $this->evaluate( $attribute_value, end( $namespace_stack ), end( $context_stack ) ); - - if ( null !== $result && ( - false !== $result || - ( strlen( $bound_attribute ) > 5 && '-' === $bound_attribute[4] ) - ) ) { - /* - * If the result of the evaluation is a boolean and the attribute is - * `aria-` or `data-, convert it to a string "true" or "false". It - * follows the exact same logic as Preact because it needs to - * replicate what Preact will later do in the client: - * https://github.com/preactjs/preact/blob/ea49f7a0f9d1ff2c98c0bdd66aa0cbc583055246/src/diff/props.js#L131C24-L136 - */ - if ( - is_bool( $result ) && - ( strlen( $bound_attribute ) > 5 && '-' === $bound_attribute[4] ) - ) { - $result = $result ? 'true' : 'false'; - } - $p->set_attribute( $bound_attribute, $result ); - } else { - $p->remove_attribute( $bound_attribute ); - } - } - } - } - - /** - * Processes the `data-wp-class` directive. - * - * It adds or removes CSS classes in the current HTML element based on the - * evaluation of its associated references. - * - * @since 6.5.0 - * - * @param WP_Interactivity_API_Directives_Processor $p The directives processor instance. - * @param string $mode Whether the processing is entering or exiting the tag. - * @param array $context_stack The reference to the context stack. - * @param array $namespace_stack The reference to the store namespace stack. - */ - private function data_wp_class_processor( WP_Interactivity_API_Directives_Processor $p, string $mode, array &$context_stack, array &$namespace_stack ) { - if ( 'enter' === $mode ) { - $all_class_directives = $p->get_attribute_names_with_prefix( 'data-wp-class--' ); - - foreach ( $all_class_directives as $attribute_name ) { - list( , $class_name ) = $this->extract_prefix_and_suffix( $attribute_name ); - if ( empty( $class_name ) ) { - return; - } - - $attribute_value = $p->get_attribute( $attribute_name ); - $result = $this->evaluate( $attribute_value, end( $namespace_stack ), end( $context_stack ) ); - - if ( $result ) { - $p->add_class( $class_name ); - } else { - $p->remove_class( $class_name ); - } - } - } - } - - /** - * Processes the `data-wp-style` directive. - * - * It updates the style attribute value of the current HTML element based on - * the evaluation of its associated references. - * - * @since 6.5.0 - * - * @param WP_Interactivity_API_Directives_Processor $p The directives processor instance. - * @param string $mode Whether the processing is entering or exiting the tag. - * @param array $context_stack The reference to the context stack. - * @param array $namespace_stack The reference to the store namespace stack. - */ - private function data_wp_style_processor( WP_Interactivity_API_Directives_Processor $p, string $mode, array &$context_stack, array &$namespace_stack ) { - if ( 'enter' === $mode ) { - $all_style_attributes = $p->get_attribute_names_with_prefix( 'data-wp-style--' ); - - foreach ( $all_style_attributes as $attribute_name ) { - list( , $style_property ) = $this->extract_prefix_and_suffix( $attribute_name ); - if ( empty( $style_property ) ) { - continue; - } - - $directive_attribute_value = $p->get_attribute( $attribute_name ); - $style_property_value = $this->evaluate( $directive_attribute_value, end( $namespace_stack ), end( $context_stack ) ); - $style_attribute_value = $p->get_attribute( 'style' ); - $style_attribute_value = ( $style_attribute_value && ! is_bool( $style_attribute_value ) ) ? $style_attribute_value : ''; - - /* - * Checks first if the style property is not falsy and the style - * attribute value is not empty because if it is, it doesn't need to - * update the attribute value. - */ - if ( $style_property_value || $style_attribute_value ) { - $style_attribute_value = $this->merge_style_property( $style_attribute_value, $style_property, $style_property_value ); - /* - * If the style attribute value is not empty, it sets it. Otherwise, - * it removes it. - */ - if ( ! empty( $style_attribute_value ) ) { - $p->set_attribute( 'style', $style_attribute_value ); - } else { - $p->remove_attribute( 'style' ); - } - } - } - } - } - - /** - * Merges an individual style property in the `style` attribute of an HTML - * element, updating or removing the property when necessary. - * - * If a property is modified, the old one is removed and the new one is added - * at the end of the list. - * - * @since 6.5.0 - * - * Example: - * - * merge_style_property( 'color:green;', 'color', 'red' ) => 'color:red;' - * merge_style_property( 'background:green;', 'color', 'red' ) => 'background:green;color:red;' - * merge_style_property( 'color:green;', 'color', null ) => '' - * - * @param string $style_attribute_value The current style attribute value. - * @param string $style_property_name The style property name to set. - * @param string|false|null $style_property_value The value to set for the style property. With false, null or an - * empty string, it removes the style property. - * @return string The new style attribute value after the specified property has been added, updated or removed. - */ - private function merge_style_property( string $style_attribute_value, string $style_property_name, $style_property_value ): string { - $style_assignments = explode( ';', $style_attribute_value ); - $result = array(); - $style_property_value = ! empty( $style_property_value ) ? rtrim( trim( $style_property_value ), ';' ) : null; - $new_style_property = $style_property_value ? $style_property_name . ':' . $style_property_value . ';' : ''; - - // Generates an array with all the properties but the modified one. - foreach ( $style_assignments as $style_assignment ) { - if ( empty( trim( $style_assignment ) ) ) { - continue; - } - list( $name, $value ) = explode( ':', $style_assignment ); - if ( trim( $name ) !== $style_property_name ) { - $result[] = trim( $name ) . ':' . trim( $value ) . ';'; - } - } - - // Adds the new/modified property at the end of the list. - $result[] = $new_style_property; - - return implode( '', $result ); - } - - /** - * Processes the `data-wp-text` directive. - * - * It updates the inner content of the current HTML element based on the - * evaluation of its associated reference. - * - * @since 6.5.0 - * - * @param WP_Interactivity_API_Directives_Processor $p The directives processor instance. - * @param string $mode Whether the processing is entering or exiting the tag. - * @param array $context_stack The reference to the context stack. - * @param array $namespace_stack The reference to the store namespace stack. - */ - private function data_wp_text_processor( WP_Interactivity_API_Directives_Processor $p, string $mode, array &$context_stack, array &$namespace_stack ) { - if ( 'enter' === $mode ) { - $attribute_value = $p->get_attribute( 'data-wp-text' ); - $result = $this->evaluate( $attribute_value, end( $namespace_stack ), end( $context_stack ) ); - - /* - * Follows the same logic as Preact in the client and only changes the - * content if the value is a string or a number. Otherwise, it removes the - * content. - */ - if ( is_string( $result ) || is_numeric( $result ) ) { - $p->set_content_between_balanced_tags( esc_html( $result ) ); - } else { - $p->set_content_between_balanced_tags( '' ); - } - } - } - - /** - * Returns the CSS styles for animating the top loading bar in the router. - * - * @since 6.5.0 - * - * @return string The CSS styles for the router's top loading bar animation. - */ - private function get_router_animation_styles(): string { - return <<<CSS - .wp-interactivity-router-loading-bar { - position: fixed; - top: 0; - left: 0; - margin: 0; - padding: 0; - width: 100vw; - max-width: 100vw !important; - height: 4px; - background-color: #000; - opacity: 0 - } - .wp-interactivity-router-loading-bar.start-animation { - animation: wp-interactivity-router-loading-bar-start-animation 30s cubic-bezier(0.03, 0.5, 0, 1) forwards - } - .wp-interactivity-router-loading-bar.finish-animation { - animation: wp-interactivity-router-loading-bar-finish-animation 300ms ease-in - } - @keyframes wp-interactivity-router-loading-bar-start-animation { - 0% { transform: scaleX(0); transform-origin: 0 0; opacity: 1 } - 100% { transform: scaleX(1); transform-origin: 0 0; opacity: 1 } - } - @keyframes wp-interactivity-router-loading-bar-finish-animation { - 0% { opacity: 1 } - 50% { opacity: 1 } - 100% { opacity: 0 } - } -CSS; - } - - /** - * Outputs the markup for the top loading indicator and the screen reader - * notifications during client-side navigations. - * - * This method prints a div element representing a loading bar visible during - * navigation, as well as an aria-live region that can be read by screen - * readers to announce navigation status. - * - * @since 6.5.0 - */ - public function print_router_loading_and_screen_reader_markup() { - echo <<<HTML - <div - class="wp-interactivity-router-loading-bar" - data-wp-interactive="core/router" - data-wp-class--start-animation="state.navigation.hasStarted" - data-wp-class--finish-animation="state.navigation.hasFinished" - ></div> - <div - class="screen-reader-text" - aria-live="polite" - data-wp-interactive="core/router" - data-wp-text="state.navigation.message" - ></div> -HTML; - } - - /** - * Processes the `data-wp-router-region` directive. - * - * It renders in the footer a set of HTML elements to notify users about - * client-side navigations. More concretely, the elements added are 1) a - * top loading bar to visually inform that a navigation is in progress - * and 2) an `aria-live` region for accessible navigation announcements. - * - * @since 6.5.0 - * - * @param WP_Interactivity_API_Directives_Processor $p The directives processor instance. - * @param string $mode Whether the processing is entering or exiting the tag. - */ - private function data_wp_router_region_processor( WP_Interactivity_API_Directives_Processor $p, string $mode ) { - if ( 'enter' === $mode && ! $this->has_processed_router_region ) { - $this->has_processed_router_region = true; - - // Initialize the `core/router` store. - $this->state( - 'core/router', - array( - 'navigation' => array( - 'texts' => array( - 'loading' => __( 'Loading page, please wait.' ), - 'loaded' => __( 'Page Loaded.' ), - ), - ), - ) - ); - - // Enqueues as an inline style. - wp_register_style( 'wp-interactivity-router-animations', false ); - wp_add_inline_style( 'wp-interactivity-router-animations', $this->get_router_animation_styles() ); - wp_enqueue_style( 'wp-interactivity-router-animations' ); - - // Adds the necessary markup to the footer. - add_action( 'wp_footer', array( $this, 'print_router_loading_and_screen_reader_markup' ) ); - } - } - - /** - * Processes the `data-wp-each` directive. - * - * This directive gets an array passed as reference and iterates over it - * generating new content for each item based on the inner markup of the - * `template` tag. - * - * @since 6.5.0 - * - * @param WP_Interactivity_API_Directives_Processor $p The directives processor instance. - * @param string $mode Whether the processing is entering or exiting the tag. - * @param array $context_stack The reference to the context stack. - * @param array $namespace_stack The reference to the store namespace stack. - * @param array $tag_stack The reference to the tag stack. - */ - private function data_wp_each_processor( WP_Interactivity_API_Directives_Processor $p, string $mode, array &$context_stack, array &$namespace_stack, array &$tag_stack ) { - if ( 'enter' === $mode && 'TEMPLATE' === $p->get_tag() ) { - $attribute_name = $p->get_attribute_names_with_prefix( 'data-wp-each' )[0]; - $extracted_suffix = $this->extract_prefix_and_suffix( $attribute_name ); - $item_name = isset( $extracted_suffix[1] ) ? $this->kebab_to_camel_case( $extracted_suffix[1] ) : 'item'; - $attribute_value = $p->get_attribute( $attribute_name ); - $result = $this->evaluate( $attribute_value, end( $namespace_stack ), end( $context_stack ) ); - - // Gets the content between the template tags and leaves the cursor in the closer tag. - $inner_content = $p->get_content_between_balanced_template_tags(); - - // Checks if there is a manual server-side directive processing. - $template_end = 'data-wp-each: template end'; - $p->set_bookmark( $template_end ); - $p->next_tag(); - $manual_sdp = $p->get_attribute( 'data-wp-each-child' ); - $p->seek( $template_end ); // Rewinds to the template closer tag. - $p->release_bookmark( $template_end ); - - /* - * It doesn't process in these situations: - * - Manual server-side directive processing. - * - Empty or non-array values. - * - Associative arrays because those are deserialized as objects in JS. - * - Templates that contain top-level texts because those texts can't be - * identified and removed in the client. - */ - if ( - $manual_sdp || - empty( $result ) || - ! is_array( $result ) || - ! array_is_list( $result ) || - ! str_starts_with( trim( $inner_content ), '<' ) || - ! str_ends_with( trim( $inner_content ), '>' ) - ) { - array_pop( $tag_stack ); - return; - } - - // Extracts the namespace from the directive attribute value. - $namespace_value = end( $namespace_stack ); - list( $namespace_value ) = is_string( $attribute_value ) && ! empty( $attribute_value ) - ? $this->extract_directive_value( $attribute_value, $namespace_value ) - : array( $namespace_value, null ); - - // Processes the inner content for each item of the array. - $processed_content = ''; - foreach ( $result as $item ) { - // Creates a new context that includes the current item of the array. - $context_stack[] = array_replace_recursive( - end( $context_stack ) !== false ? end( $context_stack ) : array(), - array( $namespace_value => array( $item_name => $item ) ) - ); - - // Processes the inner content with the new context. - $processed_item = $this->process_directives_args( $inner_content, $context_stack, $namespace_stack ); - - if ( null === $processed_item ) { - // If the HTML is unbalanced, stop processing it. - array_pop( $context_stack ); - return; - } - - // Adds the `data-wp-each-child` to each top-level tag. - $i = new WP_Interactivity_API_Directives_Processor( $processed_item ); - while ( $i->next_tag() ) { - $i->set_attribute( 'data-wp-each-child', true ); - $i->next_balanced_tag_closer_tag(); - } - $processed_content .= $i->get_updated_html(); - - // Removes the current context from the stack. - array_pop( $context_stack ); - } - - // Appends the processed content after the tag closer of the template. - $p->append_content_after_template_tag_closer( $processed_content ); - - // Pops the last tag because it skipped the closing tag of the template tag. - array_pop( $tag_stack ); - } - } - } -} diff --git a/lib/compat/wordpress-6.5/interactivity-api/interactivity-api.php b/lib/compat/wordpress-6.5/interactivity-api/interactivity-api.php deleted file mode 100644 index 20e4365a48b6a9..00000000000000 --- a/lib/compat/wordpress-6.5/interactivity-api/interactivity-api.php +++ /dev/null @@ -1,205 +0,0 @@ -<?php -/** - * Interactivity API: Functions and hooks - * - * @package WordPress - * @subpackage Interactivity API - * @since 6.5.0 - */ - -if ( ! function_exists( 'wp_interactivity_process_directives_of_interactive_blocks' ) ) { - /** - * Processes the directives on the rendered HTML of the interactive blocks. - * - * This processes only one root interactive block at a time because the - * rendered HTML of that block contains the rendered HTML of all its inner - * blocks, including any interactive block. It does so by ignoring all the - * interactive inner blocks until the root interactive block is processed. - * - * @since 6.5.0 - * - * @param array $parsed_block The parsed block. - * @return array The same parsed block. - */ - function wp_interactivity_process_directives_of_interactive_blocks( array $parsed_block ): array { - static $root_interactive_block = null; - - /* - * Checks whether a root interactive block is already annotated for - * processing, and if it is, it ignores the subsequent ones. - */ - if ( null === $root_interactive_block ) { - $block_name = $parsed_block['blockName']; - $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block_name ); - - if ( - isset( $block_name ) && - ( ( isset( $block_type->supports['interactivity'] ) && true === $block_type->supports['interactivity'] ) || - ( isset( $block_type->supports['interactivity']['interactive'] ) && true === $block_type->supports['interactivity']['interactive'] ) ) - ) { - // Annotates the root interactive block for processing. - $root_interactive_block = array( $block_name, $parsed_block ); - - /* - * Adds a filter to process the root interactive block once it has - * finished rendering. - */ - $process_interactive_blocks = static function ( string $content, array $parsed_block ) use ( &$root_interactive_block, &$process_interactive_blocks ): string { - // Checks whether the current block is the root interactive block. - list($root_block_name, $root_parsed_block) = $root_interactive_block; - if ( $root_block_name === $parsed_block['blockName'] && $parsed_block === $root_parsed_block ) { - // The root interactive blocks has finished rendering, process it. - $content = wp_interactivity_process_directives( $content ); - // Removes the filter and reset the root interactive block. - remove_filter( 'render_block_' . $parsed_block['blockName'], $process_interactive_blocks ); - $root_interactive_block = null; - } - return $content; - }; - - /* - * Uses a priority of 100 to ensure that other filters can add additional - * directives before the processing starts. - */ - add_filter( 'render_block_' . $block_name, $process_interactive_blocks, 100, 2 ); - } - } - - return $parsed_block; - } - /* - * Uses a priority of 100 to ensure that other filters can edit $parsed_block - * without crashing the SSR. - */ - add_filter( 'render_block_data', 'wp_interactivity_process_directives_of_interactive_blocks', 100 ); -} - -if ( ! function_exists( 'wp_interactivity' ) ) { - /** - * Retrieves the main WP_Interactivity_API instance. - * - * It provides access to the WP_Interactivity_API instance, creating one if it - * doesn't exist yet. - * - * @since 6.5.0 - * - * @global WP_Interactivity_API $wp_interactivity - * - * @return WP_Interactivity_API The main WP_Interactivity_API instance. - */ - function wp_interactivity(): WP_Interactivity_API { - global $wp_interactivity; - if ( ! ( $wp_interactivity instanceof WP_Interactivity_API ) ) { - $wp_interactivity = new WP_Interactivity_API(); - } - return $wp_interactivity; - } - - wp_interactivity()->add_hooks(); -} - -if ( ! function_exists( 'wp_interactivity_process_directives' ) ) { - /** - * Processes the interactivity directives contained within the HTML content - * and updates the markup accordingly. - * - * @since 6.5.0 - * - * @param string $html The HTML content to process. - * @return string The processed HTML content. It returns the original content when the HTML contains unbalanced tags. - */ - function wp_interactivity_process_directives( string $html ): string { - return wp_interactivity()->process_directives( $html ); - } -} - -if ( ! function_exists( 'wp_interactivity_state' ) ) { - /** - * Gets and/or sets the initial state of an Interactivity API store for a - * given namespace. - * - * If state for that store namespace already exists, it merges the new - * provided state with the existing one. - * - * @since 6.5.0 - * - * @param string $store_namespace The unique store namespace identifier. - * @param array $state Optional. The array that will be merged with the existing state for the specified - * store namespace. - * @return array The state for the specified store namespace. This will be the updated state if a $state argument was - * provided. - */ - function wp_interactivity_state( string $store_namespace, array $state = array() ): array { - return wp_interactivity()->state( $store_namespace, $state ); - } -} - -if ( ! function_exists( 'wp_interactivity_config' ) ) { - /** - * Gets and/or sets the configuration of the Interactivity API for a given - * store namespace. - * - * If configuration for that store namespace exists, it merges the new - * provided configuration with the existing one. - * - * @since 6.5.0 - * - * @param string $store_namespace The unique store namespace identifier. - * @param array $config Optional. The array that will be merged with the existing configuration for the - * specified store namespace. - * @return array The configuration for the specified store namespace. This will be the updated configuration if a - * $config argument was provided. - */ - function wp_interactivity_config( string $store_namespace, array $config = array() ): array { - return wp_interactivity()->config( $store_namespace, $config ); - } -} - -if ( ! function_exists( 'wp_interactivity_data_wp_context' ) ) { - /** - * Generates a `data-wp-context` directive attribute by encoding a context - * array. - * - * This helper function simplifies the creation of `data-wp-context` directives - * by providing a way to pass an array of data, which encodes into a JSON string - * safe for direct use as a HTML attribute value. - * - * Example: - * - * <div <?php echo wp_interactivity_data_wp_context( array( 'isOpen' => true, 'count' => 0 ) ); ?>> - * - * @since 6.5.0 - * - * @param array $context The array of context data to encode. - * @param string $store_namespace Optional. The unique store namespace identifier. - * @return string A complete `data-wp-context` directive with a JSON encoded value representing the context array and - * the store namespace if specified. - */ - function wp_interactivity_data_wp_context( array $context, string $store_namespace = '' ): string { - return 'data-wp-context=\'' . - ( $store_namespace ? $store_namespace . '::' : '' ) . - ( empty( $context ) ? '{}' : wp_json_encode( $context, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ) ) . - '\''; - } -} - -if ( ! function_exists( 'data_wp_context' ) ) { - /** - * `data_wp_context()` was renamed to follow WordPress Core naming schemes. - * - * @link https://github.com/WordPress/gutenberg/pull/59465/ - * @link https://core.trac.wordpress.org/ticket/60575 - * - * @since 6.5.0 - * @deprecated 6.5.0 - * - * @param array $context The array of context data to encode. - * @param string $store_namespace Optional. The unique store namespace identifier. - * @return string A complete `data-wp-context` directive with a JSON encoded value representing the context array and - * the store namespace if specified. - */ - function data_wp_context( array $context, string $store_namespace = '' ): string { - _deprecated_function( __FUNCTION__, '6.5', 'wp_interactivity_data_wp_context()' ); - return wp_interactivity_data_wp_context( $context, $store_namespace ); - } -} diff --git a/lib/compat/wordpress-6.5/kses.php b/lib/compat/wordpress-6.5/kses.php deleted file mode 100644 index 038d78645786f7..00000000000000 --- a/lib/compat/wordpress-6.5/kses.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php -/** - * Temporary compatibility shims for block APIs present in Gutenberg. - * - * @package gutenberg - */ - -/** - * Update allowed inline style attributes list. - * - * @param string[] $attrs Array of allowed CSS attributes. - * @return string[] CSS attributes. - */ -function gutenberg_safe_style_attrs_6_5( $attrs ) { - $attrs[] = 'background-repeat'; - return $attrs; -} -add_filter( 'safe_style_css', 'gutenberg_safe_style_attrs_6_5' ); diff --git a/lib/compat/wordpress-6.5/navigation-block-variations.php b/lib/compat/wordpress-6.5/navigation-block-variations.php deleted file mode 100644 index 4009eb39386aeb..00000000000000 --- a/lib/compat/wordpress-6.5/navigation-block-variations.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php - -/** - * Workaround for Core versions < 6.5 to register navigation link variations on registration - * - * @param array $args The block type arguments. - * @return array The updated block type arguments. - */ -function gutenberg_navigation_link_variations_compat( $args ) { - - if ( 'core/navigation-link' !== $args['name'] || ! empty( $args['variation_callback'] ) ) { - return $args; - } - $args['variation_callback'] = 'gutenberg_block_core_navigation_link_build_variations'; - return $args; -} - -if ( ! method_exists( 'WP_Block_Type', 'get_variations' ) ) { - add_filter( 'register_block_type_args', 'gutenberg_navigation_link_variations_compat', 9 ); -} - -/** - * Registers custom post type variations for navigation link on post type registration - * Handles all post types registered after the block is registered in register_navigation_link_post_type_variations - * - * @since 6.5.0 - * @deprecated 6.5.0 Use WP_Block_Type::get_variations / get_block_type_variations filter instead. - * - * @param string $post_type The post type name passed from registered_post_type action hook. - * @param WP_Post_Type $post_type_object The post type object passed from registered_post_type. - */ -function gutenberg_block_core_navigation_link_register_post_type_variation( $post_type, $post_type_object ) { - _deprecated_function( __FUNCTION__, '6.5.0', 'WP_Block_Type::get_variations' ); - if ( $post_type_object->show_in_nav_menus ) { - $variation = build_variation_for_navigation_link( $post_type_object, 'post-type' ); - gutenberg_block_core_navigation_link_register_variation( $variation ); - } -} - -/** - * Registers a custom taxonomy variation for navigation link on taxonomy registration - * Handles all taxonomies registered after the block is registered in register_navigation_link_post_type_variations - * - * @since 6.5.0 - * @deprecated 6.5.0 Use WP_Block_Type::get_variations / get_block_type_variations filter instead. - * - * @param string $taxonomy Taxonomy slug. - * @param array|string $object_type Object type or array of object types. - * @param array $args Array of taxonomy registration arguments. - */ -function gutenberg_block_core_navigation_link_register_taxonomy_variation( $taxonomy, $object_type, $args ) { - _deprecated_function( __FUNCTION__, '6.5.0', 'WP_Block_Type::get_variations' ); - if ( isset( $args['show_in_nav_menus'] ) && $args['show_in_nav_menus'] ) { - $variation = build_variation_for_navigation_link( (object) $args, 'post-type' ); - gutenberg_block_core_navigation_link_register_variation( $variation ); - } -} - -/** - * Unregisters a custom post type variation for navigation link on post type unregistration. - * - * @since 6.5.0 - * @deprecated 6.5.0 Use WP_Block_Type::get_variations / get_block_type_variations filter instead. - * - * @param string $post_type The post type name passed from unregistered_post_type action hook. - */ -function gutenberg_block_core_navigation_link_unregister_post_type_variation( $post_type ) { - _deprecated_function( __FUNCTION__, '6.5.0', 'WP_Block_Type::get_variations' ); - gutenberg_block_core_navigation_link_unregister_variation( $post_type ); -} - -/** - * Unregisters a custom taxonomy variation for navigation link on taxonomy unregistration. - * - * @since 6.5.0 - * @deprecated 6.5.0 Use WP_Block_Type::get_variations / get_block_type_variations filter instead. - * - * @param string $taxonomy The taxonomy name passed from unregistered_taxonomy action hook. - */ -function gutenberg_block_core_navigation_link_unregister_taxonomy_variation( $taxonomy ) { - _deprecated_function( __FUNCTION__, '6.5.0', 'WP_Block_Type::get_variations' ); - gutenberg_block_core_navigation_link_unregister_variation( $taxonomy ); -} - -/** - * Registers a variation for a post type / taxonomy for the navigation link block. - * - * @since 6.5.0 - * @deprecated 6.5.0 Use WP_Block_Type::get_variations / get_block_type_variations filter instead. - * - * @param array $variation Variation array from build_variation_for_navigation_link. - */ -function gutenberg_block_core_navigation_link_register_variation( $variation ) { - _deprecated_function( __FUNCTION__, '6.5.0', 'WP_Block_Type::get_variations' ); - /* - * Directly set the variations on the registered block type - * because there's no server side registration for variations (see #47170). - */ - $navigation_block_type = WP_Block_Type_Registry::get_instance()->get_registered( 'core/navigation-link' ); - /* - * If the block is not registered yet, bail early. - * Variation will be registered in register_block_core_navigation_link then. - */ - if ( ! $navigation_block_type ) { - return; - } - - $navigation_block_type->variations = array_merge( - $navigation_block_type->variations, - array( $variation ) - ); -} - -/** - * Unregisters a variation for a post type / taxonomy for the navigation link block. - * - * @since 6.5.0 - * @deprecated 6.5.0 Use WP_Block_Type::get_variations / get_block_type_variations filter instead. - * - * @param string $name Name of the post type / taxonomy (which was used as variation name). - */ -function gutenberg_block_core_navigation_link_unregister_variation( $name ) { - _deprecated_function( __FUNCTION__, '6.5.0', 'WP_Block_Type::get_variations' ); - /* - * Directly get the variations from the registered block type - * because there's no server side (un)registration for variations (see #47170). - */ - $navigation_block_type = WP_Block_Type_Registry::get_instance()->get_registered( 'core/navigation-link' ); - // If the block is not registered (yet), there's no need to remove a variation. - if ( ! $navigation_block_type || empty( $navigation_block_type->variations ) ) { - return; - } - $variations = $navigation_block_type->variations; - // Search for the variation and remove it from the array. - foreach ( $variations as $i => $variation ) { - if ( $variation['name'] === $name ) { - unset( $variations[ $i ] ); - break; - } - } - // Reindex array after removing one variation. - $navigation_block_type->variations = array_values( $variations ); -} diff --git a/lib/compat/wordpress-6.5/rest-api.php b/lib/compat/wordpress-6.5/rest-api.php deleted file mode 100644 index d18756844cc91a..00000000000000 --- a/lib/compat/wordpress-6.5/rest-api.php +++ /dev/null @@ -1,136 +0,0 @@ -<?php -/** - * PHP and WordPress configuration compatibility functions for the Gutenberg - * editor plugin changes related to REST API. - * - * @package gutenberg - */ - -if ( ! defined( 'ABSPATH' ) ) { - die( 'Silence is golden.' ); -} - -/** - * Registers additional fields for wp_template and wp_template_part rest api. - * - * @access private - * @internal - * - * @param array $template_object Template object. - * @return string Original source of the template one of theme, plugin, site, or user. - */ -function _gutenberg_get_wp_templates_original_source_field( $template_object ) { - if ( 'wp_template' === $template_object['type'] || 'wp_template_part' === $template_object['type'] ) { - // Added by theme. - // Template originally provided by a theme, but customized by a user. - // Templates originally didn't have the 'origin' field so identify - // older customized templates by checking for no origin and a 'theme' - // or 'custom' source. - if ( $template_object['has_theme_file'] && - ( 'theme' === $template_object['origin'] || ( - empty( $template_object['origin'] ) && in_array( - $template_object['source'], - array( - 'theme', - 'custom', - ), - true - ) ) - ) - ) { - return 'theme'; - } - - // Added by plugin. - if ( $template_object['has_theme_file'] && 'plugin' === $template_object['origin'] ) { - return 'plugin'; - } - - // Added by site. - // Template was created from scratch, but has no author. Author support - // was only added to templates in WordPress 5.9. Fallback to showing the - // site logo and title. - if ( empty( $template_object['has_theme_file'] ) && 'custom' === $template_object['source'] && empty( $template_object['author'] ) ) { - return 'site'; - } - } - - // Added by user. - return 'user'; -} - -/** - * Registers additional fields for wp_template and wp_template_part rest api. - * - * @access private - * @internal - * - * @param array $template_object Template object. - * @return string Human readable text for the author. - */ -function _gutenberg_get_wp_templates_author_text_field( $template_object ) { - $original_source = _gutenberg_get_wp_templates_original_source_field( $template_object ); - switch ( $original_source ) { - case 'theme': - $theme_name = wp_get_theme( $template_object['theme'] )->get( 'Name' ); - return empty( $theme_name ) ? $template_object['theme'] : $theme_name; - case 'plugin': - $plugins = get_plugins(); - $plugin = $plugins[ plugin_basename( sanitize_text_field( $template_object['theme'] . '.php' ) ) ]; - return empty( $plugin['Name'] ) ? $template_object['theme'] : $plugin['Name']; - case 'site': - return get_bloginfo( 'name' ); - case 'user': - $author = get_user_by( 'id', $template_object['author'] ); - if ( ! $author ) { - return __( 'Unknown author', 'gutenberg' ); - } - return $author->get( 'display_name' ); - } -} - -/** - * Registers additional fields for wp_template and wp_template_part rest api. - * - * @access private - * @internal - */ -function _gutenberg_register_wp_templates_additional_fields() { - register_rest_field( - array( 'wp_template', 'wp_template_part' ), - 'author_text', - array( - 'get_callback' => '_gutenberg_get_wp_templates_author_text_field', - 'update_callback' => null, - 'schema' => array( - 'type' => 'string', - 'description' => __( 'Human readable text for the author.', 'gutenberg' ), - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - ) - ); - - register_rest_field( - array( 'wp_template', 'wp_template_part' ), - 'original_source', - array( - 'get_callback' => '_gutenberg_get_wp_templates_original_source_field', - 'update_callback' => null, - 'schema' => array( - 'description' => __( 'Where the template originally comes from e.g. \'theme\'', 'gutenberg' ), - 'type' => 'string', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - 'enum' => array( - 'theme', - 'plugin', - 'site', - 'user', - ), - ), - ) - ); -} - -add_action( 'rest_api_init', '_gutenberg_register_wp_templates_additional_fields' ); diff --git a/lib/compat/wordpress-6.5/script-loader.php b/lib/compat/wordpress-6.5/script-loader.php deleted file mode 100644 index a77134d9182f93..00000000000000 --- a/lib/compat/wordpress-6.5/script-loader.php +++ /dev/null @@ -1,207 +0,0 @@ -<?php -/** - * Updates the script-loader.php file - * - * @package gutenberg - */ - -/** - * Updates the registered inline script `wp-date` required for moment.js localization. - * Changes to the inline script output should be synced with Core in the file - * src/wp-includes/script-loader.php in `wp_default_packages_inline_scripts()`. - * - * @since 6.4.0 Added relative time date strings. - * @since 6.5.0 Added timezone offset value. - * - * @global WP_Locale $wp_locale WordPress date and time locale object. - * - * @param WP_Scripts $scripts WP_Scripts object. - */ -function gutenberg_update_wp_date_settings( $scripts ) { - if ( did_action( 'init' ) && $scripts->query( 'wp-date', 'registered' ) ) { - global $wp_locale; - // Calculate the timezone abbr (EDT, PST) if possible. - $timezone_string = get_option( 'timezone_string', 'UTC' ); - $timezone_abbr = ''; - - if ( ! empty( $timezone_string ) ) { - $timezone_date = new DateTime( 'now', new DateTimeZone( $timezone_string ) ); - $timezone_abbr = $timezone_date->format( 'T' ); - } - - $gmt_offset = get_option( 'gmt_offset', 0 ); - - $scripts->registered['wp-date']->extra['after'] = array( - false, - sprintf( - 'wp.date.setSettings( %s );', - wp_json_encode( - array( - 'l10n' => array( - 'locale' => get_user_locale(), - 'months' => array_values( $wp_locale->month ), - 'monthsShort' => array_values( $wp_locale->month_abbrev ), - 'weekdays' => array_values( $wp_locale->weekday ), - 'weekdaysShort' => array_values( $wp_locale->weekday_abbrev ), - 'meridiem' => (object) $wp_locale->meridiem, - 'relative' => array( - /* translators: %s: Duration. */ - 'future' => __( '%s from now', 'gutenberg' ), - /* translators: %s: Duration. */ - 'past' => __( '%s ago', 'gutenberg' ), - /* translators: One second from or to a particular datetime, e.g., "a second ago" or "a second from now". */ - 's' => __( 'a second', 'gutenberg' ), - /* translators: %d: Duration in seconds from or to a particular datetime, e.g., "4 seconds ago" or "4 seconds from now". */ - 'ss' => __( '%d seconds', 'gutenberg' ), - /* translators: One minute from or to a particular datetime, e.g., "a minute ago" or "a minute from now". */ - 'm' => __( 'a minute', 'gutenberg' ), - /* translators: %d: Duration in minutes from or to a particular datetime, e.g., "4 minutes ago" or "4 minutes from now". */ - 'mm' => __( '%d minutes', 'gutenberg' ), - /* translators: One hour from or to a particular datetime, e.g., "an hour ago" or "an hour from now". */ - 'h' => __( 'an hour', 'gutenberg' ), - /* translators: %d: Duration in hours from or to a particular datetime, e.g., "4 hours ago" or "4 hours from now". */ - 'hh' => __( '%d hours', 'gutenberg' ), - /* translators: One day from or to a particular datetime, e.g., "a day ago" or "a day from now". */ - 'd' => __( 'a day', 'gutenberg' ), - /* translators: %d: Duration in days from or to a particular datetime, e.g., "4 days ago" or "4 days from now". */ - 'dd' => __( '%d days', 'gutenberg' ), - /* translators: One month from or to a particular datetime, e.g., "a month ago" or "a month from now". */ - 'M' => __( 'a month', 'gutenberg' ), - /* translators: %d: Duration in months from or to a particular datetime, e.g., "4 months ago" or "4 months from now". */ - 'MM' => __( '%d months', 'gutenberg' ), - /* translators: One year from or to a particular datetime, e.g., "a year ago" or "a year from now". */ - 'y' => __( 'a year', 'gutenberg' ), - /* translators: %d: Duration in years from or to a particular datetime, e.g., "4 years ago" or "4 years from now". */ - 'yy' => __( '%d years', 'gutenberg' ), - ), - 'startOfWeek' => (int) get_option( 'start_of_week', 0 ), - ), - 'formats' => array( - /* translators: Time format, see https://www.php.net/manual/datetime.format.php */ - 'time' => get_option( 'time_format', __( 'g:i a', 'default' ) ), - /* translators: Date format, see https://www.php.net/manual/datetime.format.php */ - 'date' => get_option( 'date_format', __( 'F j, Y', 'default' ) ), - /* translators: Date/Time format, see https://www.php.net/manual/datetime.format.php */ - 'datetime' => __( 'F j, Y g:i a', 'default' ), - /* translators: Abbreviated date/time format, see https://www.php.net/manual/datetime.format.php */ - 'datetimeAbbreviated' => __( 'M j, Y g:i a', 'default' ), - ), - 'timezone' => array( - 'offset' => (float) $gmt_offset, - 'offsetFormatted' => str_replace( array( '.25', '.5', '.75' ), array( ':15', ':30', ':45' ), (string) $gmt_offset ), - 'string' => $timezone_string, - 'abbr' => $timezone_abbr, - ), - ) - ) - ), - ); - } -} - -add_action( 'wp_default_scripts', 'gutenberg_update_wp_date_settings' ); - -/** - * Prints inline JavaScript wrapped in `<script>` tag. - * - * It is possible to inject attributes in the `<script>` tag via the {@see 'wp_script_attributes'} filter. - * Automatically injects type attribute if needed. - * - * @since 5.7.0 - * - * @param string $javascript Inline JavaScript code. - * @param array $attributes Optional. Key-value pairs representing `<script>` tag attributes. - */ -function gutenberg_print_inline_script_tag( $javascript, $attributes = array() ) { - echo gutenberg_get_inline_script_tag( $javascript, $attributes ); -} - - -/** - * Wraps inline JavaScript in `<script>` tag. - * - * It is possible to inject attributes in the `<script>` tag via the {@see 'wp_script_attributes'} filter. - * Automatically injects type attribute if needed. - * - * @since 5.7.0 - * - * @param string $javascript Inline JavaScript code. - * @param array $attributes Optional. Key-value pairs representing `<script>` tag attributes. - * @return string String containing inline JavaScript code wrapped around `<script>` tag. - */ -function gutenberg_get_inline_script_tag( $data, $attributes = array() ) { - $is_html5 = current_theme_supports( 'html5', 'script' ) || is_admin(); - if ( ! isset( $attributes['type'] ) && ! $is_html5 ) { - // Keep the type attribute as the first for legacy reasons (it has always been this way in core). - $attributes = array_merge( - array( 'type' => 'text/javascript' ), - $attributes - ); - } - - /* - * XHTML extracts the contents of the SCRIPT element and then the XML parser - * decodes character references and other syntax elements. This can lead to - * misinterpretation of the script contents or invalid XHTML documents. - * - * Wrapping the contents in a CDATA section instructs the XML parser not to - * transform the contents of the SCRIPT element before passing them to the - * JavaScript engine. - * - * Example: - * - * <script>console.log('…');</script> - * - * In an HTML document this would print "…" to the console, - * but in an XHTML document it would print "…" to the console. - * - * <script>console.log('An image is <img> in HTML');</script> - * - * In an HTML document this would print "An image is <img> in HTML", - * but it's an invalid XHTML document because it interprets the `<img>` - * as an empty tag missing its closing `/`. - * - * @see https://www.w3.org/TR/xhtml1/#h-4.8 - */ - if ( - ! $is_html5 && - ( - ! isset( $attributes['type'] ) || - 'module' === $attributes['type'] || - str_contains( $attributes['type'], 'javascript' ) || - str_contains( $attributes['type'], 'ecmascript' ) || - str_contains( $attributes['type'], 'jscript' ) || - str_contains( $attributes['type'], 'livescript' ) - ) - ) { - /* - * If the string `]]>` exists within the JavaScript it would break - * out of any wrapping CDATA section added here, so to start, it's - * necessary to escape that sequence which requires splitting the - * content into two CDATA sections wherever it's found. - * - * Note: it's only necessary to escape the closing `]]>` because - * an additional `<![CDATA[` leaves the contents unchanged. - */ - $data = str_replace( ']]>', ']]]]><![CDATA[>', $data ); - - // Wrap the entire escaped script inside a CDATA section. - $data = sprintf( "/* <![CDATA[ */\n%s\n/* ]]> */", $data ); - } - - $data = "\n" . trim( $data, "\n\r " ) . "\n"; - - /** - * Filters attributes to be added to a script tag. - * - * @since 5.7.0 - * - * @param array $attributes Key-value pairs representing `<script>` tag attributes. - * Only the attribute name is added to the `<script>` tag for - * entries with a boolean value, and that are true. - * @param string $data Inline data. - */ - $attributes = apply_filters( 'wp_inline_script_attributes', $attributes, $data ); - - return sprintf( "<script%s>%s</script>\n", wp_sanitize_script_attributes( $attributes ), $data ); -} diff --git a/lib/compat/wordpress-6.5/scripts-modules.php b/lib/compat/wordpress-6.5/scripts-modules.php deleted file mode 100644 index 110ef858eb8ce8..00000000000000 --- a/lib/compat/wordpress-6.5/scripts-modules.php +++ /dev/null @@ -1,224 +0,0 @@ -<?php -/** - * Script Modules API: Script Module functions - * - * @since 6.5.0 - * - * @package WordPress - * @subpackage Script Modules - */ - -if ( ! function_exists( 'wp_script_modules' ) ) { - /** - * Retrieves the main WP_Script_Modules instance. - * - * This function provides access to the WP_Script_Modules instance, creating one - * if it doesn't exist yet. - * - * @since 6.5.0 - * - * @global WP_Script_Modules $wp_script_modules - * - * @return WP_Script_Modules The main WP_Script_Modules instance. - */ - function wp_script_modules(): WP_Script_Modules { - global $wp_script_modules; - - if ( ! ( $wp_script_modules instanceof WP_Script_Modules ) ) { - $wp_script_modules = new WP_Script_Modules(); - } - return $wp_script_modules; - } - wp_script_modules()->add_hooks(); - - /** - * Add module fields from block metadata to WP_Block_Type settings. - * - * This filter allows us to register modules from block metadata and attach additional fields to - * WP_Block_Type instances. - * - * @param array $settings Array of determined settings for registering a block type. - * @param array $metadata Metadata provided for registering a block type. - */ - function gutenberg_filter_block_type_metadata_settings_register_modules( $settings, $metadata = null ) { - $module_fields = array( - 'viewScriptModule' => 'view_script_module_ids', - ); - foreach ( $module_fields as $metadata_field_name => $settings_field_name ) { - if ( ! empty( $settings[ $metadata_field_name ] ) ) { - $metadata[ $metadata_field_name ] = $settings[ $metadata_field_name ]; - } - if ( ! empty( $metadata[ $metadata_field_name ] ) ) { - $modules = $metadata[ $metadata_field_name ]; - $processed_modules = array(); - if ( is_array( $modules ) ) { - for ( $index = 0; $index < count( $modules ); $index++ ) { - $processed_modules[] = gutenberg_register_block_module_id( - $metadata, - $metadata_field_name, - $index - ); - } - } else { - $processed_modules[] = gutenberg_register_block_module_id( - $metadata, - $metadata_field_name - ); - } - $settings[ $settings_field_name ] = $processed_modules; - } - } - - return $settings; - } - - add_filter( 'block_type_metadata_settings', 'gutenberg_filter_block_type_metadata_settings_register_modules', 10, 2 ); - - /** - * Enqueue modules associated with the block. - * - * @param string $block_content The block content. - * @param array $parsed_block The full block, including name and attributes. - * @param WP_Block $block_instance The block instance. - */ - function gutenberg_filter_render_block_enqueue_view_script_modules( $block_content, $parsed_block, $block_instance ) { - $block_type = $block_instance->block_type; - - if ( ! empty( $block_type->view_script_module_ids ) ) { - foreach ( $block_type->view_script_module_ids as $module_id ) { - wp_enqueue_script_module( $module_id ); - } - } - - return $block_content; - } - - add_filter( 'render_block', 'gutenberg_filter_render_block_enqueue_view_script_modules', 10, 3 ); - - /** - * Registers a REST field for block types to provide view script module IDs. - * - * Adds the `view_script_module_ids` and `view_module_ids` (deprecated) field to block type objects in the REST API, which - * lists the script module IDs for any script modules associated with the - * block's viewScriptModule key. - */ - function gutenberg_register_view_script_module_ids_rest_field() { - register_rest_field( - 'block-type', - 'view_script_module_ids', - array( - 'get_callback' => function ( $item ) { - $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $item['name'] ); - if ( isset( $block_type->view_script_module_ids ) ) { - return $block_type->view_script_module_ids; - } - return array(); - }, - ) - ); - } - - add_action( 'rest_api_init', 'gutenberg_register_view_script_module_ids_rest_field' ); -} - -if ( ! function_exists( 'wp_register_script_module' ) ) { - /** - * Registers the script module if no script module with that script module - * identifier has already been registered. - * - * @since 6.5.0 - * - * @param string $id The identifier of the script module. Should be unique. It will be used in the - * final import map. - * @param string $src Optional. Full URL of the script module, or path of the script module relative - * to the WordPress root directory. If it is provided and the script module has - * not been registered yet, it will be registered. - * @param array $deps { - * Optional. List of dependencies. - * - * @type string|array $0... { - * An array of script module identifiers of the dependencies of this script - * module. The dependencies can be strings or arrays. If they are arrays, - * they need an `id` key with the script module identifier, and can contain - * an `import` key with either `static` or `dynamic`. By default, - * dependencies that don't contain an `import` key are considered static. - * - * @type string $id The script module identifier. - * @type string $import Optional. Import type. May be either `static` or - * `dynamic`. Defaults to `static`. - * } - * } - * @param string|false|null $version Optional. String specifying the script module version number. Defaults to false. - * It is added to the URL as a query string for cache busting purposes. If $version - * is set to false, the version number is the currently installed WordPress version. - * If $version is set to null, no version is added. - */ - function wp_register_script_module( string $id, string $src, array $deps = array(), $version = false ) { - wp_script_modules()->register( $id, $src, $deps, $version ); - } -} - -if ( ! function_exists( 'wp_enqueue_script_module' ) ) { - /** - * Marks the script module to be enqueued in the page. - * - * If a src is provided and the script module has not been registered yet, it - * will be registered. - * - * @since 6.5.0 - * - * @param string $id The identifier of the script module. Should be unique. It will be used in the - * final import map. - * @param string $src Optional. Full URL of the script module, or path of the script module relative - * to the WordPress root directory. If it is provided and the script module has - * not been registered yet, it will be registered. - * @param array $deps { - * Optional. List of dependencies. - * - * @type string|array $0... { - * An array of script module identifiers of the dependencies of this script - * module. The dependencies can be strings or arrays. If they are arrays, - * they need an `id` key with the script module identifier, and can contain - * an `import` key with either `static` or `dynamic`. By default, - * dependencies that don't contain an `import` key are considered static. - * - * @type string $id The script module identifier. - * @type string $import Optional. Import type. May be either `static` or - * `dynamic`. Defaults to `static`. - * } - * } - * @param string|false|null $version Optional. String specifying the script module version number. Defaults to false. - * It is added to the URL as a query string for cache busting purposes. If $version - * is set to false, the version number is the currently installed WordPress version. - * If $version is set to null, no version is added. - */ - function wp_enqueue_script_module( string $id, string $src = '', array $deps = array(), $version = false ) { - wp_script_modules()->enqueue( $id, $src, $deps, $version ); - } -} - -if ( ! function_exists( 'wp_dequeue_script_module' ) ) { - /** - * Unmarks the script module so it is no longer enqueued in the page. - * - * @since 6.5.0 - * - * @param string $id The identifier of the script module. - */ - function wp_dequeue_script_module( string $id ) { - wp_script_modules()->dequeue( $id ); - } -} - -if ( ! function_exists( 'wp_deregister_script_module' ) ) { - /** - * Deregisters the script module. - * - * @since 6.5.0 - * - * @param string $id The identifier of the script module. - */ - function wp_deregister_script_module( string $id ) { - wp_script_modules()->deregister( $id ); - } -} diff --git a/lib/compat/wordpress-6.6/class-gutenberg-rest-global-styles-revisions-controller-6-6.php b/lib/compat/wordpress-6.6/class-gutenberg-rest-global-styles-revisions-controller-6-6.php index f725366c33cfb8..3e5d4cdd68454a 100644 --- a/lib/compat/wordpress-6.6/class-gutenberg-rest-global-styles-revisions-controller-6-6.php +++ b/lib/compat/wordpress-6.6/class-gutenberg-rest-global-styles-revisions-controller-6-6.php @@ -15,7 +15,7 @@ * * @see WP_REST_Controller */ -class Gutenberg_REST_Global_Styles_Revisions_Controller_6_6 extends Gutenberg_REST_Global_Styles_Revisions_Controller_6_5 { +class Gutenberg_REST_Global_Styles_Revisions_Controller_6_6 extends WP_REST_Global_Styles_Revisions_Controller { /** * Prepares the revision for the REST response. * diff --git a/lib/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php b/lib/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php index e670afacea5b33..034187ca9a70ae 100644 --- a/lib/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php +++ b/lib/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php @@ -12,7 +12,7 @@ * `edit_theme_options` capability. In order to allow other roles to also view the templates, * we need to override the permissions check for the REST API endpoints. */ -class Gutenberg_REST_Templates_Controller_6_6 extends Gutenberg_REST_Templates_Controller_6_4 { +class Gutenberg_REST_Templates_Controller_6_6 extends WP_REST_Templates_Controller { /** * Checks if a given request has access to read templates. diff --git a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-6-6.php b/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-6-6.php index 634aaab01707cd..77801535ff3683 100644 --- a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-6-6.php +++ b/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-6-6.php @@ -293,8 +293,8 @@ public static function create_fragment( $html, $context = '<body>', $encoding = $processor->state->insertion_mode = Gutenberg_HTML_Processor_State_6_6::INSERTION_MODE_IN_BODY; // @todo Create "fake" bookmarks for non-existent but implied nodes. - $processor->bookmarks['root-node'] = new Gutenberg_HTML_Span_6_5( 0, 0 ); - $processor->bookmarks['context-node'] = new Gutenberg_HTML_Span_6_5( 0, 0 ); + $processor->bookmarks['root-node'] = new WP_HTML_Span( 0, 0 ); + $processor->bookmarks['context-node'] = new WP_HTML_Span( 0, 0 ); $processor->state->stack_of_open_elements->push( new WP_HTML_Token( diff --git a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-tag-processor-6-6.php b/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-tag-processor-6-6.php index eb873e7a063401..ecbc6d0d7b6af4 100644 --- a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-tag-processor-6-6.php +++ b/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-tag-processor-6-6.php @@ -1227,7 +1227,7 @@ public function set_bookmark( $name ) { return false; } - $this->bookmarks[ $name ] = new Gutenberg_HTML_Span_6_5( $this->token_starts_at, $this->token_length ); + $this->bookmarks[ $name ] = new WP_HTML_Span( $this->token_starts_at, $this->token_length ); return true; } @@ -2035,7 +2035,7 @@ private function parse_next_attribute() { * an array when encountering duplicates avoids needless allocations in the * normative case of parsing tags with no duplicate attributes. */ - $duplicate_span = new Gutenberg_HTML_Span_6_5( $attribute_start, $attribute_end - $attribute_start ); + $duplicate_span = new WP_HTML_Span( $attribute_start, $attribute_end - $attribute_start ); if ( null === $this->duplicate_attributes ) { $this->duplicate_attributes = array( $comparable_name => array( $duplicate_span ) ); } elseif ( ! array_key_exists( $comparable_name, $this->duplicate_attributes ) ) { @@ -3007,7 +3007,7 @@ public function set_attribute( $name, $value ) { * Result: <div id="new"/> */ $existing_attribute = $this->attributes[ $comparable_name ]; - $this->lexical_updates[ $comparable_name ] = new Gutenberg_HTML_Text_Replacement_6_5( + $this->lexical_updates[ $comparable_name ] = new WP_HTML_Text_Replacement( $existing_attribute->start, $existing_attribute->length, $updated_attribute @@ -3025,7 +3025,7 @@ public function set_attribute( $name, $value ) { * * Result: <div id="new"/> */ - $this->lexical_updates[ $comparable_name ] = new Gutenberg_HTML_Text_Replacement_6_5( + $this->lexical_updates[ $comparable_name ] = new WP_HTML_Text_Replacement( $this->tag_name_starts_at + $this->tag_name_length, 0, ' ' . $updated_attribute @@ -3103,7 +3103,7 @@ public function remove_attribute( $name ) { * * Result: <div /> */ - $this->lexical_updates[ $name ] = new Gutenberg_HTML_Text_Replacement_6_5( + $this->lexical_updates[ $name ] = new WP_HTML_Text_Replacement( $this->attributes[ $name ]->start, $this->attributes[ $name ]->length, '' @@ -3112,7 +3112,7 @@ public function remove_attribute( $name ) { // Removes any duplicated attributes if they were also present. if ( null !== $this->duplicate_attributes && array_key_exists( $name, $this->duplicate_attributes ) ) { foreach ( $this->duplicate_attributes[ $name ] as $attribute_token ) { - $this->lexical_updates[] = new Gutenberg_HTML_Text_Replacement_6_5( + $this->lexical_updates[] = new WP_HTML_Text_Replacement( $attribute_token->start, $attribute_token->length, '' diff --git a/lib/load.php b/lib/load.php index ef1b5cfe50b6a9..244b6a2d9e685a 100644 --- a/lib/load.php +++ b/lib/load.php @@ -35,17 +35,6 @@ function gutenberg_is_experiment_enabled( $name ) { require_once __DIR__ . '/experimental/class-wp-rest-block-editor-settings-controller.php'; } - // WordPress 6.4 compat. - require_once __DIR__ . '/compat/wordpress-6.4/class-gutenberg-rest-templates-controller-6-4.php'; - require_once __DIR__ . '/compat/wordpress-6.4/class-gutenberg-rest-global-styles-revisions-controller-6-4.php'; - require_once __DIR__ . '/compat/wordpress-6.4/class-gutenberg-rest-block-patterns-controller.php'; - require_once __DIR__ . '/compat/wordpress-6.4/rest-api.php'; - require_once __DIR__ . '/compat/wordpress-6.4/theme-previews.php'; - - // WordPress 6.5 compat. - require_once __DIR__ . '/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php'; - require_once __DIR__ . '/compat/wordpress-6.5/rest-api.php'; - // WordPress 6.6 compat. require __DIR__ . '/compat/wordpress-6.6/class-gutenberg-rest-global-styles-revisions-controller-6-6.php'; require __DIR__ . '/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php'; @@ -74,26 +63,12 @@ function gutenberg_is_experiment_enabled( $name ) { // Gutenberg plugin compat. require __DIR__ . '/compat/plugin/edit-site-routes-backwards-compat.php'; -require __DIR__ . '/compat/plugin/footnotes.php'; +require __DIR__ . '/compat/plugin/fonts.php'; // The Token Map was created during 6.6 in order to support the HTML API. It must be loaded before it. require __DIR__ . '/compat/wordpress-6.6/class-gutenberg-token-map-6-6.php'; require __DIR__ . '/compat/wordpress-6.7/class-gutenberg-token-map-6-7.php'; -/* - * There are upstream updates to the Tag Processor that may not appear if Gutenberg is running - * a version of WordPress newer than 6.4 and older than the latest `trunk`. This file should - * always be loaded so that Gutenberg code can run the newest version of the Tag Processor. - */ -require __DIR__ . '/compat/wordpress-6.4/html-api/class-gutenberg-html-tag-processor-6-4.php'; -require __DIR__ . '/compat/wordpress-6.5/html-api/class-gutenberg-html-attribute-token-6-5.php'; -require __DIR__ . '/compat/wordpress-6.5/html-api/class-gutenberg-html-span-6-5.php'; -require __DIR__ . '/compat/wordpress-6.5/html-api/class-gutenberg-html-text-replacement-6-5.php'; -require __DIR__ . '/compat/wordpress-6.5/html-api/class-gutenberg-html-open-elements-6-5.php'; -require __DIR__ . '/compat/wordpress-6.5/html-api/class-gutenberg-html-processor-state-6-5.php'; -require __DIR__ . '/compat/wordpress-6.5/html-api/class-gutenberg-html-tag-processor-6-5.php'; -require __DIR__ . '/compat/wordpress-6.5/html-api/class-gutenberg-html-processor-6-5.php'; - require __DIR__ . '/compat/wordpress-6.6/html-api/gutenberg-html5-named-character-references-6-6.php'; require __DIR__ . '/compat/wordpress-6.6/html-api/class-gutenberg-html-decoder-6-6.php'; require __DIR__ . '/compat/wordpress-6.6/html-api/class-gutenberg-html-tag-processor-6-6.php'; @@ -116,46 +91,6 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-processor-state-6-7.php'; require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-processor-6-7.php'; -/* - * The HTML Processor appeared after WordPress 6.3. If Gutenberg is running on a version of - * WordPress before it was introduced, these verbatim Core files will be missing. - */ -if ( ! class_exists( 'WP_HTML_Processor' ) ) { - require __DIR__ . '/compat/wordpress-6.4/html-api/class-wp-html-active-formatting-elements.php'; - require __DIR__ . '/compat/wordpress-6.4/html-api/class-wp-html-open-elements.php'; - require __DIR__ . '/compat/wordpress-6.4/html-api/class-wp-html-processor-state.php'; - require __DIR__ . '/compat/wordpress-6.4/html-api/class-wp-html-token.php'; - require __DIR__ . '/compat/wordpress-6.4/html-api/class-wp-html-unsupported-exception.php'; - require __DIR__ . '/compat/wordpress-6.4/html-api/class-wp-html-processor.php'; -} - -// WordPress 6.4 compat. -require __DIR__ . '/compat/wordpress-6.4/blocks.php'; -require __DIR__ . '/compat/wordpress-6.4/block-hooks.php'; -require __DIR__ . '/compat/wordpress-6.4/script-loader.php'; -require __DIR__ . '/compat/wordpress-6.4/kses.php'; - -// WordPress 6.5 compat. -require __DIR__ . '/compat/wordpress-6.5/compat.php'; -require __DIR__ . '/compat/wordpress-6.5/blocks.php'; -require __DIR__ . '/compat/wordpress-6.5/block-patterns.php'; -require __DIR__ . '/compat/wordpress-6.5/kses.php'; -require __DIR__ . '/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php'; -require __DIR__ . '/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api-directives-processor.php'; -require __DIR__ . '/compat/wordpress-6.5/interactivity-api/interactivity-api.php'; -require __DIR__ . '/compat/wordpress-6.5/class-wp-script-modules.php'; -require __DIR__ . '/compat/wordpress-6.5/scripts-modules.php'; -require __DIR__ . '/compat/wordpress-6.5/navigation-block-variations.php'; -if ( ! class_exists( 'WP_Block_Bindings_Source' ) ) { - require __DIR__ . '/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-source.php'; -} -if ( ! class_exists( 'WP_Block_Bindings_Registry' ) ) { - require __DIR__ . '/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-registry.php'; -} -require __DIR__ . '/compat/wordpress-6.5/block-bindings/block-bindings.php'; -require __DIR__ . '/compat/wordpress-6.5/block-bindings/post-meta.php'; -require __DIR__ . '/compat/wordpress-6.5/script-loader.php'; - // WordPress 6.6 compat. require __DIR__ . '/compat/wordpress-6.6/admin-bar.php'; require __DIR__ . '/compat/wordpress-6.6/blocks.php'; @@ -185,31 +120,6 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/experimental/disable-tinymce.php'; } -// Fonts API / Font Face. -remove_action( 'plugins_loaded', '_wp_theme_json_webfonts_handler' ); // Turns off WordPress 6.0's stopgap handler. - -// Loads the Font Library. -require __DIR__ . '/compat/wordpress-6.5/fonts/class-wp-font-collection.php'; -require __DIR__ . '/compat/wordpress-6.5/fonts/class-wp-font-library.php'; -require __DIR__ . '/compat/wordpress-6.5/fonts/class-wp-font-utils.php'; -require __DIR__ . '/compat/wordpress-6.5/fonts/class-wp-rest-font-families-controller.php'; -require __DIR__ . '/compat/wordpress-6.5/fonts/class-wp-rest-font-faces-controller.php'; -require __DIR__ . '/compat/wordpress-6.5/fonts/class-wp-rest-font-collections-controller.php'; -require __DIR__ . '/compat/wordpress-6.5/fonts/fonts.php'; - -// Load the Font Face and Font Face Resolver, if not already loaded by WordPress Core. -if ( ! class_exists( 'WP_Font_Face' ) ) { - require __DIR__ . '/compat/wordpress-6.4/fonts/font-face/class-wp-font-face.php'; - require __DIR__ . '/compat/wordpress-6.4/fonts/font-face/class-wp-font-face-resolver.php'; -} - -/* - * As _gutenberg_get_iframed_editor_assets_6_4() overrides Core's _wp_get_iframed_editor_assets(), - * load this file to ensure wp_print_font_faces() is invoked to load the styles into the - * iframed editor. - */ -require __DIR__ . '/compat/wordpress-6.4/fonts/fonts.php'; - // Load the BC Layer to avoid fatal errors of extenders using the Fonts API. // @core-merge: do not merge the BC layer files into WordPress Core. require __DIR__ . '/experimental/font-face/bc-layer/class-wp-fonts-provider.php'; diff --git a/packages/block-library/src/button/index.php b/packages/block-library/src/button/index.php index 4a53952ef537f7..f272fa9eb62b14 100644 --- a/packages/block-library/src/button/index.php +++ b/packages/block-library/src/button/index.php @@ -17,20 +17,7 @@ * @return string The block content. */ function render_block_core_button( $attributes, $content ) { - /* - * The current Gutenberg plugin supports WordPress 6.4, but the next_token() - * method does not exist in WordPress 6.4. Therefore, if Gutenberg is used - * as a plugin, use the Gutenberg class that has the `next_token()` method. - * - * TODO: After the Gutenberg plugin drops support for WordPress 6.4, this - * conditional statement will be removed and the core class `WP_HTML_Tag_Processor` - * should be used. - */ - if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN && class_exists( 'Gutenberg_HTML_Tag_Processor_6_7' ) ) { - $p = new Gutenberg_HTML_Tag_Processor_6_7( $content ); - } else { - $p = new WP_HTML_Tag_Processor( $content ); - } + $p = new WP_HTML_Tag_Processor( $content ); /* * The button block can render an `<a>` or `<button>` and also has a diff --git a/phpunit/class-gutenberg-rest-global-styles-revisions-controller-test.php b/phpunit/class-gutenberg-rest-global-styles-revisions-controller-test.php deleted file mode 100644 index 30780c50f18635..00000000000000 --- a/phpunit/class-gutenberg-rest-global-styles-revisions-controller-test.php +++ /dev/null @@ -1,351 +0,0 @@ -<?php -/** - * Unit tests covering Gutenberg_REST_Global_Styles_Revisions_Controller_6_4 functionality. - * - * Note: the bulk of the tests covering this class and its methods have been ported to Core as of 6.3. - * - * @package WordPress - * @subpackage REST API - */ - -class Gutenberg_REST_Global_Styles_Revisions_Controller_Test extends WP_Test_REST_Controller_Testcase { - /** - * @var int - */ - protected static $admin_id; - - /** - * @var int - */ - protected static $global_styles_id; - - /** - * @var int - */ - protected static $global_styles_id_2; - - /** - * @var array - */ - private $revision_1; - - /** - * @var int - */ - private $revision_1_id; - - /** - * Create fake data before our tests run. - * - * @param WP_UnitTest_Factory $factory Helper that lets us create fake data. - */ - public static function wpSetupBeforeClass( $factory ) { - self::$admin_id = $factory->user->create( - array( - 'role' => 'administrator', - ) - ); - - wp_set_current_user( self::$admin_id ); - // This creates the global styles for the current theme. - self::$global_styles_id = $factory->post->create( - array( - 'post_content' => '{"version": ' . WP_Theme_JSON::LATEST_SCHEMA . ', "isGlobalStylesUserThemeJSON": true }', - 'post_status' => 'publish', - 'post_title' => __( 'Custom Styles', 'default' ), - 'post_type' => 'wp_global_styles', - 'post_name' => 'wp-global-styles-tt1-blocks-revisions', - 'tax_input' => array( - 'wp_theme' => 'tt1-blocks', - ), - ) - ); - - // This creates another global styles post for the current theme. - self::$global_styles_id_2 = $factory->post->create( - array( - 'post_content' => '{"version": ' . WP_Theme_JSON::LATEST_SCHEMA . ', "isGlobalStylesUserThemeJSON": true }', - 'post_status' => 'publish', - 'post_title' => __( 'Custom Styles', 'default' ), - 'post_type' => 'wp_global_styles', - 'post_name' => 'wp-global-styles-tt1-blocks-revisions-2', - 'tax_input' => array( - 'wp_theme' => 'tt1-blocks', - ), - ) - ); - - // Update post to create a new revisions. - $new_styles_post = array( - 'ID' => self::$global_styles_id, - 'post_content' => wp_json_encode( - array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, - 'isGlobalStylesUserThemeJSON' => true, - 'styles' => array( - 'color' => array( - 'background' => 'hotpink', - ), - ), - 'settings' => array( - 'color' => array( - 'palette' => array( - 'custom' => array( - array( - 'name' => 'Ghost', - 'slug' => 'ghost', - 'color' => 'ghost', - ), - ), - ), - ), - ), - ) - ), - ); - - wp_update_post( $new_styles_post, true, true ); - - $new_styles_post = array( - 'ID' => self::$global_styles_id, - 'post_content' => wp_json_encode( - array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, - 'isGlobalStylesUserThemeJSON' => true, - 'styles' => array( - 'color' => array( - 'background' => 'lemonchiffon', - ), - ), - 'settings' => array( - 'color' => array( - 'palette' => array( - 'custom' => array( - array( - 'name' => 'Gwanda', - 'slug' => 'gwanda', - 'color' => 'gwanda', - ), - ), - ), - ), - ), - ) - ), - ); - - wp_update_post( $new_styles_post, true, true ); - - $new_styles_post = array( - 'ID' => self::$global_styles_id, - 'post_content' => wp_json_encode( - array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, - 'isGlobalStylesUserThemeJSON' => true, - 'styles' => array( - 'color' => array( - 'background' => 'chocolate', - ), - ), - 'settings' => array( - 'color' => array( - 'palette' => array( - 'custom' => array( - array( - 'name' => 'Stacy', - 'slug' => 'stacy', - 'color' => 'stacy', - ), - ), - ), - ), - ), - ) - ), - ); - - wp_update_post( $new_styles_post, true, true ); - wp_set_current_user( 0 ); - } - - /** - * Removes users after our tests run. - */ - public static function wpTearDownAfterClass() { - self::delete_user( self::$admin_id ); - } - - /** - * Sets up before tests. - */ - public function set_up() { - parent::set_up(); - switch_theme( 'emptytheme' ); - $revisions = wp_get_post_revisions( self::$global_styles_id ); - $this->revision_1 = array_pop( $revisions ); - $this->revision_1_id = $this->revision_1->ID; - - /* - * For some reason the `rest_api_init` doesn't run early enough to ensure an overwritten `get_item_schema()` - * is used. So we manually call it here. - * See: https://github.com/WordPress/gutenberg/pull/52370#issuecomment-1643331655. - */ - $global_styles_revisions_controller = new Gutenberg_REST_Global_Styles_Revisions_Controller_6_5(); - $global_styles_revisions_controller->register_routes(); - } - - /** - * @ticket 58524 - * - * @covers WP_REST_Global_Styles_Controller::register_routes - */ - public function test_register_routes() { - $routes = rest_get_server()->get_routes(); - $this->assertArrayHasKey( - '/wp/v2/global-styles/(?P<parent>[\d]+)/revisions/(?P<id>[\d]+)', - $routes, - 'Single global style revisions based on the given parentID and revision ID route does not exist.' - ); - } - - /** - * @ticket 59810 - * - * @covers WP_REST_Global_Styles_Controller::get_items - */ - public function test_get_item_valid_parent_id() { - wp_set_current_user( self::$admin_id ); - $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions/' . $this->revision_1_id ); - $response = rest_get_server()->dispatch( $request ); - $data = $response->get_data(); - - $this->assertSame( self::$global_styles_id, $data['parent'], "The returned revision's id should match the parent id." ); - $this->check_get_revision_response( $data, $this->revision_1 ); - } - - /** - * @ticket 59810 - * - * @covers WP_REST_Global_Styles_Controller::get_items - */ - public function test_get_item_invalid_parent_id() { - wp_set_current_user( self::$admin_id ); - $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id_2 . '/revisions/' . $this->revision_1_id ); - $response = rest_get_server()->dispatch( $request ); - $this->assertErrorResponse( 'rest_revision_parent_id_mismatch', $response, 404 ); - - $expected_message = 'The revision does not belong to the specified parent with id of "' . self::$global_styles_id_2 . '"'; - $this->assertSame( $expected_message, $response->as_error()->get_error_messages()[0], 'The message must contain the correct parent ID.' ); - } - - /** - * Utility function to check the items in WP_REST_Global_Styles_Controller::get_items - * against the expected values. - * - * @ticket 58524 - */ - protected function check_get_revision_response( $response_revision_item, $revision_expected_item ) { - $this->assertSame( (int) $revision_expected_item->post_author, $response_revision_item['author'], 'Check that the revision item `author` exists.' ); - $this->assertSame( mysql_to_rfc3339( $revision_expected_item->post_date ), $response_revision_item['date'], 'Check that the revision item `date` exists.' ); - $this->assertSame( mysql_to_rfc3339( $revision_expected_item->post_date_gmt ), $response_revision_item['date_gmt'], 'Check that the revision item `date_gmt` exists.' ); - $this->assertSame( mysql_to_rfc3339( $revision_expected_item->post_modified ), $response_revision_item['modified'], 'Check that the revision item `modified` exists.' ); - $this->assertSame( mysql_to_rfc3339( $revision_expected_item->post_modified_gmt ), $response_revision_item['modified_gmt'], 'Check that the revision item `modified_gmt` exists.' ); - $this->assertSame( $revision_expected_item->post_parent, $response_revision_item['parent'], 'Check that an id for the parent exists.' ); - - // Global styles. - $config = ( new WP_Theme_JSON_Gutenberg( json_decode( $revision_expected_item->post_content, true ), 'custom' ) )->get_raw_data(); - $this->assertEquals( - $config['settings'], - $response_revision_item['settings'], - 'Check that the revision settings exist in the response.' - ); - $this->assertEquals( - $config['styles'], - $response_revision_item['styles'], - 'Check that the revision styles match the updated styles.' - ); - } - - /** - * @ticket 59810 - * - * @covers Gutenberg_REST_Global_Styles_Revisions_Controller_6_4::get_item - */ - public function test_get_item() { - wp_set_current_user( self::$admin_id ); - - $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions/' . $this->revision_1_id ); - $response = rest_get_server()->dispatch( $request ); - $data = $response->get_data(); - - $this->assertSame( 200, $response->get_status(), 'Response status is 200.' ); - $this->check_get_revision_response( $data, $this->revision_1 ); - } - - /** - * @ticket 59810 - * - * @covers Gutenberg_REST_Global_Styles_Revisions_Controller_6_4::get_revision - */ - public function test_get_item_invalid_revision_id_should_error() { - wp_set_current_user( self::$admin_id ); - - $expected_error = 'rest_post_invalid_id'; - $expected_status = 404; - $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions/20000001' ); - $response = rest_get_server()->dispatch( $request ); - - $this->assertErrorResponse( $expected_error, $response, $expected_status ); - } - - /** - * @doesNotPerformAssertions - */ - public function test_get_items() { - // Unit tests have been more to WordPress Core for test_get_items(). - // No unique compat unit tests exist. - } - - /** - * @doesNotPerformAssertions - */ - public function test_get_item_schema() { - // Unit tests have been more to WordPress Core for test_get_item_schema(). - // No unique compat unit tests exist. - } - - /** - * @doesNotPerformAssertions - */ - public function test_context_param() { - // Controller does not implement test_context_param(). - } - - /** - * @doesNotPerformAssertions - */ - public function test_create_item() { - // Controller does not implement create_item(). - } - - /** - * @doesNotPerformAssertions - */ - public function test_delete_item() { - // Controller does not implement delete_item(). - } - - /** - * @doesNotPerformAssertions - */ - public function test_prepare_item() { - // Controller does not implement prepare_item(). - } - - /** - * @doesNotPerformAssertions - */ - public function test_update_item() { - // Controller does not implement update_item(). - } -} diff --git a/phpunit/tests/fonts/font-library/fontFamilyBackwardsCompatibility.php b/phpunit/tests/fonts/font-library/fontFamilyBackwardsCompatibility.php deleted file mode 100644 index dc720b6b7db701..00000000000000 --- a/phpunit/tests/fonts/font-library/fontFamilyBackwardsCompatibility.php +++ /dev/null @@ -1,196 +0,0 @@ -<?php -// @core-merge: Do not include these tests, they are for Gutenberg only. - -/** - * Test deleting converting legacy font family posts into font family and font faces. - * - * @package WordPress - * @subpackage Font Library - * - * @group fonts - * @group font-library - */ -class Tests_Font_Family_Backwards_Compatibility extends WP_UnitTestCase { - private $post_ids_to_delete; - - public function set_up() { - parent::set_up(); - - $this->post_ids_to_delete = array(); - delete_option( 'gutenberg_font_family_format_converted' ); - } - - public function tear_down() { - foreach ( $this->post_ids_to_delete as $post_id ) { - wp_delete_post( $post_id, true ); - } - - delete_option( 'gutenberg_font_family_format_converted' ); - - parent::tear_down(); - } - - public function test_font_faces_with_remote_src() { - $legacy_content = '{"fontFace":[{"fontFamily":"Open Sans","fontStyle":"normal","fontWeight":"400","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans-400-normal.svg","src":"https://fonts.gstatic.com/s/opensans/v35/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4nY1M2xLER.ttf"},{"fontFamily":"Open Sans","fontStyle":"italic","fontWeight":"400","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans-400-italic.svg","src":"https://fonts.gstatic.com/s/opensans/v35/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkaVcUwaERZjA.ttf"},{"fontFamily":"Open Sans","fontStyle":"normal","fontWeight":"700","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans-700-normal.svg","src":"https://fonts.gstatic.com/s/opensans/v35/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1y4nY1M2xLER.ttf"}],"fontFamily":"\'Open Sans\', sans-serif","name":"Open Sans","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans.svg","slug":"open-sans"}'; - - $font_family_id = $this->create_font_family( $legacy_content ); - - gutenberg_convert_legacy_font_family_format(); - - $font_family = $this->get_post( $font_family_id ); - $font_faces = $this->get_font_faces( $font_family_id ); - - list( $font_face1, $font_face2, $font_face3 ) = $font_faces; - - // Updated font family post. - $this->assertSame( 'wp_font_family', $font_family->post_type, 'The font family post type should be wp_font_family.' ); - $this->assertSame( 'publish', $font_family->post_status, 'The font family post status should be publish.' ); - - $font_family_title = 'Open Sans'; - $this->assertSame( $font_family_title, $font_family->post_title, 'The font family post title should be Open Sans.' ); - - $font_family_slug = 'open-sans'; - $this->assertSame( $font_family_slug, $font_family->post_name, 'The font family post name should be open-sans.' ); - - $font_family_content = wp_json_encode( json_decode( '{"fontFamily":"\'Open Sans\', sans-serif","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans.svg"}', true ) ); - $this->assertSame( $font_family_content, $font_family->post_content, 'The font family post content should match.' ); - - $meta = get_post_meta( $font_family_id, '_gutenberg_legacy_font_family', true ); - $this->assertSame( $legacy_content, $meta, 'The _gutenberg_legacy_font_family post meta content should match.' ); - - // First font face post. - $this->assertSame( 'wp_font_face', $font_face1->post_type, 'The 1st font face post type should be wp_font_face.' ); - $this->assertSame( $font_family_id, $font_face1->post_parent, 'The 1st font face post parent should match.' ); - $this->assertSame( 'publish', $font_face1->post_status, 'The 1st font face post status should be publish.' ); - - $font_face1_title = 'open sans;normal;400;100%;U+0-10FFFF'; - $this->assertSame( $font_face1_title, $font_face1->post_title, 'The 1st font face post title should match.' ); - $this->assertSame( sanitize_title( $font_face1_title ), $font_face1->post_name, 'The 1st font face post name should match.' ); - - $font_face1_content = wp_json_encode( json_decode( '{"fontFamily":"Open Sans","fontStyle":"normal","fontWeight":"400","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans-400-normal.svg","src":"https://fonts.gstatic.com/s/opensans/v35/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4nY1M2xLER.ttf"}' ) ); - $this->assertSame( $font_face1_content, $font_face1->post_content, 'The 1st font face post content should match.' ); - - // With a remote url, file post meta should not be set. - $meta = get_post_meta( $font_face1->ID, '_wp_font_face_file', true ); - $this->assertSame( '', $meta, 'The _wp_font_face_file post meta for the 1st font face should be an empty string.' ); - - // Second font face post. - $this->assertSame( 'wp_font_face', $font_face2->post_type, 'The 2nd font face post type should be wp_font_face.' ); - $this->assertSame( $font_family_id, $font_face2->post_parent, 'The 2md font face post type should be wp_font_face.' ); - $this->assertSame( 'publish', $font_face2->post_status, 'The 2nd font face post status should be publish.' ); - - $font_face2_title = 'open sans;italic;400;100%;U+0-10FFFF'; - $this->assertSame( $font_face2_title, $font_face2->post_title, 'The 2nd font face post title should match.' ); - $this->assertSame( sanitize_title( $font_face2_title ), $font_face2->post_name, 'The 2nd font face post name should match.' ); - - $font_face2_content = wp_json_encode( json_decode( '{"fontFamily":"Open Sans","fontStyle":"italic","fontWeight":"400","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans-400-italic.svg","src":"https://fonts.gstatic.com/s/opensans/v35/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkaVcUwaERZjA.ttf"}' ) ); - $this->assertSame( $font_face2_content, $font_face2->post_content, 'The 2nd font face post content should match.' ); - - // With a remote url, file post meta should not be set. - $meta = get_post_meta( $font_face2->ID, '_wp_font_face_file', true ); - $this->assertSame( '', $meta, 'The _wp_font_face_file post meta for the 2nd font face should be an empty string.' ); - - // Third font face post. - $this->assertSame( 'wp_font_face', $font_face3->post_type, 'The 3rd font face post type should be wp_font_face.' ); - $this->assertSame( $font_family_id, $font_face3->post_parent, 'The 3rd font face post type should be wp_font_face.' ); - $this->assertSame( 'publish', $font_face3->post_status, 'The 3rd font face post status should be publish.' ); - - $font_face3_title = 'open sans;normal;700;100%;U+0-10FFFF'; - $this->assertSame( $font_face3_title, $font_face3->post_title, 'The 3rd font face post title should match.' ); - $this->assertSame( sanitize_title( $font_face3_title ), $font_face3->post_name, 'The 3rd font face post name should match.' ); - - $font_face3_content = wp_json_encode( json_decode( '{"fontFamily":"Open Sans","fontStyle":"normal","fontWeight":"700","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans-700-normal.svg","src":"https://fonts.gstatic.com/s/opensans/v35/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1y4nY1M2xLER.ttf"}' ) ); - $this->assertSame( $font_face3_content, $font_face3->post_content, 'The 3rd font face post content should match.' ); - - // With a remote url, file post meta should not be set. - $meta = get_post_meta( $font_face3->ID, '_wp_font_face_file', true ); - $this->assertSame( '', $meta, 'The _wp_font_face_file post meta for the 3rd font face should be an empty string.' ); - } - - public function test_font_faces_with_local_src() { - $legacy_content = '{"fontFace":[{"fontFamily":"Open Sans","fontStyle":"normal","fontWeight":"400","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans-400-normal.svg","src":"' . site_url() . '/wp-content/fonts/open-sans_normal_400.ttf"}],"fontFamily":"\'Open Sans\', sans-serif","name":"Open Sans","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans.svg","slug":"open-sans"}'; - - $font_family_id = $this->create_font_family( $legacy_content ); - - gutenberg_convert_legacy_font_family_format(); - - $font_faces = $this->get_font_faces( $font_family_id ); - - $this->assertCount( 1, $font_faces, 'There should be 1 font face.' ); - $font_face = reset( $font_faces ); - - // Check that file meta is present. - $file_path = 'open-sans_normal_400.ttf'; - $meta = get_post_meta( $font_face->ID, '_wp_font_face_file', true ); - $this->assertSame( $file_path, $meta, 'The _wp_font_face_file should match.' ); - } - - public function test_migration_only_runs_once() { - $legacy_content = '{"fontFace":[],"fontFamily":"\'Open Sans\', sans-serif","name":"Open Sans","preview":"","slug":"open-sans"}'; - - // Simulate that the migration has already run. - update_option( 'gutenberg_font_family_format_converted', true ); - - $font_family_id = $this->create_font_family( $legacy_content ); - - gutenberg_convert_legacy_font_family_format(); - - // Meta with backup content will not be present if migration isn't triggered. - $meta = get_post_meta( $font_family_id, '_gutenberg_legacy_font_family', true ); - $this->assertSame( '', $meta ); - } - - protected function create_font_family( $content ) { - $post_id = wp_insert_post( - array( - 'post_type' => 'wp_font_family', - 'post_status' => 'publish', - 'post_title' => 'Open Sans', - 'post_name' => 'open-sans', - 'post_content' => $content, - ) - ); - - $this->store_id_for_cleanup_in_teardown( $post_id ); - - return $post_id; - } - - private function get_post( $post_id ) { - $post = get_post( $post_id ); - - $this->store_id_for_cleanup_in_teardown( $post ); - - return $post; - } - - protected function get_font_faces( $font_family_id ) { - $posts = get_posts( - array( - 'post_parent' => $font_family_id, - 'post_type' => 'wp_font_face', - 'order' => 'ASC', - 'orderby' => 'id', - ) - ); - - $this->store_id_for_cleanup_in_teardown( $posts ); - - return $posts; - } - - private function store_id_for_cleanup_in_teardown( $post ) { - if ( null === $post ) { - return; - } - - $posts = is_array( $post ) ? $post : array( $post ); - - foreach ( $posts as $post ) { - if ( null === $post ) { - continue; - } - $this->post_ids_to_delete[] = is_int( $post ) ? $post : $post->ID; - } - } -} From 25af7e3c49059cf57085a385f98ca99b00d195b3 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 31 Jul 2024 12:13:48 +0400 Subject: [PATCH 0177/1908] Plugin: Bump minimum required WordPress version to 6.5 (#64126) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .github/workflows/performance.yml | 6 +++--- gutenberg.php | 2 +- readme.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index 288bef1580038f..98615b93b8a176 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -69,13 +69,13 @@ jobs: - name: Compare performance with base branch if: github.event_name == 'push' # The base hash used here need to be a commit that is compatible with the current WP version - # The current one is 9725060a5b18904c6cc5fdbe4b06fbde7419e02c and it needs to be updated every WP major release. + # The current one is 5f4c9c853b15092ed885d5280edefb973c37d9e9 and it needs to be updated every WP major release. # It is used as a base comparison point to avoid fluctuation in the performance metrics. run: | WP_VERSION=$(awk -F ': ' '/^Tested up to/{print $2}' readme.txt) IFS=. read -ra WP_VERSION_ARRAY <<< "$WP_VERSION" WP_MAJOR="${WP_VERSION_ARRAY[0]}.${WP_VERSION_ARRAY[1]}" - ./bin/plugin/cli.js perf $GITHUB_SHA 9725060a5b18904c6cc5fdbe4b06fbde7419e02c --tests-branch $GITHUB_SHA --wp-version "$WP_MAJOR" + ./bin/plugin/cli.js perf $GITHUB_SHA 5f4c9c853b15092ed885d5280edefb973c37d9e9 --tests-branch $GITHUB_SHA --wp-version "$WP_MAJOR" - name: Compare performance with custom branches if: github.event_name == 'workflow_dispatch' @@ -101,7 +101,7 @@ jobs: CODEHEALTH_PROJECT_TOKEN: ${{ secrets.CODEHEALTH_PROJECT_TOKEN }} run: | COMMITTED_AT=$(git show -s $GITHUB_SHA --format="%cI") - ./bin/log-performance-results.js $CODEHEALTH_PROJECT_TOKEN trunk $GITHUB_SHA 9725060a5b18904c6cc5fdbe4b06fbde7419e02c $COMMITTED_AT + ./bin/log-performance-results.js $CODEHEALTH_PROJECT_TOKEN trunk $GITHUB_SHA 5f4c9c853b15092ed885d5280edefb973c37d9e9 $COMMITTED_AT - name: Archive debug artifacts (screenshots, HTML snapshots) uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 diff --git a/gutenberg.php b/gutenberg.php index dfe3e6dc8a4285..07a607327ceddd 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -3,7 +3,7 @@ * Plugin Name: Gutenberg * Plugin URI: https://github.com/WordPress/gutenberg * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. - * Requires at least: 6.4 + * Requires at least: 6.5 * Requires PHP: 7.2 * Version: 18.9.0-rc.1 * Author: Gutenberg Team diff --git a/readme.txt b/readme.txt index 3fe6e3aaf1dc4d..c5ef1231b183ee 100644 --- a/readme.txt +++ b/readme.txt @@ -1,6 +1,6 @@ === Gutenberg === Contributors: matveb, joen, karmatosed -Tested up to: 6.5 +Tested up to: 6.6 Stable tag: V.V.V License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html From d5e7a77eb851329da16510f758bdd742099fb5ac Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 31 Jul 2024 17:59:53 +0900 Subject: [PATCH 0178/1908] Improve `Button` matrix in visual regression test (#64120) * Add new variants * Improve Button matrix * Add guidance in Button stylesheet --- Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../src/button/stories/e2e/index.story.tsx | 124 +++++++++++++++--- packages/components/src/button/style.scss | 7 + 2 files changed, 110 insertions(+), 21 deletions(-) diff --git a/packages/components/src/button/stories/e2e/index.story.tsx b/packages/components/src/button/stories/e2e/index.story.tsx index a4fcfdeac5ca48..d2651e8df1ec18 100644 --- a/packages/components/src/button/stories/e2e/index.story.tsx +++ b/packages/components/src/button/stories/e2e/index.story.tsx @@ -31,28 +31,110 @@ export const VariantStates: StoryFn< typeof Button > = ( 'link', ]; - return ( - <div style={ { display: 'flex', flexDirection: 'column', gap: 24 } }> - { variants.map( ( variant ) => ( - <div - style={ { display: 'flex', gap: 8 } } - key={ variant ?? 'undefined' } + const VariantsRow = ( { + buttonProps, + name, + }: { + buttonProps?: ButtonAsButtonProps; + name: string; + } ) => { + return ( + <tr> + <th + style={ { + fontSize: 13, + fontWeight: 'normal', + padding: 8, + background: '#f3f4f5', + } } > - <Button { ...props } variant={ variant } /> - { /* eslint-disable-next-line no-restricted-syntax */ } - <Button { ...props } variant={ variant } disabled /> - <Button - { ...props } - variant={ variant } - disabled - accessibleWhenDisabled - /> - <Button { ...props } variant={ variant } isBusy /> - <Button { ...props } variant={ variant } isDestructive /> - <Button { ...props } variant={ variant } isPressed /> - </div> - ) ) } - </div> + { name } + </th> + { variants.map( ( variant ) => ( + <td key={ variant ?? 'undefined' } style={ { padding: 4 } }> + <Button + { ...props } + variant={ variant } + { ...buttonProps } + /> + </td> + ) ) } + </tr> + ); + }; + + return ( + <table> + <thead> + <tr style={ { background: '#f3f4f5' } }> + <th /> + { variants.map( ( variant ) => ( + <th + key={ variant ?? 'undefined' } + style={ { padding: 8 } } + > + { variant ?? '(default)' } + </th> + ) ) } + </tr> + </thead> + <tbody> + <VariantsRow name="(default)" /> + <VariantsRow + name="disabled" + buttonProps={ { disabled: true } } + /> + <VariantsRow + name="focusable disabled" + buttonProps={ { + accessibleWhenDisabled: true, + disabled: true, + } } + /> + <VariantsRow + name="isBusy" + buttonProps={ { + isBusy: true, + } } + /> + <VariantsRow + name="isBusy disabled" + buttonProps={ { + isBusy: true, + accessibleWhenDisabled: true, + disabled: true, + } } + /> + <VariantsRow + name="isDestructive" + buttonProps={ { + isDestructive: true, + } } + /> + <VariantsRow + name="isDestructive disabled" + buttonProps={ { + isDestructive: true, + accessibleWhenDisabled: true, + disabled: true, + } } + /> + <VariantsRow + name="isPressed" + buttonProps={ { + isPressed: true, + } } + /> + <VariantsRow + name="isPressed disabled" + buttonProps={ { + isPressed: true, + accessibleWhenDisabled: true, + disabled: true, + } } + /> + </tbody> + </table> ); }; VariantStates.args = { diff --git a/packages/components/src/button/style.scss b/packages/components/src/button/style.scss index ae242c38634180..3541699a08eefd 100644 --- a/packages/components/src/button/style.scss +++ b/packages/components/src/button/style.scss @@ -1,3 +1,10 @@ +/** + * For easier testing of potential regressions, you can use a Button variant matrix + * available in a special Storybook instance by running `npm run storybook:e2e:dev`. + * + * @see https://github.com/WordPress/gutenberg/blob/trunk/test/storybook-playwright/README.md + */ + .components-button { display: inline-flex; text-decoration: none; From de89af5e4f8155e50878c442197b9b0641f42bdd Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Wed, 31 Jul 2024 17:41:01 +0800 Subject: [PATCH 0179/1908] Improve theme.json test failure messages by pretty printing css for a more accurate diff (#64077) * Add basic formatting function and apply to one test WIP Add comment * Add assertSameCSS expectation which outputs pretty printed test failure along with raw css for updating the test Update accidentally committed test failure Fix expected,actual order and minimize diff Fix - make sure the actual is output in addition to the pretty printed failure, not the expected Update test expectation so test passes Revert "Update test expectation so test passes" This reverts commit c9f655ac55aeee96badd9bbd14ee3bec3dce127d. Update test expectation so test passes * Convert comment to docblock ---- Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- phpunit/class-wp-theme-json-test.php | 152 +++++++++++++++++---------- 1 file changed, 96 insertions(+), 56 deletions(-) diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 36b8218785f216..8d2f470efe60fe 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -46,6 +46,52 @@ public static function set_up_before_class() { static::$user_id = self::factory()->user->create(); } + /** + * Pretty print CSS in test assertions so that it provides a better diff when a test fails. + * Without this: the failing test outputs the entire css string as being different. + * With this: the failing test only highlights the specific CSS rule that is different. + * + * @param string $css A string of raw css with no line breaks. + * @return string The css with line breaks. + */ + private static function pretty_print_css( $css ) { + $css = str_replace( '{', " {\n", $css ); + $css = str_replace( '}', "}\n\n", $css ); + $css = str_replace( ';', ";\n", $css ); + return $css; + } + + /** + * Asserts that two CSS strings are equivalent, but outputs + * pretty printed test failures along with the raw css. + * + * - The pretty printed assertions are useful for understanding what actually changed. + * - The raw css is included as it's useful for updating the test case's expected CSS. + * + * Inspired by: + * https://stackoverflow.com/questions/6832263/phpunit-assertion-failed-but-i-want-to-continue-testing + * + * @param string $expected The expected CSS. + * @param string $actual The actual CSS. + */ + private function assertSameCSS( $expected, $actual, $message = '' ) { + $pretty_expected = self::pretty_print_css( $expected ); + $pretty_actual = self::pretty_print_css( $actual ); + + try { + $this->assertSame( $pretty_expected, $pretty_actual, $message ); + } catch ( PHPUnit_Framework_ExpectationFailedException $e ) { + // Test failures are thrown as exceptions by PHPUnit. + // Catch the exception and re-throw it, but with the + // raw css appended. + $raw_actual_output = + "\n\nIf the change is expected, update the test case to this CSS:\n$actual"; + throw new PHPUnit_Framework_ExpectationFailedException( + "$e$raw_actual_output" + ); + } + } + public function test_get_settings() { $theme_json = new WP_Theme_JSON_Gutenberg( array( @@ -556,10 +602,10 @@ public function test_get_stylesheet() { $presets = '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-custom-gradient-gradient-background{background: var(--wp--preset--gradient--custom-gradient) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-big-font-size{font-size: var(--wp--preset--font-size--big) !important;}.has-arial-font-family{font-family: var(--wp--preset--font-family--arial) !important;}'; $all = $variables . $styles . $presets; - $this->assertSame( $variables, $theme_json->get_stylesheet( array( 'variables' ) ) ); - $this->assertSame( $styles, $theme_json->get_stylesheet( array( 'styles' ) ) ); - $this->assertSame( $presets, $theme_json->get_stylesheet( array( 'presets' ) ) ); - $this->assertSame( $all, $theme_json->get_stylesheet() ); + $this->assertSameCSS( $variables, $theme_json->get_stylesheet( array( 'variables' ) ) ); + $this->assertSameCSS( $styles, $theme_json->get_stylesheet( array( 'styles' ) ) ); + $this->assertSameCSS( $presets, $theme_json->get_stylesheet( array( 'presets' ) ) ); + $this->assertSameCSS( $all, $theme_json->get_stylesheet() ); } public function test_get_styles_for_block_support_for_shorthand_and_longhand_values() { @@ -618,8 +664,8 @@ public function test_get_styles_for_block_support_for_shorthand_and_longhand_val $group_styles = ':root :where(.wp-block-group){border-radius: 10px;margin: 1em;padding: 24px;}'; $image_styles = ':root :where(.wp-block-image){margin-bottom: 30px;padding-top: 15px;}:root :where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-top-left-radius: 10px;border-bottom-right-radius: 1em;}'; - $this->assertSame( $group_styles, $theme_json->get_styles_for_block( $group_node ) ); - $this->assertSame( $image_styles, $theme_json->get_styles_for_block( $image_node ) ); + $this->assertSameCSS( $group_styles, $theme_json->get_styles_for_block( $group_node ) ); + $this->assertSameCSS( $image_styles, $theme_json->get_styles_for_block( $image_node ) ); } public function test_get_stylesheet_skips_disabled_protected_properties() { @@ -647,8 +693,8 @@ public function test_get_stylesheet_skips_disabled_protected_properties() { ); $expected = static::$base_styles . ':where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet() ); - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet() ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); } public function test_get_stylesheet_renders_enabled_protected_properties() { @@ -669,8 +715,8 @@ public function test_get_stylesheet_renders_enabled_protected_properties() { ); $expected = ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1em; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1em; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-flex {gap: 1em;}.is-layout-grid {gap: 1em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet() ); - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet() ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); } public function test_get_stylesheet_preset_classes_work_with_compounded_selectors() { @@ -694,7 +740,7 @@ public function test_get_stylesheet_preset_classes_work_with_compounded_selector ) ); - $this->assertSame( + $this->assertSameCSS( '.wp-block-heading.has-white-color{color: var(--wp--preset--color--white) !important;}.wp-block-heading.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.wp-block-heading.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}', $theme_json->get_stylesheet( array( 'presets' ) ) ); @@ -736,10 +782,10 @@ public function test_get_stylesheet_preset_rules_come_after_block_rules() { $all = $variables . $styles . $presets; - $this->assertSame( $all, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); - $this->assertSame( $styles, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); - $this->assertSame( $presets, $theme_json->get_stylesheet( array( 'presets' ) ) ); - $this->assertSame( $variables, $theme_json->get_stylesheet( array( 'variables' ) ) ); + $this->assertSameCSS( $all, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $styles, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $presets, $theme_json->get_stylesheet( array( 'presets' ) ) ); + $this->assertSameCSS( $variables, $theme_json->get_stylesheet( array( 'variables' ) ) ); } public function test_get_stylesheet_generates_proper_classes_and_css_vars_from_slugs() { @@ -774,11 +820,11 @@ public function test_get_stylesheet_generates_proper_classes_and_css_vars_from_s ) ); - $this->assertSame( + $this->assertSameCSS( '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-dark-grey-color{color: var(--wp--preset--color--dark-grey) !important;}.has-light-grey-color{color: var(--wp--preset--color--light-grey) !important;}.has-white-2-black-color{color: var(--wp--preset--color--white-2-black) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-dark-grey-background-color{background-color: var(--wp--preset--color--dark-grey) !important;}.has-light-grey-background-color{background-color: var(--wp--preset--color--light-grey) !important;}.has-white-2-black-background-color{background-color: var(--wp--preset--color--white-2-black) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-dark-grey-border-color{border-color: var(--wp--preset--color--dark-grey) !important;}.has-light-grey-border-color{border-color: var(--wp--preset--color--light-grey) !important;}.has-white-2-black-border-color{border-color: var(--wp--preset--color--white-2-black) !important;}', $theme_json->get_stylesheet( array( 'presets' ) ) ); - $this->assertSame( + $this->assertSameCSS( ':root{--wp--preset--color--grey: grey;--wp--preset--color--dark-grey: grey;--wp--preset--color--light-grey: grey;--wp--preset--color--white-2-black: grey;--wp--custom--white-2-black: value;}', $theme_json->get_stylesheet( array( 'variables' ) ) ); @@ -834,9 +880,9 @@ public function test_get_styles_for_block_handles_whitelisted_element_pseudo_sel $hover_style = ':root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}'; $focus_style = ':root :where(a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; - $this->assertSame( $link_style, $theme_json->get_styles_for_block( $link_node ) ); - $this->assertSame( $hover_style, $theme_json->get_styles_for_block( $hover_node ) ); - $this->assertSame( $focus_style, $theme_json->get_styles_for_block( $focus_node ) ); + $this->assertSameCSS( $link_style, $theme_json->get_styles_for_block( $link_node ) ); + $this->assertSameCSS( $hover_style, $theme_json->get_styles_for_block( $hover_node ) ); + $this->assertSameCSS( $focus_style, $theme_json->get_styles_for_block( $focus_node ) ); } /** @@ -872,8 +918,7 @@ public function test_get_stylesheet_handles_only_pseudo_selector_rules_for_given ); $expected = ':root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:root :where(a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; - - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_stylesheet_ignores_pseudo_selectors_on_non_whitelisted_elements() { @@ -906,8 +951,7 @@ public function test_get_stylesheet_ignores_pseudo_selectors_on_non_whitelisted_ ); $expected = 'h4{background-color: red;color: green;}'; - - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_stylesheet_ignores_non_whitelisted_pseudo_selectors() { @@ -940,8 +984,7 @@ public function test_get_stylesheet_ignores_non_whitelisted_pseudo_selectors() { ); $expected = 'a:where(:not(.wp-element-button)){background-color: red;color: green;}:root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;}'; - - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); $this->assertStringNotContainsString( 'a:levitate{', $theme_json->get_stylesheet( array( 'styles' ) ) ); } @@ -987,8 +1030,7 @@ public function test_get_stylesheet_handles_priority_of_elements_vs_block_elemen ); $expected = ':root :where(.wp-block-group a:where(:not(.wp-element-button))){background-color: red;color: green;}:root :where(.wp-block-group a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:root :where(.wp-block-group a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; - - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } /** @@ -1032,8 +1074,7 @@ public function test_get_stylesheet_with_deprecated_feature_level_selectors() { $block_styles = ':root :where(.wp-block-calendar){font-size: 3em;}:root :where(.wp-block-calendar table, .wp-block-calendar th){color: green;}'; $preset_styles = '.has-green-color{color: var(--wp--preset--color--green) !important;}.has-green-background-color{background-color: var(--wp--preset--color--green) !important;}.has-green-border-color{border-color: var(--wp--preset--color--green) !important;}'; $expected = $base_styles . $block_styles . $preset_styles; - - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); } @@ -1063,8 +1104,7 @@ public function test_get_stylesheet_with_block_json_selectors() { ); $expected = ':root :where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-radius: 374px;}'; - - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_stylesheet_generates_layout_styles() { @@ -1090,7 +1130,7 @@ public function test_get_stylesheet_generates_layout_styles() { ); // Results also include root site blocks styles. - $this->assertSame( + $this->assertSameCSS( ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1em; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1em; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-flex {gap: 1em;}.is-layout-grid {gap: 1em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}', $theme_json->get_stylesheet( array( 'styles' ) ) ); @@ -1119,7 +1159,7 @@ public function test_get_stylesheet_generates_layout_styles_with_spacing_presets ); // Results also include root site blocks styles. - $this->assertSame( + $this->assertSameCSS( ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: var(--wp--preset--spacing--60); margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: var(--wp--preset--spacing--60); }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}.is-layout-flex {gap: var(--wp--preset--spacing--60);}.is-layout-grid {gap: var(--wp--preset--spacing--60);}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}', $theme_json->get_stylesheet( array( 'styles' ) ) ); @@ -1149,7 +1189,7 @@ public function test_get_stylesheet_generates_fallback_gap_layout_styles() { $stylesheet = $theme_json->get_stylesheet( array( 'styles' ) ); // Results also include root site blocks styles. - $this->assertSame( + $this->assertSameCSS( ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}', $stylesheet ); @@ -1170,7 +1210,7 @@ public function test_get_stylesheet_generates_base_fallback_gap_layout_styles() $stylesheet = $theme_json->get_stylesheet( array( 'base-layout-styles' ) ); // Note the `base-layout-styles` includes a fallback gap for the Columns block for backwards compatibility. - $this->assertSame( + $this->assertSameCSS( ':where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}', $stylesheet ); @@ -1193,7 +1233,7 @@ public function test_get_stylesheet_skips_layout_styles() { remove_theme_support( 'disable-layout-styles' ); // All Layout styles should be skipped. - $this->assertSame( + $this->assertSameCSS( '', $stylesheet ); @@ -1243,7 +1283,7 @@ public function test_get_stylesheet_generates_valid_block_gap_values_and_skips_n 'default' ); - $this->assertSame( + $this->assertSameCSS( ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1rem; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1rem; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1rem;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1rem;margin-block-end: 0;}.is-layout-flex {gap: 1rem;}.is-layout-grid {gap: 1rem;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}' . ':root :where(.wp-block-post-content){color: gray;}.wp-block-social-links-is-layout-flow > :first-child{margin-block-start: 0;}.wp-block-social-links-is-layout-flow > :last-child{margin-block-end: 0;}.wp-block-social-links-is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-social-links-is-layout-constrained > :first-child{margin-block-start: 0;}.wp-block-social-links-is-layout-constrained > :last-child{margin-block-end: 0;}.wp-block-social-links-is-layout-constrained > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-social-links-is-layout-flex {gap: 0;}.wp-block-social-links-is-layout-grid {gap: 0;}.wp-block-buttons-is-layout-flow > :first-child{margin-block-start: 0;}.wp-block-buttons-is-layout-flow > :last-child{margin-block-end: 0;}.wp-block-buttons-is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-buttons-is-layout-constrained > :first-child{margin-block-start: 0;}.wp-block-buttons-is-layout-constrained > :last-child{margin-block-end: 0;}.wp-block-buttons-is-layout-constrained > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-buttons-is-layout-flex {gap: 0;}.wp-block-buttons-is-layout-grid {gap: 0;}', $theme_json->get_stylesheet() @@ -1279,7 +1319,7 @@ public function test_get_stylesheet_returns_outline_styles() { $expected = ':root :where(.wp-element-button, .wp-block-button__link){outline-color: red;outline-offset: 3px;outline-style: dashed;outline-width: 3px;}:root :where(.wp-element-button:hover, .wp-block-button__link:hover){outline-color: blue;outline-offset: 3px;outline-style: solid;outline-width: 3px;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_stylesheet_custom_root_selector() { @@ -1302,7 +1342,7 @@ public function test_get_stylesheet_custom_root_selector() { ); $actual = $theme_json->get_stylesheet( array( 'styles' ), null, $options ); - $this->assertSame( + $this->assertSameCSS( ':root :where(.custom){color: teal;}', $actual ); @@ -1360,7 +1400,7 @@ public function test_get_stylesheet_generates_fluid_typography_values() { unregister_block_type( 'test/clamp-me' ); - $this->assertSame( + $this->assertSameCSS( ':root{--wp--preset--font-size--pickles: clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.156), 16px);--wp--preset--font-size--toast: clamp(14.642px, 0.915rem + ((1vw - 3.2px) * 0.575), 22px);}body{font-size: clamp(0.875em, 0.875rem + ((1vw - 0.2em) * 0.156), 1em);}h1{font-size: clamp(50.171px, 3.136rem + ((1vw - 3.2px) * 3.893), 100px);}:root :where(.wp-block-test-clamp-me){font-size: clamp(27.894px, 1.743rem + ((1vw - 3.2px) * 1.571), 48px);}.has-pickles-font-size{font-size: var(--wp--preset--font-size--pickles) !important;}.has-toast-font-size{font-size: var(--wp--preset--font-size--toast) !important;}', $theme_json->get_stylesheet( array( 'styles', 'variables', 'presets' ), null, array( 'skip_root_layout_styles' => true ) ) ); @@ -3419,7 +3459,7 @@ public function test_get_property_value_valid() { ); $expected = 'body{background-color: #ffffff;color: #000000;}:root :where(.wp-element-button, .wp-block-button__link){background-color: #000000;color: #ffffff;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } /** @@ -3496,7 +3536,7 @@ public function test_get_property_value_loop() { ); $expected = 'body{background-color: #ffffff;}:root :where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } /** @@ -3528,7 +3568,7 @@ public function test_get_property_value_recursion() { ); $expected = 'body{background-color: #ffffff;color: #ffffff;}:root :where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } /** @@ -3551,7 +3591,7 @@ public function test_get_property_value_self() { ); $expected = 'body{background-color: #ffffff;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_styles_for_block_with_padding_aware_alignments() { @@ -3582,7 +3622,7 @@ public function test_get_styles_for_block_with_padding_aware_alignments() { $expected = ':where(body) { margin: 0; }.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }.has-global-padding :where(:not(.alignfull.is-layout-flow) > .has-global-padding:not(.wp-block-block, .alignfull)) { padding-right: 0; padding-left: 0; }.has-global-padding :where(:not(.alignfull.is-layout-flow) > .has-global-padding:not(.wp-block-block, .alignfull)) > .alignfull { margin-left: 0; margin-right: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}body{--wp--style--root--padding-top: 10px;--wp--style--root--padding-right: 12px;--wp--style--root--padding-bottom: 10px;--wp--style--root--padding-left: 12px;}'; $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ); $style_rules = $theme_json->get_styles_for_block( $metadata ); - $this->assertSame( $expected, $root_rules . $style_rules ); + $this->assertSameCSS( $expected, $root_rules . $style_rules ); } public function test_get_styles_for_block_without_padding_aware_alignments() { @@ -3610,7 +3650,7 @@ public function test_get_styles_for_block_without_padding_aware_alignments() { $expected = static::$base_styles . 'body{padding-top: 10px;padding-right: 12px;padding-bottom: 10px;padding-left: 12px;}'; $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ); $style_rules = $theme_json->get_styles_for_block( $metadata ); - $this->assertSame( $expected, $root_rules . $style_rules ); + $this->assertSameCSS( $expected, $root_rules . $style_rules ); } public function test_get_styles_with_content_width() { @@ -3632,7 +3672,7 @@ public function test_get_styles_with_content_width() { ); $expected = ':root { --wp--style--global--content-size: 800px;--wp--style--global--wide-size: 1000px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; - $this->assertSame( $expected, $theme_json->get_root_layout_rules( WP_Theme_JSON::ROOT_BLOCK_SELECTOR, $metadata ) ); + $this->assertSameCSS( $expected, $theme_json->get_root_layout_rules( WP_Theme_JSON::ROOT_BLOCK_SELECTOR, $metadata ) ); } public function test_get_styles_with_appearance_tools() { @@ -3651,7 +3691,7 @@ public function test_get_styles_with_appearance_tools() { ); $expected = ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: ; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: ; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1;margin-block-end: 0;}.is-layout-flex {gap: 1;}.is-layout-grid {gap: 1;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; - $this->assertSame( $expected, $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ) ); + $this->assertSameCSS( $expected, $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ) ); } public function test_sanitization() { @@ -4717,8 +4757,8 @@ public function test_shadow_preset_styles() { ); $expected_styles = ':root{--wp--preset--shadow--natural: 5px 5px 5px 0 black;--wp--preset--shadow--sharp: 5px 5px black;}'; - $this->assertSame( $expected_styles, $theme_json->get_stylesheet(), 'Styles returned from "::get_stylesheet()" does not match expectations' ); - $this->assertSame( $expected_styles, $theme_json->get_stylesheet( array( 'variables' ) ), 'Styles returned from "::get_stylesheet()" when requiring "variables" type does not match expectations' ); + $this->assertSameCSS( $expected_styles, $theme_json->get_stylesheet(), 'Styles returned from "::get_stylesheet()" does not match expectations' ); + $this->assertSameCSS( $expected_styles, $theme_json->get_stylesheet( array( 'variables' ) ), 'Styles returned from "::get_stylesheet()" when requiring "variables" type does not match expectations' ); } public function test_get_shadow_styles_for_blocks() { @@ -4756,7 +4796,7 @@ public function test_get_shadow_styles_for_blocks() { $variable_styles = ':root{--wp--preset--shadow--natural: 5px 5px 0 0 black;}'; $element_styles = 'a:where(:not(.wp-element-button)){box-shadow: var(--wp--preset--shadow--natural);}:root :where(.wp-element-button, .wp-block-button__link){box-shadow: var(--wp--preset--shadow--natural);}:root :where(p){box-shadow: var(--wp--preset--shadow--natural);}'; $expected_styles = $variable_styles . $element_styles; - $this->assertSame( $expected_styles, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSameCSS( $expected_styles, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_top_level_background_image_styles() { @@ -4783,7 +4823,7 @@ public function test_get_top_level_background_image_styles() { ); $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}body{background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;background-attachment: fixed;}"; - $this->assertSame( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background styles do not match expectations' ); + $this->assertSameCSS( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background styles do not match expectations' ); $theme_json = new WP_Theme_JSON_Gutenberg( array( @@ -4801,7 +4841,7 @@ public function test_get_top_level_background_image_styles() { ); $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}body{background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;background-attachment: fixed;}"; - $this->assertSame( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background image as string type do not match expectations' ); + $this->assertSameCSS( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background image as string type do not match expectations' ); } public function test_get_block_background_image_styles() { @@ -4844,7 +4884,7 @@ public function test_get_block_background_image_styles() { ); $quote_styles = ":root :where(.wp-block-quote){background-image: url('http://example.org/quote.png');background-position: center center;background-repeat: no-repeat;background-size: cover;}"; - $this->assertSame( $quote_styles, $theme_json->get_styles_for_block( $quote_node ), 'Styles returned from "::get_styles_for_block()" with block-level background styles do not match expectations' ); + $this->assertSameCSS( $quote_styles, $theme_json->get_styles_for_block( $quote_node ), 'Styles returned from "::get_styles_for_block()" with block-level background styles do not match expectations' ); $group_node = array( 'name' => 'core/group', @@ -4856,7 +4896,7 @@ public function test_get_block_background_image_styles() { ); $group_styles = ":root :where(.wp-block-group){background-image: url('http://example.org/group.png');background-position: center center;background-repeat: no-repeat;background-size: cover;background-attachment: fixed;}"; - $this->assertSame( $group_styles, $theme_json->get_styles_for_block( $group_node ), 'Styles returned from "::get_styles_for_block()" with block-level background styles as string type do not match expectations' ); + $this->assertSameCSS( $group_styles, $theme_json->get_styles_for_block( $group_node ), 'Styles returned from "::get_styles_for_block()" with block-level background styles as string type do not match expectations' ); } /** From 9c80dbdd6d0f67d3e0b3d35358f1a66b5c1f23f0 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Wed, 31 Jul 2024 11:07:46 +0100 Subject: [PATCH 0180/1908] Update radius variables in components config (#64133) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/src/utils/config-values.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/components/src/utils/config-values.js b/packages/components/src/utils/config-values.js index 2e102b8b0b77cc..ba92813bdbfb0f 100644 --- a/packages/components/src/utils/config-values.js +++ b/packages/components/src/utils/config-values.js @@ -42,6 +42,12 @@ export default Object.assign( {}, CONTROL_PROPS, TOGGLE_GROUP_CONTROL_PROPS, { colorScrollbarThumbHover: 'rgba(0, 0, 0, 0.5)', colorScrollbarTrack: 'rgba(0, 0, 0, 0.04)', elevationIntensity: 1, + radiusXSmall: '1px', + radiusSmall: '2px', + radiusMedium: '4px', + radiusLarge: '8px', + radiusFull: '9999px', + radiusRound: '50%', radiusBlockUi: '2px', borderWidth: '1px', borderWidthFocus: '1.5px', From 43846b05bb0fcd1f351bcb49dd6c6af8cc7079f8 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 31 Jul 2024 12:54:46 +0200 Subject: [PATCH 0181/1908] DataViews Extensibility: Allow unregistering restore post action (#64134) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/post-actions/actions.js | 110 +------------- .../editor/src/dataviews/actions/index.ts | 2 + .../src/dataviews/actions/restore-post.tsx | 134 ++++++++++++++++++ 3 files changed, 137 insertions(+), 109 deletions(-) create mode 100644 packages/editor/src/dataviews/actions/restore-post.tsx diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 0d5ac4764c37da..92a5cd0eec87d8 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { external, backup } from '@wordpress/icons'; +import { external } from '@wordpress/icons'; import { addQueryArgs } from '@wordpress/url'; import { useDispatch, useSelect } from '@wordpress/data'; import { decodeEntities } from '@wordpress/html-entities'; @@ -81,113 +81,6 @@ function isTemplateRemovable( template ) { ); } -const restorePostAction = { - id: 'restore', - label: __( 'Restore' ), - isPrimary: true, - icon: backup, - supportsBulk: true, - isEligible( { status, permissions } ) { - return status === 'trash' && permissions?.update; - }, - async callback( posts, { registry, onActionPerformed } ) { - const { createSuccessNotice, createErrorNotice } = - registry.dispatch( noticesStore ); - const { editEntityRecord, saveEditedEntityRecord } = - registry.dispatch( coreStore ); - await Promise.allSettled( - posts.map( ( post ) => { - return editEntityRecord( 'postType', post.type, post.id, { - status: 'draft', - } ); - } ) - ); - const promiseResult = await Promise.allSettled( - posts.map( ( post ) => { - return saveEditedEntityRecord( 'postType', post.type, post.id, { - throwOnError: true, - } ); - } ) - ); - - if ( promiseResult.every( ( { status } ) => status === 'fulfilled' ) ) { - let successMessage; - if ( posts.length === 1 ) { - successMessage = sprintf( - /* translators: The number of posts. */ - __( '"%s" has been restored.' ), - getItemTitle( posts[ 0 ] ) - ); - } else if ( posts[ 0 ].type === 'page' ) { - successMessage = sprintf( - /* translators: The number of posts. */ - __( '%d pages have been restored.' ), - posts.length - ); - } else { - successMessage = sprintf( - /* translators: The number of posts. */ - __( '%d posts have been restored.' ), - posts.length - ); - } - createSuccessNotice( successMessage, { - type: 'snackbar', - id: 'restore-post-action', - } ); - if ( onActionPerformed ) { - onActionPerformed( posts ); - } - } else { - // If there was at lease one failure. - let errorMessage; - // If we were trying to move a single post to the trash. - if ( promiseResult.length === 1 ) { - if ( promiseResult[ 0 ].reason?.message ) { - errorMessage = promiseResult[ 0 ].reason.message; - } else { - errorMessage = __( - 'An error occurred while restoring the post.' - ); - } - // If we were trying to move multiple posts to the trash - } else { - const errorMessages = new Set(); - const failedPromises = promiseResult.filter( - ( { status } ) => status === 'rejected' - ); - for ( const failedPromise of failedPromises ) { - if ( failedPromise.reason?.message ) { - errorMessages.add( failedPromise.reason.message ); - } - } - if ( errorMessages.size === 0 ) { - errorMessage = __( - 'An error occurred while restoring the posts.' - ); - } else if ( errorMessages.size === 1 ) { - errorMessage = sprintf( - /* translators: %s: an error message */ - __( 'An error occurred while restoring the posts: %s' ), - [ ...errorMessages ][ 0 ] - ); - } else { - errorMessage = sprintf( - /* translators: %s: a list of comma separated error messages */ - __( - 'Some errors occurred while restoring the posts: %s' - ), - [ ...errorMessages ].join( ',' ) - ); - } - } - createErrorNotice( errorMessage, { - type: 'snackbar', - } ); - } - }, -}; - const viewPostAction = { id: 'view-post', label: __( 'View' ), @@ -726,7 +619,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { isPattern && userCanCreatePostType && duplicatePatternAction, supportsTitle && renamePostAction, reorderPagesAction, - ! isTemplateOrTemplatePart && ! isPattern && restorePostAction, ...defaultActions, ].filter( Boolean ); // Filter actions based on provided context. If not provided diff --git a/packages/editor/src/dataviews/actions/index.ts b/packages/editor/src/dataviews/actions/index.ts index 6679b2d7d1b8f1..04addcb1cde4d2 100644 --- a/packages/editor/src/dataviews/actions/index.ts +++ b/packages/editor/src/dataviews/actions/index.ts @@ -11,6 +11,7 @@ import exportPattern from './export-pattern'; import resetPost from './reset-post'; import trashPost from './trash-post'; import permanentlyDeletePost from './permanently-delete-post'; +import restorePost from './restore-post'; // @ts-ignore import { store as editorStore } from '../../store'; @@ -23,6 +24,7 @@ export default function registerDefaultActions() { registerEntityAction( 'postType', 'wp_block', exportPattern ); registerEntityAction( 'postType', '*', resetPost ); + registerEntityAction( 'postType', '*', restorePost ); registerEntityAction( 'postType', '*', deletePost ); registerEntityAction( 'postType', '*', trashPost ); registerEntityAction( 'postType', '*', permanentlyDeletePost ); diff --git a/packages/editor/src/dataviews/actions/restore-post.tsx b/packages/editor/src/dataviews/actions/restore-post.tsx new file mode 100644 index 00000000000000..874eca91fee113 --- /dev/null +++ b/packages/editor/src/dataviews/actions/restore-post.tsx @@ -0,0 +1,134 @@ +/** + * WordPress dependencies + */ +import { backup } from '@wordpress/icons'; +import { store as coreStore } from '@wordpress/core-data'; +import { __, sprintf } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; +import type { Action } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import { getItemTitle, isTemplateOrTemplatePart } from './utils'; +import type { CoreDataError, PostWithPermissions } from '../types'; + +const restorePost: Action< PostWithPermissions > = { + id: 'restore', + label: __( 'Restore' ), + isPrimary: true, + icon: backup, + supportsBulk: true, + isEligible( item ) { + return ( + ! isTemplateOrTemplatePart( item ) && + item.type !== 'wp_block' && + item.status === 'trash' && + item.permissions?.update + ); + }, + async callback( posts, { registry, onActionPerformed } ) { + const { createSuccessNotice, createErrorNotice } = + registry.dispatch( noticesStore ); + const { editEntityRecord, saveEditedEntityRecord } = + registry.dispatch( coreStore ); + await Promise.allSettled( + posts.map( ( post ) => { + return editEntityRecord( 'postType', post.type, post.id, { + status: 'draft', + } ); + } ) + ); + const promiseResult = await Promise.allSettled( + posts.map( ( post ) => { + return saveEditedEntityRecord( 'postType', post.type, post.id, { + throwOnError: true, + } ); + } ) + ); + + if ( promiseResult.every( ( { status } ) => status === 'fulfilled' ) ) { + let successMessage; + if ( posts.length === 1 ) { + successMessage = sprintf( + /* translators: The number of posts. */ + __( '"%s" has been restored.' ), + getItemTitle( posts[ 0 ] ) + ); + } else if ( posts[ 0 ].type === 'page' ) { + successMessage = sprintf( + /* translators: The number of posts. */ + __( '%d pages have been restored.' ), + posts.length + ); + } else { + successMessage = sprintf( + /* translators: The number of posts. */ + __( '%d posts have been restored.' ), + posts.length + ); + } + createSuccessNotice( successMessage, { + type: 'snackbar', + id: 'restore-post-action', + } ); + if ( onActionPerformed ) { + onActionPerformed( posts ); + } + } else { + // If there was at lease one failure. + let errorMessage; + // If we were trying to move a single post to the trash. + if ( promiseResult.length === 1 ) { + const typedError = promiseResult[ 0 ] as { + reason?: CoreDataError; + }; + if ( typedError.reason?.message ) { + errorMessage = typedError.reason.message; + } else { + errorMessage = __( + 'An error occurred while restoring the post.' + ); + } + // If we were trying to move multiple posts to the trash + } else { + const errorMessages = new Set(); + const failedPromises = promiseResult.filter( + ( { status } ) => status === 'rejected' + ); + for ( const failedPromise of failedPromises ) { + const typedError = failedPromise as { + reason?: CoreDataError; + }; + if ( typedError.reason?.message ) { + errorMessages.add( typedError.reason.message ); + } + } + if ( errorMessages.size === 0 ) { + errorMessage = __( + 'An error occurred while restoring the posts.' + ); + } else if ( errorMessages.size === 1 ) { + errorMessage = sprintf( + /* translators: %s: an error message */ + __( 'An error occurred while restoring the posts: %s' ), + [ ...errorMessages ][ 0 ] + ); + } else { + errorMessage = sprintf( + /* translators: %s: a list of comma separated error messages */ + __( + 'Some errors occurred while restoring the posts: %s' + ), + [ ...errorMessages ].join( ',' ) + ); + } + } + createErrorNotice( errorMessage, { + type: 'snackbar', + } ); + } + }, +}; + +export default restorePost; From cf21c3a66a7f24f167ee9f0f24bf943b67fd200f Mon Sep 17 00:00:00 2001 From: Nick Diego <nick.diego@automattic.com> Date: Wed, 31 Jul 2024 06:21:29 -0500 Subject: [PATCH 0182/1908] Site Tagline: Add `levelOptions` attribute to control available heading levels (#64113) * Add `levelOptions` attribute to Site Tagline block. Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- packages/block-library/src/site-tagline/block.json | 4 ++++ packages/block-library/src/site-tagline/edit.js | 6 ++---- test/integration/fixtures/blocks/core__site-tagline.json | 3 ++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index dfe0f224c8f360..a239b60cc50b38 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -847,7 +847,7 @@ Describe in a few words what the site is about. The tagline can be used in searc - **Name:** core/site-tagline - **Category:** theme - **Supports:** align (full, wide), color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~ -- **Attributes:** level, textAlign +- **Attributes:** level, levelOptions, textAlign ## Site Title diff --git a/packages/block-library/src/site-tagline/block.json b/packages/block-library/src/site-tagline/block.json index 25b3840cd663a0..d42b7bcd4bed64 100644 --- a/packages/block-library/src/site-tagline/block.json +++ b/packages/block-library/src/site-tagline/block.json @@ -14,6 +14,10 @@ "level": { "type": "number", "default": 0 + }, + "levelOptions": { + "type": "array", + "default": [ 0, 1, 2, 3, 4, 5, 6 ] } }, "example": { diff --git a/packages/block-library/src/site-tagline/edit.js b/packages/block-library/src/site-tagline/edit.js index 15f8a789dfbe99..52b9c761ba4f54 100644 --- a/packages/block-library/src/site-tagline/edit.js +++ b/packages/block-library/src/site-tagline/edit.js @@ -18,14 +18,12 @@ import { import { __ } from '@wordpress/i18n'; import { createBlock, getDefaultBlockName } from '@wordpress/blocks'; -const HEADING_LEVELS = [ 0, 1, 2, 3, 4, 5, 6 ]; - export default function SiteTaglineEdit( { attributes, setAttributes, insertBlocksAfter, } ) { - const { textAlign, level } = attributes; + const { textAlign, level, levelOptions } = attributes; const { canUserEdit, tagline } = useSelect( ( select ) => { const { canUser, getEntityRecord, getEditedEntityRecord } = select( coreStore ); @@ -82,8 +80,8 @@ export default function SiteTaglineEdit( { <> <BlockControls group="block"> <HeadingLevelDropdown - options={ HEADING_LEVELS } value={ level } + options={ levelOptions } onChange={ ( newLevel ) => setAttributes( { level: newLevel } ) } diff --git a/test/integration/fixtures/blocks/core__site-tagline.json b/test/integration/fixtures/blocks/core__site-tagline.json index e504bc75df30c7..fe837d41df43bf 100644 --- a/test/integration/fixtures/blocks/core__site-tagline.json +++ b/test/integration/fixtures/blocks/core__site-tagline.json @@ -3,7 +3,8 @@ "name": "core/site-tagline", "isValid": true, "attributes": { - "level": 0 + "level": 0, + "levelOptions": [ 0, 1, 2, 3, 4, 5, 6 ] }, "innerBlocks": [] } From 9ba3d146219d95158e3d58cc340e862b6cf5001c Mon Sep 17 00:00:00 2001 From: Nick Diego <nick.diego@automattic.com> Date: Wed, 31 Jul 2024 06:21:46 -0500 Subject: [PATCH 0183/1908] Site Title: Add `levelOptions` attribute to control available heading levels (#64111) * Add `levelOptions` attribute to the Site Title block. Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- packages/block-library/src/site-title/block.json | 4 ++++ packages/block-library/src/site-title/edit.js | 6 ++---- test/integration/fixtures/blocks/core__site-title.json | 1 + 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index a239b60cc50b38..80f8dac91dba5a 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -856,7 +856,7 @@ Displays the name of this site. Update the block, and the changes apply everywhe - **Name:** core/site-title - **Category:** theme - **Supports:** align (full, wide), color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~ -- **Attributes:** isLink, level, linkTarget, textAlign +- **Attributes:** isLink, level, levelOptions, linkTarget, textAlign ## Social Icon diff --git a/packages/block-library/src/site-title/block.json b/packages/block-library/src/site-title/block.json index 95d8deb1e43b9d..c75b1bc229beb9 100644 --- a/packages/block-library/src/site-title/block.json +++ b/packages/block-library/src/site-title/block.json @@ -11,6 +11,10 @@ "type": "number", "default": 1 }, + "levelOptions": { + "type": "array", + "default": [ 0, 1, 2, 3, 4, 5, 6 ] + }, "textAlign": { "type": "string" }, diff --git a/packages/block-library/src/site-title/edit.js b/packages/block-library/src/site-title/edit.js index 76519ac1297b14..82e3c1d7f7bb40 100644 --- a/packages/block-library/src/site-title/edit.js +++ b/packages/block-library/src/site-title/edit.js @@ -21,14 +21,12 @@ import { ToggleControl, PanelBody } from '@wordpress/components'; import { createBlock, getDefaultBlockName } from '@wordpress/blocks'; import { decodeEntities } from '@wordpress/html-entities'; -const HEADING_LEVELS = [ 0, 1, 2, 3, 4, 5, 6 ]; - export default function SiteTitleEdit( { attributes, setAttributes, insertBlocksAfter, } ) { - const { level, textAlign, isLink, linkTarget } = attributes; + const { level, levelOptions, textAlign, isLink, linkTarget } = attributes; const { canUserEdit, title } = useSelect( ( select ) => { const { canUser, getEntityRecord, getEditedEntityRecord } = select( coreStore ); @@ -97,8 +95,8 @@ export default function SiteTitleEdit( { <> <BlockControls group="block"> <HeadingLevelDropdown - options={ HEADING_LEVELS } value={ level } + options={ levelOptions } onChange={ ( newLevel ) => setAttributes( { level: newLevel } ) } diff --git a/test/integration/fixtures/blocks/core__site-title.json b/test/integration/fixtures/blocks/core__site-title.json index 12f32615473cc8..8ca7091f30d5e7 100644 --- a/test/integration/fixtures/blocks/core__site-title.json +++ b/test/integration/fixtures/blocks/core__site-title.json @@ -4,6 +4,7 @@ "isValid": true, "attributes": { "level": 1, + "levelOptions": [ 0, 1, 2, 3, 4, 5, 6 ], "isLink": true, "linkTarget": "_self" }, From d7787b35b4b5697d1ab19478f5f66d9f950e6736 Mon Sep 17 00:00:00 2001 From: Nick Diego <nick.diego@automattic.com> Date: Wed, 31 Jul 2024 06:22:01 -0500 Subject: [PATCH 0184/1908] Add `levelOptions` attribute to Query Title block. (#64107) Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- packages/block-library/src/query-title/block.json | 3 +++ packages/block-library/src/query-title/edit.js | 10 +++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 80f8dac91dba5a..c305ecf5b645f3 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -775,7 +775,7 @@ Display the query title. ([Source](https://github.com/WordPress/gutenberg/tree/t - **Name:** core/query-title - **Category:** theme - **Supports:** align (full, wide), color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~ -- **Attributes:** level, showPrefix, showSearchTerm, textAlign, type +- **Attributes:** level, levelOptions, showPrefix, showSearchTerm, textAlign, type ## Quote diff --git a/packages/block-library/src/query-title/block.json b/packages/block-library/src/query-title/block.json index 674daadee3bb69..2a3c7d9f236995 100644 --- a/packages/block-library/src/query-title/block.json +++ b/packages/block-library/src/query-title/block.json @@ -17,6 +17,9 @@ "type": "number", "default": 1 }, + "levelOptions": { + "type": "array" + }, "showPrefix": { "type": "boolean", "default": true diff --git a/packages/block-library/src/query-title/edit.js b/packages/block-library/src/query-title/edit.js index 71f0e26d706842..845809a9300137 100644 --- a/packages/block-library/src/query-title/edit.js +++ b/packages/block-library/src/query-title/edit.js @@ -25,7 +25,14 @@ import { useArchiveLabel } from './use-archive-label'; const SUPPORTED_TYPES = [ 'archive', 'search' ]; export default function QueryTitleEdit( { - attributes: { type, level, textAlign, showPrefix, showSearchTerm }, + attributes: { + type, + level, + levelOptions, + textAlign, + showPrefix, + showSearchTerm, + }, setAttributes, } ) { const { archiveTypeLabel, archiveNameLabel } = useArchiveLabel(); @@ -130,6 +137,7 @@ export default function QueryTitleEdit( { <BlockControls group="block"> <HeadingLevelDropdown value={ level } + options={ levelOptions } onChange={ ( newLevel ) => setAttributes( { level: newLevel } ) } From 317c348874fb5d4cf47297351aee4c9098cf15c6 Mon Sep 17 00:00:00 2001 From: Nick Diego <nick.diego@automattic.com> Date: Wed, 31 Jul 2024 06:22:14 -0500 Subject: [PATCH 0185/1908] Add `levelOptions` to Comments Title block. (#64103) Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- packages/block-library/src/comments-title/block.json | 3 +++ packages/block-library/src/comments-title/edit.js | 9 ++++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index c305ecf5b645f3..8765a7cfba2f09 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -237,7 +237,7 @@ Displays a title with the number of comments. ([Source](https://github.com/WordP - **Category:** theme - **Ancestor:** core/comments - **Supports:** align, color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~anchor~~, ~~html~~ -- **Attributes:** level, showCommentsCount, showPostTitle, textAlign +- **Attributes:** level, levelOptions, showCommentsCount, showPostTitle, textAlign ## Cover diff --git a/packages/block-library/src/comments-title/block.json b/packages/block-library/src/comments-title/block.json index f8a02f2e5089b5..b66b741e1916a0 100644 --- a/packages/block-library/src/comments-title/block.json +++ b/packages/block-library/src/comments-title/block.json @@ -23,6 +23,9 @@ "level": { "type": "number", "default": 2 + }, + "levelOptions": { + "type": "array" } }, "supports": { diff --git a/packages/block-library/src/comments-title/edit.js b/packages/block-library/src/comments-title/edit.js index 07149607bfc393..f2a9d23ddf6cae 100644 --- a/packages/block-library/src/comments-title/edit.js +++ b/packages/block-library/src/comments-title/edit.js @@ -23,7 +23,13 @@ import apiFetch from '@wordpress/api-fetch'; import { addQueryArgs } from '@wordpress/url'; export default function Edit( { - attributes: { textAlign, showPostTitle, showCommentsCount, level }, + attributes: { + textAlign, + showPostTitle, + showCommentsCount, + level, + levelOptions, + }, setAttributes, context: { postType, postId }, } ) { @@ -95,6 +101,7 @@ export default function Edit( { /> <HeadingLevelDropdown value={ level } + options={ levelOptions } onChange={ ( newLevel ) => setAttributes( { level: newLevel } ) } From 15db088a1c833305a2ed191229f0db9df9d80d91 Mon Sep 17 00:00:00 2001 From: Nick Diego <nick.diego@automattic.com> Date: Wed, 31 Jul 2024 06:22:28 -0500 Subject: [PATCH 0186/1908] Add `levelOptions` attribute to the Title block. (#64106) Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- packages/block-library/src/post-title/block.json | 3 +++ packages/block-library/src/post-title/edit.js | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 8765a7cfba2f09..122779b0f4f649 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -689,7 +689,7 @@ Displays the title of a post, page, or any other content-type. ([Source](https:/ - **Name:** core/post-title - **Category:** theme - **Supports:** align (full, wide), color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~ -- **Attributes:** isLink, level, linkTarget, rel, textAlign +- **Attributes:** isLink, level, levelOptions, linkTarget, rel, textAlign ## Preformatted diff --git a/packages/block-library/src/post-title/block.json b/packages/block-library/src/post-title/block.json index 9c3ba3e214e4b1..ecb5053d6cd39e 100644 --- a/packages/block-library/src/post-title/block.json +++ b/packages/block-library/src/post-title/block.json @@ -15,6 +15,9 @@ "type": "number", "default": 2 }, + "levelOptions": { + "type": "array" + }, "isLink": { "type": "boolean", "default": false diff --git a/packages/block-library/src/post-title/edit.js b/packages/block-library/src/post-title/edit.js index 3963016e342822..d24455f0956358 100644 --- a/packages/block-library/src/post-title/edit.js +++ b/packages/block-library/src/post-title/edit.js @@ -22,7 +22,7 @@ import { useEntityProp, store as coreStore } from '@wordpress/core-data'; import { useSelect } from '@wordpress/data'; export default function PostTitleEdit( { - attributes: { level, textAlign, isLink, rel, linkTarget }, + attributes: { level, levelOptions, textAlign, isLink, rel, linkTarget }, setAttributes, context: { postType, postId, queryId }, insertBlocksAfter, @@ -125,6 +125,7 @@ export default function PostTitleEdit( { <BlockControls group="block"> <HeadingLevelDropdown value={ level } + options={ levelOptions } onChange={ ( newLevel ) => setAttributes( { level: newLevel } ) } From 08e69605f9e1ea763e0dc27da381a66292e26e5f Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 31 Jul 2024 15:59:57 +0400 Subject: [PATCH 0187/1908] Template Part: Fix 'can user edit' check (#64137) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/template-part/edit/index.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/block-library/src/template-part/edit/index.js b/packages/block-library/src/template-part/edit/index.js index 0cb6cfc8996ce9..ba3e8f57136d60 100644 --- a/packages/block-library/src/template-part/edit/index.js +++ b/packages/block-library/src/template-part/edit/index.js @@ -128,7 +128,7 @@ export default function TemplatePartEdit( { area, onNavigateToEntityRecord, title, - canEditTemplate, + canUserEdit, } = useSelect( ( select ) => { const { getEditedEntityRecord, hasFinishedResolution } = @@ -151,10 +151,13 @@ export default function TemplatePartEdit( { ) : false; - const _canEditTemplate = select( coreStore ).canUser( 'create', { - kind: 'postType', - name: 'wp_template_part', - } ); + const _canUserEdit = hasResolvedEntity + ? select( coreStore ).canUser( 'update', { + kind: 'postType', + name: 'wp_template_part', + id: templatePartId, + } ) + : false; return { hasInnerBlocks: getBlockCount( clientId ) > 0, @@ -167,7 +170,7 @@ export default function TemplatePartEdit( { onNavigateToEntityRecord: getSettings().onNavigateToEntityRecord, title: entityRecord?.title, - canEditTemplate: !! _canEditTemplate, + canUserEdit: !! _canUserEdit, }; }, [ templatePartId, attributes.area, clientId ] @@ -237,7 +240,7 @@ export default function TemplatePartEdit( { <RecursionProvider uniqueId={ templatePartId }> { isEntityAvailable && onNavigateToEntityRecord && - canEditTemplate && ( + canUserEdit && ( <BlockControls group="other"> <ToolbarButton onClick={ () => From cba05caeba7c224f42fac232bae8861986ebb609 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 31 Jul 2024 14:04:50 +0200 Subject: [PATCH 0188/1908] Site Editor: Clarify that the site icon is a back button using an animation (#63986) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> --- .../edit-site/src/components/editor/index.js | 102 ++++++++++++++---- .../src/components/editor/style.scss | 59 +++++++++- .../src/components/layout/style.scss | 8 ++ .../src/components/site-icon/style.scss | 5 +- 4 files changed, 150 insertions(+), 24 deletions(-) diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index b11a9c56c9c50c..d0c63a9db5cad6 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -7,8 +7,8 @@ import clsx from 'clsx'; * WordPress dependencies */ import { useDispatch, useSelect } from '@wordpress/data'; -import { Button } from '@wordpress/components'; -import { useInstanceId } from '@wordpress/compose'; +import { Button, __unstableMotion as motion } from '@wordpress/components'; +import { useInstanceId, useReducedMotion } from '@wordpress/compose'; import { EditorKeyboardShortcutsRegister, privateApis as editorPrivateApis, @@ -22,6 +22,7 @@ import { store as noticesStore } from '@wordpress/notices'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { store as preferencesStore } from '@wordpress/preferences'; import { decodeEntities } from '@wordpress/html-entities'; +import { Icon, chevronLeft } from '@wordpress/icons'; /** * Internal dependencies @@ -51,7 +52,32 @@ const { Editor, BackButton } = unlock( editorPrivateApis ); const { useHistory, useLocation } = unlock( routerPrivateApis ); const { BlockKeyboardShortcuts } = unlock( blockLibraryPrivateApis ); +const toggleHomeIconVariants = { + edit: { + opacity: 0, + scale: 0.2, + }, + hover: { + opacity: 1, + scale: 1, + clipPath: 'inset( 22% round 2px )', + }, +}; + +const siteIconVariants = { + edit: { + clipPath: 'inset(0% round 0)', + }, + hover: { + clipPath: 'inset( 22% round 2px )', + }, + tap: { + clipPath: 'inset(0% round 0)', + }, +}; + export default function EditSiteEditor( { isPostsList = false } ) { + const disableMotion = useReducedMotion(); const { params } = useLocation(); const isLoading = useIsSiteEditorLoading(); const { @@ -65,6 +91,7 @@ export default function EditSiteEditor( { isPostsList = false } ) { showIconLabels, editorCanvasView, currentPostIsTrashed, + hasSiteIcon, } = useSelect( ( select ) => { const { getEditorCanvasContainerView, @@ -75,8 +102,9 @@ export default function EditSiteEditor( { isPostsList = false } ) { getEditedPostId, } = unlock( select( editSiteStore ) ); const { get } = select( preferencesStore ); - const { getCurrentTheme } = select( coreDataStore ); + const { getCurrentTheme, getEntityRecord } = select( coreDataStore ); const _context = getEditedPostContext(); + const siteData = getEntityRecord( 'root', '__unstableBase', undefined ); // The currently selected entity to display. // Typically template or template part in the site editor. @@ -93,6 +121,7 @@ export default function EditSiteEditor( { isPostsList = false } ) { currentPostIsTrashed: select( editorStore ).getCurrentPostAttribute( 'status' ) === 'trash', + hasSiteIcon: !! siteData?.site_icon_url, }; }, [] ); useEditorTitle(); @@ -179,6 +208,9 @@ export default function EditSiteEditor( { isPostsList = false } ) { getEditorCanvasContainerTitleAndIcon( editorCanvasView ); const isReady = ! isLoading; + const transition = { + duration: disableMotion ? 0 : 0.2, + }; return ( <> @@ -217,26 +249,52 @@ export default function EditSiteEditor( { isPostsList = false } ) { <BackButton> { ( { length } ) => length <= 1 && ( - <Button - label={ __( 'Open Navigation' ) } - className="edit-site-layout__view-mode-toggle" - onClick={ () => { - setCanvasMode( 'view' ); - // TODO: this is a temporary solution to navigate to the posts list if we are - // come here through `posts list` and are in focus mode editing a template, template part etc.. - if ( - isPostsList && - params?.focusMode - ) { - history.push( { - page: 'gutenberg-posts-dashboard', - postType: 'post', - } ); - } - } } + <motion.div + className="edit-site-editor__view-mode-toggle" + transition={ transition } + animate="edit" + initial="edit" + whileHover="hover" + whileTap="tap" > - <SiteIcon className="edit-site-layout__view-mode-toggle-icon" /> - </Button> + <Button + label={ __( 'Open Navigation' ) } + showTooltip + tooltipPosition="middle right" + onClick={ () => { + setCanvasMode( 'view' ); + // TODO: this is a temporary solution to navigate to the posts list if we are + // come here through `posts list` and are in focus mode editing a template, template part etc.. + if ( + isPostsList && + params?.focusMode + ) { + history.push( { + page: 'gutenberg-posts-dashboard', + postType: 'post', + } ); + } + } } + > + <motion.div + variants={ siteIconVariants } + > + <SiteIcon className="edit-site-editor__view-mode-toggle-icon" /> + </motion.div> + </Button> + <motion.div + className={ clsx( + 'edit-site-editor__back-icon', + { + 'has-site-icon': + hasSiteIcon, + } + ) } + variants={ toggleHomeIconVariants } + > + <Icon icon={ chevronLeft } /> + </motion.div> + </motion.div> ) } </BackButton> diff --git a/packages/edit-site/src/components/editor/style.scss b/packages/edit-site/src/components/editor/style.scss index b157057062c9d1..0e2e85ba9f72dd 100644 --- a/packages/edit-site/src/components/editor/style.scss +++ b/packages/edit-site/src/components/editor/style.scss @@ -1,7 +1,7 @@ .edit-site-editor__editor-interface { opacity: 1; transition: opacity 0.1s ease-out; - @include reduce-motion("transition"); + @include reduce-motion( "transition" ); &.is-loading { opacity: 0; @@ -17,3 +17,60 @@ display: flex; justify-content: center; } + +.edit-site-editor__view-mode-toggle { + /* stylelint-disable -- Disable reason: View Transitions not supported properly by stylelint. */ + view-transition-name: toggle; + /* stylelint-enable */ + position: fixed; + top: 0; + left: 0; + height: $header-height; + width: $header-height; + z-index: 100; + + .components-button { + color: $white; + height: 100%; + width: 100%; + border-radius: 0; + overflow: hidden; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + &:hover, + &:active { + color: $white; + } + + &:focus { + box-shadow: none; + } + } + + .edit-site-editor__view-mode-toggle-icon { + svg, + img { + background: $gray-900; + display: block; + } + } +} + +.edit-site-editor__back-icon { + position: absolute; + top: 0; + left: 0; + width: 60px; + height: 60px; + display: flex; + align-items: center; + justify-content: center; + background-color: hsla(0, 0%, 80%); + pointer-events: none; + + &.has-site-icon { + background-color: hsla(0, 0%, 100%, 0.6); + } +} diff --git a/packages/edit-site/src/components/layout/style.scss b/packages/edit-site/src/components/layout/style.scss index 09898a530e445a..e4c95fed8b88b7 100644 --- a/packages/edit-site/src/components/layout/style.scss +++ b/packages/edit-site/src/components/layout/style.scss @@ -148,6 +148,14 @@ html.canvas-mode-edit-transition::view-transition-group(toggle) { animation-delay: 255ms; } + +@media (prefers-reduced-motion) { + ::view-transition-group(*), + ::view-transition-old(*), + ::view-transition-new(*) { + animation: none !important; + } +} /* stylelint-enable */ .edit-site-layout.is-full-canvas .edit-site-layout__sidebar-region .edit-site-layout__view-mode-toggle { diff --git a/packages/edit-site/src/components/site-icon/style.scss b/packages/edit-site/src/components/site-icon/style.scss index a461b43476fe52..a6cc7ad27fe5df 100644 --- a/packages/edit-site/src/components/site-icon/style.scss +++ b/packages/edit-site/src/components/site-icon/style.scss @@ -1,9 +1,11 @@ .edit-site-site-icon__icon { fill: currentColor; + width: 100%; + height: 100%; .edit-site-layout.is-full-canvas & { // Make the WordPress icon not so big in full canvas. - padding: $grid-unit-15 * 0.5; // 6px. + padding: $grid-unit-15; } } @@ -12,6 +14,7 @@ height: 100%; object-fit: cover; background: #333; + aspect-ratio: 1 / 1; .edit-site-layout.is-full-canvas & { border-radius: 0; From b1628c052017a3d6e2f889a0d7291c002b6badfe Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Wed, 31 Jul 2024 13:16:28 +0100 Subject: [PATCH 0189/1908] Update template preview dimensions in table layout (#63938) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/edit-site/src/components/page-templates/index.js | 3 +-- packages/edit-site/src/components/page-templates/style.scss | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/page-templates/index.js b/packages/edit-site/src/components/page-templates/index.js index 05c3b9673eaf98..01b17ae76fc9dc 100644 --- a/packages/edit-site/src/components/page-templates/index.js +++ b/packages/edit-site/src/components/page-templates/index.js @@ -54,8 +54,7 @@ const defaultLayouts = { minWidth: 320, }, preview: { - minWidth: 120, - maxWidth: 120, + width: '1%', }, author: { width: '1%', diff --git a/packages/edit-site/src/components/page-templates/style.scss b/packages/edit-site/src/components/page-templates/style.scss index 067720ad9a1e97..0313da00f89944 100644 --- a/packages/edit-site/src/components/page-templates/style.scss +++ b/packages/edit-site/src/components/page-templates/style.scss @@ -37,6 +37,8 @@ .dataviews-view-table & { border-radius: $radius-block-ui; position: relative; + width: 120px; + max-height: 160px; &::after { content: ""; From 1f97f7f0bc2da82d6bc2f5e73508cc1ba1e9978d Mon Sep 17 00:00:00 2001 From: Amit Raj <77401999+amitraj2203@users.noreply.github.com> Date: Wed, 31 Jul 2024 17:56:56 +0530 Subject: [PATCH 0190/1908] Long slugs breaking summary panel UI (#64053) * fix: long slugs breaking summary panel UI * refactor: Update styles for post URL to truncate the button when the URL is extremely long * Addressed feedback Co-authored-by: amitraj2203 <amitraj2203@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/editor/src/components/post-url/panel.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/post-url/panel.js b/packages/editor/src/components/post-url/panel.js index be32b40eaf1046..aca36566c04727 100644 --- a/packages/editor/src/components/post-url/panel.js +++ b/packages/editor/src/components/post-url/panel.js @@ -3,7 +3,11 @@ */ import { useMemo, useState } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; -import { Dropdown, Button } from '@wordpress/components'; +import { + Dropdown, + Button, + __experimentalTruncate as Truncate, +} from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; import { safeDecodeURIComponent } from '@wordpress/url'; import { store as coreStore } from '@wordpress/core-data'; @@ -86,7 +90,9 @@ function PostURLToggle( { isOpen, onClick } ) { aria-label={ sprintf( __( 'Change link: %s' ), decodedSlug ) } onClick={ onClick } > - { isFrontPage ? postLink : <>/{ decodedSlug }</> } + <Truncate numberOfLines={ 1 }> + { isFrontPage ? postLink : `/${ decodedSlug }` } + </Truncate> </Button> ); } From 7b067aa68224890dc5589b38c5df85be579997d3 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 31 Jul 2024 22:47:27 +0900 Subject: [PATCH 0191/1908] Font Library Modal: Remove notice context and add message when fonts updated (#64030) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: madhusudhand <madhudollu@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: akasunil <sunil25393@git.wordpress.org> --- .../components/global-styles/font-families.js | 4 +-- .../font-library-modal/context.js | 5 ---- .../font-library-modal/font-collection.js | 14 +++------- .../global-styles/font-library-modal/index.js | 9 ++---- .../font-library-modal/installed-fonts.js | 28 +++++++++++++++---- .../font-library-modal/upload-fonts.js | 4 +-- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-families.js b/packages/edit-site/src/components/global-styles/font-families.js index f6610d0457bbae..6a554b136317dd 100644 --- a/packages/edit-site/src/components/global-styles/font-families.js +++ b/packages/edit-site/src/components/global-styles/font-families.js @@ -26,7 +26,7 @@ import { unlock } from '../../lock-unlock'; const { useGlobalSetting } = unlock( blockEditorPrivateApis ); function FontFamilies() { - const { baseCustomFonts, modalTabOpen, setModalTabOpen, setNotice } = + const { baseCustomFonts, modalTabOpen, setModalTabOpen } = useContext( FontLibraryContext ); const [ fontFamilies ] = useGlobalSetting( 'typography.fontFamilies' ); const [ baseFontFamilies ] = useGlobalSetting( @@ -112,8 +112,6 @@ function FontFamilies() { variant="secondary" __next40pxDefaultSize onClick={ () => { - // Reset notice when opening the modal. - setNotice( null ); setModalTabOpen( hasInstalledFonts ? 'installed-fonts' diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/context.js b/packages/edit-site/src/components/global-styles/font-library-modal/context.js index e02dcb2e8a0af5..abfb5484e44bf5 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/context.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/context.js @@ -54,7 +54,6 @@ function FontLibraryProvider( { children } ) { const [ isInstalling, setIsInstalling ] = useState( false ); const [ refreshKey, setRefreshKey ] = useState( 0 ); - const [ notice, setNotice ] = useState( null ); const refreshLibrary = () => { setRefreshKey( Date.now() ); @@ -139,8 +138,6 @@ function FontLibraryProvider( { children } ) { }, [ modalTabOpen ] ); const handleSetLibraryFontSelected = ( font ) => { - setNotice( null ); - // If font is null, reset the selected font if ( ! font ) { setLibraryFontSelected( null ); @@ -527,8 +524,6 @@ function FontLibraryProvider( { children } ) { modalTabOpen, setModalTabOpen, refreshLibrary, - notice, - setNotice, saveFontFamilies, isResolvingLibrary, isInstalling, diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js index cf6857b30c59e6..6f8a27a8aa8927 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js @@ -63,20 +63,15 @@ function FontCollection( { slug } ) { }; const [ selectedFont, setSelectedFont ] = useState( null ); + const [ notice, setNotice ] = useState( false ); const [ fontsToInstall, setFontsToInstall ] = useState( [] ); const [ page, setPage ] = useState( 1 ); const [ filters, setFilters ] = useState( {} ); const [ renderConfirmDialog, setRenderConfirmDialog ] = useState( requiresPermission && ! getGoogleFontsPermissionFromStorage() ); - const { - collections, - getFontCollection, - installFonts, - isInstalling, - notice, - setNotice, - } = useContext( FontLibraryContext ); + const { collections, getFontCollection, installFonts, isInstalling } = + useContext( FontLibraryContext ); const selectedCollection = collections.find( ( collection ) => collection.slug === slug ); @@ -116,8 +111,7 @@ function FontCollection( { slug } ) { useEffect( () => { setSelectedFont( null ); - setNotice( null ); - }, [ slug, setNotice ] ); + }, [ slug ] ); useEffect( () => { // If the selected fonts change, reset the selected fonts to install diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/index.js b/packages/edit-site/src/components/global-styles/font-library-modal/index.js index 80edc1596f08cd..5af4be90fecdcf 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/index.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/index.js @@ -44,7 +44,7 @@ function FontLibraryModal( { onRequestClose, defaultTabId = 'installed-fonts', } ) { - const { collections, setNotice } = useContext( FontLibraryContext ); + const { collections } = useContext( FontLibraryContext ); const canUserCreate = useSelect( ( select ) => { return select( coreStore ).canUser( 'create', { kind: 'postType', @@ -59,11 +59,6 @@ function FontLibraryModal( { tabs.push( ...tabsFromCollections( collections || [] ) ); } - // Reset notice when new tab is selected. - const onSelect = () => { - setNotice( null ); - }; - return ( <Modal title={ __( 'Fonts' ) } @@ -72,7 +67,7 @@ function FontLibraryModal( { className="font-library-modal" > <div className="font-library-modal__tabs"> - <Tabs defaultTabId={ defaultTabId } onSelect={ onSelect }> + <Tabs defaultTabId={ defaultTabId }> <Tabs.TabList> { tabs.map( ( { id, title } ) => ( <Tabs.Tab key={ id } tabId={ id }> diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js index 6602a778dc66c3..7ca2a9218c3bb0 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js @@ -53,14 +53,13 @@ function InstalledFonts() { isInstalling, saveFontFamilies, getFontFacesActivated, - notice, - setNotice, } = useContext( FontLibraryContext ); const [ fontFamilies, setFontFamilies ] = useGlobalSetting( 'typography.fontFamilies' ); const [ isConfirmDeleteOpen, setIsConfirmDeleteOpen ] = useState( false ); + const [ notice, setNotice ] = useState( false ); const [ baseFontFamilies ] = useGlobalSetting( 'typography.fontFamilies', undefined, @@ -120,6 +119,24 @@ function InstalledFonts() { setIsConfirmDeleteOpen( true ); }; + const handleUpdate = async () => { + setNotice( null ); + try { + await saveFontFamilies( fontFamilies ); + setNotice( { + type: 'success', + message: __( 'Font family updated successfully.' ), + } ); + } catch ( error ) { + setNotice( { + type: 'error', + message: + __( 'There was an error updating the font family. ' ) + + error.message, + } ); + } + }; + const getFontFacesToDisplay = ( font ) => { if ( ! font ) { return []; @@ -265,6 +282,7 @@ function InstalledFonts() { font ) } onClick={ () => { + setNotice( null ); handleSetLibraryFontSelected( font ); @@ -305,6 +323,7 @@ function InstalledFonts() { font ) } onClick={ () => { + setNotice( null ); handleSetLibraryFontSelected( font ); @@ -337,6 +356,7 @@ function InstalledFonts() { size="small" onClick={ () => { handleSetLibraryFontSelected( null ); + setNotice( null ); } } label={ __( 'Back' ) } /> @@ -406,9 +426,7 @@ function InstalledFonts() { ) } <Button variant="primary" - onClick={ () => { - saveFontFamilies( fontFamilies ); - } } + onClick={ handleUpdate } disabled={ ! fontFamiliesHasChanges } accessibleWhenDisabled > diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/upload-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/upload-fonts.js index 5e8cfdec215175..0f6331a54304de 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/upload-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/upload-fonts.js @@ -25,9 +25,9 @@ import makeFamiliesFromFaces from './utils/make-families-from-faces'; import { loadFontFaceInBrowser } from './utils'; function UploadFonts() { - const { installFonts, notice, setNotice } = - useContext( FontLibraryContext ); + const { installFonts } = useContext( FontLibraryContext ); const [ isUploading, setIsUploading ] = useState( false ); + const [ notice, setNotice ] = useState( false ); const handleDropZone = ( files ) => { handleFilesUpload( files ); From ad917d515bba38cbc06ba1ae99a146350891b6ab Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Wed, 31 Jul 2024 06:52:43 -0700 Subject: [PATCH 0192/1908] Fix grid resizer drag over embed (#64098) * Capture pointer to avoid flaky dragging * Remove manual mouseup dispatch Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> --- .../src/components/grid/grid-item-resizer.js | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/packages/block-editor/src/components/grid/grid-item-resizer.js b/packages/block-editor/src/components/grid/grid-item-resizer.js index 28d9678772f76c..da3eb824fe92e5 100644 --- a/packages/block-editor/src/components/grid/grid-item-resizer.js +++ b/packages/block-editor/src/components/grid/grid-item-resizer.js @@ -119,6 +119,15 @@ function GridItemResizerInner( { } } bounds={ bounds } boundsByDirection + onPointerDown={ ( { target, pointerId } ) => { + /* + * Captures the pointer to avoid hiccups while dragging over objects + * like iframes and ensures that the event to end the drag is + * captured by the target (resize handle) whether or not it’s under + * the pointer. + */ + target.setPointerCapture( pointerId ); + } } onResizeStart={ ( event, direction ) => { /* * The container justification and alignment need to be set @@ -126,21 +135,6 @@ function GridItemResizerInner( { * so that it resizes in the right direction. */ setResizeDirection( direction ); - - /* - * The mouseup event on the resize handle doesn't trigger if the mouse - * isn't directly above the handle, so we try to detect if it happens - * outside the grid and dispatch a mouseup event on the handle. - */ - blockElement.ownerDocument.addEventListener( - 'mouseup', - () => { - event.target.dispatchEvent( - new Event( 'mouseup', { bubbles: true } ) - ); - }, - { once: true } - ); } } onResizeStop={ ( event, direction, boxElement ) => { const columnGap = parseFloat( From 68e47024e999735c3c0ff718822bdfc5be5c087d Mon Sep 17 00:00:00 2001 From: Rich Tabor <hi@richtabor.com> Date: Wed, 31 Jul 2024 10:58:36 -0400 Subject: [PATCH 0193/1908] Clean up List block inspector (#64025) * tweak inspector controls * block description, background default false * test * use reverse order label * clean block color support Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 4 +- .../block-library/src/list-item/block.json | 4 +- packages/block-library/src/list/block.json | 2 +- .../src/list/ordered-list-settings.js | 38 ++++++++++--------- .../src/list/test/edit.native.js | 4 +- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 122779b0f4f649..9e56387bc66658 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -410,7 +410,7 @@ Display a list of your most recent posts. ([Source](https://github.com/WordPress ## List -Create a bulleted or numbered list. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/list)) +An organized collection of items displayed in a specific order. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/list)) - **Name:** core/list - **Category:** text @@ -420,7 +420,7 @@ Create a bulleted or numbered list. ([Source](https://github.com/WordPress/guten ## List item -Create a list item. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/list-item)) +An individual item within a list. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/list-item)) - **Name:** core/list-item - **Category:** text diff --git a/packages/block-library/src/list-item/block.json b/packages/block-library/src/list-item/block.json index 6110df530bf5e0..32a552c3779cd3 100644 --- a/packages/block-library/src/list-item/block.json +++ b/packages/block-library/src/list-item/block.json @@ -6,7 +6,7 @@ "category": "text", "parent": [ "core/list" ], "allowedBlocks": [ "core/list" ], - "description": "Create a list item.", + "description": "An individual item within a list.", "textdomain": "default", "attributes": { "placeholder": { @@ -25,8 +25,8 @@ "color": { "gradients": true, "link": true, + "background": true, "__experimentalDefaultControls": { - "background": true, "text": true } }, diff --git a/packages/block-library/src/list/block.json b/packages/block-library/src/list/block.json index 157aaf7c0cf633..8b100071c15ea9 100644 --- a/packages/block-library/src/list/block.json +++ b/packages/block-library/src/list/block.json @@ -5,7 +5,7 @@ "title": "List", "category": "text", "allowedBlocks": [ "core/list-item" ], - "description": "Create a bulleted or numbered list.", + "description": "An organized collection of items displayed in a specific order.", "keywords": [ "bullet list", "ordered list", "numbered list" ], "textdomain": "default", "attributes": { diff --git a/packages/block-library/src/list/ordered-list-settings.js b/packages/block-library/src/list/ordered-list-settings.js index 8c433a465638ff..66817669806233 100644 --- a/packages/block-library/src/list/ordered-list-settings.js +++ b/packages/block-library/src/list/ordered-list-settings.js @@ -13,25 +13,10 @@ import { const OrderedListSettings = ( { setAttributes, reversed, start, type } ) => ( <InspectorControls> <PanelBody title={ __( 'Settings' ) }> - <TextControl - __nextHasNoMarginBottom - label={ __( 'Start value' ) } - type="number" - onChange={ ( value ) => { - const int = parseInt( value, 10 ); - - setAttributes( { - // It should be possible to unset the value, - // e.g. with an empty string. - start: isNaN( int ) ? undefined : int, - } ); - } } - value={ Number.isInteger( start ) ? start.toString( 10 ) : '' } - step="1" - /> <SelectControl + __next40pxDefaultSize __nextHasNoMarginBottom - label={ __( 'Numbering style' ) } + label={ __( 'List style' ) } options={ [ { label: __( 'Numbers' ), @@ -57,9 +42,26 @@ const OrderedListSettings = ( { setAttributes, reversed, start, type } ) => ( value={ type } onChange={ ( newValue ) => setAttributes( { type: newValue } ) } /> + <TextControl + __next40pxDefaultSize + __nextHasNoMarginBottom + label={ __( 'Start value' ) } + type="number" + onChange={ ( value ) => { + const int = parseInt( value, 10 ); + + setAttributes( { + // It should be possible to unset the value, + // e.g. with an empty string. + start: isNaN( int ) ? undefined : int, + } ); + } } + value={ Number.isInteger( start ) ? start.toString( 10 ) : '' } + step="1" + /> <ToggleControl __nextHasNoMarginBottom - label={ __( 'Reverse list numbering' ) } + label={ __( 'Reverse order' ) } checked={ reversed || false } onChange={ ( value ) => { setAttributes( { diff --git a/packages/block-library/src/list/test/edit.native.js b/packages/block-library/src/list/test/edit.native.js index a33bce32e5bca0..2393f2820cfc2e 100644 --- a/packages/block-library/src/list/test/edit.native.js +++ b/packages/block-library/src/list/test/edit.native.js @@ -289,9 +289,7 @@ describe( 'List block', () => { () => screen.getByTestId( 'block-settings-modal' ).props.isVisible ); - const reverseButton = screen.getByLabelText( - /Reverse list numbering\. Off/ - ); + const reverseButton = screen.getByLabelText( /Reverse order\. Off/ ); fireEvent.press( reverseButton ); expect( getEditorHtml() ).toMatchSnapshot(); From 6db6c05228c5c210201efe9f90521056071b0d57 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Wed, 31 Jul 2024 17:00:11 +0200 Subject: [PATCH 0194/1908] Fix modal dismissers in development mode (#64132) * Fix modal dismissers in development mode * Keep the close() calls * Add changelog entry Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/modal/index.tsx | 41 +++++++++++++------------ 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 7de4fcf90b0e95..aff6181833b354 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,7 @@ - `ColorPalette`: Remove extra bottom margin when `CircularOptionPicker` is unneeded ([#63961](https://github.com/WordPress/gutenberg/pull/63961)). - `CustomSelectControl`: Restore `describedBy` functionality ([#63957](https://github.com/WordPress/gutenberg/pull/63957)). +- `Modal`: Fix the dismissal logic for React development mode ([#64132](https://github.com/WordPress/gutenberg/pull/64132)). ### Enhancements diff --git a/packages/components/src/modal/index.tsx b/packages/components/src/modal/index.tsx index 42ba2d78db57a8..b18217cdbaadcb 100644 --- a/packages/components/src/modal/index.tsx +++ b/packages/components/src/modal/index.tsx @@ -2,12 +2,7 @@ * External dependencies */ import clsx from 'clsx'; -import type { - ForwardedRef, - KeyboardEvent, - MutableRefObject, - UIEvent, -} from 'react'; +import type { ForwardedRef, KeyboardEvent, RefObject, UIEvent } from 'react'; /** * WordPress dependencies @@ -44,9 +39,10 @@ import type { ModalProps } from './types'; import { withIgnoreIMEEvents } from '../utils/with-ignore-ime-events'; // Used to track and dismiss the prior modal when another opens unless nested. -const ModalContext = createContext< - MutableRefObject< ModalProps[ 'onRequestClose' ] | undefined >[] ->( [] ); +type Dismissers = Set< + RefObject< ModalProps[ 'onRequestClose' ] | undefined > +>; +const ModalContext = createContext< Dismissers >( new Set() ); // Used to track body class names applied while modals are open. const bodyOpenClasses = new Map< string, number >(); @@ -147,23 +143,28 @@ function UnforwardedModal( // one should remain open at a time and the list enables closing prior ones. const dismissers = useContext( ModalContext ); // Used for the tracking and dismissing any nested modals. - const nestedDismissers = useRef< typeof dismissers >( [] ); + const [ nestedDismissers ] = useState< Dismissers >( () => new Set() ); // Updates the stack tracking open modals at this level and calls // onRequestClose for any prior and/or nested modals as applicable. useEffect( () => { - dismissers.push( refOnRequestClose ); - const [ first, second ] = dismissers; - if ( second ) { - first?.current?.(); + // add this modal instance to the dismissers set + dismissers.add( refOnRequestClose ); + // request that all the other modals close themselves + for ( const dismisser of dismissers ) { + if ( dismisser !== refOnRequestClose ) { + dismisser.current?.(); + } } - - const nested = nestedDismissers.current; return () => { - nested[ 0 ]?.current?.(); - dismissers.shift(); + // request that all the nested modals close themselves + for ( const dismisser of nestedDismissers ) { + dismisser.current?.(); + } + // remove this modal instance from the dismissers set + dismissers.delete( refOnRequestClose ); }; - }, [ dismissers ] ); + }, [ dismissers, nestedDismissers ] ); // Adds/removes the value of bodyOpenClassName to body element. useEffect( () => { @@ -350,7 +351,7 @@ function UnforwardedModal( ); return createPortal( - <ModalContext.Provider value={ nestedDismissers.current }> + <ModalContext.Provider value={ nestedDismissers }> { modal } </ModalContext.Provider>, document.body From 48fa26d8536900d15dc33ec88463718aa6f710ee Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 31 Jul 2024 16:57:22 +0000 Subject: [PATCH 0195/1908] Bump plugin version to 18.9.0 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 07a607327ceddd..b12c3467410603 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 18.9.0-rc.1 + * Version: 18.9.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 6680025d768bef..4e7e660619249b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "18.9.0-rc.1", + "version": "18.9.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "18.9.0-rc.1", + "version": "18.9.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 412ff34b91d8c1..9234bf92cc9172 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "18.9.0-rc.1", + "version": "18.9.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 843a7f7e670ca2df47a4b939de2f938e96b55509 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 1 Aug 2024 03:35:43 +0900 Subject: [PATCH 0196/1908] Format Library: Add alt edit field to inline image (#64124) * Format Library: Add alt edit field to inline image * Remove redudant state * Add help text * Tweak spacing value * Use __next40pxDefaultSize * Use 260px width --------- Co-authored-by: Rich Tabor <hi@richtabor.com> --- packages/format-library/src/image/index.js | 69 +++++++++++++++---- packages/format-library/src/image/style.scss | 2 +- .../various/adding-inline-tokens.spec.js | 9 ++- 3 files changed, 61 insertions(+), 19 deletions(-) diff --git a/packages/format-library/src/image/index.js b/packages/format-library/src/image/index.js index 794af776c88e76..7f8e33550770d0 100644 --- a/packages/format-library/src/image/index.js +++ b/packages/format-library/src/image/index.js @@ -6,8 +6,11 @@ import { SVG, Popover, Button, - __experimentalNumberControl as NumberControl, + ExternalLink, __experimentalHStack as HStack, + __experimentalVStack as VStack, + __experimentalNumberControl as NumberControl, + TextareaControl, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useState } from '@wordpress/element'; @@ -17,7 +20,6 @@ import { RichTextToolbarButton, MediaUploadCheck, } from '@wordpress/block-editor'; -import { keyboardReturn } from '@wordpress/icons'; const ALLOWED_MEDIA_TYPES = [ 'image' ]; @@ -41,8 +43,11 @@ export const image = { }; function InlineUI( { value, onChange, activeObjectAttributes, contentRef } ) { - const { style } = activeObjectAttributes; - const [ width, setWidth ] = useState( style?.replace( /\D/g, '' ) ); + const { style, alt } = activeObjectAttributes; + const width = style?.replace( /\D/g, '' ); + const [ editedWidth, setEditedWidth ] = useState( width ); + const [ editedAlt, setEditedAlt ] = useState( alt ); + const hasChanged = editedWidth !== width || editedAlt !== alt; const popoverAnchor = useAnchor( { editableContentElement: contentRef.current, settings: image, @@ -64,7 +69,8 @@ function InlineUI( { value, onChange, activeObjectAttributes, contentRef } ) { type: name, attributes: { ...activeObjectAttributes, - style: width ? `width: ${ width }px;` : '', + style: width ? `width: ${ editedWidth }px;` : '', + alt: editedAlt, }, }; @@ -76,21 +82,54 @@ function InlineUI( { value, onChange, activeObjectAttributes, contentRef } ) { event.preventDefault(); } } > - <HStack alignment="bottom"> + <VStack spacing={ 4 }> <NumberControl + __next40pxDefaultSize label={ __( 'Width' ) } - value={ width } + value={ editedWidth } min={ 1 } - onChange={ ( newWidth ) => setWidth( newWidth ) } - size="__unstable-large" + onChange={ ( newWidth ) => { + setEditedWidth( newWidth ); + } } /> - <Button - icon={ keyboardReturn } - label={ __( 'Apply' ) } - type="submit" - __next40pxDefaultSize + <TextareaControl + label={ __( 'Alternative text' ) } + __nextHasNoMarginBottom + value={ editedAlt } + onChange={ ( newAlt ) => { + setEditedAlt( newAlt ); + } } + help={ + <> + <ExternalLink + href={ + // translators: Localized tutorial, if one exists. W3C Web Accessibility Initiative link has list of existing translations. + __( + 'https://www.w3.org/WAI/tutorials/images/decision-tree/' + ) + } + > + { __( + 'Describe the purpose of the image.' + ) } + </ExternalLink> + <br /> + { __( 'Leave empty if decorative.' ) } + </> + } /> - </HStack> + <HStack justify="right"> + <Button + disabled={ ! hasChanged } + accessibleWhenDisabled + variant="primary" + type="submit" + size="compact" + > + { __( 'Apply' ) } + </Button> + </HStack> + </VStack> </form> </Popover> ); diff --git a/packages/format-library/src/image/style.scss b/packages/format-library/src/image/style.scss index 7e9809e52f3bf2..1e0b922fdf4c8f 100644 --- a/packages/format-library/src/image/style.scss +++ b/packages/format-library/src/image/style.scss @@ -2,7 +2,7 @@ z-index: z-index(".block-editor-format-toolbar__image-popover"); .block-editor-format-toolbar__image-container-content { - width: 200px; + width: 260px; padding: $grid-unit-20; } } diff --git a/test/e2e/specs/editor/various/adding-inline-tokens.spec.js b/test/e2e/specs/editor/various/adding-inline-tokens.spec.js index 15f9d9ea877320..c7826ebf262822 100644 --- a/test/e2e/specs/editor/various/adding-inline-tokens.spec.js +++ b/test/e2e/specs/editor/various/adding-inline-tokens.spec.js @@ -64,13 +64,16 @@ test.describe( 'adding inline tokens', () => { await pageUtils.pressKeys( 'shift+ArrowLeft' ); await page.keyboard.press( 'Tab' ); - await page.keyboard.press( 'Tab' ); - await page.fill( 'role=spinbutton[name="WIDTH"i]', '20' ); + await expect( + page.locator( 'role=spinbutton[name="Width"i]' ) + ).toBeFocused(); + await page.fill( 'role=spinbutton[name="Width"i]', '20' ); + await page.fill( 'role=textbox[name="Alternative text"i]', 'Alt' ); await page.click( 'role=button[name="Apply"i]' ); // Check the content. const contentRegex2 = new RegExp( - `a <img class="wp-image-\\d+" style="width:\\s*20px;?" src="[^"]+\\/${ filename }\\.png" alt=""\\/?>` + `a <img class="wp-image-\\d+" style="width:\\s*20px;?" src="[^"]+\\/${ filename }\\.png" alt="Alt"\\/?>` ); await expect.poll( editor.getBlocks ).toMatchObject( [ From 635c13465a9ec710c81a782a971c60fab3329a79 Mon Sep 17 00:00:00 2001 From: Rich Tabor <hi@richtabor.com> Date: Wed, 31 Jul 2024 15:32:00 -0400 Subject: [PATCH 0197/1908] Tweak Tag Cloud controls and description (#64151) * improve layout of controls * update description Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- .../block-library/src/tag-cloud/block.json | 2 +- packages/block-library/src/tag-cloud/edit.js | 79 +++++++++++-------- 3 files changed, 47 insertions(+), 36 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 9e56387bc66658..72281a53c3dd18 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -908,7 +908,7 @@ Summarize your post with a list of headings. Add HTML anchors to Heading blocks ## Tag Cloud -A cloud of your most used tags. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/tag-cloud)) +A cloud of popular keywords, each sized by how often it appears. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/tag-cloud)) - **Name:** core/tag-cloud - **Category:** widgets diff --git a/packages/block-library/src/tag-cloud/block.json b/packages/block-library/src/tag-cloud/block.json index b95e02204faa29..0c2095bff2a152 100644 --- a/packages/block-library/src/tag-cloud/block.json +++ b/packages/block-library/src/tag-cloud/block.json @@ -4,7 +4,7 @@ "name": "core/tag-cloud", "title": "Tag Cloud", "category": "widgets", - "description": "A cloud of your most used tags.", + "description": "A cloud of popular keywords, each sized by how often it appears.", "textdomain": "default", "attributes": { "numberOfTags": { diff --git a/packages/block-library/src/tag-cloud/edit.js b/packages/block-library/src/tag-cloud/edit.js index 29f4823a19b425..17ca150bc4d75f 100644 --- a/packages/block-library/src/tag-cloud/edit.js +++ b/packages/block-library/src/tag-cloud/edit.js @@ -12,6 +12,7 @@ import { __experimentalUseCustomUnits as useCustomUnits, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, Disabled, + BaseControl, } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; @@ -111,6 +112,7 @@ function TagCloudEdit( { attributes, setAttributes } ) { <PanelBody title={ __( 'Settings' ) }> <SelectControl __nextHasNoMarginBottom + __next40pxDefaultSize label={ __( 'Taxonomy' ) } options={ getTaxonomyOptions() } value={ taxonomy } @@ -118,14 +120,42 @@ function TagCloudEdit( { attributes, setAttributes } ) { setAttributes( { taxonomy: selectedTaxonomy } ) } /> - <ToggleControl - __nextHasNoMarginBottom - label={ __( 'Show post counts' ) } - checked={ showTagCounts } - onChange={ () => - setAttributes( { showTagCounts: ! showTagCounts } ) - } - /> + <BaseControl> + <Flex gap={ 4 }> + <FlexItem isBlock> + <UnitControl + label={ __( 'Smallest size' ) } + value={ smallestFontSize } + onChange={ ( value ) => { + onFontSizeChange( + 'smallestFontSize', + value + ); + } } + units={ units } + min={ MIN_FONT_SIZE } + max={ MAX_FONT_SIZE } + size="__unstable-large" + /> + </FlexItem> + <FlexItem isBlock> + <UnitControl + label={ __( 'Largest size' ) } + value={ largestFontSize } + onChange={ ( value ) => { + onFontSizeChange( + 'largestFontSize', + value + ); + } } + units={ units } + min={ MIN_FONT_SIZE } + max={ MAX_FONT_SIZE } + size="__unstable-large" + /> + </FlexItem> + </Flex> + </BaseControl> <RangeControl __nextHasNoMarginBottom __next40pxDefaultSize @@ -138,32 +168,13 @@ function TagCloudEdit( { attributes, setAttributes } ) { max={ MAX_TAGS } required /> - <Flex> - <FlexItem isBlock> - <UnitControl - label={ __( 'Smallest size' ) } - value={ smallestFontSize } - onChange={ ( value ) => { - onFontSizeChange( 'smallestFontSize', value ); - } } - units={ units } - min={ MIN_FONT_SIZE } - max={ MAX_FONT_SIZE } - /> - </FlexItem> - <FlexItem isBlock> - <UnitControl - label={ __( 'Largest size' ) } - value={ largestFontSize } - onChange={ ( value ) => { - onFontSizeChange( 'largestFontSize', value ); - } } - units={ units } - min={ MIN_FONT_SIZE } - max={ MAX_FONT_SIZE } - /> - </FlexItem> - </Flex> + <ToggleControl + label={ __( 'Show tag counts' ) } + checked={ showTagCounts } + onChange={ () => + setAttributes( { showTagCounts: ! showTagCounts } ) + } + /> </PanelBody> </InspectorControls> ); From f0874aca3313cc3275b9e16ea27daff3b74f4597 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 1 Aug 2024 04:34:00 +0900 Subject: [PATCH 0198/1908] TimeInput: Expose as subcomponent of TimePicker (#63145) * TimeInput: Make subcomponent of TimePicker * Add changelog * Hide Storybook controls for TimeInput story * Add explicit font-size to colon Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: bogiii <bogdannikolic@git.wordpress.org> Co-authored-by: Tropicalista <tropicalista@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/date-time/index.ts | 3 +- .../date-time/stories/time-input.story.tsx | 36 ------------------- .../src/date-time/stories/time.story.tsx | 17 +++++++++ .../components/src/date-time/time/index.tsx | 27 +++++++++++++- .../components/src/date-time/time/styles.ts | 1 + .../date-time/{ => time}/time-input/index.tsx | 18 +++++----- .../{ => time}/time-input/test/index.tsx | 0 8 files changed, 55 insertions(+), 48 deletions(-) delete mode 100644 packages/components/src/date-time/stories/time-input.story.tsx rename packages/components/src/date-time/{ => time}/time-input/index.tsx (91%) rename packages/components/src/date-time/{ => time}/time-input/test/index.tsx (100%) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index aff6181833b354..e6e1dbbf50a1f5 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -10,6 +10,7 @@ ### Enhancements +- `TimeInput`: Expose as subcomponent of `TimePicker` ([#63145](https://github.com/WordPress/gutenberg/pull/63145)). - `RadioControl`: add support for option help text ([#63751](https://github.com/WordPress/gutenberg/pull/63751)). ### Internal diff --git a/packages/components/src/date-time/index.ts b/packages/components/src/date-time/index.ts index 8335366bcbb73b..a103bac0d30efb 100644 --- a/packages/components/src/date-time/index.ts +++ b/packages/components/src/date-time/index.ts @@ -3,8 +3,7 @@ */ import { default as DatePicker } from './date'; import { default as TimePicker } from './time'; -import { default as TimeInput } from './time-input'; import { default as DateTimePicker } from './date-time'; -export { DatePicker, TimePicker, TimeInput }; +export { DatePicker, TimePicker }; export default DateTimePicker; diff --git a/packages/components/src/date-time/stories/time-input.story.tsx b/packages/components/src/date-time/stories/time-input.story.tsx deleted file mode 100644 index c74d886e82477c..00000000000000 --- a/packages/components/src/date-time/stories/time-input.story.tsx +++ /dev/null @@ -1,36 +0,0 @@ -/** - * External dependencies - */ -import type { Meta, StoryFn } from '@storybook/react'; -import { action } from '@storybook/addon-actions'; - -/** - * Internal dependencies - */ -import { TimeInput } from '../time-input'; - -const meta: Meta< typeof TimeInput > = { - title: 'Components/TimeInput', - component: TimeInput, - argTypes: { - onChange: { action: 'onChange', control: { type: null } }, - }, - tags: [ 'status-wip' ], - parameters: { - controls: { expanded: true }, - docs: { canvas: { sourceState: 'shown' } }, - }, - args: { - onChange: action( 'onChange' ), - }, -}; -export default meta; - -const Template: StoryFn< typeof TimeInput > = ( args ) => { - return <TimeInput { ...args } />; -}; - -export const Default: StoryFn< typeof TimeInput > = Template.bind( {} ); -Default.args = { - label: 'Time', -}; diff --git a/packages/components/src/date-time/stories/time.story.tsx b/packages/components/src/date-time/stories/time.story.tsx index c48b8fb1d15922..947b5bd64d5eb1 100644 --- a/packages/components/src/date-time/stories/time.story.tsx +++ b/packages/components/src/date-time/stories/time.story.tsx @@ -16,6 +16,8 @@ import TimePicker from '../time'; const meta: Meta< typeof TimePicker > = { title: 'Components/TimePicker', component: TimePicker, + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + subcomponents: { 'TimePicker.TimeInput': TimePicker.TimeInput }, argTypes: { currentTime: { control: 'date' }, onChange: { action: 'onChange', control: { type: null } }, @@ -49,3 +51,18 @@ const Template: StoryFn< typeof TimePicker > = ( { }; export const Default: StoryFn< typeof TimePicker > = Template.bind( {} ); + +const TimeInputTemplate: StoryFn< typeof TimePicker.TimeInput > = ( args ) => { + return <TimePicker.TimeInput { ...args } />; +}; + +/** + * The time input can be used in isolation as `<TimePicker.TimeInput />`. In this case, the `value` will be passed + * as an object in 24-hour format (`{ hours: number, minutes: number }`). + */ +export const TimeInput = TimeInputTemplate.bind( {} ); +TimeInput.args = { + label: 'Time', +}; +// Hide TimePicker controls because they don't apply to TimeInput +TimeInput.parameters = { controls: { include: [] } }; diff --git a/packages/components/src/date-time/time/index.tsx b/packages/components/src/date-time/time/index.tsx index e2877a1ded5e1f..809376d99d3036 100644 --- a/packages/components/src/date-time/time/index.tsx +++ b/packages/components/src/date-time/time/index.tsx @@ -32,7 +32,7 @@ import { validateInputElementTarget, } from '../utils'; import { TIMEZONELESS_FORMAT } from '../constants'; -import { TimeInput } from '../time-input'; +import { TimeInput } from './time-input'; const VALID_DATE_ORDERS = [ 'dmy', 'mdy', 'ymd' ]; @@ -252,4 +252,29 @@ export function TimePicker( { ); } +/** + * A component to input a time. + * + * Values are passed as an object in 24-hour format (`{ hours: number, minutes: number }`). + * + * ```jsx + * import { TimePicker } from '@wordpress/components'; + * import { useState } from '@wordpress/element'; + * + * const MyTimeInput = () => { + * const [ time, setTime ] = useState( { hours: 13, minutes: 30 } ); + * + * return ( + * <TimePicker.TimeInput + * value={ time } + * onChange={ setTime } + * label="Time" + * /> + * ); + * }; + * ``` + */ +TimePicker.TimeInput = TimeInput; +Object.assign( TimePicker.TimeInput, { displayName: 'TimePicker.TimeInput' } ); + export default TimePicker; diff --git a/packages/components/src/date-time/time/styles.ts b/packages/components/src/date-time/time/styles.ts index bba0cc500e0c8a..066c8fb1d1d3cd 100644 --- a/packages/components/src/date-time/time/styles.ts +++ b/packages/components/src/date-time/time/styles.ts @@ -62,6 +62,7 @@ export const HoursInput = styled( NumberControl )` export const TimeSeparator = styled.span` border-top: ${ CONFIG.borderWidth } solid ${ COLORS.gray[ 700 ] }; border-bottom: ${ CONFIG.borderWidth } solid ${ COLORS.gray[ 700 ] }; + font-size: ${ CONFIG.fontSize }; line-height: calc( ${ CONFIG.controlHeight } - ${ CONFIG.borderWidth } * 2 ); diff --git a/packages/components/src/date-time/time-input/index.tsx b/packages/components/src/date-time/time/time-input/index.tsx similarity index 91% rename from packages/components/src/date-time/time-input/index.tsx rename to packages/components/src/date-time/time/time-input/index.tsx index bfac1e2b604c23..b4421c601b1d6d 100644 --- a/packages/components/src/date-time/time-input/index.tsx +++ b/packages/components/src/date-time/time/time-input/index.tsx @@ -18,20 +18,20 @@ import { HoursInput, MinutesInput, Fieldset, -} from '../time/styles'; -import { HStack } from '../../h-stack'; -import Button from '../../button'; -import ButtonGroup from '../../button-group'; +} from '../styles'; +import { HStack } from '../../../h-stack'; +import Button from '../../../button'; +import ButtonGroup from '../../../button-group'; import { from12hTo24h, from24hTo12h, buildPadInputStateReducer, validateInputElementTarget, -} from '../utils'; -import type { TimeInputProps } from '../types'; -import type { InputChangeCallback } from '../../input-control/types'; -import { useControlledValue } from '../../utils'; -import BaseControl from '../../base-control'; +} from '../../utils'; +import type { TimeInputProps } from '../../types'; +import type { InputChangeCallback } from '../../../input-control/types'; +import { useControlledValue } from '../../../utils'; +import BaseControl from '../../../base-control'; export function TimeInput( { value: valueProp, diff --git a/packages/components/src/date-time/time-input/test/index.tsx b/packages/components/src/date-time/time/time-input/test/index.tsx similarity index 100% rename from packages/components/src/date-time/time-input/test/index.tsx rename to packages/components/src/date-time/time/time-input/test/index.tsx From a13c4fc0f0893db46cc9829a2031218058113725 Mon Sep 17 00:00:00 2001 From: Amit Raj <77401999+amitraj2203@users.noreply.github.com> Date: Thu, 1 Aug 2024 01:06:26 +0530 Subject: [PATCH 0199/1908] Update help text for sticky control in Query loop (#63999) * feat: Update help text for StickyControl in query editor * make help text more indicative of what a sticky post is --------- Co-authored-by: Rich Tabor <hi@richtabor.com> --- .../src/query/edit/inspector-controls/sticky-control.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/query/edit/inspector-controls/sticky-control.js b/packages/block-library/src/query/edit/inspector-controls/sticky-control.js index 98bec75ad933b6..ee7ee31ba977a9 100644 --- a/packages/block-library/src/query/edit/inspector-controls/sticky-control.js +++ b/packages/block-library/src/query/edit/inspector-controls/sticky-control.js @@ -20,7 +20,7 @@ export default function StickyControl( { value, onChange } ) { value={ value } onChange={ onChange } help={ __( - 'Blog posts can be “stickied”, a feature that places them at the top of the front page of posts, keeping it there until new sticky posts are published.' + 'Sticky posts always appear first, regardless of their publish date.' ) } /> ); From f9b966b290b7ed3445b2269b3062ea1264202972 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 31 Jul 2024 19:44:10 +0000 Subject: [PATCH 0200/1908] Update Changelog for 18.9.0 --- changelog.txt | 163 ++++++++++++++++++++++---------------------------- 1 file changed, 73 insertions(+), 90 deletions(-) diff --git a/changelog.txt b/changelog.txt index 412d6184d76604..b7bbdf821f374e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,40 +1,14 @@ == Changelog == -= 18.9.0-rc.1 = - += 18.9.0 = ## Changelog -### Features - -- change: Updated soundcloud icon for social link block. ([63504](https://github.com/WordPress/gutenberg/pull/63504)) - -#### Global Styles -- Adding Font size presets UI. ([63057](https://github.com/WordPress/gutenberg/pull/63057)) - - ### Enhancements -- Background tool: Fix double border. ([63559](https://github.com/WordPress/gutenberg/pull/63559)) -- Core Data: Mark 'canUser' related actions resolvers as resolved. ([63435](https://github.com/WordPress/gutenberg/pull/63435)) -- Core Data: Resolve user capabilities when fetching an entity. ([63430](https://github.com/WordPress/gutenberg/pull/63430)) -- Core Data: Support entities in the 'canUser' selector. ([63322](https://github.com/WordPress/gutenberg/pull/63322)) -- Core Data: Support entity queries in the 'useResourcePermissions' hook. ([63653](https://github.com/WordPress/gutenberg/pull/63653)) -- DataViews: Update pagination icons. ([63594](https://github.com/WordPress/gutenberg/pull/63594)) -- Embeds: Add 'Embed' to title for clarity. ([63371](https://github.com/WordPress/gutenberg/pull/63371)) -- Polish "Delete" modal. ([63392](https://github.com/WordPress/gutenberg/pull/63392)) -- Run sync when issue is labeled with Sync Backport Changelog. ([63793](https://github.com/WordPress/gutenberg/pull/63793)) -- Update JSON Schemas to Draft 7. ([63583](https://github.com/WordPress/gutenberg/pull/63583)) -- Update: Grid layout: Allow users to adjust grid density. ([63367](https://github.com/WordPress/gutenberg/pull/63367)) -- Update: Include avatars on list view. ([63309](https://github.com/WordPress/gutenberg/pull/63309)) -- Update: List / Table layout – selected item stroke should be tinted blue. ([63312](https://github.com/WordPress/gutenberg/pull/63312)) -- Update: Make changing order an action on the ellipsis menu. ([62189](https://github.com/WordPress/gutenberg/pull/62189)) -- Update: Pages: Trash view should default to table layout try 2. ([63652](https://github.com/WordPress/gutenberg/pull/63652)) -- Update: Simplify some permission checks. ([63812](https://github.com/WordPress/gutenberg/pull/63812)) -- Use entity details when calling 'canUser' selectors. ([63415](https://github.com/WordPress/gutenberg/pull/63415)) - #### Block Library - Add Clear button for Overlay color option in Cover Block. ([63580](https://github.com/WordPress/gutenberg/pull/63580)) +- Embeds: Add 'Embed' to title for clarity. ([63371](https://github.com/WordPress/gutenberg/pull/63371)) - Columns block: Fix block preview. ([63609](https://github.com/WordPress/gutenberg/pull/63609)) - Gallery: Add border block support. ([63428](https://github.com/WordPress/gutenberg/pull/63428)) - Image block: Show placeholder when uploading HEIC files. ([63643](https://github.com/WordPress/gutenberg/pull/63643)) @@ -50,21 +24,10 @@ - Query Loop: Change default query loop variations. ([63353](https://github.com/WordPress/gutenberg/pull/63353)) - Set query loop to have the inherit value by default. ([63362](https://github.com/WordPress/gutenberg/pull/63362)) - Social Links: Add border block support. ([63629](https://github.com/WordPress/gutenberg/pull/63629)) +- Social Links: Updated soundcloud icon for social link block. ([63504](https://github.com/WordPress/gutenberg/pull/63504)) +- Social Links: Update Facebook's color to match brand guidelines. ([60424](https://github.com/WordPress/gutenberg/pull/60424)) - Term Description: Add border block support. ([63630](https://github.com/WordPress/gutenberg/pull/63630)) -#### Components -- CustomSelectControl V2 legacy adapter: Stabilize experimental props. ([63248](https://github.com/WordPress/gutenberg/pull/63248)) -- CustomSelectControl: Switch to ariakit-based implementation. ([63258](https://github.com/WordPress/gutenberg/pull/63258)) -- CustomSelectControlV2: Animate select popover appearance. ([63343](https://github.com/WordPress/gutenberg/pull/63343)) -- CustomSelectControlV2: Do not flip popover if legacy adapter. ([63357](https://github.com/WordPress/gutenberg/pull/63357)) -- DropdownMenuV2: Invert animation direction. ([63443](https://github.com/WordPress/gutenberg/pull/63443)) -- FontSizePicker: Tidy up internal logic. ([63553](https://github.com/WordPress/gutenberg/pull/63553)) -- FormTokenField: Deprecate bottom margin. ([63491](https://github.com/WordPress/gutenberg/pull/63491)) -- SelectControl: Add "minimal" variant. ([63265](https://github.com/WordPress/gutenberg/pull/63265)) -- Tabs: Hyphenate tab labels. ([63337](https://github.com/WordPress/gutenberg/pull/63337)) -- Tabs: Keep full opacity of focus ring on disabled tabs. ([63754](https://github.com/WordPress/gutenberg/pull/63754)) -- Update HeightControl component to label inputs. ([63761](https://github.com/WordPress/gutenberg/pull/63761)) - #### Design Tools - Background Image: Make panel appear in a consistent location. ([63551](https://github.com/WordPress/gutenberg/pull/63551)) - Buttons: Add border, color, and padding block supports. ([63538](https://github.com/WordPress/gutenberg/pull/63538)) @@ -77,15 +40,21 @@ #### Data Views - DataViews: Allow column re-ordering. ([63416](https://github.com/WordPress/gutenberg/pull/63416)) +- DataViews: Update pagination icons. ([63594](https://github.com/WordPress/gutenberg/pull/63594)) - DataViews: Rename the header property of fields to label. ([63843](https://github.com/WordPress/gutenberg/pull/63843)) - DataViews: Support combined fields. ([63236](https://github.com/WordPress/gutenberg/pull/63236)) - Dataviews List: Update item layout. ([63299](https://github.com/WordPress/gutenberg/pull/63299)) - Increase column-gap between fields in List layout. ([63603](https://github.com/WordPress/gutenberg/pull/63603)) -- Pages: Trash view should default to table layout. ([63138](https://github.com/WordPress/gutenberg/pull/63138)) - Update 'Front page' badge. ([63752](https://github.com/WordPress/gutenberg/pull/63752)) +- Update: Pages: Trash view should default to table layout try 2. ([63652](https://github.com/WordPress/gutenberg/pull/63652)) +- Update: Grid layout: Allow users to adjust grid density. ([63367](https://github.com/WordPress/gutenberg/pull/63367)) +- Update: Include avatars on list view. ([63309](https://github.com/WordPress/gutenberg/pull/63309)) +- Update: List / Table layout – selected item stroke should be tinted blue. ([63312](https://github.com/WordPress/gutenberg/pull/63312)) +- Update: Make changing order an action on the ellipsis menu. ([62189](https://github.com/WordPress/gutenberg/pull/62189)) #### Global Styles - Add colors and typograpghy to the browse styles section. ([63173](https://github.com/WordPress/gutenberg/pull/63173)) +- Adding Font size presets UI. ([63057](https://github.com/WordPress/gutenberg/pull/63057)) - Apply same styles to block previews on inserter and Global Styles. ([63177](https://github.com/WordPress/gutenberg/pull/63177)) - Background: Add background attachment to top level styles. ([61382](https://github.com/WordPress/gutenberg/pull/61382)) - Move background panel under color panel. ([63888](https://github.com/WordPress/gutenberg/pull/63888)) @@ -112,55 +81,60 @@ #### Block Locking - Tweak Block Locking UI. ([63881](https://github.com/WordPress/gutenberg/pull/63881)) -#### Icons +#### General UI +- Polish "Delete" modal. ([63392](https://github.com/WordPress/gutenberg/pull/63392)) - Update close icon. ([63597](https://github.com/WordPress/gutenberg/pull/63597)) +- Site Editor: Reduce navigation sidebar width. ([63431](https://github.com/WordPress/gutenberg/pull/63431)) #### Block bindings - Bootstrap sources defined in the server. ([63470](https://github.com/WordPress/gutenberg/pull/63470)) -#### Site Editor -- Reduce navigation sidebar width. ([63431](https://github.com/WordPress/gutenberg/pull/63431)) - #### Patterns - Limit pattern shuffling to theme and user patterns only. ([62677](https://github.com/WordPress/gutenberg/pull/62677)) +#### Components +- CustomSelectControl V2 legacy adapter: Stabilize experimental props. ([63248](https://github.com/WordPress/gutenberg/pull/63248)) +- CustomSelectControl: Switch to ariakit-based implementation. ([63258](https://github.com/WordPress/gutenberg/pull/63258)) +- CustomSelectControlV2: Animate select popover appearance. ([63343](https://github.com/WordPress/gutenberg/pull/63343)) +- CustomSelectControlV2: Do not flip popover if legacy adapter. ([63357](https://github.com/WordPress/gutenberg/pull/63357)) +- DropdownMenuV2: Invert animation direction. ([63443](https://github.com/WordPress/gutenberg/pull/63443)) +- FontSizePicker: Tidy up internal logic. ([63553](https://github.com/WordPress/gutenberg/pull/63553)) +- FormTokenField: Deprecate bottom margin. ([63491](https://github.com/WordPress/gutenberg/pull/63491)) +- SelectControl: Add "minimal" variant. ([63265](https://github.com/WordPress/gutenberg/pull/63265)) +- Tabs: Hyphenate tab labels. ([63337](https://github.com/WordPress/gutenberg/pull/63337)) +- Tabs: Keep full opacity of focus ring on disabled tabs. ([63754](https://github.com/WordPress/gutenberg/pull/63754)) +- Update HeightControl component to label inputs. ([63761](https://github.com/WordPress/gutenberg/pull/63761)) + +#### Core Data +- Core Data: Mark 'canUser' related actions resolvers as resolved. ([63435](https://github.com/WordPress/gutenberg/pull/63435)) +- Core Data: Resolve user capabilities when fetching an entity. ([63430](https://github.com/WordPress/gutenberg/pull/63430)) +- Core Data: Support entities in the 'canUser' selector. ([63322](https://github.com/WordPress/gutenberg/pull/63322)) +- Core Data: Support entity queries in the 'useResourcePermissions' hook. ([63653](https://github.com/WordPress/gutenberg/pull/63653)) + +#### JSON Schemas +- Update JSON Schemas to Draft 7. ([63583](https://github.com/WordPress/gutenberg/pull/63583)) ### New APIs #### Block bindings - Unify `getValue`/`getValues` and `setValue`/`setValues` APIs. ([63185](https://github.com/WordPress/gutenberg/pull/63185)) - ### Bug Fixes -- Add: Permission checks to avoid 403 errors on non admin roles. ([63296](https://github.com/WordPress/gutenberg/pull/63296)) -- DataViews: Do not render bulk actions Dropdown if no actions are available. ([63575](https://github.com/WordPress/gutenberg/pull/63575)) -- DataViews: Fix uncontrolled selection. ([63741](https://github.com/WordPress/gutenberg/pull/63741)) -- Disallow scrolling the block preview. ([63558](https://github.com/WordPress/gutenberg/pull/63558)) -- Discussions panel: Distinguish between verb and adjective form of open for internationalization. ([63791](https://github.com/WordPress/gutenberg/pull/63791)) -- Fix canvas issues by removing VisualEditor’s height. ([63724](https://github.com/WordPress/gutenberg/pull/63724)) -- Fix mobile styles for inserter pattern and media tab navigation. ([63451](https://github.com/WordPress/gutenberg/pull/63451)) -- Fix: Error while Calling edit-site getCurrentTemplateTemplateParts selector. ([63818](https://github.com/WordPress/gutenberg/pull/63818)) -- Footnotes: Register format within the init function. ([63554](https://github.com/WordPress/gutenberg/pull/63554)) -- InnerBlocks: Make sure blockType is set before trying to use it. ([63351](https://github.com/WordPress/gutenberg/pull/63351)) -- Prepare JSON schemas for Draft 7 update. ([63582](https://github.com/WordPress/gutenberg/pull/63582)) -- Revert "Pages: Trash view should default to table layout.". ([63481](https://github.com/WordPress/gutenberg/pull/63481)) -- Sync backport changelog action: Use outputs instead of env. ([63792](https://github.com/WordPress/gutenberg/pull/63792)) -- core-data: Fix `canUser` allowed methods handling. ([63615](https://github.com/WordPress/gutenberg/pull/63615)) -- useBlockElement: Return null until ref callback has time to clean up the old element. ([63565](https://github.com/WordPress/gutenberg/pull/63565)) - #### Data Views +- DataViews: Do not render bulk actions Dropdown if no actions are available. ([63575](https://github.com/WordPress/gutenberg/pull/63575)) - DataViews: Fix default layouts in the pages data views. ([63427](https://github.com/WordPress/gutenberg/pull/63427)) - DataViews: Fix featured image height regression. ([63424](https://github.com/WordPress/gutenberg/pull/63424)) - DataViews: Fix field rendering. ([63452](https://github.com/WordPress/gutenberg/pull/63452)) - DataViews: Fix pattens list selection. ([63733](https://github.com/WordPress/gutenberg/pull/63733)) +- DataViews: Fix uncontrolled selection. ([63741](https://github.com/WordPress/gutenberg/pull/63741)) - DataViews: Only show elligible actions in the bulk editing menu. ([63473](https://github.com/WordPress/gutenberg/pull/63473)) - Fix patterns sorting by `title`. ([63710](https://github.com/WordPress/gutenberg/pull/63710)) - Fix selected row styles in table layout. ([63811](https://github.com/WordPress/gutenberg/pull/63811)) - Fix: DataViews: Layout resets for patterns each time a new pattern category is selected. ([63711](https://github.com/WordPress/gutenberg/pull/63711)) - Fix: Inconsistent field spacing in Grid layout. ([63363](https://github.com/WordPress/gutenberg/pull/63363)) - Templates DataViews: Set the right context for the preview field. ([63488](https://github.com/WordPress/gutenberg/pull/63488)) - +- #### Block Editor - Fix user patterns disabling sync filter. ([63828](https://github.com/WordPress/gutenberg/pull/63828)) - ImageURLInputUI: Make onSetLightbox and resetLightbox optional. ([63573](https://github.com/WordPress/gutenberg/pull/63573)) @@ -169,11 +143,14 @@ - Prevent empty void at the bottom of editor when block directory results are present. ([63397](https://github.com/WordPress/gutenberg/pull/63397)) - Remove double shadow on Inserter category panel when zoomed out. ([63516](https://github.com/WordPress/gutenberg/pull/63516)) - Tabs: Vertical Tabs should be 40px min height. ([63446](https://github.com/WordPress/gutenberg/pull/63446)) -- Zoom out mode: Translate toolbar delete button. ([63476](https://github.com/WordPress/gutenberg/pull/63476)) +- Fix mobile styles for inserter pattern and media tab navigation. ([63451](https://github.com/WordPress/gutenberg/pull/63451)) +- useBlockElement: Return null until ref callback has time to clean up the old element. ([63565](https://github.com/WordPress/gutenberg/pull/63565)) +- Remove hint in the Settings tab. ([63515](https://github.com/WordPress/gutenberg/pull/63515)) #### Block Library - Avoid stripping attributes via group block migration when no layout is specified. ([63837](https://github.com/WordPress/gutenberg/pull/63837)) - Fix default unit issue for tag cloud block. ([59122](https://github.com/WordPress/gutenberg/pull/59122)) +- Footnotes: Register format within the init function. ([63554](https://github.com/WordPress/gutenberg/pull/63554)) - Image lightbox: Remove duplicate image when lightbox is opened. ([63381](https://github.com/WordPress/gutenberg/pull/63381)) - Query Loop: Fix 'block' scoped variations to get the `query` defaults. ([63477](https://github.com/WordPress/gutenberg/pull/63477)) - Query Loop: Fix passing of `namespace` when selecting from suggested patterns. ([63402](https://github.com/WordPress/gutenberg/pull/63402)) @@ -181,6 +158,7 @@ - Update Inherited Query Loop value from Template Settings changes. ([63358](https://github.com/WordPress/gutenberg/pull/63358)) #### Site Editor +- Fix: Error while Calling edit-site getCurrentTemplateTemplateParts selector. ([63818](https://github.com/WordPress/gutenberg/pull/63818)) - Fix error when duplicating a template part. ([63663](https://github.com/WordPress/gutenberg/pull/63663)) - Fix: Add Template Modal layout in mobile view. ([63627](https://github.com/WordPress/gutenberg/pull/63627)) - Make hover block outlines not present in Distraction Free. ([63819](https://github.com/WordPress/gutenberg/pull/63819)) @@ -192,6 +170,7 @@ - Ensure that we only enter zoom out mode if the experiment is enabled. ([63417](https://github.com/WordPress/gutenberg/pull/63417)) - Fix crash due to absence of selected block. ([63642](https://github.com/WordPress/gutenberg/pull/63642)) - Fix vertical toolbar position. ([63745](https://github.com/WordPress/gutenberg/pull/63745)) +- Translate toolbar delete button. ([63476](https://github.com/WordPress/gutenberg/pull/63476)) #### Components - Button: Never apply `aria-disabled` to anchor. ([63376](https://github.com/WordPress/gutenberg/pull/63376)) @@ -201,6 +180,7 @@ #### Global Styles - Disable "Reset styles" button when there are no changes. ([63562](https://github.com/WordPress/gutenberg/pull/63562)) +- Disallow scrolling the block preview. ([63558](https://github.com/WordPress/gutenberg/pull/63558)) - Ensure root selector (body) is not wrapped in :root :Where(). ([63726](https://github.com/WordPress/gutenberg/pull/63726)) - Global styles block previews: Fix scaling. ([63596](https://github.com/WordPress/gutenberg/pull/63596)) - Style variations: Don't display the default if its the only variation. ([63555](https://github.com/WordPress/gutenberg/pull/63555)) @@ -219,9 +199,11 @@ #### Design Tools - Background image block support: Fix dropzone size. ([63588](https://github.com/WordPress/gutenberg/pull/63588)) +- Background tool: Fix double border. ([63559](https://github.com/WordPress/gutenberg/pull/63559)) -#### Layout -- Don't remount the block when rendering grid tools. ([63557](https://github.com/WordPress/gutenberg/pull/63557)) +#### General interface +- Discussions panel: Distinguish between verb and adjective form of open for internationalization. ([63791](https://github.com/WordPress/gutenberg/pull/63791)) +- Fix canvas issues by removing VisualEditor’s height. ([63724](https://github.com/WordPress/gutenberg/pull/63724)) #### Block Transforms - Block Switcher Preview: Adjust the position and enable pattern list preview in mobile viewport. ([63512](https://github.com/WordPress/gutenberg/pull/63512)) @@ -232,6 +214,9 @@ #### Block Directory - Memoize store selectors. ([63346](https://github.com/WordPress/gutenberg/pull/63346)) +#### Inner blocks +- InnerBlocks: Make sure blockType is set before trying to use it. ([63351](https://github.com/WordPress/gutenberg/pull/63351)) + #### Widgets Editor - Widgets: Memoize 'getWidgets' store selector. ([63338](https://github.com/WordPress/gutenberg/pull/63338)) @@ -244,12 +229,16 @@ #### Media - Lock post saving during image uploads. ([41120](https://github.com/WordPress/gutenberg/pull/41120)) +#### JSON Schemas +- Prepare JSON schemas for Draft 7 update. ([63582](https://github.com/WordPress/gutenberg/pull/63582)) -### Accessibility +#### Security +- Add: Permission checks to avoid 403 errors on non admin roles. ([63296](https://github.com/WordPress/gutenberg/pull/63296)) -- Align checkbox, radio, and toggle input design. ([63490](https://github.com/WordPress/gutenberg/pull/63490)) +### Accessibility #### Components +- Align checkbox, radio, and toggle input design. ([63490](https://github.com/WordPress/gutenberg/pull/63490)) - Fix ComboboxControl reset button when using the keyboard. ([63410](https://github.com/WordPress/gutenberg/pull/63410)) #### Post Editor @@ -267,18 +256,17 @@ ### Experiments -#### Layout +#### Grid layout - Disable in-between inserter in Manual grids. ([63391](https://github.com/WordPress/gutenberg/pull/63391)) - Don't display default appender inside Manual grid. ([63395](https://github.com/WordPress/gutenberg/pull/63395)) - Fix responsive behaviour so both column start and column span are taken into account. ([63464](https://github.com/WordPress/gutenberg/pull/63464)) -- Grid: Better looking block movers. ([63394](https://github.com/WordPress/gutenberg/pull/63394)) -- Grid: Place new block after currently selected block when using slash inserter and splitting text. ([63333](https://github.com/WordPress/gutenberg/pull/63333)) +- Better looking block movers. ([63394](https://github.com/WordPress/gutenberg/pull/63394)) +- Place new block after currently selected block when using slash inserter and splitting text. ([63333](https://github.com/WordPress/gutenberg/pull/63333)) - Move visualizer popover to slot under the canvas. ([63389](https://github.com/WordPress/gutenberg/pull/63389)) +- Don't remount the block when rendering grid tools. ([63557](https://github.com/WordPress/gutenberg/pull/63557)) #### Data Views - Quick Edit: Support bulk selection. ([63841](https://github.com/WordPress/gutenberg/pull/63841)) - -#### Site Editor - DataViews: Bootstrap Quick Edit. ([63600](https://github.com/WordPress/gutenberg/pull/63600)) @@ -314,11 +302,15 @@ - Block editor settings: Add missing global styles links dependencies. ([63823](https://github.com/WordPress/gutenberg/pull/63823)) - Core Data: Remove leftover 'todo' comment. ([63842](https://github.com/WordPress/gutenberg/pull/63842)) - Core Data: Use meta-store actions for resolution status. ([63469](https://github.com/WordPress/gutenberg/pull/63469)) +- core-data: Fix `canUser` allowed methods handling. ([63615](https://github.com/WordPress/gutenberg/pull/63615)) - DataViews: Move PostList component to its own folder. ([63334](https://github.com/WordPress/gutenberg/pull/63334)) - JSON Schema Reorganization and Fixes. ([63591](https://github.com/WordPress/gutenberg/pull/63591)) - Update: Simplify and do not pass renderingMode on editor SidebarContent. ([63814](https://github.com/WordPress/gutenberg/pull/63814)) - Use Base Focus Styles for Region Focus. ([62881](https://github.com/WordPress/gutenberg/pull/62881)) - Use static 'key' when filtering BlockEdit components. ([63590](https://github.com/WordPress/gutenberg/pull/63590)) +- Update: Simplify some permission checks. ([63812](https://github.com/WordPress/gutenberg/pull/63812)) +- Use entity details when calling 'canUser' selectors. ([63415](https://github.com/WordPress/gutenberg/pull/63415)) +- HTML API: Backport updates from Core. ([63723](https://github.com/WordPress/gutenberg/pull/63723)) #### Block Library - Image block: Remove unnecessary variables on expand on click implementation. ([63290](https://github.com/WordPress/gutenberg/pull/63290)) @@ -375,34 +367,25 @@ #### Block Directory - Remove 'edit-post' package dependency. ([63349](https://github.com/WordPress/gutenberg/pull/63349)) - ### Tools -- Bug: Eslint `recommended-with-formatting` allows for unnecessary spaces. ([63549](https://github.com/WordPress/gutenberg/pull/63549)) +#### Project Management - Issue template: Use checkboxes instead of dropdown. ([63523](https://github.com/WordPress/gutenberg/pull/63523)) -- Scripts: Include variations paths in build. ([63098](https://github.com/WordPress/gutenberg/pull/63098)) -- Scripts: Remove now-obsolete `getRenderPropPaths()`. ([63661](https://github.com/WordPress/gutenberg/pull/63661)) +- Sync backport changelog action: Use outputs instead of env. ([63792](https://github.com/WordPress/gutenberg/pull/63792)) +- Run sync when issue is labeled with Sync Backport Changelog. ([63793](https://github.com/WordPress/gutenberg/pull/63793)) #### Testing - Downgrade node 22(.5) unit tests to 22.4. ([63728](https://github.com/WordPress/gutenberg/pull/63728)) - Font Library: Fix flaky end-to-end tests. ([63904](https://github.com/WordPress/gutenberg/pull/63904)) - Upgrade Playwright to v1.45. ([61443](https://github.com/WordPress/gutenberg/pull/61443)) +- Bug: Eslint `recommended-with-formatting` allows for unnecessary spaces. ([63549](https://github.com/WordPress/gutenberg/pull/63549)) -#### Build Tooling +#### Build Tooling & Plugin - Fix broken license check script. ([61868](https://github.com/WordPress/gutenberg/pull/61868)) - React: Restore umd builds. ([63602](https://github.com/WordPress/gutenberg/pull/63602)) - - -### Various - -- HTML API: Backport updates from Core. ([63723](https://github.com/WordPress/gutenberg/pull/63723)) - Upgrade TypeScript to 5.5. ([63012](https://github.com/WordPress/gutenberg/pull/63012)) - -#### Block Editor -- Remove hint in the Settings tab. ([63515](https://github.com/WordPress/gutenberg/pull/63515)) - -#### Block Library -- Social Links: Update Facebook's color to match brand guidelines. ([60424](https://github.com/WordPress/gutenberg/pull/60424)) +- Scripts: Remove now-obsolete `getRenderPropPaths()`. ([63661](https://github.com/WordPress/gutenberg/pull/63661)) +- Scripts: Include variations paths in build. ([63098](https://github.com/WordPress/gutenberg/pull/63098)) ## First-time contributors From dfa18c5031c2c8df5457b6fad92dd1e45fe05118 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Wed, 31 Jul 2024 21:15:46 +0100 Subject: [PATCH 0201/1908] Centrally align entity in focused edit mode (#64143) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/editor/src/components/visual-editor/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/visual-editor/style.scss b/packages/editor/src/components/visual-editor/style.scss index 18a61827d573da..fae61eda6b8013 100644 --- a/packages/editor/src/components/visual-editor/style.scss +++ b/packages/editor/src/components/visual-editor/style.scss @@ -1,6 +1,6 @@ .editor-visual-editor { position: relative; - display: block; + display: flex; background-color: $gray-300; // Centralize the editor horizontally (flex-direction is column). From 08d3c862187a150163086f76b9ea281d522dd6ca Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Wed, 31 Jul 2024 17:48:27 -0500 Subject: [PATCH 0202/1908] Don't overlap canvas with inserter panel at large screens (#64110) * Don't overlap canvas with inserter panel at large screens * Always resize canvas * Cleanup * Refactor to share new -sidebar-width var * Try to improve animation -- still needs work * animate the pattern category preview panel * use the same animation for both elements * Add animate presence * only use one animated div * Pattern panel zindex * Animate pattern tab panel on open * Try to smooth entrance and exit secondary sidebar animations * remove unneeded properties so that the parent controls the animation * remove unneeded double shadow --------- Co-authored-by: Ben Dwyer <ben@scruffian.com> Co-authored-by: Rich Tabor <hi@richtabor.com> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/base-styles/_variables.scss | 2 +- .../inserter/category-tabs/index.js | 37 ++++++++++++++++++- .../src/components/inserter/style.scss | 27 ++++++++------ .../src/components/tabbed-sidebar/style.scss | 5 +-- .../components/list-view-sidebar/style.scss | 4 ++ .../components/interface-skeleton/index.js | 16 ++++---- 6 files changed, 66 insertions(+), 25 deletions(-) diff --git a/packages/base-styles/_variables.scss b/packages/base-styles/_variables.scss index b26d70b7299f9f..97eb513cf38aeb 100644 --- a/packages/base-styles/_variables.scss +++ b/packages/base-styles/_variables.scss @@ -90,7 +90,7 @@ $sidebar-width: 280px; $content-width: 840px; $wide-content-width: 1100px; $widget-area-width: 700px; - +$secondary-sidebar-width: 350px; /** * Block & Editor UI. diff --git a/packages/block-editor/src/components/inserter/category-tabs/index.js b/packages/block-editor/src/components/inserter/category-tabs/index.js index a379f4719556b2..6a02cf1a170c45 100644 --- a/packages/block-editor/src/components/inserter/category-tabs/index.js +++ b/packages/block-editor/src/components/inserter/category-tabs/index.js @@ -1,11 +1,13 @@ /** * WordPress dependencies */ +import { usePrevious, useReducedMotion } from '@wordpress/compose'; import { isRTL } from '@wordpress/i18n'; import { __experimentalHStack as HStack, FlexBlock, privateApis as componentsPrivateApis, + __unstableMotion as motion, } from '@wordpress/components'; import { Icon, chevronRight, chevronLeft } from '@wordpress/icons'; @@ -22,6 +24,17 @@ function CategoryTabs( { onSelectCategory, children, } ) { + // Copied from InterfaceSkeleton. + const ANIMATION_DURATION = 0.25; + const disableMotion = useReducedMotion(); + const defaultTransition = { + type: 'tween', + duration: disableMotion ? 0 : ANIMATION_DURATION, + ease: [ 0.6, 0, 0.4, 1 ], + }; + + const previousSelectedCategory = usePrevious( selectedCategory ); + return ( <Tabs className="block-editor-inserter__category-tabs" @@ -62,9 +75,29 @@ function CategoryTabs( { key={ category.name } tabId={ category.name } focusable={ false } - className="block-editor-inserter__category-panel" > - { children } + <motion.div + className="block-editor-inserter__category-panel" + initial={ + ! previousSelectedCategory ? 'closed' : 'open' + } + animate="open" + variants={ { + open: { + transform: 'translateX( 0 )', + transitionEnd: { + zIndex: '1', + }, + }, + closed: { + transform: 'translateX( -100% )', + zIndex: '-1', + }, + } } + transition={ defaultTransition } + > + { children } + </motion.div> </Tabs.TabPanel> ) ) } </Tabs> diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index c7398aadb56ba5..960ca8b48cdf90 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -1,5 +1,5 @@ $block-inserter-preview-height: 350px; -$block-inserter-width: 350px; +$block-quick-inserter-width: 350px; $block-inserter-tabs-height: 44px; .block-editor-inserter { @@ -24,6 +24,12 @@ $block-inserter-tabs-height: 44px; &.show-as-tabs { gap: 0; } + + .block-editor-tabbed-sidebar { + @include break-medium() { + width: $secondary-sidebar-width; + } + } } .block-editor-inserter__popover.is-quick { @@ -85,6 +91,12 @@ $block-inserter-tabs-height: 44px; height: 100%; position: relative; overflow: visible; + + &.show-panel { + @include break-medium() { + width: $secondary-sidebar-width + $sidebar-width; + } + } } .block-editor-inserter__inline-elements { @@ -299,14 +311,13 @@ $block-inserter-tabs-height: 44px; @include break-medium { border-left: $border-width solid $gray-200; padding: 0; - left: 100%; - width: 300px; + left: $secondary-sidebar-width; + width: $sidebar-width; position: absolute; top: -$border-width; height: calc(100% + #{$border-width}); background: $gray-100; border-top: $border-width solid $gray-200; - box-shadow: $border-width $border-width 0 0 rgba($color: #000, $alpha: 0.133); // 0.133 = $gray-200 but with alpha. .block-editor-inserter__media-list, .block-editor-block-patterns-list { @@ -366,7 +377,7 @@ $block-inserter-tabs-height: 44px; max-width: 100%; @include break-medium { - width: $block-inserter-width; + width: $block-quick-inserter-width; } } @@ -679,12 +690,6 @@ $block-inserter-tabs-height: 44px; height: 100%; } } - - // Remove doubled-up shadow that occurs when categories panel is opened, only in zoom out. - // Shadow cannot be removed from the source, as it is required when not zoomed out. - .block-editor-inserter__category-panel { - box-shadow: none; - } } .show-icon-labels { diff --git a/packages/block-editor/src/components/tabbed-sidebar/style.scss b/packages/block-editor/src/components/tabbed-sidebar/style.scss index e392cf955ed06c..374a012173e230 100644 --- a/packages/block-editor/src/components/tabbed-sidebar/style.scss +++ b/packages/block-editor/src/components/tabbed-sidebar/style.scss @@ -1,13 +1,10 @@ .block-editor-tabbed-sidebar { + background-color: $white; height: 100%; display: flex; flex-direction: column; flex-grow: 1; overflow: hidden; - - @include break-medium() { - width: 350px; - } } .block-editor-tabbed-sidebar__tablist-and-close-button { diff --git a/packages/editor/src/components/list-view-sidebar/style.scss b/packages/editor/src/components/list-view-sidebar/style.scss index 3bf56b2c80760c..54c7376d374853 100644 --- a/packages/editor/src/components/list-view-sidebar/style.scss +++ b/packages/editor/src/components/list-view-sidebar/style.scss @@ -1,5 +1,9 @@ .editor-list-view-sidebar { height: 100%; + + @include break-medium { + width: $secondary-sidebar-width; + } } .editor-list-view-sidebar__list-view-panel-content, diff --git a/packages/interface/src/components/interface-skeleton/index.js b/packages/interface/src/components/interface-skeleton/index.js index ed4d98cdf7637f..14b2a87ba5203d 100644 --- a/packages/interface/src/components/interface-skeleton/index.js +++ b/packages/interface/src/components/interface-skeleton/index.js @@ -182,30 +182,32 @@ function InterfaceSkeleton( ariaLabel={ mergedLabels.secondarySidebar } as={ motion.div } initial="closed" - animate={ - isMobileViewport ? 'mobileOpen' : 'open' - } + animate="open" exit="closed" variants={ { open: { width: secondarySidebarSize.width }, closed: { width: 0 }, - mobileOpen: { width: '100vw' }, } } transition={ defaultTransition } > - <div + <motion.div style={ { position: 'absolute', width: isMobileViewport ? '100vw' : 'fit-content', height: '100%', - right: 0, + left: 0, } } + variants={ { + open: { x: 0 }, + closed: { x: '-100%' }, + } } + transition={ defaultTransition } > { secondarySidebarResizeListener } { secondarySidebar } - </div> + </motion.div> </NavigableRegion> ) } </AnimatePresence> From 720633938315f1ca42948955ac5861fb9327d7fe Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Thu, 1 Aug 2024 00:01:17 +0100 Subject: [PATCH 0203/1908] Global Styles: Create new public function to make it easier to expose style variations from other themes (#63318) * Global Styles: Create new public function to make it easier to expose style variations from other themes * pass scope * fix PHPCS * remove disconnected changes Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> --- ...class-wp-theme-json-resolver-gutenberg.php | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php index a2153e639db3ba..2231cb0f11538f 100644 --- a/lib/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/class-wp-theme-json-resolver-gutenberg.php @@ -764,8 +764,18 @@ private static function style_variation_has_scope( $variation, $scope ) { * @return array */ public static function get_style_variations( $scope = 'theme' ) { + return static::get_style_variations_from_directory( get_stylesheet_directory(), $scope ); + } + + /** + * Returns the style variation files defined by the theme (parent and child). + * + * @since 6.7.0 + * + * @return array An array of style variation files. + */ + protected static function get_style_variation_files_from_current_theme() { $variation_files = array(); - $variations = array(); $base_directory = get_stylesheet_directory() . '/styles'; $template_directory = get_template_directory() . '/styles'; if ( is_dir( $base_directory ) ) { @@ -783,6 +793,29 @@ public static function get_style_variations( $scope = 'theme' ) { } $variation_files = array_merge( $variation_files, $variation_files_parent ); } + + return $variation_files; + } + + /** + * Returns the style variations in the given directory. + * + * @since 6.7.0 + * + * @param string $directory The directory to get the style variations from. + * @param string $scope The scope or type of style variation to retrieve e.g. theme, block etc. + * @return array + */ + public static function get_style_variations_from_directory( $directory, $scope = 'theme' ) { + $variation_files = array(); + $variations = array(); + if ( is_dir( $directory ) ) { + if ( get_stylesheet_directory() === $directory ) { + $variation_files = static::get_style_variation_files_from_current_theme(); + } else { + $variation_files = static::recursively_iterate_json( $directory ); + } + } ksort( $variation_files ); foreach ( $variation_files as $path => $file ) { $decoded_file = self::read_json_file( $path ); From ff59ffa756be03c5ad0647e91ee363d99f201312 Mon Sep 17 00:00:00 2001 From: Grant Kinney <creativecoder@users.noreply.github.com> Date: Wed, 31 Jul 2024 20:29:59 -0500 Subject: [PATCH 0204/1908] Adds experimental blocks flag for blocks that may not be ready for general use (#64121) --- lib/experimental/editor-settings.php | 18 +++++++++++++++++- lib/experiments-page.php | 12 ++++++++++++ phpunit/bootstrap.php | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index 065264fd124e8c..c34984baa0a619 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -43,12 +43,28 @@ function gutenberg_enable_experiments() { /** * Sets a global JS variable used to trigger the availability of form & input blocks. + * + * @deprecated 19.0.0 Use gutenberg_enable_block_experiments(). */ function gutenberg_enable_form_input_blocks() { + _deprecated_function( __FUNCTION__, 'Gutenberg 19.0.0', 'gutenberg_enable_block_experiments' ); +} + +/** + * Sets global JS variables used to enable various block experiments. + */ +function gutenberg_enable_block_experiments() { $gutenberg_experiments = get_option( 'gutenberg-experiments' ); + + // Experimental form blocks. if ( $gutenberg_experiments && array_key_exists( 'gutenberg-form-blocks', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableFormBlocks = true', 'before' ); } + + // General experimental blocks that are not in the default block library. + if ( $gutenberg_experiments && array_key_exists( 'gutenberg-block-experiments', $gutenberg_experiments ) ) { + wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableBlockExperiments = true', 'before' ); + } } -add_action( 'admin_init', 'gutenberg_enable_form_input_blocks' ); +add_action( 'admin_init', 'gutenberg_enable_block_experiments' ); diff --git a/lib/experiments-page.php b/lib/experiments-page.php index acb095b47fde30..b27f6fc2726a2a 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -79,6 +79,18 @@ function gutenberg_initialize_experiments_settings() { ) ); + add_settings_field( + 'gutenberg-block-experiments', + __( 'Experimental blocks', 'gutenberg' ), + 'gutenberg_display_experiment_field', + 'gutenberg-experiments', + 'gutenberg_experiments_section', + array( + 'label' => __( 'Enable experimental blocks.<p class="description">(Warning: these blocks may have significant changes during development that cause validation errors and display issues.)</p>', 'gutenberg' ), + 'id' => 'gutenberg-block-experiments', + ) + ); + add_settings_field( 'gutenberg-form-blocks', __( 'Form and input blocks ', 'gutenberg' ), diff --git a/phpunit/bootstrap.php b/phpunit/bootstrap.php index 295d02978f120f..55319a752b61e6 100644 --- a/phpunit/bootstrap.php +++ b/phpunit/bootstrap.php @@ -95,6 +95,7 @@ function fail_if_died( $message ) { 'gutenberg-widget-experiments' => '1', 'gutenberg-full-site-editing' => 1, 'gutenberg-form-blocks' => 1, + 'gutenberg-block-experiments' => 1, ), ); From 50e12e47b109330cc1cf12cfce01aef7b8697971 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 1 Aug 2024 13:55:51 +1000 Subject: [PATCH 0205/1908] Post: add a max length to the post password protected field (#64156) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: peterwilsoncc <peterwilsoncc@git.wordpress.org> --- packages/editor/src/components/post-status/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/editor/src/components/post-status/index.js b/packages/editor/src/components/post-status/index.js index d0b5ac93977330..ca89e40366b238 100644 --- a/packages/editor/src/components/post-status/index.js +++ b/packages/editor/src/components/post-status/index.js @@ -254,6 +254,7 @@ export default function PostStatus() { id={ passwordInputId } __next40pxDefaultSize __nextHasNoMarginBottom + maxLength={ 255 } /> </div> ) } From 30c6dfb3b872baf878dc0d8ce0f5b84d6ae6cd29 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 1 Aug 2024 08:42:50 +0400 Subject: [PATCH 0206/1908] Avoid errors for post types without a 'menu_icon' (#64015) Unlinked contributors: karan4official. Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../src/components/add-new-template/utils.js | 16 ++++++++++------ packages/editor/src/store/private-selectors.js | 5 ++++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/packages/edit-site/src/components/add-new-template/utils.js b/packages/edit-site/src/components/add-new-template/utils.js index 1e544aeaadfe1b..a2644ec4ad4da9 100644 --- a/packages/edit-site/src/components/add-new-template/utils.js +++ b/packages/edit-site/src/components/add-new-template/utils.js @@ -166,9 +166,11 @@ export function usePostTypeArchiveMenuItems() { // `icon` is the `menu_icon` property of a post type. We // only handle `dashicons` for now, even if the `menu_icon` // also supports urls and svg as values. - icon: postType.icon?.startsWith( 'dashicons-' ) - ? postType.icon.slice( 10 ) - : archive, + icon: + typeof postType.icon === 'string' && + postType.icon.startsWith( 'dashicons-' ) + ? postType.icon.slice( 10 ) + : archive, templatePrefix: 'archive', }; } ) || [], @@ -272,9 +274,11 @@ export const usePostTypeMenuItems = ( onClickMenuItem ) => { // `icon` is the `menu_icon` property of a post type. We // only handle `dashicons` for now, even if the `menu_icon` // also supports urls and svg as values. - icon: icon?.startsWith( 'dashicons-' ) - ? icon.slice( 10 ) - : post, + icon: + typeof icon === 'string' && + icon.startsWith( 'dashicons-' ) + ? icon.slice( 10 ) + : post, templatePrefix: templatePrefixes[ slug ], }; const hasEntities = postTypesInfo?.[ slug ]?.hasEntities; diff --git a/packages/editor/src/store/private-selectors.js b/packages/editor/src/store/private-selectors.js index ed4672bc435cdc..6a6c8702a02217 100644 --- a/packages/editor/src/store/private-selectors.js +++ b/packages/editor/src/store/private-selectors.js @@ -110,7 +110,10 @@ export const getPostIcon = createRegistrySelector( // `icon` is the `menu_icon` property of a post type. We // only handle `dashicons` for now, even if the `menu_icon` // also supports urls and svg as values. - if ( postTypeEntity?.icon?.startsWith( 'dashicons-' ) ) { + if ( + typeof postTypeEntity?.icon === 'string' && + postTypeEntity.icon.startsWith( 'dashicons-' ) + ) { return postTypeEntity.icon.slice( 10 ); } return pageIcon; From f6a9b02abaea0cdd10cb4101b6ae945dba4dd713 Mon Sep 17 00:00:00 2001 From: Carolina Nymark <myazalea@hotmail.com> Date: Thu, 1 Aug 2024 07:06:58 +0200 Subject: [PATCH 0207/1908] Post content: Add clearfix (#63690) Add a CSS clearfix to the post content block, to clear aligned (floated) blocks and prevent them from overflowing the content area. Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/block-library/src/post-content/block.json | 1 + packages/block-library/src/post-content/style.scss | 5 +++++ packages/block-library/src/style.scss | 1 + 3 files changed, 7 insertions(+) create mode 100644 packages/block-library/src/post-content/style.scss diff --git a/packages/block-library/src/post-content/block.json b/packages/block-library/src/post-content/block.json index 5ca3892f567a54..1b9de707cb3220 100644 --- a/packages/block-library/src/post-content/block.json +++ b/packages/block-library/src/post-content/block.json @@ -54,5 +54,6 @@ } } }, + "style": "wp-block-post-content", "editorStyle": "wp-block-post-content-editor" } diff --git a/packages/block-library/src/post-content/style.scss b/packages/block-library/src/post-content/style.scss new file mode 100644 index 00000000000000..96e27d04679d44 --- /dev/null +++ b/packages/block-library/src/post-content/style.scss @@ -0,0 +1,5 @@ +.wp-block-post-content::after { + content: ""; + display: table; + clear: both; +} diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index db9d033d915db8..8f17cd7a50f55c 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -30,6 +30,7 @@ @import "./paragraph/style.scss"; @import "./post-author/style.scss"; @import "./post-comments-form/style.scss"; +@import "./post-content/style.scss"; @import "./post-date/style.scss"; @import "./post-excerpt/style.scss"; @import "./post-featured-image/style.scss"; From ecfc7efaa3fccc4b6466543c50ac262ce8093934 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 1 Aug 2024 09:53:33 +0400 Subject: [PATCH 0208/1908] Template Part: Fix capability checks for inner blocks (#64159) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> --- .../src/template-part/edit/inner-blocks.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/block-library/src/template-part/edit/inner-blocks.js b/packages/block-library/src/template-part/edit/inner-blocks.js index ef7d85948626dd..2c246809ab2d49 100644 --- a/packages/block-library/src/template-part/edit/inner-blocks.js +++ b/packages/block-library/src/template-part/edit/inner-blocks.js @@ -129,15 +129,17 @@ export default function TemplatePartInnerBlocks( { return { canViewTemplatePart: !! select( coreStore ).canUser( 'read', { kind: 'postType', - name: 'wp_template', + name: 'wp_template_part', + id, } ), - canEditTemplatePart: !! select( coreStore ).canUser( 'create', { + canEditTemplatePart: !! select( coreStore ).canUser( 'update', { kind: 'postType', - name: 'wp_template', + name: 'wp_template_part', + id, } ), }; }, - [] + [ id ] ); if ( ! canViewTemplatePart ) { From 644264cbcee25b34dd00c6ee8ba65097462e0ef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:08:20 +0200 Subject: [PATCH 0209/1908] DataViews: sort author by name in Pages + allow custom sort function (#64064) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../components/dataviews/stories/fixtures.js | 17 ++++++++++++ packages/dataviews/src/field-types/index.tsx | 22 ++++++++++++++++ .../dataviews/src/field-types/integer.tsx | 12 +++++++++ .../src/filter-and-sort-data-view.ts | 9 +++++++ packages/dataviews/src/normalize-fields.ts | 14 ++++++++++ .../src/test/filter-and-sort-data-view.js | 15 +++++++++++ packages/dataviews/src/types.ts | 6 +++++ .../src/components/post-fields/index.js | 8 ++++++ .../src/components/post-list/index.js | 26 ++++++++++++++----- 9 files changed, 123 insertions(+), 6 deletions(-) create mode 100644 packages/dataviews/src/field-types/index.tsx create mode 100644 packages/dataviews/src/field-types/integer.tsx diff --git a/packages/dataviews/src/components/dataviews/stories/fixtures.js b/packages/dataviews/src/components/dataviews/stories/fixtures.js index 01351b84848fc1..7e084d6a017ad2 100644 --- a/packages/dataviews/src/components/dataviews/stories/fixtures.js +++ b/packages/dataviews/src/components/dataviews/stories/fixtures.js @@ -23,6 +23,7 @@ export const data = [ type: 'Not a planet', categories: [ 'Space', 'NASA' ], satellites: 0, + satellites_no_type: 0, }, { id: 2, @@ -32,6 +33,7 @@ export const data = [ type: 'Not a planet', categories: [ 'Space' ], satellites: 0, + satellites_no_type: 0, }, { id: 3, @@ -41,6 +43,7 @@ export const data = [ type: 'Not a planet', categories: [ 'NASA' ], satellites: 0, + satellites_no_type: 0, }, { id: 4, @@ -50,6 +53,7 @@ export const data = [ type: 'Ice giant', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 14, + satellites_no_type: 14, }, { id: 5, @@ -59,6 +63,7 @@ export const data = [ type: 'Terrestrial', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 0, + satellites_no_type: 0, }, { id: 6, @@ -68,6 +73,7 @@ export const data = [ type: 'Terrestrial', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 0, + satellites_no_type: 0, }, { id: 7, @@ -77,6 +83,7 @@ export const data = [ type: 'Terrestrial', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 1, + satellites_no_type: 1, }, { id: 8, @@ -86,6 +93,7 @@ export const data = [ type: 'Terrestrial', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 2, + satellites_no_type: 2, }, { id: 9, @@ -95,6 +103,7 @@ export const data = [ type: 'Gas giant', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 95, + satellites_no_type: 95, }, { id: 10, @@ -104,6 +113,7 @@ export const data = [ type: 'Gas giant', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 146, + satellites_no_type: 146, }, { id: 11, @@ -113,6 +123,7 @@ export const data = [ type: 'Ice giant', categories: [ 'Space', 'Ice giant', 'Solar system' ], satellites: 28, + satellites_no_type: 28, }, ]; @@ -189,6 +200,12 @@ export const fields = [ { label: 'Satellites', id: 'satellites', + type: 'integer', + enableSorting: true, + }, + { + label: 'Satellites (no type)', + id: 'satellites_no_type', enableSorting: true, }, { diff --git a/packages/dataviews/src/field-types/index.tsx b/packages/dataviews/src/field-types/index.tsx new file mode 100644 index 00000000000000..1ca5a12bd23de0 --- /dev/null +++ b/packages/dataviews/src/field-types/index.tsx @@ -0,0 +1,22 @@ +/** + * Internal dependencies + */ +import { default as integer } from './integer'; +import type { FieldType } from '../types'; + +/** + * + * @param {FieldType} type The field type definition to get. + * + * @return A field type definition. + */ +export default function getFieldTypeDefinition( type?: FieldType ) { + if ( 'integer' === type ) { + return integer; + } + + // If no type found, the sort function doesn't do anything. + return { + sort: () => 0, + }; +} diff --git a/packages/dataviews/src/field-types/integer.tsx b/packages/dataviews/src/field-types/integer.tsx new file mode 100644 index 00000000000000..36d0b445d6275f --- /dev/null +++ b/packages/dataviews/src/field-types/integer.tsx @@ -0,0 +1,12 @@ +/** + * Internal dependencies + */ +import type { SortDirection } from '../types'; + +function sort( a: any, b: any, direction: SortDirection ) { + return direction === 'asc' ? a - b : b - a; +} + +export default { + sort, +}; diff --git a/packages/dataviews/src/filter-and-sort-data-view.ts b/packages/dataviews/src/filter-and-sort-data-view.ts index 000ec110f7d0db..b716b499e4a0f4 100644 --- a/packages/dataviews/src/filter-and-sort-data-view.ts +++ b/packages/dataviews/src/filter-and-sort-data-view.ts @@ -143,6 +143,15 @@ export function filterSortAndPaginate< Item >( const valueA = fieldToSort.getValue( { item: a } ) ?? ''; const valueB = fieldToSort.getValue( { item: b } ) ?? ''; + if ( fieldToSort.type === 'integer' ) { + return fieldToSort.sort( + a, + b, + view.sort?.direction ?? 'desc' + ); + } + + // When/if types become required, we can remove the following logic. if ( typeof valueA === 'number' && typeof valueB === 'number' diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index b7407dfe522fb6..6cb36de1029005 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -1,6 +1,7 @@ /** * Internal dependencies */ +import getFieldTypeDefinition from './field-types'; import type { Field, NormalizedField, ItemRecord } from './types'; /** @@ -13,15 +14,28 @@ export function normalizeFields< Item >( fields: Field< Item >[] ): NormalizedField< Item >[] { return fields.map( ( field ) => { + const fieldTypeDefinition = getFieldTypeDefinition( field.type ); + const getValue = field.getValue || ( ( { item }: { item: ItemRecord } ) => item[ field.id ] ); + const sort = + field.sort ?? + function sort( a, b, direction ) { + return fieldTypeDefinition.sort( + getValue( { item: a } ), + getValue( { item: b } ), + direction + ); + }; + return { ...field, label: field.label || field.id, getValue, render: field.render || getValue, + sort, }; } ); } diff --git a/packages/dataviews/src/test/filter-and-sort-data-view.js b/packages/dataviews/src/test/filter-and-sort-data-view.js index 5083648e46ebb3..8945f29e813744 100644 --- a/packages/dataviews/src/test/filter-and-sort-data-view.js +++ b/packages/dataviews/src/test/filter-and-sort-data-view.js @@ -254,6 +254,21 @@ describe( 'sorting', () => { } ); it( 'should sort by number', () => { + const { data: result } = filterSortAndPaginate( + data, + { + sort: { field: 'satellites_no_type', direction: 'desc' }, + }, + fields + ); + + expect( result ).toHaveLength( 11 ); + expect( result[ 0 ].title ).toBe( 'Saturn' ); + expect( result[ 1 ].title ).toBe( 'Jupiter' ); + expect( result[ 2 ].title ).toBe( 'Uranus' ); + } ); + + it( 'should sort by type integer', () => { const { data: result } = filterSortAndPaginate( data, { diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 37c3efbde5cfb0..f410c18aa43699 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -80,6 +80,11 @@ export type Field< Item > = { */ render?: ComponentType< { item: Item } >; + /** + * Callback used to sort the field. + */ + sort?: ( a: Item, b: Item, direction: SortDirection ) => number; + /** * Whether the field is sortable. */ @@ -124,6 +129,7 @@ export type NormalizedField< Item > = Field< Item > & { label: string; getValue: ( args: { item: Item } ) => any; render: ComponentType< { item: Item } >; + sort: ( a: Item, b: Item, direction: SortDirection ) => number; }; /** diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index ebd228dcf63aa0..dcca7d49ab708b 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -242,6 +242,14 @@ function usePostFields( viewType ) { label: name, } ) ) || [], render: PostAuthorField, + sort: ( a, b, direction ) => { + const nameA = a._embedded?.author?.[ 0 ]?.name || ''; + const nameB = b._embedded?.author?.[ 0 ]?.name || ''; + + return direction === 'asc' + ? nameA.localeCompare( nameB ) + : nameB.localeCompare( nameA ); + }, }, { label: __( 'Status' ), diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 68b8461929eb1d..2724abcff714f7 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -9,7 +9,7 @@ import { import { useState, useMemo, useCallback, useEffect } from '@wordpress/element'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { useSelect, useDispatch } from '@wordpress/data'; -import { DataViews } from '@wordpress/dataviews'; +import { DataViews, filterSortAndPaginate } from '@wordpress/dataviews'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { __ } from '@wordpress/i18n'; import { drawerRight } from '@wordpress/icons'; @@ -161,6 +161,8 @@ export default function PostList( { postType } ) { [ history ] ); + const { isLoading: isLoadingFields, fields } = usePostFields( view.type ); + const queryArgs = useMemo( () => { const filters = {}; view.filters.forEach( ( filter ) => { @@ -200,12 +202,25 @@ export default function PostList( { postType } ) { }, [ view ] ); const { records, - isResolving: isLoadingMainEntities, + isResolving: isLoadingData, totalItems, totalPages, } = useEntityRecordsWithPermissions( 'postType', postType, queryArgs ); - const ids = records?.map( ( record ) => getItemId( record ) ) ?? []; + // The REST API sort the authors by ID, but we want to sort them by name. + const data = useMemo( () => { + if ( ! isLoadingFields && view?.sort?.field === 'author' ) { + return filterSortAndPaginate( + records, + { sort: { ...view.sort } }, + fields + ).data; + } + + return records; + }, [ records, fields, isLoadingFields, view?.sort ] ); + + const ids = data?.map( ( record ) => getItemId( record ) ) ?? []; const prevIds = usePrevious( ids ) ?? []; const deletedIds = prevIds.filter( ( id ) => ! ids.includes( id ) ); const postIdWasDeleted = deletedIds.includes( postId ); @@ -263,7 +278,6 @@ export default function PostList( { postType } ) { } ); closeModal(); }; - const { isLoading: isLoadingFields, fields } = usePostFields( view.type ); return ( <Page @@ -294,8 +308,8 @@ export default function PostList( { postType } ) { paginationInfo={ paginationInfo } fields={ fields } actions={ actions } - data={ records || EMPTY_ARRAY } - isLoading={ isLoadingMainEntities || isLoadingFields } + data={ data || EMPTY_ARRAY } + isLoading={ isLoadingData || isLoadingFields } view={ view } onChangeView={ setView } selection={ selection } From c04a6f4446feb41ac2b55b262e10368fec6604b0 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:38:32 +0200 Subject: [PATCH 0210/1908] Update: chevron to home icon. (#64161) --- .../edit-site/src/components/editor/index.js | 4 ++-- packages/icons/src/index.js | 1 + packages/icons/src/library/home-button.js | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 packages/icons/src/library/home-button.js diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index d0c63a9db5cad6..96de3c60b89144 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -22,7 +22,7 @@ import { store as noticesStore } from '@wordpress/notices'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { store as preferencesStore } from '@wordpress/preferences'; import { decodeEntities } from '@wordpress/html-entities'; -import { Icon, chevronLeft } from '@wordpress/icons'; +import { Icon, homeButton } from '@wordpress/icons'; /** * Internal dependencies @@ -292,7 +292,7 @@ export default function EditSiteEditor( { isPostsList = false } ) { ) } variants={ toggleHomeIconVariants } > - <Icon icon={ chevronLeft } /> + <Icon icon={ homeButton } /> </motion.div> </motion.div> ) diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index c5d5976dd2d5f7..faa193eb7b461d 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -117,6 +117,7 @@ export { default as helpFilled } from './library/help-filled'; export { default as inbox } from './library/inbox'; export { default as institution } from './library/institution'; export { default as home } from './library/home'; +export { default as homeButton } from './library/home-button'; export { default as html } from './library/html'; export { default as image } from './library/image'; export { default as info } from './library/info'; diff --git a/packages/icons/src/library/home-button.js b/packages/icons/src/library/home-button.js new file mode 100644 index 00000000000000..5a1b26d3416f2a --- /dev/null +++ b/packages/icons/src/library/home-button.js @@ -0,0 +1,16 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const homeButton = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path + fill-rule="evenodd" + clip-rule="evenodd" + d="M4.25 7A2.75 2.75 0 0 1 7 4.25h10A2.75 2.75 0 0 1 19.75 7v10A2.75 2.75 0 0 1 17 19.75H7A2.75 2.75 0 0 1 4.25 17V7ZM7 5.75c-.69 0-1.25.56-1.25 1.25v10c0 .69.56 1.25 1.25 1.25h10c.69 0 1.25-.56 1.25-1.25V7c0-.69-.56-1.25-1.25-1.25H7Z" + /> + </SVG> +); + +export default homeButton; From 1c3e7bedddb02d64d40186e60f67f94e34175b35 Mon Sep 17 00:00:00 2001 From: Sarah Norris <1645628+mikachan@users.noreply.github.com> Date: Thu, 1 Aug 2024 09:40:01 +0100 Subject: [PATCH 0211/1908] TypesetButton: Check if variations exist before running logic (#64139) * Check if variations exists before running find * Add allFontFamilies to deps array Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> --- .../edit-site/src/components/global-styles/typeset-button.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/typeset-button.js b/packages/edit-site/src/components/global-styles/typeset-button.js index d66310f2ed8ff5..81955627526595 100644 --- a/packages/edit-site/src/components/global-styles/typeset-button.js +++ b/packages/edit-site/src/components/global-styles/typeset-button.js @@ -49,7 +49,7 @@ function TypesetButton() { if ( Object.keys( userTypographyConfig ).length === 0 ) { return __( 'Default' ); } - const activeVariation = variations.find( ( variation ) => { + const activeVariation = variations?.find( ( variation ) => { return ( JSON.stringify( filterObjectByProperties( variation, 'typography' ) @@ -60,7 +60,7 @@ function TypesetButton() { return activeVariation.title; } return allFontFamilies.map( ( font ) => font?.name ).join( ', ' ); - }, [ userTypographyConfig, variations ] ); + }, [ allFontFamilies, userTypographyConfig, variations ] ); return ( hasFonts && ( From a47a25defec095ac04e13154d575005b0225fbba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Thu, 1 Aug 2024 12:24:02 +0200 Subject: [PATCH 0212/1908] DataForm: move validation logic to the field type definition (#64164) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/dataviews/src/field-types/index.tsx | 13 +++++-- .../dataviews/src/field-types/integer.tsx | 23 +++++++++++- packages/dataviews/src/normalize-fields.ts | 10 ++++++ packages/dataviews/src/test/validation.ts | 36 ++++++++++++++++++- packages/dataviews/src/types.ts | 10 ++++++ packages/dataviews/src/validation.ts | 24 +------------ 6 files changed, 89 insertions(+), 27 deletions(-) diff --git a/packages/dataviews/src/field-types/index.tsx b/packages/dataviews/src/field-types/index.tsx index 1ca5a12bd23de0..1075858c6e0669 100644 --- a/packages/dataviews/src/field-types/index.tsx +++ b/packages/dataviews/src/field-types/index.tsx @@ -2,7 +2,7 @@ * Internal dependencies */ import { default as integer } from './integer'; -import type { FieldType } from '../types'; +import type { FieldType, ValidationContext } from '../types'; /** * @@ -15,8 +15,17 @@ export default function getFieldTypeDefinition( type?: FieldType ) { return integer; } - // If no type found, the sort function doesn't do anything. return { sort: () => 0, + isValid: ( value: any, context?: ValidationContext ) => { + if ( context?.elements ) { + const validValues = context?.elements?.map( ( f ) => f.value ); + if ( ! validValues.includes( value ) ) { + return false; + } + } + + return true; + }, }; } diff --git a/packages/dataviews/src/field-types/integer.tsx b/packages/dataviews/src/field-types/integer.tsx index 36d0b445d6275f..eaa90e8f1e4e26 100644 --- a/packages/dataviews/src/field-types/integer.tsx +++ b/packages/dataviews/src/field-types/integer.tsx @@ -1,12 +1,33 @@ /** * Internal dependencies */ -import type { SortDirection } from '../types'; +import type { SortDirection, ValidationContext } from '../types'; function sort( a: any, b: any, direction: SortDirection ) { return direction === 'asc' ? a - b : b - a; } +function isValid( value: any, context?: ValidationContext ) { + // TODO: this implicitely means the value is required. + if ( value === '' ) { + return false; + } + + if ( ! Number.isInteger( Number( value ) ) ) { + return false; + } + + if ( context?.elements ) { + const validValues = context?.elements.map( ( f ) => f.value ); + if ( ! validValues.includes( Number( value ) ) ) { + return false; + } + } + + return true; +} + export default { sort, + isValid, }; diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index 6cb36de1029005..8d08b08715c9a3 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -30,12 +30,22 @@ export function normalizeFields< Item >( ); }; + const isValid = + field.isValid ?? + function isValid( item, context ) { + return fieldTypeDefinition.isValid( + getValue( { item } ), + context + ); + }; + return { ...field, label: field.label || field.id, getValue, render: field.render || getValue, sort, + isValid, }; } ); } diff --git a/packages/dataviews/src/test/validation.ts b/packages/dataviews/src/test/validation.ts index ded002e5bc042e..4f3fb2c922433e 100644 --- a/packages/dataviews/src/test/validation.ts +++ b/packages/dataviews/src/test/validation.ts @@ -61,7 +61,7 @@ describe( 'validation', () => { expect( result ).toBe( false ); } ); - it( 'field is invalid if value is not one of the elements', () => { + it( 'integer field is invalid if value is not one of the elements', () => { const item = { id: 1, author: 3 }; const fields: Field< {} >[] = [ { @@ -77,4 +77,38 @@ describe( 'validation', () => { const result = isItemValid( item, fields, form ); expect( result ).toBe( false ); } ); + + it( 'untyped field is invalid if value is not one of the elements', () => { + const item = { id: 1, author: 'not-in-elements' }; + const fields: Field< {} >[] = [ + { + id: 'author', + elements: [ + { value: 'jane', label: 'Jane' }, + { value: 'john', label: 'John' }, + ], + }, + ]; + const form = { visibleFields: [ 'author' ] }; + const result = isItemValid( item, fields, form ); + expect( result ).toBe( false ); + } ); + + it( 'fields can provide its own isValid function', () => { + const item = { id: 1, order: 'd' }; + const fields: Field< {} >[] = [ + { + id: 'order', + type: 'integer', + elements: [ + { value: 'a', label: 'A' }, + { value: 'b', label: 'B' }, + ], + isValid: () => true, // Overrides the validation provided for integer types. + }, + ]; + const form = { visibleFields: [ 'order' ] }; + const result = isItemValid( item, fields, form ); + expect( result ).toBe( true ); + } ); } ); diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index f410c18aa43699..7029db7d17b1af 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -46,6 +46,10 @@ export type ItemRecord = Record< string, unknown >; export type FieldType = 'text' | 'integer'; +export type ValidationContext = { + elements?: Option[]; +}; + /** * A dataview field for a specific property of a data type. */ @@ -85,6 +89,11 @@ export type Field< Item > = { */ sort?: ( a: Item, b: Item, direction: SortDirection ) => number; + /** + * Callback used to validate the field. + */ + isValid?: ( item: Item, context?: ValidationContext ) => boolean; + /** * Whether the field is sortable. */ @@ -130,6 +139,7 @@ export type NormalizedField< Item > = Field< Item > & { getValue: ( args: { item: Item } ) => any; render: ComponentType< { item: Item } >; sort: ( a: Item, b: Item, direction: SortDirection ) => number; + isValid: ( item: Item, context?: ValidationContext ) => boolean; }; /** diff --git a/packages/dataviews/src/validation.ts b/packages/dataviews/src/validation.ts index a6d3515fe6e57e..e350be68d54219 100644 --- a/packages/dataviews/src/validation.ts +++ b/packages/dataviews/src/validation.ts @@ -13,28 +13,6 @@ export function isItemValid< Item >( fields.filter( ( { id } ) => !! form.visibleFields?.includes( id ) ) ); return _fields.every( ( field ) => { - const value = field.getValue( { item } ); - - // TODO: this implicitely means the value is required. - if ( field.type === 'integer' && value === '' ) { - return false; - } - - if ( - field.type === 'integer' && - ! Number.isInteger( Number( value ) ) - ) { - return false; - } - - if ( field.elements ) { - const validValues = field.elements.map( ( f ) => f.value ); - if ( ! validValues.includes( Number( value ) ) ) { - return false; - } - } - - // Nothing to validate. - return true; + return field.isValid( item, { elements: field.elements } ); } ); } From 3621ab3b8ea556a4af367ba2b5e91e748b36791e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Thu, 1 Aug 2024 13:47:46 +0200 Subject: [PATCH 0213/1908] DataViews: formalize text field type definition (#64168) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../components/dataviews/stories/fixtures.js | 16 ------ packages/dataviews/src/field-types/index.tsx | 17 +++++- packages/dataviews/src/field-types/text.tsx | 26 ++++++++++ .../src/filter-and-sort-data-view.ts | 25 +-------- .../src/test/filter-and-sort-data-view.js | 52 ++++++++++++++----- packages/dataviews/src/test/validation.ts | 17 ++++++ 6 files changed, 99 insertions(+), 54 deletions(-) create mode 100644 packages/dataviews/src/field-types/text.tsx diff --git a/packages/dataviews/src/components/dataviews/stories/fixtures.js b/packages/dataviews/src/components/dataviews/stories/fixtures.js index 7e084d6a017ad2..536c5e66e6ce97 100644 --- a/packages/dataviews/src/components/dataviews/stories/fixtures.js +++ b/packages/dataviews/src/components/dataviews/stories/fixtures.js @@ -23,7 +23,6 @@ export const data = [ type: 'Not a planet', categories: [ 'Space', 'NASA' ], satellites: 0, - satellites_no_type: 0, }, { id: 2, @@ -33,7 +32,6 @@ export const data = [ type: 'Not a planet', categories: [ 'Space' ], satellites: 0, - satellites_no_type: 0, }, { id: 3, @@ -43,7 +41,6 @@ export const data = [ type: 'Not a planet', categories: [ 'NASA' ], satellites: 0, - satellites_no_type: 0, }, { id: 4, @@ -53,7 +50,6 @@ export const data = [ type: 'Ice giant', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 14, - satellites_no_type: 14, }, { id: 5, @@ -63,7 +59,6 @@ export const data = [ type: 'Terrestrial', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 0, - satellites_no_type: 0, }, { id: 6, @@ -73,7 +68,6 @@ export const data = [ type: 'Terrestrial', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 0, - satellites_no_type: 0, }, { id: 7, @@ -83,7 +77,6 @@ export const data = [ type: 'Terrestrial', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 1, - satellites_no_type: 1, }, { id: 8, @@ -93,7 +86,6 @@ export const data = [ type: 'Terrestrial', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 2, - satellites_no_type: 2, }, { id: 9, @@ -103,7 +95,6 @@ export const data = [ type: 'Gas giant', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 95, - satellites_no_type: 95, }, { id: 10, @@ -113,7 +104,6 @@ export const data = [ type: 'Gas giant', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 146, - satellites_no_type: 146, }, { id: 11, @@ -123,7 +113,6 @@ export const data = [ type: 'Ice giant', categories: [ 'Space', 'Ice giant', 'Solar system' ], satellites: 28, - satellites_no_type: 28, }, ]; @@ -203,11 +192,6 @@ export const fields = [ type: 'integer', enableSorting: true, }, - { - label: 'Satellites (no type)', - id: 'satellites_no_type', - enableSorting: true, - }, { label: 'Description', id: 'description', diff --git a/packages/dataviews/src/field-types/index.tsx b/packages/dataviews/src/field-types/index.tsx index 1075858c6e0669..9d81d210f5d5d7 100644 --- a/packages/dataviews/src/field-types/index.tsx +++ b/packages/dataviews/src/field-types/index.tsx @@ -1,8 +1,9 @@ /** * Internal dependencies */ +import type { FieldType, SortDirection, ValidationContext } from '../types'; import { default as integer } from './integer'; -import type { FieldType, ValidationContext } from '../types'; +import { default as text } from './text'; /** * @@ -15,8 +16,20 @@ export default function getFieldTypeDefinition( type?: FieldType ) { return integer; } + if ( 'text' === type ) { + return text; + } + return { - sort: () => 0, + sort: ( a: any, b: any, direction: SortDirection ) => { + if ( typeof a === 'number' && typeof b === 'number' ) { + return direction === 'asc' ? a - b : b - a; + } + + return direction === 'asc' + ? a.localeCompare( b ) + : b.localeCompare( a ); + }, isValid: ( value: any, context?: ValidationContext ) => { if ( context?.elements ) { const validValues = context?.elements?.map( ( f ) => f.value ); diff --git a/packages/dataviews/src/field-types/text.tsx b/packages/dataviews/src/field-types/text.tsx new file mode 100644 index 00000000000000..5138fe0e397d37 --- /dev/null +++ b/packages/dataviews/src/field-types/text.tsx @@ -0,0 +1,26 @@ +/** + * Internal dependencies + */ +import type { SortDirection, ValidationContext } from '../types'; + +function sort( valueA: any, valueB: any, direction: SortDirection ) { + return direction === 'asc' + ? valueA.localeCompare( valueB ) + : valueB.localeCompare( valueA ); +} + +function isValid( value: any, context?: ValidationContext ) { + if ( context?.elements ) { + const validValues = context?.elements?.map( ( f ) => f.value ); + if ( ! validValues.includes( value ) ) { + return false; + } + } + + return true; +} + +export default { + sort, + isValid, +}; diff --git a/packages/dataviews/src/filter-and-sort-data-view.ts b/packages/dataviews/src/filter-and-sort-data-view.ts index b716b499e4a0f4..da2e9915d515ba 100644 --- a/packages/dataviews/src/filter-and-sort-data-view.ts +++ b/packages/dataviews/src/filter-and-sort-data-view.ts @@ -140,30 +140,7 @@ export function filterSortAndPaginate< Item >( } ); if ( fieldToSort ) { filteredData.sort( ( a, b ) => { - const valueA = fieldToSort.getValue( { item: a } ) ?? ''; - const valueB = fieldToSort.getValue( { item: b } ) ?? ''; - - if ( fieldToSort.type === 'integer' ) { - return fieldToSort.sort( - a, - b, - view.sort?.direction ?? 'desc' - ); - } - - // When/if types become required, we can remove the following logic. - if ( - typeof valueA === 'number' && - typeof valueB === 'number' - ) { - return view.sort?.direction === 'asc' - ? valueA - valueB - : valueB - valueA; - } - - return view.sort?.direction === 'asc' - ? valueA.localeCompare( valueB ) - : valueB.localeCompare( valueA ); + return fieldToSort.sort( a, b, view.sort?.direction ?? 'desc' ); } ); } } diff --git a/packages/dataviews/src/test/filter-and-sort-data-view.js b/packages/dataviews/src/test/filter-and-sort-data-view.js index 8945f29e813744..7538b975a30992 100644 --- a/packages/dataviews/src/test/filter-and-sort-data-view.js +++ b/packages/dataviews/src/test/filter-and-sort-data-view.js @@ -233,7 +233,22 @@ describe( 'filters', () => { } ); describe( 'sorting', () => { - it( 'should sort by string', () => { + it( 'should sort integer field types', () => { + const { data: result } = filterSortAndPaginate( + data, + { + sort: { field: 'satellites', direction: 'desc' }, + }, + fields + ); + + expect( result ).toHaveLength( 11 ); + expect( result[ 0 ].title ).toBe( 'Saturn' ); + expect( result[ 1 ].title ).toBe( 'Jupiter' ); + expect( result[ 2 ].title ).toBe( 'Uranus' ); + } ); + + it( 'should sort text field types', () => { const { data: result } = filterSortAndPaginate( data, { @@ -253,13 +268,18 @@ describe( 'sorting', () => { expect( result[ 1 ].title ).toBe( 'Neptune' ); } ); - it( 'should sort by number', () => { + it( 'should sort untyped fields if the value is a number', () => { const { data: result } = filterSortAndPaginate( data, { - sort: { field: 'satellites_no_type', direction: 'desc' }, + sort: { field: 'satellites', direction: 'desc' }, }, - fields + // Remove type information for satellites field to test sorting untyped fields. + fields.map( ( field ) => + field.id === 'satellites' + ? { ...field, type: undefined } + : field + ) ); expect( result ).toHaveLength( 11 ); @@ -268,19 +288,27 @@ describe( 'sorting', () => { expect( result[ 2 ].title ).toBe( 'Uranus' ); } ); - it( 'should sort by type integer', () => { + it( 'should sort untyped fields if the value is string', () => { const { data: result } = filterSortAndPaginate( data, { - sort: { field: 'satellites', direction: 'desc' }, + sort: { field: 'title', direction: 'desc' }, + filters: [ + { + field: 'type', + operator: 'isAny', + value: [ 'Ice giant' ], + }, + ], }, - fields + // Remove type information for the title field to test sorting untyped fields. + fields.map( ( field ) => + field.id === 'title' ? { ...field, type: undefined } : field + ) ); - - expect( result ).toHaveLength( 11 ); - expect( result[ 0 ].title ).toBe( 'Saturn' ); - expect( result[ 1 ].title ).toBe( 'Jupiter' ); - expect( result[ 2 ].title ).toBe( 'Uranus' ); + expect( result ).toHaveLength( 2 ); + expect( result[ 0 ].title ).toBe( 'Uranus' ); + expect( result[ 1 ].title ).toBe( 'Neptune' ); } ); } ); diff --git a/packages/dataviews/src/test/validation.ts b/packages/dataviews/src/test/validation.ts index 4f3fb2c922433e..4e52ca47353f78 100644 --- a/packages/dataviews/src/test/validation.ts +++ b/packages/dataviews/src/test/validation.ts @@ -78,6 +78,23 @@ describe( 'validation', () => { expect( result ).toBe( false ); } ); + it( 'text field is invalid if value is not one of the elements', () => { + const item = { id: 1, author: 'not-in-elements' }; + const fields: Field< {} >[] = [ + { + id: 'author', + type: 'text', + elements: [ + { value: 'jane', label: 'Jane' }, + { value: 'john', label: 'John' }, + ], + }, + ]; + const form = { visibleFields: [ 'author' ] }; + const result = isItemValid( item, fields, form ); + expect( result ).toBe( false ); + } ); + it( 'untyped field is invalid if value is not one of the elements', () => { const item = { id: 1, author: 'not-in-elements' }; const fields: Field< {} >[] = [ From eab064390369807b65be0cdcddeb24f3b3a41959 Mon Sep 17 00:00:00 2001 From: Ryan Welcher <me@ryanwelcher.com> Date: Thu, 1 Aug 2024 08:51:16 -0400 Subject: [PATCH 0214/1908] Update useTaxonomies hook to check for taxonomies for passed post type (#64145) Co-authored-by: ryanwelcher <welcher@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-library/src/query/utils.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/block-library/src/query/utils.js b/packages/block-library/src/query/utils.js index 73af87f684e2a4..2e9412b1683cb0 100644 --- a/packages/block-library/src/query/utils.js +++ b/packages/block-library/src/query/utils.js @@ -136,11 +136,15 @@ export const usePostTypes = () => { export const useTaxonomies = ( postType ) => { const taxonomies = useSelect( ( select ) => { - const { getTaxonomies } = select( coreStore ); - return getTaxonomies( { - type: postType, - per_page: -1, - } ); + const { getTaxonomies, getPostType } = select( coreStore ); + // Does the post type have taxonomies? + if ( getPostType( postType )?.taxonomies?.length > 0 ) { + return getTaxonomies( { + type: postType, + per_page: -1, + } ); + } + return []; }, [ postType ] ); From 58166dbfb0c9ec8563dadff6fc382940849ae308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:20:18 +0200 Subject: [PATCH 0215/1908] DataForm: centralize edit logic in field type definitions (#64171) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../src/components/dataform/index.tsx | 122 +----------------- packages/dataviews/src/field-types/index.tsx | 1 + .../dataviews/src/field-types/integer.tsx | 67 +++++++++- packages/dataviews/src/field-types/text.tsx | 41 +++++- packages/dataviews/src/normalize-fields.ts | 3 + packages/dataviews/src/types.ts | 19 ++- 6 files changed, 133 insertions(+), 120 deletions(-) diff --git a/packages/dataviews/src/components/dataform/index.tsx b/packages/dataviews/src/components/dataform/index.tsx index bd38dca472af0e..a247601e739b29 100644 --- a/packages/dataviews/src/components/dataform/index.tsx +++ b/packages/dataviews/src/components/dataform/index.tsx @@ -6,19 +6,13 @@ import type { Dispatch, SetStateAction } from 'react'; /** * WordPress dependencies */ -import { - TextControl, - __experimentalNumberControl as NumberControl, - SelectControl, -} from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import { useCallback, useMemo } from '@wordpress/element'; +import { useMemo } from '@wordpress/element'; /** * Internal dependencies */ -import type { Form, Field, NormalizedField, FieldType } from '../../types'; import { normalizeFields } from '../../normalize-fields'; +import type { Field, Form } from '../../types'; type DataFormProps< Item > = { data: Item; @@ -27,111 +21,6 @@ type DataFormProps< Item > = { onChange: Dispatch< SetStateAction< Item > >; }; -type DataFormControlProps< Item > = { - data: Item; - field: NormalizedField< Item >; - onChange: Dispatch< SetStateAction< Item > >; -}; - -function DataFormTextControl< Item >( { - data, - field, - onChange, -}: DataFormControlProps< Item > ) { - const { id, label, placeholder } = field; - const value = field.getValue( { item: data } ); - - const onChangeControl = useCallback( - ( newValue: string ) => - onChange( ( prevItem: Item ) => ( { - ...prevItem, - [ id ]: newValue, - } ) ), - [ id, onChange ] - ); - - return ( - <TextControl - label={ label } - placeholder={ placeholder } - value={ value ?? '' } - onChange={ onChangeControl } - __next40pxDefaultSize - /> - ); -} - -function DataFormNumberControl< Item >( { - data, - field, - onChange, -}: DataFormControlProps< Item > ) { - const { id, label, description } = field; - const value = field.getValue( { item: data } ) ?? ''; - const onChangeControl = useCallback( - ( newValue: string | undefined ) => - onChange( ( prevItem: Item ) => ( { - ...prevItem, - [ id ]: newValue, - } ) ), - [ id, onChange ] - ); - - if ( field.elements ) { - const elements = [ - /* - * Value can be undefined when: - * - * - the field is not required - * - in bulk editing - * - */ - { label: __( 'Select item' ), value: '' }, - ...field.elements, - ]; - - return ( - <SelectControl - label={ label } - value={ value } - options={ elements } - onChange={ onChangeControl } - /> - ); - } - - return ( - <NumberControl - label={ label } - help={ description } - value={ value } - onChange={ onChangeControl } - __next40pxDefaultSize - /> - ); -} - -const controls: { - [ key in FieldType ]: < Item >( - props: DataFormControlProps< Item > - ) => JSX.Element; -} = { - text: DataFormTextControl, - integer: DataFormNumberControl, -}; - -function getControlForField< Item >( field: NormalizedField< Item > ) { - if ( ! field.type ) { - return null; - } - - if ( ! Object.keys( controls ).includes( field.type ) ) { - return null; - } - - return controls[ field.type ]; -} - export default function DataForm< Item >( { data, fields, @@ -149,14 +38,13 @@ export default function DataForm< Item >( { ); return visibleFields.map( ( field ) => { - const DataFormControl = getControlForField( field ); - return DataFormControl ? ( - <DataFormControl + return ( + <field.Edit key={ field.id } data={ data } field={ field } onChange={ onChange } /> - ) : null; + ); } ); } diff --git a/packages/dataviews/src/field-types/index.tsx b/packages/dataviews/src/field-types/index.tsx index 9d81d210f5d5d7..3d1d824ec36bf2 100644 --- a/packages/dataviews/src/field-types/index.tsx +++ b/packages/dataviews/src/field-types/index.tsx @@ -40,5 +40,6 @@ export default function getFieldTypeDefinition( type?: FieldType ) { return true; }, + Edit: () => null, }; } diff --git a/packages/dataviews/src/field-types/integer.tsx b/packages/dataviews/src/field-types/integer.tsx index eaa90e8f1e4e26..823983bc010bf4 100644 --- a/packages/dataviews/src/field-types/integer.tsx +++ b/packages/dataviews/src/field-types/integer.tsx @@ -1,7 +1,21 @@ +/** + * WordPress dependencies + */ +import { + __experimentalNumberControl as NumberControl, + SelectControl, +} from '@wordpress/components'; +import { useCallback } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; + /** * Internal dependencies */ -import type { SortDirection, ValidationContext } from '../types'; +import type { + SortDirection, + ValidationContext, + DataFormControlProps, +} from '../types'; function sort( a: any, b: any, direction: SortDirection ) { return direction === 'asc' ? a - b : b - a; @@ -27,7 +41,58 @@ function isValid( value: any, context?: ValidationContext ) { return true; } +function Edit< Item >( { + data, + field, + onChange, +}: DataFormControlProps< Item > ) { + const { id, label, description } = field; + const value = field.getValue( { item: data } ) ?? ''; + const onChangeControl = useCallback( + ( newValue: string | undefined ) => + onChange( ( prevItem: Item ) => ( { + ...prevItem, + [ id ]: newValue, + } ) ), + [ id, onChange ] + ); + + if ( field.elements ) { + const elements = [ + /* + * Value can be undefined when: + * + * - the field is not required + * - in bulk editing + * + */ + { label: __( 'Select item' ), value: '' }, + ...field.elements, + ]; + + return ( + <SelectControl + label={ label } + value={ value } + options={ elements } + onChange={ onChangeControl } + /> + ); + } + + return ( + <NumberControl + label={ label } + help={ description } + value={ value } + onChange={ onChangeControl } + __next40pxDefaultSize + /> + ); +} + export default { sort, isValid, + Edit, }; diff --git a/packages/dataviews/src/field-types/text.tsx b/packages/dataviews/src/field-types/text.tsx index 5138fe0e397d37..45d1b66bf71d96 100644 --- a/packages/dataviews/src/field-types/text.tsx +++ b/packages/dataviews/src/field-types/text.tsx @@ -1,7 +1,17 @@ +/** + * WordPress dependencies + */ +import { TextControl } from '@wordpress/components'; +import { useCallback } from '@wordpress/element'; + /** * Internal dependencies */ -import type { SortDirection, ValidationContext } from '../types'; +import type { + SortDirection, + ValidationContext, + DataFormControlProps, +} from '../types'; function sort( valueA: any, valueB: any, direction: SortDirection ) { return direction === 'asc' @@ -20,7 +30,36 @@ function isValid( value: any, context?: ValidationContext ) { return true; } +function Edit< Item >( { + data, + field, + onChange, +}: DataFormControlProps< Item > ) { + const { id, label, placeholder } = field; + const value = field.getValue( { item: data } ); + + const onChangeControl = useCallback( + ( newValue: string ) => + onChange( ( prevItem: Item ) => ( { + ...prevItem, + [ id ]: newValue, + } ) ), + [ id, onChange ] + ); + + return ( + <TextControl + label={ label } + placeholder={ placeholder } + value={ value ?? '' } + onChange={ onChangeControl } + __next40pxDefaultSize + /> + ); +} + export default { sort, isValid, + Edit, }; diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index 8d08b08715c9a3..3c3f6b07a0c296 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -39,6 +39,8 @@ export function normalizeFields< Item >( ); }; + const Edit = field.Edit || fieldTypeDefinition.Edit; + return { ...field, label: field.label || field.id, @@ -46,6 +48,7 @@ export function normalizeFields< Item >( render: field.render || getValue, sort, isValid, + Edit, }; } ); } diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 7029db7d17b1af..7fb157465b41f4 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -1,7 +1,12 @@ /** * External dependencies */ -import type { ReactElement, ComponentType } from 'react'; +import type { + ReactElement, + ComponentType, + Dispatch, + SetStateAction, +} from 'react'; /** * Internal dependencies @@ -84,6 +89,11 @@ export type Field< Item > = { */ render?: ComponentType< { item: Item } >; + /** + * Callback used to render an edit control for the field. + */ + Edit?: ComponentType< DataFormControlProps< Item > >; + /** * Callback used to sort the field. */ @@ -138,6 +148,7 @@ export type NormalizedField< Item > = Field< Item > & { label: string; getValue: ( args: { item: Item } ) => any; render: ComponentType< { item: Item } >; + Edit: ComponentType< DataFormControlProps< Item > >; sort: ( a: Item, b: Item, direction: SortDirection ) => number; isValid: ( item: Item, context?: ValidationContext ) => boolean; }; @@ -156,6 +167,12 @@ export type Form = { visibleFields?: string[]; }; +export type DataFormControlProps< Item > = { + data: Item; + field: NormalizedField< Item >; + onChange: Dispatch< SetStateAction< Item > >; +}; + /** * The filters applied to the dataset. */ From 517d8b491aff875a6b931ff75f3425940b4485b3 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 1 Aug 2024 17:37:32 +0200 Subject: [PATCH 0216/1908] Site Icon: Add back filter effect to make it work for all kind of site icons (#64172) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/edit-site/src/components/editor/style.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/edit-site/src/components/editor/style.scss b/packages/edit-site/src/components/editor/style.scss index 0e2e85ba9f72dd..1e931e296d2f42 100644 --- a/packages/edit-site/src/components/editor/style.scss +++ b/packages/edit-site/src/components/editor/style.scss @@ -72,5 +72,7 @@ &.has-site-icon { background-color: hsla(0, 0%, 100%, 0.6); + -webkit-backdrop-filter: saturate(180%) blur(15px); + backdrop-filter: saturate(180%) blur(15px); } } From 23fe5e556f94233d4eba2ecd105be9afce9f2bbd Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Thu, 1 Aug 2024 18:03:22 +0200 Subject: [PATCH 0217/1908] Upgrade Ariakit (#64066) * Add temporary type workaround. * v0.3.13 (test: v0.3.8) * Add temporary render fork with re-render support. * v0.3.13 - test fixes * v0.3.14 * v0.4.0 (test: v0.3.9) * v0.4.0 - test fixes (data attributes) * v0.4.0 - test fixes (animation) * v0.4.0 - test fixes (tooltip describedBy) * v0.4.0 - test fixes (data attributes - missed one snapshot) * v0.4.1 (test: v0.3.10) * Revert temporary type workaround. * v0.4.2 (test: v0.3.11) * v0.4.3 (test: v0.3.12) * v0.4.4 (test: v0.3.13) * v0.4.5 (test: v0.3.14) * v0.4.6 (test: v0.3.15) * v0.4.6 - test fixes * v0.4.7 (test: v0.3.16) * Restore package.json ranges instead of locked versions. * Restrict "render" output to "rerender" and "unmount". * Add restrictedImport rules. * Revert "Add restrictedImport rules." This reverts commit 7a43523df0cda88b27b3e1e25fda2c911f1ce6b9. * Remove local `render` fork and upgrade to latest `@ariakit/test` version. * Add temporary describedBy compatibility logic to Tooltip, and add tests back. * Add changelog entries. Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- package-lock.json | 220 ++++++++++-------- package.json | 2 +- .../test/__snapshots__/control.js.snap | 2 +- .../colors-gradients/test/control.js | 5 +- packages/components/CHANGELOG.md | 3 +- packages/components/package.json | 2 +- packages/components/src/button/test/index.tsx | 58 ++--- .../src/composite/legacy/test/index.tsx | 2 +- .../src/custom-select-control-v2/styles.ts | 13 +- .../custom-select-control-v2/test/index.tsx | 27 +-- .../src/custom-select-control/test/index.tsx | 53 ++--- .../components/src/dropdown-menu-v2/styles.ts | 34 +-- .../src/font-size-picker/test/index.tsx | 93 ++++---- packages/components/src/tabs/test/index.tsx | 127 +++++----- .../test/__snapshots__/index.tsx.snap | 4 +- packages/components/src/tooltip/index.tsx | 17 +- .../src/tooltip/test/utils/index.tsx | 10 +- packages/dataviews/CHANGELOG.md | 14 +- packages/dataviews/package.json | 2 +- 19 files changed, 361 insertions(+), 327 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4e7e660619249b..283127c1861b3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -86,7 +86,7 @@ "@actions/core": "1.9.1", "@actions/github": "5.0.0", "@apidevtools/json-schema-ref-parser": "11.6.4", - "@ariakit/test": "^0.3.7", + "@ariakit/test": "^0.4.0", "@babel/core": "7.24.3", "@babel/plugin-proposal-export-namespace-from": "7.18.9", "@babel/plugin-syntax-jsx": "7.24.1", @@ -1527,55 +1527,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@ariakit/core": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.3.10.tgz", - "integrity": "sha512-AcN+GSoVXuUOzKx5d3xPL3YsEHevh4PIO6QIt/mg/nRX1XQ6cvxQEiAjO/BJQm+/MVl7/VbuGBoTFjr0tPU6NQ==" - }, - "node_modules/@ariakit/react": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.3.12.tgz", - "integrity": "sha512-HxKMZZhWSkwwS/Sh9OdWyuNKQ2tjDAIQIy2KVI7IRa8ZQ6ze/4g3YLUHbfCxO7oDupXHfXaeZ4hWx8lP7l1U/g==", - "dependencies": { - "@ariakit/react-core": "0.3.12" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ariakit" - }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" - } - }, - "node_modules/@ariakit/react-core": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.3.12.tgz", - "integrity": "sha512-w6P1A7TYb1fKUe9QbwaoTOWofl13g7TEuXdV4JyefJCQL1e9HQdEw9UL67I8aXRo8/cFHH94/z0N37t8hw5Ogg==", - "dependencies": { - "@ariakit/core": "0.3.10", - "@floating-ui/dom": "^1.0.0", - "use-sync-external-store": "^1.2.0" - }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" - } - }, "node_modules/@ariakit/test": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/@ariakit/test/-/test-0.3.7.tgz", - "integrity": "sha512-rOa9pJA0ZfPPSI4SkDX41CsBcvxs6BmxgzFEElZWZo/uBBqtnr8ZL4oe5HySeZKEAHRH86XDqfxFISkhV76m5g==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@ariakit/test/-/test-0.4.0.tgz", + "integrity": "sha512-AcrppK61/AbsMDyDS3AxY3WXI6fcL+WedNpJm44Qx603dVYkS/potk0PrD1MfdC6aRt+2bRRj0n9dLN5lVMtbg==", "dev": true, + "license": "MIT", "dependencies": { - "@ariakit/core": "0.3.10", - "@testing-library/dom": "^8.0.0 || ^9.0.0" + "@ariakit/core": "0.4.7", + "@testing-library/dom": "^8.0.0 || ^9.0.0 || ^10.0.0" }, "peerDependencies": { - "@testing-library/react": "^12.0.0 || ^13.0.0 || ^14.0.0", - "react": "^17.0.0 || ^18.0.0" + "@playwright/test": "^1.27.0", + "@testing-library/react": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { + "@playwright/test": { + "optional": true + }, "@testing-library/react": { "optional": true }, @@ -1584,6 +1554,12 @@ } } }, + "node_modules/@ariakit/test/node_modules/@ariakit/core": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.7.tgz", + "integrity": "sha512-GUy/3ZY4kW1KdYHtMZRrRlj5FYbZTAyHlimxHI7Zs0xsC+kAzIf8lopnf67Y9IYLgEMr37KosIV7kwpkJpNs5Q==", + "dev": true + }, "node_modules/@aw-web-design/x-default-browser": { "version": "1.4.126", "resolved": "https://registry.npmjs.org/@aw-web-design/x-default-browser/-/x-default-browser-1.4.126.tgz", @@ -52645,7 +52621,7 @@ "version": "28.4.0", "license": "GPL-2.0-or-later", "dependencies": { - "@ariakit/react": "^0.3.12", + "@ariakit/react": "^0.4.7", "@babel/runtime": "^7.16.0", "@emotion/cache": "^11.7.1", "@emotion/css": "^11.7.1", @@ -52701,6 +52677,41 @@ "react-dom": "^18.0.0" } }, + "packages/components/node_modules/@ariakit/core": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.7.tgz", + "integrity": "sha512-GUy/3ZY4kW1KdYHtMZRrRlj5FYbZTAyHlimxHI7Zs0xsC+kAzIf8lopnf67Y9IYLgEMr37KosIV7kwpkJpNs5Q==" + }, + "packages/components/node_modules/@ariakit/react": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.7.tgz", + "integrity": "sha512-uUruuCo1M0Nj2oq1nTwDfUlVTLuoI9xeHP75EkuXX46lg5hzE5vVWbSMO1D6MCy7UwrUx2Ts4IqxdKr97suTwQ==", + "dependencies": { + "@ariakit/react-core": "0.4.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ariakit" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "packages/components/node_modules/@ariakit/react-core": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.7.tgz", + "integrity": "sha512-OogUyQ20cxkRNRuqLI05JbmpR4Lr5HwhUIqnb/sipzt6bkg/3wCXEnUAjfxg3nPjLTMjJ8+ODWmPC9JMJTW/yg==", + "dependencies": { + "@ariakit/core": "0.4.7", + "@floating-ui/dom": "^1.0.0", + "use-sync-external-store": "^1.2.0" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "packages/components/node_modules/@floating-ui/react-dom": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.1.tgz", @@ -52969,7 +52980,7 @@ "version": "4.0.0", "license": "GPL-2.0-or-later", "dependencies": { - "@ariakit/react": "^0.3.12", + "@ariakit/react": "^0.4.7", "@babel/runtime": "^7.16.0", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", @@ -52991,38 +53002,38 @@ } }, "packages/dataviews/node_modules/@ariakit/core": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.1.tgz", - "integrity": "sha512-Rdhw0/K0x+50gFvzuMW9wp+WJxpkrgiMgegRTOZSU92bv1K+6XfQWnlieIkLt2FC7pZGrDpGlS4C7ztEVF+JRg==" + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.7.tgz", + "integrity": "sha512-GUy/3ZY4kW1KdYHtMZRrRlj5FYbZTAyHlimxHI7Zs0xsC+kAzIf8lopnf67Y9IYLgEMr37KosIV7kwpkJpNs5Q==" }, "packages/dataviews/node_modules/@ariakit/react": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.1.tgz", - "integrity": "sha512-hKfCYjc3MFW20kn2dcvejB5zbYt/uU33Teq82c414/utf5sEoeRF+bxjNku8x1baJby9/SDP6zj2IgWPuedFNA==", + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.7.tgz", + "integrity": "sha512-uUruuCo1M0Nj2oq1nTwDfUlVTLuoI9xeHP75EkuXX46lg5hzE5vVWbSMO1D6MCy7UwrUx2Ts4IqxdKr97suTwQ==", "dependencies": { - "@ariakit/react-core": "0.4.1" + "@ariakit/react-core": "0.4.7" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/ariakit" }, "peerDependencies": { - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" } }, "packages/dataviews/node_modules/@ariakit/react-core": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.1.tgz", - "integrity": "sha512-cwDczl9XWBloXNg0CuHmJtBfEe7qF265JE0Pwlcp8wMSY9PsJeb0mKBlTygUPKn/FsKpKGaYSI7DlDntbcZciw==", + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.7.tgz", + "integrity": "sha512-OogUyQ20cxkRNRuqLI05JbmpR4Lr5HwhUIqnb/sipzt6bkg/3wCXEnUAjfxg3nPjLTMjJ8+ODWmPC9JMJTW/yg==", "dependencies": { - "@ariakit/core": "0.4.1", + "@ariakit/core": "0.4.7", "@floating-ui/dom": "^1.0.0", "use-sync-external-store": "^1.2.0" }, "peerDependencies": { - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" } }, "packages/date": { @@ -56146,37 +56157,22 @@ } } }, - "@ariakit/core": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.3.10.tgz", - "integrity": "sha512-AcN+GSoVXuUOzKx5d3xPL3YsEHevh4PIO6QIt/mg/nRX1XQ6cvxQEiAjO/BJQm+/MVl7/VbuGBoTFjr0tPU6NQ==" - }, - "@ariakit/react": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.3.12.tgz", - "integrity": "sha512-HxKMZZhWSkwwS/Sh9OdWyuNKQ2tjDAIQIy2KVI7IRa8ZQ6ze/4g3YLUHbfCxO7oDupXHfXaeZ4hWx8lP7l1U/g==", - "requires": { - "@ariakit/react-core": "0.3.12" - } - }, - "@ariakit/react-core": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.3.12.tgz", - "integrity": "sha512-w6P1A7TYb1fKUe9QbwaoTOWofl13g7TEuXdV4JyefJCQL1e9HQdEw9UL67I8aXRo8/cFHH94/z0N37t8hw5Ogg==", - "requires": { - "@ariakit/core": "0.3.10", - "@floating-ui/dom": "^1.0.0", - "use-sync-external-store": "^1.2.0" - } - }, "@ariakit/test": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/@ariakit/test/-/test-0.3.7.tgz", - "integrity": "sha512-rOa9pJA0ZfPPSI4SkDX41CsBcvxs6BmxgzFEElZWZo/uBBqtnr8ZL4oe5HySeZKEAHRH86XDqfxFISkhV76m5g==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@ariakit/test/-/test-0.4.0.tgz", + "integrity": "sha512-AcrppK61/AbsMDyDS3AxY3WXI6fcL+WedNpJm44Qx603dVYkS/potk0PrD1MfdC6aRt+2bRRj0n9dLN5lVMtbg==", "dev": true, "requires": { - "@ariakit/core": "0.3.10", - "@testing-library/dom": "^8.0.0 || ^9.0.0" + "@ariakit/core": "0.4.7", + "@testing-library/dom": "^8.0.0 || ^9.0.0 || ^10.0.0" + }, + "dependencies": { + "@ariakit/core": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.7.tgz", + "integrity": "sha512-GUy/3ZY4kW1KdYHtMZRrRlj5FYbZTAyHlimxHI7Zs0xsC+kAzIf8lopnf67Y9IYLgEMr37KosIV7kwpkJpNs5Q==", + "dev": true + } } }, "@aw-web-design/x-default-browser": { @@ -67524,7 +67520,7 @@ "@wordpress/components": { "version": "file:packages/components", "requires": { - "@ariakit/react": "^0.3.12", + "@ariakit/react": "^0.4.7", "@babel/runtime": "^7.16.0", "@emotion/cache": "^11.7.1", "@emotion/css": "^11.7.1", @@ -67572,6 +67568,29 @@ "uuid": "^9.0.1" }, "dependencies": { + "@ariakit/core": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.7.tgz", + "integrity": "sha512-GUy/3ZY4kW1KdYHtMZRrRlj5FYbZTAyHlimxHI7Zs0xsC+kAzIf8lopnf67Y9IYLgEMr37KosIV7kwpkJpNs5Q==" + }, + "@ariakit/react": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.7.tgz", + "integrity": "sha512-uUruuCo1M0Nj2oq1nTwDfUlVTLuoI9xeHP75EkuXX46lg5hzE5vVWbSMO1D6MCy7UwrUx2Ts4IqxdKr97suTwQ==", + "requires": { + "@ariakit/react-core": "0.4.7" + } + }, + "@ariakit/react-core": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.7.tgz", + "integrity": "sha512-OogUyQ20cxkRNRuqLI05JbmpR4Lr5HwhUIqnb/sipzt6bkg/3wCXEnUAjfxg3nPjLTMjJ8+ODWmPC9JMJTW/yg==", + "requires": { + "@ariakit/core": "0.4.7", + "@floating-ui/dom": "^1.0.0", + "use-sync-external-store": "^1.2.0" + } + }, "@floating-ui/react-dom": { "version": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.1.tgz", "integrity": "sha512-rZtAmSht4Lry6gdhAJDrCp/6rKN7++JnL1/Anbr/DdeyYXQPxvg/ivrbYvJulbRf4vL8b212suwMM2lxbv+RQA==", @@ -67757,7 +67776,7 @@ "@wordpress/dataviews": { "version": "file:packages/dataviews", "requires": { - "@ariakit/react": "^0.3.12", + "@ariakit/react": "^0.4.7", "@babel/runtime": "^7.16.0", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", @@ -67772,23 +67791,24 @@ }, "dependencies": { "@ariakit/core": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.1.tgz", - "integrity": "sha512-Rdhw0/K0x+50gFvzuMW9wp+WJxpkrgiMgegRTOZSU92bv1K+6XfQWnlieIkLt2FC7pZGrDpGlS4C7ztEVF+JRg==" + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.7.tgz", + "integrity": "sha512-GUy/3ZY4kW1KdYHtMZRrRlj5FYbZTAyHlimxHI7Zs0xsC+kAzIf8lopnf67Y9IYLgEMr37KosIV7kwpkJpNs5Q==" }, "@ariakit/react": { - "version": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.1.tgz", - "integrity": "sha512-hKfCYjc3MFW20kn2dcvejB5zbYt/uU33Teq82c414/utf5sEoeRF+bxjNku8x1baJby9/SDP6zj2IgWPuedFNA==", + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.7.tgz", + "integrity": "sha512-uUruuCo1M0Nj2oq1nTwDfUlVTLuoI9xeHP75EkuXX46lg5hzE5vVWbSMO1D6MCy7UwrUx2Ts4IqxdKr97suTwQ==", "requires": { - "@ariakit/react-core": "0.4.1" + "@ariakit/react-core": "0.4.7" } }, "@ariakit/react-core": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.1.tgz", - "integrity": "sha512-cwDczl9XWBloXNg0CuHmJtBfEe7qF265JE0Pwlcp8wMSY9PsJeb0mKBlTygUPKn/FsKpKGaYSI7DlDntbcZciw==", + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.7.tgz", + "integrity": "sha512-OogUyQ20cxkRNRuqLI05JbmpR4Lr5HwhUIqnb/sipzt6bkg/3wCXEnUAjfxg3nPjLTMjJ8+ODWmPC9JMJTW/yg==", "requires": { - "@ariakit/core": "0.4.1", + "@ariakit/core": "0.4.7", "@floating-ui/dom": "^1.0.0", "use-sync-external-store": "^1.2.0" } diff --git a/package.json b/package.json index 9234bf92cc9172..53e8d0876ed621 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "@actions/core": "1.9.1", "@actions/github": "5.0.0", "@apidevtools/json-schema-ref-parser": "11.6.4", - "@ariakit/test": "^0.3.7", + "@ariakit/test": "^0.4.0", "@babel/core": "7.24.3", "@babel/plugin-proposal-export-namespace-from": "7.18.9", "@babel/plugin-syntax-jsx": "7.24.1", diff --git a/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap b/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap index bd9175782a224a..3c4cef664a3103 100644 --- a/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap +++ b/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap @@ -220,7 +220,7 @@ exports[`ColorPaletteControl matches the snapshot 1`] = ` aria-label="Color: red" aria-selected="true" class="components-button components-circular-option-picker__option" - data-active-item="" + data-active-item="true" id="components-circular-option-picker-0-0" role="option" style="background-color: rgb(255, 0, 0); color: rgb(255, 0, 0);" diff --git a/packages/block-editor/src/components/colors-gradients/test/control.js b/packages/block-editor/src/components/colors-gradients/test/control.js index 0bda16071ef99b..19640d41daeb35 100644 --- a/packages/block-editor/src/components/colors-gradients/test/control.js +++ b/packages/block-editor/src/components/colors-gradients/test/control.js @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; /** * Internal dependencies @@ -12,7 +13,7 @@ const noop = () => {}; describe( 'ColorPaletteControl', () => { it( 'renders tabs if it is possible to select a color and a gradient rendering a color picker at the start', async () => { - render( + await render( <ColorGradientControl label="Test Color Gradient" colorValue="#f00" diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index e6e1dbbf50a1f5..e77ae39ddb3d20 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -15,6 +15,7 @@ ### Internal +- Upgraded `@ariakit/react` (v0.4.7) and `@ariakit/test` (v0.4.0) ([#64066](https://github.com/WordPress/gutenberg/pull/64066)). - `DropdownMenuV2`: break menu item help text on multiple lines for better truncation. ([#63916](https://github.com/WordPress/gutenberg/pull/63916)). - `CustomSelectControl`: Support generic props type ([#63985](https://github.com/WordPress/gutenberg/pull/63985)). @@ -88,7 +89,7 @@ ### Internal -- `Allow ariakit and framer motion imports in the components package. ([#63123](https://github.com/WordPress/gutenberg/pull/63123)) +- Allow ariakit and framer motion imports in the components package. ([#63123](https://github.com/WordPress/gutenberg/pull/63123)) - `CustomSelectControlV2`: prevent keyboard event propagation in legacy wrapper. ([#62907](https://github.com/WordPress/gutenberg/pull/62907)) - `CustomSelectControlV2`: expose legacy wrapper through private APIs. ([#62936](https://github.com/WordPress/gutenberg/pull/62936)) - `CustomSelectControlV2`: fix item styles ([#62825](https://github.com/WordPress/gutenberg/pull/62825)) diff --git a/packages/components/package.json b/packages/components/package.json index 7c1b62f8bba22d..784b03d6574940 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -31,7 +31,7 @@ ], "types": "build-types", "dependencies": { - "@ariakit/react": "^0.3.12", + "@ariakit/react": "^0.4.7", "@babel/runtime": "^7.16.0", "@emotion/cache": "^11.7.1", "@emotion/css": "^11.7.1", diff --git a/packages/components/src/button/test/index.tsx b/packages/components/src/button/test/index.tsx index c5bf32e683ff1a..8161e68c4e21b6 100644 --- a/packages/components/src/button/test/index.tsx +++ b/packages/components/src/button/test/index.tsx @@ -2,7 +2,6 @@ * External dependencies */ import { render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; /** * WordPress dependencies @@ -16,6 +15,7 @@ import { plusCircle } from '@wordpress/icons'; import Button from '..'; import Tooltip from '../../tooltip'; import cleanupTooltip from '../../tooltip/test/utils'; +import { press } from '@ariakit/test'; jest.mock( '../../icon', () => () => <div data-testid="test-icon" /> ); @@ -73,12 +73,10 @@ describe( 'Button', () => { } ); it( 'should render a button element with has-text when children are passed', async () => { - const user = userEvent.setup(); - render( <Button icon={ plusCircle }>Children</Button> ); // Move focus to the button - await user.tab(); + await press.Tab(); expect( screen.getByRole( 'button' ) ).toHaveClass( 'has-text' ); } ); @@ -113,8 +111,6 @@ describe( 'Button', () => { } ); it( 'should render correctly as a tooltip anchor', async () => { - const user = userEvent.setup(); - render( <> <Tooltip text="Tooltip text"> @@ -128,7 +124,7 @@ describe( 'Button', () => { name: 'Tooltip anchor', } ); - await user.tab(); + await press.Tab(); expect( anchor ).toHaveFocus(); @@ -138,7 +134,7 @@ describe( 'Button', () => { expect( tooltip ).toBeVisible(); - await user.tab(); + await press.Tab(); expect( screen.getByRole( 'button', { name: 'Focus me' } ) @@ -152,8 +148,6 @@ describe( 'Button', () => { } ); it( 'should render correctly as a tooltip anchor, ignoring its internal tooltip in favour of the external tooltip', async () => { - const user = userEvent.setup(); - render( <> <Tooltip text="Tooltip text"> @@ -167,7 +161,7 @@ describe( 'Button', () => { name: 'Button label', } ); - await user.tab(); + await press.Tab(); expect( anchor ).toHaveFocus(); @@ -184,7 +178,7 @@ describe( 'Button', () => { } ) ).not.toBeInTheDocument(); - await user.tab(); + await press.Tab(); expect( screen.getByRole( 'button', { name: 'Focus me' } ) @@ -198,8 +192,6 @@ describe( 'Button', () => { } ); it( 'should not trash the rendered HTML elements when toggling between showing and not showing a tooltip', async () => { - const user = userEvent.setup(); - const { rerender } = render( <Button label="Button label">Test button</Button> ); @@ -210,7 +202,7 @@ describe( 'Button', () => { expect( button ).toBeVisible(); - await user.tab(); + await press.Tab(); expect( button ).toHaveFocus(); @@ -307,14 +299,12 @@ describe( 'Button', () => { } ); it( 'should add an aria-label when the label property is used, with Tooltip wrapper', async () => { - const user = userEvent.setup(); - render( <Button icon={ plusCircle } label="WordPress" /> ); expect( screen.queryByText( 'WordPress' ) ).not.toBeInTheDocument(); // Move focus to the button - await user.tab(); + await press.Tab(); expect( screen.getByText( 'WordPress' ) ).toBeVisible(); } ); @@ -338,8 +328,6 @@ describe( 'Button', () => { } ); it( 'should populate tooltip with label content for buttons without visible labels (no children)', async () => { - const user = userEvent.setup(); - render( <Button description="Description text" @@ -351,16 +339,14 @@ describe( 'Button', () => { expect( screen.queryByText( 'Label' ) ).not.toBeInTheDocument(); // Move focus to the button - await user.tab(); + await press.Tab(); expect( screen.getByText( 'Label' ) ).toBeVisible(); - await cleanupTooltip( user ); + await cleanupTooltip(); } ); it( 'should populate tooltip with description content for buttons with visible labels (buttons with children)', async () => { - const user = userEvent.setup(); - render( <Button label="Label" @@ -378,7 +364,7 @@ describe( 'Button', () => { } ) ).toBeVisible(); - await user.tab(); + await press.Tab(); expect( screen.getByRole( 'tooltip', { @@ -386,12 +372,10 @@ describe( 'Button', () => { } ) ).toBeVisible(); - await cleanupTooltip( user ); + await cleanupTooltip(); } ); it( 'should allow tooltip disable', async () => { - const user = userEvent.setup(); - render( <Button icon={ plusCircle } @@ -407,14 +391,12 @@ describe( 'Button', () => { expect( screen.queryByText( 'WordPress' ) ).not.toBeInTheDocument(); // Move focus to the button - await user.tab(); + await press.Tab(); expect( screen.queryByText( 'WordPress' ) ).not.toBeInTheDocument(); } ); it( 'should show the tooltip for empty children', async () => { - const user = userEvent.setup(); - render( <Button icon={ plusCircle } label="WordPress" children={ [] } /> ); @@ -422,16 +404,14 @@ describe( 'Button', () => { expect( screen.queryByText( 'WordPress' ) ).not.toBeInTheDocument(); // Move focus to the button - await user.tab(); + await press.Tab(); expect( screen.getByText( 'WordPress' ) ).toBeVisible(); - await cleanupTooltip( user ); + await cleanupTooltip(); } ); it( 'should not show the tooltip when icon and children defined', async () => { - const user = userEvent.setup(); - render( <Button icon={ plusCircle } label="WordPress"> Children @@ -441,14 +421,12 @@ describe( 'Button', () => { expect( screen.queryByText( 'WordPress' ) ).not.toBeInTheDocument(); // Move focus to the button - await user.tab(); + await press.Tab(); expect( screen.queryByText( 'WordPress' ) ).not.toBeInTheDocument(); } ); it( 'should force showing the tooltip even if icon and children defined', async () => { - const user = userEvent.setup(); - render( <Button icon={ plusCircle } label="WordPress" showTooltip> Children @@ -458,11 +436,11 @@ describe( 'Button', () => { expect( screen.queryByText( 'WordPress' ) ).not.toBeInTheDocument(); // Move focus to the button - await user.tab(); + await press.Tab(); expect( screen.getByText( 'WordPress' ) ).toBeVisible(); - await cleanupTooltip( user ); + await cleanupTooltip(); } ); describe( 'using `aria-pressed` prop', () => { diff --git a/packages/components/src/composite/legacy/test/index.tsx b/packages/components/src/composite/legacy/test/index.tsx index 315532a8b50869..085ac572e3e8a1 100644 --- a/packages/components/src/composite/legacy/test/index.tsx +++ b/packages/components/src/composite/legacy/test/index.tsx @@ -47,7 +47,7 @@ async function renderAndValidate( ...args: Parameters< typeof render > ) { const activeButton = queryByAttribute( 'data-active-item', view.baseElement, - '' + 'true' ); expect( activeButton ).not.toBeNull(); } ); diff --git a/packages/components/src/custom-select-control-v2/styles.ts b/packages/components/src/custom-select-control-v2/styles.ts index 701f69aa5757bd..6b7fa590f9d0b2 100644 --- a/packages/components/src/custom-select-control-v2/styles.ts +++ b/packages/components/src/custom-select-control-v2/styles.ts @@ -132,12 +132,13 @@ export const SelectPopover = styled( Ariakit.SelectPopover )` min-width: min-content; /* Animation */ - animation-duration: ${ ANIMATION_PARAMS.DURATION }; - animation-timing-function: ${ ANIMATION_PARAMS.EASING }; - animation-name: ${ slideDownAndFade }; - will-change: transform, opacity; - @media ( prefers-reduced-motion ) { - animation-duration: 0s; + &[data-open] { + @media not ( prefers-reduced-motion ) { + animation-duration: ${ ANIMATION_PARAMS.DURATION }; + animation-timing-function: ${ ANIMATION_PARAMS.EASING }; + animation-name: ${ slideDownAndFade }; + will-change: transform, opacity; + } } &[data-focus-visible] { diff --git a/packages/components/src/custom-select-control-v2/test/index.tsx b/packages/components/src/custom-select-control-v2/test/index.tsx index 3ff384852be04f..e02eb0f774a401 100644 --- a/packages/components/src/custom-select-control-v2/test/index.tsx +++ b/packages/components/src/custom-select-control-v2/test/index.tsx @@ -1,8 +1,9 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; import { click, press, sleep, type } from '@ariakit/test'; +import { render } from '@ariakit/test/react'; /** * WordPress dependencies @@ -66,7 +67,7 @@ describe.each( [ const [ , Component ] = modeAndComponent; it( 'Should replace the initial selection when a new item is selected', async () => { - render( <Component { ...defaultProps } /> ); + await render( <Component { ...defaultProps } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -94,7 +95,7 @@ describe.each( [ } ); it( 'Should keep current selection if dropdown is closed without changing selection', async () => { - render( <Component { ...defaultProps } /> ); + await render( <Component { ...defaultProps } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -121,7 +122,7 @@ describe.each( [ describe( 'Keyboard behavior and accessibility', () => { it( 'Should be able to change selection using keyboard', async () => { - render( <Component { ...defaultProps } /> ); + await render( <Component { ...defaultProps } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -145,7 +146,7 @@ describe.each( [ } ); it( 'Should be able to type characters to select matching options', async () => { - render( <Component { ...defaultProps } /> ); + await render( <Component { ...defaultProps } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -166,7 +167,7 @@ describe.each( [ } ); it( 'Can change selection with a focused input and closed dropdown if typed characters match an option', async () => { - render( <Component { ...defaultProps } /> ); + await render( <Component { ...defaultProps } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -194,7 +195,7 @@ describe.each( [ } ); it( 'Should have correct aria-selected value for selections', async () => { - render( <Component { ...defaultProps } /> ); + await render( <Component { ...defaultProps } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -244,7 +245,7 @@ describe.each( [ 'ultraviolet morning light', ]; - render( + await render( <Component defaultValue={ defaultValues } onChange={ onChangeMock } @@ -326,7 +327,7 @@ describe.each( [ 'ultraviolet morning light', ]; - render( + await render( <Component defaultValue={ defaultValues } label="Multi-select"> { defaultValues.map( ( item ) => ( <UncontrolledCustomSelectControlV2.Item @@ -382,7 +383,7 @@ describe.each( [ return <img src={ `${ value }.jpg` } alt={ value as string } />; }; - render( + await render( <Component label="Rendered" renderSelectedValue={ renderValue }> <UncontrolledCustomSelectControlV2.Item value="april-29"> { renderValue( 'april-29' ) } @@ -418,7 +419,7 @@ describe.each( [ } ); it( 'Should open the select popover when focussing the trigger button and pressing arrow down', async () => { - render( <Component { ...defaultProps } /> ); + await render( <Component { ...defaultProps } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -437,8 +438,8 @@ describe.each( [ ).toBeVisible(); } ); - it( 'Should label the component correctly even when the label is not visible', () => { - render( <Component { ...defaultProps } hideLabelFromVision /> ); + it( 'Should label the component correctly even when the label is not visible', async () => { + await render( <Component { ...defaultProps } hideLabelFromVision /> ); expect( screen.getByRole( 'combobox', { diff --git a/packages/components/src/custom-select-control/test/index.tsx b/packages/components/src/custom-select-control/test/index.tsx index 4bc96f318138c5..fcab84773e5a0b 100644 --- a/packages/components/src/custom-select-control/test/index.tsx +++ b/packages/components/src/custom-select-control/test/index.tsx @@ -1,8 +1,9 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; import { click, press, sleep, type, waitFor } from '@ariakit/test'; +import { render } from '@ariakit/test/react'; /** * WordPress dependencies @@ -85,7 +86,7 @@ const ControlledCustomSelectControl = ( { it( 'Should apply external controlled updates', async () => { const mockOnChange = jest.fn(); - const { rerender } = render( + const { rerender } = await render( <UncontrolledCustomSelectControl { ...props } value={ props.options[ 0 ] } @@ -101,7 +102,7 @@ it( 'Should apply external controlled updates', async () => { expect( mockOnChange ).not.toHaveBeenCalled(); - rerender( + await rerender( <UncontrolledCustomSelectControl { ...props } value={ props.options[ 1 ] } @@ -124,7 +125,7 @@ describe.each( [ it( 'Should select the first option when no explicit initial value is passed without firing onChange', async () => { const mockOnChange = jest.fn(); - render( <Component { ...props } onChange={ mockOnChange } /> ); + await render( <Component { ...props } onChange={ mockOnChange } /> ); expect( screen.getByRole( 'combobox', { @@ -140,7 +141,7 @@ describe.each( [ it( 'Should pick the initially selected option if the value prop is passed without firing onChange', async () => { const mockOnChange = jest.fn(); - render( + await render( <Component { ...props } onChange={ mockOnChange } @@ -161,7 +162,7 @@ describe.each( [ } ); it( 'Should replace the initial selection when a new item is selected', async () => { - render( <Component { ...props } /> ); + await render( <Component { ...props } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -189,7 +190,7 @@ describe.each( [ } ); it( 'Should keep current selection if dropdown is closed without changing selection', async () => { - render( <Component { ...props } /> ); + await render( <Component { ...props } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -217,7 +218,7 @@ describe.each( [ } ); it( 'Should apply class only to options that have a className defined', async () => { - render( <Component { ...props } /> ); + await render( <Component { ...props } /> ); await click( screen.getByRole( 'combobox', { @@ -251,7 +252,7 @@ describe.each( [ } ); it( 'Should apply styles only to options that have styles defined', async () => { - render( <Component { ...props } /> ); + await render( <Component { ...props } /> ); await click( screen.getByRole( 'combobox', { @@ -285,7 +286,7 @@ describe.each( [ } ); it( 'does not show selected hint by default', async () => { - render( + await render( <Component { ...props } label="Custom select" @@ -306,7 +307,7 @@ describe.each( [ } ); it( 'shows selected hint when showSelectedHint is set', async () => { - render( + await render( <Component { ...props } label="Custom select" @@ -331,7 +332,7 @@ describe.each( [ } ); it( 'shows selected hint in list of options when added, regardless of showSelectedHint prop', async () => { - render( + await render( <Component { ...props } label="Custom select" @@ -355,7 +356,7 @@ describe.each( [ it( 'Should return object onChange', async () => { const mockOnChange = jest.fn(); - render( <Component { ...props } onChange={ mockOnChange } /> ); + await render( <Component { ...props } onChange={ mockOnChange } /> ); await click( screen.getByRole( 'combobox', { @@ -385,7 +386,7 @@ describe.each( [ it( 'Should return selectedItem object when specified onChange', async () => { const mockOnChange = jest.fn(); - render( <Component { ...props } onChange={ mockOnChange } /> ); + await render( <Component { ...props } onChange={ mockOnChange } /> ); await sleep(); await press.Tab(); @@ -412,7 +413,7 @@ describe.each( [ it( "Should pass arbitrary props to onChange's selectedItem, but apply only style and className to DOM elements", async () => { const onChangeMock = jest.fn(); - render( <Component { ...props } onChange={ onChangeMock } /> ); + await render( <Component { ...props } onChange={ onChangeMock } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -449,8 +450,8 @@ describe.each( [ ); } ); - it( 'Should label the component correctly even when the label is not visible', () => { - render( <Component { ...props } hideLabelFromVision /> ); + it( 'Should label the component correctly even when the label is not visible', async () => { + await render( <Component { ...props } hideLabelFromVision /> ); expect( screen.getByRole( 'combobox', { @@ -463,7 +464,7 @@ describe.each( [ it( 'Captures the keypress event and does not let it propagate', async () => { const onKeyDown = jest.fn(); - render( + await render( <div // This role="none" is required to prevent an eslint warning about accessibility. role="none" @@ -487,7 +488,7 @@ describe.each( [ } ); it( 'Should be able to change selection using keyboard', async () => { - render( <Component { ...props } /> ); + await render( <Component { ...props } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -513,7 +514,7 @@ describe.each( [ } ); it( 'Should be able to type characters to select matching options', async () => { - render( <Component { ...props } /> ); + await render( <Component { ...props } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -534,7 +535,7 @@ describe.each( [ } ); it( 'Can change selection with a focused input and closed dropdown if typed characters match an option', async () => { - render( <Component { ...props } /> ); + await render( <Component { ...props } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -564,7 +565,7 @@ describe.each( [ } ); it( 'Can change selection with a focused input and closed dropdown while pressing arrow keys', async () => { - render( <Component { ...props } /> ); + await render( <Component { ...props } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -591,7 +592,7 @@ describe.each( [ } ); it( 'Should have correct aria-selected value for selections', async () => { - render( <Component { ...props } /> ); + await render( <Component { ...props } /> ); const currentSelectedItem = screen.getByRole( 'combobox', { expanded: false, @@ -646,7 +647,7 @@ describe.each( [ const onFocusMock = jest.fn(); const onBlurMock = jest.fn(); - render( + await render( <> <Component { ...props } @@ -674,7 +675,7 @@ describe.each( [ it( 'should render the describedBy text when specified', async () => { const describedByText = 'My description.'; - render( + await render( <Component { ...props } describedBy={ describedByText } /> ); @@ -684,7 +685,7 @@ describe.each( [ } ); it( 'should render the default ARIA description when describedBy is not specified', async () => { - render( <Component { ...props } /> ); + await render( <Component { ...props } /> ); expect( screen.getByRole( 'combobox' ) diff --git a/packages/components/src/dropdown-menu-v2/styles.ts b/packages/components/src/dropdown-menu-v2/styles.ts index b36f69e62c5094..ab7c763b5f4569 100644 --- a/packages/components/src/dropdown-menu-v2/styles.ts +++ b/packages/components/src/dropdown-menu-v2/styles.ts @@ -101,23 +101,23 @@ export const DropdownMenu = styled( Ariakit.Menu )< outline: 2px solid transparent !important; /* Animation */ - animation-duration: ${ ANIMATION_PARAMS.DURATION }; - animation-timing-function: ${ ANIMATION_PARAMS.EASING }; - will-change: transform, opacity; - /* Default animation.*/ - animation-name: ${ slideDownAndFade }; - - &[data-side='left'] { - animation-name: ${ slideLeftAndFade }; - } - &[data-side='up'] { - animation-name: ${ slideUpAndFade }; - } - &[data-side='right'] { - animation-name: ${ slideRightAndFade }; - } - @media ( prefers-reduced-motion ) { - animation-duration: 0s; + &[data-open] { + @media not ( prefers-reduced-motion ) { + animation-duration: ${ ANIMATION_PARAMS.DURATION }; + animation-timing-function: ${ ANIMATION_PARAMS.EASING }; + will-change: transform, opacity; + /* Default animation.*/ + animation-name: ${ slideDownAndFade }; + &[data-side='left'] { + animation-name: ${ slideLeftAndFade }; + } + &[data-side='up'] { + animation-name: ${ slideUpAndFade }; + } + &[data-side='right'] { + animation-name: ${ slideRightAndFade }; + } + } } `; diff --git a/packages/components/src/font-size-picker/test/index.tsx b/packages/components/src/font-size-picker/test/index.tsx index f91c12e352bf80..e7205e57eefaa6 100644 --- a/packages/components/src/font-size-picker/test/index.tsx +++ b/packages/components/src/font-size-picker/test/index.tsx @@ -1,8 +1,9 @@ /** * External dependencies */ -import { render, screen, fireEvent } from '@testing-library/react'; +import { screen, fireEvent } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import { render } from '@ariakit/test/react'; /** * Internal dependencies @@ -44,7 +45,9 @@ describe( 'FontSizePicker', () => { async ( { value, expectedValue } ) => { const user = userEvent.setup(); const onChange = jest.fn(); - render( <FontSizePicker value={ value } onChange={ onChange } /> ); + await render( + <FontSizePicker value={ value } onChange={ onChange } /> + ); const input = screen.getByLabelText( 'Custom' ); await user.clear( input ); await user.type( input, '80' ); @@ -63,7 +66,7 @@ describe( 'FontSizePicker', () => { async ( { firstFontSize, expectedValue } ) => { const user = userEvent.setup(); const onChange = jest.fn(); - render( + await render( <FontSizePicker fontSizes={ [ { slug: 'slug', size: firstFontSize } ] } onChange={ onChange } @@ -115,7 +118,7 @@ describe( 'FontSizePicker', () => { it( 'displays a select control', async () => { const user = userEvent.setup(); - render( <FontSizePicker fontSizes={ fontSizes } /> ); + await render( <FontSizePicker fontSizes={ fontSizes } /> ); await user.click( screen.getByRole( 'combobox', { name: 'Font size' } ) ); @@ -137,8 +140,8 @@ describe( 'FontSizePicker', () => { { value: '3px', expectedLabel: 'Size Custom' }, ] )( 'displays $expectedLabel as label when value is $value', - ( { value, expectedLabel } ) => { - render( + async ( { value, expectedLabel } ) => { + await render( <FontSizePicker fontSizes={ fontSizes } value={ value } /> ); expect( screen.getByLabelText( expectedLabel ) ).toBeVisible(); @@ -161,7 +164,7 @@ describe( 'FontSizePicker', () => { async ( { option, value, expectedArguments } ) => { const user = userEvent.setup(); const onChange = jest.fn(); - render( + await render( <FontSizePicker fontSizes={ fontSizes } value={ value } @@ -219,7 +222,7 @@ describe( 'FontSizePicker', () => { it( 'displays a select control', async () => { const user = userEvent.setup(); - render( <FontSizePicker fontSizes={ fontSizes } /> ); + await render( <FontSizePicker fontSizes={ fontSizes } /> ); await user.click( screen.getByRole( 'combobox', { name: 'Font size' } ) ); @@ -241,8 +244,8 @@ describe( 'FontSizePicker', () => { { value: '8px', option: 'Tiny' }, ] )( 'defaults to $option when value is $value', - ( { value, option } ) => { - render( + async ( { value, option } ) => { + await render( <FontSizePicker fontSizes={ fontSizes } value={ value } /> ); expect( @@ -260,8 +263,8 @@ describe( 'FontSizePicker', () => { { value: '3px', expectedLabel: 'Size Custom' }, ] )( 'displays $expectedLabel as label when value is $value', - ( { value, expectedLabel } ) => { - render( + async ( { value, expectedLabel } ) => { + await render( <FontSizePicker fontSizes={ fontSizes } value={ value } /> ); expect( screen.getByLabelText( expectedLabel ) ).toBeVisible(); @@ -302,7 +305,7 @@ describe( 'FontSizePicker', () => { async ( { option, value, expectedArguments } ) => { const user = userEvent.setup(); const onChange = jest.fn(); - render( + await render( <FontSizePicker fontSizes={ fontSizes } value={ value } @@ -353,8 +356,8 @@ describe( 'FontSizePicker', () => { }, ]; - it( 'displays a toggle group control with t-shirt sizes', () => { - render( <FontSizePicker fontSizes={ fontSizes } /> ); + it( 'displays a toggle group control with t-shirt sizes', async () => { + await render( <FontSizePicker fontSizes={ fontSizes } /> ); const options = screen.getAllByRole( 'radio' ); expect( options ).toHaveLength( 5 ); expect( options[ 0 ] ).toHaveTextContent( 'S' ); @@ -375,8 +378,8 @@ describe( 'FontSizePicker', () => { { value: '40px', expectedLabel: 'Size Gigantosaurus' }, ] )( 'displays $expectedLabel as label when value is $value', - ( { value, expectedLabel } ) => { - render( + async ( { value, expectedLabel } ) => { + await render( <FontSizePicker fontSizes={ fontSizes } value={ value } /> ); expect( screen.getByLabelText( expectedLabel ) ).toBeVisible(); @@ -386,7 +389,7 @@ describe( 'FontSizePicker', () => { it( 'calls onChange when a font size is selected', async () => { const user = userEvent.setup(); const onChange = jest.fn(); - render( + await render( <FontSizePicker fontSizes={ fontSizes } onChange={ onChange } /> ); await user.click( screen.getByRole( 'radio', { name: 'Medium' } ) ); @@ -422,8 +425,8 @@ describe( 'FontSizePicker', () => { }, ]; - it( 'displays a toggle group control with t-shirt sizes', () => { - render( <FontSizePicker fontSizes={ fontSizes } /> ); + it( 'displays a toggle group control with t-shirt sizes', async () => { + await render( <FontSizePicker fontSizes={ fontSizes } /> ); const options = screen.getAllByRole( 'radio' ); expect( options ).toHaveLength( 4 ); expect( options[ 0 ] ).toHaveTextContent( 'S' ); @@ -447,8 +450,8 @@ describe( 'FontSizePicker', () => { }, ] )( 'displays $expectedLabel as label when value is $value', - ( { value, expectedLabel } ) => { - render( + async ( { value, expectedLabel } ) => { + await render( <FontSizePicker fontSizes={ fontSizes } value={ value } /> ); expect( screen.getByLabelText( expectedLabel ) ).toBeVisible(); @@ -471,7 +474,7 @@ describe( 'FontSizePicker', () => { async ( { radio, expectedArguments } ) => { const user = userEvent.setup(); const onChange = jest.fn(); - render( + await render( <FontSizePicker fontSizes={ fontSizes } onChange={ onChange } @@ -490,8 +493,8 @@ describe( 'FontSizePicker', () => { } ); function commonToggleGroupTests( fontSizes: FontSize[] ) { - it( 'defaults to M when value is 16px', () => { - render( + it( 'defaults to M when value is 16px', async () => { + await render( <FontSizePicker fontSizes={ fontSizes } value={ fontSizes[ 0 ].size } @@ -504,8 +507,8 @@ describe( 'FontSizePicker', () => { test.each( [ undefined, '' ] )( 'has no selection when value is %p', - ( value ) => { - render( + async ( value ) => { + await render( <FontSizePicker fontSizes={ fontSizes } value={ value } /> ); expect( screen.getByRole( 'radiogroup' ) ).toBeVisible(); @@ -520,7 +523,7 @@ describe( 'FontSizePicker', () => { it( 'shows custom input when Custom is selected', async () => { const user = userEvent.setup(); const onChange = jest.fn(); - render( + await render( <FontSizePicker fontSizes={ fontSizes } onChange={ onChange } /> ); await user.click( @@ -535,13 +538,15 @@ describe( 'FontSizePicker', () => { } function commonTests( fontSizes: FontSize[] ) { - it( 'shows custom input when value is unknown', () => { - render( <FontSizePicker fontSizes={ fontSizes } value="3px" /> ); + it( 'shows custom input when value is unknown', async () => { + await render( + <FontSizePicker fontSizes={ fontSizes } value="3px" /> + ); expect( screen.getByLabelText( 'Custom' ) ).toBeVisible(); } ); - it( 'hides custom input when disableCustomFontSizes is set to `true` with a custom font size', () => { - const { rerender } = render( + it( 'hides custom input when disableCustomFontSizes is set to `true` with a custom font size', async () => { + const { rerender } = await render( <FontSizePicker fontSizes={ fontSizes } value="3px" /> ); expect( screen.getByLabelText( 'Custom' ) ).toBeVisible(); @@ -558,8 +563,8 @@ describe( 'FontSizePicker', () => { ).not.toBeInTheDocument(); } ); - it( "doesn't hide custom input when the selected font size is a predef", () => { - const { rerender } = render( + it( "doesn't hide custom input when the selected font size is a predef", async () => { + const { rerender } = await render( <FontSizePicker fontSizes={ fontSizes } value="3px" /> ); expect( screen.getByLabelText( 'Custom' ) ).toBeVisible(); @@ -576,7 +581,7 @@ describe( 'FontSizePicker', () => { it( 'allows custom values by default', async () => { const user = userEvent.setup(); const onChange = jest.fn(); - render( + await render( <FontSizePicker fontSizes={ fontSizes } onChange={ onChange } /> ); await user.click( @@ -590,7 +595,9 @@ describe( 'FontSizePicker', () => { it( 'allows switching between custom and predef inputs when pressing the dedicated toggle', async () => { const user = userEvent.setup(); - render( <ControlledFontSizePicker fontSizes={ fontSizes } /> ); + await render( + <ControlledFontSizePicker fontSizes={ fontSizes } /> + ); await user.click( screen.getByRole( 'button', { name: 'Set custom size' } ) @@ -607,8 +614,8 @@ describe( 'FontSizePicker', () => { ).not.toBeInTheDocument(); } ); - it( 'does not allow custom values when disableCustomFontSizes is set', () => { - render( + it( 'does not allow custom values when disableCustomFontSizes is set', async () => { + await render( <FontSizePicker fontSizes={ fontSizes } disableCustomFontSizes @@ -621,7 +628,7 @@ describe( 'FontSizePicker', () => { it( 'does not display a slider by default', async () => { const user = userEvent.setup(); - render( <FontSizePicker fontSizes={ fontSizes } /> ); + await render( <FontSizePicker fontSizes={ fontSizes } /> ); await user.click( screen.getByRole( 'button', { name: 'Set custom size' } ) ); @@ -633,7 +640,7 @@ describe( 'FontSizePicker', () => { it( 'allows a slider to be used when withSlider is set', async () => { const user = userEvent.setup(); const onChange = jest.fn(); - render( + await render( <FontSizePicker fontSizes={ fontSizes } withSlider @@ -654,7 +661,7 @@ describe( 'FontSizePicker', () => { it( 'allows reset by default', async () => { const user = userEvent.setup(); const onChange = jest.fn(); - render( + await render( <FontSizePicker fontSizes={ fontSizes } value={ fontSizes[ 0 ].size } @@ -671,7 +678,7 @@ describe( 'FontSizePicker', () => { it( 'does not allow reset when withReset is false', async () => { const user = userEvent.setup(); - render( + await render( <FontSizePicker fontSizes={ fontSizes } value={ fontSizes[ 0 ].size } @@ -689,7 +696,7 @@ describe( 'FontSizePicker', () => { it( 'applies custom units to custom font size control', async () => { const user = userEvent.setup(); - render( + await render( <FontSizePicker fontSizes={ fontSizes } value={ fontSizes[ 0 ].size } diff --git a/packages/components/src/tabs/test/index.tsx b/packages/components/src/tabs/test/index.tsx index bbb7f591d0ffc7..382163f69e8e36 100644 --- a/packages/components/src/tabs/test/index.tsx +++ b/packages/components/src/tabs/test/index.tsx @@ -1,8 +1,9 @@ /** * External dependencies */ -import { render, screen, waitFor } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; import { press, click, sleep } from '@ariakit/test'; +import { render } from '@ariakit/test/react'; /** * WordPress dependencies @@ -159,7 +160,7 @@ describe( 'Tabs', () => { describe( 'Accessibility and semantics', () => { it( 'should use the correct aria attributes', async () => { - render( <UncontrolledTabs tabs={ TABS } /> ); + await render( <UncontrolledTabs tabs={ TABS } /> ); const tabList = screen.getByRole( 'tablist' ); const allTabs = screen.getAllByRole( 'tab' ); @@ -188,7 +189,7 @@ describe( 'Tabs', () => { } ); describe( 'Focus Behavior', () => { it( 'should focus on the related TabPanel when pressing the Tab key', async () => { - render( <UncontrolledTabs tabs={ TABS } /> ); + await render( <UncontrolledTabs tabs={ TABS } /> ); const selectedTabPanel = await screen.findByRole( 'tabpanel' ); @@ -221,7 +222,7 @@ describe( 'Tabs', () => { : tabObj ); - render( + await render( <UncontrolledTabs tabs={ TABS_WITH_ALPHA_FOCUSABLE_FALSE } /> ); @@ -256,7 +257,7 @@ describe( 'Tabs', () => { : tabObj ); - render( + await render( <ControlledTabs tabs={ TABS_WITH_ALPHA_DISABLED } selectedTabId={ null } @@ -284,7 +285,7 @@ describe( 'Tabs', () => { describe( 'Tab Attributes', () => { it( "should apply the tab's `className` to the tab button", async () => { - render( <UncontrolledTabs tabs={ TABS } /> ); + await render( <UncontrolledTabs tabs={ TABS } /> ); expect( await screen.findByRole( 'tab', { name: 'Alpha' } ) @@ -302,7 +303,7 @@ describe( 'Tabs', () => { it( 'defaults to automatic tab activation (pointer clicks)', async () => { const mockOnSelect = jest.fn(); - render( + await render( <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> ); @@ -335,7 +336,7 @@ describe( 'Tabs', () => { it( 'defaults to automatic tab activation (arrow keys)', async () => { const mockOnSelect = jest.fn(); - render( + await render( <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> ); @@ -371,7 +372,7 @@ describe( 'Tabs', () => { it( 'wraps around the last/first tab when using arrow keys', async () => { const mockOnSelect = jest.fn(); - render( + await render( <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> ); @@ -405,7 +406,7 @@ describe( 'Tabs', () => { it( 'should not move tab selection when pressing the up/down arrow keys, unless the orientation is changed to `vertical`', async () => { const mockOnSelect = jest.fn(); - const { rerender } = render( + const { rerender } = await render( <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> ); @@ -437,7 +438,7 @@ describe( 'Tabs', () => { // Change orientation to `vertical`. When the orientation is vertical, // left/right arrow keys are replaced by up/down arrow keys. - rerender( + await rerender( <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } @@ -502,7 +503,7 @@ describe( 'Tabs', () => { : tabObj ); - render( + await render( <UncontrolledTabs tabs={ TABS_WITH_DELTA_DISABLED } onSelect={ mockOnSelect } @@ -556,7 +557,7 @@ describe( 'Tabs', () => { } ); it( 'should not focus the next tab when the Tab key is pressed', async () => { - render( <UncontrolledTabs tabs={ TABS } /> ); + await render( <UncontrolledTabs tabs={ TABS } /> ); // Tab should initially focus the first tab in the tablist, which // is Alpha. @@ -581,7 +582,7 @@ describe( 'Tabs', () => { it( 'switches to manual tab activation when the `selectOnMove` prop is set to `false`', async () => { const mockOnSelect = jest.fn(); - render( + await render( <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } @@ -638,7 +639,7 @@ describe( 'Tabs', () => { describe( 'Uncontrolled mode', () => { describe( 'Without `defaultTabId` prop', () => { it( 'should render first tab', async () => { - render( <UncontrolledTabs tabs={ TABS } /> ); + await render( <UncontrolledTabs tabs={ TABS } /> ); expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( @@ -646,12 +647,12 @@ describe( 'Tabs', () => { ).toBeInTheDocument(); } ); it( 'should fall back to first enabled tab if the active tab is removed', async () => { - const { rerender } = render( + const { rerender } = await render( <UncontrolledTabs tabs={ TABS } /> ); // Remove first item from `TABS` array - rerender( <UncontrolledTabs tabs={ TABS.slice( 1 ) } /> ); + await rerender( <UncontrolledTabs tabs={ TABS.slice( 1 ) } /> ); expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); } ); it( 'should not load any tab if the active tab is removed and there are no enabled tabs', async () => { @@ -667,13 +668,13 @@ describe( 'Tabs', () => { : tabObj ); - const { rerender } = render( + const { rerender } = await render( <UncontrolledTabs tabs={ TABS_WITH_BETA_GAMMA_DISABLED } /> ); expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); // Remove alpha - rerender( + await rerender( <UncontrolledTabs tabs={ TABS_WITH_BETA_GAMMA_DISABLED.slice( 1 ) } /> @@ -695,15 +696,15 @@ describe( 'Tabs', () => { describe( 'With `defaultTabId`', () => { it( 'should render the tab set by `defaultTabId` prop', async () => { - render( + await render( <UncontrolledTabs tabs={ TABS } defaultTabId="beta" /> ); expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); } ); - it( 'should not select a tab when `defaultTabId` does not match any known tab', () => { - render( + it( 'should not select a tab when `defaultTabId` does not match any known tab', async () => { + await render( <UncontrolledTabs tabs={ TABS } defaultTabId="does-not-exist" @@ -721,11 +722,11 @@ describe( 'Tabs', () => { ).not.toBeInTheDocument(); } ); it( 'should not change tabs when defaultTabId is changed', async () => { - const { rerender } = render( + const { rerender } = await render( <UncontrolledTabs tabs={ TABS } defaultTabId="beta" /> ); - rerender( + await rerender( <UncontrolledTabs tabs={ TABS } defaultTabId="alpha" /> ); @@ -735,7 +736,7 @@ describe( 'Tabs', () => { it( 'should fall back to the tab associated to `defaultTabId` if the currently active tab is removed', async () => { const mockOnSelect = jest.fn(); - const { rerender } = render( + const { rerender } = await render( <UncontrolledTabs tabs={ TABS } defaultTabId="gamma" @@ -749,7 +750,7 @@ describe( 'Tabs', () => { expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); - rerender( + await rerender( <UncontrolledTabs tabs={ TABS.slice( 1 ) } defaultTabId="gamma" @@ -763,7 +764,7 @@ describe( 'Tabs', () => { it( 'should fall back to the tab associated to `defaultTabId` if the currently active tab becomes disabled', async () => { const mockOnSelect = jest.fn(); - const { rerender } = render( + const { rerender } = await render( <UncontrolledTabs tabs={ TABS } defaultTabId="gamma" @@ -789,7 +790,7 @@ describe( 'Tabs', () => { : tabObj ); - rerender( + await rerender( <UncontrolledTabs tabs={ TABS_WITH_ALPHA_DISABLED } defaultTabId="gamma" @@ -801,14 +802,14 @@ describe( 'Tabs', () => { } ); it( 'should have no active tabs when the tab associated to `defaultTabId` is removed while being the active tab', async () => { - const { rerender } = render( + const { rerender } = await render( <UncontrolledTabs tabs={ TABS } defaultTabId="gamma" /> ); expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); // Remove gamma - rerender( + await rerender( <UncontrolledTabs tabs={ TABS.slice( 0, 2 ) } defaultTabId="gamma" @@ -827,7 +828,7 @@ describe( 'Tabs', () => { } ); it( 'waits for the tab with the `defaultTabId` to be present in the `tabs` array before selecting it', async () => { - const { rerender } = render( + const { rerender } = await render( <UncontrolledTabs tabs={ TABS } defaultTabId="delta" /> ); @@ -836,7 +837,7 @@ describe( 'Tabs', () => { screen.queryByRole( 'tab', { selected: true } ) ).not.toBeInTheDocument(); - rerender( + await rerender( <UncontrolledTabs tabs={ TABS_WITH_DELTA } defaultTabId="delta" @@ -864,7 +865,7 @@ describe( 'Tabs', () => { : tabObj ); - render( + await render( <UncontrolledTabs tabs={ TABS_WITH_DELTA_DISABLED } onSelect={ mockOnSelect } @@ -913,7 +914,7 @@ describe( 'Tabs', () => { : tabObj ); - const { rerender } = render( + const { rerender } = await render( <UncontrolledTabs tabs={ TABS_WITH_ALPHA_DISABLED } /> ); @@ -922,7 +923,7 @@ describe( 'Tabs', () => { expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); // Re-enable all tabs - rerender( <UncontrolledTabs tabs={ TABS } /> ); + await rerender( <UncontrolledTabs tabs={ TABS } /> ); // Even if the initial tab becomes enabled again, the selected // tab doesn't change. @@ -941,7 +942,7 @@ describe( 'Tabs', () => { } : tabObj ); - const { rerender } = render( + const { rerender } = await render( <UncontrolledTabs tabs={ TABS_ONLY_GAMMA_ENABLED } defaultTabId="beta" @@ -953,7 +954,7 @@ describe( 'Tabs', () => { expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); // Re-enable all tabs - rerender( + await rerender( <UncontrolledTabs tabs={ TABS } defaultTabId="beta" /> ); @@ -964,7 +965,7 @@ describe( 'Tabs', () => { it( 'should select the first enabled tab when the selected tab becomes disabled', async () => { const mockOnSelect = jest.fn(); - const { rerender } = render( + const { rerender } = await render( <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> ); @@ -985,7 +986,7 @@ describe( 'Tabs', () => { ); // Disable alpha - rerender( + await rerender( <UncontrolledTabs tabs={ TABS_WITH_ALPHA_DISABLED } onSelect={ mockOnSelect } @@ -997,7 +998,7 @@ describe( 'Tabs', () => { expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' ); // Re-enable all tabs - rerender( + await rerender( <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> ); @@ -1009,7 +1010,7 @@ describe( 'Tabs', () => { it( 'should select the first enabled tab when the tab associated to `defaultTabId` becomes disabled while being the active tab', async () => { const mockOnSelect = jest.fn(); - const { rerender } = render( + const { rerender } = await render( <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } @@ -1032,7 +1033,7 @@ describe( 'Tabs', () => { ); // Disable gamma - rerender( + await rerender( <UncontrolledTabs tabs={ TABS_WITH_GAMMA_DISABLED } onSelect={ mockOnSelect } @@ -1045,7 +1046,7 @@ describe( 'Tabs', () => { expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); // Re-enable all tabs - rerender( + await rerender( <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } @@ -1063,7 +1064,9 @@ describe( 'Tabs', () => { describe( 'Controlled mode', () => { it( 'should render the tab specified by the `selectedTabId` prop', async () => { - render( <ControlledTabs tabs={ TABS } selectedTabId="beta" /> ); + await render( + <ControlledTabs tabs={ TABS } selectedTabId="beta" /> + ); expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); expect( @@ -1071,7 +1074,7 @@ describe( 'Tabs', () => { ).toBeInTheDocument(); } ); it( 'should render the specified `selectedTabId`, and ignore the `defaultTabId` prop', async () => { - render( + await render( <ControlledTabs tabs={ TABS } selectedTabId="gamma" @@ -1082,7 +1085,7 @@ describe( 'Tabs', () => { expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); } ); it( 'should not render any tab if `selectedTabId` does not match any known tab', async () => { - render( + await render( <ControlledTabs tabs={ TABS_WITH_DELTA } selectedTabId="does-not-exist" @@ -1097,12 +1100,12 @@ describe( 'Tabs', () => { expect( screen.queryByRole( 'tabpanel' ) ).not.toBeInTheDocument(); } ); it( 'should not render any tab if the active tab is removed', async () => { - const { rerender } = render( + const { rerender } = await render( <ControlledTabs tabs={ TABS } selectedTabId="beta" /> ); // Remove beta - rerender( + await rerender( <ControlledTabs tabs={ TABS.filter( ( tab ) => tab.tabId !== 'beta' ) } selectedTabId="beta" @@ -1123,7 +1126,9 @@ describe( 'Tabs', () => { expect( screen.queryByRole( 'tabpanel' ) ).not.toBeInTheDocument(); // Restore beta - rerender( <ControlledTabs tabs={ TABS } selectedTabId="beta" /> ); + await rerender( + <ControlledTabs tabs={ TABS } selectedTabId="beta" /> + ); // No tab should be selected i.e. it doesn't reselect the previously // removed tab. @@ -1149,7 +1154,7 @@ describe( 'Tabs', () => { : tabObj ); - render( + await render( <ControlledTabs tabs={ TABS_WITH_DELTA_WITH_BETA_DISABLED } selectedTabId="beta" @@ -1168,7 +1173,7 @@ describe( 'Tabs', () => { ).not.toBeInTheDocument(); } ); it( 'should not render any tab when the selected tab becomes disabled', async () => { - const { rerender } = render( + const { rerender } = await render( <ControlledTabs tabs={ TABS } selectedTabId="beta" /> ); @@ -1186,7 +1191,7 @@ describe( 'Tabs', () => { : tabObj ); - rerender( + await rerender( <ControlledTabs tabs={ TABS_WITH_BETA_DISABLED } selectedTabId="beta" @@ -1206,7 +1211,7 @@ describe( 'Tabs', () => { ).not.toBeInTheDocument(); // re-enable all tabs - rerender( + await rerender( <ControlledTabs tabs={ TABS } selectedTabId="beta" /> ); @@ -1226,7 +1231,7 @@ describe( 'Tabs', () => { 'and `selectOnMove` is %s', ( selectOnMove ) => { it( 'should continue to handle arrow key navigation properly', async () => { - const { rerender } = render( + const { rerender } = await render( <ControlledTabs tabs={ TABS } selectedTabId="beta" @@ -1249,7 +1254,7 @@ describe( 'Tabs', () => { ); expect( await getSelectedTab() ).toHaveFocus(); - rerender( + await rerender( <ControlledTabs tabs={ TABS } selectedTabId="gamma" @@ -1275,7 +1280,7 @@ describe( 'Tabs', () => { } ); it( 'should focus the correct tab when tabbing out and back into the tablist', async () => { - const { rerender } = render( + const { rerender } = await render( <> <button>Focus me</button> <ControlledTabs @@ -1296,7 +1301,7 @@ describe( 'Tabs', () => { ); expect( await getSelectedTab() ).toHaveFocus(); - rerender( + await rerender( <> <button>Focus me</button> <ControlledTabs @@ -1344,7 +1349,9 @@ describe( 'Tabs', () => { describe( 'When `selectOnMove` is `true`', () => { it( 'should automatically select a newly focused tab', async () => { - render( <ControlledTabs tabs={ TABS } selectedTabId="beta" /> ); + await render( + <ControlledTabs tabs={ TABS } selectedTabId="beta" /> + ); await sleep(); await press.Tab(); @@ -1361,7 +1368,7 @@ describe( 'Tabs', () => { } ); describe( 'When `selectOnMove` is `false`', () => { it( 'should apply focus without automatically changing the selected tab', async () => { - render( + await render( <ControlledTabs tabs={ TABS } selectedTabId="beta" @@ -1407,7 +1414,7 @@ describe( 'Tabs', () => { it( 'should associate each `Tab` with the correct `TabPanel`, even if they are not rendered in the same order', async () => { const TABS_WITH_DELTA_REVERSED = [ ...TABS_WITH_DELTA ].reverse(); - render( + await render( <Tabs> <Tabs.TabList> { TABS_WITH_DELTA.map( ( tabObj ) => ( diff --git a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap index 908e15927e3b86..81afc7ac67b05f 100644 --- a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap +++ b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap @@ -258,7 +258,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = aria-checked="true" aria-label="Uppercase" class="emotion-12 components-toggle-group-control-option-base" - data-active-item="" + data-active-item="true" data-value="uppercase" data-wp-c16t="true" data-wp-component="ToggleGroupControlOptionBase" @@ -818,7 +818,7 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] aria-checked="true" aria-label="Uppercase" class="emotion-12 components-toggle-group-control-option-base" - data-active-item="" + data-active-item="true" data-value="uppercase" data-wp-c16t="true" data-wp-component="ToggleGroupControlOptionBase" diff --git a/packages/components/src/tooltip/index.tsx b/packages/components/src/tooltip/index.tsx index 1b6285a4ac09c4..e832119393282a 100644 --- a/packages/components/src/tooltip/index.tsx +++ b/packages/components/src/tooltip/index.tsx @@ -13,6 +13,7 @@ import { useContext, createContext, forwardRef, + cloneElement, } from '@wordpress/element'; import deprecated from '@wordpress/deprecated'; @@ -92,6 +93,7 @@ function UnforwardedTooltip( placement: computedPlacement, showTimeout: delay, } ); + const mounted = tooltipStore.useState( 'mounted' ); if ( isNestedInTooltip ) { return isOnlyChild ? ( @@ -101,12 +103,24 @@ function UnforwardedTooltip( ); } + // TODO: this is a temporary workaround to minimize the effects of the + // Ariakit upgrade. Ariakit doesn't pass the `aria-describedby` prop to + // the tooltip anchor anymore since 0.4.0, so we need to add it manually. + // See: https://github.com/WordPress/gutenberg/pull/64066 + function addDescribedById( element: React.ReactElement ) { + return describedById && mounted + ? cloneElement( element, { 'aria-describedby': describedById } ) + : element; + } + return ( <TooltipInternalContext.Provider value={ CONTEXT_VALUE }> <Ariakit.TooltipAnchor onClick={ hideOnClick ? tooltipStore.hide : undefined } store={ tooltipStore } - render={ isOnlyChild ? children : undefined } + render={ + isOnlyChild ? addDescribedById( children ) : undefined + } ref={ ref } > { isOnlyChild ? undefined : children } @@ -135,7 +149,6 @@ function UnforwardedTooltip( </TooltipInternalContext.Provider> ); } - export const Tooltip = forwardRef( UnforwardedTooltip ); export default Tooltip; diff --git a/packages/components/src/tooltip/test/utils/index.tsx b/packages/components/src/tooltip/test/utils/index.tsx index 01b0931c1a7900..1e32a10f71bd20 100644 --- a/packages/components/src/tooltip/test/utils/index.tsx +++ b/packages/components/src/tooltip/test/utils/index.tsx @@ -1,7 +1,7 @@ /** * External dependencies */ -import type { UserEvent } from '@testing-library/user-event/dist/types/setup/setup'; +import { click, press } from '@ariakit/test'; // TODO: may need to be tested with Playwright; further context: // https://github.com/WordPress/gutenberg/pull/52133#issuecomment-1613691258 @@ -13,8 +13,8 @@ import type { UserEvent } from '@testing-library/user-event/dist/types/setup/set * to avoid leaking into other tests * */ -export default async function cleanupTooltip( user: UserEvent ) { - await user.tab(); - await user.tab(); - await user.click( document.body ); +export default async function cleanupTooltip() { + await press.Tab(); + await press.Tab(); + await click( document.body ); } diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 2fc569b44f634c..881d666aa0613b 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,20 +2,24 @@ ## Unreleased +## Internal + +- Upgraded `@ariakit/react` (v0.4.7) ([#64066](https://github.com/WordPress/gutenberg/pull/64066)). + ## 4.0.0 (2024-07-24) ### Breaking Changes -- `onSelectionChange` prop has been renamed to `onChangeSelection` and its argument has been updated to be a list of ids. -- `setSelection` prop has been removed. Please use `onChangeSelection` instead. -- `header` field property has been renamed to `label`. +- `onSelectionChange` prop has been renamed to `onChangeSelection` and its argument has been updated to be a list of ids. +- `setSelection` prop has been removed. Please use `onChangeSelection` instead. +- `header` field property has been renamed to `label`. ## 3.0.0 (2024-07-10) ### Breaking Changes -- Replace the `hiddenFields` property in the view prop of `DataViews` with a `fields` property that accepts an array of visible fields instead. -- Replace the `supportedLayouts` prop in the `DataViews` component with a `defaultLayouts` prop that accepts an object whose keys are the layout names and values are the default view objects for these layouts. +- Replace the `hiddenFields` property in the view prop of `DataViews` with a `fields` property that accepts an array of visible fields instead. +- Replace the `supportedLayouts` prop in the `DataViews` component with a `defaultLayouts` prop that accepts an object whose keys are the layout names and values are the default view objects for these layouts. ### New features diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index 238e2bdd5be8bc..d95192957a1a43 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -28,7 +28,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@ariakit/react": "^0.3.12", + "@ariakit/react": "^0.4.7", "@babel/runtime": "^7.16.0", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", From 7f80f6e0195c42f4d22554e3e29641152e7d0e59 Mon Sep 17 00:00:00 2001 From: Nick Diego <nick.diego@automattic.com> Date: Thu, 1 Aug 2024 11:05:50 -0500 Subject: [PATCH 0218/1908] Docs: Add documentation for `render_block` and `register_block_type_args` to Block Filters (#64118) Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: juanmaguitar <juanmaguitar@git.wordpress.org> --- .../reference-guides/filters/block-filters.md | 194 ++++++++++++++---- 1 file changed, 152 insertions(+), 42 deletions(-) diff --git a/docs/reference-guides/filters/block-filters.md b/docs/reference-guides/filters/block-filters.md index ee100431eb512e..e7a31c1e3bbc83 100644 --- a/docs/reference-guides/filters/block-filters.md +++ b/docs/reference-guides/filters/block-filters.md @@ -4,15 +4,15 @@ WordPress exposes several APIs that allow you to modify the behavior of existing ## Registration -The following filters are available to extend block settings during their registration. +Blocks in WordPress are typically registered on both the server and client side using `block.json`` metadata. You can use the following filters to modify or extend block settings during their registration on the server with PHP and on the client with JavaScript. To learn more, refer to the [block registration](https://developer.wordpress.org/block-editor/getting-started/fundamentals/registration-of-a-block/) guide. ### `block_type_metadata` Filters the raw metadata loaded from the `block.json` file when registering a block type on the server with PHP. It allows modifications to be applied before the metadata gets processed. -The filter takes one parameter: +The callback function for this filter receives one parameter: -- `$metadata` (`array`) – metadata loaded from `block.json` for registering a block type. +- `$metadata` (`array`): Metadata loaded from `block.json` for registering a block type. The following example sets the `apiVersion` of all blocks to `2`. @@ -28,33 +28,33 @@ Here's a more robust example that disables background color and gradient support ```php function example_disable_heading_background_color_and_gradients( $metadata ) { - - // Only apply the filter to Heading blocks. - if ( ! isset( $metadata['name'] ) || 'core/heading' !== $metadata['name'] ) { - return $metadata; - } - - // Check if 'supports' key exists. - if ( isset( $metadata['supports'] ) && isset( $metadata['supports']['color'] ) ) { - - // Remove Background color and Gradients support. - $metadata['supports']['color']['background'] = false; - $metadata['supports']['color']['gradients'] = false; - } - - return $metadata; + + // Only apply the filter to Heading blocks. + if ( ! isset( $metadata['name'] ) || 'core/heading' !== $metadata['name'] ) { + return $metadata; + } + + // Check if 'supports' key exists. + if ( isset( $metadata['supports'] ) && isset( $metadata['supports']['color'] ) ) { + + // Remove Background color and Gradients support. + $metadata['supports']['color']['background'] = false; + $metadata['supports']['color']['gradients'] = false; + } + + return $metadata; } add_filter( 'block_type_metadata', 'example_disable_heading_background_color_and_gradients' ); ``` ### `block_type_metadata_settings` -Filters the settings determined from the processed block type metadata. It makes it possible to apply custom modifications using the block metadata that isn’t handled by default. +Filters the settings determined from the processed block type metadata. It makes it possible to apply custom modifications using the block metadata that isn't handled by default. -The filter takes two parameters: +The callback function for this filter receives two parameters: -- `$settings` (`array`) – Array of determined settings for registering a block type. -- `$metadata` (`array`) – Metadata loaded from the `block.json` file. +- `$settings` (`array`): Array of determined settings for registering a block type. +- `$metadata` (`array`): Metadata loaded from the `block.json` file. The following example increases the `apiVersion` for all blocks by `1`. @@ -66,6 +66,45 @@ function example_filter_metadata_registration( $settings, $metadata ) { add_filter( 'block_type_metadata_settings', 'example_filter_metadata_registration', 10, 2 ); ``` +### `register_block_type_args` + +Filters a block's arguments array (`$args`) right before the block type is officially registered on the server. + +The callback function for this filter receives two parameters: + +- `$args` (`array`): Array of arguments for registering a block type. +- `$block_type` (`string`): Block type name including namespace. + +`register_block_type_args` is the most low-level PHP filter available, and it will work for every block registered on the server. All settings defined on the server are propagated to the client with higher priority than those set in the client. + +The following code will disable the color controls for Paragraph, Heading, List, and List Item blocks. + +```php +function example_disable_color_for_specific_blocks( $args, $block_type ) { + + // List of block types to modify. + $block_types_to_modify = [ + 'core/paragraph', + 'core/heading', + 'core/list', + 'core/list-item' + ]; + + // Check if the current block type is in the list. + if ( in_array( $block_type, $block_types_to_modify, true ) ) { + // Disable color controls. + $args['supports']['color'] = array( + 'text' => false, + 'background' => false, + 'link' => false, + ); + } + + return $args; +} +add_filter( 'register_block_type_args', 'example_disable_color_for_specific_blocks', 10, 2 ); +``` + ### `blocks.registerBlockType` Used to filter the block settings when registering the block on the client with JavaScript. It receives the block settings, the name of the registered block, and either null or the deprecated block settings (when applied to a registered deprecation) as arguments. This filter is also applied to each of a block's deprecated settings. @@ -94,31 +133,100 @@ wp.hooks.addFilter( ); ``` -## Block Editor +## Front end + +The following PHP filters are available to change the output of a block on the front end. + +### `render_block` + +Filters the font-end content of any block. This filter has no impact on the behavior of blocks in the Editor. + +The callback function for this filter receives three parameters: + +- `$block_content` (`string`): The block content. +- `block` (`array`): The full block, including name and attributes. +- `$instance` (`WP_Block`): The block instance. + +In the following example, the class `example-class` is added to all Paragraph blocks on the front end. Here the [HTML API](https://make.wordpress.org/core/2023/03/07/introducing-the-html-api-in-wordpress-6-2/) is used to easily add the class instead of relying on regex. + +```php +function example_add_custom_class_to_paragraph_block( $block_content, $block ) { + + // Check if the block is a Paragraph block. + if ( 'core/paragraph' === $block['blockName'] ) { + + // Add the custom class to the block content using the HTML API. + $processor = new WP_HTML_Tag_Processor( $block_content ); + + if ( $processor->next_tag( 'p' ) ) { + $processor->add_class( 'example-class' ); + } + + return $processor->get_updated_html(); + } + + return $block_content; +} +add_filter( 'render_block', 'example_add_custom_class_to_paragraph_block', 10, 2 ); +``` + +### `render_block_{namespace/block}` + +Filters the font-end content of the defined block. This is just a simpler form of `render_block` when you only need to modify a specific block type. + +The callback function for this filter receives three parameters: + +- `$block_content` (`string`): The block content. +- `block` (`array`): The full block, including name and attributes. +- `$instance` (`WP_Block`): The block instance. + +In the following example, the class `example-class` is added to all Paragraph blocks on the front end. Notice that compared to the `render_block` example above, you no longer need to check the block type before modifying the content. Again, the [HTML API](https://make.wordpress.org/core/2023/03/07/introducing-the-html-api-in-wordpress-6-2/) is used instead of regex. + +```php +function example_add_custom_class_to_paragraph_block( $block_content, $block ) { + + // Add the custom class to the block content using the HTML API. + $processor = new WP_HTML_Tag_Processor( $block_content ); + + if ( $processor->next_tag( 'p' ) ) { + $processor->add_class( 'example-class' ); + } + + return $processor->get_updated_html(); +} +add_filter( 'render_block_core/paragraph', 'example_add_custom_class_to_paragraph_block', 10, 2 ); +``` + +## Editor -The following filters are available to change the behavior of blocks while editing in the block editor. +The following JavaScript filters are available to change the behavior of blocks while editing in the Editor. ### `blocks.getSaveElement` -A filter that applies to the result of a block's `save` function. This filter is used to replace or extend the element, for example using `React.cloneElement` to modify the element's props or replace its children, or returning an entirely new element. +A filter that applies to the result of a block's `save` function. This filter is used to replace or extend the element, for example using `React.cloneElement` to modify the element's props, replace its children, or return an entirely new element. -The filter's callback receives an element, a block-type definition object, and the block attributes as arguments. It should return an element. +The callback function for this filter receives three parameters: -The following example wraps a Cover block in an outer container div. +- `element` (`Object`): The element to be modified and returned. +- `blockType` (`Object`): A block-type definition object. +- `attributes` (`Object`): The block's attributes. + +The following example wraps a Cover block in an outer container `div`. ```js function wrapCoverBlockInContainer( element, blockType, attributes ) { - // skip if element is undefined + + // Skip if element is undefined. if ( ! element ) { return; } - // only apply to cover blocks + // Only apply to Cover blocks. if ( blockType.name !== 'core/cover' ) { return element; } - // return the element wrapped in a div + // Return the element wrapped in a div. return <div className="cover-block-wrapper">{ element }</div>; } @@ -131,9 +239,13 @@ wp.hooks.addFilter( ### `blocks.getSaveContent.extraProps` -A filter that applies to all blocks returning a WP Element in the `save` function. This filter is used to add extra props to the root element of the `save` function. For example: to add a className, an id, or any valid prop for this element. +A filter that applies to all blocks returning a WP Element in the `save` function. This filter is used to add extra props to the root element of the `save` function. For example, you could add a className, an id, or any valid prop for this element. + +The callback function for this filter receives three parameters: -The filter receives the current `save` element's props, a block type, and the block attributes as arguments. It should return a props object. +- `props` (`Object`): The current `save` element's props to be modified and returned. +- `blockType` (`Object`): A block-type definition object. +- `attributes` (`Object`): The block's attributes. The following example adds a red background by default to all blocks. @@ -152,7 +264,7 @@ wp.hooks.addFilter( ); ``` -_Note:_ A [block validation](/docs/reference-guides/block-api/block-edit-save.md#validation) error will occur if this filter modifies existing content the next time the post is edited. The editor verifies that the content stored in the post matches the content output by the `save()` function. +_Note:_ A [block validation](/docs/reference-guides/block-api/block-edit-save.md#validation) error will occur if this filter modifies existing content the next time the post is edited. The Editor verifies that the content stored in the post matches the content output by the `save()` function. To avoid this validation error, use `render_block` server-side to modify existing post content instead of this filter. See [render_block documentation](https://developer.wordpress.org/reference/hooks/render_block/). @@ -160,15 +272,13 @@ To avoid this validation error, use `render_block` server-side to modify existin Generated HTML classes for blocks follow the `wp-block-{name}` nomenclature. This filter allows to provide an alternative class name. -_Example:_ - ```js -// Our filter function +// Our filter function. function setBlockCustomClassName( className, blockName ) { return blockName === 'core/code' ? 'my-plugin-code' : className; } -// Adding the filter +// Adding the filter. wp.hooks.addFilter( 'blocks.getBlockDefaultClassName', 'my-plugin/set-block-custom-class-name', @@ -188,8 +298,7 @@ Called immediately after the default parsing of a block's attributes and before Used to modify the block's `edit` component. It receives the original block `BlockEdit` component and returns a new wrapped component. -_Example:_ - +The following example adds a new Inspector panel for all blocks. ```js const { createHigherOrderComponent } = wp.compose; @@ -216,13 +325,14 @@ wp.hooks.addFilter( ); ``` - Note that as this hook is run for _all blocks_, consuming it has the potential for performance regressions, particularly around block selection metrics. To mitigate this, consider whether any work you perform can be altered to run only under certain conditions. For example, suppose you are adding components that only need to render when the block is _selected_. In that case, you can use the block's "selected" state (`props.isSelected`) to conditionalize your rendering. +The following example adds a new Inspector panel for all blocks, but only when a block is selected. + ```js const withMyPluginControls = createHigherOrderComponent( ( BlockEdit ) => { return ( props ) => { @@ -244,7 +354,7 @@ const withMyPluginControls = createHigherOrderComponent( ( BlockEdit ) => { Used to modify the block's wrapper component containing the block's `edit` component and all toolbars. It receives the original `BlockListBlock` component and returns a new wrapped component. -The following example adds a unique class name. +The following example adds a unique class name to all blocks. ```js const { createHigherOrderComponent } = wp.compose; @@ -424,7 +534,7 @@ You can also display an icon with your block category by setting an `icon` attri You can also set a custom icon in SVG format. To do so, the icon should be rendered and set on the frontend, so it can make use of WordPress SVG, allowing mobile compatibility and making the icon more accessible. -To set an SVG icon for the category shown in the previous example, add the following example JavaScript code to the editor calling `wp.blocks.updateCategory` e.g: +To set an SVG icon for the category shown in the previous example, add the following example JavaScript code to the Editor calling `wp.blocks.updateCategory` e.g: ```js ( function () { From 1e4d4272cd5435060fef3287a84a3537af0e0473 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Thu, 1 Aug 2024 13:38:15 -0500 Subject: [PATCH 0219/1908] =?UTF-8?q?Revert=20"Remove=20unnecessary/incorr?= =?UTF-8?q?ect=20`unlock`=20call=20in=20`setEditorMode`=20action=20?= =?UTF-8?q?=E2=80=A6"=20(#64176)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 9186964684888b8385bdee11cb1c6dbcafedf8f2. --- packages/block-editor/src/store/actions.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 3a209a1267e288..f7da8fa14b382a 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -35,6 +35,7 @@ import { privateRemoveBlocks, } from './private-actions'; import { STORE_NAME } from './constants'; +import { unlock } from '../lock-unlock'; /** @typedef {import('../components/use-on-block-drop/types').WPDropOperation} WPDropOperation */ @@ -1673,9 +1674,9 @@ export const __unstableSetEditorMode = // When switching to zoom-out mode, we need to select the parent section if ( mode === 'zoom-out' ) { const firstSelectedClientId = select.getBlockSelectionStart(); - const { sectionRootClientId } = registry - .select( STORE_NAME ) - .getSettings(); + const { sectionRootClientId } = unlock( + registry.select( STORE_NAME ).getSettings() + ); if ( firstSelectedClientId ) { let sectionClientId; From 6581dfb8f1c605119db776f023a83d655209bfa8 Mon Sep 17 00:00:00 2001 From: Mikael Korpela <mikael@ihminen.org> Date: Thu, 1 Aug 2024 22:48:41 +0300 Subject: [PATCH 0220/1908] Icons: add new "send" icon (#64130) Design by: javierarce Co-authored-by: jasmussen <joen@automattic.com> Reviewed by: Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/icons/CHANGELOG.md | 4 ++++ packages/icons/src/index.js | 1 + packages/icons/src/library/send.js | 16 ++++++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 packages/icons/src/library/send.js diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index da4a4f1768fb19..4f279b5593e875 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### New Features + +- Add new `send` icon. + ## 10.4.0 (2024-07-24) ## 10.3.0 (2024-07-10) diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index faa193eb7b461d..9250f413a8572b 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -225,6 +225,7 @@ export { default as search } from './library/search'; export { default as seen } from './library/seen'; export { default as unseen } from './library/unseen'; export { default as scheduled } from './library/scheduled'; +export { default as send } from './library/send'; export { default as separator } from './library/separator'; export { default as settings } from './library/settings'; export { default as shadow } from './library/shadow'; diff --git a/packages/icons/src/library/send.js b/packages/icons/src/library/send.js new file mode 100644 index 00000000000000..9cd3d6ae5e4057 --- /dev/null +++ b/packages/icons/src/library/send.js @@ -0,0 +1,16 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const send = ( + <SVG viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <Path + fillRule="evenodd" + clipRule="evenodd" + d="M5.333 12.154c-1.03-.424-1.032-1.883-.002-2.31l12.261-5.085c1.03-.426 2.06.605 1.634 1.634l-5.084 12.262c-.427 1.03-1.886 1.027-2.31-.003l-1.896-4.603-4.603-1.895Zm6.061 1.498 1.594 3.87 3.87-9.334-5.464 5.463Zm4.403-6.524-9.333 3.87 3.87 1.593 5.463-5.463Z" + /> + </SVG> +); + +export default send; From c6d7b2f73f0af71284d8a6a745062f2afdc88a62 Mon Sep 17 00:00:00 2001 From: Christian Leucht <family.leucht@gmail.com> Date: Fri, 2 Aug 2024 05:38:32 +0200 Subject: [PATCH 0221/1908] Block categories - ensure that categories are unique by slug. (#62954) * blocks/store/reducer // ensure that categories are unique by slug. Block categories can be registered through backend by hooking into the "block_categories_all"-filter or through frontend by calling wp.blocks.setCategories(). Both require an array of WPBlockCategory elements. This change aims for making the categories: WPBlockCategory[] with unique entries by slug to avoid rendering in Block Inserter all Blocks duplicated. See also: #50061 * eslint * blocks/store/reducer.js // add test case for unique catgories by slug. ---- Co-authored-by: Chrico <chrico@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- packages/blocks/src/store/reducer.js | 7 ++++++- packages/blocks/src/store/test/reducer.js | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 0851fc2bede4ca..f1cfdcd04e3035 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -328,7 +328,12 @@ export const groupingBlockName = createBlockNameSetterReducer( export function categories( state = DEFAULT_CATEGORIES, action ) { switch ( action.type ) { case 'SET_CATEGORIES': - return action.categories || []; + // Ensure, that categories are unique by slug. + const uniqueCategories = new Map(); + ( action.categories || [] ).forEach( ( category ) => { + uniqueCategories.set( category.slug, category ); + } ); + return [ ...uniqueCategories.values() ]; case 'UPDATE_CATEGORY': { if ( ! action.category || diff --git a/packages/blocks/src/store/test/reducer.js b/packages/blocks/src/store/test/reducer.js index babaaad4e0e0d7..1a295f1efc30d7 100644 --- a/packages/blocks/src/store/test/reducer.js +++ b/packages/blocks/src/store/test/reducer.js @@ -420,6 +420,22 @@ describe( 'categories', () => { expect( state ).toEqual( [ { slug: 'wings', title: 'Wings' } ] ); } ); + it( 'should ensure, that categories are unique by slug', () => { + const original = deepFreeze( [ + { slug: 'chicken', title: 'Chicken' }, + ] ); + + const state = categories( original, { + type: 'SET_CATEGORIES', + categories: [ { slug: 'chicken', title: 'Another chicken' } ], + } ); + + expect( state ).toEqual( [ + { slug: 'chicken', title: 'Another chicken' }, + ] ); + expect( state.length ).toBe( 1 ); + } ); + it( 'should add the category icon', () => { const original = deepFreeze( [ { From a5282339f507a72eeec1c8e02b3dd16e2d6f48c8 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 2 Aug 2024 15:33:26 +1000 Subject: [PATCH 0222/1908] Theme JSON: Update core theme json resolver class use to Gutenberg version (#63981) * Theme JSON: Update core class use to Gutenberg version * Address nit Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: mukeshpanchal27 <mukesh27@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- lib/compat/wordpress-6.6/rest-api.php | 4 ++-- lib/experimental/posts/load.php | 2 +- packages/e2e-tests/plugins/delete-installed-fonts.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/compat/wordpress-6.6/rest-api.php b/lib/compat/wordpress-6.6/rest-api.php index 54eaaf28de82df..fee9c71b86c070 100644 --- a/lib/compat/wordpress-6.6/rest-api.php +++ b/lib/compat/wordpress-6.6/rest-api.php @@ -33,7 +33,7 @@ function wp_api_template_access_controller( $args, $post_type ) { /** * Adds the post classes to the REST API response. * - * @param array $post The response object data. + * @param array $post The response object data. * * @return array */ @@ -169,7 +169,7 @@ function gutenberg_block_editor_preload_paths_6_6( $paths, $context ) { if ( 'core/edit-post' === $context->name ) { $paths[] = '/wp/v2/global-styles/themes/' . get_stylesheet(); $paths[] = '/wp/v2/themes?context=edit&status=active'; - $paths[] = '/wp/v2/global-styles/' . WP_Theme_JSON_Resolver::get_user_global_styles_post_id() . '?context=edit'; + $paths[] = '/wp/v2/global-styles/' . WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id() . '?context=edit'; } return $paths; } diff --git a/lib/experimental/posts/load.php b/lib/experimental/posts/load.php index b702a374bd16db..7321392b11a25d 100644 --- a/lib/experimental/posts/load.php +++ b/lib/experimental/posts/load.php @@ -29,7 +29,7 @@ function gutenberg_posts_dashboard() { ); $editor_settings = get_block_editor_settings( $custom_settings, $block_editor_context ); - $active_global_styles_id = WP_Theme_JSON_Resolver::get_user_global_styles_post_id(); + $active_global_styles_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id(); $active_theme = get_stylesheet(); $preload_paths = array( diff --git a/packages/e2e-tests/plugins/delete-installed-fonts.php b/packages/e2e-tests/plugins/delete-installed-fonts.php index 5e547f76c338a8..871d19f82e635e 100644 --- a/packages/e2e-tests/plugins/delete-installed-fonts.php +++ b/packages/e2e-tests/plugins/delete-installed-fonts.php @@ -56,7 +56,7 @@ function gutenberg_delete_installed_fonts() { } // Delete any installed fonts from global styles. - $global_styles_post_id = WP_Theme_JSON_Resolver::get_user_global_styles_post_id(); + $global_styles_post_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id(); $request = new WP_REST_Request( 'POST', '/wp/v2/global-styles/' . $global_styles_post_id ); $request->set_body_params( array( 'settings' => array( 'typography' => array( 'fontFamilies' => array() ) ) ) ); From fac76e753e01098666627c493be2f865be5d7dd8 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 2 Aug 2024 16:18:51 +0900 Subject: [PATCH 0223/1908] Icons: Remove hardcoded color from sidesAxial and sidesBottom icons (#64174) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/icons/src/library/sides-axial.js | 7 ++----- packages/icons/src/library/sides-bottom.js | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/icons/src/library/sides-axial.js b/packages/icons/src/library/sides-axial.js index 660d3ac20853d1..df8bbd808aef51 100644 --- a/packages/icons/src/library/sides-axial.js +++ b/packages/icons/src/library/sides-axial.js @@ -6,12 +6,9 @@ import { SVG, Path } from '@wordpress/primitives'; const sidesAxial = ( <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <Path + fillRule="evenodd" + clipRule="evenodd" d="M8.2 5.3h8V3.8h-8v1.5zm0 14.5h8v-1.5h-8v1.5zm3.5-6.5h1v-1h-1v1zm1-6.5h-1v.5h1v-.5zm-1 4.5h1v-1h-1v1zm0-2h1v-1h-1v1zm0 7.5h1v-.5h-1v.5zm1-2.5h-1v1h1v-1zm-8.5 1.5h1.5v-8H4.2v8zm14.5-8v8h1.5v-8h-1.5zm-5 4.5v-1h-1v1h1zm-6.5 0h.5v-1h-.5v1zm3.5-1v1h1v-1h-1zm6 1h.5v-1h-.5v1zm-8-1v1h1v-1h-1zm6 0v1h1v-1h-1z" - style={ { - fill: '#1e1e1e', - fillRule: 'evenodd', - clipRule: 'evenodd', - } } /> </SVG> ); diff --git a/packages/icons/src/library/sides-bottom.js b/packages/icons/src/library/sides-bottom.js index 48cd1516e7c16b..2029b28b6a83e8 100644 --- a/packages/icons/src/library/sides-bottom.js +++ b/packages/icons/src/library/sides-bottom.js @@ -9,7 +9,7 @@ const sidesBottom = ( d="m7.5 6h9v-1.5h-9zm0 13.5h9v-1.5h-9zm-3-3h1.5v-9h-1.5zm13.5-9v9h1.5v-9z" style={ { opacity: 0.25 } } /> - <Path d="m16.5 19.5h-9v-1.5h9z" style={ { fill: '#1e1e1e' } } /> + <Path d="m16.5 19.5h-9v-1.5h9z" /> </SVG> ); From 324628c935588e6e736fc8079db0e667f165d1ec Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Fri, 2 Aug 2024 18:10:12 +1000 Subject: [PATCH 0224/1908] Global styles: consolidate theme.json ref and URI resolution (#64182) * Consolidate theme.json ref and URI resolution Add tests * Consolidate theme.json ref and URI resolution Add tests * Update packages/block-editor/src/components/global-styles/test/utils.js Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- .../test/theme-file-uri-utils.js | 27 +--- .../components/global-styles/test/utils.js | 120 ++++++++++++++++++ .../global-styles/theme-file-uri-utils.js | 59 --------- .../global-styles/use-global-styles-output.js | 78 +++++------- .../src/components/global-styles/utils.js | 112 ++++++++++++++++ 5 files changed, 267 insertions(+), 129 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/test/theme-file-uri-utils.js b/packages/block-editor/src/components/global-styles/test/theme-file-uri-utils.js index 06c482b67826bd..e239bb0941ea9e 100644 --- a/packages/block-editor/src/components/global-styles/test/theme-file-uri-utils.js +++ b/packages/block-editor/src/components/global-styles/test/theme-file-uri-utils.js @@ -1,10 +1,7 @@ /** * Internal dependencies */ -import { - setThemeFileUris, - getResolvedThemeFilePath, -} from '../theme-file-uri-utils'; +import { getResolvedThemeFilePath } from '../theme-file-uri-utils'; const themeFileURIs = [ { @@ -19,28 +16,6 @@ const themeFileURIs = [ }, ]; -describe( 'setThemeFileUris()', () => { - const themeJson = { - styles: { - background: { - backgroundImage: { - url: 'file:./assets/image.jpg', - }, - }, - }, - }; - - it( 'should replace relative paths with resolved URIs if found in themeFileURIs', () => { - const newThemeJson = setThemeFileUris( themeJson, themeFileURIs ); - expect( - newThemeJson.styles.background.backgroundImage.url === - 'https://wordpress.org/assets/image.jpg' - ).toBe( true ); - // Object reference should be the same as the function is mutating the object. - expect( newThemeJson ).toEqual( themeJson ); - } ); -} ); - describe( 'getResolvedThemeFilePath()', () => { it.each( [ [ diff --git a/packages/block-editor/src/components/global-styles/test/utils.js b/packages/block-editor/src/components/global-styles/test/utils.js index f06a09494ab9fb..08ed1f18e80402 100644 --- a/packages/block-editor/src/components/global-styles/test/utils.js +++ b/packages/block-editor/src/components/global-styles/test/utils.js @@ -7,6 +7,9 @@ import { getPresetVariableFromValue, getValueFromVariable, scopeFeatureSelectors, + getResolvedThemeFilePath, + getResolvedRefValue, + getResolvedValue, } from '../utils'; describe( 'editor utils', () => { @@ -52,6 +55,41 @@ describe( 'editor utils', () => { }, }, }, + styles: { + background: { + backgroundImage: { + url: 'file:./assets/image.jpg', + }, + backgroundAttachment: 'fixed', + backgroundPosition: 'top left', + }, + blocks: { + 'core/group': { + background: { + backgroundImage: { + ref: 'styles.background.backgroundImage', + }, + }, + dimensions: { + minHeight: '100px', + }, + }, + }, + }, + _links: { + 'wp:theme-file': [ + { + name: 'file:./assets/image.jpg', + href: 'https://wordpress.org/assets/image.jpg', + target: 'styles.background.backgroundImage.url', + }, + { + name: 'file:./assets/other/image.jpg', + href: 'https://wordpress.org/assets/other/image.jpg', + target: "styles.blocks.['core/group'].background.backgroundImage.url", + }, + ], + }, isGlobalStylesUserThemeJSON: true, }; @@ -366,4 +404,86 @@ describe( 'editor utils', () => { } ); } ); } ); + + describe( 'getResolvedThemeFilePath()', () => { + it.each( [ + [ + 'file:./assets/image.jpg', + 'https://wordpress.org/assets/image.jpg', + 'Should return absolute URL if found in themeFileURIs', + ], + [ + 'file:./misc/image.jpg', + 'file:./misc/image.jpg', + 'Should return value if not found in themeFileURIs', + ], + [ + 'https://wordpress.org/assets/image.jpg', + 'https://wordpress.org/assets/image.jpg', + 'Should not match absolute URLs', + ], + ] )( + 'Given file %s and return value %s: %s', + ( file, returnedValue ) => { + expect( + getResolvedThemeFilePath( + file, + themeJson._links[ 'wp:theme-file' ] + ) === returnedValue + ).toBe( true ); + } + ); + } ); + + describe( 'getResolvedRefValue()', () => { + it.each( [ + [ 'blue', 'blue', null ], + [ 0, 0, themeJson ], + [ + { ref: 'styles.background.backgroundImage' }, + { url: 'file:./assets/image.jpg' }, + themeJson, + ], + [ + { + ref: 'styles.blocks.core/group.background.backgroundImage', + }, + undefined, + themeJson, + ], + ] )( + 'Given ruleValue %s return expected value of %s', + ( ruleValue, returnedValue, tree ) => { + expect( getResolvedRefValue( ruleValue, tree ) ).toEqual( + returnedValue + ); + } + ); + } ); + + describe( 'getResolvedValue()', () => { + it.each( [ + [ 'blue', 'blue', null ], + [ 0, 0, themeJson ], + [ + { ref: 'styles.background.backgroundImage' }, + { url: 'https://wordpress.org/assets/image.jpg' }, + themeJson, + ], + [ + { + ref: 'styles.blocks.core/group.background.backgroundImage', + }, + undefined, + themeJson, + ], + ] )( + 'Given ruleValue %s return expected value of %s', + ( ruleValue, returnedValue, tree ) => { + expect( getResolvedValue( ruleValue, tree ) ).toEqual( + returnedValue + ); + } + ); + } ); } ); diff --git a/packages/block-editor/src/components/global-styles/theme-file-uri-utils.js b/packages/block-editor/src/components/global-styles/theme-file-uri-utils.js index 1ab05a45f0d54b..96b3e2e4cb68b0 100644 --- a/packages/block-editor/src/components/global-styles/theme-file-uri-utils.js +++ b/packages/block-editor/src/components/global-styles/theme-file-uri-utils.js @@ -1,8 +1,3 @@ -/** - * Internal dependencies - */ -import { getValueFromObjectPath } from '../../utils/object'; - /** * Looks up a theme file URI based on a relative path. * @@ -21,57 +16,3 @@ export function getResolvedThemeFilePath( file, themeFileURIs = [] ) { return uri?.href; } - -/** - * Mutates an object by settings a value at the provided path. - * - * @param {Object} object Object to set a value in. - * @param {number|string|Array} path Path in the object to modify. - * @param {*} value New value to set. - * @return {Object} Object with the new value set. - */ -function setMutably( object, path, value ) { - path = path.split( '.' ); - const finalValueKey = path.pop(); - let prev = object; - - for ( const key of path ) { - const current = prev[ key ]; - prev = current; - } - - prev[ finalValueKey ] = value; - - return object; -} - -/** - * Resolves any relative paths if a corresponding theme file URI is available. - * Note: this function mutates the object and is specifically to be used in - * an async styles build context in useGlobalStylesOutput - * - * @param {Object} themeJson Theme.json/Global styles tree. - * @param {Array<Object>} themeFileURIs A collection of absolute theme file URIs and their corresponding file paths. - * @return {Object} Returns mutated object. - */ -export function setThemeFileUris( themeJson, themeFileURIs ) { - if ( ! themeJson?.styles || ! themeFileURIs ) { - return themeJson; - } - - themeFileURIs.forEach( ( { name, href, target } ) => { - const value = getValueFromObjectPath( themeJson, target ); - if ( value === name ) { - /* - * The object must not be updated immutably here because the - * themeJson is a reference to the global styles tree used as a dependency in the - * useGlobalStylesOutputWithConfig() hook. If we don't mutate the object, - * the hook will detect the change and re-render the component, resulting - * in a maximum depth exceeded error. - */ - themeJson = setMutably( themeJson, target, href ); - } - } ); - - return themeJson; -} diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 69adf221900a47..6d3e29f360200a 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -24,6 +24,8 @@ import { scopeFeatureSelectors, appendToSelector, getBlockStyleVariationSelector, + compileStyleValue, + getResolvedValue, } from './utils'; import { getBlockCSSSelector } from './get-block-css-selector'; import { getTypographyFontSizeValue } from './typography-utils'; @@ -36,7 +38,6 @@ import { store as blockEditorStore } from '../../store'; import { LAYOUT_DEFINITIONS } from '../../layouts/definitions'; import { getValueFromObjectPath, setImmutably } from '../../utils/object'; import { unlock } from '../../lock-unlock'; -import { setThemeFileUris } from './theme-file-uri-utils'; // Elements that rely on class names in their selectors. const ELEMENT_CLASS_NAMES = { @@ -54,21 +55,6 @@ const BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS = { }; const { kebabCase } = unlock( componentsPrivateApis ); -function compileStyleValue( uncompiledValue ) { - const VARIABLE_REFERENCE_PREFIX = 'var:'; - const VARIABLE_PATH_SEPARATOR_TOKEN_ATTRIBUTE = '|'; - const VARIABLE_PATH_SEPARATOR_TOKEN_STYLE = '--'; - - if ( uncompiledValue?.startsWith?.( VARIABLE_REFERENCE_PREFIX ) ) { - const variable = uncompiledValue - .slice( VARIABLE_REFERENCE_PREFIX.length ) - .split( VARIABLE_PATH_SEPARATOR_TOKEN_ATTRIBUTE ) - .join( VARIABLE_PATH_SEPARATOR_TOKEN_STYLE ); - return `var(--wp--${ variable })`; - } - return uncompiledValue; -} - /** * Transform given preset tree into a set of style declarations. * @@ -395,21 +381,40 @@ export function getStylesDeclarations( ); /* - * Set background defaults. - * Applies to all background styles except the top-level site background. + * Preprocess background image values. + * + * Note: As we absorb more and more styles into the engine, we could simplify this function. + * A refactor is for the style engine to handle ref resolution (and possibly defaults) + * via a public util used internally and externally. Theme.json tree and defaults could be passed + * as options. */ - if ( ! isRoot && !! blockStyles.background ) { - blockStyles = { - ...blockStyles, - background: { - ...blockStyles.background, - ...setBackgroundStyleDefaults( blockStyles.background ), - }, - }; + if ( !! blockStyles.background ) { + /* + * Resolve dynamic values before they are compiled by the style engine, + * which doesn't (yet) resolve dynamic values. + */ + if ( blockStyles.background?.backgroundImage ) { + blockStyles.background.backgroundImage = getResolvedValue( + blockStyles.background.backgroundImage, + tree + ); + } + + /* + * Set default values for block background styles. + * Top-level styles are an exception as they are applied to the body. + */ + if ( ! isRoot ) { + blockStyles = { + ...blockStyles, + background: { + ...blockStyles.background, + ...setBackgroundStyleDefaults( blockStyles.background ), + }, + }; + } } - // The goal is to move everything to server side generated engine styles - // This is temporary as we absorb more and more styles into the engine. const extraRules = getCSSRules( blockStyles ); extraRules.forEach( ( rule ) => { // Don't output padding properties if padding variables are set or if we're not editing a full template. @@ -424,18 +429,7 @@ export function getStylesDeclarations( ? rule.key : kebabCase( rule.key ); - let ruleValue = rule.value; - if ( typeof ruleValue !== 'string' && ruleValue?.ref ) { - const refPath = ruleValue.ref.split( '.' ); - ruleValue = compileStyleValue( - getValueFromObjectPath( tree, refPath ) - ); - // Presence of another ref indicates a reference to another dynamic value. - // Pointing to another dynamic value is not supported. - if ( ! ruleValue || ruleValue?.ref ) { - return; - } - } + let ruleValue = getResolvedValue( rule.value, tree, null ); // Calculate fluid typography rules where available. if ( cssProperty === 'font-size' ) { @@ -1398,10 +1392,6 @@ export function useGlobalStylesOutputWithConfig( disableRootPadding ) { const [ blockGap ] = useGlobalSetting( 'spacing.blockGap' ); - mergedConfig = setThemeFileUris( - mergedConfig, - mergedConfig?._links?.[ 'wp:theme-file' ] - ); const hasBlockGapSupport = blockGap !== null; const hasFallbackGapSupport = ! hasBlockGapSupport; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback styles support. const disableLayoutStyles = useSelect( ( select ) => { diff --git a/packages/block-editor/src/components/global-styles/utils.js b/packages/block-editor/src/components/global-styles/utils.js index bf84e6f0b5765c..8de479e39382e5 100644 --- a/packages/block-editor/src/components/global-styles/utils.js +++ b/packages/block-editor/src/components/global-styles/utils.js @@ -525,3 +525,115 @@ export function getBlockStyleVariationSelector( variation, blockSelector ) { return result.join( ',' ); } + +/** + * Converts style preset values `var:` to CSS custom var values. + * TODO: Export and use the style engine util: getCSSVarFromStyleValue(). + * + * Example: + * + * compileStyleValue( 'var:preset|color|primary' ) // returns 'var(--wp--color-primary)' + * + * @param {string} uncompiledValue A block style value. + * @return {string} The compiled, or original value. + */ +export function compileStyleValue( uncompiledValue ) { + const VARIABLE_REFERENCE_PREFIX = 'var:'; + if ( + 'string' === typeof uncompiledValue && + uncompiledValue?.startsWith?.( VARIABLE_REFERENCE_PREFIX ) + ) { + const VARIABLE_PATH_SEPARATOR_TOKEN_ATTRIBUTE = '|'; + const VARIABLE_PATH_SEPARATOR_TOKEN_STYLE = '--'; + const variable = uncompiledValue + .slice( VARIABLE_REFERENCE_PREFIX.length ) + .split( VARIABLE_PATH_SEPARATOR_TOKEN_ATTRIBUTE ) + .join( VARIABLE_PATH_SEPARATOR_TOKEN_STYLE ); + return `var(--wp--${ variable })`; + } + return uncompiledValue; +} + +/** + * Looks up a theme file URI based on a relative path. + * + * @param {string} file A relative path. + * @param {Array<Object>} themeFileURIs A collection of absolute theme file URIs and their corresponding file paths. + * @return {string} A resolved theme file URI, if one is found in the themeFileURIs collection. + */ +export function getResolvedThemeFilePath( file, themeFileURIs ) { + if ( ! file || ! themeFileURIs || ! Array.isArray( themeFileURIs ) ) { + return file; + } + + const uri = themeFileURIs.find( + ( themeFileUri ) => themeFileUri?.name === file + ); + + if ( ! uri?.href ) { + return file; + } + + return uri?.href; +} + +/** + * Resolves ref values in theme JSON. + * + * @param {Object|string} ruleValue A block style value that may contain a reference to a theme.json value. + * @param {Object} tree A theme.json object. + * @return {*} The resolved value or incoming ruleValue. + */ +export function getResolvedRefValue( ruleValue, tree ) { + if ( ! ruleValue || ! tree ) { + return ruleValue; + } + + if ( typeof ruleValue !== 'string' && ruleValue?.ref ) { + const refPath = ruleValue.ref.split( '.' ); + const resolvedRuleValue = compileStyleValue( + getValueFromObjectPath( tree, refPath ) + ); + + /* + * Presence of another ref indicates a reference to another dynamic value. + * Pointing to another dynamic value is not supported. + */ + if ( resolvedRuleValue?.ref ) { + return undefined; + } + + if ( ! resolvedRuleValue ) { + return ruleValue; + } + + return resolvedRuleValue; + } + return ruleValue; +} + +/** + * Resolves ref and relative path values in theme JSON. + * + * @param {Object|string} ruleValue A block style value that may contain a reference to a theme.json value. + * @param {Object} tree A theme.json object. + * @return {*} The resolved value or incoming ruleValue. + */ +export function getResolvedValue( ruleValue, tree ) { + if ( ! ruleValue || ! tree ) { + return ruleValue; + } + + // Resolve ref values. + const resolvedValue = getResolvedRefValue( ruleValue, tree ); + + // Resolve relative paths. + if ( resolvedValue?.url ) { + resolvedValue.url = getResolvedThemeFilePath( + resolvedValue.url, + tree?._links?.[ 'wp:theme-file' ] + ); + } + + return resolvedValue; +} From 16c728eb71d5f900bc95847879e13bff1657aaf5 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Fri, 2 Aug 2024 10:14:17 +0200 Subject: [PATCH 0225/1908] Fix density slider minus to be correct. (#64185) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/dataviews/src/layouts/grid/density-picker.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dataviews/src/layouts/grid/density-picker.tsx b/packages/dataviews/src/layouts/grid/density-picker.tsx index df347507fb6340..364d764e343470 100644 --- a/packages/dataviews/src/layouts/grid/density-picker.tsx +++ b/packages/dataviews/src/layouts/grid/density-picker.tsx @@ -4,7 +4,7 @@ import { RangeControl, Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useViewportMatch } from '@wordpress/compose'; -import { plus, lineSolid } from '@wordpress/icons'; +import { plus, reset } from '@wordpress/icons'; import { useEffect } from '@wordpress/element'; const viewportBreaks = { @@ -90,7 +90,7 @@ export default function DensityPicker( { <> <Button size="compact" - icon={ lineSolid } + icon={ reset } disabled={ rangeValue <= 0 } accessibleWhenDisabled label={ __( 'Decrease size' ) } From a9a0287d9a942f5ae3d77a4b61d88d92b6069d19 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:50:54 +0900 Subject: [PATCH 0226/1908] Icons: Fixed invalid prop for `homeButton` icon (#64191) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/icons/src/library/home-button.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/icons/src/library/home-button.js b/packages/icons/src/library/home-button.js index 5a1b26d3416f2a..b952f46d725ff4 100644 --- a/packages/icons/src/library/home-button.js +++ b/packages/icons/src/library/home-button.js @@ -6,8 +6,8 @@ import { SVG, Path } from '@wordpress/primitives'; const homeButton = ( <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <Path - fill-rule="evenodd" - clip-rule="evenodd" + fillRule="evenodd" + clipRule="evenodd" d="M4.25 7A2.75 2.75 0 0 1 7 4.25h10A2.75 2.75 0 0 1 19.75 7v10A2.75 2.75 0 0 1 17 19.75H7A2.75 2.75 0 0 1 4.25 17V7ZM7 5.75c-.69 0-1.25.56-1.25 1.25v10c0 .69.56 1.25 1.25 1.25h10c.69 0 1.25-.56 1.25-1.25V7c0-.69-.56-1.25-1.25-1.25H7Z" /> </SVG> From 9770494e54a690832ee41aa8a80155e5144517a1 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 2 Aug 2024 12:58:05 +0400 Subject: [PATCH 0227/1908] Editor: Display empty option when post author is missing (#64165) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: mossy2100 <mossy2100@git.wordpress.org> --- packages/editor/src/components/post-author/hook.js | 14 +++++++++++--- .../editor/src/components/post-author/panel.js | 4 +++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/components/post-author/hook.js b/packages/editor/src/components/post-author/hook.js index 116c354669ca8e..62830cf6ea60e6 100644 --- a/packages/editor/src/components/post-author/hook.js +++ b/packages/editor/src/components/post-author/hook.js @@ -1,6 +1,7 @@ /** * WordPress dependencies */ +import { __ } from '@wordpress/i18n'; import { useMemo } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; import { decodeEntities } from '@wordpress/html-entities'; @@ -46,17 +47,24 @@ export function useAuthorsQuery( search ) { ( { value } ) => postAuthor?.id === value ); + let currentAuthor = []; if ( foundAuthor < 0 && postAuthor ) { - return [ + currentAuthor = [ { value: postAuthor.id, label: decodeEntities( postAuthor.name ), }, - ...fetchedAuthors, + ]; + } else if ( foundAuthor < 0 && ! postAuthor ) { + currentAuthor = [ + { + value: 0, + label: __( '(No author)' ), + }, ]; } - return fetchedAuthors; + return [ ...currentAuthor, ...fetchedAuthors ]; }, [ authors, postAuthor ] ); return { authorId, authorOptions, postAuthor }; diff --git a/packages/editor/src/components/post-author/panel.js b/packages/editor/src/components/post-author/panel.js index 5c162cfa50377f..a3c53aa417163e 100644 --- a/packages/editor/src/components/post-author/panel.js +++ b/packages/editor/src/components/post-author/panel.js @@ -4,6 +4,7 @@ import { __, sprintf } from '@wordpress/i18n'; import { Button, Dropdown } from '@wordpress/components'; import { useState, useMemo } from '@wordpress/element'; +import { decodeEntities } from '@wordpress/html-entities'; import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor'; /** @@ -16,7 +17,8 @@ import { useAuthorsQuery } from './hook'; function PostAuthorToggle( { isOpen, onClick } ) { const { postAuthor } = useAuthorsQuery(); - const authorName = postAuthor?.name || ''; + const authorName = + decodeEntities( postAuthor?.name ) || __( '(No author)' ); return ( <Button size="compact" From 41ee29e01471939afc2fffcc8ba6d252ad15935c Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Fri, 2 Aug 2024 10:58:32 +0200 Subject: [PATCH 0228/1908] Text case: Change "No Title" to "No title". (#64184) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-library/src/post-title/edit.js | 4 ++-- packages/editor/src/components/blog-title/index.js | 2 +- packages/editor/src/components/document-bar/index.js | 2 +- packages/editor/src/components/post-card-panel/index.js | 2 +- test/e2e/specs/editor/various/sidebar.spec.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/block-library/src/post-title/edit.js b/packages/block-library/src/post-title/edit.js index d24455f0956358..e9b45e2a642a61 100644 --- a/packages/block-library/src/post-title/edit.js +++ b/packages/block-library/src/post-title/edit.js @@ -73,7 +73,7 @@ export default function PostTitleEdit( { titleElement = userCanEdit ? ( <PlainText tagName={ TagName } - placeholder={ __( 'No Title' ) } + placeholder={ __( 'No title' ) } value={ rawTitle } onChange={ setTitle } __experimentalVersion={ 2 } @@ -96,7 +96,7 @@ export default function PostTitleEdit( { href={ link } target={ linkTarget } rel={ rel } - placeholder={ ! rawTitle.length ? __( 'No Title' ) : null } + placeholder={ ! rawTitle.length ? __( 'No title' ) : null } value={ rawTitle } onChange={ setTitle } __experimentalVersion={ 2 } diff --git a/packages/editor/src/components/blog-title/index.js b/packages/editor/src/components/blog-title/index.js index 1356edf9724e16..aee2a7f049eb09 100644 --- a/packages/editor/src/components/blog-title/index.js +++ b/packages/editor/src/components/blog-title/index.js @@ -111,7 +111,7 @@ export default function BlogTitle() { onClose={ onClose } /> <InputControl - placeholder={ __( 'No Title' ) } + placeholder={ __( 'No title' ) } size="__unstable-large" value={ postsPageTitle } onChange={ debounce( setPostsPageTitle, 300 ) } diff --git a/packages/editor/src/components/document-bar/index.js b/packages/editor/src/components/document-bar/index.js index 34cb68de785157..da3d886c125f42 100644 --- a/packages/editor/src/components/document-bar/index.js +++ b/packages/editor/src/components/document-bar/index.js @@ -200,7 +200,7 @@ export default function DocumentBar( props ) { > { title ? decodeEntities( title ) - : __( 'No Title' ) } + : __( 'No title' ) } </Text> </motion.div> <span className="editor-document-bar__shortcut"> diff --git a/packages/editor/src/components/post-card-panel/index.js b/packages/editor/src/components/post-card-panel/index.js index df13f1c8b65a6b..43efb6418b4fa9 100644 --- a/packages/editor/src/components/post-card-panel/index.js +++ b/packages/editor/src/components/post-card-panel/index.js @@ -101,7 +101,7 @@ export default function PostCardPanel( { actions } ) { as="h2" lineHeight="20px" > - { title ? decodeEntities( title ) : __( 'No Title' ) } + { title ? decodeEntities( title ) : __( 'No title' ) } { isFrontPage && ( <span className="editor-post-card-panel__title-badge"> { __( 'Homepage' ) } diff --git a/test/e2e/specs/editor/various/sidebar.spec.js b/test/e2e/specs/editor/various/sidebar.spec.js index c051b4e7673293..153a48e325c887 100644 --- a/test/e2e/specs/editor/various/sidebar.spec.js +++ b/test/e2e/specs/editor/various/sidebar.spec.js @@ -111,7 +111,7 @@ test.describe( 'Sidebar', () => { .getByRole( 'heading', { level: 2 } ); await expect( documentSettingsPanels ).toHaveText( [ - 'No Title', + 'No title', 'Categories', 'Tags', ] ); From 3c7d4d6aff43d1da924bdc6c501dc4389b6e9d9b Mon Sep 17 00:00:00 2001 From: Adam Silverstein <adamjs@google.com> Date: Fri, 2 Aug 2024 03:34:14 -0600 Subject: [PATCH 0229/1908] Add an async `__unstablePreSavePost` hook; resolving with false prevents saving (#58022) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add an async `__unstablePreSavePost` hook; resolving with false prevents saving * Simplify preSave check * Filter edits & enable throwing Error in `__unstablePreSavePost` filter * Pass Promise.resolve( edits ) instead of edits * Move REQUEST_POST_UPDATE_START to before preSave async filter * Update saveEntityRecord error handling to use try/catch * Use explicit false check for error * reduce changes, test functionality, don’t pass data to filter * whitespace Unlinked contributors: aduth, lex127, audiovisuel-uqam, eballeste, jenilk, zhitaryksergey, christianMiguez. Co-authored-by: adamsilverstein <adamsilverstein@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: ockham <bernhard-reiter@git.wordpress.org> Co-authored-by: sadmansh <sadmansh@git.wordpress.org> Co-authored-by: sc0ttkclark <sc0ttkclark@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: acafourek <acafourek@git.wordpress.org> Co-authored-by: marcwieland95 <marcwieland95@git.wordpress.org> Co-authored-by: margolisj <margolisj@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> --- packages/editor/src/store/actions.js | 49 ++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index d934436800cbaf..59faa6b5b73624 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -196,22 +196,45 @@ export const savePost = content, }; dispatch( { type: 'REQUEST_POST_UPDATE_START', options } ); - await registry - .dispatch( coreStore ) - .saveEntityRecord( - 'postType', - previousRecord.type, - edits, + + let error = false; + try { + error = await applyFilters( + 'editor.__unstablePreSavePost', + Promise.resolve( false ), options ); + } catch ( err ) { + error = err; + } - let error = registry - .select( coreStore ) - .getLastEntitySaveError( - 'postType', - previousRecord.type, - previousRecord.id - ); + if ( ! error ) { + try { + await registry + .dispatch( coreStore ) + .saveEntityRecord( + 'postType', + previousRecord.type, + edits, + options + ); + } catch ( err ) { + error = + err.message && err.code !== 'unknown_error' + ? err.message + : __( 'An error occurred while updating.' ); + } + } + + if ( ! error ) { + error = registry + .select( coreStore ) + .getLastEntitySaveError( + 'postType', + previousRecord.type, + previousRecord.id + ); + } if ( ! error ) { await applyFilters( From 2218059b55fa908d0c29cfa9fe3f8def840374e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 2 Aug 2024 12:01:15 +0200 Subject: [PATCH 0230/1908] Pages: update `useView` logic (#63889) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> --- .../src/components/post-list/index.js | 165 ++++++++------- .../sidebar-dataviews/add-new-view.js | 6 +- .../sidebar-dataviews/default-views.js | 190 +++++++++--------- .../src/components/sidebar-dataviews/index.js | 40 +--- test/performance/specs/site-editor.spec.js | 4 +- 5 files changed, 198 insertions(+), 207 deletions(-) diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 2724abcff714f7..e63ed4ccebcf98 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -39,100 +39,129 @@ const { useLocation, useHistory } = unlock( routerPrivateApis ); const { useEntityRecordsWithPermissions } = unlock( coreDataPrivateApis ); const EMPTY_ARRAY = []; +const getDefaultView = ( defaultViews, activeView ) => { + return defaultViews.find( ( { slug } ) => slug === activeView )?.view; +}; + +const getCustomView = ( editedEntityRecord ) => { + if ( ! editedEntityRecord?.content ) { + return undefined; + } + + const content = JSON.parse( editedEntityRecord.content ); + if ( ! content ) { + return undefined; + } + + return { + ...content, + layout: defaultLayouts[ content.type ]?.layout, + }; +}; + +/** + * This function abstracts working with default & custom views by + * providing a [ state, setState ] tuple based on the URL parameters. + * + * Consumers use the provided tuple to work with state + * and don't have to deal with the specifics of default & custom views. + * + * @param {string} postType Post type to retrieve default views for. + * @return {Array} The [ state, setState ] tuple. + */ function useView( postType ) { const { params: { activeView = 'all', isCustom = 'false', layout }, } = useLocation(); const history = useHistory(); - const DEFAULT_VIEWS = useDefaultViews( { postType } ); - const selectedDefaultView = useMemo( () => { - const defaultView = - isCustom === 'false' && - DEFAULT_VIEWS[ postType ].find( - ( { slug } ) => slug === activeView - )?.view; - if ( isCustom === 'false' && layout ) { - return { - ...defaultView, - type: layout, - layout: defaultLayouts[ layout ]?.layout, - }; - } - return defaultView; - }, [ isCustom, activeView, layout, postType, DEFAULT_VIEWS ] ); - const [ view, setView ] = useState( selectedDefaultView ); - useEffect( () => { - if ( selectedDefaultView ) { - setView( selectedDefaultView ); - } - }, [ selectedDefaultView ] ); - const editedViewRecord = useSelect( + const defaultViews = useDefaultViews( { postType } ); + const { editEntityRecord } = useDispatch( coreStore ); + const editedEntityRecord = useSelect( ( select ) => { if ( isCustom !== 'true' ) { - return; + return undefined; } + const { getEditedEntityRecord } = select( coreStore ); - const dataviewRecord = getEditedEntityRecord( + return getEditedEntityRecord( 'postType', 'wp_dataviews', Number( activeView ) ); - return dataviewRecord; }, [ activeView, isCustom ] ); - const { editEntityRecord } = useDispatch( coreStore ); - - const customView = useMemo( () => { - const storedView = - editedViewRecord?.content && - JSON.parse( editedViewRecord?.content ); - if ( ! storedView ) { - return storedView; - } - - return { - ...storedView, - layout: defaultLayouts[ storedView?.type ]?.layout, - }; - }, [ editedViewRecord?.content ] ); - - const setCustomView = useCallback( - ( viewToSet ) => { - editEntityRecord( - 'postType', - 'wp_dataviews', - editedViewRecord?.id, - { - content: JSON.stringify( viewToSet ), + const [ view, setView ] = useState( () => { + if ( isCustom === 'true' ) { + return ( + getCustomView( editedEntityRecord ) ?? { + type: layout ?? LAYOUT_LIST, } ); - }, - [ editEntityRecord, editedViewRecord?.id ] - ); + } + return ( + getDefaultView( defaultViews, activeView ) ?? { + type: layout ?? LAYOUT_LIST, + } + ); + } ); - const setDefaultViewAndUpdateUrl = useCallback( - ( viewToSet ) => { - if ( viewToSet.type !== view?.type ) { - const { params } = history.getLocationWithParams(); + const setViewWithUrlUpdate = useCallback( + ( newView ) => { + const { params } = history.getLocationWithParams(); + + if ( newView.type === LAYOUT_LIST && ! params?.layout ) { + // Skip updating the layout URL param if + // it is not present and the newView.type is LAYOUT_LIST. + } else if ( newView.type !== params?.layout ) { history.push( { ...params, - layout: viewToSet.type, + layout: newView.type, } ); } - setView( viewToSet ); + + setView( newView ); + + if ( isCustom === 'true' && editedEntityRecord?.id ) { + editEntityRecord( + 'postType', + 'wp_dataviews', + editedEntityRecord?.id, + { + content: JSON.stringify( newView ), + } + ); + } }, - [ history, view?.type ] + [ history, isCustom, editEntityRecord, editedEntityRecord?.id ] ); - if ( isCustom === 'false' ) { - return [ view, setDefaultViewAndUpdateUrl ]; - } else if ( isCustom === 'true' && customView ) { - return [ customView, setCustomView ]; - } - // Loading state where no the view was not found on custom views or default views. - return [ DEFAULT_VIEWS[ postType ][ 0 ].view, setDefaultViewAndUpdateUrl ]; + // When layout URL param changes, update the view type + // without affecting any other config. + useEffect( () => { + setView( ( prevView ) => ( { + ...prevView, + type: layout ?? LAYOUT_LIST, + } ) ); + }, [ layout ] ); + + // When activeView or isCustom URL parameters change, + // reset the view & update the layout URL param to match the view's type. + useEffect( () => { + let newView; + if ( isCustom === 'true' ) { + newView = getCustomView( editedEntityRecord ); + } else { + newView = getDefaultView( defaultViews, activeView ); + } + + if ( newView ) { + setViewWithUrlUpdate( newView ); + } + }, [ activeView, isCustom, defaultViews, editedEntityRecord ] ); + + return [ view, setViewWithUrlUpdate, setViewWithUrlUpdate ]; } const DEFAULT_STATUSES = 'draft,future,pending,private,publish'; // All but 'trash'. @@ -165,7 +194,7 @@ export default function PostList( { postType } ) { const queryArgs = useMemo( () => { const filters = {}; - view.filters.forEach( ( filter ) => { + view.filters?.forEach( ( filter ) => { if ( filter.field === 'status' && filter.operator === OPERATOR_IS_ANY diff --git a/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js b/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js index ceb2a11f2c523e..aabb49c14a2ff7 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js +++ b/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js @@ -29,7 +29,7 @@ function AddNewItemModalContent( { type, setIsAdding } ) { const { saveEntityRecord } = useDispatch( coreStore ); const [ title, setTitle ] = useState( '' ); const [ isSaving, setIsSaving ] = useState( false ); - const DEFAULT_VIEWS = useDefaultViews( { postType: type } ); + const defaultViews = useDefaultViews( { postType: type } ); return ( <form onSubmit={ async ( event ) => { @@ -61,9 +61,7 @@ function AddNewItemModalContent( { type, setIsAdding } ) { title, status: 'publish', wp_dataviews_type: dataViewTaxonomyId, - content: JSON.stringify( - DEFAULT_VIEWS[ type ][ 0 ].view - ), + content: JSON.stringify( defaultViews[ 0 ].view ), } ); const { diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 2b8a9de4c2262d..e5db492fce17d0 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -77,105 +77,105 @@ export function useDefaultViews( { postType } ) { [ postType ] ); return useMemo( () => { - return { - [ postType ]: [ - { - title: labels?.all_items || __( 'All items' ), - slug: 'all', - icon: pages, - view: DEFAULT_POST_BASE, - }, - { - title: __( 'Published' ), - slug: 'published', - icon: published, - view: { - ...DEFAULT_POST_BASE, - filters: [ - { - field: 'status', - operator: OPERATOR_IS_ANY, - value: 'publish', - }, - ], - }, + return [ + { + title: labels?.all_items || __( 'All items' ), + slug: 'all', + icon: pages, + view: DEFAULT_POST_BASE, + }, + { + title: __( 'Published' ), + slug: 'published', + icon: published, + view: { + ...DEFAULT_POST_BASE, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_ANY, + value: 'publish', + }, + ], }, - { - title: __( 'Scheduled' ), - slug: 'future', - icon: scheduled, - view: { - ...DEFAULT_POST_BASE, - filters: [ - { - field: 'status', - operator: OPERATOR_IS_ANY, - value: 'future', - }, - ], - }, + }, + { + title: __( 'Scheduled' ), + slug: 'future', + icon: scheduled, + view: { + ...DEFAULT_POST_BASE, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_ANY, + value: 'future', + }, + ], }, - { - title: __( 'Drafts' ), - slug: 'drafts', - icon: drafts, - view: { - ...DEFAULT_POST_BASE, - filters: [ - { - field: 'status', - operator: OPERATOR_IS_ANY, - value: 'draft', - }, - ], - }, + }, + { + title: __( 'Drafts' ), + slug: 'drafts', + icon: drafts, + view: { + ...DEFAULT_POST_BASE, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_ANY, + value: 'draft', + }, + ], }, - { - title: __( 'Pending' ), - slug: 'pending', - icon: pending, - view: { - ...DEFAULT_POST_BASE, - filters: [ - { - field: 'status', - operator: OPERATOR_IS_ANY, - value: 'pending', - }, - ], - }, + }, + { + title: __( 'Pending' ), + slug: 'pending', + icon: pending, + view: { + ...DEFAULT_POST_BASE, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_ANY, + value: 'pending', + }, + ], }, - { - title: __( 'Private' ), - slug: 'private', - icon: notAllowed, - view: { - ...DEFAULT_POST_BASE, - filters: [ - { - field: 'status', - operator: OPERATOR_IS_ANY, - value: 'private', - }, - ], - }, + }, + { + title: __( 'Private' ), + slug: 'private', + icon: notAllowed, + view: { + ...DEFAULT_POST_BASE, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_ANY, + value: 'private', + }, + ], }, - { - title: __( 'Trash' ), - slug: 'trash', - icon: trash, - view: { - ...DEFAULT_POST_BASE, - filters: [ - { - field: 'status', - operator: OPERATOR_IS_ANY, - value: 'trash', - }, - ], - }, + }, + { + title: __( 'Trash' ), + slug: 'trash', + icon: trash, + view: { + ...DEFAULT_POST_BASE, + type: LAYOUT_TABLE, + layout: defaultLayouts[ LAYOUT_TABLE ].layout, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_ANY, + value: 'trash', + }, + ], }, - ], - }; - }, [ labels, postType ] ); + }, + ]; + }, [ labels ] ); } diff --git a/packages/edit-site/src/components/sidebar-dataviews/index.js b/packages/edit-site/src/components/sidebar-dataviews/index.js index e0a5b08a028f07..86420c4eec1d1f 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/index.js +++ b/packages/edit-site/src/components/sidebar-dataviews/index.js @@ -3,8 +3,6 @@ */ import { __experimentalItemGroup as ItemGroup } from '@wordpress/components'; import { privateApis as routerPrivateApis } from '@wordpress/router'; -import { useRef, useEffect } from '@wordpress/element'; -import { usePrevious } from '@wordpress/compose'; /** * Internal dependencies @@ -14,45 +12,13 @@ import { unlock } from '../../lock-unlock'; import DataViewItem from './dataview-item'; import CustomDataViewsList from './custom-dataviews-list'; -const { useLocation, useHistory } = unlock( routerPrivateApis ); - -/** - * Hook to switch to table layout when switching to the trash view. - * When going out of the trash view, it switches back to the previous layout if - * there was an automatic switch to table layout. - */ -function useSwitchToTableOnTrash() { - const { - params: { activeView, layout, ...restParams }, - } = useLocation(); - const history = useHistory(); - const viewToSwitchOutOfTrash = useRef( undefined ); - const previousActiveView = usePrevious( activeView ); - useEffect( () => { - if ( activeView === 'trash' && previousActiveView !== 'trash' ) { - viewToSwitchOutOfTrash.current = layout || 'list'; - history.push( { ...restParams, layout: 'table', activeView } ); - } else if ( - previousActiveView === 'trash' && - activeView !== 'trash' && - viewToSwitchOutOfTrash.current - ) { - history.push( { - ...restParams, - layout: viewToSwitchOutOfTrash.current, - activeView, - } ); - viewToSwitchOutOfTrash.current = undefined; - } - }, [ previousActiveView, activeView, layout, history, restParams ] ); -} +const { useLocation } = unlock( routerPrivateApis ); export default function DataViewsSidebarContent() { const { params: { postType, activeView = 'all', isCustom = 'false' }, } = useLocation(); - useSwitchToTableOnTrash(); - const DEFAULT_VIEWS = useDefaultViews( { postType } ); + const defaultViews = useDefaultViews( { postType } ); if ( ! postType ) { return null; } @@ -61,7 +27,7 @@ export default function DataViewsSidebarContent() { return ( <> <ItemGroup> - { DEFAULT_VIEWS[ postType ].map( ( dataview ) => { + { defaultViews.map( ( dataview ) => { return ( <DataViewItem key={ dataview.slug } diff --git a/test/performance/specs/site-editor.spec.js b/test/performance/specs/site-editor.spec.js index 520ad76de22eef..9c9d8aec71da4a 100644 --- a/test/performance/specs/site-editor.spec.js +++ b/test/performance/specs/site-editor.spec.js @@ -438,9 +438,7 @@ test.describe( 'Site Editor Performance', () => { await Promise.all( Array.from( { length: perPage }, async ( el, index ) => { return await page - .getByRole( 'link', { - name: `Page (${ index })`, - } ) + .getByLabel( `Page (${ index })` ) .waitFor( { state: 'attached' } ); } ) ); From 6533c3265bb3db48b499ca2120f60b1b7966455b Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Fri, 2 Aug 2024 12:06:54 +0200 Subject: [PATCH 0231/1908] DataViews Extensibility: Add a hook to allow third-party scripts to register/unregister post type actions (#64138) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/edit-post/src/index.js | 2 - packages/edit-site/src/index.js | 2 - .../test/__snapshots__/index.js.snap | 111 ----------- .../components/document-outline/test/index.js | 185 ------------------ .../src/components/post-actions/actions.js | 6 +- .../actions/export-pattern.native.tsx | 3 + .../editor/src/dataviews/actions/index.ts | 31 --- .../src/dataviews/store/private-actions.ts | 68 +++++++ .../src/dataviews/store/private-selectors.ts | 26 +-- .../editor/src/dataviews/store/reducer.ts | 21 +- packages/editor/src/dataviews/types.ts | 4 + packages/editor/src/private-apis.js | 2 - .../editor/src/store/private-selectors.js | 9 +- 13 files changed, 117 insertions(+), 353 deletions(-) delete mode 100644 packages/editor/src/components/document-outline/test/__snapshots__/index.js.snap delete mode 100644 packages/editor/src/components/document-outline/test/index.js create mode 100644 packages/editor/src/dataviews/actions/export-pattern.native.tsx delete mode 100644 packages/editor/src/dataviews/actions/index.ts diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index aa3473e6e55d45..10f4a9838c8dad 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -27,7 +27,6 @@ import { unlock } from './lock-unlock'; const { BackButton: __experimentalMainDashboardButton, - registerDefaultActions, registerCoreBlockBindingsSources, bootstrapBlockBindingsSourcesFromServer, } = unlock( editorPrivateApis ); @@ -97,7 +96,6 @@ export function initializeEditor( enableFSEBlocks: settings.__unstableEnableFullSiteEditingBlocks, } ); } - registerDefaultActions(); // Show a console log warning if the browser is not in Standards rendering mode. const documentMode = diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 922e2f6ab933ab..9face28c1bfe19 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -29,7 +29,6 @@ import { unlock } from './lock-unlock'; import App from './components/app'; const { - registerDefaultActions, registerCoreBlockBindingsSources, bootstrapBlockBindingsSourcesFromServer, } = unlock( editorPrivateApis ); @@ -59,7 +58,6 @@ export function initializeEditor( id, settings ) { enableFSEBlocks: true, } ); } - registerDefaultActions(); // We dispatch actions and update the store synchronously before rendering // so that we won't trigger unnecessary re-renders with useEffect. diff --git a/packages/editor/src/components/document-outline/test/__snapshots__/index.js.snap b/packages/editor/src/components/document-outline/test/__snapshots__/index.js.snap deleted file mode 100644 index 27804e33f508b6..00000000000000 --- a/packages/editor/src/components/document-outline/test/__snapshots__/index.js.snap +++ /dev/null @@ -1,111 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DocumentOutline header blocks present should match snapshot 1`] = ` -<ul> - <li - class="document-outline__item is-h2" - > - <a - class="document-outline__button" - href="#block-clientId_0" - > - <span - aria-hidden="true" - class="document-outline__emdash" - /> - <strong - class="document-outline__level" - > - H2 - </strong> - <span - class="document-outline__item-content" - > - Heading 2 - </span> - </a> - </li> - <li - class="document-outline__item is-h3" - > - <a - class="document-outline__button" - href="#block-clientId_1" - > - <span - aria-hidden="true" - class="document-outline__emdash" - /> - <strong - class="document-outline__level" - > - H3 - </strong> - <span - class="document-outline__item-content" - > - Heading 3 - </span> - </a> - </li> -</ul> -`; - -exports[`DocumentOutline header blocks present should render warnings for multiple h1 headings 1`] = ` -<ul> - <li - class="document-outline__item is-h1 is-invalid" - > - <a - class="document-outline__button" - href="#block-clientId_0" - > - <span - aria-hidden="true" - class="document-outline__emdash" - /> - <strong - class="document-outline__level" - > - H1 - </strong> - <span - class="document-outline__item-content" - > - Heading 1 - <br /> - <em> - (Multiple H1 headings are not recommended) - </em> - </span> - </a> - </li> - <li - class="document-outline__item is-h1 is-invalid" - > - <a - class="document-outline__button" - href="#block-clientId_2" - > - <span - aria-hidden="true" - class="document-outline__emdash" - /> - <strong - class="document-outline__level" - > - H1 - </strong> - <span - class="document-outline__item-content" - > - Heading 1 - <br /> - <em> - (Multiple H1 headings are not recommended) - </em> - </span> - </a> - </li> -</ul> -`; diff --git a/packages/editor/src/components/document-outline/test/index.js b/packages/editor/src/components/document-outline/test/index.js deleted file mode 100644 index b396d7cc78349f..00000000000000 --- a/packages/editor/src/components/document-outline/test/index.js +++ /dev/null @@ -1,185 +0,0 @@ -/** - * External dependencies - */ -import { render, screen, within } from '@testing-library/react'; - -/** - * WordPress dependencies - */ -import { - createBlock, - registerBlockType, - unregisterBlockType, -} from '@wordpress/blocks'; -import { useSelect } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import DocumentOutline from '../'; - -jest.mock( '@wordpress/block-editor', () => ( { - BlockTitle: () => 'Block Title', -} ) ); -jest.mock( '@wordpress/data/src/components/use-select', () => jest.fn() ); - -function setupMockSelect( blocks ) { - useSelect.mockImplementation( ( mapSelect ) => { - return mapSelect( () => ( { - getBlocks: () => blocks, - getEditedPostAttribute: () => null, - getPostType: () => null, - } ) ); - } ); -} - -describe( 'DocumentOutline', () => { - let paragraph, headingH1, headingH2, headingH3, nestedHeading; - beforeAll( () => { - registerBlockType( 'core/heading', { - category: 'text', - title: 'Heading', - edit: () => {}, - save: () => {}, - attributes: { - level: { - type: 'number', - default: 2, - }, - content: { - type: 'string', - }, - }, - } ); - - registerBlockType( 'core/paragraph', { - category: 'text', - title: 'Paragraph', - edit: () => {}, - save: () => {}, - } ); - - registerBlockType( 'core/columns', { - category: 'text', - title: 'Paragraph', - edit: () => {}, - save: () => {}, - } ); - - paragraph = createBlock( 'core/paragraph' ); - headingH1 = createBlock( 'core/heading', { - content: 'Heading 1', - level: 1, - } ); - headingH2 = createBlock( 'core/heading', { - content: 'Heading 2', - level: 2, - } ); - headingH3 = createBlock( 'core/heading', { - content: 'Heading 3', - level: 3, - } ); - nestedHeading = createBlock( 'core/columns', undefined, [ headingH3 ] ); - } ); - - afterAll( () => { - unregisterBlockType( 'core/heading' ); - unregisterBlockType( 'core/paragraph' ); - } ); - - describe( 'no header blocks present', () => { - it( 'should not render when no blocks provided', () => { - setupMockSelect( [] ); - render( <DocumentOutline /> ); - - expect( screen.queryByRole( 'list' ) ).not.toBeInTheDocument(); - } ); - - it( 'should not render when no heading blocks provided', () => { - const blocks = [ paragraph ].map( ( block, index ) => { - // Set client IDs to a predictable value. - return { ...block, clientId: `clientId_${ index }` }; - } ); - setupMockSelect( blocks ); - render( <DocumentOutline /> ); - - expect( screen.queryByRole( 'list' ) ).not.toBeInTheDocument(); - } ); - } ); - - describe( 'header blocks present', () => { - it( 'should match snapshot', () => { - const blocks = [ headingH2, headingH3 ].map( ( block, index ) => { - // Set client IDs to a predictable value. - return { ...block, clientId: `clientId_${ index }` }; - } ); - setupMockSelect( blocks ); - render( <DocumentOutline /> ); - - expect( screen.getByRole( 'list' ) ).toMatchSnapshot(); - } ); - - it( 'should render an item when only one heading provided', () => { - const blocks = [ headingH2 ]; - setupMockSelect( blocks ); - render( <DocumentOutline /> ); - - const tableOfContentItem = within( - screen.getByRole( 'list' ) - ).getByRole( 'listitem' ); - expect( tableOfContentItem ).toBeInTheDocument(); - expect( tableOfContentItem ).toHaveTextContent( 'Heading 2' ); - } ); - - it( 'should render two items when two headings and some paragraphs provided', () => { - const blocks = [ - paragraph, - headingH2, - paragraph, - headingH3, - paragraph, - ]; - setupMockSelect( blocks ); - render( <DocumentOutline /> ); - - expect( - within( screen.getByRole( 'list' ) ).getAllByRole( 'listitem' ) - ).toHaveLength( 2 ); - } ); - - it( 'should render warnings for multiple h1 headings', () => { - const blocks = [ headingH1, paragraph, headingH1, paragraph ].map( - ( block, index ) => { - // Set client IDs to a predictable value. - return { ...block, clientId: `clientId_${ index }` }; - } - ); - setupMockSelect( blocks ); - render( <DocumentOutline /> ); - - expect( screen.getByRole( 'list' ) ).toMatchSnapshot(); - } ); - } ); - - describe( 'nested headings', () => { - it( 'should render even if the heading is nested', () => { - const blocks = [ headingH2, nestedHeading ]; - setupMockSelect( blocks ); - render( <DocumentOutline /> ); - - // Unnested heading and nested heading should appear as items. - const tableOfContentItems = within( - screen.getByRole( 'list' ) - ).getAllByRole( 'listitem' ); - expect( tableOfContentItems ).toHaveLength( 2 ); - - // Unnested heading test. - expect( tableOfContentItems[ 0 ] ).toHaveTextContent( 'H2' ); - expect( tableOfContentItems[ 0 ] ).toHaveTextContent( 'Heading 2' ); - - // Nested heading test. - expect( tableOfContentItems[ 1 ] ).toHaveTextContent( 'H3' ); - expect( tableOfContentItems[ 1 ] ).toHaveTextContent( 'Heading 3' ); - } ); - } ); -} ); diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 92a5cd0eec87d8..4afa2f614fa2c3 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -8,7 +8,7 @@ import { decodeEntities } from '@wordpress/html-entities'; import { store as coreStore } from '@wordpress/core-data'; import { __, sprintf, _x } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; -import { useMemo, useState } from '@wordpress/element'; +import { useMemo, useState, useEffect } from '@wordpress/element'; import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; import { parse } from '@wordpress/blocks'; import { DataForm, isItemValid } from '@wordpress/dataviews'; @@ -589,6 +589,10 @@ export function usePostActions( { postType, onActionPerformed, context } ) { }, [ postType ] ); + const { registerPostTypeActions } = unlock( useDispatch( editorStore ) ); + useEffect( () => { + registerPostTypeActions( postType ); + }, [ registerPostTypeActions, postType ] ); const duplicatePostAction = useDuplicatePostAction( postType ); const reorderPagesAction = useReorderPagesAction( postType ); diff --git a/packages/editor/src/dataviews/actions/export-pattern.native.tsx b/packages/editor/src/dataviews/actions/export-pattern.native.tsx new file mode 100644 index 00000000000000..c58cffcbd79e89 --- /dev/null +++ b/packages/editor/src/dataviews/actions/export-pattern.native.tsx @@ -0,0 +1,3 @@ +const exportPattern = undefined; + +export default exportPattern; diff --git a/packages/editor/src/dataviews/actions/index.ts b/packages/editor/src/dataviews/actions/index.ts deleted file mode 100644 index 04addcb1cde4d2..00000000000000 --- a/packages/editor/src/dataviews/actions/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * WordPress dependencies - */ -import { type StoreDescriptor, dispatch } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import deletePost from './delete-post'; -import exportPattern from './export-pattern'; -import resetPost from './reset-post'; -import trashPost from './trash-post'; -import permanentlyDeletePost from './permanently-delete-post'; -import restorePost from './restore-post'; - -// @ts-ignore -import { store as editorStore } from '../../store'; -import { unlock } from '../../lock-unlock'; - -export default function registerDefaultActions() { - const { registerEntityAction } = unlock( - dispatch( editorStore as StoreDescriptor ) - ); - - registerEntityAction( 'postType', 'wp_block', exportPattern ); - registerEntityAction( 'postType', '*', resetPost ); - registerEntityAction( 'postType', '*', restorePost ); - registerEntityAction( 'postType', '*', deletePost ); - registerEntityAction( 'postType', '*', trashPost ); - registerEntityAction( 'postType', '*', permanentlyDeletePost ); -} diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 562e4140ed806a..745cc0ad82e934 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -1,7 +1,22 @@ /** * WordPress dependencies */ +import { store as coreStore } from '@wordpress/core-data'; import type { Action } from '@wordpress/dataviews'; +import { doAction } from '@wordpress/hooks'; + +/** + * Internal dependencies + */ +import deletePost from '../actions/delete-post'; +import exportPattern from '../actions/export-pattern'; +import resetPost from '../actions/reset-post'; +import trashPost from '../actions/trash-post'; +import permanentlyDeletePost from '../actions/permanently-delete-post'; +import restorePost from '../actions/restore-post'; +import type { PostType } from '../types'; +import { store as editorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; export function registerEntityAction< Item >( kind: string, @@ -28,3 +43,56 @@ export function unregisterEntityAction( actionId, }; } + +export function setIsReady( kind: string, name: string ) { + return { + type: 'SET_IS_READY' as const, + kind, + name, + }; +} + +export const registerPostTypeActions = + ( postType: string ) => + async ( { registry }: { registry: any } ) => { + const isReady = unlock( registry.select( editorStore ) ).isEntityReady( + 'postType', + postType + ); + if ( isReady ) { + return; + } + + unlock( registry.dispatch( editorStore ) ).setIsReady( + 'postType', + postType + ); + + const postTypeConfig = ( await registry + .resolveSelect( coreStore ) + .getPostType( postType ) ) as PostType; + + const actions = [ + postTypeConfig.slug === 'wp_block' ? exportPattern : undefined, + resetPost, + restorePost, + deletePost, + trashPost, + permanentlyDeletePost, + ]; + + registry.batch( () => { + actions.forEach( ( action ) => { + if ( action === undefined ) { + return; + } + unlock( registry.dispatch( editorStore ) ).registerEntityAction( + 'postType', + postType, + action + ); + } ); + } ); + + doAction( 'core.registerPostTypeActions', postType ); + }; diff --git a/packages/editor/src/dataviews/store/private-selectors.ts b/packages/editor/src/dataviews/store/private-selectors.ts index bbe3d7ca95c7c1..117c5b30966a39 100644 --- a/packages/editor/src/dataviews/store/private-selectors.ts +++ b/packages/editor/src/dataviews/store/private-selectors.ts @@ -1,22 +1,14 @@ -/** - * WordPress dependencies - */ -import { createSelector } from '@wordpress/data'; - /** * Internal dependencies */ import type { State } from './reducer'; -export const getEntityActions = createSelector( - ( state: State, kind: string, name: string ) => { - return [ - ...( state.actions[ kind ]?.[ name ] ?? [] ), - ...( state.actions[ kind ]?.[ '*' ] ?? [] ), - ]; - }, - ( state: State, kind: string, name: string ) => [ - state.actions[ kind ]?.[ name ], - state.actions[ kind ]?.[ '*' ], - ] -); +const EMPTY_ARRAY = [] as []; + +export function getEntityActions( state: State, kind: string, name: string ) { + return state.actions[ kind ]?.[ name ] ?? EMPTY_ARRAY; +} + +export function isEntityReady( state: State, kind: string, name: string ) { + return state.isReady[ kind ]?.[ name ]; +} diff --git a/packages/editor/src/dataviews/store/reducer.ts b/packages/editor/src/dataviews/store/reducer.ts index 0e66fc0fcac72c..9124b74f02860a 100644 --- a/packages/editor/src/dataviews/store/reducer.ts +++ b/packages/editor/src/dataviews/store/reducer.ts @@ -6,13 +6,31 @@ import type { Action } from '@wordpress/dataviews'; type ReduxAction = | ReturnType< typeof import('./private-actions').registerEntityAction > - | ReturnType< typeof import('./private-actions').unregisterEntityAction >; + | ReturnType< typeof import('./private-actions').unregisterEntityAction > + | ReturnType< typeof import('./private-actions').setIsReady >; export type ActionState = Record< string, Record< string, Action< any >[] > >; +export type ReadyState = Record< string, Record< string, boolean > >; export type State = { actions: ActionState; + isReady: ReadyState; }; +function isReady( state: ReadyState = {}, action: ReduxAction ) { + switch ( action.type ) { + case 'SET_IS_READY': + return { + ...state, + [ action.kind ]: { + ...state[ action.kind ], + [ action.name ]: true, + }, + }; + } + + return state; +} + function actions( state: ActionState = {}, action: ReduxAction ) { switch ( action.type ) { case 'REGISTER_ENTITY_ACTION': @@ -48,4 +66,5 @@ function actions( state: ActionState = {}, action: ReduxAction ) { export default combineReducers( { actions, + isReady, } ); diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts index fd569aa21769c9..47f11c88bfb978 100644 --- a/packages/editor/src/dataviews/types.ts +++ b/packages/editor/src/dataviews/types.ts @@ -36,5 +36,9 @@ export type PostWithPermissions = Post & { }; }; +export interface PostType { + slug: string; +} + // Will be unnecessary after typescript 5.0 upgrade. export type CoreDataError = { message?: string; code?: string }; diff --git a/packages/editor/src/private-apis.js b/packages/editor/src/private-apis.js index f949be8e9321fb..a8a74d20261ce4 100644 --- a/packages/editor/src/private-apis.js +++ b/packages/editor/src/private-apis.js @@ -23,7 +23,6 @@ import { mergeBaseAndUserConfigs, GlobalStylesProvider, } from './components/global-styles-provider'; -import registerDefaultActions from './dataviews/actions'; import { registerCoreBlockBindingsSources, bootstrapBlockBindingsSourcesFromServer, @@ -46,7 +45,6 @@ lock( privateApis, { ToolsMoreMenuGroup, ViewMoreMenuGroup, ResizableEditor, - registerDefaultActions, registerCoreBlockBindingsSources, bootstrapBlockBindingsSourcesFromServer, diff --git a/packages/editor/src/store/private-selectors.js b/packages/editor/src/store/private-selectors.js index 6a6c8702a02217..357a7344f631d4 100644 --- a/packages/editor/src/store/private-selectors.js +++ b/packages/editor/src/store/private-selectors.js @@ -25,7 +25,10 @@ import { getCurrentPost, __experimentalGetDefaultTemplatePartAreas, } from './selectors'; -import { getEntityActions as _getEntityActions } from '../dataviews/store/private-selectors'; +import { + getEntityActions as _getEntityActions, + isEntityReady as _isEntityReady, +} from '../dataviews/store/private-selectors'; const EMPTY_INSERTION_POINT = { rootClientId: undefined, @@ -164,6 +167,10 @@ export function getEntityActions( state, ...args ) { return _getEntityActions( state.dataviews, ...args ); } +export function isEntityReady( state, ...args ) { + return _isEntityReady( state.dataviews, ...args ); +} + /** * Similar to getBlocksByName in @wordpress/block-editor, but only returns the top-most * blocks that aren't descendants of the query block. From 1afa442d7eea1e92cbe2aee2c5336c59aa283f0e Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Fri, 2 Aug 2024 05:20:12 -0500 Subject: [PATCH 0232/1908] Keep top level block selection if entering zoom out mode (#64178) * Keep top level block selection if entering zoom out mode * Update packages/block-editor/src/store/actions.js * Update packages/block-editor/src/store/actions.js --------- Co-authored-by: Ben Dwyer <ben@scruffian.com> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> --- packages/block-editor/src/store/actions.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index f7da8fa14b382a..319398667293e4 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1683,11 +1683,19 @@ export const __unstableSetEditorMode = if ( sectionRootClientId ) { const sectionClientIds = select.getBlockOrder( sectionRootClientId ); - sectionClientId = select - .getBlockParents( firstSelectedClientId ) - .find( ( parent ) => - sectionClientIds.includes( parent ) - ); + + // If the selected block is a section block, use it. + if ( sectionClientIds?.includes( firstSelectedClientId ) ) { + sectionClientId = firstSelectedClientId; + } else { + // If the selected block is not a section block, find + // the parent section that contains the selected block. + sectionClientId = select + .getBlockParents( firstSelectedClientId ) + .find( ( parent ) => + sectionClientIds.includes( parent ) + ); + } } else { sectionClientId = select.getBlockHierarchyRootClientId( firstSelectedClientId From eea8d0844df950103b88c0fe6a905ee1e0c16f7d Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 2 Aug 2024 21:35:40 +0900 Subject: [PATCH 0233/1908] Guide: Add `__next40pxDefaultSize` to buttons (#64181) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/guide/index.tsx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index e77ae39ddb3d20..0c0fab401d02a8 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -12,6 +12,7 @@ - `TimeInput`: Expose as subcomponent of `TimePicker` ([#63145](https://github.com/WordPress/gutenberg/pull/63145)). - `RadioControl`: add support for option help text ([#63751](https://github.com/WordPress/gutenberg/pull/63751)). +- `Guide`: Add `__next40pxDefaultSize` to buttons ([#64181](https://github.com/WordPress/gutenberg/pull/64181)). ### Internal diff --git a/packages/components/src/guide/index.tsx b/packages/components/src/guide/index.tsx index afb39e7bd12b50..0ca5957fd3a656 100644 --- a/packages/components/src/guide/index.tsx +++ b/packages/components/src/guide/index.tsx @@ -144,6 +144,7 @@ function Guide( { className="components-guide__back-button" variant="tertiary" onClick={ goBack } + __next40pxDefaultSize > { __( 'Previous' ) } </Button> @@ -153,6 +154,7 @@ function Guide( { className="components-guide__forward-button" variant="primary" onClick={ goForward } + __next40pxDefaultSize > { __( 'Next' ) } </Button> From 66982154cd3613c8fba8b0862bebf0015873d0bf Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Fri, 2 Aug 2024 14:36:13 +0200 Subject: [PATCH 0234/1908] Update column input to be default 40px. (#64190) * Update column input to be default 40px. * Change label to default placement --------- Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/block-library/src/column/edit.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/column/edit.js b/packages/block-library/src/column/edit.js index 2d399f392278c6..a0f3cdcf65393d 100644 --- a/packages/block-library/src/column/edit.js +++ b/packages/block-library/src/column/edit.js @@ -33,8 +33,8 @@ function ColumnInspectorControls( { width, setAttributes } ) { <PanelBody title={ __( 'Settings' ) }> <UnitControl label={ __( 'Width' ) } - labelPosition="edge" - __unstableInputWidth="80px" + __unstableInputWidth="calc(50% - 8px)" + __next40pxDefaultSize value={ width || '' } onChange={ ( nextWidth ) => { nextWidth = 0 > parseFloat( nextWidth ) ? '0' : nextWidth; From f9216d7731c331b940d14f04f4a9b50528e545bc Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:34:15 +0300 Subject: [PATCH 0235/1908] Components: Cleanup flaky unit test sleep() hacks (#64205) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: diegohaz <hazdiego@git.wordpress.org> --- .../alignment-matrix-control/test/index.tsx | 4 +-- .../src/circular-option-picker/test/index.tsx | 5 +--- .../src/composite/legacy/test/index.tsx | 18 +------------ .../custom-select-control-v2/test/index.tsx | 7 +----- .../src/custom-select-control/test/index.tsx | 6 ----- .../src/dropdown-menu-v2/test/index.tsx | 5 +--- .../components/src/tab-panel/test/index.tsx | 9 +------ packages/components/src/tabs/test/index.tsx | 25 +------------------ .../src/toggle-group-control/test/index.tsx | 6 ----- .../components/src/tooltip/test/index.tsx | 5 ---- 10 files changed, 7 insertions(+), 83 deletions(-) diff --git a/packages/components/src/alignment-matrix-control/test/index.tsx b/packages/components/src/alignment-matrix-control/test/index.tsx index 57c13f8c92eee0..a820b69b26c8ff 100644 --- a/packages/components/src/alignment-matrix-control/test/index.tsx +++ b/packages/components/src/alignment-matrix-control/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { render, screen, waitFor, within } from '@testing-library/react'; -import { press, click, sleep } from '@ariakit/test'; +import { press, click } from '@ariakit/test'; /** * Internal dependencies @@ -39,7 +39,6 @@ describe( 'AlignmentMatrixControl', () => { it( 'should be centered by default', async () => { await renderAndInitCompositeStore( <AlignmentMatrixControl /> ); - await sleep(); await press.Tab(); expect( getCell( 'center center' ) ).toHaveFocus(); @@ -110,7 +109,6 @@ describe( 'AlignmentMatrixControl', () => { <AlignmentMatrixControl onChange={ spy } /> ); - await sleep(); await press.Tab(); await press[ keyRef ](); diff --git a/packages/components/src/circular-option-picker/test/index.tsx b/packages/components/src/circular-option-picker/test/index.tsx index 0b5ccbeecb57d8..a6e9f2c45a05ce 100644 --- a/packages/components/src/circular-option-picker/test/index.tsx +++ b/packages/components/src/circular-option-picker/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { render, screen } from '@testing-library/react'; -import { press, sleep } from '@ariakit/test'; +import { press } from '@ariakit/test'; /** * Internal dependencies @@ -70,7 +70,6 @@ describe( 'CircularOptionPicker', () => { /> ); - await sleep(); await press.Tab(); expect( getOption( 'Option One' ) ).toHaveFocus(); await press.ArrowRight(); @@ -90,7 +89,6 @@ describe( 'CircularOptionPicker', () => { /> ); - await sleep(); await press.Tab(); expect( getOption( 'Option One' ) ).toHaveFocus(); await press.ArrowRight(); @@ -110,7 +108,6 @@ describe( 'CircularOptionPicker', () => { /> ); - await sleep(); await press.Tab(); expect( getOption( 'Option One' ) ).toHaveFocus(); await press.ArrowRight(); diff --git a/packages/components/src/composite/legacy/test/index.tsx b/packages/components/src/composite/legacy/test/index.tsx index 085ac572e3e8a1..07398e54b27ca3 100644 --- a/packages/components/src/composite/legacy/test/index.tsx +++ b/packages/components/src/composite/legacy/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { queryByAttribute, render, screen } from '@testing-library/react'; -import { press, sleep, waitFor } from '@ariakit/test'; +import { press, waitFor } from '@ariakit/test'; /** * Internal dependencies @@ -178,13 +178,10 @@ describe.each( [ ); renderAndValidate( <Test /> ); - await sleep(); await press.Tab(); expect( screen.getByText( 'Before' ) ).toHaveFocus(); - await sleep(); await press.Tab(); expect( screen.getByText( 'Item 1' ) ).toHaveFocus(); - await sleep(); await press.Tab(); expect( screen.getByText( 'After' ) ).toHaveFocus(); await press.ShiftTab(); @@ -213,7 +210,6 @@ describe.each( [ expect( item2 ).toBeDisabled(); - await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -243,7 +239,6 @@ describe.each( [ expect( item2 ).toBeEnabled(); expect( item2 ).toHaveAttribute( 'aria-disabled', 'true' ); - await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -279,7 +274,6 @@ describe.each( [ renderAndValidate( <Test /> ); const { item2 } = getOneDimensionalItems(); - await sleep(); await press.Tab(); await waitFor( () => expect( item2 ).toHaveFocus() ); } ); @@ -323,7 +317,6 @@ describe.each( [ test( 'All directions work with no orientation', async () => { const { item1, item2, item3 } = useOneDimensionalTest(); - await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -361,7 +354,6 @@ describe.each( [ orientation: 'horizontal', } ); - await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -391,7 +383,6 @@ describe.each( [ orientation: 'vertical', } ); - await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press( next ); @@ -421,7 +412,6 @@ describe.each( [ loop: true, } ); - await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -444,7 +434,6 @@ describe.each( [ const { itemA1, itemA2, itemA3, itemB1, itemB2, itemC1, itemC3 } = useTwoDimensionalTest(); - await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press.ArrowUp(); @@ -481,7 +470,6 @@ describe.each( [ const { itemA1, itemA2, itemA3, itemB1, itemC1, itemC3 } = useTwoDimensionalTest( { loop: true } ); - await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press( next ); @@ -506,7 +494,6 @@ describe.each( [ const { itemA1, itemA2, itemA3, itemB1, itemC1, itemC3 } = useTwoDimensionalTest( { wrap: true } ); - await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press( next ); @@ -539,7 +526,6 @@ describe.each( [ wrap: true, } ); - await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press( previous ); @@ -555,7 +541,6 @@ describe.each( [ test( 'Focus shifts if vertical neighbour unavailable when shift enabled', async () => { const { itemA1, itemB1, itemB2, itemC1 } = useShiftTest( true ); - await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press.ArrowDown(); @@ -577,7 +562,6 @@ describe.each( [ test( 'Focus does not shift if vertical neighbour unavailable when shift not enabled', async () => { const { itemA1, itemB1, itemB2 } = useShiftTest( false ); - await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press.ArrowDown(); diff --git a/packages/components/src/custom-select-control-v2/test/index.tsx b/packages/components/src/custom-select-control-v2/test/index.tsx index e02eb0f774a401..060a367ba8597b 100644 --- a/packages/components/src/custom-select-control-v2/test/index.tsx +++ b/packages/components/src/custom-select-control-v2/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { screen } from '@testing-library/react'; -import { click, press, sleep, type } from '@ariakit/test'; +import { click, press, type } from '@ariakit/test'; import { render } from '@ariakit/test/react'; /** @@ -101,7 +101,6 @@ describe.each( [ expanded: false, } ); - await sleep(); await press.Tab(); await press.Enter(); expect( @@ -128,7 +127,6 @@ describe.each( [ expanded: false, } ); - await sleep(); await press.Tab(); expect( currentSelectedItem ).toHaveFocus(); @@ -152,7 +150,6 @@ describe.each( [ expanded: false, } ); - await sleep(); await press.Tab(); await press.Enter(); expect( @@ -173,7 +170,6 @@ describe.each( [ expanded: false, } ); - await sleep(); await press.Tab(); expect( currentSelectedItem ).toHaveFocus(); expect( currentSelectedItem ).toHaveTextContent( 'violets' ); @@ -425,7 +421,6 @@ describe.each( [ expanded: false, } ); - await sleep(); await press.Tab(); expect( currentSelectedItem ).toHaveFocus(); expect( currentSelectedItem ).toHaveTextContent( items[ 0 ].value ); diff --git a/packages/components/src/custom-select-control/test/index.tsx b/packages/components/src/custom-select-control/test/index.tsx index fcab84773e5a0b..fdbe8d72a48dec 100644 --- a/packages/components/src/custom-select-control/test/index.tsx +++ b/packages/components/src/custom-select-control/test/index.tsx @@ -196,7 +196,6 @@ describe.each( [ expanded: false, } ); - await sleep(); await press.Tab(); await press.Enter(); expect( @@ -388,7 +387,6 @@ describe.each( [ await render( <Component { ...props } onChange={ mockOnChange } /> ); - await sleep(); await press.Tab(); expect( screen.getByRole( 'combobox', { @@ -494,7 +492,6 @@ describe.each( [ expanded: false, } ); - await sleep(); await press.Tab(); expect( currentSelectedItem ).toHaveFocus(); @@ -520,7 +517,6 @@ describe.each( [ expanded: false, } ); - await sleep(); await press.Tab(); await press.Enter(); expect( @@ -541,7 +537,6 @@ describe.each( [ expanded: false, } ); - await sleep(); await press.Tab(); expect( currentSelectedItem ).toHaveFocus(); expect( currentSelectedItem ).toHaveTextContent( @@ -571,7 +566,6 @@ describe.each( [ expanded: false, } ); - await sleep(); await press.Tab(); expect( currentSelectedItem ).toHaveFocus(); expect( currentSelectedItem ).toHaveTextContent( diff --git a/packages/components/src/dropdown-menu-v2/test/index.tsx b/packages/components/src/dropdown-menu-v2/test/index.tsx index 2829fbb8fefce0..5457f5e73e23c3 100644 --- a/packages/components/src/dropdown-menu-v2/test/index.tsx +++ b/packages/components/src/dropdown-menu-v2/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { render, screen, waitFor } from '@testing-library/react'; -import { press, click, hover, sleep, type } from '@ariakit/test'; +import { press, click, hover, type } from '@ariakit/test'; /** * WordPress dependencies @@ -128,7 +128,6 @@ describe( 'DropdownMenu', () => { } ); // Move focus on the toggle - await sleep(); await press.Tab(); expect( toggleButton ).toHaveFocus(); @@ -159,7 +158,6 @@ describe( 'DropdownMenu', () => { } ); // Move focus on the toggle - await sleep(); await press.Tab(); expect( toggleButton ).toHaveFocus(); @@ -915,7 +913,6 @@ describe( 'DropdownMenu', () => { // The outer button can be focused by pressing tab. Doing so will cause // the DropdownMenu to close. - await sleep(); await press.Tab(); expect( outerButton ).toBeInTheDocument(); expect( screen.queryByRole( 'menu' ) ).not.toBeInTheDocument(); diff --git a/packages/components/src/tab-panel/test/index.tsx b/packages/components/src/tab-panel/test/index.tsx index 65827040f1e34c..28dd1a81e9e84f 100644 --- a/packages/components/src/tab-panel/test/index.tsx +++ b/packages/components/src/tab-panel/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { render, screen, waitFor } from '@testing-library/react'; -import { press, hover, click, sleep } from '@ariakit/test'; +import { press, hover, click } from '@ariakit/test'; /** * WordPress dependencies @@ -155,7 +155,6 @@ describe.each( [ // Tab to focus the tablist. Make sure alpha is focused, and that the // corresponding tooltip is shown. expect( screen.queryByText( 'Alpha' ) ).not.toBeInTheDocument(); - await sleep(); await press.Tab(); expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); expect( screen.getByText( 'Alpha' ) ).toBeInTheDocument(); @@ -627,7 +626,6 @@ describe.each( [ // Tab to focus the tablist. Make sure alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); - await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -665,7 +663,6 @@ describe.each( [ // Tab to focus the tablist. Make sure Alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); - await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -703,7 +700,6 @@ describe.each( [ // Tab to focus the tablist. Make sure alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); - await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -799,7 +795,6 @@ describe.each( [ // Tab to focus the tablist. Make sure Alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); - await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); @@ -841,7 +836,6 @@ describe.each( [ // Tab should initially focus the first tab in the tablist, which // is Alpha. - await sleep(); await press.Tab(); expect( await screen.findByRole( 'tab', { name: 'Alpha' } ) @@ -849,7 +843,6 @@ describe.each( [ // Because all other tabs should have `tabindex=-1`, pressing Tab // should NOT move the focus to the next tab, which is Beta. - await sleep(); await press.Tab(); expect( await screen.findByRole( 'tab', { name: 'Beta' } ) diff --git a/packages/components/src/tabs/test/index.tsx b/packages/components/src/tabs/test/index.tsx index 382163f69e8e36..0563b0227d106e 100644 --- a/packages/components/src/tabs/test/index.tsx +++ b/packages/components/src/tabs/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { screen, waitFor } from '@testing-library/react'; -import { press, click, sleep } from '@ariakit/test'; +import { press, click } from '@ariakit/test'; import { render } from '@ariakit/test/react'; /** @@ -195,14 +195,12 @@ describe( 'Tabs', () => { // Tab should initially focus the first tab in the tablist, which // is Alpha. - await sleep(); await press.Tab(); expect( await screen.findByRole( 'tab', { name: 'Alpha' } ) ).toHaveFocus(); // By default the tabpanel should receive focus - await sleep(); await press.Tab(); expect( selectedTabPanel ).toHaveFocus(); } ); @@ -232,14 +230,12 @@ describe( 'Tabs', () => { // Tab should initially focus the first tab in the tablist, which // is Alpha. - await sleep(); await press.Tab(); expect( await screen.findByRole( 'tab', { name: 'Alpha' } ) ).toHaveFocus(); // Because the alpha tabpanel is set to `focusable: false`, pressing // the Tab key should focus the button, not the tabpanel - await sleep(); await press.Tab(); expect( alphaButton ).toHaveFocus(); } ); @@ -264,7 +260,6 @@ describe( 'Tabs', () => { /> ); - await sleep(); await press.Tab(); expect( await screen.findByRole( 'tab', { name: 'Beta' } ) @@ -348,7 +343,6 @@ describe( 'Tabs', () => { // Tab to focus the tablist. Make sure alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); - await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -382,7 +376,6 @@ describe( 'Tabs', () => { // Tab to focus the tablist. Make sure Alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); - await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -418,7 +411,6 @@ describe( 'Tabs', () => { // Tab to focus the tablist. Make sure alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); - await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -518,7 +510,6 @@ describe( 'Tabs', () => { // Tab to focus the tablist. Make sure Alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); - await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); // Confirm onSelect has not been re-called @@ -561,7 +552,6 @@ describe( 'Tabs', () => { // Tab should initially focus the first tab in the tablist, which // is Alpha. - await sleep(); await press.Tab(); expect( await screen.findByRole( 'tab', { name: 'Alpha' } ) @@ -570,7 +560,6 @@ describe( 'Tabs', () => { // Because all other tabs should have `tabindex=-1`, pressing Tab // should NOT move the focus to the next tab, which is Beta. // Instead, focus should go to the currently selected tabpanel (alpha). - await sleep(); await press.Tab(); expect( await screen.findByRole( 'tabpanel', { @@ -881,7 +870,6 @@ describe( 'Tabs', () => { expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); // Move focus to the tablist, make sure alpha is focused. - await sleep(); await press.Tab(); expect( screen.getByRole( 'tab', { name: 'Alpha' } ) @@ -1239,12 +1227,6 @@ describe( 'Tabs', () => { /> ); - // Due to the timing of the component re-rendering, we - // need to force a delay to ensure the test doesn't run - // the upcoming assertions too early. - // see https://github.com/WordPress/gutenberg/pull/58629#issuecomment-1924875249 - await sleep(); - // Tab key should focus the currently selected tab, which is Beta. await press.Tab(); await waitFor( async () => @@ -1292,9 +1274,7 @@ describe( 'Tabs', () => { ); // Tab key should focus the currently selected tab, which is Beta. - await sleep(); await press.Tab(); - await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveTextContent( 'Beta' @@ -1329,7 +1309,6 @@ describe( 'Tabs', () => { ).toHaveFocus(); // Press tab, move focus back to the tablist - await sleep(); await press.Tab(); const betaTab = screen.getByRole( 'tab', { @@ -1353,7 +1332,6 @@ describe( 'Tabs', () => { <ControlledTabs tabs={ TABS } selectedTabId="beta" /> ); - await sleep(); await press.Tab(); // Tab key should focus the currently selected tab, which is Beta. @@ -1379,7 +1357,6 @@ describe( 'Tabs', () => { expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); // Tab key should focus the currently selected tab, which is Beta. - await sleep(); await press.Tab(); await waitFor( async () => expect( diff --git a/packages/components/src/toggle-group-control/test/index.tsx b/packages/components/src/toggle-group-control/test/index.tsx index 098407feef1493..661bbb9fc37bab 100644 --- a/packages/components/src/toggle-group-control/test/index.tsx +++ b/packages/components/src/toggle-group-control/test/index.tsx @@ -341,11 +341,9 @@ describe.each( [ name: 'R', } ); - await sleep(); await press.Tab(); expect( rigas ).toHaveFocus(); - await sleep(); await press.Tab(); // When in controlled mode, there is an additional "Reset" button. @@ -372,7 +370,6 @@ describe.each( [ </Component> ); - await sleep(); await press.Tab(); expect( @@ -448,7 +445,6 @@ describe.each( [ </Component> ); - await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { @@ -457,7 +453,6 @@ describe.each( [ } ) ).toHaveFocus(); - await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { @@ -490,7 +485,6 @@ describe.each( [ </Component> ); - await sleep(); await press.Tab(); expect( diff --git a/packages/components/src/tooltip/test/index.tsx b/packages/components/src/tooltip/test/index.tsx index e406ff997c7295..67922ab1d5ac41 100644 --- a/packages/components/src/tooltip/test/index.tsx +++ b/packages/components/src/tooltip/test/index.tsx @@ -59,7 +59,6 @@ describe( 'Tooltip', () => { screen.getByRole( 'button', { name: 'Second button' } ) ).toBeVisible(); - await sleep(); await press.Tab(); expectTooltipToBeHidden(); @@ -145,7 +144,6 @@ describe( 'Tooltip', () => { ); // Focus the anchor, tooltip should show - await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { name: 'Tooltip anchor' } ) @@ -153,7 +151,6 @@ describe( 'Tooltip', () => { await waitExpectTooltipToShow(); // Focus the other button, tooltip should hide - await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { name: 'Focus me' } ) @@ -179,13 +176,11 @@ describe( 'Tooltip', () => { expect( anchor ).toHaveAttribute( 'aria-disabled', 'true' ); // Focus anchor, tooltip should show - await sleep(); await press.Tab(); expect( anchor ).toHaveFocus(); await waitExpectTooltipToShow(); // Focus another button, tooltip should hide - await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { From 51f43666914ad064df6a9326e804607d2e4f6243 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 2 Aug 2024 19:27:42 +0300 Subject: [PATCH 0236/1908] Edit Site: Use structuredClone for deep cloning (#64203) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- .../src/hooks/push-changes-to-global-styles/index.js | 5 ++--- .../use-theme-style-variations-by-property.js | 5 ++--- packages/edit-site/src/utils/clone-deep.js | 8 -------- 3 files changed, 4 insertions(+), 14 deletions(-) delete mode 100644 packages/edit-site/src/utils/clone-deep.js diff --git a/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js b/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js index a4aa81e88393ad..c79ba67a1a7d74 100644 --- a/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js +++ b/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js @@ -26,7 +26,6 @@ import { store as coreStore } from '@wordpress/core-data'; */ import { useSupportedStyles } from '../../components/global-styles/hooks'; import { unlock } from '../../lock-unlock'; -import cloneDeep from '../../utils/clone-deep'; import setNestedValue from '../../utils/set-nested-value'; const { cleanEmptyObject, GlobalStylesContext } = unlock( @@ -259,8 +258,8 @@ function PushChangesToGlobalStylesControl( { if ( changes.length > 0 ) { const { style: blockStyles } = attributes; - const newBlockStyles = cloneDeep( blockStyles ); - const newUserConfig = cloneDeep( userConfig ); + const newBlockStyles = structuredClone( blockStyles ); + const newUserConfig = structuredClone( userConfig ); for ( const { path, value } of changes ) { setNestedValue( newBlockStyles, path, undefined ); diff --git a/packages/edit-site/src/hooks/use-theme-style-variations/use-theme-style-variations-by-property.js b/packages/edit-site/src/hooks/use-theme-style-variations/use-theme-style-variations-by-property.js index 9486f15f802899..e6e3a1ccc3aa6d 100644 --- a/packages/edit-site/src/hooks/use-theme-style-variations/use-theme-style-variations-by-property.js +++ b/packages/edit-site/src/hooks/use-theme-style-variations/use-theme-style-variations-by-property.js @@ -11,7 +11,6 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import cloneDeep from '../../utils/clone-deep'; import { unlock } from '../../lock-unlock'; const { GlobalStylesContext, areGlobalStyleConfigsEqual } = unlock( @@ -91,7 +90,7 @@ export function useCurrentMergeThemeStyleVariationsWithUserConfig( const propertiesAsString = properties.toString(); return useMemo( () => { - const clonedUserVariation = cloneDeep( userVariation ); + const clonedUserVariation = structuredClone( userVariation ); // Get user variation and remove the settings for the given property. const userVariationWithoutProperties = removePropertiesFromObject( @@ -167,7 +166,7 @@ export const filterObjectByProperties = ( object, properties ) => { */ export function isVariationWithProperties( variation, properties ) { const variationWithProperties = filterObjectByProperties( - cloneDeep( variation ), + structuredClone( variation ), properties ); diff --git a/packages/edit-site/src/utils/clone-deep.js b/packages/edit-site/src/utils/clone-deep.js deleted file mode 100644 index 149e1df2408ea7..00000000000000 --- a/packages/edit-site/src/utils/clone-deep.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Makes a copy of an object without storing any references to the original object. - * @param {Object} object - * @return {Object} The cloned object. - */ -export default function cloneDeep( object ) { - return ! object ? {} : JSON.parse( JSON.stringify( object ) ); -} From 6fdbb2ff1b2766c6cdd0904d092186ee77d97f70 Mon Sep 17 00:00:00 2001 From: Matias Ventura <mv@matiasventura.com> Date: Fri, 2 Aug 2024 13:32:26 -0300 Subject: [PATCH 0237/1908] Data Views: be more clear with the copy of the "hide" action (#63047) --- packages/dataviews/src/layouts/table/column-header-menu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataviews/src/layouts/table/column-header-menu.tsx b/packages/dataviews/src/layouts/table/column-header-menu.tsx index d0288483327258..ef1dc3e3ed2e09 100644 --- a/packages/dataviews/src/layouts/table/column-header-menu.tsx +++ b/packages/dataviews/src/layouts/table/column-header-menu.tsx @@ -249,7 +249,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( } } > <DropdownMenuItemLabel> - { __( 'Hide' ) } + { __( 'Hide column' ) } </DropdownMenuItemLabel> </DropdownMenuItem> ) } From 517fc81afe5de59281d54d0d0c4fdedd7b4198a8 Mon Sep 17 00:00:00 2001 From: Ryan Welcher <me@ryanwelcher.com> Date: Fri, 2 Aug 2024 13:50:38 -0400 Subject: [PATCH 0238/1908] Provide a better example for the PluginSidebar slotfill. (#64206) * Add more robust example and screenshot. * Use jsx instead of js for the code example. * Update docs/reference-guides/slotfills/plugin-sidebar.md * Update the import location. Co-authored-by: ryanwelcher <welcher@git.wordpress.org> Co-authored-by: juanmaguitar <juanmaguitar@git.wordpress.org> --- docs/assets/plugin-sidebar-closed-state.png | Bin 6773 -> 0 bytes docs/assets/plugin-sidebar-open-state.png | Bin 10854 -> 27542 bytes .../slotfills/plugin-sidebar.md | 68 ++++++++++++++---- 3 files changed, 53 insertions(+), 15 deletions(-) delete mode 100644 docs/assets/plugin-sidebar-closed-state.png diff --git a/docs/assets/plugin-sidebar-closed-state.png b/docs/assets/plugin-sidebar-closed-state.png deleted file mode 100644 index 025da900ffcdd594c27a097e0b6ca23928377ec1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6773 zcmeI1<y#a$yT+I94yBP)I)s%DX;?x^LP`l)>7`q81w^{prF-d+PH6>}ZbUkk?l`>X zPdL~4_<opq=DBC)!}Ggl=EFTuZB1n&d|G?}06?UwqVNs?Knr>rN8zGB^;=YPu&01& zD+iJT0IFjN?kusMa^{aJ??3>64+j7c6bb;`JV`;@0D!vy0I+KT0Enjo0MDE=n{_0g zCh(k9jNAYK0*e1MG(dXha{z#5PgOxq&kOA!3(r(<<EDRQ&cXtaws<70MwB8O$FAMo z)=LB$85pX1SIdKZ@J2QVIz`P@+!-c&nDDsuVAYRl@VfL6>GjH5=|pE@DwEdBSy-gT zJf3D_u;P7}?Qu1Oop!AqIc|Bk|4CbEU7%6)e9QxOVc;>Nv5hfeDu{@P9JqXF<sg?u zR|$%YL;FvJx8cG8_0POp`JS>_jBZ~59&_*oYmgND;$y6#61t}(8YNuffm#-z0>A&y zQYPP4A@ZhmJUC$KxDkLZi+-RCz$(6<T~CVZWY7X&ZGZ2;A_b7!$)LZKJ?LkwjK)0l zLZ6VxmK{dRlnHzoO5&!DD%b!)^3%zo`QRCZw6t^#?fHJG)G?=P8E8|<Elm}YtojiL zvpiccoF-PhiS>%-Jpl&h?#I`(`dmqRLy?ggqc#-=d;k7TYKLThsCL_%<F@{ttuPW< z+Zf$EwXgHx#twxjvsGHDA+&k(9YEY=JV1UU%~L|64PeKL?W_z}_#11TBIa&o?%(NF zO(}^LNGIQ!IL#b{J}F-+aAH-6`uG;WC?cL)E}9;xV8i|E3aX%V-<JpaPx*K@t+-F5 zV#s9C?4$7uUp$fJz|;<!#}qchd?NSjX^n^y7V^gv0Sff;%F+frh5y|k8JtiwG4o}X za0>}b_X~WiTCkEsYvyI)8Ph;-aH4s3Oa%^H%B8webA8#_G0p!jg}4HGMNR8agm~_d zpU1S$Db<(J#BKRjxv{?Bg4dkJb7NPe_<m}rsSua+sX{f{y(JBJc+mS)Q12%;B@DqX zEs^SU)tDq?N`^X8VIWLs)1Hsy+i?W%k}S`dF}t9FOUx|(qTYVtuKOq?dL_;1rw8HS z$WV0xcQ235K@k?&OxElry07fTHKf<HZ8={XQujd&E*+Xmq+qUD%3W;M2_t{y;=#`6 zsKBu${_<Snm4Q_Q>06qTm+Y=sF7BL~h)m7k(BmEPzx(pwYcJ)^4bGoSikVB1sVJ1J zwxfRA1N*#;2N?K8bG99PH>=ZwO*HGa`ePJsZI1A=8yV=m$GO~>d4B6fcsE-^?|Y*D zt8&buW6Z*&mPq%D5wV!J%P(OtFaQSxit%rKMbr=mpou9g7v8!FJ8LVD+l)VBox3*V z9#NR+8}=QjVs4^g@O^$tTp^Z2cRb75PV6+_o|7E^Z>fYzGt=xjG{bZ3hegso?S-32 zi&>zQrZ9N!GA^);=JwfVIYi|9==|I-7l}H;t-bp7vHfYWOv}K>Pk1|%VO%-~XtX+S zc?_&360+~h%m^mv?*uKtcuO|CNn~ImLH!@u_oZe8)AWnf&J!*6W`W+<Ou60?kt5K^ zOt6HmK{0XPZYgIXX<Q=pwo3nTLPyX|kYbAmDg<^@cp&428E}<&g=)CISwtp|tKCzl zyFSd*p{S{zg+yL%AD$oII=xN0el*k5^P_3zFk5QjzqYW{rTy$k<D75QUe^o=zS*C3 zJDP_Tj7gya>sW>ZBgFH)vU0biCf5(~i=N7EBazlGHC%jVg}Wd0)K`iygJs%}c9D zvwLautWnbtg>QZiqq?jdp!T$AUJ}-;cvsdk1+Hezl!wSsmY#<k?$DGryXX>~_*%ke z=DTEe>>_Z_ux=EbZ+q5TY*<S~$q8mG<EBa9V#SG*MMX#U)!}?vv%$`{ir0q}F76w7 zB}KBE`cMI#YbUI#jOGj&ZcOW%!v>nvA<@_H;LFR9_CKHrq=11S1*846M1v(kOyT~r zFZ?LCLB2A=w000Zu=^2E+y*IW{i-f#60lqwxR@FjGwm?kOLwUTHk~Sz&PvMeLJNp7 z>rPF<*<EKiTAg*iK}@h6%$mGUL{t;%sMGSUEGk6JvBarm{`^Icw5sKS!-j^!z=oJy ztG$Ws8zFso!xRMJO1_QSUnzsfnRvm;SPllWY9hGb|7wgs`f0Jn4{Y~0{<>gz%_Vfw z;;srOhD$pxu9quGjhh#-bf;9dE1ebOm>trDDMDJYck~cVZ{rz6xwAaJQ+meXGYD?) z)RC#ACI}}9YfHU}p0S`;E;HxJ?K747?ASjBM_aq!CD68zMfv*s2Mo)=vV4;-NzC?Q zW4}NHAM@3>TDXX?89ya;ja~DxkNno7Ep>RMy^1p5KsAniL)SC+=TIQ>{2TFtNJErv z6_Mn1I~7n^77>P1WP0RUv{Cmt;$k!T`A;q`_kmeUDPjjr9&Kz86EdPuf3q(THn-8P zllNBgH^+g5>3by#_HQp(^KN`}N(AkN8jJqzz)`I4t~??_Jzy>=VSO3~9IYkX!sN(n z#XpFXsN)qHm|eVb<%h>;K?#@fTz%u+klnP#2L^^kUR1=)iX?rr$6SJ5OJu-S?q?hy z{<|g^hlkvS@-e|A+@fG^c*Q8OcM6)??EG*gd;ik`x%{T%%c);dXd=D2^eysTd;Z~M zX&SdRcYA=6YKDDS2%RArS^0apbru%SFtM!s4<?Po$FQ9Eve92jPOYyM<JV7?b;Q@# zmpbgtU=HRFD~a#yRb!>cn~9brUs!SUG-PEk-5<MFJOs7A_bDv*5{GZ+pJd&~#cIsc z9&8QnG;Cg)Gks_h4xxZE`hP4H<=z<kq1w2c@hI(yeHi?k;oqQ0>fanj*ZvV(ShfJ- z!bIBRuGO}0_uS9tZ+rd^xRNq<J(bA?L89a25l-et4Q*L{YwHARIZ#%Dm5JU%S8bTK zQFl*ap5KM8Q8u_lHydzYuN(izH5HI0o`vC0pE2}W$G;PI<}f?d6tw*Cwo6J1rGI{Q zaUggU%sAP!XVl`Vp4sdbOSByzA_D{^r0r}4dfFO26r37Q;Bd%7#L`_^@N{0)D+h?1 z78{n_o*ihq3jJn7sX|~UKY)W;Z{iL4bV4I;CCsPTz!uMYms(p_9PaEhvIKUy?fD%h zXkIV;jnQgv?fg?#B%krdVVvuHn+8Q>2qr-oKfva`Ss#=6<NUY+l^AA6@2l0@=!!yp z6ddYo<bXOPr99Jo0RcMAPLthzarpwD#|@*Xxs!Qu^#=zEAr-0{yy`0%m?`4vMTR(B zzZq26q-^SwZ#u1IdAx{nOD*%kmMj=&2Bw*-*c5VzD2lkZGuYFut2qV~z>}}-ghj8j zOC8hqk#zhmy@aQ+(6l?n`M+X*GuY|%&0N;Kx`!GXmrjw#r#x+EgMY-NZZ2cb36`%Q zHl44&O;FrO4|0AtY8idLDg5!~jDPFPpz|@jjaQT4GxXxk7w*HmzMk79TU{oV;M3@l z@;Y<Pp6l_CB}W*X-#=tr?oaM)JcDgiI{G@KS`E8S4xTv8nB695iutt(Ar3HcC$~~Y zGG*}VDSnM*Ya*v2nh&U`B~s~CI<$`>ume=^cb2*BOg}LdY0CWp;RX3cjZZ2XCkMPj zO;~?;KemL!x3Tpvxdfe3tRsaC=)S^d?MraxEadYZP{OvvzOkpvxA||o`NvmRd2A&q z%0;aCBX=Nb_QS073jL-UWTzh)gQ$X+gYG=CpvB#jrm*lI#bKy^=a03mybHKcFKc5x zpw$UXl-nJ(mvOnJsL8;nDte$Y6y?`#?khB|z@mi7Js>tjNPLe{p1?~Jv30coa{iU@ zo*wMoD2v^m(Ta>u!01R;@TE(rfz}ACN+Y~EwB64rp<W`1m9xf`%u=D9Y(zWzZSEIr zED5D;DB^RL@ULI>SzOpg!;*yFGptV!+ZmbFsqFj=k!GT2u__X~rU095(}{^D(ihB~ z!PT#NWwo}=u@j(rdxfp%gOp7A+lmZ36zI_O1c~nUp<H|9Ud-GwpCz@f5>ev?|5svu zJ0?R4C5Hxz`FAEvZF)d{8m~*eWAw@C!n%`l1qkLSLuV^q#77_5vCHc`SpwlvffY%c zt5qo+-BtQc|NZFJ-G$9VI?-_;A+?KpSbE)=DadkqTyiSXY=(GWZDx|USk`+xpQ19T z{r9!l^|MIW*%uKVoLeMhpm?ktikx&x7yyKh)H`x5sBg&O?>rQHh<OCGu#tu13N+zI zn_cZE=(%aYlh0c|jS*>N(cPwwN*;#mYo?ZF)1{OL=5EEE&kd=f<XE!g%RPBu5)MBP zw2YMnUn|uMvzPU16~*=Q_)d8r(v{3ZA4(J&n5(EHWZgMBPpDs<I0|AkkK3h<*#5p3 z-&#^&2~(xHVq4=V-4mB~*H_V5qxzc<uO0AkG;%rFP4M4Z3cPIHIXd<F?9vtg$H3MZ z^qi3TZ+Q^ITUVdJAarABp9YX+9M4HGD=i#jvuekWq8y^~^EVj?Je;@60@Or!4iba` zizbIDk6wKUUy+TlKxX^ozH)q{6a=5aFs@~dLwNK#-Q)2sLe5{Qh$VV_Ad})-ROK=( zy^S^)HuzOwxWhZI`!k)(<*I5xpq@PZBX?uZDkHIXBut32Y}E^YahLH08e?c;m!nAT z{%Ln8GXfxJ#-9K=DgGTwclfI&<xr^AZLcnkf5xCPNdT|SM-jes3>yR>U+924U^)vT zLTMUS#&YMKpNtm&N+~Bw5dA9<)N^p6Ka&7|A~5KWa5=R;BAzs{*8Z^MgbCF$Z7fs} zam^X}0|IR#Okj%Q%D1O|j+0JF!q1v=EXZ$?FvV2~`8p37V;%ErqW5TiQc!G%gk8Dk z>WcbRVs8dDb3u1_^zkvin6a4}WI2eq!*Z>TGt@i0k@nx{C7C^(d!qxEPhqqV4<x37 zWTq-=85<<U?+Q3K!FuQUuJ4HMEd-Y^0WCCgA&ZHS?3QyJyF0Jlo&s}vkQkarmYPhP z|I8tDz5hh?p~?-If3($uP2zVCtGzz$cx>i&Vbb6#@$uqKeH?NyF=_o*tFD;RA5AMQ zZ9nNi0IUWOwxkQ4)YNZQU9wfm!6n8Z$SEBB7Ii|yN;~q4{LcjHkg)4P8SAc!Nu!+? z1x$9+L!~Dt-FFzbe<qjAd!=R#RnIyeay(IeqdXKOFh-$ViP}qrc0|)l|CR3|3lzdp z&^;+B3rkUN&vyZqs&Y5uS?L+g#G>d9uH9PsGaZxWx|0}rxT>Z#?DhG2MPltc)w8on zobGi^zO!!kgN1*9X@0f}+I2wUu)xstRO-NHkZvjepw<UTF^~C10S?w)37)TZx~Cvk z?AxHPplyD283Yl%4BTMe@%0$KZN2#{e!`fe!dwF6ltYc*hmVR*mUm<M6~DBA@8Y&; zDtw(p(@ZiXqNsyX%y+SPG3|w`m8O~)X!Ro&@j(4jc5tkogHO>evSha=o{&Mmmdmc1 z!jNzXx)!nbD2omW43{i65kcK?zxd~qa#p}^$eTv$bAR%y(RSKT%0acV3=(z03$#5Y z65kiG|CC=*kpu=lpcYUSMjd!&hJ6lo1+fhNdC|PpeVpFj9aNNNlG#3`#ZA2dtlEHY z_d43n7yC{Z>J9dYr&p;J+KOF}Ir7{u@MR`&+;JmFZfz#EkP7TUHS;~E)xQU)o7V3V zfa<QxtfLSMee+Wm%mIyV8O-0cs6<9YsajO=2jZ>hup;gtt23<-5F_a5f`sJs>xw@| z*dF-=AESymW?mhi+MNC&14tbb+M|l?W3?b&bQEQDQR8^HrEbHiy^h}hC(zO2AoA7U zoYak?21O~_E(~|_9%t<7RCvu}x0adFYgFwFYz0&QQ}Fn3Hp#lAuHtut!ozcd(*lv3 z@6Y8l*@=nt-Ha-((L(~E(e@!K^1k!}H%ZQPaLW;PPgt!CcyV$}t|y%2Yf0vWD~o4N z{EI>+?(m6H>5vFN!RMNz{lxn|hnWOBqoBo3wt59@f0lW-!MW<=#%$rkbCc^rriyod z4;2Nk*qm81Dcpz}m30&hb=Q7~M>KN>RV+@0k=kmBoqaV;oTlaX6w^@mmTw#u?HQ$V zno2Pj654AdDMOt<TfOE<#lzoSC<>_VaAQ0@x=NgUoiNyX7Ud-EgW{C{`QKc-!g=D< zn6ln1YgSMH-W4!cbK*l%?ZgN{CkQt6oale4HDOq5BHUq4KvzfUTD|U1fVid;U9<+% zsOpJH=JDi(lZ21`-^0SieT-+Ugt}T(c-E5|puf7DiAcMsB_rr*XlO#PgVpXfNc-B= zCok{WcQ$33t{J=>%UTmVnFsPHMmk(1eBg8#Ey<uNWW;u*V)w4Kx7-Al&pL9P^pnAz z>WF~wl8DfNeu{4DS}rqR);6m}(#*~gh=n6uZN4kGU+C;eJJt8okIV*bHg*K_m`Hxj zS4}`y0=)nxa&Oy4(Gb`?O3Qfi;|-EXPJg3L{Izv43k!h`gaZM3&x*`MKm%`Wo@HDE zc~m+s*Cq<}e70g{ZX&{87kttkDvw^kT_CP70IO)Pc07pn_igZp7~AEP4jsWrQf#)e z;|BA`lzjty4p?hIpYIy1(_08vEHSqmvfZoDD_CS1I{TCHNmGAUIFDm_mFAo|1b)QC z((+2%Ig!jF4{wtnyCg%Zvb>3ai2L`rYuGUj;kDDlCOd8HxE*j9tE#$d3kAC4-|2r< zcrG=LmO|JptPK^#)tx!JEnV9Y*cR%738almy~38_X}+?~>071OToohPcANfAaZuwC z3h2U`cG8@UuVT1(EAs{-pfNhj*zsJ<@BL))fWK;lW!_jKC!_yKwer3(a(^U@$uBd@ zjoO3pTVHMj)3<N9BrPq5{B|4imX;H1|9bs#*50af#bM*%@Z4O2M;(_O!%BqBH&fOu z^Va8`9>9$}qmX~3`wh=}&^0JXkui}%wm0E82dfWL*W9K4#37qg*2iG8MN<hXX6Y=0 z&{DXzA2%})VX7{YxqZ|J2N)8Ym85ry<*VbK(S2sW!cqTVO3VApa4mW5GdqICGfvdY z+vg-79<+Rkh0|T{b9+6HX?M7v<~Q^sm@MbT>zQhtfuWQYgqYWxpEVOz{)R03zU8^T zaPVqJ!1~Q_U5_M0ySI$LV|#W_9(+(sh;jy2$yt)GE-yFw#OjLK{peR$?KzvLBo)aH zjg<JT-6q<?m-T=MG<*EheAd7|T=u5|F-N=GV-CJJMMe-d1*&(){`B@nxITlv*Dy3t zWGT@jUqwCk=0})(ycIER_D^1O>U)Na1CUpdIq#d<n$$Lmqd|jVH76%-*ISSOJUCa} zQzrh*^!Kz;d478BNy8Xn(TLAf$cjdd8?^YwIecMF;R_uv{j!i~B<7RB)<pDVO)dax z5{MqtnzKw_*vy?q9s)arzf1HZiAl96;ndh@)Rc9`6>Xkh2<RLe?N<q&92JqePMU_K z-ETYcZ%%Qpin$9P{*H5CIujR%rM7q+80+Z7Wn?UD2No`OD=pO1s>DV`5nN4;eVdgF z-ixp0tx6la7|`#L|B@fcUS&Zk(R-}E{$<sr>DerX{fl=@OiVyvBelU{@l+@4QCW`r zlM5*$%r-{T&YE<N;fJZ!Wj@Vt@bY0zbNf3vUL6MBVld|Hqecrx$TvP#v>Z}dG;+24 zF-^8kW;9A>>?iTX|EpNC*{z7ZB%kucjuaiuk6Hs)N1iSYkca7v`^(N^oR^Im^U1W8 wk0hUu#C*;kgx>pK@xMU+dl>#t7vYg4aex?5VY=b)^cMtBRn$~K$Xk5<AAd4pJOBUy diff --git a/docs/assets/plugin-sidebar-open-state.png b/docs/assets/plugin-sidebar-open-state.png index f1c3781a500f0020cf6db25d807eef939f612ba7..a114f7119020ab6e764a7455749f10a0ebd1c136 100644 GIT binary patch literal 27542 zcmeEubx<79-sLb1F!<o^PH^`O?m+^<U4pv@clY2BAV7c++$Fec0wEBbph1I$pxeCn zKB=v5wQB!cs$iPF(zkD4Ip_RNPmKBtc}z4?G!O`csi+{M2?8M)fk0puC>S`CSm$2} zd?2`M%1eQ&r^xq#e;llI6|GfOL9D<r6a+ya1tC3U0e&SA$o~CU4uKhj_>c2IJyEtG z$iMQu06w376oB8SGXMMp7lQvS2ZB){;=dh(S)Q^Y^H*O1AE+)0dhQ?)I^NSS0w^bs z7-%M%t(LBbuBwWNg|j1vnWeM26^D<b%Tp<kn2!i>=xF6(M(yM1;N&jiBToB|93sH+ z(`imx>VIVMuotJ*RaK{!c6PI(7U1CG;G&g4qo$@7bF;J-(Ug(<S8?D!aatP>4;K+m zPH%5-4sTu#XSdg!+`_`boLoGdJUr|`4t956Cl50pb|-hbe^&Bu^~hMcTe#V}c-T5S zQ9spdX723iAx=yCbfJI$`DZ&lY_0#}N>1+ox-H-aIiFHExjDEv|EpqFKDPgZVoxdm zEcTE4`sd}uo+=a3v~qWL@O)~Owv(-g1drH1uJPZW{*OkAJ=G<mZtG*^petkRXyxP% z6qVrR6BgtAFH`=@l6wD9lAoXVKbQPZDgP=d#`)A+|Ec%>`Dp%e7I-!iXkwiI{+uPy z=y!hDgFtYQqKu@L55iGCQmgjh&5*c<VAKmq7VczRm32QPS&h2hA-URzUxTgYOwHd3 z(H(H=YDGb|NGxxU#az~V9=)%tf3|l_CpHkh={^vimT0j4T;V<6c|Iv<Ke=_dP-h`% zBn5{;5wO7wVot&l!7vy&0vb(pK@LTrfkg-V(7<q3&=F{;jc0hNA>nXp@MZ*D#)A_Q z9_%AI{ggWd$PLE%(ghrDB8ejcl|g8!jiE9!e}F@vB8>l4MQ|2LYKUe?PqC-L=d334 z#r8WbdP<(jWmYS!AMan?vsy_<jx{I%RmDOw!!4xNL)3PRZuXtIV;Bwg9;6L0B&zi4 zUrx4P@Fk73Gpcz;P_P`DbQxBjyX{lyb`)EoP-%d6IpzJKTQ(*c*TKs4^EKlFclHw# z--)Ue=~MWI#H$sX3~riNd0RAHNU|jOS`X0glB#l^H`*Wdw|k;xD5gv^nLN6zwTur} zvrFHg*N7?L#mczMi_zj-Y{qver-3~=EE~CbO+-IfxZKyVtdGu!H@bgQ{g|2Wvl-LN z!*WK#W!f`S-Da_7qI`q@v*ezvg!#RL!mG~Y$XBbL{75LTT3OkQOl)lKY%h2E+bN(d z{(n}yIh44C<dP`6mTsw1QV8A?yG_ioS(=Q@WoUPW!|#CZ*c^Vr9RV)`I{W|P<lcQm z?Lytv!%@pxB*yWNCi_edBPrxj_e?qJL~o8r3=$rXy&0qS`Q8X3PJHvtfcqg&9|g04 zXq?{U4MfiHi_Be)gr0yuE5m8)l)=fKb@GFwF5}XD&Ku9P2j8TyATg@xj=p8mlVyHo zT*$Z~x1M~-f=r66=e&zz^1Y`wf9)Abeb3o)DNgN`CpLVfeF5?3QLJhX-$pMMOP<~I z+_r&#C&*tmBF3vYC3PyInz+X<DRjI~IJx(zi+xJx-Uzi};7hep$E#2J31os!vt_E) zV+5>Pd$S*=C$f1zsOIj7y*xT?_NhEq61$&!+nnXoi%)57-W%p3<e`$lWN!I@MI=rb z^wQWoo9ahnLo!plhhp6POpWa&qxN_PyOG`P6@|UPZjg}oW$5IRdByujt4M4r372*F znD5U7LCV1E4Rj)ofk|ets#c}e_2|w>3SCXdvB;xNNtW`+`>ghA4V6w)G&PM~B-{Ov z-cJV#A=X@>=oyL?)3R^ARp?i%^d?gH{#_bNXVd5~Z+rRU8^!HGeTC?AO(om;iWi-7 z38YN<9;w@!ZEoAMFGP<LMUU67w$juDG<y<2wKe)ptluIuZm>ekH<2>eICf7{rS#F( zsx?Uz%=$AvO}{W`ce=$In`v+=eUVV<ZL8(^D}LLSMH82o-Jsban<qk)aY4IOiNL)F zC+P1{B*^^uRiZf@-U&n9YD@!1*z121>ps`nC1F{o?6#EtR$tnDyajc#&t(15BKwJy zKq-?sB}|IjY~x3b&d!lhsYB9={gnP^*TZ)aw>U0MmFi`G3YrM3eptR!_+zVHsyBH? zFrFUi8mQO&`)4VcN>x@65vTEThxduqc*ZBA4nj?r4#-N-<Gq^r<y<O*vQj#8N^WkP zE;kX|cmp11cmU`Qj)w2_yM6NLK->1Mfo<=P$+Yi|b(?-I&xPIxbbVz|b{JdJul1B4 zbSuSnGPa*>w(71Le_pH=^Q!5Yu<=5T@wQv3(nDJj7m|SC58jru=A)(W&a3)uhWk?q zAAe?Z*kwrsv}@Z9#`cLD9fq>BPIQ?``w1P?)L;MUR-NYNqwk8|jF?G|q(f4nAH36? z4fiy-((i5y+;$7Nnh^KDz2eVpnbND<&$S{u_rjlI$w`0K<TXA&XfN1(zANIixO3W5 z#;^aqlF#;NZ2RE+K#OCk%75S2*8tT{y@{MK_C#lgpZO)O=0fME^)K&;(iHN)GE6UY z7=Mua_H_`whz$Pu3oIDlM=3>VFeiUC3=2I-=#4Y$p0ERr7qZyx_}TPMwPBa7@{1QQ zKA~BWtfF|^%#@kig7x0|_}}m-m?fQ+{`sUoe{mXXg`VrVx!Fe|Gu$4*7{G|LhaWfZ zG_+Fhw=rP(H<JBRWjc-0JzA;2jx&Q5GjfoT6bN#`93F_F*#gEF>9+a2R<%4prFpT1 zNUGD1>pM`;#>>bNPWHk<qrvR*jKOOhRl(xx5B9ERXJ<p30^KgPE-9~TSF@rQ8r_;j zm^B(rXm`Hv`Kk>CEaoM;F2}T5$XYbH)nkb69u~OfGCA|5nOZ_Ov-mvswJAu`+4YM3 zUrf<>KI5-8Hk+LfwN;*HUrg=}T)KMsr*gOQV)$35HUG0_W}SA8Z)Ymxfs0zLe>Z<j zM$DpZz5X=eo+`BC$a2A1@X`P8S(T6wx>S6&d9Y!3V1V)JBfjWRD+x;mnjBXlUlMa4 zV!sDRVv9grvLy4Dsf0?(I(et>q!DA?Ml%RH8wVJoUUQ!`edPLe&|lRla63u|##KJL zTlVXS5`-VCe&mkH>VCNb_gT&93)KGLMq<<VP?`B`QKZHEZ5}+Kzh3#qIbXz+Q6=ki zgf0o6->O(8Pbg(iHi7wXF|B&ljZ}&;8jpd!#zC6z+4G0CGRfR_loR6yt51{4^Uf7o z?OVr9tQixdf88C;{unm~x_7Z|W7+AyHy*@%JD%ZmScEP0xKN+qiRO^e+HI&M6tkXF z=W3rc`L~nYQ*vqf`Mgtw-e-?4yKSEYx5K+{jLE;&N|iGM&qkT#DLm(BqR7t{U%wm7 zqUfU#_441%_l~Btz>gVB09LtPjN4bAg;q_%DTs?Le6@w0p#GF8PKHibX9XSK9dw(- zg3`TiokRmoy7nX1UTr>@{=SLS9&0$R)#<9dp4P4ZY_#(Dnbh(!r^$a-0<*GuC9m6m z$xCN;w~SM?$@8d^U`(q<-Nt^Q*7M-DyPEB@-hflb%A1p}&SsZcRl(mr17}WBU4EA^ z4rXTR;*SyJ71GpAoyk>~+Fv)6RvcJ8uNfJ(W9$Xg@@kVW2P5B(J1lFS9z@=C-<~F} z6x>*m@W$P2E3=O+4NaI&P(22ujMh`O*iZx^46YMY$bTUEOwq$Sbaxke7uwB22j`J( zao?RPjWY4wep}OdhE^lIB#5(dW;avVTdwh*RM5%)yOB2zcb;zZ-&r~pgg=4H*=#V) zar7z6oT^PmL5fuwc!cY<oGSTfIZp+iZk9>yX%Kq^2j`yYR9Sah-(Pvpi64LMq_yg_ zpkfy@((#WvCIOdO+!j6^zqd0@R@?b&(SXOYBOTKlhVs4I==N&KIq2ex{7a2gBf-fz z@#Knaq<3^!j@;7RcF}d^Bg4!rb>+~RY2VD>Irh~XX=CUdt?QTHP2P#WX|{z-<_bD5 z)^EEGQ|NRD-UHhs7MZ}|-`#gfIi{gtG3<**U6t`Gsg!XJBQ@Dye0x<pNI$-<ns{K6 ze@ki4h|ckpLz`I|PNWdEnJJuAdw!p)%z;`?7vDoV@H6T8XFpHZ1(~Bai^clAKJ>9S zMJ{mupB)Tqb6r+xN1gDr@{hxR3>lvh1{64d{6g`g(YE3CxZ^!bGLL?Lp0K<1L{^=X zQK2in-rq=-D9VD27nJo}wio!EB{=?8_k!SyAP=AF?yfB*DzIM-OTfaj*EH)okOA~S zN0PV7&=PEf-%>ZVI#W_TH30m%`@zGS2~(f~0O^HUO<qK>2@Z_&y2;9G+pW%VuG-N5 zt<i0L$xjl~H?k+l3H!`a#lD&m$%?0c1s;5t&?NreL?Iv|ho>v1FfFE3FgOh=Xvi%l zSFM^TNIzTq+H&b+VSU^_2V%j0MKk9)L)mot0D!aG&qjic_D;WyN6@FpHCs;%1g1FY z8K243#`~MgP!AtXP*^}>P(wzbVyB~>%FplF>s6GbPo6gpuJ`AZ^2Nog8D2%iJ8y1Q zQwO9L=q<NBynUyz!AXyM!x=zBbB!-d4vw35{A)fRYjuF;oz7P9tVM~W4Eyrqo@FKd zI=is~I9f>xYDo;vk+;+hs}zx<Mg=+|6;zxG1CvAoSiPTA>l+SO5!lL;A+WdMun{hx z_ekaoD-&S~V4$PugUji|;gJBEAE`yw_6&#P!eE^A2r>*b5FQMmcO&`BE9oGq!9Z20 z)U2p9$!0+PJXMm~6g0^YpejX>h9WcsLmH^x472hVG=!d7-L5wjNl`&g5rFy0lF&WT z0}MMAZCNNiD#9dPDx@S82TTHR1)4C@m)bznq=2II)NkWqBh*h#o6D+<g(=`ZH4UM{ zG8~Tl)U?7OE$wi4>QmED6&UCsJW!x%$oyrMw2;*B;HeKPxXDV^-(}XDmz-{aaUJ*R z@b<7_n*Y1uONYh5{1hJ=r#*bvOnK9hWE$tsf300#{p>jTY|!qpAB{s7%R4J{_Vvw- zYj7DeNodb8km9)1Y+kKWp;@{!k^OQan~-00ktjAcYl{~pWRnT0R#~}B){*zOlm<>( zCv3zYXm$45P-PK}nH6YtF)gDnP4eHTUg}QJmZnkH0@7t=RnDZS&w=4+8A$dqQmU{V zNPns^0=`2B+~1wRE6lXSp1m*cqp&D)E-dfU)~kon;|SSr05pypBplwdxdy<Y0fW%9 z&WD?WTmeV4Y<$ix%^!DncgaP@YO5i)_kY&9B;0QCLO4V@SBtJ*|4!Acl<7|L*?y}t zltdM@R}@v?e>RGMl*4a74@}}NyKj~9l)mBK&k?2iSE>!$&L()L^Td4X8FZT+^d$I& z*Mkv%%~e=vtlJv%JpLZ0a(8#{XTbf|U0ArD{_@3Qt1I2yOuOen`B@sHs^3x5_rg>F zNge{7Cr=gN@#lDjeLg{O^|}{@DtWFa1Tk#3Z9BtYHSqSRybbOiMd77;zBBp!{$h4r zX6xrONM2d+&(F8V=h};@+F80C_N{jSoJR3OA~GtKia;~2+bwu=3@nR7Q7?!^Ijc;% zDK)7x2Ad$yUR8}`kt?HI5mJYCSdON?eitAh?Eyf4x@f%_1LrQ!{nE_MYP|;QY#ysZ zsp^C3j^jM{sowJiizHdSJ%HlOdC(^#K(p#i2_&tU1C6QW<y8=Tc#JhWLDSbxX#z<; zCtZI!85U~I`q4Q%*DqO8f$ivz+<k%g8-alOpvQ;!p)h1jR!uaG2+r<1H~j3g?Q!{x z<vNRD;ISoQ@CmwZ$`l3x?4XrG!e6Mg@Aq`jLt0L=!y=EH2-+kD1bk!J<5+nBa6+at zc54NmzBKjfl5`r|PI$|2LK}dJuP&Jc-Ct%|B(|N6J<DgpbN1(G-=p3A>B$wqY}C#d z#;bIzD!3v8b3b8F&hW8v2}6pRc=vqm?)>bmwQDo>S>A%^NvHd9+wO78S|Ib^*$=?# zeKD&hdc=n=i?IQ03+|#mr>4t5k4eYa0Ds>}1PsNKSeVCo8(;qVCc2d@J@G+03JZqT zSnqYD?=P1~u4u?eN+@DAhF__e7;t+9@ICLz+4~1z(h08l^UiW`{MuGJh5+EE2NJtS zWbCuS^v-|t?)xVL6ue$Zd~Ae9CiG&AEeVGOE-m6%)q0Lt@=>W^$*hOzh&FChxSSOi zS;;;QLeVH|uyPd7I#wC7NN7NZBlv}clYH?xbUceGRf5ZXN9Dt>=Z|;iHY@(aV={;& z<Q@(p)8BMV5}r$_l(cy^TtEp-{rU#p951(JQU03$bnrG$(3vs@j<VAhaO>sN;<RGd zlH4~)WD-wyglG}9Pobj7mi|==GU3{q&uxL+j=CH&S*-My_1eU3lwqaa^L_a>49U$0 z*nc<D$KF1pQww0n2_)h$R47vka(S8@05ik&gNXHQg?@H?%WtN_?qTb)08H3yU4X#6 z{5g~m2DkrKX$5v+Xu#c^FV{d6Yde&bc`dvVj)$=dY^;G-i?7%G&sAT%!0IDr9LfKI zAcSMkXk(_hFUSHNa8r8E9r_((u|zSgWQ#Hn>ib)v5Z_0yCq;_O5$OZ$y_(wvl7r8d zpxqqv_*?F@YR_L4A4J&moqEz#%gGQOS6$~c<Yn2JC%`P!&A?2OBe+7lTYJ2xYGLNV zc-VWi9=Sk+wAOi>Q<scq^H|H4ZV4{CAf`?*0u#i0*>(7dh;4j+#{|_3HW|TkXG=iI zY%`?vSw~O^smuRTz-W0V*zO7*5C<LzJI5__BS|A|4d8K-3|c5N<x_E-pQAr`b4Ns% zbIGV!9?RvlgJIFq>`8P=@Uj%=1kz;gPc#H2@XgT;q#^eVjDmnGJ%j3>MNGCsubnZu zRov{=c=fr%D92=5tFed*ooC(EQ`z&!IXc+9eln17$Ilwf;O9L|TlN|hn6_AH70aN` zc}i*Qt43xFm4QAL3f%$2{m<$fPJ0yZRo~YxXw7t4v)eb92Pix*4$r5b4<|5${&3}Y zTFx>MX~65*h@>bdG(w~Z$;PthE)0o?@I{f+`xQY?;DMt!_OVYWNElZpc%DV`xx7%J zBpw@lWY5@+Ymg=;Cv-b2&lh5gNz4_TLip`ZG+m<UT(RH}_Y+oR^ce<XS>LMeyEElG z#OQv-oS!jF1zadNNzWgAcpp$kWLo(xWbSV+^D*!syIA`!BHh9cv1X|Y_^nP|m#;7w z8hd%C#m-OrvHP(wesZvEWykkWOn~#4v<0l9gcF5pU0c=3nO_}e#01aQo`&;<;HN?2 z7|Rip#ILfrL({wygZJN_XVSSs;z=FK<MQ->Cx^a8urq~nYxYbMv^mIPs*-YE94@AD z^s;?#$4iS|FXs9qhZKyjVjs;lz&%lasD`FX)n&vWr0TycDmyh3{9&?@q$fKhw>X5G z*79PcKn0@yuwQo}u7#?AwnAx7MGA>j;pD8nLM5P8IYB~Go=^BSz<|SuWrO+RcdrYa zO$Q`pWcxcD=bB*+=z?otWv8*%DiFU~K#bl0_AxV#LB0|vI)XGd4Zpl5S7N=)XIX@u zpT&m$HKnA6uBgz@c-|Q|jam|C66LUQ@2wR1O~oYhzM%CG6glE;u0ifjcUeXxKT_1Q z#I)_fy<a?^0A*wc<VQM>P$mEJ!;8W6Jt+%sQzcUlX+yuN!9KHBh#n!q9zR-~lcqn` ze71X-km>vdid4C)!x32a)vht72)ui^J?V;RjX?ed9)$C~Wz{Y|9pP%&Tj>z=A4aPd zj9nfK1_dNNlafo3rjv=M8%Y7{$FuNQ+egz?xM-x7aV8^V$Tr&FV9aet$~X_fdVxK0 zLRsC%yyqNwaMzk3EjnvYS3MZ2%X3lIj~3cxXgc5eB44D<Z21}CVuGA0AwueA=tHf1 zJp}ZJy8#+KZW(onlm$IU7-wb^^g)7dmnzPyW-Eb^?nXN4OuwIgtZx4WOgd(r>bym( zgz<PMo7-<6bsA1LtaVohwqNjr6~BM``K&e*ze+(J@ki_=OKK@Uy}XI(WV{j&rW|@t zh;Wa=Yjl1p71tfp)s45VPIz($UJ?jc==CNdzkGM|qd;j`azB8Lo~&hdg2aKuGdttF znbsbG#_@8szAb)Y_H8)U#5nX~1BJ>T7C@=l<9D_ZMRk^nq|wRJ^O6|6j&sOngLx6u z(5yeE0`VCK`I)P3JgHgzXs;YU-7)qY?gRU@ITFzgT*n-tkI=OzmPnl1P^Eyg>mpSg zp*m+E0hC!<wFbe7RzlN2!etAV#b!jh8x`5tmv%kDo7Ro8%^%LkO2#iyfD8r>#uBKA zgVXWbnQM%AI_fxCh@-d@`wVGNY3+b82DqQb{f%D@w^TTDXJzn1k{gaDau`$qigvh- z&!p%%U!^Bqe$I{Zu!l~}-xUv|e!oOZ1G|kwu0GMbk(+e-4OR2sYvkUc9Jj}zN#ijN zMhdl!j=|7JlvRoyQ}^!--VZUG(F%x^IRP6hKym+s`%(Js(Kx`w{Vq&>LrY;_Ehk=| zs)@Ol0w82y3cdOn@<otHQJr*fkfqD!4pM6ABTAao*5M|UUBWmR=XxGWaeH%6^L(!` zY?Iku<2_eTaozjrb3#xC5*yO%e9w$G`9<XwiW28AW?ar08fiPog(g`sNwq~dGmddI zcN}CeHi?LtS;<G=x^I6>u(w&`LW>S2%1Pfs|F9cTyVJD=HmfL&z#kDY`dbE;E@gql zB7~T4N0^r<)x*G2)UE)Mjj<@l4~LgMf$~N|?SOFjCV*sdht*l2Au3NKz?Qx81{yK| zAYJ;zB25@L`-z0i>T6x%fMWopt3WPYN)6$`1mJsFQ~57EQLwG=8aI3PP-2W??7uKJ zg4YH1HL~D0Pdd>PThxjvj^m5C%iHKy<%(!2YFX&%zQ`M|GUngwmWvH(0qvpp_d9gP zrv`E5Vp7!iP#emW2LW}|@ZdFoEL?w*)uN<H4g}i0?~M2s4!s609J;12vyB7Zmj_z= zKg}AVsZ7XzW{?e3K@IsD2cOze&HZWs-sS)z9c!?e+r&V7oVW7O5-Nm6qOWVntRb*d zG9cj5-4s1W2l<)=-1og>Aubf58|bWmZ(sEP&-(wm2P(EBv_HPO2NV+^4uGL|^e*V( zFTjqlN${uKzZA>XbU)mbspj^f(r-S0J(UOWD)AKj;voR$Jqu>js~@2M38%IrWCT4C z8*nx8wgpk#a#`I6JiXLZ#JOh2CE7S(&m`<inbm9eU@4uPo=(y)F!vcM&Y&R-$pb{Q z0a_wWYe47V>^zkkDP&a5F?8ug!j`yRU-4eM-+P~Qb-W@9uPQ7wt?9Z7<tdDu2e5H? zWCsPG%?z+&a`|7Mh9IIuro~LZlXn5owexD{-w*EsNlnn|1~%)24r}`pg*KyyDc`V3 zK+H$CcXFKr0s4?E2JDLu_a{NaxC~y|P)E`?w9j;^#m*;qnbe+m9~0h3hsF9QQjCB? zuKwW#h4R(_p4uHib_4Hz4=*n-FQj26v$6JZ?c3LMAtM2Kt=0nmh~MnJ2SoW7IU2Jh zVm_x!&fOH3iW~*6*+AjfPRfHsljipT@PDE{BluTqK|ww=mdU;uY<g$Fb;{oHIsV`a z)rHU04O7O|&otS82R$177Lb4x&wBvmB3TMpnorsfI7AGz{*Hj3-<?W7KHQ^V5QDzU zWUy)O0T_)2so3Wo)mS_a@hvqD|1d4h-MoRbk>7r42|(#4d921d>(ASd+YhFMck^gV z@tU+c!r@Y#GYzk&_h&yCi0^N~#MS|_g-cZ!um3pC*)3M765R9L+Zdss<JgfLD)Z^^ z?(cbu@ZD+u?ZrNxwoqly)zMN)jI4BGj#h2Y>YEcxoWi;@{I2WGxSG#5tT*eKCV?bu zBrR(3(3g=wXXG0K;H6C(OBga7j*3SdKBMx*hPsM)Hl`ylFfJ=Oph&Ai^X)^sI#LB0 zG)MmL*|w3kp!2H#{pEM>{jW%rW-#ez4TaCDTQ>oMM>FR%98V%m)@VB$`B{x_dwaVL zKhI)oBt=GYElwOQ^<BUf$$26$s8433u^DE!$1^)1VH76*zat0`Wr^N?MOB}Q0ydY{ zpNVw&Mbc3K(Qe_e0mif#96z@YFZ1;ZQjy5R?(@ewT^%D&ZTP$~WJb1v^d&EGhR5DF z(57nCepabFpcRCI`hxcXBJ_Cw$HZ&Vsx{k@hRg55=KO<#hp<v&;FL^{*)0%tqP-er zdS~eIMK;{eot`!=-@dvHc^C*C<GcaF$n5-q{Y@;A%#Z2GbJ0@1hQ=J#?xz#!97Z|4 zB&GLdxlVmlw~4%;h3Wt$FsUT|<dk00DP#(@^L$DapeG!{U&quZ_JJ|~!}f!oO+1uy z)fWIT(+VN26e1oz0OBhQ0|t}Zfojwe%gZudircFrprR9f<6|Om(#zPWggC#pR8a(l zsNHa|iO)tv@X1}jxI%geD>j(`216uDn59uVzA)}rB6BvpOBS7K!~RH24T{&(1(>-r zHPNB~yKE2nGC=0s8N!4aHa{k<MwKP%eGEvQl*xmA5$LG0=!4IPn5hCTa4M<82M@#e zNYX#w{Q3y2D<UOwVIUFSB$oYI)2DT%pD30gqNMvb#59;Xy{auM&g*a?rD!J{??oX8 zbI)?0<i9xId(4<+09l=avCO}80BTLrl94e4kVX-N#1<#YKWbHgc`^;%6an5kLh%=9 z*l%Fg4S%V4$rSq=AfLRlH74DkmB+}n8URtJ6(KKrXv!nd27NjVTO!L+<G`m%GApvD z6QzL2#GgB|!0YJ87uhb<SLNzOZrfuB71{7s0fwfh+asA^4gyw#u0N~Fi5Z!K+opoP zA?(*LYXF(Y4{2vISH3>cMBS`)Fw~wW8N5B5aK&vu&sIS73yeibO4n!l0)Hf=xR2$P zeNErCYLs8T$5+LzzMo@N8J`^;Errc9OQ)q>R7xeUD?Ste`Z>9($;Vghcs&ZE4U)^G z{B|?xhBJcit;11bzC^IT6fHoYZMON+m#VbES*kcD>utB(`WxusU#dqTD3m?t<?j>0 z5_i5iZL)*>B=ITBP7Adm25gqCzL74oTk+vf1oqcQ#r8Eo1R|)Le*P$S#SFm5uiX!q zoPPNXq1>ZZTd9MRW!LUz;+urycnQPo;@L|8PsA3ylR|e@?%r&cPoiukSyOlfu<MTR zHX$WV^ai>hB9hZ}=y1M)ozlv0;ginu*6lM|xE&;f_+bXtkJA#5y?h4O6`7%Jxqy8{ zA|!W0td7BBqV>Q0rjz@8u%Q*h{2Em8Esp7}K~-w_X1@YKa^gxcAr0Kj&}K`(s#Ep> z81zyF`ZKRvWqn=0OiJnuQz5%PsB=je@<9sJ*`3;9PS-ds_L8PsgnMipr*3gg3r-~O z+6HHxEM$l`G~UbMeBl6*aGOJvF*2ats~+mKurLz#beukOJyc((HY<e&bw<WzO;)EB z-XRNzqKN`%6D7`uq<)=wgq7JRYuA@Ixiez4a_z-`9oKmdIOfR6zeGyN$?m1$AU0tN zDp}W-oX2pZZ6#<9!(={}x6;2r6LaC9s0ow&N%eS*A`zblglGE9lnPauua@1__~0t8 z0$$vmyf&s%OaYA^^cvBpG=vmcYbJqzBTUd{s`Plt>8C6a<iq1O5@&E3l(?StN_ySp z;Gq0!WPOh=qdIJ5=Bg&VosNu2x{g|6jV;jdE+*e|UQa-(T~~vGW(nUd1R(~UE*SSP z7_H}MuHvOMV>HH0(Rd-f!Jx(%v4u2R)CJ@<NdBeEO^}wQ6s^kUMD5-NAK|3T=ob%l zU-dts=S@+)9>!9)mj|!E@hKv+lj|;)QxM%}8+h=cH?7e~M`ne2Nq%1+wKOK&kmNB- zJ*(teg`^#GNRbWXx6BsqITV_T^HTE*5np1cgrrh8I$1a8i+W?h&R2(sBZ^`eWiZc& zN`Lw~=jS$?p_#S-%hnLWvvYgHp^3b4)StoV)aZ=GDuW3)okjDCo#-5LFym}c%dEnr zB#JcXKEtHO>uCNQT#T|-Y`<=+_8~&RZVrkPmW$_=E%L5BG1+nKSE_8|=UrUMIFDmc z)Ta-dqfqScg(*l-na}(d;ocI1_-t<YI(nRagh;tyqA+13xt5@v?APjuW+>JW4psf| z-=Jet!gVn-1bcfAId{{aE=5A>;VbNT2sM`pyHPPrKgg#QTTw<g{ir~h`myALz36rL z6zO#=JS!2E+1!9e8)cJPejs3gl`R#op}udckWpAWf682lY+(+~Hif7i=p=)iY4O51 zO<^}oY43sEGHN&{#SYLW)<?Ny5xL2Vj~1JB=lkg_@p+=<QG#Y%idJ_gd?P)G(S0uI z8Up+lSuF>I#6AUuzV*IL@#tLX$z|(j8-KVi91Kr$Jv+7%cx^*HV*LYSed0vriz%^- zhPgM_D>IzJ;je#)d2LkZw5tMaV9bWb#yxDZNI2HS!4z!hFR@+mGG%P6<b*z4pO*V1 z=!Lg`#YK`^&-AAgQ^-(ueTbwKh--jk5WNC%MA~3<#?#E>BI~vG4d6yZjV@3a!%>PR z%}+E|{g+ytr`g*D=U;YY`B-=qj;bok(O9C5S&Ws;$u>Sr=m#%07Gdn9aqxLXZDZx* zP-OHrlH4vS0nr5pIzrN{41>f4HW%F-jd9c1x0yd^WkMLtjAv0W87BA&W$?n|Bfj>Y zP7!3|+wd3jqBP178yVSQkYy?F+fMu<V$+2in8v#l)rrn{WR1fzDedcAbY&e@R&vwr zvCb{4cLU0~2!1BzSVOe{2_ueR9?u!gX)v}O&JDx-=z~K^@4UR}dMj(v;}o7491^=K zi};@ZG`z{~8!H&CPNsKEwd2gN9&1=xqETJpKrY;n4LS}RM<c%Sg=A0i7+E%f&n3p9 z#Tl|He2StYa6b^^rBv0uQm>&)62o<jKzME{g2!)ySNNFBFLKrN-Pm5D>Kd8NF<d#8 zNbO7KI=J8sTK^u(Cv~m{lkm9hJ6|RO!S__|-0`O=ue}s_Zu<oW;)COsfW<J!^{vKt z2I440DW-YHmX)Dp6k2%A1!Er?*mI-H;LT;mC8=Qin?c$RlBk|=VKzlq?v2s_TQ*85 zYeEE9Tj*gB7tWcO=|5x=tD;zxunLGi$aD91!?rQgP%QuW#zG9Ws#wA}t(XFbd7W_T z5V`=ncbdC1QlILM>QM1%A2<PFS*+>0!NGl)!rP~bv!=GqBEByV^P>=EkL>XJC&*4h zhSZjca{}=!@kegS6GI(V!<r$LL3XTm=8}FHd}RVPdPs=&sM3qU-<Gz)erB0FqZW*P z(lC&M!c1pd8oE24fw7fbPukcy8fSRC&09A;YU!lDs*z`}@l$cZ;CTtVaLaIfHVQen z;+Nh9&W-lN=o|rf?%leCGdNFDDenLm?k4nDKf}3IMqx7aFf(xs4XbmaB<$?mT72$j z0cO4FoNPeYZ{IWuv!6IR^yD-jZ40XDwURv<@SlBHF&(#zwBg**wPRGd5!33_?(GkL zu10hY&4sz5E7fvElnl0&_K1Pf*EH8N7xBtWc38L=D`9a}Fu@0448@TlaAf*?B?k-+ zZMq|7@SWb+E(LBm0Gwln`5ul&rZpa3W5Rk~17w2v9m0c`a)RzW772bFQx24E)IgiV z<Z$Z(<;IuoOFjmJ2aC`&F@;QH!~*d)3$IRmUtP2Ys32ke3=zBz&&+^UVvgkb{i>)d zAz|wm;rOV)%*Y0VL?K^ueThD;`g(*QMsA}8kye9;E^kt8NTOw^rKm}*sWK$wrK|Hn zvXBbrc_Pee%>~BA;zFSO107O?><JSXyV^v=X(5?J@Y=A23p55KX>IFQt-5v$#>|9S zcvFyZ1`&2f0^Z#B+3%I*jV@J$mW-$oJoxy$;_D~q)|J?hIukdHUoRlBu8-5k68SH( zZJ<XO>sOsmoHG12h)z~Cj{`!n&@$jbl7t4EteT9#gtRefl5w75gT*A;Krr<wHmDf! z5(p5-KSgM9Cd-weAtkiQb)D*BON2~K?CDvsQ*<!NIC^LMcpOLP{SHxyHWp3o0X2}N z_JA)$i521>73|aNty&C54QZrHh8RQJ9y#BooGCpwczbGu@^;G|U&3-=xLGT@{e=Bp z)9*mh+``jI+FO^?E)kPl*Ksdfe=&>l6d}~J%iJT6iNuQL2DpL>-Qf<org4E3^+z0q z(>H8OR_UAz3js4;9NV|<pHY8)@?0`W=TIf|&y0;f3LL$yY`$md_OQNdQ<=DG*;3Z# z_<XgSNxk$l-C5)BNTz{+O)Zasm%n^CvB5ZD+1FO?4sZQ(N42rc+GS1R&khXf-*<d{ z13#ErNE8Sv-lG9F(_r|<Lqv?>1z$VKyFV!kJrCW@yPWwMCy&WyvpP!zIZ3O1j)jL; zT?}Zb#pt?J&6p8?)kz6^qLRu``Hc(TEq$MCcIPf?j%&;$TJS{(f{xR7bqF(QdJhtS zvt!{>=g}j#kM&{HXke2f-oE##b!IV+-v^ycHU!iKCNWv-R)!Y{6F9d{El*Sf7Z1jo zu|tVeQcb*I&FmrzV}qZI-8+&*vY{Qqq9nrM!7vvneWOX*LCD6{<90Mw^I{)uuxF3s zkN!dm-!+4ig6%_3q=r^@zWjde;DE6_GD@=!rYjq)1rSG{)07;X1L>&_P)N8B&98@U z@_KV?DX(!;GV+7!(Um_L34SwlRqT!itLsON*)r5U#uU9B!Ur@@avX6;_zq6WpGT{V zkkn}z&{1%_@G*iag1p<GE-M|Ij|6sLFUYdPdmD-4?_P5lZMnQWheLxB)vpAIWU*+H zC!zEuoFK#S`yg)GneB!Ax6*D46j`cn!g+D3JZT*#>|_iL{GxB%$XHAb`O?B$G=L!y zPi#+{CA`R;^2xBPZi^7C7YCQR0hgQUwF1H2nXNBh+ZH}#ed^_AaN%NOx~iorI`SOP zX!X#!+O<sSyXuPIS$LNHh4Kyke(O<ytNcRJNNDHMZG9Ur8uU&0c_dg|%v9Pbtz{)| z5hdG7`30Uix(jo#D#E94i!#Jf6q=?IHw0k4MEKV$`+ELRfa(lFnf*j>k=(7*GjYu0 z?afco(X*M+iRu0-#a6v%lr3Y6a3hxvzE9QpKuhJQSrV$K3qAY=r58zZxlGE(VM7z2 z#R~Rd890Imz|~?HM6!_$7-E<;qmjf%EwRChKO;7y;?sy0yVgWMFhB4x%hM#MK<OPR zQ&RTIHKnLUaTMl`v+~O;=B20`o&x(`x0PN})Re%C{#{rm^#4!(?{<g+JEy~PtLsKz z1c0ZokzJRX9bcBIYzPW5=c$ov^f535Nt<qu0p2$Db9PeYOpbiOH6$r1>84D)QK#Z0 z*WqMWipz3yu|NBy^ChzYCgma^G7pGSXQvzez^UC|-#(&5Cs2yt`~bAAjYzU7k%Ow> zLYEd-8Pv@5JIoLuV1l+82nZhc$O^{Bt8Kdlw}96`vlbPPajsJPSqww`sV*aTrjbZR zxR2S<kERRXkB=wak64%hAOGQWF#m~+gedxn0m<)9<<rIaO8<=BOyKaYhY11ln+6{c zP)}0`O~LyM2$D1rfW~nG_$Mj=vPMf%WZmq%7P#IM0+_!%Y4<I)m&1KFf)TM?q$de< z41WWfLi<uVb+g^KUqHw(nstXDnl4tbeR)*M6mU-fCJ-gArjeM5e9_E{jYPl8Ukq6| zUr6ejomO&uL>AMeq&i`ADo-5%ASVIW%>kf@^kWpc8x$v7@X3j>R|g=`ZLg_3;UtNh z@<|~qu~Rs5Y`xVuatRe|J55aju)gU80%{eYmIA_9i%EAN!kHJD<Y7Pd^E*Ju1f<P5 zAW0fqe6AGKn?NC&v9VngMVZ5GAqQB;A5I=00PWHjTkNz4klB`+>;)}Hk^v2L<?HLf zDadZaw8XQQWfMR!%pV9>zp6GAwp0Y94{T@6C#RX_I$-6d6>!@c0b+z%ohsjG19o1C zzqumkG6fX@$|MC?i~RnhL5tJwyP&`d%?Q<@Lk$0`)i=&Nu7D{-=xl@z)f^P`dyr@! z5%5|T_YgdL<&g@6T?#qqSG(SL?|8?*gCLoxU;qNlB%tlZW`L6c1w?|0Y4};Q^<<7R zXP3v>*65bo&HjfIz&f!^3&VwYpvlE$up980HOd@!KL%E+A+?3#xsqT~h+F_rb@Qrz zoCEROhXTJ?{j@>ABlsCG>HwCQ({S}>pr@!2yH6X*-yGKQ!9K;{+R4_>Jvm%h6LbBZ zgle(CD5}6#qzHdDRH<&$V#zQLz51=fFf0+kAOIM4tTpO)1)IF&`%_S&<t+i-_+~u} z+hrE}_iHThh1ly>B6fX`1+%CCU<_XnlHLNU<i;q}3DFrp)tpPO%a0!$B8@=7Us6gJ zN}Sh+k<nLpIb)`<0d#$%if<n?*?#6Toy6mtugaYHu0tfl<n9<01stk>-rHvnrXPod z`T;65;4OfXp<Q?bJ!+s1|GVaQ@CkT;xs+JrGfQeB`}A5?mJfdccgyw9qzfwZBR~lR zOf$=rt^+ub0H6$0fe)>Qj|gfPV8H=`dm_q&*??E)>dC5@Qko3ur5lhfH4hE|j4DvK zR1YTg&5W3ZgPQIa^8%!~!MFK<-R9B{u+hK_KKl#H)>CdnTxOo{?`}c&*K2#l$f1Cx zspQM!`MXDW^gwAGAl!BVN;mdU=(<d28~mcJt?e4FrqHJfOx5?w=cdVw+L0`9<d5_` zx(v2#zixpxOV4AH30yGB3InE#5Ny;`Er1Cb+KddRs>6{LL9YkEqdyZxr+D0O8v1%0 zveFOE#yOpVH4Cmefq%MX%N3-B?5$kWGdUvzdr$6^!K8v=_gbu^1*K#sLFx}(?C4B* z{1%^Cuvp8+z&c$qFTO5XRhA*3OkNi@!w!JZXAh>UZm5p2FGGu(#NUz?2|$rvegLkq z{FTP_e82#fA8Wwe<FvvVANhRCe9;lmx-`(2Vo^H*!74oUvuxD(#5)h_oXdmnOYGuQ zsm1lnl%8`MGId{58TCOeSa1(Q`ik^4OHiW>Ftj7+4Xs;<16X3(fLU)73!z(JCq+rc zsPsCxkI++x=cz$pXXoc{{v3Cme7;R(^P_c=4sJz=X`P#pWMcBp8FlIfgf=WMQO{pm zPDO4`2zY|fLP0&79!_D}C!4PDBQ$9nn3RcJl^;?2-!2zVwzcYQGGhgVL@h99d_jDW z%SSgg<kjT)_4S-vhL=Zrp^OVfp?wLE`+x4ZN?w*$aI|gV7I+f<BHtJw4o{JMY&0ZJ z0nDsme_*ZI+2l#hCG(^}Ax&7}N$Lry?BkRc>BcaR?=d8ldE`_4W539a(<2f`{1ZDh z4tS-Y$&P@>GW^v<*lkVFeH;#%>H_Uo4PRQ4y#2hAp7Y6(39F)#9+%i$RxZxk-o;R6 zE_1Hvl~CdQndSIwl}vTP!}<H-y!Rs9Qan5-Rbz&HbW$PTN5kD^Kt&$=U+LuH;RYp| z^y6Z*ZVi#+p$w?Mly?OYmg#NWG0#I>;nao~$qzJC$_?*%2YF$@I}DQb?*eaZNAP(T z8iWqft9yMIU1k#yK~}7B?Y{v_S`iF)?t>atSu`M%ybjL#Lr7a_!ad~ndwDiLD-L+A z<=e9`(LCaQ#v%d9CT10gOIG*a<SJnwAs3-H@}sE?lkZFzNAENPcf%0VqW;YPErhuG zhGo@e)lsZm0v!B3ujoBh9bmXX4CGVkteZG8x+ztd=+9SyuknsYphu{VL?d(p+VE7G zQ!rV?nn&O+c8q9&TLD7i2z8H)3kTgP5M{Ao4S-+hIu$WFa2PAvh4_wSKL^z5P0WNr zinF@LcCL4r3L%TJEh~spyeG{<J~XU$7~jKCu&po3w7L37B)MeLIZY%CmjP=Pw|8MK zP2}fEOENNqmocEfF6Nk|eDKuI8xv7BMb}wDa9SKE#{p~b$=lyv8s{y(*MPK8|M+nG zhG7Mbd^Yg>0~#!^jT11#wKL4?G2Yeo04AA!{2?-NIYDP;9|p(f!%_k%RV#}z)iPr< z(8X$`hdeR@QaA|-PWHGd`DLoc$efg4@dPi1PgrY2>ocwLb$n)Ln`I|nZu1qH+24$* z+9mKobostUlM6?T%Xl~9uOwW0C53f>@&YR|Rq3l+Eut=5m4*?Qhk05QN8wo@gwA-c z1$?*Sc3Ku%ZWh`UdoRL8t1tMm;oKa014QW@4ljqAEVBu6iMwZD%>-r0(cCdsxV?pF zyv4Rl$+9r4oh`sBcSiZ<Fys?fdZ+EsaT$8{r%dJx&8$q+px_q>s&HeBajjmo7%m1& z;O24i!%327Z)wBe-*kC`J8WOJa7pGM#6Wg8FGEPUH(TXHH8lhbW`4)Yx<pke)QY_{ z5-YO!t~s$z?$>*k{p%-sK*%tTY)%`<+I_+SqgyP0?;Q^Ob#Uo4@4Yo-2ofzDyXaHv zFT{NVx^m0_X=rmbo4qpSk~b6h41K|rhg~)RY>T;zqRM0#56zzkdnl=svJr2E+xf)9 zKV<Lb>Iq8YT@IoJ-^ZVEdG=|Jn4`2L<G15B*kr{?@np@`toH_6T69~nKx9EyWDZ5B zH+C+D7zviDvRrUeClCypxJt~18h|JiixK_Bf-X3?a=Q5BQ_CtEUeWTGu|_Ci;8zR< zdLg13>{yI>8y<6>K81%qbk3RSFA|+R8_QhO6S9g0z+AKTFT)AP8!8xUM5p89Rks!= z?$o`drhDyxM#MdPmu6*x*+$vBMTH5&%O8(GfX%dRvoJv;Fa=-PJN#%wkuba<Y-sGz z-8q#rL+b(ApWPL|;l)KBaVL|EN60?zJy-Imx7JG>tt>S~_9{#FQg)U{c3gI1;cdYm za&k50ABc*Z(|yVH7;I8+@nyAMI<>EXIw}5>lj$OlFS5Io9&95+BW}2nYbD>Fq*=-Q zTR23|qn7#Z3}%t$-U4j8R2m~VR8{s0Qi`H!ER9Rjd@sIsP=+wscX7zm^1KjHtU)w> z529D#<bO=2uFV0}D*PZt+on<VpQ()|$cq+?3%-Pg&Y)0Cm4s0YY&nX9iMzfaF883{ zzBCmPmc*e{mhyEB@gp(319#AnBwJgr?Wl{tQ>S1sgRN5_yxxe@=b{wC*H4cdne84i zw;WSX+Jy0UK*26(77jfn;w55QgBMH-$T*tBYV$%Y2IOA+$}l`qR}xc9$Qw>-L*pH_ zAZryb>+ddodlDFfhA*hSV20`IGKT63DC62T+8X18<e4AhI(-@^V#(QH>v(^&QDIY^ z22{VLc0vxKNQI40rOmV=jgUgRM+0?O>c;fwA-X{c79Q-Hgt${;kP=Qy<J?L)DQXRf zf8C308wPw6=#zE=cuZLHlvJRW5WtKbZzHEI1*Ind>?WEUTIN#Jbbu?wQiit@SBkm< zkYQ5MKH%bkNkRax23?NETNqeT7LZ}Igx+SsMxYSjbq;@hvSY*Sg)cu<FN+J{cs#CN zDHsbeJu$z>#3k$eN2iDJ{ZF=Nt()msCNmddR(40Y+ei{rmfz_<d+(SZK)j~TkIjcN zqYo>`GM~rv3_FecKOfc!uA}c;HO3FCF<-ohsqu3}<fr|5zIggUr^dKe#YN=8Yiu-8 zu~!m7;t&(Zt-lpiH_@u9bZ&)=zxXN+uyoh1s4uue*7uAY^5erekJ1)=ulwGe-2Hta zV7CO<bfBNy1^HV~>wNY9g`HbV27c3WN<eWddfr?0=eD~XRS6EYWCF*Wg%<4yNSH?v zMA{?U38=?*BFG)O3<u^-<a@7<7MMG%n=OSjAfW0a7BpKuTM`*AsGyI43(zI+iP3^Y z1=uXq(8a>MwJlo6o3UNb_RgD8lm6DOKn?6`t?<ON^FtRf6V#Vl;@Ut?#3+gakG+#a zulJCck!%<acdb}zc}Zn@G|-RZK?0KI&vCsN>e>)*(N_Q{UJarjT$NGbsP2C7TU!2t zv|+l0?PW)UpJOpg=?rta@+Rf8fgzdd_tp_{q+>!C@ZagfQgCxfWtmMLUOISrnddUH zj#xW##JZa{uY=I9c+7tac(q!tv4*Pms=F_ojKtu4$C~Pi3MkJ0oI*|YvSA;+k5TTk z<#2keqXi3UE`MDq!MZx&OM`WE`!Fm*vfq<r`KRzthQHdbKNpe8n0ZF+Jw%;sX$&F~ zHBUG40CSmtwE822J0L-F=rLjasdc}F{Gz94YR4*1w9iZAuv?~_VN?9Y&<p<!dL#i! zvuS>>+Yd{*UCI87g%PVxZ{T{z6B4lIHpC8W*X-wdGe?REM&H({{c`>;apsmqh#?M1 zEgs~DF%^QmG@~S3mUcG7Q;F^~9KQ=i$2jf?A&*`8S!zmq7G@>Ceg{io?Q!khomGFI zEZ<OzfWg*t5gV|!Kwm(<_&4MJax{7lN-LTbR~!n8u$&d)@F83c=U*rr75F5ec*TM! zxMS~-cX<-@csoSqOrH|`%n%iEz$2FiI`bT_jkspvV63!9-9o-?M*Fl8QOqGpy&2mQ zo0DmjPC-W0Ei#Hs(4r&athRoISOR1G+9xTku4`fsk<qrJz|}f$<wp^<ObIWSJ++=+ z4bpFA6zeD<avPM9T9&M%=|Rq|&?E-3zZk@R_^IRrmZSBtlBGhO!3MDjW=JBn)RFe| zM~%7Vuip*0@}WmvBvXu~TScYHdgbK|voB?ASicrWum5Q`^ONiIrUjD4xB%1Wj^FVG zsi;iU0P3ZHNjR=P$IT=?B=tS#Ojp~CK1s)3LVTL+58XvCxLh}XwUrLPh#h2A*1cK% z>U?11iqVS8@>JfyI?IXxG144ECIG5{R!U0crOPKCYO?%dD1)mnAHl+01wPRmS-rP< zN_2xhh>S4g;$<hTTKj2Rm)w&@Ug(xS@x9&xYwF=bZaQkH=oPqSJn<D*OB0ekce4(~ z73rNBH&cw;)>T-`q?Y6S4#Y)<xkyLlcmiIirCHf~6_SB<!%HY%&_J7gzc0o{>!TLe z!v~;_3po1rHHel6L&OX#*i`VWkQW4EE_(VdfS(o|>G)R?a^3KtNN8tFLj~K}s<f35 z>`SRBnt(KSCU9p{!Dh@?$5S>t+I(K^%s&uv=ihYX2}VHQ@R9QJ{QWc5ac(O`IT_08 zG0xs1wAF<(dDQL~?(VAc)t;uz%g4MIRe{S56*1hi<0D-%xiS1G9tpZreqr`TC0o9g zxqP$ArWTv?-16LmP?QPpTgY}Q{@ziuBinNC(5wnt?M5$pd^HEsc!b6Z1?$fM?NMgb zCb4A_E_KkXPs?nT=<`rLjG^a=d4pr1FFi7=Dn`dN6t3ixeTK-IJ?U|@J!U8q)Zi+5 z8eX*h{ZA6L)E2vcd?V;GXP&WmBU2~m`O2`tPY-E#hTyNk1G89A$;a2pAI4pI#Cex= zzg~<b^N5G*xONs`R4)5zBRZ+346$y|cR9_r(=dA1NB_YfjsqiQg+(BXdJ-D-w8qmB zXN46ux8}4P(h6+~<wRIm&%EWDaU*3=Awo%OKQn#pDMIwEm#WOGXeZiGY65Sf1YEr5 z^<9=)_(qEDvZWXAfUch<|J^qfqPP?i&7NV*+W7XXV3F){EL_Po>wz6z`36zbx8aOj zm2JLJ41KT4$?bwSFefAUkwmio&}Ttk_q6huwym#=MTdDasJGRP;#kTPaJ%<z2JiIM zm!~EDivDRsSi3ogT!uRXD;u~@EN=*{^XaV+sAc74d!?x;e9c}DW!UnEy-HDMroMo* zEG40(Lt;@vWPE!Wkv7Kc)MD<xJ||K3J<O`$nW>{3QYv~AUki0v7kMQeNkRYRZUaeq zIaguiFb~8j<o1=sKH2aU{R>~(_raSqYA05-J#o{zkSvY&1*S?K5gP#rY(&KB37lN+ zsnO_GY_b-^QMNc~SXqg0vFdw%DV~_;ryffp(V#Q(tX3JJ8LPRwD{%VOy%^PJlvq$j zi2Yudg@Qmz@eQkF=#^CVQ4=?;zuoq2shXzsFQ;oCS33Uj@7qpToT>QV%IKkKEb-Rv z+|C0o4D@JGs_LdA->pJER2z|nm>U~zXd^LhHN*Gnt+O`YQW}u)s>w06KO2AZg3${l z1KkD*F96Qb%R=2lPP4G~m+N=rhviS-B@LyzBzA_Lw}$qbZ}_j18q8xd!Pci`SlkG} zTZm4MvT2z!r%Wa%^-jSh9hiDjIRq3lqa$@6>DJ={Hht%2b~ki}q~$0x2Gq%Yz6YPr zc{zT)4A{?>tQCtdATYJO4CvMFnWKH$Gg(Td4|c@t=X6$k%u=wWNu9qB_^{e)q9r%Q z)Mkv54|GK5HmR3y8bkbxIDOFRTY#_5u$3>oo@bdg)+PYHj3a~?keCOc=>y?#!YA)- z@z5*n2zWdIVay>)0IrF9!ZjKeA1kG(<p2em8_d8>lPn7)*O%96Ytz8!05C)xk_x~Y zS|C|(ZlSUg7L5bIqIkF>fR%87WHvhoZEfhl(-(Zm71A?8>Yv`RBjj(cWQCZ^0N(^a zrw%|Ry{8xV;z$j&3BcR{)QZMo24YuiPp|OFCVZ+y`#)-?m#^`<3|_TM({^ndv}ohM zmG|9GO||X15Q0RIDpgR3fPhF5r1v0#ph%G_5W1rD-ir`LdKGEX6?v7W^b&lfgET?u zP3av(>6|;?nK^&K-e+dd=BG>uN!AMMxv%GHvE*Lwtx0~tlMDXhS{k**Bb4UjpN4;@ zbKQzrRNuOc9zP|es0V8s)m&7K?mf9=(P@Yyb(GPDxr$Iflyl9$AP-q7k1%Az?U@ru zOMrhzF7U{Eoa~Y}hpMLYW?14r@Trm+2|G!WpPt=`mECSXIX-;AyYPM7{oCCP7B2|N zNcm{K=ag2hQ7NQXHAm0qI&UL*zPVi}*hz)>5ZM<O!TH&i$lKAP6Os|dcTz>J5OIJp zZJ|_(N9Z}tCJ*B57NU)p-GB4*{iu)WguKVW>x*b?#bZ6$rDe8~;S#KZfg5H9;T@95 zC#CTi2r{J0^kq|837)$untcVKp`i(q+6gh8N*fum?bj0_U3F3Hani-;uOY?1Fi+Xc zTl)Ff4DQD8Qhk3e<)8Y+R?5H?fBfg?w4DZHmT|@7nHa4zI*L(wsgg_*LjR$s;H?nT zH{}f6{Iw@Fu)v6T+@DL@eDmT$Z&nb**hVelh!WD%pNuRSp!P0=<g?|gPQ8irrGCX_ zbjyy)ol-N4bBK(JEnHT0!mXLJt;zKln`sX}i-;0W@Jmhi`*dD6I0F*grxDhYXgY}> zV2l$WZxeLo71U<#-3qzl>~;~nWT^CW@2*#-j|GNyHSrBK&srOw=MXHbE~J%T$Z(^| zdBn@uDKttZpRsK#KSSiQ?TRAK;)pwQh<JO+?H5}FiIpT-Yu>_?Td!RAHOsfXQ-Oz+ z7FQ6Dkc^Qouk6D6X_TeyM4q`>HsD-)(w44(YT!~M%n7CxcFB&>eflBoqWgTBKJ(ME z@0qno60;$-H?VIiy@^-{W?zzBDy&H`gdhbLie*T9EN3f)W(-4Q@linX&lxG6OJ>>B zQ?6YCchki^M9L(=j2AKtd-E9vPo5IZbaBd4a02@(FM)}V;*LZ&duG;7xkcgnMBN5Z zEoL+Aj+QxZoqKkH2<zFeJ>6?l;6Tk&#A$<7vB70V-kxTbROpK91|2H@B~x&=NsTKN z>IUgTu~yF0nu)^or@7LS9pJ_zM{{d$Y<Yc`Pb_;7xoD|$+wgL!uO*-JYwe4tBR;8y zb)IX*HS-t7XCm%HW|NugaT*;Bq7ehB_$Em<*8t*)^f{8?(h;PatEgTp3Xa4f&RTrN z9qCx6<*cO47{T`mt|r0Hpx4h(^-&mJ^xphTR(5w1xLr+=B9f1n-Qoz63UC*<j1)OJ zB91{R_{Ms%yorqe*$-Vu^mGt%z#L0Ne}(?h#PBJcoa>U7dz&*Vm`+=o_o#ASb6Sfq zGZ`UAhtA-cU=K1T_0zVmn~w79RY2Rne`21V&D<kePNHiGe7})9m)Q3U!akRK@8?2D z=i2)_S@IJq1T&(GpTRxTI5tdEFDhRjYxwC=KOu>^e6Kf0<71`j>F3!;c@keXAh|PI z=jEh-m}zZIW_-po1nx-lpzKC2qTcJ4lY5UjRMFD%|Ae$J^w|8n-F%xTvsqxog2KEe zL?vQ6so%s<_Z;(bXbZyM(AT=attpt8_hz>$N+rNtn~|OIiWa-DoYvK%)qpuP5lvJQ zaK-1;jH(E611=lWumZ_j+TSlWyxZ#gxzu3hyTm>DDBF#$**NcPiP6Va{X;N#FXTSI z(}zn7?PpHRDY%zbUq8(d9P9gg(IN-zVvV2)8Hovp0DZ(1<YX7LKgZ;sebtHlvyGyd zV)qB#%iZKCdAIrQvT%Z@^y3--YF@gtIx;D?!W{L)bC@|A#EBBe^W6Nb3_4z7PGLRg z5+2h0PyYL^SN3NxBw>jjUGy&`E*e_%4a`0%cQt^FxC;{2UNtrZL@~k?i4aR=GH2*9 zRZz~fM-KUjk~C!;Eus+&3Dc3bTIjIg5<--sNa{W_dYS^JN8_V244D5P59P=?P6OVv zWnVBOe>SqHkOto25sv6V@keT{=nG;e+q|QvVSljRpbQMB2zY;M&Sg*<fX8sL5^HLh zmsn}qM+nV;M*fKWGH%b=;2Jtk2f6s_1@HFREsQ$<n`WrCQe%S2=Z-G%#{~z$gx#xh zxG#c^6NIB&!kF!o6Q9D6+jJT$w8n6l!ZaPg)o(K(PJkqso~qRDAPg!Rp?nITIez3( zB-k+U4tWV@L)>9Pt1)eN!n(=?=QC*R7Wa9?5@ARR{z@*P*%X45$Z2J?`W55=4#ufz zJ3kgZjfK}dabQipgUY9X!CM<=(1>Zm!)qRmiC<0qpZ`YbW^o`<!XhMKsse|mhze5< zj=BB!9Mgp%g@>>NXyg7p``)->8Dymg_1-R$#QV@O7RQL>z=6R&AKH($=3WB?N-3~B zON^d&L(-+G?$tY9eGN!y3(j{qwL}XYA~g!mXW|0`kMsZScPb8eqlJV@n4L!}chrUR zAWN;PhE`Beh<Ccfna_qU%+3x@Q=!p{qv6#=s&l^@0p)NV-1$|LzE42S2E|JD&#+ZV z?Q#+17~)o;bEU!jGs5WrR^&CPtOBdH3#cg*F#15vs*)HyYLJIeO8}^`Ul%}sWdkj9 zZ|i4`+-4IA)RU-3PF6Wh!O8WpnwbQZn^0mv)C+b~dH6lB${pi1ZV-mKbF)*oXmAQ8 z3sGGHPJujwQJG~63`Qz8NoP<Gt8QL`yI~>v8?SoFZnC~+|C&klCPZkffMN-)()l$6 zvTWe-fyc`CugPn$$olTjr4S<J&?&NQu?l}Qf)5I!pd?F*<bO`1MvDmg8?h&n9n=US z=i5wAW0-$D(0c>XlfGjJZV2k+9nQRAtxf`EF47M&un^s#`YzOc3i!=wurOYQ58GHT zH9R*n?$%o%N(f^Us%k(bT#U%O6}>!K!5<Jsd#Ma~^8}}!nTz9sq>()vggg!9h2Nkw zqZRG=mO-Ar;j?XB&B4P%76RP_zd>$&J7wn50+R51Zz#AaWHJe+&gn`K%93)Mk3%a@ zdjF)%qZ27$eDeK0`UZyOy$<}<4He@`dzP~VpTD(lpAs2u{5HXkwz<UjHbV!BA|Udg zAQSNgLJ@Z!NoJ!4xRE-MMAB~KOyp7lyH6<uo%zOLto|mJM$1P9@?<zarEsNs9cUQ< zF^!%!wwWV=6iCvitUpcwgM-6Ft(aVAIsy^3X~tf12=N(C-RdTv-1+GpC~lY$h4B4& z8+%ZFG8^F?Pk*a%dzgravspb?3pt3dZAmeZyZ`LCCQ*HkIGIo&p@s}pdR<>g%2f1R zMRhBLk@gk9S$SfYySMO|Y-Sp@_Qs~Z=uSCM^j=$8l|Yo^nH0`I>R!gsq6U{MR49lP z8$SjSl~Xn5#=wi~0S5{ygsgX_tfMVi)WF`Iv>Pw5(s+KU9UOGkd}J8PRf#mAzu|9t znQP8JV!05Dm)9O%h`<g~&QqnBdZzl!h6dh%{6E_!J-+roQ2)^-ZOCnh2dlCS1-q1h z^!R8A^xIgw`TJ)(75%(C>b6>0P1&7a6I0D|6rXxQhGOYU6pLuwh*hjyeS+is#%|QK z?Q9<)GUy7EPQ9vEB+OFwVC6Ze@9sI05XJhk0rn8nR6d3IU`WR9<;BWxtKae{F>APB z^Lz>}HQE{YFG<3VT}agN$=d(}$hgiW197LqaZI*1jhY%ZJDlXqIc5pRjOZ`SOfgdP z%+j${i*vFmKPgHSgVSlpS`^vQgWY8FR5UTiFFVx0@A##|N{*YCgQ8Al%&SaG5Zd7^ zlEOjJp7d#*CCZ|@C~e;54^He?53gIGUl!Pl8>fU%7$;}GWy55@qJ>v1Ef<+}$&oyQ zxF?gTdp|6Sels|x@9%V<Ykeoxs*k+SeeKA!)_v<%nM?Xen1O03sRna1Kg;L4<3z_< zw=Y;LfqPpxErvz(Ok#)uKU}0(wLVubzHbeD=*Wu%ObZy25R%ZU|2?4bO5kg=8odTf zpW3$qVTg2$qhtUbD{gVd#WgBoZ9WjPFO{x&Bx9~b-{!f#Hy>Q>qI5h<qO(}B6CuZB zE0MJPRbt9ro8u`AYY30{?HMXGUtPi&1$%>i;`(iKQuo*M=9fOxEx|8Yr`cy1$;~z0 zArrwV3Sl=emi#Q`BT;8up<+z&wb*WQh~$`mhec~05e#a=ww6lfYn$NQv2pF`Ytz+K zb&Wh?UMn50Gxk^>?4WF~k2OD|f*JW*>$Nd?Wqwz6r)^Mm!J0H)v&EH!!kYm9L@K8| z#~cLb3aQNAm@mcSfIySC5~~K#b=}(hlt*xdD!<zgS&t2){wH==%!iYtf}K@eadwf3 zR|&i+&cQ*058Qc6a~D4L1@9C62Sf7GQScKQAF8y52ugP)uB^3Sp0t@F>3p0rii<r2 z`9s#QS7x~|ZyHheN)|-Rjh9zi+wt|MhwLh89N#xdj?lQc6L)HZdbo_)>fWd{XQeQi z#7P-)5>k8!*@i0mbG9x<RxC#4)-TSRSH@P}yL?44-q6q`r&4pt(PcA%Az_%d;q_;m z(#~2HBj)G-Dl1z*q@DSCNzT{s&E6M%=R{H*NoRWAIEI4(#kFu04(oN!1-R(?ULGg( zngtc831;`fh6gVjam0R})5&7{WxSu=RgSY5qoP8y2H)Tyb*I!y^Cx%m&G-af)AfoY z6TVQ4JWE^VM~bk9G<CSy{?M;D4;Dm504-(NTrB7~0y--Hr$O%lnuY=(m7!Jw6#5Ww z)X30e(FdAvQouCVcyHfASrZV~>SL!NeN^*PnAVI*T%5>q0_5?msCvwgv{VAFfkGWh zf<_47sBZK@1p}gt113BvcLyqDl>nnm*FKDrhZxeRJ;E~n5u3Lr`y&&@&C>yWLt6GI z=a=NH*`@LK{H3n^&J?R-C_haQzZgmF3-I8ba_~g!2!GPf)NI$~93N!bQ#G{wI0F<( z(GyGCUXJj`)W;1(@VOB3zW?3G%>2hs(wIV%YUi9FTD^|2rs7yd%#?1cVL(s){N5je zeGQyXlI9C7=&hNU=;(}juweQ9S$)x+#HTCiBwy~Vtt>T}cD_t%ArKsID$)GVI&>Sw zRr7>YS=4SI-zrAx%qd_Fai_^6*ph;!V1Y_zwUl7Qc^T6H#xHm}H~C{IO}TrSTRn+j zRg>b9e_8z*_hNMiMr7}}k15RCcWMf*>*N4=m0(vX9CUI7%u9u3ON3QxlpU}MLvONT znXk`+lc*kyb&k;SV;DRP)j&6=xd^CaL9^Iuuu%KuH2B+Es#ZGgn!Gz3Vu}hG9Az@| znPc$Xg=e$LClZYM0)v6YEd=J41%RWyJDJkE06I<~=0;eJgHCp`2--MIKZlzD4HPmU z1k_#+JJWVRD`eG9K!c<^HL^T6^?%qSKufDghL+i>vhLT1f=<mvXg!l~{iXH>9n?Z` zq~NpttHy1C0E+;ESz})`nNLuJ*c0~5idFgP9&4jR6nt*PzI^hFt4IG**&n!re+~~* zAEJlty}hS@@uvZ>-JlE0wFm?9r0YgLFfZN-SD2^-b)agLdcqrQO=u(3EU3}Yq1B!s z2b0W#4HI7v1G*8Gg3K+<k)qt*pXH$yhyj{o%D{3#gW0A-jD#qX`-FVnhXWab!j;f? z`=KI+*XNc5QKG*9>7^PGik}D{-zYK@51$`=rUD`m@MIOYHw52dX1x>yNy)3Nz?Q^I z3xy%)`g52!9!)_=aPgUzIwlF$Wg!mII$V^N!|?bUXjOvtC$86T(!=OqzNO(6M>2Cz z%l+<~Uft~N=$Nsirc#f%NAB}^9-&us|EwTyCQC1@AvGLl{(yI5M4*-=1|qg~eQ_~> zdqrO~aT!%Pnx2=OOVV`~=5*eECEL$gt@0x{$MC$1k{MYS_Z`I;FdNB^ES@=Bgp#WU zgeyhJCywCE$R29aS7#h-g8BO1mGu?$kiW##S;6=OhT!fG$}{eNR!6)m?Y^~=!iUve z0|+*1%sS&?sTKGNy~Q0y2T7HPe?Jz=0h?wQ4u&HkX|Vo%#r#FsSc;i%hdbptN)zV0 z4KMuW<`@wzp+s^)u+g}M{M9ZHMWm}pZuUma*FvXINJ~F`_@jfnV$F5l*)KOf@B8_! zLXp!JAyr91xn$n<;0XMT%apilQTp|-<0t5Qe}_MPiuiO!P$N|=shyVLDuG;wW+nQ| z!L%GGwUDu-1VpmBfY9&7{!rO7)R*il6-j7ys^Qb`A4<PrH)|fS@}X+nGQ^0uPt2t7 zgGu!RH({}01kGf*P2_%@NJARf8@V{AEMF@Ui6U37coIsM7B3c37pukVY8BF`i6Ll0 z?y_mI>qrDRSE$X%K9v>Tpk@&XV`3EME;k&`RwAioD-pNAnh%viDONFC>2yJgS%j>R z>Sa85y3&&4J-!N>*7^fccFhd)a&qa63n9X7nF)&oVDM0xOFqA7pZWSlcNVY>g|x)0 zoPUX_PdGmO`<4ZIo%+hGR7>zMSxiy+#;Tj&`QggZ+(ZN%0^qJlp)wBx5-d;Y#^b^E z2QhW)wUJ^dvm4EcRcIrnCRqyvlZi92kWB7P7uF^UEk!f4OQEtgG~}^QGe_vV$HPCj z(#<e=Z9a(VmMPUuz@_BVJZqW8L2-|2{WMV$XC#fHz>7m)s4}yRt%F5~Mbx%bjg|)2 zLH8|$J?Mxw=*<CeT;w#<i~*N|=1)H>%|lH5!uJbbaGh9`H5#F^{F-<#-vsMSA6eWp z=cp`QWKeQxAS*|H+e;rdSClN;uVG)>9HRJmEvAe<{0C#H(yjGBW%-;eFc1=Oid#z* zGwR(dx9)KNOL#_9$gC>I@d0M*hmjN^v%mr~%-Wy+DzcnFtczFHE?+}lhR%!ds8|eW z=fEVix9S^Y;uNi6EXHqX7t*v7xcZUd<)V)?;e?&5h&(K{BjFHYZ)%G~SDAL);?RS_ zLmpr)Dx=l>ah)@MFZL|yB6~CT<bAhhTU_2|hr>J0M?e)*Z{(A~LR#!Ba2x(cS6{-m zSYDMQ$0w|J<;^VYm}v;Dh<nbuK!S9@s1~X5(3AKtxby59G?J84o?Z~$*(H54+x4If zE`^_I_v;FrR^;4H{Y<>Ktcy%M?T~c7)CYS!LG*m9bYH2(>OEtq2FJKZJDG5I9$iA~ zY^t!fYN0CbpX0dw%Lxfo0X{Ka15WTc!n9Y4epdv&f&@|pYW@I0K&?3L|5XZZVG@Gx zi(oiH2?~goRnb)p$89*k|FWJz?9RVt$z3LW;u4{K`g$;@fipfVr>}?*+I4VqZ9C&; z;CT7+f@KdjUc&QWfL1|>Jf-Jw!RsBi!2X@V8(B#YJIU19tqqfgqaVt3$-@E<CyW05 z*J-RWpmmn=USQSq1a2kbEm5Zmik=72QY7U5SU<Y9e`x=SP97#!zhYgcc&$2d^!Y!V ze!8#-;pbKqzCSz9D}E}S+?mupGy1`CuKcK?`-6M8yvLMO$qsI9xmo8~vH^SfR_&Jz z>opzj%BjI8+u1!ms#NG{eq@9mwlpmTzjWTsq}(8LEY{BN=9u)`RkNJ}DgICwsfA;# z*Uw&wAA6}?eht4xTi)r`{!&)0ln=!FrtA(M$J_OLr0Q_H?(KXhiQv;KGQ2&KUI$Bo z2*Pff)PTd5>`<auzEmSGaBbx?MG4!t%7-hX5_pA`A~S)<_j$kloN*%aup57Cn%S_v z?`jbkf}`?#IFFAR{^;2<fG_D`-8{-CNgvw7n+foz@YmQYpHx`c#$;6dOLyv(a%JIS z*exAtp`gP-+{!_Nq}_hy8uBi_6sQBzM5Yfiwi~|VuN59|f8nVN@|extk$+`FOWpHf zZ+_(BR953^(sj{po?jaSA4uOur&0+G7Ts?}&Qq?Pv_;${lT+w-B&+z^(BPEL+S+qu zH&g4?yJAvf!WV8nB=-EM*8Pj0=u1=2M{do3-anwt>Q@k`pUxW@r*g!4X;oc$beVOB z;>t;*XZzT<w+`)XLG6<sB^wjVF|mQH!|${sM;R&^?N9yx6y=#^mIoYCb!p%+980Kt zpY{W{UE8Aj6(+X>{}!5-`Qiq={yYioX?)}`+4_OB?#I>Ne7fbOag4q}rw!!fl_jH} zlCxt4mwnr=J8V}nTr>Gtqcr4tFRPOJKq{e%efa1=-cONyN8kRcwq=#0z+-<uZKk7| zwC~rZ8nyLag-?n(?YBxWzAx5k9DH&3qe?4KXl*izjpvvpU|wXll(GHZ{xSX!?%7bM zScz_b!M9R%pMiG<1xIfj#+W{IjF~;s9HAuJHEnR|%Jsli2=Wex^bUADa293HdHi8n z@5F7*mMhgFz@>xu5jRq-NIxXsacQjRcC>4lKCf<(SKWBJw1kUK2O60WqbR*gTD!GG zb|Y7P<FtHSZ}l5i|5fq2e|?MukAVElho!x4)`1UpU&-0O8lJ?aP%s<{k*)t|u=yG& z@I+qT&1a&>=Iv3L<8)yb&&I0jlVYiSpRW-%8uRviylmzyRVChTt#ap?jLQ=Pv2{U- zkL6bMFW{|7<mHTqCXGvf=G@M?n^P#NQ7j#vgEwv&c*SZfXcRQwGcNEh4xf}Wkv9eY z`aahJjcMUjZP65=x|}wrE(xhDzZeIKi){N@?2}V=?f!K^hmC71!g@=m^EV>PEtLb0 z>+m;K7mf3dB$Vs^ZfH3TSM3O>{ofB-3A?wI5p(qQl7G{{il1<gka5-A{yPnmmSUd` zrUfd`@jpvW^HMf5zHGfGo6jc#W$?}=2hWDCZu+$jr}`<J94FK}*gx$Sd6-ip{IIGr zxhw70{0Gt)`c0qBNS`A!S97<()SKDz{t8}tmjZ5d>$ysJ_Dwpt1rp;wEZ=YZ8!q<+ z#rV0-Xn$Z%JtgB{L7J1)@{eD@Rs5lN@vM%|%0i2{%bus+WUIhf+R)Ya?*!3tmyrY6 zLaSrdMS8Z!^A6{Oux<m3eB%2Oy)T|n>@GY1__d4Ebrf9TV%@G9S*v`C*$FZ2`+WZG zYUuiLO55pC@6;cKfJ=$ZdHbYf8`>l}8nqHX|E~AWpWH+CMt_u<ZL4F*GIejV%e>Gi z?z1(9XDZhjHz=7OdLi?$<yH!!A{4)@&$r-zVyG**Tlz#fP$^mmr+dznQ2vx3!lZ7h zAg_{KX01v!UgE!$;B;JXz51IQ%IPP*RehZdx~|>suaH)AwAipBlDs%n^ryDo;kxJc zyOo`()bd}yi=%z3dMbEruG=1Y=v~td3zYG2$ywJe8J)V;<S?Sc{q@|ILBfF$GJ-k; z&ptQXC7LV+MeOAmmX|!0*%1o6UE5AC9qiLsRpuI>ER0)wZ|L8-JQ;1#-_L-5m_Ay~ zBXsSCj^l{2)<+$d_sopGT3u<H-E7<%^GOfof7Z13tiQToJ~&*WJ#=O6WW_BYrM11s z<bFF7@L<5UoC!b|BwMSTr>xhUE3X$63u<{|_4glag~{Ss9DnN%{vB_>B8`t2o0FK{ zdC60AGW`xO&2iS#gXFHtB7?Jt&Z)}dGM28*)Q|SMhqv??O#-LK5>q}oX^}p7BXRJ% zWu;EM<m5P8Gw+IE?QWaGD~S&i^$cU3&v`bESE+-_Z^`)ni+RJ9_}nwdYqWg4(}v1H z@5$JoixROyCip>aWCS}g`x1pr3dIQ-vFNG8)V>hMC+7)j{x8_dr>E-c^$Jdd^tJpY z8m7+99|ySA@0>I^%S!Cyn@@R|9L+LIUrj0e_%%Xz%X|~da{U?mh+qo-IPLzNSiw@{ z_cg!2OtwplfB(&ASlOA$Q<_M3e`K=u6H7joU#c@xz4A?}KDpH3%T;Bs#+u+>UF>np zQn^9;xTv()FV7|!(bT;pA>HjHO-jREb7{AO_S;!P{GTKZTTFF=_QU=mpMkTRi{f&Z zx9Ra<=S~aioZY}SuwA>}Z&e%_#~^ffcSGy+rOU_jCP!8_IWBV|3fHFST~$K+C?8N{ z#3$RSG;9|vI88q8wru&S9Hk&JpSOFH*TG*&=Gor}p<GKFG$K_z*7@$<w;qW%;|`Ll z_%}nn%j4De#!Omwkhepw&CfZ^37MD?D>=7~-#s-obJ1?ZW-g4oqCh8_&hxox%)wlW zC7CCE|LXO@co5b?Q{#HlJDN=f1j|1{&EeZ+PItzl6$szR;!V@;8St3|mjSnr2*T1O zQoyAMkgbrHbN%3EGllONh?1fRZjJEpb;38d2raS@qM|eaNI5RoG9ds@Wj`eNNfhDH zA>oT=@I5bEPhZ2gxxf>tg)<Fb7Z8@4IHV)4ND@kK!Q<4!nP43^rp^c&`%{w8f9umA z)(ftVT+X<@6N>)ClrX@VbsUJZOB8kH0eaT(G`R%C8xzkJrdUZZs#G!>1mG0i;nn)D zCqVtQINTcfK3h~m6CMMISNc{04Pu1Q5jSRRvde(zhoiaKrUv%hF#?`@5cv=2+0uab z7MX8D&o%U`;q0Hd3>lzqLVX*}MNa6RwkOoiIS3RVkcTV+@XNL0f?%}++$#UjqK8G( zT!dqHkK#fj%L%P>l@-;%V*M|Blf20e4Eh1^|A107haE8FEQNS^oA9tX<gP|=x$`5# z6!p<WeD)B%gnXlorx}n6!JOa|+C5iTj+qXk5!Nwm@bv)A)z#G%1sN&Y!8qlnQ`GV; z_)l6@gd$o;$Kv>>RwO{;$s&phXiylUP{cQ~w|w4TPT5!O@A6)4(Q_w)pW7;$H;Xam GPyY`qtQ;l) literal 10854 zcmeHtRa9I})MeASOJl)ZgG-PAjZ1KM_n^VOad#5jArOMQOYq?C76>%ZNN{KP=6TjU z%-gK>KU_WM?p0N%R_$~4t!PzcSxht%GynjADK96b4gkREyxq^C0N>8-h{Jqu7X%w| zC2;_tE)o674Ds!m%0f<E2>|eA001Ci0KmiBD+m+-@Zbahj!Xdnp$q_k$R(#;?c<vP z)kRLv4FEs~{dd3tvT}$40OoahDRE72xRYFT!}wdu;UEv8vN2`_X)^s}{TR#4w(${r z_LV0KNf`#7p%>3S{(m~8jzQ*6jut3&e+k`CnbY|#ZJFDnMoLuGp_-F(e_x+P$`Xpl z{s}01_)gy5{<-?tvvup`_nNnLaBr07M$uJK!4iUnN(D#GP*BtFF<e0lM+ZhNK->0! zAh_oODj?M+aJoTs5EjT10B_m@SPpCtL^OR)22=oy;pM<fZ?4b>0?4&25Ge}q2D5<h zM|ntgm}06mYn1bE1=|7&0UBmbyAa0p1=*Fa7+=w6I<yLi45v9wCp}Ix{U3FOhgL7y z>o3Rbc+tGZDw&GkGW_ixtGkx!oe&f+=DZ&a@#a4>PhlDN1d51>^%NC_e5z{PlA*%U zH8AixU2oegQbrZV`=_(IE7N*8pKavkLxP6+WPIGrwOzH((#vxhuGYH=ADPZ>OiW1O z`ZT3cT52^FchQM7G$fM;kBo5lIAL&pQl8wOWhFJutqGt5&}q;l6BD0Xo~s)h=cT5? z-+pVC;I!HZ-blZsB*_8=<Y_kdC8+6b9=Xmy)2luxldcpfH6Zz4=MPTvaL^eEdGFa4 z6Iu=!IJe)zuwpKsKcJKF75jpm-~9~bMB7e90Dpqyh{qQgdl=Bui2f}s=X<3G*jGCP z_`)9+!wcv|YY71$IATOzPai7u5tRDRu(%_o9;<SIB7!#$nkp~+eEBBoq{TZ)1c~r> zQ`iU+`X-JZwPYx}O+y(d^A%i{aPRnrjx4I;jzk>av8X!F%z)m)5|0BWm`0INL_lpc zeTyMm>%Us49GDhC6_Gat7bFg3%K&WM7U{dpna(8l@}T5=l3Twz_T+rnes-<#z4DFl z=<h2BVm8>}QpZrn&7~5xJgC51MVh3;!{3+H%g2kAd}mZC+;q1ex20J<^&jfw;4s(R zt64SH_84oimh^t<0!BSwMw}C=!R6qVuK_2>YGS~NY&IygwDsJ-dV7XT>T@);>T^4t zb}DR{mea(n`+F5n@n5V;fa<K&_3He%;o@u!`ZJ$XW)gZv(`PmD>F(7lVy3?lm*}vq zNcHT4yY#npx8JRosLQ-xY~Juo0!aKGi@L(~F;o<0%R$44Dn#Ytr<b6;(XR6EsHXc% zPy(Z7W~Y%cH#e7&VyM)GB#b<xM;CI%FRU!`&|bFMk(%2oT>bS5+@4c)|NA~KxDGYs z!)v?97w5Do&YIw7W8p9Fm6LaW=P&l9`pn3xkO}(!IukLuD?^!u^|79cQ1$h27;4fP zEXm@QB!?ctrSiWvgHkST{m!KEc$ugXs!=9{^kmk*_n<{~K5`((Ggh@15crf~<+Bmi z<!Z|)I(A?~sny6OJ#4k-JAHQac(hM1{0l8LZHi>dDSjj+|B2*b^hR8UrfUZ^6+Mkp z*11joO<vU2#Ht{7pJ!25lP6|AgsKU(_$@{UY<M2bAcHW&O6p@c2TOKYOWph|bC>5% zavTqdC}a|ypaFIHDAH0>wZ6J)s55<)48E2WGdu-It9z3<kEC<}1$++y!WU+u6KJ&9 zPX0Qh`2j`bq$dZrx3;q0z4uCr^oiqY@YIR0*8vhzzqsv4(ap(faN1^@pVy@SQL!sB z!Hk>{MzfQcpzHc^%ug9w#BfrKbua}Fi9E~)k9lkjue(&0d1#7)=U2~_=A-uJ;;DyU zbXR~uDSp!q&OUIOhw{_oiidmp$9EIgZcpVk6Z<d7=!eq)A;CB-(*l&O9+vdvVQ%%l z&34QRIXx~eoMbfWnWZv|U^Gu{+X5B#4dozBr@VkfD7x;edIc~EH=}PiAO_0$P%y(9 zl{6tCyomD9{eTt+w7-6Bcl`T!gA(tat<Q{oNii!w+c&R?@qz?|%lW0-Wf4h23Ey|# zviWg-WJ{`CtK>k4k1Elb(OL_mmgu8SV?-S5Z&m~(pd>%nM9H$M^7X^qW9neh#Id2B z8)vkzM0czqDB$usx!L{*vh1-p`}KN%9+vmDF({-Xwet4NNQ&y5?0(ZpEIrUTFHg9I zERr1!&-8a7r91=uEOH~`*a;;Oj$Lv`{7N`%&HVxJqRFGnD0j$5n~Vh-aFlbUW=@?g zMVQ7-re46m=Ps!Pd?(<2s9KvJAIOQYkHqO*d?c_Ua5=g8q7yl(!&6gMVpLsCMSVft z{zp>-8S(av^c@`X(f0PsvqVON$UiRL_e`xE*b9>?p%k9Y{ML;Qf(N_ivlo^QT=X|i z{YcG;YZL)<MUTkNf*L(3aZyI2+9F+@8~R3~6pykul1I!q*xqjCv6v@k^_6>FWjttR z_yvrf1+>N1CSLeA7vwg$Z3X9rahyw`WnqF3LgZ0V)^RdUn?my6@W{!?zDXWaWj4CJ zj8Hi81m?GFW8Y4&4r{<s&%*bmCU$k&uCVF_nv}hdzgwlSEMc-zQayL&SEhWGcJntZ z)wxl`>g@jVNEQv*%hls?lTKc*=cIO6McQd^N_}su9>2Y8COQ*(?JsATNSxXG@zs0& zbOSyINGEgiw;nT?QU#}kghNzb2hKr6p~q$Oa_$xsV=KQZocR8!sY<YsSflx%_h#nt zR67<RCoVlacg*0~5im&uEkEcPf>9jWPR7_QHpLbbk+=3%fc=QJW={xZl5jMLZ^mA~ zfA8lr{XxIw3$YWcqCWnvlzDe^e#G(qOw8SKW2ov&&|Mu)%PISUOxB|t{pCX)h;hs^ z@%s8|Vtn9T<`UIOyJ*%}tx##t<SY5h8kWGnd`?0s)srjChwgtQ@lV_8n)-PozddzZ zJa4(@CT-{$g@w8-na9Vw@+5Q2)D1JTuA@-a=?DdbD4u8ySn9ky?PS$CO7ey99Qn<{ z*hb@?cy^P)>m4nrJ6)9;dYmjaHB?Pw*EF~UJldI!twQAAYu|rX33GU2G!b5P$3Ku# z!NO{|#nSz_EP5cdoaJm2qa$<W>Ju;JAe=3>IhW;m=g4dc?SWZ+O-C6`3E@3D@V_;4 zDe9k=-ttL-?e>Ww2QeDoH+4wKHPi2N;u)BkkGqZ>Sw_rnYWe@w<+T$luA>9g2UD;T z0arb&+{?f<7^iDPG#TVj@$$MT;yxt`PlRm)c?@A(NQcnc#ss}%gL+C}$7h)E^yre; zdg4J(Hhs^iWc^nLLJ4!MTi*QzlK}FG*e~gn3XW$xI|s|VEzzSJcuWdz#E3Z$tljmF zy}grgl>X;)mE=Tm1~ab6ta9^3f;r|Is(C(VI=(D)0RQbfiHp+9AjZCbqjwGG*jT(B z0lJ!3rq>*17wZK19s&5`SwgxEfo^>PLh!~N)KB4>rf2`IcJd~R7B|Y2p-7`zBgCws zk<o4M+Pu*HJc15&oviIwCFMW39yLV{%x?}JnT;zklX+vqWEA9t`--c|oJ+qG>L+I> zq8tjlOJTFh_4if!zwS7+^G{z*hT${h$){!Z=IJP3J+NUUU)9^3orYl;H4dcbvRJ~F zCFSy0QX`w`<L36>*;wp5ie>E_iY=!)tOb4ScdOKxY_pBHdN(VnSgpAP_C1-BlCT~p zIat+}A{&|zAnLN-&7ZAu#^$3LX5Wu*{7SAuP55nZKC@E3IwcjgWa{8F-oOj`8rD0I ztGjxdCm4Z(33D|0(n4+Z!8zja&~H|iIQ7>iTt_z8@$YZ(nCcuT8J_HwbOX1nR>0mL z!SURjlD_#FBN>SxnNX$9IJ1%6U#RHmD$w_?Jz8=(8&q`1>o3M)CPhZw8rzBnyT%0L z;Vhnh>evy1RA2|i3@IioD&^D;<&@RWZO!ELUkGe3>Uo_aeBC96+lkhhJF^20Eh8-D z%0evEqV@R3CXzVG|E{^aag8fZJVgqS7zQfB`~=j3P?#oH@$&|)jW4OgW>J*v7l|F| zs^s_sG79z9gRcu`IL*WBx{pVsHHPLArXZHg*vjLmf{#D8I%59R>BJANz1-wS<fkN@ z+#M|9$8yE?X;jpjVlVm&`NaQ<9K!86WfgRJP|ve4`<8t6dkRww^J6y8@5A@FfhVg` zlEGOty??|MCD$Ih7r!+VYUBm}{Zr{&6b&aVUS&#jV;=$FQyV#f`P1Od{S_ftihubL ze_+_{eO<~S3JE$R*l2s#ZoiAjA6;LMX3iABh#m*MhU3<hXZd{ykM2&dp3nX+By>=^ z9Z5}E<dC!Q$Hs&KtWk-1EvWwUBNJltwq(1;9cwPGVqg#~R<j?V-=L|VoSO7at76Nq zz=p#QJ%ij~8670*BIA@m_#@pZPY`p-fVIV`3dIK{@f!~MLE`2q`;^wrc42|X&*9PO zBNcu`v@?m@A8O2PMj8R%dXKh;JgQmBXcgZnCPzAL5~zyEnG(z7%OrJjDHFeJB#W_O zr6nhB6{Xw`%$)V2_iPf+#2QHkJ5g2POSnJkL?lH)*|IO_oY_+ZvQ|@7S{%Bh-pdM& zPUH<Zr_owK&1;1Ogj1?F#R;~VA=-}eqmrI+rZU9P5`uv`zTBa)v$I-uQ%CWPvBr*X zeW@~Gm=(+h1j1ero`7dWv8Vcilz*_-ER$DJxSHijpP=)UEj=EQkr4<3s~1kGrowOZ z@+)HE<Y7*l`Lf5fb0{uK@DD^Ih{Mx;h`;yi7G>Z^p9c;m9SQT<&GP<Y|A^7CyT{=E zZCWvk<({+7DeK>fCQohysx^hip>EDw&+P6CJQ|O_lQ684HR<6z0b=q;MT-O^PIT|& zXb25afUU}>SZz%VIV<_YV%e3<;e_u?yxd&JJEr0#M9y*(LUo@4OSBGdB-Aq~E_JMT za@V5k9zUGKD|bsO!dCk?XMXe#^E6yKG30$r(mH0S7^#-W+GEZ6ttWC~vE{`?JyR$= zxlce~ox5^Voxc^~=Ke)`+*j$EYE9eOf(-c3>moiHo%^s1+V3FntB)!1$+YPqJ^0`w zqKJ!9cd`(<mos4*adn2lebF4r`A;$7=hWwghoZEQee9n>i5S|*O3~7?vy0z!m!~b@ zpShFX)2_|UZDk0q3u6*G?j@Y;?u#HX2Eqj0T6I==KhUZNKDpz;IU*w$qHTCS>l`*0 z%o4oZU|+K1tIIQo;~O+so0eg}E++%Ld%>o?1;1)Js;4|@u`BU{?n-#C9B+}mf*z+D zE1FUzg*S?^`S|Yyia(0S2Ve!vX(TU3O!V|6hC8mdV~Y0w3evd4z6>-kKG%HgU76`? zwipf!__(KnRxXE((F>zrQ=U{d(#qh|NeZr#JnODiTCUD^yt$vh3@XK=;f^4srNyad zb2Q!RXE;n09%zaT?To@Qmb}2G=*URU_$n^qkn4L}AKWu(;Y%cw*W&^6CQ~G-d>?kZ z>?F<B*cTl({exhtEs8uqCs6(F@Mt<SxzVLs)b0CC6-DpuyPXaOv#IHs0O&G671|Fa z(cY%6pDX&?5Za^5ch>K?&EZbob|HD6{(&xUlhDS3%ujHdm|Zd=DGa)_abmY8<H1Rd zk79?s0GjsWP#i*l(S~v&a&l*TT+O-!-3G!V--h}G&d{1$Dn7Ci_zSRkoQiD^zqsg9 z1iiOEBCxpN7S4=ZkPOC=LB68MYkzI|Ne<sG<fOYTSG?ZVeI7YC;DJw;dckrNOw+~P z9s$VSjX1S7H~nmBt{7F=h8u?*$Hwy0VLZ<C$1gG@s+dyQ#ZEP`m+qv>98m`xmNVSn zp{5=M9kC7dE3sr}n?bcETRPX*n4;O&Go6TA<#I=tD&Hk-t)vG}1FmKm9Nko&AId8c z*x?IDN@Na6*&U=&6>*|_r9?$Em$gO|GKBJCRIjoB?Cx%CY%C<2IFF-61b@;qVM_1t zRXXzh1%t!syW}QuC1N*(E@8JHX(&&fk(zH^GS{p!!g46{?t?U?OcggP_$o(hg<oAH zBM+X4y=fqF=pW6T4`wEIU%|qC4e*3lPA2~OY5ggMO*USszvf}+L+0k|S%CosdvLi* zC|B}&s9g*Fa|7yk62X}^UbI=i9O2D@EPB!kF^5Hfj}QzVpdEEU{m4L?Xa>p@13JcG zD12$6t-D-BWg1iqr;eU$r#3X{t0uv}{8cUgNw;MlgQqRZRw*>Joa3F-p+P(c(_6Uj zq)j(eX}ikT`G8&YfB^A}Qv8gR`DaJ&yXc*8lRzwNj^3~EbHUfyL0Spb{_m%tZTuX( z%^Kx~SjnRrmr{QV^oKFsJ>ZBCe|*(!$VJPmc^w=3!3F1CXy4HP1?o^04wIwUKbjug zp%e)4t%=|O5@%ENz)LuOs(j1ORfw<(NJ*Q`%dWJB&ouFlm8GacOvLH62nLqph9V9^ zl(xqtl3L*~m<s$fc%GF@;&Gf{?q+aw@Qe6|&NSMy*V4N0XG67y6jm3^D&fTcEY4#j zD6v9!M^#gf?8eX+zJ0RHphzU=v6tO5_6~8GK7QV50}N{PJ7ZCxoIOQ}ydZy6<urrY zp5pb=Z(;8Ac%->Ql(Ala1?hF&nqIYCM!#Bag|u>b96|4g0J;K@&)++X{-_^W5xn`= zwDXg!F;`~uJ~Sc#AFh5-7gC>iG(L{egN<Ffj)o)cbd{3)Wg$igReH?xKNAq#Vvabl z#PdIxiTs4>7pqc`&su{bRaQ%Ph@TJ<WK?-S-(i!&RZ{Y$%9?qh+0pUS7(_ALWe7Ma z-a2vI!gkPnx?s=()nFAH<<v(E=-Ti`e1!cXV)*;VyMAn>o|&zI0q^;!!ZVB@^gNO< z#;C%B*k$qJI5XwJe4{$wD(lPe`TxT9FU2fGNg8ruf$71!%6J?$`sil#YEP+3=(F+{ zsK)5);Sw+Q{L{bEUw?N?^Znla2z^1}M^Z`Pp3ie<;M`%)WIU<J@0FFh#*)VRdc4!u z2Q960(mA_Bo#wO6H8~Ue#bsqP$&qPF)J9w26klK9zbpx{$e^n6aWZnD7CT9z?431) zbIX7IvbBDzy2={D;haN~kqAi;YZP$4ins4i37$j#FDx-4e`F?+Q)Pj2U<1@fVgd-! zqaCXx-&kpd%oVEAhD*DK2Ak8=w?g1~go$@cS%p*aVAL^N){|qYYE64##JPcdxEGXP z^o)GI?i{O%qurW*ntKs(n|^C>aL~@q?z(%qMh~tcQ}8Ot!os3lXX7sL*{~%?;Rl2< z2tV<7iSJKjVmG*;=IjIbvcoIu7cD+X?^ylLXnuPlyd4X=k5Ce#CBljwzh1(Rrnovl z=jPh{e452q{g`+2<)@#=3eV3;&g9_@F?Sey?@kL6R5hvs90j+%j*gNt{72okAwy1R zBS7vD7>RJP?_AIk>K|XWX%H&(eQ;~)KR;|T<92T|U2lX=!%i+41Wq&nD$4n7cFXpf z8f_$|Z`TdzuM&V#s{obCf{-l(y!<Wd6Z7HjCi%ixm2jt_;VxfrG$0Pxe73r_u^?!g zl0P(ekU~`fAX2a`o<lH|0+=X{{3n%WZIy>K0Wwf}Kagix;Zr&5Xu{=och_CW0Z`6^ zP|>pA{cmkm6;boDPnE7W=uN|Wa<-_X##2=SXo2}CF{FV{j1ZRISN<Uqnl};l|K!+9 zb)0Wd!N!UI1{DahT~Wad4%2H6&hMA~FX9gfE;0q8!g0|Ecj5po2<1ss6Bu{|0u!j_ zlMhJ&pQzr@6Fmp?so<{PG~e<mEDIXAz&BNKTUOYd?Z3}e5$A0pxsm~5C<SQe#pHE_ za^QfsW*#;4XUIV)-^_P23A*TX1)^}8aMvqligdl$|MkLFwh|FfHUCX%et>Z@;B6zn znFAYX7lEkdDsNp2@FWJI&VQmhxgfaHaZd8|<)0E(Z%Re{hK6bz)_WSDmZaR0F193R zuatyR0S1AG-n&PE_peD0VPF6jnb2BORMu`BI5sPqnVtE^e9?ue+B{XQ;}V6>`@vw6 zXkJ%*a?RkB5>Oqo#UCepvG8`L%k{pD<+;P#ybDKYiGVOW1OL7h*&_!(gJ^Mi`|USa zuGq#|C}lM#=AgrL{-_Y_b@V{v0LE%JjR4=63o)kxAco_@<?zcypAoIU-aP)jMUPDb zMb0^QqlZ&jsU!@yf1qU=HEyx`aL&VF`+DhJMxscMEct=LUokAy@ln`d!JGfCh3;{^ z-LdX>U-nW5QdRa}rnE;9Q!rvh;@2uoa`cJ!J4E=USSL!FdS)5gpmLAb$hmM6`#=xV z{%?+l?{tXRj7d68jY-iTI<l$YT=ZRD1D6-0+VUrTjb+-)fD*uEFk+0kx!aJC{Bj?T z+cB>kptYH-qdMse=!WcOC7XjMJpDsBIXew=wu)t>w}GfL{KvW$-|GXV8d1S2L35U9 zRb*KQzJ;az9wH6(x8!!BM<*%h%=o42@&5i+LE+O^bd3JsACy7Xc2+Bk74c1_U%z^g z8bl8)4C<}O#P244S2S$2v@?DYX~WUf)<%eYkBka6opV}6PMw!iz17@CElFFB#b&s5 zz@+#gn;`m+0oyaM!PMF5pqC)Otv8^J`!Q1RQ_6T`)x(sqrpH%91B0bJb|VzmBRk2b zbh7S$OIAZ2Jv3x#RyV(@Ja-Q!FOf*U(C!c4ugOiTG>|Ec#NVC7E)Ms(h;y4>Me)Bo zPDm;s;7n+3zDl(kA88AwZCBkD8TX@Id!>+{823xS$~@6x^^%tHo;F1I&C1f^w5Fw{ zRayinK&M}6sc&!&j?c^6Bx(@THXG+E_c+$>3%)c}Px3o(nohAQ0CExnP<45Osxvd0 zho#ac+#lFM4X<QZT)zz0e2#+g(iYi0zwNmW9cmuwr6hZICq<pKmqWuOxW3}4Yb$H~ zbR94D<NPzi!IbVdQd0ZJ1sg+Q)@!N^j|z5jVwKzOxAB61k?{ah&wI_-`&e?reF)Fg zJ2^7<+=aZNmsC`;@yVk8@8NdY4G#40V!&$JLF;V@m(+~hy*Nt2l;l*8j_TWA9kp3; zM^wlKv;s}QPl?!6vi^pVAhqaH)*0syIp+-G_rDIHHgBK4tyU28xevW4g{Z6#i#Cof z`VH-wwSv0+(EZ&q{aABoWNiAQhQ<RD1JRFv2ff|{Ij@2IfmfXbv0ZF=bh^j3n%hBT z@svat_qOLYXf89ggcMZ*0T$q`x?)*ZX0(i8E~2sTEi+mKO!f<}xjWNsrUq2|P(+D` zM5q;QI$#y)WJ9(oQhL+vgTiS}s98w(5+vdJ%8udie0G{LP`5|8DXG<4<=&wdGxCPD zO(K$*U&PEDocq=2IoZ_3baytm$xik|Zhl&Pd<5mH<TiPJp(GNvrV#}vfM<b!ir`_p zuYWtqij%gszOk{nzVmA;dRZccNY~k*ptO-za6Mk#!cP!P{^+I3uOVv8o8vR+7uML{ zJ;euXFGf0xgXR%|*3m>5$60+-xdPJEDo(R+{}BP{VihLYt34ZOA;eeiC&+4ca?7kZ zTcEx7YG?AE^}_G5i*@O9ss8QNk7$_<(<?hqpaw(22X1bMa$=f791IdPt$s>6fHtx? z@cmjNDq0S@8=L?{qbVFrqy^sO+HpJYaNooB+E8;LwW(k{ztB#;BB7(EJH%H+bC9{J zehpL#lK=%2M*oP8o&}3DBw`DrkROV4LI)C$v4&1C4cad~Js@MGq1#LhS7Y>IuiQZo zAp)MxMM4;_jf%k8l$82<BvSPu&cv97&QD8YyXo-;W}yJzZvQeIe)JtMJ3>!b_!6mf zQyEqT1kUJy2d^(O`Z7Bexx-H-3o6l32j?FZZ|{;R(Deagbm>O1r*5;N#Z)j8{i~G$ z?}=b;K3qcX)3TK{I4Hw?K-y_5b9FU)BM!m|iZmkyGTt~ifB9=3b3MYG`gI>y0kHs4 zU4T9)oRY#8Hy8#ZTPSV&s^JDwbsT1MKPvfW)UnJ;K?sriLhW*NRIph9zoo4&=KWp3 z&t@bgv?cmB=T-T;g|`QJe;TKhPoruYMF;zS`&f3dY^!eHyy?bOLF+Jouo&Wuk-R%w zDtNrEb)v^fN6izO<LujA_^ZGt)cxKk7-_WMdUL+Cj<@x>R*i!OE(thJlGk1Xaywr9 zAy1T&!v3V4+H=3n#RSL4slT^n(AF07rQc}vOr*UEROfcP@LBK6t3g{989LL&>^xir zScFbV=ql%(sidOgx}WFF6Zz`V!udjT*)GRA6NC>T+2U-oi`-NdQjG{|^@y#2G-xc% zoZY#*d8RDUdH1ECv%(A01R=AHv{fyzKzKq3{r{QGG==qIi&Y1F9x;`Et<hqc4uLLP z<OgvVf9tu)DMGVVF))=+0$<`x_lbn;!^OAJz*W&hSPGhyLJ=i_N>Tu=f@rV>za04U z8_C-`&YAWlfkC)n0$ZBt3{1Rf{Wr$eU*px~q??v{WArQ(Uh7bV#&2)ry~vMAh=IzB z3#S>(0E}Ou`hSPjf2xVYUyt+(Dv*53Hv@od#)vSJqw>HLE(Sa>u>H}A#=(ycf?$ub z-44b?eTqeJ{|a~;N;ZxvpJG)JGqSD>yuo96fgvyt-P?lgT>w;kpseemjE*mQ#gcwb zW~fT)w=4?T%&$8*x=iUJY%;BUMdq6Fo(QAS+F#9-q~3}|Knj0x_A_jL@(3A^U)e3Y z52UQ&tPnM=o}{>ZNjUOKUBC)+8(Fov5%s4x6S1BC$%Wc@w;=9)uk!S8zBQHy*6(P) zt#EAUK*{{IwpUGlNe5X=jyLLI$LnBs6x18$$S3>~L7n3Cyh=1E<rEbiXF@2trMK>x z6ls($N`6GwhmWVeeoiH>Z77ANig08qnJB~13r|oG<{z@C<W*XO)tX()y8ReHnz*j} zNAl4%*DF@dVnG=u<iEhOz`$2HzCdo1p)BgQsCbHMJUcFF(Gzobt$CW#BJ_0pbC6F4 zW<s2YV#=(|6!^Pk6ZG(f$6c;~8TDKW5r1UWCywNE+u5z(#Rs5{U)h=7xmf0FmaEaB zAja5mqzbADjDev(=d#bFS|P$UOsyrl+tCZgtlw;>To#0NANaM|evK@<GJq$L#ka=! zWp#uu>VV&RvdC3r<rbvP_{s8Wb8~7#Es)*wT>m0EDY-Wm&5WD-ByPBfUevRM#_PB~ zi5&G@HFSD->UcE1yNJo&aby*A<w%(O@PHT~)JZ;qz(sBK3R@<tr)9xZ{x~$A$uX5Y zy78~)tHG42MRMp;QO(oF_-K;|bzw_K`(Mf!1v7ub>g?0+_qSzWPpEq^0DBQ}*&2`e zv>@(EUgxKi_)33KM<TukJhXk9@dw#>ZWoK*M<(cF=_eqpS!Q7L_l0Teq^86ZDXi7V zQ;gBmG37di;M2k5wPFIsvxr7AN_PG7YG_iqa~Yyzf>L)1t5ukjv$u}`*g0$zB~|%r zRP=-AWDzu5bqAy0F(SQ|C$xS$4y#Z^$zAvzJ80hB`sgj@SQ0TZ{+FU8BS+2G>& z&wXGQh(<CraXK%*Q_$u3-Aqp?VGU~L1}zUiXIw>!qIODvxk>$XhxnTYTaZ~K3AD%C z?$-s=F%W@N7{z#PGK#`zchsyb9mG0pE|RQsdSt>rX)A_{!?~Ut&~|WHi2TG-8RRv& zsOlkQiaQw=#hv@Zz8~kIs=V^Bl}*^PhF3?+@{u}5=9qgq=*6Amrg~CYrbNf<JI-0n zw}fkm@v7rO3|{^eZF%n1Q4Q*V#s08p^&<DI$7JLv&!Q~DC*)|9%6C_Wmt7`|wXPXm zCEKCBRj#uwPwS%VjW%ewxH2-U4|f@iWJ;+idFR^h=DZ)>_g%0WFtQkh=%#VtM9Tr4 z;!pZ}5vH_-m2r*9t%}$ex2|EvxAP?srXe&mJoh_OwvY~v<5dq=YC3J)yFGvq1F4RK z{HdtFkP;_%1F5jv%W|faewv@C5DhQ)$MUWX5)*k3cYfDcZNBKHGlh;10=RWlbUS4} zqGF>{I~v_-x)SeA?2FG+xug^?Cq+SAe)olpKV$Hut?-d!1iT>#dD#F;O|bU4rAMtX zVEUa^`sKEhqU7Zl{QfTz7wBep&dOa49A&e1Z3;S{tJFMsMBQ~J2UNCB=%~yuu|kI? z+Wh`JlOrlLAT{qQ5Nxz?GLl+9CWXiKhJ@Vy@_4Pz93Lyeh_jt71R%BzhG}kX4(^AE zwk44^KP4R+G%P6|vJv*eOtrVwzLpMv>CSTy?&{eK>Q{@j8R$UTGhfaQj4%zz+0Rb? zu!nv`0de!u9Vx1h-%PJ$ABN=EBR^}bMC+sOPQkLDPpbEFo*t#|M`eGt5GGMzRhEyO z40zJg(XrTCt$$tb_%J6Sx}{2<d!2ZHb8x4~G#gJYe)jkf*|3V>>k&9~u?#CJx)P%S z7RLzP-w=YR?+C|YVm`%G)5FjcSZKb*s53Dq{KCdg>UH~XN&<xBySn=3Q3zj|6WNU^ zeJN3mNqL>w$Zk*AevcP+hhT}XeRDGE{&I4mntXgN$WtX5B!s;w5g<2(fOK*JKbQvR zzxGZ<1o+{sYd_Wtn0|(y)0N18@`xfzIYo|P@rcL&nUnurhxg2eU|-?o!OV1Dmo(#K z18P<rrk>&5Nk~#niY;%k)1}T`pVT({o;d6y#Yr|7K}n1|35@b+jR1=wko%*Vhj%aP zIc%GOdQ?>)Ln~@Lns^BTg3wMxKmBJ*Z~R#}oI4_z+z)pn$%5RW$1&lU`^gB~Gb@*z zfZKvcugM~iC|o>#hv!ux_9E6wLId5+lh7p5=cMwpV!7DWL3<(!XDtqsfBhMp3_)CF zz35n0$vFp}>f3x80+O+sbTpt&#DcI8$pz;}n{2XwmF$tt+QkXs0or0Gs<gJ!KHC^+ z{E2vqPMQSfeF4%x`?3I3l6qtDrVH!9BIPU!DJp~XmIUImo~KJS`NbY0{LpZOJ7sW- z7UZld_F58Xhyop;fFr`O4MlMOkEkd4MYPFKHQx&R-cN9-P@%VS+o%Uv`yvO>0@T3K z6&%0uy8AO)?*r|dr4uO$QvK#Sea#9uPJFYRle|%|@>^ZLR0F6K!+Qhy4EVo-1QWip z((1jg|I(HM%56)dG<p+kzr<Q_grM%yz)^sD-@zr468(%o5O_;6w!={4lK_ctna6pn zYn{Cu1oYMf<&0?*)botD{bv8;_&>w*|MjG}6SMoxoqzm6#`|saCqQ0WS*lvXG~|B) D)n!^F diff --git a/docs/reference-guides/slotfills/plugin-sidebar.md b/docs/reference-guides/slotfills/plugin-sidebar.md index 8fe274414905b7..dbf1c5643d3aab 100644 --- a/docs/reference-guides/slotfills/plugin-sidebar.md +++ b/docs/reference-guides/slotfills/plugin-sidebar.md @@ -1,30 +1,68 @@ # PluginSidebar -This slot allows for adding items into the Gutenberg Toolbar. -Using this slot will add an icon to the bar that, when clicked, will open a sidebar with the content of the items wrapped in the `<PluginSidebar />` component. +This slot allows adding items to the tool bar of either the Post or Site editor screens. +Using this slot will add an icon to the toolbar that, when clicked, opens a panel with containing the items wrapped in the `<PluginSidebar />` component. ## Example -```js -import { registerPlugin } from '@wordpress/plugins'; +```jsx +import { __ } from '@wordpress/i18n'; import { PluginSidebar } from '@wordpress/editor'; -import { image } from '@wordpress/icons'; +import { + PanelBody, + Button, + TextControl, + SelectControl, +} from '@wordpress/components'; +import { registerPlugin } from '@wordpress/plugins'; +import { useState } from '@wordpress/element'; + +const PluginSidebarExample = () => { + const [ text, setText ] = useState( '' ); + const [ select, setSelect ] = useState( 'a' ); -const PluginSidebarTest = () => ( - <PluginSidebar name="plugin-sidebar-test" title="My Plugin" icon={ image }> - <p>Plugin Sidebar</p> - </PluginSidebar> -); + return ( + <PluginSidebar + name="plugin-sidebar-example" + title={ __( 'My PluginSidebar' ) } + icon={ 'smiley' } + > + <PanelBody> + <h2> + { __( 'This is a heading for the PluginSidebar example.' ) } + </h2> + <p> + { __( + 'This is some example text for the PluginSidebar example.' + ) } + </p> + <TextControl + label={ __( 'Text Control' ) } + value={ text } + onChange={ ( newText ) => setText( newText ) } + /> + <SelectControl + label={ __( 'Select Control' ) } + value={ select } + options={ [ + { value: 'a', label: 'Option A' }, + { value: 'b', label: 'Option B' }, + { value: 'c', label: 'Option C' }, + ] } + onChange={ ( newSelect ) => setSelect( newSelect ) } + /> + <Button variant="primary">{ __( 'Primary Button' ) } </Button> + </PanelBody> + </PluginSidebar> + ); +}; -registerPlugin( 'plugin-sidebar-test', { render: PluginSidebarTest } ); +// Register the plugin. +registerPlugin( 'plugin-sidebar-example', { render: PluginSidebarExample } ); ``` ## Location -### Closed State - -![Closed State](https://raw.githubusercontent.com/WordPress/gutenberg/HEAD/docs/assets/plugin-sidebar-closed-state.png?raw=true) - ### Open State ![Open State](https://raw.githubusercontent.com/WordPress/gutenberg/HEAD/docs/assets/plugin-sidebar-open-state.png?raw=true) From 823f474969461bb685970c569efaf83ebac78e66 Mon Sep 17 00:00:00 2001 From: Rich Tabor <hi@richtabor.com> Date: Fri, 2 Aug 2024 16:15:41 -0400 Subject: [PATCH 0239/1908] Improve zoom transition (#64179) * add transition to transitioning properties * remove border and radius from tablet/mobile * zoom out a little more * scope properties * update mobile/tablet transition * move mobile/tablet up a little * use all transition * Move editor canvas and iframe sizing transitions to shared mixin --------- Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: dereksmart <dsmart@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/base-styles/_animations.scss | 5 +++++ packages/block-editor/src/components/block-canvas/style.scss | 1 + packages/block-editor/src/components/iframe/content.scss | 4 ++-- packages/block-editor/src/components/iframe/index.js | 4 +--- .../block-editor/src/components/use-resize-canvas/index.js | 4 +--- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/base-styles/_animations.scss b/packages/base-styles/_animations.scss index b5e6655e660cbb..bdfd7595da8e44 100644 --- a/packages/base-styles/_animations.scss +++ b/packages/base-styles/_animations.scss @@ -3,3 +3,8 @@ animation-fill-mode: forwards; @include reduce-motion("animation"); } + +@mixin editor-canvas-resize-animation() { + transition: all 0.5s cubic-bezier(0.65, 0, 0.45, 1); + @include reduce-motion("transition"); +} diff --git a/packages/block-editor/src/components/block-canvas/style.scss b/packages/block-editor/src/components/block-canvas/style.scss index 9e924cb79bace1..1395b5c0a437d3 100644 --- a/packages/block-editor/src/components/block-canvas/style.scss +++ b/packages/block-editor/src/components/block-canvas/style.scss @@ -4,4 +4,5 @@ iframe[name="editor-canvas"] { height: 100%; display: block; background-color: transparent; + @include editor-canvas-resize-animation; } diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss index 8c03d4224745af..90b887993bf6db 100644 --- a/packages/block-editor/src/components/iframe/content.scss +++ b/packages/block-editor/src/components/iframe/content.scss @@ -22,9 +22,9 @@ } .block-editor-iframe__html { + border: 0 solid $gray-300; transform-origin: top center; - transition: transform 0.3s; - @include reduce-motion("transition"); + @include editor-canvas-resize-animation; } .block-editor-iframe__html.is-zoomed-out { diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index 669e2fe25a9fbb..3b0bce6d56b403 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -305,7 +305,7 @@ function Iframe( { iframeDocument.documentElement.classList.add( 'is-zoomed-out' ); - const maxWidth = 800; + const maxWidth = 750; iframeDocument.documentElement.style.setProperty( '--wp-block-editor-iframe-zoom-out-scale', scale === 'default' @@ -378,10 +378,8 @@ function Iframe( { <iframe { ...props } style={ { - border: 0, ...props.style, height: props.style?.height, - transition: 'all .3s', } } ref={ useMergeRefs( [ ref, setRef ] ) } tabIndex={ tabIndex } diff --git a/packages/block-editor/src/components/use-resize-canvas/index.js b/packages/block-editor/src/components/use-resize-canvas/index.js index a843f160056367..7243b0f1b0b82f 100644 --- a/packages/block-editor/src/components/use-resize-canvas/index.js +++ b/packages/block-editor/src/components/use-resize-canvas/index.js @@ -43,7 +43,7 @@ export default function useResizeCanvas( deviceType ) { return deviceWidth < actualWidth ? deviceWidth : actualWidth; }; - const marginValue = () => ( window.innerHeight < 800 ? 36 : 72 ); + const marginValue = () => ( window.innerHeight < 800 ? 36 : 64 ); const contentInlineStyles = ( device ) => { const height = device === 'Mobile' ? '768px' : '1024px'; @@ -62,8 +62,6 @@ export default function useResizeCanvas( deviceType ) { marginLeft: marginHorizontal, marginRight: marginHorizontal, height, - borderRadius: '2px 2px 2px 2px', - border: '1px solid #ddd', overflowY: 'auto', }; default: From 7324cd42fcd36a64f0dae0f9df3ded80f4b4e9d0 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Sat, 3 Aug 2024 07:29:19 +0530 Subject: [PATCH 0240/1908] Several Typo Correction in Inline Doc (#64147) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/block-editor/README.md | 2 +- packages/block-editor/src/utils/get-editor-region.js | 2 +- packages/block-editor/src/utils/get-px-from-css-unit.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index fec4f4c0dbe5c3..776b217ba54f6e 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -547,7 +547,7 @@ _Returns_ > **Deprecated** -This function was accidentially exposed for mobile/native usage. +This function was accidentally exposed for mobile/native usage. _Returns_ diff --git a/packages/block-editor/src/utils/get-editor-region.js b/packages/block-editor/src/utils/get-editor-region.js index 7edc57d1157fb4..16561b26b88aea 100644 --- a/packages/block-editor/src/utils/get-editor-region.js +++ b/packages/block-editor/src/utils/get-editor-region.js @@ -23,7 +23,7 @@ export default function getEditorRegion( editor ) { return iframeDocument === editor.ownerDocument; } ) ?? editor; - // The region is provivided by the editor, not the block-editor. + // The region is provided by the editor, not the block-editor. // We should send focus to the region if one is available to reuse the // same interface for navigating landmarks. If no region is available, // use the canvas instead. diff --git a/packages/block-editor/src/utils/get-px-from-css-unit.js b/packages/block-editor/src/utils/get-px-from-css-unit.js index f1ee9fbcafb13b..57e5e9827def85 100644 --- a/packages/block-editor/src/utils/get-px-from-css-unit.js +++ b/packages/block-editor/src/utils/get-px-from-css-unit.js @@ -1,5 +1,5 @@ /** - * This function was accidentially exposed for mobile/native usage. + * This function was accidentally exposed for mobile/native usage. * * @deprecated * From 5cb1e2ee3a86b6543a66330a6b09d4bbbee74563 Mon Sep 17 00:00:00 2001 From: Utsav Patel <75293077+up1512001@users.noreply.github.com> Date: Sat, 3 Aug 2024 09:20:51 +0530 Subject: [PATCH 0241/1908] Fix: a11y text for site editor (#62648) Co-authored-by: up1512001 <up1512001@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/edit-site/src/components/site-hub/index.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/site-hub/index.js b/packages/edit-site/src/components/site-hub/index.js index 301f7165d59354..fe6ea4440a4e80 100644 --- a/packages/edit-site/src/components/site-hub/index.js +++ b/packages/edit-site/src/components/site-hub/index.js @@ -7,7 +7,11 @@ import clsx from 'clsx'; * WordPress dependencies */ import { useSelect, useDispatch } from '@wordpress/data'; -import { Button, __experimentalHStack as HStack } from '@wordpress/components'; +import { + Button, + __experimentalHStack as HStack, + VisuallyHidden, +} from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { store as coreStore } from '@wordpress/core-data'; import { decodeEntities } from '@wordpress/html-entities'; @@ -80,9 +84,14 @@ const SiteHub = memo( variant="link" href={ homeUrl } target="_blank" - label={ __( 'View site (opens in a new tab)' ) } > { decodeEntities( siteTitle ) } + <VisuallyHidden as="span"> + { + /* translators: accessibility text */ + __( '(opens in a new tab)' ) + } + </VisuallyHidden> </Button> </div> <HStack From 79b075293de8a763a5ea892406e53d92bfd2c63a Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Sat, 3 Aug 2024 11:06:33 +0400 Subject: [PATCH 0242/1908] Primitives: Add missing peer dependency (#64218) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: anomiex <bjorsch@git.wordpress.org> --- package-lock.json | 3 +++ packages/primitives/package.json | 3 +++ 2 files changed, 6 insertions(+) diff --git a/package-lock.json b/package-lock.json index 283127c1861b3f..23f504d7cbf460 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54192,6 +54192,9 @@ "engines": { "node": ">=18.12.0", "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" } }, "packages/priority-queue": { diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 8536fa2fef3496..31bf36813d6b0e 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -35,6 +35,9 @@ "@wordpress/element": "file:../element", "clsx": "^2.1.1" }, + "peerDependencies": { + "react": "^18.0.0" + }, "publishConfig": { "access": "public" } From 06056360c942a50ed51ac8df139de920f37dc970 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Mon, 5 Aug 2024 13:02:31 +0800 Subject: [PATCH 0243/1908] Grid perf: Avoid iterating auto grid inner blocks unless mode specifically changed (#64194) * Avoid iterating auto grid inner blocks unless mode specifically changed * Un-yoda sentence ---- Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> --- .../components/grid/use-grid-layout-sync.js | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/packages/block-editor/src/components/grid/use-grid-layout-sync.js b/packages/block-editor/src/components/grid/use-grid-layout-sync.js index ed368714d63d34..2cc17eed6b33bf 100644 --- a/packages/block-editor/src/components/grid/use-grid-layout-sync.js +++ b/packages/block-editor/src/components/grid/use-grid-layout-sync.js @@ -37,6 +37,9 @@ export function useGridLayoutSync( { clientId: gridClientId } ) { ); const previouslySelectedBlockRect = usePrevious( selectedBlockRect ); + const previousIsManualPlacement = usePrevious( + gridLayout.isManualPlacement + ); useEffect( () => { const updates = {}; @@ -121,19 +124,22 @@ export function useGridLayoutSync( { clientId: gridClientId } ) { }; } } else { - // When in auto mode, remove all of the columnStart and rowStart values. - for ( const clientId of blockOrder ) { - const attributes = getBlockAttributes( clientId ); - const { columnStart, rowStart, ...layout } = - attributes.style?.layout ?? {}; - // Only update attributes if columnStart or rowStart are set. - if ( columnStart || rowStart ) { - updates[ clientId ] = { - style: { - ...attributes.style, - layout, - }, - }; + // Remove all of the columnStart and rowStart values + // when switching from manual to auto mode, + if ( previousIsManualPlacement === true ) { + for ( const clientId of blockOrder ) { + const attributes = getBlockAttributes( clientId ); + const { columnStart, rowStart, ...layout } = + attributes.style?.layout ?? {}; + // Only update attributes if columnStart or rowStart are set. + if ( columnStart || rowStart ) { + updates[ clientId ] = { + style: { + ...attributes.style, + layout, + }, + }; + } } } @@ -162,6 +168,7 @@ export function useGridLayoutSync( { clientId: gridClientId } ) { gridLayout, blockOrder, previouslySelectedBlockRect, + previousIsManualPlacement, // These won't change, but the linter thinks they might: __unstableMarkNextChangeAsNotPersistent, getBlockAttributes, From 8b1b939f9d79329e64fa9268f2fa6df81dcd133c Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Mon, 5 Aug 2024 09:38:26 +0200 Subject: [PATCH 0244/1908] Send icon: Update to be clearer. (#64183) --- packages/icons/src/library/send.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/icons/src/library/send.js b/packages/icons/src/library/send.js index 9cd3d6ae5e4057..3770d9a94bc7b7 100644 --- a/packages/icons/src/library/send.js +++ b/packages/icons/src/library/send.js @@ -8,7 +8,7 @@ const send = ( <Path fillRule="evenodd" clipRule="evenodd" - d="M5.333 12.154c-1.03-.424-1.032-1.883-.002-2.31l12.261-5.085c1.03-.426 2.06.605 1.634 1.634l-5.084 12.262c-.427 1.03-1.886 1.027-2.31-.003l-1.896-4.603-4.603-1.895Zm6.061 1.498 1.594 3.87 3.87-9.334-5.464 5.463Zm4.403-6.524-9.333 3.87 3.87 1.593 5.463-5.463Z" + d="M6.332 5.748c-1.03-.426-2.06.607-1.632 1.636l1.702 3.93 7.481.575c.123.01.123.19 0 .2l-7.483.575-1.7 3.909c-.429 1.029.602 2.062 1.632 1.636l12.265-5.076c1.03-.426 1.03-1.884 0-2.31L6.332 5.748Z" /> </SVG> ); From 86c3225039d71770c9492bb3a6f047972afbe094 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 5 Aug 2024 13:40:38 +0400 Subject: [PATCH 0245/1908] Fix flaky DataViews list layout e2e tests (#64244) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- .../site-editor/dataviews-list-layout-keyboard.spec.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/e2e/specs/site-editor/dataviews-list-layout-keyboard.spec.js b/test/e2e/specs/site-editor/dataviews-list-layout-keyboard.spec.js index f6b01db63d9118..16cc34ace8a82b 100644 --- a/test/e2e/specs/site-editor/dataviews-list-layout-keyboard.spec.js +++ b/test/e2e/specs/site-editor/dataviews-list-layout-keyboard.spec.js @@ -76,10 +76,15 @@ test.describe( 'Dataviews List Layout', () => { await page.keyboard.press( 'Tab' ); await page.keyboard.press( 'Tab' ); + const firstItem = page + .getByRole( 'grid' ) + .getByRole( 'button' ) + .first(); + // Make sure the items have loaded before reaching for the 1st item in the list. await expect( page.getByRole( 'grid' ) ).toBeVisible(); await page.keyboard.press( 'Tab' ); - await expect( page.getByLabel( 'Privacy Policy' ) ).toBeFocused(); + await expect( firstItem ).toBeFocused(); // Go to the preview. await page.keyboard.press( 'Tab' ); @@ -91,7 +96,7 @@ test.describe( 'Dataviews List Layout', () => { // Go back to the items list using SHIFT+TAB. await page.keyboard.press( 'Shift+Tab' ); - await expect( page.getByLabel( 'Privacy Policy' ) ).toBeFocused(); + await expect( firstItem ).toBeFocused(); } ); test( 'Navigates the items list via UP/DOWN arrow keys', async ( { From ac9a41867f0fd7d882547b7d5e32e47355acc693 Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Mon, 5 Aug 2024 10:50:38 +0100 Subject: [PATCH 0246/1908] Zoom Out: Add a control to enter and leave zoom out mode (#63870) * Zoom Out: Add a control to enter and leave zoom out mode revert changes Use 100% for desktop and 50% for zoom out update menu items Allow users to set zoom out back to 100% when the patterns tab is open Reset zoom when switching device mode Add text for zoom refactor click handler to a shared function Move in and out of zoom out when resizing below tablet viewport size * save the editing mode in a ref so we can restore it * update logic * Update packages/editor/src/components/preview-dropdown/index.js Co-authored-by: Alex Lende <alex+github.com@lende.xyz> * fix preview selection * remove the experiment * remove disconnected change * make the code more readable * simplify code * remove changes from the rebase * Render a down chevron in the dropdown * don't run the use effect when the mode changes * Remove incorrect comment * Customized spacing for chevron in preview dropdown * minor tweaks * Simplify logic for preview selection and keep in line with editorMode * Allow zoom out inserters if manually select zoom out mode from dropdown * Use desktop icon with 50% for zoom out --------- Co-authored-by: Alex Lende <alex+github.com@lende.xyz> Co-authored-by: Jerry Jones <jones.jeremydavid@gmail.com> Co-authored-by: Rich Tabor <hi@richtabor.com> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: paaljoachim <paaljoachim@git.wordpress.org> --- .../src/components/block-tools/index.js | 11 +- .../src/components/iframe/index.js | 6 +- .../block-editor/src/hooks/use-zoom-out.js | 2 +- .../editor/src/components/header/index.js | 3 +- .../src/components/preview-dropdown/index.js | 108 +++++++++++++----- .../components/preview-dropdown/style.scss | 5 + .../src/components/visual-editor/index.js | 14 ++- 7 files changed, 101 insertions(+), 48 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index c07adb34e584f3..163c35b54e4381 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -251,12 +251,11 @@ export default function BlockTools( { name="__unstable-block-tools-after" ref={ blockToolbarAfterRef } /> - { window.__experimentalEnableZoomedOutPatternsTab && - isZoomOutMode && ( - <ZoomOutModeInserters - __unstableContentRef={ __unstableContentRef } - /> - ) } + { isZoomOutMode && ( + <ZoomOutModeInserters + __unstableContentRef={ __unstableContentRef } + /> + ) } </InsertionPointOpenRef.Provider> </div> ); diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index 3b0bce6d56b403..e7af77920ea127 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -242,10 +242,8 @@ function Iframe( { const isZoomedOut = scale !== 1; useEffect( () => { - if ( ! isZoomedOut ) { - prevContainerWidth.current = containerWidth; - } - }, [ containerWidth, isZoomedOut ] ); + prevContainerWidth.current = containerWidth; + }, [ containerWidth ] ); const disabledRef = useDisabled( { isDisabled: ! readonly } ); const bodyRef = useMergeRefs( [ diff --git a/packages/block-editor/src/hooks/use-zoom-out.js b/packages/block-editor/src/hooks/use-zoom-out.js index 3ec701cfc4a14d..d0d7d0fd4d71c7 100644 --- a/packages/block-editor/src/hooks/use-zoom-out.js +++ b/packages/block-editor/src/hooks/use-zoom-out.js @@ -49,5 +49,5 @@ export function useZoomOut( zoomOut = true ) { ) { __unstableSetEditorMode( originalEditingMode.current ); } - }, [ __unstableSetEditorMode, zoomOut, mode ] ); + }, [ __unstableGetEditorMode, __unstableSetEditorMode, zoomOut ] ); // Mode is deliberately excluded from the dependencies so that the effect does not run when mode changes. } diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index 2a604229596005..b8eda30c721860 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -57,7 +57,6 @@ function Header( { showIconLabels, hasFixedToolbar, isNestedEntity, - isZoomedOutView, } = useSelect( ( select ) => { const { get: getPreference } = select( preferencesStore ); const { @@ -136,7 +135,7 @@ function Header( { ) } <PreviewDropdown forceIsAutosaveable={ forceIsDirty } - disabled={ isNestedEntity || isZoomedOutView } + disabled={ isNestedEntity } /> <PostPreviewButton className="editor-header__post-preview-button" diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js index b157c8cc1cfc3b..6554f7c0228a77 100644 --- a/packages/editor/src/components/preview-dropdown/index.js +++ b/packages/editor/src/components/preview-dropdown/index.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + /** * WordPress dependencies */ @@ -14,7 +19,9 @@ import { __ } from '@wordpress/i18n'; import { desktop, mobile, tablet, external } from '@wordpress/icons'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; +import { useEffect, useRef } from '@wordpress/element'; import { store as preferencesStore } from '@wordpress/preferences'; +import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Internal dependencies @@ -23,21 +30,50 @@ import { store as editorStore } from '../../store'; import PostPreviewButton from '../post-preview-button'; export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { - const { deviceType, homeUrl, isTemplate, isViewable, showIconLabels } = - useSelect( ( select ) => { - const { getDeviceType, getCurrentPostType } = select( editorStore ); - const { getUnstableBase, getPostType } = select( coreStore ); - const { get } = select( preferencesStore ); - const _currentPostType = getCurrentPostType(); - return { - deviceType: getDeviceType(), - homeUrl: getUnstableBase()?.home, - isTemplate: _currentPostType === 'wp_template', - isViewable: getPostType( _currentPostType )?.viewable ?? false, - showIconLabels: get( 'core', 'showIconLabels' ), - }; - }, [] ); + const { + deviceType, + editorMode, + homeUrl, + isTemplate, + isViewable, + showIconLabels, + } = useSelect( ( select ) => { + const { getDeviceType, getCurrentPostType } = select( editorStore ); + const { getUnstableBase, getPostType } = select( coreStore ); + const { get } = select( preferencesStore ); + const { __unstableGetEditorMode } = select( blockEditorStore ); + const _currentPostType = getCurrentPostType(); + return { + deviceType: getDeviceType(), + editorMode: __unstableGetEditorMode(), + homeUrl: getUnstableBase()?.home, + isTemplate: _currentPostType === 'wp_template', + isViewable: getPostType( _currentPostType )?.viewable ?? false, + showIconLabels: get( 'core', 'showIconLabels' ), + }; + }, [] ); const { setDeviceType } = useDispatch( editorStore ); + const { __unstableSetEditorMode } = useDispatch( blockEditorStore ); + + /** + * Save the original editing mode in a ref to restore it when we exit zoom out. + */ + const originalEditingMode = useRef( editorMode ); + useEffect( () => { + if ( editorMode !== 'zoom-out' ) { + originalEditingMode.current = editorMode; + } + + return () => { + if ( + editorMode === 'zoom-out' && + editorMode !== originalEditingMode.current + ) { + __unstableSetEditorMode( originalEditingMode.current ); + } + }; + }, [ editorMode, __unstableSetEditorMode ] ); + const isMobile = useViewportMatch( 'medium', '<' ); if ( isMobile ) { return null; @@ -48,6 +84,7 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { }; const toggleProps = { className: 'editor-preview-dropdown__toggle', + iconPosition: 'right', size: 'compact', showTooltip: ! showIconLabels, disabled, @@ -58,9 +95,9 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { }; const deviceIcons = { + desktop, mobile, tablet, - desktop, }; /** @@ -74,6 +111,11 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { label: __( 'Desktop' ), icon: desktop, }, + { + value: 'ZoomOut', + label: __( 'Desktop (50%)' ), + icon: desktop, + }, { value: 'Tablet', label: __( 'Tablet' ), @@ -86,29 +128,37 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { }, ]; + const previewValue = editorMode === 'zoom-out' ? 'ZoomOut' : deviceType; + /** - * The selected choice. + * Handles the selection of a device type. * - * @type {Object} + * @param {string} value The device type. */ - let selectedChoice = choices.find( - ( choice ) => choice.value === deviceType - ); + const onSelect = ( value ) => { + let newEditorMode = originalEditingMode.current; - /** - * If no selected choice is found, default to the first - */ - if ( ! selectedChoice ) { - selectedChoice = choices[ 0 ]; - } + if ( value === 'ZoomOut' ) { + newEditorMode = 'zoom-out'; + setDeviceType( 'Desktop' ); + } else { + setDeviceType( value ); + } + + __unstableSetEditorMode( newEditorMode ); + }; return ( <DropdownMenu - className="editor-preview-dropdown" + className={ clsx( + 'editor-preview-dropdown', + `editor-preview-dropdown--${ deviceType.toLowerCase() }` + ) } popoverProps={ popoverProps } toggleProps={ toggleProps } menuProps={ menuProps } icon={ deviceIcons[ deviceType.toLowerCase() ] } + text={ editorMode === 'zoom-out' ? __( '50%' ) : undefined } label={ __( 'View' ) } disableOpenOnArrowDown={ disabled } > @@ -117,8 +167,8 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { <MenuGroup> <MenuItemsChoice choices={ choices } - value={ selectedChoice.value } - onSelect={ setDeviceType } + value={ previewValue } + onSelect={ onSelect } /> </MenuGroup> { isTemplate && ( diff --git a/packages/editor/src/components/preview-dropdown/style.scss b/packages/editor/src/components/preview-dropdown/style.scss index 43fa7cdd8ecd97..c117a4239e9dfb 100644 --- a/packages/editor/src/components/preview-dropdown/style.scss +++ b/packages/editor/src/components/preview-dropdown/style.scss @@ -1,3 +1,8 @@ +.editor-preview-dropdown .editor-preview-dropdown__toggle.has-icon.has-text { + padding-right: 4px; + padding-left: 6px; +} + .editor-preview-dropdown__button-external { width: 100%; display: flex; diff --git a/packages/editor/src/components/visual-editor/index.js b/packages/editor/src/components/visual-editor/index.js index 8b4877704f5f18..a67feb530e96a2 100644 --- a/packages/editor/src/components/visual-editor/index.js +++ b/packages/editor/src/components/visual-editor/index.js @@ -107,6 +107,7 @@ function VisualEditor( { } ) { const [ resizeObserver, sizes ] = useResizeObserver(); const isMobileViewport = useViewportMatch( 'small', '<' ); + const isTabletViewport = useViewportMatch( 'medium', '<' ); const { renderingMode, postContentAttributes, @@ -341,12 +342,13 @@ function VisualEditor( { } ), ] ); - const zoomOutProps = isZoomOutMode - ? { - scale: 'default', - frameSize: '48px', - } - : {}; + const zoomOutProps = + isZoomOutMode && ! isTabletViewport + ? { + scale: 'default', + frameSize: '48px', + } + : {}; const forceFullHeight = postType === NAVIGATION_POST_TYPE; const enableResizing = From 645ae89fb622c4a32aedf79391df1ccd66395dcd Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Mon, 5 Aug 2024 11:54:18 +0200 Subject: [PATCH 0247/1908] Update: De-emphasise bulk actions on Grid layout. (#64209) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/base-styles/_z-index.scss | 3 +++ packages/dataviews/src/layouts/grid/index.tsx | 16 +++++++-------- .../dataviews/src/layouts/grid/style.scss | 20 +++++++++++++++++++ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index b8a9088cfd72cc..4d5f22e02fa7d1 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -208,6 +208,9 @@ $z-layers: ( // Ensure checkbox + actions don't overlap table header ".dataviews-view-table thead": 1, + // Ensure selection checkbox stays above the preview field. + ".dataviews-view-grid__card .dataviews-selection-checkbox": 1, + // Ensure quick actions toolbar appear above pagination ".dataviews-bulk-actions-toolbar": 2, ); diff --git a/packages/dataviews/src/layouts/grid/index.tsx b/packages/dataviews/src/layouts/grid/index.tsx index cbfccf5521a812..c8cac31bf7db81 100644 --- a/packages/dataviews/src/layouts/grid/index.tsx +++ b/packages/dataviews/src/layouts/grid/index.tsx @@ -84,18 +84,18 @@ function GridItem< Item >( { <div className="dataviews-view-grid__media"> { renderedMediaField } </div> + <SingleSelectionCheckbox + item={ item } + selection={ selection } + onChangeSelection={ onChangeSelection } + getItemId={ getItemId } + primaryField={ primaryField } + disabled={ ! hasBulkAction } + /> <HStack justify="space-between" className="dataviews-view-grid__title-actions" > - <SingleSelectionCheckbox - item={ item } - selection={ selection } - onChangeSelection={ onChangeSelection } - getItemId={ getItemId } - primaryField={ primaryField } - disabled={ ! hasBulkAction } - /> <HStack className="dataviews-view-grid__primary-field"> { renderedPrimaryField } </HStack> diff --git a/packages/dataviews/src/layouts/grid/style.scss b/packages/dataviews/src/layouts/grid/style.scss index a707401972cdab..ebe039ea7543b0 100644 --- a/packages/dataviews/src/layouts/grid/style.scss +++ b/packages/dataviews/src/layouts/grid/style.scss @@ -9,6 +9,7 @@ .dataviews-view-grid__card { height: 100%; justify-content: flex-start; + position: relative; .dataviews-view-grid__title-actions { padding: $grid-unit-10 0 $grid-unit-05; @@ -22,6 +23,11 @@ .dataviews-view-grid__fields .dataviews-view-grid__field .dataviews-view-grid__field-value { color: $gray-900; } + + .dataviews-view-grid__media::after { + background-color: rgba(var(--wp-admin-theme-color--rgb), 0.08); + box-shadow: inset 0 0 0 $border-width var(--wp-admin-theme-color); + } } } @@ -32,6 +38,7 @@ background-color: $gray-100; border-radius: $grid-unit-05; position: relative; + overflow: hidden; img { object-fit: cover; @@ -148,3 +155,16 @@ .dataviews-view-grid__field:empty { display: none; } + +.dataviews-view-grid__card .dataviews-selection-checkbox { + position: absolute; + top: -9999em; + left: $grid-unit-10; + z-index: z-index(".dataviews-view-grid__card .dataviews-selection-checkbox"); +} + +.dataviews-view-grid__card:hover .dataviews-selection-checkbox, +.dataviews-view-grid__card:focus-within .dataviews-selection-checkbox, +.dataviews-view-grid__card.is-selected .dataviews-selection-checkbox { + top: $grid-unit-10; +} From 4be49120a16cd79066d6528f25f7d10c046026c1 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Mon, 5 Aug 2024 12:33:29 +0200 Subject: [PATCH 0248/1908] Move filter UI into a toggle-able panel to improve experience on narrow viewports/containers (#63203) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: SaxonF <saxonafletcher@git.wordpress.org> --- .../dataviews-filters/add-filter.tsx | 58 +++-- .../components/dataviews-filters/index.tsx | 210 +++++++++++++----- .../components/dataviews-filters/style.scss | 30 +++ .../src/components/dataviews-search/index.tsx | 13 +- .../src/components/dataviews/index.tsx | 26 ++- .../src/components/dataviews/style.scss | 7 +- .../src/components/page-patterns/index.js | 1 + .../src/components/page-templates/index.js | 1 + .../src/components/post-list/index.js | 8 +- .../dataviews-list-layout-keyboard.spec.js | 9 - .../site-editor/new-templates-list.spec.js | 2 +- test/e2e/specs/site-editor/patterns.spec.js | 8 + 12 files changed, 266 insertions(+), 107 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-filters/add-filter.tsx b/packages/dataviews/src/components/dataviews-filters/add-filter.tsx index 38dda38c96e70f..ca1043d6e99fdb 100644 --- a/packages/dataviews/src/components/dataviews-filters/add-filter.tsx +++ b/packages/dataviews/src/components/dataviews-filters/add-filter.tsx @@ -32,29 +32,18 @@ interface AddFilterProps { setOpenedFilter: ( filter: string | null ) => void; } -function AddFilter( - { filters, view, onChangeView, setOpenedFilter }: AddFilterProps, - ref: Ref< HTMLButtonElement > -) { - if ( ! filters.length || filters.every( ( { isPrimary } ) => isPrimary ) ) { - return null; - } +export function AddFilterDropdownMenu( { + filters, + view, + onChangeView, + setOpenedFilter, + trigger, +}: AddFilterProps & { + trigger: React.ReactNode; +} ) { const inactiveFilters = filters.filter( ( filter ) => ! filter.isVisible ); return ( - <DropdownMenu - trigger={ - <Button - accessibleWhenDisabled - size="compact" - className="dataviews-filters__button" - variant="tertiary" - disabled={ ! inactiveFilters.length } - ref={ ref } - > - { __( 'Add filter' ) } - </Button> - } - > + <DropdownMenu trigger={ trigger }> { inactiveFilters.map( ( filter ) => { return ( <DropdownMenuItem @@ -85,4 +74,31 @@ function AddFilter( ); } +function AddFilter( + { filters, view, onChangeView, setOpenedFilter }: AddFilterProps, + ref: Ref< HTMLButtonElement > +) { + if ( ! filters.length || filters.every( ( { isPrimary } ) => isPrimary ) ) { + return null; + } + const inactiveFilters = filters.filter( ( filter ) => ! filter.isVisible ); + return ( + <AddFilterDropdownMenu + trigger={ + <Button + accessibleWhenDisabled + size="compact" + className="dataviews-filters-button" + variant="tertiary" + disabled={ ! inactiveFilters.length } + ref={ ref } + > + { __( 'Add filter' ) } + </Button> + } + { ...{ filters, view, onChangeView, setOpenedFilter } } + /> + ); +} + export default forwardRef( AddFilter ); diff --git a/packages/dataviews/src/components/dataviews-filters/index.tsx b/packages/dataviews/src/components/dataviews-filters/index.tsx index 449e0ff0323a8b..de3477914c0083 100644 --- a/packages/dataviews/src/components/dataviews-filters/index.tsx +++ b/packages/dataviews/src/components/dataviews-filters/index.tsx @@ -1,65 +1,150 @@ /** * WordPress dependencies */ -import { memo, useContext, useRef } from '@wordpress/element'; -import { __experimentalHStack as HStack } from '@wordpress/components'; +import { + memo, + useContext, + useRef, + useMemo, + useCallback, +} from '@wordpress/element'; +import { __experimentalHStack as HStack, Button } from '@wordpress/components'; +import { funnel } from '@wordpress/icons'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ import FilterSummary from './filter-summary'; -import AddFilter from './add-filter'; +import { default as AddFilter, AddFilterDropdownMenu } from './add-filter'; import ResetFilters from './reset-filters'; import DataViewsContext from '../dataviews-context'; import { sanitizeOperators } from '../../utils'; import { ALL_OPERATORS, OPERATOR_IS, OPERATOR_IS_NOT } from '../../constants'; -import type { NormalizedFilter } from '../../types'; +import type { NormalizedFilter, NormalizedField, View } from '../../types'; -function Filters() { - const { fields, view, onChangeView, openedFilter, setOpenedFilter } = - useContext( DataViewsContext ); - const addFilterRef = useRef< HTMLButtonElement >( null ); - const filters: NormalizedFilter[] = []; - fields.forEach( ( field ) => { - if ( ! field.elements?.length ) { - return; - } +export function useFilters( fields: NormalizedField< any >[], view: View ) { + return useMemo( () => { + const filters: NormalizedFilter[] = []; + fields.forEach( ( field ) => { + if ( ! field.elements?.length ) { + return; + } - const operators = sanitizeOperators( field ); - if ( operators.length === 0 ) { - return; - } + const operators = sanitizeOperators( field ); + if ( operators.length === 0 ) { + return; + } - const isPrimary = !! field.filterBy?.isPrimary; - filters.push( { - field: field.id, - name: field.label, - elements: field.elements, - singleSelection: operators.some( ( op ) => - [ OPERATOR_IS, OPERATOR_IS_NOT ].includes( op ) - ), - operators, - isVisible: - isPrimary || - !! view.filters?.some( - ( f ) => - f.field === field.id && - ALL_OPERATORS.includes( f.operator ) + const isPrimary = !! field.filterBy?.isPrimary; + filters.push( { + field: field.id, + name: field.label, + elements: field.elements, + singleSelection: operators.some( ( op ) => + [ OPERATOR_IS, OPERATOR_IS_NOT ].includes( op ) ), - isPrimary, + operators, + isVisible: + isPrimary || + !! view.filters?.some( + ( f ) => + f.field === field.id && + ALL_OPERATORS.includes( f.operator ) + ), + isPrimary, + } ); } ); - } ); - // Sort filters by primary property. We need the primary filters to be first. - // Then we sort by name. - filters.sort( ( a, b ) => { - if ( a.isPrimary && ! b.isPrimary ) { - return -1; - } - if ( ! a.isPrimary && b.isPrimary ) { - return 1; - } - return a.name.localeCompare( b.name ); - } ); + // Sort filters by primary property. We need the primary filters to be first. + // Then we sort by name. + filters.sort( ( a, b ) => { + if ( a.isPrimary && ! b.isPrimary ) { + return -1; + } + if ( ! a.isPrimary && b.isPrimary ) { + return 1; + } + return a.name.localeCompare( b.name ); + } ); + return filters; + }, [ fields, view ] ); +} + +export function FilterVisibilityToggle( { + filters, + view, + onChangeView, + setOpenedFilter, + isShowingFilter, + setIsShowingFilter, +}: { + filters: NormalizedFilter[]; + view: View; + onChangeView: ( view: View ) => void; + setOpenedFilter: ( filter: string | null ) => void; + isShowingFilter: boolean; + setIsShowingFilter: React.Dispatch< React.SetStateAction< boolean > >; +} ) { + const onChangeViewWithFilterVisibility = useCallback( + ( _view: View ) => { + onChangeView( _view ); + setIsShowingFilter( true ); + }, + [ onChangeView, setIsShowingFilter ] + ); + const visibleFilters = filters.filter( ( filter ) => filter.isVisible ); + + const hasVisibleFilters = !! visibleFilters.length; + if ( ! hasVisibleFilters ) { + return ( + <AddFilterDropdownMenu + filters={ filters } + view={ view } + onChangeView={ onChangeViewWithFilterVisibility } + setOpenedFilter={ setOpenedFilter } + trigger={ + <Button + className="dataviews-filters__visibility-toggle" + size="compact" + icon={ funnel } + label={ __( 'Add filter' ) } + isPressed={ false } + aria-expanded={ false } + /> + } + /> + ); + } + return ( + <div className="dataviews-filters__container-visibility-toggle"> + <Button + className="dataviews-filters__visibility-toggle" + size="compact" + icon={ funnel } + label={ __( 'Toggle filter display' ) } + onClick={ () => { + if ( ! isShowingFilter ) { + setOpenedFilter( null ); + } + setIsShowingFilter( ! isShowingFilter ); + } } + isPressed={ isShowingFilter } + aria-expanded={ isShowingFilter } + /> + { hasVisibleFilters && !! view.filters?.length && ( + <span className="dataviews-filters-toggle__count"> + { view.filters?.length } + </span> + ) } + </div> + ); +} + +function Filters() { + const { fields, view, onChangeView, openedFilter, setOpenedFilter } = + useContext( DataViewsContext ); + const addFilterRef = useRef< HTMLButtonElement >( null ); + const filters = useFilters( fields, view ); const addFilter = ( <AddFilter key="add-filter" @@ -70,12 +155,12 @@ function Filters() { setOpenedFilter={ setOpenedFilter } /> ); + const visibleFilters = filters.filter( ( filter ) => filter.isVisible ); + if ( visibleFilters.length === 0 ) { + return null; + } const filterComponents = [ - ...filters.map( ( filter ) => { - if ( ! filter.isVisible ) { - return null; - } - + ...visibleFilters.map( ( filter ) => { return ( <FilterSummary key={ filter.field } @@ -90,19 +175,22 @@ function Filters() { addFilter, ]; - if ( filterComponents.length > 1 ) { - filterComponents.push( - <ResetFilters - key="reset-filters" - filters={ filters } - view={ view } - onChangeView={ onChangeView } - /> - ); - } + filterComponents.push( + <ResetFilters + key="reset-filters" + filters={ filters } + view={ view } + onChangeView={ onChangeView } + /> + ); return ( - <HStack justify="flex-start" style={ { width: 'fit-content' } } wrap> + <HStack + justify="flex-start" + style={ { width: 'fit-content' } } + className="dataviews-filters__container" + wrap + > { filterComponents } </HStack> ); diff --git a/packages/dataviews/src/components/dataviews-filters/style.scss b/packages/dataviews/src/components/dataviews-filters/style.scss index 26e5e613fcbe44..6912b5cc483164 100644 --- a/packages/dataviews/src/components/dataviews-filters/style.scss +++ b/packages/dataviews/src/components/dataviews-filters/style.scss @@ -2,6 +2,10 @@ position: relative; } +.dataviews-filters__container { + padding-top: 0; +} + .dataviews-filters__reset-button.dataviews-filters__reset-button[aria-disabled="true"] { &, &:hover { @@ -250,3 +254,29 @@ width: $icon-size; } } + +.dataviews-filters__container-visibility-toggle { + position: relative; + flex-shrink: 0; +} + +.dataviews-filters-toggle__count { + position: absolute; + top: 0; + right: 0; + transform: translate(50%, -50%); + background: var(--wp-admin-theme-color, #3858e9); + height: $grid-unit-20; + min-width: $grid-unit-20; + line-height: $grid-unit-20; + padding: 0 $grid-unit-05; + text-align: center; + border-radius: $grid-unit-10; + font-size: 11px; + outline: var(--wp-admin-border-width-focus) solid $white; + color: $white; +} + +.dataviews-search { + width: fit-content; +} diff --git a/packages/dataviews/src/components/dataviews-search/index.tsx b/packages/dataviews/src/components/dataviews-search/index.tsx index 5e5ce705e11195..1aef99872960be 100644 --- a/packages/dataviews/src/components/dataviews-search/index.tsx +++ b/packages/dataviews/src/components/dataviews-search/index.tsx @@ -30,15 +30,18 @@ const DataViewsSearch = memo( function Search( { label }: SearchProps ) { viewRef.current = view; }, [ onChangeView, view ] ); useEffect( () => { - onChangeViewRef.current( { - ...viewRef.current, - page: 1, - search: debouncedSearch, - } ); + if ( debouncedSearch !== viewRef.current?.search ) { + onChangeViewRef.current( { + ...viewRef.current, + page: 1, + search: debouncedSearch, + } ); + } }, [ debouncedSearch ] ); const searchLabel = label || __( 'Search' ); return ( <SearchControl + className="dataviews-search" __nextHasNoMarginBottom onChange={ setSearch } value={ search } diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index c2f75b9b32b1e8..f6f408065058d2 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -15,7 +15,11 @@ import { useMemo, useState } from '@wordpress/element'; import { default as DataViewsBulkActions } from '../dataviews-bulk-actions'; import DataViewsBulkActionsToolbar from '../dataviews-bulk-actions-toolbar'; import DataViewsContext from '../dataviews-context'; -import DataViewsFilters from '../dataviews-filters'; +import { + default as DataViewsFilters, + useFilters, + FilterVisibilityToggle, +} from '../dataviews-filters'; import DataViewsLayout from '../dataviews-layout'; import DataviewsPagination from '../dataviews-pagination'; import DataViewsSearch from '../dataviews-search'; @@ -69,6 +73,8 @@ export default function DataViews< Item >( { }: DataViewsProps< Item > ) { const [ selectionState, setSelectionState ] = useState< string[] >( [] ); const [ density, setDensity ] = useState< number >( 0 ); + const [ isShowingFilter, setIsShowingFilter ] = + useState< boolean >( false ); const isUncontrolled = selectionProperty === undefined || onChangeSelection === undefined; const selection = isUncontrolled ? selectionState : selectionProperty; @@ -90,6 +96,7 @@ export default function DataViews< Item >( { ); }, [ selection, data, getItemId ] ); + const filters = useFilters( _fields, view ); return ( <DataViewsContext.Provider value={ { @@ -113,14 +120,18 @@ export default function DataViews< Item >( { alignment="top" justify="start" className="dataviews__view-actions" + spacing={ 1 } > - <HStack - justify="start" - className="dataviews-filters__container" - wrap - > + <HStack justify="start" wrap> { search && <DataViewsSearch label={ searchLabel } /> } - <DataViewsFilters /> + <FilterVisibilityToggle + filters={ filters } + view={ view } + onChangeView={ onChangeView } + setOpenedFilter={ setOpenedFilter } + setIsShowingFilter={ setIsShowingFilter } + isShowingFilter={ isShowingFilter } + /> </HStack> { view.type === LAYOUT_GRID && ( <DensityPicker @@ -140,6 +151,7 @@ export default function DataViews< Item >( { { header } </HStack> </HStack> + { isShowingFilter && <DataViewsFilters /> } <DataViewsLayout /> <DataviewsPagination /> <DataViewsBulkActionsToolbar /> diff --git a/packages/dataviews/src/components/dataviews/style.scss b/packages/dataviews/src/components/dataviews/style.scss index 6b8af6a90007dd..742c8c42134dfd 100644 --- a/packages/dataviews/src/components/dataviews/style.scss +++ b/packages/dataviews/src/components/dataviews/style.scss @@ -9,7 +9,8 @@ flex-direction: column; } -.dataviews__view-actions { +.dataviews__view-actions, +.dataviews-filters__container { box-sizing: border-box; padding: $grid-unit-20 $grid-unit-60; flex-shrink: 0; @@ -78,7 +79,8 @@ /* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ @container (max-width: 430px) { - .dataviews__view-actions { + .dataviews__view-actions, + .dataviews-filters__container { padding: $grid-unit-15 $grid-unit-30; .components-search-control { @@ -95,3 +97,4 @@ padding-right: $grid-unit-30; } } + diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index a8db73272c0ce7..66d2d25a4b8f04 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -171,6 +171,7 @@ export default function DataviewsPatterns() { descriptionId={ `${ id }-description` } /> <DataViews + key={ categoryId + postType } paginationInfo={ paginationInfo } fields={ fields } actions={ actions } diff --git a/packages/edit-site/src/components/page-templates/index.js b/packages/edit-site/src/components/page-templates/index.js index 01b17ae76fc9dc..5ffc2477337935 100644 --- a/packages/edit-site/src/components/page-templates/index.js +++ b/packages/edit-site/src/components/page-templates/index.js @@ -214,6 +214,7 @@ export default function PageTemplates() { actions={ <AddNewTemplate /> } > <DataViews + key={ activeView } paginationInfo={ paginationInfo } fields={ fields } actions={ actions } diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index e63ed4ccebcf98..74bbee05246178 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -174,7 +174,12 @@ export default function PostList( { postType } ) { const [ view, setView ] = useView( postType ); const history = useHistory(); const location = useLocation(); - const { postId, quickEdit = false } = location.params; + const { + postId, + quickEdit = false, + isCustom, + activeView = 'all', + } = location.params; const [ selection, setSelection ] = useState( postId?.split( ',' ) ?? [] ); const onChangeSelection = useCallback( ( items ) => { @@ -334,6 +339,7 @@ export default function PostList( { postType } ) { } > <DataViews + key={ activeView + isCustom } paginationInfo={ paginationInfo } fields={ fields } actions={ actions } diff --git a/test/e2e/specs/site-editor/dataviews-list-layout-keyboard.spec.js b/test/e2e/specs/site-editor/dataviews-list-layout-keyboard.spec.js index 16cc34ace8a82b..0ff375a9f45a33 100644 --- a/test/e2e/specs/site-editor/dataviews-list-layout-keyboard.spec.js +++ b/test/e2e/specs/site-editor/dataviews-list-layout-keyboard.spec.js @@ -41,11 +41,6 @@ test.describe( 'Dataviews List Layout', () => { page.getByRole( 'button', { name: 'Add filter' } ) ).toBeFocused(); - await page.keyboard.press( 'Tab' ); - await expect( - page.getByRole( 'button', { name: 'Reset' } ) - ).toBeFocused(); - await page.keyboard.press( 'Tab' ); await expect( page.getByRole( 'button', { name: 'Layout' } ) @@ -74,7 +69,6 @@ test.describe( 'Dataviews List Layout', () => { await page.keyboard.press( 'Tab' ); await page.keyboard.press( 'Tab' ); await page.keyboard.press( 'Tab' ); - await page.keyboard.press( 'Tab' ); const firstItem = page .getByRole( 'grid' ) @@ -109,7 +103,6 @@ test.describe( 'Dataviews List Layout', () => { await page.keyboard.press( 'Tab' ); await page.keyboard.press( 'Tab' ); await page.keyboard.press( 'Tab' ); - await page.keyboard.press( 'Tab' ); // Make sure the items have loaded before reaching for the 1st item in the list. await expect( page.getByRole( 'grid' ) ).toBeVisible(); @@ -133,7 +126,6 @@ test.describe( 'Dataviews List Layout', () => { await page.keyboard.press( 'Tab' ); await page.keyboard.press( 'Tab' ); await page.keyboard.press( 'Tab' ); - await page.keyboard.press( 'Tab' ); // Make sure the items have loaded before reaching for the 1st item in the list. await expect( page.getByRole( 'grid' ) ).toBeVisible(); @@ -175,7 +167,6 @@ test.describe( 'Dataviews List Layout', () => { await page.keyboard.press( 'Tab' ); await page.keyboard.press( 'Tab' ); await page.keyboard.press( 'Tab' ); - await page.keyboard.press( 'Tab' ); // Make sure the items have loaded before reaching for the 1st item in the list. await expect( page.getByRole( 'grid' ) ).toBeVisible(); diff --git a/test/e2e/specs/site-editor/new-templates-list.spec.js b/test/e2e/specs/site-editor/new-templates-list.spec.js index 92edc741011834..878f0ed2eb48c3 100644 --- a/test/e2e/specs/site-editor/new-templates-list.spec.js +++ b/test/e2e/specs/site-editor/new-templates-list.spec.js @@ -56,7 +56,7 @@ test.describe( 'Templates', () => { await expect( titles ).toHaveCount( 1 ); await expect( titles.first() ).toHaveText( 'Tag Archives' ); await page - .getByRole( 'button', { name: 'Reset', exact: true } ) + .getByRole( 'button', { name: 'Reset search', exact: true } ) .click(); await expect( titles ).toHaveCount( 6 ); diff --git a/test/e2e/specs/site-editor/patterns.spec.js b/test/e2e/specs/site-editor/patterns.spec.js index 0b0fada39c2622..538f9ba936a897 100644 --- a/test/e2e/specs/site-editor/patterns.spec.js +++ b/test/e2e/specs/site-editor/patterns.spec.js @@ -148,6 +148,14 @@ test.describe( 'Patterns', () => { await admin.visitSiteEditor( { postType: 'wp_block' } ); await expect( patterns.item ).toHaveCount( 3 ); + + await patterns.content + .getByRole( 'button', { + name: 'Toggle filter display', + exact: true, + } ) + .click(); + const searchBox = patterns.content.getByRole( 'searchbox', { name: 'Search', } ); From 9a3d12aa900de3efcc1f623a170b9d7ee3841933 Mon Sep 17 00:00:00 2001 From: Erik <11491369+kebbet@users.noreply.github.com> Date: Mon, 5 Aug 2024 12:36:34 +0200 Subject: [PATCH 0249/1908] Data Views: Add context to trash string (#64249) Co-authored-by: kebbet <kebbet@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/editor/src/dataviews/actions/trash-post.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/dataviews/actions/trash-post.tsx b/packages/editor/src/dataviews/actions/trash-post.tsx index c6a265eba81f5a..a8e42c510a6cd0 100644 --- a/packages/editor/src/dataviews/actions/trash-post.tsx +++ b/packages/editor/src/dataviews/actions/trash-post.tsx @@ -4,7 +4,7 @@ import { trash } from '@wordpress/icons'; import { useDispatch } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -import { __, _n, sprintf } from '@wordpress/i18n'; +import { __, _n, sprintf, _x } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; import { useState } from '@wordpress/element'; import { @@ -185,7 +185,7 @@ const trashPost: Action< PostWithPermissions > = { disabled={ isBusy } accessibleWhenDisabled > - { __( 'Trash' ) } + { _x( 'Trash', 'verb' ) } </Button> </HStack> </VStack> From 3f7611a8ae36d2fb5159185ea7b759e2b605755f Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Mon, 5 Aug 2024 20:10:35 +0900 Subject: [PATCH 0250/1908] BlockDraggable: Remove invalid aria-hidden attribute from button (#64228) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-editor/src/components/block-mover/index.js | 1 - .../src/components/block-tools/block-selection-button.js | 1 - .../block-editor/src/components/block-tools/zoom-out-toolbar.js | 1 - 3 files changed, 3 deletions(-) diff --git a/packages/block-editor/src/components/block-mover/index.js b/packages/block-editor/src/components/block-mover/index.js index 3b7f25800095a5..7aa273605bbe6b 100644 --- a/packages/block-editor/src/components/block-mover/index.js +++ b/packages/block-editor/src/components/block-mover/index.js @@ -89,7 +89,6 @@ function BlockMover( { <Button icon={ dragHandle } className="block-editor-block-mover__drag-handle" - aria-hidden="true" label={ __( 'Drag' ) } // Should not be able to tab to drag handle as this // button can only be used with a pointer device. diff --git a/packages/block-editor/src/components/block-tools/block-selection-button.js b/packages/block-editor/src/components/block-tools/block-selection-button.js index 8d99b829a84bf4..77d37634b87217 100644 --- a/packages/block-editor/src/components/block-tools/block-selection-button.js +++ b/packages/block-editor/src/components/block-tools/block-selection-button.js @@ -259,7 +259,6 @@ function BlockSelectionButton( { clientId, rootClientId }, ref ) { <Button icon={ dragHandle } className="block-selection-button_drag-handle" - aria-hidden="true" label={ dragHandleLabel } // Should not be able to tab to drag handle as this // button can only be used with a pointer device. diff --git a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js index bb5955244cd823..4dcadc798489a4 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js @@ -100,7 +100,6 @@ export default function ZoomOutToolbar( { clientId, rootClientId } ) { <Button icon={ dragHandle } className="block-selection-button_drag-handle zoom-out-toolbar-button" - aria-hidden="true" label={ __( 'Drag' ) } iconSize={ 24 } size="compact" From 525f756a89119992e378091daf7b336564b7d5db Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 5 Aug 2024 16:19:27 +0400 Subject: [PATCH 0251/1908] Plugin: Remove leftover 'WP_Rest_Customizer_Nonces' controller (#64221) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../class-wp-rest-customizer-nonces.php | 74 ------------------- lib/experimental/rest-api.php | 9 --- lib/load.php | 5 -- 3 files changed, 88 deletions(-) delete mode 100644 lib/experimental/class-wp-rest-customizer-nonces.php diff --git a/lib/experimental/class-wp-rest-customizer-nonces.php b/lib/experimental/class-wp-rest-customizer-nonces.php deleted file mode 100644 index f4202a672f5202..00000000000000 --- a/lib/experimental/class-wp-rest-customizer-nonces.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php -/** - * WP_Rest_Customizer_Nonces class. - * - * @package gutenberg - */ - -if ( ! class_exists( 'WP_Rest_Customizer_Nonces' ) ) { - - /** - * Class that returns the customizer "save" nonce that's required for the - * batch save operation using the customizer API endpoint. - */ - class WP_Rest_Customizer_Nonces extends WP_REST_Controller { - - /** - * Constructor. - */ - public function __construct() { - $this->namespace = '__experimental'; - $this->rest_base = 'customizer-nonces'; - } - - /** - * Registers the necessary REST API routes. - * - * @access public - */ - public function register_routes() { - register_rest_route( - $this->namespace, - '/' . $this->rest_base . '/get-save-nonce', - array( - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_save_nonce' ), - 'permission_callback' => array( $this, 'permissions_check' ), - 'args' => $this->get_collection_params(), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) - ); - } - - /** - * Checks if a given request has access to read menu items if they have access to edit them. - * - * @return true|WP_Error True if the request has read access, WP_Error object otherwise. - */ - public function permissions_check() { - $post_type = get_post_type_object( 'nav_menu_item' ); - if ( ! current_user_can( $post_type->cap->edit_posts ) ) { - return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit posts in this post type.', 'gutenberg' ), array( 'status' => rest_authorization_required_code() ) ); - } - return true; - } - - /** - * Returns the nonce required to request the customizer API endpoint. - * - * @access public - */ - public function get_save_nonce() { - require_once ABSPATH . 'wp-includes/class-wp-customize-manager.php'; - $wp_customize = new WP_Customize_Manager(); - $nonce = wp_create_nonce( 'save-customize_' . $wp_customize->get_stylesheet() ); - return array( - 'success' => true, - 'nonce' => $nonce, - 'stylesheet' => $wp_customize->get_stylesheet(), - ); - } - } -} diff --git a/lib/experimental/rest-api.php b/lib/experimental/rest-api.php index 77f7d091d2655d..6bb2947f889147 100644 --- a/lib/experimental/rest-api.php +++ b/lib/experimental/rest-api.php @@ -10,15 +10,6 @@ die( 'Silence is golden.' ); } -/** - * Registers the customizer nonces REST API routes. - */ -function gutenberg_register_rest_customizer_nonces() { - $customizer_nonces = new WP_Rest_Customizer_Nonces(); - $customizer_nonces->register_routes(); -} -add_action( 'rest_api_init', 'gutenberg_register_rest_customizer_nonces' ); - /** * Registers the Block editor settings REST API routes. */ diff --git a/lib/load.php b/lib/load.php index 244b6a2d9e685a..5a299f3b696968 100644 --- a/lib/load.php +++ b/lib/load.php @@ -45,12 +45,7 @@ function gutenberg_is_experiment_enabled( $name ) { require_once __DIR__ . '/class-wp-rest-edit-site-export-controller-gutenberg.php'; require_once __DIR__ . '/rest-api.php'; - // Experimental. - if ( ! class_exists( 'WP_Rest_Customizer_Nonces' ) ) { - require_once __DIR__ . '/experimental/class-wp-rest-customizer-nonces.php'; - } require_once __DIR__ . '/experimental/rest-api.php'; - require_once __DIR__ . '/experimental/kses-allowed-html.php'; } From 396e470dd2d1fabb76f769786163c8c446a9f2d0 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 5 Aug 2024 16:19:48 +0400 Subject: [PATCH 0252/1908] Site Editor: Don't trigger template ID resolution for multi-selected posts (#64254) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../sync-state-with-url/use-init-edited-entity-from-url.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js index 5c8cdfd58f6304..a0707802846fcf 100644 --- a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js +++ b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js @@ -90,6 +90,11 @@ function useResolveEditedEntityAndContext( { postId, postType } ) { return undefined; } + // Don't trigger resolution for multi-selected posts. + if ( postId && postId.includes( ',' ) ) { + return undefined; + } + const { getEditedEntityRecord, getEntityRecords, From 7559e74027f3be144509b56ab010a054a1801a58 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Mon, 5 Aug 2024 21:55:28 +0900 Subject: [PATCH 0253/1908] Tweak Create custom template modal (#64255) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../components/post-template/create-new-template-modal.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-template/create-new-template-modal.js b/packages/editor/src/components/post-template/create-new-template-modal.js index e6e5ea3f90680d..69d31b7f8f714e 100644 --- a/packages/editor/src/components/post-template/create-new-template-modal.js +++ b/packages/editor/src/components/post-template/create-new-template-modal.js @@ -118,6 +118,7 @@ export default function CreateNewTemplateModal( { onClose } ) { > <VStack spacing="3"> <TextControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Name' ) } value={ title } @@ -129,11 +130,16 @@ export default function CreateNewTemplateModal( { onClose } ) { ) } /> <HStack justify="right"> - <Button variant="tertiary" onClick={ cancel }> + <Button + __next40pxDefaultSize + variant="tertiary" + onClick={ cancel } + > { __( 'Cancel' ) } </Button> <Button + __next40pxDefaultSize variant="primary" type="submit" isBusy={ isBusy } From ee2fb2925df35fc141e0ecc86b907f0cf6a18cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Zi=C4=99ba?= <wojtek.zieba@automattic.com> Date: Mon, 5 Aug 2024 18:05:13 +0200 Subject: [PATCH 0254/1908] Bump AGP to `8.5.1` (#64044) * Bump AGP to 8.5.1 in `react-native-bridge` * Bump AGP to 8.5.1 in `react-native-aztec` * Bump AGP to 8.5.1 in `react-native-editor` Co-authored-by: wzieba <wzieba@git.wordpress.org> --- packages/react-native-aztec/android/settings.gradle | 2 +- packages/react-native-bridge/android/settings.gradle | 2 +- packages/react-native-editor/android/build.gradle | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-native-aztec/android/settings.gradle b/packages/react-native-aztec/android/settings.gradle index e77808bf87ac80..5c91464a042457 100644 --- a/packages/react-native-aztec/android/settings.gradle +++ b/packages/react-native-aztec/android/settings.gradle @@ -1,6 +1,6 @@ pluginManagement { gradle.ext.kotlinVersion = '1.8.0' - gradle.ext.agpVersion = '8.1.0' + gradle.ext.agpVersion = '8.5.1' gradle.ext.automatticPublishToS3Version = '0.8.0' plugins { diff --git a/packages/react-native-bridge/android/settings.gradle b/packages/react-native-bridge/android/settings.gradle index 35c14b4620d8e4..2863d3bb065127 100644 --- a/packages/react-native-bridge/android/settings.gradle +++ b/packages/react-native-bridge/android/settings.gradle @@ -1,6 +1,6 @@ pluginManagement { gradle.ext.kotlinVersion = '1.8.0' - gradle.ext.agpVersion = '8.1.0' + gradle.ext.agpVersion = '8.5.1' gradle.ext.automatticPublishToS3Version = '0.8.0' plugins { diff --git a/packages/react-native-editor/android/build.gradle b/packages/react-native-editor/android/build.gradle index a45374a58c7d3d..cadcfa8704b51a 100644 --- a/packages/react-native-editor/android/build.gradle +++ b/packages/react-native-editor/android/build.gradle @@ -1,6 +1,6 @@ buildscript { ext { - gradlePluginVersion = '8.1.0' + gradlePluginVersion = '8.5.1' kotlinVersion = '1.8.0' buildToolsVersion = "34.0.0" minSdkVersion = 24 From e3c2cd3c33f95119e2ffb0457118b1a7ddbdd62f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Mon, 5 Aug 2024 18:38:18 +0200 Subject: [PATCH 0255/1908] DataForm: if a field of type `text` declare `elements`, render it as a `SelectControl` in `edit` (#64251) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../dataform/stories/index.story.tsx | 12 ++++++++- packages/dataviews/src/field-types/text.tsx | 26 ++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/packages/dataviews/src/components/dataform/stories/index.story.tsx b/packages/dataviews/src/components/dataform/stories/index.story.tsx index f6f29d0e7f9ebd..6acf0c65d9bd4f 100644 --- a/packages/dataviews/src/components/dataform/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataform/stories/index.story.tsx @@ -34,6 +34,15 @@ const fields = [ { value: 2, label: 'John' }, ], }, + { + id: 'status', + label: 'Status', + type: 'text' as const, + elements: [ + { value: 'draft', label: 'Draft' }, + { value: 'published', label: 'Published' }, + ], + }, ]; export const Default = () => { @@ -41,10 +50,11 @@ export const Default = () => { title: 'Hello, World!', order: 2, author: 1, + status: 'draft', } ); const form = { - visibleFields: [ 'title', 'order', 'author' ], + visibleFields: [ 'title', 'order', 'author', 'status' ], }; return ( diff --git a/packages/dataviews/src/field-types/text.tsx b/packages/dataviews/src/field-types/text.tsx index 45d1b66bf71d96..721b3fa2b59f63 100644 --- a/packages/dataviews/src/field-types/text.tsx +++ b/packages/dataviews/src/field-types/text.tsx @@ -1,8 +1,9 @@ /** * WordPress dependencies */ -import { TextControl } from '@wordpress/components'; +import { SelectControl, TextControl } from '@wordpress/components'; import { useCallback } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -47,6 +48,29 @@ function Edit< Item >( { [ id, onChange ] ); + if ( field.elements ) { + const elements = [ + /* + * Value can be undefined when: + * + * - the field is not required + * - in bulk editing + * + */ + { label: __( 'Select item' ), value: '' }, + ...field.elements, + ]; + + return ( + <SelectControl + label={ label } + value={ value } + options={ elements } + onChange={ onChangeControl } + /> + ); + } + return ( <TextControl label={ label } From f6c809f561b16de496f5971c18b3f2961a8358fd Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 6 Aug 2024 01:59:13 +0900 Subject: [PATCH 0256/1908] Add margin-bottom lint rules for TextControl (#64212) * Fix in Form block * Fix in DataForm * Fix in Add new post modal * Fix in Language format popover * Add lint rule Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .eslintrc.js | 1 + packages/block-library/src/form-input/edit.js | 1 + .../src/components/dataform/index.tsx | 25 +++++++++------- .../dataviews/src/field-types/integer.tsx | 2 ++ packages/dataviews/src/field-types/text.tsx | 1 + .../src/components/add-new-post/index.js | 3 +- .../src/components/post-edit/index.js | 29 ++++++++++++------- packages/format-library/src/language/index.js | 12 ++++++-- 8 files changed, 50 insertions(+), 24 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 0fc37713dce4d1..97c9f395194f35 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -295,6 +295,7 @@ module.exports = { 'FocalPointPicker', 'RangeControl', 'SearchControl', + 'TextControl', 'TextareaControl', 'ToggleGroupControl', 'TreeSelect', diff --git a/packages/block-library/src/form-input/edit.js b/packages/block-library/src/form-input/edit.js index 855fdbf4684626..856d09d3945e64 100644 --- a/packages/block-library/src/form-input/edit.js +++ b/packages/block-library/src/form-input/edit.js @@ -63,6 +63,7 @@ function InputFieldBlock( { attributes, setAttributes, className } ) { ) } <InspectorControls group="advanced"> <TextControl + __nextHasNoMarginBottom autoComplete="off" label={ __( 'Name' ) } value={ name } diff --git a/packages/dataviews/src/components/dataform/index.tsx b/packages/dataviews/src/components/dataform/index.tsx index a247601e739b29..02953b2930bd1f 100644 --- a/packages/dataviews/src/components/dataform/index.tsx +++ b/packages/dataviews/src/components/dataform/index.tsx @@ -6,6 +6,7 @@ import type { Dispatch, SetStateAction } from 'react'; /** * WordPress dependencies */ +import { __experimentalVStack as VStack } from '@wordpress/components'; import { useMemo } from '@wordpress/element'; /** @@ -37,14 +38,18 @@ export default function DataForm< Item >( { [ fields, form.visibleFields ] ); - return visibleFields.map( ( field ) => { - return ( - <field.Edit - key={ field.id } - data={ data } - field={ field } - onChange={ onChange } - /> - ); - } ); + return ( + <VStack spacing={ 4 }> + { visibleFields.map( ( field ) => { + return ( + <field.Edit + key={ field.id } + data={ data } + field={ field } + onChange={ onChange } + /> + ); + } ) } + </VStack> + ); } diff --git a/packages/dataviews/src/field-types/integer.tsx b/packages/dataviews/src/field-types/integer.tsx index 823983bc010bf4..bf757776249b42 100644 --- a/packages/dataviews/src/field-types/integer.tsx +++ b/packages/dataviews/src/field-types/integer.tsx @@ -76,6 +76,8 @@ function Edit< Item >( { value={ value } options={ elements } onChange={ onChangeControl } + __next40pxDefaultSize + __nextHasNoMarginBottom /> ); } diff --git a/packages/dataviews/src/field-types/text.tsx b/packages/dataviews/src/field-types/text.tsx index 721b3fa2b59f63..227c70033cae09 100644 --- a/packages/dataviews/src/field-types/text.tsx +++ b/packages/dataviews/src/field-types/text.tsx @@ -78,6 +78,7 @@ function Edit< Item >( { value={ value ?? '' } onChange={ onChangeControl } __next40pxDefaultSize + __nextHasNoMarginBottom /> ); } diff --git a/packages/edit-site/src/components/add-new-post/index.js b/packages/edit-site/src/components/add-new-post/index.js index 7e75a47820fced..044e3c703b9948 100644 --- a/packages/edit-site/src/components/add-new-post/index.js +++ b/packages/edit-site/src/components/add-new-post/index.js @@ -95,9 +95,10 @@ export default function AddNewPostModal( { postType, onSave, onClose } ) { size="small" > <form onSubmit={ createPost }> - <VStack spacing={ 3 }> + <VStack spacing={ 4 }> <TextControl __next40pxDefaultSize + __nextHasNoMarginBottom label={ __( 'Title' ) } onChange={ setTitle } placeholder={ __( 'No title' ) } diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index f8519470749a94..6a6efc23861841 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -10,7 +10,11 @@ import { __ } from '@wordpress/i18n'; import { DataForm, isItemValid } from '@wordpress/dataviews'; import { useDispatch, useSelect, useRegistry } from '@wordpress/data'; import { store as coreDataStore } from '@wordpress/core-data'; -import { Button } from '@wordpress/components'; +import { + Button, + FlexItem, + __experimentalVStack as VStack, +} from '@wordpress/components'; import { useState, useMemo } from '@wordpress/element'; /** @@ -71,22 +75,25 @@ function PostEditForm( { postType, postId } ) { const isUpdateDisabled = ! isItemValid( itemWithEdits, fields, form ); return ( - <form onSubmit={ onSubmit }> + <VStack as="form" onSubmit={ onSubmit } spacing={ 4 }> <DataForm data={ itemWithEdits } fields={ fields } form={ form } onChange={ setEdits } /> - <Button - variant="primary" - type="submit" - accessibleWhenDisabled - disabled={ isUpdateDisabled } - > - { __( 'Update' ) } - </Button> - </form> + <FlexItem> + <Button + variant="primary" + type="submit" + accessibleWhenDisabled + disabled={ isUpdateDisabled } + __next40pxDefaultSize + > + { __( 'Update' ) } + </Button> + </FlexItem> + </VStack> ); } diff --git a/packages/format-library/src/language/index.js b/packages/format-library/src/language/index.js index d37d8d6dbd0cd8..6cfb8c4ad44927 100644 --- a/packages/format-library/src/language/index.js +++ b/packages/format-library/src/language/index.js @@ -13,6 +13,7 @@ import { Button, Popover, __experimentalHStack as HStack, + __experimentalVStack as VStack, } from '@wordpress/components'; import { useState } from '@wordpress/element'; import { applyFormat, removeFormat, useAnchor } from '@wordpress/rich-text'; @@ -78,7 +79,9 @@ function InlineLanguageUI( { value, contentRef, onChange, onClose } ) { anchor={ popoverAnchor } onClose={ onClose } > - <form + <VStack + as="form" + spacing={ 4 } className="block-editor-format-toolbar__language-container-content" onSubmit={ ( event ) => { event.preventDefault(); @@ -95,6 +98,8 @@ function InlineLanguageUI( { value, contentRef, onChange, onClose } ) { } } > <TextControl + __next40pxDefaultSize + __nextHasNoMarginBottom label={ title } value={ lang } onChange={ ( val ) => setLang( val ) } @@ -103,6 +108,8 @@ function InlineLanguageUI( { value, contentRef, onChange, onClose } ) { ) } /> <SelectControl + __next40pxDefaultSize + __nextHasNoMarginBottom label={ __( 'Text direction' ) } value={ dir } options={ [ @@ -119,12 +126,13 @@ function InlineLanguageUI( { value, contentRef, onChange, onClose } ) { /> <HStack alignment="right"> <Button + __next40pxDefaultSize variant="primary" type="submit" text={ __( 'Apply' ) } /> </HStack> - </form> + </VStack> </Popover> ); } From 650eb7f21f77dfb884eba606b7a995d5a25c5fff Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 6 Aug 2024 02:14:00 +0900 Subject: [PATCH 0257/1908] SelectControl: Pass through `options` props (#64211) * SelectControl: Pass through `options` props * Clean up types * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/select-control/README.md | 9 ++++- .../components/src/select-control/index.tsx | 34 ++++++++-------- .../select-control/test/select-control.tsx | 27 +++++++++++-- .../components/src/select-control/types.ts | 39 ++++++++++--------- 5 files changed, 70 insertions(+), 40 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 0c0fab401d02a8..570b7ac308c5fe 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -13,6 +13,7 @@ - `TimeInput`: Expose as subcomponent of `TimePicker` ([#63145](https://github.com/WordPress/gutenberg/pull/63145)). - `RadioControl`: add support for option help text ([#63751](https://github.com/WordPress/gutenberg/pull/63751)). - `Guide`: Add `__next40pxDefaultSize` to buttons ([#64181](https://github.com/WordPress/gutenberg/pull/64181)). +- `SelectControl`: Pass through `options` props ([#64211](https://github.com/WordPress/gutenberg/pull/64211)). ### Internal diff --git a/packages/components/src/select-control/README.md b/packages/components/src/select-control/README.md index bc37942231091b..464ee180b38639 100644 --- a/packages/components/src/select-control/README.md +++ b/packages/components/src/select-control/README.md @@ -190,7 +190,7 @@ In most cases, it is preferable to use the `FormTokenField` or `CheckboxControl` #### options -An array of objects containing the following properties: +An array of objects containing the following properties, as well as any other `option` element attributes: - `label`: (string) The label to be shown to the user. - `value`: (string) The internal value used to choose the selected value. This is also the value passed to onChange when the option is selected. @@ -214,6 +214,13 @@ If multiple is false the value received is a single value with the new selected - Type: `function` - Required: Yes +#### value + +The value of the selected option. If `multiple` is true, the `value` should be an array with the values of the selected options. + +- Type: `String|String[]` +- Required: No + #### variant The style variant of the control. diff --git a/packages/components/src/select-control/index.tsx b/packages/components/src/select-control/index.tsx index 5db0316d02b129..874b6ace1ea949 100644 --- a/packages/components/src/select-control/index.tsx +++ b/packages/components/src/select-control/index.tsx @@ -26,6 +26,22 @@ function useUniqueId( idProp?: string ) { return idProp || id; } +function SelectOptions( { + options, +}: { + options: NonNullable< SelectControlProps[ 'options' ] >; +} ) { + return options.map( ( { id, label, value, ...optionProps }, index ) => { + const key = id || `${ label }-${ value }-${ index }`; + + return ( + <option key={ key } value={ value } { ...optionProps }> + { label } + </option> + ); + } ); +} + function UnforwardedSelectControl( props: WordPressComponentProps< SelectControlProps, 'select', false >, ref: React.ForwardedRef< HTMLSelectElement > @@ -115,23 +131,7 @@ function UnforwardedSelectControl( value={ valueProp } variant={ variant } > - { children || - options.map( ( option, index ) => { - const key = - option.id || - `${ option.label }-${ option.value }-${ index }`; - - return ( - <option - key={ key } - value={ option.value } - disabled={ option.disabled } - hidden={ option.hidden } - > - { option.label } - </option> - ); - } ) } + { children || <SelectOptions options={ options } /> } </Select> </StyledInputBase> </BaseControl> diff --git a/packages/components/src/select-control/test/select-control.tsx b/packages/components/src/select-control/test/select-control.tsx index 03e3acbf1f7325..f2da74d9a6e911 100644 --- a/packages/components/src/select-control/test/select-control.tsx +++ b/packages/components/src/select-control/test/select-control.tsx @@ -17,8 +17,8 @@ describe( 'SelectControl', () => { expect( screen.queryByRole( 'combobox' ) ).not.toBeInTheDocument(); } ); - it( 'should not render its children', async () => { - const user = await userEvent.setup(); + it( 'should render its children', async () => { + const user = userEvent.setup(); const handleChangeMock = jest.fn(); render( @@ -46,8 +46,8 @@ describe( 'SelectControl', () => { ); } ); - it( 'should not render its options', async () => { - const user = await userEvent.setup(); + it( 'should render its options', async () => { + const user = userEvent.setup(); const handleChangeMock = jest.fn(); render( @@ -81,4 +81,23 @@ describe( 'SelectControl', () => { expect.anything() ); } ); + + it( 'should pass through options props', () => { + render( + <SelectControl + label="Select" + options={ [ + { + value: 'value', + label: 'label', + 'aria-label': 'Aria label', + }, + ] } + /> + ); + + expect( + screen.getByRole( 'option', { name: 'Aria label' } ) + ).toBeInTheDocument(); + } ); } ); diff --git a/packages/components/src/select-control/types.ts b/packages/components/src/select-control/types.ts index a1d02d444c1474..a5d0d740c593cc 100644 --- a/packages/components/src/select-control/types.ts +++ b/packages/components/src/select-control/types.ts @@ -1,7 +1,7 @@ /** * External dependencies */ -import type { ChangeEvent, FocusEvent, ReactNode } from 'react'; +import type { ChangeEvent, ReactNode } from 'react'; /** * Internal dependencies @@ -22,9 +22,12 @@ type SelectControlBaseProps = Pick< | 'suffix' > & Pick< BaseControlProps, 'help' | '__nextHasNoMarginBottom' > & { - onBlur?: ( event: FocusEvent< HTMLSelectElement > ) => void; - onFocus?: ( event: FocusEvent< HTMLSelectElement > ) => void; - options?: { + /** + * An array of option property objects to be rendered, + * each with a `label` and `value` property, as well as any other + * `<option>` attributes. + */ + options?: ( { /** * The label to be shown to the user. */ @@ -34,20 +37,10 @@ type SelectControlBaseProps = Pick< * This is also the value passed to `onChange` when the option is selected. */ value: string; - id?: string; - /** - * Whether or not the option should have the disabled attribute. - * - * @default false - */ - disabled?: boolean; - /** - * Whether or not the option should be hidden. - * - * @default false - */ - hidden?: boolean; - }[]; + } & Omit< + React.OptionHTMLAttributes< HTMLOptionElement >, + 'label' | 'value' + > )[]; /** * As an alternative to the `options` prop, `optgroup`s and `options` can be * passed in as `children` for more customizability. @@ -70,6 +63,11 @@ export type SelectControlSingleSelectionProps = SelectControlBaseProps & { * @default false */ multiple?: false; + /** + * The value of the selected option. + * + * If `multiple` is true, the `value` should be an array with the values of the selected options. + */ value?: string; /** * A function that receives the value of the new option that is being selected as input. @@ -92,6 +90,11 @@ export type SelectControlMultipleSelectionProps = SelectControlBaseProps & { * @default false */ multiple: true; + /** + * The value of the selected option. + * + * If `multiple` is true, the `value` should be an array with the values of the selected options. + */ value?: string[]; /** * A function that receives the value of the new option that is being selected as input. From 6078a01f5778833d68a83959dd33b53fd9f9e469 Mon Sep 17 00:00:00 2001 From: Ryan Welcher <me@ryanwelcher.com> Date: Mon, 5 Aug 2024 15:08:32 -0400 Subject: [PATCH 0258/1908] Add docs for some dynamically generated selectors in the core-data store (#64269) * Add post type and taxonomy selectors. * Run docs build * Change order to fix heading issue. Co-authored-by: ryanwelcher <welcher@git.wordpress.org> Co-authored-by: justintadlock <greenshady@git.wordpress.org> --- docs/reference-guides/data/data-core.md | 101 +++++++++++++++++++++++- 1 file changed, 100 insertions(+), 1 deletion(-) diff --git a/docs/reference-guides/data/data-core.md b/docs/reference-guides/data/data-core.md index a2bcf31b4d2e28..f4138c49dc8d6b 100644 --- a/docs/reference-guides/data/data-core.md +++ b/docs/reference-guides/data/data-core.md @@ -2,7 +2,106 @@ Namespace: `core`. -## Selectors +### Dynamically generated selectors + +There are a number of user-friendly selectors that are wrappers of the more generic `getEntityRecord` and `getEntityRecords` that can be used to retrieve information for the various entities. + +### getPostType + +Returns the information for a given post type. + +_Usage_ + + import { useSelect } from '@wordpress/data'; + import { store as coreDataStore } from '@wordpress/core-data'; + + const postType = useSelect( + ( select ) => select( coreDataStore ).getPostType( 'post' ) + + // Equivalent to: select( coreDataStore ).getEntityRecord( 'root', 'postType', 'post' ) + ); + +_Parameters_ + +- postType `string` + +_Returns_ + +- `EntityRecord | undefined`: Record. + +### getPostTypes + +Returns the information for post types. + +_Usage_ + + import { useSelect } from '@wordpress/data'; + import { store as coreDataStore } from '@wordpress/core-data'; + + const postTypes = useSelect( ( select ) => { + return select( coreDataStore ).getPostTypes( { per_page: 4 } ); + + // Equivalent to: + // select( coreDataStore ).getEntityRecords( 'root', 'postType', { per_page: 4 } ); + } ); + +_Parameters_ + +- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s". + +_Returns_ + +- `EntityRecord[] | null`: Records. + +### getTaxonomy + +Returns information for a given taxonomy. + +_Usage_ + + import { useSelect } from '@wordpress/data'; + import { store as coreDataStore } from '@wordpress/core-data'; + + const taxonomy = useSelect( ( select ) => { + return select( coreDataStore ).getTaxonomy( 'category' ); + + // Equivalent to: + // select( coreDataStore ).getEntityRecord( 'root', 'taxonomy', 'category' ); + } ); + +_Parameters_ + +- taxonomy `string` + +_Returns_ + +- `EntityRecord | undefined`: Record. + +### getTaxonomies + +Returns information for taxonomies. + +_Usage_ + + import { useSelect } from '@wordpress/data'; + import { store as coreDataStore } from '@wordpress/core-data'; + + const taxonomies = useSelect( ( select ) => { + return select( coreDataStore ).getTaxonomies( { type: 'post' } ); + + // Equivalent to: + // select( coreDataStore ).getEntityRecords( 'root', 'taxonomy', { type: 'post' } ); + } ); + +_Parameters_ + +- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s". + +_Returns_ + +- `EntityRecord[] | null`: Records. + +## Other Selectors <!-- START TOKEN(Autogenerated selectors|../../../packages/core-data/src/selectors.ts) --> From 96cca231cd6b9ce56c94a3dc098016ba6eddefce Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 5 Aug 2024 21:45:29 +0200 Subject: [PATCH 0259/1908] Site Icon: Fix position in distraction free mode (#64261) --- packages/edit-site/src/components/editor/style.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/edit-site/src/components/editor/style.scss b/packages/edit-site/src/components/editor/style.scss index 1e931e296d2f42..fbc231eb757c57 100644 --- a/packages/edit-site/src/components/editor/style.scss +++ b/packages/edit-site/src/components/editor/style.scss @@ -22,7 +22,6 @@ /* stylelint-disable -- Disable reason: View Transitions not supported properly by stylelint. */ view-transition-name: toggle; /* stylelint-enable */ - position: fixed; top: 0; left: 0; height: $header-height; From cf964194f6d6b620dc7ae6be8a23415242dd3a25 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Tue, 6 Aug 2024 02:13:06 +0200 Subject: [PATCH 0260/1908] Button: Improve the aria-disabled focus style (#62480) * Improve Button aria-disabled focus style. * Add changelog entry. * Adjust changelog entry after rebase. * Adjust changelog entry after rebase. * Introduce new gray-500 for disabled controls. * Use gray-500 for all disabled button variants. * Fix is-pressed disabled styles regression * Revert the introduction of the gray-500 variable --------- Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: joedolson <joedolson@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/button/style.scss | 53 ++++++++++++++--------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 570b7ac308c5fe..a71b5a0ddef35f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,7 @@ - `ColorPalette`: Remove extra bottom margin when `CircularOptionPicker` is unneeded ([#63961](https://github.com/WordPress/gutenberg/pull/63961)). - `CustomSelectControl`: Restore `describedBy` functionality ([#63957](https://github.com/WordPress/gutenberg/pull/63957)). +- `Button`: Improve the aria-disabled focus style ([#62480](https://github.com/WordPress/gutenberg/pull/62480)). - `Modal`: Fix the dismissal logic for React development mode ([#64132](https://github.com/WordPress/gutenberg/pull/64132)). ### Enhancements diff --git a/packages/components/src/button/style.scss b/packages/components/src/button/style.scss index 3541699a08eefd..fcbd363e17c7dd 100644 --- a/packages/components/src/button/style.scss +++ b/packages/components/src/button/style.scss @@ -30,16 +30,10 @@ } &[aria-expanded="true"], - &:hover { + &:hover:not(:disabled, [aria-disabled="true"]) { color: $components-color-accent; } - // Unset some hovers, instead of adding :not specificity. - &:disabled:hover, - &[aria-disabled="true"]:hover { - color: initial; - } - // Focus. // See https://github.com/WordPress/gutenberg/issues/13267 for more context on these selectors. &:focus:not(:disabled) { @@ -87,7 +81,6 @@ color: rgba($white, 0.4); background: $components-color-accent; border-color: $components-color-accent; - opacity: 1; outline: none; &:focus:enabled { @@ -132,7 +125,6 @@ color: $gray-600; background: transparent; transform: none; - opacity: 1; } } @@ -206,17 +198,22 @@ &:not(.is-primary):not(.is-secondary):not(.is-tertiary):not(.is-link) { color: $alert-red; - &:hover:not(:disabled) { + &:hover:not(:disabled, [aria-disabled="true"]) { color: darken($alert-red, 20%); } - &:focus:not(:disabled) { + &:focus { box-shadow: 0 0 0 var(--wp-admin-border-width-focus) $alert-red; } - &:active:not(:disabled) { + &:active:not(:disabled, [aria-disabled="true"]) { background: $gray-400; } + + &:disabled, + &[aria-disabled="true"] { + color: $gray-600; + } } } @@ -244,6 +241,11 @@ &:focus { border-radius: $radius-block-ui; } + + &:disabled, + &[aria-disabled="true"] { + color: $gray-600; + } } &:not(:disabled, [aria-disabled="true"]):active { @@ -253,7 +255,7 @@ &:disabled, &[aria-disabled="true"] { cursor: default; - opacity: 0.3; + color: $gray-600; } &.is-busy, @@ -266,7 +268,6 @@ @media (prefers-reduced-motion: reduce) { animation-duration: 0s; } - opacity: 1; background-size: 100px 100%; /* stylelint-disable -- Disable reason: This function call looks nicer when each argument is on its own line. */ background-image: linear-gradient( @@ -332,8 +333,23 @@ // Toggled style. &.is-pressed { - color: $components-color-foreground-inverted; - background: $components-color-foreground; + &, + &:hover { + color: $components-color-foreground-inverted; + &:not(:disabled, [aria-disabled="true"]) { + background: $components-color-foreground; + } + } + + &:disabled, + &[aria-disabled="true"] { + color: $gray-600; + + &:not(.is-primary):not(.is-secondary):not(.is-tertiary) { + color: $components-color-foreground-inverted; + background: $gray-600; + } + } &:focus:not(:disabled) { box-shadow: inset 0 0 0 1px $components-color-background, 0 0 0 var(--wp-admin-border-width-focus) $components-color-accent; @@ -341,11 +357,6 @@ // Windows High Contrast mode will show this outline, but not the box-shadow. outline: 2px solid transparent; } - - &:hover:not(:disabled) { - color: $components-color-foreground-inverted; - background: $components-color-foreground; - } } svg { From 8b69df518b1b09d722ce0df89e3bcf2389629274 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:48:10 +1000 Subject: [PATCH 0261/1908] Spacing controls: using CustomSelectControlV2 for >= 8 spacing sizes (#64284) * Exports CustomSelectControlV2 from components private APIs for use in spacing-input-control.js CustomSelectControlV2Legacy was removed in favour of V2 but the spacing input control was not updated. * Log the change * This commit is a version that uses the v1 component to save time later. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: ryelle <ryelle@git.wordpress.org> --- .../input-controls/spacing-input-control.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js index 6605d2de502fe8..4faf05ba254089 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js +++ b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js @@ -9,7 +9,7 @@ import { __experimentalUnitControl as UnitControl, __experimentalUseCustomUnits as useCustomUnits, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, - privateApis as componentsPrivateApis, + CustomSelectControl, } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { useState, useMemo } from '@wordpress/element'; @@ -31,11 +31,6 @@ import { getPresetValueFromCustomValue, isValueSpacingPreset, } from '../utils'; -import { unlock } from '../../../lock-unlock'; - -const { CustomSelectControlV2Legacy: CustomSelectControl } = unlock( - componentsPrivateApis -); const CUSTOM_VALUE_SETTINGS = { px: { max: 300, steps: 1 }, From 8a9ce7f2c25f64ddfe4fedf93dd2fb82022224ba Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Tue, 6 Aug 2024 11:20:41 +0800 Subject: [PATCH 0262/1908] Grid: Unset the rowStart and columnStart attributes when a block is removed from a manual layout (#64186) * Unset the rowStart and columnStart attributes when a block is removed from the grid * Follow the same logic as existing code for unsetting attributes when switching to auto * Add doc block * Unset the `style.layout` attribute when its empty * Also unset columnSpan and rowSpan * Keep span when switching grid types * Remove helper function in favour of `setImmutably` * Try supporting drag and drop from one grid to another * Do nothing when the new parent is a grid, it seems to work better by leaving all attributes in place * Use a mixture of destructuring and setImmutably * Only push attribute update when needed * Fix potentially destructuring non-object * Switch to for of loop ---- Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> --- .../components/grid/use-grid-layout-sync.js | 61 ++++++++++++++++--- 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/grid/use-grid-layout-sync.js b/packages/block-editor/src/components/grid/use-grid-layout-sync.js index 2cc17eed6b33bf..3e31530d4e526f 100644 --- a/packages/block-editor/src/components/grid/use-grid-layout-sync.js +++ b/packages/block-editor/src/components/grid/use-grid-layout-sync.js @@ -10,6 +10,7 @@ import { usePrevious } from '@wordpress/compose'; */ import { store as blockEditorStore } from '../../store'; import { GridRect } from './utils'; +import { setImmutably } from '../../utils/object'; export function useGridLayoutSync( { clientId: gridClientId } ) { const { gridLayout, blockOrder, selectedBlockLayout } = useSelect( @@ -26,7 +27,8 @@ export function useGridLayoutSync( { clientId: gridClientId } ) { [ gridClientId ] ); - const { getBlockAttributes } = useSelect( blockEditorStore ); + const { getBlockAttributes, getBlockRootClientId } = + useSelect( blockEditorStore ); const { updateBlockAttributes, __unstableMarkNextChangeAsNotPersistent } = useDispatch( blockEditorStore ); @@ -40,6 +42,7 @@ export function useGridLayoutSync( { clientId: gridClientId } ) { const previousIsManualPlacement = usePrevious( gridLayout.isManualPlacement ); + const previousBlockOrder = usePrevious( blockOrder ); useEffect( () => { const updates = {}; @@ -123,6 +126,46 @@ export function useGridLayoutSync( { clientId: gridClientId } ) { }, }; } + + // Unset grid layout attributes for blocks removed from the grid. + for ( const clientId of previousBlockOrder ?? [] ) { + if ( ! blockOrder.includes( clientId ) ) { + const rootClientId = getBlockRootClientId( clientId ); + + // Block was removed from the editor, so nothing to do. + if ( rootClientId === null ) { + continue; + } + + // Check if the block is being moved to another grid. + // If so, do nothing and let the new grid parent handle + // the attributes. + const rootAttributes = getBlockAttributes( rootClientId ); + if ( rootAttributes?.layout?.type === 'grid' ) { + continue; + } + + const attributes = getBlockAttributes( clientId ); + const { + columnStart, + rowStart, + columnSpan, + rowSpan, + ...layout + } = attributes.style?.layout ?? {}; + + if ( columnStart || rowStart || columnSpan || rowSpan ) { + const hasEmptyLayoutAttribute = + Object.keys( layout ).length === 0; + + updates[ clientId ] = setImmutably( + attributes, + [ 'style', 'layout' ], + hasEmptyLayoutAttribute ? undefined : layout + ); + } + } + } } else { // Remove all of the columnStart and rowStart values // when switching from manual to auto mode, @@ -133,12 +176,14 @@ export function useGridLayoutSync( { clientId: gridClientId } ) { attributes.style?.layout ?? {}; // Only update attributes if columnStart or rowStart are set. if ( columnStart || rowStart ) { - updates[ clientId ] = { - style: { - ...attributes.style, - layout, - }, - }; + const hasEmptyLayoutAttribute = + Object.keys( layout ).length === 0; + + updates[ clientId ] = setImmutably( + attributes, + [ 'style', 'layout' ], + hasEmptyLayoutAttribute ? undefined : layout + ); } } } @@ -166,12 +211,14 @@ export function useGridLayoutSync( { clientId: gridClientId } ) { // Actual deps to sync: gridClientId, gridLayout, + previousBlockOrder, blockOrder, previouslySelectedBlockRect, previousIsManualPlacement, // These won't change, but the linter thinks they might: __unstableMarkNextChangeAsNotPersistent, getBlockAttributes, + getBlockRootClientId, updateBlockAttributes, ] ); } From f12b78b7c4e830032d7f9a4641df40236644683b Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 6 Aug 2024 17:22:39 +0900 Subject: [PATCH 0263/1908] Drag & Drop: Fix unexpected row/galley creation logic (#64241) * Drag & Drop: Fix unexpected row/galley creation logic * Add comment * Remove function that checks if a row or gallery can be created Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- .../components/use-block-drop-zone/index.js | 80 +++++++++++++++---- .../src/components/use-on-block-drop/index.js | 10 +-- 2 files changed, 67 insertions(+), 23 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 857a132f1f9fa4..415ed5070d28da 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 @@ -301,8 +301,10 @@ export default function useBlockDropZone( { operation: 'insert', } ); - const { getBlockType } = useSelect( blocksStore ); + const { getBlockType, getBlockVariations, getGroupingBlockName } = + useSelect( blocksStore ); const { + canInsertBlockType, getBlockListSettings, getBlocks, getBlockIndex, @@ -310,6 +312,7 @@ export default function useBlockDropZone( { getBlockNamesByClientId, getAllowedBlocks, isDragging, + isGroupable, } = unlock( useSelect( blockEditorStore ) ); const { showInsertionPoint, @@ -385,21 +388,66 @@ export default function useBlockDropZone( { }; } ); + const dropTargetPosition = getDropTargetPosition( + blocksData, + { x: event.clientX, y: event.clientY }, + getBlockListSettings( targetRootClientId )?.orientation, + { + dropZoneElement, + parentBlockClientId, + parentBlockOrientation: parentBlockClientId + ? getBlockListSettings( parentBlockClientId ) + ?.orientation + : undefined, + rootBlockIndex: getBlockIndex( targetRootClientId ), + } + ); + const [ targetIndex, operation, nearestSide ] = - getDropTargetPosition( - blocksData, - { x: event.clientX, y: event.clientY }, - getBlockListSettings( targetRootClientId )?.orientation, - { - dropZoneElement, - parentBlockClientId, - parentBlockOrientation: parentBlockClientId - ? getBlockListSettings( parentBlockClientId ) - ?.orientation - : undefined, - rootBlockIndex: getBlockIndex( targetRootClientId ), - } + dropTargetPosition; + + if ( operation === 'group' ) { + const targetBlock = blocks[ targetIndex ]; + const areAllImages = [ + targetBlock.name, + ...draggedBlockNames, + ].every( ( name ) => name === 'core/image' ); + const canInsertGalleryBlock = canInsertBlockType( + 'core/gallery', + targetRootClientId ); + const areGroupableBlocks = isGroupable( [ + targetBlock.clientId, + getDraggedBlockClientIds(), + ] ); + const groupBlockVariations = getBlockVariations( + getGroupingBlockName(), + 'block' + ); + const canInsertRow = + groupBlockVariations && + groupBlockVariations.find( + ( { name } ) => name === 'group-row' + ); + + // If the dragged blocks and the target block are all images, + // check if it is creatable either a Row variation or a Gallery block. + if ( + areAllImages && + ! canInsertGalleryBlock && + ( ! areGroupableBlocks || ! canInsertRow ) + ) { + return; + } + // If the dragged blocks and the target block are not all images, + // check if it is creatable a Row variation. + if ( + ! areAllImages && + ( ! areGroupableBlocks || ! canInsertRow ) + ) { + return; + } + } registry.batch( () => { setDropTarget( { @@ -436,6 +484,10 @@ export default function useBlockDropZone( { showInsertionPoint, isDragging, startDragging, + canInsertBlockType, + getBlockVariations, + getGroupingBlockName, + isGroupable, ] ), 200 diff --git a/packages/block-editor/src/components/use-on-block-drop/index.js b/packages/block-editor/src/components/use-on-block-drop/index.js index 420cd398edfa39..75b9a44e166f5c 100644 --- a/packages/block-editor/src/components/use-on-block-drop/index.js +++ b/packages/block-editor/src/components/use-on-block-drop/index.js @@ -232,7 +232,6 @@ export default function useOnBlockDrop( getBlocksByClientId, getSettings, getBlock, - isGroupable, } = useSelect( blockEditorStore ); const { getGroupingBlockName } = useSelect( blocksStore ); const { @@ -255,17 +254,11 @@ export default function useOnBlockDrop( if ( ! Array.isArray( blocks ) ) { blocks = [ blocks ]; } - const clientIds = getBlockOrder( targetRootClientId ); const clientId = clientIds[ targetBlockIndex ]; - const blocksClientIds = blocks.map( ( block ) => block.clientId ); - const areGroupableBlocks = isGroupable( [ - ...blocksClientIds, - clientId, - ] ); if ( operation === 'replace' ) { replaceBlocks( clientId, blocks, undefined, initialPosition ); - } else if ( operation === 'group' && areGroupableBlocks ) { + } else if ( operation === 'group' ) { const targetBlock = getBlock( clientId ); if ( nearestSide === 'left' ) { blocks.push( targetBlock ); @@ -325,7 +318,6 @@ export default function useOnBlockDrop( getBlockOrder, targetRootClientId, targetBlockIndex, - isGroupable, operation, replaceBlocks, getBlock, From 690137ecb8f09da84b3b820f7cc1943700397def Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 6 Aug 2024 12:25:43 +0200 Subject: [PATCH 0264/1908] DataViews Actions: Update the copy of some the strings (#64099) Co-authored-by: Pascal Birchler <pascalb@google.com> --- .../actions/permanently-delete-post.tsx | 10 ++++----- .../src/dataviews/actions/trash-post.tsx | 22 +++++++++---------- .../editor/various/change-detection.spec.js | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/editor/src/dataviews/actions/permanently-delete-post.tsx b/packages/editor/src/dataviews/actions/permanently-delete-post.tsx index 42efb8a32850f3..2124fdc0ffa4ce 100644 --- a/packages/editor/src/dataviews/actions/permanently-delete-post.tsx +++ b/packages/editor/src/dataviews/actions/permanently-delete-post.tsx @@ -48,7 +48,7 @@ const permanentlyDeletePost: Action< PostWithPermissions > = { getItemTitle( posts[ 0 ] ) ); } else { - successMessage = __( 'The posts were permanently deleted.' ); + successMessage = __( 'The items were permanently deleted.' ); } createSuccessNotice( successMessage, { type: 'snackbar', @@ -67,7 +67,7 @@ const permanentlyDeletePost: Action< PostWithPermissions > = { errorMessage = typedError.reason.message; } else { errorMessage = __( - 'An error occurred while permanently deleting the post.' + 'An error occurred while permanently deleting the item.' ); } // If we were trying to permanently delete multiple posts @@ -86,13 +86,13 @@ const permanentlyDeletePost: Action< PostWithPermissions > = { } if ( errorMessages.size === 0 ) { errorMessage = __( - 'An error occurred while permanently deleting the posts.' + 'An error occurred while permanently deleting the items.' ); } else if ( errorMessages.size === 1 ) { errorMessage = sprintf( /* translators: %s: an error message */ __( - 'An error occurred while permanently deleting the posts: %s' + 'An error occurred while permanently deleting the items: %s' ), [ ...errorMessages ][ 0 ] ); @@ -100,7 +100,7 @@ const permanentlyDeletePost: Action< PostWithPermissions > = { errorMessage = sprintf( /* translators: %s: a list of comma separated error messages */ __( - 'Some errors occurred while permanently deleting the posts: %s' + 'Some errors occurred while permanently deleting the items: %s' ), [ ...errorMessages ].join( ',' ) ); diff --git a/packages/editor/src/dataviews/actions/trash-post.tsx b/packages/editor/src/dataviews/actions/trash-post.tsx index a8e42c510a6cd0..537a0ebd79a8ac 100644 --- a/packages/editor/src/dataviews/actions/trash-post.tsx +++ b/packages/editor/src/dataviews/actions/trash-post.tsx @@ -23,7 +23,7 @@ import type { CoreDataError, PostWithPermissions } from '../types'; const trashPost: Action< PostWithPermissions > = { id: 'move-to-trash', - label: __( 'Move to Trash' ), + label: __( 'Move to trash' ), isPrimary: true, icon: trash, isEligible( item ) { @@ -51,15 +51,15 @@ const trashPost: Action< PostWithPermissions > = { ? sprintf( // translators: %s: The item's title. __( - 'Are you sure you want to move to trash "%s"?' + 'Are you sure you want to move "%s" to the trash?' ), getItemTitle( items[ 0 ] ) ) : sprintf( // translators: %d: The number of items (2 or more). _n( - 'Are you sure you want to move to trash %d item?', - 'Are you sure you want to move to trash %d items?', + 'Are you sure you want to move %d item to the trash ?', + 'Are you sure you want to move %d items to the trash ?', items.length ), items.length @@ -99,15 +99,15 @@ const trashPost: Action< PostWithPermissions > = { if ( promiseResult.length === 1 ) { successMessage = sprintf( /* translators: The item's title. */ - __( '"%s" moved to trash.' ), + __( '"%s" moved to the trash.' ), getItemTitle( items[ 0 ] ) ); } else { successMessage = sprintf( /* translators: The number of items. */ _n( - '%s item moved to trash.', - '%s items moved to trash.', + '%s item moved to the trash.', + '%s items moved to the trash.', items.length ), items.length @@ -130,7 +130,7 @@ const trashPost: Action< PostWithPermissions > = { typedError.reason.message; } else { errorMessage = __( - 'An error occurred while moving to trash the item.' + 'An error occurred while moving the item to the trash.' ); } // If we were trying to delete multiple items. @@ -151,13 +151,13 @@ const trashPost: Action< PostWithPermissions > = { } if ( errorMessages.size === 0 ) { errorMessage = __( - 'An error occurred while moving to trash the items.' + 'An error occurred while moving the items to the trash.' ); } else if ( errorMessages.size === 1 ) { errorMessage = sprintf( /* translators: %s: an error message */ __( - 'An error occurred while moving to trash the item: %s' + 'An error occurred while moving the item to the trash: %s' ), [ ...errorMessages ][ 0 ] ); @@ -165,7 +165,7 @@ const trashPost: Action< PostWithPermissions > = { errorMessage = sprintf( /* translators: %s: a list of comma separated error messages */ __( - 'Some errors occurred while moving to trash the items: %s' + 'Some errors occurred while moving the items to the trash: %s' ), [ ...errorMessages ].join( ',' ) ); diff --git a/test/e2e/specs/editor/various/change-detection.spec.js b/test/e2e/specs/editor/various/change-detection.spec.js index 4ac262f4c1348d..30b2287a8d9439 100644 --- a/test/e2e/specs/editor/various/change-detection.spec.js +++ b/test/e2e/specs/editor/various/change-detection.spec.js @@ -416,7 +416,7 @@ test.describe( 'Change detection', () => { .click(); await page .getByRole( 'menu' ) - .getByRole( 'menuitem', { name: 'Move to Trash' } ) + .getByRole( 'menuitem', { name: 'Move to trash' } ) .click(); await page .getByRole( 'dialog' ) From 30d82b88850fa277dce0dee6e178d6af5391200f Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:24:47 +0200 Subject: [PATCH 0265/1908] Site Logo: Move tooltip to middle right. (#64296) Unlinked contributors: alaczek. Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> --- packages/block-library/src/site-logo/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index ac74ac2aeb6eb4..b7e47ec542d1e9 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -687,7 +687,7 @@ export default function LogoEdit( { variant="primary" label={ __( 'Choose logo' ) } showTooltip - tooltipPosition="bottom center" + tooltipPosition="middle right" onClick={ () => { open(); } } From 050c58f30ca8b0b5e9ee92da56fdc0e4dfa80b6d Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Tue, 6 Aug 2024 14:29:56 +0300 Subject: [PATCH 0266/1908] Navigation: Hide loading when overlay menu is selected (#64262) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- packages/block-library/src/navigation/edit/index.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js index 5477dc1aeebf3a..829c6395e047ef 100644 --- a/packages/block-library/src/navigation/edit/index.js +++ b/packages/block-library/src/navigation/edit/index.js @@ -721,7 +721,7 @@ function Navigation( { ); const accessibleDescriptionId = `${ clientId }-desc`; - + const isHiddenByDefault = 'always' === overlayMenu; const isManageMenusButtonDisabled = ! hasManagePermissions || ! hasResolvedNavigationMenus; @@ -760,7 +760,7 @@ function Navigation( { hasIcon={ hasIcon } icon={ icon } isResponsive={ isResponsive } - isHiddenByDefault={ 'always' === overlayMenu } + isHiddenByDefault={ isHiddenByDefault } overlayBackgroundColor={ overlayBackgroundColor } overlayTextColor={ overlayTextColor } > @@ -899,13 +899,13 @@ function Navigation( { : undefined } > - { isLoading && ( + { isLoading && ! isHiddenByDefault && ( <div className="wp-block-navigation__loading-indicator-container"> <Spinner className="wp-block-navigation__loading-indicator" /> </div> ) } - { ! isLoading && ( + { ( ! isLoading || isHiddenByDefault ) && ( <> <AccessibleMenuDescription id={ accessibleDescriptionId } @@ -917,7 +917,7 @@ function Navigation( { icon={ icon } isOpen={ isResponsiveMenuOpen } isResponsive={ isResponsive } - isHiddenByDefault={ 'always' === overlayMenu } + isHiddenByDefault={ isHiddenByDefault } overlayBackgroundColor={ overlayBackgroundColor } From 6b0e49864267c70d1eaeb97a801a0a8eff85741f Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Tue, 6 Aug 2024 15:16:30 +0200 Subject: [PATCH 0267/1908] Fix: Deleting a pattern throws a notice saying undefined deleted. (#64301) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> --- packages/editor/src/store/private-actions.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/store/private-actions.js b/packages/editor/src/store/private-actions.js index c5fe1c260071a6..0996d6eb8b9d32 100644 --- a/packages/editor/src/store/private-actions.js +++ b/packages/editor/src/store/private-actions.js @@ -393,10 +393,14 @@ export const removeTemplates = if ( items.length === 1 ) { // Depending on how the entity was retrieved its title might be // an object or simple string. - const title = - typeof items[ 0 ].title === 'string' - ? items[ 0 ].title - : items[ 0 ].title?.rendered; + let title; + if ( typeof items[ 0 ].title === 'string' ) { + title = items[ 0 ].title; + } else if ( typeof items[ 0 ].title?.rendered === 'string' ) { + title = items[ 0 ].title?.rendered; + } else if ( typeof items[ 0 ].title?.raw === 'string' ) { + title = items[ 0 ].title?.raw; + } successMessage = isResetting ? sprintf( /* translators: The template/part's name. */ From a52b95110ae225bbcb6a63af3b8700717ebc7060 Mon Sep 17 00:00:00 2001 From: Ryan Welcher <me@ryanwelcher.com> Date: Tue, 6 Aug 2024 10:05:07 -0400 Subject: [PATCH 0268/1908] Move Posts Per Page, Offset, and Pages controls from the block toolbar into Inspector Controls (#58207) * Add Per Page Controls to the Query Loop block. * Update changelog. * Update the max posts per page to match the toolbar control. * Wrap per page, offset, and max pages controls to Inspector controls inside a ToolsPanel and move them to the Inspector Controls for the block. * Remove per page, offset and pages controls from block toolbar. * Rename ToolsPanel to "Display" * Fix leftover for incorrect dropdownMenuProps value. * Convert RangeControl value to number. * Add missing value checks for perPage, offset, and max pages controls. * Update e2e test * Fix PHPCS * large and minor label tweak * "posts per page" Co-authored-by: ryanwelcher <welcher@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: justintadlock <greenshady@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> * Add __nextHasNoMarginBottom to the Per Page RangeControl component. --------- Co-authored-by: Andrea Fercia <a.fercia@gmail.com> Co-authored-by: George Mamadashvili <georgemamadashvili@gmail.com> Co-authored-by: Rich Tabor <hi@richtabor.com> --- packages/block-library/CHANGELOG.md | 4 + .../query/edit/inspector-controls/index.js | 57 ++++++++++++ .../inspector-controls/offset-controls.js | 31 +++++++ .../edit/inspector-controls/order-control.js | 1 - .../edit/inspector-controls/pages-control.js | 27 ++++++ .../inspector-controls/per-page-control.js | 33 +++++++ .../src/query/edit/query-toolbar.js | 91 +------------------ packages/e2e-tests/plugins/observe-typing.php | 28 ++++++ .../e2e-tests/plugins/observe-typing/index.js | 45 +++++++++ .../specs/editor/various/is-typing.spec.js | 40 ++++---- 10 files changed, 245 insertions(+), 112 deletions(-) create mode 100644 packages/block-library/src/query/edit/inspector-controls/offset-controls.js create mode 100644 packages/block-library/src/query/edit/inspector-controls/pages-control.js create mode 100644 packages/block-library/src/query/edit/inspector-controls/per-page-control.js create mode 100644 packages/e2e-tests/plugins/observe-typing.php create mode 100644 packages/e2e-tests/plugins/observe-typing/index.js diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index 226183e04396ef..652c89fd3540e2 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### New Feature + +- Query Loop Block: Moves per page, offset, and pages controls into Inspector Controls. ([#58207](https://github.com/WordPress/gutenberg/pull/58207)) + ## 9.4.0 (2024-07-24) ## 9.3.0 (2024-07-10) diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index 5e83ea3aaa9730..2601430329092f 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -27,6 +27,9 @@ import { TaxonomyControls } from './taxonomy-controls'; import StickyControl from './sticky-control'; import EnhancedPaginationControl from './enhanced-pagination-control'; import CreateNewPostLink from './create-new-post-link'; +import PerPageControl from './per-page-control'; +import OffsetControl from './offset-controls'; +import PagesControl from './pages-control'; import { unlock } from '../../../lock-unlock'; import { usePostTypes, @@ -47,7 +50,10 @@ export default function QueryInspectorControls( props ) { order, orderBy, author: authorIds, + pages, postType, + perPage, + offset, sticky, inherit, taxQuery, @@ -135,6 +141,16 @@ export default function QueryInspectorControls( props ) { showParentControl; const dropdownMenuProps = useToolsPanelDropdownMenuProps(); + const showPostCountControl = isControlAllowed( + allowedControls, + 'postCount' + ); + const showOffSetControl = isControlAllowed( allowedControls, 'offset' ); + const showPagesControl = isControlAllowed( allowedControls, 'pages' ); + + const showDisplayPanel = + showPostCountControl || showOffSetControl || showPagesControl; + return ( <> { !! postType && ( @@ -253,6 +269,47 @@ export default function QueryInspectorControls( props ) { /> </PanelBody> ) } + { ! inherit && showDisplayPanel && ( + <ToolsPanel + className="block-library-query-toolspanel__display" + label={ __( 'Display' ) } + resetAll={ () => { + setQuery( { + offset: 0, + pages: 0, + } ); + } } + dropdownMenuProps={ dropdownMenuProps } + > + <ToolsPanelItem + label={ __( 'Items' ) } + hasValue={ () => perPage > 0 } + > + <PerPageControl + perPage={ perPage } + offset={ offset } + onChange={ setQuery } + /> + </ToolsPanelItem> + <ToolsPanelItem + label={ __( 'Offset' ) } + hasValue={ () => offset > 0 } + onDeselect={ () => setQuery( { offset: 0 } ) } + > + <OffsetControl + offset={ offset } + onChange={ setQuery } + /> + </ToolsPanelItem> + <ToolsPanelItem + label={ __( 'Max Pages to Show' ) } + hasValue={ () => pages > 0 } + onDeselect={ () => setQuery( { pages: 0 } ) } + > + <PagesControl pages={ pages } onChange={ setQuery } /> + </ToolsPanelItem> + </ToolsPanel> + ) } { ! inherit && showFiltersPanel && ( <ToolsPanel className="block-library-query-toolspanel__filters" // unused but kept for backward compatibility diff --git a/packages/block-library/src/query/edit/inspector-controls/offset-controls.js b/packages/block-library/src/query/edit/inspector-controls/offset-controls.js new file mode 100644 index 00000000000000..ff755c95f8b0a9 --- /dev/null +++ b/packages/block-library/src/query/edit/inspector-controls/offset-controls.js @@ -0,0 +1,31 @@ +/** + * WordPress dependencies + */ +import { __experimentalNumberControl as NumberControl } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +const MIN_OFFSET = 0; +const MAX_OFFSET = 100; + +export const OffsetControl = ( { offset = 0, onChange } ) => { + return ( + <NumberControl + __next40pxDefaultSize + label={ __( 'Offset' ) } + value={ offset } + min={ MIN_OFFSET } + onChange={ ( newOffset ) => { + if ( + isNaN( newOffset ) || + newOffset < MIN_OFFSET || + newOffset > MAX_OFFSET + ) { + return; + } + onChange( { offset: newOffset } ); + } } + /> + ); +}; + +export default OffsetControl; diff --git a/packages/block-library/src/query/edit/inspector-controls/order-control.js b/packages/block-library/src/query/edit/inspector-controls/order-control.js index 2f6fa0e589d473..d50d3349bcbafd 100644 --- a/packages/block-library/src/query/edit/inspector-controls/order-control.js +++ b/packages/block-library/src/query/edit/inspector-controls/order-control.js @@ -27,7 +27,6 @@ const orderOptions = [ function OrderControl( { order, orderBy, onChange } ) { return ( <SelectControl - __nextHasNoMarginBottom __next40pxDefaultSize label={ __( 'Order by' ) } value={ `${ orderBy }/${ order }` } diff --git a/packages/block-library/src/query/edit/inspector-controls/pages-control.js b/packages/block-library/src/query/edit/inspector-controls/pages-control.js new file mode 100644 index 00000000000000..cde61453ea844d --- /dev/null +++ b/packages/block-library/src/query/edit/inspector-controls/pages-control.js @@ -0,0 +1,27 @@ +/** + * WordPress dependencies + */ +import { __experimentalNumberControl as NumberControl } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +export const PagesControl = ( { pages, onChange } ) => { + return ( + <NumberControl + __next40pxDefaultSize + label={ __( 'Max pages' ) } + value={ pages } + min={ 0 } + onChange={ ( newPages ) => { + if ( isNaN( newPages ) || newPages < 0 ) { + return; + } + onChange( { pages: newPages } ); + } } + help={ __( + 'Limit the pages you want to show, even if the query has more results. To show all pages use 0 (zero).' + ) } + /> + ); +}; + +export default PagesControl; diff --git a/packages/block-library/src/query/edit/inspector-controls/per-page-control.js b/packages/block-library/src/query/edit/inspector-controls/per-page-control.js new file mode 100644 index 00000000000000..3e0dfbf50b70bd --- /dev/null +++ b/packages/block-library/src/query/edit/inspector-controls/per-page-control.js @@ -0,0 +1,33 @@ +/** + * WordPress dependencies + */ +import { RangeControl } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +const MIN_POSTS_PER_PAGE = 1; +const MAX_POSTS_PER_PAGE = 100; + +const PerPageControl = ( { perPage, offset = 0, onChange } ) => { + return ( + <RangeControl + __next40pxDefaultSize + __nextHasNoMarginBottom + label={ __( 'Posts per page' ) } + min={ MIN_POSTS_PER_PAGE } + max={ MAX_POSTS_PER_PAGE } + onChange={ ( newPerPage ) => { + if ( + isNaN( newPerPage ) || + newPerPage < MIN_POSTS_PER_PAGE || + newPerPage > MAX_POSTS_PER_PAGE + ) { + return; + } + onChange( { perPage: newPerPage, offset } ); + } } + value={ parseInt( perPage, 10 ) } + /> + ); +}; + +export default PerPageControl; diff --git a/packages/block-library/src/query/edit/query-toolbar.js b/packages/block-library/src/query/edit/query-toolbar.js index ff670d7c001a6b..cc2d62a54d529f 100644 --- a/packages/block-library/src/query/edit/query-toolbar.js +++ b/packages/block-library/src/query/edit/query-toolbar.js @@ -1,14 +1,8 @@ /** * WordPress dependencies */ -import { - ToolbarGroup, - Dropdown, - ToolbarButton, - __experimentalNumberControl as NumberControl, -} from '@wordpress/components'; +import { ToolbarGroup, ToolbarButton } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { settings } from '@wordpress/icons'; /** * Internal dependencies @@ -16,8 +10,6 @@ import { settings } from '@wordpress/icons'; import { usePatterns } from '../utils'; export default function QueryToolbar( { - attributes: { query }, - setQuery, openPatternSelectionModal, name, clientId, @@ -26,87 +18,6 @@ export default function QueryToolbar( { return ( <> - { ! query.inherit && ( - <ToolbarGroup> - <Dropdown - contentClassName="block-library-query-toolbar__popover" - renderToggle={ ( { onToggle } ) => ( - <ToolbarButton - icon={ settings } - label={ __( 'Display settings' ) } - onClick={ onToggle } - /> - ) } - renderContent={ () => ( - <> - <NumberControl - __unstableInputWidth="60px" - className="block-library-query-toolbar__popover-number-control" - label={ __( 'Items per Page' ) } - labelPosition="edge" - min={ 1 } - max={ 100 } - onChange={ ( value ) => { - if ( - isNaN( value ) || - value < 1 || - value > 100 - ) { - return; - } - setQuery( { - perPage: value, - } ); - } } - step="1" - value={ query.perPage } - isDragEnabled={ false } - /> - <NumberControl - __unstableInputWidth="60px" - className="block-library-query-toolbar__popover-number-control" - label={ __( 'Offset' ) } - labelPosition="edge" - min={ 0 } - max={ 100 } - onChange={ ( value ) => { - if ( - isNaN( value ) || - value < 0 || - value > 100 - ) { - return; - } - setQuery( { offset: value } ); - } } - step="1" - value={ query.offset } - isDragEnabled={ false } - /> - <NumberControl - __unstableInputWidth="60px" - className="block-library-query-toolbar__popover-number-control" - label={ __( 'Max pages to show' ) } - labelPosition="edge" - min={ 0 } - onChange={ ( value ) => { - if ( isNaN( value ) || value < 0 ) { - return; - } - setQuery( { pages: value } ); - } } - step="1" - value={ query.pages } - isDragEnabled={ false } - help={ __( - 'Limit the pages you want to show, even if the query has more results. To show all pages use 0 (zero).' - ) } - /> - </> - ) } - /> - </ToolbarGroup> - ) } { hasPatterns && ( <ToolbarGroup className="wp-block-template-part__block-control-group"> <ToolbarButton onClick={ openPatternSelectionModal }> diff --git a/packages/e2e-tests/plugins/observe-typing.php b/packages/e2e-tests/plugins/observe-typing.php new file mode 100644 index 00000000000000..a9152bc79684c5 --- /dev/null +++ b/packages/e2e-tests/plugins/observe-typing.php @@ -0,0 +1,28 @@ +<?php +/** + * Plugin Name: Gutenberg Test Observe Typing + * Plugin URI: https://github.com/WordPress/gutenberg + * Author: Gutenberg Team + * + * @package gutenberg-test-block-api + */ + +/** + * Registers a custom script for the plugin. + */ +function enqueue_observe_typing_plugin_script() { + wp_enqueue_script( + 'gutenberg-test-observe-typing', + plugins_url( 'observe-typing/index.js', __FILE__ ), + array( + 'wp-blocks', + 'wp-block-editor', + 'wp-components', + 'wp-element', + ), + filemtime( plugin_dir_path( __FILE__ ) . 'observe-typing/index.js' ), + true + ); +} + +add_action( 'init', 'enqueue_observe_typing_plugin_script' ); diff --git a/packages/e2e-tests/plugins/observe-typing/index.js b/packages/e2e-tests/plugins/observe-typing/index.js new file mode 100644 index 00000000000000..fbfb6a5de757d9 --- /dev/null +++ b/packages/e2e-tests/plugins/observe-typing/index.js @@ -0,0 +1,45 @@ +( function () { + const { registerBlockType } = wp.blocks; + const { useBlockProps, BlockControls } = wp.blockEditor; + const { Dropdown, ToolbarButton, TextControl } = wp.components; + const { createElement: el, useState } = wp.element; + + registerBlockType( 'e2e-tests/observe-typing', { + apiVersion: 3, + title: 'Observe Typing', + description: 'Observe Typing test block.', + category: 'widgets', + edit: function Edit() { + const [ value, setValue ] = useState( '' ); + const blockProps = useBlockProps(); + + return el( + 'div', + blockProps, + el( + BlockControls, + { group: 'block' }, + el( Dropdown, { + renderToggle: ( { onToggle } ) => + el( + ToolbarButton, + { + onClick: onToggle, + }, + 'Open Dropdown' + ), + renderContent: () => + el( TextControl, { + label: 'Dropdown field', + value, + onChange: setValue, + __next40pxDefaultSize: true, + } ), + } ) + ), + el( 'p', {}, 'Hello Editor!' ) + ); + }, + save: () => null, + } ); +} )(); diff --git a/test/e2e/specs/editor/various/is-typing.spec.js b/test/e2e/specs/editor/various/is-typing.spec.js index 10ac90d1084127..da4492a89bef34 100644 --- a/test/e2e/specs/editor/various/is-typing.spec.js +++ b/test/e2e/specs/editor/various/is-typing.spec.js @@ -4,10 +4,18 @@ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); test.describe( 'isTyping', () => { + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activatePlugin( 'gutenberg-test-observe-typing' ); + } ); + test.beforeEach( async ( { admin } ) => { await admin.createNewPost(); } ); + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.deactivatePlugin( 'gutenberg-test-observe-typing' ); + } ); + test( 'should hide the toolbar when typing', async ( { editor, page } ) => { // Enter to reach paragraph block. await page.keyboard.press( 'Enter' ); @@ -42,33 +50,23 @@ test.describe( 'isTyping', () => { page, } ) => { // Add a block with a dropdown in the toolbar that contains an input. - await editor.insertBlock( { name: 'core/query' } ); - - await editor.canvas - .getByRole( 'document', { name: 'Block: Query Loop' } ) - .getByRole( 'button', { name: 'Start blank' } ) - .click(); - - await editor.canvas - .getByRole( 'button', { name: 'Title & Date' } ) - .click(); - - await editor.openDocumentSettingsSidebar(); - await page.getByLabel( 'Custom' ).click(); + await editor.insertBlock( { name: 'e2e-tests/observe-typing' } ); // Moving the mouse shows the toolbar. await editor.showBlockToolbar(); // Open the dropdown. - const displaySettings = page.getByRole( 'button', { - name: 'Display settings', + await page + .getByRole( 'button', { + name: 'Open Dropdown', + } ) + .click(); + + const textControl = page.getByRole( 'textbox', { + name: 'Dropdown field', } ); - await displaySettings.click(); - const itemsPerPageInput = page.getByLabel( 'Items per Page' ); - // Make sure we're where we think we are - await expect( itemsPerPageInput ).toBeFocused(); // Type inside the dropdown's input - await page.keyboard.type( '00' ); + await textControl.pressSequentially( 'Hello' ); // The input should still be visible. - await expect( itemsPerPageInput ).toBeVisible(); + await expect( textControl ).toBeVisible(); } ); } ); From 8b5cdba185ca9e65847d4db6172b71a9c63332ba Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 6 Aug 2024 23:51:50 +0900 Subject: [PATCH 0269/1908] FontFamilyControl: Deprecate bottom margin (#64280) * FontFamilyControl: Deprecate bottom margin * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/block-editor/CHANGELOG.md | 4 ++ .../src/components/font-family/README.md | 8 +++ .../src/components/font-family/index.js | 16 ++++++ .../font-family/stories/index.story.js | 54 +++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 packages/block-editor/src/components/font-family/stories/index.story.js diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 11cc15c15f0b05..9744b5240d0041 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- `FontFamilyControl`: Add `__nextHasNoMarginBottom` prop for opting into the new margin-free styles ([#64280](https://github.com/WordPress/gutenberg/pull/64280)). + ## 13.4.0 (2024-07-24) ## 13.3.0 (2024-07-10) diff --git a/packages/block-editor/src/components/font-family/README.md b/packages/block-editor/src/components/font-family/README.md index 5300873ab83459..6b37459fd127e7 100644 --- a/packages/block-editor/src/components/font-family/README.md +++ b/packages/block-editor/src/components/font-family/README.md @@ -24,6 +24,7 @@ const MyFontFamilyControl = () => { onChange={ ( newFontFamily ) => { setFontFamily( newFontFamily ); } } + __nextHasNoMarginBottom /> ); }; @@ -69,3 +70,10 @@ The current font family value. - Default: '' The rest of the props are passed down to the underlying `<SelectControl />` instance. + +#### `__nextHasNoMarginBottom` + +- **Type:** `boolean` +- **Default:** `false` + +Start opting into the new margin-free styles that will become the default in a future version. diff --git a/packages/block-editor/src/components/font-family/index.js b/packages/block-editor/src/components/font-family/index.js index 4a40a880e537cb..90a0412463b3ef 100644 --- a/packages/block-editor/src/components/font-family/index.js +++ b/packages/block-editor/src/components/font-family/index.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { SelectControl } from '@wordpress/components'; +import deprecated from '@wordpress/deprecated'; import { __ } from '@wordpress/i18n'; /** @@ -10,6 +11,8 @@ import { __ } from '@wordpress/i18n'; import { useSettings } from '../use-settings'; export default function FontFamilyControl( { + /** Start opting into the new margin-free styles that will become the default in a future version. */ + __nextHasNoMarginBottom = false, value = '', onChange, fontFamilies, @@ -33,8 +36,21 @@ export default function FontFamilyControl( { }; } ), ]; + + if ( ! __nextHasNoMarginBottom ) { + deprecated( + 'Bottom margin styles for wp.blockEditor.FontFamilyControl', + { + since: '6.7', + version: '7.0', + hint: 'Set the `__nextHasNoMarginBottom` prop to true to start opting into the new styles, which will become the default in a future version', + } + ); + } + return ( <SelectControl + __nextHasNoMarginBottom={ __nextHasNoMarginBottom } label={ __( 'Font' ) } options={ options } value={ value } diff --git a/packages/block-editor/src/components/font-family/stories/index.story.js b/packages/block-editor/src/components/font-family/stories/index.story.js new file mode 100644 index 00000000000000..54dadeb213f12c --- /dev/null +++ b/packages/block-editor/src/components/font-family/stories/index.story.js @@ -0,0 +1,54 @@ +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import FontFamilyControl from '..'; + +export default { + component: FontFamilyControl, + title: 'BlockEditor/FontFamilyControl', +}; + +export const Default = { + render: function Template( props ) { + const [ value, setValue ] = useState(); + return ( + <FontFamilyControl + onChange={ setValue } + value={ value } + { ...props } + /> + ); + }, + args: { + fontFamilies: [ + { + fontFace: [ + { + fontFamily: 'Inter', + fontStretch: 'normal', + fontStyle: 'normal', + fontWeight: '200 900', + src: [ + 'file:./assets/fonts/inter/Inter-VariableFont_slnt,wght.ttf', + ], + }, + ], + fontFamily: '"Inter", sans-serif', + name: 'Inter', + slug: 'inter', + }, + { + fontFamily: + '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif', + name: 'System Font', + slug: 'system-font', + }, + ], + __nextHasNoMarginBottom: true, + }, +}; From fa98fb5035174aeace799068171d2a59ce7ee1e8 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Tue, 6 Aug 2024 17:01:51 +0200 Subject: [PATCH 0270/1908] Try: 1.5px styles icon circle. (#64187) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/icons/src/library/styles.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/icons/src/library/styles.js b/packages/icons/src/library/styles.js index c91683d55dce18..7d3568e43fd171 100644 --- a/packages/icons/src/library/styles.js +++ b/packages/icons/src/library/styles.js @@ -5,7 +5,11 @@ import { Path, SVG } from '@wordpress/primitives'; export const styles = ( <SVG viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> - <Path d="M12 4c-4.4 0-8 3.6-8 8v.1c0 4.1 3.2 7.5 7.2 7.9h.8c4.4 0 8-3.6 8-8s-3.6-8-8-8zm0 15V5c3.9 0 7 3.1 7 7s-3.1 7-7 7z" /> + <Path + fillRule="evenodd" + clipRule="evenodd" + d="M20 12a8 8 0 1 1-16 0 8 8 0 0 1 16 0Zm-1.5 0a6.5 6.5 0 0 1-6.5 6.5v-13a6.5 6.5 0 0 1 6.5 6.5Z" + /> </SVG> ); From cd0118f623cf0c3b155ed18d30f0949a4f308b70 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 7 Aug 2024 00:59:30 +0900 Subject: [PATCH 0271/1908] LineHeightControl: Hard deprecate bottom margin (#64281) * LineHeightControl: Hard deprecate bottom margin * Remove prop usage in app * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/block-editor/CHANGELOG.md | 4 ++++ .../global-styles/typography-panel.js | 1 - .../components/line-height-control/README.md | 8 ------- .../components/line-height-control/index.js | 22 +------------------ .../stories/index.story.js | 1 - .../line-height-control/test/index.js | 8 +------ .../block-editor/src/hooks/line-height.js | 1 - 7 files changed, 6 insertions(+), 39 deletions(-) diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 9744b5240d0041..5ba19b090d9258 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- `LineHeightControl`: Remove deprecated `__nextHasNoMarginBottom` prop and promote to default behavior ([#64281](https://github.com/WordPress/gutenberg/pull/64281)). + ### Enhancements - `FontFamilyControl`: Add `__nextHasNoMarginBottom` prop for opting into the new margin-free styles ([#64280](https://github.com/WordPress/gutenberg/pull/64280)). diff --git a/packages/block-editor/src/components/global-styles/typography-panel.js b/packages/block-editor/src/components/global-styles/typography-panel.js index f6a389a5bc96d9..9bc875cdc0a308 100644 --- a/packages/block-editor/src/components/global-styles/typography-panel.js +++ b/packages/block-editor/src/components/global-styles/typography-panel.js @@ -474,7 +474,6 @@ export default function TypographyPanel( { panelId={ panelId } > <LineHeightControl - __nextHasNoMarginBottom __unstableInputWidth="auto" value={ lineHeight } onChange={ setLineHeight } diff --git a/packages/block-editor/src/components/line-height-control/README.md b/packages/block-editor/src/components/line-height-control/README.md index 38ab5c3f779a77..dafad9145022b9 100644 --- a/packages/block-editor/src/components/line-height-control/README.md +++ b/packages/block-editor/src/components/line-height-control/README.md @@ -18,7 +18,6 @@ const MyLineHeightControl = () => ( <LineHeightControl value={ lineHeight } onChange={ onChange } - __nextHasNoMarginBottom={ true } /> ); ``` @@ -37,13 +36,6 @@ The value of the line height. A callback function that handles the application of the line height value. -#### `__nextHasNoMarginBottom` - -- **Type:** `boolean` -- **Default:** `false` - -Start opting into the new margin-free styles that will become the default in a future version, currently scheduled to be WordPress 6.4. (The prop can be safely removed once this happens.) - ## Related components Block Editor components are components that can be used to compose the UI of your block editor. Thus, they can only be used under a [`BlockEditorProvider`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/provider/README.md) in the components tree. diff --git a/packages/block-editor/src/components/line-height-control/index.js b/packages/block-editor/src/components/line-height-control/index.js index 8150c2d60027e4..d605aea3d2ef18 100644 --- a/packages/block-editor/src/components/line-height-control/index.js +++ b/packages/block-editor/src/components/line-height-control/index.js @@ -1,7 +1,6 @@ /** * WordPress dependencies */ -import deprecated from '@wordpress/deprecated'; import { __ } from '@wordpress/i18n'; import { __experimentalNumberControl as NumberControl } from '@wordpress/components'; @@ -19,8 +18,6 @@ import { const LineHeightControl = ( { value: lineHeight, onChange, - /** Start opting into the new margin-free styles that will become the default in a future version. */ - __nextHasNoMarginBottom = false, __unstableInputWidth = '60px', ...otherProps } ) => { @@ -76,20 +73,6 @@ const LineHeightControl = ( { const value = isDefined ? lineHeight : RESET_VALUE; - if ( ! __nextHasNoMarginBottom ) { - deprecated( - 'Bottom margin styles for wp.blockEditor.LineHeightControl', - { - since: '6.0', - version: '6.4', - hint: 'Set the `__nextHasNoMarginBottom` prop to true to start opting into the new styles, which will become the default in a future version', - } - ); - } - const deprecatedStyles = __nextHasNoMarginBottom - ? undefined - : { marginBottom: 24 }; - const handleOnChange = ( nextValue, { event } ) => { if ( nextValue === '' ) { onChange(); @@ -105,10 +88,7 @@ const LineHeightControl = ( { }; return ( - <div - className="block-editor-line-height-control" - style={ deprecatedStyles } - > + <div className="block-editor-line-height-control"> <NumberControl { ...otherProps } __unstableInputWidth={ __unstableInputWidth } diff --git a/packages/block-editor/src/components/line-height-control/stories/index.story.js b/packages/block-editor/src/components/line-height-control/stories/index.story.js index 76da83304d4890..6d26fe2220fd23 100644 --- a/packages/block-editor/src/components/line-height-control/stories/index.story.js +++ b/packages/block-editor/src/components/line-height-control/stories/index.story.js @@ -22,7 +22,6 @@ const Template = ( props ) => { export const Default = Template.bind( {} ); Default.args = { - __nextHasNoMarginBottom: true, __unstableInputWidth: '100px', }; diff --git a/packages/block-editor/src/components/line-height-control/test/index.js b/packages/block-editor/src/components/line-height-control/test/index.js index 7a101219f2f827..b98bc93c48a83a 100644 --- a/packages/block-editor/src/components/line-height-control/test/index.js +++ b/packages/block-editor/src/components/line-height-control/test/index.js @@ -19,13 +19,7 @@ const SPIN = STEP * SPIN_FACTOR; const ControlledLineHeightControl = () => { const [ value, setValue ] = useState(); - return ( - <LineHeightControl - value={ value } - onChange={ setValue } - __nextHasNoMarginBottom - /> - ); + return <LineHeightControl value={ value } onChange={ setValue } />; }; describe( 'LineHeightControl', () => { diff --git a/packages/block-editor/src/hooks/line-height.js b/packages/block-editor/src/hooks/line-height.js index fc8bd194c1210c..9c27b9d0269722 100644 --- a/packages/block-editor/src/hooks/line-height.js +++ b/packages/block-editor/src/hooks/line-height.js @@ -39,7 +39,6 @@ export function LineHeightEdit( props ) { return ( <LineHeightControl __unstableInputWidth="100%" - __nextHasNoMarginBottom value={ style?.typography?.lineHeight } onChange={ onChange } size="__unstable-large" From a03615d5ff315b4ff99c3ba88c20f64b45ea2d00 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 7 Aug 2024 02:03:37 +0900 Subject: [PATCH 0272/1908] URLInput: Hard deprecate bottom margin (#64282) * URLInput: Add story * URLInput: Hard deprecate bottom margin * Add changelog * Remove story Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/block-editor/CHANGELOG.md | 1 + .../src/components/link-control/search-input.js | 1 - .../src/components/url-input/README.md | 5 ----- .../src/components/url-input/button.js | 1 - .../src/components/url-input/index.js | 16 +--------------- .../src/components/url-popover/link-editor.js | 1 - packages/block-library/src/social-link/edit.js | 1 - 7 files changed, 2 insertions(+), 24 deletions(-) diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 5ba19b090d9258..bc7d1b88bc9b0a 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -4,6 +4,7 @@ ### Breaking Changes +- `URLInput`: Remove deprecated `__nextHasNoMarginBottom` prop and promote to default behavior ([#64282](https://github.com/WordPress/gutenberg/pull/64282)). - `LineHeightControl`: Remove deprecated `__nextHasNoMarginBottom` prop and promote to default behavior ([#64281](https://github.com/WordPress/gutenberg/pull/64281)). ### Enhancements diff --git a/packages/block-editor/src/components/link-control/search-input.js b/packages/block-editor/src/components/link-control/search-input.js index 78730463389e26..3a5dcd4148e951 100644 --- a/packages/block-editor/src/components/link-control/search-input.js +++ b/packages/block-editor/src/components/link-control/search-input.js @@ -119,7 +119,6 @@ const LinkControlSearchInput = forwardRef( <div className="block-editor-link-control__search-input-container"> <URLInput disableSuggestions={ currentLink?.url === value } - __nextHasNoMarginBottom label={ __( 'Link' ) } hideLabelFromVision={ hideLabelFromVision } className={ className } diff --git a/packages/block-editor/src/components/url-input/README.md b/packages/block-editor/src/components/url-input/README.md index 9d3e340371a608..714f7f062990f6 100644 --- a/packages/block-editor/src/components/url-input/README.md +++ b/packages/block-editor/src/components/url-input/README.md @@ -130,10 +130,6 @@ When hiding the URLInput using CSS (as is sometimes done for accessibility purpo This prop allows the suggestions list to be programmatically not rendered by passing a boolean—it can be `true` to make sure suggestions aren't rendered, or `false`/`undefined` to fall back to the default behaviour of showing suggestions when matching autocompletion items are found. -### `__nextHasNoMarginBottom: Boolean` - -Start opting into the new margin-free styles that will become the default in a future version, currently scheduled to be WordPress 6.4. (The prop can be safely removed once this happens.) - ## Example @@ -156,7 +152,6 @@ registerBlockType( /* ... */, { edit( { className, attributes, setAttributes } ) { return ( <URLInput - __nextHasNoMarginBottom className={ className } value={ attributes.url } onChange={ ( url, post ) => setAttributes( { url, text: (post && post.title) || 'Click here' } ) } diff --git a/packages/block-editor/src/components/url-input/button.js b/packages/block-editor/src/components/url-input/button.js index fca054993e7c3c..6ee6b96f61e0e1 100644 --- a/packages/block-editor/src/components/url-input/button.js +++ b/packages/block-editor/src/components/url-input/button.js @@ -57,7 +57,6 @@ class URLInputButton extends Component { onClick={ this.toggle } /> <URLInput - __nextHasNoMarginBottom value={ url || '' } onChange={ onChange } /> diff --git a/packages/block-editor/src/components/url-input/index.js b/packages/block-editor/src/components/url-input/index.js index 36e279f94cc799..8360bfada853c6 100644 --- a/packages/block-editor/src/components/url-input/index.js +++ b/packages/block-editor/src/components/url-input/index.js @@ -6,7 +6,6 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import deprecated from '@wordpress/deprecated'; import { __, sprintf, _n } from '@wordpress/i18n'; import { Component, createRef } from '@wordpress/element'; import { UP, DOWN, ENTER, TAB } from '@wordpress/keycodes'; @@ -416,8 +415,6 @@ class URLInput extends Component { renderControl() { const { - /** Start opting into the new margin-free styles that will become the default in a future version. */ - __nextHasNoMarginBottom = false, label = null, className, isFullWidth, @@ -473,19 +470,8 @@ class URLInput extends Component { return renderControl( controlProps, inputProps, loading ); } - if ( ! __nextHasNoMarginBottom ) { - deprecated( 'Bottom margin styles for wp.blockEditor.URLInput', { - since: '6.2', - version: '6.5', - hint: 'Set the `__nextHasNoMarginBottom` prop to true to start opting into the new styles, which will become the default in a future version', - } ); - } - return ( - <BaseControl - __nextHasNoMarginBottom={ __nextHasNoMarginBottom } - { ...controlProps } - > + <BaseControl __nextHasNoMarginBottom { ...controlProps }> <input { ...inputProps } /> { loading && <Spinner /> } </BaseControl> diff --git a/packages/block-editor/src/components/url-popover/link-editor.js b/packages/block-editor/src/components/url-popover/link-editor.js index dc9d6d45590d3d..e7d39eed764b84 100644 --- a/packages/block-editor/src/components/url-popover/link-editor.js +++ b/packages/block-editor/src/components/url-popover/link-editor.js @@ -31,7 +31,6 @@ export default function LinkEditor( { { ...props } > <URLInput - __nextHasNoMarginBottom value={ value } onChange={ onChangeInputValue } autocompleteRef={ autocompleteRef } diff --git a/packages/block-library/src/social-link/edit.js b/packages/block-library/src/social-link/edit.js index 6afcedfd763569..8f372a73ea6c9d 100644 --- a/packages/block-library/src/social-link/edit.js +++ b/packages/block-library/src/social-link/edit.js @@ -58,7 +58,6 @@ const SocialLinkURLPopover = ( { > <div className="block-editor-url-input"> <URLInput - __nextHasNoMarginBottom value={ url } onChange={ ( nextURL ) => setAttributes( { url: nextURL } ) From 4efb352e8b3e84daf69d02209d45cc000c4a2efa Mon Sep 17 00:00:00 2001 From: Ryan Welcher <me@ryanwelcher.com> Date: Tue, 6 Aug 2024 15:45:58 -0400 Subject: [PATCH 0273/1908] Update data-core.md (#64309) Fix heading level causing issues with sidebar menu --- docs/reference-guides/data/data-core.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference-guides/data/data-core.md b/docs/reference-guides/data/data-core.md index f4138c49dc8d6b..f08fbc960b8b28 100644 --- a/docs/reference-guides/data/data-core.md +++ b/docs/reference-guides/data/data-core.md @@ -2,7 +2,7 @@ Namespace: `core`. -### Dynamically generated selectors +## Dynamically generated selectors There are a number of user-friendly selectors that are wrappers of the more generic `getEntityRecord` and `getEntityRecords` that can be used to retrieve information for the various entities. From 0f81a4262f394139b411035b4db3a29c938b0947 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 7 Aug 2024 05:57:06 +0900 Subject: [PATCH 0274/1908] Add margin-bottom lint rules for ToggleControl (#64213) * Fix in ImageSettingsPanel * Fix in block hooks * Fix in Avatar block * Fix in Details block * Fix in Latest posts block * Fix in Query Loop block * Fix in Tag Cloud block * Fix in Add New Pattern modal * Fix in Create pattern modal * Fix in ReusableBlockConvertButton * Add eslint rule * Add prop to docs * Fix up Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .eslintrc.js | 1 + .../src/components/global-styles/image-settings-panel.js | 1 + packages/block-editor/src/hooks/block-hooks.js | 1 + packages/block-library/src/avatar/edit.js | 1 + packages/block-library/src/details/edit.js | 1 + packages/block-library/src/latest-posts/edit.js | 1 + .../inspector-controls/enhanced-pagination-control.js | 1 + packages/block-library/src/tag-cloud/edit.js | 1 + packages/components/src/toggle-control/README.md | 9 +++++++++ packages/components/src/toggle-control/index.tsx | 1 + .../edit-post/src/components/init-pattern-modal/index.js | 1 + packages/patterns/src/components/create-pattern-modal.js | 1 + .../reusable-block-convert-button.js | 1 + 13 files changed, 21 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index 97c9f395194f35..cb132fbb3d7aba 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -297,6 +297,7 @@ module.exports = { 'SearchControl', 'TextControl', 'TextareaControl', + 'ToggleControl', 'ToggleGroupControl', 'TreeSelect', ].map( ( componentName ) => ( { diff --git a/packages/block-editor/src/components/global-styles/image-settings-panel.js b/packages/block-editor/src/components/global-styles/image-settings-panel.js index f668e7e5efc244..4ebc20ab201983 100644 --- a/packages/block-editor/src/components/global-styles/image-settings-panel.js +++ b/packages/block-editor/src/components/global-styles/image-settings-panel.js @@ -67,6 +67,7 @@ export default function ImageSettingsPanel( { panelId={ panelId } > <ToggleControl + __nextHasNoMarginBottom label={ __( 'Expand on click' ) } checked={ lightboxChecked } onChange={ onChangeLightbox } diff --git a/packages/block-editor/src/hooks/block-hooks.js b/packages/block-editor/src/hooks/block-hooks.js index 04cd6d4cfc0233..b1fab1b124f8dc 100644 --- a/packages/block-editor/src/hooks/block-hooks.js +++ b/packages/block-editor/src/hooks/block-hooks.js @@ -201,6 +201,7 @@ function BlockHooksControlPure( { return ( <ToggleControl + __nextHasNoMarginBottom checked={ checked } key={ block.title } label={ diff --git a/packages/block-library/src/avatar/edit.js b/packages/block-library/src/avatar/edit.js index 4fad0fb09f883b..8309bc5e878a0e 100644 --- a/packages/block-library/src/avatar/edit.js +++ b/packages/block-library/src/avatar/edit.js @@ -58,6 +58,7 @@ const AvatarInspectorControls = ( { /> { attributes.isLink && ( <ToggleControl + __nextHasNoMarginBottom label={ __( 'Open in new tab' ) } onChange={ ( value ) => setAttributes( { diff --git a/packages/block-library/src/details/edit.js b/packages/block-library/src/details/edit.js index 3432c00d7ab0c5..314556ba6d5919 100644 --- a/packages/block-library/src/details/edit.js +++ b/packages/block-library/src/details/edit.js @@ -48,6 +48,7 @@ function DetailsEdit( { attributes, setAttributes, clientId } ) { <InspectorControls> <PanelBody title={ __( 'Settings' ) }> <ToggleControl + __nextHasNoMarginBottom label={ __( 'Open by default' ) } checked={ showContent } onChange={ () => diff --git a/packages/block-library/src/latest-posts/edit.js b/packages/block-library/src/latest-posts/edit.js index ce8f75c671c833..49a24b08f68d77 100644 --- a/packages/block-library/src/latest-posts/edit.js +++ b/packages/block-library/src/latest-posts/edit.js @@ -202,6 +202,7 @@ export default function LatestPostsEdit( { attributes, setAttributes } ) { <InspectorControls> <PanelBody title={ __( 'Post content' ) }> <ToggleControl + __nextHasNoMarginBottom label={ __( 'Post content' ) } checked={ displayPostContent } onChange={ ( value ) => diff --git a/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js b/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js index 293baead3f5c62..e1001cda4dab39 100644 --- a/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js +++ b/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js @@ -36,6 +36,7 @@ export default function EnhancedPaginationControl( { return ( <> <ToggleControl + __nextHasNoMarginBottom label={ __( 'Force page reload' ) } help={ help } checked={ diff --git a/packages/block-library/src/tag-cloud/edit.js b/packages/block-library/src/tag-cloud/edit.js index 17ca150bc4d75f..9a2b531b30f8ab 100644 --- a/packages/block-library/src/tag-cloud/edit.js +++ b/packages/block-library/src/tag-cloud/edit.js @@ -169,6 +169,7 @@ function TagCloudEdit( { attributes, setAttributes } ) { required /> <ToggleControl + __nextHasNoMarginBottom label={ __( 'Show tag counts' ) } checked={ showTagCounts } onChange={ () => diff --git a/packages/components/src/toggle-control/README.md b/packages/components/src/toggle-control/README.md index 3a77ef6942d2e5..cf480360265ed4 100644 --- a/packages/components/src/toggle-control/README.md +++ b/packages/components/src/toggle-control/README.md @@ -15,6 +15,7 @@ const MyToggleControl = () => { return ( <ToggleControl + __nextHasNoMarginBottom label="Fixed Background" help={ hasFixedBackground @@ -78,3 +79,11 @@ The class that will be added with `components-base-control` and `components-togg - Type: `String` - Required: No + +### `__nextHasNoMarginBottom` + +Start opting into the new margin-free styles that will become the default in a future version. + +- Type: `Boolean` +- Required: No +- Default: `false` diff --git a/packages/components/src/toggle-control/index.tsx b/packages/components/src/toggle-control/index.tsx index 2c405352ab215f..5c64d57d3d0249 100644 --- a/packages/components/src/toggle-control/index.tsx +++ b/packages/components/src/toggle-control/index.tsx @@ -113,6 +113,7 @@ function UnforwardedToggleControl( * * return ( * <ToggleControl + * __nextHasNoMarginBottom * label="Fixed Background" * checked={ value } * onChange={ () => setValue( ( state ) => ! state ) } diff --git a/packages/edit-post/src/components/init-pattern-modal/index.js b/packages/edit-post/src/components/init-pattern-modal/index.js index a40ffc5dc58562..bb448953364f05 100644 --- a/packages/edit-post/src/components/init-pattern-modal/index.js +++ b/packages/edit-post/src/components/init-pattern-modal/index.js @@ -74,6 +74,7 @@ export default function InitPatternModal() { __next40pxDefaultSize /> <ToggleControl + __nextHasNoMarginBottom label={ _x( 'Synced', 'pattern (singular)' ) } help={ __( 'Sync this pattern across multiple locations.' diff --git a/packages/patterns/src/components/create-pattern-modal.js b/packages/patterns/src/components/create-pattern-modal.js index 226f48eb6c9e6f..dd86709acbca30 100644 --- a/packages/patterns/src/components/create-pattern-modal.js +++ b/packages/patterns/src/components/create-pattern-modal.js @@ -131,6 +131,7 @@ export function CreatePatternModalContents( { categoryMap={ categoryMap } /> <ToggleControl + __nextHasNoMarginBottom label={ _x( 'Synced', 'pattern (singular)' ) } help={ __( 'Sync this pattern across multiple locations.' diff --git a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js index 40f056a3a73885..21f3d0a61be042 100644 --- a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js +++ b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js @@ -176,6 +176,7 @@ export default function ReusableBlockConvertButton( { placeholder={ __( 'My pattern' ) } /> <ToggleControl + __nextHasNoMarginBottom label={ _x( 'Synced', 'pattern (singular)' ) } help={ __( 'Sync this pattern across multiple locations.' From de33f914b41ca3eec510aa2fd0c7841c6eb7e1ab Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 7 Aug 2024 07:08:17 +0900 Subject: [PATCH 0275/1908] SelectControl: Infer `value` type from `options` (#64069) * SelectControl: Infer `value` type from `options` * Don't infer onChange * Add static type tests Co-authored-by: Mikey Binns <hello@mikeybinns.com> * Rename generic to `V` (for `value`) * Add changelog * Simplify return type --------- Co-authored-by: Mikey Binns <hello@mikeybinns.com> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: mikeybinns <mikeybinns@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/date-time/time/index.tsx | 35 ++--- .../components/src/query-controls/index.tsx | 6 +- .../components/src/select-control/index.tsx | 20 ++- .../select-control/test/select-control.tsx | 125 ++++++++++++++++++ .../components/src/select-control/types.ts | 118 +++++++++-------- 6 files changed, 226 insertions(+), 79 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index a71b5a0ddef35f..8ecbf1528d6f08 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -13,6 +13,7 @@ - `TimeInput`: Expose as subcomponent of `TimePicker` ([#63145](https://github.com/WordPress/gutenberg/pull/63145)). - `RadioControl`: add support for option help text ([#63751](https://github.com/WordPress/gutenberg/pull/63751)). +- `SelectControl`: Infer `value` type from `options` ([#64069](https://github.com/WordPress/gutenberg/pull/64069)). - `Guide`: Add `__next40pxDefaultSize` to buttons ([#64181](https://github.com/WordPress/gutenberg/pull/64181)). - `SelectControl`: Pass through `options` props ([#64211](https://github.com/WordPress/gutenberg/pull/64211)). diff --git a/packages/components/src/date-time/time/index.tsx b/packages/components/src/date-time/time/index.tsx index 809376d99d3036..5f706d69190095 100644 --- a/packages/components/src/date-time/time/index.tsx +++ b/packages/components/src/date-time/time/index.tsx @@ -77,10 +77,28 @@ export function TimePicker( { ); }, [ currentTime ] ); + const monthOptions = [ + { value: '01', label: __( 'January' ) }, + { value: '02', label: __( 'February' ) }, + { value: '03', label: __( 'March' ) }, + { value: '04', label: __( 'April' ) }, + { value: '05', label: __( 'May' ) }, + { value: '06', label: __( 'June' ) }, + { value: '07', label: __( 'July' ) }, + { value: '08', label: __( 'August' ) }, + { value: '09', label: __( 'September' ) }, + { value: '10', label: __( 'October' ) }, + { value: '11', label: __( 'November' ) }, + { value: '12', label: __( 'December' ) }, + ] as const; + const { day, month, year, minutes, hours } = useMemo( () => ( { day: format( date, 'dd' ), - month: format( date, 'MM' ), + month: format( + date, + 'MM' + ) as ( typeof monthOptions )[ number ][ 'value' ], year: format( date, 'yyyy' ), minutes: format( date, 'mm' ), hours: format( date, 'HH' ), @@ -146,20 +164,7 @@ export function TimePicker( { __next40pxDefaultSize __nextHasNoMarginBottom value={ month } - options={ [ - { value: '01', label: __( 'January' ) }, - { value: '02', label: __( 'February' ) }, - { value: '03', label: __( 'March' ) }, - { value: '04', label: __( 'April' ) }, - { value: '05', label: __( 'May' ) }, - { value: '06', label: __( 'June' ) }, - { value: '07', label: __( 'July' ) }, - { value: '08', label: __( 'August' ) }, - { value: '09', label: __( 'September' ) }, - { value: '10', label: __( 'October' ) }, - { value: '11', label: __( 'November' ) }, - { value: '12', label: __( 'December' ) }, - ] } + options={ monthOptions } onChange={ ( value ) => { const newDate = setMonth( date, Number( value ) - 1 ); setDate( newDate ); diff --git a/packages/components/src/query-controls/index.tsx b/packages/components/src/query-controls/index.tsx index de53c63a9b8a82..3557335ebac5a0 100644 --- a/packages/components/src/query-controls/index.tsx +++ b/packages/components/src/query-controls/index.tsx @@ -85,7 +85,11 @@ export function QueryControls( { __next40pxDefaultSize={ __next40pxDefaultSize } key="query-controls-order-select" label={ __( 'Order by' ) } - value={ `${ orderBy }/${ order }` } + value={ + orderBy === undefined || order === undefined + ? undefined + : `${ orderBy }/${ order }` + } options={ [ { label: __( 'Newest to oldest' ), diff --git a/packages/components/src/select-control/index.tsx b/packages/components/src/select-control/index.tsx index 874b6ace1ea949..8a3b6bda68a160 100644 --- a/packages/components/src/select-control/index.tsx +++ b/packages/components/src/select-control/index.tsx @@ -42,8 +42,8 @@ function SelectOptions( { } ); } -function UnforwardedSelectControl( - props: WordPressComponentProps< SelectControlProps, 'select', false >, +function UnforwardedSelectControl< V extends string >( + props: WordPressComponentProps< SelectControlProps< V >, 'select', false >, ref: React.ForwardedRef< HTMLSelectElement > ) { const { @@ -82,12 +82,14 @@ function UnforwardedSelectControl( const selectedOptions = Array.from( event.target.options ).filter( ( { selected } ) => selected ); - const newValues = selectedOptions.map( ( { value } ) => value ); + const newValues = selectedOptions.map( + ( { value } ) => value as V + ); props.onChange?.( newValues, { event } ); return; } - props.onChange?.( event.target.value, { event } ); + props.onChange?.( event.target.value as V, { event } ); }; const classes = clsx( 'components-select-control', className ); @@ -164,6 +166,14 @@ function UnforwardedSelectControl( * }; * ``` */ -export const SelectControl = forwardRef( UnforwardedSelectControl ); +export const SelectControl = forwardRef( UnforwardedSelectControl ) as < + V extends string, +>( + props: WordPressComponentProps< + SelectControlProps< V >, + 'select', + false + > & { ref?: React.Ref< HTMLSelectElement > } +) => React.JSX.Element | null; export default SelectControl; diff --git a/packages/components/src/select-control/test/select-control.tsx b/packages/components/src/select-control/test/select-control.tsx index f2da74d9a6e911..0e8a6891087043 100644 --- a/packages/components/src/select-control/test/select-control.tsx +++ b/packages/components/src/select-control/test/select-control.tsx @@ -100,4 +100,129 @@ describe( 'SelectControl', () => { screen.getByRole( 'option', { name: 'Aria label' } ) ).toBeInTheDocument(); } ); + + /* eslint-disable jest/expect-expect */ + describe( 'static typing', () => { + describe( 'single', () => { + it( 'should infer the value type from available `options`, but not the `value` or `onChange` prop', () => { + const onChange: ( value: 'foo' | 'bar' ) => void = () => {}; + + <SelectControl + value="narrow" + options={ [ + { + value: 'narrow', + label: 'Narrow', + }, + { + value: 'value', + label: 'Value', + }, + ] } + // @ts-expect-error onChange type is not compatible with inferred value type + onChange={ onChange } + />; + + <SelectControl + // @ts-expect-error "string" is not "narrow" or "value" + value="string" + options={ [ + { + value: 'narrow', + label: 'Narrow', + }, + { + value: 'value', + label: 'Value', + }, + ] } + // @ts-expect-error "string" is not "narrow" or "value" + onChange={ ( value ) => value === 'string' } + />; + } ); + + it( 'should accept an explicit type argument', () => { + <SelectControl< 'narrow' | 'value' > + // @ts-expect-error "string" is not "narrow" or "value" + value="string" + options={ [ + { + value: 'narrow', + label: 'Narrow', + }, + { + // @ts-expect-error "string" is not "narrow" or "value" + value: 'string', + label: 'String', + }, + ] } + />; + } ); + } ); + + describe( 'multiple', () => { + it( 'should infer the value type from available `options`, but not the `value` or `onChange` prop', () => { + const onChange: ( + value: ( 'foo' | 'bar' )[] + ) => void = () => {}; + + <SelectControl + multiple + value={ [ 'narrow' ] } + options={ [ + { + value: 'narrow', + label: 'Narrow', + }, + { + value: 'value', + label: 'Value', + }, + ] } + // @ts-expect-error onChange type is not compatible with inferred value type + onChange={ onChange } + />; + + <SelectControl + multiple + // @ts-expect-error "string" is not "narrow" or "value" + value={ [ 'string' ] } + options={ [ + { + value: 'narrow', + label: 'Narrow', + }, + { + value: 'value', + label: 'Value', + }, + ] } + onChange={ ( value ) => + // @ts-expect-error "string" is not "narrow" or "value" + value.forEach( ( v ) => v === 'string' ) + } + />; + } ); + + it( 'should accept an explicit type argument', () => { + <SelectControl< 'narrow' | 'value' > + multiple + // @ts-expect-error "string" is not "narrow" or "value" + value={ [ 'string' ] } + options={ [ + { + value: 'narrow', + label: 'Narrow', + }, + { + // @ts-expect-error "string" is not "narrow" or "value" + value: 'string', + label: 'String', + }, + ] } + />; + } ); + } ); + } ); + /* eslint-enable jest/expect-expect */ } ); diff --git a/packages/components/src/select-control/types.ts b/packages/components/src/select-control/types.ts index a5d0d740c593cc..4e7211ab9abfb2 100644 --- a/packages/components/src/select-control/types.ts +++ b/packages/components/src/select-control/types.ts @@ -9,7 +9,7 @@ import type { ChangeEvent, ReactNode } from 'react'; import type { InputBaseProps } from '../input-control/types'; import type { BaseControlProps } from '../base-control/types'; -type SelectControlBaseProps = Pick< +type SelectControlBaseProps< V extends string > = Pick< InputBaseProps, | '__next36pxDefaultSize' | '__next40pxDefaultSize' @@ -27,7 +27,7 @@ type SelectControlBaseProps = Pick< * each with a `label` and `value` property, as well as any other * `<option>` attributes. */ - options?: ( { + options?: readonly ( { /** * The label to be shown to the user. */ @@ -36,7 +36,7 @@ type SelectControlBaseProps = Pick< * The internal value used to choose the selected value. * This is also the value passed to `onChange` when the option is selected. */ - value: string; + value: V; } & Omit< React.OptionHTMLAttributes< HTMLOptionElement >, 'label' | 'value' @@ -54,60 +54,62 @@ type SelectControlBaseProps = Pick< variant?: 'default' | 'minimal'; }; -export type SelectControlSingleSelectionProps = SelectControlBaseProps & { - /** - * If this property is added, multiple values can be selected. The `value` passed should be an array. - * - * In most cases, it is preferable to use the `FormTokenField` or `CheckboxControl` components instead. - * - * @default false - */ - multiple?: false; - /** - * The value of the selected option. - * - * If `multiple` is true, the `value` should be an array with the values of the selected options. - */ - value?: string; - /** - * A function that receives the value of the new option that is being selected as input. - * - * If `multiple` is `true`, the value received is an array of the selected value. - * Otherwise, the value received is a single value with the new selected value. - */ - onChange?: ( - value: string, - extra?: { event?: ChangeEvent< HTMLSelectElement > } - ) => void; -}; +export type SelectControlSingleSelectionProps< V extends string = string > = + SelectControlBaseProps< V > & { + /** + * If this property is added, multiple values can be selected. The `value` passed should be an array. + * + * In most cases, it is preferable to use the `FormTokenField` or `CheckboxControl` components instead. + * + * @default false + */ + multiple?: false; + /** + * The value of the selected option. + * + * If `multiple` is true, the `value` should be an array with the values of the selected options. + */ + value?: NoInfer< V >; + /** + * A function that receives the value of the new option that is being selected as input. + * + * If `multiple` is `true`, the value received is an array of the selected value. + * Otherwise, the value received is a single value with the new selected value. + */ + onChange?: ( + value: NoInfer< V >, + extra?: { event?: ChangeEvent< HTMLSelectElement > } + ) => void; + }; -export type SelectControlMultipleSelectionProps = SelectControlBaseProps & { - /** - * If this property is added, multiple values can be selected. The `value` passed should be an array. - * - * In most cases, it is preferable to use the `FormTokenField` or `CheckboxControl` components instead. - * - * @default false - */ - multiple: true; - /** - * The value of the selected option. - * - * If `multiple` is true, the `value` should be an array with the values of the selected options. - */ - value?: string[]; - /** - * A function that receives the value of the new option that is being selected as input. - * - * If `multiple` is `true`, the value received is an array of the selected value. - * Otherwise, the value received is a single value with the new selected value. - */ - onChange?: ( - value: string[], - extra?: { event?: ChangeEvent< HTMLSelectElement > } - ) => void; -}; +export type SelectControlMultipleSelectionProps< V extends string > = + SelectControlBaseProps< V > & { + /** + * If this property is added, multiple values can be selected. The `value` passed should be an array. + * + * In most cases, it is preferable to use the `FormTokenField` or `CheckboxControl` components instead. + * + * @default false + */ + multiple: true; + /** + * The value of the selected option. + * + * If `multiple` is true, the `value` should be an array with the values of the selected options. + */ + value?: NoInfer< V >[]; + /** + * A function that receives the value of the new option that is being selected as input. + * + * If `multiple` is `true`, the value received is an array of the selected value. + * Otherwise, the value received is a single value with the new selected value. + */ + onChange?: ( + value: NoInfer< V >[], + extra?: { event?: ChangeEvent< HTMLSelectElement > } + ) => void; + }; -export type SelectControlProps = - | SelectControlSingleSelectionProps - | SelectControlMultipleSelectionProps; +export type SelectControlProps< V extends string = string > = + | SelectControlSingleSelectionProps< V > + | SelectControlMultipleSelectionProps< V >; From 8e9034c7aa2a7f79a087e94138b1f73d5e6582bd Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 7 Aug 2024 10:48:49 +1000 Subject: [PATCH 0276/1908] Quote: Prevent block theme styles overriding global border and padding (#64045) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/quote/theme.scss | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/quote/theme.scss b/packages/block-library/src/quote/theme.scss index 5bcccbd60eefc4..2c5983003986a1 100644 --- a/packages/block-library/src/quote/theme.scss +++ b/packages/block-library/src/quote/theme.scss @@ -10,19 +10,21 @@ font-style: normal; } - &.has-text-align-right { + &:where(.has-text-align-right) { border-left: none; border-right: 0.25em solid currentColor; padding-left: 0; padding-right: 1em; } - &.has-text-align-center { + &:where(.has-text-align-center) { border: none; padding-left: 0; } // .is-style-large and .is-large are kept for backwards compatibility. - &.is-style-plain, + // They are not wrapped in `:where()` to keep specificity as it was before + // they were deprecated. + &:where(.is-style-plain), &.is-style-large, &.is-large { border: none; From 254400be75ffe17e036f233692482840951a3836 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Wed, 7 Aug 2024 10:58:29 +1000 Subject: [PATCH 0277/1908] Editor: Improve inline docs for parent page popup (#64226). Modify the inline documentation for the parent page selection popup: * Replace single quotes with double quotes per [documentation standards](https://make.wordpress.org/docs/style-guide/punctuation/quotation-marks/), * Replace industry specific example with a generic example that applies across multiple industries. Co-authored-by: peterwilsoncc <peterwilsoncc@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: kristastevens <kristastevens@git.wordpress.org> --- .../src/components/page-attributes/parent.js | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/packages/editor/src/components/page-attributes/parent.js b/packages/editor/src/components/page-attributes/parent.js index f83f700c969882..d53d82914f7c1e 100644 --- a/packages/editor/src/components/page-attributes/parent.js +++ b/packages/editor/src/components/page-attributes/parent.js @@ -14,11 +14,16 @@ import { ExternalLink, } from '@wordpress/components'; import { debounce } from '@wordpress/compose'; -import { useState, useMemo } from '@wordpress/element'; +import { + createInterpolateElement, + useState, + useMemo, +} from '@wordpress/element'; import { useSelect, useDispatch } from '@wordpress/data'; import { decodeEntities } from '@wordpress/html-entities'; import { store as coreStore } from '@wordpress/core-data'; import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor'; +import { filterURLForDisplay } from '@wordpress/url'; /** * Internal dependencies @@ -217,6 +222,10 @@ function PostParentToggle( { isOpen, onClick } ) { } export function ParentRow() { + const homeUrl = useSelect( + ( select ) => select( coreStore ).getUnstableBase()?.home, + [] + ); // Use internal state instead of a ref to make sure that the component // re-renders when the popover's anchor updates. const [ popoverAnchor, setPopoverAnchor ] = useState( null ); @@ -249,12 +258,21 @@ export function ParentRow() { onClose={ onClose } /> <div> - { - /* translators: The domain name should be a reserved domain name to prevent linking to third party sites outside the WordPress project's control. You may also wish to use wordpress.org or a wordpress.org sub-domain. */ - __( - "Child pages inherit characteristics from their parent, such as URL structure. For instance, if 'Web Design' is a child of 'Services', its URL would be example.org/services/web-design." - ) - } + { createInterpolateElement( + sprintf( + /* translators: %1$s The home URL of the WordPress installation without the scheme. */ + __( + 'Child pages inherit characteristics from their parent, such as URL structure. For instance, if "Pricing" is a child of "Services", its URL would be %1$s<wbr />/services<wbr />/pricing.' + ), + filterURLForDisplay( homeUrl ).replace( + /([/.])/g, + '<wbr />$1' + ) + ), + { + wbr: <wbr />, + } + ) } <p> { __( 'They also show up as sub-items in the default navigation menu. ' From 4aeaf7fe207cdb09fbebf610028c626b9646b41c Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Wed, 7 Aug 2024 07:16:33 +0530 Subject: [PATCH 0278/1908] Post Terms: Add border block support (#64246) Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/post-terms/block.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/block-library/src/post-terms/block.json b/packages/block-library/src/post-terms/block.json index 957181affb722c..165f50109616e7 100644 --- a/packages/block-library/src/post-terms/block.json +++ b/packages/block-library/src/post-terms/block.json @@ -60,6 +60,18 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } }, "style": "wp-block-post-terms" From 8c0bcdda4114e9fc681bb1d00da61c512a6d2dc5 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Wed, 7 Aug 2024 07:32:30 +0530 Subject: [PATCH 0279/1908] Comment Template: Add Border Block Support (#64238) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../block-library/src/comment-template/block.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/block-library/src/comment-template/block.json b/packages/block-library/src/comment-template/block.json index 70238c45a3d929..08fd591b42409b 100644 --- a/packages/block-library/src/comment-template/block.json +++ b/packages/block-library/src/comment-template/block.json @@ -31,6 +31,18 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } }, "style": "wp-block-comment-template" From 5693867520dfa933a1d43ec0dfa15646520180d2 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Wed, 7 Aug 2024 08:20:58 +0530 Subject: [PATCH 0280/1908] Post Comments Form: Add Border Block Support (#64233) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../block-library/src/post-comments-form/block.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/block-library/src/post-comments-form/block.json b/packages/block-library/src/post-comments-form/block.json index ff157beb5ced9c..af893ccb67a082 100644 --- a/packages/block-library/src/post-comments-form/block.json +++ b/packages/block-library/src/post-comments-form/block.json @@ -37,6 +37,18 @@ "__experimentalDefaultControls": { "fontSize": true } + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } }, "editorStyle": "wp-block-post-comments-form-editor", From 9a55d5ffa14d9154537904fdeb4f293cf38ac586 Mon Sep 17 00:00:00 2001 From: Tom de Visser <118618474+tomdevisser@users.noreply.github.com> Date: Wed, 7 Aug 2024 06:02:40 +0200 Subject: [PATCH 0281/1908] Add anchor block support to List Items (#48758) Co-authored-by: tomdevisser <thomasdevisser@git.wordpress.org> Co-authored-by: ejnwebmaster <ejnwebmaster@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: adamwoodnz <adamwood@git.wordpress.org> Co-authored-by: pbiron <pbiron@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- packages/block-library/src/list-item/block.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 72281a53c3dd18..5beb712c80a113 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -426,7 +426,7 @@ An individual item within a list. ([Source](https://github.com/WordPress/gutenbe - **Category:** text - **Parent:** core/list - **Allowed Blocks:** core/list -- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), splitting, typography (fontSize, lineHeight), ~~className~~ +- **Supports:** anchor, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), splitting, typography (fontSize, lineHeight), ~~className~~ - **Attributes:** content, placeholder ## Login/out diff --git a/packages/block-library/src/list-item/block.json b/packages/block-library/src/list-item/block.json index 32a552c3779cd3..fc7117d1b792fc 100644 --- a/packages/block-library/src/list-item/block.json +++ b/packages/block-library/src/list-item/block.json @@ -20,6 +20,7 @@ } }, "supports": { + "anchor": true, "className": false, "splitting": true, "color": { From 879a2a3eae4250c3f2cfda0e4b3e57ca88f36d90 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:53:10 +1000 Subject: [PATCH 0282/1908] Background image: remove toolspanel placeholder component (#64242) The dummy tools panel was originally there to allow feature toggling, which hides and shows non-default toolspanel controls. However, now that the background panel is in a popover, space is not so much of an issue. Furthermore for now, background images and their properties can be treated as a control group. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- .../global-styles/background-panel.js | 97 ++++++++++--------- .../src/components/global-styles/style.scss | 6 -- 2 files changed, 49 insertions(+), 54 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index 7a99a46943dbc6..e6b1517b420e8c 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -720,55 +720,56 @@ export default function BackgroundPanel( { } ) } > - { shouldShowBackgroundImageControls ? ( - <BackgroundControlsPanel - label={ title } - filename={ title } - url={ getResolvedThemeFilePath( url, themeFileURIs ) } - onToggle={ setIsDropDownOpen } - hasImageValue={ hasImageValue } - > - <VStack spacing={ 3 } className="single-column"> - <BackgroundImageControls - onChange={ onChange } - style={ value } - inheritedValue={ inheritedValue } - themeFileURIs={ themeFileURIs } - displayInPanel - onRemoveImage={ () => { - setIsDropDownOpen( false ); - resetBackground(); - } } - /> - <BackgroundSizeControls - onChange={ onChange } - panelId={ panelId } - style={ value } - defaultValues={ defaultValues } - inheritedValue={ inheritedValue } - themeFileURIs={ themeFileURIs } - /> - </VStack> - </BackgroundControlsPanel> - ) : ( - <BackgroundImageControls - onChange={ onChange } - style={ value } - inheritedValue={ inheritedValue } - themeFileURIs={ themeFileURIs } - /> - ) } + <ToolsPanelItem + hasValue={ () => hasImageValue } + label={ __( 'Image' ) } + onDeselect={ resetBackground } + isShownByDefault={ defaultControls.backgroundImage } + panelId={ panelId } + > + { shouldShowBackgroundImageControls ? ( + <BackgroundControlsPanel + label={ title } + filename={ title } + url={ getResolvedThemeFilePath( + url, + themeFileURIs + ) } + onToggle={ setIsDropDownOpen } + hasImageValue={ hasImageValue } + > + <VStack spacing={ 3 } className="single-column"> + <BackgroundImageControls + onChange={ onChange } + style={ value } + inheritedValue={ inheritedValue } + themeFileURIs={ themeFileURIs } + displayInPanel + onRemoveImage={ () => { + setIsDropDownOpen( false ); + resetBackground(); + } } + /> + <BackgroundSizeControls + onChange={ onChange } + panelId={ panelId } + style={ value } + defaultValues={ defaultValues } + inheritedValue={ inheritedValue } + themeFileURIs={ themeFileURIs } + /> + </VStack> + </BackgroundControlsPanel> + ) : ( + <BackgroundImageControls + onChange={ onChange } + style={ value } + inheritedValue={ inheritedValue } + themeFileURIs={ themeFileURIs } + /> + ) } + </ToolsPanelItem> </div> - - { /* Dummy ToolsPanel items, so we can control what's in the dropdown popover */ } - <ToolsPanelItem - hasValue={ () => hasImageValue } - label={ __( 'Image' ) } - onDeselect={ resetBackground } - isShownByDefault={ defaultControls.backgroundImage } - panelId={ panelId } - className="block-editor-global-styles-background-panel__hidden-tools-panel-item" - /> </Wrapper> ); } diff --git a/packages/block-editor/src/components/global-styles/style.scss b/packages/block-editor/src/components/global-styles/style.scss index 0bab29a9a3f2ad..b8dd3700a77f88 100644 --- a/packages/block-editor/src/components/global-styles/style.scss +++ b/packages/block-editor/src/components/global-styles/style.scss @@ -211,12 +211,6 @@ } } -.block-editor-global-styles-background-panel__hidden-tools-panel-item { - height: 0; - width: 0; - position: absolute; -} - // Push control panel into the background when the media modal is open. .modal-open .block-editor-global-styles-background-panel__popover { z-index: z-index(".block-editor-global-styles-background-panel__popover"); From c384bb6bacc574687c9e23a93e129b29e9ca46b2 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 7 Aug 2024 17:06:08 +1000 Subject: [PATCH 0283/1908] Background images: ensure appropriate default values (#64192) * First commit: - ensure that global styles background image blocks with user-uploaded images receive default values * First commit: - ensure that global styles background image blocks with user-uploaded images receive default values * Linterino * Add Core changelog Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- backport-changelog/6.7/7137.md | 3 ++ lib/class-wp-theme-json-gutenberg.php | 11 +++++ .../global-styles/background-panel.js | 30 +++++++----- .../test/use-global-styles-output.js | 37 ++++++++++++++ .../global-styles/use-global-styles-output.js | 2 +- phpunit/class-wp-theme-json-test.php | 49 +++++++++++++------ 6 files changed, 102 insertions(+), 30 deletions(-) create mode 100644 backport-changelog/6.7/7137.md diff --git a/backport-changelog/6.7/7137.md b/backport-changelog/6.7/7137.md new file mode 100644 index 00000000000000..834cb29a21e6d9 --- /dev/null +++ b/backport-changelog/6.7/7137.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7137 + +* https://github.com/WordPress/gutenberg/pull/64192 diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index cfe0c4d55ceed7..ad8722091c2d48 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2383,6 +2383,17 @@ protected static function compute_style_properties( $styles, $settings = array() // Processes background styles. if ( 'background' === $value_path[0] && isset( $styles['background'] ) ) { + /* + * For user-uploaded images at the block level, assign defaults. + * Matches defaults applied in the editor and in block supports: background.php. + */ + if ( static::ROOT_BLOCK_SELECTOR !== $selector && ! empty( $styles['background']['backgroundImage']['id'] ) ) { + $styles['background']['backgroundSize'] = $styles['background']['backgroundSize'] ?? 'cover'; + // If the background size is set to `contain` and no position is set, set the position to `center`. + if ( 'contain' === $styles['background']['backgroundSize'] && empty( $styles['background']['backgroundPosition'] ) ) { + $styles['background']['backgroundPosition'] = 'center'; + } + } $background_styles = gutenberg_style_engine_get_styles( array( 'background' => $styles['background'] ) ); $value = $background_styles['declarations'][ $css_property ] ?? $value; } diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index e6b1517b420e8c..61f572f970b762 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -318,8 +318,12 @@ function BackgroundImageControls( { return; } - const sizeValue = style?.background?.backgroundSize; - const positionValue = style?.background?.backgroundPosition; + const sizeValue = + style?.background?.backgroundSize || + inheritedValue?.background?.backgroundSize; + const positionValue = + style?.background?.backgroundPosition || + inheritedValue?.background?.backgroundPosition; onChange( setImmutably( style, [ 'background' ], { @@ -334,6 +338,7 @@ function BackgroundImageControls( { ! positionValue && ( 'auto' === sizeValue || ! sizeValue ) ? '50% 0' : positionValue, + backgroundSize: sizeValue, } ) ); }; @@ -448,6 +453,9 @@ function BackgroundSizeControls( { const imageValue = style?.background?.backgroundImage?.url || inheritedValue?.background?.backgroundImage?.url; + const isUploadedImage = + style?.background?.backgroundImage?.id || + inheritedValue?.background?.backgroundImage?.id; const positionValue = style?.background?.backgroundPosition || inheritedValue?.background?.backgroundPosition; @@ -456,19 +464,15 @@ function BackgroundSizeControls( { inheritedValue?.background?.backgroundAttachment; /* - * An `undefined` value is replaced with any supplied - * default control value for the toggle group control. - * An empty string is treated as `auto` - this allows a user - * to select "Size" and then enter a custom value, with an - * empty value being treated as `auto`. + * Set default values for uploaded images. + * The default values are passed by the consumer. + * Block-level controls may have different defaults to root-level controls. + * A falsy value is treated by default as `auto` (Tile). */ const currentValueForToggle = - ( sizeValue !== undefined && - sizeValue !== 'cover' && - sizeValue !== 'contain' ) || - sizeValue === '' - ? 'auto' - : sizeValue || defaultValues?.backgroundSize; + ! sizeValue && isUploadedImage + ? defaultValues?.backgroundSize + : sizeValue || 'auto'; /* * If the current value is `cover` and the repeat value is `undefined`, then diff --git a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js index 3f7fb5462e377c..f648e1db845b87 100644 --- a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js @@ -1028,6 +1028,43 @@ describe( 'global styles renderer', () => { 'letter-spacing: 2px', ] ); } ); + it( 'should set default values for block background styles', () => { + const backgroundStyles = { + background: { + backgroundImage: { + url: 'https://wordpress.org/assets/image.jpg', + id: 123, + }, + }, + }; + expect( + getStylesDeclarations( backgroundStyles, '.wp-block-group' ) + ).toEqual( [ + "background-image: url( 'https://wordpress.org/assets/image.jpg' )", + 'background-size: cover', + ] ); + // Test with root-level styles. + expect( + getStylesDeclarations( backgroundStyles, ROOT_BLOCK_SELECTOR ) + ).toEqual( [ + "background-image: url( 'https://wordpress.org/assets/image.jpg' )", + ] ); + expect( + getStylesDeclarations( + { + background: { + ...backgroundStyles.background, + backgroundSize: 'contain', + }, + }, + '.wp-block-group' + ) + ).toEqual( [ + "background-image: url( 'https://wordpress.org/assets/image.jpg' )", + 'background-position: center', + 'background-size: contain', + ] ); + } ); } ); describe( 'processCSSNesting', () => { diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 6d3e29f360200a..9190733d5b6607 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -404,7 +404,7 @@ export function getStylesDeclarations( * Set default values for block background styles. * Top-level styles are an exception as they are applied to the body. */ - if ( ! isRoot ) { + if ( ! isRoot && !! blockStyles.background?.backgroundImage?.id ) { blockStyles = { ...blockStyles, background: { diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 8d2f470efe60fe..b77b54ecc7d872 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -4808,7 +4808,6 @@ public function test_get_top_level_background_image_styles() { 'backgroundImage' => array( 'url' => 'http://example.org/image.png', ), - 'backgroundSize' => 'contain', 'backgroundRepeat' => 'no-repeat', 'backgroundPosition' => 'center center', 'backgroundAttachment' => 'fixed', @@ -4822,7 +4821,7 @@ public function test_get_top_level_background_image_styles() { 'selector' => 'body', ); - $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}body{background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;background-attachment: fixed;}"; + $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}body{background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-attachment: fixed;}"; $this->assertSameCSS( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background styles do not match expectations' ); $theme_json = new WP_Theme_JSON_Gutenberg( @@ -4853,7 +4852,6 @@ public function test_get_block_background_image_styles() { 'core/group' => array( 'background' => array( 'backgroundImage' => "url('http://example.org/group.png')", - 'backgroundSize' => 'cover', 'backgroundRepeat' => 'no-repeat', 'backgroundPosition' => 'center center', 'backgroundAttachment' => 'fixed', @@ -4861,12 +4859,19 @@ public function test_get_block_background_image_styles() { ), 'core/quote' => array( 'background' => array( - 'backgroundImage' => array( + 'backgroundImage' => array( 'url' => 'http://example.org/quote.png', + 'id' => 321, + ), + 'backgroundSize' => 'contain', + ), + ), + 'core/verse' => array( + 'background' => array( + 'backgroundImage' => array( + 'url' => 'http://example.org/verse.png', + 'id' => 123, ), - 'backgroundSize' => 'cover', - 'backgroundRepeat' => 'no-repeat', - 'backgroundPosition' => 'center center', ), ), ), @@ -4874,6 +4879,18 @@ public function test_get_block_background_image_styles() { ) ); + $group_node = array( + 'name' => 'core/group', + 'path' => array( 'styles', 'blocks', 'core/group' ), + 'selector' => '.wp-block-group', + 'selectors' => array( + 'root' => '.wp-block-group', + ), + ); + + $group_styles = ":root :where(.wp-block-group){background-image: url('http://example.org/group.png');background-position: center center;background-repeat: no-repeat;background-attachment: fixed;}"; + $this->assertSameCSS( $group_styles, $theme_json->get_styles_for_block( $group_node ), 'Styles returned from "::get_styles_for_block()" with core/group background styles as string type do not match expectations' ); + $quote_node = array( 'name' => 'core/quote', 'path' => array( 'styles', 'blocks', 'core/quote' ), @@ -4883,20 +4900,20 @@ public function test_get_block_background_image_styles() { ), ); - $quote_styles = ":root :where(.wp-block-quote){background-image: url('http://example.org/quote.png');background-position: center center;background-repeat: no-repeat;background-size: cover;}"; - $this->assertSameCSS( $quote_styles, $theme_json->get_styles_for_block( $quote_node ), 'Styles returned from "::get_styles_for_block()" with block-level background styles do not match expectations' ); + $quote_styles = ":root :where(.wp-block-quote){background-image: url('http://example.org/quote.png');background-position: center;background-size: contain;}"; + $this->assertSameCSS( $quote_styles, $theme_json->get_styles_for_block( $quote_node ), 'Styles returned from "::get_styles_for_block()" with core/quote default background styles do not match expectations' ); - $group_node = array( - 'name' => 'core/group', - 'path' => array( 'styles', 'blocks', 'core/group' ), - 'selector' => '.wp-block-group', + $verse_node = array( + 'name' => 'core/verse', + 'path' => array( 'styles', 'blocks', 'core/verse' ), + 'selector' => '.wp-block-verse', 'selectors' => array( - 'root' => '.wp-block-group', + 'root' => '.wp-block-verse', ), ); - $group_styles = ":root :where(.wp-block-group){background-image: url('http://example.org/group.png');background-position: center center;background-repeat: no-repeat;background-size: cover;background-attachment: fixed;}"; - $this->assertSameCSS( $group_styles, $theme_json->get_styles_for_block( $group_node ), 'Styles returned from "::get_styles_for_block()" with block-level background styles as string type do not match expectations' ); + $verse_styles = ":root :where(.wp-block-verse){background-image: url('http://example.org/verse.png');background-size: cover;}"; + $this->assertSameCSS( $verse_styles, $theme_json->get_styles_for_block( $verse_node ), 'Styles returned from "::get_styles_for_block()" with default core/verse background styles as string type do not match expectations' ); } /** From bd9ba413cee207338de17cd7d2141debff527074 Mon Sep 17 00:00:00 2001 From: David Arenas <david.arenas@automattic.com> Date: Wed, 7 Aug 2024 10:27:06 +0200 Subject: [PATCH 0284/1908] Interactivity API: Refactor internal proxy and signals system (#62734) * WIP * More WIP * Restore previous packages * Fix current tests * Add computation tests * Fix getter call * Fix for..in on new properties * Refactor code a little * Add tests for getters with scope * Move namespaces to properties * Fix a problem with object references * Add store handlers * Add signals-core dependency * Rename Property to PropSignal * Move withScope inside PropSignal logic * Create proxies folder * Attempt to make the context work * Reorganize code * Make peek() return only the value inside signalValue * A bit of refactoring * Return the computed value with `peek()` * Rename DEFAULT_SCOPE to NO_SCOPE * Remove deepsignal * Handle functions inside state * Fix withScope in this PR * Fix context proxification * Move store root logic to store proxy handlers * Move store initialization inside init * Add TODO comment inside `peek()` * Fix store root assignments * Fix lint error * Enable skipped test for non-initialized getters * Rename get(State|Store)Proxy to proxify(State|Store) * Make `getContext` throw when there is no scope * Fix `proxifyState` types * Rename some variables in tests * Add test for object reference keeping * Rename test suite for state proxy * Add tests for getters and functions with scope * Add tests for prop subscription inside functions * Allow functions to use `this` * Minor fixes * Add tests to store proxies * Throw an error when an object cannot be proxified * Change peek implementation * Add tests for peek and unsupported structures * Test peeking getters that access scope or other namespaces * Ignore well-known symbols * Minor comment format fix * Move namespace arg to first position in proxify functions * chore: Update jest.config.js to stop ignoring deepsignal because we removed it as dependency * Add comments to proxy registry * Remove namespace from PropSignal * Remove unused `peekValueSignal` method * Simplify PropSignal methods * Add TSDocs to PropSignal * Disable unused vars lint rule in state-proxy tests * Remove descriptor alias * Expand `getProxyNs` docs * Add more comments in `state` * Refactor state functions and add tsdocs * Fix some grammar issues * Fix default namespace for setters * Replace `isNotRoot` with `isRoot` * Update comments in store.ts * Move `isPlainObject` to utils * Remove remaining deepSignal references * Delete unnecessary @ts-ignore-next-line * Use `isPlainObject` from utils inside store * Move scopes and namespaces to separate files * Call `init` outside `DOMContentLoaded` * Replace `signals-core` imports with `signals` * Rename `proxiedStore` to `proxifiedStore` Co-authored-by: Luis Herranz <luisherranz@gmail.com> * Remove unnecessary `peek()` call * Throw more descriptive errors from getContext and getElement * Use more descriptive name for proxy functions * Use destructured `get` inside `setGetter` call * Add comment to explain `objToIterable` signals subscription Co-authored-by: Luis Herranz <luisherranz@gmail.com> * Change line comment to block comment * Replace `?` with `!` operator * Wrap Interactivity API tests with appropriate `describe` * Remove unnecessary `setNamespace` calls in tests * Remove duplicated test * Fix typo * Add extra tests for getter modification * Test the right namespace is used inside getters * Fix test name * Check if length's PropSignal exists before updating its value * Add deepMerge tests and prevent server overwritting * Make sure context inheritance is shallow and server props don't overwrite * Refactor wp-each to use new proxifyContext structure --------- Co-authored-by: DAreRodz <darerodz@git.wordpress.org> Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: luisherranz <luisherranz@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: otakupahp <otakupahp@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- package-lock.json | 32 - .../directive-each/render.php | 4 +- .../interactive-blocks/directive-each/view.js | 10 +- .../directive-priorities/view.js | 10 +- packages/interactivity-router/src/index.ts | 8 +- packages/interactivity/package.json | 1 - packages/interactivity/src/directives.tsx | 75 +- packages/interactivity/src/hooks.tsx | 93 +- packages/interactivity/src/index.ts | 21 +- packages/interactivity/src/namespaces.ts | 10 + packages/interactivity/src/proxies/index.ts | 5 + .../interactivity/src/proxies/registry.ts | 82 ++ packages/interactivity/src/proxies/signals.ts | 143 ++ packages/interactivity/src/proxies/state.ts | 250 ++++ packages/interactivity/src/proxies/store.ts | 79 + .../src/proxies/test/state-proxy.ts | 1269 +++++++++++++++++ .../src/proxies/test/store-proxy.ts | 123 ++ packages/interactivity/src/scopes.ts | 98 ++ packages/interactivity/src/store.ts | 192 +-- packages/interactivity/src/test/utils.ts | 337 ++++- packages/interactivity/src/utils.ts | 67 +- .../interactivity/deferred-store.spec.ts | 4 +- .../interactivity/directive-context.spec.ts | 50 +- .../interactivity/directive-each.spec.ts | 9 +- .../interactivity/router-navigate.spec.ts | 31 +- test/unit/jest.config.js | 2 +- 26 files changed, 2571 insertions(+), 434 deletions(-) create mode 100644 packages/interactivity/src/namespaces.ts create mode 100644 packages/interactivity/src/proxies/index.ts create mode 100644 packages/interactivity/src/proxies/registry.ts create mode 100644 packages/interactivity/src/proxies/signals.ts create mode 100644 packages/interactivity/src/proxies/state.ts create mode 100644 packages/interactivity/src/proxies/store.ts create mode 100644 packages/interactivity/src/proxies/test/state-proxy.ts create mode 100644 packages/interactivity/src/proxies/test/store-proxy.ts create mode 100644 packages/interactivity/src/scopes.ts diff --git a/package-lock.json b/package-lock.json index 23f504d7cbf460..e2cab9e63002d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53739,7 +53739,6 @@ "license": "GPL-2.0-or-later", "dependencies": { "@preact/signals": "^1.2.2", - "deepsignal": "^1.4.0", "preact": "^10.19.3" }, "engines": { @@ -53774,31 +53773,6 @@ "preact": "10.x" } }, - "packages/interactivity/node_modules/deepsignal": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/deepsignal/-/deepsignal-1.4.0.tgz", - "integrity": "sha512-x0XUMT48s+xQRLc2fPFfxnYLCJ46vffw47OQ5NcHFzacOjfW5eA0NrEmI0bhQHL6MgUHkBVT4TIiWTVwzTEwpg==", - "peerDependencies": { - "@preact/signals": "^1.1.4", - "@preact/signals-core": "^1.5.1", - "@preact/signals-react": "^1.3.8 || ^2.0.0", - "preact": "^10.16.0" - }, - "peerDependenciesMeta": { - "@preact/signals": { - "optional": true - }, - "@preact/signals-core": { - "optional": true - }, - "@preact/signals-react": { - "optional": true - }, - "preact": { - "optional": true - } - } - }, "packages/interactivity/node_modules/preact": { "version": "10.19.3", "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.3.tgz", @@ -68293,7 +68267,6 @@ "version": "file:packages/interactivity", "requires": { "@preact/signals": "^1.2.2", - "deepsignal": "^1.4.0", "preact": "^10.19.3" }, "dependencies": { @@ -68305,11 +68278,6 @@ "@preact/signals-core": "^1.4.0" } }, - "deepsignal": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/deepsignal/-/deepsignal-1.4.0.tgz", - "integrity": "sha512-x0XUMT48s+xQRLc2fPFfxnYLCJ46vffw47OQ5NcHFzacOjfW5eA0NrEmI0bhQHL6MgUHkBVT4TIiWTVwzTEwpg==" - }, "preact": { "version": "10.19.3", "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.3.tgz", diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-each/render.php b/packages/e2e-tests/plugins/interactive-blocks/directive-each/render.php index 27fd6c7d172939..47eb351d837e78 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-each/render.php +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-each/render.php @@ -220,14 +220,14 @@ <div data-wp-interactive="directive-each" data-wp-router-region="navigation-updated list" - data-wp-context='{ "list": [ "beta", "gamma", "delta" ] }' + data-wp-context='{ "b": 2, "c": 3, "d": 4 }' data-testid="navigation-updated list" > <button data-testid="navigate" data-wp-on--click="actions.navigate" >Navigate</button> - <template data-wp-each="context.list"> + <template data-wp-each="state.list"> <p data-wp-text="context.item" data-testid="item"></p> </template> <p data-testid="item" data-wp-each-child>beta</p> diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-each/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-each/view.js index e19821a2a2aff1..6ceef82864d9db 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-each/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-each/view.js @@ -169,14 +169,14 @@ const html = ` <div data-wp-interactive="directive-each" data-wp-router-region="navigation-updated list" - data-wp-context='{ "list": [ "alpha", "beta", "gamma", "delta" ] }' + data-wp-context='{ "a": 1, "b": 2, "c": 3, "d": 4 }' data-testid="navigation-updated list" > <button data-testid="navigate" data-wp-on--click="actions.navigate" >Navigate</button> - <template data-wp-each="context.list"> + <template data-wp-each="state.list"> <p data-wp-text="context.item" data-testid="item"></p> </template> <p data-testid="item" data-wp-each-child>alpha</p> @@ -187,6 +187,12 @@ const html = ` `; store( 'directive-each', { + state: { + get list() { + const ctx = getContext(); + return Object.keys( ctx ).sort(); + }, + }, actions: { *navigate() { const { actions } = yield import( diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-priorities/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-priorities/view.js index c6cdf31b4909c8..5a46908f77d87b 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-priorities/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-priorities/view.js @@ -8,7 +8,7 @@ import { privateApis, } from '@wordpress/interactivity'; -const { directive, deepSignal, h } = privateApis( +const { directive, proxifyState, h } = privateApis( 'I acknowledge that using private APIs means my theme or plugin will inevitably break in the next version of WordPress.' ); @@ -41,12 +41,12 @@ directive( 'test-context', ( { context: { Provider }, props: { children } } ) => { executionProof( 'context' ); - const value = deepSignal( { - [ namespace ]: { + const value = { + [ namespace ]: proxifyState( namespace, { attribute: 'from context', text: 'from context', - }, - } ); + } ), + }; return h( Provider, { value }, children ); }, { priority: 8 } diff --git a/packages/interactivity-router/src/index.ts b/packages/interactivity-router/src/index.ts index 79b67eeb98e656..c6e1087b038a55 100644 --- a/packages/interactivity-router/src/index.ts +++ b/packages/interactivity-router/src/index.ts @@ -14,8 +14,8 @@ const { initialVdom, toVdom, render, - parseInitialData, - populateInitialData, + parseServerData, + populateServerData, batch, } = privateApis( 'I acknowledge that using private APIs means my theme or plugin will inevitably break in the next version of WordPress.' @@ -103,7 +103,7 @@ const regionsToVdom: RegionsToVdom = async ( dom, { vdom } = {} ) => { } ); } const title = dom.querySelector( 'title' )?.innerText; - const initialData = parseInitialData( dom ); + const initialData = parseServerData( dom ); return { regions, head, title, initialData }; }; @@ -119,7 +119,7 @@ const renderRegions = ( page: Page ) => { } } if ( navigationMode === 'regionBased' ) { - populateInitialData( page.initialData ); + populateServerData( page.initialData ); const attrName = `data-${ directivePrefix }-router-region`; document .querySelectorAll( `[${ attrName }]` ) diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 835063ccc76992..332254684bdc9b 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -28,7 +28,6 @@ "types": "build-types", "dependencies": { "@preact/signals": "^1.2.2", - "deepsignal": "^1.4.0", "preact": "^10.19.3" }, "publishConfig": { diff --git a/packages/interactivity/src/directives.tsx b/packages/interactivity/src/directives.tsx index 60ddf13375a8a1..357fe203399be3 100644 --- a/packages/interactivity/src/directives.tsx +++ b/packages/interactivity/src/directives.tsx @@ -6,14 +6,24 @@ */ import { h as createElement, type RefObject } from 'preact'; import { useContext, useMemo, useRef } from 'preact/hooks'; -import { deepSignal, peek, type DeepSignal } from 'deepsignal'; +/** + * Internal dependencies + */ +import { proxifyState, peek } from './proxies'; /** * Internal dependencies */ -import { useWatch, useInit, kebabToCamelCase, warn, splitTask } from './utils'; -import type { DirectiveEntry } from './hooks'; -import { directive, getScope, getEvaluate } from './hooks'; +import { + useWatch, + useInit, + kebabToCamelCase, + warn, + splitTask, + isPlainObject, +} from './utils'; +import { directive, getEvaluate, type DirectiveEntry } from './hooks'; +import { getScope } from './scopes'; // Assigned objects should be ignored during proxification. const contextAssignedObjects = new WeakMap(); @@ -23,9 +33,6 @@ const contextObjectToProxy = new WeakMap(); const contextProxyToObject = new WeakMap(); const contextObjectToFallback = new WeakMap(); -const isPlainObject = ( item: unknown ): boolean => - Boolean( item && typeof item === 'object' && item.constructor === Object ); - const descriptor = Reflect.getOwnPropertyDescriptor; /** @@ -47,7 +54,7 @@ const proxifyContext = ( current: object, inherited: object = {} ): object => { contextObjectToFallback.set( current, inherited ); if ( ! contextObjectToProxy.has( current ) ) { const proxy = new Proxy( current, { - get: ( target: DeepSignal< any >, k ) => { + get: ( target: object, k: string ) => { const fallback = contextObjectToFallback.get( current ); // Always subscribe to prop changes in the current context. const currentProp = target[ k ]; @@ -61,9 +68,9 @@ const proxifyContext = ( current: object, inherited: object = {} ): object => { if ( k in target && ! contextAssignedObjects.get( target )?.has( k ) && - isPlainObject( peek( target, k ) ) + isPlainObject( currentProp ) ) { - return proxifyContext( currentProp, fallback[ k ] ); + return proxifyContext( currentProp ); } // Return the stored proxy for `currentProp` when it exists. @@ -125,22 +132,19 @@ const proxifyContext = ( current: object, inherited: object = {} ): object => { }; /** - * Recursively update values within a deepSignal object. + * Recursively update values within a context object. * - * @param target A deepSignal instance. + * @param target A context instance. * @param source Object with properties to update in `target`. */ -const updateSignals = ( - target: DeepSignal< any >, - source: DeepSignal< any > -) => { +const updateContext = ( target: any, source: any ) => { for ( const k in source ) { if ( isPlainObject( peek( target, k ) ) && - isPlainObject( peek( source, k ) ) + isPlainObject( source[ k ] ) ) { - updateSignals( target[ `$${ k }` ].peek(), source[ k ] ); - } else { + updateContext( peek( target, k ) as object, source[ k ] ); + } else if ( ! ( k in target ) ) { target[ k ] = source[ k ]; } } @@ -257,18 +261,21 @@ export default () => { // data-wp-context directive( 'context', - // @ts-ignore-next-line ( { directives: { context }, props: { children }, context: inheritedContext, } ) => { const { Provider } = inheritedContext; - const inheritedValue = useContext( inheritedContext ); - const currentValue = useRef( deepSignal( {} ) ); const defaultEntry = context.find( ( { suffix } ) => suffix === 'default' ); + const inheritedValue = useContext( inheritedContext ); + + const ns = defaultEntry!.namespace; + const currentValue = useRef( { + [ ns ]: proxifyState( ns, {} ), + } ); // No change should be made if `defaultEntry` does not exist. const contextStack = useMemo( () => { @@ -280,11 +287,16 @@ export default () => { `The value of data-wp-context in "${ namespace }" store must be a valid stringified JSON object.` ); } - updateSignals( currentValue.current, { - [ namespace ]: deepClone( value ), - } ); + updateContext( + currentValue.current[ namespace ], + deepClone( value ) as object + ); + currentValue.current[ namespace ] = proxifyContext( + currentValue.current[ namespace ], + inheritedValue[ namespace ] + ); } - return proxifyContext( currentValue.current, inheritedValue ); + return currentValue.current; }, [ defaultEntry, inheritedValue ] ); return createElement( Provider, { value: contextStack }, children ); @@ -677,11 +689,14 @@ export default () => { return list.map( ( item ) => { const itemProp = suffix === 'default' ? 'item' : kebabToCamelCase( suffix ); - const itemContext = deepSignal( { [ namespace ]: {} } ); - const mergedContext = proxifyContext( - itemContext, - inheritedValue + const itemContext = proxifyContext( + proxifyState( namespace, {} ), + inheritedValue[ namespace ] ); + const mergedContext = { + ...inheritedValue, + [ namespace ]: itemContext, + }; // Set the item after proxifying the context. mergedContext[ namespace ][ itemProp ] = item; diff --git a/packages/interactivity/src/hooks.tsx b/packages/interactivity/src/hooks.tsx index 9af6fb00d6aba5..215da8afef9b5b 100644 --- a/packages/interactivity/src/hooks.tsx +++ b/packages/interactivity/src/hooks.tsx @@ -12,13 +12,14 @@ import { type ComponentChildren, } from 'preact'; import { useRef, useCallback, useContext } from 'preact/hooks'; -import type { VNode, Context, RefObject } from 'preact'; +import type { VNode, Context } from 'preact'; /** * Internal dependencies */ import { store, stores, universalUnlock } from './store'; import { warn } from './utils'; +import { getScope, setScope, resetScope, type Scope } from './scopes'; export interface DirectiveEntry { value: string | object; namespace: string; @@ -56,7 +57,7 @@ interface DirectiveArgs { } interface DirectiveCallback { - ( args: DirectiveArgs ): VNode | null | void; + ( args: DirectiveArgs ): VNode< any > | null | void; } interface DirectiveOptions { @@ -69,14 +70,7 @@ interface DirectiveOptions { priority?: number; } -interface Scope { - evaluate: Evaluate; - context: object; - ref: RefObject< HTMLElement >; - attributes: createElement.JSX.HTMLAttributes; -} - -interface Evaluate { +export interface Evaluate { ( entry: DirectiveEntry, ...args: any[] ): any; } @@ -101,85 +95,6 @@ interface DirectivesProps { // Main context. const context = createContext< any >( {} ); -// Wrap the element props to prevent modifications. -const immutableMap = new WeakMap(); -const immutableError = () => { - throw new Error( - 'Please use `data-wp-bind` to modify the attributes of an element.' - ); -}; -const immutableHandlers: ProxyHandler< object > = { - get( target, key, receiver ) { - const value = Reflect.get( target, key, receiver ); - return !! value && typeof value === 'object' - ? deepImmutable( value ) - : value; - }, - set: immutableError, - deleteProperty: immutableError, -}; -const deepImmutable = < T extends object = {} >( target: T ): T => { - if ( ! immutableMap.has( target ) ) { - immutableMap.set( target, new Proxy( target, immutableHandlers ) ); - } - return immutableMap.get( target ); -}; - -// Store stacks for the current scope and the default namespaces and export APIs -// to interact with them. -const scopeStack: Scope[] = []; -const namespaceStack: string[] = []; - -/** - * Retrieves the context inherited by the element evaluating a function from the - * store. The returned value depends on the element and the namespace where the - * function calling `getContext()` exists. - * - * @param namespace Store namespace. By default, the namespace where the calling - * function exists is used. - * @return The context content. - */ -export const getContext = < T extends object >( namespace?: string ): T => - getScope()?.context[ namespace || getNamespace() ]; - -/** - * Retrieves a representation of the element where a function from the store - * is being evalutated. Such representation is read-only, and contains a - * reference to the DOM element, its props and a local reactive state. - * - * @return Element representation. - */ -export const getElement = () => { - if ( ! getScope() ) { - throw Error( - 'Cannot call `getElement()` outside getters and actions used by directives.' - ); - } - const { ref, attributes } = getScope(); - return Object.freeze( { - ref: ref.current, - attributes: deepImmutable( attributes ), - } ); -}; - -export const getScope = () => scopeStack.slice( -1 )[ 0 ]; - -export const setScope = ( scope: Scope ) => { - scopeStack.push( scope ); -}; -export const resetScope = () => { - scopeStack.pop(); -}; - -export const getNamespace = () => namespaceStack.slice( -1 )[ 0 ]; - -export const setNamespace = ( namespace: string ) => { - namespaceStack.push( namespace ); -}; -export const resetNamespace = () => { - namespaceStack.pop(); -}; - // WordPress Directives. const directiveCallbacks: Record< string, DirectiveCallback > = {}; const directivePriorities: Record< string, number > = {}; diff --git a/packages/interactivity/src/index.ts b/packages/interactivity/src/index.ts index a43534509bb5ac..336c2a97226db7 100644 --- a/packages/interactivity/src/index.ts +++ b/packages/interactivity/src/index.ts @@ -3,7 +3,6 @@ */ import { h, cloneElement, render } from 'preact'; import { batch } from '@preact/signals'; -import { deepSignal } from 'deepsignal'; /** * Internal dependencies @@ -12,11 +11,13 @@ import registerDirectives from './directives'; import { init, getRegionRootFragment, initialVdom } from './init'; import { directivePrefix } from './constants'; import { toVdom } from './vdom'; -import { directive, getNamespace } from './hooks'; -import { parseInitialData, populateInitialData } from './store'; +import { directive } from './hooks'; +import { getNamespace } from './namespaces'; +import { parseServerData, populateServerData } from './store'; +import { proxifyState } from './proxies'; export { store, getConfig } from './store'; -export { getContext, getElement } from './hooks'; +export { getContext, getElement } from './scopes'; export { withScope, useWatch, @@ -45,9 +46,9 @@ export const privateApis = ( lock ): any => { h, cloneElement, render, - deepSignal, - parseInitialData, - populateInitialData, + proxifyState, + parseServerData, + populateServerData, batch, }; } @@ -55,7 +56,5 @@ export const privateApis = ( lock ): any => { throw new Error( 'Forbidden access.' ); }; -document.addEventListener( 'DOMContentLoaded', async () => { - registerDirectives(); - await init(); -} ); +registerDirectives(); +init(); diff --git a/packages/interactivity/src/namespaces.ts b/packages/interactivity/src/namespaces.ts new file mode 100644 index 00000000000000..9103f3c76e67bb --- /dev/null +++ b/packages/interactivity/src/namespaces.ts @@ -0,0 +1,10 @@ +const namespaceStack: string[] = []; + +export const getNamespace = () => namespaceStack.slice( -1 )[ 0 ]; + +export const setNamespace = ( namespace: string ) => { + namespaceStack.push( namespace ); +}; +export const resetNamespace = () => { + namespaceStack.pop(); +}; diff --git a/packages/interactivity/src/proxies/index.ts b/packages/interactivity/src/proxies/index.ts new file mode 100644 index 00000000000000..d64fb59fa6bccf --- /dev/null +++ b/packages/interactivity/src/proxies/index.ts @@ -0,0 +1,5 @@ +/** + * Internal dependencies + */ +export { proxifyState, peek } from './state'; +export { proxifyStore } from './store'; diff --git a/packages/interactivity/src/proxies/registry.ts b/packages/interactivity/src/proxies/registry.ts new file mode 100644 index 00000000000000..767a3730dbae2d --- /dev/null +++ b/packages/interactivity/src/proxies/registry.ts @@ -0,0 +1,82 @@ +/** + * Proxies for each object. + */ +const objToProxy = new WeakMap< object, object >(); + +/** + * Namespaces for each created proxy. + */ +const proxyToNs = new WeakMap< object, string >(); + +/** + * Object types that can be proxied. + */ +const supported = new Set( [ Object, Array ] ); + +/** + * Returns a proxy to the passed object with the given handlers, assigning the + * specified namespace to it. If a proxy for the passed object was created + * before, that proxy is returned. + * + * @param namespace The namespace that will be associated to this proxy. + * @param obj The object to proxify. + * @param handlers Handlers that the proxy will use. + * + * @throws Error if the object cannot be proxified. Use {@link shouldProxy} to + * check if a proxy can be created for a specific object. + * + * @return The created proxy. + */ +export const createProxy = < T extends object >( + namespace: string, + obj: T, + handlers: ProxyHandler< T > +): T => { + if ( ! shouldProxy( obj ) ) { + throw Error( 'This object cannot be proxified.' ); + } + if ( ! objToProxy.has( obj ) ) { + const proxy = new Proxy( obj, handlers ); + objToProxy.set( obj, proxy ); + proxyToNs.set( proxy, namespace ); + } + return objToProxy.get( obj ) as T; +}; + +/** + * Returns the proxy for the given object. If there is no associated proxy, the + * function returns `undefined`. + * + * @param obj Object from which to know the proxy. + * @return Associated proxy or `undefined`. + */ +export const getProxyFromObject = < T extends object >( obj: T ): T => + objToProxy.get( obj ) as T; + +/** + * Gets the namespace associated with the given proxy. + * + * Proxies have a namespace assigned upon creation. See {@link createProxy}. + * + * @param proxy Proxy. + * @return Namespace. + */ +export const getNamespaceFromProxy = ( proxy: object ): string => + proxyToNs.get( proxy )!; + +/** + * Checks if a given object can be proxied. + * + * @param candidate Object to know whether it can be proxied. + * @return True if the passed instance can be proxied. + */ +export const shouldProxy = ( + candidate: any +): candidate is Object | Array< unknown > => { + if ( typeof candidate !== 'object' || candidate === null ) { + return false; + } + return ( + ! proxyToNs.has( candidate ) && supported.has( candidate.constructor ) + ); +}; diff --git a/packages/interactivity/src/proxies/signals.ts b/packages/interactivity/src/proxies/signals.ts new file mode 100644 index 00000000000000..6a3f41c149e134 --- /dev/null +++ b/packages/interactivity/src/proxies/signals.ts @@ -0,0 +1,143 @@ +/** + * External dependencies + */ +import { + computed, + signal, + batch, + type Signal, + type ReadonlySignal, +} from '@preact/signals'; + +/** + * Internal dependencies + */ +import { getNamespaceFromProxy } from './registry'; +import { getScope } from '../scopes'; +import { setNamespace, resetNamespace } from '../namespaces'; +import { withScope } from '../utils'; + +/** + * Identifier for property computeds not associated to any scope. + */ +const NO_SCOPE = Symbol(); + +/** + * Structure that manages reactivity for a property in a state object. It uses + * signals to keep track of property value or getter modifications. + */ +export class PropSignal { + /** + * Proxy that holds the property this PropSignal is associated with. + */ + private owner: object; + + /** + * Relation of computeds by scope. These computeds are read-only signals + * that depend on whether the property is a value or a getter and, + * therefore, can return different values depending on the scope in which + * the getter is accessed. + */ + private computedsByScope: WeakMap< WeakKey, ReadonlySignal >; + + /** + * Signal with the value assigned to the related property. + */ + private valueSignal?: Signal; + + /** + * Signal with the getter assigned to the related property. + */ + private getterSignal?: Signal< ( () => any ) | undefined >; + + /** + * Structure that manages reactivity for a property in a state object, using + * signals to keep track of property value or getter modifications. + * + * @param owner Proxy that holds the property this instance is associated + * with. + */ + constructor( owner: object ) { + this.owner = owner; + this.computedsByScope = new WeakMap(); + } + + /** + * Changes the internal value. If a getter was set before, it is set to + * `undefined`. + * + * @param value New value. + */ + public setValue( value: unknown ) { + this.update( { value } ); + } + + /** + * Changes the internal getter. If a value was set before, it is set to + * `undefined`. + * + * @param getter New getter. + */ + public setGetter( getter: () => any ) { + this.update( { get: getter } ); + } + + /** + * Returns the computed that holds the result of evaluating the prop in the + * current scope. + * + * These computeds are read-only signals that depend on whether the property + * is a value or a getter and, therefore, can return different values + * depending on the scope in which the getter is accessed. + * + * @return Computed that depends on the scope. + */ + public getComputed(): ReadonlySignal { + const scope = getScope() || NO_SCOPE; + + if ( ! this.valueSignal && ! this.getterSignal ) { + this.update( {} ); + } + + if ( ! this.computedsByScope.has( scope ) ) { + const callback = () => { + const getter = this.getterSignal?.value; + return getter + ? getter.call( this.owner ) + : this.valueSignal?.value; + }; + + setNamespace( getNamespaceFromProxy( this.owner ) ); + this.computedsByScope.set( + scope, + computed( withScope( callback ) ) + ); + resetNamespace(); + } + + return this.computedsByScope.get( scope )!; + } + + /** + * Update the internal signals for the value and the getter of the + * corresponding prop. + * + * @param param0 + * @param param0.get New getter. + * @param param0.value New value. + */ + private update( { get, value }: { get?: () => any; value?: unknown } ) { + if ( ! this.valueSignal ) { + this.valueSignal = signal( value ); + this.getterSignal = signal( get ); + } else if ( + value !== this.valueSignal.peek() || + get !== this.getterSignal!.peek() + ) { + batch( () => { + this.valueSignal!.value = value; + this.getterSignal!.value = get; + } ); + } + } +} diff --git a/packages/interactivity/src/proxies/state.ts b/packages/interactivity/src/proxies/state.ts new file mode 100644 index 00000000000000..0978fa2ccd0264 --- /dev/null +++ b/packages/interactivity/src/proxies/state.ts @@ -0,0 +1,250 @@ +/** + * External dependencies + */ +import { signal, type Signal } from '@preact/signals'; + +/** + * Internal dependencies + */ +import { + createProxy, + getProxyFromObject, + getNamespaceFromProxy, + shouldProxy, +} from './registry'; +import { PropSignal } from './signals'; +import { setNamespace, resetNamespace } from '../namespaces'; + +/** + * Set of built-in symbols. + */ +const wellKnownSymbols = new Set( + Object.getOwnPropertyNames( Symbol ) + .map( ( key ) => Symbol[ key ] ) + .filter( ( value ) => typeof value === 'symbol' ) +); + +/** + * Relates each proxy with a map of {@link PropSignal} instances, representing + * the proxy's accessed properties. + */ +const proxyToProps: WeakMap< + object, + Map< string | symbol, PropSignal > +> = new WeakMap(); + +/** + * Returns the {@link PropSignal | `PropSignal`} instance associated with the + * specified prop in the passed proxy. + * + * The `PropSignal` instance is generated if it doesn't exist yet, using the + * `initial` parameter to initialize the internal signals. + * + * @param proxy Proxy of a state object or array. + * @param key The property key. + * @param initial Initial data for the `PropSignal` instance. + * @return The `PropSignal` instance. + */ +const getPropSignal = ( + proxy: object, + key: string | number | symbol, + initial?: PropertyDescriptor +) => { + if ( ! proxyToProps.has( proxy ) ) { + proxyToProps.set( proxy, new Map() ); + } + key = typeof key === 'number' ? `${ key }` : key; + const props = proxyToProps.get( proxy )!; + if ( ! props.has( key ) ) { + const ns = getNamespaceFromProxy( proxy ); + const prop = new PropSignal( proxy ); + props.set( key, prop ); + if ( initial ) { + const { get, value } = initial; + if ( get ) { + prop.setGetter( get ); + } else { + prop.setValue( + shouldProxy( value ) ? proxifyState( ns, value ) : value + ); + } + } + } + return props.get( key )!; +}; + +/** + * Relates each proxied object (i.e., the original object) with a signal that + * tracks changes in the number of properties. + */ +const objToIterable = new WeakMap< object, Signal< number > >(); + +/** + * When this flag is `true`, it avoids any signal subscription, overriding state + * props' "reactive" behavior. + */ +let peeking = false; + +/** + * Handlers for reactive objects and arrays in the state. + */ +const stateHandlers: ProxyHandler< object > = { + get( target: object, key: string | symbol, receiver: object ): any { + /* + * The property should not be reactive for the following cases: + * 1. While using the `peek` function to read the property. + * 2. The property exists but comes from the Object or Array prototypes. + * 3. The property key is a known symbol. + */ + if ( + peeking || + ( ! target.hasOwnProperty( key ) && key in target ) || + ( typeof key === 'symbol' && wellKnownSymbols.has( key ) ) + ) { + return Reflect.get( target, key, receiver ); + } + + // At this point, the property should be reactive. + const desc = Object.getOwnPropertyDescriptor( target, key ); + const prop = getPropSignal( receiver, key, desc ); + const result = prop.getComputed().value; + + /* + * Check if the property is a synchronous function. If it is, set the + * default namespace. Synchronous functions always run in the proper scope, + * which is set by the Directives component. + */ + if ( typeof result === 'function' ) { + const ns = getNamespaceFromProxy( receiver ); + return ( ...args: unknown[] ) => { + setNamespace( ns ); + try { + return result.call( receiver, ...args ); + } finally { + resetNamespace(); + } + }; + } + + return result; + }, + + set( + target: object, + key: string, + value: unknown, + receiver: object + ): boolean { + setNamespace( getNamespaceFromProxy( receiver ) ); + try { + return Reflect.set( target, key, value, receiver ); + } finally { + resetNamespace(); + } + }, + + defineProperty( + target: object, + key: string, + desc: PropertyDescriptor + ): boolean { + const isNew = ! ( key in target ); + const result = Reflect.defineProperty( target, key, desc ); + + if ( result ) { + const receiver = getProxyFromObject( target ); + const prop = getPropSignal( receiver, key ); + const { get, value } = desc; + if ( get ) { + prop.setGetter( get ); + } else { + const ns = getNamespaceFromProxy( receiver ); + prop.setValue( + shouldProxy( value ) ? proxifyState( ns, value ) : value + ); + } + + if ( isNew && objToIterable.has( target ) ) { + objToIterable.get( target )!.value++; + } + + /* + * Modify the `length` property value only if the related + * `PropSignal` exists, which means that there are subscriptions to + * this property. + */ + if ( + Array.isArray( target ) && + proxyToProps.get( receiver )?.has( 'length' ) + ) { + const length = getPropSignal( receiver, 'length' ); + length.setValue( target.length ); + } + } + + return result; + }, + + deleteProperty( target: object, key: string ): boolean { + const result = Reflect.deleteProperty( target, key ); + + if ( result ) { + const prop = getPropSignal( getProxyFromObject( target ), key ); + prop.setValue( undefined ); + + if ( objToIterable.has( target ) ) { + objToIterable.get( target )!.value++; + } + } + + return result; + }, + + ownKeys( target: object ): ( string | symbol )[] { + if ( ! objToIterable.has( target ) ) { + objToIterable.set( target, signal( 0 ) ); + } + /* + *This subscribes to the signal while preventing the minifier from + * deleting this line in production. + */ + ( objToIterable as any )._ = objToIterable.get( target )!.value; + return Reflect.ownKeys( target ); + }, +}; + +/** + * Returns the proxy associated with the given state object, creating it if it + * does not exist. + * + * @param namespace The namespace that will be associated to this proxy. + * @param obj The object to proxify. + * + * @throws Error if the object cannot be proxified. Use {@link shouldProxy} to + * check if a proxy can be created for a specific object. + * + * @return The associated proxy. + */ +export const proxifyState = < T extends object >( + namespace: string, + obj: T +): T => createProxy( namespace, obj, stateHandlers ) as T; + +/** + * Reads the value of the specified property without subscribing to it. + * + * @param obj The object to read the property from. + * @param key The property key. + * @return The property value. + */ +export const peek = < T extends object, K extends keyof T >( + obj: T, + key: K +): T[ K ] => { + peeking = true; + try { + return obj[ key ]; + } finally { + peeking = false; + } +}; diff --git a/packages/interactivity/src/proxies/store.ts b/packages/interactivity/src/proxies/store.ts new file mode 100644 index 00000000000000..506b8c3b097bae --- /dev/null +++ b/packages/interactivity/src/proxies/store.ts @@ -0,0 +1,79 @@ +/** + * Internal dependencies + */ +import { createProxy, getNamespaceFromProxy, shouldProxy } from './registry'; +/** + * External dependencies + */ +import { setNamespace, resetNamespace } from '../namespaces'; +import { withScope, isPlainObject } from '../utils'; + +/** + * Identifies the store proxies handling the root objects of each store. + */ +const storeRoots = new WeakSet(); + +/** + * Handlers for store proxies. + */ +const storeHandlers: ProxyHandler< object > = { + get: ( target: any, key: string | symbol, receiver: any ) => { + const result = Reflect.get( target, key ); + const ns = getNamespaceFromProxy( receiver ); + + /* + * Check if the proxy is the store root and no key with that name exist. In + * that case, return an empty object for the requested key. + */ + if ( typeof result === 'undefined' && storeRoots.has( receiver ) ) { + const obj = {}; + Reflect.set( target, key, obj ); + return proxifyStore( ns, obj, false ); + } + + /* + * Check if the property is a function. If it is, add the store + * namespace to the stack and wrap the function with the current scope. + * The `withScope` util handles both synchronous functions and generator + * functions. + */ + if ( typeof result === 'function' ) { + setNamespace( ns ); + const scoped = withScope( result ); + resetNamespace(); + return scoped; + } + + // Check if the property is an object. If it is, proxyify it. + if ( isPlainObject( result ) && shouldProxy( result ) ) { + return proxifyStore( ns, result, false ); + } + + return result; + }, +}; + +/** + * Returns the proxy associated with the given store object, creating it if it + * does not exist. + * + * @param namespace The namespace that will be associated to this proxy. + * @param obj The object to proxify. + * + * @param isRoot Whether the passed object is the store root object. + * @throws Error if the object cannot be proxified. Use {@link shouldProxy} to + * check if a proxy can be created for a specific object. + * + * @return The associated proxy. + */ +export const proxifyStore = < T extends object >( + namespace: string, + obj: T, + isRoot = true +): T => { + const proxy = createProxy( namespace, obj, storeHandlers ); + if ( proxy && isRoot ) { + storeRoots.add( proxy ); + } + return proxy as T; +}; diff --git a/packages/interactivity/src/proxies/test/state-proxy.ts b/packages/interactivity/src/proxies/test/state-proxy.ts new file mode 100644 index 00000000000000..92500189fc8309 --- /dev/null +++ b/packages/interactivity/src/proxies/test/state-proxy.ts @@ -0,0 +1,1269 @@ +/* eslint-disable eslint-comments/disable-enable-pair */ +/* eslint-disable @typescript-eslint/no-shadow */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +/** + * External dependencies + */ +import { effect } from '@preact/signals'; +/** + * Internal dependencies + */ +import { proxifyState, peek } from '../'; +import { setScope, resetScope, getContext, getElement } from '../../scopes'; +import { setNamespace, resetNamespace } from '../../namespaces'; + +type State = { + a?: number; + nested: { b?: number }; + array: ( number | State[ 'nested' ] )[]; +}; + +const withScopeAndNs = ( scope, ns, callback ) => () => { + setScope( scope ); + setNamespace( ns ); + try { + return callback(); + } finally { + resetNamespace(); + resetScope(); + } +}; + +describe( 'Interactivity API', () => { + describe( 'state proxy', () => { + let nested = { b: 2 }; + let array = [ 3, nested ]; + let raw: State = { a: 1, nested, array }; + let state = proxifyState( 'test', raw ); + + const window = globalThis as any; + + beforeEach( () => { + nested = { b: 2 }; + array = [ 3, nested ]; + raw = { a: 1, nested, array }; + state = proxifyState( 'test', raw ); + } ); + + describe( 'get', () => { + it( 'should return plain objects/arrays', () => { + expect( state.nested ).toEqual( { b: 2 } ); + expect( state.array ).toEqual( [ 3, { b: 2 } ] ); + expect( state.array[ 1 ] ).toEqual( { b: 2 } ); + } ); + + it( 'should return plain primitives', () => { + expect( state.a ).toBe( 1 ); + expect( state.nested.b ).toBe( 2 ); + expect( state.array[ 0 ] ).toBe( 3 ); + expect( + typeof state.array[ 1 ] === 'object' && state.array[ 1 ].b + ).toBe( 2 ); + expect( state.array.length ).toBe( 2 ); + } ); + + it( 'should support reading from getters', () => { + const state = proxifyState( 'test', { + counter: 1, + get double() { + return state.counter * 2; + }, + } ); + expect( state.double ).toBe( 2 ); + state.counter = 2; + expect( state.double ).toBe( 4 ); + } ); + + it( 'should support getters returning other parts of the state', () => { + const state = proxifyState( 'test', { + switch: 'a', + a: { data: 'a' }, + b: { data: 'b' }, + get aOrB() { + return state.switch === 'a' ? state.a : state.b; + }, + } ); + expect( state.aOrB.data ).toBe( 'a' ); + state.switch = 'b'; + expect( state.aOrB.data ).toBe( 'b' ); + } ); + + it( 'should support getters using ownKeys traps', () => { + const state = proxifyState( 'test', { + x: { + a: 1, + b: 2, + }, + get y() { + return Object.values( state.x ); + }, + } ); + + expect( state.y ).toEqual( [ 1, 2 ] ); + } ); + + it( 'should support getters accessing the scope', () => { + const state = proxifyState( 'test', { + get y() { + const ctx = getContext< { value: string } >(); + return ctx.value; + }, + } ); + + const scope = { context: { test: { value: 'from context' } } }; + try { + setScope( scope as any ); + expect( state.y ).toBe( 'from context' ); + } finally { + resetScope(); + } + } ); + + it( 'should use its namespace by default inside getters', () => { + const state = proxifyState( 'test/right', { + get value() { + const ctx = getContext< { value: string } >(); + return ctx.value; + }, + } ); + + const scope = { + context: { + 'test/right': { value: 'OK' }, + 'test/other': { value: 'Wrong' }, + }, + }; + + try { + setScope( scope as any ); + setNamespace( 'test/other' ); + expect( state.value ).toBe( 'OK' ); + } finally { + resetNamespace(); + resetScope(); + } + } ); + + it( 'should work with normal functions', () => { + const state = proxifyState( 'test', { + value: 1, + isBigger: ( newValue: number ): boolean => + state.value < newValue, + sum( newValue: number ): number { + return state.value + newValue; + }, + replace: ( newValue: number ): void => { + state.value = newValue; + }, + } ); + expect( state.isBigger( 2 ) ).toBe( true ); + expect( state.sum( 2 ) ).toBe( 3 ); + expect( state.value ).toBe( 1 ); + state.replace( 2 ); + expect( state.value ).toBe( 2 ); + } ); + + it( 'should work with normal functions accessing the scope', () => { + const state = proxifyState( 'test', { + sumContextValue( newValue: number ): number { + const ctx = getContext< { value: number } >(); + return ctx.value + newValue; + }, + } ); + + const scope = { context: { test: { value: 1 } } }; + try { + setScope( scope as any ); + expect( state.sumContextValue( 2 ) ).toBe( 3 ); + } finally { + resetScope(); + } + } ); + + it( 'should allow using `this` inside functions', () => { + const state = proxifyState( 'test', { + value: 1, + sum( newValue: number ): number { + return this.value + newValue; + }, + } ); + expect( state.sum( 2 ) ).toBe( 3 ); + } ); + } ); + + describe( 'set', () => { + it( 'should update like plain objects/arrays', () => { + expect( state.a ).toBe( 1 ); + expect( state.nested.b ).toBe( 2 ); + state.a = 2; + state.nested.b = 3; + expect( state.a ).toBe( 2 ); + expect( state.nested.b ).toBe( 3 ); + } ); + + it( 'should support setting values with setters', () => { + const state = proxifyState( 'test', { + counter: 1, + get double() { + return state.counter * 2; + }, + set double( val ) { + state.counter = val / 2; + }, + } ); + expect( state.counter ).toBe( 1 ); + state.double = 4; + expect( state.counter ).toBe( 2 ); + } ); + + it( 'should update array length', () => { + expect( state.array.length ).toBe( 2 ); + state.array.push( 4 ); + expect( state.array.length ).toBe( 3 ); + state.array.splice( 1, 2 ); + expect( state.array.length ).toBe( 1 ); + } ); + + it( 'should support setting getters on the fly', () => { + const state = proxifyState< { + counter: number; + double?: number; + } >( 'test', { + counter: 1, + } ); + Object.defineProperty( state, 'double', { + get() { + return state.counter * 2; + }, + } ); + expect( state.double ).toBe( 2 ); + state.counter = 2; + expect( state.double ).toBe( 4 ); + } ); + + it( 'should support getter modification', () => { + const state = proxifyState< { + counter: number; + double: number; + } >( 'test', { + counter: 1, + get double() { + return state.counter * 2; + }, + } ); + + const scope = { + context: { test: { counter: 2 } }, + }; + + expect( state.double ).toBe( 2 ); + + Object.defineProperty( state, 'double', { + get() { + const ctx = getContext< { counter: number } >(); + return ctx.counter * 2; + }, + } ); + + try { + setScope( scope as any ); + expect( state.double ).toBe( 4 ); + } finally { + resetScope(); + } + } ); + + it( 'should copy object like plain JavaScript', () => { + const state = proxifyState< { + a?: { id: number; nested: { id: number } }; + b: { id: number; nested: { id: number } }; + } >( 'test', { + b: { id: 1, nested: { id: 1 } }, + } ); + + state.a = state.b; + + expect( state.a.id ).toBe( 1 ); + expect( state.b.id ).toBe( 1 ); + expect( state.a.nested.id ).toBe( 1 ); + expect( state.b.nested.id ).toBe( 1 ); + + state.a.id = 2; + state.a.nested.id = 2; + expect( state.a.id ).toBe( 2 ); + expect( state.b.id ).toBe( 2 ); + expect( state.a.nested.id ).toBe( 2 ); + expect( state.b.nested.id ).toBe( 2 ); + + state.b.id = 3; + state.b.nested.id = 3; + expect( state.b.id ).toBe( 3 ); + expect( state.a.id ).toBe( 3 ); + expect( state.a.nested.id ).toBe( 3 ); + expect( state.b.nested.id ).toBe( 3 ); + + state.a.id = 4; + state.a.nested.id = 4; + expect( state.a.id ).toBe( 4 ); + expect( state.b.id ).toBe( 4 ); + expect( state.a.nested.id ).toBe( 4 ); + expect( state.b.nested.id ).toBe( 4 ); + } ); + + it( 'should be able to reset values with Object.assign', () => { + const initialNested = { ...nested }; + const initialState = { ...raw, nested: initialNested }; + state.a = 2; + state.nested.b = 3; + Object.assign( state, initialState ); + expect( state.a ).toBe( 1 ); + expect( state.nested.b ).toBe( 2 ); + } ); + + it( 'should keep assigned object references internally', () => { + const obj = {}; + state.nested = obj; + expect( raw.nested ).toBe( obj ); + } ); + + it( 'should keep object references across namespaces', () => { + const raw1 = { obj: {} }; + const raw2 = { obj: {} }; + const state1 = proxifyState( 'test-1', raw1 ); + const state2 = proxifyState( 'test-2', raw2 ); + state2.obj = state1.obj; + expect( state2.obj ).toBe( state1.obj ); + expect( raw2.obj ).toBe( state1.obj ); + } ); + + it( 'should use its namespace by default inside setters', () => { + const state = proxifyState( 'test/right', { + set counter( val: number ) { + const ctx = getContext< { counter: number } >(); + ctx.counter = val; + }, + } ); + + const scope = { + context: { + 'test/other': { counter: 0 }, + 'test/right': { counter: 0 }, + }, + }; + + try { + setScope( scope as any ); + setNamespace( 'test/other' ); + state.counter = 4; + expect( scope.context[ 'test/right' ].counter ).toBe( 4 ); + } finally { + resetNamespace(); + resetScope(); + } + } ); + } ); + + describe( 'computations', () => { + it( 'should subscribe to values mutated with setters', () => { + const state = proxifyState( 'test', { + counter: 1, + get double() { + return state.counter * 2; + }, + set double( val ) { + state.counter = val / 2; + }, + } ); + let counter = 0; + let double = 0; + + effect( () => { + counter = state.counter; + double = state.double; + } ); + + expect( counter ).toBe( 1 ); + expect( double ).toBe( 2 ); + state.double = 4; + expect( counter ).toBe( 2 ); + expect( double ).toBe( 4 ); + } ); + + it( 'should subscribe to changes when an item is removed from the array', () => { + const state = proxifyState( 'test', [ 0, 0, 0 ] ); + let sum = 0; + + effect( () => { + sum = 0; + sum = state.reduce( ( sum ) => sum + 1, 0 ); + } ); + + expect( sum ).toBe( 3 ); + state.splice( 2, 1 ); + expect( sum ).toBe( 2 ); + } ); + + it( 'should subscribe to changes to for..in loops', () => { + const raw: Record< string, number > = { a: 0, b: 0 }; + const state = proxifyState( 'test', raw ); + let sum = 0; + + effect( () => { + sum = 0; + for ( const _ in state ) { + sum += 1; + } + } ); + + expect( sum ).toBe( 2 ); + + state.c = 0; + expect( sum ).toBe( 3 ); + + delete state.c; + expect( sum ).toBe( 2 ); + + state.c = 0; + expect( sum ).toBe( 3 ); + } ); + + it( 'should subscribe to changes for Object.getOwnPropertyNames()', () => { + const raw: Record< string, number > = { a: 1, b: 2 }; + const state = proxifyState( 'test', raw ); + let sum = 0; + + effect( () => { + sum = 0; + const keys = Object.getOwnPropertyNames( state ); + for ( const _ of keys ) { + sum += 1; + } + } ); + + expect( sum ).toBe( 2 ); + + state.c = 0; + expect( sum ).toBe( 3 ); + + delete state.a; + expect( sum ).toBe( 2 ); + } ); + + it( 'should subscribe to changes to Object.keys/values/entries()', () => { + const raw: Record< string, number > = { a: 1, b: 2 }; + const state = proxifyState( 'test', raw ); + let keys = 0; + let values = 0; + let entries = 0; + + effect( () => { + keys = 0; + Object.keys( state ).forEach( () => ( keys += 1 ) ); + } ); + + effect( () => { + values = 0; + Object.values( state ).forEach( () => ( values += 1 ) ); + } ); + + effect( () => { + entries = 0; + Object.entries( state ).forEach( () => ( entries += 1 ) ); + } ); + + expect( keys ).toBe( 2 ); + expect( values ).toBe( 2 ); + expect( entries ).toBe( 2 ); + + state.c = 0; + expect( keys ).toBe( 3 ); + expect( values ).toBe( 3 ); + expect( entries ).toBe( 3 ); + + delete state.a; + expect( keys ).toBe( 2 ); + expect( values ).toBe( 2 ); + expect( entries ).toBe( 2 ); + } ); + + it( 'should subscribe to changes to for..of loops', () => { + const state = proxifyState( 'test', [ 0, 0 ] ); + let sum = 0; + + effect( () => { + sum = 0; + for ( const _ of state ) { + sum += 1; + } + } ); + + expect( sum ).toBe( 2 ); + + state.push( 0 ); + expect( sum ).toBe( 3 ); + + state.splice( 0, 1 ); + expect( sum ).toBe( 2 ); + } ); + + it( 'should subscribe to implicit changes in length', () => { + const state = proxifyState( 'test', [ 'foo', 'bar' ] ); + let x = ''; + + effect( () => { + x = state.join( ' ' ); + } ); + + expect( x ).toBe( 'foo bar' ); + + state.push( 'baz' ); + expect( x ).toBe( 'foo bar baz' ); + + state.splice( 0, 1 ); + expect( x ).toBe( 'bar baz' ); + } ); + + it( 'should subscribe to changes when deleting properties', () => { + let x, y; + + effect( () => { + x = state.a; + } ); + + effect( () => { + y = state.nested.b; + } ); + + expect( x ).toBe( 1 ); + delete state.a; + expect( x ).toBe( undefined ); + + expect( y ).toBe( 2 ); + delete state.nested.b; + expect( y ).toBe( undefined ); + } ); + + it( 'should subscribe to changes when mutating objects', () => { + let x, y; + + const state = proxifyState< { + a?: { id: number; nested: { id: number } }; + b: { id: number; nested: { id: number } }[]; + } >( 'test', { + b: [ + { id: 1, nested: { id: 1 } }, + { id: 2, nested: { id: 2 } }, + ], + } ); + + effect( () => { + x = state.a?.id; + } ); + + effect( () => { + y = state.a?.nested.id; + } ); + + expect( x ).toBe( undefined ); + expect( y ).toBe( undefined ); + + state.a = state.b[ 0 ]; + + expect( x ).toBe( 1 ); + expect( y ).toBe( 1 ); + + state.a = state.b[ 1 ]; + expect( x ).toBe( 2 ); + expect( y ).toBe( 2 ); + + state.a = undefined; + expect( x ).toBe( undefined ); + expect( y ).toBe( undefined ); + + state.a = state.b[ 1 ]; + expect( x ).toBe( 2 ); + expect( y ).toBe( 2 ); + } ); + + it( 'should trigger effects after mutations happen', () => { + let x; + effect( () => { + x = state.a; + } ); + expect( x ).toBe( 1 ); + state.a = 11; + expect( x ).toBe( 11 ); + } ); + + it( 'should subscribe corretcly from getters', () => { + let x; + const state = proxifyState( 'test', { + counter: 1, + get double() { + return state.counter * 2; + }, + } ); + effect( () => ( x = state.double ) ); + expect( x ).toBe( 2 ); + state.counter = 2; + expect( x ).toBe( 4 ); + } ); + + it( 'should subscribe corretcly from getters returning other parts of the state', () => { + let data; + const state = proxifyState( 'test', { + switch: 'a', + a: { data: 'a' }, + b: { data: 'b' }, + get aOrB() { + return state.switch === 'a' ? state.a : state.b; + }, + } ); + effect( () => ( data = state.aOrB.data ) ); + expect( data ).toBe( 'a' ); + state.switch = 'b'; + expect( data ).toBe( 'b' ); + } ); + + it( 'should subscribe to changes', () => { + const spy1 = jest.fn( () => state.a ); + const spy2 = jest.fn( () => state.nested ); + const spy3 = jest.fn( () => state.nested.b ); + const spy4 = jest.fn( () => state.array[ 0 ] ); + const spy5 = jest.fn( + () => + typeof state.array[ 1 ] === 'object' && + state.array[ 1 ].b + ); + + effect( spy1 ); + effect( spy2 ); + effect( spy3 ); + effect( spy4 ); + effect( spy5 ); + + expect( spy1 ).toHaveBeenCalledTimes( 1 ); + expect( spy2 ).toHaveBeenCalledTimes( 1 ); + expect( spy3 ).toHaveBeenCalledTimes( 1 ); + expect( spy4 ).toHaveBeenCalledTimes( 1 ); + expect( spy5 ).toHaveBeenCalledTimes( 1 ); + + state.a = 11; + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 1 ); + expect( spy3 ).toHaveBeenCalledTimes( 1 ); + expect( spy4 ).toHaveBeenCalledTimes( 1 ); + expect( spy5 ).toHaveBeenCalledTimes( 1 ); + + state.nested.b = 22; + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 1 ); + expect( spy3 ).toHaveBeenCalledTimes( 2 ); + expect( spy4 ).toHaveBeenCalledTimes( 1 ); + expect( spy5 ).toHaveBeenCalledTimes( 2 ); // nested also exists array[1] + + state.nested = { b: 222 }; + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 2 ); + expect( spy3 ).toHaveBeenCalledTimes( 3 ); + expect( spy4 ).toHaveBeenCalledTimes( 1 ); + expect( spy5 ).toHaveBeenCalledTimes( 2 ); // now state.nested has a different reference + + state.array[ 0 ] = 33; + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 2 ); + expect( spy3 ).toHaveBeenCalledTimes( 3 ); + expect( spy4 ).toHaveBeenCalledTimes( 2 ); + expect( spy5 ).toHaveBeenCalledTimes( 2 ); + + if ( typeof state.array[ 1 ] === 'object' ) { + state.array[ 1 ].b = 2222; + } + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 2 ); + expect( spy3 ).toHaveBeenCalledTimes( 3 ); + expect( spy4 ).toHaveBeenCalledTimes( 2 ); + expect( spy5 ).toHaveBeenCalledTimes( 3 ); + + state.array[ 1 ] = { b: 22222 }; + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 2 ); + expect( spy3 ).toHaveBeenCalledTimes( 3 ); + expect( spy4 ).toHaveBeenCalledTimes( 2 ); + expect( spy5 ).toHaveBeenCalledTimes( 4 ); + + state.array.push( 4 ); + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 2 ); + expect( spy3 ).toHaveBeenCalledTimes( 3 ); + expect( spy4 ).toHaveBeenCalledTimes( 2 ); + expect( spy5 ).toHaveBeenCalledTimes( 4 ); + + state.array[ 3 ] = 5; + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 2 ); + expect( spy3 ).toHaveBeenCalledTimes( 3 ); + expect( spy4 ).toHaveBeenCalledTimes( 2 ); + expect( spy5 ).toHaveBeenCalledTimes( 4 ); + + state.array = [ 333, { b: 222222 } ]; + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 2 ); + expect( spy3 ).toHaveBeenCalledTimes( 3 ); + expect( spy4 ).toHaveBeenCalledTimes( 3 ); + expect( spy5 ).toHaveBeenCalledTimes( 5 ); + } ); + + it( 'should subscribe to array length', () => { + const array = [ 1 ]; + const state = proxifyState( 'test', { array } ); + const spy1 = jest.fn( () => state.array.length ); + const spy2 = jest.fn( () => + state.array.map( ( i: number ) => i ) + ); + + effect( spy1 ); + effect( spy2 ); + expect( spy1 ).toHaveBeenCalledTimes( 1 ); + expect( spy2 ).toHaveBeenCalledTimes( 1 ); + + state.array.push( 2 ); + expect( state.array.length ).toBe( 2 ); + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 2 ); + + state.array[ 2 ] = 3; + expect( state.array.length ).toBe( 3 ); + expect( spy1 ).toHaveBeenCalledTimes( 3 ); + expect( spy2 ).toHaveBeenCalledTimes( 3 ); + + state.array = state.array.filter( ( i: number ) => i <= 2 ); + expect( state.array.length ).toBe( 2 ); + expect( spy1 ).toHaveBeenCalledTimes( 4 ); + expect( spy2 ).toHaveBeenCalledTimes( 4 ); + } ); + + it( 'should be able to reset values with Object.assign and still react to changes', () => { + const initialNested = { ...nested }; + const initialState = { ...raw, nested: initialNested }; + let a, b; + + effect( () => { + a = state.a; + } ); + effect( () => { + b = state.nested.b; + } ); + + state.a = 2; + state.nested.b = 3; + + expect( a ).toBe( 2 ); + expect( b ).toBe( 3 ); + + Object.assign( state, initialState ); + + expect( a ).toBe( 1 ); + expect( b ).toBe( 2 ); + } ); + + it( 'should keep subscribed to properties that become getters', () => { + const state = proxifyState( 'test', { + number: 1, + } ); + + let number = 0; + + effect( () => { + number = state.number; + } ); + + expect( number ).toBe( 1 ); + state.number = 2; + expect( number ).toBe( 2 ); + Object.defineProperty( state, 'number', { + get: () => 3, + configurable: true, + } ); + expect( number ).toBe( 3 ); + } ); + + it( 'should keep subscribed to modified getters', () => { + const state = proxifyState< { + counter: number; + double: number; + } >( 'test', { + counter: 1, + get double() { + return state.counter * 2; + }, + } ); + + const scope = { + context: { test: { counter: 2 } }, + }; + + let double = 0; + + effect( + withScopeAndNs( scope, 'test', () => { + double = state.double; + } ) + ); + + expect( double ).toBe( 2 ); + + Object.defineProperty( state, 'double', { + get() { + const ctx = getContext< { counter: number } >(); + return ctx.counter * 2; + }, + } ); + + expect( double ).toBe( 4 ); + } ); + + it( 'should react to changes in props inside getters', () => { + const state = proxifyState( 'test', { + number: 1, + otherNumber: 3, + } ); + + let number = 0; + + effect( () => { + number = state.number; + } ); + + expect( number ).toBe( 1 ); + state.number = 2; + expect( number ).toBe( 2 ); + Object.defineProperty( state, 'number', { + get: () => state.otherNumber, + configurable: true, + } ); + expect( number ).toBe( 3 ); + state.otherNumber = 4; + expect( number ).toBe( 4 ); + } ); + + it( 'should react to changes in props inside getters if they become getters', () => { + const state = proxifyState( 'test', { + number: 1, + otherNumber: 3, + } ); + + let number = 0; + + effect( () => { + number = state.number; + } ); + + expect( number ).toBe( 1 ); + state.number = 2; + expect( number ).toBe( 2 ); + Object.defineProperty( state, 'number', { + get: () => state.otherNumber, + configurable: true, + } ); + expect( number ).toBe( 3 ); + state.otherNumber = 4; + expect( number ).toBe( 4 ); + Object.defineProperty( state, 'otherNumber', { + get: () => 5, + configurable: true, + } ); + expect( number ).toBe( 5 ); + } ); + + it( 'should allow getters to use `this`', () => { + const state = proxifyState( 'test', { + number: 1, + otherNumber: 3, + } ); + + let number = 0; + + effect( () => { + number = state.number; + } ); + + expect( number ).toBe( 1 ); + state.number = 2; + expect( number ).toBe( 2 ); + Object.defineProperty( state, 'number', { + get() { + return this.otherNumber; + }, + configurable: true, + } ); + expect( number ).toBe( 3 ); + state.otherNumber = 4; + expect( number ).toBe( 4 ); + } ); + + it( 'should support different scopes for the same getter', () => { + const state = proxifyState( 'test', { + number: 1, + get numWithTag() { + let tag = 'No scope'; + try { + tag = getContext< any >().tag; + } catch ( e ) {} + return `${ tag }: ${ this.number }`; + }, + } ); + + const scopeA = { + context: { test: { tag: 'A' } }, + }; + const scopeB = { + context: { test: { tag: 'B' } }, + }; + + let resultA = ''; + let resultB = ''; + let resultNoScope = ''; + + effect( + withScopeAndNs( scopeA, 'test', () => { + resultA = state.numWithTag; + } ) + ); + effect( + withScopeAndNs( scopeB, 'test', () => { + resultB = state.numWithTag; + } ) + ); + effect( () => { + resultNoScope = state.numWithTag; + } ); + + expect( resultA ).toBe( 'A: 1' ); + expect( resultB ).toBe( 'B: 1' ); + expect( resultNoScope ).toBe( 'No scope: 1' ); + state.number = 2; + expect( resultA ).toBe( 'A: 2' ); + expect( resultB ).toBe( 'B: 2' ); + expect( resultNoScope ).toBe( 'No scope: 2' ); + } ); + + it( 'should throw an error in getters that require a scope', () => { + const state = proxifyState( 'test', { + number: 1, + get sumValueFromContext() { + const ctx = getContext(); + return ctx + ? this.number + ( ctx as any ).value + : this.number; + }, + get sumValueFromElement() { + const element = getElement(); + return element + ? this.number + element.attributes.value + : this.number; + }, + } ); + + expect( () => state.sumValueFromContext ).toThrow(); + expect( () => state.sumValueFromElement ).toThrow(); + } ); + + it( 'should react to changes in props inside functions', () => { + const state = proxifyState( 'test', { + number: 1, + otherNumber: 3, + sum( value: number ) { + return state.number + state.otherNumber + value; + }, + } ); + + let result = 0; + + effect( () => { + result = state.sum( 2 ); + } ); + + expect( result ).toBe( 6 ); + state.number = 2; + expect( result ).toBe( 7 ); + state.otherNumber = 4; + expect( result ).toBe( 8 ); + } ); + } ); + + describe( 'peek', () => { + it( 'should return correct values when using peek()', () => { + expect( peek( state, 'a' ) ).toBe( 1 ); + expect( peek( state.nested, 'b' ) ).toBe( 2 ); + expect( peek( state.array, 0 ) ).toBe( 3 ); + const nested = peek( state, 'array' )[ 1 ]; + expect( typeof nested === 'object' && nested.b ).toBe( 2 ); + expect( peek( state.array, 'length' ) ).toBe( 2 ); + } ); + + it( 'should not subscribe to changes when peeking', () => { + const spy1 = jest.fn( () => peek( state, 'a' ) ); + const spy2 = jest.fn( () => peek( state, 'nested' ) ); + const spy3 = jest.fn( () => peek( state, 'nested' ).b ); + const spy4 = jest.fn( () => peek( state, 'array' )[ 0 ] ); + const spy5 = jest.fn( () => { + const nested = peek( state, 'array' )[ 1 ]; + return typeof nested === 'object' && nested.b; + } ); + const spy6 = jest.fn( () => peek( state, 'array' ).length ); + + effect( spy1 ); + effect( spy2 ); + effect( spy3 ); + effect( spy4 ); + effect( spy5 ); + effect( spy6 ); + + expect( spy1 ).toHaveBeenCalledTimes( 1 ); + expect( spy2 ).toHaveBeenCalledTimes( 1 ); + expect( spy3 ).toHaveBeenCalledTimes( 1 ); + expect( spy4 ).toHaveBeenCalledTimes( 1 ); + expect( spy5 ).toHaveBeenCalledTimes( 1 ); + expect( spy6 ).toHaveBeenCalledTimes( 1 ); + + state.a = 11; + state.nested.b = 22; + state.nested = { b: 222 }; + state.array[ 0 ] = 33; + if ( typeof state.array[ 1 ] === 'object' ) { + state.array[ 1 ].b = 2222; + } + state.array.push( 4 ); + + expect( spy1 ).toHaveBeenCalledTimes( 1 ); + expect( spy2 ).toHaveBeenCalledTimes( 1 ); + expect( spy3 ).toHaveBeenCalledTimes( 1 ); + expect( spy4 ).toHaveBeenCalledTimes( 1 ); + expect( spy5 ).toHaveBeenCalledTimes( 1 ); + expect( spy6 ).toHaveBeenCalledTimes( 1 ); + } ); + + it( 'should subscribe to some changes but not other when peeking inside an object', () => { + const spy1 = jest.fn( () => peek( state.nested, 'b' ) ); + effect( spy1 ); + expect( spy1 ).toHaveBeenCalledTimes( 1 ); + state.nested.b = 22; + expect( spy1 ).toHaveBeenCalledTimes( 1 ); + state.nested = { b: 222 }; + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + state.nested.b = 2222; + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + } ); + + it( 'should support returning peek from getters', () => { + const state = proxifyState( 'test', { + counter: 1, + get double() { + return state.counter * 2; + }, + } ); + expect( peek( state, 'double' ) ).toBe( 2 ); + state.counter = 2; + expect( peek( state, 'double' ) ).toBe( 4 ); + } ); + + it( 'should support peeking getters accessing the scope', () => { + const state = proxifyState( 'test', { + get double() { + const { counter } = getContext< { counter: number } >(); + return counter * 2; + }, + } ); + + const context = proxifyState( 'test', { counter: 1 } ); + const scope = { context: { test: context } }; + const peekStateDouble = withScopeAndNs( scope, 'test', () => + peek( state, 'double' ) + ); + + const spy = jest.fn( peekStateDouble ); + effect( spy ); + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( peekStateDouble() ).toBe( 2 ); + + context.counter = 2; + + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( peekStateDouble() ).toBe( 4 ); + } ); + + it( 'should support peeking getters accessing other namespaces', () => { + const state2 = proxifyState( 'test2', { + get counter() { + const { counter } = getContext< { counter: number } >(); + return counter; + }, + } ); + const context2 = proxifyState( 'test-2', { counter: 1 } ); + + const state1 = proxifyState( 'test1', { + get double() { + return state2.counter * 2; + }, + } ); + + const peekStateDouble = withScopeAndNs( + { context: { test2: context2 } }, + 'test2', + () => peek( state1, 'double' ) + ); + + const spy = jest.fn( peekStateDouble ); + effect( spy ); + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( peekStateDouble() ).toBe( 2 ); + + context2.counter = 2; + + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( peekStateDouble() ).toBe( 4 ); + } ); + } ); + + describe( 'refs', () => { + it( 'should preserve object references', () => { + expect( state.nested ).toBe( state.array[ 1 ] ); + + state.nested.b = 22; + + expect( state.nested ).toBe( state.array[ 1 ] ); + expect( state.nested.b ).toBe( 22 ); + expect( + typeof state.array[ 1 ] === 'object' && state.array[ 1 ].b + ).toBe( 22 ); + + state.nested = { b: 222 }; + + expect( state.nested ).not.toBe( state.array[ 1 ] ); + expect( state.nested.b ).toBe( 222 ); + expect( + typeof state.array[ 1 ] === 'object' && state.array[ 1 ].b + ).toBe( 22 ); + } ); + + it( 'should return the same proxy if initialized more than once', () => { + const raw = {}; + const state1 = proxifyState( 'test', raw ); + const state2 = proxifyState( 'test', raw ); + expect( state1 ).toBe( state2 ); + } ); + + it( 'should throw when trying to re-proxify a state object', () => { + const state = proxifyState( 'test', {} ); + expect( () => proxifyState( 'test', state ) ).toThrow(); + } ); + } ); + + describe( 'unsupported data structures', () => { + it( 'should throw when trying to proxify a class instance', () => { + class MyClass {} + const obj = new MyClass(); + expect( () => proxifyState( 'test', obj ) ).toThrow(); + } ); + + it( 'should not wrap a class instance', () => { + class MyClass {} + const obj = new MyClass(); + const state = proxifyState( 'test', { obj } ); + expect( state.obj ).toBe( obj ); + } ); + + it( 'should not wrap built-ins in proxies', () => { + window.MyClass = class MyClass {}; + const obj = new window.MyClass(); + const state = proxifyState( 'test', { obj } ); + expect( state.obj ).toBe( obj ); + } ); + + it( 'should not wrap elements in proxies', () => { + const el = window.document.createElement( 'div' ); + const state = proxifyState( 'test', { el } ); + expect( state.el ).toBe( el ); + } ); + + it( 'should wrap global objects', () => { + window.obj = { b: 2 }; + const state = proxifyState( 'test', window.obj ); + expect( state ).not.toBe( window.obj ); + expect( state ).toStrictEqual( { b: 2 } ); + } ); + + it( 'should not wrap dates', () => { + const date = new Date(); + const state = proxifyState( 'test', { date } ); + expect( state.date ).toBe( date ); + } ); + + it( 'should not wrap regular expressions', () => { + const regex = new RegExp( '' ); + const state = proxifyState( 'test', { regex } ); + expect( state.regex ).toBe( regex ); + } ); + + it( 'should not wrap Map', () => { + const map = new Map(); + const state = proxifyState( 'test', { map } ); + expect( state.map ).toBe( map ); + } ); + + it( 'should not wrap Set', () => { + const set = new Set(); + const state = proxifyState( 'test', { set } ); + expect( state.set ).toBe( set ); + } ); + } ); + + describe( 'symbols', () => { + it( 'should observe symbols', () => { + const key = Symbol( 'key' ); + let x; + const store = proxifyState< { [ key: symbol ]: any } >( + 'test', + {} + ); + effect( () => ( x = store[ key ] ) ); + + expect( store[ key ] ).toBe( undefined ); + expect( x ).toBe( undefined ); + + store[ key ] = true; + + expect( store[ key ] ).toBe( true ); + expect( x ).toBe( true ); + } ); + + it( 'should not observe well-known symbols', () => { + const key = Symbol.isConcatSpreadable; + let x; + const state = proxifyState< { [ key: symbol ]: any } >( + 'test', + {} + ); + effect( () => ( x = state[ key ] ) ); + + expect( state[ key ] ).toBe( undefined ); + expect( x ).toBe( undefined ); + + state[ key ] = true; + expect( state[ key ] ).toBe( true ); + expect( x ).toBe( undefined ); + } ); + } ); + } ); +} ); diff --git a/packages/interactivity/src/proxies/test/store-proxy.ts b/packages/interactivity/src/proxies/test/store-proxy.ts new file mode 100644 index 00000000000000..225621072929d0 --- /dev/null +++ b/packages/interactivity/src/proxies/test/store-proxy.ts @@ -0,0 +1,123 @@ +/** + * Internal dependencies + */ +import { proxifyStore, proxifyState } from '../'; +import { setScope, resetScope, getContext } from '../../scopes'; +import { setNamespace, resetNamespace } from '../../namespaces'; + +describe( 'Interactivity API', () => { + describe( 'store proxy', () => { + describe( 'get', () => { + it( 'should initialize properties at the top level if they do not exist', () => { + const store = proxifyStore< any >( 'test', {} ); + expect( store.state.props ).toBeUndefined(); + expect( store.state ).toEqual( {} ); + } ); + + it( 'should wrap sync functions with the store namespace and current scope', () => { + let result = ''; + + const syncFunc = () => { + const ctx = getContext< { value: string } >(); + result = ctx.value; + }; + + const storeTest = proxifyStore( 'test', { + callbacks: { + syncFunc, + nested: { syncFunc }, + }, + } ); + + const scope = { + context: { + test: { value: 'test' }, + }, + }; + + setNamespace( 'other-namespace' ); + setScope( scope as any ); + + storeTest.callbacks.syncFunc(); + expect( result ).toBe( 'test' ); + storeTest.callbacks.nested.syncFunc(); + expect( result ).toBe( 'test' ); + + resetScope(); + resetNamespace(); + } ); + + it( 'should wrap generators into async functions', async () => { + const asyncFunc = function* () { + const data = yield Promise.resolve( 'data' ); + const ctx = getContext< { value: string } >(); + return `${ data } from ${ ctx.value }`; + }; + + const storeTest = proxifyStore( 'test', { + callbacks: { asyncFunc, nested: { asyncFunc } }, + } ); + + const scope = { + context: { + test: { value: 'test' }, + }, + }; + + setNamespace( 'other-namespace' ); + setScope( scope as any ); + const promise1 = storeTest.callbacks.asyncFunc(); + const promise2 = storeTest.callbacks.nested.asyncFunc(); + resetScope(); + resetNamespace(); + + expect( await promise1 ).toBe( 'data from test' ); + expect( await promise2 ).toBe( 'data from test' ); + } ); + + it( 'should allow async functions to call functions from other stores', async () => { + const asyncFunc = function* () { + const data = yield Promise.resolve( 'data' ); + const ctx = getContext< { value: string } >(); + return `${ data } from ${ ctx.value }`; + }; + + const storeTest1 = proxifyStore( 'test1', { + callbacks: { asyncFunc }, + } ); + + const storeTest2 = proxifyStore( 'test2', { + callbacks: { + *asyncFunc() { + const result = + yield storeTest1.callbacks.asyncFunc(); + return result; + }, + }, + } ); + + const scope = { + context: { + test1: { value: 'test1' }, + test2: { value: 'test2' }, + }, + }; + + setNamespace( 'other-namespace' ); + setScope( scope as any ); + const promise = storeTest2.callbacks.asyncFunc(); + resetScope(); + resetNamespace(); + + expect( await promise ).toBe( 'data from test1' ); + } ); + + it( 'should not wrap other proxified objects with a store proxy', () => { + const state = proxifyState( 'test', {} ); + const store = proxifyStore( 'test', { state } ); + + expect( store.state ).toBe( state ); + } ); + } ); + } ); +} ); diff --git a/packages/interactivity/src/scopes.ts b/packages/interactivity/src/scopes.ts new file mode 100644 index 00000000000000..2e78755ec4bbe6 --- /dev/null +++ b/packages/interactivity/src/scopes.ts @@ -0,0 +1,98 @@ +/** + * External dependencies + */ +import type { h as createElement, RefObject } from 'preact'; + +/** + * Internal dependencies + */ +import { getNamespace } from './namespaces'; +import type { Evaluate } from './hooks'; + +export interface Scope { + evaluate: Evaluate; + context: object; + ref: RefObject< HTMLElement >; + attributes: createElement.JSX.HTMLAttributes; +} + +// Store stacks for the current scope and the default namespaces and export APIs +// to interact with them. +const scopeStack: Scope[] = []; + +export const getScope = () => scopeStack.slice( -1 )[ 0 ]; + +export const setScope = ( scope: Scope ) => { + scopeStack.push( scope ); +}; +export const resetScope = () => { + scopeStack.pop(); +}; + +// Wrap the element props to prevent modifications. +const immutableMap = new WeakMap(); +const immutableError = () => { + throw new Error( + 'Please use `data-wp-bind` to modify the attributes of an element.' + ); +}; +const immutableHandlers: ProxyHandler< object > = { + get( target, key, receiver ) { + const value = Reflect.get( target, key, receiver ); + return !! value && typeof value === 'object' + ? deepImmutable( value ) + : value; + }, + set: immutableError, + deleteProperty: immutableError, +}; +const deepImmutable = < T extends object = {} >( target: T ): T => { + if ( ! immutableMap.has( target ) ) { + immutableMap.set( target, new Proxy( target, immutableHandlers ) ); + } + return immutableMap.get( target ); +}; + +/** + * Retrieves the context inherited by the element evaluating a function from the + * store. The returned value depends on the element and the namespace where the + * function calling `getContext()` exists. + * + * @param namespace Store namespace. By default, the namespace where the calling + * function exists is used. + * @return The context content. + */ +export const getContext = < T extends object >( namespace?: string ): T => { + const scope = getScope(); + if ( globalThis.SCRIPT_DEBUG ) { + if ( ! scope ) { + throw Error( + 'Cannot call `getContext()` when there is no scope. If you are using an async function, please consider using a generator instead. If you are using some sort of async callbacks, like `setTimeout`, please wrap the callback with `withScope(callback)`.' + ); + } + } + return scope.context[ namespace || getNamespace() ]; +}; + +/** + * Retrieves a representation of the element where a function from the store + * is being evalutated. Such representation is read-only, and contains a + * reference to the DOM element, its props and a local reactive state. + * + * @return Element representation. + */ +export const getElement = () => { + const scope = getScope(); + if ( globalThis.SCRIPT_DEBUG ) { + if ( ! scope ) { + throw Error( + 'Cannot call `getElement()` when there is no scope. If you are using an async function, please consider using a generator instead. If you are using some sort of async callbacks, like `setTimeout`, please wrap the callback with `withScope(callback)`.' + ); + } + } + const { ref, attributes } = scope; + return Object.freeze( { + ref: ref.current, + attributes: deepImmutable( attributes ), + } ); +}; diff --git a/packages/interactivity/src/store.ts b/packages/interactivity/src/store.ts index 281a6c266021e1..25fa64eb6e160e 100644 --- a/packages/interactivity/src/store.ts +++ b/packages/interactivity/src/store.ts @@ -1,175 +1,18 @@ /** - * External dependencies + * Internal dependencies */ -import { deepSignal } from 'deepsignal'; -import { computed } from '@preact/signals'; - +import { proxifyState, proxifyStore } from './proxies'; /** - * Internal dependencies + * External dependencies */ -import { - getScope, - setScope, - resetScope, - getNamespace, - setNamespace, - resetNamespace, -} from './hooks'; -const isObject = ( item: unknown ): item is Record< string, unknown > => - Boolean( item && typeof item === 'object' && item.constructor === Object ); - -const deepMerge = ( target: any, source: any ) => { - if ( isObject( target ) && isObject( source ) ) { - for ( const key in source ) { - const getter = Object.getOwnPropertyDescriptor( source, key )?.get; - if ( typeof getter === 'function' ) { - Object.defineProperty( target, key, { get: getter } ); - } else if ( isObject( source[ key ] ) ) { - if ( ! target[ key ] ) { - target[ key ] = {}; - } - deepMerge( target[ key ], source[ key ] ); - } else { - try { - target[ key ] = source[ key ]; - } catch ( e ) { - // Assignemnts fail for properties that are only getters. - // When that's the case, the assignment is simply ignored. - } - } - } - } -}; +import { getNamespace } from './namespaces'; +import { deepMerge, isPlainObject } from './utils'; export const stores = new Map(); const rawStores = new Map(); const storeLocks = new Map(); const storeConfigs = new Map(); -const objToProxy = new WeakMap(); -const proxyToNs = new WeakMap(); -const scopeToGetters = new WeakMap(); - -const proxify = ( obj: any, ns: string ) => { - if ( ! objToProxy.has( obj ) ) { - const proxy = new Proxy( obj, handlers ); - objToProxy.set( obj, proxy ); - proxyToNs.set( proxy, ns ); - } - return objToProxy.get( obj ); -}; - -const handlers = { - get: ( target: any, key: string | symbol, receiver: any ) => { - const ns = proxyToNs.get( receiver ); - - // Check if the property is a getter and we are inside an scope. If that is - // the case, we clone the getter to avoid overwriting the scoped - // dependencies of the computed each time that getter runs. - const getter = Object.getOwnPropertyDescriptor( target, key )?.get; - if ( getter ) { - const scope = getScope(); - if ( scope ) { - const getters = - scopeToGetters.get( scope ) || - scopeToGetters.set( scope, new Map() ).get( scope ); - if ( ! getters.has( getter ) ) { - getters.set( - getter, - computed( () => { - setNamespace( ns ); - setScope( scope ); - try { - return getter.call( target ); - } finally { - resetScope(); - resetNamespace(); - } - } ) - ); - } - return getters.get( getter ).value; - } - } - - const result = Reflect.get( target, key ); - - // Check if the proxy is the store root and no key with that name exist. In - // that case, return an empty object for the requested key. - if ( typeof result === 'undefined' && receiver === stores.get( ns ) ) { - const obj = {}; - Reflect.set( target, key, obj ); - return proxify( obj, ns ); - } - - // Check if the property is a generator. If it is, we turn it into an - // asynchronous function where we restore the default namespace and scope - // each time it awaits/yields. - if ( result?.constructor?.name === 'GeneratorFunction' ) { - return async ( ...args: unknown[] ) => { - const scope = getScope(); - const gen: Generator< any > = result( ...args ); - - let value: unknown; - let it: IteratorResult< any >; - - while ( true ) { - setNamespace( ns ); - setScope( scope ); - try { - it = gen.next( value ); - } finally { - resetScope(); - resetNamespace(); - } - - try { - value = await it.value; - } catch ( e ) { - setNamespace( ns ); - setScope( scope ); - gen.throw( e ); - } finally { - resetScope(); - resetNamespace(); - } - - if ( it.done ) { - break; - } - } - - return value; - }; - } - - // Check if the property is a synchronous function. If it is, set the - // default namespace. Synchronous functions always run in the proper scope, - // which is set by the Directives component. - if ( typeof result === 'function' ) { - return ( ...args: unknown[] ) => { - setNamespace( ns ); - try { - return result( ...args ); - } finally { - resetNamespace(); - } - }; - } - - // Check if the property is an object. If it is, proxyify it. - if ( isObject( result ) ) { - return proxify( result, ns ); - } - - return result; - }, - // Prevents passing the current proxy as the receiver to the deepSignal. - set( target: any, key: string, value: any ) { - return Reflect.set( target, key, value ); - }, -}; - /** * Get the defined config for the store with the passed namespace. * @@ -280,13 +123,15 @@ export function store( storeLocks.set( namespace, lock ); } const rawStore = { - state: deepSignal( isObject( state ) ? state : {} ), + state: proxifyState( + namespace, + isPlainObject( state ) ? state : {} + ), ...block, }; - const proxiedStore = new Proxy( rawStore, handlers ); + const proxifiedStore = proxifyStore( namespace, rawStore ); rawStores.set( namespace, rawStore ); - stores.set( namespace, proxiedStore ); - proxyToNs.set( proxiedStore, namespace ); + stores.set( namespace, proxifiedStore ); } else { // Lock the store if it wasn't locked yet and the passed lock is // different from the universal unlock. If no lock is given, the store @@ -318,7 +163,7 @@ export function store( return stores.get( namespace ); } -export const parseInitialData = ( dom = document ) => { +export const parseServerData = ( dom = document ) => { const jsonDataScriptTag = // Preferred Script Module data passing form dom.getElementById( @@ -334,16 +179,17 @@ export const parseInitialData = ( dom = document ) => { return {}; }; -export const populateInitialData = ( data?: { +export const populateServerData = ( data?: { state?: Record< string, unknown >; config?: Record< string, unknown >; } ) => { - if ( isObject( data?.state ) ) { + if ( isPlainObject( data?.state ) ) { Object.entries( data!.state ).forEach( ( [ namespace, state ] ) => { - store( namespace, { state }, { lock: universalUnlock } ); + const st = store< any >( namespace, {}, { lock: universalUnlock } ); + deepMerge( st.state, state, false ); } ); } - if ( isObject( data?.config ) ) { + if ( isPlainObject( data?.config ) ) { Object.entries( data!.config ).forEach( ( [ namespace, config ] ) => { storeConfigs.set( namespace, config ); } ); @@ -351,5 +197,5 @@ export const populateInitialData = ( data?: { }; // Parse and populate the initial state and config. -const data = parseInitialData(); -populateInitialData( data ); +const data = parseServerData(); +populateServerData( data ); diff --git a/packages/interactivity/src/test/utils.ts b/packages/interactivity/src/test/utils.ts index ff564fa7c4c250..2ea0d2f04fadf7 100644 --- a/packages/interactivity/src/test/utils.ts +++ b/packages/interactivity/src/test/utils.ts @@ -1,26 +1,321 @@ /** * Internal dependencies */ -import { kebabToCamelCase } from '../utils'; - -describe( 'kebabToCamelCase', () => { - it( 'should work exactly as the PHP version', async () => { - expect( kebabToCamelCase( '' ) ).toBe( '' ); - expect( kebabToCamelCase( 'item' ) ).toBe( 'item' ); - expect( kebabToCamelCase( 'my-item' ) ).toBe( 'myItem' ); - expect( kebabToCamelCase( 'my_item' ) ).toBe( 'my_item' ); - expect( kebabToCamelCase( 'My-iTem' ) ).toBe( 'myItem' ); - expect( kebabToCamelCase( 'my-item-with-multiple-hyphens' ) ).toBe( - 'myItemWithMultipleHyphens' - ); - expect( kebabToCamelCase( 'my-item-with--double-hyphens' ) ).toBe( - 'myItemWith-DoubleHyphens' - ); - expect( kebabToCamelCase( 'my-item-with_under-score' ) ).toBe( - 'myItemWith_underScore' - ); - expect( kebabToCamelCase( '-my-item' ) ).toBe( 'myItem' ); - expect( kebabToCamelCase( 'my-item-' ) ).toBe( 'myItem' ); - expect( kebabToCamelCase( '-my-item-' ) ).toBe( 'myItem' ); +import { deepMerge, kebabToCamelCase } from '../utils'; + +describe( 'Interactivity API', () => { + describe( 'deepMerge', () => { + it( 'should merge two plain objects', () => { + const target = { a: 1, b: 2 }; + const source = { b: 3, c: 4 }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { a: 1, b: 3, c: 4 } ); + } ); + + it( 'should handle nested objects', () => { + const target = { a: { x: 1 }, b: 2 }; + const source = { a: { y: 2 }, c: 3 }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { a: { x: 1, y: 2 }, b: 2, c: 3 } ); + } ); + + it( 'should not override existing properties when override is false', () => { + const target = { a: 1, b: { x: 10 } }; + const source = { a: 2, b: { y: 20 }, c: 3 }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source, false ); + expect( result ).toEqual( { a: 1, b: { x: 10, y: 20 }, c: 3 } ); + } ); + + it( 'should handle getters', () => { + const target = { + get a() { + return 1; + }, + b: 1, + }; + const source = { + a: 2, + get b() { + return 2; + }, + }; + const result: Record< string, any > = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result.a ).toBe( 2 ); + expect( result.b ).toBe( 2 ); + expect( + Object.getOwnPropertyDescriptor( result, 'a' )?.get + ).toBeUndefined(); + expect( + Object.getOwnPropertyDescriptor( result, 'b' )?.get + ).toBeDefined(); + } ); + + it( 'should not execute getters when performing the deep merge', () => { + let targetExecuted = false; + let sourceExecuted = false; + const target = { + get a() { + targetExecuted = true; + return 1; + }, + }; + const source = { + get b() { + sourceExecuted = true; + return 2; + }, + }; + const result: Record< string, any > = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( targetExecuted ).toBe( false ); + expect( sourceExecuted ).toBe( false ); + } ); + + https: it( 'should handle setters', () => { + let targetValue = 1; + const target = { + get a() { + return targetValue; + }, + set a( value ) { + targetValue = value; + }, + b: 1, + }; + let sourceValue = 2; + const source = { + a: 3, + get b() { + return 2; + }, + set b( value ) { + sourceValue = value; + }, + }; + + const result: Record< string, any > = {}; + deepMerge( result, target ); + + result.a = 5; + expect( targetValue ).toBe( 5 ); + expect( result.a ).toBe( 5 ); + + deepMerge( result, source ); + + result.a = 6; + expect( targetValue ).toBe( 5 ); + + result.b = 7; + expect( sourceValue ).toBe( 7 ); + + expect( result.a ).toBe( 6 ); + expect( result.b ).toBe( 2 ); + expect( + Object.getOwnPropertyDescriptor( result, 'a' )?.set + ).toBeUndefined(); + expect( + Object.getOwnPropertyDescriptor( result, 'b' )?.set + ).toBeDefined(); + } ); + + it( 'should handle setters when overwrite is false', () => { + let targetValue = 1; + const target = { + get a() { + return targetValue; + }, + set a( value ) { + targetValue = value; + }, + b: 1, + }; + let sourceValue = 2; + const source = { + a: 3, + get b() { + return 2; + }, + set b( value ) { + sourceValue = value; + }, + }; + + const result: Record< string, any > = {}; + deepMerge( result, target, false ); + deepMerge( result, source, false ); + + result.a = 6; + expect( targetValue ).toBe( 6 ); + + result.b = 7; + expect( sourceValue ).toBe( 2 ); + + expect( result.a ).toBe( 6 ); + expect( result.b ).toBe( 7 ); + expect( + Object.getOwnPropertyDescriptor( result, 'a' )?.set + ).toBeDefined(); + expect( + Object.getOwnPropertyDescriptor( result, 'b' )?.set + ).toBeUndefined(); + } ); + + it( 'should handle getters and setters together', () => { + let targetValue = 1; + const target = { + get a() { + return targetValue; + }, + set a( value ) { + targetValue = value; + }, + b: 1, + }; + let sourceValue = 2; + const source = { + get a() { + return 3; + }, + set a( value ) { + sourceValue = value; + }, + }; + const result: Record< string, any > = {}; + deepMerge( result, target ); + deepMerge( result, source ); + + // Test if setters and getters are copied correctly + result.a = 5; + expect( targetValue ).toBe( 1 ); // Should not change + expect( sourceValue ).toBe( 5 ); // Should change + expect( result.a ).toBe( 3 ); // Should return the getter's value + + expect( + Object.getOwnPropertyDescriptor( result, 'a' )?.get + ).toBeDefined(); + expect( + Object.getOwnPropertyDescriptor( result, 'a' )?.set + ).toBeDefined(); + } ); + + it( 'should handle getters when overwrite is false', () => { + const target = { + get a() { + return 1; + }, + b: 1, + }; + const source = { + a: 2, + get b() { + return 2; + }, + }; + const result: Record< string, any > = {}; + deepMerge( result, target, false ); + deepMerge( result, source, false ); + expect( result.a ).toBe( 1 ); + expect( result.b ).toBe( 1 ); + expect( + Object.getOwnPropertyDescriptor( result, 'a' )?.get + ).toBeDefined(); + expect( + Object.getOwnPropertyDescriptor( result, 'b' )?.get + ).toBeUndefined(); + } ); + + it( 'should ignore non-plain objects', () => { + const target = { a: 1 }; + const source = new Date(); + const result = { ...target }; + deepMerge( result, source ); + expect( result ).toEqual( { a: 1 } ); + } ); + + it( 'should handle arrays', () => { + const target = { a: [ 1, 2 ] }; + const source = { a: [ 3, 4 ] }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { a: [ 3, 4 ] } ); + } ); + + it( 'should handle arrays when overwrite is false', () => { + const target = { a: [ 1, 2 ] }; + const source = { a: [ 3, 4 ] }; + const result = {}; + deepMerge( result, target, false ); + deepMerge( result, source, false ); + expect( result ).toEqual( { a: [ 1, 2 ] } ); + } ); + + it( 'should handle null values', () => { + const target = { a: 1, b: null }; + const source = { b: 2, c: null }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { a: 1, b: 2, c: null } ); + } ); + + it( 'should handle undefined values', () => { + const target = { a: 1, b: undefined }; + const source = { b: 2, c: undefined }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { a: 1, b: 2, c: undefined } ); + } ); + + it( 'should handle undefined values when overwrite is false', () => { + const target = { a: 1, b: undefined }; + const source = { b: 2, c: undefined }; + const result = {}; + deepMerge( result, target, false ); + deepMerge( result, source, false ); + expect( result ).toEqual( { a: 1, b: undefined, c: undefined } ); + } ); + + it( 'should handle deleted values when overwrite is false', () => { + const target = { a: 1 }; + const source = { a: 2 }; + const result: Record< string, any > = {}; + deepMerge( result, target, false ); + delete result.a; + deepMerge( result, source, false ); + expect( result ).toEqual( { a: 2 } ); + } ); + } ); + + describe( 'kebabToCamelCase', () => { + it( 'should work exactly as the PHP version', async () => { + expect( kebabToCamelCase( '' ) ).toBe( '' ); + expect( kebabToCamelCase( 'item' ) ).toBe( 'item' ); + expect( kebabToCamelCase( 'my-item' ) ).toBe( 'myItem' ); + expect( kebabToCamelCase( 'my_item' ) ).toBe( 'my_item' ); + expect( kebabToCamelCase( 'My-iTem' ) ).toBe( 'myItem' ); + expect( kebabToCamelCase( 'my-item-with-multiple-hyphens' ) ).toBe( + 'myItemWithMultipleHyphens' + ); + expect( kebabToCamelCase( 'my-item-with--double-hyphens' ) ).toBe( + 'myItemWith-DoubleHyphens' + ); + expect( kebabToCamelCase( 'my-item-with_under-score' ) ).toBe( + 'myItemWith_underScore' + ); + expect( kebabToCamelCase( '-my-item' ) ).toBe( 'myItem' ); + expect( kebabToCamelCase( 'my-item-' ) ).toBe( 'myItem' ); + expect( kebabToCamelCase( '-my-item-' ) ).toBe( 'myItem' ); + } ); } ); } ); diff --git a/packages/interactivity/src/utils.ts b/packages/interactivity/src/utils.ts index 3c880d43f17065..ee0cf1ba084dc8 100644 --- a/packages/interactivity/src/utils.ts +++ b/packages/interactivity/src/utils.ts @@ -14,14 +14,8 @@ import { effect } from '@preact/signals'; /** * Internal dependencies */ -import { - getScope, - setScope, - resetScope, - getNamespace, - setNamespace, - resetNamespace, -} from './hooks'; +import { getScope, setScope, resetScope } from './scopes'; +import { getNamespace, setNamespace, resetNamespace } from './namespaces'; interface Flusher { readonly flush: () => void; @@ -145,18 +139,26 @@ export function withScope( func: ( ...args: unknown[] ) => unknown ) { try { it = gen.next( value ); } finally { - resetNamespace(); resetScope(); + resetNamespace(); } + try { value = await it.value; } catch ( e ) { + setNamespace( ns ); + setScope( scope ); gen.throw( e ); + } finally { + resetScope(); + resetNamespace(); } + if ( it.done ) { break; } } + return value; }; } @@ -346,3 +348,50 @@ export const warn = ( message: string ): void => { logged.add( message ); } }; + +/** + * Checks if the passed `candidate` is a plain object with just the `Object` + * prototype. + * + * @param candidate The item to check. + * @return Whether `candidate` is a plain object. + */ +export const isPlainObject = ( + candidate: unknown +): candidate is Record< string, unknown > => + Boolean( + candidate && + typeof candidate === 'object' && + candidate.constructor === Object + ); + +export const deepMerge = ( + target: any, + source: any, + override: boolean = true +) => { + if ( isPlainObject( target ) && isPlainObject( source ) ) { + for ( const key in source ) { + const desc = Object.getOwnPropertyDescriptor( source, key ); + if ( + typeof desc?.get === 'function' || + typeof desc?.set === 'function' + ) { + if ( override || ! ( key in target ) ) { + Object.defineProperty( target, key, { + ...desc, + configurable: true, + enumerable: true, + } ); + } + } else if ( isPlainObject( source[ key ] ) ) { + if ( ! target[ key ] ) { + target[ key ] = {}; + } + deepMerge( target[ key ], source[ key ], override ); + } else if ( override || ! ( key in target ) ) { + Object.defineProperty( target, key, desc! ); + } + } + } +}; diff --git a/test/e2e/specs/interactivity/deferred-store.spec.ts b/test/e2e/specs/interactivity/deferred-store.spec.ts index b6a7853c40dcd4..0ddbcb0a60d2f4 100644 --- a/test/e2e/specs/interactivity/deferred-store.spec.ts +++ b/test/e2e/specs/interactivity/deferred-store.spec.ts @@ -27,9 +27,7 @@ test.describe( 'deferred store', () => { await expect( resultInput ).toHaveText( 'Hello, world!' ); } ); - // There is a known issue for deferred getters right now. - // eslint-disable-next-line playwright/no-skipped-test - test.skip( 'Ensure that a state getter can be subscribed to before it is initialized', async ( { + test( 'Ensure that a state getter can be subscribed to before it is initialized', async ( { page, } ) => { const resultInput = page.getByTestId( 'result-getter' ); diff --git a/test/e2e/specs/interactivity/directive-context.spec.ts b/test/e2e/specs/interactivity/directive-context.spec.ts index 41afa274155a28..e806049ff55e75 100644 --- a/test/e2e/specs/interactivity/directive-context.spec.ts +++ b/test/e2e/specs/interactivity/directive-context.spec.ts @@ -38,7 +38,7 @@ test.describe( 'data-wp-context', () => { } ); } ); - test( 'is correctly extended', async ( { page } ) => { + test( 'is correctly extended (shallow)', async ( { page } ) => { const childContext = await parseContent( page.getByTestId( 'child context' ) ); @@ -47,12 +47,12 @@ test.describe( 'data-wp-context', () => { prop1: 'parent', prop2: 'child', prop3: 'child', - obj: { prop4: 'parent', prop5: 'child', prop6: 'child' }, + obj: { prop5: 'child', prop6: 'child' }, array: [ 4, 5, 6 ], } ); } ); - test( 'changes in inherited properties are reflected (child)', async ( { + test( "changes in inherited properties are reflected and don't leak down (child)", async ( { page, } ) => { await page.getByTestId( 'child prop1' ).click(); @@ -70,10 +70,10 @@ test.describe( 'data-wp-context', () => { ); expect( parentContext.prop1 ).toBe( 'modifiedFromChild' ); - expect( parentContext.obj.prop4 ).toBe( 'modifiedFromChild' ); + expect( parentContext.obj.prop4 ).toBe( 'parent' ); } ); - test( 'changes in inherited properties are reflected (parent)', async ( { + test( "changes in inherited properties are reflected and don't leak up (parent)", async ( { page, } ) => { await page.getByTestId( 'parent prop1' ).click(); @@ -84,7 +84,7 @@ test.describe( 'data-wp-context', () => { ); expect( childContext.prop1 ).toBe( 'modifiedFromParent' ); - expect( childContext.obj.prop4 ).toBe( 'modifiedFromParent' ); + expect( childContext.obj.prop4 ).toBeUndefined(); const parentContext = await parseContent( page.getByTestId( 'parent context' ) @@ -170,7 +170,7 @@ test.describe( 'data-wp-context', () => { expect( childContext.array ).toMatchObject( [ 4, 5, 6 ] ); } ); - test( 'overwritten objects updates inherited values', async ( { + test( "overwritten objects don't inherit values (shallow)", async ( { page, } ) => { await page.getByTestId( 'parent replace' ).click(); @@ -182,7 +182,7 @@ test.describe( 'data-wp-context', () => { expect( childContext.obj.prop4 ).toBeUndefined(); expect( childContext.obj.prop5 ).toBe( 'child' ); expect( childContext.obj.prop6 ).toBe( 'child' ); - expect( childContext.obj.overwritten ).toBe( true ); + expect( childContext.obj.overwritten ).toBeUndefined(); const parentContext = await parseContent( page.getByTestId( 'parent context' ) @@ -230,13 +230,13 @@ test.describe( 'data-wp-context', () => { await expect( element ).toHaveAttribute( 'value', 'Text 1' ); } ); - test( 'should replace values on navigation', async ( { page } ) => { + test( 'should preserve values on navigation', async ( { page } ) => { const element = page.getByTestId( 'navigation text' ); await expect( element ).toHaveText( 'first page' ); await page.getByTestId( 'toggle text' ).click(); await expect( element ).toHaveText( 'changed dynamically' ); await page.getByTestId( 'navigate' ).click(); - await expect( element ).toHaveText( 'second page' ); + await expect( element ).toHaveText( 'changed dynamically' ); } ); test( 'should preserve the previous context values', async ( { page } ) => { @@ -248,16 +248,16 @@ test.describe( 'data-wp-context', () => { await expect( element ).toHaveText( 'some new text' ); } ); - test( 'should update values when navigating back or forward', async ( { + test( 'should preserve values when navigating back or forward', async ( { page, } ) => { const element = page.getByTestId( 'navigation text' ); await page.getByTestId( 'navigate' ).click(); - await expect( element ).toHaveText( 'second page' ); + await expect( element ).toHaveText( 'first page' ); await page.goBack(); await expect( element ).toHaveText( 'first page' ); await page.goForward(); - await expect( element ).toHaveText( 'second page' ); + await expect( element ).toHaveText( 'first page' ); } ); test( 'should inherit values on navigation', async ( { page } ) => { @@ -270,15 +270,14 @@ test.describe( 'data-wp-context', () => { await page.getByTestId( 'add text2' ).click(); await expect( text2 ).toHaveText( 'some new text' ); await page.getByTestId( 'navigate' ).click(); - await expect( text ).toHaveText( 'second page' ); - await expect( text2 ).toHaveText( 'second page' ); + await expect( text ).toHaveText( 'changed dynamically' ); + await expect( text2 ).toHaveText( 'some new text' ); await page.goBack(); - await expect( text ).toHaveText( 'first page' ); - // text2 maintains its value as it is not defined in the first page. - await expect( text2 ).toHaveText( 'second page' ); + await expect( text ).toHaveText( 'changed dynamically' ); + await expect( text2 ).toHaveText( 'some new text' ); await page.goForward(); - await expect( text ).toHaveText( 'second page' ); - await expect( text2 ).toHaveText( 'second page' ); + await expect( text ).toHaveText( 'changed dynamically' ); + await expect( text2 ).toHaveText( 'some new text' ); } ); test( 'should maintain the same context reference on async actions', async ( { @@ -289,11 +288,14 @@ test.describe( 'data-wp-context', () => { await page.getByTestId( 'async navigate' ).click(); await expect( element ).toHaveText( 'changed from async action' ); } ); + test( 'should bail out if the context is not a default directive', async ( { page, } ) => { - // This test is to ensure that the context directive is only applied to the default directive - // and not to any other directive. + /* + * This test is to ensure that the context directive is only applied to the + * default directive and not to any other directive. + */ const defaultElement = page.getByTestId( 'default suffix context' ); await expect( defaultElement ).toHaveText( 'default' ); const element = page.getByTestId( 'non-default suffix context' ); @@ -363,7 +365,7 @@ test.describe( 'data-wp-context', () => { page.getByTestId( 'child context' ) ); - expect( childContextBefore.obj2.prop4 ).toBe( 'parent' ); + expect( childContextBefore.obj2.prop4 ).toBeUndefined(); expect( childContextBefore.obj2.prop5 ).toBe( 'child' ); expect( childContextBefore.obj2.prop6 ).toBe( 'child' ); @@ -376,6 +378,6 @@ test.describe( 'data-wp-context', () => { expect( childContextAfter.obj2.prop4 ).toBeUndefined(); expect( childContextAfter.obj2.prop5 ).toBe( 'child' ); expect( childContextAfter.obj2.prop6 ).toBe( 'child' ); - expect( childContextAfter.obj2.overwritten ).toBe( true ); + expect( childContextAfter.obj2.overwritten ).toBeUndefined(); } ); } ); diff --git a/test/e2e/specs/interactivity/directive-each.spec.ts b/test/e2e/specs/interactivity/directive-each.spec.ts index 9dbd1e47a2ef1c..511b38e7ddbb8b 100644 --- a/test/e2e/specs/interactivity/directive-each.spec.ts +++ b/test/e2e/specs/interactivity/directive-each.spec.ts @@ -314,19 +314,14 @@ test.describe( 'data-wp-each', () => { } ) ); - await expect( elements ).toHaveText( [ 'beta', 'gamma', 'delta' ] ); + await expect( elements ).toHaveText( [ 'b', 'c', 'd' ] ); await page .getByTestId( 'navigation-updated list' ) .getByTestId( 'navigate' ) .click(); - await expect( elements ).toHaveText( [ - 'alpha', - 'beta', - 'gamma', - 'delta', - ] ); + await expect( elements ).toHaveText( [ 'a', 'b', 'c', 'd' ] ); // Get the tags. They should not have disappeared or changed, // except for the newly created element. diff --git a/test/e2e/specs/interactivity/router-navigate.spec.ts b/test/e2e/specs/interactivity/router-navigate.spec.ts index 872fe9ea7ea52e..d1ac30783ee2b7 100644 --- a/test/e2e/specs/interactivity/router-navigate.spec.ts +++ b/test/e2e/specs/interactivity/router-navigate.spec.ts @@ -6,10 +6,6 @@ import { test, expect } from './fixtures'; test.describe( 'Router navigate', () => { test.beforeAll( async ( { interactivityUtils: utils } ) => { await utils.activatePlugins(); - const link2 = await utils.addPostWithBlock( 'test/router-navigate', { - alias: 'router navigate - link 2', - attributes: { title: 'Link 2' }, - } ); const link1 = await utils.addPostWithBlock( 'test/router-navigate', { alias: 'router navigate - link 1', attributes: { @@ -21,6 +17,10 @@ test.describe( 'Router navigate', () => { }, }, } ); + const link2 = await utils.addPostWithBlock( 'test/router-navigate', { + alias: 'router navigate - link 2', + attributes: { title: 'Link 2' }, + } ); const link3 = await utils.addPostWithBlock( 'test/router-navigate', { alias: 'router navigate - disabled', attributes: { @@ -211,29 +211,26 @@ test.describe( 'Router navigate', () => { await expect( count ).toHaveText( '0' ); } ); - test( 'should overwrite the state with the one serialized in the new page', async ( { + test( 'should merge the state with the one serialized in the new page', async ( { page, } ) => { const prop1 = page.getByTestId( 'prop1' ); const prop2 = page.getByTestId( 'prop2' ); const prop3 = page.getByTestId( 'prop3' ); + const title = page.getByTestId( 'title' ); await expect( prop1 ).toHaveText( 'main' ); await expect( prop2 ).toHaveText( 'main' ); await expect( prop3 ).toBeEmpty(); await page.getByTestId( 'link 1' ).click(); - - // New values for existing properties should change. - // Old values not overwritten should remain the same. - // New properties should appear. - await expect( prop1 ).toHaveText( 'link 1' ); + await expect( title ).toHaveText( 'Link 1' ); + await expect( prop1 ).toHaveText( 'main' ); await expect( prop2 ).toHaveText( 'main' ); await expect( prop3 ).toHaveText( 'link 1' ); await page.goBack(); - - // New added properties are preserved. + await expect( title ).toHaveText( 'Main' ); await expect( prop1 ).toHaveText( 'main' ); await expect( prop2 ).toHaveText( 'main' ); await expect( prop3 ).toHaveText( 'link 1' ); @@ -245,26 +242,20 @@ test.describe( 'Router navigate', () => { const title = page.getByTestId( 'title' ); const getter = page.getByTestId( 'getterProp' ); - // Title should start in 'Main' and the getter prop should be the one - // returned once hydrated. await expect( title ).toHaveText( 'Main' ); await expect( getter ).toHaveText( 'value from getter (main)' ); await page.getByTestId( 'link 1' ).click(); - - // Title should have changed. If not, that means there was an error - // during render. The getter should return the correct value. await expect( title ).toHaveText( 'Link 1' ); - await expect( getter ).toHaveText( 'value from getter (link 1)' ); + await expect( getter ).toHaveText( 'value from getter (main)' ); - // Same behavior navigating back and forward. await page.goBack(); await expect( title ).toHaveText( 'Main' ); await expect( getter ).toHaveText( 'value from getter (main)' ); await page.goForward(); await expect( title ).toHaveText( 'Link 1' ); - await expect( getter ).toHaveText( 'value from getter (link 1)' ); + await expect( getter ).toHaveText( 'value from getter (main)' ); } ); test( 'should force a page reload when navigating to a page with `clientNavigationDisabled`', async ( { diff --git a/test/unit/jest.config.js b/test/unit/jest.config.js index 4a19d5bb37f316..4a3bb647a7879f 100644 --- a/test/unit/jest.config.js +++ b/test/unit/jest.config.js @@ -40,7 +40,7 @@ module.exports = { '^.+\\.[jt]sx?$': '<rootDir>/test/unit/scripts/babel-transformer.js', }, transformIgnorePatterns: [ - '/node_modules/(?!(docker-compose|yaml|preact|@preact|deepsignal)/)', + '/node_modules/(?!(docker-compose|yaml|preact|@preact)/)', '\\.pnp\\.[^\\/]+$', ], snapshotSerializers: [ From b3ccf2247b01e6a4970f08d218b19d664ccb293c Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 7 Aug 2024 14:00:56 +0400 Subject: [PATCH 0285/1908] Data Views: Don't render action modal when there are no eligible items (#64250) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../src/components/dataviews-bulk-actions/index.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx b/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx index 2047307bd7e90e..d671b8a8c62d96 100644 --- a/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx +++ b/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx @@ -89,6 +89,11 @@ function ActionWithModal< Item >( { const onCloseModal = useCallback( () => { setActionWithModal( undefined ); }, [ setActionWithModal ] ); + + if ( ! eligibleItems.length ) { + return null; + } + const label = typeof action.label === 'string' ? action.label From 2b2e7fb2e8c121ef54b7c37f2195f91da05b522a Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 7 Aug 2024 19:27:44 +0900 Subject: [PATCH 0286/1908] Components: Add missing `__nextHasNoMarginBottom` docs (#64313) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../components/src/text-control/README.md | 1 + .../components/src/text-control/index.tsx | 1 + .../README.md | 2 +- .../component.tsx | 28 +++++++++---------- .../toggle-group-control-option/README.md | 7 ++++- .../toggle-group-control-option/component.tsx | 7 ++++- .../toggle-group-control/README.md | 14 +++++++++- .../toggle-group-control/component.tsx | 7 ++++- 8 files changed, 48 insertions(+), 19 deletions(-) diff --git a/packages/components/src/text-control/README.md b/packages/components/src/text-control/README.md index 2a95e4c46864b8..4e2bfccb786d22 100644 --- a/packages/components/src/text-control/README.md +++ b/packages/components/src/text-control/README.md @@ -62,6 +62,7 @@ const MyTextControl = () => { return ( <TextControl + __nextHasNoMarginBottom label="Additional CSS Class" value={ className } onChange={ ( value ) => setClassName( value ) } diff --git a/packages/components/src/text-control/index.tsx b/packages/components/src/text-control/index.tsx index e964f918c119e0..1643c5bc37c347 100644 --- a/packages/components/src/text-control/index.tsx +++ b/packages/components/src/text-control/index.tsx @@ -75,6 +75,7 @@ function UnforwardedTextControl( * * return ( * <TextControl + * __nextHasNoMarginBottom * label="Additional CSS Class" * value={ className } * onChange={ ( value ) => setClassName( value ) } diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option-icon/README.md b/packages/components/src/toggle-group-control/toggle-group-control-option-icon/README.md index 8b96470e21301e..a0e3a44cf74607 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option-icon/README.md +++ b/packages/components/src/toggle-group-control/toggle-group-control-option-icon/README.md @@ -17,7 +17,7 @@ import { formatLowercase, formatUppercase } from '@wordpress/icons'; function Example() { return ( - <ToggleGroupControl> + <ToggleGroupControl __nextHasNoMarginBottom> <ToggleGroupControlOptionIcon value="uppercase" icon={ formatUppercase } diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option-icon/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control-option-icon/component.tsx index ec009d82344c39..352b4acee71844 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option-icon/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control-option-icon/component.tsx @@ -51,20 +51,20 @@ function UnforwardedToggleGroupControlOptionIcon( * import { formatLowercase, formatUppercase } from '@wordpress/icons'; * * function Example() { - * return ( - * <ToggleGroupControl> - * <ToggleGroupControlOptionIcon - * value="uppercase" - * label="Uppercase" - * icon={ formatUppercase } - * /> - * <ToggleGroupControlOptionIcon - * value="lowercase" - * label="Lowercase" - * icon={ formatLowercase } - * /> - * </ToggleGroupControl> - * ); + * return ( + * <ToggleGroupControl __nextHasNoMarginBottom> + * <ToggleGroupControlOptionIcon + * value="uppercase" + * label="Uppercase" + * icon={ formatUppercase } + * /> + * <ToggleGroupControlOptionIcon + * value="lowercase" + * label="Lowercase" + * icon={ formatLowercase } + * /> + * </ToggleGroupControl> + * ); * } * ``` */ diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option/README.md b/packages/components/src/toggle-group-control/toggle-group-control-option/README.md index 7f9f4d32f29fc3..2e7c55bd688361 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option/README.md +++ b/packages/components/src/toggle-group-control/toggle-group-control-option/README.md @@ -17,7 +17,12 @@ import { function Example() { return ( - <ToggleGroupControl label="my label" value="vertical" isBlock> + <ToggleGroupControl + label="my label" + value="vertical" + isBlock + __nextHasNoMarginBottom + > <ToggleGroupControlOption value="horizontal" label="Horizontal" diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control-option/component.tsx index e4b9cff4b80330..b71d37e81cf25f 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control-option/component.tsx @@ -48,7 +48,12 @@ function UnforwardedToggleGroupControlOption( * * function Example() { * return ( - * <ToggleGroupControl label="my label" value="vertical" isBlock> + * <ToggleGroupControl + * label="my label" + * value="vertical" + * isBlock + * __nextHasNoMarginBottom + * > * <ToggleGroupControlOption value="horizontal" label="Horizontal" /> * <ToggleGroupControlOption value="vertical" label="Vertical" /> * </ToggleGroupControl> diff --git a/packages/components/src/toggle-group-control/toggle-group-control/README.md b/packages/components/src/toggle-group-control/toggle-group-control/README.md index 64e0489f4171b7..6db7ec20544185 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/README.md +++ b/packages/components/src/toggle-group-control/toggle-group-control/README.md @@ -20,7 +20,12 @@ import { function Example() { return ( - <ToggleGroupControl label="my label" value="vertical" isBlock> + <ToggleGroupControl + label="my label" + value="vertical" + isBlock + __nextHasNoMarginBottom + > <ToggleGroupControlOption value="horizontal" label="Horizontal" /> <ToggleGroupControlOption value="vertical" label="Vertical" /> </ToggleGroupControl> @@ -82,3 +87,10 @@ Callback when a segment is selected. The value of the `ToggleGroupControl`. - Required: No + +### `__nextHasNoMarginBottom`: `boolean` + +Start opting into the new margin-free styles that will become the default in a future version. + +- Required: No +- Default: `false` \ No newline at end of file diff --git a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx index 520b2c414d70b9..8138b76505fe50 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx @@ -115,7 +115,12 @@ function UnconnectedToggleGroupControl( * * function Example() { * return ( - * <ToggleGroupControl label="my label" value="vertical" isBlock> + * <ToggleGroupControl + * label="my label" + * value="vertical" + * isBlock + * __nextHasNoMarginBottom + * > * <ToggleGroupControlOption value="horizontal" label="Horizontal" /> * <ToggleGroupControlOption value="vertical" label="Vertical" /> * </ToggleGroupControl> From ccd8dac274b13f8e887727b6251ba56184322d70 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 7 Aug 2024 20:07:41 +0900 Subject: [PATCH 0287/1908] Autocompleter UI: Fix text color when hovering selected item (#64294) * Autocompleter UI: Fix text color when hovering selected item * Update changelog * Restore `is-selected` CSS class Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/autocomplete/autocompleter-ui.tsx | 2 ++ packages/components/src/autocomplete/style.scss | 6 ------ 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 8ecbf1528d6f08..3c4a5b679791f9 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -8,6 +8,7 @@ - `CustomSelectControl`: Restore `describedBy` functionality ([#63957](https://github.com/WordPress/gutenberg/pull/63957)). - `Button`: Improve the aria-disabled focus style ([#62480](https://github.com/WordPress/gutenberg/pull/62480)). - `Modal`: Fix the dismissal logic for React development mode ([#64132](https://github.com/WordPress/gutenberg/pull/64132)). +- `Autocompleter UI`: Fix text color when hovering selected item ([#64294](https://github.com/WordPress/gutenberg/pull/64294)). ### Enhancements diff --git a/packages/components/src/autocomplete/autocompleter-ui.tsx b/packages/components/src/autocomplete/autocompleter-ui.tsx index 1a5aacf1438abc..c6c1b94deb577e 100644 --- a/packages/components/src/autocomplete/autocompleter-ui.tsx +++ b/packages/components/src/autocomplete/autocompleter-ui.tsx @@ -64,9 +64,11 @@ function ListBox( { 'components-autocomplete__result', className, { + // Unused, for backwards compatibility. 'is-selected': index === selectedIndex, } ) } + variant={ index === selectedIndex ? 'primary' : undefined } onClick={ () => onSelect( option ) } > { option.label } diff --git a/packages/components/src/autocomplete/style.scss b/packages/components/src/autocomplete/style.scss index fdb29fe577f206..75b219210f42e2 100644 --- a/packages/components/src/autocomplete/style.scss +++ b/packages/components/src/autocomplete/style.scss @@ -13,10 +13,4 @@ &:focus:not(:disabled) { @include block-toolbar-button-style__focus(); } - - &.is-selected, - &:not(:disabled,[aria-disabled="true"]):active { - background: $components-color-accent; - color: $white; - } } From e6627e04b0b27e45ef095303d5d6cf42b390044f Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 7 Aug 2024 13:25:54 +0200 Subject: [PATCH 0288/1908] DataForm: Fix SelectControl size and spacing (#64324) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/dataviews/src/field-types/text.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/dataviews/src/field-types/text.tsx b/packages/dataviews/src/field-types/text.tsx index 227c70033cae09..2e33ab57ecaa33 100644 --- a/packages/dataviews/src/field-types/text.tsx +++ b/packages/dataviews/src/field-types/text.tsx @@ -67,6 +67,8 @@ function Edit< Item >( { value={ value } options={ elements } onChange={ onChangeControl } + __next40pxDefaultSize + __nextHasNoMarginBottom /> ); } From ab103f2d044eb598a98053500b83495f7b8a019c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:25:38 +0200 Subject: [PATCH 0289/1908] DataViews: consider layout url parameter when loading a default/custom view (#64306) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../src/components/post-list/index.js | 35 +++++++++++-------- .../sidebar-dataviews/dataview-item.js | 4 +-- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 74bbee05246178..35ecaaa8424fd4 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -93,18 +93,22 @@ function useView( postType ) { [ activeView, isCustom ] ); const [ view, setView ] = useState( () => { + let initialView; if ( isCustom === 'true' ) { - return ( - getCustomView( editedEntityRecord ) ?? { - type: layout ?? LAYOUT_LIST, - } - ); - } - return ( - getDefaultView( defaultViews, activeView ) ?? { + initialView = getCustomView( editedEntityRecord ) ?? { type: layout ?? LAYOUT_LIST, - } - ); + }; + } else { + initialView = getDefaultView( defaultViews, activeView ) ?? { + type: layout ?? LAYOUT_LIST, + }; + } + + const type = layout ?? initialView.type; + return { + ...initialView, + type, + }; } ); const setViewWithUrlUpdate = useCallback( @@ -146,8 +150,7 @@ function useView( postType ) { } ) ); }, [ layout ] ); - // When activeView or isCustom URL parameters change, - // reset the view & update the layout URL param to match the view's type. + // When activeView or isCustom URL parameters change, reset the view. useEffect( () => { let newView; if ( isCustom === 'true' ) { @@ -157,9 +160,13 @@ function useView( postType ) { } if ( newView ) { - setViewWithUrlUpdate( newView ); + const type = layout ?? newView.type; + setView( { + ...newView, + type, + } ); } - }, [ activeView, isCustom, defaultViews, editedEntityRecord ] ); + }, [ activeView, isCustom, layout, defaultViews, editedEntityRecord ] ); return [ view, setViewWithUrlUpdate, setViewWithUrlUpdate ]; } diff --git a/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js b/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js index 0b5f93546875e5..1e12d6706d81b5 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js +++ b/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js @@ -29,7 +29,7 @@ export default function DataViewItem( { suffix, } ) { const { - params: { postType, layout }, + params: { postType }, } = useLocation(); const iconToUse = @@ -41,7 +41,7 @@ export default function DataViewItem( { } const linkInfo = useLink( { postType, - layout, + layout: type, activeView, isCustom: isCustom ? 'true' : undefined, } ); From c97587e3f9af303461883c89d9ecae0628e12429 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 7 Aug 2024 22:01:54 +0900 Subject: [PATCH 0290/1908] Block Autocompleter: Force icon color to text color when item is selected (#61376) * Block Autocompleter: Force icon color to text color when item is selected * Don't rely on css class Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/block-editor/src/autocompleters/style.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/block-editor/src/autocompleters/style.scss b/packages/block-editor/src/autocompleters/style.scss index 5380ddcfbe48b2..43acc4efc16a5e 100644 --- a/packages/block-editor/src/autocompleters/style.scss +++ b/packages/block-editor/src/autocompleters/style.scss @@ -4,6 +4,10 @@ .block-editor-block-icon { margin-right: $grid-unit-10; } + + &[aria-selected="true"] .block-editor-block-icon { + color: inherit !important; + } } .block-editor-autocompleters__link { From 59fd812fa46973f9a7319870edf7ef59a9643e23 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 7 Aug 2024 15:12:13 +0200 Subject: [PATCH 0291/1908] DataForm: Support multiple layouts and introduce the panel layout (#64299) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/heading/types.ts | 5 +- packages/dataviews/CHANGELOG.md | 5 + .../src/components/dataform/index.tsx | 54 +----- .../dataform/stories/index.story.tsx | 17 +- .../src/components/dataviews-layout/index.tsx | 2 +- .../dataviews-view-config/index.tsx | 2 +- .../src/components/dataviews/index.tsx | 2 +- .../dataviews/src/dataforms-layouts/index.tsx | 20 +++ .../src/dataforms-layouts/panel/index.tsx | 164 ++++++++++++++++++ .../src/dataforms-layouts/panel/style.scss | 59 +++++++ .../src/dataforms-layouts/regular/index.tsx | 41 +++++ .../grid/density-picker.tsx | 0 .../grid/index.tsx | 0 .../grid/style.scss | 0 .../{layouts => dataviews-layouts}/index.ts | 0 .../list/index.tsx | 0 .../list/style.scss | 0 .../table/column-header-menu.tsx | 0 .../table/index.tsx | 0 .../table/style.scss | 0 .../dataviews/src/field-types/integer.tsx | 3 + packages/dataviews/src/field-types/text.tsx | 3 + packages/dataviews/src/index.ts | 2 +- packages/dataviews/src/style.scss | 8 +- packages/dataviews/src/test/validation.ts | 16 +- packages/dataviews/src/types.ts | 11 +- packages/dataviews/src/validation.ts | 2 +- .../src/components/post-edit/index.js | 3 +- .../src/components/post-fields/index.js | 8 +- .../src/components/post-actions/actions.js | 4 +- 31 files changed, 357 insertions(+), 75 deletions(-) create mode 100644 packages/dataviews/src/dataforms-layouts/index.tsx create mode 100644 packages/dataviews/src/dataforms-layouts/panel/index.tsx create mode 100644 packages/dataviews/src/dataforms-layouts/panel/style.scss create mode 100644 packages/dataviews/src/dataforms-layouts/regular/index.tsx rename packages/dataviews/src/{layouts => dataviews-layouts}/grid/density-picker.tsx (100%) rename packages/dataviews/src/{layouts => dataviews-layouts}/grid/index.tsx (100%) rename packages/dataviews/src/{layouts => dataviews-layouts}/grid/style.scss (100%) rename packages/dataviews/src/{layouts => dataviews-layouts}/index.ts (100%) rename packages/dataviews/src/{layouts => dataviews-layouts}/list/index.tsx (100%) rename packages/dataviews/src/{layouts => dataviews-layouts}/list/style.scss (100%) rename packages/dataviews/src/{layouts => dataviews-layouts}/table/column-header-menu.tsx (100%) rename packages/dataviews/src/{layouts => dataviews-layouts}/table/index.tsx (100%) rename packages/dataviews/src/{layouts => dataviews-layouts}/table/style.scss (100%) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 3c4a5b679791f9..5cfc4eb2185b63 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -9,6 +9,7 @@ - `Button`: Improve the aria-disabled focus style ([#62480](https://github.com/WordPress/gutenberg/pull/62480)). - `Modal`: Fix the dismissal logic for React development mode ([#64132](https://github.com/WordPress/gutenberg/pull/64132)). - `Autocompleter UI`: Fix text color when hovering selected item ([#64294](https://github.com/WordPress/gutenberg/pull/64294)). +- `Heading`: Add the missing `size` prop to the component's props type ([#64299](https://github.com/WordPress/gutenberg/pull/64299)). ### Enhancements diff --git a/packages/components/src/heading/types.ts b/packages/components/src/heading/types.ts index 4767c0407d5a03..6ec3f0a82ef2eb 100644 --- a/packages/components/src/heading/types.ts +++ b/packages/components/src/heading/types.ts @@ -17,10 +17,7 @@ export type HeadingSize = | '5' | '6'; -export type HeadingProps = Omit< - TextProps, - 'size' | 'isBlock' | 'color' | 'weight' -> & { +export type HeadingProps = Omit< TextProps, 'isBlock' | 'color' | 'weight' > & { /** * Passing any of the heading levels to `level` will both render the correct * typographic text size as well as the semantic element corresponding to diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 881d666aa0613b..8dd3ade7fd7749 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -13,6 +13,11 @@ - `onSelectionChange` prop has been renamed to `onChangeSelection` and its argument has been updated to be a list of ids. - `setSelection` prop has been removed. Please use `onChangeSelection` instead. - `header` field property has been renamed to `label`. +- `DataForm`'s `visibleFields` prop has been renamed to `fields`. + +### New features + +- Support multiple layouts in `DataForm` component and introduce the `panel` layout. ## 3.0.0 (2024-07-10) diff --git a/packages/dataviews/src/components/dataform/index.tsx b/packages/dataviews/src/components/dataform/index.tsx index 02953b2930bd1f..58f0bf06afb414 100644 --- a/packages/dataviews/src/components/dataform/index.tsx +++ b/packages/dataviews/src/components/dataform/index.tsx @@ -1,55 +1,17 @@ -/** - * External dependencies - */ -import type { Dispatch, SetStateAction } from 'react'; - -/** - * WordPress dependencies - */ -import { __experimentalVStack as VStack } from '@wordpress/components'; -import { useMemo } from '@wordpress/element'; - /** * Internal dependencies */ -import { normalizeFields } from '../../normalize-fields'; -import type { Field, Form } from '../../types'; - -type DataFormProps< Item > = { - data: Item; - fields: Field< Item >[]; - form: Form; - onChange: Dispatch< SetStateAction< Item > >; -}; +import type { DataFormProps } from '../../types'; +import { getFormLayout } from '../../dataforms-layouts'; export default function DataForm< Item >( { - data, - fields, form, - onChange, + ...props }: DataFormProps< Item > ) { - const visibleFields = useMemo( - () => - normalizeFields( - fields.filter( - ( { id } ) => !! form.visibleFields?.includes( id ) - ) - ), - [ fields, form.visibleFields ] - ); + const layout = getFormLayout( form.type ?? 'regular' ); + if ( ! layout ) { + return null; + } - return ( - <VStack spacing={ 4 }> - { visibleFields.map( ( field ) => { - return ( - <field.Edit - key={ field.id } - data={ data } - field={ field } - onChange={ onChange } - /> - ); - } ) } - </VStack> - ); + return <layout.component form={ form } { ...props } />; } diff --git a/packages/dataviews/src/components/dataform/stories/index.story.tsx b/packages/dataviews/src/components/dataform/stories/index.story.tsx index 6acf0c65d9bd4f..4863eb24b4ede4 100644 --- a/packages/dataviews/src/components/dataform/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataform/stories/index.story.tsx @@ -11,6 +11,14 @@ import DataForm from '../index'; const meta = { title: 'DataViews/DataForm', component: DataForm, + argTypes: { + type: { + control: { type: 'select' }, + description: + 'Chooses the layout of the form. "regular" is the default layout.', + options: [ 'regular', 'panel' ], + }, + }, }; export default meta; @@ -45,7 +53,7 @@ const fields = [ }, ]; -export const Default = () => { +export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { const [ post, setPost ] = useState( { title: 'Hello, World!', order: 2, @@ -54,14 +62,17 @@ export const Default = () => { } ); const form = { - visibleFields: [ 'title', 'order', 'author', 'status' ], + fields: [ 'title', 'order', 'author', 'status' ], }; return ( <DataForm data={ post } fields={ fields } - form={ form } + form={ { + ...form, + type, + } } onChange={ setPost } /> ); diff --git a/packages/dataviews/src/components/dataviews-layout/index.tsx b/packages/dataviews/src/components/dataviews-layout/index.tsx index eac70763e143c1..bae4071fe2f773 100644 --- a/packages/dataviews/src/components/dataviews-layout/index.tsx +++ b/packages/dataviews/src/components/dataviews-layout/index.tsx @@ -12,7 +12,7 @@ import { useContext } from '@wordpress/element'; * Internal dependencies */ import DataViewsContext from '../dataviews-context'; -import { VIEW_LAYOUTS } from '../../layouts'; +import { VIEW_LAYOUTS } from '../../dataviews-layouts'; import type { ViewBaseProps } from '../../types'; export default function DataViewsLayout() { diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index 9f0cb87fa01a2e..b89e964f6a5d08 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -20,7 +20,7 @@ import { cog } from '@wordpress/icons'; */ import { unlock } from '../../lock-unlock'; import { SORTING_DIRECTIONS, sortLabels } from '../../constants'; -import { VIEW_LAYOUTS, getMandatoryFields } from '../../layouts'; +import { VIEW_LAYOUTS, getMandatoryFields } from '../../dataviews-layouts'; import type { NormalizedField, View, SupportedLayouts } from '../../types'; import DataViewsContext from '../dataviews-context'; diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index f6f408065058d2..337912b04e59c5 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -27,7 +27,7 @@ import DataViewsViewConfig from '../dataviews-view-config'; import { normalizeFields } from '../../normalize-fields'; import type { Action, Field, View, SupportedLayouts } from '../../types'; import type { SelectionOrUpdater } from '../../private-types'; -import DensityPicker from '../../layouts/grid/density-picker'; +import DensityPicker from '../../dataviews-layouts/grid/density-picker'; import { LAYOUT_GRID } from '../../constants'; type ItemWithId = { id: string }; diff --git a/packages/dataviews/src/dataforms-layouts/index.tsx b/packages/dataviews/src/dataforms-layouts/index.tsx new file mode 100644 index 00000000000000..9434ea724ed4ca --- /dev/null +++ b/packages/dataviews/src/dataforms-layouts/index.tsx @@ -0,0 +1,20 @@ +/** + * Internal dependencies + */ +import FormRegular from './regular'; +import FormPanel from './panel'; + +const FORM_LAYOUTS = [ + { + type: 'regular', + component: FormRegular, + }, + { + type: 'panel', + component: FormPanel, + }, +]; + +export function getFormLayout( type: string ) { + return FORM_LAYOUTS.find( ( layout ) => layout.type === type ); +} diff --git a/packages/dataviews/src/dataforms-layouts/panel/index.tsx b/packages/dataviews/src/dataforms-layouts/panel/index.tsx new file mode 100644 index 00000000000000..3dc52db0adc879 --- /dev/null +++ b/packages/dataviews/src/dataforms-layouts/panel/index.tsx @@ -0,0 +1,164 @@ +/** + * WordPress dependencies + */ +import { + __experimentalVStack as VStack, + __experimentalHStack as HStack, + __experimentalHeading as Heading, + __experimentalSpacer as Spacer, + Dropdown, + Button, +} from '@wordpress/components'; +import { useState, useMemo } from '@wordpress/element'; +import { sprintf, __ } from '@wordpress/i18n'; +import { closeSmall } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import { normalizeFields } from '../../normalize-fields'; +import type { DataFormProps, NormalizedField } from '../../types'; + +interface FormFieldProps< Item > { + data: Item; + field: NormalizedField< Item >; + onChange: ( value: any ) => void; +} + +function DropdownHeader( { + title, + onClose, +}: { + title: string; + onClose: () => void; +} ) { + return ( + <VStack + className="dataforms-layouts-panel__dropdown-header" + spacing={ 4 } + > + <HStack alignment="center"> + <Heading level={ 2 } size={ 13 }> + { title } + </Heading> + <Spacer /> + { onClose && ( + <Button + className="dataforms-layouts-panel__dropdown-header-action" + label={ __( 'Close' ) } + icon={ closeSmall } + onClick={ onClose } + /> + ) } + </HStack> + </VStack> + ); +} + +function FormField< Item >( { + data, + field, + onChange, +}: FormFieldProps< Item > ) { + // Use internal state instead of a ref to make sure that the component + // re-renders when the popover's anchor updates. + const [ popoverAnchor, setPopoverAnchor ] = useState< HTMLElement | null >( + null + ); + // Memoize popoverProps to avoid returning a new object every time. + const popoverProps = useMemo( + () => ( { + // Anchor the popover to the middle of the entire row so that it doesn't + // move around when the label changes. + anchor: popoverAnchor, + placement: 'left-start', + offset: 36, + shift: true, + } ), + [ popoverAnchor ] + ); + + return ( + <HStack + ref={ setPopoverAnchor } + className="dataforms-layouts-panel__field" + > + <div className="dataforms-layouts-panel__field-label"> + { field.label } + </div> + <div> + <Dropdown + contentClassName="dataforms-layouts-panel__field-dropdown" + popoverProps={ popoverProps } + focusOnMount + toggleProps={ { + size: 'compact', + variant: 'tertiary', + tooltipPosition: 'middle left', + } } + renderToggle={ ( { isOpen, onToggle } ) => ( + <Button + className="dataforms-layouts-panel__field-control" + size="compact" + variant="tertiary" + aria-expanded={ isOpen } + aria-label={ sprintf( + // translators: %s: Field name. + __( 'Edit %s' ), + field.label + ) } + onClick={ onToggle } + > + <field.render item={ data } /> + </Button> + ) } + renderContent={ ( { onClose } ) => ( + <> + <DropdownHeader + title={ field.label } + onClose={ onClose } + /> + <field.Edit + key={ field.id } + data={ data } + field={ field } + onChange={ onChange } + hideLabelFromVision + /> + </> + ) } + /> + </div> + </HStack> + ); +} + +export default function FormPanel< Item >( { + data, + fields, + form, + onChange, +}: DataFormProps< Item > ) { + const visibleFields = useMemo( + () => + normalizeFields( + fields.filter( ( { id } ) => !! form.fields?.includes( id ) ) + ), + [ fields, form.fields ] + ); + + return ( + <VStack spacing={ 2 }> + { visibleFields.map( ( field ) => { + return ( + <FormField + key={ field.id } + data={ data } + field={ field } + onChange={ onChange } + /> + ); + } ) } + </VStack> + ); +} diff --git a/packages/dataviews/src/dataforms-layouts/panel/style.scss b/packages/dataviews/src/dataforms-layouts/panel/style.scss new file mode 100644 index 00000000000000..e6840bed9d6e0b --- /dev/null +++ b/packages/dataviews/src/dataforms-layouts/panel/style.scss @@ -0,0 +1,59 @@ +.dataforms-layouts-panel__field { + width: 100%; + min-height: $grid-unit-40; + justify-content: flex-start !important; + align-items: flex-start !important; +} + +.dataforms-layouts-panel__field-label { + width: 38%; + flex-shrink: 0; + min-height: $grid-unit-40; + display: flex; + align-items: center; + padding: 6px 0; // Matches button to ensure alignment + line-height: $grid-unit-05 * 5; + hyphens: auto; +} + +.dataforms-layouts-panel__field-control { + flex-grow: 1; + min-height: $grid-unit-40; + display: flex; + align-items: center; + + .components-button { + max-width: 100%; + text-align: left; + white-space: normal; + text-wrap: balance; // Fallback for Safari. + text-wrap: pretty; + min-height: $button-size-compact; + } + + .components-dropdown { + max-width: 100%; + } +} + +.dataforms-layouts-panel__field-dropdown .components-popover__content { + min-width: 320px; + padding: $grid-unit-20; +} + +.dataforms-layouts-panel__dropdown-header { + margin-bottom: $grid-unit-20; +} + +[class].dataforms-layouts-panel__dropdown-header-action { + height: $icon-size; + + &.has-icon { + min-width: $icon-size; + padding: 0; + } + + &:not(.has-icon) { + text-decoration: underline; + } +} diff --git a/packages/dataviews/src/dataforms-layouts/regular/index.tsx b/packages/dataviews/src/dataforms-layouts/regular/index.tsx new file mode 100644 index 00000000000000..1164a61196a699 --- /dev/null +++ b/packages/dataviews/src/dataforms-layouts/regular/index.tsx @@ -0,0 +1,41 @@ +/** + * WordPress dependencies + */ +import { __experimentalVStack as VStack } from '@wordpress/components'; +import { useMemo } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { normalizeFields } from '../../normalize-fields'; +import type { DataFormProps } from '../../types'; + +export default function FormRegular< Item >( { + data, + fields, + form, + onChange, +}: DataFormProps< Item > ) { + const visibleFields = useMemo( + () => + normalizeFields( + fields.filter( ( { id } ) => !! form.fields?.includes( id ) ) + ), + [ fields, form.fields ] + ); + + return ( + <VStack spacing={ 4 }> + { visibleFields.map( ( field ) => { + return ( + <field.Edit + key={ field.id } + data={ data } + field={ field } + onChange={ onChange } + /> + ); + } ) } + </VStack> + ); +} diff --git a/packages/dataviews/src/layouts/grid/density-picker.tsx b/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx similarity index 100% rename from packages/dataviews/src/layouts/grid/density-picker.tsx rename to packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx diff --git a/packages/dataviews/src/layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx similarity index 100% rename from packages/dataviews/src/layouts/grid/index.tsx rename to packages/dataviews/src/dataviews-layouts/grid/index.tsx diff --git a/packages/dataviews/src/layouts/grid/style.scss b/packages/dataviews/src/dataviews-layouts/grid/style.scss similarity index 100% rename from packages/dataviews/src/layouts/grid/style.scss rename to packages/dataviews/src/dataviews-layouts/grid/style.scss diff --git a/packages/dataviews/src/layouts/index.ts b/packages/dataviews/src/dataviews-layouts/index.ts similarity index 100% rename from packages/dataviews/src/layouts/index.ts rename to packages/dataviews/src/dataviews-layouts/index.ts diff --git a/packages/dataviews/src/layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx similarity index 100% rename from packages/dataviews/src/layouts/list/index.tsx rename to packages/dataviews/src/dataviews-layouts/list/index.tsx diff --git a/packages/dataviews/src/layouts/list/style.scss b/packages/dataviews/src/dataviews-layouts/list/style.scss similarity index 100% rename from packages/dataviews/src/layouts/list/style.scss rename to packages/dataviews/src/dataviews-layouts/list/style.scss diff --git a/packages/dataviews/src/layouts/table/column-header-menu.tsx b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx similarity index 100% rename from packages/dataviews/src/layouts/table/column-header-menu.tsx rename to packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx diff --git a/packages/dataviews/src/layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx similarity index 100% rename from packages/dataviews/src/layouts/table/index.tsx rename to packages/dataviews/src/dataviews-layouts/table/index.tsx diff --git a/packages/dataviews/src/layouts/table/style.scss b/packages/dataviews/src/dataviews-layouts/table/style.scss similarity index 100% rename from packages/dataviews/src/layouts/table/style.scss rename to packages/dataviews/src/dataviews-layouts/table/style.scss diff --git a/packages/dataviews/src/field-types/integer.tsx b/packages/dataviews/src/field-types/integer.tsx index bf757776249b42..1233c3ab555567 100644 --- a/packages/dataviews/src/field-types/integer.tsx +++ b/packages/dataviews/src/field-types/integer.tsx @@ -45,6 +45,7 @@ function Edit< Item >( { data, field, onChange, + hideLabelFromVision, }: DataFormControlProps< Item > ) { const { id, label, description } = field; const value = field.getValue( { item: data } ) ?? ''; @@ -78,6 +79,7 @@ function Edit< Item >( { onChange={ onChangeControl } __next40pxDefaultSize __nextHasNoMarginBottom + hideLabelFromVision={ hideLabelFromVision } /> ); } @@ -89,6 +91,7 @@ function Edit< Item >( { value={ value } onChange={ onChangeControl } __next40pxDefaultSize + hideLabelFromVision={ hideLabelFromVision } /> ); } diff --git a/packages/dataviews/src/field-types/text.tsx b/packages/dataviews/src/field-types/text.tsx index 2e33ab57ecaa33..c6efb85f6f446b 100644 --- a/packages/dataviews/src/field-types/text.tsx +++ b/packages/dataviews/src/field-types/text.tsx @@ -35,6 +35,7 @@ function Edit< Item >( { data, field, onChange, + hideLabelFromVision, }: DataFormControlProps< Item > ) { const { id, label, placeholder } = field; const value = field.getValue( { item: data } ); @@ -69,6 +70,7 @@ function Edit< Item >( { onChange={ onChangeControl } __next40pxDefaultSize __nextHasNoMarginBottom + hideLabelFromVision={ hideLabelFromVision } /> ); } @@ -81,6 +83,7 @@ function Edit< Item >( { onChange={ onChangeControl } __next40pxDefaultSize __nextHasNoMarginBottom + hideLabelFromVision={ hideLabelFromVision } /> ); } diff --git a/packages/dataviews/src/index.ts b/packages/dataviews/src/index.ts index 95a8ab4c2e5e8d..4ca0cf3db0bd3f 100644 --- a/packages/dataviews/src/index.ts +++ b/packages/dataviews/src/index.ts @@ -1,6 +1,6 @@ export { default as DataViews } from './components/dataviews'; export { default as DataForm } from './components/dataform'; -export { VIEW_LAYOUTS } from './layouts'; +export { VIEW_LAYOUTS } from './dataviews-layouts'; export { filterSortAndPaginate } from './filter-and-sort-data-view'; export type * from './types'; export { isItemValid } from './validation'; diff --git a/packages/dataviews/src/style.scss b/packages/dataviews/src/style.scss index 49d897d9cc4d97..7cf737b9a3849f 100644 --- a/packages/dataviews/src/style.scss +++ b/packages/dataviews/src/style.scss @@ -6,6 +6,8 @@ @import "./components/dataviews-item-actions/style.scss"; @import "./components/dataviews-selection-checkbox/style.scss"; -@import "./layouts/grid/style.scss"; -@import "./layouts/list/style.scss"; -@import "./layouts/table/style.scss"; +@import "./dataviews-layouts/grid/style.scss"; +@import "./dataviews-layouts/list/style.scss"; +@import "./dataviews-layouts/table/style.scss"; + +@import "./dataforms-layouts/panel/style.scss"; diff --git a/packages/dataviews/src/test/validation.ts b/packages/dataviews/src/test/validation.ts index 4e52ca47353f78..6a81ba16425f85 100644 --- a/packages/dataviews/src/test/validation.ts +++ b/packages/dataviews/src/test/validation.ts @@ -17,7 +17,7 @@ describe( 'validation', () => { type: 'integer', }, ]; - const form = { visibleFields: [ 'valid_order' ] }; + const form = { fields: [ 'valid_order' ] }; const result = isItemValid( item, fields, form ); expect( result ).toBe( true ); } ); @@ -30,7 +30,7 @@ describe( 'validation', () => { id: 'order', }, ]; - const form = { visibleFields: [ 'order' ] }; + const form = { fields: [ 'order' ] }; const result = isItemValid( item, fields, form ); expect( result ).toBe( true ); } ); @@ -43,7 +43,7 @@ describe( 'validation', () => { type: 'integer', }, ]; - const form = { visibleFields: [ 'order' ] }; + const form = { fields: [ 'order' ] }; const result = isItemValid( item, fields, form ); expect( result ).toBe( false ); } ); @@ -56,7 +56,7 @@ describe( 'validation', () => { type: 'integer', }, ]; - const form = { visibleFields: [ 'order' ] }; + const form = { fields: [ 'order' ] }; const result = isItemValid( item, fields, form ); expect( result ).toBe( false ); } ); @@ -73,7 +73,7 @@ describe( 'validation', () => { ], }, ]; - const form = { visibleFields: [ 'author' ] }; + const form = { fields: [ 'author' ] }; const result = isItemValid( item, fields, form ); expect( result ).toBe( false ); } ); @@ -90,7 +90,7 @@ describe( 'validation', () => { ], }, ]; - const form = { visibleFields: [ 'author' ] }; + const form = { fields: [ 'author' ] }; const result = isItemValid( item, fields, form ); expect( result ).toBe( false ); } ); @@ -106,7 +106,7 @@ describe( 'validation', () => { ], }, ]; - const form = { visibleFields: [ 'author' ] }; + const form = { fields: [ 'author' ] }; const result = isItemValid( item, fields, form ); expect( result ).toBe( false ); } ); @@ -124,7 +124,7 @@ describe( 'validation', () => { isValid: () => true, // Overrides the validation provided for integer types. }, ]; - const form = { visibleFields: [ 'order' ] }; + const form = { fields: [ 'order' ] }; const result = isItemValid( item, fields, form ); expect( result ).toBe( true ); } ); diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 7fb157465b41f4..25e603d8cfa234 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -164,13 +164,15 @@ export type Data< Item > = Item[]; * The form configuration. */ export type Form = { - visibleFields?: string[]; + type?: 'regular' | 'panel'; + fields?: string[]; }; export type DataFormControlProps< Item > = { data: Item; field: NormalizedField< Item >; onChange: Dispatch< SetStateAction< Item > >; + hideLabelFromVision?: boolean; }; /** @@ -497,3 +499,10 @@ export interface SupportedLayouts { grid?: Omit< ViewGrid, 'type' >; table?: Omit< ViewTable, 'type' >; } + +export interface DataFormProps< Item > { + data: Item; + fields: Field< Item >[]; + form: Form; + onChange: Dispatch< SetStateAction< Item > >; +} diff --git a/packages/dataviews/src/validation.ts b/packages/dataviews/src/validation.ts index e350be68d54219..cc0b031f6c96c6 100644 --- a/packages/dataviews/src/validation.ts +++ b/packages/dataviews/src/validation.ts @@ -10,7 +10,7 @@ export function isItemValid< Item >( form: Form ): boolean { const _fields = normalizeFields( - fields.filter( ( { id } ) => !! form.visibleFields?.includes( id ) ) + fields.filter( ( { id } ) => !! form.fields?.includes( id ) ) ); return _fields.every( ( field ) => { return field.isValid( item, { elements: field.elements } ); diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 6a6efc23861841..86e2bf4d6edea1 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -46,7 +46,8 @@ function PostEditForm( { postType, postId } ) { const { saveEntityRecord } = useDispatch( coreDataStore ); const { fields } = usePostFields(); const form = { - visibleFields: [ 'title', 'author' ], + type: 'panel', + fields: [ 'title', 'author' ], }; const [ edits, setEdits ] = useState( {} ); const itemWithEdits = useMemo( () => { diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index dcca7d49ab708b..f476b676264ed8 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -186,6 +186,10 @@ function usePostFields( viewType ) { const addLink = [ LAYOUT_TABLE, LAYOUT_GRID ].includes( viewType ) && item.status !== 'trash'; + const renderedTitle = + typeof item.title === 'string' + ? item.title + : item.title?.rendered; const title = addLink ? ( <Link params={ { @@ -194,12 +198,12 @@ function usePostFields( viewType ) { canvas: 'edit', } } > - { decodeEntities( item.title?.rendered ) || + { decodeEntities( renderedTitle ) || __( '(no title)' ) } </Link> ) : ( <span> - { decodeEntities( item.title?.rendered ) || + { decodeEntities( renderedTitle ) || __( '(no title)' ) } </span> ); diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 4afa2f614fa2c3..983cc33b29e622 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -55,11 +55,11 @@ const fields = [ ]; const formDuplicateAction = { - visibleFields: [ 'title' ], + fields: [ 'title' ], }; const formOrderAction = { - visibleFields: [ 'menu_order' ], + fields: [ 'menu_order' ], }; /** From 19f4826cd88ed7c1144c55ee50b427f86cb9eea9 Mon Sep 17 00:00:00 2001 From: Rishit Gupta <rishitgupta2013@gmail.com> Date: Wed, 7 Aug 2024 09:53:36 -0400 Subject: [PATCH 0292/1908] Add WP Studio to list of tools in docs (#64327) Co-authored-by: Rishit30G <rishit30g@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> --- docs/getting-started/devenv/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/getting-started/devenv/README.md b/docs/getting-started/devenv/README.md index 1c2b9ed9070d30..4539dacbdf5047 100644 --- a/docs/getting-started/devenv/README.md +++ b/docs/getting-started/devenv/README.md @@ -54,6 +54,7 @@ Refer to the [Get started with `wp-env`](/docs/getting-started/devenv/get-starte This list is not exhaustive, but here are several additional options to choose from if you prefer not to use `wp-env`: - [Local](https://localwp.com/) +- [WP Studio](https://developer.wordpress.com/studio/) - [XAMPP](https://www.apachefriends.org/) - [MAMP](https://www.mamp.info/en/mamp/mac/) - [Varying Vagrant Vagrants](https://varyingvagrantvagrants.org/) (VVV) From 9ec153d297b14f5f958ba2a29ec961ae35772bb3 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 7 Aug 2024 15:56:48 +0200 Subject: [PATCH 0293/1908] Components: Update the TextControl padding to match the rest of the controls (#64326) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/text-control/style.scss | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 5cfc4eb2185b63..e8c1a0d90052b6 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -10,6 +10,7 @@ - `Modal`: Fix the dismissal logic for React development mode ([#64132](https://github.com/WordPress/gutenberg/pull/64132)). - `Autocompleter UI`: Fix text color when hovering selected item ([#64294](https://github.com/WordPress/gutenberg/pull/64294)). - `Heading`: Add the missing `size` prop to the component's props type ([#64299](https://github.com/WordPress/gutenberg/pull/64299)). +- `TextControl`: Fix the padding of the component to be consistent with the rest of the controls. ([#64326](https://github.com/WordPress/gutenberg/pull/64326)). ### Enhancements diff --git a/packages/components/src/text-control/style.scss b/packages/components/src/text-control/style.scss index 1e8477b255b9b1..d6819f86b84bf1 100644 --- a/packages/components/src/text-control/style.scss +++ b/packages/components/src/text-control/style.scss @@ -20,5 +20,10 @@ &.is-next-40px-default-size { height: $grid-unit-50; + + // Subtract 1px to account for the border, which isn't included on the element + // on newer components like InputControl, SelectControl, etc. + padding-left: $grid-unit-20; + padding-right: $grid-unit-20; } } From 19a2d835ee596132b5bcfb4550898ec433ae12e4 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 7 Aug 2024 23:01:07 +0900 Subject: [PATCH 0294/1908] DataViews: Restore focus style in Grid view (#64298) * DataViews: Restore focus style in Grid view * Prevent previews from bleeding outside the container Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/dataviews/src/dataviews-layouts/grid/style.scss | 1 - packages/edit-site/src/components/page-patterns/style.scss | 1 + packages/edit-site/src/components/page-templates/style.scss | 3 ++- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/dataviews/src/dataviews-layouts/grid/style.scss b/packages/dataviews/src/dataviews-layouts/grid/style.scss index ebe039ea7543b0..8f71953e155981 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/style.scss +++ b/packages/dataviews/src/dataviews-layouts/grid/style.scss @@ -38,7 +38,6 @@ background-color: $gray-100; border-radius: $grid-unit-05; position: relative; - overflow: hidden; img { object-fit: cover; diff --git a/packages/edit-site/src/components/page-patterns/style.scss b/packages/edit-site/src/components/page-patterns/style.scss index f457624d100c1f..ffcefd1924a535 100644 --- a/packages/edit-site/src/components/page-patterns/style.scss +++ b/packages/edit-site/src/components/page-patterns/style.scss @@ -6,6 +6,7 @@ display: flex; flex-direction: column; height: 100%; + border-radius: $radius-medium; .dataviews-view-table & { width: 96px; diff --git a/packages/edit-site/src/components/page-templates/style.scss b/packages/edit-site/src/components/page-templates/style.scss index 0313da00f89944..4e21ca2c25be28 100644 --- a/packages/edit-site/src/components/page-templates/style.scss +++ b/packages/edit-site/src/components/page-templates/style.scss @@ -3,6 +3,7 @@ flex-direction: column; height: 100%; width: 100%; + border-radius: $radius-medium; .page-templates-preview-field__button { box-shadow: none; @@ -13,7 +14,7 @@ cursor: pointer; overflow: hidden; height: 100%; - border-radius: $grid-unit-05; + border-radius: $radius-medium; &:focus-visible { box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); From dc54a90ff2fbda1476cd5bc83b7565ee85de1fb4 Mon Sep 17 00:00:00 2001 From: djcowan <dj.cowan@icloud.com> Date: Thu, 8 Aug 2024 00:45:47 +1000 Subject: [PATCH 0295/1908] Update api-reference.md (#64325) minor code example correction. Removed duplicate HTML span element closing tags `>>` on lines 58 and 69 [wp-interactive API](<https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/api-reference/#wp-interactive>) Co-authored-by: djcowan <djcowan@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- docs/reference-guides/interactivity-api/api-reference.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference-guides/interactivity-api/api-reference.md b/docs/reference-guides/interactivity-api/api-reference.md index 00030465415323..a4b400b8c0276b 100644 --- a/docs/reference-guides/interactivity-api/api-reference.md +++ b/docs/reference-guides/interactivity-api/api-reference.md @@ -55,7 +55,7 @@ The `wp-interactive` directive "activates" the interactivity for the DOM element data-wp-interactive="myPlugin" data-wp-context='{ "myColor" : "red", "myBgColor": "yellow" }' > - <p>I'm interactive now, <span data-wp-style--background-color="context.myBgColor">>and I can use directives!</span></p> + <p>I'm interactive now, <span data-wp-style--background-color="context.myBgColor">and I can use directives!</span></p> <div> <p>I'm also interactive, <span data-wp-style--color="context.myColor">and I can also use directives!</span></p> </div> @@ -66,7 +66,7 @@ The `wp-interactive` directive "activates" the interactivity for the DOM element data-wp-interactive='{ "namespace": "myPlugin" }' data-wp-context='{ "myColor" : "red", "myBgColor": "yellow" }' > - <p>I'm interactive now, <span data-wp-style--background-color="context.myBgColor">>and I can use directives!</span></p> + <p>I'm interactive now, <span data-wp-style--background-color="context.myBgColor">and I can use directives!</span></p> <div> <p>I'm also interactive, <span data-wp-style--color="context.myColor">and I can also use directives!</span></p> </div> From 50419e55466a4ebf1be49d823f86a683484c238b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 7 Aug 2024 17:29:05 +0200 Subject: [PATCH 0296/1908] DataForm: provide a better default for render when field has elements (#64338) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/dataviews/src/normalize-fields.ts | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index 3c3f6b07a0c296..860341cc946269 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -2,7 +2,7 @@ * Internal dependencies */ import getFieldTypeDefinition from './field-types'; -import type { Field, NormalizedField, ItemRecord } from './types'; +import type { Field, NormalizedField } from './types'; /** * Apply default values and normalize the fields config. @@ -18,7 +18,7 @@ export function normalizeFields< Item >( const getValue = field.getValue || - ( ( { item }: { item: ItemRecord } ) => item[ field.id ] ); + ( ( { item }: { item: Item } ) => item[ field.id as keyof Item ] ); const sort = field.sort ?? @@ -41,11 +41,25 @@ export function normalizeFields< Item >( const Edit = field.Edit || fieldTypeDefinition.Edit; + const renderFromElements = ( { item }: { item: Item } ) => { + const value = getValue( { item } ); + const label = field?.elements?.find( ( element ) => { + // Intentionally using == here to allow for type coercion. + // eslint-disable-next-line eqeqeq + return element.value == value; + } )?.label; + + return label || value; + }; + + const render = + field.render || ( field.elements ? renderFromElements : getValue ); + return { ...field, label: field.label || field.id, getValue, - render: field.render || getValue, + render, sort, isValid, Edit, From fd540c3dab11cae2f53f5f03ee60263d7f3ff51a Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Wed, 7 Aug 2024 17:52:26 +0200 Subject: [PATCH 0297/1908] Try: Improved tabbed sidebar styles (#61974) * Fix tabs indicator. * Improve styles. * Update after unified sidebar work. Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../src/components/tabbed-sidebar/style.scss | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/packages/block-editor/src/components/tabbed-sidebar/style.scss b/packages/block-editor/src/components/tabbed-sidebar/style.scss index 374a012173e230..f7fba1c0003467 100644 --- a/packages/block-editor/src/components/tabbed-sidebar/style.scss +++ b/packages/block-editor/src/components/tabbed-sidebar/style.scss @@ -23,22 +23,7 @@ } .block-editor-tabbed-sidebar__tablist { - box-sizing: border-box; - flex-grow: 1; - margin-bottom: -$border-width; - width: 100%; -} - -.block-editor-tabbed-sidebar__tab { - flex-grow: 1; margin-bottom: -$border-width; - - &[id$="reusable"] { - flex-grow: inherit; - // These are to align the `reusable` icon with the search icon. - padding-left: $grid-unit-20; - padding-right: $grid-unit-20; - } } .block-editor-tabbed-sidebar__tabpanel { From ea7d3b6c94b3b12c4b88f56da60c0987fa5840a2 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 8 Aug 2024 01:29:09 +0900 Subject: [PATCH 0298/1908] Button: Fix tertiary destructive hover style (#64152) * Button: Fix tertiary destructive hover style * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/button/style.scss | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index e8c1a0d90052b6..837fe973d1022a 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -8,6 +8,7 @@ - `CustomSelectControl`: Restore `describedBy` functionality ([#63957](https://github.com/WordPress/gutenberg/pull/63957)). - `Button`: Improve the aria-disabled focus style ([#62480](https://github.com/WordPress/gutenberg/pull/62480)). - `Modal`: Fix the dismissal logic for React development mode ([#64132](https://github.com/WordPress/gutenberg/pull/64132)). +- `Button`: Fix tertiary destructive hover style ([#64152](https://github.com/WordPress/gutenberg/pull/64152)). - `Autocompleter UI`: Fix text color when hovering selected item ([#64294](https://github.com/WordPress/gutenberg/pull/64294)). - `Heading`: Add the missing `size` prop to the component's props type ([#64299](https://github.com/WordPress/gutenberg/pull/64299)). - `TextControl`: Fix the padding of the component to be consistent with the rest of the controls. ([#64326](https://github.com/WordPress/gutenberg/pull/64326)). diff --git a/packages/components/src/button/style.scss b/packages/components/src/button/style.scss index fcbd363e17c7dd..7d67dcc0748b85 100644 --- a/packages/components/src/button/style.scss +++ b/packages/components/src/button/style.scss @@ -215,6 +215,16 @@ color: $gray-600; } } + + &.is-tertiary { + &:hover:not(:disabled, [aria-disabled="true"]) { + background: rgba($alert-red, 0.04); + } + + &:active:not(:disabled, [aria-disabled="true"]) { + background: rgba($alert-red, 0.08); + } + } } /** From b6478258875bebe7023bce45dc0316cb404a88eb Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Wed, 7 Aug 2024 19:35:37 +0200 Subject: [PATCH 0299/1908] Graduate data view options out of a menu to allow more design expression (#64175) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- package-lock.json | 2 + packages/dataviews/package.json | 1 + .../dataviews-view-config/index.tsx | 528 +++++++++--------- .../dataviews-view-config/style.scss | 44 ++ packages/dataviews/src/constants.ts | 5 + packages/dataviews/src/style.scss | 1 + packages/dataviews/tsconfig.json | 3 +- .../site-editor/new-templates-list.spec.js | 6 +- 8 files changed, 328 insertions(+), 262 deletions(-) create mode 100644 packages/dataviews/src/components/dataviews-view-config/style.scss diff --git a/package-lock.json b/package-lock.json index e2cab9e63002d4..c340c58c0b4f6c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52990,6 +52990,7 @@ "@wordpress/icons": "file:../icons", "@wordpress/primitives": "file:../primitives", "@wordpress/private-apis": "file:../private-apis", + "@wordpress/warning": "file:../warning", "clsx": "^2.1.1", "remove-accents": "^0.5.0" }, @@ -67763,6 +67764,7 @@ "@wordpress/icons": "file:../icons", "@wordpress/primitives": "file:../primitives", "@wordpress/private-apis": "file:../private-apis", + "@wordpress/warning": "file:../warning", "clsx": "^2.1.1", "remove-accents": "^0.5.0" }, diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index d95192957a1a43..53cfa97c275c60 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -38,6 +38,7 @@ "@wordpress/icons": "file:../icons", "@wordpress/primitives": "file:../primitives", "@wordpress/private-apis": "file:../private-apis", + "@wordpress/warning": "file:../warning", "clsx": "^2.1.1", "remove-accents": "^0.5.0" }, diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index b89e964f6a5d08..28e151079008eb 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -8,131 +8,92 @@ import type { ChangeEvent } from 'react'; */ import { Button, - privateApis as componentsPrivateApis, + Popover, + __experimentalToggleGroupControl as ToggleGroupControl, + __experimentalToggleGroupControlOption as ToggleGroupControlOption, + __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, + SelectControl, + __experimentalItemGroup as ItemGroup, + __experimentalItem as Item, + __experimentalGrid as Grid, + __experimentalVStack as VStack, __experimentalHStack as HStack, + __experimentalHeading as Heading, + __experimentalText as Text, + privateApis as componentsPrivateApis, } from '@wordpress/components'; import { __, _x } from '@wordpress/i18n'; -import { memo, useContext } from '@wordpress/element'; -import { cog } from '@wordpress/icons'; +import { memo, useContext, useState, useMemo } from '@wordpress/element'; +import { cog, seen, unseen } from '@wordpress/icons'; +import warning from '@wordpress/warning'; /** * Internal dependencies */ -import { unlock } from '../../lock-unlock'; -import { SORTING_DIRECTIONS, sortLabels } from '../../constants'; +import { SORTING_DIRECTIONS, sortIcons, sortLabels } from '../../constants'; import { VIEW_LAYOUTS, getMandatoryFields } from '../../dataviews-layouts'; -import type { NormalizedField, View, SupportedLayouts } from '../../types'; +import type { SupportedLayouts } from '../../types'; import DataViewsContext from '../dataviews-context'; +import { unlock } from '../../lock-unlock'; const { DropdownMenuV2: DropdownMenu, - DropdownMenuGroupV2: DropdownMenuGroup, - DropdownMenuItemV2: DropdownMenuItem, DropdownMenuRadioItemV2: DropdownMenuRadioItem, - DropdownMenuCheckboxItemV2: DropdownMenuCheckboxItem, DropdownMenuItemLabelV2: DropdownMenuItemLabel, } = unlock( componentsPrivateApis ); interface ViewTypeMenuProps { - view: View; - onChangeView: ( view: View ) => void; - defaultLayouts?: SupportedLayouts; -} - -interface PageSizeMenuProps { - view: View; - onChangeView: ( view: View ) => void; -} - -interface FieldsVisibilityMenuProps< Item > { - view: View; - onChangeView: ( view: View ) => void; - fields: NormalizedField< Item >[]; -} - -interface SortMenuProps< Item > { - fields: NormalizedField< Item >[]; - view: View; - onChangeView: ( view: View ) => void; -} - -interface ViewActionsProps { defaultLayouts?: SupportedLayouts; } function ViewTypeMenu( { - view, - onChangeView, defaultLayouts = { list: {}, grid: {}, table: {} }, }: ViewTypeMenuProps ) { + const { view, onChangeView } = useContext( DataViewsContext ); const availableLayouts = Object.keys( defaultLayouts ); if ( availableLayouts.length <= 1 ) { return null; } - return availableLayouts.map( ( layout ) => { - const config = VIEW_LAYOUTS.find( ( v ) => v.type === layout ); - if ( ! config ) { - return null; - } - return ( - <DropdownMenuRadioItem - key={ layout } - value={ layout } - name="view-actions-available-view" - checked={ layout === view.type } - hideOnClick - onChange={ ( e: ChangeEvent< HTMLInputElement > ) => { - switch ( e.target.value ) { - case 'list': - case 'grid': - case 'table': - return onChangeView( { - ...view, - type: e.target.value, - ...defaultLayouts[ e.target.value ], - } ); - } - throw new Error( 'Invalid dataview' ); - } } - > - <DropdownMenuItemLabel>{ config.label }</DropdownMenuItemLabel> - </DropdownMenuRadioItem> - ); - } ); -} - -const PAGE_SIZE_VALUES = [ 10, 20, 50, 100 ]; -function PageSizeMenu( { view, onChangeView }: PageSizeMenuProps ) { + const activeView = VIEW_LAYOUTS.find( ( v ) => view.type === v.type ); return ( <DropdownMenu trigger={ - <DropdownMenuItem - suffix={ <span aria-hidden="true">{ view.perPage }</span> } - > - <DropdownMenuItemLabel> - { __( 'Items per page' ) } - </DropdownMenuItemLabel> - </DropdownMenuItem> + <Button + size="compact" + icon={ activeView?.icon } + label={ __( 'Layout' ) } + /> } > - { PAGE_SIZE_VALUES.map( ( size ) => { + { availableLayouts.map( ( layout ) => { + const config = VIEW_LAYOUTS.find( ( v ) => v.type === layout ); + if ( ! config ) { + return null; + } return ( <DropdownMenuRadioItem - key={ size } - value={ size } - name="view-actions-page-size" - checked={ view.perPage === size } - onChange={ () => { - onChangeView( { - ...view, - // `e.target.value` holds the same value as `size` but as a string, - // so we use `size` directly to avoid parsing to int. - perPage: size, - page: 1, - } ); + key={ layout } + value={ layout } + name="view-actions-available-view" + checked={ layout === view.type } + hideOnClick + onChange={ ( e: ChangeEvent< HTMLInputElement > ) => { + switch ( e.target.value ) { + case 'list': + case 'grid': + case 'table': + return onChangeView( { + ...view, + type: e.target.value, + ...defaultLayouts[ e.target.value ], + } ); + } + warning( 'Invalid dataview' ); } } > - <DropdownMenuItemLabel>{ size }</DropdownMenuItemLabel> + <DropdownMenuItemLabel> + { config.label } + </DropdownMenuItemLabel> </DropdownMenuRadioItem> ); } ) } @@ -140,11 +101,125 @@ function PageSizeMenu( { view, onChangeView }: PageSizeMenuProps ) { ); } -function FieldsVisibilityMenu< Item >( { - view, - onChangeView, - fields, -}: FieldsVisibilityMenuProps< Item > ) { +interface ViewActionsProps { + defaultLayouts?: SupportedLayouts; +} + +function SortFieldControl() { + const { view, fields, onChangeView } = useContext( DataViewsContext ); + const orderOptions = useMemo( () => { + const sortableFields = fields.filter( + ( field ) => field.enableSorting !== false + ); + return sortableFields.map( ( field ) => { + return { + label: field.label, + value: field.id, + }; + } ); + }, [ fields ] ); + + return ( + <SelectControl + __nextHasNoMarginBottom + __next40pxDefaultSize + label={ __( 'Sort by' ) } + value={ view.sort?.field } + options={ orderOptions } + onChange={ ( value: string ) => { + onChangeView( { + ...view, + sort: { + direction: view?.sort?.direction || 'desc', + field: value, + }, + } ); + } } + /> + ); +} + +function SortDirectionControl() { + const { view, onChangeView } = useContext( DataViewsContext ); + return ( + <ToggleGroupControl + className="dataviews-view-config__sort-direction" + __nextHasNoMarginBottom + __next40pxDefaultSize + isBlock + label={ __( 'Order' ) } + value={ view.sort?.direction || 'desc' } + disabled={ ! view?.sort?.field } + onChange={ ( newDirection ) => { + if ( ! view?.sort?.field ) { + return; + } + if ( newDirection === 'asc' || newDirection === 'desc' ) { + onChangeView( { + ...view, + sort: { + direction: newDirection, + field: view.sort.field, + }, + } ); + return; + } + warning( 'Invalid direction' ); + } } + > + { SORTING_DIRECTIONS.map( ( direction ) => { + return ( + <ToggleGroupControlOptionIcon + key={ direction } + value={ direction } + icon={ sortIcons[ direction ] } + label={ sortLabels[ direction ] } + /> + ); + } ) } + </ToggleGroupControl> + ); +} + +const PAGE_SIZE_VALUES = [ 10, 20, 50, 100 ]; +function ItemsPerPageControl() { + const { view, onChangeView } = useContext( DataViewsContext ); + return ( + <ToggleGroupControl + __nextHasNoMarginBottom + __next40pxDefaultSize + isBlock + label={ __( 'Items per page' ) } + value={ view.perPage || 10 } + disabled={ ! view?.sort?.field } + onChange={ ( newItemsPerPage ) => { + const newItemsPerPageNumber = + typeof newItemsPerPage === 'number' || + newItemsPerPage === undefined + ? newItemsPerPage + : parseInt( newItemsPerPage, 10 ); + onChangeView( { + ...view, + perPage: newItemsPerPageNumber, + page: 1, + } ); + } } + > + { PAGE_SIZE_VALUES.map( ( value ) => { + return ( + <ToggleGroupControlOption + key={ value } + value={ value } + label={ value.toString() } + /> + ); + } ) } + </ToggleGroupControl> + ); +} + +function FieldControl() { + const { view, fields, onChangeView } = useContext( DataViewsContext ); const mandatoryFields = getMandatoryFields( view ); const hidableFields = fields.filter( ( field ) => @@ -156,185 +231,124 @@ function FieldsVisibilityMenu< Item >( { return null; } return ( - <DropdownMenu - trigger={ - <DropdownMenuItem> - <DropdownMenuItemLabel> - { __( 'Fields' ) } - </DropdownMenuItemLabel> - </DropdownMenuItem> - } - > + <ItemGroup isBordered isSeparated> { hidableFields?.map( ( field ) => { + const isVisible = viewFields.includes( field.id ); return ( - <DropdownMenuCheckboxItem - key={ field.id } - value={ field.id } - checked={ viewFields.includes( field.id ) } - onChange={ () => { - onChangeView( { - ...view, - fields: viewFields.includes( field.id ) - ? viewFields.filter( - ( id ) => id !== field.id - ) - : [ ...viewFields, field.id ], - } ); - } } - > - <DropdownMenuItemLabel> - { field.label } - </DropdownMenuItemLabel> - </DropdownMenuCheckboxItem> + <Item key={ field.id }> + <HStack expanded> + <span>{ field.label }</span> + <Button + className="'dataviews-view-config__field-control-button" + size="compact" + onClick={ () => + onChangeView( { + ...view, + fields: isVisible + ? viewFields.filter( + ( id ) => id !== field.id + ) + : [ ...viewFields, field.id ], + } ) + } + icon={ isVisible ? seen : unseen } + label={ + isVisible + ? __( 'Hide field' ) + : __( 'Show field' ) + } + /> + </HStack> + </Item> ); } ) } - </DropdownMenu> + </ItemGroup> ); } -function SortMenu< Item >( { - fields, - view, - onChangeView, -}: SortMenuProps< Item > ) { - const sortableFields = fields.filter( - ( field ) => field.enableSorting !== false - ); - if ( ! sortableFields?.length ) { - return null; - } - const currentSortedField = fields.find( - ( field ) => field.id === view.sort?.field - ); +function SettingsSection( { + title, + description, + children, +}: { + title: string; + description?: string; + children: React.ReactNode; +} ) { return ( - <DropdownMenu - trigger={ - <DropdownMenuItem - suffix={ - <span aria-hidden="true"> - { currentSortedField?.label } - </span> - } + <Grid columns={ 12 } className="dataviews-settings-section" gap={ 4 }> + <div className="dataviews-settings-section__sidebar"> + <Heading + level={ 2 } + className="dataviews-settings-section__title" > - <DropdownMenuItemLabel> - { __( 'Sort by' ) } - </DropdownMenuItemLabel> - </DropdownMenuItem> - } - > - { sortableFields?.map( ( field ) => { - const sortedDirection = view.sort?.direction; - return ( - <DropdownMenu - key={ field.id } - trigger={ - <DropdownMenuItem> - <DropdownMenuItemLabel> - { field.label } - </DropdownMenuItemLabel> - </DropdownMenuItem> - } - style={ { - minWidth: '220px', - } } + { title } + </Heading> + { description && ( + <Text + variant="muted" + className="dataviews-settings-section__description" > - { SORTING_DIRECTIONS.map( ( direction ) => { - const isChecked = - currentSortedField !== undefined && - sortedDirection === direction && - field.id === currentSortedField.id; - - const value = `${ field.id }-${ direction }`; + { description } + </Text> + ) } + </div> + <Grid + columns={ 8 } + gap={ 4 } + className="dataviews-settings-section__content" + > + { children } + </Grid> + </Grid> + ); +} - return ( - <DropdownMenuRadioItem - key={ value } - // All sorting radio items share the same name, so that - // selecting a sorting option automatically deselects the - // previously selected one, even if it is displayed in - // another submenu. The field and direction are passed via - // the `value` prop. - name="view-actions-sorting" - value={ value } - checked={ isChecked } - onChange={ () => { - onChangeView( { - ...view, - sort: { - field: field.id, - direction, - }, - } ); - } } - > - <DropdownMenuItemLabel> - { sortLabels[ direction ] } - </DropdownMenuItemLabel> - </DropdownMenuRadioItem> - ); - } ) } - </DropdownMenu> - ); - } ) } - </DropdownMenu> +function DataviewsViewConfigContent() { + return ( + <VStack className="dataviews-view-config" spacing={ 6 }> + <SettingsSection title={ __( 'Appearance' ) }> + <HStack expanded className="is-divided-in-two"> + <SortFieldControl /> + <SortDirectionControl /> + </HStack> + <ItemsPerPageControl /> + </SettingsSection> + <SettingsSection title={ __( 'Properties' ) }> + <FieldControl /> + </SettingsSection> + </VStack> ); } -function _DataViewsViewConfig( { defaultLayouts }: ViewActionsProps ) { - const { view, fields, onChangeView } = useContext( DataViewsContext ); - const activeView = VIEW_LAYOUTS.find( ( v ) => view.type === v.type ); +function _DataViewsViewConfig( { + defaultLayouts = { list: {}, grid: {}, table: {} }, +}: ViewActionsProps ) { + const [ isShowingViewPopover, setIsShowingViewPopover ] = + useState< boolean >( false ); + return ( <> - <HStack - spacing={ 1 } - expanded={ false } - style={ { flexShrink: 0 } } - > - <DropdownMenu - trigger={ - <Button - size="compact" - icon={ activeView?.icon } - label={ __( 'Layout' ) } - /> - } - > - <ViewTypeMenu - view={ view } - onChangeView={ onChangeView } - defaultLayouts={ defaultLayouts } - /> - </DropdownMenu> - <DropdownMenu - trigger={ - <Button - size="compact" - icon={ cog } - label={ _x( - 'View options', - 'View is used as a noun' - ) } - /> - } - > - <DropdownMenuGroup> - <SortMenu - fields={ fields } - view={ view } - onChangeView={ onChangeView } - /> - <FieldsVisibilityMenu - fields={ fields } - view={ view } - onChangeView={ onChangeView } - /> - <PageSizeMenu - view={ view } - onChangeView={ onChangeView } - /> - </DropdownMenuGroup> - </DropdownMenu> - </HStack> + <ViewTypeMenu defaultLayouts={ defaultLayouts } /> + <div> + <Button + size="compact" + icon={ cog } + label={ _x( 'View options', 'View is used as a noun' ) } + onClick={ () => setIsShowingViewPopover( true ) } + /> + { isShowingViewPopover && ( + <Popover + placement="bottom-end" + onClose={ () => { + setIsShowingViewPopover( false ); + } } + focusOnMount + > + <DataviewsViewConfigContent /> + </Popover> + ) } + </div> </> ); } diff --git a/packages/dataviews/src/components/dataviews-view-config/style.scss b/packages/dataviews/src/components/dataviews-view-config/style.scss new file mode 100644 index 00000000000000..85e86722f7b614 --- /dev/null +++ b/packages/dataviews/src/components/dataviews-view-config/style.scss @@ -0,0 +1,44 @@ +.dataviews-view-config { + width: 320px; + /* stylelint-disable-next-line property-no-unknown -- the linter needs to be updated to accepted the container-type property */ + container-type: inline-size; + padding: $grid-unit-20; +} +.dataviews-view-config__sort-direction .components-toggle-group-control-option-base { + text-transform: uppercase; +} + +.dataviews-settings-section__title.dataviews-settings-section__title { + line-height: $grid-unit-30; + font-size: 15px; +} + +.dataviews-settings-section__sidebar { + grid-column: span 4; +} + +.dataviews-settings-section__content, +.dataviews-settings-section__content > * { + grid-column: span 8; +} + +.dataviews-settings-section__content .is-divided-in-two { + display: contents; + & > * { + grid-column: span 4; + } +} + +/* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ +@container (max-width: 500px) { + .dataviews-settings-section.dataviews-settings-section { + grid-template-columns: repeat(2, 1fr); + .dataviews-settings-section__sidebar { + grid-column: span 2; + } + + .dataviews-settings-section__content { + grid-column: span 2; + } + } +} diff --git a/packages/dataviews/src/constants.ts b/packages/dataviews/src/constants.ts index 48753470280d0c..5ae94c7eb4a135 100644 --- a/packages/dataviews/src/constants.ts +++ b/packages/dataviews/src/constants.ts @@ -2,6 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; +import { arrowDown, arrowUp } from '@wordpress/icons'; /** * Internal dependencies @@ -58,6 +59,10 @@ export const sortLabels = { asc: __( 'Sort ascending' ), desc: __( 'Sort descending' ), }; +export const sortIcons = { + asc: arrowUp, + desc: arrowDown, +}; // View layouts. export const LAYOUT_TABLE = 'table'; diff --git a/packages/dataviews/src/style.scss b/packages/dataviews/src/style.scss index 7cf737b9a3849f..b780c9c3a587d5 100644 --- a/packages/dataviews/src/style.scss +++ b/packages/dataviews/src/style.scss @@ -5,6 +5,7 @@ @import "./components/dataviews-pagination/style.scss"; @import "./components/dataviews-item-actions/style.scss"; @import "./components/dataviews-selection-checkbox/style.scss"; +@import "./components/dataviews-view-config/style.scss"; @import "./dataviews-layouts/grid/style.scss"; @import "./dataviews-layouts/list/style.scss"; diff --git a/packages/dataviews/tsconfig.json b/packages/dataviews/tsconfig.json index 869f9fcfb9b499..78e68b5a7c98b4 100644 --- a/packages/dataviews/tsconfig.json +++ b/packages/dataviews/tsconfig.json @@ -14,7 +14,8 @@ { "path": "../i18n" }, { "path": "../icons" }, { "path": "../primitives" }, - { "path": "../private-apis" } + { "path": "../private-apis" }, + { "path": "../warning" } ], "include": [ "src" ] } diff --git a/test/e2e/specs/site-editor/new-templates-list.spec.js b/test/e2e/specs/site-editor/new-templates-list.spec.js index 878f0ed2eb48c3..31dbe9af814d2e 100644 --- a/test/e2e/specs/site-editor/new-templates-list.spec.js +++ b/test/e2e/specs/site-editor/new-templates-list.spec.js @@ -24,9 +24,7 @@ test.describe( 'Templates', () => { // Descending by title. await page.getByRole( 'button', { name: 'View options' } ).click(); - await page.getByRole( 'menuitem', { name: 'Sort by' } ).click(); - await page.getByRole( 'menuitem', { name: 'Template' } ).click(); - await page.getByRole( 'menuitemradio', { name: 'descending' } ).click(); + await page.getByRole( 'radio', { name: 'Sort descending' } ).click(); const firstTitle = page .getByRole( 'region', { name: 'Template', @@ -37,7 +35,7 @@ test.describe( 'Templates', () => { await expect( firstTitle ).toHaveText( 'Tag Archives' ); // Ascending by title. - await page.getByRole( 'menuitemradio', { name: 'ascending' } ).click(); + await page.getByRole( 'radio', { name: 'Sort ascending' } ).click(); await expect( firstTitle ).toHaveText( 'Category Archives' ); } ); From b43e05e8e5a136261ae04445355ee4e82a794d87 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 8 Aug 2024 02:37:57 +0900 Subject: [PATCH 0300/1908] Add margin-bottom lint rules for SelectControl (#64283) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix in ResolutionTool Doesn't matter because this is wrapped in a ToolsPanelItem, which already does normalization on BaseControl margins. * Fix in test * Fix in Form block * Fix in Post Navigation block * Fix in Font Library ▸ Install Fonts * Add eslint rule * Fix in DataForm text field type * Add prop to JSDoc * Fix in Query Loop block * Remove unnecessary additions in DataForm * TreeSelect: Fix up JSDoc formatting * Add to InspectorControls readme Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .eslintrc.js | 1 + .../src/components/inspector-controls/README.md | 5 +++++ .../block-editor/src/components/resolution-tool/index.js | 1 + .../src/components/responsive-block-control/test/index.js | 6 +++++- packages/block-library/src/form/edit.js | 5 +++-- packages/block-library/src/post-navigation-link/edit.js | 2 ++ .../src/query/edit/inspector-controls/order-control.js | 1 + packages/components/src/select-control/index.tsx | 1 + packages/components/src/tree-select/index.tsx | 3 +-- .../global-styles/font-library-modal/font-collection.js | 2 ++ .../components/global-styles/font-library-modal/style.scss | 1 + 11 files changed, 23 insertions(+), 5 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index cb132fbb3d7aba..81408499bd34f4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -295,6 +295,7 @@ module.exports = { 'FocalPointPicker', 'RangeControl', 'SearchControl', + 'SelectControl', 'TextControl', 'TextareaControl', 'ToggleControl', diff --git a/packages/block-editor/src/components/inspector-controls/README.md b/packages/block-editor/src/components/inspector-controls/README.md index cc68c7cae7c78e..fd4847f53472b2 100644 --- a/packages/block-editor/src/components/inspector-controls/README.md +++ b/packages/block-editor/src/components/inspector-controls/README.md @@ -96,6 +96,7 @@ registerBlockType( 'my-plugin/inspector-controls-example', { <InspectorControls> <PanelBody title={ __( 'Settings' ) }> <CheckboxControl + __nextHasNoMarginBottom heading="Checkbox Field" label="Tick Me" help="Additional help text" @@ -114,6 +115,7 @@ registerBlockType( 'my-plugin/inspector-controls-example', { /> <TextControl + __nextHasNoMarginBottom label="Text Field" help="Additional help text" value={ textField } @@ -121,12 +123,14 @@ registerBlockType( 'my-plugin/inspector-controls-example', { /> <ToggleControl + __nextHasNoMarginBottom label="Toggle Field" checked={ toggleField } onChange={ onChangeToggleField } /> <SelectControl + __nextHasNoMarginBottom label="Select Control" value={ selectField } options={ [ @@ -203,6 +207,7 @@ function MyBlockEdit( { attributes, setAttributes } ) { </InspectorControls> <InspectorAdvancedControls> <TextControl + __nextHasNoMarginBottom label="HTML anchor" value={ attributes.anchor } onChange={ ( nextValue ) => { diff --git a/packages/block-editor/src/components/resolution-tool/index.js b/packages/block-editor/src/components/resolution-tool/index.js index 42fea6e8655a8e..df43cb6acb096d 100644 --- a/packages/block-editor/src/components/resolution-tool/index.js +++ b/packages/block-editor/src/components/resolution-tool/index.js @@ -44,6 +44,7 @@ export default function ResolutionTool( { panelId={ panelId } > <SelectControl + __nextHasNoMarginBottom label={ __( 'Resolution' ) } value={ displayValue } options={ options } diff --git a/packages/block-editor/src/components/responsive-block-control/test/index.js b/packages/block-editor/src/components/responsive-block-control/test/index.js index 5d01d8e35ff20b..57944b591108d7 100644 --- a/packages/block-editor/src/components/responsive-block-control/test/index.js +++ b/packages/block-editor/src/components/responsive-block-control/test/index.js @@ -39,7 +39,11 @@ const sizeOptions = [ const renderTestDefaultControlComponent = ( labelComponent, device ) => { return ( <> - <SelectControl label={ labelComponent } options={ sizeOptions } /> + <SelectControl + label={ labelComponent } + options={ sizeOptions } + __nextHasNoMarginBottom + /> <p id={ device.id }> { device.label } is used here for testing purposes to ensure we have access to details about the device. diff --git a/packages/block-library/src/form/edit.js b/packages/block-library/src/form/edit.js index bea513a3785dcd..2738644878660a 100644 --- a/packages/block-library/src/form/edit.js +++ b/packages/block-library/src/form/edit.js @@ -77,8 +77,8 @@ const Edit = ( { attributes, setAttributes, clientId } ) => { <InspectorControls> <PanelBody title={ __( 'Settings' ) }> <SelectControl - // __nextHasNoMarginBottom - // size={ '__unstable-large' } + __nextHasNoMarginBottom + __next40pxDefaultSize label={ __( 'Submissions method' ) } options={ [ // TODO: Allow plugins to add their own submission methods. @@ -108,6 +108,7 @@ const Edit = ( { attributes, setAttributes, clientId } ) => { { submissionMethod === 'email' && ( <TextControl __nextHasNoMarginBottom + __next40pxDefaultSize autoComplete="off" label={ __( 'Email for form submissions' ) } value={ email } diff --git a/packages/block-library/src/post-navigation-link/edit.js b/packages/block-library/src/post-navigation-link/edit.js index 25cabe442b9c09..b181e677acae98 100644 --- a/packages/block-library/src/post-navigation-link/edit.js +++ b/packages/block-library/src/post-navigation-link/edit.js @@ -157,6 +157,8 @@ export default function PostNavigationLinkEdit( { </InspectorControls> <InspectorControls group="advanced"> <SelectControl + __next40pxDefaultSize + __nextHasNoMarginBottom label={ __( 'Filter by taxonomy' ) } value={ taxonomy } options={ getTaxonomyOptions() } diff --git a/packages/block-library/src/query/edit/inspector-controls/order-control.js b/packages/block-library/src/query/edit/inspector-controls/order-control.js index d50d3349bcbafd..2f6fa0e589d473 100644 --- a/packages/block-library/src/query/edit/inspector-controls/order-control.js +++ b/packages/block-library/src/query/edit/inspector-controls/order-control.js @@ -27,6 +27,7 @@ const orderOptions = [ function OrderControl( { order, orderBy, onChange } ) { return ( <SelectControl + __nextHasNoMarginBottom __next40pxDefaultSize label={ __( 'Order by' ) } value={ `${ orderBy }/${ order }` } diff --git a/packages/components/src/select-control/index.tsx b/packages/components/src/select-control/index.tsx index 8a3b6bda68a160..ca9966fc675b86 100644 --- a/packages/components/src/select-control/index.tsx +++ b/packages/components/src/select-control/index.tsx @@ -153,6 +153,7 @@ function UnforwardedSelectControl< V extends string >( * * return ( * <SelectControl + * __nextHasNoMarginBottom * label="Size" * value={ size } * options={ [ diff --git a/packages/components/src/tree-select/index.tsx b/packages/components/src/tree-select/index.tsx index 626fb0fda3a01c..599dee4402ec72 100644 --- a/packages/components/src/tree-select/index.tsx +++ b/packages/components/src/tree-select/index.tsx @@ -37,7 +37,7 @@ function getSelectOptions( * * return ( * <TreeSelect - * __nextHasNoMarginBottom + * __nextHasNoMarginBottom * label="Parent page" * noOptionLabel="No parent page" * onChange={ ( newPage ) => setPage( newPage ) } @@ -73,7 +73,6 @@ function getSelectOptions( * } * ``` */ - export function TreeSelect( props: TreeSelectProps ) { const { label, diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js index 6f8a27a8aa8927..357bcba1d93137 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js @@ -315,6 +315,8 @@ function FontCollection( { slug } ) { </FlexItem> <FlexItem> <SelectControl + __nextHasNoMarginBottom + __next40pxDefaultSize label={ __( 'Category' ) } value={ filters.category } onChange={ handleCategoryFilter } diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss index 10b5b816cb9bdc..ce5197a73cabf9 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss +++ b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss @@ -69,6 +69,7 @@ $footer-height: 70px; color: $gray-900; } +// TODO: See if this can be removed after https://github.com/WordPress/gutenberg/issues/38730 .font-library-modal__tabpanel-layout .components-base-control__field { margin-bottom: 0; } From 7cfd3c648aed8c05795536b21cb574800698f0b7 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 7 Aug 2024 18:05:08 +0000 Subject: [PATCH 0301/1908] Bump plugin version to 19.0.0-rc.1 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index b12c3467410603..6ec0a56f00e74d 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 18.9.0 + * Version: 19.0.0-rc.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index c340c58c0b4f6c..a28512799804aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "18.9.0", + "version": "19.0.0-rc.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "18.9.0", + "version": "19.0.0-rc.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 53e8d0876ed621..fac57093a852c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "18.9.0", + "version": "19.0.0-rc.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 32f0d30bab8c39347fc72fcd8de240079f166951 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 7 Aug 2024 18:24:21 +0000 Subject: [PATCH 0302/1908] Update Changelog for 19.0.0-rc.1 --- changelog.txt | 368 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) diff --git a/changelog.txt b/changelog.txt index b7bbdf821f374e..e85895547e87d1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,373 @@ == Changelog == += 19.0.0-rc.1 = + + +## Changelog + +### Enhancements + +- Add alt edit field to the inline image in the format library ([64124](https://github.com/WordPress/gutenberg/pull/64124)) +- Update copy from "No Title" to "No title" across multiple places on the editor. ([64184](https://github.com/WordPress/gutenberg/pull/64184)) +- Update column input to be 40px by default. ([64190](https://github.com/WordPress/gutenberg/pull/64190)) + +#### Block Library +- Add anchor block support to List Items. ([48758](https://github.com/WordPress/gutenberg/pull/48758)) +- Unset the rowStart and columnStart attributes when a block inside the Grid is removed from a manual layout. ([64186](https://github.com/WordPress/gutenberg/pull/64186)) +- Update Group block example. ([63114](https://github.com/WordPress/gutenberg/pull/63114)) +- Make SiteLogoReplaceFlow always available in the Site Logo block toolbar. ([63499](https://github.com/WordPress/gutenberg/pull/63499)) +- Make Query Loop settings more intuitive with a ToggleGroup and simplified help text. ([63739](https://github.com/WordPress/gutenberg/pull/63739)) +- Move gallery link controls to the block toolbar. ([62762](https://github.com/WordPress/gutenberg/pull/62762)) +- Hide loading when the overlay menu is selected. ([64262](https://github.com/WordPress/gutenberg/pull/64262)) +- Move the Site Logo tooltip to the middle right. ([64296](https://github.com/WordPress/gutenberg/pull/64296)) +- Prevent duplicate spacing on Tag Cloud block. ([63832](https://github.com/WordPress/gutenberg/pull/63832)) +- Fix 'can user edit' Template Part check. ([64137](https://github.com/WordPress/gutenberg/pull/64137)) +- Add clearfix in Post content. ([63690](https://github.com/WordPress/gutenberg/pull/63690)) +- Tweak Tag Cloud controls and description. ([64151](https://github.com/WordPress/gutenberg/pull/64151)) +- Tweak list block. ([64025](https://github.com/WordPress/gutenberg/pull/64025)) +- Update MediaUpload button for the site logo from "Add media" to "Choose logo". ([63498](https://github.com/WordPress/gutenberg/pull/63498)) +- Update help text for sticky control in Query loop. ([63999](https://github.com/WordPress/gutenberg/pull/63999)) +- Add border support to the following blocks: + - [Time To Read](https://github.com/WordPress/gutenberg/pull/63776) + - [Categories List](https://github.com/WordPress/gutenberg/pull/63950) + - [Post Date](https://github.com/WordPress/gutenberg/pull/64023) + - [Post Excerpt](https://github.com/WordPress/gutenberg/pull/64022) + - [Post Terms](https://github.com/WordPress/gutenberg/pull/64246) + - [Post Title](https://github.com/WordPress/gutenberg/pull/64024) + - [Site Tagline](https://github.com/WordPress/gutenberg/pull/63778) + - [Site Title](https://github.com/WordPress/gutenberg/pull/63631) + - [Table of contents](https://github.com/WordPress/gutenberg/pull/63578) + +#### Extensibility +- Add an async `__unstablePreSavePost` hook; resolving with false prevents saving. ([58022](https://github.com/WordPress/gutenberg/pull/58022)) +- Enable heading level curation. ([63535](https://github.com/WordPress/gutenberg/pull/63535)) +- Addition of `levelOptions` attribute to control available heading levels in [Post Title](https://github.com/WordPress/gutenberg/pull/64106), [Query Title](https://github.com/WordPress/gutenberg/pull/64107), [Site Tagline](https://github.com/WordPress/gutenberg/pull/64113), [Site Title](https://github.com/WordPress/gutenberg/pull/64111), and [Comments Title](https://github.com/WordPress/gutenberg/pull/64103). + +#### Data Views +- Be more clear with the copy of the "hide" action. ([63047](https://github.com/WordPress/gutenberg/pull/63047)) +- Graduate data view options out of a menu to allow more design expression. ([64175](https://github.com/WordPress/gutenberg/pull/64175)) +- Move filter UI into a toggle-able panel to improve experience on narrow viewports/containers. ([63203](https://github.com/WordPress/gutenberg/pull/63203)) +- Update field line-height across grid/list layouts. ([63945](https://github.com/WordPress/gutenberg/pull/63945)) +- Update template description in table layout. ([63942](https://github.com/WordPress/gutenberg/pull/63942)) +- De-emphasise bulk actions on Grid layout. ([64209](https://github.com/WordPress/gutenberg/pull/64209)) +- Update the copy of some of the strings on dataviews actions. ([64099](https://github.com/WordPress/gutenberg/pull/64099)) + +##### Dataviews Extensibility + +- Allow unregistering of the following post actions: [permanently delete](https://github.com/WordPress/gutenberg/pull/64088), [restore post](https://github.com/WordPress/gutenberg/pull/64134), and [trash post](https://github.com/WordPress/gutenberg/pull/64087). + +#### Dataform + +- Add author to quick edit page/post list. ([63983](https://github.com/WordPress/gutenberg/pull/63983)) +- If a field of type `text` declare `elements`, render it as a `SelectControl` in `edit`. ([64251](https://github.com/WordPress/gutenberg/pull/64251)) +- Migrate order action modal and introduce form validation. ([63895](https://github.com/WordPress/gutenberg/pull/63895)) + + + +#### Components +- Add radius scale. ([64007](https://github.com/WordPress/gutenberg/pull/64007)) +- Support generic props type on CustomSelectControl. ([63985](https://github.com/WordPress/gutenberg/pull/63985)) +- Guide: Add __next40pxDefaultSize to buttons. ([64181](https://github.com/WordPress/gutenberg/pull/64181)) +- Image: Make Placeholder white when there is a <Spinner /> on top. ([63885](https://github.com/WordPress/gutenberg/pull/63885)) +- SelectControl: Infer `value` type from `options`. ([64069](https://github.com/WordPress/gutenberg/pull/64069)) +- SelectControl: Pass through `options` props. ([64211](https://github.com/WordPress/gutenberg/pull/64211)) +- TimeInput: Expose as subcomponent of TimePicker. ([63145](https://github.com/WordPress/gutenberg/pull/63145)) +- Update radius variables in components configuration. ([64133](https://github.com/WordPress/gutenberg/pull/64133)) +- `RadioControl`: Add support for option help text. ([63751](https://github.com/WordPress/gutenberg/pull/63751)) + +#### Block Editor +- Block Autocompleter: Force icon color to text color when item is selected. ([61376](https://github.com/WordPress/gutenberg/pull/61376)) +- Don't overlap canvas with inserter panel at large screens. ([64110](https://github.com/WordPress/gutenberg/pull/64110)) +- Format Library: Polish inline image format popover. ([64016](https://github.com/WordPress/gutenberg/pull/64016)) +- LineHeightControl: Hard deprecate bottom margin. ([64281](https://github.com/WordPress/gutenberg/pull/64281)) +- New useBlockElementRef hook for storing block element into a ref. ([63799](https://github.com/WordPress/gutenberg/pull/63799)) +- Improved tabbed sidebar styles. ([61974](https://github.com/WordPress/gutenberg/pull/61974)) +- URLInput: Hard deprecate bottom margin. ([64282](https://github.com/WordPress/gutenberg/pull/64282)) + +#### Global Styles +- Add a typesets section to Typography. ([62539](https://github.com/WordPress/gutenberg/pull/62539)) +- Add tooltips to the heading level selectors. ([64039](https://github.com/WordPress/gutenberg/pull/64039)) +- Background images: Ensure appropriate default values. ([64192](https://github.com/WordPress/gutenberg/pull/64192)) +- Create new public function to make it easier to expose style variations from other themes. ([63318](https://github.com/WordPress/gutenberg/pull/63318)) +- Style Book: Clearly denote heading levels. ([64038](https://github.com/WordPress/gutenberg/pull/64038)) + +#### Design Tools +- Column: Enable border radius support. ([63924](https://github.com/WordPress/gutenberg/pull/63924)) +- Comment Template: Add Border Block Support. ([64238](https://github.com/WordPress/gutenberg/pull/64238)) +- Post Comments Form: Add Border Block Support. ([64233](https://github.com/WordPress/gutenberg/pull/64233)) + +#### Zoom Out +- Add a control to enter and leave zoom out mode. ([63870](https://github.com/WordPress/gutenberg/pull/63870)) +- Improve zoom transition. ([64179](https://github.com/WordPress/gutenberg/pull/64179)) + +#### Site Editor +- Clarify that the site icon is a back button using an animation. ([63986](https://github.com/WordPress/gutenberg/pull/63986)) +- Site Icon: Add back filter effect to make it work for all kind of site icons. ([64172](https://github.com/WordPress/gutenberg/pull/64172)) + +#### Post Editor +- Tweak Create custom template modal. ([64255](https://github.com/WordPress/gutenberg/pull/64255)) + +#### Icons +- Add new "send" icon. ([64130](https://github.com/WordPress/gutenberg/pull/64130)) + +#### Plugin +- Bump minimum required WordPress version to 6.5. ([64126](https://github.com/WordPress/gutenberg/pull/64126)) + +#### Font Library +- Include a "Select All" options for google fonts. ([63893](https://github.com/WordPress/gutenberg/pull/63893)) + +#### Block bindings +- Allow bindings bootstrap after registration. ([63797](https://github.com/WordPress/gutenberg/pull/63797)) + +#### Interactivity API +- Refactor internal proxy and signals system. ([62734](https://github.com/WordPress/gutenberg/pull/62734)) + + +### New APIs + +- Make useStyleOverride public. ([63656](https://github.com/WordPress/gutenberg/pull/63656)) + + +### Bug Fixes + +- Core Data: Fix 'getEntityRecordPermissions' memoization. ([64091](https://github.com/WordPress/gutenberg/pull/64091)) +- Document bar: Fix long title with no spaces causing layout issue. ([64092](https://github.com/WordPress/gutenberg/pull/64092)) +- Fix density slider minus to be correct. ([64185](https://github.com/WordPress/gutenberg/pull/64185)) +- Fix: Deleting a pattern throws a notice saying undefined deleted. ([64301](https://github.com/WordPress/gutenberg/pull/64301)) +- Primitives: Add missing peer dependency. ([64218](https://github.com/WordPress/gutenberg/pull/64218)) +- Site Icon: Fix position in distraction free mode. ([64261](https://github.com/WordPress/gutenberg/pull/64261)) + +#### Data Views +- Add context to trash string. ([64249](https://github.com/WordPress/gutenberg/pull/64249)) +- Conditionally shows the description field in Template Grid layout. ([64043](https://github.com/WordPress/gutenberg/pull/64043)) +- Consider layout URL parameter when loading a default/custom view. ([64306](https://github.com/WordPress/gutenberg/pull/64306)) +- Display published date for pages/posts with published status. ([64049](https://github.com/WordPress/gutenberg/pull/64049)) +- Sort author by name + allow custom sort function. ([64064](https://github.com/WordPress/gutenberg/pull/64064)) +- Don't render action modal when there are no eligible items. ([64250](https://github.com/WordPress/gutenberg/pull/64250)) +- Pages: Update `useView` logic. ([63889](https://github.com/WordPress/gutenberg/pull/63889)) +- Update template preview dimensions in table layout. ([63938](https://github.com/WordPress/gutenberg/pull/63938)) +- Update template preview dimensions in table layout. ([63938](https://github.com/WordPress/gutenberg/pull/63938)) + +#### Dataform + +- Fix SelectControl size and spacing. ([64324](https://github.com/WordPress/gutenberg/pull/64324)) +- Provide a better default for render when field has elements. ([64338](https://github.com/WordPress/gutenberg/pull/64338)) + +#### Components +- Autocompleter UI: Fix text color when hovering selected item. ([64294](https://github.com/WordPress/gutenberg/pull/64294)) +- BaseControl: change label's display: Block. ([63911](https://github.com/WordPress/gutenberg/pull/63911)) +- Button: Fix tertiary destructive hover style. ([64152](https://github.com/WordPress/gutenberg/pull/64152)) +- ColorPalette: Remove extra bottom margin when `CircularOptionPicker` is unneeded. ([63961](https://github.com/WordPress/gutenberg/pull/63961)) +- DropdownMenuV2: Break menu item help text on multiple lines for better truncation. ([63916](https://github.com/WordPress/gutenberg/pull/63916)) +- Fix modal dismissers in development mode. ([64132](https://github.com/WordPress/gutenberg/pull/64132)) +- Fix toggle help indentation. ([63903](https://github.com/WordPress/gutenberg/pull/63903)) +- Update the TextControl padding to match the rest of the controls. ([64326](https://github.com/WordPress/gutenberg/pull/64326)) + +#### Global Styles +- Fix block custom CSS pseudo element selectors. ([63980](https://github.com/WordPress/gutenberg/pull/63980)) +- Fix block library and global styles stylesheet ordering when a block style variation is active. ([63918](https://github.com/WordPress/gutenberg/pull/63918)) +- Style Book: Fix critical error when heading block is not registered. ([64047](https://github.com/WordPress/gutenberg/pull/64047)) +- TypesetButton: Check if variations exist before running logic. ([64139](https://github.com/WordPress/gutenberg/pull/64139)) + +#### Site Editor +- Centrally align entity in focused edit mode. ([64143](https://github.com/WordPress/gutenberg/pull/64143)) +- Don't trigger template ID resolution for multi-selected posts. ([64254](https://github.com/WordPress/gutenberg/pull/64254)) +- Long slugs breaking summary panel UI. ([64053](https://github.com/WordPress/gutenberg/pull/64053)) + +#### Zoom Out +- Keep top-level block selection if entering zoom out mode. ([64178](https://github.com/WordPress/gutenberg/pull/64178)) +- Use the block editor for insertion point data. ([63934](https://github.com/WordPress/gutenberg/pull/63934)) + +#### Block Library +- Fix a typo in use-image-sizes.js. ([64100](https://github.com/WordPress/gutenberg/pull/64100)) +- Template Part: Fix capability checks for inner blocks. ([64159](https://github.com/WordPress/gutenberg/pull/64159)) +- Update useTaxonomies hook to check for taxonomies for passed post type. ([64145](https://github.com/WordPress/gutenberg/pull/64145)) + +#### Design Tools +- Quote: Prevent block theme styles overriding global border and padding. ([64045](https://github.com/WordPress/gutenberg/pull/64045)) +- Spacing controls: Using CustomSelectControlV2 for >= 8 spacing sizes. ([64284](https://github.com/WordPress/gutenberg/pull/64284)) + +#### Post Editor +- Avoid errors for post types without a 'menu_icon'. ([64015](https://github.com/WordPress/gutenberg/pull/64015)) +- Post: Add a max length to the post password protected field. ([64156](https://github.com/WordPress/gutenberg/pull/64156)) + +#### Grid layout +- Fix grid resizer drag over embed. ([64098](https://github.com/WordPress/gutenberg/pull/64098)) +- Move resizer popover slot to fix display on mobile. ([63920](https://github.com/WordPress/gutenberg/pull/63920)) + +#### Block Editor +- Fix unexpected drag & rrop row/gallery creation logic. ([64241](https://github.com/WordPress/gutenberg/pull/64241)) + +#### Icons +- Remove hardcoded color from sidesAxial and sidesBottom icons. ([64174](https://github.com/WordPress/gutenberg/pull/64174)) + +#### Document Settings +- Display empty option when post author is missing. ([64165](https://github.com/WordPress/gutenberg/pull/64165)) + +#### Patterns +- Enable cross-browser support for pattern uploading. ([64123](https://github.com/WordPress/gutenberg/pull/64123)) + +#### Commands +- Fix 'Preferences' and 'Shortcuts' commands in StrictMode. ([64019](https://github.com/WordPress/gutenberg/pull/64019)) + +#### Meta Boxes +- Prevent popover from being hidden by metaboxes. ([63939](https://github.com/WordPress/gutenberg/pull/63939)) + +#### Page Content Focus +- TemplateContentPanel: Don't show content blocks that are in a Query Loop. ([63732](https://github.com/WordPress/gutenberg/pull/63732)) + +#### Font Library +- Fix item font family item height in the sidebar. ([63125](https://github.com/WordPress/gutenberg/pull/63125)) + +#### Block API +- Block categories - ensure that categories are unique by slug. ([62954](https://github.com/WordPress/gutenberg/pull/62954)) + + +### Accessibility + +- Restore focus style in dataviews grid view. ([64298](https://github.com/WordPress/gutenberg/pull/64298)) +- A11y text for site editor. ([62648](https://github.com/WordPress/gutenberg/pull/62648)) +- Accessibility issue of device preview options. ([63958](https://github.com/WordPress/gutenberg/pull/63958)) + +#### Components +- Improve the aria-disabled focus style of the Button. ([62480](https://github.com/WordPress/gutenberg/pull/62480)) +- Restore `describedBy` functionality on CustomSelectControl. ([63957](https://github.com/WordPress/gutenberg/pull/63957)) + +#### Block Library +- Fix unlabeled Spacer block controls. ([63806](https://github.com/WordPress/gutenberg/pull/63806)) +- Move Posts Per Page, Offset, and Pages controls from the block toolbar into Inspector Controls. ([58207](https://github.com/WordPress/gutenberg/pull/58207)) + +#### Font Library +- Remove notice context and add message when fonts are updated. ([64030](https://github.com/WordPress/gutenberg/pull/64030)) + + +### Performance + +- Add User Timings for the Interactivity API. ([60522](https://github.com/WordPress/gutenberg/pull/60522)) + +#### Data Views +- Optimize the patterns dataviews by extracting the fields definition. ([63927](https://github.com/WordPress/gutenberg/pull/63927)) + +#### Layout +- Avoid iterating auto grid inner blocks unless mode specifically changed. ([64194](https://github.com/WordPress/gutenberg/pull/64194)) + +#### Block bindings +- Move logic to merge `usesContext` outside the reducer. ([63941](https://github.com/WordPress/gutenberg/pull/63941)) + + +### Experiments + +- Adds experimental blocks flag. ([64121](https://github.com/WordPress/gutenberg/pull/64121)) + +#### DataForm +- Support multiple layouts and introduce the panel layout. ([64299](https://github.com/WordPress/gutenberg/pull/64299)) + +#### DataViews Extensibility +- Add a hook to allow third-party scripts to register/unregister post type actions. ([64138](https://github.com/WordPress/gutenberg/pull/64138)) + +#### Grid Interactivity +- Fix block mover layout and styles. ([64021](https://github.com/WordPress/gutenberg/pull/64021)) + +#### Block bindings +- UI for connecting bindings. ([62880](https://github.com/WordPress/gutenberg/pull/62880)) + + +### Documentation + +- .wp-env.json schema: Fix schema and add unit tests. ([63281](https://github.com/WordPress/gutenberg/pull/63281)) +- Add WP Studio to list of tools in documentation. ([64327](https://github.com/WordPress/gutenberg/pull/64327)) +- Add documentation for some dynamically generated selectors in the core-data store. ([64269](https://github.com/WordPress/gutenberg/pull/64269)) +- Block Editor: Update 'getBlocksByName' JSDoc. ([63919](https://github.com/WordPress/gutenberg/pull/63919)) +- Components: Add missing `__nextHasNoMarginBottom` documentation. ([64313](https://github.com/WordPress/gutenberg/pull/64313)) +- Corrected @deprecated doc Order in Inline Documentation. ([64013](https://github.com/WordPress/gutenberg/pull/64013)) +- Add documentation for `render_block` and `register_block_type_args` to Block Filters. ([64118](https://github.com/WordPress/gutenberg/pull/64118)) +- Fix interactivity API documentation link. ([64060](https://github.com/WordPress/gutenberg/pull/64060)) +- Fix non working link to an interactivity API example block. ([64061](https://github.com/WordPress/gutenberg/pull/64061)) +- Fix WampServer links. ([64062](https://github.com/WordPress/gutenberg/pull/64062)) +- FormToggle, ToggleControl: Fix docgen in Storybook. ([64065](https://github.com/WordPress/gutenberg/pull/64065)) +- Provide a better example for the PluginSidebar slotfill. ([64206](https://github.com/WordPress/gutenberg/pull/64206)) +- Update data-core.md to use correct headings. ([64309](https://github.com/WordPress/gutenberg/pull/64309)) + + +### Code Quality + +- Add margin-bottom lint rules ([64212](https://github.com/WordPress/gutenberg/pull/64212)),([64213](https://github.com/WordPress/gutenberg/pull/64213)) and ([63960](https://github.com/WordPress/gutenberg/pull/63960)) +- Add new useEntityRecordsWithPermissions hook. ([63857](https://github.com/WordPress/gutenberg/pull/63857)) +- Fix deprecated sass usage. ([63990](https://github.com/WordPress/gutenberg/pull/63990)) +- Remove an unnecessary wrapper component. ([63989](https://github.com/WordPress/gutenberg/pull/63989)) +- Theme JSON: Update core theme json resolver class use to Gutenberg version. ([63981](https://github.com/WordPress/gutenberg/pull/63981)) +- Zoom out: Get store action outside the loop. ([63936](https://github.com/WordPress/gutenberg/pull/63936)) +- Remove Speak from device menu selection. ([64115](https://github.com/WordPress/gutenberg/pull/64115)) + +#### Block Editor +- BlockDraggable: Remove invalid aria-hidden attribute from button. ([64228](https://github.com/WordPress/gutenberg/pull/64228)) +- FontFamilyControl: Deprecate bottom margin. ([64280](https://github.com/WordPress/gutenberg/pull/64280)) +- Remove unnecessary/incorrect `unlock` call in `setEditorMode` action. ([64073](https://github.com/WordPress/gutenberg/pull/64073)) + +#### Data Views +- Formalize text field type definition. ([64168](https://github.com/WordPress/gutenberg/pull/64168)) +- Use items with permissions and avoid hooks to register actions. ([63923](https://github.com/WordPress/gutenberg/pull/63923)) + +#### DataForm +- Centralize edit logic in field type definitions. ([64171](https://github.com/WordPress/gutenberg/pull/64171)) +- Move validation logic to the field type definition. ([64164](https://github.com/WordPress/gutenberg/pull/64164)) + +#### Global Styles +- Background image: Remove toolspanel placeholder component. ([64242](https://github.com/WordPress/gutenberg/pull/64242)) +- Consolidate theme.json ref and URI resolution. ([64182](https://github.com/WordPress/gutenberg/pull/64182)) + +#### Plugin +- Remove compat layers for WP 6.4 and 6.5. ([64096](https://github.com/WordPress/gutenberg/pull/64096)) +- Remove leftover 'WP_Rest_Customizer_Nonces' controller. ([64221](https://github.com/WordPress/gutenberg/pull/64221)) + +#### Site Editor +- Use `structuredClone` for deep cloning. ([64203](https://github.com/WordPress/gutenberg/pull/64203)) + +#### Block Library +- Add stylelint rule to prevent usage of flex-direction reverse values. ([63081](https://github.com/WordPress/gutenberg/pull/63081)) +- Image Block Lightbox: Fix warning error when resizing. ([63995](https://github.com/WordPress/gutenberg/pull/63995)) + +#### Icons +- Fix invalid prop for `homeButton` icon. ([64191](https://github.com/WordPress/gutenberg/pull/64191)) + +#### Post Editor +- Remove resolvers hack for post actions. ([64094](https://github.com/WordPress/gutenberg/pull/64094)) + +#### Components +- Upgrade Ariakit. ([64066](https://github.com/WordPress/gutenberg/pull/64066)) + +#### Page Content Focus +- Fix the 'getBlocksByName' selector call. ([63922](https://github.com/WordPress/gutenberg/pull/63922)) + + +### Tools + +#### Testing +- Components: Cleanup flaky unit test `sleep()` hacks. ([64205](https://github.com/WordPress/gutenberg/pull/64205)) +- Fix flaky DataViews list layout end-to-end tests. ([64244](https://github.com/WordPress/gutenberg/pull/64244)) +- Fix typo in 'Verify Core Backport Changelog' job title. ([64058](https://github.com/WordPress/gutenberg/pull/64058)) +- Improve `Button` matrix in visual regression test. ([64120](https://github.com/WordPress/gutenberg/pull/64120)) +- Improve theme.json test failure messages by pretty printing css for a more accurate diff. ([64077](https://github.com/WordPress/gutenberg/pull/64077)) + + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @Chrico: Block categories - ensure that categories are unique by slug. ([62954](https://github.com/WordPress/gutenberg/pull/62954)) +- @djcowan: Update api-reference.md. ([64325](https://github.com/WordPress/gutenberg/pull/64325)) +- @meteorlxy: CustomSelectControl: Support generic props type. ([63985](https://github.com/WordPress/gutenberg/pull/63985)) +- @Rishit30G: Add WP Studio to list of tools in documentation. ([64327](https://github.com/WordPress/gutenberg/pull/64327)) +- @wzieba: ([64044](https://github.com/WordPress/gutenberg/pull/64044)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @adamsilverstein @afercia @akasunil @Aljullu @amitraj2203 @andrewserong @carolinan @cbravobernal @Chrico @ciampo @creativecoder @DaniGuardiola @DAreRodz @djcowan @ellatrix @jameskoster @jasmussen @jeryj @jorgefilipecosta @jsnajdr @kebbet @kmanijak @Mamaduka @matiasbenedetto @meteorlxy @mikachan @mirka @mtias @ndiego @noisysocks @oandregal @ramonjd @richtabor @Rishit30G @ryanwelcher @SantosGuillamot @scruffian @shail-mehta @simison @stokesman @t-hamano @talldan @tomdevisser @tomjn @tyxla @up1512001 @wzieba @youknowriad + + = 18.9.0 = ## Changelog From 77d294a16e59eaaa643706637e247f6d14fd4a4a Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 7 Aug 2024 18:15:10 +0000 Subject: [PATCH 0303/1908] Update changelog files --- packages/a11y/CHANGELOG.md | 2 ++ packages/a11y/package.json | 2 +- packages/annotations/CHANGELOG.md | 2 ++ packages/annotations/package.json | 2 +- packages/api-fetch/CHANGELOG.md | 2 ++ packages/api-fetch/package.json | 2 +- packages/autop/CHANGELOG.md | 2 ++ packages/autop/package.json | 2 +- packages/babel-plugin-import-jsx-pragma/CHANGELOG.md | 2 ++ packages/babel-plugin-import-jsx-pragma/package.json | 2 +- packages/babel-plugin-makepot/CHANGELOG.md | 2 ++ packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/CHANGELOG.md | 2 ++ packages/babel-preset-default/package.json | 2 +- packages/base-styles/CHANGELOG.md | 2 ++ packages/base-styles/package.json | 2 +- packages/blob/CHANGELOG.md | 2 ++ packages/blob/package.json | 2 +- packages/block-directory/CHANGELOG.md | 2 ++ packages/block-directory/package.json | 2 +- packages/block-editor/CHANGELOG.md | 2 ++ packages/block-editor/package.json | 2 +- packages/block-library/CHANGELOG.md | 2 ++ packages/block-library/package.json | 2 +- packages/block-serialization-default-parser/CHANGELOG.md | 2 ++ packages/block-serialization-default-parser/package.json | 2 +- packages/block-serialization-spec-parser/CHANGELOG.md | 2 ++ packages/block-serialization-spec-parser/package.json | 2 +- packages/blocks/CHANGELOG.md | 2 ++ packages/blocks/package.json | 2 +- packages/browserslist-config/CHANGELOG.md | 2 ++ packages/browserslist-config/package.json | 2 +- packages/commands/CHANGELOG.md | 2 ++ packages/commands/package.json | 2 +- packages/components/CHANGELOG.md | 2 ++ packages/components/package.json | 2 +- packages/compose/CHANGELOG.md | 2 ++ packages/compose/package.json | 2 +- packages/core-commands/CHANGELOG.md | 2 ++ packages/core-commands/package.json | 2 +- packages/core-data/CHANGELOG.md | 2 ++ packages/core-data/package.json | 2 +- packages/create-block-interactive-template/CHANGELOG.md | 2 ++ packages/create-block-interactive-template/package.json | 2 +- packages/create-block-tutorial-template/CHANGELOG.md | 2 ++ packages/create-block-tutorial-template/package.json | 2 +- packages/create-block/CHANGELOG.md | 2 ++ packages/create-block/package.json | 2 +- packages/customize-widgets/CHANGELOG.md | 2 ++ packages/customize-widgets/package.json | 2 +- packages/data-controls/CHANGELOG.md | 2 ++ packages/data-controls/package.json | 2 +- packages/data/CHANGELOG.md | 2 ++ packages/data/package.json | 2 +- packages/dataviews/CHANGELOG.md | 2 ++ packages/dataviews/package.json | 2 +- packages/date/CHANGELOG.md | 2 ++ packages/date/package.json | 2 +- packages/dependency-extraction-webpack-plugin/CHANGELOG.md | 2 ++ packages/dependency-extraction-webpack-plugin/package.json | 2 +- packages/deprecated/CHANGELOG.md | 2 ++ packages/deprecated/package.json | 2 +- packages/docgen/CHANGELOG.md | 2 ++ packages/docgen/package.json | 2 +- packages/dom-ready/CHANGELOG.md | 2 ++ packages/dom-ready/package.json | 2 +- packages/dom/CHANGELOG.md | 2 ++ packages/dom/package.json | 2 +- packages/e2e-test-utils-playwright/CHANGELOG.md | 2 ++ packages/e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/CHANGELOG.md | 2 ++ packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/CHANGELOG.md | 2 ++ packages/e2e-tests/package.json | 2 +- packages/edit-post/CHANGELOG.md | 2 ++ packages/edit-post/package.json | 2 +- packages/edit-site/CHANGELOG.md | 2 ++ packages/edit-site/package.json | 2 +- packages/edit-widgets/CHANGELOG.md | 2 ++ packages/edit-widgets/package.json | 2 +- packages/editor/CHANGELOG.md | 2 ++ packages/editor/package.json | 2 +- packages/element/CHANGELOG.md | 2 ++ packages/element/package.json | 2 +- packages/env/CHANGELOG.md | 2 ++ packages/env/package.json | 2 +- packages/escape-html/CHANGELOG.md | 2 ++ packages/escape-html/package.json | 2 +- packages/eslint-plugin/CHANGELOG.md | 2 ++ packages/eslint-plugin/package.json | 2 +- packages/format-library/CHANGELOG.md | 2 ++ packages/format-library/package.json | 2 +- packages/hooks/CHANGELOG.md | 2 ++ packages/hooks/package.json | 2 +- packages/html-entities/CHANGELOG.md | 2 ++ packages/html-entities/package.json | 2 +- packages/i18n/CHANGELOG.md | 2 ++ packages/i18n/package.json | 2 +- packages/icons/CHANGELOG.md | 2 ++ packages/icons/package.json | 2 +- packages/interactivity-router/CHANGELOG.md | 2 ++ packages/interactivity-router/package.json | 2 +- packages/interactivity/CHANGELOG.md | 2 ++ packages/interactivity/package.json | 2 +- packages/interface/CHANGELOG.md | 2 ++ packages/interface/package.json | 2 +- packages/is-shallow-equal/CHANGELOG.md | 2 ++ packages/is-shallow-equal/package.json | 2 +- packages/jest-console/CHANGELOG.md | 2 ++ packages/jest-console/package.json | 2 +- packages/jest-preset-default/CHANGELOG.md | 2 ++ packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/CHANGELOG.md | 2 ++ packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/CHANGELOG.md | 2 ++ packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/CHANGELOG.md | 2 ++ packages/keycodes/package.json | 2 +- packages/lazy-import/CHANGELOG.md | 2 ++ packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/CHANGELOG.md | 2 ++ packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/CHANGELOG.md | 2 ++ packages/media-utils/package.json | 2 +- packages/notices/CHANGELOG.md | 2 ++ packages/notices/package.json | 2 +- packages/npm-package-json-lint-config/CHANGELOG.md | 2 ++ packages/npm-package-json-lint-config/package.json | 2 +- packages/nux/CHANGELOG.md | 2 ++ packages/nux/package.json | 2 +- packages/patterns/CHANGELOG.md | 2 ++ packages/patterns/package.json | 2 +- packages/plugins/CHANGELOG.md | 2 ++ packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/CHANGELOG.md | 2 ++ packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/CHANGELOG.md | 2 ++ packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/CHANGELOG.md | 2 ++ packages/preferences-persistence/package.json | 2 +- packages/preferences/CHANGELOG.md | 2 ++ packages/preferences/package.json | 2 +- packages/prettier-config/CHANGELOG.md | 2 ++ packages/prettier-config/package.json | 2 +- packages/primitives/CHANGELOG.md | 2 ++ packages/primitives/package.json | 2 +- packages/priority-queue/CHANGELOG.md | 2 ++ packages/priority-queue/package.json | 2 +- packages/private-apis/CHANGELOG.md | 2 ++ packages/private-apis/package.json | 2 +- packages/project-management-automation/CHANGELOG.md | 2 ++ packages/project-management-automation/package.json | 2 +- packages/react-i18n/CHANGELOG.md | 2 ++ packages/react-i18n/package.json | 2 +- packages/readable-js-assets-webpack-plugin/CHANGELOG.md | 2 ++ packages/readable-js-assets-webpack-plugin/package.json | 2 +- packages/redux-routine/CHANGELOG.md | 2 ++ packages/redux-routine/package.json | 2 +- packages/reusable-blocks/CHANGELOG.md | 2 ++ packages/reusable-blocks/package.json | 2 +- packages/rich-text/CHANGELOG.md | 2 ++ packages/rich-text/package.json | 2 +- packages/router/CHANGELOG.md | 2 ++ packages/router/package.json | 2 +- packages/scripts/CHANGELOG.md | 2 ++ packages/scripts/package.json | 2 +- packages/server-side-render/CHANGELOG.md | 2 ++ packages/server-side-render/package.json | 2 +- packages/shortcode/CHANGELOG.md | 2 ++ packages/shortcode/package.json | 2 +- packages/style-engine/CHANGELOG.md | 2 ++ packages/style-engine/package.json | 2 +- packages/stylelint-config/CHANGELOG.md | 2 ++ packages/stylelint-config/package.json | 2 +- packages/sync/CHANGELOG.md | 2 ++ packages/sync/package.json | 2 +- packages/token-list/CHANGELOG.md | 2 ++ packages/token-list/package.json | 2 +- packages/undo-manager/CHANGELOG.md | 2 ++ packages/undo-manager/package.json | 2 +- packages/url/CHANGELOG.md | 2 ++ packages/url/package.json | 2 +- packages/viewport/CHANGELOG.md | 2 ++ packages/viewport/package.json | 2 +- packages/warning/CHANGELOG.md | 2 ++ packages/warning/package.json | 2 +- packages/widgets/CHANGELOG.md | 2 ++ packages/widgets/package.json | 2 +- packages/wordcount/CHANGELOG.md | 2 ++ packages/wordcount/package.json | 2 +- 190 files changed, 285 insertions(+), 95 deletions(-) diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index 3253a926865bd1..7e7a192fe2cec7 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 3af093baa98c91..139bc42bd01f46 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/CHANGELOG.md b/packages/annotations/CHANGELOG.md index a8a78b900448f3..4fd75757858130 100644 --- a/packages/annotations/CHANGELOG.md +++ b/packages/annotations/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.5.0 (2024-08-07) + ## 3.4.0 (2024-07-24) ## 3.3.0 (2024-07-10) diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 147b032d256498..1d571c8b372985 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.4.0", + "version": "3.5.0-prerelease", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/CHANGELOG.md b/packages/api-fetch/CHANGELOG.md index f55dea9482a288..38185a29d5e723 100644 --- a/packages/api-fetch/CHANGELOG.md +++ b/packages/api-fetch/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.5.0 (2024-08-07) + ## 7.4.0 (2024-07-24) ## 7.3.0 (2024-07-10) diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index ad48bede6c2029..837df14c307778 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.4.0", + "version": "7.5.0-prerelease", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/CHANGELOG.md b/packages/autop/CHANGELOG.md index a039d571429dba..28c66fc53c0218 100644 --- a/packages/autop/CHANGELOG.md +++ b/packages/autop/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/autop/package.json b/packages/autop/package.json index f96a7afc7887fe..dbb5712928574c 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md index f99035b53ad4f2..a8b85caf3939cb 100644 --- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md +++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index 2be402163fdffe..bae71e052d9018 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/CHANGELOG.md b/packages/babel-plugin-makepot/CHANGELOG.md index 4d876ac3629bc8..ad77a8bda2e3cd 100644 --- a/packages/babel-plugin-makepot/CHANGELOG.md +++ b/packages/babel-plugin-makepot/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.5.0 (2024-08-07) + ## 6.4.0 (2024-07-24) ## 6.3.0 (2024-07-10) diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index 3ce5e4ac321f97..f255736856caaf 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.4.0", + "version": "6.5.0-prerelease", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index ed74690aef3a17..39ff7b2098ba71 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.5.0 (2024-08-07) + ## 8.4.0 (2024-07-24) ## 8.3.0 (2024-07-10) diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 10792a258407f4..311b9fd1594fd4 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.4.0", + "version": "8.5.0-prerelease", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/CHANGELOG.md b/packages/base-styles/CHANGELOG.md index 48e715441a86ff..c68e328b68421b 100644 --- a/packages/base-styles/CHANGELOG.md +++ b/packages/base-styles/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index ff59ac8cf960ed..1a0e6ac2c176cf 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md index 9963ce05042c70..56c1ee2a2554b0 100644 --- a/packages/blob/CHANGELOG.md +++ b/packages/blob/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/blob/package.json b/packages/blob/package.json index ca6820770afe08..ae216a1f5aaa01 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/CHANGELOG.md b/packages/block-directory/CHANGELOG.md index 99d27f9b06ca0d..8c25a168e585c8 100644 --- a/packages/block-directory/CHANGELOG.md +++ b/packages/block-directory/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 20afdad09cb53b..9b67833be0ec8e 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index bc7d1b88bc9b0a..09792d9dca5dac 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.0.0 (2024-08-07) + ### Breaking Changes - `URLInput`: Remove deprecated `__nextHasNoMarginBottom` prop and promote to default behavior ([#64282](https://github.com/WordPress/gutenberg/pull/64282)). diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index aadf192f3016ec..81f8613fb4e339 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "13.4.0", + "version": "14.0.0-prerelease", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index 652c89fd3540e2..b14275fdad3988 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.5.0 (2024-08-07) + ### New Feature - Query Loop Block: Moves per page, offset, and pages controls into Inspector Controls. ([#58207](https://github.com/WordPress/gutenberg/pull/58207)) diff --git a/packages/block-library/package.json b/packages/block-library/package.json index c1d27c8691f4fe..83d796ad11b16a 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.4.0", + "version": "9.5.0-prerelease", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/CHANGELOG.md b/packages/block-serialization-default-parser/CHANGELOG.md index e8c14374606de4..97ab311854c9b7 100644 --- a/packages/block-serialization-default-parser/CHANGELOG.md +++ b/packages/block-serialization-default-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index de4f74925baf48..34e57586ea52c5 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/CHANGELOG.md b/packages/block-serialization-spec-parser/CHANGELOG.md index 0b9d0e9922ecc6..15d6292a59b6ed 100644 --- a/packages/block-serialization-spec-parser/CHANGELOG.md +++ b/packages/block-serialization-spec-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 84704630d117f7..88851d4b60d793 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 1f77b933104583..9768d958f0382c 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 13.5.0 (2024-08-07) + ## 13.4.0 (2024-07-24) ## 13.3.0 (2024-07-10) diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 1d10cf69ec8926..f64948af554168 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.4.0", + "version": "13.5.0-prerelease", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/CHANGELOG.md b/packages/browserslist-config/CHANGELOG.md index 538af854cef48f..676c38509b22e5 100644 --- a/packages/browserslist-config/CHANGELOG.md +++ b/packages/browserslist-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.5.0 (2024-08-07) + ## 6.4.0 (2024-07-24) ## 6.3.0 (2024-07-10) diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 2dd117762b9dbd..9c3213cb2ba866 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.4.0", + "version": "6.5.0-prerelease", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/CHANGELOG.md b/packages/commands/CHANGELOG.md index 2a4b22bb9880a2..228f06635ada65 100644 --- a/packages/commands/CHANGELOG.md +++ b/packages/commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.5.0 (2024-08-07) + ## 1.4.0 (2024-07-24) ## 1.3.0 (2024-07-10) diff --git a/packages/commands/package.json b/packages/commands/package.json index 53717ff871d2dc..67ba52b5544e8a 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.4.0", + "version": "1.5.0-prerelease", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 837fe973d1022a..ef0108b09a741d 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 28.5.0 (2024-08-07) + ### Bug Fixes - `ColorPalette`: Remove extra bottom margin when `CircularOptionPicker` is unneeded ([#63961](https://github.com/WordPress/gutenberg/pull/63961)). diff --git a/packages/components/package.json b/packages/components/package.json index 784b03d6574940..e188c05ba2a847 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.4.0", + "version": "28.5.0-prerelease", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index b5dd1d8712215d..6595c9ae336855 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.5.0 (2024-08-07) + ## 7.4.0 (2024-07-24) ## 7.3.0 (2024-07-10) diff --git a/packages/compose/package.json b/packages/compose/package.json index bc295a921bea5f..c5ea618103ca95 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.4.0", + "version": "7.5.0-prerelease", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/CHANGELOG.md b/packages/core-commands/CHANGELOG.md index aab5f1ea832f17..fa46608d63254b 100644 --- a/packages/core-commands/CHANGELOG.md +++ b/packages/core-commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.5.0 (2024-08-07) + ## 1.4.0 (2024-07-24) ## 1.3.0 (2024-07-10) diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index bb9acc05139888..13312adcab650a 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.4.0", + "version": "1.5.0-prerelease", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md index 4712b66b8797b6..e3477da97811fe 100644 --- a/packages/core-data/CHANGELOG.md +++ b/packages/core-data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.5.0 (2024-08-07) + ## 7.4.0 (2024-07-24) ## 7.3.0 (2024-07-10) diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 3f4037f290a2c5..e15f84799aea53 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.4.0", + "version": "7.5.0-prerelease", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/CHANGELOG.md b/packages/create-block-interactive-template/CHANGELOG.md index 9f3b063c6fe9b3..769999da2d4ecc 100644 --- a/packages/create-block-interactive-template/CHANGELOG.md +++ b/packages/create-block-interactive-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.5.0 (2024-08-07) + ## 2.4.0 (2024-07-24) ## 2.3.0 (2024-07-10) diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index 6f679fd47d90ea..33df8821966113 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.4.0", + "version": "2.5.0-prerelease", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/CHANGELOG.md b/packages/create-block-tutorial-template/CHANGELOG.md index a1ee507eb80163..5c5856f174b0eb 100644 --- a/packages/create-block-tutorial-template/CHANGELOG.md +++ b/packages/create-block-tutorial-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index 891fda996099eb..e2647dbd531f0c 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index 3d4cd14732192b..024ef7abc8c69e 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.48.0 (2024-08-07) + ## 4.47.0 (2024-07-24) ## 4.46.0 (2024-07-10) diff --git a/packages/create-block/package.json b/packages/create-block/package.json index adaf06606d2550..203816ddf226fb 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.47.0", + "version": "4.48.0-prerelease", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/CHANGELOG.md b/packages/customize-widgets/CHANGELOG.md index 42bc3b04f4c0e1..1065adf40e15d3 100644 --- a/packages/customize-widgets/CHANGELOG.md +++ b/packages/customize-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index ce53a53ea80dec..76b152a080f388 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/CHANGELOG.md b/packages/data-controls/CHANGELOG.md index e01b3f59bea50b..f0d753d95360ca 100644 --- a/packages/data-controls/CHANGELOG.md +++ b/packages/data-controls/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index d3c670e5f0690a..9e7f2d26089ee2 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index 9789b91dfea0ea..a4686283d050c7 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.5.0 (2024-08-07) + ## 10.4.0 (2024-07-24) ## 10.3.0 (2024-07-10) diff --git a/packages/data/package.json b/packages/data/package.json index a17b3cfd4f4b28..46bd6c4a134c7e 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.4.0", + "version": "10.5.0-prerelease", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 8dd3ade7fd7749..239a69651a1f27 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.1.0 (2024-08-07) + ## Internal - Upgraded `@ariakit/react` (v0.4.7) ([#64066](https://github.com/WordPress/gutenberg/pull/64066)). diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index 53cfa97c275c60..b410f8b9b959e3 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.0.0", + "version": "4.1.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md index b5177ac190c5d3..bcd7d0d80a6909 100644 --- a/packages/date/CHANGELOG.md +++ b/packages/date/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/date/package.json b/packages/date/package.json index d7ffeaa8417596..a2f45532505fe4 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index 53e1853d8857b2..2fcbf4b78c22c9 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.5.0 (2024-08-07) + ## 6.4.0 (2024-07-24) ## 6.3.0 (2024-07-10) diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index 6146a8f562d05e..558173f7fe21ab 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.4.0", + "version": "6.5.0-prerelease", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/CHANGELOG.md b/packages/deprecated/CHANGELOG.md index 89e574358a5225..6b5c50cb2b55a6 100644 --- a/packages/deprecated/CHANGELOG.md +++ b/packages/deprecated/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 515103487ca3cd..681beb2e25d7d5 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/CHANGELOG.md b/packages/docgen/CHANGELOG.md index 5279dccdb4c51f..8bde3b25cbbd26 100644 --- a/packages/docgen/CHANGELOG.md +++ b/packages/docgen/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.5.0 (2024-08-07) + ## 2.4.0 (2024-07-24) ## 2.3.0 (2024-07-10) diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 86ce19f84b4f9b..cab58965b69936 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.4.0", + "version": "2.5.0-prerelease", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/CHANGELOG.md b/packages/dom-ready/CHANGELOG.md index 3e63c4440ae6fd..652b3d9a738ea5 100644 --- a/packages/dom-ready/CHANGELOG.md +++ b/packages/dom-ready/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 76e2f12961a0e6..f80bf5f8d35fba 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/CHANGELOG.md b/packages/dom/CHANGELOG.md index cf5f09613f3154..a337ee7214611f 100644 --- a/packages/dom/CHANGELOG.md +++ b/packages/dom/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/dom/package.json b/packages/dom/package.json index 4b1f1ba634f9b5..f1aec564927a25 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/CHANGELOG.md b/packages/e2e-test-utils-playwright/CHANGELOG.md index e19452d1e49264..fa56cd3b2aaaee 100644 --- a/packages/e2e-test-utils-playwright/CHANGELOG.md +++ b/packages/e2e-test-utils-playwright/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.5.0 (2024-08-07) + ## 1.4.0 (2024-07-24) ## 1.3.0 (2024-07-10) diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index d57f374cc979fa..25f231a39c635f 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.4.0", + "version": "1.5.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index fec97ba250f536..fa27436da8f42a 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 11.5.0 (2024-08-07) + ## 11.4.0 (2024-07-24) ## 11.3.0 (2024-07-10) diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index dee83cb79081c0..c594c0db136340 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.4.0", + "version": "11.5.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md index e89296d6606e15..2a9317924a8fec 100644 --- a/packages/e2e-tests/CHANGELOG.md +++ b/packages/e2e-tests/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.5.0 (2024-08-07) + ## 8.4.0 (2024-07-24) ## 8.3.0 (2024-07-10) diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index b2ccca8dc14f2e..8e89e852e2b962 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.4.0", + "version": "8.5.0-prerelease", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index 9542749c9d8463..6febaa5df4542c 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.5.0 (2024-08-07) + ## 8.4.0 (2024-07-24) ## 8.3.0 (2024-07-10) diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index ee02f268ac1921..c080209b37e96d 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.4.0", + "version": "8.5.0-prerelease", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/CHANGELOG.md b/packages/edit-site/CHANGELOG.md index 1990f26bce3ffb..062bf8c46ff08c 100644 --- a/packages/edit-site/CHANGELOG.md +++ b/packages/edit-site/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.5.0 (2024-08-07) + ## 6.4.0 (2024-07-24) ## 6.3.0 (2024-07-10) diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index f034b853c2cae1..fc3a9e355f2b8a 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.4.0", + "version": "6.5.0-prerelease", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/CHANGELOG.md b/packages/edit-widgets/CHANGELOG.md index edb26e6c38c1a8..bbe958c401ce6e 100644 --- a/packages/edit-widgets/CHANGELOG.md +++ b/packages/edit-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.5.0 (2024-08-07) + ## 6.4.0 (2024-07-24) ## 6.3.0 (2024-07-10) diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 793e64f5d57caa..8b43279e8dc0e6 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.4.0", + "version": "6.5.0-prerelease", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index a5fce0d1f736ad..8e7cbed3a98144 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.5.0 (2024-08-07) + ## 14.4.0 (2024-07-24) ### Deprecations diff --git a/packages/editor/package.json b/packages/editor/package.json index 6c6a22cbbcd8c7..e0d0fd93c9bc83 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.4.0", + "version": "14.5.0-prerelease", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/CHANGELOG.md b/packages/element/CHANGELOG.md index f81c95ef6eb24e..4dbbe1938a0187 100644 --- a/packages/element/CHANGELOG.md +++ b/packages/element/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.5.0 (2024-08-07) + ## 6.4.0 (2024-07-24) ## 6.3.0 (2024-07-10) diff --git a/packages/element/package.json b/packages/element/package.json index a5a85b145b51ba..fc457a950090d8 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.4.0", + "version": "6.5.0-prerelease", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md index 5e979941fb892d..dadbbb7c89ef9a 100644 --- a/packages/env/CHANGELOG.md +++ b/packages/env/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.5.0 (2024-08-07) + ## 10.4.0 (2024-07-24) ## 10.3.0 (2024-07-10) diff --git a/packages/env/package.json b/packages/env/package.json index 354a41163c0ac2..32e332040e4eaf 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.4.0", + "version": "10.5.0-prerelease", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/CHANGELOG.md b/packages/escape-html/CHANGELOG.md index 02d7e2bf83a567..8768abbb682494 100644 --- a/packages/escape-html/CHANGELOG.md +++ b/packages/escape-html/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.5.0 (2024-08-07) + ## 3.4.0 (2024-07-24) ## 3.3.0 (2024-07-10) diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 0890a53b4e1743..d1949cb32b974c 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.4.0", + "version": "3.5.0-prerelease", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index fb9a16a011a9cf..92499f5b32eb3a 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 20.2.0 (2024-08-07) + ## 20.1.0 (2024-07-24) ## 20.0.0 (2024-07-10) diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 77c9e2457b490e..0ebe3272154055 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "20.1.0", + "version": "20.2.0-prerelease", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/CHANGELOG.md b/packages/format-library/CHANGELOG.md index 6d255d2b0b4b10..7914005a0c2b1d 100644 --- a/packages/format-library/CHANGELOG.md +++ b/packages/format-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/format-library/package.json b/packages/format-library/package.json index 5c5f80d1739b68..eb23caf92ef872 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/CHANGELOG.md b/packages/hooks/CHANGELOG.md index cd6b23c1609bb3..779306149f2552 100644 --- a/packages/hooks/CHANGELOG.md +++ b/packages/hooks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 2bdf8ca3e5c933..2c55175073f2f0 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/CHANGELOG.md b/packages/html-entities/CHANGELOG.md index 0e586385970454..9dafc94de9e18d 100644 --- a/packages/html-entities/CHANGELOG.md +++ b/packages/html-entities/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 313438e3b994c6..4416d167e0cda6 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index abe87d0edd1280..8e31279a21a4da 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 96647dd7f64a40..b67d18ec695bba 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index 4f279b5593e875..630bbd7cb129ae 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.5.0 (2024-08-07) + ### New Features - Add new `send` icon. diff --git a/packages/icons/package.json b/packages/icons/package.json index 658e02ba74fa71..0d420d9ae93e62 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.4.0", + "version": "10.5.0-prerelease", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/CHANGELOG.md b/packages/interactivity-router/CHANGELOG.md index 97cd7f368bcbad..38e79f9d503b6f 100644 --- a/packages/interactivity-router/CHANGELOG.md +++ b/packages/interactivity-router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.5.0 (2024-08-07) + ## 2.4.0 (2024-07-24) ## 2.3.0 (2024-07-10) diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 212162a89ec6ed..1435f19e84ed44 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.4.0", + "version": "2.5.0-prerelease", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index d592a5258c3c83..6eb664984e1e53 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.5.0 (2024-08-07) + ## 6.4.0 (2024-07-24) ## 6.3.0 (2024-07-10) diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 332254684bdc9b..89b98463e08190 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.4.0", + "version": "6.5.0-prerelease", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index 18e36b68947b45..e60175047ec0e3 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.5.0 (2024-08-07) + ## 6.4.0 (2024-07-24) ## 6.3.0 (2024-07-10) diff --git a/packages/interface/package.json b/packages/interface/package.json index cbc3a4229bd526..75b5b92621ac7b 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "6.4.0", + "version": "6.5.0-prerelease", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/CHANGELOG.md b/packages/is-shallow-equal/CHANGELOG.md index 92e7f633cd150a..7757af92a8472e 100644 --- a/packages/is-shallow-equal/CHANGELOG.md +++ b/packages/is-shallow-equal/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index a92e70d21b6c7a..89d9ecc1155f32 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/CHANGELOG.md b/packages/jest-console/CHANGELOG.md index 3c85c40d1fe650..f72992c321204e 100644 --- a/packages/jest-console/CHANGELOG.md +++ b/packages/jest-console/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.5.0 (2024-08-07) + ## 8.4.0 (2024-07-24) ## 8.3.0 (2024-07-10) diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 9775d4c7b7977d..9744a87680c0f2 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.4.0", + "version": "8.5.0-prerelease", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md index 726b351b71b529..7dc5a2ec0e8963 100644 --- a/packages/jest-preset-default/CHANGELOG.md +++ b/packages/jest-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 12.5.0 (2024-08-07) + ## 12.4.0 (2024-07-24) ## 12.3.0 (2024-07-10) diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index db5cf4cf8d7dd2..59c8c7e984dce5 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.4.0", + "version": "12.5.0-prerelease", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/CHANGELOG.md b/packages/jest-puppeteer-axe/CHANGELOG.md index 14f2cf2e7ef525..710528ab53a242 100644 --- a/packages/jest-puppeteer-axe/CHANGELOG.md +++ b/packages/jest-puppeteer-axe/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.5.0 (2024-08-07) + ## 7.4.0 (2024-07-24) ## 7.3.0 (2024-07-10) diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 2a16312d79764e..10c891a939376f 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.4.0", + "version": "7.5.0-prerelease", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/CHANGELOG.md b/packages/keyboard-shortcuts/CHANGELOG.md index 180e1af1be4a66..deee5625cd6879 100644 --- a/packages/keyboard-shortcuts/CHANGELOG.md +++ b/packages/keyboard-shortcuts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index d32cf232e17e5c..4d32c65cf55afd 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/CHANGELOG.md b/packages/keycodes/CHANGELOG.md index 70d9c6065f1881..1503d7554393f3 100644 --- a/packages/keycodes/CHANGELOG.md +++ b/packages/keycodes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 56a2c8dce89c97..1640c7e831bb41 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/CHANGELOG.md b/packages/lazy-import/CHANGELOG.md index 0db5de62639324..e6305967c12a7d 100644 --- a/packages/lazy-import/CHANGELOG.md +++ b/packages/lazy-import/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.5.0 (2024-08-07) + ## 2.4.0 (2024-07-24) ## 2.3.0 (2024-07-10) diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index 6f0c5501387d47..9e9f77225c1794 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.4.0", + "version": "2.5.0-prerelease", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/CHANGELOG.md b/packages/list-reusable-blocks/CHANGELOG.md index c64693083af1f5..bd1ee4cd44b12c 100644 --- a/packages/list-reusable-blocks/CHANGELOG.md +++ b/packages/list-reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 277ec1e991984c..50a26cb0671713 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/CHANGELOG.md b/packages/media-utils/CHANGELOG.md index 571fe227513ca6..574d3b66273399 100644 --- a/packages/media-utils/CHANGELOG.md +++ b/packages/media-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 59adc20770a5f8..5facc75c780b67 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/CHANGELOG.md b/packages/notices/CHANGELOG.md index 8bd550869b8b34..8e22055742e287 100644 --- a/packages/notices/CHANGELOG.md +++ b/packages/notices/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/notices/package.json b/packages/notices/package.json index de6ba2f106e723..6b952f566075de 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/CHANGELOG.md b/packages/npm-package-json-lint-config/CHANGELOG.md index 661d935ebab8b4..9b83e804acdc1c 100644 --- a/packages/npm-package-json-lint-config/CHANGELOG.md +++ b/packages/npm-package-json-lint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index 4c42423e14cd61..3ab2d07913ee37 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/CHANGELOG.md b/packages/nux/CHANGELOG.md index 9c83baed0c0a80..eb7ec981961649 100644 --- a/packages/nux/CHANGELOG.md +++ b/packages/nux/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.5.0 (2024-08-07) + ## 9.4.0 (2024-07-24) ## 9.3.0 (2024-07-10) diff --git a/packages/nux/package.json b/packages/nux/package.json index c8bb71d1ce480f..4fb355fe51f341 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.4.0", + "version": "9.5.0-prerelease", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/CHANGELOG.md b/packages/patterns/CHANGELOG.md index 499b988bc66c98..0d11c1e9545b14 100644 --- a/packages/patterns/CHANGELOG.md +++ b/packages/patterns/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.5.0 (2024-08-07) + ## 2.4.0 (2024-07-24) ## 2.3.0 (2024-07-10) diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 9f1a9c09fb405f..c544287e6f7404 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.4.0", + "version": "2.5.0-prerelease", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/CHANGELOG.md b/packages/plugins/CHANGELOG.md index 4135ab1b3a4b42..368cb58e22659e 100644 --- a/packages/plugins/CHANGELOG.md +++ b/packages/plugins/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.5.0 (2024-08-07) + ## 7.4.0 (2024-07-24) ## 7.3.0 (2024-07-10) diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 7f2262c2487ed2..530a758d7bc276 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.4.0", + "version": "7.5.0-prerelease", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/CHANGELOG.md b/packages/postcss-plugins-preset/CHANGELOG.md index 7a362b300fe71e..2534e127a438e7 100644 --- a/packages/postcss-plugins-preset/CHANGELOG.md +++ b/packages/postcss-plugins-preset/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 77e5e62a404631..388855af3b5fdd 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/CHANGELOG.md b/packages/postcss-themes/CHANGELOG.md index 5f200977e62ff4..5fefbbff21cccd 100644 --- a/packages/postcss-themes/CHANGELOG.md +++ b/packages/postcss-themes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.5.0 (2024-08-07) + ## 6.4.0 (2024-07-24) ## 6.3.0 (2024-07-10) diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index 51f78e5dc7d40d..e56ed2c24d1b5d 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.4.0", + "version": "6.5.0-prerelease", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/CHANGELOG.md b/packages/preferences-persistence/CHANGELOG.md index b5bdc72282f80c..4a29b7cabc2535 100644 --- a/packages/preferences-persistence/CHANGELOG.md +++ b/packages/preferences-persistence/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.5.0 (2024-08-07) + ## 2.4.0 (2024-07-24) ## 2.3.0 (2024-07-10) diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index 81ff8d0a5452ef..de0a7dbc87164f 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.4.0", + "version": "2.5.0-prerelease", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/CHANGELOG.md b/packages/preferences/CHANGELOG.md index 2ebbd4ad386a9e..4ab14164deede9 100644 --- a/packages/preferences/CHANGELOG.md +++ b/packages/preferences/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/preferences/package.json b/packages/preferences/package.json index 47c54e52512c28..2a53487932c401 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/CHANGELOG.md b/packages/prettier-config/CHANGELOG.md index c3e02c3891f83a..8556f8d42768dd 100644 --- a/packages/prettier-config/CHANGELOG.md +++ b/packages/prettier-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 33cd14c889db6c..0a6486068067fd 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/CHANGELOG.md b/packages/primitives/CHANGELOG.md index abba3f5140d3a6..d698040432ecb8 100644 --- a/packages/primitives/CHANGELOG.md +++ b/packages/primitives/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 31bf36813d6b0e..f3298b3dfe7ebe 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/CHANGELOG.md b/packages/priority-queue/CHANGELOG.md index 063fe05d667f08..06fcc2be6ab09e 100644 --- a/packages/priority-queue/CHANGELOG.md +++ b/packages/priority-queue/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.5.0 (2024-08-07) + ## 3.4.0 (2024-07-24) ## 3.3.0 (2024-07-10) diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 27eb90e14f5c44..bd7069f6718141 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.4.0", + "version": "3.5.0-prerelease", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/CHANGELOG.md b/packages/private-apis/CHANGELOG.md index 169c9d8c4a588e..e83cd2047a5c2a 100644 --- a/packages/private-apis/CHANGELOG.md +++ b/packages/private-apis/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.5.0 (2024-08-07) + ## 1.4.0 (2024-07-24) ## 1.3.0 (2024-07-10) diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index 4034d63c0a169b..a46a499716fb10 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.4.0", + "version": "1.5.0-prerelease", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/CHANGELOG.md b/packages/project-management-automation/CHANGELOG.md index ca47a4ac381d9f..cd83382d0e2485 100644 --- a/packages/project-management-automation/CHANGELOG.md +++ b/packages/project-management-automation/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.5.0 (2024-08-07) + ## 2.4.0 (2024-07-24) ## 2.3.0 (2024-07-10) diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 13aa49f5da6290..5efd0e01ef43c1 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.4.0", + "version": "2.5.0-prerelease", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/CHANGELOG.md b/packages/react-i18n/CHANGELOG.md index 4907b55755640e..a44fe01322670e 100644 --- a/packages/react-i18n/CHANGELOG.md +++ b/packages/react-i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index d3cb47c584dbb6..89ca7018bf7da8 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md index 771067204bc156..c3d143fde84693 100644 --- a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md +++ b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.5.0 (2024-08-07) + ## 3.4.0 (2024-07-24) ## 3.3.0 (2024-07-10) diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index fa04a7266d5d00..596a8a82d4f419 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.4.0", + "version": "3.5.0-prerelease", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/CHANGELOG.md b/packages/redux-routine/CHANGELOG.md index 28f2162b322651..989af85ea8f81b 100644 --- a/packages/redux-routine/CHANGELOG.md +++ b/packages/redux-routine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 2d43d16413efaf..a329e0091f7709 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/CHANGELOG.md b/packages/reusable-blocks/CHANGELOG.md index 37ae70f2cba977..7ad0be3307056a 100644 --- a/packages/reusable-blocks/CHANGELOG.md +++ b/packages/reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 54985450b5dfb9..08d8a71c2aff26 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/CHANGELOG.md b/packages/rich-text/CHANGELOG.md index 25d2fe65213a50..a83fc8a8b0d751 100644 --- a/packages/rich-text/CHANGELOG.md +++ b/packages/rich-text/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.5.0 (2024-08-07) + ## 7.4.0 (2024-07-24) ## 7.3.0 (2024-07-10) diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 5d62e30f06d1bc..66ddc465e65ac6 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.4.0", + "version": "7.5.0-prerelease", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index aab5f1ea832f17..fa46608d63254b 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.5.0 (2024-08-07) + ## 1.4.0 (2024-07-24) ## 1.3.0 (2024-07-10) diff --git a/packages/router/package.json b/packages/router/package.json index 3173f0d51bbf7b..6f9c44faff6e3f 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.4.0", + "version": "1.5.0-prerelease", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 2cb0cbbe408d65..3a878e23689092 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 28.5.0 (2024-08-07) + ## 28.4.0 (2024-07-24) ### New Features diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 1ab69ea501be20..c0b68e73e36827 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "28.4.0", + "version": "28.5.0-prerelease", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/CHANGELOG.md b/packages/server-side-render/CHANGELOG.md index a07a67682026e2..6d0fed23681aa3 100644 --- a/packages/server-side-render/CHANGELOG.md +++ b/packages/server-side-render/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.5.0 (2024-08-07) + ## 5.4.0 (2024-07-24) ## 5.3.0 (2024-07-10) diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index 1eaa215f097a70..c28611fce5b7f3 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.4.0", + "version": "5.5.0-prerelease", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/CHANGELOG.md b/packages/shortcode/CHANGELOG.md index ed64a536ee8df2..ee2f8b49fcc24e 100644 --- a/packages/shortcode/CHANGELOG.md +++ b/packages/shortcode/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index b0db529cd58ec7..89ed91aa947ecb 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md index aa2a6e8a62a7b9..d393e427a63071 100644 --- a/packages/style-engine/CHANGELOG.md +++ b/packages/style-engine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.5.0 (2024-08-07) + ## 2.4.0 (2024-07-24) ## 2.3.0 (2024-07-10) diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 54a340e50c2290..84a76d7d0180f0 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.4.0", + "version": "2.5.0-prerelease", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/CHANGELOG.md b/packages/stylelint-config/CHANGELOG.md index d2a5cba72d5ba3..f258fa93af7a26 100644 --- a/packages/stylelint-config/CHANGELOG.md +++ b/packages/stylelint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 22.5.0 (2024-08-07) + ## 22.4.0 (2024-07-24) ## 22.3.0 (2024-07-10) diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 5942073e683ce8..084b7159788c25 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "22.4.0", + "version": "22.5.0-prerelease", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/CHANGELOG.md b/packages/sync/CHANGELOG.md index dc4639d721cbd1..5c703cc231dc88 100644 --- a/packages/sync/CHANGELOG.md +++ b/packages/sync/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.5.0 (2024-08-07) + ## 1.4.0 (2024-07-24) ## 1.3.0 (2024-07-10) diff --git a/packages/sync/package.json b/packages/sync/package.json index e4ecb8f39a5157..bc054732462496 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.4.0", + "version": "1.5.0-prerelease", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/CHANGELOG.md b/packages/token-list/CHANGELOG.md index 7f70da2e813ee6..5ccb92af128ca0 100644 --- a/packages/token-list/CHANGELOG.md +++ b/packages/token-list/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.5.0 (2024-08-07) + ## 3.4.0 (2024-07-24) ## 3.3.0 (2024-07-10) diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 1192c6f7103371..b99cb89e3695ab 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.4.0", + "version": "3.5.0-prerelease", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/CHANGELOG.md b/packages/undo-manager/CHANGELOG.md index 2a8795039da055..665d78dd646af3 100644 --- a/packages/undo-manager/CHANGELOG.md +++ b/packages/undo-manager/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.5.0 (2024-08-07) + ## 1.4.0 (2024-07-24) ## 1.3.0 (2024-07-10) diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 2f945dbc53b653..96961844152818 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.4.0", + "version": "1.5.0-prerelease", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/CHANGELOG.md b/packages/url/CHANGELOG.md index 46aeb33cd56d3a..9715c9512b34c1 100644 --- a/packages/url/CHANGELOG.md +++ b/packages/url/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/url/package.json b/packages/url/package.json index c60ca2c661b9fa..57e7fdacccd271 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/CHANGELOG.md b/packages/viewport/CHANGELOG.md index 5add422c56ebc2..1e9c4f3d91590d 100644 --- a/packages/viewport/CHANGELOG.md +++ b/packages/viewport/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.5.0 (2024-08-07) + ## 6.4.0 (2024-07-24) ## 6.3.0 (2024-07-10) diff --git a/packages/viewport/package.json b/packages/viewport/package.json index dbea04216570d9..65c9df5b7ecf6c 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.4.0", + "version": "6.5.0-prerelease", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/CHANGELOG.md b/packages/warning/CHANGELOG.md index 9d0fea35fd7d82..6b73c6f10df6c0 100644 --- a/packages/warning/CHANGELOG.md +++ b/packages/warning/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.5.0 (2024-08-07) + ## 3.4.0 (2024-07-24) ## 3.3.0 (2024-07-10) diff --git a/packages/warning/package.json b/packages/warning/package.json index 980a1afcfb61c4..dd9e01fb6cf95d 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.4.0", + "version": "3.5.0-prerelease", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/CHANGELOG.md b/packages/widgets/CHANGELOG.md index 7ae2d9c4f32d22..a13d277ace3a21 100644 --- a/packages/widgets/CHANGELOG.md +++ b/packages/widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/widgets/package.json b/packages/widgets/package.json index d302e63ee34cfb..b7f87a89d57c3e 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/CHANGELOG.md b/packages/wordcount/CHANGELOG.md index 58632ead7d0819..e3865266e4c2d4 100644 --- a/packages/wordcount/CHANGELOG.md +++ b/packages/wordcount/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-08-07) + ## 4.4.0 (2024-07-24) ## 4.3.0 (2024-07-10) diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index e6579c01f2c5f9..b507e5ee3e3c84 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 4b25473b743ab225dbe59ce10341b8397a06a577 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 7 Aug 2024 18:16:55 +0000 Subject: [PATCH 0304/1908] chore(release): publish - @wordpress/a11y@4.5.0 - @wordpress/annotations@3.5.0 - @wordpress/api-fetch@7.5.0 - @wordpress/autop@4.5.0 - @wordpress/babel-plugin-import-jsx-pragma@5.5.0 - @wordpress/babel-plugin-makepot@6.5.0 - @wordpress/babel-preset-default@8.5.0 - @wordpress/base-styles@5.5.0 - @wordpress/blob@4.5.0 - @wordpress/block-directory@5.5.0 - @wordpress/block-editor@14.0.0 - @wordpress/block-library@9.5.0 - @wordpress/block-serialization-default-parser@5.5.0 - @wordpress/block-serialization-spec-parser@5.5.0 - @wordpress/blocks@13.5.0 - @wordpress/browserslist-config@6.5.0 - @wordpress/commands@1.5.0 - @wordpress/components@28.5.0 - @wordpress/compose@7.5.0 - @wordpress/core-commands@1.5.0 - @wordpress/core-data@7.5.0 - @wordpress/create-block@4.48.0 - @wordpress/create-block-interactive-template@2.5.0 - @wordpress/create-block-tutorial-template@4.5.0 - @wordpress/customize-widgets@5.5.0 - @wordpress/data@10.5.0 - @wordpress/data-controls@4.5.0 - @wordpress/dataviews@4.1.0 - @wordpress/date@5.5.0 - @wordpress/dependency-extraction-webpack-plugin@6.5.0 - @wordpress/deprecated@4.5.0 - @wordpress/docgen@2.5.0 - @wordpress/dom@4.5.0 - @wordpress/dom-ready@4.5.0 - @wordpress/e2e-test-utils@11.5.0 - @wordpress/e2e-test-utils-playwright@1.5.0 - @wordpress/e2e-tests@8.5.0 - @wordpress/edit-post@8.5.0 - @wordpress/edit-site@6.5.0 - @wordpress/edit-widgets@6.5.0 - @wordpress/editor@14.5.0 - @wordpress/element@6.5.0 - @wordpress/env@10.5.0 - @wordpress/escape-html@3.5.0 - @wordpress/eslint-plugin@20.2.0 - @wordpress/format-library@5.5.0 - @wordpress/hooks@4.5.0 - @wordpress/html-entities@4.5.0 - @wordpress/i18n@5.5.0 - @wordpress/icons@10.5.0 - @wordpress/interactivity@6.5.0 - @wordpress/interactivity-router@2.5.0 - @wordpress/interface@6.5.0 - @wordpress/is-shallow-equal@5.5.0 - @wordpress/jest-console@8.5.0 - @wordpress/jest-preset-default@12.5.0 - @wordpress/jest-puppeteer-axe@7.5.0 - @wordpress/keyboard-shortcuts@5.5.0 - @wordpress/keycodes@4.5.0 - @wordpress/lazy-import@2.5.0 - @wordpress/list-reusable-blocks@5.5.0 - @wordpress/media-utils@5.5.0 - @wordpress/notices@5.5.0 - @wordpress/npm-package-json-lint-config@5.5.0 - @wordpress/nux@9.5.0 - @wordpress/patterns@2.5.0 - @wordpress/plugins@7.5.0 - @wordpress/postcss-plugins-preset@5.5.0 - @wordpress/postcss-themes@6.5.0 - @wordpress/preferences@4.5.0 - @wordpress/preferences-persistence@2.5.0 - @wordpress/prettier-config@4.5.0 - @wordpress/primitives@4.5.0 - @wordpress/priority-queue@3.5.0 - @wordpress/private-apis@1.5.0 - @wordpress/project-management-automation@2.5.0 - @wordpress/react-i18n@4.5.0 - @wordpress/readable-js-assets-webpack-plugin@3.5.0 - @wordpress/redux-routine@5.5.0 - @wordpress/reusable-blocks@5.5.0 - @wordpress/rich-text@7.5.0 - @wordpress/router@1.5.0 - @wordpress/scripts@28.5.0 - @wordpress/server-side-render@5.5.0 - @wordpress/shortcode@4.5.0 - @wordpress/style-engine@2.5.0 - @wordpress/stylelint-config@22.5.0 - @wordpress/sync@1.5.0 - @wordpress/token-list@3.5.0 - @wordpress/undo-manager@1.5.0 - @wordpress/url@4.5.0 - @wordpress/viewport@6.5.0 - @wordpress/warning@3.5.0 - @wordpress/widgets@4.5.0 - @wordpress/wordcount@4.5.0 --- package-lock.json | 188 +++++++++--------- packages/a11y/package.json | 2 +- packages/annotations/package.json | 2 +- packages/api-fetch/package.json | 2 +- packages/autop/package.json | 2 +- .../package.json | 2 +- packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/package.json | 2 +- packages/base-styles/package.json | 2 +- packages/blob/package.json | 2 +- packages/block-directory/package.json | 2 +- packages/block-editor/package.json | 2 +- packages/block-library/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/blocks/package.json | 2 +- packages/browserslist-config/package.json | 2 +- packages/commands/package.json | 2 +- packages/components/package.json | 2 +- packages/compose/package.json | 2 +- packages/core-commands/package.json | 2 +- packages/core-data/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/create-block/package.json | 2 +- packages/customize-widgets/package.json | 2 +- packages/data-controls/package.json | 2 +- packages/data/package.json | 2 +- packages/dataviews/package.json | 2 +- packages/date/package.json | 2 +- .../package.json | 2 +- packages/deprecated/package.json | 2 +- packages/docgen/package.json | 2 +- packages/dom-ready/package.json | 2 +- packages/dom/package.json | 2 +- .../e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/package.json | 2 +- packages/edit-post/package.json | 2 +- packages/edit-site/package.json | 2 +- packages/edit-widgets/package.json | 2 +- packages/editor/package.json | 2 +- packages/element/package.json | 2 +- packages/env/package.json | 2 +- packages/escape-html/package.json | 2 +- packages/eslint-plugin/package.json | 2 +- packages/format-library/package.json | 2 +- packages/hooks/package.json | 2 +- packages/html-entities/package.json | 2 +- packages/i18n/package.json | 2 +- packages/icons/package.json | 2 +- packages/interactivity-router/package.json | 2 +- packages/interactivity/package.json | 2 +- packages/interface/package.json | 2 +- packages/is-shallow-equal/package.json | 2 +- packages/jest-console/package.json | 2 +- packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/package.json | 2 +- packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/package.json | 2 +- packages/notices/package.json | 2 +- .../npm-package-json-lint-config/package.json | 2 +- packages/nux/package.json | 2 +- packages/patterns/package.json | 2 +- packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/package.json | 2 +- packages/preferences/package.json | 2 +- packages/prettier-config/package.json | 2 +- packages/primitives/package.json | 2 +- packages/priority-queue/package.json | 2 +- packages/private-apis/package.json | 2 +- .../package.json | 2 +- packages/react-i18n/package.json | 2 +- .../package.json | 2 +- packages/redux-routine/package.json | 2 +- packages/reusable-blocks/package.json | 2 +- packages/rich-text/package.json | 2 +- packages/router/package.json | 2 +- packages/scripts/package.json | 2 +- packages/server-side-render/package.json | 2 +- packages/shortcode/package.json | 2 +- packages/style-engine/package.json | 2 +- packages/stylelint-config/package.json | 2 +- packages/sync/package.json | 2 +- packages/token-list/package.json | 2 +- packages/undo-manager/package.json | 2 +- packages/url/package.json | 2 +- packages/viewport/package.json | 2 +- packages/warning/package.json | 2 +- packages/widgets/package.json | 2 +- packages/wordcount/package.json | 2 +- 96 files changed, 189 insertions(+), 189 deletions(-) diff --git a/package-lock.json b/package-lock.json index a28512799804aa..b0eccc961afb78 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52014,7 +52014,7 @@ }, "packages/a11y": { "name": "@wordpress/a11y", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52028,7 +52028,7 @@ }, "packages/annotations": { "name": "@wordpress/annotations", - "version": "3.4.0", + "version": "3.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52056,7 +52056,7 @@ }, "packages/api-fetch": { "name": "@wordpress/api-fetch", - "version": "7.4.0", + "version": "7.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52070,7 +52070,7 @@ }, "packages/autop": { "name": "@wordpress/autop", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52082,7 +52082,7 @@ }, "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.4.0", + "version": "5.5.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52095,7 +52095,7 @@ }, "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", - "version": "6.4.0", + "version": "6.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52113,7 +52113,7 @@ }, "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", - "version": "8.4.0", + "version": "8.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52136,7 +52136,7 @@ }, "packages/base-styles": { "name": "@wordpress/base-styles", - "version": "5.4.0", + "version": "5.5.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52146,7 +52146,7 @@ }, "packages/blob": { "name": "@wordpress/blob", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52158,7 +52158,7 @@ }, "packages/block-directory": { "name": "@wordpress/block-directory", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52193,7 +52193,7 @@ }, "packages/block-editor": { "name": "@wordpress/block-editor", - "version": "13.4.0", + "version": "14.0.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52290,7 +52290,7 @@ }, "packages/block-library": { "name": "@wordpress/block-library", - "version": "9.4.0", + "version": "9.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52356,7 +52356,7 @@ }, "packages/block-serialization-default-parser": { "name": "@wordpress/block-serialization-default-parser", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52368,7 +52368,7 @@ }, "packages/block-serialization-spec-parser": { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "pegjs": "^0.10.0", @@ -52381,7 +52381,7 @@ }, "packages/blocks": { "name": "@wordpress/blocks", - "version": "13.4.0", + "version": "13.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52435,7 +52435,7 @@ }, "packages/browserslist-config": { "name": "@wordpress/browserslist-config", - "version": "6.4.0", + "version": "6.5.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52445,7 +52445,7 @@ }, "packages/commands": { "name": "@wordpress/commands", - "version": "1.4.0", + "version": "1.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52618,7 +52618,7 @@ }, "packages/components": { "name": "@wordpress/components", - "version": "28.4.0", + "version": "28.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.7", @@ -52744,7 +52744,7 @@ }, "packages/compose": { "name": "@wordpress/compose", - "version": "7.4.0", + "version": "7.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52781,7 +52781,7 @@ }, "packages/core-commands": { "name": "@wordpress/core-commands", - "version": "1.4.0", + "version": "1.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52809,7 +52809,7 @@ }, "packages/core-data": { "name": "@wordpress/core-data", - "version": "7.4.0", + "version": "7.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52854,7 +52854,7 @@ }, "packages/create-block": { "name": "@wordpress/create-block", - "version": "4.47.0", + "version": "4.48.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52882,7 +52882,7 @@ }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", - "version": "4.4.0", + "version": "4.5.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52892,7 +52892,7 @@ }, "packages/customize-widgets": { "name": "@wordpress/customize-widgets", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52930,7 +52930,7 @@ }, "packages/data": { "name": "@wordpress/data", - "version": "10.4.0", + "version": "10.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52959,7 +52959,7 @@ }, "packages/data-controls": { "name": "@wordpress/data-controls", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52977,7 +52977,7 @@ }, "packages/dataviews": { "name": "@wordpress/dataviews", - "version": "4.0.0", + "version": "4.1.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.7", @@ -53039,7 +53039,7 @@ }, "packages/date": { "name": "@wordpress/date", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53054,7 +53054,7 @@ }, "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.4.0", + "version": "6.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53070,7 +53070,7 @@ }, "packages/deprecated": { "name": "@wordpress/deprecated", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53083,7 +53083,7 @@ }, "packages/docgen": { "name": "@wordpress/docgen", - "version": "2.4.0", + "version": "2.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53105,7 +53105,7 @@ }, "packages/dom": { "name": "@wordpress/dom", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53118,7 +53118,7 @@ }, "packages/dom-ready": { "name": "@wordpress/dom-ready", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53130,7 +53130,7 @@ }, "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", - "version": "11.4.0", + "version": "11.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53153,7 +53153,7 @@ }, "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.4.0", + "version": "1.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53181,7 +53181,7 @@ }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", - "version": "8.4.0", + "version": "8.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53221,7 +53221,7 @@ }, "packages/edit-post": { "name": "@wordpress/edit-post", - "version": "8.4.0", + "version": "8.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53268,7 +53268,7 @@ }, "packages/edit-site": { "name": "@wordpress/edit-site", - "version": "6.4.0", + "version": "6.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53330,7 +53330,7 @@ }, "packages/edit-widgets": { "name": "@wordpress/edit-widgets", - "version": "6.4.0", + "version": "6.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53373,7 +53373,7 @@ }, "packages/editor": { "name": "@wordpress/editor", - "version": "14.4.0", + "version": "14.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53434,7 +53434,7 @@ }, "packages/element": { "name": "@wordpress/element", - "version": "6.4.0", + "version": "6.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53453,7 +53453,7 @@ }, "packages/env": { "name": "@wordpress/env", - "version": "10.4.0", + "version": "10.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53595,7 +53595,7 @@ }, "packages/escape-html": { "name": "@wordpress/escape-html", - "version": "3.4.0", + "version": "3.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53607,7 +53607,7 @@ }, "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", - "version": "20.1.0", + "version": "20.2.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53650,7 +53650,7 @@ }, "packages/format-library": { "name": "@wordpress/format-library", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53678,7 +53678,7 @@ }, "packages/hooks": { "name": "@wordpress/hooks", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53690,7 +53690,7 @@ }, "packages/html-entities": { "name": "@wordpress/html-entities", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53702,7 +53702,7 @@ }, "packages/i18n": { "name": "@wordpress/i18n", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53722,7 +53722,7 @@ }, "packages/icons": { "name": "@wordpress/icons", - "version": "10.4.0", + "version": "10.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53736,7 +53736,7 @@ }, "packages/interactivity": { "name": "@wordpress/interactivity", - "version": "6.4.0", + "version": "6.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@preact/signals": "^1.2.2", @@ -53749,7 +53749,7 @@ }, "packages/interactivity-router": { "name": "@wordpress/interactivity-router", - "version": "2.4.0", + "version": "2.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/interactivity": "file:../interactivity" @@ -53785,7 +53785,7 @@ }, "packages/interface": { "name": "@wordpress/interface", - "version": "6.4.0", + "version": "6.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53814,7 +53814,7 @@ }, "packages/is-shallow-equal": { "name": "@wordpress/is-shallow-equal", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53826,7 +53826,7 @@ }, "packages/jest-console": { "name": "@wordpress/jest-console", - "version": "8.4.0", + "version": "8.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53843,7 +53843,7 @@ }, "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", - "version": "12.4.0", + "version": "12.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53861,7 +53861,7 @@ }, "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.4.0", + "version": "7.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53884,7 +53884,7 @@ }, "packages/keyboard-shortcuts": { "name": "@wordpress/keyboard-shortcuts", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53902,7 +53902,7 @@ }, "packages/keycodes": { "name": "@wordpress/keycodes", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53915,7 +53915,7 @@ }, "packages/lazy-import": { "name": "@wordpress/lazy-import", - "version": "2.4.0", + "version": "2.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53930,7 +53930,7 @@ }, "packages/list-reusable-blocks": { "name": "@wordpress/list-reusable-blocks", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53953,7 +53953,7 @@ }, "packages/media-utils": { "name": "@wordpress/media-utils", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53969,7 +53969,7 @@ }, "packages/notices": { "name": "@wordpress/notices", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53986,7 +53986,7 @@ }, "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.4.0", + "version": "5.5.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -53999,7 +53999,7 @@ }, "packages/nux": { "name": "@wordpress/nux", - "version": "9.4.0", + "version": "9.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54022,7 +54022,7 @@ }, "packages/patterns": { "name": "@wordpress/patterns", - "version": "2.4.0", + "version": "2.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54052,7 +54052,7 @@ }, "packages/plugins": { "name": "@wordpress/plugins", - "version": "7.4.0", + "version": "7.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54075,7 +54075,7 @@ }, "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", - "version": "5.4.0", + "version": "5.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54092,7 +54092,7 @@ }, "packages/postcss-themes": { "name": "@wordpress/postcss-themes", - "version": "6.4.0", + "version": "6.5.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54105,7 +54105,7 @@ }, "packages/preferences": { "name": "@wordpress/preferences", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54131,7 +54131,7 @@ }, "packages/preferences-persistence": { "name": "@wordpress/preferences-persistence", - "version": "2.4.0", + "version": "2.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54144,7 +54144,7 @@ }, "packages/prettier-config": { "name": "@wordpress/prettier-config", - "version": "4.4.0", + "version": "4.5.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54157,7 +54157,7 @@ }, "packages/primitives": { "name": "@wordpress/primitives", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54174,7 +54174,7 @@ }, "packages/priority-queue": { "name": "@wordpress/priority-queue", - "version": "3.4.0", + "version": "3.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54187,7 +54187,7 @@ }, "packages/private-apis": { "name": "@wordpress/private-apis", - "version": "1.4.0", + "version": "1.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54199,7 +54199,7 @@ }, "packages/project-management-automation": { "name": "@wordpress/project-management-automation", - "version": "2.4.0", + "version": "2.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54229,7 +54229,7 @@ }, "packages/react-i18n": { "name": "@wordpress/react-i18n", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54385,7 +54385,7 @@ }, "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.4.0", + "version": "3.5.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54398,7 +54398,7 @@ }, "packages/redux-routine": { "name": "@wordpress/redux-routine", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54443,7 +54443,7 @@ }, "packages/reusable-blocks": { "name": "@wordpress/reusable-blocks", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54470,7 +54470,7 @@ }, "packages/rich-text": { "name": "@wordpress/rich-text", - "version": "7.4.0", + "version": "7.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54494,7 +54494,7 @@ }, "packages/router": { "name": "@wordpress/router", - "version": "1.4.0", + "version": "1.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54513,7 +54513,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "28.4.0", + "version": "28.5.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54967,7 +54967,7 @@ }, "packages/server-side-render": { "name": "@wordpress/server-side-render", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54993,7 +54993,7 @@ }, "packages/shortcode": { "name": "@wordpress/shortcode", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55006,7 +55006,7 @@ }, "packages/style-engine": { "name": "@wordpress/style-engine", - "version": "2.4.0", + "version": "2.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55019,7 +55019,7 @@ }, "packages/stylelint-config": { "name": "@wordpress/stylelint-config", - "version": "22.4.0", + "version": "22.5.0", "dev": true, "license": "MIT", "dependencies": { @@ -55036,7 +55036,7 @@ }, "packages/sync": { "name": "@wordpress/sync", - "version": "1.4.0", + "version": "1.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55057,7 +55057,7 @@ }, "packages/token-list": { "name": "@wordpress/token-list", - "version": "3.4.0", + "version": "3.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -55069,7 +55069,7 @@ }, "packages/undo-manager": { "name": "@wordpress/undo-manager", - "version": "1.4.0", + "version": "1.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55082,7 +55082,7 @@ }, "packages/url": { "name": "@wordpress/url", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55095,7 +55095,7 @@ }, "packages/viewport": { "name": "@wordpress/viewport", - "version": "6.4.0", + "version": "6.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55113,7 +55113,7 @@ }, "packages/warning": { "name": "@wordpress/warning", - "version": "3.4.0", + "version": "3.5.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55122,7 +55122,7 @@ }, "packages/widgets": { "name": "@wordpress/widgets", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55150,7 +55150,7 @@ }, "packages/wordcount": { "name": "@wordpress/wordcount", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 139bc42bd01f46..c9bff2d5c73752 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 1d571c8b372985..7706e6e0b345e9 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.5.0-prerelease", + "version": "3.5.0", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 837df14c307778..4c5ee98edcd12a 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.5.0-prerelease", + "version": "7.5.0", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/package.json b/packages/autop/package.json index dbb5712928574c..af8830570bd049 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index bae71e052d9018..3cec94c138f99a 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index f255736856caaf..6540cb5bf4cd7d 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.5.0-prerelease", + "version": "6.5.0", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 311b9fd1594fd4..0ee883a0d4ee1f 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.5.0-prerelease", + "version": "8.5.0", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index 1a0e6ac2c176cf..9c243e87d1f2f1 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/package.json b/packages/blob/package.json index ae216a1f5aaa01..51987239c14515 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 9b67833be0ec8e..78a786b4c7d497 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 81f8613fb4e339..8ccaee6f0a955c 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.0.0-prerelease", + "version": "14.0.0", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 83d796ad11b16a..4948fed4e65a5b 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.5.0-prerelease", + "version": "9.5.0", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 34e57586ea52c5..c3237f9282f749 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 88851d4b60d793..918ad0f2ed78b3 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/package.json b/packages/blocks/package.json index f64948af554168..43bcc5c587071e 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.5.0-prerelease", + "version": "13.5.0", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 9c3213cb2ba866..429b3a9f82f339 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.5.0-prerelease", + "version": "6.5.0", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/package.json b/packages/commands/package.json index 67ba52b5544e8a..ea504a589acfd8 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.5.0-prerelease", + "version": "1.5.0", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/package.json b/packages/components/package.json index e188c05ba2a847..7a33e5840c2311 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.5.0-prerelease", + "version": "28.5.0", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/package.json b/packages/compose/package.json index c5ea618103ca95..2a4dcb02803c58 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.5.0-prerelease", + "version": "7.5.0", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 13312adcab650a..d29688cfbcedf4 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.5.0-prerelease", + "version": "1.5.0", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/package.json b/packages/core-data/package.json index e15f84799aea53..d736b2b7b1b936 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.5.0-prerelease", + "version": "7.5.0", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index 33df8821966113..751243b8b8021b 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.5.0-prerelease", + "version": "2.5.0", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index e2647dbd531f0c..2a344a094a4b41 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 203816ddf226fb..f0a91d54c14963 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.48.0-prerelease", + "version": "4.48.0", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 76b152a080f388..f619837ae573e0 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 9e7f2d26089ee2..40dfbdf307d2c2 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/package.json b/packages/data/package.json index 46bd6c4a134c7e..b987476d49bd90 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.5.0-prerelease", + "version": "10.5.0", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index b410f8b9b959e3..c86a4feb9c0668 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.1.0-prerelease", + "version": "4.1.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/package.json b/packages/date/package.json index a2f45532505fe4..69871d61e284fa 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index 558173f7fe21ab..ebd6e4ef19fd69 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.5.0-prerelease", + "version": "6.5.0", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 681beb2e25d7d5..80f4c62e2a84b9 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/package.json b/packages/docgen/package.json index cab58965b69936..b3f6e12e0210cb 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.5.0-prerelease", + "version": "2.5.0", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index f80bf5f8d35fba..583f03f75d2ae6 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/package.json b/packages/dom/package.json index f1aec564927a25..6297fa9d696e12 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 25f231a39c635f..521cbb5c753aa7 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.5.0-prerelease", + "version": "1.5.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index c594c0db136340..dc36a8fb4194bd 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.5.0-prerelease", + "version": "11.5.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 8e89e852e2b962..c826229a6e7a43 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.5.0-prerelease", + "version": "8.5.0", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index c080209b37e96d..8fd1bafe1ab491 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.5.0-prerelease", + "version": "8.5.0", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index fc3a9e355f2b8a..3e7e671fa1fa2f 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.5.0-prerelease", + "version": "6.5.0", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 8b43279e8dc0e6..20ff3129330082 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.5.0-prerelease", + "version": "6.5.0", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/package.json b/packages/editor/package.json index e0d0fd93c9bc83..cbe42f3b662c68 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.5.0-prerelease", + "version": "14.5.0", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/package.json b/packages/element/package.json index fc457a950090d8..382d0ac50b67c7 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.5.0-prerelease", + "version": "6.5.0", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/package.json b/packages/env/package.json index 32e332040e4eaf..2b8efcfbf07af7 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.5.0-prerelease", + "version": "10.5.0", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index d1949cb32b974c..ef6adce54b8cf6 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.5.0-prerelease", + "version": "3.5.0", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 0ebe3272154055..bf83ac72435604 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "20.2.0-prerelease", + "version": "20.2.0", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/package.json b/packages/format-library/package.json index eb23caf92ef872..72d9a054ae8253 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 2c55175073f2f0..4def8c8e7a0958 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 4416d167e0cda6..ea3a1fe00f0816 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/package.json b/packages/i18n/package.json index b67d18ec695bba..50ce8f7a839de8 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/package.json b/packages/icons/package.json index 0d420d9ae93e62..ad32ed6fca29e6 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.5.0-prerelease", + "version": "10.5.0", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 1435f19e84ed44..5ac4dcbf9b9fa0 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.5.0-prerelease", + "version": "2.5.0", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 89b98463e08190..33d575a0102f9e 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.5.0-prerelease", + "version": "6.5.0", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/package.json b/packages/interface/package.json index 75b5b92621ac7b..35b41c1b309c93 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "6.5.0-prerelease", + "version": "6.5.0", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 89d9ecc1155f32..f9996eea6c480e 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 9744a87680c0f2..4f36017125015c 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.5.0-prerelease", + "version": "8.5.0", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 59c8c7e984dce5..f69c9465a80fea 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.5.0-prerelease", + "version": "12.5.0", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 10c891a939376f..8b2b9cd4e179b6 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.5.0-prerelease", + "version": "7.5.0", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 4d32c65cf55afd..d3caa86a85ba0d 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 1640c7e831bb41..4ff043a3370e89 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index 9e9f77225c1794..d7737d0fe5a234 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.5.0-prerelease", + "version": "2.5.0", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 50a26cb0671713..79c668e8d26ac9 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 5facc75c780b67..d3bb92294fda34 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/package.json b/packages/notices/package.json index 6b952f566075de..944003de426ab5 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index 3ab2d07913ee37..9fe4005668e106 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/package.json b/packages/nux/package.json index 4fb355fe51f341..4a3ec7716c8afe 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.5.0-prerelease", + "version": "9.5.0", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/package.json b/packages/patterns/package.json index c544287e6f7404..e2e77f1d15267b 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.5.0-prerelease", + "version": "2.5.0", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 530a758d7bc276..bb4a9c3ecdd4cd 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.5.0-prerelease", + "version": "7.5.0", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 388855af3b5fdd..be6f88e9575b13 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index e56ed2c24d1b5d..20da35b26ebf14 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.5.0-prerelease", + "version": "6.5.0", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index de0a7dbc87164f..1d94d3635a51b8 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.5.0-prerelease", + "version": "2.5.0", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/package.json b/packages/preferences/package.json index 2a53487932c401..c433879f01da5a 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 0a6486068067fd..9d8020c086d90a 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/package.json b/packages/primitives/package.json index f3298b3dfe7ebe..5a922c5e243477 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index bd7069f6718141..fb7e4138395040 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.5.0-prerelease", + "version": "3.5.0", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index a46a499716fb10..2cb212b07bbb3f 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.5.0-prerelease", + "version": "1.5.0", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 5efd0e01ef43c1..03107778fcb1a1 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.5.0-prerelease", + "version": "2.5.0", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 89ca7018bf7da8..4b9f1949f7044b 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index 596a8a82d4f419..e084c40bbfab5c 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.5.0-prerelease", + "version": "3.5.0", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index a329e0091f7709..69696f72e2c430 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 08d8a71c2aff26..c3b5219f117a45 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 66ddc465e65ac6..d120411e746731 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.5.0-prerelease", + "version": "7.5.0", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/package.json b/packages/router/package.json index 6f9c44faff6e3f..e3c45b7ef0b525 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.5.0-prerelease", + "version": "1.5.0", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index c0b68e73e36827..675d6aa9feb6d5 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "28.5.0-prerelease", + "version": "28.5.0", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index c28611fce5b7f3..642c515c9c0253 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.5.0-prerelease", + "version": "5.5.0", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index 89ed91aa947ecb..e5e7e6c382550d 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 84a76d7d0180f0..c41d1524a262a4 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.5.0-prerelease", + "version": "2.5.0", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 084b7159788c25..199822d91c733b 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "22.5.0-prerelease", + "version": "22.5.0", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/package.json b/packages/sync/package.json index bc054732462496..4380d7261ca457 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.5.0-prerelease", + "version": "1.5.0", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/package.json b/packages/token-list/package.json index b99cb89e3695ab..3227b4da442eed 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.5.0-prerelease", + "version": "3.5.0", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 96961844152818..41d13755280bbf 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.5.0-prerelease", + "version": "1.5.0", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/package.json b/packages/url/package.json index 57e7fdacccd271..6bee340360a501 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 65c9df5b7ecf6c..6ef7a28a2a9e33 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.5.0-prerelease", + "version": "6.5.0", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/package.json b/packages/warning/package.json index dd9e01fb6cf95d..418f16427cd325 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.5.0-prerelease", + "version": "3.5.0", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/package.json b/packages/widgets/package.json index b7f87a89d57c3e..b8160fc6cd41ba 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index b507e5ee3e3c84..3e2bcbe2ee4ca4 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From ddadd1a95d18270908ac4a1fd8d6e354cfadf61c Mon Sep 17 00:00:00 2001 From: Damon Cook <colorful-tones@users.noreply.github.com> Date: Wed, 7 Aug 2024 16:57:41 -0400 Subject: [PATCH 0305/1908] Add clarification about importing css/scss files (#61252) * Add clarification about importing css/scss files * Wrap in callout and update phrasing for WP scripts * Fix type in Block Tutorial Styles doc --- .../applying-styles-with-stylesheets.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/how-to-guides/block-tutorial/applying-styles-with-stylesheets.md b/docs/how-to-guides/block-tutorial/applying-styles-with-stylesheets.md index 122ee3eaa0c27e..85ac956ff74ba6 100644 --- a/docs/how-to-guides/block-tutorial/applying-styles-with-stylesheets.md +++ b/docs/how-to-guides/block-tutorial/applying-styles-with-stylesheets.md @@ -138,6 +138,17 @@ And a `style.css` file to load on the frontend: The files will automatically be enqueued when specified in the block.json. +<div class="callout callout-info"> + +If you are using `@wordpress/scripts` you will need to import your stylesheet within your corresponding JavaScript file in order for `@wordpress/scripts` to process the stylesheet. + +Example: + +- In `edit.js` you would place `import './editor.scss';` +- In `index.js` you would place `import './style.scss';` +- In `view.js` you would place `import './view.scss';` (interactive block template) +</div> + **Note:** If you have multiple files to include, you can use standard `wp_enqueue_style` functions like any other plugin or theme. You will want to use the following hooks for the block editor: - `enqueue_block_editor_assets` - to load only in editor view From d578bb2370d57a4e9b975da46c05bc92133f06ee Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 8 Aug 2024 09:14:00 +0200 Subject: [PATCH 0306/1908] DataForm: Use the fields array to define the order of the fields (#64335) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: Zealth57 <elrae@git.wordpress.org> --- packages/dataviews/src/dataforms-layouts/panel/index.tsx | 8 ++++++-- .../dataviews/src/dataforms-layouts/regular/index.tsx | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/dataviews/src/dataforms-layouts/panel/index.tsx b/packages/dataviews/src/dataforms-layouts/panel/index.tsx index 3dc52db0adc879..151aefed12c24b 100644 --- a/packages/dataviews/src/dataforms-layouts/panel/index.tsx +++ b/packages/dataviews/src/dataforms-layouts/panel/index.tsx @@ -17,7 +17,7 @@ import { closeSmall } from '@wordpress/icons'; * Internal dependencies */ import { normalizeFields } from '../../normalize-fields'; -import type { DataFormProps, NormalizedField } from '../../types'; +import type { DataFormProps, NormalizedField, Field } from '../../types'; interface FormFieldProps< Item > { data: Item; @@ -142,7 +142,11 @@ export default function FormPanel< Item >( { const visibleFields = useMemo( () => normalizeFields( - fields.filter( ( { id } ) => !! form.fields?.includes( id ) ) + ( form.fields ?? [] ) + .map( ( fieldId ) => + fields.find( ( { id } ) => id === fieldId ) + ) + .filter( ( field ): field is Field< Item > => !! field ) ), [ fields, form.fields ] ); diff --git a/packages/dataviews/src/dataforms-layouts/regular/index.tsx b/packages/dataviews/src/dataforms-layouts/regular/index.tsx index 1164a61196a699..0ec427ae010032 100644 --- a/packages/dataviews/src/dataforms-layouts/regular/index.tsx +++ b/packages/dataviews/src/dataforms-layouts/regular/index.tsx @@ -8,7 +8,7 @@ import { useMemo } from '@wordpress/element'; * Internal dependencies */ import { normalizeFields } from '../../normalize-fields'; -import type { DataFormProps } from '../../types'; +import type { DataFormProps, Field } from '../../types'; export default function FormRegular< Item >( { data, @@ -19,7 +19,11 @@ export default function FormRegular< Item >( { const visibleFields = useMemo( () => normalizeFields( - fields.filter( ( { id } ) => !! form.fields?.includes( id ) ) + ( form.fields ?? [] ) + .map( ( fieldId ) => + fields.find( ( { id } ) => id === fieldId ) + ) + .filter( ( field ): field is Field< Item > => !! field ) ), [ fields, form.fields ] ); From 556219922d5bd4c761c3f36409388cef838e5c0a Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 8 Aug 2024 11:21:27 +0200 Subject: [PATCH 0307/1908] DataViews Extensibility: Allow unregistering the reorder-page action (#64199) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/dataviews/src/normalize-fields.ts | 5 +- packages/dataviews/src/types.ts | 14 +- .../src/components/post-actions/actions.js | 113 +---------------- .../dataviews/actions/reorder-page.native.tsx | 3 + .../src/dataviews/actions/reorder-page.tsx | 120 ++++++++++++++++++ packages/editor/src/dataviews/fields/index.ts | 25 ++++ .../src/dataviews/store/private-actions.ts | 4 + packages/editor/src/dataviews/types.ts | 7 + 8 files changed, 171 insertions(+), 120 deletions(-) create mode 100644 packages/editor/src/dataviews/actions/reorder-page.native.tsx create mode 100644 packages/editor/src/dataviews/actions/reorder-page.tsx create mode 100644 packages/editor/src/dataviews/fields/index.ts diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index 860341cc946269..8cd9051cbb1cc3 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -2,7 +2,7 @@ * Internal dependencies */ import getFieldTypeDefinition from './field-types'; -import type { Field, NormalizedField } from './types'; +import type { Field, NormalizedField, ItemRecord } from './types'; /** * Apply default values and normalize the fields config. @@ -18,7 +18,8 @@ export function normalizeFields< Item >( const getValue = field.getValue || - ( ( { item }: { item: Item } ) => item[ field.id as keyof Item ] ); + // @ts-ignore + ( ( { item }: { item: ItemRecord } ) => item[ field.id ] ); const sort = field.sort ?? diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 25e603d8cfa234..64580a089997d1 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -47,7 +47,7 @@ export type Operator = | 'isAll' | 'isNotAll'; -export type ItemRecord = Record< string, unknown >; +export type ItemRecord = Object; export type FieldType = 'text' | 'integer'; @@ -423,6 +423,12 @@ interface ActionBase< Item > { supportsBulk?: boolean; } +export interface RenderModalProps< Item > { + items: Item[]; + closeModal?: () => void; + onActionPerformed?: ( items: Item[] ) => void; +} + export interface ActionModal< Item > extends ActionBase< Item > { /** * Modal to render when the action is triggered. @@ -431,11 +437,7 @@ export interface ActionModal< Item > extends ActionBase< Item > { items, closeModal, onActionPerformed, - }: { - items: Item[]; - closeModal?: () => void; - onActionPerformed?: ( items: Item[] ) => void; - } ) => ReactElement; + }: RenderModalProps< Item > ) => ReactElement; /** * Whether to hide the modal header. diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 983cc33b29e622..64afec2417cd05 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -11,7 +11,7 @@ import { store as noticesStore } from '@wordpress/notices'; import { useMemo, useState, useEffect } from '@wordpress/element'; import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; import { parse } from '@wordpress/blocks'; -import { DataForm, isItemValid } from '@wordpress/dataviews'; +import { DataForm } from '@wordpress/dataviews'; import { Button, TextControl, @@ -58,10 +58,6 @@ const formDuplicateAction = { fields: [ 'title' ], }; -const formOrderAction = { - fields: [ 'menu_order' ], -}; - /** * Check if a template is removable. * @@ -238,110 +234,6 @@ const renamePostAction = { }, }; -function ReorderModal( { items, closeModal, onActionPerformed } ) { - const [ item, setItem ] = useState( items[ 0 ] ); - const orderInput = item.menu_order; - const { editEntityRecord, saveEditedEntityRecord } = - useDispatch( coreStore ); - const { createSuccessNotice, createErrorNotice } = - useDispatch( noticesStore ); - - async function onOrder( event ) { - event.preventDefault(); - - if ( ! isItemValid( item, fields, formOrderAction ) ) { - return; - } - - try { - await editEntityRecord( 'postType', item.type, item.id, { - menu_order: orderInput, - } ); - closeModal(); - // Persist edited entity. - await saveEditedEntityRecord( 'postType', item.type, item.id, { - throwOnError: true, - } ); - createSuccessNotice( __( 'Order updated' ), { - type: 'snackbar', - } ); - onActionPerformed?.( items ); - } catch ( error ) { - const errorMessage = - error.message && error.code !== 'unknown_error' - ? error.message - : __( 'An error occurred while updating the order' ); - createErrorNotice( errorMessage, { - type: 'snackbar', - } ); - } - } - const isSaveDisabled = ! isItemValid( item, fields, formOrderAction ); - return ( - <form onSubmit={ onOrder }> - <VStack spacing="5"> - <div> - { __( - 'Determines the order of pages. Pages with the same order value are sorted alphabetically. Negative order values are supported.' - ) } - </div> - <DataForm - data={ item } - fields={ fields } - form={ formOrderAction } - onChange={ setItem } - /> - <HStack justify="right"> - <Button - __next40pxDefaultSize - variant="tertiary" - onClick={ () => { - closeModal(); - } } - > - { __( 'Cancel' ) } - </Button> - <Button - __next40pxDefaultSize - variant="primary" - type="submit" - accessibleWhenDisabled - disabled={ isSaveDisabled } - __experimentalIsFocusable - > - { __( 'Save' ) } - </Button> - </HStack> - </VStack> - </form> - ); -} - -function useReorderPagesAction( postType ) { - const supportsPageAttributes = useSelect( - ( select ) => { - const { getPostType } = select( coreStore ); - const postTypeObject = getPostType( postType ); - - return !! postTypeObject?.supports?.[ 'page-attributes' ]; - }, - [ postType ] - ); - - return useMemo( - () => - supportsPageAttributes && { - id: 'order-pages', - label: __( 'Order' ), - isEligible( { status } ) { - return status !== 'trash'; - }, - RenderModal: ReorderModal, - }, - [ supportsPageAttributes ] - ); -} - const useDuplicatePostAction = ( postType ) => { const userCanCreatePost = useSelect( ( select ) => { @@ -595,7 +487,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { }, [ registerPostTypeActions, postType ] ); const duplicatePostAction = useDuplicatePostAction( postType ); - const reorderPagesAction = useReorderPagesAction( postType ); const isTemplateOrTemplatePart = [ TEMPLATE_POST_TYPE, TEMPLATE_PART_POST_TYPE, @@ -622,7 +513,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { duplicateTemplatePartAction, isPattern && userCanCreatePostType && duplicatePatternAction, supportsTitle && renamePostAction, - reorderPagesAction, ...defaultActions, ].filter( Boolean ); // Filter actions based on provided context. If not provided @@ -693,7 +583,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { isPattern, postTypeObject?.viewable, duplicatePostAction, - reorderPagesAction, onActionPerformed, isLoaded, supportsRevisions, diff --git a/packages/editor/src/dataviews/actions/reorder-page.native.tsx b/packages/editor/src/dataviews/actions/reorder-page.native.tsx new file mode 100644 index 00000000000000..61e4733b6c6bd9 --- /dev/null +++ b/packages/editor/src/dataviews/actions/reorder-page.native.tsx @@ -0,0 +1,3 @@ +const reorderPage = undefined; + +export default reorderPage; diff --git a/packages/editor/src/dataviews/actions/reorder-page.tsx b/packages/editor/src/dataviews/actions/reorder-page.tsx new file mode 100644 index 00000000000000..9193904f0f912c --- /dev/null +++ b/packages/editor/src/dataviews/actions/reorder-page.tsx @@ -0,0 +1,120 @@ +/** + * WordPress dependencies + */ +import { useDispatch } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { __ } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; +import { useState } from '@wordpress/element'; +import { DataForm, isItemValid } from '@wordpress/dataviews'; +import { + Button, + __experimentalHStack as HStack, + __experimentalVStack as VStack, +} from '@wordpress/components'; +import type { Action, RenderModalProps } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import type { CoreDataError, PostWithPageAttributesSupport } from '../types'; +import { orderField } from '../fields'; + +const fields = [ orderField ]; +const formOrderAction = { + fields: [ 'menu_order' ], +}; + +function ReorderModal( { + items, + closeModal, + onActionPerformed, +}: RenderModalProps< PostWithPageAttributesSupport > ) { + const [ item, setItem ] = useState( items[ 0 ] ); + const orderInput = item.menu_order; + const { editEntityRecord, saveEditedEntityRecord } = + useDispatch( coreStore ); + const { createSuccessNotice, createErrorNotice } = + useDispatch( noticesStore ); + + async function onOrder( event: React.FormEvent ) { + event.preventDefault(); + + if ( ! isItemValid( item, fields, formOrderAction ) ) { + return; + } + + try { + await editEntityRecord( 'postType', item.type, item.id, { + menu_order: orderInput, + } ); + closeModal?.(); + // Persist edited entity. + await saveEditedEntityRecord( 'postType', item.type, item.id, { + throwOnError: true, + } ); + createSuccessNotice( __( 'Order updated.' ), { + type: 'snackbar', + } ); + onActionPerformed?.( items ); + } catch ( error ) { + const typedError = error as CoreDataError; + const errorMessage = + typedError.message && typedError.code !== 'unknown_error' + ? typedError.message + : __( 'An error occurred while updating the order' ); + createErrorNotice( errorMessage, { + type: 'snackbar', + } ); + } + } + const isSaveDisabled = ! isItemValid( item, fields, formOrderAction ); + return ( + <form onSubmit={ onOrder }> + <VStack spacing="5"> + <div> + { __( + 'Determines the order of pages. Pages with the same order value are sorted alphabetically. Negative order values are supported.' + ) } + </div> + <DataForm + data={ item } + fields={ fields } + form={ formOrderAction } + onChange={ setItem } + /> + <HStack justify="right"> + <Button + __next40pxDefaultSize + variant="tertiary" + onClick={ () => { + closeModal?.(); + } } + > + { __( 'Cancel' ) } + </Button> + <Button + __next40pxDefaultSize + variant="primary" + type="submit" + accessibleWhenDisabled + disabled={ isSaveDisabled } + > + { __( 'Save' ) } + </Button> + </HStack> + </VStack> + </form> + ); +} + +const reorderPage: Action< PostWithPageAttributesSupport > = { + id: 'order-pages', + label: __( 'Order' ), + isEligible( { status } ) { + return status !== 'trash'; + }, + RenderModal: ReorderModal, +}; + +export default reorderPage; diff --git a/packages/editor/src/dataviews/fields/index.ts b/packages/editor/src/dataviews/fields/index.ts new file mode 100644 index 00000000000000..ea30d15dab600b --- /dev/null +++ b/packages/editor/src/dataviews/fields/index.ts @@ -0,0 +1,25 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import type { Field } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import type { BasePost, PostWithPageAttributesSupport } from '../types'; + +export const titleField: Field< BasePost > = { + type: 'text', + id: 'title', + label: __( 'Title' ), + placeholder: __( 'No title' ), + getValue: ( { item } ) => item.title, +}; + +export const orderField: Field< PostWithPageAttributesSupport > = { + type: 'integer', + id: 'menu_order', + label: __( 'Order' ), + description: __( 'Determines the order of pages.' ), +}; diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 745cc0ad82e934..d5e12e298039a1 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -14,6 +14,7 @@ import resetPost from '../actions/reset-post'; import trashPost from '../actions/trash-post'; import permanentlyDeletePost from '../actions/permanently-delete-post'; import restorePost from '../actions/restore-post'; +import reorderPage from '../actions/reorder-page'; import type { PostType } from '../types'; import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; @@ -73,6 +74,9 @@ export const registerPostTypeActions = .getPostType( postType ) ) as PostType; const actions = [ + postTypeConfig?.supports?.[ 'page-attributes' ] + ? reorderPage + : undefined, postTypeConfig.slug === 'wp_block' ? exportPattern : undefined, resetPost, restorePost, diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts index 47f11c88bfb978..0c31bef195eb9b 100644 --- a/packages/editor/src/dataviews/types.ts +++ b/packages/editor/src/dataviews/types.ts @@ -27,6 +27,10 @@ export interface Pattern extends BasePost { wp_pattern_sync_status: string; } +export interface PostWithPageAttributesSupport extends BasePost { + menu_order: number; +} + export type Post = TemplateOrTemplatePart | Pattern | BasePost; export type PostWithPermissions = Post & { @@ -38,6 +42,9 @@ export type PostWithPermissions = Post & { export interface PostType { slug: string; + supports?: { + 'page-attributes'?: boolean; + }; } // Will be unnecessary after typescript 5.0 upgrade. From 236250e3fa04ad7337c305540f76ed619b0dde98 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 8 Aug 2024 11:59:28 +0200 Subject: [PATCH 0308/1908] Components: add "Naming conventions" section (#63714) * Use update compound suggested notation * Remove reference to item group as it may not reflect anymore all recent best practices * Tweak part about experimental APIs * Fix spacing * Linter auto-formatting * Add Naming Conventions section * Update guidelines to use overloaded convention, remove references to monolithic components * Added more details to the JSX example * Grammar * Split unforwarded component from forwardRef call * Fix comment + auto-format * Add section on JSDocs + IntelliSense requirements + recommended best practices * Use named functions without attributing them to const --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: diegohaz <hazdiego@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> --- packages/components/CONTRIBUTING.md | 219 ++++++++++++++++++++-------- 1 file changed, 155 insertions(+), 64 deletions(-) diff --git a/packages/components/CONTRIBUTING.md b/packages/components/CONTRIBUTING.md index f1245da7a409c6..57a9f2fb049a24 100644 --- a/packages/components/CONTRIBUTING.md +++ b/packages/components/CONTRIBUTING.md @@ -6,20 +6,20 @@ The following is a set of guidelines for contributing to the `@wordpress/compone This set of guidelines should apply especially to newly introduced components. In fact, while these guidelines should also be retroactively applied to existing components, it is sometimes impossible to do so for legacy/compatibility reasons. -For an example of a component that follows these requirements, take a look at [`ItemGroup`](/packages/components/src/item-group). -- [Introducing new components](#introducing-new-components) -- [Compatibility](#compatibility) -- [Compound components](#compound-components) -- [Components & Hooks](#components--hooks) -- [TypeScript](#typescript) -- [Styling](#styling) -- [Context system](#context-system) -- [Unit tests](#unit-tests) -- [Storybook](#storybook) -- [Documentation](#documentation) -- [README example](#README-example) -- [Folder structure](#folder-structure) -- [Component versioning](#component-versioning) +- [Introducing new components](#introducing-new-components) +- [Compatibility](#compatibility) +- [Compound components](#compound-components) +- [Components & Hooks](#components--hooks) +- [Naming Conventions](#naming-conventions) +- [TypeScript](#typescript) +- [Styling](#styling) +- [Context system](#context-system) +- [Unit tests](#unit-tests) +- [Storybook](#storybook) +- [Documentation](#documentation) +- [README example](#README-example) +- [Folder structure](#folder-structure) +- [Component versioning](#component-versioning) ## Introducing new components @@ -95,13 +95,13 @@ In these situations, one possible approach is to "soft-deprecate" a given legacy 2. Updating all places in Gutenberg that use that API. 3. Adding deprecation warnings (only after the previous point is completed, otherwise the Browser Console will be polluted by all those warnings and some e2e tests may fail). -When adding new components or new props to existing components, it's recommended to prefix them with `__unstable` or `__experimental` until they're stable enough to be exposed as part of the public API. +When adding new components or new props to existing components, it's recommended to create a [private version](/packages/private-apis/README.md)) of the component until the changes are stable enough to be exposed as part of the public API. ### Learn more -- [How to preserve backward compatibility for a React Component](/docs/contributors/code/backward-compatibility.md#how-to-preserve-backward-compatibility-for-a-react-component) -- [Experimental and Unstable APIs](/docs/contributors/code/coding-guidelines.md#experimental-and-unstable-apis) -- [Deprecating styles](#deprecating-styles) +- [How to preserve backward compatibility for a React Component](/docs/contributors/code/backward-compatibility.md#how-to-preserve-backward-compatibility-for-a-react-component) +- [Experimental and Unstable APIs](/docs/contributors/code/coding-guidelines.md#legacy-experimental-apis-plugin-only-apis-and-private-apis) +- [Deprecating styles](#deprecating-styles) <!-- ## Polymorphic Components (i.e. the `as` prop) @@ -121,20 +121,16 @@ When creating components that render a list of subcomponents, prefer to expose t ```jsx // ❌ Don't: <List - items={ [ - { value: 'Item 1' }, - { value: 'Item 2' }, - { value: 'Item 3' }, - ] } + items={ [ { value: 'Item 1' }, { value: 'Item 2' }, { value: 'Item 3' } ] } /> ``` ```jsx // ✅ Do: <List> - <ListItem value="Item 1" /> - <ListItem value="Item 2" /> - <ListItem value="Item 3" /> + <List.Item value="Item 1" /> + <List.Item value="Item 2" /> + <List.Item value="Item 3" /> </List> ``` @@ -185,25 +181,25 @@ One way to enable reusability and composition is to extract a component's underl ```tsx // in `hook.ts` -function useExampleComponent( props: PolymorphicComponentProps< ExampleProps, 'div' > ) { +function useExampleComponent( + props: PolymorphicComponentProps< ExampleProps, 'div' > +) { // Merge received props with the context system. - const { isVisible, className, ...otherProps } = useContextSystem( props, 'Example' ); + const { isVisible, className, ...otherProps } = useContextSystem( + props, + 'Example' + ); // Any other reusable rendering logic (e.g. computing className, state, event listeners...) const cx = useCx(); const classes = useMemo( - () => - cx( - styles.example, - isVisible && styles.visible, - className - ), + () => cx( styles.example, isVisible && styles.visible, className ), [ className, isVisible ] ); return { ...otherProps, - className: classes + className: classes, }; } @@ -220,8 +216,8 @@ function Example( A couple of good examples of how hooks are used for composition are: -- the `Card` component, which builds on top of the `Surface` component by [calling the `useSurface` hook inside its own hook](/packages/components/src/card/card/hook.ts); -- the `HStack` component, which builds on top of the `Flex` component and [calls the `useFlex` hook inside its own hook](/packages/components/src/h-stack/hook.tsx). +- the `Card` component, which builds on top of the `Surface` component by [calling the `useSurface` hook inside its own hook](/packages/components/src/card/card/hook.ts); +- the `HStack` component, which builds on top of the `Flex` component and [calls the `useFlex` hook inside its own hook](/packages/components/src/h-stack/hook.tsx). <!-- ## API Consinstency @@ -236,6 +232,95 @@ A couple of good examples of how hooks are used for composition are: TDB --> +## Naming Conventions + +It is recommended that compound components use dot notation to separate the namespace from the individual component names. The top-level compound component should be called the namespace (no dot notation). + +Dedicated React context should also use dot notation, while hooks should not. + +When exporting compound components and preparing them to be consumed, it is important that: + +- the JSDocs appear correctly in IntelliSense; +- the top-level component's JSDoc appears in the Storybook docs page; +- the top-level and subcomponent's prop types appear correctly in the Storybook props table. + +To meet the above requirements, we recommend: + +- using `Object.assign()` to add subcomponents as properties of the top-level component; +- using named functions for all components; +- setting explicitly the `displayName` on all subcomponents; +- adding the top-level JSDoc to the result of the `Object.assign` call; +- adding inline subcomponent JSDocs inside the `Object.assign` call. + +The following example implements all of the above recommendations. + +```tsx +//======================= +// Component.tsx +//======================= +import { forwardRef, createContext } from '@wordpress/element'; + +function UnforwardedTopLevelComponent( props, ref ) { + /* ... */ +} +const TopLevelComponent = forwardRef( UnforwardedTopLevelComponent ); + +function UnforwardedSubComponent( props, ref ) { + /* ... */ +} +const SubComponent = forwardRef( UnforwardedSubComponent ); +SubComponent.displayName = 'Component.SubComponent'; + +const Context = createContext(); + +/** The top-level component's JSDoc. */ +export const Component = Object.assign( TopLevelComponent, { + /** The subcomponent's JSDoc. */ + SubComponent, + /** The context's JSDoc. */ + Context, +} ); + +/** The hook's JSDoc. */ +export function useComponent() { + /* ... */ +} + +//======================= +// App.tsx +//======================= +import { Component, useComponent } from '@wordpress/components'; +import { useContext } from '@wordpress/element'; + +function CompoundComponentExample() { + return ( + <Component> + <Component.SubComponent /> + </Component> + ); +} + +function ContextProviderExample() { + return ( + <Component.Context.Provider value={ /* ... */ }> + { /* React tree */ } + </Component.Context.Provider> + ); +} + +function ContextConsumerExample() { + const componentContext = useContext( Component.Context ); + + // etc +} + +function HookExample() { + const hookReturnValue = useComponent(); + + // etc. +} +``` + ## TypeScript We strongly encourage using TypeScript for all new components. @@ -278,8 +363,10 @@ function UnconnectedMyComponent( // parameter (`div` in this example) // - the special `as` prop (which marks the component as polymorphic), // unless the third parameter is `false` - props: WordPressComponentProps< ComponentOwnProps, 'div', true > -) { /* ... */ } + props: WordPressComponentProps< ComponentOwnProps, 'div', true > +) { + /* ... */ +} ``` ### Considerations for the docgen @@ -287,10 +374,15 @@ function UnconnectedMyComponent( Make sure you have a **named** export for the component, not just the default export ([example](https://github.com/WordPress/gutenberg/blob/trunk/packages/components/src/divider/component.tsx)). This ensures that the docgen can properly extract the types data. The naming should be so that the connected/forwarded component has the plain component name (`MyComponent`), and the raw component is prefixed (`UnconnectedMyComponent` or `UnforwardedMyComponent`). This makes the component's `displayName` look nicer in React devtools and in the autogenerated Storybook code snippets. ```js -function UnconnectedMyComponent() { /* ... */ } +function UnconnectedMyComponent() { + /* ... */ +} // 👇 Without this named export, the docgen will not work! -export const MyComponent = contextConnect( UnconnectedMyComponent, 'MyComponent' ); +export const MyComponent = contextConnect( + UnconnectedMyComponent, + 'MyComponent' +); export default MyComponent; ``` @@ -314,16 +406,15 @@ Changing the styles of a non-experimental component must be done with care. To p import deprecated from '@wordpress/deprecated'; import { Wrapper } from './styles.ts'; -function MyComponent({ __nextHasNoOuterMargins = false }) { +function MyComponent( { __nextHasNoOuterMargins = false } ) { if ( ! __nextHasNoOuterMargins ) { deprecated( 'Outer margin styles for wp.components.MyComponent', { since: '6.0', version: '6.2', // Set a reasonable grace period depending on impact - hint: - 'Set the `__nextHasNoOuterMargins` prop to true to start opting into the new styles, which will become the default in a future version.', + hint: 'Set the `__nextHasNoOuterMargins` prop to true to start opting into the new styles, which will become the default in a future version.', } ); } - return <Wrapper __nextHasNoOuterMargins={__nextHasNoOuterMargins} /> + return <Wrapper __nextHasNoOuterMargins={ __nextHasNoOuterMargins } />; } ``` @@ -331,7 +422,7 @@ Styles should be structured so the deprecated styles are cleanly encapsulated, a ```js // styles.ts -const deprecatedMargins = ({ __nextHasNoOuterMargins }) => { +const deprecatedMargins = ( { __nextHasNoOuterMargins } ) => { if ( ! __nextHasNoOuterMargins ) { return css` margin: 8px; @@ -342,7 +433,7 @@ const deprecatedMargins = ({ __nextHasNoOuterMargins }) => { export const Wrapper = styled.div` margin: 0; - ${deprecatedMargins} + ${ deprecatedMargins } `; ``` @@ -358,14 +449,14 @@ Not all style changes justify a formal deprecation process. The main thing to lo ##### DOES need formal deprecation -- Removing an outer margin. -- Substantial changes to width/height, such as adding or removing a size restriction. +- Removing an outer margin. +- Substantial changes to width/height, such as adding or removing a size restriction. ##### DOES NOT need formal deprecation -- Breakage only occurs in non-standard usage, such as when the consumer is overriding component internals. -- Minor layout shifts of a few pixels. -- Internal layout changes of a higher-level component. +- Breakage only occurs in non-standard usage, such as when the consumer is overriding component internals. +- Minor layout shifts of a few pixels. +- Internal layout changes of a higher-level component. ## Context system @@ -373,9 +464,9 @@ The `@wordpress/components` context system is based on [React's `Context` API](h Components can use this system via a couple of functions: -- they can provide values using a shared `ContextSystemProvider` component -- they can connect to the Context via `contextConnect` -- they can read the "computed" values from the context via `useContextSystem` +- they can provide values using a shared `ContextSystemProvider` component +- they can connect to the Context via `contextConnect` +- they can read the "computed" values from the context via `useContextSystem` An example of how this is used can be found in the [`Card` component family](/packages/components/src/card). For example, this is how the `Card` component injects the `size` and `isBorderless` props down to its `CardBody` subcomponent — which makes it use the correct spacing and border settings "auto-magically". @@ -400,11 +491,7 @@ export function useCard( props ) { import { contextConnect, ContextSystemProvider } from '../../context'; function Card( props, forwardedRef ) { - const { - size, - isBorderless, - ...otherComputedHookProps - } = useCard( props ); + const { size, isBorderless, ...otherComputedHookProps } = useCard( props ); // [...] @@ -441,7 +528,10 @@ export function useCardBody( props ) { // If a `CardBody` component is rendered as a child of a `Card` component, the value of // the `size` prop will be the one set by the parent `Card` component via the Context // System (unless the prop gets explicitely set on the `CardBody` component). - const { size = 'medium', ...otherDerivedProps } = useContextSystem( props, 'CardBody' ); + const { size = 'medium', ...otherDerivedProps } = useContextSystem( + props, + 'CardBody' + ); // [...] @@ -457,7 +547,7 @@ Please refer to the [JavaScript Testing Overview docs](/docs/contributors/code/t All new components should add stories to the project's [Storybook](https://storybook.js.org/). Each [story](https://storybook.js.org/docs/react/get-started/whats-a-story) captures the rendered state of a UI component in isolation. This greatly simplifies working on a given component, while also serving as an interactive form of documentation. -A component's story should be showcasing its different states — for example, the different variants of a `Button`: +A component's story should be showcasing its different states — for example, the different variants of a `Button`: ```jsx import Button from '../'; @@ -543,6 +633,7 @@ Prop description. With a new line before and after the description and before an Add this section when there are props that are drilled down into an internal component. See [ClipboardButton](/packages/components/src/clipboard-button/README.md) for an example. <!-- Only add the next section if the component relies on the [Context System](#context-system) --> + ## Context See examples for this section for the [ItemGroup](/packages/components/src/item-group/item-group/README.md#context) and [`Card`](/packages/components/src/card/card/README.md#context) components. @@ -601,8 +692,8 @@ As the needs of the package evolve with time, sometimes we may opt to fully rewr Here is some terminology that will be used in the upcoming sections: -- "Legacy" component: the version(s) of the component that existsted on `trunk` before the rewrite; -- API surface: the component's public APIs. It includes the list of components (and sub-components) exported from the package, their props, any associated React context. It does not include internal classnames and internal DOM structure of the components. +- "Legacy" component: the version(s) of the component that existsted on `trunk` before the rewrite; +- API surface: the component's public APIs. It includes the list of components (and subcomponents) exported from the package, their props, any associated React context. It does not include internal classnames and internal DOM structure of the components. ### Approaches From 7661f457c867906d57ea19f05becef217a1ad31c Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Thu, 8 Aug 2024 11:01:34 +0100 Subject: [PATCH 0309/1908] Stop unwanted drag and drop operations within section Patterns in Zoom Out mode (#64331) * Fix conditionals * Disable horizontal insertion points to prioritise dropping between sections --- .../components/block-tools/insertion-point.js | 11 +++++++++++ .../src/components/inner-blocks/index.js | 19 ++++++++++--------- 2 files changed, 21 insertions(+), 9 deletions(-) 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 9dac99e5e93124..469f7e53908cb4 100644 --- a/packages/block-editor/src/components/block-tools/insertion-point.js +++ b/packages/block-editor/src/components/block-tools/insertion-point.js @@ -38,6 +38,7 @@ function InbetweenInsertionPointPopover( { isInserterShown, isDistractionFree, isNavigationMode, + isZoomOutMode, } = useSelect( ( select ) => { const { getBlockOrder, @@ -48,6 +49,7 @@ function InbetweenInsertionPointPopover( { getNextBlockClientId, getSettings, isNavigationMode: _isNavigationMode, + __unstableGetEditorMode, } = select( blockEditorStore ); const insertionPoint = getBlockInsertionPoint(); const order = getBlockOrder( insertionPoint.rootClientId ); @@ -79,6 +81,7 @@ function InbetweenInsertionPointPopover( { isNavigationMode: _isNavigationMode(), isDistractionFree: settings.isDistractionFree, isInserterShown: insertionPoint?.__unstableWithInserter, + isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', }; }, [] ); const { getBlockEditingMode } = useSelect( blockEditorStore ); @@ -145,6 +148,14 @@ function InbetweenInsertionPointPopover( { return null; } + // Zoom out mode should only show the insertion point for the insert operation. + // Other operations such as "group" are when the editor tries to create a row + // block by grouping the block being dragged with the block it's being dropped + // onto. + if ( isZoomOutMode && operation !== 'insert' ) { + return null; + } + const orientationClassname = orientation === 'horizontal' || operation === 'group' ? 'is-horizontal' diff --git a/packages/block-editor/src/components/inner-blocks/index.js b/packages/block-editor/src/components/inner-blocks/index.js index 27e5064eeb6328..c8db9f8cebf905 100644 --- a/packages/block-editor/src/components/inner-blocks/index.js +++ b/packages/block-editor/src/components/inner-blocks/index.js @@ -206,13 +206,7 @@ export function useInnerBlocksProps( props = {}, options = {} ) { getSettings, } = unlock( select( blockEditorStore ) ); let _isDropZoneDisabled; - // In zoom out mode, we want to disable the drop zone for the sections. - // The inner blocks belonging to the section drop zone is - // already disabled by the blocks themselves being disabled. - if ( __unstableGetEditorMode() === 'zoom-out' ) { - const { sectionRootClientId } = unlock( getSettings() ); - _isDropZoneDisabled = clientId !== sectionRootClientId; - } + if ( ! clientId ) { return { isDropZoneDisabled: _isDropZoneDisabled }; } @@ -225,8 +219,15 @@ export function useInnerBlocksProps( props = {}, options = {} ) { const parentClientId = getBlockRootClientId( clientId ); const [ defaultLayout ] = getBlockSettings( clientId, 'layout' ); - if ( _isDropZoneDisabled !== undefined ) { - _isDropZoneDisabled = blockEditingMode === 'disabled'; + _isDropZoneDisabled = blockEditingMode === 'disabled'; + + if ( __unstableGetEditorMode() === 'zoom-out' ) { + // In zoom out mode, we want to disable the drop zone for the sections. + // The inner blocks belonging to the section drop zone is + // already disabled by the blocks themselves being disabled. + const { sectionRootClientId } = unlock( getSettings() ); + + _isDropZoneDisabled = clientId !== sectionRootClientId; } return { From 098c1a2e45d3daa1353af6e26e9f518a06392865 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Thu, 8 Aug 2024 13:14:59 +0200 Subject: [PATCH 0310/1908] DataViews: abandon the ItemRecord type (#64367) Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/dataviews/src/normalize-fields.ts | 6 ++---- packages/dataviews/src/types.ts | 24 +++++++--------------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index 8cd9051cbb1cc3..680749df5344a6 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -2,7 +2,7 @@ * Internal dependencies */ import getFieldTypeDefinition from './field-types'; -import type { Field, NormalizedField, ItemRecord } from './types'; +import type { Field, NormalizedField } from './types'; /** * Apply default values and normalize the fields config. @@ -17,9 +17,7 @@ export function normalizeFields< Item >( const fieldTypeDefinition = getFieldTypeDefinition( field.type ); const getValue = - field.getValue || - // @ts-ignore - ( ( { item }: { item: ItemRecord } ) => item[ field.id ] ); + field.getValue || ( ( { item } ) => ( item as any )[ field.id ] ); const sort = field.sort ?? diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 64580a089997d1..b0873e9c677f53 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -47,8 +47,6 @@ export type Operator = | 'isAll' | 'isNotAll'; -export type ItemRecord = Object; - export type FieldType = 'text' | 'integer'; export type ValidationContext = { @@ -128,21 +126,13 @@ export type Field< Item > = { * Filter config for the field. */ filterBy?: FilterByConfig | undefined; -} & ( Item extends ItemRecord - ? { - /** - * Callback used to retrieve the value of the field from the item. - * Defaults to `item[ field.id ]`. - */ - getValue?: ( args: { item: Item } ) => any; - } - : { - /** - * Callback used to retrieve the value of the field from the item. - * Defaults to `item[ field.id ]`. - */ - getValue: ( args: { item: Item } ) => any; - } ); + + /** + * Callback used to retrieve the value of the field from the item. + * Defaults to `item[ field.id ]`. + */ + getValue?: ( args: { item: Item } ) => any; +}; export type NormalizedField< Item > = Field< Item > & { label: string; From 3a21676ea456e3484949475c9b654de3e252ac45 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 8 Aug 2024 13:16:01 +0200 Subject: [PATCH 0311/1908] DataViews Extensibility: Allow unregistering the rename post action (#64366) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../src/components/post-actions/actions.js | 132 +--------------- .../src/dataviews/actions/rename-post.tsx | 146 ++++++++++++++++++ .../editor/src/dataviews/actions/utils.ts | 14 +- .../src/dataviews/store/private-actions.ts | 4 +- packages/editor/src/dataviews/types.ts | 16 +- 5 files changed, 174 insertions(+), 138 deletions(-) create mode 100644 packages/editor/src/dataviews/actions/rename-post.tsx diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 64afec2417cd05..490bab2cc2fa4b 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -14,7 +14,6 @@ import { parse } from '@wordpress/blocks'; import { DataForm } from '@wordpress/dataviews'; import { Button, - TextControl, __experimentalHStack as HStack, __experimentalVStack as VStack, } from '@wordpress/components'; @@ -23,7 +22,6 @@ import { * Internal dependencies */ import { - TEMPLATE_ORIGINS, TEMPLATE_PART_POST_TYPE, TEMPLATE_POST_TYPE, PATTERN_POST_TYPE, @@ -34,7 +32,7 @@ import { CreateTemplatePartModalContents } from '../create-template-part-modal'; import { getItemTitle } from '../../dataviews/actions/utils'; // Patterns. -const { PATTERN_TYPES, CreatePatternModalContents, useDuplicatePatternProps } = +const { CreatePatternModalContents, useDuplicatePatternProps } = unlock( patternsPrivateApis ); // TODO: this should be shared with other components (see post-fields in edit-site). @@ -58,25 +56,6 @@ const formDuplicateAction = { fields: [ 'title' ], }; -/** - * Check if a template is removable. - * - * @param {Object} template The template entity to check. - * @return {boolean} Whether the template is removable. - */ -function isTemplateRemovable( template ) { - if ( ! template ) { - return false; - } - // In patterns list page we map the templates parts to a different object - // than the one returned from the endpoint. This is why we need to check for - // two props whether is custom or has a theme file. - return ( - template?.source === TEMPLATE_ORIGINS.custom && - ! template?.has_theme_file - ); -} - const viewPostAction = { id: 'view-post', label: __( 'View' ), @@ -128,112 +107,6 @@ const postRevisionsAction = { }, }; -const renamePostAction = { - id: 'rename-post', - label: __( 'Rename' ), - isEligible( post ) { - if ( post.status === 'trash' ) { - return false; - } - // Templates, template parts and patterns have special checks for renaming. - if ( - ! [ - TEMPLATE_POST_TYPE, - TEMPLATE_PART_POST_TYPE, - ...Object.values( PATTERN_TYPES ), - ].includes( post.type ) - ) { - return post.permissions?.update; - } - // In the case of templates, we can only rename custom templates. - if ( post.type === TEMPLATE_POST_TYPE ) { - return ( - isTemplateRemovable( post ) && - post.is_custom && - post.permissions?.update - ); - } - // Make necessary checks for template parts and patterns. - const isTemplatePart = post.type === TEMPLATE_PART_POST_TYPE; - const isUserPattern = post.type === PATTERN_TYPES.user; - // In patterns list page we map the templates parts to a different object - // than the one returned from the endpoint. This is why we need to check for - // two props whether is custom or has a theme file. - const isCustomPattern = - isUserPattern || - ( isTemplatePart && post.source === TEMPLATE_ORIGINS.custom ); - const hasThemeFile = post?.has_theme_file; - return isCustomPattern && ! hasThemeFile && post.permissions?.update; - }, - RenderModal: ( { items, closeModal, onActionPerformed } ) => { - const [ item ] = items; - const [ title, setTitle ] = useState( () => getItemTitle( item ) ); - const { editEntityRecord, saveEditedEntityRecord } = - useDispatch( coreStore ); - const { createSuccessNotice, createErrorNotice } = - useDispatch( noticesStore ); - - async function onRename( event ) { - event.preventDefault(); - try { - await editEntityRecord( 'postType', item.type, item.id, { - title, - } ); - // Update state before saving rerenders the list. - setTitle( '' ); - closeModal(); - // Persist edited entity. - await saveEditedEntityRecord( 'postType', item.type, item.id, { - throwOnError: true, - } ); - createSuccessNotice( __( 'Name updated' ), { - type: 'snackbar', - } ); - onActionPerformed?.( items ); - } catch ( error ) { - const errorMessage = - error.message && error.code !== 'unknown_error' - ? error.message - : __( 'An error occurred while updating the name' ); - createErrorNotice( errorMessage, { type: 'snackbar' } ); - } - } - - return ( - <form onSubmit={ onRename }> - <VStack spacing="5"> - <TextControl - __nextHasNoMarginBottom - __next40pxDefaultSize - label={ __( 'Name' ) } - value={ title } - onChange={ setTitle } - required - /> - <HStack justify="right"> - <Button - __next40pxDefaultSize - variant="tertiary" - onClick={ () => { - closeModal(); - } } - > - { __( 'Cancel' ) } - </Button> - <Button - __next40pxDefaultSize - variant="primary" - type="submit" - > - { __( 'Save' ) } - </Button> - </HStack> - </VStack> - </form> - ); - }, -}; - const useDuplicatePostAction = ( postType ) => { const userCanCreatePost = useSelect( ( select ) => { @@ -494,7 +367,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { const isPattern = postType === PATTERN_POST_TYPE; const isLoaded = !! postTypeObject; const supportsRevisions = !! postTypeObject?.supports?.revisions; - const supportsTitle = !! postTypeObject?.supports?.title; return useMemo( () => { if ( ! isLoaded ) { return []; @@ -512,7 +384,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { userCanCreatePostType && duplicateTemplatePartAction, isPattern && userCanCreatePostType && duplicatePatternAction, - supportsTitle && renamePostAction, ...defaultActions, ].filter( Boolean ); // Filter actions based on provided context. If not provided @@ -586,7 +457,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { onActionPerformed, isLoaded, supportsRevisions, - supportsTitle, context, ] ); } diff --git a/packages/editor/src/dataviews/actions/rename-post.tsx b/packages/editor/src/dataviews/actions/rename-post.tsx new file mode 100644 index 00000000000000..ef9da271111ea2 --- /dev/null +++ b/packages/editor/src/dataviews/actions/rename-post.tsx @@ -0,0 +1,146 @@ +/** + * WordPress dependencies + */ +import { useDispatch } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { __ } from '@wordpress/i18n'; +import { useState } from '@wordpress/element'; +// @ts-ignore +import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; +import { + Button, + TextControl, + __experimentalHStack as HStack, + __experimentalVStack as VStack, +} from '@wordpress/components'; +import type { Action } from '@wordpress/dataviews'; +import { store as noticesStore } from '@wordpress/notices'; + +/** + * Internal dependencies + */ +import { + TEMPLATE_ORIGINS, + TEMPLATE_PART_POST_TYPE, + TEMPLATE_POST_TYPE, +} from '../../store/constants'; +import { unlock } from '../../lock-unlock'; +import { + getItemTitle, + isTemplateRemovable, + isTemplate, + isTemplatePart, +} from './utils'; +import type { CoreDataError, PostWithPermissions } from '../types'; + +// Patterns. +const { PATTERN_TYPES } = unlock( patternsPrivateApis ); + +const renamePost: Action< PostWithPermissions > = { + id: 'rename-post', + label: __( 'Rename' ), + isEligible( post ) { + if ( post.status === 'trash' ) { + return false; + } + // Templates, template parts and patterns have special checks for renaming. + if ( + ! [ + TEMPLATE_POST_TYPE, + TEMPLATE_PART_POST_TYPE, + ...Object.values( PATTERN_TYPES ), + ].includes( post.type ) + ) { + return post.permissions?.update; + } + + // In the case of templates, we can only rename custom templates. + if ( isTemplate( post ) ) { + return ( + isTemplateRemovable( post ) && + post.is_custom && + post.permissions?.update + ); + } + + if ( isTemplatePart( post ) ) { + return ( + post.source === TEMPLATE_ORIGINS.custom && + ! post?.has_theme_file && + post.permissions?.update + ); + } + + return post.type === PATTERN_TYPES.user && post.permissions?.update; + }, + RenderModal: ( { items, closeModal, onActionPerformed } ) => { + const [ item ] = items; + const [ title, setTitle ] = useState( () => getItemTitle( item ) ); + const { editEntityRecord, saveEditedEntityRecord } = + useDispatch( coreStore ); + const { createSuccessNotice, createErrorNotice } = + useDispatch( noticesStore ); + + async function onRename( event: React.FormEvent ) { + event.preventDefault(); + try { + await editEntityRecord( 'postType', item.type, item.id, { + title, + } ); + // Update state before saving rerenders the list. + setTitle( '' ); + closeModal?.(); + // Persist edited entity. + await saveEditedEntityRecord( 'postType', item.type, item.id, { + throwOnError: true, + } ); + createSuccessNotice( __( 'Name updated' ), { + type: 'snackbar', + } ); + onActionPerformed?.( items ); + } catch ( error ) { + const typedError = error as CoreDataError; + const errorMessage = + typedError.message && typedError.code !== 'unknown_error' + ? typedError.message + : __( 'An error occurred while updating the name' ); + createErrorNotice( errorMessage, { type: 'snackbar' } ); + } + } + + return ( + <form onSubmit={ onRename }> + <VStack spacing="5"> + <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize + label={ __( 'Name' ) } + value={ title } + onChange={ setTitle } + required + /> + <HStack justify="right"> + <Button + __next40pxDefaultSize + variant="tertiary" + onClick={ () => { + closeModal?.(); + } } + > + { __( 'Cancel' ) } + </Button> + <Button + __next40pxDefaultSize + variant="primary" + type="submit" + > + { __( 'Save' ) } + </Button> + </HStack> + </VStack> + </form> + ); + }, +}; + +export default renamePost; diff --git a/packages/editor/src/dataviews/actions/utils.ts b/packages/editor/src/dataviews/actions/utils.ts index 56c8c9f54c8507..7da1f71728365b 100644 --- a/packages/editor/src/dataviews/actions/utils.ts +++ b/packages/editor/src/dataviews/actions/utils.ts @@ -12,11 +12,19 @@ import { TEMPLATE_POST_TYPE, } from '../../store/constants'; -import type { Post, TemplateOrTemplatePart } from '../types'; +import type { Post, TemplatePart, Template } from '../types'; + +export function isTemplate( post: Post ): post is Template { + return post.type === TEMPLATE_POST_TYPE; +} + +export function isTemplatePart( post: Post ): post is TemplatePart { + return post.type === TEMPLATE_PART_POST_TYPE; +} export function isTemplateOrTemplatePart( p: Post -): p is TemplateOrTemplatePart { +): p is Template | TemplatePart { return p.type === TEMPLATE_POST_TYPE || p.type === TEMPLATE_PART_POST_TYPE; } @@ -39,7 +47,7 @@ export function getItemTitle( item: Post ) { * @param template The template entity to check. * @return Whether the template is removable. */ -export function isTemplateRemovable( template: TemplateOrTemplatePart ) { +export function isTemplateRemovable( template: Template | TemplatePart ) { if ( ! template ) { return false; } diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index d5e12e298039a1..a8b1573a528b50 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -13,8 +13,9 @@ import exportPattern from '../actions/export-pattern'; import resetPost from '../actions/reset-post'; import trashPost from '../actions/trash-post'; import permanentlyDeletePost from '../actions/permanently-delete-post'; -import restorePost from '../actions/restore-post'; +import renamePost from '../actions/rename-post'; import reorderPage from '../actions/reorder-page'; +import restorePost from '../actions/restore-post'; import type { PostType } from '../types'; import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; @@ -74,6 +75,7 @@ export const registerPostTypeActions = .getPostType( postType ) ) as PostType; const actions = [ + postTypeConfig.supports?.title ? renamePost : undefined, postTypeConfig?.supports?.[ 'page-attributes' ] ? reorderPage : undefined, diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts index 0c31bef195eb9b..80b6f3c5ceb852 100644 --- a/packages/editor/src/dataviews/types.ts +++ b/packages/editor/src/dataviews/types.ts @@ -13,8 +13,17 @@ export interface BasePost { type: string; id: string | number; } -export interface TemplateOrTemplatePart extends BasePost { - type: 'wp_template' | 'wp_template_part'; + +export interface Template extends BasePost { + type: 'wp_template'; + is_custom: boolean; + source: string; + has_theme_file: boolean; + id: string; +} + +export interface TemplatePart extends BasePost { + type: 'wp_template_part'; source: string; has_theme_file: boolean; id: string; @@ -31,7 +40,7 @@ export interface PostWithPageAttributesSupport extends BasePost { menu_order: number; } -export type Post = TemplateOrTemplatePart | Pattern | BasePost; +export type Post = Template | TemplatePart | Pattern | BasePost; export type PostWithPermissions = Post & { permissions: { @@ -44,6 +53,7 @@ export interface PostType { slug: string; supports?: { 'page-attributes'?: boolean; + title?: boolean; }; } From 5d408ce8849e6183cb39f48b071400b04a1cde78 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 8 Aug 2024 16:19:58 +0200 Subject: [PATCH 0312/1908] DataViews Extensibility: Allow unregistering the duplicate pattern action (#64373) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../src/components/post-actions/actions.js | 27 ------------- .../dataviews/actions/duplicate-pattern.tsx | 40 +++++++++++++++++++ .../src/dataviews/store/private-actions.ts | 11 +++++ 3 files changed, 51 insertions(+), 27 deletions(-) create mode 100644 packages/editor/src/dataviews/actions/duplicate-pattern.tsx diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 490bab2cc2fa4b..fcad5b97a13002 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -9,7 +9,6 @@ import { store as coreStore } from '@wordpress/core-data'; import { __, sprintf, _x } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; import { useMemo, useState, useEffect } from '@wordpress/element'; -import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; import { parse } from '@wordpress/blocks'; import { DataForm } from '@wordpress/dataviews'; import { @@ -31,10 +30,6 @@ import { unlock } from '../../lock-unlock'; import { CreateTemplatePartModalContents } from '../create-template-part-modal'; import { getItemTitle } from '../../dataviews/actions/utils'; -// Patterns. -const { CreatePatternModalContents, useDuplicatePatternProps } = - unlock( patternsPrivateApis ); - // TODO: this should be shared with other components (see post-fields in edit-site). const fields = [ { @@ -268,27 +263,6 @@ const useDuplicatePostAction = ( postType ) => { ); }; -export const duplicatePatternAction = { - id: 'duplicate-pattern', - label: _x( 'Duplicate', 'action label' ), - isEligible: ( item ) => item.type !== TEMPLATE_PART_POST_TYPE, - modalHeader: _x( 'Duplicate pattern', 'action label' ), - RenderModal: ( { items, closeModal } ) => { - const [ item ] = items; - const duplicatedProps = useDuplicatePatternProps( { - pattern: item, - onSuccess: () => closeModal(), - } ); - return ( - <CreatePatternModalContents - onClose={ closeModal } - confirmLabel={ _x( 'Duplicate', 'action label' ) } - { ...duplicatedProps } - /> - ); - }, -}; - export const duplicateTemplatePartAction = { id: 'duplicate-template-part', label: _x( 'Duplicate', 'action label' ), @@ -383,7 +357,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { isTemplateOrTemplatePart && userCanCreatePostType && duplicateTemplatePartAction, - isPattern && userCanCreatePostType && duplicatePatternAction, ...defaultActions, ].filter( Boolean ); // Filter actions based on provided context. If not provided diff --git a/packages/editor/src/dataviews/actions/duplicate-pattern.tsx b/packages/editor/src/dataviews/actions/duplicate-pattern.tsx new file mode 100644 index 00000000000000..98f43a27c3628c --- /dev/null +++ b/packages/editor/src/dataviews/actions/duplicate-pattern.tsx @@ -0,0 +1,40 @@ +/** + * WordPress dependencies + */ +import { _x } from '@wordpress/i18n'; +// @ts-ignore +import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; +import type { Action } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; +import type { Pattern } from '../types'; + +// Patterns. +const { CreatePatternModalContents, useDuplicatePatternProps } = + unlock( patternsPrivateApis ); + +const duplicatePattern: Action< Pattern > = { + id: 'duplicate-pattern', + label: _x( 'Duplicate', 'action label' ), + isEligible: ( item ) => item.type !== 'wp_template_part', + modalHeader: _x( 'Duplicate pattern', 'action label' ), + RenderModal: ( { items, closeModal } ) => { + const [ item ] = items; + const duplicatedProps = useDuplicatePatternProps( { + pattern: item, + onSuccess: () => closeModal?.(), + } ); + return ( + <CreatePatternModalContents + onClose={ closeModal } + confirmLabel={ _x( 'Duplicate', 'action label' ) } + { ...duplicatedProps } + /> + ); + }, +}; + +export default duplicatePattern; diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index a8b1573a528b50..6854c29bb0c4e4 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -9,6 +9,7 @@ import { doAction } from '@wordpress/hooks'; * Internal dependencies */ import deletePost from '../actions/delete-post'; +import duplicatePattern from '../actions/duplicate-pattern'; import exportPattern from '../actions/export-pattern'; import resetPost from '../actions/reset-post'; import trashPost from '../actions/trash-post'; @@ -74,7 +75,17 @@ export const registerPostTypeActions = .resolveSelect( coreStore ) .getPostType( postType ) ) as PostType; + const canCreate = await registry + .resolveSelect( coreStore ) + .canUser( 'create', { + kind: 'postType', + name: postType, + } ); + const actions = [ + canCreate && postTypeConfig.slug === 'wp_block' + ? duplicatePattern + : undefined, postTypeConfig.supports?.title ? renamePost : undefined, postTypeConfig?.supports?.[ 'page-attributes' ] ? reorderPage From c48075b6665ec3910d00677088672c1ba9e24916 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Thu, 8 Aug 2024 16:21:26 +0100 Subject: [PATCH 0313/1908] Reduce gap between steps in SpacingSizesControl, add animation, remove first/last marks (#63803) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: paaljoachim <paaljoachim@git.wordpress.org> Co-authored-by: bgardner <bgardner@git.wordpress.org> --- .../input-controls/spacing-input-control.js | 10 +++++---- .../spacing-sizes-control/style.scss | 22 ++++++++++++++----- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js index 4faf05ba254089..5cdfe47c452b23 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js +++ b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js @@ -188,10 +188,12 @@ export default function SpacingInputControl( { name: size.name, } ) ); - const marks = spacingSizes.map( ( _newValue, index ) => ( { - value: index, - label: undefined, - } ) ); + const marks = spacingSizes + .slice( 1, spacingSizes.length - 1 ) + .map( ( _newValue, index ) => ( { + value: index + 1, + label: undefined, + } ) ); const sideLabel = ALL_SIDES.includes( side ) && showSideInLabel ? LABELS[ side ] : ''; diff --git a/packages/block-editor/src/components/spacing-sizes-control/style.scss b/packages/block-editor/src/components/spacing-sizes-control/style.scss index 2fb33b5c565fba..69f30a8c7d1e90 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/style.scss +++ b/packages/block-editor/src/components/spacing-sizes-control/style.scss @@ -4,6 +4,18 @@ margin-bottom: 0; } + .is-marked { + .components-range-control__track { + transition: width ease 0.1s; + @include reduce-motion("transition"); + } + + .components-range-control__thumb-wrapper { + transition: left ease 0.1s; + @include reduce-motion("transition"); + } + } + .spacing-sizes-control__range-control, .spacing-sizes-control__custom-value-range { height: 40px; @@ -20,18 +32,16 @@ } .components-range-control__mark { + transform: translateX(-50%); height: $grid-unit-05; - width: 3px; - background-color: #fff; + width: math.div($grid-unit-05, 2); + background-color: $white; z-index: 1; + top: -#{$grid-unit-05}; } .components-range-control__marks { margin-top: 17px; - - :first-child { - display: none; - } } .components-range-control__thumb-wrapper { From 88127e20ff7386ae75417ee4c6f5e19b11d542ca Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 8 Aug 2024 20:30:54 +0400 Subject: [PATCH 0314/1908] Block Editor: Don't hide the toolbar for an empty default block in HTML mode (#64374) Unlinked contributors: designsimply. Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: Thelmachido <thelmachido@git.wordpress.org> Co-authored-by: mboynes <mboynes@git.wordpress.org> --- .../src/components/block-tools/use-show-block-tools.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-tools/use-show-block-tools.js b/packages/block-editor/src/components/block-tools/use-show-block-tools.js index 33807445b8da74..07e0ebd16a64b0 100644 --- a/packages/block-editor/src/components/block-tools/use-show-block-tools.js +++ b/packages/block-editor/src/components/block-tools/use-show-block-tools.js @@ -20,6 +20,7 @@ export function useShowBlockTools() { getSelectedBlockClientId, getFirstMultiSelectedBlockClientId, getBlock, + getBlockMode, getSettings, hasMultiSelection, __unstableGetEditorMode, @@ -33,7 +34,9 @@ export function useShowBlockTools() { const editorMode = __unstableGetEditorMode(); const hasSelectedBlock = !! clientId && !! block; const isEmptyDefaultBlock = - hasSelectedBlock && isUnmodifiedDefaultBlock( block ); + hasSelectedBlock && + isUnmodifiedDefaultBlock( block ) && + getBlockMode( clientId ) !== 'html'; const _showEmptyBlockSideInserter = clientId && ! isTyping() && From c495c7d21e3d0c3a6d3981a332202a0dd5d11ba5 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 8 Aug 2024 20:34:09 +0400 Subject: [PATCH 0315/1908] Upgrade Playwright to v1.46 (#64372) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> --- package-lock.json | 48 +++++++++++++++++------------------ package.json | 2 +- packages/scripts/package.json | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/package-lock.json b/package-lock.json index b0eccc961afb78..66c32076d3b364 100644 --- a/package-lock.json +++ b/package-lock.json @@ -99,7 +99,7 @@ "@octokit/rest": "16.26.0", "@octokit/types": "6.34.0", "@octokit/webhooks-types": "5.8.0", - "@playwright/test": "1.45.1", + "@playwright/test": "1.46.0", "@pmmmwh/react-refresh-webpack-plugin": "0.5.11", "@react-native/babel-preset": "0.73.10", "@react-native/metro-babel-transformer": "0.73.10", @@ -6950,12 +6950,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.45.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.1.tgz", - "integrity": "sha512-Wo1bWTzQvGA7LyKGIZc8nFSTFf2TkthGIFBR+QVNilvwouGzFd4PYukZe3rvf5PSqjHi1+1NyKSDZKcQWETzaA==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.46.0.tgz", + "integrity": "sha512-/QYft5VArOrGRP5pgkrfKksqsKA6CEFyGQ/gjNe6q0y4tZ1aaPfq4gIjudr1s3D+pXyrPRdsy4opKDrjBabE5w==", "dev": true, "dependencies": { - "playwright": "1.45.1" + "playwright": "1.46.0" }, "bin": { "playwright": "cli.js" @@ -41083,12 +41083,12 @@ "dev": true }, "node_modules/playwright": { - "version": "1.45.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.1.tgz", - "integrity": "sha512-Hjrgae4kpSQBr98nhCj3IScxVeVUixqj+5oyif8TdIn2opTCPEzqAqNMeK42i3cWDCVu9MI+ZsGWw+gVR4ISBg==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.0.tgz", + "integrity": "sha512-XYJ5WvfefWONh1uPAUAi0H2xXV5S3vrtcnXe6uAOgdGi3aSpqOSXX08IAjXW34xitfuOJsvXU5anXZxPSEQiJw==", "dev": true, "dependencies": { - "playwright-core": "1.45.1" + "playwright-core": "1.46.0" }, "bin": { "playwright": "cli.js" @@ -41101,9 +41101,9 @@ } }, "node_modules/playwright-core": { - "version": "1.45.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.1.tgz", - "integrity": "sha512-LF4CUUtrUu2TCpDw4mcrAIuYrEjVDfT1cHbJMfwnE2+1b8PZcFzPNgvZCvq2JfQ4aTjRCCHw5EJ2tmr2NSzdPg==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.0.tgz", + "integrity": "sha512-9Y/d5UIwuJk8t3+lhmMSAJyNP1BUC/DqP3cQJDQQL/oWqAiuPTLgy7Q5dzglmTLwcBRdetzgNM/gni7ckfTr6A==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -54585,7 +54585,7 @@ "npm": ">=8.19.2" }, "peerDependencies": { - "@playwright/test": "^1.45.1", + "@playwright/test": "^1.46.0", "react": "^18.0.0", "react-dom": "^18.0.0" } @@ -60001,12 +60001,12 @@ } }, "@playwright/test": { - "version": "1.45.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.1.tgz", - "integrity": "sha512-Wo1bWTzQvGA7LyKGIZc8nFSTFf2TkthGIFBR+QVNilvwouGzFd4PYukZe3rvf5PSqjHi1+1NyKSDZKcQWETzaA==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.46.0.tgz", + "integrity": "sha512-/QYft5VArOrGRP5pgkrfKksqsKA6CEFyGQ/gjNe6q0y4tZ1aaPfq4gIjudr1s3D+pXyrPRdsy4opKDrjBabE5w==", "dev": true, "requires": { - "playwright": "1.45.1" + "playwright": "1.46.0" } }, "@pmmmwh/react-refresh-webpack-plugin": { @@ -87337,19 +87337,19 @@ "dev": true }, "playwright": { - "version": "1.45.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.1.tgz", - "integrity": "sha512-Hjrgae4kpSQBr98nhCj3IScxVeVUixqj+5oyif8TdIn2opTCPEzqAqNMeK42i3cWDCVu9MI+ZsGWw+gVR4ISBg==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.0.tgz", + "integrity": "sha512-XYJ5WvfefWONh1uPAUAi0H2xXV5S3vrtcnXe6uAOgdGi3aSpqOSXX08IAjXW34xitfuOJsvXU5anXZxPSEQiJw==", "dev": true, "requires": { "fsevents": "2.3.2", - "playwright-core": "1.45.1" + "playwright-core": "1.46.0" } }, "playwright-core": { - "version": "1.45.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.1.tgz", - "integrity": "sha512-LF4CUUtrUu2TCpDw4mcrAIuYrEjVDfT1cHbJMfwnE2+1b8PZcFzPNgvZCvq2JfQ4aTjRCCHw5EJ2tmr2NSzdPg==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.0.tgz", + "integrity": "sha512-9Y/d5UIwuJk8t3+lhmMSAJyNP1BUC/DqP3cQJDQQL/oWqAiuPTLgy7Q5dzglmTLwcBRdetzgNM/gni7ckfTr6A==", "dev": true }, "please-upgrade-node": { diff --git a/package.json b/package.json index fac57093a852c9..e4466eb4f470e1 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "@octokit/rest": "16.26.0", "@octokit/types": "6.34.0", "@octokit/webhooks-types": "5.8.0", - "@playwright/test": "1.45.1", + "@playwright/test": "1.46.0", "@pmmmwh/react-refresh-webpack-plugin": "0.5.11", "@react-native/babel-preset": "0.73.10", "@react-native/metro-babel-transformer": "0.73.10", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 675d6aa9feb6d5..ff8e26b0e00c12 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -93,7 +93,7 @@ "webpack-dev-server": "^4.15.1" }, "peerDependencies": { - "@playwright/test": "^1.45.1", + "@playwright/test": "^1.46.0", "react": "^18.0.0", "react-dom": "^18.0.0" }, From 025125bc3734a46b2a6423f7e4287355032c2e2b Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:48:56 +1000 Subject: [PATCH 0316/1908] Background image: ensure consistency with defaults and fix reset/remove functionality (#64328) * Fixes miscellaneous bugs in the background image default values and controls. - checks global styles for uploaded images and applies defaults - changes the default position from "center" to "50% 50%" so it displays in the controls - ensures that reset/remove functionality closes the panel and removes image - do not save already-inherited styles to the block, and don't apply defaults where an inherited style already exists. * Reduce vertical height a smidge * Ensure defaults are accurately displayed in the background control panel. Add defaults for position '50% 50%' for blocks so it can be displayed in the background panel controls Pass inherited values to setBackgroundStyleDefaults so as not apply/overwrite inherited styles. Tighten up logic in setBackgroundStyleDefaults so that background position isn't set when an inherited value is contain and the block style is something else. * Simplify default logic for blocks with uploaded images * Update tests. * Adds tests for setBackgroundStyleDefaults * Simplify the inheritence checks. For uploaded images in global styles and block supports, always apply the defaults. * Simplify the inheritence checks. For uploaded images, always apply the defaults. * Changelog * Revert background.php change and comment in background-panel.js Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- backport-changelog/6.7/7137.md | 1 + lib/block-supports/background.php | 2 +- lib/class-wp-theme-json-gutenberg.php | 2 +- .../global-styles/background-panel.js | 74 +++++++++++++------ .../test/use-global-styles-output.js | 2 +- packages/block-editor/src/hooks/background.js | 39 +++++----- .../block-editor/src/hooks/test/background.js | 60 +++++++++++++++ .../components/global-styles/screen-block.js | 3 +- phpunit/block-supports/background-test.php | 24 +++--- phpunit/class-wp-theme-json-test.php | 2 +- 10 files changed, 151 insertions(+), 58 deletions(-) create mode 100644 packages/block-editor/src/hooks/test/background.js diff --git a/backport-changelog/6.7/7137.md b/backport-changelog/6.7/7137.md index 834cb29a21e6d9..1eba52ebaf5087 100644 --- a/backport-changelog/6.7/7137.md +++ b/backport-changelog/6.7/7137.md @@ -1,3 +1,4 @@ https://github.com/WordPress/wordpress-develop/pull/7137 * https://github.com/WordPress/gutenberg/pull/64192 +* https://github.com/WordPress/gutenberg/pull/64328 diff --git a/lib/block-supports/background.php b/lib/block-supports/background.php index 811608127f47ed..a1d99133c1fc09 100644 --- a/lib/block-supports/background.php +++ b/lib/block-supports/background.php @@ -62,7 +62,7 @@ function gutenberg_render_background_support( $block_content, $block ) { $background_styles['backgroundSize'] = $background_styles['backgroundSize'] ?? 'cover'; // If the background size is set to `contain` and no position is set, set the position to `center`. if ( 'contain' === $background_styles['backgroundSize'] && ! $background_styles['backgroundPosition'] ) { - $background_styles['backgroundPosition'] = 'center'; + $background_styles['backgroundPosition'] = '50% 50%'; } } diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index ad8722091c2d48..7558438dcbe745 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2391,7 +2391,7 @@ protected static function compute_style_properties( $styles, $settings = array() $styles['background']['backgroundSize'] = $styles['background']['backgroundSize'] ?? 'cover'; // If the background size is set to `contain` and no position is set, set the position to `center`. if ( 'contain' === $styles['background']['backgroundSize'] && empty( $styles['background']['backgroundPosition'] ) ) { - $styles['background']['backgroundPosition'] = 'center'; + $styles['background']['backgroundPosition'] = '50% 50%'; } } $background_styles = gutenberg_style_engine_get_styles( array( 'background' => $styles['background'] ) ); diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index 61f572f970b762..906202206d1b76 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -268,8 +268,10 @@ function BackgroundImageControls( { style, inheritedValue, onRemoveImage = noop, + onResetImage = noop, displayInPanel, themeFileURIs, + defaultValues, } ) { const mediaUpload = useSelect( ( select ) => select( blockEditorStore ).getSettings().mediaUpload, @@ -319,12 +321,8 @@ function BackgroundImageControls( { } const sizeValue = - style?.background?.backgroundSize || - inheritedValue?.background?.backgroundSize; - const positionValue = - style?.background?.backgroundPosition || - inheritedValue?.background?.backgroundPosition; - + style?.background?.backgroundSize || defaultValues?.backgroundSize; + const positionValue = style?.background?.backgroundPosition; onChange( setImmutably( style, [ 'background' ], { ...style?.background, @@ -335,6 +333,12 @@ function BackgroundImageControls( { title: media.title || undefined, }, backgroundPosition: + /* + * A background image uploaded and set in the editor receives a default background position of '50% 0', + * when the background image size is the equivalent of "Tile". + * This is to increase the chance that the image's focus point is visible. + * This is in-editor only to assist with the user experience. + */ ! positionValue && ( 'auto' === sizeValue || ! sizeValue ) ? '50% 0' : positionValue, @@ -372,7 +376,9 @@ function BackgroundImageControls( { const onRemove = () => onChange( - setImmutably( style, [ 'background', 'backgroundImage' ], 'none' ) + setImmutably( style, [ 'background' ], { + backgroundImage: 'none', + } ) ); const canRemove = ! hasValue && hasBackgroundImageValue( inheritedValue ); const imgLabel = @@ -413,6 +419,7 @@ function BackgroundImageControls( { onClick={ () => { closeAndFocus(); onRemove(); + onRemoveImage(); } } > { __( 'Remove' ) } @@ -422,7 +429,7 @@ function BackgroundImageControls( { <MenuItem onClick={ () => { closeAndFocus(); - onRemoveImage(); + onResetImage(); } } > { __( 'Reset ' ) } @@ -453,9 +460,7 @@ function BackgroundSizeControls( { const imageValue = style?.background?.backgroundImage?.url || inheritedValue?.background?.backgroundImage?.url; - const isUploadedImage = - style?.background?.backgroundImage?.id || - inheritedValue?.background?.backgroundImage?.id; + const isUploadedImage = style?.background?.backgroundImage?.id; const positionValue = style?.background?.backgroundPosition || inheritedValue?.background?.backgroundPosition; @@ -469,11 +474,19 @@ function BackgroundSizeControls( { * Block-level controls may have different defaults to root-level controls. * A falsy value is treated by default as `auto` (Tile). */ - const currentValueForToggle = + let currentValueForToggle = ! sizeValue && isUploadedImage ? defaultValues?.backgroundSize : sizeValue || 'auto'; - + /* + * The incoming value could be a value + unit, e.g. '20px'. + * In this case set the value to 'tile'. + */ + currentValueForToggle = ! [ 'cover', 'contain', 'auto' ].includes( + currentValueForToggle + ) + ? 'auto' + : currentValueForToggle; /* * If the current value is `cover` and the repeat value is `undefined`, then * the toggle should be unchecked as the default state. Otherwise, the toggle @@ -510,6 +523,7 @@ function BackgroundSizeControls( { * receives a default background position of '50% 0', * when the toggle switches to "Tile". This is to increase the chance that * the image's focus point is visible. + * This is in-editor only to assist with the user experience. */ if ( !! style?.background?.backgroundImage?.id ) { nextPosition = '50% 0'; @@ -562,14 +576,20 @@ function BackgroundSizeControls( { ) ); + // Set a default background position for non-site-wide, uploaded images with a size of 'contain'. + const backgroundPositionValue = + ! positionValue && isUploadedImage && 'contain' === sizeValue + ? defaultValues?.backgroundPosition + : positionValue; + return ( - <VStack spacing={ 4 } className="single-column"> + <VStack spacing={ 3 } className="single-column"> <FocalPointPicker __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Focal point' ) } url={ getResolvedThemeFilePath( imageValue, themeFileURIs ) } - value={ backgroundPositionToCoords( positionValue ) } + value={ backgroundPositionToCoords( backgroundPositionValue ) } onChange={ updateBackgroundPosition } /> <ToggleControl @@ -577,9 +597,6 @@ function BackgroundSizeControls( { label={ __( 'Fixed background' ) } checked={ attachmentValue === 'fixed' } onChange={ toggleScrollWithPage } - help={ __( - 'Whether your image should scroll with the page or stay fixed in place.' - ) } /> <ToggleGroupControl __nextHasNoMarginBottom @@ -660,7 +677,7 @@ function BackgroundToolsPanel( { return ( <VStack as={ ToolsPanel } - spacing={ 4 } + spacing={ 2 } label={ headerLabel } resetAll={ resetAll } panelId={ panelId } @@ -700,8 +717,13 @@ export default function BackgroundPanel( { hasBackgroundImageValue( value ) || hasBackgroundImageValue( inheritedValue ); + const imageValue = + value?.background?.backgroundImage || + inheritedValue?.background?.backgroundImage; + const shouldShowBackgroundImageControls = hasImageValue && + 'none' !== imageValue && ( settings?.background?.backgroundSize || settings?.background?.backgroundPosition || settings?.background?.backgroundRepeat ); @@ -725,7 +747,7 @@ export default function BackgroundPanel( { ) } > <ToolsPanelItem - hasValue={ () => hasImageValue } + hasValue={ () => !! value?.background } label={ __( 'Image' ) } onDeselect={ resetBackground } isShownByDefault={ defaultControls.backgroundImage } @@ -749,10 +771,14 @@ export default function BackgroundPanel( { inheritedValue={ inheritedValue } themeFileURIs={ themeFileURIs } displayInPanel - onRemoveImage={ () => { + onResetImage={ () => { setIsDropDownOpen( false ); resetBackground(); } } + onRemoveImage={ () => + setIsDropDownOpen( false ) + } + defaultValues={ defaultValues } /> <BackgroundSizeControls onChange={ onChange } @@ -770,6 +796,12 @@ export default function BackgroundPanel( { style={ value } inheritedValue={ inheritedValue } themeFileURIs={ themeFileURIs } + defaultValues={ defaultValues } + onResetImage={ () => { + setIsDropDownOpen( false ); + resetBackground(); + } } + onRemoveImage={ () => setIsDropDownOpen( false ) } /> ) } </ToolsPanelItem> diff --git a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js index f648e1db845b87..e2530fdb85f812 100644 --- a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js @@ -1061,7 +1061,7 @@ describe( 'global styles renderer', () => { ) ).toEqual( [ "background-image: url( 'https://wordpress.org/assets/image.jpg' )", - 'background-position: center', + 'background-position: 50% 50%', 'background-size: contain', ] ); } ); diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index cd0b017831b795..0d38068cdefeea 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -23,9 +23,10 @@ import { export const BACKGROUND_SUPPORT_KEY = 'background'; -// Initial control values where no block style is set. -const BACKGROUND_DEFAULT_VALUES = { +// Initial control values. +export const BACKGROUND_BLOCK_DEFAULT_VALUES = { backgroundSize: 'cover', + backgroundPosition: '50% 50%', // used only when backgroundSize is 'contain'. }; /** @@ -55,31 +56,28 @@ export function hasBackgroundSupport( blockName, feature = 'any' ) { } export function setBackgroundStyleDefaults( backgroundStyle ) { - if ( ! backgroundStyle ) { + if ( ! backgroundStyle || ! backgroundStyle?.backgroundImage?.url ) { return; } - const backgroundImage = backgroundStyle?.backgroundImage; let backgroundStylesWithDefaults; // Set block background defaults. - if ( !! backgroundImage?.url ) { - if ( ! backgroundStyle?.backgroundSize ) { - backgroundStylesWithDefaults = { - backgroundSize: 'cover', - }; - } - - if ( - 'contain' === backgroundStyle?.backgroundSize && - ! backgroundStyle?.backgroundPosition - ) { - backgroundStylesWithDefaults = { - backgroundPosition: 'center', - }; - } + if ( ! backgroundStyle?.backgroundSize ) { + backgroundStylesWithDefaults = { + backgroundSize: BACKGROUND_BLOCK_DEFAULT_VALUES.backgroundSize, + }; } + if ( + 'contain' === backgroundStyle?.backgroundSize && + ! backgroundStyle?.backgroundPosition + ) { + backgroundStylesWithDefaults = { + backgroundPosition: + BACKGROUND_BLOCK_DEFAULT_VALUES.backgroundPosition, + }; + } return backgroundStylesWithDefaults; } @@ -147,6 +145,7 @@ export function BackgroundImagePanel( { style: getBlockAttributes( clientId )?.style, _links: _settings[ globalStylesLinksDataKey ], /* + * To ensure we pass down the right inherited values: * @TODO 1. Pass inherited value down to all block style controls, * See: packages/block-editor/src/hooks/style.js * @TODO 2. Add support for block style variations, @@ -187,7 +186,7 @@ export function BackgroundImagePanel( { inheritedValue={ inheritedValue } as={ BackgroundInspectorControl } panelId={ clientId } - defaultValues={ BACKGROUND_DEFAULT_VALUES } + defaultValues={ BACKGROUND_BLOCK_DEFAULT_VALUES } settings={ updatedSettings } onChange={ onChange } value={ style } diff --git a/packages/block-editor/src/hooks/test/background.js b/packages/block-editor/src/hooks/test/background.js new file mode 100644 index 00000000000000..030e88ae67fbd8 --- /dev/null +++ b/packages/block-editor/src/hooks/test/background.js @@ -0,0 +1,60 @@ +/** + * Internal dependencies + */ +import { + setBackgroundStyleDefaults, + BACKGROUND_BLOCK_DEFAULT_VALUES, +} from '../background'; + +describe( 'background', () => { + describe( 'setBackgroundStyleDefaults', () => { + const backgroundStyles = { + backgroundImage: { id: 123, url: 'image.png' }, + }; + const backgroundStylesContain = { + backgroundImage: { id: 123, url: 'image.png' }, + backgroundSize: 'contain', + }; + const backgroundStylesNoURL = { backgroundImage: { id: 123 } }; + it.each( [ + [ + 'return background size default', + backgroundStyles, + { + backgroundSize: + BACKGROUND_BLOCK_DEFAULT_VALUES.backgroundSize, + }, + ], + [ 'return early if no styles are passed', undefined, undefined ], + [ + 'return early if images has no id', + backgroundStylesNoURL, + undefined, + ], + [ + 'return early if images has no URL', + backgroundStylesNoURL, + undefined, + ], + [ + 'return background position default', + backgroundStylesContain, + { + backgroundPosition: + BACKGROUND_BLOCK_DEFAULT_VALUES.backgroundPosition, + }, + ], + [ + 'not apply background position value if one already exists in styles', + { + ...backgroundStylesContain, + backgroundPosition: 'center', + }, + undefined, + ], + ] )( 'should %s', ( message, styles, expected ) => { + const result = setBackgroundStyleDefaults( styles ); + expect( result ).toEqual( expected ); + } ); + } ); +} ); diff --git a/packages/edit-site/src/components/global-styles/screen-block.js b/packages/edit-site/src/components/global-styles/screen-block.js index a16a01956f5a88..dee921f37f1e8a 100644 --- a/packages/edit-site/src/components/global-styles/screen-block.js +++ b/packages/edit-site/src/components/global-styles/screen-block.js @@ -25,9 +25,10 @@ import { VariationsPanel, } from './variations/variations-panel'; -// Initial control values where no block style is set. +// Initial control values. const BACKGROUND_BLOCK_DEFAULT_VALUES = { backgroundSize: 'cover', + backgroundPosition: '50% 50%', // used only when backgroundSize is 'contain'. }; function applyFallbackStyle( border ) { diff --git a/phpunit/block-supports/background-test.php b/phpunit/block-supports/background-test.php index 33e72e9b070106..4c949fa82257d3 100644 --- a/phpunit/block-supports/background-test.php +++ b/phpunit/block-supports/background-test.php @@ -122,7 +122,7 @@ public function test_background_block_support( $theme_name, $block_name, $backgr */ public function data_background_block_support() { return array( - 'background image style is applied' => array( + 'background image style is applied to uploaded images' => array( 'theme_name' => 'block-theme-child-with-fluid-typography', 'block_name' => 'test/background-rules-are-output', 'background_settings' => array( @@ -130,8 +130,8 @@ public function data_background_block_support() { ), 'background_style' => array( 'backgroundImage' => array( - 'url' => 'https://example.com/image.jpg', - 'source' => 'file', + 'url' => 'https://example.com/image.jpg', + 'id' => 123, ), ), 'expected_wrapper' => '<div class="has-background" style="background-image:url('https://example.com/image.jpg');background-size:cover;">Content</div>', @@ -157,14 +157,14 @@ public function data_background_block_support() { ), 'background_style' => array( 'backgroundImage' => array( - 'url' => 'https://example.com/image.jpg', - 'source' => 'file', + 'url' => 'https://example.com/image.jpg', + 'id' => 123, ), 'backgroundRepeat' => 'no-repeat', 'backgroundSize' => 'contain', 'backgroundAttachment' => 'fixed', ), - 'expected_wrapper' => '<div class="has-background" style="background-image:url('https://example.com/image.jpg');background-position:center;background-repeat:no-repeat;background-size:contain;background-attachment:fixed;">Content</div>', + 'expected_wrapper' => '<div class="has-background" style="background-image:url('https://example.com/image.jpg');background-position:50% 50%;background-repeat:no-repeat;background-size:contain;background-attachment:fixed;">Content</div>', 'wrapper' => '<div>Content</div>', ), 'background image style is appended if a style attribute already exists' => array( @@ -175,8 +175,8 @@ public function data_background_block_support() { ), 'background_style' => array( 'backgroundImage' => array( - 'url' => 'https://example.com/image.jpg', - 'source' => 'file', + 'url' => 'https://example.com/image.jpg', + 'id' => 123, ), ), 'expected_wrapper' => '<div class="wp-block-test has-background" style="color: red;background-image:url('https://example.com/image.jpg');background-size:cover;">Content</div>', @@ -190,8 +190,8 @@ public function data_background_block_support() { ), 'background_style' => array( 'backgroundImage' => array( - 'url' => 'https://example.com/image.jpg', - 'source' => 'file', + 'url' => 'https://example.com/image.jpg', + 'id' => 123, ), ), 'expected_wrapper' => '<div class="wp-block-test has-background" style="color: red;font-size: 15px;background-image:url('https://example.com/image.jpg');background-size:cover;">Content</div>', @@ -205,8 +205,8 @@ public function data_background_block_support() { ), 'background_style' => array( 'backgroundImage' => array( - 'url' => 'https://example.com/image.jpg', - 'source' => 'file', + 'url' => 'https://example.com/image.jpg', + 'id' => 123, ), ), 'expected_wrapper' => '<div>Content</div>', diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index b77b54ecc7d872..d366e0df44c4a2 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -4900,7 +4900,7 @@ public function test_get_block_background_image_styles() { ), ); - $quote_styles = ":root :where(.wp-block-quote){background-image: url('http://example.org/quote.png');background-position: center;background-size: contain;}"; + $quote_styles = ":root :where(.wp-block-quote){background-image: url('http://example.org/quote.png');background-position: 50% 50%;background-size: contain;}"; $this->assertSameCSS( $quote_styles, $theme_json->get_styles_for_block( $quote_node ), 'Styles returned from "::get_styles_for_block()" with core/quote default background styles do not match expectations' ); $verse_node = array( From 7c079587eba227e14b09cb34a1cafeeb7b941baa Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:31:12 +0900 Subject: [PATCH 0317/1908] Don't allow duplicating template parts in non-block-based themes (#64379) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: MadtownLems <madtownlems@git.wordpress.org> --- .../editor/src/components/post-actions/actions.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index fcad5b97a13002..425636cefede46 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -313,9 +313,15 @@ export const duplicateTemplatePartAction = { }; export function usePostActions( { postType, onActionPerformed, context } ) { - const { defaultActions, postTypeObject, userCanCreatePostType } = useSelect( + const { + defaultActions, + postTypeObject, + userCanCreatePostType, + isBlockBasedTheme, + } = useSelect( ( select ) => { - const { getPostType, canUser } = select( coreStore ); + const { getPostType, canUser, getCurrentTheme } = + select( coreStore ); const { getEntityActions } = unlock( select( editorStore ) ); return { postTypeObject: getPostType( postType ), @@ -324,10 +330,12 @@ export function usePostActions( { postType, onActionPerformed, context } ) { kind: 'postType', name: postType, } ), + isBlockBasedTheme: getCurrentTheme()?.is_block_theme, }; }, [ postType ] ); + const { registerPostTypeActions } = unlock( useDispatch( editorStore ) ); useEffect( () => { registerPostTypeActions( postType ); @@ -356,6 +364,7 @@ export function usePostActions( { postType, onActionPerformed, context } ) { : false, isTemplateOrTemplatePart && userCanCreatePostType && + isBlockBasedTheme && duplicateTemplatePartAction, ...defaultActions, ].filter( Boolean ); From b6da9e018677c06a49fc06db1e69aa4bd1460e40 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:31:53 +0900 Subject: [PATCH 0318/1908] Fix: Cancel button in duplicate template part modal doesn't work (#64377) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/editor/src/components/post-actions/actions.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 425636cefede46..5e727376a92258 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -307,6 +307,7 @@ export const duplicateTemplatePartAction = { onCreate={ onTemplatePartSuccess } onError={ closeModal } confirmLabel={ _x( 'Duplicate', 'action label' ) } + closeModal={ closeModal } /> ); }, From 00d28d0e3dcea96b8a1f580bc25192fd197d3567 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Fri, 9 Aug 2024 09:45:01 +0800 Subject: [PATCH 0319/1908] Grid: Prevent highlight of cells when dragging a block if block type can't be dropped into grid (#64290) Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: hanneslsm <hanneslsm@git.wordpress.org> --- .../src/components/grid/grid-visualizer.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/grid/grid-visualizer.js b/packages/block-editor/src/components/grid/grid-visualizer.js index e1d35f012b4d81..fad2f5cfb14835 100644 --- a/packages/block-editor/src/components/grid/grid-visualizer.js +++ b/packages/block-editor/src/components/grid/grid-visualizer.js @@ -206,8 +206,12 @@ function useGridVisualizerDropZone( gridInfo, setHighlightedRect ) { - const { getBlockAttributes, getBlockRootClientId } = - useSelect( blockEditorStore ); + const { + getBlockAttributes, + getBlockRootClientId, + canInsertBlockType, + getBlockName, + } = useSelect( blockEditorStore ); const { updateBlockAttributes, moveBlocksToPosition, @@ -221,6 +225,10 @@ function useGridVisualizerDropZone( return useDropZoneWithValidation( { validateDrag( srcClientId ) { + const blockName = getBlockName( srcClientId ); + if ( ! canInsertBlockType( blockName, gridClientId ) ) { + return false; + } const attributes = getBlockAttributes( srcClientId ); const rect = new GridRect( { columnStart: column, From b11bdc0645a0503437389c29d39ac266ba6cd2bf Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Fri, 9 Aug 2024 09:46:40 +0530 Subject: [PATCH 0320/1908] Add border support to preformatted block (#64302) Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/preformatted/block.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/block-library/src/preformatted/block.json b/packages/block-library/src/preformatted/block.json index fbec3581bc9d42..a1726ee8b0d43c 100644 --- a/packages/block-library/src/preformatted/block.json +++ b/packages/block-library/src/preformatted/block.json @@ -43,6 +43,18 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } }, "style": "wp-block-preformatted" From 0ceac8f5e8b74cbeb7ef36c44009c67ec5fabbf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 9 Aug 2024 09:16:08 +0200 Subject: [PATCH 0321/1908] Quick edit: add Date as field and `datetime` as field type (#64267) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 + .../components/src/date-time/time/index.tsx | 38 +++++--- packages/components/src/date-time/types.ts | 12 ++- .../dataform/stories/index.story.tsx | 18 +++- .../components/dataviews/stories/fixtures.js | 16 ++++ .../dataviews/src/field-types/datetime.tsx | 95 +++++++++++++++++++ packages/dataviews/src/field-types/index.tsx | 5 + .../src/test/filter-and-sort-data-view.js | 28 ++++++ packages/dataviews/src/types.ts | 2 +- .../src/components/post-edit/index.js | 5 +- .../src/components/post-fields/index.js | 1 + 11 files changed, 206 insertions(+), 18 deletions(-) create mode 100644 packages/dataviews/src/field-types/datetime.tsx diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index ef0108b09a741d..47afb0711090d8 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- `TimePicker`: add `hideLabelFromVision` prop ([#64267](https://github.com/WordPress/gutenberg/pull/64267)). + ## 28.5.0 (2024-08-07) ### Bug Fixes diff --git a/packages/components/src/date-time/time/index.tsx b/packages/components/src/date-time/time/index.tsx index 5f706d69190095..90a8a901354a39 100644 --- a/packages/components/src/date-time/time/index.tsx +++ b/packages/components/src/date-time/time/index.tsx @@ -13,6 +13,7 @@ import { __ } from '@wordpress/i18n'; * Internal dependencies */ import BaseControl from '../../base-control'; +import { VisuallyHidden } from '../../visually-hidden'; import SelectControl from '../../select-control'; import TimeZone from './timezone'; import type { TimeInputValue, TimePickerProps } from '../types'; @@ -61,6 +62,7 @@ export function TimePicker( { currentTime, onChange, dateOrder: dateOrderProp, + hideLabelFromVision = false, }: TimePickerProps ) { const [ date, setDate ] = useState( () => // Truncate the date at the minutes, see: #15495. @@ -219,12 +221,18 @@ export function TimePicker( { className="components-datetime__time" // Unused, for backwards compatibility. > <Fieldset> - <BaseControl.VisualLabel - as="legend" - className="components-datetime__time-legend" // Unused, for backwards compatibility. - > - { __( 'Time' ) } - </BaseControl.VisualLabel> + { hideLabelFromVision ? ( + <VisuallyHidden as="legend"> + { __( 'Time' ) } + </VisuallyHidden> + ) : ( + <BaseControl.VisualLabel + as="legend" + className="components-datetime__time-legend" // Unused, for backwards compatibility. + > + { __( 'Time' ) } + </BaseControl.VisualLabel> + ) } <HStack className="components-datetime__time-wrapper" // Unused, for backwards compatibility. > @@ -241,12 +249,18 @@ export function TimePicker( { </HStack> </Fieldset> <Fieldset> - <BaseControl.VisualLabel - as="legend" - className="components-datetime__time-legend" // Unused, for backwards compatibility. - > - { __( 'Date' ) } - </BaseControl.VisualLabel> + { hideLabelFromVision ? ( + <VisuallyHidden as="legend"> + { __( 'Date' ) } + </VisuallyHidden> + ) : ( + <BaseControl.VisualLabel + as="legend" + className="components-datetime__time-legend" // Unused, for backwards compatibility. + > + { __( 'Date' ) } + </BaseControl.VisualLabel> + ) } <HStack className="components-datetime__time-wrapper" // Unused, for backwards compatibility. > diff --git a/packages/components/src/date-time/types.ts b/packages/components/src/date-time/types.ts index b3716d5c135c64..1f2298d9d450b5 100644 --- a/packages/components/src/date-time/types.ts +++ b/packages/components/src/date-time/types.ts @@ -29,6 +29,13 @@ export type TimePickerProps = { * time as an argument. */ onChange?: ( time: string ) => void; + + /** + * If true, the label will only be visible to screen readers. + * + * @default false + */ + hideLabelFromVision?: boolean; }; export type TimeInputValue = { @@ -130,7 +137,10 @@ export type DatePickerProps = { }; export type DateTimePickerProps = Omit< DatePickerProps, 'onChange' > & - Omit< TimePickerProps, 'currentTime' | 'onChange' > & { + Omit< + TimePickerProps, + 'currentTime' | 'onChange' | 'hideLabelFromVision' + > & { /** * The function called when a new date or time has been selected. It is * passed the date and time as an argument. diff --git a/packages/dataviews/src/components/dataform/stories/index.story.tsx b/packages/dataviews/src/components/dataform/stories/index.story.tsx index 4863eb24b4ede4..7808756b7b6557 100644 --- a/packages/dataviews/src/components/dataform/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataform/stories/index.story.tsx @@ -33,6 +33,20 @@ const fields = [ label: 'Order', type: 'integer' as const, }, + { + id: 'date', + label: 'Date', + type: 'datetime' as const, + }, + { + id: 'birthdate', + label: 'Date as options', + type: 'datetime' as const, + elements: [ + { value: '1970-02-23T12:00:00', label: "Jane's birth date" }, + { value: '1950-02-23T12:00:00', label: "John's birth date" }, + ], + }, { id: 'author', label: 'Author', @@ -59,10 +73,12 @@ export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { order: 2, author: 1, status: 'draft', + date: '2021-01-01T12:00:00', + birthdate: '1950-02-23T12:00:00', } ); const form = { - fields: [ 'title', 'order', 'author', 'status' ], + fields: [ 'title', 'order', 'author', 'status', 'date', 'birthdate' ], }; return ( diff --git a/packages/dataviews/src/components/dataviews/stories/fixtures.js b/packages/dataviews/src/components/dataviews/stories/fixtures.js index 536c5e66e6ce97..f89cea81e6f15d 100644 --- a/packages/dataviews/src/components/dataviews/stories/fixtures.js +++ b/packages/dataviews/src/components/dataviews/stories/fixtures.js @@ -23,6 +23,7 @@ export const data = [ type: 'Not a planet', categories: [ 'Space', 'NASA' ], satellites: 0, + date: '2021-01-01T00:00:00Z', }, { id: 2, @@ -32,6 +33,7 @@ export const data = [ type: 'Not a planet', categories: [ 'Space' ], satellites: 0, + date: '2019-01-02T00:00:00Z', }, { id: 3, @@ -41,6 +43,7 @@ export const data = [ type: 'Not a planet', categories: [ 'NASA' ], satellites: 0, + date: '2025-01-03T00:00:00Z', }, { id: 4, @@ -50,6 +53,7 @@ export const data = [ type: 'Ice giant', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 14, + date: '2020-01-01T00:00:00Z', }, { id: 5, @@ -59,6 +63,7 @@ export const data = [ type: 'Terrestrial', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 0, + date: '2020-01-02T01:00:00Z', }, { id: 6, @@ -68,6 +73,7 @@ export const data = [ type: 'Terrestrial', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 0, + date: '2020-01-02T00:00:00Z', }, { id: 7, @@ -77,6 +83,7 @@ export const data = [ type: 'Terrestrial', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 1, + date: '2023-01-03T00:00:00Z', }, { id: 8, @@ -86,6 +93,7 @@ export const data = [ type: 'Terrestrial', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 2, + date: '2020-01-01T00:00:00Z', }, { id: 9, @@ -95,6 +103,7 @@ export const data = [ type: 'Gas giant', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 95, + date: '2017-01-01T00:01:00Z', }, { id: 10, @@ -104,6 +113,7 @@ export const data = [ type: 'Gas giant', categories: [ 'Space', 'Planet', 'Solar system' ], satellites: 146, + date: '2020-02-01T00:02:00Z', }, { id: 11, @@ -113,6 +123,7 @@ export const data = [ type: 'Ice giant', categories: [ 'Space', 'Ice giant', 'Solar system' ], satellites: 28, + date: '2020-03-01T00:00:00Z', }, ]; @@ -175,6 +186,11 @@ export const fields = [ enableHiding: false, enableGlobalSearch: true, }, + { + id: 'date', + label: 'Date', + type: 'datetime', + }, { label: 'Type', id: 'type', diff --git a/packages/dataviews/src/field-types/datetime.tsx b/packages/dataviews/src/field-types/datetime.tsx new file mode 100644 index 00000000000000..3861a0db635d7b --- /dev/null +++ b/packages/dataviews/src/field-types/datetime.tsx @@ -0,0 +1,95 @@ +/** + * WordPress dependencies + */ +import { BaseControl, TimePicker, SelectControl } from '@wordpress/components'; +import { useCallback } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { + SortDirection, + ValidationContext, + DataFormControlProps, +} from '../types'; + +function sort( a: any, b: any, direction: SortDirection ) { + const timeA = new Date( a ).getTime(); + const timeB = new Date( b ).getTime(); + + return direction === 'asc' ? timeA - timeB : timeB - timeA; +} + +function isValid( value: any, context?: ValidationContext ) { + if ( context?.elements ) { + const validValues = context?.elements.map( ( f ) => f.value ); + if ( ! validValues.includes( value ) ) { + return false; + } + } + + return true; +} + +function Edit< Item >( { + data, + field, + onChange, +}: DataFormControlProps< Item > ) { + const { id, label } = field; + const value = field.getValue( { item: data } ); + + const onChangeControl = useCallback( + ( newValue: string | null ) => + onChange( ( prevItem: Item ) => ( { + ...prevItem, + [ id ]: newValue, + } ) ), + [ id, onChange ] + ); + + if ( field.elements ) { + const elements = [ + /* + * Value can be undefined when: + * + * - the field is not required + * - in bulk editing + * + */ + { label: __( 'Select item' ), value: '' }, + ...field.elements, + ]; + + return ( + <SelectControl + label={ label } + value={ value } + options={ elements } + onChange={ onChangeControl } + __next40pxDefaultSize + __nextHasNoMarginBottom + /> + ); + } + + return ( + <fieldset> + <BaseControl.VisualLabel as="legend"> + { label } + </BaseControl.VisualLabel> + <TimePicker + currentTime={ value } + onChange={ onChangeControl } + hideLabelFromVision + /> + </fieldset> + ); +} + +export default { + sort, + isValid, + Edit, +}; diff --git a/packages/dataviews/src/field-types/index.tsx b/packages/dataviews/src/field-types/index.tsx index 3d1d824ec36bf2..eb9dada479c6bf 100644 --- a/packages/dataviews/src/field-types/index.tsx +++ b/packages/dataviews/src/field-types/index.tsx @@ -4,6 +4,7 @@ import type { FieldType, SortDirection, ValidationContext } from '../types'; import { default as integer } from './integer'; import { default as text } from './text'; +import { default as datetime } from './datetime'; /** * @@ -20,6 +21,10 @@ export default function getFieldTypeDefinition( type?: FieldType ) { return text; } + if ( 'datetime' === type ) { + return datetime; + } + return { sort: ( a: any, b: any, direction: SortDirection ) => { if ( typeof a === 'number' && typeof b === 'number' ) { diff --git a/packages/dataviews/src/test/filter-and-sort-data-view.js b/packages/dataviews/src/test/filter-and-sort-data-view.js index 7538b975a30992..7f0b3a30e8587c 100644 --- a/packages/dataviews/src/test/filter-and-sort-data-view.js +++ b/packages/dataviews/src/test/filter-and-sort-data-view.js @@ -268,6 +268,34 @@ describe( 'sorting', () => { expect( result[ 1 ].title ).toBe( 'Neptune' ); } ); + it( 'should sort datetime field types', () => { + const { data: resultDesc } = filterSortAndPaginate( + data, + { + sort: { field: 'date', direction: 'desc' }, + }, + fields + ); + expect( resultDesc ).toHaveLength( 11 ); + expect( resultDesc[ 0 ].title ).toBe( 'NASA' ); + expect( resultDesc[ 1 ].title ).toBe( 'Earth' ); + expect( resultDesc[ 9 ].title ).toBe( 'Space' ); + expect( resultDesc[ 10 ].title ).toBe( 'Jupiter' ); + + const { data: resultAsc } = filterSortAndPaginate( + data, + { + sort: { field: 'date', direction: 'asc' }, + }, + fields + ); + expect( resultAsc ).toHaveLength( 11 ); + expect( resultAsc[ 0 ].title ).toBe( 'Jupiter' ); + expect( resultAsc[ 1 ].title ).toBe( 'Space' ); + expect( resultAsc[ 9 ].title ).toBe( 'Earth' ); + expect( resultAsc[ 10 ].title ).toBe( 'NASA' ); + } ); + it( 'should sort untyped fields if the value is a number', () => { const { data: result } = filterSortAndPaginate( data, diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index b0873e9c677f53..2e87d1371acb61 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -47,7 +47,7 @@ export type Operator = | 'isAll' | 'isNotAll'; -export type FieldType = 'text' | 'integer'; +export type FieldType = 'text' | 'integer' | 'datetime'; export type ValidationContext = { elements?: Option[]; diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 86e2bf4d6edea1..03158e00862154 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -47,9 +47,9 @@ function PostEditForm( { postType, postId } ) { const { fields } = usePostFields(); const form = { type: 'panel', - fields: [ 'title', 'author' ], + fields: [ 'title', 'author', 'date' ], }; - const [ edits, setEdits ] = useState( {} ); + const [ edits, setEdits ] = useState( initialEdits ); const itemWithEdits = useMemo( () => { return { ...initialEdits, @@ -71,7 +71,6 @@ function PostEditForm( { postType, postId } ) { ...edits, } ); } - setEdits( {} ); }; const isUpdateDisabled = ! isItemValid( itemWithEdits, fields, form ); diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index f476b676264ed8..44625fbfbfafb9 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -271,6 +271,7 @@ function usePostFields( viewType ) { { label: __( 'Date' ), id: 'date', + type: 'datetime', render: ( { item } ) => { const isDraftOrPrivate = [ 'draft', 'private' ].includes( item.status From 97285c23d69955776b7d1b6d1468167d081beb7b Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Fri, 9 Aug 2024 13:20:15 +0530 Subject: [PATCH 0322/1908] Comment Date: Added Border Support (#64210) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- .../block-library/src/comment-date/block.json | 15 ++++++++++++++- .../block-library/src/comment-date/style.scss | 4 ++++ packages/block-library/src/style.scss | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 packages/block-library/src/comment-date/style.scss diff --git a/packages/block-library/src/comment-date/block.json b/packages/block-library/src/comment-date/block.json index ddc0281e6c668c..1e8110f836d93b 100644 --- a/packages/block-library/src/comment-date/block.json +++ b/packages/block-library/src/comment-date/block.json @@ -47,6 +47,19 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } - } + }, + "style": "wp-block-comment-date" } diff --git a/packages/block-library/src/comment-date/style.scss b/packages/block-library/src/comment-date/style.scss new file mode 100644 index 00000000000000..9b897defa655b7 --- /dev/null +++ b/packages/block-library/src/comment-date/style.scss @@ -0,0 +1,4 @@ +.wp-block-comment-date { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; +} diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index 8f17cd7a50f55c..df1337d7eb25c0 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -10,6 +10,7 @@ @import "./comments/style.scss"; @import "./comments-pagination/style.scss"; @import "./comment-template/style.scss"; +@import "./comment-date/style.scss"; @import "./cover/style.scss"; @import "./details/style.scss"; @import "./embed/style.scss"; From 651cc457521a6ec81367362618433095ae611fb0 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Fri, 9 Aug 2024 10:49:31 +0200 Subject: [PATCH 0323/1908] DataViews Quick Edit: Add Post Card to the quick edit panel (#64365) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../src/components/post-edit/index.js | 7 ++++ .../src/components/post-card-panel/index.js | 42 ++++++++----------- .../src/components/sidebar/post-summary.js | 29 ++++++++----- packages/editor/src/private-apis.js | 2 + 4 files changed, 45 insertions(+), 35 deletions(-) diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 03158e00862154..35141f743cd2e3 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -16,12 +16,16 @@ import { __experimentalVStack as VStack, } from '@wordpress/components'; import { useState, useMemo } from '@wordpress/element'; +import { privateApis as editorPrivateApis } from '@wordpress/editor'; /** * Internal dependencies */ import Page from '../page'; import usePostFields from '../post-fields'; +import { unlock } from '../../lock-unlock'; + +const { PostCardPanel } = unlock( editorPrivateApis ); function PostEditForm( { postType, postId } ) { const ids = useMemo( () => postId.split( ',' ), [ postId ] ); @@ -76,6 +80,9 @@ function PostEditForm( { postType, postId } ) { const isUpdateDisabled = ! isItemValid( itemWithEdits, fields, form ); return ( <VStack as="form" onSubmit={ onSubmit } spacing={ 4 }> + { ids.length === 1 && ( + <PostCardPanel postType={ postType } postId={ ids[ 0 ] } /> + ) } <DataForm data={ itemWithEdits } fields={ fields } diff --git a/packages/editor/src/components/post-card-panel/index.js b/packages/editor/src/components/post-card-panel/index.js index 43efb6418b4fa9..5e20ecbcf07df9 100644 --- a/packages/editor/src/components/post-card-panel/index.js +++ b/packages/editor/src/components/post-card-panel/index.js @@ -27,55 +27,47 @@ import { } from '../../store/constants'; import { unlock } from '../../lock-unlock'; -export default function PostCardPanel( { actions } ) { +export default function PostCardPanel( { postType, postId, actions } ) { const { isFrontPage, isPostsPage, title, icon, isSync } = useSelect( ( select ) => { - const { - getEditedPostAttribute, - getCurrentPostType, - getCurrentPostId, - __experimentalGetTemplateInfo, - } = select( editorStore ); - const { canUser } = select( coreStore ); - const { getEditedEntityRecord } = select( coreStore ); + const { __experimentalGetTemplateInfo } = select( editorStore ); + const { canUser, getEditedEntityRecord } = select( coreStore ); const siteSettings = canUser( 'read', { kind: 'root', name: 'site', } ) ? getEditedEntityRecord( 'root', 'site' ) : undefined; - const _type = getCurrentPostType(); - const _id = getCurrentPostId(); - const _record = getEditedEntityRecord( 'postType', _type, _id ); + const _record = getEditedEntityRecord( + 'postType', + postType, + postId + ); const _templateInfo = [ TEMPLATE_POST_TYPE, TEMPLATE_PART_POST_TYPE ].includes( - _type + postType ) && __experimentalGetTemplateInfo( _record ); let _isSync = false; - if ( GLOBAL_POST_TYPES.includes( _type ) ) { - if ( PATTERN_POST_TYPE === _type ) { + if ( GLOBAL_POST_TYPES.includes( postType ) ) { + if ( PATTERN_POST_TYPE === postType ) { // When the post is first created, the top level wp_pattern_sync_status is not set so get meta value instead. const currentSyncStatus = - getEditedPostAttribute( 'meta' ) - ?.wp_pattern_sync_status === 'unsynced' + _record?.meta?.wp_pattern_sync_status === 'unsynced' ? 'unsynced' - : getEditedPostAttribute( - 'wp_pattern_sync_status' - ); + : _record?.wp_pattern_sync_status; _isSync = currentSyncStatus !== 'unsynced'; } else { _isSync = true; } } return { - title: - _templateInfo?.title || getEditedPostAttribute( 'title' ), - icon: unlock( select( editorStore ) ).getPostIcon( _type, { + title: _templateInfo?.title || _record?.title, + icon: unlock( select( editorStore ) ).getPostIcon( postType, { area: _record?.area, } ), isSync: _isSync, - isFrontPage: siteSettings?.page_on_front === _id, - isPostsPage: siteSettings?.page_for_posts === _id, + isFrontPage: siteSettings?.page_on_front === postId, + isPostsPage: siteSettings?.page_for_posts === postId, }; }, [] diff --git a/packages/editor/src/components/sidebar/post-summary.js b/packages/editor/src/components/sidebar/post-summary.js index a6a95d36388ba5..573a59de827188 100644 --- a/packages/editor/src/components/sidebar/post-summary.js +++ b/packages/editor/src/components/sidebar/post-summary.js @@ -36,16 +36,23 @@ import { PrivatePostLastRevision } from '../post-last-revision'; const PANEL_NAME = 'post-status'; export default function PostSummary( { onActionPerformed } ) { - const { isRemovedPostStatusPanel } = useSelect( ( select ) => { - // We use isEditorPanelRemoved to hide the panel if it was programatically removed. We do - // not use isEditorPanelEnabled since this panel should not be disabled through the UI. - const { isEditorPanelRemoved, getCurrentPostType } = - select( editorStore ); - return { - isRemovedPostStatusPanel: isEditorPanelRemoved( PANEL_NAME ), - postType: getCurrentPostType(), - }; - }, [] ); + const { isRemovedPostStatusPanel, postType, postId } = useSelect( + ( select ) => { + // We use isEditorPanelRemoved to hide the panel if it was programatically removed. We do + // not use isEditorPanelEnabled since this panel should not be disabled through the UI. + const { + isEditorPanelRemoved, + getCurrentPostType, + getCurrentPostId, + } = select( editorStore ); + return { + isRemovedPostStatusPanel: isEditorPanelRemoved( PANEL_NAME ), + postType: getCurrentPostType(), + postId: getCurrentPostId(), + }; + }, + [] + ); return ( <PostPanelSection className="editor-post-summary"> @@ -54,6 +61,8 @@ export default function PostSummary( { onActionPerformed } ) { <> <VStack spacing={ 4 }> <PostCardPanel + postType={ postType } + postId={ postId } actions={ <PostActions onActionPerformed={ onActionPerformed } diff --git a/packages/editor/src/private-apis.js b/packages/editor/src/private-apis.js index a8a74d20261ce4..629600888a98eb 100644 --- a/packages/editor/src/private-apis.js +++ b/packages/editor/src/private-apis.js @@ -14,6 +14,7 @@ import BackButton from './components/header/back-button'; import CreateTemplatePartModal from './components/create-template-part-modal'; import Editor from './components/editor'; import PluginPostExcerpt from './components/post-excerpt/plugin'; +import PostCardPanel from './components/post-card-panel'; import PreferencesModal from './components/preferences-modal'; import { usePostActions } from './components/post-actions/actions'; import ToolsMoreMenuGroup from './components/more-menu/tools-more-menu-group'; @@ -40,6 +41,7 @@ lock( privateApis, { GlobalStylesProvider, mergeBaseAndUserConfigs, PluginPostExcerpt, + PostCardPanel, PreferencesModal, usePostActions, ToolsMoreMenuGroup, From 02622aee4bd75935ed73c19a40fdcbc9a1b7d5a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:57:41 +0200 Subject: [PATCH 0324/1908] Add `comment_status` field to quick edit (#64370) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../components/dataform-controls/index.tsx | 46 +++++++++++++++++++ .../components/dataform-controls/radio.tsx | 43 +++++++++++++++++ .../dataform/stories/index.story.tsx | 22 ++++++++- packages/dataviews/src/normalize-fields.ts | 3 +- packages/dataviews/src/types.ts | 22 ++++++++- .../src/components/post-edit/index.js | 2 +- .../src/components/post-fields/index.js | 26 +++++++++++ 7 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 packages/dataviews/src/components/dataform-controls/index.tsx create mode 100644 packages/dataviews/src/components/dataform-controls/radio.tsx diff --git a/packages/dataviews/src/components/dataform-controls/index.tsx b/packages/dataviews/src/components/dataform-controls/index.tsx new file mode 100644 index 00000000000000..dd913269cd09ea --- /dev/null +++ b/packages/dataviews/src/components/dataform-controls/index.tsx @@ -0,0 +1,46 @@ +/** + * External dependencies + */ +import type { ComponentType } from 'react'; + +/** + * Internal dependencies + */ +import type { + DataFormControlProps, + Field, + FieldTypeDefinition, +} from '../../types'; +import radio from './radio'; + +interface FormControls { + [ key: string ]: ComponentType< DataFormControlProps< any > >; +} + +const FORM_CONTROLS: FormControls = { + radio, +}; + +export function getControl< Item >( + field: Field< Item >, + fieldTypeDefinition: FieldTypeDefinition< Item > +) { + if ( typeof field.Edit === 'function' ) { + return field.Edit; + } + + let control; + if ( typeof field.Edit === 'string' ) { + control = getControlByType( field.Edit ); + } + + return control || fieldTypeDefinition.Edit; +} + +export function getControlByType( type: string ) { + if ( Object.keys( FORM_CONTROLS ).includes( type ) ) { + return FORM_CONTROLS[ type ]; + } + + return null; +} diff --git a/packages/dataviews/src/components/dataform-controls/radio.tsx b/packages/dataviews/src/components/dataform-controls/radio.tsx new file mode 100644 index 00000000000000..d264aa6c24b7fb --- /dev/null +++ b/packages/dataviews/src/components/dataform-controls/radio.tsx @@ -0,0 +1,43 @@ +/** + * WordPress dependencies + */ +import { RadioControl } from '@wordpress/components'; +import { useCallback } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { DataFormControlProps } from '../../types'; + +export default function Edit< Item >( { + data, + field, + onChange, + hideLabelFromVision, +}: DataFormControlProps< Item > ) { + const { id, label } = field; + const value = field.getValue( { item: data } ); + + const onChangeControl = useCallback( + ( newValue: string ) => + onChange( ( prevItem: Item ) => ( { + ...prevItem, + [ id ]: newValue, + } ) ), + [ id, onChange ] + ); + + if ( field.elements ) { + return ( + <RadioControl + label={ label } + onChange={ onChangeControl } + options={ field.elements } + selected={ value } + hideLabelFromVision={ hideLabelFromVision } + /> + ); + } + + return null; +} diff --git a/packages/dataviews/src/components/dataform/stories/index.story.tsx b/packages/dataviews/src/components/dataform/stories/index.story.tsx index 7808756b7b6557..7f3c5ff879b72a 100644 --- a/packages/dataviews/src/components/dataform/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataform/stories/index.story.tsx @@ -56,6 +56,17 @@ const fields = [ { value: 2, label: 'John' }, ], }, + { + id: 'reviewer', + label: 'Reviewer', + type: 'text' as const, + Edit: 'radio' as const, + elements: [ + { value: 'fulano', label: 'Fulano' }, + { value: 'mengano', label: 'Mengano' }, + { value: 'zutano', label: 'Zutano' }, + ], + }, { id: 'status', label: 'Status', @@ -73,12 +84,21 @@ export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { order: 2, author: 1, status: 'draft', + reviewer: 'fulano', date: '2021-01-01T12:00:00', birthdate: '1950-02-23T12:00:00', } ); const form = { - fields: [ 'title', 'order', 'author', 'status', 'date', 'birthdate' ], + fields: [ + 'title', + 'order', + 'author', + 'reviewer', + 'status', + 'date', + 'birthdate', + ], }; return ( diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index 680749df5344a6..54992ff22fe2ae 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -3,6 +3,7 @@ */ import getFieldTypeDefinition from './field-types'; import type { Field, NormalizedField } from './types'; +import { getControl } from './components/dataform-controls'; /** * Apply default values and normalize the fields config. @@ -38,7 +39,7 @@ export function normalizeFields< Item >( ); }; - const Edit = field.Edit || fieldTypeDefinition.Edit; + const Edit = getControl( field, fieldTypeDefinition ); const renderFromElements = ( { item }: { item: Item } ) => { const value = getValue( { item } ); diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 2e87d1371acb61..d8a5ee8f68ecef 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -53,6 +53,26 @@ export type ValidationContext = { elements?: Option[]; }; +/** + * An abstract interface for Field based on the field type. + */ +export type FieldTypeDefinition< Item > = { + /** + * Callback used to sort the field. + */ + sort: ( a: Item, b: Item, direction: SortDirection ) => number; + + /** + * Callback used to validate the field. + */ + isValid: ( item: Item, context?: ValidationContext ) => boolean; + + /** + * Callback used to render an edit control for the field. + */ + Edit: ComponentType< DataFormControlProps< Item > >; +}; + /** * A dataview field for a specific property of a data type. */ @@ -90,7 +110,7 @@ export type Field< Item > = { /** * Callback used to render an edit control for the field. */ - Edit?: ComponentType< DataFormControlProps< Item > >; + Edit?: ComponentType< DataFormControlProps< Item > > | 'radio'; /** * Callback used to sort the field. diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 35141f743cd2e3..0a56fdfe5786b7 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -51,7 +51,7 @@ function PostEditForm( { postType, postId } ) { const { fields } = usePostFields(); const form = { type: 'panel', - fields: [ 'title', 'author', 'date' ], + fields: [ 'title', 'author', 'date', 'comment_status' ], }; const [ edits, setEdits ] = useState( initialEdits ); const itemWithEdits = useMemo( () => { diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 44625fbfbfafb9..b03b2c6f5be3c4 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -345,6 +345,32 @@ function usePostFields( viewType ) { return <time>{ getFormattedDate( item.date ) }</time>; }, }, + { + id: 'comment_status', + label: __( 'Discussion' ), + type: 'text', + Edit: 'radio', + enableSorting: false, + filterBy: { + operators: [], + }, + elements: [ + { + value: 'open', + label: __( 'Open' ), + description: __( + 'Visitors can add new comments and replies.' + ), + }, + { + value: 'closed', + label: __( 'Closed' ), + description: __( + 'Visitors cannot add new comments or replies. Existing comments remain visible.' + ), + }, + ], + }, ], [ authors, viewType, frontPageId, postsPageId ] ); From 360c6f9b2be933baa0c224ce7a2d4f48593bee0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 9 Aug 2024 11:42:34 +0200 Subject: [PATCH 0325/1908] DataViews: update `renderFormElements` to make sure the value respects the type (#64391) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/dataviews/src/field-types/integer.tsx | 2 +- packages/dataviews/src/normalize-fields.ts | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/dataviews/src/field-types/integer.tsx b/packages/dataviews/src/field-types/integer.tsx index 1233c3ab555567..bd4956493232df 100644 --- a/packages/dataviews/src/field-types/integer.tsx +++ b/packages/dataviews/src/field-types/integer.tsx @@ -53,7 +53,7 @@ function Edit< Item >( { ( newValue: string | undefined ) => onChange( ( prevItem: Item ) => ( { ...prevItem, - [ id ]: newValue, + [ id ]: Number( newValue ), } ) ), [ id, onChange ] ); diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index 54992ff22fe2ae..2cdde5b3343798 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -43,13 +43,10 @@ export function normalizeFields< Item >( const renderFromElements = ( { item }: { item: Item } ) => { const value = getValue( { item } ); - const label = field?.elements?.find( ( element ) => { - // Intentionally using == here to allow for type coercion. - // eslint-disable-next-line eqeqeq - return element.value == value; - } )?.label; - - return label || value; + return ( + field?.elements?.find( ( element ) => element.value === value ) + ?.label || getValue( { item } ) + ); }; const render = From 758915a0e4346ca51a9e3fda5bee4500ff4e3976 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Fri, 9 Aug 2024 11:49:04 +0200 Subject: [PATCH 0326/1908] DataViews Quick Edit: Fix panel title not updating --- packages/editor/src/components/post-card-panel/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-card-panel/index.js b/packages/editor/src/components/post-card-panel/index.js index 5e20ecbcf07df9..5ac88b3dbc7f94 100644 --- a/packages/editor/src/components/post-card-panel/index.js +++ b/packages/editor/src/components/post-card-panel/index.js @@ -70,7 +70,7 @@ export default function PostCardPanel( { postType, postId, actions } ) { isPostsPage: siteSettings?.page_for_posts === postId, }; }, - [] + [ postId, postType ] ); return ( <div className="editor-post-card-panel"> From f5959ccdbab3fab3f95525c2d711e419cffe7d0a Mon Sep 17 00:00:00 2001 From: Amit Raj <77401999+amitraj2203@users.noreply.github.com> Date: Fri, 9 Aug 2024 15:39:42 +0530 Subject: [PATCH 0327/1908] Latests Posts: Used ToggleGroupControl instead for Image alignment (#64352) * Used ToggleGroupControl instead of BlockAlignmentToolbar * Addressed feedback * Use position icons instead of align * Remove isBlock prop from ToggleGroupControl Co-authored-by: amitraj2203 <amitraj2203@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../block-library/src/latest-posts/edit.js | 76 ++++++++++++++----- .../src/latest-posts/editor.scss | 6 -- 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/packages/block-library/src/latest-posts/edit.js b/packages/block-library/src/latest-posts/edit.js index 49a24b08f68d77..533e9621fd4f2b 100644 --- a/packages/block-library/src/latest-posts/edit.js +++ b/packages/block-library/src/latest-posts/edit.js @@ -7,7 +7,6 @@ import clsx from 'clsx'; * WordPress dependencies */ import { - BaseControl, PanelBody, Placeholder, QueryControls, @@ -16,19 +15,28 @@ import { Spinner, ToggleControl, ToolbarGroup, + __experimentalToggleGroupControl as ToggleGroupControl, + __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, } from '@wordpress/components'; import { __, _x, sprintf } from '@wordpress/i18n'; import { dateI18n, format, getSettings } from '@wordpress/date'; import { InspectorControls, - BlockAlignmentToolbar, BlockControls, __experimentalImageSizeControl as ImageSizeControl, useBlockProps, store as blockEditorStore, } from '@wordpress/block-editor'; import { useSelect, useDispatch } from '@wordpress/data'; -import { pin, list, grid } from '@wordpress/icons'; +import { + pin, + list, + grid, + alignNone, + positionLeft, + positionCenter, + positionRight, +} from '@wordpress/icons'; import { store as coreStore } from '@wordpress/core-data'; import { store as noticeStore } from '@wordpress/notices'; import { useInstanceId } from '@wordpress/compose'; @@ -197,6 +205,29 @@ export default function LatestPostsEdit( { attributes, setAttributes } ) { setAttributes( { categories: allCategories } ); }; + const imageAlignmentOptions = [ + { + value: 'none', + icon: alignNone, + label: __( 'None' ), + }, + { + value: 'left', + icon: positionLeft, + label: __( 'Left' ), + }, + { + value: 'center', + icon: positionCenter, + label: __( 'Center' ), + }, + { + value: 'right', + icon: positionRight, + label: __( 'Right' ), + }, + ]; + const hasPosts = !! latestPosts?.length; const inspectorControls = ( <InspectorControls> @@ -303,21 +334,32 @@ export default function LatestPostsEdit( { attributes, setAttributes } ) { } ) } /> - <BaseControl className="editor-latest-posts-image-alignment-control"> - <BaseControl.VisualLabel> - { __( 'Image alignment' ) } - </BaseControl.VisualLabel> - <BlockAlignmentToolbar - value={ featuredImageAlign } - onChange={ ( value ) => - setAttributes( { - featuredImageAlign: value, - } ) + <ToggleGroupControl + className="editor-latest-posts-image-alignment-control" + __nextHasNoMarginBottom + __next40pxDefaultSize + label={ __( 'Image alignment' ) } + value={ featuredImageAlign || 'none' } + onChange={ ( value ) => + setAttributes( { + featuredImageAlign: + value !== 'none' ? value : undefined, + } ) + } + > + { imageAlignmentOptions.map( + ( { value, icon, label } ) => { + return ( + <ToggleGroupControlOptionIcon + key={ value } + value={ value } + icon={ icon } + label={ label } + /> + ); } - controls={ [ 'left', 'center', 'right' ] } - isCollapsed={ false } - /> - </BaseControl> + ) } + </ToggleGroupControl> <ToggleControl __nextHasNoMarginBottom label={ __( 'Add link to featured image' ) } diff --git a/packages/block-library/src/latest-posts/editor.scss b/packages/block-library/src/latest-posts/editor.scss index 02651ee8495125..fe901480974461 100644 --- a/packages/block-library/src/latest-posts/editor.scss +++ b/packages/block-library/src/latest-posts/editor.scss @@ -9,12 +9,6 @@ display: inline; } -.editor-latest-posts-image-alignment-control { - .components-toolbar { - border-radius: $radius-block-ui; - } -} - :root :where(.wp-block-latest-posts) { padding-left: 2.5em; } From e0577df14a6eaad580afe94abfb736e8a04c0fc8 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 9 Aug 2024 19:13:06 +0900 Subject: [PATCH 0328/1908] Post Editor: Force iframe editor when zoom-out mode (#64316) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> --- .../edit-post/src/components/layout/use-should-iframe.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/edit-post/src/components/layout/use-should-iframe.js b/packages/edit-post/src/components/layout/use-should-iframe.js index 03efae92c72f7d..248ea53109f250 100644 --- a/packages/edit-post/src/components/layout/use-should-iframe.js +++ b/packages/edit-post/src/components/layout/use-should-iframe.js @@ -4,6 +4,7 @@ import { store as editorStore } from '@wordpress/editor'; import { useSelect } from '@wordpress/data'; import { store as blocksStore } from '@wordpress/blocks'; +import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Internal dependencies @@ -18,8 +19,10 @@ export function useShouldIframe() { hasV3BlocksOnly, isEditingTemplate, hasMetaBoxes, + isZoomOutMode, } = useSelect( ( select ) => { const { getEditorSettings, getCurrentPostType } = select( editorStore ); + const { __unstableGetEditorMode } = select( blockEditorStore ); const { getBlockTypes } = select( blocksStore ); const editorSettings = getEditorSettings(); return { @@ -29,12 +32,14 @@ export function useShouldIframe() { } ), isEditingTemplate: getCurrentPostType() === 'wp_template', hasMetaBoxes: select( editPostStore ).hasMetaBoxes(), + isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', }; }, [] ); return ( ( ( hasV3BlocksOnly || ( isGutenbergPlugin && isBlockBasedTheme ) ) && ! hasMetaBoxes ) || - isEditingTemplate + isEditingTemplate || + isZoomOutMode ); } From 22e4cc2e24e89901d7b0b8099a7ecc4f695e04e2 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 9 Aug 2024 12:18:49 +0200 Subject: [PATCH 0329/1908] Composite: stabilize new ariakit implementation (#63564) * Point legacy exports directly to the source (instead of folder root) * Swap default folder export to new version * Apply compound component naming * Export new version from the package * Update (fix) private APIs exports * Update composite implementation to use new compound naming * Update references to Composite inside components package * Update Storybook entry points for both legacy and current * Fix Storybook generated docs * Add todo * Remove unncecessary code * CHANGELOG * README * Add JSDocs to Composite exports * Move current implementation out of `current` folder * Fix import in the legacy implementation * Update docs manifest * Fix type in Storybook example * Add JSDocs for Storybook docs * Apply Overloaded naming convention * Update README * Fix typo * Update legacy storybook title/id, make sure JSDocs refer to unstable version * Derive types instead of importing them directly from ariakit * Add JSDoc snippet for stable component * Remove unnecessary JSDoc code * Remove unnecessary display name * Assign display names via Object.assign to comply with TS and get correct results in Storybook * Update subcomponent TS ignore comment to align with other components * Remove unnecessary store prop in circular option picker Composite.Item should pick up the store from context without explicit prop * Add first-party types, rewrite components with one unique forwardRef call * Use the newly added types instead of using the Parameters<> util * Fix Storybook story type * Remove unnecessary ts-expect-error * Use `CompositeStore` type directly * Manual Storybook args table * Tweak display name fallback * README * Mark `store` prop on `Composite` as required --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- docs/manifest.json | 6 + packages/components/CHANGELOG.md | 4 + .../src/alignment-matrix-control/cell.tsx | 6 +- .../src/alignment-matrix-control/index.tsx | 6 +- .../circular-option-picker-option.tsx | 11 +- .../circular-option-picker.tsx | 2 +- .../src/circular-option-picker/types.ts | 5 +- packages/components/src/composite/README.md | 176 ++++++++++++++ .../components/src/composite/current/index.ts | 20 -- .../composite/current/stories/index.story.tsx | 86 ------- packages/components/src/composite/index.ts | 7 - packages/components/src/composite/index.tsx | 177 ++++++++++++++ .../components/src/composite/legacy/index.tsx | 29 +-- .../composite/legacy/stories/index.story.tsx | 3 +- .../src/composite/legacy/stories/utils.tsx | 19 ++ .../src/composite/stories/index.story.tsx | 218 ++++++++++++++++++ .../composite/{current => }/stories/utils.tsx | 13 +- packages/components/src/composite/types.ts | 47 ++++ packages/components/src/composite/v2.ts | 4 - packages/components/src/index.ts | 3 +- packages/components/src/private-apis.ts | 18 +- .../src/dataviews-layouts/list/index.tsx | 1 + 22 files changed, 700 insertions(+), 161 deletions(-) create mode 100644 packages/components/src/composite/README.md delete mode 100644 packages/components/src/composite/current/index.ts delete mode 100644 packages/components/src/composite/current/stories/index.story.tsx delete mode 100644 packages/components/src/composite/index.ts create mode 100644 packages/components/src/composite/index.tsx create mode 100644 packages/components/src/composite/stories/index.story.tsx rename packages/components/src/composite/{current => }/stories/utils.tsx (86%) create mode 100644 packages/components/src/composite/types.ts delete mode 100644 packages/components/src/composite/v2.ts diff --git a/docs/manifest.json b/docs/manifest.json index 1704e6d711510f..b483449872cc76 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -767,6 +767,12 @@ "markdown_source": "../packages/components/src/combobox-control/README.md", "parent": "components" }, + { + "title": "Composite", + "slug": "composite", + "markdown_source": "../packages/components/src/composite/README.md", + "parent": "components" + }, { "title": "ConfirmDialog", "slug": "confirm-dialog", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 47afb0711090d8..dca5b6e03dedc3 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### New Features + +- `Composite`: add stable version of the component ([#63564](https://github.com/WordPress/gutenberg/pull/63564)). + ### Enhancements - `TimePicker`: add `hideLabelFromVision` prop ([#64267](https://github.com/WordPress/gutenberg/pull/64267)). diff --git a/packages/components/src/alignment-matrix-control/cell.tsx b/packages/components/src/alignment-matrix-control/cell.tsx index 162ca879f1a7e5..6e045c26694f4e 100644 --- a/packages/components/src/alignment-matrix-control/cell.tsx +++ b/packages/components/src/alignment-matrix-control/cell.tsx @@ -1,7 +1,7 @@ /** * Internal dependencies */ -import { CompositeItem } from '../composite/v2'; +import { Composite } from '../composite'; import Tooltip from '../tooltip'; import { VisuallyHidden } from '../visually-hidden'; @@ -26,7 +26,7 @@ export default function Cell( { return ( <Tooltip text={ tooltipText }> - <CompositeItem + <Composite.Item id={ id } render={ <CellView { ...props } role="gridcell" /> } > @@ -35,7 +35,7 @@ export default function Cell( { hidden element instead of aria-label. */ } <VisuallyHidden>{ value }</VisuallyHidden> <Point isActive={ isActive } role="presentation" /> - </CompositeItem> + </Composite.Item> </Tooltip> ); } diff --git a/packages/components/src/alignment-matrix-control/index.tsx b/packages/components/src/alignment-matrix-control/index.tsx index eaec8a285b0c57..1d22c3560625db 100644 --- a/packages/components/src/alignment-matrix-control/index.tsx +++ b/packages/components/src/alignment-matrix-control/index.tsx @@ -13,7 +13,7 @@ import { useInstanceId } from '@wordpress/compose'; * Internal dependencies */ import Cell from './cell'; -import { Composite, CompositeRow, useCompositeStore } from '../composite/v2'; +import { Composite, useCompositeStore } from '../composite'; import { Root, Row } from './styles/alignment-matrix-control-styles'; import AlignmentMatrixControlIcon from './icon'; import { GRID, getItemId, getItemValue } from './utils'; @@ -87,7 +87,7 @@ export function AlignmentMatrixControl( { } > { GRID.map( ( cells, index ) => ( - <CompositeRow render={ <Row role="row" /> } key={ index }> + <Composite.Row render={ <Row role="row" /> } key={ index }> { cells.map( ( cell ) => { const cellId = getItemId( baseId, cell ); const isActive = cellId === activeId; @@ -101,7 +101,7 @@ export function AlignmentMatrixControl( { /> ); } ) } - </CompositeRow> + </Composite.Row> ) ) } </Composite> ); diff --git a/packages/components/src/circular-option-picker/circular-option-picker-option.tsx b/packages/components/src/circular-option-picker/circular-option-picker-option.tsx index 6c00a0e5d0bf1a..35a2f427134f40 100644 --- a/packages/components/src/circular-option-picker/circular-option-picker-option.tsx +++ b/packages/components/src/circular-option-picker/circular-option-picker-option.tsx @@ -16,9 +16,9 @@ import { Icon, check } from '@wordpress/icons'; */ import { CircularOptionPickerContext } from './circular-option-picker-context'; import Button from '../button'; -import { CompositeItem } from '../composite/v2'; +import { Composite } from '../composite'; import Tooltip from '../tooltip'; -import type { OptionProps, CircularOptionPickerCompositeStore } from './types'; +import type { OptionProps } from './types'; function UnforwardedOptionAsButton( props: { @@ -45,7 +45,9 @@ function UnforwardedOptionAsOption( id: string; className?: string; isSelected?: boolean; - compositeStore: CircularOptionPickerCompositeStore; + compositeStore: NonNullable< + React.ComponentProps< typeof Composite >[ 'store' ] + >; }, forwardedRef: ForwardedRef< any > ) { @@ -57,7 +59,7 @@ function UnforwardedOptionAsOption( } return ( - <CompositeItem + <Composite.Item render={ <Button { ...additionalProps } @@ -66,7 +68,6 @@ function UnforwardedOptionAsOption( ref={ forwardedRef } /> } - store={ compositeStore } id={ id } /> ); diff --git a/packages/components/src/circular-option-picker/circular-option-picker.tsx b/packages/components/src/circular-option-picker/circular-option-picker.tsx index cd2ddcf90d7ce0..c1e719f2d4f665 100644 --- a/packages/components/src/circular-option-picker/circular-option-picker.tsx +++ b/packages/components/src/circular-option-picker/circular-option-picker.tsx @@ -13,7 +13,7 @@ import { isRTL } from '@wordpress/i18n'; * Internal dependencies */ import { CircularOptionPickerContext } from './circular-option-picker-context'; -import { Composite, useCompositeStore } from '../composite/v2'; +import { Composite, useCompositeStore } from '../composite'; import type { CircularOptionPickerProps, ListboxCircularOptionPickerProps, diff --git a/packages/components/src/circular-option-picker/types.ts b/packages/components/src/circular-option-picker/types.ts index 519d81d5905107..e23ff4165f0580 100644 --- a/packages/components/src/circular-option-picker/types.ts +++ b/packages/components/src/circular-option-picker/types.ts @@ -14,7 +14,7 @@ import type { Icon } from '@wordpress/icons'; import type { ButtonAsButtonProps } from '../button/types'; import type { DropdownProps } from '../dropdown/types'; import type { WordPressComponentProps } from '../context'; -import type { CompositeStore } from '../composite/v2'; +import type { Composite } from '../composite'; type CommonCircularOptionPickerProps = { /** @@ -123,8 +123,7 @@ export type OptionProps = Omit< >; }; -export type CircularOptionPickerCompositeStore = CompositeStore; export type CircularOptionPickerContextProps = { baseId?: string; - compositeStore?: CircularOptionPickerCompositeStore; + compositeStore?: React.ComponentProps< typeof Composite >[ 'store' ]; }; diff --git a/packages/components/src/composite/README.md b/packages/components/src/composite/README.md new file mode 100644 index 00000000000000..59953f1273a054 --- /dev/null +++ b/packages/components/src/composite/README.md @@ -0,0 +1,176 @@ +# `Composite` + +`Composite` provides a single tab stop on the page and allows navigation through the focusable descendants with arrow keys. This abstract component is based on the [WAI-ARIA Composite Role⁠](https://w3c.github.io/aria/#composite). + +See the [Ariakit docs for the `Composite` component](https://ariakit.org/components/composite). + +## Usage + +```jsx +const store = useCompositeStore(); +<Composite store={store}> + <Composite.Group> + <Composite.GroupLabel>Label</Composite.GroupLabel> + <Composite.Item>Item 1</Composite.Item> + <Composite.Item>Item 2</Composite.Item> + </CompositeGroup> +</Composite> +``` + +## Hooks + +### `useCompositeStore` + +Creates a composite store. + +#### Props + +##### `activeId`: `string | null` + +The current active item id. The active item is the element within the composite widget that has either DOM or virtual focus. + +- Required: no + +##### `defaultActiveId`: `string | null` + +The composite item id that should be active by default when the composite widget is rendered. If `null`, the composite element itself will have focus and users will be able to navigate to it using arrow keys. If `undefined`, the first enabled item will be focused. + +- Required: no + +##### `setActiveId`: `((activeId: string | null | undefined) => void)` + +A callback that gets called when the activeId state changes. + +- Required: no + +##### `focusLoop`: `boolean | 'horizontal' | 'vertical' | 'both'` + +Determines how the focus behaves when the user reaches the end of the composite widget. + +- Required: no +- Default: `false` + +##### `focusShift`: `boolean` + +Works only on two-dimensional composite widgets. If enabled, moving up or down when there's no next item or when the next item is disabled will shift to the item right before it. + +- Required: no +- Default: `false` + +##### `focusWrap`: `boolean` + +Works only on two-dimensional composite widgets. If enabled, moving to the next item from the last one in a row or column will focus on the first item in the next row or column and vice-versa. + +- Required: no +- Default: `false` + +##### `virtualFocus`: `boolean` + +If enabled, the composite element will act as an aria-activedescendant⁠ container instead of roving tabindex⁠. DOM focus will remain on the composite element while its items receive virtual focus. In both scenarios, the item in focus will carry the data-active-item attribute. + +- Required: no +- Default: `false` + +##### `orientation`: `'horizontal' | 'vertical' | 'both'` + +Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the orientation value determines which arrow keys can be used to move focus. It doesn't have any effect on two-dimensional composites. + +- Required: no +- Default: `'both'` + +##### `rtl`: `boolean` + +Determines how the next and previous functions will behave. If rtl is set to true, they will be inverted. This only affects the composite widget behavior. You still need to set dir=`rtl` on HTML/CSS. + +- Required: no +- Default: `false` + +## Components + +### `Composite` + +Renders a composite widget. + +#### Props + +##### `store`: `CompositeStore<CompositeStoreItem>` + +Object returned by the `useCompositeStore` hook. + +- Required: yes + +##### `render`: `RenderProp<React.HTMLAttributes<any> & { ref?: React.Ref<any> | undefined; }> | React.ReactElement<any, string | React.JSXElementConstructor<any>>` + +Allows the component to be rendered as a different HTML element or React component. The value can be a React element or a function that takes in the original component props and gives back a React element with the props merged. + +- Required: no + +##### `children`: `React.ReactNode` + +The contents of the component. + +- Required: no + +### `Composite.Group` + +Renders a group element for composite items. + +##### `render`: `RenderProp<React.HTMLAttributes<any> & { ref?: React.Ref<any> | undefined; }> | React.ReactElement<any, string | React.JSXElementConstructor<any>>` + +Allows the component to be rendered as a different HTML element or React component. The value can be a React element or a function that takes in the original component props and gives back a React element with the props merged. + +- Required: no + +##### `children`: `React.ReactNode` + +The contents of the component. + +- Required: no + +### `Composite.GroupLabel` + +Renders a label in a composite group. This component must be wrapped with `Composite.Group` so the `aria-labelledby` prop is properly set on the composite group element. + +##### `render`: `RenderProp<React.HTMLAttributes<any> & { ref?: React.Ref<any> | undefined; }> | React.ReactElement<any, string | React.JSXElementConstructor<any>>` + +Allows the component to be rendered as a different HTML element or React component. The value can be a React element or a function that takes in the original component props and gives back a React element with the props merged. + +- Required: no + +##### `children`: `React.ReactNode` + +The contents of the component. + +- Required: no + +### `Composite.Item` + +Renders a composite item. + +##### `render`: `RenderProp<React.HTMLAttributes<any> & { ref?: React.Ref<any> | undefined; }> | React.ReactElement<any, string | React.JSXElementConstructor<any>>` + +Allows the component to be rendered as a different HTML element or React component. The value can be a React element or a function that takes in the original component props and gives back a React element with the props merged. + +- Required: no + +##### `children`: `React.ReactNode` + +The contents of the component. + +- Required: no + +### `Composite.Row` + +Renders a composite row. Wrapping `Composite.Item` elements within `Composite.Row` will create a two-dimensional composite widget, such as a grid. + +##### `render`: `RenderProp<React.HTMLAttributes<any> & { ref?: React.Ref<any> | undefined; }> | React.ReactElement<any, string | React.JSXElementConstructor<any>>` + +Allows the component to be rendered as a different HTML element or React component. The value can be a React element or a function that takes in the original component props and gives back a React element with the props merged. + +- Required: no + +##### `children`: `React.ReactNode` + +The contents of the component. + +- Required: no diff --git a/packages/components/src/composite/current/index.ts b/packages/components/src/composite/current/index.ts deleted file mode 100644 index 96379f00296516..00000000000000 --- a/packages/components/src/composite/current/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Composite is a component that may contain navigable items represented by - * CompositeItem. It's inspired by the WAI-ARIA Composite Role and implements - * all the keyboard navigation mechanisms to ensure that there's only one - * tab stop for the whole Composite element. This means that it can behave as - * a roving tabindex or aria-activedescendant container. - * - * @see https://ariakit.org/components/composite - */ - -export { - Composite, - CompositeGroup, - CompositeGroupLabel, - CompositeItem, - CompositeRow, - useCompositeStore, -} from '@ariakit/react'; - -export type { CompositeStore, CompositeStoreProps } from '@ariakit/react'; diff --git a/packages/components/src/composite/current/stories/index.story.tsx b/packages/components/src/composite/current/stories/index.story.tsx deleted file mode 100644 index 335ebc3244c918..00000000000000 --- a/packages/components/src/composite/current/stories/index.story.tsx +++ /dev/null @@ -1,86 +0,0 @@ -/** - * External dependencies - */ -import type { Meta, StoryFn } from '@storybook/react'; - -/** - * WordPress dependencies - */ -import { isRTL } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import { - Composite, - CompositeGroup, - CompositeRow, - CompositeItem, - useCompositeStore, -} from '..'; -import { UseCompositeStorePlaceholder, transform } from './utils'; - -const meta: Meta< typeof UseCompositeStorePlaceholder > = { - title: 'Components/Composite (V2)', - component: UseCompositeStorePlaceholder, - subcomponents: { - // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - Composite, - // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - CompositeGroup, - // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - CompositeRow, - // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - CompositeItem, - }, - tags: [ 'status-private' ], - parameters: { - docs: { - canvas: { sourceState: 'shown' }, - source: { transform }, - extractArgTypes: ( component: React.FunctionComponent ) => { - const name = component.displayName; - const path = name - ?.replace( - /([a-z])([A-Z])/g, - ( _, a, b ) => `${ a }-${ b.toLowerCase() }` - ) - .toLowerCase(); - const url = `https://ariakit.org/reference/${ path }`; - return { - props: { - name: 'Props', - description: `See <a href="${ url }">Ariakit docs</a> for <code>${ name }</code>`, - table: { type: { summary: undefined } }, - }, - }; - }, - }, - }, -}; -export default meta; - -export const Default: StoryFn< typeof Composite > = ( { ...initialState } ) => { - const rtl = isRTL(); - const store = useCompositeStore( { rtl, ...initialState } ); - - return ( - <Composite role="grid" store={ store } aria-label="Ariakit Composite"> - <CompositeRow role="row"> - <CompositeItem role="gridcell">Item A1</CompositeItem> - <CompositeItem role="gridcell">Item A2</CompositeItem> - <CompositeItem role="gridcell">Item A3</CompositeItem> - </CompositeRow> - <CompositeRow role="row"> - <CompositeItem role="gridcell">Item B1</CompositeItem> - <CompositeItem role="gridcell">Item B2</CompositeItem> - <CompositeItem role="gridcell">Item B3</CompositeItem> - </CompositeRow> - <CompositeRow role="row"> - <CompositeItem role="gridcell">Item C1</CompositeItem> - <CompositeItem role="gridcell">Item C2</CompositeItem> - <CompositeItem role="gridcell">Item C3</CompositeItem> - </CompositeRow> - </Composite> - ); -}; diff --git a/packages/components/src/composite/index.ts b/packages/components/src/composite/index.ts deleted file mode 100644 index aa06a6adf36ef2..00000000000000 --- a/packages/components/src/composite/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Originally this pointed at a Reakit implementation of -// `Composite`, but we are removing Reakit entirely from the -// codebase. We will continue to support the Reakit API -// through the 'legacy' version, which uses Ariakit under -// the hood. - -export * from './legacy'; diff --git a/packages/components/src/composite/index.tsx b/packages/components/src/composite/index.tsx new file mode 100644 index 00000000000000..9496bdb9e98664 --- /dev/null +++ b/packages/components/src/composite/index.tsx @@ -0,0 +1,177 @@ +/** + * Composite is a component that may contain navigable items represented by + * Composite.Item. It's inspired by the WAI-ARIA Composite Role and implements + * all the keyboard navigation mechanisms to ensure that there's only one + * tab stop for the whole Composite element. This means that it can behave as + * a roving tabindex or aria-activedescendant container. + * + * @see https://ariakit.org/components/composite + */ + +/** + * External dependencies + */ +import * as Ariakit from '@ariakit/react'; + +/** + * WordPress dependencies + */ +import { forwardRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import type { + CompositeStoreProps, + CompositeProps, + CompositeGroupProps, + CompositeGroupLabelProps, + CompositeItemProps, + CompositeRowProps, +} from './types'; + +/** + * Creates a composite store. + * @param props + * @see https://ariakit.org/reference/use-composite-store + * @example + * ```jsx + * const store = useCompositeStore(); + * <Composite store={store}> + * <Composite.Item>Item</Composite.Item> + * <Composite.Item>Item</Composite.Item> + * <Composite.Item>Item</Composite.Item> + * </Composite> + * ``` + */ +export function useCompositeStore( props: CompositeStoreProps ) { + return Ariakit.useCompositeStore( props ); +} + +const Group = forwardRef< + HTMLDivElement, + WordPressComponentProps< CompositeGroupProps, 'div', false > +>( function CompositeGroup( props, ref ) { + return <Ariakit.CompositeGroup { ...props } ref={ ref } />; +} ); +Group.displayName = 'Composite.Group'; + +const GroupLabel = forwardRef< + HTMLDivElement, + WordPressComponentProps< CompositeGroupLabelProps, 'div', false > +>( function CompositeGroupLabel( props, ref ) { + return <Ariakit.CompositeGroupLabel { ...props } ref={ ref } />; +} ); +GroupLabel.displayName = 'Composite.GroupLabel'; + +const Item = forwardRef< + HTMLButtonElement, + WordPressComponentProps< CompositeItemProps, 'button', false > +>( function CompositeItem( props, ref ) { + return <Ariakit.CompositeItem { ...props } ref={ ref } />; +} ); +Item.displayName = 'Composite.Item'; + +const Row = forwardRef< + HTMLDivElement, + WordPressComponentProps< CompositeRowProps, 'div', false > +>( function CompositeRow( props, ref ) { + return <Ariakit.CompositeRow { ...props } ref={ ref } />; +} ); +Row.displayName = 'Composite.Row'; + +/** + * Renders a composite widget. + * @see https://ariakit.org/reference/composite + * @example + * ```jsx + * const store = useCompositeStore(); + * <Composite store={store}> + * <Composite.Item>Item 1</Composite.Item> + * <Composite.Item>Item 2</Composite.Item> + * </Composite> + * ``` + */ +export const Composite = Object.assign( + forwardRef< + HTMLDivElement, + WordPressComponentProps< CompositeProps, 'div', false > + >( function CompositeRow( props, ref ) { + return <Ariakit.Composite { ...props } ref={ ref } />; + } ), + { + displayName: 'Composite', + /** + * Renders a group element for composite items. + * @see https://ariakit.org/reference/composite-group + * @example + * ```jsx + * const store = useCompositeStore(); + * <Composite store={store}> + * <Composite.Group> + * <Composite.GroupLabel>Label</Composite.GroupLabel> + * <Composite.Item>Item 1</Composite.Item> + * <Composite.Item>Item 2</Composite.Item> + * </CompositeGroup> + * </Composite> + * ``` + */ + Group, + /** + * Renders a label in a composite group. This component must be wrapped with + * `Composite.Group` so the `aria-labelledby` prop is properly set on the + * composite group element. + * @see https://ariakit.org/reference/composite-group-label + * @example + * ```jsx + * const store = useCompositeStore(); + * <Composite store={store}> + * <Composite.Group> + * <Composite.GroupLabel>Label</Composite.GroupLabel> + * <Composite.Item>Item 1</Composite.Item> + * <Composite.Item>Item 2</Composite.Item> + * </CompositeGroup> + * </Composite> + * ``` + */ + GroupLabel, + /** + * Renders a composite item. + * @see https://ariakit.org/reference/composite-item + * @example + * ```jsx + * const store = useCompositeStore(); + * <Composite store={store}> + * <Composite.Item>Item 1</Composite.Item> + * <Composite.Item>Item 2</Composite.Item> + * <Composite.Item>Item 3</Composite.Item> + * </Composite> + * ``` + */ + Item, + /** + * Renders a composite row. Wrapping `Composite.Item` elements within + * `Composite.Row` will create a two-dimensional composite widget, such as a + * grid. + * @see https://ariakit.org/reference/composite-row + * @example + * ```jsx + * const store = useCompositeStore(); + * <Composite store={store}> + * <Composite.Row> + * <Composite.Item>Item 1.1</Composite.Item> + * <Composite.Item>Item 1.2</Composite.Item> + * <Composite.Item>Item 1.3</Composite.Item> + * </Composite.Row> + * <Composite.Row> + * <Composite.Item>Item 2.1</Composite.Item> + * <Composite.Item>Item 2.2</Composite.Item> + * <Composite.Item>Item 2.3</Composite.Item> + * </Composite.Row> + * </Composite> + * ``` + */ + Row, + } +); diff --git a/packages/components/src/composite/legacy/index.tsx b/packages/components/src/composite/legacy/index.tsx index 5c5c674b5086b8..dffdc1a2066d47 100644 --- a/packages/components/src/composite/legacy/index.tsx +++ b/packages/components/src/composite/legacy/index.tsx @@ -5,6 +5,11 @@ * tab stop for the whole Composite element. This means that it can behave as * a roving tabindex or aria-activedescendant container. * + * This file aims at providing components that are as close as possible to the + * original `reakit`-based implementation (which was removed from the codebase), + * although it is recommended that consumers of the package switch to the stable, + * un-prefixed, `ariakit`-based version of `Composite`. + * * @see https://ariakit.org/components/composite */ @@ -16,7 +21,7 @@ import { forwardRef } from '@wordpress/element'; /** * Internal dependencies */ -import * as Current from '../current'; +import { Composite as Current, useCompositeStore } from '..'; import { useInstanceId } from '@wordpress/compose'; type Orientation = 'horizontal' | 'vertical'; @@ -73,7 +78,7 @@ export interface LegacyStateOptions { type Component = React.FunctionComponent< any >; -type CompositeStore = ReturnType< typeof Current.useCompositeStore >; +type CompositeStore = ReturnType< typeof useCompositeStore >; type CompositeStoreState = { store: CompositeStore }; export type CompositeState = CompositeStoreState & Required< Pick< LegacyStateOptions, 'baseId' > >; @@ -93,9 +98,9 @@ type CompositeComponent< C extends Component > = ( ) => React.ReactElement; type CompositeComponentProps = CompositeState & ( - | ComponentProps< typeof Current.CompositeGroup > - | ComponentProps< typeof Current.CompositeItem > - | ComponentProps< typeof Current.CompositeRow > + | ComponentProps< typeof Current.Group > + | ComponentProps< typeof Current.Item > + | ComponentProps< typeof Current.Row > ); function mapLegacyStatePropsToComponentProps( @@ -145,19 +150,15 @@ function proxyComposite< C extends Component >( // provided role, and returning the appropriate component. const unproxiedCompositeGroup = forwardRef< any, - React.ComponentPropsWithoutRef< - typeof Current.CompositeGroup | typeof Current.CompositeRow - > + React.ComponentPropsWithoutRef< typeof Current.Group | typeof Current.Row > >( ( { role, ...props }, ref ) => { - const Component = - role === 'row' ? Current.CompositeRow : Current.CompositeGroup; + const Component = role === 'row' ? Current.Row : Current.Group; return <Component ref={ ref } role={ role } { ...props } />; } ); -unproxiedCompositeGroup.displayName = 'CompositeGroup'; -export const Composite = proxyComposite( Current.Composite, { baseId: 'id' } ); +export const Composite = proxyComposite( Current, { baseId: 'id' } ); export const CompositeGroup = proxyComposite( unproxiedCompositeGroup ); -export const CompositeItem = proxyComposite( Current.CompositeItem, { +export const CompositeItem = proxyComposite( Current.Item, { focusable: 'accessibleWhenDisabled', } ); @@ -178,7 +179,7 @@ export function useCompositeState( return { baseId: useInstanceId( Composite, 'composite', baseId ), - store: Current.useCompositeStore( { + store: useCompositeStore( { defaultActiveId, rtl, orientation, diff --git a/packages/components/src/composite/legacy/stories/index.story.tsx b/packages/components/src/composite/legacy/stories/index.story.tsx index e46d656a16810e..1b8e07e9bbf560 100644 --- a/packages/components/src/composite/legacy/stories/index.story.tsx +++ b/packages/components/src/composite/legacy/stories/index.story.tsx @@ -15,7 +15,8 @@ import { import { UseCompositeStatePlaceholder, transform } from './utils'; const meta: Meta< typeof UseCompositeStatePlaceholder > = { - title: 'Components/Composite', + title: 'Components (Deprecated)/Composite (Unstable)', + id: 'components-composite-unstable', component: UseCompositeStatePlaceholder, subcomponents: { Composite, diff --git a/packages/components/src/composite/legacy/stories/utils.tsx b/packages/components/src/composite/legacy/stories/utils.tsx index 06edd348634695..2fb51c845f9fbe 100644 --- a/packages/components/src/composite/legacy/stories/utils.tsx +++ b/packages/components/src/composite/legacy/stories/utils.tsx @@ -8,6 +8,25 @@ import type { StoryContext } from '@storybook/react'; */ import type { LegacyStateOptions } from '..'; +/** + * Renders a composite widget. + * + * This unstable component is deprecated. Use `Composite` instead. + * + * ```jsx + * import { + * __unstableUseCompositeState as useCompositeState, + * __unstableComposite as Composite, + * __unstableCompositeItem as CompositeItem, + * } from '@wordpress/components'; + * + * const state = useCompositeState(); + * <Composite state={ state }> + * <CompositeItem>Item 1</CompositeItem> + * <CompositeItem>Item 2</CompositeItem> + * </Composite>; + * ``` + */ export function UseCompositeStatePlaceholder( props: LegacyStateOptions ) { return ( <dl> diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx new file mode 100644 index 00000000000000..b143c1f7db05f7 --- /dev/null +++ b/packages/components/src/composite/stories/index.story.tsx @@ -0,0 +1,218 @@ +/** + * External dependencies + */ +import type { Meta, StoryFn } from '@storybook/react'; + +/** + * WordPress dependencies + */ +import { isRTL } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { Composite, useCompositeStore } from '..'; +import { UseCompositeStorePlaceholder, transform } from './utils'; + +const meta: Meta< typeof UseCompositeStorePlaceholder > = { + title: 'Components/Composite', + component: UseCompositeStorePlaceholder, + subcomponents: { + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + Composite, + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + 'Composite.Group': Composite.Group, + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + 'Composite.GroupLabel': Composite.GroupLabel, + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + 'Composite.Row': Composite.Row, + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + 'Composite.Item': Composite.Item, + }, + parameters: { + docs: { + canvas: { sourceState: 'shown' }, + source: { transform }, + extractArgTypes: ( component: React.FunctionComponent ) => { + const commonArgTypes = { + render: { + name: 'render', + description: + 'Allows the component to be rendered as a different HTML element or React component. The value can be a React element or a function that takes in the original component props and gives back a React element with the props merged.', + table: { + type: { + summary: + 'RenderProp<React.HTMLAttributes<any> & { ref?: React.Ref<any> | undefined; }> | React.ReactElement<any, string | React.JSXElementConstructor<any>>', + }, + }, + }, + children: { + name: 'children', + description: 'The contents of the component.', + table: { type: { summary: 'React.ReactNode' } }, + }, + }; + const argTypes = { + useCompositeStore: { + activeId: { + name: 'activeId', + description: + 'The current active item id. The active item is the element within the composite widget that has either DOM or virtual focus.', + table: { type: { summary: 'string | null' } }, + }, + defaultActiveId: { + name: 'defaultActiveId', + description: + 'The composite item id that should be active by default when the composite widget is rendered. If `null`, the composite element itself will have focus and users will be able to navigate to it using arrow keys. If `undefined`, the first enabled item will be focused.', + table: { type: { summary: 'string | null' } }, + }, + setActiveId: { + name: 'setActiveId', + description: + 'A callback that gets called when the activeId state changes.', + table: { + type: { + summary: + '((activeId: string | null | undefined) => void)', + }, + }, + }, + focusLoop: { + name: 'focusLoop', + description: + 'Determines how the focus behaves when the user reaches the end of the composite widget.', + table: { + defaultValue: { + summary: 'false', + }, + type: { + summary: + "boolean | 'horizontal' | 'vertical' | 'both'", + }, + }, + }, + focusShift: { + name: 'focusShift', + description: + "Works only on two-dimensional composite widgets. If enabled, moving up or down when there's no next item or when the next item is disabled will shift to the item right before it.", + table: { + defaultValue: { + summary: 'false', + }, + type: { + summary: 'boolean', + }, + }, + }, + focusWrap: { + name: 'focusWrap', + description: + 'Works only on two-dimensional composite widgets. If enabled, moving to the next item from the last one in a row or column will focus on the first item in the next row or column and vice-versa.', + table: { + defaultValue: { + summary: 'false', + }, + type: { + summary: 'boolean', + }, + }, + }, + virtualFocus: { + name: 'virtualFocus', + description: + 'If enabled, the composite element will act as an aria-activedescendant⁠ container instead of roving tabindex⁠. DOM focus will remain on the composite element while its items receive virtual focus. In both scenarios, the item in focus will carry the data-active-item attribute.', + table: { + defaultValue: { + summary: 'false', + }, + type: { + summary: 'boolean', + }, + }, + }, + orientation: { + name: 'orientation', + description: + "Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the orientation value determines which arrow keys can be used to move focus. It doesn't have any effect on two-dimensional composites.", + table: { + defaultValue: { + summary: "'both'", + }, + type: { + summary: + "'horizontal' | 'vertical' | 'both'", + }, + }, + }, + rtl: { + name: 'rtl', + description: + 'Determines how the next and previous functions will behave. If rtl is set to true, they will be inverted. This only affects the composite widget behavior. You still need to set dir="rtl" on HTML/CSS.', + table: { + defaultValue: { + summary: 'false', + }, + type: { + summary: 'boolean', + }, + }, + }, + }, + Composite: { + ...commonArgTypes, + store: { + name: 'store', + description: + 'Object returned by the `useCompositeStore` hook.', + table: { + type: { + summary: + 'CompositeStore<CompositeStoreItem>', + }, + }, + type: { required: true }, + }, + }, + 'Composite.Group': commonArgTypes, + 'Composite.GroupLabel': commonArgTypes, + 'Composite.Row': commonArgTypes, + 'Composite.Item': commonArgTypes, + }; + + const name = component.displayName ?? ''; + + return name in argTypes + ? argTypes[ name as keyof typeof argTypes ] + : {}; + }, + }, + }, +}; +export default meta; + +export const Default: StoryFn< typeof UseCompositeStorePlaceholder > = ( + storeProps +) => { + const rtl = isRTL(); + const store = useCompositeStore( { rtl, ...storeProps } ); + + return ( + <Composite role="grid" store={ store } aria-label="Composite"> + <Composite.Row role="row"> + <Composite.Item role="gridcell">Item A1</Composite.Item> + <Composite.Item role="gridcell">Item A2</Composite.Item> + <Composite.Item role="gridcell">Item A3</Composite.Item> + </Composite.Row> + <Composite.Row role="row"> + <Composite.Item role="gridcell">Item B1</Composite.Item> + <Composite.Item role="gridcell">Item B2</Composite.Item> + <Composite.Item role="gridcell">Item B3</Composite.Item> + </Composite.Row> + <Composite.Row role="row"> + <Composite.Item role="gridcell">Item C1</Composite.Item> + <Composite.Item role="gridcell">Item C2</Composite.Item> + <Composite.Item role="gridcell">Item C3</Composite.Item> + </Composite.Row> + </Composite> + ); +}; diff --git a/packages/components/src/composite/current/stories/utils.tsx b/packages/components/src/composite/stories/utils.tsx similarity index 86% rename from packages/components/src/composite/current/stories/utils.tsx rename to packages/components/src/composite/stories/utils.tsx index 4b2d1bba4b312b..425fb9a905bcff 100644 --- a/packages/components/src/composite/current/stories/utils.tsx +++ b/packages/components/src/composite/stories/utils.tsx @@ -6,8 +6,19 @@ import type { StoryContext } from '@storybook/react'; /** * Internal dependencies */ -import type { CompositeStoreProps } from '..'; +import type { CompositeStoreProps } from '../types'; +/** + * Renders a composite widget. + * + * ```jsx + * const store = useCompositeStore(); + * <Composite store={ store }> + * <Composite.Item>Item 1</Composite.Item> + * <Composite.Item>Item 2</Composite.Item> + * </Composite> + * ``` + */ export function UseCompositeStorePlaceholder( props: CompositeStoreProps ) { return ( <dl> diff --git a/packages/components/src/composite/types.ts b/packages/components/src/composite/types.ts new file mode 100644 index 00000000000000..438d1caaa94f8a --- /dev/null +++ b/packages/components/src/composite/types.ts @@ -0,0 +1,47 @@ +/** + * External dependencies + */ +import type * as Ariakit from '@ariakit/react'; + +export type CompositeStoreProps = Pick< + Ariakit.CompositeStoreProps, + | 'activeId' + | 'defaultActiveId' + | 'setActiveId' + | 'focusLoop' + | 'focusShift' + | 'focusWrap' + | 'virtualFocus' + | 'orientation' + | 'rtl' +>; + +export type CompositeProps = Pick< + Ariakit.CompositeProps, + 'render' | 'children' +> & { + /** + * Object returned by the `useCompositeStore` hook. + */ + store: Ariakit.CompositeStore; +}; + +export type CompositeGroupProps = Pick< + Ariakit.CompositeGroupProps, + 'render' | 'children' +>; + +export type CompositeGroupLabelProps = Pick< + Ariakit.CompositeGroupLabelProps, + 'render' | 'children' +>; + +export type CompositeItemProps = Pick< + Ariakit.CompositeItemProps, + 'render' | 'children' +>; + +export type CompositeRowProps = Pick< + Ariakit.CompositeRowProps, + 'render' | 'children' +>; diff --git a/packages/components/src/composite/v2.ts b/packages/components/src/composite/v2.ts deleted file mode 100644 index 38d3f628d368b6..00000000000000 --- a/packages/components/src/composite/v2.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Although we have migrated away from Reakit, the 'current' -// Ariakit implementation is still considered a v2. - -export * from './current'; diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index f0ea4a4b7e86b8..4c724a461e6775 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -61,7 +61,8 @@ export { CompositeGroup as __unstableCompositeGroup, CompositeItem as __unstableCompositeItem, useCompositeState as __unstableUseCompositeState, -} from './composite'; +} from './composite/legacy'; +export { Composite } from './composite'; export { ConfirmDialog as __experimentalConfirmDialog } from './confirm-dialog'; export { default as CustomSelectControl } from './custom-select-control'; export { default as Dashicon } from './dashicon'; diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index 5ff39ba364a041..699911e5ba046b 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -1,13 +1,7 @@ /** * Internal dependencies */ -import { - Composite as CompositeV2, - CompositeGroup as CompositeGroupV2, - CompositeItem as CompositeItemV2, - CompositeRow as CompositeRowV2, - useCompositeStore as useCompositeStoreV2, -} from './composite/v2'; +import { Composite, useCompositeStore } from './composite'; import { positionToPlacement as __experimentalPopoverLegacyPositionToPlacement } from './popover/utils'; import { createPrivateSlotFill } from './slot-fill'; import { @@ -28,11 +22,11 @@ import { lock } from './lock-unlock'; export const privateApis = {}; lock( privateApis, { - CompositeV2, - CompositeGroupV2, - CompositeItemV2, - CompositeRowV2, - useCompositeStoreV2, + CompositeV2: Composite, + CompositeGroupV2: Composite.Group, + CompositeItemV2: Composite.Item, + CompositeRowV2: Composite.Row, + useCompositeStoreV2: useCompositeStore, __experimentalPopoverLegacyPositionToPlacement, createPrivateSlotFill, ComponentsContext, diff --git a/packages/dataviews/src/dataviews-layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx index 00939a12984856..70eaf3af1cd619 100644 --- a/packages/dataviews/src/dataviews-layouts/list/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/list/index.tsx @@ -2,6 +2,7 @@ * External dependencies */ import clsx from 'clsx'; +// TODO: use the @wordpress/components one once public // Import CompositeStore type, which is not exported from @wordpress/components. // eslint-disable-next-line no-restricted-imports import type { CompositeStore } from '@ariakit/react'; From 34b5219842367bb111cc010cb1db9a3a593812dd Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Fri, 9 Aug 2024 11:30:20 +0100 Subject: [PATCH 0330/1908] Zoom Out: Don't hide the insertion point when hovering patterns (#64392) Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> --- .../block-editor/src/components/inserter/menu.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index e0bc29d62e1b9a..52e4e3062e9024 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -109,6 +109,7 @@ function InserterMenu( const onInsertPattern = useCallback( ( blocks, patternName ) => { + onToggleInsertionPoint( false ); onInsertBlocks( blocks, { patternName } ); onSelect(); }, @@ -123,13 +124,6 @@ function InserterMenu( [ onToggleInsertionPoint, setHoveredItem ] ); - const onHoverPattern = useCallback( - ( item ) => { - onToggleInsertionPoint( !! item ); - }, - [ onToggleInsertionPoint ] - ); - const onClickPatternCategory = useCallback( ( patternCategory, filter ) => { setSelectedPatternCategory( patternCategory ); @@ -176,7 +170,6 @@ function InserterMenu( filterValue={ delayedFilterValue } onSelect={ onSelect } onHover={ onHover } - onHoverPattern={ onHoverPattern } rootClientId={ rootClientId } clientId={ clientId } isAppender={ isAppender } @@ -199,7 +192,6 @@ function InserterMenu( delayedFilterValue, onSelect, onHover, - onHoverPattern, shouldFocusBlock, clientId, rootClientId, @@ -249,7 +241,6 @@ function InserterMenu( <PatternCategoryPreviews rootClientId={ destinationRootClientId } onInsert={ onInsertPattern } - onHover={ onHoverPattern } category={ selectedPatternCategory } patternFilter={ patternFilter } showTitlesAsTooltip @@ -259,7 +250,6 @@ function InserterMenu( ); }, [ destinationRootClientId, - onHoverPattern, onInsertPattern, onClickPatternCategory, patternFilter, From db35abd02371291dfa00562f29ea5901562da8cb Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Fri, 9 Aug 2024 19:56:49 +0900 Subject: [PATCH 0331/1908] DimensionControl: Add flag to remove bottom margin (#64346) * DimensionControl: Add flag to remove bottom margin * Add lint rule * Update in block-editor readme * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .eslintrc.js | 1 + .../components/responsive-block-control/README.md | 1 + packages/components/CHANGELOG.md | 1 + packages/components/src/dimension-control/README.md | 9 +++++++++ packages/components/src/dimension-control/index.tsx | 3 +++ packages/components/src/dimension-control/types.ts | 12 +++++------- 6 files changed, 20 insertions(+), 7 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 81408499bd34f4..cb669fb4177206 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -292,6 +292,7 @@ module.exports = { ...[ 'CheckboxControl', 'ComboboxControl', + 'DimensionControl', 'FocalPointPicker', 'RangeControl', 'SearchControl', diff --git a/packages/block-editor/src/components/responsive-block-control/README.md b/packages/block-editor/src/components/responsive-block-control/README.md index 1d99caa024a419..379e245f03ff37 100644 --- a/packages/block-editor/src/components/responsive-block-control/README.md +++ b/packages/block-editor/src/components/responsive-block-control/README.md @@ -64,6 +64,7 @@ registerBlockType( 'my-plugin/my-block', { const paddingControl = ( labelComponent, viewport ) => { return ( <DimensionControl + __nextHasNoMarginBottom label={ viewport.label } onChange={ // handle update to padding value here } value={ paddingSize } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index dca5b6e03dedc3..91c5a8c3bd012d 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -30,6 +30,7 @@ - `SelectControl`: Infer `value` type from `options` ([#64069](https://github.com/WordPress/gutenberg/pull/64069)). - `Guide`: Add `__next40pxDefaultSize` to buttons ([#64181](https://github.com/WordPress/gutenberg/pull/64181)). - `SelectControl`: Pass through `options` props ([#64211](https://github.com/WordPress/gutenberg/pull/64211)). +- `DimensionControl`: Add `__nextHasNoMarginBottom` prop to remove bottom margin ([#64346](https://github.com/WordPress/gutenberg/pull/64346)). ### Internal diff --git a/packages/components/src/dimension-control/README.md b/packages/components/src/dimension-control/README.md index 498322931b7ab6..42f4a9678c09a6 100644 --- a/packages/components/src/dimension-control/README.md +++ b/packages/components/src/dimension-control/README.md @@ -17,6 +17,7 @@ export default function MyCustomDimensionControl() { return ( <DimensionControl + __nextHasNoMarginBottom label={ 'Padding' } icon={ 'desktop' } onChange={ ( value ) => setPaddingSize( value ) } @@ -91,3 +92,11 @@ A callback which is triggered when a spacing size value changes (is selected/cli - **Required:** No A string of classes to be added to the control component. + +### __nextHasNoMarginBottom + +Start opting into the new margin-free styles that will become the default in a future version. + +- Type: `Boolean` +- Required: No +- Default: `false` diff --git a/packages/components/src/dimension-control/index.tsx b/packages/components/src/dimension-control/index.tsx index 8ba0de0ce0599c..114ebe987dd35d 100644 --- a/packages/components/src/dimension-control/index.tsx +++ b/packages/components/src/dimension-control/index.tsx @@ -31,6 +31,7 @@ import type { SelectControlSingleSelectionProps } from '../select-control/types' * * return ( * <DimensionControl + * __nextHasNoMarginBottom * label={ 'Padding' } * icon={ 'desktop' } * onChange={ ( value ) => setPaddingSize( value ) } @@ -43,6 +44,7 @@ import type { SelectControlSingleSelectionProps } from '../select-control/types' export function DimensionControl( props: DimensionControlProps ) { const { __next40pxDefaultSize = false, + __nextHasNoMarginBottom = false, label, value, sizes = sizesTable, @@ -87,6 +89,7 @@ export function DimensionControl( props: DimensionControlProps ) { return ( <SelectControl __next40pxDefaultSize={ __next40pxDefaultSize } + __nextHasNoMarginBottom={ __nextHasNoMarginBottom } className={ clsx( className, 'block-editor-dimension-control' ) } label={ selectLabel } hideLabelFromVision={ false } diff --git a/packages/components/src/dimension-control/types.ts b/packages/components/src/dimension-control/types.ts index 671454f18c8a9b..03a4edf29153b7 100644 --- a/packages/components/src/dimension-control/types.ts +++ b/packages/components/src/dimension-control/types.ts @@ -2,6 +2,7 @@ * Internal dependencies */ import type { IconType } from '../icon'; +import type { SelectControlProps } from '../select-control/types'; export type Size = { /** @@ -14,7 +15,10 @@ export type Size = { slug: string; }; -export type DimensionControlProps = { +export type DimensionControlProps = Pick< + SelectControlProps, + '__next40pxDefaultSize' | '__nextHasNoMarginBottom' +> & { /** * Label for the control. */ @@ -45,10 +49,4 @@ export type DimensionControlProps = { * @default '' */ className?: string; - /** - * Start opting into the larger default height that will become the default size in a future version. - * - * @default false - */ - __next40pxDefaultSize?: boolean; }; From 00a965cc6d299b049c9ce9f317295cf9302deccf Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 9 Aug 2024 15:13:15 +0400 Subject: [PATCH 0332/1908] Gallery: Remove 'withNotices' HoC (#64384) * Gallery: Remove 'withNotices' HoC * Relocate 'withViewportMatch' closer to its only usage Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: geriux <geriux@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/block-library/src/gallery/edit.js | 9 +-------- packages/block-library/src/gallery/gallery.native.js | 3 ++- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/block-library/src/gallery/edit.js b/packages/block-library/src/gallery/edit.js index f2faa40110dd13..1a7ce5fae04f8c 100644 --- a/packages/block-library/src/gallery/edit.js +++ b/packages/block-library/src/gallery/edit.js @@ -6,7 +6,6 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { compose } from '@wordpress/compose'; import { BaseControl, PanelBody, @@ -17,7 +16,6 @@ import { MenuGroup, MenuItem, ToolbarDropdownMenu, - withNotices, } from '@wordpress/components'; import { store as blockEditorStore, @@ -31,7 +29,6 @@ import { import { Platform, useEffect, useMemo } from '@wordpress/element'; import { __, _x, sprintf } from '@wordpress/i18n'; import { useSelect, useDispatch } from '@wordpress/data'; -import { withViewportMatch } from '@wordpress/viewport'; import { View } from '@wordpress/primitives'; import { createBlock } from '@wordpress/blocks'; import { createBlobURL } from '@wordpress/blob'; @@ -98,7 +95,7 @@ const MOBILE_CONTROL_PROPS_RANGE_CONTROL = Platform.isNative const DEFAULT_BLOCK = { name: 'core/image' }; const EMPTY_ARRAY = []; -function GalleryEdit( props ) { +export default function GalleryEdit( props ) { const { setAttributes, attributes, @@ -696,7 +693,3 @@ function GalleryEdit( props ) { </> ); } -export default compose( [ - withNotices, - withViewportMatch( { isNarrow: '< small' } ), -] )( GalleryEdit ); diff --git a/packages/block-library/src/gallery/gallery.native.js b/packages/block-library/src/gallery/gallery.native.js index 7fc280809db843..a5fa2db4fcf029 100644 --- a/packages/block-library/src/gallery/gallery.native.js +++ b/packages/block-library/src/gallery/gallery.native.js @@ -22,6 +22,7 @@ import { useState, useEffect } from '@wordpress/element'; import { mediaUploadSync } from '@wordpress/react-native-bridge'; import { WIDE_ALIGNMENTS } from '@wordpress/components'; import { useResizeObserver } from '@wordpress/compose'; +import { withViewportMatch } from '@wordpress/viewport'; const TILE_SPACING = 8; @@ -120,4 +121,4 @@ export const Gallery = ( props ) => { ); }; -export default Gallery; +export default withViewportMatch( { isNarrow: '< small' } )( Gallery ); From d31b30ed135d06963a7036206a5f4855880f63f2 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Fri, 9 Aug 2024 14:31:13 +0200 Subject: [PATCH 0333/1908] DataViews Quick Edit: Add the PostActions dropdown menu (#64393) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- docs/reference-guides/slotfills/README.md | 9 ++--- .../src/components/post-actions/index.js | 36 +++++++++---------- .../src/components/post-card-panel/index.js | 13 +++++-- .../src/components/sidebar/post-summary.js | 7 +--- 4 files changed, 30 insertions(+), 35 deletions(-) diff --git a/docs/reference-guides/slotfills/README.md b/docs/reference-guides/slotfills/README.md index 8b56ed4ce98b41..5ae68cdb5cb071 100644 --- a/docs/reference-guides/slotfills/README.md +++ b/docs/reference-guides/slotfills/README.md @@ -70,11 +70,10 @@ export default function PostSummary( { onActionPerformed } ) { const { isRemovedPostStatusPanel } = useSelect( ( select ) => { // We use isEditorPanelRemoved to hide the panel if it was programmatically removed. We do // not use isEditorPanelEnabled since this panel should not be disabled through the UI. - const { isEditorPanelRemoved, getCurrentPostType } = + const { isEditorPanelRemoved } = select( editorStore ); return { isRemovedPostStatusPanel: isEditorPanelRemoved( PANEL_NAME ), - postType: getCurrentPostType(), }; }, [] ); @@ -85,11 +84,7 @@ export default function PostSummary( { onActionPerformed } ) { <> <VStack spacing={ 4 }> <PostCardPanel - actions={ - <PostActions - onActionPerformed={ onActionPerformed } - /> - } + onActionPerformed={ onActionPerformed } /> <PostFeaturedImagePanel withPanelBody={ false } /> <PostExcerptPanel /> diff --git a/packages/editor/src/components/post-actions/index.js b/packages/editor/src/components/post-actions/index.js index 5b023956178938..9cc594233c8814 100644 --- a/packages/editor/src/components/post-actions/index.js +++ b/packages/editor/src/components/post-actions/index.js @@ -17,7 +17,6 @@ import { store as coreStore } from '@wordpress/core-data'; */ import { unlock } from '../../lock-unlock'; import { usePostActions } from './actions'; -import { store as editorStore } from '../../store'; const { DropdownMenuV2: DropdownMenu, @@ -27,25 +26,23 @@ const { kebabCase, } = unlock( componentsPrivateApis ); -export default function PostActions( { onActionPerformed, buttonProps } ) { +export default function PostActions( { postType, postId, onActionPerformed } ) { const [ isActionsMenuOpen, setIsActionsMenuOpen ] = useState( false ); - const { item, permissions, postType } = useSelect( ( select ) => { - const { getCurrentPostType, getCurrentPostId } = select( editorStore ); - const { getEditedEntityRecord, getEntityRecordPermissions } = unlock( - select( coreStore ) - ); - const _postType = getCurrentPostType(); - const _id = getCurrentPostId(); - return { - item: getEditedEntityRecord( 'postType', _postType, _id ), - permissions: getEntityRecordPermissions( - 'postType', - _postType, - _id - ), - postType: _postType, - }; - }, [] ); + const { item, permissions } = useSelect( + ( select ) => { + const { getEditedEntityRecord, getEntityRecordPermissions } = + unlock( select( coreStore ) ); + return { + item: getEditedEntityRecord( 'postType', postType, postId ), + permissions: getEntityRecordPermissions( + 'postType', + postType, + postId + ), + }; + }, + [ postId, postType ] + ); const itemWithPermissions = useMemo( () => { return { ...item, @@ -76,7 +73,6 @@ export default function PostActions( { onActionPerformed, buttonProps } ) { onClick={ () => setIsActionsMenuOpen( ! isActionsMenuOpen ) } - { ...buttonProps } /> } onOpenChange={ setIsActionsMenuOpen } diff --git a/packages/editor/src/components/post-card-panel/index.js b/packages/editor/src/components/post-card-panel/index.js index 5ac88b3dbc7f94..ed13af9b55a4aa 100644 --- a/packages/editor/src/components/post-card-panel/index.js +++ b/packages/editor/src/components/post-card-panel/index.js @@ -26,8 +26,13 @@ import { GLOBAL_POST_TYPES, } from '../../store/constants'; import { unlock } from '../../lock-unlock'; +import PostActions from '../post-actions'; -export default function PostCardPanel( { postType, postId, actions } ) { +export default function PostCardPanel( { + postType, + postId, + onActionPerformed, +} ) { const { isFrontPage, isPostsPage, title, icon, isSync } = useSelect( ( select ) => { const { __experimentalGetTemplateInfo } = select( editorStore ); @@ -105,7 +110,11 @@ export default function PostCardPanel( { postType, postId, actions } ) { </span> ) } </Text> - { actions } + <PostActions + postType={ postType } + postId={ postId } + onActionPerformed={ onActionPerformed } + /> </HStack> </div> ); diff --git a/packages/editor/src/components/sidebar/post-summary.js b/packages/editor/src/components/sidebar/post-summary.js index 573a59de827188..b19848f2247063 100644 --- a/packages/editor/src/components/sidebar/post-summary.js +++ b/packages/editor/src/components/sidebar/post-summary.js @@ -8,7 +8,6 @@ import { useSelect } from '@wordpress/data'; * Internal dependencies */ import PluginPostStatusInfo from '../plugin-post-status-info'; -import PostActions from '../post-actions'; import PostAuthorPanel from '../post-author/panel'; import PostCardPanel from '../post-card-panel'; import PostContentInformation from '../post-content-information'; @@ -63,11 +62,7 @@ export default function PostSummary( { onActionPerformed } ) { <PostCardPanel postType={ postType } postId={ postId } - actions={ - <PostActions - onActionPerformed={ onActionPerformed } - /> - } + onActionPerformed={ onActionPerformed } /> <PostFeaturedImagePanel withPanelBody={ false } /> <PostExcerptPanel /> From e44bc77a252e81a549652e6ab480d62cb8184d5e Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Fri, 9 Aug 2024 14:34:50 +0200 Subject: [PATCH 0334/1908] DataViews Quick Edit: Rely on the global save flow instead of a custom save button (#64389) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- packages/dataviews/CHANGELOG.md | 1 + .../dataform/stories/index.story.tsx | 7 +- .../dataviews/src/field-types/datetime.tsx | 6 +- .../dataviews/src/field-types/integer.tsx | 5 +- packages/dataviews/src/field-types/text.tsx | 5 +- packages/dataviews/src/types.ts | 11 +-- .../src/components/post-edit/index.js | 73 ++++++------------- .../src/components/post-actions/actions.js | 7 +- .../src/dataviews/actions/reorder-page.tsx | 7 +- 9 files changed, 50 insertions(+), 72 deletions(-) diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 239a69651a1f27..b1cb4504e72fad 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -16,6 +16,7 @@ - `setSelection` prop has been removed. Please use `onChangeSelection` instead. - `header` field property has been renamed to `label`. - `DataForm`'s `visibleFields` prop has been renamed to `fields`. +- `DataForm`'s `onChange` prop has been update to receive as argument only the fields that have changed. ### New features diff --git a/packages/dataviews/src/components/dataform/stories/index.story.tsx b/packages/dataviews/src/components/dataform/stories/index.story.tsx index 7f3c5ff879b72a..7147b9c2342638 100644 --- a/packages/dataviews/src/components/dataform/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataform/stories/index.story.tsx @@ -109,7 +109,12 @@ export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { ...form, type, } } - onChange={ setPost } + onChange={ ( edits ) => + setPost( ( prev ) => ( { + ...prev, + ...edits, + } ) ) + } /> ); }; diff --git a/packages/dataviews/src/field-types/datetime.tsx b/packages/dataviews/src/field-types/datetime.tsx index 3861a0db635d7b..c6b69048efe13c 100644 --- a/packages/dataviews/src/field-types/datetime.tsx +++ b/packages/dataviews/src/field-types/datetime.tsx @@ -41,11 +41,7 @@ function Edit< Item >( { const value = field.getValue( { item: data } ); const onChangeControl = useCallback( - ( newValue: string | null ) => - onChange( ( prevItem: Item ) => ( { - ...prevItem, - [ id ]: newValue, - } ) ), + ( newValue: string | null ) => onChange( { [ id ]: newValue } ), [ id, onChange ] ); diff --git a/packages/dataviews/src/field-types/integer.tsx b/packages/dataviews/src/field-types/integer.tsx index bd4956493232df..38570ea6fec1a5 100644 --- a/packages/dataviews/src/field-types/integer.tsx +++ b/packages/dataviews/src/field-types/integer.tsx @@ -51,10 +51,9 @@ function Edit< Item >( { const value = field.getValue( { item: data } ) ?? ''; const onChangeControl = useCallback( ( newValue: string | undefined ) => - onChange( ( prevItem: Item ) => ( { - ...prevItem, + onChange( { [ id ]: Number( newValue ), - } ) ), + } ), [ id, onChange ] ); diff --git a/packages/dataviews/src/field-types/text.tsx b/packages/dataviews/src/field-types/text.tsx index c6efb85f6f446b..5364017c629b00 100644 --- a/packages/dataviews/src/field-types/text.tsx +++ b/packages/dataviews/src/field-types/text.tsx @@ -42,10 +42,9 @@ function Edit< Item >( { const onChangeControl = useCallback( ( newValue: string ) => - onChange( ( prevItem: Item ) => ( { - ...prevItem, + onChange( { [ id ]: newValue, - } ) ), + } ), [ id, onChange ] ); diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index d8a5ee8f68ecef..34e74eabd7c7d8 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -1,12 +1,7 @@ /** * External dependencies */ -import type { - ReactElement, - ComponentType, - Dispatch, - SetStateAction, -} from 'react'; +import type { ReactElement, ComponentType } from 'react'; /** * Internal dependencies @@ -181,7 +176,7 @@ export type Form = { export type DataFormControlProps< Item > = { data: Item; field: NormalizedField< Item >; - onChange: Dispatch< SetStateAction< Item > >; + onChange: ( value: Record< string, any > ) => void; hideLabelFromVision?: boolean; }; @@ -516,5 +511,5 @@ export interface DataFormProps< Item > { data: Item; fields: Field< Item >[]; form: Form; - onChange: Dispatch< SetStateAction< Item > >; + onChange: ( value: Record< string, any > ) => void; } diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 0a56fdfe5786b7..80304f16503705 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -7,15 +7,11 @@ import clsx from 'clsx'; * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { DataForm, isItemValid } from '@wordpress/dataviews'; -import { useDispatch, useSelect, useRegistry } from '@wordpress/data'; +import { DataForm } from '@wordpress/dataviews'; +import { useDispatch, useSelect } from '@wordpress/data'; import { store as coreDataStore } from '@wordpress/core-data'; -import { - Button, - FlexItem, - __experimentalVStack as VStack, -} from '@wordpress/components'; -import { useState, useMemo } from '@wordpress/element'; +import { __experimentalVStack as VStack } from '@wordpress/components'; +import { useState, useMemo, useEffect } from '@wordpress/element'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; /** @@ -29,14 +25,12 @@ const { PostCardPanel } = unlock( editorPrivateApis ); function PostEditForm( { postType, postId } ) { const ids = useMemo( () => postId.split( ',' ), [ postId ] ); - const { initialEdits } = useSelect( + const { record } = useSelect( ( select ) => { - if ( ids.length !== 1 ) { - } return { - initialEdits: + record: ids.length === 1 - ? select( coreDataStore ).getEntityRecord( + ? select( coreDataStore ).getEditedEntityRecord( 'postType', postType, ids[ 0 ] @@ -46,60 +40,39 @@ function PostEditForm( { postType, postId } ) { }, [ postType, ids ] ); - const registry = useRegistry(); - const { saveEntityRecord } = useDispatch( coreDataStore ); + const [ multiEdits, setMultiEdits ] = useState( {} ); + const { editEntityRecord } = useDispatch( coreDataStore ); const { fields } = usePostFields(); const form = { type: 'panel', fields: [ 'title', 'author', 'date', 'comment_status' ], }; - const [ edits, setEdits ] = useState( initialEdits ); - const itemWithEdits = useMemo( () => { - return { - ...initialEdits, - ...edits, - }; - }, [ initialEdits, edits ] ); - const onSubmit = async ( event ) => { - event.preventDefault(); - - if ( ! isItemValid( itemWithEdits, fields, form ) ) { - return; - } - - const { getEntityRecord } = registry.resolveSelect( coreDataStore ); + const onChange = ( edits ) => { for ( const id of ids ) { - const item = await getEntityRecord( 'postType', postType, id ); - saveEntityRecord( 'postType', postType, { - ...item, - ...edits, - } ); + editEntityRecord( 'postType', postType, id, edits ); + if ( ids.length > 1 ) { + setMultiEdits( ( prev ) => ( { + ...prev, + ...edits, + } ) ); + } } }; + useEffect( () => { + setMultiEdits( {} ); + }, [ ids ] ); - const isUpdateDisabled = ! isItemValid( itemWithEdits, fields, form ); return ( - <VStack as="form" onSubmit={ onSubmit } spacing={ 4 }> + <VStack spacing={ 4 }> { ids.length === 1 && ( <PostCardPanel postType={ postType } postId={ ids[ 0 ] } /> ) } <DataForm - data={ itemWithEdits } + data={ ids.length === 1 ? record : multiEdits } fields={ fields } form={ form } - onChange={ setEdits } + onChange={ onChange } /> - <FlexItem> - <Button - variant="primary" - type="submit" - accessibleWhenDisabled - disabled={ isUpdateDisabled } - __next40pxDefaultSize - > - { __( 'Update' ) } - </Button> - </FlexItem> </VStack> ); } diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 5e727376a92258..ff5cd7ddbb5452 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -234,7 +234,12 @@ const useDuplicatePostAction = ( postType ) => { data={ item } fields={ fields } form={ formDuplicateAction } - onChange={ setItem } + onChange={ ( changes ) => + setItem( { + ...item, + ...changes, + } ) + } /> <HStack spacing={ 2 } justify="end"> <Button diff --git a/packages/editor/src/dataviews/actions/reorder-page.tsx b/packages/editor/src/dataviews/actions/reorder-page.tsx index 9193904f0f912c..1b9524123e7c95 100644 --- a/packages/editor/src/dataviews/actions/reorder-page.tsx +++ b/packages/editor/src/dataviews/actions/reorder-page.tsx @@ -81,7 +81,12 @@ function ReorderModal( { data={ item } fields={ fields } form={ formOrderAction } - onChange={ setItem } + onChange={ ( changes ) => + setItem( { + ...item, + ...changes, + } ) + } /> <HStack justify="right"> <Button From 266361a1362f8fdece5f77b5c1ff8cd89269bb8f Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Fri, 9 Aug 2024 17:50:59 +0200 Subject: [PATCH 0335/1908] Fix: Remove unnecessary className. (#64403) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> --- .../dataviews/src/components/dataviews-view-config/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index 28e151079008eb..0aae714c5ce27a 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -239,7 +239,6 @@ function FieldControl() { <HStack expanded> <span>{ field.label }</span> <Button - className="'dataviews-view-config__field-control-button" size="compact" onClick={ () => onChangeView( { From b4ba75fd00030a012c064974181d41ee30f81b91 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 9 Aug 2024 18:31:48 +0200 Subject: [PATCH 0336/1908] Composite: improve Storybook examples and clean up prop docs (#64397) * More clear tranform function comments * Add interactive controls * Add simpler default Storybook example * Improve `activeId`'s prop description * Add Groups example * CHANGELOG * Removed actions config in Storybook * Better composite description * Remove direct references to Ariakit's docs in JSDocs and README * Add import from `@wordpress/components` in all code snippets * useCompositeStore: update prop docs by using first-party docs Instead of using Ariakit's definitions and descriptions, we use our own version, which a copy or Ariakit's without any references to Ariakit, its examples, or any other props that we don't expose. * useCompositeStore: set explicit default values Along the same fashion as the previous commit, setting explicit default values will give us more control when propagating ariakit changes, and will allows to stay true to our first-part props docs. * Remove unnecessary space * Provide first-party prop descriptions also for other composite components * Add default value for store props to avoid errors while destructuring --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/composite/README.md | 62 ++++- packages/components/src/composite/index.tsx | 49 +++- .../src/composite/stories/index.story.tsx | 117 ++++++++-- .../src/composite/stories/utils.tsx | 18 +- packages/components/src/composite/types.ts | 211 +++++++++++++++--- 6 files changed, 384 insertions(+), 74 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 91c5a8c3bd012d..dd8a7a720258f2 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -8,6 +8,7 @@ ### Enhancements +- `Composite`: improve Storybook examples and add interactive controls ([#64397](https://github.com/WordPress/gutenberg/pull/64397)). - `TimePicker`: add `hideLabelFromVision` prop ([#64267](https://github.com/WordPress/gutenberg/pull/64267)). ## 28.5.0 (2024-08-07) diff --git a/packages/components/src/composite/README.md b/packages/components/src/composite/README.md index 59953f1273a054..384fa46b1a9217 100644 --- a/packages/components/src/composite/README.md +++ b/packages/components/src/composite/README.md @@ -2,11 +2,11 @@ `Composite` provides a single tab stop on the page and allows navigation through the focusable descendants with arrow keys. This abstract component is based on the [WAI-ARIA Composite Role⁠](https://w3c.github.io/aria/#composite). -See the [Ariakit docs for the `Composite` component](https://ariakit.org/components/composite). - ## Usage ```jsx +import { Composite, useCompositeStore } from '@wordpress/components'; + const store = useCompositeStore(); <Composite store={store}> <Composite.Group> @@ -27,7 +27,10 @@ Creates a composite store. ##### `activeId`: `string | null` -The current active item id. The active item is the element within the composite widget that has either DOM or virtual focus. +The current active item `id`. The active item is the element within the composite widget that has either DOM or virtual focus (in case the `virtualFocus` prop is enabled). + +- `null` represents the base composite element (the one with a [composite role](https://w3c.github.io/aria/#composite)). Users will be able to navigate out of it using arrow keys. +- If `activeId` is initially set to `null`, the base composite element itself will have focus and users will be able to navigate to it using arrow keys. - Required: no @@ -39,7 +42,7 @@ The composite item id that should be active by default when the composite widget ##### `setActiveId`: `((activeId: string | null | undefined) => void)` -A callback that gets called when the activeId state changes. +A callback that gets called when the `activeId` state changes. - Required: no @@ -47,40 +50,79 @@ A callback that gets called when the activeId state changes. Determines how the focus behaves when the user reaches the end of the composite widget. +On one-dimensional composite widgets: + +- `true` loops from the last item to the first item and vice-versa. +- `horizontal` loops only if `orientation` is `horizontal` or not set. +- `vertical` loops only if `orientation` is `vertical` or not set. +- If `activeId` is initially set to `null`, the composite element will be focused in between the last and first items. + +On two-dimensional composite widgets (ie. when using `CompositeRow`): + +- `true` loops from the last row/column item to the first item in the same row/column and vice-versa. If it's the last item in the last row, it moves to the first item in the first row and vice-versa. +- `horizontal` loops only from the last row item to the first item in the same row. +- `vertical` loops only from the last column item to the first item in the column row. +- If `activeId` is initially set to `null`, vertical loop will have no effect as moving down from the last row or up from the first row will focus on the composite element. +- If `focusWrap` matches the value of `focusLoop`, it'll wrap between the last item in the last row or column and the first item in the first row or column and vice-versa. + - Required: no - Default: `false` ##### `focusShift`: `boolean` -Works only on two-dimensional composite widgets. If enabled, moving up or down when there's no next item or when the next item is disabled will shift to the item right before it. +**Works only on two-dimensional composite widgets**. + +If enabled, moving up or down when there's no next item or when the next item is disabled will shift to the item right before it. - Required: no - Default: `false` ##### `focusWrap`: `boolean` -Works only on two-dimensional composite widgets. If enabled, moving to the next item from the last one in a row or column will focus on the first item in the next row or column and vice-versa. +**Works only on two-dimensional composite widgets**. + +If enabled, moving to the next item from the last one in a row or column +will focus on the first item in the next row or column and vice-versa. + +- `true` wraps between rows and columns. +- `horizontal` wraps only between rows. +- `vertical` wraps only between columns. +- If `focusLoop` matches the value of `focusWrap`, it'll wrap between the + last item in the last row or column and the first item in the first row or + column and vice-versa. - Required: no - Default: `false` ##### `virtualFocus`: `boolean` -If enabled, the composite element will act as an aria-activedescendant⁠ container instead of roving tabindex⁠. DOM focus will remain on the composite element while its items receive virtual focus. In both scenarios, the item in focus will carry the data-active-item attribute. +If enabled, the composite element will act as an [`aria-activedescendant`](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_focus_activedescendant) +container instead of [roving tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex). DOM focus will remain on the composite element while its items receive +virtual focus. + +In both scenarios, the item in focus will carry the `data-active-item` attribute. - Required: no - Default: `false` ##### `orientation`: `'horizontal' | 'vertical' | 'both'` -Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the orientation value determines which arrow keys can be used to move focus. It doesn't have any effect on two-dimensional composites. +Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the `orientation` value determines which arrow keys can be used to move focus: + +- `both`: all arrow keys work. +- `horizontal`: only left and right arrow keys work. +- `vertical`: only up and down arrow keys work. + +It doesn't have any effect on two-dimensional composites. - Required: no -- Default: `'both'` +- Default: `both` ##### `rtl`: `boolean` -Determines how the next and previous functions will behave. If rtl is set to true, they will be inverted. This only affects the composite widget behavior. You still need to set dir=`rtl` on HTML/CSS. +Determines how the `store`'s `next` and `previous` functions will behave. If `rtl` is set to `true`, they will be inverted. + +This only affects the composite widget behavior. You still need to set `dir="rtl"` on HTML/CSS. - Required: no - Default: `false` diff --git a/packages/components/src/composite/index.tsx b/packages/components/src/composite/index.tsx index 9496bdb9e98664..73df75272054c7 100644 --- a/packages/components/src/composite/index.tsx +++ b/packages/components/src/composite/index.tsx @@ -33,10 +33,11 @@ import type { /** * Creates a composite store. - * @param props - * @see https://ariakit.org/reference/use-composite-store + * * @example * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * * const store = useCompositeStore(); * <Composite store={store}> * <Composite.Item>Item</Composite.Item> @@ -45,8 +46,24 @@ import type { * </Composite> * ``` */ -export function useCompositeStore( props: CompositeStoreProps ) { - return Ariakit.useCompositeStore( props ); +export function useCompositeStore( { + focusLoop = false, + focusWrap = false, + focusShift = false, + virtualFocus = false, + orientation = 'both', + rtl = false, + ...props +}: CompositeStoreProps = {} ) { + return Ariakit.useCompositeStore( { + focusLoop, + focusWrap, + focusShift, + virtualFocus, + orientation, + rtl, + ...props, + } ); } const Group = forwardRef< @@ -82,10 +99,14 @@ const Row = forwardRef< Row.displayName = 'Composite.Row'; /** - * Renders a composite widget. - * @see https://ariakit.org/reference/composite + * Renders a widget based on the WAI-ARIA [`composite`](https://w3c.github.io/aria/#composite) + * role, which provides a single tab stop on the page and arrow key navigation + * through the focusable descendants. + * * @example * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * * const store = useCompositeStore(); * <Composite store={store}> * <Composite.Item>Item 1</Composite.Item> @@ -104,9 +125,11 @@ export const Composite = Object.assign( displayName: 'Composite', /** * Renders a group element for composite items. - * @see https://ariakit.org/reference/composite-group + * * @example * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * * const store = useCompositeStore(); * <Composite store={store}> * <Composite.Group> @@ -122,9 +145,11 @@ export const Composite = Object.assign( * Renders a label in a composite group. This component must be wrapped with * `Composite.Group` so the `aria-labelledby` prop is properly set on the * composite group element. - * @see https://ariakit.org/reference/composite-group-label + * * @example * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * * const store = useCompositeStore(); * <Composite store={store}> * <Composite.Group> @@ -138,9 +163,11 @@ export const Composite = Object.assign( GroupLabel, /** * Renders a composite item. - * @see https://ariakit.org/reference/composite-item + * * @example * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * * const store = useCompositeStore(); * <Composite store={store}> * <Composite.Item>Item 1</Composite.Item> @@ -154,9 +181,11 @@ export const Composite = Object.assign( * Renders a composite row. Wrapping `Composite.Item` elements within * `Composite.Row` will create a two-dimensional composite widget, such as a * grid. - * @see https://ariakit.org/reference/composite-row + * * @example * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * * const store = useCompositeStore(); * <Composite store={store}> * <Composite.Row> diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx index b143c1f7db05f7..280ed7b70546a4 100644 --- a/packages/components/src/composite/stories/index.story.tsx +++ b/packages/components/src/composite/stories/index.story.tsx @@ -29,7 +29,25 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 'Composite.Item': Composite.Item, }, + argTypes: { + activeId: { control: 'text' }, + defaultActiveId: { control: 'text' }, + setActiveId: { control: { type: null } }, + focusLoop: { + control: 'select', + options: [ true, false, 'horizontal', 'vertical', 'both' ], + }, + focusShift: { control: 'boolean' }, + focusWrap: { control: 'boolean' }, + virtualFocus: { control: 'boolean' }, + rtl: { control: 'boolean' }, + orientation: { + control: 'select', + options: [ 'horizontal', 'vertical', 'both' ], + }, + }, parameters: { + controls: { expanded: true }, docs: { canvas: { sourceState: 'shown' }, source: { transform }, @@ -56,8 +74,9 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { useCompositeStore: { activeId: { name: 'activeId', - description: - 'The current active item id. The active item is the element within the composite widget that has either DOM or virtual focus.', + description: `The current active item \`id\`. The active item is the element within the composite widget that has either DOM or virtual focus (in case the \`virtualFocus\` prop is enabled). +- \`null\` represents the base composite element (the one with a [composite role](https://w3c.github.io/aria/#composite)). Users will be able to navigate out of it using arrow keys. +- If \`activeId\` is initially set to \`null\`, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.`, table: { type: { summary: 'string | null' } }, }, defaultActiveId: { @@ -69,7 +88,7 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { setActiveId: { name: 'setActiveId', description: - 'A callback that gets called when the activeId state changes.', + 'A callback that gets called when the `activeId` state changes.', table: { type: { summary: @@ -79,8 +98,20 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { }, focusLoop: { name: 'focusLoop', - description: - 'Determines how the focus behaves when the user reaches the end of the composite widget.', + description: `On one-dimensional composite widgets: + +- \`true\` loops from the last item to the first item and vice-versa. +- \`horizontal\` loops only if \`orientation\` is \`horizontal\` or not set. +- \`vertical\` loops only if \`orientation\` is \`vertical\` or not set. +- If \`activeId\` is initially set to \`null\`, the composite element will be focused in between the last and first items. + +On two-dimensional composite widgets (ie. when using \`CompositeRow\`): + +- \`true\` loops from the last row/column item to the first item in the same row/column and vice-versa. If it's the last item in the last row, it moves to the first item in the first row and vice-versa. +- \`horizontal\` loops only from the last row item to the first item in the same row. +- \`vertical\` loops only from the last column item to the first item in the column row. +- If \`activeId\` is initially set to \`null\`, vertical loop will have no effect as moving down from the last row or up from the first row will focus on the composite element. +- If \`focusWrap\` matches the value of \`focusLoop\`, it'll wrap between the last item in the last row or column and the first item in the first row or column and vice-versa.`, table: { defaultValue: { summary: 'false', @@ -93,8 +124,9 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { }, focusShift: { name: 'focusShift', - description: - "Works only on two-dimensional composite widgets. If enabled, moving up or down when there's no next item or when the next item is disabled will shift to the item right before it.", + description: `**Works only on two-dimensional composite widgets**. + +If enabled, moving up or down when there's no next item or when the next item is disabled will shift to the item right before it.`, table: { defaultValue: { summary: 'false', @@ -106,8 +138,17 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { }, focusWrap: { name: 'focusWrap', - description: - 'Works only on two-dimensional composite widgets. If enabled, moving to the next item from the last one in a row or column will focus on the first item in the next row or column and vice-versa.', + description: `**Works only on two-dimensional composite widgets**. + +If enabled, moving to the next item from the last one in a row or column +will focus on the first item in the next row or column and vice-versa. + +- \`true\` wraps between rows and columns. +- \`horizontal\` wraps only between rows. +- \`vertical\` wraps only between columns. +- If \`focusLoop\` matches the value of \`focusWrap\`, it'll wrap between the + last item in the last row or column and the first item in the first row or + column and vice-versa.`, table: { defaultValue: { summary: 'false', @@ -119,8 +160,11 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { }, virtualFocus: { name: 'virtualFocus', - description: - 'If enabled, the composite element will act as an aria-activedescendant⁠ container instead of roving tabindex⁠. DOM focus will remain on the composite element while its items receive virtual focus. In both scenarios, the item in focus will carry the data-active-item attribute.', + description: `If enabled, the composite element will act as an [\`aria-activedescendant\`](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_focus_activedescendant) +container instead of [roving tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex). DOM focus will remain on the composite element while its items receive +virtual focus. + +In both scenarios, the item in focus will carry the \`data-active-item\` attribute.`, table: { defaultValue: { summary: 'false', @@ -132,8 +176,13 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { }, orientation: { name: 'orientation', - description: - "Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the orientation value determines which arrow keys can be used to move focus. It doesn't have any effect on two-dimensional composites.", + description: `Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the \`orientation\` value determines which arrow keys can be used to move focus: + +- \`both\`: all arrow keys work. +- \`horizontal\`: only left and right arrow keys work. +- \`vertical\`: only up and down arrow keys work. + +It doesn't have any effect on two-dimensional composites.`, table: { defaultValue: { summary: "'both'", @@ -146,8 +195,9 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { }, rtl: { name: 'rtl', - description: - 'Determines how the next and previous functions will behave. If rtl is set to true, they will be inverted. This only affects the composite widget behavior. You still need to set dir="rtl" on HTML/CSS.', + description: `Determines how the \`store\`'s \`next\` and \`previous\` functions will behave. If \`rtl\` is set to \`true\`, they will be inverted. + +This only affects the composite widget behavior. You still need to set \`dir="rtl"\` on HTML/CSS.`, table: { defaultValue: { summary: 'false', @@ -196,6 +246,43 @@ export const Default: StoryFn< typeof UseCompositeStorePlaceholder > = ( const rtl = isRTL(); const store = useCompositeStore( { rtl, ...storeProps } ); + return ( + <Composite store={ store }> + <Composite.Item>Item one</Composite.Item> + <Composite.Item>Item two</Composite.Item> + <Composite.Item>Item three</Composite.Item> + </Composite> + ); +}; + +export const Groups: StoryFn< typeof UseCompositeStorePlaceholder > = ( + storeProps +) => { + const rtl = isRTL(); + const store = useCompositeStore( { rtl, ...storeProps } ); + + return ( + <Composite store={ store }> + <Composite.Group> + <Composite.GroupLabel>Group one</Composite.GroupLabel> + <Composite.Item>Item 1.1</Composite.Item> + <Composite.Item>Item 1.2</Composite.Item> + </Composite.Group> + <Composite.Group> + <Composite.GroupLabel>Group two</Composite.GroupLabel> + <Composite.Item>Item 2.1</Composite.Item> + <Composite.Item>Item 2.1</Composite.Item> + </Composite.Group> + </Composite> + ); +}; + +export const Grid: StoryFn< typeof UseCompositeStorePlaceholder > = ( + storeProps +) => { + const rtl = isRTL(); + const store = useCompositeStore( { rtl, ...storeProps } ); + return ( <Composite role="grid" store={ store } aria-label="Composite"> <Composite.Row role="row"> diff --git a/packages/components/src/composite/stories/utils.tsx b/packages/components/src/composite/stories/utils.tsx index 425fb9a905bcff..f2f197877ff76d 100644 --- a/packages/components/src/composite/stories/utils.tsx +++ b/packages/components/src/composite/stories/utils.tsx @@ -9,9 +9,13 @@ import type { StoryContext } from '@storybook/react'; import type { CompositeStoreProps } from '../types'; /** - * Renders a composite widget. + * Renders a widget based on the WAI-ARIA [`composite`](https://w3c.github.io/aria/#composite) + * role, which provides a single tab stop on the page and arrow key navigation + * through the focusable descendants. * * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * * const store = useCompositeStore(); * <Composite store={ store }> * <Composite.Item>Item 1</Composite.Item> @@ -33,17 +37,17 @@ export function UseCompositeStorePlaceholder( props: CompositeStoreProps ) { } UseCompositeStorePlaceholder.displayName = 'useCompositeStore'; +// The output generated by Storybook for these components is +// messy, so we apply this transform to make it more useful +// for anyone reading the docs. export function transform( code: string, context: StoryContext ) { - // The output generated by Storybook for these components is - // messy, so we apply this transform to make it more useful - // for anyone reading the docs. - const config = ` ${ JSON.stringify( context.args, null, 2 ) } `; - const state = config.replace( ' {} ', '' ); + const storeConfig = ` ${ JSON.stringify( context.args, null, 2 ) } `; + const formattedStoreConfig = storeConfig.replace( ' {} ', '' ); return [ // Include a setup line, showing how to make use of // `useCompositeStore` to convert store options into // a composite store prop. - `const store = useCompositeStore(${ state });`, + `const store = useCompositeStore(${ formattedStoreConfig });`, '', 'return (', ' ' + diff --git a/packages/components/src/composite/types.ts b/packages/components/src/composite/types.ts index 438d1caaa94f8a..37709133915d6c 100644 --- a/packages/components/src/composite/types.ts +++ b/packages/components/src/composite/types.ts @@ -3,45 +3,192 @@ */ import type * as Ariakit from '@ariakit/react'; -export type CompositeStoreProps = Pick< - Ariakit.CompositeStoreProps, - | 'activeId' - | 'defaultActiveId' - | 'setActiveId' - | 'focusLoop' - | 'focusShift' - | 'focusWrap' - | 'virtualFocus' - | 'orientation' - | 'rtl' ->; +export type CompositeStoreProps = { + /** + * The current active item `id`. The active item is the element within the + * composite widget that has either DOM or virtual focus (in case + * the `virtualFocus` prop is enabled). + * - `null` represents the base composite element (the one with a [composite + * role](https://w3c.github.io/aria/#composite)). Users will be able to + * navigate out of it using arrow keys. + * - If `activeId` is initially set to `null`, the base composite element + * itself will have focus and users will be able to navigate to it using + * arrow keys. + */ + activeId?: Ariakit.CompositeStoreProps[ 'activeId' ]; + /** + * The composite item id that should be active by default when the composite + * widget is rendered. If `null`, the composite element itself will have focus + * and users will be able to navigate to it using arrow keys. If `undefined`, + * the first enabled item will be focused. + */ + defaultActiveId?: Ariakit.CompositeStoreProps[ 'defaultActiveId' ]; + /** + * A callback that gets called when the `activeId` state changes. + */ + setActiveId?: Ariakit.CompositeStoreProps[ 'setActiveId' ]; + /** + * Determines how the focus behaves when the user reaches the end of the + * composite widget. + * + * On one-dimensional composite widgets: + * - `true` loops from the last item to the first item and vice-versa. + * - `horizontal` loops only if `orientation` is `horizontal` or not set. + * - `vertical` loops only if `orientation` is `vertical` or not set. + * - If `activeId` is initially set to `null`, the composite element will + * be focused in between the last and first items. + * + * On two-dimensional composite widgets (ie. when using `CompositeRow`): + * - `true` loops from the last row/column item to the first item in the same + * row/column and vice-versa. If it's the last item in the last row, it + * moves to the first item in the first row and vice-versa. + * - `horizontal` loops only from the last row item to the first item in the + * same row. + * - `vertical` loops only from the last column item to the first item in the + * column row. + * - If `activeId` is initially set to `null`, vertical loop will have no + * effect as moving down from the last row or up from the first row will + * focus on the composite element. + * - If `focusWrap` matches the value of `focusLoop`, it'll wrap between the + * last item in the last row or column and the first item in the first row or + * column and vice-versa. + * + * @default false + */ + focusLoop?: Ariakit.CompositeStoreProps[ 'focusLoop' ]; + /** + * **Works only on two-dimensional composite widgets**. + * + * If enabled, moving to the next item from the last one in a row or column + * will focus on the first item in the next row or column and vice-versa. + * - `true` wraps between rows and columns. + * - `horizontal` wraps only between rows. + * - `vertical` wraps only between columns. + * - If `focusLoop` matches the value of `focusWrap`, it'll wrap between the + * last item in the last row or column and the first item in the first row or + * column and vice-versa. + * + * @default false + */ + focusWrap?: Ariakit.CompositeStoreProps[ 'focusWrap' ]; + /** + * **Works only on two-dimensional composite widgets**. + * + * If enabled, moving up or down when there's no next item or when the next + * item is disabled will shift to the item right before it. + * + * @default false + */ + focusShift?: Ariakit.CompositeStoreProps[ 'focusShift' ]; + /** + * If enabled, the composite element will act as an + * [`aria-activedescendant`](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_focus_activedescendant) + * container instead of [roving + * tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex). + * DOM focus will remain on the composite element while its items receive + * virtual focus. + * + * In both scenarios, the item in focus will carry the `data-active-item` + * attribute. + * + * @default false + */ + virtualFocus?: Ariakit.CompositeStoreProps[ 'virtualFocus' ]; + /** + * Defines the orientation of the composite widget. If the composite has a + * single row or column (one-dimensional), the `orientation` value determines + * which arrow keys can be used to move focus: + * - `both`: all arrow keys work. + * - `horizontal`: only left and right arrow keys work. + * - `vertical`: only up and down arrow keys work. + * + * It doesn't have any effect on two-dimensional composites. + * + * @default "both" + */ + orientation?: Ariakit.CompositeStoreProps[ 'orientation' ]; + /** + * Determines how the `store`'s `next` and `previous` functions will behave. + * If `rtl` is set to `true`, they will be inverted. + * + * This only affects the composite widget behavior. You still need to set + * `dir="rtl"` on HTML/CSS. + * + * @default false + */ + rtl?: Ariakit.CompositeStoreProps[ 'rtl' ]; +}; -export type CompositeProps = Pick< - Ariakit.CompositeProps, - 'render' | 'children' -> & { +export type CompositeProps = { /** * Object returned by the `useCompositeStore` hook. */ store: Ariakit.CompositeStore; + /** + * Allows the component to be rendered as a different HTML element or React + * component. The value can be a React element or a function that takes in the + * original component props and gives back a React element with the props + * merged. + */ + render?: Ariakit.CompositeProps[ 'render' ]; + /** + * The contents of the component. + */ + children?: Ariakit.CompositeProps[ 'children' ]; }; -export type CompositeGroupProps = Pick< - Ariakit.CompositeGroupProps, - 'render' | 'children' ->; +export type CompositeGroupProps = { + /** + * Allows the component to be rendered as a different HTML element or React + * component. The value can be a React element or a function that takes in the + * original component props and gives back a React element with the props + * merged. + */ + render?: Ariakit.CompositeGroupProps[ 'render' ]; + /** + * The contents of the component. + */ + children?: Ariakit.CompositeGroupProps[ 'children' ]; +}; -export type CompositeGroupLabelProps = Pick< - Ariakit.CompositeGroupLabelProps, - 'render' | 'children' ->; +export type CompositeGroupLabelProps = { + /** + * Allows the component to be rendered as a different HTML element or React + * component. The value can be a React element or a function that takes in the + * original component props and gives back a React element with the props + * merged. + */ + render?: Ariakit.CompositeGroupLabelProps[ 'render' ]; + /** + * The contents of the component. + */ + children?: Ariakit.CompositeGroupLabelProps[ 'children' ]; +}; -export type CompositeItemProps = Pick< - Ariakit.CompositeItemProps, - 'render' | 'children' ->; +export type CompositeItemProps = { + /** + * Allows the component to be rendered as a different HTML element or React + * component. The value can be a React element or a function that takes in the + * original component props and gives back a React element with the props + * merged. + */ + render?: Ariakit.CompositeItemProps[ 'render' ]; + /** + * The contents of the component. + */ + children?: Ariakit.CompositeItemProps[ 'children' ]; +}; -export type CompositeRowProps = Pick< - Ariakit.CompositeRowProps, - 'render' | 'children' ->; +export type CompositeRowProps = { + /** + * Allows the component to be rendered as a different HTML element or React + * component. The value can be a React element or a function that takes in the + * original component props and gives back a React element with the props + * merged. + */ + render?: Ariakit.CompositeRowProps[ 'render' ]; + /** + * The contents of the component. + */ + children?: Ariakit.CompositeRowProps[ 'children' ]; +}; From 46a026bde390382bbebb283dca25d2dba91b2b67 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 9 Aug 2024 19:15:18 +0200 Subject: [PATCH 0337/1908] Composite: add Hover and Typeahead subcomponents (#64399) * Composite: add Hover and Typeahead subcomponents * Add hover example + styles to highlight active item * Add Composite.Hover props docs * Add Typeahead docs and Storybook example * CHANGELOG * Remove the `focusOnHover` and `blurOnHoverEnd` props. * Remove ariakit references * Add import statements to code examples --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/composite/README.md | 32 +++++++ packages/components/src/composite/index.tsx | 56 ++++++++++++ .../src/composite/stories/index.story.tsx | 91 +++++++++++++++++++ packages/components/src/composite/types.ts | 28 ++++++ 5 files changed, 208 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index dd8a7a720258f2..96bf76815e71dd 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### New Features - `Composite`: add stable version of the component ([#63564](https://github.com/WordPress/gutenberg/pull/63564)). +- `Composite`: add `Hover` and `Typeahead` subcomponents ([#64399](https://github.com/WordPress/gutenberg/pull/64399)). ### Enhancements diff --git a/packages/components/src/composite/README.md b/packages/components/src/composite/README.md index 384fa46b1a9217..7bd12d0cabfa0c 100644 --- a/packages/components/src/composite/README.md +++ b/packages/components/src/composite/README.md @@ -216,3 +216,35 @@ Allows the component to be rendered as a different HTML element or React compone The contents of the component. - Required: no + +### `Composite.Hover` + +Renders an element in a composite widget that receives focus on mouse move and loses focus to the composite base element on mouse leave. This should be combined with the `Composite.Item` component. + +##### `render`: `RenderProp<React.HTMLAttributes<any> & { ref?: React.Ref<any> | undefined; }> | React.ReactElement<any, string | React.JSXElementConstructor<any>>` + +Allows the component to be rendered as a different HTML element or React component. The value can be a React element or a function that takes in the original component props and gives back a React element with the props merged. + +- Required: no + +##### `children`: `React.ReactNode` + +The contents of the component. + +- Required: no + +### `Composite.Typeahead` + +Renders a component that adds typeahead functionality to composite components. Hitting printable character keys will move focus to the next composite item that begins with the input characters. + +##### `render`: `RenderProp<React.HTMLAttributes<any> & { ref?: React.Ref<any> | undefined; }> | React.ReactElement<any, string | React.JSXElementConstructor<any>>` + +Allows the component to be rendered as a different HTML element or React component. The value can be a React element or a function that takes in the original component props and gives back a React element with the props merged. + +- Required: no + +##### `children`: `React.ReactNode` + +The contents of the component. + +- Required: no diff --git a/packages/components/src/composite/index.tsx b/packages/components/src/composite/index.tsx index 73df75272054c7..4e87b9a55fa5bb 100644 --- a/packages/components/src/composite/index.tsx +++ b/packages/components/src/composite/index.tsx @@ -29,6 +29,8 @@ import type { CompositeGroupLabelProps, CompositeItemProps, CompositeRowProps, + CompositeHoverProps, + CompositeTypeaheadProps, } from './types'; /** @@ -98,6 +100,22 @@ const Row = forwardRef< } ); Row.displayName = 'Composite.Row'; +const Hover = forwardRef< + HTMLDivElement, + WordPressComponentProps< CompositeHoverProps, 'div', false > +>( function CompositeHover( props, ref ) { + return <Ariakit.CompositeHover { ...props } ref={ ref } />; +} ); +Hover.displayName = 'Composite.Hover'; + +const Typeahead = forwardRef< + HTMLDivElement, + WordPressComponentProps< CompositeTypeaheadProps, 'div', false > +>( function CompositeTypeahead( props, ref ) { + return <Ariakit.CompositeTypeahead { ...props } ref={ ref } />; +} ); +Typeahead.displayName = 'Composite.Typeahead'; + /** * Renders a widget based on the WAI-ARIA [`composite`](https://w3c.github.io/aria/#composite) * role, which provides a single tab stop on the page and arrow key navigation @@ -202,5 +220,43 @@ export const Composite = Object.assign( * ``` */ Row, + /** + * Renders an element in a composite widget that receives focus on mouse move + * and loses focus to the composite base element on mouse leave. This should + * be combined with the `Composite.Item` component. + * + * @example + * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * + * const store = useCompositeStore(); + * <Composite store={store}> + * <Composite.Hover render={ <Composite.Item /> }> + * Item 1 + * </Composite.Hover> + * <Composite.Hover render={ <Composite.Item /> }> + * Item 2 + * </Composite.Hover> + * </Composite> + * ``` + */ + Hover, + /** + * Renders a component that adds typeahead functionality to composite + * components. Hitting printable character keys will move focus to the next + * composite item that begins with the input characters. + * + * @example + * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * + * const store = useCompositeStore(); + * <Composite store={store} render={ <CompositeTypeahead /> }> + * <Composite.Item>Item 1</Composite.Item> + * <Composite.Item>Item 2</Composite.Item> + * </Composite> + * ``` + */ + Typeahead, } ); diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx index 280ed7b70546a4..f1be53445f79ad 100644 --- a/packages/components/src/composite/stories/index.story.tsx +++ b/packages/components/src/composite/stories/index.story.tsx @@ -28,6 +28,10 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { 'Composite.Row': Composite.Row, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 'Composite.Item': Composite.Item, + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + 'Composite.Hover': Composite.Hover, + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + 'Composite.Typeahead': Composite.Typeahead, }, argTypes: { activeId: { control: 'text' }, @@ -227,6 +231,8 @@ This only affects the composite widget behavior. You still need to set \`dir="rt 'Composite.GroupLabel': commonArgTypes, 'Composite.Row': commonArgTypes, 'Composite.Item': commonArgTypes, + 'Composite.Hover': commonArgTypes, + 'Composite.Typeahead': commonArgTypes, }; const name = component.displayName ?? ''; @@ -237,6 +243,41 @@ This only affects the composite widget behavior. You still need to set \`dir="rt }, }, }, + decorators: [ + ( Story ) => { + return ( + <> + { /* Visually style the active composite item */ } + <style>{ ` + [data-active-item] { + background-color: #ffc0b5; + } + ` }</style> + <Story /> + <div + style={ { + marginTop: '2em', + fontSize: '12px', + fontStyle: 'italic', + } } + > + { /* eslint-disable-next-line no-restricted-syntax */ } + <p id="list-title">Notes</p> + <ul aria-labelledby="list-title"> + <li> + The active composite item is highlighted with a + different background color; + </li> + <li> + A composite item can be the active item even + when it doesn't have keyboard focus. + </li> + </ul> + </div> + </> + ); + }, + ], }; export default meta; @@ -303,3 +344,53 @@ export const Grid: StoryFn< typeof UseCompositeStorePlaceholder > = ( </Composite> ); }; + +export const Hover: StoryFn< typeof UseCompositeStorePlaceholder > = ( + storeProps +) => { + const rtl = isRTL(); + const store = useCompositeStore( { rtl, ...storeProps } ); + + return ( + <Composite store={ store }> + <Composite.Hover render={ <Composite.Item /> }> + Hover item one + </Composite.Hover> + <Composite.Hover render={ <Composite.Item /> }> + Hover item two + </Composite.Hover> + <Composite.Hover render={ <Composite.Item /> }> + Hover item three + </Composite.Hover> + </Composite> + ); +}; +Hover.parameters = { + docs: { + description: { + story: 'Elements in the composite widget will receive focus on mouse move and lose focus to the composite base element on mouse leave.', + }, + }, +}; + +export const Typeahead: StoryFn< typeof UseCompositeStorePlaceholder > = ( + storeProps +) => { + const rtl = isRTL(); + const store = useCompositeStore( { rtl, ...storeProps } ); + + return ( + <Composite store={ store } render={ <Composite.Typeahead /> }> + <Composite.Item>Apple</Composite.Item> + <Composite.Item>Banana</Composite.Item> + <Composite.Item>Peach</Composite.Item> + </Composite> + ); +}; +Typeahead.parameters = { + docs: { + description: { + story: 'When focus in on the composite widget, hitting printable character keys will move focus to the next composite item that begins with the input characters.', + }, + }, +}; diff --git a/packages/components/src/composite/types.ts b/packages/components/src/composite/types.ts index 37709133915d6c..8bd4b447a83aef 100644 --- a/packages/components/src/composite/types.ts +++ b/packages/components/src/composite/types.ts @@ -192,3 +192,31 @@ export type CompositeRowProps = { */ children?: Ariakit.CompositeRowProps[ 'children' ]; }; + +export type CompositeHoverProps = { + /** + * Allows the component to be rendered as a different HTML element or React + * component. The value can be a React element or a function that takes in the + * original component props and gives back a React element with the props + * merged. + */ + render?: Ariakit.CompositeHoverProps[ 'render' ]; + /** + * The contents of the component. + */ + children?: Ariakit.CompositeHoverProps[ 'children' ]; +}; + +export type CompositeTypeaheadProps = { + /** + * Allows the component to be rendered as a different HTML element or React + * component. The value can be a React element or a function that takes in the + * original component props and gives back a React element with the props + * merged. + */ + render?: Ariakit.CompositeTypeaheadProps[ 'render' ]; + /** + * The contents of the component. + */ + children?: Ariakit.CompositeTypeaheadProps[ 'children' ]; +}; From 81d5d34ba25cad8faf2ee2ce1c4c4c2d8b6aeb8a Mon Sep 17 00:00:00 2001 From: Damon Cook <colorful-tones@users.noreply.github.com> Date: Fri, 9 Aug 2024 15:58:34 -0400 Subject: [PATCH 0338/1908] Docs: Interactivity API: Add wp_interactivity_state() clarification (#64356) * Add wp_interactivity_state() clarification * Update code example for wp_interactivity_state * Update docs/reference-guides/interactivity-api/api-reference.md Co-authored-by: Luis Herranz <luisherranz@gmail.com> * Update docs/reference-guides/interactivity-api/api-reference.md Co-authored-by: Luis Herranz <luisherranz@gmail.com> * Update docs/reference-guides/interactivity-api/api-reference.md Co-authored-by: Luis Herranz <luisherranz@gmail.com> --------- Co-authored-by: Luis Herranz <luisherranz@gmail.com> --- .../interactivity-api/api-reference.md | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/docs/reference-guides/interactivity-api/api-reference.md b/docs/reference-guides/interactivity-api/api-reference.md index a4b400b8c0276b..29ec67cc17507f 100644 --- a/docs/reference-guides/interactivity-api/api-reference.md +++ b/docs/reference-guides/interactivity-api/api-reference.md @@ -1152,7 +1152,7 @@ store('mySliderPlugin', { ## Server functions -The Interactivity API comes with handy functions on the PHP part. Apart from [setting the store via server](#on-the-server-side), there is also a function to get and set Interactivity related config variables. +The Interactivity API comes with handy functions that allow you to initialize and reference configuration options on the server. This is necessary to feed the initial data that the Server Directive Processing will use to modify the HTML markup before it's send to the browser. It is also a great way to leverage many of WordPress's APIs, like nonces, AJAX, and translations. ### wp_interactivity_config @@ -1181,6 +1181,53 @@ This config can be retrieved on the client: const { showLikeButton } = getConfig(); ``` +### wp_interactivity_state + +`wp_interactivity_state` allows the initialization of the global state on the server, which will be used to process the directives on the server and then will be merged with any global state defined in the client. + +Initializing the global state on the server also allows you to use many critical WordPress APIs, including [AJAX](https://developer.wordpress.org/plugins/javascript/ajax/), or [nonces](https://developer.wordpress.org/plugins/javascript/enqueuing/#nonce). + +The `wp_interactivity_state` function receives two arguments, a string with the namespace that will be used as a reference and an associative array containing the values. + +Here is an example of passing the WP Admin AJAX endpoint with a nonce. + +```php +// render.php + +wp_interactivity_state( + 'myPlugin', + array( + 'ajaxUrl' => admin_url( 'admin-ajax.php' ), + 'nonce' => wp_create_nonce( 'myPlugin_nonce' ), + ), +); +``` + +```js +// view.js + +const { state } = store( 'myPlugin', { + actions: { + *doSomething() { + try { + const formData = new FormData(); + formData.append( 'action', 'do_something' ); + formData.append( '_ajax_nonce', state.nonce ); + + const data = yield fetch( state.ajaxUrl, { + method: 'POST', + body: formData, + } ).then( ( response ) => response.json() ); + console.log( 'Server data!', data ); + } catch ( e ) { + // Something went wrong! + } + }, + }, + } +); +``` + ### wp_interactivity_process_directives `wp_interactivity_process_directives` returns the updated HTML after the directives have been processed. From e0b54b3596b35e7df15bd674f7c9ead918f05b07 Mon Sep 17 00:00:00 2001 From: Xinyu Liu <meteor.lxy@foxmail.com> Date: Sun, 11 Aug 2024 18:35:46 +0800 Subject: [PATCH 0339/1908] Fix example of useBlockProps hook (#64363) * Fix example of useBlockProps hook * chore: tweaks * chore: updates Co-authored-by: meteorlxy <meteorlxy@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/block-editor/README.md | 23 ++++++++----------- .../block-list/use-block-props/index.js | 4 ++-- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 776b217ba54f6e..c798015804b3e5 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -920,20 +920,15 @@ _Usage_ import { useBlockProps } from '@wordpress/block-editor'; export default function Edit() { - - const blockProps = useBlockProps( - className: 'my-custom-class', - style: { - color: '#222222', - backgroundColor: '#eeeeee' - } - ) - - return ( - <div { ...blockProps }> - - </div> - ) + const blockProps = useBlockProps( { + className: 'my-custom-class', + style: { + color: '#222222', + backgroundColor: '#eeeeee', + }, + } ); + + return <div { ...blockProps }></div>; } ``` diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index 6c44aa5c5d9705..15fb83139237cc 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -49,13 +49,13 @@ import { canBindBlock } from '../../../hooks/use-bindings-attributes'; * * export default function Edit() { * - * const blockProps = useBlockProps( + * const blockProps = useBlockProps( { * className: 'my-custom-class', * style: { * color: '#222222', * backgroundColor: '#eeeeee' * } - * ) + * } ) * * return ( * <div { ...blockProps }> From 24f9ca62b0b83d3832233d276fea564b1714a172 Mon Sep 17 00:00:00 2001 From: Nick Diego <nick.diego@automattic.com> Date: Sun, 11 Aug 2024 23:41:56 -0500 Subject: [PATCH 0340/1908] Docs: Fix typos in the Block Filters documentation (#64426) Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> --- docs/reference-guides/filters/block-filters.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference-guides/filters/block-filters.md b/docs/reference-guides/filters/block-filters.md index e7a31c1e3bbc83..c70bb356a445a8 100644 --- a/docs/reference-guides/filters/block-filters.md +++ b/docs/reference-guides/filters/block-filters.md @@ -144,7 +144,7 @@ Filters the font-end content of any block. This filter has no impact on the beha The callback function for this filter receives three parameters: - `$block_content` (`string`): The block content. -- `block` (`array`): The full block, including name and attributes. +- `$block` (`array`): The full block, including name and attributes. - `$instance` (`WP_Block`): The block instance. In the following example, the class `example-class` is added to all Paragraph blocks on the front end. Here the [HTML API](https://make.wordpress.org/core/2023/03/07/introducing-the-html-api-in-wordpress-6-2/) is used to easily add the class instead of relying on regex. @@ -177,7 +177,7 @@ Filters the font-end content of the defined block. This is just a simpler form o The callback function for this filter receives three parameters: - `$block_content` (`string`): The block content. -- `block` (`array`): The full block, including name and attributes. +- `$block` (`array`): The full block, including name and attributes. - `$instance` (`WP_Block`): The block instance. In the following example, the class `example-class` is added to all Paragraph blocks on the front end. Notice that compared to the `render_block` example above, you no longer need to check the block type before modifying the content. Again, the [HTML API](https://make.wordpress.org/core/2023/03/07/introducing-the-html-api-in-wordpress-6-2/) is used instead of regex. From 92ea19f8cb946d051855aaa6791b0018a5d15fcb Mon Sep 17 00:00:00 2001 From: Luis Herranz <luisherranz@gmail.com> Date: Mon, 12 Aug 2024 10:18:00 +0200 Subject: [PATCH 0341/1908] Remove typed function from API reference (#64429) Co-authored-by: luisherranz <luisherranz@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> Co-authored-by: atachibana <atachibana@git.wordpress.org> --- docs/reference-guides/interactivity-api/api-reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference-guides/interactivity-api/api-reference.md b/docs/reference-guides/interactivity-api/api-reference.md index 29ec67cc17507f..46bd20bece0bda 100644 --- a/docs/reference-guides/interactivity-api/api-reference.md +++ b/docs/reference-guides/interactivity-api/api-reference.md @@ -776,7 +776,7 @@ Actions are just regular JavaScript functions. Usually triggered by the `data-wp ```ts const { state, actions } = store("myPlugin", { actions: { - selectItem: (id?: number) => { + selectItem: ( id ) => { const context = getContext(); // `id` is optional here, so this action can be used in a directive. state.selected = id || context.id; From 21cfde3f3ccba896a7026312ae646c74626d9621 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 12 Aug 2024 12:37:18 +0400 Subject: [PATCH 0342/1908] Site Editor: Fix Template Parts post type preload path (#64401) * Site Editor: Fix Template Parts post type preload path * Add backport changelog file Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- backport-changelog/6.7/7179.md | 3 +++ lib/compat/wordpress-6.7/rest-api.php | 31 +++++++++++++++++++++++++++ lib/load.php | 3 +++ 3 files changed, 37 insertions(+) create mode 100644 backport-changelog/6.7/7179.md create mode 100644 lib/compat/wordpress-6.7/rest-api.php diff --git a/backport-changelog/6.7/7179.md b/backport-changelog/6.7/7179.md new file mode 100644 index 00000000000000..f359b6610a94e6 --- /dev/null +++ b/backport-changelog/6.7/7179.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7179 + +* https://github.com/WordPress/gutenberg/pull/64401 diff --git a/lib/compat/wordpress-6.7/rest-api.php b/lib/compat/wordpress-6.7/rest-api.php new file mode 100644 index 00000000000000..713d31c4632c74 --- /dev/null +++ b/lib/compat/wordpress-6.7/rest-api.php @@ -0,0 +1,31 @@ +<?php +/** + * PHP and WordPress configuration compatibility functions for the Gutenberg + * editor plugin changes related to REST API. + * + * @package gutenberg + */ + +if ( ! defined( 'ABSPATH' ) ) { + die( 'Silence is golden.' ); +} + +/** + * Update the preload paths registered in Core (`site-editor.php` or `edit-form-blocks.php`). + * + * @param array $paths REST API paths to preload. + * @param WP_Block_Editor_Context $context Current block editor context. + * @return array Filtered preload paths. + */ +function gutenberg_block_editor_preload_paths_6_7( $paths, $context ) { + if ( 'core/edit-site' === $context->name ) { + // Fixes post type name. It should be `type/wp_template_part`. + $parts_key = array_search( '/wp/v2/types/wp_template-part?context=edit', $paths, true ); + if ( false !== $parts_key ) { + $paths[ $parts_key ] = '/wp/v2/types/wp_template_part?context=edit'; + } + } + + return $paths; +} +add_filter( 'block_editor_rest_api_preload_paths', 'gutenberg_block_editor_preload_paths_6_7', 10, 2 ); diff --git a/lib/load.php b/lib/load.php index 5a299f3b696968..4bb0ab88024a4a 100644 --- a/lib/load.php +++ b/lib/load.php @@ -40,6 +40,9 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php'; require __DIR__ . '/compat/wordpress-6.6/rest-api.php'; + // WordPress 6.7 compat. + require __DIR__ . '/compat/wordpress-6.7/rest-api.php'; + // Plugin specific code. require_once __DIR__ . '/class-wp-rest-global-styles-controller-gutenberg.php'; require_once __DIR__ . '/class-wp-rest-edit-site-export-controller-gutenberg.php'; From acc9a38a331cd75b559e11e268ddde2eddfc2b89 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Mon, 12 Aug 2024 09:52:36 +0100 Subject: [PATCH 0343/1908] Add elevation scale (#64108) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: hanneslsm <hanneslsm@git.wordpress.org> --- packages/base-styles/_variables.scss | 26 +++++++++++++------ .../components/src/utils/config-values.js | 4 +++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/packages/base-styles/_variables.scss b/packages/base-styles/_variables.scss index 97eb513cf38aeb..0d3e139a7dd555 100644 --- a/packages/base-styles/_variables.scss +++ b/packages/base-styles/_variables.scss @@ -50,6 +50,22 @@ $radius-large: 8px; // Applied to containers with larger padding. $radius-full: 9999px; // For lozenges. $radius-round: 50%; // For circles and ovals. +/** + * Elevation scale. + */ + +// For sections and containers that group related content and controls, which may overlap other content. Example: Preview Frame. +$elevation-x-small: 0 0.7px 1px rgba($black, 0.1), 0 1.2px 1.7px -0.2px rgba($black, 0.1), 0 2.3px 3.3px -0.5px rgba($black, 0.1); + +// For components that provide contextual feedback without being intrusive. Generally non-interruptive. Example: Tooltips, Snackbar. +$elevation-small: 0 0.7px 1px 0 rgba(0, 0, 0, 0.12), 0 2.2px 3.7px -0.2px rgba(0, 0, 0, 0.12), 0 5.3px 7.3px -0.5px rgba(0, 0, 0, 0.12); + +// For components that offer additional actions. Example: Menus, Command Palette +$elevation-medium: 0 0.7px 1px 0 rgba(0, 0, 0, 0.14), 0 4.2px 5.7px -0.2px rgba(0, 0, 0, 0.14), 0 7.3px 9.3px -0.5px rgba(0, 0, 0, 0.14); + +// For components that confirm decisions or handle necessary interruptions. Example: Modals. +$elevation-large: 0 0.7px 1px rgba($black, 0.15), 0 2.7px 3.8px -0.2px rgba($black, 0.15), 0 5.5px 7.8px -0.3px rgba($black, 0.15), 0.1px 11.5px 16.4px -0.5px rgba($black, 0.15); + /** * Dimensions. */ @@ -74,14 +90,6 @@ $modal-width-large: 840px; $spinner-size: 16px; $canvas-padding: $grid-unit-20; - -/** - * Shadows. - */ - -$shadow-popover: 0 0.7px 1px rgba($black, 0.1), 0 1.2px 1.7px -0.2px rgba($black, 0.1), 0 2.3px 3.3px -0.5px rgba($black, 0.1); -$shadow-modal: 0 0.7px 1px rgba($black, 0.15), 0 2.7px 3.8px -0.2px rgba($black, 0.15), 0 5.5px 7.8px -0.3px rgba($black, 0.15), 0.1px 11.5px 16.4px -0.5px rgba($black, 0.15); - /** * Editor widths. */ @@ -107,6 +115,8 @@ $radio-input-size-sm: 24px; // Width & height for small viewports. // Deprecated, please avoid using these. $block-padding: 14px; // Used to define space between block footprint and surrouding borders. $radius-block-ui: $radius-small; +$shadow-popover: $elevation-x-small; +$shadow-modal: $elevation-large; /** diff --git a/packages/components/src/utils/config-values.js b/packages/components/src/utils/config-values.js index ba92813bdbfb0f..65632170c9e3d7 100644 --- a/packages/components/src/utils/config-values.js +++ b/packages/components/src/utils/config-values.js @@ -74,6 +74,10 @@ export default Object.assign( {}, CONTROL_PROPS, TOGGLE_GROUP_CONTROL_PROPS, { cardPaddingMedium: `${ space( 4 ) } ${ space( 6 ) }`, cardPaddingLarge: `${ space( 6 ) } ${ space( 8 ) }`, popoverShadow: `0 0.7px 1px rgba(0, 0, 0, 0.1), 0 1.2px 1.7px -0.2px rgba(0, 0, 0, 0.1), 0 2.3px 3.3px -0.5px rgba(0, 0, 0, 0.1)`, + elevationXSmall: `0 0.7px 1px rgba(0, 0, 0, 0.1), 0 1.2px 1.7px -0.2px rgba(0, 0, 0, 0.1), 0 2.3px 3.3px -0.5px rgba(0, 0, 0, 0.1)`, + elevationSmall: `0 0.7px 1px 0 rgba(0, 0, 0, 0.12), 0 2.2px 3.7px -0.2px rgba(0, 0, 0, 0.12), 0 5.3px 7.3px -0.5px rgba(0, 0, 0, 0.12)`, + elevationMedium: `0 0.7px 1px 0 rgba(0, 0, 0, 0.14), 0 4.2px 5.7px -0.2px rgba(0, 0, 0, 0.14), 0 7.3px 9.3px -0.5px rgba(0, 0, 0, 0.14)`, + elevationLarge: `0 0.7px 1px rgba(0, 0, 0, 0.15), 0 2.7px 3.8px -0.2px rgba(0, 0, 0, 0.15), 0 5.5px 7.8px -0.3px rgba(0, 0, 0, 0.15), 0.1px 11.5px 16.4px -0.5px rgba(0, 0, 0, 0.15)`, surfaceBackgroundColor: COLORS.white, surfaceBackgroundSubtleColor: '#F3F3F3', surfaceBackgroundTintColor: '#F5F5F5', From 4a8b166d623c442087a36eb41c35cc6dcd4e14ca Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 12 Aug 2024 11:47:55 +0200 Subject: [PATCH 0344/1908] DataViews: Refactor the edit function to be based on discrete controls (#64404) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../src/dataform-controls/datetime.tsx | 37 ++++++++++ .../dataform-controls/index.tsx | 25 +++++-- .../src/dataform-controls/integer.tsx | 38 ++++++++++ .../dataform-controls/radio.tsx | 9 ++- .../src/dataform-controls/select.tsx | 52 ++++++++++++++ .../dataviews/src/dataform-controls/text.tsx | 40 +++++++++++ .../dataviews/src/field-types/datetime.tsx | 67 +---------------- .../dataviews/src/field-types/integer.tsx | 72 +------------------ packages/dataviews/src/field-types/text.tsx | 71 +----------------- packages/dataviews/src/normalize-fields.ts | 2 +- packages/dataviews/src/types.ts | 6 +- 11 files changed, 201 insertions(+), 218 deletions(-) create mode 100644 packages/dataviews/src/dataform-controls/datetime.tsx rename packages/dataviews/src/{components => }/dataform-controls/index.tsx (60%) create mode 100644 packages/dataviews/src/dataform-controls/integer.tsx rename packages/dataviews/src/{components => }/dataform-controls/radio.tsx (80%) create mode 100644 packages/dataviews/src/dataform-controls/select.tsx create mode 100644 packages/dataviews/src/dataform-controls/text.tsx diff --git a/packages/dataviews/src/dataform-controls/datetime.tsx b/packages/dataviews/src/dataform-controls/datetime.tsx new file mode 100644 index 00000000000000..3ba22dc0c1b089 --- /dev/null +++ b/packages/dataviews/src/dataform-controls/datetime.tsx @@ -0,0 +1,37 @@ +/** + * WordPress dependencies + */ +import { BaseControl, TimePicker } from '@wordpress/components'; +import { useCallback } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { DataFormControlProps } from '../types'; + +export default function DateTime< Item >( { + data, + field, + onChange, +}: DataFormControlProps< Item > ) { + const { id, label } = field; + const value = field.getValue( { item: data } ); + + const onChangeControl = useCallback( + ( newValue: string | null ) => onChange( { [ id ]: newValue } ), + [ id, onChange ] + ); + + return ( + <fieldset> + <BaseControl.VisualLabel as="legend"> + { label } + </BaseControl.VisualLabel> + <TimePicker + currentTime={ value } + onChange={ onChangeControl } + hideLabelFromVision + /> + </fieldset> + ); +} diff --git a/packages/dataviews/src/components/dataform-controls/index.tsx b/packages/dataviews/src/dataform-controls/index.tsx similarity index 60% rename from packages/dataviews/src/components/dataform-controls/index.tsx rename to packages/dataviews/src/dataform-controls/index.tsx index dd913269cd09ea..297e73c28f837c 100644 --- a/packages/dataviews/src/components/dataform-controls/index.tsx +++ b/packages/dataviews/src/dataform-controls/index.tsx @@ -10,15 +10,23 @@ import type { DataFormControlProps, Field, FieldTypeDefinition, -} from '../../types'; +} from '../types'; +import datetime from './datetime'; +import integer from './integer'; import radio from './radio'; +import select from './select'; +import text from './text'; interface FormControls { [ key: string ]: ComponentType< DataFormControlProps< any > >; } const FORM_CONTROLS: FormControls = { + datetime, + integer, radio, + select, + text, }; export function getControl< Item >( @@ -29,12 +37,19 @@ export function getControl< Item >( return field.Edit; } - let control; if ( typeof field.Edit === 'string' ) { - control = getControlByType( field.Edit ); + return getControlByType( field.Edit ); } - return control || fieldTypeDefinition.Edit; + if ( field.elements ) { + return getControlByType( 'select' ); + } + + if ( typeof fieldTypeDefinition.Edit === 'string' ) { + return getControlByType( fieldTypeDefinition.Edit ); + } + + return fieldTypeDefinition.Edit; } export function getControlByType( type: string ) { @@ -42,5 +57,5 @@ export function getControlByType( type: string ) { return FORM_CONTROLS[ type ]; } - return null; + throw 'Control ' + type + ' not found'; } diff --git a/packages/dataviews/src/dataform-controls/integer.tsx b/packages/dataviews/src/dataform-controls/integer.tsx new file mode 100644 index 00000000000000..f70a90ffe15239 --- /dev/null +++ b/packages/dataviews/src/dataform-controls/integer.tsx @@ -0,0 +1,38 @@ +/** + * WordPress dependencies + */ +import { __experimentalNumberControl as NumberControl } from '@wordpress/components'; +import { useCallback } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { DataFormControlProps } from '../types'; + +export default function Integer< Item >( { + data, + field, + onChange, + hideLabelFromVision, +}: DataFormControlProps< Item > ) { + const { id, label, description } = field; + const value = field.getValue( { item: data } ) ?? ''; + const onChangeControl = useCallback( + ( newValue: string | undefined ) => + onChange( { + [ id ]: Number( newValue ), + } ), + [ id, onChange ] + ); + + return ( + <NumberControl + label={ label } + help={ description } + value={ value } + onChange={ onChangeControl } + __next40pxDefaultSize + hideLabelFromVision={ hideLabelFromVision } + /> + ); +} diff --git a/packages/dataviews/src/components/dataform-controls/radio.tsx b/packages/dataviews/src/dataform-controls/radio.tsx similarity index 80% rename from packages/dataviews/src/components/dataform-controls/radio.tsx rename to packages/dataviews/src/dataform-controls/radio.tsx index d264aa6c24b7fb..3d616404e0c053 100644 --- a/packages/dataviews/src/components/dataform-controls/radio.tsx +++ b/packages/dataviews/src/dataform-controls/radio.tsx @@ -7,9 +7,9 @@ import { useCallback } from '@wordpress/element'; /** * Internal dependencies */ -import type { DataFormControlProps } from '../../types'; +import type { DataFormControlProps } from '../types'; -export default function Edit< Item >( { +export default function Radio< Item >( { data, field, onChange, @@ -20,10 +20,9 @@ export default function Edit< Item >( { const onChangeControl = useCallback( ( newValue: string ) => - onChange( ( prevItem: Item ) => ( { - ...prevItem, + onChange( { [ id ]: newValue, - } ) ), + } ), [ id, onChange ] ); diff --git a/packages/dataviews/src/dataform-controls/select.tsx b/packages/dataviews/src/dataform-controls/select.tsx new file mode 100644 index 00000000000000..2b3bd9373fc155 --- /dev/null +++ b/packages/dataviews/src/dataform-controls/select.tsx @@ -0,0 +1,52 @@ +/** + * WordPress dependencies + */ +import { SelectControl } from '@wordpress/components'; +import { useCallback } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { DataFormControlProps } from '../types'; + +export default function Select< Item >( { + data, + field, + onChange, + hideLabelFromVision, +}: DataFormControlProps< Item > ) { + const { id, label } = field; + const value = field.getValue( { item: data } ) ?? ''; + const onChangeControl = useCallback( + ( newValue: any ) => + onChange( { + [ id ]: newValue, + } ), + [ id, onChange ] + ); + + const elements = [ + /* + * Value can be undefined when: + * + * - the field is not required + * - in bulk editing + * + */ + { label: __( 'Select item' ), value: '' }, + ...( field?.elements ?? [] ), + ]; + + return ( + <SelectControl + label={ label } + value={ value } + options={ elements } + onChange={ onChangeControl } + __next40pxDefaultSize + __nextHasNoMarginBottom + hideLabelFromVision={ hideLabelFromVision } + /> + ); +} diff --git a/packages/dataviews/src/dataform-controls/text.tsx b/packages/dataviews/src/dataform-controls/text.tsx new file mode 100644 index 00000000000000..7ac095f4abede7 --- /dev/null +++ b/packages/dataviews/src/dataform-controls/text.tsx @@ -0,0 +1,40 @@ +/** + * WordPress dependencies + */ +import { TextControl } from '@wordpress/components'; +import { useCallback } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { DataFormControlProps } from '../types'; + +export default function Text< Item >( { + data, + field, + onChange, + hideLabelFromVision, +}: DataFormControlProps< Item > ) { + const { id, label, placeholder } = field; + const value = field.getValue( { item: data } ); + + const onChangeControl = useCallback( + ( newValue: string ) => + onChange( { + [ id ]: newValue, + } ), + [ id, onChange ] + ); + + return ( + <TextControl + label={ label } + placeholder={ placeholder } + value={ value ?? '' } + onChange={ onChangeControl } + __next40pxDefaultSize + __nextHasNoMarginBottom + hideLabelFromVision={ hideLabelFromVision } + /> + ); +} diff --git a/packages/dataviews/src/field-types/datetime.tsx b/packages/dataviews/src/field-types/datetime.tsx index c6b69048efe13c..aa97fc86c318c2 100644 --- a/packages/dataviews/src/field-types/datetime.tsx +++ b/packages/dataviews/src/field-types/datetime.tsx @@ -1,18 +1,7 @@ -/** - * WordPress dependencies - */ -import { BaseControl, TimePicker, SelectControl } from '@wordpress/components'; -import { useCallback } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; - /** * Internal dependencies */ -import type { - SortDirection, - ValidationContext, - DataFormControlProps, -} from '../types'; +import type { SortDirection, ValidationContext } from '../types'; function sort( a: any, b: any, direction: SortDirection ) { const timeA = new Date( a ).getTime(); @@ -32,60 +21,8 @@ function isValid( value: any, context?: ValidationContext ) { return true; } -function Edit< Item >( { - data, - field, - onChange, -}: DataFormControlProps< Item > ) { - const { id, label } = field; - const value = field.getValue( { item: data } ); - - const onChangeControl = useCallback( - ( newValue: string | null ) => onChange( { [ id ]: newValue } ), - [ id, onChange ] - ); - - if ( field.elements ) { - const elements = [ - /* - * Value can be undefined when: - * - * - the field is not required - * - in bulk editing - * - */ - { label: __( 'Select item' ), value: '' }, - ...field.elements, - ]; - - return ( - <SelectControl - label={ label } - value={ value } - options={ elements } - onChange={ onChangeControl } - __next40pxDefaultSize - __nextHasNoMarginBottom - /> - ); - } - - return ( - <fieldset> - <BaseControl.VisualLabel as="legend"> - { label } - </BaseControl.VisualLabel> - <TimePicker - currentTime={ value } - onChange={ onChangeControl } - hideLabelFromVision - /> - </fieldset> - ); -} - export default { sort, isValid, - Edit, + Edit: 'datetime', }; diff --git a/packages/dataviews/src/field-types/integer.tsx b/packages/dataviews/src/field-types/integer.tsx index 38570ea6fec1a5..f57c8e382db816 100644 --- a/packages/dataviews/src/field-types/integer.tsx +++ b/packages/dataviews/src/field-types/integer.tsx @@ -1,21 +1,7 @@ -/** - * WordPress dependencies - */ -import { - __experimentalNumberControl as NumberControl, - SelectControl, -} from '@wordpress/components'; -import { useCallback } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; - /** * Internal dependencies */ -import type { - SortDirection, - ValidationContext, - DataFormControlProps, -} from '../types'; +import type { SortDirection, ValidationContext } from '../types'; function sort( a: any, b: any, direction: SortDirection ) { return direction === 'asc' ? a - b : b - a; @@ -41,62 +27,8 @@ function isValid( value: any, context?: ValidationContext ) { return true; } -function Edit< Item >( { - data, - field, - onChange, - hideLabelFromVision, -}: DataFormControlProps< Item > ) { - const { id, label, description } = field; - const value = field.getValue( { item: data } ) ?? ''; - const onChangeControl = useCallback( - ( newValue: string | undefined ) => - onChange( { - [ id ]: Number( newValue ), - } ), - [ id, onChange ] - ); - - if ( field.elements ) { - const elements = [ - /* - * Value can be undefined when: - * - * - the field is not required - * - in bulk editing - * - */ - { label: __( 'Select item' ), value: '' }, - ...field.elements, - ]; - - return ( - <SelectControl - label={ label } - value={ value } - options={ elements } - onChange={ onChangeControl } - __next40pxDefaultSize - __nextHasNoMarginBottom - hideLabelFromVision={ hideLabelFromVision } - /> - ); - } - - return ( - <NumberControl - label={ label } - help={ description } - value={ value } - onChange={ onChangeControl } - __next40pxDefaultSize - hideLabelFromVision={ hideLabelFromVision } - /> - ); -} - export default { sort, isValid, - Edit, + Edit: 'integer', }; diff --git a/packages/dataviews/src/field-types/text.tsx b/packages/dataviews/src/field-types/text.tsx index 5364017c629b00..76ff699d0848c4 100644 --- a/packages/dataviews/src/field-types/text.tsx +++ b/packages/dataviews/src/field-types/text.tsx @@ -1,18 +1,7 @@ -/** - * WordPress dependencies - */ -import { SelectControl, TextControl } from '@wordpress/components'; -import { useCallback } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; - /** * Internal dependencies */ -import type { - SortDirection, - ValidationContext, - DataFormControlProps, -} from '../types'; +import type { SortDirection, ValidationContext } from '../types'; function sort( valueA: any, valueB: any, direction: SortDirection ) { return direction === 'asc' @@ -31,64 +20,8 @@ function isValid( value: any, context?: ValidationContext ) { return true; } -function Edit< Item >( { - data, - field, - onChange, - hideLabelFromVision, -}: DataFormControlProps< Item > ) { - const { id, label, placeholder } = field; - const value = field.getValue( { item: data } ); - - const onChangeControl = useCallback( - ( newValue: string ) => - onChange( { - [ id ]: newValue, - } ), - [ id, onChange ] - ); - - if ( field.elements ) { - const elements = [ - /* - * Value can be undefined when: - * - * - the field is not required - * - in bulk editing - * - */ - { label: __( 'Select item' ), value: '' }, - ...field.elements, - ]; - - return ( - <SelectControl - label={ label } - value={ value } - options={ elements } - onChange={ onChangeControl } - __next40pxDefaultSize - __nextHasNoMarginBottom - hideLabelFromVision={ hideLabelFromVision } - /> - ); - } - - return ( - <TextControl - label={ label } - placeholder={ placeholder } - value={ value ?? '' } - onChange={ onChangeControl } - __next40pxDefaultSize - __nextHasNoMarginBottom - hideLabelFromVision={ hideLabelFromVision } - /> - ); -} - export default { sort, isValid, - Edit, + Edit: 'text', }; diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index 2cdde5b3343798..f9f95b5b8140dc 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -3,7 +3,7 @@ */ import getFieldTypeDefinition from './field-types'; import type { Field, NormalizedField } from './types'; -import { getControl } from './components/dataform-controls'; +import { getControl } from './dataform-controls'; /** * Apply default values and normalize the fields config. diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 34e74eabd7c7d8..7bbbc8cb863c09 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -63,9 +63,9 @@ export type FieldTypeDefinition< Item > = { isValid: ( item: Item, context?: ValidationContext ) => boolean; /** - * Callback used to render an edit control for the field. + * Callback used to render an edit control for the field or control name. */ - Edit: ComponentType< DataFormControlProps< Item > >; + Edit: ComponentType< DataFormControlProps< Item > > | string; }; /** @@ -105,7 +105,7 @@ export type Field< Item > = { /** * Callback used to render an edit control for the field. */ - Edit?: ComponentType< DataFormControlProps< Item > > | 'radio'; + Edit?: ComponentType< DataFormControlProps< Item > > | string; /** * Callback used to sort the field. From 1e13913453eb520805e3aaadd6c2670be2c642e2 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 12 Aug 2024 14:03:34 +0400 Subject: [PATCH 0345/1908] Edit Post: Avoid unnecessary post-template ID lookup (#64431) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/edit-post/src/store/private-selectors.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/edit-post/src/store/private-selectors.js b/packages/edit-post/src/store/private-selectors.js index c151f935d68d50..0c0ac3c518024d 100644 --- a/packages/edit-post/src/store/private-selectors.js +++ b/packages/edit-post/src/store/private-selectors.js @@ -50,8 +50,11 @@ export const getEditedPostTemplateId = createRegistrySelector( } else { slugToCheck = postType === 'page' ? 'page' : `single-${ postType }`; } - return select( coreStore ).getDefaultTemplateId( { - slug: slugToCheck, - } ); + + if ( postType ) { + return select( coreStore ).getDefaultTemplateId( { + slug: slugToCheck, + } ); + } } ); From da50610ac45e2cd18b59424d260bb3d693535061 Mon Sep 17 00:00:00 2001 From: JuanMa <juanma.garrido@automattic.com> Date: Mon, 12 Aug 2024 11:28:40 +0100 Subject: [PATCH 0346/1908] Docs/Dataviews component - Update README with missing properties and recent changes (#64435) Co-authored-by: juanmaguitar <juanmaguitar@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- packages/dataviews/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index c82a748df98858..df537d2a8cecff 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -72,12 +72,12 @@ const STATUSES = [ const fields = [ { id: 'title', - header: 'Title', + label: 'Title', enableHiding: false, }, { id: 'date', - header: 'Date', + label: 'Date', render: ( { item } ) => { return ( <time>{ getFormattedDate( item.date ) }</time> @@ -86,7 +86,7 @@ const fields = [ }, { id: 'author', - header: __( 'Author' ), + label: __( 'Author' ), render: ( { item } ) => { return ( <a href="...">{ item.author }</a> @@ -102,7 +102,7 @@ const fields = [ enableSorting: false }, { - header: __( 'Status' ), + label: __( 'Status' ), id: 'status', getValue: ( { item } ) => STATUSES.find( ( { value } ) => value === item.status ) @@ -119,13 +119,14 @@ const fields = [ Each field is an object with the following properties: - `id`: identifier for the field. Unique. -- `header`: the field's name to be shown in the UI. +- `label`: the field's name to be shown in the UI. - `getValue`: function that returns the value of the field, defaults to `field[id]`. - `render`: function that renders the field. Optional, `getValue` will be used if `render` is not defined. - `elements`: the set of valid values for the field's value. - `type`: the type of the field. See "Field types". - `enableSorting`: whether the data can be sorted by the given field. True by default. - `enableHiding`: whether the field can be hidden. True by default. +- `enableGlobalSearch`: whether the field is searchable. False by default. - `filterBy`: configuration for the filters. - `operators`: the list of operators supported by the field. - `isPrimary`: whether it is a primary filter. A primary filter is always visible and is not listed in the "Add filter" component, except for the list layout where it behaves like a secondary filter. From d86a4999338183fc1f17067bed11d6b53ed46f87 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Mon, 12 Aug 2024 16:27:41 +0530 Subject: [PATCH 0347/1908] Tag Cloud: Add border block support (#63579) * Add border support to tag cloud block * Prevent duplicate border styles in editor * Add comments on style and edit component changes in tag cloud block Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/block-library/src/tag-cloud/block.json | 12 ++++++++++++ packages/block-library/src/tag-cloud/edit.js | 11 ++++++++++- packages/block-library/src/tag-cloud/editor.scss | 4 +++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/tag-cloud/block.json b/packages/block-library/src/tag-cloud/block.json index 0c2095bff2a152..044bc0c5333768 100644 --- a/packages/block-library/src/tag-cloud/block.json +++ b/packages/block-library/src/tag-cloud/block.json @@ -51,6 +51,18 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } }, "editorStyle": "wp-block-tag-cloud-editor" diff --git a/packages/block-library/src/tag-cloud/edit.js b/packages/block-library/src/tag-cloud/edit.js index 9a2b531b30f8ab..8ced99271e4807 100644 --- a/packages/block-library/src/tag-cloud/edit.js +++ b/packages/block-library/src/tag-cloud/edit.js @@ -107,6 +107,15 @@ function TagCloudEdit( { attributes, setAttributes } ) { setAttributes( updateObj ); }; + // Remove border styles from the server-side attributes to prevent duplicate border. + const serverSideAttributes = { + ...attributes, + style: { + ...attributes?.style, + border: undefined, + }, + }; + const inspectorControls = ( <InspectorControls> <PanelBody title={ __( 'Settings' ) }> @@ -188,7 +197,7 @@ function TagCloudEdit( { attributes, setAttributes } ) { <ServerSideRender skipBlockSupportAttributes block="core/tag-cloud" - attributes={ attributes } + attributes={ serverSideAttributes } /> </Disabled> </div> diff --git a/packages/block-library/src/tag-cloud/editor.scss b/packages/block-library/src/tag-cloud/editor.scss index de2a95a386fa85..d00a450174f2fd 100644 --- a/packages/block-library/src/tag-cloud/editor.scss +++ b/packages/block-library/src/tag-cloud/editor.scss @@ -1,4 +1,4 @@ -// The following styles are to prevent duplicate spacing for the tag cloud +// The following styles are to prevent duplicate spacing and border for the tag cloud // block in the editor given it uses server side rendering. The specificity // must be higher than `0-1-0` to override global styles. Targeting the // inner use of the .wp-block-tag-cloud class should minimize impact on @@ -6,4 +6,6 @@ .wp-block-tag-cloud .wp-block-tag-cloud { margin: 0; padding: 0; + border: none; + border-radius: inherit; } From ba8c2c0d76957cb5534619ea496a79344fcacc6f Mon Sep 17 00:00:00 2001 From: Anton Vlasenko <43744263+anton-vlasenko@users.noreply.github.com> Date: Mon, 12 Aug 2024 13:06:56 +0200 Subject: [PATCH 0348/1908] Fix gutenberg/gutenberg-coding-standards licensing issues (#61913) 1. change the license to `GPL-2.0-or-later`; 2. remove third-party code from the `SinceTagSniff::find_docblock()` method; 3. remove third-party code from the `SinceTagSniff::is_function_call()` method; 4. remove the `SinceTagSniff::find_hook_docblock()` method and add the new `find_previous_line_token()` method (refactoring); 5. fix typo in the `SinceTagSniff::process()` method; 6. remove unused code from `bootstrap.php` and make variables use snake case; 7. add the `License` section to the `README.md` file. Co-authored-by: anton-vlasenko <antonvlasenko@git.wordpress.org> Co-authored-by: rodrigoprimo <rodrigosprimo@git.wordpress.org> Co-authored-by: azaozz <azaozz@git.wordpress.org> --- .../.phpcs.xml.dist | 9 +- .../ForbiddenFunctionsAndClassesSniff.php | 3 +- .../GuardedFunctionAndClassNamesSniff.php | 3 +- .../Sniffs/Commenting/SinceTagSniff.php | 122 +++++++----------- .../ValidBlockLibraryFunctionNameSniff.php | 3 +- .../Gutenberg/Tests/AbstractSniffUnitTest.php | 10 +- .../ForbiddenFunctionsAndClassesUnitTest.php | 3 +- .../GuardedFunctionAndClassNamesUnitTest.php | 3 +- .../Tests/Commenting/SinceTagUnitTest.php | 3 +- .../ValidBlockLibraryFunctionNameUnitTest.php | 3 +- test/php/gutenberg-coding-standards/README.md | 8 +- .../Tests/bootstrap.php | 87 ++++--------- .../gutenberg-coding-standards/composer.json | 2 +- 13 files changed, 92 insertions(+), 167 deletions(-) diff --git a/test/php/gutenberg-coding-standards/.phpcs.xml.dist b/test/php/gutenberg-coding-standards/.phpcs.xml.dist index 7f717f65374d7b..7ebe60e3d28567 100644 --- a/test/php/gutenberg-coding-standards/.phpcs.xml.dist +++ b/test/php/gutenberg-coding-standards/.phpcs.xml.dist @@ -1,15 +1,8 @@ <?xml version="1.0"?> -<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="WordPress Coding Standards" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/squizlabs/PHP_CodeSniffer/master/phpcs.xsd"> +<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Gutenberg Coding Standards" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/PHPCSStandards/PHP_CodeSniffer/master/phpcs.xsd"> <description>The Coding standard for the Gutenberg Coding Standards itself.</description> - <!-- - ############################################################################# - COMMAND LINE ARGUMENTS - https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-Ruleset - ############################################################################# - --> - <file>.</file> <!-- Exclude Composer vendor directory. --> diff --git a/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/CodeAnalysis/ForbiddenFunctionsAndClassesSniff.php b/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/CodeAnalysis/ForbiddenFunctionsAndClassesSniff.php index 87d966ecb56030..12d388cc378180 100644 --- a/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/CodeAnalysis/ForbiddenFunctionsAndClassesSniff.php +++ b/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/CodeAnalysis/ForbiddenFunctionsAndClassesSniff.php @@ -3,8 +3,7 @@ * Gutenberg Coding Standards. * * @package gutenberg/gutenberg-coding-standards - * @link https://github.com/WordPress/gutenberg - * @license https://opensource.org/licenses/MIT MIT + * @link https://github.com/WordPress/gutenberg/tree/trunk/test/php/gutenberg-coding-standards */ namespace GutenbergCS\Gutenberg\Sniffs\CodeAnalysis; diff --git a/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/CodeAnalysis/GuardedFunctionAndClassNamesSniff.php b/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/CodeAnalysis/GuardedFunctionAndClassNamesSniff.php index c6e51119f1513a..d947d6d9382b35 100644 --- a/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/CodeAnalysis/GuardedFunctionAndClassNamesSniff.php +++ b/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/CodeAnalysis/GuardedFunctionAndClassNamesSniff.php @@ -3,8 +3,7 @@ * Gutenberg Coding Standards. * * @package gutenberg/gutenberg-coding-standards - * @link https://github.com/WordPress/gutenberg - * @license https://opensource.org/licenses/MIT MIT + * @link https://github.com/WordPress/gutenberg/tree/trunk/test/php/gutenberg-coding-standards */ namespace GutenbergCS\Gutenberg\Sniffs\CodeAnalysis; diff --git a/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/Commenting/SinceTagSniff.php b/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/Commenting/SinceTagSniff.php index f216f4f681f0e2..20f698954cb267 100644 --- a/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/Commenting/SinceTagSniff.php +++ b/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/Commenting/SinceTagSniff.php @@ -3,8 +3,7 @@ * Gutenberg Coding Standards. * * @package gutenberg/gutenberg-coding-standards - * @link https://github.com/WordPress/gutenberg - * @license https://opensource.org/licenses/MIT MIT + * @link https://github.com/WordPress/gutenberg/tree/trunk/test/php/gutenberg-coding-standards */ namespace GutenbergCS\Gutenberg\Sniffs\Commenting; @@ -22,7 +21,7 @@ /** * This sniff verifies the presence of valid `@since` tags in the docblocks of various PHP structures * and WordPress hooks. Supported structures include classes, interfaces, traits, enums, functions, methods and properties. - * Files located within the __experimental block of the block-library are excluded from checks. + * Files located within the __experimental blocks of the block-library folder are excluded from checks. */ class SinceTagSniff implements Sniff { @@ -147,7 +146,7 @@ protected function process_hook( File $phpcs_file, $stack_pointer ) { $violation_codes = static::get_violation_codes( 'Hook' ); - $docblock = static::find_hook_docblock( $phpcs_file, $stack_pointer ); + $docblock = static::find_docblock( $phpcs_file, $stack_pointer ); $version_tags = static::parse_since_tags( $phpcs_file, $docblock ); if ( empty( $version_tags ) ) { @@ -436,114 +435,81 @@ protected function check_below_minimum_visibility( $visibility ) { } /** - * Finds the docblock associated with a hook, starting from a specified position in the token stack. - * Since a line containing a hook can include any type of tokens, this method backtracks through the tokens - * to locate the first token on the current line. This token is then used as the starting point for searching the docblock. + * Finds the first token on the previous line relative to the stack pointer passed to the method. * * @param File $phpcs_file The file being scanned. - * @param int $stack_pointer The position to start looking for the docblock. - * @return array|false An associative array containing the start and end tokens of the docblock, or false if not found. + * @param int $stack_pointer The position to find the previous line token from. + * @return int|false The last token on the previous line, or false if not found. */ - protected static function find_hook_docblock( File $phpcs_file, $stack_pointer ) { + protected static function find_previous_line_token( File $phpcs_file, $stack_pointer ) { $tokens = $phpcs_file->getTokens(); $current_line = $tokens[ $stack_pointer ]['line']; - for ( $i = $stack_pointer; $i >= 0; $i-- ) { - if ( $tokens[ $i ]['line'] < $current_line ) { - // The previous token is on the previous line, so the current token is the first on the line. - return static::find_docblock( $phpcs_file, $i + 1 ); + for ( $token = $stack_pointer; $token >= 0; $token-- ) { + if ( $tokens[ $token ]['line'] < $current_line ) { + return $token; } } - return static::find_docblock( $phpcs_file, 0 ); + return false; } /** - * Determines if a T_STRING token represents a function call. - * The implementation was copied from PHPCompatibility\Sniffs\Extensions\RemovedExtensionsSniff::process(). + * Finds the docblock preceding a specified position (stack pointer) in a given PHP file. * * @param File $phpcs_file The file being scanned. - * @param int $stack_pointer The position of the T_STRING token in question. - * @return bool True if the token represents a function call, false otherwise. + * @param int $stack_pointer The position (stack pointer) in the token stack from which to start searching backwards. + * @return array|false An associative array containing the start and end tokens of the docblock, or false if not found. */ - protected static function is_function_call( File $phpcs_file, $stack_pointer ) { - $tokens = $phpcs_file->getTokens(); - - // Find the next non-empty token. - $open_bracket = $phpcs_file->findNext( Tokens::$emptyTokens, ( $stack_pointer + 1 ), null, true ); - - if ( T_OPEN_PARENTHESIS !== $tokens[ $open_bracket ]['code'] ) { - // Not a function call. + protected static function find_docblock( File $phpcs_file, $stack_pointer ) { + // It can be assumed that the DocBlock should end on the previous line, not the current one. + $previous_line_end_token = static::find_previous_line_token( $phpcs_file, $stack_pointer ); + if ( false === $previous_line_end_token ) { return false; } - if ( false === isset( $tokens[ $open_bracket ]['parenthesis_closer'] ) ) { - // Not a function call. + $docblock_end_token = $phpcs_file->findPrevious( array( T_WHITESPACE ), $previous_line_end_token, null, true ); + + $tokens = $phpcs_file->getTokens(); + if ( false === $docblock_end_token || T_DOC_COMMENT_CLOSE_TAG !== $tokens[ $docblock_end_token ]['code'] ) { + // Only "/**" style comments are supported. return false; } - // Find the previous non-empty token. - $search = Tokens::$emptyTokens; - $search[] = T_BITWISE_AND; - $previous = $phpcs_file->findPrevious( $search, ( $stack_pointer - 1 ), null, true ); - - $previous_tokens_to_ignore = array( - T_FUNCTION, // Function declaration. - T_NEW, // Creating an object. - T_OBJECT_OPERATOR, // Calling an object. + return array( + 'start_token' => $tokens[ $docblock_end_token ]['comment_opener'], + 'end_token' => $docblock_end_token, ); - - return ! in_array( $tokens[ $previous ]['code'], $previous_tokens_to_ignore, true ); } /** - * Finds the docblock preceding a specified position (stack pointer) in a given PHP file. - * The implementation was copied from PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FunctionCommentSniff::process(). + * Determines if a T_STRING token represents a function call. * * @param File $phpcs_file The file being scanned. - * @param int $stack_pointer The position (stack pointer) in the token stack from which to start searching backwards. - * @return array|false An associative array containing the start and end tokens of the docblock, or false if not found. + * @param int $stack_pointer The position of the T_STRING token in question. + * @return bool True if the token represents a function call, false otherwise. */ - protected static function find_docblock( File $phpcs_file, $stack_pointer ) { - $tokens = $phpcs_file->getTokens(); - $ignore = Tokens::$methodPrefixes; - $ignore[ T_WHITESPACE ] = T_WHITESPACE; - - for ( $comment_end = ( $stack_pointer - 1 ); $comment_end >= 0; $comment_end-- ) { - if ( isset( $ignore[ $tokens[ $comment_end ]['code'] ] ) ) { - continue; - } - - if ( T_ATTRIBUTE_END === $tokens[ $comment_end ]['code'] - && isset( $tokens[ $comment_end ]['attribute_opener'] ) - ) { - $comment_end = $tokens[ $comment_end ]['attribute_opener']; - continue; - } + protected static function is_function_call( File $phpcs_file, $stack_pointer ) { + $tokens = $phpcs_file->getTokens(); - break; - } + // Find the previous non-empty token. + $previous = $phpcs_file->findPrevious( Tokens::$emptyTokens, ( $stack_pointer - 1 ), null, true ); - if ( $tokens[ $comment_end ]['code'] === T_COMMENT ) { - // Inline comments might just be closing comments for - // control structures or functions instead of function comments - // using the wrong comment type. If there is other code on the line, - // assume they relate to that code. - $previous = $phpcs_file->findPrevious( $ignore, ( $comment_end - 1 ), null, true ); - if ( false !== $previous && $tokens[ $previous ]['line'] === $tokens[ $comment_end ]['line'] ) { - $comment_end = $previous; - } - } + $previous_tokens_to_ignore = array( + T_NEW, // Creating an object. + T_OBJECT_OPERATOR, // Calling an object. + T_FUNCTION, // Function declaration. + ); - if ( T_DOC_COMMENT_CLOSE_TAG !== $tokens[ $comment_end ]['code'] ) { - // Only "/**" style comments are supported. + if ( in_array( $tokens[ $previous ]['code'], $previous_tokens_to_ignore, true ) ) { + // This is an object or function declaration. return false; } - return array( - 'start_token' => $tokens[ $comment_end ]['comment_opener'], - 'end_token' => $comment_end, - ); + // Find the next non-empty token. + $open_bracket = $phpcs_file->findNext( Tokens::$emptyTokens, ( $stack_pointer + 1 ), null, true ); + + return ( false !== $open_bracket ) && ( T_OPEN_PARENTHESIS === $tokens[ $open_bracket ]['code'] ); } /** diff --git a/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/NamingConventions/ValidBlockLibraryFunctionNameSniff.php b/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/NamingConventions/ValidBlockLibraryFunctionNameSniff.php index 74608921c32d89..bf7dbc2fd85d3c 100644 --- a/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/NamingConventions/ValidBlockLibraryFunctionNameSniff.php +++ b/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/NamingConventions/ValidBlockLibraryFunctionNameSniff.php @@ -3,8 +3,7 @@ * Gutenberg Coding Standards. * * @package gutenberg/gutenberg-coding-standards - * @link https://github.com/WordPress/gutenberg - * @license https://opensource.org/licenses/MIT MIT + * @link https://github.com/WordPress/gutenberg/tree/trunk/test/php/gutenberg-coding-standards */ namespace GutenbergCS\Gutenberg\Sniffs\NamingConventions; diff --git a/test/php/gutenberg-coding-standards/Gutenberg/Tests/AbstractSniffUnitTest.php b/test/php/gutenberg-coding-standards/Gutenberg/Tests/AbstractSniffUnitTest.php index 08838ce412fc3a..f1be5ab00b0750 100644 --- a/test/php/gutenberg-coding-standards/Gutenberg/Tests/AbstractSniffUnitTest.php +++ b/test/php/gutenberg-coding-standards/Gutenberg/Tests/AbstractSniffUnitTest.php @@ -3,8 +3,7 @@ * An abstract class that all sniff unit tests must extend. * * @package gutenberg-coding-standards/gbc - * @link https://github.com/WordPress/gutenberg - * @license https://opensource.org/licenses/MIT MIT + * @link https://github.com/WordPress/gutenberg/tree/trunk/test/php/gutenberg-coding-standards */ namespace GutenbergCS\Gutenberg\Tests; @@ -14,6 +13,9 @@ use PHP_CodeSniffer\Ruleset; use PHP_CodeSniffer\Sniffs\Sniff; +/** + * An abstract test class that contains common methods for all sniff unit tests. + */ abstract class AbstractSniffUnitTest extends BaseAbstractSniffUnitTest { /** @@ -65,7 +67,7 @@ public function setCliValues( $filename, $config ) { if ( ! isset( $GLOBALS['PHP_CODESNIFFER_RULESETS']['Gutenberg'] ) || ( ! $GLOBALS['PHP_CODESNIFFER_RULESETS']['Gutenberg'] instanceof Ruleset ) ) { - throw new \RuntimeException( $error_message ); + throw new \RuntimeException( $error_message ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- this is non-production code. } // Backup the original Ruleset instance. @@ -76,7 +78,7 @@ public function setCliValues( $filename, $config ) { $sniff_fqcn = $this->get_sniff_fqcn(); if ( ! isset( $current_ruleset->sniffs[ $sniff_fqcn ] ) ) { - throw new \RuntimeException( $error_message ); + throw new \RuntimeException( $error_message ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- this is non-production code. } $sniff = $current_ruleset->sniffs[ $sniff_fqcn ]; diff --git a/test/php/gutenberg-coding-standards/Gutenberg/Tests/CodeAnalysis/ForbiddenFunctionsAndClassesUnitTest.php b/test/php/gutenberg-coding-standards/Gutenberg/Tests/CodeAnalysis/ForbiddenFunctionsAndClassesUnitTest.php index 8026e88f1d9453..79719fba6039db 100644 --- a/test/php/gutenberg-coding-standards/Gutenberg/Tests/CodeAnalysis/ForbiddenFunctionsAndClassesUnitTest.php +++ b/test/php/gutenberg-coding-standards/Gutenberg/Tests/CodeAnalysis/ForbiddenFunctionsAndClassesUnitTest.php @@ -3,8 +3,7 @@ * Unit test class for Gutenberg Coding Standard. * * @package gutenberg-coding-standards/gbc - * @link https://github.com/WordPress/gutenberg - * @license https://opensource.org/licenses/MIT MIT + * @link https://github.com/WordPress/gutenberg/tree/trunk/test/php/gutenberg-coding-standards */ namespace GutenbergCS\Gutenberg\Tests\CodeAnalysis; diff --git a/test/php/gutenberg-coding-standards/Gutenberg/Tests/CodeAnalysis/GuardedFunctionAndClassNamesUnitTest.php b/test/php/gutenberg-coding-standards/Gutenberg/Tests/CodeAnalysis/GuardedFunctionAndClassNamesUnitTest.php index 652f6b735378ce..b4e26fd2e69c4f 100644 --- a/test/php/gutenberg-coding-standards/Gutenberg/Tests/CodeAnalysis/GuardedFunctionAndClassNamesUnitTest.php +++ b/test/php/gutenberg-coding-standards/Gutenberg/Tests/CodeAnalysis/GuardedFunctionAndClassNamesUnitTest.php @@ -3,8 +3,7 @@ * Unit test class for Gutenberg Coding Standard. * * @package gutenberg-coding-standards/gbc - * @link https://github.com/WordPress/gutenberg - * @license https://opensource.org/licenses/MIT MIT + * @link https://github.com/WordPress/gutenberg/tree/trunk/test/php/gutenberg-coding-standards */ namespace GutenbergCS\Gutenberg\Tests\CodeAnalysis; diff --git a/test/php/gutenberg-coding-standards/Gutenberg/Tests/Commenting/SinceTagUnitTest.php b/test/php/gutenberg-coding-standards/Gutenberg/Tests/Commenting/SinceTagUnitTest.php index bc7ca28c263ffe..1318687768c9dd 100644 --- a/test/php/gutenberg-coding-standards/Gutenberg/Tests/Commenting/SinceTagUnitTest.php +++ b/test/php/gutenberg-coding-standards/Gutenberg/Tests/Commenting/SinceTagUnitTest.php @@ -3,8 +3,7 @@ * Unit test class for Gutenberg Coding Standard. * * @package gutenberg-coding-standards/gbc - * @link https://github.com/WordPress/gutenberg - * @license https://opensource.org/licenses/MIT MIT + * @link https://github.com/WordPress/gutenberg/tree/trunk/test/php/gutenberg-coding-standards */ namespace GutenbergCS\Gutenberg\Tests\Commenting; diff --git a/test/php/gutenberg-coding-standards/Gutenberg/Tests/NamingConventions/ValidBlockLibraryFunctionNameUnitTest.php b/test/php/gutenberg-coding-standards/Gutenberg/Tests/NamingConventions/ValidBlockLibraryFunctionNameUnitTest.php index 51174dd769d0a3..14a2cb1a97dd71 100644 --- a/test/php/gutenberg-coding-standards/Gutenberg/Tests/NamingConventions/ValidBlockLibraryFunctionNameUnitTest.php +++ b/test/php/gutenberg-coding-standards/Gutenberg/Tests/NamingConventions/ValidBlockLibraryFunctionNameUnitTest.php @@ -3,8 +3,7 @@ * Unit test class for Gutenberg Coding Standard. * * @package gutenberg-coding-standards/gbc - * @link https://github.com/WordPress/gutenberg - * @license https://opensource.org/licenses/MIT MIT + * @link https://github.com/WordPress/gutenberg/tree/trunk/test/php/gutenberg-coding-standards */ namespace GutenbergCS\Gutenberg\Tests\NamingConventions; diff --git a/test/php/gutenberg-coding-standards/README.md b/test/php/gutenberg-coding-standards/README.md index 51f6574fa20534..500abe2e5b4812 100644 --- a/test/php/gutenberg-coding-standards/README.md +++ b/test/php/gutenberg-coding-standards/README.md @@ -1,3 +1,9 @@ # Gutenberg Coding Standards for Gutenberg -This project is a collection of [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) rules (sniffs) to validate code developed for Gutenberg. It ensures code quality and adherence to coding conventions. \ No newline at end of file +This project is a collection of [PHP_CodeSniffer](https://github.com/PHPCSStandards/PHP_CodeSniffer) rules (sniffs) to validate code developed for Gutenberg. It ensures code quality and adherence to coding conventions. + +## License + +This project is licensed under the same terms as the Gutenberg project. + +Please refer to this [LICENSE.md](../../../LICENSE.md) file for detailed license information. diff --git a/test/php/gutenberg-coding-standards/Tests/bootstrap.php b/test/php/gutenberg-coding-standards/Tests/bootstrap.php index f28528bc1b9726..547a1ce303835f 100644 --- a/test/php/gutenberg-coding-standards/Tests/bootstrap.php +++ b/test/php/gutenberg-coding-standards/Tests/bootstrap.php @@ -1,86 +1,51 @@ <?php /** - * Gutenberg Coding Standard. + * Gutenberg Coding Standards (GBCS) Bootstrap File. * - * Bootstrap file for running the tests. - * - * - Load the PHPCS PHPUnit bootstrap file providing cross-version PHPUnit support. - * {@link https://github.com/squizlabs/PHP_CodeSniffer/pull/1384} - * - Load the Composer autoload file. - * - Automatically limit the testing to the WordPressCS tests. + * Initializes the environment for running GBCS tests. * * @package gutenberg/gutenberg-coding-standards - * @link https://github.com/WordPress/gutenberg - * @license https://opensource.org/licenses/MIT MIT + * @link https://github.com/WordPress/gutenberg/tree/trunk/test/php/gutenberg-coding-standards */ if ( ! defined( 'PHP_CODESNIFFER_IN_TESTS' ) ) { define( 'PHP_CODESNIFFER_IN_TESTS', true ); } -$ds = DIRECTORY_SEPARATOR; - -/* - * Load the necessary PHPCS files. - */ -// Get the PHPCS dir from an environment variable. -$phpcsDir = getenv( 'PHPCS_DIR' ); -$composerPHPCSPath = dirname( __DIR__ ) . $ds . 'vendor' . $ds . 'squizlabs' . $ds . 'php_codesniffer'; - -if ( false === $phpcsDir && is_dir( $composerPHPCSPath ) ) { - // PHPCS installed via Composer. - $phpcsDir = $composerPHPCSPath; -} elseif ( false !== $phpcsDir ) { - /* - * PHPCS in a custom directory. - * For this to work, the `PHPCS_DIR` needs to be set in a custom `phpunit.xml` file. - */ - $phpcsDir = realpath( $phpcsDir ); -} - -// Try and load the PHPCS autoloader. -if ( false !== $phpcsDir - && file_exists( $phpcsDir . $ds . 'autoload.php' ) - && file_exists( $phpcsDir . $ds . 'tests' . $ds . 'bootstrap.php' ) -) { - require_once $phpcsDir . $ds . 'autoload.php'; - require_once $phpcsDir . $ds . 'tests' . $ds . 'bootstrap.php'; // PHPUnit 6.x+ support. -} else { - echo 'Uh oh... can\'t find PHPCS. +$dir_separator = DIRECTORY_SEPARATOR; -If you use Composer, please run `composer install`. -Otherwise, make sure you set a `PHPCS_DIR` environment variable in your phpunit.xml file -pointing to the PHPCS directory and that PHPCSUtils is included in the `installed_paths` -for that PHPCS install. -'; +// Define the path to the PHPCS directory. +$phpcs_path = dirname( __DIR__ ) . $dir_separator . 'vendor' . $dir_separator . 'squizlabs' . $dir_separator . 'php_codesniffer'; +$autoload_script_path = $phpcs_path . $dir_separator . 'autoload.php'; +$bootstrap_script_path = $phpcs_path . $dir_separator . 'tests' . $dir_separator . 'bootstrap.php'; - die( 1 ); +// Attempt to load the PHPCS autoloader. +if ( ! file_exists( $autoload_script_path ) || ! file_exists( $bootstrap_script_path ) ) { + echo 'PHP_CodeSniffer not found. Please run "composer install".' . PHP_EOL; + exit( 1 ); } +require_once $autoload_script_path; +require_once $bootstrap_script_path; // Support for PHPUnit 6.x+. -/* - * Set the PHPCS_IGNORE_TEST environment variable to ignore tests from other standards. +/** + * Configure the environment to ignore tests from other coding standards. */ -$gbcsStandards = array( - 'Gutenberg' => true, -); - -$allStandards = PHP_CodeSniffer\Util\Standards::getInstalledStandards(); -$allStandards[] = 'Generic'; +$available_standards = PHP_CodeSniffer\Util\Standards::getInstalledStandards(); +$ignored_standards = array( 'Generic' ); -$standardsToIgnore = array(); -foreach ( $allStandards as $standard ) { - if ( isset( $gbcsStandards[ $standard ] ) === true ) { +foreach ( $available_standards as $available_standard ) { + if ( 'Gutenberg' === $available_standard ) { continue; } - $standardsToIgnore[] = $standard; + $ignored_standards[] = $available_standard; } -$standardsToIgnoreString = implode( ',', $standardsToIgnore ); +$ignore_standards_string = implode( ',', $ignored_standards ); -// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_putenv -- This is not production, but test code. -putenv( "PHPCS_IGNORE_TESTS={$standardsToIgnoreString}" ); +// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_putenv -- This is non-production code. +putenv( "PHPCS_IGNORE_TESTS={$ignore_standards_string}" ); -// Clean up. -unset( $ds, $phpcsDir, $composerPHPCSPath, $allStandards, $standardsToIgnore, $standard, $standardsToIgnoreString ); +// Cleanup. +unset( $dir_separator, $phpcs_path, $available_standards, $ignored_standards, $available_standard, $ignore_standards_string ); diff --git a/test/php/gutenberg-coding-standards/composer.json b/test/php/gutenberg-coding-standards/composer.json index c1c27f81818aa5..2d79dc906a8d9e 100644 --- a/test/php/gutenberg-coding-standards/composer.json +++ b/test/php/gutenberg-coding-standards/composer.json @@ -8,7 +8,7 @@ "static analysis", "Gutenberg" ], - "license": "MIT", + "license": "GPL-2.0-or-later", "authors": [ { "name": "Contributors", From 7969ba3b21006a33455c40df59f32e95058d26a0 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 12 Aug 2024 13:43:07 +0200 Subject: [PATCH 0349/1908] DataForm: Update the style of the datetime fields to match the other types (#64438) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- .../dataviews/src/dataform-controls/datetime.tsx | 16 +++++++++++----- .../dataviews/src/dataform-controls/style.scss | 4 ++++ packages/dataviews/src/style.scss | 1 + 3 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 packages/dataviews/src/dataform-controls/style.scss diff --git a/packages/dataviews/src/dataform-controls/datetime.tsx b/packages/dataviews/src/dataform-controls/datetime.tsx index 3ba22dc0c1b089..b31c5c60bb9c6e 100644 --- a/packages/dataviews/src/dataform-controls/datetime.tsx +++ b/packages/dataviews/src/dataform-controls/datetime.tsx @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { BaseControl, TimePicker } from '@wordpress/components'; +import { BaseControl, TimePicker, VisuallyHidden } from '@wordpress/components'; import { useCallback } from '@wordpress/element'; /** @@ -13,6 +13,7 @@ export default function DateTime< Item >( { data, field, onChange, + hideLabelFromVision, }: DataFormControlProps< Item > ) { const { id, label } = field; const value = field.getValue( { item: data } ); @@ -23,10 +24,15 @@ export default function DateTime< Item >( { ); return ( - <fieldset> - <BaseControl.VisualLabel as="legend"> - { label } - </BaseControl.VisualLabel> + <fieldset className="dataviews-controls__datetime"> + { ! hideLabelFromVision && ( + <BaseControl.VisualLabel as="legend"> + { label } + </BaseControl.VisualLabel> + ) } + { hideLabelFromVision && ( + <VisuallyHidden as="legend">{ label }</VisuallyHidden> + ) } <TimePicker currentTime={ value } onChange={ onChangeControl } diff --git a/packages/dataviews/src/dataform-controls/style.scss b/packages/dataviews/src/dataform-controls/style.scss new file mode 100644 index 00000000000000..230826c0adf823 --- /dev/null +++ b/packages/dataviews/src/dataform-controls/style.scss @@ -0,0 +1,4 @@ +.dataviews-controls__datetime { + border: none; + padding: 0; +} diff --git a/packages/dataviews/src/style.scss b/packages/dataviews/src/style.scss index b780c9c3a587d5..7be92273663a87 100644 --- a/packages/dataviews/src/style.scss +++ b/packages/dataviews/src/style.scss @@ -11,4 +11,5 @@ @import "./dataviews-layouts/list/style.scss"; @import "./dataviews-layouts/table/style.scss"; +@import "./dataform-controls/style.scss"; @import "./dataforms-layouts/panel/style.scss"; From eecd89d151e944643149825e614f13b331f703a4 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Mon, 12 Aug 2024 14:48:18 +0200 Subject: [PATCH 0350/1908] Script Modules: Move data passing to 6.7 compat file (#64006) Move Script Modules data passing to compatibility directory. Add conditions to ensure the functionality is duplicated when present in Core. This prevents duplicate script tags with duplicate IDs from being printed. This feature is planned to ship in WordPress 6.7: https://core.trac.wordpress.org/ticket/61510 --- lib/compat/wordpress-6.7/script-modules.php | 104 ++++++++++++++++++++ lib/experimental/script-modules.php | 93 ----------------- lib/load.php | 1 + 3 files changed, 105 insertions(+), 93 deletions(-) create mode 100644 lib/compat/wordpress-6.7/script-modules.php diff --git a/lib/compat/wordpress-6.7/script-modules.php b/lib/compat/wordpress-6.7/script-modules.php new file mode 100644 index 00000000000000..0a440ec81688d2 --- /dev/null +++ b/lib/compat/wordpress-6.7/script-modules.php @@ -0,0 +1,104 @@ +<?php + +/** + * Print data associated with Script Modules in Script tags. + * + * This embeds data in the page HTML so that it is available on page load. + * + * Data can be associated with a given Script Module by using the + * `script_module_data_{$module_id}` filter. + * + * The data for a given Script Module will be JSON serialized in a script tag with an ID + * like `wp-script-module-data-{$module_id}`. + */ +function gutenberg_print_script_module_data(): void { + $get_marked_for_enqueue = new ReflectionMethod( 'WP_Script_Modules', 'get_marked_for_enqueue' ); + $get_marked_for_enqueue->setAccessible( true ); + $get_import_map = new ReflectionMethod( 'WP_Script_Modules', 'get_import_map' ); + $get_import_map->setAccessible( true ); + + $modules = array(); + foreach ( array_keys( $get_marked_for_enqueue->invoke( wp_script_modules() ) ) as $id ) { + $modules[ $id ] = true; + } + foreach ( array_keys( $get_import_map->invoke( wp_script_modules() )['imports'] ) as $id ) { + $modules[ $id ] = true; + } + + foreach ( array_keys( $modules ) as $module_id ) { + /** + * Filters data associated with a given Script Module. + * + * Script Modules may require data that is required for initialization or is essential to + * have immediately available on page load. These are suitable use cases for this data. + * + * This is best suited to a minimal set of data and is not intended to replace the REST API. + * + * If the filter returns no data (an empty array), nothing will be embedded in the page. + * + * The data for a given Script Module, if provided, will be JSON serialized in a script tag + * with an ID like `wp-script-module-data-{$module_id}`. + * + * The dynamic portion of the hook name, `$module_id`, refers to the Script Module ID that + * the data is associated with. + * + * @param array $data The data that should be associated with the array. + */ + $data = apply_filters( "script_module_data_{$module_id}", array() ); + + if ( is_array( $data ) && ! empty( $data ) ) { + /* + * This data will be printed as JSON inside a script tag like this: + * <script type="application/json"></script> + * + * A script tag must be closed by a sequence beginning with `</`. It's impossible to + * close a script tag without using `<`. We ensure that `<` is escaped and `/` can + * remain unescaped, so `</script>` will be printed as `\u003C/script\u00E3`. + * + * - JSON_HEX_TAG: All < and > are converted to \u003C and \u003E. + * - JSON_UNESCAPED_SLASHES: Don't escape /. + * + * If the page will use UTF-8 encoding, it's safe to print unescaped unicode: + * + * - JSON_UNESCAPED_UNICODE: Encode multibyte Unicode characters literally (instead of as `\uXXXX`). + * - JSON_UNESCAPED_LINE_TERMINATORS: The line terminators are kept unescaped when + * JSON_UNESCAPED_UNICODE is supplied. It uses the same behaviour as it was + * before PHP 7.1 without this constant. Available as of PHP 7.1.0. + * + * The JSON specification requires encoding in UTF-8, so if the generated HTML page + * is not encoded in UTF-8 then it's not safe to include those literals. They must + * be escaped to avoid encoding issues. + * + * @see https://www.rfc-editor.org/rfc/rfc8259.html for details on encoding requirements. + * @see https://www.php.net/manual/en/json.constants.php for details on these constants. + * @see https://html.spec.whatwg.org/#script-data-state for details on script tag parsing. + */ + $json_encode_flags = JSON_HEX_TAG | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS; + if ( 'UTF-8' !== get_option( 'blog_charset' ) ) { + $json_encode_flags = JSON_HEX_TAG | JSON_UNESCAPED_SLASHES; + } + + wp_print_inline_script_tag( + wp_json_encode( $data, $json_encode_flags ), + array( + 'type' => 'application/json', + 'id' => "wp-script-module-data-{$module_id}", + ) + ); + } + } +} + +add_action( + 'after_setup_theme', + function () { + if ( ! has_action( 'wp_footer', array( wp_script_modules(), 'print_script_module_data' ) ) ) { + add_action( 'wp_footer', 'gutenberg_print_script_module_data' ); + } + + if ( ! has_action( 'admin_print_footer_scripts', array( wp_script_modules(), 'print_script_module_data' ) ) ) { + add_action( 'admin_print_footer_scripts', 'gutenberg_print_script_module_data' ); + } + }, + 20 +); diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index 0093c2e974568f..5a14e1418ed6de 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -200,96 +200,3 @@ function gutenberg_dequeue_module( $module_identifier ) { _deprecated_function( __FUNCTION__, 'Gutenberg 17.6.0', 'wp_dequeue_script_module' ); wp_script_modules()->dequeue( $module_identifier ); } - - -/** - * Print data associated with Script Modules in Script tags. - * - * This embeds data in the page HTML so that it is available on page load. - * - * Data can be associated with a given Script Module by using the - * `script_module_data_{$module_id}` filter. - * - * The data for a given Script Module will be JSON serialized in a script tag with an ID - * like `wp-script-module-data-{$module_id}`. - */ -function gutenberg_print_script_module_data(): void { - $get_marked_for_enqueue = new ReflectionMethod( 'WP_Script_Modules', 'get_marked_for_enqueue' ); - $get_marked_for_enqueue->setAccessible( true ); - $get_import_map = new ReflectionMethod( 'WP_Script_Modules', 'get_import_map' ); - $get_import_map->setAccessible( true ); - - $modules = array(); - foreach ( array_keys( $get_marked_for_enqueue->invoke( wp_script_modules() ) ) as $id ) { - $modules[ $id ] = true; - } - foreach ( array_keys( $get_import_map->invoke( wp_script_modules() )['imports'] ) as $id ) { - $modules[ $id ] = true; - } - - foreach ( array_keys( $modules ) as $module_id ) { - /** - * Filters data associated with a given Script Module. - * - * Script Modules may require data that is required for initialization or is essential to - * have immediately available on page load. These are suitable use cases for this data. - * - * This is best suited to a minimal set of data and is not intended to replace the REST API. - * - * If the filter returns no data (an empty array), nothing will be embedded in the page. - * - * The data for a given Script Module, if provided, will be JSON serialized in a script tag - * with an ID like `wp-script-module-data-{$module_id}`. - * - * The dynamic portion of the hook name, `$module_id`, refers to the Script Module ID that - * the data is associated with. - * - * @param array $data The data that should be associated with the array. - */ - $data = apply_filters( "script_module_data_{$module_id}", array() ); - - if ( is_array( $data ) && ! empty( $data ) ) { - /* - * This data will be printed as JSON inside a script tag like this: - * <script type="application/json"></script> - * - * A script tag must be closed by a sequence beginning with `</`. It's impossible to - * close a script tag without using `<`. We ensure that `<` is escaped and `/` can - * remain unescaped, so `</script>` will be printed as `\u003C/script\u00E3`. - * - * - JSON_HEX_TAG: All < and > are converted to \u003C and \u003E. - * - JSON_UNESCAPED_SLASHES: Don't escape /. - * - * If the page will use UTF-8 encoding, it's safe to print unescaped unicode: - * - * - JSON_UNESCAPED_UNICODE: Encode multibyte Unicode characters literally (instead of as `\uXXXX`). - * - JSON_UNESCAPED_LINE_TERMINATORS: The line terminators are kept unescaped when - * JSON_UNESCAPED_UNICODE is supplied. It uses the same behaviour as it was - * before PHP 7.1 without this constant. Available as of PHP 7.1.0. - * - * The JSON specification requires encoding in UTF-8, so if the generated HTML page - * is not encoded in UTF-8 then it's not safe to include those literals. They must - * be escaped to avoid encoding issues. - * - * @see https://www.rfc-editor.org/rfc/rfc8259.html for details on encoding requirements. - * @see https://www.php.net/manual/en/json.constants.php for details on these constants. - * @see https://html.spec.whatwg.org/#script-data-state for details on script tag parsing. - */ - $json_encode_flags = JSON_HEX_TAG | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS; - if ( 'UTF-8' !== get_option( 'blog_charset' ) ) { - $json_encode_flags = JSON_HEX_TAG | JSON_UNESCAPED_SLASHES; - } - - wp_print_inline_script_tag( - wp_json_encode( $data, $json_encode_flags ), - array( - 'type' => 'application/json', - 'id' => "wp-script-module-data-{$module_id}", - ) - ); - } - } -} - -add_action( 'wp_footer', 'gutenberg_print_script_module_data' ); -add_action( 'admin_print_footer_scripts', 'gutenberg_print_script_module_data' ); diff --git a/lib/load.php b/lib/load.php index 4bb0ab88024a4a..c5f12af1654df2 100644 --- a/lib/load.php +++ b/lib/load.php @@ -103,6 +103,7 @@ function gutenberg_is_experiment_enabled( $name ) { // WordPress 6.7 compat. require __DIR__ . '/compat/wordpress-6.7/blocks.php'; require __DIR__ . '/compat/wordpress-6.7/block-bindings.php'; +require __DIR__ . '/compat/wordpress-6.7/script-modules.php'; // Experimental features. require __DIR__ . '/experimental/block-editor-settings-mobile.php'; From 9f5ffd2e8dd5ffc0abedf2b258dd5ace6b3bdb1e Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 12 Aug 2024 14:58:37 +0200 Subject: [PATCH 0351/1908] DataViews Extensibility: Allow unregistering the duplicate template part action (#64388) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../src/components/post-actions/actions.js | 72 +------------------ .../actions/duplicate-template-part.tsx | 70 ++++++++++++++++++ .../src/dataviews/store/private-actions.ts | 8 +++ packages/editor/src/dataviews/types.ts | 4 +- 4 files changed, 83 insertions(+), 71 deletions(-) create mode 100644 packages/editor/src/dataviews/actions/duplicate-template-part.tsx diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index ff5cd7ddbb5452..0df73d1996deb5 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -9,7 +9,6 @@ import { store as coreStore } from '@wordpress/core-data'; import { __, sprintf, _x } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; import { useMemo, useState, useEffect } from '@wordpress/element'; -import { parse } from '@wordpress/blocks'; import { DataForm } from '@wordpress/dataviews'; import { Button, @@ -27,7 +26,6 @@ import { } from '../../store/constants'; import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; -import { CreateTemplatePartModalContents } from '../create-template-part-modal'; import { getItemTitle } from '../../dataviews/actions/utils'; // TODO: this should be shared with other components (see post-fields in edit-site). @@ -268,75 +266,14 @@ const useDuplicatePostAction = ( postType ) => { ); }; -export const duplicateTemplatePartAction = { - id: 'duplicate-template-part', - label: _x( 'Duplicate', 'action label' ), - isEligible: ( item ) => item.type === TEMPLATE_PART_POST_TYPE, - modalHeader: _x( 'Duplicate template part', 'action label' ), - RenderModal: ( { items, closeModal } ) => { - const [ item ] = items; - const blocks = useMemo( () => { - return ( - item.blocks ?? - parse( - typeof item.content === 'string' - ? item.content - : item.content.raw, - { - __unstableSkipMigrationLogs: true, - } - ) - ); - }, [ item.content, item.blocks ] ); - const { createSuccessNotice } = useDispatch( noticesStore ); - function onTemplatePartSuccess() { - createSuccessNotice( - sprintf( - // translators: %s: The new template part's title e.g. 'Call to action (copy)'. - __( '"%s" duplicated.' ), - getItemTitle( item ) - ), - { type: 'snackbar', id: 'edit-site-patterns-success' } - ); - closeModal(); - } - return ( - <CreateTemplatePartModalContents - blocks={ blocks } - defaultArea={ item.area } - defaultTitle={ sprintf( - /* translators: %s: Existing template part title */ - __( '%s (Copy)' ), - getItemTitle( item ) - ) } - onCreate={ onTemplatePartSuccess } - onError={ closeModal } - confirmLabel={ _x( 'Duplicate', 'action label' ) } - closeModal={ closeModal } - /> - ); - }, -}; - export function usePostActions( { postType, onActionPerformed, context } ) { - const { - defaultActions, - postTypeObject, - userCanCreatePostType, - isBlockBasedTheme, - } = useSelect( + const { defaultActions, postTypeObject } = useSelect( ( select ) => { - const { getPostType, canUser, getCurrentTheme } = - select( coreStore ); + const { getPostType } = select( coreStore ); const { getEntityActions } = unlock( select( editorStore ) ); return { postTypeObject: getPostType( postType ), defaultActions: getEntityActions( 'postType', postType ), - userCanCreatePostType: canUser( 'create', { - kind: 'postType', - name: postType, - } ), - isBlockBasedTheme: getCurrentTheme()?.is_block_theme, }; }, [ postType ] @@ -368,10 +305,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { ! isPattern && duplicatePostAction : false, - isTemplateOrTemplatePart && - userCanCreatePostType && - isBlockBasedTheme && - duplicateTemplatePartAction, ...defaultActions, ].filter( Boolean ); // Filter actions based on provided context. If not provided @@ -437,7 +370,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { return actions; }, [ defaultActions, - userCanCreatePostType, isTemplateOrTemplatePart, isPattern, postTypeObject?.viewable, diff --git a/packages/editor/src/dataviews/actions/duplicate-template-part.tsx b/packages/editor/src/dataviews/actions/duplicate-template-part.tsx new file mode 100644 index 00000000000000..fa3cf39ba76268 --- /dev/null +++ b/packages/editor/src/dataviews/actions/duplicate-template-part.tsx @@ -0,0 +1,70 @@ +/** + * WordPress dependencies + */ +import { useDispatch } from '@wordpress/data'; +import { __, sprintf, _x } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; +import { useMemo } from '@wordpress/element'; +// @ts-ignore +import { parse } from '@wordpress/blocks'; +import type { Action } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import { TEMPLATE_PART_POST_TYPE } from '../../store/constants'; +import { CreateTemplatePartModalContents } from '../../components/create-template-part-modal'; +import { getItemTitle } from './utils'; +import type { TemplatePart } from '../types'; + +const duplicateTemplatePart: Action< TemplatePart > = { + id: 'duplicate-template-part', + label: _x( 'Duplicate', 'action label' ), + isEligible: ( item ) => item.type === TEMPLATE_PART_POST_TYPE, + modalHeader: _x( 'Duplicate template part', 'action label' ), + RenderModal: ( { items, closeModal } ) => { + const [ item ] = items; + const blocks = useMemo( () => { + return ( + item.blocks ?? + parse( + typeof item.content === 'string' + ? item.content + : item.content.raw, + { + __unstableSkipMigrationLogs: true, + } + ) + ); + }, [ item.content, item.blocks ] ); + const { createSuccessNotice } = useDispatch( noticesStore ); + function onTemplatePartSuccess() { + createSuccessNotice( + sprintf( + // translators: %s: The new template part's title e.g. 'Call to action (copy)'. + __( '"%s" duplicated.' ), + getItemTitle( item ) + ), + { type: 'snackbar', id: 'edit-site-patterns-success' } + ); + closeModal?.(); + } + return ( + <CreateTemplatePartModalContents + blocks={ blocks } + defaultArea={ item.area } + defaultTitle={ sprintf( + /* translators: %s: Existing template part title */ + __( '%s (Copy)' ), + getItemTitle( item ) + ) } + onCreate={ onTemplatePartSuccess } + onError={ closeModal } + confirmLabel={ _x( 'Duplicate', 'action label' ) } + closeModal={ closeModal } + /> + ); + }, +}; + +export default duplicateTemplatePart; diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 6854c29bb0c4e4..80449d1b7a0798 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -10,6 +10,7 @@ import { doAction } from '@wordpress/hooks'; */ import deletePost from '../actions/delete-post'; import duplicatePattern from '../actions/duplicate-pattern'; +import duplicateTemplatePart from '../actions/duplicate-template-part'; import exportPattern from '../actions/export-pattern'; import resetPost from '../actions/reset-post'; import trashPost from '../actions/trash-post'; @@ -81,8 +82,15 @@ export const registerPostTypeActions = kind: 'postType', name: postType, } ); + const currentTheme = await registry + .resolveSelect( coreStore ) + .getCurrentTheme(); const actions = [ + postTypeConfig.slug === 'wp_template_part' && + canCreate && + currentTheme?.is_block_theme && + duplicateTemplatePart, canCreate && postTypeConfig.slug === 'wp_block' ? duplicatePattern : undefined, diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts index 80b6f3c5ceb852..5750ab96eeae81 100644 --- a/packages/editor/src/dataviews/types.ts +++ b/packages/editor/src/dataviews/types.ts @@ -10,8 +10,10 @@ type PostStatus = export interface BasePost { status?: PostStatus; title: string | { rendered: string } | { raw: string }; + content: string | { raw: string; rendered: string }; type: string; id: string | number; + blocks?: Object[]; } export interface Template extends BasePost { @@ -27,12 +29,12 @@ export interface TemplatePart extends BasePost { source: string; has_theme_file: boolean; id: string; + area: string; } export interface Pattern extends BasePost { slug: string; title: { raw: string }; - content: { raw: string } | string; wp_pattern_sync_status: string; } From c73aa361c4bd82d8b3ee004e5195a22158cad1bf Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Mon, 12 Aug 2024 14:05:40 +0100 Subject: [PATCH 0352/1908] Block Insertion: Clear the insertion point when selecting a different block or clearing block selection (#64048) * Clear the insertion point when selecting a different block or clearing block selection * Use the block insertion point in the inserter, not the the one from the editor package * use block insertion point index * Don't change the insertion point when clearing block selection * Also set the insertion point in the quick inserter Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> --- .../src/components/inserter/quick-inserter.js | 5 ++++- packages/block-editor/src/store/reducer.js | 2 ++ .../src/components/inserter-sidebar/index.js | 14 ++++++++++---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/inserter/quick-inserter.js b/packages/block-editor/src/components/inserter/quick-inserter.js index aa3d54e87a7fd1..f4c52c04d20c4b 100644 --- a/packages/block-editor/src/components/inserter/quick-inserter.js +++ b/packages/block-editor/src/components/inserter/quick-inserter.js @@ -9,7 +9,7 @@ import clsx from 'clsx'; import { useState, useEffect } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { Button, SearchControl } from '@wordpress/components'; -import { useSelect } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -82,6 +82,8 @@ export default function QuickInserter( { } }, [ setInserterIsOpened ] ); + const { showInsertionPoint } = useDispatch( blockEditorStore ); + // When clicking Browse All select the appropriate block so as // the insertion point can work as expected. const onBrowseAll = () => { @@ -91,6 +93,7 @@ export default function QuickInserter( { filterValue, onSelect, } ); + showInsertionPoint( rootClientId, insertionIndex ); }; let maxBlockPatterns = 0; diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index cd4569c45e5801..91d853a50a6a42 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1624,6 +1624,8 @@ export function insertionPoint( state = null, action ) { } case 'HIDE_INSERTION_POINT': + case 'CLEAR_SELECTED_BLOCK': + case 'SELECT_BLOCK': return null; } diff --git a/packages/editor/src/components/inserter-sidebar/index.js b/packages/editor/src/components/inserter-sidebar/index.js index 675ae5e11544bc..bf613b5c8c001a 100644 --- a/packages/editor/src/components/inserter-sidebar/index.js +++ b/packages/editor/src/components/inserter-sidebar/index.js @@ -22,6 +22,7 @@ const { PrivateInserterLibrary } = unlock( blockEditorPrivateApis ); export default function InserterSidebar() { const { + blockInsertionPoint, blockSectionRootClientId, inserterSidebarToggleRef, insertionPoint, @@ -33,8 +34,12 @@ export default function InserterSidebar() { getInsertionPoint, isPublishSidebarOpened, } = unlock( select( editorStore ) ); - const { getBlockRootClientId, __unstableGetEditorMode, getSettings } = - select( blockEditorStore ); + const { + getBlockInsertionPoint, + getBlockRootClientId, + __unstableGetEditorMode, + getSettings, + } = select( blockEditorStore ); const { get } = select( preferencesStore ); const { getActiveComplementaryArea } = select( interfaceStore ); const getBlockSectionRootClientId = () => { @@ -47,6 +52,7 @@ export default function InserterSidebar() { return getBlockRootClientId(); }; return { + blockInsertionPoint: getBlockInsertionPoint(), inserterSidebarToggleRef: getInserterSidebarToggleRef(), insertionPoint: getInsertionPoint(), showMostUsedBlocks: get( 'core', 'mostUsedBlocks' ), @@ -85,9 +91,9 @@ export default function InserterSidebar() { showInserterHelpPanel shouldFocusBlock={ isMobileViewport } rootClientId={ - blockSectionRootClientId ?? insertionPoint.rootClientId + blockSectionRootClientId ?? blockInsertionPoint.rootClientId } - __experimentalInsertionIndex={ insertionPoint.insertionIndex } + __experimentalInsertionIndex={ blockInsertionPoint.index } onSelect={ insertionPoint.onSelect } __experimentalInitialTab={ insertionPoint.tab } __experimentalInitialCategory={ insertionPoint.category } From d6a27a056c5fe5c995a96f05a10105b80c7fa838 Mon Sep 17 00:00:00 2001 From: JuanMa <juanma.garrido@automattic.com> Date: Mon, 12 Aug 2024 15:47:54 +0100 Subject: [PATCH 0353/1908] DataViews: document missing action properties and link to storybook example (#64442) Co-authored-by: juanmaguitar <juanmaguitar@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- packages/dataviews/README.md | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index df537d2a8cecff..56cecedaef66ca 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -30,6 +30,9 @@ const Example = () => { }; ``` +> [!TIP] +> At https://wordpress.github.io/gutenberg/?path=/docs/dataviews-dataviews--docs there's an example implementation of the Dataviews component." + ## Properties ### `data`: `Object[]` @@ -79,41 +82,37 @@ const fields = [ id: 'date', label: 'Date', render: ( { item } ) => { - return ( - <time>{ getFormattedDate( item.date ) }</time> - ); - } + return <time>{ getFormattedDate( item.date ) }</time>; + }, }, { id: 'author', label: __( 'Author' ), render: ( { item } ) => { - return ( - <a href="...">{ item.author }</a> - ); + return <a href="...">{ item.author }</a>; }, elements: [ { value: 1, label: 'Admin' }, - { value: 2, label: 'User' } + { value: 2, label: 'User' }, ], filterBy: { - operators: [ 'is', 'isNot' ] + operators: [ 'is', 'isNot' ], }, - enableSorting: false + enableSorting: false, }, { label: __( 'Status' ), id: 'status', getValue: ( { item } ) => - STATUSES.find( ( { value } ) => value === item.status ) - ?.label ?? item.status, + STATUSES.find( ( { value } ) => value === item.status )?.label ?? + item.status, elements: STATUSES, filterBy: { operators: [ 'isAny' ], }, enableSorting: false, }, -] +]; ``` Each field is an object with the following properties: @@ -256,6 +255,8 @@ Each action is an object with the following properties: - `callback`: function, required unless `RenderModal` is provided. Callback function that takes the record as input and performs the required action. - `RenderModal`: ReactElement, optional. If an action requires that some UI be rendered in a modal, it can provide a component which takes as props the record as `item` and a `closeModal` function. When this prop is provided, the `callback` property is ignored. - `hideModalHeader`: boolean, optional. This property is used in combination with `RenderModal` and controls the visibility of the modal's header. If the action renders a modal and doesn't hide the header, the action's label is going to be used in the modal's header. +- `supportsBulk`: Whether the action can be used as a bulk action. False by default. +- `disabled`: Whether the action is disabled. False by default. ### `paginationInfo`: `Object` @@ -289,8 +290,8 @@ const defaultLayouts = { table: { layout: { primaryKey: 'my-key', - } - } + }, + }, }; ``` From 52171c992fbb9a43e69a25054e44de595ac7390d Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Mon, 12 Aug 2024 16:03:13 +0100 Subject: [PATCH 0354/1908] Update DropdownMenuV2 elevation, remove unused config value (#64432) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/dropdown-menu-v2/styles.ts | 2 +- packages/components/src/utils/config-values.js | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 96bf76815e71dd..57ba69197cfa98 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -11,6 +11,7 @@ - `Composite`: improve Storybook examples and add interactive controls ([#64397](https://github.com/WordPress/gutenberg/pull/64397)). - `TimePicker`: add `hideLabelFromVision` prop ([#64267](https://github.com/WordPress/gutenberg/pull/64267)). +- `DropdownMenuV2`: adopt elevation scale ([#64432](https://github.com/WordPress/gutenberg/pull/64432)). ## 28.5.0 (2024-08-07) diff --git a/packages/components/src/dropdown-menu-v2/styles.ts b/packages/components/src/dropdown-menu-v2/styles.ts index ab7c763b5f4569..950a549f8566a4 100644 --- a/packages/components/src/dropdown-menu-v2/styles.ts +++ b/packages/components/src/dropdown-menu-v2/styles.ts @@ -31,7 +31,7 @@ const ITEM_PADDING_INLINE = space( 3 ); const DEFAULT_BORDER_COLOR = COLORS.gray[ 300 ]; const DIVIDER_COLOR = COLORS.gray[ 200 ]; const TOOLBAR_VARIANT_BORDER_COLOR = COLORS.gray[ '900' ]; -const DEFAULT_BOX_SHADOW = `0 0 0 ${ CONFIG.borderWidth } ${ DEFAULT_BORDER_COLOR }, ${ CONFIG.popoverShadow }`; +const DEFAULT_BOX_SHADOW = `0 0 0 ${ CONFIG.borderWidth } ${ DEFAULT_BORDER_COLOR }, ${ CONFIG.elevationXSmall }`; const TOOLBAR_VARIANT_BOX_SHADOW = `0 0 0 ${ CONFIG.borderWidth } ${ TOOLBAR_VARIANT_BORDER_COLOR }`; const GRID_TEMPLATE_COLS = 'minmax( 0, max-content ) 1fr'; diff --git a/packages/components/src/utils/config-values.js b/packages/components/src/utils/config-values.js index 65632170c9e3d7..02c6f69544c2bf 100644 --- a/packages/components/src/utils/config-values.js +++ b/packages/components/src/utils/config-values.js @@ -73,7 +73,6 @@ export default Object.assign( {}, CONTROL_PROPS, TOGGLE_GROUP_CONTROL_PROPS, { cardPaddingSmall: `${ space( 4 ) }`, cardPaddingMedium: `${ space( 4 ) } ${ space( 6 ) }`, cardPaddingLarge: `${ space( 6 ) } ${ space( 8 ) }`, - popoverShadow: `0 0.7px 1px rgba(0, 0, 0, 0.1), 0 1.2px 1.7px -0.2px rgba(0, 0, 0, 0.1), 0 2.3px 3.3px -0.5px rgba(0, 0, 0, 0.1)`, elevationXSmall: `0 0.7px 1px rgba(0, 0, 0, 0.1), 0 1.2px 1.7px -0.2px rgba(0, 0, 0, 0.1), 0 2.3px 3.3px -0.5px rgba(0, 0, 0, 0.1)`, elevationSmall: `0 0.7px 1px 0 rgba(0, 0, 0, 0.12), 0 2.2px 3.7px -0.2px rgba(0, 0, 0, 0.12), 0 5.3px 7.3px -0.5px rgba(0, 0, 0, 0.12)`, elevationMedium: `0 0.7px 1px 0 rgba(0, 0, 0, 0.14), 0 4.2px 5.7px -0.2px rgba(0, 0, 0, 0.14), 0 7.3px 9.3px -0.5px rgba(0, 0, 0, 0.14)`, From 9c96970fdfa010b2b0b710c79c13684398b792f1 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 13 Aug 2024 01:22:31 +0900 Subject: [PATCH 0355/1908] Add margin-bottom lint rules for BaseControl (#64355) * Fix in Gallery block * Fix in Latest Posts block * Fix in Search block * Fix in Tag Cloud block * Fix in Video block * Fix in Global Styles Font Size * Fix in Global Styles PushChangesToGlobalStylesControl * Fix in new template part modal * Fix in pattern overrides block inspector * Add lint rule * Update docs Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .eslintrc.js | 1 + packages/block-library/src/gallery/edit.js | 5 +- packages/block-library/src/search/edit.js | 18 ++-- packages/block-library/src/search/editor.scss | 7 +- packages/block-library/src/tag-cloud/edit.js | 69 +++++++------- .../block-library/src/tag-cloud/editor.scss | 8 ++ .../src/video/edit-common-settings.js | 1 + packages/block-library/src/video/edit.js | 4 +- .../components/src/base-control/README.md | 7 +- .../components/src/base-control/index.tsx | 89 ++++++++++--------- .../global-styles/size-control/index.js | 8 +- .../push-changes-to-global-styles/index.js | 1 + .../create-template-part-modal/index.js | 1 + .../components/pattern-overrides-controls.js | 1 + 14 files changed, 128 insertions(+), 92 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index cb669fb4177206..6143d62c28bc07 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -290,6 +290,7 @@ module.exports = { ...restrictedSyntax, ...restrictedSyntaxComponents, ...[ + 'BaseControl', 'CheckboxControl', 'ComboboxControl', 'DimensionControl', diff --git a/packages/block-library/src/gallery/edit.js b/packages/block-library/src/gallery/edit.js index 1a7ce5fae04f8c..c73fe1977ce4cc 100644 --- a/packages/block-library/src/gallery/edit.js +++ b/packages/block-library/src/gallery/edit.js @@ -602,7 +602,10 @@ export default function GalleryEdit( props ) { /> ) } { Platform.isWeb && ! imageSizeOptions && hasImageIds && ( - <BaseControl className="gallery-image-sizes"> + <BaseControl + className="gallery-image-sizes" + __nextHasNoMarginBottom + > <BaseControl.VisualLabel> { __( 'Resolution' ) } </BaseControl.VisualLabel> diff --git a/packages/block-library/src/search/edit.js b/packages/block-library/src/search/edit.js index cfe7b29caf5de0..e2f3bb3999e42c 100644 --- a/packages/block-library/src/search/edit.js +++ b/packages/block-library/src/search/edit.js @@ -28,7 +28,7 @@ import { ToolbarButton, ResizableBox, PanelBody, - BaseControl, + __experimentalVStack as VStack, __experimentalUseCustomUnits as useCustomUnits, __experimentalUnitControl as UnitControl, } from '@wordpress/components'; @@ -408,12 +408,14 @@ export default function SearchEdit( { <InspectorControls> <PanelBody title={ __( 'Settings' ) }> - <BaseControl - label={ __( 'Width' ) } - id={ unitControlInputId } + <VStack + className="wp-block-search__inspector-controls" + spacing={ 4 } > <UnitControl - id={ unitControlInputId } + __next40pxDefaultSize + label={ __( 'Width' ) } + id={ unitControlInputId } // unused, kept for backwards compatibility min={ isPercentageUnit( widthUnit ) ? 0 : MIN_WIDTH } @@ -427,7 +429,6 @@ export default function SearchEdit( { parseInt( newWidth, 10 ) > 100 ? 100 : newWidth; - setAttributes( { width: parseInt( filteredWidth, 10 ), } ); @@ -445,9 +446,8 @@ export default function SearchEdit( { value={ `${ width }${ widthUnit }` } units={ units } /> - <ButtonGroup - className="wp-block-search__components-button-group" + className="wp-block-search__components-button-group" // unused, kept for backwards compatibility aria-label={ __( 'Percentage Width' ) } > { [ 25, 50, 75, 100 ].map( ( widthValue ) => { @@ -473,7 +473,7 @@ export default function SearchEdit( { ); } ) } </ButtonGroup> - </BaseControl> + </VStack> </PanelBody> </InspectorControls> </> diff --git a/packages/block-library/src/search/editor.scss b/packages/block-library/src/search/editor.scss index 35ccfc5e633fc2..ecc244d3341e1e 100644 --- a/packages/block-library/src/search/editor.scss +++ b/packages/block-library/src/search/editor.scss @@ -15,8 +15,11 @@ justify-content: center; text-align: center; } +} - &__components-button-group { - margin-top: 10px; +.wp-block-search__inspector-controls { + .components-base-control { + // Counteract the margin added by the block inspector. + margin-bottom: 0; } } diff --git a/packages/block-library/src/tag-cloud/edit.js b/packages/block-library/src/tag-cloud/edit.js index 8ced99271e4807..eeb568e7a89ef1 100644 --- a/packages/block-library/src/tag-cloud/edit.js +++ b/packages/block-library/src/tag-cloud/edit.js @@ -11,8 +11,8 @@ import { __experimentalUnitControl as UnitControl, __experimentalUseCustomUnits as useCustomUnits, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, + __experimentalVStack as VStack, Disabled, - BaseControl, } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; @@ -119,17 +119,20 @@ function TagCloudEdit( { attributes, setAttributes } ) { const inspectorControls = ( <InspectorControls> <PanelBody title={ __( 'Settings' ) }> - <SelectControl - __nextHasNoMarginBottom - __next40pxDefaultSize - label={ __( 'Taxonomy' ) } - options={ getTaxonomyOptions() } - value={ taxonomy } - onChange={ ( selectedTaxonomy ) => - setAttributes( { taxonomy: selectedTaxonomy } ) - } - /> - <BaseControl> + <VStack + spacing={ 4 } + className="wp-block-tag-cloud__inspector-settings" + > + <SelectControl + __nextHasNoMarginBottom + __next40pxDefaultSize + label={ __( 'Taxonomy' ) } + options={ getTaxonomyOptions() } + value={ taxonomy } + onChange={ ( selectedTaxonomy ) => + setAttributes( { taxonomy: selectedTaxonomy } ) + } + /> <Flex gap={ 4 }> <FlexItem isBlock> <UnitControl @@ -164,27 +167,27 @@ function TagCloudEdit( { attributes, setAttributes } ) { /> </FlexItem> </Flex> - </BaseControl> - <RangeControl - __nextHasNoMarginBottom - __next40pxDefaultSize - label={ __( 'Number of tags' ) } - value={ numberOfTags } - onChange={ ( value ) => - setAttributes( { numberOfTags: value } ) - } - min={ MIN_TAGS } - max={ MAX_TAGS } - required - /> - <ToggleControl - __nextHasNoMarginBottom - label={ __( 'Show tag counts' ) } - checked={ showTagCounts } - onChange={ () => - setAttributes( { showTagCounts: ! showTagCounts } ) - } - /> + <RangeControl + __nextHasNoMarginBottom + __next40pxDefaultSize + label={ __( 'Number of tags' ) } + value={ numberOfTags } + onChange={ ( value ) => + setAttributes( { numberOfTags: value } ) + } + min={ MIN_TAGS } + max={ MAX_TAGS } + required + /> + <ToggleControl + __nextHasNoMarginBottom + label={ __( 'Show tag counts' ) } + checked={ showTagCounts } + onChange={ () => + setAttributes( { showTagCounts: ! showTagCounts } ) + } + /> + </VStack> </PanelBody> </InspectorControls> ); diff --git a/packages/block-library/src/tag-cloud/editor.scss b/packages/block-library/src/tag-cloud/editor.scss index d00a450174f2fd..e85129e22f1aca 100644 --- a/packages/block-library/src/tag-cloud/editor.scss +++ b/packages/block-library/src/tag-cloud/editor.scss @@ -9,3 +9,11 @@ border: none; border-radius: inherit; } + +.wp-block-tag-cloud__inspector-settings { + .components-base-control, + .components-base-control:last-child { + // Cancel out extra margins added by block inspector + margin-bottom: 0; + } +} diff --git a/packages/block-library/src/video/edit-common-settings.js b/packages/block-library/src/video/edit-common-settings.js index 5ebf431ade3fc0..9394bfaf5c6145 100644 --- a/packages/block-library/src/video/edit-common-settings.js +++ b/packages/block-library/src/video/edit-common-settings.js @@ -83,6 +83,7 @@ const VideoSettings = ( { setAttributes, attributes } ) => { ) } /> <SelectControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Preload' ) } value={ preload } diff --git a/packages/block-library/src/video/edit.js b/packages/block-library/src/video/edit.js index 97a6e148d5d069..647b6b2cbea194 100644 --- a/packages/block-library/src/video/edit.js +++ b/packages/block-library/src/video/edit.js @@ -219,7 +219,7 @@ function VideoEdit( { attributes={ attributes } /> <MediaUploadCheck> - <BaseControl className="editor-video-poster-control"> + <div className="editor-video-poster-control"> <BaseControl.VisualLabel> { __( 'Poster image' ) } </BaseControl.VisualLabel> @@ -265,7 +265,7 @@ function VideoEdit( { { __( 'Remove' ) } </Button> ) } - </BaseControl> + </div> </MediaUploadCheck> </PanelBody> </InspectorControls> diff --git a/packages/components/src/base-control/README.md b/packages/components/src/base-control/README.md index dc3d8c0e29c8e0..d51629de6f7253 100644 --- a/packages/components/src/base-control/README.md +++ b/packages/components/src/base-control/README.md @@ -15,7 +15,7 @@ const MyCustomTextareaControl = ({ children, ...baseProps }) => ( const { baseControlProps, controlProps } = useBaseControlProps( baseProps ); return ( - <BaseControl { ...baseControlProps } __nextHasNoMarginBottom={ true }> + <BaseControl { ...baseControlProps } __nextHasNoMarginBottom> <textarea { ...controlProps }> { children } </textarea> @@ -92,7 +92,10 @@ It should only be used in cases where the children being rendered inside BaseCon import { BaseControl } from '@wordpress/components'; const MyBaseControl = () => ( - <BaseControl help="This button is already accessibly labeled."> + <BaseControl + __nextHasNoMarginBottom + help="This button is already accessibly labeled." + > <BaseControl.VisualLabel>Author</BaseControl.VisualLabel> <Button>Select an author</Button> </BaseControl> diff --git a/packages/components/src/base-control/index.tsx b/packages/components/src/base-control/index.tsx index 14ecce1bdd729d..77899b6480daed 100644 --- a/packages/components/src/base-control/index.tsx +++ b/packages/components/src/base-control/index.tsx @@ -26,29 +26,6 @@ import { contextConnectWithoutRef, useContextSystem } from '../context'; export { useBaseControlProps } from './hooks'; -/** - * `BaseControl` is a component used to generate labels and help text for components handling user inputs. - * - * ```jsx - * import { BaseControl, useBaseControlProps } from '@wordpress/components'; - * - * // Render a `BaseControl` for a textarea input - * const MyCustomTextareaControl = ({ children, ...baseProps }) => ( - * // `useBaseControlProps` is a convenience hook to get the props for the `BaseControl` - * // and the inner control itself. Namely, it takes care of generating a unique `id`, - * // properly associating it with the `label` and `help` elements. - * const { baseControlProps, controlProps } = useBaseControlProps( baseProps ); - * - * return ( - * <BaseControl { ...baseControlProps } __nextHasNoMarginBottom={ true }> - * <textarea { ...controlProps }> - * { children } - * </textarea> - * </BaseControl> - * ); - * ); - * ``` - */ const UnconnectedBaseControl = ( props: WordPressComponentProps< BaseControlProps, null > ) => { @@ -105,23 +82,6 @@ const UnconnectedBaseControl = ( ); }; -/** - * `BaseControl.VisualLabel` is used to render a purely visual label inside a `BaseControl` component. - * - * It should only be used in cases where the children being rendered inside `BaseControl` are already accessibly labeled, - * e.g., a button, but we want an additional visual label for that section equivalent to the labels `BaseControl` would - * otherwise use if the `label` prop was passed. - * - * @example - * import { BaseControl } from '@wordpress/components'; - * - * const MyBaseControl = () => ( - * <BaseControl help="This button is already accessibly labeled."> - * <BaseControl.VisualLabel>Author</BaseControl.VisualLabel> - * <Button>Select an author</Button> - * </BaseControl> - * ); - */ const UnforwardedVisualLabel = ( props: WordPressComponentProps< BaseControlVisualLabelProps, 'span' >, ref: ForwardedRef< any > @@ -141,9 +101,56 @@ const UnforwardedVisualLabel = ( export const VisualLabel = forwardRef( UnforwardedVisualLabel ); +/** + * `BaseControl` is a component used to generate labels and help text for components handling user inputs. + * + * ```jsx + * import { BaseControl, useBaseControlProps } from '@wordpress/components'; + * + * // Render a `BaseControl` for a textarea input + * const MyCustomTextareaControl = ({ children, ...baseProps }) => ( + * // `useBaseControlProps` is a convenience hook to get the props for the `BaseControl` + * // and the inner control itself. Namely, it takes care of generating a unique `id`, + * // properly associating it with the `label` and `help` elements. + * const { baseControlProps, controlProps } = useBaseControlProps( baseProps ); + * + * return ( + * <BaseControl { ...baseControlProps } __nextHasNoMarginBottom> + * <textarea { ...controlProps }> + * { children } + * </textarea> + * </BaseControl> + * ); + * ); + * ``` + */ export const BaseControl = Object.assign( contextConnectWithoutRef( UnconnectedBaseControl, 'BaseControl' ), - { VisualLabel } + + { + /** + * `BaseControl.VisualLabel` is used to render a purely visual label inside a `BaseControl` component. + * + * It should only be used in cases where the children being rendered inside `BaseControl` are already accessibly labeled, + * e.g., a button, but we want an additional visual label for that section equivalent to the labels `BaseControl` would + * otherwise use if the `label` prop was passed. + * + * ```jsx + * import { BaseControl } from '@wordpress/components'; + * + * const MyBaseControl = () => ( + * <BaseControl + * __nextHasNoMarginBottom + * help="This button is already accessibly labeled." + * > + * <BaseControl.VisualLabel>Author</BaseControl.VisualLabel> + * <Button>Select an author</Button> + * </BaseControl> + * ); + * ``` + */ + VisualLabel, + } ); export default BaseControl; diff --git a/packages/edit-site/src/components/global-styles/size-control/index.js b/packages/edit-site/src/components/global-styles/size-control/index.js index a7e7bd6127a5fb..28fa64c643cbbd 100644 --- a/packages/edit-site/src/components/global-styles/size-control/index.js +++ b/packages/edit-site/src/components/global-styles/size-control/index.js @@ -20,7 +20,11 @@ import { const DEFAULT_UNITS = [ 'px', 'em', 'rem', 'vw', 'vh' ]; -function SizeControl( props ) { +function SizeControl( { + // Do not allow manipulation of margin bottom + __nextHasNoMarginBottom, + ...props +} ) { const { baseControlProps } = useBaseControlProps( props ); const { value, onChange, fallbackValue, disabled } = props; @@ -45,7 +49,7 @@ function SizeControl( props ) { }; return ( - <BaseControl { ...baseControlProps }> + <BaseControl { ...baseControlProps } __nextHasNoMarginBottom> <Flex> <FlexItem isBlock> <UnitControl diff --git a/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js b/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js index c79ba67a1a7d74..49613c8b4c2822 100644 --- a/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js +++ b/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js @@ -323,6 +323,7 @@ function PushChangesToGlobalStylesControl( { return ( <BaseControl + __nextHasNoMarginBottom className="edit-site-push-changes-to-global-styles-control" help={ sprintf( // translators: %s: Title of the block e.g. 'Heading'. diff --git a/packages/editor/src/components/create-template-part-modal/index.js b/packages/editor/src/components/create-template-part-modal/index.js index a4b6c332cd800c..63e3830295c379 100644 --- a/packages/editor/src/components/create-template-part-modal/index.js +++ b/packages/editor/src/components/create-template-part-modal/index.js @@ -143,6 +143,7 @@ export function CreateTemplatePartModalContents( { required /> <BaseControl + __nextHasNoMarginBottom label={ __( 'Area' ) } id={ `editor-create-template-part-modal__area-selection-${ instanceId }` } className="editor-create-template-part-modal__area-base-control" diff --git a/packages/patterns/src/components/pattern-overrides-controls.js b/packages/patterns/src/components/pattern-overrides-controls.js index 3a5ff3e0674a6e..9bec88a93471eb 100644 --- a/packages/patterns/src/components/pattern-overrides-controls.js +++ b/packages/patterns/src/components/pattern-overrides-controls.js @@ -92,6 +92,7 @@ function PatternOverridesControls( { <> <InspectorControls group="advanced"> <BaseControl + __nextHasNoMarginBottom id={ controlId } label={ __( 'Overrides' ) } help={ helpText } From d34ddd43e227b4421cf13b0c001a21db4e0264cf Mon Sep 17 00:00:00 2001 From: Jan Pfeil <jan.pfeil@rypox.net> Date: Mon, 12 Aug 2024 19:34:49 +0200 Subject: [PATCH 0356/1908] fix typo in block-filters.md (#64452) https://github.com/WordPress/gutenberg/pull/64447#pullrequestreview-2233534636 --- docs/reference-guides/filters/block-filters.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference-guides/filters/block-filters.md b/docs/reference-guides/filters/block-filters.md index c70bb356a445a8..637cecadf1402b 100644 --- a/docs/reference-guides/filters/block-filters.md +++ b/docs/reference-guides/filters/block-filters.md @@ -139,7 +139,7 @@ The following PHP filters are available to change the output of a block on the f ### `render_block` -Filters the font-end content of any block. This filter has no impact on the behavior of blocks in the Editor. +Filters the front-end content of any block. This filter has no impact on the behavior of blocks in the Editor. The callback function for this filter receives three parameters: @@ -172,7 +172,7 @@ add_filter( 'render_block', 'example_add_custom_class_to_paragraph_block', 10, 2 ### `render_block_{namespace/block}` -Filters the font-end content of the defined block. This is just a simpler form of `render_block` when you only need to modify a specific block type. +Filters the front-end content of the defined block. This is just a simpler form of `render_block` when you only need to modify a specific block type. The callback function for this filter receives three parameters: From 47138724bf9e6abc67f448e3403428d431f2a1b9 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:33:25 +0900 Subject: [PATCH 0357/1908] In-between Inserter: Show inserter when it doesn't conflict with block toolbar (#64229) Unlinked contributors: digitalex11. Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: hanneslsm <hanneslsm@git.wordpress.org> --- .../block-list/use-in-between-inserter.js | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 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 74151fb3b070ba..bb307816fd1501 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 @@ -25,6 +25,7 @@ export function useInBetweenInserter() { getBlockIndex, isMultiSelecting, getSelectedBlockClientIds, + getSettings, getTemplateLock, __unstableIsWithinBlockOverlay, getBlockEditingMode, @@ -88,9 +89,11 @@ export function useInBetweenInserter() { return; } + const blockListSettings = getBlockListSettings( rootClientId ); const orientation = - getBlockListSettings( rootClientId )?.orientation || - 'vertical'; + blockListSettings?.orientation || 'vertical'; + const captureToolbars = + !! blockListSettings?.__experimentalCaptureToolbars; const offsetTop = event.clientY; const offsetLeft = event.clientX; @@ -135,9 +138,18 @@ 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 ) ) { + // Don't show the inserter if the following conditions are met, + // as it conflicts with the block toolbar: + // 1. when hovering above or inside selected block(s) + // 2. when the orientation is vertical + // 3. when the __experimentalCaptureToolbars is not enabled + // 4. when the Top Toolbar is not disabled + if ( + getSelectedBlockClientIds().includes( clientId ) && + orientation === 'vertical' && + ! captureToolbars && + ! getSettings().hasFixedToolbar + ) { return; } const elementRect = element.getBoundingClientRect(); From 344d61e5df74411283014bcbb5dbbed0b54f000a Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 13 Aug 2024 08:48:19 +0400 Subject: [PATCH 0358/1908] Block Editor: Use hooks instead of HoC in 'BlockModeToggle' (#64460) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../block-settings-menu/block-mode-toggle.js | 59 +++++++++---------- .../test/block-mode-toggle.js | 49 +++++++-------- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/packages/block-editor/src/components/block-settings-menu/block-mode-toggle.js b/packages/block-editor/src/components/block-settings-menu/block-mode-toggle.js index 6810a21581f12e..7ca294a2894158 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-mode-toggle.js +++ b/packages/block-editor/src/components/block-settings-menu/block-mode-toggle.js @@ -4,8 +4,7 @@ import { __ } from '@wordpress/i18n'; import { MenuItem } from '@wordpress/components'; import { getBlockType, hasBlockSupport } from '@wordpress/blocks'; -import { withSelect, withDispatch } from '@wordpress/data'; -import { compose } from '@wordpress/compose'; +import { useDispatch, useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -14,13 +13,23 @@ import { store as blockEditorStore } from '../../store'; const noop = () => {}; -export function BlockModeToggle( { - blockType, - mode, - onToggleMode, - small = false, - isCodeEditingEnabled = true, -} ) { +export default function BlockModeToggle( { clientId, onToggle = noop } ) { + const { blockType, mode, isCodeEditingEnabled } = useSelect( + ( select ) => { + const { getBlock, getBlockMode, getSettings } = + select( blockEditorStore ); + const block = getBlock( clientId ); + + return { + mode: getBlockMode( clientId ), + blockType: block ? getBlockType( block.name ) : null, + isCodeEditingEnabled: getSettings().codeEditingEnabled, + }; + }, + [ clientId ] + ); + const { toggleBlockMode } = useDispatch( blockEditorStore ); + if ( ! blockType || ! hasBlockSupport( blockType, 'html', true ) || @@ -32,26 +41,14 @@ export function BlockModeToggle( { const label = mode === 'visual' ? __( 'Edit as HTML' ) : __( 'Edit visually' ); - return <MenuItem onClick={ onToggleMode }>{ ! small && label }</MenuItem>; + return ( + <MenuItem + onClick={ () => { + toggleBlockMode( clientId ); + onToggle(); + } } + > + { label } + </MenuItem> + ); } - -export default compose( [ - withSelect( ( select, { clientId } ) => { - const { getBlock, getBlockMode, getSettings } = - select( blockEditorStore ); - const block = getBlock( clientId ); - const isCodeEditingEnabled = getSettings().codeEditingEnabled; - - return { - mode: getBlockMode( clientId ), - blockType: block ? getBlockType( block.name ) : null, - isCodeEditingEnabled, - }; - } ), - withDispatch( ( dispatch, { onToggle = noop, clientId } ) => ( { - onToggleMode() { - dispatch( blockEditorStore ).toggleBlockMode( clientId ); - onToggle(); - }, - } ) ), -] )( BlockModeToggle ); diff --git a/packages/block-editor/src/components/block-settings-menu/test/block-mode-toggle.js b/packages/block-editor/src/components/block-settings-menu/test/block-mode-toggle.js index c297bad15f29ea..67d88125e3429c 100644 --- a/packages/block-editor/src/components/block-settings-menu/test/block-mode-toggle.js +++ b/packages/block-editor/src/components/block-settings-menu/test/block-mode-toggle.js @@ -3,16 +3,32 @@ */ import { render, screen } from '@testing-library/react'; +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; + /** * Internal dependencies */ -import { BlockModeToggle } from '../block-mode-toggle'; +import BlockModeToggle from '../block-mode-toggle'; + +jest.mock( '@wordpress/data/src/components/use-select', () => jest.fn() ); + +function setupUseSelectMock( mode, blockType, codeEditingEnabled = true ) { + useSelect.mockImplementation( () => { + return { + mode, + blockType, + isCodeEditingEnabled: codeEditingEnabled, + }; + } ); +} describe( 'BlockModeToggle', () => { it( "should not render the HTML mode button if the block doesn't support it", () => { - render( - <BlockModeToggle blockType={ { supports: { html: false } } } /> - ); + setupUseSelectMock( undefined, { supports: { html: false } } ); + render( <BlockModeToggle /> ); expect( screen.queryByRole( 'menuitem', { name: 'Edit as HTML' } ) @@ -20,12 +36,8 @@ describe( 'BlockModeToggle', () => { } ); it( 'should render the HTML mode button', () => { - render( - <BlockModeToggle - blockType={ { supports: { html: true } } } - mode="visual" - /> - ); + setupUseSelectMock( 'visual', { supports: { html: true } } ); + render( <BlockModeToggle /> ); expect( screen.getByRole( 'menuitem', { name: 'Edit as HTML' } ) @@ -33,12 +45,8 @@ describe( 'BlockModeToggle', () => { } ); it( 'should render the Visual mode button', () => { - render( - <BlockModeToggle - blockType={ { supports: { html: true } } } - mode="html" - /> - ); + setupUseSelectMock( 'html', { supports: { html: true } } ); + render( <BlockModeToggle /> ); expect( screen.getByRole( 'menuitem', { name: 'Edit visually' } ) @@ -46,13 +54,8 @@ describe( 'BlockModeToggle', () => { } ); it( 'should not render the Visual mode button if code editing is disabled', () => { - render( - <BlockModeToggle - blockType={ { supports: { html: true } } } - mode="html" - isCodeEditingEnabled={ false } - /> - ); + setupUseSelectMock( 'html', { supports: { html: true } }, false ); + render( <BlockModeToggle /> ); expect( screen.queryByRole( 'menuitem', { name: 'Edit visually' } ) From 6445ff13273b7bdbf5315c1394b5aeda8011e47c Mon Sep 17 00:00:00 2001 From: Robert Lee <rslee1247@gmail.com> Date: Mon, 12 Aug 2024 22:46:36 -0700 Subject: [PATCH 0359/1908] WPCompleter: Restrict block list to allowed blocks only (#64413) Unlinked contributors: ssang. Co-authored-by: talldan <talldanwp@git.wordpress.org> --- packages/block-editor/src/autocompleters/block.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/autocompleters/block.js b/packages/block-editor/src/autocompleters/block.js index bc06c9de5aaaff..859ae11036c82a 100644 --- a/packages/block-editor/src/autocompleters/block.js +++ b/packages/block-editor/src/autocompleters/block.js @@ -60,7 +60,8 @@ function createBlockCompleter() { }, [] ); const [ items, categories, collections ] = useBlockTypesState( rootClientId, - noop + noop, + true ); const filteredItems = useMemo( () => { From 476c78b36e0ac1af0f1cbec75507a6b288c4df29 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Tue, 13 Aug 2024 14:15:23 +0800 Subject: [PATCH 0360/1908] Fix bumped specificity for layout styles in non-iframed editor (#64076) * Fix too specific layout styles in non-iframed editor * Ensure first/last child rules take precedence * Adjust selectors so that `> :first-child`/`> :last-child` still has 0,2,0 specificity to override theme.json spacing * Update tests * Update client side layout selectors to match theme json * Add backport changelog ---- Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- backport-changelog/6.6/7145.md | 3 +++ lib/class-wp-theme-json-gutenberg.php | 2 +- .../global-styles/test/use-global-styles-output.js | 6 +++--- .../global-styles/use-global-styles-output.js | 4 ++-- phpunit/class-wp-theme-json-test.php | 11 +++++------ 5 files changed, 14 insertions(+), 12 deletions(-) create mode 100644 backport-changelog/6.6/7145.md diff --git a/backport-changelog/6.6/7145.md b/backport-changelog/6.6/7145.md new file mode 100644 index 00000000000000..386f765cb22fa8 --- /dev/null +++ b/backport-changelog/6.6/7145.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7145 + +* https://github.com/WordPress/gutenberg/pull/64076 diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 7558438dcbe745..20ea31090407b4 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -1744,7 +1744,7 @@ protected function get_layout_styles( $block_metadata, $types = array() ) { $spacing_rule['selector'] ); } else { - $format = static::ROOT_BLOCK_SELECTOR === $selector ? '.%2$s %3$s' : '%1$s-%2$s %3$s'; + $format = static::ROOT_BLOCK_SELECTOR === $selector ? ':root :where(.%2$s)%3$s' : ':root :where(%1$s-%2$s)%3$s'; $layout_selector = sprintf( $format, $selector, diff --git a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js index e2530fdb85f812..1b061f6921f2c2 100644 --- a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js @@ -763,7 +763,7 @@ describe( 'global styles renderer', () => { } ); expect( layoutStyles ).toEqual( - '.is-layout-flow > * { margin-block-start: 0; margin-block-end: 0; }.is-layout-flow > * + * { margin-block-start: 0.5em; margin-block-end: 0; }.is-layout-flex { gap: 0.5em; }:root { --wp--style--block-gap: 0.5em; }.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > * { margin: 0; }' + ':root :where(.is-layout-flow) > * { margin-block-start: 0; margin-block-end: 0; }:root :where(.is-layout-flow) > * + * { margin-block-start: 0.5em; margin-block-end: 0; }:root :where(.is-layout-flex) { gap: 0.5em; }:root { --wp--style--block-gap: 0.5em; }.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > * { margin: 0; }' ); } ); @@ -780,7 +780,7 @@ describe( 'global styles renderer', () => { } ); expect( layoutStyles ).toEqual( - '.is-layout-flow > * { margin-block-start: 0; margin-block-end: 0; }.is-layout-flow > * + * { margin-block-start: 12px; margin-block-end: 0; }.is-layout-flex { gap: 12px; }:root { --wp--style--block-gap: 12px; }.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > * { margin: 0; }' + ':root :where(.is-layout-flow) > * { margin-block-start: 0; margin-block-end: 0; }:root :where(.is-layout-flow) > * + * { margin-block-start: 12px; margin-block-end: 0; }:root :where(.is-layout-flex) { gap: 12px; }:root { --wp--style--block-gap: 12px; }.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > * { margin: 0; }' ); } ); @@ -797,7 +797,7 @@ describe( 'global styles renderer', () => { } ); expect( layoutStyles ).toEqual( - '.wp-block-group-is-layout-flow > * { margin-block-start: 0; margin-block-end: 0; }.wp-block-group-is-layout-flow > * + * { margin-block-start: 12px; margin-block-end: 0; }.wp-block-group-is-layout-flex { gap: 12px; }' + ':root :where(.wp-block-group-is-layout-flow) > * { margin-block-start: 0; margin-block-end: 0; }:root :where(.wp-block-group-is-layout-flow) > * + * { margin-block-start: 12px; margin-block-end: 0; }:root :where(.wp-block-group-is-layout-flex) { gap: 12px; }' ); } ); diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 9190733d5b6607..c1449d6d8b298f 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -538,10 +538,10 @@ export function getLayoutStyles( { } else { combinedSelector = selector === ROOT_BLOCK_SELECTOR - ? `.${ className }${ + ? `:root :where(.${ className })${ spacingStyle?.selector || '' }` - : `${ selector }-${ className }${ + : `:root :where(${ selector }-${ className })${ spacingStyle?.selector || '' }`; } diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index d366e0df44c4a2..3f11dd97a6688f 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -714,7 +714,7 @@ public function test_get_stylesheet_renders_enabled_protected_properties() { ) ); - $expected = ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1em; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1em; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-flex {gap: 1em;}.is-layout-grid {gap: 1em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; + $expected = ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1em; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1em; }:root :where(.is-layout-flow) > :first-child{margin-block-start: 0;}:root :where(.is-layout-flow) > :last-child{margin-block-end: 0;}:root :where(.is-layout-flow) > *{margin-block-start: 1em;margin-block-end: 0;}:root :where(.is-layout-constrained) > :first-child{margin-block-start: 0;}:root :where(.is-layout-constrained) > :last-child{margin-block-end: 0;}:root :where(.is-layout-constrained) > *{margin-block-start: 1em;margin-block-end: 0;}:root :where(.is-layout-flex){gap: 1em;}:root :where(.is-layout-grid){gap: 1em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; $this->assertSameCSS( $expected, $theme_json->get_stylesheet() ); $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); } @@ -1131,7 +1131,7 @@ public function test_get_stylesheet_generates_layout_styles() { // Results also include root site blocks styles. $this->assertSameCSS( - ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1em; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1em; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-flex {gap: 1em;}.is-layout-grid {gap: 1em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}', + ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1em; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1em; }:root :where(.is-layout-flow) > :first-child{margin-block-start: 0;}:root :where(.is-layout-flow) > :last-child{margin-block-end: 0;}:root :where(.is-layout-flow) > *{margin-block-start: 1em;margin-block-end: 0;}:root :where(.is-layout-constrained) > :first-child{margin-block-start: 0;}:root :where(.is-layout-constrained) > :last-child{margin-block-end: 0;}:root :where(.is-layout-constrained) > *{margin-block-start: 1em;margin-block-end: 0;}:root :where(.is-layout-flex){gap: 1em;}:root :where(.is-layout-grid){gap: 1em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}', $theme_json->get_stylesheet( array( 'styles' ) ) ); } @@ -1160,7 +1160,7 @@ public function test_get_stylesheet_generates_layout_styles_with_spacing_presets // Results also include root site blocks styles. $this->assertSameCSS( - ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: var(--wp--preset--spacing--60); margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: var(--wp--preset--spacing--60); }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}.is-layout-flex {gap: var(--wp--preset--spacing--60);}.is-layout-grid {gap: var(--wp--preset--spacing--60);}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}', + ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: var(--wp--preset--spacing--60); margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: var(--wp--preset--spacing--60); }:root :where(.is-layout-flow) > :first-child{margin-block-start: 0;}:root :where(.is-layout-flow) > :last-child{margin-block-end: 0;}:root :where(.is-layout-flow) > *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}:root :where(.is-layout-constrained) > :first-child{margin-block-start: 0;}:root :where(.is-layout-constrained) > :last-child{margin-block-end: 0;}:root :where(.is-layout-constrained) > *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}:root :where(.is-layout-flex){gap: var(--wp--preset--spacing--60);}:root :where(.is-layout-grid){gap: var(--wp--preset--spacing--60);}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}', $theme_json->get_stylesheet( array( 'styles' ) ) ); } @@ -1284,8 +1284,7 @@ public function test_get_stylesheet_generates_valid_block_gap_values_and_skips_n ); $this->assertSameCSS( - ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1rem; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1rem; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1rem;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1rem;margin-block-end: 0;}.is-layout-flex {gap: 1rem;}.is-layout-grid {gap: 1rem;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}' . - ':root :where(.wp-block-post-content){color: gray;}.wp-block-social-links-is-layout-flow > :first-child{margin-block-start: 0;}.wp-block-social-links-is-layout-flow > :last-child{margin-block-end: 0;}.wp-block-social-links-is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-social-links-is-layout-constrained > :first-child{margin-block-start: 0;}.wp-block-social-links-is-layout-constrained > :last-child{margin-block-end: 0;}.wp-block-social-links-is-layout-constrained > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-social-links-is-layout-flex {gap: 0;}.wp-block-social-links-is-layout-grid {gap: 0;}.wp-block-buttons-is-layout-flow > :first-child{margin-block-start: 0;}.wp-block-buttons-is-layout-flow > :last-child{margin-block-end: 0;}.wp-block-buttons-is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-buttons-is-layout-constrained > :first-child{margin-block-start: 0;}.wp-block-buttons-is-layout-constrained > :last-child{margin-block-end: 0;}.wp-block-buttons-is-layout-constrained > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-buttons-is-layout-flex {gap: 0;}.wp-block-buttons-is-layout-grid {gap: 0;}', + ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1rem; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1rem; }:root :where(.is-layout-flow) > :first-child{margin-block-start: 0;}:root :where(.is-layout-flow) > :last-child{margin-block-end: 0;}:root :where(.is-layout-flow) > *{margin-block-start: 1rem;margin-block-end: 0;}:root :where(.is-layout-constrained) > :first-child{margin-block-start: 0;}:root :where(.is-layout-constrained) > :last-child{margin-block-end: 0;}:root :where(.is-layout-constrained) > *{margin-block-start: 1rem;margin-block-end: 0;}:root :where(.is-layout-flex){gap: 1rem;}:root :where(.is-layout-grid){gap: 1rem;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:root :where(.wp-block-post-content){color: gray;}:root :where(.wp-block-social-links-is-layout-flow) > :first-child{margin-block-start: 0;}:root :where(.wp-block-social-links-is-layout-flow) > :last-child{margin-block-end: 0;}:root :where(.wp-block-social-links-is-layout-flow) > *{margin-block-start: 0;margin-block-end: 0;}:root :where(.wp-block-social-links-is-layout-constrained) > :first-child{margin-block-start: 0;}:root :where(.wp-block-social-links-is-layout-constrained) > :last-child{margin-block-end: 0;}:root :where(.wp-block-social-links-is-layout-constrained) > *{margin-block-start: 0;margin-block-end: 0;}:root :where(.wp-block-social-links-is-layout-flex){gap: 0;}:root :where(.wp-block-social-links-is-layout-grid){gap: 0;}:root :where(.wp-block-buttons-is-layout-flow) > :first-child{margin-block-start: 0;}:root :where(.wp-block-buttons-is-layout-flow) > :last-child{margin-block-end: 0;}:root :where(.wp-block-buttons-is-layout-flow) > *{margin-block-start: 0;margin-block-end: 0;}:root :where(.wp-block-buttons-is-layout-constrained) > :first-child{margin-block-start: 0;}:root :where(.wp-block-buttons-is-layout-constrained) > :last-child{margin-block-end: 0;}:root :where(.wp-block-buttons-is-layout-constrained) > *{margin-block-start: 0;margin-block-end: 0;}:root :where(.wp-block-buttons-is-layout-flex){gap: 0;}:root :where(.wp-block-buttons-is-layout-grid){gap: 0;}', $theme_json->get_stylesheet() ); } @@ -3690,7 +3689,7 @@ public function test_get_styles_with_appearance_tools() { 'selector' => 'body', ); - $expected = ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: ; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: ; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1;margin-block-end: 0;}.is-layout-flex {gap: 1;}.is-layout-grid {gap: 1;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; + $expected = ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: ; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: ; }:root :where(.is-layout-flow) > :first-child{margin-block-start: 0;}:root :where(.is-layout-flow) > :last-child{margin-block-end: 0;}:root :where(.is-layout-flow) > *{margin-block-start: 1;margin-block-end: 0;}:root :where(.is-layout-constrained) > :first-child{margin-block-start: 0;}:root :where(.is-layout-constrained) > :last-child{margin-block-end: 0;}:root :where(.is-layout-constrained) > *{margin-block-start: 1;margin-block-end: 0;}:root :where(.is-layout-flex){gap: 1;}:root :where(.is-layout-grid){gap: 1;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; $this->assertSameCSS( $expected, $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ) ); } From 33093652ea76c4463e78252bb53f2f331a81610c Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Tue, 13 Aug 2024 08:29:48 +0100 Subject: [PATCH 0361/1908] Focus pattern inserter search when activating zoom out inserter (#64396) * Add new search focus option for inserter panel * Try focusing when inserter clicked in Zoom Out * Store search input ref in block editor settings * Remove legacy selector * Remove more legacy code * Move all ref selectors to block editor * Update packages/editor/src/components/inserter-sidebar/index.js --------- Co-authored-by: Ben Dwyer <ben@scruffian.com> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> --- .../block-tools/zoom-out-mode-inserters.js | 8 ++++- .../src/components/inserter/library.js | 2 ++ .../src/components/inserter/menu.js | 34 ++++++++++++------- .../src/store/private-selectors.js | 4 +++ packages/block-editor/src/store/reducer.js | 5 +++ 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js index bb044f9479c024..6f986ce90dc3bd 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js @@ -23,6 +23,7 @@ function ZoomOutModeInserters() { sectionRootClientId, selectedBlockClientId, hoveredBlockClientId, + inserterSearchInputRef, } = useSelect( ( select ) => { const { getSettings, @@ -32,8 +33,11 @@ function ZoomOutModeInserters() { getSelectedBlockClientId, getHoveredBlockClientId, isBlockInsertionPointVisible, - } = select( blockEditorStore ); + getInserterSearchInputRef, + } = unlock( select( blockEditorStore ) ); + const { sectionRootClientId: root } = unlock( getSettings() ); + return { hasSelection: !! getSelectionStart().clientId, blockInsertionPoint: getBlockInsertionPoint(), @@ -44,6 +48,7 @@ function ZoomOutModeInserters() { getSettings().__experimentalSetIsInserterOpened, selectedBlockClientId: getSelectedBlockClientId(), hoveredBlockClientId: getHoveredBlockClientId(), + inserterSearchInputRef: getInserterSearchInputRef(), }; }, [] ); @@ -110,6 +115,7 @@ function ZoomOutModeInserters() { showInsertionPoint( sectionRootClientId, index, { operation: 'insert', } ); + inserterSearchInputRef?.current?.focus(); } } /> ) } diff --git a/packages/block-editor/src/components/inserter/library.js b/packages/block-editor/src/components/inserter/library.js index 4e10a051996a9f..fe14d48bb4016b 100644 --- a/packages/block-editor/src/components/inserter/library.js +++ b/packages/block-editor/src/components/inserter/library.js @@ -27,6 +27,7 @@ function InserterLibrary( onSelect = noop, shouldFocusBlock = false, onClose, + __experimentalSearchInputRef, }, ref ) { @@ -58,6 +59,7 @@ function InserterLibrary( shouldFocusBlock={ shouldFocusBlock } ref={ ref } onClose={ onClose } + __experimentalSearchInputRef={ __experimentalSearchInputRef } /> ); } diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index 52e4e3062e9024..c5f41f9e3bf0a0 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -33,6 +33,7 @@ import useInsertionPoint from './hooks/use-insertion-point'; import { store as blockEditorStore } from '../../store'; import TabbedSidebar from '../tabbed-sidebar'; import { useZoomOut } from '../../hooks/use-zoom-out'; +import { unlock } from '../../lock-unlock'; const NOOP = () => {}; function InserterMenu( @@ -53,11 +54,16 @@ function InserterMenu( }, ref ) { - const isZoomOutMode = useSelect( - ( select ) => - select( blockEditorStore ).__unstableGetEditorMode() === 'zoom-out', - [] - ); + const { isZoomOutMode, inserterSearchInputRef } = useSelect( ( select ) => { + const { __unstableGetEditorMode, getInserterSearchInputRef } = unlock( + select( blockEditorStore ) + ); + return { + isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', + inserterSearchInputRef: getInserterSearchInputRef(), + }; + }, [] ); + const [ filterValue, setFilterValue, delayedFilterValue ] = useDebouncedInput( __experimentalFilterValue ); const [ hoveredItem, setHoveredItem ] = useState( null ); @@ -104,7 +110,7 @@ function InserterMenu( } } ); }, - [ onInsertBlocks, onSelect, shouldFocusBlock ] + [ onInsertBlocks, onSelect, ref, shouldFocusBlock ] ); const onInsertPattern = useCallback( @@ -113,7 +119,7 @@ function InserterMenu( onInsertBlocks( blocks, { patternName } ); onSelect(); }, - [ onInsertBlocks, onSelect ] + [ onInsertBlocks, onSelect, onToggleInsertionPoint ] ); const onHover = useCallback( @@ -164,7 +170,9 @@ function InserterMenu( value={ filterValue } label={ __( 'Search for blocks and patterns' ) } placeholder={ __( 'Search' ) } + ref={ inserterSearchInputRef } /> + { !! delayedFilterValue && ( <InserterSearchResults filterValue={ delayedFilterValue } @@ -185,18 +193,18 @@ function InserterMenu( ); }, [ selectedTab, - hoveredItem, - setHoveredItem, - setFilterValue, filterValue, + inserterSearchInputRef, delayedFilterValue, onSelect, onHover, - shouldFocusBlock, - clientId, rootClientId, - __experimentalInsertionIndex, + clientId, isAppender, + __experimentalInsertionIndex, + shouldFocusBlock, + hoveredItem, + setFilterValue, ] ); const blocksTab = useMemo( () => { diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index c534c65b8defe7..dcd315a0ae2804 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -511,3 +511,7 @@ export function getTemporarilyEditingAsBlocks( state ) { export function getTemporarilyEditingFocusModeToRevert( state ) { return state.temporarilyEditingFocusModeRevert; } + +export function getInserterSearchInputRef( state ) { + return state.inserterSearchInputRef; +} diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 91d853a50a6a42..d9352670776371 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -2087,6 +2087,10 @@ export function hoveredBlockClientId( state = false, action ) { return state; } +export function inserterSearchInputRef( state = { current: null } ) { + return state; +} + const combinedReducers = combineReducers( { blocks, isDragging, @@ -2120,6 +2124,7 @@ const combinedReducers = combineReducers( { openedBlockSettingsMenu, registeredInserterMediaCategories, hoveredBlockClientId, + inserterSearchInputRef, } ); function withAutomaticChangeReset( reducer ) { From 27e441209db11f384e484f5a71453143c64c9b4a Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Tue, 13 Aug 2024 16:00:20 +0800 Subject: [PATCH 0362/1908] Update postcss-prefixwrap dependency to 1.51.0 to fix prefixing in `:where` selectors (#64458) * Update postcss-prefixwrap dependency to 1.51.0 to fix prefixing in :where selectors * Add extra test for :where with a pseudo selector ---- Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: andreiglingeanu <andreiglingeanu@git.wordpress.org> --- package-lock.json | 31 ++++++------ packages/block-editor/package.json | 2 +- .../src/utils/test/transform-styles.js | 49 +++++++++++++++++++ 3 files changed, 66 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 66c32076d3b364..471d7b845d24f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41754,14 +41754,6 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, - "node_modules/postcss-prefixwrap": { - "version": "1.41.0", - "resolved": "https://registry.npmjs.org/postcss-prefixwrap/-/postcss-prefixwrap-1.41.0.tgz", - "integrity": "sha512-gmwwAEE+ci3/ZKjUZppTETINlh1QwihY8gCstInuS7ohk353KYItU4d64hvnUvO2GUy29hBGPHz4Ce+qJRi90A==", - "peerDependencies": { - "postcss": "*" - } - }, "node_modules/postcss-reduce-initial": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz", @@ -52237,7 +52229,7 @@ "fast-deep-equal": "^3.1.3", "memize": "^2.1.0", "postcss": "^8.4.21", - "postcss-prefixwrap": "^1.41.0", + "postcss-prefixwrap": "^1.51.0", "postcss-urlrebase": "^1.4.0", "react-autosize-textarea": "^7.1.0", "react-easy-crop": "^5.0.6", @@ -52252,6 +52244,15 @@ "react-dom": "^18.0.0" } }, + "packages/block-editor/node_modules/postcss-prefixwrap": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/postcss-prefixwrap/-/postcss-prefixwrap-1.51.0.tgz", + "integrity": "sha512-PuP4md5zFSY921dUcLShwSLv2YyyDec0dK9/puXl/lu7ZNvJ1U59+ZEFRMS67xwfNg5nIIlPXnAycPJlhA/Isw==", + "license": "MIT", + "peerDependencies": { + "postcss": "*" + } + }, "packages/block-editor/node_modules/postcss-urlrebase": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.4.0.tgz", @@ -67255,13 +67256,18 @@ "fast-deep-equal": "^3.1.3", "memize": "^2.1.0", "postcss": "^8.4.21", - "postcss-prefixwrap": "^1.41.0", + "postcss-prefixwrap": "^1.51.0", "postcss-urlrebase": "^1.4.0", "react-autosize-textarea": "^7.1.0", "react-easy-crop": "^5.0.6", "remove-accents": "^0.5.0" }, "dependencies": { + "postcss-prefixwrap": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/postcss-prefixwrap/-/postcss-prefixwrap-1.51.0.tgz", + "integrity": "sha512-PuP4md5zFSY921dUcLShwSLv2YyyDec0dK9/puXl/lu7ZNvJ1U59+ZEFRMS67xwfNg5nIIlPXnAycPJlhA/Isw==" + }, "postcss-urlrebase": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.4.0.tgz", @@ -87820,11 +87826,6 @@ } } }, - "postcss-prefixwrap": { - "version": "1.41.0", - "resolved": "https://registry.npmjs.org/postcss-prefixwrap/-/postcss-prefixwrap-1.41.0.tgz", - "integrity": "sha512-gmwwAEE+ci3/ZKjUZppTETINlh1QwihY8gCstInuS7ohk353KYItU4d64hvnUvO2GUy29hBGPHz4Ce+qJRi90A==" - }, "postcss-reduce-initial": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 8ccaee6f0a955c..02765376e314b6 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -73,7 +73,7 @@ "fast-deep-equal": "^3.1.3", "memize": "^2.1.0", "postcss": "^8.4.21", - "postcss-prefixwrap": "^1.41.0", + "postcss-prefixwrap": "^1.51.0", "postcss-urlrebase": "^1.4.0", "react-autosize-textarea": "^7.1.0", "react-easy-crop": "^5.0.6", diff --git a/packages/block-editor/src/utils/test/transform-styles.js b/packages/block-editor/src/utils/test/transform-styles.js index 8245ce62831078..b0c6ca48deb355 100644 --- a/packages/block-editor/src/utils/test/transform-styles.js +++ b/packages/block-editor/src/utils/test/transform-styles.js @@ -125,6 +125,21 @@ describe( 'transformStyles', () => { expect( output ).toMatchSnapshot(); } ); + it( `should not try to replace 'body' in the middle of a classname`, () => { + const prefix = '.my-namespace'; + const input = `.has-body-text { color: red; }`; + const output = transformStyles( + [ + { + css: input, + }, + ], + prefix + ); + + expect( output ).toEqual( [ `${ prefix } ${ input }` ] ); + } ); + it( 'should ignore keyframes', () => { const input = ` @keyframes edit-post__fade-in-animation { @@ -210,6 +225,40 @@ describe( 'transformStyles', () => { expect( output ).toMatchSnapshot(); } ); + + it( 'should not try to wrap items within `:where` selectors', () => { + const input = `:where(.wp-element-button:active, .wp-block-button__link:active) { color: blue; }`; + const prefix = '.my-namespace'; + const expected = [ `${ prefix } ${ input }` ]; + + const output = transformStyles( + [ + { + css: input, + }, + ], + prefix + ); + + expect( output ).toEqual( expected ); + } ); + + it( 'should not try to prefix pseudo elements on `:where` selectors', () => { + const input = `:where(.wp-element-button, .wp-block-button__link)::before { color: blue; }`; + const prefix = '.my-namespace'; + const expected = [ `${ prefix } ${ input }` ]; + + const output = transformStyles( + [ + { + css: input, + }, + ], + prefix + ); + + expect( output ).toEqual( expected ); + } ); } ); it( 'should not break with data urls', () => { From 926e7389a95701c3eba4702d4b4ef7f5d4325ffb Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 13 Aug 2024 10:25:34 +0200 Subject: [PATCH 0363/1908] DataViews Extensibility: Allow unregistering the duplicate post action (#64441) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- .../src/components/post-actions/actions.js | 219 +----------------- .../actions/duplicate-post.native.tsx | 3 + .../src/dataviews/actions/duplicate-post.tsx | 174 ++++++++++++++ .../src/dataviews/actions/reorder-page.tsx | 6 +- packages/editor/src/dataviews/fields/index.ts | 7 +- .../src/dataviews/store/private-actions.ts | 9 + packages/editor/src/dataviews/types.ts | 26 ++- 7 files changed, 213 insertions(+), 231 deletions(-) create mode 100644 packages/editor/src/dataviews/actions/duplicate-post.native.tsx create mode 100644 packages/editor/src/dataviews/actions/duplicate-post.tsx diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 0df73d1996deb5..627de5e8652e47 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -4,50 +4,15 @@ import { external } from '@wordpress/icons'; import { addQueryArgs } from '@wordpress/url'; import { useDispatch, useSelect } from '@wordpress/data'; -import { decodeEntities } from '@wordpress/html-entities'; import { store as coreStore } from '@wordpress/core-data'; -import { __, sprintf, _x } from '@wordpress/i18n'; -import { store as noticesStore } from '@wordpress/notices'; -import { useMemo, useState, useEffect } from '@wordpress/element'; -import { DataForm } from '@wordpress/dataviews'; -import { - Button, - __experimentalHStack as HStack, - __experimentalVStack as VStack, -} from '@wordpress/components'; +import { __, sprintf } from '@wordpress/i18n'; +import { useMemo, useEffect } from '@wordpress/element'; /** * Internal dependencies */ -import { - TEMPLATE_PART_POST_TYPE, - TEMPLATE_POST_TYPE, - PATTERN_POST_TYPE, -} from '../../store/constants'; import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; -import { getItemTitle } from '../../dataviews/actions/utils'; - -// TODO: this should be shared with other components (see post-fields in edit-site). -const fields = [ - { - type: 'text', - id: 'title', - label: __( 'Title' ), - placeholder: __( 'No title' ), - getValue: ( { item } ) => item.title, - }, - { - type: 'integer', - id: 'menu_order', - label: __( 'Order' ), - description: __( 'Determines the order of pages.' ), - }, -]; - -const formDuplicateAction = { - fields: [ 'title' ], -}; const viewPostAction = { id: 'view-post', @@ -100,172 +65,6 @@ const postRevisionsAction = { }, }; -const useDuplicatePostAction = ( postType ) => { - const userCanCreatePost = useSelect( - ( select ) => { - return select( coreStore ).canUser( 'create', { - kind: 'postType', - name: postType, - } ); - }, - [ postType ] - ); - return useMemo( - () => - userCanCreatePost && { - id: 'duplicate-post', - label: _x( 'Duplicate', 'action label' ), - isEligible( { status } ) { - return status !== 'trash'; - }, - RenderModal: ( { items, closeModal, onActionPerformed } ) => { - const [ item, setItem ] = useState( { - ...items[ 0 ], - title: sprintf( - /* translators: %s: Existing template title */ - __( '%s (Copy)' ), - getItemTitle( items[ 0 ] ) - ), - } ); - - const [ isCreatingPage, setIsCreatingPage ] = - useState( false ); - - const { saveEntityRecord } = useDispatch( coreStore ); - const { createSuccessNotice, createErrorNotice } = - useDispatch( noticesStore ); - - async function createPage( event ) { - event.preventDefault(); - - if ( isCreatingPage ) { - return; - } - - const newItemOject = { - status: 'draft', - title: item.title, - slug: item.title || __( 'No title' ), - comment_status: item.comment_status, - content: - typeof item.content === 'string' - ? item.content - : item.content.raw, - excerpt: item.excerpt.raw, - meta: item.meta, - parent: item.parent, - password: item.password, - template: item.template, - format: item.format, - featured_media: item.featured_media, - menu_order: item.menu_order, - ping_status: item.ping_status, - }; - const assignablePropertiesPrefix = 'wp:action-assign-'; - // Get all the properties that the current user is able to assign normally author, categories, tags, - // and custom taxonomies. - const assignableProperties = Object.keys( - item?._links || {} - ) - .filter( ( property ) => - property.startsWith( - assignablePropertiesPrefix - ) - ) - .map( ( property ) => - property.slice( - assignablePropertiesPrefix.length - ) - ); - assignableProperties.forEach( ( property ) => { - if ( item[ property ] ) { - newItemOject[ property ] = item[ property ]; - } - } ); - setIsCreatingPage( true ); - try { - const newItem = await saveEntityRecord( - 'postType', - item.type, - newItemOject, - { throwOnError: true } - ); - - createSuccessNotice( - sprintf( - // translators: %s: Title of the created template e.g: "Category". - __( '"%s" successfully created.' ), - decodeEntities( - newItem.title?.rendered || item.title - ) - ), - { - id: 'duplicate-post-action', - type: 'snackbar', - } - ); - - if ( onActionPerformed ) { - onActionPerformed( [ newItem ] ); - } - } catch ( error ) { - const errorMessage = - error.message && error.code !== 'unknown_error' - ? error.message - : __( - 'An error occurred while duplicating the page.' - ); - - createErrorNotice( errorMessage, { - type: 'snackbar', - } ); - } finally { - setIsCreatingPage( false ); - closeModal(); - } - } - - return ( - <form onSubmit={ createPage }> - <VStack spacing={ 3 }> - <DataForm - data={ item } - fields={ fields } - form={ formDuplicateAction } - onChange={ ( changes ) => - setItem( { - ...item, - ...changes, - } ) - } - /> - <HStack spacing={ 2 } justify="end"> - <Button - variant="tertiary" - onClick={ closeModal } - __next40pxDefaultSize - > - { __( 'Cancel' ) } - </Button> - <Button - variant="primary" - type="submit" - isBusy={ isCreatingPage } - aria-disabled={ isCreatingPage } - __next40pxDefaultSize - > - { _x( 'Duplicate', 'action label' ) } - </Button> - </HStack> - </VStack> - </form> - ); - }, - }, - [ userCanCreatePost ] - ); -}; - export function usePostActions( { postType, onActionPerformed, context } ) { const { defaultActions, postTypeObject } = useSelect( ( select ) => { @@ -284,12 +83,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { registerPostTypeActions( postType ); }, [ registerPostTypeActions, postType ] ); - const duplicatePostAction = useDuplicatePostAction( postType ); - const isTemplateOrTemplatePart = [ - TEMPLATE_POST_TYPE, - TEMPLATE_PART_POST_TYPE, - ].includes( postType ); - const isPattern = postType === PATTERN_POST_TYPE; const isLoaded = !! postTypeObject; const supportsRevisions = !! postTypeObject?.supports?.revisions; return useMemo( () => { @@ -300,11 +93,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { let actions = [ postTypeObject?.viewable && viewPostAction, supportsRevisions && postRevisionsAction, - globalThis.IS_GUTENBERG_PLUGIN - ? ! isTemplateOrTemplatePart && - ! isPattern && - duplicatePostAction - : false, ...defaultActions, ].filter( Boolean ); // Filter actions based on provided context. If not provided @@ -370,10 +158,7 @@ export function usePostActions( { postType, onActionPerformed, context } ) { return actions; }, [ defaultActions, - isTemplateOrTemplatePart, - isPattern, postTypeObject?.viewable, - duplicatePostAction, onActionPerformed, isLoaded, supportsRevisions, diff --git a/packages/editor/src/dataviews/actions/duplicate-post.native.tsx b/packages/editor/src/dataviews/actions/duplicate-post.native.tsx new file mode 100644 index 00000000000000..5468aa649abbd4 --- /dev/null +++ b/packages/editor/src/dataviews/actions/duplicate-post.native.tsx @@ -0,0 +1,3 @@ +const duplicatePost = undefined; + +export default duplicatePost; diff --git a/packages/editor/src/dataviews/actions/duplicate-post.tsx b/packages/editor/src/dataviews/actions/duplicate-post.tsx new file mode 100644 index 00000000000000..0979d30da39519 --- /dev/null +++ b/packages/editor/src/dataviews/actions/duplicate-post.tsx @@ -0,0 +1,174 @@ +/** + * WordPress dependencies + */ +import { useDispatch } from '@wordpress/data'; +import { decodeEntities } from '@wordpress/html-entities'; +import { store as coreStore } from '@wordpress/core-data'; +import { __, sprintf, _x } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; +import { useState } from '@wordpress/element'; +import { DataForm } from '@wordpress/dataviews'; +import { + Button, + __experimentalHStack as HStack, + __experimentalVStack as VStack, +} from '@wordpress/components'; +import type { Action } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import { getItemTitle } from '../../dataviews/actions/utils'; +import type { CoreDataError, BasePost } from '../types'; +import { titleField } from '../fields'; + +const fields = [ titleField ]; +const formDuplicateAction = { + fields: [ 'title' ], +}; + +const duplicatePost: Action< BasePost > = { + id: 'duplicate-post', + label: _x( 'Duplicate', 'action label' ), + isEligible( { status } ) { + return status !== 'trash'; + }, + RenderModal: ( { items, closeModal, onActionPerformed } ) => { + const [ item, setItem ] = useState< BasePost >( { + ...items[ 0 ], + title: sprintf( + /* translators: %s: Existing template title */ + __( '%s (Copy)' ), + getItemTitle( items[ 0 ] ) + ), + } ); + + const [ isCreatingPage, setIsCreatingPage ] = useState( false ); + const { saveEntityRecord } = useDispatch( coreStore ); + const { createSuccessNotice, createErrorNotice } = + useDispatch( noticesStore ); + + async function createPage( event: React.FormEvent ) { + event.preventDefault(); + + if ( isCreatingPage ) { + return; + } + + const newItemOject = { + status: 'draft', + title: item.title, + slug: item.title || __( 'No title' ), + comment_status: item.comment_status, + content: + typeof item.content === 'string' + ? item.content + : item.content.raw, + excerpt: + typeof item.excerpt === 'string' + ? item.excerpt + : item.excerpt?.raw, + meta: item.meta, + parent: item.parent, + password: item.password, + template: item.template, + format: item.format, + featured_media: item.featured_media, + menu_order: item.menu_order, + ping_status: item.ping_status, + }; + const assignablePropertiesPrefix = 'wp:action-assign-'; + // Get all the properties that the current user is able to assign normally author, categories, tags, + // and custom taxonomies. + const assignableProperties = Object.keys( item?._links || {} ) + .filter( ( property ) => + property.startsWith( assignablePropertiesPrefix ) + ) + .map( ( property ) => + property.slice( assignablePropertiesPrefix.length ) + ); + assignableProperties.forEach( ( property ) => { + if ( item.hasOwnProperty( property ) ) { + // @ts-ignore + newItemOject[ property ] = item[ property ]; + } + } ); + setIsCreatingPage( true ); + try { + const newItem = await saveEntityRecord( + 'postType', + item.type, + newItemOject, + { throwOnError: true } + ); + + createSuccessNotice( + sprintf( + // translators: %s: Title of the created template e.g: "Category". + __( '"%s" successfully created.' ), + decodeEntities( newItem.title?.rendered || item.title ) + ), + { + id: 'duplicate-post-action', + type: 'snackbar', + } + ); + + if ( onActionPerformed ) { + onActionPerformed( [ newItem ] ); + } + } catch ( error ) { + const typedError = error as CoreDataError; + const errorMessage = + typedError.message && typedError.code !== 'unknown_error' + ? typedError.message + : __( 'An error occurred while duplicating the page.' ); + + createErrorNotice( errorMessage, { + type: 'snackbar', + } ); + } finally { + setIsCreatingPage( false ); + closeModal?.(); + } + } + + return ( + <form onSubmit={ createPage }> + <VStack spacing={ 3 }> + <DataForm + data={ item } + fields={ fields } + form={ formDuplicateAction } + onChange={ ( changes ) => + setItem( ( prev ) => ( { + ...prev, + ...changes, + } ) ) + } + /> + <HStack spacing={ 2 } justify="end"> + <Button + variant="tertiary" + onClick={ closeModal } + __next40pxDefaultSize + > + { __( 'Cancel' ) } + </Button> + <Button + variant="primary" + type="submit" + isBusy={ isCreatingPage } + aria-disabled={ isCreatingPage } + __next40pxDefaultSize + > + { _x( 'Duplicate', 'action label' ) } + </Button> + </HStack> + </VStack> + </form> + ); + }, +}; + +export default duplicatePost; diff --git a/packages/editor/src/dataviews/actions/reorder-page.tsx b/packages/editor/src/dataviews/actions/reorder-page.tsx index 1b9524123e7c95..1820884d8d8c73 100644 --- a/packages/editor/src/dataviews/actions/reorder-page.tsx +++ b/packages/editor/src/dataviews/actions/reorder-page.tsx @@ -17,7 +17,7 @@ import type { Action, RenderModalProps } from '@wordpress/dataviews'; /** * Internal dependencies */ -import type { CoreDataError, PostWithPageAttributesSupport } from '../types'; +import type { CoreDataError, BasePost } from '../types'; import { orderField } from '../fields'; const fields = [ orderField ]; @@ -29,7 +29,7 @@ function ReorderModal( { items, closeModal, onActionPerformed, -}: RenderModalProps< PostWithPageAttributesSupport > ) { +}: RenderModalProps< BasePost > ) { const [ item, setItem ] = useState( items[ 0 ] ); const orderInput = item.menu_order; const { editEntityRecord, saveEditedEntityRecord } = @@ -113,7 +113,7 @@ function ReorderModal( { ); } -const reorderPage: Action< PostWithPageAttributesSupport > = { +const reorderPage: Action< BasePost > = { id: 'order-pages', label: __( 'Order' ), isEligible( { status } ) { diff --git a/packages/editor/src/dataviews/fields/index.ts b/packages/editor/src/dataviews/fields/index.ts index ea30d15dab600b..b215172eaf7f02 100644 --- a/packages/editor/src/dataviews/fields/index.ts +++ b/packages/editor/src/dataviews/fields/index.ts @@ -7,17 +7,18 @@ import type { Field } from '@wordpress/dataviews'; /** * Internal dependencies */ -import type { BasePost, PostWithPageAttributesSupport } from '../types'; +import type { BasePost } from '../types'; +import { getItemTitle } from '../actions/utils'; export const titleField: Field< BasePost > = { type: 'text', id: 'title', label: __( 'Title' ), placeholder: __( 'No title' ), - getValue: ( { item } ) => item.title, + getValue: ( { item } ) => getItemTitle( item ), }; -export const orderField: Field< PostWithPageAttributesSupport > = { +export const orderField: Field< BasePost > = { type: 'integer', id: 'menu_order', label: __( 'Order' ), diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 80449d1b7a0798..d5b299b012e364 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -21,6 +21,7 @@ import restorePost from '../actions/restore-post'; import type { PostType } from '../types'; import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; +import duplicatePost from '../actions/duplicate-post'; export function registerEntityAction< Item >( kind: string, @@ -87,6 +88,14 @@ export const registerPostTypeActions = .getCurrentTheme(); const actions = [ + // @ts-ignore + globalThis.IS_GUTENBERG_PLUGIN + ? ! [ 'wp_template', 'wp_block', 'wp_template_part' ].includes( + postTypeConfig.slug + ) && + canCreate && + duplicatePost + : undefined, postTypeConfig.slug === 'wp_template_part' && canCreate && currentTheme?.is_block_theme && diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts index 5750ab96eeae81..514953d6691290 100644 --- a/packages/editor/src/dataviews/types.ts +++ b/packages/editor/src/dataviews/types.ts @@ -7,7 +7,7 @@ type PostStatus = | 'auto-draft' | 'trash'; -export interface BasePost { +export interface CommonPost { status?: PostStatus; title: string | { rendered: string } | { raw: string }; content: string | { raw: string; rendered: string }; @@ -16,7 +16,21 @@ export interface BasePost { blocks?: Object[]; } -export interface Template extends BasePost { +export interface BasePost extends CommonPost { + comment_status?: 'open' | 'closed'; + excerpt?: string | { raw: string; rendered: string }; + meta?: Record< string, any >; + parent?: number; + password?: string; + template?: string; + format?: string; + featured_media?: number; + menu_order?: number; + ping_status?: 'open' | 'closed'; + _links?: Record< string, { href: string }[] >; +} + +export interface Template extends CommonPost { type: 'wp_template'; is_custom: boolean; source: string; @@ -24,7 +38,7 @@ export interface Template extends BasePost { id: string; } -export interface TemplatePart extends BasePost { +export interface TemplatePart extends CommonPost { type: 'wp_template_part'; source: string; has_theme_file: boolean; @@ -32,16 +46,12 @@ export interface TemplatePart extends BasePost { area: string; } -export interface Pattern extends BasePost { +export interface Pattern extends CommonPost { slug: string; title: { raw: string }; wp_pattern_sync_status: string; } -export interface PostWithPageAttributesSupport extends BasePost { - menu_order: number; -} - export type Post = Template | TemplatePart | Pattern | BasePost; export type PostWithPermissions = Post & { From f9268debccb0fb53bb7552dd5723cece5c1178a2 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 13 Aug 2024 11:00:12 +0200 Subject: [PATCH 0364/1908] `Composite`: export `useCompositeStore`, add more focus-related props (#64450) * Export useCompositeStore from package * Add `accessibleWhenDisabled` prop to `Composite.Item` * Add `focusable`, `disabled`, `accessibleWhenDisabled`, and `onFocusVisible` props to `Composite` * CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/composite/README.md | 67 +++++++++++++++++ packages/components/src/composite/index.tsx | 6 +- .../src/composite/stories/index.story.tsx | 71 ++++++++++++++++++- packages/components/src/composite/types.ts | 67 +++++++++++++++++ packages/components/src/index.ts | 2 +- 6 files changed, 210 insertions(+), 4 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 57ba69197cfa98..761e6604a127a2 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,7 @@ - `Composite`: add stable version of the component ([#63564](https://github.com/WordPress/gutenberg/pull/63564)). - `Composite`: add `Hover` and `Typeahead` subcomponents ([#64399](https://github.com/WordPress/gutenberg/pull/64399)). +- `Composite`: export `useCompositeStore, add focus-related props to `Composite`and`Composite.Item` subcomponents ([#64450](https://github.com/WordPress/gutenberg/pull/64450)). ### Enhancements diff --git a/packages/components/src/composite/README.md b/packages/components/src/composite/README.md index 7bd12d0cabfa0c..3670e31b01e9df 100644 --- a/packages/components/src/composite/README.md +++ b/packages/components/src/composite/README.md @@ -147,6 +147,55 @@ Allows the component to be rendered as a different HTML element or React compone - Required: no +##### `focusable`: `boolean` + +Makes the component a focusable element. When this element gains keyboard focus, it gets a `data-focus-visible` attribute and triggers the `onFocusVisible` prop. + +The component supports the `disabled` prop even for those elements not supporting the native `disabled` attribute. Disabled elements may be still accessible via keyboard by using the the `accessibleWhenDisabled` prop. + +Non-native focusable elements will lose their focusability entirely. However, native focusable elements will retain their inherent focusability. + +- Required: no + +##### `disabled`: `boolean` + +Determines if the element is disabled. This sets the `aria-disabled` attribute accordingly, enabling support for all elements, including those that don't support the native `disabled` attribute. + +This feature can be combined with the `accessibleWhenDisabled` prop to +make disabled elements still accessible via keyboard. + +**Note**: For this prop to work, the `focusable` prop must be set to +`true`, if it's not set by default. + +- Required: no +- Default: `false` + +##### `accessibleWhenDisabled`: `boolean` + +Indicates whether the element should be focusable even when it is +`disabled`. + +This is important when discoverability is a concern. For example: + +> A toolbar in an editor contains a set of special smart paste functions +> that are disabled when the clipboard is empty or when the function is not +> applicable to the current content of the clipboard. It could be helpful to +> keep the disabled buttons focusable if the ability to discover their +> functionality is primarily via their presence on the toolbar. + +Learn more on [Focusability of disabled +controls](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols). + +- Required: no + +##### `onFocusVisible`: `(event: SyntheticEvent<HTMLElement>) => void` + +Custom event handler invoked when the element gains focus through keyboard interaction or a key press occurs while the element is in focus. This is the programmatic equivalent of the `data-focus-visible` attribute. + +**Note**: For this prop to work, the `focusable` prop must be set to `true` if it's not set by default. + +- Required: no + ##### `children`: `React.ReactNode` The contents of the component. @@ -189,6 +238,24 @@ The contents of the component. Renders a composite item. +##### `accessibleWhenDisabled`: `boolean` + +Indicates whether the element should be focusable even when it is +`disabled`. + +This is important when discoverability is a concern. For example: + +> A toolbar in an editor contains a set of special smart paste functions +> that are disabled when the clipboard is empty or when the function is not +> applicable to the current content of the clipboard. It could be helpful to +> keep the disabled buttons focusable if the ability to discover their +> functionality is primarily via their presence on the toolbar. + +Learn more on [Focusability of disabled +controls](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols). + +- Required: no + ##### `render`: `RenderProp<React.HTMLAttributes<any> & { ref?: React.Ref<any> | undefined; }> | React.ReactElement<any, string | React.JSXElementConstructor<any>>` Allows the component to be rendered as a different HTML element or React component. The value can be a React element or a function that takes in the original component props and gives back a React element with the props merged. diff --git a/packages/components/src/composite/index.tsx b/packages/components/src/composite/index.tsx index 4e87b9a55fa5bb..f5d92330cada3c 100644 --- a/packages/components/src/composite/index.tsx +++ b/packages/components/src/composite/index.tsx @@ -136,8 +136,10 @@ export const Composite = Object.assign( forwardRef< HTMLDivElement, WordPressComponentProps< CompositeProps, 'div', false > - >( function CompositeRow( props, ref ) { - return <Ariakit.Composite { ...props } ref={ ref } />; + >( function Composite( { disabled = false, ...props }, ref ) { + return ( + <Ariakit.Composite disabled={ disabled } { ...props } ref={ ref } /> + ); } ), { displayName: 'Composite', diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx index f1be53445f79ad..405962b92a761c 100644 --- a/packages/components/src/composite/stories/index.story.tsx +++ b/packages/components/src/composite/stories/index.story.tsx @@ -74,6 +74,28 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { table: { type: { summary: 'React.ReactNode' } }, }, }; + const accessibleWhenDisabled = { + name: 'accessibleWhenDisabled', + description: `Indicates whether the element should be focusable even when it is +\`disabled\`. + +This is important when discoverability is a concern. For example: + +> A toolbar in an editor contains a set of special smart paste functions +> that are disabled when the clipboard is empty or when the function is not +> applicable to the current content of the clipboard. It could be helpful to +> keep the disabled buttons focusable if the ability to discover their +> functionality is primarily via their presence on the toolbar. + +Learn more on [Focusability of disabled +controls](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols).`, + table: { + type: { + summary: 'boolean', + }, + }, + }; + const argTypes = { useCompositeStore: { activeId: { @@ -226,11 +248,58 @@ This only affects the composite widget behavior. You still need to set \`dir="rt }, type: { required: true }, }, + focusable: { + name: 'focusable', + description: `Makes the component a focusable element. When this element gains keyboard focus, it gets a \`data-focus-visible\` attribute and triggers the \`onFocusVisible\` prop. + +The component supports the \`disabled\` prop even for those elements not supporting the native \`disabled\` attribute. Disabled elements may be still accessible via keyboard by using the the \`accessibleWhenDisabled\` prop. + +Non-native focusable elements will lose their focusability entirely. However, native focusable elements will retain their inherent focusability.`, + table: { + type: { + summary: 'boolean', + }, + }, + }, + disabled: { + name: 'disabled', + description: `Determines if the element is disabled. This sets the \`aria-disabled\` attribute accordingly, enabling support for all elements, including those that don't support the native \`disabled\` attribute. + +This feature can be combined with the \`accessibleWhenDisabled\` prop to +make disabled elements still accessible via keyboard. + +**Note**: For this prop to work, the \`focusable\` prop must be set to +\`true\`, if it's not set by default.`, + table: { + defaultValue: { + summary: 'false', + }, + type: { + summary: 'boolean', + }, + }, + }, + accessibleWhenDisabled, + onFocusVisible: { + name: 'onFocusVisible', + description: `Custom event handler invoked when the element gains focus through keyboard interaction or a key press occurs while the element is in focus. This is the programmatic equivalent of the \`data-focus-visible\` attribute. + +**Note**: For this prop to work, the \`focusable\` prop must be set to \`true\` if it's not set by default.`, + table: { + type: { + summary: + '(event: SyntheticEvent<HTMLElement>) => void', + }, + }, + }, }, 'Composite.Group': commonArgTypes, 'Composite.GroupLabel': commonArgTypes, 'Composite.Row': commonArgTypes, - 'Composite.Item': commonArgTypes, + 'Composite.Item': { + ...commonArgTypes, + accessibleWhenDisabled, + }, 'Composite.Hover': commonArgTypes, 'Composite.Typeahead': commonArgTypes, }; diff --git a/packages/components/src/composite/types.ts b/packages/components/src/composite/types.ts index 8bd4b447a83aef..5afe410f7582ba 100644 --- a/packages/components/src/composite/types.ts +++ b/packages/components/src/composite/types.ts @@ -131,6 +131,57 @@ export type CompositeProps = { * merged. */ render?: Ariakit.CompositeProps[ 'render' ]; + /** + * Makes the component a focusable element. When this element gains keyboard + * focus, it gets a `data-focus-visible` attribute and triggers the + * `onFocusVisible` prop. + * The component supports the `disabled` prop even for those elements not + * supporting the native `disabled` attribute. Disabled elements may be + * still accessible via keyboard by using the the `accessibleWhenDisabled` + * prop. + * Non-native focusable elements will lose their focusability entirely. + * However, native focusable elements will retain their inherent focusability. + */ + focusable?: Ariakit.CompositeProps[ 'focusable' ]; + /** + * Determines if the element is disabled. This sets the `aria-disabled` + * attribute accordingly, enabling support for all elements, including those + * that don't support the native `disabled` attribute. + * + * This feature can be combined with the `accessibleWhenDisabled` prop to + * make disabled elements still accessible via keyboard. + * + * **Note**: For this prop to work, the `focusable` prop must be set to + * `true`, if it's not set by default. + * + * @default false + */ + disabled?: Ariakit.CompositeProps[ 'disabled' ]; + /** + * Indicates whether the element should be focusable even when it is + * `disabled`. + * + * This is important when discoverability is a concern. For example: + * + * > A toolbar in an editor contains a set of special smart paste functions + * that are disabled when the clipboard is empty or when the function is not + * applicable to the current content of the clipboard. It could be helpful to + * keep the disabled buttons focusable if the ability to discover their + * functionality is primarily via their presence on the toolbar. + * + * Learn more on [Focusability of disabled + * controls](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols). + */ + accessibleWhenDisabled?: Ariakit.CompositeProps[ 'accessibleWhenDisabled' ]; + /** + * Custom event handler invoked when the element gains focus through keyboard + * interaction or a key press occurs while the element is in focus. This is + * the programmatic equivalent of the `data-focus-visible` attribute. + * + * **Note**: For this prop to work, the `focusable` prop must be set to `true` + * if it's not set by default. + */ + onFocusVisible?: Ariakit.CompositeProps[ 'onFocusVisible' ]; /** * The contents of the component. */ @@ -177,6 +228,22 @@ export type CompositeItemProps = { * The contents of the component. */ children?: Ariakit.CompositeItemProps[ 'children' ]; + /** + * Indicates whether the element should be focusable even when it is + * `disabled`. + * + * This is important when discoverability is a concern. For example: + * + * > A toolbar in an editor contains a set of special smart paste functions + * that are disabled when the clipboard is empty or when the function is not + * applicable to the current content of the clipboard. It could be helpful to + * keep the disabled buttons focusable if the ability to discover their + * functionality is primarily via their presence on the toolbar. + * + * Learn more on [Focusability of disabled + * controls](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols). + */ + accessibleWhenDisabled?: Ariakit.CompositeItemProps[ 'accessibleWhenDisabled' ]; }; export type CompositeRowProps = { diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index 4c724a461e6775..cd6d2a77db9cb6 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -62,7 +62,7 @@ export { CompositeItem as __unstableCompositeItem, useCompositeState as __unstableUseCompositeState, } from './composite/legacy'; -export { Composite } from './composite'; +export { Composite, useCompositeStore } from './composite'; export { ConfirmDialog as __experimentalConfirmDialog } from './confirm-dialog'; export { default as CustomSelectControl } from './custom-select-control'; export { default as Dashicon } from './dashicon'; From ad37f2063021a9d151253ca1386c213ef300fe6d Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Tue, 13 Aug 2024 10:03:02 +0100 Subject: [PATCH 0365/1908] Zoom Out: Defalt the inserter in the patterns tab when in zoom out (#64193) Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> --- .../block-editor/src/components/inserter/menu.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index c5f41f9e3bf0a0..629765315c1d6b 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -73,9 +73,16 @@ function InserterMenu( const [ patternFilter, setPatternFilter ] = useState( 'all' ); const [ selectedMediaCategory, setSelectedMediaCategory ] = useState( null ); - const [ selectedTab, setSelectedTab ] = useState( - __experimentalInitialTab - ); + function getInitialTab() { + if ( __experimentalInitialTab ) { + return __experimentalInitialTab; + } + + if ( isZoomOutMode ) { + return 'patterns'; + } + } + const [ selectedTab, setSelectedTab ] = useState( getInitialTab() ); const [ destinationRootClientId, onInsertBlocks, onToggleInsertionPoint ] = useInsertionPoint( { From 943b72aecdfa160e925e43dad4cfbc9f9b277810 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:39:56 +0530 Subject: [PATCH 0366/1908] Fix: Embed blocks: adding captions via toolbar (#64394) * Add the Caption component to be used for consistency on the embed block similar to audio and image * Change the label for the embed caption text Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: Rishit30G <rishit30g@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: simison <simison@git.wordpress.org> --- packages/block-library/src/embed/edit.js | 9 +++++ .../block-library/src/embed/embed-preview.js | 40 ++----------------- 2 files changed, 12 insertions(+), 37 deletions(-) diff --git a/packages/block-library/src/embed/edit.js b/packages/block-library/src/embed/edit.js index 12265883d6963c..0b589eb68ecf49 100644 --- a/packages/block-library/src/embed/edit.js +++ b/packages/block-library/src/embed/edit.js @@ -14,6 +14,7 @@ import { embedContentIcon } from './icons'; import EmbedLoading from './embed-loading'; import EmbedPlaceholder from './embed-placeholder'; import EmbedPreview from './embed-preview'; +import { Caption } from '../utils/caption'; /** * External dependencies @@ -277,6 +278,14 @@ const EmbedEdit = ( props ) => { label={ label } insertBlocksAfter={ insertBlocksAfter } /> + <Caption + attributes={ attributes } + setAttributes={ setAttributes } + isSelected={ isSelected } + insertBlocksAfter={ insertBlocksAfter } + label={ __( 'Embed caption text' ) } + showToolbarButton={ isSelected } + /> </View> </> ); diff --git a/packages/block-library/src/embed/embed-preview.js b/packages/block-library/src/embed/embed-preview.js index ba079cc2e1e8b6..d53f1148cee13c 100644 --- a/packages/block-library/src/embed/embed-preview.js +++ b/packages/block-library/src/embed/embed-preview.js @@ -13,13 +13,8 @@ import clsx from 'clsx'; */ import { __, sprintf } from '@wordpress/i18n'; import { Placeholder, SandBox } from '@wordpress/components'; -import { - RichText, - BlockIcon, - __experimentalGetElementClassName, -} from '@wordpress/block-editor'; +import { BlockIcon } from '@wordpress/block-editor'; import { Component } from '@wordpress/element'; -import { createBlock, getDefaultBlockName } from '@wordpress/blocks'; import { getAuthority } from '@wordpress/url'; /** @@ -57,19 +52,8 @@ class EmbedPreview extends Component { } render() { - const { - preview, - previewable, - url, - type, - caption, - onCaptionChange, - isSelected, - className, - icon, - label, - insertBlocksAfter, - } = this.props; + const { preview, previewable, url, type, className, icon, label } = + this.props; const { scripts } = preview; const { interactive } = this.state; @@ -139,24 +123,6 @@ class EmbedPreview extends Component { </p> </Placeholder> ) } - { ( ! RichText.isEmpty( caption ) || isSelected ) && ( - <RichText - identifier="caption" - tagName="figcaption" - className={ __experimentalGetElementClassName( - 'caption' - ) } - placeholder={ __( 'Add caption' ) } - value={ caption } - onChange={ onCaptionChange } - inlineToolbar - __unstableOnSplitAtEnd={ () => - insertBlocksAfter( - createBlock( getDefaultBlockName() ) - ) - } - /> - ) } </figure> ); } From 600aa54ca87ad53b8b7e81977651ba0e5fc9affc Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 13 Aug 2024 18:27:00 +0900 Subject: [PATCH 0367/1908] Table Block: Hide caption toolbar button on multiple selection (#64462) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-library/src/table/edit.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/block-library/src/table/edit.js b/packages/block-library/src/table/edit.js index 5510d0031ff6be..95162f4e14c00b 100644 --- a/packages/block-library/src/table/edit.js +++ b/packages/block-library/src/table/edit.js @@ -95,7 +95,7 @@ function TableEdit( { attributes, setAttributes, insertBlocksAfter, - isSelected, + isSelected: isSingleSelected, } ) { const { hasFixedLayout, head, foot } = attributes; const [ initialRowCount, setInitialRowCount ] = useState( 2 ); @@ -340,10 +340,10 @@ function TableEdit( { } useEffect( () => { - if ( ! isSelected ) { + if ( ! isSingleSelected ) { setSelectedCell(); } - }, [ isSelected ] ); + }, [ isSingleSelected ] ); useEffect( () => { if ( hasTableCreated ) { @@ -565,9 +565,10 @@ function TableEdit( { <Caption attributes={ attributes } setAttributes={ setAttributes } - isSelected={ isSelected } + isSelected={ isSingleSelected } insertBlocksAfter={ insertBlocksAfter } label={ __( 'Table caption text' ) } + showToolbarButton={ isSingleSelected } /> ) } </figure> From 992bcde7651e93d3115f6c54e8bb485acd808bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Juh=C3=A9=20Lluveras?= <contact@albertjuhe.com> Date: Tue, 13 Aug 2024 11:57:24 +0200 Subject: [PATCH 0368/1908] Add plugin template registration API (#61577) Co-authored-by: Aljullu <aljullu@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: peterwilsoncc <peterwilsoncc@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: TimothyBJacobs <timothyblynjacobs@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: nerrad <nerrad@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- backport-changelog/6.7/7125.md | 3 + lib/compat/wordpress-6.7/block-templates.php | 41 ++ ...utenberg-rest-templates-controller-6-7.php | 203 ++++++++++ .../class-wp-block-templates-registry.php | 256 +++++++++++++ lib/compat/wordpress-6.7/compat.php | 114 ++++++ lib/compat/wordpress-6.7/rest-api.php | 51 +++ lib/load.php | 4 + .../core-data/src/entity-types/wp-template.ts | 4 + .../plugins/block-template-registration.php | 72 ++++ .../src/utils/is-template-removable.js | 6 +- .../src/utils/is-template-revertable.js | 3 +- .../src/dataviews/actions/reset-post.tsx | 3 +- .../editor/src/dataviews/actions/utils.ts | 4 +- packages/editor/src/dataviews/types.ts | 3 + packages/editor/src/store/private-actions.js | 2 +- .../src/store/utils/is-template-revertable.js | 3 +- phpunit/block-template-test.php | 37 ++ ...tenberg-rest-templates-controller-test.php | 119 ++++++ ...class-wp-block-templates-registry-test.php | 192 ++++++++++ .../site-editor/template-registration.spec.js | 356 ++++++++++++++++++ 20 files changed, 1469 insertions(+), 7 deletions(-) create mode 100644 backport-changelog/6.7/7125.md create mode 100644 lib/compat/wordpress-6.7/block-templates.php create mode 100644 lib/compat/wordpress-6.7/class-gutenberg-rest-templates-controller-6-7.php create mode 100644 lib/compat/wordpress-6.7/class-wp-block-templates-registry.php create mode 100644 lib/compat/wordpress-6.7/compat.php create mode 100644 packages/e2e-tests/plugins/block-template-registration.php create mode 100644 phpunit/block-template-test.php create mode 100644 phpunit/class-gutenberg-rest-templates-controller-test.php create mode 100644 phpunit/class-wp-block-templates-registry-test.php create mode 100644 test/e2e/specs/site-editor/template-registration.spec.js diff --git a/backport-changelog/6.7/7125.md b/backport-changelog/6.7/7125.md new file mode 100644 index 00000000000000..ce208decd2d145 --- /dev/null +++ b/backport-changelog/6.7/7125.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7125 + +* https://github.com/WordPress/gutenberg/pull/61577 diff --git a/lib/compat/wordpress-6.7/block-templates.php b/lib/compat/wordpress-6.7/block-templates.php new file mode 100644 index 00000000000000..e270ab226c1d9f --- /dev/null +++ b/lib/compat/wordpress-6.7/block-templates.php @@ -0,0 +1,41 @@ +<?php +/** + * Block template functions. + * + * @package gutenberg + */ + +if ( ! function_exists( 'wp_register_block_template' ) ) { + /** + * Register a template. + * + * @param string $template_name Template name in the form of `plugin_uri//template_name`. + * @param array|string $args Object type or array of object types with which the taxonomy should be associated. + * @param array|string $args { + * @type string $title Optional. Title of the template as it will be shown in the Site Editor + * and other UI elements. + * @type string $description Optional. Description of the template as it will be shown in the Site + * Editor. + * @type string $content Optional. Default content of the template that will be used when the + * template is rendered or edited in the editor. + * @type string[] $post_types Optional. Array of post types to which the template should be available. + * @type string $plugin Uri of the plugin that registers the template. + * } + * @return WP_Block_Template|WP_Error The registered template object on success, WP_Error object on failure. + */ + function wp_register_block_template( $template_name, $args = array() ) { + return WP_Block_Templates_Registry::get_instance()->register( $template_name, $args ); + } +} + +if ( ! function_exists( 'wp_unregister_block_template' ) ) { + /** + * Unregister a template. + * + * @param string $template_name Template name in the form of `plugin_uri//template_name`. + * @return true|WP_Error True on success, WP_Error on failure or if the template doesn't exist. + */ + function wp_unregister_block_template( $template_name ) { + return WP_Block_Templates_Registry::get_instance()->unregister( $template_name ); + } +} diff --git a/lib/compat/wordpress-6.7/class-gutenberg-rest-templates-controller-6-7.php b/lib/compat/wordpress-6.7/class-gutenberg-rest-templates-controller-6-7.php new file mode 100644 index 00000000000000..ed67dded75ecb1 --- /dev/null +++ b/lib/compat/wordpress-6.7/class-gutenberg-rest-templates-controller-6-7.php @@ -0,0 +1,203 @@ +<?php +/** + * REST API: Gutenberg_REST_Templates_Controller_6_7 class + * + * @package gutenberg + */ + +/** + * Gutenberg_REST_Templates_Controller_6_7 class + * + */ +class Gutenberg_REST_Templates_Controller_6_7 extends Gutenberg_REST_Templates_Controller_6_6 { + /** + * Returns the given template + * + * @param WP_REST_Request $request The request instance. + * @return WP_REST_Response|WP_Error + */ + public function get_item( $request ) { + if ( isset( $request['source'] ) && ( 'theme' === $request['source'] || 'plugin' === $request['source'] ) ) { + $template = get_block_file_template( $request['id'], $this->post_type ); + } else { + $template = get_block_template( $request['id'], $this->post_type ); + } + + if ( ! $template ) { + return new WP_Error( 'rest_template_not_found', __( 'No templates exist with that id.' ), array( 'status' => 404 ) ); + } + + return $this->prepare_item_for_response( $template, $request ); + } + + /** + * Prepare a single template output for response + * + * @param WP_Block_Template $item Template instance. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + // @core-merge: Fix wrong author in plugin templates. + public function prepare_item_for_response( $item, $request ) { + $template = $item; + + $fields = $this->get_fields_for_response( $request ); + + if ( 'plugin' !== $item->origin ) { + return parent::prepare_item_for_response( $item, $request ); + } + $cloned_item = clone $item; + // Set the origin as theme when calling the previous `prepare_item_for_response()` to prevent warnings when generating the author text. + $cloned_item->origin = 'theme'; + $response = parent::prepare_item_for_response( $cloned_item, $request ); + $data = $response->data; + + if ( rest_is_field_included( 'origin', $fields ) ) { + $data['origin'] = 'plugin'; + } + + if ( rest_is_field_included( 'plugin', $fields ) ) { + $registered_template = WP_Block_Templates_Registry::get_instance()->get_by_slug( $cloned_item->slug ); + if ( $registered_template ) { + $data['plugin'] = $registered_template->plugin; + } + } + + if ( rest_is_field_included( 'author_text', $fields ) ) { + $data['author_text'] = $this->get_wp_templates_author_text_field( $template ); + } + + if ( rest_is_field_included( 'original_source', $fields ) ) { + $data['original_source'] = $this->get_wp_templates_original_source_field( $template ); + } + + $response = rest_ensure_response( $data ); + + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $links = $this->prepare_links( $template->id ); + $response->add_links( $links ); + if ( ! empty( $links['self']['href'] ) ) { + $actions = $this->get_available_actions(); + $self = $links['self']['href']; + foreach ( $actions as $rel ) { + $response->add_link( $rel, $self ); + } + } + } + + return $response; + } + + /** + * Returns the source from where the template originally comes from. + * + * @param WP_Block_Template $template_object Template instance. + * @return string Original source of the template one of theme, plugin, site, or user. + */ + // @core-merge: Changed the comments format (from inline to multi-line) in the entire function. + private static function get_wp_templates_original_source_field( $template_object ) { + if ( 'wp_template' === $template_object->type || 'wp_template_part' === $template_object->type ) { + /* + * Added by theme. + * Template originally provided by a theme, but customized by a user. + * Templates originally didn't have the 'origin' field so identify + * older customized templates by checking for no origin and a 'theme' + * or 'custom' source. + */ + if ( $template_object->has_theme_file && + ( 'theme' === $template_object->origin || ( + empty( $template_object->origin ) && in_array( + $template_object->source, + array( + 'theme', + 'custom', + ), + true + ) ) + ) + ) { + return 'theme'; + } + + // Added by plugin. + // @core-merge: Removed `$template_object->has_theme_file` check from this if clause. + if ( 'plugin' === $template_object->origin ) { + return 'plugin'; + } + + /* + * Added by site. + * Template was created from scratch, but has no author. Author support + * was only added to templates in WordPress 5.9. Fallback to showing the + * site logo and title. + */ + if ( empty( $template_object->has_theme_file ) && 'custom' === $template_object->source && empty( $template_object->author ) ) { + return 'site'; + } + } + + // Added by user. + return 'user'; + } + + /** + * Returns a human readable text for the author of the template. + * + * @param WP_Block_Template $template_object Template instance. + * @return string Human readable text for the author. + */ + private static function get_wp_templates_author_text_field( $template_object ) { + $original_source = self::get_wp_templates_original_source_field( $template_object ); + switch ( $original_source ) { + case 'theme': + $theme_name = wp_get_theme( $template_object->theme )->get( 'Name' ); + return empty( $theme_name ) ? $template_object->theme : $theme_name; + case 'plugin': + // @core-merge: Prioritize plugin name instead of theme name for plugin-registered templates. + if ( ! function_exists( 'get_plugins' ) || ! function_exists( 'get_plugin_data' ) ) { + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + } + if ( isset( $template_object->plugin ) ) { + $plugins = wp_get_active_and_valid_plugins(); + + foreach ( $plugins as $plugin_file ) { + $plugin_basename = plugin_basename( $plugin_file ); + // Split basename by '/' to get the plugin slug. + list( $plugin_slug, ) = explode( '/', $plugin_basename ); + + if ( $plugin_slug === $template_object->plugin ) { + $plugin_data = get_plugin_data( $plugin_file ); + + if ( ! empty( $plugin_data['Name'] ) ) { + return $plugin_data['Name']; + } + + break; + } + } + } + + /* + * Fall back to the theme name if the plugin is not defined. That's needed to keep backwards + * compatibility with templates that were registered before the plugin attribute was added. + */ + $plugins = get_plugins(); + $plugin_basename = plugin_basename( sanitize_text_field( $template_object->theme . '.php' ) ); + if ( isset( $plugins[ $plugin_basename ] ) && isset( $plugins[ $plugin_basename ]['Name'] ) ) { + return $plugins[ $plugin_basename ]['Name']; + } + return isset( $template_object->plugin ) ? + $template_object->plugin : + $template_object->theme; + // @core-merge: End of changes to merge in core. + case 'site': + return get_bloginfo( 'name' ); + case 'user': + $author = get_user_by( 'id', $template_object->author ); + if ( ! $author ) { + return __( 'Unknown author' ); + } + return $author->get( 'display_name' ); + } + } +} diff --git a/lib/compat/wordpress-6.7/class-wp-block-templates-registry.php b/lib/compat/wordpress-6.7/class-wp-block-templates-registry.php new file mode 100644 index 00000000000000..db53f735e13b3d --- /dev/null +++ b/lib/compat/wordpress-6.7/class-wp-block-templates-registry.php @@ -0,0 +1,256 @@ +<?php +/** + * Templates registry functions. + * + * @package Gutenberg + * @since 6.7.0 + */ + +if ( ! class_exists( 'WP_Block_Templates_Registry' ) ) { + /** + * Core class used for interacting with templates. + * + * @since 6.7.0 + */ + final class WP_Block_Templates_Registry { + /** + * Registered templates, as `$name => $instance` pairs. + * + * @since 6.7.0 + * @var WP_Block_Template[] $registered_block_templates Registered templates. + */ + private $registered_templates = array(); + + /** + * Container for the main instance of the class. + * + * @since 6.7.0 + * @var WP_Block_Templates_Registry|null + */ + private static $instance = null; + + /** + * Registers a template. + * + * @since 6.7.0 + * + * @param string $template_name Template name including namespace. + * @param array $args Optional. Array of template arguments. + * @return WP_Block_Template|WP_Error The registered template on success, or false on failure. + */ + public function register( $template_name, $args = array() ) { + + $template = null; + + $error_message = ''; + $error_code = ''; + if ( ! is_string( $template_name ) ) { + $error_message = __( 'Template names must be strings.', 'gutenberg' ); + $error_code = 'template_name_no_string'; + } elseif ( preg_match( '/[A-Z]+/', $template_name ) ) { + $error_message = __( 'Template names must not contain uppercase characters.', 'gutenberg' ); + $error_code = 'template_name_no_uppercase'; + } elseif ( ! preg_match( '/^[a-z0-9-]+\/\/[a-z0-9-]+$/', $template_name ) ) { + $error_message = __( 'Template names must contain a namespace prefix. Example: my-plugin//my-custom-template', 'gutenberg' ); + $error_code = 'template_no_prefix'; + } elseif ( $this->is_registered( $template_name ) ) { + /* translators: %s: Template name. */ + $error_message = sprintf( __( 'Template "%s" is already registered.', 'gutenberg' ), $template_name ); + $error_code = 'template_already_registered'; + } + + if ( $error_message ) { + _doing_it_wrong( + __METHOD__, + $error_message, + '6.7.0' + ); + return new WP_Error( $error_code, $error_message ); + } + + if ( ! $template ) { + $theme_name = get_stylesheet(); + list( $plugin, $slug ) = explode( '//', $template_name ); + $default_template_types = get_default_block_template_types(); + + $template = new WP_Block_Template(); + $template->id = $theme_name . '//' . $slug; + $template->theme = $theme_name; + $template->plugin = $plugin; + $template->author = null; + $template->content = isset( $args['content'] ) ? $args['content'] : ''; + $template->source = 'plugin'; + $template->slug = $slug; + $template->type = 'wp_template'; + $template->title = isset( $args['title'] ) ? $args['title'] : $template_name; + $template->description = isset( $args['description'] ) ? $args['description'] : ''; + $template->status = 'publish'; + $template->origin = 'plugin'; + $template->is_custom = ! isset( $default_template_types[ $template_name ] ); + $template->post_types = isset( $args['post_types'] ) ? $args['post_types'] : array(); + } + + $this->registered_templates[ $template_name ] = $template; + + return $template; + } + + /** + * Retrieves all registered templates. + * + * @since 6.7.0 + * + * @return WP_Block_Template[]|false Associative array of `$template_name => $template` pairs. + */ + public function get_all_registered() { + return $this->registered_templates; + } + + /** + * Retrieves a registered template by its name. + * + * @since 6.7.0 + * + * @param string $template_name Template name including namespace. + * @return WP_Block_Template|null|false The registered template, or null if it is not registered. + */ + public function get_registered( $template_name ) { + if ( ! $this->is_registered( $template_name ) ) { + return null; + } + + return $this->registered_templates[ $template_name ]; + } + + /** + * Retrieves a registered template by its slug. + * + * @since 6.7.0 + * + * @param string $template_slug Slug of the template. + * @return WP_Block_Template|null The registered template, or null if it is not registered. + */ + public function get_by_slug( $template_slug ) { + $all_templates = $this->get_all_registered(); + + if ( ! $all_templates ) { + return null; + } + + foreach ( $all_templates as $template ) { + if ( $template->slug === $template_slug ) { + return $template; + } + } + + return null; + } + + /** + * Retrieves registered templates matching a query. + * + * @since 6.7.0 + * + * @param array $query { + * Arguments to retrieve templates. Optional, empty by default. + * + * @type string[] $slug__in List of slugs to include. + * @type string[] $slug__not_in List of slugs to skip. + * @type string $post_type Post type to get the templates for. + * } + */ + public function get_by_query( $query = array() ) { + $all_templates = $this->get_all_registered(); + + if ( ! $all_templates ) { + return array(); + } + + $query = wp_parse_args( + $query, + array( + 'slug__in' => array(), + 'slug__not_in' => array(), + 'post_type' => '', + ) + ); + $slugs_to_include = $query['slug__in']; + $slugs_to_skip = $query['slug__not_in']; + $post_type = $query['post_type']; + + $matching_templates = array(); + foreach ( $all_templates as $template_name => $template ) { + if ( $slugs_to_include && ! in_array( $template->slug, $slugs_to_include, true ) ) { + continue; + } + + if ( $slugs_to_skip && in_array( $template->slug, $slugs_to_skip, true ) ) { + continue; + } + + if ( $post_type && ! in_array( $post_type, $template->post_types, true ) ) { + continue; + } + + $matching_templates[ $template_name ] = $template; + } + + return $matching_templates; + } + + /** + * Checks if a template is registered. + * + * @since 6.7.0 + * + * @param string $template_name Template name. + * @return bool True if the template is registered, false otherwise. + */ + public function is_registered( $template_name ) { + return isset( $this->registered_templates[ $template_name ] ); + } + + /** + * Unregisters a template. + * + * @since 6.7.0 + * + * @param string $template_name Template name including namespace. + * @return WP_Block_Template|false The unregistered template on success, or false on failure. + */ + public function unregister( $template_name ) { + if ( ! $this->is_registered( $template_name ) ) { + _doing_it_wrong( + __METHOD__, + /* translators: %s: Template name. */ + sprintf( __( 'Template "%s" is not registered.', 'gutenberg' ), $template_name ), + '6.7.0' + ); + /* translators: %s: Template name. */ + return new WP_Error( 'template_not_registered', __( 'Template "%s" is not registered.', 'gutenberg' ) ); + } + + $unregistered_template = $this->registered_templates[ $template_name ]; + unset( $this->registered_templates[ $template_name ] ); + + return $unregistered_template; + } + + /** + * Utility method to retrieve the main instance of the class. + * + * The instance will be created if it does not exist yet. + * + * @since 6.7.0 + * + * @return WP_Block_Templates_Registry The main instance. + */ + public static function get_instance() { + if ( null === self::$instance ) { + self::$instance = new self(); + } + + return self::$instance; + } + } +} diff --git a/lib/compat/wordpress-6.7/compat.php b/lib/compat/wordpress-6.7/compat.php new file mode 100644 index 00000000000000..7021cab2053eff --- /dev/null +++ b/lib/compat/wordpress-6.7/compat.php @@ -0,0 +1,114 @@ +<?php +/** + * WordPress 6.7 compatibility functions. + * + * @package gutenberg + */ + +/** + * Hooks into `get_block_templates` so templates from the registry are also returned, as long as there + * isn't a theme template with the same slug. + * + * @param WP_Block_Template[] $query_result Array of found block templates. + * @param array $query { + * Arguments to retrieve templates. All arguments are optional. + * + * @type string[] $slug__in List of slugs to include. + * @type int $wp_id Post ID of customized template. + * @type string $area A 'wp_template_part_area' taxonomy value to filter by (for 'wp_template_part' template type only). + * @type string $post_type Post type to get the templates for. + * } + * @param string $template_type wp_template or wp_template_part. + * @return WP_Block_Template[] The same $query_result but might contain some additional templates from + * the registry. + */ +function _gutenberg_add_block_templates_from_registry( $query_result, $query, $template_type ) { + // Add `plugin` property to templates registered by a plugin. + foreach ( $query_result as $key => $value ) { + $registered_template = WP_Block_Templates_Registry::get_instance()->get_by_slug( $query_result[ $key ]->slug ); + if ( $registered_template ) { + $query_result[ $key ]->plugin = $registered_template->plugin; + $query_result[ $key ]->origin = + 'theme' !== $query_result[ $key ]->origin && 'theme' !== $query_result[ $key ]->source ? + 'plugin' : + $query_result[ $key ]->origin; + } + } + + if ( ! isset( $query['wp_id'] ) ) { + $template_files = _gutenberg_get_block_templates_files( $template_type, $query ); + + /* + * Add templates registered in the template registry. Filtering out the ones which have a theme file. + */ + $registered_templates = WP_Block_Templates_Registry::get_instance()->get_by_query( $query ); + $matching_registered_templates = array_filter( + $registered_templates, + function ( $registered_template ) use ( $template_files ) { + foreach ( $template_files as $template_file ) { + if ( $template_file['slug'] === $registered_template->slug ) { + return false; + } + } + return true; + } + ); + $query_result = array_merge( $query_result, $matching_registered_templates ); + } + + return $query_result; +} +add_filter( 'get_block_templates', '_gutenberg_add_block_templates_from_registry', 10, 3 ); + +/** + * Hooks into `get_block_template` to add the `plugin` property when necessary. + * + * @param [WP_Block_Template|null] $block_template The found block template, or null if there isn’t one. + * @return [WP_Block_Template|null] The block template that was already found with the plugin property defined if it was reigstered by a plugin. + */ +function _gutenberg_add_block_template_plugin_attribute( $block_template ) { + if ( $block_template ) { + $registered_template = WP_Block_Templates_Registry::get_instance()->get_by_slug( $block_template->slug ); + if ( $registered_template ) { + $block_template->plugin = $registered_template->plugin; + $block_template->origin = + 'theme' !== $block_template->origin && 'theme' !== $block_template->source ? + 'plugin' : + $block_template->origin; + } + } + + return $block_template; +} +add_filter( 'get_block_template', '_gutenberg_add_block_template_plugin_attribute', 10, 1 ); + +/** + * Hooks into `get_block_file_template` so templates from the registry are also returned. + * + * @param WP_Block_Template|null $block_template The found block template, or null if there is none. + * @param string $id Template unique identifier (example: 'theme_slug//template_slug'). + * @return WP_Block_Template|null The block template that was already found or from the registry. In case the template was already found, add the necessary details from the registry. + */ +function _gutenberg_add_block_file_templates_from_registry( $block_template, $id ) { + if ( $block_template ) { + $registered_template = WP_Block_Templates_Registry::get_instance()->get_by_slug( $block_template->slug ); + if ( $registered_template ) { + $block_template->plugin = $registered_template->plugin; + $block_template->origin = + 'theme' !== $block_template->origin && 'theme' !== $block_template->source ? + 'plugin' : + $block_template->origin; + } + return $block_template; + } + + $parts = explode( '//', $id, 2 ); + + if ( count( $parts ) < 2 ) { + return $block_template; + } + + list( , $slug ) = $parts; + return WP_Block_Templates_Registry::get_instance()->get_by_slug( $slug ); +} +add_filter( 'get_block_file_template', '_gutenberg_add_block_file_templates_from_registry', 10, 2 ); diff --git a/lib/compat/wordpress-6.7/rest-api.php b/lib/compat/wordpress-6.7/rest-api.php index 713d31c4632c74..fe2aac9c2580ae 100644 --- a/lib/compat/wordpress-6.7/rest-api.php +++ b/lib/compat/wordpress-6.7/rest-api.php @@ -29,3 +29,54 @@ function gutenberg_block_editor_preload_paths_6_7( $paths, $context ) { return $paths; } add_filter( 'block_editor_rest_api_preload_paths', 'gutenberg_block_editor_preload_paths_6_7', 10, 2 ); + +if ( ! function_exists( 'wp_api_template_registry' ) ) { + /** + * Hook in to the template and template part post types and modify the rest + * endpoint to include modifications to read templates from the + * BlockTemplatesRegistry. + * + * @param array $args Current registered post type args. + * @param string $post_type Name of post type. + * + * @return array + */ + function wp_api_template_registry( $args, $post_type ) { + if ( 'wp_template' === $post_type || 'wp_template_part' === $post_type ) { + $args['rest_controller_class'] = 'Gutenberg_REST_Templates_Controller_6_7'; + } + return $args; + } +} +add_filter( 'register_post_type_args', 'wp_api_template_registry', 10, 2 ); + +/** + * Adds `plugin` fields to WP_REST_Templates_Controller class. + */ +function gutenberg_register_wp_rest_templates_controller_plugin_field() { + + register_rest_field( + 'wp_template', + 'plugin', + array( + 'get_callback' => function ( $template_object ) { + if ( $template_object ) { + $registered_template = WP_Block_Templates_Registry::get_instance()->get_by_slug( $template_object['slug'] ); + if ( $registered_template ) { + return $registered_template->plugin; + } + } + + return; + }, + 'update_callback' => null, + 'schema' => array( + 'type' => 'string', + 'description' => __( 'Plugin that registered the template.', 'gutenberg' ), + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + ) + ); +} +add_action( 'rest_api_init', 'gutenberg_register_wp_rest_templates_controller_plugin_field' ); diff --git a/lib/load.php b/lib/load.php index c5f12af1654df2..b501f0abd1c978 100644 --- a/lib/load.php +++ b/lib/load.php @@ -41,6 +41,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.6/rest-api.php'; // WordPress 6.7 compat. + require __DIR__ . '/compat/wordpress-6.7/class-gutenberg-rest-templates-controller-6-7.php'; require __DIR__ . '/compat/wordpress-6.7/rest-api.php'; // Plugin specific code. @@ -101,9 +102,12 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.6/post.php'; // WordPress 6.7 compat. +require __DIR__ . '/compat/wordpress-6.7/block-templates.php'; require __DIR__ . '/compat/wordpress-6.7/blocks.php'; require __DIR__ . '/compat/wordpress-6.7/block-bindings.php'; require __DIR__ . '/compat/wordpress-6.7/script-modules.php'; +require __DIR__ . '/compat/wordpress-6.7/class-wp-block-templates-registry.php'; +require __DIR__ . '/compat/wordpress-6.7/compat.php'; // Experimental features. require __DIR__ . '/experimental/block-editor-settings-mobile.php'; diff --git a/packages/core-data/src/entity-types/wp-template.ts b/packages/core-data/src/entity-types/wp-template.ts index ac6db09035f193..70d3e40c295dcf 100644 --- a/packages/core-data/src/entity-types/wp-template.ts +++ b/packages/core-data/src/entity-types/wp-template.ts @@ -73,6 +73,10 @@ declare module './base-entity-records' { * Post ID. */ wp_id: number; + /** + * Plugin that registered the template. + */ + plugin?: string; /** * Theme file exists. */ diff --git a/packages/e2e-tests/plugins/block-template-registration.php b/packages/e2e-tests/plugins/block-template-registration.php new file mode 100644 index 00000000000000..a7c75552849658 --- /dev/null +++ b/packages/e2e-tests/plugins/block-template-registration.php @@ -0,0 +1,72 @@ +<?php +/** + * Plugin Name: Gutenberg Test Block Template Registration + * Plugin URI: https://github.com/WordPress/gutenberg + * Author: Gutenberg Team + * + * @package gutenberg-test-block-template-registration + */ + +add_action( + 'init', + function () { + // Custom template used by most tests. + wp_register_block_template( + 'gutenberg//plugin-template', + array( + 'title' => 'Plugin Template', + 'description' => 'A template registered by a plugin.', + 'content' => '<!-- wp:template-part {"slug":"header","tagName":"header"} /--><!-- wp:group {"tagName":"main","layout":{"inherit":true}} --><main class="wp-block-group"><!-- wp:paragraph --><p>This is a plugin-registered template.</p><!-- /wp:paragraph --></main><!-- /wp:group -->', + 'post_types' => array( 'post' ), + ) + ); + add_action( + 'category_template_hierarchy', + function () { + return array( 'plugin-template' ); + } + ); + + // Custom template overridden by the theme. + wp_register_block_template( + 'gutenberg//custom-template', + array( + 'title' => 'Custom Template (overridden by the theme)', + 'description' => 'A custom template registered by a plugin and overridden by a theme.', + 'content' => '<!-- wp:template-part {"slug":"header","tagName":"header"} /--><!-- wp:group {"tagName":"main","layout":{"inherit":true}} --><main class="wp-block-group"><!-- wp:paragraph --><p>This is a plugin-registered template and overridden by a theme.</p><!-- /wp:paragraph --></main><!-- /wp:group -->', + 'post_types' => array( 'post' ), + ) + ); + + // Custom template used to test unregistration. + wp_register_block_template( + 'gutenberg//plugin-unregistered-template', + array( + 'title' => 'Plugin Unregistered Template', + 'description' => 'A plugin-registered template that is unregistered.', + 'content' => '<!-- wp:template-part {"slug":"header","tagName":"header"} /--><!-- wp:group {"tagName":"main","layout":{"inherit":true}} --><main class="wp-block-group"><!-- wp:paragraph --><p>This is a plugin-registered template that is also unregistered.</p><!-- /wp:paragraph --></main><!-- /wp:group -->', + ) + ); + wp_unregister_block_template( 'gutenberg//plugin-unregistered-template' ); + + // Custom template used to test overriding default WP templates. + wp_register_block_template( + 'gutenberg//page', + array( + 'title' => 'Plugin Page Template', + 'description' => 'A plugin-registered page template.', + 'content' => '<!-- wp:template-part {"slug":"header","tagName":"header"} /--><!-- wp:group {"tagName":"main","layout":{"inherit":true}} --><main class="wp-block-group"><!-- wp:paragraph --><p>This is a plugin-registered page template.</p><!-- /wp:paragraph --></main><!-- /wp:group -->', + ) + ); + + // Custom template used to test overriding default WP templates which can be created by the user. + wp_register_block_template( + 'gutenberg//author-admin', + array( + 'title' => 'Plugin Author Template', + 'description' => 'A plugin-registered author template.', + 'content' => '<!-- wp:template-part {"slug":"header","tagName":"header"} /--><!-- wp:group {"tagName":"main","layout":{"inherit":true}} --><main class="wp-block-group"><!-- wp:paragraph --><p>This is a plugin-registered author template.</p><!-- /wp:paragraph --></main><!-- /wp:group -->', + ) + ); + } +); diff --git a/packages/edit-site/src/utils/is-template-removable.js b/packages/edit-site/src/utils/is-template-removable.js index 9cb1de23daab75..f81cb74b022e73 100644 --- a/packages/edit-site/src/utils/is-template-removable.js +++ b/packages/edit-site/src/utils/is-template-removable.js @@ -7,7 +7,7 @@ import { TEMPLATE_ORIGINS } from './constants'; * Check if a template is removable. * * @param {Object} template The template entity to check. - * @return {boolean} Whether the template is revertable. + * @return {boolean} Whether the template is removable. */ export default function isTemplateRemovable( template ) { if ( ! template ) { @@ -15,6 +15,8 @@ export default function isTemplateRemovable( template ) { } return ( - template.source === TEMPLATE_ORIGINS.custom && ! template.has_theme_file + template.source === TEMPLATE_ORIGINS.custom && + ! Boolean( template.plugin ) && + ! template.has_theme_file ); } diff --git a/packages/edit-site/src/utils/is-template-revertable.js b/packages/edit-site/src/utils/is-template-revertable.js index a6274d07ebebb6..42413b06cd48ec 100644 --- a/packages/edit-site/src/utils/is-template-revertable.js +++ b/packages/edit-site/src/utils/is-template-revertable.js @@ -15,7 +15,8 @@ export default function isTemplateRevertable( template ) { } /* eslint-disable camelcase */ return ( - template?.source === TEMPLATE_ORIGINS.custom && template?.has_theme_file + template?.source === TEMPLATE_ORIGINS.custom && + ( Boolean( template?.plugin ) || template?.has_theme_file ) ); /* eslint-enable camelcase */ } diff --git a/packages/editor/src/dataviews/actions/reset-post.tsx b/packages/editor/src/dataviews/actions/reset-post.tsx index 59199555ddd4db..cc4cea8f5c82c0 100644 --- a/packages/editor/src/dataviews/actions/reset-post.tsx +++ b/packages/editor/src/dataviews/actions/reset-post.tsx @@ -32,7 +32,8 @@ const resetPost: Action< Post > = { return ( isTemplateOrTemplatePart( item ) && item?.source === TEMPLATE_ORIGINS.custom && - item?.has_theme_file + ( Boolean( item.type === 'wp_template' && item?.plugin ) || + item?.has_theme_file ) ); }, icon: backup, diff --git a/packages/editor/src/dataviews/actions/utils.ts b/packages/editor/src/dataviews/actions/utils.ts index 7da1f71728365b..33a2be16397f3f 100644 --- a/packages/editor/src/dataviews/actions/utils.ts +++ b/packages/editor/src/dataviews/actions/utils.ts @@ -57,6 +57,8 @@ export function isTemplateRemovable( template: Template | TemplatePart ) { return ( [ template.source, template.source ].includes( TEMPLATE_ORIGINS.custom - ) && ! template.has_theme_file + ) && + ! Boolean( template.type === 'wp_template' && template?.plugin ) && + ! template.has_theme_file ); } diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts index 514953d6691290..d207410ca2b6a5 100644 --- a/packages/editor/src/dataviews/types.ts +++ b/packages/editor/src/dataviews/types.ts @@ -34,6 +34,8 @@ export interface Template extends CommonPost { type: 'wp_template'; is_custom: boolean; source: string; + origin: string; + plugin?: string; has_theme_file: boolean; id: string; } @@ -41,6 +43,7 @@ export interface Template extends CommonPost { export interface TemplatePart extends CommonPost { type: 'wp_template_part'; source: string; + origin: string; has_theme_file: boolean; id: string; area: string; diff --git a/packages/editor/src/store/private-actions.js b/packages/editor/src/store/private-actions.js index 0996d6eb8b9d32..e22929011256d5 100644 --- a/packages/editor/src/store/private-actions.js +++ b/packages/editor/src/store/private-actions.js @@ -269,7 +269,7 @@ export const revertTemplate = const fileTemplatePath = addQueryArgs( `${ templateEntityConfig.baseURL }/${ template.id }`, - { context: 'edit', source: 'theme' } + { context: 'edit', source: template.origin } ); const fileTemplate = await apiFetch( { path: fileTemplatePath } ); diff --git a/packages/editor/src/store/utils/is-template-revertable.js b/packages/editor/src/store/utils/is-template-revertable.js index a09715af875bc2..2cb674920e3e4c 100644 --- a/packages/editor/src/store/utils/is-template-revertable.js +++ b/packages/editor/src/store/utils/is-template-revertable.js @@ -18,6 +18,7 @@ export default function isTemplateRevertable( templateOrTemplatePart ) { return ( templateOrTemplatePart.source === TEMPLATE_ORIGINS.custom && - templateOrTemplatePart.has_theme_file + ( Boolean( templateOrTemplatePart?.plugin ) || + templateOrTemplatePart?.has_theme_file ) ); } diff --git a/phpunit/block-template-test.php b/phpunit/block-template-test.php new file mode 100644 index 00000000000000..6589aad90b8053 --- /dev/null +++ b/phpunit/block-template-test.php @@ -0,0 +1,37 @@ +<?php +/** + * Tests block template registry via block-related functions. + */ +class Tests_Block_Template extends WP_UnitTestCase { + public function set_up() { + parent::set_up(); + switch_theme( 'block-theme' ); + } + + public function test_get_block_templates_from_registry() { + $template_name = 'test-plugin//test-template'; + + wp_register_block_template( $template_name ); + + $templates = get_block_templates(); + + $this->assertArrayHasKey( $template_name, $templates ); + + wp_unregister_block_template( $template_name ); + } + + public function test_get_block_template_from_registry() { + $template_name = 'test-plugin//test-template'; + $args = array( + 'title' => 'Test Template', + ); + + wp_register_block_template( $template_name, $args ); + + $template = get_block_template( 'block-theme//test-template' ); + + $this->assertEquals( 'Test Template', $template->title ); + + wp_unregister_block_template( $template_name ); + } +} diff --git a/phpunit/class-gutenberg-rest-templates-controller-test.php b/phpunit/class-gutenberg-rest-templates-controller-test.php new file mode 100644 index 00000000000000..14735246c6fb20 --- /dev/null +++ b/phpunit/class-gutenberg-rest-templates-controller-test.php @@ -0,0 +1,119 @@ +<?php +/** + * Unit tests covering Gutenberg_REST_Templates_Controller_6_7 functionality. + */ +class Gutenberg_REST_Templates_Controller_6_7_Test extends WP_Test_REST_Controller_Testcase { + + /** + * @var int + */ + protected static $admin_id; + + public static function wpSetupBeforeClass( $factory ) { + self::$admin_id = $factory->user->create( + array( + 'role' => 'administrator', + ) + ); + } + + public static function wpTearDownAfterClass() { + self::delete_user( self::$admin_id ); + } + + public function test_get_item() { + wp_set_current_user( self::$admin_id ); + + $template_name = 'test-plugin//test-template'; + $args = array( + 'content' => 'Template content', + 'title' => 'Test Template', + 'description' => 'Description of test template', + 'post_types' => array( 'post', 'page' ), + ); + + wp_register_block_template( $template_name, $args ); + + $request = new WP_REST_Request( 'GET', '/wp/v2/templates/test-plugin//test-template' ); + $response = rest_get_server()->dispatch( $request ); + + $this->assertNotWPError( $response, "Fetching a registered template shouldn't cause an error." ); + + $data = $response->get_data(); + + $this->assertSame( 'default//test-template', $data['id'], 'Template ID mismatch.' ); + $this->assertSame( 'default', $data['theme'], 'Template theme mismatch.' ); + $this->assertSame( 'Template content', $data['content']['raw'], 'Template content mismatch.' ); + $this->assertSame( 'test-template', $data['slug'], 'Template slug mismatch.' ); + $this->assertSame( 'plugin', $data['source'], "Template source should be 'plugin'." ); + $this->assertSame( 'plugin', $data['origin'], "Template origin should be 'plugin'." ); + $this->assertSame( 'test-plugin', $data['author_text'], 'Template author text mismatch.' ); + $this->assertSame( 'Description of test template', $data['description'], 'Template description mismatch.' ); + $this->assertSame( 'Test Template', $data['title']['rendered'], 'Template title mismatch.' ); + $this->assertSame( 'test-plugin', $data['plugin'], 'Plugin name mismatch.' ); + + wp_unregister_block_template( $template_name ); + + $request = new WP_REST_Request( 'GET', '/wp/v2/templates/test-plugin//test-template' ); + $response = rest_get_server()->dispatch( $request ); + + $this->assertNotWPError( $response, "Fetching an unregistered template shouldn't cause an error." ); + $this->assertSame( 404, $response->get_status(), 'Fetching an unregistered template should return 404.' ); + } + + /** + * @doesNotPerformAssertions + */ + public function test_register_routes() { + // Already present in core test class: Tests_REST_WpRestTemplatesController. + } + + /** + * @doesNotPerformAssertions + */ + public function test_get_items() { + // Already present in core test class: Tests_REST_WpRestTemplatesController. + } + + /** + * @doesNotPerformAssertions + */ + public function test_create_item() { + // Already present in core test class: Tests_REST_WpRestTemplatesController. + } + + /** + * @doesNotPerformAssertions + */ + public function test_update_item() { + // Already present in core test class: Tests_REST_WpRestTemplatesController. + } + + /** + * @doesNotPerformAssertions + */ + public function test_delete_item() { + // Already present in core test class: Tests_REST_WpRestTemplatesController. + } + + /** + * @doesNotPerformAssertions + */ + public function test_context_param() { + // Already present in core test class: Tests_REST_WpRestTemplatesController. + } + + /** + * @doesNotPerformAssertions + */ + public function test_prepare_item() { + // Already present in core test class: Tests_REST_WpRestTemplatesController. + } + + /** + * @doesNotPerformAssertions + */ + public function test_get_item_schema() { + // Already present in core test class: Tests_REST_WpRestTemplatesController. + } +} diff --git a/phpunit/class-wp-block-templates-registry-test.php b/phpunit/class-wp-block-templates-registry-test.php new file mode 100644 index 00000000000000..fb8436eb6153d4 --- /dev/null +++ b/phpunit/class-wp-block-templates-registry-test.php @@ -0,0 +1,192 @@ +<?php +/** + * Test WP_Block_Templates_Registry class. + * + * @covers WP_Block_Templates_Registry + */ +class WP_Block_Templates_Registry_Test extends WP_UnitTestCase { + + /** + * @var WP_Block_Templates_Registry + */ + protected static $registry; + + public static function set_up_before_class() { + parent::set_up_before_class(); + + self::$registry = WP_Block_Templates_Registry::get_instance(); + } + + public function test_register_template() { + // Register a valid template. + $template_name = 'test-plugin//test-template'; + $template = self::$registry->register( $template_name ); + + $this->assertSame( $template->slug, 'test-template' ); + + self::$registry->unregister( $template_name ); + } + + public function test_register_template_invalid_name() { + // Try to register a template with invalid name (non-string). + $template_name = array( 'invalid-template-name' ); + + $this->setExpectedIncorrectUsage( 'WP_Block_Templates_Registry::register' ); + $result = self::$registry->register( $template_name ); + + $this->assertWPError( $result ); + $this->assertSame( 'template_name_no_string', $result->get_error_code(), 'Error code mismatch.' ); + $this->assertSame( 'Template names must be strings.', $result->get_error_message(), 'Error message mismatch.' ); + } + + public function test_register_template_invalid_name_uppercase() { + // Try to register a template with uppercase characters in the name. + $template_name = 'test-plugin//Invalid-Template-Name'; + + $this->setExpectedIncorrectUsage( 'WP_Block_Templates_Registry::register' ); + $result = self::$registry->register( $template_name ); + + $this->assertWPError( $result ); + $this->assertSame( 'template_name_no_uppercase', $result->get_error_code(), 'Error code mismatch.' ); + $this->assertSame( 'Template names must not contain uppercase characters.', $result->get_error_message(), 'Error message mismatch.' ); + } + + public function test_register_template_no_prefix() { + // Try to register a template without a namespace. + $this->setExpectedIncorrectUsage( 'WP_Block_Templates_Registry::register' ); + $result = self::$registry->register( 'template-no-plugin', array() ); + + $this->assertWPError( $result ); + $this->assertSame( 'template_no_prefix', $result->get_error_code(), 'Error code mismatch.' ); + $this->assertSame( 'Template names must contain a namespace prefix. Example: my-plugin//my-custom-template', $result->get_error_message(), 'Error message mismatch.' ); + } + + public function test_register_template_already_exists() { + // Register the template for the first time. + $template_name = 'test-plugin//duplicate-template'; + self::$registry->register( $template_name ); + + // Try to register the same template again. + $this->setExpectedIncorrectUsage( 'WP_Block_Templates_Registry::register' ); + $result = self::$registry->register( $template_name ); + + $this->assertWPError( $result ); + $this->assertSame( 'template_already_registered', $result->get_error_code(), 'Error code mismatch.' ); + $this->assertStringContainsString( 'Template "test-plugin//duplicate-template" is already registered.', $result->get_error_message(), 'Error message mismatch.' ); + + self::$registry->unregister( $template_name ); + } + + public function test_get_all_registered() { + $template_name_1 = 'test-plugin//template-1'; + $template_name_2 = 'test-plugin//template-2'; + self::$registry->register( $template_name_1 ); + self::$registry->register( $template_name_2 ); + + $all_templates = self::$registry->get_all_registered(); + + $this->assertIsArray( $all_templates, 'Registered templates should be an array.' ); + $this->assertCount( 2, $all_templates, 'Registered templates should contain 2 items.' ); + $this->assertArrayHasKey( 'test-plugin//template-1', $all_templates, 'Registered templates should contain "test-plugin//template-1".' ); + $this->assertArrayHasKey( 'test-plugin//template-2', $all_templates, 'Registered templates should contain "test-plugin//template-2".' ); + + self::$registry->unregister( $template_name_1 ); + self::$registry->unregister( $template_name_2 ); + } + + public function test_get_registered() { + $template_name = 'test-plugin//registered-template'; + $args = array( + 'content' => 'Template content', + 'title' => 'Registered Template', + 'description' => 'Description of registered template', + 'post_types' => array( 'post', 'page' ), + ); + self::$registry->register( $template_name, $args ); + + $registered_template = self::$registry->get_registered( $template_name ); + + $this->assertSame( 'default', $registered_template->theme, 'Template theme mismatch.' ); + $this->assertSame( 'registered-template', $registered_template->slug, 'Template slug mismatch.' ); + $this->assertSame( 'default//registered-template', $registered_template->id, 'Template ID mismatch.' ); + $this->assertSame( 'Registered Template', $registered_template->title, 'Template title mismatch.' ); + $this->assertSame( 'Template content', $registered_template->content, 'Template content mismatch.' ); + $this->assertSame( 'Description of registered template', $registered_template->description, 'Template description mismatch.' ); + $this->assertSame( 'plugin', $registered_template->source, "Template source should be 'plugin'." ); + $this->assertSame( 'plugin', $registered_template->origin, "Template origin should be 'plugin'." ); + $this->assertEquals( array( 'post', 'page' ), $registered_template->post_types, 'Template post types mismatch.' ); + $this->assertSame( 'test-plugin', $registered_template->plugin, 'Plugin name mismatch.' ); + + self::$registry->unregister( $template_name ); + } + + public function test_get_by_slug() { + $slug = 'slug-template'; + $template_name = 'test-plugin//' . $slug; + $args = array( + 'content' => 'Template content', + 'title' => 'Slug Template', + ); + self::$registry->register( $template_name, $args ); + + $registered_template = self::$registry->get_by_slug( $slug ); + + $this->assertNotNull( $registered_template, 'Registered template should not be null.' ); + $this->assertSame( $slug, $registered_template->slug, 'Template slug mismatch.' ); + + self::$registry->unregister( $template_name ); + } + + public function test_get_by_query() { + $template_name_1 = 'test-plugin//query-template-1'; + $template_name_2 = 'test-plugin//query-template-2'; + $args_1 = array( + 'content' => 'Template content 1', + 'title' => 'Query Template 1', + ); + $args_2 = array( + 'content' => 'Template content 2', + 'title' => 'Query Template 2', + ); + self::$registry->register( $template_name_1, $args_1 ); + self::$registry->register( $template_name_2, $args_2 ); + + $query = array( + 'slug__in' => array( 'query-template-1' ), + ); + $results = self::$registry->get_by_query( $query ); + + $this->assertCount( 1, $results, 'Query result should contain 1 item.' ); + $this->assertArrayHasKey( $template_name_1, $results, 'Query result should contain "test-plugin//query-template-1".' ); + + self::$registry->unregister( $template_name_1 ); + self::$registry->unregister( $template_name_2 ); + } + + public function test_is_registered() { + $template_name = 'test-plugin//is-registered-template'; + $args = array( + 'content' => 'Template content', + 'title' => 'Is Registered Template', + ); + self::$registry->register( $template_name, $args ); + + $this->assertTrue( self::$registry->is_registered( $template_name ) ); + + self::$registry->unregister( $template_name ); + } + + public function test_unregister() { + $template_name = 'test-plugin//unregister-template'; + $args = array( + 'content' => 'Template content', + 'title' => 'Unregister Template', + ); + $template = self::$registry->register( $template_name, $args ); + + $unregistered_template = self::$registry->unregister( $template_name ); + + $this->assertEquals( $template, $unregistered_template, 'Unregistered template should be the same as the registered one.' ); + $this->assertFalse( self::$registry->is_registered( $template_name ), 'Template should not be registered after unregistering.' ); + } +} diff --git a/test/e2e/specs/site-editor/template-registration.spec.js b/test/e2e/specs/site-editor/template-registration.spec.js new file mode 100644 index 00000000000000..132e3a8c49a902 --- /dev/null +++ b/test/e2e/specs/site-editor/template-registration.spec.js @@ -0,0 +1,356 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.use( { + blockTemplateRegistrationUtils: async ( { editor, page }, use ) => { + await use( new BlockTemplateRegistrationUtils( { editor, page } ) ); + }, +} ); + +test.describe( 'Block template registration', () => { + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'emptytheme' ); + await requestUtils.activatePlugin( + 'gutenberg-test-block-template-registration' + ); + } ); + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.deactivatePlugin( + 'gutenberg-test-block-template-registration' + ); + } ); + test.afterEach( async ( { requestUtils } ) => { + await requestUtils.deleteAllTemplates( 'wp_template' ); + await requestUtils.deleteAllPosts(); + } ); + + test( 'templates can be registered and edited', async ( { + admin, + editor, + page, + blockTemplateRegistrationUtils, + } ) => { + // Verify template is applied to the frontend. + await page.goto( '/?cat=1' ); + await expect( + page.getByText( 'This is a plugin-registered template.' ) + ).toBeVisible(); + + // Verify template is listed in the Site Editor. + await admin.visitSiteEditor( { + postType: 'wp_template', + } ); + await blockTemplateRegistrationUtils.searchForTemplate( + 'Plugin Template' + ); + await expect( page.getByText( 'Plugin Template' ) ).toBeVisible(); + await expect( + page.getByText( 'A template registered by a plugin.' ) + ).toBeVisible(); + await expect( page.getByText( 'AuthorGutenberg' ) ).toBeVisible(); + + // Verify the template contents are rendered in the editor. + await page.getByText( 'Plugin Template' ).click(); + await expect( + editor.canvas.getByText( 'This is a plugin-registered template.' ) + ).toBeVisible(); + + // Verify edits persist in the frontend. + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { content: 'User-edited template' }, + } ); + await editor.saveSiteEditorEntities( { + isOnlyCurrentEntityDirty: true, + } ); + await page.goto( '/?cat=1' ); + await expect( page.getByText( 'User-edited template' ) ).toBeVisible(); + + // Verify template can be reset. + await admin.visitSiteEditor( { + postType: 'wp_template', + } ); + const resetNotice = page + .getByLabel( 'Dismiss this notice' ) + .getByText( `"Plugin Template" reset.` ); + const savedButton = page.getByRole( 'button', { + name: 'Saved', + } ); + await blockTemplateRegistrationUtils.searchForTemplate( + 'Plugin Template' + ); + const searchResults = page.getByLabel( 'Actions' ); + await searchResults.first().click(); + await page.getByRole( 'menuitem', { name: 'Reset' } ).click(); + await page.getByRole( 'button', { name: 'Reset' } ).click(); + + await expect( resetNotice ).toBeVisible(); + await expect( savedButton ).toBeVisible(); + await page.goto( '/?cat=1' ); + await expect( + page.getByText( 'Content edited template.' ) + ).toBeHidden(); + } ); + + test( 'registered templates are available in the Swap template screen', async ( { + admin, + editor, + page, + } ) => { + // Create a post. + await admin.visitAdminPage( '/post-new.php' ); + await page.getByLabel( 'Close', { exact: true } ).click(); + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { content: 'User-created post.' }, + } ); + + // Swap template. + await page.getByRole( 'button', { name: 'Post' } ).click(); + await page.getByRole( 'button', { name: 'Template options' } ).click(); + await page.getByRole( 'menuitem', { name: 'Swap template' } ).click(); + await page.getByText( 'Plugin Template' ).click(); + + // Verify the template is applied. + const postId = await editor.publishPost(); + await page.goto( `?p=${ postId }` ); + await expect( + page.getByText( 'This is a plugin-registered template.' ) + ).toBeVisible(); + } ); + + test( 'themes can override registered templates', async ( { + admin, + editor, + page, + blockTemplateRegistrationUtils, + } ) => { + // Create a post. + await admin.visitAdminPage( '/post-new.php' ); + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { content: 'User-created post.' }, + } ); + + // Swap template. + await page.getByRole( 'button', { name: 'Post' } ).click(); + await page.getByRole( 'button', { name: 'Template options' } ).click(); + await page.getByRole( 'menuitem', { name: 'Swap template' } ).click(); + await page.getByText( 'Custom', { exact: true } ).click(); + + // Verify the theme template is applied. + const postId = await editor.publishPost(); + await page.goto( `?p=${ postId }` ); + await expect( + page.getByText( 'Custom template for Posts' ) + ).toBeVisible(); + await expect( + page.getByText( + 'This is a plugin-registered template and overridden by a theme.' + ) + ).toBeHidden(); + + // Verify the plugin-registered template doesn't appear in the Site Editor. + await admin.visitSiteEditor( { + postType: 'wp_template', + } ); + await blockTemplateRegistrationUtils.searchForTemplate( 'Custom' ); + await expect( + page.getByText( 'Custom Template (overridden by the theme)' ) + ).toBeHidden(); + // Verify the theme template shows the theme name as the author. + await expect( page.getByText( 'AuthorEmptytheme' ) ).toBeVisible(); + } ); + + test( 'templates can be deleted if the registered plugin is deactivated', async ( { + admin, + editor, + page, + requestUtils, + blockTemplateRegistrationUtils, + } ) => { + // Make an edit to the template. + await admin.visitSiteEditor( { + postType: 'wp_template', + } ); + await blockTemplateRegistrationUtils.searchForTemplate( + 'Plugin Template' + ); + await page.getByText( 'Plugin Template' ).click(); + await expect( + editor.canvas.getByText( 'This is a plugin-registered template.' ) + ).toBeVisible(); + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { content: 'User-customized template' }, + } ); + await editor.saveSiteEditorEntities( { + isOnlyCurrentEntityDirty: true, + } ); + + // Deactivate plugin. + await requestUtils.deactivatePlugin( + 'gutenberg-test-block-template-registration' + ); + + // Verify template can be deleted. + await admin.visitSiteEditor( { + postType: 'wp_template', + } ); + const deletedNotice = page + .getByLabel( 'Dismiss this notice' ) + .getByText( `"Plugin Template" deleted.` ); + const savedButton = page.getByRole( 'button', { + name: 'Saved', + } ); + await blockTemplateRegistrationUtils.searchForTemplate( + 'Plugin Template' + ); + const searchResults = page.getByLabel( 'Actions' ); + await searchResults.first().click(); + await page.getByRole( 'menuitem', { name: 'Delete' } ).click(); + await page.getByRole( 'button', { name: 'Delete' } ).click(); + + await expect( deletedNotice ).toBeVisible(); + await expect( savedButton ).toBeVisible(); + + // Expect template to no longer appear in the Site Editor. + await expect( page.getByLabel( 'Actions' ) ).toBeHidden(); + + // Reactivate plugin. + await requestUtils.activatePlugin( + 'gutenberg-test-block-template-registration' + ); + } ); + + test( 'registered templates can be unregistered', async ( { + admin, + page, + blockTemplateRegistrationUtils, + } ) => { + await admin.visitSiteEditor( { + postType: 'wp_template', + } ); + await blockTemplateRegistrationUtils.searchForTemplate( + 'Plugin Unregistered Template' + ); + await expect( + page.getByText( 'Plugin Unregistered Template' ) + ).toBeHidden(); + } ); + + test( 'WP default templates can be overridden by plugins', async ( { + page, + } ) => { + await page.goto( '?page_id=2' ); + await expect( + page.getByText( 'This is a plugin-registered page template.' ) + ).toBeVisible(); + } ); + + test( 'user-customized templates cannot be overridden by plugins', async ( { + admin, + editor, + page, + requestUtils, + blockTemplateRegistrationUtils, + } ) => { + await requestUtils.deactivatePlugin( + 'gutenberg-test-block-template-registration' + ); + + // Create an author template. + await admin.visitSiteEditor( { + postType: 'wp_template', + } ); + await page.getByLabel( 'Add New Template' ).click(); + await page.getByRole( 'button', { name: 'Author Archives' } ).click(); + await page + .getByRole( 'button', { name: 'Author For a specific item' } ) + .click(); + await page.getByRole( 'option', { name: 'admin' } ).click(); + await expect( page.getByText( 'Choose a pattern' ) ).toBeVisible(); + await page.getByLabel( 'Close', { exact: true } ).click(); + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { content: 'Author template customized by the user.' }, + } ); + await editor.saveSiteEditorEntities( { + isOnlyCurrentEntityDirty: true, + } ); + + await requestUtils.activatePlugin( + 'gutenberg-test-block-template-registration' + ); + + // Verify the template edited by the user has priority over the one registered by the theme. + await page.goto( '?author=1' ); + await expect( + page.getByText( 'Author template customized by the user.' ) + ).toBeVisible(); + await expect( + page.getByText( 'This is a plugin-registered author template.' ) + ).toBeHidden(); + + // Verify the template registered by the plugin is not visible in the Site Editor. + await admin.visitSiteEditor( { + postType: 'wp_template', + } ); + await blockTemplateRegistrationUtils.searchForTemplate( + 'Plugin Author Template' + ); + await expect( page.getByText( 'Plugin Author Template' ) ).toBeHidden(); + + // Reset the user-modified template. + const resetNotice = page + .getByLabel( 'Dismiss this notice' ) + .getByText( `"Author: Admin" reset.` ); + await page.getByPlaceholder( 'Search' ).fill( 'Author: admin' ); + await page.getByRole( 'link', { name: 'Author: Admin' } ).click(); + const actions = page.getByLabel( 'Actions' ); + await actions.first().click(); + await page.getByRole( 'menuitem', { name: 'Reset' } ).click(); + await page.getByRole( 'button', { name: 'Reset' } ).click(); + + await expect( resetNotice ).toBeVisible(); + + // Verify the template registered by the plugin is applied in the editor... + await expect( + editor.canvas.getByText( 'Author template customized by the user.' ) + ).toBeHidden(); + await expect( + editor.canvas.getByText( + 'This is a plugin-registered author template.' + ) + ).toBeVisible(); + + // ... and the frontend. + await page.goto( '?author=1' ); + await expect( + page.getByText( 'Author template customized by the user.' ) + ).toBeHidden(); + await expect( + page.getByText( 'This is a plugin-registered author template.' ) + ).toBeVisible(); + } ); +} ); + +class BlockTemplateRegistrationUtils { + constructor( { page } ) { + this.page = page; + } + + async searchForTemplate( searchTerm ) { + const searchResults = this.page.getByLabel( 'Actions' ); + await expect + .poll( async () => await searchResults.count() ) + .toBeGreaterThan( 0 ); + const initialSearchResultsCount = await searchResults.count(); + await this.page.getByPlaceholder( 'Search' ).fill( searchTerm ); + await expect + .poll( async () => await searchResults.count() ) + .toBeLessThan( initialSearchResultsCount ); + } +} From 7502c6a39ccb50df5fc1be7c11bac4d8e04aa48b Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:13:46 +0200 Subject: [PATCH 0369/1908] Fit items into 100% width (#64465) Fix long keys overflow in bindings panel Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/block-editor/src/hooks/block-bindings.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss index 73e7c490160d3e..603b2115623b8f 100644 --- a/packages/block-editor/src/hooks/block-bindings.scss +++ b/packages/block-editor/src/hooks/block-bindings.scss @@ -1,5 +1,5 @@ div.block-editor-bindings__panel { - grid-template-columns: auto; + grid-template-columns: repeat(auto-fit, minmax(100%, 1fr)); button:hover .block-editor-bindings__item-explanation { color: inherit; } From ea0bcf1ce1345afc840595040a6f4bf9be5faf9c Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 13 Aug 2024 12:35:17 +0200 Subject: [PATCH 0370/1908] DataViews Extensibility: Allow unregistering the view post revisions action (#64464) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/dataviews/src/types.ts | 6 +++ .../src/components/post-actions/actions.js | 40 +--------------- .../dataviews/actions/view-post-revisions.tsx | 47 +++++++++++++++++++ .../src/dataviews/store/private-actions.ts | 4 ++ packages/editor/src/dataviews/types.ts | 9 +++- 5 files changed, 66 insertions(+), 40 deletions(-) create mode 100644 packages/editor/src/dataviews/actions/view-post-revisions.tsx diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 7bbbc8cb863c09..fa5cec8d7d0320 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -426,6 +426,12 @@ interface ActionBase< Item > { * Whether the action can be used as a bulk action. */ supportsBulk?: boolean; + + /** + * The context in which the action is visible. + * This is only a "meta" information for now. + */ + context?: 'list' | 'single'; } export interface RenderModalProps< Item > { diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 627de5e8652e47..831a4f5349869b 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -2,10 +2,9 @@ * WordPress dependencies */ import { external } from '@wordpress/icons'; -import { addQueryArgs } from '@wordpress/url'; import { useDispatch, useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -import { __, sprintf } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; import { useMemo, useEffect } from '@wordpress/element'; /** @@ -31,40 +30,6 @@ const viewPostAction = { }, }; -const postRevisionsAction = { - id: 'view-post-revisions', - context: 'list', - label( items ) { - const revisionsCount = - items[ 0 ]._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0; - return sprintf( - /* translators: %s: number of revisions */ - __( 'View revisions (%s)' ), - revisionsCount - ); - }, - isEligible: ( post ) => { - if ( post.status === 'trash' ) { - return false; - } - const lastRevisionId = - post?._links?.[ 'predecessor-version' ]?.[ 0 ]?.id ?? null; - const revisionsCount = - post?._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0; - return lastRevisionId && revisionsCount > 1; - }, - callback( posts, { onActionPerformed } ) { - const post = posts[ 0 ]; - const href = addQueryArgs( 'revision.php', { - revision: post?._links?.[ 'predecessor-version' ]?.[ 0 ]?.id, - } ); - document.location.href = href; - if ( onActionPerformed ) { - onActionPerformed( posts ); - } - }, -}; - export function usePostActions( { postType, onActionPerformed, context } ) { const { defaultActions, postTypeObject } = useSelect( ( select ) => { @@ -84,7 +49,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { }, [ registerPostTypeActions, postType ] ); const isLoaded = !! postTypeObject; - const supportsRevisions = !! postTypeObject?.supports?.revisions; return useMemo( () => { if ( ! isLoaded ) { return []; @@ -92,7 +56,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { let actions = [ postTypeObject?.viewable && viewPostAction, - supportsRevisions && postRevisionsAction, ...defaultActions, ].filter( Boolean ); // Filter actions based on provided context. If not provided @@ -161,7 +124,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { postTypeObject?.viewable, onActionPerformed, isLoaded, - supportsRevisions, context, ] ); } diff --git a/packages/editor/src/dataviews/actions/view-post-revisions.tsx b/packages/editor/src/dataviews/actions/view-post-revisions.tsx new file mode 100644 index 00000000000000..875b925b94f070 --- /dev/null +++ b/packages/editor/src/dataviews/actions/view-post-revisions.tsx @@ -0,0 +1,47 @@ +/** + * WordPress dependencies + */ +import { addQueryArgs } from '@wordpress/url'; +import { __, sprintf } from '@wordpress/i18n'; +import type { Action } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import type { Post } from '../types'; + +const viewPostRevisions: Action< Post > = { + id: 'view-post-revisions', + context: 'list', + label( items ) { + const revisionsCount = + items[ 0 ]._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0; + return sprintf( + /* translators: %s: number of revisions */ + __( 'View revisions (%s)' ), + revisionsCount + ); + }, + isEligible( post ) { + if ( post.status === 'trash' ) { + return false; + } + const lastRevisionId = + post?._links?.[ 'predecessor-version' ]?.[ 0 ]?.id ?? null; + const revisionsCount = + post?._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0; + return !! lastRevisionId && revisionsCount > 1; + }, + callback( posts, { onActionPerformed } ) { + const post = posts[ 0 ]; + const href = addQueryArgs( 'revision.php', { + revision: post?._links?.[ 'predecessor-version' ]?.[ 0 ]?.id, + } ); + document.location.href = href; + if ( onActionPerformed ) { + onActionPerformed( posts ); + } + }, +}; + +export default viewPostRevisions; diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index d5b299b012e364..3ac121aea7393b 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -22,6 +22,7 @@ import type { PostType } from '../types'; import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; import duplicatePost from '../actions/duplicate-post'; +import viewPostRevisions from '../actions/view-post-revisions'; export function registerEntityAction< Item >( kind: string, @@ -88,6 +89,9 @@ export const registerPostTypeActions = .getCurrentTheme(); const actions = [ + !! postTypeConfig?.supports?.revisions + ? viewPostRevisions + : undefined, // @ts-ignore globalThis.IS_GUTENBERG_PLUGIN ? ! [ 'wp_template', 'wp_block', 'wp_template_part' ].includes( diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts index d207410ca2b6a5..e5886792fb9c33 100644 --- a/packages/editor/src/dataviews/types.ts +++ b/packages/editor/src/dataviews/types.ts @@ -14,6 +14,13 @@ export interface CommonPost { type: string; id: string | number; blocks?: Object[]; + _links?: Links; +} + +interface Links { + 'predecessor-version'?: { href: string; id: number }[]; + 'version-history'?: { href: string; count: number }[]; + [ key: string ]: { href: string }[] | undefined; } export interface BasePost extends CommonPost { @@ -27,7 +34,6 @@ export interface BasePost extends CommonPost { featured_media?: number; menu_order?: number; ping_status?: 'open' | 'closed'; - _links?: Record< string, { href: string }[] >; } export interface Template extends CommonPost { @@ -69,6 +75,7 @@ export interface PostType { supports?: { 'page-attributes'?: boolean; title?: boolean; + revisions?: boolean; }; } From 64643ed8727d915557c4bef65f247ab287d72465 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 13 Aug 2024 14:59:14 +0400 Subject: [PATCH 0371/1908] Block Editor: Refactor inner blocks appender components (#64470) * Block Editor: Refactor inner blocks appender components * Remove 'withClientId' HoC Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../inner-blocks/button-block-appender.js | 12 ++++----- .../inner-blocks/default-block-appender.js | 27 +++---------------- .../components/inner-blocks/with-client-id.js | 19 ------------- 3 files changed, 9 insertions(+), 49 deletions(-) delete mode 100644 packages/block-editor/src/components/inner-blocks/with-client-id.js diff --git a/packages/block-editor/src/components/inner-blocks/button-block-appender.js b/packages/block-editor/src/components/inner-blocks/button-block-appender.js index 500e59863db429..5bc788d58582f6 100644 --- a/packages/block-editor/src/components/inner-blocks/button-block-appender.js +++ b/packages/block-editor/src/components/inner-blocks/button-block-appender.js @@ -7,15 +7,15 @@ import clsx from 'clsx'; * Internal dependencies */ import BaseButtonBlockAppender from '../button-block-appender'; -import withClientId from './with-client-id'; +import { useBlockEditContext } from '../block-edit/context'; -export const ButtonBlockAppender = ( { - clientId, +export default function ButtonBlockAppender( { showSeparator, isFloating, onAddBlock, isToggle, -} ) => { +} ) { + const { clientId } = useBlockEditContext(); return ( <BaseButtonBlockAppender className={ clsx( { @@ -27,6 +27,4 @@ export const ButtonBlockAppender = ( { onAddBlock={ onAddBlock } /> ); -}; - -export default withClientId( ButtonBlockAppender ); +} diff --git a/packages/block-editor/src/components/inner-blocks/default-block-appender.js b/packages/block-editor/src/components/inner-blocks/default-block-appender.js index d2e137004d83bf..91e48a2854b513 100644 --- a/packages/block-editor/src/components/inner-blocks/default-block-appender.js +++ b/packages/block-editor/src/components/inner-blocks/default-block-appender.js @@ -1,29 +1,10 @@ -/** - * WordPress dependencies - */ -import { compose } from '@wordpress/compose'; -import { withSelect } from '@wordpress/data'; - /** * Internal dependencies */ import BaseDefaultBlockAppender from '../default-block-appender'; -import withClientId from './with-client-id'; -import { store as blockEditorStore } from '../../store'; +import { useBlockEditContext } from '../block-edit/context'; -export const DefaultBlockAppender = ( { clientId } ) => { +export default function DefaultBlockAppender() { + const { clientId } = useBlockEditContext(); return <BaseDefaultBlockAppender rootClientId={ clientId } />; -}; - -export default compose( [ - withClientId, - withSelect( ( select, { clientId } ) => { - const { getBlockOrder } = select( blockEditorStore ); - - const blockClientIds = getBlockOrder( clientId ); - - return { - lastBlockClientId: blockClientIds[ blockClientIds.length - 1 ], - }; - } ), -] )( DefaultBlockAppender ); +} diff --git a/packages/block-editor/src/components/inner-blocks/with-client-id.js b/packages/block-editor/src/components/inner-blocks/with-client-id.js deleted file mode 100644 index 97c73ae2803934..00000000000000 --- a/packages/block-editor/src/components/inner-blocks/with-client-id.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * WordPress dependencies - */ -import { createHigherOrderComponent } from '@wordpress/compose'; - -/** - * Internal dependencies - */ -import { useBlockEditContext } from '../block-edit/context'; - -const withClientId = createHigherOrderComponent( - ( WrappedComponent ) => ( props ) => { - const { clientId } = useBlockEditContext(); - return <WrappedComponent { ...props } clientId={ clientId } />; - }, - 'withClientId' -); - -export default withClientId; From e8b45dacc23052952e01b4869027c9354818d74a Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 13 Aug 2024 13:14:17 +0200 Subject: [PATCH 0372/1908] DataViews Extensibility: Allow unregistering the view post action (#64467) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/post-actions/actions.js | 43 ++----------------- .../src/dataviews/actions/view-post.tsx | 30 +++++++++++++ .../src/dataviews/store/private-actions.ts | 11 +++-- packages/editor/src/dataviews/types.ts | 2 + 4 files changed, 42 insertions(+), 44 deletions(-) create mode 100644 packages/editor/src/dataviews/actions/view-post.tsx diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 831a4f5349869b..e1c0ed1558193d 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -1,10 +1,7 @@ /** * WordPress dependencies */ -import { external } from '@wordpress/icons'; import { useDispatch, useSelect } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; -import { __ } from '@wordpress/i18n'; import { useMemo, useEffect } from '@wordpress/element'; /** @@ -13,30 +10,11 @@ import { useMemo, useEffect } from '@wordpress/element'; import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; -const viewPostAction = { - id: 'view-post', - label: __( 'View' ), - isPrimary: true, - icon: external, - isEligible( post ) { - return post.status !== 'trash'; - }, - callback( posts, { onActionPerformed } ) { - const post = posts[ 0 ]; - window.open( post.link, '_blank' ); - if ( onActionPerformed ) { - onActionPerformed( posts ); - } - }, -}; - export function usePostActions( { postType, onActionPerformed, context } ) { - const { defaultActions, postTypeObject } = useSelect( + const { defaultActions } = useSelect( ( select ) => { - const { getPostType } = select( coreStore ); const { getEntityActions } = unlock( select( editorStore ) ); return { - postTypeObject: getPostType( postType ), defaultActions: getEntityActions( 'postType', postType ), }; }, @@ -48,23 +26,14 @@ export function usePostActions( { postType, onActionPerformed, context } ) { registerPostTypeActions( postType ); }, [ registerPostTypeActions, postType ] ); - const isLoaded = !! postTypeObject; return useMemo( () => { - if ( ! isLoaded ) { - return []; - } - - let actions = [ - postTypeObject?.viewable && viewPostAction, - ...defaultActions, - ].filter( Boolean ); // Filter actions based on provided context. If not provided // all actions are returned. We'll have a single entry for getting the actions // and the consumer should provide the context to filter the actions, if needed. // Actions should also provide the `context` they support, if it's specific, to // compare with the provided context to get all the actions. // Right now the only supported context is `list`. - actions = actions.filter( ( action ) => { + const actions = defaultActions.filter( ( action ) => { if ( ! action.context ) { return true; } @@ -119,11 +88,5 @@ export function usePostActions( { postType, onActionPerformed, context } ) { } return actions; - }, [ - defaultActions, - postTypeObject?.viewable, - onActionPerformed, - isLoaded, - context, - ] ); + }, [ defaultActions, onActionPerformed, context ] ); } diff --git a/packages/editor/src/dataviews/actions/view-post.tsx b/packages/editor/src/dataviews/actions/view-post.tsx new file mode 100644 index 00000000000000..47eb1a66d019ad --- /dev/null +++ b/packages/editor/src/dataviews/actions/view-post.tsx @@ -0,0 +1,30 @@ +/** + * WordPress dependencies + */ +import { external } from '@wordpress/icons'; +import { __ } from '@wordpress/i18n'; +import type { Action } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../types'; + +const viewPost: Action< BasePost > = { + id: 'view-post', + label: __( 'View' ), + isPrimary: true, + icon: external, + isEligible( post ) { + return post.status !== 'trash'; + }, + callback( posts, { onActionPerformed } ) { + const post = posts[ 0 ]; + window.open( post?.link, '_blank' ); + if ( onActionPerformed ) { + onActionPerformed( posts ); + } + }, +}; + +export default viewPost; diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 3ac121aea7393b..a9101e57dd08b5 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -23,6 +23,7 @@ import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; import duplicatePost from '../actions/duplicate-post'; import viewPostRevisions from '../actions/view-post-revisions'; +import viewPost from '../actions/view-post'; export function registerEntityAction< Item >( kind: string, @@ -89,6 +90,7 @@ export const registerPostTypeActions = .getCurrentTheme(); const actions = [ + postTypeConfig.viewable ? viewPost : undefined, !! postTypeConfig?.supports?.revisions ? viewPostRevisions : undefined, @@ -101,9 +103,10 @@ export const registerPostTypeActions = duplicatePost : undefined, postTypeConfig.slug === 'wp_template_part' && - canCreate && - currentTheme?.is_block_theme && - duplicateTemplatePart, + canCreate && + currentTheme?.is_block_theme + ? duplicateTemplatePart + : undefined, canCreate && postTypeConfig.slug === 'wp_block' ? duplicatePattern : undefined, @@ -121,7 +124,7 @@ export const registerPostTypeActions = registry.batch( () => { actions.forEach( ( action ) => { - if ( action === undefined ) { + if ( ! action ) { return; } unlock( registry.dispatch( editorStore ) ).registerEntityAction( diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts index e5886792fb9c33..664c2dd417201c 100644 --- a/packages/editor/src/dataviews/types.ts +++ b/packages/editor/src/dataviews/types.ts @@ -34,6 +34,7 @@ export interface BasePost extends CommonPost { featured_media?: number; menu_order?: number; ping_status?: 'open' | 'closed'; + link?: string; } export interface Template extends CommonPost { @@ -72,6 +73,7 @@ export type PostWithPermissions = Post & { export interface PostType { slug: string; + viewable: boolean; supports?: { 'page-attributes'?: boolean; title?: boolean; From 3ec1ced865757f6568c42c126acb3478b25fe2be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:43:15 +0200 Subject: [PATCH 0373/1908] Add `status` to quick edit (#64398) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../src/components/post-edit/index.js | 29 +++++++++++++- .../src/components/post-fields/index.js | 40 +++++++++++++++---- 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 80304f16503705..0ec63589d97673 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -42,13 +42,38 @@ function PostEditForm( { postType, postId } ) { ); const [ multiEdits, setMultiEdits ] = useState( {} ); const { editEntityRecord } = useDispatch( coreDataStore ); - const { fields } = usePostFields(); + const { fields: _fields } = usePostFields(); + const fields = useMemo( + () => + _fields?.map( ( field ) => { + if ( field.id === 'status' ) { + return { + ...field, + elements: field.elements.filter( + ( element ) => element.value !== 'trash' + ), + }; + } + return field; + } ), + [ _fields ] + ); const form = { type: 'panel', - fields: [ 'title', 'author', 'date', 'comment_status' ], + fields: [ 'title', 'status', 'date', 'author', 'comment_status' ], }; const onChange = ( edits ) => { for ( const id of ids ) { + if ( + edits.status !== 'future' && + record.status === 'future' && + new Date( record.date ) > new Date() + ) { + edits.date = null; + } + if ( edits.status === 'private' && record.password ) { + edits.password = ''; + } editEntityRecord( 'postType', postType, id, edits ); if ( ids.length > 1 ) { setMultiEdits( ( prev ) => ( { diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index b03b2c6f5be3c4..9e59b23d61922d 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -42,11 +42,36 @@ import Media from '../media'; // See https://github.com/WordPress/gutenberg/issues/55886 // We do not support custom statutes at the moment. const STATUSES = [ - { value: 'draft', label: __( 'Draft' ), icon: drafts }, - { value: 'future', label: __( 'Scheduled' ), icon: scheduled }, - { value: 'pending', label: __( 'Pending Review' ), icon: pending }, - { value: 'private', label: __( 'Private' ), icon: notAllowed }, - { value: 'publish', label: __( 'Published' ), icon: published }, + { + value: 'draft', + label: __( 'Draft' ), + icon: drafts, + description: __( 'Not ready to publish.' ), + }, + { + value: 'future', + label: __( 'Scheduled' ), + icon: scheduled, + description: __( 'Publish automatically on a chosen date.' ), + }, + { + value: 'pending', + label: __( 'Pending Review' ), + icon: pending, + description: __( 'Waiting for review before publishing.' ), + }, + { + value: 'private', + label: __( 'Private' ), + icon: notAllowed, + description: __( 'Only visible to site admins and editors.' ), + }, + { + value: 'publish', + label: __( 'Published' ), + icon: published, + description: __( 'Visible to everyone.' ), + }, { value: 'trash', label: __( 'Trash' ), icon: trash }, ]; @@ -258,11 +283,10 @@ function usePostFields( viewType ) { { label: __( 'Status' ), id: 'status', - getValue: ( { item } ) => - STATUSES.find( ( { value } ) => value === item.status ) - ?.label ?? item.status, + type: 'text', elements: STATUSES, render: PostStatusField, + Edit: 'radio', enableSorting: false, filterBy: { operators: [ OPERATOR_IS_ANY ], From 9ca5628ed1cd11975086b25cd0cc318352b94619 Mon Sep 17 00:00:00 2001 From: JuanMa <juanma.garrido@automattic.com> Date: Tue, 13 Aug 2024 13:33:04 +0100 Subject: [PATCH 0374/1908] Fix tip link in DataViews docs (#64469) Co-authored-by: juanmaguitar <juanmaguitar@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- packages/dataviews/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 56cecedaef66ca..368880b69b14f0 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -30,8 +30,7 @@ const Example = () => { }; ``` -> [!TIP] -> At https://wordpress.github.io/gutenberg/?path=/docs/dataviews-dataviews--docs there's an example implementation of the Dataviews component." +<div class="callout callout-info">At <a href="https://wordpress.github.io/gutenberg/">WordPress Gutenberg's Storybook</a> there's and <a href="https://wordpress.github.io/gutenberg/?path=/docs/dataviews-dataviews--docs">example implementation of the Dataviews component</a></div> ## Properties From 02d052033868ea554bbdfee9b18b766e77128a6b Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 13 Aug 2024 17:18:12 +0400 Subject: [PATCH 0375/1908] Edit Post: Remove user pattern preloading (#64459) * Edit Post: Remove user pattern preloading * Update backport changelog Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- backport-changelog/6.7/7179.md | 1 + lib/compat/wordpress-6.7/rest-api.php | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/backport-changelog/6.7/7179.md b/backport-changelog/6.7/7179.md index f359b6610a94e6..a6e9cc4efe2cd0 100644 --- a/backport-changelog/6.7/7179.md +++ b/backport-changelog/6.7/7179.md @@ -1,3 +1,4 @@ https://github.com/WordPress/wordpress-develop/pull/7179 * https://github.com/WordPress/gutenberg/pull/64401 +* https://github.com/WordPress/gutenberg/pull/64459 diff --git a/lib/compat/wordpress-6.7/rest-api.php b/lib/compat/wordpress-6.7/rest-api.php index fe2aac9c2580ae..2520a06fbb18be 100644 --- a/lib/compat/wordpress-6.7/rest-api.php +++ b/lib/compat/wordpress-6.7/rest-api.php @@ -26,6 +26,24 @@ function gutenberg_block_editor_preload_paths_6_7( $paths, $context ) { } } + if ( 'core/edit-post' === $context->name ) { + $reusable_blocks_key = array_search( + add_query_arg( + array( + 'context' => 'edit', + 'per_page' => -1, + ), + rest_get_route_for_post_type_items( 'wp_block' ) + ), + $paths, + true + ); + + if ( false !== $parts_key ) { + unset( $paths[ $reusable_blocks_key ] ); + } + } + return $paths; } add_filter( 'block_editor_rest_api_preload_paths', 'gutenberg_block_editor_preload_paths_6_7', 10, 2 ); From cedbe111a2cc2b806356a985df1f47034b7545df Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Tue, 13 Aug 2024 17:55:15 +0300 Subject: [PATCH 0376/1908] Update the copy of quick edit tooltip (#64475) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/edit-site/src/components/post-list/index.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 35ecaaa8424fd4..bbfece24518495 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -366,11 +366,7 @@ export default function PostList( { postType } ) { size="compact" isPressed={ quickEdit } icon={ drawerRight } - label={ - ! quickEdit - ? __( 'Show quick edit sidebar' ) - : __( 'Close quick edit sidebar' ) - } + label={ __( 'Toggle details panel' ) } onClick={ () => { history.push( { ...location.params, From b3ce94ea25990e329ce4c08f3d49eb07e7ec929b Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Tue, 13 Aug 2024 18:40:08 +0300 Subject: [PATCH 0377/1908] Edit Post: Fix user pattern preloading filter (#64477) * Edit Post: Fix user pattern preloading filter * Backport changelog Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- backport-changelog/6.7/7179.md | 1 + lib/compat/wordpress-6.7/rest-api.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backport-changelog/6.7/7179.md b/backport-changelog/6.7/7179.md index a6e9cc4efe2cd0..d777eace2cb05e 100644 --- a/backport-changelog/6.7/7179.md +++ b/backport-changelog/6.7/7179.md @@ -2,3 +2,4 @@ https://github.com/WordPress/wordpress-develop/pull/7179 * https://github.com/WordPress/gutenberg/pull/64401 * https://github.com/WordPress/gutenberg/pull/64459 +* https://github.com/WordPress/gutenberg/pull/64477 diff --git a/lib/compat/wordpress-6.7/rest-api.php b/lib/compat/wordpress-6.7/rest-api.php index 2520a06fbb18be..081c22c8102914 100644 --- a/lib/compat/wordpress-6.7/rest-api.php +++ b/lib/compat/wordpress-6.7/rest-api.php @@ -39,7 +39,7 @@ function gutenberg_block_editor_preload_paths_6_7( $paths, $context ) { true ); - if ( false !== $parts_key ) { + if ( false !== $reusable_blocks_key ) { unset( $paths[ $reusable_blocks_key ] ); } } From 5dae25b15e82a59d28c6c065b5a3745f3f83980f Mon Sep 17 00:00:00 2001 From: Jan Pfeil <jan.pfeil@rypox.net> Date: Tue, 13 Aug 2024 18:40:35 +0200 Subject: [PATCH 0378/1908] fix typo in block-wrapper.md (#64447) --- docs/getting-started/fundamentals/block-wrapper.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/fundamentals/block-wrapper.md b/docs/getting-started/fundamentals/block-wrapper.md index 39c80262d7bcbe..98c435f6ebe2f7 100644 --- a/docs/getting-started/fundamentals/block-wrapper.md +++ b/docs/getting-started/fundamentals/block-wrapper.md @@ -102,7 +102,7 @@ The [example block](https://github.com/WordPress/block-development-examples/tree ## Dynamic render markup -In dynamic blocks, where the font-end markup is rendered server-side, you can utilize the [`get_block_wrapper_attributes()`](https://developer.wordpress.org/reference/functions/get_block_wrapper_attributes/) function to output the necessary classes and attributes just like you would use `useBlockProps.save()` in the `save` function. (See [example](https://github.com/WordPress/block-development-examples/blob/f68640f42d993f0866d1879f67c73910285ca114/plugins/block-dynamic-rendering-64756b/src/render.php#L11)) +In dynamic blocks, where the front-end markup is rendered server-side, you can utilize the [`get_block_wrapper_attributes()`](https://developer.wordpress.org/reference/functions/get_block_wrapper_attributes/) function to output the necessary classes and attributes just like you would use `useBlockProps.save()` in the `save` function. (See [example](https://github.com/WordPress/block-development-examples/blob/f68640f42d993f0866d1879f67c73910285ca114/plugins/block-dynamic-rendering-64756b/src/render.php#L11)) ```php <p <?php echo get_block_wrapper_attributes(); ?>> From 3be25a1db5915a94fe755f078ed35b63ebf7cc91 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Tue, 13 Aug 2024 20:52:40 +0100 Subject: [PATCH 0379/1908] Apply minimal variant to pagination dropdown (#63815) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../components/dataviews-pagination/index.tsx | 51 +++++++++++++------ .../dataviews-pagination/style.scss | 13 +++-- 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-pagination/index.tsx b/packages/dataviews/src/components/dataviews-pagination/index.tsx index f8ebf41469d949..f022b382cdb70d 100644 --- a/packages/dataviews/src/components/dataviews-pagination/index.tsx +++ b/packages/dataviews/src/components/dataviews-pagination/index.tsx @@ -21,10 +21,31 @@ function DataViewsPagination() { onChangeView, paginationInfo: { totalItems = 0, totalPages }, } = useContext( DataViewsContext ); + if ( ! totalItems || ! totalPages ) { return null; } + const currentPage = view.page ?? 1; + const pageSelectOptions = Array.from( Array( totalPages ) ).map( + ( _, i ) => { + const page = i + 1; + return { + value: page.toString(), + label: page.toString(), + 'aria-label': + currentPage === page + ? sprintf( + // translators: Current page number in total number of pages + __( 'Page %1$s of %2$s' ), + currentPage, + totalPages + ) + : page.toString(), + }; + } + ); + return ( !! totalItems && totalPages !== 1 && ( @@ -37,37 +58,35 @@ function DataViewsPagination() { <HStack justify="flex-start" expanded={ false } - spacing={ 2 } - className="dataviews-pagination__page-selection" + spacing={ 1 } + className="dataviews-pagination__page-select" > { createInterpolateElement( sprintf( - // translators: %s: Total number of pages. - _x( 'Page <CurrentPageControl /> of %s', 'paging' ), + // translators: 1: Current page number, 2: Total number of pages. + _x( + '<div>Page</div>%1$s<div>of %2$s</div>', + 'paging' + ), + '<CurrentPage />', totalPages ), { - CurrentPageControl: ( + div: <div aria-hidden />, + CurrentPage: ( <SelectControl aria-label={ __( 'Current page' ) } - value={ view.page?.toString() } - options={ Array.from( - Array( totalPages ) - ).map( ( _, i ) => { - const page = i + 1; - return { - value: page.toString(), - label: page.toString(), - }; - } ) } + value={ currentPage.toString() } + options={ pageSelectOptions } onChange={ ( newValue ) => { onChangeView( { ...view, page: +newValue, } ); } } - size="compact" + size="small" __nextHasNoMarginBottom + variant="minimal" /> ), } diff --git a/packages/dataviews/src/components/dataviews-pagination/style.scss b/packages/dataviews/src/components/dataviews-pagination/style.scss index 4e754ab90fa54a..16f064cc3a5178 100644 --- a/packages/dataviews/src/components/dataviews-pagination/style.scss +++ b/packages/dataviews/src/components/dataviews-pagination/style.scss @@ -5,17 +5,22 @@ background-color: $white; padding: $grid-unit-15 $grid-unit-60; border-top: $border-width solid $gray-100; - color: $gray-700; flex-shrink: 0; transition: padding ease-out 0.1s; @include reduce-motion("transition"); } -.dataviews-pagination__page-selection { +.dataviews-pagination__page-select { font-size: 11px; - text-transform: uppercase; font-weight: 500; - color: $gray-900; + text-transform: uppercase; + + @include break-small() { + .components-select-control__input { + font-size: 11px !important; + font-weight: 500; + } + } } /* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ From 562fff19e73a1416bdc533ef372b8117beeed436 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 14 Aug 2024 04:53:08 +0900 Subject: [PATCH 0380/1908] Start adding lint rules for 40px default size (#64410) * Start adding lint rules for 40px default size * Make stricter Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .eslintrc.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index 6143d62c28bc07..0dc184eabb8b04 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -278,7 +278,6 @@ module.exports = { }, }, { - // Temporary rules until we're ready to officially deprecate the bottom margins. files: [ 'packages/*/src/**/*.[tj]s?(x)' ], excludedFiles: [ 'packages/components/src/**/@(test|stories)/**', @@ -289,6 +288,7 @@ module.exports = { 'error', ...restrictedSyntax, ...restrictedSyntaxComponents, + // Temporary rules until we're ready to officially deprecate the bottom margins. ...[ 'BaseControl', 'CheckboxControl', @@ -309,6 +309,19 @@ module.exports = { componentName + ' should have the `__nextHasNoMarginBottom` prop to opt-in to the new margin-free styles.', } ) ), + // Temporary rules until we're ready to officially default to the new size. + ...[ + 'BorderBoxControl', + 'BorderControl', + 'DimensionControl', + 'FontSizePicker', + ].map( ( componentName ) => ( { + // Falsy `__next40pxDefaultSize` without a non-default `size` prop. + selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"][value.expression.value!=false])):not(:has(JSXAttribute[name.name="size"][value.value!="default"]))`, + message: + componentName + + ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', + } ) ), ], }, }, From 40b51b8619e120c96c3dfc6844ed72f3c84e2ca4 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 14 Aug 2024 05:28:37 +0900 Subject: [PATCH 0381/1908] QueryControls: Default to new 40px size (#64457) * QueryControls: Default to new 40px size * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/query-controls/index.tsx | 11 +++++------ packages/components/src/query-controls/types.ts | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 761e6604a127a2..6b95e23818c864 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -11,6 +11,7 @@ ### Enhancements - `Composite`: improve Storybook examples and add interactive controls ([#64397](https://github.com/WordPress/gutenberg/pull/64397)). +- `QueryControls`: Default to new 40px size ([#64457](https://github.com/WordPress/gutenberg/pull/64457)). - `TimePicker`: add `hideLabelFromVision` prop ([#64267](https://github.com/WordPress/gutenberg/pull/64267)). - `DropdownMenuV2`: adopt elevation scale ([#64432](https://github.com/WordPress/gutenberg/pull/64432)). diff --git a/packages/components/src/query-controls/index.tsx b/packages/components/src/query-controls/index.tsx index 3557335ebac5a0..452dd303c778bb 100644 --- a/packages/components/src/query-controls/index.tsx +++ b/packages/components/src/query-controls/index.tsx @@ -60,7 +60,6 @@ function isMultipleCategorySelection( * ``` */ export function QueryControls( { - __next40pxDefaultSize = false, authorList, selectedAuthorId, numberOfItems, @@ -82,7 +81,7 @@ export function QueryControls( { onOrderChange && onOrderByChange && ( <SelectControl __nextHasNoMarginBottom - __next40pxDefaultSize={ __next40pxDefaultSize } + __next40pxDefaultSize key="query-controls-order-select" label={ __( 'Order by' ) } value={ @@ -137,7 +136,7 @@ export function QueryControls( { props.categoriesList && props.onCategoryChange && ( <CategorySelect - __next40pxDefaultSize={ __next40pxDefaultSize } + __next40pxDefaultSize key="query-controls-category-select" categoriesList={ props.categoriesList } label={ __( 'Category' ) } @@ -150,7 +149,7 @@ export function QueryControls( { props.categorySuggestions && props.onCategoryChange && ( <FormTokenField - __next40pxDefaultSize={ __next40pxDefaultSize } + __next40pxDefaultSize __nextHasNoMarginBottom key="query-controls-categories-select" label={ __( 'Categories' ) } @@ -174,7 +173,7 @@ export function QueryControls( { ), onAuthorChange && ( <AuthorSelect - __next40pxDefaultSize={ __next40pxDefaultSize } + __next40pxDefaultSize key="query-controls-author-select" authorList={ authorList } label={ __( 'Author' ) } @@ -186,7 +185,7 @@ export function QueryControls( { onNumberOfItemsChange && ( <RangeControl __nextHasNoMarginBottom - __next40pxDefaultSize={ __next40pxDefaultSize } + __next40pxDefaultSize key="query-controls-range-control" label={ __( 'Number of items' ) } value={ numberOfItems } diff --git a/packages/components/src/query-controls/types.ts b/packages/components/src/query-controls/types.ts index 8c45d22c54c064..eb004bf8215b0a 100644 --- a/packages/components/src/query-controls/types.ts +++ b/packages/components/src/query-controls/types.ts @@ -107,7 +107,8 @@ type BaseQueryControlsProps = { * Start opting into the larger default height that will become the * default size in a future version. * - * @default false + * @deprecated Default behavior since WP 6.7. Prop can be safely removed. + * @ignore */ __next40pxDefaultSize?: boolean; }; From 898f59721160a8ea9448f73e2c2c4843baceffac Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 14 Aug 2024 06:32:10 +0900 Subject: [PATCH 0382/1908] TextControl: Add lint rule for 40px size prop usage (#64455) * TextControl: Add lint rule for 40px size prop usage * Fixup * Fixup formatting Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .eslintrc.js | 8 ++++++++ .../src/components/date-format-picker/index.js | 2 ++ .../src/components/media-upload/index.native.js | 2 ++ .../src/components/url-popover/image-url-input-ui.js | 4 ++++ packages/block-library/src/button/edit.js | 2 ++ packages/block-library/src/form-input/edit.js | 2 ++ packages/block-library/src/form/edit.js | 2 ++ packages/block-library/src/image/image.js | 2 ++ .../src/navigation/edit/navigation-menu-name-control.js | 2 ++ packages/block-library/src/post-comment/edit.js | 2 ++ packages/block-library/src/post-featured-image/edit.js | 2 ++ packages/block-library/src/post-terms/edit.js | 2 ++ packages/block-library/src/post-title/edit.js | 2 ++ packages/block-library/src/social-link/edit.js | 4 ++++ .../src/template-part/edit/advanced-controls.js | 2 ++ packages/block-library/src/video/tracks-editor.js | 4 ++++ .../src/components/sidebar-dataviews/add-new-view.js | 2 ++ .../components/sidebar-dataviews/custom-dataviews-list.js | 2 ++ .../src/components/post-publish-panel/postpublish.js | 2 ++ packages/editor/src/components/post-slug/index.js | 2 ++ .../post-taxonomies/hierarchical-term-selector.js | 2 ++ .../reusable-block-convert-button.js | 2 ++ 22 files changed, 56 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index 0dc184eabb8b04..eb2d2db47e4cab 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -322,6 +322,14 @@ module.exports = { componentName + ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', } ) ), + // Temporary rules until all existing components have the `__next40pxDefaultSize` prop. + ...[ 'TextControl' ].map( ( componentName ) => ( { + // Not strict. Allows pre-existing __next40pxDefaultSize={ false } usage until they are all manually updated. + selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"])):not(:has(JSXAttribute[name.name="size"]))`, + message: + componentName + + ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', + } ) ), ], }, }, diff --git a/packages/block-editor/src/components/date-format-picker/index.js b/packages/block-editor/src/components/date-format-picker/index.js index 15beec4ac6ed54..63c977b111e01c 100644 --- a/packages/block-editor/src/components/date-format-picker/index.js +++ b/packages/block-editor/src/components/date-format-picker/index.js @@ -149,6 +149,8 @@ function NonDefaultControls( { format, onChange } ) { /> { isCustom && ( <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Custom format' ) } hideLabelFromVision diff --git a/packages/block-editor/src/components/media-upload/index.native.js b/packages/block-editor/src/components/media-upload/index.native.js index 05a36d7a09bcab..c4871d48ebe129 100644 --- a/packages/block-editor/src/components/media-upload/index.native.js +++ b/packages/block-editor/src/components/media-upload/index.native.js @@ -327,6 +327,8 @@ function URLInput( props ) { > <PanelBody style={ styles[ 'media-upload__link-input' ] }> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus autoCapitalize="none" diff --git a/packages/block-editor/src/components/url-popover/image-url-input-ui.js b/packages/block-editor/src/components/url-popover/image-url-input-ui.js index 8209ff1939f091..c19021c52356f5 100644 --- a/packages/block-editor/src/components/url-popover/image-url-input-ui.js +++ b/packages/block-editor/src/components/url-popover/image-url-input-ui.js @@ -227,12 +227,16 @@ const ImageURLInputUI = ( { checked={ linkTarget === '_blank' } /> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Link rel' ) } value={ rel ?? '' } onChange={ onSetLinkRel } /> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Link CSS class' ) } value={ linkClass || '' } diff --git a/packages/block-library/src/button/edit.js b/packages/block-library/src/button/edit.js index 3b2bb562e63c06..d9f8acc91e4c8e 100644 --- a/packages/block-library/src/button/edit.js +++ b/packages/block-library/src/button/edit.js @@ -380,6 +380,8 @@ function ButtonEdit( props ) { <InspectorControls group="advanced"> { isLinkTag && ( <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Link rel' ) } value={ rel || '' } diff --git a/packages/block-library/src/form-input/edit.js b/packages/block-library/src/form-input/edit.js index 856d09d3945e64..fb84b0465b8402 100644 --- a/packages/block-library/src/form-input/edit.js +++ b/packages/block-library/src/form-input/edit.js @@ -63,6 +63,8 @@ function InputFieldBlock( { attributes, setAttributes, className } ) { ) } <InspectorControls group="advanced"> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom autoComplete="off" label={ __( 'Name' ) } diff --git a/packages/block-library/src/form/edit.js b/packages/block-library/src/form/edit.js index 2738644878660a..d6f9d80f155c38 100644 --- a/packages/block-library/src/form/edit.js +++ b/packages/block-library/src/form/edit.js @@ -145,6 +145,8 @@ const Edit = ( { attributes, setAttributes, clientId } ) => { ) } /> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom autoComplete="off" label={ __( 'Form action' ) } diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 7dd03a7fb5837c..0623d576e75aec 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -690,6 +690,8 @@ export default function Image( { ) } renderContent={ () => ( <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="wp-block-image__toolbar_content_textarea" __nextHasNoMarginBottom label={ __( 'Title attribute' ) } diff --git a/packages/block-library/src/navigation/edit/navigation-menu-name-control.js b/packages/block-library/src/navigation/edit/navigation-menu-name-control.js index fe1075f0044070..97a97d7763fc72 100644 --- a/packages/block-library/src/navigation/edit/navigation-menu-name-control.js +++ b/packages/block-library/src/navigation/edit/navigation-menu-name-control.js @@ -14,6 +14,8 @@ export default function NavigationMenuNameControl() { return ( <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Menu name' ) } value={ title } diff --git a/packages/block-library/src/post-comment/edit.js b/packages/block-library/src/post-comment/edit.js index 54ad72be30d7c0..f6abb5ff60c68e 100644 --- a/packages/block-library/src/post-comment/edit.js +++ b/packages/block-library/src/post-comment/edit.js @@ -34,6 +34,8 @@ export default function Edit( { attributes: { commentId }, setAttributes } ) { ) } > <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom value={ commentId } onChange={ ( val ) => diff --git a/packages/block-library/src/post-featured-image/edit.js b/packages/block-library/src/post-featured-image/edit.js index c9f4645e5e8654..675580c71c1d7b 100644 --- a/packages/block-library/src/post-featured-image/edit.js +++ b/packages/block-library/src/post-featured-image/edit.js @@ -230,6 +230,8 @@ export default function PostFeaturedImageEdit( { checked={ linkTarget === '_blank' } /> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Link rel' ) } value={ rel } diff --git a/packages/block-library/src/post-terms/edit.js b/packages/block-library/src/post-terms/edit.js index b822e457ffcaeb..0403a1d1406bd3 100644 --- a/packages/block-library/src/post-terms/edit.js +++ b/packages/block-library/src/post-terms/edit.js @@ -83,6 +83,8 @@ export default function PostTermsEdit( { </BlockControls> <InspectorControls group="advanced"> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom autoComplete="off" label={ __( 'Separator' ) } diff --git a/packages/block-library/src/post-title/edit.js b/packages/block-library/src/post-title/edit.js index e9b45e2a642a61..abd52febd1882b 100644 --- a/packages/block-library/src/post-title/edit.js +++ b/packages/block-library/src/post-title/edit.js @@ -162,6 +162,8 @@ export default function PostTitleEdit( { checked={ linkTarget === '_blank' } /> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Link rel' ) } value={ rel } diff --git a/packages/block-library/src/social-link/edit.js b/packages/block-library/src/social-link/edit.js index 8f372a73ea6c9d..39e3803982f48b 100644 --- a/packages/block-library/src/social-link/edit.js +++ b/packages/block-library/src/social-link/edit.js @@ -139,6 +139,8 @@ const SocialLinkEdit = ( { <PanelBody title={ __( 'Settings' ) }> <PanelRow> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Text' ) } help={ __( @@ -155,6 +157,8 @@ const SocialLinkEdit = ( { </InspectorControls> <InspectorControls group="advanced"> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Link rel' ) } value={ rel || '' } diff --git a/packages/block-library/src/template-part/edit/advanced-controls.js b/packages/block-library/src/template-part/edit/advanced-controls.js index 44562c472dd4f6..79a3a158b87ea0 100644 --- a/packages/block-library/src/template-part/edit/advanced-controls.js +++ b/packages/block-library/src/template-part/edit/advanced-controls.js @@ -73,6 +73,8 @@ export function TemplatePartAdvancedControls( { { isEntityAvailable && ( <> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Title' ) } value={ title } diff --git a/packages/block-library/src/video/tracks-editor.js b/packages/block-library/src/video/tracks-editor.js index 366d521f5aa625..3864722c7a7794 100644 --- a/packages/block-library/src/video/tracks-editor.js +++ b/packages/block-library/src/video/tracks-editor.js @@ -99,6 +99,8 @@ function SingleTrackEditor( { track, onChange, onClose, onRemove } ) { </span> <Grid columns={ 2 } gap={ 4 }> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom /* eslint-disable jsx-a11y/no-autofocus */ autoFocus @@ -114,6 +116,8 @@ function SingleTrackEditor( { track, onChange, onClose, onRemove } ) { help={ __( 'Title of track' ) } /> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom onChange={ ( newSrcLang ) => onChange( { diff --git a/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js b/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js index aabb49c14a2ff7..69cca49fd84563 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js +++ b/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js @@ -78,6 +78,8 @@ function AddNewItemModalContent( { type, setIsAdding } ) { > <VStack spacing="5"> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Name' ) } value={ title } diff --git a/packages/edit-site/src/components/sidebar-dataviews/custom-dataviews-list.js b/packages/edit-site/src/components/sidebar-dataviews/custom-dataviews-list.js index f033c932c59e12..cab5b0d31fa2ed 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/custom-dataviews-list.js +++ b/packages/edit-site/src/components/sidebar-dataviews/custom-dataviews-list.js @@ -51,6 +51,8 @@ function RenameItemModalContent( { dataviewId, currentTitle, setIsRenaming } ) { > <VStack spacing="5"> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Name' ) } value={ title } diff --git a/packages/editor/src/components/post-publish-panel/postpublish.js b/packages/editor/src/components/post-publish-panel/postpublish.js index 39f48d3bc811c4..fdc1194527f5f7 100644 --- a/packages/editor/src/components/post-publish-panel/postpublish.js +++ b/packages/editor/src/components/post-publish-panel/postpublish.js @@ -122,6 +122,8 @@ class PostPublishPanelPostpublish extends Component { </p> <div className="post-publish-panel__postpublish-post-address-container"> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom className="post-publish-panel__postpublish-post-address" readOnly diff --git a/packages/editor/src/components/post-slug/index.js b/packages/editor/src/components/post-slug/index.js index cc86405157b88f..adabac2f18b0bd 100644 --- a/packages/editor/src/components/post-slug/index.js +++ b/packages/editor/src/components/post-slug/index.js @@ -24,6 +24,8 @@ function PostSlugControl() { return ( <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Slug' ) } autoComplete="off" diff --git a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js index 79039d0a5d0d25..c711268a91e631 100644 --- a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js +++ b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js @@ -407,6 +407,8 @@ export function HierarchicalTermSelector( { slug } ) { <Flex direction="column" gap="4"> { showFilter && ( <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ filterLabel } value={ filterValue } diff --git a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js index 21f3d0a61be042..b6f30e24a2fdb3 100644 --- a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js +++ b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js @@ -169,6 +169,8 @@ export default function ReusableBlockConvertButton( { > <VStack spacing="5"> <TextControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Name' ) } value={ title } From 46f9fe0f31bf9ce5f6210cad96074206e90527e6 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 14 Aug 2024 07:15:24 +0900 Subject: [PATCH 0383/1908] Deprecate bottom margin on BaseControl-based components (#64408) * BaseControl: Deprecate bottom margin * Propagate to components * Missed spots * Add changelog * List all affected components in changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 17 ++++++++++ .../components/src/base-control/index.tsx | 13 +++++++ packages/components/src/base-control/types.ts | 7 ++++ .../components/src/checkbox-control/index.tsx | 1 + .../checkbox-control/stories/index.story.tsx | 1 + .../src/checkbox-control/test/index.tsx | 9 ++++- .../components/src/combobox-control/index.tsx | 1 + .../combobox-control/stories/index.story.tsx | 7 ++-- .../src/combobox-control/test/index.tsx | 6 +++- .../src/dimension-control/index.tsx | 34 +++++++++++++------ .../dimension-control/stories/index.story.tsx | 1 + .../test/__snapshots__/index.test.js.snap | 16 --------- .../src/dimension-control/test/index.test.js | 6 +++- .../src/focal-point-picker/index.tsx | 1 + .../stories/index.story.tsx | 3 ++ .../src/focal-point-picker/test/index.tsx | 6 +++- .../components/src/range-control/index.tsx | 1 + .../src/range-control/stories/index.story.tsx | 7 ++++ .../src/range-control/test/index.tsx | 8 ++++- .../components/src/search-control/index.tsx | 11 +++--- .../search-control/stories/index.story.tsx | 1 + .../src/search-control/test/index.tsx | 1 + .../components/src/select-control/index.tsx | 1 + .../select-control/stories/index.story.tsx | 13 ++++--- .../select-control/test/select-control.tsx | 18 ++++++---- .../components/src/text-control/index.tsx | 1 + .../src/text-control/stories/index.story.tsx | 4 ++- .../src/text-control/test/text-control.tsx | 6 +++- .../components/src/textarea-control/index.tsx | 1 + .../textarea-control/stories/index.story.tsx | 1 + .../components/src/toggle-control/index.tsx | 9 +++++ .../toggle-control/stories/index.story.tsx | 1 + .../src/toggle-control/test/index.tsx | 8 ++++- .../test/__snapshots__/index.tsx.snap | 16 --------- .../src/toggle-group-control/test/index.tsx | 6 +++- .../toggle-group-control/component.tsx | 1 + packages/components/src/tree-select/index.tsx | 21 +++++++++--- .../src/tree-select/stories/index.story.tsx | 1 + 38 files changed, 191 insertions(+), 75 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 6b95e23818c864..36b1c8fcc55d00 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,23 @@ ## Unreleased +### Deprecations + +- Deprecate bottom margin on the following `BaseControl`-based components. Set the `__nextHasNoMarginBottom` prop to true to start opting into the new styles, which will become the default in a future version ([#64408](https://github.com/WordPress/gutenberg/pull/64408)). + - `BaseControl` + - `CheckboxControl` + - `ComboboxControl` + - `DimensionControl` + - `FocalPointPicker` + - `RangeControl` + - `SearchControl` + - `SelectControl` + - `TextControl` + - `TextareaControl` + - `ToggleControl` + - `ToggleGroupControl` + - `TreeSelect` + ### New Features - `Composite`: add stable version of the component ([#63564](https://github.com/WordPress/gutenberg/pull/63564)). diff --git a/packages/components/src/base-control/index.tsx b/packages/components/src/base-control/index.tsx index 77899b6480daed..423636a92cd5f0 100644 --- a/packages/components/src/base-control/index.tsx +++ b/packages/components/src/base-control/index.tsx @@ -7,6 +7,7 @@ import type { ForwardedRef } from 'react'; /** * WordPress dependencies */ +import deprecated from '@wordpress/deprecated'; import { forwardRef } from '@wordpress/element'; /** @@ -31,6 +32,7 @@ const UnconnectedBaseControl = ( ) => { const { __nextHasNoMarginBottom = false, + __associatedWPComponentName = 'BaseControl', id, label, hideLabelFromVision = false, @@ -39,6 +41,17 @@ const UnconnectedBaseControl = ( children, } = useContextSystem( props, 'BaseControl' ); + if ( ! __nextHasNoMarginBottom ) { + deprecated( + `Bottom margin styles for wp.components.${ __associatedWPComponentName }`, + { + since: '6.7', + version: '7.0', + hint: 'Set the `__nextHasNoMarginBottom` prop to true to start opting into the new styles, which will become the default in a future version.', + } + ); + } + return ( <Wrapper className={ className }> <StyledField diff --git a/packages/components/src/base-control/types.ts b/packages/components/src/base-control/types.ts index 07a358d09c14b4..e4c838459209c4 100644 --- a/packages/components/src/base-control/types.ts +++ b/packages/components/src/base-control/types.ts @@ -10,6 +10,13 @@ export type BaseControlProps = { * @default false */ __nextHasNoMarginBottom?: boolean; + /** + * Temporary private prop for showing better deprecation messages, + * e.g. `Some feature from wp.components.${ __associatedWPControl } is deprecated`. + * + * @ignore + */ + __associatedWPComponentName?: string; /** * The HTML `id` of the control element (passed in as a child to `BaseControl`) to which labels and help text are being generated. * This is necessary to accessibly associate the label with that element. diff --git a/packages/components/src/checkbox-control/index.tsx b/packages/components/src/checkbox-control/index.tsx index 51e232d97847a9..a24d1abaab45a7 100644 --- a/packages/components/src/checkbox-control/index.tsx +++ b/packages/components/src/checkbox-control/index.tsx @@ -95,6 +95,7 @@ export function CheckboxControl( return ( <BaseControl __nextHasNoMarginBottom={ __nextHasNoMarginBottom } + __associatedWPComponentName="CheckboxControl" label={ heading } id={ id } help={ diff --git a/packages/components/src/checkbox-control/stories/index.story.tsx b/packages/components/src/checkbox-control/stories/index.story.tsx index 2dbc14c8cde111..3c55ba3192a3cf 100644 --- a/packages/components/src/checkbox-control/stories/index.story.tsx +++ b/packages/components/src/checkbox-control/stories/index.story.tsx @@ -59,6 +59,7 @@ export const Default: StoryFn< typeof CheckboxControl > = DefaultTemplate.bind( {} ); Default.args = { + __nextHasNoMarginBottom: true, label: 'Is author', help: 'Is the user an author or not?', }; diff --git a/packages/components/src/checkbox-control/test/index.tsx b/packages/components/src/checkbox-control/test/index.tsx index 899a9b100015b3..547f479184e862 100644 --- a/packages/components/src/checkbox-control/test/index.tsx +++ b/packages/components/src/checkbox-control/test/index.tsx @@ -20,13 +20,20 @@ const noop = () => {}; const getInput = () => screen.getByRole( 'checkbox' ) as HTMLInputElement; const CheckboxControl = ( props: Omit< CheckboxControlProps, 'onChange' > ) => { - return <BaseCheckboxControl onChange={ noop } { ...props } />; + return ( + <BaseCheckboxControl + onChange={ noop } + { ...props } + __nextHasNoMarginBottom + /> + ); }; const ControlledCheckboxControl = ( { onChange }: CheckboxControlProps ) => { const [ isChecked, setChecked ] = useState( false ); return ( <BaseCheckboxControl + __nextHasNoMarginBottom checked={ isChecked } onChange={ ( value ) => { setChecked( value ); diff --git a/packages/components/src/combobox-control/index.tsx b/packages/components/src/combobox-control/index.tsx index e3b1434be8c7c2..fc3ecccf0b6599 100644 --- a/packages/components/src/combobox-control/index.tsx +++ b/packages/components/src/combobox-control/index.tsx @@ -320,6 +320,7 @@ function ComboboxControl( props: ComboboxControlProps ) { <DetectOutside onFocusOutside={ onFocusOutside }> <BaseControl __nextHasNoMarginBottom={ __nextHasNoMarginBottom } + __associatedWPComponentName="ComboboxControl" className={ clsx( className, 'components-combobox-control' ) } label={ label } id={ `components-form-token-input-${ instanceId }` } diff --git a/packages/components/src/combobox-control/stories/index.story.tsx b/packages/components/src/combobox-control/stories/index.story.tsx index 0f45c8a54a2ee3..516cd262fd5aa6 100644 --- a/packages/components/src/combobox-control/stories/index.story.tsx +++ b/packages/components/src/combobox-control/stories/index.story.tsx @@ -76,6 +76,7 @@ const Template: StoryFn< typeof ComboboxControl > = ( { }; export const Default = Template.bind( {} ); Default.args = { + __nextHasNoMarginBottom: true, allowReset: false, label: 'Select a country', options: countryOptions, @@ -135,8 +136,7 @@ const optionsWithDisabledOptions = countryOptions.map( ( option, index ) => ( { } ) ); WithDisabledOptions.args = { - allowReset: false, - label: 'Select a country', + ...Default.args, options: optionsWithDisabledOptions, }; @@ -148,8 +148,7 @@ WithDisabledOptions.args = { export const NotExpandOnFocus = Template.bind( {} ); NotExpandOnFocus.args = { - allowReset: false, - label: 'Select a country', + ...Default.args, options: countryOptions, expandOnFocus: false, }; diff --git a/packages/components/src/combobox-control/test/index.tsx b/packages/components/src/combobox-control/test/index.tsx index 76ce9cc4724c54..adc76590c24538 100644 --- a/packages/components/src/combobox-control/test/index.tsx +++ b/packages/components/src/combobox-control/test/index.tsx @@ -12,7 +12,7 @@ import { useState } from '@wordpress/element'; /** * Internal dependencies */ -import ComboboxControl from '..'; +import _ComboboxControl from '..'; import type { ComboboxControlOption, ComboboxControlProps } from '../types'; const timezones = [ @@ -57,6 +57,10 @@ const getAllOptions = () => screen.getAllByRole( 'option' ); const getOptionSearchString = ( option: ComboboxControlOption ) => option.label.substring( 0, 11 ); +const ComboboxControl = ( props: ComboboxControlProps ) => { + return <_ComboboxControl { ...props } __nextHasNoMarginBottom />; +}; + const ControlledComboboxControl = ( { value: valueProp, onChange, diff --git a/packages/components/src/dimension-control/index.tsx b/packages/components/src/dimension-control/index.tsx index 114ebe987dd35d..52662f31c3f24c 100644 --- a/packages/components/src/dimension-control/index.tsx +++ b/packages/components/src/dimension-control/index.tsx @@ -16,6 +16,15 @@ import SelectControl from '../select-control'; import sizesTable, { findSizeBySlug } from './sizes'; import type { DimensionControlProps, Size } from './types'; import type { SelectControlSingleSelectionProps } from '../select-control/types'; +import { ContextSystemProvider } from '../context'; + +const CONTEXT_VALUE = { + BaseControl: { + // Temporary during deprecation grace period: Overrides the underlying `__associatedWPComponentName` + // via the context system to override the value set by SelectControl. + _overrides: { __associatedWPComponentName: 'DimensionControl' }, + }, +}; /** * `DimensionControl` is a component designed to provide a UI to control spacing and/or dimensions. @@ -87,16 +96,21 @@ export function DimensionControl( props: DimensionControlProps ) { ); return ( - <SelectControl - __next40pxDefaultSize={ __next40pxDefaultSize } - __nextHasNoMarginBottom={ __nextHasNoMarginBottom } - className={ clsx( className, 'block-editor-dimension-control' ) } - label={ selectLabel } - hideLabelFromVision={ false } - value={ value } - onChange={ onChangeSpacingSize } - options={ formatSizesAsOptions( sizes ) } - /> + <ContextSystemProvider value={ CONTEXT_VALUE }> + <SelectControl + __next40pxDefaultSize={ __next40pxDefaultSize } + __nextHasNoMarginBottom={ __nextHasNoMarginBottom } + className={ clsx( + className, + 'block-editor-dimension-control' + ) } + label={ selectLabel } + hideLabelFromVision={ false } + value={ value } + onChange={ onChangeSpacingSize } + options={ formatSizesAsOptions( sizes ) } + /> + </ContextSystemProvider> ); } diff --git a/packages/components/src/dimension-control/stories/index.story.tsx b/packages/components/src/dimension-control/stories/index.story.tsx index 33d5bad4ff4b19..3a6da44f461164 100644 --- a/packages/components/src/dimension-control/stories/index.story.tsx +++ b/packages/components/src/dimension-control/stories/index.story.tsx @@ -44,6 +44,7 @@ const Template: StoryFn< typeof DimensionControl > = ( args ) => ( export const Default = Template.bind( {} ); Default.args = { + __nextHasNoMarginBottom: true, label: 'Please select a size', sizes, }; diff --git a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap index 5990fbbd4a3f5f..658fe7febc02bc 100644 --- a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap +++ b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap @@ -13,10 +13,6 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = ` box-sizing: inherit; } -.emotion-2 { - margin-bottom: calc(4px * 2); -} - .components-panel__row .emotion-2 { margin-bottom: inherit; } @@ -299,10 +295,6 @@ exports[`DimensionControl rendering renders with defaults 1`] = ` box-sizing: inherit; } -.emotion-2 { - margin-bottom: calc(4px * 2); -} - .components-panel__row .emotion-2 { margin-bottom: inherit; } @@ -595,10 +587,6 @@ exports[`DimensionControl rendering renders with icon and custom icon label 1`] box-sizing: inherit; } -.emotion-2 { - margin-bottom: calc(4px * 2); -} - .components-panel__row .emotion-2 { margin-bottom: inherit; } @@ -903,10 +891,6 @@ exports[`DimensionControl rendering renders with icon and default icon label 1`] box-sizing: inherit; } -.emotion-2 { - margin-bottom: calc(4px * 2); -} - .components-panel__row .emotion-2 { margin-bottom: inherit; } diff --git a/packages/components/src/dimension-control/test/index.test.js b/packages/components/src/dimension-control/test/index.test.js index 1d65dd86c7e7c8..1b34d2983ad0f1 100644 --- a/packages/components/src/dimension-control/test/index.test.js +++ b/packages/components/src/dimension-control/test/index.test.js @@ -12,7 +12,11 @@ import { plus } from '@wordpress/icons'; /** * Internal dependencies */ -import { DimensionControl } from '../'; +import { DimensionControl as _DimensionControl } from '../'; + +const DimensionControl = ( props ) => { + return <_DimensionControl { ...props } __nextHasNoMarginBottom />; +}; describe( 'DimensionControl', () => { const onChangeHandler = jest.fn(); diff --git a/packages/components/src/focal-point-picker/index.tsx b/packages/components/src/focal-point-picker/index.tsx index 4575108fe6a21d..8f299751be0d48 100644 --- a/packages/components/src/focal-point-picker/index.tsx +++ b/packages/components/src/focal-point-picker/index.tsx @@ -251,6 +251,7 @@ export function FocalPointPicker( { <BaseControl { ...restProps } __nextHasNoMarginBottom={ __nextHasNoMarginBottom } + __associatedWPComponentName="FocalPointPicker" label={ label } id={ id } help={ help } diff --git a/packages/components/src/focal-point-picker/stories/index.story.tsx b/packages/components/src/focal-point-picker/stories/index.story.tsx index ce93d3557060c9..42fd64b8e4d855 100644 --- a/packages/components/src/focal-point-picker/stories/index.story.tsx +++ b/packages/components/src/focal-point-picker/stories/index.story.tsx @@ -49,6 +49,9 @@ const Template: StoryFn< typeof FocalPointPicker > = ( { }; export const Default = Template.bind( {} ); +Default.args = { + __nextHasNoMarginBottom: true, +}; export const Image = Template.bind( {} ); Image.args = { diff --git a/packages/components/src/focal-point-picker/test/index.tsx b/packages/components/src/focal-point-picker/test/index.tsx index 1eccced32c70af..377ba6c4e9e6b3 100644 --- a/packages/components/src/focal-point-picker/test/index.tsx +++ b/packages/components/src/focal-point-picker/test/index.tsx @@ -7,12 +7,16 @@ import userEvent from '@testing-library/user-event'; /** * Internal dependencies */ -import Picker from '..'; +import _Picker from '..'; import type { FocalPointPickerProps } from '../types'; type Log = { name: string; args: unknown[] }; type EventLogger = ( name: string, args: unknown[] ) => void; +const Picker = ( props: React.ComponentProps< typeof _Picker > ) => { + return <_Picker { ...props } __nextHasNoMarginBottom />; +}; + const props: FocalPointPickerProps = { onChange: jest.fn(), url: 'test-url', diff --git a/packages/components/src/range-control/index.tsx b/packages/components/src/range-control/index.tsx index 5b4ecfa585679b..20d9712df9c251 100644 --- a/packages/components/src/range-control/index.tsx +++ b/packages/components/src/range-control/index.tsx @@ -213,6 +213,7 @@ function UnforwardedRangeControl( return ( <BaseControl __nextHasNoMarginBottom={ __nextHasNoMarginBottom } + __associatedWPComponentName="RangeControl" className={ classes } label={ label } hideLabelFromVision={ hideLabelFromVision } diff --git a/packages/components/src/range-control/stories/index.story.tsx b/packages/components/src/range-control/stories/index.story.tsx index 4e0c1f19e078b6..7775c364195722 100644 --- a/packages/components/src/range-control/stories/index.story.tsx +++ b/packages/components/src/range-control/stories/index.story.tsx @@ -70,6 +70,7 @@ const Template: StoryFn< typeof RangeControl > = ( { onChange, ...args } ) => { export const Default: StoryFn< typeof RangeControl > = Template.bind( {} ); Default.args = { + __nextHasNoMarginBottom: true, help: 'Please select how transparent you would like this.', initialPosition: 50, label: 'Opacity', @@ -104,6 +105,7 @@ export const WithAnyStep: StoryFn< typeof RangeControl > = ( { ); }; WithAnyStep.args = { + __nextHasNoMarginBottom: true, label: 'Brightness', step: 'any', }; @@ -167,6 +169,7 @@ export const WithIntegerStepAndMarks: StoryFn< typeof RangeControl > = MarkTemplate.bind( {} ); WithIntegerStepAndMarks.args = { + __nextHasNoMarginBottom: true, label: 'Integer Step', marks: marksBase, max: 10, @@ -183,6 +186,7 @@ export const WithDecimalStepAndMarks: StoryFn< typeof RangeControl > = MarkTemplate.bind( {} ); WithDecimalStepAndMarks.args = { + __nextHasNoMarginBottom: true, marks: [ ...marksBase, { value: 3.5, label: '3.5' }, @@ -202,6 +206,7 @@ export const WithNegativeMinimumAndMarks: StoryFn< typeof RangeControl > = MarkTemplate.bind( {} ); WithNegativeMinimumAndMarks.args = { + __nextHasNoMarginBottom: true, marks: marksWithNegatives, max: 10, min: -10, @@ -217,6 +222,7 @@ export const WithNegativeRangeAndMarks: StoryFn< typeof RangeControl > = MarkTemplate.bind( {} ); WithNegativeRangeAndMarks.args = { + __nextHasNoMarginBottom: true, marks: marksWithNegatives, max: -1, min: -10, @@ -232,6 +238,7 @@ export const WithAnyStepAndMarks: StoryFn< typeof RangeControl > = MarkTemplate.bind( {} ); WithAnyStepAndMarks.args = { + __nextHasNoMarginBottom: true, marks: marksBase, max: 10, min: 0, diff --git a/packages/components/src/range-control/test/index.tsx b/packages/components/src/range-control/test/index.tsx index d843b615ed0078..a4c5d8c6f2bc7f 100644 --- a/packages/components/src/range-control/test/index.tsx +++ b/packages/components/src/range-control/test/index.tsx @@ -6,7 +6,7 @@ import { act, fireEvent, render, screen } from '@testing-library/react'; /** * Internal dependencies */ -import RangeControl from '../'; +import _RangeControl from '../'; const getRangeInput = (): HTMLInputElement => screen.getByRole( 'slider' ); const getNumberInput = (): HTMLInputElement => screen.getByRole( 'spinbutton' ); @@ -15,6 +15,12 @@ const getResetButton = (): HTMLButtonElement => screen.getByRole( 'button' ); const fireChangeEvent = ( input: HTMLInputElement, value?: number | string ) => fireEvent.change( input, { target: { value } } ); +const RangeControl = ( + props: React.ComponentProps< typeof _RangeControl > +) => { + return <_RangeControl { ...props } __nextHasNoMarginBottom />; +}; + describe( 'RangeControl', () => { describe( '#render()', () => { it( 'should trigger change callback with numeric value', () => { diff --git a/packages/components/src/search-control/index.tsx b/packages/components/src/search-control/index.tsx index 08cb3b065c904e..aac905e137e025 100644 --- a/packages/components/src/search-control/index.tsx +++ b/packages/components/src/search-control/index.tsx @@ -77,10 +77,13 @@ function UnforwardedSearchControl( const contextValue = useMemo( () => ( { - // Overrides the underlying BaseControl `__nextHasNoMarginBottom` via the context system - // to provide backwards compatibile margin for SearchControl. - // (In a standard InputControl, the BaseControl `__nextHasNoMarginBottom` is always set to true.) - BaseControl: { _overrides: { __nextHasNoMarginBottom } }, + BaseControl: { + // Overrides the underlying BaseControl `__nextHasNoMarginBottom` via the context system + // to provide backwards compatibile margin for SearchControl. + // (In a standard InputControl, the BaseControl `__nextHasNoMarginBottom` is always set to true.) + _overrides: { __nextHasNoMarginBottom }, + __associatedWPComponentName: 'SearchControl', + }, // `isBorderless` is still experimental and not a public prop for InputControl yet. InputBase: { isBorderless: true }, } ), diff --git a/packages/components/src/search-control/stories/index.story.tsx b/packages/components/src/search-control/stories/index.story.tsx index 433d3eef655adf..215288bb67c9b6 100644 --- a/packages/components/src/search-control/stories/index.story.tsx +++ b/packages/components/src/search-control/stories/index.story.tsx @@ -48,6 +48,7 @@ const Template: StoryFn< typeof SearchControl > = ( { export const Default = Template.bind( {} ); Default.args = { help: 'Help text to explain the input.', + __nextHasNoMarginBottom: true, }; /** diff --git a/packages/components/src/search-control/test/index.tsx b/packages/components/src/search-control/test/index.tsx index f130cab1b2a7cd..c6637945adcf63 100644 --- a/packages/components/src/search-control/test/index.tsx +++ b/packages/components/src/search-control/test/index.tsx @@ -23,6 +23,7 @@ function ControlledSearchControl( { return ( <SearchControl { ...restProps } + __nextHasNoMarginBottom value={ value } onChange={ ( ...args ) => { setValue( ...args ); diff --git a/packages/components/src/select-control/index.tsx b/packages/components/src/select-control/index.tsx index ca9966fc675b86..3686661b8a58dc 100644 --- a/packages/components/src/select-control/index.tsx +++ b/packages/components/src/select-control/index.tsx @@ -99,6 +99,7 @@ function UnforwardedSelectControl< V extends string >( help={ help } id={ id } __nextHasNoMarginBottom={ __nextHasNoMarginBottom } + __associatedWPComponentName="SelectControl" > <StyledInputBase className={ classes } diff --git a/packages/components/src/select-control/stories/index.story.tsx b/packages/components/src/select-control/stories/index.story.tsx index 11a63510d9337c..018f519e6b6d43 100644 --- a/packages/components/src/select-control/stories/index.story.tsx +++ b/packages/components/src/select-control/stories/index.story.tsx @@ -63,6 +63,7 @@ const SelectControlWithState: StoryFn< typeof SelectControl > = ( props ) => { export const Default = SelectControlWithState.bind( {} ); Default.args = { + __nextHasNoMarginBottom: true, options: [ { value: '', label: 'Select an Option', disabled: true }, { value: 'a', label: 'Option A' }, @@ -82,9 +83,11 @@ WithLabelAndHelpText.args = { * As an alternative to the `options` prop, `optgroup`s and `options` can be * passed in as `children` for more customizeability. */ -export const WithCustomChildren: StoryFn< typeof SelectControl > = ( args ) => { - return ( - <SelectControlWithState { ...args }> +export const WithCustomChildren = SelectControlWithState.bind( {} ); +WithCustomChildren.args = { + __nextHasNoMarginBottom: true, + children: ( + <> <option value="option-1">Option 1</option> <option value="option-2" disabled> Option 2 - Disabled @@ -97,8 +100,8 @@ export const WithCustomChildren: StoryFn< typeof SelectControl > = ( args ) => { Option Group 1 - Option 2 - Disabled </option> </optgroup> - </SelectControlWithState> - ); + </> + ), }; export const Minimal = SelectControlWithState.bind( {} ); diff --git a/packages/components/src/select-control/test/select-control.tsx b/packages/components/src/select-control/test/select-control.tsx index 0e8a6891087043..47b684cd20e280 100644 --- a/packages/components/src/select-control/test/select-control.tsx +++ b/packages/components/src/select-control/test/select-control.tsx @@ -7,7 +7,13 @@ import userEvent from '@testing-library/user-event'; /** * Internal dependencies */ -import SelectControl from '..'; +import _SelectControl from '..'; + +const SelectControl = ( + props: React.ComponentProps< typeof _SelectControl > +) => { + return <_SelectControl { ...props } __nextHasNoMarginBottom />; +}; describe( 'SelectControl', () => { it( 'should not render when no options or children are provided', () => { @@ -123,7 +129,7 @@ describe( 'SelectControl', () => { onChange={ onChange } />; - <SelectControl + <_SelectControl // @ts-expect-error "string" is not "narrow" or "value" value="string" options={ [ @@ -142,7 +148,7 @@ describe( 'SelectControl', () => { } ); it( 'should accept an explicit type argument', () => { - <SelectControl< 'narrow' | 'value' > + <_SelectControl< 'narrow' | 'value' > // @ts-expect-error "string" is not "narrow" or "value" value="string" options={ [ @@ -166,7 +172,7 @@ describe( 'SelectControl', () => { value: ( 'foo' | 'bar' )[] ) => void = () => {}; - <SelectControl + <_SelectControl multiple value={ [ 'narrow' ] } options={ [ @@ -183,7 +189,7 @@ describe( 'SelectControl', () => { onChange={ onChange } />; - <SelectControl + <_SelectControl multiple // @ts-expect-error "string" is not "narrow" or "value" value={ [ 'string' ] } @@ -205,7 +211,7 @@ describe( 'SelectControl', () => { } ); it( 'should accept an explicit type argument', () => { - <SelectControl< 'narrow' | 'value' > + <_SelectControl< 'narrow' | 'value' > multiple // @ts-expect-error "string" is not "narrow" or "value" value={ [ 'string' ] } diff --git a/packages/components/src/text-control/index.tsx b/packages/components/src/text-control/index.tsx index 1643c5bc37c347..ea2d2c17bb9cf6 100644 --- a/packages/components/src/text-control/index.tsx +++ b/packages/components/src/text-control/index.tsx @@ -41,6 +41,7 @@ function UnforwardedTextControl( return ( <BaseControl __nextHasNoMarginBottom={ __nextHasNoMarginBottom } + __associatedWPComponentName="TextControl" label={ label } hideLabelFromVision={ hideLabelFromVision } id={ id } diff --git a/packages/components/src/text-control/stories/index.story.tsx b/packages/components/src/text-control/stories/index.story.tsx index ddc8af7a9f2b3a..bebdb2caf75f63 100644 --- a/packages/components/src/text-control/stories/index.story.tsx +++ b/packages/components/src/text-control/stories/index.story.tsx @@ -52,7 +52,9 @@ const DefaultTemplate: StoryFn< typeof TextControl > = ( { export const Default: StoryFn< typeof TextControl > = DefaultTemplate.bind( {} ); -Default.args = {}; +Default.args = { + __nextHasNoMarginBottom: true, +}; export const WithLabelAndHelpText: StoryFn< typeof TextControl > = DefaultTemplate.bind( {} ); diff --git a/packages/components/src/text-control/test/text-control.tsx b/packages/components/src/text-control/test/text-control.tsx index fc048b93992f08..19b17cae443614 100644 --- a/packages/components/src/text-control/test/text-control.tsx +++ b/packages/components/src/text-control/test/text-control.tsx @@ -6,7 +6,11 @@ import { render, screen } from '@testing-library/react'; /** * Internal dependencies */ -import TextControl from '..'; +import _TextControl from '..'; + +const TextControl = ( props: React.ComponentProps< typeof _TextControl > ) => { + return <_TextControl { ...props } __nextHasNoMarginBottom />; +}; const noop = () => {}; diff --git a/packages/components/src/textarea-control/index.tsx b/packages/components/src/textarea-control/index.tsx index 3b96e11b0621b5..e7528510667b75 100644 --- a/packages/components/src/textarea-control/index.tsx +++ b/packages/components/src/textarea-control/index.tsx @@ -35,6 +35,7 @@ function UnforwardedTextareaControl( return ( <BaseControl __nextHasNoMarginBottom={ __nextHasNoMarginBottom } + __associatedWPComponentName="TextareaControl" label={ label } hideLabelFromVision={ hideLabelFromVision } id={ id } diff --git a/packages/components/src/textarea-control/stories/index.story.tsx b/packages/components/src/textarea-control/stories/index.story.tsx index e227519a069383..e8cb986a141325 100644 --- a/packages/components/src/textarea-control/stories/index.story.tsx +++ b/packages/components/src/textarea-control/stories/index.story.tsx @@ -51,6 +51,7 @@ const Template: StoryFn< typeof TextareaControl > = ( { export const Default: StoryFn< typeof TextareaControl > = Template.bind( {} ); Default.args = { + __nextHasNoMarginBottom: true, label: 'Text', help: 'Enter some text', }; diff --git a/packages/components/src/toggle-control/index.tsx b/packages/components/src/toggle-control/index.tsx index 5c64d57d3d0249..d2ee234a9695f8 100644 --- a/packages/components/src/toggle-control/index.tsx +++ b/packages/components/src/toggle-control/index.tsx @@ -10,6 +10,7 @@ import clsx from 'clsx'; */ import { forwardRef } from '@wordpress/element'; import { useInstanceId } from '@wordpress/compose'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies @@ -48,6 +49,14 @@ function UnforwardedToggleControl( ! __nextHasNoMarginBottom && css( { marginBottom: space( 3 ) } ) ); + if ( ! __nextHasNoMarginBottom ) { + deprecated( 'Bottom margin styles for wp.components.ToggleControl', { + since: '6.7', + version: '7.0', + hint: 'Set the `__nextHasNoMarginBottom` prop to true to start opting into the new styles, which will become the default in a future version.', + } ); + } + let describedBy, helpLabel; if ( help ) { if ( typeof help === 'function' ) { diff --git a/packages/components/src/toggle-control/stories/index.story.tsx b/packages/components/src/toggle-control/stories/index.story.tsx index b8043b8f48e523..97723aa207a394 100644 --- a/packages/components/src/toggle-control/stories/index.story.tsx +++ b/packages/components/src/toggle-control/stories/index.story.tsx @@ -48,6 +48,7 @@ const Template: StoryFn< typeof ToggleControl > = ( { export const Default = Template.bind( {} ); Default.args = { + __nextHasNoMarginBottom: true, label: 'Enable something', }; diff --git a/packages/components/src/toggle-control/test/index.tsx b/packages/components/src/toggle-control/test/index.tsx index cc89031d9affa3..b0eec2aca6663d 100644 --- a/packages/components/src/toggle-control/test/index.tsx +++ b/packages/components/src/toggle-control/test/index.tsx @@ -6,7 +6,13 @@ import { render, screen } from '@testing-library/react'; /** * Internal dependencies */ -import ToggleControl from '..'; +import _ToggleControl from '..'; + +const ToggleControl = ( + props: React.ComponentProps< typeof _ToggleControl > +) => { + return <_ToggleControl { ...props } __nextHasNoMarginBottom />; +}; describe( 'ToggleControl', () => { it( 'should label the toggle', () => { diff --git a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap index 81afc7ac67b05f..d055ea5fcc9838 100644 --- a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap +++ b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap @@ -13,10 +13,6 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = box-sizing: inherit; } -.emotion-2 { - margin-bottom: calc(4px * 2); -} - .components-panel__row .emotion-2 { margin-bottom: inherit; } @@ -349,10 +345,6 @@ exports[`ToggleGroupControl controlled should render correctly with text options box-sizing: inherit; } -.emotion-2 { - margin-bottom: calc(4px * 2); -} - .components-panel__row .emotion-2 { margin-bottom: inherit; } @@ -573,10 +565,6 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] box-sizing: inherit; } -.emotion-2 { - margin-bottom: calc(4px * 2); -} - .components-panel__row .emotion-2 { margin-bottom: inherit; } @@ -903,10 +891,6 @@ exports[`ToggleGroupControl uncontrolled should render correctly with text optio box-sizing: inherit; } -.emotion-2 { - margin-bottom: calc(4px * 2); -} - .components-panel__row .emotion-2 { margin-bottom: inherit; } diff --git a/packages/components/src/toggle-group-control/test/index.tsx b/packages/components/src/toggle-group-control/test/index.tsx index 661bbb9fc37bab..170db01ae523c2 100644 --- a/packages/components/src/toggle-group-control/test/index.tsx +++ b/packages/components/src/toggle-group-control/test/index.tsx @@ -15,7 +15,7 @@ import { formatLowercase, formatUppercase } from '@wordpress/icons'; */ import Button from '../../button'; import { - ToggleGroupControl, + ToggleGroupControl as _ToggleGroupControl, ToggleGroupControlOption, ToggleGroupControlOptionIcon, } from '../index'; @@ -27,6 +27,10 @@ const hoverOutside = async () => { await hover( document.body, { clientX: 10, clientY: 10 } ); }; +const ToggleGroupControl = ( props: ToggleGroupControlProps ) => { + return <_ToggleGroupControl { ...props } __nextHasNoMarginBottom />; +}; + const ControlledToggleGroupControl = ( { value: valueProp, onChange, diff --git a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx index 8138b76505fe50..1c86c93548f6df 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx @@ -72,6 +72,7 @@ function UnconnectedToggleGroupControl( <BaseControl help={ help } __nextHasNoMarginBottom={ __nextHasNoMarginBottom } + __associatedWPComponentName="ToggleGroupControl" > { ! hideLabelFromVision && ( <VisualLabelWrapper> diff --git a/packages/components/src/tree-select/index.tsx b/packages/components/src/tree-select/index.tsx index 599dee4402ec72..bd92807bff4cc9 100644 --- a/packages/components/src/tree-select/index.tsx +++ b/packages/components/src/tree-select/index.tsx @@ -10,6 +10,15 @@ import { decodeEntities } from '@wordpress/html-entities'; import { SelectControl } from '../select-control'; import type { TreeSelectProps, Tree, Truthy } from './types'; import { useDeprecated36pxDefaultSizeProp } from '../utils/use-deprecated-props'; +import { ContextSystemProvider } from '../context'; + +const CONTEXT_VALUE = { + BaseControl: { + // Temporary during deprecation grace period: Overrides the underlying `__associatedWPComponentName` + // via the context system to override the value set by SelectControl. + _overrides: { __associatedWPComponentName: 'TreeSelect' }, + }, +}; function getSelectOptions( tree: Tree[], @@ -91,11 +100,13 @@ export function TreeSelect( props: TreeSelectProps ) { }, [ noOptionLabel, tree ] ); return ( - <SelectControl - { ...{ label, options, onChange } } - value={ selectedId } - { ...restProps } - /> + <ContextSystemProvider value={ CONTEXT_VALUE }> + <SelectControl + { ...{ label, options, onChange } } + value={ selectedId } + { ...restProps } + /> + </ContextSystemProvider> ); } diff --git a/packages/components/src/tree-select/stories/index.story.tsx b/packages/components/src/tree-select/stories/index.story.tsx index 0a4212dc791227..33103786bbc541 100644 --- a/packages/components/src/tree-select/stories/index.story.tsx +++ b/packages/components/src/tree-select/stories/index.story.tsx @@ -48,6 +48,7 @@ const TreeSelectWithState: StoryFn< typeof TreeSelect > = ( props ) => { export const Default = TreeSelectWithState.bind( {} ); Default.args = { + __nextHasNoMarginBottom: true, label: 'Label Text', noOptionLabel: 'No parent page', help: 'Help text to explain the select control.', From e0760706272e4d6af3f1b0c7f90ab4ea9e305256 Mon Sep 17 00:00:00 2001 From: Amit Raj <77401999+amitraj2203@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:16:04 +0530 Subject: [PATCH 0384/1908] chore: Add label prop to SizeControl component (#64428) Co-authored-by: amitraj2203 <amitraj2203@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../src/components/global-styles/size-control/index.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/size-control/index.js b/packages/edit-site/src/components/global-styles/size-control/index.js index 28fa64c643cbbd..06ea0bb5617e31 100644 --- a/packages/edit-site/src/components/global-styles/size-control/index.js +++ b/packages/edit-site/src/components/global-styles/size-control/index.js @@ -1,7 +1,6 @@ /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -26,7 +25,7 @@ function SizeControl( { ...props } ) { const { baseControlProps } = useBaseControlProps( props ); - const { value, onChange, fallbackValue, disabled } = props; + const { value, onChange, fallbackValue, disabled, label } = props; const units = useCustomUnits( { availableUnits: DEFAULT_UNITS, @@ -55,7 +54,7 @@ function SizeControl( { <UnitControl __next40pxDefaultSize __nextHasNoMarginBottom - label={ __( 'Custom' ) } + label={ label } hideLabelFromVision value={ value } onChange={ handleUnitControlChange } @@ -69,7 +68,7 @@ function SizeControl( { <RangeControl __next40pxDefaultSize __nextHasNoMarginBottom - label={ __( 'Custom Size' ) } + label={ label } hideLabelFromVision value={ valueQuantity } initialPosition={ fallbackValue } From 7498ac2ed444e7737086e95d7da7ff2229fda3fe Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Wed, 14 Aug 2024 08:23:24 +0100 Subject: [PATCH 0385/1908] Zoon Out: Fix scale calculations (#64478) --- packages/block-editor/src/components/iframe/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index e7af77920ea127..3b0bce6d56b403 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -242,8 +242,10 @@ function Iframe( { const isZoomedOut = scale !== 1; useEffect( () => { - prevContainerWidth.current = containerWidth; - }, [ containerWidth ] ); + if ( ! isZoomedOut ) { + prevContainerWidth.current = containerWidth; + } + }, [ containerWidth, isZoomedOut ] ); const disabledRef = useDisabled( { isDisabled: ! readonly } ); const bodyRef = useMergeRefs( [ From c20273736e30e2bfc54f82faaeaad4912b25cd29 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 14 Aug 2024 12:18:10 +0000 Subject: [PATCH 0386/1908] Bump plugin version to 19.0.0 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 6ec0a56f00e74d..66f0aa31a65baa 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.0.0-rc.1 + * Version: 19.0.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 471d7b845d24f8..ddfec3a5dddc63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.0.0-rc.1", + "version": "19.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.0.0-rc.1", + "version": "19.0.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index e4466eb4f470e1..ee78f197a43e28 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.0.0-rc.1", + "version": "19.0.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 54269c00f74805533b5fec9bf14b84d18f8d3ae9 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 14 Aug 2024 12:41:28 +0000 Subject: [PATCH 0387/1908] Update Changelog for 19.0.0 --- changelog.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index e85895547e87d1..748df8da3484c7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,6 @@ == Changelog == -= 19.0.0-rc.1 = - += 19.0.0 = ## Changelog @@ -368,6 +367,8 @@ The following contributors merged PRs in this release: @aaronrobertshaw @adamsilverstein @afercia @akasunil @Aljullu @amitraj2203 @andrewserong @carolinan @cbravobernal @Chrico @ciampo @creativecoder @DaniGuardiola @DAreRodz @djcowan @ellatrix @jameskoster @jasmussen @jeryj @jorgefilipecosta @jsnajdr @kebbet @kmanijak @Mamaduka @matiasbenedetto @meteorlxy @mikachan @mirka @mtias @ndiego @noisysocks @oandregal @ramonjd @richtabor @Rishit30G @ryanwelcher @SantosGuillamot @scruffian @shail-mehta @simison @stokesman @t-hamano @talldan @tomdevisser @tomjn @tyxla @up1512001 @wzieba @youknowriad + + = 18.9.0 = ## Changelog From b533bfd6d00c2aa99341568d5328a6ca6f826823 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 14 Aug 2024 15:32:14 +0200 Subject: [PATCH 0388/1908] `Composite`: use internal context to consume composite store (#64493) * Create CompositeContext * Use context to pass store to composite subcomponents * CHANGELOG * Remove double dot * Export `Context`, add basic docs * Update CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 +- packages/components/src/composite/README.md | 4 + packages/components/src/composite/context.ts | 14 +++ packages/components/src/composite/index.tsx | 95 ++++++++++++++++++-- packages/components/src/composite/types.ts | 9 ++ 5 files changed, 116 insertions(+), 10 deletions(-) create mode 100644 packages/components/src/composite/context.ts diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 36b1c8fcc55d00..594bb47e187d51 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -23,11 +23,13 @@ - `Composite`: add stable version of the component ([#63564](https://github.com/WordPress/gutenberg/pull/63564)). - `Composite`: add `Hover` and `Typeahead` subcomponents ([#64399](https://github.com/WordPress/gutenberg/pull/64399)). -- `Composite`: export `useCompositeStore, add focus-related props to `Composite`and`Composite.Item` subcomponents ([#64450](https://github.com/WordPress/gutenberg/pull/64450)). +- `Composite`: export `useCompositeStore`, add focus-related props to `Composite`and`Composite.Item` subcomponents ([#64450](https://github.com/WordPress/gutenberg/pull/64450)). +- `Composite`: add `Context` subcomponent ([#64493](https://github.com/WordPress/gutenberg/pull/64493)). ### Enhancements - `Composite`: improve Storybook examples and add interactive controls ([#64397](https://github.com/WordPress/gutenberg/pull/64397)). +- `Composite`: use internal context to forward the composite store to sub-components ([#64493](https://github.com/WordPress/gutenberg/pull/64493)). - `QueryControls`: Default to new 40px size ([#64457](https://github.com/WordPress/gutenberg/pull/64457)). - `TimePicker`: add `hideLabelFromVision` prop ([#64267](https://github.com/WordPress/gutenberg/pull/64267)). - `DropdownMenuV2`: adopt elevation scale ([#64432](https://github.com/WordPress/gutenberg/pull/64432)). diff --git a/packages/components/src/composite/README.md b/packages/components/src/composite/README.md index 3670e31b01e9df..76e345b16d13fa 100644 --- a/packages/components/src/composite/README.md +++ b/packages/components/src/composite/README.md @@ -315,3 +315,7 @@ Allows the component to be rendered as a different HTML element or React compone The contents of the component. - Required: no + +### `Composite.Context` + +The React context used by the composite components. It can be used by to access the composite store, and to forward the context when composite sub-components are rendered across portals (ie. `SlotFill` components) that would not otherwise forward the context to the `Fill` children. diff --git a/packages/components/src/composite/context.ts b/packages/components/src/composite/context.ts new file mode 100644 index 00000000000000..69a052c5bfba19 --- /dev/null +++ b/packages/components/src/composite/context.ts @@ -0,0 +1,14 @@ +/** + * WordPress dependencies + */ +import { createContext, useContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { CompositeContextProps } from './types'; + +export const CompositeContext = + createContext< CompositeContextProps >( undefined ); + +export const useCompositeContext = () => useContext( CompositeContext ); diff --git a/packages/components/src/composite/index.tsx b/packages/components/src/composite/index.tsx index f5d92330cada3c..0bfcec2bf76600 100644 --- a/packages/components/src/composite/index.tsx +++ b/packages/components/src/composite/index.tsx @@ -16,12 +16,13 @@ import * as Ariakit from '@ariakit/react'; /** * WordPress dependencies */ -import { forwardRef } from '@wordpress/element'; +import { useMemo, forwardRef } from '@wordpress/element'; /** * Internal dependencies */ import type { WordPressComponentProps } from '../context'; +import { CompositeContext, useCompositeContext } from './context'; import type { CompositeStoreProps, CompositeProps, @@ -72,7 +73,14 @@ const Group = forwardRef< HTMLDivElement, WordPressComponentProps< CompositeGroupProps, 'div', false > >( function CompositeGroup( props, ref ) { - return <Ariakit.CompositeGroup { ...props } ref={ ref } />; + const context = useCompositeContext(); + return ( + <Ariakit.CompositeGroup + store={ context?.store } + { ...props } + ref={ ref } + /> + ); } ); Group.displayName = 'Composite.Group'; @@ -80,7 +88,14 @@ const GroupLabel = forwardRef< HTMLDivElement, WordPressComponentProps< CompositeGroupLabelProps, 'div', false > >( function CompositeGroupLabel( props, ref ) { - return <Ariakit.CompositeGroupLabel { ...props } ref={ ref } />; + const context = useCompositeContext(); + return ( + <Ariakit.CompositeGroupLabel + store={ context?.store } + { ...props } + ref={ ref } + /> + ); } ); GroupLabel.displayName = 'Composite.GroupLabel'; @@ -88,7 +103,14 @@ const Item = forwardRef< HTMLButtonElement, WordPressComponentProps< CompositeItemProps, 'button', false > >( function CompositeItem( props, ref ) { - return <Ariakit.CompositeItem { ...props } ref={ ref } />; + const context = useCompositeContext(); + return ( + <Ariakit.CompositeItem + store={ context?.store } + { ...props } + ref={ ref } + /> + ); } ); Item.displayName = 'Composite.Item'; @@ -96,7 +118,14 @@ const Row = forwardRef< HTMLDivElement, WordPressComponentProps< CompositeRowProps, 'div', false > >( function CompositeRow( props, ref ) { - return <Ariakit.CompositeRow { ...props } ref={ ref } />; + const context = useCompositeContext(); + return ( + <Ariakit.CompositeRow + store={ context?.store } + { ...props } + ref={ ref } + /> + ); } ); Row.displayName = 'Composite.Row'; @@ -104,7 +133,14 @@ const Hover = forwardRef< HTMLDivElement, WordPressComponentProps< CompositeHoverProps, 'div', false > >( function CompositeHover( props, ref ) { - return <Ariakit.CompositeHover { ...props } ref={ ref } />; + const context = useCompositeContext(); + return ( + <Ariakit.CompositeHover + store={ context?.store } + { ...props } + ref={ ref } + /> + ); } ); Hover.displayName = 'Composite.Hover'; @@ -112,7 +148,14 @@ const Typeahead = forwardRef< HTMLDivElement, WordPressComponentProps< CompositeTypeaheadProps, 'div', false > >( function CompositeTypeahead( props, ref ) { - return <Ariakit.CompositeTypeahead { ...props } ref={ ref } />; + const context = useCompositeContext(); + return ( + <Ariakit.CompositeTypeahead + store={ context?.store } + { ...props } + ref={ ref } + /> + ); } ); Typeahead.displayName = 'Composite.Typeahead'; @@ -136,9 +179,28 @@ export const Composite = Object.assign( forwardRef< HTMLDivElement, WordPressComponentProps< CompositeProps, 'div', false > - >( function Composite( { disabled = false, ...props }, ref ) { + >( function Composite( + { children, store, disabled = false, ...props }, + ref + ) { + const contextValue = useMemo( + () => ( { + store, + } ), + [ store ] + ); + return ( - <Ariakit.Composite disabled={ disabled } { ...props } ref={ ref } /> + <Ariakit.Composite + disabled={ disabled } + store={ store } + { ...props } + ref={ ref } + > + <CompositeContext.Provider value={ contextValue }> + { children } + </CompositeContext.Provider> + </Ariakit.Composite> ); } ), { @@ -260,5 +322,20 @@ export const Composite = Object.assign( * ``` */ Typeahead, + /** + * The React context used by the composite components. It can be used by + * to access the composite store, and to forward the context when composite + * sub-components are rendered across portals (ie. `SlotFill` components) + * that would not otherwise forward the context to the `Fill` children. + * + * @example + * ```jsx + * import { Composite } from '@wordpress/components'; + * import { useContext } from '@wordpress/element'; + * + * const compositeContext = useContext( Composite.Context ); + * ``` + */ + Context: CompositeContext, } ); diff --git a/packages/components/src/composite/types.ts b/packages/components/src/composite/types.ts index 5afe410f7582ba..05a2b8473eb349 100644 --- a/packages/components/src/composite/types.ts +++ b/packages/components/src/composite/types.ts @@ -3,6 +3,15 @@ */ import type * as Ariakit from '@ariakit/react'; +export type CompositeContextProps = + | { + /** + * Object returned by the `useCompositeStore` hook. + */ + store: Ariakit.CompositeStore; + } + | undefined; + export type CompositeStoreProps = { /** * The current active item `id`. The active item is the element within the From 00d1f8afac2e3b9764dc28261462b72794ae5ce0 Mon Sep 17 00:00:00 2001 From: Luis Herranz <luisherranz@gmail.com> Date: Wed, 14 Aug 2024 17:04:04 +0200 Subject: [PATCH 0389/1908] Add missing changes to the changelog for the PR #62734 (#64507) Co-authored-by: luisherranz <luisherranz@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> --- packages/interactivity/CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 6eb664984e1e53..52707b70ba5a7b 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -4,14 +4,24 @@ ## 6.5.0 (2024-08-07) +### Enhancements + +- Refactor internal proxy and signals system ([#62734](https://github.com/WordPress/gutenberg/pull/62734)). + +### Bug Fixes + +- Prevent overriding of existing properties on state and context after a client-side navigation ([#62734](https://github.com/WordPress/gutenberg/pull/62734)). + ## 6.4.0 (2024-07-24) ## 6.3.0 (2024-07-10) ## 6.2.0 (2024-06-26) + ### Enhancements - Export `splitTask` function from `@wordpress/interactivity` package to facilitate yielding to the main thread. See example in [async actions](https://github.com/WordPress/gutenberg/blob/trunk/docs/reference-guides/interactivity-api/api-reference.md#async-actions) documentation. ([#62665](https://github.com/WordPress/gutenberg/pull/62665)) + ## 6.1.0 (2024-06-15) ## 6.0.0 (2024-05-31) From 93b473840667751c655a9afbed2ebd2c1ade522e Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 14 Aug 2024 17:29:41 +0200 Subject: [PATCH 0390/1908] `Composite` v2: undo stabilizing new version (#64510) * Remove exports from `@wordpress/components` package * Update Storybook * Update CHANGELOG * README --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 13 ++++++------- packages/components/src/composite/README.md | 4 ++++ .../src/composite/legacy/stories/index.story.tsx | 3 +-- .../src/composite/stories/index.story.tsx | 3 ++- packages/components/src/index.ts | 1 - 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 594bb47e187d51..7b3a2aea460d9f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -19,13 +19,6 @@ - `ToggleGroupControl` - `TreeSelect` -### New Features - -- `Composite`: add stable version of the component ([#63564](https://github.com/WordPress/gutenberg/pull/63564)). -- `Composite`: add `Hover` and `Typeahead` subcomponents ([#64399](https://github.com/WordPress/gutenberg/pull/64399)). -- `Composite`: export `useCompositeStore`, add focus-related props to `Composite`and`Composite.Item` subcomponents ([#64450](https://github.com/WordPress/gutenberg/pull/64450)). -- `Composite`: add `Context` subcomponent ([#64493](https://github.com/WordPress/gutenberg/pull/64493)). - ### Enhancements - `Composite`: improve Storybook examples and add interactive controls ([#64397](https://github.com/WordPress/gutenberg/pull/64397)). @@ -34,6 +27,12 @@ - `TimePicker`: add `hideLabelFromVision` prop ([#64267](https://github.com/WordPress/gutenberg/pull/64267)). - `DropdownMenuV2`: adopt elevation scale ([#64432](https://github.com/WordPress/gutenberg/pull/64432)). +### Internal + +- `Composite` v2: add `Hover` and `Typeahead` subcomponents ([#64399](https://github.com/WordPress/gutenberg/pull/64399)). +- `Composite` v2: add focus-related props to `Composite`and`Composite.Item` subcomponents ([#64450](https://github.com/WordPress/gutenberg/pull/64450)). +- `Composite` v2: add `Context` subcomponent ([#64493](https://github.com/WordPress/gutenberg/pull/64493)). + ## 28.5.0 (2024-08-07) ### Bug Fixes diff --git a/packages/components/src/composite/README.md b/packages/components/src/composite/README.md index 76e345b16d13fa..35881d815cf1bc 100644 --- a/packages/components/src/composite/README.md +++ b/packages/components/src/composite/README.md @@ -1,5 +1,9 @@ # `Composite` +<div class="callout callout-alert"> +This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +</div> + `Composite` provides a single tab stop on the page and allows navigation through the focusable descendants with arrow keys. This abstract component is based on the [WAI-ARIA Composite Role⁠](https://w3c.github.io/aria/#composite). ## Usage diff --git a/packages/components/src/composite/legacy/stories/index.story.tsx b/packages/components/src/composite/legacy/stories/index.story.tsx index 1b8e07e9bbf560..e46d656a16810e 100644 --- a/packages/components/src/composite/legacy/stories/index.story.tsx +++ b/packages/components/src/composite/legacy/stories/index.story.tsx @@ -15,8 +15,7 @@ import { import { UseCompositeStatePlaceholder, transform } from './utils'; const meta: Meta< typeof UseCompositeStatePlaceholder > = { - title: 'Components (Deprecated)/Composite (Unstable)', - id: 'components-composite-unstable', + title: 'Components/Composite', component: UseCompositeStatePlaceholder, subcomponents: { Composite, diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx index 405962b92a761c..034e1d6721f7bd 100644 --- a/packages/components/src/composite/stories/index.story.tsx +++ b/packages/components/src/composite/stories/index.story.tsx @@ -15,7 +15,7 @@ import { Composite, useCompositeStore } from '..'; import { UseCompositeStorePlaceholder, transform } from './utils'; const meta: Meta< typeof UseCompositeStorePlaceholder > = { - title: 'Components/Composite', + title: 'Components/Composite (V2)', component: UseCompositeStorePlaceholder, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 @@ -50,6 +50,7 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { options: [ 'horizontal', 'vertical', 'both' ], }, }, + tags: [ 'status-private' ], parameters: { controls: { expanded: true }, docs: { diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index cd6d2a77db9cb6..6483e34dc222a8 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -62,7 +62,6 @@ export { CompositeItem as __unstableCompositeItem, useCompositeState as __unstableUseCompositeState, } from './composite/legacy'; -export { Composite, useCompositeStore } from './composite'; export { ConfirmDialog as __experimentalConfirmDialog } from './confirm-dialog'; export { default as CustomSelectControl } from './custom-select-control'; export { default as Dashicon } from './dashicon'; From b8d195e3196c82318270f561b958b3da943a03e9 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 15 Aug 2024 02:48:46 +0900 Subject: [PATCH 0391/1908] FocalPointPicker: Default to new 40px size (#64456) * FocalPointPicker: Default to new 40px size * Simplify prop passing * Remove unnecessary usage * Add changelog --------- Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/global-styles/background-panel.js | 1 - packages/block-library/src/cover/edit/inspector-controls.js | 1 - packages/block-library/src/media-text/edit.js | 1 - packages/components/CHANGELOG.md | 1 + packages/components/src/focal-point-picker/controls.tsx | 4 +--- packages/components/src/focal-point-picker/index.tsx | 2 -- packages/components/src/focal-point-picker/types.ts | 4 ++-- 7 files changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index 906202206d1b76..14b37bb3007658 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -585,7 +585,6 @@ function BackgroundSizeControls( { return ( <VStack spacing={ 3 } className="single-column"> <FocalPointPicker - __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Focal point' ) } url={ getResolvedThemeFilePath( imageValue, themeFileURIs ) } diff --git a/packages/block-library/src/cover/edit/inspector-controls.js b/packages/block-library/src/cover/edit/inspector-controls.js index 5f93df58ad6fa4..eedd94de88e4aa 100644 --- a/packages/block-library/src/cover/edit/inspector-controls.js +++ b/packages/block-library/src/cover/edit/inspector-controls.js @@ -188,7 +188,6 @@ export default function CoverInspectorControls( { { showFocalPointPicker && ( <FocalPointPicker __nextHasNoMarginBottom - __next40pxDefaultSize label={ __( 'Focal point' ) } url={ url } value={ focalPoint } diff --git a/packages/block-library/src/media-text/edit.js b/packages/block-library/src/media-text/edit.js index 5a3b4fab04ab63..2c020506dc889c 100644 --- a/packages/block-library/src/media-text/edit.js +++ b/packages/block-library/src/media-text/edit.js @@ -360,7 +360,6 @@ function MediaTextEdit( { > <FocalPointPicker __nextHasNoMarginBottom - __next40pxDefaultSize label={ __( 'Focal point' ) } url={ useFeaturedImage && featuredImageURL diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 7b3a2aea460d9f..2530b66152bdc2 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -25,6 +25,7 @@ - `Composite`: use internal context to forward the composite store to sub-components ([#64493](https://github.com/WordPress/gutenberg/pull/64493)). - `QueryControls`: Default to new 40px size ([#64457](https://github.com/WordPress/gutenberg/pull/64457)). - `TimePicker`: add `hideLabelFromVision` prop ([#64267](https://github.com/WordPress/gutenberg/pull/64267)). +- `FocalPointPicker`: Default to new 40px size ([#64456](https://github.com/WordPress/gutenberg/pull/64456)). - `DropdownMenuV2`: adopt elevation scale ([#64432](https://github.com/WordPress/gutenberg/pull/64432)). ### Internal diff --git a/packages/components/src/focal-point-picker/controls.tsx b/packages/components/src/focal-point-picker/controls.tsx index 3df1725bf3bedb..1ecf846b10635e 100644 --- a/packages/components/src/focal-point-picker/controls.tsx +++ b/packages/components/src/focal-point-picker/controls.tsx @@ -23,7 +23,6 @@ const noop = () => {}; export default function FocalPointPickerControls( { __nextHasNoMarginBottom, - __next40pxDefaultSize, hasHelpText, onChange = noop, point = { @@ -57,7 +56,6 @@ export default function FocalPointPickerControls( { gap={ 4 } > <FocalPointUnitControl - __next40pxDefaultSize={ __next40pxDefaultSize } label={ __( 'Left' ) } aria-label={ __( 'Focal point left position' ) } value={ [ valueX, '%' ].join( '' ) } @@ -71,7 +69,6 @@ export default function FocalPointPickerControls( { dragDirection="e" /> <FocalPointUnitControl - __next40pxDefaultSize={ __next40pxDefaultSize } label={ __( 'Top' ) } aria-label={ __( 'Focal point top position' ) } value={ [ valueY, '%' ].join( '' ) } @@ -91,6 +88,7 @@ export default function FocalPointPickerControls( { function FocalPointUnitControl( props: UnitControlProps ) { return ( <StyledUnitControl + __next40pxDefaultSize className="focal-point-picker__controls-position-unit-control" labelPosition="top" max={ TEXTCONTROL_MAX } diff --git a/packages/components/src/focal-point-picker/index.tsx b/packages/components/src/focal-point-picker/index.tsx index 8f299751be0d48..cad14aff5b693f 100644 --- a/packages/components/src/focal-point-picker/index.tsx +++ b/packages/components/src/focal-point-picker/index.tsx @@ -85,7 +85,6 @@ const GRID_OVERLAY_TIMEOUT = 600; */ export function FocalPointPicker( { __nextHasNoMarginBottom, - __next40pxDefaultSize = false, autoPlay = true, className, help, @@ -286,7 +285,6 @@ export function FocalPointPicker( { </MediaWrapper> <Controls __nextHasNoMarginBottom={ __nextHasNoMarginBottom } - __next40pxDefaultSize={ __next40pxDefaultSize } hasHelpText={ !! help } point={ { x, y } } onChange={ ( value ) => { diff --git a/packages/components/src/focal-point-picker/types.ts b/packages/components/src/focal-point-picker/types.ts index bd66ae02451a95..357af1e090d7f5 100644 --- a/packages/components/src/focal-point-picker/types.ts +++ b/packages/components/src/focal-point-picker/types.ts @@ -29,7 +29,8 @@ export type FocalPointPickerProps = Pick< /** * Start opting into the larger default height that will become the default size in a future version. * - * @default false + * @deprecated Default behavior since WP 6.7. Prop can be safely removed. + * @ignore */ __next40pxDefaultSize?: boolean; /** @@ -68,7 +69,6 @@ export type FocalPointPickerProps = Pick< export type FocalPointPickerControlsProps = { __nextHasNoMarginBottom?: boolean; - __next40pxDefaultSize?: boolean; /** * A bit of extra bottom margin will be added if a `help` text * needs to be rendered under it. From 1b6c106d704ad2eab5f576d13064f4ee1399ec61 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Thu, 15 Aug 2024 02:14:20 +0530 Subject: [PATCH 0392/1908] Updated small typo in modularity.md (#64518) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> --- docs/explanations/architecture/modularity.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/explanations/architecture/modularity.md b/docs/explanations/architecture/modularity.md index f94f8ec7b9472e..ff619ccbfdf5b7 100644 --- a/docs/explanations/architecture/modularity.md +++ b/docs/explanations/architecture/modularity.md @@ -42,7 +42,7 @@ function MyApp() { ```php // myplugin.php -// Example of script registration dependending on the "components" and "element packages. +// Example of script registration depending on the "components" and "element packages. wp_register_script( 'myscript', 'pathtomyscript.js', array ('wp-components', "react" ) ); ``` From cf8aeba074334550bc42471b022dac7137aa1eb2 Mon Sep 17 00:00:00 2001 From: Felix Arntz <flixos90@gmail.com> Date: Wed, 14 Aug 2024 15:05:11 -0700 Subject: [PATCH 0393/1908] Make wp-env compatible with WordPress versions older than 5.4 by fixing wp-config anchors (#55864) * Make wp-env compatible with WordPress versions older than 5.4 by fixing wp-config anchors. * Use simple version compare function instead of semver library. * Fix lint violations. * Convert wpVersion to a string if needed. * Simplify utility function for WP version check. * Temp test. * Temp test. * Temp test. * Remove temp code. * Add missing spaces in WP 5.1-5.3 code. --- packages/env/lib/wordpress.js | 54 +++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/packages/env/lib/wordpress.js b/packages/env/lib/wordpress.js index 423547fad688b5..bd3c4a23f8ff5d 100644 --- a/packages/env/lib/wordpress.js +++ b/packages/env/lib/wordpress.js @@ -27,6 +27,30 @@ const { getCache, setCache } = require( './cache' ); * @typedef {'development'|'tests'|'all'} WPEnvironmentSelection */ +/** + * Utility function to check if a WordPress version is lower than another version. + * + * This is a non-comprehensive check only intended for this usage, to avoid pulling in a full semver library. + * It only considers the major and minor portions of the version and ignores the rest. Additionally, it assumes that + * the minor version is always a single digit (i.e. 0-9). + * + * Do not use this function for general version comparison, as it will not work for all cases. + * + * @param {string} version The version to check. + * @param {string} compareVersion The compare version to check whether the version is lower than. + * @return {boolean} True if the version is lower than the compare version, false otherwise. + */ +function isWPMajorMinorVersionLower( version, compareVersion ) { + const versionNumber = Number.parseFloat( + version.match( /^[0-9]+(\.[0-9]+)?/ )[ 0 ] + ); + const compareVersionNumber = Number.parseFloat( + compareVersion.match( /^[0-9]+(\.[0-9]+)?/ )[ 0 ] + ); + + return versionNumber < compareVersionNumber; +} + /** * Checks a WordPress database connection. An error is thrown if the test is * unsuccessful. @@ -51,11 +75,28 @@ async function checkDatabaseConnection( { dockerComposeConfigPath, debug } ) { * @param {Object} spinner A CLI spinner which indicates progress. */ async function configureWordPress( environment, config, spinner ) { + let wpVersion = ''; + try { + wpVersion = await readWordPressVersion( + config.env[ environment ].coreSource, + spinner, + config.debug + ); + } catch ( err ) { + // Ignore error. + } + const installCommand = `wp core install --url="${ config.env[ environment ].config.WP_SITEURL }" --title="${ config.name }" --admin_user=admin --admin_password=password --admin_email=wordpress@example.com --skip-email`; // -eo pipefail exits the command as soon as anything fails in bash. const setupCommands = [ 'set -eo pipefail', installCommand ]; + // WordPress versions below 5.1 didn't use proper spacing in wp-config. + const configAnchor = + wpVersion && isWPMajorMinorVersionLower( wpVersion, '5.1' ) + ? `"define('WP_DEBUG',"` + : `"define( 'WP_DEBUG',"`; + // Set wp-config.php values. for ( let [ key, value ] of Object.entries( config.env[ environment ].config @@ -68,7 +109,7 @@ async function configureWordPress( environment, config, spinner ) { // Add quotes around string values to work with multi-word strings better. value = typeof value === 'string' ? `"${ value }"` : value; setupCommands.push( - `wp config set ${ key } ${ value } --anchor="define( 'WP_DEBUG',"${ + `wp config set ${ key } ${ value } --anchor=${ configAnchor }${ typeof value !== 'string' ? ' --raw' : '' }` ); @@ -98,6 +139,15 @@ async function configureWordPress( environment, config, spinner ) { } ); + // WordPress versions below 5.1 didn't use proper spacing in wp-config. + // Additionally, WordPress versions below 5.4 used `dirname( __FILE__ )` instead of `__DIR__`. + let abspathDef = `define( 'ABSPATH', __DIR__ . '\\/' );`; + if ( wpVersion && isWPMajorMinorVersionLower( wpVersion, '5.1' ) ) { + abspathDef = `define('ABSPATH', dirname(__FILE__) . '\\/');`; + } else if ( wpVersion && isWPMajorMinorVersionLower( wpVersion, '5.4' ) ) { + abspathDef = `define( 'ABSPATH', dirname( __FILE__ ) . '\\/' );`; + } + // WordPress' PHPUnit suite expects a `wp-tests-config.php` in // the directory that the test suite is contained within. // Make sure ABSPATH points to the WordPress install. @@ -106,7 +156,7 @@ async function configureWordPress( environment, config, spinner ) { [ 'sh', '-c', - `sed -e "/^require.*wp-settings.php/d" -e "s/define( 'ABSPATH', __DIR__ . '\\/' );/define( 'ABSPATH', '\\/var\\/www\\/html\\/' );\\n\\tdefine( 'WP_DEFAULT_THEME', 'default' );/" /var/www/html/wp-config.php > /wordpress-phpunit/wp-tests-config.php`, + `sed -e "/^require.*wp-settings.php/d" -e "s/${ abspathDef }/define( 'ABSPATH', '\\/var\\/www\\/html\\/' );\\n\\tdefine( 'WP_DEFAULT_THEME', 'default' );/" /var/www/html/wp-config.php > /wordpress-phpunit/wp-tests-config.php`, ], { config: config.dockerComposeConfigPath, From 454129b07628e7fead84f158a4d05580ee5a6d3f Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:20:51 +1000 Subject: [PATCH 0394/1908] `RangeControl`: tweak mark and label absolute positioning (#64487) * This commit tweaks the position of the range control marks and labels to fit the original design. * CHANGELOG.md update Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ .../src/range-control/styles/range-control-styles.ts | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 2530b66152bdc2..f7b7bdc088cee9 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -28,6 +28,10 @@ - `FocalPointPicker`: Default to new 40px size ([#64456](https://github.com/WordPress/gutenberg/pull/64456)). - `DropdownMenuV2`: adopt elevation scale ([#64432](https://github.com/WordPress/gutenberg/pull/64432)). +### Bug Fixes + +- `RangeControl`: tweak mark and label absolute positioning ([#64487](https://github.com/WordPress/gutenberg/pull/64487)). + ### Internal - `Composite` v2: add `Hover` and `Typeahead` subcomponents ([#64399](https://github.com/WordPress/gutenberg/pull/64399)). diff --git a/packages/components/src/range-control/styles/range-control-styles.ts b/packages/components/src/range-control/styles/range-control-styles.ts index 89f4864aee2ea6..ec1572d2679247 100644 --- a/packages/components/src/range-control/styles/range-control-styles.ts +++ b/packages/components/src/range-control/styles/range-control-styles.ts @@ -154,7 +154,7 @@ export const Mark = styled.span` height: ${ thumbSize }px; left: 0; position: absolute; - top: -4px; + top: 9px; width: 1px; ${ markFill }; @@ -170,7 +170,7 @@ export const MarkLabel = styled.span` color: ${ COLORS.gray[ 300 ] }; font-size: 11px; position: absolute; - top: 12px; + top: 22px; white-space: nowrap; ${ rtl( { left: 0 } ) }; From add79ad40619242e31a1cc57f38d1aa44ebb9929 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 15 Aug 2024 12:42:09 +1000 Subject: [PATCH 0395/1908] Style engine: export util to compile CSS custom var from preset string (#64490) Remove `compileStyleValue` in favour of pre-existing `getCSSValueFromRawStyle()` from the style engine package. Update style engine tests to cover bugfix in https://github.com/WordPress/gutenberg/pull/43116 Moves style engine utils tests into correct directory Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- .../global-styles/use-global-styles-output.js | 7 +-- .../src/components/global-styles/utils.js | 31 +--------- packages/style-engine/CHANGELOG.md | 4 ++ packages/style-engine/README.md | 16 +++++ packages/style-engine/src/index.ts | 3 + .../style-engine/src/styles/test/utils.js | 54 ++++++++++++++++ packages/style-engine/src/styles/utils.ts | 18 ++++-- packages/style-engine/src/test/utils.js | 62 ------------------- packages/style-engine/src/types.ts | 2 +- 9 files changed, 96 insertions(+), 101 deletions(-) create mode 100644 packages/style-engine/src/styles/test/utils.js delete mode 100644 packages/style-engine/src/test/utils.js diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index c1449d6d8b298f..cd4ad0cea50e0d 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -10,7 +10,7 @@ import { } from '@wordpress/blocks'; import { useSelect } from '@wordpress/data'; import { useContext, useMemo } from '@wordpress/element'; -import { getCSSRules } from '@wordpress/style-engine'; +import { getCSSRules, getCSSValueFromRawStyle } from '@wordpress/style-engine'; import { privateApis as componentsPrivateApis } from '@wordpress/components'; /** @@ -24,7 +24,6 @@ import { scopeFeatureSelectors, appendToSelector, getBlockStyleVariationSelector, - compileStyleValue, getResolvedValue, } from './utils'; import { getBlockCSSSelector } from './get-block-css-selector'; @@ -357,7 +356,7 @@ export function getStylesDeclarations( ? name : kebabCase( name ); declarations.push( - `${ cssProperty }: ${ compileStyleValue( + `${ cssProperty }: ${ getCSSValueFromRawStyle( getValueFromObjectPath( styleValue, [ prop ] ) ) }` ); @@ -369,7 +368,7 @@ export function getStylesDeclarations( ? key : kebabCase( key ); declarations.push( - `${ cssProperty }: ${ compileStyleValue( + `${ cssProperty }: ${ getCSSValueFromRawStyle( getValueFromObjectPath( blockStyles, pathToValue ) ) }` ); diff --git a/packages/block-editor/src/components/global-styles/utils.js b/packages/block-editor/src/components/global-styles/utils.js index 8de479e39382e5..4cd93357b081b3 100644 --- a/packages/block-editor/src/components/global-styles/utils.js +++ b/packages/block-editor/src/components/global-styles/utils.js @@ -7,6 +7,7 @@ import fastDeepEqual from 'fast-deep-equal/es6'; * WordPress dependencies */ import { useViewportMatch } from '@wordpress/compose'; +import { getCSSValueFromRawStyle } from '@wordpress/style-engine'; /** * Internal dependencies @@ -526,34 +527,6 @@ export function getBlockStyleVariationSelector( variation, blockSelector ) { return result.join( ',' ); } -/** - * Converts style preset values `var:` to CSS custom var values. - * TODO: Export and use the style engine util: getCSSVarFromStyleValue(). - * - * Example: - * - * compileStyleValue( 'var:preset|color|primary' ) // returns 'var(--wp--color-primary)' - * - * @param {string} uncompiledValue A block style value. - * @return {string} The compiled, or original value. - */ -export function compileStyleValue( uncompiledValue ) { - const VARIABLE_REFERENCE_PREFIX = 'var:'; - if ( - 'string' === typeof uncompiledValue && - uncompiledValue?.startsWith?.( VARIABLE_REFERENCE_PREFIX ) - ) { - const VARIABLE_PATH_SEPARATOR_TOKEN_ATTRIBUTE = '|'; - const VARIABLE_PATH_SEPARATOR_TOKEN_STYLE = '--'; - const variable = uncompiledValue - .slice( VARIABLE_REFERENCE_PREFIX.length ) - .split( VARIABLE_PATH_SEPARATOR_TOKEN_ATTRIBUTE ) - .join( VARIABLE_PATH_SEPARATOR_TOKEN_STYLE ); - return `var(--wp--${ variable })`; - } - return uncompiledValue; -} - /** * Looks up a theme file URI based on a relative path. * @@ -591,7 +564,7 @@ export function getResolvedRefValue( ruleValue, tree ) { if ( typeof ruleValue !== 'string' && ruleValue?.ref ) { const refPath = ruleValue.ref.split( '.' ); - const resolvedRuleValue = compileStyleValue( + const resolvedRuleValue = getCSSValueFromRawStyle( getValueFromObjectPath( tree, refPath ) ); diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md index d393e427a63071..42928ac9fbd3c7 100644 --- a/packages/style-engine/CHANGELOG.md +++ b/packages/style-engine/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### New Features + +- Style engine: export util to compile CSS custom var from preset string. ([#64490](https://github.com/WordPress/gutenberg/pull/64490)) + ## 2.5.0 (2024-08-07) ## 2.4.0 (2024-07-24) diff --git a/packages/style-engine/README.md b/packages/style-engine/README.md index 44b78eed8a81a6..14e8edbd0dec26 100644 --- a/packages/style-engine/README.md +++ b/packages/style-engine/README.md @@ -258,6 +258,22 @@ _Changelog_ `6.1.0` Introduced in WordPress core. +### getCSSValueFromRawStyle + +Returns a WordPress CSS custom var value from incoming style preset value. The preset value follows the pattern `var:description|context|slug`. + +Example: + +`getCSSValueFromRawStyle( 'var:preset|color|heavenlyBlue' )` // returns 'var(--wp--preset--color--heavenly-blue)' + +_Parameters_ + +- _styleValue_ `string | any`: A raw style value. + +_Returns_ + +- `string | unknown`: A CSS var value. + <!-- END TOKEN(Autogenerated API docs) --> ## Glossary diff --git a/packages/style-engine/src/index.ts b/packages/style-engine/src/index.ts index fe5b9929877be7..102d5842e7a0be 100644 --- a/packages/style-engine/src/index.ts +++ b/packages/style-engine/src/index.ts @@ -91,3 +91,6 @@ export function getCSSRules( return rules; } + +// Export style utils. +export { getCSSValueFromRawStyle } from './styles/utils'; diff --git a/packages/style-engine/src/styles/test/utils.js b/packages/style-engine/src/styles/test/utils.js new file mode 100644 index 00000000000000..02f0adf494e71f --- /dev/null +++ b/packages/style-engine/src/styles/test/utils.js @@ -0,0 +1,54 @@ +/** + * Internal dependencies + */ +import { camelCaseJoin, getCSSValueFromRawStyle, upperFirst } from '../utils'; + +describe( 'utils', () => { + describe( 'upperFirst()', () => { + it( 'should return an string with a capitalized first letter', () => { + expect( upperFirst( 'toontown' ) ).toEqual( 'Toontown' ); + } ); + } ); + + describe( 'camelCaseJoin()', () => { + it( 'should return a camelCase string', () => { + expect( camelCaseJoin( [ 'toon', 'town' ] ) ).toEqual( 'toonTown' ); + } ); + } ); + + describe( 'getCSSValueFromRawStyle()', () => { + it.each( [ + [ 'min(40%, 400px)', 'min(40%, 400px)' ], + [ + 'var(--wp--preset--color--yellow-bun)', + 'var:preset|color|yellow-bun', + ], + [ 'var(--wp--preset--font-size--h-1)', 'var:preset|font-size|h1' ], + [ + 'var(--wp--preset--font-size--1-px)', + 'var:preset|font-size|1px', + ], + [ + 'var(--wp--preset--color--orange-11-orange)', + 'var:preset|color|orange11orange', + ], + [ + 'var(--wp--preset--color--heavenly-blue)', + 'var:preset|color|heavenlyBlue', + ], + [ + 'var(--wp--preset--background--dark-secrets-100)', + 'var:preset|background|dark_Secrets_100', + ], + [ null, null ], + [ false, false ], + [ 1000, 1000 ], + [ undefined, undefined ], + ] )( + 'should return %s using an incoming value of %s', + ( expected, value ) => { + expect( getCSSValueFromRawStyle( value ) ).toEqual( expected ); + } + ); + } ); +} ); diff --git a/packages/style-engine/src/styles/utils.ts b/packages/style-engine/src/styles/utils.ts index 00e9dab8b5892b..0c9b40c384b101 100644 --- a/packages/style-engine/src/styles/utils.ts +++ b/packages/style-engine/src/styles/utils.ts @@ -61,7 +61,7 @@ export function generateRule( { selector: options?.selector, key: ruleKey, - value: getCSSVarFromStyleValue( styleValue ), + value: getCSSValueFromRawStyle( styleValue ), }, ] : []; @@ -103,7 +103,7 @@ export function generateBoxRules( } else { const sideRules = individualProperties.reduce( ( acc: GeneratedCSSRule[], side: string ) => { - const value: string | undefined = getCSSVarFromStyleValue( + const value = getCSSValueFromRawStyle( getStyleValueByPath( boxStyle, [ side ] ) ); if ( value ) { @@ -127,13 +127,21 @@ export function generateBoxRules( } /** - * Returns a CSS var value from incoming style value following the pattern `var:description|context|slug`. + * Returns a WordPress CSS custom var value from incoming style preset value. + * The preset value follows the pattern `var:description|context|slug`. + * + * Example: + * + * `getCSSValueFromRawStyle( 'var:preset|color|heavenlyBlue' )` // returns 'var(--wp--preset--color--heavenly-blue)' * * @param styleValue A raw style value. * - * @return string A CSS var value. + * @return A CSS var value. */ -export function getCSSVarFromStyleValue( styleValue: string ): string { + +export function getCSSValueFromRawStyle( + styleValue: string | any +): string | unknown { if ( typeof styleValue === 'string' && styleValue.startsWith( VARIABLE_REFERENCE_PREFIX ) diff --git a/packages/style-engine/src/test/utils.js b/packages/style-engine/src/test/utils.js deleted file mode 100644 index 9f1f84d2b45310..00000000000000 --- a/packages/style-engine/src/test/utils.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Internal dependencies - */ -import { - camelCaseJoin, - getCSSVarFromStyleValue, - upperFirst, -} from '../styles/utils'; - -describe( 'utils', () => { - describe( 'upperFirst()', () => { - it( 'should return an string with a capitalized first letter', () => { - expect( upperFirst( 'toontown' ) ).toEqual( 'Toontown' ); - } ); - } ); - - describe( 'camelCaseJoin()', () => { - it( 'should return a camelCase string', () => { - expect( camelCaseJoin( [ 'toon', 'town' ] ) ).toEqual( 'toonTown' ); - } ); - } ); - - describe( 'getCSSVarFromStyleValue()', () => { - it( 'should return a compiled CSS var', () => { - expect( - getCSSVarFromStyleValue( 'var:preset|color|yellow-bun' ) - ).toEqual( 'var(--wp--preset--color--yellow-bun)' ); - } ); - - it( 'should kebab case numbers', () => { - expect( - getCSSVarFromStyleValue( 'var:preset|font-size|h1' ) - ).toEqual( 'var(--wp--preset--font-size--h-1)' ); - } ); - - it( 'should kebab case numbers as prefix', () => { - expect( - getCSSVarFromStyleValue( 'var:preset|font-size|1px' ) - ).toEqual( 'var(--wp--preset--font-size--1-px)' ); - } ); - - it( 'should kebab case both sides of numbers', () => { - expect( - getCSSVarFromStyleValue( 'var:preset|color|orange11orange' ) - ).toEqual( 'var(--wp--preset--color--orange-11-orange)' ); - } ); - - it( 'should kebab case camel case', () => { - expect( - getCSSVarFromStyleValue( 'var:preset|color|heavenlyBlue' ) - ).toEqual( 'var(--wp--preset--color--heavenly-blue)' ); - } ); - - it( 'should kebab case underscores', () => { - expect( - getCSSVarFromStyleValue( - 'var:preset|background|dark_Secrets_100' - ) - ).toEqual( 'var(--wp--preset--background--dark-secrets-100)' ); - } ); - } ); -} ); diff --git a/packages/style-engine/src/types.ts b/packages/style-engine/src/types.ts index 5b361836a8e375..8de623fcfcb2bf 100644 --- a/packages/style-engine/src/types.ts +++ b/packages/style-engine/src/types.ts @@ -94,7 +94,7 @@ export interface StyleOptions { export interface GeneratedCSSRule { selector?: string; - value: string; + value: string | unknown; /** * The CSS key in JS style attribute format, compatible with React. * E.g. `paddingTop` instead of `padding-top`. From de656233be92e37fd1a7fdb0e31cf87824f63776 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:18:30 +0700 Subject: [PATCH 0396/1908] List Item: Add border support (#63541) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- packages/block-library/src/list-item/block.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/list-item/block.json b/packages/block-library/src/list-item/block.json index fc7117d1b792fc..a4bf2351d97509 100644 --- a/packages/block-library/src/list-item/block.json +++ b/packages/block-library/src/list-item/block.json @@ -23,6 +23,12 @@ "anchor": true, "className": false, "splitting": true, + "__experimentalBorder": { + "color": true, + "radius": true, + "style": true, + "width": true + }, "color": { "gradients": true, "link": true, @@ -57,6 +63,7 @@ } }, "selectors": { - "root": ".wp-block-list > li" + "root": ".wp-block-list > li", + "border": ".wp-block-list:not(.wp-block-list .wp-block-list) > li" } } From e6057ce69fb2f743fb0c8a71494f56ff39f5a900 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:19:07 +0700 Subject: [PATCH 0397/1908] List: Add border support (#63540) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> --- packages/block-library/src/list/block.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/block-library/src/list/block.json b/packages/block-library/src/list/block.json index 8b100071c15ea9..ea07a0eb542df3 100644 --- a/packages/block-library/src/list/block.json +++ b/packages/block-library/src/list/block.json @@ -39,6 +39,12 @@ "supports": { "anchor": true, "html": false, + "__experimentalBorder": { + "color": true, + "radius": true, + "style": true, + "width": true + }, "typography": { "fontSize": true, "lineHeight": true, @@ -75,6 +81,9 @@ "clientNavigation": true } }, + "selectors": { + "border": ".wp-block-list:not(.wp-block-list .wp-block-list)" + }, "editorStyle": "wp-block-list-editor", "style": "wp-block-list" } From d669eb661c69af31816ead9359c5986cffcea301 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:44:09 +1000 Subject: [PATCH 0398/1908] Background images: add support for theme.json ref value resolution (#64128) Resolves refs before passing styles to style engine in the WP_Theme_JSON class. Consolidates all resolutions in the background panel (image and ref). Removes useGlobalStyleLinks completely. Delete theme URI utils. Ensures that backgroundImage style objects are not merged, but replaced when merged theme.json configs. For example, an incoming config such as a saved user config should overwrite the background styles of the base theme.json, where it exists. --------- Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- backport-changelog/6.7/7137.md | 1 + lib/class-wp-theme-json-gutenberg.php | 68 +++++--- .../global-styles/background-panel.js | 74 +++++--- .../src/components/global-styles/hooks.js | 5 - .../src/components/global-styles/index.js | 1 - .../test/theme-file-uri-utils.js | 41 ----- .../test/use-global-styles-output.js | 16 ++ .../global-styles/theme-file-uri-utils.js | 18 -- .../src/components/global-styles/utils.js | 5 + packages/block-editor/src/hooks/background.js | 9 +- .../global-styles/background-panel.js | 3 - .../components/global-styles/screen-block.js | 3 - .../global-styles-provider/index.js | 19 ++- .../src/styles/background/index.ts | 26 ++- phpunit/class-wp-theme-json-test.php | 160 ++++++++++++++++++ 15 files changed, 313 insertions(+), 136 deletions(-) delete mode 100644 packages/block-editor/src/components/global-styles/test/theme-file-uri-utils.js delete mode 100644 packages/block-editor/src/components/global-styles/theme-file-uri-utils.js diff --git a/backport-changelog/6.7/7137.md b/backport-changelog/6.7/7137.md index 1eba52ebaf5087..00771b8bc6c21d 100644 --- a/backport-changelog/6.7/7137.md +++ b/backport-changelog/6.7/7137.md @@ -1,4 +1,5 @@ https://github.com/WordPress/wordpress-develop/pull/7137 +* https://github.com/WordPress/gutenberg/pull/64128 * https://github.com/WordPress/gutenberg/pull/64192 * https://github.com/WordPress/gutenberg/pull/64328 diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 20ea31090407b4..756ef06c80aa87 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2329,7 +2329,7 @@ protected static function flatten_tree( $tree, $prefix = '', $token = '--' ) { * ```php * array( * 'name' => 'property_name', - * 'value' => 'property_value, + * 'value' => 'property_value', * ) * ``` * @@ -2338,6 +2338,7 @@ protected static function flatten_tree( $tree, $prefix = '', $token = '--' ) { * @since 6.1.0 Added `$theme_json`, `$selector`, and `$use_root_padding` parameters. * @since 6.5.0 Output a `min-height: unset` rule when `aspect-ratio` is set. * @since 6.6.0 Passing current theme JSON settings to wp_get_typography_font_size_value(). Using style engine to correctly fetch background CSS values. + * @since 6.7.0 Allow ref resolution of background properties. * * @param array $styles Styles to process. * @param array $settings Theme settings. @@ -2381,21 +2382,28 @@ protected static function compute_style_properties( $styles, $settings = array() $root_variable_duplicates[] = substr( $css_property, $root_style_length ); } - // Processes background styles. - if ( 'background' === $value_path[0] && isset( $styles['background'] ) ) { - /* - * For user-uploaded images at the block level, assign defaults. - * Matches defaults applied in the editor and in block supports: background.php. - */ - if ( static::ROOT_BLOCK_SELECTOR !== $selector && ! empty( $styles['background']['backgroundImage']['id'] ) ) { - $styles['background']['backgroundSize'] = $styles['background']['backgroundSize'] ?? 'cover'; - // If the background size is set to `contain` and no position is set, set the position to `center`. - if ( 'contain' === $styles['background']['backgroundSize'] && empty( $styles['background']['backgroundPosition'] ) ) { - $styles['background']['backgroundPosition'] = '50% 50%'; - } + /* + * Processes background image styles. + * If the value is a URL, it will be converted to a CSS `url()` value. + * For an uploaded image (images with a database ID), apply size and position + * defaults equal to those applied in block supports in lib/background.php. + */ + if ( 'background-image' === $css_property && ! empty( $value ) ) { + $background_styles = gutenberg_style_engine_get_styles( + array( 'background' => array( 'backgroundImage' => $value ) ) + ); + + $value = $background_styles['declarations'][ $css_property ]; + } + if ( empty( $value ) && static::ROOT_BLOCK_SELECTOR !== $selector && ! empty( $styles['background']['backgroundImage']['id'] ) ) { + if ( 'background-size' === $css_property ) { + $value = 'cover'; + } + // If the background size is set to `contain` and no position is set, set the position to `center`. + if ( 'background-position' === $css_property ) { + $background_size = $styles['background']['backgroundSize'] ?? null; + $value = 'contain' === $background_size ? '50% 50%' : null; } - $background_styles = gutenberg_style_engine_get_styles( array( 'background' => $styles['background'] ) ); - $value = $background_styles['declarations'][ $css_property ] ?? $value; } // Skip if empty and not "0" or value represents array of longhand values. @@ -2463,6 +2471,7 @@ protected static function compute_style_properties( $styles, $settings = array() * @since 5.8.0 * @since 5.9.0 Added support for values of array type, which are returned as is. * @since 6.1.0 Added the `$theme_json` parameter. + * @since 6.7.0 Added support for background image refs * * @param array $styles Styles subtree. * @param array $path Which property to process. @@ -2479,15 +2488,17 @@ protected static function get_property_value( $styles, $path, $theme_json = null } /* - * This converts references to a path to the value at that path - * where the values is an array with a "ref" key, pointing to a path. + * Where the current value is an array with a 'ref' key pointing + * to a path, this converts that path into the value at that path. * For example: { "ref": "style.color.background" } => "#fff". */ if ( is_array( $value ) && isset( $value['ref'] ) ) { $value_path = explode( '.', $value['ref'] ); - $ref_value = _wp_array_get( $theme_json, $value_path ); + $ref_value = _wp_array_get( $theme_json, $value_path, null ); + // Background Image refs can refer to a string or an array containing a URL string. + $ref_value_url = $ref_value['url'] ?? null; // Only use the ref value if we find anything. - if ( ! empty( $ref_value ) && is_string( $ref_value ) ) { + if ( ! empty( $ref_value ) && ( is_string( $ref_value ) || is_string( $ref_value_url ) ) ) { $value = $ref_value; } @@ -3247,6 +3258,25 @@ public function merge( $incoming ) { } } } + + /* + * Style values are merged at the leaf level, however + * some values provide exceptions, namely style values that are + * objects and represent unique definitions for the style. + */ + $style_nodes = static::get_styles_block_nodes(); + foreach ( $style_nodes as $style_node ) { + $path = $style_node['path']; + /* + * Background image styles should be replaced, not merged, + * as they themselves are specific object definitions for the style. + */ + $background_image_path = array_merge( $path, static::PROPERTIES_METADATA['background-image'] ); + $content = _wp_array_get( $incoming_data, $background_image_path, null ); + if ( isset( $content ) ) { + _wp_array_set( $this->theme_json, $background_image_path, $content ); + } + } } /** diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index 14b37bb3007658..1373c54764d155 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -34,6 +34,7 @@ import { useRef, useState, useEffect, + useMemo, } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; import { focus } from '@wordpress/dom'; @@ -42,11 +43,15 @@ import { isBlobURL } from '@wordpress/blob'; /** * Internal dependencies */ -import { useToolsPanelDropdownMenuProps } from './utils'; +import { useToolsPanelDropdownMenuProps, getResolvedValue } from './utils'; import { setImmutably } from '../../utils/object'; import MediaReplaceFlow from '../media-replace-flow'; import { store as blockEditorStore } from '../../store'; -import { getResolvedThemeFilePath } from './theme-file-uri-utils'; + +import { + globalStylesDataKey, + globalStylesLinksDataKey, +} from '../../store/private-keys'; const IMAGE_BACKGROUND_TYPE = 'image'; const DEFAULT_CONTROLS = { @@ -270,7 +275,6 @@ function BackgroundImageControls( { onRemoveImage = noop, onResetImage = noop, displayInPanel, - themeFileURIs, defaultValues, } ) { const mediaUpload = useSelect( @@ -404,10 +408,7 @@ function BackgroundImageControls( { name={ <InspectorImagePreviewItem className="block-editor-global-styles-background-panel__image-preview" - imgUrl={ getResolvedThemeFilePath( - url, - themeFileURIs - ) } + imgUrl={ url } filename={ title } label={ imgLabel } /> @@ -449,7 +450,6 @@ function BackgroundSizeControls( { style, inheritedValue, defaultValues, - themeFileURIs, } ) { const sizeValue = style?.background?.backgroundSize || @@ -587,7 +587,7 @@ function BackgroundSizeControls( { <FocalPointPicker __nextHasNoMarginBottom label={ __( 'Focal point' ) } - url={ getResolvedThemeFilePath( imageValue, themeFileURIs ) } + url={ imageValue } value={ backgroundPositionToCoords( backgroundPositionValue ) } onChange={ updateBackgroundPosition } /> @@ -697,8 +697,44 @@ export default function BackgroundPanel( { defaultControls = DEFAULT_CONTROLS, defaultValues = {}, headerLabel = __( 'Background image' ), - themeFileURIs, } ) { + /* + * Resolve any inherited "ref" pointers. + * Should the block editor need resolved, inherited values + * across all controls, this could be abstracted into a hook, + * e.g., useResolveGlobalStyle + */ + const { globalStyles, _links } = useSelect( ( select ) => { + const { getSettings } = select( blockEditorStore ); + const _settings = getSettings(); + return { + globalStyles: _settings[ globalStylesDataKey ], + _links: _settings[ globalStylesLinksDataKey ], + }; + }, [] ); + const resolvedInheritedValue = useMemo( () => { + const resolvedValues = { + background: {}, + }; + + if ( ! inheritedValue?.background ) { + return inheritedValue; + } + + Object.entries( inheritedValue?.background ).forEach( + ( [ key, backgroundValue ] ) => { + resolvedValues.background[ key ] = getResolvedValue( + backgroundValue, + { + styles: globalStyles, + _links, + } + ); + } + ); + return resolvedValues; + }, [ globalStyles, _links, inheritedValue ] ); + const resetAllFilter = useCallback( ( previousValue ) => { return { ...previousValue, @@ -710,11 +746,11 @@ export default function BackgroundPanel( { onChange( setImmutably( value, [ 'background' ], {} ) ); const { title, url } = value?.background?.backgroundImage || { - ...inheritedValue?.background?.backgroundImage, + ...resolvedInheritedValue?.background?.backgroundImage, }; const hasImageValue = hasBackgroundImageValue( value ) || - hasBackgroundImageValue( inheritedValue ); + hasBackgroundImageValue( resolvedInheritedValue ); const imageValue = value?.background?.backgroundImage || @@ -756,10 +792,7 @@ export default function BackgroundPanel( { <BackgroundControlsPanel label={ title } filename={ title } - url={ getResolvedThemeFilePath( - url, - themeFileURIs - ) } + url={ url } onToggle={ setIsDropDownOpen } hasImageValue={ hasImageValue } > @@ -767,8 +800,7 @@ export default function BackgroundPanel( { <BackgroundImageControls onChange={ onChange } style={ value } - inheritedValue={ inheritedValue } - themeFileURIs={ themeFileURIs } + inheritedValue={ resolvedInheritedValue } displayInPanel onResetImage={ () => { setIsDropDownOpen( false ); @@ -784,8 +816,7 @@ export default function BackgroundPanel( { panelId={ panelId } style={ value } defaultValues={ defaultValues } - inheritedValue={ inheritedValue } - themeFileURIs={ themeFileURIs } + inheritedValue={ resolvedInheritedValue } /> </VStack> </BackgroundControlsPanel> @@ -793,8 +824,7 @@ export default function BackgroundPanel( { <BackgroundImageControls onChange={ onChange } style={ value } - inheritedValue={ inheritedValue } - themeFileURIs={ themeFileURIs } + inheritedValue={ resolvedInheritedValue } defaultValues={ defaultValues } onResetImage={ () => { setIsDropDownOpen( false ); diff --git a/packages/block-editor/src/components/global-styles/hooks.js b/packages/block-editor/src/components/global-styles/hooks.js index a1a4fc1a0a6ae1..2be77aec18a2c6 100644 --- a/packages/block-editor/src/components/global-styles/hooks.js +++ b/packages/block-editor/src/components/global-styles/hooks.js @@ -209,11 +209,6 @@ export function useGlobalStyle( return [ result, setStyle ]; } -export function useGlobalStyleLinks() { - const { merged: mergedConfig } = useContext( GlobalStylesContext ); - return mergedConfig?._links; -} - /** * React hook that overrides a global settings object with block and element specific settings. * diff --git a/packages/block-editor/src/components/global-styles/index.js b/packages/block-editor/src/components/global-styles/index.js index 062df0a5606e90..8096a48569f199 100644 --- a/packages/block-editor/src/components/global-styles/index.js +++ b/packages/block-editor/src/components/global-styles/index.js @@ -3,7 +3,6 @@ export { useGlobalSetting, useGlobalStyle, useSettingsForBlockElement, - useGlobalStyleLinks, } from './hooks'; export { getBlockCSSSelector } from './get-block-css-selector'; export { diff --git a/packages/block-editor/src/components/global-styles/test/theme-file-uri-utils.js b/packages/block-editor/src/components/global-styles/test/theme-file-uri-utils.js deleted file mode 100644 index e239bb0941ea9e..00000000000000 --- a/packages/block-editor/src/components/global-styles/test/theme-file-uri-utils.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Internal dependencies - */ -import { getResolvedThemeFilePath } from '../theme-file-uri-utils'; - -const themeFileURIs = [ - { - name: 'file:./assets/image.jpg', - href: 'https://wordpress.org/assets/image.jpg', - target: 'styles.background.backgroundImage.url', - }, - { - name: 'file:./assets/other/image.jpg', - href: 'https://wordpress.org/assets/other/image.jpg', - target: "styles.blocks.['core/group].background.backgroundImage.url", - }, -]; - -describe( 'getResolvedThemeFilePath()', () => { - it.each( [ - [ - 'file:./assets/image.jpg', - 'https://wordpress.org/assets/image.jpg', - 'Should return absolute URL if found in themeFileURIs', - ], - [ - 'file:./misc/image.jpg', - 'file:./misc/image.jpg', - 'Should return value if not found in themeFileURIs', - ], - [ - 'https://wordpress.org/assets/image.jpg', - 'https://wordpress.org/assets/image.jpg', - 'Should not match absolute URLs', - ], - ] )( 'Given file %s and return value %s: %s', ( file, returnedValue ) => { - expect( - getResolvedThemeFilePath( file, themeFileURIs ) === returnedValue - ).toBe( true ); - } ); -} ); diff --git a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js index 1b061f6921f2c2..5022e8ba591dbb 100644 --- a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js @@ -1008,9 +1008,23 @@ describe( 'global styles renderer', () => { ref: 'styles.elements.h1.typography.letterSpacing', }, }, + background: { + backgroundImage: { + ref: 'styles.background.backgroundImage', + }, + backgroundSize: { + ref: 'styles.background.backgroundSize', + }, + }, }; const tree = { styles: { + background: { + backgroundImage: { + url: 'http://my-image.org/image.gif', + }, + backgroundSize: 'cover', + }, elements: { h1: { typography: { @@ -1026,6 +1040,8 @@ describe( 'global styles renderer', () => { ).toEqual( [ 'font-size: var(--wp--preset--font-size--xx-large)', 'letter-spacing: 2px', + "background-image: url( 'http://my-image.org/image.gif' )", + 'background-size: cover', ] ); } ); it( 'should set default values for block background styles', () => { diff --git a/packages/block-editor/src/components/global-styles/theme-file-uri-utils.js b/packages/block-editor/src/components/global-styles/theme-file-uri-utils.js deleted file mode 100644 index 96b3e2e4cb68b0..00000000000000 --- a/packages/block-editor/src/components/global-styles/theme-file-uri-utils.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Looks up a theme file URI based on a relative path. - * - * @param {string} file A relative path. - * @param {Array<Object>} themeFileURIs A collection of absolute theme file URIs and their corresponding file paths. - * @return {string?} A resolved theme file URI, if one is found in the themeFileURIs collection. - */ -export function getResolvedThemeFilePath( file, themeFileURIs = [] ) { - const uri = themeFileURIs.find( - ( themeFileUri ) => themeFileUri.name === file - ); - - if ( ! uri?.href ) { - return file; - } - - return uri?.href; -} diff --git a/packages/block-editor/src/components/global-styles/utils.js b/packages/block-editor/src/components/global-styles/utils.js index 4cd93357b081b3..59799c9032c67f 100644 --- a/packages/block-editor/src/components/global-styles/utils.js +++ b/packages/block-editor/src/components/global-styles/utils.js @@ -562,6 +562,11 @@ export function getResolvedRefValue( ruleValue, tree ) { return ruleValue; } + /* + * Where the rule value is an object with a 'ref' property pointing + * to a path, this converts that path into the value at that path. + * For example: { "ref": "style.color.background" } => "#fff". + */ if ( typeof ruleValue !== 'string' && ruleValue?.ref ) { const refPath = ruleValue.ref.split( '.' ); const resolvedRuleValue = getCSSValueFromRawStyle( diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index 0d38068cdefeea..3755aecbcb9d0b 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -16,10 +16,7 @@ import { useHasBackgroundPanel, hasBackgroundImageValue, } from '../components/global-styles/background-panel'; -import { - globalStylesDataKey, - globalStylesLinksDataKey, -} from '../store/private-keys'; +import { globalStylesDataKey } from '../store/private-keys'; export const BACKGROUND_SUPPORT_KEY = 'background'; @@ -136,14 +133,13 @@ export function BackgroundImagePanel( { setAttributes, settings, } ) { - const { style, inheritedValue, _links } = useSelect( + const { style, inheritedValue } = useSelect( ( select ) => { const { getBlockAttributes, getSettings } = select( blockEditorStore ); const _settings = getSettings(); return { style: getBlockAttributes( clientId )?.style, - _links: _settings[ globalStylesLinksDataKey ], /* * To ensure we pass down the right inherited values: * @TODO 1. Pass inherited value down to all block style controls, @@ -190,7 +186,6 @@ export function BackgroundImagePanel( { settings={ updatedSettings } onChange={ onChange } value={ style } - themeFileURIs={ _links?.[ 'wp:theme-file' ] } /> ); } diff --git a/packages/edit-site/src/components/global-styles/background-panel.js b/packages/edit-site/src/components/global-styles/background-panel.js index 24ab914bed8c52..e185079d8cee04 100644 --- a/packages/edit-site/src/components/global-styles/background-panel.js +++ b/packages/edit-site/src/components/global-styles/background-panel.js @@ -16,7 +16,6 @@ const BACKGROUND_DEFAULT_VALUES = { const { useGlobalStyle, useGlobalSetting, - useGlobalStyleLinks, BackgroundPanel: StylesBackgroundPanel, } = unlock( blockEditorPrivateApis ); @@ -42,7 +41,6 @@ export default function BackgroundPanel() { const [ inheritedStyle, setStyle ] = useGlobalStyle( '', undefined, 'all', { shouldDecodeEncode: false, } ); - const _links = useGlobalStyleLinks(); const [ settings ] = useGlobalSetting( '' ); return ( @@ -52,7 +50,6 @@ export default function BackgroundPanel() { onChange={ setStyle } settings={ settings } defaultValues={ BACKGROUND_DEFAULT_VALUES } - themeFileURIs={ _links?.[ 'wp:theme-file' ] } /> ); } diff --git a/packages/edit-site/src/components/global-styles/screen-block.js b/packages/edit-site/src/components/global-styles/screen-block.js index dee921f37f1e8a..b1489167f2dc75 100644 --- a/packages/edit-site/src/components/global-styles/screen-block.js +++ b/packages/edit-site/src/components/global-styles/screen-block.js @@ -85,7 +85,6 @@ const { FiltersPanel: StylesFiltersPanel, ImageSettingsPanel, AdvancedPanel: StylesAdvancedPanel, - useGlobalStyleLinks, } = unlock( blockEditorPrivateApis ); function ScreenBlock( { name, variation } ) { @@ -105,7 +104,6 @@ function ScreenBlock( { name, variation } ) { const [ rawSettings, setSettings ] = useGlobalSetting( '', name ); const settings = useSettingsForBlockElement( rawSettings, name ); const blockType = getBlockType( name ); - const _links = useGlobalStyleLinks(); // Only allow `blockGap` support if serialization has not been skipped, to be sure global spacing can be applied. if ( @@ -272,7 +270,6 @@ function ScreenBlock( { name, variation } ) { onChange={ setStyle } settings={ settings } defaultValues={ BACKGROUND_BLOCK_DEFAULT_VALUES } - themeFileURIs={ _links?.[ 'wp:theme-file' ] } /> ) } { hasTypographyPanel && ( diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js index 8ac292fb2ce0b2..8426593d8f5f51 100644 --- a/packages/editor/src/components/global-styles-provider/index.js +++ b/packages/editor/src/components/global-styles-provider/index.js @@ -23,10 +23,23 @@ const { GlobalStylesContext, cleanEmptyObject } = unlock( export function mergeBaseAndUserConfigs( base, user ) { return deepmerge( base, user, { - // We only pass as arrays the presets, - // in which case we want the new array of values - // to override the old array (no merging). + /* + * We only pass as arrays the presets, + * in which case we want the new array of values + * to override the old array (no merging). + */ isMergeableObject: isPlainObject, + /* + * Exceptions to the above rule. + * Background images should be replaced, not merged, + * as they themselves are specific object definitions for the style. + */ + customMerge: ( key ) => { + if ( key === 'backgroundImage' ) { + return ( baseConfig, userConfig ) => userConfig; + } + return undefined; + }, } ); } diff --git a/packages/style-engine/src/styles/background/index.ts b/packages/style-engine/src/styles/background/index.ts index 211b97343d89cc..b943032f9c4417 100644 --- a/packages/style-engine/src/styles/background/index.ts +++ b/packages/style-engine/src/styles/background/index.ts @@ -8,6 +8,12 @@ const backgroundImage = { name: 'backgroundImage', generate: ( style: Style, options: StyleOptions ) => { const _backgroundImage = style?.background?.backgroundImage; + + /* + * The background image can be a string or an object. + * If the background image is a string, it could already contain a url() function, + * or have a linear-gradient value. + */ if ( typeof _backgroundImage === 'object' && _backgroundImage?.url ) { return [ { @@ -21,20 +27,12 @@ const backgroundImage = { ]; } - /* - * If the background image is a string, it could already contain a url() function, - * or have a linear-gradient value. - */ - if ( typeof _backgroundImage === 'string' ) { - return generateRule( - style, - options, - [ 'background', 'backgroundImage' ], - 'backgroundImage' - ); - } - - return []; + return generateRule( + style, + options, + [ 'background', 'backgroundImage' ], + 'backgroundImage' + ); }, }; diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 3f11dd97a6688f..10bb47b87fba89 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -2294,6 +2294,112 @@ public function test_merge_incoming_data_presets_use_default_names() { $this->assertSameSetsWithIndex( $expected, $actual ); } + public function test_merge_incoming_background_styles() { + $theme_json = new WP_Theme_JSON_Gutenberg( + array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'background' => array( + 'backgroundImage' => array( + 'url' => 'http://example.org/quote.png', + ), + 'backgroundSize' => 'cover', + ), + 'blocks' => array( + 'core/group' => array( + 'background' => array( + 'backgroundImage' => array( + 'ref' => 'styles.blocks.core/verse.background.backgroundImage', + ), + 'backgroundAttachment' => 'fixed', + ), + ), + 'core/quote' => array( + 'background' => array( + 'backgroundImage' => array( + 'url' => 'http://example.org/quote.png', + ), + 'backgroundAttachment' => array( + 'ref' => 'styles.blocks.core/group.background.backgroundAttachment', + ), + ), + ), + ), + ), + ) + ); + + $update_background_image_styles = array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'background' => array( + 'backgroundSize' => 'contain', + ), + 'blocks' => array( + 'core/group' => array( + 'background' => array( + 'backgroundImage' => array( + 'url' => 'http://example.org/group.png', + ), + ), + ), + 'core/quote' => array( + 'background' => array( + 'backgroundAttachment' => 'fixed', + ), + ), + 'core/verse' => array( + 'background' => array( + 'backgroundImage' => array( + 'ref' => 'styles.blocks.core/group.background.backgroundImage', + ), + ), + ), + ), + ), + ); + $expected = array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'background' => array( + 'backgroundImage' => array( + 'url' => 'http://example.org/quote.png', + ), + 'backgroundSize' => 'contain', + ), + 'blocks' => array( + 'core/group' => array( + 'background' => array( + 'backgroundImage' => array( + 'url' => 'http://example.org/group.png', + ), + 'backgroundAttachment' => 'fixed', + ), + ), + 'core/quote' => array( + 'background' => array( + 'backgroundImage' => array( + 'url' => 'http://example.org/quote.png', + ), + 'backgroundAttachment' => 'fixed', + ), + ), + 'core/verse' => array( + 'background' => array( + 'backgroundImage' => array( + 'ref' => 'styles.blocks.core/group.background.backgroundImage', + ), + ), + ), + ), + ), + ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $update_background_image_styles ) ); + $actual = $theme_json->get_raw_data(); + + $this->assertEqualSetsWithIndex( $expected, $actual ); + } + public function test_remove_insecure_properties_removes_unsafe_styles() { $actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( array( @@ -4915,6 +5021,60 @@ public function test_get_block_background_image_styles() { $this->assertSameCSS( $verse_styles, $theme_json->get_styles_for_block( $verse_node ), 'Styles returned from "::get_styles_for_block()" with default core/verse background styles as string type do not match expectations' ); } + /** + * Testing background dynamic properties in theme.json. + */ + public function test_get_resolved_background_image_styles() { + $theme_json = new WP_Theme_JSON_Gutenberg( + array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'background' => array( + 'backgroundImage' => array( + 'url' => 'http://example.org/top.png', + ), + 'backgroundSize' => 'contain', + 'backgroundRepeat' => 'repeat', + 'backgroundPosition' => '10% 20%', + 'backgroundAttachment' => 'scroll', + ), + 'blocks' => array( + 'core/group' => array( + 'background' => array( + 'backgroundImage' => array( + 'id' => 123, + 'url' => 'http://example.org/group.png', + ), + ), + ), + 'core/post-content' => array( + 'background' => array( + 'backgroundImage' => array( + 'ref' => 'styles.background.backgroundImage', + ), + 'backgroundSize' => array( + 'ref' => 'styles.background.backgroundSize', + ), + 'backgroundRepeat' => array( + 'ref' => 'styles.background.backgroundRepeat', + ), + 'backgroundPosition' => array( + 'ref' => 'styles.background.backgroundPosition', + ), + 'backgroundAttachment' => array( + 'ref' => 'styles.background.backgroundAttachment', + ), + ), + ), + ), + ), + ) + ); + + $expected = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}body{background-image: url('http://example.org/top.png');background-position: 10% 20%;background-repeat: repeat;background-size: contain;background-attachment: scroll;}:root :where(.wp-block-group){background-image: url('http://example.org/group.png');background-size: cover;}:root :where(.wp-block-post-content){background-image: url('http://example.org/top.png');background-position: 10% 20%;background-repeat: repeat;background-size: contain;background-attachment: scroll;}"; + $this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); + } + /** * Tests that base custom CSS is generated correctly. */ From c8eaf5c0c4f4d0bc07fb39626ae3268bd83fbcfe Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Thu, 15 Aug 2024 11:49:14 +0800 Subject: [PATCH 0399/1908] Components: Allow `style` prop on `Popover` (#64489) * Allow style prop on popover * Ensure styles are not overwritten by popoverProps * Add tests and fix overriding of built-in popover styles * Update comment * Remove blank line * Un-should tests * Update test to use `not.toHaveStyle * Add changelog entry * Remove `style` from types file ---- Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 2 ++ packages/components/src/popover/index.tsx | 12 +++++-- .../components/src/popover/test/index.tsx | 34 +++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index f7b7bdc088cee9..e758e457bdd03e 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -27,6 +27,8 @@ - `TimePicker`: add `hideLabelFromVision` prop ([#64267](https://github.com/WordPress/gutenberg/pull/64267)). - `FocalPointPicker`: Default to new 40px size ([#64456](https://github.com/WordPress/gutenberg/pull/64456)). - `DropdownMenuV2`: adopt elevation scale ([#64432](https://github.com/WordPress/gutenberg/pull/64432)). +- `Popover`: allow `style` prop usage ([#64489](https://github.com/WordPress/gutenberg/pull/64489)). + ### Bug Fixes diff --git a/packages/components/src/popover/index.tsx b/packages/components/src/popover/index.tsx index 68d331ce8266ba..3005f13c952ec0 100644 --- a/packages/components/src/popover/index.tsx +++ b/packages/components/src/popover/index.tsx @@ -113,8 +113,9 @@ const UnforwardedPopover = ( WordPressComponentProps< PopoverProps, 'div', false >, // To avoid overlaps between the standard HTML attributes and the props // expected by `framer-motion`, omit all framer motion props from popover - // props (except for `animate` and `children`, which are re-defined in `PopoverProps`). - keyof Omit< MotionProps, 'animate' | 'children' > + // props (except for `animate` and `children` which are re-defined in + // `PopoverProps`, and `style` which is merged safely). + keyof Omit< MotionProps, 'animate' | 'children' | 'style' > >, forwardedRef: ForwardedRef< any > ) => { @@ -139,6 +140,7 @@ const UnforwardedPopover = ( shift = false, inline = false, variant, + style: contentStyle, // Deprecated props __unstableForcePosition, @@ -370,6 +372,7 @@ const UnforwardedPopover = ( const animationProps: HTMLMotionProps< 'div' > = shouldAnimate ? { style: { + ...contentStyle, ...motionInlineStyles, ...style, }, @@ -378,7 +381,10 @@ const UnforwardedPopover = ( } : { animate: false, - style, + style: { + ...contentStyle, + ...style, + }, }; // When Floating UI has finished positioning and Framer Motion has finished animating diff --git a/packages/components/src/popover/test/index.tsx b/packages/components/src/popover/test/index.tsx index f5ee7e96e4c54d..eac0f942df2f6e 100644 --- a/packages/components/src/popover/test/index.tsx +++ b/packages/components/src/popover/test/index.tsx @@ -179,6 +179,40 @@ describe( 'Popover', () => { } ); } ); + describe( 'style', () => { + it( 'outputs inline styles added through the style prop in addition to built-in popover positioning styles', async () => { + render( + <Popover + style={ { zIndex: 0 } } + data-testid="popover-element" + > + Hello + </Popover> + ); + const popover = screen.getByTestId( 'popover-element' ); + + await waitFor( () => expect( popover ).toBeVisible() ); + expect( popover ).toHaveStyle( + 'position: absolute; top: 0px; left: 0px; z-index: 0;' + ); + } ); + + it( 'is not possible to override built-in popover positioning styles via the style prop', async () => { + render( + <Popover + style={ { position: 'static' } } + data-testid="popover-element" + > + Hello + </Popover> + ); + const popover = screen.getByTestId( 'popover-element' ); + + await waitFor( () => expect( popover ).toBeVisible() ); + expect( popover ).not.toHaveStyle( 'position: static;' ); + } ); + } ); + describe( 'focus behavior', () => { it( 'should focus the popover container when opened', async () => { render( From 9a9186cd09424a91e3cf59288e2290d6d6867f73 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Thu, 15 Aug 2024 10:25:18 +0530 Subject: [PATCH 0400/1908] Comment Content: Add Border Support (#64230) * Commtent Content: Add Border Support * fixed lint issue * Commtent Content: Add Border Support * Added style at root level * fixed lint issue * Added Border box in Editor Side * Added suggested changes * Fixed Conflict Issue * Removed Duplicate css * remove editor style Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- .../block-library/src/comment-content/block.json | 15 ++++++++++++++- .../block-library/src/comment-content/style.scss | 5 +++++ packages/block-library/src/style.scss | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/comment-content/block.json b/packages/block-library/src/comment-content/block.json index 9ac4b5453365bb..0e812299a45e89 100644 --- a/packages/block-library/src/comment-content/block.json +++ b/packages/block-library/src/comment-content/block.json @@ -35,6 +35,18 @@ "fontSize": true } }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + }, "spacing": { "padding": [ "horizontal", "vertical" ], "__experimentalDefaultControls": { @@ -42,5 +54,6 @@ } }, "html": false - } + }, + "style": "wp-block-comment-content" } diff --git a/packages/block-library/src/comment-content/style.scss b/packages/block-library/src/comment-content/style.scss index dd9c4b22ae99c1..a94048de6014d3 100644 --- a/packages/block-library/src/comment-content/style.scss +++ b/packages/block-library/src/comment-content/style.scss @@ -3,3 +3,8 @@ font-size: 0.875em; line-height: 1.5; } + +.wp-block-comment-content { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; +} diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index df1337d7eb25c0..86fe5a3eefabaf 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -11,6 +11,7 @@ @import "./comments-pagination/style.scss"; @import "./comment-template/style.scss"; @import "./comment-date/style.scss"; +@import "./comment-content/style.scss"; @import "./cover/style.scss"; @import "./details/style.scss"; @import "./embed/style.scss"; From 38c233fef036073ce4aded4ae9f5ea3b43a45d48 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 15 Aug 2024 16:12:15 +1000 Subject: [PATCH 0401/1908] Style engine: update type for getCSSValueFromRawStyle (#64528) * Use a generic type parameter StyleValue to describe argument and return value. By default, StyleValue is set to string. This allows the function to be flexible with the type of styleValue, but it defaults to handling strings. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- packages/style-engine/README.md | 8 +++++--- packages/style-engine/src/styles/utils.ts | 18 ++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/style-engine/README.md b/packages/style-engine/README.md index 14e8edbd0dec26..a3e302fab4bb9a 100644 --- a/packages/style-engine/README.md +++ b/packages/style-engine/README.md @@ -260,7 +260,9 @@ _Changelog_ ### getCSSValueFromRawStyle -Returns a WordPress CSS custom var value from incoming style preset value. The preset value follows the pattern `var:description|context|slug`. +Returns a WordPress CSS custom var value from incoming style preset value, if one is detected. + +The preset value is a string and follows the pattern `var:description|context|slug`. Example: @@ -268,11 +270,11 @@ Example: _Parameters_ -- _styleValue_ `string | any`: A raw style value. +- _styleValue_ `StyleValue`: A string representing a raw CSS value. Non-strings won't be processed. _Returns_ -- `string | unknown`: A CSS var value. +- `StyleValue`: A CSS custom var value if the incoming style value is a preset value. <!-- END TOKEN(Autogenerated API docs) --> diff --git a/packages/style-engine/src/styles/utils.ts b/packages/style-engine/src/styles/utils.ts index 0c9b40c384b101..74a18d2c2a6e45 100644 --- a/packages/style-engine/src/styles/utils.ts +++ b/packages/style-engine/src/styles/utils.ts @@ -127,21 +127,23 @@ export function generateBoxRules( } /** - * Returns a WordPress CSS custom var value from incoming style preset value. - * The preset value follows the pattern `var:description|context|slug`. + * Returns a WordPress CSS custom var value from incoming style preset value, + * if one is detected. + * + * The preset value is a string and follows the pattern `var:description|context|slug`. * * Example: * * `getCSSValueFromRawStyle( 'var:preset|color|heavenlyBlue' )` // returns 'var(--wp--preset--color--heavenly-blue)' * - * @param styleValue A raw style value. + * @param styleValue A string representing a raw CSS value. Non-strings won't be processed. * - * @return A CSS var value. + * @return A CSS custom var value if the incoming style value is a preset value. */ -export function getCSSValueFromRawStyle( - styleValue: string | any -): string | unknown { +export function getCSSValueFromRawStyle< StyleValue = string >( + styleValue: StyleValue +): StyleValue { if ( typeof styleValue === 'string' && styleValue.startsWith( VARIABLE_REFERENCE_PREFIX ) @@ -160,7 +162,7 @@ export function getCSSValueFromRawStyle( } ) ) .join( VARIABLE_PATH_SEPARATOR_TOKEN_STYLE ); - return `var(--wp--${ variable })`; + return `var(--wp--${ variable })` as StyleValue; } return styleValue; } From 8fc4c29ef51b1e0dd07000ee4374116a7bad3b71 Mon Sep 17 00:00:00 2001 From: Robert Anderson <robert@noisysocks.com> Date: Thu, 15 Aug 2024 16:18:53 +1000 Subject: [PATCH 0402/1908] GridPopover: Avoid over-selecting by using a new getBlockStyles private selector (#64386) * Add getBlockStyles selector so avoid over-selecting in GridPopover * Will an empty commit make the tests run? --- .../src/components/grid/grid-visualizer.js | 17 ++-- .../src/store/private-selectors.js | 21 +++++ .../src/store/test/private-selectors.js | 89 +++++++++++++++++++ 3 files changed, 122 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/grid/grid-visualizer.js b/packages/block-editor/src/components/grid/grid-visualizer.js index fad2f5cfb14835..81da0457ffc5ca 100644 --- a/packages/block-editor/src/components/grid/grid-visualizer.js +++ b/packages/block-editor/src/components/grid/grid-visualizer.js @@ -19,6 +19,7 @@ import { range, GridRect, getGridInfo } from './utils'; import { store as blockEditorStore } from '../../store'; import { useGetNumberOfBlocksBeforeCell } from './use-get-number-of-blocks-before-cell'; import ButtonBlockAppender from '../button-block-appender'; +import { unlock } from '../../lock-unlock'; export function GridVisualizer( { clientId, contentRef, parentLayout } ) { const isDistractionFree = useSelect( @@ -118,19 +119,25 @@ const GridVisualizerGrid = forwardRef( function ManualGridVisualizer( { gridClientId, gridInfo } ) { const [ highlightedRect, setHighlightedRect ] = useState( null ); - const gridItems = useSelect( - ( select ) => select( blockEditorStore ).getBlocks( gridClientId ), + const gridItemStyles = useSelect( + ( select ) => { + const { getBlockOrder, getBlockStyles } = unlock( + select( blockEditorStore ) + ); + const blockOrder = getBlockOrder( gridClientId ); + return getBlockStyles( blockOrder ); + }, [ gridClientId ] ); const occupiedRects = useMemo( () => { const rects = []; - for ( const block of gridItems ) { + for ( const style of Object.values( gridItemStyles ) ) { const { columnStart, rowStart, columnSpan = 1, rowSpan = 1, - } = block.attributes.style?.layout || {}; + } = style?.layout ?? {}; if ( ! columnStart || ! rowStart ) { continue; } @@ -144,7 +151,7 @@ function ManualGridVisualizer( { gridClientId, gridInfo } ) { ); } return rects; - }, [ gridItems ] ); + }, [ gridItemStyles ] ); return range( 1, gridInfo.numRows ).map( ( row ) => range( 1, gridInfo.numColumns ).map( ( column ) => { diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index dcd315a0ae2804..7f0a4c58ab6747 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -515,3 +515,24 @@ export function getTemporarilyEditingFocusModeToRevert( state ) { export function getInserterSearchInputRef( state ) { return state.inserterSearchInputRef; } + +/** + * Returns the style attributes of multiple blocks. + * + * @param {Object} state Global application state. + * @param {string[]} clientIds An array of block client IDs. + * + * @return {Object} An object where keys are client IDs and values are the corresponding block styles or undefined. + */ +export const getBlockStyles = createSelector( + ( state, clientIds ) => + clientIds.reduce( ( styles, clientId ) => { + styles[ clientId ] = state.blocks.attributes.get( clientId )?.style; + return styles; + }, {} ), + ( state, clientIds ) => [ + ...clientIds.map( + ( clientId ) => state.blocks.attributes.get( clientId )?.style + ), + ] +); diff --git a/packages/block-editor/src/store/test/private-selectors.js b/packages/block-editor/src/store/test/private-selectors.js index 185da1ffb98046..45432b750bb9eb 100644 --- a/packages/block-editor/src/store/test/private-selectors.js +++ b/packages/block-editor/src/store/test/private-selectors.js @@ -9,6 +9,7 @@ import { getEnabledBlockParents, getExpandedBlock, isDragging, + getBlockStyles, } from '../private-selectors'; import { getBlockEditingMode } from '../selectors'; @@ -509,4 +510,92 @@ describe( 'private selectors', () => { ); } ); } ); + + describe( 'getBlockStyles', () => { + it( 'should return an empty object when no client IDs are provided', () => { + const state = { + blocks: { + attributes: new Map(), + }, + }; + const result = getBlockStyles( state, [] ); + expect( result ).toEqual( {} ); + } ); + + it( 'should return styles for a single block', () => { + const state = { + blocks: { + attributes: new Map( [ + [ 'block-1', { style: { color: 'red' } } ], + ] ), + }, + }; + const result = getBlockStyles( state, [ 'block-1' ] ); + expect( result ).toEqual( { + 'block-1': { color: 'red' }, + } ); + } ); + + it( 'should return styles for multiple blocks', () => { + const state = { + blocks: { + attributes: new Map( [ + [ 'block-1', { style: { color: 'red' } } ], + [ 'block-2', { style: { fontSize: '16px' } } ], + [ 'block-3', { style: { margin: '10px' } } ], + ] ), + }, + }; + const result = getBlockStyles( state, [ + 'block-1', + 'block-2', + 'block-3', + ] ); + expect( result ).toEqual( { + 'block-1': { color: 'red' }, + 'block-2': { fontSize: '16px' }, + 'block-3': { margin: '10px' }, + } ); + } ); + + it( 'should return undefined for blocks without styles', () => { + const state = { + blocks: { + attributes: new Map( [ + [ 'block-1', { style: { color: 'red' } } ], + [ 'block-2', {} ], + [ 'block-3', { style: { margin: '10px' } } ], + ] ), + }, + }; + const result = getBlockStyles( state, [ + 'block-1', + 'block-2', + 'block-3', + ] ); + expect( result ).toEqual( { + 'block-1': { color: 'red' }, + 'block-2': undefined, + 'block-3': { margin: '10px' }, + } ); + } ); + + it( 'should return undefined for non-existent blocks', () => { + const state = { + blocks: { + attributes: new Map( [ + [ 'block-1', { style: { color: 'red' } } ], + ] ), + }, + }; + const result = getBlockStyles( state, [ + 'block-1', + 'non-existent-block', + ] ); + expect( result ).toEqual( { + 'block-1': { color: 'red' }, + 'non-existent-block': undefined, + } ); + } ); + } ); } ); From 1dfcd70549bacd2ec26623d4ecf62559ff40b72c Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 15 Aug 2024 09:28:46 +0200 Subject: [PATCH 0403/1908] Paste: fix blob uploading (#64479) --- packages/block-library/src/image/transforms.js | 8 +++++++- packages/block-library/src/video/transforms.js | 6 +++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/image/transforms.js b/packages/block-library/src/image/transforms.js index fda29a2ca2530a..0e1dfb6ee9da44 100644 --- a/packages/block-library/src/image/transforms.js +++ b/packages/block-library/src/image/transforms.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { createBlobURL } from '@wordpress/blob'; +import { createBlobURL, isBlobURL } from '@wordpress/blob'; import { createBlock, getBlockAttributes } from '@wordpress/blocks'; import { dispatch } from '@wordpress/data'; import { store as noticesStore } from '@wordpress/notices'; @@ -123,6 +123,12 @@ const transforms = { anchor, } ); + + if ( isBlobURL( attributes.url ) ) { + attributes.blob = attributes.url; + delete attributes.url; + } + return createBlock( 'core/image', attributes ); }, }, diff --git a/packages/block-library/src/video/transforms.js b/packages/block-library/src/video/transforms.js index c1bbb3431aaf37..4325cd1e7e7e9d 100644 --- a/packages/block-library/src/video/transforms.js +++ b/packages/block-library/src/video/transforms.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { createBlobURL } from '@wordpress/blob'; +import { createBlobURL, isBlobURL } from '@wordpress/blob'; import { createBlock } from '@wordpress/blocks'; const transforms = { @@ -92,6 +92,10 @@ const transforms = { poster: videoElement.getAttribute( 'poster' ) || undefined, src: videoElement.getAttribute( 'src' ) || undefined, }; + if ( isBlobURL( attributes.src ) ) { + attributes.blob = attributes.src; + delete attributes.src; + } return createBlock( 'core/video', attributes ); }, }, From f5f0c67ca561da46fe5430df75c4beffc8b1ce8d Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Thu, 15 Aug 2024 10:04:12 +0100 Subject: [PATCH 0404/1908] Add private isZoomOutMode selector (#64503) --- packages/block-editor/src/store/private-selectors.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 7f0a4c58ab6747..58479d69cbfbe7 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -536,3 +536,14 @@ export const getBlockStyles = createSelector( ), ] ); + +/** + * Returns whether zoom out mode is enabled. + * + * @param {Object} state Editor state. + * + * @return {boolean} Is zoom out mode enabled. + */ +export function isZoomOutMode( state ) { + return state.editorMode === 'zoom-out'; +} From 8fc3df806a7e3494937477155fad18f92fdb9538 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Thu, 15 Aug 2024 14:53:48 +0530 Subject: [PATCH 0405/1908] Post Author Name: Add Border Support (#64530) * Post Author Name: Border Support * Post Author Name: Border Support * Keep Spacing Controle bydefault * Added Border Control Display By Default Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- .../block-library/src/post-author-name/block.json | 15 ++++++++++++++- .../block-library/src/post-author-name/style.scss | 4 ++++ packages/block-library/src/style.scss | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 packages/block-library/src/post-author-name/style.scss diff --git a/packages/block-library/src/post-author-name/block.json b/packages/block-library/src/post-author-name/block.json index 31874ddbf9bc5d..68d2c49bd91056 100644 --- a/packages/block-library/src/post-author-name/block.json +++ b/packages/block-library/src/post-author-name/block.json @@ -53,6 +53,19 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } - } + }, + "style": "wp-block-post-author-name" } diff --git a/packages/block-library/src/post-author-name/style.scss b/packages/block-library/src/post-author-name/style.scss new file mode 100644 index 00000000000000..0f57b30490fa68 --- /dev/null +++ b/packages/block-library/src/post-author-name/style.scss @@ -0,0 +1,4 @@ +.wp-block-post-author-name { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; +} diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index 86fe5a3eefabaf..338753ae53fcbf 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -40,6 +40,7 @@ @import "./post-terms/style.scss"; @import "./post-time-to-read/style.scss"; @import "./post-title/style.scss"; +@import "./post-author-name/style.scss"; @import "./preformatted/style.scss"; @import "./pullquote/style.scss"; @import "./post-template/style.scss"; From 787895eb794432803d45f88c4da9addb7bda0202 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Thu, 15 Aug 2024 16:18:23 +0530 Subject: [PATCH 0406/1908] Updated small typo in compat.php file (#64535) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- lib/compat/wordpress-6.7/compat.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compat/wordpress-6.7/compat.php b/lib/compat/wordpress-6.7/compat.php index 7021cab2053eff..edc8e3fa5fb03f 100644 --- a/lib/compat/wordpress-6.7/compat.php +++ b/lib/compat/wordpress-6.7/compat.php @@ -64,7 +64,7 @@ function ( $registered_template ) use ( $template_files ) { * Hooks into `get_block_template` to add the `plugin` property when necessary. * * @param [WP_Block_Template|null] $block_template The found block template, or null if there isn’t one. - * @return [WP_Block_Template|null] The block template that was already found with the plugin property defined if it was reigstered by a plugin. + * @return [WP_Block_Template|null] The block template that was already found with the plugin property defined if it was registered by a plugin. */ function _gutenberg_add_block_template_plugin_attribute( $block_template ) { if ( $block_template ) { From cdbd5829e24459f9f2e23132ae46824ec1571c85 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 15 Aug 2024 20:10:38 +0900 Subject: [PATCH 0407/1908] ToggleGroupControl: Add lint rule for 40px size prop usage (#64524) * Fix in blocks * Fix in Navigation block * Fix in Comments Pagination block * Fix in Grid layout * Fix in Flex layout * Fix in Constrained layout (e.g. Group block) * Add lint rule Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .eslintrc.js | 1 + packages/block-editor/src/layouts/constrained.js | 1 + packages/block-editor/src/layouts/flex.js | 2 ++ packages/block-editor/src/layouts/grid.js | 1 + .../comments-pagination-arrow-controls.js | 1 + packages/block-library/src/navigation/edit/index.js | 6 +++--- .../src/navigation/edit/overlay-menu-preview.js | 2 ++ packages/block-library/src/navigation/editor.scss | 5 +++++ .../src/post-featured-image/dimension-controls.js | 1 + packages/block-library/src/post-navigation-link/edit.js | 1 + .../src/query-pagination/query-pagination-arrow-controls.js | 1 + 11 files changed, 19 insertions(+), 3 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index eb2d2db47e4cab..94b443853e0a81 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -315,6 +315,7 @@ module.exports = { 'BorderControl', 'DimensionControl', 'FontSizePicker', + 'ToggleGroupControl', ].map( ( componentName ) => ( { // Falsy `__next40pxDefaultSize` without a non-default `size` prop. selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"][value.expression.value!=false])):not(:has(JSXAttribute[name.name="size"][value.value!="default"]))`, diff --git a/packages/block-editor/src/layouts/constrained.js b/packages/block-editor/src/layouts/constrained.js index 2e671e8e53975a..b48e331792bd8a 100644 --- a/packages/block-editor/src/layouts/constrained.js +++ b/packages/block-editor/src/layouts/constrained.js @@ -125,6 +125,7 @@ export default { ) } { allowJustification && ( <ToggleGroupControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Justification' ) } value={ justifyContent } diff --git a/packages/block-editor/src/layouts/flex.js b/packages/block-editor/src/layouts/flex.js index 72beca11b3f0c9..afefc2d5f103a3 100644 --- a/packages/block-editor/src/layouts/flex.js +++ b/packages/block-editor/src/layouts/flex.js @@ -325,6 +325,7 @@ function FlexLayoutJustifyContentControl( { return ( <ToggleGroupControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Justification' ) } value={ justifyContent } @@ -370,6 +371,7 @@ function OrientationControl( { layout, onChange } ) { } = layout; return ( <ToggleGroupControl + __next40pxDefaultSize __nextHasNoMarginBottom className="block-editor-hooks__flex-layout-orientation-controls" label={ __( 'Orientation' ) } diff --git a/packages/block-editor/src/layouts/grid.js b/packages/block-editor/src/layouts/grid.js index 395d0ca1e9d833..c574ad0ae43d5d 100644 --- a/packages/block-editor/src/layouts/grid.js +++ b/packages/block-editor/src/layouts/grid.js @@ -449,6 +449,7 @@ function GridLayoutTypeControl( { layout, onChange } ) { return ( <ToggleGroupControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Grid item position' ) } value={ gridPlacement } diff --git a/packages/block-library/src/comments-pagination/comments-pagination-arrow-controls.js b/packages/block-library/src/comments-pagination/comments-pagination-arrow-controls.js index ac3c17a2c4e721..c3a2d1dae648a5 100644 --- a/packages/block-library/src/comments-pagination/comments-pagination-arrow-controls.js +++ b/packages/block-library/src/comments-pagination/comments-pagination-arrow-controls.js @@ -10,6 +10,7 @@ import { export function CommentsPaginationArrowControls( { value, onChange } ) { return ( <ToggleGroupControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Arrow' ) } value={ value } diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js index 829c6395e047ef..12b052d28fc72e 100644 --- a/packages/block-library/src/navigation/edit/index.js +++ b/packages/block-library/src/navigation/edit/index.js @@ -626,10 +626,11 @@ function Navigation( { </div> </> ) } - <h3>{ __( 'Overlay Menu' ) }</h3> <ToggleGroupControl + __next40pxDefaultSize __nextHasNoMarginBottom - label={ __( 'Configure overlay menu' ) } + label={ __( 'Overlay Menu' ) } + aria-label={ __( 'Configure overlay menu' ) } value={ overlayMenu } help={ __( 'Collapses the navigation options in a menu icon opening an overlay.' @@ -638,7 +639,6 @@ function Navigation( { setAttributes( { overlayMenu: value } ) } isBlock - hideLabelFromVision > <ToggleGroupControlOption value="never" diff --git a/packages/block-library/src/navigation/edit/overlay-menu-preview.js b/packages/block-library/src/navigation/edit/overlay-menu-preview.js index 8ea07351821c89..cdd4d6e3263c98 100644 --- a/packages/block-library/src/navigation/edit/overlay-menu-preview.js +++ b/packages/block-library/src/navigation/edit/overlay-menu-preview.js @@ -27,7 +27,9 @@ export default function OverlayMenuPreview( { setAttributes, hasIcon, icon } ) { /> <ToggleGroupControl + __next40pxDefaultSize __nextHasNoMarginBottom + className="wp-block-navigation__overlay-menu-icon-toggle-group" label={ __( 'Icon' ) } value={ icon } onChange={ ( value ) => setAttributes( { icon: value } ) } diff --git a/packages/block-library/src/navigation/editor.scss b/packages/block-library/src/navigation/editor.scss index b279dc08cfe6e7..24480bb1592516 100644 --- a/packages/block-library/src/navigation/editor.scss +++ b/packages/block-library/src/navigation/editor.scss @@ -628,3 +628,8 @@ body.editor-styles-wrapper .wp-block-navigation__responsive-container.is-menu-op .wp-block-navigation__menu-inspector-controls__empty-message { margin-left: 24px; } + +.wp-block-navigation__overlay-menu-icon-toggle-group { + // Counteract the margin added by the block inspector. + margin-bottom: $grid-unit-20; +} diff --git a/packages/block-library/src/post-featured-image/dimension-controls.js b/packages/block-library/src/post-featured-image/dimension-controls.js index c8e8c0005cfef5..4d272d3d8bb415 100644 --- a/packages/block-library/src/post-featured-image/dimension-controls.js +++ b/packages/block-library/src/post-featured-image/dimension-controls.js @@ -203,6 +203,7 @@ const DimensionControls = ( { panelId={ clientId } > <ToggleGroupControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ scaleLabel } value={ scale } diff --git a/packages/block-library/src/post-navigation-link/edit.js b/packages/block-library/src/post-navigation-link/edit.js index b181e677acae98..a3a3bf19749774 100644 --- a/packages/block-library/src/post-navigation-link/edit.js +++ b/packages/block-library/src/post-navigation-link/edit.js @@ -120,6 +120,7 @@ export default function PostNavigationLinkEdit( { /> ) } <ToggleGroupControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Arrow' ) } value={ arrow } diff --git a/packages/block-library/src/query-pagination/query-pagination-arrow-controls.js b/packages/block-library/src/query-pagination/query-pagination-arrow-controls.js index d5b3353a7187e7..0f2e9c1788bf7b 100644 --- a/packages/block-library/src/query-pagination/query-pagination-arrow-controls.js +++ b/packages/block-library/src/query-pagination/query-pagination-arrow-controls.js @@ -10,6 +10,7 @@ import { export function QueryPaginationArrowControls( { value, onChange } ) { return ( <ToggleGroupControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Arrow' ) } value={ value } From f4fe8d74d28ed2c0a7429963333d325073be5e27 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Thu, 15 Aug 2024 14:01:48 +0200 Subject: [PATCH 0408/1908] Fix: Changing sorting direction on patterns does nothing. (#64508) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../src/components/dataviews-view-config/index.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index 0aae714c5ce27a..69b4cba7763262 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -140,7 +140,7 @@ function SortFieldControl() { } function SortDirectionControl() { - const { view, onChangeView } = useContext( DataViewsContext ); + const { view, fields, onChangeView } = useContext( DataViewsContext ); return ( <ToggleGroupControl className="dataviews-view-config__sort-direction" @@ -149,17 +149,19 @@ function SortDirectionControl() { isBlock label={ __( 'Order' ) } value={ view.sort?.direction || 'desc' } - disabled={ ! view?.sort?.field } onChange={ ( newDirection ) => { - if ( ! view?.sort?.field ) { - return; - } if ( newDirection === 'asc' || newDirection === 'desc' ) { onChangeView( { ...view, sort: { direction: newDirection, - field: view.sort.field, + field: + view.sort?.field || + // If there is no field assigned as the sorting field assign the first sortable field. + fields.find( + ( field ) => field.enableSorting !== false + )?.id || + '', }, } ); return; From cb224d4a5a73ebe3d616d54d72a1590dbbdfc09f Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 15 Aug 2024 21:43:35 +0900 Subject: [PATCH 0409/1908] Quote Block: Add align support (#64188) * Quote Block: Add align support * Inherit alignment when transforming from pullquote block * Inherit alignment when transforming to pullquote block * Try to fix mobile unit test * Try to fix mobile unit test * Try to fix mobile unit test Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: geriux <geriux@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- packages/block-library/src/quote/block.json | 1 + .../src/quote/test/transforms.native.js | 2 +- packages/block-library/src/quote/transforms.js | 13 +++++++++++-- .../src/mobile/utils/alignments.native.js | 1 + 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 5beb712c80a113..b9cae44550181c 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -783,7 +783,7 @@ Give quoted text visual emphasis. "In quoting others, we cite ourselves." — Ju - **Name:** core/quote - **Category:** text -- **Supports:** anchor, background (backgroundImage, backgroundSize), color (background, gradients, heading, link, text), dimensions (minHeight), interactivity (clientNavigation), layout (~~allowEditing~~), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~ +- **Supports:** align (full, left, right, wide), anchor, background (backgroundImage, backgroundSize), color (background, gradients, heading, link, text), dimensions (minHeight), interactivity (clientNavigation), layout (~~allowEditing~~), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~ - **Attributes:** citation, textAlign, value ## Read More diff --git a/packages/block-library/src/quote/block.json b/packages/block-library/src/quote/block.json index c695c938923ae7..0f9ec97422f64b 100644 --- a/packages/block-library/src/quote/block.json +++ b/packages/block-library/src/quote/block.json @@ -28,6 +28,7 @@ }, "supports": { "anchor": true, + "align": [ "left", "right", "wide", "full" ], "html": false, "background": { "backgroundImage": true, diff --git a/packages/block-library/src/quote/test/transforms.native.js b/packages/block-library/src/quote/test/transforms.native.js index 25030e0a018d41..3d2bc8ae609182 100644 --- a/packages/block-library/src/quote/test/transforms.native.js +++ b/packages/block-library/src/quote/test/transforms.native.js @@ -14,7 +14,7 @@ import { const block = 'Quote'; const initialHtml = ` -<!-- wp:quote {"align":"left","className":"is-style-large"} --> +<!-- wp:quote {"textAlign":"left","className":"is-style-large"} --> <blockquote class="wp-block-quote has-text-align-left is-style-large"><!-- wp:paragraph --> <p>"This will make running your own blog a viable alternative again."</p> <!-- /wp:paragraph --><cite>— <a href="https://twitter.com/azumbrunnen_/status/1019347243084800005">Adrian Zumbrunnen</a></cite></blockquote> diff --git a/packages/block-library/src/quote/transforms.js b/packages/block-library/src/quote/transforms.js index f9b3970433fad6..c960759691bf16 100644 --- a/packages/block-library/src/quote/transforms.js +++ b/packages/block-library/src/quote/transforms.js @@ -9,10 +9,18 @@ const transforms = { { type: 'block', blocks: [ 'core/pullquote' ], - transform: ( { value, citation, anchor, fontSize, style } ) => { + transform: ( { + value, + align, + citation, + anchor, + fontSize, + style, + } ) => { return createBlock( 'core/quote', { + align, citation, anchor, fontSize, @@ -95,7 +103,7 @@ const transforms = { ); }, transform: ( - { citation, anchor, fontSize, style }, + { align, citation, anchor, fontSize, style }, innerBlocks ) => { const value = innerBlocks @@ -103,6 +111,7 @@ const transforms = { .join( '<br>' ); return createBlock( 'core/pullquote', { value, + align, citation, anchor, fontSize, diff --git a/packages/components/src/mobile/utils/alignments.native.js b/packages/components/src/mobile/utils/alignments.native.js index bc42385988a5d1..f1f737d7ed367a 100644 --- a/packages/components/src/mobile/utils/alignments.native.js +++ b/packages/components/src/mobile/utils/alignments.native.js @@ -13,6 +13,7 @@ export const WIDE_ALIGNMENTS = { 'core/image', 'core/separator', 'core/media-text', + 'core/quote', 'core/pullquote', ], }; From d530eca033c91cacbd047eda685c45af787913b4 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Thu, 15 Aug 2024 16:11:22 +0200 Subject: [PATCH 0410/1908] Update: Move item size control to the new view config UI. (#64380) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../dataviews-view-config/index.tsx | 40 +++++++-- .../src/components/dataviews/index.tsx | 10 +-- .../dataviews-layouts/grid/density-picker.tsx | 84 ++++--------------- .../src/dataviews-layouts/grid/style.scss | 4 - 4 files changed, 52 insertions(+), 86 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index 69b4cba7763262..034f618aea00ff 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -30,11 +30,17 @@ import warning from '@wordpress/warning'; /** * Internal dependencies */ -import { SORTING_DIRECTIONS, sortIcons, sortLabels } from '../../constants'; +import { + SORTING_DIRECTIONS, + LAYOUT_GRID, + sortIcons, + sortLabels, +} from '../../constants'; import { VIEW_LAYOUTS, getMandatoryFields } from '../../dataviews-layouts'; import type { SupportedLayouts } from '../../types'; import DataViewsContext from '../dataviews-context'; import { unlock } from '../../lock-unlock'; +import DensityPicker from '../../dataviews-layouts/grid/density-picker'; const { DropdownMenuV2: DropdownMenu, @@ -101,10 +107,6 @@ function ViewTypeMenu( { ); } -interface ViewActionsProps { - defaultLayouts?: SupportedLayouts; -} - function SortFieldControl() { const { view, fields, onChangeView } = useContext( DataViewsContext ); const orderOptions = useMemo( () => { @@ -305,7 +307,14 @@ function SettingsSection( { ); } -function DataviewsViewConfigContent() { +function DataviewsViewConfigContent( { + density, + setDensity, +}: { + density: number; + setDensity: React.Dispatch< React.SetStateAction< number > >; +} ) { + const { view } = useContext( DataViewsContext ); return ( <VStack className="dataviews-view-config" spacing={ 6 }> <SettingsSection title={ __( 'Appearance' ) }> @@ -313,6 +322,12 @@ function DataviewsViewConfigContent() { <SortFieldControl /> <SortDirectionControl /> </HStack> + { view.type === LAYOUT_GRID && ( + <DensityPicker + density={ density } + setDensity={ setDensity } + /> + ) } <ItemsPerPageControl /> </SettingsSection> <SettingsSection title={ __( 'Properties' ) }> @@ -323,8 +338,14 @@ function DataviewsViewConfigContent() { } function _DataViewsViewConfig( { + density, + setDensity, defaultLayouts = { list: {}, grid: {}, table: {} }, -}: ViewActionsProps ) { +}: { + density: number; + setDensity: React.Dispatch< React.SetStateAction< number > >; + defaultLayouts?: SupportedLayouts; +} ) { const [ isShowingViewPopover, setIsShowingViewPopover ] = useState< boolean >( false ); @@ -346,7 +367,10 @@ function _DataViewsViewConfig( { } } focusOnMount > - <DataviewsViewConfigContent /> + <DataviewsViewConfigContent + density={ density } + setDensity={ setDensity } + /> </Popover> ) } </div> diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index 337912b04e59c5..81f901f0859bbc 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -27,8 +27,6 @@ import DataViewsViewConfig from '../dataviews-view-config'; import { normalizeFields } from '../../normalize-fields'; import type { Action, Field, View, SupportedLayouts } from '../../types'; import type { SelectionOrUpdater } from '../../private-types'; -import DensityPicker from '../../dataviews-layouts/grid/density-picker'; -import { LAYOUT_GRID } from '../../constants'; type ItemWithId = { id: string }; @@ -133,12 +131,6 @@ export default function DataViews< Item >( { isShowingFilter={ isShowingFilter } /> </HStack> - { view.type === LAYOUT_GRID && ( - <DensityPicker - density={ density } - setDensity={ setDensity } - /> - ) } <DataViewsBulkActions /> <HStack spacing={ 1 } @@ -147,6 +139,8 @@ export default function DataViews< Item >( { > <DataViewsViewConfig defaultLayouts={ defaultLayouts } + density={ density } + setDensity={ setDensity } /> { header } </HStack> diff --git a/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx b/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx index 364d764e343470..8f0782878af224 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx @@ -1,10 +1,9 @@ /** * WordPress dependencies */ -import { RangeControl, Button } from '@wordpress/components'; +import { RangeControl } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useViewportMatch } from '@wordpress/compose'; -import { plus, reset } from '@wordpress/icons'; import { useEffect } from '@wordpress/element'; const viewportBreaks = { @@ -40,21 +39,6 @@ function useViewPortBreakpoint() { return null; } -// Value is number from 0 to 100 representing how big an item is in the grid -// 100 being the biggest and 0 being the smallest. -// The size is relative to the viewport size, if one a given viewport the -// number of allowed items in a grid is 3 to 6 a 0 ( the smallest ) will mean that the grid will -// have 6 items in a row, a 100 ( the biggest ) will mean that the grid will have 3 items in a row. -// A value of 75 will mean that the grid will have 4 items in a row. -function getRangeValue( - density: number, - breakValues: { min: number; max: number; default: number } -) { - const inverseDensity = breakValues.max - density; - const max = breakValues.max - breakValues.min; - return Math.round( ( inverseDensity * 100 ) / max ); -} - export default function DensityPicker( { density, setDensity, @@ -78,59 +62,27 @@ export default function DensityPicker( { return _density; } ); }, [ setDensity, viewport ] ); + const breakValues = viewportBreaks[ viewport || 'mobile' ]; + const densityToUse = density || breakValues.default; + if ( ! viewport ) { return null; } - const breakValues = viewportBreaks[ viewport ]; - const densityToUse = density || breakValues.default; - const rangeValue = getRangeValue( densityToUse, breakValues ); - const step = 100 / ( breakValues.max - breakValues.min + 1 ); return ( - <> - <Button - size="compact" - icon={ reset } - disabled={ rangeValue <= 0 } - accessibleWhenDisabled - label={ __( 'Decrease size' ) } - onClick={ () => { - setDensity( densityToUse + 1 ); - } } - /> - <RangeControl - __nextHasNoMarginBottom - showTooltip={ false } - className="dataviews-density-picker__range-control" - label={ __( 'Item size' ) } - hideLabelFromVision - value={ rangeValue } - min={ 0 } - max={ 100 } - withInputField={ false } - onChange={ ( value = 0 ) => { - const inverseValue = 100 - value; - setDensity( - Math.round( - ( inverseValue * - ( breakValues.max - breakValues.min ) ) / - 100 + - breakValues.min - ) - ); - } } - step={ step } - /> - <Button - size="compact" - icon={ plus } - disabled={ rangeValue >= 100 } - accessibleWhenDisabled - label={ __( 'Increase size' ) } - onClick={ () => { - setDensity( densityToUse - 1 ); - } } - /> - </> + <RangeControl + __nextHasNoMarginBottom + __next40pxDefaultSize + showTooltip={ false } + label={ __( 'Preview size' ) } + value={ breakValues.max + breakValues.min - densityToUse } + min={ breakValues.min } + max={ breakValues.max } + withInputField={ false } + onChange={ ( value = 0 ) => { + setDensity( breakValues.max + breakValues.min - value ); + } } + step={ 1 } + /> ); } diff --git a/packages/dataviews/src/dataviews-layouts/grid/style.scss b/packages/dataviews/src/dataviews-layouts/grid/style.scss index 8f71953e155981..d154d2b614def5 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/style.scss +++ b/packages/dataviews/src/dataviews-layouts/grid/style.scss @@ -146,10 +146,6 @@ } } -.dataviews-density-picker__range-control { - width: 200px; -} - .dataviews-view-grid__field-value:empty, .dataviews-view-grid__field:empty { display: none; From 8bee004d9014604d4b9ea6a2cc20634e507ccb14 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 15 Aug 2024 19:18:56 +0400 Subject: [PATCH 0411/1908] Fix flaky block template registration e2e test (#64541) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- test/e2e/specs/site-editor/template-registration.spec.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/e2e/specs/site-editor/template-registration.spec.js b/test/e2e/specs/site-editor/template-registration.spec.js index 132e3a8c49a902..3927623b2824dc 100644 --- a/test/e2e/specs/site-editor/template-registration.spec.js +++ b/test/e2e/specs/site-editor/template-registration.spec.js @@ -243,8 +243,13 @@ test.describe( 'Block template registration', () => { test( 'WP default templates can be overridden by plugins', async ( { page, + requestUtils, } ) => { - await page.goto( '?page_id=2' ); + const { id } = await requestUtils.createPage( { + title: 'Plugin override page', + status: 'publish', + } ); + await page.goto( `?page_id=${ id }` ); await expect( page.getByText( 'This is a plugin-registered page template.' ) ).toBeVisible(); From 8bcd5f01e9921f9a57b51e16ca46b04a83e5f0ab Mon Sep 17 00:00:00 2001 From: Amit Raj <77401999+amitraj2203@users.noreply.github.com> Date: Thu, 15 Aug 2024 20:53:21 +0530 Subject: [PATCH 0412/1908] ToolsPanel: Sets column-gap to 16px for grid (#64497) * feat: sets column-gap to 16px for ToolsPanel grid * Updates changelog Co-authored-by: amitraj2203 <amitraj2203@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 2 +- packages/components/src/tools-panel/styles.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index e758e457bdd03e..eb207643cdfcb2 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -28,7 +28,7 @@ - `FocalPointPicker`: Default to new 40px size ([#64456](https://github.com/WordPress/gutenberg/pull/64456)). - `DropdownMenuV2`: adopt elevation scale ([#64432](https://github.com/WordPress/gutenberg/pull/64432)). - `Popover`: allow `style` prop usage ([#64489](https://github.com/WordPress/gutenberg/pull/64489)). - +- `ToolsPanel`: sets column-gap to 16px for ToolsPanel grid ([#64497](https://github.com/WordPress/gutenberg/pull/64497)). ### Bug Fixes diff --git a/packages/components/src/tools-panel/styles.ts b/packages/components/src/tools-panel/styles.ts index 1da1003c0462e3..11536e98a128a9 100644 --- a/packages/components/src/tools-panel/styles.ts +++ b/packages/components/src/tools-panel/styles.ts @@ -21,7 +21,7 @@ const toolsPanelGrid = { grid-template-columns: ${ `repeat( ${ columns }, minmax(0, 1fr) )` }; `, spacing: css` - column-gap: ${ space( 2 ) }; + column-gap: ${ space( 4 ) }; row-gap: ${ space( 4 ) }; `, item: { From 294b888b6f7ab2b9cfa6c40f5664586265fea689 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Thu, 15 Aug 2024 17:40:59 +0200 Subject: [PATCH 0413/1908] DataViews: Update: Sort descending button may be wrongly pressed. (#64547) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> --- .../src/components/dataviews-view-config/index.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index 034f618aea00ff..e396b1c68203cc 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -143,6 +143,10 @@ function SortFieldControl() { function SortDirectionControl() { const { view, fields, onChangeView } = useContext( DataViewsContext ); + let value = view.sort?.direction; + if ( ! value && view.sort?.field ) { + value = 'desc'; + } return ( <ToggleGroupControl className="dataviews-view-config__sort-direction" @@ -150,7 +154,7 @@ function SortDirectionControl() { __next40pxDefaultSize isBlock label={ __( 'Order' ) } - value={ view.sort?.direction || 'desc' } + value={ value } onChange={ ( newDirection ) => { if ( newDirection === 'asc' || newDirection === 'desc' ) { onChangeView( { From 9fc46bee0184658a093664b1e514b487fdd78bed Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 15 Aug 2024 19:55:07 +0400 Subject: [PATCH 0414/1908] Improve Image block e2e tests (#64537) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- test/e2e/specs/editor/blocks/image.spec.js | 56 +++++++++++++++++----- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/test/e2e/specs/editor/blocks/image.spec.js b/test/e2e/specs/editor/blocks/image.spec.js index c4c725e083625e..43527b48fbf707 100644 --- a/test/e2e/specs/editor/blocks/image.spec.js +++ b/test/e2e/specs/editor/blocks/image.spec.js @@ -708,13 +708,14 @@ test.describe( 'Image', () => { await editor.clickBlockToolbarButton( 'Upload to Media Library' ); - const imageBlock = editor.canvas.locator( - 'role=document[name="Block: Image"i]' + await expect( + editor.canvas + .locator( 'role=document[name="Block: Image"i]' ) + .locator( 'img[src^="http"]' ) + ).toHaveAttribute( + 'src', + expect.stringMatching( /\/wp-content\/uploads\// ) ); - const image = imageBlock.locator( 'img[src^="http"]' ); - const src = await image.getAttribute( 'src' ); - - expect( src ).toMatch( /\/wp-content\/uploads\// ); } ); test( 'should upload through prepublish panel', async ( { @@ -736,14 +737,45 @@ test.describe( 'Image', () => { .click(); await expect( page.locator( '.components-spinner' ) ).toHaveCount( 0 ); - - const imageBlock = editor.canvas.locator( - 'role=document[name="Block: Image"i]' + await expect( + editor.canvas + .locator( 'role=document[name="Block: Image"i]' ) + .locator( 'img[src^="http"]' ) + ).toHaveAttribute( + 'src', + expect.stringMatching( /\/wp-content\/uploads\// ) ); - const image = imageBlock.locator( 'img[src^="http"]' ); - const src = await image.getAttribute( 'src' ); + } ); - expect( src ).toMatch( /\/wp-content\/uploads\// ); + test( 'uploads data url through blobs from raw handling', async ( { + editor, + page, + pageUtils, + } ) => { + const blobUrl = await page.evaluate( async () => { + const canvas = document.createElement( 'canvas' ); + canvas.width = 20; + canvas.height = 20; + + const ctx = canvas.getContext( '2d' ); + ctx.fillStyle = 'red'; + ctx.fillRect( 0, 0, 20, 20 ); + + return canvas.toDataURL( 'image/png' ); + } ); + + pageUtils.setClipboardData( { html: `<img src="${ blobUrl }">` } ); + + await pageUtils.pressKeys( 'primary+v' ); + + await expect( + editor.canvas + .locator( 'role=document[name="Block: Image"i]' ) + .locator( 'img[src^="http"]' ) + ).toHaveAttribute( + 'src', + expect.stringMatching( /\/wp-content\/uploads\// ) + ); } ); test( 'should have keyboard navigable link UI popover', async ( { From 8559790a6d4bd3192773368a281d7320c3de24b1 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Fri, 16 Aug 2024 00:58:09 +0900 Subject: [PATCH 0415/1908] SelectControl: Add lint rule for 40px size prop usage (#64486) * SelectControl: Add lint rule for 40px size prop usage * Add lint rule * Fix in Author block * Fix in File block * Fix in Audio block * Fix in Archives block * Fix formatting Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .eslintrc.js | 16 +++++++++------- .../src/components/font-family/README.md | 13 +++++++++++-- .../src/components/font-family/index.js | 3 +++ .../responsive-block-control/test/index.js | 1 + packages/block-library/src/archives/edit.js | 1 + packages/block-library/src/audio/edit.js | 7 ++++--- packages/block-library/src/file/inspector.js | 1 + packages/block-library/src/form/edit.js | 2 ++ packages/block-library/src/post-author/edit.js | 2 ++ .../post-featured-image/dimension-controls.js | 4 ++++ .../src/template-part/edit/advanced-controls.js | 2 ++ .../block-library/src/video/tracks-editor.js | 2 ++ .../legacy-widget/edit/widget-type-selector.js | 2 ++ 13 files changed, 44 insertions(+), 12 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 94b443853e0a81..2cdbb5c056cb14 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -324,13 +324,15 @@ module.exports = { ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', } ) ), // Temporary rules until all existing components have the `__next40pxDefaultSize` prop. - ...[ 'TextControl' ].map( ( componentName ) => ( { - // Not strict. Allows pre-existing __next40pxDefaultSize={ false } usage until they are all manually updated. - selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"])):not(:has(JSXAttribute[name.name="size"]))`, - message: - componentName + - ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', - } ) ), + ...[ 'SelectControl', 'TextControl' ].map( + ( componentName ) => ( { + // Not strict. Allows pre-existing __next40pxDefaultSize={ false } usage until they are all manually updated. + selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"])):not(:has(JSXAttribute[name.name="size"]))`, + message: + componentName + + ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', + } ) + ), ], }, }, diff --git a/packages/block-editor/src/components/font-family/README.md b/packages/block-editor/src/components/font-family/README.md index 6b37459fd127e7..63965f509ba534 100644 --- a/packages/block-editor/src/components/font-family/README.md +++ b/packages/block-editor/src/components/font-family/README.md @@ -71,9 +71,18 @@ The current font family value. The rest of the props are passed down to the underlying `<SelectControl />` instance. +#### `__next40pxDefaultSize` + +- Type: `boolean` +- Required: No +- Default: `false` + +Start opting into the larger default height that will become the default size in a future version. + #### `__nextHasNoMarginBottom` -- **Type:** `boolean` -- **Default:** `false` +- Type: `boolean` +- Required: No +- Default: `false` Start opting into the new margin-free styles that will become the default in a future version. diff --git a/packages/block-editor/src/components/font-family/index.js b/packages/block-editor/src/components/font-family/index.js index 90a0412463b3ef..c87a52b4c676d2 100644 --- a/packages/block-editor/src/components/font-family/index.js +++ b/packages/block-editor/src/components/font-family/index.js @@ -11,6 +11,8 @@ import { __ } from '@wordpress/i18n'; import { useSettings } from '../use-settings'; export default function FontFamilyControl( { + /** Start opting into the larger default height that will become the default size in a future version. */ + __next40pxDefaultSize = false, /** Start opting into the new margin-free styles that will become the default in a future version. */ __nextHasNoMarginBottom = false, value = '', @@ -50,6 +52,7 @@ export default function FontFamilyControl( { return ( <SelectControl + __next40pxDefaultSize={ __next40pxDefaultSize } __nextHasNoMarginBottom={ __nextHasNoMarginBottom } label={ __( 'Font' ) } options={ options } diff --git a/packages/block-editor/src/components/responsive-block-control/test/index.js b/packages/block-editor/src/components/responsive-block-control/test/index.js index 57944b591108d7..ef32c60722f541 100644 --- a/packages/block-editor/src/components/responsive-block-control/test/index.js +++ b/packages/block-editor/src/components/responsive-block-control/test/index.js @@ -40,6 +40,7 @@ const renderTestDefaultControlComponent = ( labelComponent, device ) => { return ( <> <SelectControl + __next40pxDefaultSize label={ labelComponent } options={ sizeOptions } __nextHasNoMarginBottom diff --git a/packages/block-library/src/archives/edit.js b/packages/block-library/src/archives/edit.js index 4eed206314e427..ee9bf60fb77ec0 100644 --- a/packages/block-library/src/archives/edit.js +++ b/packages/block-library/src/archives/edit.js @@ -51,6 +51,7 @@ export default function ArchivesEdit( { attributes, setAttributes } ) { } /> <SelectControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Group by:' ) } options={ [ diff --git a/packages/block-library/src/audio/edit.js b/packages/block-library/src/audio/edit.js index 97d3c9c5a1ae3f..3c9f9e11c3b24b 100644 --- a/packages/block-library/src/audio/edit.js +++ b/packages/block-library/src/audio/edit.js @@ -174,6 +174,7 @@ function AudioEdit( { checked={ loop } /> <SelectControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ _x( 'Preload', 'noun; Audio block parameter' ) } value={ preload || '' } @@ -197,9 +198,9 @@ function AudioEdit( { </InspectorControls> <figure { ...blockProps }> { /* - Disable the audio tag if the block is not selected - so the user clicking on it won't play the - file or change the position slider when the controls are enabled. + Disable the audio tag if the block is not selected + so the user clicking on it won't play the + file or change the position slider when the controls are enabled. */ } <Disabled isDisabled={ ! isSingleSelected }> <audio controls="controls" src={ src ?? temporaryURL } /> diff --git a/packages/block-library/src/file/inspector.js b/packages/block-library/src/file/inspector.js index 76ed28d124600e..c29f84f60ebace 100644 --- a/packages/block-library/src/file/inspector.js +++ b/packages/block-library/src/file/inspector.js @@ -73,6 +73,7 @@ export default function FileBlockInspector( { ) } <PanelBody title={ __( 'Settings' ) }> <SelectControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Link to' ) } value={ textLinkHref } diff --git a/packages/block-library/src/form/edit.js b/packages/block-library/src/form/edit.js index d6f9d80f155c38..6a30dd0b61bf9d 100644 --- a/packages/block-library/src/form/edit.js +++ b/packages/block-library/src/form/edit.js @@ -130,6 +130,8 @@ const Edit = ( { attributes, setAttributes, clientId } ) => { { submissionMethod !== 'email' && ( <InspectorControls group="advanced"> <SelectControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Method' ) } options={ [ diff --git a/packages/block-library/src/post-author/edit.js b/packages/block-library/src/post-author/edit.js index dfe0a001d2ee59..1bc1ef4ffcd8a3 100644 --- a/packages/block-library/src/post-author/edit.js +++ b/packages/block-library/src/post-author/edit.js @@ -112,6 +112,7 @@ function PostAuthorEdit( { /> ) ) || ( <SelectControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Author' ) } value={ authorId } @@ -129,6 +130,7 @@ function PostAuthorEdit( { /> { showAvatar && ( <SelectControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Avatar size' ) } value={ attributes.avatarSize } diff --git a/packages/block-library/src/post-featured-image/dimension-controls.js b/packages/block-library/src/post-featured-image/dimension-controls.js index 4d272d3d8bb415..fa0f022332b0cb 100644 --- a/packages/block-library/src/post-featured-image/dimension-controls.js +++ b/packages/block-library/src/post-featured-image/dimension-controls.js @@ -134,6 +134,8 @@ const DimensionControls = ( { panelId={ clientId } > <SelectControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Aspect ratio' ) } value={ aspectRatio } @@ -233,6 +235,8 @@ const DimensionControls = ( { panelId={ clientId } > <SelectControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Resolution' ) } value={ sizeSlug || DEFAULT_SIZE } diff --git a/packages/block-library/src/template-part/edit/advanced-controls.js b/packages/block-library/src/template-part/edit/advanced-controls.js index 79a3a158b87ea0..bf834065d1a54b 100644 --- a/packages/block-library/src/template-part/edit/advanced-controls.js +++ b/packages/block-library/src/template-part/edit/advanced-controls.js @@ -85,6 +85,8 @@ export function TemplatePartAdvancedControls( { /> <SelectControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Area' ) } labelPosition="top" diff --git a/packages/block-library/src/video/tracks-editor.js b/packages/block-library/src/video/tracks-editor.js index 3864722c7a7794..521d54e9231d1b 100644 --- a/packages/block-library/src/video/tracks-editor.js +++ b/packages/block-library/src/video/tracks-editor.js @@ -132,6 +132,8 @@ function SingleTrackEditor( { track, onChange, onClose, onRemove } ) { </Grid> <VStack spacing="8"> <SelectControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom className="block-library-video-tracks-editor__single-track-editor-kind-select" options={ KIND_OPTIONS } diff --git a/packages/widgets/src/blocks/legacy-widget/edit/widget-type-selector.js b/packages/widgets/src/blocks/legacy-widget/edit/widget-type-selector.js index 215e2d2447c3c9..cc7c0830a319bf 100644 --- a/packages/widgets/src/blocks/legacy-widget/edit/widget-type-selector.js +++ b/packages/widgets/src/blocks/legacy-widget/edit/widget-type-selector.js @@ -27,6 +27,8 @@ export default function WidgetTypeSelector( { selectedId, onSelect } ) { return ( <SelectControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } __nextHasNoMarginBottom label={ __( 'Select a legacy widget to display:' ) } value={ selectedId ?? '' } From 289589cae37e855481ab29e3cd2c0a8afb08a5c2 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Thu, 15 Aug 2024 18:00:23 +0200 Subject: [PATCH 0416/1908] Update: Add marks to preview size control. (#64546) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../dataviews-layouts/grid/density-picker.tsx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx b/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx index 8f0782878af224..34ddf6c3fe52f3 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx @@ -4,7 +4,7 @@ import { RangeControl } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useViewportMatch } from '@wordpress/compose'; -import { useEffect } from '@wordpress/element'; +import { useEffect, useMemo } from '@wordpress/element'; const viewportBreaks = { xhuge: { min: 3, max: 6, default: 5 }, @@ -65,6 +65,19 @@ export default function DensityPicker( { const breakValues = viewportBreaks[ viewport || 'mobile' ]; const densityToUse = density || breakValues.default; + const marks = useMemo( + () => + Array.from( + { length: breakValues.max - breakValues.min + 1 }, + ( _, i ) => { + return { + value: breakValues.min + i, + }; + } + ), + [ breakValues ] + ); + if ( ! viewport ) { return null; } @@ -76,6 +89,7 @@ export default function DensityPicker( { showTooltip={ false } label={ __( 'Preview size' ) } value={ breakValues.max + breakValues.min - densityToUse } + marks={ marks } min={ breakValues.min } max={ breakValues.max } withInputField={ false } From 38d0500ca8e70622e460ecb62d433b482ef3cb6c Mon Sep 17 00:00:00 2001 From: Rich Tabor <hi@richtabor.com> Date: Thu, 15 Aug 2024 13:52:17 -0400 Subject: [PATCH 0417/1908] Remove inconsistent dark theme focus style on block selection (#64549) * remove $dark-theme-focus * remove is-dark-theme outline color shift on block selection * remove custom dark theme focus for nav link * remove template part dark theme focus Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/base-styles/_colors.scss | 1 - .../src/components/block-list/content.scss | 10 ---------- packages/block-library/src/navigation-link/editor.scss | 3 --- packages/block-library/src/template-part/editor.scss | 5 ----- 4 files changed, 19 deletions(-) diff --git a/packages/base-styles/_colors.scss b/packages/base-styles/_colors.scss index 2ce58b64e43b8c..b296a0f1f03063 100644 --- a/packages/base-styles/_colors.scss +++ b/packages/base-styles/_colors.scss @@ -17,7 +17,6 @@ $gray-100: #f0f0f0; // Used for light gray backgrounds. $white: #fff; // Opacities & additional colors. -$dark-theme-focus: $white; // Focus color when the theme is dark. $dark-gray-placeholder: rgba($gray-900, 0.62); $medium-gray-placeholder: rgba($gray-900, 0.55); $light-gray-placeholder: rgba($white, 0.65); diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index 17ebad06c4d78e..c8f24e7efcbd2f 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -89,11 +89,6 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b &::after { @include selected-block-focus(); z-index: 1; - - // Show a light color for dark themes. - .is-dark-theme & { - outline-color: $dark-theme-focus; - } } } @@ -285,11 +280,6 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b &.block-editor-block-list__block:not([contenteditable]):focus { &::after { outline-color: var(--wp-block-synced-color); - - // Show a light color for dark themes. - .is-dark-theme & { - outline-color: $dark-theme-focus; - } } } } diff --git a/packages/block-library/src/navigation-link/editor.scss b/packages/block-library/src/navigation-link/editor.scss index 6d1dc32e5310b5..84cd6f6d4ee363 100644 --- a/packages/block-library/src/navigation-link/editor.scss +++ b/packages/block-library/src/navigation-link/editor.scss @@ -87,9 +87,6 @@ $stop2: 64%; --wp-underline-color: var(--wp-admin-theme-color); - .is-dark-theme & { - --wp-underline-color: #{ $dark-theme-focus }; - } background-image: linear-gradient(45deg, transparent ($stop1 - $blur), var(--wp-underline-color) $stop1, var(--wp-underline-color) ($stop1 + $width), transparent ($stop1 + $width + $blur)), diff --git a/packages/block-library/src/template-part/editor.scss b/packages/block-library/src/template-part/editor.scss index 71659ce6ba717a..735c9370099d91 100644 --- a/packages/block-library/src/template-part/editor.scss +++ b/packages/block-library/src/template-part/editor.scss @@ -35,11 +35,6 @@ &.block-editor-block-list__block:not([contenteditable]):focus { &::after { outline-color: var(--wp-block-synced-color); - - // Show a light color for dark themes. - .is-dark-theme & { - outline-color: $dark-theme-focus; - } } } } From 8457cb8eff5bcdf37c6f3518aac9fc15f2a61278 Mon Sep 17 00:00:00 2001 From: Jeremy Herve <jeremy@jeremy.hu> Date: Thu, 15 Aug 2024 21:06:50 +0200 Subject: [PATCH 0418/1908] Props Bot: update to correct event type (#64557) When wanting to filter by event type, we must use `types`, and not `type`. Reference: https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#issue_comment Co-authored-by: jeherve <jeherve@git.wordpress.org> Co-authored-by: aaronjorbin <jorbin@git.wordpress.org> --- .github/workflows/props-bot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/props-bot.yml b/.github/workflows/props-bot.yml index 0f21f47ef14f99..b2332aabb816c7 100644 --- a/.github/workflows/props-bot.yml +++ b/.github/workflows/props-bot.yml @@ -18,7 +18,7 @@ on: # You cannot filter this event for PR comments only. # However, the logic below does short-circuit the workflow for issues. issue_comment: - type: + types: - created # This event will run everytime a new PR review is initially submitted. pull_request_review: From 6de3f66b0a0560969d6328864e2125fdf323c6b7 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Fri, 16 Aug 2024 11:57:00 +1000 Subject: [PATCH 0419/1908] Background block supports: remove unused properties in unit tests (#64564) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- phpunit/block-supports/background-test.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/phpunit/block-supports/background-test.php b/phpunit/block-supports/background-test.php index 4c949fa82257d3..c698f9e7c2f1c1 100644 --- a/phpunit/block-supports/background-test.php +++ b/phpunit/block-supports/background-test.php @@ -122,7 +122,7 @@ public function test_background_block_support( $theme_name, $block_name, $backgr */ public function data_background_block_support() { return array( - 'background image style is applied to uploaded images' => array( + 'background image style is applied' => array( 'theme_name' => 'block-theme-child-with-fluid-typography', 'block_name' => 'test/background-rules-are-output', 'background_settings' => array( @@ -131,7 +131,6 @@ public function data_background_block_support() { 'background_style' => array( 'backgroundImage' => array( 'url' => 'https://example.com/image.jpg', - 'id' => 123, ), ), 'expected_wrapper' => '<div class="has-background" style="background-image:url('https://example.com/image.jpg');background-size:cover;">Content</div>', @@ -158,7 +157,6 @@ public function data_background_block_support() { 'background_style' => array( 'backgroundImage' => array( 'url' => 'https://example.com/image.jpg', - 'id' => 123, ), 'backgroundRepeat' => 'no-repeat', 'backgroundSize' => 'contain', @@ -176,7 +174,6 @@ public function data_background_block_support() { 'background_style' => array( 'backgroundImage' => array( 'url' => 'https://example.com/image.jpg', - 'id' => 123, ), ), 'expected_wrapper' => '<div class="wp-block-test has-background" style="color: red;background-image:url('https://example.com/image.jpg');background-size:cover;">Content</div>', @@ -191,7 +188,6 @@ public function data_background_block_support() { 'background_style' => array( 'backgroundImage' => array( 'url' => 'https://example.com/image.jpg', - 'id' => 123, ), ), 'expected_wrapper' => '<div class="wp-block-test has-background" style="color: red;font-size: 15px;background-image:url('https://example.com/image.jpg');background-size:cover;">Content</div>', @@ -206,7 +202,6 @@ public function data_background_block_support() { 'background_style' => array( 'backgroundImage' => array( 'url' => 'https://example.com/image.jpg', - 'id' => 123, ), ), 'expected_wrapper' => '<div>Content</div>', From e26396756d7fbd6c78ab5cacf4049dd8d0e8cb58 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 16 Aug 2024 12:56:48 +0900 Subject: [PATCH 0420/1908] Base Styles: Restore deprecated `$dark-theme-focus` variable (#64563) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/base-styles/_colors.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/base-styles/_colors.scss b/packages/base-styles/_colors.scss index b296a0f1f03063..e65551e48c783c 100644 --- a/packages/base-styles/_colors.scss +++ b/packages/base-styles/_colors.scss @@ -25,3 +25,6 @@ $light-gray-placeholder: rgba($white, 0.65); $alert-yellow: #f0b849; $alert-red: #cc1818; $alert-green: #4ab866; + +// Deprecated, please avoid using these. +$dark-theme-focus: $white; // Focus color when the theme is dark. From 1defa19697561ec203235f2d2beaaf340231d41f Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Fri, 16 Aug 2024 15:36:58 +1000 Subject: [PATCH 0421/1908] Background image: add uploading state and restrict drag to one image. (#64565) Add a loading spinner over the background image control Restrict upload to one image Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- .../global-styles/background-panel.js | 27 ++++++++++++++++--- .../src/components/global-styles/style.scss | 11 ++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index 1373c54764d155..c01db44792989e 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -23,6 +23,8 @@ import { __experimentalHStack as HStack, __experimentalTruncate as Truncate, Dropdown, + Placeholder, + Spinner, __experimentalDropdownContentWrapper as DropdownContentWrapper, } from '@wordpress/components'; import { __, _x, sprintf } from '@wordpress/i18n'; @@ -268,6 +270,14 @@ function BackgroundControlsPanel( { ); } +function LoadingSpinner() { + return ( + <Placeholder className="block-editor-global-styles-background-panel__loading"> + <Spinner /> + </Placeholder> + ); +} + function BackgroundImageControls( { onChange, style, @@ -277,6 +287,7 @@ function BackgroundImageControls( { displayInPanel, defaultValues, } ) { + const [ isUploading, setIsUploading ] = useState( false ); const mediaUpload = useSelect( ( select ) => select( blockEditorStore ).getSettings().mediaUpload, [] @@ -289,6 +300,7 @@ function BackgroundImageControls( { const { createErrorNotice } = useDispatch( noticesStore ); const onUploadError = ( message ) => { createErrorNotice( message, { type: 'snackbar' } ); + setIsUploading( false ); }; const resetBackgroundImage = () => @@ -303,10 +315,12 @@ function BackgroundImageControls( { const onSelectMedia = ( media ) => { if ( ! media || ! media.url ) { resetBackgroundImage(); + setIsUploading( false ); return; } if ( isBlobURL( media.url ) ) { + setIsUploading( true ); return; } @@ -349,16 +363,21 @@ function BackgroundImageControls( { backgroundSize: sizeValue, } ) ); + setIsUploading( false ); }; + // Drag and drop callback, restricting image to one. const onFilesDrop = ( filesList ) => { + if ( filesList?.length > 1 ) { + onUploadError( + __( 'Only one image can be used as a background image.' ) + ); + return; + } mediaUpload( { allowedTypes: [ IMAGE_BACKGROUND_TYPE ], filesList, onFileChange( [ image ] ) { - if ( isBlobURL( image?.url ) ) { - return; - } onSelectMedia( image ); }, onError: onUploadError, @@ -393,6 +412,7 @@ function BackgroundImageControls( { ref={ replaceContainerRef } className="block-editor-global-styles-background-panel__image-tools-panel-item" > + { isUploading && <LoadingSpinner /> } <MediaReplaceFlow mediaId={ id } mediaURL={ url } @@ -414,6 +434,7 @@ function BackgroundImageControls( { /> } variant="secondary" + onError={ onUploadError } > { canRemove && ( <MenuItem diff --git a/packages/block-editor/src/components/global-styles/style.scss b/packages/block-editor/src/components/global-styles/style.scss index b8dd3700a77f88..acd5fd6f41c7bc 100644 --- a/packages/block-editor/src/components/global-styles/style.scss +++ b/packages/block-editor/src/components/global-styles/style.scss @@ -134,6 +134,17 @@ box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); } } + + .block-editor-global-styles-background-panel__loading { + height: 100%; + position: absolute; + z-index: 1; + width: 100%; + padding: 10px 0 0 0; + svg { + margin: 0; + } + } } .block-editor-global-styles-background-panel__image-preview-content, From be6bc93743304a1790fbb76579ff681aced1dce1 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 16 Aug 2024 10:44:49 +0400 Subject: [PATCH 0422/1908] PostFeaturedImage: Disable the media modal while uploading an image (#64566) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/editor/src/components/post-featured-image/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/editor/src/components/post-featured-image/index.js b/packages/editor/src/components/post-featured-image/index.js index 5e1874e9b84026..febf56a46778fc 100644 --- a/packages/editor/src/components/post-featured-image/index.js +++ b/packages/editor/src/components/post-featured-image/index.js @@ -180,6 +180,8 @@ function PostFeaturedImage( { : `editor-post-featured-image-${ featuredImageId }-describedby` } aria-haspopup="dialog" + disabled={ isLoading } + accessibleWhenDisabled > { !! featuredImageId && media && ( <img From 81ce216685e285348fcfda5fd5c64d1229ffa6f2 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Fri, 16 Aug 2024 13:13:02 +0530 Subject: [PATCH 0423/1908] Comment Author Name: Add Border Support (#64550) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- .../src/comment-author-name/block.json | 15 ++++++++++++++- .../src/comment-author-name/style.scss | 4 ++++ packages/block-library/src/style.scss | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 packages/block-library/src/comment-author-name/style.scss diff --git a/packages/block-library/src/comment-author-name/block.json b/packages/block-library/src/comment-author-name/block.json index f3422faf0264df..1889d054c940e7 100644 --- a/packages/block-library/src/comment-author-name/block.json +++ b/packages/block-library/src/comment-author-name/block.json @@ -51,6 +51,19 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } - } + }, + "style": "wp-block-comment-author-name" } diff --git a/packages/block-library/src/comment-author-name/style.scss b/packages/block-library/src/comment-author-name/style.scss new file mode 100644 index 00000000000000..1e8c5eeb154b05 --- /dev/null +++ b/packages/block-library/src/comment-author-name/style.scss @@ -0,0 +1,4 @@ +.wp-block-comment-author-name { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; +} diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index 338753ae53fcbf..1070bedc8c3dbc 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -12,6 +12,7 @@ @import "./comment-template/style.scss"; @import "./comment-date/style.scss"; @import "./comment-content/style.scss"; +@import "./comment-author-name/style.scss"; @import "./cover/style.scss"; @import "./details/style.scss"; @import "./embed/style.scss"; From 0da4ce0b0343b2ec61d2718c20a9b2dc4de51fb3 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 16 Aug 2024 12:34:02 +0400 Subject: [PATCH 0424/1908] Background Image: Remove unnecessary 'block-editor' store subscription (#64568) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/components/global-styles/background-panel.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index c01db44792989e..6391f72a084875 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -288,10 +288,7 @@ function BackgroundImageControls( { defaultValues, } ) { const [ isUploading, setIsUploading ] = useState( false ); - const mediaUpload = useSelect( - ( select ) => select( blockEditorStore ).getSettings().mediaUpload, - [] - ); + const { getSettings } = useSelect( blockEditorStore ); const { id, title, url } = style?.background?.backgroundImage || { ...inheritedValue?.background?.backgroundImage, @@ -374,7 +371,7 @@ function BackgroundImageControls( { ); return; } - mediaUpload( { + getSettings().mediaUpload( { allowedTypes: [ IMAGE_BACKGROUND_TYPE ], filesList, onFileChange( [ image ] ) { From 70d2020250ab71675ef5ce6330ca43e96200442c Mon Sep 17 00:00:00 2001 From: Jan Pfeil <jan.pfeil@rypox.net> Date: Fri, 16 Aug 2024 11:21:36 +0200 Subject: [PATCH 0425/1908] fix typo and link in static-dynamic-rendering.md (#64449) * fix typo and link in static-dynamic-rendering.md * update link to render_callback Unlinked contributors: janpfeil. Co-authored-by: tyxla <tyxla@git.wordpress.org> --- docs/getting-started/fundamentals/static-dynamic-rendering.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/fundamentals/static-dynamic-rendering.md b/docs/getting-started/fundamentals/static-dynamic-rendering.md index 8d199f66cccd2a..dfb6a7123b44b3 100644 --- a/docs/getting-started/fundamentals/static-dynamic-rendering.md +++ b/docs/getting-started/fundamentals/static-dynamic-rendering.md @@ -61,7 +61,7 @@ Dynamic blocks, which we'll explore in the following section, can specify an ini For a practical demonstration of how this works, refer to the [Building your first block](/docs/getting-started/tutorial.md) tutorial. Specifically, the [Adding static rendering](/docs/getting-started/tutorial.md#adding-static-rendering) section illustrates how a block can have both a saved HTML structure and dynamic rendering capabilities. <div class="callout callout-info"> -WordPress provides mechanisms like the <a href="https://developer.wordpress.org/reference/functions/render_block/"><code>render_block</code></a> are the <code>$render_callback</code> function to alter the saved HTML of a block before it appears on the front end. These tools offer developers the capability to customize block output dynamically, catering to complex and interactive user experiences. +WordPress provides mechanisms like the <a href="https://developer.wordpress.org/reference/functions/render_block/"><code>render_block</code></a> and the <a href="https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/creating-dynamic-blocks/"><code>render_callback</code></a> function to alter the saved HTML of a block before it appears on the front end. These tools offer developers the capability to customize block output dynamically, catering to complex and interactive user experiences. </div> Additional examples of WordPress blocks that use static rendering, meaning their output is fixed at the time of saving and doesn't rely on server-side processing, include: From a00448ab9aa12ea99657e909a2a03cb01d041450 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Fri, 16 Aug 2024 14:24:58 +0100 Subject: [PATCH 0426/1908] Update components radius (#64368) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/base-styles/_variables.scss | 2 +- packages/components/CHANGELOG.md | 26 +++++++++++++++++++ .../styles/alignment-matrix-control-styles.ts | 4 +-- .../styles/angle-picker-control-styles.tsx | 4 +-- .../components/src/border-control/styles.ts | 2 +- .../components/src/button-group/style.scss | 4 +-- packages/components/src/button/style.scss | 4 +-- .../src/circular-option-picker/style.scss | 4 +-- .../components/src/color-indicator/style.scss | 2 +- .../components/src/color-palette/style.scss | 4 +-- .../src/custom-gradient-picker/style.scss | 2 +- packages/components/src/drop-zone/style.scss | 2 +- .../components/src/dropdown-menu-v2/styles.ts | 4 +-- .../styles/focal-point-picker-style.ts | 2 +- packages/components/src/guide/style.scss | 1 - packages/components/src/item-group/styles.ts | 2 +- packages/components/src/modal/style.scss | 4 +-- .../components/src/palette-edit/styles.ts | 10 +++---- .../components/src/placeholder/style.scss | 2 +- packages/components/src/popover/style.scss | 2 +- .../components/src/progress-bar/styles.ts | 4 +-- .../components/src/radio-control/style.scss | 2 +- packages/components/src/snackbar/style.scss | 2 +- packages/components/src/tab-panel/style.scss | 2 +- packages/components/src/text/styles.ts | 2 +- .../test/__snapshots__/index.tsx.snap | 16 ++++++------ .../styles.ts | 4 +-- .../toggle-group-control/styles.ts | 2 +- .../components/src/toolbar/toolbar/style.scss | 4 +-- packages/components/src/tooltip/style.scss | 2 +- .../styles/unit-control-styles.ts | 2 +- .../components/src/utils/config-values.js | 2 -- packages/components/src/utils/input/base.js | 2 +- 33 files changed, 78 insertions(+), 55 deletions(-) diff --git a/packages/base-styles/_variables.scss b/packages/base-styles/_variables.scss index 0d3e139a7dd555..0f0c9e6d019ba3 100644 --- a/packages/base-styles/_variables.scss +++ b/packages/base-styles/_variables.scss @@ -47,7 +47,7 @@ $radius-x-small: 1px; // Applied to elements like buttons nested within primit $radius-small: 2px; // Applied to most primitives. $radius-medium: 4px; // Applied to containers with smaller padding. $radius-large: 8px; // Applied to containers with larger padding. -$radius-full: 9999px; // For lozenges. +$radius-full: 9999px; // For pills. $radius-round: 50%; // For circles and ovals. /** diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index eb207643cdfcb2..1e6a96d2618d6f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -27,6 +27,32 @@ - `TimePicker`: add `hideLabelFromVision` prop ([#64267](https://github.com/WordPress/gutenberg/pull/64267)). - `FocalPointPicker`: Default to new 40px size ([#64456](https://github.com/WordPress/gutenberg/pull/64456)). - `DropdownMenuV2`: adopt elevation scale ([#64432](https://github.com/WordPress/gutenberg/pull/64432)). +- `AlignmentMatrixControl`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `AnglePickerControl`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `BorderControl`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `ButtonGroup`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `Button`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `CircularOptionPicker`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `ColorIndicator`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `ColorPalette`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `CustomGradientPicker`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `DropZone`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `DropdownMenuV2`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `FocalPointPicker`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `Guide`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `Modal`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `Placeholder`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `Popover`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `ProgressBar`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `RadioControl`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `Snackbar`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `TabPanel`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `Text`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `ToggleGroupControl`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `ToolbarGroup`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `Toolbar`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `Tooltip`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). +- `UnitControl`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). - `Popover`: allow `style` prop usage ([#64489](https://github.com/WordPress/gutenberg/pull/64489)). - `ToolsPanel`: sets column-gap to 16px for ToolsPanel grid ([#64497](https://github.com/WordPress/gutenberg/pull/64497)). diff --git a/packages/components/src/alignment-matrix-control/styles/alignment-matrix-control-styles.ts b/packages/components/src/alignment-matrix-control/styles/alignment-matrix-control-styles.ts index bdb015ec64c6a7..efbd23ab2be0af 100644 --- a/packages/components/src/alignment-matrix-control/styles/alignment-matrix-control-styles.ts +++ b/packages/components/src/alignment-matrix-control/styles/alignment-matrix-control-styles.ts @@ -7,7 +7,7 @@ import { css } from '@emotion/react'; /** * Internal dependencies */ -import { COLORS } from '../../utils'; +import { COLORS, CONFIG } from '../../utils'; import type { AlignmentMatrixControlProps, AlignmentMatrixControlCellProps, @@ -15,7 +15,7 @@ import type { export const rootBase = () => { return css` - border-radius: 2px; + border-radius: ${ CONFIG.radiusMedium }; box-sizing: border-box; direction: ltr; display: grid; diff --git a/packages/components/src/angle-picker-control/styles/angle-picker-control-styles.tsx b/packages/components/src/angle-picker-control/styles/angle-picker-control-styles.tsx index 0141bd860d7df9..f57d60db0744b1 100644 --- a/packages/components/src/angle-picker-control/styles/angle-picker-control-styles.tsx +++ b/packages/components/src/angle-picker-control/styles/angle-picker-control-styles.tsx @@ -15,7 +15,7 @@ const CIRCLE_SIZE = 32; const INNER_CIRCLE_SIZE = 6; export const CircleRoot = styled.div` - border-radius: 50%; + border-radius: ${ CONFIG.radiusRound }; border: ${ CONFIG.borderWidth } solid ${ COLORS.ui.border }; box-sizing: border-box; cursor: grab; @@ -41,7 +41,7 @@ export const CircleIndicatorWrapper = styled.div` export const CircleIndicator = styled.div` background: ${ COLORS.theme.accent }; - border-radius: 50%; + border-radius: ${ CONFIG.radiusRound }; box-sizing: border-box; display: block; left: 50%; diff --git a/packages/components/src/border-control/styles.ts b/packages/components/src/border-control/styles.ts index 28669ebf3ccc78..2c77a2d21465d6 100644 --- a/packages/components/src/border-control/styles.ts +++ b/packages/components/src/border-control/styles.ts @@ -99,7 +99,7 @@ export const colorIndicatorWrapper = ( const { style } = border || {}; return css` - border-radius: 9999px; + border-radius: ${ CONFIG.radiusFull }; border: 2px solid transparent; ${ style ? colorIndicatorBorder( border ) : undefined } width: ${ size === '__unstable-large' ? '24px' : '22px' }; diff --git a/packages/components/src/button-group/style.scss b/packages/components/src/button-group/style.scss index 171722b409f693..96a9e8f458c84c 100644 --- a/packages/components/src/button-group/style.scss +++ b/packages/components/src/button-group/style.scss @@ -12,11 +12,11 @@ } &:first-child { - border-radius: $radius-block-ui 0 0 $radius-block-ui; + border-radius: $radius-small 0 0 $radius-small; } &:last-child { - border-radius: 0 $radius-block-ui $radius-block-ui 0; + border-radius: 0 $radius-small $radius-small 0; } // The focused button should be elevated so the focus ring isn't cropped, diff --git a/packages/components/src/button/style.scss b/packages/components/src/button/style.scss index 7d67dcc0748b85..444e4d397b3ef8 100644 --- a/packages/components/src/button/style.scss +++ b/packages/components/src/button/style.scss @@ -22,7 +22,7 @@ align-items: center; box-sizing: border-box; padding: 6px 12px; - border-radius: $radius-block-ui; + border-radius: $radius-small; color: $components-color-foreground; &.is-next-40px-default-size { @@ -249,7 +249,7 @@ height: auto; &:focus { - border-radius: $radius-block-ui; + border-radius: $radius-small; } &:disabled, diff --git a/packages/components/src/circular-option-picker/style.scss b/packages/components/src/circular-option-picker/style.scss index 33ba6070dde799..74a380e0936be8 100644 --- a/packages/components/src/circular-option-picker/style.scss +++ b/packages/components/src/circular-option-picker/style.scss @@ -70,7 +70,7 @@ $color-palette-circle-spacing: 12px; height: 100%; width: 100%; border: none; - border-radius: 50%; + border-radius: $radius-round; background: transparent; box-shadow: inset 0 0 0 ($color-palette-circle-size * 0.5); transition: 100ms box-shadow ease; @@ -93,7 +93,7 @@ $color-palette-circle-spacing: 12px; position: absolute; left: 2px; top: 2px; - border-radius: 50%; + border-radius: $radius-round; z-index: z-index(".components-circular-option-picker__option.is-pressed + svg"); pointer-events: none; } diff --git a/packages/components/src/color-indicator/style.scss b/packages/components/src/color-indicator/style.scss index e70b8a09ca5bf5..4029b50340e62a 100644 --- a/packages/components/src/color-indicator/style.scss +++ b/packages/components/src/color-indicator/style.scss @@ -2,7 +2,7 @@ width: $grid-unit-50 * 0.5; height: $grid-unit-50 * 0.5; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); - border-radius: 50%; + border-radius: $radius-round; display: inline-block; padding: 0; background: $white linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%); diff --git a/packages/components/src/color-palette/style.scss b/packages/components/src/color-palette/style.scss index 2d6bc4ddc1db3d..9d922a8130692a 100644 --- a/packages/components/src/color-palette/style.scss +++ b/packages/components/src/color-palette/style.scss @@ -14,7 +14,7 @@ $border-as-box-shadow: inset 0 0 0 $border-width rgba(0, 0, 0, 0.2); cursor: pointer; // Show a thin outline in Windows high contrast mode. outline: 1px solid transparent; - border-radius: $radius-block-ui $radius-block-ui 0 0; + border-radius: $radius-medium $radius-medium 0 0; box-shadow: $border-as-box-shadow; &:focus { @@ -46,7 +46,7 @@ $border-as-box-shadow: inset 0 0 0 $border-width rgba(0, 0, 0, 0.2); .components-color-palette__custom-color-text-wrapper { padding: $grid-unit-15 $grid-unit-20; - border-radius: 0 0 $radius-block-ui $radius-block-ui; + border-radius: 0 0 $radius-medium $radius-medium; position: relative; font-size: $default-font-size; diff --git a/packages/components/src/custom-gradient-picker/style.scss b/packages/components/src/custom-gradient-picker/style.scss index e7828127ff8d33..a8c6d6b872caf0 100644 --- a/packages/components/src/custom-gradient-picker/style.scss +++ b/packages/components/src/custom-gradient-picker/style.scss @@ -1,7 +1,7 @@ $components-custom-gradient-picker__padding: $grid-unit-20; // 48px container, 16px handles inside, that leaves 32px padding, half of which is 1å6. .components-custom-gradient-picker__gradient-bar { - border-radius: $radius-block-ui; + border-radius: $radius-small; width: 100%; height: $grid-unit-60; position: relative; diff --git a/packages/components/src/drop-zone/style.scss b/packages/components/src/drop-zone/style.scss index 2793dc708cf03f..d3cd18a75b1f8f 100644 --- a/packages/components/src/drop-zone/style.scss +++ b/packages/components/src/drop-zone/style.scss @@ -7,7 +7,7 @@ z-index: z-index(".components-drop-zone"); visibility: hidden; opacity: 0; - border-radius: $radius-block-ui; + border-radius: $radius-small; &.is-active { opacity: 1; diff --git a/packages/components/src/dropdown-menu-v2/styles.ts b/packages/components/src/dropdown-menu-v2/styles.ts index 950a549f8566a4..3260a83f45f1c1 100644 --- a/packages/components/src/dropdown-menu-v2/styles.ts +++ b/packages/components/src/dropdown-menu-v2/styles.ts @@ -87,7 +87,7 @@ export const DropdownMenu = styled( Ariakit.Menu )< padding: ${ CONTENT_WRAPPER_PADDING }; background-color: ${ COLORS.ui.background }; - border-radius: 4px; + border-radius: ${ CONFIG.radiusMedium }; ${ ( props ) => css` box-shadow: ${ props.variant === 'toolbar' ? TOOLBAR_VARIANT_BOX_SHADOW @@ -150,7 +150,7 @@ const baseItem = css` line-height: 20px; color: ${ COLORS.gray[ 900 ] }; - border-radius: ${ CONFIG.radiusBlockUi }; + border-radius: ${ CONFIG.radiusSmall }; padding-block: ${ ITEM_PADDING_BLOCK }; padding-inline: ${ ITEM_PADDING_INLINE }; diff --git a/packages/components/src/focal-point-picker/styles/focal-point-picker-style.ts b/packages/components/src/focal-point-picker/styles/focal-point-picker-style.ts index 71bf4b651b4ad7..fba3eda2fb0f29 100644 --- a/packages/components/src/focal-point-picker/styles/focal-point-picker-style.ts +++ b/packages/components/src/focal-point-picker/styles/focal-point-picker-style.ts @@ -22,7 +22,7 @@ export const MediaWrapper = styled.div` export const MediaContainer = styled.div` align-items: center; - border-radius: ${ CONFIG.radiusBlockUi }; + border-radius: ${ CONFIG.radiusSmall }; cursor: pointer; display: inline-flex; justify-content: center; diff --git a/packages/components/src/guide/style.scss b/packages/components/src/guide/style.scss index 76f7b03ac4aafc..073bfc06843075 100644 --- a/packages/components/src/guide/style.scss +++ b/packages/components/src/guide/style.scss @@ -9,7 +9,6 @@ .components-modal__content { padding: 0; margin-top: 0; - border-radius: $radius-block-ui; &::before { content: none; diff --git a/packages/components/src/item-group/styles.ts b/packages/components/src/item-group/styles.ts index 166f225790ce27..66c6158f9af1a3 100644 --- a/packages/components/src/item-group/styles.ts +++ b/packages/components/src/item-group/styles.ts @@ -70,7 +70,7 @@ export const separated = css` } `; -const borderRadius = CONFIG.controlBorderRadius; +const borderRadius = CONFIG.radiusSmall; export const spacedAround = css` border-radius: ${ borderRadius }; diff --git a/packages/components/src/modal/style.scss b/packages/components/src/modal/style.scss index e563b29070bef2..c862363a0d3c81 100644 --- a/packages/components/src/modal/style.scss +++ b/packages/components/src/modal/style.scss @@ -21,7 +21,7 @@ width: 100%; background: $white; box-shadow: $shadow-modal; - border-radius: $grid-unit-05 $grid-unit-05 0 0; + border-radius: $radius-large $radius-large 0 0; overflow: hidden; // Have the content element fill the vertical space yet not overflow. display: flex; @@ -32,7 +32,7 @@ // Show a centered modal on bigger screens. @include break-small() { - border-radius: $grid-unit-05; + border-radius: $radius-large; margin: auto; width: auto; min-width: $modal-min-width; diff --git a/packages/components/src/palette-edit/styles.ts b/packages/components/src/palette-edit/styles.ts index aa4ed720b93bfe..ad918d8590cf23 100644 --- a/packages/components/src/palette-edit/styles.ts +++ b/packages/components/src/palette-edit/styles.ts @@ -31,7 +31,7 @@ export const IndicatorStyled = styled( ColorIndicator )` export const NameInputControl = styled( InputControl )` ${ InputControlContainer } { background: ${ COLORS.gray[ 100 ] }; - border-radius: ${ CONFIG.controlBorderRadius }; + border-radius: ${ CONFIG.radiusXSmall }; ${ Input }${ Input }${ Input }${ Input } { height: ${ space( 8 ) }; } @@ -85,8 +85,8 @@ export const PaletteItem = styled( View )` outline-offset: 0; } - border-top-left-radius: ${ CONFIG.controlBorderRadius }; - border-top-right-radius: ${ CONFIG.controlBorderRadius }; + border-top-left-radius: ${ CONFIG.radiusSmall }; + border-top-right-radius: ${ CONFIG.radiusSmall }; & + & { border-top-left-radius: 0; @@ -94,8 +94,8 @@ export const PaletteItem = styled( View )` } &:last-child { - border-bottom-left-radius: ${ CONFIG.controlBorderRadius }; - border-bottom-right-radius: ${ CONFIG.controlBorderRadius }; + border-bottom-left-radius: ${ CONFIG.radiusSmall }; + border-bottom-right-radius: ${ CONFIG.radiusSmall }; border-bottom-color: ${ CONFIG.surfaceBorderColor }; } diff --git a/packages/components/src/placeholder/style.scss b/packages/components/src/placeholder/style.scss index e046ce1e3a427e..61090c81110a5c 100644 --- a/packages/components/src/placeholder/style.scss +++ b/packages/components/src/placeholder/style.scss @@ -19,7 +19,7 @@ // Block UI appearance. - border-radius: $radius-block-ui; + border-radius: $radius-medium; background-color: $white; box-shadow: inset 0 0 0 $border-width $gray-900; outline: 1px solid transparent; // Shown for Windows 10 High Contrast mode. diff --git a/packages/components/src/popover/style.scss b/packages/components/src/popover/style.scss index c7ff0510986bfa..f9f43870a6b927 100644 --- a/packages/components/src/popover/style.scss +++ b/packages/components/src/popover/style.scss @@ -23,7 +23,7 @@ $shadow-popover-border-top-only-alternate: 0 #{-$border-width} 0 $gray-900; .components-popover__content { background: $white; box-shadow: $shadow-popover-border-default, $shadow-popover; - border-radius: $radius-block-ui; + border-radius: $radius-medium; box-sizing: border-box; width: min-content; diff --git a/packages/components/src/progress-bar/styles.ts b/packages/components/src/progress-bar/styles.ts index 79b9103e73a1ed..585b9ab2620753 100644 --- a/packages/components/src/progress-bar/styles.ts +++ b/packages/components/src/progress-bar/styles.ts @@ -40,7 +40,7 @@ export const Track = styled.div` ${ COLORS.theme.foreground }, transparent 90% ); - border-radius: ${ CONFIG.radiusBlockUi }; + border-radius: ${ CONFIG.radiusFull }; // Windows high contrast mode. outline: 2px solid transparent; @@ -58,7 +58,7 @@ export const Indicator = styled.div< { position: absolute; top: 0; height: 100%; - border-radius: ${ CONFIG.radiusBlockUi }; + border-radius: ${ CONFIG.radiusFull }; /* Text color at 90% opacity */ background-color: color-mix( in srgb, diff --git a/packages/components/src/radio-control/style.scss b/packages/components/src/radio-control/style.scss index 7444ea1343b842..e9732558f2901e 100644 --- a/packages/components/src/radio-control/style.scss +++ b/packages/components/src/radio-control/style.scss @@ -32,7 +32,7 @@ &::before { content: ""; - border-radius: 50%; + border-radius: $radius-round; } } } diff --git a/packages/components/src/snackbar/style.scss b/packages/components/src/snackbar/style.scss index 0ba1774d67382f..5bea7076599b56 100644 --- a/packages/components/src/snackbar/style.scss +++ b/packages/components/src/snackbar/style.scss @@ -3,7 +3,7 @@ font-size: $default-font-size; background: rgba($black, 0.85); // Emulates #1e1e1e closely. backdrop-filter: blur($grid-unit-20) saturate(180%); - border-radius: $radius-block-ui; + border-radius: $radius-medium; box-shadow: $shadow-popover; color: $white; padding: $grid-unit-15 ($grid-unit-05 * 5); diff --git a/packages/components/src/tab-panel/style.scss b/packages/components/src/tab-panel/style.scss index 2855f8c2b06a01..ab73a7affaeed4 100644 --- a/packages/components/src/tab-panel/style.scss +++ b/packages/components/src/tab-panel/style.scss @@ -67,7 +67,7 @@ // Draw the indicator. box-shadow: 0 0 0 0 transparent; - border-radius: $radius-block-ui; + border-radius: $radius-small; // Animation transition: all 0.1s linear; diff --git a/packages/components/src/text/styles.ts b/packages/components/src/text/styles.ts index c7d48552795938..e777ed4f0941de 100644 --- a/packages/components/src/text/styles.ts +++ b/packages/components/src/text/styles.ts @@ -35,7 +35,7 @@ export const muted = css` export const highlighterText = css` mark { background: ${ COLORS.alert.yellow }; - border-radius: 2px; + border-radius: ${ CONFIG.radiusSmall }; box-shadow: 0 0 0 1px rgba( 0, 0, 0, 0.05 ) inset, 0 -1px 0 rgba( 0, 0, 0, 0.1 ) inset; diff --git a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap index d055ea5fcc9838..e9b4f4ca22ab85 100644 --- a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap +++ b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap @@ -84,7 +84,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = appearance: none; background: transparent; border: none; - border-radius: 2px; + border-radius: 1px; color: #757575; fill: currentColor; cursor: pointer; @@ -152,7 +152,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = .emotion-15 { background: #1e1e1e; - border-radius: 2px; + border-radius: 1px; position: absolute; inset: 0; z-index: 1; @@ -171,7 +171,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = appearance: none; background: transparent; border: none; - border-radius: 2px; + border-radius: 1px; color: #757575; fill: currentColor; cursor: pointer; @@ -416,7 +416,7 @@ exports[`ToggleGroupControl controlled should render correctly with text options appearance: none; background: transparent; border: none; - border-radius: 2px; + border-radius: 1px; color: #757575; fill: currentColor; cursor: pointer; @@ -636,7 +636,7 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] appearance: none; background: transparent; border: none; - border-radius: 2px; + border-radius: 1px; color: #757575; fill: currentColor; cursor: pointer; @@ -704,7 +704,7 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] .emotion-15 { background: #1e1e1e; - border-radius: 2px; + border-radius: 1px; position: absolute; inset: 0; z-index: 1; @@ -723,7 +723,7 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] appearance: none; background: transparent; border: none; - border-radius: 2px; + border-radius: 1px; color: #757575; fill: currentColor; cursor: pointer; @@ -962,7 +962,7 @@ exports[`ToggleGroupControl uncontrolled should render correctly with text optio appearance: none; background: transparent; border: none; - border-radius: 2px; + border-radius: 1px; color: #757575; fill: currentColor; cursor: pointer; diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts b/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts index 999a25df8bdd40..86efc5224077f4 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts +++ b/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts @@ -37,7 +37,7 @@ export const buttonView = ( { appearance: none; background: transparent; border: none; - border-radius: ${ CONFIG.controlBorderRadius }; + border-radius: ${ CONFIG.radiusXSmall }; color: ${ COLORS.gray[ 700 ] }; fill: currentColor; cursor: pointer; @@ -122,7 +122,7 @@ const isIconStyles = ( { export const backdropView = css` background: ${ COLORS.gray[ 900 ] }; - border-radius: ${ CONFIG.controlBorderRadius }; + border-radius: ${ CONFIG.radiusXSmall }; position: absolute; inset: 0; z-index: 1; diff --git a/packages/components/src/toggle-group-control/toggle-group-control/styles.ts b/packages/components/src/toggle-group-control/toggle-group-control/styles.ts index 7310024706e1de..8d01c150a45eaf 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/styles.ts +++ b/packages/components/src/toggle-group-control/toggle-group-control/styles.ts @@ -19,7 +19,7 @@ export const toggleGroupControl = ( { } ) => css` background: ${ COLORS.ui.background }; border: 1px solid transparent; - border-radius: ${ CONFIG.controlBorderRadius }; + border-radius: ${ CONFIG.radiusSmall }; display: inline-flex; min-width: 0; position: relative; diff --git a/packages/components/src/toolbar/toolbar/style.scss b/packages/components/src/toolbar/toolbar/style.scss index eccfc3bf705cbd..c0cabacb84c77e 100644 --- a/packages/components/src/toolbar/toolbar/style.scss +++ b/packages/components/src/toolbar/toolbar/style.scss @@ -1,7 +1,7 @@ .components-accessible-toolbar { display: inline-flex; border: $border-width solid $gray-900; - border-radius: $radius-block-ui; + border-radius: $radius-small; flex-shrink: 0; & > .components-toolbar-group:last-child { @@ -47,7 +47,7 @@ content: ""; position: absolute; display: block; - border-radius: $radius-block-ui; + border-radius: $radius-small; height: $grid-unit-40; // Position the focus rectangle. diff --git a/packages/components/src/tooltip/style.scss b/packages/components/src/tooltip/style.scss index feda6cfa81c887..eaac8b3ad1c7f6 100644 --- a/packages/components/src/tooltip/style.scss +++ b/packages/components/src/tooltip/style.scss @@ -1,7 +1,7 @@ .components-tooltip { background: $black; font-family: $default-font; - border-radius: $radius-block-ui; + border-radius: $radius-small; color: $gray-100; text-align: center; line-height: 1.4; diff --git a/packages/components/src/unit-control/styles/unit-control-styles.ts b/packages/components/src/unit-control/styles/unit-control-styles.ts index 321bfb8406569d..5f59771bd48a6a 100644 --- a/packages/components/src/unit-control/styles/unit-control-styles.ts +++ b/packages/components/src/unit-control/styles/unit-control-styles.ts @@ -135,7 +135,7 @@ export const UnitSelect = styled.select< SelectProps >` &&& { appearance: none; background: transparent; - border-radius: 2px; + border-radius: ${ CONFIG.radiusXSmall }; border: none; display: block; outline: none; diff --git a/packages/components/src/utils/config-values.js b/packages/components/src/utils/config-values.js index 02c6f69544c2bf..0ad1b3294a926b 100644 --- a/packages/components/src/utils/config-values.js +++ b/packages/components/src/utils/config-values.js @@ -14,7 +14,6 @@ const CONTROL_PROPS = { controlPaddingXLarge: `calc(${ CONTROL_PADDING_X } * 1.3334)`, controlPaddingXSmall: `calc(${ CONTROL_PADDING_X } / 1.3334)`, controlBackgroundColor: COLORS.white, - controlBorderRadius: '2px', controlBoxShadow: 'transparent', controlBoxShadowFocus: `0 0 0 0.5px ${ COLORS.theme.accent }`, controlDestructiveBorderColor: COLORS.alert.red, @@ -48,7 +47,6 @@ export default Object.assign( {}, CONTROL_PROPS, TOGGLE_GROUP_CONTROL_PROPS, { radiusLarge: '8px', radiusFull: '9999px', radiusRound: '50%', - radiusBlockUi: '2px', borderWidth: '1px', borderWidthFocus: '1.5px', borderWidthTab: '4px', diff --git a/packages/components/src/utils/input/base.js b/packages/components/src/utils/input/base.js index f03a1d9c77abbe..9eebd1c0bcea78 100644 --- a/packages/components/src/utils/input/base.js +++ b/packages/components/src/utils/input/base.js @@ -11,7 +11,7 @@ import { CONFIG } from '../'; export const inputStyleNeutral = css` box-shadow: 0 0 0 transparent; - border-radius: ${ CONFIG.radiusBlockUi }; + border-radius: ${ CONFIG.radiusSmall }; border: ${ CONFIG.borderWidth } solid ${ COLORS.ui.border }; @media not ( prefers-reduced-motion ) { From 42db13fbac9b738d1874896e77214a6cbbaf0927 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 16 Aug 2024 17:34:39 +0200 Subject: [PATCH 0427/1908] Navigator: simplify backwards navigation APIs (#63317) * NavigatorProvider: make goBack an alias for goToParent * NavigatorBackButton: deprecate and ignore `goToParent` prop * NavigatorBackButton: always call `goBack` * Navigator: deprecate `goToParent` method * NavigatorToParentButton: deprecate the component, make it an alias for NavigatorGoBackButton * Add missing JSDocs for Navigator types * Update README * More docs additions * Fix tests by assuming that even an invalid HTML path starts with '/' * Add emphasis on the need for `path` to start with `/` * Add deprecation warnings * Update unit tests * Add back README for deprecated component * Add deprecation warning for `goToParent` function * CHANGELOG * Add more docs * Typos * Remove entirely the `goToParent` prop on `useNavigatorBackButton` This can be done because its usage was actually only internal to the component * Add deprecated APIs tests * Remove extra import (thank you autocomplete) --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../navigator-back-button/component.tsx | 2 +- .../navigator/navigator-back-button/hook.ts | 16 +- .../navigator/navigator-provider/README.md | 74 ++++----- .../navigator-provider/component.tsx | 20 ++- .../src/navigator/navigator-screen/README.md | 14 +- .../navigator-to-parent-button/README.md | 2 + .../navigator-to-parent-button/component.tsx | 57 ++----- .../components/src/navigator/test/index.tsx | 142 +++++++++++++++++- packages/components/src/navigator/types.ts | 55 +++++-- 10 files changed, 269 insertions(+), 114 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 1e6a96d2618d6f..f824bf8d2b2ddc 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -18,6 +18,7 @@ - `ToggleControl` - `ToggleGroupControl` - `TreeSelect` +- Deprecate `NavigatorToParentButton` and `useNavigator().goToParent()` in favor of `NavigatorBackButton` and `useNavigator().goBack()` ([#63317](https://github.com/WordPress/gutenberg/pull/63317)). ### Enhancements diff --git a/packages/components/src/navigator/navigator-back-button/component.tsx b/packages/components/src/navigator/navigator-back-button/component.tsx index 71c5ac14cd00d9..88ed45b643a13d 100644 --- a/packages/components/src/navigator/navigator-back-button/component.tsx +++ b/packages/components/src/navigator/navigator-back-button/component.tsx @@ -48,7 +48,7 @@ function UnconnectedNavigatorBackButton( * <NavigatorScreen path="/child"> * <p>This is the child screen.</p> * <NavigatorBackButton> - * Go back + * Go back (to parent) * </NavigatorBackButton> * </NavigatorScreen> * </NavigatorProvider> diff --git a/packages/components/src/navigator/navigator-back-button/hook.ts b/packages/components/src/navigator/navigator-back-button/hook.ts index edf55be0f15f5b..d4447b5f40ad46 100644 --- a/packages/components/src/navigator/navigator-back-button/hook.ts +++ b/packages/components/src/navigator/navigator-back-button/hook.ts @@ -10,31 +10,27 @@ import type { WordPressComponentProps } from '../../context'; import { useContextSystem } from '../../context'; import Button from '../../button'; import useNavigator from '../use-navigator'; -import type { NavigatorBackButtonHookProps } from '../types'; +import type { NavigatorBackButtonProps } from '../types'; export function useNavigatorBackButton( - props: WordPressComponentProps< NavigatorBackButtonHookProps, 'button' > + props: WordPressComponentProps< NavigatorBackButtonProps, 'button' > ) { const { onClick, as = Button, - goToParent: goToParentProp = false, + ...otherProps } = useContextSystem( props, 'NavigatorBackButton' ); - const { goBack, goToParent } = useNavigator(); + const { goBack } = useNavigator(); const handleClick: React.MouseEventHandler< HTMLButtonElement > = useCallback( ( e ) => { e.preventDefault(); - if ( goToParentProp ) { - goToParent(); - } else { - goBack(); - } + goBack(); onClick?.( e ); }, - [ goToParentProp, goToParent, goBack, onClick ] + [ goBack, onClick ] ); return { diff --git a/packages/components/src/navigator/navigator-provider/README.md b/packages/components/src/navigator/navigator-provider/README.md index 8be27a65101843..13745fae68a15d 100644 --- a/packages/components/src/navigator/navigator-provider/README.md +++ b/packages/components/src/navigator/navigator-provider/README.md @@ -10,38 +10,42 @@ The `NavigatorProvider` component allows rendering nested views/panels/menus (vi ```jsx import { - __experimentalNavigatorProvider as NavigatorProvider, - __experimentalNavigatorScreen as NavigatorScreen, - __experimentalNavigatorButton as NavigatorButton, - __experimentalNavigatorToParentButton as NavigatorToParentButton, + __experimentalNavigatorProvider as NavigatorProvider, + __experimentalNavigatorScreen as NavigatorScreen, + __experimentalNavigatorButton as NavigatorButton, + __experimentalNavigatorBackButton as NavigatorBackButton, } from '@wordpress/components'; const MyNavigation = () => ( - <NavigatorProvider initialPath="/"> - <NavigatorScreen path="/"> - <p>This is the home screen.</p> - <NavigatorButton path="/child"> - Navigate to child screen. - </NavigatorButton> - </NavigatorScreen> - - <NavigatorScreen path="/child"> - <p>This is the child screen.</p> - <NavigatorToParentButton> - Go back - </NavigatorToParentButton> - </NavigatorScreen> - </NavigatorProvider> + <NavigatorProvider initialPath="/"> + <NavigatorScreen path="/"> + <p>This is the home screen.</p> + <NavigatorButton path="/child"> + Navigate to child screen. + </NavigatorButton> + </NavigatorScreen> + + <NavigatorScreen path="/child"> + <p>This is the child screen.</p> + <NavigatorBackButton>Go back</NavigatorBackButton> + </NavigatorScreen> + </NavigatorProvider> ); ``` + **Important note** -Parent/child navigation only works if the path you define are hierarchical, following a URL-like scheme where each path segment is separated by the `/` character. +`Navigator` assumes that screens are organized hierarchically according to their `path`, which should follow a URL-like scheme where each path segment starts with and is separated by the `/` character. + +`Navigator` will treat "back" navigations as going to the parent screen — it is therefore responsibility of the consumer of the component to create the correct screen hierarchy. + For example: -- `/` is the root of all paths. There should always be a screen with `path="/"`. -- `/parent/child` is a child of `/parent`. -- `/parent/child/grand-child` is a child of `/parent/child`. -- `/parent/:param` is a child of `/parent` as well. + +- `/` is the root of all paths. There should always be a screen with `path="/"`. +- `/parent/child` is a child of `/parent`. +- `/parent/child/grand-child` is a child of `/parent/child`. +- `/parent/:param` is a child of `/parent` as well. +- if the current screen has a `path` with value `/parent/child/grand-child`, when going "back" `Navigator` will try to recursively navigate the path hierarchy until a matching screen (or the root `/`) is found. ## Props @@ -65,28 +69,26 @@ The `goTo` function allows navigating to a given path. The second argument can a The available options are: -- `focusTargetSelector`: `string`. An optional property used to specify the CSS selector used to restore focus on the matching element when navigating back. -- `isBack`: `boolean`. An optional property used to specify whether the navigation should be considered as backwards (thus enabling focus restoration when possible, and causing the animation to be backwards too) - -### `goToParent`: `() => void;` +- `focusTargetSelector`: `string`. An optional property used to specify the CSS selector used to restore focus on the matching element when navigating back; +- `isBack`: `boolean`. An optional property used to specify whether the navigation should be considered as backwards (thus enabling focus restoration when possible, and causing the animation to be backwards too); +- `skipFocus`: `boolean`. An optional property used to opt out of `Navigator`'s focus management, useful when the consumer of the component wants to manage focus themselves; +- `replace`: `boolean`. An optional property used to cause the new location to replace the current location in the stack. -The `goToParent` function allows navigating to the parent screen. +### `goBack`: `( path: string, options: NavigateOptions ) => void` -Parent/child navigation only works if the path you define are hierarchical (see note above). +The `goBack` function allows navigating to the parent screen. Parent/child navigation only works if the paths you define are hierarchical (see note above). When a match is not found, the function will try to recursively navigate the path hierarchy until a matching screen (or the root `/`) are found. -### `goBack`: `() => void` - -The `goBack` function allows navigating to the previous path. +The available options are the same as for the `goTo` method, except for the `isBack` property, which is not available for the `goBack` method. ### `location`: `NavigatorLocation` The `location` object represent the current location, and has a few properties: -- `path`: `string`. The path associated to the location. -- `isBack`: `boolean`. A flag that is `true` when the current location was reached by navigating backwards in the location stack. -- `isInitial`: `boolean`. A flag that is `true` only for the first (root) location in the location stack. +- `path`: `string`. The path associated to the location. +- `isBack`: `boolean`. A flag that is `true` when the current location was reached by navigating backwards in the location history. +- `isInitial`: `boolean`. A flag that is `true` only for the first (root) location in the location history. ### `params`: `Record< string, string | string[] >` diff --git a/packages/components/src/navigator/navigator-provider/component.tsx b/packages/components/src/navigator/navigator-provider/component.tsx index 15eb4d6bd3b1d3..78bc674c06fbd5 100644 --- a/packages/components/src/navigator/navigator-provider/component.tsx +++ b/packages/components/src/navigator/navigator-provider/component.tsx @@ -27,12 +27,12 @@ import type { Screen, NavigateToParentOptions, } from '../types'; +import deprecated from '@wordpress/deprecated'; type MatchedPath = ReturnType< typeof patternMatch >; type RouterAction = | { type: 'add' | 'remove'; screen: Screen } - | { type: 'goback' } | { type: 'goto'; path: string; options?: NavigateOptions } | { type: 'gotoparent'; options?: NavigateToParentOptions }; @@ -160,9 +160,6 @@ function routerReducer( case 'remove': screens = removeScreen( state, action.screen ); break; - case 'goback': - locationHistory = goBack( state ); - break; case 'goto': locationHistory = goTo( state, action.path, action.options ); break; @@ -223,11 +220,20 @@ function UnconnectedNavigatorProvider( // The methods are constant forever, create stable references to them. const methods = useMemo( () => ( { - goBack: () => dispatch( { type: 'goback' } ), + // Note: calling goBack calls `goToParent` internally, as it was established + // that `goBack` should behave like `goToParent`, and `goToParent` should + // be marked as deprecated. + goBack: ( options: NavigateToParentOptions | undefined ) => + dispatch( { type: 'gotoparent', options } ), goTo: ( path: string, options?: NavigateOptions ) => dispatch( { type: 'goto', path, options } ), - goToParent: ( options: NavigateToParentOptions | undefined ) => - dispatch( { type: 'gotoparent', options } ), + goToParent: ( options: NavigateToParentOptions | undefined ) => { + deprecated( `wp.components.useNavigator().goToParent`, { + since: '6.7', + alternative: 'wp.components.useNavigator().goBack', + } ); + dispatch( { type: 'gotoparent', options } ); + }, addScreen: ( screen: Screen ) => dispatch( { type: 'add', screen } ), removeScreen: ( screen: Screen ) => diff --git a/packages/components/src/navigator/navigator-screen/README.md b/packages/components/src/navigator/navigator-screen/README.md index 5ba5af44fe8c1a..583da461cd3c27 100644 --- a/packages/components/src/navigator/navigator-screen/README.md +++ b/packages/components/src/navigator/navigator-screen/README.md @@ -16,6 +16,18 @@ The component accepts the following props: ### `path`: `string` -The screen's path, matched against the current path stored in the navigator. +The screen"s path, matched against the current path stored in the navigator. + +`Navigator` assumes that screens are organized hierarchically according to their `path`, which should follow a URL-like scheme where each path segment starts with and is separated by the `/` character. + +`Navigator` will treat "back" navigations as going to the parent screen — it is therefore responsibility of the consumer of the component to create the correct screen hierarchy. + +For example: + +- `/` is the root of all paths. There should always be a screen with `path="/"`. +- `/parent/child` is a child of `/parent`. +- `/parent/child/grand-child` is a child of `/parent/child`. +- `/parent/:param` is a child of `/parent` as well. +- if the current screen has a `path` with value `/parent/child/grand-child`, when going "back" `Navigator` will try to recursively navigate the path hierarchy until a matching screen (or the root `/`) is found. - Required: Yes diff --git a/packages/components/src/navigator/navigator-to-parent-button/README.md b/packages/components/src/navigator/navigator-to-parent-button/README.md index 62dacc3dfa4ea5..0100ea9b8d2e1f 100644 --- a/packages/components/src/navigator/navigator-to-parent-button/README.md +++ b/packages/components/src/navigator/navigator-to-parent-button/README.md @@ -4,6 +4,8 @@ This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. </div> +This component is deprecated. Please use the [`NavigatorBackButton`](/packages/components/src/navigator/navigator-back-button/README.md) component instead. + The `NavigatorToParentButton` component can be used to navigate to a screen and should be used in combination with the [`NavigatorProvider`](/packages/components/src/navigator/navigator-provider/README.md), the [`NavigatorScreen`](/packages/components/src/navigator/navigator-screen/README.md) and the [`NavigatorButton`](/packages/components/src/navigator/navigator-button/README.md) components (or the `useNavigator` hook). ## Usage diff --git a/packages/components/src/navigator/navigator-to-parent-button/component.tsx b/packages/components/src/navigator/navigator-to-parent-button/component.tsx index e73a3619f3d494..400498b1fc96ca 100644 --- a/packages/components/src/navigator/navigator-to-parent-button/component.tsx +++ b/packages/components/src/navigator/navigator-to-parent-button/component.tsx @@ -1,62 +1,33 @@ /** - * External dependencies + * WordPress dependencies */ -import type { ForwardedRef } from 'react'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies */ +import { NavigatorBackButton } from '../navigator-back-button'; import type { WordPressComponentProps } from '../../context'; import { contextConnect } from '../../context'; -import { View } from '../../view'; -import { useNavigatorBackButton } from '../navigator-back-button/hook'; -import type { NavigatorToParentButtonProps } from '../types'; +import type { NavigatorBackButtonProps } from '../types'; function UnconnectedNavigatorToParentButton( - props: WordPressComponentProps< NavigatorToParentButtonProps, 'button' >, - forwardedRef: ForwardedRef< any > + props: WordPressComponentProps< NavigatorBackButtonProps, 'button' >, + forwardedRef: React.ForwardedRef< any > ) { - const navigatorToParentButtonProps = useNavigatorBackButton( { - ...props, - goToParent: true, + deprecated( 'wp.components.NavigatorToParentButton', { + since: '6.7', + alternative: 'wp.components.NavigatorBackButton', } ); - return <View ref={ forwardedRef } { ...navigatorToParentButtonProps } />; + return <NavigatorBackButton ref={ forwardedRef } { ...props } />; } -/* - * The `NavigatorToParentButton` component can be used to navigate to a screen and - * should be used in combination with the `NavigatorProvider`, the - * `NavigatorScreen` and the `NavigatorButton` components (or the `useNavigator` - * hook). - * - * @example - * ```jsx - * import { - * __experimentalNavigatorProvider as NavigatorProvider, - * __experimentalNavigatorScreen as NavigatorScreen, - * __experimentalNavigatorButton as NavigatorButton, - * __experimentalNavigatorToParentButton as NavigatorToParentButton, - * } from '@wordpress/components'; - * - * const MyNavigation = () => ( - * <NavigatorProvider initialPath="/"> - * <NavigatorScreen path="/"> - * <p>This is the home screen.</p> - * <NavigatorButton path="/child"> - * Navigate to child screen. - * </NavigatorButton> - * </NavigatorScreen> +/** + * _Note: this component is deprecated. Please use the `NavigatorBackButton` + * component instead._ * - * <NavigatorScreen path="/child"> - * <p>This is the child screen.</p> - * <NavigatorToParentButton> - * Go to parent - * </NavigatorToParentButton> - * </NavigatorScreen> - * </NavigatorProvider> - * ); - * ``` + * @deprecated */ export const NavigatorToParentButton = contextConnect( UnconnectedNavigatorToParentButton, diff --git a/packages/components/src/navigator/test/index.tsx b/packages/components/src/navigator/test/index.tsx index b83bd70d9d7444..9b9b257ea09681 100644 --- a/packages/components/src/navigator/test/index.tsx +++ b/packages/components/src/navigator/test/index.tsx @@ -25,8 +25,8 @@ import { import type { NavigateOptions } from '../types'; const INVALID_HTML_ATTRIBUTE = { - raw: ' "\'><=invalid_path', - escaped: " "'><=invalid_path", + raw: '/ "\'><=invalid_path', + escaped: "/ "'><=invalid_path", }; const PATHS = { @@ -165,6 +165,27 @@ function CustomNavigatorToParentButton( { ); } +function CustomNavigatorToParentButtonAlternative( { + onClick, + children, +}: { + children: React.ReactNode; + onClick?: CustomTestOnClickHandler; +} ) { + const { goToParent } = useNavigator(); + return ( + <button + onClick={ () => { + goToParent(); + // Used to spy on the values passed to `navigator.goBack`. + onClick?.( { type: 'goToParent' } ); + } } + > + { children } + </button> + ); +} + const ProductScreen = ( { onBackButtonClick, }: { @@ -344,20 +365,20 @@ const MyHierarchicalNavigation = ( { > { BUTTON_TEXT.toNestedScreen } </CustomNavigatorButton> - <CustomNavigatorToParentButton + <CustomNavigatorBackButton onClick={ onNavigatorButtonClick } > { BUTTON_TEXT.back } - </CustomNavigatorToParentButton> + </CustomNavigatorBackButton> </NavigatorScreen> <NavigatorScreen path={ PATHS.NESTED }> <p>{ SCREEN_TEXT.nested }</p> - <CustomNavigatorToParentButton + <CustomNavigatorBackButton onClick={ onNavigatorButtonClick } > { BUTTON_TEXT.back } - </CustomNavigatorToParentButton> + </CustomNavigatorBackButton> <CustomNavigatorGoToBackButton path={ PATHS.CHILD } onClick={ onNavigatorButtonClick } @@ -376,6 +397,66 @@ const MyHierarchicalNavigation = ( { ); }; +const MyDeprecatedNavigation = ( { + initialPath = PATHS.HOME, + onNavigatorButtonClick, +}: { + initialPath?: string; + onNavigatorButtonClick?: CustomTestOnClickHandler; +} ) => { + return ( + <> + <NavigatorProvider initialPath={ initialPath }> + <NavigatorScreen path={ PATHS.HOME }> + <p>{ SCREEN_TEXT.home }</p> + { /* + * A button useful to test focus restoration. This button is the first + * tabbable item in the screen, but should not receive focus when + * navigating to screen as a result of a backwards navigation. + */ } + <button>First tabbable home screen button</button> + <CustomNavigatorButton + path={ PATHS.CHILD } + onClick={ onNavigatorButtonClick } + > + { BUTTON_TEXT.toChildScreen } + </CustomNavigatorButton> + </NavigatorScreen> + + <NavigatorScreen path={ PATHS.CHILD }> + <p>{ SCREEN_TEXT.child }</p> + { /* + * A button useful to test focus restoration. This button is the first + * tabbable item in the screen, but should not receive focus when + * navigating to screen as a result of a backwards navigation. + */ } + <button>First tabbable child screen button</button> + <CustomNavigatorButton + path={ PATHS.NESTED } + onClick={ onNavigatorButtonClick } + > + { BUTTON_TEXT.toNestedScreen } + </CustomNavigatorButton> + <CustomNavigatorToParentButton + onClick={ onNavigatorButtonClick } + > + { BUTTON_TEXT.back } + </CustomNavigatorToParentButton> + </NavigatorScreen> + + <NavigatorScreen path={ PATHS.NESTED }> + <p>{ SCREEN_TEXT.nested }</p> + <CustomNavigatorToParentButtonAlternative + onClick={ onNavigatorButtonClick } + > + { BUTTON_TEXT.back } + </CustomNavigatorToParentButtonAlternative> + </NavigatorScreen> + </NavigatorProvider> + </> + ); +}; + const getScreen = ( screenKey: keyof typeof SCREEN_TEXT ) => screen.getByText( SCREEN_TEXT[ screenKey ] ); const queryScreen = ( screenKey: keyof typeof SCREEN_TEXT ) => @@ -769,4 +850,53 @@ describe( 'Navigator', () => { ).toHaveFocus(); } ); } ); + + describe( 'deprecated APIs', () => { + it( 'should log a deprecation notice when using the NavigatorToParentButton component', async () => { + const user = userEvent.setup(); + + render( <MyDeprecatedNavigation initialPath={ PATHS.CHILD } /> ); + + expect( getScreen( 'child' ) ).toBeInTheDocument(); + + // Navigate back to home screen. + // The first tabbable element receives focus, since focus restoration + // it not possible (there was no forward navigation). + await user.click( getNavigationButton( 'back' ) ); + expect( getScreen( 'home' ) ).toBeInTheDocument(); + expect( + screen.getByRole( 'button', { + name: 'First tabbable home screen button', + } ) + ).toHaveFocus(); + + // Rendering `NavigatorToParentButton` logs a deprecation notice + expect( console ).toHaveWarnedWith( + 'wp.components.NavigatorToParentButton is deprecated since version 6.7. Please use wp.components.NavigatorBackButton instead.' + ); + } ); + + it( 'should log a deprecation notice when using the useNavigator().goToParent() function', async () => { + const user = userEvent.setup(); + + render( <MyDeprecatedNavigation initialPath={ PATHS.NESTED } /> ); + + expect( getScreen( 'nested' ) ).toBeInTheDocument(); + + // Navigate back to child screen using the back button. + // The first tabbable element receives focus, since focus restoration + // it not possible (there was no forward navigation). + await user.click( getNavigationButton( 'back' ) ); + expect( getScreen( 'child' ) ).toBeInTheDocument(); + expect( + screen.getByRole( 'button', { + name: 'First tabbable child screen button', + } ) + ).toHaveFocus(); + + expect( console ).toHaveWarnedWith( + 'wp.components.useNavigator().goToParent is deprecated since version 6.7. Please use wp.components.useNavigator().goBack instead.' + ); + } ); + } ); } ); diff --git a/packages/components/src/navigator/types.ts b/packages/components/src/navigator/types.ts index 557f8074fd42e2..c45762d558af2d 100644 --- a/packages/components/src/navigator/types.ts +++ b/packages/components/src/navigator/types.ts @@ -11,26 +11,70 @@ import type { ButtonAsButtonProps } from '../button/types'; export type MatchParams = Record< string, string | string[] >; export type NavigateOptions = { + /** + * Specify the CSS selector used to restore focus on an given element when + * navigating back. When not provided, the component will attempt to restore + * focus on the element that originated the forward navigation. + */ focusTargetSelector?: string; + /** + * Whether the navigation is a backwards navigation. This enables focus + * restoration (when possible), and causes the animation to be backwards. + */ isBack?: boolean; + /** + * Opt out of focus management. Useful when the consumer of the component + * wants to manage focus themselves. + */ skipFocus?: boolean; + /** + * Whether the navigation should replace the current location in the stack. + */ replace?: boolean; }; export type NavigateToParentOptions = Omit< NavigateOptions, 'isBack' >; export type NavigatorLocation = NavigateOptions & { + /** + * Whether the current location is the initial one (ie. first in the stack). + */ isInitial?: boolean; + /** + * The path associated to the location. + */ path?: string; + /** + * Whether focus was already restored for this location (in case of + * backwards navigation). + */ hasRestoredFocus?: boolean; }; // Returned by the `useNavigator` hook. export type Navigator = { + /** + * The current location. + */ location: NavigatorLocation; + /** + * Params associated with the current location + */ params: MatchParams; + /** + * Navigate to a new location. + */ goTo: ( path: string, options?: NavigateOptions ) => void; - goBack: () => void; + /** + * Go back to the parent location (ie. "/some/path" will navigate back + * to "/some") + */ + goBack: ( options?: NavigateToParentOptions ) => void; + /** + * _Note: This function is deprecated. Please use `goBack` instead._ + * @deprecated + * @ignore + */ goToParent: ( options?: NavigateToParentOptions ) => void; }; @@ -64,15 +108,6 @@ export type NavigatorScreenProps = { export type NavigatorBackButtonProps = ButtonAsButtonProps; -export type NavigatorBackButtonHookProps = NavigatorBackButtonProps & { - /** - * Whether we should navigate to the parent screen. - * - * @default 'false' - */ - goToParent?: boolean; -}; - export type NavigatorToParentButtonProps = NavigatorBackButtonProps; export type NavigatorButtonProps = NavigatorBackButtonProps & { From 65da2128fb798638717bc27d55823590afc3cd47 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Sat, 17 Aug 2024 01:56:12 +0900 Subject: [PATCH 0428/1908] CustomSelectControl: Add lint rule for 40px size prop usage (#64559) * Fix in DateFormatPicker * Make explicit in FontAppearanceControl * Add lint rule Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .eslintrc.js | 1 + .../block-editor/src/components/date-format-picker/index.js | 1 + .../src/components/font-appearance-control/index.js | 3 +++ 3 files changed, 5 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index 2cdbb5c056cb14..42bb0accd72f1a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -313,6 +313,7 @@ module.exports = { ...[ 'BorderBoxControl', 'BorderControl', + 'CustomSelectControl', 'DimensionControl', 'FontSizePicker', 'ToggleGroupControl', diff --git a/packages/block-editor/src/components/date-format-picker/index.js b/packages/block-editor/src/components/date-format-picker/index.js index 63c977b111e01c..edefd6249f1aae 100644 --- a/packages/block-editor/src/components/date-format-picker/index.js +++ b/packages/block-editor/src/components/date-format-picker/index.js @@ -129,6 +129,7 @@ function NonDefaultControls( { format, onChange } ) { return ( <VStack> <CustomSelectControl + __next40pxDefaultSize label={ __( 'Choose a format' ) } options={ [ ...suggestedOptions, customOption ] } value={ diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index 418d43e322ac89..38cb42e394a3bd 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -39,6 +39,8 @@ const getFontAppearanceLabel = ( hasFontStyles, hasFontWeights ) => { */ export default function FontAppearanceControl( props ) { const { + /** Start opting into the larger default height that will become the default size in a future version. */ + __next40pxDefaultSize = false, onChange, hasFontStyles = true, hasFontWeights = true, @@ -150,6 +152,7 @@ export default function FontAppearanceControl( props ) { <CustomSelectControl { ...otherProps } className="components-font-appearance-control" + __next40pxDefaultSize={ __next40pxDefaultSize } label={ label } describedBy={ getDescribedBy() } options={ selectOptions } From 78722b9e62b13308d8ce39a1a31901bdf70562b4 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Sat, 17 Aug 2024 02:38:24 +0900 Subject: [PATCH 0429/1908] NumberControl: Add lint rule for 40px size prop usage (#64561) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .eslintrc.js | 1 + .../src/components/line-height-control/README.md | 7 +++++++ .../src/components/line-height-control/index.js | 3 +++ 3 files changed, 11 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index 42bb0accd72f1a..e21f7d6e6d7806 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -316,6 +316,7 @@ module.exports = { 'CustomSelectControl', 'DimensionControl', 'FontSizePicker', + 'NumberControl', 'ToggleGroupControl', ].map( ( componentName ) => ( { // Falsy `__next40pxDefaultSize` without a non-default `size` prop. diff --git a/packages/block-editor/src/components/line-height-control/README.md b/packages/block-editor/src/components/line-height-control/README.md index dafad9145022b9..89bcc69622367f 100644 --- a/packages/block-editor/src/components/line-height-control/README.md +++ b/packages/block-editor/src/components/line-height-control/README.md @@ -36,6 +36,13 @@ The value of the line height. A callback function that handles the application of the line height value. +#### `__next40pxDefaultSize` + +- **Type:** `boolean` +- **Default:** `false` + +Start opting into the larger default height that will become the default size in a future version. + ## Related components Block Editor components are components that can be used to compose the UI of your block editor. Thus, they can only be used under a [`BlockEditorProvider`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/provider/README.md) in the components tree. diff --git a/packages/block-editor/src/components/line-height-control/index.js b/packages/block-editor/src/components/line-height-control/index.js index d605aea3d2ef18..b2c99c03f87840 100644 --- a/packages/block-editor/src/components/line-height-control/index.js +++ b/packages/block-editor/src/components/line-height-control/index.js @@ -16,6 +16,8 @@ import { } from './utils'; const LineHeightControl = ( { + /** Start opting into the larger default height that will become the default size in a future version. */ + __next40pxDefaultSize = false, value: lineHeight, onChange, __unstableInputWidth = '60px', @@ -91,6 +93,7 @@ const LineHeightControl = ( { <div className="block-editor-line-height-control"> <NumberControl { ...otherProps } + __next40pxDefaultSize={ __next40pxDefaultSize } __unstableInputWidth={ __unstableInputWidth } __unstableStateReducer={ stateReducer } onChange={ handleOnChange } From a0951885b0a9bdd225046c2a5c7def9bf5c5aefc Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Sat, 17 Aug 2024 04:01:35 +0900 Subject: [PATCH 0430/1908] ComboboxControl: Add lint rule for 40px size prop usage (#64560) * Fix in Author block * Fix in Avatar block * Add lint rule Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .eslintrc.js | 1 + .../block-library/src/avatar/user-control.js | 1 + packages/block-library/src/editor.scss | 1 + .../block-library/src/post-author/block.json | 1 + .../block-library/src/post-author/edit.js | 125 ++++++++++-------- .../block-library/src/post-author/editor.scss | 7 + 6 files changed, 78 insertions(+), 58 deletions(-) create mode 100644 packages/block-library/src/post-author/editor.scss diff --git a/.eslintrc.js b/.eslintrc.js index e21f7d6e6d7806..f6b24dcb15017f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -313,6 +313,7 @@ module.exports = { ...[ 'BorderBoxControl', 'BorderControl', + 'ComboboxControl', 'CustomSelectControl', 'DimensionControl', 'FontSizePicker', diff --git a/packages/block-library/src/avatar/user-control.js b/packages/block-library/src/avatar/user-control.js index 598c05011eaed7..235202ffec90d7 100644 --- a/packages/block-library/src/avatar/user-control.js +++ b/packages/block-library/src/avatar/user-control.js @@ -33,6 +33,7 @@ function UserControl( { value, onChange } ) { return ( <ComboboxControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'User' ) } help={ __( diff --git a/packages/block-library/src/editor.scss b/packages/block-library/src/editor.scss index 52f3aa64287fae..0669a082b1086f 100644 --- a/packages/block-library/src/editor.scss +++ b/packages/block-library/src/editor.scss @@ -31,6 +31,7 @@ @import "./nextpage/editor.scss"; @import "./page-list/editor.scss"; @import "./paragraph/editor.scss"; +@import "./post-author/editor.scss"; @import "./post-excerpt/editor.scss"; @import "./pullquote/editor.scss"; @import "./rss/editor.scss"; diff --git a/packages/block-library/src/post-author/block.json b/packages/block-library/src/post-author/block.json index 6f814810744c6d..dde9320841820d 100644 --- a/packages/block-library/src/post-author/block.json +++ b/packages/block-library/src/post-author/block.json @@ -66,5 +66,6 @@ "clientNavigation": true } }, + "editorStyle": "wp-block-post-author-editor", "style": "wp-block-post-author" } diff --git a/packages/block-library/src/post-author/edit.js b/packages/block-library/src/post-author/edit.js index 1bc1ef4ffcd8a3..6186b0d052e8aa 100644 --- a/packages/block-library/src/post-author/edit.js +++ b/packages/block-library/src/post-author/edit.js @@ -18,6 +18,7 @@ import { PanelBody, SelectControl, ToggleControl, + __experimentalVStack as VStack, } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; @@ -100,74 +101,82 @@ function PostAuthorEdit( { <> <InspectorControls> <PanelBody title={ __( 'Settings' ) }> - { showAuthorControl && - ( ( showCombobox && ( - <ComboboxControl - __nextHasNoMarginBottom - label={ __( 'Author' ) } - options={ authorOptions } - value={ authorId } - onChange={ handleSelect } - allowReset={ false } - /> - ) ) || ( + <VStack + spacing={ 4 } + className="wp-block-post-author__inspector-settings" + > + { showAuthorControl && + ( ( showCombobox && ( + <ComboboxControl + __next40pxDefaultSize + __nextHasNoMarginBottom + label={ __( 'Author' ) } + options={ authorOptions } + value={ authorId } + onChange={ handleSelect } + allowReset={ false } + /> + ) ) || ( + <SelectControl + __next40pxDefaultSize + __nextHasNoMarginBottom + label={ __( 'Author' ) } + value={ authorId } + options={ authorOptions } + onChange={ handleSelect } + /> + ) ) } + <ToggleControl + __nextHasNoMarginBottom + label={ __( 'Show avatar' ) } + checked={ showAvatar } + onChange={ () => + setAttributes( { showAvatar: ! showAvatar } ) + } + /> + { showAvatar && ( <SelectControl __next40pxDefaultSize __nextHasNoMarginBottom - label={ __( 'Author' ) } - value={ authorId } - options={ authorOptions } - onChange={ handleSelect } + label={ __( 'Avatar size' ) } + value={ attributes.avatarSize } + options={ avatarSizes } + onChange={ ( size ) => { + setAttributes( { + avatarSize: Number( size ), + } ); + } } /> - ) ) } - <ToggleControl - __nextHasNoMarginBottom - label={ __( 'Show avatar' ) } - checked={ showAvatar } - onChange={ () => - setAttributes( { showAvatar: ! showAvatar } ) - } - /> - { showAvatar && ( - <SelectControl - __next40pxDefaultSize + ) } + <ToggleControl __nextHasNoMarginBottom - label={ __( 'Avatar size' ) } - value={ attributes.avatarSize } - options={ avatarSizes } - onChange={ ( size ) => { - setAttributes( { - avatarSize: Number( size ), - } ); - } } + label={ __( 'Show bio' ) } + checked={ showBio } + onChange={ () => + setAttributes( { showBio: ! showBio } ) + } /> - ) } - <ToggleControl - __nextHasNoMarginBottom - label={ __( 'Show bio' ) } - checked={ showBio } - onChange={ () => - setAttributes( { showBio: ! showBio } ) - } - /> - <ToggleControl - __nextHasNoMarginBottom - label={ __( 'Link author name to author page' ) } - checked={ isLink } - onChange={ () => setAttributes( { isLink: ! isLink } ) } - /> - { isLink && ( <ToggleControl __nextHasNoMarginBottom - label={ __( 'Open in new tab' ) } - onChange={ ( value ) => - setAttributes( { - linkTarget: value ? '_blank' : '_self', - } ) + label={ __( 'Link author name to author page' ) } + checked={ isLink } + onChange={ () => + setAttributes( { isLink: ! isLink } ) } - checked={ linkTarget === '_blank' } /> - ) } + { isLink && ( + <ToggleControl + __nextHasNoMarginBottom + label={ __( 'Open in new tab' ) } + onChange={ ( value ) => + setAttributes( { + linkTarget: value ? '_blank' : '_self', + } ) + } + checked={ linkTarget === '_blank' } + /> + ) } + </VStack> </PanelBody> </InspectorControls> diff --git a/packages/block-library/src/post-author/editor.scss b/packages/block-library/src/post-author/editor.scss new file mode 100644 index 00000000000000..f6464893138cff --- /dev/null +++ b/packages/block-library/src/post-author/editor.scss @@ -0,0 +1,7 @@ +.wp-block-post-author__inspector-settings { + // Counteract the margin added by the block inspector. + .components-base-control, + .components-base-control:last-child { + margin-bottom: 0; + } +} From c459a7bebec8d8c7db8af2a0be6517a02d573b3c Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Sat, 17 Aug 2024 00:39:54 +0530 Subject: [PATCH 0431/1908] Feat: Button groups in Typography tools should use ToggleGroupControl (#64529) * Update the letterCase typogrpahy panel to use toggleGroupOption component * Remove unecessary style for segmented text control and match height with components * Remove SegmentedTextControl component and use toggleControl * Reduce the diff change in the PR Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../segmented-text-control/index.js | 63 ------------------- .../segmented-text-control/style.scss | 15 ----- .../text-alignment-control/index.js | 28 ++++++--- .../text-decoration-control/index.js | 28 ++++++--- .../text-transform-control/index.js | 28 ++++++--- .../components/writing-mode-control/index.js | 28 ++++++--- packages/block-editor/src/style.scss | 1 - 7 files changed, 80 insertions(+), 111 deletions(-) delete mode 100644 packages/block-editor/src/components/segmented-text-control/index.js delete mode 100644 packages/block-editor/src/components/segmented-text-control/style.scss diff --git a/packages/block-editor/src/components/segmented-text-control/index.js b/packages/block-editor/src/components/segmented-text-control/index.js deleted file mode 100644 index 28f049bfb40ec9..00000000000000 --- a/packages/block-editor/src/components/segmented-text-control/index.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - -/** - * WordPress dependencies - */ -import { BaseControl, Button } from '@wordpress/components'; - -/** - * @typedef {Object} Option - * @property {string} label The label of the option. - * @property {string} value The value of the option. - * @property {string} icon The icon of the option. - */ - -/** - * Control to facilitate selecting a text style from a set of options. - * - * @param {Object} props Component props. - * @param {string} props.label A label for the option. - * @param {string} props.value Currently selected value. - * @param {Function} props.onChange Callback to handle onChange. - * @param {Option[]} props.options Array of options to display. - * @param {string} props.className Additional class name to apply. - * - * @return {Element} Element to render. - */ -export default function SegmentedTextControl( { - label, - value, - options, - onChange, - className, -} ) { - return ( - <fieldset - className={ clsx( - 'block-editor-segmented-text-control', - className - ) } - > - <BaseControl.VisualLabel as="legend"> - { label } - </BaseControl.VisualLabel> - <div className="block-editor-segmented-text-control__buttons"> - { options.map( ( option ) => { - return ( - <Button - size="compact" - key={ option.value } - icon={ option.icon } - label={ option.label } - isPressed={ option.value === value } - onClick={ () => onChange( option.value ) } - /> - ); - } ) } - </div> - </fieldset> - ); -} diff --git a/packages/block-editor/src/components/segmented-text-control/style.scss b/packages/block-editor/src/components/segmented-text-control/style.scss deleted file mode 100644 index 7a4a3bbea7cb33..00000000000000 --- a/packages/block-editor/src/components/segmented-text-control/style.scss +++ /dev/null @@ -1,15 +0,0 @@ -.block-editor-segmented-text-control { - border: 0; - margin: 0; - padding: 0; - - .block-editor-segmented-text-control__buttons { - // 4px of padding makes the row 40px high, same as an input. - padding: $grid-unit-05 0; - display: flex; - } - - .components-button.has-icon { - margin-right: $grid-unit-05; - } -} diff --git a/packages/block-editor/src/components/text-alignment-control/index.js b/packages/block-editor/src/components/text-alignment-control/index.js index 88a6fe274ea09b..6eeaad784db0f0 100644 --- a/packages/block-editor/src/components/text-alignment-control/index.js +++ b/packages/block-editor/src/components/text-alignment-control/index.js @@ -14,11 +14,10 @@ import { alignJustify, } from '@wordpress/icons'; import { useMemo } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import SegmentedTextControl from '../segmented-text-control'; +import { + __experimentalToggleGroupControl as ToggleGroupControl, + __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, +} from '@wordpress/components'; const TEXT_ALIGNMENT_OPTIONS = [ { @@ -75,9 +74,11 @@ export default function TextAlignmentControl( { } return ( - <SegmentedTextControl + <ToggleGroupControl + isDeselectable + __nextHasNoMarginBottom + __next40pxDefaultSize label={ __( 'Text alignment' ) } - options={ validOptions } className={ clsx( 'block-editor-text-alignment-control', className @@ -86,6 +87,17 @@ export default function TextAlignmentControl( { onChange={ ( newValue ) => { onChange( newValue === value ? undefined : newValue ); } } - /> + > + { validOptions.map( ( option ) => { + return ( + <ToggleGroupControlOptionIcon + key={ option.value } + value={ option.value } + icon={ option.icon } + label={ option.label } + /> + ); + } ) } + </ToggleGroupControl> ); } diff --git a/packages/block-editor/src/components/text-decoration-control/index.js b/packages/block-editor/src/components/text-decoration-control/index.js index d06632afdbb3ca..720f3d2d9558eb 100644 --- a/packages/block-editor/src/components/text-decoration-control/index.js +++ b/packages/block-editor/src/components/text-decoration-control/index.js @@ -8,11 +8,10 @@ import clsx from 'clsx'; */ import { reset, formatStrikethrough, formatUnderline } from '@wordpress/icons'; import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import SegmentedTextControl from '../segmented-text-control'; +import { + __experimentalToggleGroupControl as ToggleGroupControl, + __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, +} from '@wordpress/components'; const TEXT_DECORATIONS = [ { @@ -48,9 +47,11 @@ export default function TextDecorationControl( { className, } ) { return ( - <SegmentedTextControl + <ToggleGroupControl + isDeselectable + __nextHasNoMarginBottom + __next40pxDefaultSize label={ __( 'Decoration' ) } - options={ TEXT_DECORATIONS } className={ clsx( 'block-editor-text-decoration-control', className @@ -59,6 +60,17 @@ export default function TextDecorationControl( { onChange={ ( newValue ) => { onChange( newValue === value ? undefined : newValue ); } } - /> + > + { TEXT_DECORATIONS.map( ( option ) => { + return ( + <ToggleGroupControlOptionIcon + key={ option.value } + value={ option.value } + icon={ option.icon } + label={ option.label } + /> + ); + } ) } + </ToggleGroupControl> ); } diff --git a/packages/block-editor/src/components/text-transform-control/index.js b/packages/block-editor/src/components/text-transform-control/index.js index f448a55ed946c3..a3183e630c328a 100644 --- a/packages/block-editor/src/components/text-transform-control/index.js +++ b/packages/block-editor/src/components/text-transform-control/index.js @@ -13,11 +13,10 @@ import { formatLowercase, formatUppercase, } from '@wordpress/icons'; - -/** - * Internal dependencies - */ -import SegmentedTextControl from '../segmented-text-control'; +import { + __experimentalToggleGroupControl as ToggleGroupControl, + __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, +} from '@wordpress/components'; const TEXT_TRANSFORMS = [ { @@ -54,9 +53,11 @@ const TEXT_TRANSFORMS = [ */ export default function TextTransformControl( { className, value, onChange } ) { return ( - <SegmentedTextControl + <ToggleGroupControl + isDeselectable + __nextHasNoMarginBottom + __next40pxDefaultSize label={ __( 'Letter case' ) } - options={ TEXT_TRANSFORMS } className={ clsx( 'block-editor-text-transform-control', className @@ -65,6 +66,17 @@ export default function TextTransformControl( { className, value, onChange } ) { onChange={ ( newValue ) => { onChange( newValue === value ? undefined : newValue ); } } - /> + > + { TEXT_TRANSFORMS.map( ( option ) => { + return ( + <ToggleGroupControlOptionIcon + key={ option.value } + value={ option.value } + icon={ option.icon } + label={ option.label } + /> + ); + } ) } + </ToggleGroupControl> ); } diff --git a/packages/block-editor/src/components/writing-mode-control/index.js b/packages/block-editor/src/components/writing-mode-control/index.js index 7732f54b1569a7..bffccfd579c6b0 100644 --- a/packages/block-editor/src/components/writing-mode-control/index.js +++ b/packages/block-editor/src/components/writing-mode-control/index.js @@ -8,11 +8,10 @@ import clsx from 'clsx'; */ import { __, isRTL } from '@wordpress/i18n'; import { textHorizontal, textVertical } from '@wordpress/icons'; - -/** - * Internal dependencies - */ -import SegmentedTextControl from '../segmented-text-control'; +import { + __experimentalToggleGroupControl as ToggleGroupControl, + __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, +} from '@wordpress/components'; const WRITING_MODES = [ { @@ -39,14 +38,27 @@ const WRITING_MODES = [ */ export default function WritingModeControl( { className, value, onChange } ) { return ( - <SegmentedTextControl + <ToggleGroupControl + isDeselectable + __nextHasNoMarginBottom + __next40pxDefaultSize label={ __( 'Orientation' ) } - options={ WRITING_MODES } className={ clsx( 'block-editor-writing-mode-control', className ) } value={ value } onChange={ ( newValue ) => { onChange( newValue === value ? undefined : newValue ); } } - /> + > + { WRITING_MODES.map( ( option ) => { + return ( + <ToggleGroupControlOptionIcon + key={ option.value } + value={ option.value } + icon={ option.icon } + label={ option.label } + /> + ); + } ) } + </ToggleGroupControl> ); } diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index 47b87bb50918df..feaabbbda94426 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -40,7 +40,6 @@ @import "./components/multi-selection-inspector/style.scss"; @import "./components/responsive-block-control/style.scss"; @import "./components/rich-text/style.scss"; -@import "./components/segmented-text-control/style.scss"; @import "./components/skip-to-selected-block/style.scss"; @import "./components/tabbed-sidebar/style.scss"; @import "./components/tool-selector/style.scss"; From 68dd5ce54901a2d5f8bf25ba170d603701426ad4 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Sat, 17 Aug 2024 04:33:24 +0900 Subject: [PATCH 0432/1908] RangeControl: Add lint rule for 40px size prop usage (#64558) * Fix in Query Loop block * Fix in Excerpt block * Fix in Grid block * Fix in SpacingSizesControl * Fix in Image block Zoom control * Fix in HeightControl * Fix in BorderRadiusControl * Add lint rule * Fixup in HeightControl * Address in ColorPicker Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .eslintrc.js | 1 + .../components/border-radius-control/index.js | 1 + .../border-radius-control/style.scss | 10 ------- .../src/components/height-control/index.js | 1 + .../components/image-editor/zoom-dropdown.js | 26 ++++++++++++------- .../input-controls/spacing-input-control.js | 2 ++ .../spacing-sizes-control/style.scss | 10 ------- packages/block-editor/src/layouts/grid.js | 2 ++ .../block-library/src/post-excerpt/edit.js | 1 + .../src/query-pagination-numbers/edit.js | 1 + .../src/color-picker/input-with-slider.tsx | 1 + 11 files changed, 27 insertions(+), 29 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index f6b24dcb15017f..5a939aeb9173b7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -318,6 +318,7 @@ module.exports = { 'DimensionControl', 'FontSizePicker', 'NumberControl', + 'RangeControl', 'ToggleGroupControl', ].map( ( componentName ) => ( { // Falsy `__next40pxDefaultSize` without a non-default `size` prop. diff --git a/packages/block-editor/src/components/border-radius-control/index.js b/packages/block-editor/src/components/border-radius-control/index.js index 4c614084a7e200..cab9b87b3b29c0 100644 --- a/packages/block-editor/src/components/border-radius-control/index.js +++ b/packages/block-editor/src/components/border-radius-control/index.js @@ -104,6 +104,7 @@ export default function BorderRadiusControl( { onChange, values } ) { units={ units } /> <RangeControl + __next40pxDefaultSize label={ __( 'Border radius' ) } hideLabelFromVision className="components-border-radius-control__range-control" diff --git a/packages/block-editor/src/components/border-radius-control/style.scss b/packages/block-editor/src/components/border-radius-control/style.scss index c94dfbbd0a8fdb..18360cf3162ab1 100644 --- a/packages/block-editor/src/components/border-radius-control/style.scss +++ b/packages/block-editor/src/components/border-radius-control/style.scss @@ -20,16 +20,6 @@ .components-border-radius-control__range-control { flex: 1; margin-right: $grid-unit-15; - - > div { - height: 40px; - display: flex; - align-items: center; - } - } - - > span { - flex: 0 0 auto; } } diff --git a/packages/block-editor/src/components/height-control/index.js b/packages/block-editor/src/components/height-control/index.js index 71753a67beb021..5d42e217776d6a 100644 --- a/packages/block-editor/src/components/height-control/index.js +++ b/packages/block-editor/src/components/height-control/index.js @@ -164,6 +164,7 @@ export default function HeightControl( { <FlexItem isBlock> <Spacer marginX={ 2 } marginBottom={ 0 }> <RangeControl + __next40pxDefaultSize value={ customRangeValue } min={ 0 } max={ diff --git a/packages/block-editor/src/components/image-editor/zoom-dropdown.js b/packages/block-editor/src/components/image-editor/zoom-dropdown.js index 70baa28b2e112c..5093b11feb6d87 100644 --- a/packages/block-editor/src/components/image-editor/zoom-dropdown.js +++ b/packages/block-editor/src/components/image-editor/zoom-dropdown.js @@ -1,7 +1,12 @@ /** * WordPress dependencies */ -import { ToolbarButton, RangeControl, Dropdown } from '@wordpress/components'; +import { + ToolbarButton, + RangeControl, + Dropdown, + __experimentalDropdownContentWrapper as DropdownContentWrapper, +} from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { search } from '@wordpress/icons'; @@ -27,14 +32,17 @@ export default function ZoomDropdown() { /> ) } renderContent={ () => ( - <RangeControl - __nextHasNoMarginBottom - label={ __( 'Zoom' ) } - min={ MIN_ZOOM } - max={ MAX_ZOOM } - value={ Math.round( zoom ) } - onChange={ setZoom } - /> + <DropdownContentWrapper paddingSize="medium"> + <RangeControl + __next40pxDefaultSize + __nextHasNoMarginBottom + label={ __( 'Zoom' ) } + min={ MIN_ZOOM } + max={ MAX_ZOOM } + value={ Math.round( zoom ) } + onChange={ setZoom } + /> + </DropdownContentWrapper> ) } /> ); diff --git a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js index 5cdfe47c452b23..d00feed704d17a 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js +++ b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js @@ -249,6 +249,7 @@ export default function SpacingInputControl( { } } /> <RangeControl + __next40pxDefaultSize onMouseOver={ onMouseOver } onMouseOut={ onMouseOut } onFocus={ onMouseOver } @@ -270,6 +271,7 @@ export default function SpacingInputControl( { ) } { showRangeControl && ! showCustomValueControl && ( <RangeControl + __next40pxDefaultSize onMouseOver={ onMouseOver } onMouseOut={ onMouseOut } className="spacing-sizes-control__range-control" diff --git a/packages/block-editor/src/components/spacing-sizes-control/style.scss b/packages/block-editor/src/components/spacing-sizes-control/style.scss index 69f30a8c7d1e90..cbcc8e30c58253 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/style.scss +++ b/packages/block-editor/src/components/spacing-sizes-control/style.scss @@ -18,17 +18,7 @@ .spacing-sizes-control__range-control, .spacing-sizes-control__custom-value-range { - height: 40px; - /* Vertically center the RangeControl until it has true 40px height. */ - display: flex; - align-items: center; - margin-bottom: 0; flex: 1; - - > .components-base-control__field { - /* Fixes RangeControl contents when the outer wrapper is flex */ - flex: 1; - } } .components-range-control__mark { diff --git a/packages/block-editor/src/layouts/grid.js b/packages/block-editor/src/layouts/grid.js index c574ad0ae43d5d..7ab5c7ebbc8c3d 100644 --- a/packages/block-editor/src/layouts/grid.js +++ b/packages/block-editor/src/layouts/grid.js @@ -264,6 +264,7 @@ function GridLayoutMinimumWidthControl( { layout, onChange } ) { </FlexItem> <FlexItem isBlock> <RangeControl + __next40pxDefaultSize __nextHasNoMarginBottom onChange={ handleSliderChange } value={ quantity || 0 } @@ -368,6 +369,7 @@ function GridLayoutColumnsAndRowsControl( { /> ) : ( <RangeControl + __next40pxDefaultSize __nextHasNoMarginBottom value={ columnCount ?? 0 } onChange={ ( value ) => diff --git a/packages/block-library/src/post-excerpt/edit.js b/packages/block-library/src/post-excerpt/edit.js index 45d0a79a411d61..05aaf543b59196 100644 --- a/packages/block-library/src/post-excerpt/edit.js +++ b/packages/block-library/src/post-excerpt/edit.js @@ -231,6 +231,7 @@ export default function PostExcerptEditor( { } /> <RangeControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Max number of words' ) } value={ excerptLength } diff --git a/packages/block-library/src/query-pagination-numbers/edit.js b/packages/block-library/src/query-pagination-numbers/edit.js index e495fe8529a07a..b8d8c160cc874d 100644 --- a/packages/block-library/src/query-pagination-numbers/edit.js +++ b/packages/block-library/src/query-pagination-numbers/edit.js @@ -51,6 +51,7 @@ export default function QueryPaginationNumbersEdit( { <InspectorControls> <PanelBody title={ __( 'Settings' ) }> <RangeControl + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Number of links' ) } help={ __( diff --git a/packages/components/src/color-picker/input-with-slider.tsx b/packages/components/src/color-picker/input-with-slider.tsx index b51db75c1f4513..535adc3f2af6ee 100644 --- a/packages/components/src/color-picker/input-with-slider.tsx +++ b/packages/components/src/color-picker/input-with-slider.tsx @@ -53,6 +53,7 @@ export const InputWithSlider = ( { /> <RangeControl __nextHasNoMarginBottom + __next40pxDefaultSize label={ label } hideLabelFromVision min={ min } From 8169dfd2c89b82ed39bb74be8063a715b467c184 Mon Sep 17 00:00:00 2001 From: Xinyu Liu <meteor.lxy@foxmail.com> Date: Sat, 17 Aug 2024 05:51:32 +0800 Subject: [PATCH 0433/1908] CustomSelectControl: improve props type inferring (#64412) * CustomSelectControl: improve props type inferring * chore: update changelog * chore: updates Co-authored-by: meteorlxy <meteorlxy@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 + .../src/custom-select-control/test/index.tsx | 125 ++++++++++++++++++ .../src/custom-select-control/types.ts | 6 +- 3 files changed, 132 insertions(+), 3 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index f824bf8d2b2ddc..f1b6ba3341de60 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -67,6 +67,10 @@ - `Composite` v2: add focus-related props to `Composite`and`Composite.Item` subcomponents ([#64450](https://github.com/WordPress/gutenberg/pull/64450)). - `Composite` v2: add `Context` subcomponent ([#64493](https://github.com/WordPress/gutenberg/pull/64493)). +### Internal + +- `CustomSelectControl`: Improve type inferring ([#64412](https://github.com/WordPress/gutenberg/pull/64412)). + ## 28.5.0 (2024-08-07) ### Bug Fixes diff --git a/packages/components/src/custom-select-control/test/index.tsx b/packages/components/src/custom-select-control/test/index.tsx index fdbe8d72a48dec..b2ac5c19c6ab3f 100644 --- a/packages/components/src/custom-select-control/test/index.tsx +++ b/packages/components/src/custom-select-control/test/index.tsx @@ -689,3 +689,128 @@ describe.each( [ } ); } ); } ); + +describe( 'Type checking', () => { + // eslint-disable-next-line jest/expect-expect + it( 'should infer the value type from available `options`, but not the `value` or `onChange` prop', () => { + const options = [ + { + key: 'narrow', + name: 'Narrow', + }, + { + key: 'value', + name: 'Value', + }, + ]; + const optionsReadOnly = [ + { + key: 'narrow', + name: 'Narrow', + }, + { + key: 'value', + name: 'Value', + }, + ] as const; + + const onChange = (): void => {}; + + <UncontrolledCustomSelectControl + label="Label" + options={ options } + value={ { + key: 'narrow', + name: 'Narrow', + } } + onChange={ onChange } + />; + + <UncontrolledCustomSelectControl + label="Label" + options={ options } + value={ { + key: 'random string is also accepted for non-readonly options', + name: 'Narrow', + } } + onChange={ onChange } + />; + + <UncontrolledCustomSelectControl + label="Label" + options={ options } + value={ { + key: 'narrow', + name: 'Narrow', + // @ts-expect-error: the option type should not be inferred from `value` + foo: 'foo', + } } + onChange={ onChange } + />; + + <UncontrolledCustomSelectControl + label="Label" + options={ options } + value={ { + key: 'narrow', + name: 'Narrow', + } } + // To ensure the type inferring is working correctly, but this is not a common use case. + // @ts-expect-error: the option type should not be inferred from `onChange` + onChange={ + onChange as ( obj: { + selectedItem: { key: string; name: string; foo: string }; + } ) => void + } + />; + + <UncontrolledCustomSelectControl + label="Label" + options={ optionsReadOnly } + value={ { + key: 'narrow', + name: 'Narrow', + } } + onChange={ onChange } + />; + + <UncontrolledCustomSelectControl + label="Label" + options={ optionsReadOnly } + value={ { + // @ts-expect-error: random string is not accepted for immutable options + key: 'random string is not accepted for readonly options', + name: 'Narrow', + } } + onChange={ onChange } + />; + + <UncontrolledCustomSelectControl + label="Label" + options={ optionsReadOnly } + value={ { + key: 'narrow', + name: 'Narrow', + // @ts-expect-error: the option type should not be inferred from `value` + foo: 'foo', + } } + onChange={ onChange } + />; + + <UncontrolledCustomSelectControl + label="Label" + options={ optionsReadOnly } + value={ { + key: 'narrow', + name: 'Narrow', + } } + // To ensure the type inferring is working correctly, but this is not a common use case. + // @ts-expect-error: the option type should not be inferred from `onChange` + onChange={ + onChange as ( obj: { + selectedItem: { key: string; name: string; foo: string }; + } ) => void + } + />; + } ); +} ); diff --git a/packages/components/src/custom-select-control/types.ts b/packages/components/src/custom-select-control/types.ts index e37ba349a2b843..0cbc2388e79638 100644 --- a/packages/components/src/custom-select-control/types.ts +++ b/packages/components/src/custom-select-control/types.ts @@ -55,7 +55,7 @@ export type CustomSelectProps< T extends CustomSelectOption > = { * Function called with the control's internal state changes. The `selectedItem` * property contains the next selected item. */ - onChange?: ( newValue: CustomSelectChangeObject< T > ) => void; + onChange?: ( newValue: CustomSelectChangeObject< NoInfer< T > > ) => void; /** * A handler for `blur` events on the trigger button. * @@ -83,7 +83,7 @@ export type CustomSelectProps< T extends CustomSelectOption > = { /** * The list of options that can be chosen from. */ - options: Array< T >; + options: ReadonlyArray< T >; /** * The size of the control. * @@ -93,7 +93,7 @@ export type CustomSelectProps< T extends CustomSelectOption > = { /** * Can be used to externally control the value of the control. */ - value?: T; + value?: NoInfer< T >; /** * Use the `showSelectedHint` property instead. * @deprecated From 898448ab292642aa6b6430b9bd0a2fe9b017d335 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Sat, 17 Aug 2024 15:36:16 +0530 Subject: [PATCH 0434/1908] Updated typo in doc file (#64596) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- docs/contributors/code/release.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributors/code/release.md b/docs/contributors/code/release.md index f304ec9cd3a487..ec3af0d7bd4cb2 100644 --- a/docs/contributors/code/release.md +++ b/docs/contributors/code/release.md @@ -227,7 +227,7 @@ The final step is to write a release post on [make.wordpress.org/core](https://m > The plugin was published to the WordPress.org plugin directory but the workflow failed. -This has happened ocassionally, see [this one](https://github.com/WordPress/gutenberg/actions/runs/6955409957/job/18924124118) for example. +This has happened occasionally, see [this one](https://github.com/WordPress/gutenberg/actions/runs/6955409957/job/18924124118) for example. It's important to check that: From 633236b6d667608788bb033dbc917214c23a5f72 Mon Sep 17 00:00:00 2001 From: Shreya Agarwal <78657883+shreya0204@users.noreply.github.com> Date: Sat, 17 Aug 2024 15:52:46 +0530 Subject: [PATCH 0435/1908] fix: empty content sidebar panel (#64569) Co-authored-by: shreya0204 <shreya0204@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: hanneslsm <hanneslsm@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> --- .../editor/src/components/template-content-panel/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/template-content-panel/index.js b/packages/editor/src/components/template-content-panel/index.js index af9721dfdf2b32..41e170e76daef5 100644 --- a/packages/editor/src/components/template-content-panel/index.js +++ b/packages/editor/src/components/template-content-panel/index.js @@ -59,7 +59,10 @@ export default function TemplateContentPanel() { const { enableComplementaryArea } = useDispatch( interfaceStore ); - if ( renderingMode === 'post-only' && postType !== TEMPLATE_POST_TYPE ) { + if ( + ( renderingMode === 'post-only' && postType !== TEMPLATE_POST_TYPE ) || + clientIds.length === 0 + ) { return null; } From 699288326ed7c8320d481ed86cf4c4bfa192c9d8 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 19 Aug 2024 05:25:14 +0900 Subject: [PATCH 0436/1908] Components: Add 40px size prop to readmes (#64592) * Components: Add 40px size prop to readmes * Fixup Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../border-box-control/README.md | 7 +++++++ .../border-control/border-control/README.md | 7 +++++++ packages/components/src/button/README.md | 7 +++++++ .../components/src/combobox-control/README.md | 8 ++++++++ .../src/custom-select-control/README.md | 7 +++++++ .../components/src/dimension-control/README.md | 18 +++++++++++++----- .../src/focal-point-picker/README.md | 10 +++++++++- .../components/src/font-size-picker/README.md | 7 +++++++ .../components/src/form-file-upload/README.md | 8 ++++++++ .../components/src/form-token-field/README.md | 1 + .../components/src/input-control/README.md | 8 ++++++++ .../components/src/number-control/README.md | 8 ++++++++ .../components/src/query-controls/README.md | 7 +++++++ .../components/src/range-control/README.md | 7 +++++++ .../components/src/select-control/README.md | 8 ++++++++ packages/components/src/text-control/README.md | 8 ++++++++ .../toggle-group-control/README.md | 7 +++++++ packages/components/src/unit-control/README.md | 7 +++++++ 18 files changed, 134 insertions(+), 6 deletions(-) diff --git a/packages/components/src/border-box-control/border-box-control/README.md b/packages/components/src/border-box-control/border-box-control/README.md index 20352e03c8243d..5ec2263bf16741 100644 --- a/packages/components/src/border-box-control/border-box-control/README.md +++ b/packages/components/src/border-box-control/border-box-control/README.md @@ -169,3 +169,10 @@ const splitBorders = { ``` - Required: No + +### `__next40pxDefaultSize`: `boolean` + +Start opting into the larger default height that will become the default size in a future version. + +- Required: No +- Default: `false` diff --git a/packages/components/src/border-control/border-control/README.md b/packages/components/src/border-control/border-control/README.md index 51fb7172b7c553..74a212d00026bd 100644 --- a/packages/components/src/border-control/border-control/README.md +++ b/packages/components/src/border-control/border-control/README.md @@ -173,3 +173,10 @@ Flags whether this `BorderControl` should also render a `RangeControl` for additional control over a border's width. - Required: No + +### `__next40pxDefaultSize`: `boolean` + +Start opting into the larger default height that will become the default size in a future version. + +- Required: No +- Default: `false` diff --git a/packages/components/src/button/README.md b/packages/components/src/button/README.md index b3a83904bc9ba6..d458771494a338 100644 --- a/packages/components/src/button/README.md +++ b/packages/components/src/button/README.md @@ -292,6 +292,13 @@ Specifies the button's style. The accepted values are `'primary'` (the primary b - Required: No +#### `__next40pxDefaultSize`: `boolean` + +Start opting into the larger default height that will become the default size in a future version. + +- Required: No +- Default: `false` + ## Related components - To group buttons together, use the [ButtonGroup](/packages/components/src/button-group/README.md) component. diff --git a/packages/components/src/combobox-control/README.md b/packages/components/src/combobox-control/README.md index 9d00804e2f30e0..61611f82fee233 100644 --- a/packages/components/src/combobox-control/README.md +++ b/packages/components/src/combobox-control/README.md @@ -118,6 +118,14 @@ Custom renderer invoked for each option in the suggestion list. The render prop - Type: `( args: { item: object } ) => ReactNode` - Required: No +#### __next40pxDefaultSize + +Start opting into the larger default height that will become the default size in a future version. + +- Type: `Boolean` +- Required: No +- Default: `false` + #### __nextHasNoMarginBottom Start opting into the new margin-free styles that will become the default in a future version. diff --git a/packages/components/src/custom-select-control/README.md b/packages/components/src/custom-select-control/README.md index 6804f4cf6ecd3a..a764a0df133eab 100644 --- a/packages/components/src/custom-select-control/README.md +++ b/packages/components/src/custom-select-control/README.md @@ -142,6 +142,13 @@ A handler for `blur` events on the trigger button. - Required: No +#### `__next40pxDefaultSize`: `boolean` + +Start opting into the larger default height that will become the default size in a future version. + +- Required: No +- Default: `false` + ## Related components - Like this component, but implemented using a native `<select>` for when custom styling is not necessary, the `SelectControl` component. diff --git a/packages/components/src/dimension-control/README.md b/packages/components/src/dimension-control/README.md index 42f4a9678c09a6..3cd0191a046068 100644 --- a/packages/components/src/dimension-control/README.md +++ b/packages/components/src/dimension-control/README.md @@ -93,10 +93,18 @@ A callback which is triggered when a spacing size value changes (is selected/cli A string of classes to be added to the control component. -### __nextHasNoMarginBottom +### `__next40pxDefaultSize` -Start opting into the new margin-free styles that will become the default in a future version. +- **Type:** `Boolean` +- **Required:** No +- **Default:** `false` + +Start opting into the larger default height that will become the default size in a future version. + +### `__nextHasNoMarginBottom` -- Type: `Boolean` -- Required: No -- Default: `false` +- **Type:** `Boolean` +- **Required:** No +- **Default:** `false` + +Start opting into the new margin-free styles that will become the default in a future version. diff --git a/packages/components/src/focal-point-picker/README.md b/packages/components/src/focal-point-picker/README.md index f5db4885fdf7a4..baa6601d74dbcf 100644 --- a/packages/components/src/focal-point-picker/README.md +++ b/packages/components/src/focal-point-picker/README.md @@ -100,10 +100,18 @@ Callback which is called at the start of drag operations. Function which is called before internal updates to the value state. It receives the upcoming value and may return a modified one. -#### __nextHasNoMarginBottom +### `__next40pxDefaultSize` + +- Type: `Boolean` +- Required: No +- Default: `false` Start opting into the new margin-free styles that will become the default in a future version. +### `__nextHasNoMarginBottom` + - Type: `Boolean` - Required: No - Default: `false` + +Start opting into the new margin-free styles that will become the default in a future version. \ No newline at end of file diff --git a/packages/components/src/font-size-picker/README.md b/packages/components/src/font-size-picker/README.md index 790468acc6c1fa..5d7fe2b39a7373 100644 --- a/packages/components/src/font-size-picker/README.md +++ b/packages/components/src/font-size-picker/README.md @@ -113,3 +113,10 @@ If `true`, a slider will be displayed alongside the input field when a custom fo - Required: no - Default: `false` + +### `__next40pxDefaultSize`: `boolean` + +Start opting into the larger default height that will become the default size in a future version. + +- Required: No +- Default: `false` diff --git a/packages/components/src/form-file-upload/README.md b/packages/components/src/form-file-upload/README.md index f4dc4d1ef5a023..4dd8affc5f54a0 100644 --- a/packages/components/src/form-file-upload/README.md +++ b/packages/components/src/form-file-upload/README.md @@ -85,3 +85,11 @@ Optional callback function used to render the UI. If passed, the component does - Type: `Function` - Required: No + +### __next40pxDefaultSize + +Start opting into the larger default height that will become the default size in a future version. + +- Type: `Boolean` +- Required: No +- Default: `false` diff --git a/packages/components/src/form-token-field/README.md b/packages/components/src/form-token-field/README.md index 3da19ba534d312..70e9bd09a61a36 100644 --- a/packages/components/src/form-token-field/README.md +++ b/packages/components/src/form-token-field/README.md @@ -61,6 +61,7 @@ The `value` property is handled in a manner similar to controlled form component - `__experimentalShowHowTo` - If false, the text on how to use the select (ie: _Separate with commas or the Enter key._) will be hidden. - `__experimentalValidateInput` - If passed, all introduced values will be validated before being added as tokens. - `__experimentalAutoSelectFirstMatch` - If true, the select the first matching suggestion when the user presses the Enter key (or space when tokenizeOnSpace is true). +- `__next40pxDefaultSize` - Start opting into the larger default height that will become the default size in a future version. - `__nextHasNoMarginBottom` - Start opting into the new margin-free styles that will become the default in a future version, currently scheduled to be WordPress 7.0. (The prop can be safely removed once this happens.) - `tokenizeOnBlur` - If true, add any incompleteTokenValue as a new token when the field loses focus. diff --git a/packages/components/src/input-control/README.md b/packages/components/src/input-control/README.md index 7af244f823516d..58a3b4a3b1a094 100644 --- a/packages/components/src/input-control/README.md +++ b/packages/components/src/input-control/README.md @@ -107,3 +107,11 @@ The current value of the input. - Type: `String` - Required: No + +### __next40pxDefaultSize + +Start opting into the larger default height that will become the default size in a future version. + +- Type: `Boolean` +- Required: No +- Default: `false` diff --git a/packages/components/src/number-control/README.md b/packages/components/src/number-control/README.md index 3a54351cd29258..8421691296e90a 100644 --- a/packages/components/src/number-control/README.md +++ b/packages/components/src/number-control/README.md @@ -139,3 +139,11 @@ Amount by which the `value` is changed when incrementing/decrementing. It is als - Type: `Number | "any"` - Required: No - Default: `1` + +### __next40pxDefaultSize + +Start opting into the larger default height that will become the default size in a future version. + +- Type: `Boolean` +- Required: No +- Default: `false` \ No newline at end of file diff --git a/packages/components/src/query-controls/README.md b/packages/components/src/query-controls/README.md index 83cae88952d407..3eb6d507c9ccd6 100644 --- a/packages/components/src/query-controls/README.md +++ b/packages/components/src/query-controls/README.md @@ -240,3 +240,10 @@ The selected category for the `categoriesList` prop. - Required: No - Platform: Web + +#### `__next40pxDefaultSize`: `boolean` + +Start opting into the larger default height that will become the default size in a future version. + +- Required: No +- Default: `false` \ No newline at end of file diff --git a/packages/components/src/range-control/README.md b/packages/components/src/range-control/README.md index 3da335b9ecf6e8..cfa8c76740e74f 100644 --- a/packages/components/src/range-control/README.md +++ b/packages/components/src/range-control/README.md @@ -362,6 +362,13 @@ Determines if the `input` number field will render next to the RangeControl. Thi - Required: No - Platform: Web +### `__next40pxDefaultSize`: `boolean` + +Start opting into the larger default height that will become the default size in a future version. + +- Required: No +- Default: `false` + ### `__nextHasNoMarginBottom`: `boolean` Start opting into the new margin-free styles that will become the default in a future version. diff --git a/packages/components/src/select-control/README.md b/packages/components/src/select-control/README.md index 464ee180b38639..6c3ecda886a188 100644 --- a/packages/components/src/select-control/README.md +++ b/packages/components/src/select-control/README.md @@ -229,6 +229,14 @@ The style variant of the control. - Required: No - Default: `'default'` +### __next40pxDefaultSize + +Start opting into the larger default height that will become the default size in a future version. + +- Type: `Boolean` +- Required: No +- Default: `false` + ### __nextHasNoMarginBottom Start opting into the new margin-free styles that will become the default in a future version. diff --git a/packages/components/src/text-control/README.md b/packages/components/src/text-control/README.md index 4e2bfccb786d22..0b6e2d4ebc684e 100644 --- a/packages/components/src/text-control/README.md +++ b/packages/components/src/text-control/README.md @@ -127,6 +127,14 @@ A function that receives the value of the input. - Type: `function` - Required: Yes +#### __next40pxDefaultSize + +Start opting into the larger default height that will become the default size in a future version. + +- Type: `Boolean` +- Required: No +- Default: `false` + ## Related components - To offer users more constrained options for input, use SelectControl, RadioControl, CheckboxControl, or RangeControl. diff --git a/packages/components/src/toggle-group-control/toggle-group-control/README.md b/packages/components/src/toggle-group-control/toggle-group-control/README.md index 6db7ec20544185..ca5c5d14eb6b5a 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/README.md +++ b/packages/components/src/toggle-group-control/toggle-group-control/README.md @@ -88,6 +88,13 @@ The value of the `ToggleGroupControl`. - Required: No +### `__next40pxDefaultSize`: `boolean` + +Start opting into the larger default height that will become the default size in a future version. + +- Required: No +- Default: `false` + ### `__nextHasNoMarginBottom`: `boolean` Start opting into the new margin-free styles that will become the default in a future version. diff --git a/packages/components/src/unit-control/README.md b/packages/components/src/unit-control/README.md index b3c0496f86b800..dd54de80357d8e 100644 --- a/packages/components/src/unit-control/README.md +++ b/packages/components/src/unit-control/README.md @@ -147,3 +147,10 @@ Example: ``` - Required: No + +### `__next40pxDefaultSize`: `boolean` + +Start opting into the larger default height that will become the default size in a future version. + +- Required: No +- Default: `false` From e266e3f59cd60a8a531e9dcedebe55072a908b0e Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 19 Aug 2024 05:27:45 +0900 Subject: [PATCH 0437/1908] TextDecorationControl, TextTransformControl: Remove size prop in Storybook (#64583) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../components/text-decoration-control/stories/index.story.js | 4 ---- .../components/text-transform-control/stories/index.story.js | 4 ---- 2 files changed, 8 deletions(-) diff --git a/packages/block-editor/src/components/text-decoration-control/stories/index.story.js b/packages/block-editor/src/components/text-decoration-control/stories/index.story.js index cb50e4cd6c6f73..2212b484185cde 100644 --- a/packages/block-editor/src/components/text-decoration-control/stories/index.story.js +++ b/packages/block-editor/src/components/text-decoration-control/stories/index.story.js @@ -13,10 +13,6 @@ export default { component: TextDecorationControl, argTypes: { onChange: { action: 'onChange' }, - size: { - options: [ 'default', '__unstable-large' ], - control: { type: 'radio' }, - }, }, }; diff --git a/packages/block-editor/src/components/text-transform-control/stories/index.story.js b/packages/block-editor/src/components/text-transform-control/stories/index.story.js index 3219d714257e81..96dd8ed479dc4e 100644 --- a/packages/block-editor/src/components/text-transform-control/stories/index.story.js +++ b/packages/block-editor/src/components/text-transform-control/stories/index.story.js @@ -13,10 +13,6 @@ export default { component: TextTransformControl, argTypes: { onChange: { action: 'onChange' }, - size: { - options: [ 'default', '__unstable-large' ], - control: { type: 'radio' }, - }, }, }; From fdbc84cef37ba0d0a89c2c41e460861204ad357d Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 19 Aug 2024 11:35:43 +0900 Subject: [PATCH 0438/1908] FormFileUpload: Add lint rule for 40px size prop usage (#64585) * FormFileUpload: Document `__next40pxDefaultSize` prop * Switch to explicit Button in MediaPlaceholder * Add lint rule Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .eslintrc.js | 7 +++++++ .../src/components/media-placeholder/index.js | 19 ++++++++++++------- .../components/src/form-file-upload/types.ts | 6 ++++++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 5a939aeb9173b7..3d484a6b3ed9d0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -327,6 +327,13 @@ module.exports = { componentName + ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', } ) ), + { + // Falsy `__next40pxDefaultSize` without a `render` prop. + selector: + 'JSXOpeningElement[name.name="FormFileUpload"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"][value.expression.value!=false])):not(:has(JSXAttribute[name.name="render"]))', + message: + 'FormFileUpload should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', + }, // Temporary rules until all existing components have the `__next40pxDefaultSize` prop. ...[ 'SelectControl', 'TextControl' ].map( ( componentName ) => ( { diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index 347cd3e42d130f..c54ee9c0caf617 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -491,17 +491,22 @@ export function MediaPlaceholder( { <> { renderDropZone() } <FormFileUpload - variant="primary" - className={ clsx( - 'block-editor-media-placeholder__button', - 'block-editor-media-placeholder__upload-button' + render={ ( { openFileDialog } ) => ( + <Button + onClick={ openFileDialog } + variant="primary" + className={ clsx( + 'block-editor-media-placeholder__button', + 'block-editor-media-placeholder__upload-button' + ) } + > + { __( 'Upload' ) } + </Button> ) } onChange={ onUpload } accept={ accept } multiple={ !! multiple } - > - { __( 'Upload' ) } - </FormFileUpload> + /> { uploadMediaLibraryButton } { renderUrlSelectionUI() } { renderFeaturedImageToggle() } diff --git a/packages/components/src/form-file-upload/types.ts b/packages/components/src/form-file-upload/types.ts index 5b9054fa869eea..728ed959aba76e 100644 --- a/packages/components/src/form-file-upload/types.ts +++ b/packages/components/src/form-file-upload/types.ts @@ -10,6 +10,12 @@ import type Icon from '../icon'; // TODO: Replace `children` and `icon` types with props from Button once Button is typed. export type FormFileUploadProps = { + /** + * Start opting into the larger default height that will become the default size in a future version. + * + * @default false + */ + __next40pxDefaultSize?: boolean; /** * A string passed to `input` element that tells the browser which file types can be * upload to the upload by the user use. e.g: `image/*,video/*`. From 515d0d9bb75ec1e5a21deb1bbf3e4795d590e85f Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 19 Aug 2024 11:36:58 +0900 Subject: [PATCH 0439/1908] FormTokenField: Add lint rule for 40px size prop usage (#64590) * Fix in Query Loop block * Add lint rule Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .eslintrc.js | 1 + .../src/query/edit/inspector-controls/parent-control.js | 1 + 2 files changed, 2 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index 3d484a6b3ed9d0..5408ad5da884e2 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -317,6 +317,7 @@ module.exports = { 'CustomSelectControl', 'DimensionControl', 'FontSizePicker', + 'FormTokenField', 'NumberControl', 'RangeControl', 'ToggleGroupControl', diff --git a/packages/block-library/src/query/edit/inspector-controls/parent-control.js b/packages/block-library/src/query/edit/inspector-controls/parent-control.js index 33cc1f83eda591..5fb9ffaad20e88 100644 --- a/packages/block-library/src/query/edit/inspector-controls/parent-control.js +++ b/packages/block-library/src/query/edit/inspector-controls/parent-control.js @@ -132,6 +132,7 @@ function ParentControl( { parents, postType, onChange } ) { }; return ( <FormTokenField + __next40pxDefaultSize label={ __( 'Parents' ) } value={ value } onInputChange={ debouncedSearch } From 2ad366bd072e722b407eed1c9c8364fc0d1236b2 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 19 Aug 2024 12:09:49 +0900 Subject: [PATCH 0440/1908] TextControl: Fix remaining 40px size violations (#64594) * Fix in DateFormatPicker * Fix in ImageURLInputUI * Fix in Button block * Fix in Form block InputFieldBlock * Fix in Form block * Fix in Image block content only mode * Fix in Navigation block * Fix in Post Comment block (deprecated) * Fix in Featured Image block * Fix in Categories block * Fix in Title block * Fix in Social Icons block * Fix in Template Part block * Fix in Video block track editor * Fix in Dataviews Add new view modal * Fix in Dataviews Rename view modal * Fix in PostPublishPanel * Fix in PostSlug component (unused in app) * Fix in HierarchicalTermSelector * Fix in ReusableBlockConvertButton (unused in app) * Move to stricter lint rule * Update snapshot Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .eslintrc.js | 17 ++++++++--------- .../src/components/date-format-picker/index.js | 3 +-- .../url-popover/image-url-input-ui.js | 6 ++---- packages/block-library/src/button/edit.js | 3 +-- packages/block-library/src/form-input/edit.js | 3 +-- packages/block-library/src/form/edit.js | 6 ++---- packages/block-library/src/image/image.js | 3 +-- .../edit/navigation-menu-name-control.js | 3 +-- packages/block-library/src/post-comment/edit.js | 4 ++-- .../src/post-featured-image/edit.js | 3 +-- packages/block-library/src/post-terms/edit.js | 3 +-- packages/block-library/src/post-title/edit.js | 3 +-- packages/block-library/src/social-link/edit.js | 6 ++---- .../src/template-part/edit/advanced-controls.js | 6 ++---- .../block-library/src/video/tracks-editor.js | 9 +++------ .../sidebar-dataviews/add-new-view.js | 3 +-- .../sidebar-dataviews/custom-dataviews-list.js | 3 +-- .../post-publish-panel/postpublish.js | 12 ++++++++---- .../test/__snapshots__/index.js.snap | 16 ++++++++-------- .../editor/src/components/post-slug/index.js | 3 +-- .../hierarchical-term-selector.js | 3 +-- .../reusable-block-convert-button.js | 3 +-- 22 files changed, 50 insertions(+), 71 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 5408ad5da884e2..0637f7d84354eb 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -320,6 +320,7 @@ module.exports = { 'FormTokenField', 'NumberControl', 'RangeControl', + 'TextControl', 'ToggleGroupControl', ].map( ( componentName ) => ( { // Falsy `__next40pxDefaultSize` without a non-default `size` prop. @@ -336,15 +337,13 @@ module.exports = { 'FormFileUpload should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', }, // Temporary rules until all existing components have the `__next40pxDefaultSize` prop. - ...[ 'SelectControl', 'TextControl' ].map( - ( componentName ) => ( { - // Not strict. Allows pre-existing __next40pxDefaultSize={ false } usage until they are all manually updated. - selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"])):not(:has(JSXAttribute[name.name="size"]))`, - message: - componentName + - ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', - } ) - ), + ...[ 'SelectControl' ].map( ( componentName ) => ( { + // Not strict. Allows pre-existing __next40pxDefaultSize={ false } usage until they are all manually updated. + selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"])):not(:has(JSXAttribute[name.name="size"]))`, + message: + componentName + + ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', + } ) ), ], }, }, diff --git a/packages/block-editor/src/components/date-format-picker/index.js b/packages/block-editor/src/components/date-format-picker/index.js index edefd6249f1aae..eb269e03ca5abc 100644 --- a/packages/block-editor/src/components/date-format-picker/index.js +++ b/packages/block-editor/src/components/date-format-picker/index.js @@ -150,8 +150,7 @@ function NonDefaultControls( { format, onChange } ) { /> { isCustom && ( <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Custom format' ) } hideLabelFromVision diff --git a/packages/block-editor/src/components/url-popover/image-url-input-ui.js b/packages/block-editor/src/components/url-popover/image-url-input-ui.js index c19021c52356f5..c68cf5e58b9530 100644 --- a/packages/block-editor/src/components/url-popover/image-url-input-ui.js +++ b/packages/block-editor/src/components/url-popover/image-url-input-ui.js @@ -227,16 +227,14 @@ const ImageURLInputUI = ( { checked={ linkTarget === '_blank' } /> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Link rel' ) } value={ rel ?? '' } onChange={ onSetLinkRel } /> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Link CSS class' ) } value={ linkClass || '' } diff --git a/packages/block-library/src/button/edit.js b/packages/block-library/src/button/edit.js index d9f8acc91e4c8e..28d42ef16ca1e4 100644 --- a/packages/block-library/src/button/edit.js +++ b/packages/block-library/src/button/edit.js @@ -380,8 +380,7 @@ function ButtonEdit( props ) { <InspectorControls group="advanced"> { isLinkTag && ( <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Link rel' ) } value={ rel || '' } diff --git a/packages/block-library/src/form-input/edit.js b/packages/block-library/src/form-input/edit.js index fb84b0465b8402..6939443011ee5b 100644 --- a/packages/block-library/src/form-input/edit.js +++ b/packages/block-library/src/form-input/edit.js @@ -63,8 +63,7 @@ function InputFieldBlock( { attributes, setAttributes, className } ) { ) } <InspectorControls group="advanced"> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom autoComplete="off" label={ __( 'Name' ) } diff --git a/packages/block-library/src/form/edit.js b/packages/block-library/src/form/edit.js index 6a30dd0b61bf9d..a7260afabedf39 100644 --- a/packages/block-library/src/form/edit.js +++ b/packages/block-library/src/form/edit.js @@ -130,8 +130,7 @@ const Edit = ( { attributes, setAttributes, clientId } ) => { { submissionMethod !== 'email' && ( <InspectorControls group="advanced"> <SelectControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Method' ) } options={ [ @@ -147,8 +146,7 @@ const Edit = ( { attributes, setAttributes, clientId } ) => { ) } /> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom autoComplete="off" label={ __( 'Form action' ) } diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 0623d576e75aec..c4b54259028d91 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -690,8 +690,7 @@ export default function Image( { ) } renderContent={ () => ( <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="wp-block-image__toolbar_content_textarea" __nextHasNoMarginBottom label={ __( 'Title attribute' ) } diff --git a/packages/block-library/src/navigation/edit/navigation-menu-name-control.js b/packages/block-library/src/navigation/edit/navigation-menu-name-control.js index 97a97d7763fc72..db895b0b644aac 100644 --- a/packages/block-library/src/navigation/edit/navigation-menu-name-control.js +++ b/packages/block-library/src/navigation/edit/navigation-menu-name-control.js @@ -14,8 +14,7 @@ export default function NavigationMenuNameControl() { return ( <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Menu name' ) } value={ title } diff --git a/packages/block-library/src/post-comment/edit.js b/packages/block-library/src/post-comment/edit.js index f6abb5ff60c68e..a5193e427fa981 100644 --- a/packages/block-library/src/post-comment/edit.js +++ b/packages/block-library/src/post-comment/edit.js @@ -34,8 +34,7 @@ export default function Edit( { attributes: { commentId }, setAttributes } ) { ) } > <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom value={ commentId } onChange={ ( val ) => @@ -44,6 +43,7 @@ export default function Edit( { attributes: { commentId }, setAttributes } ) { /> <Button + __next40pxDefaultSize variant="primary" onClick={ () => { setAttributes( { commentId: commentIdInput } ); diff --git a/packages/block-library/src/post-featured-image/edit.js b/packages/block-library/src/post-featured-image/edit.js index 675580c71c1d7b..b2fc63ba9cbdc4 100644 --- a/packages/block-library/src/post-featured-image/edit.js +++ b/packages/block-library/src/post-featured-image/edit.js @@ -230,8 +230,7 @@ export default function PostFeaturedImageEdit( { checked={ linkTarget === '_blank' } /> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Link rel' ) } value={ rel } diff --git a/packages/block-library/src/post-terms/edit.js b/packages/block-library/src/post-terms/edit.js index 0403a1d1406bd3..13d5b61ad13d6b 100644 --- a/packages/block-library/src/post-terms/edit.js +++ b/packages/block-library/src/post-terms/edit.js @@ -83,8 +83,7 @@ export default function PostTermsEdit( { </BlockControls> <InspectorControls group="advanced"> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom autoComplete="off" label={ __( 'Separator' ) } diff --git a/packages/block-library/src/post-title/edit.js b/packages/block-library/src/post-title/edit.js index abd52febd1882b..fdfb8e7c2c6cd2 100644 --- a/packages/block-library/src/post-title/edit.js +++ b/packages/block-library/src/post-title/edit.js @@ -162,8 +162,7 @@ export default function PostTitleEdit( { checked={ linkTarget === '_blank' } /> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Link rel' ) } value={ rel } diff --git a/packages/block-library/src/social-link/edit.js b/packages/block-library/src/social-link/edit.js index 39e3803982f48b..5ba57a8a29edf9 100644 --- a/packages/block-library/src/social-link/edit.js +++ b/packages/block-library/src/social-link/edit.js @@ -139,8 +139,7 @@ const SocialLinkEdit = ( { <PanelBody title={ __( 'Settings' ) }> <PanelRow> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Text' ) } help={ __( @@ -157,8 +156,7 @@ const SocialLinkEdit = ( { </InspectorControls> <InspectorControls group="advanced"> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Link rel' ) } value={ rel || '' } diff --git a/packages/block-library/src/template-part/edit/advanced-controls.js b/packages/block-library/src/template-part/edit/advanced-controls.js index bf834065d1a54b..0a2b8bebbf4fca 100644 --- a/packages/block-library/src/template-part/edit/advanced-controls.js +++ b/packages/block-library/src/template-part/edit/advanced-controls.js @@ -73,8 +73,7 @@ export function TemplatePartAdvancedControls( { { isEntityAvailable && ( <> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Title' ) } value={ title } @@ -85,8 +84,7 @@ export function TemplatePartAdvancedControls( { /> <SelectControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Area' ) } labelPosition="top" diff --git a/packages/block-library/src/video/tracks-editor.js b/packages/block-library/src/video/tracks-editor.js index 521d54e9231d1b..8928c26840e3d9 100644 --- a/packages/block-library/src/video/tracks-editor.js +++ b/packages/block-library/src/video/tracks-editor.js @@ -99,8 +99,7 @@ function SingleTrackEditor( { track, onChange, onClose, onRemove } ) { </span> <Grid columns={ 2 } gap={ 4 }> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom /* eslint-disable jsx-a11y/no-autofocus */ autoFocus @@ -116,8 +115,7 @@ function SingleTrackEditor( { track, onChange, onClose, onRemove } ) { help={ __( 'Title of track' ) } /> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom onChange={ ( newSrcLang ) => onChange( { @@ -132,8 +130,7 @@ function SingleTrackEditor( { track, onChange, onClose, onRemove } ) { </Grid> <VStack spacing="8"> <SelectControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom className="block-library-video-tracks-editor__single-track-editor-kind-select" options={ KIND_OPTIONS } diff --git a/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js b/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js index 69cca49fd84563..5f366a8f93e65f 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js +++ b/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js @@ -78,8 +78,7 @@ function AddNewItemModalContent( { type, setIsAdding } ) { > <VStack spacing="5"> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Name' ) } value={ title } diff --git a/packages/edit-site/src/components/sidebar-dataviews/custom-dataviews-list.js b/packages/edit-site/src/components/sidebar-dataviews/custom-dataviews-list.js index cab5b0d31fa2ed..847029e8d6dcfe 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/custom-dataviews-list.js +++ b/packages/edit-site/src/components/sidebar-dataviews/custom-dataviews-list.js @@ -51,8 +51,7 @@ function RenameItemModalContent( { dataviewId, currentTitle, setIsRenaming } ) { > <VStack spacing="5"> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Name' ) } value={ title } diff --git a/packages/editor/src/components/post-publish-panel/postpublish.js b/packages/editor/src/components/post-publish-panel/postpublish.js index fdc1194527f5f7..29ee1871057ea1 100644 --- a/packages/editor/src/components/post-publish-panel/postpublish.js +++ b/packages/editor/src/components/post-publish-panel/postpublish.js @@ -44,7 +44,7 @@ const getFuturePostUrl = ( post ) => { function CopyButton( { text, onCopy, children } ) { const ref = useCopyToClipboard( text, onCopy ); return ( - <Button variant="secondary" ref={ ref }> + <Button __next40pxDefaultSize variant="secondary" ref={ ref }> { children } </Button> ); @@ -122,8 +122,7 @@ class PostPublishPanelPostpublish extends Component { </p> <div className="post-publish-panel__postpublish-post-address-container"> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom className="post-publish-panel__postpublish-post-address" readOnly @@ -147,12 +146,17 @@ class PostPublishPanelPostpublish extends Component { <div className="post-publish-panel__postpublish-buttons"> { ! isScheduled && ( - <Button variant="primary" href={ link }> + <Button + variant="primary" + href={ link } + __next40pxDefaultSize + > { viewPostLabel } </Button> ) } <Button variant={ isScheduled ? 'primary' : 'secondary' } + __next40pxDefaultSize href={ addLink } > { addNewPostLabel } diff --git a/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap b/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap index 42fc0f7fe0f245..9331376d7f9c35 100644 --- a/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap +++ b/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap @@ -120,7 +120,7 @@ exports[`PostPublishPanel should render the post-publish panel if the post is pu post address </label> <input - class="components-text-control__input" + class="components-text-control__input is-next-40px-default-size" id="inspector-text-control-0" readonly="" type="text" @@ -132,7 +132,7 @@ exports[`PostPublishPanel should render the post-publish panel if the post is pu class="post-publish-panel__postpublish-post-address__copy-button-wrap" > <button - class="components-button is-secondary" + class="components-button is-next-40px-default-size is-secondary" type="button" > Copy @@ -143,11 +143,11 @@ exports[`PostPublishPanel should render the post-publish panel if the post is pu class="post-publish-panel__postpublish-buttons" > <a - class="components-button is-primary" + class="components-button is-next-40px-default-size is-primary" href="https://wordpress.local/sample-page/" /> <a - class="components-button is-secondary" + class="components-button is-next-40px-default-size is-secondary" href="post-new.php?" /> </div> @@ -312,7 +312,7 @@ exports[`PostPublishPanel should render the post-publish panel if the post is sc post address </label> <input - class="components-text-control__input" + class="components-text-control__input is-next-40px-default-size" id="inspector-text-control-1" readonly="" type="text" @@ -324,7 +324,7 @@ exports[`PostPublishPanel should render the post-publish panel if the post is sc class="post-publish-panel__postpublish-post-address__copy-button-wrap" > <button - class="components-button is-secondary" + class="components-button is-next-40px-default-size is-secondary" type="button" > Copy @@ -335,11 +335,11 @@ exports[`PostPublishPanel should render the post-publish panel if the post is sc class="post-publish-panel__postpublish-buttons" > <a - class="components-button is-primary" + class="components-button is-next-40px-default-size is-primary" href="https://wordpress.local/sample-page/" /> <a - class="components-button is-secondary" + class="components-button is-next-40px-default-size is-secondary" href="post-new.php?" /> </div> diff --git a/packages/editor/src/components/post-slug/index.js b/packages/editor/src/components/post-slug/index.js index adabac2f18b0bd..1a4f8e93d7565c 100644 --- a/packages/editor/src/components/post-slug/index.js +++ b/packages/editor/src/components/post-slug/index.js @@ -24,8 +24,7 @@ function PostSlugControl() { return ( <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Slug' ) } autoComplete="off" diff --git a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js index c711268a91e631..14bcaef7a0399a 100644 --- a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js +++ b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js @@ -407,8 +407,7 @@ export function HierarchicalTermSelector( { slug } ) { <Flex direction="column" gap="4"> { showFilter && ( <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ filterLabel } value={ filterValue } diff --git a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js index b6f30e24a2fdb3..81536b70a7ad32 100644 --- a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js +++ b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js @@ -169,8 +169,7 @@ export default function ReusableBlockConvertButton( { > <VStack spacing="5"> <TextControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Name' ) } value={ title } From cb37db7796b71463b9a8fece6409e446157c57d2 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 19 Aug 2024 12:33:09 +0900 Subject: [PATCH 0441/1908] InputControl: Add lint rule for 40px size prop usage (#64589) * Fix in ShadowsEditPanel * Add lint rule Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .eslintrc.js | 1 + .../edit-site/src/components/global-styles/shadows-edit-panel.js | 1 + 2 files changed, 2 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index 0637f7d84354eb..8f9b2d3337e18e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -318,6 +318,7 @@ module.exports = { 'DimensionControl', 'FontSizePicker', 'FormTokenField', + 'InputControl', 'NumberControl', 'RangeControl', 'TextControl', diff --git a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js index acca656428d187..2445863549593e 100644 --- a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js +++ b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js @@ -223,6 +223,7 @@ export default function ShadowsEditPanel() { } } > <InputControl + __next40pxDefaultSize autoComplete="off" label={ __( 'Name' ) } placeholder={ __( 'Shadow name' ) } From bca4aeb1df77949d1254bf99674053cead5a34ec Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 19 Aug 2024 09:39:32 +0200 Subject: [PATCH 0442/1908] RangeControl: disable reset button consistently (#64579) * Add some temporary test TODOs * Temporarily comment out initialPosition's default value in Storybook * Tweak reset button disable logic, extract computeResetValue function * Update test comments * Clean up code * Update reset-related tests * Restore Storybook default args * CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/range-control/index.tsx | 47 ++++++++++++--- .../src/range-control/test/index.tsx | 60 +++++++++++++++---- 3 files changed, 86 insertions(+), 22 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index f1b6ba3341de60..da44a5837bb816 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -59,6 +59,7 @@ ### Bug Fixes +- `RangeControl`: disable reset button when the current value is equal to the reset value ([#64579](https://github.com/WordPress/gutenberg/pull/64579)). - `RangeControl`: tweak mark and label absolute positioning ([#64487](https://github.com/WordPress/gutenberg/pull/64487)). ### Internal diff --git a/packages/components/src/range-control/index.tsx b/packages/components/src/range-control/index.tsx index 20d9712df9c251..c9fbdc0055c855 100644 --- a/packages/components/src/range-control/index.tsx +++ b/packages/components/src/range-control/index.tsx @@ -41,6 +41,25 @@ import { space } from '../utils/space'; const noop = () => {}; +/** + * Computes the value that `RangeControl` should reset to when pressing + * the reset button. + */ +function computeResetValue( { + resetFallbackValue, + initialPosition, +}: Pick< RangeControlProps, 'resetFallbackValue' | 'initialPosition' > ) { + if ( resetFallbackValue !== undefined ) { + return ! Number.isNaN( resetFallbackValue ) ? resetFallbackValue : null; + } + + if ( initialPosition !== undefined ) { + return ! Number.isNaN( initialPosition ) ? initialPosition : null; + } + + return null; +} + function UnforwardedRangeControl( props: WordPressComponentProps< RangeControlProps, 'input', false >, forwardedRef: ForwardedRef< HTMLInputElement > @@ -166,13 +185,12 @@ function UnforwardedRangeControl( }; const handleOnReset = () => { - let resetValue: number | null = parseFloat( `${ resetFallbackValue }` ); - let onChangeResetValue: number | undefined = resetValue; - - if ( isNaN( resetValue ) ) { - resetValue = null; - onChangeResetValue = undefined; - } + // Reset to `resetFallbackValue` if defined, otherwise set internal value + // to `null` — which, if propagated to the `value` prop, will cause + // the value to be reset to the `initialPosition` prop if defined. + const resetValue = Number.isNaN( resetFallbackValue ) + ? null + : resetFallbackValue ?? null; setValue( resetValue ); @@ -189,7 +207,7 @@ function UnforwardedRangeControl( * preserve the undefined callback argument, except when a * resetFallbackValue is defined. */ - onChange( onChangeResetValue ); + onChange( resetValue ?? undefined ); }; const handleShowTooltip = () => setShowTooltip( true ); @@ -210,6 +228,7 @@ function UnforwardedRangeControl( const offsetStyle = { [ isRTL() ? 'right' : 'left' ]: fillValueOffset, }; + return ( <BaseControl __nextHasNoMarginBottom={ __nextHasNoMarginBottom } @@ -329,7 +348,17 @@ function UnforwardedRangeControl( className="components-range-control__reset" // If the RangeControl itself is disabled, the reset button shouldn't be in the tab sequence. accessibleWhenDisabled={ ! disabled } - disabled={ disabled || value === undefined } + // The reset button should be disabled if RangeControl itself is disabled, + // or if the current `value` is equal to the value that would be currently + // assigned when clicking the button. + disabled={ + disabled || + value === + computeResetValue( { + resetFallbackValue, + initialPosition, + } ) + } variant="secondary" size="small" onClick={ handleOnReset } diff --git a/packages/components/src/range-control/test/index.tsx b/packages/components/src/range-control/test/index.tsx index a4c5d8c6f2bc7f..3ce741867d0dbc 100644 --- a/packages/components/src/range-control/test/index.tsx +++ b/packages/components/src/range-control/test/index.tsx @@ -298,14 +298,37 @@ describe( 'RangeControl', () => { } ); describe( 'reset', () => { - it( 'should reset to a custom fallback value, defined by a parent component', () => { + it( 'should clear the input value when clicking the reset button', () => { + const spy = jest.fn(); + render( <RangeControl allowReset onChange={ spy } /> ); + + const resetButton = getResetButton(); + const rangeInput = getRangeInput(); + const numberInput = getNumberInput(); + + fireChangeEvent( numberInput, '14' ); + + expect( rangeInput.value ).toBe( '14' ); + expect( numberInput.value ).toBe( '14' ); + expect( spy ).toHaveBeenCalledWith( 14 ); + + fireEvent.click( resetButton ); + + // range input resets to min + (max-min)/2 + expect( rangeInput.value ).toBe( '50' ); + expect( numberInput.value ).toBe( '' ); + expect( spy ).toHaveBeenCalledWith( undefined ); + + expect( resetButton ).toHaveAttribute( 'aria-disabled', 'true' ); + } ); + + it( 'should reset to the `initialPosition` value when clicking the reset button', () => { const spy = jest.fn(); render( <RangeControl - initialPosition={ 10 } allowReset + initialPosition={ 23 } onChange={ spy } - resetFallbackValue={ 33 } /> ); @@ -313,21 +336,29 @@ describe( 'RangeControl', () => { const rangeInput = getRangeInput(); const numberInput = getNumberInput(); + fireChangeEvent( numberInput, '14' ); + + expect( rangeInput.value ).toBe( '14' ); + expect( numberInput.value ).toBe( '14' ); + expect( spy ).toHaveBeenCalledWith( 14 ); + fireEvent.click( resetButton ); - expect( rangeInput.value ).toBe( '33' ); - expect( numberInput.value ).toBe( '33' ); - expect( spy ).toHaveBeenCalledWith( 33 ); + expect( rangeInput.value ).toBe( '23' ); + expect( numberInput.value ).toBe( '23' ); + expect( spy ).toHaveBeenCalledWith( undefined ); + + expect( resetButton ).toHaveAttribute( 'aria-disabled', 'true' ); } ); - it( 'should reset to a 50% of min/max value, of no initialPosition or value is defined', () => { + it( 'should reset to the `resetFallbackValue` value when clicking the reset button', () => { + const spy = jest.fn(); render( <RangeControl - initialPosition={ undefined } - min={ 0 } - max={ 100 } + initialPosition={ 10 } allowReset - resetFallbackValue={ undefined } + onChange={ spy } + resetFallbackValue={ 33 } /> ); @@ -337,8 +368,11 @@ describe( 'RangeControl', () => { fireEvent.click( resetButton ); - expect( rangeInput.value ).toBe( '50' ); - expect( numberInput.value ).toBe( '' ); + expect( rangeInput.value ).toBe( '33' ); + expect( numberInput.value ).toBe( '33' ); + expect( spy ).toHaveBeenCalledWith( 33 ); + + expect( resetButton ).toHaveAttribute( 'aria-disabled', 'true' ); } ); } ); } ); From c1517edb5ee2f42cf6898928def56cc837960c56 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Mon, 19 Aug 2024 09:44:06 +0200 Subject: [PATCH 0443/1908] Try: Overlay caption w. text-shadow. (#63471) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: beafialho <beafialho@git.wordpress.org> Co-authored-by: paaljoachim <paaljoachim@git.wordpress.org> --- packages/block-library/src/gallery/style.scss | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/packages/block-library/src/gallery/style.scss b/packages/block-library/src/gallery/style.scss index afbc3088049858..1c4d5549339e1f 100644 --- a/packages/block-library/src/gallery/style.scss +++ b/packages/block-library/src/gallery/style.scss @@ -43,22 +43,44 @@ figure.wp-block-gallery.has-nested-images { width: auto; } + // Position caption and scrim at the bottom. + &:has(figcaption)::before, figcaption { - background: linear-gradient(0deg, rgba($color: $black, $alpha: 0.7) 0, rgba($color: $black, $alpha: 0.3) 70%, transparent); + position: absolute; bottom: 0; + right: 0; + left: 0; + max-height: 100%; + } + + // Create a background blur layer. + &:has(figcaption)::before { + content: ""; + height: 100%; + max-height: 40%; + + // Blur the background under the gradient scrim. + backdrop-filter: blur(3px); + + // Crop the caption so the blur is only on the edge. + mask-image: linear-gradient(0deg, $black 20%, transparent 100%); + } + + // Place the caption at the bottom. + figcaption { color: $white; + text-shadow: 0 0 1.5px $black; font-size: $default-font-size; - left: 0; - margin-bottom: 0; - max-height: 60%; + margin: 0; overflow: auto; - padding: 0 8px 8px; - position: absolute; + padding: 1em; text-align: center; - width: 100%; box-sizing: border-box; @include custom-scrollbars-on-hover(transparent, rgba($white, 0.8)); + // Dark gradient scrim. + background: linear-gradient(0deg, rgba($color: $black, $alpha: 0.4) 0%, transparent 100%); + img { display: inline; } @@ -85,6 +107,10 @@ figure.wp-block-gallery.has-nested-images { margin: 0; padding: 10px 10px 9px; position: relative; + text-shadow: none; + } + &::before { + content: none; } } } From 2862f2d1f169bea73e0550ff800d4ea121945a60 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Mon, 19 Aug 2024 09:42:37 +0100 Subject: [PATCH 0444/1908] Disallow dropping outside section root in Zoom Out mode (#64500) * Conditionalise Zoom Out dragOver to account for section root * Fix comment typo Co-authored-by: Andrew Serong <14988353+andrewserong@users.noreply.github.com> * Refactor to only call functions inside throttled callback --------- Co-authored-by: Andrew Serong <14988353+andrewserong@users.noreply.github.com> --- .../components/use-block-drop-zone/index.js | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 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 415ed5070d28da..8115fe8f72a647 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 @@ -313,6 +313,8 @@ export default function useBlockDropZone( { getAllowedBlocks, isDragging, isGroupable, + getSettings, + isZoomOutMode, } = unlock( useSelect( blockEditorStore ) ); const { showInsertionPoint, @@ -343,6 +345,7 @@ export default function useBlockDropZone( { const targetBlockName = getBlockNamesByClientId( [ targetRootClientId, ] )[ 0 ]; + const draggedBlockNames = getBlockNamesByClientId( getDraggedBlockClientIds() ); @@ -352,10 +355,23 @@ export default function useBlockDropZone( { draggedBlockNames, targetBlockName ); + if ( ! isBlockDroppingAllowed ) { return; } + const { sectionRootClientId } = unlock( getSettings() ); + + // In Zoom Out mode, if the target is not the section root provided by settings then + // do not allow dropping as the drop target is not within the root (that which is + // treated as "the content" by Zoom Out Mode). + if ( + isZoomOutMode() && + sectionRootClientId !== targetRootClientId + ) { + return; + } + const blocks = getBlocks( targetRootClientId ); // The block list is empty, don't show the insertion point but still allow dropping. @@ -470,6 +486,7 @@ export default function useBlockDropZone( { } ); }, [ + isDragging, getAllowedBlocks, targetRootClientId, getBlockNamesByClientId, @@ -481,13 +498,14 @@ export default function useBlockDropZone( { parentBlockClientId, getBlockIndex, registry, - showInsertionPoint, - isDragging, startDragging, + showInsertionPoint, canInsertBlockType, + isGroupable, getBlockVariations, getGroupingBlockName, - isGroupable, + getSettings, + isZoomOutMode, ] ), 200 From ade27acfd25a7900e807ecfb52ef3d9dfe5c9ee3 Mon Sep 17 00:00:00 2001 From: Luis Herranz <luisherranz@gmail.com> Date: Mon, 19 Aug 2024 12:40:07 +0200 Subject: [PATCH 0445/1908] iAPI Docs: The first three Core Concepts guides (#63759) * Initial version * Convert all tabs to spaces (except in non-PHP code snippets) * Initial SSR guide version * Initial version * Changes to properly add a subsection in the docs * Reorganize headers a bit * Add titles (are they necessary?) * Reorganize SSR sections * Use async handlers and update state/context guide * Finish review of the Declarative/reactive guide * Remove last "we's" * added manifest and toc data and intro to guides * Final revision * Fix typos Co-authored-by: Damon Cook <colorful-tones@users.noreply.github.com> --------- Co-authored-by: luisherranz <luisherranz@git.wordpress.org> Co-authored-by: juanmaguitar <juanmaguitar@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> --- docs/manifest.json | 24 + .../interactivity-api/core-concepts/README.md | 9 + .../core-concepts/server-side-rendering.md | 491 ++++++++++++ .../the-reactive-and-declarative-mindset.md | 300 +++++++ ...l-state-local-context-and-derived-state.md | 740 ++++++++++++++++++ docs/toc.json | 13 + 6 files changed, 1577 insertions(+) create mode 100644 docs/reference-guides/interactivity-api/core-concepts/README.md create mode 100644 docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md create mode 100644 docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md create mode 100644 docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md diff --git a/docs/manifest.json b/docs/manifest.json index b483449872cc76..e4eba19d99fa29 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -497,6 +497,30 @@ "markdown_source": "../docs/reference-guides/interactivity-api/README.md", "parent": "reference-guides" }, + { + "title": "Core Concepts", + "slug": "core-concepts", + "markdown_source": "../docs/reference-guides/interactivity-api/core-concepts/README.md", + "parent": "interactivity-api" + }, + { + "title": "The Reactive and Declarative mindset", + "slug": "the-reactive-and-declarative-mindset", + "markdown_source": "../docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md", + "parent": "core-concepts" + }, + { + "title": "Understanding global state, local context and derived state", + "slug": "undestanding-global-state-local-context-and-derived-state", + "markdown_source": "../docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md", + "parent": "core-concepts" + }, + { + "title": "Server-side rendering: Processing directives on the server", + "slug": "server-side-rendering", + "markdown_source": "../docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md", + "parent": "core-concepts" + }, { "title": "Quick start guide", "slug": "iapi-quick-start-guide", diff --git a/docs/reference-guides/interactivity-api/core-concepts/README.md b/docs/reference-guides/interactivity-api/core-concepts/README.md new file mode 100644 index 00000000000000..ef59fb6075f925 --- /dev/null +++ b/docs/reference-guides/interactivity-api/core-concepts/README.md @@ -0,0 +1,9 @@ +# Core Concepts + +This section provides some guides on important concepts and mental models related to Interactivity API development. Use the following links to learn more: + +1. **[The Reactive and Declarative mindset](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset):** This guide covers core concepts of reactivity and declarativeness, providing a foundation for effective use of the Interactivity API. + +2. **[Understanding global state, local context and derived state](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state):** The guide explains how to effectively use global state, local context, and derived state within the Interactivity API emphasizing the importance of choosing the appropriate state management technique based on the scope and requirements of your data. + +3. **[Server-side rendering: Processing directives on the server](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/core-concepts/server-side-rendering):** The Interactivity API allows WordPress to use server-side rendering to create interactive and state-aware HTML, smoothly connected with client-side features while maintaining performance and SEO benefits. diff --git a/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md b/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md new file mode 100644 index 00000000000000..2032d12d5670b1 --- /dev/null +++ b/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md @@ -0,0 +1,491 @@ +# Server-side rendering: Processing directives on the server + +WordPress has always been built on the foundation of server-side rendering. Traditionally, when a user requests a WordPress page, the server processes the PHP code, queries the database, and generates the HTML markup that is sent to the browser. + +In recent years, modern JavaScript frameworks like Vue, React, or Svelte have revolutionized the way we build web applications. These frameworks provide reactive and declarative programming models that enable developers to create dynamic, interactive user interfaces with ease. + +However, when it comes to server-side rendering, these frameworks require a JavaScript-based server, such as NodeJS, to execute their code and generate the initial HTML. This means that PHP-based servers, like WordPress, cannot directly utilize these frameworks without sacrificing their native PHP rendering capabilities. This limitation poses a challenge for WordPress developers who want to leverage the power of reactive and declarative programming while still benefiting from WordPress's traditional server-side rendering strengths. The Interactivity API bridges this gap by bringing [reactive and declarative programming principles](./the-reactive-and-declarative-mindset.md) to WordPress without compromising its server-side rendering foundation. + +In this guide, we'll explore how the Interactivity API processes directives on the server, enabling WordPress to deliver interactive, state-aware HTML from the initial page load, while setting the stage for seamless client-side interactivity. + +## Processing the directives on the server + +The Interactivity API's Server Directive Processing capabilities enable WordPress to generate the initial HTML with the correct interactive state, providing a faster initial render. After the initial server-side render, the Interactivity API's client-side JavaScript takes over, enabling dynamic updates and interactions without requiring full page reloads. This approach combines the best of both worlds: the SEO and performance benefits of traditional WordPress server-side rendering, and the dynamic, reactive user interfaces offered by modern JavaScript frameworks. + +To understand how the Server Directive Processing works, let's start with an example where a list of fruits is rendered using the `data-wp-each` directive. + +The following are the necessary steps to ensure that the directives are correctly processed by the Server Directive Processing of the Interactivity API during the server-side rendering of WordPress. + +- **1. Mark the block as interactive** + + First, to enable the server processing of the interactive block's directives, you must add `supports.interactivity` to the `block.json`: + + ```json + { + "supports": { + "interactivity": true + } + } + ``` + +- **2. Initialize the global state or local context** + + Then, you must initialize either the global state or the local context that will be used during the server-side rendering of the page. + + If you are using global state, you must use the `wp_interactivity_state` function: + + ```php + wp_interactivity_state( 'myFruitPlugin', array( + 'fruits' => array( 'Apple', 'Banana', 'Cherry' ) + )); + ``` + + If you are using local context, the initial values are defined with the `data-wp-context` directive itself, either by: + + - Adding it directly to the HTML. + + ```html + <ul data-wp-context='{ "fruits": ["Apple", "Banana", "Cherry"] }'> + ... + </ul> + ``` + + - Using the `wp_interactivity_data_wp_context` helper. + + ```php + <?php + $context = array( 'fruits' => array( 'Apple', 'Banana', 'Cherry' ) ); + ?> + + <ul <?php echo wp_interactivity_data_wp_context( $context ); ?>> + ... + </ul> + ``` + +- **3. Define the interactive elements using directives** + + Next, you need to add the necessary directives to the HTML markup. + + ```html + <ul data-wp-interactive="myFruitPlugin"> + <template data-wp-each="state.fruits"> + <li data-wp-text="context.item"></li> + </template> + </ul> + ``` + + In this example: + + - The `data-wp-interactive` directive activates the interactivity for the DOM element and its children. + - The `data-wp-each` directive is used to render a list of elements. The directive can be used in `<template>` tags, with the value being a reference path to an array stored in the global state or the local context. + - The `data-wp-text` directive sets the inner text of an HTML element. Here, it points to `context.item`, which is where the `data-wp-each` directive stores each item of the array. + + The exact same directives can also be used when using local context instead of global state. The only difference is that `data-wp-each` points to `context.fruits` instead of `state.fruits`: + + ```html + <ul + data-wp-interactive="myFruitPlugin" + data-wp-context='{ "fruits": [ "Apple", "Banana", "Cherry" ] }' + > + <template data-wp-each="context.fruits"> + <li data-wp-text="context.item"></li> + </template> + </ul> + ``` + +That's it! Once you've set up your interctive block with `supports.interactivity`, initialized your global state or local context, and added the directives to the HTML markup, the Interactivity API will take care of the rest. There's no additional code required from the developer to process these directives on the server side. + +Behind the scenes, WordPress uses the `wp_interactivity_process_directives` function to find and process the directives in the HTML markup of your block. This function uses the HTML API to make the necessary changes to the markup, based on the found directives and the initial global state and/or local context. + +As a result, the HTML markup sent to the browser is already in its final form, with all directives correctly processed. This means that when the page first loads in the browser, it already contains the correct initial state of all interactive elements, without needing any JavaScript to modify it. + +This is how the final HTML markup of the fruit list example would look like (directives omitted): + +```html +<ul> + <li>Apple</li> + <li>Banana</li> + <li>Cherry</li> +</ul> +``` + +As you can see, the `data-wp-each` directive has generated a `<li>` element for each fruit in the array, and the `data-wp-text` directive has been processed, populating each `<li>` with the correct fruit name. + +## Manipulating the global state and local context in the client + +One of the key strengths of the Interactivity API is how it bridges the gap between server-side rendering and client-side interactivity. To do so, the global state and local context initialized on the server are also serialized and made available to the Interactivity API stores in the client, allowing the application to continue functioning and manipulating the DOM dynamically. + +Let's extend this example to include a button that the user can click to add a new fruit to the list: + +```html +<button data-wp-on-async--click="actions.addMango">Add Mango</button> +``` + +This new button has a `data-wp-on-async--click` directive that references `actions.addMango`, which is defined in our JavaScript store: + +```javascript +const { state } = store( 'myFruitPlugin', { + actions: { + addMango() { + state.fruits.push( 'Mango' ); + }, + }, +} ); +``` + +The same example would also work if you were using local context: + +```javascript +store( 'myFruitPlugin', { + actions: { + addMango() { + const context = getContext(); + context.fruits.push( 'Mango' ); + }, + }, +} ); +``` + +Now, when the user clicks the "Add Mango" button: + +1. The `addMango` action is triggered. +2. The `'Mango'` item is added to the `state.fruits` (or `context.fruits`) array. +3. The Interactivity API automatically updates the DOM, adding a new `<li>` element for the new fruit. + +```html +<ul> + <li>Apple</li> + <li>Banana</li> + <li>Cherry</li> + <li>Mango</li> +</ul> +``` + +Remember: initializing the state on the client is not necessary when it has already been done on the server. + +```javascript +store( 'myFruitPlugin', { + state: { + fruits: [ 'Apple', 'Banana', 'Cherry' ], // This is not necessary! + }, +} ); +``` + +## Initializing the derived state in the server + +The derived state, regardless of whether it derives from the global state, local context, or both, can also be processed on the server by the Server Directive Processing. + +_Please, visit the [Understanding global state, local context and derived state](./undestanding-global-state-local-context-and-derived-state.md) guide to learn more about how derived state works in the Interactivity API._ + +### Derived state that can be defined statically + +Let's imagine adding a button that can delete all fruits: + +```html +<button data-wp-on-async--click="actions.deleteFruits"> + Delete all fruits +</button> +``` + +```javascript +const { state } = store( 'myFruitPlugin', { + actions: { + // ... + deleteFruits() { + state.fruits = []; + }, + }, +} ); +``` + +Now, let's display a special message when there is no fruit. To do this, let's use a `data-wp-bind--hidden` directive that references a derived state called `state.hasFruits` to show/hide the message. + +```html +<div data-wp-interactive="myFruitPlugin"> + <ul data-wp-bind--hidden="!state.hasFruits"> + <template data-wp-each="state.fruits"> + <li data-wp-text="context.item"></li> + </template> + </ul> + <div data-wp-bind--hidden="state.hasFruits">No fruits, sorry!</div> +</div> +``` + +The derived state `state.hasFruits` is defined on the client using a getter: + +```javascript +const { state } = store( 'myFruitPlugin', { + state: { + get hasFruits() { + return state.fruits.length > 0; + }, + }, + // ... +} ); +``` + +Up to this point, everything is fine in the client, and when we press the "Delete all fruits" button, the "No fruits, sorry!" message will be displayed. The problem is that since `state.hasFruits` is not defined on the server, the `hidden` attribute will not be part of the initial HTML, which means it will also be showing the message until JavaScript loads, causing not only confusion to the visitor, but also a layout shift when JavaScript finally loads and the message is hidden. + +To fix this, you must define the initial value of the derived state in the server using `wp_interactivity_state`. + +- When the initial value is known and static, it can be defined directly: + + ```php + wp_interactivity_state( 'myFruitPlugin', array( + 'fruits' => array( 'Apple', 'Banana', 'Cherry' ), + 'hasFruits' => true + )); + ``` + +- Or it can be defined by doing the necessary computations: + + ```php + $fruits = array( 'Apple', 'Banana', 'Cherry' ); + $hasFruits = count( $fruits ) > 0; + + wp_interactivity_state( 'myFruitPlugin', array( + 'fruits' => $fruits, + 'hasFruits' => $hasFruits, + )); + ``` + +Regardless of the approach, the key point is that the initial value of `state.hasFruits` is now defined on the server. This allows the Server Directive Processing to handle the `data-wp-bind--hidden` directive and modify the HTML markup, adding the `hidden` attribute when needed. + +### Derived state that needs to be defined dynamically + +In most cases, the initial derived state can be defined statically, as in the previous example. But sometimes, the value depends on dynamic values that also change in the server, and the derived logic needs to be replicated in PHP. + +To see an example of this, let's continue by adding a shopping cart emoji (🛒) for each fruit, depending on whether it is on a shopping list or not. + +First, let's add an array that represents the shopping list. _Remember that even though these arrays are static for simplicity sake, usually you will work with dynamic information, for example, information coming from the database._ + +```php +wp_interactivity_state( 'myFruitPlugin', array( + 'fruits' => array( 'Apple', 'Banana', 'Cherry' ), + 'shoppingList' => array( 'Apple', 'Cherry' ), +)); +``` + +Now, let's add a derived state on the client that checks if each fruit is on the shopping list or not and returns the emoji. + +```javascript +store( 'myFruitPlugin', { + state: { + get onShoppingList() { + const context = getContext(); + return state.shoppingList.includes( context.item ) ? '🛒' : ''; + }, + }, + // ... +} ); +``` + +And let's use that derived state to show the appropriate emoji for each fruit. + +```html +<ul data-wp-interactive="myFruitPlugin"> + <template data-wp-each="state.fruits"> + <li> + <span data-wp-text="context.item"></span> + <span data-wp-text="state.onShoppingList"></span> + </li> + </template> +</ul> +``` + +Again, up to this point, everything is fine on the client side and the visitor will see the correct emoji displayed for the fruits they have on their shopping list. However, since `state.onShoppingList` is not defined on the server, the emoji will not be part of the initial HTML, and it will not be shown until JavaScript loads. + +Let's fix that by adding the initial derived state using `wp_interactivity_state`. Remember that this time, the value depends on `context.item` that comes from the `data-wp-each` directive, which makes the derived value dynamic, so let's replicate the JavaScript logic in PHP: + +```php +wp_interactivity_state( 'myFruitPlugin', array( + // ... + 'onShoppingList' => function() { + $state = wp_interactivity_state(); + $context = wp_interactivity_get_context(); + return in_array( $context['item'], $state['shoppingList'] ) ? '🛒' : ''; + } +)); +``` + +That's it! Now, our server can compute the derived state and know which fruits are on the shopping list and which are not. This allows the Server Directive Processing to populate the initial HTML with the correct values, ensuring that the user sees the correct information immediately, even before the JavaScript runtime loads. + +## Serializing other processed values to be consumed on the client + +The `wp_interactivity_state` function is also valuable for sending processed values from the server to the client so they can be consumed later on. This feature is useful in many situations, such as managing translations. + +Let's add translations to our example to see how this would work. + +```php +<?php +wp_interactivity_state( 'myFruitPlugin', array( + 'fruits' => array( __( 'Apple' ), __( 'Banana' ), __( 'Cherry' ) ), + 'shoppingList' => array( __( 'Apple' ), __( 'Cherry' ) ), + // ... +?> + +<div data-wp-interactive="myFruitPlugin"> + <button data-wp-on-async--click="actions.deleteFruits"> + <?php echo __( 'Delete all fruits' ); ?> + </button> + <button data-wp-on-async--click="actions.addMango"> + <?php echo __( 'Add Mango' ); ?> + </button> + <ul data-wp-bind--hidden="!state.hasFruits"> + <template data-wp-each="state.fruits"> + <li> + <span data-wp-text="context.item"></span> + <span data-wp-text="state.onShoppingList"></span> + </li> + </template> + </ul> + <div data-wp-bind--hidden="state.hasFruits"> + <?php echo __( 'No fruits, sorry!' ); ?> + </div> +</div> +``` + +That's it! Since the Interactivity API works in PHP, you can add translations directly to the global state, the local context and the HTML markup. + +But wait, what happens with our `addMango` action? Remember, this action is defined only on JavaScript: + +```javascript +const { state } = store( 'myFruitPlugin', { + actions: { + addMango() { + state.fruits.push( 'Mango' ); // Not translated! + }, + }, +} ); +``` + +To fix this issue, you can use the `wp_interactivity_state` function to serialize the translated mango string and then access that value in your action. + +```php +wp_interactivity_state( 'myFruitPlugin', array( + 'fruits' => array( __( 'Apple' ), __( 'Banana' ), __( 'Cherry' ) ), + 'mango' => __( 'Mango' ), +)); +``` + +```javascript +const { state } = store( 'myFruitPlugin', { + actions: { + addMango() { + // `state.mango` contains the 'Mango' string already translated. + state.fruits.push( state.mango ); + }, + }, +} ); +``` + +Take into account that if your application is more dynamic, you could serialize an array with all the fruit translations and just work with _fruit keywords_ in your actions. For example: + +```php +wp_interactivity_state( 'myFruitPlugin', array( + 'fruits' => array( 'apple', 'banana', 'cherry' ), + 'translatedFruits' => array( + 'apple' => __( 'Apple' ), + 'banana' => __( 'Banana' ), + 'cherry' => __( 'Cherry' ), + 'mango' => __( 'Mango' ), + ), + 'translatedFruit' => function() { + $state = wp_interactivity_state(); + $context = wp_interactivity_get_context(); + return $state['translatedFruits'][ $context['item'] ]; + } +)); +``` + +```javascript +const { state } = store( 'myFruitPlugin', { + state: { + get translatedFruit() { + const context = getContext(); + return state.translatedFruits[ context.item ]; + } + } + actions: { + addMango() { + state.fruits.push( 'mango' ); + }, + }, +} ); +``` + +```html +<template data-wp-each="state.fruits"> + <li data-wp-text="state.translatedFruit"></li> +</template> +``` + +Serializing information from the server can also be useful in other scenarios, such as passing Ajax/REST-API URLs and nonces. + +```php +wp_interactivity_state( 'myPlugin', array( + 'ajaxUrl' => admin_url( 'admin-ajax.php' ), + 'nonce' => wp_create_nonce( 'myPlugin_nonce' ), +)); +``` + +```js +const { state } = store( 'myPlugin', { + actions: { + *doSomething() { + const formData = new FormData(); + formData.append( 'action', 'do_something' ); + formData.append( '_ajax_nonce', state.nonce ); + + const data = yield fetch( state.ajaxUrl, { + method: 'POST', + body: formData, + } ).then( ( response ) => response.json() ); + + console.log( 'Server data', data ); + }, + }, +} ); +``` + +## Processing directives in classic themes + +Server Directive Processing happens automatically in your interactive blocks as soon as you add `supports.interactivity` to your `block.json` file. But what about classic themes? + +Classic themes can also use the Interactivity API, and if they want to take advantage of the Server Directive Processing (which they should), they can do so through the `wp_interactivity_process_directives` function. This function receives the HTML markup with unprocessed directives and returns the HTML markup modified according to the initial values of the global state, local context, and derived state. + +```php +// Initializes the global and derived state… +wp_interactivity_state( '...', /* ... */ ); + +// The interactive HTML markup that contains the directives. +$html = '<div data-wp-...>...</div>'; + +// Processes the directives so they are ready to be sent to the client. +$processed_html = wp_interactivity_process_directives( $html ); +``` + +That's it! There's nothing else you need to do. + +If you want to use `wp_interactivity_process_directives` in a template file, you can use `ob_start` and `ob_get_clean` to capture the HTML output and process it before rendering. + +```php +<?php +wp_interactivity_state( 'myClassicTheme', /* ... */ ); +ob_start(); +?> + +<div data-wp-interactive="myClassicTheme"> + ... +</div> + +<?php +$html = ob_get_clean(); +echo wp_interactivity_process_directives( $html ); +``` + +**Important:** You only need to process the directives once. If you're including an inner template file within another template, ensure that `wp_interactivity_process_directives` is only called in the outermost template file to avoid redundant processing. + +## Conclusion + +The Interactivity API ensures a smooth and transparent transition from server-rendered content to client-side interactivity. The directives you define on the server, the initial global state or local context, and the client-side behavior all form part of the same ecosystem. This unified approach simplifies development, improves maintainability, and provides a better developer experience when creating interactive WordPress blocks. diff --git a/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md b/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md new file mode 100644 index 00000000000000..59940560fe20b6 --- /dev/null +++ b/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md @@ -0,0 +1,300 @@ +# The Reactive and Declarative mindset + +The Interactivity API is a reactive and declarative framework, similar to other modern frameworks like React, Vue, Svelte, or Alpine. When working with the Interactivity API, adopting the right mindset is crucial for maximizing its potential. This guide will explain the core concepts of reactivity and declarativeness, providing a foundation for effective use of the Interactivity API. + +## Declarative vs. imperative + +**Declarative Programming** describes _what_ a program should accomplish. It focuses on the desired outcome without explicitly listing commands or steps to achieve that result. In contrast, **imperative programming** specifies _how_ to accomplish tasks by explicitly stating each step to manipulate the program’s state. + +### The imperative approach + +In the early days of web development, the imperative approach was predominant. This method involves manually updating the DOM with JavaScript to reflect changes. + +Take, for example, this interactive block with two buttons and a paragraph: + +- **The show/hide button**: Toggles paragraph visibility and enables/disables the "Activate" button. +- **The activate/deactivate button**: Toggles the paragraph's text and color between "active" (green) and "inactive" (red). + +```html +<div id="my-interactive-plugin"> + <button + id="show-hide-btn" + aria-expanded="false" + aria-controls="status-paragraph" + > + show + </button> + <button id="activate-btn" disabled>activate</button> + <p id="status-paragraph" class="inactive" hidden>this is inactive</p> +</div> + +<script> + const showHideBtn = document.getElementById( 'show-hide-btn' ); + const activateBtn = document.getElementById( 'activate-btn' ); + const statusParagraph = document.getElementById( 'status-paragraph' ); + + showHideBtn.addEventListener( 'click', () => { + if ( statusParagraph.hasAttribute( 'hidden' ) ) { + statusParagraph.removeAttribute( 'hidden' ); + showHideBtn.textContent = 'hide'; + showHideBtn.setAttribute( 'aria-expanded', 'true' ); + activateBtn.removeAttribute( 'disabled' ); + } else { + if ( statusParagraph.classList.contains( 'active' ) ) { + statusParagraph.textContent = 'this is inactive'; + statusParagraph.classList.remove( 'active' ); + activateBtn.textContent = 'activate'; + } + statusParagraph.setAttribute( 'hidden', true ); + showHideBtn.textContent = 'show'; + showHideBtn.setAttribute( 'aria-expanded', 'false' ); + activateBtn.setAttribute( 'disabled', true ); + } + } ); + + activateBtn.addEventListener( 'click', () => { + if ( activateBtn.textContent === 'activate' ) { + statusParagraph.textContent = 'this is active'; + statusParagraph.classList.remove( 'inactive' ); + statusParagraph.classList.add( 'active' ); + activateBtn.textContent = 'deactivate'; + } else { + statusParagraph.textContent = 'this is inactive'; + statusParagraph.classList.remove( 'active' ); + statusParagraph.classList.add( 'inactive' ); + activateBtn.textContent = 'activate'; + } + } ); +</script> +``` + +As you can see, for each condition, you have to use JavaScript to modify everything in the DOM that has changed, taking into account the previous state. + +### The declarative approach + +The declarative approach simplifies the process by focusing on _what_ should happen. The UI updates automatically in response to changes in state. Here is a similar example using the Interactivity API's declarative approach: + +```html +<div id="my-interactive-plugin" data-wp-interactive="myInteractivePlugin"> + <button + data-wp-on--click="actions.toggleVisibility" + data-wp-bind--aria-expanded="state.isVisible" + data-wp-text="state.visibilityText" + aria-controls="status-paragraph" + > + show + </button> + <button + data-wp-on--click="actions.toggleActivation" + data-wp-bind--disabled="!state.isVisible" + data-wp-text="state.activationText" + > + activate + </button> + <p + id="status-paragraph" + data-wp-bind--hidden="!state.isVisible" + data-wp-class--active="state.isActive" + data-wp-class--inactive="!state.isActive" + data-wp-text="state.paragraphText" + > + this is inactive + </p> +</div> +``` + +```js +import { store } from '@wordpress/interactivity'; + +const { state } = store( 'myInteractivePlugin', { + state: { + isVisible: false, + isActive: false, + get visibilityText() { + return state.isVisible ? 'hide' : 'show'; + }, + get activationText() { + return state.isActive ? 'deactivate' : 'activate'; + }, + get paragraphText() { + return state.isActive ? 'this is active' : 'this is inactive'; + }, + }, + actions: { + toggleVisibility() { + state.isVisible = ! state.isVisible; + if ( ! state.isVisible ) state.isActive = false; + }, + toggleActivation() { + state.isActive = ! state.isActive; + }, + }, +} ); +``` + +In this declarative example, the UI automatically updates based on the current state. All you have to do as developers is to declare the necessary state, any derived state, the actions that modify the state, and which parts of the DOM depend on which parts of the state. The framework takes care of making all the necessary updates to the DOM so that it is always in sync with the current state. The logic remains simple and maintainable regardless of the number of elements controlled by the framework. + +### Can you spot the bug? + +In the imperative example, a bug has been intentionally introduced for didactical purposes. Can you find it? It's not easy! + +<details> +<summary>Show me the answer!</summary> + +In the case that the Show button is pressed first, then the Activate button, and finally the Hide button, it doesn't add the `inactive` class using `statusParagraph.classList.add('inactive');`. Therefore, the next time the user presses Show, the paragraph will not appear in red. + +</details> + +These types of bugs are very common in imperative code because you have to manually control all the conditions. On the other hand, they do not exist in declarative code because the framework takes care of updating the DOM and never forgets about anything. + +### Benefits of the declarative approach + +As demonstrated, the imperative approach requires detailed steps and direct manipulation of the DOM, which can quickly become complex and hard to maintain as the interactivity complexity grows. The more possible states and elements there are, the more conditional logic needs to be added, making the code exponentially more complicated. The declarative approach, on the other hand, simplifies the process by managing the state and letting the framework handle the DOM updates. This leads to more readable, maintainable, and scalable code. + +## Reactivity + +The Interactivity API is a declarative framework thanks to its leverage of reactivity. In a reactive system, changes to the data automatically trigger updates in the user interface, ensuring that the view always reflects the current state of the application. + +### How reactivity works + +The Interactivity API uses a fine-grained reactivity system. Here's how it works: + +1. **Reactive State**: In the Interactivity API, both the global state and the local context are reactive. This means that when either of these data sources changes, any parts of the UI that depend on them will automatically update. + + - **Global state**: This is global data that can be accessed throughout your interactive blocks. + - **Local context**: This is local data that is specific to a particular element and its children. + - **Derived State**: In addition to basic state properties, you can define computed properties that automatically update when their dependencies change. + + _Please, visit the [Understanding global state, local context and derived state](./undestanding-global-state-local-context-and-derived-state.md) guide to learn more about how to work with the different types of reactive state in the Interactivity API._ + +2. **Actions**: These are functions, usually triggered by event handlers, that mutate the global state or local context. + +3. **Reactive Bindings**: HTML elements are bound to reactive state values using special attributes like `data-wp-bind`, `data-wp-text`, or `data-wp-class`. + +4. **Automatic Updates**: When the actions mutate the global state or local context, the Interactivity API automatically updates all the parts of the DOM that depend on that state (either directly or through the derived state). + +Let's break down these concepts by reviewing the previous example: + +```javascript +const { state } = store( 'myInteractivePlugin', { + state: { + isVisible: false, + isActive: false, + get visibilityText() { + return state.isVisible ? 'hide' : 'show'; + }, + // ... other derived state + }, + actions: { + toggleVisibility() { + state.isVisible = ! state.isVisible; + }, + // ... other actions + }, +} ); +``` + +In this code: + +- `isVisible` and `isActive` are basic state properties. +- `visibilityText` is a derived state that automatically updates when `isVisible` changes. +- `toggleVisibility` is an action that modifies the state. + +The HTML bindings look like this: + +```html +<button + data-wp-on--click="actions.toggleVisibility" + data-wp-text="state.visibilityText" + data-wp-bind--aria-expanded="state.isVisible" +> + show +</button> +``` + +Here's how reactivity works in practice: + +1. When the button is clicked, it triggers the `toggleVisibility` action. +2. This action updates `state.isVisible`. +3. The Interactivity API detects this change and automatically: + - Updates the button's text content (because of `data-wp-text="state.visibilityText"`). + - Changes the `aria-expanded` attribute (due to `data-wp-bind--aria-expanded="state.isVisible"`). + - Updates any other parts of the DOM that depend on `isVisible` or `visibilityText`. + +### Mutability vs immutability + +Unlike many other reactive frameworks, **the Interactivity API does not require the use of immutability** when updating the global state or the local context. You can directly mutate objects and arrays, and the reactivity system will still work as expected. This can lead to more intuitive and straightforward code in many cases. + +For example, you can push a new item to an array like this: + +```javascript +const { state } = store( 'myArrayPlugin', { + state: { + list: [ 'item 1', 'item 2' ], + }, + actions: { + addItem() { + // Right: + state.list.push( 'new item' ); + + // Wrong: + state.list = [ ...state.list, 'new item' ]; // Don't do this! + }, + }, +} ); +``` + +There's no need to create a new array or use the spread operator as you might in other frameworks. The Interactivity API will detect this change and update any parts of the UI that depend on `state.list`. + +### Reactive side effects + +In addition to automatically updating the UI, the Interactivity API allows you to perform side effects when reactive data changes using directives like `data-wp-watch`. Side effects are useful for tasks like logging, making API calls, or updating other parts of your application that aren't directly tied to the UI. + +Here's an example of how you might use `data-wp-watch`: + +```html +<div + data-wp-interactive="myCounterPlugin" + data-wp-context='{ "counter": 0 }' + data-wp-watch="callbacks.logCounter" +> + <p>Counter: <span data-wp-text="context.counter"></span></p> + <button data-wp-on--click="actions.increment">Increment</button> +</div> +``` + +```javascript +store( 'myCounterPlugin', { + actions: { + increment() { + const context = getContext(); + context.counter += 1; + }, + }, + callbacks: { + logCounter: () => { + const context = getContext(); + console.log( `The counter is now: ${ context.counter }` ); + }, + }, +} ); +``` + +In this example: + +1. The `data-wp-context` directive adds a local context with a property `counter` whose value is `0`. +2. The `data-wp-watch` directive is set to `callbacks.logCounter`. +3. Every time `context.counter` changes, the `logCounter` callback will be executed. +4. The `logCounter` callback logs the current counter to the console. + +This allows you to create declarative side effects that automatically run in response to data changes. Some other use cases for `data-wp-watch` might include: + +- Saving data to `localStorage` when the data changes. +- Sending analytics events. +- Changing the focus for accessibility purposes. +- Updating the page title, meta tags, or `<body>` attributes. +- Triggering animations. + +## Conclusion + +As you continue to work with the Interactivity API, remember to think in terms of state, actions, and side effects. Define your data, describe how it should change, and let the Interactivity API handle the rest. This mental shift may take some time, especially if you're used to more imperative programming styles, but by embracing it, you'll unlock the full potential of the Interactivity API to create truly dynamic and interactive WordPress blocks that delight your users. diff --git a/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md b/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md new file mode 100644 index 00000000000000..0071f26fc8a333 --- /dev/null +++ b/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md @@ -0,0 +1,740 @@ +# Understanding global state, local context and derived state + +The Interactivity API offers a powerful framework for creating interactive blocks. To make the most of its capabilities, it's crucial to understand when to use global state, local context, or derived state. This guide will clarify these concepts and provide practical examples to help you decide when to use each one. + +Let's start with a brief definition of global state, local context and derived state. + +- **Global state:** Global data that can be accessed and modified by any interactive block on the page, allowing different parts of your interactive blocks to stay in sync. +- **Local context:** Local data defined within a specific element in the HTML structure, accessible only to that element and its children, providing independent state for individual blocks. +- **Derived state:** Computed values based on global state or local context, dynamically calculated on-demand to ensure consistent data representation without storing redundant data. + +Let's now dive into each of these concepts to study them in more detail and provide some examples. + +## Global state + +**Global state** in the Interactivity API refers to global data that can be accessed and modified by any interactive block on the page. It serves as a shared information hub, allowing different parts of your blocks to communicate and stay in sync. Global state is the ideal mechanism for exchanging information between interactive blocks, regardless of their position in the DOM tree. + +You should use global state when: + +- You need to share data between multiple interactive blocks that are not directly related in the DOM hierarchy. +- You want to maintain a single source of truth for certain data across all your interactive blocks. +- You're dealing with data that affects multiple parts of your UI simultaneously. +- You want to implement features that are global for the page. + +### Working with global state + +- **Initializing the global state** + + Typically, the initial global state values should be defined on the server using the `wp_interactivity_state` function: + + ```php + // Populates the initial global state values. + wp_interactivity_state( 'myPlugin', array( + 'isDarkTheme' => true, + 'show' => false, + 'helloText' => __( 'world' ), + )); + ``` + + These initial global state values will be used during the rendering of the page in PHP to populate the HTML markup that is sent to the browser. + + - HTML markup written in the PHP file by the developer: + + ```html + <div + data-wp-interactive="myPlugin" + data-wp-class--is-dark-theme="state.isDarkTheme" + class="my-plugin" + > + <div data-wp-bind--hidden="!state.show"> + Hello <span data-wp-text="state.helloText"></span> + </div> + <button data-wp-on-async--click="actions.toggle">Toggle</button> + </div> + ``` + + - HTML markup after the directives have been processed and it is ready to be sent to the browser: + + ```html + <div + data-wp-interactive="myPlugin" + data-wp-class--is-dark-theme="state.isDarkTheme" + class="my-plugin is-dark-theme" + > + <div hidden data-wp-bind--hidden="!state.show"> + Hello <span data-wp-text="state.helloText">world</span> + </div> + <button data-wp-on-async--click="actions.toggle">Toggle</button> + </div> + ``` + + _Please, visit [the Server-side Rendering guide](./server-side-rendering.md) to learn more about how directives are processed on the server._ + + In cases where the global state is not used during the rendering of the page in PHP, it can also be defined directly on the client. + + ```js + const { state } = store( 'myPlugin', { + state: { + isLoading: false, + }, + actions: { + *loadSomething() { + state.isLoading = true; + // ... + }, + }, + } ); + ``` + + _Please note that, although this works, in general it is a good practice to define all the global state on the server._ + +- **Accessing the global state** + + In the HTML markup, you can access the global state values directly by referencing `state` in the directive attribute values: + + ```html + <div data-wp-bind--hidden="!state.show"> + <span data-wp-text="state.helloText"></span> + </div> + ``` + + In JavaScript, the `store` function from the package at `@wordpress/interactivity` works both as a setter and a getter, returning the store of the selected namespace. + + To access the global state in your actions and callbacks, you can use the `state` property of the object returned by the `store` function: + + ```js + const myPluginStore = store( 'myPlugin' ); + + myPluginStore.state; // This is the state of the 'myPlugin' namespace. + ``` + + You can also destructure the object returned by `store`: + + ```js + const { state } = store( 'myPlugin' ); + ``` + + And you can do the same even if you are defining the store at that moment, which is the most common scenario: + + ```js + const { state } = store( 'myPlugin', { + state: { + // ... + }, + actions: { + toggle() { + state.show = ! state.show; + }, + }, + } ); + ``` + + The global state initialized on the server using the `wp_interactivity_state` function is also included in that object because it is automatically serialized from the server to the client: + + ```php + wp_interactivity_state( 'myPlugin', array( + 'someValue' => 1, + )); + ``` + + ```js + const { state } = store( 'myPlugin', { + state: { + otherValue: 2, + }, + actions: { + readGlobalState() { + state.someValue; // It exists and its initial value is 1. + state.otherValue; // It exists and its initial value is 2. + }, + }, + } ); + ``` + + Lastly, all calls to the `store` function with the same namespace are merged together: + + ```js + store( 'myPlugin', { state: { someValue: 1 } } ); + + store( 'myPlugin', { state: { otherValue: 2 } } ); + + /* All calls to `store` return a stable reference to the same object, so you + * can get a reference to `state` from any of them. */ + const { state } = store( 'myPlugin' ); + + store( 'myPlugin', { + actions: { + readValues() { + state.someValue; // It exists and its initial value is 1. + state.otherValue; // It exists and its initial value is 2. + }, + }, + } ); + ``` + +- **Updating the global state** + + To update the global state, all you need to do is mutate the `state` object once you have obtained it from the `store` function: + + ```js + const { state } = store( 'myPlugin', { + actions: { + updateValues() { + state.someValue = 3; + state.otherValue = 4; + }, + }, + } ); + ``` + + Changes to the global state will automatically trigger updates in any directives that depend on the modified values. + + _Please, visit [The Reactive and Declarative mindset](./the-reactive-and-declarative-mindset.md) guide to learn more about how reactivity works in the Interactivity API._ + +### Example: Two interactive blocks using global state to communicate + +In this example, there are two independent interactive blocks. One displays a counter, and the other a button to increment that counter. These blocks can be positioned anywhere on the page, regardless of the HTML structure. In other words, one does not need to be an inner block of the other. + +- **Counter Block** + + ```php + <?php + wp_interactivity_state( 'myCounterPlugin', array( + 'counter' => 0 + )); + ?> + + <div + data-wp-interactive="myCounterPlugin" + <?php echo get_block_wrapper_attributes(); ?> + > + Counter: <span data-wp-text="state.counter"></span> + </div> + ``` + +- **Increment Block** + + ```php + <div + data-wp-interactive="myCounterPlugin" + <?php echo get_block_wrapper_attributes(); ?> + > + <button data-wp-on-async--click="actions.increment"> + Increment + </button> + </div> + ``` + + ```js + const { state } = store( 'myCounterPlugin', { + actions: { + increment() { + state.counter += 1; + }, + }, + } ); + ``` + +In this example: + +1. The global state is initialized on the server using `wp_interactivity_state`, setting an initial `counter` of 0. +2. The Counter Block displays the current counter using `data-wp-text="state.counter"`, which reads from the global state. +3. The Increment Block contains a button that triggers the `increment` action when clicked, using `data-wp-on-async--click="actions.increment"`. +4. In JavaScript, the `increment` action directly modifies the global state by incrementing `state.counter`. + +Both blocks are independent and can be placed anywhere on the page. They don't need to be nested or directly related in the DOM structure. Multiple instances of these interactive blocks can be added to the page, and they will all share and update the same global counter value. + +## Local context + +**Local context** in the Interactivity API refers to local data defined within a specific element in the HTML structure. Unlike global state, local context is only accessible to the element where it's defined and its child elements. + +The local context is particularly useful when you need independent state for individual interactive blocks, ensuring that each instance of a block can maintain its own unique data without interfering with others. + +You should use local context when: + +- You need to maintain separate state for multiple instances of the same interactive block. +- You want to encapsulate data that's only relevant to a specific interactive block and its children. +- You need to implement features that are isolated to a specific part of your UI. + +### Working with local context + +- **Initializing the local context** + + The local context is initialized directly within the HTML structure using the `data-wp-context` directive. This directive accepts a JSON string that defines the initial values for that piece of context. + + ```html + <div data-wp-context='{ "counter": 0 }'> + <!-- Child elements will have access to `context.counter` --> + </div> + ``` + + You can also initialize the local context on the server using the `wp_interactivity_data_wp_context` PHP helper, which ensures proper escaping and formatting of the stringified values: + + ```php + <?php + $context = array( 'counter' => 0 ); + ?> + + <div <?php echo wp_interactivity_data_wp_context( $context ); ?>> + <!-- Child elements will have access to `context.counter` --> + </div> + ``` + +- **Accessing the local context** + + In the HTML markup, you can access the local context values directly by referencing `context` in the directive values: + + ```html + <div data-wp-bind--hidden="!context.isOpen"> + <span data-wp-text="context.counter"></span> + </div> + ``` + + In JavaScript, you can access the local context values using the `getContext` function: + + ```js + store( 'myPlugin', { + actions: { + sendAnalyticsEvent() { + const { counter } = getContext(); + myAnalyticsLibrary.sendEvent( 'updated counter', counter ); + }, + }, + callbacks: { + logCounter() { + const { counter } = getContext(); + console.log( `Current counter: ${ counter }` ); + }, + }, + } ); + ``` + + The `getContext` function returns the local context of the element that triggered the action/callback execution. + +- **Updating the local context** + + To update the local context values in JavaScript, you can modify the object returned by `getContext`: + + ```js + store( 'myPlugin', { + actions: { + increment() { + const context = getContext(); + context.counter += 1; + }, + updateName( event ) { + const context = getContext(); + context.name = event.target.value; + }, + }, + } ); + ``` + + Changes to the local context will automatically trigger updates in any directives that depend on the modified values. + + _Please, visit [The Reactive and Declarative mindset](./the-reactive-and-declarative-mindset.md) guide to learn more about how reactivity works in the Interactivity API._ + +- **Nesting local contexts** + + Local contexts can be nested, with child contexts inheriting and potentially overriding values from parent contexts: + + ```html + <div data-wp-context='{ "theme": "light", "counter": 0 }'> + <p>Theme: <span data-wp-text="context.theme"></span></p> + <p>Counter: <span data-wp-text="context.counter"></span></p> + + <div data-wp-context='{ "theme": "dark" }'> + <p>Theme: <span data-wp-text="context.theme"></span></p> + <p>Counter: <span data-wp-text="context.counter"></span></p> + </div> + </div> + ``` + + In this example, the inner `div` will have a `theme` value of `"dark"`, but will inherit the `counter` value `0` from its parent context. + +### Example: One interactive block using local context to have independent state + +In this example, there is a single interactive block that shows a counter and can increment it. By using local context, each instance of this block will have its own independent counter, even if multiple blocks are added to the page. + +```php +<div + data-wp-interactive="myCounterPlugin" + <?php echo get_block_wrapper_attributes(); ?> + data-wp-context='{ "counter": 0 }' +> + <p>Counter: <span data-wp-text="context.counter"></span></p> + <button data-wp-on-async--click="actions.increment">Increment</button> +</div> +``` + +```js +store( 'myCounterPlugin', { + actions: { + increment() { + const context = getContext(); + context.counter += 1; + }, + }, +} ); +``` + +In this example: + +1. A local context with an initial `counter` value of `0` is defined using the `data-wp-context` directive. +2. The counter is displayed using `data-wp-text="context.counter"`, which reads from the local context. +3. The increment button uses `data-wp-on-async--click="actions.increment"` to trigger the increment action. +4. In JavaScript, the `getContext` function is used to access and modify the local context for each block instance. + +A user will be able to add multiple instances of this block to a page, and each will maintain its own independent counter. Clicking the "Increment" button on one block will only affect that specific block's counter and not the others. + +## Derived state + +**Derived state** in the Interactivity API refers to a value that is computed from other parts of the global state or local context. It's calculated on demand rather than stored. It ensures consistency, reduces redundancies, and enhances the declarative nature of your code. + +Derived state is a fundamental concept in modern state management, not unique to the Interactivity API. It's also used in other popular state management systems like Redux, where it's called `selectors`, or Preact Signals, where it's known as `computed` values. + +Derived state offers several key benefits that make it an essential part of a well-designed application state, including: + +1. **Single source of truth:** Derived state encourages you to store only the essential, raw data in your state. Any values that can be calculated from this core data become derived state. This approach reduces the risk of inconsistencies in your interactive blocks. + +2. **Automatic updates:** When you use derived state, values are recalculated automatically whenever the underlying data changes. This ensures that all parts of your interactive blocks always have access to the most up-to-date information without manual intervention. + +3. **Simplified state management:** By computing values on-demand rather than storing and updating them manually, you reduce the complexity of your state management logic. This leads to cleaner, more maintainable code. + +4. **Improved performance:** In many cases, derived state can be optimized to recalculate only when necessary, potentially improving your interactive blocks' performance. + +5. **Easier debugging:** With derived state, it's clearer where data originates and how it's transformed. This can make it easier to track down issues in your interactive blocks. + +In essence, derived state allows you to express relationships between different pieces of data in your interactive blocks declaratively, instead of imperatively updating related values whenever something changes. + +_Please, visit [The Reactive and Declarative mindset](./the-reactive-and-declarative-mindset.md) guide to learn more about how to leverage declarative coding in the Interactivity API._ + +You should use derived state: + +- When a part of your global state or local context can be computed from other state values. +- To avoid redundant data that needs to be manually kept in sync. +- To ensure consistency across your interactive blocks by automatically updating derived values. +- To simplify your actions by removing the need to update multiple related state properties. + +### Working with derived state + +- **Initializing the derived state** + + Typically, the derived state should be initialized on the server using the `wp_interactivity_state` function in the exact same way as the global state. + + - When the initial value is known and static, it can be defined directly: + + ```php + wp_interactivity_state( 'myCounterPlugin', array( + 'counter' => 1, // This is global state. + 'double' => 2, // This is derived state. + )); + ``` + + - Or it can be defined by doing the necessary computations: + + ```php + $counter = 1; + $double = $counter * 2; + + wp_interactivity_state( 'myCounterPlugin', array( + 'counter' => $counter, // This is global state. + 'double' => $double, // This is derived state. + )); + ``` + + Regardless of the approach, the initial derived state values will be used during the rendering of the page in PHP, and the HTML can be populated with the correct values. + + _Please, visit [the Server-side Rendering guide](./server-side-rendering.md) to learn more about how directives are processed on the server._ + + The same mechanism applies even when the derived state property depends on the local context. + + ```php + <?php + $counter = 1; + + // This is the local context. + $context = array( 'counter' => $counter ); + + wp_interactivity_state( 'myCounterPlugin', array( + 'double' => $counter * 2, // This is derived state. + )); + ?> + + <div + data-wp-interactive="myCounterPlugin" + <?php echo wp_interactivity_data_wp_context( $context ); ?> + > + <div> + Counter: <span data-wp-text="context.counter"></span> + </div> + <div> + Double: <span data-wp-text="state.double"></span> + </div> + </div> + ``` + + In JavaScript, the derived state is defined using getters: + + ```js + const { state } = store( 'myCounterPlugin', { + state: { + get double() { + return state.counter * 2; + }, + }, + } ); + ``` + + Derived state can depend on local context, or local context and global state at the same time. + + ```js + const { state } = store( 'myCounterPlugin', { + state: { + get double() { + const { counter } = getContext(); + // Depends on local context. + return counter * 2; + }, + get product() { + const { counter } = getContext(); + // Depends on local context and global state. + return counter * state.factor; + }, + }, + } ); + ``` + + In some cases, when the derived state depends on the local context and the local context can change dynamically in the server, instead of the initial derived state, you can use a function (Closure) that calculates it dynamically. + + ```php + <?php + wp_interactivity_state( 'myProductPlugin', array( + 'list' => array( 1, 2, 3 ), + 'factor' => 3, + 'product' => function() { + $state = wp_interactivity_state(); + $context = wp_interactivity_get_context(); + return $context['item'] * $state['factor']; + } + )); + ?> + + <template + data-wp-interactive="myProductPlugin" + data-wp-each="state.list" + > + <span data-wp-text="state.product"></span> + </template> + ``` + + This `data-wp-each` template will render this HTML (directives omitted): + + ```html + <span>3</span> + <span>6</span> + <span>9</span> + ``` + +- **Accessing the derived state** + + In the HTML markup, the syntax for the derived state is the same as the one for the global state, just by referencing `state` in the directive attribute values. + + ```html + <span data-wp-text="state.double"></span> + ``` + + The same happens in JavaScript. Both global state and derived state can be consumed through the `state` property of the store: + + ```js + const { state } = store( 'myCounterPlugin', { + // ... + actions: { + readValues() { + state.counter; // Regular state, returns 1. + state.double; // Derived state, returns 2. + }, + }, + } ); + ``` + + This lack of distinction is intentional, allowing developers to consume both derived and global state uniformly, and making them interchangeable in practice. + + You can also access the derived state from another derived state and, thus, create multiple levels of computed values. + + ```js + const { state } = store( 'myPlugin', { + state: { + get double() { + return state.counter * 2; + }, + get doublePlusOne() { + return state.double + 1; + }, + }, + } ); + ``` + +- **Updating the derived state** + + The derived state cannot be updated directly. To update its values, you need to update the global state or local context on which that derived state depends. + + ```js + const { state } = store( 'myCounterPlugin', { + // ... + actions: { + updateValues() { + state.counter; // Regular state, returns 1. + state.double; // Derived state, returns 2. + + state.counter = 2; + + state.counter; // Regular state, returns 2. + state.double; // Derived state, returns 4. + }, + }, + } ); + ``` + +### Example: Not using derived state vs using derived state + +Let's consider a scenario where there is a counter and the double value needs to be displayed, and let's compare two approaches: one without derived state and one with derived state. + +- **Not using derived state** + + ```js + const { state } = store( 'myCounterPlugin', { + state: { + counter: 1, + double: 2, + }, + actions: { + increment() { + state.counter += 1; + state.double = state.counter * 2; + }, + }, + } ); + ``` + + In this approach, both the `state.counter` and `state.double` values are manually updated in the `increment` action. While this works, it has several drawbacks: + + - It's less declarative. + - It can lead to bugs if `state.counter` is updated from multiple places and developers forget to keep `state.double` in sync. + - It requires more cognitive load to remember to update related values. + +- **Using derived state** + + ```js + const { state } = store( 'myCounterPlugin', { + state: { + counter: 1, + get double() { + return state.counter * 2; + }, + }, + actions: { + increment() { + state.counter += 1; + }, + }, + } ); + ``` + + In this improved version: + + - `state.double` is defined as a getter, automatically deriving its value from `state.counter`. + - The `increment` action only needs to update `state.counter`. + - `state.double` is always guaranteed to have the correct value, regardless of how or where `state.counter` is updated. + +### Example: Using derived state with local context + +Let's now consider a scenario where there is a local context that initializes a counter. + +```js +store( 'myCounterPlugin', { + state: { + get double() { + const { counter } = getContext(); + return counter * 2; + }, + }, + actions: { + increment() { + const context = getContext(); + context.counter += 1; + }, + }, +} ); +``` + +```html +<div data-wp-interactive="myCounterPlugin"> + <!-- This will render "Double: 2" --> + <div data-wp-context='{ "counter": 1 }'> + Double: <span data-wp-text="state.double"></span> + + <!-- This button will increment the local counter. --> + <button data-wp-on-async--click="actions.increment">Increment</button> + </div> + + <!-- This will render "Double: 4" --> + <div data-wp-context='{ "counter": 2 }'> + Double: <span data-wp-text="state.double"></span> + + <!-- This button will increment the local counter. --> + <button data-wp-on-async--click="actions.increment">Increment</button> + </div> +</div> +``` + +In this example, the derived state `state.double` reads from the local context present in each element and returns the correct value for each instance where it is used. + +### Example: Using derived state with both local context and global state + +Let's now consider a scenario where there are a global tax rate and local product prices and calculate the final price, including tax. + +```html +<div + data-wp-interactive="myProductPlugin" + data-wp-context='{ "priceWithoutTax": 100 }' +> + <p>Product Price: $<span data-wp-text="context.priceWithoutTax"></span></p> + <p>Tax Rate: <span data-wp-text="state.taxRatePercentage"></span></p> + <p>Price (inc. tax): $<span data-wp-text="state.priceWithTax"></span></p> +</div> +``` + +```js +const { state } = store( 'myProductPlugin', { + state: { + taxRate: 0.21, + get taxRatePercentage() { + return `${ state.taxRate * 100 }%`; + }, + get priceWithTax() { + const { priceWithoutTax } = getContext(); + return price * ( 1 + state.taxRate ); + }, + }, + actions: { + updateTaxRate( event ) { + // Updates the global tax rate. + state.taxRate = event.target.value; + }, + updatePrice( event ) { + // Updates the local product price. + const context = getContext(); + context.priceWithoutTax = event.target.value; + }, + }, +} ); +``` + +In this example, `priceWithTax` is derived from both the global `taxRate` and the local `priceWithoutTax`. Every time you update the global state or local context through the `updateTaxRate` or `updatePrice` actions, the Interactivity API recomputes the derived state and updates the necessary parts of the DOM. + +By using derived state, you create a more maintainable and less error-prone codebase. It ensures that related state values are always in sync, reduces the complexity of your actions, and makes your code more declarative and easier to reason about. + +## Conclusion + +Remember, the key to effective state management is to keep your state minimal and avoid redundancy. Use derived state to compute values dynamically, and choose between global state and local context based on the scope and requirements of your data. This will lead to a cleaner, more robust architecture that is easier to debug and maintain. diff --git a/docs/toc.json b/docs/toc.json index fa80ee6c4f4404..719ffa344e3744 100644 --- a/docs/toc.json +++ b/docs/toc.json @@ -204,6 +204,19 @@ }, { "docs/reference-guides/interactivity-api/README.md": [ + { + "docs/reference-guides/interactivity-api/core-concepts/README.md": [ + { + "docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md": [] + }, + { + "docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md": [] + }, + { + "docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md": [] + } + ] + }, { "docs/reference-guides/interactivity-api/iapi-quick-start-guide.md": [] }, From a8a202b13ebb87bc44f41154479b0552023c1198 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Mon, 19 Aug 2024 17:16:37 +0530 Subject: [PATCH 0446/1908] Post Author: Add Border Support (#64599) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/block-library/src/post-author/block.json | 12 ++++++++++++ packages/block-library/src/post-author/style.scss | 1 + 2 files changed, 13 insertions(+) diff --git a/packages/block-library/src/post-author/block.json b/packages/block-library/src/post-author/block.json index dde9320841820d..d66498c8ee3df9 100644 --- a/packages/block-library/src/post-author/block.json +++ b/packages/block-library/src/post-author/block.json @@ -64,6 +64,18 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } }, "editorStyle": "wp-block-post-author-editor", diff --git a/packages/block-library/src/post-author/style.scss b/packages/block-library/src/post-author/style.scss index 0b2d63aab44f60..28fd4fad3cf5a7 100644 --- a/packages/block-library/src/post-author/style.scss +++ b/packages/block-library/src/post-author/style.scss @@ -1,6 +1,7 @@ .wp-block-post-author { display: flex; flex-wrap: wrap; + box-sizing: border-box; &__byline { width: 100%; From 31e9078d1209d428dc04b78f0102a7f71c52d928 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Mon, 19 Aug 2024 17:21:43 +0530 Subject: [PATCH 0447/1908] Query Title: Add Border Support (#64581) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/block-library/src/query-title/block.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/block-library/src/query-title/block.json b/packages/block-library/src/query-title/block.json index 2a3c7d9f236995..de3e60214685c2 100644 --- a/packages/block-library/src/query-title/block.json +++ b/packages/block-library/src/query-title/block.json @@ -58,6 +58,18 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } }, "style": "wp-block-query-title" From 1db6ca0c5e79cd89ae1885d9720b822528c5afdd Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Mon, 19 Aug 2024 19:12:56 +0530 Subject: [PATCH 0448/1908] Add border support to file block (#64509) Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/block-library/src/file/block.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/block-library/src/file/block.json b/packages/block-library/src/file/block.json index a5dbaae0c10256..0526120c4dfc1e 100644 --- a/packages/block-library/src/file/block.json +++ b/packages/block-library/src/file/block.json @@ -74,6 +74,18 @@ "link": true } }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } + }, "interactivity": true }, "editorStyle": "wp-block-file-editor", From d69aab423dd9bf8ee4ba8f13264673d2a05eb156 Mon Sep 17 00:00:00 2001 From: JuanMa <juanma.garrido@automattic.com> Date: Mon, 19 Aug 2024 16:23:26 +0100 Subject: [PATCH 0449/1908] fix internal links core-concepts (#64609) --- .../core-concepts/server-side-rendering.md | 2 +- .../the-reactive-and-declarative-mindset.md | 2 +- ...ing-global-state-local-context-and-derived-state.md | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md b/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md index 2032d12d5670b1..8c62bd82eaba90 100644 --- a/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md +++ b/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md @@ -4,7 +4,7 @@ WordPress has always been built on the foundation of server-side rendering. Trad In recent years, modern JavaScript frameworks like Vue, React, or Svelte have revolutionized the way we build web applications. These frameworks provide reactive and declarative programming models that enable developers to create dynamic, interactive user interfaces with ease. -However, when it comes to server-side rendering, these frameworks require a JavaScript-based server, such as NodeJS, to execute their code and generate the initial HTML. This means that PHP-based servers, like WordPress, cannot directly utilize these frameworks without sacrificing their native PHP rendering capabilities. This limitation poses a challenge for WordPress developers who want to leverage the power of reactive and declarative programming while still benefiting from WordPress's traditional server-side rendering strengths. The Interactivity API bridges this gap by bringing [reactive and declarative programming principles](./the-reactive-and-declarative-mindset.md) to WordPress without compromising its server-side rendering foundation. +However, when it comes to server-side rendering, these frameworks require a JavaScript-based server, such as NodeJS, to execute their code and generate the initial HTML. This means that PHP-based servers, like WordPress, cannot directly utilize these frameworks without sacrificing their native PHP rendering capabilities. This limitation poses a challenge for WordPress developers who want to leverage the power of reactive and declarative programming while still benefiting from WordPress's traditional server-side rendering strengths. The Interactivity API bridges this gap by bringing [reactive and declarative programming principles](/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md) to WordPress without compromising its server-side rendering foundation. In this guide, we'll explore how the Interactivity API processes directives on the server, enabling WordPress to deliver interactive, state-aware HTML from the initial page load, while setting the stage for seamless client-side interactivity. diff --git a/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md b/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md index 59940560fe20b6..3760fdf3867802 100644 --- a/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md +++ b/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md @@ -165,7 +165,7 @@ The Interactivity API uses a fine-grained reactivity system. Here's how it works - **Local context**: This is local data that is specific to a particular element and its children. - **Derived State**: In addition to basic state properties, you can define computed properties that automatically update when their dependencies change. - _Please, visit the [Understanding global state, local context and derived state](./undestanding-global-state-local-context-and-derived-state.md) guide to learn more about how to work with the different types of reactive state in the Interactivity API._ + _Please, visit the [Understanding global state, local context and derived state](/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md) guide to learn more about how to work with the different types of reactive state in the Interactivity API._ 2. **Actions**: These are functions, usually triggered by event handlers, that mutate the global state or local context. diff --git a/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md b/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md index 0071f26fc8a333..a2b39fc4c77fb2 100644 --- a/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md +++ b/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md @@ -68,7 +68,7 @@ You should use global state when: </div> ``` - _Please, visit [the Server-side Rendering guide](./server-side-rendering.md) to learn more about how directives are processed on the server._ + _Please, visit [the Server-side Rendering guide](/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md) to learn more about how directives are processed on the server._ In cases where the global state is not used during the rendering of the page in PHP, it can also be defined directly on the client. @@ -189,7 +189,7 @@ You should use global state when: Changes to the global state will automatically trigger updates in any directives that depend on the modified values. - _Please, visit [The Reactive and Declarative mindset](./the-reactive-and-declarative-mindset.md) guide to learn more about how reactivity works in the Interactivity API._ + _Please, visit [The Reactive and Declarative mindset](/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md) guide to learn more about how reactivity works in the Interactivity API._ ### Example: Two interactive blocks using global state to communicate @@ -332,7 +332,7 @@ You should use local context when: Changes to the local context will automatically trigger updates in any directives that depend on the modified values. - _Please, visit [The Reactive and Declarative mindset](./the-reactive-and-declarative-mindset.md) guide to learn more about how reactivity works in the Interactivity API._ + _Please, visit [The Reactive and Declarative mindset](/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md) guide to learn more about how reactivity works in the Interactivity API._ - **Nesting local contexts** @@ -407,7 +407,7 @@ Derived state offers several key benefits that make it an essential part of a we In essence, derived state allows you to express relationships between different pieces of data in your interactive blocks declaratively, instead of imperatively updating related values whenever something changes. -_Please, visit [The Reactive and Declarative mindset](./the-reactive-and-declarative-mindset.md) guide to learn more about how to leverage declarative coding in the Interactivity API._ +_Please, visit [The Reactive and Declarative mindset](/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md) guide to learn more about how to leverage declarative coding in the Interactivity API._ You should use derived state: @@ -445,7 +445,7 @@ You should use derived state: Regardless of the approach, the initial derived state values will be used during the rendering of the page in PHP, and the HTML can be populated with the correct values. - _Please, visit [the Server-side Rendering guide](./server-side-rendering.md) to learn more about how directives are processed on the server._ + _Please, visit [the Server-side Rendering guide](/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md) to learn more about how directives are processed on the server._ The same mechanism applies even when the derived state property depends on the local context. From c828678c8b6f10ecd0daee9cd05e948a523c7138 Mon Sep 17 00:00:00 2001 From: JuanMa <juanma.garrido@automattic.com> Date: Mon, 19 Aug 2024 16:24:34 +0100 Subject: [PATCH 0450/1908] Docs - Interactivity API: Add code concepts to Navigating the Interactivity API docs (#64608) --- .../interactivity-api/README.md | 47 +++++++++---------- .../interactivity-api/core-concepts/README.md | 6 +-- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/docs/reference-guides/interactivity-api/README.md b/docs/reference-guides/interactivity-api/README.md index f5d410a8439f45..3a5bbb84ff159c 100644 --- a/docs/reference-guides/interactivity-api/README.md +++ b/docs/reference-guides/interactivity-api/README.md @@ -16,17 +16,17 @@ For more information about the genesis of the Interactivity API, check out the [ Use the following links to locate the topic you're interested in. If you have never worked with the Interactivity API before, consider reading through the following resources in the order listed. -- **[Requirements](#requirements-of-the-interactivity-api):** Check this section before you start creating your interactive blocks with the Interactivity API. -- **[Quick Start Guide](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/iapi-quick-start-guide/):** Get a custom block using the Interactivity API up and running in less than one minute. -- **[Tutorial: A first look at the Interactivity API](https://developer.wordpress.org/news/2024/04/11/a-first-look-at-the-interactivity-api/)** This article from the [WordPress Developer Blog](https://developer.wordpress.org/news/) is a great way to get introduced to the Interactivity API. -- **[API Reference](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/api-reference/):** To take a deep dive into how the API works internally, the list of Directives, and how the Store works. -- **[Docs and Examples](#docs-examples):** Additional resources to learn/read more about the Interactivity API. +- **[Requirements](#requirements-of-the-interactivity-api):** Check this section before you start creating your interactive blocks with the Interactivity API. +- **[Quick Start Guide](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/iapi-quick-start-guide/):** Get a custom block using the Interactivity API up and running in less than one minute. +- **[Tutorial: A first look at the Interactivity API](https://developer.wordpress.org/news/2024/04/11/a-first-look-at-the-interactivity-api/)** This article from the [WordPress Developer Blog](https://developer.wordpress.org/news/) is a great way to get introduced to the Interactivity API. +- **[Core Concepts](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/core-concepts/)** Gain a better understanding of concepts and mental models related to Interactivity API development from this section. +- **[API Reference](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/api-reference/):** To take a deep dive into how the API works internally, the list of Directives, and how the Store works. +- **[Docs and Examples](#docs-examples):** Additional resources to learn/read more about the Interactivity API. To get a deeper understanding of what the Interactivity API is or find answers to questions you may have about this standard, check the following resources: -- **[About the Interactivity API](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/iapi-about/):** To learn more about the API Goals and the reasoning behind the use of a standard to add interactivity to blocks. -- **[Frequently Asked Questions](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/iapi-faq/):** To find responses to some frequently asked questions about the technology behind and alternatives. - +- **[About the Interactivity API](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/iapi-about/):** To learn more about the API Goals and the reasoning behind the use of a standard to add interactivity to blocks. +- **[Frequently Asked Questions](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/iapi-faq/):** To find responses to some frequently asked questions about the technology behind and alternatives. ## Requirements of the Interactivity API @@ -34,9 +34,9 @@ Interactivity API is included in Core in WordPress 6.5. For versions below, you' It’s also important to highlight that the block creation workflow doesn’t change, and all the [prerequisites](https://developer.wordpress.org/block-editor/getting-started/devenv/) remain the same. These include: -- [Code Editor](https://developer.wordpress.org/block-editor/getting-started/devenv/#code-editor) -- [Node.js development tools](https://developer.wordpress.org/block-editor/getting-started/devenv/#node-js-development-tools) -- [Local WordPress environment (site)](https://developer.wordpress.org/block-editor/getting-started/devenv/#local-wordpress-environment) +- [Code Editor](https://developer.wordpress.org/block-editor/getting-started/devenv/#code-editor) +- [Node.js development tools](https://developer.wordpress.org/block-editor/getting-started/devenv/#node-js-development-tools) +- [Local WordPress environment (site)](https://developer.wordpress.org/block-editor/getting-started/devenv/#local-wordpress-environment) You can start creating interactions once you set up a block development environment and run WordPress 6.5+ (or Gutenberg 17.5+). @@ -56,7 +56,6 @@ Import the store into your `view.js`. Refer to the [store documentation](https:/ import { store } from '@wordpress/interactivity'; ``` - #### Add `interactivity` support to `block.json` To indicate that the block [supports](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/) the Interactivity API features, add `"interactivity": true` to the `supports` attribute of the block's `block.json` file. @@ -84,7 +83,6 @@ The Interactivity API provides the `@wordpress/interactivity` Script Module. Jav The use of `viewScriptModule` also requires the `--experimental-modules` flag for both the [`build`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-scripts/#build) and [`start`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-scripts/#start) scripts of `wp-scripts` to ensure a proper build of the Script Modules. - ```json // package.json { @@ -99,11 +97,9 @@ The use of `viewScriptModule` also requires the `--experimental-modules` flag fo To "activate" the Interactivity API in a DOM element (and its children), add the [`wp-interactive`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity/packages-interactivity-api-reference/#wp-interactive) directive to the DOM element in the block's `render.php` or `save.js` files. - - ```html <div data-wp-interactive="myPlugin"> - <!-- Interactivity API zone --> + <!-- Interactivity API zone --> </div> ``` @@ -113,17 +109,16 @@ Refer to the [`wp-interactive` documentation](https://developer.wordpress.org/bl Here you have some more resources to learn/read more about the Interactivity API: -- [WordPress 6.5 Dev Note](https://make.wordpress.org/core/2024/03/04/interactivity-api-dev-note/) -- [Merge announcement](https://make.wordpress.org/core/2024/02/19/merge-announcement-interactivity-api/) -- [Proposal: The Interactivity API – A better developer experience in building interactive blocks](https://make.wordpress.org/core/2023/03/30/proposal-the-interactivity-api-a-better-developer-experience-in-building-interactive-blocks/) -- [Interactivity API Discussions](https://github.com/WordPress/gutenberg/discussions/52882), especially the [showcase](https://github.com/WordPress/gutenberg/discussions/55642#discussioncomment-9667164) discussions. -- [wpmovies.dev](http://wpmovies.dev/) demo and its [wp-movies-demo](https://github.com/WordPress/wp-movies-demo) repo -- Examples using the Interactivity API at [block-development-examples](https://github.com/WordPress/block-development-examples): - - [`interactivity-api-block-833d15`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/interactivity-api-block-833d15) - - [`interactivity-api-countdown-3cd73e`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/interactivity-api-countdown-3cd73e) - - [`interactivity-api-quiz-1835fa`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/interactivity-api-quiz-1835fa) +- [WordPress 6.5 Dev Note](https://make.wordpress.org/core/2024/03/04/interactivity-api-dev-note/) +- [Merge announcement](https://make.wordpress.org/core/2024/02/19/merge-announcement-interactivity-api/) +- [Proposal: The Interactivity API – A better developer experience in building interactive blocks](https://make.wordpress.org/core/2023/03/30/proposal-the-interactivity-api-a-better-developer-experience-in-building-interactive-blocks/) +- [Interactivity API Discussions](https://github.com/WordPress/gutenberg/discussions/52882), especially the [showcase](https://github.com/WordPress/gutenberg/discussions/55642#discussioncomment-9667164) discussions. +- [wpmovies.dev](http://wpmovies.dev/) demo and its [wp-movies-demo](https://github.com/WordPress/wp-movies-demo) repo +- Examples using the Interactivity API at [block-development-examples](https://github.com/WordPress/block-development-examples): + - [`interactivity-api-block-833d15`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/interactivity-api-block-833d15) + - [`interactivity-api-countdown-3cd73e`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/interactivity-api-countdown-3cd73e) + - [`interactivity-api-quiz-1835fa`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/interactivity-api-quiz-1835fa) <div class="callout"> There's a Tracking Issue opened to ease the coordination of the work related to the Interactivity API Docs: <a href="https://github.com/WordPress/gutenberg/issues/53296">Documentation for the Interactivity API - Tracking Issue #53296</a> </div> - diff --git a/docs/reference-guides/interactivity-api/core-concepts/README.md b/docs/reference-guides/interactivity-api/core-concepts/README.md index ef59fb6075f925..f4e6891c4ff165 100644 --- a/docs/reference-guides/interactivity-api/core-concepts/README.md +++ b/docs/reference-guides/interactivity-api/core-concepts/README.md @@ -2,8 +2,8 @@ This section provides some guides on important concepts and mental models related to Interactivity API development. Use the following links to learn more: -1. **[The Reactive and Declarative mindset](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset):** This guide covers core concepts of reactivity and declarativeness, providing a foundation for effective use of the Interactivity API. +1. **[The Reactive and Declarative mindset](/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md):** This guide covers core concepts of reactivity and declarativeness, providing a foundation for effective use of the Interactivity API. -2. **[Understanding global state, local context and derived state](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state):** The guide explains how to effectively use global state, local context, and derived state within the Interactivity API emphasizing the importance of choosing the appropriate state management technique based on the scope and requirements of your data. +2. **[Understanding global state, local context and derived state](/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md):** The guide explains how to effectively use global state, local context, and derived state within the Interactivity API emphasizing the importance of choosing the appropriate state management technique based on the scope and requirements of your data. -3. **[Server-side rendering: Processing directives on the server](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/core-concepts/server-side-rendering):** The Interactivity API allows WordPress to use server-side rendering to create interactive and state-aware HTML, smoothly connected with client-side features while maintaining performance and SEO benefits. +3. **[Server-side rendering: Processing directives on the server](/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md):** The Interactivity API allows WordPress to use server-side rendering to create interactive and state-aware HTML, smoothly connected with client-side features while maintaining performance and SEO benefits. From 9c9f6535cdc3cd57a3b8583ea6292a2c90552ab3 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 20 Aug 2024 12:46:20 +0900 Subject: [PATCH 0451/1908] Add 40px size lint rule for Block Editor typography components (#64591) * Add 40px size lint rule for Block Editor typography components * Exclude all test and story files --------- Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .eslintrc.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index 8f9b2d3337e18e..25173a9f0e8a82 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -280,7 +280,7 @@ module.exports = { { files: [ 'packages/*/src/**/*.[tj]s?(x)' ], excludedFiles: [ - 'packages/components/src/**/@(test|stories)/**', + 'packages/*/src/**/@(test|stories)/**', '**/*.@(native|ios|android).js', ], rules: { @@ -316,9 +316,12 @@ module.exports = { 'ComboboxControl', 'CustomSelectControl', 'DimensionControl', + 'FontAppearanceControl', + 'FontFamilyControl', 'FontSizePicker', 'FormTokenField', 'InputControl', + 'LineHeightControl', 'NumberControl', 'RangeControl', 'TextControl', From 79340eb0791d9499a68cf670b9a2fe320940508f Mon Sep 17 00:00:00 2001 From: Christian Weiske <cweiske+github.com@cweiske.de> Date: Tue, 20 Aug 2024 09:01:25 +0200 Subject: [PATCH 0452/1908] Note about image sizes in MediaUpload::onSelect (#64616) Document that not all image sizes are available when an image has been selected in MediaUpload. Co-authored-by: cweiske <cweiske@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-editor/src/components/media-upload/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/block-editor/src/components/media-upload/README.md b/packages/block-editor/src/components/media-upload/README.md index 592d64e42f497d..27bbc93d8a2b65 100644 --- a/packages/block-editor/src/components/media-upload/README.md +++ b/packages/block-editor/src/components/media-upload/README.md @@ -105,6 +105,8 @@ Callback called when the media modal is closed after media is selected. This is called subsequent to `onClose` when media is selected. The selected media are passed as an argument. +The `image.sizes.full` resolution does always exist. Other defined sizes are only available when the image is larger and thus could be scaled down. + - Type: `Function` - Required: Yes - Platform: Web | Mobile From 8ef31233e593176e234aa6dff469af5d96ced10b Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 20 Aug 2024 11:08:42 +0200 Subject: [PATCH 0453/1908] RadioControl: label radio group using fieldset and legend (#64582) * Swap BaseControl for fieldset + legend * Add help text * Use group help text to describe the fieldset instead of each individual option * CHANGELOG * Re-apply ID and classname * Render visually hidden label as div * Fix spacing in latest post block * Increase margin-top override specificity * Remove redundant styles * Use legend even when the label is visually hidden * Test that group labelling works as expected also when label is visually hidden * typo * Revert to original classname order * Move styles from styles.scss to editor.scss --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../block-library/src/latest-posts/edit.js | 1 + .../src/latest-posts/editor.scss | 11 +++ packages/components/CHANGELOG.md | 1 + .../components/src/radio-control/index.tsx | 48 ++++++----- .../components/src/radio-control/style.scss | 13 ++- .../src/radio-control/test/index.tsx | 83 ++++++++++--------- .../src/components/post-discussion/style.scss | 9 -- .../src/components/post-format/style.scss | 6 -- .../src/components/post-status/style.scss | 19 ----- .../src/components/site-discussion/style.scss | 14 ---- 10 files changed, 96 insertions(+), 109 deletions(-) diff --git a/packages/block-library/src/latest-posts/edit.js b/packages/block-library/src/latest-posts/edit.js index 533e9621fd4f2b..b02747bb1c1d8e 100644 --- a/packages/block-library/src/latest-posts/edit.js +++ b/packages/block-library/src/latest-posts/edit.js @@ -242,6 +242,7 @@ export default function LatestPostsEdit( { attributes, setAttributes } ) { /> { displayPostContent && ( <RadioControl + className="wp-block-latest-posts__post-content-radio" label={ __( 'Show:' ) } selected={ displayPostContentRadio } options={ [ diff --git a/packages/block-library/src/latest-posts/editor.scss b/packages/block-library/src/latest-posts/editor.scss index fe901480974461..aaab74cc0ef2d6 100644 --- a/packages/block-library/src/latest-posts/editor.scss +++ b/packages/block-library/src/latest-posts/editor.scss @@ -18,3 +18,14 @@ padding-left: 0; } } + +// Apply the same styles that would be applied to +// ".block-editor-block-inspector .components-base-control" +// (see packages/block-editor/src/components/block-inspector/style.scss) +.wp-block-latest-posts__post-content-radio { + margin-bottom: #{ $grid-unit-30 }; + + &:last-child { + margin-bottom: $grid-unit-10; + } +} diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index da44a5837bb816..4b1095db90327d 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -61,6 +61,7 @@ - `RangeControl`: disable reset button when the current value is equal to the reset value ([#64579](https://github.com/WordPress/gutenberg/pull/64579)). - `RangeControl`: tweak mark and label absolute positioning ([#64487](https://github.com/WordPress/gutenberg/pull/64487)). +- `RadioGroup`: use fieldset and legend to group radio inputs ([#64582](https://github.com/WordPress/gutenberg/pull/64582)). ### Internal diff --git a/packages/components/src/radio-control/index.tsx b/packages/components/src/radio-control/index.tsx index c574e5af539def..29927558c58cd4 100644 --- a/packages/components/src/radio-control/index.tsx +++ b/packages/components/src/radio-control/index.tsx @@ -16,8 +16,8 @@ import BaseControl from '../base-control'; import type { WordPressComponentProps } from '../context'; import type { RadioControlProps } from './types'; import { VStack } from '../v-stack'; -import { useBaseControlProps } from '../base-control/hooks'; import { StyledHelp } from '../base-control/styles/base-control-styles'; +import { VisuallyHidden } from '../visually-hidden'; function generateOptionDescriptionId( radioGroupId: string, index: number ) { return `${ radioGroupId }-${ index }-option-description`; @@ -27,6 +27,10 @@ function generateOptionId( radioGroupId: string, index: number ) { return `${ radioGroupId }-${ index }`; } +function generateHelpId( radioGroupId: string ) { + return `${ radioGroupId }__help`; +} + /** * Render a user interface to select the user type using radio inputs. * @@ -75,24 +79,24 @@ export function RadioControl( const onChangeValue = ( event: ChangeEvent< HTMLInputElement > ) => onChange( event.target.value ); - // Use `useBaseControlProps` to get the id of the help text. - const { - controlProps: { 'aria-describedby': helpTextId }, - } = useBaseControlProps( { id, help } ); - if ( ! options?.length ) { return null; } return ( - <BaseControl - __nextHasNoMarginBottom - label={ label } + <fieldset id={ id } - hideLabelFromVision={ hideLabelFromVision } - help={ help } className={ clsx( className, 'components-radio-control' ) } + aria-describedby={ !! help ? generateHelpId( id ) : undefined } > + { hideLabelFromVision ? ( + <VisuallyHidden as="legend">{ label }</VisuallyHidden> + ) : ( + <BaseControl.VisualLabel as="legend"> + { label } + </BaseControl.VisualLabel> + ) } + <VStack spacing={ 3 } className={ clsx( 'components-radio-control__group-wrapper', { @@ -113,14 +117,9 @@ export function RadioControl( onChange={ onChangeValue } checked={ option.value === selected } aria-describedby={ - clsx( [ - !! option.description && - generateOptionDescriptionId( - id, - index - ), - helpTextId, - ] ) || undefined + !! option.description + ? generateOptionDescriptionId( id, index ) + : undefined } { ...additionalProps } /> @@ -142,7 +141,16 @@ export function RadioControl( </div> ) ) } </VStack> - </BaseControl> + { !! help && ( + <StyledHelp + __nextHasNoMarginBottom + id={ generateHelpId( id ) } + className="components-base-control__help" + > + { help } + </StyledHelp> + ) } + </fieldset> ); } diff --git a/packages/components/src/radio-control/style.scss b/packages/components/src/radio-control/style.scss index e9732558f2901e..e3dcb8d1e58270 100644 --- a/packages/components/src/radio-control/style.scss +++ b/packages/components/src/radio-control/style.scss @@ -1,3 +1,12 @@ +.components-radio-control { + border: 0; + margin: 0; + padding: 0; + + font-family: $default-font; + font-size: $default-font-size; +} + .components-radio-control__group-wrapper.has-help { margin-block-end: $grid-unit-15; } @@ -57,5 +66,7 @@ // Override the top margin of the StyledHelp component from BaseControl. // TODO: we should tweak the StyledHelp component to not have a top margin. - margin-top: 0; + &.components-radio-control__option-description { + margin-top: 0; + } } diff --git a/packages/components/src/radio-control/test/index.tsx b/packages/components/src/radio-control/test/index.tsx index 0be166513a9a4d..7e30744d96b826 100644 --- a/packages/components/src/radio-control/test/index.tsx +++ b/packages/components/src/radio-control/test/index.tsx @@ -56,6 +56,47 @@ describe.each( [ const [ , Component ] = modeAndComponent; describe( 'semantics and labelling', () => { + it( 'should group all radios under a fieldset with an accessible label (legend)', () => { + const onChangeSpy = jest.fn(); + render( + <Component { ...defaultProps } onChange={ onChangeSpy } /> + ); + + expect( + screen.getByRole( 'group', { name: defaultProps.label } ) + ).toBeVisible(); + } ); + + it( 'should group all radios under a fieldset with an accessible label even when the label is visually hidden', () => { + const onChangeSpy = jest.fn(); + render( + <Component + { ...defaultProps } + hideLabelFromVision + onChange={ onChangeSpy } + /> + ); + + expect( + screen.getByRole( 'group', { name: defaultProps.label } ) + ).toBeVisible(); + } ); + + it( 'should describe the radio group with the help text', () => { + const onChangeSpy = jest.fn(); + render( + <Component + { ...defaultProps } + help="Test help text" + onChange={ onChangeSpy } + /> + ); + + expect( + screen.getByRole( 'group', { name: defaultProps.label } ) + ).toHaveAccessibleDescription( 'Test help text' ); + } ); + it( 'should render radio inputs with accessible labels', () => { const onChangeSpy = jest.fn(); render( @@ -101,46 +142,7 @@ describe.each( [ ).toHaveAccessibleName( defaultProps.options[ 1 ].label ); } ); - it( 'should use the group help text to describe individual options', () => { - const onChangeSpy = jest.fn(); - render( - <Component - { ...defaultProps } - onChange={ onChangeSpy } - selected={ defaultProps.options[ 1 ].value } - help="Select your favorite animal." - /> - ); - - for ( const option of defaultProps.options ) { - expect( - screen.getByRole( 'radio', { name: option.label } ) - ).toHaveAccessibleDescription( 'Select your favorite animal.' ); - } - } ); - it( 'should use the option description text to describe individual options', () => { - const onChangeSpy = jest.fn(); - render( - <Component - { ...defaultPropsWithDescriptions } - onChange={ onChangeSpy } - selected={ defaultProps.options[ 1 ].value } - /> - ); - - let index = 1; - for ( const option of defaultProps.options ) { - expect( - screen.getByRole( 'radio', { name: option.label } ) - ).toHaveAccessibleDescription( - `This is the option number ${ index }.` - ); - index += 1; - } - } ); - - it( 'should use both the option description text and the group help text to describe individual options', () => { const onChangeSpy = jest.fn(); render( <Component @@ -151,12 +153,13 @@ describe.each( [ /> ); + // Group help text should not be used to describe individual options. let index = 1; for ( const option of defaultProps.options ) { expect( screen.getByRole( 'radio', { name: option.label } ) ).toHaveAccessibleDescription( - `This is the option number ${ index }. Select your favorite animal` + `This is the option number ${ index }.` ); index += 1; } diff --git a/packages/editor/src/components/post-discussion/style.scss b/packages/editor/src/components/post-discussion/style.scss index b2d65c9aa7cf3f..d5320605579e41 100644 --- a/packages/editor/src/components/post-discussion/style.scss +++ b/packages/editor/src/components/post-discussion/style.scss @@ -2,15 +2,6 @@ // sidebar width - popover padding - form margin min-width: $sidebar-width - $grid-unit-20 - $grid-unit-20; margin: $grid-unit-10; - - .components-radio-control__option { - align-items: flex-start; - } - - .components-radio-control__label .components-text { - display: block; - margin-top: $grid-unit-05; - } } .editor-post-discussion__panel-toggle { diff --git a/packages/editor/src/components/post-format/style.scss b/packages/editor/src/components/post-format/style.scss index ec3a8b1626b543..9c893f36bcc16c 100644 --- a/packages/editor/src/components/post-format/style.scss +++ b/packages/editor/src/components/post-format/style.scss @@ -7,9 +7,3 @@ min-width: $sidebar-width - $grid-unit-20 - $grid-unit-20; margin: $grid-unit-10; } - -.editor-post-format__options { - .components-base-control__field > .components-v-stack { - gap: $grid-unit-15; - } -} diff --git a/packages/editor/src/components/post-status/style.scss b/packages/editor/src/components/post-status/style.scss index bfd9de46234da3..c601d887d68c7f 100644 --- a/packages/editor/src/components/post-status/style.scss +++ b/packages/editor/src/components/post-status/style.scss @@ -18,25 +18,6 @@ padding: $grid-unit-20; } - .editor-change-status__options { - .components-base-control__field > .components-v-stack { - gap: $grid-unit-15; - } - - // TODO: it's not great to override component styles.. This might be resolved - // by the new radio control component. - .components-radio-control__option { - align-items: flex-start; - } - - label { - .components-text { - display: block; - margin-top: $grid-unit-05; - } - } - } - .editor-change-status__password-legend { padding: 0; margin-bottom: $grid-unit-10; diff --git a/packages/editor/src/components/site-discussion/style.scss b/packages/editor/src/components/site-discussion/style.scss index 2c54424207ea5c..dc0608f0cf3ab1 100644 --- a/packages/editor/src/components/site-discussion/style.scss +++ b/packages/editor/src/components/site-discussion/style.scss @@ -3,17 +3,3 @@ padding: $grid-unit-20; } -.editor-site-discussion__options { - // TODO: it's not great to override component styles.. This might be resolved - // by the new radio control component. - .components-radio-control__option { - align-items: flex-start; - } - - label { - .components-text { - display: block; - margin-top: $grid-unit-05; - } - } -} From c4a77c5813603c4a8ef9702008f3c6dae8dae4b9 Mon Sep 17 00:00:00 2001 From: arthur791004 <arthur.chu@automattic.com> Date: Tue, 20 Aug 2024 17:19:51 +0800 Subject: [PATCH 0454/1908] Additional CSS: Localise the link if it exists (#64603) --- packages/edit-site/src/components/global-styles/screen-css.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/screen-css.js b/packages/edit-site/src/components/global-styles/screen-css.js index e49207aaea2241..b6d8cb7fd7086e 100644 --- a/packages/edit-site/src/components/global-styles/screen-css.js +++ b/packages/edit-site/src/components/global-styles/screen-css.js @@ -34,7 +34,9 @@ function ScreenCSS() { <> { description } <ExternalLink - href="https://developer.wordpress.org/advanced-administration/wordpress/css/" + href={ __( + 'https://developer.wordpress.org/advanced-administration/wordpress/css/' + ) } className="edit-site-global-styles-screen-css-help-link" > { __( 'Learn more about CSS' ) } From 8384d2a9f3762828cc90969ffc9e658647187be5 Mon Sep 17 00:00:00 2001 From: JuanMa <juanma.garrido@automattic.com> Date: Tue, 20 Aug 2024 10:32:07 +0100 Subject: [PATCH 0455/1908] Docs - Dataviews: Better explanation of the "elements" property and its connection to the "filterBy" property (#64633) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * better explanation of the elements property * Update packages/dataviews/README.md Co-authored-by: André <583546+oandregal@users.noreply.github.com> * Update packages/dataviews/README.md Co-authored-by: André <583546+oandregal@users.noreply.github.com> --------- Co-authored-by: André <583546+oandregal@users.noreply.github.com> --- packages/dataviews/README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 368880b69b14f0..6c1e2af26386c7 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -120,13 +120,20 @@ Each field is an object with the following properties: - `label`: the field's name to be shown in the UI. - `getValue`: function that returns the value of the field, defaults to `field[id]`. - `render`: function that renders the field. Optional, `getValue` will be used if `render` is not defined. -- `elements`: the set of valid values for the field's value. +- <code id="fields-elements">elements</code>: The list of options to pick from when using the field as a filter or when editing (DataForm component). It expects an array of objects with the following properties: + + - `value`: The id of the value to filter to (for internal use) + - `label`: The text that will be displayed in the UI for the item. + - `description`: A longer description that describes the element, to also be displayed. Optional. + + To enable the filter by a field we just need to set a proper value to the `elements` property of the field we'd like to filter by. + - `type`: the type of the field. See "Field types". - `enableSorting`: whether the data can be sorted by the given field. True by default. - `enableHiding`: whether the field can be hidden. True by default. - `enableGlobalSearch`: whether the field is searchable. False by default. -- `filterBy`: configuration for the filters. - - `operators`: the list of operators supported by the field. +- `filterBy`: configuration for the filters enabled by the `elements` property. + - `operators`: the list of [operators](#operators) supported by the field. - `isPrimary`: whether it is a primary filter. A primary filter is always visible and is not listed in the "Add filter" component, except for the list layout where it behaves like a secondary filter. ### `view`: `object` From 7f1523c2432c1e47423abe0ba4169b3f4c11c072 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 20 Aug 2024 13:37:53 +0400 Subject: [PATCH 0456/1908] Block Editor: Use hooks instead of HoC in 'MultiSelectionInspector' (#64634) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../multi-selection-inspector/index.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/components/multi-selection-inspector/index.js b/packages/block-editor/src/components/multi-selection-inspector/index.js index 14eda5f930cada..f5e7f696347686 100644 --- a/packages/block-editor/src/components/multi-selection-inspector/index.js +++ b/packages/block-editor/src/components/multi-selection-inspector/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { sprintf, _n } from '@wordpress/i18n'; -import { withSelect } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; import { serialize } from '@wordpress/blocks'; import { count as wordCount } from '@wordpress/wordcount'; import { copy } from '@wordpress/icons'; @@ -13,7 +13,13 @@ import { copy } from '@wordpress/icons'; import BlockIcon from '../block-icon'; import { store as blockEditorStore } from '../../store'; -function MultiSelectionInspector( { blocks } ) { +export default function MultiSelectionInspector() { + const { blocks } = useSelect( ( select ) => { + const { getMultiSelectedBlocks } = select( blockEditorStore ); + return { + blocks: getMultiSelectedBlocks(), + }; + }, [] ); const words = wordCount( serialize( blocks ), 'words' ); return ( @@ -38,10 +44,3 @@ function MultiSelectionInspector( { blocks } ) { </div> ); } - -export default withSelect( ( select ) => { - const { getMultiSelectedBlocks } = select( blockEditorStore ); - return { - blocks: getMultiSelectedBlocks(), - }; -} )( MultiSelectionInspector ); From 3ed18120972d7af4a1e6445d6e719dd911727504 Mon Sep 17 00:00:00 2001 From: Rishit Gupta <rishitgupta2013@gmail.com> Date: Tue, 20 Aug 2024 05:40:38 -0400 Subject: [PATCH 0457/1908] `ColorPalette`: partial support of `color-mix()` CSS colors (#64224) * Fix incorrect dropdown label with selected color value * Fix normalizeColorValue function * Add isSimpleCSSColor function * Fix isSimpleCSSColor function, add early return * Update CHANGELOG.md with ColorPalette: partial support of color-mix() CSS colors * Update packages/components/CHANGELOG.md --------- Co-authored-by: Rishit30G <rishit30g@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/color-palette/utils.ts | 33 +++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 4b1095db90327d..c03d2455962c99 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -88,6 +88,7 @@ ### Enhancements +- `ColorPalette`: partial support of `color-mix()` CSS colors ([#64224](https://github.com/WordPress/gutenberg/pull/64224)). - `TimeInput`: Expose as subcomponent of `TimePicker` ([#63145](https://github.com/WordPress/gutenberg/pull/63145)). - `RadioControl`: add support for option help text ([#63751](https://github.com/WordPress/gutenberg/pull/63751)). - `SelectControl`: Infer `value` type from `options` ([#64069](https://github.com/WordPress/gutenberg/pull/64069)). diff --git a/packages/components/src/color-palette/utils.ts b/packages/components/src/color-palette/utils.ts index 79141bf752eb73..cfe909c580f8bc 100644 --- a/packages/components/src/color-palette/utils.ts +++ b/packages/components/src/color-palette/utils.ts @@ -17,6 +17,18 @@ import type { ColorObject, ColorPaletteProps, PaletteObject } from './types'; extend( [ namesPlugin, a11yPlugin ] ); +/** + * Checks if a color value is a simple CSS color. + * + * @param value The color value to check. + * @return A boolean indicating whether the color value is a simple CSS color. + */ +const isSimpleCSSColor = ( value: string ): boolean => { + const valueIsCssVariable = /var\(/.test( value ?? '' ); + const valueIsColorMix = /color-mix\(/.test( value ?? '' ); + return ! valueIsCssVariable && ! valueIsColorMix; +}; + export const extractColorNameFromCurrentValue = ( currentValue?: ColorPaletteProps[ 'value' ], colors: ColorPaletteProps[ 'colors' ] = [], @@ -25,11 +37,12 @@ export const extractColorNameFromCurrentValue = ( if ( ! currentValue ) { return ''; } - - const currentValueIsCssVariable = /^var\(/.test( currentValue ); - const normalizedCurrentValue = currentValueIsCssVariable - ? currentValue - : colord( currentValue ).toHex(); + const currentValueIsSimpleColor = currentValue + ? isSimpleCSSColor( currentValue ) + : false; + const normalizedCurrentValue = currentValueIsSimpleColor + ? colord( currentValue ).toHex() + : currentValue; // Normalize format of `colors` to simplify the following loop type normalizedPaletteObject = { colors: ColorObject[] }; @@ -38,9 +51,9 @@ export const extractColorNameFromCurrentValue = ( : [ { colors: colors as ColorObject[] } ]; for ( const { colors: paletteColors } of colorPalettes ) { for ( const { name: colorName, color: colorValue } of paletteColors ) { - const normalizedColorValue = currentValueIsCssVariable - ? colorValue - : colord( colorValue ).toHex(); + const normalizedColorValue = currentValueIsSimpleColor + ? colord( colorValue ).toHex() + : colorValue; if ( normalizedCurrentValue === normalizedColorValue ) { return colorName; @@ -79,9 +92,9 @@ export const normalizeColorValue = ( value: string | undefined, element: HTMLElement | null ) => { - const currentValueIsCssVariable = /^var\(/.test( value ?? '' ); + const valueIsSimpleColor = value ? isSimpleCSSColor( value ) : false; - if ( ! currentValueIsCssVariable || element === null ) { + if ( valueIsSimpleColor || element === null ) { return value; } From 07c2a8e9f7aa185c20ff165e1267f216fbba8b79 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 20 Aug 2024 13:12:21 +0200 Subject: [PATCH 0458/1908] Performance: Fetch permissions for visible patterns only (#64606) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/page-patterns/index.js | 6 +- .../components/page-patterns/use-patterns.js | 63 ++++++++++--------- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index 66d2d25a4b8f04..be3bb7429c32f9 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -23,7 +23,7 @@ import { } from '../../utils/constants'; import usePatternSettings from './use-pattern-settings'; import { unlock } from '../../lock-unlock'; -import usePatterns from './use-patterns'; +import usePatterns, { useAugmentPatternsWithPermissions } from './use-patterns'; import PatternsHeader from './header'; import { useEditPostAction } from '../dataviews-actions'; import { @@ -136,6 +136,8 @@ export default function DataviewsPatterns() { return filterSortAndPaginate( patterns, viewWithoutFilters, fields ); }, [ patterns, view, fields, type ] ); + const dataWithPermissions = useAugmentPatternsWithPermissions( data ); + const templatePartActions = usePostActions( { postType: TEMPLATE_PART_POST_TYPE, context: 'list', @@ -175,7 +177,7 @@ export default function DataviewsPatterns() { paginationInfo={ paginationInfo } fields={ fields } actions={ actions } - data={ data || EMPTY_ARRAY } + data={ dataWithPermissions || EMPTY_ARRAY } getItemId={ ( item ) => item.name ?? item.id } isLoading={ isResolving } view={ view } diff --git a/packages/edit-site/src/components/page-patterns/use-patterns.js b/packages/edit-site/src/components/page-patterns/use-patterns.js index 2947088bb19b5f..f32e278e6354f5 100644 --- a/packages/edit-site/src/components/page-patterns/use-patterns.js +++ b/packages/edit-site/src/components/page-patterns/use-patterns.js @@ -256,12 +256,44 @@ const selectUserPatterns = createSelector( ] ); +export function useAugmentPatternsWithPermissions( patterns ) { + const idsAndTypes = useMemo( + () => + patterns + ?.filter( ( record ) => record.type !== PATTERN_TYPES.theme ) + .map( ( record ) => [ record.type, record.id ] ) ?? [], + [ patterns ] + ); + + const permissions = useSelect( + ( select ) => { + const { getEntityRecordPermissions } = unlock( + select( coreStore ) + ); + return idsAndTypes.reduce( ( acc, [ type, id ] ) => { + acc[ id ] = getEntityRecordPermissions( 'postType', type, id ); + return acc; + }, {} ); + }, + [ idsAndTypes ] + ); + + return useMemo( + () => + patterns?.map( ( record ) => ( { + ...record, + permissions: permissions?.[ record.id ] ?? {}, + } ) ) ?? [], + [ patterns, permissions ] + ); +} + export const usePatterns = ( postType, categoryId, { search = '', syncStatus } = {} ) => { - const { patterns, ...rest } = useSelect( + return useSelect( ( select ) => { if ( postType === TEMPLATE_PART_POST_TYPE ) { return selectTemplateParts( select, categoryId, search ); @@ -284,35 +316,6 @@ export const usePatterns = ( }, [ categoryId, postType, search, syncStatus ] ); - - const ids = useMemo( - () => patterns?.map( ( record ) => record.id ) ?? [], - [ patterns ] - ); - - const permissions = useSelect( - ( select ) => { - const { getEntityRecordsPermissions } = unlock( - select( coreStore ) - ); - return getEntityRecordsPermissions( 'postType', postType, ids ); - }, - [ ids, postType ] - ); - - const patternsWithPermissions = useMemo( - () => - patterns?.map( ( record, index ) => ( { - ...record, - permissions: permissions[ index ], - } ) ) ?? [], - [ patterns, permissions ] - ); - - return { - ...rest, - patterns: patternsWithPermissions, - }; }; export default usePatterns; From ebc9865083d4f9ebb07d24b48ca40dd9c322ba58 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:58:52 +0300 Subject: [PATCH 0459/1908] Ariakit: Update to v0.4.10 (#64637) * Ariakit: Update to v0.4.9 * CHANGELOG * Deduplicate some ariakit dependencies * TabPanel: keep tabs accessible when disabled * Tab: enable accessibleWhenDisabled specifically * Bump to 0.4.10 * Revert "TabPanel: keep tabs accessible when disabled" This reverts commit 44ede08ef4976d1f683690fd504fa78c833d0c30. * Revert "Tab: enable accessibleWhenDisabled specifically" This reverts commit 312804105575044a83d6086268ec50cee4da26bb. * Fix CHANGELOG Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> --------- Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: diegohaz <hazdiego@git.wordpress.org> --- package-lock.json | 135 +++++++++++++------------------ package.json | 2 +- packages/components/CHANGELOG.md | 4 +- packages/components/package.json | 2 +- packages/dataviews/package.json | 2 +- 5 files changed, 59 insertions(+), 86 deletions(-) diff --git a/package-lock.json b/package-lock.json index ddfec3a5dddc63..8db4860e895854 100644 --- a/package-lock.json +++ b/package-lock.json @@ -86,7 +86,7 @@ "@actions/core": "1.9.1", "@actions/github": "5.0.0", "@apidevtools/json-schema-ref-parser": "11.6.4", - "@ariakit/test": "^0.4.0", + "@ariakit/test": "^0.4.2", "@babel/core": "7.24.3", "@babel/plugin-proposal-export-namespace-from": "7.18.9", "@babel/plugin-syntax-jsx": "7.24.1", @@ -1527,14 +1527,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@ariakit/core": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.9.tgz", + "integrity": "sha512-nV0B/OTK/0iB+P9RC7fudznYZ8eR6rR1F912Zc54e3+wSW5RrRvNOiRxyMrgENidd4R7cCMDw77XJLSBLKgEPQ==" + }, "node_modules/@ariakit/test": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@ariakit/test/-/test-0.4.0.tgz", - "integrity": "sha512-AcrppK61/AbsMDyDS3AxY3WXI6fcL+WedNpJm44Qx603dVYkS/potk0PrD1MfdC6aRt+2bRRj0n9dLN5lVMtbg==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@ariakit/test/-/test-0.4.2.tgz", + "integrity": "sha512-WXAAiAyTaHV9klntOB81Y+YHyA5iGxy9wXCmjQOfYK5InsuIour+7TVXICUxn2NF0XD6j6OoEJbCVDJ2Y46xEA==", "dev": true, - "license": "MIT", "dependencies": { - "@ariakit/core": "0.4.7", + "@ariakit/core": "0.4.9", "@testing-library/dom": "^8.0.0 || ^9.0.0 || ^10.0.0" }, "peerDependencies": { @@ -1554,12 +1558,6 @@ } } }, - "node_modules/@ariakit/test/node_modules/@ariakit/core": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.7.tgz", - "integrity": "sha512-GUy/3ZY4kW1KdYHtMZRrRlj5FYbZTAyHlimxHI7Zs0xsC+kAzIf8lopnf67Y9IYLgEMr37KosIV7kwpkJpNs5Q==", - "dev": true - }, "node_modules/@aw-web-design/x-default-browser": { "version": "1.4.126", "resolved": "https://registry.npmjs.org/@aw-web-design/x-default-browser/-/x-default-browser-1.4.126.tgz", @@ -52622,7 +52620,7 @@ "version": "28.5.0", "license": "GPL-2.0-or-later", "dependencies": { - "@ariakit/react": "^0.4.7", + "@ariakit/react": "^0.4.10", "@babel/runtime": "^7.16.0", "@emotion/cache": "^11.7.1", "@emotion/css": "^11.7.1", @@ -52678,17 +52676,12 @@ "react-dom": "^18.0.0" } }, - "packages/components/node_modules/@ariakit/core": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.7.tgz", - "integrity": "sha512-GUy/3ZY4kW1KdYHtMZRrRlj5FYbZTAyHlimxHI7Zs0xsC+kAzIf8lopnf67Y9IYLgEMr37KosIV7kwpkJpNs5Q==" - }, "packages/components/node_modules/@ariakit/react": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.7.tgz", - "integrity": "sha512-uUruuCo1M0Nj2oq1nTwDfUlVTLuoI9xeHP75EkuXX46lg5hzE5vVWbSMO1D6MCy7UwrUx2Ts4IqxdKr97suTwQ==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.10.tgz", + "integrity": "sha512-c1+6sNLj57aAXrBZMCVGG+OXeFrPAG0TV1jT7oPJcN/KLRs3aCuO3CCJVep/eKepFzzK01kNRGYX3wPT1TXPNw==", "dependencies": { - "@ariakit/react-core": "0.4.7" + "@ariakit/react-core": "0.4.10" }, "funding": { "type": "opencollective", @@ -52700,11 +52693,11 @@ } }, "packages/components/node_modules/@ariakit/react-core": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.7.tgz", - "integrity": "sha512-OogUyQ20cxkRNRuqLI05JbmpR4Lr5HwhUIqnb/sipzt6bkg/3wCXEnUAjfxg3nPjLTMjJ8+ODWmPC9JMJTW/yg==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.10.tgz", + "integrity": "sha512-r6DZmtHBmSoOj848+RpBwdZy/55YxPhMhfH14JIO2OLn1F6iSFkQwR7AAGpIrlYycWJFSF7KrQu50O+SSfFJdQ==", "dependencies": { - "@ariakit/core": "0.4.7", + "@ariakit/core": "0.4.9", "@floating-ui/dom": "^1.0.0", "use-sync-external-store": "^1.2.0" }, @@ -52981,7 +52974,7 @@ "version": "4.1.0", "license": "GPL-2.0-or-later", "dependencies": { - "@ariakit/react": "^0.4.7", + "@ariakit/react": "^0.4.10", "@babel/runtime": "^7.16.0", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", @@ -53003,17 +52996,12 @@ "react": "^18.0.0" } }, - "packages/dataviews/node_modules/@ariakit/core": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.7.tgz", - "integrity": "sha512-GUy/3ZY4kW1KdYHtMZRrRlj5FYbZTAyHlimxHI7Zs0xsC+kAzIf8lopnf67Y9IYLgEMr37KosIV7kwpkJpNs5Q==" - }, "packages/dataviews/node_modules/@ariakit/react": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.7.tgz", - "integrity": "sha512-uUruuCo1M0Nj2oq1nTwDfUlVTLuoI9xeHP75EkuXX46lg5hzE5vVWbSMO1D6MCy7UwrUx2Ts4IqxdKr97suTwQ==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.10.tgz", + "integrity": "sha512-c1+6sNLj57aAXrBZMCVGG+OXeFrPAG0TV1jT7oPJcN/KLRs3aCuO3CCJVep/eKepFzzK01kNRGYX3wPT1TXPNw==", "dependencies": { - "@ariakit/react-core": "0.4.7" + "@ariakit/react-core": "0.4.10" }, "funding": { "type": "opencollective", @@ -53025,11 +53013,11 @@ } }, "packages/dataviews/node_modules/@ariakit/react-core": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.7.tgz", - "integrity": "sha512-OogUyQ20cxkRNRuqLI05JbmpR4Lr5HwhUIqnb/sipzt6bkg/3wCXEnUAjfxg3nPjLTMjJ8+ODWmPC9JMJTW/yg==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.10.tgz", + "integrity": "sha512-r6DZmtHBmSoOj848+RpBwdZy/55YxPhMhfH14JIO2OLn1F6iSFkQwR7AAGpIrlYycWJFSF7KrQu50O+SSfFJdQ==", "dependencies": { - "@ariakit/core": "0.4.7", + "@ariakit/core": "0.4.9", "@floating-ui/dom": "^1.0.0", "use-sync-external-store": "^1.2.0" }, @@ -56136,22 +56124,19 @@ } } }, + "@ariakit/core": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.9.tgz", + "integrity": "sha512-nV0B/OTK/0iB+P9RC7fudznYZ8eR6rR1F912Zc54e3+wSW5RrRvNOiRxyMrgENidd4R7cCMDw77XJLSBLKgEPQ==" + }, "@ariakit/test": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@ariakit/test/-/test-0.4.0.tgz", - "integrity": "sha512-AcrppK61/AbsMDyDS3AxY3WXI6fcL+WedNpJm44Qx603dVYkS/potk0PrD1MfdC6aRt+2bRRj0n9dLN5lVMtbg==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@ariakit/test/-/test-0.4.2.tgz", + "integrity": "sha512-WXAAiAyTaHV9klntOB81Y+YHyA5iGxy9wXCmjQOfYK5InsuIour+7TVXICUxn2NF0XD6j6OoEJbCVDJ2Y46xEA==", "dev": true, "requires": { - "@ariakit/core": "0.4.7", + "@ariakit/core": "0.4.9", "@testing-library/dom": "^8.0.0 || ^9.0.0 || ^10.0.0" - }, - "dependencies": { - "@ariakit/core": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.7.tgz", - "integrity": "sha512-GUy/3ZY4kW1KdYHtMZRrRlj5FYbZTAyHlimxHI7Zs0xsC+kAzIf8lopnf67Y9IYLgEMr37KosIV7kwpkJpNs5Q==", - "dev": true - } } }, "@aw-web-design/x-default-browser": { @@ -67504,7 +67489,7 @@ "@wordpress/components": { "version": "file:packages/components", "requires": { - "@ariakit/react": "^0.4.7", + "@ariakit/react": "^0.4.10", "@babel/runtime": "^7.16.0", "@emotion/cache": "^11.7.1", "@emotion/css": "^11.7.1", @@ -67552,25 +67537,20 @@ "uuid": "^9.0.1" }, "dependencies": { - "@ariakit/core": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.7.tgz", - "integrity": "sha512-GUy/3ZY4kW1KdYHtMZRrRlj5FYbZTAyHlimxHI7Zs0xsC+kAzIf8lopnf67Y9IYLgEMr37KosIV7kwpkJpNs5Q==" - }, "@ariakit/react": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.7.tgz", - "integrity": "sha512-uUruuCo1M0Nj2oq1nTwDfUlVTLuoI9xeHP75EkuXX46lg5hzE5vVWbSMO1D6MCy7UwrUx2Ts4IqxdKr97suTwQ==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.10.tgz", + "integrity": "sha512-c1+6sNLj57aAXrBZMCVGG+OXeFrPAG0TV1jT7oPJcN/KLRs3aCuO3CCJVep/eKepFzzK01kNRGYX3wPT1TXPNw==", "requires": { - "@ariakit/react-core": "0.4.7" + "@ariakit/react-core": "0.4.10" } }, "@ariakit/react-core": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.7.tgz", - "integrity": "sha512-OogUyQ20cxkRNRuqLI05JbmpR4Lr5HwhUIqnb/sipzt6bkg/3wCXEnUAjfxg3nPjLTMjJ8+ODWmPC9JMJTW/yg==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.10.tgz", + "integrity": "sha512-r6DZmtHBmSoOj848+RpBwdZy/55YxPhMhfH14JIO2OLn1F6iSFkQwR7AAGpIrlYycWJFSF7KrQu50O+SSfFJdQ==", "requires": { - "@ariakit/core": "0.4.7", + "@ariakit/core": "0.4.9", "@floating-ui/dom": "^1.0.0", "use-sync-external-store": "^1.2.0" } @@ -67760,7 +67740,7 @@ "@wordpress/dataviews": { "version": "file:packages/dataviews", "requires": { - "@ariakit/react": "^0.4.7", + "@ariakit/react": "^0.4.10", "@babel/runtime": "^7.16.0", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", @@ -67775,25 +67755,20 @@ "remove-accents": "^0.5.0" }, "dependencies": { - "@ariakit/core": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.7.tgz", - "integrity": "sha512-GUy/3ZY4kW1KdYHtMZRrRlj5FYbZTAyHlimxHI7Zs0xsC+kAzIf8lopnf67Y9IYLgEMr37KosIV7kwpkJpNs5Q==" - }, "@ariakit/react": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.7.tgz", - "integrity": "sha512-uUruuCo1M0Nj2oq1nTwDfUlVTLuoI9xeHP75EkuXX46lg5hzE5vVWbSMO1D6MCy7UwrUx2Ts4IqxdKr97suTwQ==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.10.tgz", + "integrity": "sha512-c1+6sNLj57aAXrBZMCVGG+OXeFrPAG0TV1jT7oPJcN/KLRs3aCuO3CCJVep/eKepFzzK01kNRGYX3wPT1TXPNw==", "requires": { - "@ariakit/react-core": "0.4.7" + "@ariakit/react-core": "0.4.10" } }, "@ariakit/react-core": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.7.tgz", - "integrity": "sha512-OogUyQ20cxkRNRuqLI05JbmpR4Lr5HwhUIqnb/sipzt6bkg/3wCXEnUAjfxg3nPjLTMjJ8+ODWmPC9JMJTW/yg==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.10.tgz", + "integrity": "sha512-r6DZmtHBmSoOj848+RpBwdZy/55YxPhMhfH14JIO2OLn1F6iSFkQwR7AAGpIrlYycWJFSF7KrQu50O+SSfFJdQ==", "requires": { - "@ariakit/core": "0.4.7", + "@ariakit/core": "0.4.9", "@floating-ui/dom": "^1.0.0", "use-sync-external-store": "^1.2.0" } diff --git a/package.json b/package.json index ee78f197a43e28..5b0bdf823e617a 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "@actions/core": "1.9.1", "@actions/github": "5.0.0", "@apidevtools/json-schema-ref-parser": "11.6.4", - "@ariakit/test": "^0.4.0", + "@ariakit/test": "^0.4.2", "@babel/core": "7.24.3", "@babel/plugin-proposal-export-namespace-from": "7.18.9", "@babel/plugin-syntax-jsx": "7.24.1", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index c03d2455962c99..cff965f161230a 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -68,10 +68,8 @@ - `Composite` v2: add `Hover` and `Typeahead` subcomponents ([#64399](https://github.com/WordPress/gutenberg/pull/64399)). - `Composite` v2: add focus-related props to `Composite`and`Composite.Item` subcomponents ([#64450](https://github.com/WordPress/gutenberg/pull/64450)). - `Composite` v2: add `Context` subcomponent ([#64493](https://github.com/WordPress/gutenberg/pull/64493)). - -### Internal - - `CustomSelectControl`: Improve type inferring ([#64412](https://github.com/WordPress/gutenberg/pull/64412)). +- Update `ariakit` to version `0.4.10` ([#64637](https://github.com/WordPress/gutenberg/pull/64637)). ## 28.5.0 (2024-08-07) diff --git a/packages/components/package.json b/packages/components/package.json index 7a33e5840c2311..5469e52bed8c68 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -31,7 +31,7 @@ ], "types": "build-types", "dependencies": { - "@ariakit/react": "^0.4.7", + "@ariakit/react": "^0.4.10", "@babel/runtime": "^7.16.0", "@emotion/cache": "^11.7.1", "@emotion/css": "^11.7.1", diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index c86a4feb9c0668..8b72104f106d02 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -28,7 +28,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@ariakit/react": "^0.4.7", + "@ariakit/react": "^0.4.10", "@babel/runtime": "^7.16.0", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", From b1324c55d67d24d924f7c073b9c482e5d5699453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 20 Aug 2024 17:57:16 +0200 Subject: [PATCH 0460/1908] DataViews: make the move left/right controls in table header always available (#64646) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/dataviews/CHANGELOG.md | 2 ++ .../src/dataviews-layouts/table/column-header-menu.tsx | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index b1cb4504e72fad..cc6f4df9428b09 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- The "move left/move right" controls in the table layout (popup displayed on cliking header) are always visible. ([#64646](https://github.com/WordPress/gutenberg/pull/64646)). Before this, its visibility depending on filters, enableSorting, and enableHiding. + ## 4.1.0 (2024-08-07) ## Internal diff --git a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx index ef1dc3e3ed2e09..b8fd0517e49d1a 100644 --- a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx @@ -91,9 +91,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( !! field.elements?.length && !! operators.length && ! field.filterBy?.isPrimary; - if ( ! isSortable && ! isHidable && ! canAddFilter ) { - return field.label; - } + return ( <DropdownMenu align="start" From bfd96033d1644e58ed364153174e50ed281b9a2e Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 21 Aug 2024 05:22:01 +0400 Subject: [PATCH 0461/1908] Missing Block: Use hooks instead of HoC (#64657) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/block-library/src/missing/edit.js | 30 +++++++++------------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/packages/block-library/src/missing/edit.js b/packages/block-library/src/missing/edit.js index f7aef453b5447c..e7945630534d70 100644 --- a/packages/block-library/src/missing/edit.js +++ b/packages/block-library/src/missing/edit.js @@ -5,7 +5,7 @@ import { __, sprintf } from '@wordpress/i18n'; import { RawHTML } from '@wordpress/element'; import { Button } from '@wordpress/components'; import { createBlock } from '@wordpress/blocks'; -import { withDispatch, useSelect } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import { Warning, useBlockProps, @@ -13,7 +13,7 @@ import { } from '@wordpress/block-editor'; import { safeHTML } from '@wordpress/dom'; -function MissingBlockWarning( { attributes, convertToHTML, clientId } ) { +export default function MissingEdit( { attributes, clientId } ) { const { originalName, originalUndelimitedContent } = attributes; const hasContent = !! originalUndelimitedContent; const { hasFreeformBlock, hasHTMLBlock } = useSelect( @@ -34,6 +34,16 @@ function MissingBlockWarning( { attributes, convertToHTML, clientId } ) { }, [ clientId ] ); + const { replaceBlock } = useDispatch( blockEditorStore ); + + function convertToHTML() { + replaceBlock( + clientId, + createBlock( 'core/html', { + content: originalUndelimitedContent, + } ) + ); + } const actions = []; let messageHTML; @@ -81,19 +91,3 @@ function MissingBlockWarning( { attributes, convertToHTML, clientId } ) { </div> ); } - -const MissingEdit = withDispatch( ( dispatch, { clientId, attributes } ) => { - const { replaceBlock } = dispatch( blockEditorStore ); - return { - convertToHTML() { - replaceBlock( - clientId, - createBlock( 'core/html', { - content: attributes.originalUndelimitedContent, - } ) - ); - }, - }; -} )( MissingBlockWarning ); - -export default MissingEdit; From fc4c19e893a4f7742b73b8bec815c89fba6c2cb6 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:26:16 +0900 Subject: [PATCH 0462/1908] Site Editor: Always use auto cursor for editable text (#64627) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../block-editor/src/components/block-list/content.scss | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index c8f24e7efcbd2f..fb7687e69ffbe4 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -250,11 +250,13 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b .is-outline-mode .block-editor-block-list__block:not(.remove-outline) { - &.is-selected { + &.is-selected, + &.is-hovered { cursor: default; - &.rich-text { - cursor: unset; + &.rich-text, + .rich-text { + cursor: auto; } } From 2719bc8129c7b15d64933cde5cc63a43fe6b15d1 Mon Sep 17 00:00:00 2001 From: Vipul Gupta <55375170+vipul0425@users.noreply.github.com> Date: Wed, 21 Aug 2024 06:57:56 +0530 Subject: [PATCH 0463/1908] refactor: Update textControl to searchControl in taxonomy search. (#64605) Co-authored-by: vipul0425 <vipulgupta003@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../components/post-taxonomies/hierarchical-term-selector.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js index 14bcaef7a0399a..112bfaabd0c8ec 100644 --- a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js +++ b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js @@ -12,6 +12,7 @@ import { withFilters, Flex, FlexItem, + SearchControl, } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; import { useDebounce } from '@wordpress/compose'; @@ -406,7 +407,7 @@ export function HierarchicalTermSelector( { slug } ) { return ( <Flex direction="column" gap="4"> { showFilter && ( - <TextControl + <SearchControl __next40pxDefaultSize __nextHasNoMarginBottom label={ filterLabel } From d4539644fc2fd6c8102ced8e70bf2e5057a93949 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 21 Aug 2024 11:45:05 +0900 Subject: [PATCH 0464/1908] TextareaControl: Update styles (#64586) * TextareaControl: Refactor styles * Add 40px size prop * Tweak typography styles * Clarify with comment * Remove opt-in prop * Improve comment * Clean up unnecessary prop type * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../textarea-control/stories/index.story.tsx | 1 + .../styles/textarea-control-styles.ts | 77 ++++++++++++++++++- packages/components/src/utils/input/base.js | 30 -------- packages/components/src/utils/input/index.js | 1 - .../src/utils/input/input-control.js | 63 --------------- 6 files changed, 77 insertions(+), 96 deletions(-) delete mode 100644 packages/components/src/utils/input/base.js delete mode 100644 packages/components/src/utils/input/index.js delete mode 100644 packages/components/src/utils/input/input-control.js diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index cff965f161230a..c97e25862addec 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -56,6 +56,7 @@ - `UnitControl`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). - `Popover`: allow `style` prop usage ([#64489](https://github.com/WordPress/gutenberg/pull/64489)). - `ToolsPanel`: sets column-gap to 16px for ToolsPanel grid ([#64497](https://github.com/WordPress/gutenberg/pull/64497)). +- `TextareaControl`: Update styles ([#64586](https://github.com/WordPress/gutenberg/pull/64586)). ### Bug Fixes diff --git a/packages/components/src/textarea-control/stories/index.story.tsx b/packages/components/src/textarea-control/stories/index.story.tsx index e8cb986a141325..a8e5dc036248db 100644 --- a/packages/components/src/textarea-control/stories/index.story.tsx +++ b/packages/components/src/textarea-control/stories/index.story.tsx @@ -54,4 +54,5 @@ Default.args = { __nextHasNoMarginBottom: true, label: 'Text', help: 'Enter some text', + placeholder: 'Placeholder', }; diff --git a/packages/components/src/textarea-control/styles/textarea-control-styles.ts b/packages/components/src/textarea-control/styles/textarea-control-styles.ts index 046e17816eff24..022ce3560ea3a5 100644 --- a/packages/components/src/textarea-control/styles/textarea-control-styles.ts +++ b/packages/components/src/textarea-control/styles/textarea-control-styles.ts @@ -2,13 +2,86 @@ * External dependencies */ import styled from '@emotion/styled'; +import { css } from '@emotion/react'; /** * Internal dependencies */ -import { inputControl } from '../../utils/input'; +import { font } from '../../utils/font'; +import { COLORS } from '../../utils/colors-values'; +import { CONFIG } from '../../utils'; +import { breakpoint } from '../../utils/breakpoint'; + +const inputStyleNeutral = css` + box-shadow: 0 0 0 transparent; + border-radius: ${ CONFIG.radiusSmall }; + border: ${ CONFIG.borderWidth } solid ${ COLORS.ui.border }; + + @media not ( prefers-reduced-motion ) { + transition: box-shadow 0.1s linear; + } +`; + +const inputStyleFocus = css` + border-color: ${ COLORS.theme.accent }; + box-shadow: 0 0 0 + calc( ${ CONFIG.borderWidthFocus } - ${ CONFIG.borderWidth } ) + ${ COLORS.theme.accent }; + + // Windows High Contrast mode will show this outline, but not the box-shadow. + outline: 2px solid transparent; +`; export const StyledTextarea = styled.textarea` width: 100%; - ${ inputControl } + display: block; + font-family: ${ font( 'default.fontFamily' ) }; + line-height: 20px; + + // Vertical padding is to match the standard 40px control height when rows=1, + // in conjunction with the 20px line-height. + // "Standard" metrics are 10px 12px, but subtracts 1px each to account for the border width. + padding: 9px 11px; + + ${ inputStyleNeutral }; + + /* Fonts smaller than 16px causes mobile safari to zoom. */ + font-size: ${ font( 'mobileTextMinFontSize' ) }; + + ${ breakpoint( 'small' ) } { + font-size: ${ font( 'default.fontSize' ) }; + } + + &:focus { + ${ inputStyleFocus } + } + + // Use opacity to work in various editor styles. + &::-webkit-input-placeholder { + color: ${ COLORS.ui.darkGrayPlaceholder }; + } + + &::-moz-placeholder { + opacity: 1; // Necessary because Firefox reduces this from 1. + color: ${ COLORS.ui.darkGrayPlaceholder }; + } + + &:-ms-input-placeholder { + color: ${ COLORS.ui.darkGrayPlaceholder }; + } + + .is-dark-theme & { + &::-webkit-input-placeholder { + color: ${ COLORS.ui.lightGrayPlaceholder }; + } + + &::-moz-placeholder { + opacity: 1; // Necessary because Firefox reduces this from 1. + color: ${ COLORS.ui.lightGrayPlaceholder }; + } + + &:-ms-input-placeholder { + color: ${ COLORS.ui.lightGrayPlaceholder }; + } + } `; diff --git a/packages/components/src/utils/input/base.js b/packages/components/src/utils/input/base.js deleted file mode 100644 index 9eebd1c0bcea78..00000000000000 --- a/packages/components/src/utils/input/base.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * External dependencies - */ -import { css } from '@emotion/react'; - -/** - * Internal dependencies - */ -import { COLORS } from '../colors-values'; -import { CONFIG } from '../'; - -export const inputStyleNeutral = css` - box-shadow: 0 0 0 transparent; - border-radius: ${ CONFIG.radiusSmall }; - border: ${ CONFIG.borderWidth } solid ${ COLORS.ui.border }; - - @media not ( prefers-reduced-motion ) { - transition: box-shadow 0.1s linear; - } -`; - -export const inputStyleFocus = css` - border-color: ${ COLORS.theme.accent }; - box-shadow: 0 0 0 - calc( ${ CONFIG.borderWidthFocus } - ${ CONFIG.borderWidth } ) - ${ COLORS.theme.accent }; - - // Windows High Contrast mode will show this outline, but not the box-shadow. - outline: 2px solid transparent; -`; diff --git a/packages/components/src/utils/input/index.js b/packages/components/src/utils/input/index.js deleted file mode 100644 index 23fd731db99d94..00000000000000 --- a/packages/components/src/utils/input/index.js +++ /dev/null @@ -1 +0,0 @@ -export * from './input-control'; diff --git a/packages/components/src/utils/input/input-control.js b/packages/components/src/utils/input/input-control.js deleted file mode 100644 index 8af838247d9c25..00000000000000 --- a/packages/components/src/utils/input/input-control.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * External dependencies - */ -import { css } from '@emotion/react'; - -/** - * Internal dependencies - */ -import { inputStyleNeutral, inputStyleFocus } from './base'; -import { font } from '../font'; -import { COLORS } from '../colors-values'; -import { breakpoint } from '../breakpoint'; - -export const inputControl = css` - display: block; - font-family: ${ font( 'default.fontFamily' ) }; - padding: 6px 8px; - ${ inputStyleNeutral }; - - /* Fonts smaller than 16px causes mobile safari to zoom. */ - font-size: ${ font( 'mobileTextMinFontSize' ) }; - /* Override core line-height. To be reviewed. */ - line-height: normal; - - ${ breakpoint( 'small' ) } { - font-size: ${ font( 'default.fontSize' ) }; - /* Override core line-height. To be reviewed. */ - line-height: normal; - } - - &:focus { - ${ inputStyleFocus } - } - - // Use opacity to work in various editor styles. - &::-webkit-input-placeholder { - color: ${ COLORS.ui.darkGrayPlaceholder }; - } - - &::-moz-placeholder { - opacity: 1; // Necessary because Firefox reduces this from 1. - color: ${ COLORS.ui.darkGrayPlaceholder }; - } - - &:-ms-input-placeholder { - color: ${ COLORS.ui.darkGrayPlaceholder }; - } - - .is-dark-theme & { - &::-webkit-input-placeholder { - color: ${ COLORS.ui.lightGrayPlaceholder }; - } - - &::-moz-placeholder { - opacity: 1; // Necessary because Firefox reduces this from 1. - color: ${ COLORS.ui.lightGrayPlaceholder }; - } - - &:-ms-input-placeholder { - color: ${ COLORS.ui.lightGrayPlaceholder }; - } - } -`; From 18d1752e5a0877e0b7b8c13e3b195334e64bd57d Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Wed, 21 Aug 2024 08:44:30 +0530 Subject: [PATCH 0465/1908] Updated @since order in Inline document in client-assets.php file (#64653) * Updated @since Order in Inline document * Updated @since Order in Inline document Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- lib/client-assets.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index a159bc53e6a591..62e874d6b06c82 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -487,7 +487,9 @@ function gutenberg_register_packages_styles( $styles ) { * This hook also exists, and should be backported to Core in future versions. * However, it is envisaged that Gutenberg will continue to use the Style Engine's `gutenberg_*` functions and `_Gutenberg` classes to aid continuous development. * - * See: https://developer.wordpress.org/block-editor/reference-guides/packages/packages-style-engine/ + * @since 6.1 + * + * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-style-engine/ * * @param array $options { * Optional. An array of options to pass to gutenberg_style_engine_get_stylesheet_from_context(). Default empty array. @@ -496,8 +498,6 @@ function gutenberg_register_packages_styles( $styles ) { * @type bool $prettify Whether to add new lines and indents to output. Default is the test of whether the global constant `SCRIPT_DEBUG` is defined. * } * - * @since 6.1 - * * @return void */ function gutenberg_enqueue_stored_styles( $options = array() ) { From 22e9896d9ad7ee1d8662deb1456d60816adc654b Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Wed, 21 Aug 2024 08:59:58 +0530 Subject: [PATCH 0466/1908] Post Author Biography: Add Border Support (#64615) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- .../src/post-author-biography/block.json | 15 ++++++++++++++- .../src/post-author-biography/style.scss | 4 ++++ packages/block-library/src/style.scss | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 packages/block-library/src/post-author-biography/style.scss diff --git a/packages/block-library/src/post-author-biography/block.json b/packages/block-library/src/post-author-biography/block.json index c3845c77d6dbed..c6e27bc484dfd0 100644 --- a/packages/block-library/src/post-author-biography/block.json +++ b/packages/block-library/src/post-author-biography/block.json @@ -43,6 +43,19 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } - } + }, + "style": "wp-block-post-author-biography" } diff --git a/packages/block-library/src/post-author-biography/style.scss b/packages/block-library/src/post-author-biography/style.scss new file mode 100644 index 00000000000000..9a69fac9ba95b8 --- /dev/null +++ b/packages/block-library/src/post-author-biography/style.scss @@ -0,0 +1,4 @@ +.wp-block-post-author-biography { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; +} diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index 1070bedc8c3dbc..7906a1231d922b 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -32,6 +32,7 @@ @import "./page-list/style.scss"; @import "./paragraph/style.scss"; @import "./post-author/style.scss"; +@import "./post-author-biography/style.scss"; @import "./post-comments-form/style.scss"; @import "./post-content/style.scss"; @import "./post-date/style.scss"; From f971fbffa21398c28ba866f4404a2de6068fa0f8 Mon Sep 17 00:00:00 2001 From: Raj Patel <71687258+imrraaj@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:52:21 +0530 Subject: [PATCH 0467/1908] DataViews: hide filter toggle if there are no filters (#64640) Unlinked contributors: raj.patel@rtcamp.com. Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: imrraaj <imrraaj@git.wordpress.org> Co-authored-by: juanmaguitar <juanmaguitar@git.wordpress.org> --- packages/dataviews/src/components/dataviews-filters/index.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/dataviews/src/components/dataviews-filters/index.tsx b/packages/dataviews/src/components/dataviews-filters/index.tsx index de3477914c0083..96e7f5b5d7b9d9 100644 --- a/packages/dataviews/src/components/dataviews-filters/index.tsx +++ b/packages/dataviews/src/components/dataviews-filters/index.tsx @@ -95,6 +95,9 @@ export function FilterVisibilityToggle( { const visibleFilters = filters.filter( ( filter ) => filter.isVisible ); const hasVisibleFilters = !! visibleFilters.length; + if ( filters.length === 0 ) { + return null; + } if ( ! hasVisibleFilters ) { return ( <AddFilterDropdownMenu From 94091e03fed9ed5072650d5b7615efea83236663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:28:20 +0200 Subject: [PATCH 0468/1908] DataViews: load the filter toggle as open if there are primary filters (#64651) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/dataviews/src/components/dataviews/index.tsx | 6 ++++-- test/e2e/specs/site-editor/patterns.spec.js | 7 ------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index 81f901f0859bbc..c8a34028d78903 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -71,8 +71,6 @@ export default function DataViews< Item >( { }: DataViewsProps< Item > ) { const [ selectionState, setSelectionState ] = useState< string[] >( [] ); const [ density, setDensity ] = useState< number >( 0 ); - const [ isShowingFilter, setIsShowingFilter ] = - useState< boolean >( false ); const isUncontrolled = selectionProperty === undefined || onChangeSelection === undefined; const selection = isUncontrolled ? selectionState : selectionProperty; @@ -95,6 +93,10 @@ export default function DataViews< Item >( { }, [ selection, data, getItemId ] ); const filters = useFilters( _fields, view ); + const [ isShowingFilter, setIsShowingFilter ] = useState< boolean >( () => + ( filters || [] ).some( ( filter ) => filter.isPrimary ) + ); + return ( <DataViewsContext.Provider value={ { diff --git a/test/e2e/specs/site-editor/patterns.spec.js b/test/e2e/specs/site-editor/patterns.spec.js index 538f9ba936a897..162ec15146c67e 100644 --- a/test/e2e/specs/site-editor/patterns.spec.js +++ b/test/e2e/specs/site-editor/patterns.spec.js @@ -149,13 +149,6 @@ test.describe( 'Patterns', () => { await expect( patterns.item ).toHaveCount( 3 ); - await patterns.content - .getByRole( 'button', { - name: 'Toggle filter display', - exact: true, - } ) - .click(); - const searchBox = patterns.content.getByRole( 'searchbox', { name: 'Search', } ); From 35bd3777d707abfcd095ef69b34cfefc381094f6 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 21 Aug 2024 11:09:25 +0200 Subject: [PATCH 0469/1908] Block Bindings: Create utils to update or remove bindings (#64102) * Add `useBlockBindingsUtils` * Use utils in custom fields UI * Use utils in pattern overrides * Properly populate custom fields * Add comments * Update wrong comment Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- .../block-editor/src/hooks/block-bindings.js | 111 +++++------------- packages/block-editor/src/private-apis.js | 2 + .../block-editor/src/utils/block-bindings.js | 98 ++++++++++++++++ .../components/pattern-overrides-controls.js | 46 +++----- 4 files changed, 144 insertions(+), 113 deletions(-) create mode 100644 packages/block-editor/src/utils/block-bindings.js diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index ce3fdd2f327c40..a7aa72ae6693a6 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -13,7 +13,7 @@ import { __experimentalVStack as VStack, privateApis as componentsPrivateApis, } from '@wordpress/components'; -import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; +import { useRegistry } from '@wordpress/data'; import { useContext, Fragment } from '@wordpress/element'; import { useViewportMatch } from '@wordpress/compose'; @@ -24,10 +24,10 @@ import { canBindAttribute, getBindableAttributes, } from '../hooks/use-bindings-attributes'; -import { store as blockEditorStore } from '../store'; import { unlock } from '../lock-unlock'; import InspectorControls from '../components/inspector-controls'; import BlockContext from '../components/block-context'; +import { useBlockBindingsUtils } from '../utils/block-bindings'; const { DropdownMenuV2: DropdownMenu, @@ -51,17 +51,15 @@ const useToolsPanelDropdownMenuProps = () => { : {}; }; -function BlockBindingsPanelDropdown( { - fieldsList, - addConnection, - attribute, - binding, -} ) { +function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) { + const { getBlockBindingsSources } = unlock( blocksPrivateApis ); + const registeredSources = getBlockBindingsSources(); + const { updateBlockBindings } = useBlockBindingsUtils(); const currentKey = binding?.args?.key; return ( <> - { Object.entries( fieldsList ).map( ( [ label, fields ], i ) => ( - <Fragment key={ label }> + { Object.entries( fieldsList ).map( ( [ name, fields ], i ) => ( + <Fragment key={ name }> <DropdownMenuGroup> { Object.keys( fieldsList ).length > 1 && ( <Text @@ -70,14 +68,19 @@ function BlockBindingsPanelDropdown( { variant="muted" aria-hidden > - { label } + { registeredSources[ name ].label } </Text> ) } { Object.entries( fields ).map( ( [ key, value ] ) => ( <DropdownMenuRadioItem key={ key } onChange={ () => - addConnection( key, attribute ) + updateBlockBindings( { + [ attribute ]: { + source: name, + args: { key }, + }, + } ) } name={ attribute + '-binding' } value={ key } @@ -141,9 +144,8 @@ function EditableBlockBindingsPanelItems( { attributes, bindings, fieldsList, - addConnection, - removeConnection, } ) { + const { updateBlockBindings } = useBlockBindingsUtils(); const isMobile = useViewportMatch( 'medium', '<' ); return ( <> @@ -155,7 +157,9 @@ function EditableBlockBindingsPanelItems( { hasValue={ () => !! binding } label={ attribute } onDeselect={ () => { - removeConnection( attribute ); + updateBlockBindings( { + [ attribute ]: undefined, + } ); } } > <DropdownMenu @@ -175,7 +179,6 @@ function EditableBlockBindingsPanelItems( { > <BlockBindingsPanelDropdown fieldsList={ fieldsList } - addConnection={ addConnection } attribute={ attribute } binding={ binding } /> @@ -187,91 +190,33 @@ function EditableBlockBindingsPanelItems( { ); } -export const BlockBindingsPanel = ( { name, metadata } ) => { +export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { const registry = useRegistry(); const blockContext = useContext( BlockContext ); const { bindings } = metadata || {}; - - const bindableAttributes = getBindableAttributes( name ); + const { removeAllBlockBindings } = useBlockBindingsUtils(); + const bindableAttributes = getBindableAttributes( blockName ); const dropdownMenuProps = useToolsPanelDropdownMenuProps(); const filteredBindings = { ...bindings }; Object.keys( filteredBindings ).forEach( ( key ) => { if ( - ! canBindAttribute( name, key ) || + ! canBindAttribute( blockName, key ) || filteredBindings[ key ].source === 'core/pattern-overrides' ) { delete filteredBindings[ key ]; } } ); - const { updateBlockAttributes } = useDispatch( blockEditorStore ); - - const { _id } = useSelect( ( select ) => { - const { getSelectedBlockClientId } = select( blockEditorStore ); - - return { - _id: getSelectedBlockClientId(), - }; - }, [] ); - if ( ! bindableAttributes || bindableAttributes.length === 0 ) { return null; } - const removeAllConnections = () => { - const newMetadata = { ...metadata }; - delete newMetadata.bindings; - updateBlockAttributes( _id, { - metadata: - Object.keys( newMetadata ).length === 0 - ? undefined - : newMetadata, - } ); - }; - - const addConnection = ( value, attribute ) => { - // Assuming the block expects a flat structure for its metadata attribute - const newMetadata = { - ...metadata, - // Adjust this according to the actual structure expected by your block - bindings: { - ...metadata?.bindings, - [ attribute ]: { - source: 'core/post-meta', - args: { key: value }, - }, - }, - }; - // Update the block's attributes with the new metadata - updateBlockAttributes( _id, { - metadata: newMetadata, - } ); - }; - - const removeConnection = ( key ) => { - const newMetadata = { ...metadata }; - if ( ! newMetadata.bindings ) { - return; - } - - delete newMetadata.bindings[ key ]; - if ( Object.keys( newMetadata.bindings ).length === 0 ) { - delete newMetadata.bindings; - } - updateBlockAttributes( _id, { - metadata: - Object.keys( newMetadata ).length === 0 - ? undefined - : newMetadata, - } ); - }; - const fieldsList = {}; const { getBlockBindingsSources } = unlock( blocksPrivateApis ); const registeredSources = getBlockBindingsSources(); - Object.values( registeredSources ).forEach( - ( { getFieldsList, label, usesContext } ) => { + Object.entries( registeredSources ).forEach( + ( [ sourceName, { getFieldsList, usesContext } ] ) => { if ( getFieldsList ) { // Populate context. const context = {}; @@ -286,7 +231,7 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { } ); // Only add source if the list is not empty. if ( sourceList ) { - fieldsList[ label ] = { ...sourceList }; + fieldsList[ sourceName ] = { ...sourceList }; } } } @@ -312,7 +257,7 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { <ToolsPanel label={ __( 'Attributes' ) } resetAll={ () => { - removeAllConnections(); + removeAllBlockBindings(); } } dropdownMenuProps={ dropdownMenuProps } className="block-editor-bindings__panel" @@ -327,8 +272,6 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { attributes={ bindableAttributes } bindings={ filteredBindings } fieldsList={ fieldsList } - addConnection={ addConnection } - removeConnection={ removeConnection } /> ) } </ItemGroup> diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index cf464cedf04175..788bb2bef56efa 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -47,6 +47,7 @@ import { PrivatePublishDateTimePicker } from './components/publish-date-time-pic import useSpacingSizes from './components/spacing-sizes-control/hooks/use-spacing-sizes'; import useBlockDisplayTitle from './components/block-title/use-block-display-title'; import TabbedSidebar from './components/tabbed-sidebar'; +import { useBlockBindingsUtils } from './utils/block-bindings'; /** * Private @wordpress/block-editor APIs. @@ -92,4 +93,5 @@ lock( privateApis, { useBlockDisplayTitle, __unstableBlockStyleVariationOverridesWithConfig, setBackgroundStyleDefaults, + useBlockBindingsUtils, } ); diff --git a/packages/block-editor/src/utils/block-bindings.js b/packages/block-editor/src/utils/block-bindings.js new file mode 100644 index 00000000000000..4ba6e1a362958c --- /dev/null +++ b/packages/block-editor/src/utils/block-bindings.js @@ -0,0 +1,98 @@ +/** + * WordPress dependencies + */ +import { useDispatch, useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../store'; +import { useBlockEditContext } from '../components/block-edit'; + +export function useBlockBindingsUtils() { + const { clientId } = useBlockEditContext(); + const { updateBlockAttributes } = useDispatch( blockEditorStore ); + const { getBlockAttributes } = useSelect( blockEditorStore ); + + /** + * Updates the value of the bindings connected to block attributes. + * It removes the binding when the new value is `undefined`. + * + * @param {Object} bindings Bindings including the attributes to update and the new object. + * @param {string} bindings.source The source name to connect to. + * @param {Object} [bindings.args] Object containing the arguments needed by the source. + * + * @example + * ```js + * import { useBlockBindingsUtils } from '@wordpress/block-editor' + * + * const { updateBlockBindings } = useBlockBindingsUtils(); + * updateBlockBindings( { + * url: { + * source: 'core/post-meta', + * args: { + * key: 'url_custom_field', + * }, + * }, + * alt: { + * source: 'core/post-meta', + * args: { + * key: 'text_custom_field', + * }, + * } + * } ); + * ``` + */ + const updateBlockBindings = ( bindings ) => { + const { metadata } = getBlockAttributes( clientId ); + const newBindings = { ...metadata?.bindings }; + Object.entries( bindings ).forEach( ( [ attribute, binding ] ) => { + if ( ! binding && newBindings[ attribute ] ) { + delete newBindings[ attribute ]; + return; + } + newBindings[ attribute ] = binding; + } ); + + const newMetadata = { + ...metadata, + bindings: newBindings, + }; + + if ( Object.keys( newMetadata.bindings ).length === 0 ) { + delete newMetadata.bindings; + } + + updateBlockAttributes( clientId, { + metadata: + Object.keys( newMetadata ).length === 0 + ? undefined + : newMetadata, + } ); + }; + + /** + * Removes the bindings property of the `metadata` attribute. + * + * @example + * ```js + * import { useBlockBindingsUtils } from '@wordpress/block-editor' + * + * const { removeAllBlockBindings } = useBlockBindingsUtils(); + * removeAllBlockBindings(); + * ``` + */ + const removeAllBlockBindings = () => { + const { metadata } = getBlockAttributes( clientId ); + const newMetadata = { ...metadata }; + delete newMetadata.bindings; + updateBlockAttributes( clientId, { + metadata: + Object.keys( newMetadata ).length === 0 + ? undefined + : newMetadata, + } ); + }; + + return { updateBlockBindings, removeAllBlockBindings }; +} diff --git a/packages/patterns/src/components/pattern-overrides-controls.js b/packages/patterns/src/components/pattern-overrides-controls.js index 9bec88a93471eb..28dd8788a390c6 100644 --- a/packages/patterns/src/components/pattern-overrides-controls.js +++ b/packages/patterns/src/components/pattern-overrides-controls.js @@ -2,7 +2,10 @@ * WordPress dependencies */ import { useState, useId } from '@wordpress/element'; -import { InspectorControls } from '@wordpress/block-editor'; +import { + InspectorControls, + privateApis as blockEditorPrivateApis, +} from '@wordpress/block-editor'; import { BaseControl, Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; @@ -14,22 +17,9 @@ import { AllowOverridesModal, DisallowOverridesModal, } from './allow-overrides-modal'; +import { unlock } from '../lock-unlock'; -function removeBindings( bindings ) { - let updatedBindings = { ...bindings }; - delete updatedBindings.__default; - if ( ! Object.keys( updatedBindings ).length ) { - updatedBindings = undefined; - } - return updatedBindings; -} - -function addBindings( bindings ) { - return { - ...bindings, - __default: { source: PATTERN_OVERRIDES_BINDING_SOURCE }, - }; -} +const { useBlockBindingsUtils } = unlock( blockEditorPrivateApis ); function PatternOverridesControls( { attributes, @@ -49,24 +39,22 @@ function PatternOverridesControls( { const isConnectedToOtherSources = defaultBindings?.source && defaultBindings.source !== PATTERN_OVERRIDES_BINDING_SOURCE; + const { updateBlockBindings } = useBlockBindingsUtils(); function updateBindings( isChecked, customName ) { - const prevBindings = attributes?.metadata?.bindings; - const updatedBindings = isChecked - ? addBindings( prevBindings ) - : removeBindings( prevBindings ); - - const updatedMetadata = { - ...attributes.metadata, - bindings: updatedBindings, - }; - if ( customName ) { - updatedMetadata.name = customName; + setAttributes( { + metadata: { + ...attributes.metadata, + name: customName, + }, + } ); } - setAttributes( { - metadata: updatedMetadata, + updateBlockBindings( { + __default: isChecked + ? { source: PATTERN_OVERRIDES_BINDING_SOURCE } + : undefined, } ); } From 2a59bf1ee08410f1ee0a0c39c59b6bf5c7b920a0 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:58:18 +0530 Subject: [PATCH 0470/1908] Image block: Add reset button (#64669) * Add reset button on image block * Update argument on onSelectImage function Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-library/src/image/image.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index c4b54259028d91..646299bb7e0892 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -3,6 +3,7 @@ */ import { isBlobURL } from '@wordpress/blob'; import { + MenuItem, ExternalLink, ResizableBox, Spinner, @@ -597,7 +598,11 @@ export default function Image( { onSelect={ onSelectImage } onSelectURL={ onSelectURL } onError={ onUploadError } - /> + > + <MenuItem onClick={ () => onSelectImage( undefined ) }> + { __( 'Reset' ) } + </MenuItem> + </MediaReplaceFlow> </BlockControls> ) } { isSingleSelected && externalBlob && ( From 8352584988479e9d060645b9ce253a17cc8c2e4e Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 21 Aug 2024 11:56:12 +0200 Subject: [PATCH 0471/1908] DataViews: Support defining field headers/names as React elements. (#64642) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/dataviews/CHANGELOG.md | 8 +++++++- .../src/components/dataviews/stories/fixtures.js | 14 +++++++++++++- .../components/dataviews/stories/index.story.js | 8 +++++++- .../dataviews/src/dataviews-layouts/grid/index.tsx | 2 +- .../dataviews-layouts/table/column-header-menu.tsx | 4 ++-- packages/dataviews/src/normalize-fields.ts | 1 + packages/dataviews/src/types.ts | 9 +++++++++ 7 files changed, 40 insertions(+), 6 deletions(-) diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index cc6f4df9428b09..d51cf9c969016d 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,7 +2,13 @@ ## Unreleased -- The "move left/move right" controls in the table layout (popup displayed on cliking header) are always visible. ([#64646](https://github.com/WordPress/gutenberg/pull/64646)). Before this, its visibility depending on filters, enableSorting, and enableHiding. +## New features + +- Support using a component for field headers or names by providing a `header` property in the field object. The string `label` property (or `id`) is still mandatory. ([#64642](https://github.com/WordPress/gutenberg/pull/64642)). + +## Internal + +- The "move left/move right" controls in the table layout (popup displayed on cliking header) are always visible. ([#64646](https://github.com/WordPress/gutenberg/pull/64646)). Before this, its visibility depending on filters, enableSorting, and enableHiding. ## 4.1.0 (2024-08-07) diff --git a/packages/dataviews/src/components/dataviews/stories/fixtures.js b/packages/dataviews/src/components/dataviews/stories/fixtures.js index f89cea81e6f15d..50401d97b026b5 100644 --- a/packages/dataviews/src/components/dataviews/stories/fixtures.js +++ b/packages/dataviews/src/components/dataviews/stories/fixtures.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { trash } from '@wordpress/icons'; +import { trash, image, Icon, category } from '@wordpress/icons'; import { Button, __experimentalText as Text, @@ -173,6 +173,12 @@ export const fields = [ { label: 'Image', id: 'image', + header: ( + <HStack spacing={ 1 } justify="start"> + <Icon icon={ image } /> + <span>Image</span> + </HStack> + ), render: ( { item } ) => { return ( <img src={ item.image } alt="" style={ { width: '100%' } } /> @@ -217,6 +223,12 @@ export const fields = [ { label: 'Categories', id: 'categories', + header: ( + <HStack spacing={ 1 } justify="start"> + <Icon icon={ category } /> + <span>Categories</span> + </HStack> + ), elements: [ { value: 'Space', label: 'Space' }, { value: 'NASA', label: 'NASA' }, diff --git a/packages/dataviews/src/components/dataviews/stories/index.story.js b/packages/dataviews/src/components/dataviews/stories/index.story.js index 9ce1c29573e55c..376b14a464666c 100644 --- a/packages/dataviews/src/components/dataviews/stories/index.story.js +++ b/packages/dataviews/src/components/dataviews/stories/index.story.js @@ -8,7 +8,7 @@ import { useState, useMemo } from '@wordpress/element'; */ import DataViews from '../index'; import { DEFAULT_VIEW, actions, data, fields } from './fixtures'; -import { LAYOUT_GRID, LAYOUT_TABLE } from '../../../constants'; +import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../../../constants'; import { filterSortAndPaginate } from '../../../filter-and-sort-data-view'; const meta = { @@ -61,5 +61,11 @@ Default.args = { primaryField: 'title', }, }, + [ LAYOUT_LIST ]: { + layout: { + mediaField: 'image', + primaryField: 'title', + }, + }, }, }; diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx index c8cac31bf7db81..230ffe0dc50b5c 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx @@ -145,7 +145,7 @@ function GridItem< Item >( { > <> <FlexItem className="dataviews-view-grid__field-name"> - { field.label } + { field.header } </FlexItem> <FlexItem className="dataviews-view-grid__field-value" diff --git a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx index b8fd0517e49d1a..ba672715b91ccf 100644 --- a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx @@ -72,7 +72,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( ); const index = view.fields?.indexOf( fieldId ) as number; if ( !! combinedField ) { - return combinedField.label; + return combinedField.header || combinedField.label; } const field = fields.find( ( f ) => f.id === fieldId ); if ( ! field ) { @@ -102,7 +102,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( ref={ ref } variant="tertiary" > - { field.label } + { field.header } { view.sort && isSorted && ( <span aria-hidden="true"> { sortArrows[ view.sort.direction ] } diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index f9f95b5b8140dc..5f0baec12c4df2 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -55,6 +55,7 @@ export function normalizeFields< Item >( return { ...field, label: field.label || field.id, + header: field.header || field.label || field.id, getValue, render, sort, diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index fa5cec8d7d0320..ca55442f6529a5 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -87,6 +87,12 @@ export type Field< Item > = { */ label?: string; + /** + * The header of the field. Defaults to the label. + * It allows the usage of a React Element to render the field labels. + */ + header?: string | ReactElement; + /** * A description of the field. */ @@ -151,6 +157,7 @@ export type Field< Item > = { export type NormalizedField< Item > = Field< Item > & { label: string; + header: string | ReactElement; getValue: ( args: { item: Item } ) => any; render: ComponentType< { item: Item } >; Edit: ComponentType< DataFormControlProps< Item > >; @@ -289,6 +296,8 @@ export interface CombinedField { label: string; + header?: string | ReactElement; + /** * The fields to use as columns. */ From 5fb9c1cb1dc77863b4f9ec0bf55cd1c91eaa68b4 Mon Sep 17 00:00:00 2001 From: David Arenas <david.arenas@automattic.com> Date: Wed, 21 Aug 2024 12:20:52 +0200 Subject: [PATCH 0472/1908] Interactivity API: Fix context inheritance from namespaces different than the current one (#64677) * Add failing test * Fix contextStack generation to include other namespaces * Update changelog Co-authored-by: DAreRodz <darerodz@git.wordpress.org> Co-authored-by: luisherranz <luisherranz@git.wordpress.org> --- .../directive-context/render.php | 21 +++++++++++++++++++ packages/interactivity/CHANGELOG.md | 4 ++++ packages/interactivity/src/directives.tsx | 14 ++++++------- .../interactivity/directive-context.spec.ts | 15 +++++++++++++ 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-context/render.php b/packages/e2e-tests/plugins/interactive-blocks/directive-context/render.php index b52120debdc560..76635e37a26086 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-context/render.php +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-context/render.php @@ -212,3 +212,24 @@ ></span> </div> </div> + + +<div + data-testid="inheritance from other namespaces" + data-wp-interactive="directive-context/parent" + data-wp-context='{ "prop": "fromParentNs" }' +> + <div + data-wp-interactive="directive-context/child" + data-wp-context='{ "prop": "fromChildNs" }' + > + <span + data-testid="parent" + data-wp-text="directive-context/parent::context.prop" + ></span> + <span + data-testid="child" + data-wp-text="directive-context/child::context.prop" + ></span> + </div> +</div> diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 52707b70ba5a7b..9068e1780cc10e 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- Fix context inheritance from namespaces different than the current one ([#64677](https://github.com/WordPress/gutenberg/pull/64677)). + ## 6.5.0 (2024-08-07) ### Enhancements diff --git a/packages/interactivity/src/directives.tsx b/packages/interactivity/src/directives.tsx index 357fe203399be3..715bc2ea7b16b6 100644 --- a/packages/interactivity/src/directives.tsx +++ b/packages/interactivity/src/directives.tsx @@ -273,12 +273,11 @@ export default () => { const inheritedValue = useContext( inheritedContext ); const ns = defaultEntry!.namespace; - const currentValue = useRef( { - [ ns ]: proxifyState( ns, {} ), - } ); + const currentValue = useRef( proxifyState( ns, {} ) ); // No change should be made if `defaultEntry` does not exist. const contextStack = useMemo( () => { + const result = { ...inheritedValue }; if ( defaultEntry ) { const { namespace, value } = defaultEntry; // Check that the value is a JSON object. Send a console warning if not. @@ -288,15 +287,16 @@ export default () => { ); } updateContext( - currentValue.current[ namespace ], + currentValue.current, deepClone( value ) as object ); - currentValue.current[ namespace ] = proxifyContext( - currentValue.current[ namespace ], + currentValue.current = proxifyContext( + currentValue.current, inheritedValue[ namespace ] ); + result[ namespace ] = currentValue.current; } - return currentValue.current; + return result; }, [ defaultEntry, inheritedValue ] ); return createElement( Provider, { value: contextStack }, children ); diff --git a/test/e2e/specs/interactivity/directive-context.spec.ts b/test/e2e/specs/interactivity/directive-context.spec.ts index e806049ff55e75..0a27fe258d5a8d 100644 --- a/test/e2e/specs/interactivity/directive-context.spec.ts +++ b/test/e2e/specs/interactivity/directive-context.spec.ts @@ -380,4 +380,19 @@ test.describe( 'data-wp-context', () => { expect( childContextAfter.obj2.prop6 ).toBe( 'child' ); expect( childContextAfter.obj2.overwritten ).toBeUndefined(); } ); + + test( 'properties from other namespaces defined in a parent context are inherited', async ( { + page, + } ) => { + const childProp = page + .getByTestId( 'inheritance from other namespaces' ) + .getByTestId( 'child' ); + + const parentProp = page + .getByTestId( 'inheritance from other namespaces' ) + .getByTestId( 'parent' ); + + await expect( childProp ).toHaveText( 'fromChildNs' ); + await expect( parentProp ).toHaveText( 'fromParentNs' ); + } ); } ); From 5de4d860b9a55e3fbb7a8b1a230ae9643d294e25 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 21 Aug 2024 19:23:12 +0900 Subject: [PATCH 0473/1908] Try: Hyphenate long block names in the inserter (#64667) Unlinked contributors: La-Geek. Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: hedgefield <hedgefield@git.wordpress.org> Co-authored-by: karmatosed <karmatosed@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: laras126 <notlaura@git.wordpress.org> Co-authored-by: Soean <soean@git.wordpress.org> --- .../block-editor/src/components/inserter-list-item/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/components/inserter-list-item/style.scss b/packages/block-editor/src/components/inserter-list-item/style.scss index fb15113400522b..f91e4365db30ce 100644 --- a/packages/block-editor/src/components/inserter-list-item/style.scss +++ b/packages/block-editor/src/components/inserter-list-item/style.scss @@ -120,4 +120,5 @@ .block-editor-block-types-list__item-title { padding: 4px 2px 8px; font-size: 12px; + hyphens: auto; } From 543a4695aed3aeb2ea75b5d385b094c34d7024f2 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 21 Aug 2024 19:24:21 +0900 Subject: [PATCH 0474/1908] Embed Block: Replace native input element with InputControl component (#64668) * Embed Block: Replace native input element with InputControl component * Don't use hardcoded label Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/block-library/src/embed/edit.js | 2 +- packages/block-library/src/embed/editor.scss | 4 ++++ packages/block-library/src/embed/embed-placeholder.js | 11 +++++++---- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/block-library/src/embed/edit.js b/packages/block-library/src/embed/edit.js index 0b589eb68ecf49..6978e144794047 100644 --- a/packages/block-library/src/embed/edit.js +++ b/packages/block-library/src/embed/edit.js @@ -226,7 +226,7 @@ const EmbedEdit = ( props ) => { } } value={ url } cannotEmbed={ cannotEmbed } - onChange={ ( event ) => setURL( event.target.value ) } + onChange={ ( value ) => setURL( value ) } fallback={ () => fallback( url, onReplace ) } tryAgain={ () => { invalidateResolution( 'getEmbedPreview', [ url ] ); diff --git a/packages/block-library/src/embed/editor.scss b/packages/block-library/src/embed/editor.scss index 6d1fc5496bc73b..eda859eee9040c 100644 --- a/packages/block-library/src/embed/editor.scss +++ b/packages/block-library/src/embed/editor.scss @@ -12,6 +12,10 @@ justify-content: center; } + .wp-block-embed__placeholder-input { + flex: 1 1 auto; + } + // Stops long URLs from breaking out of the no preview available screen .components-placeholder__error { word-break: break-word; diff --git a/packages/block-library/src/embed/embed-placeholder.js b/packages/block-library/src/embed/embed-placeholder.js index 7b4cd5f8db9aa8..57aa0645ee3d94 100644 --- a/packages/block-library/src/embed/embed-placeholder.js +++ b/packages/block-library/src/embed/embed-placeholder.js @@ -8,6 +8,7 @@ import { ExternalLink, __experimentalHStack as HStack, __experimentalVStack as VStack, + __experimentalInputControl as InputControl, } from '@wordpress/components'; import { BlockIcon } from '@wordpress/block-editor'; @@ -31,15 +32,17 @@ const EmbedPlaceholder = ( { ) } > <form onSubmit={ onSubmit }> - <input + <InputControl + __next40pxDefaultSize type="url" value={ value || '' } - className="components-placeholder__input" - aria-label={ label } + className="wp-block-embed__placeholder-input" + label={ label } + hideLabelFromVision placeholder={ __( 'Enter URL to embed here…' ) } onChange={ onChange } /> - <Button variant="primary" type="submit"> + <Button __next40pxDefaultSize variant="primary" type="submit"> { _x( 'Embed', 'button label' ) } </Button> </form> From cc8009e9e1f076a435e0443670ec1c7da4c30f62 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 21 Aug 2024 13:18:25 +0200 Subject: [PATCH 0475/1908] DropdownMenu V2: use themed color variables (#64647) * Use foreground theme color instead of hardcoded gray 900 * Use shared theme variable for gray 700 text * Use theme variables for remaining colors.gray variables * Update comments * Extract lighter background color * CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/dropdown-menu-v2/styles.ts | 26 ++++++++++--------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index c97e25862addec..357427f8f3443c 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -69,6 +69,7 @@ - `Composite` v2: add `Hover` and `Typeahead` subcomponents ([#64399](https://github.com/WordPress/gutenberg/pull/64399)). - `Composite` v2: add focus-related props to `Composite`and`Composite.Item` subcomponents ([#64450](https://github.com/WordPress/gutenberg/pull/64450)). - `Composite` v2: add `Context` subcomponent ([#64493](https://github.com/WordPress/gutenberg/pull/64493)). +- `DropdownMenu` v2: use themed color variables ([#64647](https://github.com/WordPress/gutenberg/pull/64647)). - `CustomSelectControl`: Improve type inferring ([#64412](https://github.com/WordPress/gutenberg/pull/64412)). - Update `ariakit` to version `0.4.10` ([#64637](https://github.com/WordPress/gutenberg/pull/64637)). diff --git a/packages/components/src/dropdown-menu-v2/styles.ts b/packages/components/src/dropdown-menu-v2/styles.ts index 3260a83f45f1c1..9e71316b6b9dc5 100644 --- a/packages/components/src/dropdown-menu-v2/styles.ts +++ b/packages/components/src/dropdown-menu-v2/styles.ts @@ -25,12 +25,14 @@ const ITEM_PADDING_BLOCK = space( 2 ); const ITEM_PADDING_INLINE = space( 3 ); // TODO: -// - those values are different from saved variables? -// - should bring this into the config, and make themeable -// - border color and divider color are different? -const DEFAULT_BORDER_COLOR = COLORS.gray[ 300 ]; -const DIVIDER_COLOR = COLORS.gray[ 200 ]; -const TOOLBAR_VARIANT_BORDER_COLOR = COLORS.gray[ '900' ]; +// - border color and divider color are different from COLORS.theme variables +// - lighter text color is not defined in COLORS.theme, should it be? +// - lighter background color is not defined in COLORS.theme, should it be? +const DEFAULT_BORDER_COLOR = COLORS.theme.gray[ 300 ]; +const DIVIDER_COLOR = COLORS.theme.gray[ 200 ]; +const LIGHTER_TEXT_COLOR = COLORS.theme.gray[ 700 ]; +const LIGHT_BACKGROUND_COLOR = COLORS.theme.gray[ 100 ]; +const TOOLBAR_VARIANT_BORDER_COLOR = COLORS.theme.foreground; const DEFAULT_BOX_SHADOW = `0 0 0 ${ CONFIG.borderWidth } ${ DEFAULT_BORDER_COLOR }, ${ CONFIG.elevationXSmall }`; const TOOLBAR_VARIANT_BOX_SHADOW = `0 0 0 ${ CONFIG.borderWidth } ${ TOOLBAR_VARIANT_BORDER_COLOR }`; @@ -149,7 +151,7 @@ const baseItem = css` font-weight: normal; line-height: 20px; - color: ${ COLORS.gray[ 900 ] }; + color: ${ COLORS.theme.foreground }; border-radius: ${ CONFIG.radiusSmall }; padding-block: ${ ITEM_PADDING_BLOCK }; @@ -193,8 +195,8 @@ const baseItem = css` /* When the item is the trigger of an open submenu */ ${ DropdownMenu }:not(:focus) &:not(:focus)[aria-expanded="true"] { - background-color: ${ COLORS.gray[ 100 ] }; - color: ${ COLORS.gray[ 900 ] }; + background-color: ${ LIGHT_BACKGROUND_COLOR }; + color: ${ COLORS.theme.foreground }; } svg { @@ -238,7 +240,7 @@ export const ItemPrefixWrapper = styled.span` align-items: center; justify-content: center; - color: ${ COLORS.gray[ '700' ] }; + color: ${ LIGHTER_TEXT_COLOR }; /* * When the parent menu item is active, except when it's a non-focused/hovered @@ -284,7 +286,7 @@ export const ItemSuffixWrapper = styled.span` justify-content: center; gap: ${ space( 3 ) }; - color: ${ COLORS.gray[ '700' ] }; + color: ${ LIGHTER_TEXT_COLOR }; /* * When the parent menu item is active, except when it's a non-focused/hovered @@ -343,7 +345,7 @@ export const DropdownMenuItemLabel = styled( Truncate )` export const DropdownMenuItemHelpText = styled( Truncate )` font-size: ${ font( 'helpText.fontSize' ) }; line-height: 16px; - color: ${ COLORS.gray[ '700' ] }; + color: ${ LIGHTER_TEXT_COLOR }; word-break: break-all; [data-active-item]:not( [data-focus-visible] ) *:not( ${ DropdownMenu } ) &, From 9d51f4532ca576021e5a90651a9dccea3400df4b Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Wed, 21 Aug 2024 12:24:56 +0100 Subject: [PATCH 0476/1908] Apply elevation scale (#64656) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/block-editor/src/components/inserter/style.scss | 2 +- packages/block-editor/src/components/url-input/style.scss | 2 +- packages/block-library/src/gallery/editor.scss | 2 +- .../src/components/dataviews-bulk-actions-toolbar/style.scss | 2 +- packages/edit-widgets/src/components/error-boundary/style.scss | 2 +- packages/editor/src/components/error-boundary/style.scss | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index 960ca8b48cdf90..a567ce1cee07e5 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -36,7 +36,7 @@ $block-inserter-tabs-height: 44px; .components-popover__content { border: none; outline: none; - box-shadow: $shadow-popover; + box-shadow: $elevation-x-small; .block-editor-inserter__quick-inserter > * { border-left: $border-width solid $gray-400; diff --git a/packages/block-editor/src/components/url-input/style.scss b/packages/block-editor/src/components/url-input/style.scss index f8d84ae43b8089..e6ba17a71aaa5b 100644 --- a/packages/block-editor/src/components/url-input/style.scss +++ b/packages/block-editor/src/components/url-input/style.scss @@ -120,7 +120,7 @@ $input-size: 300px; } .block-editor-url-input__button-modal { - box-shadow: $shadow-popover; + box-shadow: $elevation-x-small; border: 1px solid $gray-300; background: $white; } diff --git a/packages/block-library/src/gallery/editor.scss b/packages/block-library/src/gallery/editor.scss index 025e86277f7edc..3184b9d3d8fb22 100644 --- a/packages/block-library/src/gallery/editor.scss +++ b/packages/block-library/src/gallery/editor.scss @@ -144,7 +144,7 @@ border: $border-width solid $gray-900; &:hover { - box-shadow: $shadow-popover; + box-shadow: $elevation-x-small; } @include break-small() { diff --git a/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss b/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss index 21e6c2ad4d4d64..5672234d8cbbb7 100644 --- a/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss +++ b/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss @@ -12,7 +12,7 @@ .components-accessible-toolbar { border-color: $gray-300; - box-shadow: $shadow-popover; + box-shadow: $elevation-x-small; .components-toolbar-group { border-color: $gray-200; diff --git a/packages/edit-widgets/src/components/error-boundary/style.scss b/packages/edit-widgets/src/components/error-boundary/style.scss index c1605b42a5ea86..b909b79dc1d304 100644 --- a/packages/edit-widgets/src/components/error-boundary/style.scss +++ b/packages/edit-widgets/src/components/error-boundary/style.scss @@ -3,5 +3,5 @@ max-width: 780px; padding: 20px; margin-top: 60px; - box-shadow: $shadow-modal; + box-shadow: $elevation-large; } diff --git a/packages/editor/src/components/error-boundary/style.scss b/packages/editor/src/components/error-boundary/style.scss index d1b792d0ff3d32..2913a644b94576 100644 --- a/packages/editor/src/components/error-boundary/style.scss +++ b/packages/editor/src/components/error-boundary/style.scss @@ -3,5 +3,5 @@ max-width: 780px; padding: 20px; margin-top: 60px; - box-shadow: $shadow-modal; + box-shadow: $elevation-large; } From e6ecb4d93e1db53dddd5e65e63af316108735ba4 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:25:16 +0200 Subject: [PATCH 0477/1908] Placeholders: Update radius temporarily. (#64672) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/placeholder/style.scss | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 357427f8f3443c..ff9749f2dad080 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -22,6 +22,7 @@ ### Enhancements +- `Placeholder`: Temporarily rewind radius scale ([#64672](https://github.com/WordPress/gutenberg/pull/64672)). - `Composite`: improve Storybook examples and add interactive controls ([#64397](https://github.com/WordPress/gutenberg/pull/64397)). - `Composite`: use internal context to forward the composite store to sub-components ([#64493](https://github.com/WordPress/gutenberg/pull/64493)). - `QueryControls`: Default to new 40px size ([#64457](https://github.com/WordPress/gutenberg/pull/64457)). diff --git a/packages/components/src/placeholder/style.scss b/packages/components/src/placeholder/style.scss index 61090c81110a5c..a38d7d3e3ace8b 100644 --- a/packages/components/src/placeholder/style.scss +++ b/packages/components/src/placeholder/style.scss @@ -19,7 +19,7 @@ // Block UI appearance. - border-radius: $radius-medium; + border-radius: $radius-small; // Match the block toolbar material radius. background-color: $white; box-shadow: inset 0 0 0 $border-width $gray-900; outline: 1px solid transparent; // Shown for Windows 10 High Contrast mode. @@ -144,6 +144,9 @@ display: flex; box-shadow: none; + // In the unselected state, radius should match Global Styles > Image > Radius. + border-radius: 0; + // Blur the background so layered dashed placeholders are still visually separate. // Make the background transparent to not interfere with the background overlay in placeholder-style() pseudo element backdrop-filter: blur(100px); From c47491ad84892584ef4e84846c0eb72e47cf7402 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Wed, 21 Aug 2024 12:48:44 +0100 Subject: [PATCH 0478/1908] Apply elevation scale to: Modal, Popover, and Snackbar components (#64655) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 3 +++ packages/components/src/modal/style.scss | 2 +- packages/components/src/popover/style.scss | 2 +- packages/components/src/snackbar/style.scss | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index ff9749f2dad080..8a3b890a2c62f1 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -57,6 +57,9 @@ - `UnitControl`: Adopt radius scale ([#64368](https://github.com/WordPress/gutenberg/pull/64368)). - `Popover`: allow `style` prop usage ([#64489](https://github.com/WordPress/gutenberg/pull/64489)). - `ToolsPanel`: sets column-gap to 16px for ToolsPanel grid ([#64497](https://github.com/WordPress/gutenberg/pull/64497)). +- `Modal`: Replace references to deprecated styling variables ([#64655](https://github.com/WordPress/gutenberg/pull/64655)). +- `Popover`: Replace references to deprecated styling variables ([#64655](https://github.com/WordPress/gutenberg/pull/64655)). +- `Snackbar`: Replace references to deprecated styling variables ([#64655](https://github.com/WordPress/gutenberg/pull/64655)). - `TextareaControl`: Update styles ([#64586](https://github.com/WordPress/gutenberg/pull/64586)). ### Bug Fixes diff --git a/packages/components/src/modal/style.scss b/packages/components/src/modal/style.scss index c862363a0d3c81..75ba7e1384e4c1 100644 --- a/packages/components/src/modal/style.scss +++ b/packages/components/src/modal/style.scss @@ -20,7 +20,7 @@ margin: $grid-unit-50 0 0 0; width: 100%; background: $white; - box-shadow: $shadow-modal; + box-shadow: $elevation-large; border-radius: $radius-large $radius-large 0 0; overflow: hidden; // Have the content element fill the vertical space yet not overflow. diff --git a/packages/components/src/popover/style.scss b/packages/components/src/popover/style.scss index f9f43870a6b927..01b0eb91161422 100644 --- a/packages/components/src/popover/style.scss +++ b/packages/components/src/popover/style.scss @@ -22,7 +22,7 @@ $shadow-popover-border-top-only-alternate: 0 #{-$border-width} 0 $gray-900; .components-popover__content { background: $white; - box-shadow: $shadow-popover-border-default, $shadow-popover; + box-shadow: $shadow-popover-border-default, $elevation-x-small; border-radius: $radius-medium; box-sizing: border-box; width: min-content; diff --git a/packages/components/src/snackbar/style.scss b/packages/components/src/snackbar/style.scss index 5bea7076599b56..e7f29267d6f6db 100644 --- a/packages/components/src/snackbar/style.scss +++ b/packages/components/src/snackbar/style.scss @@ -4,7 +4,7 @@ background: rgba($black, 0.85); // Emulates #1e1e1e closely. backdrop-filter: blur($grid-unit-20) saturate(180%); border-radius: $radius-medium; - box-shadow: $shadow-popover; + box-shadow: $elevation-x-small; color: $white; padding: $grid-unit-15 ($grid-unit-05 * 5); width: 100%; From 9749a4aef1f2092146e3c49c01bba5ae62938fe3 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:28:55 +0300 Subject: [PATCH 0479/1908] Components: Use `useStoreState()` instead of `store.useState()` (#64648) * Components: Use useStoreState() instead of store.useState() * CHANGELOG * Cleanup TabList Co-authored-by: ciampo <mciampini@git.wordpress.org> --------- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/alignment-matrix-control/index.tsx | 3 ++- .../circular-option-picker-option.tsx | 3 ++- .../src/custom-select-control-v2/custom-select.tsx | 3 ++- packages/components/src/dropdown-menu-v2/index.tsx | 8 +++++--- packages/components/src/radio-group/radio.tsx | 3 ++- packages/components/src/tab-panel/index.tsx | 5 ++++- packages/components/src/tabs/index.tsx | 3 ++- packages/components/src/tabs/tablist.tsx | 10 ++++++---- packages/components/src/tabs/tabpanel.tsx | 8 ++++++-- .../toggle-group-control/as-radio-group.tsx | 3 ++- packages/components/src/tooltip/index.tsx | 3 ++- .../dataviews/src/dataviews-layouts/list/index.tsx | 7 +++++-- 13 files changed, 41 insertions(+), 19 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 8a3b890a2c62f1..7a48717419605a 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -76,6 +76,7 @@ - `DropdownMenu` v2: use themed color variables ([#64647](https://github.com/WordPress/gutenberg/pull/64647)). - `CustomSelectControl`: Improve type inferring ([#64412](https://github.com/WordPress/gutenberg/pull/64412)). - Update `ariakit` to version `0.4.10` ([#64637](https://github.com/WordPress/gutenberg/pull/64637)). +- Ariakit: Use `useStoreState()` instead of `store.useState()` ([#64648](https://github.com/WordPress/gutenberg/pull/64648)). ## 28.5.0 (2024-08-07) diff --git a/packages/components/src/alignment-matrix-control/index.tsx b/packages/components/src/alignment-matrix-control/index.tsx index 1d22c3560625db..cd6bc7acabc3cd 100644 --- a/packages/components/src/alignment-matrix-control/index.tsx +++ b/packages/components/src/alignment-matrix-control/index.tsx @@ -2,6 +2,7 @@ * External dependencies */ import clsx from 'clsx'; +import { useStoreState } from '@ariakit/react'; /** * WordPress dependencies @@ -68,7 +69,7 @@ export function AlignmentMatrixControl( { rtl: isRTL(), } ); - const activeId = compositeStore.useState( 'activeId' ); + const activeId = useStoreState( compositeStore, 'activeId' ); const classes = clsx( 'component-alignment-matrix-control', className ); diff --git a/packages/components/src/circular-option-picker/circular-option-picker-option.tsx b/packages/components/src/circular-option-picker/circular-option-picker-option.tsx index 35a2f427134f40..1ab4fd0d017901 100644 --- a/packages/components/src/circular-option-picker/circular-option-picker-option.tsx +++ b/packages/components/src/circular-option-picker/circular-option-picker-option.tsx @@ -2,6 +2,7 @@ * External dependencies */ import clsx from 'clsx'; +import { useStoreState } from '@ariakit/react'; import type { ForwardedRef } from 'react'; /** @@ -52,7 +53,7 @@ function UnforwardedOptionAsOption( forwardedRef: ForwardedRef< any > ) { const { id, isSelected, compositeStore, ...additionalProps } = props; - const activeId = compositeStore.useState( 'activeId' ); + const activeId = useStoreState( compositeStore, 'activeId' ); if ( isSelected && ! activeId ) { compositeStore.setActiveId( id ); diff --git a/packages/components/src/custom-select-control-v2/custom-select.tsx b/packages/components/src/custom-select-control-v2/custom-select.tsx index e925038812fa73..bb458abcc282ff 100644 --- a/packages/components/src/custom-select-control-v2/custom-select.tsx +++ b/packages/components/src/custom-select-control-v2/custom-select.tsx @@ -2,6 +2,7 @@ * External dependencies */ import * as Ariakit from '@ariakit/react'; +import { useStoreState } from '@ariakit/react'; /** * WordPress dependencies @@ -62,7 +63,7 @@ const CustomSelectButton = ( { CustomSelectStore, 'onChange' > ) => { - const { value: currentValue } = store.useState(); + const { value: currentValue } = useStoreState( store ); const computedRenderSelectedValue = useMemo( () => renderSelectedValue ?? defaultRenderSelectedValue, diff --git a/packages/components/src/dropdown-menu-v2/index.tsx b/packages/components/src/dropdown-menu-v2/index.tsx index c53286a7da128b..b6ac9e45e37758 100644 --- a/packages/components/src/dropdown-menu-v2/index.tsx +++ b/packages/components/src/dropdown-menu-v2/index.tsx @@ -2,6 +2,7 @@ * External dependencies */ import * as Ariakit from '@ariakit/react'; +import { useStoreState } from '@ariakit/react'; /** * WordPress dependencies @@ -248,9 +249,10 @@ const UnconnectedDropdownMenu = ( ); // Extract the side from the applied placement — useful for animations. - const appliedPlacementSide = dropdownMenuStore - .useState( 'placement' ) - .split( '-' )[ 0 ]; + const appliedPlacementSide = useStoreState( + dropdownMenuStore, + 'placement' + ).split( '-' )[ 0 ]; if ( dropdownMenuStore.parent && diff --git a/packages/components/src/radio-group/radio.tsx b/packages/components/src/radio-group/radio.tsx index 0c90c337fcdf2f..50a5a2647b39d5 100644 --- a/packages/components/src/radio-group/radio.tsx +++ b/packages/components/src/radio-group/radio.tsx @@ -7,6 +7,7 @@ import { forwardRef, useContext } from '@wordpress/element'; * External dependencies */ import * as Ariakit from '@ariakit/react'; +import { useStoreState } from '@ariakit/react'; /** * Internal dependencies @@ -26,7 +27,7 @@ function UnforwardedRadio( ) { const { store, disabled } = useContext( RadioGroupContext ); - const selectedValue = store?.useState( 'value' ); + const selectedValue = useStoreState( store, 'value' ); const isChecked = selectedValue !== undefined && selectedValue === value; return ( diff --git a/packages/components/src/tab-panel/index.tsx b/packages/components/src/tab-panel/index.tsx index f85119d938c659..9e180c30321b93 100644 --- a/packages/components/src/tab-panel/index.tsx +++ b/packages/components/src/tab-panel/index.tsx @@ -2,6 +2,7 @@ * External dependencies */ import * as Ariakit from '@ariakit/react'; +import { useStoreState } from '@ariakit/react'; import clsx from 'clsx'; import type { ForwardedRef } from 'react'; @@ -121,7 +122,9 @@ const UnforwardedTabPanel = ( defaultSelectedId: prependInstanceId( initialTabName ), } ); - const selectedTabName = extractTabName( tabStore.useState( 'selectedId' ) ); + const selectedTabName = extractTabName( + useStoreState( tabStore, 'selectedId' ) + ); const setTabStoreSelectedId = useCallback( ( tabName: string ) => { diff --git a/packages/components/src/tabs/index.tsx b/packages/components/src/tabs/index.tsx index cad4a217efd44d..ef8978b647a904 100644 --- a/packages/components/src/tabs/index.tsx +++ b/packages/components/src/tabs/index.tsx @@ -2,6 +2,7 @@ * External dependencies */ import * as Ariakit from '@ariakit/react'; +import { useStoreState } from '@ariakit/react'; /** * WordPress dependencies @@ -48,7 +49,7 @@ function Tabs( { const isControlled = selectedTabId !== undefined; - const { items, selectedId, activeId } = store.useState(); + const { items, selectedId, activeId } = useStoreState( store ); const { setSelectedId, setActiveId } = store; // Keep track of whether tabs have been populated. This is used to prevent diff --git a/packages/components/src/tabs/tablist.tsx b/packages/components/src/tabs/tablist.tsx index 4906e0088417b7..80ed9b4c5bea2f 100644 --- a/packages/components/src/tabs/tablist.tsx +++ b/packages/components/src/tabs/tablist.tsx @@ -2,6 +2,7 @@ * External dependencies */ import * as Ariakit from '@ariakit/react'; +import { useStoreState } from '@ariakit/react'; /** * WordPress dependencies @@ -26,7 +27,8 @@ export const TabList = forwardRef< >( function TabList( { children, ...otherProps }, ref ) { const context = useTabsContext(); - const selectedId = context?.store.useState( 'selectedId' ); + const tabStoreState = useStoreState( context?.store ); + const selectedId = tabStoreState?.selectedId; const indicatorPosition = useTrackElementOffsetRect( context?.store.item( selectedId )?.element ); @@ -37,13 +39,13 @@ export const TabList = forwardRef< ( { previousValue } ) => previousValue && setAnimationEnabled( true ) ); - if ( ! context ) { + if ( ! context || ! tabStoreState ) { warning( '`Tabs.TabList` must be wrapped in a `Tabs` component.' ); return null; } - const { store } = context; - const { activeId, selectOnMove } = store.useState(); + const { store } = context; + const { activeId, selectOnMove } = tabStoreState; const { setActiveId } = store; const onBlur = () => { diff --git a/packages/components/src/tabs/tabpanel.tsx b/packages/components/src/tabs/tabpanel.tsx index 439671a39ff9b7..512b2609682722 100644 --- a/packages/components/src/tabs/tabpanel.tsx +++ b/packages/components/src/tabs/tabpanel.tsx @@ -1,7 +1,11 @@ /** - * WordPress dependencies + * External dependencies */ +import { useStoreState } from '@ariakit/react'; +/** + * WordPress dependencies + */ import { forwardRef } from '@wordpress/element'; /** @@ -22,13 +26,13 @@ export const TabPanel = forwardRef< ref ) { const context = useTabsContext(); + const selectedId = useStoreState( context?.store, 'selectedId' ); if ( ! context ) { warning( '`Tabs.TabPanel` must be wrapped in a `Tabs` component.' ); return null; } const { store, instanceId } = context; const instancedTabId = `${ instanceId }-${ tabId }`; - const selectedId = store.useState( ( state ) => state.selectedId ); return ( <StyledTabPanel diff --git a/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx b/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx index c363cb6577d839..6baadd65dc5ff6 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx @@ -3,6 +3,7 @@ */ import type { ForwardedRef } from 'react'; import * as Ariakit from '@ariakit/react'; +import { useStoreState } from '@ariakit/react'; /** * WordPress dependencies @@ -66,7 +67,7 @@ function UnforwardedToggleGroupControlAsRadioGroup( setValue: wrappedOnChangeProp, } ); - const selectedValue = radio.useState( 'value' ); + const selectedValue = useStoreState( radio, 'value' ); const setValue = radio.setValue; const groupContextValue = useMemo( diff --git a/packages/components/src/tooltip/index.tsx b/packages/components/src/tooltip/index.tsx index e832119393282a..7ce9311fc942ea 100644 --- a/packages/components/src/tooltip/index.tsx +++ b/packages/components/src/tooltip/index.tsx @@ -2,6 +2,7 @@ * External dependencies */ import * as Ariakit from '@ariakit/react'; +import { useStoreState } from '@ariakit/react'; import clsx from 'clsx'; /** @@ -93,7 +94,7 @@ function UnforwardedTooltip( placement: computedPlacement, showTimeout: delay, } ); - const mounted = tooltipStore.useState( 'mounted' ); + const mounted = useStoreState( tooltipStore, 'mounted' ); if ( isNestedInTooltip ) { return isOnlyChild ? ( diff --git a/packages/dataviews/src/dataviews-layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx index 70eaf3af1cd619..d8889f25b24e9c 100644 --- a/packages/dataviews/src/dataviews-layouts/list/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/list/index.tsx @@ -3,6 +3,8 @@ */ import clsx from 'clsx'; // TODO: use the @wordpress/components one once public +// eslint-disable-next-line no-restricted-imports +import { useStoreState } from '@ariakit/react'; // Import CompositeStore type, which is not exported from @wordpress/components. // eslint-disable-next-line no-restricted-imports import type { CompositeStore } from '@ariakit/react'; @@ -359,10 +361,11 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) { const store = useCompositeStore( { defaultActiveId: getItemDomId( selectedItem ), - } ); + } ) as CompositeStore; // TODO, remove once composite APIs are public // Manage focused item, when the active one is removed from the list. - const isActiveIdInList = store.useState( + const isActiveIdInList = useStoreState( + store, ( state: { items: any[]; activeId: any } ) => state.items.some( ( item: { id: any } ) => item.id === state.activeId From 5e779974ddda4e66d22a508bc3c79a75c4769497 Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Wed, 21 Aug 2024 15:43:06 +0200 Subject: [PATCH 0480/1908] ESLint: Enable and enforce remaining i18n rules for the plugin (e.g. no trailing spaces) (#60196) Co-authored-by: Mahesh Bohara <maheshbohara0101@gmail.com> --- .eslintrc.js | 2 ++ lib/experiments-page.php | 6 ++--- .../convert-to-group-buttons/index.js | 2 +- .../global-styles/background-panel.js | 2 +- .../get-global-styles-changes.js | 5 +++- packages/block-library/src/group/edit.js | 2 +- .../src/post-navigation-link/edit.js | 7 ++++-- .../src/query/edit/query-content.js | 2 +- .../src/components/welcome-guide/default.js | 22 ++++++++++------- .../font-library-modal/installed-fonts.js | 10 ++++---- .../src/components/welcome-guide/index.js | 22 ++++++++++------- .../src/components/page-attributes/parent.js | 22 ++++++++++------- .../editor/src/components/post-url/index.js | 24 ++++++++++++------- 13 files changed, 78 insertions(+), 50 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 25173a9f0e8a82..13362e76c4e473 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -177,6 +177,8 @@ module.exports = { '@wordpress/dependency-group': 'error', '@wordpress/wp-global-usage': 'error', '@wordpress/react-no-unsafe-timeout': 'error', + '@wordpress/i18n-hyphenated-range': 'error', + '@wordpress/i18n-no-flanking-whitespace': 'error', '@wordpress/i18n-text-domain': [ 'error', { diff --git a/lib/experiments-page.php b/lib/experiments-page.php index b27f6fc2726a2a..fa95923061daff 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -45,7 +45,7 @@ function gutenberg_initialize_experiments_settings() { add_settings_field( 'gutenberg-sync-collaboration', - __( 'Live Collaboration and offline persistence ', 'gutenberg' ), + __( 'Live Collaboration and offline persistence', 'gutenberg' ), 'gutenberg_display_experiment_field', 'gutenberg-experiments', 'gutenberg_experiments_section', @@ -93,7 +93,7 @@ function gutenberg_initialize_experiments_settings() { add_settings_field( 'gutenberg-form-blocks', - __( 'Form and input blocks ', 'gutenberg' ), + __( 'Form and input blocks', 'gutenberg' ), 'gutenberg_display_experiment_field', 'gutenberg-experiments', 'gutenberg_experiments_section', @@ -105,7 +105,7 @@ function gutenberg_initialize_experiments_settings() { add_settings_field( 'gutenberg-grid-interactivity', - __( 'Grid interactivity ', 'gutenberg' ), + __( 'Grid interactivity', 'gutenberg' ), 'gutenberg_display_experiment_field', 'gutenberg-experiments', 'gutenberg_experiments_section', diff --git a/packages/block-editor/src/components/convert-to-group-buttons/index.js b/packages/block-editor/src/components/convert-to-group-buttons/index.js index 2a015d569e85b4..d2e5fda1e96b7c 100644 --- a/packages/block-editor/src/components/convert-to-group-buttons/index.js +++ b/packages/block-editor/src/components/convert-to-group-buttons/index.js @@ -82,7 +82,7 @@ function ConvertToGroupButton( { > { _x( 'Ungroup', - 'Ungrouping blocks from within a grouping block back into individual blocks within the Editor ' + 'Ungrouping blocks from within a grouping block back into individual blocks within the Editor' ) } </MenuItem> ) } diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index 6391f72a084875..e230e6e600508c 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -451,7 +451,7 @@ function BackgroundImageControls( { onResetImage(); } } > - { __( 'Reset ' ) } + { __( 'Reset' ) } </MenuItem> ) } </MediaReplaceFlow> diff --git a/packages/block-editor/src/components/global-styles/get-global-styles-changes.js b/packages/block-editor/src/components/global-styles/get-global-styles-changes.js index c525cf45c6d52e..51e9b16d8048f4 100644 --- a/packages/block-editor/src/components/global-styles/get-global-styles-changes.js +++ b/packages/block-editor/src/components/global-styles/get-global-styles-changes.js @@ -202,7 +202,10 @@ export default function getGlobalStylesChanges( next, previous, options = {} ) { }, {} ) ).map( ( [ key, changeValues ] ) => { const changeValuesLength = changeValues.length; - const joinedChangesValue = changeValues.join( __( ', ' ) ); + const joinedChangesValue = changeValues.join( + /* translators: Used between list items, there is a space after the comma. */ + __( ', ' ) // eslint-disable-line @wordpress/i18n-no-flanking-whitespace + ); switch ( key ) { case 'blocks': { return sprintf( diff --git a/packages/block-library/src/group/edit.js b/packages/block-library/src/group/edit.js index a763bc95e60d7c..352a6fbc77819e 100644 --- a/packages/block-library/src/group/edit.js +++ b/packages/block-library/src/group/edit.js @@ -34,7 +34,7 @@ function GroupEditControls( { tagName, onSelectTagName } ) { 'The <header> element should represent introductory content, typically a group of introductory or navigational aids.' ), main: __( - 'The <main> element should be used for the primary content of your document only. ' + 'The <main> element should be used for the primary content of your document only.' ), section: __( "The <section> element should represent a standalone portion of the document that can't be better represented by another element." diff --git a/packages/block-library/src/post-navigation-link/edit.js b/packages/block-library/src/post-navigation-link/edit.js index a3a3bf19749774..e27d094feb79ab 100644 --- a/packages/block-library/src/post-navigation-link/edit.js +++ b/packages/block-library/src/post-navigation-link/edit.js @@ -49,8 +49,11 @@ export default function PostNavigationLinkEdit( { const displayArrow = arrowMap[ arrow ]; if ( showTitle ) { - /* translators: Label before for next and previous post. There is a space after the colon. */ - placeholder = isNext ? __( 'Next: ' ) : __( 'Previous: ' ); + placeholder = isNext + ? /* translators: Label before for next and previous post. There is a space after the colon. */ + __( 'Next: ' ) // eslint-disable-line @wordpress/i18n-no-flanking-whitespace + : /* translators: Label before for next and previous post. There is a space after the colon. */ + __( 'Previous: ' ); // eslint-disable-line @wordpress/i18n-no-flanking-whitespace } const ariaLabel = isNext ? __( 'Next post' ) : __( 'Previous post' ); diff --git a/packages/block-library/src/query/edit/query-content.js b/packages/block-library/src/query/edit/query-content.js index be10f88cb911ec..949ffc653420fe 100644 --- a/packages/block-library/src/query/edit/query-content.js +++ b/packages/block-library/src/query/edit/query-content.js @@ -109,7 +109,7 @@ export default function QueryContent( { } ); const htmlElementMessages = { main: __( - 'The <main> element should be used for the primary content of your document only. ' + 'The <main> element should be used for the primary content of your document only.' ), section: __( "The <section> element should represent a standalone portion of the document that can't be better represented by another element." diff --git a/packages/edit-post/src/components/welcome-guide/default.js b/packages/edit-post/src/components/welcome-guide/default.js index c4723c65a33df2..cdaf2c7608b43e 100644 --- a/packages/edit-post/src/components/welcome-guide/default.js +++ b/packages/edit-post/src/components/welcome-guide/default.js @@ -105,16 +105,20 @@ export default function WelcomeGuideDefault() { { __( 'Learn how to use the block editor' ) } </h1> <p className="edit-post-welcome-guide__text"> - { __( - 'New to the block editor? Want to learn more about using it? ' + { createInterpolateElement( + __( + "New to the block editor? Want to learn more about using it? <a>Here's a detailed guide.</a>" + ), + { + a: ( + <ExternalLink + href={ __( + 'https://wordpress.org/documentation/article/wordpress-block-editor/' + ) } + /> + ), + } ) } - <ExternalLink - href={ __( - 'https://wordpress.org/documentation/article/wordpress-block-editor/' - ) } - > - { __( "Here's a detailed guide." ) } - </ExternalLink> </p> </> ), diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js index 7ca2a9218c3bb0..9896a9a525d446 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js @@ -130,9 +130,11 @@ function InstalledFonts() { } catch ( error ) { setNotice( { type: 'error', - message: - __( 'There was an error updating the font family. ' ) + - error.message, + message: sprintf( + /* translators: %s: error message */ + __( 'There was an error updating the font family. %s' ), + error.message + ), } ); } }; @@ -464,7 +466,7 @@ function ConfirmDeleteDialog( { setNotice( { type: 'error', message: - __( 'There was an error uninstalling the font family. ' ) + + __( 'There was an error uninstalling the font family.' ) + error.message, } ); } diff --git a/packages/edit-widgets/src/components/welcome-guide/index.js b/packages/edit-widgets/src/components/welcome-guide/index.js index 51244956286d8d..bd06234e399b58 100644 --- a/packages/edit-widgets/src/components/welcome-guide/index.js +++ b/packages/edit-widgets/src/components/welcome-guide/index.js @@ -172,16 +172,20 @@ export default function WelcomeGuide() { { __( 'Learn how to use the block editor' ) } </h1> <p className="edit-widgets-welcome-guide__text"> - { __( - 'New to the block editor? Want to learn more about using it? ' + { createInterpolateElement( + __( + "New to the block editor? Want to learn more about using it? <a>Here's a detailed guide.</a>" + ), + { + a: ( + <ExternalLink + href={ __( + 'https://wordpress.org/documentation/article/wordpress-block-editor/' + ) } + /> + ), + } ) } - <ExternalLink - href={ __( - 'https://wordpress.org/documentation/article/wordpress-block-editor/' - ) } - > - { __( "Here's a detailed guide." ) } - </ExternalLink> </p> </> ), diff --git a/packages/editor/src/components/page-attributes/parent.js b/packages/editor/src/components/page-attributes/parent.js index d53d82914f7c1e..1018834d1b9fca 100644 --- a/packages/editor/src/components/page-attributes/parent.js +++ b/packages/editor/src/components/page-attributes/parent.js @@ -274,16 +274,20 @@ export function ParentRow() { } ) } <p> - { __( - 'They also show up as sub-items in the default navigation menu. ' + { createInterpolateElement( + __( + 'They also show up as sub-items in the default navigation menu. <a>Learn more.</a>' + ), + { + a: ( + <ExternalLink + href={ __( + 'https://wordpress.org/documentation/article/page-post-settings-sidebar/#page-attributes' + ) } + /> + ), + } ) } - <ExternalLink - href={ __( - 'https://wordpress.org/documentation/article/page-post-settings-sidebar/#page-attributes' - ) } - > - { __( 'Learn more' ) } - </ExternalLink> </p> </div> <PageAttributesParent /> diff --git a/packages/editor/src/components/post-url/index.js b/packages/editor/src/components/post-url/index.js index c2b2ac8826b205..e767ae04f5ec0e 100644 --- a/packages/editor/src/components/post-url/index.js +++ b/packages/editor/src/components/post-url/index.js @@ -3,7 +3,7 @@ */ import { useSelect, useDispatch } from '@wordpress/data'; import { safeDecodeURIComponent, cleanForSlug } from '@wordpress/url'; -import { useState } from '@wordpress/element'; +import { useState, createInterpolateElement } from '@wordpress/element'; import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; import { @@ -83,14 +83,20 @@ export default function PostURL( { onClose } ) { <VStack spacing={ 3 }> { isEditable && ( <div> - { __( 'Customize the last part of the URL. ' ) } - <ExternalLink - href={ __( - 'https://wordpress.org/documentation/article/page-post-settings-sidebar/#permalink' - ) } - > - { __( 'Learn more.' ) } - </ExternalLink> + { createInterpolateElement( + __( + 'Customize the last part of the URL. <a>Learn more.</a>' + ), + { + a: ( + <ExternalLink + href={ __( + 'https://wordpress.org/documentation/article/page-post-settings-sidebar/#permalink' + ) } + /> + ), + } + ) } </div> ) } <div> From ab06c003670d33f007d516ab31d48f2f42a638a3 Mon Sep 17 00:00:00 2001 From: Bernie Reiter <96308+ockham@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:01:06 +0200 Subject: [PATCH 0481/1908] Navigation Block: Remove now-obsolete function_exists guards (#64673) - Remove a number of `function_exists()` guards that checked for existence of the `set_ignored_hooked_blocks_metadata` function. (That function was introduced in WP 6.5, and Gutenberg now requires WP 6.5 as a minimum.) - Delete code that checked if the `block_core_navigation_update_ignore_hooked_blocks_meta` function was attached to the `rest_insert_wp_navigation` _action_ hook, and removed it if it was. Co-authored-by: ockham <bernhard-reiter@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- .../block-library/src/navigation/index.php | 37 +++++-------------- .../block-navigation-block-hooks-test.php | 12 ------ 2 files changed, 10 insertions(+), 39 deletions(-) diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index a73aa682f596c9..ccadd5c4a222d4 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -241,13 +241,11 @@ private static function get_inner_blocks_from_navigation_post( $attributes ) { // it encounters whitespace. This code strips it. $blocks = block_core_navigation_filter_out_empty_blocks( $parsed_blocks ); - if ( function_exists( 'set_ignored_hooked_blocks_metadata' ) ) { - // Run Block Hooks algorithm to inject hooked blocks. - $markup = block_core_navigation_insert_hooked_blocks( $blocks, $navigation_post ); - $root_nav_block = parse_blocks( $markup )[0]; + // Run Block Hooks algorithm to inject hooked blocks. + $markup = block_core_navigation_insert_hooked_blocks( $blocks, $navigation_post ); + $root_nav_block = parse_blocks( $markup )[0]; - $blocks = isset( $root_nav_block['innerBlocks'] ) ? $root_nav_block['innerBlocks'] : $blocks; - } + $blocks = isset( $root_nav_block['innerBlocks'] ) ? $root_nav_block['innerBlocks'] : $blocks; // TODO - this uses the full navigation block attributes for the // context which could be refined. @@ -1083,15 +1081,13 @@ function block_core_navigation_get_fallback_blocks() { // In this case default to the (Page List) fallback. $fallback_blocks = ! empty( $maybe_fallback ) ? $maybe_fallback : $fallback_blocks; - if ( function_exists( 'set_ignored_hooked_blocks_metadata' ) ) { - // Run Block Hooks algorithm to inject hooked blocks. - // We have to run it here because we need the post ID of the Navigation block to track ignored hooked blocks. - $markup = block_core_navigation_insert_hooked_blocks( $fallback_blocks, $navigation_post ); - $blocks = parse_blocks( $markup ); + // Run Block Hooks algorithm to inject hooked blocks. + // We have to run it here because we need the post ID of the Navigation block to track ignored hooked blocks. + $markup = block_core_navigation_insert_hooked_blocks( $fallback_blocks, $navigation_post ); + $blocks = parse_blocks( $markup ); - if ( isset( $blocks[0]['innerBlocks'] ) ) { - $fallback_blocks = $blocks[0]['innerBlocks']; - } + if ( isset( $blocks[0]['innerBlocks'] ) ) { + $fallback_blocks = $blocks[0]['innerBlocks']; } } @@ -1621,26 +1617,15 @@ function block_core_navigation_update_ignore_hooked_blocks_meta( $post ) { /* * Do not add the `block_core_navigation_update_ignore_hooked_blocks_meta` filter in the following cases: * - If Core has added the `update_ignored_hooked_blocks_postmeta` filter already (WP >= 6.6); - * - or if the `set_ignored_hooked_blocks_metadata` function is unavailable (which is required for the filter to work. It was introduced by WP 6.5 but is not present in Gutenberg's WP 6.5 compatibility layer); * - or if the `$rest_insert_wp_navigation_core_callback` filter has already been added. */ if ( ! has_filter( 'rest_pre_insert_wp_navigation', 'update_ignored_hooked_blocks_postmeta' ) && - function_exists( 'set_ignored_hooked_blocks_metadata' ) && ! has_filter( 'rest_pre_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ) ) { add_filter( 'rest_pre_insert_wp_navigation', 'block_core_navigation_update_ignore_hooked_blocks_meta' ); } -/* - * Previous versions of Gutenberg were attaching the block_core_navigation_update_ignore_hooked_blocks_meta - * function to the `rest_insert_wp_navigation` _action_ (rather than the `rest_pre_insert_wp_navigation` _filter_). - * To avoid collisions, we need to remove the filter from that action if it's present. - */ -if ( has_filter( 'rest_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ) ) { - remove_filter( 'rest_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ); -} - /** * Hooks into the REST API response for the core/navigation block and adds the first and last inner blocks. * @@ -1678,12 +1663,10 @@ function block_core_navigation_insert_hooked_blocks_into_rest_response( $respons /* * Do not add the `block_core_navigation_insert_hooked_blocks_into_rest_response` filter in the following cases: * - If Core has added the `insert_hooked_blocks_into_rest_response` filter already (WP >= 6.6); - * - or if the `set_ignored_hooked_blocks_metadata` function is unavailable (which is required for the filter to work. It was introduced by WP 6.5 but is not present in Gutenberg's WP 6.5 compatibility layer); * - or if the `$rest_prepare_wp_navigation_core_callback` filter has already been added. */ if ( ! has_filter( 'rest_prepare_wp_navigation', 'insert_hooked_blocks_into_rest_response' ) && - function_exists( 'set_ignored_hooked_blocks_metadata' ) && ! has_filter( 'rest_prepare_wp_navigation', $rest_prepare_wp_navigation_core_callback ) ) { add_filter( 'rest_prepare_wp_navigation', 'block_core_navigation_insert_hooked_blocks_into_rest_response', 10, 3 ); diff --git a/phpunit/blocks/block-navigation-block-hooks-test.php b/phpunit/blocks/block-navigation-block-hooks-test.php index 3cb2e785a8e11a..1d3c86bf4bca4b 100644 --- a/phpunit/blocks/block-navigation-block-hooks-test.php +++ b/phpunit/blocks/block-navigation-block-hooks-test.php @@ -58,10 +58,6 @@ public function tear_down() { * @covers ::gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta */ public function test_block_core_navigation_update_ignore_hooked_blocks_meta_preserves_entities() { - if ( ! function_exists( 'set_ignored_hooked_blocks_metadata' ) ) { - $this->markTestSkipped( 'Test skipped on WordPress versions that do not included required Block Hooks functionality.' ); - } - register_block_type( 'tests/my-block', array( @@ -97,10 +93,6 @@ public function test_block_core_navigation_update_ignore_hooked_blocks_meta_pres * @covers ::gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta */ public function test_block_core_navigation_dont_modify_no_post_id() { - if ( ! function_exists( 'set_ignored_hooked_blocks_metadata' ) ) { - $this->markTestSkipped( 'Test skipped on WordPress versions that do not included required Block Hooks functionality.' ); - } - register_block_type( 'tests/my-block', array( @@ -127,10 +119,6 @@ public function test_block_core_navigation_dont_modify_no_post_id() { * @covers ::gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta */ public function test_block_core_navigation_retains_content_if_not_set() { - if ( ! function_exists( 'set_ignored_hooked_blocks_metadata' ) ) { - $this->markTestSkipped( 'Test skipped on WordPress versions that do not included required Block Hooks functionality.' ); - } - register_block_type( 'tests/my-block', array( From e8a8bd5fa794dfef2943535fdc5671c2e3965a2e Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:17:39 +0200 Subject: [PATCH 0482/1908] Hide keys starting with underscore (#64618) --- packages/editor/src/bindings/post-meta.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index 298ec4d8ba1535..87c06cc45e009a 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -88,10 +88,10 @@ export default { return null; } - // Remove footnotes from the list of fields + // Remove footnotes or private keys from the list of fields. return Object.fromEntries( Object.entries( metaFields ).filter( - ( [ key ] ) => key !== 'footnotes' + ( [ key ] ) => key !== 'footnotes' && key.charAt( 0 ) !== '_' ) ); }, From 81a09c0b6361012dca5630be7592709fc862bb66 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Wed, 21 Aug 2024 16:16:40 +0100 Subject: [PATCH 0483/1908] =?UTF-8?q?border:=201px=20=E2=86=92=20$border-w?= =?UTF-8?q?idth=20(#64680)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../src/components/downloadable-block-icon/style.scss | 2 +- .../block-editor/src/components/block-tools/style.scss | 2 +- .../components/block-variation-transforms/style.scss | 2 +- .../src/components/global-styles/style.scss | 4 ++-- .../src/components/link-control/style.scss | 2 +- .../block-editor/src/components/url-input/style.scss | 2 +- packages/commands/src/components/style.scss | 2 +- packages/components/CHANGELOG.md | 2 ++ .../components/src/circular-option-picker/style.scss | 2 +- .../components/src/custom-gradient-picker/style.scss | 2 +- .../src/components/dataviews-filters/style.scss | 2 +- .../src/components/add-new-template/style.scss | 2 +- packages/edit-site/src/components/editor/style.scss | 2 +- .../global-styles/font-library-modal/style.scss | 2 +- .../editor/src/components/block-manager/style.scss | 4 ++-- .../src/components/error-boundary/style.native.scss | 2 +- .../src/components/save-publish-panels/style.scss | 6 +++--- packages/widgets/src/blocks/legacy-widget/editor.scss | 10 +++++----- packages/widgets/src/blocks/widget-group/editor.scss | 2 +- 19 files changed, 28 insertions(+), 26 deletions(-) diff --git a/packages/block-directory/src/components/downloadable-block-icon/style.scss b/packages/block-directory/src/components/downloadable-block-icon/style.scss index 57a792b3f7f6e3..e11c1f05e864f8 100644 --- a/packages/block-directory/src/components/downloadable-block-icon/style.scss +++ b/packages/block-directory/src/components/downloadable-block-icon/style.scss @@ -3,5 +3,5 @@ width: $button-size * 1.5; height: $button-size * 1.5; vertical-align: middle; - border: 1px solid $gray-300; + border: $border-width solid $gray-300; } diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index 6bf1f91cb08682..000be3d239e8d9 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -231,7 +231,7 @@ } .block-editor-block-parent-selector__button { - border: 1px solid $gray-900; + border: $border-width solid $gray-900; padding-right: 6px; padding-left: 6px; background-color: $white; diff --git a/packages/block-editor/src/components/block-variation-transforms/style.scss b/packages/block-editor/src/components/block-variation-transforms/style.scss index b828bc6020bfbe..cfb0ff04a5bc80 100644 --- a/packages/block-editor/src/components/block-variation-transforms/style.scss +++ b/packages/block-editor/src/components/block-variation-transforms/style.scss @@ -3,7 +3,7 @@ width: 100%; .components-dropdown-menu__toggle { - border: 1px solid $gray-700; + border: $border-width solid $gray-700; border-radius: $radius-block-ui; min-height: 30px; width: 100%; diff --git a/packages/block-editor/src/components/global-styles/style.scss b/packages/block-editor/src/components/global-styles/style.scss index acd5fd6f41c7bc..e979ed77f53da2 100644 --- a/packages/block-editor/src/components/global-styles/style.scss +++ b/packages/block-editor/src/components/global-styles/style.scss @@ -73,7 +73,7 @@ .block-editor-global-styles-background-panel__inspector-media-replace-container { - border: 1px solid $gray-300; + border: $border-width solid $gray-300; border-radius: 2px; // Full width. ToolsPanel lays out children in a grid. grid-column: 1 / -1; @@ -101,7 +101,7 @@ } .block-editor-global-styles-background-panel__image-tools-panel-item { - border: 1px solid $gray-300; + border: $border-width solid $gray-300; border-radius: 2px; // Full width. ToolsPanel lays out children in a grid. diff --git a/packages/block-editor/src/components/link-control/style.scss b/packages/block-editor/src/components/link-control/style.scss index c0cf8a3bc2afe9..1390a285fe163e 100644 --- a/packages/block-editor/src/components/link-control/style.scss +++ b/packages/block-editor/src/components/link-control/style.scss @@ -77,7 +77,7 @@ $block-editor-link-control-number-of-actions: 1; &.block-editor-url-input input[type="text"].block-editor-url-input__input { @include input-control; display: block; - border: 1px solid $gray-600; + border: $border-width solid $gray-600; border-radius: $radius-block-ui; height: $button-size-next-default-40px; // components do not properly support unstable-large yet. margin: 0; diff --git a/packages/block-editor/src/components/url-input/style.scss b/packages/block-editor/src/components/url-input/style.scss index e6ba17a71aaa5b..5afb22269765e2 100644 --- a/packages/block-editor/src/components/url-input/style.scss +++ b/packages/block-editor/src/components/url-input/style.scss @@ -121,7 +121,7 @@ $input-size: 300px; .block-editor-url-input__button-modal { box-shadow: $elevation-x-small; - border: 1px solid $gray-300; + border: $border-width solid $gray-300; background: $white; } diff --git a/packages/commands/src/components/style.scss b/packages/commands/src/components/style.scss index ff6bf1090b0dcd..e69853bad95997 100644 --- a/packages/commands/src/components/style.scss +++ b/packages/commands/src/components/style.scss @@ -30,7 +30,7 @@ .components-button { height: $grid-unit-70; width: $grid-unit-70; - border: 1px solid $gray-600; + border: $border-width solid $gray-600; border-right: 0; justify-content: center; border-radius: $radius-block-ui 0 0 $radius-block-ui; diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 7a48717419605a..cd60da190996d6 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -61,6 +61,8 @@ - `Popover`: Replace references to deprecated styling variables ([#64655](https://github.com/WordPress/gutenberg/pull/64655)). - `Snackbar`: Replace references to deprecated styling variables ([#64655](https://github.com/WordPress/gutenberg/pull/64655)). - `TextareaControl`: Update styles ([#64586](https://github.com/WordPress/gutenberg/pull/64586)). +- `CircularOptionPicker`: Update hard-coded border-width value ([#64680](https://github.com/WordPress/gutenberg/pull/64680)). +- `CustomGradientPicker`: Update hard-coded border-width value ([#64680](https://github.com/WordPress/gutenberg/pull/64680)). ### Bug Fixes diff --git a/packages/components/src/circular-option-picker/style.scss b/packages/components/src/circular-option-picker/style.scss index 74a380e0936be8..24b67eb7e7021e 100644 --- a/packages/components/src/circular-option-picker/style.scss +++ b/packages/components/src/circular-option-picker/style.scss @@ -109,7 +109,7 @@ $color-palette-circle-spacing: 12px; border-radius: $radius-round; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); // Show a thin circular outline in Windows high contrast mode, otherwise the button is invisible. - border: 1px solid transparent; + border: $border-width solid transparent; box-sizing: inherit; } diff --git a/packages/components/src/custom-gradient-picker/style.scss b/packages/components/src/custom-gradient-picker/style.scss index a8c6d6b872caf0..a0b616d6ca1d72 100644 --- a/packages/components/src/custom-gradient-picker/style.scss +++ b/packages/components/src/custom-gradient-picker/style.scss @@ -112,7 +112,7 @@ $components-custom-gradient-picker__padding: $grid-unit-20; // 48px container, 1 &.is-pressed { > svg { background: $white; - border: 1px solid $gray-600; + border: $border-width solid $gray-600; border-radius: 2px; } } diff --git a/packages/dataviews/src/components/dataviews-filters/style.scss b/packages/dataviews/src/components/dataviews-filters/style.scss index 6912b5cc483164..3853aba960e790 100644 --- a/packages/dataviews/src/components/dataviews-filters/style.scss +++ b/packages/dataviews/src/components/dataviews-filters/style.scss @@ -48,7 +48,7 @@ .dataviews-filters__summary-chip { border-radius: $grid-unit-20; - border: 1px solid transparent; + border: $border-width solid transparent; cursor: pointer; padding: $grid-unit-05 $grid-unit-15; min-height: $grid-unit-40; diff --git a/packages/edit-site/src/components/add-new-template/style.scss b/packages/edit-site/src/components/add-new-template/style.scss index 5f9cd89b74ce2c..922083d14b75eb 100644 --- a/packages/edit-site/src/components/add-new-template/style.scss +++ b/packages/edit-site/src/components/add-new-template/style.scss @@ -81,7 +81,7 @@ } .edit-site-custom-template-modal__no-results { - border: 1px solid $gray-400; + border: $border-width solid $gray-400; border-radius: $radius-block-ui; padding: $grid-unit-20; } diff --git a/packages/edit-site/src/components/editor/style.scss b/packages/edit-site/src/components/editor/style.scss index fbc231eb757c57..10efff92af6434 100644 --- a/packages/edit-site/src/components/editor/style.scss +++ b/packages/edit-site/src/components/editor/style.scss @@ -12,7 +12,7 @@ box-sizing: border-box; width: $sidebar-width; background-color: $white; - border: 1px dotted $gray-300; + border: $border-width dotted $gray-300; padding: $grid-unit-30; display: flex; justify-content: center; diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss index ce5197a73cabf9..a9a0784cbcb5a1 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss +++ b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss @@ -92,7 +92,7 @@ $footer-height: 70px; } .font-library-modal__font-card { - border: 1px solid $gray-200; + border: $border-width solid $gray-200; width: 100%; height: auto; padding: $grid-unit-20; diff --git a/packages/editor/src/components/block-manager/style.scss b/packages/editor/src/components/block-manager/style.scss index 62e5c9d60cb178..411ee9faf34f75 100644 --- a/packages/editor/src/components/block-manager/style.scss +++ b/packages/editor/src/components/block-manager/style.scss @@ -9,8 +9,8 @@ } .editor-block-manager__disabled-blocks-count { - border: 1px solid $gray-300; - border-width: 1px 0; + border: $border-width solid $gray-300; + border-width: $border-width 0; // Cover up horizontal areas off the sides of the box rectangle box-shadow: -$grid-unit-40 0 0 0 $white, $grid-unit-40 0 0 0 $white; padding: $grid-unit-10; diff --git a/packages/editor/src/components/error-boundary/style.native.scss b/packages/editor/src/components/error-boundary/style.native.scss index 1ff5c1799915d6..413242a1779947 100644 --- a/packages/editor/src/components/error-boundary/style.native.scss +++ b/packages/editor/src/components/error-boundary/style.native.scss @@ -86,7 +86,7 @@ } .copy-button__container--secondary { - border: 1px #c6c6c8; + border: $border-width #c6c6c8; background-color: $white; } diff --git a/packages/editor/src/components/save-publish-panels/style.scss b/packages/editor/src/components/save-publish-panels/style.scss index 74dcf113f0479b..1de6420a0a6837 100644 --- a/packages/editor/src/components/save-publish-panels/style.scss +++ b/packages/editor/src/components/save-publish-panels/style.scss @@ -3,7 +3,7 @@ .editor-layout__toggle-sidebar-panel, .editor-layout__toggle-entities-saved-states-panel { z-index: z-index(".editor-layout__toggle-sidebar-panel"); - position: fixed !important; // Need to override the default relative positionning + position: fixed !important; // Necessary to override the default relative positioning. top: -9999em; bottom: auto; left: auto; @@ -11,8 +11,8 @@ box-sizing: border-box; width: $sidebar-width; background-color: $white; - border: 1px dotted $gray-300; - height: auto !important; // Need to override the default sidebar positionnings + border: $border-width dotted $gray-300; + height: auto !important; // Necessary to override the default sidebar positioning. padding: $grid-unit-30; display: flex; justify-content: center; diff --git a/packages/widgets/src/blocks/legacy-widget/editor.scss b/packages/widgets/src/blocks/legacy-widget/editor.scss index 78bcf533ac5e9d..6b04ce0a407e43 100644 --- a/packages/widgets/src/blocks/legacy-widget/editor.scss +++ b/packages/widgets/src/blocks/legacy-widget/editor.scss @@ -4,9 +4,9 @@ } background: $white; border-radius: $radius-block-ui; - border: 1px solid $gray-900; - padding: $grid-unit-15 - 1px; // Subtract the border width. - max-height: calc(100vh - 2px); // Subtract the border width (both top and bottom). + border: $border-width solid $gray-900; + padding: $grid-unit-15 - $border-width; + max-height: calc(100vh - #{ $border-width } - #{ $border-width }); overflow-y: scroll; .wp-block-legacy-widget__edit-form-title { @@ -57,7 +57,7 @@ font-family: system-ui; background-color: transparent; box-sizing: border-box; - border: 1px solid $gray-700; + border: $border-width solid $gray-700; border-radius: 3px; box-shadow: none; color: $black; @@ -96,7 +96,7 @@ &:hover::after { border-radius: $radius-block-ui; - border: 1px solid $gray-600; + border: $border-width solid $gray-600; bottom: 0; content: ""; left: 0; diff --git a/packages/widgets/src/blocks/widget-group/editor.scss b/packages/widgets/src/blocks/widget-group/editor.scss index f854c792eeb240..38798ef34c7c6e 100644 --- a/packages/widgets/src/blocks/widget-group/editor.scss +++ b/packages/widgets/src/blocks/widget-group/editor.scss @@ -1,7 +1,7 @@ .wp-block-widget-group { &.has-child-selected::after { border-radius: $radius-block-ui; - border: 1px solid var(--wp-admin-theme-color); + border: $border-width solid var(--wp-admin-theme-color); bottom: 0; content: ""; left: 0; From be2d49fa34bca7f62c6f0bdb85b1bc77b6ed26c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 21 Aug 2024 17:26:39 +0200 Subject: [PATCH 0484/1908] DataViews: do not display element descriptions in filters (#64674) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/dataviews/CHANGELOG.md | 2 ++ .../src/components/dataviews-filters/search-widget.tsx | 9 +-------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index d51cf9c969016d..8fb42a3d406646 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -9,6 +9,8 @@ ## Internal - The "move left/move right" controls in the table layout (popup displayed on cliking header) are always visible. ([#64646](https://github.com/WordPress/gutenberg/pull/64646)). Before this, its visibility depending on filters, enableSorting, and enableHiding. +- Filters no longer display the elements' description. ([#64674](https://github.com/WordPress/gutenberg/pull/64674)) + ## 4.1.0 (2024-08-07) diff --git a/packages/dataviews/src/components/dataviews-filters/search-widget.tsx b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx index 3516ff23b28503..ca24de59b1ea73 100644 --- a/packages/dataviews/src/components/dataviews-filters/search-widget.tsx +++ b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx @@ -184,14 +184,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) { <Icon icon={ check } /> ) } </span> - <span> - { element.label } - { !! element.description && ( - <span className="dataviews-filters__search-widget-listitem-description"> - { element.description } - </span> - ) } - </span> + <span>{ element.label }</span> </Ariakit.CompositeHover> ) ) } </Composite> From e6bc14c0d71d1a7539adecd6b6c0962d6c3a0bcf Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Wed, 21 Aug 2024 16:50:15 +0100 Subject: [PATCH 0485/1908] Data views: Update search appearance in narrow containers (#64681) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/dataviews/CHANGELOG.md | 4 ++++ .../dataviews/src/components/dataviews/index.tsx | 10 +++++++--- .../dataviews/src/components/dataviews/style.scss | 12 ------------ 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 8fb42a3d406646..5969d8b462d65b 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -12,6 +12,10 @@ - Filters no longer display the elements' description. ([#64674](https://github.com/WordPress/gutenberg/pull/64674)) +## Enhancements + +- Adjust layout of filter / actions row, increase width of search control when the container is narrower. ([#64681](https://github.com/WordPress/gutenberg/pull/64681)). + ## 4.1.0 (2024-08-07) ## Internal diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index c8a34028d78903..59167a9fe04188 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -118,11 +118,15 @@ export default function DataViews< Item >( { <div className="dataviews-wrapper"> <HStack alignment="top" - justify="start" + justify="space-between" className="dataviews__view-actions" spacing={ 1 } > - <HStack justify="start" wrap> + <HStack + justify="start" + expanded={ false } + className="dataviews__search" + > { search && <DataViewsSearch label={ searchLabel } /> } <FilterVisibilityToggle filters={ filters } @@ -133,12 +137,12 @@ export default function DataViews< Item >( { isShowingFilter={ isShowingFilter } /> </HStack> - <DataViewsBulkActions /> <HStack spacing={ 1 } expanded={ false } style={ { flexShrink: 0 } } > + <DataViewsBulkActions /> <DataViewsViewConfig defaultLayouts={ defaultLayouts } density={ density } diff --git a/packages/dataviews/src/components/dataviews/style.scss b/packages/dataviews/src/components/dataviews/style.scss index 742c8c42134dfd..1ce75d36020a78 100644 --- a/packages/dataviews/src/components/dataviews/style.scss +++ b/packages/dataviews/src/components/dataviews/style.scss @@ -18,12 +18,6 @@ left: 0; transition: padding ease-out 0.1s; @include reduce-motion("transition"); - - .components-search-control { - .components-base-control__field { - max-width: 240px; - } - } } .dataviews-view-list__primary-field, @@ -82,12 +76,6 @@ .dataviews__view-actions, .dataviews-filters__container { padding: $grid-unit-15 $grid-unit-30; - - .components-search-control { - .components-base-control__field { - max-width: 112px; - } - } } .dataviews-view-grid, From aef91dc03199e8b5dbfbad83e35805f392a08f01 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 21 Aug 2024 15:55:40 +0000 Subject: [PATCH 0486/1908] Bump plugin version to 19.1.0-rc.1 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 66f0aa31a65baa..2cd33a570f5857 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.0.0 + * Version: 19.1.0-rc.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 8db4860e895854..cead8e172a5575 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.0.0", + "version": "19.1.0-rc.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.0.0", + "version": "19.1.0-rc.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 5b0bdf823e617a..7349e60eb4c210 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.0.0", + "version": "19.1.0-rc.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From fef7a6bd5928b4ee28a964ba26cfbd693564c702 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 21 Aug 2024 16:14:05 +0000 Subject: [PATCH 0487/1908] Update changelog files --- packages/a11y/CHANGELOG.md | 2 ++ packages/a11y/package.json | 2 +- packages/annotations/CHANGELOG.md | 2 ++ packages/annotations/package.json | 2 +- packages/api-fetch/CHANGELOG.md | 2 ++ packages/api-fetch/package.json | 2 +- packages/autop/CHANGELOG.md | 2 ++ packages/autop/package.json | 2 +- packages/babel-plugin-import-jsx-pragma/CHANGELOG.md | 2 ++ packages/babel-plugin-import-jsx-pragma/package.json | 2 +- packages/babel-plugin-makepot/CHANGELOG.md | 2 ++ packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/CHANGELOG.md | 2 ++ packages/babel-preset-default/package.json | 2 +- packages/base-styles/CHANGELOG.md | 2 ++ packages/base-styles/package.json | 2 +- packages/blob/CHANGELOG.md | 2 ++ packages/blob/package.json | 2 +- packages/block-directory/CHANGELOG.md | 2 ++ packages/block-directory/package.json | 2 +- packages/block-editor/CHANGELOG.md | 2 ++ packages/block-editor/package.json | 2 +- packages/block-library/CHANGELOG.md | 2 ++ packages/block-library/package.json | 2 +- packages/block-serialization-default-parser/CHANGELOG.md | 2 ++ packages/block-serialization-default-parser/package.json | 2 +- packages/block-serialization-spec-parser/CHANGELOG.md | 2 ++ packages/block-serialization-spec-parser/package.json | 2 +- packages/blocks/CHANGELOG.md | 2 ++ packages/blocks/package.json | 2 +- packages/browserslist-config/CHANGELOG.md | 2 ++ packages/browserslist-config/package.json | 2 +- packages/commands/CHANGELOG.md | 2 ++ packages/commands/package.json | 2 +- packages/components/CHANGELOG.md | 2 ++ packages/components/package.json | 2 +- packages/compose/CHANGELOG.md | 2 ++ packages/compose/package.json | 2 +- packages/core-commands/CHANGELOG.md | 2 ++ packages/core-commands/package.json | 2 +- packages/core-data/CHANGELOG.md | 2 ++ packages/core-data/package.json | 2 +- packages/create-block-interactive-template/CHANGELOG.md | 2 ++ packages/create-block-interactive-template/package.json | 2 +- packages/create-block-tutorial-template/CHANGELOG.md | 2 ++ packages/create-block-tutorial-template/package.json | 2 +- packages/create-block/CHANGELOG.md | 2 ++ packages/create-block/package.json | 2 +- packages/customize-widgets/CHANGELOG.md | 2 ++ packages/customize-widgets/package.json | 2 +- packages/data-controls/CHANGELOG.md | 2 ++ packages/data-controls/package.json | 2 +- packages/data/CHANGELOG.md | 2 ++ packages/data/package.json | 2 +- packages/dataviews/CHANGELOG.md | 2 ++ packages/dataviews/package.json | 2 +- packages/date/CHANGELOG.md | 2 ++ packages/date/package.json | 2 +- packages/dependency-extraction-webpack-plugin/CHANGELOG.md | 2 ++ packages/dependency-extraction-webpack-plugin/package.json | 2 +- packages/deprecated/CHANGELOG.md | 2 ++ packages/deprecated/package.json | 2 +- packages/docgen/CHANGELOG.md | 2 ++ packages/docgen/package.json | 2 +- packages/dom-ready/CHANGELOG.md | 2 ++ packages/dom-ready/package.json | 2 +- packages/dom/CHANGELOG.md | 2 ++ packages/dom/package.json | 2 +- packages/e2e-test-utils-playwright/CHANGELOG.md | 2 ++ packages/e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/CHANGELOG.md | 2 ++ packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/CHANGELOG.md | 2 ++ packages/e2e-tests/package.json | 2 +- packages/edit-post/CHANGELOG.md | 2 ++ packages/edit-post/package.json | 2 +- packages/edit-site/CHANGELOG.md | 2 ++ packages/edit-site/package.json | 2 +- packages/edit-widgets/CHANGELOG.md | 2 ++ packages/edit-widgets/package.json | 2 +- packages/editor/CHANGELOG.md | 2 ++ packages/editor/package.json | 2 +- packages/element/CHANGELOG.md | 2 ++ packages/element/package.json | 2 +- packages/env/CHANGELOG.md | 2 ++ packages/env/package.json | 2 +- packages/escape-html/CHANGELOG.md | 2 ++ packages/escape-html/package.json | 2 +- packages/eslint-plugin/CHANGELOG.md | 2 ++ packages/eslint-plugin/package.json | 2 +- packages/format-library/CHANGELOG.md | 2 ++ packages/format-library/package.json | 2 +- packages/hooks/CHANGELOG.md | 2 ++ packages/hooks/package.json | 2 +- packages/html-entities/CHANGELOG.md | 2 ++ packages/html-entities/package.json | 2 +- packages/i18n/CHANGELOG.md | 2 ++ packages/i18n/package.json | 2 +- packages/icons/CHANGELOG.md | 2 ++ packages/icons/package.json | 2 +- packages/interactivity-router/CHANGELOG.md | 2 ++ packages/interactivity-router/package.json | 2 +- packages/interactivity/CHANGELOG.md | 2 ++ packages/interactivity/package.json | 2 +- packages/interface/CHANGELOG.md | 2 ++ packages/interface/package.json | 2 +- packages/is-shallow-equal/CHANGELOG.md | 2 ++ packages/is-shallow-equal/package.json | 2 +- packages/jest-console/CHANGELOG.md | 2 ++ packages/jest-console/package.json | 2 +- packages/jest-preset-default/CHANGELOG.md | 2 ++ packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/CHANGELOG.md | 2 ++ packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/CHANGELOG.md | 2 ++ packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/CHANGELOG.md | 2 ++ packages/keycodes/package.json | 2 +- packages/lazy-import/CHANGELOG.md | 2 ++ packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/CHANGELOG.md | 2 ++ packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/CHANGELOG.md | 2 ++ packages/media-utils/package.json | 2 +- packages/notices/CHANGELOG.md | 2 ++ packages/notices/package.json | 2 +- packages/npm-package-json-lint-config/CHANGELOG.md | 2 ++ packages/npm-package-json-lint-config/package.json | 2 +- packages/nux/CHANGELOG.md | 2 ++ packages/nux/package.json | 2 +- packages/patterns/CHANGELOG.md | 2 ++ packages/patterns/package.json | 2 +- packages/plugins/CHANGELOG.md | 2 ++ packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/CHANGELOG.md | 2 ++ packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/CHANGELOG.md | 2 ++ packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/CHANGELOG.md | 2 ++ packages/preferences-persistence/package.json | 2 +- packages/preferences/CHANGELOG.md | 2 ++ packages/preferences/package.json | 2 +- packages/prettier-config/CHANGELOG.md | 2 ++ packages/prettier-config/package.json | 2 +- packages/primitives/CHANGELOG.md | 2 ++ packages/primitives/package.json | 2 +- packages/priority-queue/CHANGELOG.md | 2 ++ packages/priority-queue/package.json | 2 +- packages/private-apis/CHANGELOG.md | 2 ++ packages/private-apis/package.json | 2 +- packages/project-management-automation/CHANGELOG.md | 2 ++ packages/project-management-automation/package.json | 2 +- packages/react-i18n/CHANGELOG.md | 2 ++ packages/react-i18n/package.json | 2 +- packages/readable-js-assets-webpack-plugin/CHANGELOG.md | 2 ++ packages/readable-js-assets-webpack-plugin/package.json | 2 +- packages/redux-routine/CHANGELOG.md | 2 ++ packages/redux-routine/package.json | 2 +- packages/reusable-blocks/CHANGELOG.md | 2 ++ packages/reusable-blocks/package.json | 2 +- packages/rich-text/CHANGELOG.md | 2 ++ packages/rich-text/package.json | 2 +- packages/router/CHANGELOG.md | 2 ++ packages/router/package.json | 2 +- packages/scripts/CHANGELOG.md | 2 ++ packages/scripts/package.json | 2 +- packages/server-side-render/CHANGELOG.md | 2 ++ packages/server-side-render/package.json | 2 +- packages/shortcode/CHANGELOG.md | 2 ++ packages/shortcode/package.json | 2 +- packages/style-engine/CHANGELOG.md | 2 ++ packages/style-engine/package.json | 2 +- packages/stylelint-config/CHANGELOG.md | 2 ++ packages/stylelint-config/package.json | 2 +- packages/sync/CHANGELOG.md | 2 ++ packages/sync/package.json | 2 +- packages/token-list/CHANGELOG.md | 2 ++ packages/token-list/package.json | 2 +- packages/undo-manager/CHANGELOG.md | 2 ++ packages/undo-manager/package.json | 2 +- packages/url/CHANGELOG.md | 2 ++ packages/url/package.json | 2 +- packages/viewport/CHANGELOG.md | 2 ++ packages/viewport/package.json | 2 +- packages/warning/CHANGELOG.md | 2 ++ packages/warning/package.json | 2 +- packages/widgets/CHANGELOG.md | 2 ++ packages/widgets/package.json | 2 +- packages/wordcount/CHANGELOG.md | 2 ++ packages/wordcount/package.json | 2 +- 190 files changed, 285 insertions(+), 95 deletions(-) diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index 7e7a192fe2cec7..5a90a6cc98f0de 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/a11y/package.json b/packages/a11y/package.json index c9bff2d5c73752..16c3fd0e329989 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/CHANGELOG.md b/packages/annotations/CHANGELOG.md index 4fd75757858130..b3e0dbab635b8b 100644 --- a/packages/annotations/CHANGELOG.md +++ b/packages/annotations/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.6.0 (2024-08-21) + ## 3.5.0 (2024-08-07) ## 3.4.0 (2024-07-24) diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 7706e6e0b345e9..bd3588e01f0386 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.5.0", + "version": "3.6.0-prerelease", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/CHANGELOG.md b/packages/api-fetch/CHANGELOG.md index 38185a29d5e723..49319c18ab7543 100644 --- a/packages/api-fetch/CHANGELOG.md +++ b/packages/api-fetch/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.6.0 (2024-08-21) + ## 7.5.0 (2024-08-07) ## 7.4.0 (2024-07-24) diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 4c5ee98edcd12a..a1558d26e26640 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.5.0", + "version": "7.6.0-prerelease", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/CHANGELOG.md b/packages/autop/CHANGELOG.md index 28c66fc53c0218..353495eae8983d 100644 --- a/packages/autop/CHANGELOG.md +++ b/packages/autop/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/autop/package.json b/packages/autop/package.json index af8830570bd049..578de505767bd0 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md index a8b85caf3939cb..d96d2315e2a51e 100644 --- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md +++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index 3cec94c138f99a..09d09bb957ed0d 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/CHANGELOG.md b/packages/babel-plugin-makepot/CHANGELOG.md index ad77a8bda2e3cd..98da250e2ba6b6 100644 --- a/packages/babel-plugin-makepot/CHANGELOG.md +++ b/packages/babel-plugin-makepot/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.6.0 (2024-08-21) + ## 6.5.0 (2024-08-07) ## 6.4.0 (2024-07-24) diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index 6540cb5bf4cd7d..dd741954d4c71e 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.5.0", + "version": "6.6.0-prerelease", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index 39ff7b2098ba71..43c9675fcb885b 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.6.0 (2024-08-21) + ## 8.5.0 (2024-08-07) ## 8.4.0 (2024-07-24) diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 0ee883a0d4ee1f..2b8e044fcb02b5 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.5.0", + "version": "8.6.0-prerelease", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/CHANGELOG.md b/packages/base-styles/CHANGELOG.md index c68e328b68421b..ce98cebeae1c2a 100644 --- a/packages/base-styles/CHANGELOG.md +++ b/packages/base-styles/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index 9c243e87d1f2f1..821f35a1f82ec3 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md index 56c1ee2a2554b0..5c21e96d7269cd 100644 --- a/packages/blob/CHANGELOG.md +++ b/packages/blob/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/blob/package.json b/packages/blob/package.json index 51987239c14515..66968a12e0e767 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/CHANGELOG.md b/packages/block-directory/CHANGELOG.md index 8c25a168e585c8..4d15343f0c0926 100644 --- a/packages/block-directory/CHANGELOG.md +++ b/packages/block-directory/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 78a786b4c7d497..cbf57e9c62ed4b 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 09792d9dca5dac..0b365c18ae8ad4 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.1.0 (2024-08-21) + ## 14.0.0 (2024-08-07) ### Breaking Changes diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 02765376e314b6..50918321569fd3 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.0.0", + "version": "14.1.0-prerelease", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index b14275fdad3988..319d2b04a31687 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.6.0 (2024-08-21) + ## 9.5.0 (2024-08-07) ### New Feature diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 4948fed4e65a5b..4b98185de62d97 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.5.0", + "version": "9.6.0-prerelease", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/CHANGELOG.md b/packages/block-serialization-default-parser/CHANGELOG.md index 97ab311854c9b7..7357d96bdcf7c5 100644 --- a/packages/block-serialization-default-parser/CHANGELOG.md +++ b/packages/block-serialization-default-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index c3237f9282f749..db61600cf496a2 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/CHANGELOG.md b/packages/block-serialization-spec-parser/CHANGELOG.md index 15d6292a59b6ed..d4091d455937d7 100644 --- a/packages/block-serialization-spec-parser/CHANGELOG.md +++ b/packages/block-serialization-spec-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 918ad0f2ed78b3..001ab1d920352d 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 9768d958f0382c..ce7417db1f35af 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 13.6.0 (2024-08-21) + ## 13.5.0 (2024-08-07) ## 13.4.0 (2024-07-24) diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 43bcc5c587071e..fe35929a6fd354 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.5.0", + "version": "13.6.0-prerelease", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/CHANGELOG.md b/packages/browserslist-config/CHANGELOG.md index 676c38509b22e5..2d0fafa7bc9889 100644 --- a/packages/browserslist-config/CHANGELOG.md +++ b/packages/browserslist-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.6.0 (2024-08-21) + ## 6.5.0 (2024-08-07) ## 6.4.0 (2024-07-24) diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 429b3a9f82f339..ce38298f4200a1 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.5.0", + "version": "6.6.0-prerelease", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/CHANGELOG.md b/packages/commands/CHANGELOG.md index 228f06635ada65..86cefcc971b249 100644 --- a/packages/commands/CHANGELOG.md +++ b/packages/commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.6.0 (2024-08-21) + ## 1.5.0 (2024-08-07) ## 1.4.0 (2024-07-24) diff --git a/packages/commands/package.json b/packages/commands/package.json index ea504a589acfd8..b4efa95538b37e 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.5.0", + "version": "1.6.0-prerelease", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index cd60da190996d6..c98f2bfa38aafd 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 28.6.0 (2024-08-21) + ### Deprecations - Deprecate bottom margin on the following `BaseControl`-based components. Set the `__nextHasNoMarginBottom` prop to true to start opting into the new styles, which will become the default in a future version ([#64408](https://github.com/WordPress/gutenberg/pull/64408)). diff --git a/packages/components/package.json b/packages/components/package.json index 5469e52bed8c68..c8344ac5013f61 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.5.0", + "version": "28.6.0-prerelease", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index 6595c9ae336855..951f70604f41c6 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.6.0 (2024-08-21) + ## 7.5.0 (2024-08-07) ## 7.4.0 (2024-07-24) diff --git a/packages/compose/package.json b/packages/compose/package.json index 2a4dcb02803c58..605f1866d9e4b4 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.5.0", + "version": "7.6.0-prerelease", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/CHANGELOG.md b/packages/core-commands/CHANGELOG.md index fa46608d63254b..16bf8c495eb03c 100644 --- a/packages/core-commands/CHANGELOG.md +++ b/packages/core-commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.6.0 (2024-08-21) + ## 1.5.0 (2024-08-07) ## 1.4.0 (2024-07-24) diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index d29688cfbcedf4..ac061baf5fd2a6 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.5.0", + "version": "1.6.0-prerelease", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md index e3477da97811fe..caed77084733bf 100644 --- a/packages/core-data/CHANGELOG.md +++ b/packages/core-data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.6.0 (2024-08-21) + ## 7.5.0 (2024-08-07) ## 7.4.0 (2024-07-24) diff --git a/packages/core-data/package.json b/packages/core-data/package.json index d736b2b7b1b936..88fac357dfae9e 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.5.0", + "version": "7.6.0-prerelease", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/CHANGELOG.md b/packages/create-block-interactive-template/CHANGELOG.md index 769999da2d4ecc..9b061370752df3 100644 --- a/packages/create-block-interactive-template/CHANGELOG.md +++ b/packages/create-block-interactive-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.6.0 (2024-08-21) + ## 2.5.0 (2024-08-07) ## 2.4.0 (2024-07-24) diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index 751243b8b8021b..cb7b96ad19b681 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.5.0", + "version": "2.6.0-prerelease", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/CHANGELOG.md b/packages/create-block-tutorial-template/CHANGELOG.md index 5c5856f174b0eb..ddcf23926e52a0 100644 --- a/packages/create-block-tutorial-template/CHANGELOG.md +++ b/packages/create-block-tutorial-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index 2a344a094a4b41..ebf97cb579cb2a 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index 024ef7abc8c69e..b0dae14eb13c87 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.49.0 (2024-08-21) + ## 4.48.0 (2024-08-07) ## 4.47.0 (2024-07-24) diff --git a/packages/create-block/package.json b/packages/create-block/package.json index f0a91d54c14963..5c97dc83e09f64 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.48.0", + "version": "4.49.0-prerelease", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/CHANGELOG.md b/packages/customize-widgets/CHANGELOG.md index 1065adf40e15d3..aeec00430f47d1 100644 --- a/packages/customize-widgets/CHANGELOG.md +++ b/packages/customize-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index f619837ae573e0..52820914a97600 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/CHANGELOG.md b/packages/data-controls/CHANGELOG.md index f0d753d95360ca..ae38ef764c535d 100644 --- a/packages/data-controls/CHANGELOG.md +++ b/packages/data-controls/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 40dfbdf307d2c2..d0de45f0640bb5 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index a4686283d050c7..52b88a1c5d4297 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.6.0 (2024-08-21) + ## 10.5.0 (2024-08-07) ## 10.4.0 (2024-07-24) diff --git a/packages/data/package.json b/packages/data/package.json index b987476d49bd90..3753b8131a9583 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.5.0", + "version": "10.6.0-prerelease", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 5969d8b462d65b..bf93b9e52f657a 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.2.0 (2024-08-21) + ## New features - Support using a component for field headers or names by providing a `header` property in the field object. The string `label` property (or `id`) is still mandatory. ([#64642](https://github.com/WordPress/gutenberg/pull/64642)). diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index 8b72104f106d02..ab0f266929f430 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.1.0", + "version": "4.2.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md index bcd7d0d80a6909..3940814a2f5d88 100644 --- a/packages/date/CHANGELOG.md +++ b/packages/date/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/date/package.json b/packages/date/package.json index 69871d61e284fa..5069d271e05c60 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index 2fcbf4b78c22c9..ddfd7fb32710a7 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.6.0 (2024-08-21) + ## 6.5.0 (2024-08-07) ## 6.4.0 (2024-07-24) diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index ebd6e4ef19fd69..bc9967892d47db 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.5.0", + "version": "6.6.0-prerelease", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/CHANGELOG.md b/packages/deprecated/CHANGELOG.md index 6b5c50cb2b55a6..5a19167c70965e 100644 --- a/packages/deprecated/CHANGELOG.md +++ b/packages/deprecated/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 80f4c62e2a84b9..af3e1e49475057 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/CHANGELOG.md b/packages/docgen/CHANGELOG.md index 8bde3b25cbbd26..db2451d2184338 100644 --- a/packages/docgen/CHANGELOG.md +++ b/packages/docgen/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.6.0 (2024-08-21) + ## 2.5.0 (2024-08-07) ## 2.4.0 (2024-07-24) diff --git a/packages/docgen/package.json b/packages/docgen/package.json index b3f6e12e0210cb..6c424b9097d5a5 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.5.0", + "version": "2.6.0-prerelease", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/CHANGELOG.md b/packages/dom-ready/CHANGELOG.md index 652b3d9a738ea5..45cf7f02b51061 100644 --- a/packages/dom-ready/CHANGELOG.md +++ b/packages/dom-ready/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 583f03f75d2ae6..463fc3ed0ddda7 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/CHANGELOG.md b/packages/dom/CHANGELOG.md index a337ee7214611f..6444d64321a28d 100644 --- a/packages/dom/CHANGELOG.md +++ b/packages/dom/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/dom/package.json b/packages/dom/package.json index 6297fa9d696e12..24230be5f8ba98 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/CHANGELOG.md b/packages/e2e-test-utils-playwright/CHANGELOG.md index fa56cd3b2aaaee..2344239ebcdb27 100644 --- a/packages/e2e-test-utils-playwright/CHANGELOG.md +++ b/packages/e2e-test-utils-playwright/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.6.0 (2024-08-21) + ## 1.5.0 (2024-08-07) ## 1.4.0 (2024-07-24) diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 521cbb5c753aa7..968f942f3872b0 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.5.0", + "version": "1.6.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index fa27436da8f42a..da33570821a311 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 11.6.0 (2024-08-21) + ## 11.5.0 (2024-08-07) ## 11.4.0 (2024-07-24) diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index dc36a8fb4194bd..cb14bfa532e9e9 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.5.0", + "version": "11.6.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md index 2a9317924a8fec..568e58c11cdb0a 100644 --- a/packages/e2e-tests/CHANGELOG.md +++ b/packages/e2e-tests/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.6.0 (2024-08-21) + ## 8.5.0 (2024-08-07) ## 8.4.0 (2024-07-24) diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index c826229a6e7a43..bb9ab39b165ad4 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.5.0", + "version": "8.6.0-prerelease", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index 6febaa5df4542c..c715ddebcd82a1 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.6.0 (2024-08-21) + ## 8.5.0 (2024-08-07) ## 8.4.0 (2024-07-24) diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 8fd1bafe1ab491..2d502f5d2fee35 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.5.0", + "version": "8.6.0-prerelease", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/CHANGELOG.md b/packages/edit-site/CHANGELOG.md index 062bf8c46ff08c..2bed952f89a4e6 100644 --- a/packages/edit-site/CHANGELOG.md +++ b/packages/edit-site/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.6.0 (2024-08-21) + ## 6.5.0 (2024-08-07) ## 6.4.0 (2024-07-24) diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 3e7e671fa1fa2f..4b8d1e7854a1c5 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.5.0", + "version": "6.6.0-prerelease", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/CHANGELOG.md b/packages/edit-widgets/CHANGELOG.md index bbe958c401ce6e..eb185d530887d3 100644 --- a/packages/edit-widgets/CHANGELOG.md +++ b/packages/edit-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.6.0 (2024-08-21) + ## 6.5.0 (2024-08-07) ## 6.4.0 (2024-07-24) diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 20ff3129330082..9582375c0d75d9 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.5.0", + "version": "6.6.0-prerelease", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index 8e7cbed3a98144..05bb9beb3b1fcc 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.6.0 (2024-08-21) + ## 14.5.0 (2024-08-07) ## 14.4.0 (2024-07-24) diff --git a/packages/editor/package.json b/packages/editor/package.json index cbe42f3b662c68..44f27edeb57a5a 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.5.0", + "version": "14.6.0-prerelease", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/CHANGELOG.md b/packages/element/CHANGELOG.md index 4dbbe1938a0187..4c0d695bef6a37 100644 --- a/packages/element/CHANGELOG.md +++ b/packages/element/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.6.0 (2024-08-21) + ## 6.5.0 (2024-08-07) ## 6.4.0 (2024-07-24) diff --git a/packages/element/package.json b/packages/element/package.json index 382d0ac50b67c7..ab6c1f8838352a 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.5.0", + "version": "6.6.0-prerelease", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md index dadbbb7c89ef9a..836084cd437fe7 100644 --- a/packages/env/CHANGELOG.md +++ b/packages/env/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.6.0 (2024-08-21) + ## 10.5.0 (2024-08-07) ## 10.4.0 (2024-07-24) diff --git a/packages/env/package.json b/packages/env/package.json index 2b8efcfbf07af7..aa913774db7bce 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.5.0", + "version": "10.6.0-prerelease", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/CHANGELOG.md b/packages/escape-html/CHANGELOG.md index 8768abbb682494..d3a505806d4575 100644 --- a/packages/escape-html/CHANGELOG.md +++ b/packages/escape-html/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.6.0 (2024-08-21) + ## 3.5.0 (2024-08-07) ## 3.4.0 (2024-07-24) diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index ef6adce54b8cf6..3fbd4e1e0742d7 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.5.0", + "version": "3.6.0-prerelease", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 92499f5b32eb3a..d66d8e9c9212cf 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 20.3.0 (2024-08-21) + ## 20.2.0 (2024-08-07) ## 20.1.0 (2024-07-24) diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index bf83ac72435604..a28f4c71919122 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "20.2.0", + "version": "20.3.0-prerelease", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/CHANGELOG.md b/packages/format-library/CHANGELOG.md index 7914005a0c2b1d..ff23fff3e0487f 100644 --- a/packages/format-library/CHANGELOG.md +++ b/packages/format-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/format-library/package.json b/packages/format-library/package.json index 72d9a054ae8253..bf7190b49b17a4 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/CHANGELOG.md b/packages/hooks/CHANGELOG.md index 779306149f2552..f23ab552ca7711 100644 --- a/packages/hooks/CHANGELOG.md +++ b/packages/hooks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 4def8c8e7a0958..8daebc0ee96b9a 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/CHANGELOG.md b/packages/html-entities/CHANGELOG.md index 9dafc94de9e18d..03e163b070bd86 100644 --- a/packages/html-entities/CHANGELOG.md +++ b/packages/html-entities/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index ea3a1fe00f0816..95be8c75e4919f 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index 8e31279a21a4da..40f11787b9779f 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 50ce8f7a839de8..759bf3c90872dd 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index 630bbd7cb129ae..f5d33c3a0dea01 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.6.0 (2024-08-21) + ## 10.5.0 (2024-08-07) ### New Features diff --git a/packages/icons/package.json b/packages/icons/package.json index ad32ed6fca29e6..a0be54afe254cf 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.5.0", + "version": "10.6.0-prerelease", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/CHANGELOG.md b/packages/interactivity-router/CHANGELOG.md index 38e79f9d503b6f..472b351682bbce 100644 --- a/packages/interactivity-router/CHANGELOG.md +++ b/packages/interactivity-router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.6.0 (2024-08-21) + ## 2.5.0 (2024-08-07) ## 2.4.0 (2024-07-24) diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 5ac4dcbf9b9fa0..9743f8deca8ad8 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.5.0", + "version": "2.6.0-prerelease", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 9068e1780cc10e..abc79853d222bf 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.6.0 (2024-08-21) + ### Bug Fixes - Fix context inheritance from namespaces different than the current one ([#64677](https://github.com/WordPress/gutenberg/pull/64677)). diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 33d575a0102f9e..2fcf32af782869 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.5.0", + "version": "6.6.0-prerelease", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index e60175047ec0e3..60a339f019bf50 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.6.0 (2024-08-21) + ## 6.5.0 (2024-08-07) ## 6.4.0 (2024-07-24) diff --git a/packages/interface/package.json b/packages/interface/package.json index 35b41c1b309c93..55e1ef058124f8 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "6.5.0", + "version": "6.6.0-prerelease", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/CHANGELOG.md b/packages/is-shallow-equal/CHANGELOG.md index 7757af92a8472e..23e1a6e0098484 100644 --- a/packages/is-shallow-equal/CHANGELOG.md +++ b/packages/is-shallow-equal/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index f9996eea6c480e..eb7e6f105c87a2 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/CHANGELOG.md b/packages/jest-console/CHANGELOG.md index f72992c321204e..ff8c00c83fc8ee 100644 --- a/packages/jest-console/CHANGELOG.md +++ b/packages/jest-console/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.6.0 (2024-08-21) + ## 8.5.0 (2024-08-07) ## 8.4.0 (2024-07-24) diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 4f36017125015c..0cea0667d09771 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.5.0", + "version": "8.6.0-prerelease", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md index 7dc5a2ec0e8963..04acc6e69ef606 100644 --- a/packages/jest-preset-default/CHANGELOG.md +++ b/packages/jest-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 12.6.0 (2024-08-21) + ## 12.5.0 (2024-08-07) ## 12.4.0 (2024-07-24) diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index f69c9465a80fea..42d1c3fa96601b 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.5.0", + "version": "12.6.0-prerelease", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/CHANGELOG.md b/packages/jest-puppeteer-axe/CHANGELOG.md index 710528ab53a242..984fdf249f504e 100644 --- a/packages/jest-puppeteer-axe/CHANGELOG.md +++ b/packages/jest-puppeteer-axe/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.6.0 (2024-08-21) + ## 7.5.0 (2024-08-07) ## 7.4.0 (2024-07-24) diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 8b2b9cd4e179b6..16d81e52d68341 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.5.0", + "version": "7.6.0-prerelease", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/CHANGELOG.md b/packages/keyboard-shortcuts/CHANGELOG.md index deee5625cd6879..20396b4b935ac6 100644 --- a/packages/keyboard-shortcuts/CHANGELOG.md +++ b/packages/keyboard-shortcuts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index d3caa86a85ba0d..83149638b9b1f2 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/CHANGELOG.md b/packages/keycodes/CHANGELOG.md index 1503d7554393f3..745412efcb990b 100644 --- a/packages/keycodes/CHANGELOG.md +++ b/packages/keycodes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 4ff043a3370e89..d35b4bee0b01f8 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/CHANGELOG.md b/packages/lazy-import/CHANGELOG.md index e6305967c12a7d..944cb6207fb962 100644 --- a/packages/lazy-import/CHANGELOG.md +++ b/packages/lazy-import/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.6.0 (2024-08-21) + ## 2.5.0 (2024-08-07) ## 2.4.0 (2024-07-24) diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index d7737d0fe5a234..f69de9791b06a4 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.5.0", + "version": "2.6.0-prerelease", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/CHANGELOG.md b/packages/list-reusable-blocks/CHANGELOG.md index bd1ee4cd44b12c..1338124bf1a7cd 100644 --- a/packages/list-reusable-blocks/CHANGELOG.md +++ b/packages/list-reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 79c668e8d26ac9..1d23734ae905f1 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/CHANGELOG.md b/packages/media-utils/CHANGELOG.md index 574d3b66273399..c155b906ab6dca 100644 --- a/packages/media-utils/CHANGELOG.md +++ b/packages/media-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index d3bb92294fda34..5c9c78bb4797bd 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/CHANGELOG.md b/packages/notices/CHANGELOG.md index 8e22055742e287..32d51970c2141d 100644 --- a/packages/notices/CHANGELOG.md +++ b/packages/notices/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/notices/package.json b/packages/notices/package.json index 944003de426ab5..17b4de0e325132 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/CHANGELOG.md b/packages/npm-package-json-lint-config/CHANGELOG.md index 9b83e804acdc1c..cfb2ea682ba456 100644 --- a/packages/npm-package-json-lint-config/CHANGELOG.md +++ b/packages/npm-package-json-lint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index 9fe4005668e106..8e12261f900677 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/CHANGELOG.md b/packages/nux/CHANGELOG.md index eb7ec981961649..90c3e96deb80aa 100644 --- a/packages/nux/CHANGELOG.md +++ b/packages/nux/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.6.0 (2024-08-21) + ## 9.5.0 (2024-08-07) ## 9.4.0 (2024-07-24) diff --git a/packages/nux/package.json b/packages/nux/package.json index 4a3ec7716c8afe..6b16428101c5a5 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.5.0", + "version": "9.6.0-prerelease", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/CHANGELOG.md b/packages/patterns/CHANGELOG.md index 0d11c1e9545b14..612586efb30a5b 100644 --- a/packages/patterns/CHANGELOG.md +++ b/packages/patterns/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.6.0 (2024-08-21) + ## 2.5.0 (2024-08-07) ## 2.4.0 (2024-07-24) diff --git a/packages/patterns/package.json b/packages/patterns/package.json index e2e77f1d15267b..01a25d37185635 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.5.0", + "version": "2.6.0-prerelease", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/CHANGELOG.md b/packages/plugins/CHANGELOG.md index 368cb58e22659e..14b9e4cffa4ad8 100644 --- a/packages/plugins/CHANGELOG.md +++ b/packages/plugins/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.6.0 (2024-08-21) + ## 7.5.0 (2024-08-07) ## 7.4.0 (2024-07-24) diff --git a/packages/plugins/package.json b/packages/plugins/package.json index bb4a9c3ecdd4cd..139727ad8b235f 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.5.0", + "version": "7.6.0-prerelease", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/CHANGELOG.md b/packages/postcss-plugins-preset/CHANGELOG.md index 2534e127a438e7..1811914b5bd884 100644 --- a/packages/postcss-plugins-preset/CHANGELOG.md +++ b/packages/postcss-plugins-preset/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index be6f88e9575b13..e1be8aa957ae8e 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/CHANGELOG.md b/packages/postcss-themes/CHANGELOG.md index 5fefbbff21cccd..11da169548988e 100644 --- a/packages/postcss-themes/CHANGELOG.md +++ b/packages/postcss-themes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.6.0 (2024-08-21) + ## 6.5.0 (2024-08-07) ## 6.4.0 (2024-07-24) diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index 20da35b26ebf14..da5d9b65716124 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.5.0", + "version": "6.6.0-prerelease", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/CHANGELOG.md b/packages/preferences-persistence/CHANGELOG.md index 4a29b7cabc2535..5b280b336f051c 100644 --- a/packages/preferences-persistence/CHANGELOG.md +++ b/packages/preferences-persistence/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.6.0 (2024-08-21) + ## 2.5.0 (2024-08-07) ## 2.4.0 (2024-07-24) diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index 1d94d3635a51b8..c5a1f8a21a80e0 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.5.0", + "version": "2.6.0-prerelease", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/CHANGELOG.md b/packages/preferences/CHANGELOG.md index 4ab14164deede9..5a71145f2396d3 100644 --- a/packages/preferences/CHANGELOG.md +++ b/packages/preferences/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/preferences/package.json b/packages/preferences/package.json index c433879f01da5a..dba0a3b55972f3 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/CHANGELOG.md b/packages/prettier-config/CHANGELOG.md index 8556f8d42768dd..5764c3b87cdd9f 100644 --- a/packages/prettier-config/CHANGELOG.md +++ b/packages/prettier-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 9d8020c086d90a..2719306df168a8 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/CHANGELOG.md b/packages/primitives/CHANGELOG.md index d698040432ecb8..b75cafd7ce35f4 100644 --- a/packages/primitives/CHANGELOG.md +++ b/packages/primitives/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 5a922c5e243477..a083c69d9099cb 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/CHANGELOG.md b/packages/priority-queue/CHANGELOG.md index 06fcc2be6ab09e..398db84f0bb44f 100644 --- a/packages/priority-queue/CHANGELOG.md +++ b/packages/priority-queue/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.6.0 (2024-08-21) + ## 3.5.0 (2024-08-07) ## 3.4.0 (2024-07-24) diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index fb7e4138395040..d870ea1b0d31ea 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.5.0", + "version": "3.6.0-prerelease", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/CHANGELOG.md b/packages/private-apis/CHANGELOG.md index e83cd2047a5c2a..ebba5ca7d26b93 100644 --- a/packages/private-apis/CHANGELOG.md +++ b/packages/private-apis/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.6.0 (2024-08-21) + ## 1.5.0 (2024-08-07) ## 1.4.0 (2024-07-24) diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index 2cb212b07bbb3f..951cb28aac1f5d 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.5.0", + "version": "1.6.0-prerelease", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/CHANGELOG.md b/packages/project-management-automation/CHANGELOG.md index cd83382d0e2485..d72669229fd2ab 100644 --- a/packages/project-management-automation/CHANGELOG.md +++ b/packages/project-management-automation/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.6.0 (2024-08-21) + ## 2.5.0 (2024-08-07) ## 2.4.0 (2024-07-24) diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 03107778fcb1a1..5c5c7d2cca3bb6 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.5.0", + "version": "2.6.0-prerelease", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/CHANGELOG.md b/packages/react-i18n/CHANGELOG.md index a44fe01322670e..20bd01908d4065 100644 --- a/packages/react-i18n/CHANGELOG.md +++ b/packages/react-i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 4b9f1949f7044b..1e39d34725b086 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md index c3d143fde84693..a522759971264c 100644 --- a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md +++ b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.6.0 (2024-08-21) + ## 3.5.0 (2024-08-07) ## 3.4.0 (2024-07-24) diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index e084c40bbfab5c..fc14fd4d05104e 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.5.0", + "version": "3.6.0-prerelease", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/CHANGELOG.md b/packages/redux-routine/CHANGELOG.md index 989af85ea8f81b..1241701e225e92 100644 --- a/packages/redux-routine/CHANGELOG.md +++ b/packages/redux-routine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 69696f72e2c430..5659d689f26222 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/CHANGELOG.md b/packages/reusable-blocks/CHANGELOG.md index 7ad0be3307056a..41a66dd019d784 100644 --- a/packages/reusable-blocks/CHANGELOG.md +++ b/packages/reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index c3b5219f117a45..2f8f8af8f4a047 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/CHANGELOG.md b/packages/rich-text/CHANGELOG.md index a83fc8a8b0d751..b3f7b7a2e4fdda 100644 --- a/packages/rich-text/CHANGELOG.md +++ b/packages/rich-text/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.6.0 (2024-08-21) + ## 7.5.0 (2024-08-07) ## 7.4.0 (2024-07-24) diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index d120411e746731..d356cd8d9978c3 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.5.0", + "version": "7.6.0-prerelease", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index fa46608d63254b..16bf8c495eb03c 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.6.0 (2024-08-21) + ## 1.5.0 (2024-08-07) ## 1.4.0 (2024-07-24) diff --git a/packages/router/package.json b/packages/router/package.json index e3c45b7ef0b525..d429845e4f4e0c 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.5.0", + "version": "1.6.0-prerelease", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 3a878e23689092..178b1c4fae36da 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 28.6.0 (2024-08-21) + ## 28.5.0 (2024-08-07) ## 28.4.0 (2024-07-24) diff --git a/packages/scripts/package.json b/packages/scripts/package.json index ff8e26b0e00c12..41cda62ea0fa8f 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "28.5.0", + "version": "28.6.0-prerelease", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/CHANGELOG.md b/packages/server-side-render/CHANGELOG.md index 6d0fed23681aa3..6246bff21cb488 100644 --- a/packages/server-side-render/CHANGELOG.md +++ b/packages/server-side-render/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.6.0 (2024-08-21) + ## 5.5.0 (2024-08-07) ## 5.4.0 (2024-07-24) diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index 642c515c9c0253..184bb3bd8146da 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.5.0", + "version": "5.6.0-prerelease", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/CHANGELOG.md b/packages/shortcode/CHANGELOG.md index ee2f8b49fcc24e..eeb738b9e49123 100644 --- a/packages/shortcode/CHANGELOG.md +++ b/packages/shortcode/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index e5e7e6c382550d..b77de9b92fbfcc 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md index 42928ac9fbd3c7..b8462204ea958c 100644 --- a/packages/style-engine/CHANGELOG.md +++ b/packages/style-engine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.6.0 (2024-08-21) + ### New Features - Style engine: export util to compile CSS custom var from preset string. ([#64490](https://github.com/WordPress/gutenberg/pull/64490)) diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index c41d1524a262a4..b844bf28d9af6b 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.5.0", + "version": "2.6.0-prerelease", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/CHANGELOG.md b/packages/stylelint-config/CHANGELOG.md index f258fa93af7a26..4df376a34b0986 100644 --- a/packages/stylelint-config/CHANGELOG.md +++ b/packages/stylelint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 22.6.0 (2024-08-21) + ## 22.5.0 (2024-08-07) ## 22.4.0 (2024-07-24) diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 199822d91c733b..0999871d88bf9a 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "22.5.0", + "version": "22.6.0-prerelease", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/CHANGELOG.md b/packages/sync/CHANGELOG.md index 5c703cc231dc88..b38fb8b48945cc 100644 --- a/packages/sync/CHANGELOG.md +++ b/packages/sync/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.6.0 (2024-08-21) + ## 1.5.0 (2024-08-07) ## 1.4.0 (2024-07-24) diff --git a/packages/sync/package.json b/packages/sync/package.json index 4380d7261ca457..7a43a8af6fa104 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.5.0", + "version": "1.6.0-prerelease", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/CHANGELOG.md b/packages/token-list/CHANGELOG.md index 5ccb92af128ca0..97b674024e637d 100644 --- a/packages/token-list/CHANGELOG.md +++ b/packages/token-list/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.6.0 (2024-08-21) + ## 3.5.0 (2024-08-07) ## 3.4.0 (2024-07-24) diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 3227b4da442eed..63f35bb8288dab 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.5.0", + "version": "3.6.0-prerelease", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/CHANGELOG.md b/packages/undo-manager/CHANGELOG.md index 665d78dd646af3..63338342dfe54c 100644 --- a/packages/undo-manager/CHANGELOG.md +++ b/packages/undo-manager/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.6.0 (2024-08-21) + ## 1.5.0 (2024-08-07) ## 1.4.0 (2024-07-24) diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 41d13755280bbf..34efb289632362 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.5.0", + "version": "1.6.0-prerelease", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/CHANGELOG.md b/packages/url/CHANGELOG.md index 9715c9512b34c1..f9af22f9fa7447 100644 --- a/packages/url/CHANGELOG.md +++ b/packages/url/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/url/package.json b/packages/url/package.json index 6bee340360a501..2dfd743152506e 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/CHANGELOG.md b/packages/viewport/CHANGELOG.md index 1e9c4f3d91590d..8ce0b7b1ffb750 100644 --- a/packages/viewport/CHANGELOG.md +++ b/packages/viewport/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.6.0 (2024-08-21) + ## 6.5.0 (2024-08-07) ## 6.4.0 (2024-07-24) diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 6ef7a28a2a9e33..a452e2883b31ab 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.5.0", + "version": "6.6.0-prerelease", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/CHANGELOG.md b/packages/warning/CHANGELOG.md index 6b73c6f10df6c0..ca176032261544 100644 --- a/packages/warning/CHANGELOG.md +++ b/packages/warning/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.6.0 (2024-08-21) + ## 3.5.0 (2024-08-07) ## 3.4.0 (2024-07-24) diff --git a/packages/warning/package.json b/packages/warning/package.json index 418f16427cd325..11277449f9cb29 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.5.0", + "version": "3.6.0-prerelease", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/CHANGELOG.md b/packages/widgets/CHANGELOG.md index a13d277ace3a21..e95c3904f97e1e 100644 --- a/packages/widgets/CHANGELOG.md +++ b/packages/widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/widgets/package.json b/packages/widgets/package.json index b8160fc6cd41ba..685d1182d6d32b 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/CHANGELOG.md b/packages/wordcount/CHANGELOG.md index e3865266e4c2d4..33eb27b885ab48 100644 --- a/packages/wordcount/CHANGELOG.md +++ b/packages/wordcount/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-08-21) + ## 4.5.0 (2024-08-07) ## 4.4.0 (2024-07-24) diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index 3e2bcbe2ee4ca4..c79eba44b39e1f 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 6a4f89df48ff031b1421f12af28c16e9250a5f4b Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 21 Aug 2024 16:15:47 +0000 Subject: [PATCH 0488/1908] chore(release): publish - @wordpress/a11y@4.6.0 - @wordpress/annotations@3.6.0 - @wordpress/api-fetch@7.6.0 - @wordpress/autop@4.6.0 - @wordpress/babel-plugin-import-jsx-pragma@5.6.0 - @wordpress/babel-plugin-makepot@6.6.0 - @wordpress/babel-preset-default@8.6.0 - @wordpress/base-styles@5.6.0 - @wordpress/blob@4.6.0 - @wordpress/block-directory@5.6.0 - @wordpress/block-editor@14.1.0 - @wordpress/block-library@9.6.0 - @wordpress/block-serialization-default-parser@5.6.0 - @wordpress/block-serialization-spec-parser@5.6.0 - @wordpress/blocks@13.6.0 - @wordpress/browserslist-config@6.6.0 - @wordpress/commands@1.6.0 - @wordpress/components@28.6.0 - @wordpress/compose@7.6.0 - @wordpress/core-commands@1.6.0 - @wordpress/core-data@7.6.0 - @wordpress/create-block@4.49.0 - @wordpress/create-block-interactive-template@2.6.0 - @wordpress/create-block-tutorial-template@4.6.0 - @wordpress/customize-widgets@5.6.0 - @wordpress/data@10.6.0 - @wordpress/data-controls@4.6.0 - @wordpress/dataviews@4.2.0 - @wordpress/date@5.6.0 - @wordpress/dependency-extraction-webpack-plugin@6.6.0 - @wordpress/deprecated@4.6.0 - @wordpress/docgen@2.6.0 - @wordpress/dom@4.6.0 - @wordpress/dom-ready@4.6.0 - @wordpress/e2e-test-utils@11.6.0 - @wordpress/e2e-test-utils-playwright@1.6.0 - @wordpress/e2e-tests@8.6.0 - @wordpress/edit-post@8.6.0 - @wordpress/edit-site@6.6.0 - @wordpress/edit-widgets@6.6.0 - @wordpress/editor@14.6.0 - @wordpress/element@6.6.0 - @wordpress/env@10.6.0 - @wordpress/escape-html@3.6.0 - @wordpress/eslint-plugin@20.3.0 - @wordpress/format-library@5.6.0 - @wordpress/hooks@4.6.0 - @wordpress/html-entities@4.6.0 - @wordpress/i18n@5.6.0 - @wordpress/icons@10.6.0 - @wordpress/interactivity@6.6.0 - @wordpress/interactivity-router@2.6.0 - @wordpress/interface@6.6.0 - @wordpress/is-shallow-equal@5.6.0 - @wordpress/jest-console@8.6.0 - @wordpress/jest-preset-default@12.6.0 - @wordpress/jest-puppeteer-axe@7.6.0 - @wordpress/keyboard-shortcuts@5.6.0 - @wordpress/keycodes@4.6.0 - @wordpress/lazy-import@2.6.0 - @wordpress/list-reusable-blocks@5.6.0 - @wordpress/media-utils@5.6.0 - @wordpress/notices@5.6.0 - @wordpress/npm-package-json-lint-config@5.6.0 - @wordpress/nux@9.6.0 - @wordpress/patterns@2.6.0 - @wordpress/plugins@7.6.0 - @wordpress/postcss-plugins-preset@5.6.0 - @wordpress/postcss-themes@6.6.0 - @wordpress/preferences@4.6.0 - @wordpress/preferences-persistence@2.6.0 - @wordpress/prettier-config@4.6.0 - @wordpress/primitives@4.6.0 - @wordpress/priority-queue@3.6.0 - @wordpress/private-apis@1.6.0 - @wordpress/project-management-automation@2.6.0 - @wordpress/react-i18n@4.6.0 - @wordpress/readable-js-assets-webpack-plugin@3.6.0 - @wordpress/redux-routine@5.6.0 - @wordpress/reusable-blocks@5.6.0 - @wordpress/rich-text@7.6.0 - @wordpress/router@1.6.0 - @wordpress/scripts@28.6.0 - @wordpress/server-side-render@5.6.0 - @wordpress/shortcode@4.6.0 - @wordpress/style-engine@2.6.0 - @wordpress/stylelint-config@22.6.0 - @wordpress/sync@1.6.0 - @wordpress/token-list@3.6.0 - @wordpress/undo-manager@1.6.0 - @wordpress/url@4.6.0 - @wordpress/viewport@6.6.0 - @wordpress/warning@3.6.0 - @wordpress/widgets@4.6.0 - @wordpress/wordcount@4.6.0 --- package-lock.json | 188 +++++++++--------- packages/a11y/package.json | 2 +- packages/annotations/package.json | 2 +- packages/api-fetch/package.json | 2 +- packages/autop/package.json | 2 +- .../package.json | 2 +- packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/package.json | 2 +- packages/base-styles/package.json | 2 +- packages/blob/package.json | 2 +- packages/block-directory/package.json | 2 +- packages/block-editor/package.json | 2 +- packages/block-library/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/blocks/package.json | 2 +- packages/browserslist-config/package.json | 2 +- packages/commands/package.json | 2 +- packages/components/package.json | 2 +- packages/compose/package.json | 2 +- packages/core-commands/package.json | 2 +- packages/core-data/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/create-block/package.json | 2 +- packages/customize-widgets/package.json | 2 +- packages/data-controls/package.json | 2 +- packages/data/package.json | 2 +- packages/dataviews/package.json | 2 +- packages/date/package.json | 2 +- .../package.json | 2 +- packages/deprecated/package.json | 2 +- packages/docgen/package.json | 2 +- packages/dom-ready/package.json | 2 +- packages/dom/package.json | 2 +- .../e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/package.json | 2 +- packages/edit-post/package.json | 2 +- packages/edit-site/package.json | 2 +- packages/edit-widgets/package.json | 2 +- packages/editor/package.json | 2 +- packages/element/package.json | 2 +- packages/env/package.json | 2 +- packages/escape-html/package.json | 2 +- packages/eslint-plugin/package.json | 2 +- packages/format-library/package.json | 2 +- packages/hooks/package.json | 2 +- packages/html-entities/package.json | 2 +- packages/i18n/package.json | 2 +- packages/icons/package.json | 2 +- packages/interactivity-router/package.json | 2 +- packages/interactivity/package.json | 2 +- packages/interface/package.json | 2 +- packages/is-shallow-equal/package.json | 2 +- packages/jest-console/package.json | 2 +- packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/package.json | 2 +- packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/package.json | 2 +- packages/notices/package.json | 2 +- .../npm-package-json-lint-config/package.json | 2 +- packages/nux/package.json | 2 +- packages/patterns/package.json | 2 +- packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/package.json | 2 +- packages/preferences/package.json | 2 +- packages/prettier-config/package.json | 2 +- packages/primitives/package.json | 2 +- packages/priority-queue/package.json | 2 +- packages/private-apis/package.json | 2 +- .../package.json | 2 +- packages/react-i18n/package.json | 2 +- .../package.json | 2 +- packages/redux-routine/package.json | 2 +- packages/reusable-blocks/package.json | 2 +- packages/rich-text/package.json | 2 +- packages/router/package.json | 2 +- packages/scripts/package.json | 2 +- packages/server-side-render/package.json | 2 +- packages/shortcode/package.json | 2 +- packages/style-engine/package.json | 2 +- packages/stylelint-config/package.json | 2 +- packages/sync/package.json | 2 +- packages/token-list/package.json | 2 +- packages/undo-manager/package.json | 2 +- packages/url/package.json | 2 +- packages/viewport/package.json | 2 +- packages/warning/package.json | 2 +- packages/widgets/package.json | 2 +- packages/wordcount/package.json | 2 +- 96 files changed, 189 insertions(+), 189 deletions(-) diff --git a/package-lock.json b/package-lock.json index cead8e172a5575..ccf59ff66a853d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52004,7 +52004,7 @@ }, "packages/a11y": { "name": "@wordpress/a11y", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52018,7 +52018,7 @@ }, "packages/annotations": { "name": "@wordpress/annotations", - "version": "3.5.0", + "version": "3.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52046,7 +52046,7 @@ }, "packages/api-fetch": { "name": "@wordpress/api-fetch", - "version": "7.5.0", + "version": "7.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52060,7 +52060,7 @@ }, "packages/autop": { "name": "@wordpress/autop", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52072,7 +52072,7 @@ }, "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.5.0", + "version": "5.6.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52085,7 +52085,7 @@ }, "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", - "version": "6.5.0", + "version": "6.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52103,7 +52103,7 @@ }, "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", - "version": "8.5.0", + "version": "8.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52126,7 +52126,7 @@ }, "packages/base-styles": { "name": "@wordpress/base-styles", - "version": "5.5.0", + "version": "5.6.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52136,7 +52136,7 @@ }, "packages/blob": { "name": "@wordpress/blob", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52148,7 +52148,7 @@ }, "packages/block-directory": { "name": "@wordpress/block-directory", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52183,7 +52183,7 @@ }, "packages/block-editor": { "name": "@wordpress/block-editor", - "version": "14.0.0", + "version": "14.1.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52289,7 +52289,7 @@ }, "packages/block-library": { "name": "@wordpress/block-library", - "version": "9.5.0", + "version": "9.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52355,7 +52355,7 @@ }, "packages/block-serialization-default-parser": { "name": "@wordpress/block-serialization-default-parser", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52367,7 +52367,7 @@ }, "packages/block-serialization-spec-parser": { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "pegjs": "^0.10.0", @@ -52380,7 +52380,7 @@ }, "packages/blocks": { "name": "@wordpress/blocks", - "version": "13.5.0", + "version": "13.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52434,7 +52434,7 @@ }, "packages/browserslist-config": { "name": "@wordpress/browserslist-config", - "version": "6.5.0", + "version": "6.6.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52444,7 +52444,7 @@ }, "packages/commands": { "name": "@wordpress/commands", - "version": "1.5.0", + "version": "1.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52617,7 +52617,7 @@ }, "packages/components": { "name": "@wordpress/components", - "version": "28.5.0", + "version": "28.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -52738,7 +52738,7 @@ }, "packages/compose": { "name": "@wordpress/compose", - "version": "7.5.0", + "version": "7.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52775,7 +52775,7 @@ }, "packages/core-commands": { "name": "@wordpress/core-commands", - "version": "1.5.0", + "version": "1.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52803,7 +52803,7 @@ }, "packages/core-data": { "name": "@wordpress/core-data", - "version": "7.5.0", + "version": "7.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52848,7 +52848,7 @@ }, "packages/create-block": { "name": "@wordpress/create-block", - "version": "4.48.0", + "version": "4.49.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52876,7 +52876,7 @@ }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", - "version": "4.5.0", + "version": "4.6.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52886,7 +52886,7 @@ }, "packages/customize-widgets": { "name": "@wordpress/customize-widgets", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52924,7 +52924,7 @@ }, "packages/data": { "name": "@wordpress/data", - "version": "10.5.0", + "version": "10.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52953,7 +52953,7 @@ }, "packages/data-controls": { "name": "@wordpress/data-controls", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52971,7 +52971,7 @@ }, "packages/dataviews": { "name": "@wordpress/dataviews", - "version": "4.1.0", + "version": "4.2.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -53028,7 +53028,7 @@ }, "packages/date": { "name": "@wordpress/date", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53043,7 +53043,7 @@ }, "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.5.0", + "version": "6.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53059,7 +53059,7 @@ }, "packages/deprecated": { "name": "@wordpress/deprecated", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53072,7 +53072,7 @@ }, "packages/docgen": { "name": "@wordpress/docgen", - "version": "2.5.0", + "version": "2.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53094,7 +53094,7 @@ }, "packages/dom": { "name": "@wordpress/dom", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53107,7 +53107,7 @@ }, "packages/dom-ready": { "name": "@wordpress/dom-ready", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53119,7 +53119,7 @@ }, "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", - "version": "11.5.0", + "version": "11.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53142,7 +53142,7 @@ }, "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.5.0", + "version": "1.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53170,7 +53170,7 @@ }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", - "version": "8.5.0", + "version": "8.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53210,7 +53210,7 @@ }, "packages/edit-post": { "name": "@wordpress/edit-post", - "version": "8.5.0", + "version": "8.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53257,7 +53257,7 @@ }, "packages/edit-site": { "name": "@wordpress/edit-site", - "version": "6.5.0", + "version": "6.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53319,7 +53319,7 @@ }, "packages/edit-widgets": { "name": "@wordpress/edit-widgets", - "version": "6.5.0", + "version": "6.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53362,7 +53362,7 @@ }, "packages/editor": { "name": "@wordpress/editor", - "version": "14.5.0", + "version": "14.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53423,7 +53423,7 @@ }, "packages/element": { "name": "@wordpress/element", - "version": "6.5.0", + "version": "6.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53442,7 +53442,7 @@ }, "packages/env": { "name": "@wordpress/env", - "version": "10.5.0", + "version": "10.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53584,7 +53584,7 @@ }, "packages/escape-html": { "name": "@wordpress/escape-html", - "version": "3.5.0", + "version": "3.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53596,7 +53596,7 @@ }, "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", - "version": "20.2.0", + "version": "20.3.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53639,7 +53639,7 @@ }, "packages/format-library": { "name": "@wordpress/format-library", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53667,7 +53667,7 @@ }, "packages/hooks": { "name": "@wordpress/hooks", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53679,7 +53679,7 @@ }, "packages/html-entities": { "name": "@wordpress/html-entities", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53691,7 +53691,7 @@ }, "packages/i18n": { "name": "@wordpress/i18n", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53711,7 +53711,7 @@ }, "packages/icons": { "name": "@wordpress/icons", - "version": "10.5.0", + "version": "10.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53725,7 +53725,7 @@ }, "packages/interactivity": { "name": "@wordpress/interactivity", - "version": "6.5.0", + "version": "6.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@preact/signals": "^1.2.2", @@ -53738,7 +53738,7 @@ }, "packages/interactivity-router": { "name": "@wordpress/interactivity-router", - "version": "2.5.0", + "version": "2.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/interactivity": "file:../interactivity" @@ -53774,7 +53774,7 @@ }, "packages/interface": { "name": "@wordpress/interface", - "version": "6.5.0", + "version": "6.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53803,7 +53803,7 @@ }, "packages/is-shallow-equal": { "name": "@wordpress/is-shallow-equal", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53815,7 +53815,7 @@ }, "packages/jest-console": { "name": "@wordpress/jest-console", - "version": "8.5.0", + "version": "8.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53832,7 +53832,7 @@ }, "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", - "version": "12.5.0", + "version": "12.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53850,7 +53850,7 @@ }, "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.5.0", + "version": "7.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53873,7 +53873,7 @@ }, "packages/keyboard-shortcuts": { "name": "@wordpress/keyboard-shortcuts", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53891,7 +53891,7 @@ }, "packages/keycodes": { "name": "@wordpress/keycodes", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53904,7 +53904,7 @@ }, "packages/lazy-import": { "name": "@wordpress/lazy-import", - "version": "2.5.0", + "version": "2.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53919,7 +53919,7 @@ }, "packages/list-reusable-blocks": { "name": "@wordpress/list-reusable-blocks", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53942,7 +53942,7 @@ }, "packages/media-utils": { "name": "@wordpress/media-utils", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53958,7 +53958,7 @@ }, "packages/notices": { "name": "@wordpress/notices", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53975,7 +53975,7 @@ }, "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.5.0", + "version": "5.6.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -53988,7 +53988,7 @@ }, "packages/nux": { "name": "@wordpress/nux", - "version": "9.5.0", + "version": "9.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54011,7 +54011,7 @@ }, "packages/patterns": { "name": "@wordpress/patterns", - "version": "2.5.0", + "version": "2.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54041,7 +54041,7 @@ }, "packages/plugins": { "name": "@wordpress/plugins", - "version": "7.5.0", + "version": "7.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54064,7 +54064,7 @@ }, "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", - "version": "5.5.0", + "version": "5.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54081,7 +54081,7 @@ }, "packages/postcss-themes": { "name": "@wordpress/postcss-themes", - "version": "6.5.0", + "version": "6.6.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54094,7 +54094,7 @@ }, "packages/preferences": { "name": "@wordpress/preferences", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54120,7 +54120,7 @@ }, "packages/preferences-persistence": { "name": "@wordpress/preferences-persistence", - "version": "2.5.0", + "version": "2.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54133,7 +54133,7 @@ }, "packages/prettier-config": { "name": "@wordpress/prettier-config", - "version": "4.5.0", + "version": "4.6.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54146,7 +54146,7 @@ }, "packages/primitives": { "name": "@wordpress/primitives", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54163,7 +54163,7 @@ }, "packages/priority-queue": { "name": "@wordpress/priority-queue", - "version": "3.5.0", + "version": "3.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54176,7 +54176,7 @@ }, "packages/private-apis": { "name": "@wordpress/private-apis", - "version": "1.5.0", + "version": "1.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54188,7 +54188,7 @@ }, "packages/project-management-automation": { "name": "@wordpress/project-management-automation", - "version": "2.5.0", + "version": "2.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54218,7 +54218,7 @@ }, "packages/react-i18n": { "name": "@wordpress/react-i18n", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54374,7 +54374,7 @@ }, "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.5.0", + "version": "3.6.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54387,7 +54387,7 @@ }, "packages/redux-routine": { "name": "@wordpress/redux-routine", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54432,7 +54432,7 @@ }, "packages/reusable-blocks": { "name": "@wordpress/reusable-blocks", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54459,7 +54459,7 @@ }, "packages/rich-text": { "name": "@wordpress/rich-text", - "version": "7.5.0", + "version": "7.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54483,7 +54483,7 @@ }, "packages/router": { "name": "@wordpress/router", - "version": "1.5.0", + "version": "1.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54502,7 +54502,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "28.5.0", + "version": "28.6.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54956,7 +54956,7 @@ }, "packages/server-side-render": { "name": "@wordpress/server-side-render", - "version": "5.5.0", + "version": "5.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54982,7 +54982,7 @@ }, "packages/shortcode": { "name": "@wordpress/shortcode", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54995,7 +54995,7 @@ }, "packages/style-engine": { "name": "@wordpress/style-engine", - "version": "2.5.0", + "version": "2.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55008,7 +55008,7 @@ }, "packages/stylelint-config": { "name": "@wordpress/stylelint-config", - "version": "22.5.0", + "version": "22.6.0", "dev": true, "license": "MIT", "dependencies": { @@ -55025,7 +55025,7 @@ }, "packages/sync": { "name": "@wordpress/sync", - "version": "1.5.0", + "version": "1.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55046,7 +55046,7 @@ }, "packages/token-list": { "name": "@wordpress/token-list", - "version": "3.5.0", + "version": "3.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -55058,7 +55058,7 @@ }, "packages/undo-manager": { "name": "@wordpress/undo-manager", - "version": "1.5.0", + "version": "1.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55071,7 +55071,7 @@ }, "packages/url": { "name": "@wordpress/url", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55084,7 +55084,7 @@ }, "packages/viewport": { "name": "@wordpress/viewport", - "version": "6.5.0", + "version": "6.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55102,7 +55102,7 @@ }, "packages/warning": { "name": "@wordpress/warning", - "version": "3.5.0", + "version": "3.6.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55111,7 +55111,7 @@ }, "packages/widgets": { "name": "@wordpress/widgets", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55139,7 +55139,7 @@ }, "packages/wordcount": { "name": "@wordpress/wordcount", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 16c3fd0e329989..0e307e813c56ad 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/package.json b/packages/annotations/package.json index bd3588e01f0386..95ceadb1d990ed 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.6.0-prerelease", + "version": "3.6.0", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index a1558d26e26640..abbe8cce374c31 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.6.0-prerelease", + "version": "7.6.0", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/package.json b/packages/autop/package.json index 578de505767bd0..03bb56412195ec 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index 09d09bb957ed0d..be1dbc4235f289 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index dd741954d4c71e..4d439baf28163d 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.6.0-prerelease", + "version": "6.6.0", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 2b8e044fcb02b5..2559b60401790e 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.6.0-prerelease", + "version": "8.6.0", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index 821f35a1f82ec3..fbe3bf149b1cdf 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/package.json b/packages/blob/package.json index 66968a12e0e767..58feea189bed0e 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index cbf57e9c62ed4b..85222ecaa38827 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 50918321569fd3..8002e165059e0e 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.1.0-prerelease", + "version": "14.1.0", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 4b98185de62d97..460e97fdf583ad 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.6.0-prerelease", + "version": "9.6.0", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index db61600cf496a2..cbfcbfc0e4cb64 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 001ab1d920352d..0020908e338331 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/package.json b/packages/blocks/package.json index fe35929a6fd354..e6c5253c7a4af1 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.6.0-prerelease", + "version": "13.6.0", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index ce38298f4200a1..6cf84334da5b30 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.6.0-prerelease", + "version": "6.6.0", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/package.json b/packages/commands/package.json index b4efa95538b37e..5bca7f6ad6fae5 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.6.0-prerelease", + "version": "1.6.0", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/package.json b/packages/components/package.json index c8344ac5013f61..ba943ece33340f 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.6.0-prerelease", + "version": "28.6.0", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/package.json b/packages/compose/package.json index 605f1866d9e4b4..92b3085e585755 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.6.0-prerelease", + "version": "7.6.0", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index ac061baf5fd2a6..02b8b76b4f145e 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.6.0-prerelease", + "version": "1.6.0", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 88fac357dfae9e..e96f3247086073 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.6.0-prerelease", + "version": "7.6.0", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index cb7b96ad19b681..848cd757652150 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.6.0-prerelease", + "version": "2.6.0", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index ebf97cb579cb2a..0d9baf39d8db80 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 5c97dc83e09f64..7548fca1532f07 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.49.0-prerelease", + "version": "4.49.0", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 52820914a97600..41184daf672b7a 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index d0de45f0640bb5..216f4000adff8e 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/package.json b/packages/data/package.json index 3753b8131a9583..fb27caaf37798f 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.6.0-prerelease", + "version": "10.6.0", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index ab0f266929f430..e02c0a624aa41c 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.2.0-prerelease", + "version": "4.2.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/package.json b/packages/date/package.json index 5069d271e05c60..b927d596864433 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index bc9967892d47db..5fd9b52f1acfdd 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.6.0-prerelease", + "version": "6.6.0", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index af3e1e49475057..244a8a0825e297 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 6c424b9097d5a5..e5b8b294cde520 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.6.0-prerelease", + "version": "2.6.0", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 463fc3ed0ddda7..5911fba9c58ebd 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/package.json b/packages/dom/package.json index 24230be5f8ba98..d861e4263accea 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 968f942f3872b0..2430644c77b3b4 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.6.0-prerelease", + "version": "1.6.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index cb14bfa532e9e9..d533cacee7a8be 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.6.0-prerelease", + "version": "11.6.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index bb9ab39b165ad4..f6491e6d58c531 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.6.0-prerelease", + "version": "8.6.0", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 2d502f5d2fee35..a9c483873b6d7e 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.6.0-prerelease", + "version": "8.6.0", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 4b8d1e7854a1c5..8122a1427deaba 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.6.0-prerelease", + "version": "6.6.0", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 9582375c0d75d9..38163afae6934b 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.6.0-prerelease", + "version": "6.6.0", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/package.json b/packages/editor/package.json index 44f27edeb57a5a..7e120895c782f3 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.6.0-prerelease", + "version": "14.6.0", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/package.json b/packages/element/package.json index ab6c1f8838352a..b1ed7cef47033b 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.6.0-prerelease", + "version": "6.6.0", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/package.json b/packages/env/package.json index aa913774db7bce..f7b8b2fb4a64d1 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.6.0-prerelease", + "version": "10.6.0", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 3fbd4e1e0742d7..3b5572ffcfc2bf 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.6.0-prerelease", + "version": "3.6.0", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index a28f4c71919122..7edb4033f32510 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "20.3.0-prerelease", + "version": "20.3.0", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/package.json b/packages/format-library/package.json index bf7190b49b17a4..531ec71224ce76 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 8daebc0ee96b9a..007404ec4a371d 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 95be8c75e4919f..690bd5d6762215 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 759bf3c90872dd..ef53c5a52900fb 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/package.json b/packages/icons/package.json index a0be54afe254cf..576160fdb52738 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.6.0-prerelease", + "version": "10.6.0", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 9743f8deca8ad8..29a3f53a6109f0 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.6.0-prerelease", + "version": "2.6.0", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 2fcf32af782869..fca8a03a7e45a7 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.6.0-prerelease", + "version": "6.6.0", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/package.json b/packages/interface/package.json index 55e1ef058124f8..6e017bfd349256 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "6.6.0-prerelease", + "version": "6.6.0", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index eb7e6f105c87a2..baa1dd7b3ebea9 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 0cea0667d09771..4e0d804088f893 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.6.0-prerelease", + "version": "8.6.0", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 42d1c3fa96601b..d09e89e88a63f1 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.6.0-prerelease", + "version": "12.6.0", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 16d81e52d68341..a512a018a9760c 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.6.0-prerelease", + "version": "7.6.0", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 83149638b9b1f2..52070a0904e101 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index d35b4bee0b01f8..4206b93430cfa5 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index f69de9791b06a4..54ea606faefac5 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.6.0-prerelease", + "version": "2.6.0", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 1d23734ae905f1..8e5fb404607c6e 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 5c9c78bb4797bd..0cbf38592a1fd6 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/package.json b/packages/notices/package.json index 17b4de0e325132..46715eb74a891f 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index 8e12261f900677..1acbcdede95aba 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/package.json b/packages/nux/package.json index 6b16428101c5a5..0997a29878bee6 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.6.0-prerelease", + "version": "9.6.0", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 01a25d37185635..5ca0cdbe5b9df5 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.6.0-prerelease", + "version": "2.6.0", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 139727ad8b235f..c5bf069bfaa170 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.6.0-prerelease", + "version": "7.6.0", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index e1be8aa957ae8e..892586a194e6fc 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index da5d9b65716124..57234c6f8d7fb7 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.6.0-prerelease", + "version": "6.6.0", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index c5a1f8a21a80e0..f994ca28f63012 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.6.0-prerelease", + "version": "2.6.0", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/package.json b/packages/preferences/package.json index dba0a3b55972f3..e39668e6ebe5d0 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 2719306df168a8..da728197725181 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/package.json b/packages/primitives/package.json index a083c69d9099cb..d53ac401d07b6c 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index d870ea1b0d31ea..012970e6344689 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.6.0-prerelease", + "version": "3.6.0", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index 951cb28aac1f5d..4493a6a4acc6b8 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.6.0-prerelease", + "version": "1.6.0", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 5c5c7d2cca3bb6..c82b5821342fec 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.6.0-prerelease", + "version": "2.6.0", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 1e39d34725b086..6067ae8cf929cc 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index fc14fd4d05104e..aefee907eb7461 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.6.0-prerelease", + "version": "3.6.0", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 5659d689f26222..d78fad4d28eda1 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 2f8f8af8f4a047..c1e5c9a71b0729 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index d356cd8d9978c3..163b7f5e7188a8 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.6.0-prerelease", + "version": "7.6.0", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/package.json b/packages/router/package.json index d429845e4f4e0c..5bda384293cf5c 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.6.0-prerelease", + "version": "1.6.0", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 41cda62ea0fa8f..dcc17a2926a654 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "28.6.0-prerelease", + "version": "28.6.0", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index 184bb3bd8146da..054e8b938ce845 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.6.0-prerelease", + "version": "5.6.0", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index b77de9b92fbfcc..42ca3458d72a5b 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index b844bf28d9af6b..91409072cb6503 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.6.0-prerelease", + "version": "2.6.0", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 0999871d88bf9a..aab9f8e8c3b417 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "22.6.0-prerelease", + "version": "22.6.0", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/package.json b/packages/sync/package.json index 7a43a8af6fa104..703de650e3f242 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.6.0-prerelease", + "version": "1.6.0", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 63f35bb8288dab..d40820a1f73a87 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.6.0-prerelease", + "version": "3.6.0", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 34efb289632362..3607f6f6a990ca 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.6.0-prerelease", + "version": "1.6.0", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/package.json b/packages/url/package.json index 2dfd743152506e..e83c05e594e5f9 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/package.json b/packages/viewport/package.json index a452e2883b31ab..7575c63256b632 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.6.0-prerelease", + "version": "6.6.0", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/package.json b/packages/warning/package.json index 11277449f9cb29..b18ad5ffc51678 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.6.0-prerelease", + "version": "3.6.0", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 685d1182d6d32b..c7fbb82eb0cb1d 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index c79eba44b39e1f..55cbfe3311d285 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 0e88cdae4586a1b071bf135b08bb33c2c0c3880d Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 21 Aug 2024 16:30:36 +0000 Subject: [PATCH 0489/1908] Update Changelog for 19.1.0-rc.1 --- changelog.txt | 311 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 311 insertions(+) diff --git a/changelog.txt b/changelog.txt index 748df8da3484c7..b21f0b433eec23 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,316 @@ == Changelog == += 19.1.0-rc.1 = + +## Changelog + +### Enhancements + +#### Components +- Allow `style` prop on `Popover`. ([64489](https://github.com/WordPress/gutenberg/pull/64489)) +- Add elevation scale. ([64108](https://github.com/WordPress/gutenberg/pull/64108)) +- Apply elevation scale to: Modal, Popover, and Snackbar components. ([64655](https://github.com/WordPress/gutenberg/pull/64655)) +- Ariakit: Update to v0.4.10. ([64637](https://github.com/WordPress/gutenberg/pull/64637)) +- DimensionControl: Add flag to remove bottom margin. ([64346](https://github.com/WordPress/gutenberg/pull/64346)) +- DropdownMenu V2: Use themed color variables. ([64647](https://github.com/WordPress/gutenberg/pull/64647)) +- FocalPointPicker: Default to new 40px size. ([64456](https://github.com/WordPress/gutenberg/pull/64456)) +- Placeholders: Update radius temporarily. ([64672](https://github.com/WordPress/gutenberg/pull/64672)) +- QueryControls: Default to new 40px size. ([64457](https://github.com/WordPress/gutenberg/pull/64457)) +- Reduce gap between steps in SpacingSizesControl, add animation, remove first/last marks. ([63803](https://github.com/WordPress/gutenberg/pull/63803)) +- Textarea Control: Update styles. ([64586](https://github.com/WordPress/gutenberg/pull/64586)) +- Tools Panel: Sets column-gap to 16px for grid. ([64497](https://github.com/WordPress/gutenberg/pull/64497)) +- Update DropdownMenuV2 elevation, remove unused configuration value. ([64432](https://github.com/WordPress/gutenberg/pull/64432)) +- Update components radius. ([64368](https://github.com/WordPress/gutenberg/pull/64368)) +- Use `useStoreState()` instead of `store.useState()`. ([64648](https://github.com/WordPress/gutenberg/pull/64648)) +- Composite: Use internal context to consume composite store. ([64493](https://github.com/WordPress/gutenberg/pull/64493)) + +#### Data Views +- Do not display element descriptions in filters. ([64674](https://github.com/WordPress/gutenberg/pull/64674)) +- Add `comment_status` field to quick edit. ([64370](https://github.com/WordPress/gutenberg/pull/64370)) +- Add `status` to quick edit. ([64398](https://github.com/WordPress/gutenberg/pull/64398)) +- Apply minimal variant to pagination dropdown. ([63815](https://github.com/WordPress/gutenberg/pull/63815)) +- Update the style of the datetime fields to match the other types. ([64438](https://github.com/WordPress/gutenberg/pull/64438)) +- Use the fields array to define the order of the fields. ([64335](https://github.com/WordPress/gutenberg/pull/64335)) +- Make the move left/right controls in table header always available. ([64646](https://github.com/WordPress/gutenberg/pull/64646)) +- Support defining field headers/names as React elements. ([64642](https://github.com/WordPress/gutenberg/pull/64642)) +- Quick edit: Add Date as field and `datetime` as field type. ([64267](https://github.com/WordPress/gutenberg/pull/64267)) +- Add marks to preview size control. ([64546](https://github.com/WordPress/gutenberg/pull/64546)) +- Move item size control to the new view configuration UI. ([64380](https://github.com/WordPress/gutenberg/pull/64380)) +- Update search appearance in narrow containers. ([64681](https://github.com/WordPress/gutenberg/pull/64681)) +- Extensibility - allow unregistering of the following: + - Duplicate post action ([64441](https://github.com/WordPress/gutenberg/pull/64441)) + - Duplicate pattern action ([64373](https://github.com/WordPress/gutenberg/pull/64373)) + - Duplicate template part action ([64388](https://github.com/WordPress/gutenberg/pull/64388)) + - Rename post action ([64366](https://github.com/WordPress/gutenberg/pull/64366)) + - Reorder-page action ([64199](https://github.com/WordPress/gutenberg/pull/64199)) + - View post action ([64467](https://github.com/WordPress/gutenberg/pull/64467)) + - View post revisions action ([64464](https://github.com/WordPress/gutenberg/pull/64464)) + +#### Block Library +- Embed Block: Replace native input element with InputControl component. ([64668](https://github.com/WordPress/gutenberg/pull/64668)) +- File: Add border block support. ([64509](https://github.com/WordPress/gutenberg/pull/64509)) +- Grid: Prevent highlight of cells when dragging a block if block type can't be dropped into grid. ([64290](https://github.com/WordPress/gutenberg/pull/64290)) +- Image block: Add reset button. ([64669](https://github.com/WordPress/gutenberg/pull/64669)) +- List Item: Add border support. ([63541](https://github.com/WordPress/gutenberg/pull/63541)) +- List: Add border support. ([63540](https://github.com/WordPress/gutenberg/pull/63540)) +- Preformatted: Add border block support. ([64302](https://github.com/WordPress/gutenberg/pull/64302)) +- Tag Cloud: Add border block support. ([63579](https://github.com/WordPress/gutenberg/pull/63579)) +- Overlay caption w. text-shadow. ([63471](https://github.com/WordPress/gutenberg/pull/63471)) + +#### Design Tools +- Background image: Add uploading state and restrict drag to one image. ([64565](https://github.com/WordPress/gutenberg/pull/64565)) +- Quote Block: Add align support. ([64188](https://github.com/WordPress/gutenberg/pull/64188)) +- Add border support to the following: + - Comment Author Name ([64550](https://github.com/WordPress/gutenberg/pull/64550)) + - Comment Content ([64230](https://github.com/WordPress/gutenberg/pull/64230)) + - Comment Date ([64210](https://github.com/WordPress/gutenberg/pull/64210)) + - Post Author Biography ([64615](https://github.com/WordPress/gutenberg/pull/64615)) + - Post Author Name ([64530](https://github.com/WordPress/gutenberg/pull/64530)) + - Post Author ([64599](https://github.com/WordPress/gutenberg/pull/64599)) + - Query Title ([64581](https://github.com/WordPress/gutenberg/pull/64581)) + +#### Zoom Out +- Add private `isZoomOutMode` selector. ([64503](https://github.com/WordPress/gutenberg/pull/64503)) +- Block Insertion: Clear the insertion point when selecting a different block or clearing block selection. ([64048](https://github.com/WordPress/gutenberg/pull/64048)) +- Default the inserter to the patterns tab when in zoom out. ([64193](https://github.com/WordPress/gutenberg/pull/64193)) +- Focus pattern inserter search when activating zoom out inserter. ([64396](https://github.com/WordPress/gutenberg/pull/64396)) +- Stop unwanted drag and drop operations within section Patterns in Zoom Out mode. ([64331](https://github.com/WordPress/gutenberg/pull/64331)) + +#### Block Editor +- Button groups in Typography tools should use ToggleGroupControl. ([64529](https://github.com/WordPress/gutenberg/pull/64529)) +- Hyphenate long block names in the inserter. ([64667](https://github.com/WordPress/gutenberg/pull/64667)) + +#### Global Styles +- Additional CSS: Localize the link if it exists. ([64603](https://github.com/WordPress/gutenberg/pull/64603)) +- Background images: Add support for theme.json ref value resolution. ([64128](https://github.com/WordPress/gutenberg/pull/64128)) + + +### New APIs + +#### Components +- Composite + - Add Hover and Typeahead subcomponents. ([64399](https://github.com/WordPress/gutenberg/pull/64399)) + - Stabilize new ariakit implementation. ([63564](https://github.com/WordPress/gutenberg/pull/63564)) + - Export `useCompositeStore`, add more focus-related props. ([64450](https://github.com/WordPress/gutenberg/pull/64450)) + +#### Synced Patterns +- Block Bindings: Create utils to update or remove bindings. ([64102](https://github.com/WordPress/gutenberg/pull/64102)) + +#### Extensibility +- Add plugin template registration API. ([61577](https://github.com/WordPress/gutenberg/pull/61577)) + + +### Bug Fixes + +#### Components +- CustomSelectControl: Improve props type inferring. ([64412](https://github.com/WordPress/gutenberg/pull/64412)) +- ColorPalette: Partial support of `color-mix()` CSS colors. ([64224](https://github.com/WordPress/gutenberg/pull/64224)) +- RangeControl: Disable reset button consistently. ([64579](https://github.com/WordPress/gutenberg/pull/64579)) +- RangeControl: Tweak mark and label absolute positioning. ([64487](https://github.com/WordPress/gutenberg/pull/64487)) + +#### Data Views +- Load the filter toggle as open if there are primary filters. ([64651](https://github.com/WordPress/gutenberg/pull/64651)) +- Sort descending button may be wrongly pressed. ([64547](https://github.com/WordPress/gutenberg/pull/64547)) +- Filter icon is displayed even when no filter capabilities are given to any field. ([64640](https://github.com/WordPress/gutenberg/pull/64640)) + +#### Zoom Out +- Disallow dropping outside section root in Zoom Out mode. ([64500](https://github.com/WordPress/gutenberg/pull/64500)) +- Don't hide the insertion point when hovering patterns. ([64392](https://github.com/WordPress/gutenberg/pull/64392)) +- Use previous device width for scale calculations. ([64478](https://github.com/WordPress/gutenberg/pull/64478)) + +#### Block Library +- Embed blocks: Adding captions via toolbar - #64385. ([64394](https://github.com/WordPress/gutenberg/pull/64394)) +- Paste: Fix blob uploading. ([64479](https://github.com/WordPress/gutenberg/pull/64479)) +- Table Block: Hide caption toolbar button on multiple selection. ([64462](https://github.com/WordPress/gutenberg/pull/64462)) + +#### Post Editor +- Fix user pattern preloading filter. ([64477](https://github.com/WordPress/gutenberg/pull/64477)) +- Fix preloaded REST API paths. ([64459](https://github.com/WordPress/gutenberg/pull/64459)) +- Force iframe editor when zoom-out mode. ([64316](https://github.com/WordPress/gutenberg/pull/64316)) + +#### Block Editor +- Don't hide the toolbar for an empty default block in HTML mode. ([64374](https://github.com/WordPress/gutenberg/pull/64374)) +- In-between Inserter: Show inserter when it doesn't conflict with block toolbar. ([64229](https://github.com/WordPress/gutenberg/pull/64229)) +- Slash Inserter: Restrict block list to allowed blocks only. ([64413](https://github.com/WordPress/gutenberg/pull/64413)) + +#### Site Editor +- Don't allow duplicating template parts in non-block-based themes. ([64379](https://github.com/WordPress/gutenberg/pull/64379)) +- Fix Template Parts post type preload path. ([64401](https://github.com/WordPress/gutenberg/pull/64401)) +- Cancel button in duplicate template part modal doesn't work. ([64377](https://github.com/WordPress/gutenberg/pull/64377)) +- Fix empty content sidebar panel. ([64569](https://github.com/WordPress/gutenberg/pull/64569)) + +#### Block bindings +- Fix long keys overflow in bindings panel. ([64465](https://github.com/WordPress/gutenberg/pull/64465)) +- Hide keys starting with underscore. ([64618](https://github.com/WordPress/gutenberg/pull/64618)) + +#### CSS & Styling +- Remove inconsistent dark theme focus style on block selection. ([64549](https://github.com/WordPress/gutenberg/pull/64549)) +- Update postcss-prefixwrap dependency to 1.51.0 to fix prefixing in `:Where` selectors. ([64458](https://github.com/WordPress/gutenberg/pull/64458)) + +#### Interactivity API +- Fix context inheritance from namespaces different than the current one. ([64677](https://github.com/WordPress/gutenberg/pull/64677)) + +#### Document Settings +- Post Featured Image: Disable the media modal while uploading an image. ([64566](https://github.com/WordPress/gutenberg/pull/64566)) + +#### Patterns +- Changing sorting direction on patterns does nothing. ([64508](https://github.com/WordPress/gutenberg/pull/64508)) + +#### Design Tools +- Background image: Ensure consistency with defaults and fix reset/remove functionality. ([64328](https://github.com/WordPress/gutenberg/pull/64328)) + +#### Global Styles +- Fix bumped specificity for layout styles in non-iframed editor. ([64076](https://github.com/WordPress/gutenberg/pull/64076)) + + +### Accessibility + +- Site Editor: Always use auto-cursor style for editable text. ([64627](https://github.com/WordPress/gutenberg/pull/64627)) +- Post Editor: Update textControl to searchControl in taxonomy search. ([64605](https://github.com/WordPress/gutenberg/pull/64605)) +- RadioControl: Label radio group using fieldset and legend. ([64582](https://github.com/WordPress/gutenberg/pull/64582)) +- Fix labeling in Typography font size presets panel. ([64428](https://github.com/WordPress/gutenberg/pull/64428)) +- Latests Posts: Used ToggleGroupControl instead for Image alignment. ([64352](https://github.com/WordPress/gutenberg/pull/64352)) + + +### Performance + +- Fetch permissions for visible patterns only. ([64606](https://github.com/WordPress/gutenberg/pull/64606)) +- Background Image: Remove unnecessary 'block-editor' store subscription. ([64568](https://github.com/WordPress/gutenberg/pull/64568)) +- Edit Post: Avoid unnecessary post-template ID lookup. ([64431](https://github.com/WordPress/gutenberg/pull/64431)) +- GridVisualizer: Avoid over-selecting by using a new getBlockStyles private selector. ([64386](https://github.com/WordPress/gutenberg/pull/64386)) + + +### Experiments + +#### Data Views +- DataViews Quick Edit + - Add Post Card to the quick edit panel. ([64365](https://github.com/WordPress/gutenberg/pull/64365)) + - Add the PostActions dropdown menu. ([64393](https://github.com/WordPress/gutenberg/pull/64393)) + - Rely on the global save flow instead of a custom save button. ([64389](https://github.com/WordPress/gutenberg/pull/64389)) +- Update the copy of quick edit tooltip. ([64475](https://github.com/WordPress/gutenberg/pull/64475)) + +#### Components +- Composite v2: Undo stabilizing new version. ([64510](https://github.com/WordPress/gutenberg/pull/64510)) + + +### Documentation + +- Add clarification about importing css/scss files. ([61252](https://github.com/WordPress/gutenberg/pull/61252)) +- Components + - Add "Naming conventions" section. ([63714](https://github.com/WordPress/gutenberg/pull/63714)) + - Add 40px size prop to readmes. ([64592](https://github.com/WordPress/gutenberg/pull/64592)) +- Composite: Improve Storybook examples and clean up prop documentation. ([64397](https://github.com/WordPress/gutenberg/pull/64397)) +- Dataviews + - Added missing properties for actions object and link to storybook example. ([64442](https://github.com/WordPress/gutenberg/pull/64442)) + - Fixed tip link for block editor view. ([64469](https://github.com/WordPress/gutenberg/pull/64469)) + - Update README with missing properties and recent changes. ([64435](https://github.com/WordPress/gutenberg/pull/64435)) + - Better explanation of the "elements" property and its connection to the "filterBy" property. ([64633](https://github.com/WordPress/gutenberg/pull/64633)) +- Interactivity API + - The first three Core Concepts guides. ([63759](https://github.com/WordPress/gutenberg/pull/63759)) + - Fix internal links core-concepts. ([64609](https://github.com/WordPress/gutenberg/pull/64609)) + - Remove typed function from API reference. ([64429](https://github.com/WordPress/gutenberg/pull/64429)) + - Add code concepts to Navigating the Interactivity API documentation. ([64608](https://github.com/WordPress/gutenberg/pull/64608)) + - Interactivity API: Add wp_interactivity_state() clarification. ([64356](https://github.com/WordPress/gutenberg/pull/64356)) +- Fix typos in the Block Filters documentation.. ([64426](https://github.com/WordPress/gutenberg/pull/64426)) +- Fix example of useBlockProps hook. ([64363](https://github.com/WordPress/gutenberg/pull/64363)) +- Fix typo and link in static-dynamic-rendering.md. ([64449](https://github.com/WordPress/gutenberg/pull/64449)) +- Fix typo in block-filters.md. ([64452](https://github.com/WordPress/gutenberg/pull/64452)) +- Fix typo in block-wrapper.md. ([64447](https://github.com/WordPress/gutenberg/pull/64447)) +- Note about image sizes in MediaUpload::OnSelect. ([64616](https://github.com/WordPress/gutenberg/pull/64616)) +- Small typo correction in doc file. ([64596](https://github.com/WordPress/gutenberg/pull/64596)) +- TextDecorationControl, TextTransformControl: Remove size prop in Storybook. ([64583](https://github.com/WordPress/gutenberg/pull/64583)) +- Updated `@since` order in Inline document in client-assets.php file. ([64653](https://github.com/WordPress/gutenberg/pull/64653)) +- Updated small typo in compat.php file. ([64535](https://github.com/WordPress/gutenberg/pull/64535)) +- Updated small typo in modularity.md. ([64518](https://github.com/WordPress/gutenberg/pull/64518)) + + +### Code Quality + +- Add lint rule for 40px size prop usage in the following: + - BorderBoxControl, BorderControl, DimensionControl, FontSizePicker: ([64410](https://github.com/WordPress/gutenberg/pull/64410)) + - Block Editor typography components ([64591](https://github.com/WordPress/gutenberg/pull/64591)) + - FormFileUpload: ([64585](https://github.com/WordPress/gutenberg/pull/64585)) + - FormTokenField: ([64590](https://github.com/WordPress/gutenberg/pull/64590)) + - InputControl: ([64589](https://github.com/WordPress/gutenberg/pull/64589)) + - NumberControl: ([64561](https://github.com/WordPress/gutenberg/pull/64561)) + - RangeControl: ([64558](https://github.com/WordPress/gutenberg/pull/64558)) + - SelectControl: ([64486](https://github.com/WordPress/gutenberg/pull/64486)) + - TextControl: ([64455](https://github.com/WordPress/gutenberg/pull/64455)) + - ToggleGroupControl: ([64524](https://github.com/WordPress/gutenberg/pull/64524)) + - ComboboxControl: ([64560](https://github.com/WordPress/gutenberg/pull/64560)) + - CustomSelectControl: ([64559](https://github.com/WordPress/gutenberg/pull/64559)) +- Add margin-bottom lint rules for BaseControl. ([64355](https://github.com/WordPress/gutenberg/pull/64355)) +- Add missing changes to the changelog for the PR #62734. ([64507](https://github.com/WordPress/gutenberg/pull/64507)) +- Base Styles: Restore deprecated `$dark-theme-focus` variable. ([64563](https://github.com/WordPress/gutenberg/pull/64563)) +- ESLint: Enable and enforce remaining i18n rules for the plugin (e.g. no trailing spaces). ([60196](https://github.com/WordPress/gutenberg/pull/60196)) +- Remove unnecessary className. ([64403](https://github.com/WordPress/gutenberg/pull/64403)) +- Replace instances of deprecated elevation variables. ([64656](https://github.com/WordPress/gutenberg/pull/64656)) +- Style engine: Export util to compile CSS custom var from preset string. ([64490](https://github.com/WordPress/gutenberg/pull/64490)) +- Style engine: Update type for getCSSValueFromRawStyle. ([64528](https://github.com/WordPress/gutenberg/pull/64528)) +- TextControl: Fix remaining 40px size violations. ([64594](https://github.com/WordPress/gutenberg/pull/64594)) +- Border: 1px → $border-width. ([64680](https://github.com/WordPress/gutenberg/pull/64680)) + +#### Block Library +- Gallery: Remove 'withNotices' HoC. ([64384](https://github.com/WordPress/gutenberg/pull/64384)) +- Missing Block: Use hooks instead of HoC. ([64657](https://github.com/WordPress/gutenberg/pull/64657)) + +#### Block Editor +- Use hooks instead of HoC in: + - 'BlockModeToggle'. ([64460](https://github.com/WordPress/gutenberg/pull/64460)) + - 'MultiSelectionInspector'. ([64634](https://github.com/WordPress/gutenberg/pull/64634)) + +#### Components +- Deprecate bottom margin on BaseControl-based components. ([64408](https://github.com/WordPress/gutenberg/pull/64408)) +- Navigator: Simplify backwards navigation APIs. ([63317](https://github.com/WordPress/gutenberg/pull/63317)) + +#### Data Views +- Refactor the edit function to be based on discrete controls. ([64404](https://github.com/WordPress/gutenberg/pull/64404)) +- Update `renderFormElements` to make sure the value respects the type. ([64391](https://github.com/WordPress/gutenberg/pull/64391)) +- Abandon the ItemRecord type. ([64367](https://github.com/WordPress/gutenberg/pull/64367)) + +#### Block hooks +- Navigation Block: Remove now-obsolete function_exists guards. ([64673](https://github.com/WordPress/gutenberg/pull/64673)) + +#### Nested / Inner Blocks +- Block Editor: Refactor inner blocks appender components. ([64470](https://github.com/WordPress/gutenberg/pull/64470)) + +#### Plugin +- Script Modules: Move data passing to 6.7 compat file. ([64006](https://github.com/WordPress/gutenberg/pull/64006)) + + +### Tools + +- Make wp-env compatible with WordPress versions older than 5.4 by fixing wp-config anchors. ([55864](https://github.com/WordPress/gutenberg/pull/55864)) + +#### Testing +- Background block supports: Remove unused properties in unit tests. ([64564](https://github.com/WordPress/gutenberg/pull/64564)) +- Fix flaky block template registration end-to-end test. ([64541](https://github.com/WordPress/gutenberg/pull/64541)) +- Improve Image block end-to-end tests. ([64537](https://github.com/WordPress/gutenberg/pull/64537)) +- Upgrade Playwright to v1.46. ([64372](https://github.com/WordPress/gutenberg/pull/64372)) + +#### Build Tooling +- Fix gutenberg/gutenberg-coding-standards licensing issues. ([61913](https://github.com/WordPress/gutenberg/pull/61913)) +- Props Bot: Update to correct event type. ([64557](https://github.com/WordPress/gutenberg/pull/64557)) + + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @cweiske: Note about image sizes in MediaUpload::OnSelect. ([64616](https://github.com/WordPress/gutenberg/pull/64616)) +- @imrraaj: Dataviews: Filter icon is displayed even when no filter capabilities are given to any field. ([64640](https://github.com/WordPress/gutenberg/pull/64640)) +- @janpfeil: Fix typo in block-filters.md. ([64452](https://github.com/WordPress/gutenberg/pull/64452)) +- @Rishit30G: `ColorPalette`: Partial support of `color-mix()` CSS colors. ([64224](https://github.com/WordPress/gutenberg/pull/64224)) +- @ssang: Slash Inserter: Restrict block list to allowed blocks only. ([64413](https://github.com/WordPress/gutenberg/pull/64413)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @akasunil @Aljullu @amitraj2203 @anton-vlasenko @arthur791004 @cbravobernal @ciampo @colorful-tones @cweiske @DAreRodz @ellatrix @felixarntz @getdave @hbhalodia @imrraaj @jameskoster @janpfeil @jasmussen @jeherve @jorgefilipecosta @jsnajdr @juanmaguitar @luisherranz @Mamaduka @meteorlxy @mirka @ndiego @noisysocks @ntsekouras @oandregal @ockham @ramonjd @richtabor @Rishit30G @SantosGuillamot @scruffian @shail-mehta @shreya0204 @sirreal @ssang @swissspidy @t-hamano @talldan @tyxla @vipul0425 @youknowriad + + = 19.0.0 = ## Changelog From 54eee32b043ff1879cba2f82f9d5568df43bc34c Mon Sep 17 00:00:00 2001 From: Rich Tabor <hi@richtabor.com> Date: Wed, 21 Aug 2024 20:34:16 -0400 Subject: [PATCH 0490/1908] Make Distraction Free not conditional on viewport width (#63949) * check for isWideViewport * make distraction free always available * Ensure mobile styles work with and without distraction free * use isLargeViewport "medium" instead * use ! isMobileViewport instead of isLargeViewport --- packages/editor/src/components/editor-interface/index.js | 6 ++---- packages/editor/src/components/header/style.scss | 9 ++++++--- .../interface/src/components/interface-skeleton/index.js | 8 ++++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/editor/src/components/editor-interface/index.js b/packages/editor/src/components/editor-interface/index.js index 5b0aea5400d7ba..848767f856ce7b 100644 --- a/packages/editor/src/components/editor-interface/index.js +++ b/packages/editor/src/components/editor-interface/index.js @@ -99,7 +99,6 @@ export default function EditorInterface( { select( blockEditorStore ).__unstableGetEditorMode(), }; }, [] ); - const isWideViewport = useViewportMatch( 'large' ); const isLargeViewport = useViewportMatch( 'medium' ); const secondarySidebarLabel = isListViewOpened ? __( 'Document Overview' ) @@ -122,11 +121,10 @@ export default function EditorInterface( { return ( <InterfaceSkeleton enableRegionNavigation={ enableRegionNavigation } - isDistractionFree={ isDistractionFree && isWideViewport } + isDistractionFree={ isDistractionFree } className={ clsx( 'editor-editor-interface', className, { 'is-entity-save-view-open': !! entitiesSavedStatesCallback, - 'is-distraction-free': - isDistractionFree && isWideViewport && ! isPreviewMode, + 'is-distraction-free': isDistractionFree && ! isPreviewMode, } ) } labels={ { ...interfaceLabels, diff --git a/packages/editor/src/components/header/style.scss b/packages/editor/src/components/header/style.scss index de690d89a66ae4..99c9cc70e166e4 100644 --- a/packages/editor/src/components/header/style.scss +++ b/packages/editor/src/components/header/style.scss @@ -228,7 +228,7 @@ } .editor-header__post-preview-button { - @include break-small { + @include break-mobile { display: none; } } @@ -240,10 +240,13 @@ .editor-header { background-color: $white; - border-bottom: 1px solid #e0e0e0; - position: absolute; width: 100%; + @include break-medium { + border-bottom: 1px solid #e0e0e0; + position: absolute; + } + // hide some parts & > .edit-post-header__settings > .edit-post-header__post-preview-button { diff --git a/packages/interface/src/components/interface-skeleton/index.js b/packages/interface/src/components/interface-skeleton/index.js index 14b2a87ba5203d..a1fd20b642206f 100644 --- a/packages/interface/src/components/interface-skeleton/index.js +++ b/packages/interface/src/components/interface-skeleton/index.js @@ -143,22 +143,22 @@ function InterfaceSkeleton( className="interface-interface-skeleton__header" aria-label={ mergedLabels.header } initial={ - isDistractionFree + isDistractionFree && ! isMobileViewport ? 'distractionFreeHidden' : 'hidden' } whileHover={ - isDistractionFree + isDistractionFree && ! isMobileViewport ? 'distractionFreeHover' : 'visible' } animate={ - isDistractionFree + isDistractionFree && ! isMobileViewport ? 'distractionFreeDisabled' : 'visible' } exit={ - isDistractionFree + isDistractionFree && ! isMobileViewport ? 'distractionFreeHidden' : 'hidden' } From 66b8b617c767829d9b7972459ca11e0c037c5e27 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Thu, 22 Aug 2024 13:15:58 +1000 Subject: [PATCH 0491/1908] Block Library: Remove Gutenberg i18n domain from block-library package (#64701). As these files are distributed to WordPress in an unaltered form, the domain needs to be removed to allow it to be added to the WordPress translations. Co-authored-by: peterwilsoncc <peterwilsoncc@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/comment-date/index.php | 2 +- packages/block-library/src/form/index.php | 4 ++-- packages/block-library/src/post-date/index.php | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/block-library/src/comment-date/index.php b/packages/block-library/src/comment-date/index.php index 8deed941324886..bdb6fd5ba42ae3 100644 --- a/packages/block-library/src/comment-date/index.php +++ b/packages/block-library/src/comment-date/index.php @@ -30,7 +30,7 @@ function render_block_core_comment_date( $attributes, $content, $block ) { $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $classes ) ); if ( isset( $attributes['format'] ) && 'human-diff' === $attributes['format'] ) { // translators: %s: human-readable time difference. - $formatted_date = sprintf( __( '%s ago', 'gutenberg' ), human_time_diff( get_comment_date( 'U', $comment ) ) ); + $formatted_date = sprintf( __( '%s ago' ), human_time_diff( get_comment_date( 'U', $comment ) ) ); } else { $formatted_date = get_comment_date( empty( $attributes['format'] ) ? '' : $attributes['format'], $comment ); } diff --git a/packages/block-library/src/form/index.php b/packages/block-library/src/form/index.php index 8c63594671ca65..c887d46ad86188 100644 --- a/packages/block-library/src/form/index.php +++ b/packages/block-library/src/form/index.php @@ -92,7 +92,7 @@ function block_core_form_send_email() { // Start building the email content. $content = sprintf( /* translators: %s: The request URI. */ - __( 'Form submission from %1$s', 'gutenberg' ) . '</br>', + __( 'Form submission from %1$s' ) . '</br>', '<a href="' . esc_url( get_site_url( null, $params['_wp_http_referer'] ) ) . '">' . get_bloginfo( 'name' ) . '</a>' ); @@ -110,7 +110,7 @@ function block_core_form_send_email() { // Send the email. $result = wp_mail( str_replace( 'mailto:', '', $params['formAction'] ), - __( 'Form submission', 'gutenberg' ), + __( 'Form submission' ), $content ); diff --git a/packages/block-library/src/post-date/index.php b/packages/block-library/src/post-date/index.php index 3e79855aa25b73..79aa81e7f9c11a 100644 --- a/packages/block-library/src/post-date/index.php +++ b/packages/block-library/src/post-date/index.php @@ -26,10 +26,10 @@ function render_block_core_post_date( $attributes, $content, $block ) { $post_timestamp = get_post_timestamp( $post_ID ); if ( $post_timestamp > time() ) { // translators: %s: human-readable time difference. - $formatted_date = sprintf( __( '%s from now', 'gutenberg' ), human_time_diff( $post_timestamp ) ); + $formatted_date = sprintf( __( '%s from now' ), human_time_diff( $post_timestamp ) ); } else { // translators: %s: human-readable time difference. - $formatted_date = sprintf( __( '%s ago', 'gutenberg' ), human_time_diff( $post_timestamp ) ); + $formatted_date = sprintf( __( '%s ago' ), human_time_diff( $post_timestamp ) ); } } else { $formatted_date = get_the_date( empty( $attributes['format'] ) ? '' : $attributes['format'], $post_ID ); @@ -52,7 +52,7 @@ function render_block_core_post_date( $attributes, $content, $block ) { if ( get_the_modified_date( 'Ymdhi', $post_ID ) > get_the_date( 'Ymdhi', $post_ID ) ) { if ( isset( $attributes['format'] ) && 'human-diff' === $attributes['format'] ) { // translators: %s: human-readable time difference. - $formatted_date = sprintf( __( '%s ago', 'gutenberg' ), human_time_diff( get_post_timestamp( $post_ID, 'modified' ) ) ); + $formatted_date = sprintf( __( '%s ago' ), human_time_diff( get_post_timestamp( $post_ID, 'modified' ) ) ); } else { $formatted_date = get_the_modified_date( empty( $attributes['format'] ) ? '' : $attributes['format'], $post_ID ); } From 4d4522c3102a9e32b8a1a36b09f7c1ab43d3ad37 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 22 Aug 2024 07:32:12 +0400 Subject: [PATCH 0492/1908] Post Title: Fix pasting in Safari (#64671) Unlinked contributors: lukasbesch, Kuuuzya. Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ironprogrammer <ironprogrammer@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: murshed <fahimmurshed@git.wordpress.org> Co-authored-by: megane9988 <megane9988@git.wordpress.org> Co-authored-by: MatzeKitt <kittmedia@git.wordpress.org> Co-authored-by: marekzelezny <igreenie@git.wordpress.org> --- packages/editor/src/components/post-title/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/editor/src/components/post-title/index.js b/packages/editor/src/components/post-title/index.js index 3e333b38eee00e..1eee94d578b82b 100644 --- a/packages/editor/src/components/post-title/index.js +++ b/packages/editor/src/components/post-title/index.js @@ -192,7 +192,6 @@ function PostTitle( _, forwardedRef ) { onFocus={ onSelect } onBlur={ onUnselect } onKeyDown={ onKeyDown } - onKeyPress={ onUnselect } onPaste={ onPaste } /> </PostTypeSupportCheck> From eac8d5eeddcefc4ee34b6202e0a7ed67f1d85032 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 22 Aug 2024 17:14:54 +0900 Subject: [PATCH 0493/1908] UnitControl: Add lint rule for 40px size prop usage (#64520) * Fix in Featured Image block * Fix in Cover block * Make explicit in LetterSpacingControl * Add TODO comments * Add lint rule * Tweak in Cover block * Move to prefix slot in Dimensions Panel * Tweak padding? * Fix "Block spacing" in Dimensions Panel * Add LetterSpacingControl to linter * Fix tests * Revert "Tweak padding?" This reverts commit 7aabc7621752627d057c0dc49bc172e8d7c36fec. * Revert "Move to prefix slot in Dimensions Panel" This reverts commit 2b3e3a1593b8ef6aab0771784d9eb4d14ea3c456. * Move to less strict lint * Add link to relevant discussion Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .eslintrc.js | 17 ++++++++++------- .../global-styles/dimensions-panel.js | 9 ++++++++- .../components/letter-spacing-control/README.md | 9 ++++++++- .../components/letter-spacing-control/index.js | 11 +++++++---- .../block-editor/src/layouts/constrained.js | 4 ++++ .../src/cover/edit/inspector-controls.js | 5 +++-- packages/block-library/src/cover/test/edit.js | 4 ++-- .../post-featured-image/dimension-controls.js | 5 +++-- test/e2e/specs/editor/blocks/cover.spec.js | 2 +- 9 files changed, 46 insertions(+), 20 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 13362e76c4e473..03c4fd78385277 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -323,6 +323,7 @@ module.exports = { 'FontSizePicker', 'FormTokenField', 'InputControl', + 'LetterSpacingControl', 'LineHeightControl', 'NumberControl', 'RangeControl', @@ -343,13 +344,15 @@ module.exports = { 'FormFileUpload should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', }, // Temporary rules until all existing components have the `__next40pxDefaultSize` prop. - ...[ 'SelectControl' ].map( ( componentName ) => ( { - // Not strict. Allows pre-existing __next40pxDefaultSize={ false } usage until they are all manually updated. - selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"])):not(:has(JSXAttribute[name.name="size"]))`, - message: - componentName + - ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', - } ) ), + ...[ 'SelectControl', 'UnitControl' ].map( + ( componentName ) => ( { + // Not strict. Allows pre-existing __next40pxDefaultSize={ false } usage until they are all manually updated. + selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"])):not(:has(JSXAttribute[name.name="size"]))`, + message: + componentName + + ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', + } ) + ), ], }, }, diff --git a/packages/block-editor/src/components/global-styles/dimensions-panel.js b/packages/block-editor/src/components/global-styles/dimensions-panel.js index 5711e16ffadcb1..241d3bb93d1b13 100644 --- a/packages/block-editor/src/components/global-styles/dimensions-panel.js +++ b/packages/block-editor/src/components/global-styles/dimensions-panel.js @@ -476,6 +476,8 @@ export default function DimensionsPanel( { > <HStack alignment="flex-end" justify="flex-start"> <UnitControl + // TODO: Switch to `true` (40px size) if possible (https://github.com/WordPress/gutenberg/pull/64520#discussion_r1717314262) + __next40pxDefaultSize={ false } label={ __( 'Content' ) } labelPosition="top" __unstableInputWidth="80px" @@ -504,6 +506,8 @@ export default function DimensionsPanel( { > <HStack alignment="flex-end" justify="flex-start"> <UnitControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } label={ __( 'Wide' ) } labelPosition="top" __unstableInputWidth="80px" @@ -611,6 +615,9 @@ export default function DimensionsPanel( { } className={ clsx( { 'tools-panel-item-spacing': showSpacingPresetsControl, + 'single-column': + // If UnitControl is used, should be single-column. + ! showSpacingPresetsControl && ! isAxialGap, } ) } panelId={ panelId } > @@ -628,8 +635,8 @@ export default function DimensionsPanel( { /> ) : ( <UnitControl + __next40pxDefaultSize label={ __( 'Block spacing' ) } - __unstableInputWidth="80px" min={ 0 } onChange={ setGapValue } units={ units } diff --git a/packages/block-editor/src/components/letter-spacing-control/README.md b/packages/block-editor/src/components/letter-spacing-control/README.md index 4288f67a2aa99b..ef119bbc943d2f 100644 --- a/packages/block-editor/src/components/letter-spacing-control/README.md +++ b/packages/block-editor/src/components/letter-spacing-control/README.md @@ -38,13 +38,20 @@ The current value of the letter spacing setting. A callback function invoked when the value is changed. -### `_unstableInputWidth` +### `__unstableInputWidth` - **Type:** `string|number|undefined` - **Default:** `undefined` Input width to pass through to inner UnitControl. Should be a valid CSS value. +#### `__next40pxDefaultSize` + +- **Type:** `boolean` +- **Default:** `false` + +Start opting into the larger default height that will become the default size in a future version. + ## Related components Block Editor components are components that can be used to compose the UI of your block editor. Thus, they can only be used under a [`BlockEditorProvider`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/provider/README.md) in the components tree. diff --git a/packages/block-editor/src/components/letter-spacing-control/index.js b/packages/block-editor/src/components/letter-spacing-control/index.js index 2c36e59cd8241c..1577e184c4a06c 100644 --- a/packages/block-editor/src/components/letter-spacing-control/index.js +++ b/packages/block-editor/src/components/letter-spacing-control/index.js @@ -15,14 +15,16 @@ import { useSettings } from '../../components/use-settings'; /** * Control for letter-spacing. * - * @param {Object} props Component props. - * @param {string} props.value Currently selected letter-spacing. - * @param {Function} props.onChange Handles change in letter-spacing selection. - * @param {string|number|undefined} props.__unstableInputWidth Input width to pass through to inner UnitControl. Should be a valid CSS value. + * @param {Object} props Component props. + * @param {boolean} props.__next40pxDefaultSize Start opting into the larger default height that will become the default size in a future version. + * @param {string} props.value Currently selected letter-spacing. + * @param {Function} props.onChange Handles change in letter-spacing selection. + * @param {string|number|undefined} props.__unstableInputWidth Input width to pass through to inner UnitControl. Should be a valid CSS value. * * @return {Element} Letter-spacing control. */ export default function LetterSpacingControl( { + __next40pxDefaultSize = false, value, onChange, __unstableInputWidth = '60px', @@ -35,6 +37,7 @@ export default function LetterSpacingControl( { } ); return ( <UnitControl + __next40pxDefaultSize={ __next40pxDefaultSize } { ...otherProps } label={ __( 'Letter spacing' ) } value={ value } diff --git a/packages/block-editor/src/layouts/constrained.js b/packages/block-editor/src/layouts/constrained.js index b48e331792bd8a..b8dcde637a4d30 100644 --- a/packages/block-editor/src/layouts/constrained.js +++ b/packages/block-editor/src/layouts/constrained.js @@ -75,6 +75,8 @@ export default { <div className="block-editor-hooks__layout-controls"> <div className="block-editor-hooks__layout-controls-unit"> <UnitControl + // TODO: Switch to `true` (40px size) if possible (https://github.com/WordPress/gutenberg/pull/64520#discussion_r1717314262) + __next40pxDefaultSize={ false } className="block-editor-hooks__layout-controls-unit-input" label={ __( 'Content' ) } labelPosition="top" @@ -96,6 +98,8 @@ export default { </div> <div className="block-editor-hooks__layout-controls-unit"> <UnitControl + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="block-editor-hooks__layout-controls-unit-input" label={ __( 'Wide' ) } labelPosition="top" diff --git a/packages/block-library/src/cover/edit/inspector-controls.js b/packages/block-library/src/cover/edit/inspector-controls.js index eedd94de88e4aa..10bd3de890a0c4 100644 --- a/packages/block-library/src/cover/edit/inspector-controls.js +++ b/packages/block-library/src/cover/edit/inspector-controls.js @@ -73,13 +73,13 @@ function CoverHeightInput( { return ( <UnitControl - label={ __( 'Minimum height of cover' ) } + __next40pxDefaultSize + label={ __( 'Minimum height' ) } id={ inputId } isResetValueOnUnitChange min={ min } onChange={ handleOnChange } onUnitChange={ onUnitChange } - __unstableInputWidth="80px" units={ units } value={ computedValue } /> @@ -299,6 +299,7 @@ export default function CoverInspectorControls( { ) } <InspectorControls group="dimensions"> <ToolsPanelItem + className="single-column" hasValue={ () => !! minHeight } label={ __( 'Minimum height' ) } onDeselect={ () => diff --git a/packages/block-library/src/cover/test/edit.js b/packages/block-library/src/cover/test/edit.js index ab99d3c555e3bc..ca34c15d0b7ec6 100644 --- a/packages/block-library/src/cover/test/edit.js +++ b/packages/block-library/src/cover/test/edit.js @@ -372,10 +372,10 @@ describe( 'Cover block', () => { } ) ); await userEvent.clear( - screen.getByLabelText( 'Minimum height of cover' ) + screen.getByLabelText( 'Minimum height' ) ); await userEvent.type( - screen.getByLabelText( 'Minimum height of cover' ), + screen.getByLabelText( 'Minimum height' ), '300' ); diff --git a/packages/block-library/src/post-featured-image/dimension-controls.js b/packages/block-library/src/post-featured-image/dimension-controls.js index fa0f022332b0cb..b31b68b7811976 100644 --- a/packages/block-library/src/post-featured-image/dimension-controls.js +++ b/packages/block-library/src/post-featured-image/dimension-controls.js @@ -134,8 +134,7 @@ const DimensionControls = ( { panelId={ clientId } > <SelectControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Aspect ratio' ) } value={ aspectRatio } @@ -157,6 +156,7 @@ const DimensionControls = ( { panelId={ clientId } > <UnitControl + __next40pxDefaultSize label={ __( 'Height' ) } labelPosition="top" value={ height || '' } @@ -179,6 +179,7 @@ const DimensionControls = ( { panelId={ clientId } > <UnitControl + __next40pxDefaultSize label={ __( 'Width' ) } labelPosition="top" value={ width || '' } diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index fa5103ebaa4eeb..cf3005c9eaa18f 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -158,7 +158,7 @@ test.describe( 'Cover', () => { // Ensure there the default value for the minimum height of cover is undefined. const defaultHeightValue = await coverBlockEditorSettings - .getByLabel( 'Minimum height of cover' ) + .getByLabel( 'Minimum height' ) .inputValue(); expect( defaultHeightValue ).toBeFalsy(); From b6bdf780b5cd9d1a7d5da081f62296a5a90f2d59 Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Thu, 22 Aug 2024 10:33:15 +0200 Subject: [PATCH 0494/1908] Add remaining i18n rules to recommended ESLint ruleset (#64710) --- packages/eslint-plugin/CHANGELOG.md | 5 +++++ packages/eslint-plugin/configs/i18n.js | 2 ++ 2 files changed, 7 insertions(+) diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index d66d8e9c9212cf..b61a4ecb9f3bb7 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +### Breaking Changes + +- Add [`@wordpress/i18n-no-flanking-whitespace`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/eslint-plugin/docs/rules/i18n-no-flanking-whitespace.md) to the recommended i18n ruleset ([#64710](https://github.com/WordPress/gutenberg/pull/64710). +- Add [`@wordpress/i18n-hyphenated-range`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/eslint-plugin/docs/rules/i18n-hyphenated-range.md) to the recommended i18n ruleset ([#64710](https://github.com/WordPress/gutenberg/pull/64710). + ## 20.3.0 (2024-08-21) ## 20.2.0 (2024-08-07) diff --git a/packages/eslint-plugin/configs/i18n.js b/packages/eslint-plugin/configs/i18n.js index c3271214e3ef5c..fb8cad233232d4 100644 --- a/packages/eslint-plugin/configs/i18n.js +++ b/packages/eslint-plugin/configs/i18n.js @@ -8,5 +8,7 @@ module.exports = { '@wordpress/i18n-no-placeholders-only': 'error', '@wordpress/i18n-no-variables': 'error', '@wordpress/i18n-ellipsis': 'error', + '@wordpress/i18n-no-flanking-whitespace': 'error', + '@wordpress/i18n-hyphenated-range': 'error', }, }; From 3455f60ebc2c0f8a6af5ca3dba0c33a1bc940aa6 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Thu, 22 Aug 2024 09:54:20 +0100 Subject: [PATCH 0495/1908] Add "Edit" button to Zoom Out mode toolbar (#64571) --- .../components/block-tools/zoom-out-toolbar.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js index 4dcadc798489a4..b35c67482b4c78 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js @@ -6,7 +6,7 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { dragHandle, trash } from '@wordpress/icons'; +import { dragHandle, trash, edit } from '@wordpress/icons'; import { Button, ToolbarButton } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as blocksStore } from '@wordpress/blocks'; @@ -77,7 +77,8 @@ export default function ZoomOutToolbar( { clientId, rootClientId } ) { canMove, } = selected; - const { removeBlock } = useDispatch( blockEditorStore ); + const { removeBlock, __unstableSetEditorMode } = + useDispatch( blockEditorStore ); const classNames = clsx( 'zoom-out-toolbar', { 'is-block-moving-mode': !! blockMovingMode, @@ -124,6 +125,18 @@ export default function ZoomOutToolbar( { clientId, rootClientId } ) { { canMove && canRemove && ( <Shuffle clientId={ clientId } as={ ToolbarButton } /> ) } + + { ! isBlockTemplatePart && ( + <ToolbarButton + className="zoom-out-toolbar-button" + icon={ edit } + label={ __( 'Edit' ) } + onClick={ () => { + __unstableSetEditorMode( 'edit' ); + } } + /> + ) } + { canRemove && ! isBlockTemplatePart && ( <ToolbarButton className="zoom-out-toolbar-button" From 2a7c3e6f7cb0ad39a128063f4658ec2ddb760d42 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Thu, 22 Aug 2024 10:15:11 +0100 Subject: [PATCH 0496/1908] Fix list layout actions scrim (#64696) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/dataviews/src/dataviews-layouts/list/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/dataviews/src/dataviews-layouts/list/style.scss b/packages/dataviews/src/dataviews-layouts/list/style.scss index 5b8f764d012a22..a3295d1f3fd5f2 100644 --- a/packages/dataviews/src/dataviews-layouts/list/style.scss +++ b/packages/dataviews/src/dataviews-layouts/list/style.scss @@ -73,6 +73,7 @@ color: $gray-900; } &:hover, + &.is-hovered, &:focus-within { color: var(--wp-admin-theme-color); background-color: #f8f8f8; From 2cbba93a29600f09f6f95c09f690576b90e79e9f Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 22 Aug 2024 11:45:42 +0200 Subject: [PATCH 0497/1908] Composite: fix Storybook docgen (#64682) * Move subcomponents to separate files, add default export * Remove custom Storybook args info * Remove subcomponents folder * Do not export `useCompositeStore` in the index.tsx file * CHANGELOG * Update contributing guidelines * Remove unnecessary displayName override on top level composite * Remove default exports * Move CHANGELOG entry under right section * Remove JSDoc prop types * CHANGELOG update * typo --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 + packages/components/CONTRIBUTING.md | 58 ++-- .../src/alignment-matrix-control/index.tsx | 3 +- .../circular-option-picker.tsx | 3 +- .../components/src/composite/group-label.tsx | 31 ++ packages/components/src/composite/group.tsx | 31 ++ packages/components/src/composite/hover.tsx | 31 ++ packages/components/src/composite/index.tsx | 157 +--------- packages/components/src/composite/item.tsx | 31 ++ .../components/src/composite/legacy/index.tsx | 3 +- packages/components/src/composite/row.tsx | 31 ++ packages/components/src/composite/store.ts | 46 +++ .../src/composite/stories/index.story.tsx | 268 +----------------- .../components/src/composite/typeahead.tsx | 31 ++ packages/components/src/private-apis.ts | 3 +- 15 files changed, 301 insertions(+), 430 deletions(-) create mode 100644 packages/components/src/composite/group-label.tsx create mode 100644 packages/components/src/composite/group.tsx create mode 100644 packages/components/src/composite/hover.tsx create mode 100644 packages/components/src/composite/item.tsx create mode 100644 packages/components/src/composite/row.tsx create mode 100644 packages/components/src/composite/store.ts create mode 100644 packages/components/src/composite/typeahead.tsx diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index c98f2bfa38aafd..a95e99fb630c93 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Internal + +- `Composite` V2: fix Storybook docgen ([#64682](https://github.com/WordPress/gutenberg/pull/64682)). + ## 28.6.0 (2024-08-21) ### Deprecations diff --git a/packages/components/CONTRIBUTING.md b/packages/components/CONTRIBUTING.md index 57a9f2fb049a24..40718b3577ab94 100644 --- a/packages/components/CONTRIBUTING.md +++ b/packages/components/CONTRIBUTING.md @@ -248,6 +248,7 @@ To meet the above requirements, we recommend: - using `Object.assign()` to add subcomponents as properties of the top-level component; - using named functions for all components; +- using a separate file for each component, context and hook; - setting explicitly the `displayName` on all subcomponents; - adding the top-level JSDoc to the result of the `Object.assign` call; - adding inline subcomponent JSDocs inside the `Object.assign` call. @@ -256,36 +257,55 @@ The following example implements all of the above recommendations. ```tsx //======================= -// Component.tsx +// subcomponent.tsx //======================= -import { forwardRef, createContext } from '@wordpress/element'; +import { forwardRef } from '@wordpress/element'; -function UnforwardedTopLevelComponent( props, ref ) { - /* ... */ -} -const TopLevelComponent = forwardRef( UnforwardedTopLevelComponent ); - -function UnforwardedSubComponent( props, ref ) { - /* ... */ -} -const SubComponent = forwardRef( UnforwardedSubComponent ); +export const SubComponent = forwardRef( + function UnforwardedSubComponent( props, ref ) { + /* ... */ + } +); SubComponent.displayName = 'Component.SubComponent'; -const Context = createContext(); +//======================= +// context.ts +//======================= +import { createContext } from '@wordpress/element'; -/** The top-level component's JSDoc. */ -export const Component = Object.assign( TopLevelComponent, { - /** The subcomponent's JSDoc. */ - SubComponent, - /** The context's JSDoc. */ - Context, -} ); +export const Context = createContext(); + +//======================= +// hook.ts +//======================= /** The hook's JSDoc. */ export function useComponent() { /* ... */ } +//======================= +// component.tsx +//======================= +import { forwardRef } from '@wordpress/element'; +import { SubComponent } from './subcomponent'; +import { Context } from './context'; + +/** The top-level component's JSDoc. */ +export const Component = Object.assign( + forwardRef( function UnforwardedTopLevelComponent( props, ref ) { + /* ... */ + } ), + { + /** The subcomponent's JSDoc. */ + SubComponent, + /** The context's JSDoc. */ + Context, + } +); + +export default Component; + //======================= // App.tsx //======================= diff --git a/packages/components/src/alignment-matrix-control/index.tsx b/packages/components/src/alignment-matrix-control/index.tsx index cd6bc7acabc3cd..4f3e78ca921f01 100644 --- a/packages/components/src/alignment-matrix-control/index.tsx +++ b/packages/components/src/alignment-matrix-control/index.tsx @@ -14,7 +14,8 @@ import { useInstanceId } from '@wordpress/compose'; * Internal dependencies */ import Cell from './cell'; -import { Composite, useCompositeStore } from '../composite'; +import { Composite } from '../composite'; +import { useCompositeStore } from '../composite/store'; import { Root, Row } from './styles/alignment-matrix-control-styles'; import AlignmentMatrixControlIcon from './icon'; import { GRID, getItemId, getItemValue } from './utils'; diff --git a/packages/components/src/circular-option-picker/circular-option-picker.tsx b/packages/components/src/circular-option-picker/circular-option-picker.tsx index c1e719f2d4f665..c878000aff84b8 100644 --- a/packages/components/src/circular-option-picker/circular-option-picker.tsx +++ b/packages/components/src/circular-option-picker/circular-option-picker.tsx @@ -13,7 +13,8 @@ import { isRTL } from '@wordpress/i18n'; * Internal dependencies */ import { CircularOptionPickerContext } from './circular-option-picker-context'; -import { Composite, useCompositeStore } from '../composite'; +import { Composite } from '../composite'; +import { useCompositeStore } from '../composite/store'; import type { CircularOptionPickerProps, ListboxCircularOptionPickerProps, diff --git a/packages/components/src/composite/group-label.tsx b/packages/components/src/composite/group-label.tsx new file mode 100644 index 00000000000000..ce3629e1d3e4b1 --- /dev/null +++ b/packages/components/src/composite/group-label.tsx @@ -0,0 +1,31 @@ +/** + * External dependencies + */ +import * as Ariakit from '@ariakit/react'; + +/** + * WordPress dependencies + */ +import { forwardRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import { useCompositeContext } from './context'; +import type { CompositeGroupLabelProps } from './types'; + +export const CompositeGroupLabel = forwardRef< + HTMLDivElement, + WordPressComponentProps< CompositeGroupLabelProps, 'div', false > +>( function CompositeGroupLabel( props, ref ) { + const context = useCompositeContext(); + return ( + <Ariakit.CompositeGroupLabel + store={ context?.store } + { ...props } + ref={ ref } + /> + ); +} ); +CompositeGroupLabel.displayName = 'Composite.GroupLabel'; diff --git a/packages/components/src/composite/group.tsx b/packages/components/src/composite/group.tsx new file mode 100644 index 00000000000000..cd908d97c2a3e2 --- /dev/null +++ b/packages/components/src/composite/group.tsx @@ -0,0 +1,31 @@ +/** + * External dependencies + */ +import * as Ariakit from '@ariakit/react'; + +/** + * WordPress dependencies + */ +import { forwardRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import { useCompositeContext } from './context'; +import type { CompositeGroupProps } from './types'; + +export const CompositeGroup = forwardRef< + HTMLDivElement, + WordPressComponentProps< CompositeGroupProps, 'div', false > +>( function CompositeGroup( props, ref ) { + const context = useCompositeContext(); + return ( + <Ariakit.CompositeGroup + store={ context?.store } + { ...props } + ref={ ref } + /> + ); +} ); +CompositeGroup.displayName = 'Composite.Group'; diff --git a/packages/components/src/composite/hover.tsx b/packages/components/src/composite/hover.tsx new file mode 100644 index 00000000000000..57aae1dde63c84 --- /dev/null +++ b/packages/components/src/composite/hover.tsx @@ -0,0 +1,31 @@ +/** + * External dependencies + */ +import * as Ariakit from '@ariakit/react'; + +/** + * WordPress dependencies + */ +import { forwardRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import { useCompositeContext } from './context'; +import type { CompositeHoverProps } from './types'; + +export const CompositeHover = forwardRef< + HTMLDivElement, + WordPressComponentProps< CompositeHoverProps, 'div', false > +>( function CompositeHover( props, ref ) { + const context = useCompositeContext(); + return ( + <Ariakit.CompositeHover + store={ context?.store } + { ...props } + ref={ ref } + /> + ); +} ); +CompositeHover.displayName = 'Composite.Hover'; diff --git a/packages/components/src/composite/index.tsx b/packages/components/src/composite/index.tsx index 0bfcec2bf76600..1b4cc361ea4cfa 100644 --- a/packages/components/src/composite/index.tsx +++ b/packages/components/src/composite/index.tsx @@ -22,142 +22,14 @@ import { useMemo, forwardRef } from '@wordpress/element'; * Internal dependencies */ import type { WordPressComponentProps } from '../context'; -import { CompositeContext, useCompositeContext } from './context'; -import type { - CompositeStoreProps, - CompositeProps, - CompositeGroupProps, - CompositeGroupLabelProps, - CompositeItemProps, - CompositeRowProps, - CompositeHoverProps, - CompositeTypeaheadProps, -} from './types'; - -/** - * Creates a composite store. - * - * @example - * ```jsx - * import { Composite, useCompositeStore } from '@wordpress/components'; - * - * const store = useCompositeStore(); - * <Composite store={store}> - * <Composite.Item>Item</Composite.Item> - * <Composite.Item>Item</Composite.Item> - * <Composite.Item>Item</Composite.Item> - * </Composite> - * ``` - */ -export function useCompositeStore( { - focusLoop = false, - focusWrap = false, - focusShift = false, - virtualFocus = false, - orientation = 'both', - rtl = false, - ...props -}: CompositeStoreProps = {} ) { - return Ariakit.useCompositeStore( { - focusLoop, - focusWrap, - focusShift, - virtualFocus, - orientation, - rtl, - ...props, - } ); -} - -const Group = forwardRef< - HTMLDivElement, - WordPressComponentProps< CompositeGroupProps, 'div', false > ->( function CompositeGroup( props, ref ) { - const context = useCompositeContext(); - return ( - <Ariakit.CompositeGroup - store={ context?.store } - { ...props } - ref={ ref } - /> - ); -} ); -Group.displayName = 'Composite.Group'; - -const GroupLabel = forwardRef< - HTMLDivElement, - WordPressComponentProps< CompositeGroupLabelProps, 'div', false > ->( function CompositeGroupLabel( props, ref ) { - const context = useCompositeContext(); - return ( - <Ariakit.CompositeGroupLabel - store={ context?.store } - { ...props } - ref={ ref } - /> - ); -} ); -GroupLabel.displayName = 'Composite.GroupLabel'; - -const Item = forwardRef< - HTMLButtonElement, - WordPressComponentProps< CompositeItemProps, 'button', false > ->( function CompositeItem( props, ref ) { - const context = useCompositeContext(); - return ( - <Ariakit.CompositeItem - store={ context?.store } - { ...props } - ref={ ref } - /> - ); -} ); -Item.displayName = 'Composite.Item'; - -const Row = forwardRef< - HTMLDivElement, - WordPressComponentProps< CompositeRowProps, 'div', false > ->( function CompositeRow( props, ref ) { - const context = useCompositeContext(); - return ( - <Ariakit.CompositeRow - store={ context?.store } - { ...props } - ref={ ref } - /> - ); -} ); -Row.displayName = 'Composite.Row'; - -const Hover = forwardRef< - HTMLDivElement, - WordPressComponentProps< CompositeHoverProps, 'div', false > ->( function CompositeHover( props, ref ) { - const context = useCompositeContext(); - return ( - <Ariakit.CompositeHover - store={ context?.store } - { ...props } - ref={ ref } - /> - ); -} ); -Hover.displayName = 'Composite.Hover'; - -const Typeahead = forwardRef< - HTMLDivElement, - WordPressComponentProps< CompositeTypeaheadProps, 'div', false > ->( function CompositeTypeahead( props, ref ) { - const context = useCompositeContext(); - return ( - <Ariakit.CompositeTypeahead - store={ context?.store } - { ...props } - ref={ ref } - /> - ); -} ); -Typeahead.displayName = 'Composite.Typeahead'; +import { CompositeContext } from './context'; +import { CompositeGroup } from './group'; +import { CompositeGroupLabel } from './group-label'; +import { CompositeHover } from './hover'; +import { CompositeItem } from './item'; +import { CompositeRow } from './row'; +import { CompositeTypeahead } from './typeahead'; +import type { CompositeProps } from './types'; /** * Renders a widget based on the WAI-ARIA [`composite`](https://w3c.github.io/aria/#composite) @@ -204,7 +76,6 @@ export const Composite = Object.assign( ); } ), { - displayName: 'Composite', /** * Renders a group element for composite items. * @@ -222,7 +93,7 @@ export const Composite = Object.assign( * </Composite> * ``` */ - Group, + Group: CompositeGroup, /** * Renders a label in a composite group. This component must be wrapped with * `Composite.Group` so the `aria-labelledby` prop is properly set on the @@ -242,7 +113,7 @@ export const Composite = Object.assign( * </Composite> * ``` */ - GroupLabel, + GroupLabel: CompositeGroupLabel, /** * Renders a composite item. * @@ -258,7 +129,7 @@ export const Composite = Object.assign( * </Composite> * ``` */ - Item, + Item: CompositeItem, /** * Renders a composite row. Wrapping `Composite.Item` elements within * `Composite.Row` will create a two-dimensional composite widget, such as a @@ -283,7 +154,7 @@ export const Composite = Object.assign( * </Composite> * ``` */ - Row, + Row: CompositeRow, /** * Renders an element in a composite widget that receives focus on mouse move * and loses focus to the composite base element on mouse leave. This should @@ -304,7 +175,7 @@ export const Composite = Object.assign( * </Composite> * ``` */ - Hover, + Hover: CompositeHover, /** * Renders a component that adds typeahead functionality to composite * components. Hitting printable character keys will move focus to the next @@ -321,7 +192,7 @@ export const Composite = Object.assign( * </Composite> * ``` */ - Typeahead, + Typeahead: CompositeTypeahead, /** * The React context used by the composite components. It can be used by * to access the composite store, and to forward the context when composite diff --git a/packages/components/src/composite/item.tsx b/packages/components/src/composite/item.tsx new file mode 100644 index 00000000000000..634ddfbb9bf9e9 --- /dev/null +++ b/packages/components/src/composite/item.tsx @@ -0,0 +1,31 @@ +/** + * External dependencies + */ +import * as Ariakit from '@ariakit/react'; + +/** + * WordPress dependencies + */ +import { forwardRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import { useCompositeContext } from './context'; +import type { CompositeItemProps } from './types'; + +export const CompositeItem = forwardRef< + HTMLButtonElement, + WordPressComponentProps< CompositeItemProps, 'button', false > +>( function CompositeItem( props, ref ) { + const context = useCompositeContext(); + return ( + <Ariakit.CompositeItem + store={ context?.store } + { ...props } + ref={ ref } + /> + ); +} ); +CompositeItem.displayName = 'Composite.Item'; diff --git a/packages/components/src/composite/legacy/index.tsx b/packages/components/src/composite/legacy/index.tsx index dffdc1a2066d47..41ecc6ceb3f66b 100644 --- a/packages/components/src/composite/legacy/index.tsx +++ b/packages/components/src/composite/legacy/index.tsx @@ -21,7 +21,8 @@ import { forwardRef } from '@wordpress/element'; /** * Internal dependencies */ -import { Composite as Current, useCompositeStore } from '..'; +import { Composite as Current } from '..'; +import { useCompositeStore } from '../store'; import { useInstanceId } from '@wordpress/compose'; type Orientation = 'horizontal' | 'vertical'; diff --git a/packages/components/src/composite/row.tsx b/packages/components/src/composite/row.tsx new file mode 100644 index 00000000000000..eb130ce54aa85c --- /dev/null +++ b/packages/components/src/composite/row.tsx @@ -0,0 +1,31 @@ +/** + * External dependencies + */ +import * as Ariakit from '@ariakit/react'; + +/** + * WordPress dependencies + */ +import { forwardRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import { useCompositeContext } from './context'; +import type { CompositeRowProps } from './types'; + +export const CompositeRow = forwardRef< + HTMLDivElement, + WordPressComponentProps< CompositeRowProps, 'div', false > +>( function CompositeRow( props, ref ) { + const context = useCompositeContext(); + return ( + <Ariakit.CompositeRow + store={ context?.store } + { ...props } + ref={ ref } + /> + ); +} ); +CompositeRow.displayName = 'Composite.Row'; diff --git a/packages/components/src/composite/store.ts b/packages/components/src/composite/store.ts new file mode 100644 index 00000000000000..acf24b96cb8128 --- /dev/null +++ b/packages/components/src/composite/store.ts @@ -0,0 +1,46 @@ +/** + * External dependencies + */ +import * as Ariakit from '@ariakit/react'; + +/** + * Internal dependencies + */ +import type { CompositeStoreProps } from './types'; + +// Props are already documented in TypeScript types. +// eslint-disable-next-line jsdoc/require-param +/** + * Creates a composite store. + * + * @example + * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * + * const store = useCompositeStore(); + * <Composite store={store}> + * <Composite.Item>Item</Composite.Item> + * <Composite.Item>Item</Composite.Item> + * <Composite.Item>Item</Composite.Item> + * </Composite> + * ``` + */ +export function useCompositeStore( { + focusLoop = false, + focusWrap = false, + focusShift = false, + virtualFocus = false, + orientation = 'both', + rtl = false, + ...props +}: CompositeStoreProps = {} ) { + return Ariakit.useCompositeStore( { + focusLoop, + focusWrap, + focusShift, + virtualFocus, + orientation, + rtl, + ...props, + } ); +} diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx index 034e1d6721f7bd..80e3d85e3ce296 100644 --- a/packages/components/src/composite/stories/index.story.tsx +++ b/packages/components/src/composite/stories/index.story.tsx @@ -11,7 +11,8 @@ import { isRTL } from '@wordpress/i18n'; /** * Internal dependencies */ -import { Composite, useCompositeStore } from '..'; +import { Composite } from '..'; +import { useCompositeStore } from '../store'; import { UseCompositeStorePlaceholder, transform } from './utils'; const meta: Meta< typeof UseCompositeStorePlaceholder > = { @@ -34,20 +35,14 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { 'Composite.Typeahead': Composite.Typeahead, }, argTypes: { - activeId: { control: 'text' }, - defaultActiveId: { control: 'text' }, setActiveId: { control: { type: null } }, focusLoop: { control: 'select', options: [ true, false, 'horizontal', 'vertical', 'both' ], }, - focusShift: { control: 'boolean' }, - focusWrap: { control: 'boolean' }, - virtualFocus: { control: 'boolean' }, - rtl: { control: 'boolean' }, - orientation: { + focusWrap: { control: 'select', - options: [ 'horizontal', 'vertical', 'both' ], + options: [ true, false, 'horizontal', 'vertical', 'both' ], }, }, tags: [ 'status-private' ], @@ -56,261 +51,6 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { docs: { canvas: { sourceState: 'shown' }, source: { transform }, - extractArgTypes: ( component: React.FunctionComponent ) => { - const commonArgTypes = { - render: { - name: 'render', - description: - 'Allows the component to be rendered as a different HTML element or React component. The value can be a React element or a function that takes in the original component props and gives back a React element with the props merged.', - table: { - type: { - summary: - 'RenderProp<React.HTMLAttributes<any> & { ref?: React.Ref<any> | undefined; }> | React.ReactElement<any, string | React.JSXElementConstructor<any>>', - }, - }, - }, - children: { - name: 'children', - description: 'The contents of the component.', - table: { type: { summary: 'React.ReactNode' } }, - }, - }; - const accessibleWhenDisabled = { - name: 'accessibleWhenDisabled', - description: `Indicates whether the element should be focusable even when it is -\`disabled\`. - -This is important when discoverability is a concern. For example: - -> A toolbar in an editor contains a set of special smart paste functions -> that are disabled when the clipboard is empty or when the function is not -> applicable to the current content of the clipboard. It could be helpful to -> keep the disabled buttons focusable if the ability to discover their -> functionality is primarily via their presence on the toolbar. - -Learn more on [Focusability of disabled -controls](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols).`, - table: { - type: { - summary: 'boolean', - }, - }, - }; - - const argTypes = { - useCompositeStore: { - activeId: { - name: 'activeId', - description: `The current active item \`id\`. The active item is the element within the composite widget that has either DOM or virtual focus (in case the \`virtualFocus\` prop is enabled). -- \`null\` represents the base composite element (the one with a [composite role](https://w3c.github.io/aria/#composite)). Users will be able to navigate out of it using arrow keys. -- If \`activeId\` is initially set to \`null\`, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.`, - table: { type: { summary: 'string | null' } }, - }, - defaultActiveId: { - name: 'defaultActiveId', - description: - 'The composite item id that should be active by default when the composite widget is rendered. If `null`, the composite element itself will have focus and users will be able to navigate to it using arrow keys. If `undefined`, the first enabled item will be focused.', - table: { type: { summary: 'string | null' } }, - }, - setActiveId: { - name: 'setActiveId', - description: - 'A callback that gets called when the `activeId` state changes.', - table: { - type: { - summary: - '((activeId: string | null | undefined) => void)', - }, - }, - }, - focusLoop: { - name: 'focusLoop', - description: `On one-dimensional composite widgets: - -- \`true\` loops from the last item to the first item and vice-versa. -- \`horizontal\` loops only if \`orientation\` is \`horizontal\` or not set. -- \`vertical\` loops only if \`orientation\` is \`vertical\` or not set. -- If \`activeId\` is initially set to \`null\`, the composite element will be focused in between the last and first items. - -On two-dimensional composite widgets (ie. when using \`CompositeRow\`): - -- \`true\` loops from the last row/column item to the first item in the same row/column and vice-versa. If it's the last item in the last row, it moves to the first item in the first row and vice-versa. -- \`horizontal\` loops only from the last row item to the first item in the same row. -- \`vertical\` loops only from the last column item to the first item in the column row. -- If \`activeId\` is initially set to \`null\`, vertical loop will have no effect as moving down from the last row or up from the first row will focus on the composite element. -- If \`focusWrap\` matches the value of \`focusLoop\`, it'll wrap between the last item in the last row or column and the first item in the first row or column and vice-versa.`, - table: { - defaultValue: { - summary: 'false', - }, - type: { - summary: - "boolean | 'horizontal' | 'vertical' | 'both'", - }, - }, - }, - focusShift: { - name: 'focusShift', - description: `**Works only on two-dimensional composite widgets**. - -If enabled, moving up or down when there's no next item or when the next item is disabled will shift to the item right before it.`, - table: { - defaultValue: { - summary: 'false', - }, - type: { - summary: 'boolean', - }, - }, - }, - focusWrap: { - name: 'focusWrap', - description: `**Works only on two-dimensional composite widgets**. - -If enabled, moving to the next item from the last one in a row or column -will focus on the first item in the next row or column and vice-versa. - -- \`true\` wraps between rows and columns. -- \`horizontal\` wraps only between rows. -- \`vertical\` wraps only between columns. -- If \`focusLoop\` matches the value of \`focusWrap\`, it'll wrap between the - last item in the last row or column and the first item in the first row or - column and vice-versa.`, - table: { - defaultValue: { - summary: 'false', - }, - type: { - summary: 'boolean', - }, - }, - }, - virtualFocus: { - name: 'virtualFocus', - description: `If enabled, the composite element will act as an [\`aria-activedescendant\`](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_focus_activedescendant) -container instead of [roving tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex). DOM focus will remain on the composite element while its items receive -virtual focus. - -In both scenarios, the item in focus will carry the \`data-active-item\` attribute.`, - table: { - defaultValue: { - summary: 'false', - }, - type: { - summary: 'boolean', - }, - }, - }, - orientation: { - name: 'orientation', - description: `Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the \`orientation\` value determines which arrow keys can be used to move focus: - -- \`both\`: all arrow keys work. -- \`horizontal\`: only left and right arrow keys work. -- \`vertical\`: only up and down arrow keys work. - -It doesn't have any effect on two-dimensional composites.`, - table: { - defaultValue: { - summary: "'both'", - }, - type: { - summary: - "'horizontal' | 'vertical' | 'both'", - }, - }, - }, - rtl: { - name: 'rtl', - description: `Determines how the \`store\`'s \`next\` and \`previous\` functions will behave. If \`rtl\` is set to \`true\`, they will be inverted. - -This only affects the composite widget behavior. You still need to set \`dir="rtl"\` on HTML/CSS.`, - table: { - defaultValue: { - summary: 'false', - }, - type: { - summary: 'boolean', - }, - }, - }, - }, - Composite: { - ...commonArgTypes, - store: { - name: 'store', - description: - 'Object returned by the `useCompositeStore` hook.', - table: { - type: { - summary: - 'CompositeStore<CompositeStoreItem>', - }, - }, - type: { required: true }, - }, - focusable: { - name: 'focusable', - description: `Makes the component a focusable element. When this element gains keyboard focus, it gets a \`data-focus-visible\` attribute and triggers the \`onFocusVisible\` prop. - -The component supports the \`disabled\` prop even for those elements not supporting the native \`disabled\` attribute. Disabled elements may be still accessible via keyboard by using the the \`accessibleWhenDisabled\` prop. - -Non-native focusable elements will lose their focusability entirely. However, native focusable elements will retain their inherent focusability.`, - table: { - type: { - summary: 'boolean', - }, - }, - }, - disabled: { - name: 'disabled', - description: `Determines if the element is disabled. This sets the \`aria-disabled\` attribute accordingly, enabling support for all elements, including those that don't support the native \`disabled\` attribute. - -This feature can be combined with the \`accessibleWhenDisabled\` prop to -make disabled elements still accessible via keyboard. - -**Note**: For this prop to work, the \`focusable\` prop must be set to -\`true\`, if it's not set by default.`, - table: { - defaultValue: { - summary: 'false', - }, - type: { - summary: 'boolean', - }, - }, - }, - accessibleWhenDisabled, - onFocusVisible: { - name: 'onFocusVisible', - description: `Custom event handler invoked when the element gains focus through keyboard interaction or a key press occurs while the element is in focus. This is the programmatic equivalent of the \`data-focus-visible\` attribute. - -**Note**: For this prop to work, the \`focusable\` prop must be set to \`true\` if it's not set by default.`, - table: { - type: { - summary: - '(event: SyntheticEvent<HTMLElement>) => void', - }, - }, - }, - }, - 'Composite.Group': commonArgTypes, - 'Composite.GroupLabel': commonArgTypes, - 'Composite.Row': commonArgTypes, - 'Composite.Item': { - ...commonArgTypes, - accessibleWhenDisabled, - }, - 'Composite.Hover': commonArgTypes, - 'Composite.Typeahead': commonArgTypes, - }; - - const name = component.displayName ?? ''; - - return name in argTypes - ? argTypes[ name as keyof typeof argTypes ] - : {}; - }, }, }, decorators: [ diff --git a/packages/components/src/composite/typeahead.tsx b/packages/components/src/composite/typeahead.tsx new file mode 100644 index 00000000000000..7d5a9931d19ab0 --- /dev/null +++ b/packages/components/src/composite/typeahead.tsx @@ -0,0 +1,31 @@ +/** + * External dependencies + */ +import * as Ariakit from '@ariakit/react'; + +/** + * WordPress dependencies + */ +import { forwardRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import { useCompositeContext } from './context'; +import type { CompositeTypeaheadProps } from './types'; + +export const CompositeTypeahead = forwardRef< + HTMLDivElement, + WordPressComponentProps< CompositeTypeaheadProps, 'div', false > +>( function CompositeTypeahead( props, ref ) { + const context = useCompositeContext(); + return ( + <Ariakit.CompositeTypeahead + store={ context?.store } + { ...props } + ref={ ref } + /> + ); +} ); +CompositeTypeahead.displayName = 'Composite.Typeahead'; diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index 699911e5ba046b..a4d7fa98ecfb0d 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -1,7 +1,8 @@ /** * Internal dependencies */ -import { Composite, useCompositeStore } from './composite'; +import { Composite } from './composite'; +import { useCompositeStore } from './composite/store'; import { positionToPlacement as __experimentalPopoverLegacyPositionToPlacement } from './popover/utils'; import { createPrivateSlotFill } from './slot-fill'; import { From d8160d86566d1a0e9a3db592131136ef99cc816a Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 22 Aug 2024 12:24:25 +0200 Subject: [PATCH 0498/1908] DropdownMenuV2: use overloaded naming conventions (#64654) * Move subcomponents to overloaded syntax, rename to DropdownMenuV2 * Update imports and usage in Storybook * Update imports and usage in unit tests * Update README * Fix private APIs * Switch to overloaded naming in the rest of the project * Storybook story name typo * Try separate files * CHANGELOG * CHANGELOG: move to unreleased section --------- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../block-editor/src/hooks/block-bindings.js | 31 +- packages/components/CHANGELOG.md | 1 + .../components/src/dropdown-menu-v2/README.md | 115 ++-- .../src/dropdown-menu-v2/checkbox-item.tsx | 60 ++ .../src/dropdown-menu-v2/context.tsx | 14 + .../components/src/dropdown-menu-v2/group.tsx | 27 + .../components/src/dropdown-menu-v2/index.tsx | 216 +------- .../src/dropdown-menu-v2/item-help-text.tsx | 24 + .../src/dropdown-menu-v2/item-label.tsx | 24 + .../components/src/dropdown-menu-v2/item.tsx | 47 ++ .../src/dropdown-menu-v2/radio-item.tsx | 67 +++ .../src/dropdown-menu-v2/separator.tsx | 28 + .../dropdown-menu-v2/stories/index.story.tsx | 512 +++++++++--------- .../src/dropdown-menu-v2/test/index.tsx | 291 +++++----- packages/components/src/private-apis.ts | 18 +- .../dataviews-bulk-actions/index.tsx | 33 +- .../dataviews-filters/add-filter.tsx | 18 +- .../dataviews-item-actions/index.tsx | 22 +- .../dataviews-view-config/index.tsx | 18 +- .../table/column-header-menu.tsx | 67 +-- .../global-styles/font-sizes/font-size.js | 29 +- .../global-styles/font-sizes/font-sizes.js | 20 +- .../global-styles/shadows-edit-panel.js | 18 +- .../src/components/post-actions/index.js | 22 +- 24 files changed, 909 insertions(+), 813 deletions(-) create mode 100644 packages/components/src/dropdown-menu-v2/checkbox-item.tsx create mode 100644 packages/components/src/dropdown-menu-v2/context.tsx create mode 100644 packages/components/src/dropdown-menu-v2/group.tsx create mode 100644 packages/components/src/dropdown-menu-v2/item-help-text.tsx create mode 100644 packages/components/src/dropdown-menu-v2/item-label.tsx create mode 100644 packages/components/src/dropdown-menu-v2/item.tsx create mode 100644 packages/components/src/dropdown-menu-v2/radio-item.tsx create mode 100644 packages/components/src/dropdown-menu-v2/separator.tsx diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index a7aa72ae6693a6..961a34f6f858fc 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -29,14 +29,7 @@ import InspectorControls from '../components/inspector-controls'; import BlockContext from '../components/block-context'; import { useBlockBindingsUtils } from '../utils/block-bindings'; -const { - DropdownMenuV2: DropdownMenu, - DropdownMenuGroupV2: DropdownMenuGroup, - DropdownMenuRadioItemV2: DropdownMenuRadioItem, - DropdownMenuItemLabelV2: DropdownMenuItemLabel, - DropdownMenuItemHelpTextV2: DropdownMenuItemHelpText, - DropdownMenuSeparatorV2: DropdownMenuSeparator, -} = unlock( componentsPrivateApis ); +const { DropdownMenuV2 } = unlock( componentsPrivateApis ); const useToolsPanelDropdownMenuProps = () => { const isMobile = useViewportMatch( 'medium', '<' ); @@ -60,7 +53,7 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) { <> { Object.entries( fieldsList ).map( ( [ name, fields ], i ) => ( <Fragment key={ name }> - <DropdownMenuGroup> + <DropdownMenuV2.Group> { Object.keys( fieldsList ).length > 1 && ( <Text className="block-editor-bindings__source-label" @@ -72,7 +65,7 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) { </Text> ) } { Object.entries( fields ).map( ( [ key, value ] ) => ( - <DropdownMenuRadioItem + <DropdownMenuV2.RadioItem key={ key } onChange={ () => updateBlockBindings( { @@ -86,17 +79,17 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) { value={ key } checked={ key === currentKey } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> { key } - </DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> { value } - </DropdownMenuItemHelpText> - </DropdownMenuRadioItem> + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.RadioItem> ) ) } - </DropdownMenuGroup> + </DropdownMenuV2.Group> { i !== Object.keys( fieldsList ).length - 1 && ( - <DropdownMenuSeparator /> + <DropdownMenuV2.Separator /> ) } </Fragment> ) ) } @@ -162,7 +155,7 @@ function EditableBlockBindingsPanelItems( { } ); } } > - <DropdownMenu + <DropdownMenuV2 placement={ isMobile ? 'bottom-start' : 'left-start' } @@ -182,7 +175,7 @@ function EditableBlockBindingsPanelItems( { attribute={ attribute } binding={ binding } /> - </DropdownMenu> + </DropdownMenuV2> </ToolsPanelItem> ); } ) } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index a95e99fb630c93..5d2479e3149c56 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -4,6 +4,7 @@ ### Internal +- `DropdownMenu` v2: refactor to overloaded naming convention ([#64654](https://github.com/WordPress/gutenberg/pull/64654)). - `Composite` V2: fix Storybook docgen ([#64682](https://github.com/WordPress/gutenberg/pull/64682)). ## 28.6.0 (2024-08-21) diff --git a/packages/components/src/dropdown-menu-v2/README.md b/packages/components/src/dropdown-menu-v2/README.md index 2902b541169766..d0547f1f142600 100644 --- a/packages/components/src/dropdown-menu-v2/README.md +++ b/packages/components/src/dropdown-menu-v2/README.md @@ -1,11 +1,10 @@ -# `DropdownMenu` (v2) +# `DropdownMenuV2` <div class="callout callout-alert"> This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. </div> -`DropdownMenu` displays a menu to the user (such as a set of actions or functions) triggered by a button. - +`DropdownMenuV2` displays a menu to the user (such as a set of actions or functions) triggered by a button. ## Design guidelines @@ -46,7 +45,7 @@ This component is still highly experimental, and it's not normally accessible to The component exposes a set of components that are meant to be used in combination with each other in order to implement a `DropdownMenu` correctly. -### `DropdownMenu` +### `DropdownMenuV2` The root component, used to specify the menu's trigger and its contents. @@ -58,62 +57,62 @@ The component accepts the following props: The trigger button -- Required: yes +- Required: yes ##### `children`: `React.ReactNode` The contents of the dropdown -- Required: yes +- Required: yes ##### `defaultOpen`: `boolean` The open state of the dropdown menu when it is initially rendered. Use when not wanting to control its open state. -- Required: no -- Default: `false` +- Required: no +- Default: `false` ##### `open`: `boolean` The controlled open state of the dropdown menu. Must be used in conjunction with `onOpenChange`. -- Required: no +- Required: no ##### `onOpenChange`: `(open: boolean) => void` Event handler called when the open state of the dropdown menu changes. -- Required: no +- Required: no ##### `modal`: `boolean` The modality of the dropdown menu. When set to true, interaction with outside elements will be disabled and only menu content will be visible to screen readers. -- Required: no -- Default: `true` +- Required: no +- Default: `true` ##### `placement`: ``'top' | 'top-start' | 'top-end' | 'right' | 'right-start' | 'right-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end'` The placement of the dropdown menu popover. -- Required: no -- Default: `'bottom-start'` for root-level menus, `'right-start'` for nested menus +- Required: no +- Default: `'bottom-start'` for root-level menus, `'right-start'` for nested menus ##### `gutter`: `number` The distance in pixels from the trigger. -- Required: no -- Default: `8` for root-level menus, `16` for nested menus +- Required: no +- Default: `8` for root-level menus, `16` for nested menus ##### `shift`: `number` The skidding of the popover along the anchor element. Can be set to negative values to make the popover shift to the opposite side. -- Required: no -- Default: `0` for root-level menus, `-8` for nested menus +- Required: no +- Default: `0` for root-level menus, `-8` for nested menus -### `DropdownMenuItem` +### `DropdownMenuV2.Item` Used to render a menu item. @@ -125,35 +124,35 @@ The component accepts the following props: The contents of the item -- Required: yes +- Required: yes ##### `prefix`: `React.ReactNode` The contents of the item's prefix. -- Required: no +- Required: no ##### `suffix`: `React.ReactNode` The contents of the item's suffix. -- Required: no +- Required: no ##### `hideOnClick`: `boolean` Whether to hide the dropdown menu when the menu item is clicked. -- Required: no -- Default: `true` +- Required: no +- Default: `true` ##### `disabled`: `boolean` Determines if the element is disabled. -- Required: no -- Default: `false` +- Required: no +- Default: `false` -### `DropdownMenuCheckboxItem` +### `DropdownMenuV2.CheckboxItem` Used to render a checkbox item. @@ -165,61 +164,61 @@ The component accepts the following props: The contents of the item -- Required: yes +- Required: yes ##### `suffix`: `React.ReactNode` The contents of the item's suffix. -- Required: no +- Required: no ##### `hideOnClick`: `boolean` Whether to hide the dropdown menu when the menu item is clicked. -- Required: no -- Default: `false` +- Required: no +- Default: `false` ##### `disabled`: `boolean` Determines if the element is disabled. -- Required: no -- Default: `false` +- Required: no +- Default: `false` ##### `name`: `string` The checkbox item's name. -- Required: yes +- Required: yes ##### `value`: `string` The checkbox item's value, useful when using multiple checkbox items - associated to the same `name`. +associated to the same `name`. -- Required: no +- Required: no ##### `checked`: `boolean` The checkbox item's value, useful when using multiple checkbox items - associated to the same `name`. +associated to the same `name`. -- Required: no +- Required: no ##### `defaultChecked`: `boolean` The checked state of the checkbox menu item when it is initially rendered. Use when not wanting to control its checked state. -- Required: no +- Required: no ##### `onChange`: `( event: React.ChangeEvent< HTMLInputElement > ) => void;` Event handler called when the checked state of the checkbox menu item changes. -- Required: no +- Required: no -### `DropdownMenuRadioItem` +### `DropdownMenuV2.RadioItem` Used to render a radio item. @@ -231,60 +230,60 @@ The component accepts the following props: The contents of the item -- Required: yes +- Required: yes ##### `suffix`: `React.ReactNode` The contents of the item's suffix. -- Required: no +- Required: no ##### `hideOnClick`: `boolean` Whether to hide the dropdown menu when the menu item is clicked. -- Required: no -- Default: `false` +- Required: no +- Default: `false` ##### `disabled`: `boolean` Determines if the element is disabled. -- Required: no -- Default: `false` +- Required: no +- Default: `false` ##### `name`: `string` The radio item's name. -- Required: yes +- Required: yes ##### `value`: `string | number` The radio item's value. -- Required: yes +- Required: yes ##### `checked`: `boolean` The checkbox item's value, useful when using multiple checkbox items - associated to the same `name`. +associated to the same `name`. -- Required: no +- Required: no ##### `defaultChecked`: `boolean` The checked state of the radio menu item when it is initially rendered. Use when not wanting to control its checked state. -- Required: no +- Required: no ##### `onChange`: `( event: React.ChangeEvent< HTMLInputElement > ) => void;` Event handler called when the checked radio menu item changes. -- Required: no +- Required: no -### `DropdownMenuItemLabel` +### `DropdownMenuV2.ItemLabel` Used to render the menu item's label. @@ -296,9 +295,9 @@ The component accepts the following props: The label contents. -- Required: yes +- Required: yes -### `DropdownMenuItemHelpText` +### `DropdownMenuV2.ItemHelpText` Used to render the menu item's help text. @@ -310,7 +309,7 @@ The component accepts the following props: The help text contents. -- Required: yes +- Required: yes ### `DropdownMenuGroup` @@ -324,7 +323,7 @@ The component accepts the following props: The contents of the group. -- Required: yes +- Required: yes ### `DropdownMenuSeparatorProps` diff --git a/packages/components/src/dropdown-menu-v2/checkbox-item.tsx b/packages/components/src/dropdown-menu-v2/checkbox-item.tsx new file mode 100644 index 00000000000000..d97859461b893f --- /dev/null +++ b/packages/components/src/dropdown-menu-v2/checkbox-item.tsx @@ -0,0 +1,60 @@ +/** + * External dependencies + */ +import * as Ariakit from '@ariakit/react'; + +/** + * WordPress dependencies + */ +import { forwardRef, useContext } from '@wordpress/element'; +import { Icon, check } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import { DropdownMenuContext } from './context'; +import type { DropdownMenuCheckboxItemProps } from './types'; +import * as Styled from './styles'; + +export const DropdownMenuCheckboxItem = forwardRef< + HTMLDivElement, + WordPressComponentProps< DropdownMenuCheckboxItemProps, 'div', false > +>( function DropdownMenuCheckboxItem( + { suffix, children, hideOnClick = false, ...props }, + ref +) { + const dropdownMenuContext = useContext( DropdownMenuContext ); + + return ( + <Styled.DropdownMenuCheckboxItem + ref={ ref } + { ...props } + accessibleWhenDisabled + hideOnClick={ hideOnClick } + store={ dropdownMenuContext?.store } + > + <Ariakit.MenuItemCheck + store={ dropdownMenuContext?.store } + render={ <Styled.ItemPrefixWrapper /> } + // Override some ariakit inline styles + style={ { width: 'auto', height: 'auto' } } + > + <Icon icon={ check } size={ 24 } /> + </Ariakit.MenuItemCheck> + + <Styled.DropdownMenuItemContentWrapper> + <Styled.DropdownMenuItemChildrenWrapper> + { children } + </Styled.DropdownMenuItemChildrenWrapper> + + { suffix && ( + <Styled.ItemSuffixWrapper> + { suffix } + </Styled.ItemSuffixWrapper> + ) } + </Styled.DropdownMenuItemContentWrapper> + </Styled.DropdownMenuCheckboxItem> + ); +} ); +DropdownMenuCheckboxItem.displayName = 'DropdownMenuV2.CheckboxItem'; diff --git a/packages/components/src/dropdown-menu-v2/context.tsx b/packages/components/src/dropdown-menu-v2/context.tsx new file mode 100644 index 00000000000000..c69fb3d30ef76f --- /dev/null +++ b/packages/components/src/dropdown-menu-v2/context.tsx @@ -0,0 +1,14 @@ +/** + * WordPress dependencies + */ +import { createContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { DropdownMenuContext as DropdownMenuContextType } from './types'; + +export const DropdownMenuContext = createContext< + DropdownMenuContextType | undefined +>( undefined ); +DropdownMenuContext.displayName = 'DropdownMenuV2.Context'; diff --git a/packages/components/src/dropdown-menu-v2/group.tsx b/packages/components/src/dropdown-menu-v2/group.tsx new file mode 100644 index 00000000000000..806e22ca6a39a6 --- /dev/null +++ b/packages/components/src/dropdown-menu-v2/group.tsx @@ -0,0 +1,27 @@ +/** + * WordPress dependencies + */ +import { forwardRef, useContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import { DropdownMenuContext } from './context'; +import type { DropdownMenuGroupProps } from './types'; +import * as Styled from './styles'; + +export const DropdownMenuGroup = forwardRef< + HTMLDivElement, + WordPressComponentProps< DropdownMenuGroupProps, 'div', false > +>( function DropdownMenuGroup( props, ref ) { + const dropdownMenuContext = useContext( DropdownMenuContext ); + return ( + <Styled.DropdownMenuGroup + ref={ ref } + { ...props } + store={ dropdownMenuContext?.store } + /> + ); +} ); +DropdownMenuGroup.displayName = 'DropdownMenuV2.Group'; diff --git a/packages/components/src/dropdown-menu-v2/index.tsx b/packages/components/src/dropdown-menu-v2/index.tsx index b6ac9e45e37758..73c0890b6121e6 100644 --- a/packages/components/src/dropdown-menu-v2/index.tsx +++ b/packages/components/src/dropdown-menu-v2/index.tsx @@ -8,8 +8,6 @@ import { useStoreState } from '@ariakit/react'; * WordPress dependencies */ import { - forwardRef, - createContext, useContext, useMemo, cloneElement, @@ -17,165 +15,26 @@ import { useCallback, } from '@wordpress/element'; import { isRTL } from '@wordpress/i18n'; -import { check, chevronRightSmall } from '@wordpress/icons'; -import { SVG, Circle } from '@wordpress/primitives'; +import { chevronRightSmall } from '@wordpress/icons'; /** * Internal dependencies */ import { useContextSystem, contextConnect } from '../context'; import type { WordPressComponentProps } from '../context'; -import Icon from '../icon'; import type { DropdownMenuContext as DropdownMenuContextType, DropdownMenuProps, - DropdownMenuGroupProps, - DropdownMenuItemProps, - DropdownMenuCheckboxItemProps, - DropdownMenuRadioItemProps, - DropdownMenuSeparatorProps, } from './types'; import * as Styled from './styles'; - -export const DropdownMenuContext = createContext< - DropdownMenuContextType | undefined ->( undefined ); - -export const DropdownMenuItem = forwardRef< - HTMLDivElement, - WordPressComponentProps< DropdownMenuItemProps, 'div', false > ->( function DropdownMenuItem( - { prefix, suffix, children, hideOnClick = true, ...props }, - ref -) { - const dropdownMenuContext = useContext( DropdownMenuContext ); - - return ( - <Styled.DropdownMenuItem - ref={ ref } - { ...props } - accessibleWhenDisabled - hideOnClick={ hideOnClick } - store={ dropdownMenuContext?.store } - > - <Styled.ItemPrefixWrapper>{ prefix }</Styled.ItemPrefixWrapper> - - <Styled.DropdownMenuItemContentWrapper> - <Styled.DropdownMenuItemChildrenWrapper> - { children } - </Styled.DropdownMenuItemChildrenWrapper> - - { suffix && ( - <Styled.ItemSuffixWrapper> - { suffix } - </Styled.ItemSuffixWrapper> - ) } - </Styled.DropdownMenuItemContentWrapper> - </Styled.DropdownMenuItem> - ); -} ); - -export const DropdownMenuCheckboxItem = forwardRef< - HTMLDivElement, - WordPressComponentProps< DropdownMenuCheckboxItemProps, 'div', false > ->( function DropdownMenuCheckboxItem( - { suffix, children, hideOnClick = false, ...props }, - ref -) { - const dropdownMenuContext = useContext( DropdownMenuContext ); - - return ( - <Styled.DropdownMenuCheckboxItem - ref={ ref } - { ...props } - accessibleWhenDisabled - hideOnClick={ hideOnClick } - store={ dropdownMenuContext?.store } - > - <Ariakit.MenuItemCheck - store={ dropdownMenuContext?.store } - render={ <Styled.ItemPrefixWrapper /> } - // Override some ariakit inline styles - style={ { width: 'auto', height: 'auto' } } - > - <Icon icon={ check } size={ 24 } /> - </Ariakit.MenuItemCheck> - - <Styled.DropdownMenuItemContentWrapper> - <Styled.DropdownMenuItemChildrenWrapper> - { children } - </Styled.DropdownMenuItemChildrenWrapper> - - { suffix && ( - <Styled.ItemSuffixWrapper> - { suffix } - </Styled.ItemSuffixWrapper> - ) } - </Styled.DropdownMenuItemContentWrapper> - </Styled.DropdownMenuCheckboxItem> - ); -} ); - -const radioCheck = ( - <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> - <Circle cx={ 12 } cy={ 12 } r={ 3 }></Circle> - </SVG> -); - -export const DropdownMenuRadioItem = forwardRef< - HTMLDivElement, - WordPressComponentProps< DropdownMenuRadioItemProps, 'div', false > ->( function DropdownMenuRadioItem( - { suffix, children, hideOnClick = false, ...props }, - ref -) { - const dropdownMenuContext = useContext( DropdownMenuContext ); - - return ( - <Styled.DropdownMenuRadioItem - ref={ ref } - { ...props } - accessibleWhenDisabled - hideOnClick={ hideOnClick } - store={ dropdownMenuContext?.store } - > - <Ariakit.MenuItemCheck - store={ dropdownMenuContext?.store } - render={ <Styled.ItemPrefixWrapper /> } - // Override some ariakit inline styles - style={ { width: 'auto', height: 'auto' } } - > - <Icon icon={ radioCheck } size={ 24 } /> - </Ariakit.MenuItemCheck> - - <Styled.DropdownMenuItemContentWrapper> - <Styled.DropdownMenuItemChildrenWrapper> - { children } - </Styled.DropdownMenuItemChildrenWrapper> - - { suffix && ( - <Styled.ItemSuffixWrapper> - { suffix } - </Styled.ItemSuffixWrapper> - ) } - </Styled.DropdownMenuItemContentWrapper> - </Styled.DropdownMenuRadioItem> - ); -} ); - -export const DropdownMenuGroup = forwardRef< - HTMLDivElement, - WordPressComponentProps< DropdownMenuGroupProps, 'div', false > ->( function DropdownMenuGroup( props, ref ) { - const dropdownMenuContext = useContext( DropdownMenuContext ); - return ( - <Styled.DropdownMenuGroup - ref={ ref } - { ...props } - store={ dropdownMenuContext?.store } - /> - ); -} ); +import { DropdownMenuContext } from './context'; +import { DropdownMenuItem } from './item'; +import { DropdownMenuCheckboxItem } from './checkbox-item'; +import { DropdownMenuRadioItem } from './radio-item'; +import { DropdownMenuGroup } from './group'; +import { DropdownMenuSeparator } from './separator'; +import { DropdownMenuItemLabel } from './item-label'; +import { DropdownMenuItemHelpText } from './item-help-text'; const UnconnectedDropdownMenu = ( props: WordPressComponentProps< DropdownMenuProps, 'div', false >, @@ -337,48 +196,19 @@ const UnconnectedDropdownMenu = ( </> ); }; -export const DropdownMenu = contextConnect( - UnconnectedDropdownMenu, - 'DropdownMenu' -); -export const DropdownMenuSeparator = forwardRef< - HTMLHRElement, - WordPressComponentProps< DropdownMenuSeparatorProps, 'hr', false > ->( function DropdownMenuSeparator( props, ref ) { - const dropdownMenuContext = useContext( DropdownMenuContext ); - return ( - <Styled.DropdownMenuSeparator - ref={ ref } - { ...props } - store={ dropdownMenuContext?.store } - variant={ dropdownMenuContext?.variant } - /> - ); -} ); - -export const DropdownMenuItemLabel = forwardRef< - HTMLSpanElement, - WordPressComponentProps< { children: React.ReactNode }, 'span', true > ->( function DropdownMenuItemLabel( props, ref ) { - return ( - <Styled.DropdownMenuItemLabel - numberOfLines={ 1 } - ref={ ref } - { ...props } - /> - ); -} ); +export const DropdownMenuV2 = Object.assign( + contextConnect( UnconnectedDropdownMenu, 'DropdownMenu' ), + { + Context: DropdownMenuContext, + Item: DropdownMenuItem, + RadioItem: DropdownMenuRadioItem, + CheckboxItem: DropdownMenuCheckboxItem, + Group: DropdownMenuGroup, + Separator: DropdownMenuSeparator, + ItemLabel: DropdownMenuItemLabel, + ItemHelpText: DropdownMenuItemHelpText, + } +); -export const DropdownMenuItemHelpText = forwardRef< - HTMLSpanElement, - WordPressComponentProps< { children: React.ReactNode }, 'span', true > ->( function DropdownMenuItemHelpText( props, ref ) { - return ( - <Styled.DropdownMenuItemHelpText - numberOfLines={ 2 } - ref={ ref } - { ...props } - /> - ); -} ); +export default DropdownMenuV2; diff --git a/packages/components/src/dropdown-menu-v2/item-help-text.tsx b/packages/components/src/dropdown-menu-v2/item-help-text.tsx new file mode 100644 index 00000000000000..71240db1cacfb6 --- /dev/null +++ b/packages/components/src/dropdown-menu-v2/item-help-text.tsx @@ -0,0 +1,24 @@ +/** + * WordPress dependencies + */ +import { forwardRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import * as Styled from './styles'; + +export const DropdownMenuItemHelpText = forwardRef< + HTMLSpanElement, + WordPressComponentProps< { children: React.ReactNode }, 'span', true > +>( function DropdownMenuItemHelpText( props, ref ) { + return ( + <Styled.DropdownMenuItemHelpText + numberOfLines={ 2 } + ref={ ref } + { ...props } + /> + ); +} ); +DropdownMenuItemHelpText.displayName = 'DropdownMenuV2.ItemHelpText'; diff --git a/packages/components/src/dropdown-menu-v2/item-label.tsx b/packages/components/src/dropdown-menu-v2/item-label.tsx new file mode 100644 index 00000000000000..1ba03b59ace5cd --- /dev/null +++ b/packages/components/src/dropdown-menu-v2/item-label.tsx @@ -0,0 +1,24 @@ +/** + * WordPress dependencies + */ +import { forwardRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import * as Styled from './styles'; + +export const DropdownMenuItemLabel = forwardRef< + HTMLSpanElement, + WordPressComponentProps< { children: React.ReactNode }, 'span', true > +>( function DropdownMenuItemLabel( props, ref ) { + return ( + <Styled.DropdownMenuItemLabel + numberOfLines={ 1 } + ref={ ref } + { ...props } + /> + ); +} ); +DropdownMenuItemLabel.displayName = 'DropdownMenuV2.ItemLabel'; diff --git a/packages/components/src/dropdown-menu-v2/item.tsx b/packages/components/src/dropdown-menu-v2/item.tsx new file mode 100644 index 00000000000000..35cd747b47c259 --- /dev/null +++ b/packages/components/src/dropdown-menu-v2/item.tsx @@ -0,0 +1,47 @@ +/** + * WordPress dependencies + */ +import { forwardRef, useContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import type { DropdownMenuItemProps } from './types'; +import * as Styled from './styles'; +import { DropdownMenuContext } from './context'; + +export const DropdownMenuItem = forwardRef< + HTMLDivElement, + WordPressComponentProps< DropdownMenuItemProps, 'div', false > +>( function DropdownMenuItem( + { prefix, suffix, children, hideOnClick = true, ...props }, + ref +) { + const dropdownMenuContext = useContext( DropdownMenuContext ); + + return ( + <Styled.DropdownMenuItem + ref={ ref } + { ...props } + accessibleWhenDisabled + hideOnClick={ hideOnClick } + store={ dropdownMenuContext?.store } + > + <Styled.ItemPrefixWrapper>{ prefix }</Styled.ItemPrefixWrapper> + + <Styled.DropdownMenuItemContentWrapper> + <Styled.DropdownMenuItemChildrenWrapper> + { children } + </Styled.DropdownMenuItemChildrenWrapper> + + { suffix && ( + <Styled.ItemSuffixWrapper> + { suffix } + </Styled.ItemSuffixWrapper> + ) } + </Styled.DropdownMenuItemContentWrapper> + </Styled.DropdownMenuItem> + ); +} ); +DropdownMenuItem.displayName = 'DropdownMenuV2.Item'; diff --git a/packages/components/src/dropdown-menu-v2/radio-item.tsx b/packages/components/src/dropdown-menu-v2/radio-item.tsx new file mode 100644 index 00000000000000..6cfe85e149877c --- /dev/null +++ b/packages/components/src/dropdown-menu-v2/radio-item.tsx @@ -0,0 +1,67 @@ +/** + * External dependencies + */ +import * as Ariakit from '@ariakit/react'; + +/** + * WordPress dependencies + */ +import { forwardRef, useContext } from '@wordpress/element'; +import { Icon } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import { DropdownMenuContext } from './context'; +import type { DropdownMenuRadioItemProps } from './types'; +import * as Styled from './styles'; +import { SVG, Circle } from '@wordpress/primitives'; + +const radioCheck = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Circle cx={ 12 } cy={ 12 } r={ 3 }></Circle> + </SVG> +); + +export const DropdownMenuRadioItem = forwardRef< + HTMLDivElement, + WordPressComponentProps< DropdownMenuRadioItemProps, 'div', false > +>( function DropdownMenuRadioItem( + { suffix, children, hideOnClick = false, ...props }, + ref +) { + const dropdownMenuContext = useContext( DropdownMenuContext ); + + return ( + <Styled.DropdownMenuRadioItem + ref={ ref } + { ...props } + accessibleWhenDisabled + hideOnClick={ hideOnClick } + store={ dropdownMenuContext?.store } + > + <Ariakit.MenuItemCheck + store={ dropdownMenuContext?.store } + render={ <Styled.ItemPrefixWrapper /> } + // Override some ariakit inline styles + style={ { width: 'auto', height: 'auto' } } + > + <Icon icon={ radioCheck } size={ 24 } /> + </Ariakit.MenuItemCheck> + + <Styled.DropdownMenuItemContentWrapper> + <Styled.DropdownMenuItemChildrenWrapper> + { children } + </Styled.DropdownMenuItemChildrenWrapper> + + { suffix && ( + <Styled.ItemSuffixWrapper> + { suffix } + </Styled.ItemSuffixWrapper> + ) } + </Styled.DropdownMenuItemContentWrapper> + </Styled.DropdownMenuRadioItem> + ); +} ); +DropdownMenuRadioItem.displayName = 'DropdownMenuV2.RadioItem'; diff --git a/packages/components/src/dropdown-menu-v2/separator.tsx b/packages/components/src/dropdown-menu-v2/separator.tsx new file mode 100644 index 00000000000000..9bd551ea068ea5 --- /dev/null +++ b/packages/components/src/dropdown-menu-v2/separator.tsx @@ -0,0 +1,28 @@ +/** + * WordPress dependencies + */ +import { forwardRef, useContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import { DropdownMenuContext } from './context'; +import type { DropdownMenuSeparatorProps } from './types'; +import * as Styled from './styles'; + +export const DropdownMenuSeparator = forwardRef< + HTMLHRElement, + WordPressComponentProps< DropdownMenuSeparatorProps, 'hr', false > +>( function DropdownMenuSeparator( props, ref ) { + const dropdownMenuContext = useContext( DropdownMenuContext ); + return ( + <Styled.DropdownMenuSeparator + ref={ ref } + { ...props } + store={ dropdownMenuContext?.store } + variant={ dropdownMenuContext?.variant } + /> + ); +} ); +DropdownMenuSeparator.displayName = 'DropdownMenuV2.Separator'; diff --git a/packages/components/src/dropdown-menu-v2/stories/index.story.tsx b/packages/components/src/dropdown-menu-v2/stories/index.story.tsx index a2fc476cd8ac07..fd14bb68b1d6ad 100644 --- a/packages/components/src/dropdown-menu-v2/stories/index.story.tsx +++ b/packages/components/src/dropdown-menu-v2/stories/index.story.tsx @@ -14,43 +14,33 @@ import { useState, useMemo, useContext } from '@wordpress/element'; * Internal dependencies */ import { useCx } from '../../utils'; -import { - DropdownMenu, - DropdownMenuItem, - DropdownMenuCheckboxItem, - DropdownMenuGroup, - DropdownMenuSeparator, - DropdownMenuContext, - DropdownMenuRadioItem, - DropdownMenuItemLabel, - DropdownMenuItemHelpText, -} from '..'; +import DropdownMenuV2 from '..'; import Icon from '../../icon'; import Button from '../../button'; import Modal from '../../modal'; import { createSlotFill, Provider as SlotFillProvider } from '../../slot-fill'; import { ContextSystemProvider } from '../../context'; -const meta: Meta< typeof DropdownMenu > = { +const meta: Meta< typeof DropdownMenuV2 > = { title: 'Components (Experimental)/DropdownMenu V2', - component: DropdownMenu, + component: DropdownMenuV2, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - DropdownMenuItem, + Item: DropdownMenuV2.Item, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - DropdownMenuCheckboxItem, + CheckboxItem: DropdownMenuV2.CheckboxItem, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - DropdownMenuGroup, + Group: DropdownMenuV2.Group, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - DropdownMenuSeparator, + Separator: DropdownMenuV2.Separator, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - DropdownMenuContext, + Context: DropdownMenuV2.Context, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - DropdownMenuRadioItem, + RadioItem: DropdownMenuV2.RadioItem, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - DropdownMenuItemLabel, + ItemLabel: DropdownMenuV2.ItemLabel, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - DropdownMenuItemHelpText, + ItemHelpText: DropdownMenuV2.ItemHelpText, }, argTypes: { children: { control: { type: null } }, @@ -68,51 +58,51 @@ const meta: Meta< typeof DropdownMenu > = { }; export default meta; -export const Default: StoryFn< typeof DropdownMenu > = ( props ) => ( - <DropdownMenu { ...props }> - <DropdownMenuItem> - <DropdownMenuItemLabel>Label</DropdownMenuItemLabel> - </DropdownMenuItem> - <DropdownMenuItem> - <DropdownMenuItemLabel>Label</DropdownMenuItemLabel> - <DropdownMenuItemHelpText>Help text</DropdownMenuItemHelpText> - </DropdownMenuItem> - <DropdownMenuItem> - <DropdownMenuItemLabel>Label</DropdownMenuItemLabel> - <DropdownMenuItemHelpText> +export const Default: StoryFn< typeof DropdownMenuV2 > = ( props ) => ( + <DropdownMenuV2 { ...props }> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel>Label</DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel>Label</DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText>Help text</DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.Item> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel>Label</DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> The menu item help text is automatically truncated when there are more than two lines of text - </DropdownMenuItemHelpText> - </DropdownMenuItem> - <DropdownMenuItem hideOnClick={ false }> - <DropdownMenuItemLabel>Label</DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.Item> + <DropdownMenuV2.Item hideOnClick={ false }> + <DropdownMenuV2.ItemLabel>Label</DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> This item doesn't close the menu on click - </DropdownMenuItemHelpText> - </DropdownMenuItem> - <DropdownMenuItem disabled>Disabled item</DropdownMenuItem> - <DropdownMenuSeparator /> - <DropdownMenuGroup> - <DropdownMenuItem + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.Item> + <DropdownMenuV2.Item disabled>Disabled item</DropdownMenuV2.Item> + <DropdownMenuV2.Separator /> + <DropdownMenuV2.Group> + <DropdownMenuV2.Item prefix={ <Icon icon={ customLink } size={ 24 } /> } > - <DropdownMenuItemLabel>With prefix</DropdownMenuItemLabel> - </DropdownMenuItem> - <DropdownMenuItem suffix="⌘S">With suffix</DropdownMenuItem> - <DropdownMenuItem + <DropdownMenuV2.ItemLabel>With prefix</DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + <DropdownMenuV2.Item suffix="⌘S">With suffix</DropdownMenuV2.Item> + <DropdownMenuV2.Item disabled prefix={ <Icon icon={ formatCapitalize } size={ 24 } /> } suffix="⌥⌘T" > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> Disabled with prefix and suffix - </DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> And help text - </DropdownMenuItemHelpText> - </DropdownMenuItem> - </DropdownMenuGroup> - </DropdownMenu> + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.Item> + </DropdownMenuV2.Group> + </DropdownMenuV2> ); Default.args = { trigger: ( @@ -122,48 +112,56 @@ Default.args = { ), }; -export const WithSubmenu: StoryFn< typeof DropdownMenu > = ( props ) => ( - <DropdownMenu { ...props }> - <DropdownMenuItem>Level 1 item</DropdownMenuItem> - <DropdownMenu +export const WithSubmenu: StoryFn< typeof DropdownMenuV2 > = ( props ) => ( + <DropdownMenuV2 { ...props }> + <DropdownMenuV2.Item>Level 1 item</DropdownMenuV2.Item> + <DropdownMenuV2 trigger={ - <DropdownMenuItem suffix="Suffix"> - <DropdownMenuItemLabel> + <DropdownMenuV2.Item suffix="Suffix"> + <DropdownMenuV2.ItemLabel> Submenu trigger item with a long label - </DropdownMenuItemLabel> - </DropdownMenuItem> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> } > - <DropdownMenuItem> - <DropdownMenuItemLabel>Level 2 item</DropdownMenuItemLabel> - </DropdownMenuItem> - <DropdownMenuItem> - <DropdownMenuItemLabel>Level 2 item</DropdownMenuItemLabel> - </DropdownMenuItem> - <DropdownMenu + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> + Level 2 item + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> + Level 2 item + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + <DropdownMenuV2 trigger={ - <DropdownMenuItem> - <DropdownMenuItemLabel> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> Submenu trigger - </DropdownMenuItemLabel> - </DropdownMenuItem> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> } > - <DropdownMenuItem> - <DropdownMenuItemLabel>Level 3 item</DropdownMenuItemLabel> - </DropdownMenuItem> - <DropdownMenuItem> - <DropdownMenuItemLabel>Level 3 item</DropdownMenuItemLabel> - </DropdownMenuItem> - </DropdownMenu> - </DropdownMenu> - </DropdownMenu> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> + Level 3 item + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> + Level 3 item + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + </DropdownMenuV2> + </DropdownMenuV2> + </DropdownMenuV2> ); WithSubmenu.args = { ...Default.args, }; -export const WithCheckboxes: StoryFn< typeof DropdownMenu > = ( props ) => { +export const WithCheckboxes: StoryFn< typeof DropdownMenuV2 > = ( props ) => { const [ isAChecked, setAChecked ] = useState( false ); const [ isBChecked, setBChecked ] = useState( true ); const [ multipleCheckboxesValue, setMultipleCheckboxesValue ] = useState< @@ -171,7 +169,7 @@ export const WithCheckboxes: StoryFn< typeof DropdownMenu > = ( props ) => { >( [ 'b' ] ); const onMultipleCheckboxesCheckedChange: React.ComponentProps< - typeof DropdownMenuCheckboxItem + typeof DropdownMenuV2.CheckboxItem >[ 'onChange' ] = ( e ) => { setMultipleCheckboxesValue( ( prevValues ) => { if ( prevValues.includes( e.target.value ) ) { @@ -182,176 +180,184 @@ export const WithCheckboxes: StoryFn< typeof DropdownMenu > = ( props ) => { }; return ( - <DropdownMenu { ...props }> - <DropdownMenuGroup> - <DropdownMenuCheckboxItem + <DropdownMenuV2 { ...props }> + <DropdownMenuV2.Group> + <DropdownMenuV2.CheckboxItem name="checkbox-individual-uncontrolled-a" value="a" suffix="⌥⌘T" > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> Checkbox item A - </DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> Uncontrolled - </DropdownMenuItemHelpText> - </DropdownMenuCheckboxItem> - <DropdownMenuCheckboxItem + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.CheckboxItem> + <DropdownMenuV2.CheckboxItem name="checkbox-individual-uncontrolled-b" value="b" defaultChecked > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> Checkbox item B - </DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> Uncontrolled, initially checked - </DropdownMenuItemHelpText> - </DropdownMenuCheckboxItem> - </DropdownMenuGroup> - <DropdownMenuSeparator /> - <DropdownMenuGroup> - <DropdownMenuCheckboxItem + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.CheckboxItem> + </DropdownMenuV2.Group> + <DropdownMenuV2.Separator /> + <DropdownMenuV2.Group> + <DropdownMenuV2.CheckboxItem name="checkbox-individual-controlled-a" value="a" checked={ isAChecked } onChange={ ( e ) => setAChecked( e.target.checked ) } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> Checkbox item A - </DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> Controlled - </DropdownMenuItemHelpText> - </DropdownMenuCheckboxItem> - <DropdownMenuCheckboxItem + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.CheckboxItem> + <DropdownMenuV2.CheckboxItem name="checkbox-individual-controlled-b" value="b" checked={ isBChecked } onChange={ ( e ) => setBChecked( e.target.checked ) } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> Checkbox item B - </DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> Controlled, initially checked - </DropdownMenuItemHelpText> - </DropdownMenuCheckboxItem> - </DropdownMenuGroup> - <DropdownMenuSeparator /> - <DropdownMenuGroup> - <DropdownMenuCheckboxItem + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.CheckboxItem> + </DropdownMenuV2.Group> + <DropdownMenuV2.Separator /> + <DropdownMenuV2.Group> + <DropdownMenuV2.CheckboxItem name="checkbox-multiple-uncontrolled" value="a" > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> Checkbox item A - </DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> Uncontrolled, multiple selection - </DropdownMenuItemHelpText> - </DropdownMenuCheckboxItem> - <DropdownMenuCheckboxItem + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.CheckboxItem> + <DropdownMenuV2.CheckboxItem name="checkbox-multiple-uncontrolled" value="b" defaultChecked > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> Checkbox item B - </DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> Uncontrolled, multiple selection, initially checked - </DropdownMenuItemHelpText> - </DropdownMenuCheckboxItem> - </DropdownMenuGroup> - <DropdownMenuSeparator /> - <DropdownMenuGroup> - <DropdownMenuCheckboxItem + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.CheckboxItem> + </DropdownMenuV2.Group> + <DropdownMenuV2.Separator /> + <DropdownMenuV2.Group> + <DropdownMenuV2.CheckboxItem name="checkbox-multiple-controlled" value="a" checked={ multipleCheckboxesValue.includes( 'a' ) } onChange={ onMultipleCheckboxesCheckedChange } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> Checkbox item A - </DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> Controlled, multiple selection - </DropdownMenuItemHelpText> - </DropdownMenuCheckboxItem> - <DropdownMenuCheckboxItem + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.CheckboxItem> + <DropdownMenuV2.CheckboxItem name="checkbox-multiple-controlled" value="b" checked={ multipleCheckboxesValue.includes( 'b' ) } onChange={ onMultipleCheckboxesCheckedChange } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> Checkbox item B - </DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> Controlled, multiple selection, initially checked - </DropdownMenuItemHelpText> - </DropdownMenuCheckboxItem> - </DropdownMenuGroup> - </DropdownMenu> + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.CheckboxItem> + </DropdownMenuV2.Group> + </DropdownMenuV2> ); }; WithCheckboxes.args = { ...Default.args, }; -export const WithRadios: StoryFn< typeof DropdownMenu > = ( props ) => { +export const WithRadios: StoryFn< typeof DropdownMenuV2 > = ( props ) => { const [ radioValue, setRadioValue ] = useState( 'two' ); const onRadioChange: React.ComponentProps< - typeof DropdownMenuRadioItem + typeof DropdownMenuV2.RadioItem >[ 'onChange' ] = ( e ) => setRadioValue( e.target.value ); return ( - <DropdownMenu { ...props }> - <DropdownMenuGroup> - <DropdownMenuRadioItem name="radio-uncontrolled" value="one"> - <DropdownMenuItemLabel>Radio item 1</DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + <DropdownMenuV2 { ...props }> + <DropdownMenuV2.Group> + <DropdownMenuV2.RadioItem name="radio-uncontrolled" value="one"> + <DropdownMenuV2.ItemLabel> + Radio item 1 + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> Uncontrolled - </DropdownMenuItemHelpText> - </DropdownMenuRadioItem> - <DropdownMenuRadioItem + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.RadioItem> + <DropdownMenuV2.RadioItem name="radio-uncontrolled" value="two" defaultChecked > - <DropdownMenuItemLabel>Radio item 2</DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + <DropdownMenuV2.ItemLabel> + Radio item 2 + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> Uncontrolled, initially checked - </DropdownMenuItemHelpText> - </DropdownMenuRadioItem> - </DropdownMenuGroup> - <DropdownMenuSeparator /> - <DropdownMenuGroup> - <DropdownMenuRadioItem + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.RadioItem> + </DropdownMenuV2.Group> + <DropdownMenuV2.Separator /> + <DropdownMenuV2.Group> + <DropdownMenuV2.RadioItem name="radio-controlled" value="one" checked={ radioValue === 'one' } onChange={ onRadioChange } > - <DropdownMenuItemLabel>Radio item 1</DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + <DropdownMenuV2.ItemLabel> + Radio item 1 + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> Controlled - </DropdownMenuItemHelpText> - </DropdownMenuRadioItem> - <DropdownMenuRadioItem + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.RadioItem> + <DropdownMenuV2.RadioItem name="radio-controlled" value="two" checked={ radioValue === 'two' } onChange={ onRadioChange } > - <DropdownMenuItemLabel>Radio item 2</DropdownMenuItemLabel> - <DropdownMenuItemHelpText> + <DropdownMenuV2.ItemLabel> + Radio item 2 + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> Controlled, initially checked - </DropdownMenuItemHelpText> - </DropdownMenuRadioItem> - </DropdownMenuGroup> - </DropdownMenu> + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.RadioItem> + </DropdownMenuV2.Group> + </DropdownMenuV2> ); }; WithRadios.args = { @@ -365,7 +371,7 @@ const modalOnTopOfDropdown = css` `; // For more examples with `Modal`, check https://ariakit.org/examples/menu-wordpress-modal -export const WithModals: StoryFn< typeof DropdownMenu > = ( props ) => { +export const WithModals: StoryFn< typeof DropdownMenuV2 > = ( props ) => { const [ isOuterModalOpen, setOuterModalOpen ] = useState( false ); const [ isInnerModalOpen, setInnerModalOpen ] = useState( false ); @@ -374,23 +380,23 @@ export const WithModals: StoryFn< typeof DropdownMenu > = ( props ) => { return ( <> - <DropdownMenu { ...props }> - <DropdownMenuItem + <DropdownMenuV2 { ...props }> + <DropdownMenuV2.Item onClick={ () => setOuterModalOpen( true ) } hideOnClick={ false } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> Open outer modal - </DropdownMenuItemLabel> - </DropdownMenuItem> - <DropdownMenuItem + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + <DropdownMenuV2.Item onClick={ () => setInnerModalOpen( true ) } hideOnClick={ false } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> Open inner modal - </DropdownMenuItemLabel> - </DropdownMenuItem> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> { isInnerModalOpen && ( <Modal onRequestClose={ () => setInnerModalOpen( false ) } @@ -402,7 +408,7 @@ export const WithModals: StoryFn< typeof DropdownMenu > = ( props ) => { </button> </Modal> ) } - </DropdownMenu> + </DropdownMenuV2> { isOuterModalOpen && ( <Modal onRequestClose={ () => setOuterModalOpen( false ) } @@ -424,14 +430,14 @@ WithModals.args = { const ExampleSlotFill = createSlotFill( 'Example' ); const Slot = () => { - const dropdownMenuContext = useContext( DropdownMenuContext ); + const dropdownMenuContext = useContext( DropdownMenuV2.Context ); // Forwarding the content of the slot so that it can be used by the fill const fillProps = useMemo( () => ( { forwardedContext: [ [ - DropdownMenuContext.Provider, + DropdownMenuV2.Context.Provider, { value: dropdownMenuContext }, ], ], @@ -472,37 +478,37 @@ const Fill = ( { children }: { children: React.ReactNode } ) => { ); }; -export const WithSlotFill: StoryFn< typeof DropdownMenu > = ( props ) => { +export const WithSlotFill: StoryFn< typeof DropdownMenuV2 > = ( props ) => { return ( <SlotFillProvider> - <DropdownMenu { ...props }> - <DropdownMenuItem> - <DropdownMenuItemLabel>Item</DropdownMenuItemLabel> - </DropdownMenuItem> + <DropdownMenuV2 { ...props }> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel>Item</DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> <Slot /> - </DropdownMenu> + </DropdownMenuV2> <Fill> - <DropdownMenuItem> - <DropdownMenuItemLabel> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> Item from fill - </DropdownMenuItemLabel> - </DropdownMenuItem> - <DropdownMenu + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + <DropdownMenuV2 trigger={ - <DropdownMenuItem> - <DropdownMenuItemLabel> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> Submenu from fill - </DropdownMenuItemLabel> - </DropdownMenuItem> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> } > - <DropdownMenuItem> - <DropdownMenuItemLabel> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> Submenu item from fill - </DropdownMenuItemLabel> - </DropdownMenuItem> - </DropdownMenu> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + </DropdownMenuV2> </Fill> </SlotFillProvider> ); @@ -512,42 +518,48 @@ WithSlotFill.args = { }; const toolbarVariantContextValue = { - DropdownMenu: { + DropdownMenuV2: { variant: 'toolbar', }, }; -export const ToolbarVariant: StoryFn< typeof DropdownMenu > = ( props ) => ( +export const ToolbarVariant: StoryFn< typeof DropdownMenuV2 > = ( props ) => ( // TODO: add toolbar <ContextSystemProvider value={ toolbarVariantContextValue }> - <DropdownMenu { ...props }> - <DropdownMenuItem> - <DropdownMenuItemLabel>Level 1 item</DropdownMenuItemLabel> - </DropdownMenuItem> - <DropdownMenuItem> - <DropdownMenuItemLabel>Level 1 item</DropdownMenuItemLabel> - </DropdownMenuItem> - <DropdownMenuSeparator /> - <DropdownMenu + <DropdownMenuV2 { ...props }> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> + Level 1 item + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> + Level 1 item + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + <DropdownMenuV2.Separator /> + <DropdownMenuV2 trigger={ - <DropdownMenuItem> - <DropdownMenuItemLabel> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> Submenu trigger - </DropdownMenuItemLabel> - </DropdownMenuItem> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> } > - <DropdownMenuItem> - <DropdownMenuItemLabel>Level 2 item</DropdownMenuItemLabel> - </DropdownMenuItem> - </DropdownMenu> - </DropdownMenu> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> + Level 2 item + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + </DropdownMenuV2> + </DropdownMenuV2> </ContextSystemProvider> ); ToolbarVariant.args = { ...Default.args, }; -export const InsideModal: StoryFn< typeof DropdownMenu > = ( props ) => { +export const InsideModal: StoryFn< typeof DropdownMenuV2 > = ( props ) => { const [ isModalOpen, setModalOpen ] = useState( false ); return ( <> @@ -560,34 +572,34 @@ export const InsideModal: StoryFn< typeof DropdownMenu > = ( props ) => { </Button> { isModalOpen && ( <Modal onRequestClose={ () => setModalOpen( false ) }> - <DropdownMenu { ...props }> - <DropdownMenuItem> - <DropdownMenuItemLabel> + <DropdownMenuV2 { ...props }> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> Level 1 item - </DropdownMenuItemLabel> - </DropdownMenuItem> - <DropdownMenuItem> - <DropdownMenuItemLabel> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> Level 1 item - </DropdownMenuItemLabel> - </DropdownMenuItem> - <DropdownMenuSeparator /> - <DropdownMenu + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + <DropdownMenuV2.Separator /> + <DropdownMenuV2 trigger={ - <DropdownMenuItem> - <DropdownMenuItemLabel> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> Submenu trigger - </DropdownMenuItemLabel> - </DropdownMenuItem> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> } > - <DropdownMenuItem> - <DropdownMenuItemLabel> + <DropdownMenuV2.Item> + <DropdownMenuV2.ItemLabel> Level 2 item - </DropdownMenuItemLabel> - </DropdownMenuItem> - </DropdownMenu> - </DropdownMenu> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + </DropdownMenuV2> + </DropdownMenuV2> <Button onClick={ () => setModalOpen( false ) }> Close modal </Button> diff --git a/packages/components/src/dropdown-menu-v2/test/index.tsx b/packages/components/src/dropdown-menu-v2/test/index.tsx index 5457f5e73e23c3..cb674f27edaacf 100644 --- a/packages/components/src/dropdown-menu-v2/test/index.tsx +++ b/packages/components/src/dropdown-menu-v2/test/index.tsx @@ -12,14 +12,7 @@ import { useState } from '@wordpress/element'; /** * Internal dependencies */ -import { - DropdownMenu, - DropdownMenuCheckboxItem, - DropdownMenuItem, - DropdownMenuRadioItem, - DropdownMenuSeparator, - DropdownMenuGroup, -} from '..'; +import { DropdownMenuV2 } from '..'; const delay = ( delayInMs: number ) => { return new Promise( ( resolve ) => setTimeout( resolve, delayInMs ) ); @@ -29,18 +22,24 @@ describe( 'DropdownMenu', () => { // See https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/ it( 'should follow the WAI-ARIA spec', async () => { render( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuItem>Dropdown menu item</DropdownMenuItem> - <DropdownMenuSeparator /> - <DropdownMenu + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.Item>Dropdown menu item</DropdownMenuV2.Item> + <DropdownMenuV2.Separator /> + <DropdownMenuV2 trigger={ - <DropdownMenuItem>Dropdown submenu</DropdownMenuItem> + <DropdownMenuV2.Item> + Dropdown submenu + </DropdownMenuV2.Item> } > - <DropdownMenuItem>Dropdown submenu item 1</DropdownMenuItem> - <DropdownMenuItem>Dropdown submenu item 2</DropdownMenuItem> - </DropdownMenu> - </DropdownMenu> + <DropdownMenuV2.Item> + Dropdown submenu item 1 + </DropdownMenuV2.Item> + <DropdownMenuV2.Item> + Dropdown submenu item 2 + </DropdownMenuV2.Item> + </DropdownMenuV2> + </DropdownMenuV2> ); const toggleButton = screen.getByRole( 'button', { @@ -95,9 +94,11 @@ describe( 'DropdownMenu', () => { describe( 'pointer and keyboard interactions', () => { it( 'should open and focus the menu when clicking the trigger', async () => { render( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuItem>Dropdown menu item</DropdownMenuItem> - </DropdownMenu> + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.Item> + Dropdown menu item + </DropdownMenuV2.Item> + </DropdownMenuV2> ); const toggleButton = screen.getByRole( 'button', { @@ -116,11 +117,13 @@ describe( 'DropdownMenu', () => { it( 'should open and focus the first item when pressing the arrow down key on the trigger', async () => { render( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuItem disabled>First item</DropdownMenuItem> - <DropdownMenuItem>Second item</DropdownMenuItem> - <DropdownMenuItem>Third item</DropdownMenuItem> - </DropdownMenu> + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.Item disabled> + First item + </DropdownMenuV2.Item> + <DropdownMenuV2.Item>Second item</DropdownMenuV2.Item> + <DropdownMenuV2.Item>Third item</DropdownMenuV2.Item> + </DropdownMenuV2> ); const toggleButton = screen.getByRole( 'button', { @@ -146,11 +149,13 @@ describe( 'DropdownMenu', () => { it( 'should open and focus the first item when pressing the space key on the trigger', async () => { render( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuItem disabled>First item</DropdownMenuItem> - <DropdownMenuItem>Second item</DropdownMenuItem> - <DropdownMenuItem>Third item</DropdownMenuItem> - </DropdownMenu> + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.Item disabled> + First item + </DropdownMenuV2.Item> + <DropdownMenuV2.Item>Second item</DropdownMenuV2.Item> + <DropdownMenuV2.Item>Third item</DropdownMenuV2.Item> + </DropdownMenuV2> ); const toggleButton = screen.getByRole( 'button', { @@ -176,9 +181,11 @@ describe( 'DropdownMenu', () => { it( 'should close when pressing the escape key', async () => { render( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuItem>Dropdown menu item</DropdownMenuItem> - </DropdownMenu> + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.Item> + Dropdown menu item + </DropdownMenuV2.Item> + </DropdownMenuV2> ); const trigger = screen.getByRole( 'button', { @@ -205,12 +212,14 @@ describe( 'DropdownMenu', () => { it( 'should close when clicking outside of the content', async () => { render( - <DropdownMenu + <DropdownMenuV2 defaultOpen trigger={ <button>Open dropdown</button> } > - <DropdownMenuItem>Dropdown menu item</DropdownMenuItem> - </DropdownMenu> + <DropdownMenuV2.Item> + Dropdown menu item + </DropdownMenuV2.Item> + </DropdownMenuV2> ); expect( screen.getByRole( 'menu' ) ).toBeInTheDocument(); @@ -223,12 +232,14 @@ describe( 'DropdownMenu', () => { it( 'should close when clicking on a menu item', async () => { render( - <DropdownMenu + <DropdownMenuV2 defaultOpen trigger={ <button>Open dropdown</button> } > - <DropdownMenuItem>Dropdown menu item</DropdownMenuItem> - </DropdownMenu> + <DropdownMenuV2.Item> + Dropdown menu item + </DropdownMenuV2.Item> + </DropdownMenuV2> ); expect( screen.getByRole( 'menu' ) ).toBeInTheDocument(); @@ -241,14 +252,14 @@ describe( 'DropdownMenu', () => { it( 'should not close when clicking on a menu item when the `hideOnClick` prop is set to `false`', async () => { render( - <DropdownMenu + <DropdownMenuV2 defaultOpen trigger={ <button>Open dropdown</button> } > - <DropdownMenuItem hideOnClick={ false }> + <DropdownMenuV2.Item hideOnClick={ false }> Dropdown menu item - </DropdownMenuItem> - </DropdownMenu> + </DropdownMenuV2.Item> + </DropdownMenuV2> ); expect( screen.getByRole( 'menu' ) ).toBeVisible(); @@ -261,14 +272,14 @@ describe( 'DropdownMenu', () => { it( 'should not close when clicking on a disabled menu item', async () => { render( - <DropdownMenu + <DropdownMenuV2 defaultOpen trigger={ <button>Open dropdown</button> } > - <DropdownMenuItem disabled> + <DropdownMenuV2.Item disabled> Dropdown menu item - </DropdownMenuItem> - </DropdownMenu> + </DropdownMenuV2.Item> + </DropdownMenuV2> ); expect( screen.getByRole( 'menu' ) ).toBeInTheDocument(); @@ -281,28 +292,34 @@ describe( 'DropdownMenu', () => { it( 'should reveal submenu content when hovering over the submenu trigger', async () => { render( - <DropdownMenu + <DropdownMenuV2 defaultOpen trigger={ <button>Open dropdown</button> } > - <DropdownMenuItem>Dropdown menu item 1</DropdownMenuItem> - <DropdownMenuItem>Dropdown menu item 2</DropdownMenuItem> - <DropdownMenu + <DropdownMenuV2.Item> + Dropdown menu item 1 + </DropdownMenuV2.Item> + <DropdownMenuV2.Item> + Dropdown menu item 2 + </DropdownMenuV2.Item> + <DropdownMenuV2 trigger={ - <DropdownMenuItem> + <DropdownMenuV2.Item> Dropdown submenu - </DropdownMenuItem> + </DropdownMenuV2.Item> } > - <DropdownMenuItem> + <DropdownMenuV2.Item> Dropdown submenu item 1 - </DropdownMenuItem> - <DropdownMenuItem> + </DropdownMenuV2.Item> + <DropdownMenuV2.Item> Dropdown submenu item 2 - </DropdownMenuItem> - </DropdownMenu> - <DropdownMenuItem>Dropdown menu item 3</DropdownMenuItem> - </DropdownMenu> + </DropdownMenuV2.Item> + </DropdownMenuV2> + <DropdownMenuV2.Item> + Dropdown menu item 3 + </DropdownMenuV2.Item> + </DropdownMenuV2> ); // Before hover, submenu items are not rendered @@ -326,28 +343,34 @@ describe( 'DropdownMenu', () => { it( 'should navigate menu items and subitems using the arrow, spacebar and enter keys', async () => { render( - <DropdownMenu + <DropdownMenuV2 defaultOpen trigger={ <button>Open dropdown</button> } > - <DropdownMenuItem>Dropdown menu item 1</DropdownMenuItem> - <DropdownMenuItem>Dropdown menu item 2</DropdownMenuItem> - <DropdownMenu + <DropdownMenuV2.Item> + Dropdown menu item 1 + </DropdownMenuV2.Item> + <DropdownMenuV2.Item> + Dropdown menu item 2 + </DropdownMenuV2.Item> + <DropdownMenuV2 trigger={ - <DropdownMenuItem> + <DropdownMenuV2.Item> Dropdown submenu - </DropdownMenuItem> + </DropdownMenuV2.Item> } > - <DropdownMenuItem> + <DropdownMenuV2.Item> Dropdown submenu item 1 - </DropdownMenuItem> - <DropdownMenuItem> + </DropdownMenuV2.Item> + <DropdownMenuV2.Item> Dropdown submenu item 2 - </DropdownMenuItem> - </DropdownMenu> - <DropdownMenuItem>Dropdown menu item 3</DropdownMenuItem> - </DropdownMenu> + </DropdownMenuV2.Item> + </DropdownMenuV2> + <DropdownMenuV2.Item> + Dropdown menu item 3 + </DropdownMenuV2.Item> + </DropdownMenuV2> ); // The menu is focused automatically when `defaultOpen` is set. @@ -450,32 +473,32 @@ describe( 'DropdownMenu', () => { const ControlledRadioGroup = () => { const [ radioValue, setRadioValue ] = useState( 'two' ); const onRadioChange: React.ComponentProps< - typeof DropdownMenuRadioItem + typeof DropdownMenuV2.RadioItem >[ 'onChange' ] = ( e ) => { onRadioValueChangeSpy( e.target.value ); setRadioValue( e.target.value ); }; return ( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuGroup> - <DropdownMenuRadioItem + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.Group> + <DropdownMenuV2.RadioItem name="radio-test" value="radio-one" checked={ radioValue === 'radio-one' } onChange={ onRadioChange } > Radio item one - </DropdownMenuRadioItem> - <DropdownMenuRadioItem + </DropdownMenuV2.RadioItem> + <DropdownMenuV2.RadioItem name="radio-test" value="radio-two" checked={ radioValue === 'radio-two' } onChange={ onRadioChange } > Radio item two - </DropdownMenuRadioItem> - </DropdownMenuGroup> - </DropdownMenu> + </DropdownMenuV2.RadioItem> + </DropdownMenuV2.Group> + </DropdownMenuV2> ); }; @@ -533,9 +556,9 @@ describe( 'DropdownMenu', () => { it( 'should check radio items and keep the menu open when clicking (uncontrolled)', async () => { const onRadioValueChangeSpy = jest.fn(); render( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuGroup> - <DropdownMenuRadioItem + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.Group> + <DropdownMenuV2.RadioItem name="radio-test" value="radio-one" onChange={ ( e ) => @@ -543,8 +566,8 @@ describe( 'DropdownMenu', () => { } > Radio item one - </DropdownMenuRadioItem> - <DropdownMenuRadioItem + </DropdownMenuV2.RadioItem> + <DropdownMenuV2.RadioItem name="radio-test" value="radio-two" defaultChecked @@ -553,9 +576,9 @@ describe( 'DropdownMenu', () => { } > Radio item two - </DropdownMenuRadioItem> - </DropdownMenuGroup> - </DropdownMenu> + </DropdownMenuV2.RadioItem> + </DropdownMenuV2.Group> + </DropdownMenuV2> ); // Open dropdown @@ -617,8 +640,8 @@ describe( 'DropdownMenu', () => { useState< boolean >(); return ( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuCheckboxItem + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.CheckboxItem name="item-one" value="item-one-value" checked={ itemOneChecked } @@ -632,9 +655,9 @@ describe( 'DropdownMenu', () => { } } > Checkbox item one - </DropdownMenuCheckboxItem> + </DropdownMenuV2.CheckboxItem> - <DropdownMenuCheckboxItem + <DropdownMenuV2.CheckboxItem name="item-two" value="item-two-value" checked={ itemTwoChecked } @@ -648,8 +671,8 @@ describe( 'DropdownMenu', () => { } } > Checkbox item two - </DropdownMenuCheckboxItem> - </DropdownMenu> + </DropdownMenuV2.CheckboxItem> + </DropdownMenuV2> ); }; @@ -740,8 +763,8 @@ describe( 'DropdownMenu', () => { const onCheckboxValueChangeSpy = jest.fn(); render( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuCheckboxItem + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.CheckboxItem name="item-one" value="item-one-value" onChange={ ( e ) => { @@ -753,9 +776,9 @@ describe( 'DropdownMenu', () => { } } > Checkbox item one - </DropdownMenuCheckboxItem> + </DropdownMenuV2.CheckboxItem> - <DropdownMenuCheckboxItem + <DropdownMenuV2.CheckboxItem name="item-two" value="item-two-value" defaultChecked @@ -768,8 +791,8 @@ describe( 'DropdownMenu', () => { } } > Checkbox item two - </DropdownMenuCheckboxItem> - </DropdownMenu> + </DropdownMenuV2.CheckboxItem> + </DropdownMenuV2> ); // Open dropdown @@ -858,9 +881,11 @@ describe( 'DropdownMenu', () => { it( 'should be modal by default', async () => { render( <> - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuItem>Dropdown menu item</DropdownMenuItem> - </DropdownMenu> + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.Item> + Dropdown menu item + </DropdownMenuV2.Item> + </DropdownMenuV2> <button>Button outside of dropdown</button> </> ); @@ -885,12 +910,14 @@ describe( 'DropdownMenu', () => { it( 'should not be modal when the `modal` prop is set to `false`', async () => { render( <> - <DropdownMenu + <DropdownMenuV2 trigger={ <button>Open dropdown</button> } modal={ false } > - <DropdownMenuItem>Dropdown menu item</DropdownMenuItem> - </DropdownMenu> + <DropdownMenuV2.Item> + Dropdown menu item + </DropdownMenuV2.Item> + </DropdownMenuV2> <button>Button outside of dropdown</button> </> ); @@ -922,11 +949,11 @@ describe( 'DropdownMenu', () => { describe( 'items prefix and suffix', () => { it( 'should display a prefix on regular items', async () => { render( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuItem prefix={ <>Item prefix</> }> + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.Item prefix={ <>Item prefix</> }> Dropdown menu item - </DropdownMenuItem> - </DropdownMenu> + </DropdownMenuV2.Item> + </DropdownMenuV2> ); // Click to open the menu @@ -946,11 +973,11 @@ describe( 'DropdownMenu', () => { it( 'should display a suffix on regular items', async () => { render( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuItem suffix={ <>Item suffix</> }> + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.Item suffix={ <>Item suffix</> }> Dropdown menu item - </DropdownMenuItem> - </DropdownMenu> + </DropdownMenuV2.Item> + </DropdownMenuV2> ); // Click to open the menu @@ -970,15 +997,15 @@ describe( 'DropdownMenu', () => { it( 'should display a suffix on radio items', async () => { render( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuRadioItem + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.RadioItem name="radio-test" value="radio-one" suffix="Radio suffix" > Radio item one - </DropdownMenuRadioItem> - </DropdownMenu> + </DropdownMenuV2.RadioItem> + </DropdownMenuV2> ); // Click to open the menu @@ -998,15 +1025,15 @@ describe( 'DropdownMenu', () => { it( 'should display a suffix on checkbox items', async () => { render( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuCheckboxItem + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.CheckboxItem name="checkbox-test" value="checkbox-one" suffix="Checkbox suffix" > Checkbox item one - </DropdownMenuCheckboxItem> - </DropdownMenu> + </DropdownMenuV2.CheckboxItem> + </DropdownMenuV2> ); // Click to open the menu @@ -1028,10 +1055,10 @@ describe( 'DropdownMenu', () => { describe( 'typeahead', () => { it( 'should highlight matching item', async () => { render( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuItem>One</DropdownMenuItem> - <DropdownMenuItem>Two</DropdownMenuItem> - </DropdownMenu> + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.Item>One</DropdownMenuV2.Item> + <DropdownMenuV2.Item>Two</DropdownMenuV2.Item> + </DropdownMenuV2> ); // Click to open the menu @@ -1061,10 +1088,10 @@ describe( 'DropdownMenu', () => { it( 'should keep previous focus when no matches are found', async () => { render( - <DropdownMenu trigger={ <button>Open dropdown</button> }> - <DropdownMenuItem>One</DropdownMenuItem> - <DropdownMenuItem>Two</DropdownMenuItem> - </DropdownMenu> + <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> + <DropdownMenuV2.Item>One</DropdownMenuV2.Item> + <DropdownMenuV2.Item>Two</DropdownMenuV2.Item> + </DropdownMenuV2> ); // Click to open the menu diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index a4d7fa98ecfb0d..fa9fece048617e 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -5,16 +5,7 @@ import { Composite } from './composite'; import { useCompositeStore } from './composite/store'; import { positionToPlacement as __experimentalPopoverLegacyPositionToPlacement } from './popover/utils'; import { createPrivateSlotFill } from './slot-fill'; -import { - DropdownMenu as DropdownMenuV2, - DropdownMenuGroup as DropdownMenuGroupV2, - DropdownMenuItem as DropdownMenuItemV2, - DropdownMenuCheckboxItem as DropdownMenuCheckboxItemV2, - DropdownMenuRadioItem as DropdownMenuRadioItemV2, - DropdownMenuSeparator as DropdownMenuSeparatorV2, - DropdownMenuItemLabel as DropdownMenuItemLabelV2, - DropdownMenuItemHelpText as DropdownMenuItemHelpTextV2, -} from './dropdown-menu-v2'; +import { DropdownMenuV2 } from './dropdown-menu-v2'; import { ComponentsContext } from './context/context-system-provider'; import Theme from './theme'; import Tabs from './tabs'; @@ -34,12 +25,5 @@ lock( privateApis, { Tabs, Theme, DropdownMenuV2, - DropdownMenuGroupV2, - DropdownMenuItemV2, - DropdownMenuCheckboxItemV2, - DropdownMenuRadioItemV2, - DropdownMenuSeparatorV2, - DropdownMenuItemLabelV2, - DropdownMenuItemHelpTextV2, kebabCase, } ); diff --git a/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx b/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx index d671b8a8c62d96..279126c597bc82 100644 --- a/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx +++ b/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx @@ -18,12 +18,7 @@ import { LAYOUT_TABLE, LAYOUT_GRID } from '../../constants'; import { unlock } from '../../lock-unlock'; import type { Action, ActionModal } from '../../types'; -const { - DropdownMenuV2: DropdownMenu, - DropdownMenuGroupV2: DropdownMenuGroup, - DropdownMenuItemV2: DropdownMenuItem, - DropdownMenuSeparatorV2: DropdownMenuSeparator, -} = unlock( componentsPrivateApis ); +const { DropdownMenuV2 } = unlock( componentsPrivateApis ); interface ActionWithModalProps< Item > { action: ActionModal< Item >; @@ -129,7 +124,7 @@ function BulkActionItem< Item >( { const shouldShowModal = 'RenderModal' in action; return ( - <DropdownMenuItem + <DropdownMenuV2.Item key={ action.id } hideOnClick={ ! shouldShowModal } onClick={ async () => { @@ -142,7 +137,7 @@ function BulkActionItem< Item >( { suffix={ eligibleItems.length } > { action.label } - </DropdownMenuItem> + </DropdownMenuV2.Item> ); } @@ -163,7 +158,7 @@ function ActionsMenuGroup< Item >( { } return ( <> - <DropdownMenuGroup> + <DropdownMenuV2.Group> { elligibleActions.map( ( action ) => ( <BulkActionItem key={ action.id } @@ -172,8 +167,8 @@ function ActionsMenuGroup< Item >( { setActionWithModal={ setActionWithModal } /> ) ) } - </DropdownMenuGroup> - <DropdownMenuSeparator /> + </DropdownMenuV2.Group> + <DropdownMenuV2.Separator /> </> ); } @@ -219,7 +214,7 @@ function _BulkActions() { } return ( <> - <DropdownMenu + <DropdownMenuV2 open={ isMenuOpen } onOpenChange={ onMenuOpenChange } label={ __( 'Bulk actions' ) } @@ -250,8 +245,8 @@ function _BulkActions() { setActionWithModal={ setActionWithModal } selectedItems={ selectedItems } /> - <DropdownMenuGroup> - <DropdownMenuItem + <DropdownMenuV2.Group> + <DropdownMenuV2.Item disabled={ areAllSelected } hideOnClick={ false } onClick={ () => { @@ -264,8 +259,8 @@ function _BulkActions() { suffix={ numberSelectableItems } > { __( 'Select all' ) } - </DropdownMenuItem> - <DropdownMenuItem + </DropdownMenuV2.Item> + <DropdownMenuV2.Item disabled={ selection.length === 0 } hideOnClick={ false } onClick={ () => { @@ -273,9 +268,9 @@ function _BulkActions() { } } > { __( 'Deselect' ) } - </DropdownMenuItem> - </DropdownMenuGroup> - </DropdownMenu> + </DropdownMenuV2.Item> + </DropdownMenuV2.Group> + </DropdownMenuV2> { actionWithModal && ( <ActionWithModal action={ actionWithModal } diff --git a/packages/dataviews/src/components/dataviews-filters/add-filter.tsx b/packages/dataviews/src/components/dataviews-filters/add-filter.tsx index ca1043d6e99fdb..c8b6b5fda38fcc 100644 --- a/packages/dataviews/src/components/dataviews-filters/add-filter.tsx +++ b/packages/dataviews/src/components/dataviews-filters/add-filter.tsx @@ -19,11 +19,7 @@ import { forwardRef } from '@wordpress/element'; import { unlock } from '../../lock-unlock'; import type { NormalizedFilter, View } from '../../types'; -const { - DropdownMenuV2: DropdownMenu, - DropdownMenuItemV2: DropdownMenuItem, - DropdownMenuItemLabelV2: DropdownMenuItemLabel, -} = unlock( componentsPrivateApis ); +const { DropdownMenuV2 } = unlock( componentsPrivateApis ); interface AddFilterProps { filters: NormalizedFilter[]; @@ -43,10 +39,10 @@ export function AddFilterDropdownMenu( { } ) { const inactiveFilters = filters.filter( ( filter ) => ! filter.isVisible ); return ( - <DropdownMenu trigger={ trigger }> + <DropdownMenuV2 trigger={ trigger }> { inactiveFilters.map( ( filter ) => { return ( - <DropdownMenuItem + <DropdownMenuV2.Item key={ filter.field } onClick={ () => { setOpenedFilter( filter.field ); @@ -64,13 +60,13 @@ export function AddFilterDropdownMenu( { } ); } } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> { filter.name } - </DropdownMenuItemLabel> - </DropdownMenuItem> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> ); } ) } - </DropdownMenu> + </DropdownMenuV2> ); } diff --git a/packages/dataviews/src/components/dataviews-item-actions/index.tsx b/packages/dataviews/src/components/dataviews-item-actions/index.tsx index 53b468c1ab7d3e..e33cb0fe56d0ed 100644 --- a/packages/dataviews/src/components/dataviews-item-actions/index.tsx +++ b/packages/dataviews/src/components/dataviews-item-actions/index.tsx @@ -23,13 +23,7 @@ import { useRegistry } from '@wordpress/data'; import { unlock } from '../../lock-unlock'; import type { Action, ActionModal as ActionModalType } from '../../types'; -const { - DropdownMenuV2: DropdownMenu, - DropdownMenuGroupV2: DropdownMenuGroup, - DropdownMenuItemV2: DropdownMenuItem, - DropdownMenuItemLabelV2: DropdownMenuItemLabel, - kebabCase, -} = unlock( componentsPrivateApis ); +const { DropdownMenuV2, kebabCase } = unlock( componentsPrivateApis ); export interface ActionTriggerProps< Item > { action: Action< Item >; @@ -91,12 +85,12 @@ function DropdownMenuItemTrigger< Item >( { const label = typeof action.label === 'string' ? action.label : action.label( items ); return ( - <DropdownMenuItem + <DropdownMenuV2.Item onClick={ onClick } hideOnClick={ ! ( 'RenderModal' in action ) } > - <DropdownMenuItemLabel>{ label }</DropdownMenuItemLabel> - </DropdownMenuItem> + <DropdownMenuV2.ItemLabel>{ label }</DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> ); } @@ -158,7 +152,7 @@ export function ActionsDropdownMenuGroup< Item >( { }: ActionsDropdownMenuGroupProps< Item > ) { const registry = useRegistry(); return ( - <DropdownMenuGroup> + <DropdownMenuV2.Group> { actions.map( ( action ) => { if ( 'RenderModal' in action ) { return ( @@ -181,7 +175,7 @@ export function ActionsDropdownMenuGroup< Item >( { /> ); } ) } - </DropdownMenuGroup> + </DropdownMenuV2.Group> ); } @@ -251,7 +245,7 @@ function CompactItemActions< Item >( { actions, }: CompactItemActionsProps< Item > ) { return ( - <DropdownMenu + <DropdownMenuV2 trigger={ <Button size="compact" @@ -265,6 +259,6 @@ function CompactItemActions< Item >( { placement="bottom-end" > <ActionsDropdownMenuGroup actions={ actions } item={ item } /> - </DropdownMenu> + </DropdownMenuV2> ); } diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index e396b1c68203cc..3e4fc97308aa32 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -42,11 +42,7 @@ import DataViewsContext from '../dataviews-context'; import { unlock } from '../../lock-unlock'; import DensityPicker from '../../dataviews-layouts/grid/density-picker'; -const { - DropdownMenuV2: DropdownMenu, - DropdownMenuRadioItemV2: DropdownMenuRadioItem, - DropdownMenuItemLabelV2: DropdownMenuItemLabel, -} = unlock( componentsPrivateApis ); +const { DropdownMenuV2 } = unlock( componentsPrivateApis ); interface ViewTypeMenuProps { defaultLayouts?: SupportedLayouts; @@ -62,7 +58,7 @@ function ViewTypeMenu( { } const activeView = VIEW_LAYOUTS.find( ( v ) => view.type === v.type ); return ( - <DropdownMenu + <DropdownMenuV2 trigger={ <Button size="compact" @@ -77,7 +73,7 @@ function ViewTypeMenu( { return null; } return ( - <DropdownMenuRadioItem + <DropdownMenuV2.RadioItem key={ layout } value={ layout } name="view-actions-available-view" @@ -97,13 +93,13 @@ function ViewTypeMenu( { warning( 'Invalid dataview' ); } } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> { config.label } - </DropdownMenuItemLabel> - </DropdownMenuRadioItem> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.RadioItem> ); } ) } - </DropdownMenu> + </DropdownMenuV2> ); } diff --git a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx index ba672715b91ccf..b019cbae36ab3a 100644 --- a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx @@ -27,14 +27,7 @@ import type { ViewTable as ViewTableType, } from '../../types'; -const { - DropdownMenuV2: DropdownMenu, - DropdownMenuGroupV2: DropdownMenuGroup, - DropdownMenuItemV2: DropdownMenuItem, - DropdownMenuRadioItemV2: DropdownMenuRadioItem, - DropdownMenuItemLabelV2: DropdownMenuItemLabel, - DropdownMenuSeparatorV2: DropdownMenuSeparator, -} = unlock( componentsPrivateApis ); +const { DropdownMenuV2 } = unlock( componentsPrivateApis ); interface HeaderMenuProps< Item > { fieldId: string; @@ -50,7 +43,7 @@ function WithDropDownMenuSeparators( { children }: { children: ReactNode } ) { .filter( Boolean ) .map( ( child, i ) => ( <Fragment key={ i }> - { i > 0 && <DropdownMenuSeparator /> } + { i > 0 && <DropdownMenuV2.Separator /> } { child } </Fragment> ) ); @@ -93,7 +86,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( ! field.filterBy?.isPrimary; return ( - <DropdownMenu + <DropdownMenuV2 align="start" trigger={ <Button @@ -114,7 +107,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( > <WithDropDownMenuSeparators> { isSortable && ( - <DropdownMenuGroup> + <DropdownMenuV2.Group> { SORTING_DIRECTIONS.map( ( direction: SortDirection ) => { const isChecked = @@ -125,7 +118,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( const value = `${ field.id }-${ direction }`; return ( - <DropdownMenuRadioItem + <DropdownMenuV2.RadioItem key={ value } // All sorting radio items share the same name, so that // selecting a sorting option automatically deselects the @@ -145,18 +138,18 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( } ); } } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> { sortLabels[ direction ] } - </DropdownMenuItemLabel> - </DropdownMenuRadioItem> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.RadioItem> ); } ) } - </DropdownMenuGroup> + </DropdownMenuV2.Group> ) } { canAddFilter && ( - <DropdownMenuGroup> - <DropdownMenuItem + <DropdownMenuV2.Group> + <DropdownMenuV2.Item prefix={ <Icon icon={ funnel } /> } onClick={ () => { setOpenedFilter( field.id ); @@ -174,14 +167,14 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( } ); } } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> { __( 'Add filter' ) } - </DropdownMenuItemLabel> - </DropdownMenuItem> - </DropdownMenuGroup> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + </DropdownMenuV2.Group> ) } - <DropdownMenuGroup> - <DropdownMenuItem + <DropdownMenuV2.Group> + <DropdownMenuV2.Item prefix={ <Icon icon={ arrowLeft } /> } disabled={ index < 1 } onClick={ () => { @@ -200,11 +193,11 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( } ); } } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> { __( 'Move left' ) } - </DropdownMenuItemLabel> - </DropdownMenuItem> - <DropdownMenuItem + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + <DropdownMenuV2.Item prefix={ <Icon icon={ arrowRight } /> } disabled={ ! view.fields || index >= view.fields.length - 1 @@ -227,12 +220,12 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( } ); } } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> { __( 'Move right' ) } - </DropdownMenuItemLabel> - </DropdownMenuItem> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> { isHidable && ( - <DropdownMenuItem + <DropdownMenuV2.Item prefix={ <Icon icon={ unseen } /> } onClick={ () => { const viewFields = @@ -246,14 +239,14 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( } ); } } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> { __( 'Hide column' ) } - </DropdownMenuItemLabel> - </DropdownMenuItem> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> ) } - </DropdownMenuGroup> + </DropdownMenuV2.Group> </WithDropDownMenuSeparators> - </DropdownMenu> + </DropdownMenuV2> ); } ); diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js index 8eb6bc20bd407d..7eaf74c3365cc7 100644 --- a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js @@ -21,18 +21,15 @@ import { useState } from '@wordpress/element'; * Internal dependencies */ import { unlock } from '../../../lock-unlock'; -const { - DropdownMenuV2: DropdownMenu, - DropdownMenuItemV2: DropdownMenuItem, - DropdownMenuItemLabelV2: DropdownMenuItemLabel, -} = unlock( componentsPrivateApis ); -const { useGlobalSetting } = unlock( blockEditorPrivateApis ); import ScreenHeader from '../header'; import FontSizePreview from './font-size-preview'; import ConfirmDeleteFontSizeDialog from './confirm-delete-font-size-dialog'; import RenameFontSizeDialog from './rename-font-size-dialog'; import SizeControl from '../size-control'; +const { DropdownMenuV2 } = unlock( componentsPrivateApis ); +const { useGlobalSetting } = unlock( blockEditorPrivateApis ); + function FontSize() { const [ isDeleteConfirmOpen, setIsDeleteConfirmOpen ] = useState( false ); const [ isRenameDialogOpen, setIsRenameDialogOpen ] = useState( false ); @@ -160,7 +157,7 @@ function FontSize() { marginBottom={ 0 } paddingX={ 4 } > - <DropdownMenu + <DropdownMenuV2 trigger={ <Button size="small" @@ -169,21 +166,21 @@ function FontSize() { /> } > - <DropdownMenuItem + <DropdownMenuV2.Item onClick={ toggleRenameDialog } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> { __( 'Rename' ) } - </DropdownMenuItemLabel> - </DropdownMenuItem> - <DropdownMenuItem + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + <DropdownMenuV2.Item onClick={ toggleDeleteConfirm } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> { __( 'Delete' ) } - </DropdownMenuItemLabel> - </DropdownMenuItem> - </DropdownMenu> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + </DropdownMenuV2> </Spacer> </FlexItem> ) } diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-sizes.js b/packages/edit-site/src/components/global-styles/font-sizes/font-sizes.js index 450d0797139f85..e09dda1a82fe81 100644 --- a/packages/edit-site/src/components/global-styles/font-sizes/font-sizes.js +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-sizes.js @@ -27,11 +27,7 @@ import { useState } from '@wordpress/element'; * Internal dependencies */ import { unlock } from '../../../lock-unlock'; -const { - DropdownMenuV2: DropdownMenu, - DropdownMenuItemV2: DropdownMenuItem, - DropdownMenuItemLabelV2: DropdownMenuItemLabel, -} = unlock( componentsPrivateApis ); +const { DropdownMenuV2 } = unlock( componentsPrivateApis ); const { useGlobalSetting } = unlock( blockEditorPrivateApis ); import Subtitle from '../subtitle'; import { NavigationButtonAsItem } from '../navigation-button'; @@ -85,7 +81,7 @@ function FontSizeGroup( { /> ) } { !! handleResetFontSizes && ( - <DropdownMenu + <DropdownMenuV2 trigger={ <Button size="small" @@ -96,14 +92,16 @@ function FontSizeGroup( { /> } > - <DropdownMenuItem onClick={ toggleResetDialog }> - <DropdownMenuItemLabel> + <DropdownMenuV2.Item + onClick={ toggleResetDialog } + > + <DropdownMenuV2.ItemLabel> { origin === 'custom' ? __( 'Remove font size presets' ) : __( 'Reset font size presets' ) } - </DropdownMenuItemLabel> - </DropdownMenuItem> - </DropdownMenu> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> + </DropdownMenuV2> ) } </FlexItem> </HStack> diff --git a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js index 2445863549593e..284f498efea3e1 100644 --- a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js +++ b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js @@ -55,11 +55,7 @@ import { } from './shadow-utils'; const { useGlobalSetting } = unlock( blockEditorPrivateApis ); -const { - DropdownMenuV2: DropdownMenu, - DropdownMenuItemV2: DropdownMenuItem, - DropdownMenuItemLabelV2: DropdownMenuItemLabel, -} = unlock( componentsPrivateApis ); +const { DropdownMenuV2 } = unlock( componentsPrivateApis ); const customShadowMenuItems = [ { @@ -151,7 +147,7 @@ export default function ShadowsEditPanel() { <ScreenHeader title={ selectedShadow.name } /> <FlexItem> <Spacer marginTop={ 2 } marginBottom={ 0 } paddingX={ 4 }> - <DropdownMenu + <DropdownMenuV2 trigger={ <Button size="small" @@ -164,7 +160,7 @@ export default function ShadowsEditPanel() { ? customShadowMenuItems : presetShadowMenuItems ).map( ( item ) => ( - <DropdownMenuItem + <DropdownMenuV2.Item key={ item.action } onClick={ () => onMenuClick( item.action ) } disabled={ @@ -173,12 +169,12 @@ export default function ShadowsEditPanel() { baseSelectedShadow.shadow } > - <DropdownMenuItemLabel> + <DropdownMenuV2.ItemLabel> { item.label } - </DropdownMenuItemLabel> - </DropdownMenuItem> + </DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> ) ) } - </DropdownMenu> + </DropdownMenuV2> </Spacer> </FlexItem> </HStack> diff --git a/packages/editor/src/components/post-actions/index.js b/packages/editor/src/components/post-actions/index.js index 9cc594233c8814..8a3850e8f547c1 100644 --- a/packages/editor/src/components/post-actions/index.js +++ b/packages/editor/src/components/post-actions/index.js @@ -18,13 +18,7 @@ import { store as coreStore } from '@wordpress/core-data'; import { unlock } from '../../lock-unlock'; import { usePostActions } from './actions'; -const { - DropdownMenuV2: DropdownMenu, - DropdownMenuGroupV2: DropdownMenuGroup, - DropdownMenuItemV2: DropdownMenuItem, - DropdownMenuItemLabelV2: DropdownMenuItemLabel, - kebabCase, -} = unlock( componentsPrivateApis ); +const { DropdownMenuV2, kebabCase } = unlock( componentsPrivateApis ); export default function PostActions( { postType, postId, onActionPerformed } ) { const [ isActionsMenuOpen, setIsActionsMenuOpen ] = useState( false ); @@ -60,7 +54,7 @@ export default function PostActions( { postType, postId, onActionPerformed } ) { }, [ allActions, itemWithPermissions ] ); return ( - <DropdownMenu + <DropdownMenuV2 open={ isActionsMenuOpen } trigger={ <Button @@ -85,7 +79,7 @@ export default function PostActions( { postType, postId, onActionPerformed } ) { setIsActionsMenuOpen( false ); } } /> - </DropdownMenu> + </DropdownMenuV2> ); } @@ -99,12 +93,12 @@ function DropdownMenuItemTrigger( { action, onClick, items } ) { const label = typeof action.label === 'string' ? action.label : action.label( items ); return ( - <DropdownMenuItem + <DropdownMenuV2.Item onClick={ onClick } hideOnClick={ ! action.RenderModal } > - <DropdownMenuItemLabel>{ label }</DropdownMenuItemLabel> - </DropdownMenuItem> + <DropdownMenuV2.ItemLabel>{ label }</DropdownMenuV2.ItemLabel> + </DropdownMenuV2.Item> ); } @@ -151,7 +145,7 @@ function ActionWithModal( { action, item, ActionTrigger, onClose } ) { // With an added onClose prop. function ActionsDropdownMenuGroup( { actions, item, onClose } ) { return ( - <DropdownMenuGroup> + <DropdownMenuV2.Group> { actions.map( ( action ) => { if ( action.RenderModal ) { return ( @@ -173,6 +167,6 @@ function ActionsDropdownMenuGroup( { actions, item, onClose } ) { /> ); } ) } - </DropdownMenuGroup> + </DropdownMenuV2.Group> ); } From 498ce1743750f4a661c96c5883acd6893b165fb0 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 22 Aug 2024 19:35:00 +0900 Subject: [PATCH 0499/1908] Components: Decrease standard padding to 12px (#64708) * Components: Decrease standard padding to 12px * Fixup * Update snapshots * Add changelog * Fixup Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/components/CHANGELOG.md | 23 +++++++++++++++++++ .../components/src/color-picker/hex-input.tsx | 16 +++++-------- .../src/color-picker/input-with-slider.tsx | 16 +++++-------- .../src/custom-select-control-v2/styles.ts | 6 ++--- .../test/__snapshots__/index.test.js.snap | 8 +++---- .../src/input-control/input-base.tsx | 4 ++-- .../styles/input-control-styles.tsx | 17 +++++++------- packages/components/src/item-group/styles.ts | 6 ++--- .../test/__snapshots__/index.js.snap | 6 ++--- .../styles/select-control-styles.ts | 10 ++++---- .../components/src/text-control/style.scss | 5 ++-- .../components/src/utils/config-values.js | 10 ++++---- 12 files changed, 72 insertions(+), 55 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 5d2479e3149c56..ffea5a0aac616c 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,29 @@ ## Unreleased +### Enhancements + +- Decrease horizontal padding from 16px to 12px on the following components, when in the 40px default size ([#64708](https://github.com/WordPress/gutenberg/pull/64708)). + - `AnglePickerControl` + - `ColorPicker` (on the inputs) + - `CustomSelectControl` + - `CustomSelectControlV2` + - `DateTimePicker` (on the selects and inputs) + - `DimensionControl` + - `FocalPointPicker` (on the inputs) + - `FontSizePicker` (on the custom inputs) + - `GradientPicker` (on the selects and inputs) + - `InputControl` + - `NumberControl` + - `QueryControls` (on the selects and inputs) + - `RangeControl` (on the inputs) + - `SearchControl` + - `SelectControl` + - `TextControl` + - `TimePicker` (on the inputs) + - `TreeSelect` + - `UnitControl` + ### Internal - `DropdownMenu` v2: refactor to overloaded naming convention ([#64654](https://github.com/WordPress/gutenberg/pull/64654)). diff --git a/packages/components/src/color-picker/hex-input.tsx b/packages/components/src/color-picker/hex-input.tsx index 90ebc0a101bd35..ef8b5356c0edc1 100644 --- a/packages/components/src/color-picker/hex-input.tsx +++ b/packages/components/src/color-picker/hex-input.tsx @@ -13,11 +13,10 @@ import { __ } from '@wordpress/i18n'; */ import { InputControl } from '../input-control'; import { Text } from '../text'; -import { Spacer } from '../spacer'; -import { space } from '../utils/space'; import { COLORS } from '../utils/colors-values'; import type { StateReducer } from '../input-control/reducer/state'; import type { HexInputProps } from './types'; +import InputControlPrefixWrapper from '../input-control/input-prefix-wrapper'; export const HexInput = ( { color, onChange, enableAlpha }: HexInputProps ) => { const handleChange = ( nextValue: string | undefined ) => { @@ -48,14 +47,11 @@ export const HexInput = ( { color, onChange, enableAlpha }: HexInputProps ) => { return ( <InputControl prefix={ - <Spacer - as={ Text } - marginLeft={ space( 4 ) } - color={ COLORS.theme.accent } - lineHeight={ 1 } - > - # - </Spacer> + <InputControlPrefixWrapper> + <Text color={ COLORS.theme.accent } lineHeight={ 1 }> + # + </Text> + </InputControlPrefixWrapper> } value={ color.toHex().slice( 1 ).toUpperCase() } onChange={ handleChange } diff --git a/packages/components/src/color-picker/input-with-slider.tsx b/packages/components/src/color-picker/input-with-slider.tsx index 535adc3f2af6ee..5e08fa42daf80e 100644 --- a/packages/components/src/color-picker/input-with-slider.tsx +++ b/packages/components/src/color-picker/input-with-slider.tsx @@ -3,11 +3,10 @@ */ import { HStack } from '../h-stack'; import { Text } from '../text'; -import { Spacer } from '../spacer'; -import { space } from '../utils/space'; import { RangeControl, NumberControlWrapper } from './styles'; import { COLORS } from '../utils/colors-values'; import type { InputWithSliderProps } from './types'; +import InputControlPrefixWrapper from '../input-control/input-prefix-wrapper'; export const InputWithSlider = ( { min, @@ -39,14 +38,11 @@ export const InputWithSlider = ( { value={ value } onChange={ onNumberControlChange } prefix={ - <Spacer - as={ Text } - paddingLeft={ space( 4 ) } - color={ COLORS.theme.accent } - lineHeight={ 1 } - > - { abbreviation } - </Spacer> + <InputControlPrefixWrapper> + <Text color={ COLORS.theme.accent } lineHeight={ 1 }> + { abbreviation } + </Text> + </InputControlPrefixWrapper> } spinControls="none" size="__unstable-large" diff --git a/packages/components/src/custom-select-control-v2/styles.ts b/packages/components/src/custom-select-control-v2/styles.ts index 6b7fa590f9d0b2..add1a29e1602d6 100644 --- a/packages/components/src/custom-select-control-v2/styles.ts +++ b/packages/components/src/custom-select-control-v2/styles.ts @@ -21,9 +21,9 @@ const ANIMATION_PARAMS = { }; const INLINE_PADDING = { - compact: 8, // space(2) - small: 8, // space(2) - default: 16, // space(4) + compact: CONFIG.controlPaddingXSmall, + small: CONFIG.controlPaddingXSmall, + default: CONFIG.controlPaddingX, }; const getSelectSize = ( diff --git a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap index 658fe7febc02bc..cb6fffb5aeff03 100644 --- a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap +++ b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap @@ -158,7 +158,7 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = ` .emotion-21 { margin-bottom: 0; - padding-right: calc(4px * 2); + padding-right: 8px; position: absolute; pointer-events: none; right: 0; @@ -440,7 +440,7 @@ exports[`DimensionControl rendering renders with defaults 1`] = ` .emotion-21 { margin-bottom: 0; - padding-right: calc(4px * 2); + padding-right: 8px; position: absolute; pointer-events: none; right: 0; @@ -732,7 +732,7 @@ exports[`DimensionControl rendering renders with icon and custom icon label 1`] .emotion-21 { margin-bottom: 0; - padding-right: calc(4px * 2); + padding-right: 8px; position: absolute; pointer-events: none; right: 0; @@ -1036,7 +1036,7 @@ exports[`DimensionControl rendering renders with icon and default icon label 1`] .emotion-21 { margin-bottom: 0; - padding-right: calc(4px * 2); + padding-right: 8px; position: absolute; pointer-events: none; right: 0; diff --git a/packages/components/src/input-control/input-base.tsx b/packages/components/src/input-control/input-base.tsx index 58396f3ab98591..f59c2a411e05a5 100644 --- a/packages/components/src/input-control/input-base.tsx +++ b/packages/components/src/input-control/input-base.tsx @@ -96,8 +96,8 @@ function InputBase( } ); const prefixSuffixContextValue = useMemo( () => { return { - InputControlPrefixWrapper: { paddingLeft }, - InputControlSuffixWrapper: { paddingRight }, + InputControlPrefixWrapper: { paddingLeft: `${ paddingLeft }px` }, + InputControlSuffixWrapper: { paddingRight: `${ paddingRight }px` }, }; }, [ paddingLeft, paddingRight ] ); diff --git a/packages/components/src/input-control/styles/input-control-styles.tsx b/packages/components/src/input-control/styles/input-control-styles.tsx index ddfad620b91244..7a2040af9bdff9 100644 --- a/packages/components/src/input-control/styles/input-control-styles.tsx +++ b/packages/components/src/input-control/styles/input-control-styles.tsx @@ -14,7 +14,6 @@ import { Flex, FlexItem } from '../../flex'; import { Text } from '../../text'; import { baseLabelTypography, COLORS, CONFIG, rtl } from '../../utils'; import type { LabelPosition, Size } from '../types'; -import { space } from '../../utils/space'; type ContainerProps = { disabled?: boolean; @@ -188,29 +187,29 @@ export const getSizeConfig = ( { height: 40, lineHeight: 1, minHeight: 40, - paddingLeft: space( 4 ), - paddingRight: space( 4 ), + paddingLeft: CONFIG.controlPaddingX, + paddingRight: CONFIG.controlPaddingX, }, small: { height: 24, lineHeight: 1, minHeight: 24, - paddingLeft: space( 2 ), - paddingRight: space( 2 ), + paddingLeft: CONFIG.controlPaddingXSmall, + paddingRight: CONFIG.controlPaddingXSmall, }, compact: { height: 32, lineHeight: 1, minHeight: 32, - paddingLeft: space( 2 ), - paddingRight: space( 2 ), + paddingLeft: CONFIG.controlPaddingXSmall, + paddingRight: CONFIG.controlPaddingXSmall, }, '__unstable-large': { height: 40, lineHeight: 1, minHeight: 40, - paddingLeft: space( 4 ), - paddingRight: space( 4 ), + paddingLeft: CONFIG.controlPaddingX, + paddingRight: CONFIG.controlPaddingX, }, }; diff --git a/packages/components/src/item-group/styles.ts b/packages/components/src/item-group/styles.ts index 66c6158f9af1a3..a2d73c8dcfc592 100644 --- a/packages/components/src/item-group/styles.ts +++ b/packages/components/src/item-group/styles.ts @@ -105,12 +105,12 @@ const paddingYLarge = `calc((${ CONFIG.controlHeightLarge } - ${ baseFontHeight export const itemSizes = { small: css` - padding: ${ paddingYSmall } ${ CONFIG.controlPaddingXSmall }; + padding: ${ paddingYSmall } ${ CONFIG.controlPaddingXSmall }px; `, medium: css` - padding: ${ paddingY } ${ CONFIG.controlPaddingX }; + padding: ${ paddingY } ${ CONFIG.controlPaddingX }px; `, large: css` - padding: ${ paddingYLarge } ${ CONFIG.controlPaddingXLarge }; + padding: ${ paddingYLarge } ${ CONFIG.controlPaddingXLarge }px; `, }; diff --git a/packages/components/src/item-group/test/__snapshots__/index.js.snap b/packages/components/src/item-group/test/__snapshots__/index.js.snap index 24ecd27f68c49f..4104a4bf5140c1 100644 --- a/packages/components/src/item-group/test/__snapshots__/index.js.snap +++ b/packages/components/src/item-group/test/__snapshots__/index.js.snap @@ -12,7 +12,7 @@ Snapshot Diff: > <div - class="components-item css-au4yox-PolymorphicDiv-medium-item-spacedAround e19lxcc00" -+ class="components-item css-1h3jinl-PolymorphicDiv-large-item-spacedAround e19lxcc00" ++ class="components-item css-1ycukrf-PolymorphicDiv-large-item-spacedAround e19lxcc00" data-wp-c16t="true" data-wp-component="Item" > @@ -25,7 +25,7 @@ Snapshot Diff: > <div - class="components-item css-au4yox-PolymorphicDiv-medium-item-spacedAround e19lxcc00" -+ class="components-item css-1h3jinl-PolymorphicDiv-large-item-spacedAround e19lxcc00" ++ class="components-item css-1ycukrf-PolymorphicDiv-large-item-spacedAround e19lxcc00" data-wp-c16t="true" data-wp-component="Item" > @@ -45,7 +45,7 @@ Snapshot Diff: > <div - class="components-item css-tpom78-PolymorphicDiv-medium-item e19lxcc00" -+ class="components-item css-vss65r-PolymorphicDiv-large-item e19lxcc00" ++ class="components-item css-sbyvbg-PolymorphicDiv-large-item e19lxcc00" data-wp-c16t="true" data-wp-component="Item" > diff --git a/packages/components/src/select-control/styles/select-control-styles.ts b/packages/components/src/select-control/styles/select-control-styles.ts index 780334c67e85e6..5248e7af988285 100644 --- a/packages/components/src/select-control/styles/select-control-styles.ts +++ b/packages/components/src/select-control/styles/select-control-styles.ts @@ -7,7 +7,7 @@ import styled from '@emotion/styled'; /** * Internal dependencies */ -import { COLORS, rtl } from '../../utils'; +import { COLORS, rtl, CONFIG } from '../../utils'; import { space } from '../../utils/space'; import type { SelectControlProps } from '../types'; import InputControlSuffixWrapper from '../../input-control/input-suffix-wrapper'; @@ -108,10 +108,10 @@ const sizePaddings = ( { selectSize = 'default', }: SelectProps ) => { const padding = { - default: 16, - small: 8, - compact: 8, - '__unstable-large': 16, + default: CONFIG.controlPaddingX, + small: CONFIG.controlPaddingXSmall, + compact: CONFIG.controlPaddingXSmall, + '__unstable-large': CONFIG.controlPaddingX, }; if ( ! __next40pxDefaultSize ) { diff --git a/packages/components/src/text-control/style.scss b/packages/components/src/text-control/style.scss index d6819f86b84bf1..5ae2a90b827736 100644 --- a/packages/components/src/text-control/style.scss +++ b/packages/components/src/text-control/style.scss @@ -23,7 +23,8 @@ // Subtract 1px to account for the border, which isn't included on the element // on newer components like InputControl, SelectControl, etc. - padding-left: $grid-unit-20; - padding-right: $grid-unit-20; + // These values should be shared with the `controlPaddingX` in ./utils/config-values.js + padding-left: $grid-unit-15; + padding-right: $grid-unit-15; } } diff --git a/packages/components/src/utils/config-values.js b/packages/components/src/utils/config-values.js index 0ad1b3294a926b..f76c1291a8b319 100644 --- a/packages/components/src/utils/config-values.js +++ b/packages/components/src/utils/config-values.js @@ -5,14 +5,16 @@ import { space } from './space'; import { COLORS } from './colors-values'; const CONTROL_HEIGHT = '36px'; -const CONTROL_PADDING_X = '12px'; const CONTROL_PROPS = { controlSurfaceColor: COLORS.white, controlTextActiveColor: COLORS.theme.accent, - controlPaddingX: CONTROL_PADDING_X, - controlPaddingXLarge: `calc(${ CONTROL_PADDING_X } * 1.3334)`, - controlPaddingXSmall: `calc(${ CONTROL_PADDING_X } / 1.3334)`, + + // These values should be shared with TextControl. + controlPaddingX: 12, + controlPaddingXSmall: 8, + controlPaddingXLarge: 12 * 1.3334, // TODO: Deprecate + controlBackgroundColor: COLORS.white, controlBoxShadow: 'transparent', controlBoxShadowFocus: `0 0 0 0.5px ${ COLORS.theme.accent }`, From 49aa701ec230e75acd285084cc2af85b001273d1 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 22 Aug 2024 13:15:23 +0200 Subject: [PATCH 0500/1908] DataViews: Add missing styles and remove opinionated ones for generic usage (#64711) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../src/components/dataviews-view-config/style.scss | 4 ++++ .../dataviews/src/components/dataviews/stories/fixtures.js | 3 +++ packages/dataviews/src/dataviews-layouts/list/style.scss | 1 + packages/dataviews/src/dataviews-layouts/table/style.scss | 5 ----- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-view-config/style.scss b/packages/dataviews/src/components/dataviews-view-config/style.scss index 85e86722f7b614..00c1c6a9baf44f 100644 --- a/packages/dataviews/src/components/dataviews-view-config/style.scss +++ b/packages/dataviews/src/components/dataviews-view-config/style.scss @@ -29,6 +29,10 @@ } } +.dataviews-settings-section:has(.dataviews-settings-section__content:empty) { + display: none; +} + /* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ @container (max-width: 500px) { .dataviews-settings-section.dataviews-settings-section { diff --git a/packages/dataviews/src/components/dataviews/stories/fixtures.js b/packages/dataviews/src/components/dataviews/stories/fixtures.js index 50401d97b026b5..e061d0951ade73 100644 --- a/packages/dataviews/src/components/dataviews/stories/fixtures.js +++ b/packages/dataviews/src/components/dataviews/stories/fixtures.js @@ -191,6 +191,9 @@ export const fields = [ id: 'title', enableHiding: false, enableGlobalSearch: true, + render: ( { item } ) => { + return <a href="#nothing">{ item.title }</a>; + }, }, { id: 'date', diff --git a/packages/dataviews/src/dataviews-layouts/list/style.scss b/packages/dataviews/src/dataviews-layouts/list/style.scss index a3295d1f3fd5f2..5bbe76f87ca5b8 100644 --- a/packages/dataviews/src/dataviews-layouts/list/style.scss +++ b/packages/dataviews/src/dataviews-layouts/list/style.scss @@ -101,6 +101,7 @@ } .dataviews-view-list__item { + box-sizing: border-box; padding: $grid-unit-20 $grid-unit-30; width: 100%; scroll-margin: $grid-unit-10 0; diff --git a/packages/dataviews/src/dataviews-layouts/table/style.scss b/packages/dataviews/src/dataviews-layouts/table/style.scss index 7bbd172c8c91b8..dd091db4ec99f5 100644 --- a/packages/dataviews/src/dataviews-layouts/table/style.scss +++ b/packages/dataviews/src/dataviews-layouts/table/style.scss @@ -7,11 +7,6 @@ color: $gray-700; margin-bottom: auto; - a { - text-decoration: none; - color: $gray-900; - font-weight: 500; - } th { text-align: left; color: $gray-900; From e7674d669354941ed221b2142bef55bd3e72e49e Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 22 Aug 2024 20:56:14 +0900 Subject: [PATCH 0501/1908] UnitControl: Update unit select styles (#64712) * UnitControl: Update unit select styles * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/unit-control/styles/unit-control-styles.ts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index ffea5a0aac616c..2fe344090bcdfc 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -4,6 +4,7 @@ ### Enhancements +- `UnitControl`: Update unit select styles ([#64712](https://github.com/WordPress/gutenberg/pull/64712)). - Decrease horizontal padding from 16px to 12px on the following components, when in the 40px default size ([#64708](https://github.com/WordPress/gutenberg/pull/64708)). - `AnglePickerControl` - `ColorPicker` (on the inputs) diff --git a/packages/components/src/unit-control/styles/unit-control-styles.ts b/packages/components/src/unit-control/styles/unit-control-styles.ts index 5f59771bd48a6a..8ec575c8499ec2 100644 --- a/packages/components/src/unit-control/styles/unit-control-styles.ts +++ b/packages/components/src/unit-control/styles/unit-control-styles.ts @@ -64,6 +64,7 @@ const baseUnitLabelStyles = ( { selectSize }: SelectProps ) => { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; + field-sizing: content; &:not( :disabled ) { color: ${ COLORS.theme.accent }; @@ -114,7 +115,7 @@ const unitSelectSizes = ( { selectSize = 'default' }: SelectProps ) => { align-items: center; &:where( :not( :disabled ) ):hover { - box-shadow: inset 0 0 0 + box-shadow: 0 0 0 ${ CONFIG.borderWidth + ' ' + COLORS.ui.borderFocus }; outline: ${ CONFIG.borderWidth } solid transparent; // For High Contrast Mode } From 8572b1737e0cb6d843ee8baeeaca8234f1a3a133 Mon Sep 17 00:00:00 2001 From: Matias Benedetto <matias.benedetto@gmail.com> Date: Thu, 22 Aug 2024 09:16:51 -0300 Subject: [PATCH 0502/1908] Hide typeset button when there are no typesets available (#64515) --- .../src/components/global-styles/typeset-button.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/typeset-button.js b/packages/edit-site/src/components/global-styles/typeset-button.js index 81955627526595..bcd450def06f8e 100644 --- a/packages/edit-site/src/components/global-styles/typeset-button.js +++ b/packages/edit-site/src/components/global-styles/typeset-button.js @@ -23,14 +23,20 @@ import { getFontFamilies } from './utils'; import { NavigationButtonAsItem } from './navigation-button'; import Subtitle from './subtitle'; import { unlock } from '../../lock-unlock'; -import { filterObjectByProperties } from '../../hooks/use-theme-style-variations/use-theme-style-variations-by-property'; +import { + filterObjectByProperties, + useCurrentMergeThemeStyleVariationsWithUserConfig, +} from '../../hooks/use-theme-style-variations/use-theme-style-variations-by-property'; const { GlobalStylesContext } = unlock( blockEditorPrivateApis ); const { mergeBaseAndUserConfigs } = unlock( editorPrivateApis ); function TypesetButton() { - const { base } = useContext( GlobalStylesContext ); - const { user: userConfig } = useContext( GlobalStylesContext ); + const propertiesToFilter = [ 'typography' ]; + const typographyVariations = + useCurrentMergeThemeStyleVariationsWithUserConfig( propertiesToFilter ); + const hasTypographyVariations = typographyVariations?.length > 1; + const { base, user: userConfig } = useContext( GlobalStylesContext ); const config = mergeBaseAndUserConfigs( base, userConfig ); const allFontFamilies = getFontFamilies( config ); const hasFonts = @@ -63,6 +69,7 @@ function TypesetButton() { }, [ allFontFamilies, userTypographyConfig, variations ] ); return ( + hasTypographyVariations && hasFonts && ( <VStack spacing={ 2 }> <HStack justify="space-between"> From cf4d798badcf83d1815b72399cf57dedf226160e Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Thu, 22 Aug 2024 19:07:30 +0530 Subject: [PATCH 0503/1908] Tag Cloud: Improve state of block with no tags (#63774) * Render nothing when no tags are available in tag cloud block * Added condition to display placeholder in editor * Fix phpcs errors * Use wp_is_serving_rest_request function for conditional check Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/block-library/src/tag-cloud/index.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/tag-cloud/index.php b/packages/block-library/src/tag-cloud/index.php index 69b8c25ec87209..8949dd8e5b11fb 100644 --- a/packages/block-library/src/tag-cloud/index.php +++ b/packages/block-library/src/tag-cloud/index.php @@ -29,8 +29,13 @@ function render_block_core_tag_cloud( $attributes ) { ); $tag_cloud = wp_tag_cloud( $args ); - if ( ! $tag_cloud ) { - $tag_cloud = __( 'There’s no content to show here yet.' ); + if ( empty( $tag_cloud ) ) { + // Display placeholder content when there are no tags only in editor. + if ( wp_is_serving_rest_request() ) { + $tag_cloud = __( 'There’s no content to show here yet.' ); + } else { + return ''; + } } $wrapper_attributes = get_block_wrapper_attributes(); From 609a3c8d38a0608b41b1827ec4a8c1f812487ef2 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 22 Aug 2024 17:37:53 +0300 Subject: [PATCH 0504/1908] Rename refs to fix tons of 'Mutating a value' errors (#64718) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/block-draggable/index.js | 8 +- .../use-scroll-when-dragging.js | 50 +++++------ .../src/components/block-lock/toolbar.js | 6 +- .../block-tools/block-toolbar-popover.js | 8 +- .../src/components/iframe/index.js | 10 +-- .../use-inner-block-template-sync.js | 6 +- .../components/inserter-list-item/index.js | 8 +- .../components/inserter/media-tab/hooks.js | 6 +- .../src/components/link-control/index.js | 14 ++-- .../src/components/provider/use-block-sync.js | 40 ++++----- .../rich-text/use-mark-persistent.js | 10 +-- .../components/writing-flow/use-tab-nav.js | 8 +- .../src/hooks/spacing-visualizer.js | 6 +- .../block-editor/src/hooks/use-zoom-out.js | 14 ++-- packages/block-library/src/freeform/edit.js | 8 +- .../navigation/edit/unsaved-inner-blocks.js | 8 +- .../block-library/src/social-links/edit.js | 6 +- packages/block-library/src/utils/hooks.js | 22 ++--- .../commands/src/components/command-menu.js | 8 +- packages/commands/src/hooks/use-command.js | 6 +- .../src/angle-picker-control/angle-circle.tsx | 20 +++-- .../components/src/clipboard-button/index.tsx | 12 +-- .../src/color-picker/color-copy-button.tsx | 18 ++-- .../gradient-bar/control-points.tsx | 20 ++--- packages/components/src/draggable/index.tsx | 8 +- .../src/input-control/reducer/reducer.ts | 23 +++--- .../components/src/input-control/utils.ts | 6 +- packages/components/src/modal/index.tsx | 10 +-- packages/components/src/navigation/index.tsx | 8 +- .../components/src/palette-edit/index.tsx | 4 +- .../src/slot-fill/bubbles-virtually/fill.tsx | 8 +- packages/components/src/snackbar/index.tsx | 8 +- packages/components/src/tabs/index.tsx | 12 ++- .../toggle-group-control/utils.ts | 14 ++-- .../src/tools-panel/tools-panel/hook.ts | 12 +-- .../src/utils/hooks/use-update-effect.js | 8 +- .../src/hooks/use-copy-on-click/index.js | 10 +-- .../src/hooks/use-focus-on-mount/index.js | 8 +- .../src/hooks/use-focus-outside/index.ts | 22 ++--- .../src/hooks/use-keyboard-shortcut/index.js | 6 +- .../compose/src/hooks/use-merge-refs/index.js | 28 ++++--- .../compose/src/hooks/use-ref-effect/index.ts | 8 +- .../src/hooks/use-resize-observer/index.tsx | 26 +++--- .../use-dispatch/use-dispatch-with-map.js | 8 +- .../dataviews-bulk-actions-toolbar/index.tsx | 12 +-- .../src/dataviews-layouts/table/index.tsx | 6 +- .../editor-initialization/listener-hooks.js | 8 +- .../use-sync-canvas-mode-with-url.js | 27 +++--- .../src/components/document-bar/index.js | 8 +- .../local-autosave-monitor/index.js | 12 +-- .../src/components/preview-dropdown/index.js | 10 +-- .../components/complementary-area/index.js | 22 ++--- packages/rich-text/src/component/index.js | 82 ++++++++++--------- 53 files changed, 382 insertions(+), 364 deletions(-) diff --git a/packages/block-editor/src/components/block-draggable/index.js b/packages/block-editor/src/components/block-draggable/index.js index e1afc1f2513841..5bb328f7cf9f58 100644 --- a/packages/block-editor/src/components/block-draggable/index.js +++ b/packages/block-editor/src/components/block-draggable/index.js @@ -62,7 +62,7 @@ const BlockDraggable = ( { [ clientIds ] ); - const isDragging = useRef( false ); + const isDraggingRef = useRef( false ); const [ startScrolling, scrollOnDragOver, stopScrolling ] = useScrollWhenDragging(); @@ -75,7 +75,7 @@ const BlockDraggable = ( { // Stop dragging blocks if the block draggable is unmounted. useEffect( () => { return () => { - if ( isDragging.current ) { + if ( isDraggingRef.current ) { stopDraggingBlocks(); } }; @@ -193,7 +193,7 @@ const BlockDraggable = ( { // frame to enable dragging. window.requestAnimationFrame( () => { startDraggingBlocks( clientIds ); - isDragging.current = true; + isDraggingRef.current = true; startScrolling( event ); @@ -205,7 +205,7 @@ const BlockDraggable = ( { onDragOver={ scrollOnDragOver } onDragEnd={ () => { stopDraggingBlocks(); - isDragging.current = false; + isDraggingRef.current = false; stopScrolling(); diff --git a/packages/block-editor/src/components/block-draggable/use-scroll-when-dragging.js b/packages/block-editor/src/components/block-draggable/use-scroll-when-dragging.js index a01db4927b6525..515f3002de9344 100644 --- a/packages/block-editor/src/components/block-draggable/use-scroll-when-dragging.js +++ b/packages/block-editor/src/components/block-draggable/use-scroll-when-dragging.js @@ -18,36 +18,36 @@ const VELOCITY_MULTIPLIER = * and `onDragEnd` events respectively. */ export default function useScrollWhenDragging() { - const dragStartY = useRef( null ); - const velocityY = useRef( null ); - const scrollParentY = useRef( null ); - const scrollEditorInterval = useRef( null ); + const dragStartYRef = useRef( null ); + const velocityYRef = useRef( null ); + const scrollParentYRef = useRef( null ); + const scrollEditorIntervalRef = useRef( null ); // Clear interval when unmounting. useEffect( () => () => { - if ( scrollEditorInterval.current ) { - clearInterval( scrollEditorInterval.current ); - scrollEditorInterval.current = null; + if ( scrollEditorIntervalRef.current ) { + clearInterval( scrollEditorIntervalRef.current ); + scrollEditorIntervalRef.current = null; } }, [] ); const startScrolling = useCallback( ( event ) => { - dragStartY.current = event.clientY; + dragStartYRef.current = event.clientY; // Find nearest parent(s) to scroll. - scrollParentY.current = getScrollContainer( event.target ); + scrollParentYRef.current = getScrollContainer( event.target ); - scrollEditorInterval.current = setInterval( () => { - if ( scrollParentY.current && velocityY.current ) { + scrollEditorIntervalRef.current = setInterval( () => { + if ( scrollParentYRef.current && velocityYRef.current ) { const newTop = - scrollParentY.current.scrollTop + velocityY.current; + scrollParentYRef.current.scrollTop + velocityYRef.current; // Setting `behavior: 'smooth'` as a scroll property seems to hurt performance. // Better to use a small scroll interval. - scrollParentY.current.scroll( { + scrollParentYRef.current.scroll( { top: newTop, } ); } @@ -55,14 +55,14 @@ export default function useScrollWhenDragging() { }, [] ); const scrollOnDragOver = useCallback( ( event ) => { - if ( ! scrollParentY.current ) { + if ( ! scrollParentYRef.current ) { return; } - const scrollParentHeight = scrollParentY.current.offsetHeight; + const scrollParentHeight = scrollParentYRef.current.offsetHeight; const offsetDragStartPosition = - dragStartY.current - scrollParentY.current.offsetTop; + dragStartYRef.current - scrollParentYRef.current.offsetTop; const offsetDragPosition = - event.clientY - scrollParentY.current.offsetTop; + event.clientY - scrollParentYRef.current.offsetTop; if ( event.clientY > offsetDragStartPosition ) { // User is dragging downwards. @@ -82,7 +82,7 @@ export default function useScrollWhenDragging() { moveableDistance === 0 || dragDistance === 0 ? 0 : dragDistance / moveableDistance; - velocityY.current = VELOCITY_MULTIPLIER * distancePercentage; + velocityYRef.current = VELOCITY_MULTIPLIER * distancePercentage; } else if ( event.clientY < offsetDragStartPosition ) { // User is dragging upwards. const moveableDistance = Math.max( @@ -99,19 +99,19 @@ export default function useScrollWhenDragging() { moveableDistance === 0 || dragDistance === 0 ? 0 : dragDistance / moveableDistance; - velocityY.current = -VELOCITY_MULTIPLIER * distancePercentage; + velocityYRef.current = -VELOCITY_MULTIPLIER * distancePercentage; } else { - velocityY.current = 0; + velocityYRef.current = 0; } }, [] ); const stopScrolling = () => { - dragStartY.current = null; - scrollParentY.current = null; + dragStartYRef.current = null; + scrollParentYRef.current = null; - if ( scrollEditorInterval.current ) { - clearInterval( scrollEditorInterval.current ); - scrollEditorInterval.current = null; + if ( scrollEditorIntervalRef.current ) { + clearInterval( scrollEditorIntervalRef.current ); + scrollEditorIntervalRef.current = null; } }; diff --git a/packages/block-editor/src/components/block-lock/toolbar.js b/packages/block-editor/src/components/block-lock/toolbar.js index 29bf0cdd6a60c6..12376a7b56a5ee 100644 --- a/packages/block-editor/src/components/block-lock/toolbar.js +++ b/packages/block-editor/src/components/block-lock/toolbar.js @@ -20,7 +20,7 @@ export default function BlockLockToolbar( { clientId } ) { false ); - const hasLockButtonShown = useRef( false ); + const hasLockButtonShownRef = useRef( false ); // If the block lock button has been shown, we don't want to remove it // from the toolbar until the toolbar is rendered again without it. @@ -29,11 +29,11 @@ export default function BlockLockToolbar( { clientId } ) { // whence it came, and to do that, we need to leave the button in the toolbar. useEffect( () => { if ( isLocked ) { - hasLockButtonShown.current = true; + hasLockButtonShownRef.current = true; } }, [ isLocked ] ); - if ( ! isLocked && ! hasLockButtonShown.current ) { + if ( ! isLocked && ! hasLockButtonShownRef.current ) { return null; } diff --git a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js index eef5b5afca304d..8428222268408a 100644 --- a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js +++ b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js @@ -36,15 +36,15 @@ export default function BlockToolbarPopover( { }, [ clientId ] ); const { stopTyping } = useDispatch( blockEditorStore ); - const isToolbarForced = useRef( false ); + const isToolbarForcedRef = useRef( false ); useShortcut( 'core/block-editor/focus-toolbar', () => { - isToolbarForced.current = true; + isToolbarForcedRef.current = true; stopTyping( true ); } ); useEffect( () => { - isToolbarForced.current = false; + isToolbarForcedRef.current = false; } ); const popoverProps = useBlockToolbarPopoverProps( { @@ -66,7 +66,7 @@ export default function BlockToolbarPopover( { <PrivateBlockToolbar // If the toolbar is being shown because of being forced // it should focus the toolbar right after the mount. - focusOnMount={ isToolbarForced.current } + focusOnMount={ isToolbarForcedRef.current } __experimentalInitialIndex={ initialToolbarItemIndexRef.current } diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index 3b0bce6d56b403..3e022cf95ae556 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -122,7 +122,7 @@ function Iframe( { }, [] ); const { styles = '', scripts = '' } = resolvedAssets; const [ iframeDocument, setIframeDocument ] = useState(); - const prevContainerWidth = useRef(); + const prevContainerWidthRef = useRef(); const [ bodyClasses, setBodyClasses ] = useState( [] ); const clearerRef = useBlockSelectionClearer(); const [ before, writingFlowRef, after ] = useWritingFlow(); @@ -243,7 +243,7 @@ function Iframe( { useEffect( () => { if ( ! isZoomedOut ) { - prevContainerWidth.current = containerWidth; + prevContainerWidthRef.current = containerWidth; } }, [ containerWidth, isZoomedOut ] ); @@ -310,7 +310,7 @@ function Iframe( { '--wp-block-editor-iframe-zoom-out-scale', scale === 'default' ? Math.min( containerWidth, maxWidth ) / - prevContainerWidth.current + prevContainerWidthRef.current : scale ); iframeDocument.documentElement.style.setProperty( @@ -331,7 +331,7 @@ function Iframe( { ); iframeDocument.documentElement.style.setProperty( '--wp-block-editor-iframe-zoom-out-prev-container-width', - `${ prevContainerWidth.current }px` + `${ prevContainerWidthRef.current }px` ); return () => { @@ -456,7 +456,7 @@ function Iframe( { '--wp-block-editor-iframe-zoom-out-container-width': isZoomedOut && `${ containerWidth }px`, '--wp-block-editor-iframe-zoom-out-prev-container-width': - isZoomedOut && `${ prevContainerWidth.current }px`, + isZoomedOut && `${ prevContainerWidthRef.current }px`, } } > { iframe } diff --git a/packages/block-editor/src/components/inner-blocks/use-inner-block-template-sync.js b/packages/block-editor/src/components/inner-blocks/use-inner-block-template-sync.js index 020b391039a01b..fd801779372aac 100644 --- a/packages/block-editor/src/components/inner-blocks/use-inner-block-template-sync.js +++ b/packages/block-editor/src/components/inner-blocks/use-inner-block-template-sync.js @@ -52,7 +52,7 @@ export default function useInnerBlockTemplateSync( useDispatch( blockEditorStore ); // Maintain a reference to the previous value so we can do a deep equality check. - const existingTemplate = useRef( null ); + const existingTemplateRef = useRef( null ); useLayoutEffect( () => { let isCancelled = false; @@ -76,14 +76,14 @@ export default function useInnerBlockTemplateSync( const hasTemplateChanged = ! fastDeepEqual( template, - existingTemplate.current + existingTemplateRef.current ); if ( ! shouldApplyTemplate || ! hasTemplateChanged ) { return; } - existingTemplate.current = template; + existingTemplateRef.current = template; const nextBlocks = synchronizeBlocksWithTemplate( currentInnerBlocks, template diff --git a/packages/block-editor/src/components/inserter-list-item/index.js b/packages/block-editor/src/components/inserter-list-item/index.js index 4a0ef102e84b0e..c5bf2110702629 100644 --- a/packages/block-editor/src/components/inserter-list-item/index.js +++ b/packages/block-editor/src/components/inserter-list-item/index.js @@ -32,7 +32,7 @@ function InserterListItem( { isDraggable, ...props } ) { - const isDragging = useRef( false ); + const isDraggingRef = useRef( false ); const itemIconStyle = item.icon ? { backgroundColor: item.icon.background, @@ -70,14 +70,14 @@ function InserterListItem( { ) } draggable={ draggable } onDragStart={ ( event ) => { - isDragging.current = true; + isDraggingRef.current = true; if ( onDragStart ) { onHover( null ); onDragStart( event ); } } } onDragEnd={ ( event ) => { - isDragging.current = false; + isDraggingRef.current = false; if ( onDragEnd ) { onDragEnd( event ); } @@ -110,7 +110,7 @@ function InserterListItem( { } } } onMouseEnter={ () => { - if ( isDragging.current ) { + if ( isDraggingRef.current ) { return; } onHover( item ); diff --git a/packages/block-editor/src/components/inserter/media-tab/hooks.js b/packages/block-editor/src/components/inserter/media-tab/hooks.js index 3a4c8fa9da7df5..694b321832422a 100644 --- a/packages/block-editor/src/components/inserter/media-tab/hooks.js +++ b/packages/block-editor/src/components/inserter/media-tab/hooks.js @@ -31,18 +31,18 @@ export function useMediaResults( category, query = {} ) { // In the future we could use AbortController to cancel previous // requests, but we don't for now as it involves adding support // for this to `core-data` package. - const lastRequest = useRef(); + const lastRequestRef = useRef(); useEffect( () => { ( async () => { const key = JSON.stringify( { category: category.name, ...query, } ); - lastRequest.current = key; + lastRequestRef.current = key; setIsLoading( true ); setMediaList( [] ); // Empty the previous results. const _media = await category.fetch?.( query ); - if ( key === lastRequest.current ) { + if ( key === lastRequestRef.current ) { setMediaList( _media ); setIsLoading( false ); } diff --git a/packages/block-editor/src/components/link-control/index.js b/packages/block-editor/src/components/link-control/index.js index 576556519fb2f4..85626e50fcf2aa 100644 --- a/packages/block-editor/src/components/link-control/index.js +++ b/packages/block-editor/src/components/link-control/index.js @@ -180,10 +180,10 @@ function LinkControl( { // Therefore a local state is used as a fallback. const isSettingsOpen = advancedSettingsPreference || settingsOpen; - const isMounting = useRef( true ); + const isMountingRef = useRef( true ); const wrapperNode = useRef(); const textInputRef = useRef(); - const isEndingEditWithFocus = useRef( false ); + const isEndingEditWithFocusRef = useRef( false ); const settingsKeys = settings.map( ( { id } ) => id ); @@ -219,7 +219,7 @@ function LinkControl( { // We don't auto focus into the Link UI on mount // because otherwise using the keyboard to select text // *within* the link format is not possible. - if ( isMounting.current ) { + if ( isMountingRef.current ) { return; } @@ -234,16 +234,16 @@ function LinkControl( { nextFocusTarget.focus(); - isEndingEditWithFocus.current = false; + isEndingEditWithFocusRef.current = false; }, [ isEditingLink, isCreatingPage ] ); // The component mounting reference is maintained separately // to correctly reset values in `StrictMode`. useEffect( () => { - isMounting.current = false; + isMountingRef.current = false; return () => { - isMounting.current = true; + isMountingRef.current = true; }; }, [] ); @@ -254,7 +254,7 @@ function LinkControl( { * the next render, if focus was within the wrapper when editing finished. */ const stopEditing = () => { - isEndingEditWithFocus.current = !! wrapperNode.current?.contains( + isEndingEditWithFocusRef.current = !! wrapperNode.current?.contains( wrapperNode.current.ownerDocument.activeElement ); diff --git a/packages/block-editor/src/components/provider/use-block-sync.js b/packages/block-editor/src/components/provider/use-block-sync.js index 4e9cc9784554f5..fa148109d510f6 100644 --- a/packages/block-editor/src/components/provider/use-block-sync.js +++ b/packages/block-editor/src/components/provider/use-block-sync.js @@ -91,8 +91,8 @@ export default function useBlockSync( { [ clientId ] ); - const pendingChanges = useRef( { incoming: null, outgoing: [] } ); - const subscribed = useRef( false ); + const pendingChangesRef = useRef( { incoming: null, outgoing: [] } ); + const subscribedRef = useRef( false ); const setControlledBlocks = () => { if ( ! controlledBlocks ) { @@ -113,15 +113,15 @@ export default function useBlockSync( { const storeBlocks = controlledBlocks.map( ( block ) => cloneBlock( block ) ); - if ( subscribed.current ) { - pendingChanges.current.incoming = storeBlocks; + if ( subscribedRef.current ) { + pendingChangesRef.current.incoming = storeBlocks; } __unstableMarkNextChangeAsNotPersistent(); replaceInnerBlocks( clientId, storeBlocks ); } ); } else { - if ( subscribed.current ) { - pendingChanges.current.incoming = controlledBlocks; + if ( subscribedRef.current ) { + pendingChangesRef.current.incoming = controlledBlocks; } resetBlocks( controlledBlocks ); } @@ -153,7 +153,7 @@ export default function useBlockSync( { // Determine if blocks need to be reset when they change. useEffect( () => { - if ( pendingChanges.current.outgoing.includes( controlledBlocks ) ) { + if ( pendingChangesRef.current.outgoing.includes( controlledBlocks ) ) { // Skip block reset if the value matches expected outbound sync // triggered by this component by a preceding change detection. // Only skip if the value matches expectation, since a reset should @@ -161,18 +161,18 @@ export default function useBlockSync( { // to allow that the consumer may apply modifications to reflect // back on the editor. if ( - pendingChanges.current.outgoing[ - pendingChanges.current.outgoing.length - 1 + pendingChangesRef.current.outgoing[ + pendingChangesRef.current.outgoing.length - 1 ] === controlledBlocks ) { - pendingChanges.current.outgoing = []; + pendingChangesRef.current.outgoing = []; } } else if ( getBlocks( clientId ) !== controlledBlocks ) { // Reset changing value in all other cases than the sync described // above. Since this can be reached in an update following an out- // bound sync, unset the outbound value to avoid considering it in // subsequent renders. - pendingChanges.current.outgoing = []; + pendingChangesRef.current.outgoing = []; setControlledBlocks(); if ( controlledSelection ) { @@ -185,19 +185,19 @@ export default function useBlockSync( { } }, [ controlledBlocks, clientId ] ); - const isMounted = useRef( false ); + const isMountedRef = useRef( false ); useEffect( () => { // On mount, controlled blocks are already set in the effect above. - if ( ! isMounted.current ) { - isMounted.current = true; + if ( ! isMountedRef.current ) { + isMountedRef.current = true; return; } // When the block becomes uncontrolled, it means its inner state has been reset // we need to take the blocks again from the external value property. if ( ! isControlled ) { - pendingChanges.current.outgoing = []; + pendingChangesRef.current.outgoing = []; setControlledBlocks(); } }, [ isControlled ] ); @@ -214,7 +214,7 @@ export default function useBlockSync( { let isPersistent = isLastBlockChangePersistent(); let previousAreBlocksDifferent = false; - subscribed.current = true; + subscribedRef.current = true; const unsubscribe = registry.subscribe( () => { // Sometimes, when changing block lists, lingering subscriptions // might trigger before they are cleaned up. If the block for which @@ -243,10 +243,10 @@ export default function useBlockSync( { blocks = newBlocks; if ( areBlocksDifferent && - ( pendingChanges.current.incoming || + ( pendingChangesRef.current.incoming || __unstableIsLastBlockChangeIgnored() ) ) { - pendingChanges.current.incoming = null; + pendingChangesRef.current.incoming = null; isPersistent = newIsPersistent; return; } @@ -266,7 +266,7 @@ export default function useBlockSync( { // We need to be aware that it was caused by an outgoing change // so that we do not treat it as an incoming change later on, // which would cause a block reset. - pendingChanges.current.outgoing.push( blocks ); + pendingChangesRef.current.outgoing.push( blocks ); // Inform the controlling entity that changes have been made to // the block-editor store they should be aware about. @@ -286,7 +286,7 @@ export default function useBlockSync( { }, blockEditorStore ); return () => { - subscribed.current = false; + subscribedRef.current = false; unsubscribe(); }; }, [ registry, clientId ] ); diff --git a/packages/block-editor/src/components/rich-text/use-mark-persistent.js b/packages/block-editor/src/components/rich-text/use-mark-persistent.js index 10e157452fbe22..0be460fedd92fa 100644 --- a/packages/block-editor/src/components/rich-text/use-mark-persistent.js +++ b/packages/block-editor/src/components/rich-text/use-mark-persistent.js @@ -10,7 +10,7 @@ import { useDispatch } from '@wordpress/data'; import { store as blockEditorStore } from '../../store'; export function useMarkPersistent( { html, value } ) { - const previousText = useRef(); + const previousTextRef = useRef(); const hasActiveFormats = !! value.activeFormats?.length; const { __unstableMarkLastChangeAsPersistent } = useDispatch( blockEditorStore ); @@ -18,18 +18,18 @@ export function useMarkPersistent( { html, value } ) { // Must be set synchronously to make sure it applies to the last change. useLayoutEffect( () => { // Ignore mount. - if ( ! previousText.current ) { - previousText.current = value.text; + if ( ! previousTextRef.current ) { + previousTextRef.current = value.text; return; } // Text input, so don't create an undo level for every character. // Create an undo level after 1 second of no input. - if ( previousText.current !== value.text ) { + if ( previousTextRef.current !== value.text ) { const timeout = window.setTimeout( () => { __unstableMarkLastChangeAsPersistent(); }, 1000 ); - previousText.current = value.text; + previousTextRef.current = value.text; return () => { window.clearTimeout( timeout ); }; diff --git a/packages/block-editor/src/components/writing-flow/use-tab-nav.js b/packages/block-editor/src/components/writing-flow/use-tab-nav.js index 1394fbbd37e258..b321d7c8d29957 100644 --- a/packages/block-editor/src/components/writing-flow/use-tab-nav.js +++ b/packages/block-editor/src/components/writing-flow/use-tab-nav.js @@ -36,12 +36,12 @@ export default function useTabNav() { // Reference that holds the a flag for enabling or disabling // capturing on the focus capture elements. - const noCapture = useRef(); + const noCaptureRef = useRef(); function onFocusCapture( event ) { // Do not capture incoming focus if set by us in WritingFlow. - if ( noCapture.current ) { - noCapture.current = null; + if ( noCaptureRef.current ) { + noCaptureRef.current = null; } else if ( hasMultiSelection() ) { container.current.focus(); } else if ( getSelectedBlockClientId() ) { @@ -165,7 +165,7 @@ export default function useTabNav() { // Disable focus capturing on the focus capture element, so it // doesn't refocus this block and so it allows default behaviour // (moving focus to the next tabbable element). - noCapture.current = true; + noCaptureRef.current = true; // Focusing the focus capture element, which is located above and // below the editor, should not scroll the page all the way up or diff --git a/packages/block-editor/src/hooks/spacing-visualizer.js b/packages/block-editor/src/hooks/spacing-visualizer.js index 52141d87be7150..2f0abe8e0d293d 100644 --- a/packages/block-editor/src/hooks/spacing-visualizer.js +++ b/packages/block-editor/src/hooks/spacing-visualizer.js @@ -36,16 +36,16 @@ function SpacingVisualizer( { clientId, value, computeStyle, forceShow } ) { ); }, [ blockElement, value ] ); - const previousValue = useRef( value ); + const previousValueRef = useRef( value ); const [ isActive, setIsActive ] = useState( false ); useEffect( () => { - if ( isShallowEqual( value, previousValue.current ) || forceShow ) { + if ( isShallowEqual( value, previousValueRef.current ) || forceShow ) { return; } setIsActive( true ); - previousValue.current = value; + previousValueRef.current = value; const timeout = setTimeout( () => { setIsActive( false ); diff --git a/packages/block-editor/src/hooks/use-zoom-out.js b/packages/block-editor/src/hooks/use-zoom-out.js index d0d7d0fd4d71c7..d7e21ec1be0578 100644 --- a/packages/block-editor/src/hooks/use-zoom-out.js +++ b/packages/block-editor/src/hooks/use-zoom-out.js @@ -18,22 +18,22 @@ export function useZoomOut( zoomOut = true ) { const { __unstableSetEditorMode } = useDispatch( blockEditorStore ); const { __unstableGetEditorMode } = useSelect( blockEditorStore ); - const originalEditingMode = useRef( null ); + const originalEditingModeRef = useRef( null ); const mode = __unstableGetEditorMode(); useEffect( () => { // Only set this on mount so we know what to return to when we unmount. - if ( ! originalEditingMode.current ) { - originalEditingMode.current = mode; + if ( ! originalEditingModeRef.current ) { + originalEditingModeRef.current = mode; } return () => { // We need to use __unstableGetEditorMode() here and not `mode`, as mode may not update on unmount if ( __unstableGetEditorMode() === 'zoom-out' && - __unstableGetEditorMode() !== originalEditingMode.current + __unstableGetEditorMode() !== originalEditingModeRef.current ) { - __unstableSetEditorMode( originalEditingMode.current ); + __unstableSetEditorMode( originalEditingModeRef.current ); } }; }, [] ); @@ -45,9 +45,9 @@ export function useZoomOut( zoomOut = true ) { } else if ( ! zoomOut && __unstableGetEditorMode() === 'zoom-out' && - originalEditingMode.current !== mode + originalEditingModeRef.current !== mode ) { - __unstableSetEditorMode( originalEditingMode.current ); + __unstableSetEditorMode( originalEditingModeRef.current ); } }, [ __unstableGetEditorMode, __unstableSetEditorMode, zoomOut ] ); // Mode is deliberately excluded from the dependencies so that the effect does not run when mode changes. } diff --git a/packages/block-library/src/freeform/edit.js b/packages/block-library/src/freeform/edit.js index 9e432992a30054..b0ba245a6e7021 100644 --- a/packages/block-library/src/freeform/edit.js +++ b/packages/block-library/src/freeform/edit.js @@ -75,10 +75,10 @@ function ClassicEdit( { onReplace, } ) { const { getMultiSelectedBlockClientIds } = useSelect( blockEditorStore ); - const didMount = useRef( false ); + const didMountRef = useRef( false ); useEffect( () => { - if ( ! didMount.current ) { + if ( ! didMountRef.current ) { return; } @@ -96,7 +96,7 @@ function ClassicEdit( { useEffect( () => { const { baseURL, suffix } = window.wpEditorL10n.tinymce; - didMount.current = true; + didMountRef.current = true; window.tinymce.EditorManager.overrideDefaults( { base_url: baseURL, @@ -230,7 +230,7 @@ function ClassicEdit( { onReadyStateChange ); wp.oldEditor.remove( `editor-${ clientId }` ); - didMount.current = false; + didMountRef.current = false; }; }, [] ); diff --git a/packages/block-library/src/navigation/edit/unsaved-inner-blocks.js b/packages/block-library/src/navigation/edit/unsaved-inner-blocks.js index e5afbc66dd8b55..6cdcaa46f2bac3 100644 --- a/packages/block-library/src/navigation/edit/unsaved-inner-blocks.js +++ b/packages/block-library/src/navigation/edit/unsaved-inner-blocks.js @@ -20,13 +20,13 @@ export default function UnsavedInnerBlocks( { createNavigationMenu, hasSelection, } ) { - const originalBlocks = useRef(); + const originalBlocksRef = useRef(); useEffect( () => { // Initially store the uncontrolled inner blocks for // dirty state comparison. - if ( ! originalBlocks?.current ) { - originalBlocks.current = blocks; + if ( ! originalBlocksRef?.current ) { + originalBlocksRef.current = blocks; } }, [ blocks ] ); @@ -38,7 +38,7 @@ export default function UnsavedInnerBlocks( { // entity records. As a result we need to perform a deep equality check skipping // the page list's inner blocks. const innerBlocksAreDirty = areBlocksDirty( - originalBlocks?.current, + originalBlocksRef?.current, blocks ); diff --git a/packages/block-library/src/social-links/edit.js b/packages/block-library/src/social-links/edit.js index bea4a4e6721ec6..1bd943de7fb8e7 100644 --- a/packages/block-library/src/social-links/edit.js +++ b/packages/block-library/src/social-links/edit.js @@ -59,10 +59,10 @@ export function SocialLinksEdit( props ) { // Remove icon background color when logos only style is selected or // restore it when any other style is selected. - const backgroundBackup = useRef( {} ); + const backgroundBackupRef = useRef( {} ); useEffect( () => { if ( logosOnly ) { - backgroundBackup.current = { + backgroundBackupRef.current = { iconBackgroundColor, iconBackgroundColorValue, customIconBackgroundColor, @@ -73,7 +73,7 @@ export function SocialLinksEdit( props ) { iconBackgroundColorValue: undefined, } ); } else { - setAttributes( { ...backgroundBackup.current } ); + setAttributes( { ...backgroundBackupRef.current } ); } }, [ logosOnly ] ); diff --git a/packages/block-library/src/utils/hooks.js b/packages/block-library/src/utils/hooks.js index f9ad52297c53e1..61515306e8bfd1 100644 --- a/packages/block-library/src/utils/hooks.js +++ b/packages/block-library/src/utils/hooks.js @@ -37,36 +37,36 @@ export function useCanEditEntity( kind, name, recordId ) { * @param {Function} args.onError Function called when an error happens. */ export function useUploadMediaFromBlobURL( args = {} ) { - const latestArgs = useRef( args ); - const hasUploadStarted = useRef( false ); + const latestArgsRef = useRef( args ); + const hasUploadStartedRef = useRef( false ); const { getSettings } = useSelect( blockEditorStore ); useLayoutEffect( () => { - latestArgs.current = args; + latestArgsRef.current = args; } ); useEffect( () => { // Uploading is a special effect that can't be canceled via the cleanup method. // The extra check avoids duplicate uploads in development mode (React.StrictMode). - if ( hasUploadStarted.current ) { + if ( hasUploadStartedRef.current ) { return; } if ( - ! latestArgs.current.url || - ! isBlobURL( latestArgs.current.url ) + ! latestArgsRef.current.url || + ! isBlobURL( latestArgsRef.current.url ) ) { return; } - const file = getBlobByURL( latestArgs.current.url ); + const file = getBlobByURL( latestArgsRef.current.url ); if ( ! file ) { return; } - const { url, allowedTypes, onChange, onError } = latestArgs.current; + const { url, allowedTypes, onChange, onError } = latestArgsRef.current; const { mediaUpload } = getSettings(); - hasUploadStarted.current = true; + hasUploadStartedRef.current = true; mediaUpload( { filesList: [ file ], @@ -78,12 +78,12 @@ export function useUploadMediaFromBlobURL( args = {} ) { revokeBlobURL( url ); onChange( media ); - hasUploadStarted.current = false; + hasUploadStartedRef.current = false; }, onError: ( message ) => { revokeBlobURL( url ); onError( message ); - hasUploadStarted.current = false; + hasUploadStartedRef.current = false; }, } ); }, [ getSettings ] ); diff --git a/packages/commands/src/components/command-menu.js b/packages/commands/src/components/command-menu.js index ac305246fefb70..55f78ac02c655b 100644 --- a/packages/commands/src/components/command-menu.js +++ b/packages/commands/src/components/command-menu.js @@ -79,11 +79,11 @@ export function CommandMenuLoaderWrapper( { hook, search, setLoader, close } ) { // the CommandMenuLoaderWrapper component need to be // remounted on each hook prop change // We use the key state to make sure we do that properly. - const currentLoader = useRef( hook ); + const currentLoaderRef = useRef( hook ); const [ key, setKey ] = useState( 0 ); useEffect( () => { - if ( currentLoader.current !== hook ) { - currentLoader.current = hook; + if ( currentLoaderRef.current !== hook ) { + currentLoaderRef.current = hook; setKey( ( prevKey ) => prevKey + 1 ); } }, [ hook ] ); @@ -91,7 +91,7 @@ export function CommandMenuLoaderWrapper( { hook, search, setLoader, close } ) { return ( <CommandMenuLoader key={ key } - hook={ currentLoader.current } + hook={ currentLoaderRef.current } search={ search } setLoader={ setLoader } close={ close } diff --git a/packages/commands/src/hooks/use-command.js b/packages/commands/src/hooks/use-command.js index 416ffbd7f73c68..32ff6336a7d467 100644 --- a/packages/commands/src/hooks/use-command.js +++ b/packages/commands/src/hooks/use-command.js @@ -32,9 +32,9 @@ import { store as commandsStore } from '../store'; */ export default function useCommand( command ) { const { registerCommand, unregisterCommand } = useDispatch( commandsStore ); - const currentCallback = useRef( command.callback ); + const currentCallbackRef = useRef( command.callback ); useEffect( () => { - currentCallback.current = command.callback; + currentCallbackRef.current = command.callback; }, [ command.callback ] ); useEffect( () => { @@ -47,7 +47,7 @@ export default function useCommand( command ) { label: command.label, searchLabel: command.searchLabel, icon: command.icon, - callback: ( ...args ) => currentCallback.current( ...args ), + callback: ( ...args ) => currentCallbackRef.current( ...args ), } ); return () => { unregisterCommand( command.name ); diff --git a/packages/components/src/angle-picker-control/angle-circle.tsx b/packages/components/src/angle-picker-control/angle-circle.tsx index 8558b23279302d..52a2d2838a1f26 100644 --- a/packages/components/src/angle-picker-control/angle-circle.tsx +++ b/packages/components/src/angle-picker-control/angle-circle.tsx @@ -28,8 +28,10 @@ function AngleCircle( { ...props }: WordPressComponentProps< AngleCircleProps, 'div' > ) { const angleCircleRef = useRef< HTMLDivElement | null >( null ); - const angleCircleCenter = useRef< { x: number; y: number } | undefined >(); - const previousCursorValue = useRef< CSSStyleDeclaration[ 'cursor' ] >(); + const angleCircleCenterRef = useRef< + { x: number; y: number } | undefined + >(); + const previousCursorValueRef = useRef< CSSStyleDeclaration[ 'cursor' ] >(); const setAngleCircleCenter = () => { if ( angleCircleRef.current === null ) { @@ -37,7 +39,7 @@ function AngleCircle( { } const rect = angleCircleRef.current.getBoundingClientRect(); - angleCircleCenter.current = { + angleCircleCenterRef.current = { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2, }; @@ -55,10 +57,10 @@ function AngleCircle( { ( event.target as HTMLDivElement | null )?.focus(); if ( - angleCircleCenter.current !== undefined && + angleCircleCenterRef.current !== undefined && onChange !== undefined ) { - const { x: centerX, y: centerY } = angleCircleCenter.current; + const { x: centerX, y: centerY } = angleCircleCenterRef.current; onChange( getAngle( centerX, centerY, event.clientX, event.clientY ) ); @@ -76,13 +78,13 @@ function AngleCircle( { useEffect( () => { if ( isDragging ) { - if ( previousCursorValue.current === undefined ) { - previousCursorValue.current = document.body.style.cursor; + if ( previousCursorValueRef.current === undefined ) { + previousCursorValueRef.current = document.body.style.cursor; } document.body.style.cursor = 'grabbing'; } else { - document.body.style.cursor = previousCursorValue.current || ''; - previousCursorValue.current = undefined; + document.body.style.cursor = previousCursorValueRef.current || ''; + previousCursorValueRef.current = undefined; } }, [ isDragging ] ); diff --git a/packages/components/src/clipboard-button/index.tsx b/packages/components/src/clipboard-button/index.tsx index 2f66b97a5a00ff..0bf7d177e251ef 100644 --- a/packages/components/src/clipboard-button/index.tsx +++ b/packages/components/src/clipboard-button/index.tsx @@ -32,21 +32,21 @@ export default function ClipboardButton( { alternative: 'wp.compose.useCopyToClipboard', } ); - const timeoutId = useRef< NodeJS.Timeout >(); + const timeoutIdRef = useRef< NodeJS.Timeout >(); const ref = useCopyToClipboard( text, () => { onCopy(); - if ( timeoutId.current ) { - clearTimeout( timeoutId.current ); + if ( timeoutIdRef.current ) { + clearTimeout( timeoutIdRef.current ); } if ( onFinishCopy ) { - timeoutId.current = setTimeout( () => onFinishCopy(), TIMEOUT ); + timeoutIdRef.current = setTimeout( () => onFinishCopy(), TIMEOUT ); } } ); useEffect( () => { - if ( timeoutId.current ) { - clearTimeout( timeoutId.current ); + if ( timeoutIdRef.current ) { + clearTimeout( timeoutIdRef.current ); } }, [] ); diff --git a/packages/components/src/color-picker/color-copy-button.tsx b/packages/components/src/color-picker/color-copy-button.tsx index 11ff7ca52de788..b8a4822544322c 100644 --- a/packages/components/src/color-picker/color-copy-button.tsx +++ b/packages/components/src/color-picker/color-copy-button.tsx @@ -17,7 +17,9 @@ import type { ColorCopyButtonProps } from './types'; export const ColorCopyButton = ( props: ColorCopyButtonProps ) => { const { color, colorType } = props; const [ copiedColor, setCopiedColor ] = useState< string | null >( null ); - const copyTimer = useRef< ReturnType< typeof setTimeout > | undefined >(); + const copyTimerRef = useRef< + ReturnType< typeof setTimeout > | undefined + >(); const copyRef = useCopyToClipboard< HTMLDivElement >( () => { switch ( colorType ) { @@ -34,21 +36,21 @@ export const ColorCopyButton = ( props: ColorCopyButtonProps ) => { } }, () => { - if ( copyTimer.current ) { - clearTimeout( copyTimer.current ); + if ( copyTimerRef.current ) { + clearTimeout( copyTimerRef.current ); } setCopiedColor( color.toHex() ); - copyTimer.current = setTimeout( () => { + copyTimerRef.current = setTimeout( () => { setCopiedColor( null ); - copyTimer.current = undefined; + copyTimerRef.current = undefined; }, 3000 ); } ); useEffect( () => { - // Clear copyTimer on component unmount. + // Clear copyTimerRef on component unmount. return () => { - if ( copyTimer.current ) { - clearTimeout( copyTimer.current ); + if ( copyTimerRef.current ) { + clearTimeout( copyTimerRef.current ); } }; }, [] ); diff --git a/packages/components/src/custom-gradient-picker/gradient-bar/control-points.tsx b/packages/components/src/custom-gradient-picker/gradient-bar/control-points.tsx index e3620655aee1aa..a92e973d88c5a8 100644 --- a/packages/components/src/custom-gradient-picker/gradient-bar/control-points.tsx +++ b/packages/components/src/custom-gradient-picker/gradient-bar/control-points.tsx @@ -128,11 +128,11 @@ function ControlPoints( { onStopControlPointChange, __experimentalIsRenderedInSidebar, }: ControlPointsProps ) { - const controlPointMoveState = useRef< ControlPointMoveState >(); + const controlPointMoveStateRef = useRef< ControlPointMoveState >(); const onMouseMove = ( event: MouseEvent ) => { if ( - controlPointMoveState.current === undefined || + controlPointMoveStateRef.current === undefined || gradientPickerDomRef.current === null ) { return; @@ -144,14 +144,14 @@ function ControlPoints( { ); const { initialPosition, index, significantMoveHappened } = - controlPointMoveState.current; + controlPointMoveStateRef.current; if ( ! significantMoveHappened && Math.abs( initialPosition - relativePosition ) >= MINIMUM_SIGNIFICANT_MOVE ) { - controlPointMoveState.current.significantMoveHappened = true; + controlPointMoveStateRef.current.significantMoveHappened = true; } onChange( @@ -163,13 +163,13 @@ function ControlPoints( { if ( window && window.removeEventListener && - controlPointMoveState.current && - controlPointMoveState.current.listenersActivated + controlPointMoveStateRef.current && + controlPointMoveStateRef.current.listenersActivated ) { window.removeEventListener( 'mousemove', onMouseMove ); window.removeEventListener( 'mouseup', cleanEventListeners ); onStopControlPointChange(); - controlPointMoveState.current.listenersActivated = false; + controlPointMoveStateRef.current.listenersActivated = false; } }; @@ -202,8 +202,8 @@ function ControlPoints( { key={ index } onClick={ () => { if ( - controlPointMoveState.current && - controlPointMoveState.current + controlPointMoveStateRef.current && + controlPointMoveStateRef.current .significantMoveHappened ) { return; @@ -220,7 +220,7 @@ function ControlPoints( { window && window.addEventListener ) { - controlPointMoveState.current = { + controlPointMoveStateRef.current = { initialPosition, index, significantMoveHappened: false, diff --git a/packages/components/src/draggable/index.tsx b/packages/components/src/draggable/index.tsx index 0a3000538dbf24..b9dea8fed43061 100644 --- a/packages/components/src/draggable/index.tsx +++ b/packages/components/src/draggable/index.tsx @@ -71,7 +71,7 @@ export function Draggable( { __experimentalDragComponent: dragComponent, }: DraggableProps ) { const dragComponentRef = useRef< HTMLDivElement >( null ); - const cleanup = useRef( () => {} ); + const cleanupRef = useRef( () => {} ); /** * Removes the element clone, resets cursor, and removes drag listener. @@ -80,7 +80,7 @@ export function Draggable( { */ function end( event: DragEvent ) { event.preventDefault(); - cleanup.current(); + cleanupRef.current(); if ( onDragEnd ) { onDragEnd( event ); @@ -216,7 +216,7 @@ export function Draggable( { onDragStart( event ); } - cleanup.current = () => { + cleanupRef.current = () => { // Remove drag clone. if ( cloneWrapper && cloneWrapper.parentNode ) { cloneWrapper.parentNode.removeChild( cloneWrapper ); @@ -235,7 +235,7 @@ export function Draggable( { useEffect( () => () => { - cleanup.current(); + cleanupRef.current(); }, [] ); diff --git a/packages/components/src/input-control/reducer/reducer.ts b/packages/components/src/input-control/reducer/reducer.ts index 8e3584d3910d74..51e54d6492f5c5 100644 --- a/packages/components/src/input-control/reducer/reducer.ts +++ b/packages/components/src/input-control/reducer/reducer.ts @@ -192,25 +192,28 @@ export function useInputControlStateReducer( const pressDown = createKeyEvent( actions.PRESS_DOWN ); const pressEnter = createKeyEvent( actions.PRESS_ENTER ); - const currentState = useRef( state ); - const refProps = useRef( { value: initialState.value, onChangeHandler } ); + const currentStateRef = useRef( state ); + const refPropsRef = useRef( { + value: initialState.value, + onChangeHandler, + } ); // Freshens refs to props and state so that subsequent effects have access // to their latest values without their changes causing effect runs. useLayoutEffect( () => { - currentState.current = state; - refProps.current = { value: initialState.value, onChangeHandler }; + currentStateRef.current = state; + refPropsRef.current = { value: initialState.value, onChangeHandler }; } ); // Propagates the latest state through onChange. useLayoutEffect( () => { if ( - currentState.current._event !== undefined && - state.value !== refProps.current.value && + currentStateRef.current._event !== undefined && + state.value !== refPropsRef.current.value && ! state.isDirty ) { - refProps.current.onChangeHandler( state.value ?? '', { - event: currentState.current._event as + refPropsRef.current.onChangeHandler( state.value ?? '', { + event: currentStateRef.current._event as | ChangeEvent< HTMLInputElement > | PointerEvent< HTMLInputElement >, } ); @@ -220,8 +223,8 @@ export function useInputControlStateReducer( // Updates the state from props. useLayoutEffect( () => { if ( - initialState.value !== currentState.current.value && - ! currentState.current.isDirty + initialState.value !== currentStateRef.current.value && + ! currentStateRef.current.isDirty ) { dispatch( { type: actions.CONTROL, diff --git a/packages/components/src/input-control/utils.ts b/packages/components/src/input-control/utils.ts index 7e3eb939808000..5bc42312af1f5d 100644 --- a/packages/components/src/input-control/utils.ts +++ b/packages/components/src/input-control/utils.ts @@ -73,7 +73,7 @@ export function useDraft( props: { onBlur?: FocusEventHandler; onChange: InputChangeCallback; } ) { - const refPreviousValue = useRef( props.value ); + const previousValueRef = useRef( props.value ); const [ draft, setDraft ] = useState< { value?: string; isStale?: boolean; @@ -84,8 +84,8 @@ export function useDraft( props: { // To do so, it tracks the previous value and marks the draft value as stale // after each render. useLayoutEffect( () => { - const { current: previousValue } = refPreviousValue; - refPreviousValue.current = props.value; + const { current: previousValue } = previousValueRef; + previousValueRef.current = props.value; if ( draft.value !== undefined && ! draft.isStale ) { setDraft( { ...draft, isStale: true } ); } else if ( draft.isStale && props.value !== previousValue ) { diff --git a/packages/components/src/modal/index.tsx b/packages/components/src/modal/index.tsx index b18217cdbaadcb..e1f103b98c2735 100644 --- a/packages/components/src/modal/index.tsx +++ b/packages/components/src/modal/index.tsx @@ -134,9 +134,9 @@ function UnforwardedModal( }, [] ); // Keeps a fresh ref for the subsequent effect. - const refOnRequestClose = useRef< ModalProps[ 'onRequestClose' ] >(); + const onRequestCloseRef = useRef< ModalProps[ 'onRequestClose' ] >(); useEffect( () => { - refOnRequestClose.current = onRequestClose; + onRequestCloseRef.current = onRequestClose; }, [ onRequestClose ] ); // The list of `onRequestClose` callbacks of open (non-nested) Modals. Only @@ -149,10 +149,10 @@ function UnforwardedModal( // onRequestClose for any prior and/or nested modals as applicable. useEffect( () => { // add this modal instance to the dismissers set - dismissers.add( refOnRequestClose ); + dismissers.add( onRequestCloseRef ); // request that all the other modals close themselves for ( const dismisser of dismissers ) { - if ( dismisser !== refOnRequestClose ) { + if ( dismisser !== onRequestCloseRef ) { dismisser.current?.(); } } @@ -162,7 +162,7 @@ function UnforwardedModal( dismisser.current?.(); } // remove this modal instance from the dismissers set - dismissers.delete( refOnRequestClose ); + dismissers.delete( onRequestCloseRef ); }; }, [ dismissers, nestedDismissers ] ); diff --git a/packages/components/src/navigation/index.tsx b/packages/components/src/navigation/index.tsx index b1c12f59e27a99..0069369f3e00cb 100644 --- a/packages/components/src/navigation/index.tsx +++ b/packages/components/src/navigation/index.tsx @@ -93,10 +93,10 @@ export function Navigation( { }; // Used to prevent the sliding animation on mount - const isMounted = useRef( false ); + const isMountedRef = useRef( false ); useEffect( () => { - if ( ! isMounted.current ) { - isMounted.current = true; + if ( ! isMountedRef.current ) { + isMountedRef.current = true; } }, [] ); @@ -130,7 +130,7 @@ export function Navigation( { animateClassName ? clsx( { [ animateClassName ]: - isMounted.current && slideOrigin, + isMountedRef.current && slideOrigin, } ) : undefined } diff --git a/packages/components/src/palette-edit/index.tsx b/packages/components/src/palette-edit/index.tsx index 05866e0ee05647..601ea758b75bba 100644 --- a/packages/components/src/palette-edit/index.tsx +++ b/packages/components/src/palette-edit/index.tsx @@ -275,9 +275,9 @@ function PaletteEditListView< T extends Color | Gradient >( { addColorRef, }: PaletteEditListViewProps< T > ) { // When unmounting the component if there are empty elements (the user did not complete the insertion) clean them. - const elementsReference = useRef< typeof elements >(); + const elementsReferenceRef = useRef< typeof elements >(); useEffect( () => { - elementsReference.current = elements; + elementsReferenceRef.current = elements; }, [ elements ] ); const debounceOnChange = useDebounce( onChange, 100 ); diff --git a/packages/components/src/slot-fill/bubbles-virtually/fill.tsx b/packages/components/src/slot-fill/bubbles-virtually/fill.tsx index 083d7302992dde..3cfadbadc62c4b 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/fill.tsx +++ b/packages/components/src/slot-fill/bubbles-virtually/fill.tsx @@ -12,17 +12,17 @@ import type { FillComponentProps } from '../types'; function useForceUpdate() { const [ , setState ] = useState( {} ); - const mounted = useRef( true ); + const mountedRef = useRef( true ); useEffect( () => { - mounted.current = true; + mountedRef.current = true; return () => { - mounted.current = false; + mountedRef.current = false; }; }, [] ); return () => { - if ( mounted.current ) { + if ( mountedRef.current ) { setState( {} ); } }; diff --git a/packages/components/src/snackbar/index.tsx b/packages/components/src/snackbar/index.tsx index 5bd44d8aace336..0f2b74caca7d4a 100644 --- a/packages/components/src/snackbar/index.tsx +++ b/packages/components/src/snackbar/index.tsx @@ -96,17 +96,17 @@ function UnforwardedSnackbar( // The `onDismiss/onRemove` can have unstable references, // trigger side-effect cleanup, and reset timers. - const callbackRefs = useRef( { onDismiss, onRemove } ); + const callbacksRef = useRef( { onDismiss, onRemove } ); useLayoutEffect( () => { - callbackRefs.current = { onDismiss, onRemove }; + callbacksRef.current = { onDismiss, onRemove }; } ); useEffect( () => { // Only set up the timeout dismiss if we're not explicitly dismissing. const timeoutHandle = setTimeout( () => { if ( ! explicitDismiss ) { - callbackRefs.current.onDismiss?.(); - callbackRefs.current.onRemove?.(); + callbacksRef.current.onDismiss?.(); + callbacksRef.current.onRemove?.(); } }, NOTICE_TIMEOUT ); diff --git a/packages/components/src/tabs/index.tsx b/packages/components/src/tabs/index.tsx index ef8978b647a904..ca8c5b19bcd622 100644 --- a/packages/components/src/tabs/index.tsx +++ b/packages/components/src/tabs/index.tsx @@ -55,9 +55,9 @@ function Tabs( { // Keep track of whether tabs have been populated. This is used to prevent // certain effects from firing too early while tab data and relevant // variables are undefined during the initial render. - const tabsHavePopulated = useRef( false ); + const tabsHavePopulatedRef = useRef( false ); if ( items.length > 0 ) { - tabsHavePopulated.current = true; + tabsHavePopulatedRef.current = true; } const selectedTab = items.find( ( item ) => item.id === selectedId ); @@ -94,7 +94,7 @@ function Tabs( { if ( firstEnabledTab ) { setSelectedId( firstEnabledTab.id ); - } else if ( tabsHavePopulated.current ) { + } else if ( tabsHavePopulatedRef.current ) { setSelectedId( null ); } } @@ -148,7 +148,11 @@ function Tabs( { // Once the tabs have populated, if the `selectedTabId` still can't be // found, clear the selection. - if ( tabsHavePopulated.current && !! selectedTabId && ! selectedTab ) { + if ( + tabsHavePopulatedRef.current && + !! selectedTabId && + ! selectedTab + ) { setSelectedId( null ); } }, [ isControlled, selectedTab, selectedTabId, setSelectedId ] ); diff --git a/packages/components/src/toggle-group-control/toggle-group-control/utils.ts b/packages/components/src/toggle-group-control/toggle-group-control/utils.ts index fe2b84c5b81231..0cc6dcd743b119 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/utils.ts +++ b/packages/components/src/toggle-group-control/toggle-group-control/utils.ts @@ -21,23 +21,23 @@ type ValueProp = ToggleGroupControlProps[ 'value' ]; export function useComputeControlledOrUncontrolledValue( valueProp: ValueProp ): { value: ValueProp; defaultValue: ValueProp } { - const isInitialRender = useRef( true ); + const isInitialRenderRef = useRef( true ); const prevValueProp = usePrevious( valueProp ); - const prevIsControlled = useRef( false ); + const prevIsControlledRef = useRef( false ); useEffect( () => { - if ( isInitialRender.current ) { - isInitialRender.current = false; + if ( isInitialRenderRef.current ) { + isInitialRenderRef.current = false; } }, [] ); // Assume the component is being used in controlled mode on the first re-render // that has a different `valueProp` from the previous render. const isControlled = - prevIsControlled.current || - ( ! isInitialRender.current && prevValueProp !== valueProp ); + prevIsControlledRef.current || + ( ! isInitialRenderRef.current && prevValueProp !== valueProp ); useEffect( () => { - prevIsControlled.current = isControlled; + prevIsControlledRef.current = isControlled; }, [ isControlled ] ); if ( isControlled ) { diff --git a/packages/components/src/tools-panel/tools-panel/hook.ts b/packages/components/src/tools-panel/tools-panel/hook.ts index 8742f1c494ce1b..931bf2494e6e34 100644 --- a/packages/components/src/tools-panel/tools-panel/hook.ts +++ b/packages/components/src/tools-panel/tools-panel/hook.ts @@ -94,16 +94,16 @@ export function useToolsPanel( ...otherProps } = useContextSystem( props, 'ToolsPanel' ); - const isResetting = useRef( false ); - const wasResetting = isResetting.current; + const isResettingRef = useRef( false ); + const wasResetting = isResettingRef.current; - // `isResetting` is cleared via this hook to effectively batch together + // `isResettingRef` is cleared via this hook to effectively batch together // the resetAll task. Without this, the flag is cleared after the first // control updates and forces a rerender with subsequent controls then // believing they need to reset, unfortunately using stale data. useEffect( () => { if ( wasResetting ) { - isResetting.current = false; + isResettingRef.current = false; } }, [ wasResetting ] ); @@ -303,7 +303,7 @@ export function useToolsPanel( // Resets display of children and executes resetAll callback if available. const resetAllItems = useCallback( () => { if ( typeof resetAll === 'function' ) { - isResetting.current = true; + isResettingRef.current = true; resetAll( resetAllFilters ); } @@ -340,7 +340,7 @@ export function useToolsPanel( firstDisplayedItem, flagItemCustomization, hasMenuItems: !! panelItems.length, - isResetting: isResetting.current, + isResetting: isResettingRef.current, lastDisplayedItem, menuItems, panelId, diff --git a/packages/components/src/utils/hooks/use-update-effect.js b/packages/components/src/utils/hooks/use-update-effect.js index d49ca951cdcff9..ed2c3ca4363579 100644 --- a/packages/components/src/utils/hooks/use-update-effect.js +++ b/packages/components/src/utils/hooks/use-update-effect.js @@ -12,12 +12,12 @@ import { useRef, useEffect } from '@wordpress/element'; * @param {import('react').DependencyList} deps */ function useUpdateEffect( effect, deps ) { - const mounted = useRef( false ); + const mountedRef = useRef( false ); useEffect( () => { - if ( mounted.current ) { + if ( mountedRef.current ) { return effect(); } - mounted.current = true; + mountedRef.current = true; return undefined; // Disable reasons: // 1. This hook needs to pass a dep list that isn't an array literal @@ -28,7 +28,7 @@ function useUpdateEffect( effect, deps ) { useEffect( () => () => { - mounted.current = false; + mountedRef.current = false; }, [] ); diff --git a/packages/compose/src/hooks/use-copy-on-click/index.js b/packages/compose/src/hooks/use-copy-on-click/index.js index 383be2b957342c..eab34045f3c21a 100644 --- a/packages/compose/src/hooks/use-copy-on-click/index.js +++ b/packages/compose/src/hooks/use-copy-on-click/index.js @@ -31,7 +31,7 @@ export default function useCopyOnClick( ref, text, timeout = 4000 ) { } ); /** @type {import('react').MutableRefObject<Clipboard | undefined>} */ - const clipboard = useRef(); + const clipboardRef = useRef(); const [ hasCopied, setHasCopied ] = useState( false ); useEffect( () => { @@ -43,11 +43,11 @@ export default function useCopyOnClick( ref, text, timeout = 4000 ) { } // Clipboard listens to click events. - clipboard.current = new Clipboard( ref.current, { + clipboardRef.current = new Clipboard( ref.current, { text: () => ( typeof text === 'function' ? text() : text ), } ); - clipboard.current.on( 'success', ( { clearSelection, trigger } ) => { + clipboardRef.current.on( 'success', ( { clearSelection, trigger } ) => { // Clearing selection will move focus back to the triggering button, // ensuring that it is not reset to the body, and further that it is // kept within the rendered node. @@ -66,8 +66,8 @@ export default function useCopyOnClick( ref, text, timeout = 4000 ) { } ); return () => { - if ( clipboard.current ) { - clipboard.current.destroy(); + if ( clipboardRef.current ) { + clipboardRef.current.destroy(); } clearTimeout( timeoutId ); }; diff --git a/packages/compose/src/hooks/use-focus-on-mount/index.js b/packages/compose/src/hooks/use-focus-on-mount/index.js index db1f2dcdbe3ead..77bee27772d2d0 100644 --- a/packages/compose/src/hooks/use-focus-on-mount/index.js +++ b/packages/compose/src/hooks/use-focus-on-mount/index.js @@ -49,7 +49,7 @@ export default function useFocusOnMount( focusOnMount = 'firstElement' ) { }; /** @type {import('react').MutableRefObject<ReturnType<setTimeout> | undefined>} */ - const timerId = useRef(); + const timerIdRef = useRef(); useEffect( () => { focusOnMountRef.current = focusOnMount; @@ -65,7 +65,7 @@ export default function useFocusOnMount( focusOnMount = 'firstElement' ) { } if ( focusOnMountRef.current === 'firstElement' ) { - timerId.current = setTimeout( () => { + timerIdRef.current = setTimeout( () => { const firstTabbable = focus.tabbable.find( node )[ 0 ]; if ( firstTabbable ) { @@ -79,8 +79,8 @@ export default function useFocusOnMount( focusOnMount = 'firstElement' ) { setFocus( node ); return () => { - if ( timerId.current ) { - clearTimeout( timerId.current ); + if ( timerIdRef.current ) { + clearTimeout( timerIdRef.current ); } }; }, [] ); diff --git a/packages/compose/src/hooks/use-focus-outside/index.ts b/packages/compose/src/hooks/use-focus-outside/index.ts index 3d85b588a9ab3a..812621a09d21d0 100644 --- a/packages/compose/src/hooks/use-focus-outside/index.ts +++ b/packages/compose/src/hooks/use-focus-outside/index.ts @@ -71,20 +71,20 @@ type UseFocusOutsideReturn = { export default function useFocusOutside( onFocusOutside: ( ( event: React.FocusEvent ) => void ) | undefined ): UseFocusOutsideReturn { - const currentOnFocusOutside = useRef( onFocusOutside ); + const currentOnFocusOutsideRef = useRef( onFocusOutside ); useEffect( () => { - currentOnFocusOutside.current = onFocusOutside; + currentOnFocusOutsideRef.current = onFocusOutside; }, [ onFocusOutside ] ); - const preventBlurCheck = useRef( false ); + const preventBlurCheckRef = useRef( false ); - const blurCheckTimeoutId = useRef< number | undefined >(); + const blurCheckTimeoutIdRef = useRef< number | undefined >(); /** * Cancel a blur check timeout. */ const cancelBlurCheck = useCallback( () => { - clearTimeout( blurCheckTimeoutId.current ); + clearTimeout( blurCheckTimeoutIdRef.current ); }, [] ); // Cancel blur checks on unmount. @@ -116,9 +116,9 @@ export default function useFocusOutside( const isInteractionEnd = [ 'mouseup', 'touchend' ].includes( type ); if ( isInteractionEnd ) { - preventBlurCheck.current = false; + preventBlurCheckRef.current = false; } else if ( isFocusNormalizedButton( target ) ) { - preventBlurCheck.current = true; + preventBlurCheckRef.current = true; } }, [] ); @@ -135,7 +135,7 @@ export default function useFocusOutside( event.persist(); // Skip blur check if clicking button. See `normalizeButtonFocus`. - if ( preventBlurCheck.current ) { + if ( preventBlurCheckRef.current ) { return; } @@ -156,7 +156,7 @@ export default function useFocusOutside( return; } - blurCheckTimeoutId.current = setTimeout( () => { + blurCheckTimeoutIdRef.current = setTimeout( () => { // If document is not focused then focus should remain // inside the wrapped component and therefore we cancel // this blur event thereby leaving focus in place. @@ -166,8 +166,8 @@ export default function useFocusOutside( return; } - if ( 'function' === typeof currentOnFocusOutside.current ) { - currentOnFocusOutside.current( event ); + if ( 'function' === typeof currentOnFocusOutsideRef.current ) { + currentOnFocusOutsideRef.current( event ); } }, 0 ); }, [] ); diff --git a/packages/compose/src/hooks/use-keyboard-shortcut/index.js b/packages/compose/src/hooks/use-keyboard-shortcut/index.js index be27d15864633a..be3f3a2554c7f3 100644 --- a/packages/compose/src/hooks/use-keyboard-shortcut/index.js +++ b/packages/compose/src/hooks/use-keyboard-shortcut/index.js @@ -42,9 +42,9 @@ function useKeyboardShortcut( target, } = {} ) { - const currentCallback = useRef( callback ); + const currentCallbackRef = useRef( callback ); useEffect( () => { - currentCallback.current = callback; + currentCallbackRef.current = callback; }, [ callback ] ); useEffect( () => { @@ -93,7 +93,7 @@ function useKeyboardShortcut( /** @type {[e: import('mousetrap').ExtendedKeyboardEvent, combo: string]} */ ...args ) => /* eslint-enable jsdoc/valid-types */ - currentCallback.current( ...args ), + currentCallbackRef.current( ...args ), eventName ); } ); diff --git a/packages/compose/src/hooks/use-merge-refs/index.js b/packages/compose/src/hooks/use-merge-refs/index.js index f39160444c5229..ed7f4247018be1 100644 --- a/packages/compose/src/hooks/use-merge-refs/index.js +++ b/packages/compose/src/hooks/use-merge-refs/index.js @@ -71,28 +71,28 @@ function assignRef( ref, value ) { */ export default function useMergeRefs( refs ) { const element = useRef(); - const isAttached = useRef( false ); - const didElementChange = useRef( false ); + const isAttachedRef = useRef( false ); + const didElementChangeRef = useRef( false ); /* eslint-disable jsdoc/no-undefined-types */ /** @type {import('react').MutableRefObject<TRef[]>} */ /* eslint-enable jsdoc/no-undefined-types */ - const previousRefs = useRef( [] ); - const currentRefs = useRef( refs ); + const previousRefsRef = useRef( [] ); + const currentRefsRef = useRef( refs ); // Update on render before the ref callback is called, so the ref callback // always has access to the current refs. - currentRefs.current = refs; + currentRefsRef.current = refs; // If any of the refs change, call the previous ref with `null` and the new // ref with the node, except when the element changes in the same cycle, in // which case the ref callbacks will already have been called. useLayoutEffect( () => { if ( - didElementChange.current === false && - isAttached.current === true + didElementChangeRef.current === false && + isAttachedRef.current === true ) { refs.forEach( ( ref, index ) => { - const previousRef = previousRefs.current[ index ]; + const previousRef = previousRefsRef.current[ index ]; if ( ref !== previousRef ) { assignRef( previousRef, null ); assignRef( ref, element.current ); @@ -100,13 +100,13 @@ export default function useMergeRefs( refs ) { } ); } - previousRefs.current = refs; + previousRefsRef.current = refs; }, refs ); // No dependencies, must be reset after every render so ref callbacks are // correctly called after a ref change. useLayoutEffect( () => { - didElementChange.current = false; + didElementChangeRef.current = false; } ); // There should be no dependencies so that `callback` is only called when @@ -116,12 +116,14 @@ export default function useMergeRefs( refs ) { // dependency change. assignRef( element, value ); - didElementChange.current = true; - isAttached.current = value !== null; + didElementChangeRef.current = true; + isAttachedRef.current = value !== null; // When an element changes, the current ref callback should be called // with the new element and the previous one with `null`. - const refsToAssign = value ? currentRefs.current : previousRefs.current; + const refsToAssign = value + ? currentRefsRef.current + : previousRefsRef.current; // Update the latest refs. for ( const ref of refsToAssign ) { diff --git a/packages/compose/src/hooks/use-ref-effect/index.ts b/packages/compose/src/hooks/use-ref-effect/index.ts index 06d826229980c1..89cc3bc2392c21 100644 --- a/packages/compose/src/hooks/use-ref-effect/index.ts +++ b/packages/compose/src/hooks/use-ref-effect/index.ts @@ -31,12 +31,12 @@ export default function useRefEffect< TElement = Node >( callback: ( node: TElement ) => ( () => void ) | void, dependencies: DependencyList ): RefCallback< TElement | null > { - const cleanup = useRef< ( () => void ) | void >(); + const cleanupRef = useRef< ( () => void ) | void >(); return useCallback( ( node: TElement | null ) => { if ( node ) { - cleanup.current = callback( node ); - } else if ( cleanup.current ) { - cleanup.current(); + cleanupRef.current = callback( node ); + } else if ( cleanupRef.current ) { + cleanupRef.current(); } }, dependencies ); } diff --git a/packages/compose/src/hooks/use-resize-observer/index.tsx b/packages/compose/src/hooks/use-resize-observer/index.tsx index 21fcd0bff4f4d0..c8c964228edfc2 100644 --- a/packages/compose/src/hooks/use-resize-observer/index.tsx +++ b/packages/compose/src/hooks/use-resize-observer/index.tsx @@ -25,7 +25,7 @@ function useResolvedElement< T extends HTMLElement >( subscriber: ( element: T ) => SubscriberResponse, refOrElement?: T | RefObject< T > | null ): RefCallback< T > { - const callbackRefElement = useRef< T | null >( null ); + const callbackElementRef = useRef< T | null >( null ); const lastReportRef = useRef< { reporter: () => void; element: T | null; @@ -34,8 +34,8 @@ function useResolvedElement< T extends HTMLElement >( const callSubscriber = useCallback( () => { let element = null; - if ( callbackRefElement.current ) { - element = callbackRefElement.current; + if ( callbackElementRef.current ) { + element = callbackElementRef.current; } else if ( refOrElement ) { if ( refOrElement instanceof HTMLElement ) { element = refOrElement; @@ -80,7 +80,7 @@ function useResolvedElement< T extends HTMLElement >( return useCallback< RefCallback< T > >( ( element ) => { - callbackRefElement.current = element; + callbackElementRef.current = element; callSubscriber(); }, [ callSubscriber ] @@ -200,16 +200,16 @@ function useResizeObserver< T extends HTMLElement >( // In certain edge cases the RO might want to report a size change just after // the component unmounted. - const didUnmount = useRef( false ); + const didUnmountRef = useRef( false ); useEffect( () => { - didUnmount.current = false; + didUnmountRef.current = false; return () => { - didUnmount.current = true; + didUnmountRef.current = true; }; }, [] ); // Using a ref to track the previous width / height to avoid unnecessary renders. - const previous: { + const previousRef: { current: { width?: number; height?: number; @@ -270,18 +270,18 @@ function useResizeObserver< T extends HTMLElement >( : undefined; if ( - previous.current.width !== newWidth || - previous.current.height !== newHeight + previousRef.current.width !== newWidth || + previousRef.current.height !== newHeight ) { const newSize = { width: newWidth, height: newHeight, }; - previous.current.width = newWidth; - previous.current.height = newHeight; + previousRef.current.width = newWidth; + previousRef.current.height = newHeight; if ( onResizeRef.current ) { onResizeRef.current( newSize ); - } else if ( ! didUnmount.current ) { + } else if ( ! didUnmountRef.current ) { setSize( newSize ); } } diff --git a/packages/data/src/components/use-dispatch/use-dispatch-with-map.js b/packages/data/src/components/use-dispatch/use-dispatch-with-map.js index 7b595b9740eeb3..f6fce490a68871 100644 --- a/packages/data/src/components/use-dispatch/use-dispatch-with-map.js +++ b/packages/data/src/components/use-dispatch/use-dispatch-with-map.js @@ -25,14 +25,14 @@ import useRegistry from '../registry-provider/use-registry'; */ const useDispatchWithMap = ( dispatchMap, deps ) => { const registry = useRegistry(); - const currentDispatchMap = useRef( dispatchMap ); + const currentDispatchMapRef = useRef( dispatchMap ); useIsomorphicLayoutEffect( () => { - currentDispatchMap.current = dispatchMap; + currentDispatchMapRef.current = dispatchMap; } ); return useMemo( () => { - const currentDispatchProps = currentDispatchMap.current( + const currentDispatchProps = currentDispatchMapRef.current( registry.dispatch, registry ); @@ -48,7 +48,7 @@ const useDispatchWithMap = ( dispatchMap, deps ) => { return [ propName, ( ...args ) => - currentDispatchMap + currentDispatchMapRef .current( registry.dispatch, registry ) [ propName ]( ...args ), ]; diff --git a/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/index.tsx b/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/index.tsx index c25328db6a108a..09e9d5f9df8120 100644 --- a/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/index.tsx +++ b/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/index.tsx @@ -183,10 +183,10 @@ function ToolbarContent< Item >( { const [ actionInProgress, setActionInProgress ] = useState< string | null >( null ); - const buttons = useRef< JSX.Element | null >( null ); + const buttonsRef = useRef< JSX.Element | null >( null ); if ( ! actionInProgress ) { - if ( buttons.current ) { - buttons.current = null; + if ( buttonsRef.current ) { + buttonsRef.current = null; } return renderToolbarContent( selection, @@ -196,8 +196,8 @@ function ToolbarContent< Item >( { setActionInProgress, onChangeSelection ); - } else if ( ! buttons.current ) { - buttons.current = renderToolbarContent( + } else if ( ! buttonsRef.current ) { + buttonsRef.current = renderToolbarContent( selection, actionsToShow, selectedItems, @@ -206,7 +206,7 @@ function ToolbarContent< Item >( { onChangeSelection ); } - return buttons.current; + return buttonsRef.current; } function _BulkActionsToolbar() { diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index df66f225988a7d..a4adde7fb382f3 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -212,7 +212,7 @@ function TableRow< Item >( { // Will be set to true if `onTouchStart` fires. This happens before // `onClick` and can be used to exclude touchscreen devices from certain // behaviours. - const isTouchDevice = useRef( false ); + const isTouchDeviceRef = useRef( false ); const columns = view.fields || fields.map( ( f ) => f.id ); return ( @@ -225,14 +225,14 @@ function TableRow< Item >( { onMouseEnter={ handleMouseEnter } onMouseLeave={ handleMouseLeave } onTouchStart={ () => { - isTouchDevice.current = true; + isTouchDeviceRef.current = true; } } onClick={ () => { if ( ! hasPossibleBulkAction ) { return; } if ( - ! isTouchDevice.current && + ! isTouchDeviceRef.current && document.getSelection()?.type !== 'Range' ) { onChangeSelection( diff --git a/packages/edit-post/src/components/editor-initialization/listener-hooks.js b/packages/edit-post/src/components/editor-initialization/listener-hooks.js index 786be08fdca0c3..968031d59adbc3 100644 --- a/packages/edit-post/src/components/editor-initialization/listener-hooks.js +++ b/packages/edit-post/src/components/editor-initialization/listener-hooks.js @@ -24,18 +24,18 @@ export const useUpdatePostLinkListener = () => { } ), [] ); - const nodeToUpdate = useRef(); + const nodeToUpdateRef = useRef(); useEffect( () => { - nodeToUpdate.current = + nodeToUpdateRef.current = document.querySelector( VIEW_AS_PREVIEW_LINK_SELECTOR ) || document.querySelector( VIEW_AS_LINK_SELECTOR ); }, [] ); useEffect( () => { - if ( ! newPermalink || ! nodeToUpdate.current ) { + if ( ! newPermalink || ! nodeToUpdateRef.current ) { return; } - nodeToUpdate.current.setAttribute( 'href', newPermalink ); + nodeToUpdateRef.current.setAttribute( 'href', newPermalink ); }, [ newPermalink ] ); }; diff --git a/packages/edit-site/src/components/sync-state-with-url/use-sync-canvas-mode-with-url.js b/packages/edit-site/src/components/sync-state-with-url/use-sync-canvas-mode-with-url.js index 9f0c8dd9a0e11f..d9295f83ee2452 100644 --- a/packages/edit-site/src/components/sync-state-with-url/use-sync-canvas-mode-with-url.js +++ b/packages/edit-site/src/components/sync-state-with-url/use-sync-canvas-mode-with-url.js @@ -21,48 +21,51 @@ export default function useSyncCanvasModeWithURL() { [] ); const { setCanvasMode } = unlock( useDispatch( editSiteStore ) ); - const currentCanvasMode = useRef( canvasMode ); + const currentCanvasModeRef = useRef( canvasMode ); const { canvas: canvasInUrl } = params; - const currentCanvasInUrl = useRef( canvasInUrl ); - const currentUrlParams = useRef( params ); + const currentCanvasInUrlRef = useRef( canvasInUrl ); + const currentUrlParamsRef = useRef( params ); useEffect( () => { - currentUrlParams.current = params; + currentUrlParamsRef.current = params; }, [ params ] ); useEffect( () => { - currentCanvasMode.current = canvasMode; + currentCanvasModeRef.current = canvasMode; if ( canvasMode === 'init' ) { return; } if ( canvasMode === 'edit' && - currentCanvasInUrl.current !== canvasMode + currentCanvasInUrlRef.current !== canvasMode ) { history.push( { - ...currentUrlParams.current, + ...currentUrlParamsRef.current, canvas: 'edit', } ); } if ( canvasMode === 'view' && - currentCanvasInUrl.current !== undefined + currentCanvasInUrlRef.current !== undefined ) { history.push( { - ...currentUrlParams.current, + ...currentUrlParamsRef.current, canvas: undefined, } ); } }, [ canvasMode, history ] ); useEffect( () => { - currentCanvasInUrl.current = canvasInUrl; - if ( canvasInUrl !== 'edit' && currentCanvasMode.current !== 'view' ) { + currentCanvasInUrlRef.current = canvasInUrl; + if ( + canvasInUrl !== 'edit' && + currentCanvasModeRef.current !== 'view' + ) { setCanvasMode( 'view' ); } else if ( canvasInUrl === 'edit' && - currentCanvasMode.current !== 'edit' + currentCanvasModeRef.current !== 'edit' ) { setCanvasMode( 'edit' ); } diff --git a/packages/editor/src/components/document-bar/index.js b/packages/editor/src/components/document-bar/index.js index da3d886c125f42..f71cbce23fdafb 100644 --- a/packages/editor/src/components/document-bar/index.js +++ b/packages/editor/src/components/document-bar/index.js @@ -120,9 +120,9 @@ export default function DocumentBar( props ) { const title = props.title || entityTitle; const icon = props.icon || templateIcon; - const mounted = useRef( false ); + const mountedRef = useRef( false ); useEffect( () => { - mounted.current = true; + mountedRef.current = true; }, [] ); return ( @@ -143,7 +143,7 @@ export default function DocumentBar( props ) { } } size="compact" initial={ - mounted.current + mountedRef.current ? { opacity: 0, transform: 'translateX(15%)' } : false // Don't show entry animation when DocumentBar mounts. } @@ -170,7 +170,7 @@ export default function DocumentBar( props ) { // Force entry animation when the back button is added or removed. key={ hasBackButton } initial={ - mounted.current + mountedRef.current ? { opacity: 0, transform: hasBackButton diff --git a/packages/editor/src/components/local-autosave-monitor/index.js b/packages/editor/src/components/local-autosave-monitor/index.js index f999cf9ef85340..ad4e40d15d5c58 100644 --- a/packages/editor/src/components/local-autosave-monitor/index.js +++ b/packages/editor/src/components/local-autosave-monitor/index.js @@ -144,20 +144,20 @@ function useAutosavePurge() { [] ); - const lastIsDirty = useRef( isDirty ); - const lastIsAutosaving = useRef( isAutosaving ); + const lastIsDirtyRef = useRef( isDirty ); + const lastIsAutosavingRef = useRef( isAutosaving ); useEffect( () => { if ( ! didError && - ( ( lastIsAutosaving.current && ! isAutosaving ) || - ( lastIsDirty.current && ! isDirty ) ) + ( ( lastIsAutosavingRef.current && ! isAutosaving ) || + ( lastIsDirtyRef.current && ! isDirty ) ) ) { localAutosaveClear( postId, isEditedPostNew ); } - lastIsDirty.current = isDirty; - lastIsAutosaving.current = isAutosaving; + lastIsDirtyRef.current = isDirty; + lastIsAutosavingRef.current = isAutosaving; }, [ isDirty, isAutosaving, didError ] ); // Once the isEditedPostNew changes from true to false, let's clear the auto-draft autosave. diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js index 6554f7c0228a77..ef41fc087f1d2e 100644 --- a/packages/editor/src/components/preview-dropdown/index.js +++ b/packages/editor/src/components/preview-dropdown/index.js @@ -58,18 +58,18 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { /** * Save the original editing mode in a ref to restore it when we exit zoom out. */ - const originalEditingMode = useRef( editorMode ); + const originalEditingModeRef = useRef( editorMode ); useEffect( () => { if ( editorMode !== 'zoom-out' ) { - originalEditingMode.current = editorMode; + originalEditingModeRef.current = editorMode; } return () => { if ( editorMode === 'zoom-out' && - editorMode !== originalEditingMode.current + editorMode !== originalEditingModeRef.current ) { - __unstableSetEditorMode( originalEditingMode.current ); + __unstableSetEditorMode( originalEditingModeRef.current ); } }; }, [ editorMode, __unstableSetEditorMode ] ); @@ -136,7 +136,7 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { * @param {string} value The device type. */ const onSelect = ( value ) => { - let newEditorMode = originalEditingMode.current; + let newEditorMode = originalEditingModeRef.current; if ( value === 'ZoomOut' ) { newEditorMode = 'zoom-out'; diff --git a/packages/interface/src/components/complementary-area/index.js b/packages/interface/src/components/complementary-area/index.js index b37b8b7da33d02..363a6ee9dea76c 100644 --- a/packages/interface/src/components/complementary-area/index.js +++ b/packages/interface/src/components/complementary-area/index.js @@ -119,42 +119,42 @@ function useAdjustComplementaryListener( isActive, isSmall ) { - const previousIsSmall = useRef( false ); - const shouldOpenWhenNotSmall = useRef( false ); + const previousIsSmallRef = useRef( false ); + const shouldOpenWhenNotSmallRef = useRef( false ); const { enableComplementaryArea, disableComplementaryArea } = useDispatch( interfaceStore ); useEffect( () => { // If the complementary area is active and the editor is switching from // a big to a small window size. - if ( isActive && isSmall && ! previousIsSmall.current ) { + if ( isActive && isSmall && ! previousIsSmallRef.current ) { disableComplementaryArea( scope ); // Flag the complementary area to be reopened when the window size // goes from small to big. - shouldOpenWhenNotSmall.current = true; + shouldOpenWhenNotSmallRef.current = true; } else if ( // If there is a flag indicating the complementary area should be // enabled when we go from small to big window size and we are going // from a small to big window size. - shouldOpenWhenNotSmall.current && + shouldOpenWhenNotSmallRef.current && ! isSmall && - previousIsSmall.current + previousIsSmallRef.current ) { // Remove the flag indicating the complementary area should be // enabled. - shouldOpenWhenNotSmall.current = false; + shouldOpenWhenNotSmallRef.current = false; enableComplementaryArea( scope, identifier ); } else if ( // If the flag is indicating the current complementary should be // reopened but another complementary area becomes active, remove // the flag. - shouldOpenWhenNotSmall.current && + shouldOpenWhenNotSmallRef.current && activeArea && activeArea !== identifier ) { - shouldOpenWhenNotSmall.current = false; + shouldOpenWhenNotSmallRef.current = false; } - if ( isSmall !== previousIsSmall.current ) { - previousIsSmall.current = isSmall; + if ( isSmall !== previousIsSmallRef.current ) { + previousIsSmallRef.current = isSmall; } }, [ isActive, diff --git a/packages/rich-text/src/component/index.js b/packages/rich-text/src/component/index.js index 2606ae9f902fab..600fc0faff5209 100644 --- a/packages/rich-text/src/component/index.js +++ b/packages/rich-text/src/component/index.js @@ -60,46 +60,48 @@ export function useRichText( { } // Internal values are updated synchronously, unlike props and state. - const _value = useRef( value ); - const record = useRef(); + const _valueRef = useRef( value ); + const recordRef = useRef(); function setRecordFromProps() { - _value.current = value; - record.current = value; + _valueRef.current = value; + recordRef.current = value; if ( ! ( value instanceof RichTextData ) ) { - record.current = value + recordRef.current = value ? RichTextData.fromHTMLString( value, { preserveWhiteSpace } ) : RichTextData.empty(); } // To do: make rich text internally work with RichTextData. - record.current = { - text: record.current.text, - formats: record.current.formats, - replacements: record.current.replacements, + recordRef.current = { + text: recordRef.current.text, + formats: recordRef.current.formats, + replacements: recordRef.current.replacements, }; if ( disableFormats ) { - record.current.formats = Array( value.length ); - record.current.replacements = Array( value.length ); + recordRef.current.formats = Array( value.length ); + recordRef.current.replacements = Array( value.length ); } if ( __unstableAfterParse ) { - record.current.formats = __unstableAfterParse( record.current ); + recordRef.current.formats = __unstableAfterParse( + recordRef.current + ); } - record.current.start = selectionStart; - record.current.end = selectionEnd; + recordRef.current.start = selectionStart; + recordRef.current.end = selectionEnd; } - const hadSelectionUpdate = useRef( false ); + const hadSelectionUpdateRef = useRef( false ); - if ( ! record.current ) { - hadSelectionUpdate.current = isSelected; + if ( ! recordRef.current ) { + hadSelectionUpdateRef.current = isSelected; setRecordFromProps(); } else if ( - selectionStart !== record.current.start || - selectionEnd !== record.current.end + selectionStart !== recordRef.current.start || + selectionEnd !== recordRef.current.end ) { - hadSelectionUpdate.current = isSelected; - record.current = { - ...record.current, + hadSelectionUpdateRef.current = isSelected; + recordRef.current = { + ...recordRef.current, start: selectionStart, end: selectionEnd, activeFormats: undefined, @@ -113,34 +115,34 @@ export function useRichText( { * @param {Object} newRecord The record to sync and apply. */ function handleChange( newRecord ) { - record.current = newRecord; + recordRef.current = newRecord; applyRecord( newRecord ); if ( disableFormats ) { - _value.current = newRecord.text; + _valueRef.current = newRecord.text; } else { const newFormats = __unstableBeforeSerialize ? __unstableBeforeSerialize( newRecord ) : newRecord.formats; newRecord = { ...newRecord, formats: newFormats }; if ( typeof value === 'string' ) { - _value.current = toHTMLString( { + _valueRef.current = toHTMLString( { value: newRecord, preserveWhiteSpace, } ); } else { - _value.current = new RichTextData( newRecord ); + _valueRef.current = new RichTextData( newRecord ); } } - const { start, end, formats, text } = record.current; + const { start, end, formats, text } = recordRef.current; // Selection must be updated first, so it is recorded in history when // the content change happens. // We batch both calls to only attempt to rerender once. registry.batch( () => { onSelectionChange( start, end ); - onChange( _value.current, { + onChange( _valueRef.current, { __unstableFormats: formats, __unstableText: text, } ); @@ -150,14 +152,14 @@ export function useRichText( { function applyFromProps() { setRecordFromProps(); - applyRecord( record.current ); + applyRecord( recordRef.current ); } - const didMount = useRef( false ); + const didMountRef = useRef( false ); // Value updates must happen synchonously to avoid overwriting newer values. useLayoutEffect( () => { - if ( didMount.current && value !== _value.current ) { + if ( didMountRef.current && value !== _valueRef.current ) { applyFromProps(); forceRender(); } @@ -165,7 +167,7 @@ export function useRichText( { // Value updates must happen synchonously to avoid overwriting newer values. useLayoutEffect( () => { - if ( ! hadSelectionUpdate.current ) { + if ( ! hadSelectionUpdateRef.current ) { return; } @@ -173,16 +175,16 @@ export function useRichText( { ref.current.focus(); } - applyRecord( record.current ); - hadSelectionUpdate.current = false; - }, [ hadSelectionUpdate.current ] ); + applyRecord( recordRef.current ); + hadSelectionUpdateRef.current = false; + }, [ hadSelectionUpdateRef.current ] ); const mergedRefs = useMergeRefs( [ ref, useDefaultStyle(), - useBoundaryStyle( { record } ), + useBoundaryStyle( { record: recordRef } ), useEventListeners( { - record, + record: recordRef, handleChange, applyRecord, createRecord, @@ -192,18 +194,18 @@ export function useRichText( { } ), useRefEffect( () => { applyFromProps(); - didMount.current = true; + didMountRef.current = true; }, [ placeholder, ...__unstableDependencies ] ), ] ); return { - value: record.current, + value: recordRef.current, // A function to get the most recent value so event handlers in // useRichText implementations have access to it. For example when // listening to input events, we internally update the state, but this // state is not yet available to the input event handler because React // may re-render asynchronously. - getValue: () => record.current, + getValue: () => recordRef.current, onChange: handleChange, ref: mergedRefs, }; From 6aeba745bcba51621310a318e8dccfdf3eb4c92e Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:55:28 +0200 Subject: [PATCH 0505/1908] Allow multi-select on iOS Safari/touch devices (#63671) --- .../use-focus-first-element.js | 1 + .../event-listeners/paste-handler.js | 7 +- .../src/components/rich-text/index.js | 14 +++- .../src/components/writing-flow/index.js | 2 + .../components/writing-flow/use-arrow-nav.js | 11 ++- .../writing-flow/use-event-redirect.js | 72 +++++++++++++++++++ .../src/components/writing-flow/use-input.js | 37 +++++++++- .../components/writing-flow/use-select-all.js | 19 ++++- .../writing-flow/use-selection-observer.js | 17 ++++- .../src/components/writing-flow/utils.js | 30 ++++++++ packages/dom/src/dom/place-caret-at-edge.js | 12 ++-- .../component/event-listeners/copy-handler.js | 17 +++-- .../event-listeners/input-and-selection.js | 19 ++--- .../editor/various/block-deletion.spec.js | 11 +-- .../editor/various/pattern-overrides.spec.js | 4 +- 15 files changed, 237 insertions(+), 36 deletions(-) create mode 100644 packages/block-editor/src/components/writing-flow/use-event-redirect.js diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js b/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js index 27f72d1a100d3e..a6308f48005f9d 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js @@ -68,6 +68,7 @@ export function useFocusFirstElement( { clientId, initialPosition } ) { textInputs[ isReverse ? textInputs.length - 1 : 0 ] || ref.current; if ( ! isInsideRootBlock( ref.current, target ) ) { + ownerDocument.defaultView.getSelection().removeAllRanges(); ref.current.focus(); return; } diff --git a/packages/block-editor/src/components/rich-text/event-listeners/paste-handler.js b/packages/block-editor/src/components/rich-text/event-listeners/paste-handler.js index 59633f4750ff92..9266cd25537545 100644 --- a/packages/block-editor/src/components/rich-text/event-listeners/paste-handler.js +++ b/packages/block-editor/src/components/rich-text/event-listeners/paste-handler.js @@ -26,10 +26,15 @@ export default ( props ) => ( element ) => { preserveWhiteSpace, pastePlainText, } = props.current; + const { ownerDocument } = element; + const { defaultView } = ownerDocument; + const { anchorNode, focusNode } = defaultView.getSelection(); + const containsSelection = + element.contains( anchorNode ) && element.contains( focusNode ); // The event listener is attached to the window, so we need to check if // the target is the element. - if ( event.target !== element ) { + if ( ! containsSelection ) { return; } diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 68f00ca1b5d149..e8fbec1e0b7458 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -357,7 +357,19 @@ export function RichTextWrapper( const inputEvents = useRef( new Set() ); function onFocus() { - anchorRef.current?.focus(); + let element = anchorRef.current; + + if ( ! element ) { + return; + } + + // Writing flow might be editable, so we should make sure focus goes to + // the root editable element. + while ( element.parentElement?.isContentEditable ) { + element = element.parentElement; + } + + element.focus(); } const registry = useRegistry(); diff --git a/packages/block-editor/src/components/writing-flow/index.js b/packages/block-editor/src/components/writing-flow/index.js index 7e6b36b0e22143..cea3e4b19707dd 100644 --- a/packages/block-editor/src/components/writing-flow/index.js +++ b/packages/block-editor/src/components/writing-flow/index.js @@ -23,6 +23,7 @@ import useSelectionObserver from './use-selection-observer'; import useClickSelection from './use-click-selection'; import useInput from './use-input'; import useClipboardHandler from './use-clipboard-handler'; +import useEventRedirect from './use-event-redirect'; import { store as blockEditorStore } from '../../store'; export function useWritingFlow() { @@ -65,6 +66,7 @@ export function useWritingFlow() { }, [ hasMultiSelection ] ), + useEventRedirect(), ] ), after, ]; diff --git a/packages/block-editor/src/components/writing-flow/use-arrow-nav.js b/packages/block-editor/src/components/writing-flow/use-arrow-nav.js index 44051b324ff64d..fda5a0133ee00c 100644 --- a/packages/block-editor/src/components/writing-flow/use-arrow-nav.js +++ b/packages/block-editor/src/components/writing-flow/use-arrow-nav.js @@ -19,6 +19,7 @@ import { useRefEffect } from '@wordpress/compose'; */ import { getBlockClientId, isInSameBlock } from '../../utils/dom'; import { store as blockEditorStore } from '../../store'; +import { getSelectionRoot } from './utils'; /** * Returns true if the element should consider edge navigation upon a keyboard @@ -190,8 +191,7 @@ export default function useArrowNav() { return; } - const { keyCode, target, shiftKey, ctrlKey, altKey, metaKey } = - event; + const { keyCode, shiftKey, ctrlKey, altKey, metaKey } = event; const isUp = keyCode === UP; const isDown = keyCode === DOWN; const isLeft = keyCode === LEFT; @@ -233,6 +233,11 @@ export default function useArrowNav() { return; } + const target = + ownerDocument.activeElement === node + ? getSelectionRoot( ownerDocument ) + : event.target; + // Abort if our current target is not a candidate for navigation // (e.g. preserve native input behaviors). if ( ! isNavigationCandidate( target, keyCode, hasModifier ) ) { @@ -274,6 +279,7 @@ export default function useArrowNav() { ( altKey ? isHorizontalEdge( target, isReverseDir ) : true ) && ! keepCaretInsideBlock ) { + node.contentEditable = false; const closestTabbable = getClosestTabbable( target, isReverse, @@ -297,6 +303,7 @@ export default function useArrowNav() { isHorizontalEdge( target, isReverseDir ) && ! keepCaretInsideBlock ) { + node.contentEditable = false; const closestTabbable = getClosestTabbable( target, isReverseDir, diff --git a/packages/block-editor/src/components/writing-flow/use-event-redirect.js b/packages/block-editor/src/components/writing-flow/use-event-redirect.js new file mode 100644 index 00000000000000..b8dcd7eda69697 --- /dev/null +++ b/packages/block-editor/src/components/writing-flow/use-event-redirect.js @@ -0,0 +1,72 @@ +/** + * WordPress dependencies + */ +import { useRefEffect } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import { getSelectionRoot } from './utils'; + +/** + * Whenever content editable is enabled on writing flow, it will have focus, so + * we need to dispatch some events to the root of the selection to ensure + * compatibility with rich text. In the future, perhaps the rich text event + * handlers should be attached to the window instead. + * + * Alternatively, we could try to find a way to always maintain rich text focus. + */ +export default function useEventRedirect() { + return useRefEffect( ( node ) => { + function onInput( event ) { + if ( event.target !== node ) { + return; + } + + const { ownerDocument } = node; + const { defaultView } = ownerDocument; + const prototype = Object.getPrototypeOf( event ); + const constructorName = prototype.constructor.name; + const Constructor = defaultView[ constructorName ]; + const root = getSelectionRoot( ownerDocument ); + + if ( ! root || root === node ) { + return; + } + + const init = {}; + + for ( const key in event ) { + init[ key ] = event[ key ]; + } + + init.bubbles = false; + + const newEvent = new Constructor( event.type, init ); + const cancelled = ! root.dispatchEvent( newEvent ); + + if ( cancelled ) { + event.preventDefault(); + } + } + + const events = [ + 'beforeinput', + 'input', + 'compositionstart', + 'compositionend', + 'compositionupdate', + 'keydown', + ]; + + events.forEach( ( eventType ) => { + node.addEventListener( eventType, onInput ); + } ); + + return () => { + events.forEach( ( eventType ) => { + node.removeEventListener( eventType, onInput ); + } ); + }; + }, [] ); +} diff --git a/packages/block-editor/src/components/writing-flow/use-input.js b/packages/block-editor/src/components/writing-flow/use-input.js index 0f10cc9c2d1c75..31c5d769834c01 100644 --- a/packages/block-editor/src/components/writing-flow/use-input.js +++ b/packages/block-editor/src/components/writing-flow/use-input.js @@ -16,6 +16,7 @@ import { * Internal dependencies */ import { store as blockEditorStore } from '../../store'; +import { getSelectionRoot } from './utils'; /** * Handles input for selections across blocks. @@ -49,7 +50,24 @@ export default function useInput() { // DOM. This will cause React errors (and the DOM should only be // altered in a controlled fashion). if ( node.contentEditable === 'true' ) { - event.preventDefault(); + const selection = node.ownerDocument.defaultView.getSelection(); + const range = selection.rangeCount + ? selection.getRangeAt( 0 ) + : null; + const root = getSelectionRoot( node.ownerDocument ); + + // If selection is contained within a nested editable, allow + // input. We need to ensure that selection is maintained. + if ( root ) { + node.contentEditable = false; + root.focus(); + selection.removeAllRanges(); + if ( range ) { + selection.addRange( range ); + } + } else { + event.preventDefault(); + } } } @@ -59,6 +77,23 @@ export default function useInput() { } if ( ! hasMultiSelection() ) { + const { ownerDocument } = node; + if ( node === ownerDocument.activeElement ) { + if ( event.key === 'End' || event.key === 'Home' ) { + const selectionRoot = getSelectionRoot( ownerDocument ); + const selection = + ownerDocument.defaultView.getSelection(); + selection.selectAllChildren( selectionRoot ); + const method = + event.key === 'End' + ? 'collapseToEnd' + : 'collapseToStart'; + selection[ method ](); + event.preventDefault(); + return; + } + } + if ( event.keyCode === ENTER ) { if ( event.shiftKey || __unstableIsFullySelected() ) { return; diff --git a/packages/block-editor/src/components/writing-flow/use-select-all.js b/packages/block-editor/src/components/writing-flow/use-select-all.js index c56549acf54ad5..5a7acb3a8783a4 100644 --- a/packages/block-editor/src/components/writing-flow/use-select-all.js +++ b/packages/block-editor/src/components/writing-flow/use-select-all.js @@ -10,6 +10,7 @@ import { useRefEffect } from '@wordpress/compose'; * Internal dependencies */ import { store as blockEditorStore } from '../../store'; +import { getSelectionRoot } from './utils'; export default function useSelectAll() { const { getBlockOrder, getSelectedBlockClientIds, getBlockRootClientId } = @@ -23,12 +24,27 @@ export default function useSelectAll() { return; } + const selectionRoot = getSelectionRoot( node.ownerDocument ); const selectedClientIds = getSelectedBlockClientIds(); + // Abort if there is selection, but it is not within a block. + if ( selectionRoot && ! selectedClientIds.length ) { + return; + } + if ( + selectionRoot && selectedClientIds.length < 2 && - ! isEntirelySelected( event.target ) + ! isEntirelySelected( selectionRoot ) ) { + if ( node === node.ownerDocument.activeElement ) { + event.preventDefault(); + node.ownerDocument.defaultView + .getSelection() + .selectAllChildren( selectionRoot ); + return; + } + return; } @@ -45,6 +61,7 @@ export default function useSelectAll() { node.ownerDocument.defaultView .getSelection() .removeAllRanges(); + node.contentEditable = 'false'; selectBlock( rootClientId ); } return; diff --git a/packages/block-editor/src/components/writing-flow/use-selection-observer.js b/packages/block-editor/src/components/writing-flow/use-selection-observer.js index 57082f90c055fd..824e01d07358b7 100644 --- a/packages/block-editor/src/components/writing-flow/use-selection-observer.js +++ b/packages/block-editor/src/components/writing-flow/use-selection-observer.js @@ -98,8 +98,12 @@ function getRichTextElement( node ) { export default function useSelectionObserver() { const { multiSelect, selectBlock, selectionChange } = useDispatch( blockEditorStore ); - const { getBlockParents, getBlockSelectionStart, isMultiSelecting } = - useSelect( blockEditorStore ); + const { + getBlockParents, + getBlockSelectionStart, + isMultiSelecting, + getSelectedBlockClientId, + } = useSelect( blockEditorStore ); return useRefEffect( ( node ) => { const { ownerDocument } = node; @@ -182,10 +186,17 @@ export default function useSelectionObserver() { return; } + setContentEditableWrapper( + node, + !! ( startClientId && endClientId ) + ); + const isSingularSelection = startClientId === endClientId; if ( isSingularSelection ) { if ( ! isMultiSelecting() ) { - selectBlock( startClientId ); + if ( getSelectedBlockClientId() !== startClientId ) { + selectBlock( startClientId ); + } } else { multiSelect( startClientId, startClientId ); } diff --git a/packages/block-editor/src/components/writing-flow/utils.js b/packages/block-editor/src/components/writing-flow/utils.js index 2a2010854ed205..0cd41eedd3f6f1 100644 --- a/packages/block-editor/src/components/writing-flow/utils.js +++ b/packages/block-editor/src/components/writing-flow/utils.js @@ -116,3 +116,33 @@ function toPlainText( html ) { // Merge any consecutive line breaks return plainText.replace( /\n\n+/g, '\n\n' ); } + +/** + * Gets the current content editable root element based on the selection. + * @param {Document} ownerDocument + * @return {Element|undefined} The content editable root element. + */ +export function getSelectionRoot( ownerDocument ) { + const { defaultView } = ownerDocument; + const { anchorNode, focusNode } = defaultView.getSelection(); + + if ( ! anchorNode || ! focusNode ) { + return; + } + + const anchorElement = ( + anchorNode.nodeType === anchorNode.ELEMENT_NODE + ? anchorNode + : anchorNode.parentElement + ).closest( '[contenteditable]' ); + + if ( ! anchorElement ) { + return; + } + + if ( ! anchorElement.contains( focusNode ) ) { + return; + } + + return anchorElement; +} diff --git a/packages/dom/src/dom/place-caret-at-edge.js b/packages/dom/src/dom/place-caret-at-edge.js index 4075fc7c439586..013a64d076e559 100644 --- a/packages/dom/src/dom/place-caret-at-edge.js +++ b/packages/dom/src/dom/place-caret-at-edge.js @@ -67,7 +67,14 @@ export default function placeCaretAtEdge( container, isReverse, x ) { return; } + const { ownerDocument } = container; + const { defaultView } = ownerDocument; + assertIsDefined( defaultView, 'defaultView' ); + const selection = defaultView.getSelection(); + assertIsDefined( selection, 'selection' ); + if ( ! container.isContentEditable ) { + selection.removeAllRanges(); return; } @@ -79,11 +86,6 @@ export default function placeCaretAtEdge( container, isReverse, x ) { return; } - const { ownerDocument } = container; - const { defaultView } = ownerDocument; - assertIsDefined( defaultView, 'defaultView' ); - const selection = defaultView.getSelection(); - assertIsDefined( selection, 'selection' ); selection.removeAllRanges(); selection.addRange( range ); } diff --git a/packages/rich-text/src/component/event-listeners/copy-handler.js b/packages/rich-text/src/component/event-listeners/copy-handler.js index 0cc1594c3ab914..1a92237bb4c5b4 100644 --- a/packages/rich-text/src/component/event-listeners/copy-handler.js +++ b/packages/rich-text/src/component/event-listeners/copy-handler.js @@ -2,18 +2,21 @@ * Internal dependencies */ import { toHTMLString } from '../../to-html-string'; -import { isCollapsed } from '../../is-collapsed'; import { slice } from '../../slice'; +import { remove } from '../../remove'; import { getTextContent } from '../../get-text-content'; export default ( props ) => ( element ) => { function onCopy( event ) { - const { record } = props.current; + const { record, createRecord, handleChange } = props.current; const { ownerDocument } = element; - if ( - isCollapsed( record.current ) || - ! element.contains( ownerDocument.activeElement ) - ) { + const { defaultView } = ownerDocument; + const { anchorNode, focusNode, isCollapsed } = + defaultView.getSelection(); + const containsSelection = + element.contains( anchorNode ) && element.contains( focusNode ); + + if ( isCollapsed || ! containsSelection ) { return; } @@ -26,7 +29,7 @@ export default ( props ) => ( element ) => { event.preventDefault(); if ( event.type === 'cut' ) { - ownerDocument.execCommand( 'delete' ); + handleChange( remove( createRecord() ) ); } } diff --git a/packages/rich-text/src/component/event-listeners/input-and-selection.js b/packages/rich-text/src/component/event-listeners/input-and-selection.js index 621f1c59fab04e..11dcdb0d8ff9ab 100644 --- a/packages/rich-text/src/component/event-listeners/input-and-selection.js +++ b/packages/rich-text/src/component/event-listeners/input-and-selection.js @@ -114,14 +114,13 @@ export default ( props ) => ( element ) => { return; } - // Ensure the active element is the rich text element. - if ( ownerDocument.activeElement !== element ) { - // If it is not, we can stop listening for selection changes. We - // resume listening when the element is focused. - ownerDocument.removeEventListener( - 'selectionchange', - handleSelectionChange - ); + const { anchorNode, focusNode } = defaultView.getSelection(); + const containsSelection = + element.contains( anchorNode ) && + element.contains( focusNode ) && + ownerDocument.activeElement.contains( element ); + + if ( ! containsSelection ) { return; } @@ -255,5 +254,9 @@ export default ( props ) => ( element ) => { element.removeEventListener( 'compositionstart', onCompositionStart ); element.removeEventListener( 'compositionend', onCompositionEnd ); element.removeEventListener( 'focus', onFocus ); + ownerDocument.removeEventListener( + 'selectionchange', + handleSelectionChange + ); }; }; diff --git a/test/e2e/specs/editor/various/block-deletion.spec.js b/test/e2e/specs/editor/various/block-deletion.spec.js index 9346412c46bcb2..00b51a94668d50 100644 --- a/test/e2e/specs/editor/various/block-deletion.spec.js +++ b/test/e2e/specs/editor/various/block-deletion.spec.js @@ -287,15 +287,16 @@ test.describe( 'Block deletion', () => { await expect.poll( editor.getBlocks ).toMatchObject( [ { name: 'core/paragraph', attributes: { content: 'First' } }, { name: 'core/paragraph', attributes: { content: 'Second' } }, - { name: 'core/paragraph', attributes: { content: '' } }, ] ); // Ensure that the newly created empty block is focused. - await expect.poll( editor.getBlocks ).toHaveLength( 3 ); + await expect.poll( editor.getBlocks ).toHaveLength( 2 ); await expect( - editor.canvas.getByRole( 'document', { - name: 'Empty block', - } ) + editor.canvas + .getByRole( 'document', { + name: 'Block: Paragraph', + } ) + .nth( 1 ) ).toBeFocused(); } ); diff --git a/test/e2e/specs/editor/various/pattern-overrides.spec.js b/test/e2e/specs/editor/various/pattern-overrides.spec.js index 5e529043ec3ed6..88d45ac5d8d3c6 100644 --- a/test/e2e/specs/editor/various/pattern-overrides.spec.js +++ b/test/e2e/specs/editor/various/pattern-overrides.spec.js @@ -150,7 +150,7 @@ test.describe( 'Pattern Overrides', () => { name: 'Block: Paragraph', } ); // Ensure the first pattern is selected. - await patternBlocks.first().selectText(); + await editor.selectBlocks( patternBlocks.first() ); await expect( paragraphs.first() ).not.toHaveAttribute( 'inert', 'true' @@ -168,7 +168,7 @@ test.describe( 'Pattern Overrides', () => { await page.keyboard.type( 'I would word it this way' ); // Ensure the second pattern is selected. - await patternBlocks.last().selectText(); + await editor.selectBlocks( patternBlocks.last() ); await patternBlocks .last() .getByRole( 'document', { From 3ce50532ea40608cbe29ecb0262ffb727f4ac958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Juh=C3=A9=20Lluveras?= <contact@albertjuhe.com> Date: Thu, 22 Aug 2024 18:02:31 +0200 Subject: [PATCH 0506/1908] Make plugin-registered templates overriden by themes to fall back to plugin-registered title and description (#64610) * Make plugin-registered templates overriden by themes to fall back to plugin-registered title and description * Update backport changelog file --- backport-changelog/6.7/7125.md | 1 + lib/compat/wordpress-6.7/compat.php | 14 ++++++++++---- .../site-editor/template-registration.spec.js | 6 ++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/backport-changelog/6.7/7125.md b/backport-changelog/6.7/7125.md index ce208decd2d145..341e0415cc61a2 100644 --- a/backport-changelog/6.7/7125.md +++ b/backport-changelog/6.7/7125.md @@ -1,3 +1,4 @@ https://github.com/WordPress/wordpress-develop/pull/7125 * https://github.com/WordPress/gutenberg/pull/61577 +* https://github.com/WordPress/gutenberg/pull/64610 diff --git a/lib/compat/wordpress-6.7/compat.php b/lib/compat/wordpress-6.7/compat.php index edc8e3fa5fb03f..cd533a42cc528e 100644 --- a/lib/compat/wordpress-6.7/compat.php +++ b/lib/compat/wordpress-6.7/compat.php @@ -27,11 +27,15 @@ function _gutenberg_add_block_templates_from_registry( $query_result, $query, $t foreach ( $query_result as $key => $value ) { $registered_template = WP_Block_Templates_Registry::get_instance()->get_by_slug( $query_result[ $key ]->slug ); if ( $registered_template ) { - $query_result[ $key ]->plugin = $registered_template->plugin; - $query_result[ $key ]->origin = + $query_result[ $key ]->plugin = $registered_template->plugin; + $query_result[ $key ]->origin = 'theme' !== $query_result[ $key ]->origin && 'theme' !== $query_result[ $key ]->source ? 'plugin' : $query_result[ $key ]->origin; + $query_result[ $key ]->title = + empty( $query_result[ $key ]->title ) || $query_result[ $key ]->title === $query_result[ $key ]->slug ? + $registered_template->title : $query_result[ $key ]->title; + $query_result[ $key ]->description = empty( $query_result[ $key ]->description ) ? $registered_template->description : $query_result[ $key ]->description; } } @@ -70,11 +74,13 @@ function _gutenberg_add_block_template_plugin_attribute( $block_template ) { if ( $block_template ) { $registered_template = WP_Block_Templates_Registry::get_instance()->get_by_slug( $block_template->slug ); if ( $registered_template ) { - $block_template->plugin = $registered_template->plugin; - $block_template->origin = + $block_template->plugin = $registered_template->plugin; + $block_template->origin = 'theme' !== $block_template->origin && 'theme' !== $block_template->source ? 'plugin' : $block_template->origin; + $block_template->title = empty( $block_template->title ) || $block_template->title === $block_template->slug ? $registered_template->title : $block_template->title; + $block_template->description = empty( $block_template->description ) ? $registered_template->description : $block_template->description; } } diff --git a/test/e2e/specs/site-editor/template-registration.spec.js b/test/e2e/specs/site-editor/template-registration.spec.js index 3927623b2824dc..ba9667358b3142 100644 --- a/test/e2e/specs/site-editor/template-registration.spec.js +++ b/test/e2e/specs/site-editor/template-registration.spec.js @@ -160,6 +160,12 @@ test.describe( 'Block template registration', () => { await expect( page.getByText( 'Custom Template (overridden by the theme)' ) ).toBeHidden(); + // Verify the template description fall backs to the plugin registered description. + await expect( + page.getByText( + 'A custom template registered by a plugin and overridden by a theme.' + ) + ).toBeVisible(); // Verify the theme template shows the theme name as the author. await expect( page.getByText( 'AuthorEmptytheme' ) ).toBeVisible(); } ); From 5266ed84ccd4e5f2474190b1e19cc12b6810682d Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 22 Aug 2024 23:04:52 +0400 Subject: [PATCH 0507/1908] Post Title: Move selection at the end after pasting over the text (#64665) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ironprogrammer <ironprogrammer@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: MadtownLems <madtownlems@git.wordpress.org> --- .../editor/src/components/post-title/index.js | 70 ++++++++----------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/packages/editor/src/components/post-title/index.js b/packages/editor/src/components/post-title/index.js index 1eee94d578b82b..50595d936b36d9 100644 --- a/packages/editor/src/components/post-title/index.js +++ b/packages/editor/src/components/post-title/index.js @@ -15,7 +15,6 @@ import { pasteHandler } from '@wordpress/blocks'; import { __unstableUseRichText as useRichText, create, - toHTMLString, insert, } from '@wordpress/rich-text'; import { useMergeRefs } from '@wordpress/compose'; @@ -50,9 +49,35 @@ function PostTitle( _, forwardedRef ) { const { clearSelectedBlock, insertBlocks, insertDefaultBlock } = useDispatch( blockEditorStore ); - function onChange( value ) { - onUpdate( value.replace( REGEXP_NEWLINES, ' ' ) ); - } + const decodedPlaceholder = + decodeEntities( placeholder ) || __( 'Add title' ); + + const { + value, + onChange, + ref: richTextRef, + } = useRichText( { + value: title, + onChange( newValue ) { + onUpdate( newValue.replace( REGEXP_NEWLINES, ' ' ) ); + }, + placeholder: decodedPlaceholder, + selectionStart: selection.start, + selectionEnd: selection.end, + onSelectionChange( newStart, newEnd ) { + setSelection( ( sel ) => { + const { start, end } = sel; + if ( start === newStart && end === newEnd ) { + return sel; + } + return { + start: newStart, + end: newEnd, + }; + } ); + }, + __unstableDisableFormats: false, + } ); function onInsertBlockAfter( blocks ) { insertBlocks( blocks, 0 ); @@ -130,49 +155,14 @@ function PostTitle( _, forwardedRef ) { onInsertBlockAfter( content ); } } else { - const value = { - ...create( { html: title } ), - ...selection, - }; - // Strip HTML to avoid unwanted HTML being added to the title. // In the majority of cases it is assumed that HTML in the title // is undesirable. const contentNoHTML = stripHTML( content ); - - const newValue = insert( value, create( { html: contentNoHTML } ) ); - onUpdate( toHTMLString( { value: newValue } ) ); - setSelection( { - start: newValue.start, - end: newValue.end, - } ); + onChange( insert( value, create( { html: contentNoHTML } ) ) ); } } - const decodedPlaceholder = - decodeEntities( placeholder ) || __( 'Add title' ); - - const { ref: richTextRef } = useRichText( { - value: title, - onChange, - placeholder: decodedPlaceholder, - selectionStart: selection.start, - selectionEnd: selection.end, - onSelectionChange( newStart, newEnd ) { - setSelection( ( sel ) => { - const { start, end } = sel; - if ( start === newStart && end === newEnd ) { - return sel; - } - return { - start: newStart, - end: newEnd, - }; - } ); - }, - __unstableDisableFormats: false, - } ); - // The wp-block className is important for editor styles. // This same block is used in both the visual and the code editor. const className = clsx( DEFAULT_CLASSNAMES, { From c926af77c063fbe06fc01f8132f41b61eef8ede9 Mon Sep 17 00:00:00 2001 From: Rich Tabor <hi@richtabor.com> Date: Thu, 22 Aug 2024 15:18:12 -0400 Subject: [PATCH 0508/1908] Use four color palette colors instead of five for useStylesPreviewColors (#64700) Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../edit-site/src/components/global-styles/preset-colors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/preset-colors.js b/packages/edit-site/src/components/global-styles/preset-colors.js index c24b5ea3c75e0f..7977cd88a13c3f 100644 --- a/packages/edit-site/src/components/global-styles/preset-colors.js +++ b/packages/edit-site/src/components/global-styles/preset-colors.js @@ -5,7 +5,7 @@ import { useStylesPreviewColors } from './hooks'; export default function PresetColors() { const { paletteColors } = useStylesPreviewColors(); - return paletteColors.slice( 0, 5 ).map( ( { slug, color }, index ) => ( + return paletteColors.slice( 0, 4 ).map( ( { slug, color }, index ) => ( <div key={ `${ slug }-${ index }` } style={ { From 8c4be5842025e3e4a707194323258adbdcddeaa4 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Fri, 23 Aug 2024 07:34:39 +0800 Subject: [PATCH 0509/1908] Post editor: apply space below content using a pseudo-element instead of padding-bottom (#64639) Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: PC888 <kracked888@git.wordpress.org> --- packages/edit-post/src/components/layout/index.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 9266cbbb10a557..519b32691c6a49 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -74,7 +74,6 @@ function useEditorStyles() { hasThemeStyleSupport, editorSettings, isZoomedOutView, - hasMetaBoxes, renderingMode, postType, } = useSelect( ( select ) => { @@ -86,7 +85,6 @@ function useEditorStyles() { select( editPostStore ).isFeatureActive( 'themeStyles' ), editorSettings: select( editorStore ).getEditorSettings(), isZoomedOutView: __unstableGetEditorMode() === 'zoom-out', - hasMetaBoxes: select( editPostStore ).hasMetaBoxes(), renderingMode: getRenderingMode(), postType: _postType, }; @@ -132,16 +130,13 @@ function useEditorStyles() { // bottom, there needs to be room to scroll up. if ( ! isZoomedOutView && - ! hasMetaBoxes && renderingMode === 'post-only' && ! DESIGN_POST_TYPES.includes( postType ) ) { return [ ...baseStyles, { - // Should override global styles padding, so ensure 0-1-0 - // specificity. - css: ':root :where(body){padding-bottom: 40vh}', + css: ':root :where(.editor-styles-wrapper)::after {content: ""; display: block; height: 40vh;}', }, ]; } From 8ba6b11fba4e12bec3ad6174886fbcc8a97a0094 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 23 Aug 2024 13:02:37 +0900 Subject: [PATCH 0510/1908] Template Part: Hide Advanced panel for non-admin users (#64721) * Template Part: Hide Advanced panel for non-admin users * Restore original conditional statement Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../template-part/edit/advanced-controls.js | 1 - .../src/template-part/edit/index.js | 22 ++++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/block-library/src/template-part/edit/advanced-controls.js b/packages/block-library/src/template-part/edit/advanced-controls.js index 0a2b8bebbf4fca..3c319a7ec0fe73 100644 --- a/packages/block-library/src/template-part/edit/advanced-controls.js +++ b/packages/block-library/src/template-part/edit/advanced-controls.js @@ -82,7 +82,6 @@ export function TemplatePartAdvancedControls( { } } onFocus={ ( event ) => event.target.select() } /> - <SelectControl __next40pxDefaultSize __nextHasNoMarginBottom diff --git a/packages/block-library/src/template-part/edit/index.js b/packages/block-library/src/template-part/edit/index.js index ba3e8f57136d60..951f875143b0f9 100644 --- a/packages/block-library/src/template-part/edit/index.js +++ b/packages/block-library/src/template-part/edit/index.js @@ -254,16 +254,18 @@ export default function TemplatePartEdit( { </ToolbarButton> </BlockControls> ) } - <InspectorControls group="advanced"> - <TemplatePartAdvancedControls - tagName={ tagName } - setAttributes={ setAttributes } - isEntityAvailable={ isEntityAvailable } - templatePartId={ templatePartId } - defaultWrapper={ areaObject.tagName } - hasInnerBlocks={ hasInnerBlocks } - /> - </InspectorControls> + { canUserEdit && ( + <InspectorControls group="advanced"> + <TemplatePartAdvancedControls + tagName={ tagName } + setAttributes={ setAttributes } + isEntityAvailable={ isEntityAvailable } + templatePartId={ templatePartId } + defaultWrapper={ areaObject.tagName } + hasInnerBlocks={ hasInnerBlocks } + /> + </InspectorControls> + ) } { isPlaceholder && ( <TagName { ...blockProps }> <TemplatePartPlaceholder From b194a803ab4061adc27a3c037f0099d3a3c1152e Mon Sep 17 00:00:00 2001 From: Dean Sas <dean@deansas.org> Date: Fri, 23 Aug 2024 08:46:33 +0100 Subject: [PATCH 0511/1908] Featured Image Block: Reduce CSS specificity (#64463) Co-authored-by: dsas <dsas@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- packages/block-library/src/post-featured-image/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/post-featured-image/style.scss b/packages/block-library/src/post-featured-image/style.scss index e740b8c56e608c..70022d82902f84 100644 --- a/packages/block-library/src/post-featured-image/style.scss +++ b/packages/block-library/src/post-featured-image/style.scss @@ -5,7 +5,7 @@ display: block; height: 100%; } - img { + :where(img) { max-width: 100%; width: 100%; height: auto; From 81b66bf5912d964d6698e7c30b5737e7dd37b174 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Fri, 23 Aug 2024 09:08:50 +0000 Subject: [PATCH 0512/1908] chore(release): publish - @wordpress/block-library@9.6.1 - @wordpress/customize-widgets@5.6.1 - @wordpress/edit-post@8.6.1 - @wordpress/edit-site@6.6.1 - @wordpress/edit-widgets@6.6.1 --- package-lock.json | 10 +++++----- packages/block-library/package.json | 2 +- packages/customize-widgets/package.json | 2 +- packages/edit-post/package.json | 2 +- packages/edit-site/package.json | 2 +- packages/edit-widgets/package.json | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index ccf59ff66a853d..fe6c1dfa150dba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52289,7 +52289,7 @@ }, "packages/block-library": { "name": "@wordpress/block-library", - "version": "9.6.0", + "version": "9.6.1", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52886,7 +52886,7 @@ }, "packages/customize-widgets": { "name": "@wordpress/customize-widgets", - "version": "5.6.0", + "version": "5.6.1", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53210,7 +53210,7 @@ }, "packages/edit-post": { "name": "@wordpress/edit-post", - "version": "8.6.0", + "version": "8.6.1", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53257,7 +53257,7 @@ }, "packages/edit-site": { "name": "@wordpress/edit-site", - "version": "6.6.0", + "version": "6.6.1", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53319,7 +53319,7 @@ }, "packages/edit-widgets": { "name": "@wordpress/edit-widgets", - "version": "6.6.0", + "version": "6.6.1", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 460e97fdf583ad..5b522f01ea7786 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.6.0", + "version": "9.6.1", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 41184daf672b7a..9c8c0a79b771ab 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.6.0", + "version": "5.6.1", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index a9c483873b6d7e..74152b849cf22b 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.6.0", + "version": "8.6.1", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 8122a1427deaba..52292464a21d69 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.6.0", + "version": "6.6.1", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 38163afae6934b..ed48d07a1d1e5c 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.6.0", + "version": "6.6.1", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From d5d2667fe430562f5a3f1686b45da1b69a79aead Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 23 Aug 2024 14:35:11 +0400 Subject: [PATCH 0513/1908] Shuffle: Don't call '__experimentalGetAllowedPatterns' for every block (#64736) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: wpsoul <wpsoul@git.wordpress.org> --- .../src/components/block-toolbar/shuffle.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/shuffle.js b/packages/block-editor/src/components/block-toolbar/shuffle.js index e9101e76e65667..954c7ff22d68ce 100644 --- a/packages/block-editor/src/components/block-toolbar/shuffle.js +++ b/packages/block-editor/src/components/block-toolbar/shuffle.js @@ -34,7 +34,14 @@ export default function Shuffle( { clientId, as = Container } ) { const _categories = attributes?.metadata?.categories || EMPTY_ARRAY; const _patternName = attributes?.metadata?.patternName; const rootBlock = getBlockRootClientId( clientId ); - const _patterns = __experimentalGetAllowedPatterns( rootBlock ); + + // Calling `__experimentalGetAllowedPatterns` is expensive. + // Checking if the block can be shuffled prevents unnecessary selector calls. + // See: https://github.com/WordPress/gutenberg/pull/64736. + const _patterns = + _categories.length > 0 + ? __experimentalGetAllowedPatterns( rootBlock ) + : EMPTY_ARRAY; return { categories: _categories, patterns: _patterns, @@ -45,12 +52,7 @@ export default function Shuffle( { clientId, as = Container } ) { ); const { replaceBlocks } = useDispatch( blockEditorStore ); const sameCategoryPatternsWithSingleWrapper = useMemo( () => { - if ( - ! categories || - categories.length === 0 || - ! patterns || - patterns.length === 0 - ) { + if ( categories.length === 0 || ! patterns || patterns.length === 0 ) { return EMPTY_ARRAY; } return patterns.filter( ( pattern ) => { From 7a7cdd750305148096f77353a82f58f0e614319a Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Fri, 23 Aug 2024 14:46:13 +0100 Subject: [PATCH 0514/1908] Update hard-coded border-radius instances (#64693) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../src/components/block-list/content.scss | 2 +- .../src/components/block-popover/style.scss | 2 +- .../src/components/block-tools/style.scss | 2 +- .../src/components/global-styles/style.scss | 3 +-- .../src/components/inserter/style.scss | 4 ++-- .../src/components/list-view/style.scss | 1 - .../src/components/rich-text/content.scss | 2 +- packages/components/CHANGELOG.md | 11 +++++++++ .../components/src/color-picker/styles.ts | 2 +- .../src/custom-gradient-picker/style.scss | 23 ++----------------- .../src/custom-select-control-v2/styles.ts | 2 +- .../components/src/date-time/date/styles.ts | 3 +-- .../styles/focal-point-style.ts | 7 +++++- .../components/src/form-toggle/style.scss | 2 +- .../src/form-token-field/style.scss | 5 ++-- .../styles/input-control-styles.tsx | 2 +- .../navigation/styles/navigation-styles.tsx | 6 ++--- .../styles/range-control-styles.ts | 14 +++++------ .../styles/resize-tooltip.styles.ts | 4 ++-- .../components/src/resizable-box/style.scss | 4 ++-- packages/components/src/tab-panel/style.scss | 1 - packages/components/src/tabs/styles.ts | 5 ++-- .../src/components/header/style.scss | 2 +- .../src/components/layout/style.scss | 22 ------------------ .../src/components/page-patterns/style.scss | 5 ---- .../create-template-part-modal/style.scss | 2 +- 26 files changed, 51 insertions(+), 87 deletions(-) diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index fb7687e69ffbe4..15f0239d0f0765 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -421,7 +421,7 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b width: 100%; border: none; outline: none; - border-radius: 2px; + border-radius: $radius-small; box-shadow: inset 0 0 0 $border-width $gray-900; resize: none; overflow: hidden; diff --git a/packages/block-editor/src/components/block-popover/style.scss b/packages/block-editor/src/components/block-popover/style.scss index e393e77c63b056..c49538378a12ca 100644 --- a/packages/block-editor/src/components/block-popover/style.scss +++ b/packages/block-editor/src/components/block-popover/style.scss @@ -57,6 +57,6 @@ position: absolute; inset: 0; background-color: var(--wp-admin-theme-color); - border-radius: 2px; + border-radius: $radius-small; } } diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index 000be3d239e8d9..a37271e609b179 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -13,7 +13,7 @@ .block-editor-block-list__insertion-point-indicator { position: absolute; background: var(--wp-admin-theme-color); - border-radius: 2px; + border-radius: $radius-small; transform-origin: center; opacity: 0; will-change: transform, opacity; diff --git a/packages/block-editor/src/components/global-styles/style.scss b/packages/block-editor/src/components/global-styles/style.scss index e979ed77f53da2..6fb07eb090a55f 100644 --- a/packages/block-editor/src/components/global-styles/style.scss +++ b/packages/block-editor/src/components/global-styles/style.scss @@ -74,7 +74,7 @@ .block-editor-global-styles-background-panel__inspector-media-replace-container { border: $border-width solid $gray-300; - border-radius: 2px; + border-radius: $radius-small; // Full width. ToolsPanel lays out children in a grid. grid-column: 1 / -1; @@ -102,7 +102,6 @@ .block-editor-global-styles-background-panel__image-tools-panel-item { border: $border-width solid $gray-300; - border-radius: 2px; // Full width. ToolsPanel lays out children in a grid. grid-column: 1 / -1; diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index a567ce1cee07e5..21f8abfa59c9e8 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -285,7 +285,7 @@ $block-inserter-tabs-height: 44px; &:focus-visible, &:focus:not(:disabled) { - border-radius: 2px; + border-radius: $radius-small; box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); // Windows high contrast mode. outline: 2px solid transparent; @@ -604,7 +604,7 @@ $block-inserter-tabs-height: 44px; display: flex; align-items: center; overflow: hidden; - border-radius: 2px; + border-radius: $radius-small; > * { margin: 0 auto; diff --git a/packages/block-editor/src/components/list-view/style.scss b/packages/block-editor/src/components/list-view/style.scss index 2dce32d535d881..406053af89317c 100644 --- a/packages/block-editor/src/components/list-view/style.scss +++ b/packages/block-editor/src/components/list-view/style.scss @@ -553,7 +553,6 @@ svg { background-color: #1e1e1e; color: #fff; margin: $grid-unit-10 0 0 24px; - border-radius: 2px; height: 24px; min-width: 24px; padding: 0; diff --git a/packages/block-editor/src/components/rich-text/content.scss b/packages/block-editor/src/components/rich-text/content.scss index 6f6d88c777ea74..6f118479fc6b03 100644 --- a/packages/block-editor/src/components/rich-text/content.scss +++ b/packages/block-editor/src/components/rich-text/content.scss @@ -15,7 +15,7 @@ outline: none; [data-rich-text-format-boundary] { - border-radius: 2px; + border-radius: $radius-small; } } } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 2fe344090bcdfc..542d2b8334ed67 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -4,6 +4,17 @@ ### Enhancements +- `ColorPicker`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). +- `CustomSelectControl V2`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). +- `DateTime`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). +- `FormToggle`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). +- `FormTokenField`: Remove unused border-radius ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). +- `InputControl`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). +- `Navigation`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). +- `RangeControl`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). +- `ResizeableBox`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). +- `TabPanel`: Remove radius applied to panel focus style ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). +- `Tabs`: Remove radius applied to panel focus style ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). - `UnitControl`: Update unit select styles ([#64712](https://github.com/WordPress/gutenberg/pull/64712)). - Decrease horizontal padding from 16px to 12px on the following components, when in the 40px default size ([#64708](https://github.com/WordPress/gutenberg/pull/64708)). - `AnglePickerControl` diff --git a/packages/components/src/color-picker/styles.ts b/packages/components/src/color-picker/styles.ts index ecc75f5157625b..a78f10de2e4a32 100644 --- a/packages/components/src/color-picker/styles.ts +++ b/packages/components/src/color-picker/styles.ts @@ -81,7 +81,7 @@ export const ColorfulWrapper = styled.div` .react-colorful__alpha { width: 184px; height: 16px; - border-radius: 16px; + border-radius: ${ CONFIG.radiusFull }; margin-bottom: ${ space( 2 ) }; } diff --git a/packages/components/src/custom-gradient-picker/style.scss b/packages/components/src/custom-gradient-picker/style.scss index a0b616d6ca1d72..fea18f340951e5 100644 --- a/packages/components/src/custom-gradient-picker/style.scss +++ b/packages/components/src/custom-gradient-picker/style.scss @@ -48,7 +48,7 @@ $components-custom-gradient-picker__padding: $grid-unit-20; // 48px container, 1 height: inherit; width: inherit; min-width: $grid-unit-20; - border-radius: 50%; + border-radius: $radius-round; background: $white; padding: 2px; @@ -65,7 +65,7 @@ $components-custom-gradient-picker__padding: $grid-unit-20; // 48px container, 1 // Same size as the .components-custom-gradient-picker__control-point-dropdown parent height: inherit; width: inherit; - border-radius: 50%; + border-radius: $radius-round; padding: 0; // Shadow and stroke. @@ -100,25 +100,6 @@ $components-custom-gradient-picker__padding: $grid-unit-20; // 48px container, 1 height: 20px; } -.components-custom-gradient-picker .components-custom-gradient-picker__toolbar { - border: none; - - // Work-around to target the inner button containers rendered by <ToolbarGroup /> - > div + div { - margin-left: 1px; - } - - button { - &.is-pressed { - > svg { - background: $white; - border: $border-width solid $gray-600; - border-radius: 2px; - } - } - } -} - .components-custom-gradient-picker__ui-line { position: relative; z-index: 0; diff --git a/packages/components/src/custom-select-control-v2/styles.ts b/packages/components/src/custom-select-control-v2/styles.ts index add1a29e1602d6..c82d6eba2e1a76 100644 --- a/packages/components/src/custom-select-control-v2/styles.ts +++ b/packages/components/src/custom-select-control-v2/styles.ts @@ -118,7 +118,7 @@ export const SelectPopover = styled( Ariakit.SelectPopover )` flex-direction: column; background-color: ${ COLORS.theme.background }; - border-radius: 2px; + border-radius: ${ CONFIG.radiusSmall }; border: 1px solid ${ COLORS.theme.foreground }; /* z-index(".components-popover") */ diff --git a/packages/components/src/date-time/date/styles.ts b/packages/components/src/date-time/date/styles.ts index c25cdca367910a..8f208b53fac22a 100644 --- a/packages/components/src/date-time/date/styles.ts +++ b/packages/components/src/date-time/date/styles.ts @@ -83,7 +83,7 @@ export const DayButton = styled( Button, { ` } &&& { - border-radius: 100%; + border-radius: ${ CONFIG.radiusRound }; height: ${ space( 7 ) }; width: ${ space( 7 ) }; @@ -107,7 +107,6 @@ export const DayButton = styled( Button, { ` ::before { background: ${ props.isSelected ? COLORS.white : COLORS.theme.accent }; - border-radius: 2px; bottom: 2px; content: " "; height: 4px; diff --git a/packages/components/src/focal-point-picker/styles/focal-point-style.ts b/packages/components/src/focal-point-picker/styles/focal-point-style.ts index 6f95978256f72e..ad1e8eeb286779 100644 --- a/packages/components/src/focal-point-picker/styles/focal-point-style.ts +++ b/packages/components/src/focal-point-picker/styles/focal-point-style.ts @@ -3,6 +3,11 @@ */ import styled from '@emotion/styled'; +/** + * Internal dependencies + */ +import { CONFIG } from '../../utils'; + export const PointerCircle = styled.div` background-color: transparent; cursor: grab; @@ -15,7 +20,7 @@ export const PointerCircle = styled.div` z-index: 10000; background: rgba( 255, 255, 255, 0.4 ); border: 1px solid rgba( 255, 255, 255, 0.4 ); - border-radius: 50%; + border-radius: ${ CONFIG.radiusRound }; backdrop-filter: blur( 16px ) saturate( 180% ); box-shadow: rgb( 0 0 0 / 10% ) 0px 0px 8px; diff --git a/packages/components/src/form-toggle/style.scss b/packages/components/src/form-toggle/style.scss index 6fd25590b56e41..dd7888403b34d4 100644 --- a/packages/components/src/form-toggle/style.scss +++ b/packages/components/src/form-toggle/style.scss @@ -54,7 +54,7 @@ $transition-duration: 0.2s; left: math.div($toggle-thumb-size, 6); width: $toggle-thumb-size; height: $toggle-thumb-size; - border-radius: 50%; + border-radius: $radius-round; transition: $transition-duration transform ease, $transition-duration background-color ease-out; diff --git a/packages/components/src/form-token-field/style.scss b/packages/components/src/form-token-field/style.scss index 57435a3f62ad26..cf5cc5b63e2227 100644 --- a/packages/components/src/form-token-field/style.scss +++ b/packages/components/src/form-token-field/style.scss @@ -102,7 +102,6 @@ &.is-error { .components-form-token-field__token-text { color: $alert-red; - border-radius: 4px 0 0 4px; padding: 0 4px 0 6px; } } @@ -133,7 +132,7 @@ } .components-form-token-field__token-text { - border-radius: 2px 0 0 2px; + border-radius: $radius-x-small 0 0 $radius-x-small; padding: 0 0 0 8px; white-space: nowrap; overflow: hidden; @@ -142,7 +141,7 @@ .components-form-token-field__remove-token.components-button { cursor: pointer; - border-radius: 0 2px 2px 0; + border-radius: 0 $radius-x-small $radius-x-small 0; padding: 0 2px; color: $gray-900; line-height: 10px; diff --git a/packages/components/src/input-control/styles/input-control-styles.tsx b/packages/components/src/input-control/styles/input-control-styles.tsx index 7a2040af9bdff9..c2be294424f50a 100644 --- a/packages/components/src/input-control/styles/input-control-styles.tsx +++ b/packages/components/src/input-control/styles/input-control-styles.tsx @@ -77,7 +77,7 @@ export const BackdropUI = styled.div< BackdropProps >` export const Root = styled( Flex )` box-sizing: border-box; position: relative; - border-radius: 2px; + border-radius: ${ CONFIG.radiusSmall }; padding-top: 0; // Focus within, excluding cases where auxiliary controls in prefix or suffix have focus. diff --git a/packages/components/src/navigation/styles/navigation-styles.tsx b/packages/components/src/navigation/styles/navigation-styles.tsx index 299a9b89bec709..580c0eef4dba8f 100644 --- a/packages/components/src/navigation/styles/navigation-styles.tsx +++ b/packages/components/src/navigation/styles/navigation-styles.tsx @@ -15,7 +15,7 @@ import { COLORS } from '../../utils/colors-values'; import Button from '../../button'; import { Text } from '../../text'; import { Heading } from '../../heading'; -import { rtl } from '../../utils'; +import { rtl, CONFIG } from '../../utils'; import { space } from '../../utils/space'; export const NavigationUI = styled.div` @@ -111,7 +111,7 @@ export const GroupTitleUI = styled( Heading )` `; export const ItemBaseUI = styled.li` - border-radius: 2px; + border-radius: ${ CONFIG.radiusSmall }; color: inherit; margin-bottom: 0; @@ -172,7 +172,7 @@ export const ItemBadgeUI = styled.span` margin-right: ${ () => ( isRTL() ? space( 2 ) : '0' ) }; display: inline-flex; padding: ${ space( 1 ) } ${ space( 3 ) }; - border-radius: 2px; + border-radius: ${ CONFIG.radiusSmall }; @keyframes fade-in { from { diff --git a/packages/components/src/range-control/styles/range-control-styles.ts b/packages/components/src/range-control/styles/range-control-styles.ts index ec1572d2679247..e2b651bd317da5 100644 --- a/packages/components/src/range-control/styles/range-control-styles.ts +++ b/packages/components/src/range-control/styles/range-control-styles.ts @@ -8,7 +8,7 @@ import styled from '@emotion/styled'; * Internal dependencies */ import NumberControl from '../../number-control'; -import { COLORS, rtl } from '../../utils'; +import { COLORS, rtl, CONFIG } from '../../utils'; import { space } from '../../utils/space'; import type { @@ -102,7 +102,7 @@ export const Rail = styled.span` position: absolute; margin-top: ${ ( rangeHeightValue - railHeight ) / 2 }px; top: 0; - border-radius: ${ railHeight }px; + border-radius: ${ CONFIG.radiusFull }; ${ railBackgroundColor }; `; @@ -119,7 +119,7 @@ const trackBackgroundColor = ( { disabled, trackColor }: TrackProps ) => { export const Track = styled.span` background-color: currentColor; - border-radius: ${ railHeight }px; + border-radius: ${ CONFIG.radiusFull }; height: ${ railHeight }px; pointer-events: none; display: block; @@ -203,7 +203,7 @@ export const ThumbWrapper = styled.span` top: 0; user-select: none; width: ${ thumbSize }px; - border-radius: 50%; + border-radius: ${ CONFIG.radiusRound }; ${ thumbColor }; ${ rtl( { marginLeft: -10 } ) }; @@ -221,7 +221,7 @@ const thumbFocus = ( { isFocused }: ThumbProps ) => { position: absolute; background-color: ${ COLORS.theme.accent }; opacity: 0.4; - border-radius: 50%; + border-radius: ${ CONFIG.radiusRound }; height: ${ thumbSize + 8 }px; width: ${ thumbSize + 8 }px; top: -4px; @@ -233,7 +233,7 @@ const thumbFocus = ( { isFocused }: ThumbProps ) => { export const Thumb = styled.span< ThumbProps >` align-items: center; - border-radius: 50%; + border-radius: ${ CONFIG.radiusRound }; height: 100%; outline: 0; position: absolute; @@ -281,7 +281,7 @@ const tooltipPosition = ( { position }: TooltipProps ) => { export const Tooltip = styled.span< TooltipProps >` background: rgba( 0, 0, 0, 0.8 ); - border-radius: 2px; + border-radius: ${ CONFIG.radiusSmall }; color: white; display: inline-block; font-size: 12px; diff --git a/packages/components/src/resizable-box/resize-tooltip/styles/resize-tooltip.styles.ts b/packages/components/src/resizable-box/resize-tooltip/styles/resize-tooltip.styles.ts index acd015687f81b8..1cfc2f381f2c11 100644 --- a/packages/components/src/resizable-box/resize-tooltip/styles/resize-tooltip.styles.ts +++ b/packages/components/src/resizable-box/resize-tooltip/styles/resize-tooltip.styles.ts @@ -7,7 +7,7 @@ import styled from '@emotion/styled'; * Internal dependencies */ import { Text } from '../../../text'; -import { font, COLORS } from '../../../utils'; +import { font, COLORS, CONFIG } from '../../../utils'; export const Root = styled.div` bottom: 0; @@ -31,7 +31,7 @@ export const TooltipWrapper = styled.div` export const Tooltip = styled.div` background: ${ COLORS.theme.foreground }; - border-radius: 2px; + border-radius: ${ CONFIG.radiusSmall }; box-sizing: border-box; font-family: ${ font( 'default.fontFamily' ) }; font-size: 12px; diff --git a/packages/components/src/resizable-box/style.scss b/packages/components/src/resizable-box/style.scss index eed13578b3f0c4..2e709a5bbb382d 100644 --- a/packages/components/src/resizable-box/style.scss +++ b/packages/components/src/resizable-box/style.scss @@ -28,7 +28,7 @@ $resize-handler-container-size: $resize-handler-size + ($grid-unit-05 * 2); // M content: ""; width: $resize-handler-size; height: $resize-handler-size; - border-radius: 50%; + border-radius: $radius-round; background: $white; cursor: inherit; position: absolute; @@ -43,7 +43,7 @@ $resize-handler-container-size: $resize-handler-size + ($grid-unit-05 * 2); // M // This is the "visible" resize handle for side handles - the line .components-resizable-box__side-handle::before { display: block; - border-radius: 2px; + border-radius: $radius-full; content: ""; width: 3px; height: 3px; diff --git a/packages/components/src/tab-panel/style.scss b/packages/components/src/tab-panel/style.scss index ab73a7affaeed4..229b32c7477e87 100644 --- a/packages/components/src/tab-panel/style.scss +++ b/packages/components/src/tab-panel/style.scss @@ -89,7 +89,6 @@ } &:focus-visible { - border-radius: 2px; box-shadow: 0 0 0 var(--wp-admin-border-width-focus) $components-color-accent; // Windows high contrast mode. diff --git a/packages/components/src/tabs/styles.ts b/packages/components/src/tabs/styles.ts index ddad0f7b2d767d..fcdb43512d82f9 100644 --- a/packages/components/src/tabs/styles.ts +++ b/packages/components/src/tabs/styles.ts @@ -7,7 +7,7 @@ import * as Ariakit from '@ariakit/react'; /** * Internal dependencies */ -import { COLORS } from '../utils'; +import { COLORS, CONFIG } from '../utils'; import { space } from '../utils/space'; export const TabListWrapper = styled.div` @@ -107,7 +107,7 @@ export const Tab = styled( Ariakit.Tab )` // Outline works for Windows high contrast mode as well. outline: var( --wp-admin-border-width-focus ) solid ${ COLORS.theme.accent }; - border-radius: 2px; + border-radius: ${ CONFIG.radiusSmall }; // Animation opacity: 0; @@ -136,7 +136,6 @@ export const TabPanel = styled( Ariakit.TabPanel )` } &:focus-visible { - border-radius: 2px; box-shadow: 0 0 0 var( --wp-admin-border-width-focus ) ${ COLORS.theme.accent }; // Windows high contrast mode. diff --git a/packages/customize-widgets/src/components/header/style.scss b/packages/customize-widgets/src/components/header/style.scss index 27460a82e0ad10..5c3f37a0bf0d42 100644 --- a/packages/customize-widgets/src/components/header/style.scss +++ b/packages/customize-widgets/src/components/header/style.scss @@ -30,7 +30,7 @@ align-items: center; .customize-widgets-header-toolbar__inserter-toggle.components-button.has-icon { - border-radius: 2px; + border-radius: $radius-small; color: $white; padding: 0; min-width: $grid-unit-30; diff --git a/packages/edit-site/src/components/layout/style.scss b/packages/edit-site/src/components/layout/style.scss index e4c95fed8b88b7..64fb1914af3dd3 100644 --- a/packages/edit-site/src/components/layout/style.scss +++ b/packages/edit-site/src/components/layout/style.scss @@ -259,25 +259,3 @@ html.canvas-mode-edit-transition::view-transition-group(toggle) { padding-left: 16px; padding-right: 16px; } - -.edit-site-layout.is-full-canvas { - .edit-site-layout__view-mode-toggle.components-button { - &:focus-visible, - &:focus { - - box-shadow: none; - outline: none; - outline-offset: 0; - - .edit-site-site-icon svg { - box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color, #3858e9); - outline: 3px solid #0000; - height: 40px; - width: 40px; - padding: 2px; - border-radius: 2px; - } - - } - } -} diff --git a/packages/edit-site/src/components/page-patterns/style.scss b/packages/edit-site/src/components/page-patterns/style.scss index ffcefd1924a535..34b258e3a92041 100644 --- a/packages/edit-site/src/components/page-patterns/style.scss +++ b/packages/edit-site/src/components/page-patterns/style.scss @@ -11,11 +11,6 @@ .dataviews-view-table & { width: 96px; flex-grow: 0; - border-radius: 2px; - - .page-patterns-preview-field__button { - border-radius: 2px; - } } .page-patterns-preview-field__button { diff --git a/packages/editor/src/components/create-template-part-modal/style.scss b/packages/editor/src/components/create-template-part-modal/style.scss index 85df0270e3a5a5..be15e8d76d536e 100644 --- a/packages/editor/src/components/create-template-part-modal/style.scss +++ b/packages/editor/src/components/create-template-part-modal/style.scss @@ -5,7 +5,7 @@ .editor-create-template-part-modal__area-radio-group { width: 100%; border: $border-width solid $gray-700; - border-radius: 2px; + border-radius: $radius-small; .components-button.editor-create-template-part-modal__area-radio { display: block; From 447293ef0b3a06e0b7cf068a5539194663ff8477 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Fri, 23 Aug 2024 09:20:17 -0500 Subject: [PATCH 0515/1908] Focus selected block in editor canvas when clicking edit button on zoom out mode toolbar (#64725) There is currently a focus loss when clicking the edit button on the zoom out mode toolbar. This sends focus to the contentRef, which lets writing flow handle sending the focus to the selected block. Co-authored-by: Dave Smith <getdavemail@gmail.com> --- .../src/components/block-tools/zoom-out-popover.js | 1 + .../src/components/block-tools/zoom-out-toolbar.js | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-tools/zoom-out-popover.js b/packages/block-editor/src/components/block-tools/zoom-out-popover.js index 0a7ab6d31fab8f..bb127351f09d87 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-popover.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-popover.js @@ -42,6 +42,7 @@ export default function ZoomOutPopover( { clientId, __unstableContentRef } ) { { ...props } > <ZoomOutToolbar + __unstableContentRef={ __unstableContentRef } clientId={ clientId } rootClientId={ rootClientId } /> diff --git a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js index b35c67482b4c78..b5503c253548b1 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js @@ -21,7 +21,11 @@ import BlockMover from '../block-mover'; import Shuffle from '../block-toolbar/shuffle'; import NavigableToolbar from '../navigable-toolbar'; -export default function ZoomOutToolbar( { clientId, rootClientId } ) { +export default function ZoomOutToolbar( { + clientId, + rootClientId, + __unstableContentRef, +} ) { const selected = useSelect( ( select ) => { const { @@ -133,6 +137,7 @@ export default function ZoomOutToolbar( { clientId, rootClientId } ) { label={ __( 'Edit' ) } onClick={ () => { __unstableSetEditorMode( 'edit' ); + __unstableContentRef.current?.focus(); } } /> ) } From 4e1210c9230a6913fd36f58b8d89befc7abda804 Mon Sep 17 00:00:00 2001 From: Ryan Welcher <me@ryanwelcher.com> Date: Fri, 23 Aug 2024 12:19:52 -0400 Subject: [PATCH 0516/1908] Update text to match code examples (#64751) Co-authored-by: ryanwelcher <welcher@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> --- docs/reference-guides/slotfills/README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/reference-guides/slotfills/README.md b/docs/reference-guides/slotfills/README.md index 5ae68cdb5cb071..b09aa5d49102e3 100644 --- a/docs/reference-guides/slotfills/README.md +++ b/docs/reference-guides/slotfills/README.md @@ -9,9 +9,9 @@ In order to use them, we must leverage the [@wordpress/plugins](/packages/plugin In order to access the SlotFills, we need to do four things: -1. Import the `registerPlugin` method from `wp.plugins`. -2. Import the SlotFill we want from `wp.editor`. -3. Define a method to render our changes. Our changes/additions will be wrapped in the SlotFill component we imported. +1. Import the `registerPlugin` method from the `@wordpress/plugins` package. +2. Import the SlotFill we want from the `@wordpress/editor'` package. +3. Define a component to render our changes. Our changes/additions will be wrapped in the SlotFill component we imported. 4. Register the plugin. Here is an example using the `PluginPostStatusInfo` slotFill: @@ -70,8 +70,7 @@ export default function PostSummary( { onActionPerformed } ) { const { isRemovedPostStatusPanel } = useSelect( ( select ) => { // We use isEditorPanelRemoved to hide the panel if it was programmatically removed. We do // not use isEditorPanelEnabled since this panel should not be disabled through the UI. - const { isEditorPanelRemoved } = - select( editorStore ); + const { isEditorPanelRemoved } = select( editorStore ); return { isRemovedPostStatusPanel: isEditorPanelRemoved( PANEL_NAME ), }; From a26967879c9ba4fa6bf644ae8a424bdffba1345b Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Fri, 23 Aug 2024 17:21:49 +0100 Subject: [PATCH 0517/1908] Revert Focus pattern inserter search when activating zoom out inserter (#64748) --- .../block-tools/zoom-out-mode-inserters.js | 8 +---- .../src/components/inserter/library.js | 2 -- .../src/components/inserter/menu.js | 34 +++++++------------ .../src/store/private-selectors.js | 4 --- packages/block-editor/src/store/reducer.js | 5 --- 5 files changed, 14 insertions(+), 39 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js index 6f986ce90dc3bd..bb044f9479c024 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js @@ -23,7 +23,6 @@ function ZoomOutModeInserters() { sectionRootClientId, selectedBlockClientId, hoveredBlockClientId, - inserterSearchInputRef, } = useSelect( ( select ) => { const { getSettings, @@ -33,11 +32,8 @@ function ZoomOutModeInserters() { getSelectedBlockClientId, getHoveredBlockClientId, isBlockInsertionPointVisible, - getInserterSearchInputRef, - } = unlock( select( blockEditorStore ) ); - + } = select( blockEditorStore ); const { sectionRootClientId: root } = unlock( getSettings() ); - return { hasSelection: !! getSelectionStart().clientId, blockInsertionPoint: getBlockInsertionPoint(), @@ -48,7 +44,6 @@ function ZoomOutModeInserters() { getSettings().__experimentalSetIsInserterOpened, selectedBlockClientId: getSelectedBlockClientId(), hoveredBlockClientId: getHoveredBlockClientId(), - inserterSearchInputRef: getInserterSearchInputRef(), }; }, [] ); @@ -115,7 +110,6 @@ function ZoomOutModeInserters() { showInsertionPoint( sectionRootClientId, index, { operation: 'insert', } ); - inserterSearchInputRef?.current?.focus(); } } /> ) } diff --git a/packages/block-editor/src/components/inserter/library.js b/packages/block-editor/src/components/inserter/library.js index fe14d48bb4016b..4e10a051996a9f 100644 --- a/packages/block-editor/src/components/inserter/library.js +++ b/packages/block-editor/src/components/inserter/library.js @@ -27,7 +27,6 @@ function InserterLibrary( onSelect = noop, shouldFocusBlock = false, onClose, - __experimentalSearchInputRef, }, ref ) { @@ -59,7 +58,6 @@ function InserterLibrary( shouldFocusBlock={ shouldFocusBlock } ref={ ref } onClose={ onClose } - __experimentalSearchInputRef={ __experimentalSearchInputRef } /> ); } diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index 629765315c1d6b..bac53b680c71fb 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -33,7 +33,6 @@ import useInsertionPoint from './hooks/use-insertion-point'; import { store as blockEditorStore } from '../../store'; import TabbedSidebar from '../tabbed-sidebar'; import { useZoomOut } from '../../hooks/use-zoom-out'; -import { unlock } from '../../lock-unlock'; const NOOP = () => {}; function InserterMenu( @@ -54,16 +53,11 @@ function InserterMenu( }, ref ) { - const { isZoomOutMode, inserterSearchInputRef } = useSelect( ( select ) => { - const { __unstableGetEditorMode, getInserterSearchInputRef } = unlock( - select( blockEditorStore ) - ); - return { - isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', - inserterSearchInputRef: getInserterSearchInputRef(), - }; - }, [] ); - + const isZoomOutMode = useSelect( + ( select ) => + select( blockEditorStore ).__unstableGetEditorMode() === 'zoom-out', + [] + ); const [ filterValue, setFilterValue, delayedFilterValue ] = useDebouncedInput( __experimentalFilterValue ); const [ hoveredItem, setHoveredItem ] = useState( null ); @@ -117,7 +111,7 @@ function InserterMenu( } } ); }, - [ onInsertBlocks, onSelect, ref, shouldFocusBlock ] + [ onInsertBlocks, onSelect, shouldFocusBlock ] ); const onInsertPattern = useCallback( @@ -126,7 +120,7 @@ function InserterMenu( onInsertBlocks( blocks, { patternName } ); onSelect(); }, - [ onInsertBlocks, onSelect, onToggleInsertionPoint ] + [ onInsertBlocks, onSelect ] ); const onHover = useCallback( @@ -177,9 +171,7 @@ function InserterMenu( value={ filterValue } label={ __( 'Search for blocks and patterns' ) } placeholder={ __( 'Search' ) } - ref={ inserterSearchInputRef } /> - { !! delayedFilterValue && ( <InserterSearchResults filterValue={ delayedFilterValue } @@ -200,18 +192,18 @@ function InserterMenu( ); }, [ selectedTab, + hoveredItem, + setHoveredItem, + setFilterValue, filterValue, - inserterSearchInputRef, delayedFilterValue, onSelect, onHover, - rootClientId, + shouldFocusBlock, clientId, - isAppender, + rootClientId, __experimentalInsertionIndex, - shouldFocusBlock, - hoveredItem, - setFilterValue, + isAppender, ] ); const blocksTab = useMemo( () => { diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 58479d69cbfbe7..3a6dcdd4e19e6b 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -512,10 +512,6 @@ export function getTemporarilyEditingFocusModeToRevert( state ) { return state.temporarilyEditingFocusModeRevert; } -export function getInserterSearchInputRef( state ) { - return state.inserterSearchInputRef; -} - /** * Returns the style attributes of multiple blocks. * diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index d9352670776371..91d853a50a6a42 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -2087,10 +2087,6 @@ export function hoveredBlockClientId( state = false, action ) { return state; } -export function inserterSearchInputRef( state = { current: null } ) { - return state; -} - const combinedReducers = combineReducers( { blocks, isDragging, @@ -2124,7 +2120,6 @@ const combinedReducers = combineReducers( { openedBlockSettingsMenu, registeredInserterMediaCategories, hoveredBlockClientId, - inserterSearchInputRef, } ); function withAutomaticChangeReset( reducer ) { From ccfe7dec027f630e2d0c0edad07b3bd1047e3d8d Mon Sep 17 00:00:00 2001 From: Ryan Welcher <me@ryanwelcher.com> Date: Fri, 23 Aug 2024 12:50:07 -0400 Subject: [PATCH 0518/1908] Provide better examples and remove outdating site edit references for the MainDashboardButton SlotFill (#64753) * Provide better examples and remove outdating site edit references. * Add experimental call out. Co-authored-by: ryanwelcher <welcher@git.wordpress.org> Co-authored-by: justintadlock <greenshady@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../slotfills/main-dashboard-button.md | 48 +++++++------------ 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/docs/reference-guides/slotfills/main-dashboard-button.md b/docs/reference-guides/slotfills/main-dashboard-button.md index a333b0f39a4e16..b55ed50648db15 100644 --- a/docs/reference-guides/slotfills/main-dashboard-button.md +++ b/docs/reference-guides/slotfills/main-dashboard-button.md @@ -1,21 +1,26 @@ # MainDashboardButton -This slot allows replacing the default main dashboard button in the post editor and site editor. +This slot allows replacing the default main dashboard button in the post editor. It is no longer available in the site editor as of WordPress 6.2. It's used for returning back to main wp-admin dashboard when editor is in fullscreen mode. +<div class="callout callout-warning"> + Please note that this SlotFill is still considered experimental and may change +</div> + ## Examples -### Post editor example +### Change the icon -This will override the W icon button in the header. +This will replace the W icon button in the header with a close icon. ```js import { registerPlugin } from '@wordpress/plugins'; import { __experimentalMainDashboardButton as MainDashboardButton } from '@wordpress/edit-post'; +import { close } from '@wordpress/icons'; const MainDashboardButtonTest = () => ( <MainDashboardButton> - Custom main dashboard button content + <FullscreenModeClose icon={ close } /> </MainDashboardButton> ); @@ -24,8 +29,11 @@ registerPlugin( 'main-dashboard-button-test', { } ); ``` -If your goal is just to replace the icon of the existing button in -the post editor, that can be achieved in the following way: +![The edit post screen in fullscreen mode displaying a close icon instead of the default W](https://developer.wordpress.org/files/2024/08/main-dashboard-button-close-icon-example.png 'Replace the W icon button in the header with a close icon') + +### Change the icon and link + +This example will change the icon in the header to indicate an external link that will take the user to http://wordpress.org when clicked. ```js import { registerPlugin } from '@wordpress/plugins'; @@ -33,11 +41,11 @@ import { __experimentalFullscreenModeClose as FullscreenModeClose, __experimentalMainDashboardButton as MainDashboardButton, } from '@wordpress/edit-post'; -import { close } from '@wordpress/icons'; +import { external } from '@wordpress/icons'; const MainDashboardButtonIconTest = () => ( <MainDashboardButton> - <FullscreenModeClose icon={ close } href="http://wordpress.org" /> + <FullscreenModeClose icon={ external } href="http://wordpress.org" /> </MainDashboardButton> ); @@ -46,26 +54,4 @@ registerPlugin( 'main-dashboard-button-icon-test', { } ); ``` -### Site editor example - -In the site editor this slot refers to the "back to dashboard" button in the navigation sidebar. - -```js -import { registerPlugin } from '@wordpress/plugins'; -import { __experimentalMainDashboardButton as MainDashboardButton } from '@wordpress/edit-site'; -import { __experimentalNavigationBackButton as NavigationBackButton } from '@wordpress/components'; - -const MainDashboardButtonIconTest = () => ( - <MainDashboardButton> - <NavigationBackButton - backButtonLabel={ __( 'Back to dashboard' ) } - className="edit-site-navigation-panel__back-to-dashboard" - href="index.php" - /> - </MainDashboardButton> -); - -registerPlugin( 'main-dashboard-button-icon-test', { - render: MainDashboardButtonIconTest, -} ); -``` +![The edit post screen in fullscreen mode displaying an external link icon instead of the default W](https://developer.wordpress.org/files/2024/08/main-dashboard-button-external-link-example.png 'Change the icon in the header to indicate an external link that will take the user to http://wordpress.org when clicked') From 903f2f4cb3a797ba5b4064a3e036f9fece07f5bb Mon Sep 17 00:00:00 2001 From: Ryan Welcher <me@ryanwelcher.com> Date: Fri, 23 Aug 2024 13:08:08 -0400 Subject: [PATCH 0519/1908] Update the import for PluginBlockSettingsMenuItem (#64758) Co-authored-by: ryanwelcher <welcher@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> --- .../slotfills/plugin-block-settings-menu-item.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference-guides/slotfills/plugin-block-settings-menu-item.md b/docs/reference-guides/slotfills/plugin-block-settings-menu-item.md index 8e17893b546421..aa1eecb293261c 100644 --- a/docs/reference-guides/slotfills/plugin-block-settings-menu-item.md +++ b/docs/reference-guides/slotfills/plugin-block-settings-menu-item.md @@ -7,7 +7,7 @@ This will either appear in the controls for each block or at the Top Toolbar dep ```js import { registerPlugin } from '@wordpress/plugins'; -import { PluginBlockSettingsMenuItem } from '@wordpress/edit-post'; +import { PluginBlockSettingsMenuItem } from '@wordpress/editor'; const PluginBlockSettingsMenuGroupTest = () => ( <PluginBlockSettingsMenuItem From 1e3efbb73a0984e40e67490b38f92929f54ce947 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 23 Aug 2024 19:35:08 +0200 Subject: [PATCH 0520/1908] Navigator: remove location history, simplify internal logic (#64675) * Remove location history and only use current location * Deprecate `options.replace` * Make sure that two screens with the same path cannot be added * Re-implement focus restoration relying on a map with paths as keys * Re-implement the isInitial flag by relying on the initialPath * Update README * Comment map deletion out * CHANGELOG * Fix broken focus restoration by updating focusSelectors in the navigator reducer * create a copy of focusSelectors map only when necessary * Set isInitial inside the reducer, instead of on the context value --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 5 + .../navigator/navigator-provider/README.md | 5 +- .../navigator-provider/component.tsx | 173 +++++++++--------- packages/components/src/navigator/types.ts | 4 +- 4 files changed, 100 insertions(+), 87 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 542d2b8334ed67..44536df98b5815 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Deprecations + +- Deprecate `replace` from the options accepted by `useNavigator().goTo()` ([#64675](https://github.com/WordPress/gutenberg/pull/64675)). + ### Enhancements - `ColorPicker`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). @@ -16,6 +20,7 @@ - `TabPanel`: Remove radius applied to panel focus style ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). - `Tabs`: Remove radius applied to panel focus style ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). - `UnitControl`: Update unit select styles ([#64712](https://github.com/WordPress/gutenberg/pull/64712)). +- `Navigator`: remove location history, simplify internal logic ([#64675](https://github.com/WordPress/gutenberg/pull/64675)). - Decrease horizontal padding from 16px to 12px on the following components, when in the 40px default size ([#64708](https://github.com/WordPress/gutenberg/pull/64708)). - `AnglePickerControl` - `ColorPicker` (on the inputs) diff --git a/packages/components/src/navigator/navigator-provider/README.md b/packages/components/src/navigator/navigator-provider/README.md index 13745fae68a15d..35bf7a69720be2 100644 --- a/packages/components/src/navigator/navigator-provider/README.md +++ b/packages/components/src/navigator/navigator-provider/README.md @@ -72,7 +72,6 @@ The available options are: - `focusTargetSelector`: `string`. An optional property used to specify the CSS selector used to restore focus on the matching element when navigating back; - `isBack`: `boolean`. An optional property used to specify whether the navigation should be considered as backwards (thus enabling focus restoration when possible, and causing the animation to be backwards too); - `skipFocus`: `boolean`. An optional property used to opt out of `Navigator`'s focus management, useful when the consumer of the component wants to manage focus themselves; -- `replace`: `boolean`. An optional property used to cause the new location to replace the current location in the stack. ### `goBack`: `( path: string, options: NavigateOptions ) => void` @@ -87,8 +86,8 @@ The available options are the same as for the `goTo` method, except for the `isB The `location` object represent the current location, and has a few properties: - `path`: `string`. The path associated to the location. -- `isBack`: `boolean`. A flag that is `true` when the current location was reached by navigating backwards in the location history. -- `isInitial`: `boolean`. A flag that is `true` only for the first (root) location in the location history. +- `isBack`: `boolean`. A flag that is `true` when the current location was reached by navigating backwards. +- `isInitial`: `boolean`. A flag that is `true` only for the initial location. ### `params`: `Record< string, string | string[] >` diff --git a/packages/components/src/navigator/navigator-provider/component.tsx b/packages/components/src/navigator/navigator-provider/component.tsx index 78bc674c06fbd5..8e596778c7f21c 100644 --- a/packages/components/src/navigator/navigator-provider/component.tsx +++ b/packages/components/src/navigator/navigator-provider/component.tsx @@ -37,14 +37,22 @@ type RouterAction = | { type: 'gotoparent'; options?: NavigateToParentOptions }; type RouterState = { + initialPath: string; screens: Screen[]; - locationHistory: NavigatorLocation[]; + currentLocation: NavigatorLocation; matchedPath: MatchedPath; + focusSelectors: Map< string, string >; }; -const MAX_HISTORY_LENGTH = 50; - function addScreen( { screens }: RouterState, screen: Screen ) { + if ( screens.some( ( s ) => s.path === screen.path ) ) { + // eslint-disable-next-line no-console + console.warn( + `Navigator: a screen with path ${ screen.path } already exists. +The screen with id ${ screen.id } will not be added.` + ); + return screens; + } return [ ...screens, screen ]; } @@ -52,95 +60,74 @@ function removeScreen( { screens }: RouterState, screen: Screen ) { return screens.filter( ( s ) => s.id !== screen.id ); } -function goBack( { locationHistory }: RouterState ) { - if ( locationHistory.length <= 1 ) { - return locationHistory; - } - return [ - ...locationHistory.slice( 0, -2 ), - { - ...locationHistory[ locationHistory.length - 2 ], - isBack: true, - hasRestoredFocus: false, - }, - ]; -} - function goTo( state: RouterState, path: string, options: NavigateOptions = {} ) { - const { locationHistory } = state; + const { currentLocation, focusSelectors } = state; + const { - focusTargetSelector, + // Default assignments isBack = false, skipFocus = false, - replace = false, + // Extract to avoid forwarding + replace, + focusTargetSelector, + // Rest ...restOptions } = options; - const isNavigatingToSamePath = - locationHistory.length > 0 && - locationHistory[ locationHistory.length - 1 ].path === path; - if ( isNavigatingToSamePath ) { - return locationHistory; - } - - const isNavigatingToPreviousPath = - isBack && - locationHistory.length > 1 && - locationHistory[ locationHistory.length - 2 ].path === path; - - if ( isNavigatingToPreviousPath ) { - return goBack( state ); + if ( currentLocation?.path === path ) { + return { currentLocation, focusSelectors }; } - const newLocation = { - ...restOptions, - path, - isBack, - hasRestoredFocus: false, - skipFocus, - }; + let focusSelectorsCopy; - if ( locationHistory.length === 0 ) { - return replace ? [] : [ newLocation ]; + // Set a focus selector that will be used when navigating + // back to the current location. + if ( focusTargetSelector && currentLocation?.path ) { + if ( ! focusSelectorsCopy ) { + focusSelectorsCopy = new Map( state.focusSelectors ); + } + focusSelectorsCopy.set( currentLocation.path, focusTargetSelector ); } - const newLocationHistory = locationHistory.slice( - locationHistory.length > MAX_HISTORY_LENGTH - 1 ? 1 : 0, - -1 - ); - - if ( ! replace ) { - newLocationHistory.push( - // Assign `focusTargetSelector` to the previous location in history - // (the one we just navigated from). - { - ...locationHistory[ locationHistory.length - 1 ], - focusTargetSelector, - } - ); + // Get the focus selector for the new location. + let currentFocusSelector; + if ( isBack ) { + if ( ! focusSelectorsCopy ) { + focusSelectorsCopy = new Map( state.focusSelectors ); + } + currentFocusSelector = focusSelectorsCopy.get( path ); + focusSelectorsCopy.delete( path ); } - newLocationHistory.push( newLocation ); - - return newLocationHistory; + return { + currentLocation: { + ...restOptions, + path, + isBack, + hasRestoredFocus: false, + focusTargetSelector: currentFocusSelector, + skipFocus, + }, + focusSelectors: focusSelectorsCopy ?? focusSelectors, + }; } function goToParent( state: RouterState, options: NavigateToParentOptions = {} ) { - const { locationHistory, screens } = state; - const currentPath = locationHistory[ locationHistory.length - 1 ].path; + const { currentLocation, screens, focusSelectors } = state; + const currentPath = currentLocation?.path; if ( currentPath === undefined ) { - return locationHistory; + return { currentLocation, focusSelectors }; } const parentPath = findParent( currentPath, screens ); if ( parentPath === undefined ) { - return locationHistory; + return { currentLocation, focusSelectors }; } return goTo( state, parentPath, { ...options, @@ -152,7 +139,13 @@ function routerReducer( state: RouterState, action: RouterAction ): RouterState { - let { screens, locationHistory, matchedPath } = state; + let { + screens, + currentLocation, + matchedPath, + focusSelectors, + ...restState + } = state; switch ( action.type ) { case 'add': screens = addScreen( state, action.screen ); @@ -161,26 +154,31 @@ function routerReducer( screens = removeScreen( state, action.screen ); break; case 'goto': - locationHistory = goTo( state, action.path, action.options ); + const goToNewState = goTo( state, action.path, action.options ); + currentLocation = goToNewState.currentLocation; + focusSelectors = goToNewState.focusSelectors; break; case 'gotoparent': - locationHistory = goToParent( state, action.options ); + const goToParentNewState = goToParent( state, action.options ); + currentLocation = goToParentNewState.currentLocation; + focusSelectors = goToParentNewState.focusSelectors; break; } + if ( currentLocation?.path === state.initialPath ) { + currentLocation = { ...currentLocation, isInitial: true }; + } + // Return early in case there is no change if ( screens === state.screens && - locationHistory === state.locationHistory + currentLocation === state.currentLocation ) { return state; } // Compute the matchedPath - const currentPath = - locationHistory.length > 0 - ? locationHistory[ locationHistory.length - 1 ].path - : undefined; + const currentPath = currentLocation?.path; matchedPath = currentPath !== undefined ? patternMatch( currentPath, screens ) @@ -197,23 +195,35 @@ function routerReducer( matchedPath = state.matchedPath; } - return { screens, locationHistory, matchedPath }; + return { + ...restState, + screens, + currentLocation, + matchedPath, + focusSelectors, + }; } function UnconnectedNavigatorProvider( props: WordPressComponentProps< NavigatorProviderProps, 'div' >, forwardedRef: ForwardedRef< any > ) { - const { initialPath, children, className, ...otherProps } = - useContextSystem( props, 'NavigatorProvider' ); + const { + initialPath: initialPathProp, + children, + className, + ...otherProps + } = useContextSystem( props, 'NavigatorProvider' ); const [ routerState, dispatch ] = useReducer( routerReducer, - initialPath, + initialPathProp, ( path ) => ( { screens: [], - locationHistory: [ { path } ], + currentLocation: { path }, matchedPath: undefined, + focusSelectors: new Map(), + initialPath: initialPathProp, } ) ); @@ -242,19 +252,16 @@ function UnconnectedNavigatorProvider( [] ); - const { locationHistory, matchedPath } = routerState; + const { currentLocation, matchedPath } = routerState; const navigatorContextValue: NavigatorContextType = useMemo( () => ( { - location: { - ...locationHistory[ locationHistory.length - 1 ], - isInitial: locationHistory.length === 1, - }, + location: currentLocation, params: matchedPath?.params ?? {}, match: matchedPath?.id, ...methods, } ), - [ locationHistory, matchedPath, methods ] + [ currentLocation, matchedPath, methods ] ); const cx = useCx(); diff --git a/packages/components/src/navigator/types.ts b/packages/components/src/navigator/types.ts index c45762d558af2d..855787b4d0a193 100644 --- a/packages/components/src/navigator/types.ts +++ b/packages/components/src/navigator/types.ts @@ -28,7 +28,9 @@ export type NavigateOptions = { */ skipFocus?: boolean; /** - * Whether the navigation should replace the current location in the stack. + * Note: this option is deprecated and currently doesn't have any effect. + * @deprecated + * @ignore */ replace?: boolean; }; From f25c5ee56d776ebd70f894cb63ec72554f4b93bd Mon Sep 17 00:00:00 2001 From: Ryan Welcher <me@ryanwelcher.com> Date: Fri, 23 Aug 2024 13:49:52 -0400 Subject: [PATCH 0521/1908] Update screenshot and description. (#64759) Co-authored-by: ryanwelcher <welcher@git.wordpress.org> Co-authored-by: justintadlock <greenshady@git.wordpress.org> --- docs/reference-guides/slotfills/plugin-sidebar.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/reference-guides/slotfills/plugin-sidebar.md b/docs/reference-guides/slotfills/plugin-sidebar.md index dbf1c5643d3aab..9bf911b3bb13f2 100644 --- a/docs/reference-guides/slotfills/plugin-sidebar.md +++ b/docs/reference-guides/slotfills/plugin-sidebar.md @@ -2,6 +2,7 @@ This slot allows adding items to the tool bar of either the Post or Site editor screens. Using this slot will add an icon to the toolbar that, when clicked, opens a panel with containing the items wrapped in the `<PluginSidebar />` component. +Additionally, it will also create a `<PluginSidebarMoreMenuItem />` that will allow opening the panel from Options panel when clicked. ## Example @@ -63,6 +64,4 @@ registerPlugin( 'plugin-sidebar-example', { render: PluginSidebarExample } ); ## Location -### Open State - -![Open State](https://raw.githubusercontent.com/WordPress/gutenberg/HEAD/docs/assets/plugin-sidebar-open-state.png?raw=true) +![PluginSidebar example expanded](https://developer.wordpress.org/files/2024/08/plugin-sidebar-example.png) From 5e90ab40b0fa7f342cb63b4820e4a5c72576acc0 Mon Sep 17 00:00:00 2001 From: Ryan Welcher <me@ryanwelcher.com> Date: Fri, 23 Aug 2024 15:40:44 -0400 Subject: [PATCH 0522/1908] PluginSidebarMoreMenuItem: Update example, screenshot and description. (#64761) * Update example, screenshot and description. * Update docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md Co-authored-by: Nick Diego <nick.diego@automattic.com> * Update docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md Co-authored-by: Nick Diego <nick.diego@automattic.com> * Update docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md Co-authored-by: Nick Diego <nick.diego@automattic.com> --------- Co-authored-by: Nick Diego <nick.diego@automattic.com> Co-authored-by: ryanwelcher <welcher@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> --- .../plugin-sidebar-more-menu-item.md | 79 +++++++++++++++---- 1 file changed, 63 insertions(+), 16 deletions(-) diff --git a/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md b/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md index 76fb3018de7b68..4a4ff98697b5f3 100644 --- a/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md +++ b/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md @@ -1,31 +1,78 @@ # PluginSidebarMoreMenuItem -This slot allows the creation of a `<PluginSidebar>` with a menu item that when clicked will expand the sidebar to the appropriate Plugin section. -This is done by setting the `target` on `<PluginSidebarMoreMenuItem>` to match the `name` on the `<PluginSidebar>` +This slot is used to allow the opening of a `<PluginSidebar />` panel from the Options dropdown. +When a `<PluginSidebar />` is registered, a `<PluginSidebarMoreMenuItem />` is automatically registered using the title prop from the `<PluginSidebar />` and so it's not required to use this slot to create the menu item. ## Example +This example shows how customize the text for the menu item instead of using the default text provided by the `<PluginSidebar />` title. + ```js -import { registerPlugin } from '@wordpress/plugins'; +import { __ } from '@wordpress/i18n'; import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/editor'; +import { + PanelBody, + Button, + TextControl, + SelectControl, +} from '@wordpress/components'; +import { registerPlugin } from '@wordpress/plugins'; +import { useState } from '@wordpress/element'; import { image } from '@wordpress/icons'; -const PluginSidebarMoreMenuItemTest = () => ( - <> - <PluginSidebarMoreMenuItem target="sidebar-name" icon={ image }> - Expanded Sidebar - More item - </PluginSidebarMoreMenuItem> - <PluginSidebar name="sidebar-name" icon={ image } title="My Sidebar"> - Content of the sidebar - </PluginSidebar> - </> -); - -registerPlugin( 'plugin-sidebar-expanded-test', { +const PluginSidebarMoreMenuItemTest = () => { + const [ text, setText ] = useState( '' ); + const [ select, setSelect ] = useState( 'a' ); + return ( + <> + <PluginSidebarMoreMenuItem target="sidebar-name" icon={ image }> + { __( 'Custom Menu Item Text' ) } + </PluginSidebarMoreMenuItem> + <PluginSidebar + name="sidebar-name" + icon={ image } + title="My Sidebar" + > + <PanelBody> + <h2> + { __( + 'This is a heading for the PluginSidebar example.' + ) } + </h2> + <p> + { __( + 'This is some example text for the PluginSidebar example.' + ) } + </p> + <TextControl + label={ __( 'Text Control' ) } + value={ text } + onChange={ ( newText ) => setText( newText ) } + /> + <SelectControl + label={ __( 'Select Control' ) } + value={ select } + options={ [ + { value: 'a', label: __( 'Option A' ) }, + { value: 'b', label: __( 'Option B' ) }, + { value: 'c', label: __( 'Option C' ) }, + ] } + onChange={ ( newSelect ) => setSelect( newSelect ) } + /> + <Button variant="primary"> + { __( 'Primary Button' ) }{ ' ' } + </Button> + </PanelBody> + </PluginSidebar> + </> + ); +}; + +registerPlugin( 'plugin-sidebar-more-menu-item-example', { render: PluginSidebarMoreMenuItemTest, } ); ``` ## Location -![Interaction](https://raw.githubusercontent.com/WordPress/gutenberg/HEAD/docs/assets/plugin-sidebar-more-menu-item.gif?raw=true) +![Interaction](https://developer.wordpress.org/files/2024/08/pluginsidebar-more-menu-item-1.gif) From 604d7b2c44a75ad2e162914efd7e7446d7f44466 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 23 Aug 2024 23:51:07 +0400 Subject: [PATCH 0523/1908] Block Bindings: Fix ESLint warnings (#64684) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/block-library/src/button/edit.js | 2 +- packages/block-library/src/image/edit.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/button/edit.js b/packages/block-library/src/button/edit.js index 28d42ef16ca1e4..d7b8e6486c3c66 100644 --- a/packages/block-library/src/button/edit.js +++ b/packages/block-library/src/button/edit.js @@ -254,7 +254,7 @@ function ButtonEdit( props ) { } ), }; }, - [ isSelected, metadata?.bindings?.url ] + [ context, isSelected, metadata?.bindings?.url ] ); return ( diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index 9eba4dacb57c31..fb11b3f50a5b64 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -322,7 +322,7 @@ export function ImageEdit( { : __( 'Connected to dynamic data' ), }; }, - [ isSingleSelected, metadata?.bindings?.url ] + [ context, isSingleSelected, metadata?.bindings?.url ] ); const placeholder = ( content ) => { return ( From 46ad90a5630344c7280e18f8149d7898458b281c Mon Sep 17 00:00:00 2001 From: Ryan Welcher <me@ryanwelcher.com> Date: Fri, 23 Aug 2024 16:00:30 -0400 Subject: [PATCH 0524/1908] Removing ryanwelcher as a docs codeowner because my inbox is dead. (#64762) Co-authored-by: ryanwelcher <welcher@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e5f958eb9e9d85..bf778bd434e110 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,5 +1,5 @@ # Documentation -/docs @ajitbohra @ryanwelcher @juanmaguitar @fabiankaegy @ndiego +/docs @ajitbohra @juanmaguitar @fabiankaegy @ndiego /packages/interactivity/docs @juanmaguitar # Schemas From 042f320a909817f49e4061ceae5115344b684316 Mon Sep 17 00:00:00 2001 From: Rohit Mathur <62138457+rohitmathur-7@users.noreply.github.com> Date: Sat, 24 Aug 2024 13:35:51 +0530 Subject: [PATCH 0525/1908] Cover Block: Move Clear Media button from Inspector Controls to Block Controls. (#64630) Unlinked contributors: rohitmathur-7. Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../src/cover/edit/block-controls.js | 13 ++++- .../block-library/src/cover/edit/index.js | 1 + .../src/cover/edit/inspector-controls.js | 13 ----- packages/block-library/src/cover/test/edit.js | 52 ++++++++++--------- 4 files changed, 41 insertions(+), 38 deletions(-) diff --git a/packages/block-library/src/cover/edit/block-controls.js b/packages/block-library/src/cover/edit/block-controls.js index c4137ad2a8409a..499aef5e9a8cf7 100644 --- a/packages/block-library/src/cover/edit/block-controls.js +++ b/packages/block-library/src/cover/edit/block-controls.js @@ -10,6 +10,7 @@ import { __experimentalBlockFullHeightAligmentControl as FullHeightAlignmentControl, privateApis as blockEditorPrivateApis, } from '@wordpress/block-editor'; +import { MenuItem } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; /** @@ -26,6 +27,7 @@ export default function CoverBlockControls( { onSelectMedia, currentSettings, toggleUseFeaturedImage, + onClearMedia, } ) { const { contentPosition, id, useFeaturedImage, minHeight, minHeightUnit } = attributes; @@ -101,7 +103,16 @@ export default function CoverBlockControls( { onToggleFeaturedImage={ toggleUseFeaturedImage } useFeaturedImage={ useFeaturedImage } name={ ! url ? __( 'Add Media' ) : __( 'Replace' ) } - /> + > + { !! url && ( + <MenuItem + className="block-library-cover__reset-button" + onClick={ onClearMedia } + > + { __( 'Reset' ) } + </MenuItem> + ) } + </MediaReplaceFlow> </BlockControls> </> ); diff --git a/packages/block-library/src/cover/edit/index.js b/packages/block-library/src/cover/edit/index.js index 458f279e8748b8..3f68c08b632ace 100644 --- a/packages/block-library/src/cover/edit/index.js +++ b/packages/block-library/src/cover/edit/index.js @@ -398,6 +398,7 @@ function CoverEdit( { onSelectMedia={ onSelectMedia } currentSettings={ currentSettings } toggleUseFeaturedImage={ toggleUseFeaturedImage } + onClearMedia={ onClearMedia } /> ); diff --git a/packages/block-library/src/cover/edit/inspector-controls.js b/packages/block-library/src/cover/edit/inspector-controls.js index 10bd3de890a0c4..fd83ba716ddd45 100644 --- a/packages/block-library/src/cover/edit/inspector-controls.js +++ b/packages/block-library/src/cover/edit/inspector-controls.js @@ -3,11 +3,9 @@ */ import { useMemo } from '@wordpress/element'; import { - Button, ExternalLink, FocalPointPicker, PanelBody, - PanelRow, RangeControl, TextareaControl, ToggleControl, @@ -93,7 +91,6 @@ export default function CoverInspectorControls( { coverRef, currentSettings, updateDimRatio, - onClearMedia, } ) { const { useFeaturedImage, @@ -228,16 +225,6 @@ export default function CoverInspectorControls( { } /> ) } - <PanelRow> - <Button - variant="secondary" - size="small" - className="block-library-cover__reset-button" - onClick={ onClearMedia } - > - { __( 'Clear Media' ) } - </Button> - </PanelRow> </PanelBody> ) } </InspectorControls> diff --git a/packages/block-library/src/cover/test/edit.js b/packages/block-library/src/cover/test/edit.js index ca34c15d0b7ec6..97c52a47ec4d72 100644 --- a/packages/block-library/src/cover/test/edit.js +++ b/packages/block-library/src/cover/test/edit.js @@ -155,6 +155,34 @@ describe( 'Cover block', () => { 'is-position-top-left' ); } ); + + test( 'clears media when clear media button clicked', async () => { + await setup( { + url: 'http://localhost/my-image.jpg', + } ); + + await selectBlock( 'Block: Cover' ); + expect( + within( screen.getByLabelText( 'Block: Cover' ) ).getByRole( + 'img' + ) + ).toBeInTheDocument(); + + await userEvent.click( + screen.getByRole( 'button', { name: 'Replace' } ) + ); + await userEvent.click( + screen.getByRole( 'menuitem', { + name: 'Reset', + } ) + ); + + expect( + within( screen.getByLabelText( 'Block: Cover' ) ).queryByRole( + 'img' + ) + ).not.toBeInTheDocument(); + } ); } ); describe( 'Inspector controls', () => { @@ -242,30 +270,6 @@ describe( 'Cover block', () => { expect( screen.getByAltText( 'Me' ) ).toBeInTheDocument(); } ); - test( 'clears media when clear media button clicked', async () => { - await setup( { - url: 'http://localhost/my-image.jpg', - } ); - - await selectBlock( 'Block: Cover' ); - expect( - within( screen.getByLabelText( 'Block: Cover' ) ).getByRole( - 'img' - ) - ).toBeInTheDocument(); - - await userEvent.click( - screen.getByRole( 'button', { - name: 'Clear Media', - } ) - ); - expect( - within( screen.getByLabelText( 'Block: Cover' ) ).queryByRole( - 'img' - ) - ).not.toBeInTheDocument(); - } ); - describe( 'Color panel', () => { test( 'applies selected opacity to block when number control value changed', async () => { const { container } = await setup(); From da007bbf7d6ebaf0d058619cb12d9bb63a4bda2d Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Sat, 24 Aug 2024 23:17:20 +0530 Subject: [PATCH 0526/1908] Fix closing tag issue in api-reference.md (#64778) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> --- docs/reference-guides/interactivity-api/api-reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference-guides/interactivity-api/api-reference.md b/docs/reference-guides/interactivity-api/api-reference.md index 46bd20bece0bda..e9b005d55899e8 100644 --- a/docs/reference-guides/interactivity-api/api-reference.md +++ b/docs/reference-guides/interactivity-api/api-reference.md @@ -501,7 +501,7 @@ The `unique-id` doesn't need to be unique globally. It just needs to be differen ```html <div data-wp-init="callbacks.logTimeInit"> - <p>Hi!</> + <p>Hi!</p> </div> ``` From f42d7753866d5b870931489fef1d2ab204d65413 Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Sat, 24 Aug 2024 22:48:36 +0200 Subject: [PATCH 0527/1908] Fix hacky block editor settings filter (#64743) --- .../block-editor-settings-mobile.php | 25 ++++++------------- ...-rest-block-editor-settings-controller.php | 4 +++ .../block-editor-settings-mobile-test.php | 12 +++------ 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/lib/experimental/block-editor-settings-mobile.php b/lib/experimental/block-editor-settings-mobile.php index 91e3694c199f83..62c03db222afce 100644 --- a/lib/experimental/block-editor-settings-mobile.php +++ b/lib/experimental/block-editor-settings-mobile.php @@ -16,24 +16,15 @@ * @return array New block editor settings. */ function gutenberg_get_block_editor_settings_mobile( $settings ) { - if ( - defined( 'REST_REQUEST' ) && - REST_REQUEST && - isset( $_GET['context'] ) && - 'mobile' === $_GET['context'] - ) { - if ( wp_theme_has_theme_json() ) { - $settings['__experimentalStyles'] = gutenberg_get_global_styles(); - } - - // To tell mobile that the site uses quote v2 (inner blocks). - // See https://github.com/WordPress/gutenberg/pull/25892. - $settings['__experimentalEnableQuoteBlockV2'] = true; - // To tell mobile that the site uses list v2 (inner blocks). - $settings['__experimentalEnableListBlockV2'] = true; + if ( wp_theme_has_theme_json() ) { + $settings['__experimentalStyles'] = gutenberg_get_global_styles(); } + // To tell mobile that the site uses quote v2 (inner blocks). + // See https://github.com/WordPress/gutenberg/pull/25892. + $settings['__experimentalEnableQuoteBlockV2'] = true; + // To tell mobile that the site uses list v2 (inner blocks). + $settings['__experimentalEnableListBlockV2'] = true; + return $settings; } - -add_filter( 'block_editor_settings_all', 'gutenberg_get_block_editor_settings_mobile', PHP_INT_MAX ); diff --git a/lib/experimental/class-wp-rest-block-editor-settings-controller.php b/lib/experimental/class-wp-rest-block-editor-settings-controller.php index 2c4bf29bc21a73..ed2dcfe8584a6c 100644 --- a/lib/experimental/class-wp-rest-block-editor-settings-controller.php +++ b/lib/experimental/class-wp-rest-block-editor-settings-controller.php @@ -93,9 +93,13 @@ public function get_items( $request ) { // phpcs:ignore VariableAnalysis.CodeAna break; } + add_filter( 'block_editor_settings_all', 'gutenberg_get_block_editor_settings_mobile', PHP_INT_MAX ); + $editor_context = new WP_Block_Editor_Context( array( 'name' => $editor_context_name ) ); $settings = get_block_editor_settings( array(), $editor_context ); + remove_filter( 'block_editor_settings_all', 'gutenberg_get_block_editor_settings_mobile', PHP_INT_MAX ); + return rest_ensure_response( $settings ); } diff --git a/phpunit/experimental/block-editor-settings-mobile-test.php b/phpunit/experimental/block-editor-settings-mobile-test.php index 907b750d8c8638..967efebc346fc8 100644 --- a/phpunit/experimental/block-editor-settings-mobile-test.php +++ b/phpunit/experimental/block-editor-settings-mobile-test.php @@ -10,11 +10,6 @@ * * @covers WP_REST_Block_Editor_Settings_Controller */ - -if ( ! defined( 'REST_REQUEST' ) ) { - define( 'REST_REQUEST', true ); -} - class Gutenberg_REST_Block_Editor_Settings_Controller_Test extends WP_Test_REST_Controller_Testcase { /** * @var int @@ -56,10 +51,9 @@ public function test_register_routes() { public function test_get_items() { wp_set_current_user( self::$admin_id ); $request = new WP_REST_Request( 'GET', '/wp-block-editor/v1/settings' ); - // Set context for mobile settings. - $_GET['context'] = 'mobile'; - $response = rest_get_server()->dispatch( $request ); - $data = $response->get_data(); + $request->set_param( 'context', 'mobile' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); $this->assertArrayHasKey( '__experimentalStyles', $data, '__experimentalStyles should be in the returned data' ); $this->assertArrayHasKey( '__experimentalFeatures', $data, '__experimentalFeatures should be in the returned data' ); From c48c800eb9a26acd9eb3f16d8c254852fc032574 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Sun, 25 Aug 2024 18:28:29 +0900 Subject: [PATCH 0528/1908] Replace NavigatorToParentButton with NavigatorBackButton (#64775) * Navigator: Replace deprecated NavigatorToParentButton with NavigatorBackButton * Update storybook --- Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../src/navigator/stories/index.story.tsx | 17 ++++++++--------- .../font-library-modal/font-collection.js | 4 ++-- .../font-library-modal/installed-fonts.js | 4 ++-- .../src/components/global-styles/header.js | 9 ++------- .../global-styles/navigation-button.js | 6 ++---- 5 files changed, 16 insertions(+), 24 deletions(-) diff --git a/packages/components/src/navigator/stories/index.story.tsx b/packages/components/src/navigator/stories/index.story.tsx index 218580a4cc3ba2..633d5897678cbf 100644 --- a/packages/components/src/navigator/stories/index.story.tsx +++ b/packages/components/src/navigator/stories/index.story.tsx @@ -15,7 +15,6 @@ import { NavigatorScreen, NavigatorButton, NavigatorBackButton, - NavigatorToParentButton, useNavigator, } from '..'; @@ -261,9 +260,9 @@ export const NestedNavigator: StoryObj< typeof NavigatorProvider > = { <Card> <CardBody> This is the first child - <NavigatorToParentButton variant="secondary"> + <NavigatorBackButton variant="secondary"> Go back to parent - </NavigatorToParentButton> + </NavigatorBackButton> </CardBody> </Card> </NavigatorScreen> @@ -271,9 +270,9 @@ export const NestedNavigator: StoryObj< typeof NavigatorProvider > = { <Card> <CardBody> This is the second child - <NavigatorToParentButton variant="secondary"> + <NavigatorBackButton variant="secondary"> Go back to parent - </NavigatorToParentButton> + </NavigatorBackButton> <NavigatorButton variant="secondary" path="/child2/grandchild" @@ -287,9 +286,9 @@ export const NestedNavigator: StoryObj< typeof NavigatorProvider > = { <Card> <CardBody> This is the grand child - <NavigatorToParentButton variant="secondary"> + <NavigatorBackButton variant="secondary"> Go back to parent - </NavigatorToParentButton> + </NavigatorBackButton> </CardBody> </Card> </NavigatorScreen> @@ -345,9 +344,9 @@ export const SkipFocus: StoryObj< typeof NavigatorProvider > = { } } > <h2>Child screen</h2> - <NavigatorToParentButton variant="secondary"> + <NavigatorBackButton variant="secondary"> Go to parent screen. - </NavigatorToParentButton> + </NavigatorBackButton> </NavigatorScreen> </div> diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js index 357bcba1d93137..5c8263c0df1024 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js @@ -15,7 +15,7 @@ import { __experimentalVStack as VStack, __experimentalNavigatorProvider as NavigatorProvider, __experimentalNavigatorScreen as NavigatorScreen, - __experimentalNavigatorToParentButton as NavigatorToParentButton, + __experimentalNavigatorBackButton as NavigatorBackButton, __experimentalHeading as Heading, Notice, SelectControl, @@ -382,7 +382,7 @@ function FontCollection( { slug } ) { <NavigatorScreen path="/fontFamily"> <Flex justify="flex-start"> - <NavigatorToParentButton + <NavigatorBackButton icon={ chevronLeft } size="small" onClick={ () => { diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js index 9896a9a525d446..281ec0b30f7627 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js @@ -8,7 +8,7 @@ import { __experimentalHeading as Heading, __experimentalNavigatorProvider as NavigatorProvider, __experimentalNavigatorScreen as NavigatorScreen, - __experimentalNavigatorToParentButton as NavigatorToParentButton, + __experimentalNavigatorBackButton as NavigatorBackButton, __experimentalUseNavigator as useNavigator, __experimentalSpacer as Spacer, __experimentalText as Text, @@ -353,7 +353,7 @@ function InstalledFonts() { /> <Flex justify="flex-start"> - <NavigatorToParentButton + <NavigatorBackButton icon={ chevronLeft } size="small" onClick={ () => { diff --git a/packages/edit-site/src/components/global-styles/header.js b/packages/edit-site/src/components/global-styles/header.js index fdddc54a07ad71..1d9de84183aef7 100644 --- a/packages/edit-site/src/components/global-styles/header.js +++ b/packages/edit-site/src/components/global-styles/header.js @@ -7,7 +7,7 @@ import { __experimentalSpacer as Spacer, __experimentalHeading as Heading, __experimentalView as View, - __experimentalNavigatorToParentButton as NavigatorToParentButton, + __experimentalNavigatorBackButton as NavigatorBackButton, } from '@wordpress/components'; import { isRTL, __ } from '@wordpress/i18n'; import { chevronRight, chevronLeft } from '@wordpress/icons'; @@ -18,12 +18,7 @@ function ScreenHeader( { title, description, onBack } ) { <View> <Spacer marginBottom={ 0 } paddingX={ 4 } paddingY={ 3 }> <HStack spacing={ 2 }> - <NavigatorToParentButton - style={ - // TODO: This style override is also used in ToolsPanelHeader. - // It should be supported out-of-the-box by Button. - { minWidth: 24, padding: 0 } - } + <NavigatorBackButton icon={ isRTL() ? chevronRight : chevronLeft } size="small" label={ __( 'Back' ) } diff --git a/packages/edit-site/src/components/global-styles/navigation-button.js b/packages/edit-site/src/components/global-styles/navigation-button.js index 2053ba8a36fe6e..5bc8a50e0e2f45 100644 --- a/packages/edit-site/src/components/global-styles/navigation-button.js +++ b/packages/edit-site/src/components/global-styles/navigation-button.js @@ -3,7 +3,7 @@ */ import { __experimentalNavigatorButton as NavigatorButton, - __experimentalNavigatorToParentButton as NavigatorToParentButton, + __experimentalNavigatorBackButton as NavigatorBackButton, __experimentalItem as Item, FlexItem, __experimentalHStack as HStack, @@ -33,9 +33,7 @@ function NavigationButtonAsItem( props ) { } function NavigationBackButtonAsItem( props ) { - return ( - <NavigatorToParentButton as={ GenericNavigationButton } { ...props } /> - ); + return <NavigatorBackButton as={ GenericNavigationButton } { ...props } />; } export { NavigationButtonAsItem, NavigationBackButtonAsItem }; From 4baf1617af71d3d6cd3f91f47c3dc2bb611bdbd1 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Sun, 25 Aug 2024 20:49:50 +0530 Subject: [PATCH 0529/1908] Update typos in doc files (#64787) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- docs/getting-started/fundamentals/block-in-the-editor.md | 2 +- docs/reference-guides/block-api/block-attributes.md | 2 +- .../interactivity-api/core-concepts/server-side-rendering.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/getting-started/fundamentals/block-in-the-editor.md b/docs/getting-started/fundamentals/block-in-the-editor.md index f7357def5ec2df..d1f2a25063e6c6 100644 --- a/docs/getting-started/fundamentals/block-in-the-editor.md +++ b/docs/getting-started/fundamentals/block-in-the-editor.md @@ -124,7 +124,7 @@ export default function Edit( { attributes, setAttributes } ) { <legend className="blocks-base-control__label"> { __( 'Background color', 'block-development-examples' ) } </legend> - <ColorPalette // Element Tag for Gutenberg standard colour selector + <ColorPalette // Element Tag for Gutenberg standard color selector onChange={ onChangeBGColor } // onChange event callback /> </fieldset> diff --git a/docs/reference-guides/block-api/block-attributes.md b/docs/reference-guides/block-api/block-attributes.md index 52a325ff9253de..544f35593106f1 100644 --- a/docs/reference-guides/block-api/block-attributes.md +++ b/docs/reference-guides/block-api/block-attributes.md @@ -1,6 +1,6 @@ # Attributes -Block attributes provide information about the data stored by a block. For example, rich content, a list of image URLs, a background colour, or a button title. +Block attributes provide information about the data stored by a block. For example, rich content, a list of image URLs, a background color, or a button title. A block can contain any number of attributes, and these are specified by the `attributes` field - an object where each key is the name of the attribute, and the value is the attribute definition. diff --git a/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md b/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md index 8c62bd82eaba90..075c2cb977bdfd 100644 --- a/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md +++ b/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md @@ -93,7 +93,7 @@ The following are the necessary steps to ensure that the directives are correctl </ul> ``` -That's it! Once you've set up your interctive block with `supports.interactivity`, initialized your global state or local context, and added the directives to the HTML markup, the Interactivity API will take care of the rest. There's no additional code required from the developer to process these directives on the server side. +That's it! Once you've set up your interactive block with `supports.interactivity`, initialized your global state or local context, and added the directives to the HTML markup, the Interactivity API will take care of the rest. There's no additional code required from the developer to process these directives on the server side. Behind the scenes, WordPress uses the `wp_interactivity_process_directives` function to find and process the directives in the HTML markup of your block. This function uses the HTML API to make the necessary changes to the markup, based on the found directives and the initial global state and/or local context. From dec82e2dffda718feff8607d0205d2483d2de4be Mon Sep 17 00:00:00 2001 From: Robert Anderson <robert@noisysocks.com> Date: Mon, 26 Aug 2024 10:03:19 +1000 Subject: [PATCH 0530/1908] Position BlockToolbar below all of the selected block's descendants (#62711) * Position BlockToolbar below all of the selected block's descendants * Fix scrolling * Don't use window global * Explain what capturingClientId is * No need to clip bounds to viewport * Use explicit check for VisuallyHidden * To calculate visible bounds using rectUnion, take into account the outer limits of the container in which an element is supposed to be "visible" For example, if an element is positioned -10px to the left of the window x value (0), we should discount the negative overhang because it's not visible and therefore to be counted in the visible calculations. * switch to checkVisibility DOM method --------- Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: ramonopoly <ramonopoly@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- .../src/components/block-popover/index.js | 35 ++---- .../block-tools/block-toolbar-popover.js | 8 +- .../use-block-toolbar-popover-props.js | 3 +- packages/block-editor/src/utils/dom.js | 107 ++++++++++++++++++ 4 files changed, 122 insertions(+), 31 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 2413601a590e2e..47022e336e4869 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -20,6 +20,7 @@ import { */ import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; import usePopoverScroll from './use-popover-scroll'; +import { rectUnion, getVisibleElementBounds } from '../../utils/dom'; const MAX_POPOVER_RECOMPUTE_COUNTER = Number.MAX_SAFE_INTEGER; @@ -87,34 +88,12 @@ function BlockPopover( return { getBoundingClientRect() { - const selectedBCR = selectedElement.getBoundingClientRect(); - const lastSelectedBCR = - lastSelectedElement?.getBoundingClientRect(); - - // Get the biggest rectangle that encompasses completely the currently - // selected element and the last selected element: - // - for top/left coordinates, use the smaller numbers - // - for the bottom/right coordinates, use the largest numbers - const left = Math.min( - selectedBCR.left, - lastSelectedBCR?.left ?? Infinity - ); - const top = Math.min( - selectedBCR.top, - lastSelectedBCR?.top ?? Infinity - ); - const right = Math.max( - selectedBCR.right, - lastSelectedBCR.right ?? -Infinity - ); - const bottom = Math.max( - selectedBCR.bottom, - lastSelectedBCR.bottom ?? -Infinity - ); - const width = right - left; - const height = bottom - top; - - return new window.DOMRect( left, top, width, height ); + return lastSelectedElement + ? rectUnion( + getVisibleElementBounds( selectedElement ), + getVisibleElementBounds( lastSelectedElement ) + ) + : getVisibleElementBounds( selectedElement ); }, contextElement: selectedElement, }; diff --git a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js index 8428222268408a..c6378130b7da42 100644 --- a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js +++ b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js @@ -47,15 +47,19 @@ export default function BlockToolbarPopover( { isToolbarForcedRef.current = false; } ); + // If the block has a parent with __experimentalCaptureToolbars enabled, + // the toolbar should be positioned over the topmost capturing parent. + const clientIdToPositionOver = capturingClientId || clientId; + const popoverProps = useBlockToolbarPopoverProps( { contentElement: __unstableContentRef?.current, - clientId, + clientId: clientIdToPositionOver, } ); return ( ! isTyping && ( <BlockPopover - clientId={ capturingClientId || clientId } + clientId={ clientIdToPositionOver } bottomClientId={ lastClientId } className={ clsx( 'block-editor-block-list__block-popover', { 'is-insertion-point-visible': isInsertionPointVisible, diff --git a/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js b/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js index 0ca0f6e5a43dda..6d64f5a5882cb8 100644 --- a/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js +++ b/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js @@ -17,6 +17,7 @@ import { import { store as blockEditorStore } from '../../store'; import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; import { hasStickyOrFixedPositionValue } from '../../hooks/position'; +import { getVisibleElementBounds } from '../../utils/dom'; const COMMON_PROPS = { placement: 'top-start', @@ -67,7 +68,7 @@ function getProps( // Get how far the content area has been scrolled. const scrollTop = scrollContainer?.scrollTop || 0; - const blockRect = selectedBlockElement.getBoundingClientRect(); + const blockRect = getVisibleElementBounds( selectedBlockElement ); const contentRect = contentElement.getBoundingClientRect(); // Get the vertical position of top of the visible content area. diff --git a/packages/block-editor/src/utils/dom.js b/packages/block-editor/src/utils/dom.js index 6af35aff730155..e41ade344e49d8 100644 --- a/packages/block-editor/src/utils/dom.js +++ b/packages/block-editor/src/utils/dom.js @@ -57,3 +57,110 @@ export function getBlockClientId( node ) { return blockNode.id.slice( 'block-'.length ); } + +/** + * Calculates the union of two rectangles, and optionally constrains this union within a containerRect's + * left and right values. + * The function returns a new DOMRect object representing this union. + * + * @param {DOMRect} rect1 First rectangle. + * @param {DOMRect} rect2 Second rectangle. + * @param {DOMRectReadOnly?} containerRect An optional container rectangle. The union will be clipped to this rectangle. + * @return {DOMRect} Union of the two rectangles. + */ +export function rectUnion( rect1, rect2, containerRect ) { + let left = Math.min( rect1.left, rect2.left ); + let right = Math.max( rect1.right, rect2.right ); + const bottom = Math.max( rect1.bottom, rect2.bottom ); + const top = Math.min( rect1.top, rect2.top ); + + /* + * To calculate visible bounds using rectUnion, take into account the outer + * horizontal limits of the container in which an element is supposed to be "visible". + * For example, if an element is positioned -10px to the left of the window x value (0), + * this function discounts the negative overhang because it's not visible and + * therefore not to be counted in the visibility calculations. + * Top and bottom values are not accounted for to accommodate vertical scroll. + */ + if ( containerRect ) { + left = Math.max( left, containerRect.left ); + right = Math.min( right, containerRect.right ); + } + + return new window.DOMRect( left, top, right - left, bottom - top ); +} + +/** + * Returns whether an element is visible. + * + * @param {Element} element Element. + * @return {boolean} Whether the element is visible. + */ +function isElementVisible( element ) { + const viewport = element.ownerDocument.defaultView; + if ( ! viewport ) { + return false; + } + + // Check for <VisuallyHidden> component. + if ( element.classList.contains( 'components-visually-hidden' ) ) { + return false; + } + + const bounds = element.getBoundingClientRect(); + if ( bounds.width === 0 || bounds.height === 0 ) { + return false; + } + + return element.checkVisibility( { + opacityProperty: true, + contentVisibilityAuto: true, + visibilityProperty: true, + } ); +} + +/** + * Returns the rect of the element including all visible nested elements. + * + * Visible nested elements, including elements that overflow the parent, are + * taken into account. + * + * This function is useful for calculating the visible area of a block that + * contains nested elements that overflow the block, e.g. the Navigation block, + * which can contain overflowing Submenu blocks. + * + * The returned rect represents the full extent of the element and its visible + * children, which may extend beyond the viewport. + * + * @param {Element} element Element. + * @return {DOMRect} Bounding client rect of the element and its visible children. + */ +export function getVisibleElementBounds( element ) { + const viewport = element.ownerDocument.defaultView; + if ( ! viewport ) { + return new window.DOMRect(); + } + + let bounds = element.getBoundingClientRect(); + const viewportRect = new window.DOMRectReadOnly( + 0, + 0, + viewport.innerWidth, + viewport.innerHeight + ); + + const stack = [ element ]; + let currentElement; + + while ( ( currentElement = stack.pop() ) ) { + for ( const child of currentElement.children ) { + if ( isElementVisible( child ) ) { + const childBounds = child.getBoundingClientRect(); + bounds = rectUnion( bounds, childBounds, viewportRect ); + stack.push( child ); + } + } + } + + return bounds; +} From c7c8c4b31cb7e4f63d9377e825f79ed4d23de3ef Mon Sep 17 00:00:00 2001 From: Kai Hao <kevin830726@gmail.com> Date: Mon, 26 Aug 2024 15:06:21 +0800 Subject: [PATCH 0531/1908] Limit the max width of image to its container size (#63341) Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> * Limit the max width of image to its container size * Try fixing e2e tests * Snap to max width after resize * Set to undefined instead * Do not override aspect ratio --- packages/block-library/src/image/edit.js | 70 +++++++++++++---------- packages/block-library/src/image/image.js | 21 ++++++- 2 files changed, 60 insertions(+), 31 deletions(-) diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index fb11b3f50a5b64..b7c25595dcfccf 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -23,6 +23,7 @@ import { useEffect, useRef, useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { image as icon, plugins as pluginsIcon } from '@wordpress/icons'; import { store as noticesStore } from '@wordpress/notices'; +import { useResizeObserver } from '@wordpress/compose'; /** * Internal dependencies @@ -109,6 +110,9 @@ export function ImageEdit( { } = attributes; const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob ); + const [ contentResizeListener, { width: containerWidth } ] = + useResizeObserver(); + const altRef = useRef(); useEffect( () => { altRef.current = alt; @@ -364,35 +368,43 @@ export function ImageEdit( { }; return ( - <figure { ...blockProps }> - <Image - temporaryURL={ temporaryURL } - attributes={ attributes } - setAttributes={ setAttributes } - isSingleSelected={ isSingleSelected } - insertBlocksAfter={ insertBlocksAfter } - onReplace={ onReplace } - onSelectImage={ onSelectImage } - onSelectURL={ onSelectURL } - onUploadError={ onUploadError } - context={ context } - clientId={ clientId } - blockEditingMode={ blockEditingMode } - parentLayoutType={ parentLayout?.type } - /> - <MediaPlaceholder - icon={ <BlockIcon icon={ icon } /> } - onSelect={ onSelectImage } - onSelectURL={ onSelectURL } - onError={ onUploadError } - placeholder={ placeholder } - accept="image/*" - allowedTypes={ ALLOWED_MEDIA_TYPES } - value={ { id, src } } - mediaPreview={ mediaPreview } - disableMediaButtons={ temporaryURL || url } - /> - </figure> + <> + <figure { ...blockProps }> + <Image + temporaryURL={ temporaryURL } + attributes={ attributes } + setAttributes={ setAttributes } + isSingleSelected={ isSingleSelected } + insertBlocksAfter={ insertBlocksAfter } + onReplace={ onReplace } + onSelectImage={ onSelectImage } + onSelectURL={ onSelectURL } + onUploadError={ onUploadError } + context={ context } + clientId={ clientId } + blockEditingMode={ blockEditingMode } + parentLayoutType={ parentLayout?.type } + containerWidth={ containerWidth } + /> + <MediaPlaceholder + icon={ <BlockIcon icon={ icon } /> } + onSelect={ onSelectImage } + onSelectURL={ onSelectURL } + onError={ onUploadError } + placeholder={ placeholder } + accept="image/*" + allowedTypes={ ALLOWED_MEDIA_TYPES } + value={ { id, src } } + mediaPreview={ mediaPreview } + disableMediaButtons={ temporaryURL || url } + /> + </figure> + { + // The listener cannot be placed as the first element as it will break the in-between inserter. + // See https://github.com/WordPress/gutenberg/blob/71134165868298fc15e22896d0c28b41b3755ff7/packages/block-editor/src/components/block-list/use-in-between-inserter.js#L120 + contentResizeListener + } + </> ); } diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 646299bb7e0892..3ad12d8dca4b62 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -109,6 +109,7 @@ export default function Image( { clientId, blockEditingMode, parentLayoutType, + containerWidth, } ) { const { url = '', @@ -928,6 +929,7 @@ export default function Image( { // @todo It would be good to revisit this once a content-width variable // becomes available. const maxWidthBuffer = maxWidth * 2.5; + const maxContentWidth = containerWidth || maxWidthBuffer; let showRightHandle = false; let showLeftHandle = false; @@ -973,9 +975,9 @@ export default function Image( { } } showHandle={ isSingleSelected } minWidth={ minWidth } - maxWidth={ maxWidthBuffer } + maxWidth={ maxContentWidth } minHeight={ minHeight } - maxHeight={ maxWidthBuffer / ratio } + maxHeight={ maxContentWidth / ratio } lockAspectRatio={ ratio } enable={ { top: false, @@ -986,6 +988,21 @@ export default function Image( { onResizeStart={ onResizeStart } onResizeStop={ ( event, direction, elt ) => { onResizeStop(); + + // Clear hardcoded width if the resized width is close to the max-content width. + if ( + // Only do this if the image is bigger than the container to prevent it from being squished. + // TODO: Remove this check if the image support setting 100% width. + naturalWidth >= maxContentWidth && + Math.abs( elt.offsetWidth - maxContentWidth ) < 10 + ) { + setAttributes( { + width: undefined, + height: undefined, + } ); + return; + } + // Since the aspect ratio is locked when resizing, we can // use the width of the resized element to calculate the // height in CSS to prevent stretching when the max-width From 35ee08a552d7da7257ab22e1f8a749a11fea9583 Mon Sep 17 00:00:00 2001 From: Kai Hao <kevin830726@gmail.com> Date: Mon, 26 Aug 2024 15:07:21 +0800 Subject: [PATCH 0532/1908] Fix Modify content-locked menu item not showing if the block is not selected (#61605) Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../block-settings-menu-controls/index.js | 8 ++- .../src/components/content-lock/index.js | 1 + .../modify-content-lock-menu-item.js | 58 +++++++++++++++++++ .../block-editor/src/hooks/content-lock-ui.js | 47 ++++----------- .../block-editor/src/store/private-actions.js | 1 + .../content-only-settings-menu.js | 14 ++--- 6 files changed, 83 insertions(+), 46 deletions(-) create mode 100644 packages/block-editor/src/components/content-lock/index.js create mode 100644 packages/block-editor/src/components/content-lock/modify-content-lock-menu-item.js diff --git a/packages/block-editor/src/components/block-settings-menu-controls/index.js b/packages/block-editor/src/components/block-settings-menu-controls/index.js index 1edf02eb368945..39063db4f52e02 100644 --- a/packages/block-editor/src/components/block-settings-menu-controls/index.js +++ b/packages/block-editor/src/components/block-settings-menu-controls/index.js @@ -21,7 +21,7 @@ import { import { BlockLockMenuItem, useBlockLock } from '../block-lock'; import { store as blockEditorStore } from '../../store'; import BlockModeToggle from '../block-settings-menu/block-mode-toggle'; - +import { ModifyContentLockMenuItem } from '../content-lock'; import { BlockRenameControl, useBlockRename } from '../block-rename'; const { Fill, Slot } = createSlotFill( 'BlockSettingsMenuControls' ); @@ -108,6 +108,12 @@ const BlockSettingsMenuControlsSlot = ( { fillProps, clientIds = null } ) => { { __( 'Move to' ) } </MenuItem> ) } + { selectedClientIds.length === 1 && ( + <ModifyContentLockMenuItem + clientId={ selectedClientIds[ 0 ] } + onClose={ fillProps?.onClose } + /> + ) } { fillProps?.count === 1 && ! isContentOnly && ( <BlockModeToggle clientId={ fillProps?.firstBlockClientId } diff --git a/packages/block-editor/src/components/content-lock/index.js b/packages/block-editor/src/components/content-lock/index.js new file mode 100644 index 00000000000000..651bf885a7d1e9 --- /dev/null +++ b/packages/block-editor/src/components/content-lock/index.js @@ -0,0 +1 @@ +export { ModifyContentLockMenuItem } from './modify-content-lock-menu-item'; diff --git a/packages/block-editor/src/components/content-lock/modify-content-lock-menu-item.js b/packages/block-editor/src/components/content-lock/modify-content-lock-menu-item.js new file mode 100644 index 00000000000000..18c4d0763cd52d --- /dev/null +++ b/packages/block-editor/src/components/content-lock/modify-content-lock-menu-item.js @@ -0,0 +1,58 @@ +/** + * WordPress dependencies + */ +import { MenuItem } from '@wordpress/components'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { _x } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; + +// The implementation of content locking is mainly in this file, although the mechanism +// to stop temporarily editing as blocks when an outside block is selected is on component StopEditingAsBlocksOnOutsideSelect +// at block-editor/src/components/block-list/index.js. +// Besides the components on this file and the file referenced above the implementation +// also includes artifacts on the store (actions, reducers, and selector). + +export function ModifyContentLockMenuItem( { clientId, onClose } ) { + const { templateLock, isLockedByParent, isEditingAsBlocks } = useSelect( + ( select ) => { + const { + getContentLockingParent, + getTemplateLock, + getTemporarilyEditingAsBlocks, + } = unlock( select( blockEditorStore ) ); + return { + templateLock: getTemplateLock( clientId ), + isLockedByParent: !! getContentLockingParent( clientId ), + isEditingAsBlocks: getTemporarilyEditingAsBlocks() === clientId, + }; + }, + [ clientId ] + ); + const blockEditorActions = useDispatch( blockEditorStore ); + const isContentLocked = + ! isLockedByParent && templateLock === 'contentOnly'; + if ( ! isContentLocked && ! isEditingAsBlocks ) { + return null; + } + + const { modifyContentLockBlock } = unlock( blockEditorActions ); + const showStartEditingAsBlocks = ! isEditingAsBlocks && isContentLocked; + + return ( + showStartEditingAsBlocks && ( + <MenuItem + onClick={ () => { + modifyContentLockBlock( clientId ); + onClose(); + } } + > + { _x( 'Modify', 'Unlock content locked blocks' ) } + </MenuItem> + ) + ); +} diff --git a/packages/block-editor/src/hooks/content-lock-ui.js b/packages/block-editor/src/hooks/content-lock-ui.js index 7cca4b325b09d7..f5e3bde31ce509 100644 --- a/packages/block-editor/src/hooks/content-lock-ui.js +++ b/packages/block-editor/src/hooks/content-lock-ui.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { ToolbarButton, MenuItem } from '@wordpress/components'; +import { ToolbarButton } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { useCallback } from '@wordpress/element'; @@ -10,7 +10,7 @@ import { useCallback } from '@wordpress/element'; * Internal dependencies */ import { store as blockEditorStore } from '../store'; -import { BlockControls, BlockSettingsMenuControls } from '../components'; +import { BlockControls } from '../components'; import { unlock } from '../lock-unlock'; // The implementation of content locking is mainly in this file, although the mechanism @@ -19,7 +19,7 @@ import { unlock } from '../lock-unlock'; // Besides the components on this file and the file referenced above the implementation // also includes artifacts on the store (actions, reducers, and selector). -function ContentLockControlsPure( { clientId, isSelected } ) { +function ContentLockControlsPure( { clientId } ) { const { templateLock, isLockedByParent, isEditingAsBlocks } = useSelect( ( select ) => { const { @@ -36,9 +36,7 @@ function ContentLockControlsPure( { clientId, isSelected } ) { [ clientId ] ); - const { stopEditingAsBlocks, modifyContentLockBlock } = unlock( - useDispatch( blockEditorStore ) - ); + const { stopEditingAsBlocks } = unlock( useDispatch( blockEditorStore ) ); const isContentLocked = ! isLockedByParent && templateLock === 'contentOnly'; @@ -51,38 +49,15 @@ function ContentLockControlsPure( { clientId, isSelected } ) { } const showStopEditingAsBlocks = isEditingAsBlocks && ! isContentLocked; - const showStartEditingAsBlocks = - ! isEditingAsBlocks && isContentLocked && isSelected; return ( - <> - { showStopEditingAsBlocks && ( - <> - <BlockControls group="other"> - <ToolbarButton onClick={ stopEditingAsBlockCallback }> - { __( 'Done' ) } - </ToolbarButton> - </BlockControls> - </> - ) } - { showStartEditingAsBlocks && ( - <BlockSettingsMenuControls> - { ( { selectedClientIds, onClose } ) => - selectedClientIds.length === 1 && - selectedClientIds[ 0 ] === clientId && ( - <MenuItem - onClick={ () => { - modifyContentLockBlock( clientId ); - onClose(); - } } - > - { __( 'Modify' ) } - </MenuItem> - ) - } - </BlockSettingsMenuControls> - ) } - </> + showStopEditingAsBlocks && ( + <BlockControls group="other"> + <ToolbarButton onClick={ stopEditingAsBlockCallback }> + { __( 'Done' ) } + </ToolbarButton> + </BlockControls> + ) ); } diff --git a/packages/block-editor/src/store/private-actions.js b/packages/block-editor/src/store/private-actions.js index 74aec3c49d1e89..dc57d61fd6b76c 100644 --- a/packages/block-editor/src/store/private-actions.js +++ b/packages/block-editor/src/store/private-actions.js @@ -367,6 +367,7 @@ export function expandBlock( clientId ) { export const modifyContentLockBlock = ( clientId ) => ( { select, dispatch } ) => { + dispatch.selectBlock( clientId ); dispatch.__unstableMarkNextChangeAsNotPersistent(); dispatch.updateBlockAttributes( clientId, { templateLock: undefined, diff --git a/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js b/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js index b5e93659a4b7ab..fcf7adfa77635c 100644 --- a/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js +++ b/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js @@ -10,7 +10,7 @@ import { import { store as coreStore } from '@wordpress/core-data'; import { __experimentalText as Text, MenuItem } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; -import { __ } from '@wordpress/i18n'; +import { __, _x } from '@wordpress/i18n'; /** * Internal dependencies @@ -137,27 +137,23 @@ function TemplateLockContentOnlyMenuItems( { clientId, onClose } ) { ); const blockDisplayInformation = useBlockDisplayInformation( contentLockingParent ); - // Disable reason: We're using a hook here so it has to be on top-level. - // eslint-disable-next-line @wordpress/no-unused-vars-before-return - const { modifyContentLockBlock, selectBlock } = unlock( - useDispatch( blockEditorStore ) - ); - + const blockEditorActions = useDispatch( blockEditorStore ); if ( ! blockDisplayInformation?.title ) { return null; } + const { modifyContentLockBlock } = unlock( blockEditorActions ); + return ( <> <BlockSettingsMenuFirstItem> <MenuItem onClick={ () => { - selectBlock( contentLockingParent ); modifyContentLockBlock( contentLockingParent ); onClose(); } } > - { __( 'Unlock' ) } + { _x( 'Unlock', 'Unlock content locked blocks' ) } </MenuItem> </BlockSettingsMenuFirstItem> <Text From 353164a8782c9082e09e5e995e6a4651050454a7 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Mon, 26 Aug 2024 10:29:57 +0200 Subject: [PATCH 0533/1908] Docs: Update design resources to indicate edit isn't fee. (#64792) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> --- docs/explanations/user-interface/design-resources.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/explanations/user-interface/design-resources.md b/docs/explanations/user-interface/design-resources.md index 235951e4839e98..4a2a78f6822a5d 100644 --- a/docs/explanations/user-interface/design-resources.md +++ b/docs/explanations/user-interface/design-resources.md @@ -2,7 +2,7 @@ ## Figma -The [WordPress Design team](https://make.wordpress.org/design/) uses [Figma](https://www.figma.com/) to collaborate and share work. If you'd like to contribute, join the [#design channel](https://app.slack.com/client/T024MFP4J/C02S78ZAL) in [Slack](https://make.wordpress.org/chat/) and ask the team to set you up with a free Figma account. This will give you access to a helpful library of components used in WordPress. They are stable, fully supported, up to date, and ready for use in designs and prototypes. +The [WordPress Design team](https://make.wordpress.org/design/) uses [Figma](https://www.figma.com/) to collaborate and share work. If you'd like to contribute, you can use [the WordPress Figma design library](https://make.wordpress.org/design/handbook/get-involved/tools-figma/) to make mockups. You can also join the [#design channel](https://app.slack.com/client/T024MFP4J/C02S78ZAL) in [Slack](https://make.wordpress.org/chat/) and if you'd like to ask for advice or otherwise. Figma accounts are free, and with one you can use components from the shared libraries, or duplicate files to your draft if you need to make edits. Full edit access to the WordPress libraries is paid and reserved for the design team. ### How to contribute From 16f89774b016f331eb885c98f632725695b92a26 Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Mon, 26 Aug 2024 13:25:08 +0200 Subject: [PATCH 0534/1908] Core Data Types: `recordId` can be a number (#64796) * `recordId` can be a number * Update docs --- docs/reference-guides/data/data-core.md | 2 +- packages/core-data/README.md | 4 +-- packages/core-data/src/actions.js | 32 +++++++++---------- .../core-data/src/hooks/use-entity-prop.js | 8 ++--- packages/core-data/src/resolvers.js | 6 ++-- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/reference-guides/data/data-core.md b/docs/reference-guides/data/data-core.md index f08fbc960b8b28..474207aa20460f 100644 --- a/docs/reference-guides/data/data-core.md +++ b/docs/reference-guides/data/data-core.md @@ -772,7 +772,7 @@ _Parameters_ - _kind_ `string`: Kind of the deleted entity. - _name_ `string`: Name of the deleted entity. -- _recordId_ `string`: Record ID of the deleted entity. +- _recordId_ `number|string`: Record ID of the deleted entity. - _query_ `?Object`: Special query parameters for the DELETE API call. - _options_ `[Object]`: Delete options. - _options.\_\_unstableFetch_ `[Function]`: Internal use only. Function to call instead of `apiFetch()`. Must return a promise. diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 89e7a201fe5e25..079f95ddbfc7a6 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -182,7 +182,7 @@ _Parameters_ - _kind_ `string`: Kind of the deleted entity. - _name_ `string`: Name of the deleted entity. -- _recordId_ `string`: Record ID of the deleted entity. +- _recordId_ `number|string`: Record ID of the deleted entity. - _query_ `?Object`: Special query parameters for the DELETE API call. - _options_ `[Object]`: Delete options. - _options.\_\_unstableFetch_ `[Function]`: Internal use only. Function to call instead of `apiFetch()`. Must return a promise. @@ -1011,7 +1011,7 @@ _Parameters_ - _kind_ `string`: The entity kind. - _name_ `string`: The entity name. - _prop_ `string`: The property name. -- _\_id_ `[string]`: An entity ID to use instead of the context-provided one. +- _\_id_ `[number|string]`: An entity ID to use instead of the context-provided one. _Returns_ diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index d7cc4d708d3c68..fd16675122c567 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -265,17 +265,17 @@ export function receiveEmbedPreview( url, preview ) { /** * Action triggered to delete an entity record. * - * @param {string} kind Kind of the deleted entity. - * @param {string} name Name of the deleted entity. - * @param {string} recordId Record ID of the deleted entity. - * @param {?Object} query Special query parameters for the - * DELETE API call. - * @param {Object} [options] Delete options. - * @param {Function} [options.__unstableFetch] Internal use only. Function to - * call instead of `apiFetch()`. - * Must return a promise. - * @param {boolean} [options.throwOnError=false] If false, this action suppresses all - * the exceptions. Defaults to false. + * @param {string} kind Kind of the deleted entity. + * @param {string} name Name of the deleted entity. + * @param {number|string} recordId Record ID of the deleted entity. + * @param {?Object} query Special query parameters for the + * DELETE API call. + * @param {Object} [options] Delete options. + * @param {Function} [options.__unstableFetch] Internal use only. Function to + * call instead of `apiFetch()`. + * Must return a promise. + * @param {boolean} [options.throwOnError=false] If false, this action suppresses all + * the exceptions. Defaults to false. */ export const deleteEntityRecord = ( @@ -805,11 +805,11 @@ export const saveEditedEntityRecord = /** * Action triggered to save only specified properties for the entity. * - * @param {string} kind Kind of the entity. - * @param {string} name Name of the entity. - * @param {Object} recordId ID of the record. - * @param {Array} itemsToSave List of entity properties or property paths to save. - * @param {Object} options Saving options. + * @param {string} kind Kind of the entity. + * @param {string} name Name of the entity. + * @param {number|string} recordId ID of the record. + * @param {Array} itemsToSave List of entity properties or property paths to save. + * @param {Object} options Saving options. */ export const __experimentalSaveSpecifiedEntityEdits = ( kind, name, recordId, itemsToSave, options ) => diff --git a/packages/core-data/src/hooks/use-entity-prop.js b/packages/core-data/src/hooks/use-entity-prop.js index 2894721410dfdf..ac2f22ace70792 100644 --- a/packages/core-data/src/hooks/use-entity-prop.js +++ b/packages/core-data/src/hooks/use-entity-prop.js @@ -15,10 +15,10 @@ import useEntityId from './use-entity-id'; * specified property of the nearest provided * entity of the specified type. * - * @param {string} kind The entity kind. - * @param {string} name The entity name. - * @param {string} prop The property name. - * @param {string} [_id] An entity ID to use instead of the context-provided one. + * @param {string} kind The entity kind. + * @param {string} name The entity name. + * @param {string} prop The property name. + * @param {number|string} [_id] An entity ID to use instead of the context-provided one. * * @return {[*, Function, *]} An array where the first item is the * property value, the second is the diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 148988cf723199..c28f018508e38c 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -463,9 +463,9 @@ export const canUser = * Checks whether the current user can perform the given action on the given * REST resource. * - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {string} recordId Record's id. + * @param {string} kind Entity kind. + * @param {string} name Entity name. + * @param {number|string} recordId Record's id. */ export const canUserEditEntityRecord = ( kind, name, recordId ) => From e9a8c6ae15160d4c522ee7520b5ed6cf8343528f Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 26 Aug 2024 15:44:06 +0200 Subject: [PATCH 0535/1908] Navigator: fix isInitial, refine focusSelector logic (#64786) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix isInitial logic * Use '@wordpress/warning' instead of console.warn * Improved destructuring and isInitial assignment * Refactor focus selector logic, better cleanup, lazier map copy * Remove unnecessary optional chaining — currentLocation is always defined --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- .../navigator-provider/component.tsx | 66 +++++++++++-------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/packages/components/src/navigator/navigator-provider/component.tsx b/packages/components/src/navigator/navigator-provider/component.tsx index 8e596778c7f21c..ebcb247c574830 100644 --- a/packages/components/src/navigator/navigator-provider/component.tsx +++ b/packages/components/src/navigator/navigator-provider/component.tsx @@ -8,6 +8,7 @@ import type { ForwardedRef } from 'react'; */ import { useMemo, useReducer } from '@wordpress/element'; import isShallowEqual from '@wordpress/is-shallow-equal'; +import warning from '@wordpress/warning'; /** * Internal dependencies @@ -46,8 +47,7 @@ type RouterState = { function addScreen( { screens }: RouterState, screen: Screen ) { if ( screens.some( ( s ) => s.path === screen.path ) ) { - // eslint-disable-next-line no-console - console.warn( + warning( `Navigator: a screen with path ${ screen.path } already exists. The screen with id ${ screen.id } will not be added.` ); @@ -65,7 +65,8 @@ function goTo( path: string, options: NavigateOptions = {} ) { - const { currentLocation, focusSelectors } = state; + const { focusSelectors } = state; + const currentLocation = { ...state.currentLocation, isInitial: false }; const { // Default assignments @@ -78,29 +79,36 @@ function goTo( ...restOptions } = options; - if ( currentLocation?.path === path ) { + if ( currentLocation.path === path ) { return { currentLocation, focusSelectors }; } - let focusSelectorsCopy; + let focusSelectorsCopy: typeof focusSelectors | undefined; + function getFocusSelectorsCopy() { + focusSelectorsCopy = + focusSelectorsCopy ?? new Map( state.focusSelectors ); + return focusSelectorsCopy; + } // Set a focus selector that will be used when navigating // back to the current location. - if ( focusTargetSelector && currentLocation?.path ) { - if ( ! focusSelectorsCopy ) { - focusSelectorsCopy = new Map( state.focusSelectors ); - } - focusSelectorsCopy.set( currentLocation.path, focusTargetSelector ); + if ( focusTargetSelector && currentLocation.path ) { + getFocusSelectorsCopy().set( + currentLocation.path, + focusTargetSelector + ); } // Get the focus selector for the new location. let currentFocusSelector; - if ( isBack ) { - if ( ! focusSelectorsCopy ) { - focusSelectorsCopy = new Map( state.focusSelectors ); + if ( focusSelectors.get( path ) ) { + if ( isBack ) { + // Use the found focus selector only when navigating back. + currentFocusSelector = focusSelectors.get( path ); } - currentFocusSelector = focusSelectorsCopy.get( path ); - focusSelectorsCopy.delete( path ); + // Make a copy of the focusSelectors map to remove the focus selector + // only if necessary (ie. a focus selector was found). + getFocusSelectorsCopy().delete( path ); } return { @@ -120,8 +128,9 @@ function goToParent( state: RouterState, options: NavigateToParentOptions = {} ) { - const { currentLocation, screens, focusSelectors } = state; - const currentPath = currentLocation?.path; + const { screens, focusSelectors } = state; + const currentLocation = { ...state.currentLocation, isInitial: false }; + const currentPath = currentLocation.path; if ( currentPath === undefined ) { return { currentLocation, focusSelectors }; } @@ -154,21 +163,20 @@ function routerReducer( screens = removeScreen( state, action.screen ); break; case 'goto': - const goToNewState = goTo( state, action.path, action.options ); - currentLocation = goToNewState.currentLocation; - focusSelectors = goToNewState.focusSelectors; + ( { currentLocation, focusSelectors } = goTo( + state, + action.path, + action.options + ) ); break; case 'gotoparent': - const goToParentNewState = goToParent( state, action.options ); - currentLocation = goToParentNewState.currentLocation; - focusSelectors = goToParentNewState.focusSelectors; + ( { currentLocation, focusSelectors } = goToParent( + state, + action.options + ) ); break; } - if ( currentLocation?.path === state.initialPath ) { - currentLocation = { ...currentLocation, isInitial: true }; - } - // Return early in case there is no change if ( screens === state.screens && @@ -178,7 +186,7 @@ function routerReducer( } // Compute the matchedPath - const currentPath = currentLocation?.path; + const currentPath = currentLocation.path; matchedPath = currentPath !== undefined ? patternMatch( currentPath, screens ) @@ -220,7 +228,7 @@ function UnconnectedNavigatorProvider( initialPathProp, ( path ) => ( { screens: [], - currentLocation: { path }, + currentLocation: { path, isInitial: true }, matchedPath: undefined, focusSelectors: new Map(), initialPath: initialPathProp, From 36c6738dfa85d9ed202eee4dc920c1ea5706af0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 12:23:35 -0400 Subject: [PATCH 0536/1908] Bump ruby/setup-ruby from 1.188.0 to 1.190.0 in the github-actions group (#64055) Bumps the github-actions group with 1 update: [ruby/setup-ruby](https://github.com/ruby/setup-ruby). Updates `ruby/setup-ruby` from 1.188.0 to 1.190.0 - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb) - [Commits](https://github.com/ruby/setup-ruby/compare/50ba3386b050ad5b97a41fcb81240cbee1d1821f...a6e6f86333f0a2523ece813039b8b4be04560854) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/rnmobile-ios-runner.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rnmobile-ios-runner.yml b/.github/workflows/rnmobile-ios-runner.yml index 2f515ce5148f8b..2926e494b09f89 100644 --- a/.github/workflows/rnmobile-ios-runner.yml +++ b/.github/workflows/rnmobile-ios-runner.yml @@ -27,7 +27,7 @@ jobs: with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - uses: ruby/setup-ruby@50ba3386b050ad5b97a41fcb81240cbee1d1821f # v1.188.0 + - uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0 with: # `.ruby-version` file location working-directory: packages/react-native-editor/ios From 8a243453dccd71be63d31dad3b87a801606adaa2 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 26 Aug 2024 19:04:42 +0200 Subject: [PATCH 0537/1908] Components: move displayName assignment to top-level files (#64793) * Update CONTRIBUTING guidelines * Update Composite component * Update DropdownMenuV2 component --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CONTRIBUTING.md | 19 ++++++----- .../components/src/composite/group-label.tsx | 1 - packages/components/src/composite/group.tsx | 1 - packages/components/src/composite/hover.tsx | 1 - packages/components/src/composite/index.tsx | 24 ++++++++++---- packages/components/src/composite/item.tsx | 1 - packages/components/src/composite/row.tsx | 1 - .../components/src/composite/typeahead.tsx | 1 - .../src/dropdown-menu-v2/checkbox-item.tsx | 1 - .../src/dropdown-menu-v2/context.tsx | 1 - .../components/src/dropdown-menu-v2/group.tsx | 1 - .../components/src/dropdown-menu-v2/index.tsx | 32 ++++++++++++++----- .../src/dropdown-menu-v2/item-help-text.tsx | 1 - .../src/dropdown-menu-v2/item-label.tsx | 1 - .../components/src/dropdown-menu-v2/item.tsx | 1 - .../src/dropdown-menu-v2/radio-item.tsx | 1 - .../src/dropdown-menu-v2/separator.tsx | 1 - 17 files changed, 52 insertions(+), 37 deletions(-) diff --git a/packages/components/CONTRIBUTING.md b/packages/components/CONTRIBUTING.md index 40718b3577ab94..8af8bbf801edfe 100644 --- a/packages/components/CONTRIBUTING.md +++ b/packages/components/CONTRIBUTING.md @@ -261,19 +261,18 @@ The following example implements all of the above recommendations. //======================= import { forwardRef } from '@wordpress/element'; -export const SubComponent = forwardRef( - function UnforwardedSubComponent( props, ref ) { +export const ComponentSubcomponent = forwardRef( + function UnforwardedComponentSubcomponent( props, ref ) { /* ... */ } ); -SubComponent.displayName = 'Component.SubComponent'; //======================= // context.ts //======================= import { createContext } from '@wordpress/element'; -export const Context = createContext(); +export const ComponentContext = createContext(); //======================= // hook.ts @@ -288,8 +287,8 @@ export function useComponent() { // component.tsx //======================= import { forwardRef } from '@wordpress/element'; -import { SubComponent } from './subcomponent'; -import { Context } from './context'; +import { ComponentSubcomponent } from './subcomponent'; +import { ComponentContext } from './context'; /** The top-level component's JSDoc. */ export const Component = Object.assign( @@ -298,9 +297,13 @@ export const Component = Object.assign( } ), { /** The subcomponent's JSDoc. */ - SubComponent, + Subcomponent: Object.assign(ComponentSubcomponent, { + displayName: 'Component.SubComponent';, + }), /** The context's JSDoc. */ - Context, + Context: Object.assign(ComponentContext, { + displayName: 'Component.Context' + }), } ); diff --git a/packages/components/src/composite/group-label.tsx b/packages/components/src/composite/group-label.tsx index ce3629e1d3e4b1..26d043cd0a1400 100644 --- a/packages/components/src/composite/group-label.tsx +++ b/packages/components/src/composite/group-label.tsx @@ -28,4 +28,3 @@ export const CompositeGroupLabel = forwardRef< /> ); } ); -CompositeGroupLabel.displayName = 'Composite.GroupLabel'; diff --git a/packages/components/src/composite/group.tsx b/packages/components/src/composite/group.tsx index cd908d97c2a3e2..a6b1b8b3f5254a 100644 --- a/packages/components/src/composite/group.tsx +++ b/packages/components/src/composite/group.tsx @@ -28,4 +28,3 @@ export const CompositeGroup = forwardRef< /> ); } ); -CompositeGroup.displayName = 'Composite.Group'; diff --git a/packages/components/src/composite/hover.tsx b/packages/components/src/composite/hover.tsx index 57aae1dde63c84..76a240e0767009 100644 --- a/packages/components/src/composite/hover.tsx +++ b/packages/components/src/composite/hover.tsx @@ -28,4 +28,3 @@ export const CompositeHover = forwardRef< /> ); } ); -CompositeHover.displayName = 'Composite.Hover'; diff --git a/packages/components/src/composite/index.tsx b/packages/components/src/composite/index.tsx index 1b4cc361ea4cfa..787150eb9b7146 100644 --- a/packages/components/src/composite/index.tsx +++ b/packages/components/src/composite/index.tsx @@ -93,7 +93,9 @@ export const Composite = Object.assign( * </Composite> * ``` */ - Group: CompositeGroup, + Group: Object.assign( CompositeGroup, { + displayName: 'Composite.Group', + } ), /** * Renders a label in a composite group. This component must be wrapped with * `Composite.Group` so the `aria-labelledby` prop is properly set on the @@ -113,7 +115,9 @@ export const Composite = Object.assign( * </Composite> * ``` */ - GroupLabel: CompositeGroupLabel, + GroupLabel: Object.assign( CompositeGroupLabel, { + displayName: 'Composite.GroupLabel', + } ), /** * Renders a composite item. * @@ -129,7 +133,7 @@ export const Composite = Object.assign( * </Composite> * ``` */ - Item: CompositeItem, + Item: Object.assign( CompositeItem, { displayName: 'Composite.Item' } ), /** * Renders a composite row. Wrapping `Composite.Item` elements within * `Composite.Row` will create a two-dimensional composite widget, such as a @@ -154,7 +158,7 @@ export const Composite = Object.assign( * </Composite> * ``` */ - Row: CompositeRow, + Row: Object.assign( CompositeRow, { displayName: 'Composite.Row' } ), /** * Renders an element in a composite widget that receives focus on mouse move * and loses focus to the composite base element on mouse leave. This should @@ -175,7 +179,9 @@ export const Composite = Object.assign( * </Composite> * ``` */ - Hover: CompositeHover, + Hover: Object.assign( CompositeHover, { + displayName: 'Composite.Hover', + } ), /** * Renders a component that adds typeahead functionality to composite * components. Hitting printable character keys will move focus to the next @@ -192,7 +198,9 @@ export const Composite = Object.assign( * </Composite> * ``` */ - Typeahead: CompositeTypeahead, + Typeahead: Object.assign( CompositeTypeahead, { + displayName: 'Composite.Typeahead', + } ), /** * The React context used by the composite components. It can be used by * to access the composite store, and to forward the context when composite @@ -207,6 +215,8 @@ export const Composite = Object.assign( * const compositeContext = useContext( Composite.Context ); * ``` */ - Context: CompositeContext, + Context: Object.assign( CompositeContext, { + displayName: 'Composite.Context', + } ), } ); diff --git a/packages/components/src/composite/item.tsx b/packages/components/src/composite/item.tsx index 634ddfbb9bf9e9..8067c222c1c97f 100644 --- a/packages/components/src/composite/item.tsx +++ b/packages/components/src/composite/item.tsx @@ -28,4 +28,3 @@ export const CompositeItem = forwardRef< /> ); } ); -CompositeItem.displayName = 'Composite.Item'; diff --git a/packages/components/src/composite/row.tsx b/packages/components/src/composite/row.tsx index eb130ce54aa85c..cbb9f80045de76 100644 --- a/packages/components/src/composite/row.tsx +++ b/packages/components/src/composite/row.tsx @@ -28,4 +28,3 @@ export const CompositeRow = forwardRef< /> ); } ); -CompositeRow.displayName = 'Composite.Row'; diff --git a/packages/components/src/composite/typeahead.tsx b/packages/components/src/composite/typeahead.tsx index 7d5a9931d19ab0..d5bb7e6e2e4cc5 100644 --- a/packages/components/src/composite/typeahead.tsx +++ b/packages/components/src/composite/typeahead.tsx @@ -28,4 +28,3 @@ export const CompositeTypeahead = forwardRef< /> ); } ); -CompositeTypeahead.displayName = 'Composite.Typeahead'; diff --git a/packages/components/src/dropdown-menu-v2/checkbox-item.tsx b/packages/components/src/dropdown-menu-v2/checkbox-item.tsx index d97859461b893f..2f0d15557bb5e5 100644 --- a/packages/components/src/dropdown-menu-v2/checkbox-item.tsx +++ b/packages/components/src/dropdown-menu-v2/checkbox-item.tsx @@ -57,4 +57,3 @@ export const DropdownMenuCheckboxItem = forwardRef< </Styled.DropdownMenuCheckboxItem> ); } ); -DropdownMenuCheckboxItem.displayName = 'DropdownMenuV2.CheckboxItem'; diff --git a/packages/components/src/dropdown-menu-v2/context.tsx b/packages/components/src/dropdown-menu-v2/context.tsx index c69fb3d30ef76f..b285843327267f 100644 --- a/packages/components/src/dropdown-menu-v2/context.tsx +++ b/packages/components/src/dropdown-menu-v2/context.tsx @@ -11,4 +11,3 @@ import type { DropdownMenuContext as DropdownMenuContextType } from './types'; export const DropdownMenuContext = createContext< DropdownMenuContextType | undefined >( undefined ); -DropdownMenuContext.displayName = 'DropdownMenuV2.Context'; diff --git a/packages/components/src/dropdown-menu-v2/group.tsx b/packages/components/src/dropdown-menu-v2/group.tsx index 806e22ca6a39a6..f2bf79015bc691 100644 --- a/packages/components/src/dropdown-menu-v2/group.tsx +++ b/packages/components/src/dropdown-menu-v2/group.tsx @@ -24,4 +24,3 @@ export const DropdownMenuGroup = forwardRef< /> ); } ); -DropdownMenuGroup.displayName = 'DropdownMenuV2.Group'; diff --git a/packages/components/src/dropdown-menu-v2/index.tsx b/packages/components/src/dropdown-menu-v2/index.tsx index 73c0890b6121e6..96d335f7b38bb9 100644 --- a/packages/components/src/dropdown-menu-v2/index.tsx +++ b/packages/components/src/dropdown-menu-v2/index.tsx @@ -200,14 +200,30 @@ const UnconnectedDropdownMenu = ( export const DropdownMenuV2 = Object.assign( contextConnect( UnconnectedDropdownMenu, 'DropdownMenu' ), { - Context: DropdownMenuContext, - Item: DropdownMenuItem, - RadioItem: DropdownMenuRadioItem, - CheckboxItem: DropdownMenuCheckboxItem, - Group: DropdownMenuGroup, - Separator: DropdownMenuSeparator, - ItemLabel: DropdownMenuItemLabel, - ItemHelpText: DropdownMenuItemHelpText, + Context: Object.assign( DropdownMenuContext, { + displayName: 'DropdownMenuV2.Context', + } ), + Item: Object.assign( DropdownMenuItem, { + displayName: 'DropdownMenuV2.Item', + } ), + RadioItem: Object.assign( DropdownMenuRadioItem, { + displayName: 'DropdownMenuV2.RadioItem', + } ), + CheckboxItem: Object.assign( DropdownMenuCheckboxItem, { + displayName: 'DropdownMenuV2.CheckboxItem', + } ), + Group: Object.assign( DropdownMenuGroup, { + displayName: 'DropdownMenuV2.Group', + } ), + Separator: Object.assign( DropdownMenuSeparator, { + displayName: 'DropdownMenuV2.Separator', + } ), + ItemLabel: Object.assign( DropdownMenuItemLabel, { + displayName: 'DropdownMenuV2.ItemLabel', + } ), + ItemHelpText: Object.assign( DropdownMenuItemHelpText, { + displayName: 'DropdownMenuV2.ItemHelpText', + } ), } ); diff --git a/packages/components/src/dropdown-menu-v2/item-help-text.tsx b/packages/components/src/dropdown-menu-v2/item-help-text.tsx index 71240db1cacfb6..0408d20dfbd40d 100644 --- a/packages/components/src/dropdown-menu-v2/item-help-text.tsx +++ b/packages/components/src/dropdown-menu-v2/item-help-text.tsx @@ -21,4 +21,3 @@ export const DropdownMenuItemHelpText = forwardRef< /> ); } ); -DropdownMenuItemHelpText.displayName = 'DropdownMenuV2.ItemHelpText'; diff --git a/packages/components/src/dropdown-menu-v2/item-label.tsx b/packages/components/src/dropdown-menu-v2/item-label.tsx index 1ba03b59ace5cd..a1f9391af2f92d 100644 --- a/packages/components/src/dropdown-menu-v2/item-label.tsx +++ b/packages/components/src/dropdown-menu-v2/item-label.tsx @@ -21,4 +21,3 @@ export const DropdownMenuItemLabel = forwardRef< /> ); } ); -DropdownMenuItemLabel.displayName = 'DropdownMenuV2.ItemLabel'; diff --git a/packages/components/src/dropdown-menu-v2/item.tsx b/packages/components/src/dropdown-menu-v2/item.tsx index 35cd747b47c259..50cf21f614dc59 100644 --- a/packages/components/src/dropdown-menu-v2/item.tsx +++ b/packages/components/src/dropdown-menu-v2/item.tsx @@ -44,4 +44,3 @@ export const DropdownMenuItem = forwardRef< </Styled.DropdownMenuItem> ); } ); -DropdownMenuItem.displayName = 'DropdownMenuV2.Item'; diff --git a/packages/components/src/dropdown-menu-v2/radio-item.tsx b/packages/components/src/dropdown-menu-v2/radio-item.tsx index 6cfe85e149877c..c31f3ca0486398 100644 --- a/packages/components/src/dropdown-menu-v2/radio-item.tsx +++ b/packages/components/src/dropdown-menu-v2/radio-item.tsx @@ -64,4 +64,3 @@ export const DropdownMenuRadioItem = forwardRef< </Styled.DropdownMenuRadioItem> ); } ); -DropdownMenuRadioItem.displayName = 'DropdownMenuV2.RadioItem'; diff --git a/packages/components/src/dropdown-menu-v2/separator.tsx b/packages/components/src/dropdown-menu-v2/separator.tsx index 9bd551ea068ea5..bc5aff7ae26118 100644 --- a/packages/components/src/dropdown-menu-v2/separator.tsx +++ b/packages/components/src/dropdown-menu-v2/separator.tsx @@ -25,4 +25,3 @@ export const DropdownMenuSeparator = forwardRef< /> ); } ); -DropdownMenuSeparator.displayName = 'DropdownMenuV2.Separator'; From 23b7bafb4cd15dba81ff00dcb1a1565c511d71c0 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 26 Aug 2024 20:45:33 +0200 Subject: [PATCH 0538/1908] TimePicker: use ToggleGroupControl for AM/PM toggle (#64800) * TimePicker: use ToggleGroupControl instead of ButtonGroup * Update unit tests * CHANGELOG * Move changelog entry to bug fixes * Removed legacy classnames --- Unlinked contributors: MadGanGithub. Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: patil-vipul <vipulpatil@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++ .../src/date-time/time/test/index.tsx | 9 ++-- .../src/date-time/time/time-input/index.tsx | 50 +++++++++---------- .../date-time/time/time-input/test/index.tsx | 13 +++-- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 44536df98b5815..693fcf71db183f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -42,6 +42,10 @@ - `TreeSelect` - `UnitControl` +### Bug Fixes + +- `TimePicker`: use ToggleGroupControl for AM/PM toggle ([#64800](https://github.com/WordPress/gutenberg/pull/64800)). + ### Internal - `DropdownMenu` v2: refactor to overloaded naming convention ([#64654](https://github.com/WordPress/gutenberg/pull/64654)). diff --git a/packages/components/src/date-time/time/test/index.tsx b/packages/components/src/date-time/time/test/index.tsx index 0b91d95a5fc92d..6f843fda75336c 100644 --- a/packages/components/src/date-time/time/test/index.tsx +++ b/packages/components/src/date-time/time/test/index.tsx @@ -281,12 +281,9 @@ describe( 'TimePicker', () => { expect( ( screen.getByLabelText( 'Minutes' ) as HTMLInputElement ).value ).toBe( '00' ); - /** - * This is not ideal, but best of we can do for now until we refactor - * AM/PM into accessible elements, like radio buttons. - */ - expect( screen.getByText( 'AM' ) ).not.toHaveClass( 'is-primary' ); - expect( screen.getByText( 'PM' ) ).toHaveClass( 'is-primary' ); + + expect( screen.getByRole( 'radio', { name: 'AM' } ) ).not.toBeChecked(); + expect( screen.getByRole( 'radio', { name: 'PM' } ) ).toBeChecked(); } ); it( 'should have different layouts/orders for 12/24 hour formats', () => { diff --git a/packages/components/src/date-time/time/time-input/index.tsx b/packages/components/src/date-time/time/time-input/index.tsx index b4421c601b1d6d..e2628fdb7a2b46 100644 --- a/packages/components/src/date-time/time/time-input/index.tsx +++ b/packages/components/src/date-time/time/time-input/index.tsx @@ -20,8 +20,6 @@ import { Fieldset, } from '../styles'; import { HStack } from '../../../h-stack'; -import Button from '../../../button'; -import ButtonGroup from '../../../button-group'; import { from12hTo24h, from24hTo12h, @@ -32,6 +30,10 @@ import type { TimeInputProps } from '../../types'; import type { InputChangeCallback } from '../../../input-control/types'; import { useControlledValue } from '../../../utils'; import BaseControl from '../../../base-control'; +import { + ToggleGroupControl, + ToggleGroupControlOption, +} from '../../../toggle-group-control'; export function TimeInput( { value: valueProp, @@ -164,30 +166,28 @@ export function TimeInput( { /> </TimeWrapper> { is12Hour && ( - <ButtonGroup - className="components-datetime__time-field components-datetime__time-field-am-pm" // Unused, for backwards compatibility. + <ToggleGroupControl + __next40pxDefaultSize + __nextHasNoMarginBottom + isBlock + label={ __( 'Select AM or PM' ) } + hideLabelFromVision + value={ dayPeriod } + onChange={ ( newValue ) => { + buildAmPmChangeCallback( + newValue as 'AM' | 'PM' + )(); + } } > - <Button - className="components-datetime__time-am-button" // Unused, for backwards compatibility. - variant={ - dayPeriod === 'AM' ? 'primary' : 'secondary' - } - __next40pxDefaultSize - onClick={ buildAmPmChangeCallback( 'AM' ) } - > - { __( 'AM' ) } - </Button> - <Button - className="components-datetime__time-pm-button" // Unused, for backwards compatibility. - variant={ - dayPeriod === 'PM' ? 'primary' : 'secondary' - } - __next40pxDefaultSize - onClick={ buildAmPmChangeCallback( 'PM' ) } - > - { __( 'PM' ) } - </Button> - </ButtonGroup> + <ToggleGroupControlOption + value="AM" + label={ __( 'AM' ) } + /> + <ToggleGroupControlOption + value="PM" + label={ __( 'PM' ) } + /> + </ToggleGroupControl> ) } </HStack> </Wrapper> diff --git a/packages/components/src/date-time/time/time-input/test/index.tsx b/packages/components/src/date-time/time/time-input/test/index.tsx index c107cd2c9d79b6..eae082a12bc1c9 100644 --- a/packages/components/src/date-time/time/time-input/test/index.tsx +++ b/packages/components/src/date-time/time/time-input/test/index.tsx @@ -80,12 +80,11 @@ describe( 'TimeInput', () => { const minutesInput = screen.getByRole( 'spinbutton', { name: 'Minutes', } ); - const amButton = screen.getByRole( 'button', { name: 'AM' } ); - const pmButton = screen.getByRole( 'button', { name: 'PM' } ); + const amButton = screen.getByRole( 'radio', { name: 'AM' } ); + const pmButton = screen.getByRole( 'radio', { name: 'PM' } ); - // TODO: Update assert these states through the accessibility tree rather than through styles, see: https://github.com/WordPress/gutenberg/issues/61163 - expect( amButton ).toHaveClass( 'is-primary' ); - expect( pmButton ).not.toHaveClass( 'is-primary' ); + expect( amButton ).toBeChecked(); + expect( pmButton ).not.toBeChecked(); expect( hoursInput ).not.toHaveValue( 0 ); expect( hoursInput ).toHaveValue( 12 ); @@ -94,7 +93,7 @@ describe( 'TimeInput', () => { await user.keyboard( '{Tab}' ); expect( onChangeSpy ).toHaveBeenCalledWith( { hours: 0, minutes: 35 } ); - expect( amButton ).toHaveClass( 'is-primary' ); + expect( amButton ).toBeChecked(); await user.clear( hoursInput ); await user.type( hoursInput, '12' ); @@ -107,7 +106,7 @@ describe( 'TimeInput', () => { hours: 12, minutes: 35, } ); - expect( pmButton ).toHaveClass( 'is-primary' ); + expect( pmButton ).toBeChecked(); } ); it( 'should call onChange with defined minutes steps', async () => { From b0e7fe288f4a22fd4648494f4d1efa48417cb80a Mon Sep 17 00:00:00 2001 From: Ryan Welcher <me@ryanwelcher.com> Date: Mon, 26 Aug 2024 14:54:00 -0400 Subject: [PATCH 0539/1908] Add a new section to the SlotFill reference to show how to conditionally render Fills . (#64807) * Add a conditionally rendering section to slotfill docs. * Changes per peer review. * Update docs/reference-guides/slotfills/README.md Co-authored-by: Nick Diego <nick.diego@automattic.com> --------- Co-authored-by: Nick Diego <nick.diego@automattic.com> Co-authored-by: ryanwelcher <welcher@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> --- docs/reference-guides/slotfills/README.md | 233 ++++++++++++++++++++++ 1 file changed, 233 insertions(+) diff --git a/docs/reference-guides/slotfills/README.md b/docs/reference-guides/slotfills/README.md index b09aa5d49102e3..bab08dc34c40c1 100644 --- a/docs/reference-guides/slotfills/README.md +++ b/docs/reference-guides/slotfills/README.md @@ -29,6 +29,239 @@ const PluginPostStatusInfoTest = () => ( registerPlugin( 'post-status-info-test', { render: PluginPostStatusInfoTest } ); ``` +## Conditionally rendering SlotFill content + +With the exception of [MainDashboardButton](/docs/reference-guides/slotfills/main-dashboard-button.md), every available SlotFill is exposed in both the Post Editor and Site Editor and any Fill that is registered will be rendered in both contexts. There are a number of approaches that can be implemented to conditionally render Fills. + +### Restricting fills to the Post Editor + +A fill can be restricted to the Post Editor by checking to see if the current post type object property `viewable` is set to `true`. Any post type not set to `viewable`, does not have an associated edit post screen and is a good indicator that the user is not in the Post Editor. The example below will render its content on the edit post screen for any registered post type. + +```js +/** + * WordPress dependencies + */ +import { registerPlugin } from '@wordpress/plugins'; +import { + PluginDocumentSettingPanel, + store as editorStore, +} from '@wordpress/editor'; +import { store as coreStore } from '@wordpress/core-data'; +import { useSelect } from '@wordpress/data'; +import { __ } from '@wordpress/i18n'; + +/** + * The component to be rendered as part of the plugin. + */ +const EditPostDocumentSettingPanel = () => { + // Retrieve information about the current post type. + const isViewable = useSelect( ( select ) => { + const postTypeName = select( editorStore ).getCurrentPostType(); + const postTypeObject = select( coreStore ).getPostType( postTypeName ); + return postTypeObject?.viewable; + }, [] ); + + // If the post type is not viewable, then do not render my the fill. + if ( ! isViewable ) { + return null; + } + + return ( + <PluginDocumentSettingPanel + name="custom-panel" + title={ __( 'Post Editor Example' ) } + className="custom-panel" + > + <p>{ __( 'Only appears in the Edit Post screen' ) }</p> + </PluginDocumentSettingPanel> + ); +}; + +registerPlugin( 'example-post-edit-only', { + render: EditPostDocumentSettingPanel, +} ); +``` + +### Restricting fills to certain post types. + +The following example expands on the example above by creating an allow list of post types where the fill should be rendered. In this case, the fill is only rendered when editing pages. + +```js +/** + * WordPress dependencies + */ +import { registerPlugin } from '@wordpress/plugins'; +import { + PluginDocumentSettingPanel, + store as editorStore, +} from '@wordpress/editor'; +import { store as coreStore } from '@wordpress/core-data'; +import { useSelect } from '@wordpress/data'; +import { __, sprintf } from '@wordpress/i18n'; + +/** + * The component to be rendered as part of the plugin. + */ +const RestrictPostTypes = () => { + // Retrieve information about the current post type. + const { isViewable, postTypeName } = useSelect( ( select ) => { + const postType = select( editorStore ).getCurrentPostType(); + const postTypeObject = select( coreStore ).getPostType( postType ); + return { + isViewable: postTypeObject?.viewable, + postTypeName: postType, + }; + }, [] ); + + // The list of post types that are allowed to render the plugin. + const allowedPostTypes = [ 'page' ]; + + // If the post type is not viewable or not in the allowed list, do not render the plugin. + if ( ! isViewable || ! allowedPostTypes.includes( postTypeName ) ) { + return null; + } + + return ( + <PluginDocumentSettingPanel + name="custom-panel" + title={ __( 'Restrict Post Types Example' ) } + className="custom-panel" + > + <p> + { sprintf( + __( + 'Only appears on Post Types that are in the allowed list. %s' + ), + allowedPostTypes.join( ', ' ) + ) } + </p> + </PluginDocumentSettingPanel> + ); +}; + +registerPlugin( 'example-restrict-post-types', { + render: RestrictPostTypes, +} ); +``` + +### Restricting fills to the Side Editor + +To restrict fills to the Site Editor, the reverse logic is true. If the post type object's `viewable` property is set to `true`, then the fill should not be rendered. The example below will render its content on any Site Editor screen. + +```js +/** + * WordPress dependencies + */ +import { registerPlugin } from '@wordpress/plugins'; +import { + PluginDocumentSettingPanel, + store as editorStore, +} from '@wordpress/editor'; +import { store as coreStore } from '@wordpress/core-data'; +import { useSelect } from '@wordpress/data'; +import { __ } from '@wordpress/i18n'; + +/** + * The component to be rendered as part of the plugin. + */ +const SiteEditorDocumentSettingPanel = () => { + // Retrieve information about the current post type. + const { isViewable } = useSelect( ( select ) => { + const postTypeName = select( editorStore ).getCurrentPostType(); + const postTypeObject = select( coreStore ).getPostType( postTypeName ); + + // A viewable post type is one than can be viewed in the WordPress admin. Internal ones are not set to viewable. + return postTypeObject?.viewable; + }, [] ); + + // If the post type is viewable, do not render my fill + if ( isViewable ) { + return null; + } + + return ( + <PluginDocumentSettingPanel + name="custom-panel" + title={ __( 'Site Editor Example' ) } + className="custom-panel" + > + <p>{ __( 'Only appears in the Site Editor' ) }</p> + </PluginDocumentSettingPanel> + ); +}; + +registerPlugin( 'example-site-editor', { + render: SiteEditorDocumentSettingPanel, +} ); +``` + +### Restricting fills to certain screens in the Site Editor. + +This example builds on the example above by providing an allow list to control which screens a fill can be rendered within the Site Editor. + +```js +/** + * WordPress dependencies + */ +import { registerPlugin } from '@wordpress/plugins'; +import { + PluginDocumentSettingPanel, + store as editorStore, +} from '@wordpress/editor'; +import { store as coreStore } from '@wordpress/core-data'; +import { useSelect } from '@wordpress/data'; +import { __, sprintf } from '@wordpress/i18n'; + +/** + * The component to be rendered as part of the plugin. + */ +const SiteEditorDocumentSettingPanel = () => { + // Allowed areas in the Site Editor. + const allowedSiteEditorScreens = [ + 'wp_template', // Templates + 'wp_block', // Patterns + 'wp_template_part', // Template Parts + ]; + + const { isViewable, postType } = useSelect( ( select ) => { + const postTypeName = select( editorStore ).getCurrentPostType(); + const postTypeObject = select( coreStore ).getPostType( postTypeName ); + + return { + // A viewable post type is one than can be viewed in the WordPress admin. Internal ones are not set to viewable. + isViewable: postTypeObject?.viewable, + postType: postTypeName, + }; + }, [] ); + + // If the post type is viewable, do not render my plugin. + if ( isViewable || ! allowedSiteEditorScreens.includes( postType ) ) { + return null; + } + + return ( + <PluginDocumentSettingPanel + name="custom-panel" + title={ __( 'Restricted to Site Editor screens' ) } + className="custom-panel" + > + <p> + { sprintf( + __( + 'Only appears on Editor Screens that are in the allowed list. %s' + ), + allowedSiteEditorScreens.join( ', ' ) + ) } + </p> + </PluginDocumentSettingPanel> + ); +}; + +registerPlugin( 'example-site-editor-only', { + render: SiteEditorDocumentSettingPanel, +} ); +``` + ## How do they work? SlotFills are created using `createSlotFill`. This creates two components, `Slot` and `Fill` which are then used to create a new component that is exported on the `wp.plugins` global. From 1195cb28a20d11489c3180401441f581e5406dbc Mon Sep 17 00:00:00 2001 From: Raj Patel <71687258+imrraaj@users.noreply.github.com> Date: Tue, 27 Aug 2024 01:14:23 +0530 Subject: [PATCH 0540/1908] Fix: Adjust Site URL Styles to Prevent Overflow in Pre-Publish Component (#64745) Co-authored-by: imrraaj <imrraaj@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: vcanales <vcanales@git.wordpress.org> --- packages/editor/src/components/post-publish-panel/style.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/editor/src/components/post-publish-panel/style.scss b/packages/editor/src/components/post-publish-panel/style.scss index c319924086b0e4..bcd7c798c7e9fb 100644 --- a/packages/editor/src/components/post-publish-panel/style.scss +++ b/packages/editor/src/components/post-publish-panel/style.scss @@ -39,6 +39,7 @@ border: none; border-radius: $radius-block-ui; margin-right: $grid-unit-15; + flex-shrink: 0; // Same size as in the Site menu. height: 36px; @@ -54,6 +55,7 @@ display: block; color: $gray-700; font-size: $helptext-font-size; + word-break: break-word; } .editor-post-publish-panel__header-publish-button, From b74aeada2b26566ee071a0f973272f1861d86307 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 17:19:44 -0400 Subject: [PATCH 0541/1908] Bump the react-native group across 1 directory with 3 updates (#64375) Bumps the react-native group with 3 updates in the / directory: [actions/setup-java](https://github.com/actions/setup-java), [gradle/actions](https://github.com/gradle/actions) and [reactivecircus/android-emulator-runner](https://github.com/reactivecircus/android-emulator-runner). Updates `actions/setup-java` from 4.2.1 to 4.2.2 - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/99b8673ff64fbf99d8d325f52d9a5bdedb8483e9...6a0805fcefea3d4657a47ac4c165951e33482018) Updates `gradle/actions` from 3.4.2 to 4.0.0 - [Release notes](https://github.com/gradle/actions/releases) - [Commits](https://github.com/gradle/actions/compare/dbbdc275be76ac10734476cc723d82dfe7ec6eda...af1da67850ed9a4cedd57bfd976089dd991e2582) Updates `reactivecircus/android-emulator-runner` from 2.31.0 to 2.32.0 - [Release notes](https://github.com/reactivecircus/android-emulator-runner/releases) - [Changelog](https://github.com/ReactiveCircus/android-emulator-runner/blob/main/CHANGELOG.md) - [Commits](https://github.com/reactivecircus/android-emulator-runner/compare/77986be26589807b8ebab3fde7bbf5c60dabec32...f0d1ed2dcad93c7479e8b2f2226c83af54494915) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-patch dependency-group: react-native - dependency-name: gradle/actions dependency-type: direct:production update-type: version-update:semver-major dependency-group: react-native - dependency-name: reactivecircus/android-emulator-runner dependency-type: direct:production update-type: version-update:semver-minor dependency-group: react-native ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/rnmobile-android-runner.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index 23c1134c1417a0..3efd7d79ee2276 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -28,7 +28,7 @@ jobs: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Java - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: 'corretto' java-version: '17' @@ -47,7 +47,7 @@ jobs: run: npm run native test:e2e:setup - name: Gradle cache - uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3.4.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 - name: AVD cache uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 @@ -60,7 +60,7 @@ jobs: - name: Create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@77986be26589807b8ebab3fde7bbf5c60dabec32 # v2.31.0 + uses: reactivecircus/android-emulator-runner@f0d1ed2dcad93c7479e8b2f2226c83af54494915 # v2.32.0 with: api-level: ${{ matrix.api-level }} force-avd-creation: false @@ -71,7 +71,7 @@ jobs: script: echo "Generated AVD snapshot for caching." - name: Run tests - uses: reactivecircus/android-emulator-runner@77986be26589807b8ebab3fde7bbf5c60dabec32 # v2.31.0 + uses: reactivecircus/android-emulator-runner@f0d1ed2dcad93c7479e8b2f2226c83af54494915 # v2.32.0 with: api-level: ${{ matrix.api-level }} force-avd-creation: false From 8bdb64e894ac65088a3f6d22645de1b16c318980 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:06:25 +1000 Subject: [PATCH 0542/1908] Fluid typography: allow individual preset overrides (#64790) * This commit allows individual font preset overrides. So, if fluid typography is disabled or not active but an individual font preset does enable it, calculate the clamp value for that individual preset. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- backport-changelog/6.7/7247.md | 3 ++ lib/block-supports/typography.php | 34 +++++++------- .../global-styles/test/typography-utils.js | 46 +++++++++++++++++-- .../global-styles/typography-utils.js | 22 +++++++-- phpunit/block-supports/typography-test.php | 39 ++++++++++++++-- 5 files changed, 112 insertions(+), 32 deletions(-) create mode 100644 backport-changelog/6.7/7247.md diff --git a/backport-changelog/6.7/7247.md b/backport-changelog/6.7/7247.md new file mode 100644 index 00000000000000..d0b1de25872344 --- /dev/null +++ b/backport-changelog/6.7/7247.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7247 + +* https://github.com/WordPress/gutenberg/pull/64790 diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index fa2a7b81e94e21..c6ef59970de8c6 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -449,6 +449,7 @@ function gutenberg_get_computed_fluid_typography_value( $args = array() ) { * @since 6.3.0 Using layout.wideSize as max viewport width, and logarithmic scale factor to calculate minimum font scale. * @since 6.4.0 Added configurable min and max viewport width values to the typography.fluid theme.json schema. * @since 6.6.0 Deprecated bool argument $should_use_fluid_typography. + * @since 6.7.0 Enabled individual block fluid typography settings overrides. * * @param array $preset { * Required. fontSizes preset value as seen in theme.json. @@ -468,10 +469,11 @@ function gutenberg_get_typography_font_size_value( $preset, $settings = array() } /* - * Catches empty values and 0/'0'. - * Fluid calculations cannot be performed on 0. + * Catch falsy values and 0/'0'. Fluid calculations cannot be performed on `0`. + * Also return early when a preset font size explicitly disables fluid typography with `false`. */ - if ( empty( $preset['size'] ) ) { + $fluid_font_size_settings = $preset['fluid'] ?? null; + if ( false === $fluid_font_size_settings || empty( $preset['size'] ) ) { return $preset['size']; } @@ -489,20 +491,26 @@ function gutenberg_get_typography_font_size_value( $preset, $settings = array() } // Fallback to global settings as default. - $global_settings = gutenberg_get_global_settings(); - $settings = wp_parse_args( + $global_settings = gutenberg_get_global_settings(); + $settings = wp_parse_args( $settings, $global_settings ); - $typography_settings = isset( $settings['typography'] ) ? $settings['typography'] : array(); - $should_use_fluid_typography = ! empty( $typography_settings['fluid'] ); + $typography_settings = $settings['typography'] ?? array(); - if ( ! $should_use_fluid_typography ) { + /* + * Return early when fluid typography is disabled in the settings, and there + * are no local settings to enable it for the individual preset. + * + * If this condition isn't met, either the settings or individual preset settings + * have enabled fluid typography. + */ + if ( empty( $typography_settings['fluid'] ) && empty( $fluid_font_size_settings ) ) { return $preset['size']; } // $typography_settings['fluid'] can be a bool or an array. Normalize to array. - $fluid_settings = is_array( $typography_settings['fluid'] ) ? $typography_settings['fluid'] : array(); + $fluid_settings = isset( $typography_settings['fluid'] ) ? $typography_settings['fluid'] : array(); $layout_settings = isset( $settings['layout'] ) ? $settings['layout'] : array(); // Defaults. @@ -522,14 +530,6 @@ function gutenberg_get_typography_font_size_value( $preset, $settings = array() $has_min_font_size = isset( $fluid_settings['minFontSize'] ) && ! empty( gutenberg_get_typography_value_and_unit( $fluid_settings['minFontSize'] ) ); $minimum_font_size_limit = $has_min_font_size ? $fluid_settings['minFontSize'] : $default_minimum_font_size_limit; - // Font sizes. - $fluid_font_size_settings = isset( $preset['fluid'] ) ? $preset['fluid'] : null; - - // A font size has explicitly bypassed fluid calculations. - if ( false === $fluid_font_size_settings ) { - return $preset['size']; - } - // Try to grab explicit min and max fluid font sizes. $minimum_font_size_raw = isset( $fluid_font_size_settings['min'] ) ? $fluid_font_size_settings['min'] : null; $maximum_font_size_raw = isset( $fluid_font_size_settings['max'] ) ? $fluid_font_size_settings['max'] : null; diff --git a/packages/block-editor/src/components/global-styles/test/typography-utils.js b/packages/block-editor/src/components/global-styles/test/typography-utils.js index 41a7d6b5e37b8b..155eaa0fe063ee 100644 --- a/packages/block-editor/src/components/global-styles/test/typography-utils.js +++ b/packages/block-editor/src/components/global-styles/test/typography-utils.js @@ -28,7 +28,9 @@ describe( 'typography utils', () => { preset: { size: 0, }, - typographySettings: undefined, + typographySettings: { + fluid: true, + }, expected: 0, }, @@ -37,7 +39,9 @@ describe( 'typography utils', () => { preset: { size: '0', }, - typographySettings: undefined, + typographySettings: { + fluid: true, + }, expected: '0', }, @@ -46,7 +50,9 @@ describe( 'typography utils', () => { preset: { size: null, }, - typographySettings: null, + typographySettings: { + fluid: true, + }, expected: null, }, @@ -153,7 +159,6 @@ describe( 'typography utils', () => { message: 'should return already clamped value', preset: { size: 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)', - fluid: false, }, settings: { typography: { @@ -168,7 +173,6 @@ describe( 'typography utils', () => { message: 'should return value with unsupported unit', preset: { size: '1000%', - fluid: false, }, settings: { typography: { @@ -677,6 +681,38 @@ describe( 'typography utils', () => { }, expected: 'clamp(16px, 1rem + ((1vw - 6.4px) * 0.179), 17px)', }, + + // Individual preset settings override global settings. + { + message: + 'should convert individual preset size to fluid if fluid is disabled in global settings', + preset: { + size: '17px', + fluid: true, + }, + settings: { + typography: {}, + }, + expected: + 'clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.234), 17px)', + }, + { + message: + 'should use individual preset settings if fluid is disabled in global settings', + preset: { + size: '17px', + fluid: { + min: '16px', + max: '26px', + }, + }, + settings: { + typography: { + fluid: false, + }, + }, + expected: 'clamp(16px, 1rem + ((1vw - 3.2px) * 0.781), 26px)', + }, ].forEach( ( { message, preset, settings, expected } ) => { it( `${ message }`, () => { expect( getTypographyFontSizeValue( preset, settings ) ).toBe( diff --git a/packages/block-editor/src/components/global-styles/typography-utils.js b/packages/block-editor/src/components/global-styles/typography-utils.js index 59ff04bf21ebcb..32fbd50db2dbff 100644 --- a/packages/block-editor/src/components/global-styles/typography-utils.js +++ b/packages/block-editor/src/components/global-styles/typography-utils.js @@ -40,6 +40,8 @@ import { getFontStylesAndWeights } from '../../utils/get-font-styles-and-weights * Returns a font-size value based on a given font-size preset. * Takes into account fluid typography parameters and attempts to return a css formula depending on available, valid values. * + * The Core PHP equivalent is wp_get_typography_font_size_value(). + * * @param {Preset} preset * @param {Object} settings * @param {boolean|TypographySettings} settings.typography.fluid Whether fluid typography is enabled, and, optionally, fluid font size options. @@ -50,15 +52,25 @@ import { getFontStylesAndWeights } from '../../utils/get-font-styles-and-weights export function getTypographyFontSizeValue( preset, settings ) { const { size: defaultSize } = preset; - if ( ! isFluidTypographyEnabled( settings?.typography ) ) { + /* + * Catch falsy values and 0/'0'. Fluid calculations cannot be performed on `0`. + * Also return early when a preset font size explicitly disables fluid typography with `false`. + */ + if ( ! defaultSize || '0' === defaultSize || false === preset?.fluid ) { return defaultSize; } + /* - * Checks whether a font size has explicitly bypassed fluid calculations. - * Also catches falsy values and 0/'0'. - * Fluid calculations cannot be performed on `0`. + * Return early when fluid typography is disabled in the settings, and there + * are no local settings to enable it for the individual preset. + * + * If this condition isn't met, either the settings or individual preset settings + * have enabled fluid typography. */ - if ( ! defaultSize || '0' === defaultSize || false === preset?.fluid ) { + if ( + ! isFluidTypographyEnabled( settings?.typography ) && + ! isFluidTypographyEnabled( preset ) + ) { return defaultSize; } diff --git a/phpunit/block-supports/typography-test.php b/phpunit/block-supports/typography-test.php index 61aa76d591e9c2..eafd505db6ec65 100644 --- a/phpunit/block-supports/typography-test.php +++ b/phpunit/block-supports/typography-test.php @@ -351,7 +351,11 @@ public function data_generate_font_size_preset_fixtures() { 'font_size' => array( 'size' => null, ), - 'settings' => null, + 'settings' => array( + 'typography' => array( + 'fluid' => true, + ), + ), 'expected_output' => null, ), @@ -425,8 +429,7 @@ public function data_generate_font_size_preset_fixtures() { 'returns already clamped value' => array( 'font_size' => array( - 'size' => 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)', - 'fluid' => false, + 'size' => 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)', ), 'settings' => array( 'typography' => array( @@ -438,8 +441,7 @@ public function data_generate_font_size_preset_fixtures() { 'returns value with unsupported unit' => array( 'font_size' => array( - 'size' => '1000%', - 'fluid' => false, + 'size' => '1000%', ), 'settings' => array( 'typography' => array( @@ -769,6 +771,33 @@ public function data_generate_font_size_preset_fixtures() { ), 'expected_output' => 'clamp(100px, 6.25rem + ((1vw - 3.2px) * 7.813), 200px)', ), + + // Individual preset settings override global settings. + 'should convert individual preset size to fluid if fluid is disabled in global settings' => array( + 'font_size' => array( + 'size' => '17px', + 'fluid' => true, + ), + 'settings' => array( + 'typography' => array(), + ), + 'expected_output' => 'clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.234), 17px)', + ), + 'should use individual preset settings if fluid is disabled in global settings' => array( + 'font_size' => array( + 'size' => '17px', + 'fluid' => array( + 'min' => '16px', + 'max' => '26px', + ), + ), + 'settings' => array( + 'typography' => array( + 'fluid' => false, + ), + ), + 'expected_output' => 'clamp(16px, 1rem + ((1vw - 3.2px) * 0.781), 26px)', + ), ); } From 7c73e6e19aff0832531f5aa9f1a206d708f768a3 Mon Sep 17 00:00:00 2001 From: Matias Benedetto <matias.benedetto@gmail.com> Date: Mon, 26 Aug 2024 23:11:37 -0300 Subject: [PATCH 0543/1908] fix the default fluid value on the UI based on the global typography fluid value (#64803) Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/components/global-styles/font-sizes/font-size.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js index 7eaf74c3365cc7..eec86acb8533f4 100644 --- a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js @@ -44,14 +44,17 @@ function FontSize() { 'typography.fontSizes' ); + const [ globalFluid ] = useGlobalSetting( 'typography.fluid' ); + // Get the font sizes from the origin, default to empty array. const sizes = fontSizes[ origin ] ?? []; // Get the font size by slug. const fontSize = sizes.find( ( size ) => size.slug === slug ); - // Whether fluid is true or an object, set it to true, otherwise false. - const isFluid = !! fontSize.fluid ?? false; + // Whether the font size is fluid. If not defined, use the global fluid value of the theme. + const isFluid = + fontSize.fluid !== undefined ? !! fontSize.fluid : globalFluid; // Whether custom fluid values are used. const isCustomFluid = typeof fontSize.fluid === 'object'; From 6be14bbaa73c2d6a9620747d8f46fd9f0b49d714 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 27 Aug 2024 08:17:46 +0400 Subject: [PATCH 0544/1908] Core Data: Resolve entity collection user permissions (#64504) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: TimothyBJacobs <timothyblynjacobs@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: spacedmonkey <spacedmonkey@git.wordpress.org> --- backport-changelog/6.7/7139.md | 3 + .../class-gutenberg-rest-server.php | 169 ++++++++++++++++++ lib/compat/wordpress-6.7/rest-api.php | 10 ++ lib/load.php | 1 + packages/core-data/src/resolvers.js | 50 +++++- packages/core-data/src/test/resolvers.js | 1 + packages/core-data/src/utils/index.js | 2 +- .../core-data/src/utils/user-permissions.js | 10 +- phpunit/class-gutenberg-rest-server-test.php | 88 +++++++++ 9 files changed, 322 insertions(+), 12 deletions(-) create mode 100644 backport-changelog/6.7/7139.md create mode 100644 lib/compat/wordpress-6.7/class-gutenberg-rest-server.php create mode 100644 phpunit/class-gutenberg-rest-server-test.php diff --git a/backport-changelog/6.7/7139.md b/backport-changelog/6.7/7139.md new file mode 100644 index 00000000000000..9023695102a919 --- /dev/null +++ b/backport-changelog/6.7/7139.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7139 + +* https://github.com/WordPress/gutenberg/pull/64504 diff --git a/lib/compat/wordpress-6.7/class-gutenberg-rest-server.php b/lib/compat/wordpress-6.7/class-gutenberg-rest-server.php new file mode 100644 index 00000000000000..8374e8dc1fa23f --- /dev/null +++ b/lib/compat/wordpress-6.7/class-gutenberg-rest-server.php @@ -0,0 +1,169 @@ +<?php +/** + * A custom REST server for Gutenberg. + * + * @package gutenberg + * @since 6.7.0 + */ + +class Gutenberg_REST_Server extends WP_REST_Server { + /** + * Converts a response to data to send. + * + * @since 4.4.0 + * @since 5.4.0 The `$embed` parameter can now contain a list of link relations to include. + * + * @param WP_REST_Response $response Response object. + * @param bool|string[] $embed Whether to embed all links, a filtered list of link relations, or no links. + * @return array { + * Data with sub-requests embedded. + * + * @type array $_links Links. + * @type array $_embedded Embedded objects. + * } + */ + // @core-merge: Do not merge. The method is copied here to fix the inheritance issue. + public function response_to_data( $response, $embed ) { + $data = $response->get_data(); + $links = static::get_compact_response_links( $response ); + + if ( ! empty( $links ) ) { + // Convert links to part of the data. + $data['_links'] = $links; + } + + if ( $embed ) { + $this->embed_cache = array(); + // Determine if this is a numeric array. + if ( wp_is_numeric_array( $data ) ) { + foreach ( $data as $key => $item ) { + $data[ $key ] = $this->embed_links( $item, $embed ); + } + } else { + $data = $this->embed_links( $data, $embed ); + } + $this->embed_cache = array(); + } + + return $data; + } + + /** + * Retrieves links from a response. + * + * Extracts the links from a response into a structured hash, suitable for + * direct output. + * + * @since 4.4.0 + * @since 6.7.0 The `targetHints` property to the `self` link object was added. + * + * @param WP_REST_Response $response Response to extract links from. + * @return array Map of link relation to list of link hashes. + */ + public static function get_response_links( $response ) { + $links = $response->get_links(); + + if ( empty( $links ) ) { + return array(); + } + + $server = rest_get_server(); + + // Convert links to part of the data. + $data = array(); + foreach ( $links as $rel => $items ) { + $data[ $rel ] = array(); + + foreach ( $items as $item ) { + $attributes = $item['attributes']; + $attributes['href'] = $item['href']; + + if ( 'self' !== $rel ) { + $data[ $rel ][] = $attributes; + continue; + } + + // Prefer targetHints that were specifically designated by the developer. + if ( isset( $attributes['targetHints']['allow'] ) ) { + $data[ $rel ][] = $attributes; + continue; + } + + $request = WP_REST_Request::from_url( $item['href'] ); + if ( ! $request ) { + $data[ $rel ][] = $attributes; + continue; + } + + $match = $server->match_request_to_handler( $request ); + if ( ! is_wp_error( $match ) ) { + $response = new WP_REST_Response(); + $response->set_matched_route( $match[0] ); + $response->set_matched_handler( $match[1] ); + $headers = rest_send_allow_header( $response, $server, $request )->get_headers(); + + foreach ( $headers as $name => $value ) { + $name = WP_REST_Request::canonicalize_header_name( $name ); + $attributes['targetHints'][ $name ] = array_map( 'trim', explode( ',', $value ) ); + } + } + + $data[ $rel ][] = $attributes; + } + } + + return $data; + } + + /** + * Retrieves the CURIEs (compact URIs) used for relations. + * + * Extracts the links from a response into a structured hash, suitable for + * direct output. + * + * @since 4.5.0 + * + * @param WP_REST_Response $response Response to extract links from. + * @return array Map of link relation to list of link hashes. + */ + // @core-merge: Do not merge. The method is copied here to fix the inheritance issue. + public static function get_compact_response_links( $response ) { + $links = static::get_response_links( $response ); + + if ( empty( $links ) ) { + return array(); + } + + $curies = $response->get_curies(); + $used_curies = array(); + + foreach ( $links as $rel => $items ) { + + // Convert $rel URIs to their compact versions if they exist. + foreach ( $curies as $curie ) { + $href_prefix = substr( $curie['href'], 0, strpos( $curie['href'], '{rel}' ) ); + if ( ! str_starts_with( $rel, $href_prefix ) ) { + continue; + } + + // Relation now changes from '$uri' to '$curie:$relation'. + $rel_regex = str_replace( '\{rel\}', '(.+)', preg_quote( $curie['href'], '!' ) ); + preg_match( '!' . $rel_regex . '!', $rel, $matches ); + if ( $matches ) { + $new_rel = $curie['name'] . ':' . $matches[1]; + $used_curies[ $curie['name'] ] = $curie; + $links[ $new_rel ] = $items; + unset( $links[ $rel ] ); + break; + } + } + } + + // Push the curies onto the start of the links array. + if ( $used_curies ) { + $links['curies'] = array_values( $used_curies ); + } + + return $links; + } +} diff --git a/lib/compat/wordpress-6.7/rest-api.php b/lib/compat/wordpress-6.7/rest-api.php index 081c22c8102914..f2f5d72104527d 100644 --- a/lib/compat/wordpress-6.7/rest-api.php +++ b/lib/compat/wordpress-6.7/rest-api.php @@ -98,3 +98,13 @@ function gutenberg_register_wp_rest_templates_controller_plugin_field() { ); } add_action( 'rest_api_init', 'gutenberg_register_wp_rest_templates_controller_plugin_field' ); + +/** + * Overrides the default 'WP_REST_Server' class. + * + * @return string The name of the custom server class. + */ +function gutenberg_override_default_rest_server() { + return 'Gutenberg_REST_Server'; +} +add_filter( 'wp_rest_server_class', 'gutenberg_override_default_rest_server', 1 ); diff --git a/lib/load.php b/lib/load.php index b501f0abd1c978..2f2c168a5fc290 100644 --- a/lib/load.php +++ b/lib/load.php @@ -42,6 +42,7 @@ function gutenberg_is_experiment_enabled( $name ) { // WordPress 6.7 compat. require __DIR__ . '/compat/wordpress-6.7/class-gutenberg-rest-templates-controller-6-7.php'; + require __DIR__ . '/compat/wordpress-6.7/class-gutenberg-rest-server.php'; require __DIR__ . '/compat/wordpress-6.7/rest-api.php'; // Plugin specific code. diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index c28f018508e38c..2cec1997c0efd9 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -19,7 +19,7 @@ import { forwardResolver, getNormalizedCommaSeparable, getUserPermissionCacheKey, - getUserPermissionsFromResponse, + getUserPermissionsFromAllowHeader, ALLOWED_RESOURCE_ACTIONS, } from './utils'; import { getSyncProvider } from './sync'; @@ -173,7 +173,9 @@ export const getEntityRecord = const response = await apiFetch( { path, parse: false } ); const record = await response.json(); - const permissions = getUserPermissionsFromResponse( response ); + const permissions = getUserPermissionsFromAllowHeader( + response.headers?.get( 'allow' ) + ); registry.batch( () => { dispatch.receiveEntityRecords( kind, name, record, query ); @@ -299,19 +301,52 @@ export const getEntityRecords = meta ); - // When requesting all fields, the list of results can be used to - // resolve the `getEntityRecord` selector in addition to `getEntityRecords`. + // When requesting all fields, the list of results can be used to resolve + // the `getEntityRecord` and `canUser` selectors in addition to `getEntityRecords`. // See https://github.com/WordPress/gutenberg/pull/26575 + // See https://github.com/WordPress/gutenberg/pull/64504 if ( ! query?._fields && ! query.context ) { const key = entityConfig.key || DEFAULT_ENTITY_KEY; const resolutionsArgs = records .filter( ( record ) => record?.[ key ] ) .map( ( record ) => [ kind, name, record[ key ] ] ); + const targetHints = records + .filter( ( record ) => record?.[ key ] ) + .map( ( record ) => ( { + id: record[ key ], + permissions: getUserPermissionsFromAllowHeader( + record?._links?.self?.[ 0 ].targetHints.allow + ), + } ) ); + + const canUserResolutionsArgs = []; + for ( const targetHint of targetHints ) { + for ( const action of ALLOWED_RESOURCE_ACTIONS ) { + canUserResolutionsArgs.push( [ + action, + { kind, name, id: targetHint.id }, + ] ); + + dispatch.receiveUserPermission( + getUserPermissionCacheKey( action, { + kind, + name, + id: targetHint.id, + } ), + targetHint.permissions[ action ] + ); + } + } + dispatch.finishResolutions( 'getEntityRecord', resolutionsArgs ); + dispatch.finishResolutions( + 'canUser', + canUserResolutionsArgs + ); } dispatch.__unstableReleaseStoreLock( lock ); @@ -440,7 +475,12 @@ export const canUser = return; } - const permissions = getUserPermissionsFromResponse( response ); + // Optional chaining operator is used here because the API requests don't + // return the expected result in the React native version. Instead, API requests + // only return the result, without including response properties like the headers. + const permissions = getUserPermissionsFromAllowHeader( + response.headers?.get( 'allow' ) + ); registry.batch( () => { for ( const action of ALLOWED_RESOURCE_ACTIONS ) { const key = getUserPermissionCacheKey( action, resource, id ); diff --git a/packages/core-data/src/test/resolvers.js b/packages/core-data/src/test/resolvers.js index fa0d53d79aa7d8..240d6b1e1a29c2 100644 --- a/packages/core-data/src/test/resolvers.js +++ b/packages/core-data/src/test/resolvers.js @@ -219,6 +219,7 @@ describe( 'getEntityRecords', () => { const finishResolutions = jest.fn(); const dispatch = Object.assign( jest.fn(), { receiveEntityRecords: jest.fn(), + receiveUserPermission: jest.fn(), __unstableAcquireStoreLock: jest.fn(), __unstableReleaseStoreLock: jest.fn(), finishResolutions, diff --git a/packages/core-data/src/utils/index.js b/packages/core-data/src/utils/index.js index bb4b5544435021..189635647779e5 100644 --- a/packages/core-data/src/utils/index.js +++ b/packages/core-data/src/utils/index.js @@ -11,6 +11,6 @@ export { default as getNestedValue } from './get-nested-value'; export { default as isNumericID } from './is-numeric-id'; export { getUserPermissionCacheKey, - getUserPermissionsFromResponse, + getUserPermissionsFromAllowHeader, ALLOWED_RESOURCE_ACTIONS, } from './user-permissions'; diff --git a/packages/core-data/src/utils/user-permissions.js b/packages/core-data/src/utils/user-permissions.js index a81c83f9e5af50..f1f02b5f5ba702 100644 --- a/packages/core-data/src/utils/user-permissions.js +++ b/packages/core-data/src/utils/user-permissions.js @@ -5,13 +5,11 @@ export const ALLOWED_RESOURCE_ACTIONS = [ 'delete', ]; -export function getUserPermissionsFromResponse( response ) { +export function getUserPermissionsFromAllowHeader( allowedMethods ) { const permissions = {}; - - // Optional chaining operator is used here because the API requests don't - // return the expected result in the React native version. Instead, API requests - // only return the result, without including response properties like the headers. - const allowedMethods = response.headers?.get( 'allow' ) || ''; + if ( ! allowedMethods ) { + return permissions; + } const methods = { create: 'POST', diff --git a/phpunit/class-gutenberg-rest-server-test.php b/phpunit/class-gutenberg-rest-server-test.php new file mode 100644 index 00000000000000..943d5b34b999ec --- /dev/null +++ b/phpunit/class-gutenberg-rest-server-test.php @@ -0,0 +1,88 @@ +<?php + +class Gutenberg_REST_Server_Test extends WP_Test_REST_TestCase { + + protected static $admin_id; + protected static $post_id; + + public static function wpSetupBeforeClass( $factory ) { + self::$admin_id = $factory->user->create( + array( + 'role' => 'administrator', + ) + ); + + self::$post_id = $factory->post->create(); + } + + public static function wpTearDownAfterClass() { + self::delete_user( self::$admin_id ); + wp_delete_post( self::$post_id ); + } + + public function set_up() { + parent::set_up(); + add_filter( + 'wp_rest_server_class', + function () { + return 'Gutenberg_REST_Server'; + } + ); + } + + public function test_populates_target_hints_for_administrator() { + wp_set_current_user( self::$admin_id ); + $response = rest_do_request( '/wp/v2/posts' ); + $post = $response->get_data()[0]; + + $link = $post['_links']['self'][0]; + $this->assertArrayHasKey( 'targetHints', $link ); + $this->assertArrayHasKey( 'allow', $link['targetHints'] ); + $this->assertSame( array( 'GET', 'POST', 'PUT', 'PATCH', 'DELETE' ), $link['targetHints']['allow'] ); + } + + public function test_populates_target_hints_for_logged_out_user() { + $response = rest_do_request( '/wp/v2/posts' ); + $post = $response->get_data()[0]; + + $link = $post['_links']['self'][0]; + $this->assertArrayHasKey( 'targetHints', $link ); + $this->assertArrayHasKey( 'allow', $link['targetHints'] ); + $this->assertSame( array( 'GET' ), $link['targetHints']['allow'] ); + } + + public function test_does_not_error_on_invalid_urls() { + $response = new WP_REST_Response(); + $response->add_link( 'self', 'this is not a real URL' ); + + $links = rest_get_server()::get_response_links( $response ); + $this->assertArrayNotHasKey( 'targetHints', $links['self'][0] ); + } + + public function test_does_not_error_on_bad_rest_api_routes() { + $response = new WP_REST_Response(); + $response->add_link( 'self', rest_url( '/this/is/not/a/real/route' ) ); + + $links = rest_get_server()::get_response_links( $response ); + $this->assertArrayNotHasKey( 'targetHints', $links['self'][0] ); + } + + public function test_prefers_developer_defined_target_hints() { + $response = new WP_REST_Response(); + $response->add_link( + 'self', + '/wp/v2/posts/' . self::$post_id, + array( + 'targetHints' => array( + 'allow' => array( 'GET', 'PUT' ), + ), + ) + ); + + $links = rest_get_server()::get_response_links( $response ); + $link = $links['self'][0]; + $this->assertArrayHasKey( 'targetHints', $link ); + $this->assertArrayHasKey( 'allow', $link['targetHints'] ); + $this->assertSame( array( 'GET', 'PUT' ), $link['targetHints']['allow'] ); + } +} From 9a6b2cca1a83e13237fd0f18bd2ce74d54f975b0 Mon Sep 17 00:00:00 2001 From: Jawad Malik <82345120+jawadmalikdev@users.noreply.github.com> Date: Tue, 27 Aug 2024 09:21:40 +0500 Subject: [PATCH 0545/1908] [Docs]: update block variation picker store import (#55555) Unlinked contributors: jawadmalikdev. Co-authored-by: ajitbohra <ajitbohra@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/block-variation-picker/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-variation-picker/README.md b/packages/block-editor/src/components/block-variation-picker/README.md index 84aae556160667..891cd21b1f50c2 100644 --- a/packages/block-editor/src/components/block-variation-picker/README.md +++ b/packages/block-editor/src/components/block-variation-picker/README.md @@ -19,9 +19,9 @@ Renders the variations of a block. ```jsx import { useSelect } from '@wordpress/data'; import { - __experimentalBlockVariationPicker as BlockVariationPicker, - store as blockEditorStore, + __experimentalBlockVariationPicker as BlockVariationPicker } from '@wordpress/block-editor'; +import { store as blocksStore } from '@wordpress/blocks'; const MyBlockVariationPicker = ( { blockName } ) => { const variations = useSelect( From 0f1924357719462cfbc3f48cb45828b16ae4a108 Mon Sep 17 00:00:00 2001 From: Carolina Nymark <myazalea@hotmail.com> Date: Tue, 27 Aug 2024 07:28:40 +0200 Subject: [PATCH 0546/1908] Fix: Page list: Pages without a title has no link text (#64297) Add placeholder title to the page list block, that shows when the page is missing a title. Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/block-library/src/page-list/edit.js | 6 +++++- packages/block-library/src/page-list/index.php | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/page-list/edit.js b/packages/block-library/src/page-list/edit.js index 2b7f31c3c7c5e5..923b2d4fd88555 100644 --- a/packages/block-library/src/page-list/edit.js +++ b/packages/block-library/src/page-list/edit.js @@ -225,7 +225,11 @@ export default function PageListEdit( { page.title?.rendered?.trim() !== '' ? page.title?.rendered : __( '(no title)' ), - title: page.title?.rendered, + title: + // translators: displayed when a page has an empty title. + page.title?.rendered?.trim() !== '' + ? page.title?.rendered + : __( '(no title)' ), link: page.url, hasChildren, }; diff --git a/packages/block-library/src/page-list/index.php b/packages/block-library/src/page-list/index.php index 4ff57e1a36a23e..a574633d4ddf47 100644 --- a/packages/block-library/src/page-list/index.php +++ b/packages/block-library/src/page-list/index.php @@ -192,7 +192,9 @@ function block_core_page_list_render_nested_page_list( $open_submenus_on_click, $css_class .= ' menu-item-home'; } - $title = wp_kses_post( $page['title'] ); + $title = wp_kses_post( $page['title'] ); + $title = $title ? $title : __( '(no title)' ); + $aria_label = sprintf( /* translators: Accessibility text. %s: Parent page title. */ __( '%s submenu' ), From 2520296ec9b555195122065bfd671d76449f4e25 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Tue, 27 Aug 2024 01:55:52 -0400 Subject: [PATCH 0547/1908] Revert "Downgrade node 22(.5) unit tests to 22.4 (#63728)" (#63758) This reverts commit 32b4b2ec8acf8dc5e5eca4efbf6ed0ad6be3c3de. Co-authored-by: Jonathan Desrosiers <desrosj@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- .github/workflows/create-block.yml | 10 +++------- .github/workflows/unit-test.yml | 20 ++++++-------------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/.github/workflows/create-block.yml b/.github/workflows/create-block.yml index 245b136ee22c18..0de1b9ee6566ae 100644 --- a/.github/workflows/create-block.yml +++ b/.github/workflows/create-block.yml @@ -14,17 +14,13 @@ concurrency: jobs: checks: - name: Checks w/Node.js ${{ matrix.node.name }} on ${{ matrix.os }} + name: Checks w/Node.js ${{ matrix.node }} on ${{ matrix.os }} runs-on: ${{ matrix.os }} if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} strategy: fail-fast: false matrix: - node: - - name: 20 - version: 20 - - name: 22 - version: 22.4 + node: ['20', '22'] os: ['macos-latest', 'ubuntu-latest', 'windows-latest'] steps: @@ -35,7 +31,7 @@ jobs: - name: Setup Node.js and install dependencies uses: ./.github/setup-node with: - node-version: ${{ matrix.node.version }} + node-version: ${{ matrix.node }} - name: Create block shell: bash diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 98764848ecd809..c0f70070908c1c 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -21,17 +21,13 @@ concurrency: jobs: unit-js: - name: JavaScript (Node.js ${{ matrix.node.name }}) ${{ matrix.shard }} + name: JavaScript (Node.js ${{ matrix.node }}) ${{ matrix.shard }} runs-on: ubuntu-latest if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} strategy: fail-fast: false matrix: - node: - - name: 20 - version: 20 - - name: 22 - version: 22.4 + node: ['20', '22'] shard: ['1/4', '2/4', '3/4', '4/4'] steps: @@ -43,7 +39,7 @@ jobs: - name: Setup Node.js and install dependencies uses: ./.github/setup-node with: - node-version: ${{ matrix.node.version }} + node-version: ${{ matrix.node }} - name: Determine the number of CPU cores uses: SimenB/github-actions-cpu-cores@97ba232459a8e02ff6121db9362b09661c875ab8 # v2.0.0 @@ -64,17 +60,13 @@ jobs: --cacheDirectory="$HOME/.jest-cache" unit-js-date: - name: JavaScript Date Tests (Node.js ${{ matrix.node.name }}) + name: JavaScript Date Tests (Node.js ${{ matrix.node }}) runs-on: ubuntu-latest if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} strategy: fail-fast: false matrix: - node: - - name: 20 - version: 20 - - name: 22 - version: 22.4 + node: ['20', '22'] steps: - name: Checkout repository @@ -85,7 +77,7 @@ jobs: - name: Setup Node.js and install dependencies uses: ./.github/setup-node with: - node-version: ${{ matrix.node.version }} + node-version: ${{ matrix.node }} - name: Determine the number of CPU cores uses: SimenB/github-actions-cpu-cores@97ba232459a8e02ff6121db9362b09661c875ab8 # v2.0.0 From 482c18803ed9becccc57d1b23632438e1afc1d67 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Tue, 27 Aug 2024 09:38:07 +0200 Subject: [PATCH 0548/1908] Flaky Test: Fix "Sorting" test in new-templates-list.spec.js (#64776) * Use claude AI to fix flaky * Cleaner approach * Comment cleaning --- .../e2e/specs/site-editor/new-templates-list.spec.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/e2e/specs/site-editor/new-templates-list.spec.js b/test/e2e/specs/site-editor/new-templates-list.spec.js index 31dbe9af814d2e..6faa85a2659cf1 100644 --- a/test/e2e/specs/site-editor/new-templates-list.spec.js +++ b/test/e2e/specs/site-editor/new-templates-list.spec.js @@ -22,9 +22,11 @@ test.describe( 'Templates', () => { test( 'Sorting', async ( { admin, page } ) => { await admin.visitSiteEditor( { postType: 'wp_template' } ); - // Descending by title. - await page.getByRole( 'button', { name: 'View options' } ).click(); - await page.getByRole( 'radio', { name: 'Sort descending' } ).click(); + // Wait for the template list to be visible. + await expect( + page.locator( '[aria-label="Templates"]' ) + ).toBeVisible(); + const firstTitle = page .getByRole( 'region', { name: 'Template', @@ -32,6 +34,10 @@ test.describe( 'Templates', () => { } ) .getByRole( 'link', { includeHidden: true } ) .first(); + + // Descending by title. + await page.getByRole( 'button', { name: 'View options' } ).click(); + await page.getByRole( 'radio', { name: 'Sort descending' } ).click(); await expect( firstTitle ).toHaveText( 'Tag Archives' ); // Ascending by title. From bee59379db7bc86f870799ad53aa6bb9acee8ce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 27 Aug 2024 10:54:07 +0200 Subject: [PATCH 0549/1908] DataViews: hide sort direction control if there is no sortable fields (#64817) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../src/components/dataviews-view-config/index.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index 3e4fc97308aa32..bd9bc1b19803e1 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -139,6 +139,14 @@ function SortFieldControl() { function SortDirectionControl() { const { view, fields, onChangeView } = useContext( DataViewsContext ); + + const sortableFields = fields.filter( + ( field ) => field.enableSorting !== false + ); + if ( sortableFields.length === 0 ) { + return null; + } + let value = view.sort?.direction; if ( ! value && view.sort?.field ) { value = 'desc'; From 9c527761d4fac06f84fa77c170ac811aa56a242c Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 27 Aug 2024 18:17:53 +0900 Subject: [PATCH 0550/1908] Storybook: Hide deprecated `__next36pxDefaultSize` prop (#64806) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/src/combobox-control/types.ts | 1 + packages/components/src/form-token-field/types.ts | 1 + packages/components/src/input-control/types.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/packages/components/src/combobox-control/types.ts b/packages/components/src/combobox-control/types.ts index 61953ce9466293..10adf8c0ff0ef6 100644 --- a/packages/components/src/combobox-control/types.ts +++ b/packages/components/src/combobox-control/types.ts @@ -31,6 +31,7 @@ export type ComboboxControlProps = Pick< * * @default false * @deprecated + * @ignore */ __next36pxDefaultSize?: boolean; /** diff --git a/packages/components/src/form-token-field/types.ts b/packages/components/src/form-token-field/types.ts index db4549a7f0779c..051f00a6cdeb06 100644 --- a/packages/components/src/form-token-field/types.ts +++ b/packages/components/src/form-token-field/types.ts @@ -157,6 +157,7 @@ export interface FormTokenFieldProps * * @default false * @deprecated + * @ignore */ __next36pxDefaultSize?: boolean; /** diff --git a/packages/components/src/input-control/types.ts b/packages/components/src/input-control/types.ts index ef01a9fe3db00a..7d7a8267424b88 100644 --- a/packages/components/src/input-control/types.ts +++ b/packages/components/src/input-control/types.ts @@ -31,6 +31,7 @@ interface BaseProps { * * @default false * @deprecated + * @ignore */ __next36pxDefaultSize?: boolean; /** From fb15df10badb69e8a5a2630fac548517ba4ef91f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Gomes?= <mail@sgomes.com> Date: Tue, 27 Aug 2024 10:19:45 +0100 Subject: [PATCH 0551/1908] Post publish upload media dialog: fix silent failure (#64741) * Post publish upload media dialog: fix silent failure * Wait until animation ends before activating button --- .../post-publish-panel/maybe-upload-media.js | 53 +++++++++---------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/packages/editor/src/components/post-publish-panel/maybe-upload-media.js b/packages/editor/src/components/post-publish-panel/maybe-upload-media.js index 7061ab9c387ee9..609864e01716a8 100644 --- a/packages/editor/src/components/post-publish-panel/maybe-upload-media.js +++ b/packages/editor/src/components/post-publish-panel/maybe-upload-media.js @@ -14,11 +14,6 @@ import { store as blockEditorStore } from '@wordpress/block-editor'; import { useState } from '@wordpress/element'; import { isBlobURL } from '@wordpress/blob'; -/** - * Internal dependencies - */ -import { store as editorStore } from '../../store'; - function flattenBlocks( blocks ) { const result = []; @@ -65,9 +60,10 @@ function Image( block ) { export default function PostFormatPanel() { const [ isUploading, setIsUploading ] = useState( false ); + const [ isAnimating, setIsAnimating ] = useState( false ); const { editorBlocks, mediaUpload } = useSelect( ( select ) => ( { - editorBlocks: select( editorStore ).getEditorBlocks(), + editorBlocks: select( blockEditorStore ).getBlocks(), mediaUpload: select( blockEditorStore ).getSettings().mediaUpload, } ), [] @@ -102,27 +98,26 @@ export default function PostFormatPanel() { : image.attributes.url + '?' ) .then( ( response ) => response.blob() ) - .then( - ( blob ) => - new Promise( ( resolve, reject ) => { - mediaUpload( { - filesList: [ blob ], - onFileChange: ( [ media ] ) => { - if ( isBlobURL( media.url ) ) { - return; - } + .then( ( blob ) => + new Promise( ( resolve, reject ) => { + mediaUpload( { + filesList: [ blob ], + onFileChange: ( [ media ] ) => { + if ( isBlobURL( media.url ) ) { + return; + } - updateBlockAttributes( image.clientId, { - id: media.id, - url: media.url, - } ); - resolve(); - }, - onError() { - reject(); - }, - } ); - } ) + updateBlockAttributes( image.clientId, { + id: media.id, + url: media.url, + } ); + resolve(); + }, + onError() { + reject(); + }, + } ); + } ).then( () => setIsAnimating( true ) ) ) ) ).finally( () => { @@ -144,12 +139,14 @@ export default function PostFormatPanel() { gap: '8px', } } > - <AnimatePresence> + <AnimatePresence + onExitComplete={ () => setIsAnimating( false ) } + > { externalImages.map( ( image ) => { return <Image key={ image.clientId } { ...image } />; } ) } </AnimatePresence> - { isUploading ? ( + { isUploading || isAnimating ? ( <Spinner /> ) : ( <Button variant="primary" onClick={ uploadImages }> From 57c9c69afbd2e295719b7f201b821da7fe5729fb Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Tue, 27 Aug 2024 11:29:14 +0200 Subject: [PATCH 0552/1908] Block Bindings: Refactor utils file. (#64740) * Refactor block binding utils * Add security checks Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- .../block-editor/src/utils/block-bindings.js | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/packages/block-editor/src/utils/block-bindings.js b/packages/block-editor/src/utils/block-bindings.js index 4ba6e1a362958c..b3daf4f4b36b43 100644 --- a/packages/block-editor/src/utils/block-bindings.js +++ b/packages/block-editor/src/utils/block-bindings.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { useDispatch, useSelect } from '@wordpress/data'; +import { useDispatch, useRegistry } from '@wordpress/data'; /** * Internal dependencies @@ -9,10 +9,14 @@ import { useDispatch, useSelect } from '@wordpress/data'; import { store as blockEditorStore } from '../store'; import { useBlockEditContext } from '../components/block-edit'; +function isObjectEmpty( object ) { + return ! object || Object.keys( object ).length === 0; +} + export function useBlockBindingsUtils() { const { clientId } = useBlockEditContext(); const { updateBlockAttributes } = useDispatch( blockEditorStore ); - const { getBlockAttributes } = useSelect( blockEditorStore ); + const { getBlockAttributes } = useRegistry().select( blockEditorStore ); /** * Updates the value of the bindings connected to block attributes. @@ -44,8 +48,10 @@ export function useBlockBindingsUtils() { * ``` */ const updateBlockBindings = ( bindings ) => { - const { metadata } = getBlockAttributes( clientId ); - const newBindings = { ...metadata?.bindings }; + const { metadata: { bindings: currentBindings, ...metadata } = {} } = + getBlockAttributes( clientId ); + const newBindings = { ...currentBindings }; + Object.entries( bindings ).forEach( ( [ attribute, binding ] ) => { if ( ! binding && newBindings[ attribute ] ) { delete newBindings[ attribute ]; @@ -59,15 +65,12 @@ export function useBlockBindingsUtils() { bindings: newBindings, }; - if ( Object.keys( newMetadata.bindings ).length === 0 ) { + if ( isObjectEmpty( newMetadata.bindings ) ) { delete newMetadata.bindings; } updateBlockAttributes( clientId, { - metadata: - Object.keys( newMetadata ).length === 0 - ? undefined - : newMetadata, + metadata: isObjectEmpty( newMetadata ) ? undefined : newMetadata, } ); }; @@ -83,14 +86,10 @@ export function useBlockBindingsUtils() { * ``` */ const removeAllBlockBindings = () => { - const { metadata } = getBlockAttributes( clientId ); - const newMetadata = { ...metadata }; - delete newMetadata.bindings; + const { metadata: { bindings, ...metadata } = {} } = + getBlockAttributes( clientId ); updateBlockAttributes( clientId, { - metadata: - Object.keys( newMetadata ).length === 0 - ? undefined - : newMetadata, + metadata: isObjectEmpty( metadata ) ? undefined : metadata, } ); }; From 8f2555cd8e090fc781a8c57b5745ccea7c92a58b Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 28 Aug 2024 00:35:43 +0900 Subject: [PATCH 0553/1908] Add variants to InputControl prefix/suffix wrappers (#64824) * Add variants to InputControl prefix/suffix wrappers * Use smaller close icon * Add changelog * Update snapshot Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../test/__snapshots__/index.test.js.snap | 32 +++++++------- .../src/input-control/input-base.tsx | 18 ++------ .../input-control/input-prefix-wrapper.tsx | 12 ++++-- .../input-control/input-suffix-wrapper.tsx | 10 ++--- .../src/input-control/stories/index.story.tsx | 43 +++++++++++++------ .../styles/input-control-styles.tsx | 34 ++++++++++++++- .../components/src/input-control/types.ts | 29 ++++++++++--- 8 files changed, 119 insertions(+), 60 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 693fcf71db183f..8c676c3334465c 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -20,6 +20,7 @@ - `TabPanel`: Remove radius applied to panel focus style ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). - `Tabs`: Remove radius applied to panel focus style ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). - `UnitControl`: Update unit select styles ([#64712](https://github.com/WordPress/gutenberg/pull/64712)). +- `InputControl`: Add variants to prefix/suffix wrappers ([#64824](https://github.com/WordPress/gutenberg/pull/64824)). - `Navigator`: remove location history, simplify internal logic ([#64675](https://github.com/WordPress/gutenberg/pull/64675)). - Decrease horizontal padding from 16px to 12px on the following components, when in the 40px default size ([#64708](https://github.com/WordPress/gutenberg/pull/64708)). - `AnglePickerControl` diff --git a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap index cb6fffb5aeff03..bd2c26d641fe72 100644 --- a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap +++ b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap @@ -45,7 +45,7 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = ` min-height: 0; } -.emotion-6:focus-within:not( :has( :is( .em5sgkm7, .emotion-19 ):focus-within ) ) .emotion-26 { +.emotion-6:focus-within:not( :has( :is( .em5sgkm8, .emotion-19 ):focus-within ) ) .emotion-26 { border-color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9)); box-shadow: 0 0 0 0.5px var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9)); outline: 2px solid transparent; @@ -157,8 +157,8 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = ` } .emotion-21 { - margin-bottom: 0; - padding-right: 8px; + -webkit-padding-end: 8px; + padding-inline-end: 8px; position: absolute; pointer-events: none; right: 0; @@ -249,7 +249,7 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = ` class="components-input-control__suffix emotion-18 emotion-19" > <div - class="components-spacer components-input-control-suffix-wrapper emotion-20 emotion-21 emotion-7" + class="components-input-control-suffix-wrapper emotion-20 emotion-21 emotion-22" data-wp-c16t="true" data-wp-component="InputControlSuffixWrapper" > @@ -327,7 +327,7 @@ exports[`DimensionControl rendering renders with defaults 1`] = ` min-height: 0; } -.emotion-6:focus-within:not( :has( :is( .em5sgkm7, .emotion-19 ):focus-within ) ) .emotion-26 { +.emotion-6:focus-within:not( :has( :is( .em5sgkm8, .emotion-19 ):focus-within ) ) .emotion-26 { border-color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9)); box-shadow: 0 0 0 0.5px var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9)); outline: 2px solid transparent; @@ -439,8 +439,8 @@ exports[`DimensionControl rendering renders with defaults 1`] = ` } .emotion-21 { - margin-bottom: 0; - padding-right: 8px; + -webkit-padding-end: 8px; + padding-inline-end: 8px; position: absolute; pointer-events: none; right: 0; @@ -541,7 +541,7 @@ exports[`DimensionControl rendering renders with defaults 1`] = ` class="components-input-control__suffix emotion-18 emotion-19" > <div - class="components-spacer components-input-control-suffix-wrapper emotion-20 emotion-21 emotion-7" + class="components-input-control-suffix-wrapper emotion-20 emotion-21 emotion-22" data-wp-c16t="true" data-wp-component="InputControlSuffixWrapper" > @@ -619,7 +619,7 @@ exports[`DimensionControl rendering renders with icon and custom icon label 1`] min-height: 0; } -.emotion-6:focus-within:not( :has( :is( .em5sgkm7, .emotion-19 ):focus-within ) ) .emotion-26 { +.emotion-6:focus-within:not( :has( :is( .em5sgkm8, .emotion-19 ):focus-within ) ) .emotion-26 { border-color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9)); box-shadow: 0 0 0 0.5px var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9)); outline: 2px solid transparent; @@ -731,8 +731,8 @@ exports[`DimensionControl rendering renders with icon and custom icon label 1`] } .emotion-21 { - margin-bottom: 0; - padding-right: 8px; + -webkit-padding-end: 8px; + padding-inline-end: 8px; position: absolute; pointer-events: none; right: 0; @@ -845,7 +845,7 @@ exports[`DimensionControl rendering renders with icon and custom icon label 1`] class="components-input-control__suffix emotion-18 emotion-19" > <div - class="components-spacer components-input-control-suffix-wrapper emotion-20 emotion-21 emotion-7" + class="components-input-control-suffix-wrapper emotion-20 emotion-21 emotion-22" data-wp-c16t="true" data-wp-component="InputControlSuffixWrapper" > @@ -923,7 +923,7 @@ exports[`DimensionControl rendering renders with icon and default icon label 1`] min-height: 0; } -.emotion-6:focus-within:not( :has( :is( .em5sgkm7, .emotion-19 ):focus-within ) ) .emotion-26 { +.emotion-6:focus-within:not( :has( :is( .em5sgkm8, .emotion-19 ):focus-within ) ) .emotion-26 { border-color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9)); box-shadow: 0 0 0 0.5px var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9)); outline: 2px solid transparent; @@ -1035,8 +1035,8 @@ exports[`DimensionControl rendering renders with icon and default icon label 1`] } .emotion-21 { - margin-bottom: 0; - padding-right: 8px; + -webkit-padding-end: 8px; + padding-inline-end: 8px; position: absolute; pointer-events: none; right: 0; @@ -1149,7 +1149,7 @@ exports[`DimensionControl rendering renders with icon and default icon label 1`] class="components-input-control__suffix emotion-18 emotion-19" > <div - class="components-spacer components-input-control-suffix-wrapper emotion-20 emotion-21 emotion-7" + class="components-input-control-suffix-wrapper emotion-20 emotion-21 emotion-22" data-wp-c16t="true" data-wp-component="InputControlSuffixWrapper" > diff --git a/packages/components/src/input-control/input-base.tsx b/packages/components/src/input-control/input-base.tsx index f59c2a411e05a5..f1b8227563cfdc 100644 --- a/packages/components/src/input-control/input-base.tsx +++ b/packages/components/src/input-control/input-base.tsx @@ -14,13 +14,7 @@ import { useMemo } from '@wordpress/element'; */ import Backdrop from './backdrop'; import Label from './label'; -import { - Container, - Root, - Prefix, - Suffix, - getSizeConfig, -} from './styles/input-control-styles'; +import { Container, Root, Prefix, Suffix } from './styles/input-control-styles'; import type { InputBaseProps, LabelPosition } from './types'; import type { WordPressComponentProps } from '../context'; import { @@ -90,16 +84,12 @@ function InputBase( const id = useUniqueId( idProp ); const hideLabel = hideLabelFromVision || ! label; - const { paddingLeft, paddingRight } = getSizeConfig( { - inputSize: size, - __next40pxDefaultSize, - } ); const prefixSuffixContextValue = useMemo( () => { return { - InputControlPrefixWrapper: { paddingLeft: `${ paddingLeft }px` }, - InputControlSuffixWrapper: { paddingRight: `${ paddingRight }px` }, + InputControlPrefixWrapper: { __next40pxDefaultSize, size }, + InputControlSuffixWrapper: { __next40pxDefaultSize, size }, }; - }, [ paddingLeft, paddingRight ] ); + }, [ __next40pxDefaultSize, size ] ); return ( // @ts-expect-error The `direction` prop from Flex (FlexDirection) conflicts with legacy SVGAttributes `direction` (string) that come from React intrinsic prop definitions. diff --git a/packages/components/src/input-control/input-prefix-wrapper.tsx b/packages/components/src/input-control/input-prefix-wrapper.tsx index 23d9e823da932d..c5232e4d9e6bbc 100644 --- a/packages/components/src/input-control/input-prefix-wrapper.tsx +++ b/packages/components/src/input-control/input-prefix-wrapper.tsx @@ -6,19 +6,23 @@ import type { ForwardedRef } from 'react'; /** * Internal dependencies */ -import { Spacer } from '../spacer'; import type { WordPressComponentProps } from '../context'; import { contextConnect, useContextSystem } from '../context'; -import type { InputControlPrefixWrapperProps } from './types'; +import type { PrefixSuffixWrapperProps } from './types'; +import { PrefixSuffixWrapper } from './styles/input-control-styles'; function UnconnectedInputControlPrefixWrapper( - props: WordPressComponentProps< InputControlPrefixWrapperProps, 'div' >, + props: WordPressComponentProps< PrefixSuffixWrapperProps, 'div' >, forwardedRef: ForwardedRef< any > ) { const derivedProps = useContextSystem( props, 'InputControlPrefixWrapper' ); return ( - <Spacer marginBottom={ 0 } { ...derivedProps } ref={ forwardedRef } /> + <PrefixSuffixWrapper + { ...derivedProps } + isPrefix + ref={ forwardedRef } + /> ); } diff --git a/packages/components/src/input-control/input-suffix-wrapper.tsx b/packages/components/src/input-control/input-suffix-wrapper.tsx index 1be352f562e369..fb3ec4c6ae9be9 100644 --- a/packages/components/src/input-control/input-suffix-wrapper.tsx +++ b/packages/components/src/input-control/input-suffix-wrapper.tsx @@ -6,20 +6,18 @@ import type { ForwardedRef } from 'react'; /** * Internal dependencies */ -import { Spacer } from '../spacer'; import type { WordPressComponentProps } from '../context'; import { contextConnect, useContextSystem } from '../context'; -import type { InputControlSuffixWrapperProps } from './types'; +import type { PrefixSuffixWrapperProps } from './types'; +import { PrefixSuffixWrapper } from './styles/input-control-styles'; function UnconnectedInputControlSuffixWrapper( - props: WordPressComponentProps< InputControlSuffixWrapperProps, 'div' >, + props: WordPressComponentProps< PrefixSuffixWrapperProps, 'div' >, forwardedRef: ForwardedRef< any > ) { const derivedProps = useContextSystem( props, 'InputControlSuffixWrapper' ); - return ( - <Spacer marginBottom={ 0 } { ...derivedProps } ref={ forwardedRef } /> - ); + return <PrefixSuffixWrapper { ...derivedProps } ref={ forwardedRef } />; } /** diff --git a/packages/components/src/input-control/stories/index.story.tsx b/packages/components/src/input-control/stories/index.story.tsx index 6067c467f9fe68..1a9290e8e856ea 100644 --- a/packages/components/src/input-control/stories/index.story.tsx +++ b/packages/components/src/input-control/stories/index.story.tsx @@ -5,7 +5,7 @@ import type { Meta, StoryFn } from '@storybook/react'; /** * WordPress dependencies */ -import { seen, unseen } from '@wordpress/icons'; +import { closeSmall, Icon, link, seen, unseen } from '@wordpress/icons'; import { useState } from '@wordpress/element'; /** * Internal dependencies @@ -75,6 +75,29 @@ WithSuffix.args = { suffix: <InputControlSuffixWrapper>%</InputControlSuffixWrapper>, }; +/** + * `<InputControlPrefixWrapper>` and `<InputControlSuffixWrapper>` have a `variant` prop that can be used to + * adjust the wrapper based on the prefix or suffix content. + * + * - `'default'`: Standard padding for text content. + * - `'icon'`: For icons. + * - `'control'`: For controls, like buttons or selects. + */ +export const WithIconOrControl = Template.bind( {} ); +WithIconOrControl.args = { + ...Default.args, + prefix: ( + <InputControlPrefixWrapper variant="icon"> + <Icon icon={ link } /> + </InputControlPrefixWrapper> + ), + suffix: ( + <InputControlSuffixWrapper variant="control"> + <Button icon={ closeSmall } size="small" label="Clear" /> + </InputControlSuffixWrapper> + ), +}; + export const WithSideLabel = Template.bind( {} ); WithSideLabel.args = { ...Default.args, @@ -95,17 +118,13 @@ export const ShowPassword: StoryFn< typeof InputControl > = ( args ) => { type={ visible ? 'text' : 'password' } label="Password" suffix={ - <InputControlSuffixWrapper> - <div style={ { display: 'flex' } }> - <Button - size="small" - icon={ visible ? unseen : seen } - onClick={ () => setVisible( ( value ) => ! value ) } - label={ - visible ? 'Hide password' : 'Show password' - } - /> - </div> + <InputControlSuffixWrapper variant="control"> + <Button + size="small" + icon={ visible ? unseen : seen } + onClick={ () => setVisible( ( value ) => ! value ) } + label={ visible ? 'Hide password' : 'Show password' } + /> </InputControlSuffixWrapper> } { ...args } diff --git a/packages/components/src/input-control/styles/input-control-styles.tsx b/packages/components/src/input-control/styles/input-control-styles.tsx index c2be294424f50a..39eea8fdb029a1 100644 --- a/packages/components/src/input-control/styles/input-control-styles.tsx +++ b/packages/components/src/input-control/styles/input-control-styles.tsx @@ -13,7 +13,7 @@ import type { WordPressComponentProps } from '../../context'; import { Flex, FlexItem } from '../../flex'; import { Text } from '../../text'; import { baseLabelTypography, COLORS, CONFIG, rtl } from '../../utils'; -import type { LabelPosition, Size } from '../types'; +import type { LabelPosition, Size, PrefixSuffixWrapperProps } from '../types'; type ContainerProps = { disabled?: boolean; @@ -318,3 +318,35 @@ export const Label = ( export const LabelWrapper = styled( FlexItem )` max-width: calc( 100% - 10px ); `; + +const prefixSuffixWrapperStyles = ( { + variant = 'default', + size, + __next40pxDefaultSize, + isPrefix, +}: PrefixSuffixWrapperProps & { isPrefix?: boolean } ) => { + const { paddingLeft: padding } = getSizeConfig( { + inputSize: size, + __next40pxDefaultSize, + } ); + + const paddingProperty = isPrefix + ? 'paddingInlineStart' + : 'paddingInlineEnd'; + + if ( variant === 'default' ) { + return css( { + [ paddingProperty ]: padding, + } ); + } + + // If variant is 'icon' or 'control' + return css( { + display: 'flex', + [ paddingProperty ]: padding - 4, + } ); +}; + +export const PrefixSuffixWrapper = styled.div` + ${ prefixSuffixWrapperStyles } +`; diff --git a/packages/components/src/input-control/types.ts b/packages/components/src/input-control/types.ts index 7d7a8267424b88..13f078cd89cc1f 100644 --- a/packages/components/src/input-control/types.ts +++ b/packages/components/src/input-control/types.ts @@ -209,16 +209,31 @@ export interface InputControlLabelProps { size?: BaseProps[ 'size' ]; } -export type InputControlPrefixWrapperProps = { +export type PrefixSuffixWrapperProps = { /** - * The prefix to be inserted. + * The content to be inserted. */ children: ReactNode; -}; - -export type InputControlSuffixWrapperProps = { /** - * The suffix to be inserted. + * Internal prop used to control the padding size of the wrapper. + * + * @ignore */ - children: ReactNode; + size?: BaseProps[ 'size' ]; + /** + * Internal prop used to control the padding size of the wrapper. + * + * @ignore + */ + __next40pxDefaultSize?: BaseProps[ '__next40pxDefaultSize' ]; + /** + * Adjust the wrapper based on the prefix or suffix content. + * + * - `'default'`: Standard padding for text content. + * - `'icon'`: For icons. + * - `'control'`: For controls, like buttons or selects. + * + * @default 'default' + */ + variant?: 'default' | 'icon' | 'control'; }; From 601bc2b63ffe06c55f1bf18aea7152dd698efcf9 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 28 Aug 2024 01:10:45 +0900 Subject: [PATCH 0554/1908] SelectControl: Fix remaining 40px size violations (#64831) * Fix in Featured Image block * Fix in Legacy Widget block * Move lint rule Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .eslintrc.js | 17 ++++++++--------- .../post-featured-image/dimension-controls.js | 3 +-- .../legacy-widget/edit/widget-type-selector.js | 3 +-- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 03c4fd78385277..55fa288b79b995 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -327,6 +327,7 @@ module.exports = { 'LineHeightControl', 'NumberControl', 'RangeControl', + 'SelectControl', 'TextControl', 'ToggleGroupControl', ].map( ( componentName ) => ( { @@ -344,15 +345,13 @@ module.exports = { 'FormFileUpload should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', }, // Temporary rules until all existing components have the `__next40pxDefaultSize` prop. - ...[ 'SelectControl', 'UnitControl' ].map( - ( componentName ) => ( { - // Not strict. Allows pre-existing __next40pxDefaultSize={ false } usage until they are all manually updated. - selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"])):not(:has(JSXAttribute[name.name="size"]))`, - message: - componentName + - ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', - } ) - ), + ...[ 'UnitControl' ].map( ( componentName ) => ( { + // Not strict. Allows pre-existing __next40pxDefaultSize={ false } usage until they are all manually updated. + selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"])):not(:has(JSXAttribute[name.name="size"]))`, + message: + componentName + + ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', + } ) ), ], }, }, diff --git a/packages/block-library/src/post-featured-image/dimension-controls.js b/packages/block-library/src/post-featured-image/dimension-controls.js index b31b68b7811976..5a3e40a126bf8d 100644 --- a/packages/block-library/src/post-featured-image/dimension-controls.js +++ b/packages/block-library/src/post-featured-image/dimension-controls.js @@ -236,8 +236,7 @@ const DimensionControls = ( { panelId={ clientId } > <SelectControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Resolution' ) } value={ sizeSlug || DEFAULT_SIZE } diff --git a/packages/widgets/src/blocks/legacy-widget/edit/widget-type-selector.js b/packages/widgets/src/blocks/legacy-widget/edit/widget-type-selector.js index cc7c0830a319bf..d543b7b4b08d80 100644 --- a/packages/widgets/src/blocks/legacy-widget/edit/widget-type-selector.js +++ b/packages/widgets/src/blocks/legacy-widget/edit/widget-type-selector.js @@ -27,8 +27,7 @@ export default function WidgetTypeSelector( { selectedId, onSelect } ) { return ( <SelectControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize __nextHasNoMarginBottom label={ __( 'Select a legacy widget to display:' ) } value={ selectedId ?? '' } From 23db6dcaef148526d7de0487fc5f2b09c45f2b90 Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Tue, 27 Aug 2024 18:12:45 +0200 Subject: [PATCH 0555/1908] Add experiment for client-side media processing (#64650) Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: felixarntz <flixos90@git.wordpress.org> Co-authored-by: spacedmonkey <spacedmonkey@git.wordpress.org> Co-authored-by: TimothyBJacobs <timothyblynjacobs@git.wordpress.org> Co-authored-by: adamsilverstein <adamsilverstein@git.wordpress.org> --- lib/experimental/editor-settings.php | 3 + ...-gutenberg-rest-attachments-controller.php | 367 ++++++++++++++++++ lib/experimental/media/load.php | 347 +++++++++++++++++ lib/experiments-page.php | 12 + lib/load.php | 5 + phpunit/bootstrap.php | 1 + ...nberg-rest-attachments-controller-test.php | 314 +++++++++++++++ .../media/media-processing-test.php | 197 ++++++++++ 8 files changed, 1246 insertions(+) create mode 100644 lib/experimental/media/class-gutenberg-rest-attachments-controller.php create mode 100644 lib/experimental/media/load.php create mode 100644 phpunit/experimental/media/class-gutenberg-rest-attachments-controller-test.php create mode 100644 phpunit/experimental/media/media-processing-test.php diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index c34984baa0a619..c6bd99a18bf4c7 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -37,6 +37,9 @@ function gutenberg_enable_experiments() { if ( $gutenberg_experiments && array_key_exists( 'gutenberg-block-bindings-ui', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalBlockBindingsUI = true', 'before' ); } + if ( $gutenberg_experiments && array_key_exists( 'gutenberg-media-processing', $gutenberg_experiments ) ) { + wp_add_inline_script( 'wp-block-editor', 'window.__experimentalMediaProcessing = true', 'before' ); + } } add_action( 'admin_init', 'gutenberg_enable_experiments' ); diff --git a/lib/experimental/media/class-gutenberg-rest-attachments-controller.php b/lib/experimental/media/class-gutenberg-rest-attachments-controller.php new file mode 100644 index 00000000000000..71bf7b7a958351 --- /dev/null +++ b/lib/experimental/media/class-gutenberg-rest-attachments-controller.php @@ -0,0 +1,367 @@ +<?php +/** + * Class Gutenberg_REST_Attachments_Controller. + * + * @package MediaExperiments + */ + +/** + * Class Gutenberg_REST_Attachments_Controller. + */ +class Gutenberg_REST_Attachments_Controller extends WP_REST_Attachments_Controller { + /** + * Registers the routes for attachments. + * + * @see register_rest_route() + */ + public function register_routes(): void { + parent::register_routes(); + + $valid_image_sizes = array_keys( wp_get_registered_image_subsizes() ); + + // Special case to set 'original_image' in attachment metadata. + $valid_image_sizes[] = 'original'; + // Used for PDF thumbnails. + $valid_image_sizes[] = 'full'; + + register_rest_route( + $this->namespace, + '/' . $this->rest_base . '/(?P<id>[\d]+)/sideload', + array( + array( + 'methods' => WP_REST_Server::CREATABLE, + 'callback' => array( $this, 'sideload_item' ), + 'permission_callback' => array( $this, 'sideload_item_permissions_check' ), + 'args' => array( + 'id' => array( + 'description' => __( 'Unique identifier for the attachment.', 'gutenberg' ), + 'type' => 'integer', + ), + 'image_size' => array( + 'description' => __( 'Image size.', 'gutenberg' ), + 'type' => 'string', + 'enum' => $valid_image_sizes, + 'required' => true, + ), + ), + ), + 'allow_batch' => $this->allow_batch, + 'schema' => array( $this, 'get_public_item_schema' ), + ) + ); + } + + /** + * Retrieves an array of endpoint arguments from the item schema for the controller. + * + * @param string $method Optional. HTTP method of the request. The arguments for `CREATABLE` requests are + * checked for required values and may fall-back to a given default, this is not done + * on `EDITABLE` requests. Default WP_REST_Server::CREATABLE. + * @return array Endpoint arguments. + */ + public function get_endpoint_args_for_item_schema( $method = WP_REST_Server::CREATABLE ) { + $args = rest_get_endpoint_args_for_schema( $this->get_item_schema(), $method ); + + if ( WP_REST_Server::CREATABLE === $method ) { + $args['generate_sub_sizes'] = array( + 'type' => 'boolean', + 'default' => true, + 'description' => __( 'Whether to generate image sub sizes.', 'gutenberg' ), + ); + $args['convert_format'] = array( + 'type' => 'boolean', + 'default' => true, + 'description' => __( 'Whether to convert image formats.', 'gutenberg' ), + ); + } + + return $args; + } + + /** + * Prepares a single attachment output for response. + * + * Ensures 'missing_image_sizes' is set for PDFs and not just images. + * + * @param WP_Post $item Attachment object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response( $item, $request ): WP_REST_Response { + $response = parent::prepare_item_for_response( $item, $request ); + + $data = $response->get_data(); + + // Handle missing image sizes for PDFs. + + $fields = $this->get_fields_for_response( $request ); + + if ( + rest_is_field_included( 'missing_image_sizes', $fields ) && + empty( $data['missing_image_sizes'] ) + ) { + $mime_type = get_post_mime_type( $item ); + + if ( 'application/pdf' === $mime_type ) { + $metadata = wp_get_attachment_metadata( $item->ID, true ); + + if ( ! is_array( $metadata ) ) { + $metadata = array(); + } + + $metadata['sizes'] = $metadata['sizes'] ?? array(); + + $fallback_sizes = array( + 'thumbnail', + 'medium', + 'large', + ); + + // The filter might have been added by ::create_item(). + remove_filter( 'fallback_intermediate_image_sizes', '__return_empty_array', 100 ); + + /** This filter is documented in wp-admin/includes/image.php */ + $fallback_sizes = apply_filters( 'fallback_intermediate_image_sizes', $fallback_sizes, $metadata ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound + + $registered_sizes = wp_get_registered_image_subsizes(); + $merged_sizes = array_keys( array_intersect_key( $registered_sizes, array_flip( $fallback_sizes ) ) ); + + $missing_image_sizes = array_diff( $merged_sizes, array_keys( $metadata['sizes'] ) ); + $data['missing_image_sizes'] = $missing_image_sizes; + } + } + + $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; + $data = $this->add_additional_fields_to_object( $data, $request ); + $data = $this->filter_response_by_context( $data, $context ); + + $links = $response->get_links(); + + $response = rest_ensure_response( $data ); + + foreach ( $links as $rel => $rel_links ) { + foreach ( $rel_links as $link ) { + $response->add_link( $rel, $link['href'], $link['attributes'] ); + } + } + + return $response; + } + + /** + * Creates a single attachment. + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure. + */ + public function create_item( $request ) { + if ( ! $request['generate_sub_sizes'] ) { + add_filter( 'intermediate_image_sizes_advanced', '__return_empty_array', 100 ); + add_filter( 'fallback_intermediate_image_sizes', '__return_empty_array', 100 ); + + } + + if ( ! $request['convert_format'] ) { + add_filter( 'image_editor_output_format', '__return_empty_array', 100 ); + } + + $response = parent::create_item( $request ); + + remove_filter( 'intermediate_image_sizes_advanced', '__return_empty_array', 100 ); + remove_filter( 'fallback_intermediate_image_sizes', '__return_empty_array', 100 ); + remove_filter( 'image_editor_output_format', '__return_empty_array', 100 ); + + return $response; + } + + + /** + * Checks if a given request has access to sideload a file. + * + * Sideloading a file for an existing attachment + * requires both update and create permissions. + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise. + */ + public function sideload_item_permissions_check( $request ) { + return $this->edit_media_item_permissions_check( $request ); + } + + /** + * Filters {@see 'wp_unique_filename'} during sideloads. + * + * {@see wp_unique_filename()} will always add numeric suffix if the name looks like a sub-size to avoid conflicts. + * + * Adding this closure to the filter helps work around this safeguard. + * + * Example: when uploading myphoto.jpeg, WordPress normally creates myphoto-150x150.jpeg, + * and when uploading myphoto-150x150.jpeg, it will be renamed to myphoto-150x150-1.jpeg + * However, here it is desired not to add the suffix in order to maintain the same + * naming convention as if the file was uploaded regularly. + * + * @link https://github.com/WordPress/wordpress-develop/blob/30954f7ac0840cfdad464928021d7f380940c347/src/wp-includes/functions.php#L2576-L2582 + * + * @param string $filename Unique file name. + * @param string $ext File extension. Example: ".png". + * @param string $dir Directory path. + * @param callable|null $unique_filename_callback Callback function that generates the unique file name. + * @param string[] $alt_filenames Array of alternate file names that were checked for collisions. + * @param int|string $number The highest number that was used to make the file name unique + * or an empty string if unused. + * @return string Filtered file name. + */ + private function filter_wp_unique_filename( $filename, $ext, $dir, $unique_filename_callback, $alt_filenames, $number, $attachment_filename ) { + if ( empty( $number ) || ! $attachment_filename ) { + return $filename; + } + + $ext = pathinfo( $filename, PATHINFO_EXTENSION ); + $name = pathinfo( $filename, PATHINFO_FILENAME ); + $orig_name = pathinfo( $attachment_filename, PATHINFO_FILENAME ); + + if ( ! $ext || ! $name ) { + return $filename; + } + + $matches = array(); + if ( preg_match( '/(.*)(-\d+x\d+)-' . $number . '$/', $name, $matches ) ) { + $filename_without_suffix = $matches[1] . $matches[2] . ".$ext"; + if ( $matches[1] === $orig_name && ! file_exists( "$dir/$filename_without_suffix" ) ) { + return $filename_without_suffix; + } + } + + return $filename; + } + + /** + * Side-loads a media file without creating an attachment. + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure. + */ + public function sideload_item( WP_REST_Request $request ) { + $attachment_id = $request['id']; + + $post = $this->get_post( $attachment_id ); + + if ( is_wp_error( $post ) ) { + return $post; + } + + if ( + ! wp_attachment_is_image( $post ) && + ! wp_attachment_is( 'pdf', $post ) + ) { + return new WP_Error( + 'rest_post_invalid_id', + __( 'Invalid post ID, only images and PDFs can be sideloaded.', 'gutenberg' ), + array( 'status' => 400 ) + ); + } + + if ( ! $request['convert_format'] ) { + // Prevent image conversion as that is done client-side. + add_filter( 'image_editor_output_format', '__return_empty_array', 100 ); + } + + // Get the file via $_FILES or raw data. + $files = $request->get_file_params(); + $headers = $request->get_headers(); + + /* + * wp_unique_filename() will always add numeric suffix if the name looks like a sub-size to avoid conflicts. + * See https://github.com/WordPress/wordpress-develop/blob/30954f7ac0840cfdad464928021d7f380940c347/src/wp-includes/functions.php#L2576-L2582 + * With the following filter we can work around this safeguard. + */ + + $attachment_filename = get_attached_file( $attachment_id, true ); + $attachment_filename = $attachment_filename ? wp_basename( $attachment_filename ) : null; + + /** + * @param string $filename Unique file name. + * @param string $ext File extension. Example: ".png". + * @param string $dir Directory path. + * @param callable|null $unique_filename_callback Callback function that generates the unique file name. + * @param string[] $alt_filenames Array of alternate file names that were checked for collisions. + * @param int|string $number The highest number that was used to make the file name unique + * or an empty string if unused. + * @return string Filtered file name. + */ + $filter_filename = function ( $filename, $ext, $dir, $unique_filename_callback, $alt_filenames, $number ) use ( $attachment_filename ) { + return $this->filter_wp_unique_filename( $filename, $ext, $dir, $unique_filename_callback, $alt_filenames, $number, $attachment_filename ); + }; + + add_filter( 'wp_unique_filename', $filter_filename, 10, 6 ); + + $parent_post = get_post_parent( $attachment_id ); + + $time = null; + + // Matches logic in media_handle_upload(). + // The post date doesn't usually matter for pages, so don't backdate this upload. + if ( $parent_post && 'page' !== $parent_post->post_type && substr( $parent_post->post_date, 0, 4 ) > 0 ) { + $time = $parent_post->post_date; + } + + if ( ! empty( $files ) ) { + $file = $this->upload_from_file( $files, $headers, $time ); + } else { + $file = $this->upload_from_data( $request->get_body(), $headers, $time ); + } + + remove_filter( 'wp_unique_filename', $filter_filename ); + remove_filter( 'image_editor_output_format', '__return_empty_array', 100 ); + + if ( is_wp_error( $file ) ) { + return $file; + } + + $type = $file['type']; + $path = $file['file']; + + $image_size = $request['image_size']; + + $metadata = wp_get_attachment_metadata( $attachment_id, true ); + + if ( ! $metadata ) { + $metadata = array(); + } + + if ( 'original' === $image_size ) { + $metadata['original_image'] = wp_basename( $path ); + } else { + $metadata['sizes'] = $metadata['sizes'] ?? array(); + + $size = wp_getimagesize( $path ); + + $metadata['sizes'][ $image_size ] = array( + 'width' => $size ? $size[0] : 0, + 'height' => $size ? $size[1] : 0, + 'file' => wp_basename( $path ), + 'mime-type' => $type, + 'filesize' => wp_filesize( $path ), + ); + } + + wp_update_attachment_metadata( $attachment_id, $metadata ); + + $response_request = new WP_REST_Request( + WP_REST_Server::READABLE, + rest_get_route_for_post( $attachment_id ) + ); + + $response_request['context'] = 'edit'; + + if ( isset( $request['_fields'] ) ) { + $response_request['_fields'] = $request['_fields']; + } + + $response = $this->prepare_item_for_response( get_post( $attachment_id ), $response_request ); + + $response->header( 'Location', rest_url( rest_get_route_for_post( $attachment_id ) ) ); + + return $response; + } +} diff --git a/lib/experimental/media/load.php b/lib/experimental/media/load.php new file mode 100644 index 00000000000000..5cb16d84e1d8d9 --- /dev/null +++ b/lib/experimental/media/load.php @@ -0,0 +1,347 @@ +<?php +/** + * Adds media-related experimental functionality. + * + * @package gutenberg + */ + +/** + * Returns a list of all available image sizes. + * + * @return array Existing image sizes. + */ +function gutenberg_get_all_image_sizes(): array { + $sizes = wp_get_registered_image_subsizes(); + + foreach ( $sizes as $name => &$size ) { + $size['height'] = (int) $size['height']; + $size['width'] = (int) $size['width']; + $size['name'] = $name; + } + unset( $size ); + + return $sizes; +} + +/** + * Returns the default output format mapping for the supported image formats. + * + * @return array<string,string> Map of input formats to output formats. + */ +function gutenberg_get_default_image_output_formats() { + $input_formats = array( + 'image/jpeg', + 'image/png', + 'image/gif', + 'image/webp', + 'image/avif', + 'image/heic', + ); + + $output_formats = array(); + + foreach ( $input_formats as $mime_type ) { + /** This filter is documented in wp-includes/media.php */ + $output_formats = apply_filters( + 'image_editor_output_format', // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound + $output_formats, + '', + $mime_type + ); + } + + return $output_formats; +} + +/** + * Filters the REST API root index data to add custom settings. + * + * @param WP_REST_Response $response Response data. + */ +function gutenberg_media_processing_filter_rest_index( WP_REST_Response $response ) { + /** This filter is documented in wp-admin/includes/images.php */ + $image_size_threshold = (int) apply_filters( 'big_image_size_threshold', 2560, array( 0, 0 ), '', 0 ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound + + $default_image_output_formats = gutenberg_get_default_image_output_formats(); + + /** This filter is documented in wp-includes/class-wp-image-editor-imagick.php */ + $jpeg_interlaced = (bool) apply_filters( 'image_save_progressive', false, 'image/jpeg' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound + /** This filter is documented in wp-includes/class-wp-image-editor-imagick.php */ + $png_interlaced = (bool) apply_filters( 'image_save_progressive', false, 'image/png' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound + /** This filter is documented in wp-includes/class-wp-image-editor-imagick.php */ + $gif_interlaced = (bool) apply_filters( 'image_save_progressive', false, 'image/gif' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound + + if ( current_user_can( 'upload_files' ) ) { + $response->data['image_sizes'] = gutenberg_get_all_image_sizes(); + $response->data['image_size_threshold'] = $image_size_threshold; + $response->data['image_output_formats'] = (object) $default_image_output_formats; + $response->data['jpeg_interlaced'] = $jpeg_interlaced; + $response->data['png_interlaced'] = $png_interlaced; + $response->data['gif_interlaced'] = $gif_interlaced; + } + + return $response; +} + +add_filter( 'rest_index', 'gutenberg_media_processing_filter_rest_index' ); + + +/** + * Overrides the REST controller for the attachment post type. + * + * @param array $args Array of arguments for registering a post type. + * See the register_post_type() function for accepted arguments. + * @param string $post_type Post type key. + */ +function gutenberg_filter_attachment_post_type_args( array $args, string $post_type ): array { + if ( 'attachment' === $post_type ) { + require_once __DIR__ . '/class-gutenberg-rest-attachments-controller.php'; + + $args['rest_controller_class'] = Gutenberg_REST_Attachments_Controller::class; + } + + return $args; +} + +add_filter( 'register_post_type_args', 'gutenberg_filter_attachment_post_type_args', 10, 2 ); + + +/** + * Registers additional REST fields for attachments. + */ +function gutenberg_media_processing_register_rest_fields(): void { + register_rest_field( + 'attachment', + 'filename', + array( + 'schema' => array( + 'description' => __( 'Original attachment file name', 'gutenberg' ), + 'type' => 'string', + 'context' => array( 'view', 'edit' ), + ), + 'get_callback' => 'gutenberg_rest_get_attachment_filename', + ) + ); + + register_rest_field( + 'attachment', + 'filesize', + array( + 'schema' => array( + 'description' => __( 'Attachment file size', 'gutenberg' ), + 'type' => 'number', + 'context' => array( 'view', 'edit' ), + ), + 'get_callback' => 'gutenberg_rest_get_attachment_filesize', + ) + ); +} + +add_action( 'rest_api_init', 'gutenberg_media_processing_register_rest_fields' ); + +/** + * Returns the attachment's original file name. + * + * @param array $post Post data. + * @return string|null Attachment file name. + */ +function gutenberg_rest_get_attachment_filename( array $post ): ?string { + $path = wp_get_original_image_path( $post['id'] ); + + if ( $path ) { + return basename( $path ); + } + + $path = get_attached_file( $post['id'] ); + + if ( $path ) { + return basename( $path ); + } + + return null; +} + +/** + * Returns the attachment's file size in bytes. + * + * @param array $post Post data. + * @return int|null Attachment file size. + */ +function gutenberg_rest_get_attachment_filesize( array $post ): ?int { + $attachment_id = $post['id']; + + $meta = wp_get_attachment_metadata( $attachment_id ); + + if ( isset( $meta['filesize'] ) ) { + return $meta['filesize']; + } + + $original_path = wp_get_original_image_path( $attachment_id ); + $attached_file = $original_path ? $original_path : get_attached_file( $attachment_id ); + + if ( is_string( $attached_file ) && file_exists( $attached_file ) ) { + return wp_filesize( $attached_file ); + } + + return null; +} + +/** + * Enables cross-origin isolation in the block editor. + * + * Required for enabling SharedArrayBuffer for WebAssembly-based + * media processing in the editor. + * + * @link https://web.dev/coop-coep/ + */ +function gutenberg_set_up_cross_origin_isolation() { + $screen = get_current_screen(); + + if ( ! $screen ) { + return; + } + + if ( ! $screen->is_block_editor() && 'site-editor' !== $screen->id && ! ( 'widgets' === $screen->id && wp_use_widgets_block_editor() ) ) { + return; + } + + $user_id = get_current_user_id(); + if ( ! $user_id ) { + return; + } + + // Cross-origin isolation is not needed if users can't upload files anyway. + if ( ! user_can( $user_id, 'upload_files' ) ) { + return; + } + + gutenberg_start_cross_origin_isolation_output_buffer(); +} + +add_action( 'load-post.php', 'gutenberg_set_up_cross_origin_isolation' ); +add_action( 'load-post-new.php', 'gutenberg_set_up_cross_origin_isolation' ); +add_action( 'load-site-editor.php', 'gutenberg_set_up_cross_origin_isolation' ); +add_action( 'load-widgets.php', 'gutenberg_set_up_cross_origin_isolation' ); + +/** + * Sends headers for cross-origin isolation. + * + * Uses an output buffer to add crossorigin="anonymous" where needed. + * + * @link https://web.dev/coop-coep/ + */ +function gutenberg_start_cross_origin_isolation_output_buffer(): void { + global $is_safari; + + $coep = $is_safari ? 'require-corp' : 'credentialless'; + + ob_start( + function ( string $output, ?int $phase ) use ( $coep ): string { + // Only send the header when the buffer is not being cleaned. + if ( ( $phase & PHP_OUTPUT_HANDLER_CLEAN ) === 0 ) { + header( 'Cross-Origin-Opener-Policy: same-origin' ); + header( "Cross-Origin-Embedder-Policy: $coep" ); + + $output = gutenberg_add_crossorigin_attributes( $output ); + } + + return $output; + } + ); +} + +/** + * Adds crossorigin="anonymous" to relevant tags in the given HTML string. + * + * @param string $html HTML input. + * + * @return string Modified HTML. + */ +function gutenberg_add_crossorigin_attributes( string $html ): string { + $site_url = site_url(); + + $processor = new WP_HTML_Tag_Processor( $html ); + + // See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin. + $tags = array( + 'AUDIO' => 'src', + 'IMG' => 'src', + 'LINK' => 'href', + 'SCRIPT' => 'src', + 'VIDEO' => 'src', + 'SOURCE' => 'src', + ); + + $tag_names = array_keys( $tags ); + + while ( $processor->next_tag() ) { + $tag = $processor->get_tag(); + + if ( ! in_array( $tag, $tag_names, true ) ) { + continue; + } + + if ( 'AUDIO' === $tag || 'VIDEO' === $tag ) { + $processor->set_bookmark( 'audio-video-parent' ); + } + + $processor->set_bookmark( 'resume' ); + + $seeked = false; + + $crossorigin = $processor->get_attribute( 'crossorigin' ); + + $url = $processor->get_attribute( $tags[ $tag ] ); + + if ( is_string( $url ) && ! str_starts_with( $url, $site_url ) && ! str_starts_with( $url, '/' ) && ! is_string( $crossorigin ) ) { + if ( 'SOURCE' === $tag ) { + $seeked = $processor->seek( 'audio-video-parent' ); + + if ( $seeked ) { + $processor->set_attribute( 'crossorigin', 'anonymous' ); + } + } else { + $processor->set_attribute( 'crossorigin', 'anonymous' ); + } + + if ( $seeked ) { + $processor->seek( 'resume' ); + $processor->release_bookmark( 'audio-video-parent' ); + } + } + } + + return $processor->get_updated_html(); +} + +/** + * Overrides templates from wp_print_media_templates with custom ones. + * + * Adds `crossorigin` attribute to all tags that + * could have assets loaded from a different domain. + */ +function gutenberg_override_media_templates(): void { + remove_action( 'admin_footer', 'wp_print_media_templates' ); + add_action( + 'admin_footer', + static function (): void { + ob_start(); + wp_print_media_templates(); + $html = (string) ob_get_clean(); + + $tags = array( + 'audio', + 'img', + 'video', + ); + + foreach ( $tags as $tag ) { + $html = (string) str_replace( "<$tag", "<$tag crossorigin=\"anonymous\"", $html ); + } + + echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + } + ); +} + +add_action( 'wp_enqueue_media', 'gutenberg_override_media_templates' ); diff --git a/lib/experiments-page.php b/lib/experiments-page.php index fa95923061daff..f76dcdca7d18cb 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -187,6 +187,18 @@ function gutenberg_initialize_experiments_settings() { ) ); + add_settings_field( + 'gutenberg-media-processing', + __( 'Client-side media processing', 'gutenberg' ), + 'gutenberg_display_experiment_field', + 'gutenberg-experiments', + 'gutenberg_experiments_section', + array( + 'label' => __( 'Enable client-side media processing.', 'gutenberg' ), + 'id' => 'gutenberg-media-processing', + ) + ); + register_setting( 'gutenberg-experiments', 'gutenberg-experiments' diff --git a/lib/load.php b/lib/load.php index 2f2c168a5fc290..6ac2bd61f1de49 100644 --- a/lib/load.php +++ b/lib/load.php @@ -185,3 +185,8 @@ function gutenberg_is_experiment_enabled( $name ) { // Data views. require_once __DIR__ . '/experimental/data-views.php'; + +// Client-side media processing. +if ( gutenberg_is_experiment_enabled( 'gutenberg-media-processing' ) ) { + require_once __DIR__ . '/experimental/media/load.php'; +} diff --git a/phpunit/bootstrap.php b/phpunit/bootstrap.php index 55319a752b61e6..5d078193f0c3bf 100644 --- a/phpunit/bootstrap.php +++ b/phpunit/bootstrap.php @@ -96,6 +96,7 @@ function fail_if_died( $message ) { 'gutenberg-full-site-editing' => 1, 'gutenberg-form-blocks' => 1, 'gutenberg-block-experiments' => 1, + 'gutenberg-media-processing' => 1, ), ); diff --git a/phpunit/experimental/media/class-gutenberg-rest-attachments-controller-test.php b/phpunit/experimental/media/class-gutenberg-rest-attachments-controller-test.php new file mode 100644 index 00000000000000..56286f76ace836 --- /dev/null +++ b/phpunit/experimental/media/class-gutenberg-rest-attachments-controller-test.php @@ -0,0 +1,314 @@ +<?php + +/** + * @coversDefaultClass \Gutenberg_REST_Attachments_Controller + */ +class Gutenberg_REST_Attachments_Controller_Test extends WP_Test_REST_Post_Type_Controller_Testcase { + /** + * @var int Administrator ID. + */ + protected static $admin_id; + + public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { + self::$admin_id = $factory->user->create( + array( + 'role' => 'administrator', + ) + ); + } + + public function set_up() { + parent::set_up(); + + $this->remove_added_uploads(); + } + + public function tear_down() { + $this->remove_added_uploads(); + + parent::tear_down(); + } + + /** + * @covers ::register_routes + */ + public function test_register_routes() { + $routes = rest_get_server()->get_routes(); + $this->assertArrayHasKey( '/wp/v2/media', $routes ); + $this->assertCount( 2, $routes['/wp/v2/media'] ); + $this->assertArrayHasKey( '/wp/v2/media/(?P<id>[\d]+)', $routes ); + $this->assertCount( 3, $routes['/wp/v2/media/(?P<id>[\d]+)'] ); + $this->assertArrayHasKey( '/wp/v2/media/(?P<id>[\d]+)/sideload', $routes ); + $this->assertCount( 1, $routes['/wp/v2/media/(?P<id>[\d]+)/sideload'] ); + } + + public function test_get_items() { + $this->markTestSkipped( 'No need to implement' ); + } + + public function test_get_item() { + $this->markTestSkipped( 'No need to implement' ); + } + + public function test_update_item() { + $this->markTestSkipped( 'No need to implement' ); + } + + public function test_delete_item() { + $this->markTestSkipped( 'No need to implement' ); + } + + public function test_get_item_schema() { + $this->markTestSkipped( 'No need to implement' ); + } + + public function test_context_param() { + $this->markTestSkipped( 'No need to implement' ); + } + + /** + * Verifies that skipping sub-size generation works. + * + * @covers ::create_item + * @covers ::create_item_permissions_check + */ + public function test_create_item() { + wp_set_current_user( self::$admin_id ); + + $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' ); + $request->set_param( 'title', 'My title is very cool' ); + $request->set_param( 'caption', 'This is a better caption.' ); + $request->set_param( 'description', 'Without a description, my attachment is descriptionless.' ); + $request->set_param( 'alt_text', 'Alt text is stored outside post schema.' ); + $request->set_param( 'generate_sub_sizes', false ); + + $request->set_body( file_get_contents( DIR_TESTDATA . '/images/canola.jpg' ) ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + $this->assertSame( 201, $response->get_status() ); + $this->assertSame( 'image', $data['media_type'] ); + $this->assertArrayHasKey( 'missing_image_sizes', $data ); + $this->assertNotEmpty( $data['missing_image_sizes'] ); + } + + /** + * Verifies that skipping sub-size generation works. + * + * @covers ::create_item + * @covers ::create_item_permissions_check + */ + public function test_create_item_insert_additional_metadata() { + wp_set_current_user( self::$admin_id ); + + $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' ); + $request->set_param( 'title', 'My title is very cool' ); + $request->set_param( 'caption', 'This is a better caption.' ); + $request->set_param( 'description', 'Without a description, my attachment is descriptionless.' ); + $request->set_param( 'alt_text', 'Alt text is stored outside post schema.' ); + $request->set_param( 'generate_sub_sizes', false ); + + $request->set_body( file_get_contents( DIR_TESTDATA . '/images/canola.jpg' ) ); + $response = rest_get_server()->dispatch( $request ); + + remove_filter( 'wp_generate_attachment_metadata', '__return_empty_array', 1 ); + + $this->assertSame( 201, $response->get_status() ); + + $data = $response->get_data(); + + $this->assertArrayHasKey( 'media_details', $data ); + $this->assertArrayHasKey( 'image_meta', $data['media_details'] ); + } + + public function test_prepare_item() { + $this->markTestSkipped( 'No need to implement' ); + } + + /** + * @covers ::prepare_item_for_response + */ + public function test_prepare_item_lists_missing_image_sizes_for_pdfs() { + wp_set_current_user( self::$admin_id ); + + $attachment_id = self::factory()->attachment->create_object( + DIR_TESTDATA . '/images/test-alpha.pdf', + 0, + array( + 'post_mime_type' => 'application/pdf', + 'post_excerpt' => 'A sample caption', + ) + ); + + $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/media/%d', $attachment_id ) ); + $request->set_param( 'context', 'edit' ); + + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + $this->assertArrayHasKey( 'missing_image_sizes', $data ); + $this->assertNotEmpty( $data['missing_image_sizes'] ); + $this->assertArrayHasKey( 'filename', $data ); + $this->assertArrayHasKey( 'filesize', $data ); + } + + /** + * @covers ::sideload_item + * @covers ::sideload_item_permissions_check + */ + public function test_sideload_item() { + wp_set_current_user( self::$admin_id ); + + $attachment_id = self::factory()->attachment->create_object( + DIR_TESTDATA . '/images/canola.jpg', + 0, + array( + 'post_mime_type' => 'image/jpeg', + 'post_excerpt' => 'A sample caption', + ) + ); + + wp_update_attachment_metadata( + $attachment_id, + wp_generate_attachment_metadata( $attachment_id, DIR_TESTDATA . '/images/canola.jpg' ) + ); + + $request = new WP_REST_Request( 'POST', "/wp/v2/media/$attachment_id/sideload" ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=canola-777x777.jpg' ); + $request->set_param( 'image_size', 'medium' ); + + $request->set_body( file_get_contents( DIR_TESTDATA . '/images/canola.jpg' ) ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + $this->assertSame( 200, $response->get_status() ); + $this->assertSame( 'image', $data['media_type'] ); + $this->assertArrayHasKey( 'missing_image_sizes', $data ); + $this->assertEmpty( $data['missing_image_sizes'] ); + $this->assertArrayHasKey( 'media_details', $data ); + $this->assertArrayHasKey( 'sizes', $data['media_details'] ); + $this->assertArrayHasKey( 'medium', $data['media_details']['sizes'] ); + $this->assertArrayHasKey( 'file', $data['media_details']['sizes']['medium'] ); + $this->assertSame( 'canola-777x777.jpg', $data['media_details']['sizes']['medium']['file'] ); + } + + /** + * @covers ::sideload_item + * @covers ::sideload_item_permissions_check + */ + public function test_sideload_item_year_month_based_folders() { + if ( version_compare( get_bloginfo( 'version' ), '6.6-beta1', '<' ) ) { + $this->markTestSkipped( 'This test requires WordPress 6.6+' ); + } + + update_option( 'uploads_use_yearmonth_folders', 1 ); + + wp_set_current_user( self::$admin_id ); + + $published_post = self::factory()->post->create( + array( + 'post_status' => 'publish', + 'post_date' => '2017-02-14 00:00:00', + 'post_date_gmt' => '2017-02-14 00:00:00', + ) + ); + + $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=canola-year-month.jpg' ); + $request->set_param( 'post', $published_post ); + $request->set_param( 'generate_sub_sizes', false ); + + $request->set_body( file_get_contents( DIR_TESTDATA . '/images/canola.jpg' ) ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + $attachment_id = $data['id']; + + $request = new WP_REST_Request( 'POST', "/wp/v2/media/$attachment_id/sideload" ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=canola-year-month-777x777.jpg' ); + $request->set_param( 'image_size', 'medium' ); + + $request->set_body( file_get_contents( DIR_TESTDATA . '/images/canola.jpg' ) ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + update_option( 'uploads_use_yearmonth_folders', 0 ); + + $this->assertSame( 200, $response->get_status() ); + + $attachment = get_post( $data['id'] ); + + $this->assertSame( $attachment->post_parent, $data['post'] ); + $this->assertSame( $attachment->post_parent, $published_post ); + $this->assertSame( wp_get_attachment_url( $attachment->ID ), $data['source_url'] ); + $this->assertStringContainsString( '2017/02', $data['source_url'] ); + } + + /** + * @covers ::sideload_item + * @covers ::sideload_item_permissions_check + */ + public function test_sideload_item_year_month_based_folders_page_post_type() { + if ( version_compare( get_bloginfo( 'version' ), '6.6-beta1', '<' ) ) { + $this->markTestSkipped( 'This test requires WordPress 6.6+' ); + } + + update_option( 'uploads_use_yearmonth_folders', 1 ); + + wp_set_current_user( self::$admin_id ); + + $published_post = self::factory()->post->create( + array( + 'post_type' => 'page', + 'post_status' => 'publish', + 'post_date' => '2017-02-14 00:00:00', + 'post_date_gmt' => '2017-02-14 00:00:00', + ) + ); + + $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=canola-year-month-page.jpg' ); + $request->set_param( 'post', $published_post ); + $request->set_param( 'generate_sub_sizes', false ); + + $request->set_body( file_get_contents( DIR_TESTDATA . '/images/canola.jpg' ) ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + $attachment_id = $data['id']; + + $request = new WP_REST_Request( 'POST', "/wp/v2/media/$attachment_id/sideload" ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=canola-year-month-page-777x777.jpg' ); + $request->set_param( 'image_size', 'medium' ); + + $request->set_body( file_get_contents( DIR_TESTDATA . '/images/canola.jpg' ) ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + update_option( 'uploads_use_yearmonth_folders', 0 ); + + $time = current_time( 'mysql' ); + $y = substr( $time, 0, 4 ); + $m = substr( $time, 5, 2 ); + $subdir = "/$y/$m"; + + $this->assertSame( 200, $response->get_status() ); + + $attachment = get_post( $data['id'] ); + + $this->assertSame( $attachment->post_parent, $data['post'] ); + $this->assertSame( $attachment->post_parent, $published_post ); + $this->assertSame( wp_get_attachment_url( $attachment->ID ), $data['source_url'] ); + $this->assertStringNotContainsString( '2017/02', $data['source_url'] ); + $this->assertStringContainsString( $subdir, $data['source_url'] ); + } +} diff --git a/phpunit/experimental/media/media-processing-test.php b/phpunit/experimental/media/media-processing-test.php new file mode 100644 index 00000000000000..2717d2582879ff --- /dev/null +++ b/phpunit/experimental/media/media-processing-test.php @@ -0,0 +1,197 @@ +<?php + +/** + * Tests for experimental client-side media processing. + */ +class Media_Processing_Test extends WP_UnitTestCase { + /** + * @var int Administrator ID. + */ + protected static $admin_id; + + /** + * @var string Image file path. + */ + private static $image_file; + + public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { + self::$admin_id = $factory->user->create( + array( + 'role' => 'administrator', + ) + ); + } + + public function set_up() { + parent::set_up(); + + self::$image_file = get_temp_dir() . 'canola.jpg'; + if ( ! file_exists( self::$image_file ) ) { + copy( DIR_TESTDATA . '/images/canola.jpg', self::$image_file ); + } + } + + public function tear_down() { + $this->remove_added_uploads(); + + parent::tear_down(); + } + + /** + * @covers gutenberg_get_all_image_sizes + */ + public function test_get_all_image_sizes() { + $sizes = gutenberg_get_all_image_sizes(); + $this->assertNotEmpty( $sizes ); + foreach ( $sizes as $size ) { + $this->assertIsInt( $size['width'] ); + $this->assertIsInt( $size['height'] ); + $this->assertIsString( $size['name'] ); + } + } + + /** + * @covers gutenberg_filter_attachment_post_type_args + */ + public function test_filter_attachment_post_type_args() { + $post_type_object = get_post_type_object( 'attachment' ); + $this->assertInstanceOf( Gutenberg_REST_Attachments_Controller::class, $post_type_object->get_rest_controller() ); + + $this->assertSame( + array( 'rest_controller_class' => Gutenberg_REST_Attachments_Controller::class ), + gutenberg_filter_attachment_post_type_args( array(), 'attachment' ) + ); + $this->assertSame( + array(), + gutenberg_filter_attachment_post_type_args( array(), 'post' ) + ); + } + + /** + * @covers ::gutenberg_rest_get_attachment_filesize + */ + public function test_rest_get_attachment_filesize() { + $attachment_id = self::factory()->attachment->create_object( + self::$image_file, + 0, + array( + 'post_mime_type' => 'image/jpeg', + 'post_excerpt' => 'A sample caption', + ) + ); + + $this->assertSame( wp_filesize( self::$image_file ), gutenberg_rest_get_attachment_filesize( array( 'id' => $attachment_id ) ) ); + } + + /** + * @covers ::gutenberg_rest_get_attachment_filename + */ + public function test_rest_get_attachment_filename() { + $attachment_id = self::factory()->attachment->create_object( + self::$image_file, + 0, + array( + 'post_mime_type' => 'image/jpeg', + 'post_excerpt' => 'A sample caption', + ) + ); + + $this->assertSame( 'canola.jpg', gutenberg_rest_get_attachment_filename( array( 'id' => $attachment_id ) ) ); + } + + /** + * @covers ::gutenberg_media_processing_filter_rest_index + */ + public function test_get_rest_index_should_return_additional_settings() { + $server = new WP_REST_Server(); + + $request = new WP_REST_Request( 'GET', '/' ); + $index = $server->dispatch( $request ); + $data = $index->get_data(); + + $this->assertArrayNotHasKey( 'image_size_threshold', $data ); + $this->assertArrayNotHasKey( 'image_output_formats', $data ); + $this->assertArrayNotHasKey( 'jpeg_interlaced', $data ); + $this->assertArrayNotHasKey( 'png_interlaced', $data ); + $this->assertArrayNotHasKey( 'gif_interlaced', $data ); + $this->assertArrayNotHasKey( 'image_sizes', $data ); + } + + /** + * @covers ::gutenberg_media_processing_filter_rest_index + */ + public function test_get_rest_index_should_return_additional_settings_can_upload_files() { + wp_set_current_user( self::$admin_id ); + + $server = new WP_REST_Server(); + + $request = new WP_REST_Request( 'GET', '/' ); + $index = $server->dispatch( $request ); + $data = $index->get_data(); + + $this->assertArrayHasKey( 'image_size_threshold', $data ); + $this->assertArrayHasKey( 'image_output_formats', $data ); + $this->assertArrayHasKey( 'jpeg_interlaced', $data ); + $this->assertArrayHasKey( 'png_interlaced', $data ); + $this->assertArrayHasKey( 'gif_interlaced', $data ); + $this->assertArrayHasKey( 'image_sizes', $data ); + } + + /** + * @covers ::gutenberg_add_crossorigin_attributes + */ + public function test_add_crossorigin_attributes() { + $html = <<<HTML +<img src="https://www.someothersite.com/test1.jpg" /> +<img src="test2.jpg" /> +<audio><source src="https://www.someothersite.com/test1.mp3"></audio> +<audio src="https://www.someothersite.com/test1.mp3"></audio> +<audio src="/test2.mp3"></audio> +<video><source src="https://www.someothersite.com/test1.mp4"></video> +<video src="https://www.someothersite.com/test1.mp4"></video> +<video src="/test2.mp4"></video> +<script src="https://www.someothersite.com/test1.js"></script> +<script src="/test2.js"></script> +<link href="https://www.someothersite.com/test1.css"></link> +<link href="/test2.css"></link> +HTML; + + $expected = <<<HTML +<img crossorigin="anonymous" src="https://www.someothersite.com/test1.jpg" /> +<img crossorigin="anonymous" src="test2.jpg" /> +<audio crossorigin="anonymous"><source src="https://www.someothersite.com/test1.mp3"></audio> +<audio crossorigin="anonymous" src="https://www.someothersite.com/test1.mp3"></audio> +<audio src="/test2.mp3"></audio> +<video crossorigin="anonymous"><source src="https://www.someothersite.com/test1.mp4"></video> +<video crossorigin="anonymous" src="https://www.someothersite.com/test1.mp4"></video> +<video src="/test2.mp4"></video> +<script crossorigin="anonymous" src="https://www.someothersite.com/test1.js"></script> +<script src="/test2.js"></script> +<link crossorigin="anonymous" href="https://www.someothersite.com/test1.css"></link> +<link href="/test2.css"></link> +HTML; + + $actual = gutenberg_add_crossorigin_attributes( $html ); + + $this->assertSame( $expected, $actual ); + } + + /** + * @covers ::gutenberg_override_media_templates + */ + public function test_gutenberg_override_media_templates(): void { + if ( ! function_exists( '\wp_print_media_templates' ) ) { + require_once ABSPATH . WPINC . '/media-template.php'; + } + + gutenberg_override_media_templates(); + + ob_start(); + do_action( 'admin_footer' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound + $output = ob_get_clean(); + + $this->assertStringContainsString( '<audio crossorigin="anonymous"', $output ); + $this->assertStringContainsString( '<img crossorigin="anonymous"', $output ); + $this->assertStringContainsString( '<video crossorigin="anonymous"', $output ); + } +} From 7099e9c037caac3792b94668187a83038852fff2 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Tue, 27 Aug 2024 09:41:54 -0700 Subject: [PATCH 0556/1908] Add units to avoid console warning (#64810) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/edit-site/src/components/editor/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 96de3c60b89144..85119acab493d3 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -66,13 +66,13 @@ const toggleHomeIconVariants = { const siteIconVariants = { edit: { - clipPath: 'inset(0% round 0)', + clipPath: 'inset(0% round 0px)', }, hover: { clipPath: 'inset( 22% round 2px )', }, tap: { - clipPath: 'inset(0% round 0)', + clipPath: 'inset(0% round 0px)', }, }; From 5751e827c45ee808156805df19af1c8121287adc Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 28 Aug 2024 02:13:58 +0900 Subject: [PATCH 0557/1908] Button: Add lint rule for 40px size prop usage (#64835) * Fix in URLPopover story * Fix in Dataviews story * Fix in WithDispatch test * Add todo comments * Add lint rule Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .eslintrc.js | 2 +- .../downloadable-block-list-item/index.js | 2 ++ .../src/plugins/get-install-missing/index.js | 8 +++++++- .../get-install-missing/install-button.js | 2 ++ .../src/components/block-breadcrumb/index.js | 4 ++++ .../src/components/block-compare/block-view.js | 8 +++++++- .../block-edit/multiple-usage-warning.js | 4 ++++ .../block-list/block-invalid-warning.js | 2 ++ .../src/components/block-mover/button.js | 2 ++ .../src/components/block-mover/index.js | 2 ++ .../components/block-navigation/dropdown.js | 2 ++ .../block-pattern-setup/setup-toolbar.js | 15 ++++++++++++++- .../components/block-patterns-paging/index.js | 6 ++++++ .../components/block-quick-navigation/index.js | 2 ++ .../block-tools/block-selection-button.js | 4 ++++ .../components/block-variation-picker/index.js | 7 ++++++- .../block-variation-transforms/index.js | 2 ++ .../components/button-block-appender/index.js | 2 ++ .../components/colors-gradients/dropdown.js | 6 +++++- .../components/global-styles/color-panel.js | 6 +++++- .../components/global-styles/filters-panel.js | 6 +++++- .../global-styles/shadow-panel-components.js | 10 +++++++++- .../src/components/inserter-listbox/item.js | 10 +++++++++- .../pattern-explorer-sidebar.js | 2 ++ .../inserter/block-patterns-tab/index.js | 2 ++ .../inserter/media-tab/media-preview.js | 14 ++++++++++++-- .../components/inserter/media-tab/media-tab.js | 2 ++ .../src/components/inserter/quick-inserter.js | 2 ++ .../inspector-controls-tabs/index.js | 2 ++ .../inspector-popover-header/index.js | 4 ++++ .../src/components/link-control/index.js | 11 ++++++++++- .../components/link-control/settings-drawer.js | 2 ++ .../list-view/block-select-button.js | 2 ++ .../src/components/media-placeholder/index.js | 14 ++++++++++++++ .../components/skip-to-selected-block/index.js | 2 ++ .../src/components/tool-selector/index.js | 2 ++ .../src/components/url-input/button.js | 6 ++++++ .../src/components/url-input/index.js | 2 ++ .../url-popover/stories/index.story.js | 8 +++++++- packages/block-editor/src/hooks/layout.js | 2 ++ packages/block-editor/src/layouts/flex.js | 2 ++ .../src/comments/edit/comments-legacy.js | 2 ++ .../src/embed/embed-placeholder.js | 14 ++++++++++++-- packages/block-library/src/freeform/modal.js | 11 ++++++++++- packages/block-library/src/missing/edit.js | 8 +++++++- .../src/navigation-link/link-ui.js | 2 ++ .../edit/deleted-navigation-warning.js | 9 ++++++++- .../block-library/src/navigation/edit/index.js | 2 ++ .../edit/navigation-menu-delete-control.js | 2 ++ .../src/navigation/edit/placeholder/index.js | 2 ++ .../src/navigation/edit/responsive-wrapper.js | 4 ++++ .../src/page-list/convert-to-links-modal.js | 9 ++++++++- packages/block-library/src/page-list/edit.js | 2 ++ .../src/post-comments-form/form.js | 2 ++ .../src/post-featured-image/edit.js | 2 ++ .../query/edit/enhanced-pagination-modal.js | 7 ++++++- .../src/query/edit/query-placeholder.js | 4 ++++ packages/block-library/src/site-logo/edit.js | 4 ++++ packages/block-library/src/social-link/edit.js | 2 ++ .../src/template-part/edit/placeholder.js | 9 ++++++++- packages/block-library/src/video/edit.js | 12 ++++++++---- .../block-library/src/video/tracks-editor.js | 6 ++++++ .../src/components/error-boundary/index.js | 7 ++++++- .../src/components/inserter/index.js | 2 ++ .../src/components/welcome-guide/index.js | 2 ++ .../src/components/with-dispatch/test/index.js | 4 +++- .../components/dataviews/stories/fixtures.js | 14 +++++++++++--- .../src/dataforms-layouts/panel/index.tsx | 2 ++ .../back-button/fullscreen-mode-close.js | 2 ++ .../src/components/init-pattern-modal/index.js | 2 ++ .../preferences-modal/enable-custom-fields.js | 2 ++ .../add-custom-template-modal-content.js | 2 ++ .../src/components/add-new-template/index.js | 2 ++ .../editor-canvas-container/index.js | 2 ++ .../edit-site/src/components/editor/index.js | 2 ++ .../src/components/error-boundary/warning.js | 7 ++++++- .../font-library-modal/font-card.js | 2 ++ .../font-library-modal/font-collection.js | 2 ++ .../font-library-modal/installed-fonts.js | 4 ++++ .../font-library-modal/upload-fonts.js | 2 ++ .../src/components/global-styles/palette.js | 2 ++ .../screen-revisions/revisions-buttons.js | 2 ++ .../global-styles/shadows-edit-panel.js | 18 ++++++++++++++++-- .../src/components/page-patterns/fields.js | 2 ++ .../src/components/save-panel/index.js | 2 ++ .../src/components/sidebar-button/index.js | 2 ++ .../sidebar-dataviews/add-new-view.js | 4 ++++ .../edit-site/src/components/site-hub/index.js | 12 ++++++++++++ .../src/components/error-boundary/index.js | 7 ++++++- .../secondary-sidebar/inserter-sidebar.js | 2 ++ .../secondary-sidebar/list-view-sidebar.js | 2 ++ .../src/components/sidebar/widget-areas.js | 2 ++ .../src/components/block-manager/index.js | 2 ++ .../src/components/editor-history/redo.js | 2 ++ .../src/components/editor-history/undo.js | 2 ++ .../src/components/error-boundary/index.js | 7 ++++++- .../src/components/post-excerpt/panel.js | 2 ++ .../components/post-featured-image/index.js | 6 ++++++ .../editor/src/components/post-format/index.js | 2 ++ .../src/components/post-last-revision/index.js | 2 ++ .../src/components/post-locked-modal/index.js | 14 ++++++++++++-- .../src/components/post-publish-panel/index.js | 2 ++ .../maybe-post-format-panel.js | 2 ++ .../post-publish-panel/maybe-upload-media.js | 7 ++++++- .../hierarchical-term-selector.js | 2 ++ .../post-taxonomies/most-used-terms.js | 2 ++ .../components/post-template/classic-theme.js | 2 ++ .../editor/src/components/post-url/index.js | 2 ++ .../components/save-publish-panels/index.js | 4 ++++ .../components/start-template-options/index.js | 7 ++++++- .../src/components/table-of-contents/index.js | 2 ++ .../editor/src/components/text-editor/index.js | 2 ++ .../src/dataviews/actions/reset-post.tsx | 4 ++++ .../src/dataviews/actions/trash-post.tsx | 4 ++++ .../src/components/import-dropdown/index.js | 2 ++ .../src/components/import-form/index.js | 2 ++ packages/nux/src/components/dot-tip/index.js | 9 ++++++++- .../reusable-block-convert-button.js | 9 ++++++++- 118 files changed, 490 insertions(+), 42 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 55fa288b79b995..484387a285e78b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -345,7 +345,7 @@ module.exports = { 'FormFileUpload should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', }, // Temporary rules until all existing components have the `__next40pxDefaultSize` prop. - ...[ 'UnitControl' ].map( ( componentName ) => ( { + ...[ 'Button', 'UnitControl' ].map( ( componentName ) => ( { // Not strict. Allows pre-existing __next40pxDefaultSize={ false } usage until they are all manually updated. selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"])):not(:has(JSXAttribute[name.name="size"]))`, message: diff --git a/packages/block-directory/src/components/downloadable-block-list-item/index.js b/packages/block-directory/src/components/downloadable-block-list-item/index.js index b1ef34ccdba596..03e6e79d8928e9 100644 --- a/packages/block-directory/src/components/downloadable-block-list-item/index.js +++ b/packages/block-directory/src/components/downloadable-block-list-item/index.js @@ -96,6 +96,8 @@ function DownloadableBlockListItem( { composite, item, onClick } ) { <CompositeItem render={ <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } accessibleWhenDisabled type="button" role="option" diff --git a/packages/block-directory/src/plugins/get-install-missing/index.js b/packages/block-directory/src/plugins/get-install-missing/index.js index 58d6cdb1a188cb..8b192cbe8fdc49 100644 --- a/packages/block-directory/src/plugins/get-install-missing/index.js +++ b/packages/block-directory/src/plugins/get-install-missing/index.js @@ -100,7 +100,13 @@ const ModifiedWarning = ( { originalBlock, ...props } ) => { originalBlock.title || originalName ); actions.push( - <Button key="convert" onClick={ convertToHTML } variant="tertiary"> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + key="convert" + onClick={ convertToHTML } + variant="tertiary" + > { __( 'Keep as HTML' ) } </Button> ); diff --git a/packages/block-directory/src/plugins/get-install-missing/install-button.js b/packages/block-directory/src/plugins/get-install-missing/install-button.js index 9dcd45f67760f4..3b05b53a380b9a 100644 --- a/packages/block-directory/src/plugins/get-install-missing/install-button.js +++ b/packages/block-directory/src/plugins/get-install-missing/install-button.js @@ -22,6 +22,8 @@ export default function InstallButton( { attributes, block, clientId } ) { return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } onClick={ () => installBlockType( block ).then( ( success ) => { if ( success ) { diff --git a/packages/block-editor/src/components/block-breadcrumb/index.js b/packages/block-editor/src/components/block-breadcrumb/index.js index 8bd790c5c8fb21..8a70616d358d9e 100644 --- a/packages/block-editor/src/components/block-breadcrumb/index.js +++ b/packages/block-editor/src/components/block-breadcrumb/index.js @@ -66,6 +66,8 @@ function BlockBreadcrumb( { rootLabelText } ) { > { hasSelection && ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="block-editor-block-breadcrumb__button" variant="tertiary" onClick={ () => { @@ -94,6 +96,8 @@ function BlockBreadcrumb( { rootLabelText } ) { { parents.map( ( parentClientId ) => ( <li key={ parentClientId }> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="block-editor-block-breadcrumb__button" variant="tertiary" onClick={ () => selectBlock( parentClientId ) } diff --git a/packages/block-editor/src/components/block-compare/block-view.js b/packages/block-editor/src/components/block-compare/block-view.js index 3c4839931e10fe..55492fb2d76ae9 100644 --- a/packages/block-editor/src/components/block-compare/block-view.js +++ b/packages/block-editor/src/components/block-compare/block-view.js @@ -30,7 +30,13 @@ export default function BlockView( { </div> <div className="block-editor-block-compare__action"> - <Button variant="secondary" tabIndex="0" onClick={ action }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="secondary" + tabIndex="0" + onClick={ action } + > { actionText } </Button> </div> diff --git a/packages/block-editor/src/components/block-edit/multiple-usage-warning.js b/packages/block-editor/src/components/block-edit/multiple-usage-warning.js index 4acd4d1f349dd0..bff12342904537 100644 --- a/packages/block-editor/src/components/block-edit/multiple-usage-warning.js +++ b/packages/block-editor/src/components/block-edit/multiple-usage-warning.js @@ -24,6 +24,8 @@ export function MultipleUsageWarning( { <Warning actions={ [ <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } key="find-original" variant="secondary" onClick={ () => selectBlock( originalBlockClientId ) } @@ -31,6 +33,8 @@ export function MultipleUsageWarning( { { __( 'Find original' ) } </Button>, <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } key="remove" variant="secondary" onClick={ () => onReplace( [] ) } diff --git a/packages/block-editor/src/components/block-list/block-invalid-warning.js b/packages/block-editor/src/components/block-list/block-invalid-warning.js index a3ece994916a43..42ec5f9deb84d0 100644 --- a/packages/block-editor/src/components/block-list/block-invalid-warning.js +++ b/packages/block-editor/src/components/block-list/block-invalid-warning.js @@ -101,6 +101,8 @@ export default function BlockInvalidWarning( { clientId } ) { <Warning actions={ [ <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } key="recover" onClick={ convert.toRecoveredBlock } variant="primary" diff --git a/packages/block-editor/src/components/block-mover/button.js b/packages/block-editor/src/components/block-mover/button.js index 7e01ee4a359db9..98c0aff79eff38 100644 --- a/packages/block-editor/src/components/block-mover/button.js +++ b/packages/block-editor/src/components/block-mover/button.js @@ -129,6 +129,8 @@ const BlockMoverButton = forwardRef( return ( <> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } ref={ ref } className={ clsx( 'block-editor-block-mover-button', diff --git a/packages/block-editor/src/components/block-mover/index.js b/packages/block-editor/src/components/block-mover/index.js index 7aa273605bbe6b..1e846227c793bd 100644 --- a/packages/block-editor/src/components/block-mover/index.js +++ b/packages/block-editor/src/components/block-mover/index.js @@ -87,6 +87,8 @@ function BlockMover( { <BlockDraggable clientIds={ clientIds } fadeWhenDisabled> { ( draggableProps ) => ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ dragHandle } className="block-editor-block-mover__drag-handle" label={ __( 'Drag' ) } diff --git a/packages/block-editor/src/components/block-navigation/dropdown.js b/packages/block-editor/src/components/block-navigation/dropdown.js index e04589d002c539..035a38604b0293 100644 --- a/packages/block-editor/src/components/block-navigation/dropdown.js +++ b/packages/block-editor/src/components/block-navigation/dropdown.js @@ -27,6 +27,8 @@ function BlockNavigationDropdownToggle( { } ) { return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } { ...props } ref={ innerRef } icon={ listView } diff --git a/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js b/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js index df559194e5b78b..01272976adaafa 100644 --- a/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js +++ b/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js @@ -17,7 +17,12 @@ import { VIEWMODES } from './constants'; const Actions = ( { onBlockPatternSelect } ) => ( <div className="block-editor-block-pattern-setup__actions"> - <Button variant="primary" onClick={ onBlockPatternSelect }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="primary" + onClick={ onBlockPatternSelect } + > { __( 'Choose' ) } </Button> </div> @@ -31,6 +36,8 @@ const CarouselNavigation = ( { } ) => ( <div className="block-editor-block-pattern-setup__navigation"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ chevronLeft } label={ __( 'Previous pattern' ) } onClick={ handlePrevious } @@ -38,6 +45,8 @@ const CarouselNavigation = ( { accessibleWhenDisabled /> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ chevronRight } label={ __( 'Next pattern' ) } onClick={ handleNext } @@ -60,12 +69,16 @@ const SetupToolbar = ( { const displayControls = ( <div className="block-editor-block-pattern-setup__display-controls"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ stretchFullWidth } label={ __( 'Carousel view' ) } onClick={ () => setViewMode( VIEWMODES.carousel ) } isPressed={ isCarouselView } /> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ grid } label={ __( 'Grid view' ) } onClick={ () => setViewMode( VIEWMODES.grid ) } diff --git a/packages/block-editor/src/components/block-patterns-paging/index.js b/packages/block-editor/src/components/block-patterns-paging/index.js index 7ddbfc4702bf2f..ce1fa8b93df735 100644 --- a/packages/block-editor/src/components/block-patterns-paging/index.js +++ b/packages/block-editor/src/components/block-patterns-paging/index.js @@ -38,6 +38,8 @@ export default function Pagination( { className="block-editor-patterns__grid-pagination-previous" > <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="tertiary" onClick={ () => changePage( 1 ) } disabled={ currentPage === 1 } @@ -47,6 +49,8 @@ export default function Pagination( { <span>«</span> </Button> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="tertiary" onClick={ () => changePage( currentPage - 1 ) } disabled={ currentPage === 1 } @@ -70,6 +74,8 @@ export default function Pagination( { className="block-editor-patterns__grid-pagination-next" > <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="tertiary" onClick={ () => changePage( currentPage + 1 ) } disabled={ currentPage === numPages } diff --git a/packages/block-editor/src/components/block-quick-navigation/index.js b/packages/block-editor/src/components/block-quick-navigation/index.js index 63d0edbb868aa8..4f22c2a266722d 100644 --- a/packages/block-editor/src/components/block-quick-navigation/index.js +++ b/packages/block-editor/src/components/block-quick-navigation/index.js @@ -59,6 +59,8 @@ function BlockQuickNavigationItem( { clientId, onSelect } ) { return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } isPressed={ isSelected } onClick={ async () => { await selectBlock( clientId ); diff --git a/packages/block-editor/src/components/block-tools/block-selection-button.js b/packages/block-editor/src/components/block-tools/block-selection-button.js index 77d37634b87217..9c6c22181ef2ac 100644 --- a/packages/block-editor/src/components/block-tools/block-selection-button.js +++ b/packages/block-editor/src/components/block-tools/block-selection-button.js @@ -257,6 +257,8 @@ function BlockSelectionButton( { clientId, rootClientId }, ref ) { <BlockDraggable clientIds={ [ clientId ] }> { ( draggableProps ) => ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ dragHandle } className="block-selection-button_drag-handle" label={ dragHandleLabel } @@ -272,6 +274,8 @@ function BlockSelectionButton( { clientId, rootClientId }, ref ) { { editorMode === 'navigation' && ( <FlexItem> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } ref={ ref } onClick={ editorMode === 'navigation' diff --git a/packages/block-editor/src/components/block-variation-picker/index.js b/packages/block-editor/src/components/block-variation-picker/index.js index 2bba44d4bedfe6..ecdf8b23bec3fe 100644 --- a/packages/block-editor/src/components/block-variation-picker/index.js +++ b/packages/block-editor/src/components/block-variation-picker/index.js @@ -63,7 +63,12 @@ function BlockVariationPicker( { { /* eslint-enable jsx-a11y/no-redundant-roles */ } { allowSkip && ( <div className="block-editor-block-variation-picker__skip"> - <Button variant="link" onClick={ () => onSelect() }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="link" + onClick={ () => onSelect() } + > { __( 'Skip' ) } </Button> </div> diff --git a/packages/block-editor/src/components/block-variation-transforms/index.js b/packages/block-editor/src/components/block-variation-transforms/index.js index b7ecaad635e44c..97a3f980541842 100644 --- a/packages/block-editor/src/components/block-variation-transforms/index.js +++ b/packages/block-editor/src/components/block-variation-transforms/index.js @@ -35,6 +35,8 @@ function VariationsButtons( { </VisuallyHidden> { variations.map( ( variation ) => ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } key={ variation.name } icon={ <BlockIcon icon={ variation.icon } showColors /> } isPressed={ selectedValue === variation.name } 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 3ac1ef62e1e24a..fd349ad1daac07 100644 --- a/packages/block-editor/src/components/button-block-appender/index.js +++ b/packages/block-editor/src/components/button-block-appender/index.js @@ -51,6 +51,8 @@ function ButtonBlockAppender( let inserterButton = ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } ref={ ref } onFocus={ onFocus } tabIndex={ tabIndex } diff --git a/packages/block-editor/src/components/colors-gradients/dropdown.js b/packages/block-editor/src/components/colors-gradients/dropdown.js index 7033c2ebde48f4..d3cf59a2a5e6e6 100644 --- a/packages/block-editor/src/components/colors-gradients/dropdown.js +++ b/packages/block-editor/src/components/colors-gradients/dropdown.js @@ -88,7 +88,11 @@ const renderToggle = }; return ( - <Button { ...toggleProps }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + { ...toggleProps } + > <LabeledColorIndicator colorValue={ colorValue } label={ label } diff --git a/packages/block-editor/src/components/global-styles/color-panel.js b/packages/block-editor/src/components/global-styles/color-panel.js index 957d68edaf8492..15f06310176c70 100644 --- a/packages/block-editor/src/components/global-styles/color-panel.js +++ b/packages/block-editor/src/components/global-styles/color-panel.js @@ -239,7 +239,11 @@ function ColorPanelDropdown( { }; return ( - <Button { ...toggleProps }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + { ...toggleProps } + > <LabeledColorIndicators indicators={ indicators } label={ label } diff --git a/packages/block-editor/src/components/global-styles/filters-panel.js b/packages/block-editor/src/components/global-styles/filters-panel.js index 9eee1b3ff0ec75..de6e58b3334f13 100644 --- a/packages/block-editor/src/components/global-styles/filters-panel.js +++ b/packages/block-editor/src/components/global-styles/filters-panel.js @@ -189,7 +189,11 @@ export default function FiltersPanel( { return ( <ItemGroup isBordered isSeparated> - <Button { ...toggleProps }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + { ...toggleProps } + > <LabeledColorIndicator indicator={ duotone } label={ __( 'Duotone' ) } diff --git a/packages/block-editor/src/components/global-styles/shadow-panel-components.js b/packages/block-editor/src/components/global-styles/shadow-panel-components.js index a30e209027a2bf..e3a6c71adf8fc6 100644 --- a/packages/block-editor/src/components/global-styles/shadow-panel-components.js +++ b/packages/block-editor/src/components/global-styles/shadow-panel-components.js @@ -52,6 +52,8 @@ export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) { /> <div className="block-editor-global-styles__clear-shadow"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="tertiary" onClick={ () => onShadowChange( undefined ) } > @@ -99,6 +101,8 @@ export function ShadowIndicator( { type, label, isActive, onSelect, shadow } ) { } ) } render={ <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className={ clsx( 'block-editor-global-styles__shadow-indicator', { @@ -151,7 +155,11 @@ function renderShadowToggle() { }; return ( - <Button { ...toggleProps }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + { ...toggleProps } + > <HStack justify="flex-start"> <Icon className="block-editor-global-styles__toggle-icon" diff --git a/packages/block-editor/src/components/inserter-listbox/item.js b/packages/block-editor/src/components/inserter-listbox/item.js index 951eb86223ce8f..825c3fdfc353c6 100644 --- a/packages/block-editor/src/components/inserter-listbox/item.js +++ b/packages/block-editor/src/components/inserter-listbox/item.js @@ -42,7 +42,15 @@ function InserterListboxItem( if ( typeof children === 'function' ) { return children( propsWithTabIndex ); } - return <Button { ...propsWithTabIndex }>{ children }</Button>; + return ( + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + { ...propsWithTabIndex } + > + { children } + </Button> + ); } } /> ); diff --git a/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js b/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js index bc5e4d37ab2c28..95de775e48eef8 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js +++ b/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js @@ -15,6 +15,8 @@ function PatternCategoriesList( { { patternCategories.map( ( { name, label } ) => { return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } key={ name } label={ label } className={ `${ baseClassName }__categories-list__item` } diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/index.js b/packages/block-editor/src/components/inserter/block-patterns-tab/index.js index 65b477d09069f3..0db78cec24dcb2 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/index.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/index.js @@ -61,6 +61,8 @@ function BlockPatternsTab( { { children } </CategoryTabs> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="block-editor-inserter__patterns-explore-button" onClick={ () => setShowPatternsExplorer( true ) } variant="secondary" diff --git a/packages/block-editor/src/components/inserter/media-tab/media-preview.js b/packages/block-editor/src/components/inserter/media-tab/media-preview.js index 816cc9373ea08d..be0058fe022118 100644 --- a/packages/block-editor/src/components/inserter/media-tab/media-preview.js +++ b/packages/block-editor/src/components/inserter/media-tab/media-preview.js @@ -102,12 +102,22 @@ function InsertExternalImageModal( { onClose, onSubmit } ) { expanded={ false } > <FlexItem> - <Button variant="tertiary" onClick={ onClose }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="tertiary" + onClick={ onClose } + > { __( 'Cancel' ) } </Button> </FlexItem> <FlexItem> - <Button variant="primary" onClick={ onSubmit }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="primary" + onClick={ onSubmit } + > { __( 'Insert' ) } </Button> </FlexItem> diff --git a/packages/block-editor/src/components/inserter/media-tab/media-tab.js b/packages/block-editor/src/components/inserter/media-tab/media-tab.js index 2f3985aef569cb..07fce9ee6d80b0 100644 --- a/packages/block-editor/src/components/inserter/media-tab/media-tab.js +++ b/packages/block-editor/src/components/inserter/media-tab/media-tab.js @@ -71,6 +71,8 @@ function MediaTab( { allowedTypes={ ALLOWED_MEDIA_TYPES } render={ ( { open } ) => ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } onClick={ ( event ) => { // Safari doesn't emit a focus event on button elements when // clicked and we need to manually focus the button here. diff --git a/packages/block-editor/src/components/inserter/quick-inserter.js b/packages/block-editor/src/components/inserter/quick-inserter.js index f4c52c04d20c4b..0852c562828a4b 100644 --- a/packages/block-editor/src/components/inserter/quick-inserter.js +++ b/packages/block-editor/src/components/inserter/quick-inserter.js @@ -141,6 +141,8 @@ export default function QuickInserter( { { setInserterIsOpened && ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="block-editor-inserter__quick-inserter-expand" onClick={ onBrowseAll } aria-label={ __( diff --git a/packages/block-editor/src/components/inspector-controls-tabs/index.js b/packages/block-editor/src/components/inspector-controls-tabs/index.js index 9e348ab4b1ed11..601854373b7eb0 100644 --- a/packages/block-editor/src/components/inspector-controls-tabs/index.js +++ b/packages/block-editor/src/components/inspector-controls-tabs/index.js @@ -49,6 +49,8 @@ export default function InspectorControlsTabs( { tabId={ tab.name } render={ <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ ! showIconLabels ? tab.icon : undefined } diff --git a/packages/block-editor/src/components/inspector-popover-header/index.js b/packages/block-editor/src/components/inspector-popover-header/index.js index e5f492eddd2b77..d543ab0298cc62 100644 --- a/packages/block-editor/src/components/inspector-popover-header/index.js +++ b/packages/block-editor/src/components/inspector-popover-header/index.js @@ -31,6 +31,8 @@ export default function InspectorPopoverHeader( { <Spacer /> { actions.map( ( { label, icon, onClick } ) => ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } key={ label } className="block-editor-inspector-popover-header__action" label={ label } @@ -43,6 +45,8 @@ export default function InspectorPopoverHeader( { ) ) } { onClose && ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="block-editor-inspector-popover-header__action" label={ __( 'Close' ) } icon={ closeSmall } diff --git a/packages/block-editor/src/components/link-control/index.js b/packages/block-editor/src/components/link-control/index.js index 85626e50fcf2aa..2024aca998caac 100644 --- a/packages/block-editor/src/components/link-control/index.js +++ b/packages/block-editor/src/components/link-control/index.js @@ -408,6 +408,8 @@ function LinkControl( { { ! showActions && ( <div className="block-editor-link-control__search-enter"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } onClick={ isDisabled ? noop : handleSubmit } label={ __( 'Submit' ) } icon={ keyboardReturn } @@ -467,10 +469,17 @@ function LinkControl( { justify="right" className="block-editor-link-control__search-actions" > - <Button variant="tertiary" onClick={ handleCancel }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="tertiary" + onClick={ handleCancel } + > { __( 'Cancel' ) } </Button> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="primary" onClick={ isDisabled ? noop : handleSubmit } className="block-editor-link-control__search-submit" diff --git a/packages/block-editor/src/components/link-control/settings-drawer.js b/packages/block-editor/src/components/link-control/settings-drawer.js index 8d0c717b1af6cc..d8bffbd553f81b 100644 --- a/packages/block-editor/src/components/link-control/settings-drawer.js +++ b/packages/block-editor/src/components/link-control/settings-drawer.js @@ -25,6 +25,8 @@ function LinkSettingsDrawer( { children, settingsOpen, setSettingsOpen } ) { return ( <> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="block-editor-link-control__drawer-toggle" aria-expanded={ settingsOpen } onClick={ () => setSettingsOpen( ! settingsOpen ) } diff --git a/packages/block-editor/src/components/list-view/block-select-button.js b/packages/block-editor/src/components/list-view/block-select-button.js index 6755bb58e02569..fbfa06ee10936b 100644 --- a/packages/block-editor/src/components/list-view/block-select-button.js +++ b/packages/block-editor/src/components/list-view/block-select-button.js @@ -83,6 +83,8 @@ function ListViewBlockSelectButton( return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className={ clsx( 'block-editor-list-view-block-select-button', className diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index c54ee9c0caf617..a5b4eb0bf19b3f 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -51,6 +51,8 @@ const InsertFromURLPopover = ( { value={ src } /> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="block-editor-media-placeholder__url-input-submit-button" icon={ keyboardReturn } label={ __( 'Apply' ) } @@ -85,6 +87,8 @@ const URLSelectionUI = ( { src, onChangeSrc, onSelectURL } ) => { return ( <div className="block-editor-media-placeholder__url-input-container"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="block-editor-media-placeholder__button" onClick={ openURLInput } isPressed={ isURLInputVisible } @@ -382,6 +386,8 @@ export function MediaPlaceholder( { return ( onCancel && ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="block-editor-media-placeholder__cancel-button" title={ __( 'Cancel' ) } variant="link" @@ -410,6 +416,8 @@ export function MediaPlaceholder( { onToggleFeaturedImage && ( <div className="block-editor-media-placeholder__url-input-container"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="block-editor-media-placeholder__button" onClick={ onToggleFeaturedImage } variant="secondary" @@ -425,6 +433,8 @@ export function MediaPlaceholder( { const defaultButton = ( { open } ) => { return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="secondary" onClick={ () => { open(); @@ -464,6 +474,8 @@ export function MediaPlaceholder( { const content = ( <> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="primary" className={ clsx( 'block-editor-media-placeholder__button', @@ -493,6 +505,8 @@ export function MediaPlaceholder( { <FormFileUpload render={ ( { openFileDialog } ) => ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } onClick={ openFileDialog } variant="primary" className={ clsx( diff --git a/packages/block-editor/src/components/skip-to-selected-block/index.js b/packages/block-editor/src/components/skip-to-selected-block/index.js index 2f78f706112c38..dee7f37550e379 100644 --- a/packages/block-editor/src/components/skip-to-selected-block/index.js +++ b/packages/block-editor/src/components/skip-to-selected-block/index.js @@ -28,6 +28,8 @@ export default function SkipToSelectedBlock() { return selectedBlockClientId ? ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="secondary" className="block-editor-skip-to-selected-block" onClick={ onClick } diff --git a/packages/block-editor/src/components/tool-selector/index.js b/packages/block-editor/src/components/tool-selector/index.js index 1e93a18cf6bb9e..4ec777a911cc73 100644 --- a/packages/block-editor/src/components/tool-selector/index.js +++ b/packages/block-editor/src/components/tool-selector/index.js @@ -41,6 +41,8 @@ function ToolSelector( props, ref ) { <Dropdown renderToggle={ ( { isOpen, onToggle } ) => ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } { ...props } ref={ ref } icon={ mode === 'navigation' ? selectIcon : editIcon } diff --git a/packages/block-editor/src/components/url-input/button.js b/packages/block-editor/src/components/url-input/button.js index 6ee6b96f61e0e1..8170ea614ace26 100644 --- a/packages/block-editor/src/components/url-input/button.js +++ b/packages/block-editor/src/components/url-input/button.js @@ -38,6 +38,8 @@ class URLInputButton extends Component { return ( <div className="block-editor-url-input__button"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ link } label={ buttonLabel } onClick={ this.toggle } @@ -51,6 +53,8 @@ class URLInputButton extends Component { > <div className="block-editor-url-input__button-modal-line"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="block-editor-url-input__back" icon={ arrowLeft } label={ __( 'Close' ) } @@ -61,6 +65,8 @@ class URLInputButton extends Component { onChange={ onChange } /> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ keyboardReturn } label={ __( 'Submit' ) } type="submit" diff --git a/packages/block-editor/src/components/url-input/index.js b/packages/block-editor/src/components/url-input/index.js index 8360bfada853c6..9a5c589a44a047 100644 --- a/packages/block-editor/src/components/url-input/index.js +++ b/packages/block-editor/src/components/url-input/index.js @@ -539,6 +539,8 @@ class URLInput extends Component { > { suggestions.map( ( suggestion, index ) => ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } { ...buildSuggestionItemProps( suggestion, index ) } key={ suggestion.id } className={ clsx( diff --git a/packages/block-editor/src/components/url-popover/stories/index.story.js b/packages/block-editor/src/components/url-popover/stories/index.story.js index 5d548f964062a4..ceed23eed6b841 100644 --- a/packages/block-editor/src/components/url-popover/stories/index.story.js +++ b/packages/block-editor/src/components/url-popover/stories/index.story.js @@ -22,7 +22,12 @@ const TestURLPopover = () => { return ( <> - <Button onClick={ () => setVisiblility( true ) }>Edit URL</Button> + <Button + __next40pxDefaultSize + onClick={ () => setVisiblility( true ) } + > + Edit URL + </Button> { isVisible && ( <URLPopover onClose={ close } @@ -37,6 +42,7 @@ const TestURLPopover = () => { <form onSubmit={ close }> <input type="url" value={ url } onChange={ setUrl } /> <Button + __next40pxDefaultSize icon={ keyboardReturn } label={ __( 'Apply' ) } type="submit" diff --git a/packages/block-editor/src/hooks/layout.js b/packages/block-editor/src/hooks/layout.js index a19c5604701f6d..2ea8c5f37c9e77 100644 --- a/packages/block-editor/src/hooks/layout.js +++ b/packages/block-editor/src/hooks/layout.js @@ -320,6 +320,8 @@ function LayoutTypeSwitcher( { type, onChange } ) { { getLayoutTypes().map( ( { name, label } ) => { return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } key={ name } isPressed={ type === name } onClick={ () => onChange( name ) } diff --git a/packages/block-editor/src/layouts/flex.js b/packages/block-editor/src/layouts/flex.js index afefc2d5f103a3..dc7e9d1a167a19 100644 --- a/packages/block-editor/src/layouts/flex.js +++ b/packages/block-editor/src/layouts/flex.js @@ -246,6 +246,8 @@ function FlexLayoutVerticalAlignmentControl( { { verticalAlignmentOptions.map( ( value, icon, label ) => { return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } key={ value } label={ label } icon={ icon } diff --git a/packages/block-library/src/comments/edit/comments-legacy.js b/packages/block-library/src/comments/edit/comments-legacy.js index be460dbbcb0b5e..b5a12e34343dac 100644 --- a/packages/block-library/src/comments/edit/comments-legacy.js +++ b/packages/block-library/src/comments/edit/comments-legacy.js @@ -29,6 +29,8 @@ export default function CommentsLegacy( { const actions = [ <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } key="convert" onClick={ () => void setAttributes( { legacy: false } ) } variant="primary" diff --git a/packages/block-library/src/embed/embed-placeholder.js b/packages/block-library/src/embed/embed-placeholder.js index 57aa0645ee3d94..9a26060a294120 100644 --- a/packages/block-library/src/embed/embed-placeholder.js +++ b/packages/block-library/src/embed/embed-placeholder.js @@ -65,10 +65,20 @@ const EmbedPlaceholder = ( { spacing={ 3 } justify="flex-start" > - <Button variant="secondary" onClick={ tryAgain }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="secondary" + onClick={ tryAgain } + > { _x( 'Try again', 'button label' ) } </Button>{ ' ' } - <Button variant="secondary" onClick={ fallback }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="secondary" + onClick={ fallback } + > { _x( 'Convert to link', 'button label' ) } </Button> </HStack> diff --git a/packages/block-library/src/freeform/modal.js b/packages/block-library/src/freeform/modal.js index c1b10a61de808d..1768022377a432 100644 --- a/packages/block-library/src/freeform/modal.js +++ b/packages/block-library/src/freeform/modal.js @@ -25,6 +25,8 @@ function ModalAuxiliaryActions( { onClick, isModalFullScreen } ) { return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } onClick={ onClick } icon={ fullscreen } isPressed={ isModalFullScreen } @@ -120,12 +122,19 @@ export default function ModalEdit( props ) { expanded={ false } > <FlexItem> - <Button variant="tertiary" onClick={ onClose }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="tertiary" + onClick={ onClose } + > { __( 'Cancel' ) } </Button> </FlexItem> <FlexItem> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="primary" onClick={ () => { setAttributes( { diff --git a/packages/block-library/src/missing/edit.js b/packages/block-library/src/missing/edit.js index e7945630534d70..9fb507794756f8 100644 --- a/packages/block-library/src/missing/edit.js +++ b/packages/block-library/src/missing/edit.js @@ -49,7 +49,13 @@ export default function MissingEdit( { attributes, clientId } ) { let messageHTML; const convertToHtmlButton = ( - <Button key="convert" onClick={ convertToHTML } variant="primary"> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + key="convert" + onClick={ convertToHTML } + variant="primary" + > { __( 'Keep as HTML' ) } </Button> ); diff --git a/packages/block-library/src/navigation-link/link-ui.js b/packages/block-library/src/navigation-link/link-ui.js index deed35145d6dea..fb3e6d40196127 100644 --- a/packages/block-library/src/navigation-link/link-ui.js +++ b/packages/block-library/src/navigation-link/link-ui.js @@ -310,6 +310,8 @@ const LinkUITools = ( { setAddingBlock, focusAddBlockButton } ) => { return ( <VStack className="link-ui-tools"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } ref={ addBlockButtonRef } icon={ plus } onClick={ ( e ) => { diff --git a/packages/block-library/src/navigation/edit/deleted-navigation-warning.js b/packages/block-library/src/navigation/edit/deleted-navigation-warning.js index 915e19694085de..8950a700ace513 100644 --- a/packages/block-library/src/navigation/edit/deleted-navigation-warning.js +++ b/packages/block-library/src/navigation/edit/deleted-navigation-warning.js @@ -14,7 +14,14 @@ function DeletedNavigationWarning( { onCreateNew } ) { 'Navigation Menu has been deleted or is unavailable. <button>Create a new Menu?</button>' ), { - button: <Button onClick={ onCreateNew } variant="link" />, + button: ( + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + onClick={ onCreateNew } + variant="link" + /> + ), } ) } </Warning> diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js index 12b052d28fc72e..c9ce17eea6b1ab 100644 --- a/packages/block-library/src/navigation/edit/index.js +++ b/packages/block-library/src/navigation/edit/index.js @@ -591,6 +591,8 @@ function Navigation( { { isResponsive && ( <> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className={ overlayMenuPreviewClasses } onClick={ () => { setOverlayMenuPreview( diff --git a/packages/block-library/src/navigation/edit/navigation-menu-delete-control.js b/packages/block-library/src/navigation/edit/navigation-menu-delete-control.js index dcef345581a765..a75ad1dd00cce2 100644 --- a/packages/block-library/src/navigation/edit/navigation-menu-delete-control.js +++ b/packages/block-library/src/navigation/edit/navigation-menu-delete-control.js @@ -19,6 +19,8 @@ export default function NavigationMenuDeleteControl( { onDelete } ) { return ( <> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="wp-block-navigation-delete-menu-button" variant="secondary" isDestructive diff --git a/packages/block-library/src/navigation/edit/placeholder/index.js b/packages/block-library/src/navigation/edit/placeholder/index.js index 0d7c1a7c863b54..f4d01b73e1fbbd 100644 --- a/packages/block-library/src/navigation/edit/placeholder/index.js +++ b/packages/block-library/src/navigation/edit/placeholder/index.js @@ -76,6 +76,8 @@ export default function NavigationPlaceholder( { { canUserCreateNavigationMenus && ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="tertiary" onClick={ onCreateEmpty } > diff --git a/packages/block-library/src/navigation/edit/responsive-wrapper.js b/packages/block-library/src/navigation/edit/responsive-wrapper.js index 0c6fa0e3b9128a..328152723026f5 100644 --- a/packages/block-library/src/navigation/edit/responsive-wrapper.js +++ b/packages/block-library/src/navigation/edit/responsive-wrapper.js @@ -79,6 +79,8 @@ export default function ResponsiveWrapper( { <> { ! isOpen && ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } aria-haspopup="true" aria-label={ hasIcon && __( 'Open menu' ) } className={ openButtonClasses } @@ -100,6 +102,8 @@ export default function ResponsiveWrapper( { > <div { ...dialogProps }> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="wp-block-navigation__responsive-container-close" aria-label={ hasIcon && __( 'Close menu' ) } onClick={ () => onToggle( false ) } diff --git a/packages/block-library/src/page-list/convert-to-links-modal.js b/packages/block-library/src/page-list/convert-to-links-modal.js index 209987b1942386..b56b3bf7c6b4f1 100644 --- a/packages/block-library/src/page-list/convert-to-links-modal.js +++ b/packages/block-library/src/page-list/convert-to-links-modal.js @@ -31,10 +31,17 @@ export function ConvertToLinksModal( { onClick, onClose, disabled } ) { { convertDescription } </p> <div className="wp-block-page-list-modal-buttons"> - <Button variant="tertiary" onClick={ onClose }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="tertiary" + onClick={ onClose } + > { __( 'Cancel' ) } </Button> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="primary" accessibleWhenDisabled disabled={ disabled } diff --git a/packages/block-library/src/page-list/edit.js b/packages/block-library/src/page-list/edit.js index 923b2d4fd88555..750d5a1ad8b92a 100644 --- a/packages/block-library/src/page-list/edit.js +++ b/packages/block-library/src/page-list/edit.js @@ -342,6 +342,8 @@ export default function PageListEdit( { <PanelBody title={ __( 'Edit this menu' ) }> <p>{ convertDescription }</p> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="primary" accessibleWhenDisabled disabled={ ! hasResolvedPages } diff --git a/packages/block-library/src/post-comments-form/form.js b/packages/block-library/src/post-comments-form/form.js index f6ab07ed897d76..882282a53c6afc 100644 --- a/packages/block-library/src/post-comments-form/form.js +++ b/packages/block-library/src/post-comments-form/form.js @@ -84,6 +84,8 @@ const CommentsForm = ( { postId, postType } ) => { if ( 'closed' === commentStatus ) { const actions = [ <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } key="enableComments" onClick={ () => setCommentStatus( 'open' ) } variant="primary" diff --git a/packages/block-library/src/post-featured-image/edit.js b/packages/block-library/src/post-featured-image/edit.js index b2fc63ba9cbdc4..3d54a7415f288b 100644 --- a/packages/block-library/src/post-featured-image/edit.js +++ b/packages/block-library/src/post-featured-image/edit.js @@ -309,6 +309,8 @@ export default function PostFeaturedImageEdit( { mediaLibraryButton={ ( { open } ) => { return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ upload } variant="primary" label={ label } diff --git a/packages/block-library/src/query/edit/enhanced-pagination-modal.js b/packages/block-library/src/query/edit/enhanced-pagination-modal.js index bc8e05f67a01ee..f33c45646e536b 100644 --- a/packages/block-library/src/query/edit/enhanced-pagination-modal.js +++ b/packages/block-library/src/query/edit/enhanced-pagination-modal.js @@ -75,7 +75,12 @@ export default function EnhancedPaginationModal( { > <VStack alignment="right" spacing={ 5 }> <span id={ modalDescriptionId }>{ notice }</span> - <Button variant="primary" onClick={ closeModal }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="primary" + onClick={ closeModal } + > { __( 'OK' ) } </Button> </VStack> diff --git a/packages/block-library/src/query/edit/query-placeholder.js b/packages/block-library/src/query/edit/query-placeholder.js index eec982c9750cf8..098c29f0ec512b 100644 --- a/packages/block-library/src/query/edit/query-placeholder.js +++ b/packages/block-library/src/query/edit/query-placeholder.js @@ -79,6 +79,8 @@ export default function QueryPlaceholder( { > { !! hasPatterns && ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="primary" onClick={ openPatternSelectionModal } > @@ -87,6 +89,8 @@ export default function QueryPlaceholder( { ) } <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="secondary" onClick={ () => { setIsStartingBlank( true ); diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index b7e47ec542d1e9..e44147529af2b5 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -639,6 +639,8 @@ export default function LogoEdit( { render={ ( { open } ) => ( <div className="block-library-site-logo__inspector-upload-container"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } onClick={ open } variant="secondary" > @@ -683,6 +685,8 @@ export default function LogoEdit( { mediaLibraryButton={ ( { open } ) => { return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ upload } variant="primary" label={ __( 'Choose logo' ) } diff --git a/packages/block-library/src/social-link/edit.js b/packages/block-library/src/social-link/edit.js index 5ba57a8a29edf9..f6d46731a399f3 100644 --- a/packages/block-library/src/social-link/edit.js +++ b/packages/block-library/src/social-link/edit.js @@ -81,6 +81,8 @@ const SocialLinkURLPopover = ( { /> </div> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ keyboardReturn } label={ __( 'Apply' ) } type="submit" diff --git a/packages/block-library/src/template-part/edit/placeholder.js b/packages/block-library/src/template-part/edit/placeholder.js index c7e5e70c970e09..d54401c2327fbb 100644 --- a/packages/block-library/src/template-part/edit/placeholder.js +++ b/packages/block-library/src/template-part/edit/placeholder.js @@ -74,13 +74,20 @@ export default function TemplatePartPlaceholder( { { ! isResolving && !! ( templateParts.length || blockPatterns.length ) && ( - <Button variant="primary" onClick={ onOpenSelectionModal }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="primary" + onClick={ onOpenSelectionModal } + > { __( 'Choose' ) } </Button> ) } { ! isResolving && isBlockBasedTheme && canCreateTemplatePart && ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="secondary" onClick={ () => { setShowTitleModal( true ); diff --git a/packages/block-library/src/video/edit.js b/packages/block-library/src/video/edit.js index 647b6b2cbea194..05dbcc58e8b8e5 100644 --- a/packages/block-library/src/video/edit.js +++ b/packages/block-library/src/video/edit.js @@ -231,6 +231,8 @@ function VideoEdit( { } render={ ( { open } ) => ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="primary" onClick={ open } ref={ posterImageButton } @@ -259,6 +261,8 @@ function VideoEdit( { </p> { !! poster && ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } onClick={ onRemovePoster } variant="tertiary" > @@ -271,10 +275,10 @@ function VideoEdit( { </InspectorControls> <figure { ...blockProps }> { /* - Disable the video tag if the block is not selected - so the user clicking on it won't play the - video when the controls are enabled. - */ } + Disable the video tag if the block is not selected + so the user clicking on it won't play the + video when the controls are enabled. + */ } <Disabled isDisabled={ ! isSingleSelected }> <video controls={ controls } diff --git a/packages/block-library/src/video/tracks-editor.js b/packages/block-library/src/video/tracks-editor.js index 8928c26840e3d9..079ffd9fc46f82 100644 --- a/packages/block-library/src/video/tracks-editor.js +++ b/packages/block-library/src/video/tracks-editor.js @@ -58,6 +58,8 @@ function TrackList( { tracks, onEditPress } ) { > <span>{ track.label } </span> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="tertiary" onClick={ () => onEditPress( index ) } aria-label={ sprintf( @@ -145,6 +147,8 @@ function SingleTrackEditor( { track, onChange, onClose, onRemove } ) { /> <HStack className="block-library-video-tracks-editor__single-track-editor-buttons-container"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="secondary" onClick={ () => { const changes = {}; @@ -173,6 +177,8 @@ function SingleTrackEditor( { track, onChange, onClose, onRemove } ) { { __( 'Close' ) } </Button> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } isDestructive variant="link" onClick={ onRemove } diff --git a/packages/customize-widgets/src/components/error-boundary/index.js b/packages/customize-widgets/src/components/error-boundary/index.js index d1aece49b91736..49867787afd059 100644 --- a/packages/customize-widgets/src/components/error-boundary/index.js +++ b/packages/customize-widgets/src/components/error-boundary/index.js @@ -11,7 +11,12 @@ import { doAction } from '@wordpress/hooks'; function CopyButton( { text, children } ) { const ref = useCopyToClipboard( text ); return ( - <Button variant="secondary" ref={ ref }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="secondary" + ref={ ref } + > { children } </Button> ); diff --git a/packages/customize-widgets/src/components/inserter/index.js b/packages/customize-widgets/src/components/inserter/index.js index c0156cf774ddc6..41fc037cf673c9 100644 --- a/packages/customize-widgets/src/components/inserter/index.js +++ b/packages/customize-widgets/src/components/inserter/index.js @@ -37,6 +37,8 @@ function Inserter( { setIsOpened } ) { { __( 'Add a block' ) } </h2> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="customize-widgets-layout__inserter-panel-header-close-button" icon={ closeSmall } onClick={ () => setIsOpened( false ) } diff --git a/packages/customize-widgets/src/components/welcome-guide/index.js b/packages/customize-widgets/src/components/welcome-guide/index.js index 52807118baec7c..51c4d479be51ff 100644 --- a/packages/customize-widgets/src/components/welcome-guide/index.js +++ b/packages/customize-widgets/src/components/welcome-guide/index.js @@ -43,6 +43,8 @@ export default function WelcomeGuide( { sidebar } ) { ) } </p> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="customize-widgets-welcome-guide__button" variant="primary" onClick={ () => diff --git a/packages/data/src/components/with-dispatch/test/index.js b/packages/data/src/components/with-dispatch/test/index.js index f4e38d28edba0a..6bcda99ba9c0f0 100644 --- a/packages/data/src/components/with-dispatch/test/index.js +++ b/packages/data/src/components/with-dispatch/test/index.js @@ -58,7 +58,9 @@ describe( 'withDispatch', () => { } ); }, }; - } )( ( props ) => <Button onClick={ props.increment } /> ); + } )( ( props ) => ( + <Button __next40pxDefaultSize onClick={ props.increment } /> + ) ); const { rerender } = render( <RegistryProvider value={ registry }> diff --git a/packages/dataviews/src/components/dataviews/stories/fixtures.js b/packages/dataviews/src/components/dataviews/stories/fixtures.js index e061d0951ade73..4edc16c53f5de6 100644 --- a/packages/dataviews/src/components/dataviews/stories/fixtures.js +++ b/packages/dataviews/src/components/dataviews/stories/fixtures.js @@ -148,13 +148,21 @@ export const actions = [ return ( <VStack spacing="5"> <Text> - { `Are you sure you want to delete "${ item.title }"?` } + { `Are you sure you want to delete "${ item?.title }"?` } </Text> <HStack justify="right"> - <Button variant="tertiary" onClick={ closeModal }> + <Button + __next40pxDefaultSize + variant="tertiary" + onClick={ closeModal } + > Cancel </Button> - <Button variant="primary" onClick={ closeModal }> + <Button + __next40pxDefaultSize + variant="primary" + onClick={ closeModal } + > Delete </Button> </HStack> diff --git a/packages/dataviews/src/dataforms-layouts/panel/index.tsx b/packages/dataviews/src/dataforms-layouts/panel/index.tsx index 151aefed12c24b..9f118584998bd3 100644 --- a/packages/dataviews/src/dataforms-layouts/panel/index.tsx +++ b/packages/dataviews/src/dataforms-layouts/panel/index.tsx @@ -44,6 +44,8 @@ function DropdownHeader( { <Spacer /> { onClose && ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="dataforms-layouts-panel__dropdown-header-action" label={ __( 'Close' ) } icon={ closeSmall } diff --git a/packages/edit-post/src/components/back-button/fullscreen-mode-close.js b/packages/edit-post/src/components/back-button/fullscreen-mode-close.js index 02eaceb3a35e50..626212cbab0542 100644 --- a/packages/edit-post/src/components/back-button/fullscreen-mode-close.js +++ b/packages/edit-post/src/components/back-button/fullscreen-mode-close.js @@ -91,6 +91,8 @@ function FullscreenModeClose( { showTooltip, icon, href, initialPost } ) { return ( <motion.div whileHover="expand"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className={ classes } href={ buttonHref } label={ buttonLabel } diff --git a/packages/edit-post/src/components/init-pattern-modal/index.js b/packages/edit-post/src/components/init-pattern-modal/index.js index bb448953364f05..5b94e838dbcad2 100644 --- a/packages/edit-post/src/components/init-pattern-modal/index.js +++ b/packages/edit-post/src/components/init-pattern-modal/index.js @@ -88,6 +88,8 @@ export default function InitPatternModal() { /> <HStack justify="right"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="primary" type="submit" disabled={ ! title } diff --git a/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js b/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js index 94d4f28c632cd6..c32e337be58c0e 100644 --- a/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js +++ b/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js @@ -39,6 +39,8 @@ export function CustomFieldsConfirmation( { willEnable } ) { ) } </p> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="edit-post-preferences-modal__custom-fields-confirmation-button" variant="secondary" isBusy={ isReloading } diff --git a/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js b/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js index 10f3c7c54521f4..0ef403379ccdb8 100644 --- a/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js +++ b/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js @@ -43,6 +43,8 @@ function SuggestionListItem( { <CompositeItem render={ <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } role="option" className={ baseCssClass } onClick={ () => diff --git a/packages/edit-site/src/components/add-new-template/index.js b/packages/edit-site/src/components/add-new-template/index.js index e8f68905e34ccf..8a900ecc958009 100644 --- a/packages/edit-site/src/components/add-new-template/index.js +++ b/packages/edit-site/src/components/add-new-template/index.js @@ -107,6 +107,8 @@ function TemplateListItem( { } ) { return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className={ className } onClick={ onClick } label={ description } diff --git a/packages/edit-site/src/components/editor-canvas-container/index.js b/packages/edit-site/src/components/editor-canvas-container/index.js index 4f93c2e1995d29..75a04b5887d75f 100644 --- a/packages/edit-site/src/components/editor-canvas-container/index.js +++ b/packages/edit-site/src/components/editor-canvas-container/index.js @@ -136,6 +136,8 @@ function EditorCanvasContainer( { > { shouldShowCloseButton && ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="edit-site-editor-canvas-container__close-button" icon={ closeSmall } label={ closeButtonLabel || __( 'Close' ) } diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 85119acab493d3..4be3c960bb4a34 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -258,6 +258,8 @@ export default function EditSiteEditor( { isPostsList = false } ) { whileTap="tap" > <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } label={ __( 'Open Navigation' ) } showTooltip tooltipPosition="middle right" diff --git a/packages/edit-site/src/components/error-boundary/warning.js b/packages/edit-site/src/components/error-boundary/warning.js index af51b43be3431e..b03c99f46f03b1 100644 --- a/packages/edit-site/src/components/error-boundary/warning.js +++ b/packages/edit-site/src/components/error-boundary/warning.js @@ -9,7 +9,12 @@ import { useCopyToClipboard } from '@wordpress/compose'; function CopyButton( { text, children } ) { const ref = useCopyToClipboard( text ); return ( - <Button variant="secondary" ref={ ref }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="secondary" + ref={ ref } + > { children } </Button> ); diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js index 8728e5d61b22a0..7ecfa431ac8d20 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js @@ -28,6 +28,8 @@ function FontCard( { font, onClick, variantsText, navigatorPath } ) { return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } onClick={ () => { onClick(); if ( navigatorPath ) { diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js index 5c8263c0df1024..efa9524167f7b8 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js @@ -456,6 +456,8 @@ function FontCollection( { slug } ) { className="font-library-modal__footer" > <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="primary" onClick={ handleInstall } isBusy={ isInstalling } diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js index 281ec0b30f7627..945db7ccb8ae63 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js @@ -419,6 +419,8 @@ function InstalledFonts() { { isInstalling && <ProgressBar /> } { shouldDisplayDeleteButton && ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } isDestructive variant="tertiary" onClick={ handleUninstallClick } @@ -427,6 +429,8 @@ function InstalledFonts() { </Button> ) } <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="primary" onClick={ handleUpdate } disabled={ ! fontFamiliesHasChanges } diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/upload-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/upload-fonts.js index 0f6331a54304de..d2ec234ab444c5 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/upload-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/upload-fonts.js @@ -230,6 +230,8 @@ function UploadFonts() { onChange={ onFilesUpload } render={ ( { openFileDialog } ) => ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="font-library-modal__upload-area" onClick={ openFileDialog } > diff --git a/packages/edit-site/src/components/global-styles/palette.js b/packages/edit-site/src/components/global-styles/palette.js index e85c0e93314027..7d2ea0c1cfa0ed 100644 --- a/packages/edit-site/src/components/global-styles/palette.js +++ b/packages/edit-site/src/components/global-styles/palette.js @@ -87,6 +87,8 @@ function Palette( { name } ) { { window.__experimentalEnableColorRandomizer && themeColors?.length > 0 && ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="secondary" icon={ shuffle } onClick={ randomizeThemeColors } diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js b/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js index a17e5fde5763a7..84f074b8d00c09 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js +++ b/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js @@ -162,6 +162,8 @@ function RevisionsButtons( { aria-current={ isSelected } > <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="edit-site-global-styles-screen-revisions__revision-button" accessibleWhenDisabled disabled={ isSelected } diff --git a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js index 284f498efea3e1..77bbdb88221167 100644 --- a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js +++ b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js @@ -234,6 +234,8 @@ export default function ShadowsEditPanel() { > <FlexItem> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="tertiary" onClick={ () => setIsRenameModalVisible( false ) @@ -243,7 +245,12 @@ export default function ShadowsEditPanel() { </Button> </FlexItem> <FlexItem> - <Button variant="primary" type="submit"> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="primary" + type="submit" + > { __( 'Save' ) } </Button> </FlexItem> @@ -373,7 +380,12 @@ function ShadowItem( { shadow, onChange, canRemove, onRemove } ) { return ( <HStack align="center" justify="flex-start" spacing={ 0 }> <FlexItem style={ { flexGrow: 1 } }> - <Button icon={ shadowIcon } { ...toggleProps }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + icon={ shadowIcon } + { ...toggleProps } + > { shadowObj.inset ? __( 'Inner shadow' ) : __( 'Drop shadow' ) } @@ -382,6 +394,8 @@ function ShadowItem( { shadow, onChange, canRemove, onRemove } ) { { canRemove && ( <FlexItem> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ reset } { ...removeButtonProps } /> diff --git a/packages/edit-site/src/components/page-patterns/fields.js b/packages/edit-site/src/components/page-patterns/fields.js index eab6dbca32833a..ff14aa371fdc7e 100644 --- a/packages/edit-site/src/components/page-patterns/fields.js +++ b/packages/edit-site/src/components/page-patterns/fields.js @@ -133,6 +133,8 @@ function TitleField( { item } ) { title ) : ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="link" onClick={ onClick } // Required for the grid's roving tab index system. diff --git a/packages/edit-site/src/components/save-panel/index.js b/packages/edit-site/src/components/save-panel/index.js index ad65fb208b4a06..babcf72181a1af 100644 --- a/packages/edit-site/src/components/save-panel/index.js +++ b/packages/edit-site/src/components/save-panel/index.js @@ -150,6 +150,8 @@ export default function SavePanel() { } ) } > <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="secondary" className="edit-site-editor__toggle-save-panel-button" onClick={ () => setIsSaveViewOpened( true ) } diff --git a/packages/edit-site/src/components/sidebar-button/index.js b/packages/edit-site/src/components/sidebar-button/index.js index 9329515b21c7d6..d7030597dac503 100644 --- a/packages/edit-site/src/components/sidebar-button/index.js +++ b/packages/edit-site/src/components/sidebar-button/index.js @@ -11,6 +11,8 @@ import { Button } from '@wordpress/components'; export default function SidebarButton( props ) { return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } { ...props } className={ clsx( 'edit-site-sidebar-button', props.className ) } /> diff --git a/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js b/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js index 5f366a8f93e65f..3e369db9b2a821 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js +++ b/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js @@ -88,6 +88,8 @@ function AddNewItemModalContent( { type, setIsAdding } ) { /> <HStack justify="right"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="tertiary" onClick={ () => { setIsAdding( false ); @@ -97,6 +99,8 @@ function AddNewItemModalContent( { type, setIsAdding } ) { </Button> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="primary" type="submit" aria-disabled={ ! title || isSaving } diff --git a/packages/edit-site/src/components/site-hub/index.js b/packages/edit-site/src/components/site-hub/index.js index fe6ea4440a4e80..66439cd0712fab 100644 --- a/packages/edit-site/src/components/site-hub/index.js +++ b/packages/edit-site/src/components/site-hub/index.js @@ -65,6 +65,8 @@ const SiteHub = memo( ) } > <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } ref={ ref } href={ dashboardLink } label={ __( 'Go to the Dashboard' ) } @@ -81,6 +83,8 @@ const SiteHub = memo( <HStack> <div className="edit-site-site-hub__title"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="link" href={ homeUrl } target="_blank" @@ -100,6 +104,8 @@ const SiteHub = memo( className="edit-site-site-hub__actions" > <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="edit-site-site-hub_toggle-command-center" icon={ search } onClick={ () => openCommandCenter() } @@ -149,6 +155,8 @@ export const SiteHubMobile = memo( ) } > <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } ref={ ref } label={ __( 'Go to Site Editor' ) } className="edit-site-layout__view-mode-toggle" @@ -168,6 +176,8 @@ export const SiteHubMobile = memo( <HStack> <div className="edit-site-site-hub__title"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="link" href={ homeUrl } target="_blank" @@ -182,6 +192,8 @@ export const SiteHubMobile = memo( className="edit-site-site-hub__actions" > <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="edit-site-site-hub_toggle-command-center" icon={ search } onClick={ () => openCommandCenter() } diff --git a/packages/edit-widgets/src/components/error-boundary/index.js b/packages/edit-widgets/src/components/error-boundary/index.js index 5bb7a44fea4135..e6ed91926da3ef 100644 --- a/packages/edit-widgets/src/components/error-boundary/index.js +++ b/packages/edit-widgets/src/components/error-boundary/index.js @@ -11,7 +11,12 @@ import { doAction } from '@wordpress/hooks'; function CopyButton( { text, children } ) { const ref = useCopyToClipboard( text ); return ( - <Button variant="secondary" ref={ ref }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="secondary" + ref={ ref } + > { children } </Button> ); diff --git a/packages/edit-widgets/src/components/secondary-sidebar/inserter-sidebar.js b/packages/edit-widgets/src/components/secondary-sidebar/inserter-sidebar.js index 2374b35ad2d699..085ca38a3e182a 100644 --- a/packages/edit-widgets/src/components/secondary-sidebar/inserter-sidebar.js +++ b/packages/edit-widgets/src/components/secondary-sidebar/inserter-sidebar.js @@ -44,6 +44,8 @@ export default function InserterSidebar() { > <TagName className="edit-widgets-layout__inserter-panel-header"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ close } onClick={ closeInserter } label={ __( 'Close block inserter' ) } diff --git a/packages/edit-widgets/src/components/secondary-sidebar/list-view-sidebar.js b/packages/edit-widgets/src/components/secondary-sidebar/list-view-sidebar.js index 6aa2123a6774ad..9822f3ff00bc74 100644 --- a/packages/edit-widgets/src/components/secondary-sidebar/list-view-sidebar.js +++ b/packages/edit-widgets/src/components/secondary-sidebar/list-view-sidebar.js @@ -51,6 +51,8 @@ export default function ListViewSidebar() { <div className="edit-widgets-editor__list-view-panel-header"> <strong>{ __( 'List View' ) }</strong> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ closeSmall } label={ __( 'Close' ) } onClick={ closeListView } diff --git a/packages/edit-widgets/src/components/sidebar/widget-areas.js b/packages/edit-widgets/src/components/sidebar/widget-areas.js index 98ce523d6e4fe2..3bcba478eefe8e 100644 --- a/packages/edit-widgets/src/components/sidebar/widget-areas.js +++ b/packages/edit-widgets/src/components/sidebar/widget-areas.js @@ -66,6 +66,8 @@ export default function WidgetAreas( { selectedWidgetAreaId } ) { ) } { ! selectedWidgetArea && ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } href={ addQueryArgs( 'customize.php', { 'autofocus[panel]': 'widgets', return: window.location.pathname, diff --git a/packages/editor/src/components/block-manager/index.js b/packages/editor/src/components/block-manager/index.js index 910eeda4470b01..0f70812e268de4 100644 --- a/packages/editor/src/components/block-manager/index.js +++ b/packages/editor/src/components/block-manager/index.js @@ -67,6 +67,8 @@ function BlockManager( { numberOfHiddenBlocks ) } <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="link" onClick={ () => enableAllBlockTypes( blockTypes ) } > diff --git a/packages/editor/src/components/editor-history/redo.js b/packages/editor/src/components/editor-history/redo.js index 2ded5bfd52539a..ef46ff6bc78e2c 100644 --- a/packages/editor/src/components/editor-history/redo.js +++ b/packages/editor/src/components/editor-history/redo.js @@ -25,6 +25,8 @@ function EditorHistoryRedo( props, ref ) { const { redo } = useDispatch( editorStore ); return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } { ...props } ref={ ref } icon={ ! isRTL() ? redoIcon : undoIcon } diff --git a/packages/editor/src/components/editor-history/undo.js b/packages/editor/src/components/editor-history/undo.js index 18f2cb2e7e35d6..0c28f8c8231f8f 100644 --- a/packages/editor/src/components/editor-history/undo.js +++ b/packages/editor/src/components/editor-history/undo.js @@ -21,6 +21,8 @@ function EditorHistoryUndo( props, ref ) { const { undo } = useDispatch( editorStore ); return ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } { ...props } ref={ ref } icon={ ! isRTL() ? undoIcon : redoIcon } diff --git a/packages/editor/src/components/error-boundary/index.js b/packages/editor/src/components/error-boundary/index.js index 966ea433c0d643..30cc6b970f3066 100644 --- a/packages/editor/src/components/error-boundary/index.js +++ b/packages/editor/src/components/error-boundary/index.js @@ -29,7 +29,12 @@ function getContent() { function CopyButton( { text, children } ) { const ref = useCopyToClipboard( text ); return ( - <Button variant="secondary" ref={ ref }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="secondary" + ref={ ref } + > { children } </Button> ); diff --git a/packages/editor/src/components/post-excerpt/panel.js b/packages/editor/src/components/post-excerpt/panel.js index 0c800c1a360b9b..9a37e9134775aa 100644 --- a/packages/editor/src/components/post-excerpt/panel.js +++ b/packages/editor/src/components/post-excerpt/panel.js @@ -198,6 +198,8 @@ function PrivateExcerpt() { ref={ setPopoverAnchor } renderToggle={ ( { onToggle } ) => ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="editor-post-excerpt__dropdown__trigger" onClick={ onToggle } variant="link" diff --git a/packages/editor/src/components/post-featured-image/index.js b/packages/editor/src/components/post-featured-image/index.js index febf56a46778fc..b6d44bd668cf75 100644 --- a/packages/editor/src/components/post-featured-image/index.js +++ b/packages/editor/src/components/post-featured-image/index.js @@ -160,6 +160,8 @@ function PostFeaturedImage( { render={ ( { open } ) => ( <div className="editor-post-featured-image__container"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } ref={ toggleRef } className={ ! featuredImageId @@ -200,6 +202,8 @@ function PostFeaturedImage( { { !! featuredImageId && ( <HStack className="editor-post-featured-image__actions"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="editor-post-featured-image__action" onClick={ open } aria-haspopup="dialog" @@ -207,6 +211,8 @@ function PostFeaturedImage( { { __( 'Replace' ) } </Button> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="editor-post-featured-image__action" onClick={ () => { onRemoveImage(); diff --git a/packages/editor/src/components/post-format/index.js b/packages/editor/src/components/post-format/index.js index a61d230a00119d..34e86a15b9d7fa 100644 --- a/packages/editor/src/components/post-format/index.js +++ b/packages/editor/src/components/post-format/index.js @@ -100,6 +100,8 @@ export default function PostFormat() { { suggestion && suggestion.id !== postFormat && ( <p className="editor-post-format__suggestion"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="link" onClick={ () => onUpdatePostFormat( suggestion.id ) diff --git a/packages/editor/src/components/post-last-revision/index.js b/packages/editor/src/components/post-last-revision/index.js index d0f94e26048d77..b47ddb3acddd5a 100644 --- a/packages/editor/src/components/post-last-revision/index.js +++ b/packages/editor/src/components/post-last-revision/index.js @@ -36,6 +36,8 @@ function PostLastRevision() { return ( <PostLastRevisionCheck> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } href={ addQueryArgs( 'revision.php', { revision: lastRevisionId, } ) } diff --git a/packages/editor/src/components/post-locked-modal/index.js b/packages/editor/src/components/post-locked-modal/index.js index 6f858c13722a28..3c79c0466622e0 100644 --- a/packages/editor/src/components/post-locked-modal/index.js +++ b/packages/editor/src/components/post-locked-modal/index.js @@ -254,11 +254,21 @@ export default function PostLockedModal() { justify="flex-end" > { ! isTakeover && ( - <Button variant="tertiary" href={ unlockUrl }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="tertiary" + href={ unlockUrl } + > { __( 'Take over' ) } </Button> ) } - <Button variant="primary" href={ allPostsUrl }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="primary" + href={ allPostsUrl } + > { allPostsLabel } </Button> </HStack> diff --git a/packages/editor/src/components/post-publish-panel/index.js b/packages/editor/src/components/post-publish-panel/index.js index 28567c60780219..3e411e91db4724 100644 --- a/packages/editor/src/components/post-publish-panel/index.js +++ b/packages/editor/src/components/post-publish-panel/index.js @@ -78,6 +78,8 @@ export class PostPublishPanel extends Component { <div className="editor-post-publish-panel__header"> { isPostPublish ? ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } onClick={ onClose } icon={ closeSmall } label={ __( 'Close panel' ) } diff --git a/packages/editor/src/components/post-publish-panel/maybe-post-format-panel.js b/packages/editor/src/components/post-publish-panel/maybe-post-format-panel.js index 4555b33dbb9efb..6320390d9da5cc 100644 --- a/packages/editor/src/components/post-publish-panel/maybe-post-format-panel.js +++ b/packages/editor/src/components/post-publish-panel/maybe-post-format-panel.js @@ -25,6 +25,8 @@ const PostFormatSuggestion = ( { onUpdatePostFormat, } ) => ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="link" onClick={ () => onUpdatePostFormat( suggestedPostFormat ) } > diff --git a/packages/editor/src/components/post-publish-panel/maybe-upload-media.js b/packages/editor/src/components/post-publish-panel/maybe-upload-media.js index 609864e01716a8..d3e861ee7c29d3 100644 --- a/packages/editor/src/components/post-publish-panel/maybe-upload-media.js +++ b/packages/editor/src/components/post-publish-panel/maybe-upload-media.js @@ -149,7 +149,12 @@ export default function PostFormatPanel() { { isUploading || isAnimating ? ( <Spinner /> ) : ( - <Button variant="primary" onClick={ uploadImages }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="primary" + onClick={ uploadImages } + > { __( 'Upload' ) } </Button> ) } diff --git a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js index 112bfaabd0c8ec..4913cef9b4c86f 100644 --- a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js +++ b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js @@ -428,6 +428,8 @@ export function HierarchicalTermSelector( { slug } ) { { ! loading && hasCreateAction && ( <FlexItem> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } onClick={ onToggleForm } className="editor-post-taxonomies__hierarchical-terms-add" aria-expanded={ showForm } diff --git a/packages/editor/src/components/post-taxonomies/most-used-terms.js b/packages/editor/src/components/post-taxonomies/most-used-terms.js index 36a44fb7f986c2..e42337b54e444f 100644 --- a/packages/editor/src/components/post-taxonomies/most-used-terms.js +++ b/packages/editor/src/components/post-taxonomies/most-used-terms.js @@ -62,6 +62,8 @@ export default function MostUsedTerms( { onSelect, taxonomy } ) { { terms.map( ( term ) => ( <li key={ term.id }> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="link" onClick={ () => onSelect( term ) } > diff --git a/packages/editor/src/components/post-template/classic-theme.js b/packages/editor/src/components/post-template/classic-theme.js index 276c6454fef09c..8127a18909f5cc 100644 --- a/packages/editor/src/components/post-template/classic-theme.js +++ b/packages/editor/src/components/post-template/classic-theme.js @@ -177,6 +177,8 @@ function PostTemplateDropdownContent( { onClose } ) { { canEdit && onNavigateToEntityRecord && ( <p> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="link" onClick={ () => { onNavigateToEntityRecord( { diff --git a/packages/editor/src/components/post-url/index.js b/packages/editor/src/components/post-url/index.js index e767ae04f5ec0e..5ed3155388c8cc 100644 --- a/packages/editor/src/components/post-url/index.js +++ b/packages/editor/src/components/post-url/index.js @@ -110,6 +110,8 @@ export default function PostURL( { onClose } ) { } suffix={ <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } icon={ copySmall } ref={ copyButtonRef } label={ __( 'Copy' ) } diff --git a/packages/editor/src/components/save-publish-panels/index.js b/packages/editor/src/components/save-publish-panels/index.js index 139ebd54bee95e..d559f13fd96a45 100644 --- a/packages/editor/src/components/save-publish-panels/index.js +++ b/packages/editor/src/components/save-publish-panels/index.js @@ -71,6 +71,8 @@ export default function SavePublishPanels( { unmountableContent = ( <div className="editor-layout__toggle-publish-panel"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="secondary" className="editor-layout__toggle-publish-panel-button" onClick={ togglePublishSidebar } @@ -84,6 +86,8 @@ export default function SavePublishPanels( { unmountableContent = ( <div className="editor-layout__toggle-entities-saved-states-panel"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="secondary" className="editor-layout__toggle-entities-saved-states-panel-button" onClick={ openEntitiesSavedStates } diff --git a/packages/editor/src/components/start-template-options/index.js b/packages/editor/src/components/start-template-options/index.js index e350ca9c607c39..e86531272b54fd 100644 --- a/packages/editor/src/components/start-template-options/index.js +++ b/packages/editor/src/components/start-template-options/index.js @@ -155,7 +155,12 @@ function StartModal( { slug, isCustom, onClose, postType } ) { expanded={ false } > <FlexItem> - <Button variant="tertiary" onClick={ onClose }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="tertiary" + onClick={ onClose } + > { __( 'Skip' ) } </Button> </FlexItem> diff --git a/packages/editor/src/components/table-of-contents/index.js b/packages/editor/src/components/table-of-contents/index.js index 74a535240833d6..f2c79fb0347446 100644 --- a/packages/editor/src/components/table-of-contents/index.js +++ b/packages/editor/src/components/table-of-contents/index.js @@ -30,6 +30,8 @@ function TableOfContents( contentClassName="table-of-contents__popover" renderToggle={ ( { isOpen, onToggle } ) => ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } { ...props } ref={ ref } onClick={ hasBlocks ? onToggle : undefined } diff --git a/packages/editor/src/components/text-editor/index.js b/packages/editor/src/components/text-editor/index.js index b65a958249b6f8..6bfe2a5375a35e 100644 --- a/packages/editor/src/components/text-editor/index.js +++ b/packages/editor/src/components/text-editor/index.js @@ -40,6 +40,8 @@ export default function TextEditor( { autoFocus = false } ) { <div className="editor-text-editor__toolbar"> <h2>{ __( 'Editing code' ) }</h2> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="tertiary" onClick={ () => switchEditorMode( 'visual' ) } shortcut={ shortcut } diff --git a/packages/editor/src/dataviews/actions/reset-post.tsx b/packages/editor/src/dataviews/actions/reset-post.tsx index cc4cea8f5c82c0..64396e45c392ff 100644 --- a/packages/editor/src/dataviews/actions/reset-post.tsx +++ b/packages/editor/src/dataviews/actions/reset-post.tsx @@ -114,6 +114,8 @@ const resetPost: Action< Post > = { </Text> <HStack justify="right"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="tertiary" onClick={ closeModal } disabled={ isBusy } @@ -122,6 +124,8 @@ const resetPost: Action< Post > = { { __( 'Cancel' ) } </Button> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="primary" onClick={ async () => { setIsBusy( true ); diff --git a/packages/editor/src/dataviews/actions/trash-post.tsx b/packages/editor/src/dataviews/actions/trash-post.tsx index 537a0ebd79a8ac..1e2b3639dddc83 100644 --- a/packages/editor/src/dataviews/actions/trash-post.tsx +++ b/packages/editor/src/dataviews/actions/trash-post.tsx @@ -67,6 +67,8 @@ const trashPost: Action< PostWithPermissions > = { </Text> <HStack justify="right"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="tertiary" onClick={ closeModal } disabled={ isBusy } @@ -75,6 +77,8 @@ const trashPost: Action< PostWithPermissions > = { { __( 'Cancel' ) } </Button> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="primary" onClick={ async () => { setIsBusy( true ); diff --git a/packages/list-reusable-blocks/src/components/import-dropdown/index.js b/packages/list-reusable-blocks/src/components/import-dropdown/index.js index 94f70a1551199d..d20ba9fcf10999 100644 --- a/packages/list-reusable-blocks/src/components/import-dropdown/index.js +++ b/packages/list-reusable-blocks/src/components/import-dropdown/index.js @@ -17,6 +17,8 @@ function ImportDropdown( { onUpload } ) { contentClassName="list-reusable-blocks-import-dropdown__content" renderToggle={ ( { isOpen, onToggle } ) => ( <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } aria-expanded={ isOpen } onClick={ onToggle } variant="primary" diff --git a/packages/list-reusable-blocks/src/components/import-form/index.js b/packages/list-reusable-blocks/src/components/import-form/index.js index 9c6e8bf57835f1..b78869df61eb6c 100644 --- a/packages/list-reusable-blocks/src/components/import-form/index.js +++ b/packages/list-reusable-blocks/src/components/import-form/index.js @@ -84,6 +84,8 @@ function ImportForm( { instanceId, onUpload } ) { </label> <input id={ inputId } type="file" onChange={ onChangeFile } /> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } type="submit" isBusy={ isLoading } accessibleWhenDisabled diff --git a/packages/nux/src/components/dot-tip/index.js b/packages/nux/src/components/dot-tip/index.js index 50de7ddb3be9df..80db7568b351b1 100644 --- a/packages/nux/src/components/dot-tip/index.js +++ b/packages/nux/src/components/dot-tip/index.js @@ -56,11 +56,18 @@ export function DotTip( { > <p>{ children }</p> <p> - <Button variant="link" onClick={ onDismiss }> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="link" + onClick={ onDismiss } + > { hasNextTip ? __( 'See next tip' ) : __( 'Got it' ) } </Button> </p> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } className="nux-dot-tip__disable" icon={ close } label={ __( 'Disable tips' ) } diff --git a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js index 81536b70a7ad32..bceca4876654cf 100644 --- a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js +++ b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js @@ -191,6 +191,8 @@ export default function ReusableBlockConvertButton( { /> <HStack justify="right"> <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } variant="tertiary" onClick={ () => { setIsModalOpen( false ); @@ -200,7 +202,12 @@ export default function ReusableBlockConvertButton( { { __( 'Cancel' ) } </Button> - <Button variant="primary" type="submit"> + <Button + // TODO: Switch to `true` (40px size) if possible + __next40pxDefaultSize={ false } + variant="primary" + type="submit" + > { __( 'Create' ) } </Button> </HStack> From d0337f218df4fc61b7e2e62c1246d38ec1bdb3a9 Mon Sep 17 00:00:00 2001 From: David Arenas <david.arenas@automattic.com> Date: Tue, 27 Aug 2024 20:05:55 +0200 Subject: [PATCH 0558/1908] Interactivity API: Fix computeds without scope in Firefox (#64825) * Replace NO_SCOPE symbol with an object * Update changelog Co-authored-by: DAreRodz <darerodz@git.wordpress.org> Co-authored-by: luisherranz <luisherranz@git.wordpress.org> Co-authored-by: Marc-pi <mdxfr@git.wordpress.org> --- packages/interactivity/CHANGELOG.md | 4 ++++ packages/interactivity/src/proxies/signals.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index abc79853d222bf..b9ca382e835d5e 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- Fix computeds without scope in Firefox ([#64825](https://github.com/WordPress/gutenberg/pull/64825)). + ## 6.6.0 (2024-08-21) ### Bug Fixes diff --git a/packages/interactivity/src/proxies/signals.ts b/packages/interactivity/src/proxies/signals.ts index 6a3f41c149e134..29bd58aaa4fced 100644 --- a/packages/interactivity/src/proxies/signals.ts +++ b/packages/interactivity/src/proxies/signals.ts @@ -20,7 +20,7 @@ import { withScope } from '../utils'; /** * Identifier for property computeds not associated to any scope. */ -const NO_SCOPE = Symbol(); +const NO_SCOPE = {}; /** * Structure that manages reactivity for a property in a state object. It uses From 5773ae60ca33bda03f2a35e6707d961b8db3af18 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 27 Aug 2024 21:36:45 +0200 Subject: [PATCH 0559/1908] AlignmentMatrixControl: simplify styles and markup (#64827) * Simplify icon active cell computation * AlignmentMatrixControl: simplify styles * AlignmentMatrixControl.Icon: rewrite using SVG * Do not use `size` prop on AlignmentMatrixControl.Icon in Storybook * Cleanup * CHANGELOG * Do not type height and width explicitly * Fix typo * Inline computedWidth and computedHeight * Restore getAlignmentIndex function, since it normalizes values internally --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 2 + .../src/alignment-matrix-control/cell.tsx | 12 +- .../src/alignment-matrix-control/icon.tsx | 78 +++++++----- .../src/alignment-matrix-control/index.tsx | 29 ++--- .../stories/index.story.tsx | 13 +- .../src/alignment-matrix-control/styles.ts | 113 ++++++++++++++++++ .../alignment-matrix-control-icon-styles.ts | 77 ------------ .../styles/alignment-matrix-control-styles.ts | 102 ---------------- .../src/alignment-matrix-control/types.ts | 13 +- 9 files changed, 190 insertions(+), 249 deletions(-) create mode 100644 packages/components/src/alignment-matrix-control/styles.ts delete mode 100644 packages/components/src/alignment-matrix-control/styles/alignment-matrix-control-icon-styles.ts delete mode 100644 packages/components/src/alignment-matrix-control/styles/alignment-matrix-control-styles.ts diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 8c676c3334465c..f3c851344b9769 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,11 +5,13 @@ ### Deprecations - Deprecate `replace` from the options accepted by `useNavigator().goTo()` ([#64675](https://github.com/WordPress/gutenberg/pull/64675)). +- Soft deprecate `size` prop on `AlignmentMatrixControl.Icon` ([#64827](https://github.com/WordPress/gutenberg/pull/64827)). ### Enhancements - `ColorPicker`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). - `CustomSelectControl V2`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). +- `AlignmentMatrixControl.Icon`: rewrite entirely using SVG markup ([#64827](https://github.com/WordPress/gutenberg/pull/64827)). - `DateTime`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). - `FormToggle`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). - `FormTokenField`: Remove unused border-radius ([#64693](https://github.com/WordPress/gutenberg/pull/64693)). diff --git a/packages/components/src/alignment-matrix-control/cell.tsx b/packages/components/src/alignment-matrix-control/cell.tsx index 6e045c26694f4e..8a3d1735b5ecfa 100644 --- a/packages/components/src/alignment-matrix-control/cell.tsx +++ b/packages/components/src/alignment-matrix-control/cell.tsx @@ -9,23 +9,17 @@ import { VisuallyHidden } from '../visually-hidden'; * Internal dependencies */ import { ALIGNMENT_LABEL } from './utils'; -import { - Cell as CellView, - Point, -} from './styles/alignment-matrix-control-styles'; +import { Cell as CellView, Point } from './styles'; import type { AlignmentMatrixControlCellProps } from './types'; import type { WordPressComponentProps } from '../context'; export default function Cell( { id, - isActive = false, value, ...props }: WordPressComponentProps< AlignmentMatrixControlCellProps, 'span', false > ) { - const tooltipText = ALIGNMENT_LABEL[ value ]; - return ( - <Tooltip text={ tooltipText }> + <Tooltip text={ ALIGNMENT_LABEL[ value ] }> <Composite.Item id={ id } render={ <CellView { ...props } role="gridcell" /> } @@ -34,7 +28,7 @@ export default function Cell( { otherwise it'll announce the content as "blank". So we use a visually hidden element instead of aria-label. */ } <VisuallyHidden>{ value }</VisuallyHidden> - <Point isActive={ isActive } role="presentation" /> + <Point role="presentation" /> </Composite.Item> </Tooltip> ); diff --git a/packages/components/src/alignment-matrix-control/icon.tsx b/packages/components/src/alignment-matrix-control/icon.tsx index bacc9771cf3e44..24cf54c0214937 100644 --- a/packages/components/src/alignment-matrix-control/icon.tsx +++ b/packages/components/src/alignment-matrix-control/icon.tsx @@ -3,59 +3,77 @@ */ import clsx from 'clsx'; +/** + * WordPress dependencies + */ +import { Rect, SVG } from '@wordpress/primitives'; + /** * Internal dependencies */ import { ALIGNMENTS, getAlignmentIndex } from './utils'; -import { - Root, - Cell, - Point, -} from './styles/alignment-matrix-control-icon-styles'; import type { AlignmentMatrixControlIconProps } from './types'; import type { WordPressComponentProps } from '../context'; const BASE_SIZE = 24; +const GRID_CELL_SIZE = 7; +const GRID_PADDING = ( BASE_SIZE - 3 * GRID_CELL_SIZE ) / 2; +const DOT_SIZE = 2; +const DOT_SIZE_SELECTED = 4; function AlignmentMatrixControlIcon( { className, disablePointerEvents = true, - size = BASE_SIZE, + size, + width, + height, style = {}, value = 'center', ...props -}: WordPressComponentProps< AlignmentMatrixControlIconProps, 'div', false > ) { - const alignIndex = getAlignmentIndex( value ); - const scale = ( size / BASE_SIZE ).toFixed( 2 ); - - const classes = clsx( - 'component-alignment-matrix-control-icon', - className - ); - - const styles = { - ...style, - transform: `scale(${ scale })`, - }; - +}: WordPressComponentProps< AlignmentMatrixControlIconProps, 'svg', false > ) { return ( - <Root - { ...props } - className={ classes } - disablePointerEvents={ disablePointerEvents } + <SVG + xmlns="http://www.w3.org/2000/svg" + viewBox={ `0 0 ${ BASE_SIZE } ${ BASE_SIZE }` } + width={ size ?? width ?? BASE_SIZE } + height={ size ?? height ?? BASE_SIZE } role="presentation" - style={ styles } + className={ clsx( + 'component-alignment-matrix-control-icon', + className + ) } + style={ { + pointerEvents: disablePointerEvents ? 'none' : undefined, + ...style, + } } + { ...props } > { ALIGNMENTS.map( ( align, index ) => { - const isActive = alignIndex === index; + const dotSize = + getAlignmentIndex( value ) === index + ? DOT_SIZE_SELECTED + : DOT_SIZE; return ( - <Cell key={ align }> - <Point isActive={ isActive } /> - </Cell> + <Rect + key={ align } + x={ + GRID_PADDING + + ( index % 3 ) * GRID_CELL_SIZE + + ( GRID_CELL_SIZE - dotSize ) / 2 + } + y={ + GRID_PADDING + + Math.floor( index / 3 ) * GRID_CELL_SIZE + + ( GRID_CELL_SIZE - dotSize ) / 2 + } + width={ dotSize } + height={ dotSize } + fill="currentColor" + /> ); } ) } - </Root> + </SVG> ); } diff --git a/packages/components/src/alignment-matrix-control/index.tsx b/packages/components/src/alignment-matrix-control/index.tsx index 4f3e78ca921f01..a865cd4f57a98b 100644 --- a/packages/components/src/alignment-matrix-control/index.tsx +++ b/packages/components/src/alignment-matrix-control/index.tsx @@ -2,7 +2,6 @@ * External dependencies */ import clsx from 'clsx'; -import { useStoreState } from '@ariakit/react'; /** * WordPress dependencies @@ -16,7 +15,7 @@ import { useInstanceId } from '@wordpress/compose'; import Cell from './cell'; import { Composite } from '../composite'; import { useCompositeStore } from '../composite/store'; -import { Root, Row } from './styles/alignment-matrix-control-styles'; +import { GridContainer, GridRow } from './styles'; import AlignmentMatrixControlIcon from './icon'; import { GRID, getItemId, getItemValue } from './utils'; import type { WordPressComponentProps } from '../context'; @@ -70,15 +69,13 @@ export function AlignmentMatrixControl( { rtl: isRTL(), } ); - const activeId = useStoreState( compositeStore, 'activeId' ); - const classes = clsx( 'component-alignment-matrix-control', className ); return ( <Composite store={ compositeStore } render={ - <Root + <GridContainer { ...props } aria-label={ label } className={ classes } @@ -89,20 +86,14 @@ export function AlignmentMatrixControl( { } > { GRID.map( ( cells, index ) => ( - <Composite.Row render={ <Row role="row" /> } key={ index }> - { cells.map( ( cell ) => { - const cellId = getItemId( baseId, cell ); - const isActive = cellId === activeId; - - return ( - <Cell - id={ cellId } - isActive={ isActive } - key={ cell } - value={ cell } - /> - ); - } ) } + <Composite.Row render={ <GridRow role="row" /> } key={ index }> + { cells.map( ( cell ) => ( + <Cell + id={ getItemId( baseId, cell ) } + key={ cell } + value={ cell } + /> + ) ) } </Composite.Row> ) ) } </Composite> diff --git a/packages/components/src/alignment-matrix-control/stories/index.story.tsx b/packages/components/src/alignment-matrix-control/stories/index.story.tsx index 03bec9d92a8b78..11de17153492d8 100644 --- a/packages/components/src/alignment-matrix-control/stories/index.story.tsx +++ b/packages/components/src/alignment-matrix-control/stories/index.story.tsx @@ -59,18 +59,9 @@ export const Default = Template.bind( {} ); export const IconSubcomponent = () => { return ( <HStack justify="flex-start"> + <Icon icon={ <AlignmentMatrixControl.Icon value="top left" /> } /> <Icon - icon={ - <AlignmentMatrixControl.Icon size={ 24 } value="top left" /> - } - /> - <Icon - icon={ - <AlignmentMatrixControl.Icon - size={ 24 } - value="center center" - /> - } + icon={ <AlignmentMatrixControl.Icon value="center center" /> } /> </HStack> ); diff --git a/packages/components/src/alignment-matrix-control/styles.ts b/packages/components/src/alignment-matrix-control/styles.ts new file mode 100644 index 00000000000000..73a20c2a37564b --- /dev/null +++ b/packages/components/src/alignment-matrix-control/styles.ts @@ -0,0 +1,113 @@ +/** + * External dependencies + */ +import styled from '@emotion/styled'; +import { css } from '@emotion/react'; + +/** + * Internal dependencies + */ +import { COLORS, CONFIG } from '../utils'; +import type { + AlignmentMatrixControlProps, + AlignmentMatrixControlIconProps, +} from './types'; + +// Grid structure + +const rootBase = ( { size = 92 } ) => css` + direction: ltr; + + display: grid; + grid-template-columns: repeat( 3, 1fr ); + grid-template-rows: repeat( 3, 1fr ); + + box-sizing: border-box; + width: ${ size }px; + aspect-ratio: 1; + + border-radius: ${ CONFIG.radiusMedium }; + outline: none; +`; + +export const GridContainer = styled.div< { + size?: AlignmentMatrixControlProps[ 'width' ]; + disablePointerEvents?: AlignmentMatrixControlIconProps[ 'disablePointerEvents' ]; +} >` + ${ rootBase } + + border: 1px solid transparent; + + ${ ( props ) => + props.disablePointerEvents + ? css`` + : css` + cursor: pointer; + ` } +`; + +export const GridRow = styled.div` + grid-column: 1 / -1; + + box-sizing: border-box; + display: grid; + grid-template-columns: repeat( 3, 1fr ); +`; + +// Cell +export const Cell = styled.span` + position: relative; + + display: flex; + align-items: center; + justify-content: center; + + box-sizing: border-box; + margin: 0; + padding: 0; + + appearance: none; + border: none; + outline: none; +`; + +const POINT_SIZE = 6; +export const Point = styled.span` + display: block; + contain: strict; + + box-sizing: border-box; + width: ${ POINT_SIZE }px; + aspect-ratio: 1; + + margin: auto; + + color: ${ COLORS.theme.gray[ 400 ] }; + + /* Use border instead of background color so that the point shows + in Windows High Contrast Mode */ + border: ${ POINT_SIZE / 2 }px solid currentColor; + + /* Highlight active item */ + ${ Cell }[data-active-item] & { + color: ${ COLORS.gray[ 900 ] }; + transform: scale( calc( 5 / 3 ) ); + } + + /* Hover styles for non-active items */ + ${ Cell }:not([data-active-item]):hover & { + color: ${ COLORS.theme.accent }; + } + + /* Show an outline only when interacting with keyboard */ + ${ Cell }[data-focus-visible] & { + outline: 1px solid ${ COLORS.theme.accent }; + outline-offset: 1px; + } + + @media not ( prefers-reduced-motion ) { + transition-property: color, transform; + transition-duration: 120ms; + transition-timing-function: linear; + } +`; diff --git a/packages/components/src/alignment-matrix-control/styles/alignment-matrix-control-icon-styles.ts b/packages/components/src/alignment-matrix-control/styles/alignment-matrix-control-icon-styles.ts deleted file mode 100644 index a14894633e05d1..00000000000000 --- a/packages/components/src/alignment-matrix-control/styles/alignment-matrix-control-icon-styles.ts +++ /dev/null @@ -1,77 +0,0 @@ -/** - * External dependencies - */ -import styled from '@emotion/styled'; -import { css } from '@emotion/react'; - -/** - * Internal dependencies - */ -import { - rootBase, - pointBase, - Cell as CellBase, -} from './alignment-matrix-control-styles'; -import type { - AlignmentMatrixControlIconProps, - AlignmentMatrixControlCellProps, -} from '../types'; - -const rootSize = () => { - const padding = 1.5; - const size = 24; - - return css( { - gridTemplateRows: `repeat( 3, calc( ${ size - padding * 2 }px / 3))`, - padding, - maxHeight: size, - maxWidth: size, - } ); -}; - -const rootPointerEvents = ( { - disablePointerEvents, -}: Pick< AlignmentMatrixControlIconProps, 'disablePointerEvents' > ) => { - return css( { - pointerEvents: disablePointerEvents ? 'none' : undefined, - } ); -}; - -export const Wrapper = styled.div` - box-sizing: border-box; - padding: 2px; -`; - -export const Root = styled.div` - transform-origin: top left; - height: 100%; - width: 100%; - - ${ rootBase }; - ${ rootSize }; - ${ rootPointerEvents }; -`; - -const pointActive = ( { - isActive, -}: Pick< AlignmentMatrixControlCellProps, 'isActive' > ) => { - const boxShadow = isActive ? `0 0 0 1px currentColor` : null; - - return css` - box-shadow: ${ boxShadow }; - color: currentColor; - - *:hover > & { - color: currentColor; - } - `; -}; - -export const Point = styled.span` - height: 2px; - width: 2px; - ${ pointBase }; - ${ pointActive }; -`; - -export const Cell = CellBase; diff --git a/packages/components/src/alignment-matrix-control/styles/alignment-matrix-control-styles.ts b/packages/components/src/alignment-matrix-control/styles/alignment-matrix-control-styles.ts deleted file mode 100644 index efbd23ab2be0af..00000000000000 --- a/packages/components/src/alignment-matrix-control/styles/alignment-matrix-control-styles.ts +++ /dev/null @@ -1,102 +0,0 @@ -/** - * External dependencies - */ -import styled from '@emotion/styled'; -import { css } from '@emotion/react'; - -/** - * Internal dependencies - */ -import { COLORS, CONFIG } from '../../utils'; -import type { - AlignmentMatrixControlProps, - AlignmentMatrixControlCellProps, -} from '../types'; - -export const rootBase = () => { - return css` - border-radius: ${ CONFIG.radiusMedium }; - box-sizing: border-box; - direction: ltr; - display: grid; - grid-template-columns: repeat( 3, 1fr ); - outline: none; - `; -}; - -const rootSize = ( { size = 92 } ) => { - return css` - grid-template-rows: repeat( 3, calc( ${ size }px / 3 ) ); - width: ${ size }px; - `; -}; - -export const Root = styled.div< { - size: AlignmentMatrixControlProps[ 'width' ]; -} >` - ${ rootBase }; - - border: 1px solid transparent; - cursor: pointer; - grid-template-columns: auto; - - ${ rootSize }; -`; - -export const Row = styled.div` - box-sizing: border-box; - display: grid; - grid-template-columns: repeat( 3, 1fr ); -`; - -const pointActive = ( { - isActive, -}: Pick< AlignmentMatrixControlCellProps, 'isActive' > ) => { - const boxShadow = isActive ? `0 0 0 2px ${ COLORS.gray[ 900 ] }` : null; - const pointColor = isActive ? COLORS.gray[ 900 ] : COLORS.gray[ 400 ]; - const pointColorHover = isActive ? COLORS.gray[ 900 ] : COLORS.theme.accent; - - return css` - box-shadow: ${ boxShadow }; - color: ${ pointColor }; - - *:hover > & { - color: ${ pointColorHover }; - } - `; -}; - -export const pointBase = ( - props: Pick< AlignmentMatrixControlCellProps, 'isActive' > -) => { - return css` - background: currentColor; - box-sizing: border-box; - display: grid; - margin: auto; - @media not ( prefers-reduced-motion ) { - transition: all 120ms linear; - } - - ${ pointActive( props ) } - `; -}; - -export const Point = styled.span` - height: 6px; - width: 6px; - ${ pointBase } -`; - -export const Cell = styled.span` - appearance: none; - border: none; - box-sizing: border-box; - margin: 0; - display: flex; - position: relative; - outline: none; - align-items: center; - justify-content: center; - padding: 0; -`; diff --git a/packages/components/src/alignment-matrix-control/types.ts b/packages/components/src/alignment-matrix-control/types.ts index 892781234e694c..0f97c2df3b02bb 100644 --- a/packages/components/src/alignment-matrix-control/types.ts +++ b/packages/components/src/alignment-matrix-control/types.ts @@ -44,11 +44,22 @@ export type AlignmentMatrixControlIconProps = Pick< AlignmentMatrixControlProps, 'value' > & { + /** + * If `true`, disables pointer events on the icon. + * @default true + */ disablePointerEvents?: boolean; + /** + * _Note: this prop is deprecated. Use the `size` prop on the parent `Icon` + * component instead_ + * + * The size of the icon. + * @ignore + * @default 24 + */ size?: number; }; export type AlignmentMatrixControlCellProps = { - isActive?: boolean; value: NonNullable< AlignmentMatrixControlProps[ 'value' ] >; }; From 3d026e566a15950a5559fc97d7e8e221ca691785 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 28 Aug 2024 09:50:41 +0700 Subject: [PATCH 0560/1908] Global Styles: Allow referenced zero value and simplify getValueFromObjectPath calls (#64836) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/components/global-styles/test/utils.js | 10 ++++++++++ .../block-editor/src/components/global-styles/utils.js | 10 ++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/test/utils.js b/packages/block-editor/src/components/global-styles/test/utils.js index 08ed1f18e80402..57a157662969e1 100644 --- a/packages/block-editor/src/components/global-styles/test/utils.js +++ b/packages/block-editor/src/components/global-styles/test/utils.js @@ -73,6 +73,11 @@ describe( 'editor utils', () => { dimensions: { minHeight: '100px', }, + spacing: { + padding: { + top: 0, + }, + }, }, }, }, @@ -444,6 +449,11 @@ describe( 'editor utils', () => { { url: 'file:./assets/image.jpg' }, themeJson, ], + [ + { ref: 'styles.blocks.core/group.spacing.padding.top' }, + 0, + themeJson, + ], [ { ref: 'styles.blocks.core/group.background.backgroundImage', diff --git a/packages/block-editor/src/components/global-styles/utils.js b/packages/block-editor/src/components/global-styles/utils.js index 59799c9032c67f..f5dc157d1df8eb 100644 --- a/packages/block-editor/src/components/global-styles/utils.js +++ b/packages/block-editor/src/components/global-styles/utils.js @@ -306,9 +306,8 @@ function getValueFromCustomVariable( features, blockName, variable, path ) { */ export function getValueFromVariable( features, blockName, variable ) { if ( ! variable || typeof variable !== 'string' ) { - if ( variable?.ref && typeof variable?.ref === 'string' ) { - const refPath = variable.ref.split( '.' ); - variable = getValueFromObjectPath( features, refPath ); + if ( typeof variable?.ref === 'string' ) { + variable = getValueFromObjectPath( features, variable.ref ); // Presence of another ref indicates a reference to another dynamic value. // Pointing to another dynamic value is not supported. if ( ! variable || !! variable?.ref ) { @@ -568,9 +567,8 @@ export function getResolvedRefValue( ruleValue, tree ) { * For example: { "ref": "style.color.background" } => "#fff". */ if ( typeof ruleValue !== 'string' && ruleValue?.ref ) { - const refPath = ruleValue.ref.split( '.' ); const resolvedRuleValue = getCSSValueFromRawStyle( - getValueFromObjectPath( tree, refPath ) + getValueFromObjectPath( tree, ruleValue.ref ) ); /* @@ -581,7 +579,7 @@ export function getResolvedRefValue( ruleValue, tree ) { return undefined; } - if ( ! resolvedRuleValue ) { + if ( resolvedRuleValue === undefined ) { return ruleValue; } From 1e8495954e3fd6265f742408707847494848d920 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Wed, 28 Aug 2024 12:09:58 +0800 Subject: [PATCH 0561/1908] Retain the same specificity for non iframed selectors (#64534) * WIP * Small fixes, improvements to root selector handling, avoid double prefixing * Add test for compound :where statements * Fix too specific layout styles in non-iframed editor * Update handling of root selectors * Fix all the problems * Update comment * Add text for root selector text in middle of selector * Also avoid double-prefix of root selectors * Change how root selectors are transformed, inject the prefix after the root part of the selector * Remove hard-coded editor-styles-wrapper prefix from selectors * Update tests and fix double prefixing for root selectors * Fix test * Update comment * Update another test * Avoid transforming selectors that already contain .editor-styles-wrapper * Update ignored selectors to match behavior of postcss-prefix-wrap * Stop using snapshots * Add more tests * Fix typo * Add tests for regex ignores * Fix ropey root selectors and add tests * Use a tokenizer for root prefixing * Small optimization, Use a for loop to avoid unneccessary looping * Remove outdated comment * Update block library editor-styles-wrapper styles * Update comment * Add comment * Add more detail to nav block style comment * Also use same scope specificity in widget editor * Fix strings that look like regular expressions in ignoredSelectors * Reduce diff * Explain the function behavior further ---- Unlinked contributors: ktmn. Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: mrleemon <leemon@git.wordpress.org> Co-authored-by: apmeyer <apmeyer@git.wordpress.org> Co-authored-by: wongjn <wongjn@git.wordpress.org> --- package-lock.json | 45 ++- packages/block-editor/README.md | 11 +- packages/block-editor/package.json | 3 +- .../src/components/block-canvas/index.js | 10 +- .../src/components/editor-styles/index.js | 7 +- packages/block-editor/src/hooks/duotone.js | 4 - packages/block-editor/src/hooks/style.js | 5 +- .../block-editor/src/layouts/test/grid.js | 4 +- .../block-editor/src/layouts/test/utils.js | 14 +- packages/block-editor/src/layouts/utils.js | 10 +- .../__snapshots__/transform-styles.js.snap | 109 ------ .../src/utils/test/transform-styles.js | 309 +++++++++++++++--- .../src/utils/transform-styles/index.js | 153 +++++++-- packages/block-library/src/button/editor.scss | 5 - .../block-library/src/buttons/editor.scss | 6 - .../src/comments-pagination/editor.scss | 2 +- packages/block-library/src/cover/editor.scss | 5 - .../block-library/src/navigation/editor.scss | 6 +- .../src/query-pagination/editor.scss | 2 +- .../block-library/src/site-title/editor.scss | 4 - .../index.js | 2 +- test/unit/jest.config.js | 2 +- 22 files changed, 455 insertions(+), 263 deletions(-) delete mode 100644 packages/block-editor/src/utils/test/__snapshots__/transform-styles.js.snap diff --git a/package-lock.json b/package-lock.json index fe6c1dfa150dba..6bae0fa5859941 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40549,6 +40549,12 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/parsel-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/parsel-js/-/parsel-js-1.1.2.tgz", + "integrity": "sha512-D66DG2nKx4Yoq66TMEyCUHlR2STGqO7vsBrX7tgyS9cfQyO6XD5JyzOiflwmWN6a4wbUAqpmHqmrxlTQVGZcbA==", + "license": "MIT" + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -41752,6 +41758,15 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/postcss-prefix-selector": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/postcss-prefix-selector/-/postcss-prefix-selector-1.16.1.tgz", + "integrity": "sha512-Umxu+FvKMwlY6TyDzGFoSUnzW+NOfMBLyC1tAkIjgX+Z/qGspJeRjVC903D7mx7TuBpJlwti2ibXtWuA7fKMeQ==", + "license": "MIT", + "peerDependencies": { + "postcss": ">4 <9" + } + }, "node_modules/postcss-reduce-initial": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz", @@ -52226,8 +52241,9 @@ "diff": "^4.0.2", "fast-deep-equal": "^3.1.3", "memize": "^2.1.0", + "parsel-js": "^1.1.2", "postcss": "^8.4.21", - "postcss-prefixwrap": "^1.51.0", + "postcss-prefix-selector": "^1.16.0", "postcss-urlrebase": "^1.4.0", "react-autosize-textarea": "^7.1.0", "react-easy-crop": "^5.0.6", @@ -52242,15 +52258,6 @@ "react-dom": "^18.0.0" } }, - "packages/block-editor/node_modules/postcss-prefixwrap": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/postcss-prefixwrap/-/postcss-prefixwrap-1.51.0.tgz", - "integrity": "sha512-PuP4md5zFSY921dUcLShwSLv2YyyDec0dK9/puXl/lu7ZNvJ1U59+ZEFRMS67xwfNg5nIIlPXnAycPJlhA/Isw==", - "license": "MIT", - "peerDependencies": { - "postcss": "*" - } - }, "packages/block-editor/node_modules/postcss-urlrebase": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.4.0.tgz", @@ -67240,19 +67247,15 @@ "diff": "^4.0.2", "fast-deep-equal": "^3.1.3", "memize": "^2.1.0", + "parsel-js": "^1.1.2", "postcss": "^8.4.21", - "postcss-prefixwrap": "^1.51.0", + "postcss-prefix-selector": "^1.16.0", "postcss-urlrebase": "^1.4.0", "react-autosize-textarea": "^7.1.0", "react-easy-crop": "^5.0.6", "remove-accents": "^0.5.0" }, "dependencies": { - "postcss-prefixwrap": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/postcss-prefixwrap/-/postcss-prefixwrap-1.51.0.tgz", - "integrity": "sha512-PuP4md5zFSY921dUcLShwSLv2YyyDec0dK9/puXl/lu7ZNvJ1U59+ZEFRMS67xwfNg5nIIlPXnAycPJlhA/Isw==" - }, "postcss-urlrebase": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.4.0.tgz", @@ -86925,6 +86928,11 @@ } } }, + "parsel-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/parsel-js/-/parsel-js-1.1.2.tgz", + "integrity": "sha512-D66DG2nKx4Yoq66TMEyCUHlR2STGqO7vsBrX7tgyS9cfQyO6XD5JyzOiflwmWN6a4wbUAqpmHqmrxlTQVGZcbA==" + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -87801,6 +87809,11 @@ } } }, + "postcss-prefix-selector": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/postcss-prefix-selector/-/postcss-prefix-selector-1.16.1.tgz", + "integrity": "sha512-Umxu+FvKMwlY6TyDzGFoSUnzW+NOfMBLyC1tAkIjgX+Z/qGspJeRjVC903D7mx7TuBpJlwti2ibXtWuA7fKMeQ==" + }, "postcss-reduce-initial": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz", diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index c798015804b3e5..a474d1df7e56d0 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -811,21 +811,12 @@ _Parameters_ - _styles_ `EditorStyle[]`: CSS rules. - _wrapperSelector_ `string`: Wrapper selector. +- _transformOptions_ `TransformOptions`: Additional options for style transformation. _Returns_ - `Array`: converted rules. -_Type Definition_ - -- _EditorStyle_ `Object` - -_Properties_ - -- _css_ `string`: the CSS block(s), as a single string. -- _baseURL_ `?string`: the base URL to be used as the reference when rewritting urls. -- _ignoredSelectors_ `?string[]`: the selectors not to wrap. - ### Typewriter Ensures that the text selection keeps the same vertical distance from the viewport during keyboard events within this component. The vertical distance can vary. It is the last clicked or scrolled to position. diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 8002e165059e0e..640a5fc319330a 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -72,8 +72,9 @@ "diff": "^4.0.2", "fast-deep-equal": "^3.1.3", "memize": "^2.1.0", + "parsel-js": "^1.1.2", "postcss": "^8.4.21", - "postcss-prefixwrap": "^1.51.0", + "postcss-prefix-selector": "^1.16.0", "postcss-urlrebase": "^1.4.0", "react-autosize-textarea": "^7.1.0", "react-easy-crop": "^5.0.6", diff --git a/packages/block-editor/src/components/block-canvas/index.js b/packages/block-editor/src/components/block-canvas/index.js index c6a47b7b5533cc..9bad3ca22e95f7 100644 --- a/packages/block-editor/src/components/block-canvas/index.js +++ b/packages/block-editor/src/components/block-canvas/index.js @@ -16,6 +16,13 @@ import { useMouseMoveTypingReset } from '../observe-typing'; import { useBlockSelectionClearer } from '../block-selection-clearer'; import { useBlockCommands } from '../use-block-commands'; +// EditorStyles is a memoized component, so avoid passing a new +// object reference on each render. +const EDITOR_STYLE_TRANSFORM_OPTIONS = { + // Don't transform selectors that already specify `.editor-styles-wrapper`. + ignoredSelectors: [ /\.editor-styles-wrapper/gi ], +}; + export function ExperimentalBlockCanvas( { shouldIframe = true, height = '300px', @@ -38,7 +45,8 @@ export function ExperimentalBlockCanvas( { > <EditorStyles styles={ styles } - scope=".editor-styles-wrapper" + scope=":where(.editor-styles-wrapper)" + transformOptions={ EDITOR_STYLE_TRANSFORM_OPTIONS } /> <WritingFlow ref={ contentRef } diff --git a/packages/block-editor/src/components/editor-styles/index.js b/packages/block-editor/src/components/editor-styles/index.js index 34c4a90020e3be..a59ac310bcd303 100644 --- a/packages/block-editor/src/components/editor-styles/index.js +++ b/packages/block-editor/src/components/editor-styles/index.js @@ -67,7 +67,7 @@ function useDarkThemeBodyClassName( styles, scope ) { ); } -function EditorStyles( { styles, scope } ) { +function EditorStyles( { styles, scope, transformOptions } ) { const overrides = useSelect( ( select ) => unlock( select( blockEditorStore ) ).getStyleOverrides(), [] @@ -88,14 +88,15 @@ function EditorStyles( { styles, scope } ) { return [ transformStyles( _styles.filter( ( style ) => style?.css ), - scope + scope, + transformOptions ), _styles .filter( ( style ) => style.__unstableType === 'svgs' ) .map( ( style ) => style.assets ) .join( '' ), ]; - }, [ styles, overrides, scope ] ); + }, [ styles, overrides, scope, transformOptions ] ); return ( <> diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index 0a1d630d00de59..51130ccb9ec2a4 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -251,10 +251,6 @@ function useDuotoneStyles( { const selectors = duotoneSelector.split( ',' ); const selectorsScoped = selectors.map( ( selectorPart ) => { - // Extra .editor-styles-wrapper specificity is needed in the editor - // since we're not using inline styles to apply the filter. We need to - // override duotone applied by global styles and theme.json. - // Assuming the selector part is a subclass selector (not a tag name) // so we can prepend the filter id class. If we want to support elements // such as `img` or namespaces, we'll need to add a case for that here. diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index 4cd33350224541..2dcc19f424b2cf 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -381,10 +381,7 @@ function useBlockProps( { name, style } ) { useBlockProps ) }`; - // The .editor-styles-wrapper selector is required on elements styles. As it is - // added to all other editor styles, not providing it causes reset and global - // styles to override element styles because of higher specificity. - const baseElementSelector = `.editor-styles-wrapper .${ blockElementsContainerIdentifier }`; + const baseElementSelector = `.${ blockElementsContainerIdentifier }`; const blockElementStyles = style?.elements; const styles = useMemo( () => { diff --git a/packages/block-editor/src/layouts/test/grid.js b/packages/block-editor/src/layouts/test/grid.js index 79257ec0200be1..ab7b279aaae78c 100644 --- a/packages/block-editor/src/layouts/test/grid.js +++ b/packages/block-editor/src/layouts/test/grid.js @@ -5,7 +5,7 @@ import grid from '../grid'; describe( 'getLayoutStyle', () => { it( 'should return only `grid-template-columns` and `container-type` properties if no non-default params are provided', () => { - const expected = `.editor-styles-wrapper .my-container { grid-template-columns: repeat(auto-fill, minmax(min(12rem, 100%), 1fr)); container-type: inline-size; }`; + const expected = `.my-container { grid-template-columns: repeat(auto-fill, minmax(min(12rem, 100%), 1fr)); container-type: inline-size; }`; const result = grid.getLayoutStyle( { selector: '.my-container', @@ -19,7 +19,7 @@ describe( 'getLayoutStyle', () => { expect( result ).toBe( expected ); } ); it( 'should return only `grid-template-columns` if columnCount property is provided', () => { - const expected = `.editor-styles-wrapper .my-container { grid-template-columns: repeat(3, minmax(0, 1fr)); }`; + const expected = `.my-container { grid-template-columns: repeat(3, minmax(0, 1fr)); }`; const result = grid.getLayoutStyle( { selector: '.my-container', diff --git a/packages/block-editor/src/layouts/test/utils.js b/packages/block-editor/src/layouts/test/utils.js index a2a3ac644d7ba7..09cfef8f48f8ff 100644 --- a/packages/block-editor/src/layouts/test/utils.js +++ b/packages/block-editor/src/layouts/test/utils.js @@ -37,7 +37,7 @@ const layoutDefinitions = { describe( 'getBlockGapCSS', () => { it( 'should output default blockGap rules', () => { const expected = - '.editor-styles-wrapper .my-container > * { margin-block-start: 0; margin-block-end: 0; }.editor-styles-wrapper .my-container > * + * { margin-block-start: 3em; margin-block-end: 0; }'; + '.my-container > * { margin-block-start: 0; margin-block-end: 0; }.my-container > * + * { margin-block-start: 3em; margin-block-end: 0; }'; const result = getBlockGapCSS( '.my-container', @@ -50,7 +50,7 @@ describe( 'getBlockGapCSS', () => { } ); it( 'should output flex blockGap rules', () => { - const expected = '.editor-styles-wrapper .my-container { gap: 3em; }'; + const expected = '.my-container { gap: 3em; }'; const result = getBlockGapCSS( '.my-container', @@ -97,7 +97,7 @@ describe( 'getBlockGapCSS', () => { } ); it( 'should treat a blockGap string containing 0 as a valid value', () => { - const expected = '.editor-styles-wrapper .my-container { gap: 0; }'; + const expected = '.my-container { gap: 0; }'; const result = getBlockGapCSS( '.my-container', @@ -113,21 +113,19 @@ describe( 'getBlockGapCSS', () => { describe( 'appendSelectors', () => { it( 'should append a subselector without an appended selector', () => { expect( appendSelectors( '.original-selector' ) ).toBe( - '.editor-styles-wrapper .original-selector' + '.original-selector' ); } ); it( 'should append a subselector to a single selector', () => { expect( appendSelectors( '.original-selector', '.appended' ) ).toBe( - '.editor-styles-wrapper .original-selector .appended' + '.original-selector .appended' ); } ); it( 'should append a subselector to multiple selectors', () => { expect( appendSelectors( '.first-selector,.second-selector', '.appended' ) - ).toBe( - '.editor-styles-wrapper .first-selector .appended,.editor-styles-wrapper .second-selector .appended' - ); + ).toBe( '.first-selector .appended,.second-selector .appended' ); } ); } ); diff --git a/packages/block-editor/src/layouts/utils.js b/packages/block-editor/src/layouts/utils.js index 30280b8906e7a0..15a8d2cef83732 100644 --- a/packages/block-editor/src/layouts/utils.js +++ b/packages/block-editor/src/layouts/utils.js @@ -17,19 +17,11 @@ import { LAYOUT_DEFINITIONS } from './definitions'; * @return {string} - CSS selector. */ export function appendSelectors( selectors, append = '' ) { - // Ideally we shouldn't need the `.editor-styles-wrapper` increased specificity here - // The problem though is that we have a `.editor-styles-wrapper p { margin: reset; }` style - // it's used to reset the default margin added by wp-admin to paragraphs - // so we need this to be higher speficity otherwise, it won't be applied to paragraphs inside containers - // When the post editor is fully iframed, this extra classname could be removed. - return selectors .split( ',' ) .map( ( subselector ) => - `.editor-styles-wrapper ${ subselector }${ - append ? ` ${ append }` : '' - }` + `${ subselector }${ append ? ` ${ append }` : '' }` ) .join( ',' ); } diff --git a/packages/block-editor/src/utils/test/__snapshots__/transform-styles.js.snap b/packages/block-editor/src/utils/test/__snapshots__/transform-styles.js.snap deleted file mode 100644 index 9da07667d0a3e0..00000000000000 --- a/packages/block-editor/src/utils/test/__snapshots__/transform-styles.js.snap +++ /dev/null @@ -1,109 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`transformStyles URL rewrite should not replace absolute paths 1`] = ` -[ - "h1 { background: url(/images/test.png); }", -] -`; - -exports[`transformStyles URL rewrite should not replace remote paths 1`] = ` -[ - "h1 { background: url(http://wp.org/images/test.png); }", -] -`; - -exports[`transformStyles URL rewrite should replace complex relative paths 1`] = ` -[ - "h1 { background: url(http://wp-site.local/themes/gut/images/test.png); }", -] -`; - -exports[`transformStyles URL rewrite should rewrite relative paths 1`] = ` -[ - "h1 { background: url(http://wp-site.local/themes/gut/css/images/test.png); }", -] -`; - -exports[`transformStyles error handling should handle multiple instances of \`:root :where(body)\` 1`] = ` -[ - ".my-namespace { color: pink; } .my-namespace { color: orange; }", -] -`; - -exports[`transformStyles selector wrap should ignore font-face selectors 1`] = ` -[ - " - @font-face { - font-family: myFirstFont; - src: url(sansation_light.woff); - }", -] -`; - -exports[`transformStyles selector wrap should ignore keyframes 1`] = ` -[ - " - @keyframes edit-post__fade-in-animation { - from { - opacity: 0; - } - }", -] -`; - -exports[`transformStyles selector wrap should ignore selectors 1`] = ` -[ - ".my-namespace h1, body { color: red; }", -] -`; - -exports[`transformStyles selector wrap should not double wrap selectors 1`] = ` -[ - " .my-namespace h1, .my-namespace .red { color: red; }", -] -`; - -exports[`transformStyles selector wrap should replace :root selectors 1`] = ` -[ - " - .my-namespace { - --my-color: #ff0000; - }", -] -`; - -exports[`transformStyles selector wrap should replace root tags 1`] = ` -[ - ".my-namespace, .my-namespace h1 { color: red; }", -] -`; - -exports[`transformStyles selector wrap should wrap multiple selectors 1`] = ` -[ - ".my-namespace h1, .my-namespace h2 { color: red; }", -] -`; - -exports[`transformStyles selector wrap should wrap regular selectors 1`] = ` -[ - ".my-namespace h1 { color: red; }", -] -`; - -exports[`transformStyles selector wrap should wrap selectors inside container queries 1`] = ` -[ - " - @container (width > 400px) { - .my-namespace h1 { color: red; } - }", -] -`; - -exports[`transformStyles should not break with data urls 1`] = ` -[ - ".wp-block-group { - background-image: url("data:image/svg+xml,%3Csvg%3E.b%7Bclip-path:url(test);%7D%3C/svg%3E"); - color: red !important; - }", -] -`; diff --git a/packages/block-editor/src/utils/test/transform-styles.js b/packages/block-editor/src/utils/test/transform-styles.js index b0c6ca48deb355..3a68cc63c248ec 100644 --- a/packages/block-editor/src/utils/test/transform-styles.js +++ b/packages/block-editor/src/utils/test/transform-styles.js @@ -62,14 +62,16 @@ describe( 'transformStyles', () => { ], '.my-namespace' ); + const expected = + ':root :where(body) .my-namespace { color: pink; } :root :where(body) .my-namespace { color: orange; }'; - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ expected ] ); } ); } ); - describe( 'selector wrap', () => { - it( 'should wrap regular selectors', () => { - const input = `h1 { color: red; }`; + describe( 'root selectors', () => { + it( 'should append prefix after `:root :where(body)` selectors', () => { + const input = ':root :where(body) { color: red; }'; const output = transformStyles( [ { @@ -78,12 +80,13 @@ describe( 'transformStyles', () => { ], '.my-namespace' ); + const expected = ':root :where(body) .my-namespace { color: red; }'; - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ expected ] ); } ); - it( 'should wrap multiple selectors', () => { - const input = `h1, h2 { color: red; }`; + it( 'should append prefix after `:where(body)` selectors', () => { + const input = ':where(body) { color: red; }'; const output = transformStyles( [ { @@ -92,27 +95,142 @@ describe( 'transformStyles', () => { ], '.my-namespace' ); + const expected = ':where(body) .my-namespace { color: red; }'; - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ expected ] ); } ); - it( 'should ignore selectors', () => { - const input = `h1, body { color: red; }`; + it( 'should append prefix after body selectors', () => { + const input = `body { color: red; }`; + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + const expected = 'body .my-namespace { color: red; }'; + + expect( output ).toEqual( [ expected ] ); + } ); + + it( 'should append prefix after html selectors', () => { + const input = `html { color: red; }`; + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + const expected = 'html .my-namespace { color: red; }'; + + expect( output ).toEqual( [ expected ] ); + } ); + + it( 'should append prefix after html selectors, but before selectors that contain the word html', () => { + const input = `html [data-type="core/html"] .test { color: red; }`; + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + const expected = + 'html .my-namespace [data-type="core/html"] .test { color: red; }'; + + expect( output ).toEqual( [ expected ] ); + } ); + + it( 'should append prefix after :root selectors', () => { + const input = ':root { color: red; }'; + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + const expected = ':root .my-namespace { color: red; }'; + + expect( output ).toEqual( [ expected ] ); + } ); + + it( 'should append prefix after root selector when the selector contains a combinator without spaces around it', () => { + const input = ` + body> .some-style { color: red; } + body>.some-style { color: blue; } + body >.some-style { color: yellow; } + html body > .some-style { color: purple; } + html body.with-class+.some-style { color: silver; } + html body.with-class~.some-style { color: goldenrod; } + `; + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + const expected = ` + body .my-namespace>.some-style { color: red; } + body .my-namespace>.some-style { color: blue; } + body .my-namespace>.some-style { color: yellow; } + html body .my-namespace>.some-style { color: purple; } + html body.with-class .my-namespace+.some-style { color: silver; } + html body.with-class .my-namespace~.some-style { color: goldenrod; } + `; + + expect( output ).toEqual( [ expected ] ); + } ); + + it( 'appends after multiple root selectors', () => { + const input = ` + :root html[lang="th"] body { color: red; } + :root html[lang="th"] { color: orange; } + :root html[lang="th"] body .some-class { color: green; } + `; + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + const expected = ` + :root html[lang="th"] body .my-namespace { color: red; } + :root html[lang="th"] .my-namespace { color: orange; } + :root html[lang="th"] body .my-namespace .some-class { color: green; } + `; + + expect( output ).toEqual( [ expected ] ); + } ); + + it( 'should not double prefix a root selector', () => { + const input = 'body .my-namespace h1 { color: goldenrod; }'; const output = transformStyles( [ { css: input, - ignoredSelectors: [ 'body' ], }, ], '.my-namespace' ); - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ input ] ); } ); + } ); - it( 'should replace root tags', () => { - const input = `body, h1 { color: red; }`; + describe( 'selector wrap', () => { + it( 'should wrap regular selectors', () => { + const input = `h1 { color: red; }`; const output = transformStyles( [ { @@ -121,23 +239,56 @@ describe( 'transformStyles', () => { ], '.my-namespace' ); + const expected = '.my-namespace h1 { color: red; }'; - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ expected ] ); + } ); + + it( 'should wrap multiple selectors', () => { + const input = `h1, h2 { color: red; }`; + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + const expected = + '.my-namespace h1, .my-namespace h2 { color: red; }'; + + expect( output ).toEqual( [ expected ] ); + } ); + + it( 'should ignore ignored selectors', () => { + const input = `h1, body { color: red; }`; + const output = transformStyles( + [ + { + css: input, + ignoredSelectors: [ 'body' ], + }, + ], + '.my-namespace' + ); + const expected = '.my-namespace h1, body { color: red; }'; + + expect( output ).toEqual( [ expected ] ); } ); it( `should not try to replace 'body' in the middle of a classname`, () => { - const prefix = '.my-namespace'; - const input = `.has-body-text { color: red; }`; + const input = '.has-body-text { color: red; }'; const output = transformStyles( [ { css: input, }, ], - prefix + '.my-namespace' ); + const expected = '.my-namespace .has-body-text { color: red; }'; - expect( output ).toEqual( [ `${ prefix } ${ input }` ] ); + expect( output ).toEqual( [ expected ] ); } ); it( 'should ignore keyframes', () => { @@ -156,7 +307,7 @@ describe( 'transformStyles', () => { '.my-namespace' ); - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ input ] ); } ); it( 'should wrap selectors inside container queries', () => { @@ -172,8 +323,12 @@ describe( 'transformStyles', () => { ], '.my-namespace' ); + const expected = ` + @container (width > 400px) { + .my-namespace h1 { color: red; } + }`; - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ expected ] ); } ); it( 'should ignore font-face selectors', () => { @@ -191,14 +346,11 @@ describe( 'transformStyles', () => { '.my-namespace' ); - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ input ] ); } ); - it( 'should replace :root selectors', () => { - const input = ` - :root { - --my-color: #ff0000; - }`; + it( 'should not double wrap selectors', () => { + const input = ' .my-namespace h1, .red { color: red; }'; const output = transformStyles( [ { @@ -207,57 +359,111 @@ describe( 'transformStyles', () => { ], '.my-namespace' ); + const expected = ` .my-namespace h1, .my-namespace .red { color: red; }`; - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ expected ] ); } ); - it( 'should not double wrap selectors', () => { - const input = ` .my-namespace h1, .red { color: red; }`; + it( 'should not double wrap selectors when the prefix can be misinterpreted as a regular expression', () => { + const input = + ' :where(.editor-styles-wrapper) h1, .red { color: red; }'; + const output = transformStyles( + [ + { + css: input, + }, + ], + ':where(.editor-styles-wrapper)' + ); + const expected = ` :where(.editor-styles-wrapper) h1, :where(.editor-styles-wrapper) .red { color: red; }`; + + expect( output ).toEqual( [ expected ] ); + } ); + it( 'should allow specification of ignoredSelectors per css input', () => { + const input = '.ignored { color: red; }'; const output = transformStyles( [ + { + css: input, + ignoredSelectors: [ '.ignored' ], + }, + { + css: input, + ignoredSelectors: [ /^\.ignored/ ], + }, { css: input, }, ], - '.my-namespace' + '.not' ); + const expected1 = input; + const expected2 = input; + const expected3 = '.not .ignored { color: red; }'; - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ expected1, expected2, expected3 ] ); } ); - it( 'should not try to wrap items within `:where` selectors', () => { - const input = `:where(.wp-element-button:active, .wp-block-button__link:active) { color: blue; }`; - const prefix = '.my-namespace'; - const expected = [ `${ prefix } ${ input }` ]; + it( 'allows specification of ignoredSelectors globally via the transformOptions param', () => { + const input1 = '.ignored { color: red; }'; + const input2 = '.modified { color: red; }'; + const input3 = '.regexed { color: red; }'; + const output = transformStyles( + [ + { + css: input1, + }, + { + css: input2, + }, + { + css: input3, + }, + ], + '.prefix', + { ignoredSelectors: [ '.ignored', /\.regexed/ ] } + ); + expect( output ).toEqual( [ + input1, + '.prefix .modified { color: red; }', + input3, + ] ); + } ); + + it( 'should not try to wrap items within `:where` selectors', () => { + const input = + ':where(.wp-element-button:active, .wp-block-button__link:active) { color: blue; }'; const output = transformStyles( [ { css: input, }, ], - prefix + '.my-namespace' ); + const expected = + '.my-namespace :where(.wp-element-button:active, .wp-block-button__link:active) { color: blue; }'; - expect( output ).toEqual( expected ); + expect( output ).toEqual( [ expected ] ); } ); it( 'should not try to prefix pseudo elements on `:where` selectors', () => { - const input = `:where(.wp-element-button, .wp-block-button__link)::before { color: blue; }`; - const prefix = '.my-namespace'; - const expected = [ `${ prefix } ${ input }` ]; - + const input = + ':where(.wp-element-button, .wp-block-button__link)::before { color: blue; }'; const output = transformStyles( [ { css: input, }, ], - prefix + '.my-namespace' ); + const expected = + '.my-namespace :where(.wp-element-button, .wp-block-button__link)::before { color: blue; }'; - expect( output ).toEqual( expected ); + expect( output ).toEqual( [ expected ] ); } ); } ); @@ -274,7 +480,7 @@ describe( 'transformStyles', () => { }, ] ); - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ input ] ); } ); describe( 'URL rewrite', () => { @@ -286,8 +492,10 @@ describe( 'transformStyles', () => { baseURL: 'http://wp-site.local/themes/gut/css/', }, ] ); + const expected = + 'h1 { background: url(http://wp-site.local/themes/gut/css/images/test.png); }'; - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ expected ] ); } ); it( 'should replace complex relative paths', () => { @@ -298,8 +506,10 @@ describe( 'transformStyles', () => { baseURL: 'http://wp-site.local/themes/gut/css/', }, ] ); + const expected = + 'h1 { background: url(http://wp-site.local/themes/gut/images/test.png); }'; - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ expected ] ); } ); it( 'should not replace absolute paths', () => { @@ -310,8 +520,7 @@ describe( 'transformStyles', () => { baseURL: 'http://wp-site.local/themes/gut/css/', }, ] ); - - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ input ] ); } ); it( 'should not replace remote paths', () => { @@ -323,7 +532,7 @@ describe( 'transformStyles', () => { }, ] ); - expect( output ).toMatchSnapshot(); + expect( output ).toEqual( [ input ] ); } ); } ); } ); diff --git a/packages/block-editor/src/utils/transform-styles/index.js b/packages/block-editor/src/utils/transform-styles/index.js index 9d57de3fa3833c..936ebb016fa1b3 100644 --- a/packages/block-editor/src/utils/transform-styles/index.js +++ b/packages/block-editor/src/utils/transform-styles/index.js @@ -1,39 +1,142 @@ /** * External dependencies */ +import * as parsel from 'parsel-js'; import postcss, { CssSyntaxError } from 'postcss'; -import wrap from 'postcss-prefixwrap'; +import prefixSelector from 'postcss-prefix-selector'; import rebaseUrl from 'postcss-urlrebase'; const cacheByWrapperSelector = new Map(); +const ROOT_SELECTOR_TOKENS = [ + { type: 'type', content: 'body' }, + { type: 'type', content: 'html' }, + { type: 'pseudo-class', content: ':root' }, + { type: 'pseudo-class', content: ':where(body)' }, + { type: 'pseudo-class', content: ':where(:root)' }, + { type: 'pseudo-class', content: ':where(html)' }, +]; + +/** + * Prefixes root selectors in a way that ensures consistent specificity. + * This requires special handling, since prefixing a classname before + * html, body, or :root will generally result in an invalid selector. + * + * Some libraries will simply replace the root selector with the prefix + * instead, but this results in inconsistent specificity. + * + * This function instead inserts the prefix after the root tags but before + * any other part of the selector. This results in consistent specificity: + * - If a `:where()` selector is used for the prefix, all selectors output + * by `transformStyles` will have no specificity increase. + * - If a classname, id, or something else is used as the prefix, all selectors + * will have the same specificity bump when transformed. + * + * @param {string} prefix The prefix. + * @param {string} selector The selector. + * + * @return {string} The prefixed root selector. + */ +function prefixRootSelector( prefix, selector ) { + // Use a tokenizer, since regular expressions are unreliable. + const tokenized = parsel.tokenize( selector ); + + // Find the last token that contains a root selector by walking back + // through the tokens. + const lastRootIndex = tokenized.findLastIndex( ( { content, type } ) => { + return ROOT_SELECTOR_TOKENS.some( + ( rootSelector ) => + content === rootSelector.content && type === rootSelector.type + ); + } ); + + // Walk forwards to find the combinator after the last root. + // This is where the root ends and the rest of the selector begins, + // and the index to insert before. + // Doing it this way takes into account that a root selector like + // 'body' may have additional id/class/pseudo-class/attribute-selector + // parts chained to it, which is difficult to quantify using a regex. + let insertionPoint = -1; + for ( let i = lastRootIndex + 1; i < tokenized.length; i++ ) { + if ( tokenized[ i ].type === 'combinator' ) { + insertionPoint = i; + break; + } + } + + // Tokenize and insert the prefix with a ' ' combinator before it. + const tokenizedPrefix = parsel.tokenize( prefix ); + tokenized.splice( + // Insert at the insertion point, or the end. + insertionPoint === -1 ? tokenized.length : insertionPoint, + 0, + { + type: 'combinator', + content: ' ', + }, + ...tokenizedPrefix + ); + + return parsel.stringify( tokenized ); +} + function transformStyle( { css, ignoredSelectors = [], baseURL }, - wrapperSelector = '' + wrapperSelector = '', + transformOptions ) { - // When there is no wrapper selector or base URL, there is no need + // When there is no wrapper selector and no base URL, there is no need // to transform the CSS. This is most cases because in the default // iframed editor, no wrapping is needed, and not many styles // provide a base URL. if ( ! wrapperSelector && ! baseURL ) { return css; } - const postcssFriendlyCSS = css - .replace( /:root :where\(body\)/g, 'body' ) - .replace( /:where\(body\)/g, 'body' ); + try { + const excludedSelectors = [ + ...ignoredSelectors, + ...( transformOptions?.ignoredSelectors ?? [] ), + wrapperSelector, + ]; + return postcss( [ wrapperSelector && - wrap( wrapperSelector, { - ignoredSelectors: [ - ...ignoredSelectors, - wrapperSelector, - ], + prefixSelector( { + prefix: wrapperSelector, + transform( prefix, selector, prefixedSelector ) { + // For backwards compatibility, don't use the `exclude` option + // of postcss-prefix-selector, instead handle it here to match + // the behavior of the old library (postcss-prefix-wrap) that + // `transformStyle` previously used. + if ( + excludedSelectors.some( ( excludedSelector ) => + excludedSelector instanceof RegExp + ? selector.match( excludedSelector ) + : selector.includes( excludedSelector ) + ) + ) { + return selector; + } + + const hasRootSelector = ROOT_SELECTOR_TOKENS.some( + ( rootSelector ) => + selector.startsWith( rootSelector.content ) + ); + + // Reorganize root selectors such that the root part comes before the prefix, + // but the prefix still comes before the remaining part of the selector. + if ( hasRootSelector ) { + return prefixRootSelector( prefix, selector ); + } + + return prefixedSelector; + }, } ), baseURL && rebaseUrl( { rootUrl: baseURL } ), ].filter( Boolean ) - ).process( postcssFriendlyCSS, {} ).css; // use sync PostCSS API + ).process( css, {} ).css; // use sync PostCSS API } catch ( error ) { if ( error instanceof CssSyntaxError ) { // eslint-disable-next-line no-console @@ -54,18 +157,26 @@ function transformStyle( } /** - * Applies a series of CSS rule transforms to wrap selectors inside a given class and/or rewrite URLs depending on the parameters passed. - * * @typedef {Object} EditorStyle - * @property {string} css the CSS block(s), as a single string. - * @property {?string} baseURL the base URL to be used as the reference when rewritting urls. - * @property {?string[]} ignoredSelectors the selectors not to wrap. + * @property {string} css the CSS block(s), as a single string. + * @property {?string} baseURL the base URL to be used as the reference when rewritting urls. + * @property {?string[]} ignoredSelectors the selectors not to wrap. + */ + +/** + * @typedef {Object} TransformOptions + * @property {?string[]} ignoredSelectors the selectors not to wrap. + */ + +/** + * Applies a series of CSS rule transforms to wrap selectors inside a given class and/or rewrite URLs depending on the parameters passed. * - * @param {EditorStyle[]} styles CSS rules. - * @param {string} wrapperSelector Wrapper selector. + * @param {EditorStyle[]} styles CSS rules. + * @param {string} wrapperSelector Wrapper selector. + * @param {TransformOptions} transformOptions Additional options for style transformation. * @return {Array} converted rules. */ -const transformStyles = ( styles, wrapperSelector = '' ) => { +const transformStyles = ( styles, wrapperSelector = '', transformOptions ) => { let cache = cacheByWrapperSelector.get( wrapperSelector ); if ( ! cache ) { cache = new WeakMap(); @@ -74,7 +185,7 @@ const transformStyles = ( styles, wrapperSelector = '' ) => { return styles.map( ( style ) => { let css = cache.get( style ); if ( ! css ) { - css = transformStyle( style, wrapperSelector ); + css = transformStyle( style, wrapperSelector, transformOptions ); cache.set( style, css ); } return css; diff --git a/packages/block-library/src/button/editor.scss b/packages/block-library/src/button/editor.scss index 8c879c7e3b7c9e..8531f810e59e25 100644 --- a/packages/block-library/src/button/editor.scss +++ b/packages/block-library/src/button/editor.scss @@ -32,8 +32,3 @@ div[data-type="core/button"] { display: table; } - -.editor-styles-wrapper .wp-block-button[style*="text-decoration"] .wp-block-button__link { - text-decoration: inherit; -} - diff --git a/packages/block-library/src/buttons/editor.scss b/packages/block-library/src/buttons/editor.scss index b97c915671ad90..1aa775fd1d6483 100644 --- a/packages/block-library/src/buttons/editor.scss +++ b/packages/block-library/src/buttons/editor.scss @@ -52,12 +52,6 @@ $blocks-block__margin: 0.5em; margin-bottom: 0; } } - - .editor-styles-wrapper &.has-custom-font-size { - .wp-block-button__link { - font-size: inherit; - } - } } .wp-block[data-align="center"] > .wp-block-buttons { diff --git a/packages/block-library/src/comments-pagination/editor.scss b/packages/block-library/src/comments-pagination/editor.scss index dbf7e60ff65c06..a875c9e0ee21ce 100644 --- a/packages/block-library/src/comments-pagination/editor.scss +++ b/packages/block-library/src/comments-pagination/editor.scss @@ -5,7 +5,7 @@ $pagination-margin: 0.5em; justify-content: center; } -.editor-styles-wrapper { +:where(.editor-styles-wrapper) { .wp-block-comments-pagination { max-width: 100%; &.block-editor-block-list__layout { diff --git a/packages/block-library/src/cover/editor.scss b/packages/block-library/src/cover/editor.scss index 189d658e955c98..b92c401311beee 100644 --- a/packages/block-library/src/cover/editor.scss +++ b/packages/block-library/src/cover/editor.scss @@ -1,9 +1,4 @@ .wp-block-cover { - /* Extra specificity needed because the reset.css applied in the editor context is overriding this rule. */ - .editor-styles-wrapper & { - box-sizing: border-box; - } - // Override default cover styles // because we're not ready yet to show the cover block. &.is-placeholder { diff --git a/packages/block-library/src/navigation/editor.scss b/packages/block-library/src/navigation/editor.scss index 24480bb1592516..619b8dc6f0c7bd 100644 --- a/packages/block-library/src/navigation/editor.scss +++ b/packages/block-library/src/navigation/editor.scss @@ -5,6 +5,10 @@ // Undo default editor styles. // These need extra specificity. .editor-styles-wrapper .wp-block-navigation { + // Extra specificity is applied to do two things in classic themes: + // 1. Override the auto margin from alignment styles. This is needed as the `ul` element + // has a `wp-block` class applied to it, even though it's not a block. + // 2. Override list indentation that targets `ul,ol` elements. ul { margin-top: 0; margin-bottom: 0; @@ -478,7 +482,7 @@ $color-control-label-height: 20px; } } -// The iframe makes these rules a lot simpler. +// `body.editor-styles-wrapper` ensures this only applies to the iframed editor. body.editor-styles-wrapper .wp-block-navigation__responsive-container.is-menu-open { top: 0; right: 0; diff --git a/packages/block-library/src/query-pagination/editor.scss b/packages/block-library/src/query-pagination/editor.scss index 169f2b5ca72afb..0b755d155091f3 100644 --- a/packages/block-library/src/query-pagination/editor.scss +++ b/packages/block-library/src/query-pagination/editor.scss @@ -5,7 +5,7 @@ $pagination-margin: 0.5em; justify-content: center; } -.editor-styles-wrapper { +:where(.editor-styles-wrapper) { .wp-block-query-pagination { max-width: 100%; &.block-editor-block-list__layout { diff --git a/packages/block-library/src/site-title/editor.scss b/packages/block-library/src/site-title/editor.scss index ce83659170ff6f..372a85db2f4b13 100644 --- a/packages/block-library/src/site-title/editor.scss +++ b/packages/block-library/src/site-title/editor.scss @@ -2,7 +2,3 @@ padding: 1em 0; border: 1px dashed; } - -.editor-styles-wrapper :where(.wp-block-site-title a) { - color: inherit; -} diff --git a/packages/edit-widgets/src/components/widget-areas-block-editor-content/index.js b/packages/edit-widgets/src/components/widget-areas-block-editor-content/index.js index a9024da1f0074f..e1bd7a6b12f1e6 100644 --- a/packages/edit-widgets/src/components/widget-areas-block-editor-content/index.js +++ b/packages/edit-widgets/src/components/widget-areas-block-editor-content/index.js @@ -45,7 +45,7 @@ export default function WidgetAreasBlockEditorContent( { <KeyboardShortcuts /> <EditorStyles styles={ styles } - scope=".editor-styles-wrapper" + scope=":where(.editor-styles-wrapper)" /> <BlockSelectionClearer> <WritingFlow> diff --git a/test/unit/jest.config.js b/test/unit/jest.config.js index 4a3bb647a7879f..30f94485396432 100644 --- a/test/unit/jest.config.js +++ b/test/unit/jest.config.js @@ -40,7 +40,7 @@ module.exports = { '^.+\\.[jt]sx?$': '<rootDir>/test/unit/scripts/babel-transformer.js', }, transformIgnorePatterns: [ - '/node_modules/(?!(docker-compose|yaml|preact|@preact)/)', + '/node_modules/(?!(docker-compose|yaml|preact|@preact|parsel-js)/)', '\\.pnp\\.[^\\/]+$', ], snapshotSerializers: [ From 71e0fae484c5588b7b5101a3827a5265b653af9f Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:23:43 +1000 Subject: [PATCH 0562/1908] Typography: backport comment changes only (#64859) --- lib/block-supports/typography.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index c6ef59970de8c6..a4719b7bdd4099 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -449,7 +449,7 @@ function gutenberg_get_computed_fluid_typography_value( $args = array() ) { * @since 6.3.0 Using layout.wideSize as max viewport width, and logarithmic scale factor to calculate minimum font scale. * @since 6.4.0 Added configurable min and max viewport width values to the typography.fluid theme.json schema. * @since 6.6.0 Deprecated bool argument $should_use_fluid_typography. - * @since 6.7.0 Enabled individual block fluid typography settings overrides. + * @since 6.7.0 Font size presets can enable fluid typography individually, even if it’s disabled globally. * * @param array $preset { * Required. fontSizes preset value as seen in theme.json. @@ -509,7 +509,6 @@ function gutenberg_get_typography_font_size_value( $preset, $settings = array() return $preset['size']; } - // $typography_settings['fluid'] can be a bool or an array. Normalize to array. $fluid_settings = isset( $typography_settings['fluid'] ) ? $typography_settings['fluid'] : array(); $layout_settings = isset( $settings['layout'] ) ? $settings['layout'] : array(); From 8c43856222664f4285ff0649937e14f306dac132 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:17:37 +0900 Subject: [PATCH 0563/1908] Video Block: fix layout issue (#64834) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/block-library/src/video/editor.scss | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/block-library/src/video/editor.scss b/packages/block-library/src/video/editor.scss index 792939356b1de9..922c6dfd9d04a9 100644 --- a/packages/block-library/src/video/editor.scss +++ b/packages/block-library/src/video/editor.scss @@ -85,7 +85,6 @@ .block-library-video-tracks-editor > .components-popover__content { width: 360px; - padding: 0; } .block-library-video-tracks-editor__track-list, @@ -94,10 +93,3 @@ padding: 0; } } - -.block-library-video-tracks-editor__single-track-editor, -.block-library-video-tracks-editor__track-list, -.block-library-video-tracks-editor__add-tracks-container { - padding: $grid-unit-15; -} - From 59057e823ec67f0a8011ce18e785aa037b146320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 28 Aug 2024 09:49:41 +0200 Subject: [PATCH 0564/1908] DataViews List layout: update broken styles (#64837) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/dataviews/src/dataviews-layouts/list/style.scss | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/dataviews/src/dataviews-layouts/list/style.scss b/packages/dataviews/src/dataviews-layouts/list/style.scss index 5bbe76f87ca5b8..7344af6c3d1e82 100644 --- a/packages/dataviews/src/dataviews-layouts/list/style.scss +++ b/packages/dataviews/src/dataviews-layouts/list/style.scss @@ -1,3 +1,7 @@ +ul.dataviews-view-list { + list-style-type: none; +} + .dataviews-view-list { margin: 0 0 auto; @@ -153,8 +157,8 @@ } .dataviews-view-list__media-placeholder { - min-width: $grid-unit-40; - height: $grid-unit-40; + width: $grid-unit-05 * 13; + height: $grid-unit-05 * 13; background-color: $gray-200; } From bf485356d5196ca2636bb4410ec9ac1669fac4d3 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 28 Aug 2024 18:17:42 +0900 Subject: [PATCH 0565/1908] Video Block: Remove custom CSS code for placeholder style (#64861) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/block-library/src/video/edit.js | 34 +++++++++--------- packages/block-library/src/video/editor.scss | 37 -------------------- 2 files changed, 17 insertions(+), 54 deletions(-) diff --git a/packages/block-library/src/video/edit.js b/packages/block-library/src/video/edit.js index 05dbcc58e8b8e5..63f633a41adf94 100644 --- a/packages/block-library/src/video/edit.js +++ b/packages/block-library/src/video/edit.js @@ -42,23 +42,6 @@ import TracksEditor from './tracks-editor'; import Tracks from './tracks'; import { Caption } from '../utils/caption'; -// Much of this description is duplicated from MediaPlaceholder. -const placeholder = ( content ) => { - return ( - <Placeholder - className="block-editor-media-placeholder" - withIllustration - icon={ icon } - label={ __( 'Video' ) } - instructions={ __( - 'Upload a video file, pick one from your media library, or add one with a URL.' - ) } - > - { content } - </Placeholder> - ); -}; - const ALLOWED_MEDIA_TYPES = [ 'video' ]; const VIDEO_POSTER_ALLOWED_MEDIA_TYPES = [ 'image' ]; @@ -149,6 +132,23 @@ function VideoEdit( { createErrorNotice( message, { type: 'snackbar' } ); } + // Much of this description is duplicated from MediaPlaceholder. + const placeholder = ( content ) => { + return ( + <Placeholder + className="block-editor-media-placeholder" + withIllustration={ ! isSingleSelected } + icon={ icon } + label={ __( 'Video' ) } + instructions={ __( + 'Upload a video file, pick one from your media library, or add one with a URL.' + ) } + > + { content } + </Placeholder> + ); + }; + const classes = clsx( className, { 'is-transient': !! temporaryURL, } ); diff --git a/packages/block-library/src/video/editor.scss b/packages/block-library/src/video/editor.scss index 922c6dfd9d04a9..dd50ecc6c066fd 100644 --- a/packages/block-library/src/video/editor.scss +++ b/packages/block-library/src/video/editor.scss @@ -1,40 +1,3 @@ -// Provide special styling for the placeholder. -// @todo this particular minimal style of placeholder could be componentized further. -.wp-block-video.wp-block-video { - // Show Placeholder style on-select. - &.is-selected .components-placeholder { - // Block UI appearance. - color: $gray-900; - background-color: $white; - box-shadow: inset 0 0 0 $border-width $gray-900; - border: none; - - // @todo this should eventually be overridden by a custom border-radius set in the inspector. - border-radius: $radius-block-ui; - - > svg { - opacity: 0; - } - - .components-placeholder__illustration { - display: none; - } - - &::before { - opacity: 0; - } - } - - // Remove the transition while we still have a legacy placeholder style. - // Otherwise the content jumps between the 1px placeholder border, and any inherited custom - // parent border that may get applied when you deselect. - .components-placeholder__label, - .components-placeholder__instructions, - .components-button { - transition: none; - } -} - .wp-block[data-align="center"] > .wp-block-video { text-align: center; } From b22314d36d90dc69002362e5e7a79a9b04e6508c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Gomes?= <mail@sgomes.com> Date: Wed, 28 Aug 2024 10:21:43 +0100 Subject: [PATCH 0566/1908] Post publish upload media dialog: handle upload errors (#64823) * Post publish upload media dialog: handle upload errors * Change text color * Drop unused classname * Add catch-all for any errors during upload * Remove redundant setHadUploadError call --- .../src/components/post-publish-panel/maybe-upload-media.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/editor/src/components/post-publish-panel/maybe-upload-media.js b/packages/editor/src/components/post-publish-panel/maybe-upload-media.js index d3e861ee7c29d3..b090e25cd4dbff 100644 --- a/packages/editor/src/components/post-publish-panel/maybe-upload-media.js +++ b/packages/editor/src/components/post-publish-panel/maybe-upload-media.js @@ -61,6 +61,7 @@ function Image( block ) { export default function PostFormatPanel() { const [ isUploading, setIsUploading ] = useState( false ); const [ isAnimating, setIsAnimating ] = useState( false ); + const [ hadUploadError, setHadUploadError ] = useState( false ); const { editorBlocks, mediaUpload } = useSelect( ( select ) => ( { editorBlocks: select( blockEditorStore ).getBlocks(), @@ -89,6 +90,7 @@ export default function PostFormatPanel() { function uploadImages() { setIsUploading( true ); + setHadUploadError( false ); Promise.all( externalImages.map( ( image ) => window @@ -119,6 +121,9 @@ export default function PostFormatPanel() { } ); } ).then( () => setIsAnimating( true ) ) ) + .catch( () => { + setHadUploadError( true ); + } ) ) ).finally( () => { setIsUploading( false ); @@ -159,6 +164,7 @@ export default function PostFormatPanel() { </Button> ) } </div> + { hadUploadError && <p>{ __( 'Upload failed, try again.' ) }</p> } </PanelBody> ); } From 8236cf69cc1b0daac41a111334e57af86e294ac5 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Wed, 28 Aug 2024 11:59:21 +0200 Subject: [PATCH 0567/1908] Move bulk actions menu to the Footer, consolidate with floating toolbar and total items display (#64268) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/base-styles/_z-index.scss | 6 +- .../dataviews-bulk-actions-toolbar/index.tsx | 288 ----------- .../dataviews-bulk-actions-toolbar/style.scss | 45 -- .../dataviews-bulk-actions/index.tsx | 472 ++++++++++-------- .../dataviews-bulk-actions/style.scss | 13 +- .../src/components/dataviews-footer/index.tsx | 50 ++ .../components/dataviews-footer/style.scss | 40 ++ .../components/dataviews-pagination/index.tsx | 4 +- .../dataviews-pagination/style.scss | 19 - .../src/components/dataviews/index.tsx | 8 +- .../src/dataviews-layouts/table/index.tsx | 62 +-- packages/dataviews/src/style.scss | 2 +- .../src/components/page-patterns/style.scss | 4 - .../src/dataviews/actions/export-pattern.tsx | 2 + .../actions/permanently-delete-post.tsx | 2 + 15 files changed, 376 insertions(+), 641 deletions(-) delete mode 100644 packages/dataviews/src/components/dataviews-bulk-actions-toolbar/index.tsx delete mode 100644 packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss create mode 100644 packages/dataviews/src/components/dataviews-footer/index.tsx create mode 100644 packages/dataviews/src/components/dataviews-footer/style.scss diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index 4d5f22e02fa7d1..cc99df6dbeaafc 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -131,7 +131,6 @@ $z-layers: ( ".block-editor-template-part__selection-modal": 1000001, ".block-editor-block-rename-modal": 1000001, ".edit-site-list__rename-modal": 1000001, - ".dataviews-bulk-actions__modal": 1000001, ".dataviews-action-modal": 1000001, ".editor-action-modal": 1000001, ".editor-post-template__swap-template-modal": 1000001, @@ -194,7 +193,6 @@ $z-layers: ( // Site editor layout ".edit-site-page-header": 2, ".edit-site-page-content": 1, - ".edit-site-patterns__dataviews-list-pagination": 2, ".edit-site-templates__dataviews-list-pagination": 2, ".edit-site-layout__canvas-container": 2, ".edit-site-layout__sidebar": 1, @@ -211,8 +209,8 @@ $z-layers: ( // Ensure selection checkbox stays above the preview field. ".dataviews-view-grid__card .dataviews-selection-checkbox": 1, - // Ensure quick actions toolbar appear above pagination - ".dataviews-bulk-actions-toolbar": 2, + // Ensure footer stays above the preview field. + ".dataviews-footer": 2, ); @function z-index( $key ) { diff --git a/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/index.tsx b/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/index.tsx deleted file mode 100644 index 09e9d5f9df8120..00000000000000 --- a/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/index.tsx +++ /dev/null @@ -1,288 +0,0 @@ -/** - * WordPress dependencies - */ -import { - ToolbarButton, - Toolbar, - ToolbarGroup, - __unstableMotion as motion, - __unstableAnimatePresence as AnimatePresence, -} from '@wordpress/components'; -import { useMemo, useState, useRef, useContext } from '@wordpress/element'; -import { _n, sprintf, __ } from '@wordpress/i18n'; -import { closeSmall } from '@wordpress/icons'; -import { useReducedMotion } from '@wordpress/compose'; -import { useRegistry } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import { useSomeItemHasAPossibleBulkAction } from '../dataviews-bulk-actions'; -import DataViewsContext from '../dataviews-context'; -import { ActionWithModal } from '../dataviews-item-actions'; -import { LAYOUT_GRID, LAYOUT_TABLE } from '../../constants'; -import type { Action } from '../../types'; -import type { ActionTriggerProps } from '../dataviews-item-actions'; -import type { SetSelection } from '../../private-types'; - -interface ActionButtonProps< Item > { - action: Action< Item >; - selectedItems: Item[]; - actionInProgress: string | null; - setActionInProgress: ( actionId: string | null ) => void; -} - -interface ToolbarContentProps< Item > { - selection: string[]; - actionsToShow: Action< Item >[]; - selectedItems: Item[]; - onChangeSelection: SetSelection; -} - -const SNACKBAR_VARIANTS = { - init: { - bottom: -48, - }, - open: { - bottom: 24, - transition: { - bottom: { type: 'tween', duration: 0.2, ease: [ 0, 0, 0.2, 1 ] }, - }, - }, - exit: { - opacity: 0, - bottom: 24, - transition: { - opacity: { type: 'tween', duration: 0.2, ease: [ 0, 0, 0.2, 1 ] }, - }, - }, -}; - -function ActionTrigger< Item >( { - action, - onClick, - isBusy, - items, -}: ActionTriggerProps< Item > ) { - const label = - typeof action.label === 'string' ? action.label : action.label( items ); - return ( - <ToolbarButton - disabled={ isBusy } - label={ label } - icon={ action.icon } - isDestructive={ action.isDestructive } - size="compact" - onClick={ onClick } - isBusy={ isBusy } - tooltipPosition="top" - /> - ); -} - -const EMPTY_ARRAY: [] = []; - -function ActionButton< Item >( { - action, - selectedItems, - actionInProgress, - setActionInProgress, -}: ActionButtonProps< Item > ) { - const registry = useRegistry(); - const selectedEligibleItems = useMemo( () => { - return selectedItems.filter( ( item ) => { - return ! action.isEligible || action.isEligible( item ); - } ); - }, [ action, selectedItems ] ); - if ( 'RenderModal' in action ) { - return ( - <ActionWithModal - key={ action.id } - action={ action } - items={ selectedEligibleItems } - ActionTrigger={ ActionTrigger } - /> - ); - } - return ( - <ActionTrigger - key={ action.id } - action={ action } - onClick={ () => { - setActionInProgress( action.id ); - action.callback( selectedItems, { - registry, - } ); - } } - items={ selectedEligibleItems } - isBusy={ actionInProgress === action.id } - /> - ); -} - -function renderToolbarContent< Item >( - selection: string[], - actionsToShow: Action< Item >[], - selectedItems: Item[], - actionInProgress: string | null, - setActionInProgress: ( actionId: string | null ) => void, - onChangeSelection: SetSelection -) { - return ( - <> - <ToolbarGroup> - <div className="dataviews-bulk-actions-toolbar__selection-count"> - { selection.length === 1 - ? __( '1 item selected' ) - : sprintf( - // translators: %s: Total number of selected items. - _n( - '%s item selected', - '%s items selected', - selection.length - ), - selection.length - ) } - </div> - </ToolbarGroup> - <ToolbarGroup> - { actionsToShow.map( ( action ) => { - return ( - <ActionButton - key={ action.id } - action={ action } - selectedItems={ selectedItems } - actionInProgress={ actionInProgress } - setActionInProgress={ setActionInProgress } - /> - ); - } ) } - </ToolbarGroup> - <ToolbarGroup> - <ToolbarButton - icon={ closeSmall } - showTooltip - tooltipPosition="top" - label={ __( 'Cancel' ) } - disabled={ !! actionInProgress } - onClick={ () => { - onChangeSelection( EMPTY_ARRAY ); - } } - /> - </ToolbarGroup> - </> - ); -} - -function ToolbarContent< Item >( { - selection, - actionsToShow, - selectedItems, - onChangeSelection, -}: ToolbarContentProps< Item > ) { - const [ actionInProgress, setActionInProgress ] = useState< string | null >( - null - ); - const buttonsRef = useRef< JSX.Element | null >( null ); - if ( ! actionInProgress ) { - if ( buttonsRef.current ) { - buttonsRef.current = null; - } - return renderToolbarContent( - selection, - actionsToShow, - selectedItems, - actionInProgress, - setActionInProgress, - onChangeSelection - ); - } else if ( ! buttonsRef.current ) { - buttonsRef.current = renderToolbarContent( - selection, - actionsToShow, - selectedItems, - actionInProgress, - setActionInProgress, - onChangeSelection - ); - } - return buttonsRef.current; -} - -function _BulkActionsToolbar() { - const { - data, - selection, - actions = EMPTY_ARRAY, - onChangeSelection, - getItemId, - } = useContext( DataViewsContext ); - const isReducedMotion = useReducedMotion(); - const selectedItems = useMemo( () => { - return data.filter( ( item ) => - selection.includes( getItemId( item ) ) - ); - }, [ selection, data, getItemId ] ); - - const actionsToShow = useMemo( - () => - actions.filter( ( action ) => { - return ( - action.supportsBulk && - action.icon && - selectedItems.some( - ( item ) => - ! action.isEligible || action.isEligible( item ) - ) - ); - } ), - [ actions, selectedItems ] - ); - - if ( - ( selection && selection.length === 0 ) || - actionsToShow.length === 0 - ) { - return null; - } - - return ( - <AnimatePresence> - <motion.div - layout={ ! isReducedMotion } // See https://www.framer.com/docs/animation/#layout-animations - initial="init" - animate="open" - exit="exit" - variants={ isReducedMotion ? undefined : SNACKBAR_VARIANTS } - className="dataviews-bulk-actions-toolbar" - > - <Toolbar label={ __( 'Bulk actions' ) }> - <div className="dataviews-bulk-actions-toolbar__wrapper"> - <ToolbarContent - selection={ selection } - actionsToShow={ actionsToShow } - selectedItems={ selectedItems } - onChangeSelection={ onChangeSelection } - /> - </div> - </Toolbar> - </motion.div> - </AnimatePresence> - ); -} - -export default function BulkActionsToolbar() { - const { data, actions = [], view } = useContext( DataViewsContext ); - const hasPossibleBulkAction = useSomeItemHasAPossibleBulkAction( - actions, - data - ); - if ( - ! [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) || - ! hasPossibleBulkAction - ) { - return null; - } - - return <_BulkActionsToolbar />; -} diff --git a/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss b/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss deleted file mode 100644 index 5672234d8cbbb7..00000000000000 --- a/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss +++ /dev/null @@ -1,45 +0,0 @@ -.dataviews-bulk-actions-toolbar { - position: sticky; - display: flex; - flex-direction: column; - align-content: center; - flex-wrap: wrap; - width: fit-content; - margin-left: auto; - margin-right: auto; - bottom: $grid-unit-30; - z-index: z-index(".dataviews-bulk-actions-toolbar"); - - .components-accessible-toolbar { - border-color: $gray-300; - box-shadow: $elevation-x-small; - - .components-toolbar-group { - border-color: $gray-200; - - &:last-child { - border: 0; - } - } - } - - .dataviews-bulk-actions-toolbar__selection-count { - display: flex; - align-items: center; - margin: 0 $grid-unit-10 0 $grid-unit-10; - } -} - -.dataviews-bulk-actions-toolbar__wrapper { - display: flex; - flex-grow: 1; - width: 100%; - - .components-toolbar-group { - align-items: center; - } - - .components-button.is-busy { - max-height: $button-size; - } -} diff --git a/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx b/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx index 279126c597bc82..5eb9c5e1b6a4d0 100644 --- a/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx +++ b/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx @@ -2,42 +2,23 @@ * WordPress dependencies */ import { - privateApis as componentsPrivateApis, Button, - Modal, + CheckboxControl, + __experimentalHStack as HStack, } from '@wordpress/components'; import { __, sprintf, _n } from '@wordpress/i18n'; -import { useMemo, useState, useCallback, useContext } from '@wordpress/element'; +import { useMemo, useState, useRef, useContext } from '@wordpress/element'; import { useRegistry } from '@wordpress/data'; +import { closeSmall } from '@wordpress/icons'; /** * Internal dependencies */ import DataViewsContext from '../dataviews-context'; -import { LAYOUT_TABLE, LAYOUT_GRID } from '../../constants'; -import { unlock } from '../../lock-unlock'; -import type { Action, ActionModal } from '../../types'; - -const { DropdownMenuV2 } = unlock( componentsPrivateApis ); - -interface ActionWithModalProps< Item > { - action: ActionModal< Item >; - selectedItems: Item[]; - setActionWithModal: ( action?: ActionModal< Item > ) => void; - onMenuOpenChange: ( isOpen: boolean ) => void; -} - -interface BulkActionsItemProps< Item > { - action: Action< Item >; - selectedItems: Item[]; - setActionWithModal: ( action?: ActionModal< Item > ) => void; -} - -interface ActionsMenuGroupProps< Item > { - actions: Action< Item >[]; - selectedItems: Item[]; - setActionWithModal: ( action?: ActionModal< Item > ) => void; -} +import { ActionWithModal } from '../dataviews-item-actions'; +import type { Action } from '../../types'; +import type { SetSelection } from '../../private-types'; +import type { ActionTriggerProps } from '../dataviews-item-actions'; export function useHasAPossibleBulkAction< Item >( actions: Action< Item >[], @@ -69,126 +50,231 @@ export function useSomeItemHasAPossibleBulkAction< Item >( }, [ actions, data ] ); } -function ActionWithModal< Item >( { - action, - selectedItems, - setActionWithModal, - onMenuOpenChange, -}: ActionWithModalProps< Item > ) { - const eligibleItems = useMemo( () => { - return selectedItems.filter( - ( item ) => ! action.isEligible || action.isEligible( item ) - ); - }, [ action, selectedItems ] ); - const { RenderModal, hideModalHeader } = action; - const onCloseModal = useCallback( () => { - setActionWithModal( undefined ); - }, [ setActionWithModal ] ); +interface BulkSelectionCheckboxProps< Item > { + selection: string[]; + onChangeSelection: SetSelection; + data: Item[]; + actions: Action< Item >[]; + getItemId: ( item: Item ) => string; +} - if ( ! eligibleItems.length ) { - return null; - } +export function BulkSelectionCheckbox< Item >( { + selection, + onChangeSelection, + data, + actions, + getItemId, +}: BulkSelectionCheckboxProps< Item > ) { + const selectableItems = useMemo( () => { + return data.filter( ( item ) => { + return actions.some( + ( action ) => + action.supportsBulk && + ( ! action.isEligible || action.isEligible( item ) ) + ); + } ); + }, [ data, actions ] ); + const selectedItems = data.filter( + ( item ) => + selection.includes( getItemId( item ) ) && + selectableItems.includes( item ) + ); + const areAllSelected = selectedItems.length === selectableItems.length; + return ( + <CheckboxControl + className="dataviews-view-table-selection-checkbox" + __nextHasNoMarginBottom + checked={ areAllSelected } + indeterminate={ ! areAllSelected && !! selectedItems.length } + onChange={ () => { + if ( areAllSelected ) { + onChangeSelection( [] ); + } else { + onChangeSelection( + selectableItems.map( ( item ) => getItemId( item ) ) + ); + } + } } + aria-label={ + areAllSelected ? __( 'Deselect all' ) : __( 'Select all' ) + } + /> + ); +} + +interface ActionButtonProps< Item > { + action: Action< Item >; + selectedItems: Item[]; + actionInProgress: string | null; + setActionInProgress: ( actionId: string | null ) => void; +} + +interface ToolbarContentProps< Item > { + selection: string[]; + onChangeSelection: SetSelection; + data: Item[]; + actions: Action< Item >[]; + getItemId: ( item: Item ) => string; +} +function ActionTrigger< Item >( { + action, + onClick, + isBusy, + items, +}: ActionTriggerProps< Item > ) { const label = - typeof action.label === 'string' - ? action.label - : action.label( selectedItems ); + typeof action.label === 'string' ? action.label : action.label( items ); return ( - <Modal - title={ ! hideModalHeader ? label : undefined } - __experimentalHideHeader={ !! hideModalHeader } - onRequestClose={ onCloseModal } - overlayClassName="dataviews-bulk-actions__modal" - > - <RenderModal - items={ eligibleItems } - closeModal={ onCloseModal } - onActionPerformed={ () => onMenuOpenChange( false ) } - /> - </Modal> + <Button + disabled={ isBusy } + accessibleWhenDisabled + label={ label } + icon={ action.icon } + isDestructive={ action.isDestructive } + size="compact" + onClick={ onClick } + isBusy={ isBusy } + tooltipPosition="top" + /> ); } -function BulkActionItem< Item >( { +const EMPTY_ARRAY: [] = []; + +function ActionButton< Item >( { action, selectedItems, - setActionWithModal, -}: BulkActionsItemProps< Item > ) { + actionInProgress, + setActionInProgress, +}: ActionButtonProps< Item > ) { const registry = useRegistry(); - const eligibleItems = useMemo( () => { - return selectedItems.filter( - ( item ) => ! action.isEligible || action.isEligible( item ) - ); + const selectedEligibleItems = useMemo( () => { + return selectedItems.filter( ( item ) => { + return ! action.isEligible || action.isEligible( item ); + } ); }, [ action, selectedItems ] ); - - const shouldShowModal = 'RenderModal' in action; - + if ( 'RenderModal' in action ) { + return ( + <ActionWithModal + key={ action.id } + action={ action } + items={ selectedEligibleItems } + ActionTrigger={ ActionTrigger } + /> + ); + } return ( - <DropdownMenuV2.Item + <ActionTrigger key={ action.id } - hideOnClick={ ! shouldShowModal } + action={ action } onClick={ async () => { - if ( shouldShowModal ) { - setActionWithModal( action ); - } else { - action.callback( eligibleItems, { registry } ); - } + setActionInProgress( action.id ); + await action.callback( selectedItems, { + registry, + } ); + setActionInProgress( null ); } } - suffix={ eligibleItems.length } - > - { action.label } - </DropdownMenuV2.Item> + items={ selectedEligibleItems } + isBusy={ actionInProgress === action.id } + /> ); } -function ActionsMenuGroup< Item >( { - actions, - selectedItems, - setActionWithModal, -}: ActionsMenuGroupProps< Item > ) { - const elligibleActions = useMemo( () => { - return actions.filter( ( action ) => { - return selectedItems.some( - ( item ) => ! action.isEligible || action.isEligible( item ) - ); - } ); - }, [ actions, selectedItems ] ); - if ( ! elligibleActions.length ) { - return null; - } +function renderFooterContent< Item >( + data: Item[], + actions: Action< Item >[], + getItemId: ( item: Item ) => string, + selection: string[], + actionsToShow: Action< Item >[], + selectedItems: Item[], + actionInProgress: string | null, + setActionInProgress: ( actionId: string | null ) => void, + onChangeSelection: SetSelection +) { + const message = + selectedItems.length > 0 + ? sprintf( + /* translators: %d: number of items. */ + _n( + '%d Item selected', + '%d Items selected', + selectedItems.length + ), + selectedItems.length + ) + : sprintf( + /* translators: %d: number of items. */ + _n( '%d Item', '%d Items', data.length ), + data.length + ); return ( - <> - <DropdownMenuV2.Group> - { elligibleActions.map( ( action ) => ( - <BulkActionItem - key={ action.id } - action={ action } - selectedItems={ selectedItems } - setActionWithModal={ setActionWithModal } + <HStack + expanded={ false } + className="dataviews-bulk-actions-footer__container" + spacing={ 3 } + > + <BulkSelectionCheckbox + selection={ selection } + onChangeSelection={ onChangeSelection } + data={ data } + actions={ actions } + getItemId={ getItemId } + /> + <span className="dataviews-bulk-actions-footer__item-count"> + { message } + </span> + <HStack + className="dataviews-bulk-actions-footer__action-buttons" + expanded={ false } + spacing={ 1 } + > + { actionsToShow.map( ( action ) => { + return ( + <ActionButton + key={ action.id } + action={ action } + selectedItems={ selectedItems } + actionInProgress={ actionInProgress } + setActionInProgress={ setActionInProgress } + /> + ); + } ) } + { selectedItems.length > 0 && ( + <Button + icon={ closeSmall } + showTooltip + tooltipPosition="top" + size="compact" + label={ __( 'Cancel' ) } + disabled={ !! actionInProgress } + accessibleWhenDisabled={ false } + onClick={ () => { + onChangeSelection( EMPTY_ARRAY ); + } } /> - ) ) } - </DropdownMenuV2.Group> - <DropdownMenuV2.Separator /> - </> + ) } + </HStack> + </HStack> ); } -function _BulkActions() { - const { - data, - actions = [], - selection, - onChangeSelection, - getItemId, - } = useContext( DataViewsContext ); +function FooterContent< Item >( { + selection, + actions, + onChangeSelection, + data, + getItemId, +}: ToolbarContentProps< Item > ) { + const [ actionInProgress, setActionInProgress ] = useState< string | null >( + null + ); + const footerContent = useRef< JSX.Element | null >( null ); + const bulkActions = useMemo( () => actions.filter( ( action ) => action.supportsBulk ), [ actions ] ); - const [ isMenuOpen, onMenuOpenChange ] = useState( false ); - const [ actionWithModal, setActionWithModal ] = useState< - ActionModal< any > | undefined - >(); const selectableItems = useMemo( () => { return data.filter( ( item ) => { return bulkActions.some( @@ -197,8 +283,6 @@ function _BulkActions() { } ); }, [ data, bulkActions ] ); - const numberSelectableItems = selectableItems.length; - const selectedItems = useMemo( () => { return data.filter( ( item ) => @@ -207,94 +291,66 @@ function _BulkActions() { ); }, [ selection, data, getItemId, selectableItems ] ); - const areAllSelected = selectedItems.length === numberSelectableItems; - - if ( bulkActions.length === 0 ) { - return null; - } - return ( - <> - <DropdownMenuV2 - open={ isMenuOpen } - onOpenChange={ onMenuOpenChange } - label={ __( 'Bulk actions' ) } - style={ { minWidth: '240px' } } - trigger={ - <Button - className="dataviews-bulk-actions__edit-button" - __next40pxDefaultSize - variant="tertiary" - size="compact" - > - { selectedItems.length - ? sprintf( - /* translators: %d: Number of items. */ - _n( - 'Edit %d item', - 'Edit %d items', - selectedItems.length - ), - selectedItems.length - ) - : __( 'Bulk edit' ) } - </Button> - } - > - <ActionsMenuGroup - actions={ bulkActions } - setActionWithModal={ setActionWithModal } - selectedItems={ selectedItems } - /> - <DropdownMenuV2.Group> - <DropdownMenuV2.Item - disabled={ areAllSelected } - hideOnClick={ false } - onClick={ () => { - onChangeSelection( - selectableItems.map( ( item ) => - getItemId( item ) - ) - ); - } } - suffix={ numberSelectableItems } - > - { __( 'Select all' ) } - </DropdownMenuV2.Item> - <DropdownMenuV2.Item - disabled={ selection.length === 0 } - hideOnClick={ false } - onClick={ () => { - onChangeSelection( [] ); - } } - > - { __( 'Deselect' ) } - </DropdownMenuV2.Item> - </DropdownMenuV2.Group> - </DropdownMenuV2> - { actionWithModal && ( - <ActionWithModal - action={ actionWithModal } - selectedItems={ selectedItems } - setActionWithModal={ setActionWithModal } - onMenuOpenChange={ onMenuOpenChange } - /> - ) } - </> + const actionsToShow = useMemo( + () => + actions.filter( ( action ) => { + return ( + action.supportsBulk && + action.icon && + selectedItems.some( + ( item ) => + ! action.isEligible || action.isEligible( item ) + ) + ); + } ), + [ actions, selectedItems ] ); + if ( ! actionInProgress ) { + if ( footerContent.current ) { + footerContent.current = null; + } + return renderFooterContent( + data, + actions, + getItemId, + selection, + actionsToShow, + selectedItems, + actionInProgress, + setActionInProgress, + onChangeSelection + ); + } else if ( ! footerContent.current ) { + footerContent.current = renderFooterContent( + data, + actions, + getItemId, + selection, + actionsToShow, + selectedItems, + actionInProgress, + setActionInProgress, + onChangeSelection + ); + } + return footerContent.current; } -export default function BulkActions() { - const { data, actions = [], view } = useContext( DataViewsContext ); - const hasPossibleBulkAction = useSomeItemHasAPossibleBulkAction( - actions, - data +export function BulkActionsFooter() { + const { + data, + selection, + actions = EMPTY_ARRAY, + onChangeSelection, + getItemId, + } = useContext( DataViewsContext ); + return ( + <FooterContent + selection={ selection } + onChangeSelection={ onChangeSelection } + data={ data } + actions={ actions } + getItemId={ getItemId } + /> ); - if ( - ! [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) || - ! hasPossibleBulkAction - ) { - return null; - } - - return <_BulkActions />; } diff --git a/packages/dataviews/src/components/dataviews-bulk-actions/style.scss b/packages/dataviews/src/components/dataviews-bulk-actions/style.scss index 71f76ce9a6c16f..b2e946aa202abe 100644 --- a/packages/dataviews/src/components/dataviews-bulk-actions/style.scss +++ b/packages/dataviews/src/components/dataviews-bulk-actions/style.scss @@ -1,7 +1,12 @@ -.dataviews-bulk-actions__modal { - z-index: z-index(".dataviews-bulk-actions__modal"); + +.dataviews-bulk-actions-footer__item-count { + color: $gray-900; + font-weight: 500; + font-size: 11px; + text-transform: uppercase; } -.dataviews-bulk-actions__edit-button.components-button { - flex-shrink: 0; +.dataviews-bulk-actions-footer__container { + margin-right: auto; + min-height: $grid-unit-40; } diff --git a/packages/dataviews/src/components/dataviews-footer/index.tsx b/packages/dataviews/src/components/dataviews-footer/index.tsx new file mode 100644 index 00000000000000..191e16f47e2c96 --- /dev/null +++ b/packages/dataviews/src/components/dataviews-footer/index.tsx @@ -0,0 +1,50 @@ +/** + * WordPress dependencies + */ +import { __experimentalHStack as HStack } from '@wordpress/components'; +import { useContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import DataViewsContext from '../dataviews-context'; +import DataViewsPagination from '../dataviews-pagination'; +import { + BulkActionsFooter, + useSomeItemHasAPossibleBulkAction, +} from '../dataviews-bulk-actions'; +import { LAYOUT_GRID, LAYOUT_TABLE } from '../../constants'; + +const EMPTY_ARRAY: [] = []; + +export default function DataViewsFooter() { + const { + view, + paginationInfo: { totalItems = 0, totalPages }, + data, + actions = EMPTY_ARRAY, + } = useContext( DataViewsContext ); + const hasBulkActions = + useSomeItemHasAPossibleBulkAction( actions, data ) && + [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ); + + if ( + ! totalItems || + ! totalPages || + ( totalPages <= 1 && ! hasBulkActions ) + ) { + return null; + } + return ( + !! totalItems && ( + <HStack + expanded={ false } + justify="end" + className="dataviews-footer" + > + { hasBulkActions && <BulkActionsFooter /> } + <DataViewsPagination /> + </HStack> + ) + ); +} diff --git a/packages/dataviews/src/components/dataviews-footer/style.scss b/packages/dataviews/src/components/dataviews-footer/style.scss new file mode 100644 index 00000000000000..cdb1359ccee393 --- /dev/null +++ b/packages/dataviews/src/components/dataviews-footer/style.scss @@ -0,0 +1,40 @@ +.dataviews-footer { + position: sticky; + bottom: 0; + left: 0; + background-color: $white; + padding: $grid-unit-15 $grid-unit-60; + border-top: $border-width solid $gray-100; + flex-shrink: 0; + transition: padding ease-out 0.1s; + @include reduce-motion("transition"); + z-index: z-index(".dataviews-footer"); +} + + +/* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ +@container (max-width: 430px) { + .dataviews-footer { + padding: $grid-unit-15 $grid-unit-30; + } +} + +/* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ +@container (max-width: 560px) { + .dataviews-footer { + flex-direction: column !important; + + .dataviews-bulk-actions-footer__container { + width: 100%; + } + + .dataviews-bulk-actions-footer__item-count { + flex-grow: 1; + } + + .dataviews-pagination { + width: 100%; + justify-content: space-between; + } + } +} diff --git a/packages/dataviews/src/components/dataviews-pagination/index.tsx b/packages/dataviews/src/components/dataviews-pagination/index.tsx index f022b382cdb70d..d2744b0c39bc0b 100644 --- a/packages/dataviews/src/components/dataviews-pagination/index.tsx +++ b/packages/dataviews/src/components/dataviews-pagination/index.tsx @@ -51,9 +51,9 @@ function DataViewsPagination() { totalPages !== 1 && ( <HStack expanded={ false } - spacing={ 6 } - justify="end" className="dataviews-pagination" + justify="end" + spacing={ 6 } > <HStack justify="flex-start" diff --git a/packages/dataviews/src/components/dataviews-pagination/style.scss b/packages/dataviews/src/components/dataviews-pagination/style.scss index 16f064cc3a5178..c8079c6b3ee828 100644 --- a/packages/dataviews/src/components/dataviews-pagination/style.scss +++ b/packages/dataviews/src/components/dataviews-pagination/style.scss @@ -1,15 +1,3 @@ -.dataviews-pagination { - position: sticky; - bottom: 0; - left: 0; - background-color: $white; - padding: $grid-unit-15 $grid-unit-60; - border-top: $border-width solid $gray-100; - flex-shrink: 0; - transition: padding ease-out 0.1s; - @include reduce-motion("transition"); -} - .dataviews-pagination__page-select { font-size: 11px; font-weight: 500; @@ -22,10 +10,3 @@ } } } - -/* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ -@container (max-width: 430px) { - .dataviews-pagination { - padding: $grid-unit-15 $grid-unit-30; - } -} diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index 59167a9fe04188..da60ab15ecadec 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -12,8 +12,6 @@ import { useMemo, useState } from '@wordpress/element'; /** * Internal dependencies */ -import { default as DataViewsBulkActions } from '../dataviews-bulk-actions'; -import DataViewsBulkActionsToolbar from '../dataviews-bulk-actions-toolbar'; import DataViewsContext from '../dataviews-context'; import { default as DataViewsFilters, @@ -21,7 +19,7 @@ import { FilterVisibilityToggle, } from '../dataviews-filters'; import DataViewsLayout from '../dataviews-layout'; -import DataviewsPagination from '../dataviews-pagination'; +import DataViewsFooter from '../dataviews-footer'; import DataViewsSearch from '../dataviews-search'; import DataViewsViewConfig from '../dataviews-view-config'; import { normalizeFields } from '../../normalize-fields'; @@ -142,7 +140,6 @@ export default function DataViews< Item >( { expanded={ false } style={ { flexShrink: 0 } } > - <DataViewsBulkActions /> <DataViewsViewConfig defaultLayouts={ defaultLayouts } density={ density } @@ -153,8 +150,7 @@ export default function DataViews< Item >( { </HStack> { isShowingFilter && <DataViewsFilters /> } <DataViewsLayout /> - <DataviewsPagination /> - <DataViewsBulkActionsToolbar /> + <DataViewsFooter /> </div> </DataViewsContext.Provider> ); diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index a4adde7fb382f3..b12082a55623b2 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -8,18 +8,11 @@ import clsx from 'clsx'; */ import { __ } from '@wordpress/i18n'; import { - CheckboxControl, Spinner, __experimentalHStack as HStack, __experimentalVStack as VStack, } from '@wordpress/components'; -import { - useEffect, - useId, - useRef, - useState, - useMemo, -} from '@wordpress/element'; +import { useEffect, useId, useRef, useState } from '@wordpress/element'; /** * Internal dependencies @@ -30,6 +23,7 @@ import { sortValues } from '../../constants'; import { useSomeItemHasAPossibleBulkAction, useHasAPossibleBulkAction, + BulkSelectionCheckbox, } from '../../components/dataviews-bulk-actions'; import type { Action, @@ -41,14 +35,6 @@ import type { import type { SetSelection } from '../../private-types'; import ColumnHeaderMenu from './column-header-menu'; -interface BulkSelectionCheckboxProps< Item > { - selection: string[]; - onChangeSelection: SetSelection; - data: Item[]; - actions: Action< Item >[]; - getItemId: ( item: Item ) => string; -} - interface TableColumnFieldProps< Item > { primaryField?: NormalizedField< Item >; field: NormalizedField< Item >; @@ -84,50 +70,6 @@ interface TableRowProps< Item > { onChangeSelection: SetSelection; } -function BulkSelectionCheckbox< Item >( { - selection, - onChangeSelection, - data, - actions, - getItemId, -}: BulkSelectionCheckboxProps< Item > ) { - const selectableItems = useMemo( () => { - return data.filter( ( item ) => { - return actions.some( - ( action ) => - action.supportsBulk && - ( ! action.isEligible || action.isEligible( item ) ) - ); - } ); - }, [ data, actions ] ); - const selectedItems = data.filter( - ( item ) => - selection.includes( getItemId( item ) ) && - selectableItems.includes( item ) - ); - const areAllSelected = selectedItems.length === selectableItems.length; - return ( - <CheckboxControl - className="dataviews-view-table-selection-checkbox" - __nextHasNoMarginBottom - checked={ areAllSelected } - indeterminate={ ! areAllSelected && !! selectedItems.length } - onChange={ () => { - if ( areAllSelected ) { - onChangeSelection( [] ); - } else { - onChangeSelection( - selectableItems.map( ( item ) => getItemId( item ) ) - ); - } - } } - aria-label={ - areAllSelected ? __( 'Deselect all' ) : __( 'Select all' ) - } - /> - ); -} - function TableColumn< Item >( { column, fields, diff --git a/packages/dataviews/src/style.scss b/packages/dataviews/src/style.scss index 7be92273663a87..087e812fffa192 100644 --- a/packages/dataviews/src/style.scss +++ b/packages/dataviews/src/style.scss @@ -1,7 +1,7 @@ @import "./components/dataviews/style.scss"; @import "./components/dataviews-bulk-actions/style.scss"; -@import "./components/dataviews-bulk-actions-toolbar/style.scss"; @import "./components/dataviews-filters/style.scss"; +@import "./components/dataviews-footer/style.scss"; @import "./components/dataviews-pagination/style.scss"; @import "./components/dataviews-item-actions/style.scss"; @import "./components/dataviews-selection-checkbox/style.scss"; diff --git a/packages/edit-site/src/components/page-patterns/style.scss b/packages/edit-site/src/components/page-patterns/style.scss index 34b258e3a92041..a5aa1eb9ac796e 100644 --- a/packages/edit-site/src/components/page-patterns/style.scss +++ b/packages/edit-site/src/components/page-patterns/style.scss @@ -105,10 +105,6 @@ } .edit-site-page-patterns-dataviews { - .dataviews-pagination { - z-index: z-index(".edit-site-patterns__dataviews-list-pagination"); - } - .dataviews-view-grid__badge-fields { .dataviews-view-grid__field-value:has(.edit-site-patterns__field-sync-status-fully) { background: rgba(var(--wp-block-synced-color--rgb), 0.04); diff --git a/packages/editor/src/dataviews/actions/export-pattern.tsx b/packages/editor/src/dataviews/actions/export-pattern.tsx index f4e5c91c7cabfa..b6be83eeda84b4 100644 --- a/packages/editor/src/dataviews/actions/export-pattern.tsx +++ b/packages/editor/src/dataviews/actions/export-pattern.tsx @@ -9,6 +9,7 @@ import { downloadZip } from 'client-zip'; */ import { downloadBlob } from '@wordpress/blob'; import { __ } from '@wordpress/i18n'; +import { download } from '@wordpress/icons'; import type { Action } from '@wordpress/dataviews'; /** @@ -36,6 +37,7 @@ function getJsonFromItem( item: Pattern ) { const exportPattern: Action< Pattern > = { id: 'export-pattern', label: __( 'Export as JSON' ), + icon: download, supportsBulk: true, isEligible: ( item ) => item.type === 'wp_block', callback: async ( items ) => { diff --git a/packages/editor/src/dataviews/actions/permanently-delete-post.tsx b/packages/editor/src/dataviews/actions/permanently-delete-post.tsx index 2124fdc0ffa4ce..afbb84ae12c74c 100644 --- a/packages/editor/src/dataviews/actions/permanently-delete-post.tsx +++ b/packages/editor/src/dataviews/actions/permanently-delete-post.tsx @@ -5,6 +5,7 @@ import { store as coreStore } from '@wordpress/core-data'; import { __, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; import type { Action } from '@wordpress/dataviews'; +import { trash } from '@wordpress/icons'; /** * Internal dependencies @@ -16,6 +17,7 @@ const permanentlyDeletePost: Action< PostWithPermissions > = { id: 'permanently-delete', label: __( 'Permanently delete' ), supportsBulk: true, + icon: trash, isEligible( item ) { if ( isTemplateOrTemplatePart( item ) || item.type === 'wp_block' ) { return false; From 2c7c936c77b3ba595b5291c950246ac6851f4125 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Wed, 28 Aug 2024 13:01:13 +0200 Subject: [PATCH 0568/1908] Edit Site Layout: remove redundant fullResizer (#64821) --- packages/edit-site/src/components/layout/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index a4e4fa57a5bbf1..c54b7efa382c66 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -81,7 +81,6 @@ export default function Layout( { route } ) { } ); const disableMotion = useReducedMotion(); const [ canvasResizer, canvasSize ] = useResizeObserver(); - const [ fullResizer ] = useResizeObserver(); const isEditorLoading = useIsSiteEditorLoading(); const [ isResizableFrameOversized, setIsResizableFrameOversized ] = useState( false ); @@ -113,7 +112,6 @@ export default function Layout( { route } ) { <CommandMenu /> <KeyboardShortcutsRegister /> <KeyboardShortcutsGlobal /> - { fullResizer } <div { ...navigateRegionsProps } ref={ navigateRegionsProps.ref } From e1e10ab8063c21f74e0e21a81ff3f0a0baaba3dc Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Wed, 28 Aug 2024 13:07:56 +0200 Subject: [PATCH 0569/1908] Add safeguard to `mediaUploadMiddleware` (#64843) --- packages/api-fetch/src/middlewares/media-upload.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/api-fetch/src/middlewares/media-upload.js b/packages/api-fetch/src/middlewares/media-upload.js index 417abf775db636..ddd0be4e4ab436 100644 --- a/packages/api-fetch/src/middlewares/media-upload.js +++ b/packages/api-fetch/src/middlewares/media-upload.js @@ -63,6 +63,11 @@ const mediaUploadMiddleware = ( options, next ) => { return next( { ...options, parse: false } ) .catch( ( response ) => { + // `response` could actually be an error thrown by `defaultFetchHandler`. + if ( ! response.headers ) { + return Promise.reject( response ); + } + const attachmentId = response.headers.get( 'x-wp-upload-attachment-id' ); From 2c8922e159c825ce0bf3869c548c5a65a0389945 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Wed, 28 Aug 2024 08:29:20 -0500 Subject: [PATCH 0570/1908] Remove ability to crop image if content only mode (#64838) --- packages/block-library/src/image/image.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 3ad12d8dca4b62..2eec1cd185ed76 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -358,7 +358,11 @@ export default function Image( { }, [ isSingleSelected ] ); const canEditImage = id && naturalWidth && naturalHeight && imageEditing; - const allowCrop = isSingleSelected && canEditImage && ! isEditingImage; + const allowCrop = + isSingleSelected && + canEditImage && + ! isEditingImage && + ! isContentOnlyMode; function switchToCover() { replaceBlocks( From 9de565cf87cf301fba8260afd0b63b3e6b7de1fc Mon Sep 17 00:00:00 2001 From: Jonny Harris <spacedmonkey@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:41:47 +0100 Subject: [PATCH 0571/1908] Add back editor-post-locked-modal to post lock component. (#64257) * Add back editor-post-locked-modal to post lock component. * Add comment to preserve class in post-locked-modal Ensure the `editor-post-locked-modal` class remains unchanged because third-party plugins depend on it. This change prevents potential breakages in plugin functionality. --- packages/editor/src/components/post-locked-modal/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/editor/src/components/post-locked-modal/index.js b/packages/editor/src/components/post-locked-modal/index.js index 3c79c0466622e0..afb0d48e1a133a 100644 --- a/packages/editor/src/components/post-locked-modal/index.js +++ b/packages/editor/src/components/post-locked-modal/index.js @@ -178,6 +178,8 @@ export default function PostLockedModal() { shouldCloseOnClickOutside={ false } shouldCloseOnEsc={ false } isDismissible={ false } + // Do not remove this class, as this class is used by third party plugins. + className="editor-post-locked-modal" size="medium" > <HStack alignment="top" spacing={ 6 }> From 58406a830fabdff95ee834e34559436e4e245e40 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 28 Aug 2024 15:43:35 +0000 Subject: [PATCH 0572/1908] Bump plugin version to 19.1.0 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 2cd33a570f5857..f0e2f94ef57fd6 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.1.0-rc.1 + * Version: 19.1.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 6bae0fa5859941..48c0805aef9ed8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.1.0-rc.1", + "version": "19.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.1.0-rc.1", + "version": "19.1.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 7349e60eb4c210..0e495308e44e1e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.1.0-rc.1", + "version": "19.1.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 88be48d62399e09c2ec505f6894c07fb13cec2c8 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 28 Aug 2024 16:06:01 +0000 Subject: [PATCH 0573/1908] Update Changelog for 19.1.0 --- changelog.txt | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/changelog.txt b/changelog.txt index b21f0b433eec23..0fb2b93056b9bc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,6 @@ == Changelog == -= 19.1.0-rc.1 = += 19.1.0 = ## Changelog @@ -13,9 +13,7 @@ - Ariakit: Update to v0.4.10. ([64637](https://github.com/WordPress/gutenberg/pull/64637)) - DimensionControl: Add flag to remove bottom margin. ([64346](https://github.com/WordPress/gutenberg/pull/64346)) - DropdownMenu V2: Use themed color variables. ([64647](https://github.com/WordPress/gutenberg/pull/64647)) -- FocalPointPicker: Default to new 40px size. ([64456](https://github.com/WordPress/gutenberg/pull/64456)) - Placeholders: Update radius temporarily. ([64672](https://github.com/WordPress/gutenberg/pull/64672)) -- QueryControls: Default to new 40px size. ([64457](https://github.com/WordPress/gutenberg/pull/64457)) - Reduce gap between steps in SpacingSizesControl, add animation, remove first/last marks. ([63803](https://github.com/WordPress/gutenberg/pull/63803)) - Textarea Control: Update styles. ([64586](https://github.com/WordPress/gutenberg/pull/64586)) - Tools Panel: Sets column-gap to 16px for grid. ([64497](https://github.com/WordPress/gutenberg/pull/64497)) @@ -23,20 +21,24 @@ - Update components radius. ([64368](https://github.com/WordPress/gutenberg/pull/64368)) - Use `useStoreState()` instead of `store.useState()`. ([64648](https://github.com/WordPress/gutenberg/pull/64648)) - Composite: Use internal context to consume composite store. ([64493](https://github.com/WordPress/gutenberg/pull/64493)) +- Default to new 40px size in the following: + - FocalPointPicker: ([64456](https://github.com/WordPress/gutenberg/pull/64456)) + - QueryControls: ([64457](https://github.com/WordPress/gutenberg/pull/64457)) #### Data Views - Do not display element descriptions in filters. ([64674](https://github.com/WordPress/gutenberg/pull/64674)) -- Add `comment_status` field to quick edit. ([64370](https://github.com/WordPress/gutenberg/pull/64370)) -- Add `status` to quick edit. ([64398](https://github.com/WordPress/gutenberg/pull/64398)) - Apply minimal variant to pagination dropdown. ([63815](https://github.com/WordPress/gutenberg/pull/63815)) - Update the style of the datetime fields to match the other types. ([64438](https://github.com/WordPress/gutenberg/pull/64438)) - Use the fields array to define the order of the fields. ([64335](https://github.com/WordPress/gutenberg/pull/64335)) - Make the move left/right controls in table header always available. ([64646](https://github.com/WordPress/gutenberg/pull/64646)) - Support defining field headers/names as React elements. ([64642](https://github.com/WordPress/gutenberg/pull/64642)) -- Quick edit: Add Date as field and `datetime` as field type. ([64267](https://github.com/WordPress/gutenberg/pull/64267)) - Add marks to preview size control. ([64546](https://github.com/WordPress/gutenberg/pull/64546)) - Move item size control to the new view configuration UI. ([64380](https://github.com/WordPress/gutenberg/pull/64380)) - Update search appearance in narrow containers. ([64681](https://github.com/WordPress/gutenberg/pull/64681)) +- Quick edit additions: + - `comment_status` field. ([64370](https://github.com/WordPress/gutenberg/pull/64370)) + - `status` field. ([64398](https://github.com/WordPress/gutenberg/pull/64398)) + - 'Date' as field and `datetime` as field type. ([64267](https://github.com/WordPress/gutenberg/pull/64267)) - Extensibility - allow unregistering of the following: - Duplicate post action ([64441](https://github.com/WordPress/gutenberg/pull/64441)) - Duplicate pattern action ([64373](https://github.com/WordPress/gutenberg/pull/64373)) @@ -45,16 +47,12 @@ - Reorder-page action ([64199](https://github.com/WordPress/gutenberg/pull/64199)) - View post action ([64467](https://github.com/WordPress/gutenberg/pull/64467)) - View post revisions action ([64464](https://github.com/WordPress/gutenberg/pull/64464)) +- Add missing styles and remove opinionated ones for generic usage. ([64711](https://github.com/WordPress/gutenberg/pull/64711)) #### Block Library - Embed Block: Replace native input element with InputControl component. ([64668](https://github.com/WordPress/gutenberg/pull/64668)) -- File: Add border block support. ([64509](https://github.com/WordPress/gutenberg/pull/64509)) - Grid: Prevent highlight of cells when dragging a block if block type can't be dropped into grid. ([64290](https://github.com/WordPress/gutenberg/pull/64290)) - Image block: Add reset button. ([64669](https://github.com/WordPress/gutenberg/pull/64669)) -- List Item: Add border support. ([63541](https://github.com/WordPress/gutenberg/pull/63541)) -- List: Add border support. ([63540](https://github.com/WordPress/gutenberg/pull/63540)) -- Preformatted: Add border block support. ([64302](https://github.com/WordPress/gutenberg/pull/64302)) -- Tag Cloud: Add border block support. ([63579](https://github.com/WordPress/gutenberg/pull/63579)) - Overlay caption w. text-shadow. ([63471](https://github.com/WordPress/gutenberg/pull/63471)) #### Design Tools @@ -68,6 +66,11 @@ - Post Author Name ([64530](https://github.com/WordPress/gutenberg/pull/64530)) - Post Author ([64599](https://github.com/WordPress/gutenberg/pull/64599)) - Query Title ([64581](https://github.com/WordPress/gutenberg/pull/64581)) + - File: ([64509](https://github.com/WordPress/gutenberg/pull/64509)) + - List Item: ([63541](https://github.com/WordPress/gutenberg/pull/63541)) + - List: ([63540](https://github.com/WordPress/gutenberg/pull/63540)) + - Preformatted: ([64302](https://github.com/WordPress/gutenberg/pull/64302)) + - Tag Cloud: ([63579](https://github.com/WordPress/gutenberg/pull/63579)) #### Zoom Out - Add private `isZoomOutMode` selector. ([64503](https://github.com/WordPress/gutenberg/pull/64503)) @@ -112,6 +115,7 @@ - Load the filter toggle as open if there are primary filters. ([64651](https://github.com/WordPress/gutenberg/pull/64651)) - Sort descending button may be wrongly pressed. ([64547](https://github.com/WordPress/gutenberg/pull/64547)) - Filter icon is displayed even when no filter capabilities are given to any field. ([64640](https://github.com/WordPress/gutenberg/pull/64640)) +- Hide sort direction control if there are no sortable fields. ([64817](https://github.com/WordPress/gutenberg/pull/64817)) #### Zoom Out - Disallow dropping outside section root in Zoom Out mode. ([64500](https://github.com/WordPress/gutenberg/pull/64500)) @@ -142,6 +146,7 @@ #### Block bindings - Fix long keys overflow in bindings panel. ([64465](https://github.com/WordPress/gutenberg/pull/64465)) - Hide keys starting with underscore. ([64618](https://github.com/WordPress/gutenberg/pull/64618)) +- Refactor utils file. ([64740](https://github.com/WordPress/gutenberg/pull/64740)) #### CSS & Styling - Remove inconsistent dark theme focus style on block selection. ([64549](https://github.com/WordPress/gutenberg/pull/64549)) @@ -149,6 +154,7 @@ #### Interactivity API - Fix context inheritance from namespaces different than the current one. ([64677](https://github.com/WordPress/gutenberg/pull/64677)) +- Fix computeds without scope in Firefox. ([64825](https://github.com/WordPress/gutenberg/pull/64825)) #### Document Settings - Post Featured Image: Disable the media modal while uploading an image. ([64566](https://github.com/WordPress/gutenberg/pull/64566)) From 810a513c148d73e040b0e1c91cfa8a16f2ffa449 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Wed, 28 Aug 2024 18:21:33 +0200 Subject: [PATCH 0574/1908] Reusable blocks: fix performance of __experimentalGetAllowedPatterns (#64871) --- .../src/store/private-selectors.js | 10 ++-- packages/block-editor/src/store/selectors.js | 49 ++++--------------- packages/block-editor/src/store/utils.js | 38 ++++++++++++++ 3 files changed, 52 insertions(+), 45 deletions(-) diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 3a6dcdd4e19e6b..9d3c5f27a7cc98 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -20,6 +20,7 @@ import { checkAllowListRecursive, getAllPatternsDependants, getInsertBlockTypeDependants, + getParsedPattern, } from './utils'; import { INSERTER_PATTERN_TYPES } from '../components/inserter/block-patterns-tab/utils'; import { STORE_NAME } from './constants'; @@ -291,16 +292,15 @@ export const getInserterMediaCategories = createSelector( export const hasAllowedPatterns = createRegistrySelector( ( select ) => createSelector( ( state, rootClientId = null ) => { - const { getAllPatterns, __experimentalGetParsedPattern } = unlock( - select( STORE_NAME ) - ); + const { getAllPatterns } = unlock( select( STORE_NAME ) ); const patterns = getAllPatterns(); const { allowedBlockTypes } = getSettings( state ); - return patterns.some( ( { name, inserter = true } ) => { + return patterns.some( ( pattern ) => { + const { inserter = true } = pattern; if ( ! inserter ) { return false; } - const { blocks } = __experimentalGetParsedPattern( name ); + const { blocks } = getParsedPattern( pattern ); return ( checkAllowListRecursive( blocks, allowedBlockTypes ) && blocks.every( ( { name: blockName } ) => diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index f06293dadf233c..32fa081b390ae9 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -7,7 +7,6 @@ import { getBlockVariations, hasBlockSupport, getPossibleBlockTransformations, - parse, switchToBlockType, store as blocksStore, } from '@wordpress/blocks'; @@ -27,6 +26,7 @@ import { checkAllowList, getAllPatternsDependants, getInsertBlockTypeDependants, + getParsedPattern, } from './utils'; import { orderBy } from '../utils/sorting'; import { STORE_NAME } from './constants'; @@ -2349,40 +2349,12 @@ export function __experimentalGetDirectInsertBlock( } export const __experimentalGetParsedPattern = createRegistrySelector( - ( select ) => - createSelector( - ( state, patternName ) => { - const pattern = unlock( select( STORE_NAME ) ).getPatternBySlug( - patternName - ); - if ( ! pattern ) { - return null; - } - const blocks = parse( pattern.content, { - __unstableSkipMigrationLogs: true, - } ); - if ( blocks.length === 1 ) { - blocks[ 0 ].attributes = { - ...blocks[ 0 ].attributes, - metadata: { - ...( blocks[ 0 ].attributes.metadata || {} ), - categories: pattern.categories, - patternName: pattern.name, - name: - blocks[ 0 ].attributes.metadata?.name || - pattern.title, - }, - }; - } - return { - ...pattern, - blocks, - }; - }, - ( state, patternName ) => [ - unlock( select( STORE_NAME ) ).getPatternBySlug( patternName ), - ] - ) + ( select ) => ( state, patternName ) => { + const pattern = unlock( select( STORE_NAME ) ).getPatternBySlug( + patternName + ); + return pattern ? getParsedPattern( pattern ) : null; + } ); const getAllowedPatternsDependants = ( select ) => ( state, rootClientId ) => [ @@ -2401,16 +2373,13 @@ const getAllowedPatternsDependants = ( select ) => ( state, rootClientId ) => [ export const __experimentalGetAllowedPatterns = createRegistrySelector( ( select ) => { return createSelector( ( state, rootClientId = null ) => { - const { - getAllPatterns, - __experimentalGetParsedPattern: getParsedPattern, - } = unlock( select( STORE_NAME ) ); + const { getAllPatterns } = unlock( select( STORE_NAME ) ); const patterns = getAllPatterns(); const { allowedBlockTypes } = getSettings( state ); const parsedPatterns = patterns .filter( ( { inserter = true } ) => !! inserter ) - .map( ( { name } ) => getParsedPattern( name ) ); + .map( getParsedPattern ); const availableParsedPatterns = parsedPatterns.filter( ( { blocks } ) => checkAllowListRecursive( blocks, allowedBlockTypes ) diff --git a/packages/block-editor/src/store/utils.js b/packages/block-editor/src/store/utils.js index c94453e99c60a4..71c5ac44f45b83 100644 --- a/packages/block-editor/src/store/utils.js +++ b/packages/block-editor/src/store/utils.js @@ -1,3 +1,8 @@ +/** + * WordPress dependencies + */ +import { parse } from '@wordpress/blocks'; + /** * Internal dependencies */ @@ -7,6 +12,39 @@ import { STORE_NAME } from './constants'; export const withRootClientIdOptionKey = Symbol( 'withRootClientId' ); +const parsedPatternCache = new WeakMap(); + +function parsePattern( pattern ) { + const blocks = parse( pattern.content, { + __unstableSkipMigrationLogs: true, + } ); + if ( blocks.length === 1 ) { + blocks[ 0 ].attributes = { + ...blocks[ 0 ].attributes, + metadata: { + ...( blocks[ 0 ].attributes.metadata || {} ), + categories: pattern.categories, + patternName: pattern.name, + name: blocks[ 0 ].attributes.metadata?.name || pattern.title, + }, + }; + } + return { + ...pattern, + blocks, + }; +} + +export function getParsedPattern( pattern ) { + let parsedPattern = parsedPatternCache.get( pattern ); + if ( parsedPattern ) { + return parsedPattern; + } + parsedPattern = parsePattern( pattern ); + parsedPatternCache.set( pattern, parsedPattern ); + return parsedPattern; +} + export const checkAllowList = ( list, item, defaultResult = null ) => { if ( typeof list === 'boolean' ) { return list; From fdff00c9b442dd4263da62a7dd8a3f9fe617b3ad Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 28 Aug 2024 19:00:09 +0200 Subject: [PATCH 0575/1908] Navigator: polish Storybook examples (#64798) * Remove subfolder index.ts files, since they interfere with Storybook docgen * Use MenuItem for Dropdown, remove unnecessary types * Remove Card usage from the Storybook example * Fix sticky screen styles after removal of Card * Set inline padding and height on every screen * Better title semantics and typography * Add one more link to product details screen to show how it works * Refactor skip focus styles * Avoid double y-scrolling on full-height container * Move back wrongly positioned metaphor ipsum * Move navigator styles to decorator * Tweak screen and provider styles * Simplify Storybook examples, removing edge cases and focusing on standard usage --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/src/navigator/index.ts | 12 +- .../navigator/navigator-back-button/hook.ts | 2 +- .../navigator/navigator-back-button/index.ts | 1 - .../src/navigator/navigator-button/hook.ts | 2 +- .../src/navigator/navigator-button/index.ts | 1 - .../src/navigator/navigator-provider/index.ts | 1 - .../src/navigator/navigator-screen/index.ts | 1 - .../navigator-to-parent-button/component.tsx | 2 +- .../navigator-to-parent-button/index.ts | 1 - .../src/navigator/stories/index.story.tsx | 328 +++++------------- .../components/src/navigator/use-navigator.ts | 4 +- 11 files changed, 89 insertions(+), 266 deletions(-) delete mode 100644 packages/components/src/navigator/navigator-back-button/index.ts delete mode 100644 packages/components/src/navigator/navigator-button/index.ts delete mode 100644 packages/components/src/navigator/navigator-provider/index.ts delete mode 100644 packages/components/src/navigator/navigator-screen/index.ts delete mode 100644 packages/components/src/navigator/navigator-to-parent-button/index.ts diff --git a/packages/components/src/navigator/index.ts b/packages/components/src/navigator/index.ts index 74c69a0daa9c31..130edc2ae52eb8 100644 --- a/packages/components/src/navigator/index.ts +++ b/packages/components/src/navigator/index.ts @@ -1,6 +1,6 @@ -export { NavigatorProvider } from './navigator-provider'; -export { NavigatorScreen } from './navigator-screen'; -export { NavigatorButton } from './navigator-button'; -export { NavigatorBackButton } from './navigator-back-button'; -export { NavigatorToParentButton } from './navigator-to-parent-button'; -export { default as useNavigator } from './use-navigator'; +export { NavigatorProvider } from './navigator-provider/component'; +export { NavigatorScreen } from './navigator-screen/component'; +export { NavigatorButton } from './navigator-button/component'; +export { NavigatorBackButton } from './navigator-back-button/component'; +export { NavigatorToParentButton } from './navigator-to-parent-button/component'; +export { useNavigator } from './use-navigator'; diff --git a/packages/components/src/navigator/navigator-back-button/hook.ts b/packages/components/src/navigator/navigator-back-button/hook.ts index d4447b5f40ad46..9ddc095292190a 100644 --- a/packages/components/src/navigator/navigator-back-button/hook.ts +++ b/packages/components/src/navigator/navigator-back-button/hook.ts @@ -9,7 +9,7 @@ import { useCallback } from '@wordpress/element'; import type { WordPressComponentProps } from '../../context'; import { useContextSystem } from '../../context'; import Button from '../../button'; -import useNavigator from '../use-navigator'; +import { useNavigator } from '../use-navigator'; import type { NavigatorBackButtonProps } from '../types'; export function useNavigatorBackButton( diff --git a/packages/components/src/navigator/navigator-back-button/index.ts b/packages/components/src/navigator/navigator-back-button/index.ts deleted file mode 100644 index 9046e90350e278..00000000000000 --- a/packages/components/src/navigator/navigator-back-button/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as NavigatorBackButton } from './component'; diff --git a/packages/components/src/navigator/navigator-button/hook.ts b/packages/components/src/navigator/navigator-button/hook.ts index 3952dc3fd56ba5..3e39b05661e1b2 100644 --- a/packages/components/src/navigator/navigator-button/hook.ts +++ b/packages/components/src/navigator/navigator-button/hook.ts @@ -10,7 +10,7 @@ import { escapeAttribute } from '@wordpress/escape-html'; import type { WordPressComponentProps } from '../../context'; import { useContextSystem } from '../../context'; import Button from '../../button'; -import useNavigator from '../use-navigator'; +import { useNavigator } from '../use-navigator'; import type { NavigatorButtonProps } from '../types'; const cssSelectorForAttribute = ( attrName: string, attrValue: string ) => diff --git a/packages/components/src/navigator/navigator-button/index.ts b/packages/components/src/navigator/navigator-button/index.ts deleted file mode 100644 index 74975a5e1b0c14..00000000000000 --- a/packages/components/src/navigator/navigator-button/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as NavigatorButton } from './component'; diff --git a/packages/components/src/navigator/navigator-provider/index.ts b/packages/components/src/navigator/navigator-provider/index.ts deleted file mode 100644 index b9a330613ac847..00000000000000 --- a/packages/components/src/navigator/navigator-provider/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as NavigatorProvider } from './component'; diff --git a/packages/components/src/navigator/navigator-screen/index.ts b/packages/components/src/navigator/navigator-screen/index.ts deleted file mode 100644 index 9c9a40d435fff3..00000000000000 --- a/packages/components/src/navigator/navigator-screen/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as NavigatorScreen } from './component'; diff --git a/packages/components/src/navigator/navigator-to-parent-button/component.tsx b/packages/components/src/navigator/navigator-to-parent-button/component.tsx index 400498b1fc96ca..fcbadea03cf7bb 100644 --- a/packages/components/src/navigator/navigator-to-parent-button/component.tsx +++ b/packages/components/src/navigator/navigator-to-parent-button/component.tsx @@ -6,7 +6,7 @@ import deprecated from '@wordpress/deprecated'; /** * Internal dependencies */ -import { NavigatorBackButton } from '../navigator-back-button'; +import { NavigatorBackButton } from '../navigator-back-button/component'; import type { WordPressComponentProps } from '../../context'; import { contextConnect } from '../../context'; import type { NavigatorBackButtonProps } from '../types'; diff --git a/packages/components/src/navigator/navigator-to-parent-button/index.ts b/packages/components/src/navigator/navigator-to-parent-button/index.ts deleted file mode 100644 index f5218e456065e6..00000000000000 --- a/packages/components/src/navigator/navigator-to-parent-button/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as NavigatorToParentButton } from './component'; diff --git a/packages/components/src/navigator/stories/index.story.tsx b/packages/components/src/navigator/stories/index.story.tsx index 633d5897678cbf..30b9c71a368c1a 100644 --- a/packages/components/src/navigator/stories/index.story.tsx +++ b/packages/components/src/navigator/stories/index.story.tsx @@ -7,9 +7,7 @@ import type { Meta, StoryObj } from '@storybook/react'; * Internal dependencies */ import Button from '../../button'; -import { Card, CardBody, CardFooter, CardHeader } from '../../card'; import { VStack } from '../../v-stack'; -import Dropdown from '../../dropdown'; import { NavigatorProvider, NavigatorScreen, @@ -17,6 +15,7 @@ import { NavigatorBackButton, useNavigator, } from '..'; +import { HStack } from '../../h-stack'; const meta: Meta< typeof NavigatorProvider > = { component: NavigatorProvider, @@ -32,268 +31,106 @@ const meta: Meta< typeof NavigatorProvider > = { controls: { expanded: true }, docs: { canvas: { sourceState: 'shown' } }, }, + decorators: [ + ( Story ) => { + return ( + <> + <style>{ ` + /* These attributes are a private implementation detail of the + Navigator component. Do not use outside of its source code. */ + [data-wp-component="NavigatorProvider"] { + height: calc(100vh - 2rem); + max-height: 250px; + + } + [data-wp-component="NavigatorScreen"]:not([data-sticky]) { + padding: 8px; + } + ` }</style> + <Story /> + </> + ); + }, + ], }; export default meta; export const Default: StoryObj< typeof NavigatorProvider > = { args: { initialPath: '/', - style: { height: '100vh', maxHeight: '450px' }, children: ( <> <NavigatorScreen path="/"> - <Card> - <CardBody> - <p>This is the home screen.</p> + <h2>This is the home screen.</h2> - <VStack alignment="left"> - <NavigatorButton - variant="secondary" - path="/child" - > - Navigate to child screen. - </NavigatorButton> - - <NavigatorButton - variant="secondary" - path="/overflow-child" - > - Navigate to screen with horizontal overflow. - </NavigatorButton> - - <NavigatorButton - variant="secondary" - path="/stickies" - > - Navigate to screen with sticky content. - </NavigatorButton> + <VStack alignment="left"> + <NavigatorButton variant="primary" path="/child"> + Go to child screen. + </NavigatorButton> - <NavigatorButton - variant="secondary" - path="/product/1" - > - Navigate to product screen with id 1. - </NavigatorButton> + <NavigatorButton variant="primary" path="/product/1"> + Go to dynamic path screen with id 1. + </NavigatorButton> - <Dropdown - renderToggle={ ( { - isOpen, - onToggle, - }: { - // TODO: remove once `Dropdown` is refactored to TypeScript - isOpen: boolean; - onToggle: () => void; - } ) => ( - <Button - onClick={ onToggle } - aria-expanded={ isOpen } - variant="primary" - > - Open test dialog - </Button> - ) } - renderContent={ () => ( - <Card> - <CardHeader>Go</CardHeader> - <CardBody>Stuff</CardBody> - </Card> - ) } - /> - </VStack> - </CardBody> - </Card> + <NavigatorButton variant="primary" path="/product/2"> + Go to dynamic path screen with id 2. + </NavigatorButton> + </VStack> </NavigatorScreen> <NavigatorScreen path="/child"> - <Card> - <CardBody> - <p>This is the child screen.</p> - <NavigatorBackButton variant="secondary"> - Go back - </NavigatorBackButton> - </CardBody> - </Card> - </NavigatorScreen> + <h2>This is the child screen.</h2> + <HStack spacing={ 2 } alignment="left"> + <NavigatorBackButton variant="secondary"> + Go back + </NavigatorBackButton> - <NavigatorScreen path="/overflow-child"> - <Card> - <CardBody> - <NavigatorBackButton variant="secondary"> - Go back - </NavigatorBackButton> - <div - style={ { - display: 'inline-block', - background: 'papayawhip', - } } - > - <span - style={ { - color: 'palevioletred', - whiteSpace: 'nowrap', - fontSize: '42vw', - } } - > - ¯\_(ツ)_/¯ - </span> - </div> - </CardBody> - </Card> + <NavigatorButton + variant="primary" + path="/child/grandchild" + > + Go to grand child screen. + </NavigatorButton> + </HStack> </NavigatorScreen> - <NavigatorScreen path="/stickies"> - <Card> - <CardHeader style={ getStickyStyles( { zIndex: 2 } ) }> - <NavigatorBackButton variant="secondary"> - Go back - </NavigatorBackButton> - </CardHeader> - <CardBody> - <div - style={ getStickyStyles( { - top: 69, - bgColor: 'peachpuff', - } ) } - > - <h2>A wild sticky element appears</h2> - </div> - <MetaphorIpsum quantity={ 3 } /> - </CardBody> - <CardBody> - <div - style={ getStickyStyles( { - top: 69, - bgColor: 'paleturquoise', - } ) } - > - <h2>Another wild sticky element appears</h2> - </div> - <MetaphorIpsum quantity={ 3 } /> - </CardBody> - <CardFooter - style={ getStickyStyles( { - bgColor: 'mistyrose', - } ) } - > - <Button variant="primary">Primary noop</Button> - </CardFooter> - </Card> + <NavigatorScreen path="/child/grandchild"> + <h2>This is the grand child screen.</h2> + <NavigatorBackButton variant="secondary"> + Go back + </NavigatorBackButton> </NavigatorScreen> <NavigatorScreen path="/product/:id"> - <ProductDetails /> + <DynamicScreen /> </NavigatorScreen> </> ), }, }; -function getStickyStyles( { - bottom = 0, - bgColor = 'whitesmoke', - top = 0, - zIndex = 1, -} ): React.CSSProperties { - return { - display: 'flex', - position: 'sticky', - top, - bottom, - zIndex, - backgroundColor: bgColor, - }; -} +function DynamicScreen() { + const { params } = useNavigator(); -function MetaphorIpsum( { quantity }: { quantity: number } ) { - const list = [ - 'A loopy clarinet’s year comes with it the thought that the fenny step-son is an ophthalmologist. The literature would have us believe that a glabrate country is not but a rhythm. A beech is a rub from the right perspective. In ancient times few can name an unglossed walrus that isn’t an unspilt trial.', - 'Authors often misinterpret the afterthought as a roseless mother-in-law, when in actuality it feels more like an uncapped thunderstorm. In recent years, some posit the tarry bottle to be less than acerb. They were lost without the unkissed timbale that composed their customer. A donna is a springtime breath.', - 'It’s an undeniable fact, really; their museum was, in this moment, a snotty beef. The swordfishes could be said to resemble prowessed lasagnas. However, the rainier authority comes from a cureless soup. Unfortunately, that is wrong; on the contrary, the cover is a powder.', - ]; - quantity = Math.min( list.length, quantity ); return ( <> - { list.slice( 0, quantity ).map( ( text, key ) => ( - <p style={ { maxWidth: '20em' } } key={ key }> - { text } - </p> - ) ) } + <h2>This is the dynamic screen</h2> + <p> + This screen can parse params dynamically. The current id is:{ ' ' } + { params.id } + </p> + <NavigatorBackButton variant="secondary"> + Go back + </NavigatorBackButton> </> ); } -function ProductDetails() { - const { params } = useNavigator(); - - return ( - <Card> - <CardBody> - <NavigatorBackButton variant="secondary"> - Go back - </NavigatorBackButton> - <p>This is the screen for the product with id: { params.id }</p> - </CardBody> - </Card> - ); -} - -export const NestedNavigator: StoryObj< typeof NavigatorProvider > = { +export const WithNestedInitialPath: StoryObj< typeof NavigatorProvider > = { ...Default, args: { ...Default.args, - initialPath: '/child2/grandchild', - children: ( - <> - <NavigatorScreen path="/"> - <Card> - <CardBody> - <NavigatorButton variant="secondary" path="/child1"> - Go to first child. - </NavigatorButton> - <NavigatorButton variant="secondary" path="/child2"> - Go to second child. - </NavigatorButton> - </CardBody> - </Card> - </NavigatorScreen> - <NavigatorScreen path="/child1"> - <Card> - <CardBody> - This is the first child - <NavigatorBackButton variant="secondary"> - Go back to parent - </NavigatorBackButton> - </CardBody> - </Card> - </NavigatorScreen> - <NavigatorScreen path="/child2"> - <Card> - <CardBody> - This is the second child - <NavigatorBackButton variant="secondary"> - Go back to parent - </NavigatorBackButton> - <NavigatorButton - variant="secondary" - path="/child2/grandchild" - > - Go to grand child. - </NavigatorButton> - </CardBody> - </Card> - </NavigatorScreen> - <NavigatorScreen path="/child2/grandchild"> - <Card> - <CardBody> - This is the grand child - <NavigatorBackButton variant="secondary"> - Go back to parent - </NavigatorBackButton> - </CardBody> - </Card> - </NavigatorScreen> - </> - ), + initialPath: '/child/grandchild', }, }; @@ -307,6 +144,10 @@ const NavigatorButtonWithSkipFocus = ( { return ( <Button { ...props } + style={ { + marginInline: '8px', + ...props.style, + } } onClick={ ( e: React.MouseEvent< HTMLButtonElement > ) => { goTo( path, { skipFocus: true } ); onClick?.( e ); @@ -322,39 +163,28 @@ export const SkipFocus: StoryObj< typeof NavigatorProvider > = { <> <div style={ { - height: 250, - border: '1px solid black', + height: 150, + outline: '1px solid black', + outlineOffset: '-1px', + marginBlockEnd: '1rem', } } > - <NavigatorScreen - path="/" - style={ { - height: '100%', - } } - > - <h1>Home screen</h1> - <NavigatorButton variant="secondary" path="/child"> + <NavigatorScreen path="/"> + <h2>Home screen</h2> + <NavigatorButton variant="primary" path="/child"> Go to child screen. </NavigatorButton> </NavigatorScreen> - <NavigatorScreen - path="/child" - style={ { - height: '100%', - } } - > + + <NavigatorScreen path="/child"> <h2>Child screen</h2> <NavigatorBackButton variant="secondary"> - Go to parent screen. + Go back to home screen </NavigatorBackButton> </NavigatorScreen> </div> - <NavigatorButtonWithSkipFocus - variant="secondary" - path="/child" - style={ { margin: '1rem 2rem' } } - > + <NavigatorButtonWithSkipFocus path="/child"> Go to child screen, but keep focus on this button </NavigatorButtonWithSkipFocus> </> diff --git a/packages/components/src/navigator/use-navigator.ts b/packages/components/src/navigator/use-navigator.ts index 4d917649374d53..7ac35d73150d32 100644 --- a/packages/components/src/navigator/use-navigator.ts +++ b/packages/components/src/navigator/use-navigator.ts @@ -12,7 +12,7 @@ import type { Navigator } from './types'; /** * Retrieves a `navigator` instance. */ -function useNavigator(): Navigator { +export function useNavigator(): Navigator { const { location, params, goTo, goBack, goToParent } = useContext( NavigatorContext ); @@ -24,5 +24,3 @@ function useNavigator(): Navigator { params, }; } - -export default useNavigator; From bcf7a915ddf550b4844fb1ee39e68c780bf1d836 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Wed, 28 Aug 2024 12:17:50 -0500 Subject: [PATCH 0576/1908] Rename Alt to Alternative Text in content only image toolbar (#64841) Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- packages/block-library/src/image/image.js | 2 +- test/e2e/specs/editor/various/pattern-overrides.spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 2eec1cd185ed76..996d011b5e62a1 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -641,7 +641,7 @@ export default function Image( { } } > { _x( - 'Alt', + 'Alternative text', 'Alternative text for an image. Block toolbar label, a low character count is preferred.' ) } </ToolbarButton> diff --git a/test/e2e/specs/editor/various/pattern-overrides.spec.js b/test/e2e/specs/editor/various/pattern-overrides.spec.js index 88d45ac5d8d3c6..83f2f880f3bf1b 100644 --- a/test/e2e/specs/editor/various/pattern-overrides.spec.js +++ b/test/e2e/specs/editor/various/pattern-overrides.spec.js @@ -1131,7 +1131,7 @@ test.describe( 'Pattern Overrides', () => { /\/wp-content\/uploads\// ); await editor.showBlockToolbar(); - await editor.clickBlockToolbarButton( 'Alt' ); + await editor.clickBlockToolbarButton( 'Alternative text' ); await page .getByRole( 'textbox', { name: 'alternative text' } ) .fill( 'Test Image' ); From 49a31879df9c27c520ad583d177c6c3af4b1251f Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Wed, 28 Aug 2024 12:27:46 -0500 Subject: [PATCH 0577/1908] Only show title in content only toolbar if has title value (#64840) Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/block-library/src/image/image.js | 91 ++++++++++++----------- 1 file changed, 48 insertions(+), 43 deletions(-) diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 996d011b5e62a1..c6fbdc8fee43d4 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -681,51 +681,56 @@ export default function Image( { /> ) } /> - <Dropdown - popoverProps={ { position: 'bottom right' } } - renderToggle={ ( { isOpen, onToggle } ) => ( - <ToolbarButton - onClick={ onToggle } - aria-haspopup="true" - aria-expanded={ isOpen } - onKeyDown={ ( event ) => { - if ( ! isOpen && event.keyCode === DOWN ) { - event.preventDefault(); - onToggle(); - } - } } - > - { __( 'Title' ) } - </ToolbarButton> - ) } - renderContent={ () => ( - <TextControl - __next40pxDefaultSize - className="wp-block-image__toolbar_content_textarea" - __nextHasNoMarginBottom - label={ __( 'Title attribute' ) } - value={ title || '' } - onChange={ onSetTitle } - disabled={ lockTitleControls } - help={ - lockTitleControls ? ( - <>{ lockTitleControlsMessage }</> - ) : ( - <> - { __( - 'Describe the role of this image on the page.' - ) } - <ExternalLink href="https://www.w3.org/TR/html52/dom.html#the-title-attribute"> + { title && ( + <Dropdown + popoverProps={ { position: 'bottom right' } } + renderToggle={ ( { isOpen, onToggle } ) => ( + <ToolbarButton + onClick={ onToggle } + aria-haspopup="true" + aria-expanded={ isOpen } + onKeyDown={ ( event ) => { + if ( + ! isOpen && + event.keyCode === DOWN + ) { + event.preventDefault(); + onToggle(); + } + } } + > + { __( 'Title' ) } + </ToolbarButton> + ) } + renderContent={ () => ( + <TextControl + __next40pxDefaultSize + className="wp-block-image__toolbar_content_textarea" + __nextHasNoMarginBottom + label={ __( 'Title attribute' ) } + value={ title || '' } + onChange={ onSetTitle } + disabled={ lockTitleControls } + help={ + lockTitleControls ? ( + <>{ lockTitleControlsMessage }</> + ) : ( + <> { __( - '(Note: many devices and browsers do not display this text.)' + 'Describe the role of this image on the page.' ) } - </ExternalLink> - </> - ) - } - /> - ) } - /> + <ExternalLink href="https://www.w3.org/TR/html52/dom.html#the-title-attribute"> + { __( + '(Note: many devices and browsers do not display this text.)' + ) } + </ExternalLink> + </> + ) + } + /> + ) } + /> + ) } </BlockControls> ) } <InspectorControls> From affacdb7b6114ac69a4d22fa4013af8945048b24 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 28 Aug 2024 22:57:50 +0400 Subject: [PATCH 0578/1908] Editor: Don't use selector shortcuts for the Site data (#64884) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- packages/block-library/src/home-link/edit.js | 11 ++++------- .../edit-post/src/store/private-selectors.js | 5 +++-- .../src/components/add-new-template/index.js | 12 ++++-------- .../edit-site/src/components/site-hub/index.js | 18 ++++++------------ .../use-init-edited-entity-from-url.js | 7 +++---- .../src/hooks/commands/use-common-commands.js | 8 +++----- .../src/components/page-attributes/parent.js | 9 +++++---- .../src/components/preview-dropdown/index.js | 4 ++-- packages/editor/src/store/private-actions.js | 4 +++- 9 files changed, 33 insertions(+), 45 deletions(-) diff --git a/packages/block-library/src/home-link/edit.js b/packages/block-library/src/home-link/edit.js index ec9ae2864e3d50..fa6b27a3e2128b 100644 --- a/packages/block-library/src/home-link/edit.js +++ b/packages/block-library/src/home-link/edit.js @@ -19,13 +19,10 @@ import { useEffect } from '@wordpress/element'; const preventDefault = ( event ) => event.preventDefault(); export default function HomeEdit( { attributes, setAttributes, context } ) { - const { homeUrl } = useSelect( ( select ) => { - const { - getUnstableBase, // Site index. - } = select( coreStore ); - return { - homeUrl: getUnstableBase()?.home, - }; + const homeUrl = useSelect( ( select ) => { + // Site index. + return select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.home; }, [] ); const { __unstableMarkNextChangeAsNotPersistent } = useDispatch( blockEditorStore ); diff --git a/packages/edit-post/src/store/private-selectors.js b/packages/edit-post/src/store/private-selectors.js index 0c0ac3c518024d..246b2754d895ab 100644 --- a/packages/edit-post/src/store/private-selectors.js +++ b/packages/edit-post/src/store/private-selectors.js @@ -12,12 +12,13 @@ export const getEditedPostTemplateId = createRegistrySelector( type: postType, slug, } = select( editorStore ).getCurrentPost(); - const { getSite, getEntityRecords, canUser } = select( coreStore ); + const { getEntityRecord, getEntityRecords, canUser } = + select( coreStore ); const siteSettings = canUser( 'read', { kind: 'root', name: 'site', } ) - ? getSite() + ? getEntityRecord( 'root', 'site' ) : undefined; // First check if the current page is set as the posts page. const isPostsPage = +postId === siteSettings?.page_for_posts; diff --git a/packages/edit-site/src/components/add-new-template/index.js b/packages/edit-site/src/components/add-new-template/index.js index 8a900ecc958009..933ea6df1198bb 100644 --- a/packages/edit-site/src/components/add-new-template/index.js +++ b/packages/edit-site/src/components/add-new-template/index.js @@ -166,14 +166,10 @@ function NewTemplateModal( { onClose } ) { const isMobile = useViewportMatch( 'medium', '<' ); - const { homeUrl } = useSelect( ( select ) => { - const { - getUnstableBase, // Site index. - } = select( coreStore ); - - return { - homeUrl: getUnstableBase()?.home, - }; + const homeUrl = useSelect( ( select ) => { + // Site index. + return select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.home; }, [] ); const TEMPLATE_SHORT_DESCRIPTIONS = { diff --git a/packages/edit-site/src/components/site-hub/index.js b/packages/edit-site/src/components/site-hub/index.js index 66439cd0712fab..7fe929d20a1db2 100644 --- a/packages/edit-site/src/components/site-hub/index.js +++ b/packages/edit-site/src/components/site-hub/index.js @@ -36,15 +36,12 @@ const SiteHub = memo( const { dashboardLink, homeUrl, siteTitle } = useSelect( ( select ) => { const { getSettings } = unlock( select( editSiteStore ) ); - const { - getSite, - getUnstableBase, // Site index. - } = select( coreStore ); - const _site = getSite(); + const { getEntityRecord } = select( coreStore ); + const _site = getEntityRecord( 'root', 'site' ); return { dashboardLink: getSettings().__experimentalDashboardLink || 'index.php', - homeUrl: getUnstableBase()?.home, + homeUrl: getEntityRecord( 'root', '__unstableBase' )?.home, siteTitle: ! _site?.title && !! _site?.url ? filterURLForDisplay( _site?.url ) @@ -128,13 +125,10 @@ export const SiteHubMobile = memo( const { navigate } = useContext( SidebarNavigationContext ); const { homeUrl, siteTitle } = useSelect( ( select ) => { - const { - getSite, - getUnstableBase, // Site index. - } = select( coreStore ); - const _site = getSite(); + const { getEntityRecord } = select( coreStore ); + const _site = getEntityRecord( 'root', 'site' ); return { - homeUrl: getUnstableBase()?.home, + homeUrl: getEntityRecord( 'root', '__unstableBase' )?.home, siteTitle: ! _site?.title && !! _site?.url ? filterURLForDisplay( _site?.url ) diff --git a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js index a0707802846fcf..ab6ea92bac4413 100644 --- a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js +++ b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js @@ -37,10 +37,9 @@ function useResolveEditedEntityAndContext( { postId, postType } ) { url, frontPageTemplateId, } = useSelect( ( select ) => { - const { getSite, getUnstableBase, getEntityRecords } = - select( coreDataStore ); - const siteData = getSite(); - const base = getUnstableBase(); + const { getEntityRecord, getEntityRecords } = select( coreDataStore ); + const siteData = getEntityRecord( 'root', 'site' ); + const base = getEntityRecord( 'root', '__unstableBase' ); const templates = getEntityRecords( 'postType', TEMPLATE_POST_TYPE, { per_page: -1, } ); diff --git a/packages/edit-site/src/hooks/commands/use-common-commands.js b/packages/edit-site/src/hooks/commands/use-common-commands.js index 2b5d0d8614c954..ca6e2d1c6b45dd 100644 --- a/packages/edit-site/src/hooks/commands/use-common-commands.js +++ b/packages/edit-site/src/hooks/commands/use-common-commands.js @@ -287,11 +287,9 @@ function useGlobalStylesOpenRevisionsCommands() { export function useCommonCommands() { const homeUrl = useSelect( ( select ) => { - const { - getUnstableBase, // Site index. - } = select( coreStore ); - - return getUnstableBase()?.home; + // Site index. + return select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.home; }, [] ); useCommand( { diff --git a/packages/editor/src/components/page-attributes/parent.js b/packages/editor/src/components/page-attributes/parent.js index 1018834d1b9fca..0f19ffcdd5daa4 100644 --- a/packages/editor/src/components/page-attributes/parent.js +++ b/packages/editor/src/components/page-attributes/parent.js @@ -222,10 +222,11 @@ function PostParentToggle( { isOpen, onClick } ) { } export function ParentRow() { - const homeUrl = useSelect( - ( select ) => select( coreStore ).getUnstableBase()?.home, - [] - ); + const homeUrl = useSelect( ( select ) => { + // Site index. + return select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.home; + }, [] ); // Use internal state instead of a ref to make sure that the component // re-renders when the popover's anchor updates. const [ popoverAnchor, setPopoverAnchor ] = useState( null ); diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js index ef41fc087f1d2e..ec30d55cf0f17b 100644 --- a/packages/editor/src/components/preview-dropdown/index.js +++ b/packages/editor/src/components/preview-dropdown/index.js @@ -39,14 +39,14 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { showIconLabels, } = useSelect( ( select ) => { const { getDeviceType, getCurrentPostType } = select( editorStore ); - const { getUnstableBase, getPostType } = select( coreStore ); + const { getEntityRecord, getPostType } = select( coreStore ); const { get } = select( preferencesStore ); const { __unstableGetEditorMode } = select( blockEditorStore ); const _currentPostType = getCurrentPostType(); return { deviceType: getDeviceType(), editorMode: __unstableGetEditorMode(), - homeUrl: getUnstableBase()?.home, + homeUrl: getEntityRecord( 'root', '__unstableBase' )?.home, isTemplate: _currentPostType === 'wp_template', isViewable: getPostType( _currentPostType )?.viewable ?? false, showIconLabels: get( 'core', 'showIconLabels' ), diff --git a/packages/editor/src/store/private-actions.js b/packages/editor/src/store/private-actions.js index e22929011256d5..358d00af396bbb 100644 --- a/packages/editor/src/store/private-actions.js +++ b/packages/editor/src/store/private-actions.js @@ -137,7 +137,9 @@ export const saveDirtyEntities = { kind: 'postType', name: 'wp_navigation' }, ]; const saveNoticeId = 'site-editor-save-success'; - const homeUrl = registry.select( coreStore ).getUnstableBase()?.home; + const homeUrl = registry + .select( coreStore ) + .getEntityRecord( 'root', '__unstableBase' )?.home; registry.dispatch( noticesStore ).removeNotice( saveNoticeId ); const entitiesToSave = dirtyEntityRecords.filter( ( { kind, name, key, property } ) => { From 9b1af681b4166f6fc857f08e4d74ee34a0f35dc3 Mon Sep 17 00:00:00 2001 From: David Calhoun <github@davidcalhoun.me> Date: Wed, 28 Aug 2024 15:44:21 -0400 Subject: [PATCH 0579/1908] task: Remove dcalhoun code owner (#64886) --- .github/CODEOWNERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bf778bd434e110..2ec03cba722c6b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -119,9 +119,9 @@ /packages/plugins @gziolo @adamsilverstein # Rich Text -/packages/format-library @ellatrix @dcalhoun -/packages/rich-text @ellatrix @dcalhoun -/packages/block-editor/src/components/rich-text @ellatrix @dcalhoun +/packages/format-library @ellatrix +/packages/rich-text @ellatrix +/packages/block-editor/src/components/rich-text @ellatrix # Project Management /.github @desrosj From bee05392aa23c0e2769558b0ede6581f0c53eb75 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 28 Aug 2024 23:29:39 +0200 Subject: [PATCH 0580/1908] Contemplate empty strings and false values (#64881) Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- packages/editor/src/bindings/post-meta.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index 87c06cc45e009a..a1575f2b4baba2 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -53,13 +53,14 @@ export default { } // Check that the custom field is not protected and available in the REST API. - const isFieldExposed = !! select( coreDataStore ).getEntityRecord( + // Empty string or `false` could be a valid value, so we need to check if the field value is undefined. + const fieldValue = select( coreDataStore ).getEntityRecord( 'postType', postType, context?.postId )?.meta?.[ args.key ]; - if ( ! isFieldExposed ) { + if ( fieldValue === undefined ) { return false; } From 832543917932ec258b420cfdeb99b315b57a1431 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 28 Aug 2024 23:44:09 +0200 Subject: [PATCH 0581/1908] DropdownMenuV2: remove flashing styles when moving focus with keyboard (#64873) * DropdownMenuV2: remove flashing styles when moving focus with keyboard * CHANGELOG * Add comment about ariakit issue --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: diegohaz <hazdiego@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/dropdown-menu-v2/styles.ts | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index f3c851344b9769..ce3fd808e7ed89 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -51,6 +51,7 @@ ### Internal +- `DropdownMenu` v2: fix flashing menu item styles when using keyboard ([#64873](https://github.com/WordPress/gutenberg/pull/64873)). - `DropdownMenu` v2: refactor to overloaded naming convention ([#64654](https://github.com/WordPress/gutenberg/pull/64654)). - `Composite` V2: fix Storybook docgen ([#64682](https://github.com/WordPress/gutenberg/pull/64682)). diff --git a/packages/components/src/dropdown-menu-v2/styles.ts b/packages/components/src/dropdown-menu-v2/styles.ts index 9e71316b6b9dc5..a39ef83326c3aa 100644 --- a/packages/components/src/dropdown-menu-v2/styles.ts +++ b/packages/components/src/dropdown-menu-v2/styles.ts @@ -171,16 +171,23 @@ const baseItem = css` cursor: not-allowed; } - /* Hover */ - &[data-active-item]:not( [data-focus-visible] ):not( + /* Active item (including hover) + * Note: we should be able to remove :focus-visible once + * https://github.com/ariakit/ariakit/issues/4083 is fixed and released + */ + &[data-active-item]:not( [data-focus-visible] ):not( :focus-visible ):not( [aria-disabled='true'] ) { background-color: ${ COLORS.theme.accent }; color: ${ COLORS.white }; } - /* Keyboard focus (focus-visible) */ - &[data-focus-visible] { + /* Keyboard focus (focus-visible) + * Note: we should be able to remove :focus-visible once + * https://github.com/ariakit/ariakit/issues/4083 is fixed and released + */ + &[data-focus-visible], + &:focus-visible { box-shadow: 0 0 0 1.5px ${ COLORS.theme.accent }; /* Only visible in Windows High Contrast mode */ From d574952a66fa9bf40fb03df937d8bed84e89b899 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 28 Aug 2024 23:59:49 +0200 Subject: [PATCH 0582/1908] Dataviews filter: move resetValueOnSelect prop to combobox item (#64852) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/dataviews-filters/search-widget.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataviews/src/components/dataviews-filters/search-widget.tsx b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx index ca24de59b1ea73..1b369222b8f28c 100644 --- a/packages/dataviews/src/components/dataviews-filters/search-widget.tsx +++ b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx @@ -206,7 +206,6 @@ function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) { }, [ filter.elements, deferredSearchValue ] ); return ( <Ariakit.ComboboxProvider - resetValueOnSelect={ false } selectedValue={ currentValue } setSelectedValue={ ( value ) => { const newFilters = currentFilter @@ -266,6 +265,7 @@ function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) { { matches.map( ( element ) => { return ( <Ariakit.ComboboxItem + resetValueOnSelect={ false } key={ element.value } value={ element.value } className="dataviews-filters__search-widget-listitem" From d82ce72ffc9260d3ef1693fbdc9c28ca7d7bccbc Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 29 Aug 2024 10:23:45 +0900 Subject: [PATCH 0583/1908] Global Styles: Adjust spacing of background panel (#64880) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/components/global-styles/background-panel.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index e230e6e600508c..58703dcbc9929e 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -692,16 +692,14 @@ function BackgroundToolsPanel( { }; return ( - <VStack - as={ ToolsPanel } - spacing={ 2 } + <ToolsPanel label={ headerLabel } resetAll={ resetAll } panelId={ panelId } dropdownMenuProps={ dropdownMenuProps } > { children } - </VStack> + </ToolsPanel> ); } From d578068d542341e18f98eb698f6e73c4219ce7bf Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 29 Aug 2024 08:19:43 +0400 Subject: [PATCH 0584/1908] Block Editor: Update conditions when the Shuffle button can be displayed (#64888) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- .../block-editor/src/components/block-toolbar/index.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 6c6acd662ed962..90e6394d0975dd 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -65,6 +65,7 @@ export function PrivateBlockToolbar( { shouldShowVisualToolbar, showParentSelector, isUsingBindings, + canRemove, } = useSelect( ( select ) => { const { getBlockName, @@ -75,6 +76,7 @@ export function PrivateBlockToolbar( { getBlockRootClientId, getBlockEditingMode, getBlockAttributes, + canRemoveBlock, } = select( blockEditorStore ); const selectedBlockClientIds = getSelectedBlockClientIds(); const selectedBlockClientId = selectedBlockClientIds[ 0 ]; @@ -115,6 +117,7 @@ export function PrivateBlockToolbar( { selectedBlockClientIds.length === 1 && _isDefaultEditingMode, isUsingBindings: _isUsingBindings, + canRemove: canRemoveBlock( selectedBlockClientId ), }; }, [] ); @@ -195,7 +198,9 @@ export function PrivateBlockToolbar( { </ToolbarGroup> </div> ) } - <Shuffle clientId={ blockClientId } /> + { ! isMultiToolbar && canRemove && ( + <Shuffle clientId={ blockClientId } /> + ) } { shouldShowVisualToolbar && isMultiToolbar && ( <BlockGroupToolbar /> ) } From 47bf56ad0da4e733e98dcd53f205a973ebcda631 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 29 Aug 2024 11:43:01 +0700 Subject: [PATCH 0585/1908] Block Styles: Ensure unique classname generation for variations (#64511) * Block Styles: Ensure unique classname generation for variations * Add backport changelog Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: asafm7 <asafm7@git.wordpress.org> --- backport-changelog/6.7/7200.md | 3 +++ lib/block-supports/block-style-variations.php | 11 ++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 backport-changelog/6.7/7200.md diff --git a/backport-changelog/6.7/7200.md b/backport-changelog/6.7/7200.md new file mode 100644 index 00000000000000..520b3d6054cc18 --- /dev/null +++ b/backport-changelog/6.7/7200.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7200 + +* https://github.com/WordPress/gutenberg/pull/64511 diff --git a/lib/block-supports/block-style-variations.php b/lib/block-supports/block-style-variations.php index 73e4f9fce25843..3942fed24b98a8 100644 --- a/lib/block-supports/block-style-variations.php +++ b/lib/block-supports/block-style-variations.php @@ -11,12 +11,15 @@ * * @since 6.6.0 * + * @deprecated 6.7.0 + * * @param array $block Block object. * @param string $variation Slug for the block style variation. * * @return string The unique variation name. */ function gutenberg_create_block_style_variation_instance_name( $block, $variation ) { + _deprecated_function( __FUNCTION__, '6.7.0' ); return $variation . '--' . md5( serialize( $block ) ); } @@ -119,7 +122,7 @@ function gutenberg_render_block_style_variation_support_styles( $parsed_block ) // theme_json data. gutenberg_resolve_block_style_variation_ref_values( $variation_data, $theme_json ); - $variation_instance = gutenberg_create_block_style_variation_instance_name( $parsed_block, $variation ); + $variation_instance = wp_unique_id( $variation . '--' ); $class_name = "is-style-$variation_instance"; $updated_class_name = $parsed_block['attrs']['className'] . " $class_name"; @@ -224,11 +227,9 @@ function gutenberg_render_block_style_variation_class_name( $block_content, $blo /* * Matches a class prefixed by `is-style`, followed by the - * variation slug, then `--`, and finally a hash. - * - * See `gutenberg_create_block_style_variation_instance_name` for class generation. + * variation slug, then `--`, and finally an instance number. */ - preg_match( '/\bis-style-(\S+?--\w+)\b/', $block['attrs']['className'], $matches ); + preg_match( '/\bis-style-(\S+?--\d+)\b/', $block['attrs']['className'], $matches ); if ( empty( $matches ) ) { return $block_content; From a9f239b0ef9cafc8e744ebccfa8c529351d35b7c Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 29 Aug 2024 11:28:33 +0400 Subject: [PATCH 0586/1908] Zoom Out: Don't pass 'rootClientId' to block lock selectors (#64887) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- docs/reference-guides/data/data-core-block-editor.md | 2 +- .../src/components/block-tools/zoom-out-popover.js | 9 ++------- .../src/components/block-tools/zoom-out-toolbar.js | 12 ++++-------- packages/block-editor/src/store/selectors.js | 2 +- 4 files changed, 8 insertions(+), 17 deletions(-) diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index 040a10f8f506c2..c6552ef431cef8 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -84,7 +84,7 @@ _Parameters_ _Returns_ -- `boolean | undefined`: Whether the given block is allowed to be moved. +- `boolean`: Whether the given block is allowed to be moved. ### canMoveBlocks diff --git a/packages/block-editor/src/components/block-tools/zoom-out-popover.js b/packages/block-editor/src/components/block-tools/zoom-out-popover.js index bb127351f09d87..a1f2990a5cc1ef 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-popover.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-popover.js @@ -11,12 +11,8 @@ import useSelectedBlockToolProps from './use-selected-block-tool-props'; import ZoomOutToolbar from './zoom-out-toolbar'; export default function ZoomOutPopover( { clientId, __unstableContentRef } ) { - const { - capturingClientId, - isInsertionPointVisible, - lastClientId, - rootClientId, - } = useSelectedBlockToolProps( clientId ); + const { capturingClientId, isInsertionPointVisible, lastClientId } = + useSelectedBlockToolProps( clientId ); const popoverProps = useBlockToolbarPopoverProps( { contentElement: __unstableContentRef?.current, @@ -44,7 +40,6 @@ export default function ZoomOutPopover( { clientId, __unstableContentRef } ) { <ZoomOutToolbar __unstableContentRef={ __unstableContentRef } clientId={ clientId } - rootClientId={ rootClientId } /> </BlockPopover> ); diff --git a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js index b5503c253548b1..0d3df9e20dfc54 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js @@ -21,11 +21,7 @@ import BlockMover from '../block-mover'; import Shuffle from '../block-toolbar/shuffle'; import NavigableToolbar from '../navigable-toolbar'; -export default function ZoomOutToolbar( { - clientId, - rootClientId, - __unstableContentRef, -} ) { +export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { const selected = useSelect( ( select ) => { const { @@ -65,11 +61,11 @@ export default function ZoomOutToolbar( { isBlockTemplatePart, isNextBlockTemplatePart, isPrevBlockTemplatePart, - canRemove: canRemoveBlock( clientId, rootClientId ), - canMove: canMoveBlock( clientId, rootClientId ), + canRemove: canRemoveBlock( clientId ), + canMove: canMoveBlock( clientId ), }; }, - [ clientId, rootClientId ] + [ clientId ] ); const { diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 32fa081b390ae9..8d4d94bdaa98f7 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -1752,7 +1752,7 @@ export function canRemoveBlocks( state, clientIds ) { * @param {Object} state Editor state. * @param {string} clientId The block client Id. * - * @return {boolean | undefined} Whether the given block is allowed to be moved. + * @return {boolean} Whether the given block is allowed to be moved. */ export function canMoveBlock( state, clientId ) { const attributes = getBlockAttributes( state, clientId ); From aa2e342480b5eb7961165fb2a1b8979c65e68e43 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Thu, 29 Aug 2024 13:40:14 +0530 Subject: [PATCH 0587/1908] Add 'Reset' option to MediaReplaceFlow component (#64826) * Add reset option in MediaReplaceFlow component * Add media reset option in toolbar of media-text block * Refactor MediaReplaceFlow component use in cover, image and post-featured-image blocks * Refactor MediaReplaceFlow component use in site-logo block * Refactor BackgroundImageControls component under global styles * Add media reset option in video, audio and file blocks * Fix onReset argument value error on image block * Remove unused MenuItem component from blocks * Reset attribute on reset option click in file block * Fix issue of reset option in media-text block Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../global-styles/background-panel.js | 14 ++++---------- .../src/components/media-replace-flow/index.js | 13 ++++++++++++- packages/block-library/src/audio/edit.js | 1 + .../src/cover/edit/block-controls.js | 13 ++----------- packages/block-library/src/file/edit.js | 11 +++++++++++ packages/block-library/src/image/image.js | 8 ++------ .../src/media-text/media-container.js | 9 ++------- .../src/post-featured-image/edit.js | 8 ++------ packages/block-library/src/site-logo/edit.js | 18 +++--------------- packages/block-library/src/video/edit.js | 1 + 10 files changed, 40 insertions(+), 56 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index 58703dcbc9929e..93fed5780e454d 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -432,6 +432,10 @@ function BackgroundImageControls( { } variant="secondary" onError={ onUploadError } + onReset={ () => { + closeAndFocus(); + onResetImage(); + } } > { canRemove && ( <MenuItem @@ -444,16 +448,6 @@ function BackgroundImageControls( { { __( 'Remove' ) } </MenuItem> ) } - { hasValue && ( - <MenuItem - onClick={ () => { - closeAndFocus(); - onResetImage(); - } } - > - { __( 'Reset' ) } - </MenuItem> - ) } </MediaReplaceFlow> <DropZone onFilesDrop={ onFilesDrop } diff --git a/packages/block-editor/src/components/media-replace-flow/index.js b/packages/block-editor/src/components/media-replace-flow/index.js index 6a52e28c223671..0da15033a86bf0 100644 --- a/packages/block-editor/src/components/media-replace-flow/index.js +++ b/packages/block-editor/src/components/media-replace-flow/index.js @@ -48,6 +48,7 @@ const MediaReplaceFlow = ( { onError, onSelect, onSelectURL, + onReset, onToggleFeaturedImage, useFeaturedImage, onFilesUpload = noop, @@ -75,7 +76,7 @@ const MediaReplaceFlow = ( { } // We need to set a timeout for showing the notice // so that VoiceOver and possibly other screen readers - // can announce the error afer the toolbar button + // can announce the error after the toolbar button // regains focus once the upload dialog closes. // Otherwise VO simply skips over the notice and announces // the focused element and the open menu. @@ -202,6 +203,16 @@ const MediaReplaceFlow = ( { { __( 'Use featured image' ) } </MenuItem> ) } + { mediaURL && onReset && ( + <MenuItem + onClick={ () => { + onReset(); + onClose(); + } } + > + { __( 'Reset' ) } + </MenuItem> + ) } { typeof children === 'function' ? children( { onClose } ) : children } diff --git a/packages/block-library/src/audio/edit.js b/packages/block-library/src/audio/edit.js index 3c9f9e11c3b24b..e3b4ca670f957d 100644 --- a/packages/block-library/src/audio/edit.js +++ b/packages/block-library/src/audio/edit.js @@ -155,6 +155,7 @@ function AudioEdit( { onSelect={ onSelectAudio } onSelectURL={ onSelectURL } onError={ onUploadError } + onReset={ () => onSelectAudio( undefined ) } /> </BlockControls> ) } diff --git a/packages/block-library/src/cover/edit/block-controls.js b/packages/block-library/src/cover/edit/block-controls.js index 499aef5e9a8cf7..041566c0a51971 100644 --- a/packages/block-library/src/cover/edit/block-controls.js +++ b/packages/block-library/src/cover/edit/block-controls.js @@ -10,7 +10,6 @@ import { __experimentalBlockFullHeightAligmentControl as FullHeightAlignmentControl, privateApis as blockEditorPrivateApis, } from '@wordpress/block-editor'; -import { MenuItem } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; /** @@ -103,16 +102,8 @@ export default function CoverBlockControls( { onToggleFeaturedImage={ toggleUseFeaturedImage } useFeaturedImage={ useFeaturedImage } name={ ! url ? __( 'Add Media' ) : __( 'Replace' ) } - > - { !! url && ( - <MenuItem - className="block-library-cover__reset-button" - onClick={ onClearMedia } - > - { __( 'Reset' ) } - </MenuItem> - ) } - </MediaReplaceFlow> + onReset={ onClearMedia } + /> </BlockControls> </> ); diff --git a/packages/block-library/src/file/edit.js b/packages/block-library/src/file/edit.js index 448b6f5ec73d15..be061d357bffd1 100644 --- a/packages/block-library/src/file/edit.js +++ b/packages/block-library/src/file/edit.js @@ -109,6 +109,16 @@ function FileEdit( { attributes, isSelected, setAttributes, clientId } ) { function onSelectFile( newMedia ) { if ( ! newMedia || ! newMedia.url ) { + // Reset attributes. + setAttributes( { + href: undefined, + fileName: undefined, + textLinkHref: undefined, + id: undefined, + fileId: undefined, + displayPreview: undefined, + previewHeight: undefined, + } ); setTemporaryURL(); return; } @@ -230,6 +240,7 @@ function FileEdit( { attributes, isSelected, setAttributes, clientId } ) { accept="*" onSelect={ onSelectFile } onError={ onUploadError } + onReset={ () => onSelectFile( undefined ) } /> <ClipboardToolbarButton text={ href } diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index c6fbdc8fee43d4..2de316f78ba5d8 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -3,7 +3,6 @@ */ import { isBlobURL } from '@wordpress/blob'; import { - MenuItem, ExternalLink, ResizableBox, Spinner, @@ -603,11 +602,8 @@ export default function Image( { onSelect={ onSelectImage } onSelectURL={ onSelectURL } onError={ onUploadError } - > - <MenuItem onClick={ () => onSelectImage( undefined ) }> - { __( 'Reset' ) } - </MenuItem> - </MediaReplaceFlow> + onReset={ () => onSelectImage( undefined ) } + /> </BlockControls> ) } { isSingleSelected && externalBlob && ( diff --git a/packages/block-library/src/media-text/media-container.js b/packages/block-library/src/media-text/media-container.js index 2d8556f9ebe327..986ecad6cc7e69 100644 --- a/packages/block-library/src/media-text/media-container.js +++ b/packages/block-library/src/media-text/media-container.js @@ -62,22 +62,18 @@ function ToolbarEditButton( { onSelectMedia, toggleUseFeaturedImage, useFeaturedImage, - featuredImageURL, } ) { return ( <BlockControls group="other"> <MediaReplaceFlow mediaId={ mediaId } - mediaUrl={ - useFeaturedImage && featuredImageURL - ? featuredImageURL - : mediaUrl - } + mediaURL={ mediaUrl } allowedTypes={ ALLOWED_MEDIA_TYPES } accept="image/*,video/*" onSelect={ onSelectMedia } onToggleFeaturedImage={ toggleUseFeaturedImage } useFeaturedImage={ useFeaturedImage } + onReset={ () => onSelectMedia( undefined ) } /> </BlockControls> ); @@ -200,7 +196,6 @@ function MediaContainer( props, ref ) { } mediaId={ mediaId } toggleUseFeaturedImage={ toggleUseFeaturedImage } - useFeaturedImage={ useFeaturedImage } /> { ( mediaTypeRenderers[ mediaType ] || noop )() } { isTemporaryMedia && <Spinner /> } diff --git a/packages/block-library/src/post-featured-image/edit.js b/packages/block-library/src/post-featured-image/edit.js index 3d54a7415f288b..ff777f707330df 100644 --- a/packages/block-library/src/post-featured-image/edit.js +++ b/packages/block-library/src/post-featured-image/edit.js @@ -10,7 +10,6 @@ import { isBlobURL } from '@wordpress/blob'; import { useEntityProp, store as coreStore } from '@wordpress/core-data'; import { useSelect, useDispatch } from '@wordpress/data'; import { - MenuItem, ToggleControl, PanelBody, Placeholder, @@ -368,11 +367,8 @@ export default function PostFeaturedImageEdit( { accept="image/*" onSelect={ onSelectImage } onError={ onUploadError } - > - <MenuItem onClick={ () => setFeaturedImage( 0 ) }> - { __( 'Reset' ) } - </MenuItem> - </MediaReplaceFlow> + onReset={ () => setFeaturedImage( 0 ) } + /> </BlockControls> ) } <figure { ...blockProps }> diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index e44147529af2b5..81217e6cb5135f 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -14,7 +14,6 @@ import { } from '@wordpress/element'; import { __, isRTL } from '@wordpress/i18n'; import { - MenuItem, PanelBody, RangeControl, ResizableBox, @@ -356,22 +355,11 @@ function SiteLogoReplaceFlow( { return ( <MediaReplaceFlow { ...mediaReplaceProps } + mediaURL={ mediaURL } allowedTypes={ ALLOWED_MEDIA_TYPES } accept={ ACCEPT_MEDIA_STRING } - > - { ( { onClose } ) => - mediaURL && ( - <MenuItem - onClick={ () => { - onRemoveLogo(); - onClose(); - } } - > - { __( 'Reset' ) } - </MenuItem> - ) - } - </MediaReplaceFlow> + onReset={ onRemoveLogo } + /> ); } diff --git a/packages/block-library/src/video/edit.js b/packages/block-library/src/video/edit.js index 63f633a41adf94..d72dd5463cde33 100644 --- a/packages/block-library/src/video/edit.js +++ b/packages/block-library/src/video/edit.js @@ -208,6 +208,7 @@ function VideoEdit( { onSelect={ onSelectVideo } onSelectURL={ onSelectURL } onError={ onUploadError } + onReset={ () => onSelectVideo( undefined ) } /> </BlockControls> </> From 6986b13f2d759ced09bd4f06fcad297bd406cf1d Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Thu, 29 Aug 2024 11:54:22 +0200 Subject: [PATCH 0588/1908] Fix: Impossible to see pagination on viewports between small and medium. (#64844) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/edit-site/src/components/page/style.scss | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/page/style.scss b/packages/edit-site/src/components/page/style.scss index 99c8d793c6f3a3..03e062a576b6e6 100644 --- a/packages/edit-site/src/components/page/style.scss +++ b/packages/edit-site/src/components/page/style.scss @@ -1,11 +1,15 @@ .edit-site-page { color: $gray-800; background: $white; - height: 100%; + height: calc(100% - #{$header-height}); /* stylelint-disable-next-line property-no-unknown -- '@container' not globally permitted */ container: edit-site-page / inline-size; transition: width ease-out 0.2s; @include reduce-motion("transition"); + + @include break-medium() { + height: 100%; + } } .edit-site-page-header { From 99e8faa1328e17ccc9a1354e192d008ce67afb4d Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 29 Aug 2024 15:21:53 +0400 Subject: [PATCH 0589/1908] Site Editor: Remove unused 'useSiteEditorSettings' hook (#64892) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../block-editor/use-site-editor-settings.js | 18 ------------------ packages/editor/src/private-apis.js | 2 -- 2 files changed, 20 deletions(-) diff --git a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js index 475640439c76bd..e4d70402efa8be 100644 --- a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js +++ b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js @@ -3,7 +3,6 @@ */ import { useSelect } from '@wordpress/data'; import { useMemo } from '@wordpress/element'; -import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { usePrevious } from '@wordpress/compose'; @@ -15,7 +14,6 @@ import { unlock } from '../../lock-unlock'; import useNavigateToEntityRecord from './use-navigate-to-entity-record'; import { FOCUSABLE_ENTITIES } from '../../utils/constants'; -const { useBlockEditorSettings } = unlock( editorPrivateApis ); const { useLocation, useHistory } = unlock( routerPrivateApis ); function useNavigateToPreviousEntityRecord() { @@ -83,19 +81,3 @@ export function useSpecificEditorSettings() { return defaultEditorSettings; } - -export default function useSiteEditorSettings() { - const defaultEditorSettings = useSpecificEditorSettings(); - const { postType, postId } = useSelect( ( select ) => { - const { getEditedPostType, getEditedPostId } = unlock( - select( editSiteStore ) - ); - const usedPostType = getEditedPostType(); - const usedPostId = getEditedPostId(); - return { - postType: usedPostType, - postId: usedPostId, - }; - }, [] ); - return useBlockEditorSettings( defaultEditorSettings, postType, postId ); -} diff --git a/packages/editor/src/private-apis.js b/packages/editor/src/private-apis.js index 629600888a98eb..d4a5c3eebbb4ce 100644 --- a/packages/editor/src/private-apis.js +++ b/packages/editor/src/private-apis.js @@ -9,7 +9,6 @@ import * as interfaceApis from '@wordpress/interface'; import { lock } from './lock-unlock'; import { EntitiesSavedStatesExtensible } from './components/entities-saved-states'; import EditorContentSlotFill from './components/editor-interface/content-slot-fill'; -import useBlockEditorSettings from './components/provider/use-block-editor-settings'; import BackButton from './components/header/back-button'; import CreateTemplatePartModal from './components/create-template-part-modal'; import Editor from './components/editor'; @@ -51,7 +50,6 @@ lock( privateApis, { bootstrapBlockBindingsSourcesFromServer, // This is a temporary private API while we're updating the site editor to use EditorProvider. - useBlockEditorSettings, interfaceStore, ...remainingInterfaceApis, } ); From bfbc9f6de5a25631ea31ee78430b6fe990bdf1ea Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Thu, 29 Aug 2024 15:38:51 +0300 Subject: [PATCH 0590/1908] ContentOnly: Add support for block styles on top-level contentOnly locked blocks (#64872) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/block-inspector/index.js | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index 9daf29f8043bba..75b5239f47d6cc 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -32,6 +32,14 @@ import { useBorderPanelLabel } from '../../hooks/border'; import { unlock } from '../../lock-unlock'; +function BlockStylesPanel( { clientId } ) { + return ( + <PanelBody title={ __( 'Styles' ) }> + <BlockStyles clientId={ clientId } /> + </PanelBody> + ); +} + function BlockInspectorLockedBlocks( { topLevelLockedBlock } ) { const contentClientIds = useSelect( ( select ) => { @@ -48,6 +56,15 @@ function BlockInspectorLockedBlocks( { topLevelLockedBlock } ) { }, [ topLevelLockedBlock ] ); + const hasBlockStyles = useSelect( + ( select ) => { + const { getBlockName } = select( blockEditorStore ); + const { getBlockStyles } = select( blocksStore ); + return !! getBlockStyles( getBlockName( topLevelLockedBlock ) ) + ?.length; + }, + [ topLevelLockedBlock ] + ); const blockInformation = useBlockDisplayInformation( topLevelLockedBlock ); return ( <div className="block-editor-block-inspector"> @@ -57,6 +74,9 @@ function BlockInspectorLockedBlocks( { topLevelLockedBlock } ) { /> <BlockVariationTransforms blockClientId={ topLevelLockedBlock } /> <BlockInfo.Slot /> + { hasBlockStyles && ( + <BlockStylesPanel clientId={ topLevelLockedBlock } /> + ) } { contentClientIds.length > 0 && ( <PanelBody title={ __( 'Content' ) }> <BlockQuickNavigation clientIds={ contentClientIds } /> @@ -81,7 +101,6 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { getContentLockingParent, getTemplateLock, } = unlock( select( blockEditorStore ) ); - const _selectedBlockClientId = getSelectedBlockClientId(); const _selectedBlockName = _selectedBlockClientId && getBlockName( _selectedBlockClientId ); @@ -276,11 +295,7 @@ const BlockInspectorSingleBlock = ( { clientId, blockName } ) => { { ! showTabs && ( <> { hasBlockStyles && ( - <div> - <PanelBody title={ __( 'Styles' ) }> - <BlockStyles clientId={ clientId } /> - </PanelBody> - </div> + <BlockStylesPanel clientId={ clientId } /> ) } <InspectorControls.Slot /> <InspectorControls.Slot group="list" /> From 59814040f96c048f086c8af00d2700a7dea88fe5 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 29 Aug 2024 16:43:54 +0400 Subject: [PATCH 0591/1908] Site Editor: Add 'OPTIONS /page' to preloaded paths (#64890) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- backport-changelog/6.7/7270.md | 3 +++ lib/compat/wordpress-6.7/rest-api.php | 6 ++++++ 2 files changed, 9 insertions(+) create mode 100644 backport-changelog/6.7/7270.md diff --git a/backport-changelog/6.7/7270.md b/backport-changelog/6.7/7270.md new file mode 100644 index 00000000000000..358b0d7c9a9674 --- /dev/null +++ b/backport-changelog/6.7/7270.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7270 + +* https://github.com/WordPress/gutenberg/pull/64890 diff --git a/lib/compat/wordpress-6.7/rest-api.php b/lib/compat/wordpress-6.7/rest-api.php index f2f5d72104527d..c5e2927198da0c 100644 --- a/lib/compat/wordpress-6.7/rest-api.php +++ b/lib/compat/wordpress-6.7/rest-api.php @@ -24,6 +24,12 @@ function gutenberg_block_editor_preload_paths_6_7( $paths, $context ) { if ( false !== $parts_key ) { $paths[ $parts_key ] = '/wp/v2/types/wp_template_part?context=edit'; } + + $page_options_path = array( rest_get_route_for_post_type_items( 'page' ), 'OPTIONS' ); + $page_options_key = array_search( $page_options_path, $paths, true ); + if ( false === $page_options_key ) { + $paths[] = $page_options_path; + } } if ( 'core/edit-post' === $context->name ) { From 924dfb3870eb1eab3f4dbfc0746c181528ea68c6 Mon Sep 17 00:00:00 2001 From: Matias Benedetto <matias.benedetto@gmail.com> Date: Thu, 29 Aug 2024 10:13:48 -0300 Subject: [PATCH 0592/1908] cast globalFluid value to boolean (#64882) Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> --- .../src/components/global-styles/font-sizes/font-size.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js index eec86acb8533f4..25ff6812d583c9 100644 --- a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js @@ -54,7 +54,7 @@ function FontSize() { // Whether the font size is fluid. If not defined, use the global fluid value of the theme. const isFluid = - fontSize.fluid !== undefined ? !! fontSize.fluid : globalFluid; + fontSize.fluid !== undefined ? !! fontSize.fluid : !! globalFluid; // Whether custom fluid values are used. const isCustomFluid = typeof fontSize.fluid === 'object'; From db0465c01661c0ee53e976af25329c817174f0ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Thu, 29 Aug 2024 17:03:58 +0200 Subject: [PATCH 0593/1908] DataViews: fix RenderModal props in storybook (#64901) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../dataviews/src/components/dataviews/stories/fixtures.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dataviews/src/components/dataviews/stories/fixtures.js b/packages/dataviews/src/components/dataviews/stories/fixtures.js index 4edc16c53f5de6..14c9718a50d76b 100644 --- a/packages/dataviews/src/components/dataviews/stories/fixtures.js +++ b/packages/dataviews/src/components/dataviews/stories/fixtures.js @@ -144,11 +144,11 @@ export const actions = [ isPrimary: true, icon: trash, hideModalHeader: true, - RenderModal: ( { item, closeModal } ) => { + RenderModal: ( { items, closeModal } ) => { return ( <VStack spacing="5"> <Text> - { `Are you sure you want to delete "${ item?.title }"?` } + { `Are you sure you want to delete "${ items[ 0 ].title }"?` } </Text> <HStack justify="right"> <Button From a959d03b28f21dd446f80be3b9640a7bb78c21ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Thu, 29 Aug 2024 17:22:21 +0200 Subject: [PATCH 0594/1908] DataViews: document combined fields (#64904) --- packages/dataviews/README.md | 44 ++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 6c1e2af26386c7..1d1f62e1032f0c 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -175,11 +175,16 @@ Properties: - `field`: the field used for sorting the dataset. - `direction`: the direction to use for sorting, one of `asc` or `desc`. - `fields`: the `id` of the fields that are visible in the UI. -- `layout`: config that is specific to a particular layout type. - - `primaryField`: used by the `table`, `grid` and `list` layouts. The `id` of the field to be highlighted in each row/card/item. This field is not hiddable. - - `mediaField`: used by the `grid` and `list` layouts. The `id` of the field to be used for rendering each card's media. This field is not hiddable. - - `badgeFields`: used by the `grid` layout. It renders these fields without a label and styled as badges. - - `columnFields`: used by the `grid` layout. It renders the label and the field data vertically stacked instead of horizontally (the default). +- `layout`: config that is specific to a particular layout type: + +| Properties of `layout` | Table | Grid | List | +| --- | --- | --- | --- | +| `primaryField`: the field's `id` to be highlighted in each layout. It's not hidable. | ✓ | ✓ | ✓ | +| `mediaField`: the field's `id` to be used for rendering each card's media. It's not hiddable. | | ✓ | ✓ | +| `columnFields`: a list of field's `id` to render vertically stacked instead of horizontally (the default). | | ✓ | | +| `badgeFields`: a list of field's `id` to render without label and styled as badges. | | ✓ | | +| `combinedFields`: a list of "virtual" fields that are made by combining others. See "Combining fields" section. | ✓ | | | +| `styles`: additional `width`, `maxWidth`, `minWidth` styles for each field column. | ✓ | | | ### `onChangeView`: `function` @@ -317,6 +322,35 @@ Callback that signals the user selected one of more items, and takes them as par > The `enumeration` type was removed as it was deemed redundant with the field.elements metadata. New types will be introduced soon. +## Combining fields + +The `table` layout has the ability to create "virtual" fields that are made out by combining existing ones. + +Each "virtual field", has to provide an `id` and `label` (optionally a `header` instead), which have the same meaning as any other field. + +Additionally, they need to provide: + +- `children`: a list of field's `id` to combine +- `direction`: how should they be stacked, `vertically` or `horizontally` + +For example, this is how you'd define a `site` field which is a combination of a `title` and `description` fields, which are not displayed: + +```js +{ + fields: [ 'site', 'status' ], + layout: { + combinedFields: [ + { + id: 'site', + label: 'Site', + children: [ 'title', 'description' ], + direction: 'vertical', + } + ] + } +} +``` + ### Operators Allowed operators: From 63ddd1157a5d6dbc887d9a7b27eb723b3db2caf8 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 29 Aug 2024 19:25:20 +0400 Subject: [PATCH 0595/1908] Editor: Remove create template permission check in 'VisualEditor' (#64905) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/editor/src/components/visual-editor/index.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/editor/src/components/visual-editor/index.js b/packages/editor/src/components/visual-editor/index.js index a67feb530e96a2..2ff115272d614b 100644 --- a/packages/editor/src/components/visual-editor/index.js +++ b/packages/editor/src/components/visual-editor/index.js @@ -128,8 +128,7 @@ function VisualEditor( { getRenderingMode, getDeviceType, } = select( editorStore ); - const { getPostType, canUser, getEditedEntityRecord } = - select( coreStore ); + const { getPostType, getEditedEntityRecord } = select( coreStore ); const postTypeSlug = getCurrentPostType(); const _renderingMode = getRenderingMode(); let _wrapperBlockName; @@ -143,10 +142,6 @@ function VisualEditor( { const editorSettings = getEditorSettings(); const supportsTemplateMode = editorSettings.supportsTemplateMode; const postTypeObject = getPostType( postTypeSlug ); - const canEditTemplate = canUser( 'create', { - kind: 'postType', - name: 'wp_template', - } ); const currentTemplateId = getCurrentTemplateId(); const template = currentTemplateId ? getEditedEntityRecord( @@ -163,9 +158,7 @@ function VisualEditor( { // Post template fetch returns a 404 on classic themes, which // messes with e2e tests, so check it's a block theme first. editedPostTemplate: - postTypeObject?.viewable && - supportsTemplateMode && - canEditTemplate + postTypeObject?.viewable && supportsTemplateMode ? template : undefined, wrapperBlockName: _wrapperBlockName, From 214b3ca3656382b1f9644c4df84a7d1dfea8d287 Mon Sep 17 00:00:00 2001 From: David Arenas <david.arenas@automattic.com> Date: Thu, 29 Aug 2024 18:31:40 +0200 Subject: [PATCH 0596/1908] Interactivity API: Improve internal `deepMerge` function (#64879) * Move deepMerge to proxies and update implementation * Remove Boolean casting in hasPropSignal implementation * Test subscriptions to nested props updates * Remove extraneous label * Check signals are not created for nested props * Fix getProxyFromObject types * Add missing imports * Add extra assertions to ensure correct signal creation * Do not expose hasPropSignal from proxies/index * Add missing TSDocs * Update changelog Co-authored-by: DAreRodz <darerodz@git.wordpress.org> Co-authored-by: luisherranz <luisherranz@git.wordpress.org> --- packages/interactivity/CHANGELOG.md | 4 + packages/interactivity/src/proxies/index.ts | 2 +- .../interactivity/src/proxies/registry.ts | 18 +- packages/interactivity/src/proxies/state.ts | 98 ++++- .../src/proxies/test/deep-merge.ts | 378 ++++++++++++++++++ packages/interactivity/src/store.ts | 4 +- packages/interactivity/src/test/utils.ts | 295 +------------- packages/interactivity/src/utils.ts | 31 -- 8 files changed, 497 insertions(+), 333 deletions(-) create mode 100644 packages/interactivity/src/proxies/test/deep-merge.ts diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index b9ca382e835d5e..1d72e85f3c34e2 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Improve internal `deepMerge` function ([#64879](https://github.com/WordPress/gutenberg/pull/64879)). + ### Bug Fixes - Fix computeds without scope in Firefox ([#64825](https://github.com/WordPress/gutenberg/pull/64825)). diff --git a/packages/interactivity/src/proxies/index.ts b/packages/interactivity/src/proxies/index.ts index d64fb59fa6bccf..1a495de6b469fe 100644 --- a/packages/interactivity/src/proxies/index.ts +++ b/packages/interactivity/src/proxies/index.ts @@ -1,5 +1,5 @@ /** * Internal dependencies */ -export { proxifyState, peek } from './state'; +export { proxifyState, peek, deepMerge } from './state'; export { proxifyStore } from './store'; diff --git a/packages/interactivity/src/proxies/registry.ts b/packages/interactivity/src/proxies/registry.ts index 767a3730dbae2d..3bfe3b9168b79e 100644 --- a/packages/interactivity/src/proxies/registry.ts +++ b/packages/interactivity/src/proxies/registry.ts @@ -2,6 +2,7 @@ * Proxies for each object. */ const objToProxy = new WeakMap< object, object >(); +const proxyToObj = new WeakMap< object, object >(); /** * Namespaces for each created proxy. @@ -38,6 +39,7 @@ export const createProxy = < T extends object >( if ( ! objToProxy.has( obj ) ) { const proxy = new Proxy( obj, handlers ); objToProxy.set( obj, proxy ); + proxyToObj.set( proxy, obj ); proxyToNs.set( proxy, namespace ); } return objToProxy.get( obj ) as T; @@ -50,8 +52,9 @@ export const createProxy = < T extends object >( * @param obj Object from which to know the proxy. * @return Associated proxy or `undefined`. */ -export const getProxyFromObject = < T extends object >( obj: T ): T => - objToProxy.get( obj ) as T; +export const getProxyFromObject = < T extends object >( + obj: T +): T | undefined => objToProxy.get( obj ) as T; /** * Gets the namespace associated with the given proxy. @@ -80,3 +83,14 @@ export const shouldProxy = ( ! proxyToNs.has( candidate ) && supported.has( candidate.constructor ) ); }; + +/** + * Returns the target object for the passed proxy. If the passed object is not a registered proxy, the + * function returns `undefined`. + * + * @param proxy Proxy from which to know the target. + * @return The target object or `undefined`. + */ +export const getObjectFromProxy = < T extends object >( + proxy: T +): T | undefined => proxyToObj.get( proxy ) as T; diff --git a/packages/interactivity/src/proxies/state.ts b/packages/interactivity/src/proxies/state.ts index 0978fa2ccd0264..323cd306bf9acf 100644 --- a/packages/interactivity/src/proxies/state.ts +++ b/packages/interactivity/src/proxies/state.ts @@ -1,7 +1,7 @@ /** * External dependencies */ -import { signal, type Signal } from '@preact/signals'; +import { batch, signal, type Signal } from '@preact/signals'; /** * Internal dependencies @@ -11,9 +11,11 @@ import { getProxyFromObject, getNamespaceFromProxy, shouldProxy, + getObjectFromProxy, } from './registry'; import { PropSignal } from './signals'; import { setNamespace, resetNamespace } from '../namespaces'; +import { isPlainObject } from '../utils'; /** * Set of built-in symbols. @@ -33,6 +35,17 @@ const proxyToProps: WeakMap< Map< string | symbol, PropSignal > > = new WeakMap(); +/** + * Checks wether a {@link PropSignal | `PropSignal`} instance exists for the + * given property in the passed proxy. + * + * @param proxy Proxy of a state object or array. + * @param key The property key. + * @return `true` when it exists; false otherwise. + */ +export const hasPropSignal = ( proxy: object, key: string ) => + proxyToProps.has( proxy ) && proxyToProps.get( proxy )!.has( key ); + /** * Returns the {@link PropSignal | `PropSignal`} instance associated with the * specified prop in the passed proxy. @@ -152,7 +165,7 @@ const stateHandlers: ProxyHandler< object > = { const result = Reflect.defineProperty( target, key, desc ); if ( result ) { - const receiver = getProxyFromObject( target ); + const receiver = getProxyFromObject( target )!; const prop = getPropSignal( receiver, key ); const { get, value } = desc; if ( get ) { @@ -189,7 +202,7 @@ const stateHandlers: ProxyHandler< object > = { const result = Reflect.deleteProperty( target, key ); if ( result ) { - const prop = getPropSignal( getProxyFromObject( target ), key ); + const prop = getPropSignal( getProxyFromObject( target )!, key ); prop.setValue( undefined ); if ( objToIterable.has( target ) ) { @@ -248,3 +261,82 @@ export const peek = < T extends object, K extends keyof T >( peeking = false; } }; + +/** + * Internal recursive implementation for {@link deepMerge | `deepMerge`}. + * + * @param target The target object. + * @param source The source object containing new values and props. + * @param override Whether existing props should be overwritten or not (`true` + * by default). + */ +const deepMergeRecursive = ( + target: any, + source: any, + override: boolean = true +) => { + if ( isPlainObject( target ) && isPlainObject( source ) ) { + for ( const key in source ) { + const desc = Object.getOwnPropertyDescriptor( source, key ); + if ( + typeof desc?.get === 'function' || + typeof desc?.set === 'function' + ) { + if ( override || ! ( key in target ) ) { + Object.defineProperty( target, key, { + ...desc, + configurable: true, + enumerable: true, + } ); + + const proxy = getProxyFromObject( target ); + if ( desc?.get && proxy && hasPropSignal( proxy, key ) ) { + const propSignal = getPropSignal( proxy, key ); + propSignal.setGetter( desc.get ); + } + } + } else if ( isPlainObject( source[ key ] ) ) { + if ( ! ( key in target ) ) { + target[ key ] = {}; + } + + deepMergeRecursive( target[ key ], source[ key ], override ); + } else if ( override || ! ( key in target ) ) { + Object.defineProperty( target, key, desc! ); + + const proxy = getProxyFromObject( target ); + if ( desc?.value && proxy && hasPropSignal( proxy, key ) ) { + const propSignal = getPropSignal( proxy, key ); + propSignal.setValue( desc.value ); + } + } + } + } +}; + +/** + * Recursively update prop values inside the passed `target` and nested plain + * objects, using the values present in `source`. References to plain objects + * are kept, only updating props containing primitives or arrays. Arrays are + * replaced instead of merged or concatenated. + * + * If the `override` parameter is set to `false`, then all values in `target` + * are preserved, and only new properties from `source` are added. + * + * @param target The target object. + * @param source The source object containing new values and props. + * @param override Whether existing props should be overwritten or not (`true` + * by default). + */ +export const deepMerge = ( + target: any, + source: any, + override: boolean = true +) => + batch( () => + deepMergeRecursive( + getObjectFromProxy( target ) || target, + source, + override + ) + ); diff --git a/packages/interactivity/src/proxies/test/deep-merge.ts b/packages/interactivity/src/proxies/test/deep-merge.ts new file mode 100644 index 00000000000000..b24d9b6781cfe2 --- /dev/null +++ b/packages/interactivity/src/proxies/test/deep-merge.ts @@ -0,0 +1,378 @@ +/* eslint-disable eslint-comments/disable-enable-pair */ +/* eslint-disable @typescript-eslint/no-shadow */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +/** + * External dependencies + */ +import { effect } from '@preact/signals'; +/** + * Internal dependencies + */ +import { proxifyState, peek, deepMerge } from '../'; +import { hasPropSignal } from '../state'; +import { getProxyFromObject } from '../registry'; + +describe( 'Interactivity API', () => { + describe( 'deepMerge', () => { + it( 'should merge two plain objects', () => { + const target = { a: 1, b: 2 }; + const source = { b: 3, c: 4 }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { a: 1, b: 3, c: 4 } ); + } ); + + it( 'should handle nested objects', () => { + const target = { a: { x: 1 }, b: 2 }; + const source = { a: { y: 2 }, c: 3 }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { a: { x: 1, y: 2 }, b: 2, c: 3 } ); + } ); + + it( 'should not override existing properties when override is false', () => { + const target = { a: 1, b: { x: 10 } }; + const source = { a: 2, b: { y: 20 }, c: 3 }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source, false ); + expect( result ).toEqual( { a: 1, b: { x: 10, y: 20 }, c: 3 } ); + } ); + + it( 'should handle getters', () => { + const target = { + get a() { + return 1; + }, + b: 1, + }; + const source = { + a: 2, + get b() { + return 2; + }, + }; + const result: Record< string, any > = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result.a ).toBe( 2 ); + expect( result.b ).toBe( 2 ); + expect( + Object.getOwnPropertyDescriptor( result, 'a' )?.get + ).toBeUndefined(); + expect( + Object.getOwnPropertyDescriptor( result, 'b' )?.get + ).toBeDefined(); + } ); + + it( 'should not execute getters when performing the deep merge', () => { + let targetExecuted = false; + let sourceExecuted = false; + const target = { + get a() { + targetExecuted = true; + return 1; + }, + }; + const source = { + get b() { + sourceExecuted = true; + return 2; + }, + }; + const result: Record< string, any > = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( targetExecuted ).toBe( false ); + expect( sourceExecuted ).toBe( false ); + } ); + + it( 'should handle setters', () => { + let targetValue = 1; + const target = { + get a() { + return targetValue; + }, + set a( value ) { + targetValue = value; + }, + b: 1, + }; + let sourceValue = 2; + const source = { + a: 3, + get b() { + return 2; + }, + set b( value ) { + sourceValue = value; + }, + }; + + const result: Record< string, any > = {}; + deepMerge( result, target ); + + result.a = 5; + expect( targetValue ).toBe( 5 ); + expect( result.a ).toBe( 5 ); + + deepMerge( result, source ); + + result.a = 6; + expect( targetValue ).toBe( 5 ); + + result.b = 7; + expect( sourceValue ).toBe( 7 ); + + expect( result.a ).toBe( 6 ); + expect( result.b ).toBe( 2 ); + expect( + Object.getOwnPropertyDescriptor( result, 'a' )?.set + ).toBeUndefined(); + expect( + Object.getOwnPropertyDescriptor( result, 'b' )?.set + ).toBeDefined(); + } ); + + it( 'should handle setters when overwrite is false', () => { + let targetValue = 1; + const target = { + get a() { + return targetValue; + }, + set a( value ) { + targetValue = value; + }, + b: 1, + }; + let sourceValue = 2; + const source = { + a: 3, + get b() { + return 2; + }, + set b( value ) { + sourceValue = value; + }, + }; + + const result: Record< string, any > = {}; + deepMerge( result, target, false ); + deepMerge( result, source, false ); + + result.a = 6; + expect( targetValue ).toBe( 6 ); + + result.b = 7; + expect( sourceValue ).toBe( 2 ); + + expect( result.a ).toBe( 6 ); + expect( result.b ).toBe( 7 ); + expect( + Object.getOwnPropertyDescriptor( result, 'a' )?.set + ).toBeDefined(); + expect( + Object.getOwnPropertyDescriptor( result, 'b' )?.set + ).toBeUndefined(); + } ); + + it( 'should handle getters and setters together', () => { + let targetValue = 1; + const target = { + get a() { + return targetValue; + }, + set a( value ) { + targetValue = value; + }, + b: 1, + }; + let sourceValue = 2; + const source = { + get a() { + return 3; + }, + set a( value ) { + sourceValue = value; + }, + }; + const result: Record< string, any > = {}; + deepMerge( result, target ); + deepMerge( result, source ); + + // Test if setters and getters are copied correctly + result.a = 5; + expect( targetValue ).toBe( 1 ); // Should not change + expect( sourceValue ).toBe( 5 ); // Should change + expect( result.a ).toBe( 3 ); // Should return the getter's value + + expect( + Object.getOwnPropertyDescriptor( result, 'a' )?.get + ).toBeDefined(); + expect( + Object.getOwnPropertyDescriptor( result, 'a' )?.set + ).toBeDefined(); + } ); + + it( 'should handle getters when overwrite is false', () => { + const target = { + get a() { + return 1; + }, + b: 1, + }; + const source = { + a: 2, + get b() { + return 2; + }, + }; + const result: Record< string, any > = {}; + deepMerge( result, target, false ); + deepMerge( result, source, false ); + expect( result.a ).toBe( 1 ); + expect( result.b ).toBe( 1 ); + expect( + Object.getOwnPropertyDescriptor( result, 'a' )?.get + ).toBeDefined(); + expect( + Object.getOwnPropertyDescriptor( result, 'b' )?.get + ).toBeUndefined(); + } ); + + it( 'should ignore non-plain objects', () => { + const target = { a: 1 }; + const source = new Date(); + const result = { ...target }; + deepMerge( result, source ); + expect( result ).toEqual( { a: 1 } ); + } ); + + it( 'should handle arrays', () => { + const target = { a: [ 1, 2 ] }; + const source = { a: [ 3, 4 ] }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { a: [ 3, 4 ] } ); + } ); + + it( 'should handle arrays when overwrite is false', () => { + const target = { a: [ 1, 2 ] }; + const source = { a: [ 3, 4 ] }; + const result = {}; + deepMerge( result, target, false ); + deepMerge( result, source, false ); + expect( result ).toEqual( { a: [ 1, 2 ] } ); + } ); + + it( 'should handle null values', () => { + const target = { a: 1, b: null }; + const source = { b: 2, c: null }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { a: 1, b: 2, c: null } ); + } ); + + it( 'should handle undefined values', () => { + const target = { a: 1, b: undefined }; + const source = { b: 2, c: undefined }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { a: 1, b: 2, c: undefined } ); + } ); + + it( 'should handle undefined values when overwrite is false', () => { + const target = { a: 1, b: undefined }; + const source = { b: 2, c: undefined }; + const result = {}; + deepMerge( result, target, false ); + deepMerge( result, source, false ); + expect( result ).toEqual( { a: 1, b: undefined, c: undefined } ); + } ); + + it( 'should handle deleted values when overwrite is false', () => { + const target = { a: 1 }; + const source = { a: 2 }; + const result: Record< string, any > = {}; + deepMerge( result, target, false ); + delete result.a; + deepMerge( result, source, false ); + expect( result ).toEqual( { a: 2 } ); + } ); + + it( 'should never create signals', () => { + const target = { a: 1, b: { x: 10 } }; + const source = { a: 2, b: { y: 20 }, c: 3 }; + const result = proxifyState( + 'test', + {} as typeof target & typeof source + ); + deepMerge( result, target ); + deepMerge( result, source, false ); + + expect( hasPropSignal( result, 'a' ) ).toBe( false ); + expect( hasPropSignal( result, 'b' ) ).toBe( false ); + expect( hasPropSignal( result, 'c' ) ).toBe( false ); + + const proxyB = getProxyFromObject( peek( result, 'b' ) )!; + expect( hasPropSignal( proxyB, 'x' ) ).toBe( false ); + expect( hasPropSignal( proxyB, 'y' ) ).toBe( false ); + } ); + + it( 'should update signals when they exist', () => { + const target = { a: 1, b: { x: 10 } }; + const source = { a: 2, b: { x: 20, y: 30 }, c: 3 }; + const result = proxifyState< any >( 'test', {} ); + + const spyA = jest.fn( () => result.a ); + effect( spyA ); + + expect( spyA ).toHaveBeenCalledTimes( 1 ); + + deepMerge( result, target ); + + const spyBx = jest.fn( () => result.b.x ); + effect( spyBx ); + expect( spyA ).toHaveBeenCalledTimes( 2 ); + expect( spyBx ).toHaveBeenCalledTimes( 1 ); + + deepMerge( result, source ); + + expect( spyA ).toHaveBeenCalledTimes( 3 ); + expect( spyBx ).toHaveBeenCalledTimes( 2 ); + + expect( hasPropSignal( result, 'a' ) ).toBe( true ); + expect( hasPropSignal( result, 'b' ) ).toBe( true ); + expect( hasPropSignal( result, 'c' ) ).toBe( false ); + + const proxyB = getProxyFromObject( peek( result, 'b' ) )!; + expect( hasPropSignal( proxyB, 'x' ) ).toBe( true ); + expect( hasPropSignal( proxyB, 'y' ) ).toBe( false ); + } ); + + it( 'should batch all signal updates together', () => { + const target = { a: 1, b: 2 }; + const source = { a: 3, b: 4 }; + const result = proxifyState< any >( 'test', {} ); + + const spy = jest.fn( () => ( result.a, result.b ) ); + effect( spy ); + + expect( spy ).toHaveBeenCalledTimes( 1 ); + + deepMerge( result, target ); + + expect( spy ).toHaveBeenCalledTimes( 2 ); + + deepMerge( result, source ); + + expect( spy ).toHaveBeenCalledTimes( 3 ); + } ); + } ); +} ); diff --git a/packages/interactivity/src/store.ts b/packages/interactivity/src/store.ts index 25fa64eb6e160e..c74764b902e194 100644 --- a/packages/interactivity/src/store.ts +++ b/packages/interactivity/src/store.ts @@ -1,12 +1,12 @@ /** * Internal dependencies */ -import { proxifyState, proxifyStore } from './proxies'; +import { proxifyState, proxifyStore, deepMerge } from './proxies'; /** * External dependencies */ import { getNamespace } from './namespaces'; -import { deepMerge, isPlainObject } from './utils'; +import { isPlainObject } from './utils'; export const stores = new Map(); const rawStores = new Map(); diff --git a/packages/interactivity/src/test/utils.ts b/packages/interactivity/src/test/utils.ts index 2ea0d2f04fadf7..2de0ffe6d31e06 100644 --- a/packages/interactivity/src/test/utils.ts +++ b/packages/interactivity/src/test/utils.ts @@ -1,302 +1,9 @@ /** * Internal dependencies */ -import { deepMerge, kebabToCamelCase } from '../utils'; +import { kebabToCamelCase } from '../utils'; describe( 'Interactivity API', () => { - describe( 'deepMerge', () => { - it( 'should merge two plain objects', () => { - const target = { a: 1, b: 2 }; - const source = { b: 3, c: 4 }; - const result = {}; - deepMerge( result, target ); - deepMerge( result, source ); - expect( result ).toEqual( { a: 1, b: 3, c: 4 } ); - } ); - - it( 'should handle nested objects', () => { - const target = { a: { x: 1 }, b: 2 }; - const source = { a: { y: 2 }, c: 3 }; - const result = {}; - deepMerge( result, target ); - deepMerge( result, source ); - expect( result ).toEqual( { a: { x: 1, y: 2 }, b: 2, c: 3 } ); - } ); - - it( 'should not override existing properties when override is false', () => { - const target = { a: 1, b: { x: 10 } }; - const source = { a: 2, b: { y: 20 }, c: 3 }; - const result = {}; - deepMerge( result, target ); - deepMerge( result, source, false ); - expect( result ).toEqual( { a: 1, b: { x: 10, y: 20 }, c: 3 } ); - } ); - - it( 'should handle getters', () => { - const target = { - get a() { - return 1; - }, - b: 1, - }; - const source = { - a: 2, - get b() { - return 2; - }, - }; - const result: Record< string, any > = {}; - deepMerge( result, target ); - deepMerge( result, source ); - expect( result.a ).toBe( 2 ); - expect( result.b ).toBe( 2 ); - expect( - Object.getOwnPropertyDescriptor( result, 'a' )?.get - ).toBeUndefined(); - expect( - Object.getOwnPropertyDescriptor( result, 'b' )?.get - ).toBeDefined(); - } ); - - it( 'should not execute getters when performing the deep merge', () => { - let targetExecuted = false; - let sourceExecuted = false; - const target = { - get a() { - targetExecuted = true; - return 1; - }, - }; - const source = { - get b() { - sourceExecuted = true; - return 2; - }, - }; - const result: Record< string, any > = {}; - deepMerge( result, target ); - deepMerge( result, source ); - expect( targetExecuted ).toBe( false ); - expect( sourceExecuted ).toBe( false ); - } ); - - https: it( 'should handle setters', () => { - let targetValue = 1; - const target = { - get a() { - return targetValue; - }, - set a( value ) { - targetValue = value; - }, - b: 1, - }; - let sourceValue = 2; - const source = { - a: 3, - get b() { - return 2; - }, - set b( value ) { - sourceValue = value; - }, - }; - - const result: Record< string, any > = {}; - deepMerge( result, target ); - - result.a = 5; - expect( targetValue ).toBe( 5 ); - expect( result.a ).toBe( 5 ); - - deepMerge( result, source ); - - result.a = 6; - expect( targetValue ).toBe( 5 ); - - result.b = 7; - expect( sourceValue ).toBe( 7 ); - - expect( result.a ).toBe( 6 ); - expect( result.b ).toBe( 2 ); - expect( - Object.getOwnPropertyDescriptor( result, 'a' )?.set - ).toBeUndefined(); - expect( - Object.getOwnPropertyDescriptor( result, 'b' )?.set - ).toBeDefined(); - } ); - - it( 'should handle setters when overwrite is false', () => { - let targetValue = 1; - const target = { - get a() { - return targetValue; - }, - set a( value ) { - targetValue = value; - }, - b: 1, - }; - let sourceValue = 2; - const source = { - a: 3, - get b() { - return 2; - }, - set b( value ) { - sourceValue = value; - }, - }; - - const result: Record< string, any > = {}; - deepMerge( result, target, false ); - deepMerge( result, source, false ); - - result.a = 6; - expect( targetValue ).toBe( 6 ); - - result.b = 7; - expect( sourceValue ).toBe( 2 ); - - expect( result.a ).toBe( 6 ); - expect( result.b ).toBe( 7 ); - expect( - Object.getOwnPropertyDescriptor( result, 'a' )?.set - ).toBeDefined(); - expect( - Object.getOwnPropertyDescriptor( result, 'b' )?.set - ).toBeUndefined(); - } ); - - it( 'should handle getters and setters together', () => { - let targetValue = 1; - const target = { - get a() { - return targetValue; - }, - set a( value ) { - targetValue = value; - }, - b: 1, - }; - let sourceValue = 2; - const source = { - get a() { - return 3; - }, - set a( value ) { - sourceValue = value; - }, - }; - const result: Record< string, any > = {}; - deepMerge( result, target ); - deepMerge( result, source ); - - // Test if setters and getters are copied correctly - result.a = 5; - expect( targetValue ).toBe( 1 ); // Should not change - expect( sourceValue ).toBe( 5 ); // Should change - expect( result.a ).toBe( 3 ); // Should return the getter's value - - expect( - Object.getOwnPropertyDescriptor( result, 'a' )?.get - ).toBeDefined(); - expect( - Object.getOwnPropertyDescriptor( result, 'a' )?.set - ).toBeDefined(); - } ); - - it( 'should handle getters when overwrite is false', () => { - const target = { - get a() { - return 1; - }, - b: 1, - }; - const source = { - a: 2, - get b() { - return 2; - }, - }; - const result: Record< string, any > = {}; - deepMerge( result, target, false ); - deepMerge( result, source, false ); - expect( result.a ).toBe( 1 ); - expect( result.b ).toBe( 1 ); - expect( - Object.getOwnPropertyDescriptor( result, 'a' )?.get - ).toBeDefined(); - expect( - Object.getOwnPropertyDescriptor( result, 'b' )?.get - ).toBeUndefined(); - } ); - - it( 'should ignore non-plain objects', () => { - const target = { a: 1 }; - const source = new Date(); - const result = { ...target }; - deepMerge( result, source ); - expect( result ).toEqual( { a: 1 } ); - } ); - - it( 'should handle arrays', () => { - const target = { a: [ 1, 2 ] }; - const source = { a: [ 3, 4 ] }; - const result = {}; - deepMerge( result, target ); - deepMerge( result, source ); - expect( result ).toEqual( { a: [ 3, 4 ] } ); - } ); - - it( 'should handle arrays when overwrite is false', () => { - const target = { a: [ 1, 2 ] }; - const source = { a: [ 3, 4 ] }; - const result = {}; - deepMerge( result, target, false ); - deepMerge( result, source, false ); - expect( result ).toEqual( { a: [ 1, 2 ] } ); - } ); - - it( 'should handle null values', () => { - const target = { a: 1, b: null }; - const source = { b: 2, c: null }; - const result = {}; - deepMerge( result, target ); - deepMerge( result, source ); - expect( result ).toEqual( { a: 1, b: 2, c: null } ); - } ); - - it( 'should handle undefined values', () => { - const target = { a: 1, b: undefined }; - const source = { b: 2, c: undefined }; - const result = {}; - deepMerge( result, target ); - deepMerge( result, source ); - expect( result ).toEqual( { a: 1, b: 2, c: undefined } ); - } ); - - it( 'should handle undefined values when overwrite is false', () => { - const target = { a: 1, b: undefined }; - const source = { b: 2, c: undefined }; - const result = {}; - deepMerge( result, target, false ); - deepMerge( result, source, false ); - expect( result ).toEqual( { a: 1, b: undefined, c: undefined } ); - } ); - - it( 'should handle deleted values when overwrite is false', () => { - const target = { a: 1 }; - const source = { a: 2 }; - const result: Record< string, any > = {}; - deepMerge( result, target, false ); - delete result.a; - deepMerge( result, source, false ); - expect( result ).toEqual( { a: 2 } ); - } ); - } ); - describe( 'kebabToCamelCase', () => { it( 'should work exactly as the PHP version', async () => { expect( kebabToCamelCase( '' ) ).toBe( '' ); diff --git a/packages/interactivity/src/utils.ts b/packages/interactivity/src/utils.ts index ee0cf1ba084dc8..c5eb91681294f2 100644 --- a/packages/interactivity/src/utils.ts +++ b/packages/interactivity/src/utils.ts @@ -364,34 +364,3 @@ export const isPlainObject = ( typeof candidate === 'object' && candidate.constructor === Object ); - -export const deepMerge = ( - target: any, - source: any, - override: boolean = true -) => { - if ( isPlainObject( target ) && isPlainObject( source ) ) { - for ( const key in source ) { - const desc = Object.getOwnPropertyDescriptor( source, key ); - if ( - typeof desc?.get === 'function' || - typeof desc?.set === 'function' - ) { - if ( override || ! ( key in target ) ) { - Object.defineProperty( target, key, { - ...desc, - configurable: true, - enumerable: true, - } ); - } - } else if ( isPlainObject( source[ key ] ) ) { - if ( ! target[ key ] ) { - target[ key ] = {}; - } - deepMerge( target[ key ], source[ key ], override ); - } else if ( override || ! ( key in target ) ) { - Object.defineProperty( target, key, desc! ); - } - } - } -}; From 8a0e8bc1b6e964b70f5cf085bd3aac9d4d88e373 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Thu, 29 Aug 2024 17:47:16 +0100 Subject: [PATCH 0597/1908] Improve Social Icons setup and appending (#64877) Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../components/button-block-appender/index.js | 15 ++++++++-- .../block-library/src/social-links/edit.js | 21 +++++++++----- .../src/social-links/editor.scss | 29 +++++++++++++++---- 3 files changed, 50 insertions(+), 15 deletions(-) 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 fd349ad1daac07..9cd745ac5eb3d6 100644 --- a/packages/block-editor/src/components/button-block-appender/index.js +++ b/packages/block-editor/src/components/button-block-appender/index.js @@ -7,7 +7,7 @@ import clsx from 'clsx'; * WordPress dependencies */ import { Button, Tooltip, VisuallyHidden } from '@wordpress/components'; -import { forwardRef } from '@wordpress/element'; +import { forwardRef, useRef } from '@wordpress/element'; import { _x, sprintf } from '@wordpress/i18n'; import { Icon, plus } from '@wordpress/icons'; import deprecated from '@wordpress/deprecated'; @@ -16,17 +16,26 @@ import deprecated from '@wordpress/deprecated'; * Internal dependencies */ import Inserter from '../inserter'; +import { useMergeRefs } from '@wordpress/compose'; function ButtonBlockAppender( { rootClientId, className, onFocus, tabIndex, onSelect }, ref ) { + const inserterButtonRef = useRef(); + + const mergedInserterButtonRef = useMergeRefs( [ inserterButtonRef, ref ] ); return ( <Inserter position="bottom center" rootClientId={ rootClientId } __experimentalIsQuick - onSelectOrClose={ onSelect } + onSelectOrClose={ ( ...args ) => { + if ( onSelect && typeof onSelect === 'function' ) { + onSelect( ...args ); + } + inserterButtonRef.current?.focus(); + } } renderToggle={ ( { onToggle, disabled, @@ -53,7 +62,7 @@ function ButtonBlockAppender( <Button // TODO: Switch to `true` (40px size) if possible __next40pxDefaultSize={ false } - ref={ ref } + ref={ mergedInserterButtonRef } onFocus={ onFocus } tabIndex={ tabIndex } className={ clsx( diff --git a/packages/block-library/src/social-links/edit.js b/packages/block-library/src/social-links/edit.js index 1bd943de7fb8e7..d4dfae70aac5ae 100644 --- a/packages/block-library/src/social-links/edit.js +++ b/packages/block-library/src/social-links/edit.js @@ -14,8 +14,10 @@ import { InspectorControls, ContrastChecker, withColors, + InnerBlocks, __experimentalColorGradientSettingsDropdown as ColorGradientSettingsDropdown, __experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients, + store as blockEditorStore, } from '@wordpress/block-editor'; import { MenuGroup, @@ -26,6 +28,7 @@ import { } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { check } from '@wordpress/icons'; +import { useSelect } from '@wordpress/data'; const sizeOptions = [ { name: __( 'Small' ), value: 'has-small-icon-size' }, @@ -55,6 +58,14 @@ export function SocialLinksEdit( props ) { size, } = attributes; + const hasSelectedChild = useSelect( + ( select ) => + select( blockEditorStore ).hasSelectedInnerBlock( clientId ), + [ clientId ] + ); + + const hasAnySelected = isSelected || hasSelectedChild; + const logosOnly = attributes.className?.includes( 'is-style-logos-only' ); // Remove icon background color when logos only style is selected or @@ -75,6 +86,7 @@ export function SocialLinksEdit( props ) { } else { setAttributes( { ...backgroundBackupRef.current } ); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ logosOnly ] ); const SocialPlaceholder = ( @@ -87,12 +99,6 @@ export function SocialLinksEdit( props ) { </li> ); - const SelectedSocialPlaceholder = ( - <li className="wp-block-social-links__social-prompt"> - { __( 'Click plus to add' ) } - </li> - ); - // Fallback color values are used maintain selections in case switching // themes and named colors in palette do not match. const className = clsx( size, { @@ -104,10 +110,11 @@ export function SocialLinksEdit( props ) { const blockProps = useBlockProps( { className } ); const innerBlocksProps = useInnerBlocksProps( blockProps, { - placeholder: isSelected ? SelectedSocialPlaceholder : SocialPlaceholder, + placeholder: ! isSelected && SocialPlaceholder, templateLock: false, orientation: attributes.layout?.orientation ?? 'horizontal', __experimentalAppenderTagName: 'li', + renderAppender: hasAnySelected && InnerBlocks.ButtonBlockAppender, } ); const POPOVER_PROPS = { diff --git a/packages/block-library/src/social-links/editor.scss b/packages/block-library/src/social-links/editor.scss index 6f07ea209ecbea..f9491cc068f159 100644 --- a/packages/block-library/src/social-links/editor.scss +++ b/packages/block-library/src/social-links/editor.scss @@ -1,11 +1,10 @@ // Editor specific styles for Social Links. -.wp-block-social-links { - div.block-editor-url-input { - display: inline-block; - margin-left: $grid-unit-10; - } +.wp-block-social-links div.block-editor-url-input { + display: inline-block; + margin-left: $grid-unit-10; } + // Prevent toolbar from jumping when selecting / hovering a link. .wp-social-link:hover { transform: none; @@ -98,3 +97,23 @@ .wp-social-link.wp-social-link__is-incomplete:focus { opacity: 1; } + +.wp-block-social-links .block-list-appender { + position: static; // display inline. + + .block-editor-button-block-appender.components-button.components-button { + padding: $grid-unit-10 - 2px; + } +} + +.wp-block-social-links { + &.has-small-icon-size .block-editor-button-block-appender.components-button.components-button { + padding: 0; + } + &.has-large-icon-size .block-editor-button-block-appender.components-button.components-button { + padding: $grid-unit-20 - 2px; + } + &.has-huge-icon-size .block-editor-button-block-appender.components-button.components-button { + padding: $grid-unit-30 - 1px; + } +} From c4b3a38a100822feaca1192a81ef381782ac1c06 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Thu, 29 Aug 2024 19:06:58 +0200 Subject: [PATCH 0598/1908] Add: Reorder control at the field level on the new view config UI. (#64381) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: paulwilde <paulwilde@git.wordpress.org> --- .../dataviews-view-config/index.tsx | 296 +++++++++++++++--- .../dataviews-view-config/style.scss | 19 ++ 2 files changed, 277 insertions(+), 38 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index bd9bc1b19803e1..331d0d62dca00a 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -21,10 +21,11 @@ import { __experimentalHeading as Heading, __experimentalText as Text, privateApis as componentsPrivateApis, + BaseControl, } from '@wordpress/components'; -import { __, _x } from '@wordpress/i18n'; +import { __, _x, sprintf } from '@wordpress/i18n'; import { memo, useContext, useState, useMemo } from '@wordpress/element'; -import { cog, seen, unseen } from '@wordpress/icons'; +import { chevronDown, chevronUp, cog, seen, unseen } from '@wordpress/icons'; import warning from '@wordpress/warning'; /** @@ -33,11 +34,12 @@ import warning from '@wordpress/warning'; import { SORTING_DIRECTIONS, LAYOUT_GRID, + LAYOUT_TABLE, sortIcons, sortLabels, } from '../../constants'; import { VIEW_LAYOUTS, getMandatoryFields } from '../../dataviews-layouts'; -import type { SupportedLayouts } from '../../types'; +import type { NormalizedField, SupportedLayouts, View } from '../../types'; import DataViewsContext from '../dataviews-context'; import { unlock } from '../../lock-unlock'; import DensityPicker from '../../dataviews-layouts/grid/density-picker'; @@ -230,50 +232,268 @@ function ItemsPerPageControl() { ); } -function FieldControl() { - const { view, fields, onChangeView } = useContext( DataViewsContext ); - const mandatoryFields = getMandatoryFields( view ); - const hidableFields = fields.filter( - ( field ) => - field.enableHiding !== false && - ! mandatoryFields.includes( field.id ) - ); - const viewFields = view.fields || fields.map( ( field ) => field.id ); - if ( ! hidableFields?.length ) { - return null; +function FieldItem( { + fields, + fieldId, + mandatoryFields, + viewFields, + view, + onChangeView, +}: { + fields: NormalizedField< any >[]; + fieldId: string; + mandatoryFields: string | any[]; + viewFields: string[]; + view: View; + onChangeView: ( view: View ) => void; +} ) { + let fieldLabel; + let fieldIsHidable; + const fieldObject = fields.find( + ( f ) => f.id === fieldId + ) as NormalizedField< any >; + if ( fieldObject ) { + fieldLabel = fieldObject.label; + fieldIsHidable = + fieldObject.enableHiding !== false && + ! mandatoryFields.includes( fieldId ); + } else if ( view.type === LAYOUT_TABLE ) { + const combinedFieldObject = view.layout?.combinedFields?.find( + ( f ) => f.id === fieldId + ); + if ( combinedFieldObject ) { + fieldLabel = combinedFieldObject.label; + fieldIsHidable = ! mandatoryFields.includes( fieldId ); + } } + + const index = view.fields?.indexOf( fieldId ) as number; + const isVisible = viewFields.includes( fieldId ); return ( - <ItemGroup isBordered isSeparated> - { hidableFields?.map( ( field ) => { - const isVisible = viewFields.includes( field.id ); - return ( - <Item key={ field.id }> - <HStack expanded> - <span>{ field.label }</span> + <Item key={ fieldId }> + <HStack + expanded + className={ `dataviews-field-control__field dataviews-field-control__field-${ fieldId }` } + > + <span>{ fieldLabel }</span> + <HStack + justify="flex-end" + expanded={ false } + className="dataviews-field-control__actions" + > + { view.type === LAYOUT_TABLE && isVisible && ( + <> <Button + disabled={ ! isVisible || index < 1 } + accessibleWhenDisabled size="compact" - onClick={ () => + onClick={ () => { + if ( ! view.fields || index < 1 ) { + return; + } onChangeView( { ...view, - fields: isVisible - ? viewFields.filter( - ( id ) => id !== field.id - ) - : [ ...viewFields, field.id ], - } ) + fields: [ + ...( view.fields.slice( + 0, + index - 1 + ) ?? [] ), + fieldId, + view.fields[ index - 1 ], + ...view.fields.slice( index + 1 ), + ], + } ); + } } + icon={ chevronUp } + label={ sprintf( + /* translators: %s: field label */ + __( 'Move %s up' ), + fieldLabel + ) } + /> + <Button + disabled={ + ! isVisible || + ! view.fields || + index >= view.fields.length - 1 } - icon={ isVisible ? seen : unseen } - label={ - isVisible - ? __( 'Hide field' ) - : __( 'Show field' ) + accessibleWhenDisabled + size="compact" + onClick={ () => { + if ( + ! view.fields || + index >= view.fields.length - 1 + ) { + return; + } + onChangeView( { + ...view, + fields: [ + ...( view.fields.slice( + 0, + index + ) ?? [] ), + view.fields[ index + 1 ], + fieldId, + ...view.fields.slice( index + 2 ), + ], + } ); + } } + icon={ chevronDown } + label={ sprintf( + /* translators: %s: field label */ + __( 'Move %s down' ), + fieldLabel + ) } + />{ ' ' } + </> + ) } + <Button + className="dataviews-field-control__field-visibility-button" + disabled={ ! fieldIsHidable } + accessibleWhenDisabled + size="compact" + onClick={ () => { + onChangeView( { + ...view, + fields: isVisible + ? viewFields.filter( + ( id ) => id !== fieldId + ) + : [ ...viewFields, fieldId ], + } ); + // Focus the visibility button to avoid focus loss. + // Our code is safe against the component being unmounted, so we don't need to worry about cleaning the timeout. + // eslint-disable-next-line @wordpress/react-no-unsafe-timeout + setTimeout( () => { + const element = document.querySelector( + `.dataviews-field-control__field-${ fieldId } .dataviews-field-control__field-visibility-button` + ); + if ( element instanceof HTMLElement ) { + element.focus(); } - /> - </HStack> - </Item> + }, 50 ); + } } + icon={ isVisible ? seen : unseen } + label={ + isVisible + ? sprintf( + /* translators: %s: field label */ + __( 'Hide %s' ), + fieldLabel + ) + : sprintf( + /* translators: %s: field label */ + __( 'Show %s' ), + fieldLabel + ) + } + /> + </HStack> + </HStack> + </Item> + ); +} + +function FieldList( { + fields, + fieldIds, + mandatoryFields, + viewFields, + view, + onChangeView, +}: Omit< Parameters< typeof FieldItem >[ 0 ], 'fieldId' > & { + fieldIds: string[]; +} ) { + return fieldIds.map( ( fieldId ) => ( + <FieldItem + key={ fieldId } + fields={ fields } + fieldId={ fieldId } + mandatoryFields={ mandatoryFields } + viewFields={ viewFields } + view={ view } + onChangeView={ onChangeView } + /> + ) ); +} + +function FieldControl() { + const { view, fields, onChangeView } = useContext( DataViewsContext ); + const mandatoryFields = useMemo( + () => getMandatoryFields( view ), + [ view ] + ); + const viewFields = view.fields || fields.map( ( field ) => field.id ); + const visibleFields = view.fields; + const hiddenFields = useMemo( () => { + const nonViewFieldsList = fields + .filter( + ( field ) => + ! viewFields.includes( field.id ) && + ! mandatoryFields?.includes( field.id ) + ) + .map( ( field ) => field.id ); + + if ( view.type !== LAYOUT_TABLE ) { + return nonViewFieldsList; + } + const nonViewFieldsAndNonCombinedList = nonViewFieldsList.filter( + ( fieldId ) => { + return ! view.layout?.combinedFields?.some( ( combinedField ) => + combinedField.children.includes( fieldId ) ); - } ) } - </ItemGroup> + } + ); + const nonViewFieldsCombinedFieldsList = + view.layout?.combinedFields + ?.filter( + ( combinedField ) => + ! viewFields.includes( combinedField.id ) + ) + .map( ( combinedField ) => combinedField.id ) || []; + return [ + ...nonViewFieldsAndNonCombinedList, + ...nonViewFieldsCombinedFieldsList, + ]; + }, [ view, mandatoryFields, fields, viewFields ] ); + if ( ! visibleFields?.length && ! hiddenFields?.length ) { + return null; + } + return ( + <VStack spacing={ 6 } className="dataviews-field-control"> + { !! visibleFields?.length && ( + <ItemGroup isBordered isSeparated> + <FieldList + fields={ fields } + fieldIds={ visibleFields } + mandatoryFields={ mandatoryFields } + viewFields={ viewFields } + view={ view } + onChangeView={ onChangeView } + /> + </ItemGroup> + ) } + { !! hiddenFields?.length && ( + <> + <VStack spacing={ 4 }> + <BaseControl.VisualLabel style={ { margin: 0 } }> + { __( 'Hidden' ) } + </BaseControl.VisualLabel> + <ItemGroup isBordered isSeparated> + <FieldList + fields={ fields } + fieldIds={ hiddenFields } + mandatoryFields={ mandatoryFields } + viewFields={ viewFields } + view={ view } + onChangeView={ onChangeView } + /> + </ItemGroup> + </VStack> + </> + ) } + </VStack> ); } diff --git a/packages/dataviews/src/components/dataviews-view-config/style.scss b/packages/dataviews/src/components/dataviews-view-config/style.scss index 00c1c6a9baf44f..2351793d0c2424 100644 --- a/packages/dataviews/src/components/dataviews-view-config/style.scss +++ b/packages/dataviews/src/components/dataviews-view-config/style.scss @@ -46,3 +46,22 @@ } } } +.dataviews-field-control__field { + height: $grid-unit-40; +} + +.dataviews-field-control__actions { + position: absolute; + top: -9999em; +} +.dataviews-field-control__actions.dataviews-field-control__actions { + gap: $grid-unit-05; +} + +.dataviews-field-control__field:hover, +.dataviews-field-control__field:focus-within { + .dataviews-field-control__actions { + position: unset; + top: unset; + } +} From 70b257a8646015197bbf6ac844a4628a2c43f293 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Thu, 29 Aug 2024 12:08:30 -0500 Subject: [PATCH 0599/1908] Show block icon in contentOnly toolbar (#64694) --- .../src/components/block-switcher/index.js | 46 +++++++++++-------- .../src/components/block-switcher/style.scss | 7 ++- .../src/components/block-toolbar/index.js | 10 ++-- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js index f28d0e49333817..c8ee422091ad1f 100644 --- a/packages/block-editor/src/components/block-switcher/index.js +++ b/packages/block-editor/src/components/block-switcher/index.js @@ -181,6 +181,21 @@ function BlockSwitcherDropdownMenuContents( { ); } +const BlockIndicator = ( { icon, showTitle, blockTitle } ) => ( + <> + <BlockIcon + className="block-editor-block-switcher__toggle" + icon={ icon } + showColors + /> + { showTitle && blockTitle && ( + <span className="block-editor-block-switcher__toggle-text"> + { blockTitle } + </span> + ) } + </> +); + export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { const { canRemove, @@ -247,6 +262,7 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { : __( 'Multiple blocks selected' ); const hideDropdown = disabled || ( ! hasBlockStyles && ! canRemove ); + if ( hideDropdown ) { return ( <ToolbarGroup> @@ -255,14 +271,11 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { className="block-editor-block-switcher__no-switcher-icon" title={ blockSwitcherLabel } icon={ - <> - <BlockIcon icon={ icon } showColors /> - { ( isReusable || isTemplate ) && ( - <span className="block-editor-block-switcher__toggle-text"> - { blockTitle } - </span> - ) } - </> + <BlockIndicator + icon={ icon } + showTitle={ isReusable || isTemplate } + blockTitle={ blockTitle } + /> } /> </ToolbarGroup> @@ -292,18 +305,11 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { className: 'block-editor-block-switcher__popover', } } icon={ - <> - <BlockIcon - icon={ icon } - className="block-editor-block-switcher__toggle" - showColors - /> - { ( isReusable || isTemplate ) && ( - <span className="block-editor-block-switcher__toggle-text"> - { blockTitle } - </span> - ) } - </> + <BlockIndicator + icon={ icon } + showTitle={ isReusable || isTemplate } + blockTitle={ blockTitle } + /> } toggleProps={ { description: blockSwitcherDescription, diff --git a/packages/block-editor/src/components/block-switcher/style.scss b/packages/block-editor/src/components/block-switcher/style.scss index afcb576bd8db49..287afaed4055c6 100644 --- a/packages/block-editor/src/components/block-switcher/style.scss +++ b/packages/block-editor/src/components/block-switcher/style.scss @@ -46,12 +46,11 @@ } // Even when the block switcher does not have any transformations, it still serves as a block indicator. -.components-button.block-editor-block-switcher__no-switcher-icon:disabled { - opacity: 1; +.components-button.block-editor-block-switcher__no-switcher-icon[aria-disabled="true"] { + color: $gray-900; // Since it's not clickable, though, don't show a hover state. - &, - .block-editor-block-icon.has-colors { + &:hover { color: $gray-900; } } diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 90e6394d0975dd..984670762262c9 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -59,6 +59,7 @@ export function PrivateBlockToolbar( { const { blockClientId, blockClientIds, + isContentOnlyEditingMode, isDefaultEditingMode, blockType, toolbarKey, @@ -85,8 +86,8 @@ export function PrivateBlockToolbar( { const firstParentClientId = parents[ parents.length - 1 ]; const parentBlockName = getBlockName( firstParentClientId ); const parentBlockType = getBlockType( parentBlockName ); - const _isDefaultEditingMode = - getBlockEditingMode( selectedBlockClientId ) === 'default'; + const editingMode = getBlockEditingMode( selectedBlockClientId ); + const _isDefaultEditingMode = editingMode === 'default'; const _blockName = getBlockName( selectedBlockClientId ); const isValid = selectedBlockClientIds.every( ( id ) => isBlockValid( id ) @@ -101,6 +102,7 @@ export function PrivateBlockToolbar( { return { blockClientId: selectedBlockClientId, blockClientIds: selectedBlockClientIds, + isContentOnlyEditingMode: editingMode === 'contentOnly', isDefaultEditingMode: _isDefaultEditingMode, blockType: selectedBlockClientId && getBlockType( _blockName ), shouldShowVisualToolbar: isValid && isVisual, @@ -171,7 +173,9 @@ export function PrivateBlockToolbar( { isLargeViewport && isDefaultEditingMode && <BlockParentSelector /> } { ( shouldShowVisualToolbar || isMultiToolbar ) && - ( isDefaultEditingMode || isSynced ) && ( + ( isDefaultEditingMode || + isContentOnlyEditingMode || + isSynced ) && ( <div ref={ nodeRef } { ...showHoveredOrFocusedGestures } From 520fa41016d9e469aee9328724ac78744f257bf1 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Thu, 29 Aug 2024 19:12:12 +0100 Subject: [PATCH 0600/1908] Update modal animation (#64580) Unlinked contributors: nick-a8c. Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: hanneslsm <hanneslsm@git.wordpress.org> Co-authored-by: paaljoachim <paaljoachim@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/base-styles/_animations.scss | 4 ++-- packages/components/CHANGELOG.md | 1 + packages/components/src/modal/style.scss | 9 +++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/base-styles/_animations.scss b/packages/base-styles/_animations.scss index bdfd7595da8e44..ce1f935b7d4d5b 100644 --- a/packages/base-styles/_animations.scss +++ b/packages/base-styles/_animations.scss @@ -1,5 +1,5 @@ -@mixin edit-post__fade-in-animation($speed: 0.2s, $delay: 0s) { - animation: edit-post__fade-in-animation $speed ease-out $delay; +@mixin edit-post__fade-in-animation($speed: 0.08s, $delay: 0s) { + animation: edit-post__fade-in-animation $speed linear $delay; animation-fill-mode: forwards; @include reduce-motion("animation"); } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index ce3fd808e7ed89..fc74129492fd75 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -44,6 +44,7 @@ - `TimePicker` (on the inputs) - `TreeSelect` - `UnitControl` +- `Modal`: Update animation effect ([#64580](https://github.com/WordPress/gutenberg/pull/64580)). ### Bug Fixes diff --git a/packages/components/src/modal/style.scss b/packages/components/src/modal/style.scss index 75ba7e1384e4c1..47d5df116d8865 100644 --- a/packages/components/src/modal/style.scss +++ b/packages/components/src/modal/style.scss @@ -8,7 +8,6 @@ background-color: rgba($black, 0.35); z-index: z-index(".components-modal__screen-overlay"); display: flex; - // backdrop-filter: blur($grid-unit); // This animates the appearance of the white background. @include edit-post__fade-in-animation(); } @@ -26,7 +25,7 @@ // Have the content element fill the vertical space yet not overflow. display: flex; // Animate the modal frame/contents appearing on the page. - animation: components-modal__appear-animation 0.1s ease-out; + animation: components-modal__appear-animation 0.26s cubic-bezier(0.29, 0, 0, 1); animation-fill-mode: forwards; @include reduce-motion("animation"); @@ -80,10 +79,12 @@ @keyframes components-modal__appear-animation { from { - transform: translateY($grid-unit-40); + opacity: 0; + transform: scale(0.9); } to { - transform: translateY(0); + opacity: 1; + transform: scale(1); } } From bab73af901c162ad6e8ff46c4254d3184dbd94d4 Mon Sep 17 00:00:00 2001 From: JuanMa <juanma.garrido@automattic.com> Date: Fri, 30 Aug 2024 07:20:52 +0100 Subject: [PATCH 0601/1908] fixed property name for defaultLayouts settings (#64897) --- packages/dataviews/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 1d1f62e1032f0c..e217f6af337a4b 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -174,8 +174,9 @@ Properties: - `sort`: - `field`: the field used for sorting the dataset. - `direction`: the direction to use for sorting, one of `asc` or `desc`. -- `fields`: the `id` of the fields that are visible in the UI. -- `layout`: config that is specific to a particular layout type: + +- `fields`: the `id` of the fields that are visible in the UI and the specific order in which they are displayed. +- `layout`: config that is specific to a particular layout type. | Properties of `layout` | Table | Grid | List | | --- | --- | --- | --- | @@ -300,7 +301,7 @@ For example, this is how you'd enable only the table view type: const defaultLayouts = { table: { layout: { - primaryKey: 'my-key', + primaryField: 'my-key', }, }, }; From 77784ee2d2f2b90295cf511c957ba6736422f43f Mon Sep 17 00:00:00 2001 From: rithik56 <70520896+rithik56@users.noreply.github.com> Date: Fri, 30 Aug 2024 13:53:01 +0530 Subject: [PATCH 0602/1908] Scripts: Added chunk filename in webpack config to avoid reading stale files (#58176) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added chunk filename in webpack config to avoid reading stale files from cache * fixed typo in webpack config * Update CHANGELOG.md --------- Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> Unlinked contributors: rithik56. Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: johnstonphilip <johnstonphilip@git.wordpress.org> --- packages/scripts/CHANGELOG.md | 4 ++++ packages/scripts/config/webpack.config.js | 1 + 2 files changed, 5 insertions(+) diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 178b1c4fae36da..9d39bf21f1ba0f 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- Added chunk filename in webpack config to avoid reading stale files ([#58176](https://github.com/WordPress/gutenberg/pull/58176)). + ## 28.6.0 (2024-08-21) ## 28.5.0 (2024-08-07) diff --git a/packages/scripts/config/webpack.config.js b/packages/scripts/config/webpack.config.js index 508d4d262942d1..d8f9d356dda891 100644 --- a/packages/scripts/config/webpack.config.js +++ b/packages/scripts/config/webpack.config.js @@ -147,6 +147,7 @@ const baseConfig = { target, output: { filename: '[name].js', + chunkFilename: '[name].js?v=[chunkhash]', path: resolve( process.cwd(), 'build' ), }, resolve: { From d74df84a7ccc96888a2f4186e25659a858bb6f36 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 30 Aug 2024 12:31:05 +0400 Subject: [PATCH 0603/1908] Core Data: Derive collection totals for unbound queries (#64772) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/core-data/src/hooks/test/use-entity-records.js | 4 ++-- packages/core-data/src/resolvers.js | 4 ++++ packages/core-data/src/test/resolvers.js | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/core-data/src/hooks/test/use-entity-records.js b/packages/core-data/src/hooks/test/use-entity-records.js index 2547cda890b05e..f1d69e85a051dc 100644 --- a/packages/core-data/src/hooks/test/use-entity-records.js +++ b/packages/core-data/src/hooks/test/use-entity-records.js @@ -69,8 +69,8 @@ describe( 'useEntityRecords', () => { hasStarted: true, isResolving: false, status: 'SUCCESS', - totalItems: null, - totalPages: null, + totalItems: 3, + totalPages: 1, } ); } ); } ); diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 2cec1997c0efd9..11079dbf091971 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -273,6 +273,10 @@ export const getEntityRecords = }; } else { records = Object.values( await apiFetch( { path } ) ); + meta = { + totalItems: records.length, + totalPages: 1, + }; } // If we request fields but the result doesn't contain the fields, diff --git a/packages/core-data/src/test/resolvers.js b/packages/core-data/src/test/resolvers.js index 240d6b1e1a29c2..5e36abd2659122 100644 --- a/packages/core-data/src/test/resolvers.js +++ b/packages/core-data/src/test/resolvers.js @@ -181,7 +181,7 @@ describe( 'getEntityRecords', () => { {}, false, undefined, - undefined + { totalItems: 2, totalPages: 1 } ); } ); From 8aa2e0b5cde09797ab849f29fbadccea5e59a58f Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 30 Aug 2024 11:11:36 +0200 Subject: [PATCH 0604/1908] DropdownMenuV2: add GroupLabel subcomponent (#64854) * DropdownMenuV2: add GroupLabel subcomponent * Use in Storybook examples * Use Text component * Use the first-party group label in the block bindings dropdown menu * Apply design feedback * Remove unneeded block-editor-bindings__popover classname * Add dedicated DropdownMenuGroupLabelProps type * Fix README * CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- .../block-editor/src/hooks/block-bindings.js | 10 +---- .../src/hooks/block-bindings.scss | 8 ---- packages/components/CHANGELOG.md | 1 + .../components/src/dropdown-menu-v2/README.md | 18 +++++++- .../src/dropdown-menu-v2/group-label.tsx | 37 +++++++++++++++ .../components/src/dropdown-menu-v2/index.tsx | 4 ++ .../dropdown-menu-v2/stories/index.story.tsx | 45 ++++++++++++++----- .../components/src/dropdown-menu-v2/styles.ts | 9 ++++ .../components/src/dropdown-menu-v2/types.ts | 7 +++ 9 files changed, 109 insertions(+), 30 deletions(-) create mode 100644 packages/components/src/dropdown-menu-v2/group-label.tsx diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 961a34f6f858fc..3b90ecc1a0c178 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -55,14 +55,9 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) { <Fragment key={ name }> <DropdownMenuV2.Group> { Object.keys( fieldsList ).length > 1 && ( - <Text - className="block-editor-bindings__source-label" - upperCase - variant="muted" - aria-hidden - > + <DropdownMenuV2.GroupLabel> { registeredSources[ name ].label } - </Text> + </DropdownMenuV2.GroupLabel> ) } { Object.entries( fields ).map( ( [ key, value ] ) => ( <DropdownMenuV2.RadioItem @@ -160,7 +155,6 @@ function EditableBlockBindingsPanelItems( { isMobile ? 'bottom-start' : 'left-start' } gutter={ isMobile ? 8 : 36 } - className="block-editor-bindings__popover" trigger={ <Item> <BlockBindingsAttribute diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss index 603b2115623b8f..69eaa18d57daea 100644 --- a/packages/block-editor/src/hooks/block-bindings.scss +++ b/packages/block-editor/src/hooks/block-bindings.scss @@ -4,11 +4,3 @@ div.block-editor-bindings__panel { color: inherit; } } - -.block-editor-bindings__popover { - // This won't be needed if `DropdownMenuGroup` component handles the label. - .block-editor-bindings__source-label { - grid-column: 2; - margin: $grid-unit-10 0; - } -} diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index fc74129492fd75..95fcc006b32a1b 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -54,6 +54,7 @@ - `DropdownMenu` v2: fix flashing menu item styles when using keyboard ([#64873](https://github.com/WordPress/gutenberg/pull/64873)). - `DropdownMenu` v2: refactor to overloaded naming convention ([#64654](https://github.com/WordPress/gutenberg/pull/64654)). +- `DropdownMenu` v2: add `GroupLabel` subcomponent ([#64854](https://github.com/WordPress/gutenberg/pull/64854)). - `Composite` V2: fix Storybook docgen ([#64682](https://github.com/WordPress/gutenberg/pull/64682)). ## 28.6.0 (2024-08-21) diff --git a/packages/components/src/dropdown-menu-v2/README.md b/packages/components/src/dropdown-menu-v2/README.md index d0547f1f142600..771b5b74b24bf7 100644 --- a/packages/components/src/dropdown-menu-v2/README.md +++ b/packages/components/src/dropdown-menu-v2/README.md @@ -311,7 +311,7 @@ The help text contents. - Required: yes -### `DropdownMenuGroup` +### `DropdownMenuV2.Group` Used to group menu items. @@ -325,6 +325,20 @@ The contents of the group. - Required: yes -### `DropdownMenuSeparatorProps` +### `DropdownMenuV2.GroupLabel` + +Used to render a group label. The label text should be kept as short as possible. + +#### Props + +The component accepts the following props: + +##### `children`: `React.ReactNode` + +The contents of the group label. + +- Required: yes + +### `DropdownMenuV2.Separator` Used to render a visual separator. diff --git a/packages/components/src/dropdown-menu-v2/group-label.tsx b/packages/components/src/dropdown-menu-v2/group-label.tsx new file mode 100644 index 00000000000000..7d838ef9fa620a --- /dev/null +++ b/packages/components/src/dropdown-menu-v2/group-label.tsx @@ -0,0 +1,37 @@ +/** + * WordPress dependencies + */ +import { forwardRef, useContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { WordPressComponentProps } from '../context'; +import { DropdownMenuContext } from './context'; +import { Text } from '../text'; +import type { DropdownMenuGroupLabelProps } from './types'; +import * as Styled from './styles'; + +export const DropdownMenuGroupLabel = forwardRef< + HTMLDivElement, + WordPressComponentProps< DropdownMenuGroupLabelProps, 'div', false > +>( function DropdownMenuGroup( props, ref ) { + const dropdownMenuContext = useContext( DropdownMenuContext ); + return ( + <Styled.DropdownMenuGroupLabel + ref={ ref } + render={ + // @ts-expect-error The `children` prop is passed + <Text + upperCase + variant="muted" + size="11px" + weight={ 500 } + lineHeight="16px" + /> + } + { ...props } + store={ dropdownMenuContext?.store } + /> + ); +} ); diff --git a/packages/components/src/dropdown-menu-v2/index.tsx b/packages/components/src/dropdown-menu-v2/index.tsx index 96d335f7b38bb9..34805d2d3e2687 100644 --- a/packages/components/src/dropdown-menu-v2/index.tsx +++ b/packages/components/src/dropdown-menu-v2/index.tsx @@ -32,6 +32,7 @@ import { DropdownMenuItem } from './item'; import { DropdownMenuCheckboxItem } from './checkbox-item'; import { DropdownMenuRadioItem } from './radio-item'; import { DropdownMenuGroup } from './group'; +import { DropdownMenuGroupLabel } from './group-label'; import { DropdownMenuSeparator } from './separator'; import { DropdownMenuItemLabel } from './item-label'; import { DropdownMenuItemHelpText } from './item-help-text'; @@ -215,6 +216,9 @@ export const DropdownMenuV2 = Object.assign( Group: Object.assign( DropdownMenuGroup, { displayName: 'DropdownMenuV2.Group', } ), + GroupLabel: Object.assign( DropdownMenuGroupLabel, { + displayName: 'DropdownMenuV2.GroupLabel', + } ), Separator: Object.assign( DropdownMenuSeparator, { displayName: 'DropdownMenuV2.Separator', } ), diff --git a/packages/components/src/dropdown-menu-v2/stories/index.story.tsx b/packages/components/src/dropdown-menu-v2/stories/index.story.tsx index fd14bb68b1d6ad..90d15ca2ea6c18 100644 --- a/packages/components/src/dropdown-menu-v2/stories/index.story.tsx +++ b/packages/components/src/dropdown-menu-v2/stories/index.story.tsx @@ -32,6 +32,8 @@ const meta: Meta< typeof DropdownMenuV2 > = { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 Group: DropdownMenuV2.Group, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + GroupLabel: DropdownMenuV2.GroupLabel, + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 Separator: DropdownMenuV2.Separator, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 Context: DropdownMenuV2.Context, @@ -83,6 +85,7 @@ export const Default: StoryFn< typeof DropdownMenuV2 > = ( props ) => ( <DropdownMenuV2.Item disabled>Disabled item</DropdownMenuV2.Item> <DropdownMenuV2.Separator /> <DropdownMenuV2.Group> + <DropdownMenuV2.GroupLabel>Group label</DropdownMenuV2.GroupLabel> <DropdownMenuV2.Item prefix={ <Icon icon={ customLink } size={ 24 } /> } > @@ -182,6 +185,9 @@ export const WithCheckboxes: StoryFn< typeof DropdownMenuV2 > = ( props ) => { return ( <DropdownMenuV2 { ...props }> <DropdownMenuV2.Group> + <DropdownMenuV2.GroupLabel> + Single selection, uncontrolled + </DropdownMenuV2.GroupLabel> <DropdownMenuV2.CheckboxItem name="checkbox-individual-uncontrolled-a" value="a" @@ -191,7 +197,7 @@ export const WithCheckboxes: StoryFn< typeof DropdownMenuV2 > = ( props ) => { Checkbox item A </DropdownMenuV2.ItemLabel> <DropdownMenuV2.ItemHelpText> - Uncontrolled + Initially unchecked </DropdownMenuV2.ItemHelpText> </DropdownMenuV2.CheckboxItem> <DropdownMenuV2.CheckboxItem @@ -203,12 +209,15 @@ export const WithCheckboxes: StoryFn< typeof DropdownMenuV2 > = ( props ) => { Checkbox item B </DropdownMenuV2.ItemLabel> <DropdownMenuV2.ItemHelpText> - Uncontrolled, initially checked + Initially checked </DropdownMenuV2.ItemHelpText> </DropdownMenuV2.CheckboxItem> </DropdownMenuV2.Group> <DropdownMenuV2.Separator /> <DropdownMenuV2.Group> + <DropdownMenuV2.GroupLabel> + Single selection, controlled + </DropdownMenuV2.GroupLabel> <DropdownMenuV2.CheckboxItem name="checkbox-individual-controlled-a" value="a" @@ -219,7 +228,7 @@ export const WithCheckboxes: StoryFn< typeof DropdownMenuV2 > = ( props ) => { Checkbox item A </DropdownMenuV2.ItemLabel> <DropdownMenuV2.ItemHelpText> - Controlled + Initially unchecked </DropdownMenuV2.ItemHelpText> </DropdownMenuV2.CheckboxItem> <DropdownMenuV2.CheckboxItem @@ -232,12 +241,15 @@ export const WithCheckboxes: StoryFn< typeof DropdownMenuV2 > = ( props ) => { Checkbox item B </DropdownMenuV2.ItemLabel> <DropdownMenuV2.ItemHelpText> - Controlled, initially checked + Initially checked </DropdownMenuV2.ItemHelpText> </DropdownMenuV2.CheckboxItem> </DropdownMenuV2.Group> <DropdownMenuV2.Separator /> <DropdownMenuV2.Group> + <DropdownMenuV2.GroupLabel> + Multiple selection, uncontrolled + </DropdownMenuV2.GroupLabel> <DropdownMenuV2.CheckboxItem name="checkbox-multiple-uncontrolled" value="a" @@ -246,7 +258,7 @@ export const WithCheckboxes: StoryFn< typeof DropdownMenuV2 > = ( props ) => { Checkbox item A </DropdownMenuV2.ItemLabel> <DropdownMenuV2.ItemHelpText> - Uncontrolled, multiple selection + Initially unchecked </DropdownMenuV2.ItemHelpText> </DropdownMenuV2.CheckboxItem> <DropdownMenuV2.CheckboxItem @@ -258,12 +270,15 @@ export const WithCheckboxes: StoryFn< typeof DropdownMenuV2 > = ( props ) => { Checkbox item B </DropdownMenuV2.ItemLabel> <DropdownMenuV2.ItemHelpText> - Uncontrolled, multiple selection, initially checked + Initially checked </DropdownMenuV2.ItemHelpText> </DropdownMenuV2.CheckboxItem> </DropdownMenuV2.Group> <DropdownMenuV2.Separator /> <DropdownMenuV2.Group> + <DropdownMenuV2.GroupLabel> + Multiple selection, controlled + </DropdownMenuV2.GroupLabel> <DropdownMenuV2.CheckboxItem name="checkbox-multiple-controlled" value="a" @@ -274,7 +289,7 @@ export const WithCheckboxes: StoryFn< typeof DropdownMenuV2 > = ( props ) => { Checkbox item A </DropdownMenuV2.ItemLabel> <DropdownMenuV2.ItemHelpText> - Controlled, multiple selection + Initially unchecked </DropdownMenuV2.ItemHelpText> </DropdownMenuV2.CheckboxItem> <DropdownMenuV2.CheckboxItem @@ -287,7 +302,7 @@ export const WithCheckboxes: StoryFn< typeof DropdownMenuV2 > = ( props ) => { Checkbox item B </DropdownMenuV2.ItemLabel> <DropdownMenuV2.ItemHelpText> - Controlled, multiple selection, initially checked + Initially checked </DropdownMenuV2.ItemHelpText> </DropdownMenuV2.CheckboxItem> </DropdownMenuV2.Group> @@ -307,12 +322,15 @@ export const WithRadios: StoryFn< typeof DropdownMenuV2 > = ( props ) => { return ( <DropdownMenuV2 { ...props }> <DropdownMenuV2.Group> + <DropdownMenuV2.GroupLabel> + Uncontrolled + </DropdownMenuV2.GroupLabel> <DropdownMenuV2.RadioItem name="radio-uncontrolled" value="one"> <DropdownMenuV2.ItemLabel> Radio item 1 </DropdownMenuV2.ItemLabel> <DropdownMenuV2.ItemHelpText> - Uncontrolled + Initially unchecked </DropdownMenuV2.ItemHelpText> </DropdownMenuV2.RadioItem> <DropdownMenuV2.RadioItem @@ -324,12 +342,15 @@ export const WithRadios: StoryFn< typeof DropdownMenuV2 > = ( props ) => { Radio item 2 </DropdownMenuV2.ItemLabel> <DropdownMenuV2.ItemHelpText> - Uncontrolled, initially checked + Initially checked </DropdownMenuV2.ItemHelpText> </DropdownMenuV2.RadioItem> </DropdownMenuV2.Group> <DropdownMenuV2.Separator /> <DropdownMenuV2.Group> + <DropdownMenuV2.GroupLabel> + Controlled + </DropdownMenuV2.GroupLabel> <DropdownMenuV2.RadioItem name="radio-controlled" value="one" @@ -340,7 +361,7 @@ export const WithRadios: StoryFn< typeof DropdownMenuV2 > = ( props ) => { Radio item 1 </DropdownMenuV2.ItemLabel> <DropdownMenuV2.ItemHelpText> - Controlled + Initially unchecked </DropdownMenuV2.ItemHelpText> </DropdownMenuV2.RadioItem> <DropdownMenuV2.RadioItem @@ -353,7 +374,7 @@ export const WithRadios: StoryFn< typeof DropdownMenuV2 > = ( props ) => { Radio item 2 </DropdownMenuV2.ItemLabel> <DropdownMenuV2.ItemHelpText> - Controlled, initially checked + Initially checked </DropdownMenuV2.ItemHelpText> </DropdownMenuV2.RadioItem> </DropdownMenuV2.Group> diff --git a/packages/components/src/dropdown-menu-v2/styles.ts b/packages/components/src/dropdown-menu-v2/styles.ts index a39ef83326c3aa..9bb2f07b282622 100644 --- a/packages/components/src/dropdown-menu-v2/styles.ts +++ b/packages/components/src/dropdown-menu-v2/styles.ts @@ -311,6 +311,15 @@ export const DropdownMenuGroup = styled( Ariakit.MenuGroup )` display: contents; `; +export const DropdownMenuGroupLabel = styled( Ariakit.MenuGroupLabel )` + /* Occupy the width of all grid columns (ie. full width) */ + grid-column: 1 / -1; + + padding-block-start: ${ space( 3 ) }; + padding-block-end: ${ space( 2 ) }; + padding-inline: ${ ITEM_PADDING_INLINE }; +`; + export const DropdownMenuSeparator = styled( Ariakit.MenuSeparator )< Pick< DropdownMenuContext, 'variant' > >` diff --git a/packages/components/src/dropdown-menu-v2/types.ts b/packages/components/src/dropdown-menu-v2/types.ts index f49f026b787933..795cd9ac76ff58 100644 --- a/packages/components/src/dropdown-menu-v2/types.ts +++ b/packages/components/src/dropdown-menu-v2/types.ts @@ -87,6 +87,13 @@ export interface DropdownMenuGroupProps { children: React.ReactNode; } +export interface DropdownMenuGroupLabelProps { + /** + * The contents of the dropdown menu group. + */ + children: React.ReactNode; +} + export interface DropdownMenuItemProps { /** * The contents of the menu item. From 75955973b7cb4f48f780b13235757295684ca3dd Mon Sep 17 00:00:00 2001 From: JuanMa <juanma.garrido@automattic.com> Date: Fri, 30 Aug 2024 10:16:23 +0100 Subject: [PATCH 0605/1908] Dataviews docs: Layout properties checks and link (#64918) * fix check icons * defaultLayouts clarification and link to properties of layout --- packages/dataviews/README.md | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index e217f6af337a4b..cc1ef3bbebe4d0 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -124,7 +124,7 @@ Each field is an object with the following properties: - `value`: The id of the value to filter to (for internal use) - `label`: The text that will be displayed in the UI for the item. - - `description`: A longer description that describes the element, to also be displayed. Optional. + - `description`: A longer description that describes the element, to also be displayed. Optional. To enable the filter by a field we just need to set a proper value to the `elements` property of the field we'd like to filter by. @@ -172,20 +172,23 @@ Properties: - `perPage`: number of records to show per page. - `page`: the page that is visible. - `sort`: + - `field`: the field used for sorting the dataset. - `direction`: the direction to use for sorting, one of `asc` or `desc`. - `fields`: the `id` of the fields that are visible in the UI and the specific order in which they are displayed. - `layout`: config that is specific to a particular layout type. -| Properties of `layout` | Table | Grid | List | -| --- | --- | --- | --- | -| `primaryField`: the field's `id` to be highlighted in each layout. It's not hidable. | ✓ | ✓ | ✓ | -| `mediaField`: the field's `id` to be used for rendering each card's media. It's not hiddable. | | ✓ | ✓ | -| `columnFields`: a list of field's `id` to render vertically stacked instead of horizontally (the default). | | ✓ | | -| `badgeFields`: a list of field's `id` to render without label and styled as badges. | | ✓ | | -| `combinedFields`: a list of "virtual" fields that are made by combining others. See "Combining fields" section. | ✓ | | | -| `styles`: additional `width`, `maxWidth`, `minWidth` styles for each field column. | ✓ | | | +#### Properties of `layout` + +| Properties of `layout` | Table | Grid | List | +| --------------------------------------------------------------------------------------------------------------- | ----- | ---- | ---- | +| `primaryField`: the field's `id` to be highlighted in each layout. It's not hidable. | ✓ | ✓ | ✓ | +| `mediaField`: the field's `id` to be used for rendering each card's media. It's not hiddable. | | ✓ | ✓ | +| `columnFields`: a list of field's `id` to render vertically stacked instead of horizontally (the default). | | ✓ | | +| `badgeFields`: a list of field's `id` to render without label and styled as badges. | | ✓ | | +| `combinedFields`: a list of "virtual" fields that are made by combining others. See "Combining fields" section. | ✓ | | | +| `styles`: additional `width`, `maxWidth`, `minWidth` styles for each field column. | ✓ | | | ### `onChangeView`: `function` @@ -307,6 +310,8 @@ const defaultLayouts = { }; ``` +The `defaultLayouts` property should be an object that includes properties named `table`, `grid`, or `list`. Each of these properties should contain a `layout` property, which holds the configuration for each specific layout type. Check [here](#properties-of-layout) the full list of properties available for each layout's configuration + ### `onChangeSelection`: `function` Callback that signals the user selected one of more items, and takes them as parameter. So far, only the `list` view implements it. @@ -331,8 +336,8 @@ Each "virtual field", has to provide an `id` and `label` (optionally a `header` Additionally, they need to provide: -- `children`: a list of field's `id` to combine -- `direction`: how should they be stacked, `vertically` or `horizontally` +- `children`: a list of field's `id` to combine +- `direction`: how should they be stacked, `vertically` or `horizontally` For example, this is how you'd define a `site` field which is a combination of a `title` and `description` fields, which are not displayed: From 7ed54f49085e6d9443df0f520dc8eec6a7116750 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Fri, 30 Aug 2024 12:31:29 +0200 Subject: [PATCH 0606/1908] Block Bindings: Remove `getPlaceholder` API and rely on `key` argument or source label (#64910) * Remove `getPlaceholder` API * Skip unregistered sources * Add e2e tests * Accept undefined as a valid value * Properly check if value is a URL Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- .../src/hooks/use-bindings-attributes.js | 47 +++++++++--------- packages/blocks/src/api/registration.js | 11 +---- packages/blocks/src/api/test/registration.js | 16 ------ packages/blocks/src/store/private-actions.js | 1 - packages/blocks/src/store/reducer.js | 1 - packages/editor/src/bindings/post-meta.js | 7 ++- .../editor/various/block-bindings.spec.js | 49 ++++++++++++++++++- 7 files changed, 75 insertions(+), 57 deletions(-) diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index 4cac29a8bc5e91..e1ebf5fda6b8ee 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -10,6 +10,7 @@ import { addFilter } from '@wordpress/hooks'; /** * Internal dependencies */ +import isURLLike from '../components/link-control/is-url-like'; import { unlock } from '../lock-unlock'; import BlockContext from '../components/block-context'; @@ -134,10 +135,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( ) ) { const { source: sourceName, args: sourceArgs } = binding; const source = sources[ sourceName ]; - if ( - ! source?.getValues || - ! canBindAttribute( name, attributeName ) - ) { + if ( ! source || ! canBindAttribute( name, attributeName ) ) { continue; } @@ -161,29 +159,30 @@ export const withBlockBindingSupport = createHigherOrderComponent( } // Get values in batch if the source supports it. - const values = source.getValues( { - registry, - context, - clientId, - bindings, - } ); + let values = {}; + if ( ! source.getValues ) { + Object.keys( bindings ).forEach( ( attr ) => { + // Default to the `key` or the source label when `getValues` doesn't exist + values[ attr ] = + bindings[ attr ].args?.key || source.label; + } ); + } else { + values = source.getValues( { + registry, + context, + clientId, + bindings, + } ); + } for ( const [ attributeName, value ] of Object.entries( values ) ) { - // Use placeholder when value is undefined. - if ( value === undefined ) { - if ( attributeName === 'url' ) { - attributes[ attributeName ] = null; - } else { - attributes[ attributeName ] = - source.getPlaceholder?.( { - registry, - context, - clientId, - attributeName, - args: bindings[ attributeName ].args, - } ); - } + if ( + attributeName === 'url' && + ( ! value || ! isURLLike( value ) ) + ) { + // Return null if value is not a valid URL. + attributes[ attributeName ] = null; } else { attributes[ attributeName ] = value; } diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index e109a7e562f00e..b0f5ae350759f0 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -773,7 +773,6 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { * @param {Array} [source.usesContext] Array of context needed by the source only in the editor. * @param {Function} [source.getValues] Function to get the values from the source. * @param {Function} [source.setValues] Function to update multiple values connected to the source. - * @param {Function} [source.getPlaceholder] Function to get the placeholder when the value is undefined. * @param {Function} [source.canUserEditValue] Function to determine if the user can edit the value. * @param {Function} [source.getFieldsList] Function to get the lists of fields to expose in the connections panel. * @@ -787,7 +786,6 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { * label: _x( 'My Custom Source', 'block bindings source' ), * getValues: () => getSourceValues(), * setValues: () => updateMyCustomValuesInBatch(), - * getPlaceholder: () => 'Placeholder text when the value is undefined', * canUserEditValue: () => true, * } ); * ``` @@ -799,7 +797,6 @@ export const registerBlockBindingsSource = ( source ) => { usesContext, getValues, setValues, - getPlaceholder, canUserEditValue, getFieldsList, } = source; @@ -889,13 +886,7 @@ export const registerBlockBindingsSource = ( source ) => { return; } - // Check the `getPlaceholder` property is correct. - if ( getPlaceholder && typeof getPlaceholder !== 'function' ) { - warning( 'Block bindings source getPlaceholder must be a function.' ); - return; - } - - // Check the `getPlaceholder` property is correct. + // Check the `canUserEditValue` property is correct. if ( canUserEditValue && typeof canUserEditValue !== 'function' ) { warning( 'Block bindings source canUserEditValue must be a function.' ); return; diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index 874d664f139047..483949af4fe5f2 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -1630,19 +1630,6 @@ describe( 'blocks', () => { expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); } ); - // Check the `getPlaceholder` callback is correct. - it( 'should reject invalid getPlaceholder callback', () => { - registerBlockBindingsSource( { - name: 'core/testing', - label: 'testing', - getPlaceholder: 'should be a function', - } ); - expect( console ).toHaveWarnedWith( - 'Block bindings source getPlaceholder must be a function.' - ); - expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); - } ); - // Check the `canUserEditValue` callback is correct. it( 'should reject invalid canUserEditValue callback', () => { registerBlockBindingsSource( { @@ -1676,7 +1663,6 @@ describe( 'blocks', () => { usesContext: [ 'postId' ], getValues: () => 'value', setValues: () => 'new values', - getPlaceholder: () => 'placeholder', canUserEditValue: () => true, getFieldsList: () => { return { field: 'value' }; @@ -1701,7 +1687,6 @@ describe( 'blocks', () => { expect( source.usesContext ).toBeUndefined(); expect( source.getValues ).toBeUndefined(); expect( source.setValues ).toBeUndefined(); - expect( source.getPlaceholder ).toBeUndefined(); expect( source.canUserEditValue ).toBeUndefined(); expect( source.getFieldsList ).toBeUndefined(); unregisterBlockBindingsSource( 'core/valid-source' ); @@ -1726,7 +1711,6 @@ describe( 'blocks', () => { const clientOnlyProperties = { getValues: () => 'values', setValues: () => 'new values', - getPlaceholder: () => 'placeholder', canUserEditValue: () => true, }; registerBlockBindingsSource( { diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index 6d2f7598ef7838..02f8506b3c3bf8 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -54,7 +54,6 @@ export function addBlockBindingsSource( source ) { usesContext: source.usesContext, getValues: source.getValues, setValues: source.setValues, - getPlaceholder: source.getPlaceholder, canUserEditValue: source.canUserEditValue, getFieldsList: source.getFieldsList, }; diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index f1cfdcd04e3035..fbcec7a619cf63 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -404,7 +404,6 @@ export function blockBindingsSources( state = {}, action ) { ), getValues: action.getValues, setValues: action.setValues, - getPlaceholder: action.getPlaceholder, canUserEditValue: action.canUserEditValue, getFieldsList: action.getFieldsList, }, diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index a1575f2b4baba2..1ecd6ea50ba274 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -10,9 +10,6 @@ import { store as editorStore } from '../store'; export default { name: 'core/post-meta', - getPlaceholder( { args } ) { - return args.key; - }, getValues( { registry, context, bindings } ) { const meta = registry .select( coreDataStore ) @@ -23,7 +20,9 @@ export default { )?.meta; const newValues = {}; for ( const [ attributeName, source ] of Object.entries( bindings ) ) { - newValues[ attributeName ] = meta?.[ source.args.key ]; + // Use the key if the value is not set. + newValues[ attributeName ] = + meta?.[ source.args.key ] || source.args.key; } return newValues; }, diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index d0e1f079ce8439..3fa17bdf6163a8 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -41,7 +41,7 @@ test.describe( 'Block bindings', () => { } ); test.describe( 'Paragraph', () => { - test( 'should show the value of the custom field', async ( { + test( 'should show the key of the custom field in post meta', async ( { editor, } ) => { await editor.insertBlock( { @@ -66,6 +66,53 @@ test.describe( 'Block bindings', () => { ); } ); + test( 'should show the key of the custom field in server sources with key', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'paragraph default content', + metadata: { + bindings: { + content: { + source: 'core/server-source', + args: { key: 'text_custom_field' }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( + 'text_custom_field' + ); + } ); + + test( 'should show the source label in server sources without key', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'paragraph default content', + metadata: { + bindings: { + content: { + source: 'core/server-source', + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( 'Server Source' ); + } ); + test( 'should lock the appropriate controls with a registered source', async ( { editor, page, From 497f58182a270cc3cfef123913ff51f800e9d493 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Fri, 30 Aug 2024 12:57:36 +0200 Subject: [PATCH 0607/1908] Core data: Performance: fix receive user permissions (#64894) --- packages/core-data/src/actions.js | 22 ++++++++++++++++++++++ packages/core-data/src/reducer.js | 5 +++++ packages/core-data/src/resolvers.js | 11 +++++++---- packages/core-data/src/test/resolvers.js | 2 +- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index fd16675122c567..e83ad02828cfe7 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -888,6 +888,28 @@ export function receiveUserPermission( key, isAllowed ) { }; } +/** + * Returns an action object used in signalling that the current user has + * permission to perform an action on a REST resource. Ignored from + * documentation as it's internal to the data store. + * + * @ignore + * + * @param {Object<string, boolean>} permissions An object where keys represent + * actions and REST resources, and + * values indicate whether the user + * is allowed to perform the + * action. + * + * @return {Object} Action object. + */ +export function receiveUserPermissions( permissions ) { + return { + type: 'RECEIVE_USER_PERMISSIONS', + permissions, + }; +} + /** * Returns an action object used in signalling that the autosaves for a * post have been received. diff --git a/packages/core-data/src/reducer.js b/packages/core-data/src/reducer.js index 3d6473d7610366..97a8cc59041534 100644 --- a/packages/core-data/src/reducer.js +++ b/packages/core-data/src/reducer.js @@ -521,6 +521,11 @@ export function userPermissions( state = {}, action ) { ...state, [ action.key ]: action.isAllowed, }; + case 'RECEIVE_USER_PERMISSIONS': + return { + ...state, + ...action.permissions, + }; } return state; diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 11079dbf091971..2e0c2497d382d1 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -325,6 +325,7 @@ export const getEntityRecords = } ) ); const canUserResolutionsArgs = []; + const receiveUserPermissionArgs = {}; for ( const targetHint of targetHints ) { for ( const action of ALLOWED_RESOURCE_ACTIONS ) { canUserResolutionsArgs.push( [ @@ -332,17 +333,19 @@ export const getEntityRecords = { kind, name, id: targetHint.id }, ] ); - dispatch.receiveUserPermission( + receiveUserPermissionArgs[ getUserPermissionCacheKey( action, { kind, name, id: targetHint.id, - } ), - targetHint.permissions[ action ] - ); + } ) + ] = targetHint.permissions[ action ]; } } + dispatch.receiveUserPermissions( + receiveUserPermissionArgs + ); dispatch.finishResolutions( 'getEntityRecord', resolutionsArgs diff --git a/packages/core-data/src/test/resolvers.js b/packages/core-data/src/test/resolvers.js index 5e36abd2659122..c3dbdaa6533386 100644 --- a/packages/core-data/src/test/resolvers.js +++ b/packages/core-data/src/test/resolvers.js @@ -219,7 +219,7 @@ describe( 'getEntityRecords', () => { const finishResolutions = jest.fn(); const dispatch = Object.assign( jest.fn(), { receiveEntityRecords: jest.fn(), - receiveUserPermission: jest.fn(), + receiveUserPermissions: jest.fn(), __unstableAcquireStoreLock: jest.fn(), __unstableReleaseStoreLock: jest.fn(), finishResolutions, From 90e6d26c6ff56a6370f5808cdfc79709d5bf1ff2 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Fri, 30 Aug 2024 13:41:19 +0200 Subject: [PATCH 0608/1908] Paste: fix image paste from Google Forms (#64502) --- packages/blocks/src/api/raw-handling/figure-content-reducer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/blocks/src/api/raw-handling/figure-content-reducer.js b/packages/blocks/src/api/raw-handling/figure-content-reducer.js index 4dfb24f2c97816..4c8c1a8dd736bb 100644 --- a/packages/blocks/src/api/raw-handling/figure-content-reducer.js +++ b/packages/blocks/src/api/raw-handling/figure-content-reducer.js @@ -95,7 +95,7 @@ export default function figureContentReducer( node, doc, schema ) { ) { wrapFigureContent( nodeToInsert, wrapper ); } - } else if ( nodeToInsert.parentNode.nodeName === 'BODY' ) { + } else { wrapFigureContent( nodeToInsert ); } } From 5b21c10cad80c5f31d17056a058fc0ac55b69e8e Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Fri, 30 Aug 2024 14:42:20 +0200 Subject: [PATCH 0609/1908] Footnotes: only replace attribute if footnotes were detected (#63935) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: sgomes <sergiomdgomes@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/core-data/src/footnotes/index.js | 13 +++++--- .../specs/editor/various/footnotes.spec.js | 32 +++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/packages/core-data/src/footnotes/index.js b/packages/core-data/src/footnotes/index.js index 9e30f10c06a93f..3c267ae6f92cf2 100644 --- a/packages/core-data/src/footnotes/index.js +++ b/packages/core-data/src/footnotes/index.js @@ -72,6 +72,8 @@ export function updateFootnotesFromMeta( blocks, meta ) { ? RichTextData.fromHTMLString( value ) : new RichTextData( value ); + let hasFootnotes = false; + richTextValue.replacements.forEach( ( replacement ) => { if ( replacement.type === 'core/footnote' ) { const id = replacement.attributes[ 'data-fn' ]; @@ -92,13 +94,16 @@ export function updateFootnotesFromMeta( blocks, meta ) { replacement.innerHTML = toHTMLString( { value: countValue, } ); + hasFootnotes = true; } } ); - attributes[ key ] = - typeof value === 'string' - ? richTextValue.toHTMLString() - : richTextValue; + if ( hasFootnotes ) { + attributes[ key ] = + typeof value === 'string' + ? richTextValue.toHTMLString() + : richTextValue; + } } return attributes; diff --git a/test/e2e/specs/editor/various/footnotes.spec.js b/test/e2e/specs/editor/various/footnotes.spec.js index fc1918ba7ceb06..d9f571414bacf3 100644 --- a/test/e2e/specs/editor/various/footnotes.spec.js +++ b/test/e2e/specs/editor/various/footnotes.spec.js @@ -456,4 +456,36 @@ test.describe( 'Footnotes', () => { '1 ↩︎' ); } ); + + test( 'should leave alone other block attributes', async ( { + editor, + page, + } ) => { + await page.evaluate( () => { + window.wp.blocks.registerBlockType( 'core/test-block-string', { + apiVersion: 3, + title: 'Block with string attribute', + attributes: { string: { type: 'string' } }, + edit: () => null, + save: () => null, + } ); + } ); + await editor.insertBlock( { + name: 'core/test-block-string', + attributes: { string: 'a\nb' }, + } ); + + await editor.insertBlock( { name: 'core/paragraph' } ); + await page.keyboard.type( 'a' ); + await editor.showBlockToolbar(); + await editor.clickBlockToolbarButton( 'More' ); + await page.locator( 'button:text("Footnote")' ).click(); + await page.keyboard.type( '1' ); + + expect( ( await editor.getBlocks() )[ 0 ] ).toMatchObject( { + name: 'core/test-block-string', + // This should NOT be 'a<br>b'! + attributes: { string: 'a\nb' }, + } ); + } ); } ); From 78f4af2119d9a2d90c9d46efca430070916d2a94 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:06:50 +0200 Subject: [PATCH 0610/1908] Details block: add transform from any block type (#63422) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: fjorgemota <fjorgemota@git.wordpress.org> --- packages/block-library/src/details/index.js | 2 ++ .../block-library/src/details/transforms.js | 26 +++++++++++++++++++ .../editor/plugins/post-type-locking.spec.js | 1 + .../editor/various/block-switcher.spec.js | 17 ++++++++++-- 4 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 packages/block-library/src/details/transforms.js diff --git a/packages/block-library/src/details/index.js b/packages/block-library/src/details/index.js index e30d1a8e04974f..3ba5efb04e27d2 100644 --- a/packages/block-library/src/details/index.js +++ b/packages/block-library/src/details/index.js @@ -11,6 +11,7 @@ import initBlock from '../utils/init-block'; import metadata from './block.json'; import edit from './edit'; import save from './save'; +import transforms from './transforms'; const { name } = metadata; export { metadata, name }; @@ -35,6 +36,7 @@ export const settings = { }, save, edit, + transforms, }; export const init = () => initBlock( { name, metadata, settings } ); diff --git a/packages/block-library/src/details/transforms.js b/packages/block-library/src/details/transforms.js new file mode 100644 index 00000000000000..e8a30dbe34759c --- /dev/null +++ b/packages/block-library/src/details/transforms.js @@ -0,0 +1,26 @@ +/** + * WordPress dependencies + */ +import { createBlock, cloneBlock } from '@wordpress/blocks'; + +export default { + from: [ + { + type: 'block', + isMultiBlock: true, + blocks: [ '*' ], + isMatch( {}, blocks ) { + return ! ( + blocks.length === 1 && blocks[ 0 ].name === 'core/details' + ); + }, + __experimentalConvert( blocks ) { + return createBlock( + 'core/details', + {}, + blocks.map( ( block ) => cloneBlock( block ) ) + ); + }, + }, + ], +}; diff --git a/test/e2e/specs/editor/plugins/post-type-locking.spec.js b/test/e2e/specs/editor/plugins/post-type-locking.spec.js index dc56b6a9b3b421..af6256d05e02eb 100644 --- a/test/e2e/specs/editor/plugins/post-type-locking.spec.js +++ b/test/e2e/specs/editor/plugins/post-type-locking.spec.js @@ -363,6 +363,7 @@ test.describe( 'Post-type locking', () => { 'Buttons', 'Code', 'Columns', + 'Details', 'Group', 'Preformatted', 'Pullquote', diff --git a/test/e2e/specs/editor/various/block-switcher.spec.js b/test/e2e/specs/editor/various/block-switcher.spec.js index 88d58651a715a4..41b0b1ee49c88c 100644 --- a/test/e2e/specs/editor/various/block-switcher.spec.js +++ b/test/e2e/specs/editor/various/block-switcher.spec.js @@ -34,7 +34,14 @@ test.describe( 'Block Switcher', () => { await blockSwitcher.click(); await expect( page.getByRole( 'menu', { name: 'List' } ).getByRole( 'menuitem' ) - ).toHaveText( [ 'Paragraph', 'Heading', 'Quote', 'Columns', 'Group' ] ); + ).toHaveText( [ + 'Paragraph', + 'Heading', + 'Quote', + 'Columns', + 'Details', + 'Group', + ] ); } ); test( 'Should show the expected block transforms on the list block when the quote block is removed', async ( { @@ -74,7 +81,13 @@ test.describe( 'Block Switcher', () => { await blockSwitcher.click(); await expect( page.getByRole( 'menu', { name: 'List' } ).getByRole( 'menuitem' ) - ).toHaveText( [ 'Paragraph', 'Heading', 'Columns', 'Group' ] ); + ).toHaveText( [ + 'Paragraph', + 'Heading', + 'Columns', + 'Details', + 'Group', + ] ); } ); test( 'Should not show the block switcher if the block has no styles and cannot be removed', async ( { From a3d1c078cf88ff84a1d902cd86337dfa83c32642 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:51:24 +0200 Subject: [PATCH 0611/1908] Writing flow: fix triple click inside text blocks (#64928) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: eidolonnight <eidolonnight@git.wordpress.org> --- .../writing-flow/use-selection-observer.js | 9 +++++++++ packages/dom/README.md | 16 ++++++++++++++++ packages/dom/src/dom/index.js | 1 + 3 files changed, 26 insertions(+) diff --git a/packages/block-editor/src/components/writing-flow/use-selection-observer.js b/packages/block-editor/src/components/writing-flow/use-selection-observer.js index 824e01d07358b7..8ecba461d1025f 100644 --- a/packages/block-editor/src/components/writing-flow/use-selection-observer.js +++ b/packages/block-editor/src/components/writing-flow/use-selection-observer.js @@ -4,6 +4,7 @@ import { useSelect, useDispatch } from '@wordpress/data'; import { useRefEffect } from '@wordpress/compose'; import { create } from '@wordpress/rich-text'; +import { isSelectionForward } from '@wordpress/dom'; /** * Internal dependencies @@ -53,6 +54,14 @@ function extractSelectionEndNode( selection ) { return focusNode; } + // When the selection is forward (the selection ends with the focus node), + // the selection may extend into the next element with an offset of 0. This + // may trigger multi selection even though the selection does not visually + // end in the next block. + if ( focusOffset === 0 && isSelectionForward( selection ) ) { + return focusNode.previousSibling ?? focusNode.parentElement; + } + return focusNode.childNodes[ focusOffset ]; } diff --git a/packages/dom/README.md b/packages/dom/README.md index 5440ff2820ccc6..26740c74e8561e 100644 --- a/packages/dom/README.md +++ b/packages/dom/README.md @@ -239,6 +239,22 @@ _Returns_ - `boolean`: True if rtl, false if ltr. +### isSelectionForward + +Returns true if the given selection object is in the forward direction, or false otherwise. + +_Related_ + +- <https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition> + +_Parameters_ + +- _selection_ `Selection`: Selection object to check. + +_Returns_ + +- `boolean`: Whether the selection is forward. + ### isTextContent _Parameters_ diff --git a/packages/dom/src/dom/index.js b/packages/dom/src/dom/index.js index f21ec1e4e85e66..4522ac1fd1b89c 100644 --- a/packages/dom/src/dom/index.js +++ b/packages/dom/src/dom/index.js @@ -24,3 +24,4 @@ export { default as isEmpty } from './is-empty'; export { default as removeInvalidHTML } from './remove-invalid-html'; export { default as isRTL } from './is-rtl'; export { default as safeHTML } from './safe-html'; +export { default as isSelectionForward } from './is-selection-forward'; From 4782b4854a6393079b91ec0fccf8753654b48954 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Sat, 31 Aug 2024 00:39:43 +0900 Subject: [PATCH 0612/1908] InputControl: Tighten gap between input and prefix/suffix (#64908) * InputControl: Tighten padding between input and prefix/suffix * Add changelog * BorderControl: Add back padding * Add more components to changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/components/CHANGELOG.md | 9 +++++ .../border-control/component.tsx | 39 +++++++++++-------- .../components/src/input-control/index.tsx | 4 +- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 95fcc006b32a1b..80ba60c6604fe5 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -24,6 +24,15 @@ - `UnitControl`: Update unit select styles ([#64712](https://github.com/WordPress/gutenberg/pull/64712)). - `InputControl`: Add variants to prefix/suffix wrappers ([#64824](https://github.com/WordPress/gutenberg/pull/64824)). - `Navigator`: remove location history, simplify internal logic ([#64675](https://github.com/WordPress/gutenberg/pull/64675)). +- Tighten gap between the main control and the prefix/suffix slot for the following components ([#64908](https://github.com/WordPress/gutenberg/pull/64908)). + - `InputControl` + - `NumberControl` + - `SelectControl` + - `TreeSelect` + - `UnitControl` + - Contains internal visual changes from this PR: + - `AnglePickerControl` + - `ColorPicker` - Decrease horizontal padding from 16px to 12px on the following components, when in the 40px default size ([#64708](https://github.com/WordPress/gutenberg/pull/64708)). - `AnglePickerControl` - `ColorPicker` (on the inputs) diff --git a/packages/components/src/border-control/border-control/component.tsx b/packages/components/src/border-control/border-control/component.tsx index 5fe2abce1b4117..e2c96eaa9ffc0d 100644 --- a/packages/components/src/border-control/border-control/component.tsx +++ b/packages/components/src/border-control/border-control/component.tsx @@ -18,6 +18,7 @@ import { contextConnect } from '../../context'; import { useBorderControl } from './hook'; import type { BorderControlProps, LabelProps } from '../types'; +import { Spacer } from '../../spacer'; const BorderLabel = ( props: LabelProps ) => { const { label, hideLabelFromVision } = props; @@ -75,22 +76,28 @@ const UnconnectedBorderControl = ( <HStack spacing={ 4 } className={ innerWrapperClassName }> <UnitControl prefix={ - <BorderControlDropdown - border={ border } - colors={ colors } - __unstablePopoverProps={ __unstablePopoverProps } - disableCustomColors={ disableCustomColors } - enableAlpha={ enableAlpha } - enableStyle={ enableStyle } - isStyleSettable={ isStyleSettable } - onChange={ onBorderChange } - previousStyleSelection={ previousStyleSelection } - showDropdownHeader={ showDropdownHeader } - __experimentalIsRenderedInSidebar={ - __experimentalIsRenderedInSidebar - } - size={ size } - /> + <Spacer marginRight={ 1 } marginBottom={ 0 }> + <BorderControlDropdown + border={ border } + colors={ colors } + __unstablePopoverProps={ + __unstablePopoverProps + } + disableCustomColors={ disableCustomColors } + enableAlpha={ enableAlpha } + enableStyle={ enableStyle } + isStyleSettable={ isStyleSettable } + onChange={ onBorderChange } + previousStyleSelection={ + previousStyleSelection + } + showDropdownHeader={ showDropdownHeader } + __experimentalIsRenderedInSidebar={ + __experimentalIsRenderedInSidebar + } + size={ size } + /> + </Spacer> } label={ __( 'Border width' ) } hideLabelFromVision diff --git a/packages/components/src/input-control/index.tsx b/packages/components/src/input-control/index.tsx index a5a9e054bc37d8..fd0fc0a5c45536 100644 --- a/packages/components/src/input-control/index.tsx +++ b/packages/components/src/input-control/index.tsx @@ -100,8 +100,8 @@ export function UnforwardedInputControl( isPressEnterToChange={ isPressEnterToChange } onKeyDown={ onKeyDown } onValidate={ onValidate } - paddingInlineStart={ prefix ? space( 2 ) : undefined } - paddingInlineEnd={ suffix ? space( 2 ) : undefined } + paddingInlineStart={ prefix ? space( 1 ) : undefined } + paddingInlineEnd={ suffix ? space( 1 ) : undefined } ref={ ref } size={ size } stateReducer={ stateReducer } From 8a6903f81e47b5c3528ef9eea342913e60d32793 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Fri, 30 Aug 2024 19:23:45 +0200 Subject: [PATCH 0613/1908] Simplify useResizeObserver (#64820) Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> --- packages/compose/README.md | 2 +- .../src/hooks/use-resize-observer/index.tsx | 373 ++++-------------- 2 files changed, 86 insertions(+), 289 deletions(-) diff --git a/packages/compose/README.md b/packages/compose/README.md index f3109253e44c11..0da853ad75c5af 100644 --- a/packages/compose/README.md +++ b/packages/compose/README.md @@ -500,7 +500,7 @@ _Returns_ ### useResizeObserver -Hook which allows to listen the resize event of any target element when it changes sizes. \_Note: `useResizeObserver` will report `null` until after first render. +Hook which allows to listen to the resize event of any target element when it changes size. \_Note: `useResizeObserver` will report `null` sizes until after first render. _Usage_ diff --git a/packages/compose/src/hooks/use-resize-observer/index.tsx b/packages/compose/src/hooks/use-resize-observer/index.tsx index c8c964228edfc2..05461bb2468b07 100644 --- a/packages/compose/src/hooks/use-resize-observer/index.tsx +++ b/packages/compose/src/hooks/use-resize-observer/index.tsx @@ -1,116 +1,23 @@ /** * External dependencies */ -import type { ReactElement, RefCallback, RefObject } from 'react'; +import type { ReactElement } from 'react'; /** * WordPress dependencies */ import { - useMemo, - useRef, useCallback, - useEffect, + useLayoutEffect, + useRef, useState, } from '@wordpress/element'; -type SubscriberCleanup = () => void; -type SubscriberResponse = SubscriberCleanup | void; - -// This of course could've been more streamlined with internal state instead of -// refs, but then host hooks / components could not opt out of renders. -// This could've been exported to its own module, but the current build doesn't -// seem to work with module imports and I had no more time to spend on this... -function useResolvedElement< T extends HTMLElement >( - subscriber: ( element: T ) => SubscriberResponse, - refOrElement?: T | RefObject< T > | null -): RefCallback< T > { - const callbackElementRef = useRef< T | null >( null ); - const lastReportRef = useRef< { - reporter: () => void; - element: T | null; - } | null >( null ); - const cleanupRef = useRef< SubscriberResponse | null >(); - - const callSubscriber = useCallback( () => { - let element = null; - if ( callbackElementRef.current ) { - element = callbackElementRef.current; - } else if ( refOrElement ) { - if ( refOrElement instanceof HTMLElement ) { - element = refOrElement; - } else { - element = refOrElement.current; - } - } - - if ( - lastReportRef.current && - lastReportRef.current.element === element && - lastReportRef.current.reporter === callSubscriber - ) { - return; - } - - if ( cleanupRef.current ) { - cleanupRef.current(); - // Making sure the cleanup is not called accidentally multiple times. - cleanupRef.current = null; - } - lastReportRef.current = { - reporter: callSubscriber, - element, - }; - - // Only calling the subscriber, if there's an actual element to report. - if ( element ) { - cleanupRef.current = subscriber( element ); - } - }, [ refOrElement, subscriber ] ); - - // On each render, we check whether a ref changed, or if we got a new raw - // element. - useEffect( () => { - // With this we're *technically* supporting cases where ref objects' current value changes, but only if there's a - // render accompanying that change as well. - // To guarantee we always have the right element, one must use the ref callback provided instead, but we support - // RefObjects to make the hook API more convenient in certain cases. - callSubscriber(); - }, [ callSubscriber ] ); - - return useCallback< RefCallback< T > >( - ( element ) => { - callbackElementRef.current = element; - callSubscriber(); - }, - [ callSubscriber ] - ); -} - type ObservedSize = { - width: number | undefined; - height: number | undefined; + width: number | null; + height: number | null; }; -type ResizeHandler = ( size: ObservedSize ) => void; - -type HookResponse< T extends HTMLElement > = { - ref: RefCallback< T >; -} & ObservedSize; - -// Declaring my own type here instead of using the one provided by TS (available since 4.2.2), because this way I'm not -// forcing consumers to use a specific TS version. -type ResizeObserverBoxOptions = - | 'border-box' - | 'content-box' - | 'device-pixel-content-box'; - -declare global { - interface ResizeObserverEntry { - readonly devicePixelContentBoxSize: ReadonlyArray< ResizeObserverSize >; - } -} - // We're only using the first element of the size sequences, until future versions of the spec solidify on how // exactly it'll be used for fragments in multi-column scenarios: // From the spec: @@ -136,187 +43,88 @@ declare global { // even though it seems we have access to results for all box types. // This also means that we get to keep the current api, being able to return a simple { width, height } pair, // regardless of box option. -const extractSize = ( - entry: ResizeObserverEntry, - boxProp: 'borderBoxSize' | 'contentBoxSize' | 'devicePixelContentBoxSize', - sizeType: keyof ResizeObserverSize -): number | undefined => { - if ( ! entry[ boxProp ] ) { - if ( boxProp === 'contentBoxSize' ) { - // The dimensions in `contentBoxSize` and `contentRect` are equivalent according to the spec. - // See the 6th step in the description for the RO algorithm: - // https://drafts.csswg.org/resize-observer/#create-and-populate-resizeobserverentry-h - // > Set this.contentRect to logical this.contentBoxSize given target and observedBox of "content-box". - // In real browser implementations of course these objects differ, but the width/height values should be equivalent. - return entry.contentRect[ - sizeType === 'inlineSize' ? 'width' : 'height' - ]; - } - - return undefined; +const extractSize = ( entry: ResizeObserverEntry ): ObservedSize => { + let entrySize; + if ( ! entry.contentBoxSize ) { + // The dimensions in `contentBoxSize` and `contentRect` are equivalent according to the spec. + // See the 6th step in the description for the RO algorithm: + // https://drafts.csswg.org/resize-observer/#create-and-populate-resizeobserverentry-h + // > Set this.contentRect to logical this.contentBoxSize given target and observedBox of "content-box". + // In real browser implementations of course these objects differ, but the width/height values should be equivalent. + entrySize = [ entry.contentRect.width, entry.contentRect.height ]; + } else if ( entry.contentBoxSize[ 0 ] ) { + const contentBoxSize = entry.contentBoxSize[ 0 ]; + entrySize = [ contentBoxSize.inlineSize, contentBoxSize.blockSize ]; + } else { + // TS complains about this, because the RO entry type follows the spec and does not reflect Firefox's buggy + // behaviour of returning objects instead of arrays for `borderBoxSize` and `contentBoxSize`. + const contentBoxSize = + entry.contentBoxSize as unknown as ResizeObserverSize; + entrySize = [ contentBoxSize.inlineSize, contentBoxSize.blockSize ]; } - // A couple bytes smaller than calling Array.isArray() and just as effective here. - return entry[ boxProp ][ 0 ] - ? entry[ boxProp ][ 0 ][ sizeType ] - : // TS complains about this, because the RO entry type follows the spec and does not reflect Firefox's current - // behaviour of returning objects instead of arrays for `borderBoxSize` and `contentBoxSize`. - // @ts-ignore - entry[ boxProp ][ sizeType ]; + const [ width, height ] = entrySize.map( ( d ) => Math.round( d ) ); + return { width, height }; +}; + +const RESIZE_ELEMENT_STYLES = { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + pointerEvents: 'none', + opacity: 0, + overflow: 'hidden', + zIndex: -1, +} as const; + +type ResizeElementProps = { + onResize: ( s: ObservedSize ) => void; }; -type RoundingFunction = ( n: number ) => number; +function ResizeElement( { onResize }: ResizeElementProps ) { + const resizeElementRef = useRef< HTMLDivElement >( null ); + const resizeCallbackRef = useRef( onResize ); -function useResizeObserver< T extends HTMLElement >( - opts: { - ref?: RefObject< T > | T | null | undefined; - onResize?: ResizeHandler; - box?: ResizeObserverBoxOptions; - round?: RoundingFunction; - } = {} -): HookResponse< T > { - // Saving the callback as a ref. With this, I don't need to put onResize in the - // effect dep array, and just passing in an anonymous function without memoising - // will not reinstantiate the hook's ResizeObserver. - const onResize = opts.onResize; - const onResizeRef = useRef< ResizeHandler | undefined >( undefined ); - onResizeRef.current = onResize; - const round = opts.round || Math.round; + useLayoutEffect( () => { + resizeCallbackRef.current = onResize; + }, [ onResize ] ); - // Using a single instance throughout the hook's lifetime - const resizeObserverRef = useRef< { - box?: ResizeObserverBoxOptions; - round?: RoundingFunction; - instance: ResizeObserver; - } >(); + useLayoutEffect( () => { + const resizeElement = resizeElementRef.current as HTMLDivElement; + const resizeObserver = new ResizeObserver( ( entries ) => { + for ( const entry of entries ) { + const newSize = extractSize( entry ); + resizeCallbackRef.current( newSize ); + } + } ); - const [ size, setSize ] = useState< { - width?: number; - height?: number; - } >( { - width: undefined, - height: undefined, - } ); + resizeObserver.observe( resizeElement ); - // In certain edge cases the RO might want to report a size change just after - // the component unmounted. - const didUnmountRef = useRef( false ); - useEffect( () => { - didUnmountRef.current = false; return () => { - didUnmountRef.current = true; + resizeObserver.unobserve( resizeElement ); }; }, [] ); - // Using a ref to track the previous width / height to avoid unnecessary renders. - const previousRef: { - current: { - width?: number; - height?: number; - }; - } = useRef( { - width: undefined, - height: undefined, - } ); - - // This block is kinda like a useEffect, only it's called whenever a new - // element could be resolved based on the ref option. It also has a cleanup - // function. - const refCallback = useResolvedElement< T >( - useCallback( - ( element ) => { - // We only use a single Resize Observer instance, and we're instantiating it on demand, only once there's something to observe. - // This instance is also recreated when the `box` option changes, so that a new observation is fired if there was a previously observed element with a different box option. - if ( - ! resizeObserverRef.current || - resizeObserverRef.current.box !== opts.box || - resizeObserverRef.current.round !== round - ) { - resizeObserverRef.current = { - box: opts.box, - round, - instance: new ResizeObserver( ( entries ) => { - const entry = entries[ 0 ]; - - let boxProp: - | 'borderBoxSize' - | 'contentBoxSize' - | 'devicePixelContentBoxSize' = 'borderBoxSize'; - if ( opts.box === 'border-box' ) { - boxProp = 'borderBoxSize'; - } else { - boxProp = - opts.box === 'device-pixel-content-box' - ? 'devicePixelContentBoxSize' - : 'contentBoxSize'; - } - - const reportedWidth = extractSize( - entry, - boxProp, - 'inlineSize' - ); - const reportedHeight = extractSize( - entry, - boxProp, - 'blockSize' - ); - - const newWidth = reportedWidth - ? round( reportedWidth ) - : undefined; - const newHeight = reportedHeight - ? round( reportedHeight ) - : undefined; - - if ( - previousRef.current.width !== newWidth || - previousRef.current.height !== newHeight - ) { - const newSize = { - width: newWidth, - height: newHeight, - }; - previousRef.current.width = newWidth; - previousRef.current.height = newHeight; - if ( onResizeRef.current ) { - onResizeRef.current( newSize ); - } else if ( ! didUnmountRef.current ) { - setSize( newSize ); - } - } - } ), - }; - } - - resizeObserverRef.current.instance.observe( element, { - box: opts.box, - } ); - - return () => { - if ( resizeObserverRef.current ) { - resizeObserverRef.current.instance.unobserve( element ); - } - }; - }, - [ opts.box, round ] - ), - opts.ref + return ( + <div + ref={ resizeElementRef } + style={ RESIZE_ELEMENT_STYLES } + aria-hidden="true" + /> ); +} - return useMemo( - () => ( { - ref: refCallback, - width: size.width, - height: size.height, - } ), - [ refCallback, size ? size.width : null, size ? size.height : null ] - ); +function sizeEquals( a: ObservedSize, b: ObservedSize ) { + return a.width === b.width && a.height === b.height; } +const NULL_SIZE: ObservedSize = { width: null, height: null }; + /** - * Hook which allows to listen the resize event of any target element when it changes sizes. - * _Note: `useResizeObserver` will report `null` until after first render. + * Hook which allows to listen to the resize event of any target element when it changes size. + * _Note: `useResizeObserver` will report `null` sizes until after first render. * * @example * @@ -333,30 +141,19 @@ function useResizeObserver< T extends HTMLElement >( * }; * ``` */ -export default function useResizeAware(): [ - ReactElement, - { width: number | null; height: number | null }, -] { - const { ref, width, height } = useResizeObserver(); - const sizes = useMemo( () => { - return { width: width ?? null, height: height ?? null }; - }, [ width, height ] ); - const resizeListener = ( - <div - style={ { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, - pointerEvents: 'none', - opacity: 0, - overflow: 'hidden', - zIndex: -1, - } } - aria-hidden="true" - ref={ ref } - /> - ); - return [ resizeListener, sizes ]; +export default function useResizeObserver(): [ ReactElement, ObservedSize ] { + const [ size, setSize ] = useState( NULL_SIZE ); + + // Using a ref to track the previous width / height to avoid unnecessary renders. + const previousSizeRef = useRef( NULL_SIZE ); + + const handleResize = useCallback( ( newSize: ObservedSize ) => { + if ( ! sizeEquals( previousSizeRef.current, newSize ) ) { + previousSizeRef.current = newSize; + setSize( newSize ); + } + }, [] ); + + const resizeElement = <ResizeElement onResize={ handleResize } />; + return [ resizeElement, size ]; } From 05b8d271a63c2747219a4ed01fe0ac45cedc25c9 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Fri, 30 Aug 2024 20:09:19 +0200 Subject: [PATCH 0614/1908] Inserter: use lighter grammar parse to check allowed status (#64902) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- package-lock.json | 2 + packages/block-editor/package.json | 1 + .../src/store/private-selectors.js | 8 +-- packages/block-editor/src/store/selectors.js | 23 ++++++-- packages/block-editor/src/store/utils.js | 20 +++++-- packages/block-editor/tsconfig.json | 1 + .../editor/various/parsing-patterns.spec.js | 57 +++++++++++++++++++ 7 files changed, 98 insertions(+), 14 deletions(-) create mode 100644 test/e2e/specs/editor/various/parsing-patterns.spec.js diff --git a/package-lock.json b/package-lock.json index 48c0805aef9ed8..9083d7ee16cbbd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52208,6 +52208,7 @@ "@wordpress/a11y": "file:../a11y", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", + "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", "@wordpress/blocks": "file:../blocks", "@wordpress/commands": "file:../commands", "@wordpress/components": "file:../components", @@ -67214,6 +67215,7 @@ "@wordpress/a11y": "file:../a11y", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", + "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", "@wordpress/blocks": "file:../blocks", "@wordpress/commands": "file:../commands", "@wordpress/components": "file:../components", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 640a5fc319330a..1f4fa7588ec6c9 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -39,6 +39,7 @@ "@wordpress/a11y": "file:../a11y", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", + "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", "@wordpress/blocks": "file:../blocks", "@wordpress/commands": "file:../commands", "@wordpress/components": "file:../components", diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 9d3c5f27a7cc98..9cc793362296c4 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -20,7 +20,7 @@ import { checkAllowListRecursive, getAllPatternsDependants, getInsertBlockTypeDependants, - getParsedPattern, + getGrammar, } from './utils'; import { INSERTER_PATTERN_TYPES } from '../components/inserter/block-patterns-tab/utils'; import { STORE_NAME } from './constants'; @@ -300,10 +300,10 @@ export const hasAllowedPatterns = createRegistrySelector( ( select ) => if ( ! inserter ) { return false; } - const { blocks } = getParsedPattern( pattern ); + const grammar = getGrammar( pattern ); return ( - checkAllowListRecursive( blocks, allowedBlockTypes ) && - blocks.every( ( { name: blockName } ) => + checkAllowListRecursive( grammar, allowedBlockTypes ) && + grammar.every( ( { name: blockName } ) => canInsertBlockType( state, blockName, rootClientId ) ) ); diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 8d4d94bdaa98f7..b30a719d21fd4d 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -27,6 +27,7 @@ import { getAllPatternsDependants, getInsertBlockTypeDependants, getParsedPattern, + getGrammar, } from './utils'; import { orderBy } from '../utils/sorting'; import { STORE_NAME } from './constants'; @@ -2376,17 +2377,27 @@ export const __experimentalGetAllowedPatterns = createRegistrySelector( const { getAllPatterns } = unlock( select( STORE_NAME ) ); const patterns = getAllPatterns(); const { allowedBlockTypes } = getSettings( state ); - const parsedPatterns = patterns .filter( ( { inserter = true } ) => !! inserter ) - .map( getParsedPattern ); + .map( ( pattern ) => { + return { + ...pattern, + get blocks() { + return getParsedPattern( pattern ).blocks; + }, + }; + } ); + const availableParsedPatterns = parsedPatterns.filter( - ( { blocks } ) => - checkAllowListRecursive( blocks, allowedBlockTypes ) + ( pattern ) => + checkAllowListRecursive( + getGrammar( pattern ), + allowedBlockTypes + ) ); const patternsAllowed = availableParsedPatterns.filter( - ( { blocks } ) => - blocks.every( ( { name } ) => + ( pattern ) => + getGrammar( pattern ).every( ( { blockName: name } ) => canInsertBlockType( state, name, rootClientId ) ) ); diff --git a/packages/block-editor/src/store/utils.js b/packages/block-editor/src/store/utils.js index 71c5ac44f45b83..b630912a5163d6 100644 --- a/packages/block-editor/src/store/utils.js +++ b/packages/block-editor/src/store/utils.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { parse } from '@wordpress/blocks'; +import { parse as grammarParse } from '@wordpress/block-serialization-default-parser'; /** * Internal dependencies @@ -13,6 +14,7 @@ import { STORE_NAME } from './constants'; export const withRootClientIdOptionKey = Symbol( 'withRootClientId' ); const parsedPatternCache = new WeakMap(); +const grammarMapCache = new WeakMap(); function parsePattern( pattern ) { const blocks = parse( pattern.content, { @@ -37,14 +39,24 @@ function parsePattern( pattern ) { export function getParsedPattern( pattern ) { let parsedPattern = parsedPatternCache.get( pattern ); - if ( parsedPattern ) { - return parsedPattern; + if ( ! parsedPattern ) { + parsedPattern = parsePattern( pattern ); + parsedPatternCache.set( pattern, parsedPattern ); } - parsedPattern = parsePattern( pattern ); - parsedPatternCache.set( pattern, parsedPattern ); return parsedPattern; } +export function getGrammar( pattern ) { + let grammarMap = grammarMapCache.get( pattern ); + if ( ! grammarMap ) { + grammarMap = grammarParse( pattern.content ); + // Block names are null only at the top level for whitespace. + grammarMap = grammarMap.filter( ( block ) => block.blockName !== null ); + grammarMapCache.set( pattern, grammarMap ); + } + return grammarMap; +} + export const checkAllowList = ( list, item, defaultResult = null ) => { if ( typeof list === 'boolean' ) { return list; diff --git a/packages/block-editor/tsconfig.json b/packages/block-editor/tsconfig.json index 192b6f7de7e127..37fb61895d252e 100644 --- a/packages/block-editor/tsconfig.json +++ b/packages/block-editor/tsconfig.json @@ -8,6 +8,7 @@ "references": [ { "path": "../a11y" }, { "path": "../api-fetch" }, + { "path": "../block-serialization-default-parser" }, { "path": "../blob" }, { "path": "../components" }, { "path": "../compose" }, diff --git a/test/e2e/specs/editor/various/parsing-patterns.spec.js b/test/e2e/specs/editor/various/parsing-patterns.spec.js new file mode 100644 index 00000000000000..d8abe7a46fbc1b --- /dev/null +++ b/test/e2e/specs/editor/various/parsing-patterns.spec.js @@ -0,0 +1,57 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.describe( 'Parsing patterns', () => { + test( 'Considers a pattern with whitespace an allowed pattern', async ( { + admin, + editor, + page, + } ) => { + await admin.createNewPost(); + await editor.insertBlock( { + name: 'core/buttons', + innerBlocks: [ { name: 'core/button', attributes: { text: 'a' } } ], + } ); + await page.keyboard.press( 'ArrowDown' ); + await page.getByLabel( 'Toggle block inserter' ).click(); + + await page.getByRole( 'tab', { name: 'Patterns' } ).click(); + await page.evaluate( () => { + window.wp.data.dispatch( 'core/block-editor' ).updateSettings( { + __experimentalBlockPatterns: [ + { + name: 'test/whitespace', + title: 'Pattern with top-level whitespace', + description: '', + content: `<!-- wp:button --> +<div class="wp-block-button"><a class="wp-block-button__link wp-element-button">test</a></div> +<!-- /wp:button --> + +<!-- wp:button --> +<div class="wp-block-button"><a class="wp-block-button__link wp-element-button">test</a></div> +<!-- /wp:button -->`, + }, + ], + } ); + } ); + await page.fill( + 'role=region[name="Block Library"i] >> role=searchbox[name="Search for blocks and patterns"i]', + 'whitespace' + ); + await page + .locator( 'role=option[name="Pattern with top-level whitespace"i]' ) + .click(); + expect( await editor.getBlocks() ).toMatchObject( [ + { + name: 'core/buttons', + innerBlocks: [ + { name: 'core/button', attributes: { text: 'a' } }, + { name: 'core/button', attributes: { text: 'test' } }, + { name: 'core/button', attributes: { text: 'test' } }, + ], + }, + ] ); + } ); +} ); From 4c5feda412b6eb0631c1feb90297493429dc1d4f Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Fri, 30 Aug 2024 21:01:49 +0200 Subject: [PATCH 0615/1908] Rich text: add comment on placeholder approach (#64945) --- packages/rich-text/src/to-tree.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/rich-text/src/to-tree.js b/packages/rich-text/src/to-tree.js index 131174460a74bc..46671c951bc09d 100644 --- a/packages/rich-text/src/to-tree.js +++ b/packages/rich-text/src/to-tree.js @@ -299,6 +299,8 @@ export function toTree( { if ( shouldInsertPadding && i === text.length ) { append( getParent( pointer ), ZWNBSP ); + // We CANNOT use CSS to add a placeholder with pseudo elements on + // the main block wrappers because that could clash with theme CSS. if ( placeholder && text.length === 0 ) { append( getParent( pointer ), { type: 'span', From 5a87fb03b2f7cdcd56cee8d925349bf4c443a714 Mon Sep 17 00:00:00 2001 From: Marcelo Serpa <81248+fullofcaffeine@users.noreply.github.com> Date: Fri, 30 Aug 2024 13:58:07 -0600 Subject: [PATCH 0616/1908] AlignmentMatrixControl: Promote to stable (#60913) * Remove "experimental" designation for `AlignmentMatrixControl` * Add CHANGELOG entry * Tweak exports * Replace in app * Add changelog * Fix changelog --------- Co-authored-by: fullofcaffeine <fullofcaffeine@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../block-alignment-matrix-control/index.js | 2 +- packages/components/CHANGELOG.md | 2 + .../src/alignment-matrix-control/README.md | 6 +- .../src/alignment-matrix-control/index.tsx | 61 ++++++++++++------- .../stories/index.story.tsx | 2 +- packages/components/src/index.ts | 6 +- storybook/manager-head.html | 5 +- 7 files changed, 51 insertions(+), 33 deletions(-) diff --git a/packages/block-editor/src/components/block-alignment-matrix-control/index.js b/packages/block-editor/src/components/block-alignment-matrix-control/index.js index 53baa97421e6c1..cdec41dfc7b978 100644 --- a/packages/block-editor/src/components/block-alignment-matrix-control/index.js +++ b/packages/block-editor/src/components/block-alignment-matrix-control/index.js @@ -6,7 +6,7 @@ import { DOWN } from '@wordpress/keycodes'; import { ToolbarButton, Dropdown, - __experimentalAlignmentMatrixControl as AlignmentMatrixControl, + AlignmentMatrixControl, } from '@wordpress/components'; const noop = () => {}; diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 80ba60c6604fe5..00204111a1efd6 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,7 @@ - Deprecate `replace` from the options accepted by `useNavigator().goTo()` ([#64675](https://github.com/WordPress/gutenberg/pull/64675)). - Soft deprecate `size` prop on `AlignmentMatrixControl.Icon` ([#64827](https://github.com/WordPress/gutenberg/pull/64827)). +- `__experimentalAlignmentMatrixControl` can now be imported as a stable `AlignmentMatrixControl` ([#60913](https://github.com/WordPress/gutenberg/pull/60913)). ### Enhancements @@ -24,6 +25,7 @@ - `UnitControl`: Update unit select styles ([#64712](https://github.com/WordPress/gutenberg/pull/64712)). - `InputControl`: Add variants to prefix/suffix wrappers ([#64824](https://github.com/WordPress/gutenberg/pull/64824)). - `Navigator`: remove location history, simplify internal logic ([#64675](https://github.com/WordPress/gutenberg/pull/64675)). +- `AlignmentMatrixControl`: Promote to stable ([#60913](https://github.com/WordPress/gutenberg/pull/60913)). - Tighten gap between the main control and the prefix/suffix slot for the following components ([#64908](https://github.com/WordPress/gutenberg/pull/64908)). - `InputControl` - `NumberControl` diff --git a/packages/components/src/alignment-matrix-control/README.md b/packages/components/src/alignment-matrix-control/README.md index d087a177d8d414..68ecab6b7adb47 100644 --- a/packages/components/src/alignment-matrix-control/README.md +++ b/packages/components/src/alignment-matrix-control/README.md @@ -1,16 +1,12 @@ # AlignmentMatrixControl -<div class="callout callout-alert"> -This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. -</div> - AlignmentMatrixControl components enable adjustments to horizontal and vertical alignments for UI. ## Usage ```jsx import { useState } from 'react'; -import { __experimentalAlignmentMatrixControl as AlignmentMatrixControl } from '@wordpress/components'; +import { AlignmentMatrixControl } from '@wordpress/components'; const Example = () => { const [ alignment, setAlignment ] = useState( 'center center' ); diff --git a/packages/components/src/alignment-matrix-control/index.tsx b/packages/components/src/alignment-matrix-control/index.tsx index a865cd4f57a98b..fcf8c2fd470156 100644 --- a/packages/components/src/alignment-matrix-control/index.tsx +++ b/packages/components/src/alignment-matrix-control/index.tsx @@ -21,27 +21,7 @@ import { GRID, getItemId, getItemValue } from './utils'; import type { WordPressComponentProps } from '../context'; import type { AlignmentMatrixControlProps } from './types'; -/** - * - * AlignmentMatrixControl components enable adjustments to horizontal and vertical alignments for UI. - * - * ```jsx - * import { __experimentalAlignmentMatrixControl as AlignmentMatrixControl } from '@wordpress/components'; - * import { useState } from '@wordpress/element'; - * - * const Example = () => { - * const [ alignment, setAlignment ] = useState( 'center center' ); - * - * return ( - * <AlignmentMatrixControl - * value={ alignment } - * onChange={ setAlignment } - * /> - * ); - * }; - * ``` - */ -export function AlignmentMatrixControl( { +function UnforwardedAlignmentMatrixControl( { className, id, label = __( 'Alignment Matrix Control' ), @@ -52,7 +32,7 @@ export function AlignmentMatrixControl( { ...props }: WordPressComponentProps< AlignmentMatrixControlProps, 'div', false > ) { const baseId = useInstanceId( - AlignmentMatrixControl, + UnforwardedAlignmentMatrixControl, 'alignment-matrix-control', id ); @@ -100,6 +80,41 @@ export function AlignmentMatrixControl( { ); } -AlignmentMatrixControl.Icon = AlignmentMatrixControlIcon; +/** + * AlignmentMatrixControl components enable adjustments to horizontal and vertical alignments for UI. + * + * ```jsx + * import { AlignmentMatrixControl } from '@wordpress/components'; + * import { useState } from '@wordpress/element'; + * + * const Example = () => { + * const [ alignment, setAlignment ] = useState( 'center center' ); + * + * return ( + * <AlignmentMatrixControl + * value={ alignment } + * onChange={ setAlignment } + * /> + * ); + * }; + * ``` + */ +export const AlignmentMatrixControl = Object.assign( + UnforwardedAlignmentMatrixControl, + { + /** + * Render an alignment matrix as an icon. + * + * ```jsx + * import { AlignmentMatrixControl } from '@wordpress/components'; + * + * <Icon icon={<AlignmentMatrixControl.Icon value="top left" />} /> + * ``` + */ + Icon: Object.assign( AlignmentMatrixControlIcon, { + displayName: 'AlignmentMatrixControl.Icon', + } ), + } +); export default AlignmentMatrixControl; diff --git a/packages/components/src/alignment-matrix-control/stories/index.story.tsx b/packages/components/src/alignment-matrix-control/stories/index.story.tsx index 11de17153492d8..433d7540197da2 100644 --- a/packages/components/src/alignment-matrix-control/stories/index.story.tsx +++ b/packages/components/src/alignment-matrix-control/stories/index.story.tsx @@ -17,7 +17,7 @@ import { HStack } from '../../h-stack'; import type { AlignmentMatrixControlProps } from '../types'; const meta: Meta< typeof AlignmentMatrixControl > = { - title: 'Components (Experimental)/AlignmentMatrixControl', + title: 'Components/AlignmentMatrixControl', component: AlignmentMatrixControl, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index 6483e34dc222a8..3ddfbd05cd6581 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -12,7 +12,11 @@ export { } from '@wordpress/primitives'; // Components. -export { default as __experimentalAlignmentMatrixControl } from './alignment-matrix-control'; +export { + /** @deprecated Import `AlignmentMatrixControl` instead. */ + default as __experimentalAlignmentMatrixControl, + default as AlignmentMatrixControl, +} from './alignment-matrix-control'; export { default as Animate, getAnimateClassName as __unstableGetAnimateClassName, diff --git a/storybook/manager-head.html b/storybook/manager-head.html index ab9c1a71010718..174433776e27c9 100644 --- a/storybook/manager-head.html +++ b/storybook/manager-head.html @@ -1,10 +1,11 @@ <script> ( function redirectIfStoryMoved() { const PREVIOUSLY_EXPERIMENTAL_COMPONENTS = [ - 'navigation', + 'alignmentmatrixcontrol', 'customselectcontrol-v2', - 'theme', + 'navigation', 'progressbar', + 'theme', ]; const REDIRECTS = [ { From 58e4926e0b0c1551a97704ea672b1478bb0a1a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= <grzegorz@gziolo.pl> Date: Sat, 31 Aug 2024 08:31:08 +0200 Subject: [PATCH 0617/1908] Create Block: Set minimum supported WordPress version to 6.6 (#64920) * Create Block: Set minimum supported WordPress version to 6.6 * Update changelog entries Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/create-block-interactive-template/CHANGELOG.md | 4 ++++ .../plugin-templates/$slug.php.mustache | 2 +- .../plugin-templates/readme.txt.mustache | 2 +- packages/create-block-tutorial-template/CHANGELOG.md | 4 ++++ .../plugin-templates/$slug.php.mustache | 2 +- .../plugin-templates/readme.txt.mustache | 2 +- packages/create-block/CHANGELOG.md | 4 ++++ packages/create-block/lib/init-wp-scripts.js | 2 +- packages/create-block/lib/templates/es5/$slug.php.mustache | 2 +- packages/create-block/lib/templates/es5/readme.txt.mustache | 2 +- packages/create-block/lib/templates/plugin/$slug.php.mustache | 2 +- .../create-block/lib/templates/plugin/readme.txt.mustache | 2 +- 12 files changed, 21 insertions(+), 9 deletions(-) diff --git a/packages/create-block-interactive-template/CHANGELOG.md b/packages/create-block-interactive-template/CHANGELOG.md index 9b061370752df3..52f97a68cbf87a 100644 --- a/packages/create-block-interactive-template/CHANGELOG.md +++ b/packages/create-block-interactive-template/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Set the minimum supported WordPress version to 6.6 to make it work seamlessly with the latest version of `@wordpress/scripts` package ([#64920](https://github.com/WordPress/gutenberg/pull/64920)). + ## 2.6.0 (2024-08-21) ## 2.5.0 (2024-08-07) diff --git a/packages/create-block-interactive-template/plugin-templates/$slug.php.mustache b/packages/create-block-interactive-template/plugin-templates/$slug.php.mustache index 83890732cc41bc..56f660ce2b1257 100644 --- a/packages/create-block-interactive-template/plugin-templates/$slug.php.mustache +++ b/packages/create-block-interactive-template/plugin-templates/$slug.php.mustache @@ -8,7 +8,7 @@ * Description: {{description}} {{/description}} * Version: {{version}} - * Requires at least: 6.1 + * Requires at least: 6.6 * Requires PHP: 7.0 {{#author}} * Author: {{author}} diff --git a/packages/create-block-interactive-template/plugin-templates/readme.txt.mustache b/packages/create-block-interactive-template/plugin-templates/readme.txt.mustache index f069906fb19fa5..c3abf5ae4ec024 100644 --- a/packages/create-block-interactive-template/plugin-templates/readme.txt.mustache +++ b/packages/create-block-interactive-template/plugin-templates/readme.txt.mustache @@ -3,7 +3,7 @@ Contributors: {{author}} {{/author}} Tags: block -Tested up to: 6.1 +Tested up to: 6.6 Stable tag: {{version}} {{#license}} License: {{license}} diff --git a/packages/create-block-tutorial-template/CHANGELOG.md b/packages/create-block-tutorial-template/CHANGELOG.md index ddcf23926e52a0..50290a8e07e90e 100644 --- a/packages/create-block-tutorial-template/CHANGELOG.md +++ b/packages/create-block-tutorial-template/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Set the minimum supported WordPress version to 6.6 to make it work seamlessly with the latest version of `@wordpress/scripts` package ([#64920](https://github.com/WordPress/gutenberg/pull/64920)). + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/create-block-tutorial-template/plugin-templates/$slug.php.mustache b/packages/create-block-tutorial-template/plugin-templates/$slug.php.mustache index 6de24df94c8d83..bcc7f7537d95a8 100644 --- a/packages/create-block-tutorial-template/plugin-templates/$slug.php.mustache +++ b/packages/create-block-tutorial-template/plugin-templates/$slug.php.mustache @@ -8,7 +8,7 @@ * Description: {{description}} {{/description}} * Version: {{version}} - * Requires at least: 6.2 + * Requires at least: 6.6 * Requires PHP: 7.0 {{#author}} * Author: {{author}} diff --git a/packages/create-block-tutorial-template/plugin-templates/readme.txt.mustache b/packages/create-block-tutorial-template/plugin-templates/readme.txt.mustache index d2b31bed6c0e60..c3abf5ae4ec024 100644 --- a/packages/create-block-tutorial-template/plugin-templates/readme.txt.mustache +++ b/packages/create-block-tutorial-template/plugin-templates/readme.txt.mustache @@ -3,7 +3,7 @@ Contributors: {{author}} {{/author}} Tags: block -Tested up to: 6.4 +Tested up to: 6.6 Stable tag: {{version}} {{#license}} License: {{license}} diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index b0dae14eb13c87..3f742b352614e0 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Unpin the `@wordpress/scripts` version and set the minimum supported WordPress version to 6.6 ([#64920](https://github.com/WordPress/gutenberg/pull/64920)). + ## 4.49.0 (2024-08-21) ## 4.48.0 (2024-08-07) diff --git a/packages/create-block/lib/init-wp-scripts.js b/packages/create-block/lib/init-wp-scripts.js index 531eb970d89255..ca0101957f47f1 100644 --- a/packages/create-block/lib/init-wp-scripts.js +++ b/packages/create-block/lib/init-wp-scripts.js @@ -16,7 +16,7 @@ module.exports = async ( { slug } ) => { info( 'Installing `@wordpress/scripts` package. It might take a couple of minutes...' ); - await command( 'npm install @wordpress/scripts@27 --save-dev', { + await command( 'npm install @wordpress/scripts --save-dev', { cwd, } ); diff --git a/packages/create-block/lib/templates/es5/$slug.php.mustache b/packages/create-block/lib/templates/es5/$slug.php.mustache index 0f64471e434a7f..a67c3ad55d3fec 100644 --- a/packages/create-block/lib/templates/es5/$slug.php.mustache +++ b/packages/create-block/lib/templates/es5/$slug.php.mustache @@ -7,7 +7,7 @@ {{#description}} * Description: {{description}} {{/description}} - * Requires at least: 6.1 + * Requires at least: 6.6 * Requires PHP: 7.0 * Version: {{version}} {{#author}} diff --git a/packages/create-block/lib/templates/es5/readme.txt.mustache b/packages/create-block/lib/templates/es5/readme.txt.mustache index f069906fb19fa5..c3abf5ae4ec024 100644 --- a/packages/create-block/lib/templates/es5/readme.txt.mustache +++ b/packages/create-block/lib/templates/es5/readme.txt.mustache @@ -3,7 +3,7 @@ Contributors: {{author}} {{/author}} Tags: block -Tested up to: 6.1 +Tested up to: 6.6 Stable tag: {{version}} {{#license}} License: {{license}} diff --git a/packages/create-block/lib/templates/plugin/$slug.php.mustache b/packages/create-block/lib/templates/plugin/$slug.php.mustache index 45487ef61006f7..4524477ba73df2 100644 --- a/packages/create-block/lib/templates/plugin/$slug.php.mustache +++ b/packages/create-block/lib/templates/plugin/$slug.php.mustache @@ -7,7 +7,7 @@ {{#description}} * Description: {{description}} {{/description}} - * Requires at least: 6.1 + * Requires at least: 6.6 * Requires PHP: 7.0 * Version: {{version}} {{#author}} diff --git a/packages/create-block/lib/templates/plugin/readme.txt.mustache b/packages/create-block/lib/templates/plugin/readme.txt.mustache index f069906fb19fa5..c3abf5ae4ec024 100644 --- a/packages/create-block/lib/templates/plugin/readme.txt.mustache +++ b/packages/create-block/lib/templates/plugin/readme.txt.mustache @@ -3,7 +3,7 @@ Contributors: {{author}} {{/author}} Tags: block -Tested up to: 6.1 +Tested up to: 6.6 Stable tag: {{version}} {{#license}} License: {{license}} From 5a153200a3221c424951b06f3addb7c0ac18cb22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Chantre?= <mail@benoitchantre.com> Date: Sat, 31 Aug 2024 09:06:56 +0200 Subject: [PATCH 0618/1908] Scripts: Import CSS files before optimization (#61121) * Import CSS files before optimization Closes #61112. * Update changelog Co-authored-by: benoitchantre <benoitchantre@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- package-lock.json | 63 +++++++++++++++++++++++ package.json | 1 + packages/scripts/CHANGELOG.md | 4 ++ packages/scripts/config/webpack.config.js | 1 + packages/scripts/package.json | 1 + 5 files changed, 70 insertions(+) diff --git a/package-lock.json b/package-lock.json index 9083d7ee16cbbd..a5841a06e163ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -216,6 +216,7 @@ "npm-run-all": "4.1.5", "patch-package": "8.0.0", "postcss": "8.4.38", + "postcss-import": "16.1.0", "postcss-loader": "6.2.1", "postcss-local-keyframes": "^0.0.2", "prettier": "npm:wp-prettier@3.0.3", @@ -41328,6 +41329,29 @@ "postcss": "^8.2.15" } }, + "node_modules/postcss-import": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz", + "integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-import/node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, "node_modules/postcss-loader": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", @@ -43410,6 +43434,15 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, "node_modules/read-cmd-shim": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz", @@ -54555,6 +54588,7 @@ "npm-package-json-lint": "^6.4.0", "npm-packlist": "^3.0.0", "postcss": "^8.4.5", + "postcss-import": "^16.1.0", "postcss-loader": "^6.2.1", "prettier": "npm:wp-prettier@3.0.3", "puppeteer-core": "^13.2.0", @@ -68733,6 +68767,7 @@ "npm-package-json-lint": "^6.4.0", "npm-packlist": "^3.0.0", "postcss": "^8.4.5", + "postcss-import": "^16.1.0", "postcss-loader": "^6.2.1", "prettier": "npm:wp-prettier@3.0.3", "puppeteer-core": "^13.2.0", @@ -87490,6 +87525,25 @@ "integrity": "sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw==", "dev": true }, + "postcss-import": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz", + "integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "dependencies": { + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + } + } + }, "postcss-loader": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", @@ -89042,6 +89096,15 @@ } } }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "requires": { + "pify": "^2.3.0" + } + }, "read-cmd-shim": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz", diff --git a/package.json b/package.json index 0e495308e44e1e..c0a7853a418178 100644 --- a/package.json +++ b/package.json @@ -228,6 +228,7 @@ "npm-run-all": "4.1.5", "patch-package": "8.0.0", "postcss": "8.4.38", + "postcss-import": "16.1.0", "postcss-loader": "6.2.1", "postcss-local-keyframes": "^0.0.2", "prettier": "npm:wp-prettier@3.0.3", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 9d39bf21f1ba0f..cd796ba46dbfa1 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Inlines CSS files imported from other CSS files before optimization in the `build` command ([#61121](https://github.com/WordPress/gutenberg/pull/61121)). + ### Bug Fixes - Added chunk filename in webpack config to avoid reading stale files ([#58176](https://github.com/WordPress/gutenberg/pull/58176)). diff --git a/packages/scripts/config/webpack.config.js b/packages/scripts/config/webpack.config.js index d8f9d356dda891..4c60e3859207de 100644 --- a/packages/scripts/config/webpack.config.js +++ b/packages/scripts/config/webpack.config.js @@ -119,6 +119,7 @@ const cssLoaders = [ plugins: isProduction ? [ ...postcssPlugins, + require( 'postcss-import' ), require( 'cssnano' )( { // Provide a fallback configuration if there's not // one explicitly available in the project. diff --git a/packages/scripts/package.json b/packages/scripts/package.json index dcc17a2926a654..c4582ba65d15e9 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -73,6 +73,7 @@ "npm-package-json-lint": "^6.4.0", "npm-packlist": "^3.0.0", "postcss": "^8.4.5", + "postcss-import": "^16.1.0", "postcss-loader": "^6.2.1", "prettier": "npm:wp-prettier@3.0.3", "puppeteer-core": "^13.2.0", From 2157b85f7dbbfb52903a430c4946cfba27224b09 Mon Sep 17 00:00:00 2001 From: Akira Tachibana <atachibana@unofficialtokyo.com> Date: Sun, 1 Sep 2024 12:21:29 +0900 Subject: [PATCH 0619/1908] Fix wrong code snippets in API reference (#64416) Co-authored-by: atachibana <atachibana@git.wordpress.org> Co-authored-by: shail-mehta <shailu25@git.wordpress.org> --- .../interactivity-api/api-reference.md | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/reference-guides/interactivity-api/api-reference.md b/docs/reference-guides/interactivity-api/api-reference.md index e9b005d55899e8..25498d10bde2ef 100644 --- a/docs/reference-guides/interactivity-api/api-reference.md +++ b/docs/reference-guides/interactivity-api/api-reference.md @@ -84,7 +84,7 @@ It provides a **local** state available to a specific HTML node and its children The `wp-context` directive accepts a stringified JSON as a value. ```php -//render.php +// render.php <div data-wp-context='{ "post": { "id": <?php echo $post->ID; ?> } }' > <button data-wp-on--click="actions.logId" > Click Me! @@ -110,13 +110,13 @@ store( "myPlugin", { Different contexts can be defined at different levels, and deeper levels will merge their own context with any parent one: ```html -<div data-wp-context="{ foo: 'bar' }"> +<div data-wp-context='{ "foo": "bar" }'> <span data-wp-text="context.foo"><!-- Will output: "bar" --></span> - <div data-wp-context="{ bar: 'baz' }"> + <div data-wp-context='{ "bar": "baz" }'> <span data-wp-text="context.foo"><!-- Will output: "bar" --></span> - <div data-wp-context="{ foo: 'bob' }"> + <div data-wp-context='{ "foo": "bob" }'> <span data-wp-text="context.foo"><!-- Will output: "bob" --></span> </div> @@ -356,8 +356,7 @@ The callback passed as the reference receives [the event](https://developer.mozi ### `wp-on-async` -This directive is a more performant approach for `wp-on`. It immediately yields to main to avoid contributing to a long task, allowing other interactions that otherwise would be waiting on the main thread -to run sooner. Use this async version whenever there is no need for synchronous access to the `event` object, in particular the methods `event.preventDefault()`, `event.stopPropagation()`, and `event.stopImmediatePropagation()`. +This directive is a more performant approach for `wp-on`. It immediately yields to main to avoid contributing to a long task, allowing other interactions that otherwise would be waiting on the main thread to run sooner. Use this async version whenever there is no need for synchronous access to the `event` object, in particular the methods `event.preventDefault()`, `event.stopPropagation()`, and `event.stopImmediatePropagation()`. ### `wp-on-window` @@ -369,8 +368,7 @@ This directive allows you to attach global window events like `resize`, `copy`, [List of supported window events.](https://developer.mozilla.org/en-US/docs/Web/API/Window#events) -The syntax of this directive is `data-wp-on-window--[window-event]` (like `data-wp-on-window--resize` -or `data-wp-on-window--languagechange`). +The syntax of this directive is `data-wp-on-window--[window-event]` (like `data-wp-on-window--resize` or `data-wp-on-window--languagechange`). ```php <div data-wp-on-window--resize="callbacks.logWidth"></div> @@ -406,8 +404,7 @@ This directive allows you to attach global document events like `scroll`, `mouse [List of supported document events.](https://developer.mozilla.org/en-US/docs/Web/API/Document#events) -The syntax of this directive is `data-wp-on-document--[document-event]` (like `data-wp-on-document--keydown` -or `data-wp-on-document--selectionchange`). +The syntax of this directive is `data-wp-on-document--[document-event]` (like `data-wp-on-document--keydown` or `data-wp-on-document--selectionchange`). ```php <div data-wp-on-document--keydown="callbacks.logKeydown"></div> @@ -520,6 +517,8 @@ Here's another example with several `wp-init` directives on the same DOM element <summary><em>See store used with the directive above</em></summary> ```js +import { store, getElement } from '@wordpress/interactivity'; + store( "myPlugin", { callbacks: { logTimeInit: () => console.log( `Init at ` + new Date() ), @@ -882,10 +881,10 @@ const { state } = store( "myPlugin", { GBP: 0.85, }, get amountInUSD() { - return state.currencyExchange[ 'USD' ] * state.amount, + return state.currencyExchange[ 'USD' ] * state.amount; }, get amountInGBP() { - return state.currencyExchange[ 'GBP' ] * state.amount, + return state.currencyExchange[ 'GBP' ] * state.amount; }, }, } ); @@ -965,7 +964,7 @@ This approach enables some functionalities that make directives flexible and pow *In the `view.js` file of each block* the developer can define both the state and the elements of the store referencing functions like actions, side effects or derived state. -The `store` method used to set the store in javascript can be imported from `@wordpress/interactivity`. +The `store` method used to set the store in JavaScript can be imported from `@wordpress/interactivity`. ```js // store @@ -1111,7 +1110,7 @@ store( "myPlugin", { actions: { log: () => { const element = getElement(); - // Logs "false" + // Logs attributes console.log('element attributes => ', element.attributes) }, }, @@ -1122,7 +1121,7 @@ The code will log: ```json { - "data-wp-on--click": 'actions.increaseCounter', + "data-wp-on--click": 'actions.log', "children": ['Log'], "onclick": event => { evaluate(entry, event); } } @@ -1147,6 +1146,7 @@ store('mySliderPlugin', { 3_000 ); }, + }, }) ``` @@ -1245,7 +1245,7 @@ echo $processed_html; will output: ```html -<div data-wp-text="create-block::state.greeting">Hello, World!</div> +<div data-wp-text="myPlugin::state.greeting">Hello, World!</div> ``` ### wp_interactivity_data_wp_context From 88a565300e7132d070d57c8058f79f194f31f879 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Sun, 1 Sep 2024 16:25:44 +0530 Subject: [PATCH 0620/1908] Added Global Documentation in several php file (#64956) * Added @global documentation in php file * Added @global documentation in php file Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../wordpress-6.6/html-api/class-gutenberg-html-decoder-6-6.php | 2 ++ .../wordpress-6.7/html-api/class-gutenberg-html-decoder-6-7.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-decoder-6-6.php b/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-decoder-6-6.php index 2999921be52259..d0b9f18bf5b29b 100644 --- a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-decoder-6-6.php +++ b/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-decoder-6-6.php @@ -196,6 +196,8 @@ public static function decode( $context, $text ) { * * @since 6.6.0 * + * @global WP_Token_Map $html5_named_character_references + * * @param string $context `attribute` for decoding attribute values, `data` otherwise. * @param string $text Text document containing span of text to decode. * @param int $at Optional. Byte offset into text where span begins, defaults to the beginning (0). diff --git a/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-decoder-6-7.php b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-decoder-6-7.php index 70f51151d86478..c745904865b1f8 100644 --- a/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-decoder-6-7.php +++ b/lib/compat/wordpress-6.7/html-api/class-gutenberg-html-decoder-6-7.php @@ -196,6 +196,8 @@ public static function decode( $context, $text ): string { * * @since 6.6.0 * + * @global WP_Token_Map $html5_named_character_references + * * @param string $context `attribute` for decoding attribute values, `data` otherwise. * @param string $text Text document containing span of text to decode. * @param int $at Optional. Byte offset into text where span begins, defaults to the beginning (0). From 843e14b0e7768117ca6571bd009d04f522b63374 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Sun, 1 Sep 2024 20:53:51 +0900 Subject: [PATCH 0621/1908] Font Library Modal: Group font variations as a list (#64029) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../font-library-modal/font-collection.js | 56 ++++++++++++------- .../font-library-modal/installed-fonts.js | 34 ++++++++--- 2 files changed, 60 insertions(+), 30 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js index efa9524167f7b8..8c3140454b160b 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js @@ -376,7 +376,7 @@ function FontCollection( { slug } ) { </li> ) ) } </ul> - { /* eslint-enable jsx-a11y/no-redundant-roles */ }{ ' ' } + { /* eslint-enable jsx-a11y/no-redundant-roles */ } </div> </NavigatorScreen> @@ -425,26 +425,40 @@ function FontCollection( { slug } ) { __nextHasNoMarginBottom /> <VStack spacing={ 0 }> - <Spacer margin={ 8 } /> - { getSortedFontFaces( selectedFont ).map( - ( face, i ) => ( - <CollectionFontVariant - font={ selectedFont } - face={ face } - key={ `face${ i }` } - handleToggleVariant={ - handleToggleVariant - } - selected={ isFontFontFaceInOutline( - selectedFont.slug, - selectedFont.fontFace - ? face - : null, // If the font has no fontFace, we want to check if the font is in the outline - fontToInstallOutline - ) } - /> - ) - ) } + { /* + * Disable reason: The `list` ARIA role is redundant but + * Safari+VoiceOver won't announce the list otherwise. + */ + /* eslint-disable jsx-a11y/no-redundant-roles */ } + <ul + role="list" + className="font-library-modal__fonts-list" + > + { getSortedFontFaces( selectedFont ).map( + ( face, i ) => ( + <li + key={ `face${ i }` } + className="font-library-modal__fonts-list-item" + > + <CollectionFontVariant + font={ selectedFont } + face={ face } + handleToggleVariant={ + handleToggleVariant + } + selected={ isFontFontFaceInOutline( + selectedFont.slug, + selectedFont.fontFace + ? face + : null, // If the font has no fontFace, we want to check if the font is in the outline + fontToInstallOutline + ) } + /> + </li> + ) + ) } + </ul> + { /* eslint-enable jsx-a11y/no-redundant-roles */ } </VStack> <Spacer margin={ 16 } /> </NavigatorScreen> diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js index 945db7ccb8ae63..b9042d0fe609f6 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js @@ -399,15 +399,31 @@ function InstalledFonts() { __nextHasNoMarginBottom /> <Spacer margin={ 8 } /> - { getFontFacesToDisplay( - libraryFontSelected - ).map( ( face, i ) => ( - <LibraryFontVariant - font={ libraryFontSelected } - face={ face } - key={ `face${ i }` } - /> - ) ) } + { /* + * Disable reason: The `list` ARIA role is redundant but + * Safari+VoiceOver won't announce the list otherwise. + */ + /* eslint-disable jsx-a11y/no-redundant-roles */ } + <ul + role="list" + className="font-library-modal__fonts-list" + > + { getFontFacesToDisplay( + libraryFontSelected + ).map( ( face, i ) => ( + <li + key={ `face${ i }` } + className="font-library-modal__fonts-list-item" + > + <LibraryFontVariant + font={ libraryFontSelected } + face={ face } + key={ `face${ i }` } + /> + </li> + ) ) } + </ul> + { /* eslint-enable jsx-a11y/no-redundant-roles */ } </VStack> </NavigatorScreen> </NavigatorProvider> From 908821725095a4cd4f2dcbb0bff5730a5e5a464c Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Mon, 2 Sep 2024 16:24:51 +0900 Subject: [PATCH 0622/1908] DataViews: Fix pattern title direction in RTL languages (#64967) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/edit-site/src/components/page-patterns/fields.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/page-patterns/fields.js b/packages/edit-site/src/components/page-patterns/fields.js index ff14aa371fdc7e..ff9c0dbe81a047 100644 --- a/packages/edit-site/src/components/page-patterns/fields.js +++ b/packages/edit-site/src/components/page-patterns/fields.js @@ -126,7 +126,7 @@ function TitleField( { item } ) { <Flex as="div" gap={ 0 } - justify="left" + justify="flex-start" className="edit-site-patterns__pattern-title" > { item.type === PATTERN_TYPES.theme ? ( From 341b5e829b4c9ab552d3907cb843b812e5d4187e Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Mon, 2 Sep 2024 19:00:14 +1000 Subject: [PATCH 0623/1908] ColorPalette utils: do not normalize undefined color values (#64969) `normalizeColorValue` was detecting false positives, treating empty style values as non-simple values and therefore returning defaultView?.getComputedStyle. This commit returns the supplied value if undefined values are passed. adding tests. Also updates tests and changelog Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/color-palette/test/utils.ts | 23 +++++++++++++++++-- .../components/src/color-palette/utils.ts | 4 +--- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 00204111a1efd6..97b7724cee1ab9 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -60,6 +60,7 @@ ### Bug Fixes - `TimePicker`: use ToggleGroupControl for AM/PM toggle ([#64800](https://github.com/WordPress/gutenberg/pull/64800)). +- `ColorPalette` utils: do not normalize undefined color values ([#64969](https://github.com/WordPress/gutenberg/pull/64969)). ### Internal diff --git a/packages/components/src/color-palette/test/utils.ts b/packages/components/src/color-palette/test/utils.ts index 65e829a58a06bd..56acec5416ecbd 100644 --- a/packages/components/src/color-palette/test/utils.ts +++ b/packages/components/src/color-palette/test/utils.ts @@ -26,18 +26,37 @@ describe( 'ColorPalette: Utils', () => { } ); describe( 'normalizeColorValue', () => { - test( 'should return the value as is if the color value is not a CSS variable', () => { + test( 'should return the value if the value argument is not a CSS variable', () => { const element = document.createElement( 'div' ); expect( normalizeColorValue( '#ff0000', element ) ).toBe( '#ff0000' ); } ); - test( 'should return the background color computed from a element if the color value is a CSS variable', () => { + test( 'should return the background color computed from an element if the value argument is a CSS variable', () => { const element = document.createElement( 'div' ); element.style.backgroundColor = '#ff0000'; expect( normalizeColorValue( 'var(--red)', element ) ).toBe( '#ff0000' ); } ); + test( 'should return the background color computed from an element if the value argument is a color mix', () => { + const element = document.createElement( 'div' ); + element.style.backgroundColor = '#ff0000'; + expect( + normalizeColorValue( + 'color-mix(in oklab, #a71e14, white)', + element + ) + ).toBe( '#ff0000' ); + } ); + test( 'should return the value if the value argument is undefined', () => { + const element = document.createElement( 'div' ); + expect( normalizeColorValue( undefined, element ) ).toBe( + undefined + ); + } ); + test( 'should return the value if the element argument is null', () => { + expect( normalizeColorValue( '#ff0000', null ) ).toBe( '#ff0000' ); + } ); } ); } ); diff --git a/packages/components/src/color-palette/utils.ts b/packages/components/src/color-palette/utils.ts index cfe909c580f8bc..19fd4b7252f639 100644 --- a/packages/components/src/color-palette/utils.ts +++ b/packages/components/src/color-palette/utils.ts @@ -92,9 +92,7 @@ export const normalizeColorValue = ( value: string | undefined, element: HTMLElement | null ) => { - const valueIsSimpleColor = value ? isSimpleCSSColor( value ) : false; - - if ( valueIsSimpleColor || element === null ) { + if ( ! value || ! element || isSimpleCSSColor( value ) ) { return value; } From c7a991c16f193da7e6f5d03447956b98af20efac Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 2 Sep 2024 11:07:19 +0200 Subject: [PATCH 0624/1908] Composite: accept store props on top level component (#64832) * Composite: accept store props on top level component * CHANGELOG --- packages/components/CHANGELOG.md | 1 + packages/components/src/composite/index.tsx | 37 ++++++++++++++++++++- packages/components/src/composite/types.ts | 4 +-- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 97b7724cee1ab9..0021df7a361106 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -68,6 +68,7 @@ - `DropdownMenu` v2: refactor to overloaded naming convention ([#64654](https://github.com/WordPress/gutenberg/pull/64654)). - `DropdownMenu` v2: add `GroupLabel` subcomponent ([#64854](https://github.com/WordPress/gutenberg/pull/64854)). - `Composite` V2: fix Storybook docgen ([#64682](https://github.com/WordPress/gutenberg/pull/64682)). +- `Composite` V2: accept store props on top-level component ([#64832](https://github.com/WordPress/gutenberg/pull/64832)). ## 28.6.0 (2024-08-21) diff --git a/packages/components/src/composite/index.tsx b/packages/components/src/composite/index.tsx index 787150eb9b7146..629010d271e811 100644 --- a/packages/components/src/composite/index.tsx +++ b/packages/components/src/composite/index.tsx @@ -52,9 +52,44 @@ export const Composite = Object.assign( HTMLDivElement, WordPressComponentProps< CompositeProps, 'div', false > >( function Composite( - { children, store, disabled = false, ...props }, + { + // Composite store props + activeId, + defaultActiveId, + setActiveId, + focusLoop = false, + focusWrap = false, + focusShift = false, + virtualFocus = false, + orientation = 'both', + rtl = false, + + // Composite component props + children, + disabled = false, + + // To be removed + store: storeProp, + + // Rest props + ...props + }, ref ) { + const newStore = Ariakit.useCompositeStore( { + activeId, + defaultActiveId, + setActiveId, + focusLoop, + focusWrap, + focusShift, + virtualFocus, + orientation, + rtl, + } ); + + const store = storeProp || newStore; + const contextValue = useMemo( () => ( { store, diff --git a/packages/components/src/composite/types.ts b/packages/components/src/composite/types.ts index 05a2b8473eb349..fcde842e1cba77 100644 --- a/packages/components/src/composite/types.ts +++ b/packages/components/src/composite/types.ts @@ -128,11 +128,11 @@ export type CompositeStoreProps = { rtl?: Ariakit.CompositeStoreProps[ 'rtl' ]; }; -export type CompositeProps = { +export type CompositeProps = CompositeStoreProps & { /** * Object returned by the `useCompositeStore` hook. */ - store: Ariakit.CompositeStore; + store?: Ariakit.CompositeStore; /** * Allows the component to be rendered as a different HTML element or React * component. The value can be a React element or a function that takes in the From 77554a131e81a05e86e1d9ba39b4f02242b708c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Mon, 2 Sep 2024 11:10:58 +0200 Subject: [PATCH 0625/1908] DataViews docs: fix typo in `direction` values (#64973) --- packages/dataviews/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index cc1ef3bbebe4d0..3ce895680a15c5 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -337,7 +337,7 @@ Each "virtual field", has to provide an `id` and `label` (optionally a `header` Additionally, they need to provide: - `children`: a list of field's `id` to combine -- `direction`: how should they be stacked, `vertically` or `horizontally` +- `direction`: how should they be stacked, `vertical` or `horizontal` For example, this is how you'd define a `site` field which is a combination of a `title` and `description` fields, which are not displayed: From ac0f9e8d62e7daf8242468cbf8e309fef0968bb1 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Mon, 2 Sep 2024 10:50:21 +0100 Subject: [PATCH 0626/1908] DataViews: fix style inheritance (#64933) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- .../src/components/dataviews-filters/style.scss | 12 +++++++++++- .../src/components/dataviews-view-config/style.scss | 2 ++ .../dataviews/src/components/dataviews/style.scss | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/dataviews/src/components/dataviews-filters/style.scss b/packages/dataviews/src/components/dataviews-filters/style.scss index 3853aba960e790..f2841c16f0fec4 100644 --- a/packages/dataviews/src/components/dataviews-filters/style.scss +++ b/packages/dataviews/src/components/dataviews-filters/style.scss @@ -18,11 +18,19 @@ } .dataviews-filters__summary-popover { + font-size: $default-font-size; + line-height: $default-line-height; + .components-popover__content { width: 230px; - padding: 0; border-radius: $grid-unit-05; } + + &.components-dropdown__content { + .components-popover__content { + padding: 0; + } + } } .dataviews-filters__summary-operators-container { @@ -57,6 +65,7 @@ position: relative; display: flex; align-items: center; + box-sizing: border-box; &.has-reset { padding-inline-end: $button-size-small + $grid-unit-05; @@ -275,6 +284,7 @@ font-size: 11px; outline: var(--wp-admin-border-width-focus) solid $white; color: $white; + box-sizing: border-box; } .dataviews-search { diff --git a/packages/dataviews/src/components/dataviews-view-config/style.scss b/packages/dataviews/src/components/dataviews-view-config/style.scss index 2351793d0c2424..4c01de6b8994e6 100644 --- a/packages/dataviews/src/components/dataviews-view-config/style.scss +++ b/packages/dataviews/src/components/dataviews-view-config/style.scss @@ -3,6 +3,8 @@ /* stylelint-disable-next-line property-no-unknown -- the linter needs to be updated to accepted the container-type property */ container-type: inline-size; padding: $grid-unit-20; + font-size: $default-font-size; + line-height: $default-line-height; } .dataviews-view-config__sort-direction .components-toggle-group-control-option-base { text-transform: uppercase; diff --git a/packages/dataviews/src/components/dataviews/style.scss b/packages/dataviews/src/components/dataviews/style.scss index 1ce75d36020a78..8909c7cf1c7cfd 100644 --- a/packages/dataviews/src/components/dataviews/style.scss +++ b/packages/dataviews/src/components/dataviews/style.scss @@ -7,6 +7,8 @@ container: dataviews-wrapper / inline-size; display: flex; flex-direction: column; + font-size: $default-font-size; + line-height: $default-line-height; } .dataviews__view-actions, From 844790e84026bb06fa88bf2577a074d7a9c72908 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Mon, 2 Sep 2024 12:54:24 +0200 Subject: [PATCH 0627/1908] Block Bindings: Change placeholder when attribute is bound (#64903) * Change placeholder when attribute is bound * Only change placeholder when value is empty * Translate empty text Co-authored-by: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> * Adapt latest commit * Add `adjustedValue` in `useSelect` * Different message depending on capabilities * Remove "empty" from placeholder * Change `relatedBinding` variable name --------- Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> --- .../src/components/rich-text/index.js | 81 ++++++++++--------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index e8fbec1e0b7458..732b8dbf2c089c 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -20,8 +20,9 @@ import { removeFormat, } from '@wordpress/rich-text'; import { Popover } from '@wordpress/components'; -import { getBlockType, store as blocksStore } from '@wordpress/blocks'; +import { store as blocksStore } from '@wordpress/blocks'; import deprecated from '@wordpress/deprecated'; +import { __, sprintf } from '@wordpress/i18n'; /** * Internal dependencies @@ -163,49 +164,47 @@ export function RichTextWrapper( isBlockSelected, ] ); - const disableBoundBlocks = useSelect( + const { disableBoundBlock, bindingsPlaceholder } = useSelect( ( select ) => { - // Disable Rich Text editing if block bindings specify that. - let _disableBoundBlocks = false; - if ( blockBindings && canBindBlock( blockName ) ) { - const blockTypeAttributes = - getBlockType( blockName ).attributes; - const { getBlockBindingsSource } = unlock( - select( blocksStore ) - ); - for ( const [ attribute, binding ] of Object.entries( - blockBindings - ) ) { - if ( - blockTypeAttributes?.[ attribute ]?.source !== - 'rich-text' - ) { - break; - } - - // If the source is not defined, or if its value of `canUserEditValue` is `false`, disable it. - const blockBindingsSource = getBlockBindingsSource( - binding.source - ); - if ( - ! blockBindingsSource?.canUserEditValue?.( { - select, - context: blockContext, - args: binding.args, - } ) - ) { - _disableBoundBlocks = true; - break; - } - } + if ( + ! blockBindings?.[ identifier ] || + ! canBindBlock( blockName ) + ) { + return {}; } - return _disableBoundBlocks; + const relatedBinding = blockBindings[ identifier ]; + const { getBlockBindingsSource } = unlock( select( blocksStore ) ); + const blockBindingsSource = getBlockBindingsSource( + relatedBinding.source + ); + + const _disableBoundBlock = + ! blockBindingsSource?.canUserEditValue?.( { + select, + context: blockContext, + args: relatedBinding.args, + } ); + + const _bindingsPlaceholder = _disableBoundBlock + ? relatedBinding?.args?.key || blockBindingsSource?.label + : sprintf( + /* translators: %s: source label or key */ + __( 'Add %s' ), + relatedBinding?.args?.key || blockBindingsSource?.label + ); + + return { + disableBoundBlock: _disableBoundBlock, + bindingsPlaceholder: + ( ! adjustedValue || adjustedValue.length === 0 ) && + _bindingsPlaceholder, + }; }, - [ blockBindings, blockName ] + [ blockBindings, identifier, blockName, blockContext, adjustedValue ] ); - const shouldDisableEditing = readOnly || disableBoundBlocks; + const shouldDisableEditing = readOnly || disableBoundBlock; const { getSelectionStart, getSelectionEnd, getBlockRootClientId } = useSelect( blockEditorStore ); @@ -335,7 +334,7 @@ export function RichTextWrapper( selectionStart, selectionEnd, onSelectionChange, - placeholder, + placeholder: bindingsPlaceholder || placeholder, __unstableIsSelected: isSelected, __unstableDisableFormats: disableFormats, preserveWhiteSpace, @@ -404,9 +403,11 @@ export function RichTextWrapper( // Overridable props. role="textbox" aria-multiline={ ! disableLineBreaks } - aria-label={ placeholder } aria-readonly={ shouldDisableEditing } { ...props } + aria-label={ + bindingsPlaceholder || props[ 'aria-label' ] || placeholder + } { ...autocompleteProps } ref={ useMergeRefs( [ // Rich text ref must be first because its focus listener From 9ff171f393b749e19415f4e72815b58c0e75c45d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Mon, 2 Sep 2024 12:59:43 +0200 Subject: [PATCH 0628/1908] DataViews: adds two new stories for edge cases (#64975) --- .../dataviews/stories/index.story.js | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/packages/dataviews/src/components/dataviews/stories/index.story.js b/packages/dataviews/src/components/dataviews/stories/index.story.js index 376b14a464666c..75fb0786ecfee6 100644 --- a/packages/dataviews/src/components/dataviews/stories/index.story.js +++ b/packages/dataviews/src/components/dataviews/stories/index.story.js @@ -33,6 +33,46 @@ export const Default = ( props ) => { /> ); }; + +export const Empty = ( props ) => { + const [ view, setView ] = useState( DEFAULT_VIEW ); + + return ( + <DataViews + { ...props } + paginationInfo={ { totalItems: 0, totalPages: 0 } } + data={ [] } + view={ view } + fields={ fields } + onChangeView={ setView } + /> + ); +}; + +export const FieldsNoSortableNoHidable = ( props ) => { + const [ view, setView ] = useState( DEFAULT_VIEW ); + const { data: shownData, paginationInfo } = useMemo( () => { + return filterSortAndPaginate( data, view, fields ); + }, [ view ] ); + + const _fields = fields.map( ( field ) => ( { + ...field, + enableSorting: false, + enableHiding: false, + } ) ); + + return ( + <DataViews + { ...props } + paginationInfo={ paginationInfo } + data={ shownData } + view={ view } + fields={ _fields } + onChangeView={ setView } + /> + ); +}; + Default.args = { actions, defaultLayouts: { From a342589389b3ca5900005f06116ae150e42077e4 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 2 Sep 2024 16:04:07 +0400 Subject: [PATCH 0629/1908] Core Data: Avoid loops in 'registry.batch' calls (#64955) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/core-data/src/resolvers.js | 40 ++++++++++++++---------- packages/core-data/src/test/resolvers.js | 4 +-- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 2e0c2497d382d1..d1aaf0b447cfed 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -177,24 +177,32 @@ export const getEntityRecord = response.headers?.get( 'allow' ) ); + const canUserResolutionsArgs = []; + const receiveUserPermissionArgs = {}; + for ( const action of ALLOWED_RESOURCE_ACTIONS ) { + receiveUserPermissionArgs[ + getUserPermissionCacheKey( action, { + kind, + name, + id: key, + } ) + ] = permissions[ action ]; + + canUserResolutionsArgs.push( [ + action, + { kind, name, id: key }, + ] ); + } + registry.batch( () => { dispatch.receiveEntityRecords( kind, name, record, query ); - - for ( const action of ALLOWED_RESOURCE_ACTIONS ) { - const permissionKey = getUserPermissionCacheKey( - action, - { kind, name, id: key } - ); - - dispatch.receiveUserPermission( - permissionKey, - permissions[ action ] - ); - dispatch.finishResolution( 'canUser', [ - action, - { kind, name, id: key }, - ] ); - } + dispatch.receiveUserPermissions( + receiveUserPermissionArgs + ); + dispatch.finishResolutions( + 'canUser', + canUserResolutionsArgs + ); } ); } } finally { diff --git a/packages/core-data/src/test/resolvers.js b/packages/core-data/src/test/resolvers.js index c3dbdaa6533386..946b795726d2a2 100644 --- a/packages/core-data/src/test/resolvers.js +++ b/packages/core-data/src/test/resolvers.js @@ -36,8 +36,8 @@ describe( 'getEntityRecord', () => { receiveEntityRecords: jest.fn(), __unstableAcquireStoreLock: jest.fn(), __unstableReleaseStoreLock: jest.fn(), - receiveUserPermission: jest.fn(), - finishResolution: jest.fn(), + receiveUserPermissions: jest.fn(), + finishResolutions: jest.fn(), } ); triggerFetch.mockReset(); } ); From 52832f5bc8ff4dcbe9e5116dc3a47438b7460b13 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 2 Sep 2024 14:20:03 +0200 Subject: [PATCH 0630/1908] DropdownMenuV2: fix active and focus-visible item glitches (#64942) * Remove previous workaround * Implement flushSync-based workaround * Update CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: diegohaz <hazdiego@git.wordpress.org> --- packages/components/CHANGELOG.md | 2 +- .../src/dropdown-menu-v2/checkbox-item.tsx | 6 ++++- .../components/src/dropdown-menu-v2/item.tsx | 6 ++++- .../src/dropdown-menu-v2/radio-item.tsx | 6 ++++- .../components/src/dropdown-menu-v2/styles.ts | 15 ++++--------- .../use-temporary-focus-visible-fix.ts | 22 +++++++++++++++++++ 6 files changed, 42 insertions(+), 15 deletions(-) create mode 100644 packages/components/src/dropdown-menu-v2/use-temporary-focus-visible-fix.ts diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 0021df7a361106..48bdc1e9cbdcfb 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -64,7 +64,7 @@ ### Internal -- `DropdownMenu` v2: fix flashing menu item styles when using keyboard ([#64873](https://github.com/WordPress/gutenberg/pull/64873)). +- `DropdownMenu` v2: fix flashing menu item styles when using keyboard ([#64873](https://github.com/WordPress/gutenberg/pull/64873), [#64942](https://github.com/WordPress/gutenberg/pull/64942)). - `DropdownMenu` v2: refactor to overloaded naming convention ([#64654](https://github.com/WordPress/gutenberg/pull/64654)). - `DropdownMenu` v2: add `GroupLabel` subcomponent ([#64854](https://github.com/WordPress/gutenberg/pull/64854)). - `Composite` V2: fix Storybook docgen ([#64682](https://github.com/WordPress/gutenberg/pull/64682)). diff --git a/packages/components/src/dropdown-menu-v2/checkbox-item.tsx b/packages/components/src/dropdown-menu-v2/checkbox-item.tsx index 2f0d15557bb5e5..bcbc920cbb7205 100644 --- a/packages/components/src/dropdown-menu-v2/checkbox-item.tsx +++ b/packages/components/src/dropdown-menu-v2/checkbox-item.tsx @@ -16,20 +16,24 @@ import type { WordPressComponentProps } from '../context'; import { DropdownMenuContext } from './context'; import type { DropdownMenuCheckboxItemProps } from './types'; import * as Styled from './styles'; +import { useTemporaryFocusVisibleFix } from './use-temporary-focus-visible-fix'; export const DropdownMenuCheckboxItem = forwardRef< HTMLDivElement, WordPressComponentProps< DropdownMenuCheckboxItemProps, 'div', false > >( function DropdownMenuCheckboxItem( - { suffix, children, hideOnClick = false, ...props }, + { suffix, children, onBlur, hideOnClick = false, ...props }, ref ) { + // TODO: Remove when https://github.com/ariakit/ariakit/issues/4083 is fixed + const focusVisibleFixProps = useTemporaryFocusVisibleFix( { onBlur } ); const dropdownMenuContext = useContext( DropdownMenuContext ); return ( <Styled.DropdownMenuCheckboxItem ref={ ref } { ...props } + { ...focusVisibleFixProps } accessibleWhenDisabled hideOnClick={ hideOnClick } store={ dropdownMenuContext?.store } diff --git a/packages/components/src/dropdown-menu-v2/item.tsx b/packages/components/src/dropdown-menu-v2/item.tsx index 50cf21f614dc59..2680603db22aa7 100644 --- a/packages/components/src/dropdown-menu-v2/item.tsx +++ b/packages/components/src/dropdown-menu-v2/item.tsx @@ -10,20 +10,24 @@ import type { WordPressComponentProps } from '../context'; import type { DropdownMenuItemProps } from './types'; import * as Styled from './styles'; import { DropdownMenuContext } from './context'; +import { useTemporaryFocusVisibleFix } from './use-temporary-focus-visible-fix'; export const DropdownMenuItem = forwardRef< HTMLDivElement, WordPressComponentProps< DropdownMenuItemProps, 'div', false > >( function DropdownMenuItem( - { prefix, suffix, children, hideOnClick = true, ...props }, + { prefix, suffix, children, onBlur, hideOnClick = true, ...props }, ref ) { + // TODO: Remove when https://github.com/ariakit/ariakit/issues/4083 is fixed + const focusVisibleFixProps = useTemporaryFocusVisibleFix( { onBlur } ); const dropdownMenuContext = useContext( DropdownMenuContext ); return ( <Styled.DropdownMenuItem ref={ ref } { ...props } + { ...focusVisibleFixProps } accessibleWhenDisabled hideOnClick={ hideOnClick } store={ dropdownMenuContext?.store } diff --git a/packages/components/src/dropdown-menu-v2/radio-item.tsx b/packages/components/src/dropdown-menu-v2/radio-item.tsx index c31f3ca0486398..547d8f257cdf4b 100644 --- a/packages/components/src/dropdown-menu-v2/radio-item.tsx +++ b/packages/components/src/dropdown-menu-v2/radio-item.tsx @@ -17,6 +17,7 @@ import { DropdownMenuContext } from './context'; import type { DropdownMenuRadioItemProps } from './types'; import * as Styled from './styles'; import { SVG, Circle } from '@wordpress/primitives'; +import { useTemporaryFocusVisibleFix } from './use-temporary-focus-visible-fix'; const radioCheck = ( <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> @@ -28,15 +29,18 @@ export const DropdownMenuRadioItem = forwardRef< HTMLDivElement, WordPressComponentProps< DropdownMenuRadioItemProps, 'div', false > >( function DropdownMenuRadioItem( - { suffix, children, hideOnClick = false, ...props }, + { suffix, children, onBlur, hideOnClick = false, ...props }, ref ) { + // TODO: Remove when https://github.com/ariakit/ariakit/issues/4083 is fixed + const focusVisibleFixProps = useTemporaryFocusVisibleFix( { onBlur } ); const dropdownMenuContext = useContext( DropdownMenuContext ); return ( <Styled.DropdownMenuRadioItem ref={ ref } { ...props } + { ...focusVisibleFixProps } accessibleWhenDisabled hideOnClick={ hideOnClick } store={ dropdownMenuContext?.store } diff --git a/packages/components/src/dropdown-menu-v2/styles.ts b/packages/components/src/dropdown-menu-v2/styles.ts index 9bb2f07b282622..fb336377bd9f18 100644 --- a/packages/components/src/dropdown-menu-v2/styles.ts +++ b/packages/components/src/dropdown-menu-v2/styles.ts @@ -171,23 +171,16 @@ const baseItem = css` cursor: not-allowed; } - /* Active item (including hover) - * Note: we should be able to remove :focus-visible once - * https://github.com/ariakit/ariakit/issues/4083 is fixed and released - */ - &[data-active-item]:not( [data-focus-visible] ):not( :focus-visible ):not( + /* Active item (including hover) */ + &[data-active-item]:not( [data-focus-visible] ):not( [aria-disabled='true'] ) { background-color: ${ COLORS.theme.accent }; color: ${ COLORS.white }; } - /* Keyboard focus (focus-visible) - * Note: we should be able to remove :focus-visible once - * https://github.com/ariakit/ariakit/issues/4083 is fixed and released - */ - &[data-focus-visible], - &:focus-visible { + /* Keyboard focus (focus-visible) */ + &[data-focus-visible] { box-shadow: 0 0 0 1.5px ${ COLORS.theme.accent }; /* Only visible in Windows High Contrast mode */ diff --git a/packages/components/src/dropdown-menu-v2/use-temporary-focus-visible-fix.ts b/packages/components/src/dropdown-menu-v2/use-temporary-focus-visible-fix.ts new file mode 100644 index 00000000000000..0df13133739609 --- /dev/null +++ b/packages/components/src/dropdown-menu-v2/use-temporary-focus-visible-fix.ts @@ -0,0 +1,22 @@ +/** + * WordPress dependencies + */ +import { useState, flushSync } from '@wordpress/element'; + +export function useTemporaryFocusVisibleFix( { + onBlur: onBlurProp, +}: { + onBlur?: React.FocusEventHandler< HTMLDivElement >; +} ) { + const [ focusVisible, setFocusVisible ] = useState( false ); + return { + 'data-focus-visible': focusVisible || undefined, + onFocusVisible: () => { + flushSync( () => setFocusVisible( true ) ); + }, + onBlur: ( ( event ) => { + onBlurProp?.( event ); + setFocusVisible( false ); + } ) as React.FocusEventHandler< HTMLDivElement >, + }; +} From c0c870ca92ad0280d73e2cba02a00f231de4d178 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 2 Sep 2024 14:31:13 +0200 Subject: [PATCH 0631/1908] DropdownMenuV2: update animation (#64868) * DropdownMenuV2: update animation specs * Swap inner and outer wrappers so that role="menu" is direct parent of menuitems * CHANGELOG * Using currentPlacement instead of placement * Move z-index styles to inner wrapper * Consolidate animation styles * Tweak outer wrapper scale factor * Remove will-change as it seems to cause glitchiness * Add exit animation - Refactor from CSS animation to transition - Use `[data-enter]` and `[data-leave]` ariakit attributes - Move CSS comments inline * Remove unuesed import * Update packages/components/src/dropdown-menu-v2/styles.ts Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com> * Change out animation duration to 200ms --------- Unlinked contributors: nick-a8c. Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/dropdown-menu-v2/index.tsx | 18 +- .../components/src/dropdown-menu-v2/styles.ts | 157 ++++++++++-------- 3 files changed, 107 insertions(+), 69 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 48bdc1e9cbdcfb..a3acb863f3869b 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -67,6 +67,7 @@ - `DropdownMenu` v2: fix flashing menu item styles when using keyboard ([#64873](https://github.com/WordPress/gutenberg/pull/64873), [#64942](https://github.com/WordPress/gutenberg/pull/64942)). - `DropdownMenu` v2: refactor to overloaded naming convention ([#64654](https://github.com/WordPress/gutenberg/pull/64654)). - `DropdownMenu` v2: add `GroupLabel` subcomponent ([#64854](https://github.com/WordPress/gutenberg/pull/64854)). +- `DropdownMenuV2`: update animation ([#64868](https://github.com/WordPress/gutenberg/pull/64868)). - `Composite` V2: fix Storybook docgen ([#64682](https://github.com/WordPress/gutenberg/pull/64682)). - `Composite` V2: accept store props on top-level component ([#64832](https://github.com/WordPress/gutenberg/pull/64832)). diff --git a/packages/components/src/dropdown-menu-v2/index.tsx b/packages/components/src/dropdown-menu-v2/index.tsx index 34805d2d3e2687..50c4f3069d51b5 100644 --- a/packages/components/src/dropdown-menu-v2/index.tsx +++ b/packages/components/src/dropdown-menu-v2/index.tsx @@ -109,9 +109,11 @@ const UnconnectedDropdownMenu = ( ); // Extract the side from the applied placement — useful for animations. + // Using `currentPlacement` instead of `placement` to make sure that we + // use the final computed placement (including "flips" etc). const appliedPlacementSide = useStoreState( dropdownMenuStore, - 'placement' + 'currentPlacement' ).split( '-' )[ 0 ]; if ( @@ -173,7 +175,7 @@ const UnconnectedDropdownMenu = ( /> { /* Menu popover */ } - <Styled.DropdownMenu + <Ariakit.Menu { ...otherProps } modal={ modal } store={ dropdownMenuStore } @@ -185,15 +187,23 @@ const UnconnectedDropdownMenu = ( shift={ shift ?? ( dropdownMenuStore.parent ? -4 : 0 ) } hideOnHoverOutside={ false } data-side={ appliedPlacementSide } - variant={ variant } wrapperProps={ wrapperProps } hideOnEscape={ hideOnEscape } unmountOnHide + render={ ( renderProps ) => ( + // Two wrappers are needed for the entry animation, where the menu + // container scales with a different factor than its contents. + // The {...renderProps} are passed to the inner wrapper, so that the + // menu element is the direct parent of the menu item elements. + <Styled.MenuPopoverOuterWrapper variant={ variant }> + <Styled.MenuPopoverInnerWrapper { ...renderProps } /> + </Styled.MenuPopoverOuterWrapper> + ) } > <DropdownMenuContext.Provider value={ contextValue }> { children } </DropdownMenuContext.Provider> - </Styled.DropdownMenu> + </Ariakit.Menu> </> ); }; diff --git a/packages/components/src/dropdown-menu-v2/styles.ts b/packages/components/src/dropdown-menu-v2/styles.ts index fb336377bd9f18..55020fbcd41354 100644 --- a/packages/components/src/dropdown-menu-v2/styles.ts +++ b/packages/components/src/dropdown-menu-v2/styles.ts @@ -2,7 +2,7 @@ * External dependencies */ import * as Ariakit from '@ariakit/react'; -import { css, keyframes } from '@emotion/react'; +import { css } from '@emotion/react'; import styled from '@emotion/styled'; /** @@ -15,9 +15,13 @@ import { Truncate } from '../truncate'; import type { DropdownMenuContext } from './types'; const ANIMATION_PARAMS = { - SLIDE_AMOUNT: '2px', - DURATION: '400ms', - EASING: 'cubic-bezier( 0.16, 1, 0.3, 1 )', + SCALE_AMOUNT_OUTER: 0.82, + SCALE_AMOUNT_CONTENT: 0.9, + DURATION: { + IN: '400ms', + OUT: '200ms', + }, + EASING: 'cubic-bezier(0.33, 0, 0, 1)', }; const CONTENT_WRAPPER_PADDING = space( 1 ); @@ -38,41 +42,60 @@ const TOOLBAR_VARIANT_BOX_SHADOW = `0 0 0 ${ CONFIG.borderWidth } ${ TOOLBAR_VAR const GRID_TEMPLATE_COLS = 'minmax( 0, max-content ) 1fr'; -const slideUpAndFade = keyframes( { - '0%': { - opacity: 0, - transform: `translateY(${ ANIMATION_PARAMS.SLIDE_AMOUNT })`, - }, - '100%': { opacity: 1, transform: 'translateY(0)' }, -} ); +export const MenuPopoverOuterWrapper = styled.div< + Pick< DropdownMenuContext, 'variant' > +>` + position: relative; -const slideRightAndFade = keyframes( { - '0%': { - opacity: 0, - transform: `translateX(-${ ANIMATION_PARAMS.SLIDE_AMOUNT })`, - }, - '100%': { opacity: 1, transform: 'translateX(0)' }, -} ); + background-color: ${ COLORS.ui.background }; + border-radius: ${ CONFIG.radiusMedium }; + ${ ( props ) => css` + box-shadow: ${ props.variant === 'toolbar' + ? TOOLBAR_VARIANT_BOX_SHADOW + : DEFAULT_BOX_SHADOW }; + ` } -const slideDownAndFade = keyframes( { - '0%': { - opacity: 0, - transform: `translateY(-${ ANIMATION_PARAMS.SLIDE_AMOUNT })`, - }, - '100%': { opacity: 1, transform: 'translateY(0)' }, -} ); + overflow: hidden; -const slideLeftAndFade = keyframes( { - '0%': { - opacity: 0, - transform: `translateX(${ ANIMATION_PARAMS.SLIDE_AMOUNT })`, - }, - '100%': { opacity: 1, transform: 'translateX(0)' }, -} ); + /* Open/close animation (outer wrapper) */ + @media not ( prefers-reduced-motion ) { + transition-property: transform, opacity; + transition-timing-function: ${ ANIMATION_PARAMS.EASING }; + transition-duration: ${ ANIMATION_PARAMS.DURATION.IN }; + will-change: transform, opacity; -export const DropdownMenu = styled( Ariakit.Menu )< - Pick< DropdownMenuContext, 'variant' > ->` + /* Regardless of the side, fade in and out. */ + opacity: 0; + &:has( [data-enter] ) { + opacity: 1; + } + + &:has( [data-leave] ) { + transition-duration: ${ ANIMATION_PARAMS.DURATION.OUT }; + } + + /* For menus opening on top and bottom side, animate the scale Y too. */ + &:has( [data-side='bottom'] ), + &:has( [data-side='top'] ) { + transform: scaleY( ${ ANIMATION_PARAMS.SCALE_AMOUNT_OUTER } ); + } + &:has( [data-side='bottom'] ) { + transform-origin: top; + } + &:has( [data-side='top'] ) { + transform-origin: bottom; + } + &:has( [data-enter][data-side='bottom'] ), + &:has( [data-enter][data-side='top'] ), + /* Do not animate the scaleY when closing the menu */ + &:has( [data-leave][data-side='bottom'] ), + &:has( [data-leave][data-side='top'] ) { + transform: scaleY( 1 ); + } + } +`; + +export const MenuPopoverInnerWrapper = styled.div` position: relative; /* Same as popover component */ /* TODO: is there a way to read the sass variable? */ @@ -86,15 +109,8 @@ export const DropdownMenu = styled( Ariakit.Menu )< min-width: 160px; max-width: 320px; max-height: var( --popover-available-height ); - padding: ${ CONTENT_WRAPPER_PADDING }; - background-color: ${ COLORS.ui.background }; - border-radius: ${ CONFIG.radiusMedium }; - ${ ( props ) => css` - box-shadow: ${ props.variant === 'toolbar' - ? TOOLBAR_VARIANT_BOX_SHADOW - : DEFAULT_BOX_SHADOW }; - ` } + padding: ${ CONTENT_WRAPPER_PADDING }; overscroll-behavior: contain; overflow: auto; @@ -102,23 +118,32 @@ export const DropdownMenu = styled( Ariakit.Menu )< /* Only visible in Windows High Contrast mode */ outline: 2px solid transparent !important; - /* Animation */ - &[data-open] { - @media not ( prefers-reduced-motion ) { - animation-duration: ${ ANIMATION_PARAMS.DURATION }; - animation-timing-function: ${ ANIMATION_PARAMS.EASING }; - will-change: transform, opacity; - /* Default animation.*/ - animation-name: ${ slideDownAndFade }; - &[data-side='left'] { - animation-name: ${ slideLeftAndFade }; - } - &[data-side='up'] { - animation-name: ${ slideUpAndFade }; - } - &[data-side='right'] { - animation-name: ${ slideRightAndFade }; - } + /* Open/close animation (inner content wrapper) */ + @media not ( prefers-reduced-motion ) { + transition: inherit; + transform-origin: inherit; + + /* + * For menus opening on top and bottom side, animate the scale Y too. + * The content scales at a different rate than the outer container: + * - first, counter the outer scale factor by doing "1 / scaleAmountOuter" + * - then, apply the content scale factor. + */ + &[data-side='bottom'], + &[data-side='top'] { + transform: scaleY( + calc( + 1 / ${ ANIMATION_PARAMS.SCALE_AMOUNT_OUTER } * + ${ ANIMATION_PARAMS.SCALE_AMOUNT_CONTENT } + ) + ); + } + &[data-enter][data-side='bottom'], + &[data-enter][data-side='top'], + /* Do not animate the scaleY when closing the menu */ + &[data-leave][data-side='bottom'], + &[data-leave][data-side='top'] { + transform: scaleY( 1 ); } } `; @@ -194,7 +219,7 @@ const baseItem = css` } /* When the item is the trigger of an open submenu */ - ${ DropdownMenu }:not(:focus) &:not(:focus)[aria-expanded="true"] { + ${ MenuPopoverInnerWrapper }:not(:focus) &:not(:focus)[aria-expanded="true"] { background-color: ${ LIGHT_BACKGROUND_COLOR }; color: ${ COLORS.theme.foreground }; } @@ -292,9 +317,9 @@ export const ItemSuffixWrapper = styled.span` * When the parent menu item is active, except when it's a non-focused/hovered * submenu trigger (in that case, color should not be inherited) */ - [data-active-item]:not( [data-focus-visible] ) *:not(${ DropdownMenu }) &, + [data-active-item]:not( [data-focus-visible] ) *:not(${ MenuPopoverInnerWrapper }) &, /* When the parent menu item is disabled */ - [aria-disabled='true'] *:not(${ DropdownMenu }) & { + [aria-disabled='true'] *:not(${ MenuPopoverInnerWrapper }) & { color: inherit; } `; @@ -357,8 +382,10 @@ export const DropdownMenuItemHelpText = styled( Truncate )` color: ${ LIGHTER_TEXT_COLOR }; word-break: break-all; - [data-active-item]:not( [data-focus-visible] ) *:not( ${ DropdownMenu } ) &, - [aria-disabled='true'] *:not( ${ DropdownMenu } ) & { + [data-active-item]:not( [data-focus-visible] ) + *:not( ${ MenuPopoverInnerWrapper } ) + &, + [aria-disabled='true'] *:not( ${ MenuPopoverInnerWrapper } ) & { color: inherit; } `; From ade686369e5bf3768a456c4bac6bdc9b919f403b Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 2 Sep 2024 15:07:05 +0200 Subject: [PATCH 0632/1908] AlignmentMatrixControl: do not use Composite store (#64850) * AlignmentMatrixControl: do not use composite store * CHANGELOG --- packages/components/CHANGELOG.md | 1 + .../src/alignment-matrix-control/index.tsx | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index a3acb863f3869b..03520d901d85f6 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -56,6 +56,7 @@ - `TreeSelect` - `UnitControl` - `Modal`: Update animation effect ([#64580](https://github.com/WordPress/gutenberg/pull/64580)). +- `AlignmentMatrixControl`: do not use composite store directly ([#64850](https://github.com/WordPress/gutenberg/pull/64850)). ### Bug Fixes diff --git a/packages/components/src/alignment-matrix-control/index.tsx b/packages/components/src/alignment-matrix-control/index.tsx index fcf8c2fd470156..0e3c23623883fc 100644 --- a/packages/components/src/alignment-matrix-control/index.tsx +++ b/packages/components/src/alignment-matrix-control/index.tsx @@ -8,13 +8,13 @@ import clsx from 'clsx'; */ import { __, isRTL } from '@wordpress/i18n'; import { useInstanceId } from '@wordpress/compose'; +import { useCallback } from '@wordpress/element'; /** * Internal dependencies */ import Cell from './cell'; import { Composite } from '../composite'; -import { useCompositeStore } from '../composite/store'; import { GridContainer, GridRow } from './styles'; import AlignmentMatrixControlIcon from './icon'; import { GRID, getItemId, getItemValue } from './utils'; @@ -37,23 +37,26 @@ function UnforwardedAlignmentMatrixControl( { id ); - const compositeStore = useCompositeStore( { - defaultActiveId: getItemId( baseId, defaultValue ), - activeId: getItemId( baseId, value ), - setActiveId: ( nextActiveId ) => { + const setActiveId = useCallback< + NonNullable< React.ComponentProps< typeof Composite >[ 'setActiveId' ] > + >( + ( nextActiveId ) => { const nextValue = getItemValue( baseId, nextActiveId ); if ( nextValue ) { onChange?.( nextValue ); } }, - rtl: isRTL(), - } ); + [ baseId, onChange ] + ); const classes = clsx( 'component-alignment-matrix-control', className ); return ( <Composite - store={ compositeStore } + defaultActiveId={ getItemId( baseId, defaultValue ) } + activeId={ getItemId( baseId, value ) } + setActiveId={ setActiveId } + rtl={ isRTL() } render={ <GridContainer { ...props } From b40fc02649e98db01d1fc3967da10e3dcdba8e76 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 2 Sep 2024 16:55:05 +0200 Subject: [PATCH 0633/1908] CircularOptionPicker: stop using composite store (#64833) * CircularOptionPicker: do not use composite store directly * Wait for composite to initialize in unit tests * CHANGELOG --------- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: diegohaz <hazdiego@git.wordpress.org> --- .../components/color-palette/test/control.js | 17 ++++++++- packages/components/CHANGELOG.md | 1 + .../circular-option-picker-option.tsx | 35 ++++++++---------- .../circular-option-picker.tsx | 37 +++++++++++++------ .../src/circular-option-picker/types.ts | 4 +- 5 files changed, 59 insertions(+), 35 deletions(-) diff --git a/packages/block-editor/src/components/color-palette/test/control.js b/packages/block-editor/src/components/color-palette/test/control.js index 3a5dcc657a94c4..e1a5529544f791 100644 --- a/packages/block-editor/src/components/color-palette/test/control.js +++ b/packages/block-editor/src/components/color-palette/test/control.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { render } from '@testing-library/react'; +import { render, waitFor, queryByAttribute } from '@testing-library/react'; /** * Internal dependencies @@ -10,9 +10,22 @@ import ColorPaletteControl from '../control'; const noop = () => {}; +async function renderAndValidate( ...renderArgs ) { + const view = render( ...renderArgs ); + await waitFor( () => { + const activeButton = queryByAttribute( + 'data-active-item', + view.baseElement, + 'true' + ); + expect( activeButton ).not.toBeNull(); + } ); + return view; +} + describe( 'ColorPaletteControl', () => { it( 'matches the snapshot', async () => { - const { container } = render( + const { container } = await renderAndValidate( <ColorPaletteControl label="Test Color" value="#f00" diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 03520d901d85f6..3b8d45be5861bc 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -57,6 +57,7 @@ - `UnitControl` - `Modal`: Update animation effect ([#64580](https://github.com/WordPress/gutenberg/pull/64580)). - `AlignmentMatrixControl`: do not use composite store directly ([#64850](https://github.com/WordPress/gutenberg/pull/64850)). +- `CircularOptionPicker`: do not use composite store directly ([#64833](https://github.com/WordPress/gutenberg/pull/64833)). ### Bug Fixes diff --git a/packages/components/src/circular-option-picker/circular-option-picker-option.tsx b/packages/components/src/circular-option-picker/circular-option-picker-option.tsx index 1ab4fd0d017901..276ab7549781ed 100644 --- a/packages/components/src/circular-option-picker/circular-option-picker-option.tsx +++ b/packages/components/src/circular-option-picker/circular-option-picker-option.tsx @@ -2,14 +2,13 @@ * External dependencies */ import clsx from 'clsx'; -import { useStoreState } from '@ariakit/react'; import type { ForwardedRef } from 'react'; /** * WordPress dependencies */ import { useInstanceId } from '@wordpress/compose'; -import { forwardRef, useContext } from '@wordpress/element'; +import { forwardRef, useContext, useEffect } from '@wordpress/element'; import { Icon, check } from '@wordpress/icons'; /** @@ -46,18 +45,21 @@ function UnforwardedOptionAsOption( id: string; className?: string; isSelected?: boolean; - compositeStore: NonNullable< - React.ComponentProps< typeof Composite >[ 'store' ] - >; }, forwardedRef: ForwardedRef< any > ) { - const { id, isSelected, compositeStore, ...additionalProps } = props; - const activeId = useStoreState( compositeStore, 'activeId' ); + const { id, isSelected, ...additionalProps } = props; - if ( isSelected && ! activeId ) { - compositeStore.setActiveId( id ); - } + const { setActiveId, activeId } = useContext( CircularOptionPickerContext ); + + useEffect( () => { + if ( isSelected && ! activeId ) { + // The setTimeout call is necessary to make sure that this update + // doesn't get overridden by `Composite`'s internal logic, which picks + // an initial active item if one is not specifically set. + window.setTimeout( () => setActiveId?.( id ), 0 ); + } + }, [ isSelected, setActiveId, activeId, id ] ); return ( <Composite.Item @@ -83,9 +85,7 @@ export function Option( { tooltipText, ...additionalProps }: OptionProps ) { - const { baseId, compositeStore } = useContext( - CircularOptionPickerContext - ); + const { baseId, setActiveId } = useContext( CircularOptionPickerContext ); const id = useInstanceId( Option, baseId || 'components-circular-option-picker__option' @@ -97,12 +97,9 @@ export function Option( { ...additionalProps, }; - const optionControl = compositeStore ? ( - <OptionAsOption - { ...commonProps } - compositeStore={ compositeStore } - isSelected={ isSelected } - /> + const isListbox = setActiveId !== undefined; + const optionControl = isListbox ? ( + <OptionAsOption { ...commonProps } isSelected={ isSelected } /> ) : ( <OptionAsButton { ...commonProps } isPressed={ isSelected } /> ); diff --git a/packages/components/src/circular-option-picker/circular-option-picker.tsx b/packages/components/src/circular-option-picker/circular-option-picker.tsx index c878000aff84b8..adf2b386e5cbec 100644 --- a/packages/components/src/circular-option-picker/circular-option-picker.tsx +++ b/packages/components/src/circular-option-picker/circular-option-picker.tsx @@ -8,13 +8,13 @@ import clsx from 'clsx'; */ import { useInstanceId } from '@wordpress/compose'; import { isRTL } from '@wordpress/i18n'; +import { useMemo, useState } from '@wordpress/element'; /** * Internal dependencies */ import { CircularOptionPickerContext } from './circular-option-picker-context'; import { Composite } from '../composite'; -import { useCompositeStore } from '../composite/store'; import type { CircularOptionPickerProps, ListboxCircularOptionPickerProps, @@ -86,24 +86,30 @@ function ListboxCircularOptionPicker( ...additionalProps } = props; - const compositeStore = useCompositeStore( { - focusLoop: loop, - rtl: isRTL(), - } ); + const [ activeId, setActiveId ] = useState< string | null | undefined >( + undefined + ); - const compositeContext = { - baseId, - compositeStore, - }; + const contextValue = useMemo( + () => ( { + baseId, + activeId, + setActiveId, + } ), + [ baseId, activeId, setActiveId ] + ); return ( <div className={ className }> - <CircularOptionPickerContext.Provider value={ compositeContext }> + <CircularOptionPickerContext.Provider value={ contextValue }> <Composite { ...additionalProps } id={ baseId } - store={ compositeStore } + focusLoop={ loop } + rtl={ isRTL() } role="listbox" + activeId={ activeId } + setActiveId={ setActiveId } > { options } </Composite> @@ -119,9 +125,16 @@ function ButtonsCircularOptionPicker( ) { const { actions, options, children, baseId, ...additionalProps } = props; + const contextValue = useMemo( + () => ( { + baseId, + } ), + [ baseId ] + ); + return ( <div { ...additionalProps } id={ baseId }> - <CircularOptionPickerContext.Provider value={ { baseId } }> + <CircularOptionPickerContext.Provider value={ contextValue }> { options } { children } { actions } diff --git a/packages/components/src/circular-option-picker/types.ts b/packages/components/src/circular-option-picker/types.ts index e23ff4165f0580..411782aed575b1 100644 --- a/packages/components/src/circular-option-picker/types.ts +++ b/packages/components/src/circular-option-picker/types.ts @@ -14,7 +14,6 @@ import type { Icon } from '@wordpress/icons'; import type { ButtonAsButtonProps } from '../button/types'; import type { DropdownProps } from '../dropdown/types'; import type { WordPressComponentProps } from '../context'; -import type { Composite } from '../composite'; type CommonCircularOptionPickerProps = { /** @@ -125,5 +124,6 @@ export type OptionProps = Omit< export type CircularOptionPickerContextProps = { baseId?: string; - compositeStore?: React.ComponentProps< typeof Composite >[ 'store' ]; + activeId?: string | null | undefined; + setActiveId?: ( newId: string | null | undefined ) => void; }; From 825cdacb91c4787da63a2572999d8d6c568aff5a Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 3 Sep 2024 00:06:18 +0900 Subject: [PATCH 0634/1908] Fix: Pagination arrows are pointing in the wrong direction in RTL languages (#64962) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- .../components/block-pattern-setup/setup-toolbar.js | 6 +++--- .../src/components/grid/grid-item-movers.js | 6 +++--- packages/block-library/src/navigation-link/link-ui.js | 6 +++--- .../src/components/dataviews-pagination/index.tsx | 6 +++--- .../global-styles/font-library-modal/font-card.js | 6 +++--- .../font-library-modal/font-collection.js | 10 ++++++---- .../font-library-modal/installed-fonts.js | 8 +++++--- packages/edit-site/src/components/pagination/index.js | 10 +++++----- 8 files changed, 31 insertions(+), 27 deletions(-) diff --git a/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js b/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js index 01272976adaafa..c551c2e1632bcf 100644 --- a/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js +++ b/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; +import { __, isRTL } from '@wordpress/i18n'; import { Button } from '@wordpress/components'; import { chevronRight, @@ -38,7 +38,7 @@ const CarouselNavigation = ( { <Button // TODO: Switch to `true` (40px size) if possible __next40pxDefaultSize={ false } - icon={ chevronLeft } + icon={ isRTL() ? chevronRight : chevronLeft } label={ __( 'Previous pattern' ) } onClick={ handlePrevious } disabled={ activeSlide === 0 } @@ -47,7 +47,7 @@ const CarouselNavigation = ( { <Button // TODO: Switch to `true` (40px size) if possible __next40pxDefaultSize={ false } - icon={ chevronRight } + icon={ isRTL() ? chevronLeft : chevronRight } label={ __( 'Next pattern' ) } onClick={ handleNext } disabled={ activeSlide === totalSlides - 1 } diff --git a/packages/block-editor/src/components/grid/grid-item-movers.js b/packages/block-editor/src/components/grid/grid-item-movers.js index fc9a3c5bf39955..a7f21181eb9a5f 100644 --- a/packages/block-editor/src/components/grid/grid-item-movers.js +++ b/packages/block-editor/src/components/grid/grid-item-movers.js @@ -6,7 +6,7 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; +import { __, isRTL } from '@wordpress/i18n'; import { VisuallyHidden, ToolbarButton, @@ -57,7 +57,7 @@ export function GridItemMovers( { <ToolbarGroup className="block-editor-grid-item-mover__move-button-container"> <div className="block-editor-grid-item-mover__move-horizontal-button-container is-left"> <GridItemMover - icon={ chevronLeft } + icon={ isRTL() ? chevronRight : chevronLeft } label={ __( 'Move left' ) } description={ __( 'Move left' ) } isDisabled={ columnStart <= 1 } @@ -126,7 +126,7 @@ export function GridItemMovers( { </div> <div className="block-editor-grid-item-mover__move-horizontal-button-container is-right"> <GridItemMover - icon={ chevronRight } + icon={ isRTL() ? chevronLeft : chevronRight } label={ __( 'Move right' ) } description={ __( 'Move right' ) } isDisabled={ columnCount && columnEnd >= columnCount } diff --git a/packages/block-library/src/navigation-link/link-ui.js b/packages/block-library/src/navigation-link/link-ui.js index fb3e6d40196127..1d303843644474 100644 --- a/packages/block-library/src/navigation-link/link-ui.js +++ b/packages/block-library/src/navigation-link/link-ui.js @@ -8,7 +8,7 @@ import { VisuallyHidden, __experimentalVStack as VStack, } from '@wordpress/components'; -import { __, sprintf } from '@wordpress/i18n'; +import { __, sprintf, isRTL } from '@wordpress/i18n'; import { __experimentalLinkControl as LinkControl, store as blockEditorStore, @@ -28,7 +28,7 @@ import { } from '@wordpress/core-data'; import { decodeEntities } from '@wordpress/html-entities'; import { useSelect, useDispatch } from '@wordpress/data'; -import { chevronLeftSmall, plus } from '@wordpress/icons'; +import { chevronLeftSmall, chevronRightSmall, plus } from '@wordpress/icons'; import { useInstanceId, useFocusOnMount } from '@wordpress/compose'; /** @@ -123,7 +123,7 @@ function LinkUIBlockInserter( { clientId, onBack, onSelectBlock } ) { <Button className="link-ui-block-inserter__back" - icon={ chevronLeftSmall } + icon={ isRTL() ? chevronRightSmall : chevronLeftSmall } onClick={ ( e ) => { e.preventDefault(); onBack(); diff --git a/packages/dataviews/src/components/dataviews-pagination/index.tsx b/packages/dataviews/src/components/dataviews-pagination/index.tsx index d2744b0c39bc0b..08a25ea01224e0 100644 --- a/packages/dataviews/src/components/dataviews-pagination/index.tsx +++ b/packages/dataviews/src/components/dataviews-pagination/index.tsx @@ -7,7 +7,7 @@ import { SelectControl, } from '@wordpress/components'; import { createInterpolateElement, memo, useContext } from '@wordpress/element'; -import { sprintf, __, _x } from '@wordpress/i18n'; +import { sprintf, __, _x, isRTL } from '@wordpress/i18n'; import { next, previous } from '@wordpress/icons'; /** @@ -103,7 +103,7 @@ function DataViewsPagination() { disabled={ currentPage === 1 } accessibleWhenDisabled label={ __( 'Previous page' ) } - icon={ previous } + icon={ isRTL() ? next : previous } showTooltip size="compact" tooltipPosition="top" @@ -115,7 +115,7 @@ function DataViewsPagination() { disabled={ currentPage >= totalPages } accessibleWhenDisabled label={ __( 'Next page' ) } - icon={ next } + icon={ isRTL() ? previous : next } showTooltip size="compact" tooltipPosition="top" diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js index 7ecfa431ac8d20..735179588d0723 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { _n, sprintf } from '@wordpress/i18n'; +import { _n, sprintf, isRTL } from '@wordpress/i18n'; import { __experimentalUseNavigator as useNavigator, __experimentalText as Text, @@ -15,7 +15,7 @@ import { * Internal dependencies */ import FontDemo from './font-demo'; -import { chevronRight } from '@wordpress/icons'; +import { chevronLeft, chevronRight } from '@wordpress/icons'; function FontCard( { font, onClick, variantsText, navigatorPath } ) { const variantsCount = font.fontFace?.length || 1; @@ -57,7 +57,7 @@ function FontCard( { font, onClick, variantsText, navigatorPath } ) { </Text> </FlexItem> <FlexItem> - <Icon icon={ chevronRight } /> + <Icon icon={ isRTL() ? chevronLeft : chevronRight } /> </FlexItem> </Flex> </Flex> diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js index 8c3140454b160b..f2184f7e406049 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js @@ -28,7 +28,7 @@ import { CheckboxControl, } from '@wordpress/components'; import { debounce } from '@wordpress/compose'; -import { sprintf, __, _x } from '@wordpress/i18n'; +import { sprintf, __, _x, isRTL } from '@wordpress/i18n'; import { moreVertical, chevronLeft, chevronRight } from '@wordpress/icons'; /** @@ -383,7 +383,9 @@ function FontCollection( { slug } ) { <NavigatorScreen path="/fontFamily"> <Flex justify="flex-start"> <NavigatorBackButton - icon={ chevronLeft } + icon={ + isRTL() ? chevronRight : chevronLeft + } size="small" onClick={ () => { setSelectedFont( null ); @@ -498,7 +500,7 @@ function FontCollection( { slug } ) { disabled={ page === 1 } showTooltip accessibleWhenDisabled - icon={ chevronLeft } + icon={ isRTL() ? chevronRight : chevronLeft } tooltipPosition="top" /> <HStack @@ -549,7 +551,7 @@ function FontCollection( { slug } ) { onClick={ () => setPage( page + 1 ) } disabled={ page === totalPages } accessibleWhenDisabled - icon={ chevronRight } + icon={ isRTL() ? chevronLeft : chevronRight } tooltipPosition="top" /> </HStack> diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js index b9042d0fe609f6..f42f71095420b5 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js @@ -21,8 +21,8 @@ import { import { useEntityRecord, store as coreStore } from '@wordpress/core-data'; import { useSelect } from '@wordpress/data'; import { useContext, useEffect, useState } from '@wordpress/element'; -import { __, _x, sprintf } from '@wordpress/i18n'; -import { chevronLeft } from '@wordpress/icons'; +import { __, _x, sprintf, isRTL } from '@wordpress/i18n'; +import { chevronLeft, chevronRight } from '@wordpress/icons'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; /** @@ -354,7 +354,9 @@ function InstalledFonts() { <Flex justify="flex-start"> <NavigatorBackButton - icon={ chevronLeft } + icon={ + isRTL() ? chevronRight : chevronLeft + } size="small" onClick={ () => { handleSetLibraryFontSelected( null ); diff --git a/packages/edit-site/src/components/pagination/index.js b/packages/edit-site/src/components/pagination/index.js index 66b89735b8cb47..8ef45883eb4524 100644 --- a/packages/edit-site/src/components/pagination/index.js +++ b/packages/edit-site/src/components/pagination/index.js @@ -11,7 +11,7 @@ import { __experimentalText as Text, Button, } from '@wordpress/components'; -import { __, _x, _n, sprintf } from '@wordpress/i18n'; +import { __, _x, _n, sprintf, isRTL } from '@wordpress/i18n'; import { previous, chevronLeft, chevronRight, next } from '@wordpress/icons'; export default function Pagination( { @@ -50,7 +50,7 @@ export default function Pagination( { accessibleWhenDisabled disabled={ disabled || currentPage === 1 } label={ __( 'First page' ) } - icon={ previous } + icon={ isRTL() ? next : previous } size="compact" /> <Button @@ -59,7 +59,7 @@ export default function Pagination( { accessibleWhenDisabled disabled={ disabled || currentPage === 1 } label={ __( 'Previous page' ) } - icon={ chevronLeft } + icon={ isRTL() ? chevronRight : chevronLeft } size="compact" /> </HStack> @@ -78,7 +78,7 @@ export default function Pagination( { accessibleWhenDisabled disabled={ disabled || currentPage === numPages } label={ __( 'Next page' ) } - icon={ chevronRight } + icon={ isRTL() ? chevronLeft : chevronRight } size="compact" /> <Button @@ -87,7 +87,7 @@ export default function Pagination( { accessibleWhenDisabled disabled={ disabled || currentPage === numPages } label={ __( 'Last page' ) } - icon={ next } + icon={ isRTL() ? previous : next } size="compact" /> </HStack> From dcfddbe8c53d8e6d41284afa09a35ca247ed7f93 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Tue, 3 Sep 2024 10:54:43 +1000 Subject: [PATCH 0635/1908] Relocate backport files for grid layout improvements (#64991). Moves the backport changelog file for https://github.com/WordPress/wordpress-develop/pull/6910 from the WordPress 6.7 directory to the WordPress 6.8 directory. These changes are now targeted for a future release and do not need to be merged in to WordPress 6.7 as part of the package update. See #57478. Co-authored-by: peterwilsoncc <peterwilsoncc@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> --- backport-changelog/{6.7 => 6.8}/6910.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename backport-changelog/{6.7 => 6.8}/6910.md (100%) diff --git a/backport-changelog/6.7/6910.md b/backport-changelog/6.8/6910.md similarity index 100% rename from backport-changelog/6.7/6910.md rename to backport-changelog/6.8/6910.md From a4f0acff0ec7adcd448ef2cb8bcdc44b278d9ebc Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 3 Sep 2024 07:15:12 +0400 Subject: [PATCH 0636/1908] Block Editor: Remove the Shuffle block toolbar button (#64954) * Block Editor: Remove the Shuffle block toolbar button * Remove unused 'rootClientId' selection Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- .../block-editor/src/components/block-toolbar/index.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 984670762262c9..13dfd6b33e56a6 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -34,7 +34,6 @@ import { useShowHoveredOrFocusedGestures } from './utils'; import { store as blockEditorStore } from '../../store'; import __unstableBlockNameContext from './block-name-context'; import NavigableToolbar from '../navigable-toolbar'; -import Shuffle from './shuffle'; import { useHasBlockToolbar } from './use-has-block-toolbar'; /** @@ -66,7 +65,6 @@ export function PrivateBlockToolbar( { shouldShowVisualToolbar, showParentSelector, isUsingBindings, - canRemove, } = useSelect( ( select ) => { const { getBlockName, @@ -74,14 +72,11 @@ export function PrivateBlockToolbar( { getBlockParents, getSelectedBlockClientIds, isBlockValid, - getBlockRootClientId, getBlockEditingMode, getBlockAttributes, - canRemoveBlock, } = select( blockEditorStore ); const selectedBlockClientIds = getSelectedBlockClientIds(); const selectedBlockClientId = selectedBlockClientIds[ 0 ]; - const blockRootClientId = getBlockRootClientId( selectedBlockClientId ); const parents = getBlockParents( selectedBlockClientId ); const firstParentClientId = parents[ parents.length - 1 ]; const parentBlockName = getBlockName( firstParentClientId ); @@ -106,7 +101,6 @@ export function PrivateBlockToolbar( { isDefaultEditingMode: _isDefaultEditingMode, blockType: selectedBlockClientId && getBlockType( _blockName ), shouldShowVisualToolbar: isValid && isVisual, - rootClientId: blockRootClientId, toolbarKey: `${ selectedBlockClientId }${ firstParentClientId }`, showParentSelector: parentBlockType && @@ -119,7 +113,6 @@ export function PrivateBlockToolbar( { selectedBlockClientIds.length === 1 && _isDefaultEditingMode, isUsingBindings: _isUsingBindings, - canRemove: canRemoveBlock( selectedBlockClientId ), }; }, [] ); @@ -202,9 +195,6 @@ export function PrivateBlockToolbar( { </ToolbarGroup> </div> ) } - { ! isMultiToolbar && canRemove && ( - <Shuffle clientId={ blockClientId } /> - ) } { shouldShowVisualToolbar && isMultiToolbar && ( <BlockGroupToolbar /> ) } From 9f4f79a963208aa7a95c41f9ca0118e66a891fb2 Mon Sep 17 00:00:00 2001 From: Robert Anderson <robert@noisysocks.com> Date: Tue, 3 Sep 2024 13:59:06 +1000 Subject: [PATCH 0637/1908] Use rectIntersect instead of a custom argument to rectUnion (#64855) * Use rectIntersect instead of a custom argument to rectUnion * Adjust left and right manually at end of getVisibleElementBounds Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-editor/src/utils/dom.js | 57 ++++++++++++-------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/packages/block-editor/src/utils/dom.js b/packages/block-editor/src/utils/dom.js index e41ade344e49d8..bfdce60b9f0060 100644 --- a/packages/block-editor/src/utils/dom.js +++ b/packages/block-editor/src/utils/dom.js @@ -59,35 +59,19 @@ export function getBlockClientId( node ) { } /** - * Calculates the union of two rectangles, and optionally constrains this union within a containerRect's - * left and right values. - * The function returns a new DOMRect object representing this union. + * Calculates the union of two rectangles. * - * @param {DOMRect} rect1 First rectangle. - * @param {DOMRect} rect2 Second rectangle. - * @param {DOMRectReadOnly?} containerRect An optional container rectangle. The union will be clipped to this rectangle. + * @param {DOMRect} rect1 First rectangle. + * @param {DOMRect} rect2 Second rectangle. * @return {DOMRect} Union of the two rectangles. */ -export function rectUnion( rect1, rect2, containerRect ) { - let left = Math.min( rect1.left, rect2.left ); - let right = Math.max( rect1.right, rect2.right ); +export function rectUnion( rect1, rect2 ) { + const left = Math.min( rect1.left, rect2.left ); + const right = Math.max( rect1.right, rect2.right ); const bottom = Math.max( rect1.bottom, rect2.bottom ); const top = Math.min( rect1.top, rect2.top ); - /* - * To calculate visible bounds using rectUnion, take into account the outer - * horizontal limits of the container in which an element is supposed to be "visible". - * For example, if an element is positioned -10px to the left of the window x value (0), - * this function discounts the negative overhang because it's not visible and - * therefore not to be counted in the visibility calculations. - * Top and bottom values are not accounted for to accommodate vertical scroll. - */ - if ( containerRect ) { - left = Math.max( left, containerRect.left ); - right = Math.min( right, containerRect.right ); - } - - return new window.DOMRect( left, top, right - left, bottom - top ); + return new window.DOMRectReadOnly( left, top, right - left, bottom - top ); } /** @@ -138,16 +122,10 @@ function isElementVisible( element ) { export function getVisibleElementBounds( element ) { const viewport = element.ownerDocument.defaultView; if ( ! viewport ) { - return new window.DOMRect(); + return new window.DOMRectReadOnly(); } let bounds = element.getBoundingClientRect(); - const viewportRect = new window.DOMRectReadOnly( - 0, - 0, - viewport.innerWidth, - viewport.innerHeight - ); const stack = [ element ]; let currentElement; @@ -156,11 +134,28 @@ export function getVisibleElementBounds( element ) { for ( const child of currentElement.children ) { if ( isElementVisible( child ) ) { const childBounds = child.getBoundingClientRect(); - bounds = rectUnion( bounds, childBounds, viewportRect ); + bounds = rectUnion( bounds, childBounds ); stack.push( child ); } } } + /* + * Take into account the outer horizontal limits of the container in which + * an element is supposed to be "visible". For example, if an element is + * positioned -10px to the left of the window x value (0), this function + * discounts the negative overhang because it's not visible and therefore + * not to be counted in the visibility calculations. Top and bottom values + * are not accounted for to accommodate vertical scroll. + */ + const left = Math.max( bounds.left, 0 ); + const right = Math.min( bounds.right, viewport.innerWidth ); + bounds = new window.DOMRectReadOnly( + left, + bounds.top, + right - left, + bounds.height + ); + return bounds; } From 5109d5ba18b0fbb33ffd2c61c7793c16a5b31a58 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Tue, 3 Sep 2024 10:53:11 +0530 Subject: [PATCH 0638/1908] Site Logo: Fix loader alignment issue (#64919) * Fix loader alignment issue in site logo block * Update isLoading check Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/block-library/src/site-logo/edit.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index 81217e6cb5135f..edf8bbccfeb652 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -654,16 +654,17 @@ export default function LogoEdit( { { controls } { mediaInspectorPanel } { ( !! logoUrl || !! temporaryURL ) && logoImage } - { ! temporaryURL && ! logoUrl && ! canUserEdit && ( - <Placeholder className="site-logo_placeholder"> - { !! isLoading && ( + { ( isLoading || + ( ! temporaryURL && ! logoUrl && ! canUserEdit ) ) && ( + <Placeholder className="site-logo_placeholder" withIllustration> + { isLoading && ( <span className="components-placeholder__preview"> <Spinner /> </span> ) } </Placeholder> ) } - { ! temporaryURL && ! logoUrl && canUserEdit && ( + { ! isLoading && ! temporaryURL && ! logoUrl && canUserEdit && ( <MediaPlaceholder onSelect={ onInitialSelectLogo } accept={ ACCEPT_MEDIA_STRING } From 30258b51228b78f8973c32a86148d7c66e470b7d Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 3 Sep 2024 08:19:44 +0200 Subject: [PATCH 0639/1908] Block Patterns List: do not use Composite store (#64983) --- .../components/block-patterns-list/index.js | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/packages/block-editor/src/components/block-patterns-list/index.js b/packages/block-editor/src/components/block-patterns-list/index.js index b2af3456be7b0c..47deb777a84aab 100644 --- a/packages/block-editor/src/components/block-patterns-list/index.js +++ b/packages/block-editor/src/components/block-patterns-list/index.js @@ -27,11 +27,9 @@ import InserterDraggableBlocks from '../inserter-draggable-blocks'; import BlockPatternsPaging from '../block-patterns-paging'; import { INSERTER_PATTERN_TYPES } from '../inserter/block-patterns-tab/utils'; -const { - CompositeV2: Composite, - CompositeItemV2: CompositeItem, - useCompositeStoreV2: useCompositeStore, -} = unlock( componentsPrivateApis ); +const { CompositeV2: Composite, CompositeItemV2: CompositeItem } = unlock( + componentsPrivateApis +); const WithToolTip = ( { showTooltip, title, children } ) => { if ( showTooltip ) { @@ -206,19 +204,23 @@ function BlockPatternsList( }, ref ) { - const compositeStore = useCompositeStore( { orientation } ); - const { setActiveId } = compositeStore; + const [ activeCompositeId, setActiveCompositeId ] = useState( undefined ); useEffect( () => { - // We reset the active composite item whenever the - // available patterns change, to make sure that - // focus is put back to the start. - setActiveId( undefined ); - }, [ setActiveId, shownPatterns, blockPatterns ] ); + // Reset the active composite item whenever the available patterns change, + // to make sure that Composite widget can receive focus correctly when its + // composite items change. The first composite item will receive focus. + const firstCompositeItemId = blockPatterns.find( ( pattern ) => + shownPatterns.includes( pattern ) + )?.name; + setActiveCompositeId( firstCompositeItemId ); + }, [ shownPatterns, blockPatterns ] ); return ( <Composite - store={ compositeStore } + orientation={ orientation } + activeId={ activeCompositeId } + setActiveId={ setActiveCompositeId } role="listbox" className="block-editor-block-patterns-list" aria-label={ label } From 6058323845a92811293a613c88a7d874c7aa5622 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Tue, 3 Sep 2024 10:26:57 +0200 Subject: [PATCH 0640/1908] Layout content and wide width controls: remove confusing icon and clarify labels (#64891) * Remove confusing icons. * Used 40px input size. * Improve content and wide widths labeling. * Remove confusing icons from block settings constrained layout widths. * Try icons in input prefix. * Adjust vertical spacing. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> --- .../global-styles/dimensions-panel.js | 79 +++++++------- packages/block-editor/src/hooks/layout.scss | 14 +-- .../block-editor/src/layouts/constrained.js | 101 +++++++++--------- 3 files changed, 89 insertions(+), 105 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/dimensions-panel.js b/packages/block-editor/src/components/global-styles/dimensions-panel.js index 241d3bb93d1b13..8430703aec966d 100644 --- a/packages/block-editor/src/components/global-styles/dimensions-panel.js +++ b/packages/block-editor/src/components/global-styles/dimensions-panel.js @@ -11,12 +11,11 @@ import { __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, __experimentalBoxControl as BoxControl, - __experimentalHStack as HStack, __experimentalUnitControl as UnitControl, __experimentalUseCustomUnits as useCustomUnits, - __experimentalView as View, + __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper, } from '@wordpress/components'; -import { Icon, positionCenter, stretchWide } from '@wordpress/icons'; +import { Icon, alignNone, stretchWide } from '@wordpress/icons'; import { useCallback, useState, Platform } from '@wordpress/element'; /** @@ -252,7 +251,7 @@ export default function DimensionsPanel( { const minimumMargin = -Infinity; const [ minMarginValue, setMinMarginValue ] = useState( minimumMargin ); - // Content Size + // Content Width const showContentSizeControl = useHasContentSize( settings ) && includeLayoutControls; const contentSizeValue = decodeValue( inheritedValue?.layout?.contentSize ); @@ -268,7 +267,7 @@ export default function DimensionsPanel( { const hasUserSetContentSizeValue = () => !! value?.layout?.contentSize; const resetContentSizeValue = () => setContentSizeValue( undefined ); - // Wide Size + // Wide Width const showWideSizeControl = useHasWideSize( settings ) && includeLayoutControls; const wideSizeValue = decodeValue( inheritedValue?.layout?.wideSize ); @@ -464,8 +463,7 @@ export default function DimensionsPanel( { ) } { showContentSizeControl && ( <ToolsPanelItem - className="single-column" - label={ __( 'Content size' ) } + label={ __( 'Content width' ) } hasValue={ hasUserSetContentSizeValue } onDeselect={ resetContentSizeValue } isShownByDefault={ @@ -474,29 +472,26 @@ export default function DimensionsPanel( { } panelId={ panelId } > - <HStack alignment="flex-end" justify="flex-start"> - <UnitControl - // TODO: Switch to `true` (40px size) if possible (https://github.com/WordPress/gutenberg/pull/64520#discussion_r1717314262) - __next40pxDefaultSize={ false } - label={ __( 'Content' ) } - labelPosition="top" - __unstableInputWidth="80px" - value={ contentSizeValue || '' } - onChange={ ( nextContentSize ) => { - setContentSizeValue( nextContentSize ); - } } - units={ units } - /> - <View> - <Icon icon={ positionCenter } /> - </View> - </HStack> + <UnitControl + __next40pxDefaultSize + label={ __( 'Content width' ) } + labelPosition="top" + value={ contentSizeValue || '' } + onChange={ ( nextContentSize ) => { + setContentSizeValue( nextContentSize ); + } } + units={ units } + prefix={ + <InputControlPrefixWrapper variant="icon"> + <Icon icon={ alignNone } /> + </InputControlPrefixWrapper> + } + /> </ToolsPanelItem> ) } { showWideSizeControl && ( <ToolsPanelItem - className="single-column" - label={ __( 'Wide size' ) } + label={ __( 'Wide width' ) } hasValue={ hasUserSetWideSizeValue } onDeselect={ resetWideSizeValue } isShownByDefault={ @@ -504,23 +499,21 @@ export default function DimensionsPanel( { } panelId={ panelId } > - <HStack alignment="flex-end" justify="flex-start"> - <UnitControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - label={ __( 'Wide' ) } - labelPosition="top" - __unstableInputWidth="80px" - value={ wideSizeValue || '' } - onChange={ ( nextWideSize ) => { - setWideSizeValue( nextWideSize ); - } } - units={ units } - /> - <View> - <Icon icon={ stretchWide } /> - </View> - </HStack> + <UnitControl + __next40pxDefaultSize + label={ __( 'Wide width' ) } + labelPosition="top" + value={ wideSizeValue || '' } + onChange={ ( nextWideSize ) => { + setWideSizeValue( nextWideSize ); + } } + units={ units } + prefix={ + <InputControlPrefixWrapper variant="icon"> + <Icon icon={ stretchWide } /> + </InputControlPrefixWrapper> + } + /> </ToolsPanelItem> ) } { showPaddingControl && ( diff --git a/packages/block-editor/src/hooks/layout.scss b/packages/block-editor/src/hooks/layout.scss index 83a044e3cdca75..3eedd1f629a633 100644 --- a/packages/block-editor/src/hooks/layout.scss +++ b/packages/block-editor/src/hooks/layout.scss @@ -1,15 +1,7 @@ -.block-editor-hooks__layout-controls { +.block-editor-hooks__layout-controls-units { display: flex; - margin-bottom: $grid-unit-10; - - .block-editor-hooks__layout-controls-unit { - display: flex; - margin-right: $grid-unit-30; - - svg { - margin: auto 0 $grid-unit-05 $grid-unit-10; - } - } + flex-direction: column; + gap: $grid-unit-20; } .block-editor-block-inspector .block-editor-hooks__layout-controls-unit-input { diff --git a/packages/block-editor/src/layouts/constrained.js b/packages/block-editor/src/layouts/constrained.js index b8dcde637a4d30..21aca422a315ff 100644 --- a/packages/block-editor/src/layouts/constrained.js +++ b/packages/block-editor/src/layouts/constrained.js @@ -6,11 +6,12 @@ import { __experimentalUnitControl as UnitControl, __experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, + __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { Icon, - positionCenter, + alignNone, stretchWide, justifyLeft, justifyCenter, @@ -71,61 +72,59 @@ export default { return ( <> { allowCustomContentAndWideSize && ( - <> - <div className="block-editor-hooks__layout-controls"> - <div className="block-editor-hooks__layout-controls-unit"> - <UnitControl - // TODO: Switch to `true` (40px size) if possible (https://github.com/WordPress/gutenberg/pull/64520#discussion_r1717314262) - __next40pxDefaultSize={ false } - className="block-editor-hooks__layout-controls-unit-input" - label={ __( 'Content' ) } - labelPosition="top" - __unstableInputWidth="80px" - value={ contentSize || wideSize || '' } - onChange={ ( nextWidth ) => { - nextWidth = - 0 > parseFloat( nextWidth ) - ? '0' - : nextWidth; - onChange( { - ...layout, - contentSize: nextWidth, - } ); - } } - units={ units } - /> - <Icon icon={ positionCenter } /> - </div> - <div className="block-editor-hooks__layout-controls-unit"> - <UnitControl - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - className="block-editor-hooks__layout-controls-unit-input" - label={ __( 'Wide' ) } - labelPosition="top" - __unstableInputWidth="80px" - value={ wideSize || contentSize || '' } - onChange={ ( nextWidth ) => { - nextWidth = - 0 > parseFloat( nextWidth ) - ? '0' - : nextWidth; - onChange( { - ...layout, - wideSize: nextWidth, - } ); - } } - units={ units } - /> - <Icon icon={ stretchWide } /> - </div> - </div> + <div className="block-editor-hooks__layout-controls-units"> + <UnitControl + __next40pxDefaultSize + className="block-editor-hooks__layout-controls-unit-input" + label={ __( 'Content width' ) } + labelPosition="top" + value={ contentSize || wideSize || '' } + onChange={ ( nextWidth ) => { + nextWidth = + 0 > parseFloat( nextWidth ) + ? '0' + : nextWidth; + onChange( { + ...layout, + contentSize: nextWidth, + } ); + } } + units={ units } + prefix={ + <InputControlPrefixWrapper variant="icon"> + <Icon icon={ alignNone } /> + </InputControlPrefixWrapper> + } + /> + <UnitControl + __next40pxDefaultSize + className="block-editor-hooks__layout-controls-unit-input" + label={ __( 'Wide width' ) } + labelPosition="top" + value={ wideSize || contentSize || '' } + onChange={ ( nextWidth ) => { + nextWidth = + 0 > parseFloat( nextWidth ) + ? '0' + : nextWidth; + onChange( { + ...layout, + wideSize: nextWidth, + } ); + } } + units={ units } + prefix={ + <InputControlPrefixWrapper variant="icon"> + <Icon icon={ stretchWide } /> + </InputControlPrefixWrapper> + } + /> <p className="block-editor-hooks__layout-controls-helptext"> { __( 'Customize the width for all elements that are assigned to the center or wide columns.' ) } </p> - </> + </div> ) } { allowJustification && ( <ToggleGroupControl From cdc5b49de6159f2c76b92819a09a0670d5d257a7 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Tue, 3 Sep 2024 12:03:02 +0200 Subject: [PATCH 0641/1908] Try: Update block warnings. (#64997) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> --- .../components/block-list/block-invalid-warning.js | 4 ++-- .../block-editor/src/components/warning/content.scss | 11 ++--------- packages/block-library/src/missing/edit.js | 4 ++-- test/e2e/specs/editor/various/invalid-block.spec.js | 2 +- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/packages/block-editor/src/components/block-list/block-invalid-warning.js b/packages/block-editor/src/components/block-list/block-invalid-warning.js index 42ec5f9deb84d0..fb235cbce9ca21 100644 --- a/packages/block-editor/src/components/block-list/block-invalid-warning.js +++ b/packages/block-editor/src/components/block-list/block-invalid-warning.js @@ -107,12 +107,12 @@ export default function BlockInvalidWarning( { clientId } ) { onClick={ convert.toRecoveredBlock } variant="primary" > - { __( 'Attempt Block Recovery' ) } + { __( 'Attempt recovery' ) } </Button>, ] } secondaryActions={ secondaryActions } > - { __( 'This block contains unexpected or invalid content.' ) } + { __( 'Block contains unexpected or invalid content.' ) } </Warning> { compare && ( <Modal diff --git a/packages/block-editor/src/components/warning/content.scss b/packages/block-editor/src/components/warning/content.scss index f4eeb253c1c2fb..0c1185a0782e41 100644 --- a/packages/block-editor/src/components/warning/content.scss +++ b/packages/block-editor/src/components/warning/content.scss @@ -30,21 +30,14 @@ flex-wrap: wrap; align-items: baseline; width: 100%; + gap: $grid-unit-15; } .block-editor-warning__actions { align-items: center; display: flex; - margin-top: 1em; + gap: $grid-unit-10; } - - .block-editor-warning__action { - margin: 0 $grid-unit-10 0 0; - } -} - -.block-editor-warning__secondary { - margin: auto 0 auto $grid-unit-10; } .components-popover.block-editor-warning__dropdown { diff --git a/packages/block-library/src/missing/edit.js b/packages/block-library/src/missing/edit.js index 9fb507794756f8..70b032cb9a2fe8 100644 --- a/packages/block-library/src/missing/edit.js +++ b/packages/block-library/src/missing/edit.js @@ -75,7 +75,7 @@ export default function MissingEdit( { attributes, clientId } ) { messageHTML = sprintf( /* translators: %s: block name */ __( - 'Your site doesn’t include support for the "%s" block. You can leave this block intact, convert its content to a Custom HTML block, or remove it entirely.' + 'Your site doesn’t include support for the "%s" block. You can leave it as-is, convert it to custom HTML, or remove it.' ), originalName ); @@ -84,7 +84,7 @@ export default function MissingEdit( { attributes, clientId } ) { messageHTML = sprintf( /* translators: %s: block name */ __( - 'Your site doesn’t include support for the "%s" block. You can leave this block intact or remove it entirely.' + 'Your site doesn’t include support for the "%s" block. You can leave it as-is or remove it.' ), originalName ); diff --git a/test/e2e/specs/editor/various/invalid-block.spec.js b/test/e2e/specs/editor/various/invalid-block.spec.js index 07c04a5a55457e..3487c326d2851f 100644 --- a/test/e2e/specs/editor/various/invalid-block.spec.js +++ b/test/e2e/specs/editor/various/invalid-block.spec.js @@ -81,7 +81,7 @@ test.describe( 'Invalid blocks', () => { await expect( editor.canvas .getByRole( 'document', { name: 'Block: Paragraph' } ) - .getByRole( 'button', { name: 'Attempt Block Recovery' } ) + .getByRole( 'button', { name: 'Attempt recovery' } ) ).toBeVisible(); expect( hasAlert ).toBe( false ); From 7bd8f8e0256cb106066faa1af9e582cb47e265aa Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Tue, 3 Sep 2024 12:42:13 +0200 Subject: [PATCH 0642/1908] Fix the post summary Status toggle button accessibility (#63988) * Fix Change status label. * Add missing aria-expanded attribute to Status setting. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/editor/src/components/post-status/index.js | 5 +++-- test/e2e/specs/editor/various/change-detection.spec.js | 4 +--- test/e2e/specs/editor/various/post-visibility.spec.js | 6 ++---- test/e2e/specs/editor/various/preview.spec.js | 4 +--- test/e2e/specs/editor/various/switch-to-draft.spec.js | 2 +- 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/packages/editor/src/components/post-status/index.js b/packages/editor/src/components/post-status/index.js index ca89e40366b238..1d3050e7e3dd6b 100644 --- a/packages/editor/src/components/post-status/index.js +++ b/packages/editor/src/components/post-status/index.js @@ -171,7 +171,7 @@ export default function PostStatus() { contentClassName="editor-change-status__content" popoverProps={ popoverProps } focusOnMount - renderToggle={ ( { onToggle } ) => ( + renderToggle={ ( { onToggle, isOpen } ) => ( <Button variant="tertiary" size="compact" @@ -179,9 +179,10 @@ export default function PostStatus() { icon={ postStatusesInfo[ status ]?.icon } aria-label={ sprintf( // translators: %s: Current post status. - __( 'Change post status: %s' ), + __( 'Change status: %s' ), postStatusesInfo[ status ]?.label ) } + aria-expanded={ isOpen } > { postStatusesInfo[ status ]?.label } </Button> diff --git a/test/e2e/specs/editor/various/change-detection.spec.js b/test/e2e/specs/editor/various/change-detection.spec.js index 30b2287a8d9439..12d13b4890e368 100644 --- a/test/e2e/specs/editor/various/change-detection.spec.js +++ b/test/e2e/specs/editor/various/change-detection.spec.js @@ -80,9 +80,7 @@ test.describe( 'Change detection', () => { // Toggle post as needing review (not persisted for autosave). await editor.openDocumentSettingsSidebar(); - await page - .getByRole( 'button', { name: 'Change post status:' } ) - .click(); + await page.getByRole( 'button', { name: 'Change status:' } ).click(); await page.getByRole( 'radio', { name: 'Pending' } ).click(); // Force autosave to occur immediately. await Promise.all( [ diff --git a/test/e2e/specs/editor/various/post-visibility.spec.js b/test/e2e/specs/editor/various/post-visibility.spec.js index 61cd5e65f01015..67c8597953815b 100644 --- a/test/e2e/specs/editor/various/post-visibility.spec.js +++ b/test/e2e/specs/editor/various/post-visibility.spec.js @@ -18,7 +18,7 @@ test.describe( 'Post visibility', () => { await editor.openDocumentSettingsSidebar(); await page - .getByRole( 'button', { name: 'Change post status:' } ) + .getByRole( 'button', { name: 'Change status:' } ) .click(); await page.getByRole( 'radio', { name: 'Private' } ).click(); @@ -57,9 +57,7 @@ test.describe( 'Post visibility', () => { name: 'Close', } ) .click(); - await page - .getByRole( 'button', { name: 'Change post status:' } ) - .click(); + await page.getByRole( 'button', { name: 'Change status:' } ).click(); await page.getByRole( 'radio', { name: 'Private' } ).click(); await page .getByRole( 'region', { name: 'Editor top bar' } ) diff --git a/test/e2e/specs/editor/various/preview.spec.js b/test/e2e/specs/editor/various/preview.spec.js index b25d1da48122ce..e15f143983b742 100644 --- a/test/e2e/specs/editor/various/preview.spec.js +++ b/test/e2e/specs/editor/various/preview.spec.js @@ -183,9 +183,7 @@ test.describe( 'Preview', () => { // Return to editor and switch to Draft. await editorPage.bringToFront(); - await page - .getByRole( 'button', { name: 'Change post status:' } ) - .click(); + await page.getByRole( 'button', { name: 'Change status:' } ).click(); await page.getByRole( 'radio', { name: 'Draft' } ).click(); await page .getByRole( 'region', { name: 'Editor top bar' } ) diff --git a/test/e2e/specs/editor/various/switch-to-draft.spec.js b/test/e2e/specs/editor/various/switch-to-draft.spec.js index 516de6d0c85cc5..81652d9c11e2bb 100644 --- a/test/e2e/specs/editor/various/switch-to-draft.spec.js +++ b/test/e2e/specs/editor/various/switch-to-draft.spec.js @@ -47,7 +47,7 @@ test.describe( 'Clicking "Switch to draft" on a published/scheduled post/page', await editor.openDocumentSettingsSidebar(); await page - .getByRole( 'button', { name: 'Change post status:' } ) + .getByRole( 'button', { name: 'Change status:' } ) .click(); await page.getByRole( 'radio', { name: 'Draft' } ).click(); From 9c625558d034de78768df74a8c922430db19d83b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 3 Sep 2024 13:05:19 +0200 Subject: [PATCH 0643/1908] DataViews: add story about combining fields (#64984) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../components/dataviews/stories/fixtures.js | 261 ------- .../components/dataviews/stories/fixtures.tsx | 690 ++++++++++++++++++ .../dataviews/stories/index.story.js | 111 --- .../dataviews/stories/index.story.tsx | 164 +++++ 4 files changed, 854 insertions(+), 372 deletions(-) delete mode 100644 packages/dataviews/src/components/dataviews/stories/fixtures.js create mode 100644 packages/dataviews/src/components/dataviews/stories/fixtures.tsx delete mode 100644 packages/dataviews/src/components/dataviews/stories/index.story.js create mode 100644 packages/dataviews/src/components/dataviews/stories/index.story.tsx diff --git a/packages/dataviews/src/components/dataviews/stories/fixtures.js b/packages/dataviews/src/components/dataviews/stories/fixtures.js deleted file mode 100644 index 14c9718a50d76b..00000000000000 --- a/packages/dataviews/src/components/dataviews/stories/fixtures.js +++ /dev/null @@ -1,261 +0,0 @@ -/** - * WordPress dependencies - */ -import { trash, image, Icon, category } from '@wordpress/icons'; -import { - Button, - __experimentalText as Text, - __experimentalHStack as HStack, - __experimentalVStack as VStack, -} from '@wordpress/components'; - -/** - * Internal dependencies - */ -import { LAYOUT_TABLE } from '../../../constants'; - -export const data = [ - { - id: 1, - title: 'Apollo', - description: 'Apollo description', - image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', - type: 'Not a planet', - categories: [ 'Space', 'NASA' ], - satellites: 0, - date: '2021-01-01T00:00:00Z', - }, - { - id: 2, - title: 'Space', - description: 'Space description', - image: 'https://live.staticflickr.com/5678/21911065441_92e2d44708_b.jpg', - type: 'Not a planet', - categories: [ 'Space' ], - satellites: 0, - date: '2019-01-02T00:00:00Z', - }, - { - id: 3, - title: 'NASA', - description: 'NASA photo', - image: 'https://live.staticflickr.com/742/21712365770_8f70a2c91e_b.jpg', - type: 'Not a planet', - categories: [ 'NASA' ], - satellites: 0, - date: '2025-01-03T00:00:00Z', - }, - { - id: 4, - title: 'Neptune', - description: 'Neptune description', - image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', - type: 'Ice giant', - categories: [ 'Space', 'Planet', 'Solar system' ], - satellites: 14, - date: '2020-01-01T00:00:00Z', - }, - { - id: 5, - title: 'Mercury', - description: 'Mercury description', - image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', - type: 'Terrestrial', - categories: [ 'Space', 'Planet', 'Solar system' ], - satellites: 0, - date: '2020-01-02T01:00:00Z', - }, - { - id: 6, - title: 'Venus', - description: 'La planète Vénus', - image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', - type: 'Terrestrial', - categories: [ 'Space', 'Planet', 'Solar system' ], - satellites: 0, - date: '2020-01-02T00:00:00Z', - }, - { - id: 7, - title: 'Earth', - description: 'Earth description', - image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', - type: 'Terrestrial', - categories: [ 'Space', 'Planet', 'Solar system' ], - satellites: 1, - date: '2023-01-03T00:00:00Z', - }, - { - id: 8, - title: 'Mars', - description: 'Mars description', - image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', - type: 'Terrestrial', - categories: [ 'Space', 'Planet', 'Solar system' ], - satellites: 2, - date: '2020-01-01T00:00:00Z', - }, - { - id: 9, - title: 'Jupiter', - description: 'Jupiter description', - image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', - type: 'Gas giant', - categories: [ 'Space', 'Planet', 'Solar system' ], - satellites: 95, - date: '2017-01-01T00:01:00Z', - }, - { - id: 10, - title: 'Saturn', - description: 'Saturn description', - image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', - type: 'Gas giant', - categories: [ 'Space', 'Planet', 'Solar system' ], - satellites: 146, - date: '2020-02-01T00:02:00Z', - }, - { - id: 11, - title: 'Uranus', - description: 'Uranus description', - image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', - type: 'Ice giant', - categories: [ 'Space', 'Ice giant', 'Solar system' ], - satellites: 28, - date: '2020-03-01T00:00:00Z', - }, -]; - -export const DEFAULT_VIEW = { - type: LAYOUT_TABLE, - search: '', - page: 1, - perPage: 10, - fields: [ 'title', 'description', 'categories' ], - layout: {}, - filters: [], -}; - -export const actions = [ - { - id: 'delete', - label: 'Delete item', - isPrimary: true, - icon: trash, - hideModalHeader: true, - RenderModal: ( { items, closeModal } ) => { - return ( - <VStack spacing="5"> - <Text> - { `Are you sure you want to delete "${ items[ 0 ].title }"?` } - </Text> - <HStack justify="right"> - <Button - __next40pxDefaultSize - variant="tertiary" - onClick={ closeModal } - > - Cancel - </Button> - <Button - __next40pxDefaultSize - variant="primary" - onClick={ closeModal } - > - Delete - </Button> - </HStack> - </VStack> - ); - }, - }, - { - id: 'secondary', - label: 'Secondary action', - callback() {}, - }, -]; - -export const fields = [ - { - label: 'Image', - id: 'image', - header: ( - <HStack spacing={ 1 } justify="start"> - <Icon icon={ image } /> - <span>Image</span> - </HStack> - ), - render: ( { item } ) => { - return ( - <img src={ item.image } alt="" style={ { width: '100%' } } /> - ); - }, - enableSorting: false, - }, - { - label: 'Title', - id: 'title', - enableHiding: false, - enableGlobalSearch: true, - render: ( { item } ) => { - return <a href="#nothing">{ item.title }</a>; - }, - }, - { - id: 'date', - label: 'Date', - type: 'datetime', - }, - { - label: 'Type', - id: 'type', - enableHiding: false, - elements: [ - { value: 'Not a planet', label: 'Not a planet' }, - { value: 'Ice giant', label: 'Ice giant' }, - { value: 'Terrestrial', label: 'Terrestrial' }, - { value: 'Gas giant', label: 'Gas giant' }, - ], - }, - { - label: 'Satellites', - id: 'satellites', - type: 'integer', - enableSorting: true, - }, - { - label: 'Description', - id: 'description', - enableSorting: false, - enableGlobalSearch: true, - }, - { - label: 'Categories', - id: 'categories', - header: ( - <HStack spacing={ 1 } justify="start"> - <Icon icon={ category } /> - <span>Categories</span> - </HStack> - ), - elements: [ - { value: 'Space', label: 'Space' }, - { value: 'NASA', label: 'NASA' }, - { value: 'Planet', label: 'Planet' }, - { value: 'Solar system', label: 'Solar system' }, - { value: 'Ice giant', label: 'Ice giant' }, - ], - filterBy: { - operators: [ 'isAny', 'isNone', 'isAll', 'isNotAll' ], - }, - getValue: ( { item } ) => { - return item.categories; - }, - render: ( { item } ) => { - return item.categories.join( ',' ); - }, - enableSorting: false, - }, -]; diff --git a/packages/dataviews/src/components/dataviews/stories/fixtures.tsx b/packages/dataviews/src/components/dataviews/stories/fixtures.tsx new file mode 100644 index 00000000000000..2ab02ec728e5e0 --- /dev/null +++ b/packages/dataviews/src/components/dataviews/stories/fixtures.tsx @@ -0,0 +1,690 @@ +/** + * WordPress dependencies + */ +import { trash, image, Icon, category } from '@wordpress/icons'; +import { + Button, + __experimentalText as Text, + __experimentalHStack as HStack, + __experimentalVStack as VStack, +} from '@wordpress/components'; + +/** + * Internal dependencies + */ +import type { Field, Action } from '../../../types'; + +export type Theme = { + slug: string; + name: string; + description: string; + requires: string; + tested: string; + tags: string[]; +}; + +export type SpaceObject = { + id: number; + title: string; + description: string; + image: string; + type: string; + categories: string[]; + satellites: number; + date: string; +}; + +export const data: SpaceObject[] = [ + { + id: 1, + title: 'Apollo', + description: 'Apollo description', + image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', + type: 'Not a planet', + categories: [ 'Space', 'NASA' ], + satellites: 0, + date: '2021-01-01T00:00:00Z', + }, + { + id: 2, + title: 'Space', + description: 'Space description', + image: 'https://live.staticflickr.com/5678/21911065441_92e2d44708_b.jpg', + type: 'Not a planet', + categories: [ 'Space' ], + satellites: 0, + date: '2019-01-02T00:00:00Z', + }, + { + id: 3, + title: 'NASA', + description: 'NASA photo', + image: 'https://live.staticflickr.com/742/21712365770_8f70a2c91e_b.jpg', + type: 'Not a planet', + categories: [ 'NASA' ], + satellites: 0, + date: '2025-01-03T00:00:00Z', + }, + { + id: 4, + title: 'Neptune', + description: 'Neptune description', + image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', + type: 'Ice giant', + categories: [ 'Space', 'Planet', 'Solar system' ], + satellites: 14, + date: '2020-01-01T00:00:00Z', + }, + { + id: 5, + title: 'Mercury', + description: 'Mercury description', + image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', + type: 'Terrestrial', + categories: [ 'Space', 'Planet', 'Solar system' ], + satellites: 0, + date: '2020-01-02T01:00:00Z', + }, + { + id: 6, + title: 'Venus', + description: 'La planète Vénus', + image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', + type: 'Terrestrial', + categories: [ 'Space', 'Planet', 'Solar system' ], + satellites: 0, + date: '2020-01-02T00:00:00Z', + }, + { + id: 7, + title: 'Earth', + description: 'Earth description', + image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', + type: 'Terrestrial', + categories: [ 'Space', 'Planet', 'Solar system' ], + satellites: 1, + date: '2023-01-03T00:00:00Z', + }, + { + id: 8, + title: 'Mars', + description: 'Mars description', + image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', + type: 'Terrestrial', + categories: [ 'Space', 'Planet', 'Solar system' ], + satellites: 2, + date: '2020-01-01T00:00:00Z', + }, + { + id: 9, + title: 'Jupiter', + description: 'Jupiter description', + image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', + type: 'Gas giant', + categories: [ 'Space', 'Planet', 'Solar system' ], + satellites: 95, + date: '2017-01-01T00:01:00Z', + }, + { + id: 10, + title: 'Saturn', + description: 'Saturn description', + image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', + type: 'Gas giant', + categories: [ 'Space', 'Planet', 'Solar system' ], + satellites: 146, + date: '2020-02-01T00:02:00Z', + }, + { + id: 11, + title: 'Uranus', + description: 'Uranus description', + image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg', + type: 'Ice giant', + categories: [ 'Space', 'Ice giant', 'Solar system' ], + satellites: 28, + date: '2020-03-01T00:00:00Z', + }, +]; + +export const themeData: Theme[] = [ + { + slug: 'twentyeleven', + name: 'Twenty Eleven', + description: + 'The 2011 theme for WordPress is sophisticated, lightweight, and adaptable. Make it yours with a custom menu, header image, and background -- then go further with available theme options for light or dark color scheme, custom link colors, and three layout choices. Twenty Eleven comes equipped with a Showcase page template that transforms your front page into a showcase to show off your best content, widget support galore (sidebar, three footer areas, and a Showcase page widget area), and a custom "Ephemera" widget to display your Aside, Link, Quote, or Status posts. Included are styles for print and for the admin editor, support for featured images (as custom header images on posts and pages and as large images on featured "sticky" posts), and special styles for six different post formats.', + requires: '3.2', + tested: '6.6', + tags: [ + 'blog', + 'one-column', + 'two-columns', + 'left-sidebar', + 'right-sidebar', + 'custom-background', + 'custom-colors', + 'custom-header', + 'custom-menu', + 'editor-style', + 'featured-image-header', + 'featured-images', + 'flexible-header', + 'footer-widgets', + 'full-width-template', + 'microformats', + 'post-formats', + 'rtl-language-support', + 'sticky-post', + 'theme-options', + 'translation-ready', + 'block-patterns', + ], + }, + { + slug: 'twentyfifteen', + name: 'Twenty Fifteen', + description: + "Our 2015 default theme is clean, blog-focused, and designed for clarity. Twenty Fifteen's simple, straightforward typography is readable on a wide variety of screen sizes, and suitable for multiple languages. We designed it using a mobile-first approach, meaning your content takes center-stage, regardless of whether your visitors arrive by smartphone, tablet, laptop, or desktop computer.", + requires: '4.1', + tested: '6.6', + tags: [ + 'blog', + 'two-columns', + 'left-sidebar', + 'accessibility-ready', + 'custom-background', + 'custom-colors', + 'custom-header', + 'custom-logo', + 'custom-menu', + 'editor-style', + 'featured-images', + 'microformats', + 'post-formats', + 'rtl-language-support', + 'sticky-post', + 'threaded-comments', + 'translation-ready', + 'block-patterns', + ], + }, + { + slug: 'twentyfourteen', + name: 'Twenty Fourteen', + description: + "In 2014, our default theme lets you create a responsive magazine website with a sleek, modern design. Feature your favorite homepage content in either a grid or a slider. Use the three widget areas to customize your website, and change your content's layout with a full-width page template and a contributor page to show off your authors. Creating a magazine website with WordPress has never been easier.", + requires: '3.6', + tested: '6.6', + tags: [ + 'blog', + 'news', + 'two-columns', + 'three-columns', + 'left-sidebar', + 'right-sidebar', + 'custom-background', + 'custom-header', + 'custom-menu', + 'editor-style', + 'featured-images', + 'flexible-header', + 'footer-widgets', + 'full-width-template', + 'microformats', + 'post-formats', + 'rtl-language-support', + 'sticky-post', + 'theme-options', + 'translation-ready', + 'accessibility-ready', + 'block-patterns', + ], + }, + { + slug: 'twentynineteen', + name: 'Twenty Nineteen', + description: + "Our 2019 default theme is designed to show off the power of the block editor. It features custom styles for all the default blocks, and is built so that what you see in the editor looks like what you'll see on your website. Twenty Nineteen is designed to be adaptable to a wide range of websites, whether you’re running a photo blog, launching a new business, or supporting a non-profit. Featuring ample whitespace and modern sans-serif headlines paired with classic serif body text, it's built to be beautiful on all screen sizes.", + requires: '4.7', + tested: '6.6', + tags: [ + 'one-column', + 'accessibility-ready', + 'custom-colors', + 'custom-menu', + 'custom-logo', + 'editor-style', + 'featured-images', + 'footer-widgets', + 'rtl-language-support', + 'sticky-post', + 'threaded-comments', + 'translation-ready', + 'block-patterns', + ], + }, + { + slug: 'twentyseventeen', + name: 'Twenty Seventeen', + description: + 'Twenty Seventeen brings your site to life with header video and immersive featured images. With a focus on business sites, it features multiple sections on the front page as well as widgets, navigation and social menus, a logo, and more. Personalize its asymmetrical grid with a custom color scheme and showcase your multimedia content with post formats. Our default theme for 2017 works great in many languages, for any abilities, and on any device.', + requires: '4.7', + tested: '6.6', + tags: [ + 'one-column', + 'two-columns', + 'right-sidebar', + 'flexible-header', + 'accessibility-ready', + 'custom-colors', + 'custom-header', + 'custom-menu', + 'custom-logo', + 'editor-style', + 'featured-images', + 'footer-widgets', + 'post-formats', + 'rtl-language-support', + 'sticky-post', + 'theme-options', + 'threaded-comments', + 'translation-ready', + 'block-patterns', + ], + }, + { + slug: 'twentysixteen', + name: 'Twenty Sixteen', + description: + 'Twenty Sixteen is a modernized take on an ever-popular WordPress layout — the horizontal masthead with an optional right sidebar that works perfectly for blogs and websites. It has custom color options with beautiful default color schemes, a harmonious fluid grid using a mobile-first approach, and impeccable polish in every detail. Twenty Sixteen will make your WordPress look beautiful everywhere.', + requires: '4.4', + tested: '6.6', + tags: [ + 'one-column', + 'two-columns', + 'right-sidebar', + 'accessibility-ready', + 'custom-background', + 'custom-colors', + 'custom-header', + 'custom-menu', + 'editor-style', + 'featured-images', + 'flexible-header', + 'microformats', + 'post-formats', + 'rtl-language-support', + 'sticky-post', + 'threaded-comments', + 'translation-ready', + 'blog', + 'block-patterns', + ], + }, + { + slug: 'twentyten', + name: 'Twenty Ten', + description: + 'The 2010 theme for WordPress is stylish, customizable, simple, and readable -- make it yours with a custom menu, header image, and background. Twenty Ten supports six widgetized areas (two in the sidebar, four in the footer) and featured images (thumbnails for gallery posts and custom header images for posts and pages). It includes stylesheets for print and the admin Visual Editor, special styles for posts in the "Asides" and "Gallery" categories, and has an optional one-column page template that removes the sidebar.', + requires: '5.6', + tested: '6.6', + tags: [ + 'blog', + 'two-columns', + 'custom-header', + 'custom-background', + 'threaded-comments', + 'sticky-post', + 'translation-ready', + 'microformats', + 'rtl-language-support', + 'editor-style', + 'custom-menu', + 'flexible-header', + 'featured-images', + 'footer-widgets', + 'featured-image-header', + 'block-patterns', + ], + }, + { + slug: 'twentythirteen', + name: 'Twenty Thirteen', + description: + 'The 2013 theme for WordPress takes us back to the blog, featuring a full range of post formats, each displayed beautifully in their own unique way. Design details abound, starting with a vibrant color scheme and matching header images, beautiful typography and icons, and a flexible layout that looks great on any device, big or small.', + requires: '3.6', + tested: '6.6', + tags: [ + 'blog', + 'one-column', + 'two-columns', + 'right-sidebar', + 'custom-header', + 'custom-menu', + 'editor-style', + 'featured-images', + 'footer-widgets', + 'microformats', + 'post-formats', + 'rtl-language-support', + 'sticky-post', + 'translation-ready', + 'accessibility-ready', + 'block-patterns', + ], + }, + { + slug: 'twentytwelve', + name: 'Twenty Twelve', + description: + 'The 2012 theme for WordPress is a fully responsive theme that looks great on any device. Features include a front page template with its own widgets, an optional display font, styling for post formats on both index and single views, and an optional no-sidebar page template. Make it yours with a custom menu, header image, and background.', + requires: '3.5', + tested: '6.6', + tags: [ + 'blog', + 'one-column', + 'two-columns', + 'right-sidebar', + 'custom-background', + 'custom-header', + 'custom-menu', + 'editor-style', + 'featured-images', + 'flexible-header', + 'footer-widgets', + 'full-width-template', + 'microformats', + 'post-formats', + 'rtl-language-support', + 'sticky-post', + 'theme-options', + 'translation-ready', + 'block-patterns', + ], + }, + { + slug: 'twentytwenty', + name: 'Twenty Twenty', + description: + 'Our default theme for 2020 is designed to take full advantage of the flexibility of the block editor. Organizations and businesses have the ability to create dynamic landing pages with endless layouts using the group and column blocks. The centered content column and fine-tuned typography also makes it perfect for traditional blogs. Complete editor styles give you a good idea of what your content will look like, even before you publish. You can give your site a personal touch by changing the background colors and the accent color in the Customizer. The colors of all elements on your site are automatically calculated based on the colors you pick, ensuring a high, accessible color contrast for your visitors.', + requires: '4.7', + tested: '6.6', + tags: [ + 'blog', + 'one-column', + 'custom-background', + 'custom-colors', + 'custom-logo', + 'custom-menu', + 'editor-style', + 'featured-images', + 'footer-widgets', + 'full-width-template', + 'rtl-language-support', + 'sticky-post', + 'theme-options', + 'threaded-comments', + 'translation-ready', + 'block-patterns', + 'block-styles', + 'wide-blocks', + 'accessibility-ready', + ], + }, + { + slug: 'twentytwentyfour', + name: 'Twenty Twenty-Four', + description: + 'Twenty Twenty-Four is designed to be flexible, versatile and applicable to any website. Its collection of templates and patterns tailor to different needs, such as presenting a business, blogging and writing or showcasing work. A multitude of possibilities open up with just a few adjustments to color and typography. Twenty Twenty-Four comes with style variations and full page designs to help speed up the site building process, is fully compatible with the site editor, and takes advantage of new design tools introduced in WordPress 6.4.', + requires: '6.4', + tested: '6.6', + tags: [ + 'one-column', + 'custom-colors', + 'custom-menu', + 'custom-logo', + 'editor-style', + 'featured-images', + 'full-site-editing', + 'block-patterns', + 'rtl-language-support', + 'sticky-post', + 'threaded-comments', + 'translation-ready', + 'wide-blocks', + 'block-styles', + 'style-variations', + 'accessibility-ready', + 'blog', + 'portfolio', + 'news', + ], + }, + { + slug: 'twentytwentyone', + name: 'Twenty Twenty-One', + description: + 'Twenty Twenty-One is a blank canvas for your ideas and it makes the block editor your best brush. With new block patterns, which allow you to create a beautiful layout in a matter of seconds, this theme’s soft colors and eye-catching — yet timeless — design will let your work shine. Take it for a spin! See how Twenty Twenty-One elevates your portfolio, business website, or personal blog.', + requires: '5.3', + tested: '6.6', + tags: [ + 'one-column', + 'accessibility-ready', + 'custom-colors', + 'custom-menu', + 'custom-logo', + 'editor-style', + 'featured-images', + 'footer-widgets', + 'block-patterns', + 'rtl-language-support', + 'sticky-post', + 'threaded-comments', + 'translation-ready', + 'blog', + 'portfolio', + ], + }, + { + slug: 'twentytwentythree', + name: 'Twenty Twenty-Three', + description: + 'Twenty Twenty-Three is designed to take advantage of the new design tools introduced in WordPress 6.1. With a clean, blank base as a starting point, this default theme includes ten diverse style variations created by members of the WordPress community. Whether you want to build a complex or incredibly simple website, you can do it quickly and intuitively through the bundled styles or dive into creation and full customization yourself.', + requires: '6.1', + tested: '6.6', + tags: [ + 'one-column', + 'custom-colors', + 'custom-menu', + 'custom-logo', + 'editor-style', + 'featured-images', + 'full-site-editing', + 'block-patterns', + 'rtl-language-support', + 'sticky-post', + 'threaded-comments', + 'translation-ready', + 'wide-blocks', + 'block-styles', + 'style-variations', + 'accessibility-ready', + 'blog', + 'portfolio', + 'news', + ], + }, + { + slug: 'twentytwentytwo', + name: 'Twenty Twenty-Two', + description: + 'Built on a solidly designed foundation, Twenty Twenty-Two embraces the idea that everyone deserves a truly unique website. The theme’s subtle styles are inspired by the diversity and versatility of birds: its typography is lightweight yet strong, its color palette is drawn from nature, and its layout elements sit gently on the page. The true richness of Twenty Twenty-Two lies in its opportunity for customization. The theme is built to take advantage of the Site Editor features introduced in WordPress 5.9, which means that colors, typography, and the layout of every single page on your site can be customized to suit your vision. It also includes dozens of block patterns, opening the door to a wide range of professionally designed layouts in just a few clicks. Whether you’re building a single-page website, a blog, a business website, or a portfolio, Twenty Twenty-Two will help you create a site that is uniquely yours.', + requires: '5.9', + tested: '6.6', + tags: [ + 'one-column', + 'custom-colors', + 'custom-menu', + 'custom-logo', + 'editor-style', + 'featured-images', + 'full-site-editing', + 'block-patterns', + 'rtl-language-support', + 'sticky-post', + 'threaded-comments', + 'style-variations', + 'wide-blocks', + 'block-styles', + 'accessibility-ready', + 'blog', + 'portfolio', + 'news', + ], + }, +]; + +export const themeFields: Field< Theme >[] = [ + { id: 'slug', label: 'Slug' }, + { id: 'name', label: 'Name' }, + { id: 'description', label: 'Description' }, + { id: 'requires', label: 'Requires at least' }, + { id: 'tested', label: 'Tested up to' }, + { + id: 'tags', + label: 'Tags', + render: ( { item } ) => item.tags.join( ', ' ), + }, +]; + +export const DEFAULT_VIEW = { + type: 'table' as const, + search: '', + page: 1, + perPage: 10, + layout: {}, + filters: [], +}; + +export const actions: Action< SpaceObject >[] = [ + { + id: 'delete', + label: 'Delete item', + isPrimary: true, + icon: trash, + hideModalHeader: true, + RenderModal: ( { items, closeModal } ) => { + return ( + <VStack spacing="5"> + <Text> + { `Are you sure you want to delete "${ items[ 0 ].title }"?` } + </Text> + <HStack justify="right"> + <Button + __next40pxDefaultSize + variant="tertiary" + onClick={ closeModal } + > + Cancel + </Button> + <Button + __next40pxDefaultSize + variant="primary" + onClick={ closeModal } + > + Delete + </Button> + </HStack> + </VStack> + ); + }, + }, + { + id: 'secondary', + label: 'Secondary action', + callback() {}, + }, +]; + +export const fields: Field< SpaceObject >[] = [ + { + label: 'Image', + id: 'image', + header: ( + <HStack spacing={ 1 } justify="start"> + <Icon icon={ image } /> + <span>Image</span> + </HStack> + ), + render: ( { item } ) => { + return ( + <img src={ item.image } alt="" style={ { width: '100%' } } /> + ); + }, + enableSorting: false, + }, + { + label: 'Title', + id: 'title', + enableHiding: false, + enableGlobalSearch: true, + render: ( { item } ) => { + return <a href="#nothing">{ item.title }</a>; + }, + }, + { + id: 'date', + label: 'Date', + type: 'datetime', + }, + { + label: 'Type', + id: 'type', + enableHiding: false, + elements: [ + { value: 'Not a planet', label: 'Not a planet' }, + { value: 'Ice giant', label: 'Ice giant' }, + { value: 'Terrestrial', label: 'Terrestrial' }, + { value: 'Gas giant', label: 'Gas giant' }, + ], + }, + { + label: 'Satellites', + id: 'satellites', + type: 'integer', + enableSorting: true, + }, + { + label: 'Description', + id: 'description', + enableSorting: false, + enableGlobalSearch: true, + }, + { + label: 'Categories', + id: 'categories', + header: ( + <HStack spacing={ 1 } justify="start"> + <Icon icon={ category } /> + <span>Categories</span> + </HStack> + ), + elements: [ + { value: 'Space', label: 'Space' }, + { value: 'NASA', label: 'NASA' }, + { value: 'Planet', label: 'Planet' }, + { value: 'Solar system', label: 'Solar system' }, + { value: 'Ice giant', label: 'Ice giant' }, + ], + filterBy: { + operators: [ 'isAny', 'isNone', 'isAll', 'isNotAll' ], + }, + getValue: ( { item } ) => { + return item.categories; + }, + render: ( { item } ) => { + return item.categories.join( ',' ); + }, + enableSorting: false, + }, +]; diff --git a/packages/dataviews/src/components/dataviews/stories/index.story.js b/packages/dataviews/src/components/dataviews/stories/index.story.js deleted file mode 100644 index 75fb0786ecfee6..00000000000000 --- a/packages/dataviews/src/components/dataviews/stories/index.story.js +++ /dev/null @@ -1,111 +0,0 @@ -/** - * WordPress dependencies - */ -import { useState, useMemo } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import DataViews from '../index'; -import { DEFAULT_VIEW, actions, data, fields } from './fixtures'; -import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../../../constants'; -import { filterSortAndPaginate } from '../../../filter-and-sort-data-view'; - -const meta = { - title: 'DataViews/DataViews', - component: DataViews, -}; -export default meta; - -export const Default = ( props ) => { - const [ view, setView ] = useState( DEFAULT_VIEW ); - const { data: shownData, paginationInfo } = useMemo( () => { - return filterSortAndPaginate( data, view, fields ); - }, [ view ] ); - return ( - <DataViews - { ...props } - paginationInfo={ paginationInfo } - data={ shownData } - view={ view } - fields={ fields } - onChangeView={ setView } - /> - ); -}; - -export const Empty = ( props ) => { - const [ view, setView ] = useState( DEFAULT_VIEW ); - - return ( - <DataViews - { ...props } - paginationInfo={ { totalItems: 0, totalPages: 0 } } - data={ [] } - view={ view } - fields={ fields } - onChangeView={ setView } - /> - ); -}; - -export const FieldsNoSortableNoHidable = ( props ) => { - const [ view, setView ] = useState( DEFAULT_VIEW ); - const { data: shownData, paginationInfo } = useMemo( () => { - return filterSortAndPaginate( data, view, fields ); - }, [ view ] ); - - const _fields = fields.map( ( field ) => ( { - ...field, - enableSorting: false, - enableHiding: false, - } ) ); - - return ( - <DataViews - { ...props } - paginationInfo={ paginationInfo } - data={ shownData } - view={ view } - fields={ _fields } - onChangeView={ setView } - /> - ); -}; - -Default.args = { - actions, - defaultLayouts: { - [ LAYOUT_TABLE ]: { - layout: { - primaryField: 'title', - styles: { - image: { - width: 50, - }, - title: { - maxWidth: 400, - }, - type: { - maxWidth: 400, - }, - description: { - maxWidth: 200, - }, - }, - }, - }, - [ LAYOUT_GRID ]: { - layout: { - mediaField: 'image', - primaryField: 'title', - }, - }, - [ LAYOUT_LIST ]: { - layout: { - mediaField: 'image', - primaryField: 'title', - }, - }, - }, -}; diff --git a/packages/dataviews/src/components/dataviews/stories/index.story.tsx b/packages/dataviews/src/components/dataviews/stories/index.story.tsx new file mode 100644 index 00000000000000..645c6d7ddcd922 --- /dev/null +++ b/packages/dataviews/src/components/dataviews/stories/index.story.tsx @@ -0,0 +1,164 @@ +/** + * WordPress dependencies + */ +import { useState, useMemo } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import DataViews from '../index'; +import { + DEFAULT_VIEW, + actions, + data, + fields, + themeData, + themeFields, +} from './fixtures'; +import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../../../constants'; +import { filterSortAndPaginate } from '../../../filter-and-sort-data-view'; +import type { View } from '../../../types'; + +const meta = { + title: 'DataViews/DataViews', + component: DataViews, +}; +export default meta; + +const defaultLayouts = { + [ LAYOUT_TABLE ]: { + layout: { + primaryField: 'title', + styles: { + image: { + width: 50, + }, + title: { + maxWidth: 400, + }, + type: { + maxWidth: 400, + }, + description: { + maxWidth: 200, + }, + }, + }, + }, + [ LAYOUT_GRID ]: { + layout: { + mediaField: 'image', + primaryField: 'title', + }, + }, + [ LAYOUT_LIST ]: { + layout: { + mediaField: 'image', + primaryField: 'title', + }, + }, +}; + +export const Default = () => { + const [ view, setView ] = useState< View >( { + ...DEFAULT_VIEW, + fields: [ 'title', 'description', 'categories' ], + } ); + const { data: shownData, paginationInfo } = useMemo( () => { + return filterSortAndPaginate( data, view, fields ); + }, [ view ] ); + return ( + <DataViews + getItemId={ ( item ) => item.id.toString() } + paginationInfo={ paginationInfo } + data={ shownData } + view={ view } + fields={ fields } + onChangeView={ setView } + actions={ actions } + defaultLayouts={ defaultLayouts } + /> + ); +}; + +export const Empty = () => { + const [ view, setView ] = useState< View >( { + ...DEFAULT_VIEW, + fields: [ 'title', 'description', 'categories' ], + } ); + + return ( + <DataViews + getItemId={ ( item ) => item.id.toString() } + paginationInfo={ { totalItems: 0, totalPages: 0 } } + data={ [] } + view={ view } + fields={ fields } + onChangeView={ setView } + actions={ actions } + defaultLayouts={ defaultLayouts } + /> + ); +}; + +export const FieldsNoSortableNoHidable = () => { + const [ view, setView ] = useState< View >( { + ...DEFAULT_VIEW, + fields: [ 'title', 'description', 'categories' ], + } ); + const { data: shownData, paginationInfo } = useMemo( () => { + return filterSortAndPaginate( data, view, fields ); + }, [ view ] ); + + const _fields = fields.map( ( field ) => ( { + ...field, + enableSorting: false, + enableHiding: false, + } ) ); + + return ( + <DataViews + getItemId={ ( item ) => item.id.toString() } + paginationInfo={ paginationInfo } + data={ shownData } + view={ view } + fields={ _fields } + onChangeView={ setView } + defaultLayouts={ { + table: {}, + } } + /> + ); +}; + +export const CombinedFields = () => { + const [ view, setView ] = useState< View >( { + ...DEFAULT_VIEW, + fields: [ 'theme', 'requires', 'tested' ], + layout: { + combinedFields: [ + { + id: 'theme', + label: 'Theme', + children: [ 'name', 'description' ], + direction: 'vertical', + }, + ], + }, + } ); + const { data: shownData, paginationInfo } = useMemo( () => { + return filterSortAndPaginate( themeData, view, themeFields ); + }, [ view ] ); + + return ( + <DataViews + getItemId={ ( item ) => item.name } + paginationInfo={ paginationInfo } + data={ shownData } + view={ view } + fields={ themeFields } + onChangeView={ setView } + defaultLayouts={ { table: {} } } + /> + ); +}; From 9d4f918cd107cda355802ddffd1eb96358d1162f Mon Sep 17 00:00:00 2001 From: Miguel Lezama <lezama@gmail.com> Date: Tue, 3 Sep 2024 08:06:28 -0300 Subject: [PATCH 0644/1908] Editor: Add extensibility to PreviewOptions v2 (#64644) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add plugin-preview-dropdown-item * Add slot * export PluginPreviewDropdownItem * add registerPlugin example Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> * example import from @wordpress/editor Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> * rename to PluginPreviewMenuItem * add tests tests --------- Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> Co-authored-by: lezama <migueluy@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: simison <simison@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: fumikito <takahashi_fumiki@git.wordpress.org> Co-authored-by: westonruter <westonruter@git.wordpress.org> --- packages/e2e-tests/plugins/plugins-api.php | 13 +++++ .../plugins/plugins-api/preview-menu.js | 14 +++++ packages/editor/README.md | 37 +++++++++++++ packages/editor/src/components/index.js | 1 + .../plugin-preview-menu-item/index.js | 52 +++++++++++++++++++ .../src/components/preview-dropdown/index.js | 6 +++ .../specs/editor/plugins/plugins-api.spec.js | 21 ++++++++ 7 files changed, 144 insertions(+) create mode 100644 packages/e2e-tests/plugins/plugins-api/preview-menu.js create mode 100644 packages/editor/src/components/plugin-preview-menu-item/index.js diff --git a/packages/e2e-tests/plugins/plugins-api.php b/packages/e2e-tests/plugins/plugins-api.php index fb8054924cebb0..10e35f16226f2a 100644 --- a/packages/e2e-tests/plugins/plugins-api.php +++ b/packages/e2e-tests/plugins/plugins-api.php @@ -86,6 +86,19 @@ function enqueue_plugins_api_plugin_scripts() { filemtime( plugin_dir_path( __FILE__ ) . 'plugins-api/document-setting.js' ), true ); + + wp_enqueue_script( + 'gutenberg-test-plugins-api-preview-menu', + plugins_url( 'plugins-api/preview-menu.js', __FILE__ ), + array( + 'wp-editor', + 'wp-element', + 'wp-i18n', + 'wp-plugins', + ), + filemtime( plugin_dir_path( __FILE__ ) . 'plugins-api/preview-menu.js' ), + true + ); } add_action( 'init', 'enqueue_plugins_api_plugin_scripts' ); diff --git a/packages/e2e-tests/plugins/plugins-api/preview-menu.js b/packages/e2e-tests/plugins/plugins-api/preview-menu.js new file mode 100644 index 00000000000000..1aa53b2e8509ac --- /dev/null +++ b/packages/e2e-tests/plugins/plugins-api/preview-menu.js @@ -0,0 +1,14 @@ +( function () { + const { __ } = wp.i18n; + const { registerPlugin } = wp.plugins; + const PluginPreviewMenuItem = wp.editor.PluginPreviewMenuItem; + const el = wp.element.createElement; + + function CustomPreviewMenuItem() { + return el( PluginPreviewMenuItem, {}, __( 'Custom Preview' ) ); + } + + registerPlugin( 'custom-preview-menu-item', { + render: CustomPreviewMenuItem, + } ); +} )(); diff --git a/packages/editor/README.md b/packages/editor/README.md index 89ea15ef378495..ebd4af31e287d8 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -862,6 +862,43 @@ _Returns_ - `Component`: The component to be rendered. +### PluginPreviewMenuItem + +Renders a menu item in the Preview dropdown, which can be used as a button or link depending on the props provided. The text within the component appears as the menu item label. + +_Usage_ + +```jsx +import { __ } from '@wordpress/i18n'; +import { PluginPreviewMenuItem } from '@wordpress/editor'; +import { external } from '@wordpress/icons'; + +function onPreviewClick() { + // Handle preview action +} + +const ExternalPreviewMenuItem = () => ( + <PreviewDropdownMenuItem icon={ external } onClick={ onPreviewClick }> + { __( 'Preview in new tab' ) } + </PreviewDropdownMenuItem> +); +registerPlugin( 'external-preview-menu-item', { + render: ExternalPreviewMenuItem, +} ); +``` + +_Parameters_ + +- _props_ `Object`: Component properties. +- _props.href_ `[string]`: When `href` is provided, the menu item is rendered as an anchor instead of a button. It corresponds to the `href` attribute of the anchor. +- _props.icon_ `[WPBlockTypeIconRender]`: The icon to be rendered to the left of the menu item label. Can be a Dashicon slug or an SVG WP element. +- _props.onClick_ `[Function]`: The callback function to be executed when the user clicks the menu item. +- _props.other_ `[...*]`: Any additional props are passed through to the underlying MenuItem component. + +_Returns_ + +- `Component`: The rendered menu item component. + ### PluginSidebar Renders a sidebar when activated. The contents within the `PluginSidebar` will appear as content within the sidebar. It also automatically renders a corresponding `PluginSidebarMenuItem` component when `isPinnable` flag is set to `true`. If you wish to display the sidebar, you can with use the `PluginSidebarMoreMenuItem` component or the `wp.data.dispatch` API: diff --git a/packages/editor/src/components/index.js b/packages/editor/src/components/index.js index 91dcc883d661b2..b42566aac653be 100644 --- a/packages/editor/src/components/index.js +++ b/packages/editor/src/components/index.js @@ -32,6 +32,7 @@ export { default as PluginMoreMenuItem } from './plugin-more-menu-item'; export { default as PluginPostPublishPanel } from './plugin-post-publish-panel'; export { default as PluginPostStatusInfo } from './plugin-post-status-info'; export { default as PluginPrePublishPanel } from './plugin-pre-publish-panel'; +export { default as PluginPreviewMenuItem } from './plugin-preview-menu-item'; export { default as PluginSidebar } from './plugin-sidebar'; export { default as PluginSidebarMoreMenuItem } from './plugin-sidebar-more-menu-item'; export { default as PostTemplatePanel } from './post-template/panel'; diff --git a/packages/editor/src/components/plugin-preview-menu-item/index.js b/packages/editor/src/components/plugin-preview-menu-item/index.js new file mode 100644 index 00000000000000..422248e17b88e1 --- /dev/null +++ b/packages/editor/src/components/plugin-preview-menu-item/index.js @@ -0,0 +1,52 @@ +/** + * WordPress dependencies + */ +import { compose } from '@wordpress/compose'; +import { MenuItem } from '@wordpress/components'; +import { withPluginContext } from '@wordpress/plugins'; +import { ActionItem } from '@wordpress/interface'; + +/** + * Renders a menu item in the Preview dropdown, which can be used as a button or link depending on the props provided. + * The text within the component appears as the menu item label. + * + * @param {Object} props Component properties. + * @param {string} [props.href] When `href` is provided, the menu item is rendered as an anchor instead of a button. It corresponds to the `href` attribute of the anchor. + * @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The icon to be rendered to the left of the menu item label. Can be a Dashicon slug or an SVG WP element. + * @param {Function} [props.onClick] The callback function to be executed when the user clicks the menu item. + * @param {...*} [props.other] Any additional props are passed through to the underlying MenuItem component. + * + * @example + * ```jsx + * import { __ } from '@wordpress/i18n'; + * import { PluginPreviewMenuItem } from '@wordpress/editor'; + * import { external } from '@wordpress/icons'; + * + * function onPreviewClick() { + * // Handle preview action + * } + * + * const ExternalPreviewMenuItem = () => ( + * <PreviewDropdownMenuItem + * icon={ external } + * onClick={ onPreviewClick } + * > + * { __( 'Preview in new tab' ) } + * </PreviewDropdownMenuItem> + * ); + * registerPlugin( 'external-preview-menu-item', { + * render: ExternalPreviewMenuItem, + * } ); + * ``` + * + * @return {Component} The rendered menu item component. + */ +export default compose( + withPluginContext( ( context, ownProps ) => { + return { + as: ownProps.as ?? MenuItem, + icon: ownProps.icon || context.icon, + name: 'core/plugin-preview-menu', + }; + } ) +)( ActionItem ); diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js index ec30d55cf0f17b..8b51bb79bc8873 100644 --- a/packages/editor/src/components/preview-dropdown/index.js +++ b/packages/editor/src/components/preview-dropdown/index.js @@ -22,6 +22,7 @@ import { store as coreStore } from '@wordpress/core-data'; import { useEffect, useRef } from '@wordpress/element'; import { store as preferencesStore } from '@wordpress/preferences'; import { store as blockEditorStore } from '@wordpress/block-editor'; +import { ActionItem } from '@wordpress/interface'; /** * Internal dependencies @@ -206,6 +207,11 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { /> </MenuGroup> ) } + <ActionItem.Slot + name="core/plugin-preview-menu" + as={ MenuGroup } + fillProps={ { onClick: onClose } } + /> </> ) } </DropdownMenu> diff --git a/test/e2e/specs/editor/plugins/plugins-api.spec.js b/test/e2e/specs/editor/plugins/plugins-api.spec.js index c71b49e3c4d815..c7f3a655e14240 100644 --- a/test/e2e/specs/editor/plugins/plugins-api.spec.js +++ b/test/e2e/specs/editor/plugins/plugins-api.spec.js @@ -230,4 +230,25 @@ test.describe( 'Plugins API', () => { ).toBeVisible(); } ); } ); + + test.describe( 'Preview Menu Item', () => { + test( 'Should render and interact with PluginPreviewMenuItem', async ( { + page, + } ) => { + await page + .getByRole( 'region', { name: 'Editor top bar' } ) + .locator( '.editor-preview-dropdown__toggle' ) + .click(); + + const customPreviewItem = page.getByRole( 'menuitem', { + name: 'Custom Preview', + } ); + + await expect( customPreviewItem ).toBeVisible(); + + await customPreviewItem.click(); + + await expect( customPreviewItem ).toBeHidden(); + } ); + } ); } ); From 7b7196f06b6bbfc2d138fb313b9c1d84e2a5f066 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 3 Sep 2024 15:53:24 +0200 Subject: [PATCH 0645/1908] Dataviews Filter search widget: do not use Composite store (#64985) * Dataviews Filter search widget: do not use Composite store * Use internal CompositeHover and CompositeTypeahead version * Better comment * Refactor generateCompositeItemId arguments * Export Composite.Typeahead and Composite.Hover as private APIs * CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/private-apis.ts | 2 + .../dataviews-filters/search-widget.tsx | 60 ++++++++++++++----- 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 3b8d45be5861bc..5a58ddfda38b99 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -66,6 +66,7 @@ ### Internal +- `DropdownMenu` v2: expose CompositeTypeaheadV2 and CompositeHoverV2 via private APIs ([#64985](https://github.com/WordPress/gutenberg/pull/64985)). - `DropdownMenu` v2: fix flashing menu item styles when using keyboard ([#64873](https://github.com/WordPress/gutenberg/pull/64873), [#64942](https://github.com/WordPress/gutenberg/pull/64942)). - `DropdownMenu` v2: refactor to overloaded naming convention ([#64654](https://github.com/WordPress/gutenberg/pull/64654)). - `DropdownMenu` v2: add `GroupLabel` subcomponent ([#64854](https://github.com/WordPress/gutenberg/pull/64854)). diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index fa9fece048617e..7bcab0e052e022 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -18,6 +18,8 @@ lock( privateApis, { CompositeGroupV2: Composite.Group, CompositeItemV2: Composite.Item, CompositeRowV2: Composite.Row, + CompositeTypeaheadV2: Composite.Typeahead, + CompositeHoverV2: Composite.Hover, useCompositeStoreV2: useCompositeStore, __experimentalPopoverLegacyPositionToPlacement, createPrivateSlotFill, diff --git a/packages/dataviews/src/components/dataviews-filters/search-widget.tsx b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx index 1b369222b8f28c..24ef3b5594b413 100644 --- a/packages/dataviews/src/components/dataviews-filters/search-widget.tsx +++ b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx @@ -8,6 +8,7 @@ import removeAccents from 'remove-accents'; /** * WordPress dependencies */ +import { useInstanceId } from '@wordpress/compose'; import { __, sprintf } from '@wordpress/i18n'; import { useState, useMemo, useDeferredValue } from '@wordpress/element'; import { @@ -27,7 +28,8 @@ import type { Filter, NormalizedFilter, View } from '../../types'; const { CompositeV2: Composite, CompositeItemV2: CompositeItem, - useCompositeStoreV2: useCompositeStore, + CompositeHoverV2: CompositeHover, + CompositeTypeaheadV2: CompositeTypeahead, } = unlock( componentsPrivateApis ); interface SearchWidgetProps { @@ -84,22 +86,37 @@ const getNewValue = ( return [ value ]; }; +function generateFilterElementCompositeItemId( + prefix: string, + filterElementValue: string +) { + return `${ prefix }-${ filterElementValue }`; +} + function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) { - const compositeStore = useCompositeStore( { - virtualFocus: true, - focusLoop: true, - // When we have no or just one operator, we can set the first item as active. - // We do that by passing `undefined` to `defaultActiveId`. Otherwise, we set it to `null`, - // so the first item is not selected, since the focus is on the operators control. - defaultActiveId: filter.operators?.length === 1 ? undefined : null, - } ); + const baseId = useInstanceId( ListBox, 'dataviews-filter-list-box' ); + + const [ activeCompositeId, setActiveCompositeId ] = useState< + string | null | undefined + >( + // When there are one or less operators, the first item is set as active + // (by setting the initial `activeId` to `undefined`). + // With 2 or more operators, the focus is moved on the operators control + // (by setting the initial `activeId` to `null`), meaning that there won't + // be an active item initially. Focus is then managed via the + // `onFocusVisible` callback. + filter.operators?.length === 1 ? undefined : null + ); const currentFilter = view.filters?.find( ( f ) => f.field === filter.field ); const currentValue = getCurrentValue( filter, currentFilter ); return ( <Composite - store={ compositeStore } + virtualFocus + focusLoop + activeId={ activeCompositeId } + setActiveId={ setActiveCompositeId } role="listbox" className="dataviews-filters__search-widget-listbox" aria-label={ sprintf( @@ -108,18 +125,29 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) { filter.name ) } onFocusVisible={ () => { - if ( ! compositeStore.getState().activeId ) { - compositeStore.move( compositeStore.first() ); + // `onFocusVisible` needs the `Composite` component to be focusable, + // which is implicitly achieved via the `virtualFocus: true` option + // in the `useCompositeStore` hook. + if ( ! activeCompositeId && filter.elements.length ) { + setActiveCompositeId( + generateFilterElementCompositeItemId( + baseId, + filter.elements[ 0 ].value + ) + ); } } } - render={ <Ariakit.CompositeTypeahead store={ compositeStore } /> } + render={ <CompositeTypeahead /> } > { filter.elements.map( ( element ) => ( - <Ariakit.CompositeHover - store={ compositeStore } + <CompositeHover key={ element.value } render={ <CompositeItem + id={ generateFilterElementCompositeItemId( + baseId, + element.value + ) } render={ <div aria-label={ element.label } @@ -185,7 +213,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) { ) } </span> <span>{ element.label }</span> - </Ariakit.CompositeHover> + </CompositeHover> ) ) } </Composite> ); From 66eeb388745456156d21cfc4733933a731a6c883 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Tue, 3 Sep 2024 15:57:23 +0200 Subject: [PATCH 0646/1908] Block Bindings: Add warning in attributes connected to invalid sources (#65002) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add warning with invalid sources * Change variable name Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> * Use `isSourceInvalid` variable --------- Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/block-editor/src/hooks/block-bindings.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 3b90ecc1a0c178..ea069c15a028fe 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -96,16 +96,20 @@ function BlockBindingsAttribute( { attribute, binding } ) { const { source: sourceName, args } = binding || {}; const sourceProps = unlock( blocksPrivateApis ).getBlockBindingsSource( sourceName ); + const isSourceInvalid = ! sourceProps; return ( <VStack> <Truncate>{ attribute }</Truncate> { !! binding && ( <Text - variant="muted" + variant={ ! isSourceInvalid && 'muted' } className="block-editor-bindings__item-explanation" + isDestructive={ isSourceInvalid } > <Truncate> - { args?.key || sourceProps?.label || sourceName } + { isSourceInvalid + ? __( 'Invalid source' ) + : args?.key || sourceProps?.label || sourceName } </Truncate> </Text> ) } From 84b48f7256dceae44432c8ee3b54433ed0674035 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Tue, 3 Sep 2024 16:00:50 +0200 Subject: [PATCH 0647/1908] Icons: Add thumbs up and down icons. (#65004) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/icons/src/index.js | 2 ++ packages/icons/src/library/thumbs-down.js | 12 ++++++++++++ packages/icons/src/library/thumbs-up.js | 12 ++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 packages/icons/src/library/thumbs-down.js create mode 100644 packages/icons/src/library/thumbs-up.js diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index 9250f413a8572b..11b3da927f3644 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -255,6 +255,8 @@ export { default as tableRowBefore } from './library/table-row-before'; export { default as tableRowDelete } from './library/table-row-delete'; export { default as table } from './library/table'; export { default as tag } from './library/tag'; +export { default as thumbsDown } from './library/thumbs-down'; +export { default as thumbsUp } from './library/thumbs-up'; export { default as symbolFilled } from './library/symbol-filled'; export { default as termDescription } from './library/term-description'; export { default as footer } from './library/footer'; diff --git a/packages/icons/src/library/thumbs-down.js b/packages/icons/src/library/thumbs-down.js new file mode 100644 index 00000000000000..94e11ee8f06386 --- /dev/null +++ b/packages/icons/src/library/thumbs-down.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const thumbsDown = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M19.8 4h-1.5l1 8h1.5l-1-8ZM17 5.8c-.1-1-1-1.8-2-1.8H6.8c-.9 0-1.7.6-1.9 1.4l-1.8 6C2.7 12.7 3.7 14 5 14h4.4l-.8 3.6c-.3 1.3.7 2.4 1.9 2.4h.2c.6 0 1.2-.3 1.6-.8l5-6.6c.3-.4.5-.9.4-1.5L17 5.7Zm-.9 5.9-5 6.6c0 .1-.2.2-.4.2h-.2c-.3 0-.6-.3-.5-.6l.8-3.6c.1-.4 0-.9-.3-1.3s-.7-.6-1.2-.6H4.9c-.3 0-.6-.3-.5-.6l1.8-6c0-.2.3-.4.5-.4h8.2c.3 0 .5.2.5.4l.7 5.4v.4Z" /> + </SVG> +); + +export default thumbsDown; diff --git a/packages/icons/src/library/thumbs-up.js b/packages/icons/src/library/thumbs-up.js new file mode 100644 index 00000000000000..f65b6445359e25 --- /dev/null +++ b/packages/icons/src/library/thumbs-up.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const thumbsUp = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="m3 12 1 8h1.5l-1-8H3Zm15.8-2h-4.4l.8-3.6c.3-1.3-.7-2.4-1.9-2.4h-.2c-.6 0-1.2.3-1.6.8l-5 6.6c-.3.4-.4.8-.4 1.2v.2l.7 5.4v.2c.2.9 1 1.5 1.9 1.5h8.2c.9 0 1.7-.6 1.9-1.4l1.8-6c.4-1.3-.6-2.6-1.9-2.6Zm.5 2.1-1.8 6c0 .2-.3.4-.5.4H8.8c-.3 0-.5-.2-.5-.4l-.7-5.4v-.4l5-6.6c0-.1.2-.2.4-.2h.2c.3 0 .6.3.5.6l-.8 3.6c-.1.4 0 .9.3 1.3s.7.6 1.2.6h4.4c.3 0 .6.3.5.6Z" /> + </SVG> +); + +export default thumbsUp; From 559edaedc00efd3cd9f47418904fb2214d970124 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 4 Sep 2024 00:09:03 +1000 Subject: [PATCH 0648/1908] Color panel hook: rename to remove ambiguity (#64993) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../src/components/global-styles/color-panel.js | 6 +++--- .../src/components/global-styles/color-panel.native.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/color-panel.js b/packages/block-editor/src/components/global-styles/color-panel.js index 15f06310176c70..87c19adedbb27b 100644 --- a/packages/block-editor/src/components/global-styles/color-panel.js +++ b/packages/block-editor/src/components/global-styles/color-panel.js @@ -33,7 +33,7 @@ import { unlock } from '../../lock-unlock'; export function useHasColorPanel( settings ) { const hasTextPanel = useHasTextPanel( settings ); - const hasBackgroundPanel = useHasBackgroundPanel( settings ); + const hasBackgroundPanel = useHasBackgroundColorPanel( settings ); const hasLinkPanel = useHasLinkPanel( settings ); const hasHeadingPanel = useHasHeadingPanel( settings ); const hasButtonPanel = useHasButtonPanel( settings ); @@ -97,7 +97,7 @@ export function useHasButtonPanel( settings ) { ); } -export function useHasBackgroundPanel( settings ) { +export function useHasBackgroundColorPanel( settings ) { const colors = useColorsPerOrigin( settings ); const gradients = useGradientsPerOrigin( settings ); return ( @@ -347,7 +347,7 @@ export default function ColorPanel( { }; // BackgroundColor - const showBackgroundPanel = useHasBackgroundPanel( settings ); + const showBackgroundPanel = useHasBackgroundColorPanel( settings ); const backgroundColor = decodeValue( inheritedValue?.color?.background ); const userBackgroundColor = decodeValue( value?.color?.background ); const gradient = decodeValue( inheritedValue?.color?.gradient ); diff --git a/packages/block-editor/src/components/global-styles/color-panel.native.js b/packages/block-editor/src/components/global-styles/color-panel.native.js index fcbff4e5a07d78..87002b5fa3e22f 100644 --- a/packages/block-editor/src/components/global-styles/color-panel.native.js +++ b/packages/block-editor/src/components/global-styles/color-panel.native.js @@ -18,7 +18,7 @@ import InspectorControls from '../inspector-controls'; import { useHasColorPanel, useHasTextPanel, - useHasBackgroundPanel, + useHasBackgroundColorPanel, } from './color-panel.js'; import { useGlobalStyles } from './use-global-styles-context'; @@ -95,7 +95,7 @@ const ColorPanel = ( { ); // BackgroundColor - const showBackgroundPanel = useHasBackgroundPanel( settings ); + const showBackgroundPanel = useHasBackgroundColorPanel( settings ); const backgroundColor = decodeValue( inheritedValue?.color?.background ); const gradient = decodeValue( inheritedValue?.color?.gradient ); const setBackgroundColor = useCallback( From 7c0638b5a5ad278da458ff5d3fa4cd8a753e301d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 3 Sep 2024 16:18:38 +0200 Subject: [PATCH 0649/1908] DataViews: fix field reordering and visibility logic (#64999) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> --- .../dataviews-view-config/index.tsx | 251 ++++++++---------- .../dataviews/src/dataviews-layouts/index.ts | 65 ++++- .../table/column-header-menu.tsx | 105 ++++---- .../src/dataviews-layouts/table/index.tsx | 5 +- packages/dataviews/src/normalize-fields.ts | 2 + packages/dataviews/src/types.ts | 2 + 6 files changed, 238 insertions(+), 192 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index 331d0d62dca00a..c01c72d2ebc699 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -38,8 +38,13 @@ import { sortIcons, sortLabels, } from '../../constants'; -import { VIEW_LAYOUTS, getMandatoryFields } from '../../dataviews-layouts'; -import type { NormalizedField, SupportedLayouts, View } from '../../types'; +import { + VIEW_LAYOUTS, + getNotHidableFieldIds, + getVisibleFieldIds, + getHiddenFieldIds, +} from '../../dataviews-layouts'; +import type { SupportedLayouts, View, Field } from '../../types'; import DataViewsContext from '../dataviews-context'; import { unlock } from '../../lock-unlock'; import DensityPicker from '../../dataviews-layouts/grid/density-picker'; @@ -232,50 +237,34 @@ function ItemsPerPageControl() { ); } +interface FieldItemProps { + id: any; + label: string; + index: number; + isVisible: boolean; + isHidable: boolean; +} + function FieldItem( { + field: { id, label, index, isVisible, isHidable }, fields, - fieldId, - mandatoryFields, - viewFields, view, onChangeView, }: { - fields: NormalizedField< any >[]; - fieldId: string; - mandatoryFields: string | any[]; - viewFields: string[]; + field: FieldItemProps; + fields: Field< any >[]; view: View; onChangeView: ( view: View ) => void; } ) { - let fieldLabel; - let fieldIsHidable; - const fieldObject = fields.find( - ( f ) => f.id === fieldId - ) as NormalizedField< any >; - if ( fieldObject ) { - fieldLabel = fieldObject.label; - fieldIsHidable = - fieldObject.enableHiding !== false && - ! mandatoryFields.includes( fieldId ); - } else if ( view.type === LAYOUT_TABLE ) { - const combinedFieldObject = view.layout?.combinedFields?.find( - ( f ) => f.id === fieldId - ); - if ( combinedFieldObject ) { - fieldLabel = combinedFieldObject.label; - fieldIsHidable = ! mandatoryFields.includes( fieldId ); - } - } + const visibleFieldIds = getVisibleFieldIds( view, fields ); - const index = view.fields?.indexOf( fieldId ) as number; - const isVisible = viewFields.includes( fieldId ); return ( - <Item key={ fieldId }> + <Item key={ id }> <HStack expanded - className={ `dataviews-field-control__field dataviews-field-control__field-${ fieldId }` } + className={ `dataviews-field-control__field dataviews-field-control__field-${ id }` } > - <span>{ fieldLabel }</span> + <span>{ label }</span> <HStack justify="flex-end" expanded={ false } @@ -284,23 +273,22 @@ function FieldItem( { { view.type === LAYOUT_TABLE && isVisible && ( <> <Button - disabled={ ! isVisible || index < 1 } + disabled={ index < 1 } accessibleWhenDisabled size="compact" onClick={ () => { - if ( ! view.fields || index < 1 ) { - return; - } onChangeView( { ...view, fields: [ - ...( view.fields.slice( + ...( visibleFieldIds.slice( 0, index - 1 ) ?? [] ), - fieldId, - view.fields[ index - 1 ], - ...view.fields.slice( index + 1 ), + id, + visibleFieldIds[ index - 1 ], + ...visibleFieldIds.slice( + index + 1 + ), ], } ); } } @@ -308,34 +296,26 @@ function FieldItem( { label={ sprintf( /* translators: %s: field label */ __( 'Move %s up' ), - fieldLabel + label ) } /> <Button - disabled={ - ! isVisible || - ! view.fields || - index >= view.fields.length - 1 - } + disabled={ index >= visibleFieldIds.length - 1 } accessibleWhenDisabled size="compact" onClick={ () => { - if ( - ! view.fields || - index >= view.fields.length - 1 - ) { - return; - } onChangeView( { ...view, fields: [ - ...( view.fields.slice( + ...( visibleFieldIds.slice( 0, index ) ?? [] ), - view.fields[ index + 1 ], - fieldId, - ...view.fields.slice( index + 2 ), + visibleFieldIds[ index + 1 ], + id, + ...visibleFieldIds.slice( + index + 2 + ), ], } ); } } @@ -343,31 +323,31 @@ function FieldItem( { label={ sprintf( /* translators: %s: field label */ __( 'Move %s down' ), - fieldLabel + label ) } />{ ' ' } </> ) } <Button className="dataviews-field-control__field-visibility-button" - disabled={ ! fieldIsHidable } + disabled={ ! isHidable } accessibleWhenDisabled size="compact" onClick={ () => { onChangeView( { ...view, fields: isVisible - ? viewFields.filter( - ( id ) => id !== fieldId + ? visibleFieldIds.filter( + ( fieldId ) => fieldId !== id ) - : [ ...viewFields, fieldId ], + : [ ...visibleFieldIds, id ], } ); // Focus the visibility button to avoid focus loss. // Our code is safe against the component being unmounted, so we don't need to worry about cleaning the timeout. // eslint-disable-next-line @wordpress/react-no-unsafe-timeout setTimeout( () => { const element = document.querySelector( - `.dataviews-field-control__field-${ fieldId } .dataviews-field-control__field-visibility-button` + `.dataviews-field-control__field-${ id } .dataviews-field-control__field-visibility-button` ); if ( element instanceof HTMLElement ) { element.focus(); @@ -380,12 +360,12 @@ function FieldItem( { ? sprintf( /* translators: %s: field label */ __( 'Hide %s' ), - fieldLabel + label ) : sprintf( /* translators: %s: field label */ __( 'Show %s' ), - fieldLabel + label ) } /> @@ -395,83 +375,77 @@ function FieldItem( { ); } -function FieldList( { - fields, - fieldIds, - mandatoryFields, - viewFields, - view, - onChangeView, -}: Omit< Parameters< typeof FieldItem >[ 0 ], 'fieldId' > & { - fieldIds: string[]; -} ) { - return fieldIds.map( ( fieldId ) => ( - <FieldItem - key={ fieldId } - fields={ fields } - fieldId={ fieldId } - mandatoryFields={ mandatoryFields } - viewFields={ viewFields } - view={ view } - onChangeView={ onChangeView } - /> - ) ); -} - function FieldControl() { const { view, fields, onChangeView } = useContext( DataViewsContext ); - const mandatoryFields = useMemo( - () => getMandatoryFields( view ), + + const visibleFieldIds = useMemo( + () => getVisibleFieldIds( view, fields ), + [ view, fields ] + ); + const hiddenFieldIds = useMemo( + () => getHiddenFieldIds( view, fields ), + [ view, fields ] + ); + const notHidableFieldIds = useMemo( + () => getNotHidableFieldIds( view ), [ view ] ); - const viewFields = view.fields || fields.map( ( field ) => field.id ); - const visibleFields = view.fields; - const hiddenFields = useMemo( () => { - const nonViewFieldsList = fields - .filter( - ( field ) => - ! viewFields.includes( field.id ) && - ! mandatoryFields?.includes( field.id ) - ) - .map( ( field ) => field.id ); - if ( view.type !== LAYOUT_TABLE ) { - return nonViewFieldsList; - } - const nonViewFieldsAndNonCombinedList = nonViewFieldsList.filter( - ( fieldId ) => { - return ! view.layout?.combinedFields?.some( ( combinedField ) => - combinedField.children.includes( fieldId ) - ); - } - ); - const nonViewFieldsCombinedFieldsList = - view.layout?.combinedFields - ?.filter( - ( combinedField ) => - ! viewFields.includes( combinedField.id ) - ) - .map( ( combinedField ) => combinedField.id ) || []; - return [ - ...nonViewFieldsAndNonCombinedList, - ...nonViewFieldsCombinedFieldsList, - ]; - }, [ view, mandatoryFields, fields, viewFields ] ); + const visibleFields = fields + .filter( ( { id } ) => visibleFieldIds.includes( id ) ) + .map( ( { id, label, enableHiding } ) => { + return { + id, + label, + index: visibleFieldIds.indexOf( id ), + isVisible: true, + isHidable: notHidableFieldIds.includes( id ) + ? false + : enableHiding, + }; + } ); + if ( view.type === LAYOUT_TABLE && view.layout?.combinedFields ) { + view.layout.combinedFields.forEach( ( { id, label } ) => { + visibleFields.push( { + id, + label, + index: visibleFieldIds.indexOf( id ), + isVisible: true, + isHidable: notHidableFieldIds.includes( id ), + } ); + } ); + } + visibleFields.sort( ( a, b ) => a.index - b.index ); + + const hiddenFields = fields + .filter( ( { id } ) => hiddenFieldIds.includes( id ) ) + .map( ( { id, label, enableHiding }, index ) => { + return { + id, + label, + index, + isVisible: false, + isHidable: enableHiding, + }; + } ); + if ( ! visibleFields?.length && ! hiddenFields?.length ) { return null; } + return ( <VStack spacing={ 6 } className="dataviews-field-control"> { !! visibleFields?.length && ( <ItemGroup isBordered isSeparated> - <FieldList - fields={ fields } - fieldIds={ visibleFields } - mandatoryFields={ mandatoryFields } - viewFields={ viewFields } - view={ view } - onChangeView={ onChangeView } - /> + { visibleFields.map( ( field ) => ( + <FieldItem + key={ field.id } + field={ field } + fields={ fields } + view={ view } + onChangeView={ onChangeView } + /> + ) ) } </ItemGroup> ) } { !! hiddenFields?.length && ( @@ -481,14 +455,15 @@ function FieldControl() { { __( 'Hidden' ) } </BaseControl.VisualLabel> <ItemGroup isBordered isSeparated> - <FieldList - fields={ fields } - fieldIds={ hiddenFields } - mandatoryFields={ mandatoryFields } - viewFields={ viewFields } - view={ view } - onChangeView={ onChangeView } - /> + { hiddenFields.map( ( field ) => ( + <FieldItem + key={ field.id } + field={ field } + fields={ fields } + view={ view } + onChangeView={ onChangeView } + /> + ) ) } </ItemGroup> </VStack> </> diff --git a/packages/dataviews/src/dataviews-layouts/index.ts b/packages/dataviews/src/dataviews-layouts/index.ts index 9c96475777c007..eece17d0f4f10c 100644 --- a/packages/dataviews/src/dataviews-layouts/index.ts +++ b/packages/dataviews/src/dataviews-layouts/index.ts @@ -16,7 +16,7 @@ import ViewTable from './table'; import ViewGrid from './grid'; import ViewList from './list'; import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../constants'; -import type { View } from '../types'; +import type { View, Field } from '../types'; export const VIEW_LAYOUTS = [ { @@ -39,7 +39,7 @@ export const VIEW_LAYOUTS = [ }, ]; -export function getMandatoryFields( view: View ): string[] { +export function getNotHidableFieldIds( view: View ): string[] { if ( view.type === 'table' ) { return [ view.layout?.primaryField ] .concat( @@ -64,3 +64,64 @@ export function getMandatoryFields( view: View ): string[] { return []; } + +function getCombinedFieldIds( view: View ): string[] { + const combinedFields: string[] = []; + if ( view.type === LAYOUT_TABLE && view.layout?.combinedFields ) { + view.layout.combinedFields.forEach( ( combination ) => { + combinedFields.push( ...combination.children ); + } ); + } + return combinedFields; +} + +export function getVisibleFieldIds( + view: View, + fields: Field< any >[] +): string[] { + const fieldsToExclude = getCombinedFieldIds( view ); + + if ( view.fields ) { + return view.fields.filter( ( id ) => ! fieldsToExclude.includes( id ) ); + } + + const visibleFields = []; + if ( view.type === LAYOUT_TABLE && view.layout?.combinedFields ) { + visibleFields.push( + ...view.layout.combinedFields.map( ( { id } ) => id ) + ); + } + visibleFields.push( + ...fields + .filter( ( { id } ) => ! fieldsToExclude.includes( id ) ) + .map( ( { id } ) => id ) + ); + + return visibleFields; +} + +export function getHiddenFieldIds( + view: View, + fields: Field< any >[] +): string[] { + const fieldsToExclude = [ + ...getCombinedFieldIds( view ), + ...getVisibleFieldIds( view, fields ), + ]; + + // The media field does not need to be in the view.fields to be displayed. + if ( view.type === LAYOUT_GRID && view.layout?.mediaField ) { + fieldsToExclude.push( view.layout?.mediaField ); + } + + if ( view.type === LAYOUT_LIST && view.layout?.mediaField ) { + fieldsToExclude.push( view.layout?.mediaField ); + } + + return fields + .filter( + ( { id, enableHiding } ) => + ! fieldsToExclude.includes( id ) && enableHiding + ) + .map( ( { id } ) => id ); +} diff --git a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx index b019cbae36ab3a..aff211fb613dcf 100644 --- a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx @@ -25,7 +25,9 @@ import type { NormalizedField, SortDirection, ViewTable as ViewTableType, + Operator, } from '../../types'; +import { getVisibleFieldIds } from '../index'; const { DropdownMenuV2 } = unlock( componentsPrivateApis ); @@ -60,30 +62,43 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( }: HeaderMenuProps< Item >, ref: Ref< HTMLButtonElement > ) { + const visibleFieldIds = getVisibleFieldIds( view, fields ); + const index = visibleFieldIds?.indexOf( fieldId ) as number; + const isSorted = view.sort?.field === fieldId; + let isHidable = false; + let isSortable = false; + let canAddFilter = false; + let header; + let operators: Operator[] = []; + const combinedField = view.layout?.combinedFields?.find( ( f ) => f.id === fieldId ); - const index = view.fields?.indexOf( fieldId ) as number; - if ( !! combinedField ) { - return combinedField.header || combinedField.label; - } const field = fields.find( ( f ) => f.id === fieldId ); - if ( ! field ) { - return null; + + if ( ! combinedField ) { + if ( ! field ) { + // No combined or regular field found. + return null; + } + + isHidable = field.enableHiding !== false; + isSortable = field.enableSorting !== false; + header = field.header; + + operators = sanitizeOperators( field ); + // Filter can be added: + // 1. If the field is not already part of a view's filters. + // 2. If the field meets the type and operator requirements. + // 3. If it's not primary. If it is, it should be already visible. + canAddFilter = + ! view.filters?.some( ( _filter ) => fieldId === _filter.field ) && + !! field.elements?.length && + !! operators.length && + ! field.filterBy?.isPrimary; + } else { + header = combinedField.header || combinedField.label; } - const isHidable = field.enableHiding !== false; - const isSortable = field.enableSorting !== false; - const isSorted = view.sort?.field === field.id; - const operators = sanitizeOperators( field ); - // Filter can be added: - // 1. If the field is not already part of a view's filters. - // 2. If the field meets the type and operator requirements. - // 3. If it's not primary. If it is, it should be already visible. - const canAddFilter = - ! view.filters?.some( ( _filter ) => field.id === _filter.field ) && - !! field.elements?.length && - !! operators.length && - ! field.filterBy?.isPrimary; return ( <DropdownMenuV2 @@ -95,7 +110,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( ref={ ref } variant="tertiary" > - { field.header } + { header } { view.sort && isSorted && ( <span aria-hidden="true"> { sortArrows[ view.sort.direction ] } @@ -115,7 +130,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( isSorted && view.sort.direction === direction; - const value = `${ field.id }-${ direction }`; + const value = `${ fieldId }-${ direction }`; return ( <DropdownMenuV2.RadioItem @@ -132,7 +147,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( onChangeView( { ...view, sort: { - field: field.id, + field: fieldId, direction, }, } ); @@ -152,14 +167,14 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( <DropdownMenuV2.Item prefix={ <Icon icon={ funnel } /> } onClick={ () => { - setOpenedFilter( field.id ); + setOpenedFilter( fieldId ); onChangeView( { ...view, page: 1, filters: [ ...( view.filters || [] ), { - field: field.id, + field: fieldId, value: undefined, operator: operators[ 0 ], }, @@ -178,17 +193,16 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( prefix={ <Icon icon={ arrowLeft } /> } disabled={ index < 1 } onClick={ () => { - if ( ! view.fields || index < 1 ) { - return; - } onChangeView( { ...view, fields: [ - ...( view.fields.slice( 0, index - 1 ) ?? - [] ), - field.id, - view.fields[ index - 1 ], - ...view.fields.slice( index + 1 ), + ...( visibleFieldIds.slice( + 0, + index - 1 + ) ?? [] ), + fieldId, + visibleFieldIds[ index - 1 ], + ...visibleFieldIds.slice( index + 1 ), ], } ); } } @@ -199,23 +213,16 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( </DropdownMenuV2.Item> <DropdownMenuV2.Item prefix={ <Icon icon={ arrowRight } /> } - disabled={ - ! view.fields || index >= view.fields.length - 1 - } + disabled={ index >= visibleFieldIds.length - 1 } onClick={ () => { - if ( - ! view.fields || - index >= view.fields.length - 1 - ) { - return; - } onChangeView( { ...view, fields: [ - ...( view.fields.slice( 0, index ) ?? [] ), - view.fields[ index + 1 ], - field.id, - ...view.fields.slice( index + 2 ), + ...( visibleFieldIds.slice( 0, index ) ?? + [] ), + visibleFieldIds[ index + 1 ], + fieldId, + ...visibleFieldIds.slice( index + 2 ), ], } ); } } @@ -224,17 +231,15 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( { __( 'Move right' ) } </DropdownMenuV2.ItemLabel> </DropdownMenuV2.Item> - { isHidable && ( + { isHidable && field && ( <DropdownMenuV2.Item prefix={ <Icon icon={ unseen } /> } onClick={ () => { - const viewFields = - view.fields || fields.map( ( f ) => f.id ); onHide( field ); onChangeView( { ...view, - fields: viewFields.filter( - ( id ) => id !== field.id + fields: visibleFieldIds.filter( + ( id ) => id !== fieldId ), } ); } } diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index b12082a55623b2..4e1607b01489c2 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -34,6 +34,7 @@ import type { } from '../../types'; import type { SetSelection } from '../../private-types'; import ColumnHeaderMenu from './column-header-menu'; +import { getVisibleFieldIds } from '../index'; interface TableColumnFieldProps< Item > { primaryField?: NormalizedField< Item >; @@ -155,7 +156,7 @@ function TableRow< Item >( { // `onClick` and can be used to exclude touchscreen devices from certain // behaviours. const isTouchDeviceRef = useRef( false ); - const columns = view.fields || fields.map( ( f ) => f.id ); + const columns = getVisibleFieldIds( view, fields ); return ( <tr @@ -288,7 +289,7 @@ function ViewTable< Item >( { setNextHeaderMenuToFocus( fallback?.node ); }; - const columns = view.fields || fields.map( ( f ) => f.id ); + const columns = getVisibleFieldIds( view, fields ); const hasData = !! data?.length; const primaryField = fields.find( diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index 5f0baec12c4df2..2d1cc0402bc206 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -61,6 +61,8 @@ export function normalizeFields< Item >( sort, isValid, Edit, + enableHiding: field.enableHiding ?? true, + enableSorting: field.enableSorting ?? true, }; } ); } diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index ca55442f6529a5..e95a43994cd63d 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -163,6 +163,8 @@ export type NormalizedField< Item > = Field< Item > & { Edit: ComponentType< DataFormControlProps< Item > >; sort: ( a: Item, b: Item, direction: SortDirection ) => number; isValid: ( item: Item, context?: ValidationContext ) => boolean; + enableHiding: boolean; + enableSorting: boolean; }; /** From 18164f0fcd09a282157f02bba7fd737012cc44fd Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Tue, 3 Sep 2024 15:22:05 +0100 Subject: [PATCH 0650/1908] Fix error and improve privacy of sectionRootClientId setting (#65000) Co-authored-by: Daniel Richards 677833+talldan@users.noreply.github.com --- .../block-tools/zoom-out-mode-inserters.js | 4 ++-- .../src/components/inner-blocks/index.js | 4 +++- .../src/components/use-block-drop-zone/index.js | 4 +++- packages/block-editor/src/private-apis.js | 2 ++ packages/block-editor/src/store/actions.js | 10 ++++++---- packages/block-editor/src/store/private-keys.js | 1 + packages/block-editor/src/store/selectors.js | 16 +++++++++++----- .../src/components/inserter-sidebar/index.js | 7 +++++-- .../provider/use-block-editor-settings.js | 9 ++++----- 9 files changed, 37 insertions(+), 20 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js index bb044f9479c024..d15ee34714f5de 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js @@ -10,7 +10,7 @@ import { useEffect, useState } from '@wordpress/element'; import BlockPopoverInbetween from '../block-popover/inbetween'; import ZoomOutModeInserterButton from './zoom-out-mode-inserter-button'; import { store as blockEditorStore } from '../../store'; -import { unlock } from '../../lock-unlock'; +import { sectionRootClientIdKey } from '../../store/private-keys'; function ZoomOutModeInserters() { const [ isReady, setIsReady ] = useState( false ); @@ -33,7 +33,7 @@ function ZoomOutModeInserters() { getHoveredBlockClientId, isBlockInsertionPointVisible, } = select( blockEditorStore ); - const { sectionRootClientId: root } = unlock( getSettings() ); + const { [ sectionRootClientIdKey ]: root } = getSettings(); return { hasSelection: !! getSelectionStart().clientId, blockInsertionPoint: getBlockInsertionPoint(), diff --git a/packages/block-editor/src/components/inner-blocks/index.js b/packages/block-editor/src/components/inner-blocks/index.js index c8db9f8cebf905..9702044aeca6b0 100644 --- a/packages/block-editor/src/components/inner-blocks/index.js +++ b/packages/block-editor/src/components/inner-blocks/index.js @@ -30,6 +30,7 @@ import useBlockSync from '../provider/use-block-sync'; import { store as blockEditorStore } from '../../store'; import useBlockDropZone from '../use-block-drop-zone'; import { unlock } from '../../lock-unlock'; +import { sectionRootClientIdKey } from '../../store/private-keys'; const EMPTY_OBJECT = {}; @@ -225,7 +226,8 @@ export function useInnerBlocksProps( props = {}, options = {} ) { // In zoom out mode, we want to disable the drop zone for the sections. // The inner blocks belonging to the section drop zone is // already disabled by the blocks themselves being disabled. - const { sectionRootClientId } = unlock( getSettings() ); + const { [ sectionRootClientIdKey ]: sectionRootClientId } = + getSettings(); _isDropZoneDisabled = clientId !== sectionRootClientId; } 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 8115fe8f72a647..fb25368239a011 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 @@ -24,6 +24,7 @@ import { } from '../../utils/math'; import { store as blockEditorStore } from '../../store'; import { unlock } from '../../lock-unlock'; +import { sectionRootClientIdKey } from '../../store/private-keys'; const THRESHOLD_DISTANCE = 30; const MINIMUM_HEIGHT_FOR_THRESHOLD = 120; @@ -360,7 +361,8 @@ export default function useBlockDropZone( { return; } - const { sectionRootClientId } = unlock( getSettings() ); + const { [ sectionRootClientIdKey ]: sectionRootClientId } = + getSettings(); // In Zoom Out mode, if the target is not the section root provided by settings then // do not allow dropping as the drop target is not within the root (that which is diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 788bb2bef56efa..404c94940058ad 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -38,6 +38,7 @@ import { reusableBlocksSelectKey, globalStylesDataKey, globalStylesLinksDataKey, + sectionRootClientIdKey, } from './store/private-keys'; import { requiresWrapperOnCopy } from './components/writing-flow/utils'; import { PrivateRichText } from './components/rich-text/'; @@ -94,4 +95,5 @@ lock( privateApis, { __unstableBlockStyleVariationOverridesWithConfig, setBackgroundStyleDefaults, useBlockBindingsUtils, + sectionRootClientIdKey, } ); diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 319398667293e4..ebd310b3de9d3f 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -35,7 +35,8 @@ import { privateRemoveBlocks, } from './private-actions'; import { STORE_NAME } from './constants'; -import { unlock } from '../lock-unlock'; + +import { sectionRootClientIdKey } from './private-keys'; /** @typedef {import('../components/use-on-block-drop/types').WPDropOperation} WPDropOperation */ @@ -1674,9 +1675,10 @@ export const __unstableSetEditorMode = // When switching to zoom-out mode, we need to select the parent section if ( mode === 'zoom-out' ) { const firstSelectedClientId = select.getBlockSelectionStart(); - const { sectionRootClientId } = unlock( - registry.select( STORE_NAME ).getSettings() - ); + const { [ sectionRootClientIdKey ]: sectionRootClientId } = registry + .select( STORE_NAME ) + .getSettings(); + if ( firstSelectedClientId ) { let sectionClientId; diff --git a/packages/block-editor/src/store/private-keys.js b/packages/block-editor/src/store/private-keys.js index 00fac5531b9c3f..e24b4a6264e72f 100644 --- a/packages/block-editor/src/store/private-keys.js +++ b/packages/block-editor/src/store/private-keys.js @@ -2,3 +2,4 @@ export const globalStylesDataKey = Symbol( 'globalStylesDataKey' ); export const globalStylesLinksDataKey = Symbol( 'globalStylesLinks' ); export const selectBlockPatternsKey = Symbol( 'selectBlockPatternsKey' ); export const reusableBlocksSelectKey = Symbol( 'reusableBlocksSelect' ); +export const sectionRootClientIdKey = Symbol( 'sectionRootClientIdKey' ); diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index b30a719d21fd4d..2a840392fbffed 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -39,6 +39,8 @@ import { getTemporarilyEditingFocusModeToRevert, } from './private-selectors'; +import { sectionRootClientIdKey } from './private-keys'; + /** * A block selection object. * @@ -2058,9 +2060,10 @@ export const getInserterItems = createRegistrySelector( ( select ) => if ( ! item.rootClientId ) { let sectionRootClientId; try { - sectionRootClientId = unlock( - getSettings( state ) - ).sectionRootClientId; + sectionRootClientId = + getSettings( state )[ + sectionRootClientIdKey + ]; } catch ( e ) {} if ( sectionRootClientId && @@ -2838,7 +2841,8 @@ export function __unstableHasActiveBlockOverlayActive( state, clientId ) { // In zoom-out mode, the block overlay is always active for section level blocks. if ( editorMode === 'zoom-out' ) { - const { sectionRootClientId } = unlock( getSettings( state ) ); + const { [ sectionRootClientIdKey ]: sectionRootClientId } = + getSettings( state ); if ( sectionRootClientId ) { const sectionClientIds = getBlockOrder( state, @@ -2931,7 +2935,9 @@ export const getBlockEditingMode = createRegistrySelector( // sections. const editorMode = __unstableGetEditorMode( state ); if ( editorMode === 'zoom-out' ) { - const { sectionRootClientId } = unlock( getSettings( state ) ); + const { [ sectionRootClientIdKey ]: sectionRootClientId } = + getSettings( state ); + if ( clientId === '' /* ROOT_CONTAINER_CLIENT_ID */ ) { return sectionRootClientId ? 'disabled' : 'contentOnly'; } diff --git a/packages/editor/src/components/inserter-sidebar/index.js b/packages/editor/src/components/inserter-sidebar/index.js index bf613b5c8c001a..3e54fec6cc06b8 100644 --- a/packages/editor/src/components/inserter-sidebar/index.js +++ b/packages/editor/src/components/inserter-sidebar/index.js @@ -18,7 +18,9 @@ import { store as interfaceStore } from '@wordpress/interface'; import { unlock } from '../../lock-unlock'; import { store as editorStore } from '../../store'; -const { PrivateInserterLibrary } = unlock( blockEditorPrivateApis ); +const { PrivateInserterLibrary, sectionRootClientIdKey } = unlock( + blockEditorPrivateApis +); export default function InserterSidebar() { const { @@ -44,7 +46,8 @@ export default function InserterSidebar() { const { getActiveComplementaryArea } = select( interfaceStore ); const getBlockSectionRootClientId = () => { if ( __unstableGetEditorMode() === 'zoom-out' ) { - const { sectionRootClientId } = unlock( getSettings() ); + const { [ sectionRootClientIdKey ]: sectionRootClientId } = + getSettings(); if ( sectionRootClientId ) { return sectionRootClientId; } diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 6aa2763cf9db06..69e544be99d0ee 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -23,7 +23,7 @@ import { import inserterMediaCategories from '../media-categories'; import { mediaUpload } from '../../utils'; import { store as editorStore } from '../../store'; -import { lock, unlock } from '../../lock-unlock'; +import { unlock } from '../../lock-unlock'; import { useGlobalStylesContext } from '../global-styles-provider'; const EMPTY_BLOCKS_LIST = []; @@ -74,7 +74,6 @@ const BLOCK_EDITOR_SETTINGS = [ 'postContentAttributes', 'postsPerPage', 'readOnly', - 'sectionRootClientId', 'styles', 'titlePlaceholder', 'supportsLayout', @@ -90,6 +89,7 @@ const { globalStylesLinksDataKey, selectBlockPatternsKey, reusableBlocksSelectKey, + sectionRootClientIdKey, } = unlock( privateApis ); /** @@ -325,10 +325,9 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { ? [ [ 'core/navigation', {}, [] ] ] : settings.template, __experimentalSetIsInserterOpened: setIsInserterOpened, + [ sectionRootClientIdKey ]: sectionRootClientId, }; - lock( blockEditorSettings, { - sectionRootClientId, - } ); + return blockEditorSettings; }, [ allowedBlockTypes, From ebabad69cd486448ccf3a6521810e90c7857a65f Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Tue, 3 Sep 2024 17:38:15 +0200 Subject: [PATCH 0651/1908] Rely on `Text` component instead of `Truncate` (#65007) Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- packages/block-editor/src/hooks/block-bindings.js | 15 ++++++--------- .../block-editor/src/hooks/block-bindings.scss | 2 +- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index ea069c15a028fe..c1422acaac0e5a 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -9,7 +9,6 @@ import { __experimentalText as Text, __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, - __experimentalTruncate as Truncate, __experimentalVStack as VStack, privateApis as componentsPrivateApis, } from '@wordpress/components'; @@ -98,19 +97,17 @@ function BlockBindingsAttribute( { attribute, binding } ) { unlock( blocksPrivateApis ).getBlockBindingsSource( sourceName ); const isSourceInvalid = ! sourceProps; return ( - <VStack> - <Truncate>{ attribute }</Truncate> + <VStack className="block-editor-bindings__item"> + <Text truncate>{ attribute }</Text> { !! binding && ( <Text + truncate variant={ ! isSourceInvalid && 'muted' } - className="block-editor-bindings__item-explanation" isDestructive={ isSourceInvalid } > - <Truncate> - { isSourceInvalid - ? __( 'Invalid source' ) - : args?.key || sourceProps?.label || sourceName } - </Truncate> + { isSourceInvalid + ? __( 'Invalid source' ) + : args?.key || sourceProps?.label || sourceName } </Text> ) } </VStack> diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss index 69eaa18d57daea..e8f05895922f0f 100644 --- a/packages/block-editor/src/hooks/block-bindings.scss +++ b/packages/block-editor/src/hooks/block-bindings.scss @@ -1,6 +1,6 @@ div.block-editor-bindings__panel { grid-template-columns: repeat(auto-fit, minmax(100%, 1fr)); - button:hover .block-editor-bindings__item-explanation { + button:hover .block-editor-bindings__item span { color: inherit; } } From e2d5864d6ffd316793d808dfa713506a8b46c626 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Tue, 3 Sep 2024 21:12:45 +0530 Subject: [PATCH 0652/1908] Comment Edit Link: Add Border Block Support (#64239) * Add Border Support * Hide Default Spacing & Border Control default Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/comment-edit-link/block.json | 15 +++++++++++++-- .../src/comment-edit-link/style.scss | 4 ++++ packages/block-library/src/style.scss | 1 + 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 packages/block-library/src/comment-edit-link/style.scss diff --git a/packages/block-library/src/comment-edit-link/block.json b/packages/block-library/src/comment-edit-link/block.json index a49f9a23161b80..578b284715c2a0 100644 --- a/packages/block-library/src/comment-edit-link/block.json +++ b/packages/block-library/src/comment-edit-link/block.json @@ -30,7 +30,11 @@ }, "spacing": { "margin": true, - "padding": true + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } }, "typography": { "fontSize": true, @@ -47,6 +51,13 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true } - } + }, + "style": "wp-block-comment-edit-link" } diff --git a/packages/block-library/src/comment-edit-link/style.scss b/packages/block-library/src/comment-edit-link/style.scss new file mode 100644 index 00000000000000..1ae7daf55009e4 --- /dev/null +++ b/packages/block-library/src/comment-edit-link/style.scss @@ -0,0 +1,4 @@ +.wp-block-comment-edit-link { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; +} diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index 7906a1231d922b..8549b80ae89de2 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -13,6 +13,7 @@ @import "./comment-date/style.scss"; @import "./comment-content/style.scss"; @import "./comment-author-name/style.scss"; +@import "./comment-edit-link/style.scss"; @import "./cover/style.scss"; @import "./details/style.scss"; @import "./embed/style.scss"; From 14a8cf3cc0eac2c084d24fce5492ac34a879f2e6 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 3 Sep 2024 18:10:22 +0200 Subject: [PATCH 0653/1908] Dataviews list view: do not use Composite store (#64987) * Move over changes from POW PR * Simpler new active item comment * Simplify dropdown trigger keydown override * Simplify getItemDomId * Further simplify dropdown menu trigger keydown handler * Extract primary action grid cell to separate component * Sort render function order for better logic flow * Extract more logic to generate IDs + always use ID prefix * Fix buggy initial active composite ID logic * Add key to primary action gridcell --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../src/dataviews-layouts/list/index.tsx | 326 +++++++++++------- 1 file changed, 199 insertions(+), 127 deletions(-) diff --git a/packages/dataviews/src/dataviews-layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx index d8889f25b24e9c..00146c3ee35220 100644 --- a/packages/dataviews/src/dataviews-layouts/list/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/list/index.tsx @@ -2,17 +2,11 @@ * External dependencies */ import clsx from 'clsx'; -// TODO: use the @wordpress/components one once public -// eslint-disable-next-line no-restricted-imports -import { useStoreState } from '@ariakit/react'; -// Import CompositeStore type, which is not exported from @wordpress/components. -// eslint-disable-next-line no-restricted-imports -import type { CompositeStore } from '@ariakit/react'; /** * WordPress dependencies */ -import { useInstanceId } from '@wordpress/compose'; +import { useInstanceId, usePrevious } from '@wordpress/compose'; import { __experimentalHStack as HStack, __experimentalVStack as VStack, @@ -44,39 +38,115 @@ import type { Action, NormalizedField, ViewListProps } from '../../types'; interface ListViewItemProps< Item > { actions: Action< Item >[]; - id?: string; + idPrefix: string; isSelected: boolean; item: Item; mediaField?: NormalizedField< Item >; onSelect: ( item: Item ) => void; primaryField?: NormalizedField< Item >; - store: CompositeStore; visibleFields: NormalizedField< Item >[]; + onDropdownTriggerKeyDown: React.KeyboardEventHandler< HTMLButtonElement >; } const { - useCompositeStoreV2: useCompositeStore, CompositeV2: Composite, CompositeItemV2: CompositeItem, CompositeRowV2: CompositeRow, DropdownMenuV2: DropdownMenu, } = unlock( componentsPrivateApis ); +function generateItemWrapperCompositeId( idPrefix: string ) { + return `${ idPrefix }-item-wrapper`; +} +function generatePrimaryActionCompositeId( + idPrefix: string, + primaryActionId: string +) { + return `${ idPrefix }-primary-action-${ primaryActionId }`; +} +function generateDropdownTriggerCompositeId( idPrefix: string ) { + return `${ idPrefix }-dropdown`; +} + +function PrimaryActionGridCell< Item >( { + idPrefix, + primaryAction, + item, +}: { + idPrefix: string; + primaryAction: Action< Item >; + item: Item; +} ) { + const registry = useRegistry(); + const [ isModalOpen, setIsModalOpen ] = useState( false ); + + const compositeItemId = generatePrimaryActionCompositeId( + idPrefix, + primaryAction.id + ); + + const label = + typeof primaryAction.label === 'string' + ? primaryAction.label + : primaryAction.label( [ item ] ); + + return 'RenderModal' in primaryAction ? ( + <div role="gridcell" key={ primaryAction.id }> + <CompositeItem + id={ compositeItemId } + render={ + <Button + label={ label } + icon={ primaryAction.icon } + isDestructive={ primaryAction.isDestructive } + size="small" + onClick={ () => setIsModalOpen( true ) } + /> + } + > + { isModalOpen && ( + <ActionModal< Item > + action={ primaryAction } + items={ [ item ] } + closeModal={ () => setIsModalOpen( false ) } + /> + ) } + </CompositeItem> + </div> + ) : ( + <div role="gridcell" key={ primaryAction.id }> + <CompositeItem + id={ compositeItemId } + render={ + <Button + label={ label } + icon={ primaryAction.icon } + isDestructive={ primaryAction.isDestructive } + size="small" + onClick={ () => { + primaryAction.callback( [ item ], { registry } ); + } } + /> + } + /> + </div> + ); +} + function ListItem< Item >( { actions, - id, + idPrefix, isSelected, item, mediaField, onSelect, primaryField, - store, visibleFields, + onDropdownTriggerKeyDown, }: ListViewItemProps< Item > ) { - const registry = useRegistry(); const itemRef = useRef< HTMLElement >( null ); - const labelId = `${ id }-label`; - const descriptionId = `${ id }-description`; + const labelId = `${ idPrefix }-label`; + const descriptionId = `${ idPrefix }-description`; const [ isHovered, setIsHovered ] = useState( false ); const handleMouseEnter = () => { @@ -111,13 +181,6 @@ function ListItem< Item >( { }; }, [ actions, item ] ); - const [ isModalOpen, setIsModalOpen ] = useState( false ); - const primaryActionLabel = - primaryAction && - ( typeof primaryAction.label === 'string' - ? primaryAction.label - : primaryAction.label( [ item ] ) ); - const renderedMediaField = mediaField?.render ? ( <mediaField.render item={ item } /> ) : ( @@ -147,10 +210,9 @@ function ListItem< Item >( { > <div role="gridcell"> <CompositeItem - store={ store } render={ <div /> } role="button" - id={ id } + id={ generateItemWrapperCompositeId( idPrefix ) } aria-pressed={ isSelected } aria-labelledby={ labelId } aria-describedby={ descriptionId } @@ -210,65 +272,20 @@ function ListItem< Item >( { width: 'auto', } } > - { primaryAction && 'RenderModal' in primaryAction && ( - <div role="gridcell"> - <CompositeItem - store={ store } - render={ - <Button - label={ primaryActionLabel } - icon={ primaryAction.icon } - isDestructive={ - primaryAction.isDestructive - } - size="small" - onClick={ () => - setIsModalOpen( true ) - } - /> - } - > - { isModalOpen && ( - <ActionModal< Item > - action={ primaryAction } - items={ [ item ] } - closeModal={ () => - setIsModalOpen( false ) - } - /> - ) } - </CompositeItem> - </div> + { primaryAction && ( + <PrimaryActionGridCell + idPrefix={ idPrefix } + primaryAction={ primaryAction } + item={ item } + /> ) } - { primaryAction && - ! ( 'RenderModal' in primaryAction ) && ( - <div role="gridcell" key={ primaryAction.id }> - <CompositeItem - store={ store } - render={ - <Button - label={ primaryActionLabel } - icon={ primaryAction.icon } - isDestructive={ - primaryAction.isDestructive - } - size="small" - onClick={ () => { - primaryAction.callback( - [ item ], - { registry } - ); - } } - /> - } - /> - </div> - ) } <div role="gridcell"> <DropdownMenu trigger={ <CompositeItem - store={ store } + id={ generateDropdownTriggerCompositeId( + idPrefix + ) } render={ <Button size="small" @@ -276,30 +293,9 @@ function ListItem< Item >( { label={ __( 'Actions' ) } accessibleWhenDisabled disabled={ ! actions.length } - onKeyDown={ ( event: { - key: string; - preventDefault: () => void; - } ) => { - if ( - event.key === - 'ArrowDown' - ) { - // Prevent the default behaviour (open dropdown menu) and go down. - event.preventDefault(); - store.move( - store.down() - ); - } - if ( - event.key === 'ArrowUp' - ) { - // Prevent the default behavior (open dropdown menu) and go up. - event.preventDefault(); - store.move( - store.up() - ); - } - } } + onKeyDown={ + onDropdownTriggerKeyDown + } /> } /> @@ -331,6 +327,7 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) { view, } = props; const baseId = useInstanceId( ViewList, 'view-list' ); + const selectedItem = data?.findLast( ( item ) => selection.includes( getItemId( item ) ) ); @@ -353,34 +350,108 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) { const onSelect = ( item: Item ) => onChangeSelection( [ getItemId( item ) ] ); - const getItemDomId = useCallback( - ( item?: Item ) => - item ? `${ baseId }-${ getItemId( item ) }` : undefined, + const generateCompositeItemIdPrefix = useCallback( + ( item: Item ) => `${ baseId }-${ getItemId( item ) }`, [ baseId, getItemId ] ); - const store = useCompositeStore( { - defaultActiveId: getItemDomId( selectedItem ), - } ) as CompositeStore; // TODO, remove once composite APIs are public + const isActiveCompositeItem = useCallback( + ( item: Item, idToCheck: string ) => { + // All composite items use the same prefix in their IDs. + return idToCheck.startsWith( + generateCompositeItemIdPrefix( item ) + ); + }, + [ generateCompositeItemIdPrefix ] + ); - // Manage focused item, when the active one is removed from the list. - const isActiveIdInList = useStoreState( - store, - ( state: { items: any[]; activeId: any } ) => - state.items.some( - ( item: { id: any } ) => item.id === state.activeId - ) + // Controlled state for the active composite item. + const [ activeCompositeId, setActiveCompositeId ] = useState< + string | null | undefined + >( undefined ); + + // Update the active composite item when the selected item changes. + useEffect( () => { + if ( selectedItem ) { + setActiveCompositeId( + generateItemWrapperCompositeId( + generateCompositeItemIdPrefix( selectedItem ) + ) + ); + } + }, [ selectedItem, generateCompositeItemIdPrefix ] ); + + const activeItemIndex = data.findIndex( ( item ) => + isActiveCompositeItem( item, activeCompositeId ?? '' ) ); + const previousActiveItemIndex = usePrevious( activeItemIndex ); + const isActiveIdInList = activeItemIndex !== -1; + + const selectCompositeItem = useCallback( + ( + targetIndex: number, + // Allows invokers to specify a custom function to generate the + // target composite item ID + generateCompositeId: ( idPrefix: string ) => string + ) => { + // Clamping between 0 and data.length - 1 to avoid out of bounds. + const clampedIndex = Math.min( + data.length - 1, + Math.max( 0, targetIndex ) + ); + const itemIdPrefix = generateCompositeItemIdPrefix( + data[ clampedIndex ] + ); + const targetCompositeItemId = generateCompositeId( itemIdPrefix ); + + setActiveCompositeId( targetCompositeItemId ); + document.getElementById( targetCompositeItemId )?.focus(); + }, + [ data, generateCompositeItemIdPrefix ] + ); + + // Select a new active composite item when the current active item + // is removed from the list. useEffect( () => { - if ( ! isActiveIdInList ) { - // Prefer going down, except if there is no item below (last item), then go up (last item in list). - if ( store.down() ) { - store.move( store.down() ); - } else if ( store.up() ) { - store.move( store.up() ); - } + const wasActiveIdInList = + previousActiveItemIndex !== undefined && + previousActiveItemIndex !== -1; + if ( ! isActiveIdInList && wasActiveIdInList ) { + // By picking `previousActiveItemIndex` as the next item index, we are + // basically picking the item that would have been after the deleted one. + // If the previously active (and removed) item was the last of the list, + // we will select the item before it — which is the new last item. + selectCompositeItem( + previousActiveItemIndex, + generateItemWrapperCompositeId + ); } - }, [ isActiveIdInList ] ); + }, [ isActiveIdInList, selectCompositeItem, previousActiveItemIndex ] ); + + // Prevent the default behavior (open dropdown menu) and instead select the + // dropdown menu trigger on the previous/next row. + // https://github.com/ariakit/ariakit/issues/3768 + const onDropdownTriggerKeyDown = useCallback( + ( event: React.KeyboardEvent< HTMLButtonElement > ) => { + if ( event.key === 'ArrowDown' ) { + // Select the dropdown menu trigger item in the next row. + event.preventDefault(); + selectCompositeItem( + activeItemIndex + 1, + generateDropdownTriggerCompositeId + ); + } + if ( event.key === 'ArrowUp' ) { + // Select the dropdown menu trigger item in the previous row. + event.preventDefault(); + selectCompositeItem( + activeItemIndex - 1, + generateDropdownTriggerCompositeId + ); + } + }, + [ selectCompositeItem, activeItemIndex ] + ); const hasData = data?.length; if ( ! hasData ) { @@ -404,22 +475,23 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) { render={ <ul /> } className="dataviews-view-list" role="grid" - store={ store } + activeId={ activeCompositeId } + setActiveId={ setActiveCompositeId } > { data.map( ( item ) => { - const id = getItemDomId( item ); + const id = generateCompositeItemIdPrefix( item ); return ( <ListItem key={ id } - id={ id } + idPrefix={ id } actions={ actions } item={ item } isSelected={ item === selectedItem } onSelect={ onSelect } mediaField={ mediaField } primaryField={ primaryField } - store={ store } visibleFields={ visibleFields } + onDropdownTriggerKeyDown={ onDropdownTriggerKeyDown } /> ); } ) } From d35a3715f9be0ef46aebfe69c00b1b675506fba2 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 4 Sep 2024 03:58:48 +0900 Subject: [PATCH 0654/1908] Deprecate `DimensionControl` (#64951) * Update readme * Mark as `@deprecated` * Remove mentions in ResponsiveBlockControl readme * Move to deprecated group in Storybook * Fixup JSDocs * Throw deprecation warning * Fix test * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../responsive-block-control/README.md | 30 ++----------------- packages/components/CHANGELOG.md | 1 + .../src/dimension-control/README.md | 4 +++ .../src/dimension-control/index.tsx | 8 ++++- .../dimension-control/stories/index.story.tsx | 9 ++++-- .../src/dimension-control/test/index.test.js | 1 + storybook/manager-head.html | 1 + 7 files changed, 24 insertions(+), 30 deletions(-) diff --git a/packages/block-editor/src/components/responsive-block-control/README.md b/packages/block-editor/src/components/responsive-block-control/README.md index 379e245f03ff37..16183ccd6314f5 100644 --- a/packages/block-editor/src/components/responsive-block-control/README.md +++ b/packages/block-editor/src/components/responsive-block-control/README.md @@ -27,9 +27,6 @@ import { InspectorControls, __experimentalResponsiveBlockControl as ResponsiveBlockControl, } from '@wordpress/block-editor'; -import { - DimensionControl, -} from '@wordpress/components'; registerBlockType( 'my-plugin/my-block', { // ... @@ -37,34 +34,13 @@ registerBlockType( 'my-plugin/my-block', { edit( { attributes, setAttributes } ) { const [ isResponsive, setIsResponsive ] = useState( false ); - - // Used for example purposes only - const sizeOptions = [ - { - label: 'Small', - value: 'small', - }, - { - label: 'Medium', - value: 'medium', - }, - { - label: 'Large', - value: 'large', - }, - ]; - const { paddingSize } = attributes; - // Your custom control can be anything you'd like to use. - // You are not restricted to `DimensionControl`s, but this - // makes life easier if dealing with standard CSS values. - // see `packages/components/src/dimension-control/README.md` const paddingControl = ( labelComponent, viewport ) => { return ( - <DimensionControl - __nextHasNoMarginBottom + <input + type="number" label={ viewport.label } onChange={ // handle update to padding value here } value={ paddingSize } @@ -155,7 +131,7 @@ const renderDefaultControl = ( labelComponent, viewport ) => { // id: 'small', // label: 'All' // } - return <DimensionControl label={ labelComponent } />; + return <SelectControl label={ labelComponent } />; }; ``` diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 5a58ddfda38b99..81ad1717801a95 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -7,6 +7,7 @@ - Deprecate `replace` from the options accepted by `useNavigator().goTo()` ([#64675](https://github.com/WordPress/gutenberg/pull/64675)). - Soft deprecate `size` prop on `AlignmentMatrixControl.Icon` ([#64827](https://github.com/WordPress/gutenberg/pull/64827)). - `__experimentalAlignmentMatrixControl` can now be imported as a stable `AlignmentMatrixControl` ([#60913](https://github.com/WordPress/gutenberg/pull/60913)). +- Deprecate `DimensionControl`, scheduled to be removed in WordPress 7.0 ([#64951](https://github.com/WordPress/gutenberg/pull/64951)). ### Enhancements diff --git a/packages/components/src/dimension-control/README.md b/packages/components/src/dimension-control/README.md index 3cd0191a046068..78c1a60275c13a 100644 --- a/packages/components/src/dimension-control/README.md +++ b/packages/components/src/dimension-control/README.md @@ -1,5 +1,9 @@ # DimensionControl +<div class="callout callout-alert"> +This component is deprecated. +</div> + <div class="callout callout-alert"> This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. </div> diff --git a/packages/components/src/dimension-control/index.tsx b/packages/components/src/dimension-control/index.tsx index 52662f31c3f24c..25880f9b4fdb38 100644 --- a/packages/components/src/dimension-control/index.tsx +++ b/packages/components/src/dimension-control/index.tsx @@ -17,6 +17,7 @@ import sizesTable, { findSizeBySlug } from './sizes'; import type { DimensionControlProps, Size } from './types'; import type { SelectControlSingleSelectionProps } from '../select-control/types'; import { ContextSystemProvider } from '../context'; +import deprecated from '@wordpress/deprecated'; const CONTEXT_VALUE = { BaseControl: { @@ -29,7 +30,7 @@ const CONTEXT_VALUE = { /** * `DimensionControl` is a component designed to provide a UI to control spacing and/or dimensions. * - * This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. + * @deprecated * * ```jsx * import { __experimentalDimensionControl as DimensionControl } from '@wordpress/components'; @@ -62,6 +63,11 @@ export function DimensionControl( props: DimensionControlProps ) { className = '', } = props; + deprecated( 'wp.components.DimensionControl', { + since: '6.7', + version: '7.0', + } ); + const onChangeSpacingSize: SelectControlSingleSelectionProps[ 'onChange' ] = ( val ) => { const theSize = findSizeBySlug( sizes, val ); diff --git a/packages/components/src/dimension-control/stories/index.story.tsx b/packages/components/src/dimension-control/stories/index.story.tsx index 3a6da44f461164..15a63fcf6ccf6c 100644 --- a/packages/components/src/dimension-control/stories/index.story.tsx +++ b/packages/components/src/dimension-control/stories/index.story.tsx @@ -13,9 +13,15 @@ import sizes from '../sizes'; */ import { desktop, tablet, mobile } from '@wordpress/icons'; +/** + * `DimensionControl` is a component designed to provide a UI to control spacing and/or dimensions. + * + * This component is deprecated. + */ const meta: Meta< typeof DimensionControl > = { component: DimensionControl, - title: 'Components (Experimental)/DimensionControl', + title: 'Components (Deprecated)/DimensionControl', + id: 'components-dimensioncontrol', argTypes: { onChange: { action: 'onChange' }, value: { control: { type: null } }, @@ -42,7 +48,6 @@ const Template: StoryFn< typeof DimensionControl > = ( args ) => ( ); export const Default = Template.bind( {} ); - Default.args = { __nextHasNoMarginBottom: true, label: 'Please select a size', diff --git a/packages/components/src/dimension-control/test/index.test.js b/packages/components/src/dimension-control/test/index.test.js index 1b34d2983ad0f1..14f1c509f70cf9 100644 --- a/packages/components/src/dimension-control/test/index.test.js +++ b/packages/components/src/dimension-control/test/index.test.js @@ -31,6 +31,7 @@ describe( 'DimensionControl', () => { const { container } = render( <DimensionControl instanceId={ instanceId } label="Padding" /> ); + expect( console ).toHaveWarned(); expect( container ).toMatchSnapshot(); } ); diff --git a/storybook/manager-head.html b/storybook/manager-head.html index 174433776e27c9..ebf2d6891ba0bb 100644 --- a/storybook/manager-head.html +++ b/storybook/manager-head.html @@ -3,6 +3,7 @@ const PREVIOUSLY_EXPERIMENTAL_COMPONENTS = [ 'alignmentmatrixcontrol', 'customselectcontrol-v2', + 'dimensioncontrol', 'navigation', 'progressbar', 'theme', From ef309ba7394b03ced076632258a30521f807a1d9 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 4 Sep 2024 05:17:41 +0900 Subject: [PATCH 0655/1908] UnitControl: Move to stricter lint rule for 40px size adherence (#65017) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .eslintrc.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index 484387a285e78b..caf01b7cbd71d4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -330,6 +330,7 @@ module.exports = { 'SelectControl', 'TextControl', 'ToggleGroupControl', + 'UnitControl', ].map( ( componentName ) => ( { // Falsy `__next40pxDefaultSize` without a non-default `size` prop. selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"][value.expression.value!=false])):not(:has(JSXAttribute[name.name="size"][value.value!="default"]))`, @@ -345,7 +346,7 @@ module.exports = { 'FormFileUpload should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', }, // Temporary rules until all existing components have the `__next40pxDefaultSize` prop. - ...[ 'Button', 'UnitControl' ].map( ( componentName ) => ( { + ...[ 'Button' ].map( ( componentName ) => ( { // Not strict. Allows pre-existing __next40pxDefaultSize={ false } usage until they are all manually updated. selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"])):not(:has(JSXAttribute[name.name="size"]))`, message: From 661d6296fd0e37476a457ddf8ea555a74c643a48 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Tue, 3 Sep 2024 16:32:22 -0700 Subject: [PATCH 0656/1908] Fix visibility of the template Welcome Guide in the Site Editor (#64789) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Require previous entity record for display * Show template edit notice only if welcome guide isn’t active * Hack around flash of presence * Use a simpler hack around flash of presence * Use edited entity record hook for post type condition * Read record type only if edited entity hook says it’s loaded Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- .../src/components/welcome-guide/template.js | 30 ++++++++----------- .../components/post-template/block-theme.js | 24 +++++++++------ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/packages/edit-site/src/components/welcome-guide/template.js b/packages/edit-site/src/components/welcome-guide/template.js index 0e699e6b4b242a..e6568a23bb3a3c 100644 --- a/packages/edit-site/src/components/welcome-guide/template.js +++ b/packages/edit-site/src/components/welcome-guide/template.js @@ -10,29 +10,23 @@ import { store as editorStore } from '@wordpress/editor'; /** * Internal dependencies */ -import { store as editSiteStore } from '../../store'; +import useEditedEntityRecord from '../use-edited-entity-record'; export default function WelcomeGuideTemplate() { const { toggle } = useDispatch( preferencesStore ); - const isVisible = useSelect( ( select ) => { - const isTemplateActive = !! select( preferencesStore ).get( - 'core/edit-site', - 'welcomeGuideTemplate' - ); - const isEditorActive = !! select( preferencesStore ).get( - 'core/edit-site', - 'welcomeGuide' - ); - const { isPage } = select( editSiteStore ); - const { getCurrentPostType } = select( editorStore ); - return ( - isTemplateActive && - ! isEditorActive && - isPage() && - getCurrentPostType() === 'wp_template' - ); + const { isLoaded, record } = useEditedEntityRecord(); + const isPostTypeTemplate = isLoaded && record.type === 'wp_template'; + const { isActive, hasPreviousEntity } = useSelect( ( select ) => { + const { getEditorSettings } = select( editorStore ); + const { get } = select( preferencesStore ); + return { + isActive: get( 'core/edit-site', 'welcomeGuideTemplate' ), + hasPreviousEntity: + !! getEditorSettings().onNavigateToPreviousEntityRecord, + }; }, [] ); + const isVisible = isActive && isPostTypeTemplate && hasPreviousEntity; if ( ! isVisible ) { return null; diff --git a/packages/editor/src/components/post-template/block-theme.js b/packages/editor/src/components/post-template/block-theme.js index 7fcc5ead14f5b8..62de10a2c715ff 100644 --- a/packages/editor/src/components/post-template/block-theme.js +++ b/packages/editor/src/components/post-template/block-theme.js @@ -8,6 +8,7 @@ import { __ } from '@wordpress/i18n'; import { useEntityRecord, store as coreStore } from '@wordpress/core-data'; import { check } from '@wordpress/icons'; import { store as noticesStore } from '@wordpress/notices'; +import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies @@ -43,6 +44,8 @@ export default function BlockThemeControl( { id } ) { }; }, [] ); + const { get: getPreference } = useSelect( preferencesStore ); + const { editedRecord: template, hasResolved } = useEntityRecord( 'postType', 'wp_template', @@ -75,6 +78,17 @@ export default function BlockThemeControl( { id } ) { }, ] : undefined; + + const mayShowTemplateEditNotice = () => { + if ( ! getPreference( 'core/edit-site', 'welcomeGuideTemplate' ) ) { + createSuccessNotice( + __( + 'Editing template. Changes made here affect all posts and pages that use the template.' + ), + { type: 'snackbar', actions: notificationAction } + ); + } + }; return ( <DropdownMenu popoverProps={ POPOVER_PROPS } @@ -99,15 +113,7 @@ export default function BlockThemeControl( { id } ) { postType: 'wp_template', } ); onClose(); - createSuccessNotice( - __( - 'Editing template. Changes made here affect all posts and pages that use the template.' - ), - { - type: 'snackbar', - actions: notificationAction, - } - ); + mayShowTemplateEditNotice(); } } > { __( 'Edit template' ) } From 3a310c4dc4ad1c08c38a5cd72972f3db11ae60a8 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 4 Sep 2024 11:39:46 +0900 Subject: [PATCH 0657/1908] Site Logo Block: Fix non-admin users seeing zero character (#65010) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/site-logo/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index edf8bbccfeb652..1d541ba35d6313 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -423,7 +423,7 @@ export default function LogoEdit( { context: 'view', } ); const _isRequestingMediaItem = - _siteLogoId && + !! _siteLogoId && ! select( coreStore ).hasFinishedResolution( 'getMedia', [ _siteLogoId, { context: 'view' }, From d179303b68f47c9ed68fb5c5af5a63df743ebb79 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 4 Sep 2024 11:30:42 +0400 Subject: [PATCH 0658/1908] Pattern: Don't render block controls when an entity is missing (#65028) * Pattern: Don't render block controls when an entity is missing * Reference correct 'ButtonBlockAppender' Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-library/src/block/edit.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/block/edit.js b/packages/block-library/src/block/edit.js index 53422e1c4cb8c0..3dd5faf67b31f6 100644 --- a/packages/block-library/src/block/edit.js +++ b/packages/block-library/src/block/edit.js @@ -29,6 +29,7 @@ import { privateApis as blockEditorPrivateApis, store as blockEditorStore, BlockControls, + InnerBlocks, } from '@wordpress/block-editor'; import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; import { store as blocksStore } from '@wordpress/blocks'; @@ -254,7 +255,9 @@ function ReusableBlockEdit( { value: innerBlocks.length > 0 ? innerBlocks : blocks, onInput: NOOP, onChange: NOOP, - renderAppender: blocks?.length ? undefined : blocks.ButtonBlockAppender, + renderAppender: blocks?.length + ? undefined + : InnerBlocks.ButtonBlockAppender, } ); const handleEditOriginal = () => { @@ -292,7 +295,7 @@ function ReusableBlockEdit( { return ( <> - { hasResolved && ( + { hasResolved && ! isMissing && ( <ReusableBlockControl recordId={ ref } canOverrideBlocks={ canOverrideBlocks } From 3aaf6ffeaa433b61b44c9bbd7ea8c86bb773337b Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Wed, 4 Sep 2024 10:51:41 +0200 Subject: [PATCH 0659/1908] Range control: Restore bottom margin rule. (#65035) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../block-editor/src/components/spacing-sizes-control/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/components/spacing-sizes-control/style.scss b/packages/block-editor/src/components/spacing-sizes-control/style.scss index cbcc8e30c58253..a387e5369d01ed 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/style.scss +++ b/packages/block-editor/src/components/spacing-sizes-control/style.scss @@ -19,6 +19,7 @@ .spacing-sizes-control__range-control, .spacing-sizes-control__custom-value-range { flex: 1; + margin-bottom: 0; // Needed for some instances of the range control, such as the Spacer block. } .components-range-control__mark { From 9cf31628d2844caa7ddedee87a7a00676aa01192 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Wed, 4 Sep 2024 10:11:23 +0100 Subject: [PATCH 0660/1908] Add selector for getting section root clientId (#65001) * Normalize usage to private selector * Remove the lock * Avoid double call * Avoid setting default in selector Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> --- .../block-tools/zoom-out-mode-inserters.js | 9 ++++++--- .../src/components/inner-blocks/index.js | 6 ++---- .../src/components/use-block-drop-zone/index.js | 10 ++++------ packages/block-editor/src/store/actions.js | 10 +++------- .../block-editor/src/store/private-selectors.js | 5 +++++ packages/block-editor/src/store/selectors.js | 13 ++++--------- .../editor/src/components/inserter-sidebar/index.js | 12 +++++------- 7 files changed, 29 insertions(+), 36 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js index d15ee34714f5de..30d51654b77cf4 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js @@ -10,7 +10,7 @@ import { useEffect, useState } from '@wordpress/element'; import BlockPopoverInbetween from '../block-popover/inbetween'; import ZoomOutModeInserterButton from './zoom-out-mode-inserter-button'; import { store as blockEditorStore } from '../../store'; -import { sectionRootClientIdKey } from '../../store/private-keys'; +import { unlock } from '../../lock-unlock'; function ZoomOutModeInserters() { const [ isReady, setIsReady ] = useState( false ); @@ -32,8 +32,11 @@ function ZoomOutModeInserters() { getSelectedBlockClientId, getHoveredBlockClientId, isBlockInsertionPointVisible, - } = select( blockEditorStore ); - const { [ sectionRootClientIdKey ]: root } = getSettings(); + getSectionRootClientId, + } = unlock( select( blockEditorStore ) ); + + const root = getSectionRootClientId(); + return { hasSelection: !! getSelectionStart().clientId, blockInsertionPoint: getBlockInsertionPoint(), diff --git a/packages/block-editor/src/components/inner-blocks/index.js b/packages/block-editor/src/components/inner-blocks/index.js index 9702044aeca6b0..0d35b459190fef 100644 --- a/packages/block-editor/src/components/inner-blocks/index.js +++ b/packages/block-editor/src/components/inner-blocks/index.js @@ -30,7 +30,6 @@ import useBlockSync from '../provider/use-block-sync'; import { store as blockEditorStore } from '../../store'; import useBlockDropZone from '../use-block-drop-zone'; import { unlock } from '../../lock-unlock'; -import { sectionRootClientIdKey } from '../../store/private-keys'; const EMPTY_OBJECT = {}; @@ -204,7 +203,7 @@ export function useInnerBlocksProps( props = {}, options = {} ) { getBlockEditingMode, getBlockSettings, isDragging, - getSettings, + getSectionRootClientId, } = unlock( select( blockEditorStore ) ); let _isDropZoneDisabled; @@ -226,8 +225,7 @@ export function useInnerBlocksProps( props = {}, options = {} ) { // In zoom out mode, we want to disable the drop zone for the sections. // The inner blocks belonging to the section drop zone is // already disabled by the blocks themselves being disabled. - const { [ sectionRootClientIdKey ]: sectionRootClientId } = - getSettings(); + const sectionRootClientId = getSectionRootClientId(); _isDropZoneDisabled = clientId !== sectionRootClientId; } 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 fb25368239a011..5af82915233703 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 @@ -24,7 +24,6 @@ import { } from '../../utils/math'; import { store as blockEditorStore } from '../../store'; import { unlock } from '../../lock-unlock'; -import { sectionRootClientIdKey } from '../../store/private-keys'; const THRESHOLD_DISTANCE = 30; const MINIMUM_HEIGHT_FOR_THRESHOLD = 120; @@ -314,8 +313,8 @@ export default function useBlockDropZone( { getAllowedBlocks, isDragging, isGroupable, - getSettings, isZoomOutMode, + getSectionRootClientId, } = unlock( useSelect( blockEditorStore ) ); const { showInsertionPoint, @@ -361,8 +360,7 @@ export default function useBlockDropZone( { return; } - const { [ sectionRootClientIdKey ]: sectionRootClientId } = - getSettings(); + const sectionRootClientId = getSectionRootClientId(); // In Zoom Out mode, if the target is not the section root provided by settings then // do not allow dropping as the drop target is not within the root (that which is @@ -494,6 +492,8 @@ export default function useBlockDropZone( { getBlockNamesByClientId, getDraggedBlockClientIds, getBlockType, + getSectionRootClientId, + isZoomOutMode, getBlocks, getBlockListSettings, dropZoneElement, @@ -506,8 +506,6 @@ export default function useBlockDropZone( { isGroupable, getBlockVariations, getGroupingBlockName, - getSettings, - isZoomOutMode, ] ), 200 diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index ebd310b3de9d3f..e91f997ca67837 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -34,9 +34,6 @@ import { __experimentalUpdateSettings, privateRemoveBlocks, } from './private-actions'; -import { STORE_NAME } from './constants'; - -import { sectionRootClientIdKey } from './private-keys'; /** @typedef {import('../components/use-on-block-drop/types').WPDropOperation} WPDropOperation */ @@ -1671,13 +1668,12 @@ export const setNavigationMode = */ export const __unstableSetEditorMode = ( mode ) => - ( { dispatch, select, registry } ) => { + ( { dispatch, select } ) => { // When switching to zoom-out mode, we need to select the parent section if ( mode === 'zoom-out' ) { const firstSelectedClientId = select.getBlockSelectionStart(); - const { [ sectionRootClientIdKey ]: sectionRootClientId } = registry - .select( STORE_NAME ) - .getSettings(); + + const sectionRootClientId = select.getSectionRootClientId(); if ( firstSelectedClientId ) { let sectionClientId; diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 9cc793362296c4..7e323cee6581ae 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -28,6 +28,7 @@ import { unlock } from '../lock-unlock'; import { selectBlockPatternsKey, reusableBlocksSelectKey, + sectionRootClientIdKey, } from './private-keys'; export { getBlockSettings } from './get-block-settings'; @@ -543,3 +544,7 @@ export const getBlockStyles = createSelector( export function isZoomOutMode( state ) { return state.editorMode === 'zoom-out'; } + +export function getSectionRootClientId( state ) { + return state.settings?.[ sectionRootClientIdKey ]; +} diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 2a840392fbffed..30fdb76bdbe787 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -37,10 +37,9 @@ import { getContentLockingParent, getTemporarilyEditingAsBlocks, getTemporarilyEditingFocusModeToRevert, + getSectionRootClientId, } from './private-selectors'; -import { sectionRootClientIdKey } from './private-keys'; - /** * A block selection object. * @@ -2061,9 +2060,7 @@ export const getInserterItems = createRegistrySelector( ( select ) => let sectionRootClientId; try { sectionRootClientId = - getSettings( state )[ - sectionRootClientIdKey - ]; + getSectionRootClientId( state ); } catch ( e ) {} if ( sectionRootClientId && @@ -2841,8 +2838,7 @@ export function __unstableHasActiveBlockOverlayActive( state, clientId ) { // In zoom-out mode, the block overlay is always active for section level blocks. if ( editorMode === 'zoom-out' ) { - const { [ sectionRootClientIdKey ]: sectionRootClientId } = - getSettings( state ); + const sectionRootClientId = getSectionRootClientId( state ); if ( sectionRootClientId ) { const sectionClientIds = getBlockOrder( state, @@ -2935,8 +2931,7 @@ export const getBlockEditingMode = createRegistrySelector( // sections. const editorMode = __unstableGetEditorMode( state ); if ( editorMode === 'zoom-out' ) { - const { [ sectionRootClientIdKey ]: sectionRootClientId } = - getSettings( state ); + const sectionRootClientId = getSectionRootClientId( state ); if ( clientId === '' /* ROOT_CONTAINER_CLIENT_ID */ ) { return sectionRootClientId ? 'disabled' : 'contentOnly'; diff --git a/packages/editor/src/components/inserter-sidebar/index.js b/packages/editor/src/components/inserter-sidebar/index.js index 3e54fec6cc06b8..fef5e54e52f68f 100644 --- a/packages/editor/src/components/inserter-sidebar/index.js +++ b/packages/editor/src/components/inserter-sidebar/index.js @@ -18,9 +18,7 @@ import { store as interfaceStore } from '@wordpress/interface'; import { unlock } from '../../lock-unlock'; import { store as editorStore } from '../../store'; -const { PrivateInserterLibrary, sectionRootClientIdKey } = unlock( - blockEditorPrivateApis -); +const { PrivateInserterLibrary } = unlock( blockEditorPrivateApis ); export default function InserterSidebar() { const { @@ -40,14 +38,14 @@ export default function InserterSidebar() { getBlockInsertionPoint, getBlockRootClientId, __unstableGetEditorMode, - getSettings, - } = select( blockEditorStore ); + getSectionRootClientId, + } = unlock( select( blockEditorStore ) ); const { get } = select( preferencesStore ); const { getActiveComplementaryArea } = select( interfaceStore ); const getBlockSectionRootClientId = () => { if ( __unstableGetEditorMode() === 'zoom-out' ) { - const { [ sectionRootClientIdKey ]: sectionRootClientId } = - getSettings(); + const sectionRootClientId = getSectionRootClientId(); + if ( sectionRootClientId ) { return sectionRootClientId; } From 2807adb9a174ea45427bb9683b57d6332c751fce Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Wed, 4 Sep 2024 11:23:42 +0200 Subject: [PATCH 0661/1908] Block bindings: Lock editing in fields in editor if meta fields panel is opened. (#64738) * Lock editing bindings if meta fields interface is opened * Update snapshots * Refactor the EnableCustomFieldsOption component to improve code readability and maintainability. * Update snapshots * Remove extra text Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/editor/src/bindings/post-meta.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index 1ecd6ea50ba274..4de8396d4c13bb 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -62,6 +62,12 @@ export default { if ( fieldValue === undefined ) { return false; } + // Check that custom fields metabox is not enabled. + const areCustomFieldsEnabled = + select( editorStore ).getEditorSettings().enableCustomFields; + if ( areCustomFieldsEnabled ) { + return false; + } // Check that the user has the capability to edit post meta. const canUserEdit = select( coreDataStore ).canUser( 'update', { From c5b5135bfb9dd0460b7f64b82fecb18cb0e0afe5 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 4 Sep 2024 19:01:25 +0900 Subject: [PATCH 0662/1908] DatePicker: restore round radius for event dot (#65031) * DatePicker: restore round radius for event dot * Add CHANGELOG Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/date-time/date/styles.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 81ad1717801a95..33677f10b58fcb 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -64,6 +64,7 @@ - `TimePicker`: use ToggleGroupControl for AM/PM toggle ([#64800](https://github.com/WordPress/gutenberg/pull/64800)). - `ColorPalette` utils: do not normalize undefined color values ([#64969](https://github.com/WordPress/gutenberg/pull/64969)). +- `DatePicker` restore round radius for event dot ([#65031](https://github.com/WordPress/gutenberg/pull/65031)). ### Internal diff --git a/packages/components/src/date-time/date/styles.ts b/packages/components/src/date-time/date/styles.ts index 8f208b53fac22a..bffc8ae35d2a64 100644 --- a/packages/components/src/date-time/date/styles.ts +++ b/packages/components/src/date-time/date/styles.ts @@ -107,6 +107,7 @@ export const DayButton = styled( Button, { ` ::before { background: ${ props.isSelected ? COLORS.white : COLORS.theme.accent }; + border-radius: ${ CONFIG.radiusRound }; bottom: 2px; content: " "; height: 4px; From 6730169bf55353f504c17447f40b3ae1cfa37567 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 4 Sep 2024 14:27:44 +0400 Subject: [PATCH 0663/1908] Patterns: Pass 'blocks' as inner blocks value (#65029) * Patterns (Try): Pass 'blocks' as inner blocks value * Remove comment Unlinked contributors: rdoughbs. Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: arthur791004 <arthur791004@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: skorasaurus <skorasaurus@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: htmgarcia <htmgarcia@git.wordpress.org> Co-authored-by: rfischmann <rfischmann@git.wordpress.org> --- packages/block-library/src/block/edit.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/block-library/src/block/edit.js b/packages/block-library/src/block/edit.js index 3dd5faf67b31f6..af9c99876e9d20 100644 --- a/packages/block-library/src/block/edit.js +++ b/packages/block-library/src/block/edit.js @@ -248,11 +248,10 @@ function ReusableBlockEdit( { ), } ); - // Use `blocks` variable until `innerBlocks` is populated, which has the proper clientIds. const innerBlocksProps = useInnerBlocksProps( blockProps, { templateLock: 'all', layout, - value: innerBlocks.length > 0 ? innerBlocks : blocks, + value: blocks, onInput: NOOP, onChange: NOOP, renderAppender: blocks?.length From bca5c2554f79431a804bd5ae41816cb59da86e61 Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Wed, 4 Sep 2024 12:52:18 +0200 Subject: [PATCH 0664/1908] Add context to `View` string in post actions (#65046) Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/editor/src/dataviews/actions/view-post.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/dataviews/actions/view-post.tsx b/packages/editor/src/dataviews/actions/view-post.tsx index 47eb1a66d019ad..187faffafb5d3c 100644 --- a/packages/editor/src/dataviews/actions/view-post.tsx +++ b/packages/editor/src/dataviews/actions/view-post.tsx @@ -2,7 +2,7 @@ * WordPress dependencies */ import { external } from '@wordpress/icons'; -import { __ } from '@wordpress/i18n'; +import { _x } from '@wordpress/i18n'; import type { Action } from '@wordpress/dataviews'; /** @@ -12,7 +12,7 @@ import type { BasePost } from '../types'; const viewPost: Action< BasePost > = { id: 'view-post', - label: __( 'View' ), + label: _x( 'View', 'verb' ), isPrimary: true, icon: external, isEligible( post ) { From 6accdd3a2d1c02ea9eea9093c9c751d09e487cbb Mon Sep 17 00:00:00 2001 From: Jacob Cassidy <jacob@jacobcassidy.com> Date: Wed, 4 Sep 2024 18:27:13 +0700 Subject: [PATCH 0665/1908] Scripts: Update `puppeteer-core` dependency (#64597) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix the issue with `@wordpress/scripts` having 5 high severity vulnerabilities by upgrading the `puppeteer-core` package to the latest version (23.1.0) * Update scripts package version to 28.6.0 * Remove manual CHANGELOG version change * Remove manual version update from `package.json` * Update CHANGELOG.md * Add `"puppeteer-core": "23.1.0"` as a `devDependencies` * Update package-lock.json with `"puppeteer-core": "23.1.0"` as a `devDependencies` in package.json --------- Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> Co-authored-by: jacobcassidy <jacobcassidy@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- package-lock.json | 675 +++++++++++++++++++++++++++------- package.json | 1 + packages/scripts/CHANGELOG.md | 4 + packages/scripts/package.json | 2 +- 4 files changed, 539 insertions(+), 143 deletions(-) diff --git a/package-lock.json b/package-lock.json index a5841a06e163ed..e9ae02a0c4768b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -221,6 +221,7 @@ "postcss-local-keyframes": "^0.0.2", "prettier": "npm:wp-prettier@3.0.3", "progress": "2.0.3", + "puppeteer-core": "23.1.0", "react": "18.3.1", "react-dom": "18.3.1", "react-native": "0.73.3", @@ -22569,15 +22570,6 @@ "node": ">=4.0" } }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dev": true, - "dependencies": { - "node-fetch": "2.6.7" - } - }, "node_modules/cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -24111,10 +24103,11 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.981744", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.981744.tgz", - "integrity": "sha512-0cuGS8+jhR67Fy7qG3i3Pc7Aw494sb9yG9QgpG97SFVWwolgYjlhJg7n+UaHxOQT30d1TYu/EYe9k01ivLErIg==", - "dev": true + "version": "0.0.1312386", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz", + "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==", + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/diff": { "version": "4.0.2", @@ -42325,33 +42318,120 @@ } }, "node_modules/puppeteer-core": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-13.7.0.tgz", - "integrity": "sha512-rXja4vcnAzFAP1OVLq/5dWNfwBGuzcOARJ6qGV7oAZhnLmVRU8G5MsdeQEAOy332ZhkIOnn9jp15R89LKHyp2Q==", + "version": "23.1.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.1.0.tgz", + "integrity": "sha512-SvAsu+xnLN2FMXE/59bp3s3WXp8ewqUGzVV4AQtml/2xmsciZnU/bXcCW+eETHPWQ6Agg2vTI7QzWXPpEARK2g==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "cross-fetch": "3.1.5", - "debug": "4.3.4", - "devtools-protocol": "0.0.981744", - "extract-zip": "2.0.1", - "https-proxy-agent": "5.0.1", - "pkg-dir": "4.2.0", - "progress": "2.0.3", - "proxy-from-env": "1.1.0", - "rimraf": "3.0.2", - "tar-fs": "2.1.1", - "unbzip2-stream": "1.4.3", - "ws": "8.5.0" + "@puppeteer/browsers": "2.3.1", + "chromium-bidi": "0.6.4", + "debug": "^4.3.6", + "devtools-protocol": "0.0.1312386", + "typed-query-selector": "^2.12.0", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/puppeteer-core/node_modules/@puppeteer/browsers": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.1.tgz", + "integrity": "sha512-uK7o3hHkK+naEobMSJ+2ySYyXtQkBxIH8Gn4MK9ciePjNV+Pf+PgY/W7iPzn2MTjl3stcYB5AlcTmPYw7AXDwA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.3.6", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.4.0", + "semver": "^7.6.3", + "tar-fs": "^3.0.6", + "unbzip2-stream": "^1.4.3", + "yargs": "^17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" }, "engines": { - "node": ">=10.18.1" + "node": ">=18" } }, + "node_modules/puppeteer-core/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/puppeteer-core/node_modules/chromium-bidi": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.4.tgz", + "integrity": "sha512-8zoq6ogmhQQkAKZVKO2ObFTl4uOkqoX1PlKQX3hZQ5E9cbUotcAb7h4pTNVAGGv8Z36PF3CtdOriEp/Rz82JqQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "mitt": "3.0.1", + "urlpattern-polyfill": "10.0.0", + "zod": "3.23.8" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/puppeteer-core/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/puppeteer-core/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/puppeteer-core/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, "node_modules/puppeteer-core/node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -42367,99 +42447,199 @@ "@types/yauzl": "^2.9.1" } }, - "node_modules/puppeteer-core/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/puppeteer-core/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, + "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=8" + "node": ">= 14" } }, - "node_modules/puppeteer-core/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/puppeteer-core/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, + "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "agent-base": "^7.0.2", + "debug": "4" }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/puppeteer-core/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/puppeteer-core/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/puppeteer-core/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/puppeteer-core/node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true, + "license": "MIT" + }, + "node_modules/puppeteer-core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/puppeteer-core/node_modules/proxy-agent": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", "dev": true, + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 14" } }, - "node_modules/puppeteer-core/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/puppeteer-core/node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, + "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/puppeteer-core/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/puppeteer-core/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/puppeteer-core/node_modules/socks-proxy-agent": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, "engines": { - "node": ">=6" + "node": ">= 14" } }, - "node_modules/puppeteer-core/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/puppeteer-core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { "node": ">=8" } }, - "node_modules/puppeteer-core/node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/puppeteer-core/node_modules/tar-fs": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", + "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", "dev": true, + "license": "MIT", "dependencies": { - "find-up": "^4.0.0" + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^2.1.1", + "bare-path": "^2.1.0" + } + }, + "node_modules/puppeteer-core/node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/puppeteer-core/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/puppeteer-core/node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -42470,6 +42650,45 @@ } } }, + "node_modules/puppeteer-core/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/puppeteer-core/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/puppeteer-core/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/pure-rand": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", @@ -48633,6 +48852,12 @@ "node": ">= 10" } }, + "node_modules/typed-query-selector": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", + "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", + "dev": true + }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -49318,6 +49543,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/urlpattern-polyfill": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", + "dev": true + }, "node_modules/use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -54591,7 +54822,7 @@ "postcss-import": "^16.1.0", "postcss-loader": "^6.2.1", "prettier": "npm:wp-prettier@3.0.3", - "puppeteer-core": "^13.2.0", + "puppeteer-core": "^23.1.0", "react-refresh": "^0.14.0", "read-pkg-up": "^7.0.1", "resolve-bin": "^0.4.0", @@ -68770,7 +69001,7 @@ "postcss-import": "^16.1.0", "postcss-loader": "^6.2.1", "prettier": "npm:wp-prettier@3.0.3", - "puppeteer-core": "^13.2.0", + "puppeteer-core": "^23.1.0", "react-refresh": "^0.14.0", "read-pkg-up": "^7.0.1", "resolve-bin": "^0.4.0", @@ -73319,15 +73550,6 @@ "is-windows": "^1.0.0" } }, - "cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dev": true, - "requires": { - "node-fetch": "2.6.7" - } - }, "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -74451,9 +74673,9 @@ } }, "devtools-protocol": { - "version": "0.0.981744", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.981744.tgz", - "integrity": "sha512-0cuGS8+jhR67Fy7qG3i3Pc7Aw494sb9yG9QgpG97SFVWwolgYjlhJg7n+UaHxOQT30d1TYu/EYe9k01ivLErIg==", + "version": "0.0.1312386", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz", + "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==", "dev": true }, "diff": { @@ -88284,25 +88506,81 @@ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" }, "puppeteer-core": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-13.7.0.tgz", - "integrity": "sha512-rXja4vcnAzFAP1OVLq/5dWNfwBGuzcOARJ6qGV7oAZhnLmVRU8G5MsdeQEAOy332ZhkIOnn9jp15R89LKHyp2Q==", + "version": "23.1.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.1.0.tgz", + "integrity": "sha512-SvAsu+xnLN2FMXE/59bp3s3WXp8ewqUGzVV4AQtml/2xmsciZnU/bXcCW+eETHPWQ6Agg2vTI7QzWXPpEARK2g==", "dev": true, "requires": { - "cross-fetch": "3.1.5", - "debug": "4.3.4", - "devtools-protocol": "0.0.981744", - "extract-zip": "2.0.1", - "https-proxy-agent": "5.0.1", - "pkg-dir": "4.2.0", - "progress": "2.0.3", - "proxy-from-env": "1.1.0", - "rimraf": "3.0.2", - "tar-fs": "2.1.1", - "unbzip2-stream": "1.4.3", - "ws": "8.5.0" + "@puppeteer/browsers": "2.3.1", + "chromium-bidi": "0.6.4", + "debug": "^4.3.6", + "devtools-protocol": "0.0.1312386", + "typed-query-selector": "^2.12.0", + "ws": "^8.18.0" }, "dependencies": { + "@puppeteer/browsers": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.1.tgz", + "integrity": "sha512-uK7o3hHkK+naEobMSJ+2ySYyXtQkBxIH8Gn4MK9ciePjNV+Pf+PgY/W7iPzn2MTjl3stcYB5AlcTmPYw7AXDwA==", + "dev": true, + "requires": { + "debug": "^4.3.6", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.4.0", + "semver": "^7.6.3", + "tar-fs": "^3.0.6", + "unbzip2-stream": "^1.4.3", + "yargs": "^17.7.2" + } + }, + "agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "requires": { + "debug": "^4.3.4" + } + }, + "chromium-bidi": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.4.tgz", + "integrity": "sha512-8zoq6ogmhQQkAKZVKO2ObFTl4uOkqoX1PlKQX3hZQ5E9cbUotcAb7h4pTNVAGGv8Z36PF3CtdOriEp/Rz82JqQ==", + "dev": true, + "requires": { + "mitt": "3.0.1", + "urlpattern-polyfill": "10.0.0", + "zod": "3.23.8" + } + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -88315,68 +88593,169 @@ "yauzl": "^2.10.0" } }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "agent-base": "^7.1.0", + "debug": "^4.3.4" } }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "agent-base": "^7.0.2", + "debug": "4" } }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "proxy-agent": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", "dev": true, "requires": { - "p-try": "^2.0.0" + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" } }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true + "socks-proxy-agent": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "dev": true, + "requires": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" + } }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { - "find-up": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "tar-fs": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", + "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", + "dev": true, + "requires": { + "bare-fs": "^2.1.1", + "bare-path": "^2.1.0", + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + } + }, + "tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "requires": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } }, "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true } } @@ -93104,6 +93483,12 @@ "integrity": "sha512-bctQIOqx2iVbWGDGPWwIm18QScpu2XRmkC19D8rQGFsjKSgteq/o1hTZvIG/wuDq8fanpBDrLkLq+aEN/6y5XQ==", "dev": true }, + "typed-query-selector": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", + "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", + "dev": true + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -93631,6 +94016,12 @@ "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==", "dev": true }, + "urlpattern-polyfill": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", + "dev": true + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", diff --git a/package.json b/package.json index c0a7853a418178..32f114cb9afa44 100644 --- a/package.json +++ b/package.json @@ -233,6 +233,7 @@ "postcss-local-keyframes": "^0.0.2", "prettier": "npm:wp-prettier@3.0.3", "progress": "2.0.3", + "puppeteer-core": "23.1.0", "react": "18.3.1", "react-dom": "18.3.1", "react-native": "0.73.3", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index cd796ba46dbfa1..9d666313f76abc 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Fixed the issue with having 5 high severity vulnerabilities by upgrading the `puppeteer-core` package to the latest major version `^23.1.0` ([#64597](https://github.com/WordPress/gutenberg/pull/64597)). + ### Enhancements - Inlines CSS files imported from other CSS files before optimization in the `build` command ([#61121](https://github.com/WordPress/gutenberg/pull/61121)). diff --git a/packages/scripts/package.json b/packages/scripts/package.json index c4582ba65d15e9..291b8a58bca408 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -76,7 +76,7 @@ "postcss-import": "^16.1.0", "postcss-loader": "^6.2.1", "prettier": "npm:wp-prettier@3.0.3", - "puppeteer-core": "^13.2.0", + "puppeteer-core": "^23.1.0", "react-refresh": "^0.14.0", "read-pkg-up": "^7.0.1", "resolve-bin": "^0.4.0", From 04cf5797631e746cfd4bcaae11aa687ad6cb33be Mon Sep 17 00:00:00 2001 From: Bernie Reiter <96308+ockham@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:54:12 +0200 Subject: [PATCH 0666/1908] Categories Block: Add iAPI directive for client-side routing (#64907) Enable client-side navigation for the Categories block, when used within the Query Loop block. Co-authored-by: ockham <bernhard-reiter@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: luisherranz <luisherranz@git.wordpress.org> Co-authored-by: dmsnell <dmsnell@git.wordpress.org> --- packages/block-library/src/categories/block.json | 1 + packages/block-library/src/categories/index.php | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/categories/block.json b/packages/block-library/src/categories/block.json index f192087dfb4617..460fbef92fdab2 100644 --- a/packages/block-library/src/categories/block.json +++ b/packages/block-library/src/categories/block.json @@ -36,6 +36,7 @@ "default": true } }, + "usesContext": [ "enhancedPagination" ], "supports": { "align": true, "html": false, diff --git a/packages/block-library/src/categories/index.php b/packages/block-library/src/categories/index.php index 062130e85010a5..5c0cc63415cb78 100644 --- a/packages/block-library/src/categories/index.php +++ b/packages/block-library/src/categories/index.php @@ -9,12 +9,15 @@ * Renders the `core/categories` block on server. * * @since 5.0.0 + * @since 6.7.0 Enable client-side rendering if enhancedPagination context is true. * - * @param array $attributes The block attributes. + * @param array $attributes The block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. * * @return string Returns the categories list/dropdown markup. */ -function render_block_core_categories( $attributes ) { +function render_block_core_categories( $attributes, $content, $block ) { static $block_id = 0; ++$block_id; @@ -54,6 +57,14 @@ function render_block_core_categories( $attributes ) { $wrapper_markup = '<ul %1$s>%2$s</ul>'; $items_markup = wp_list_categories( $args ); $type = 'list'; + + if ( ! empty( $block->context['enhancedPagination'] ) ) { + $p = new WP_HTML_Tag_Processor( $items_markup ); + while ( $p->next_tag( 'a' ) ) { + $p->set_attribute( 'data-wp-on--click', 'core/query::actions.navigate' ); + } + $items_markup = $p->get_updated_html(); + } } $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => "wp-block-categories-{$type}" ) ); From c2b0226456bc968be3faba7c4e874a3712902cb7 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Wed, 4 Sep 2024 05:09:11 -0700 Subject: [PATCH 0667/1908] Post Editor: fix click space after post content to append (#64992) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix minimally * Revise comment * Stop propagation and don’t prevent default * Insert default block if no blocks are present --- packages/edit-post/src/components/layout/index.js | 4 ++-- .../src/components/layout/use-padding-appender.js | 15 +++++---------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 519b32691c6a49..185f97ba45a56f 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -126,8 +126,8 @@ function useEditorStyles() { ? editorSettings.styles ?? [] : defaultEditorStyles; - // Add a constant padding for the typewriter effect. When typing at the - // bottom, there needs to be room to scroll up. + // Add a space for the typewriter effect. When typing in the last block, + // there needs to be room to scroll up. if ( ! isZoomedOutView && renderingMode === 'post-only' && diff --git a/packages/edit-post/src/components/layout/use-padding-appender.js b/packages/edit-post/src/components/layout/use-padding-appender.js index ff342ded90817a..efd46a485058ca 100644 --- a/packages/edit-post/src/components/layout/use-padding-appender.js +++ b/packages/edit-post/src/components/layout/use-padding-appender.js @@ -18,12 +18,12 @@ export function usePaddingAppender() { const { ownerDocument } = node; const { defaultView } = ownerDocument; - const paddingBottom = defaultView.parseInt( - defaultView.getComputedStyle( node ).paddingBottom, + const pseudoHeight = defaultView.parseInt( + defaultView.getComputedStyle( node, ':after' ).height, 10 ); - if ( ! paddingBottom ) { + if ( ! pseudoHeight ) { return; } @@ -38,25 +38,20 @@ export function usePaddingAppender() { return; } - event.preventDefault(); + event.stopPropagation(); const blockOrder = registry .select( blockEditorStore ) .getBlockOrder( '' ); const lastBlockClientId = blockOrder[ blockOrder.length - 1 ]; - // Do nothing when only default block appender is present. - if ( ! lastBlockClientId ) { - return; - } - const lastBlock = registry .select( blockEditorStore ) .getBlock( lastBlockClientId ); const { selectBlock, insertDefaultBlock } = registry.dispatch( blockEditorStore ); - if ( isUnmodifiedDefaultBlock( lastBlock ) ) { + if ( lastBlock && isUnmodifiedDefaultBlock( lastBlock ) ) { selectBlock( lastBlockClientId ); } else { insertDefaultBlock(); From 6fecca7efe7a6158b45a547d41b9b7a2e0ce31e7 Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Wed, 4 Sep 2024 13:16:19 +0100 Subject: [PATCH 0668/1908] Zoom Out: Remove the experiment that connects zoom out to the pattern inserter (#65045) Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- lib/experimental/editor-settings.php | 3 --- lib/experiments-page.php | 12 ------------ .../block-editor/src/components/inserter/menu.js | 6 ------ 3 files changed, 21 deletions(-) diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index c6bd99a18bf4c7..d27de1a3042734 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -28,9 +28,6 @@ function gutenberg_enable_experiments() { if ( gutenberg_is_experiment_enabled( 'gutenberg-full-page-client-side-navigation' ) ) { wp_add_inline_script( 'wp-block-library', 'window.__experimentalFullPageClientSideNavigation = true', 'before' ); } - if ( $gutenberg_experiments && array_key_exists( 'gutenberg-zoomed-out-patterns-tab', $gutenberg_experiments ) ) { - wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableZoomedOutPatternsTab = true', 'before' ); - } if ( $gutenberg_experiments && array_key_exists( 'gutenberg-quick-edit-dataviews', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalQuickEditDataViews = true', 'before' ); } diff --git a/lib/experiments-page.php b/lib/experiments-page.php index f76dcdca7d18cb..634d7e33c43815 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -139,18 +139,6 @@ function gutenberg_initialize_experiments_settings() { ) ); - add_settings_field( - 'gutenberg-zoomed-out-patterns-tab', - __( 'Enable zoomed out view when patterns are browsed in the inserter', 'gutenberg' ), - 'gutenberg_display_experiment_field', - 'gutenberg-experiments', - 'gutenberg_experiments_section', - array( - 'label' => __( 'Enable zoomed out view when selecting a pattern category in the main inserter.', 'gutenberg' ), - 'id' => 'gutenberg-zoomed-out-patterns-tab', - ) - ); - add_settings_field( 'gutenberg-new-posts-dashboard', __( 'Redesigned posts dashboard', 'gutenberg' ), diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index bac53b680c71fb..b884ea97588459 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -32,7 +32,6 @@ import InserterSearchResults from './search-results'; import useInsertionPoint from './hooks/use-insertion-point'; import { store as blockEditorStore } from '../../store'; import TabbedSidebar from '../tabbed-sidebar'; -import { useZoomOut } from '../../hooks/use-zoom-out'; const NOOP = () => {}; function InserterMenu( @@ -147,11 +146,6 @@ function InserterMenu( const showMediaPanel = selectedTab === 'media' && !! selectedMediaCategory; - const showZoomOut = - showPatternPanel && !! window.__experimentalEnableZoomedOutPatternsTab; - - useZoomOut( showZoomOut ); - const inserterSearch = useMemo( () => { if ( selectedTab === 'media' ) { return null; From f0608fc8d84c3ecaf41686abc5209321fb561430 Mon Sep 17 00:00:00 2001 From: Tom Cafferkey <tjcafferkey@gmail.com> Date: Wed, 4 Sep 2024 13:36:18 +0100 Subject: [PATCH 0669/1908] Pagination Block: Fix inconsistent margins between editor and frontend (#64874) * Remove hardcoded margins for query pagination block --- .../src/query-pagination/editor.scss | 20 ------------------- .../src/query-pagination/style.scss | 15 -------------- 2 files changed, 35 deletions(-) diff --git a/packages/block-library/src/query-pagination/editor.scss b/packages/block-library/src/query-pagination/editor.scss index 0b755d155091f3..ed8a2cc47a30f7 100644 --- a/packages/block-library/src/query-pagination/editor.scss +++ b/packages/block-library/src/query-pagination/editor.scss @@ -1,5 +1,3 @@ -$pagination-margin: 0.5em; - // Center flex items. This has an equivalent in style.scss. .wp-block[data-align="center"] > .wp-block-query-pagination { justify-content: center; @@ -14,21 +12,3 @@ $pagination-margin: 0.5em; } } -.wp-block-query-pagination { - > .wp-block-query-pagination-next, - > .wp-block-query-pagination-previous, - > .wp-block-query-pagination-numbers { - // Override editor auto block margins. - margin-left: 0; - margin-top: $pagination-margin; - - /*rtl:ignore*/ - margin-right: $pagination-margin; - margin-bottom: $pagination-margin; - - &:last-child { - /*rtl:ignore*/ - margin-right: 0; - } - } -} diff --git a/packages/block-library/src/query-pagination/style.scss b/packages/block-library/src/query-pagination/style.scss index a7f2832af48c7a..e949c766e56511 100644 --- a/packages/block-library/src/query-pagination/style.scss +++ b/packages/block-library/src/query-pagination/style.scss @@ -1,19 +1,4 @@ -$pagination-margin: 0.5em; .wp-block-query-pagination { - // Increased specificity to override blocks default margin. - > .wp-block-query-pagination-next, - > .wp-block-query-pagination-previous, - > .wp-block-query-pagination-numbers { - /*rtl:ignore*/ - margin-right: $pagination-margin; - margin-bottom: $pagination-margin; - - &:last-child { - /*rtl:ignore*/ - margin-right: 0; - } - } - // This moves the next link to the right side of the container, // which is important when it's the only block displayed // and the block has a "space-between" justification. From 9691105c3f06e3364ddba23f5927f4ec7d32d6a0 Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Wed, 4 Sep 2024 13:44:10 +0100 Subject: [PATCH 0670/1908] Add new zoom out experiment (#65048) * Zoom Out: Add a new experiment for zoom out * Update lib/experiments-page.php Co-authored-by: Dave Smith <getdavemail@gmail.com> --------- Co-authored-by: Dave Smith <getdavemail@gmail.com> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- lib/experimental/editor-settings.php | 3 ++ lib/experiments-page.php | 11 ++++++++ .../src/components/preview-dropdown/index.js | 28 ++++++++++--------- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index d27de1a3042734..f7cedd98239a36 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -37,6 +37,9 @@ function gutenberg_enable_experiments() { if ( $gutenberg_experiments && array_key_exists( 'gutenberg-media-processing', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalMediaProcessing = true', 'before' ); } + if ( $gutenberg_experiments && array_key_exists( 'gutenberg-zoom-out-experiment', $gutenberg_experiments ) ) { + wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableZoomOutExperiment = true', 'before' ); + } } add_action( 'admin_init', 'gutenberg_enable_experiments' ); diff --git a/lib/experiments-page.php b/lib/experiments-page.php index 634d7e33c43815..1b7df237176a2c 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -187,6 +187,17 @@ function gutenberg_initialize_experiments_settings() { ) ); + add_settings_field( + 'gutenberg-zoom-out-experiment', + __( 'Zoom out experiments', 'gutenberg' ), + 'gutenberg_display_experiment_field', + 'gutenberg-experiments', + 'gutenberg_experiments_section', + array( + 'label' => __( 'Enable zoom out experiments; shows zoom out in the device preview and other zoom out experiments.', 'gutenberg' ), + 'id' => 'gutenberg-zoom-out-experiment', + ) + ); register_setting( 'gutenberg-experiments', 'gutenberg-experiments' diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js index 8b51bb79bc8873..5acaa351c9bb7e 100644 --- a/packages/editor/src/components/preview-dropdown/index.js +++ b/packages/editor/src/components/preview-dropdown/index.js @@ -112,22 +112,24 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { label: __( 'Desktop' ), icon: desktop, }, - { + ]; + if ( window.__experimentalEnableZoomOutExperiment ) { + choices.push( { value: 'ZoomOut', label: __( 'Desktop (50%)' ), icon: desktop, - }, - { - value: 'Tablet', - label: __( 'Tablet' ), - icon: tablet, - }, - { - value: 'Mobile', - label: __( 'Mobile' ), - icon: mobile, - }, - ]; + } ); + } + choices.push( { + value: 'Tablet', + label: __( 'Tablet' ), + icon: tablet, + } ); + choices.push( { + value: 'Mobile', + label: __( 'Mobile' ), + icon: mobile, + } ); const previewValue = editorMode === 'zoom-out' ? 'ZoomOut' : deviceType; From cd77dd950b7762ebfa99987ffb0b3ed8f9888d94 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Wed, 4 Sep 2024 13:45:47 +0100 Subject: [PATCH 0671/1908] Apply radius scale in the editor (#64930) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/base-styles/_mixins.scss | 8 ++--- .../components/block-breadcrumb/style.scss | 2 +- .../components/block-draggable/content.scss | 2 +- .../src/components/block-draggable/style.scss | 2 +- .../src/components/block-list/content.scss | 3 +- .../src/components/block-lock/style.scss | 2 +- .../src/components/block-mover/style.scss | 2 +- .../components/block-pattern-setup/style.scss | 4 +-- .../components/block-patterns-list/style.scss | 4 +-- .../src/components/block-switcher/style.scss | 4 +-- .../src/components/block-tools/style.scss | 5 ++-- .../block-variation-transforms/style.scss | 2 +- .../button-block-appender/content.scss | 1 - .../components/colors-gradients/style.scss | 8 ++--- .../default-block-appender/content.scss | 1 - .../src/components/global-styles/style.scss | 4 +-- .../src/components/grid/style.scss | 2 +- .../components/inserter-list-item/style.scss | 4 +-- .../src/components/inserter/style.scss | 10 +++---- .../src/components/link-control/style.scss | 4 +-- .../src/components/list-view/style.scss | 29 +++++++++---------- .../src/components/rich-text/style.scss | 2 +- .../src/components/warning/content.scss | 2 +- .../block-library/src/freeform/editor.scss | 2 +- .../block-library/src/gallery/editor.scss | 2 +- packages/block-library/src/group/editor.scss | 1 - packages/block-library/src/image/editor.scss | 3 -- .../block-library/src/navigation/editor.scss | 3 +- packages/commands/src/components/style.scss | 4 +-- .../components/dataviews-filters/style.scss | 2 +- .../src/dataviews-layouts/grid/style.scss | 2 +- .../src/dataviews-layouts/list/style.scss | 4 +-- .../src/components/back-button/style.scss | 4 +-- .../components/add-new-template/style.scss | 3 +- .../editor-canvas-container/style.scss | 2 +- .../global-styles/screen-revisions/style.scss | 2 +- .../src/components/global-styles/style.scss | 10 +++---- .../global-styles/variations/style.scss | 3 +- .../src/components/layout/style.scss | 4 +-- .../src/components/page-patterns/style.scss | 4 +-- .../src/components/page-templates/style.scss | 3 +- .../src/components/post-list/style.scss | 2 +- .../components/sidebar-dataviews/style.scss | 2 +- .../sidebar-navigation-item/style.scss | 1 - .../sidebar-navigation-screen/style.scss | 1 - .../src/components/style-book/style.scss | 4 +-- .../components/document-outline/style.scss | 2 +- .../src/components/post-card-panel/style.scss | 2 +- .../components/post-featured-image/style.scss | 3 +- .../components/post-locked-modal/style.scss | 2 +- .../components/post-publish-panel/style.scss | 2 +- .../components/resizable-editor/style.scss | 4 +-- packages/patterns/src/components/style.scss | 4 +-- .../src/blocks/legacy-widget/editor.scss | 4 +-- .../src/blocks/widget-group/editor.scss | 2 +- 55 files changed, 89 insertions(+), 111 deletions(-) diff --git a/packages/base-styles/_mixins.scss b/packages/base-styles/_mixins.scss index 69735d75aac71a..ebccbe0e5e8aee 100644 --- a/packages/base-styles/_mixins.scss +++ b/packages/base-styles/_mixins.scss @@ -74,7 +74,7 @@ @mixin input-style__neutral() { box-shadow: 0 0 0 transparent; transition: box-shadow 0.1s linear; - border-radius: $radius-block-ui; + border-radius: $radius-small; border: $border-width solid $gray-600; @include reduce-motion("transition"); } @@ -227,7 +227,7 @@ border: $border-width solid $gray-900; margin-right: $grid-unit-15; transition: none; - border-radius: $radius-block-ui; + border-radius: $radius-small; &:focus { box-shadow: 0 0 0 ($border-width * 2) $white, 0 0 0 ($border-width * 2 + $border-width-focus-fallback) var(--wp-admin-theme-color); @@ -363,7 +363,7 @@ &:focus { color: var(--wp-admin-theme-color--rgb); box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color, #007cba); - border-radius: $radius-block-ui; + border-radius: $radius-small; } } @@ -375,7 +375,7 @@ padding: $grid-unit-15 !important; border: $border-width solid $gray-900 !important; box-shadow: none !important; - border-radius: $radius-block-ui !important; + border-radius: $radius-small !important; // Fonts smaller than 16px causes mobile safari to zoom. font-size: $mobile-text-min-font-size !important; diff --git a/packages/block-editor/src/components/block-breadcrumb/style.scss b/packages/block-editor/src/components/block-breadcrumb/style.scss index 5d2e3154dc2d90..78d422d7b09978 100644 --- a/packages/block-editor/src/components/block-breadcrumb/style.scss +++ b/packages/block-editor/src/components/block-breadcrumb/style.scss @@ -41,7 +41,7 @@ content: ""; display: block; position: absolute; - border-radius: $radius-block-ui; + border-radius: $radius-small; top: $border-width; right: $border-width; bottom: $border-width; diff --git a/packages/block-editor/src/components/block-draggable/content.scss b/packages/block-editor/src/components/block-draggable/content.scss index f1318daebd5a04..102230168e2133 100644 --- a/packages/block-editor/src/components/block-draggable/content.scss +++ b/packages/block-editor/src/components/block-draggable/content.scss @@ -3,7 +3,7 @@ .block-editor-block-list__layout .is-dragging { background-color: currentColor !important; opacity: 0.05 !important; - border-radius: $radius-block-ui !important; + border-radius: $radius-small !important; // Disabling pointer events during the drag event is necessary, // lest the block might affect your drag operation. diff --git a/packages/block-editor/src/components/block-draggable/style.scss b/packages/block-editor/src/components/block-draggable/style.scss index afbf77319f7200..349afa2c3563c0 100644 --- a/packages/block-editor/src/components/block-draggable/style.scss +++ b/packages/block-editor/src/components/block-draggable/style.scss @@ -7,7 +7,7 @@ .block-editor-block-draggable-chip { background-color: $gray-900; - border-radius: $radius-block-ui; + border-radius: $radius-small; box-shadow: 0 6px 8px rgba($black, 0.3); color: $white; cursor: grabbing; diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index 15f0239d0f0765..95bb610da9967c 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -107,7 +107,7 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b right: 0; left: 0; top: -$default-block-margin * 0.5; - border-radius: $radius-block-ui; + border-radius: $radius-small; border-top: 4px solid $gray-400; bottom: auto; box-shadow: none; @@ -215,7 +215,6 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b right: 0; bottom: 0; left: 0; - border-radius: $radius-block-ui; background-color: rgba($white, 0.4); } diff --git a/packages/block-editor/src/components/block-lock/style.scss b/packages/block-editor/src/components/block-lock/style.scss index 8dc6bfb2021f08..ad59030a8f4405 100644 --- a/packages/block-editor/src/components/block-lock/style.scss +++ b/packages/block-editor/src/components/block-lock/style.scss @@ -41,7 +41,7 @@ &:hover { background-color: $gray-100; - border-radius: $radius-block-ui; + border-radius: $radius-small; } } diff --git a/packages/block-editor/src/components/block-mover/style.scss b/packages/block-editor/src/components/block-mover/style.scss index 11bc362663a4d9..c58ac9f19673fc 100644 --- a/packages/block-editor/src/components/block-mover/style.scss +++ b/packages/block-editor/src/components/block-mover/style.scss @@ -76,7 +76,7 @@ content: ""; position: absolute; display: block; - border-radius: $radius-block-ui; + border-radius: $radius-small; height: $grid-unit-40; // Position the focus rectangle. diff --git a/packages/block-editor/src/components/block-pattern-setup/style.scss b/packages/block-editor/src/components/block-pattern-setup/style.scss index 3474eed5be5176..10582a7a2ce496 100644 --- a/packages/block-editor/src/components/block-pattern-setup/style.scss +++ b/packages/block-editor/src/components/block-pattern-setup/style.scss @@ -4,7 +4,7 @@ justify-content: center; align-items: flex-start; width: 100%; - border-radius: $radius-block-ui; + border-radius: $radius-small; &.view-mode-grid { padding-top: $grid-unit-05; @@ -60,7 +60,7 @@ .block-editor-block-preview__container { min-height: 100px; - border-radius: $radius-block-ui; + border-radius: $radius-medium; border: $border-width solid $gray-300; } diff --git a/packages/block-editor/src/components/block-patterns-list/style.scss b/packages/block-editor/src/components/block-patterns-list/style.scss index 6b23c1e844dad9..84e95563737c3c 100644 --- a/packages/block-editor/src/components/block-patterns-list/style.scss +++ b/packages/block-editor/src/components/block-patterns-list/style.scss @@ -36,12 +36,12 @@ display: flex; align-items: center; overflow: hidden; - border-radius: $radius-block-ui; + border-radius: $radius-medium; &::after { outline: $border-width solid rgba($black, 0.1); outline-offset: -$border-width; - border-radius: $radius-block-ui; + border-radius: $radius-medium; } } diff --git a/packages/block-editor/src/components/block-switcher/style.scss b/packages/block-editor/src/components/block-switcher/style.scss index 287afaed4055c6..823a656668a621 100644 --- a/packages/block-editor/src/components/block-switcher/style.scss +++ b/packages/block-editor/src/components/block-switcher/style.scss @@ -99,7 +99,7 @@ width: 300px; border: $border-width solid $gray-900; background: $white; - border-radius: $radius-block-ui; + border-radius: $radius-medium; outline: none; box-shadow: none; overflow: auto; @@ -161,7 +161,7 @@ .block-editor-block-switcher__preview-patterns-container-list__item { height: 100%; - border-radius: $radius-block-ui; + border-radius: $radius-small; transition: all 0.05s ease-in-out; position: relative; border: $border-width solid transparent; diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index a37271e609b179..9f1325d7f95a1a 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -63,7 +63,6 @@ .block-editor-inserter__toggle.components-button.has-icon { // Basic look background: $gray-900; - border-radius: $radius-block-ui; color: $white; padding: 0; @@ -95,7 +94,7 @@ z-index: z-index(".block-editor-block-list__block-selection-button"); // Dark block UI appearance. - border-radius: $radius-block-ui; + border-radius: $radius-small; background-color: $gray-900; font-size: $default-font-size; @@ -188,7 +187,7 @@ .block-editor-block-contextual-toolbar { border: $border-width solid $gray-900; - border-radius: $radius-block-ui; + border-radius: $radius-small; overflow: visible; // allow the parent selector to be visible position: static; width: auto; diff --git a/packages/block-editor/src/components/block-variation-transforms/style.scss b/packages/block-editor/src/components/block-variation-transforms/style.scss index cfb0ff04a5bc80..b8d2a1d4649fa0 100644 --- a/packages/block-editor/src/components/block-variation-transforms/style.scss +++ b/packages/block-editor/src/components/block-variation-transforms/style.scss @@ -4,7 +4,7 @@ .components-dropdown-menu__toggle { border: $border-width solid $gray-700; - border-radius: $radius-block-ui; + border-radius: $radius-small; min-height: 30px; width: 100%; position: relative; diff --git a/packages/block-editor/src/components/button-block-appender/content.scss b/packages/block-editor/src/components/button-block-appender/content.scss index 4e3f32b3f4ffc3..e462278c07c104 100644 --- a/packages/block-editor/src/components/button-block-appender/content.scss +++ b/packages/block-editor/src/components/button-block-appender/content.scss @@ -52,7 +52,6 @@ left: 0; pointer-events: none; border: $border-width dashed currentColor; - border-radius: $radius-block-ui; } .block-editor-inserter { diff --git a/packages/block-editor/src/components/colors-gradients/style.scss b/packages/block-editor/src/components/colors-gradients/style.scss index b3539637a9904c..fc1b1a4d469033 100644 --- a/packages/block-editor/src/components/colors-gradients/style.scss +++ b/packages/block-editor/src/components/colors-gradients/style.scss @@ -73,15 +73,15 @@ $swatch-gap: 12px; // Identify the first visible instance as placeholder items will not have this class. &:nth-child(1 of &) { margin-top: $grid-unit-30; - border-top-left-radius: $radius-block-ui; - border-top-right-radius: $radius-block-ui; + border-top-left-radius: $radius-small; + border-top-right-radius: $radius-small; border-top: 1px solid $gray-300; } // Identify the last visible instance as placeholder items will not have this class. &:nth-last-child(1 of &) { - border-bottom-left-radius: $radius-block-ui; - border-bottom-right-radius: $radius-block-ui; + border-bottom-left-radius: $radius-small; + border-bottom-right-radius: $radius-small; } > div, diff --git a/packages/block-editor/src/components/default-block-appender/content.scss b/packages/block-editor/src/components/default-block-appender/content.scss index 77725d2508ec5e..51e0b4381a15d5 100644 --- a/packages/block-editor/src/components/default-block-appender/content.scss +++ b/packages/block-editor/src/components/default-block-appender/content.scss @@ -48,7 +48,6 @@ .block-editor-inserter__toggle.components-button.has-icon { // Basic look background: $gray-900; - border-radius: $radius-block-ui; color: $white; padding: 0; diff --git a/packages/block-editor/src/components/global-styles/style.scss b/packages/block-editor/src/components/global-styles/style.scss index 6fb07eb090a55f..1cebbfe7a85d4d 100644 --- a/packages/block-editor/src/components/global-styles/style.scss +++ b/packages/block-editor/src/components/global-styles/style.scss @@ -39,7 +39,7 @@ .block-editor-global-styles__shadow-indicator { color: $gray-800; border: $gray-200 $border-width solid; - border-radius: $radius-block-ui; + border-radius: $radius-small; cursor: pointer; padding: 0; @@ -207,7 +207,7 @@ .components-focal-point-picker-wrapper { background-color: $gray-100; width: 100%; - border-radius: $radius-block-ui; + border-radius: $radius-small; border: $border-width solid $gray-300; } diff --git a/packages/block-editor/src/components/grid/style.scss b/packages/block-editor/src/components/grid/style.scss index 6790d683ca7d03..3a04eb006e7910 100644 --- a/packages/block-editor/src/components/grid/style.scss +++ b/packages/block-editor/src/components/grid/style.scss @@ -117,7 +117,7 @@ content: ""; position: absolute; display: block; - border-radius: $radius-block-ui; + border-radius: $radius-small; height: $grid-unit-40; // Position the focus rectangle. diff --git a/packages/block-editor/src/components/inserter-list-item/style.scss b/packages/block-editor/src/components/inserter-list-item/style.scss index f91e4365db30ce..435f60ed9e2f14 100644 --- a/packages/block-editor/src/components/inserter-list-item/style.scss +++ b/packages/block-editor/src/components/inserter-list-item/style.scss @@ -43,7 +43,6 @@ cursor: pointer; background: transparent; word-break: break-word; - border-radius: $radius-block-ui; transition: all 0.05s ease-in-out; @include reduce-motion("transition"); position: relative; @@ -72,7 +71,7 @@ bottom: 0; left: 0; right: 0; - border-radius: $radius-block-ui; + border-radius: $radius-small; opacity: 0.04; background: var(--wp-admin-theme-color); // This fixes drag-and-drop in Firefox. @@ -97,7 +96,6 @@ .block-editor-block-types-list__item-icon { padding: 12px 20px; - border-radius: $radius-block-ui; color: $gray-900; transition: all 0.05s ease-in-out; @include reduce-motion("transition"); diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index 21f8abfa59c9e8..bd3ac3f961b88a 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -44,12 +44,12 @@ $block-inserter-tabs-height: 44px; &:first-child { border-top: $border-width solid $gray-400; - border-radius: $radius-block-ui $radius-block-ui 0 0; + border-radius: $radius-medium $radius-medium 0 0; } &:last-child { border-bottom: $border-width solid $gray-400; - border-radius: 0 0 $radius-block-ui $radius-block-ui; + border-radius: 0 0 $radius-medium $radius-medium; } &.components-button { @@ -276,7 +276,7 @@ $block-inserter-tabs-height: 44px; bottom: 0; left: 0; right: 0; - border-radius: $radius-block-ui; + border-radius: $radius-small; opacity: 0.04; background: var(--wp-admin-theme-color); height: 100%; @@ -359,7 +359,7 @@ $block-inserter-tabs-height: 44px; min-height: $grid-unit-60 * 3; color: $gray-700; background: $gray-100; - border-radius: $radius-block-ui; + border-radius: $radius-small; } .block-editor-inserter__tips { @@ -577,7 +577,6 @@ $block-inserter-tabs-height: 44px; > button { background: $white; - border-radius: $radius-block-ui; display: none; // These styles are important so as focus isn't lost @@ -611,7 +610,6 @@ $block-inserter-tabs-height: 44px; max-width: 100%; outline: $border-width solid rgba($black, 0.1); outline-offset: -$border-width; - border-radius: $radius-block-ui; } .block-editor-inserter__media-list__item-preview-spinner { diff --git a/packages/block-editor/src/components/link-control/style.scss b/packages/block-editor/src/components/link-control/style.scss index 1390a285fe163e..b0a5f6af2651b3 100644 --- a/packages/block-editor/src/components/link-control/style.scss +++ b/packages/block-editor/src/components/link-control/style.scss @@ -78,7 +78,6 @@ $block-editor-link-control-number-of-actions: 1; @include input-control; display: block; border: $border-width solid $gray-600; - border-radius: $radius-block-ui; height: $button-size-next-default-40px; // components do not properly support unstable-large yet. margin: 0; padding: $grid-unit-10 $button-size-next-default-40px $grid-unit-10 $grid-unit-20; @@ -230,7 +229,7 @@ $block-editor-link-control-number-of-actions: 1; background-color: $gray-100; width: $grid-unit-40; height: $grid-unit-40; - border-radius: $radius-block-ui; + border-radius: $radius-small; } .block-editor-link-control__search-item-icon { @@ -252,7 +251,6 @@ $block-editor-link-control-number-of-actions: 1; } .block-editor-link-control__search-item-title { - border-radius: $radius-block-ui; line-height: 1.1; diff --git a/packages/block-editor/src/components/list-view/style.scss b/packages/block-editor/src/components/list-view/style.scss index 406053af89317c..3d25597d2af904 100644 --- a/packages/block-editor/src/components/list-view/style.scss +++ b/packages/block-editor/src/components/list-view/style.scss @@ -101,16 +101,16 @@ // Border radius for corners of the selected item. &.is-first-selected td:first-child { - border-top-left-radius: $radius-block-ui; + border-top-left-radius: $radius-small; } &.is-first-selected td:last-child { - border-top-right-radius: $radius-block-ui; + border-top-right-radius: $radius-small; } &.is-last-selected td:first-child { - border-bottom-left-radius: $radius-block-ui; + border-bottom-left-radius: $radius-small; } &.is-last-selected td:last-child { - border-bottom-right-radius: $radius-block-ui; + border-bottom-right-radius: $radius-small; } &.is-branch-selected:not(.is-selected):not(.is-synced-branch) { background: rgba(var(--wp-admin-theme-color--rgb), 0.04); @@ -119,23 +119,23 @@ background: rgba(var(--wp-block-synced-color--rgb), 0.04); } &.is-branch-selected.is-first-selected td:first-child { - border-top-left-radius: $radius-block-ui; + border-top-left-radius: $radius-small; } &.is-branch-selected.is-first-selected td:last-child { - border-top-right-radius: $radius-block-ui; + border-top-right-radius: $radius-small; } &[data-expanded="false"] { &.is-branch-selected.is-first-selected td:first-child { - border-top-left-radius: $radius-block-ui; + border-top-left-radius: $radius-small; } &.is-branch-selected.is-first-selected td:last-child { - border-top-right-radius: $radius-block-ui; + border-top-right-radius: $radius-small; } &.is-branch-selected.is-last-selected td:first-child { - border-bottom-left-radius: $radius-block-ui; + border-bottom-left-radius: $radius-small; } &.is-branch-selected.is-last-selected td:last-child { - border-bottom-right-radius: $radius-block-ui; + border-bottom-right-radius: $radius-small; } } &.is-branch-selected:not(.is-selected) td { @@ -214,7 +214,6 @@ height: $grid-unit-40; padding: ($grid-unit-15 * 0.5) $grid-unit-05 ($grid-unit-15 * 0.5) 0; text-align: left; - border-radius: $radius-block-ui; position: relative; white-space: nowrap; @@ -406,7 +405,7 @@ right: 0; transform: translateY(-50%); background: rgba($black, 0.1); - border-radius: $radius-block-ui; + border-radius: $radius-x-small; padding: 2px 6px; max-width: 100%; box-sizing: border-box; @@ -429,10 +428,10 @@ background-size: cover; width: 18px; height: 18px; - border-radius: $radius-block-ui; + border-radius: $radius-x-small; &:not(:only-child) { - box-shadow: 0 0 0 $radius-block-ui $white; + box-shadow: 0 0 0 $radius-small $white; } &:not(:first-child) { @@ -442,7 +441,7 @@ &.is-selected .block-editor-list-view-block-select-button__image { &:not(:only-child) { - box-shadow: 0 0 0 $radius-block-ui var(--wp-admin-theme-color); + box-shadow: 0 0 0 $radius-small var(--wp-admin-theme-color); } } } diff --git a/packages/block-editor/src/components/rich-text/style.scss b/packages/block-editor/src/components/rich-text/style.scss index a3bb78b2521db8..ca274d378d4088 100644 --- a/packages/block-editor/src/components/rich-text/style.scss +++ b/packages/block-editor/src/components/rich-text/style.scss @@ -12,7 +12,7 @@ } .components-toolbar { - border-radius: $radius-block-ui; + border-radius: $radius-small; } .components-toolbar__control, diff --git a/packages/block-editor/src/components/warning/content.scss b/packages/block-editor/src/components/warning/content.scss index 0c1185a0782e41..9380a224b2ff95 100644 --- a/packages/block-editor/src/components/warning/content.scss +++ b/packages/block-editor/src/components/warning/content.scss @@ -7,7 +7,7 @@ // Block UI appearance. border: $border-width solid $gray-900; - border-radius: $radius-block-ui; + border-radius: $radius-small; background-color: $white; .block-editor-warning__message { diff --git a/packages/block-library/src/freeform/editor.scss b/packages/block-library/src/freeform/editor.scss index 7329eb6e5fb064..c2256ecd7a795f 100644 --- a/packages/block-library/src/freeform/editor.scss +++ b/packages/block-library/src/freeform/editor.scss @@ -299,7 +299,7 @@ div[data-type="core/freeform"] { top: 0; border: $border-width solid $gray-300; border-bottom: none; - border-radius: $radius-block-ui; + border-radius: $radius-small; margin-bottom: $grid-unit-10; // On mobile, toolbars go edge to edge. diff --git a/packages/block-library/src/gallery/editor.scss b/packages/block-library/src/gallery/editor.scss index 3184b9d3d8fb22..61121f3dd866dc 100644 --- a/packages/block-library/src/gallery/editor.scss +++ b/packages/block-library/src/gallery/editor.scss @@ -139,7 +139,7 @@ z-index: z-index(".block-library-gallery-item__inline-menu"); transition: box-shadow 0.2s ease-out; @include reduce-motion("transition"); - border-radius: $radius-block-ui; + border-radius: $radius-small; background: $white; border: $border-width solid $gray-900; diff --git a/packages/block-library/src/group/editor.scss b/packages/block-library/src/group/editor.scss index 041a2f9f884e84..11beecbab0eb68 100644 --- a/packages/block-library/src/group/editor.scss +++ b/packages/block-library/src/group/editor.scss @@ -43,7 +43,6 @@ pointer-events: none; min-height: $grid-unit-60 - $border-width - $border-width; border: $border-width dashed currentColor; - border-radius: $radius-block-ui; } // Let the parent be selectable in the placeholder area. diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss index db6928766c0b72..636741c7d9ddbb 100644 --- a/packages/block-library/src/image/editor.scss +++ b/packages/block-library/src/image/editor.scss @@ -13,9 +13,6 @@ // Disable any duotone filter applied in the selected state. filter: none !important; - // @todo this should eventually be overridden by a custom border-radius set in the inspector. - border-radius: $radius-block-ui; - > svg { opacity: 0; } diff --git a/packages/block-library/src/navigation/editor.scss b/packages/block-library/src/navigation/editor.scss index 619b8dc6f0c7bd..a8d135656e44a1 100644 --- a/packages/block-library/src/navigation/editor.scss +++ b/packages/block-library/src/navigation/editor.scss @@ -104,7 +104,6 @@ background: $gray-900; padding: 0; width: $button-size-small; - border-radius: $radius-block-ui; margin-right: 0; margin-left: auto; } @@ -326,7 +325,7 @@ $color-control-label-height: 20px; } .wp-block-navigation-placeholder__controls { - border-radius: $radius-block-ui; + border-radius: $radius-small; background-color: $white; box-shadow: inset 0 0 0 $border-width $gray-900; display: none; diff --git a/packages/commands/src/components/style.scss b/packages/commands/src/components/style.scss index e69853bad95997..bcf3d17d7baa6c 100644 --- a/packages/commands/src/components/style.scss +++ b/packages/commands/src/components/style.scss @@ -33,7 +33,7 @@ border: $border-width solid $gray-600; border-right: 0; justify-content: center; - border-radius: $radius-block-ui 0 0 $radius-block-ui; + border-radius: $radius-small 0 0 $radius-small; & + [cmdk-input] { border-top-left-radius: 0; @@ -68,7 +68,7 @@ } [cmdk-item] { - border-radius: $radius-block-ui; + border-radius: $radius-small; cursor: pointer; display: flex; align-items: center; diff --git a/packages/dataviews/src/components/dataviews-filters/style.scss b/packages/dataviews/src/components/dataviews-filters/style.scss index f2841c16f0fec4..ad834fb224e2e4 100644 --- a/packages/dataviews/src/components/dataviews-filters/style.scss +++ b/packages/dataviews/src/components/dataviews-filters/style.scss @@ -169,7 +169,7 @@ display: flex; align-items: center; gap: $grid-unit-10; - border-radius: $radius-block-ui; + border-radius: $radius-small; box-sizing: border-box; padding: $grid-unit-10 $grid-unit-15; cursor: default; diff --git a/packages/dataviews/src/dataviews-layouts/grid/style.scss b/packages/dataviews/src/dataviews-layouts/grid/style.scss index d154d2b614def5..5fab362b0b47b6 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/style.scss +++ b/packages/dataviews/src/dataviews-layouts/grid/style.scss @@ -118,7 +118,7 @@ background: $gray-100; padding: 0 $grid-unit-10; min-height: $grid-unit-30; - border-radius: $radius-block-ui; + border-radius: $radius-small; display: flex; align-items: center; font-size: 12px; diff --git a/packages/dataviews/src/dataviews-layouts/list/style.scss b/packages/dataviews/src/dataviews-layouts/list/style.scss index 7344af6c3d1e82..ea3236f6d75e1e 100644 --- a/packages/dataviews/src/dataviews-layouts/list/style.scss +++ b/packages/dataviews/src/dataviews-layouts/list/style.scss @@ -114,12 +114,12 @@ ul.dataviews-view-list { &::before { position: absolute; content: ""; - top: calc(var(--wp-admin-border-width-focus) + 1px); + top: var(--wp-admin-border-width-focus); right: var(--wp-admin-border-width-focus); bottom: var(--wp-admin-border-width-focus); left: var(--wp-admin-border-width-focus); box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - border-radius: $radius-block-ui; + border-radius: $radius-small; } } .dataviews-view-list__primary-field { diff --git a/packages/edit-post/src/components/back-button/style.scss b/packages/edit-post/src/components/back-button/style.scss index 8ffae89e31e054..aced752bfedfae 100644 --- a/packages/edit-post/src/components/back-button/style.scss +++ b/packages/edit-post/src/components/back-button/style.scss @@ -32,7 +32,7 @@ right: 9px; bottom: 9px + $border-width; // Height of toolbar in edit-post (not edit-site) is 61px tall. left: 9px; - border-radius: $radius-block-ui + $border-width + $border-width; + border-radius: $radius-small + $border-width + $border-width; box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) $gray-900; } @@ -54,7 +54,7 @@ .edit-post-fullscreen-mode-close_site-icon { width: $button-size; height: $button-size; - border-radius: $radius-block-ui; + border-radius: $radius-small; object-fit: cover; // Compensate for the top-bar border. margin-top: -($border-width); diff --git a/packages/edit-site/src/components/add-new-template/style.scss b/packages/edit-site/src/components/add-new-template/style.scss index 922083d14b75eb..a83754ce2e547a 100644 --- a/packages/edit-site/src/components/add-new-template/style.scss +++ b/packages/edit-site/src/components/add-new-template/style.scss @@ -82,7 +82,7 @@ .edit-site-custom-template-modal__no-results { border: $border-width solid $gray-400; - border-radius: $radius-block-ui; + border-radius: $radius-small; padding: $grid-unit-20; } @@ -132,7 +132,6 @@ .edit-site-add-new-template__template-list__contents { > .components-button { padding: $grid-unit-40; - border-radius: $radius-block-ui; display: flex; flex-direction: column; border: $border-width solid $gray-300; diff --git a/packages/edit-site/src/components/editor-canvas-container/style.scss b/packages/edit-site/src/components/editor-canvas-container/style.scss index fad566212e7328..7df2b0ceca552f 100644 --- a/packages/edit-site/src/components/editor-canvas-container/style.scss +++ b/packages/edit-site/src/components/editor-canvas-container/style.scss @@ -16,7 +16,7 @@ .edit-site-editor-canvas-container__section { background: $white; // Fallback color, overridden by JavaScript. - border-radius: $radius-block-ui; + border-radius: $radius-large; bottom: 0; left: 0; overflow: hidden; diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/style.scss b/packages/edit-site/src/components/global-styles/screen-revisions/style.scss index 46972f4b7c52ff..5d0e7cb185137a 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/style.scss +++ b/packages/edit-site/src/components/global-styles/screen-revisions/style.scss @@ -43,7 +43,7 @@ } &.is-selected { - border-radius: $radius-block-ui; + border-radius: $radius-small; // Only visible in Windows High Contrast mode. outline: 3px solid transparent; diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss index f85d69ad864ad8..9bab48e308947a 100644 --- a/packages/edit-site/src/components/global-styles/style.scss +++ b/packages/edit-site/src/components/global-styles/style.scss @@ -19,7 +19,7 @@ min-height: 100px; margin-bottom: $grid-unit-20; background: $gray-100; - border-radius: $radius-block-ui; + border-radius: $radius-small; overflow: hidden; } @@ -45,7 +45,7 @@ display: flex !important; align-items: center; justify-content: center; - border-radius: $radius-block-ui; + border-radius: $radius-x-small; } .edit-site-global-styles-screen-typography__font-variants-count { @@ -113,14 +113,14 @@ position: relative; width: 100%; border: $gray-200 $border-width solid; - border-radius: $radius-block-ui; + border-radius: $radius-medium; overflow: hidden; } .edit-site-global-styles__shadow-preview-panel { height: $grid-unit-60 * 3; border: $gray-200 $border-width solid; - border-radius: $radius-block-ui; + border-radius: $radius-medium; overflow: auto; background-image: repeating-linear-gradient(45deg, #f5f5f5 25%, #0000 0, #0000 75%, #f5f5f5 0, #f5f5f5), repeating-linear-gradient(45deg, #f5f5f5 25%, #0000 0, #0000 75%, #f5f5f5 0, #f5f5f5); background-position: 0 0, 8px 8px; @@ -128,7 +128,7 @@ .edit-site-global-styles__shadow-preview-block { border: $gray-200 $border-width solid; - border-radius: $radius-block-ui; + border-radius: $radius-small; background-color: $white; width: 60%; height: 60px; diff --git a/packages/edit-site/src/components/global-styles/variations/style.scss b/packages/edit-site/src/components/global-styles/variations/style.scss index 8d9b4238efa337..5f57c72f180b12 100644 --- a/packages/edit-site/src/components/global-styles/variations/style.scss +++ b/packages/edit-site/src/components/global-styles/variations/style.scss @@ -1,11 +1,10 @@ .edit-site-global-styles-variations_item { box-sizing: border-box; // To round the outline in Windows 10 high contrast mode. - border-radius: $radius-block-ui; cursor: pointer; .edit-site-global-styles-variations_item-preview { - border-radius: $radius-block-ui; + border-radius: $radius-small; outline: $border-width solid rgba($black, 0.1); outline-offset: -$border-width; overflow: hidden; diff --git a/packages/edit-site/src/components/layout/style.scss b/packages/edit-site/src/components/layout/style.scss index 64fb1914af3dd3..b2d929a7943dbf 100644 --- a/packages/edit-site/src/components/layout/style.scss +++ b/packages/edit-site/src/components/layout/style.scss @@ -120,7 +120,7 @@ overflow: hidden; .edit-site-layout:not(.is-full-canvas) & { - border-radius: $radius-block-ui * 4; + border-radius: $radius-large; } } } @@ -200,7 +200,7 @@ html.canvas-mode-edit-transition::view-transition-group(toggle) { right: 9px; bottom: 9px; left: 9px; - border-radius: $radius-block-ui + $border-width + $border-width; + border-radius: $radius-medium; box-shadow: none; } diff --git a/packages/edit-site/src/components/page-patterns/style.scss b/packages/edit-site/src/components/page-patterns/style.scss index a5aa1eb9ac796e..c62fe34daf7d67 100644 --- a/packages/edit-site/src/components/page-patterns/style.scss +++ b/packages/edit-site/src/components/page-patterns/style.scss @@ -126,8 +126,8 @@ .components-form-token-field__suggestions-list:not(:empty) { position: absolute; border: $border-width solid var(--wp-admin-theme-color); - border-bottom-left-radius: $radius-block-ui; - border-bottom-right-radius: $radius-block-ui; + border-bottom-left-radius: $radius-small; + border-bottom-right-radius: $radius-small; box-shadow: 0 0 0.5px 0.5px var(--wp-admin-theme-color); box-sizing: border-box; z-index: 1; diff --git a/packages/edit-site/src/components/page-templates/style.scss b/packages/edit-site/src/components/page-templates/style.scss index 4e21ca2c25be28..6a753921f6f40a 100644 --- a/packages/edit-site/src/components/page-templates/style.scss +++ b/packages/edit-site/src/components/page-templates/style.scss @@ -36,7 +36,6 @@ } .dataviews-view-table & { - border-radius: $radius-block-ui; position: relative; width: 120px; max-height: 160px; @@ -49,7 +48,7 @@ width: 100%; height: 100%; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); - border-radius: $radius-block-ui; + border-radius: $radius-medium; } } } diff --git a/packages/edit-site/src/components/post-list/style.scss b/packages/edit-site/src/components/post-list/style.scss index a86783c163c83e..895a02b3106725 100644 --- a/packages/edit-site/src/components/post-list/style.scss +++ b/packages/edit-site/src/components/post-list/style.scss @@ -68,7 +68,7 @@ background: $gray-100; color: $gray-700; padding: 0 $grid-unit-05; - border-radius: $radius-block-ui; + border-radius: $radius-small; font-size: 12px; font-weight: 400; flex-shrink: 0; diff --git a/packages/edit-site/src/components/sidebar-dataviews/style.scss b/packages/edit-site/src/components/sidebar-dataviews/style.scss index 9c5b8f48e944f2..14e6bf1d03fca8 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/style.scss +++ b/packages/edit-site/src/components/sidebar-dataviews/style.scss @@ -8,7 +8,7 @@ } .edit-site-sidebar-dataviews-dataview-item { - border-radius: $radius-block-ui; + border-radius: $radius-small; padding-right: $grid-unit-10; .edit-site-sidebar-dataviews-dataview-item__dropdown-menu { diff --git a/packages/edit-site/src/components/sidebar-navigation-item/style.scss b/packages/edit-site/src/components/sidebar-navigation-item/style.scss index 908056d52af48c..016027ef715a45 100644 --- a/packages/edit-site/src/components/sidebar-navigation-item/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-item/style.scss @@ -4,7 +4,6 @@ padding: $grid-unit-10 6px $grid-unit-10 $grid-unit-20; border: none; min-height: $grid-unit-50; - border-radius: $radius-block-ui; &:hover, &:focus, diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss index 43b789d669ba4d..f0260581a8988f 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss @@ -146,7 +146,6 @@ .components-input-control__input { color: $gray-200 !important; background: $gray-800 !important; - border-radius: $radius-block-ui; } .components-input-control__backdrop { border: 4px !important; diff --git a/packages/edit-site/src/components/style-book/style.scss b/packages/edit-site/src/components/style-book/style.scss index 3b2c6ab0867dbe..ab66ec288da310 100644 --- a/packages/edit-site/src/components/style-book/style.scss +++ b/packages/edit-site/src/components/style-book/style.scss @@ -3,13 +3,13 @@ // This is useful when the style book is used to fill a frame. height: 100%; &.is-button { - border-radius: $radius-block-ui * 4; + border-radius: $radius-large; } } .edit-site-style-book__iframe { &.is-button { - border-radius: $radius-block-ui * 4; + border-radius: $radius-large; } &.is-focused { outline: calc(2 * var(--wp-admin-border-width-focus)) solid var(--wp-admin-theme-color); diff --git a/packages/editor/src/components/document-outline/style.scss b/packages/editor/src/components/document-outline/style.scss index efd2606b82d394..49ce0c9b2d1325 100644 --- a/packages/editor/src/components/document-outline/style.scss +++ b/packages/editor/src/components/document-outline/style.scss @@ -51,7 +51,7 @@ padding: 2px 5px 2px 1px; color: $gray-900; text-align: left; - border-radius: $radius-block-ui; + border-radius: $radius-small; &:disabled { cursor: default; diff --git a/packages/editor/src/components/post-card-panel/style.scss b/packages/editor/src/components/post-card-panel/style.scss index 3547b0ab104936..73b638673f3e91 100644 --- a/packages/editor/src/components/post-card-panel/style.scss +++ b/packages/editor/src/components/post-card-panel/style.scss @@ -46,7 +46,7 @@ background: $gray-100; color: $gray-700; padding: 0 $grid-unit-05; - border-radius: $radius-block-ui; + border-radius: $radius-small; font-size: 12px; font-weight: 400; flex-shrink: 0; diff --git a/packages/editor/src/components/post-featured-image/style.scss b/packages/editor/src/components/post-featured-image/style.scss index d3a4fbbcaef689..3a537471b42f29 100644 --- a/packages/editor/src/components/post-featured-image/style.scss +++ b/packages/editor/src/components/post-featured-image/style.scss @@ -22,7 +22,7 @@ } .components-drop-zone__content { - border-radius: $radius-block-ui; + border-radius: $radius-small; } // Align text and icons horizontally to avoid clipping when the featured image is not set. @@ -65,7 +65,6 @@ } .editor-post-featured-image__toggle { - border-radius: $radius-block-ui; height: 100%; line-height: 20px; padding: $grid-unit-10 0; diff --git a/packages/editor/src/components/post-locked-modal/style.scss b/packages/editor/src/components/post-locked-modal/style.scss index 03e86642493df3..7f680022344664 100644 --- a/packages/editor/src/components/post-locked-modal/style.scss +++ b/packages/editor/src/components/post-locked-modal/style.scss @@ -3,7 +3,7 @@ } .editor-post-locked-modal__avatar { - border-radius: $radius-block-ui; + border-radius: $radius-round; margin-top: $grid-unit-20; min-width: initial !important; } diff --git a/packages/editor/src/components/post-publish-panel/style.scss b/packages/editor/src/components/post-publish-panel/style.scss index bcd7c798c7e9fb..9892cf5430f9a2 100644 --- a/packages/editor/src/components/post-publish-panel/style.scss +++ b/packages/editor/src/components/post-publish-panel/style.scss @@ -37,7 +37,7 @@ .components-site-icon { border: none; - border-radius: $radius-block-ui; + border-radius: $radius-small; margin-right: $grid-unit-15; flex-shrink: 0; diff --git a/packages/editor/src/components/resizable-editor/style.scss b/packages/editor/src/components/resizable-editor/style.scss index 91ff1144c4179b..364fdf39ad3155 100644 --- a/packages/editor/src/components/resizable-editor/style.scss +++ b/packages/editor/src/components/resizable-editor/style.scss @@ -16,7 +16,7 @@ cursor: ew-resize; outline: none; background: none; - border-radius: $radius-block-ui; + border-radius: $radius-full; border: 0; height: 100px; @@ -29,7 +29,7 @@ content: ""; width: $grid-unit-05; background-color: rgba($gray-700, 0.4); - border-radius: $radius-block-ui; + border-radius: $radius-full; } &.is-left { diff --git a/packages/patterns/src/components/style.scss b/packages/patterns/src/components/style.scss index 30fe0300503c48..1b053ab7ac2517 100644 --- a/packages/patterns/src/components/style.scss +++ b/packages/patterns/src/components/style.scss @@ -13,8 +13,8 @@ .components-form-token-field__suggestions-list:not(:empty) { position: absolute; border: $border-width solid var(--wp-admin-theme-color); - border-bottom-left-radius: $radius-block-ui; - border-bottom-right-radius: $radius-block-ui; + border-bottom-left-radius: $radius-small; + border-bottom-right-radius: $radius-small; box-shadow: 0 0 0.5px 0.5px var(--wp-admin-theme-color); box-sizing: border-box; z-index: 1; diff --git a/packages/widgets/src/blocks/legacy-widget/editor.scss b/packages/widgets/src/blocks/legacy-widget/editor.scss index 6b04ce0a407e43..8c213eec86f9fa 100644 --- a/packages/widgets/src/blocks/legacy-widget/editor.scss +++ b/packages/widgets/src/blocks/legacy-widget/editor.scss @@ -3,7 +3,7 @@ display: flow-root; } background: $white; - border-radius: $radius-block-ui; + border-radius: $radius-small; border: $border-width solid $gray-900; padding: $grid-unit-15 - $border-width; max-height: calc(100vh - #{ $border-width } - #{ $border-width }); @@ -95,7 +95,7 @@ cursor: pointer; &:hover::after { - border-radius: $radius-block-ui; + border-radius: $radius-small; border: $border-width solid $gray-600; bottom: 0; content: ""; diff --git a/packages/widgets/src/blocks/widget-group/editor.scss b/packages/widgets/src/blocks/widget-group/editor.scss index 38798ef34c7c6e..1cd179539bc1a9 100644 --- a/packages/widgets/src/blocks/widget-group/editor.scss +++ b/packages/widgets/src/blocks/widget-group/editor.scss @@ -1,6 +1,6 @@ .wp-block-widget-group { &.has-child-selected::after { - border-radius: $radius-block-ui; + border-radius: $radius-small; border: $border-width solid var(--wp-admin-theme-color); bottom: 0; content: ""; From 0a86ab3ef5253d18306ed6c81d6f1820428b4384 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 4 Sep 2024 15:56:04 +0200 Subject: [PATCH 0672/1908] Downloadable Block List: do not use composite store (#65038) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/downloadable-block-list-item/index.js | 3 +-- .../src/components/downloadable-blocks-list/index.js | 6 +----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/block-directory/src/components/downloadable-block-list-item/index.js b/packages/block-directory/src/components/downloadable-block-list-item/index.js index 03e6e79d8928e9..45a2930ad656e3 100644 --- a/packages/block-directory/src/components/downloadable-block-list-item/index.js +++ b/packages/block-directory/src/components/downloadable-block-list-item/index.js @@ -65,7 +65,7 @@ function getDownloadableBlockLabel( ); } -function DownloadableBlockListItem( { composite, item, onClick } ) { +function DownloadableBlockListItem( { item, onClick } ) { const { author, description, icon, rating, title } = item; // getBlockType returns a block object if this block exists, or null if not. const isInstalled = !! getBlockType( item.name ); @@ -116,7 +116,6 @@ function DownloadableBlockListItem( { composite, item, onClick } ) { tooltipPosition="top center" /> } - store={ composite } disabled={ isInstalling || ! isInstallable } > <div className="block-directory-downloadable-block-list-item__icon"> diff --git a/packages/block-directory/src/components/downloadable-blocks-list/index.js b/packages/block-directory/src/components/downloadable-blocks-list/index.js index 09f509c4ed49c9..3911c3297376db 100644 --- a/packages/block-directory/src/components/downloadable-blocks-list/index.js +++ b/packages/block-directory/src/components/downloadable-blocks-list/index.js @@ -13,12 +13,10 @@ import DownloadableBlockListItem from '../downloadable-block-list-item'; import { store as blockDirectoryStore } from '../../store'; import { unlock } from '../../lock-unlock'; -const { CompositeV2: Composite, useCompositeStoreV2: useCompositeStore } = - unlock( componentsPrivateApis ); +const { CompositeV2: Composite } = unlock( componentsPrivateApis ); const noop = () => {}; function DownloadableBlocksList( { items, onHover = noop, onSelect } ) { - const composite = useCompositeStore(); const { installBlockType } = useDispatch( blockDirectoryStore ); if ( ! items.length ) { @@ -27,7 +25,6 @@ function DownloadableBlocksList( { items, onHover = noop, onSelect } ) { return ( <Composite - store={ composite } role="listbox" className="block-directory-downloadable-blocks-list" aria-label={ __( 'Blocks available for install' ) } @@ -36,7 +33,6 @@ function DownloadableBlocksList( { items, onHover = noop, onSelect } ) { return ( <DownloadableBlockListItem key={ item.id } - composite={ composite } onClick={ () => { // Check if the block is registered (`getBlockType` // will return an object). If so, insert the block. From 1d5340ac8c1b0669439d31a7def8ebbf65dd5685 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 4 Sep 2024 15:56:30 +0200 Subject: [PATCH 0673/1908] Block Pattern Setup: do not use Composite store (#65039) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/block-pattern-setup/index.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/block-pattern-setup/index.js b/packages/block-editor/src/components/block-pattern-setup/index.js index edd55e90dc3e27..6ec3f79b5f703b 100644 --- a/packages/block-editor/src/components/block-pattern-setup/index.js +++ b/packages/block-editor/src/components/block-pattern-setup/index.js @@ -22,11 +22,9 @@ import usePatternsSetup from './use-patterns-setup'; import { VIEWMODES } from './constants'; import { unlock } from '../../lock-unlock'; -const { - CompositeV2: Composite, - CompositeItemV2: CompositeItem, - useCompositeStoreV2: useCompositeStore, -} = unlock( componentsPrivateApis ); +const { CompositeV2: Composite, CompositeItemV2: CompositeItem } = unlock( + componentsPrivateApis +); const SetupContent = ( { viewMode, @@ -35,7 +33,6 @@ const SetupContent = ( { onBlockPatternSelect, showTitles, } ) => { - const compositeStore = useCompositeStore(); const containerClass = 'block-editor-block-pattern-setup__container'; if ( viewMode === VIEWMODES.carousel ) { @@ -65,7 +62,6 @@ const SetupContent = ( { return ( <div className="block-editor-block-pattern-setup__grid"> <Composite - store={ compositeStore } role="listbox" className={ containerClass } aria-label={ __( 'Patterns list' ) } From bf468ed89e3106f32d57d51ddc9484cda5c19cc7 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 4 Sep 2024 15:57:01 +0200 Subject: [PATCH 0674/1908] Pattern Transformations Menu: do not use Composite store (#65040) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../block-switcher/pattern-transformations-menu.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js b/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js index 46fd83c92d91f6..c2e7fa88a879be 100644 --- a/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js +++ b/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js @@ -21,11 +21,9 @@ import BlockPreview from '../block-preview'; import useTransformedPatterns from './use-transformed-patterns'; import { unlock } from '../../lock-unlock'; -const { - CompositeV2: Composite, - CompositeItemV2: CompositeItem, - useCompositeStoreV2: useCompositeStore, -} = unlock( componentsPrivateApis ); +const { CompositeV2: Composite, CompositeItemV2: CompositeItem } = unlock( + componentsPrivateApis +); function PatternTransformationsMenu( { blocks, @@ -82,10 +80,8 @@ function PreviewPatternsPopover( { patterns, onSelect } ) { } function BlockPatternsList( { patterns, onSelect } ) { - const composite = useCompositeStore(); return ( <Composite - store={ composite } role="listbox" className="block-editor-block-switcher__preview-patterns-container" aria-label={ __( 'Patterns list' ) } From 1a1e3a96569b51c7d061b9968b11924047f8d1c5 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 4 Sep 2024 15:58:24 +0200 Subject: [PATCH 0675/1908] Global Styles Shadow Panel: do not use Composite store (#65041) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../global-styles/shadow-panel-components.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/shadow-panel-components.js b/packages/block-editor/src/components/global-styles/shadow-panel-components.js index e3a6c71adf8fc6..0f30f769f7b102 100644 --- a/packages/block-editor/src/components/global-styles/shadow-panel-components.js +++ b/packages/block-editor/src/components/global-styles/shadow-panel-components.js @@ -32,11 +32,9 @@ import { unlock } from '../../lock-unlock'; * @type {Array} */ const EMPTY_ARRAY = []; -const { - CompositeItemV2: CompositeItem, - CompositeV2: Composite, - useCompositeStoreV2: useCompositeStore, -} = unlock( componentsPrivateApis ); +const { CompositeItemV2: CompositeItem, CompositeV2: Composite } = unlock( + componentsPrivateApis +); export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) { const shadows = useShadowPresets( settings ); @@ -66,10 +64,8 @@ export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) { } export function ShadowPresets( { presets, activeShadow, onSelect } ) { - const compositeStore = useCompositeStore(); return ! presets ? null : ( <Composite - store={ compositeStore } role="listbox" className="block-editor-global-styles__shadow__list" aria-label={ __( 'Drop shadows' ) } From be1617dd3f0ea782703e221f2bddc0474e50aa0b Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 4 Sep 2024 15:59:26 +0200 Subject: [PATCH 0676/1908] Block Inserter Listbox: do not use Composite store (#65042) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/inserter-listbox/index.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/inserter-listbox/index.js b/packages/block-editor/src/components/inserter-listbox/index.js index 6af26a1d746bfb..f1168f67fd6113 100644 --- a/packages/block-editor/src/components/inserter-listbox/index.js +++ b/packages/block-editor/src/components/inserter-listbox/index.js @@ -12,17 +12,11 @@ export { default as InserterListboxGroup } from './group'; export { default as InserterListboxRow } from './row'; export { default as InserterListboxItem } from './item'; -const { CompositeV2: Composite, useCompositeStoreV2: useCompositeStore } = - unlock( componentsPrivateApis ); +const { CompositeV2: Composite } = unlock( componentsPrivateApis ); function InserterListbox( { children } ) { - const store = useCompositeStore( { - focusShift: true, - focusWrap: 'horizontal', - } ); - return ( - <Composite store={ store } render={ <></> }> + <Composite focusShift focusWrap="horizontal" render={ <></> }> { children } </Composite> ); From ba63b90f01c4d4b80171cc0640e1e8dafe2e0e4e Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 4 Sep 2024 15:59:48 +0200 Subject: [PATCH 0677/1908] Block Inserter Media List: do not use Composite store (#65043) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/inserter/media-tab/media-list.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/inserter/media-tab/media-list.js b/packages/block-editor/src/components/inserter/media-tab/media-list.js index bfc858bc8c4de7..9d03b3086176f0 100644 --- a/packages/block-editor/src/components/inserter/media-tab/media-list.js +++ b/packages/block-editor/src/components/inserter/media-tab/media-list.js @@ -10,8 +10,7 @@ import { __ } from '@wordpress/i18n'; import { MediaPreview } from './media-preview'; import { unlock } from '../../../lock-unlock'; -const { CompositeV2: Composite, useCompositeStoreV2: useCompositeStore } = - unlock( componentsPrivateApis ); +const { CompositeV2: Composite } = unlock( componentsPrivateApis ); function MediaList( { mediaList, @@ -19,10 +18,8 @@ function MediaList( { onClick, label = __( 'Media List' ), } ) { - const compositeStore = useCompositeStore(); return ( <Composite - store={ compositeStore } role="listbox" className="block-editor-inserter__media-list" aria-label={ label } From 0adcec4dca448cf0ff06f14abe08a0f8dee23ee9 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 4 Sep 2024 16:03:09 +0200 Subject: [PATCH 0678/1908] Add Custom Template modal: do not use Composite store (#65044) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../add-custom-template-modal-content.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js b/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js index 0ef403379ccdb8..f63a980954e36c 100644 --- a/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js +++ b/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js @@ -23,11 +23,9 @@ import { useDebouncedInput } from '@wordpress/compose'; import { unlock } from '../../lock-unlock'; import { mapToIHasNameAndId } from './utils'; -const { - CompositeV2: Composite, - CompositeItemV2: CompositeItem, - useCompositeStoreV2: useCompositeStore, -} = unlock( componentsPrivateApis ); +const { CompositeV2: Composite, CompositeItemV2: CompositeItem } = unlock( + componentsPrivateApis +); const EMPTY_ARRAY = []; @@ -122,7 +120,6 @@ function useSearchSuggestions( entityForSuggestions, search ) { } function SuggestionList( { entityForSuggestions, onSelect } ) { - const composite = useCompositeStore( { orientation: 'vertical' } ); const [ search, setSearch, debouncedSearch ] = useDebouncedInput(); const suggestions = useSearchSuggestions( entityForSuggestions, @@ -146,7 +143,7 @@ function SuggestionList( { entityForSuggestions, onSelect } ) { ) } { !! suggestions?.length && ( <Composite - store={ composite } + orientation="vertical" role="listbox" className="edit-site-custom-template-modal__suggestions_list" aria-label={ __( 'Suggestions list' ) } From 793d32601834d6acf7280a61f7d060ddd3aa2429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Gomes?= <mail@sgomes.com> Date: Wed, 4 Sep 2024 15:13:08 +0100 Subject: [PATCH 0679/1908] Media & Text: don't use background-image (#64981) * media-text block: don't use background-image * Add PR link to deprecated.js for future reference * Fix PHP indentation * Fix inconsistencies in some fixtures after markup changes * Update PHP tests to match new expected render * Add back old fixtures as new deprecated fixtures * Improve deprecation comment wording in styles Co-authored-by: Nik Tsekouras <ntsekouras@outlook.com> * Remove 'not contains' checks from PHP tests * Rename new CSS class to is-image-fill-element --------- Co-authored-by: sgomes <sergiomdgomes@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: skorasaurus <skorasaurus@git.wordpress.org> --- .../src/media-text/deprecated.js | 162 +++++++++++++++++- packages/block-library/src/media-text/edit.js | 10 +- .../block-library/src/media-text/editor.scss | 4 +- .../src/media-text/image-fill.js | 11 ++ .../block-library/src/media-text/index.php | 96 ++++++----- .../src/media-text/media-container.js | 41 +++-- .../src/media-text/media-container.native.js | 2 - packages/block-library/src/media-text/save.js | 22 +-- .../block-library/src/media-text/style.scss | 21 +++ .../src/media-text/test/image-fill.js | 19 ++ .../src/media-text/test/media-container.js | 24 --- .../blocks/render-block-media-text-test.php | 28 ++- ..._media-text__deprecated-v5.serialized.html | 2 +- ...v7-image-fill-no-focal-point-selected.html | 13 ++ ...v7-image-fill-no-focal-point-selected.json | 29 ++++ ...e-fill-no-focal-point-selected.parsed.json | 29 ++++ ...ll-no-focal-point-selected.serialized.html | 5 + ...-image-fill-with-focal-point-selected.html | 13 ++ ...-image-fill-with-focal-point-selected.json | 33 ++++ ...fill-with-focal-point-selected.parsed.json | 33 ++++ ...-with-focal-point-selected.serialized.html | 5 + .../core__media-text__deprecated-v7.html | 13 ++ .../core__media-text__deprecated-v7.json | 30 ++++ ...ore__media-text__deprecated-v7.parsed.json | 29 ++++ ..._media-text__deprecated-v7.serialized.html | 5 + ...t__image-fill-no-focal-point-selected.html | 9 +- ...t__image-fill-no-focal-point-selected.json | 5 +- ...e-fill-no-focal-point-selected.parsed.json | 5 +- ...ll-no-focal-point-selected.serialized.html | 2 +- ..._image-fill-with-focal-point-selected.html | 9 +- ..._image-fill-with-focal-point-selected.json | 5 +- ...fill-with-focal-point-selected.parsed.json | 5 +- ...-with-focal-point-selected.serialized.html | 2 +- 33 files changed, 575 insertions(+), 146 deletions(-) create mode 100644 packages/block-library/src/media-text/image-fill.js create mode 100644 packages/block-library/src/media-text/test/image-fill.js delete mode 100644 packages/block-library/src/media-text/test/media-container.js create mode 100644 test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.html create mode 100644 test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.json create mode 100644 test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.parsed.json create mode 100644 test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.serialized.html create mode 100644 test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.html create mode 100644 test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.json create mode 100644 test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.parsed.json create mode 100644 test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.serialized.html create mode 100644 test/integration/fixtures/blocks/core__media-text__deprecated-v7.html create mode 100644 test/integration/fixtures/blocks/core__media-text__deprecated-v7.json create mode 100644 test/integration/fixtures/blocks/core__media-text__deprecated-v7.parsed.json create mode 100644 test/integration/fixtures/blocks/core__media-text__deprecated-v7.serialized.html diff --git a/packages/block-library/src/media-text/deprecated.js b/packages/block-library/src/media-text/deprecated.js index 1cd1472f876c05..54c6f863311ffe 100644 --- a/packages/block-library/src/media-text/deprecated.js +++ b/packages/block-library/src/media-text/deprecated.js @@ -30,7 +30,7 @@ const v1ToV5ImageFillStyles = ( url, focalPoint ) => { : {}; }; -const v6ImageFillStyles = ( url, focalPoint ) => { +const v6ToV7ImageFillStyles = ( url, focalPoint ) => { return url ? { backgroundImage: `url(${ url })`, @@ -198,6 +198,20 @@ const v6Attributes = { }, }; +const v7Attributes = { + ...v6Attributes, + align: { + type: 'string', + // v7 changed the default for the `align` attribute. + default: 'none', + }, + // New attribute. + useFeaturedImage: { + type: 'boolean', + default: false, + }, +}; + const v4ToV5Supports = { anchor: true, align: [ 'wide', 'full' ], @@ -237,6 +251,148 @@ const v6Supports = { }, }; +const v7Supports = { + ...v6Supports, + __experimentalBorder: { + color: true, + radius: true, + style: true, + width: true, + __experimentalDefaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, + }, + color: { + gradients: true, + heading: true, + link: true, + __experimentalDefaultControls: { + background: true, + text: true, + }, + }, + interactivity: { + clientNavigation: true, + }, +}; + +// Version with 'none' as the default alignment. +// See: https://github.com/WordPress/gutenberg/pull/64981 +const v7 = { + attributes: v7Attributes, + supports: v7Supports, + usesContext: [ 'postId', 'postType' ], + save( { attributes } ) { + const { + isStackedOnMobile, + mediaAlt, + mediaPosition, + mediaType, + mediaUrl, + mediaWidth, + mediaId, + verticalAlignment, + imageFill, + focalPoint, + linkClass, + href, + linkTarget, + rel, + } = attributes; + const mediaSizeSlug = + attributes.mediaSizeSlug || DEFAULT_MEDIA_SIZE_SLUG; + const newRel = ! rel ? undefined : rel; + + const imageClasses = clsx( { + [ `wp-image-${ mediaId }` ]: mediaId && mediaType === 'image', + [ `size-${ mediaSizeSlug }` ]: mediaId && mediaType === 'image', + } ); + + let image = mediaUrl ? ( + <img + src={ mediaUrl } + alt={ mediaAlt } + className={ imageClasses || null } + /> + ) : null; + + if ( href ) { + image = ( + <a + className={ linkClass } + href={ href } + target={ linkTarget } + rel={ newRel } + > + { image } + </a> + ); + } + + const mediaTypeRenders = { + image: () => image, + video: () => <video controls src={ mediaUrl } />, + }; + const className = clsx( { + 'has-media-on-the-right': 'right' === mediaPosition, + 'is-stacked-on-mobile': isStackedOnMobile, + [ `is-vertically-aligned-${ verticalAlignment }` ]: + verticalAlignment, + 'is-image-fill': imageFill, + } ); + const backgroundStyles = imageFill + ? v6ToV7ImageFillStyles( mediaUrl, focalPoint ) + : {}; + + let gridTemplateColumns; + if ( mediaWidth !== DEFAULT_MEDIA_WIDTH ) { + gridTemplateColumns = + 'right' === mediaPosition + ? `auto ${ mediaWidth }%` + : `${ mediaWidth }% auto`; + } + const style = { + gridTemplateColumns, + }; + + if ( 'right' === mediaPosition ) { + return ( + <div { ...useBlockProps.save( { className, style } ) }> + <div + { ...useInnerBlocksProps.save( { + className: 'wp-block-media-text__content', + } ) } + /> + <figure + className="wp-block-media-text__media" + style={ backgroundStyles } + > + { ( mediaTypeRenders[ mediaType ] || noop )() } + </figure> + </div> + ); + } + return ( + <div { ...useBlockProps.save( { className, style } ) }> + <figure + className="wp-block-media-text__media" + style={ backgroundStyles } + > + { ( mediaTypeRenders[ mediaType ] || noop )() } + </figure> + <div + { ...useInnerBlocksProps.save( { + className: 'wp-block-media-text__content', + } ) } + /> + </div> + ); + }, +}; + // Version with wide as the default alignment. // See: https://github.com/WordPress/gutenberg/pull/48404 const v6 = { @@ -301,7 +457,7 @@ const v6 = { 'is-image-fill': imageFill, } ); const backgroundStyles = imageFill - ? v6ImageFillStyles( mediaUrl, focalPoint ) + ? v6ToV7ImageFillStyles( mediaUrl, focalPoint ) : {}; let gridTemplateColumns; @@ -902,4 +1058,4 @@ const v1 = { }, }; -export default [ v6, v5, v4, v3, v2, v1 ]; +export default [ v7, v6, v5, v4, v3, v2, v1 ]; diff --git a/packages/block-library/src/media-text/edit.js b/packages/block-library/src/media-text/edit.js index 2c020506dc889c..a946a499b26f21 100644 --- a/packages/block-library/src/media-text/edit.js +++ b/packages/block-library/src/media-text/edit.js @@ -213,11 +213,11 @@ function MediaTextEdit( { [ isSelected, mediaId ] ); - const refMediaContainer = useRef(); + const refMedia = useRef(); const imperativeFocalPointPreview = ( value ) => { - const { style } = refMediaContainer.current.resizable; + const { style } = refMedia.current; const { x, y } = value; - style.backgroundPosition = `${ x * 100 }% ${ y * 100 }%`; + style.objectPosition = `${ x * 100 }% ${ y * 100 }%`; }; const [ temporaryMediaWidth, setTemporaryMediaWidth ] = useState( null ); @@ -243,7 +243,7 @@ function MediaTextEdit( { 'is-selected': isSelected, 'is-stacked-on-mobile': isStackedOnMobile, [ `is-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment, - 'is-image-fill': imageFill, + 'is-image-fill-element': imageFill, } ); const widthString = `${ temporaryMediaWidth || mediaWidth }%`; const gridTemplateColumns = @@ -480,7 +480,7 @@ function MediaTextEdit( { onSelectMedia={ onSelectMedia } onWidthChange={ onWidthChange } commitWidthChange={ commitWidthChange } - ref={ refMediaContainer } + refMedia={ refMedia } enableResize={ blockEditingMode === 'default' } toggleUseFeaturedImage={ toggleUseFeaturedImage } { ...{ diff --git a/packages/block-library/src/media-text/editor.scss b/packages/block-library/src/media-text/editor.scss index b417fb951e99d0..639ceaed8ea99c 100644 --- a/packages/block-library/src/media-text/editor.scss +++ b/packages/block-library/src/media-text/editor.scss @@ -27,7 +27,9 @@ } .wp-block-media-text.is-image-fill .editor-media-container__resizer, -.wp-block-media-text.is-image-fill .components-placeholder.has-illustration { +.wp-block-media-text.is-image-fill .components-placeholder.has-illustration, +.wp-block-media-text.is-image-fill-element .editor-media-container__resizer, +.wp-block-media-text.is-image-fill-element .components-placeholder.has-illustration { // The resizer sets an inline height but for the image fill we set it to full height. height: 100% !important; } diff --git a/packages/block-library/src/media-text/image-fill.js b/packages/block-library/src/media-text/image-fill.js new file mode 100644 index 00000000000000..c277c49b5c310b --- /dev/null +++ b/packages/block-library/src/media-text/image-fill.js @@ -0,0 +1,11 @@ +export function imageFillStyles( url, focalPoint ) { + return url + ? { + objectPosition: focalPoint + ? `${ Math.round( focalPoint.x * 100 ) }% ${ Math.round( + focalPoint.y * 100 + ) }%` + : `50% 50%`, + } + : {}; +} diff --git a/packages/block-library/src/media-text/index.php b/packages/block-library/src/media-text/index.php index 87be164a04bb99..b65137b150ba53 100644 --- a/packages/block-library/src/media-text/index.php +++ b/packages/block-library/src/media-text/index.php @@ -29,15 +29,32 @@ function render_block_core_media_text( $attributes, $content ) { return $content; } + $has_media_on_right = isset( $attributes['mediaPosition'] ) && 'right' === $attributes['mediaPosition']; + $image_fill = isset( $attributes['imageFill'] ) && $attributes['imageFill']; + $focal_point = isset( $attributes['focalPoint'] ) ? round( $attributes['focalPoint']['x'] * 100 ) . '% ' . round( $attributes['focalPoint']['y'] * 100 ) . '%' : '50% 50%'; + $unique_id = 'wp-block-media-text__media-' . wp_unique_id(); + + $block_tag_processor = new WP_HTML_Tag_Processor( $content ); + $block_query = array( + 'tag_name' => 'div', + 'class_name' => 'wp-block-media-text', + ); + + while ( $block_tag_processor->next_tag( $block_query ) ) { + if ( $image_fill ) { + // The markup below does not work with the deprecated `is-image-fill` class. + $block_tag_processor->remove_class( 'is-image-fill' ); + $block_tag_processor->add_class( 'is-image-fill-element' ); + } + } + + $content = $block_tag_processor->get_updated_html(); + $media_tag_processor = new WP_HTML_Tag_Processor( $content ); $wrapping_figure_query = array( 'tag_name' => 'figure', 'class_name' => 'wp-block-media-text__media', ); - $has_media_on_right = isset( $attributes['mediaPosition'] ) && 'right' === $attributes['mediaPosition']; - $image_fill = isset( $attributes['imageFill'] ) && $attributes['imageFill']; - $focal_point = isset( $attributes['focalPoint'] ) ? round( $attributes['focalPoint']['x'] * 100 ) . '% ' . round( $attributes['focalPoint']['y'] * 100 ) . '%' : '50% 50%'; - $unique_id = 'wp-block-media-text__media-' . wp_unique_id(); if ( $has_media_on_right ) { // Loop through all the figure tags and set a bookmark on the last figure tag. @@ -46,59 +63,52 @@ function render_block_core_media_text( $attributes, $content ) { } if ( $media_tag_processor->has_bookmark( 'last_figure' ) ) { $media_tag_processor->seek( 'last_figure' ); - if ( $image_fill ) { - $media_tag_processor->set_attribute( 'style', 'background-image:url(' . esc_url( $current_featured_image ) . ');background-position:' . $focal_point . ';' ); - } else { - // Insert a unique ID to identify the figure tag. - $media_tag_processor->set_attribute( 'id', $unique_id ); - } + // Insert a unique ID to identify the figure tag. + $media_tag_processor->set_attribute( 'id', $unique_id ); } } else { if ( $media_tag_processor->next_tag( $wrapping_figure_query ) ) { - if ( $image_fill ) { - $media_tag_processor->set_attribute( 'style', 'background-image:url(' . esc_url( $current_featured_image ) . ');background-position:' . $focal_point . ';' ); - } else { - // Insert a unique ID to identify the figure tag. - $media_tag_processor->set_attribute( 'id', $unique_id ); - } + // Insert a unique ID to identify the figure tag. + $media_tag_processor->set_attribute( 'id', $unique_id ); } } $content = $media_tag_processor->get_updated_html(); - // If the image is not set to fill, add the image tag inside the figure tag, - // and update the image attributes in order to display the featured image. - if ( ! $image_fill ) { - $media_size_slug = isset( $attributes['mediaSizeSlug'] ) ? $attributes['mediaSizeSlug'] : 'full'; - $image_tag = '<img class="wp-block-media-text__featured_image">'; - $content = preg_replace( - '/(<figure\s+id="' . preg_quote( $unique_id, '/' ) . '"\s+class="wp-block-media-text__media"\s*>)/', - '$1' . $image_tag, - $content - ); + // Add the image tag inside the figure tag, and update the image attributes + // in order to display the featured image. + $media_size_slug = isset( $attributes['mediaSizeSlug'] ) ? $attributes['mediaSizeSlug'] : 'full'; + $image_tag = '<img class="wp-block-media-text__featured_image">'; + $content = preg_replace( + '/(<figure\s+id="' . preg_quote( $unique_id, '/' ) . '"\s+class="wp-block-media-text__media"\s*>)/', + '$1' . $image_tag, + $content + ); - $image_tag_processor = new WP_HTML_Tag_Processor( $content ); + $image_tag_processor = new WP_HTML_Tag_Processor( $content ); + if ( $image_tag_processor->next_tag( + array( + 'tag_name' => 'figure', + 'id' => $unique_id, + ) + ) ) { + // The ID is only used to ensure that the correct figure tag is selected, + // and can now be removed. + $image_tag_processor->remove_attribute( 'id' ); if ( $image_tag_processor->next_tag( array( - 'tag_name' => 'figure', - 'id' => $unique_id, + 'tag_name' => 'img', + 'class_name' => 'wp-block-media-text__featured_image', ) ) ) { - // The ID is only used to ensure that the correct figure tag is selected, - // and can now be removed. - $image_tag_processor->remove_attribute( 'id' ); - if ( $image_tag_processor->next_tag( - array( - 'tag_name' => 'img', - 'class_name' => 'wp-block-media-text__featured_image', - ) - ) ) { - $image_tag_processor->set_attribute( 'src', esc_url( $current_featured_image ) ); - $image_tag_processor->set_attribute( 'class', 'wp-image-' . get_post_thumbnail_id() . ' size-' . $media_size_slug ); - $image_tag_processor->set_attribute( 'alt', trim( strip_tags( get_post_meta( get_post_thumbnail_id(), '_wp_attachment_image_alt', true ) ) ) ); - - $content = $image_tag_processor->get_updated_html(); + $image_tag_processor->set_attribute( 'src', esc_url( $current_featured_image ) ); + $image_tag_processor->set_attribute( 'class', 'wp-image-' . get_post_thumbnail_id() . ' size-' . $media_size_slug ); + $image_tag_processor->set_attribute( 'alt', trim( strip_tags( get_post_meta( get_post_thumbnail_id(), '_wp_attachment_image_alt', true ) ) ) ); + if ( $image_fill ) { + $image_tag_processor->set_attribute( 'style', 'object-position:' . $focal_point . ';' ); } + + $content = $image_tag_processor->get_updated_html(); } } diff --git a/packages/block-library/src/media-text/media-container.js b/packages/block-library/src/media-text/media-container.js index 986ecad6cc7e69..735aaf73b88aae 100644 --- a/packages/block-library/src/media-text/media-container.js +++ b/packages/block-library/src/media-text/media-container.js @@ -22,25 +22,17 @@ import { isBlobURL } from '@wordpress/blob'; import { store as noticesStore } from '@wordpress/notices'; import { media as icon } from '@wordpress/icons'; +/** + * Internal dependencies + */ +import { imageFillStyles } from './image-fill'; + /** * Constants */ const ALLOWED_MEDIA_TYPES = [ 'image', 'video' ]; const noop = () => {}; -export function imageFillStyles( url, focalPoint ) { - return url - ? { - backgroundImage: `url(${ url })`, - backgroundPosition: focalPoint - ? `${ Math.round( focalPoint.x * 100 ) }% ${ Math.round( - focalPoint.y * 100 - ) }%` - : `50% 50%`, - } - : {}; -} - const ResizableBoxContainer = forwardRef( ( { isSelected, isStackedOnMobile, ...props }, ref ) => { const isMobile = useViewportMatch( 'small', '<' ); @@ -129,6 +121,7 @@ function MediaContainer( props, ref ) { useFeaturedImage, featuredImageURL, featuredImageAlt, + refMedia, } = props; const isTemporaryMedia = ! mediaId && isBlobURL( mediaUrl ); @@ -151,7 +144,7 @@ function MediaContainer( props, ref ) { left: enableResize && mediaPosition === 'right', }; - const backgroundStyles = + const positionStyles = mediaType === 'image' && imageFill ? imageFillStyles( mediaUrl || featuredImageURL, focalPoint ) : {}; @@ -159,11 +152,23 @@ function MediaContainer( props, ref ) { const mediaTypeRenderers = { image: () => useFeaturedImage && featuredImageURL ? ( - <img src={ featuredImageURL } alt={ featuredImageAlt } /> + <img + ref={ refMedia } + src={ featuredImageURL } + alt={ featuredImageAlt } + style={ positionStyles } + /> ) : ( - mediaUrl && <img src={ mediaUrl } alt={ mediaAlt } /> + mediaUrl && ( + <img + ref={ refMedia } + src={ mediaUrl } + alt={ mediaAlt } + style={ positionStyles } + /> + ) ), - video: () => <video controls src={ mediaUrl } />, + video: () => <video controls ref={ refMedia } src={ mediaUrl } />, }; return ( @@ -174,7 +179,6 @@ function MediaContainer( props, ref ) { 'editor-media-container__resizer', { 'is-transient': isTemporaryMedia } ) } - style={ backgroundStyles } size={ { width: mediaWidth + '%' } } minWidth="10%" maxWidth="100%" @@ -203,6 +207,7 @@ function MediaContainer( props, ref ) { { ! featuredImageURL && useFeaturedImage && ( <Placeholder className="wp-block-media-text--placeholder-image" + style={ positionStyles } withIllustration /> ) } diff --git a/packages/block-library/src/media-text/media-container.native.js b/packages/block-library/src/media-text/media-container.native.js index eaee027c061856..3bf4fbf25d8f2a 100644 --- a/packages/block-library/src/media-text/media-container.native.js +++ b/packages/block-library/src/media-text/media-container.native.js @@ -44,8 +44,6 @@ const ICON_TYPE = { RETRY: 'retry', }; -export { imageFillStyles } from './media-container.js'; - class MediaContainer extends Component { constructor() { super( ...arguments ); diff --git a/packages/block-library/src/media-text/save.js b/packages/block-library/src/media-text/save.js index 5bf9517adae669..3e660d94e789ee 100644 --- a/packages/block-library/src/media-text/save.js +++ b/packages/block-library/src/media-text/save.js @@ -11,7 +11,7 @@ import { useInnerBlocksProps, useBlockProps } from '@wordpress/block-editor'; /** * Internal dependencies */ -import { imageFillStyles } from './media-container'; +import { imageFillStyles } from './image-fill'; import { DEFAULT_MEDIA_SIZE_SLUG } from './constants'; const DEFAULT_MEDIA_WIDTH = 50; @@ -42,11 +42,16 @@ export default function save( { attributes } ) { [ `size-${ mediaSizeSlug }` ]: mediaId && mediaType === 'image', } ); + const positionStyles = imageFill + ? imageFillStyles( mediaUrl, focalPoint ) + : {}; + let image = mediaUrl ? ( <img src={ mediaUrl } alt={ mediaAlt } className={ imageClasses || null } + style={ positionStyles } /> ) : null; @@ -71,11 +76,8 @@ export default function save( { attributes } ) { 'has-media-on-the-right': 'right' === mediaPosition, 'is-stacked-on-mobile': isStackedOnMobile, [ `is-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment, - 'is-image-fill': imageFill, + 'is-image-fill-element': imageFill, } ); - const backgroundStyles = imageFill - ? imageFillStyles( mediaUrl, focalPoint ) - : {}; let gridTemplateColumns; if ( mediaWidth !== DEFAULT_MEDIA_WIDTH ) { @@ -96,10 +98,7 @@ export default function save( { attributes } ) { className: 'wp-block-media-text__content', } ) } /> - <figure - className="wp-block-media-text__media" - style={ backgroundStyles } - > + <figure className="wp-block-media-text__media"> { ( mediaTypeRenders[ mediaType ] || noop )() } </figure> </div> @@ -107,10 +106,7 @@ export default function save( { attributes } ) { } return ( <div { ...useBlockProps.save( { className, style } ) }> - <figure - className="wp-block-media-text__media" - style={ backgroundStyles } - > + <figure className="wp-block-media-text__media"> { ( mediaTypeRenders[ mediaType ] || noop )() } </figure> <div diff --git a/packages/block-library/src/media-text/style.scss b/packages/block-library/src/media-text/style.scss index de020611b36ced..0f7a34f05548c0 100644 --- a/packages/block-library/src/media-text/style.scss +++ b/packages/block-library/src/media-text/style.scss @@ -80,6 +80,7 @@ vertical-align: middle; } +/* `is-image-fill` is deprecated and the styles are kept for backwards compatibility. */ .wp-block-media-text.is-image-fill > .wp-block-media-text__media { height: 100%; min-height: 250px; @@ -102,6 +103,26 @@ clip: rect(0, 0, 0, 0); border: 0; } + +/* Image fill for versions 8 and onwards */ +.wp-block-media-text.is-image-fill-element > .wp-block-media-text__media { + position: relative; + height: 100%; + min-height: 250px; +} + +.wp-block-media-text.is-image-fill-element > .wp-block-media-text__media > a { + display: block; + height: 100%; +} + +.wp-block-media-text.is-image-fill-element > .wp-block-media-text__media img { + position: absolute; + width: 100%; + height: 100%; + object-fit: cover; +} + /* * Here we here not able to use a mobile first CSS approach. * Custom widths are set using inline styles, and on mobile, diff --git a/packages/block-library/src/media-text/test/image-fill.js b/packages/block-library/src/media-text/test/image-fill.js new file mode 100644 index 00000000000000..4862fcbfb02453 --- /dev/null +++ b/packages/block-library/src/media-text/test/image-fill.js @@ -0,0 +1,19 @@ +/** + * Internal dependencies + */ +import { imageFillStyles } from '../image-fill'; + +describe( 'imageFillStyles()', () => { + it( 'should return centered object position', () => { + const { objectPosition } = imageFillStyles( 'image.jpg' ); + expect( objectPosition ).toBe( '50% 50%' ); + } ); + + it( 'should return custom object position', () => { + const { objectPosition } = imageFillStyles( 'image.jpg', { + x: 0.56, + y: 0.57, + } ); + expect( objectPosition ).toBe( '56% 57%' ); + } ); +} ); diff --git a/packages/block-library/src/media-text/test/media-container.js b/packages/block-library/src/media-text/test/media-container.js deleted file mode 100644 index 582ec2be8d5ad8..00000000000000 --- a/packages/block-library/src/media-text/test/media-container.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Internal dependencies - */ -import { imageFillStyles } from '../media-container'; - -describe( 'imageFillStyles()', () => { - it( 'should return image url', () => { - const { backgroundImage } = imageFillStyles( 'image.jpg' ); - expect( backgroundImage ).toBe( 'url(image.jpg)' ); - } ); - - it( 'should return centered background position', () => { - const { backgroundPosition } = imageFillStyles( 'image.jpg' ); - expect( backgroundPosition ).toBe( '50% 50%' ); - } ); - - it( 'should return custom background position', () => { - const { backgroundPosition } = imageFillStyles( 'image.jpg', { - x: 0.56, - y: 0.57, - } ); - expect( backgroundPosition ).toBe( '56% 57%' ); - } ); -} ); diff --git a/phpunit/blocks/render-block-media-text-test.php b/phpunit/blocks/render-block-media-text-test.php index 94c184408c89fb..f5b67f0a8dc9b7 100644 --- a/phpunit/blocks/render-block-media-text-test.php +++ b/phpunit/blocks/render-block-media-text-test.php @@ -81,15 +81,14 @@ public function test_render_block_core_media_text_featured_image() { $rendered = gutenberg_render_block_core_media_text( $attributes, $content ); $this->assertStringContainsString( '<img alt="" src="' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . '"', $rendered ); - // Assert that the rendered block contains the featured image as the background-image url, - // and not the image element, when image fill is true. + // Assert that the rendered block contains the featured image as an image element, + // when image fill is true. $attributes = array( 'useFeaturedImage' => true, 'imageFill' => true, ); $rendered = gutenberg_render_block_core_media_text( $attributes, $content ); - $this->assertStringContainsString( 'background-image:url(' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . ')', $rendered ); - $this->assertStringNotContainsString( '<img', $rendered ); + $this->assertStringContainsString( '<img alt="" src="' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . '"', $rendered ); } /** @@ -107,15 +106,14 @@ public function test_render_block_core_media_text_featured_image_nested() { $rendered = gutenberg_render_block_core_media_text( $attributes, $content ); $this->assertStringContainsString( '<img alt="" src="' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . '"', $rendered ); - // Assert that the rendered block contains the featured image as the background-image url, - // and not the image element, when image fill is true. + // Assert that the rendered block contains the featured image as an image element, + // when image fill is true. $attributes = array( 'useFeaturedImage' => true, 'imageFill' => true, ); $rendered = gutenberg_render_block_core_media_text( $attributes, $content ); - $this->assertStringContainsString( 'background-image:url(' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . ')', $rendered ); - $this->assertStringNotContainsString( '<img', $rendered ); + $this->assertStringContainsString( '<img alt="" src="' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . '"', $rendered ); } /** @@ -134,16 +132,15 @@ public function test_render_block_core_media_text_featured_image_media_on_right( $rendered = gutenberg_render_block_core_media_text( $attributes, $content ); $this->assertStringContainsString( '<img alt="" src="' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . '"', $rendered ); - // Assert that the rendered block contains the featured image as the background-image url, - // and not the image element, when image fill is true and the media is on the right. + // Assert that the rendered block contains the featured image as an image element, + // when image fill is true and the media is on the right. $attributes = array( 'useFeaturedImage' => true, 'mediaPosition' => 'right', 'imageFill' => true, ); $rendered = gutenberg_render_block_core_media_text( $attributes, $content ); - $this->assertStringContainsString( 'background-image:url(' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . ')', $rendered ); - $this->assertStringNotContainsString( '<img', $rendered ); + $this->assertStringContainsString( '<img alt="" src="' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . '"', $rendered ); } /** @@ -164,8 +161,8 @@ public function test_render_block_core_media_text_featured_image_media_on_right_ $rendered = gutenberg_render_block_core_media_text( $attributes, $content ); $this->assertStringContainsString( '<img alt="" src="' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . '"', $rendered ); - // Assert that the rendered block contains the featured image as the background-image url, - // and not the image element, when image fill is true and the media is on the right. + // Assert that the rendered block contains the featured image as an image element, + // when image fill is true and the media is on the right. $attributes = array( 'useFeaturedImage' => true, 'mediaPosition' => 'right', @@ -173,7 +170,6 @@ public function test_render_block_core_media_text_featured_image_media_on_right_ ); $rendered = gutenberg_render_block_core_media_text( $attributes, $content ); - $this->assertStringContainsString( 'background-image:url(' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . ')', $rendered ); - $this->assertStringNotContainsString( '<img', $rendered ); + $this->assertStringContainsString( '<img alt="" src="' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . '"', $rendered ); } } diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v5.serialized.html b/test/integration/fixtures/blocks/core__media-text__deprecated-v5.serialized.html index 7d7a76c730b273..8c88b8b67795d7 100644 --- a/test/integration/fixtures/blocks/core__media-text__deprecated-v5.serialized.html +++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v5.serialized.html @@ -1,5 +1,5 @@ <!-- wp:media-text {"align":"wide","mediaType":"image","imageFill":true,"focalPoint":{"x":"0.56","y":"0.57"}} --> -<div class="wp-block-media-text alignwide is-stacked-on-mobile is-image-fill"><figure class="wp-block-media-text__media" style="background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:56% 57%"><img src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" alt="My alt text"/></figure><div class="wp-block-media-text__content"><!-- wp:paragraph {"placeholder":"Content…"} --> +<div class="wp-block-media-text alignwide is-stacked-on-mobile is-image-fill-element"><figure class="wp-block-media-text__media"><img src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" alt="My alt text" style="object-position:56% 57%"/></figure><div class="wp-block-media-text__content"><!-- wp:paragraph {"placeholder":"Content…"} --> <p>My Content</p> <!-- /wp:paragraph --></div></div> <!-- /wp:media-text --> diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.html b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.html new file mode 100644 index 00000000000000..22a2a3e18f74f6 --- /dev/null +++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.html @@ -0,0 +1,13 @@ +<!-- wp:media-text {"mediaType":"image","imageFill":true} --> +<div class="wp-block-media-text alignwide is-image-fill is-stacked-on-mobile"> + <figure class="wp-block-media-text__media" + style="background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:50% 50%"> + <img src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" + alt="My alt text" /></figure> + <div class="wp-block-media-text__content"> + <!-- wp:paragraph {"placeholder":"Content…","fontSize":"large"} --> + <p class="has-large-font-size">My Content</p> + <!-- /wp:paragraph --> + </div> +</div> +<!-- /wp:media-text --> diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.json b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.json new file mode 100644 index 00000000000000..bf195f6fa1c953 --- /dev/null +++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.json @@ -0,0 +1,29 @@ +[ + { + "name": "core/media-text", + "isValid": true, + "attributes": { + "align": "wide", + "mediaAlt": "My alt text", + "mediaPosition": "left", + "mediaType": "image", + "mediaWidth": 50, + "isStackedOnMobile": true, + "mediaUrl": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=", + "imageFill": true + }, + "innerBlocks": [ + { + "name": "core/paragraph", + "isValid": true, + "attributes": { + "content": "My Content", + "dropCap": false, + "placeholder": "Content…", + "fontSize": "large" + }, + "innerBlocks": [] + } + ] + } +] diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.parsed.json b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.parsed.json new file mode 100644 index 00000000000000..2e878c98a18a89 --- /dev/null +++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.parsed.json @@ -0,0 +1,29 @@ +[ + { + "blockName": "core/media-text", + "attrs": { + "mediaType": "image", + "imageFill": true + }, + "innerBlocks": [ + { + "blockName": "core/paragraph", + "attrs": { + "placeholder": "Content…", + "fontSize": "large" + }, + "innerBlocks": [], + "innerHTML": "\n\t\t<p class=\"has-large-font-size\">My Content</p>\n\t\t", + "innerContent": [ + "\n\t\t<p class=\"has-large-font-size\">My Content</p>\n\t\t" + ] + } + ], + "innerHTML": "\n<div class=\"wp-block-media-text alignwide is-image-fill is-stacked-on-mobile\">\n\t<figure class=\"wp-block-media-text__media\"\n\t\tstyle=\"background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:50% 50%\">\n\t\t<img src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\"\n\t\t\talt=\"My alt text\" /></figure>\n\t<div class=\"wp-block-media-text__content\">\n\t\t\n\t</div>\n</div>\n", + "innerContent": [ + "\n<div class=\"wp-block-media-text alignwide is-image-fill is-stacked-on-mobile\">\n\t<figure class=\"wp-block-media-text__media\"\n\t\tstyle=\"background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:50% 50%\">\n\t\t<img src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\"\n\t\t\talt=\"My alt text\" /></figure>\n\t<div class=\"wp-block-media-text__content\">\n\t\t", + null, + "\n\t</div>\n</div>\n" + ] + } +] diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.serialized.html b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.serialized.html new file mode 100644 index 00000000000000..b9d5e14f90277c --- /dev/null +++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.serialized.html @@ -0,0 +1,5 @@ +<!-- wp:media-text {"align":"wide","mediaType":"image","imageFill":true} --> +<div class="wp-block-media-text alignwide is-stacked-on-mobile is-image-fill-element"><figure class="wp-block-media-text__media"><img src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" alt="My alt text" style="object-position:50% 50%"/></figure><div class="wp-block-media-text__content"><!-- wp:paragraph {"placeholder":"Content…","fontSize":"large"} --> +<p class="has-large-font-size">My Content</p> +<!-- /wp:paragraph --></div></div> +<!-- /wp:media-text --> diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.html b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.html new file mode 100644 index 00000000000000..47a0f0c126fa70 --- /dev/null +++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.html @@ -0,0 +1,13 @@ +<!-- wp:media-text {"mediaType":"image","imageFill":true,"focalPoint":{"x":0.84,"y":0.84}} --> +<div class="wp-block-media-text alignwide is-image-fill is-stacked-on-mobile"> + <figure class="wp-block-media-text__media" + style="background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:84% 84%"> + <img src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" + alt="My alt text" /></figure> + <div class="wp-block-media-text__content"> + <!-- wp:paragraph {"placeholder":"Content…","fontSize":"large"} --> + <p class="has-large-font-size">My Content</p> + <!-- /wp:paragraph --> + </div> +</div> +<!-- /wp:media-text --> diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.json b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.json new file mode 100644 index 00000000000000..986e049099541f --- /dev/null +++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.json @@ -0,0 +1,33 @@ +[ + { + "name": "core/media-text", + "isValid": true, + "attributes": { + "align": "wide", + "mediaAlt": "My alt text", + "mediaPosition": "left", + "mediaType": "image", + "mediaWidth": 50, + "isStackedOnMobile": true, + "mediaUrl": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=", + "imageFill": true, + "focalPoint": { + "x": 0.84, + "y": 0.84 + } + }, + "innerBlocks": [ + { + "name": "core/paragraph", + "isValid": true, + "attributes": { + "content": "My Content", + "dropCap": false, + "placeholder": "Content…", + "fontSize": "large" + }, + "innerBlocks": [] + } + ] + } +] diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.parsed.json b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.parsed.json new file mode 100644 index 00000000000000..175fbad27927b7 --- /dev/null +++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.parsed.json @@ -0,0 +1,33 @@ +[ + { + "blockName": "core/media-text", + "attrs": { + "mediaType": "image", + "imageFill": true, + "focalPoint": { + "x": 0.84, + "y": 0.84 + } + }, + "innerBlocks": [ + { + "blockName": "core/paragraph", + "attrs": { + "placeholder": "Content…", + "fontSize": "large" + }, + "innerBlocks": [], + "innerHTML": "\n\t\t<p class=\"has-large-font-size\">My Content</p>\n\t\t", + "innerContent": [ + "\n\t\t<p class=\"has-large-font-size\">My Content</p>\n\t\t" + ] + } + ], + "innerHTML": "\n<div class=\"wp-block-media-text alignwide is-image-fill is-stacked-on-mobile\">\n\t<figure class=\"wp-block-media-text__media\"\n\t\tstyle=\"background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:84% 84%\">\n\t\t<img src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\"\n\t\t\talt=\"My alt text\" /></figure>\n\t<div class=\"wp-block-media-text__content\">\n\t\t\n\t</div>\n</div>\n", + "innerContent": [ + "\n<div class=\"wp-block-media-text alignwide is-image-fill is-stacked-on-mobile\">\n\t<figure class=\"wp-block-media-text__media\"\n\t\tstyle=\"background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:84% 84%\">\n\t\t<img src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\"\n\t\t\talt=\"My alt text\" /></figure>\n\t<div class=\"wp-block-media-text__content\">\n\t\t", + null, + "\n\t</div>\n</div>\n" + ] + } +] diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.serialized.html b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.serialized.html new file mode 100644 index 00000000000000..4b001f4f27c8ad --- /dev/null +++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.serialized.html @@ -0,0 +1,5 @@ +<!-- wp:media-text {"align":"wide","mediaType":"image","imageFill":true,"focalPoint":{"x":0.84,"y":0.84}} --> +<div class="wp-block-media-text alignwide is-stacked-on-mobile is-image-fill-element"><figure class="wp-block-media-text__media"><img src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" alt="My alt text" style="object-position:84% 84%"/></figure><div class="wp-block-media-text__content"><!-- wp:paragraph {"placeholder":"Content…","fontSize":"large"} --> +<p class="has-large-font-size">My Content</p> +<!-- /wp:paragraph --></div></div> +<!-- /wp:media-text --> diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7.html b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.html new file mode 100644 index 00000000000000..92b4b4d2754133 --- /dev/null +++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.html @@ -0,0 +1,13 @@ +<!-- wp:media-text {"mediaType":"image","imageFill":true} --> +<div class="wp-block-media-text is-image-fill is-stacked-on-mobile"> + <figure class="wp-block-media-text__media" + style="background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:50% 50%"> + <img src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" + alt="My alt text" /></figure> + <div class="wp-block-media-text__content"> + <!-- wp:paragraph {"placeholder":"Content…","fontSize":"large"} --> + <p class="has-large-font-size">My Content</p> + <!-- /wp:paragraph --> + </div> +</div> +<!-- /wp:media-text --> diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7.json b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.json new file mode 100644 index 00000000000000..a6f0dff927874d --- /dev/null +++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.json @@ -0,0 +1,30 @@ +[ + { + "name": "core/media-text", + "isValid": true, + "attributes": { + "align": "none", + "mediaAlt": "My alt text", + "mediaPosition": "left", + "mediaType": "image", + "mediaWidth": 50, + "isStackedOnMobile": true, + "mediaUrl": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=", + "imageFill": true, + "useFeaturedImage": false + }, + "innerBlocks": [ + { + "name": "core/paragraph", + "isValid": true, + "attributes": { + "content": "My Content", + "dropCap": false, + "placeholder": "Content…", + "fontSize": "large" + }, + "innerBlocks": [] + } + ] + } +] diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7.parsed.json b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.parsed.json new file mode 100644 index 00000000000000..49b392d4231384 --- /dev/null +++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.parsed.json @@ -0,0 +1,29 @@ +[ + { + "blockName": "core/media-text", + "attrs": { + "mediaType": "image", + "imageFill": true + }, + "innerBlocks": [ + { + "blockName": "core/paragraph", + "attrs": { + "placeholder": "Content…", + "fontSize": "large" + }, + "innerBlocks": [], + "innerHTML": "\n\t\t<p class=\"has-large-font-size\">My Content</p>\n\t\t", + "innerContent": [ + "\n\t\t<p class=\"has-large-font-size\">My Content</p>\n\t\t" + ] + } + ], + "innerHTML": "\n<div class=\"wp-block-media-text is-image-fill is-stacked-on-mobile\">\n\t<figure class=\"wp-block-media-text__media\"\n\t\tstyle=\"background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:50% 50%\">\n\t\t<img src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\"\n\t\t\talt=\"My alt text\" /></figure>\n\t<div class=\"wp-block-media-text__content\">\n\t\t\n\t</div>\n</div>\n", + "innerContent": [ + "\n<div class=\"wp-block-media-text is-image-fill is-stacked-on-mobile\">\n\t<figure class=\"wp-block-media-text__media\"\n\t\tstyle=\"background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:50% 50%\">\n\t\t<img src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\"\n\t\t\talt=\"My alt text\" /></figure>\n\t<div class=\"wp-block-media-text__content\">\n\t\t", + null, + "\n\t</div>\n</div>\n" + ] + } +] diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7.serialized.html b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.serialized.html new file mode 100644 index 00000000000000..b44ebe1c4ee896 --- /dev/null +++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.serialized.html @@ -0,0 +1,5 @@ +<!-- wp:media-text {"mediaType":"image","imageFill":true} --> +<div class="wp-block-media-text is-stacked-on-mobile is-image-fill-element"><figure class="wp-block-media-text__media"><img src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" alt="My alt text" style="object-position:50% 50%"/></figure><div class="wp-block-media-text__content"><!-- wp:paragraph {"placeholder":"Content…","fontSize":"large"} --> +<p class="has-large-font-size">My Content</p> +<!-- /wp:paragraph --></div></div> +<!-- /wp:media-text --> diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.html b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.html index 22a2a3e18f74f6..30667e0dd24dc5 100644 --- a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.html +++ b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.html @@ -1,9 +1,8 @@ -<!-- wp:media-text {"mediaType":"image","imageFill":true} --> -<div class="wp-block-media-text alignwide is-image-fill is-stacked-on-mobile"> - <figure class="wp-block-media-text__media" - style="background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:50% 50%"> +<!-- wp:media-text {"align":"wide","mediaType":"image","imageFill":true} --> +<div class="wp-block-media-text alignwide is-image-fill-element is-stacked-on-mobile"> + <figure class="wp-block-media-text__media"> <img src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" - alt="My alt text" /></figure> + alt="My alt text" style="object-position:50% 50%"/></figure> <div class="wp-block-media-text__content"> <!-- wp:paragraph {"placeholder":"Content…","fontSize":"large"} --> <p class="has-large-font-size">My Content</p> diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.json b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.json index bf195f6fa1c953..bb57f08ad5cfa7 100644 --- a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.json +++ b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.json @@ -6,11 +6,12 @@ "align": "wide", "mediaAlt": "My alt text", "mediaPosition": "left", + "mediaUrl": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=", "mediaType": "image", "mediaWidth": 50, "isStackedOnMobile": true, - "mediaUrl": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=", - "imageFill": true + "imageFill": true, + "useFeaturedImage": false }, "innerBlocks": [ { diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.parsed.json b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.parsed.json index 2e878c98a18a89..674b3724af8e88 100644 --- a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.parsed.json +++ b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.parsed.json @@ -2,6 +2,7 @@ { "blockName": "core/media-text", "attrs": { + "align": "wide", "mediaType": "image", "imageFill": true }, @@ -19,9 +20,9 @@ ] } ], - "innerHTML": "\n<div class=\"wp-block-media-text alignwide is-image-fill is-stacked-on-mobile\">\n\t<figure class=\"wp-block-media-text__media\"\n\t\tstyle=\"background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:50% 50%\">\n\t\t<img src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\"\n\t\t\talt=\"My alt text\" /></figure>\n\t<div class=\"wp-block-media-text__content\">\n\t\t\n\t</div>\n</div>\n", + "innerHTML": "\n<div class=\"wp-block-media-text alignwide is-image-fill-element is-stacked-on-mobile\">\n\t<figure class=\"wp-block-media-text__media\">\n\t\t<img src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\"\n\t\t\talt=\"My alt text\" style=\"object-position:50% 50%\"/></figure>\n\t<div class=\"wp-block-media-text__content\">\n\t\t\n\t</div>\n</div>\n", "innerContent": [ - "\n<div class=\"wp-block-media-text alignwide is-image-fill is-stacked-on-mobile\">\n\t<figure class=\"wp-block-media-text__media\"\n\t\tstyle=\"background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:50% 50%\">\n\t\t<img src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\"\n\t\t\talt=\"My alt text\" /></figure>\n\t<div class=\"wp-block-media-text__content\">\n\t\t", + "\n<div class=\"wp-block-media-text alignwide is-image-fill-element is-stacked-on-mobile\">\n\t<figure class=\"wp-block-media-text__media\">\n\t\t<img src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\"\n\t\t\talt=\"My alt text\" style=\"object-position:50% 50%\"/></figure>\n\t<div class=\"wp-block-media-text__content\">\n\t\t", null, "\n\t</div>\n</div>\n" ] diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.serialized.html b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.serialized.html index 40382e884f618e..b9d5e14f90277c 100644 --- a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.serialized.html +++ b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.serialized.html @@ -1,5 +1,5 @@ <!-- wp:media-text {"align":"wide","mediaType":"image","imageFill":true} --> -<div class="wp-block-media-text alignwide is-stacked-on-mobile is-image-fill"><figure class="wp-block-media-text__media" style="background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:50% 50%"><img src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" alt="My alt text"/></figure><div class="wp-block-media-text__content"><!-- wp:paragraph {"placeholder":"Content…","fontSize":"large"} --> +<div class="wp-block-media-text alignwide is-stacked-on-mobile is-image-fill-element"><figure class="wp-block-media-text__media"><img src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" alt="My alt text" style="object-position:50% 50%"/></figure><div class="wp-block-media-text__content"><!-- wp:paragraph {"placeholder":"Content…","fontSize":"large"} --> <p class="has-large-font-size">My Content</p> <!-- /wp:paragraph --></div></div> <!-- /wp:media-text --> diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.html b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.html index 47a0f0c126fa70..60e2cc7be572d4 100644 --- a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.html +++ b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.html @@ -1,9 +1,8 @@ -<!-- wp:media-text {"mediaType":"image","imageFill":true,"focalPoint":{"x":0.84,"y":0.84}} --> -<div class="wp-block-media-text alignwide is-image-fill is-stacked-on-mobile"> - <figure class="wp-block-media-text__media" - style="background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:84% 84%"> +<!-- wp:media-text {"align":"wide","mediaType":"image","imageFill":true,"focalPoint":{"x":0.84,"y":0.84}} --> +<div class="wp-block-media-text alignwide is-image-fill-element is-stacked-on-mobile"> + <figure class="wp-block-media-text__media"> <img src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" - alt="My alt text" /></figure> + alt="My alt text" style="object-position:84% 84%" /></figure> <div class="wp-block-media-text__content"> <!-- wp:paragraph {"placeholder":"Content…","fontSize":"large"} --> <p class="has-large-font-size">My Content</p> diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.json b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.json index 986e049099541f..0de71c867457ef 100644 --- a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.json +++ b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.json @@ -6,15 +6,16 @@ "align": "wide", "mediaAlt": "My alt text", "mediaPosition": "left", + "mediaUrl": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=", "mediaType": "image", "mediaWidth": 50, "isStackedOnMobile": true, - "mediaUrl": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=", "imageFill": true, "focalPoint": { "x": 0.84, "y": 0.84 - } + }, + "useFeaturedImage": false }, "innerBlocks": [ { diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.parsed.json b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.parsed.json index 175fbad27927b7..92bd57443a1c34 100644 --- a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.parsed.json +++ b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.parsed.json @@ -2,6 +2,7 @@ { "blockName": "core/media-text", "attrs": { + "align": "wide", "mediaType": "image", "imageFill": true, "focalPoint": { @@ -23,9 +24,9 @@ ] } ], - "innerHTML": "\n<div class=\"wp-block-media-text alignwide is-image-fill is-stacked-on-mobile\">\n\t<figure class=\"wp-block-media-text__media\"\n\t\tstyle=\"background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:84% 84%\">\n\t\t<img src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\"\n\t\t\talt=\"My alt text\" /></figure>\n\t<div class=\"wp-block-media-text__content\">\n\t\t\n\t</div>\n</div>\n", + "innerHTML": "\n<div class=\"wp-block-media-text alignwide is-image-fill-element is-stacked-on-mobile\">\n\t<figure class=\"wp-block-media-text__media\">\n\t\t<img src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\"\n\t\t\talt=\"My alt text\" style=\"object-position:84% 84%\" /></figure>\n\t<div class=\"wp-block-media-text__content\">\n\t\t\n\t</div>\n</div>\n", "innerContent": [ - "\n<div class=\"wp-block-media-text alignwide is-image-fill is-stacked-on-mobile\">\n\t<figure class=\"wp-block-media-text__media\"\n\t\tstyle=\"background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:84% 84%\">\n\t\t<img src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\"\n\t\t\talt=\"My alt text\" /></figure>\n\t<div class=\"wp-block-media-text__content\">\n\t\t", + "\n<div class=\"wp-block-media-text alignwide is-image-fill-element is-stacked-on-mobile\">\n\t<figure class=\"wp-block-media-text__media\">\n\t\t<img src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\"\n\t\t\talt=\"My alt text\" style=\"object-position:84% 84%\" /></figure>\n\t<div class=\"wp-block-media-text__content\">\n\t\t", null, "\n\t</div>\n</div>\n" ] diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.serialized.html b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.serialized.html index 9445d0ad259b22..4b001f4f27c8ad 100644 --- a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.serialized.html +++ b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.serialized.html @@ -1,5 +1,5 @@ <!-- wp:media-text {"align":"wide","mediaType":"image","imageFill":true,"focalPoint":{"x":0.84,"y":0.84}} --> -<div class="wp-block-media-text alignwide is-stacked-on-mobile is-image-fill"><figure class="wp-block-media-text__media" style="background-image:url(data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=);background-position:84% 84%"><img src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" alt="My alt text"/></figure><div class="wp-block-media-text__content"><!-- wp:paragraph {"placeholder":"Content…","fontSize":"large"} --> +<div class="wp-block-media-text alignwide is-stacked-on-mobile is-image-fill-element"><figure class="wp-block-media-text__media"><img src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" alt="My alt text" style="object-position:84% 84%"/></figure><div class="wp-block-media-text__content"><!-- wp:paragraph {"placeholder":"Content…","fontSize":"large"} --> <p class="has-large-font-size">My Content</p> <!-- /wp:paragraph --></div></div> <!-- /wp:media-text --> From b1143facde28b02d409f9f3dbb95ee063c1f9591 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Wed, 4 Sep 2024 22:17:14 +0800 Subject: [PATCH 0680/1908] De-duplicate block toolbar icons for patterns (#65054) Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> --- .../src/components/block-toolbar/index.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 13dfd6b33e56a6..b14ceb50590495 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -65,6 +65,7 @@ export function PrivateBlockToolbar( { shouldShowVisualToolbar, showParentSelector, isUsingBindings, + hasParentPattern, } = useSelect( ( select ) => { const { getBlockName, @@ -74,6 +75,7 @@ export function PrivateBlockToolbar( { isBlockValid, getBlockEditingMode, getBlockAttributes, + getBlockParentsByBlockName, } = select( blockEditorStore ); const selectedBlockClientIds = getSelectedBlockClientIds(); const selectedBlockClientId = selectedBlockClientIds[ 0 ]; @@ -94,6 +96,13 @@ export function PrivateBlockToolbar( { ( clientId ) => !! getBlockAttributes( clientId )?.metadata?.bindings ); + + const _hasParentPattern = selectedBlockClientIds.every( + ( clientId ) => + getBlockParentsByBlockName( clientId, 'core/block', true ) + .length > 0 + ); + return { blockClientId: selectedBlockClientId, blockClientIds: selectedBlockClientIds, @@ -113,6 +122,7 @@ export function PrivateBlockToolbar( { selectedBlockClientIds.length === 1 && _isDefaultEditingMode, isUsingBindings: _isUsingBindings, + hasParentPattern: _hasParentPattern, }; }, [] ); @@ -167,7 +177,7 @@ export function PrivateBlockToolbar( { isDefaultEditingMode && <BlockParentSelector /> } { ( shouldShowVisualToolbar || isMultiToolbar ) && ( isDefaultEditingMode || - isContentOnlyEditingMode || + ( isContentOnlyEditingMode && ! hasParentPattern ) || isSynced ) && ( <div ref={ nodeRef } From 20f7dfd8a68b0db7965f12d165f6f628b6c4b68f Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 4 Sep 2024 16:24:46 +0200 Subject: [PATCH 0681/1908] Style Book: do not use Composite store (#65047) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/edit-site/src/components/style-book/index.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 7ee8eed375f9a9..c4c2fa45d2bed7 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -48,7 +48,6 @@ const { mergeBaseAndUserConfigs } = unlock( editorPrivateApis ); const { CompositeV2: Composite, CompositeItemV2: CompositeItem, - useCompositeStoreV2: useCompositeStore, Tabs, } = unlock( componentsPrivateApis ); @@ -383,11 +382,9 @@ const StyleBookBody = ( { const Examples = memo( ( { className, examples, category, label, isSelected, onSelect } ) => { - const compositeStore = useCompositeStore( { orientation: 'vertical' } ); - return ( <Composite - store={ compositeStore } + orientation="vertical" className={ className } aria-label={ label } role="grid" From 633e298d381f227cddb91e2730742b3db5166252 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Wed, 4 Sep 2024 20:24:35 +0530 Subject: [PATCH 0682/1908] Comment Reply Link: Add border support (#64271) * Comment Reply Link: Add Border Support * Hide Spacing & Border Support Default Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../src/comment-reply-link/block.json | 15 +++++++++++++-- .../src/comment-reply-link/style.scss | 4 ++++ packages/block-library/src/style.scss | 1 + 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 packages/block-library/src/comment-reply-link/style.scss diff --git a/packages/block-library/src/comment-reply-link/block.json b/packages/block-library/src/comment-reply-link/block.json index c10129412145c8..68aa93c3c1526a 100644 --- a/packages/block-library/src/comment-reply-link/block.json +++ b/packages/block-library/src/comment-reply-link/block.json @@ -25,7 +25,11 @@ }, "spacing": { "margin": true, - "padding": true + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } }, "typography": { "fontSize": true, @@ -40,6 +44,13 @@ "fontSize": true } }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + }, "html": false - } + }, + "style": "wp-block-comment-reply-link" } diff --git a/packages/block-library/src/comment-reply-link/style.scss b/packages/block-library/src/comment-reply-link/style.scss new file mode 100644 index 00000000000000..7eca6cee1aa979 --- /dev/null +++ b/packages/block-library/src/comment-reply-link/style.scss @@ -0,0 +1,4 @@ +.wp-block-comment-reply-link { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; +} diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index 8549b80ae89de2..a8819c2084dc2e 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -14,6 +14,7 @@ @import "./comment-content/style.scss"; @import "./comment-author-name/style.scss"; @import "./comment-edit-link/style.scss"; +@import "./comment-reply-link/style.scss"; @import "./cover/style.scss"; @import "./details/style.scss"; @import "./embed/style.scss"; From 626c3fa98d7bcbdbc425d9b968055619640bbdec Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Wed, 4 Sep 2024 18:00:20 +0300 Subject: [PATCH 0683/1908] Inserter: Fix subtle media insertion error (#65057) * Inserter: Fix subtle media insertion error * Remove unnecessary ref optional chaining Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> * Reformat --------- Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-editor/src/components/inserter/menu.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index b884ea97588459..faf2c20514f67a 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -101,12 +101,12 @@ function InserterMenu( window.requestAnimationFrame( () => { if ( ! shouldFocusBlock && - ! blockTypesTabRef?.current.contains( + ! blockTypesTabRef.current?.contains( ref.current.ownerDocument.activeElement ) ) { // There has been a focus loss, so focus the first button in the block types tab - blockTypesTabRef?.current.querySelector( 'button' ).focus(); + blockTypesTabRef.current?.querySelector( 'button' ).focus(); } } ); }, From abf72c95b1da1b8f6709858bb750e1d56782c27d Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 4 Sep 2024 17:13:25 +0200 Subject: [PATCH 0684/1908] Composite: add context-forwarding with SlotFill example (#65051) * Composite: add context-forwarding with SlotFill example * Add custom code snippet * CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/composite/stories/index.story.tsx | 135 +++++++++++++++++- 2 files changed, 135 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 33677f10b58fcb..aeb1de80a73c55 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -74,6 +74,7 @@ - `DropdownMenu` v2: add `GroupLabel` subcomponent ([#64854](https://github.com/WordPress/gutenberg/pull/64854)). - `DropdownMenuV2`: update animation ([#64868](https://github.com/WordPress/gutenberg/pull/64868)). - `Composite` V2: fix Storybook docgen ([#64682](https://github.com/WordPress/gutenberg/pull/64682)). +- `Composite` V2: add "With Slot Fill" example ([#65051](https://github.com/WordPress/gutenberg/pull/65051)). - `Composite` V2: accept store props on top-level component ([#64832](https://github.com/WordPress/gutenberg/pull/64832)). ## 28.6.0 (2024-08-21) diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx index 80e3d85e3ce296..2fdec079255490 100644 --- a/packages/components/src/composite/stories/index.story.tsx +++ b/packages/components/src/composite/stories/index.story.tsx @@ -1,16 +1,18 @@ /** * External dependencies */ -import type { Meta, StoryFn } from '@storybook/react'; +import type { Meta, StoryFn, StoryContext } from '@storybook/react'; /** * WordPress dependencies */ import { isRTL } from '@wordpress/i18n'; +import { useContext, useMemo } from '@wordpress/element'; /** * Internal dependencies */ +import { createSlotFill, Provider as SlotFillProvider } from '../../slot-fill'; import { Composite } from '..'; import { useCompositeStore } from '../store'; import { UseCompositeStorePlaceholder, transform } from './utils'; @@ -204,3 +206,134 @@ Typeahead.parameters = { }, }, }; + +const ExampleSlotFill = createSlotFill( 'Example' ); + +const Slot = () => { + const compositeContext = useContext( Composite.Context ); + + // Forward the Slot's composite context to the Fill via fillProps, so that + // Composite components rendered inside the Fill can work as expected. + const fillProps = useMemo( + () => ( { + forwardedContext: [ + [ Composite.Context.Provider, { value: compositeContext } ], + ], + } ), + [ compositeContext ] + ); + + return ( + <ExampleSlotFill.Slot + fillProps={ fillProps } + bubblesVirtually + style={ { display: 'contents' } } + /> + ); +}; + +type ForwardedContextTuple< P = {} > = [ + React.ComponentType< React.PropsWithChildren< P > >, + P, +]; + +const Fill = ( { children }: { children: React.ReactNode } ) => { + const innerMarkup = <>{ children }</>; + + return ( + <ExampleSlotFill.Fill> + { ( fillProps: { forwardedContext?: ForwardedContextTuple[] } ) => { + const { forwardedContext = [] } = fillProps; + + // Render all context providers forwarded by the Slot via fillProps. + return forwardedContext.reduce( + ( inner: JSX.Element, [ Provider, props ] ) => ( + <Provider { ...props }>{ inner }</Provider> + ), + innerMarkup + ); + } } + </ExampleSlotFill.Fill> + ); +}; + +export const WithSlotFill: StoryFn< typeof UseCompositeStorePlaceholder > = ( + props +) => { + return ( + <SlotFillProvider> + <Composite { ...props }> + <Composite.Item>Item one (direct child)</Composite.Item> + <Slot /> + <Composite.Item>Item four (direct child)</Composite.Item> + </Composite> + + <Fill> + <Composite.Item>Item two (from slot fill)</Composite.Item> + <Composite.Item>Item three (from slot fill)</Composite.Item> + </Fill> + </SlotFillProvider> + ); +}; +WithSlotFill.args = { + ...Default.args, +}; +WithSlotFill.parameters = { + docs: { + description: { + story: 'When rendering Composite components across a SlotFill, the Composite.Context should be manually forwarded from the Slot to the Fill component.', + }, + source: { + transform: ( code: string, storyContext: StoryContext ) => { + return `const ExampleSlotFill = createSlotFill( 'Example' ); + +const Slot = () => { + const compositeContext = useContext( Composite.Context ); + + // Forward the Slot's composite context to the Fill via fillProps, so that + // Composite components rendered inside the Fill can work as expected. + const fillProps = useMemo( + () => ( { + forwardedContext: [ + [ Composite.Context.Provider, { value: compositeContext } ], + ], + } ), + [ compositeContext ] + ); + + return ( + <ExampleSlotFill.Slot + fillProps={ fillProps } + bubblesVirtually + style={ { display: 'contents' } } + /> + ); +}; + +const Fill = ( { children } ) => { + const innerMarkup = <>{ children }</>; + + return ( + <ExampleSlotFill.Fill> + { ( fillProps ) => { + const { forwardedContext = [] } = fillProps; + + // Render all context providers forwarded by the Slot via fillProps. + return forwardedContext.reduce( + ( inner, [ Provider, props ] ) => ( + <Provider { ...props }>{ inner }</Provider> + ), + innerMarkup + ); + } } + </ExampleSlotFill.Fill> + ); +}; + +// In a separate component: + +${ transform( code, storyContext ) }`; + }, + }, + }, +}; From fae4d1b9fb25e76209ea6e3b220dc57391757394 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Wed, 4 Sep 2024 19:46:08 +0100 Subject: [PATCH 0685/1908] Double click block to exit zoom out mode (#64573) Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> --- .../src/components/block-list/block.js | 8 +++- .../block-list/use-block-props/index.js | 3 ++ .../use-block-props/use-zoom-out-mode-exit.js | 44 +++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index bdf33c944deb13..deda4e3b9d0897 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -646,6 +646,8 @@ function BlockListBlockProvider( props ) { blocksWithSameName.length && blocksWithSameName[ 0 ] !== clientId; + const editorMode = __unstableGetEditorMode(); + return { ...previewContext, mode: getBlockMode( clientId ), @@ -672,6 +674,7 @@ function BlockListBlockProvider( props ) { ) && hasSelectedInnerBlock( clientId ), blockApiVersion: blockType?.apiVersion || 1, blockTitle: match?.title || blockType?.title, + editorMode, isSubtreeDisabled: blockEditingMode === 'disabled' && isBlockSubtreeDisabled( clientId ), @@ -680,8 +683,7 @@ function BlockListBlockProvider( props ) { ! isDragging(), initialPosition: _isSelected && - ( __unstableGetEditorMode() === 'edit' || - __unstableGetEditorMode() === 'zoom-out' ) // Don't recalculate the initialPosition when toggling in/out of zoom-out mode + ( editorMode === 'edit' || editorMode === 'zoom-out' ) // Don't recalculate the initialPosition when toggling in/out of zoom-out mode ? getSelectedBlocksInitialCaretPosition() : undefined, isHighlighted: isBlockHighlighted( clientId ), @@ -728,6 +730,7 @@ function BlockListBlockProvider( props ) { themeSupportsLayout, isTemporarilyEditingAsBlocks, blockEditingMode, + editorMode, mayDisplayControls, mayDisplayParentControls, index, @@ -782,6 +785,7 @@ function BlockListBlockProvider( props ) { hasOverlay, initialPosition, blockEditingMode, + editorMode, isHighlighted, isMultiSelected, isPartiallySelected, diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index 15fb83139237cc..c3a279a618b5da 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -26,6 +26,7 @@ import { import { useFocusHandler } from './use-focus-handler'; import { useEventHandlers } from './use-selected-block-event-handlers'; import { useNavModeExit } from './use-nav-mode-exit'; +import { useZoomOutModeExit } from './use-zoom-out-mode-exit'; import { useBlockRefProvider } from './use-block-refs'; import { useIntersectionObserver } from './use-intersection-observer'; import { useScrollIntoView } from './use-scroll-into-view'; @@ -85,6 +86,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { name, blockApiVersion, blockTitle, + editorMode, isSelected, isSubtreeDisabled, hasOverlay, @@ -115,6 +117,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { useFocusHandler( clientId ), useEventHandlers( { clientId, isSelected } ), useNavModeExit( clientId ), + useZoomOutModeExit( { editorMode } ), useIsHovered( { clientId } ), useIntersectionObserver(), useMovingAnimation( { triggerAnimationOnChange: index, clientId } ), diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js b/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js new file mode 100644 index 00000000000000..bb6edd066f06f1 --- /dev/null +++ b/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js @@ -0,0 +1,44 @@ +/** + * WordPress dependencies + */ +import { useDispatch } from '@wordpress/data'; +import { useRefEffect } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../../../store'; +import { unlock } from '../../../lock-unlock'; + +/** + * Allows Zoom Out mode to be exited by double clicking in the selected block. + * + * @param {string} clientId Block client ID. + */ +export function useZoomOutModeExit( { editorMode } ) { + const { __unstableSetEditorMode } = unlock( + useDispatch( blockEditorStore ) + ); + + return useRefEffect( + ( node ) => { + if ( editorMode !== 'zoom-out' ) { + return; + } + + function onDoubleClick( event ) { + if ( ! event.defaultPrevented ) { + event.preventDefault(); + __unstableSetEditorMode( 'edit' ); + } + } + + node.addEventListener( 'dblclick', onDoubleClick ); + + return () => { + node.removeEventListener( 'dblclick', onDoubleClick ); + }; + }, + [ editorMode, __unstableSetEditorMode ] + ); +} From b4676adf751b644ebeb154ef2f7f7372da45585c Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 4 Sep 2024 23:11:35 +0200 Subject: [PATCH 0686/1908] Block Bindings: Allow only admin users to create and modify bindings by default (#64570) * Remove block bindings UI experiment * Use block settings preferences * Add "bindings" group * Make changes to the helper text * Fix tests * Fix remaining test * Import `useSelect` * Change comment * Hide controls in templates * Adapt preference phrasing and capabilities * Change name in tests * Remove preference * Add `canUpdateBlockBindings` in Gutenberg * Update comment * Add backport changelog Unlinked contributors: jarekmorawski. Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: bacoords <bacoords@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- backport-changelog/6.7/7258.md | 3 ++ lib/compat/wordpress-6.7/block-bindings.php | 15 ++++++ lib/experimental/editor-settings.php | 3 -- lib/experiments-page.php | 12 ----- .../src/components/block-inspector/index.js | 1 + .../inspector-controls-tabs/settings-tab.js | 1 + .../use-inspector-controls-tabs.js | 7 ++- .../components/inspector-controls/groups.js | 2 + .../block-editor/src/hooks/block-bindings.js | 27 +++++++--- .../provider/use-block-editor-settings.js | 1 + .../editor/various/block-bindings.spec.js | 54 +++---------------- 11 files changed, 53 insertions(+), 73 deletions(-) create mode 100644 backport-changelog/6.7/7258.md diff --git a/backport-changelog/6.7/7258.md b/backport-changelog/6.7/7258.md new file mode 100644 index 00000000000000..6714b13b70b8d2 --- /dev/null +++ b/backport-changelog/6.7/7258.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7258 + +* https://github.com/WordPress/gutenberg/pull/64570 \ No newline at end of file diff --git a/lib/compat/wordpress-6.7/block-bindings.php b/lib/compat/wordpress-6.7/block-bindings.php index 398b53b340673b..9e82c1843f35a0 100644 --- a/lib/compat/wordpress-6.7/block-bindings.php +++ b/lib/compat/wordpress-6.7/block-bindings.php @@ -38,3 +38,18 @@ function gutenberg_add_server_block_bindings_sources_to_editor_settings( $editor } add_filter( 'block_editor_settings_all', 'gutenberg_add_server_block_bindings_sources_to_editor_settings', 10 ); + +/** + * Initialize `canUpdateBlockBindings` editor setting if it doesn't exist. By default, it is `true` only for admin users. + * + * @param array $settings The block editor settings from the `block_editor_settings_all` filter. + * @return array The editor settings including `canUpdateBlockBindings`. + */ +function gutenberg_add_can_update_block_bindings_editor_setting( $editor_settings ) { + if ( empty( $editor_settings['canUpdateBlockBindings'] ) ) { + $editor_settings['canUpdateBlockBindings'] = current_user_can( 'manage_options' ); + } + return $editor_settings; +} + +add_filter( 'block_editor_settings_all', 'gutenberg_add_can_update_block_bindings_editor_setting', 10 ); diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index f7cedd98239a36..919be2e6e34a45 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -31,9 +31,6 @@ function gutenberg_enable_experiments() { if ( $gutenberg_experiments && array_key_exists( 'gutenberg-quick-edit-dataviews', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalQuickEditDataViews = true', 'before' ); } - if ( $gutenberg_experiments && array_key_exists( 'gutenberg-block-bindings-ui', $gutenberg_experiments ) ) { - wp_add_inline_script( 'wp-block-editor', 'window.__experimentalBlockBindingsUI = true', 'before' ); - } if ( $gutenberg_experiments && array_key_exists( 'gutenberg-media-processing', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalMediaProcessing = true', 'before' ); } diff --git a/lib/experiments-page.php b/lib/experiments-page.php index 1b7df237176a2c..5acd5f0f192364 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -163,18 +163,6 @@ function gutenberg_initialize_experiments_settings() { ) ); - add_settings_field( - 'gutenberg-block-bindings-ui', - __( 'UI to create block bindings', 'gutenberg' ), - 'gutenberg_display_experiment_field', - 'gutenberg-experiments', - 'gutenberg_experiments_section', - array( - 'label' => __( 'Add UI to create and update block bindings in block inspector controls.', 'gutenberg' ), - 'id' => 'gutenberg-block-bindings-ui', - ) - ); - add_settings_field( 'gutenberg-media-processing', __( 'Client-side media processing', 'gutenberg' ), diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index 75b5239f47d6cc..1986ad8730c121 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -322,6 +322,7 @@ const BlockInspectorSingleBlock = ( { clientId, blockName } ) => { /> <InspectorControls.Slot group="styles" /> <PositionControls /> + <InspectorControls.Slot group="bindings" /> <div> <AdvancedControls /> </div> diff --git a/packages/block-editor/src/components/inspector-controls-tabs/settings-tab.js b/packages/block-editor/src/components/inspector-controls-tabs/settings-tab.js index ec34035b754a91..ea2f45114bf9cf 100644 --- a/packages/block-editor/src/components/inspector-controls-tabs/settings-tab.js +++ b/packages/block-editor/src/components/inspector-controls-tabs/settings-tab.js @@ -9,6 +9,7 @@ const SettingsTab = ( { showAdvancedControls = false } ) => ( <> <InspectorControls.Slot /> <PositionControls /> + <InspectorControls.Slot group="bindings" /> { showAdvancedControls && ( <div> <AdvancedControls /> diff --git a/packages/block-editor/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js b/packages/block-editor/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js index ff68be82a829f1..6a80d47f024816 100644 --- a/packages/block-editor/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js +++ b/packages/block-editor/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js @@ -32,6 +32,7 @@ function getShowTabs( blockName, tabSettings = {} ) { export default function useInspectorControlsTabs( blockName ) { const tabs = []; const { + bindings: bindingsGroup, border: borderGroup, color: colorGroup, default: defaultGroup, @@ -64,8 +65,10 @@ export default function useInspectorControlsTabs( blockName ) { // (i.e. both list view and styles), check only the default and position // InspectorControls slots. If we have multiple tabs, we'll need to check // the advanced controls slot as well to ensure they are rendered. - const advancedFills = - useSlotFills( InspectorAdvancedControls.slotName ) || []; + const advancedFills = [ + ...( useSlotFills( InspectorAdvancedControls.slotName ) || [] ), + ...( useSlotFills( bindingsGroup.Slot.__unstableName ) || [] ), + ]; const settingsFills = [ ...( useSlotFills( defaultGroup.Slot.__unstableName ) || [] ), diff --git a/packages/block-editor/src/components/inspector-controls/groups.js b/packages/block-editor/src/components/inspector-controls/groups.js index 9ca1a72b9918a6..34ec49a5e1cb41 100644 --- a/packages/block-editor/src/components/inspector-controls/groups.js +++ b/packages/block-editor/src/components/inspector-controls/groups.js @@ -5,6 +5,7 @@ import { createSlotFill } from '@wordpress/components'; const InspectorControlsDefault = createSlotFill( 'InspectorControls' ); const InspectorControlsAdvanced = createSlotFill( 'InspectorAdvancedControls' ); +const InspectorControlsBindings = createSlotFill( 'InspectorControlsBindings' ); const InspectorControlsBackground = createSlotFill( 'InspectorControlsBackground' ); @@ -26,6 +27,7 @@ const groups = { default: InspectorControlsDefault, advanced: InspectorControlsAdvanced, background: InspectorControlsBackground, + bindings: InspectorControlsBindings, border: InspectorControlsBorder, color: InspectorControlsColor, dimensions: InspectorControlsDimensions, diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index c1422acaac0e5a..3b59de2238b968 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -12,7 +12,7 @@ import { __experimentalVStack as VStack, privateApis as componentsPrivateApis, } from '@wordpress/components'; -import { useRegistry } from '@wordpress/data'; +import { useRegistry, useSelect } from '@wordpress/data'; import { useContext, Fragment } from '@wordpress/element'; import { useViewportMatch } from '@wordpress/compose'; @@ -27,6 +27,7 @@ import { unlock } from '../lock-unlock'; import InspectorControls from '../components/inspector-controls'; import BlockContext from '../components/block-context'; import { useBlockBindingsUtils } from '../utils/block-bindings'; +import { store as blockEditorStore } from '../store'; const { DropdownMenuV2 } = unlock( componentsPrivateApis ); @@ -196,6 +197,13 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { } } ); + const { canUpdateBlockBindings } = useSelect( ( select ) => { + return { + canUpdateBlockBindings: + select( blockEditorStore ).getSettings().canUpdateBlockBindings, + }; + }, [] ); + if ( ! bindableAttributes || bindableAttributes.length === 0 ) { return null; } @@ -231,17 +239,16 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { } } ); - // Lock the UI when the experiment is not enabled or there are no fields to connect to. + // Lock the UI when the user can't update bindings or there are no fields to connect to. const readOnly = - ! window.__experimentalBlockBindingsUI || - ! Object.keys( fieldsList ).length; + ! canUpdateBlockBindings || ! Object.keys( fieldsList ).length; if ( readOnly && Object.keys( filteredBindings ).length === 0 ) { return null; } return ( - <InspectorControls> + <InspectorControls group="bindings"> <ToolsPanel label={ __( 'Attributes' ) } resetAll={ () => { @@ -263,9 +270,13 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { /> ) } </ItemGroup> - <Text variant="muted"> - { __( 'Attributes connected to various sources.' ) } - </Text> + <ItemGroup> + <Text variant="muted"> + { __( + 'Attributes connected to custom fields or other dynamic data.' + ) } + </Text> + </ItemGroup> </ToolsPanel> </InspectorControls> ); diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 69e544be99d0ee..868ff08b3d0709 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -47,6 +47,7 @@ const BLOCK_EDITOR_SETTINGS = [ 'allowedMimeTypes', 'bodyPlaceholder', 'canLockBlocks', + 'canUpdateBlockBindings', 'capabilities', 'clearBlockSelection', 'codeEditingEnabled', diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index 3fa17bdf6163a8..2799315a10b220 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -1441,20 +1441,10 @@ test.describe( 'Block bindings', () => { editor, page, } ) => { - // Activate the block bindings UI experiment. - await page.evaluate( () => { - window.__experimentalBlockBindingsUI = true; - } ); - await editor.insertBlock( { name: 'core/paragraph', } ); - await page - .getByRole( 'tabpanel', { - name: 'Settings', - } ) - .getByLabel( 'Attributes options' ) - .click(); + await page.getByLabel( 'Attributes options' ).click(); const contentAttribute = page.getByRole( 'menuitemcheckbox', { name: 'Show content', } ); @@ -1464,11 +1454,6 @@ test.describe( 'Block bindings', () => { editor, page, } ) => { - // Activate the block bindings UI experiment. - await page.evaluate( () => { - window.__experimentalBlockBindingsUI = true; - } ); - await editor.insertBlock( { name: 'core/paragraph', attributes: { @@ -1483,12 +1468,7 @@ test.describe( 'Block bindings', () => { }, }, } ); - await page - .getByRole( 'tabpanel', { - name: 'Settings', - } ) - .getByRole( 'button', { name: 'content' } ) - .click(); + await page.getByRole( 'button', { name: 'content' } ).click(); await page .getByRole( 'menuitemradio' ) @@ -1586,20 +1566,10 @@ test.describe( 'Block bindings', () => { editor, page, } ) => { - // Activate the block bindings UI experiment. - await page.evaluate( () => { - window.__experimentalBlockBindingsUI = true; - } ); - await editor.insertBlock( { name: 'core/heading', } ); - await page - .getByRole( 'tabpanel', { - name: 'Settings', - } ) - .getByLabel( 'Attributes options' ) - .click(); + await page.getByLabel( 'Attributes options' ).click(); const contentAttribute = page.getByRole( 'menuitemcheckbox', { name: 'Show content', } ); @@ -1786,11 +1756,6 @@ test.describe( 'Block bindings', () => { editor, page, } ) => { - // Activate the block bindings UI experiment. - await page.evaluate( () => { - window.__experimentalBlockBindingsUI = true; - } ); - await editor.insertBlock( { name: 'core/buttons', innerBlocks: [ @@ -2121,11 +2086,6 @@ test.describe( 'Block bindings', () => { editor, page, } ) => { - // Activate the block bindings UI experiment. - await page.evaluate( () => { - window.__experimentalBlockBindingsUI = true; - } ); - await editor.insertBlock( { name: 'core/image', } ); @@ -2414,11 +2374,9 @@ test.describe( 'Block bindings', () => { }, } ); - const bindingsPanel = page - .getByRole( 'tabpanel', { - name: 'Settings', - } ) - .locator( '.block-editor-bindings__panel' ); + const bindingsPanel = page.locator( + '.block-editor-bindings__panel' + ); await expect( bindingsPanel ).toContainText( 'Server Source' ); } ); } ); From 4ba79a23f566d36dcc5d05598181ea79e29ccde4 Mon Sep 17 00:00:00 2001 From: Imran Hossain <imranh920@gmail.com> Date: Thu, 5 Sep 2024 05:47:13 +0600 Subject: [PATCH 0687/1908] Fix site editor broken when fontWeight is not defined or is an integer in theme.json or theme styles (#64953) * Handle if nearest value input is not string for fontweight * handle string and undefined fontweights when getting in site editor * Add additional check for fontStyle keys * Test getting styles and fonts for numeric and undefined fontweight * Test numeric font style getting in typography utils * Add test for nearest value when fontWeight undefined Co-authored-by: Imran92 <imranh920@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- .../global-styles/test/typography-utils.js | 55 +++++++ .../global-styles/typography-utils.js | 6 +- .../src/utils/get-font-styles-and-weights.js | 16 +- .../utils/test/get-font-styles-and-weights.js | 148 ++++++++++++++++++ 4 files changed, 220 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/test/typography-utils.js b/packages/block-editor/src/components/global-styles/test/typography-utils.js index 155eaa0fe063ee..b094d1e827783e 100644 --- a/packages/block-editor/src/components/global-styles/test/typography-utils.js +++ b/packages/block-editor/src/components/global-styles/test/typography-utils.js @@ -1291,6 +1291,61 @@ describe( 'typography utils', () => { nearestFontWeight: '400', }, }, + { + message: + 'should return nearest fontStyle and fontWeight for normal/400 when fontFamilyFaces contain numerical fontWeight value', + fontFamilyFaces: [ + { + fontFamily: 'IBM Plex Mono', + fontStyle: 'normal', + fontWeight: 400, + src: [ + 'file:./assets/fonts/ibm-plex-mono/IBMPlexMono-Regular.woff2', + ], + }, + { + fontFamily: 'IBM Plex Mono', + fontStyle: 'italic', + fontWeight: '400', + src: [ + 'file:./assets/fonts/ibm-plex-mono/IBMPlexMono-Italic.woff2', + ], + }, + { + fontFamily: 'IBM Plex Mono', + fontStyle: 'normal', + fontWeight: '700', + src: [ + 'file:./assets/fonts/ibm-plex-mono/IBMPlexMono-Bold.woff2', + ], + }, + ], + fontStyle: 'normal', + fontWeight: '400', + expected: { + nearestFontStyle: 'normal', + nearestFontWeight: '400', + }, + }, + { + message: + 'should return nearest fontStyle and fontWeight for normal/400 when fontFamilyFaces contain undefined fontWeight value', + fontFamilyFaces: [ + { + fontFamily: 'IBM Plex Mono', + fontStyle: 'normal', + src: [ + 'file:./assets/fonts/ibm-plex-mono/IBMPlexMono-Regular.woff2', + ], + }, + ], + fontStyle: 'normal', + fontWeight: '400', + expected: { + nearestFontStyle: 'normal', + nearestFontWeight: '700', + }, + }, ].forEach( ( { message, diff --git a/packages/block-editor/src/components/global-styles/typography-utils.js b/packages/block-editor/src/components/global-styles/typography-utils.js index 32fbd50db2dbff..4b7c90ae4f222c 100644 --- a/packages/block-editor/src/components/global-styles/typography-utils.js +++ b/packages/block-editor/src/components/global-styles/typography-utils.js @@ -174,6 +174,10 @@ export function findNearestFontWeight( availableFontWeights, newFontWeightValue ) { + newFontWeightValue = + 'number' === typeof newFontWeightValue + ? newFontWeightValue.toString() + : newFontWeightValue; if ( ! newFontWeightValue || typeof newFontWeightValue !== 'string' ) { return ''; } @@ -260,7 +264,7 @@ export function findNearestStyleAndWeight( ( { value: fs } ) => fs === fontStyle ); const hasFontWeight = fontWeights?.some( - ( { value: fw } ) => fw === fontWeight + ( { value: fw } ) => fw?.toString() === fontWeight?.toString() ); if ( ! hasFontStyle ) { diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js index 88b40a5aacfeb5..dcb56fc86b2673 100644 --- a/packages/block-editor/src/utils/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -79,7 +79,10 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { fontFamilyFaces?.forEach( ( face ) => { // Check for variable font by looking for a space in the font weight value. e.g. "100 900" - if ( /\s/.test( face.fontWeight.trim() ) ) { + if ( + 'string' === typeof face.fontWeight && + /\s/.test( face.fontWeight.trim() ) + ) { isVariableFont = true; // Find font weight start and end values. @@ -105,11 +108,15 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { } // Format font style and weight values. - const fontWeight = formatFontWeight( face.fontWeight ); + const fontWeight = formatFontWeight( + 'number' === typeof face.fontWeight + ? face.fontWeight.toString() + : face.fontWeight + ); const fontStyle = formatFontStyle( face.fontStyle ); // Create font style and font weight lists without duplicates. - if ( fontStyle ) { + if ( fontStyle && Object.keys( fontStyle ).length ) { if ( ! fontStyles.some( ( style ) => style.value === fontStyle.value @@ -118,7 +125,8 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { fontStyles.push( fontStyle ); } } - if ( fontWeight ) { + + if ( fontWeight && Object.keys( fontWeight ).length ) { if ( ! fontWeights.some( ( weight ) => weight.value === fontWeight.value diff --git a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js index ffc1a635aa1fb1..7c50409bae1acc 100644 --- a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js @@ -343,6 +343,17 @@ describe( 'getFontStylesAndWeights', () => { fontWeight: '400', src: 'http://www.wordpress.org/wp-content/uploads/fonts/N0b52SlTPu5rIkWIZjVKKtYtfxYqZ4RJBFzFfYUjkSDdlqZgy7LYxnL31AHfAAy5.woff2', }, + { + fontFamily: 'Piazzolla', + fontStyle: 'normal', + fontWeight: 600, + src: 'http://www.wordpress.org/wp-content/uploads/fonts/N0b52SlTPu5rIkWIZjVKKtYtfxYqZ4RJBFzFfYUjkSDdlqZgy7JxwXL31AHfAAy5.woff2', + }, + { + fontFamily: 'Piazzolla', + fontStyle: 'normal', + src: 'http://www.wordpress.org/wp-content/uploads/fonts/N0b52SlTPu5rIkWIZjVKKtYtfxYqZ4RJBFzFfYUjkSDdlqZgy7JxwXL31AHfAAy5.woff2', + }, { fontFamily: 'Piazzolla', fontStyle: 'normal', @@ -378,6 +389,10 @@ describe( 'getFontStylesAndWeights', () => { name: 'Regular', value: '400', }, + { + name: 'Semi Bold', + value: '600', + }, { name: 'Black', value: '900', @@ -396,6 +411,14 @@ describe( 'getFontStylesAndWeights', () => { fontWeight: '400', }, }, + { + key: 'normal-600', + name: 'Semi Bold', + style: { + fontStyle: 'normal', + fontWeight: '600', + }, + }, { key: 'normal-900', name: 'Black', @@ -420,6 +443,14 @@ describe( 'getFontStylesAndWeights', () => { fontWeight: '400', }, }, + { + key: 'italic-600', + name: 'Semi Bold Italic', + style: { + fontStyle: 'italic', + fontWeight: '600', + }, + }, { key: 'italic-900', name: 'Black Italic', @@ -510,4 +541,121 @@ describe( 'getFontStylesAndWeights', () => { isVariableFont: false, } ); } ); + + it( 'should return available styles and weights for a font without fontWeight', () => { + const fontFamilyFaces = [ + { + fontFamily: 'AR One Sans', + fontStyle: 'normal', + src: 'http://www.wordpress.org/wp-content/uploads/fonts/AROneSans-VariableFont_ARRRwght.ttf', + }, + ]; + expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( { + fontStyles: [ + { + name: 'Regular', + value: 'normal', + }, + { + name: 'Italic', + value: 'italic', + }, + ], + fontWeights: [ + { + name: 'Bold', + value: '700', + }, + ], + combinedStyleAndWeightOptions: [ + { + key: 'normal-700', + name: 'Bold', + style: { + fontStyle: 'normal', + fontWeight: '700', + }, + }, + { + key: 'italic-700', + name: 'Bold Italic', + style: { + fontStyle: 'italic', + fontWeight: '700', + }, + }, + ], + isSystemFont: false, + isVariableFont: false, + } ); + } ); + + it( 'should return available styles and weights for a font with numeric fontWeight', () => { + const fontFamilyFaces = [ + { + fontFamily: 'AR One Sans', + fontStyle: 'normal', + fontWeight: 400, + src: 'http://www.wordpress.org/wp-content/uploads/fonts/AROneSans-VariableFont_ARRRwght.ttf', + }, + ]; + expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( { + fontStyles: [ + { + name: 'Regular', + value: 'normal', + }, + { + name: 'Italic', + value: 'italic', + }, + ], + fontWeights: [ + { + name: 'Regular', + value: '400', + }, + { + name: 'Bold', + value: '700', + }, + ], + combinedStyleAndWeightOptions: [ + { + key: 'normal-400', + name: 'Regular', + style: { + fontStyle: 'normal', + fontWeight: '400', + }, + }, + { + key: 'normal-700', + name: 'Bold', + style: { + fontStyle: 'normal', + fontWeight: '700', + }, + }, + { + key: 'italic-400', + name: 'Regular Italic', + style: { + fontStyle: 'italic', + fontWeight: '400', + }, + }, + { + key: 'italic-700', + name: 'Bold Italic', + style: { + fontStyle: 'italic', + fontWeight: '700', + }, + }, + ], + isSystemFont: false, + isVariableFont: false, + } ); + } ); } ); From 179cffad3e7719c5ac0396d0009327253db16d17 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Thu, 5 Sep 2024 10:16:07 +1000 Subject: [PATCH 0688/1908] Fix editor error in Safari due to availability of checkVisibility method (#65069) * Fix editor error in Safari due to availability of checkVisibility method * Add fallback approach if checkVisibility is not available * Be specific about which Safari version we're talking about Co-authored-by: Ramon <ramonjd@users.noreply.github.com> --------- Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-editor/src/utils/dom.js | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/utils/dom.js b/packages/block-editor/src/utils/dom.js index bfdce60b9f0060..9c2e813ef742b6 100644 --- a/packages/block-editor/src/utils/dom.js +++ b/packages/block-editor/src/utils/dom.js @@ -96,11 +96,26 @@ function isElementVisible( element ) { return false; } - return element.checkVisibility( { - opacityProperty: true, - contentVisibilityAuto: true, - visibilityProperty: true, - } ); + // Older browsers, e.g. Safari < 17.4 may not support the `checkVisibility` method. + if ( element.checkVisibility ) { + return element.checkVisibility?.( { + opacityProperty: true, + contentVisibilityAuto: true, + visibilityProperty: true, + } ); + } + + const style = viewport.getComputedStyle( element ); + + if ( + style.display === 'none' || + style.visibility === 'hidden' || + style.opacity === '0' + ) { + return false; + } + + return true; } /** From c7acc06a16893f3e3200cff20dae2dc09cdd7e99 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 5 Sep 2024 02:38:53 +0000 Subject: [PATCH 0689/1908] Bump plugin version to 19.2.0-rc.1 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index f0e2f94ef57fd6..117f4168524d8a 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.1.0 + * Version: 19.2.0-rc.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index e9ae02a0c4768b..10ebadc05aa36b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.1.0", + "version": "19.2.0-rc.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.1.0", + "version": "19.2.0-rc.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 32f114cb9afa44..a67b376f3dbdc1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.1.0", + "version": "19.2.0-rc.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 7a711b09c27748c7545fe56677e10479ffe5b96d Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 5 Sep 2024 03:38:19 +0000 Subject: [PATCH 0690/1908] Update changelog files --- packages/a11y/CHANGELOG.md | 2 ++ packages/a11y/package.json | 2 +- packages/annotations/CHANGELOG.md | 2 ++ packages/annotations/package.json | 2 +- packages/api-fetch/CHANGELOG.md | 2 ++ packages/api-fetch/package.json | 2 +- packages/autop/CHANGELOG.md | 2 ++ packages/autop/package.json | 2 +- packages/babel-plugin-import-jsx-pragma/CHANGELOG.md | 2 ++ packages/babel-plugin-import-jsx-pragma/package.json | 2 +- packages/babel-plugin-makepot/CHANGELOG.md | 2 ++ packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/CHANGELOG.md | 2 ++ packages/babel-preset-default/package.json | 2 +- packages/base-styles/CHANGELOG.md | 2 ++ packages/base-styles/package.json | 2 +- packages/blob/CHANGELOG.md | 2 ++ packages/blob/package.json | 2 +- packages/block-directory/CHANGELOG.md | 2 ++ packages/block-directory/package.json | 2 +- packages/block-editor/CHANGELOG.md | 2 ++ packages/block-editor/package.json | 2 +- packages/block-library/CHANGELOG.md | 2 ++ packages/block-library/package.json | 2 +- packages/block-serialization-default-parser/CHANGELOG.md | 2 ++ packages/block-serialization-default-parser/package.json | 2 +- packages/block-serialization-spec-parser/CHANGELOG.md | 2 ++ packages/block-serialization-spec-parser/package.json | 2 +- packages/blocks/CHANGELOG.md | 2 ++ packages/blocks/package.json | 2 +- packages/browserslist-config/CHANGELOG.md | 2 ++ packages/browserslist-config/package.json | 2 +- packages/commands/CHANGELOG.md | 2 ++ packages/commands/package.json | 2 +- packages/components/CHANGELOG.md | 2 ++ packages/components/package.json | 2 +- packages/compose/CHANGELOG.md | 2 ++ packages/compose/package.json | 2 +- packages/core-commands/CHANGELOG.md | 2 ++ packages/core-commands/package.json | 2 +- packages/core-data/CHANGELOG.md | 2 ++ packages/core-data/package.json | 2 +- packages/create-block-interactive-template/CHANGELOG.md | 2 ++ packages/create-block-interactive-template/package.json | 2 +- packages/create-block-tutorial-template/CHANGELOG.md | 2 ++ packages/create-block-tutorial-template/package.json | 2 +- packages/create-block/CHANGELOG.md | 2 ++ packages/create-block/package.json | 2 +- packages/customize-widgets/CHANGELOG.md | 2 ++ packages/customize-widgets/package.json | 2 +- packages/data-controls/CHANGELOG.md | 2 ++ packages/data-controls/package.json | 2 +- packages/data/CHANGELOG.md | 2 ++ packages/data/package.json | 2 +- packages/dataviews/CHANGELOG.md | 2 ++ packages/dataviews/package.json | 2 +- packages/date/CHANGELOG.md | 2 ++ packages/date/package.json | 2 +- packages/dependency-extraction-webpack-plugin/CHANGELOG.md | 2 ++ packages/dependency-extraction-webpack-plugin/package.json | 2 +- packages/deprecated/CHANGELOG.md | 2 ++ packages/deprecated/package.json | 2 +- packages/docgen/CHANGELOG.md | 2 ++ packages/docgen/package.json | 2 +- packages/dom-ready/CHANGELOG.md | 2 ++ packages/dom-ready/package.json | 2 +- packages/dom/CHANGELOG.md | 2 ++ packages/dom/package.json | 2 +- packages/e2e-test-utils-playwright/CHANGELOG.md | 2 ++ packages/e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/CHANGELOG.md | 2 ++ packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/CHANGELOG.md | 2 ++ packages/e2e-tests/package.json | 2 +- packages/edit-post/CHANGELOG.md | 2 ++ packages/edit-post/package.json | 2 +- packages/edit-site/CHANGELOG.md | 2 ++ packages/edit-site/package.json | 2 +- packages/edit-widgets/CHANGELOG.md | 2 ++ packages/edit-widgets/package.json | 2 +- packages/editor/CHANGELOG.md | 2 ++ packages/editor/package.json | 2 +- packages/element/CHANGELOG.md | 2 ++ packages/element/package.json | 2 +- packages/env/CHANGELOG.md | 2 ++ packages/env/package.json | 2 +- packages/escape-html/CHANGELOG.md | 2 ++ packages/escape-html/package.json | 2 +- packages/eslint-plugin/CHANGELOG.md | 2 ++ packages/eslint-plugin/package.json | 2 +- packages/format-library/CHANGELOG.md | 2 ++ packages/format-library/package.json | 2 +- packages/hooks/CHANGELOG.md | 2 ++ packages/hooks/package.json | 2 +- packages/html-entities/CHANGELOG.md | 2 ++ packages/html-entities/package.json | 2 +- packages/i18n/CHANGELOG.md | 2 ++ packages/i18n/package.json | 2 +- packages/icons/CHANGELOG.md | 2 ++ packages/icons/package.json | 2 +- packages/interactivity-router/CHANGELOG.md | 2 ++ packages/interactivity-router/package.json | 2 +- packages/interactivity/CHANGELOG.md | 2 ++ packages/interactivity/package.json | 2 +- packages/interface/CHANGELOG.md | 2 ++ packages/interface/package.json | 2 +- packages/is-shallow-equal/CHANGELOG.md | 2 ++ packages/is-shallow-equal/package.json | 2 +- packages/jest-console/CHANGELOG.md | 2 ++ packages/jest-console/package.json | 2 +- packages/jest-preset-default/CHANGELOG.md | 2 ++ packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/CHANGELOG.md | 2 ++ packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/CHANGELOG.md | 2 ++ packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/CHANGELOG.md | 2 ++ packages/keycodes/package.json | 2 +- packages/lazy-import/CHANGELOG.md | 2 ++ packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/CHANGELOG.md | 2 ++ packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/CHANGELOG.md | 2 ++ packages/media-utils/package.json | 2 +- packages/notices/CHANGELOG.md | 2 ++ packages/notices/package.json | 2 +- packages/npm-package-json-lint-config/CHANGELOG.md | 2 ++ packages/npm-package-json-lint-config/package.json | 2 +- packages/nux/CHANGELOG.md | 2 ++ packages/nux/package.json | 2 +- packages/patterns/CHANGELOG.md | 2 ++ packages/patterns/package.json | 2 +- packages/plugins/CHANGELOG.md | 2 ++ packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/CHANGELOG.md | 2 ++ packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/CHANGELOG.md | 2 ++ packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/CHANGELOG.md | 2 ++ packages/preferences-persistence/package.json | 2 +- packages/preferences/CHANGELOG.md | 2 ++ packages/preferences/package.json | 2 +- packages/prettier-config/CHANGELOG.md | 2 ++ packages/prettier-config/package.json | 2 +- packages/primitives/CHANGELOG.md | 2 ++ packages/primitives/package.json | 2 +- packages/priority-queue/CHANGELOG.md | 2 ++ packages/priority-queue/package.json | 2 +- packages/private-apis/CHANGELOG.md | 2 ++ packages/private-apis/package.json | 2 +- packages/project-management-automation/CHANGELOG.md | 2 ++ packages/project-management-automation/package.json | 2 +- packages/react-i18n/CHANGELOG.md | 2 ++ packages/react-i18n/package.json | 2 +- packages/readable-js-assets-webpack-plugin/CHANGELOG.md | 2 ++ packages/readable-js-assets-webpack-plugin/package.json | 2 +- packages/redux-routine/CHANGELOG.md | 2 ++ packages/redux-routine/package.json | 2 +- packages/reusable-blocks/CHANGELOG.md | 2 ++ packages/reusable-blocks/package.json | 2 +- packages/rich-text/CHANGELOG.md | 2 ++ packages/rich-text/package.json | 2 +- packages/router/CHANGELOG.md | 2 ++ packages/router/package.json | 2 +- packages/scripts/CHANGELOG.md | 2 ++ packages/scripts/package.json | 2 +- packages/server-side-render/CHANGELOG.md | 2 ++ packages/server-side-render/package.json | 2 +- packages/shortcode/CHANGELOG.md | 2 ++ packages/shortcode/package.json | 2 +- packages/style-engine/CHANGELOG.md | 2 ++ packages/style-engine/package.json | 2 +- packages/stylelint-config/CHANGELOG.md | 2 ++ packages/stylelint-config/package.json | 2 +- packages/sync/CHANGELOG.md | 2 ++ packages/sync/package.json | 2 +- packages/token-list/CHANGELOG.md | 2 ++ packages/token-list/package.json | 2 +- packages/undo-manager/CHANGELOG.md | 2 ++ packages/undo-manager/package.json | 2 +- packages/url/CHANGELOG.md | 2 ++ packages/url/package.json | 2 +- packages/viewport/CHANGELOG.md | 2 ++ packages/viewport/package.json | 2 +- packages/warning/CHANGELOG.md | 2 ++ packages/warning/package.json | 2 +- packages/widgets/CHANGELOG.md | 2 ++ packages/widgets/package.json | 2 +- packages/wordcount/CHANGELOG.md | 2 ++ packages/wordcount/package.json | 2 +- 190 files changed, 285 insertions(+), 95 deletions(-) diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index 5a90a6cc98f0de..36973cce020f33 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 0e307e813c56ad..dc35e8a47b534b 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/CHANGELOG.md b/packages/annotations/CHANGELOG.md index b3e0dbab635b8b..6211cf30688e5c 100644 --- a/packages/annotations/CHANGELOG.md +++ b/packages/annotations/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.7.0 (2024-09-05) + ## 3.6.0 (2024-08-21) ## 3.5.0 (2024-08-07) diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 95ceadb1d990ed..d8fa386cb3707e 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.6.0", + "version": "3.7.0-prerelease", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/CHANGELOG.md b/packages/api-fetch/CHANGELOG.md index 49319c18ab7543..01b37d4e14a7d1 100644 --- a/packages/api-fetch/CHANGELOG.md +++ b/packages/api-fetch/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.7.0 (2024-09-05) + ## 7.6.0 (2024-08-21) ## 7.5.0 (2024-08-07) diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index abbe8cce374c31..cf40a5a23ac4e2 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.6.0", + "version": "7.7.0-prerelease", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/CHANGELOG.md b/packages/autop/CHANGELOG.md index 353495eae8983d..ed19f1ceafbc58 100644 --- a/packages/autop/CHANGELOG.md +++ b/packages/autop/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/autop/package.json b/packages/autop/package.json index 03bb56412195ec..220e6d78bd6675 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md index d96d2315e2a51e..c916b788243a06 100644 --- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md +++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index be1dbc4235f289..c343d8e2ab0061 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/CHANGELOG.md b/packages/babel-plugin-makepot/CHANGELOG.md index 98da250e2ba6b6..e7345f314d5788 100644 --- a/packages/babel-plugin-makepot/CHANGELOG.md +++ b/packages/babel-plugin-makepot/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.7.0 (2024-09-05) + ## 6.6.0 (2024-08-21) ## 6.5.0 (2024-08-07) diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index 4d439baf28163d..f2a74f7982f486 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.6.0", + "version": "6.7.0-prerelease", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index 43c9675fcb885b..70a740f60cad38 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.7.0 (2024-09-05) + ## 8.6.0 (2024-08-21) ## 8.5.0 (2024-08-07) diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 2559b60401790e..19122df83f2948 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.6.0", + "version": "8.7.0-prerelease", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/CHANGELOG.md b/packages/base-styles/CHANGELOG.md index ce98cebeae1c2a..cad2f94c98da7b 100644 --- a/packages/base-styles/CHANGELOG.md +++ b/packages/base-styles/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index fbe3bf149b1cdf..f17404a4896bdb 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md index 5c21e96d7269cd..f95598025a8b68 100644 --- a/packages/blob/CHANGELOG.md +++ b/packages/blob/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/blob/package.json b/packages/blob/package.json index 58feea189bed0e..2af9c8c1b65775 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/CHANGELOG.md b/packages/block-directory/CHANGELOG.md index 4d15343f0c0926..70914f293ca998 100644 --- a/packages/block-directory/CHANGELOG.md +++ b/packages/block-directory/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 85222ecaa38827..86a293c39d186c 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 0b365c18ae8ad4..da44ebc4149f58 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.2.0 (2024-09-05) + ## 14.1.0 (2024-08-21) ## 14.0.0 (2024-08-07) diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 1f4fa7588ec6c9..972187c13e6cf0 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.1.0", + "version": "14.2.0-prerelease", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index 319d2b04a31687..4ee3ebc7564b53 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.7.0 (2024-09-05) + ## 9.6.0 (2024-08-21) ## 9.5.0 (2024-08-07) diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 5b522f01ea7786..16d11a57a5bde7 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.6.1", + "version": "9.7.0-prerelease", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/CHANGELOG.md b/packages/block-serialization-default-parser/CHANGELOG.md index 7357d96bdcf7c5..9dd0bd70309764 100644 --- a/packages/block-serialization-default-parser/CHANGELOG.md +++ b/packages/block-serialization-default-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index cbfcbfc0e4cb64..72782dec49fdb9 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/CHANGELOG.md b/packages/block-serialization-spec-parser/CHANGELOG.md index d4091d455937d7..b8d02b5348e1b6 100644 --- a/packages/block-serialization-spec-parser/CHANGELOG.md +++ b/packages/block-serialization-spec-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 0020908e338331..828a9781dad8e7 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index ce7417db1f35af..0755d5170d1b32 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 13.7.0 (2024-09-05) + ## 13.6.0 (2024-08-21) ## 13.5.0 (2024-08-07) diff --git a/packages/blocks/package.json b/packages/blocks/package.json index e6c5253c7a4af1..8df16682e40997 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.6.0", + "version": "13.7.0-prerelease", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/CHANGELOG.md b/packages/browserslist-config/CHANGELOG.md index 2d0fafa7bc9889..b8ee58633b7ef2 100644 --- a/packages/browserslist-config/CHANGELOG.md +++ b/packages/browserslist-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.7.0 (2024-09-05) + ## 6.6.0 (2024-08-21) ## 6.5.0 (2024-08-07) diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 6cf84334da5b30..da69f2a773f518 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.6.0", + "version": "6.7.0-prerelease", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/CHANGELOG.md b/packages/commands/CHANGELOG.md index 86cefcc971b249..bde7767a0f61f6 100644 --- a/packages/commands/CHANGELOG.md +++ b/packages/commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.7.0 (2024-09-05) + ## 1.6.0 (2024-08-21) ## 1.5.0 (2024-08-07) diff --git a/packages/commands/package.json b/packages/commands/package.json index 5bca7f6ad6fae5..938afdce00ed95 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.6.0", + "version": "1.7.0-prerelease", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index aeb1de80a73c55..535f49ae00b11c 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 28.7.0 (2024-09-05) + ### Deprecations - Deprecate `replace` from the options accepted by `useNavigator().goTo()` ([#64675](https://github.com/WordPress/gutenberg/pull/64675)). diff --git a/packages/components/package.json b/packages/components/package.json index ba943ece33340f..5048541645ad44 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.6.0", + "version": "28.7.0-prerelease", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index 951f70604f41c6..2683fe8d79be70 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.7.0 (2024-09-05) + ## 7.6.0 (2024-08-21) ## 7.5.0 (2024-08-07) diff --git a/packages/compose/package.json b/packages/compose/package.json index 92b3085e585755..911b06b3f6f15e 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.6.0", + "version": "7.7.0-prerelease", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/CHANGELOG.md b/packages/core-commands/CHANGELOG.md index 16bf8c495eb03c..02871d4f31e135 100644 --- a/packages/core-commands/CHANGELOG.md +++ b/packages/core-commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.7.0 (2024-09-05) + ## 1.6.0 (2024-08-21) ## 1.5.0 (2024-08-07) diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 02b8b76b4f145e..43bb231fb5ada5 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.6.0", + "version": "1.7.0-prerelease", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md index caed77084733bf..6286a55291a54f 100644 --- a/packages/core-data/CHANGELOG.md +++ b/packages/core-data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.7.0 (2024-09-05) + ## 7.6.0 (2024-08-21) ## 7.5.0 (2024-08-07) diff --git a/packages/core-data/package.json b/packages/core-data/package.json index e96f3247086073..4b14bfce8ebdc7 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.6.0", + "version": "7.7.0-prerelease", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/CHANGELOG.md b/packages/create-block-interactive-template/CHANGELOG.md index 52f97a68cbf87a..c044dfff15e3ac 100644 --- a/packages/create-block-interactive-template/CHANGELOG.md +++ b/packages/create-block-interactive-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.7.0 (2024-09-05) + ### Enhancements - Set the minimum supported WordPress version to 6.6 to make it work seamlessly with the latest version of `@wordpress/scripts` package ([#64920](https://github.com/WordPress/gutenberg/pull/64920)). diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index 848cd757652150..ddf0e50af79b60 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.6.0", + "version": "2.7.0-prerelease", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/CHANGELOG.md b/packages/create-block-tutorial-template/CHANGELOG.md index 50290a8e07e90e..0fe0f748b8804d 100644 --- a/packages/create-block-tutorial-template/CHANGELOG.md +++ b/packages/create-block-tutorial-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ### Enhancements - Set the minimum supported WordPress version to 6.6 to make it work seamlessly with the latest version of `@wordpress/scripts` package ([#64920](https://github.com/WordPress/gutenberg/pull/64920)). diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index 0d9baf39d8db80..7638f46580c446 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index 3f742b352614e0..99e7b1fd37a33a 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.50.0 (2024-09-05) + ### Enhancements - Unpin the `@wordpress/scripts` version and set the minimum supported WordPress version to 6.6 ([#64920](https://github.com/WordPress/gutenberg/pull/64920)). diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 7548fca1532f07..bbaadf957122c4 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.49.0", + "version": "4.50.0-prerelease", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/CHANGELOG.md b/packages/customize-widgets/CHANGELOG.md index aeec00430f47d1..4e0d5a37553577 100644 --- a/packages/customize-widgets/CHANGELOG.md +++ b/packages/customize-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 9c8c0a79b771ab..0e0d1245d42346 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.6.1", + "version": "5.7.0-prerelease", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/CHANGELOG.md b/packages/data-controls/CHANGELOG.md index ae38ef764c535d..e6af7fdcb6e240 100644 --- a/packages/data-controls/CHANGELOG.md +++ b/packages/data-controls/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 216f4000adff8e..0b7387c34eb520 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index 52b88a1c5d4297..4ba90611c2a787 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.7.0 (2024-09-05) + ## 10.6.0 (2024-08-21) ## 10.5.0 (2024-08-07) diff --git a/packages/data/package.json b/packages/data/package.json index fb27caaf37798f..f4fbc2cb7280d8 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.6.0", + "version": "10.7.0-prerelease", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index bf93b9e52f657a..1e323714c4d5f7 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.3.0 (2024-09-05) + ## 4.2.0 (2024-08-21) ## New features diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index e02c0a624aa41c..bdffbaffcb22b9 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.2.0", + "version": "4.3.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md index 3940814a2f5d88..e19aa08ab6fe50 100644 --- a/packages/date/CHANGELOG.md +++ b/packages/date/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/date/package.json b/packages/date/package.json index b927d596864433..7bdca4b813190c 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index ddfd7fb32710a7..1da5f074301fd6 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.7.0 (2024-09-05) + ## 6.6.0 (2024-08-21) ## 6.5.0 (2024-08-07) diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index 5fd9b52f1acfdd..37767cdb37b52d 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.6.0", + "version": "6.7.0-prerelease", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/CHANGELOG.md b/packages/deprecated/CHANGELOG.md index 5a19167c70965e..673567a2a3e492 100644 --- a/packages/deprecated/CHANGELOG.md +++ b/packages/deprecated/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 244a8a0825e297..36610fdcc79885 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/CHANGELOG.md b/packages/docgen/CHANGELOG.md index db2451d2184338..3aefc7cae99ae2 100644 --- a/packages/docgen/CHANGELOG.md +++ b/packages/docgen/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.7.0 (2024-09-05) + ## 2.6.0 (2024-08-21) ## 2.5.0 (2024-08-07) diff --git a/packages/docgen/package.json b/packages/docgen/package.json index e5b8b294cde520..93e17d24f58d29 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.6.0", + "version": "2.7.0-prerelease", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/CHANGELOG.md b/packages/dom-ready/CHANGELOG.md index 45cf7f02b51061..f3290182dff5c2 100644 --- a/packages/dom-ready/CHANGELOG.md +++ b/packages/dom-ready/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 5911fba9c58ebd..275843061ba832 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/CHANGELOG.md b/packages/dom/CHANGELOG.md index 6444d64321a28d..1857e3d51cb70f 100644 --- a/packages/dom/CHANGELOG.md +++ b/packages/dom/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/dom/package.json b/packages/dom/package.json index d861e4263accea..25bec8b42cf5c4 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/CHANGELOG.md b/packages/e2e-test-utils-playwright/CHANGELOG.md index 2344239ebcdb27..eb3cbd95fe3ad0 100644 --- a/packages/e2e-test-utils-playwright/CHANGELOG.md +++ b/packages/e2e-test-utils-playwright/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.7.0 (2024-09-05) + ## 1.6.0 (2024-08-21) ## 1.5.0 (2024-08-07) diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 2430644c77b3b4..07ff68cbb10174 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.6.0", + "version": "1.7.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index da33570821a311..b22c016a799bc5 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 11.7.0 (2024-09-05) + ## 11.6.0 (2024-08-21) ## 11.5.0 (2024-08-07) diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index d533cacee7a8be..6974d0e4dc7e26 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.6.0", + "version": "11.7.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md index 568e58c11cdb0a..a7ba03f05f4668 100644 --- a/packages/e2e-tests/CHANGELOG.md +++ b/packages/e2e-tests/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.7.0 (2024-09-05) + ## 8.6.0 (2024-08-21) ## 8.5.0 (2024-08-07) diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index f6491e6d58c531..20dd8753011535 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.6.0", + "version": "8.7.0-prerelease", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index c715ddebcd82a1..cd4b4a36295f07 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.7.0 (2024-09-05) + ## 8.6.0 (2024-08-21) ## 8.5.0 (2024-08-07) diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 74152b849cf22b..5965a0348b98b1 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.6.1", + "version": "8.7.0-prerelease", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/CHANGELOG.md b/packages/edit-site/CHANGELOG.md index 2bed952f89a4e6..025d2389e4b01d 100644 --- a/packages/edit-site/CHANGELOG.md +++ b/packages/edit-site/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.7.0 (2024-09-05) + ## 6.6.0 (2024-08-21) ## 6.5.0 (2024-08-07) diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 52292464a21d69..1678b16c194eb7 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.6.1", + "version": "6.7.0-prerelease", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/CHANGELOG.md b/packages/edit-widgets/CHANGELOG.md index eb185d530887d3..f1cbcef0667d7c 100644 --- a/packages/edit-widgets/CHANGELOG.md +++ b/packages/edit-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.7.0 (2024-09-05) + ## 6.6.0 (2024-08-21) ## 6.5.0 (2024-08-07) diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index ed48d07a1d1e5c..c7616de2090b8d 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.6.1", + "version": "6.7.0-prerelease", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index 05bb9beb3b1fcc..b380c2fd296d55 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.7.0 (2024-09-05) + ## 14.6.0 (2024-08-21) ## 14.5.0 (2024-08-07) diff --git a/packages/editor/package.json b/packages/editor/package.json index 7e120895c782f3..6405b55693853b 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.6.0", + "version": "14.7.0-prerelease", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/CHANGELOG.md b/packages/element/CHANGELOG.md index 4c0d695bef6a37..ccfa6a6021d71f 100644 --- a/packages/element/CHANGELOG.md +++ b/packages/element/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.7.0 (2024-09-05) + ## 6.6.0 (2024-08-21) ## 6.5.0 (2024-08-07) diff --git a/packages/element/package.json b/packages/element/package.json index b1ed7cef47033b..ef9c1d64a4d18b 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.6.0", + "version": "6.7.0-prerelease", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md index 836084cd437fe7..b3dcf350596a0f 100644 --- a/packages/env/CHANGELOG.md +++ b/packages/env/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.7.0 (2024-09-05) + ## 10.6.0 (2024-08-21) ## 10.5.0 (2024-08-07) diff --git a/packages/env/package.json b/packages/env/package.json index f7b8b2fb4a64d1..0b1c76a1627da9 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.6.0", + "version": "10.7.0-prerelease", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/CHANGELOG.md b/packages/escape-html/CHANGELOG.md index d3a505806d4575..490cbdb184f5b1 100644 --- a/packages/escape-html/CHANGELOG.md +++ b/packages/escape-html/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.7.0 (2024-09-05) + ## 3.6.0 (2024-08-21) ## 3.5.0 (2024-08-07) diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 3b5572ffcfc2bf..08513c1cdb711a 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.6.0", + "version": "3.7.0-prerelease", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index b61a4ecb9f3bb7..14d44d21acda9f 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 21.0.0 (2024-09-05) + ### Breaking Changes - Add [`@wordpress/i18n-no-flanking-whitespace`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/eslint-plugin/docs/rules/i18n-no-flanking-whitespace.md) to the recommended i18n ruleset ([#64710](https://github.com/WordPress/gutenberg/pull/64710). diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 7edb4033f32510..fb756e3788ca76 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "20.3.0", + "version": "21.0.0-prerelease", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/CHANGELOG.md b/packages/format-library/CHANGELOG.md index ff23fff3e0487f..c003ac587fcdfa 100644 --- a/packages/format-library/CHANGELOG.md +++ b/packages/format-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/format-library/package.json b/packages/format-library/package.json index 531ec71224ce76..b3ca6bcb187954 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/CHANGELOG.md b/packages/hooks/CHANGELOG.md index f23ab552ca7711..de9e11c38fe905 100644 --- a/packages/hooks/CHANGELOG.md +++ b/packages/hooks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 007404ec4a371d..c74488d78c3d16 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/CHANGELOG.md b/packages/html-entities/CHANGELOG.md index 03e163b070bd86..6887a70b391f98 100644 --- a/packages/html-entities/CHANGELOG.md +++ b/packages/html-entities/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 690bd5d6762215..a6fea5015d93cc 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index 40f11787b9779f..d2bf7ad7ea7eb3 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/i18n/package.json b/packages/i18n/package.json index ef53c5a52900fb..2ea131d18b7597 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index f5d33c3a0dea01..32bbd88181e369 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.7.0 (2024-09-05) + ## 10.6.0 (2024-08-21) ## 10.5.0 (2024-08-07) diff --git a/packages/icons/package.json b/packages/icons/package.json index 576160fdb52738..24473645663673 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.6.0", + "version": "10.7.0-prerelease", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/CHANGELOG.md b/packages/interactivity-router/CHANGELOG.md index 472b351682bbce..00c47f3ed074b6 100644 --- a/packages/interactivity-router/CHANGELOG.md +++ b/packages/interactivity-router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.7.0 (2024-09-05) + ## 2.6.0 (2024-08-21) ## 2.5.0 (2024-08-07) diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 29a3f53a6109f0..796581950866ca 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.6.0", + "version": "2.7.0-prerelease", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 1d72e85f3c34e2..b410eb270358f0 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.7.0 (2024-09-05) + ### Enhancements - Improve internal `deepMerge` function ([#64879](https://github.com/WordPress/gutenberg/pull/64879)). diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index fca8a03a7e45a7..a81a87549f07bc 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.6.0", + "version": "6.7.0-prerelease", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index 60a339f019bf50..64f8c370bb6ece 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.7.0 (2024-09-05) + ## 6.6.0 (2024-08-21) ## 6.5.0 (2024-08-07) diff --git a/packages/interface/package.json b/packages/interface/package.json index 6e017bfd349256..e4397f72ac730d 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "6.6.0", + "version": "6.7.0-prerelease", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/CHANGELOG.md b/packages/is-shallow-equal/CHANGELOG.md index 23e1a6e0098484..81f2c4b164a3ab 100644 --- a/packages/is-shallow-equal/CHANGELOG.md +++ b/packages/is-shallow-equal/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index baa1dd7b3ebea9..7851c57b8e625d 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/CHANGELOG.md b/packages/jest-console/CHANGELOG.md index ff8c00c83fc8ee..7f7f80b815a850 100644 --- a/packages/jest-console/CHANGELOG.md +++ b/packages/jest-console/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.7.0 (2024-09-05) + ## 8.6.0 (2024-08-21) ## 8.5.0 (2024-08-07) diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 4e0d804088f893..28005427da2e43 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.6.0", + "version": "8.7.0-prerelease", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md index 04acc6e69ef606..e48d25dc1e6424 100644 --- a/packages/jest-preset-default/CHANGELOG.md +++ b/packages/jest-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 12.7.0 (2024-09-05) + ## 12.6.0 (2024-08-21) ## 12.5.0 (2024-08-07) diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index d09e89e88a63f1..c1daabe124076f 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.6.0", + "version": "12.7.0-prerelease", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/CHANGELOG.md b/packages/jest-puppeteer-axe/CHANGELOG.md index 984fdf249f504e..572b4aa137a141 100644 --- a/packages/jest-puppeteer-axe/CHANGELOG.md +++ b/packages/jest-puppeteer-axe/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.7.0 (2024-09-05) + ## 7.6.0 (2024-08-21) ## 7.5.0 (2024-08-07) diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index a512a018a9760c..1d7a5c582d0070 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.6.0", + "version": "7.7.0-prerelease", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/CHANGELOG.md b/packages/keyboard-shortcuts/CHANGELOG.md index 20396b4b935ac6..fe3506ea4a5f19 100644 --- a/packages/keyboard-shortcuts/CHANGELOG.md +++ b/packages/keyboard-shortcuts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 52070a0904e101..f7968035b42d81 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/CHANGELOG.md b/packages/keycodes/CHANGELOG.md index 745412efcb990b..51050728f2f5a3 100644 --- a/packages/keycodes/CHANGELOG.md +++ b/packages/keycodes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 4206b93430cfa5..8d5a55a39977fe 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/CHANGELOG.md b/packages/lazy-import/CHANGELOG.md index 944cb6207fb962..daea6da3404d3f 100644 --- a/packages/lazy-import/CHANGELOG.md +++ b/packages/lazy-import/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.7.0 (2024-09-05) + ## 2.6.0 (2024-08-21) ## 2.5.0 (2024-08-07) diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index 54ea606faefac5..d668e2e30517c8 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.6.0", + "version": "2.7.0-prerelease", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/CHANGELOG.md b/packages/list-reusable-blocks/CHANGELOG.md index 1338124bf1a7cd..9f62523fd94e11 100644 --- a/packages/list-reusable-blocks/CHANGELOG.md +++ b/packages/list-reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 8e5fb404607c6e..be97fc57765b19 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/CHANGELOG.md b/packages/media-utils/CHANGELOG.md index c155b906ab6dca..7ab4d4a5794d88 100644 --- a/packages/media-utils/CHANGELOG.md +++ b/packages/media-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 0cbf38592a1fd6..a52150dc88d0b4 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/CHANGELOG.md b/packages/notices/CHANGELOG.md index 32d51970c2141d..f32648df69728e 100644 --- a/packages/notices/CHANGELOG.md +++ b/packages/notices/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/notices/package.json b/packages/notices/package.json index 46715eb74a891f..43e684393915de 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/CHANGELOG.md b/packages/npm-package-json-lint-config/CHANGELOG.md index cfb2ea682ba456..24dfd09fff55a2 100644 --- a/packages/npm-package-json-lint-config/CHANGELOG.md +++ b/packages/npm-package-json-lint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index 1acbcdede95aba..f8d10f9e9f4505 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/CHANGELOG.md b/packages/nux/CHANGELOG.md index 90c3e96deb80aa..85feaa73dbc239 100644 --- a/packages/nux/CHANGELOG.md +++ b/packages/nux/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.7.0 (2024-09-05) + ## 9.6.0 (2024-08-21) ## 9.5.0 (2024-08-07) diff --git a/packages/nux/package.json b/packages/nux/package.json index 0997a29878bee6..0449093f6ba13c 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.6.0", + "version": "9.7.0-prerelease", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/CHANGELOG.md b/packages/patterns/CHANGELOG.md index 612586efb30a5b..eaef3c431d6687 100644 --- a/packages/patterns/CHANGELOG.md +++ b/packages/patterns/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.7.0 (2024-09-05) + ## 2.6.0 (2024-08-21) ## 2.5.0 (2024-08-07) diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 5ca0cdbe5b9df5..9cd2ae339da9f4 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.6.0", + "version": "2.7.0-prerelease", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/CHANGELOG.md b/packages/plugins/CHANGELOG.md index 14b9e4cffa4ad8..c2c010c8881150 100644 --- a/packages/plugins/CHANGELOG.md +++ b/packages/plugins/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.7.0 (2024-09-05) + ## 7.6.0 (2024-08-21) ## 7.5.0 (2024-08-07) diff --git a/packages/plugins/package.json b/packages/plugins/package.json index c5bf069bfaa170..7c18507d16863b 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.6.0", + "version": "7.7.0-prerelease", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/CHANGELOG.md b/packages/postcss-plugins-preset/CHANGELOG.md index 1811914b5bd884..b16c9284417a31 100644 --- a/packages/postcss-plugins-preset/CHANGELOG.md +++ b/packages/postcss-plugins-preset/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 892586a194e6fc..4d13e9ccf4bfc5 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/CHANGELOG.md b/packages/postcss-themes/CHANGELOG.md index 11da169548988e..774c2edf77e0c3 100644 --- a/packages/postcss-themes/CHANGELOG.md +++ b/packages/postcss-themes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.7.0 (2024-09-05) + ## 6.6.0 (2024-08-21) ## 6.5.0 (2024-08-07) diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index 57234c6f8d7fb7..5350bc7d021a25 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.6.0", + "version": "6.7.0-prerelease", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/CHANGELOG.md b/packages/preferences-persistence/CHANGELOG.md index 5b280b336f051c..a4a3081901bf52 100644 --- a/packages/preferences-persistence/CHANGELOG.md +++ b/packages/preferences-persistence/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.7.0 (2024-09-05) + ## 2.6.0 (2024-08-21) ## 2.5.0 (2024-08-07) diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index f994ca28f63012..df7863073795ca 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.6.0", + "version": "2.7.0-prerelease", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/CHANGELOG.md b/packages/preferences/CHANGELOG.md index 5a71145f2396d3..7d87ce93868757 100644 --- a/packages/preferences/CHANGELOG.md +++ b/packages/preferences/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/preferences/package.json b/packages/preferences/package.json index e39668e6ebe5d0..93cc4d653ece1a 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/CHANGELOG.md b/packages/prettier-config/CHANGELOG.md index 5764c3b87cdd9f..e0e01d2b7f3ac8 100644 --- a/packages/prettier-config/CHANGELOG.md +++ b/packages/prettier-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index da728197725181..87aff7454f9f56 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/CHANGELOG.md b/packages/primitives/CHANGELOG.md index b75cafd7ce35f4..48db582f65e109 100644 --- a/packages/primitives/CHANGELOG.md +++ b/packages/primitives/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/primitives/package.json b/packages/primitives/package.json index d53ac401d07b6c..91467745a06300 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/CHANGELOG.md b/packages/priority-queue/CHANGELOG.md index 398db84f0bb44f..a7f1257b8f6b49 100644 --- a/packages/priority-queue/CHANGELOG.md +++ b/packages/priority-queue/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.7.0 (2024-09-05) + ## 3.6.0 (2024-08-21) ## 3.5.0 (2024-08-07) diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 012970e6344689..cbca16771ae351 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.6.0", + "version": "3.7.0-prerelease", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/CHANGELOG.md b/packages/private-apis/CHANGELOG.md index ebba5ca7d26b93..cd6449dc774ce7 100644 --- a/packages/private-apis/CHANGELOG.md +++ b/packages/private-apis/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.7.0 (2024-09-05) + ## 1.6.0 (2024-08-21) ## 1.5.0 (2024-08-07) diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index 4493a6a4acc6b8..ff31a9533bdb70 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.6.0", + "version": "1.7.0-prerelease", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/CHANGELOG.md b/packages/project-management-automation/CHANGELOG.md index d72669229fd2ab..167e68512b3dfc 100644 --- a/packages/project-management-automation/CHANGELOG.md +++ b/packages/project-management-automation/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.7.0 (2024-09-05) + ## 2.6.0 (2024-08-21) ## 2.5.0 (2024-08-07) diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index c82b5821342fec..0a6a938ebfc3ce 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.6.0", + "version": "2.7.0-prerelease", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/CHANGELOG.md b/packages/react-i18n/CHANGELOG.md index 20bd01908d4065..d0c0dbe7079f4e 100644 --- a/packages/react-i18n/CHANGELOG.md +++ b/packages/react-i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 6067ae8cf929cc..d2ddf5a66ed4dd 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md index a522759971264c..8147d5c3b3475f 100644 --- a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md +++ b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.7.0 (2024-09-05) + ## 3.6.0 (2024-08-21) ## 3.5.0 (2024-08-07) diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index aefee907eb7461..894363c76f1221 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.6.0", + "version": "3.7.0-prerelease", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/CHANGELOG.md b/packages/redux-routine/CHANGELOG.md index 1241701e225e92..bd03c25219ddbc 100644 --- a/packages/redux-routine/CHANGELOG.md +++ b/packages/redux-routine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index d78fad4d28eda1..5a88268219c263 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/CHANGELOG.md b/packages/reusable-blocks/CHANGELOG.md index 41a66dd019d784..33f4ef529587f2 100644 --- a/packages/reusable-blocks/CHANGELOG.md +++ b/packages/reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index c1e5c9a71b0729..971b1a9b2c44e7 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/CHANGELOG.md b/packages/rich-text/CHANGELOG.md index b3f7b7a2e4fdda..cee6ada55f7b61 100644 --- a/packages/rich-text/CHANGELOG.md +++ b/packages/rich-text/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.7.0 (2024-09-05) + ## 7.6.0 (2024-08-21) ## 7.5.0 (2024-08-07) diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 163b7f5e7188a8..ace76b50432c88 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.6.0", + "version": "7.7.0-prerelease", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index 16bf8c495eb03c..02871d4f31e135 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.7.0 (2024-09-05) + ## 1.6.0 (2024-08-21) ## 1.5.0 (2024-08-07) diff --git a/packages/router/package.json b/packages/router/package.json index 5bda384293cf5c..3498ff54c05157 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.6.0", + "version": "1.7.0-prerelease", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 9d666313f76abc..ea8a59d1ad2ad4 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 29.0.0 (2024-09-05) + ### Breaking Changes - Fixed the issue with having 5 high severity vulnerabilities by upgrading the `puppeteer-core` package to the latest major version `^23.1.0` ([#64597](https://github.com/WordPress/gutenberg/pull/64597)). diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 291b8a58bca408..e7a461d72a87ce 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "28.6.0", + "version": "29.0.0-prerelease", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/CHANGELOG.md b/packages/server-side-render/CHANGELOG.md index 6246bff21cb488..d576f09c8e34b7 100644 --- a/packages/server-side-render/CHANGELOG.md +++ b/packages/server-side-render/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.7.0 (2024-09-05) + ## 5.6.0 (2024-08-21) ## 5.5.0 (2024-08-07) diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index 054e8b938ce845..30948ce80270e4 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.6.0", + "version": "5.7.0-prerelease", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/CHANGELOG.md b/packages/shortcode/CHANGELOG.md index eeb738b9e49123..6abdd3c52f6d74 100644 --- a/packages/shortcode/CHANGELOG.md +++ b/packages/shortcode/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index 42ca3458d72a5b..867dc0eba27fd4 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md index b8462204ea958c..a5292bfdd6c191 100644 --- a/packages/style-engine/CHANGELOG.md +++ b/packages/style-engine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.7.0 (2024-09-05) + ## 2.6.0 (2024-08-21) ### New Features diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 91409072cb6503..0e2fd9d8287610 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.6.0", + "version": "2.7.0-prerelease", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/CHANGELOG.md b/packages/stylelint-config/CHANGELOG.md index 4df376a34b0986..9cb29690af289e 100644 --- a/packages/stylelint-config/CHANGELOG.md +++ b/packages/stylelint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 22.7.0 (2024-09-05) + ## 22.6.0 (2024-08-21) ## 22.5.0 (2024-08-07) diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index aab9f8e8c3b417..54b79e2775d327 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "22.6.0", + "version": "22.7.0-prerelease", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/CHANGELOG.md b/packages/sync/CHANGELOG.md index b38fb8b48945cc..071974be2a3a88 100644 --- a/packages/sync/CHANGELOG.md +++ b/packages/sync/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.7.0 (2024-09-05) + ## 1.6.0 (2024-08-21) ## 1.5.0 (2024-08-07) diff --git a/packages/sync/package.json b/packages/sync/package.json index 703de650e3f242..f6bf88d7057662 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.6.0", + "version": "1.7.0-prerelease", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/CHANGELOG.md b/packages/token-list/CHANGELOG.md index 97b674024e637d..7258699a5322ae 100644 --- a/packages/token-list/CHANGELOG.md +++ b/packages/token-list/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.7.0 (2024-09-05) + ## 3.6.0 (2024-08-21) ## 3.5.0 (2024-08-07) diff --git a/packages/token-list/package.json b/packages/token-list/package.json index d40820a1f73a87..84d22c0cc4051d 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.6.0", + "version": "3.7.0-prerelease", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/CHANGELOG.md b/packages/undo-manager/CHANGELOG.md index 63338342dfe54c..cbe86921a489d2 100644 --- a/packages/undo-manager/CHANGELOG.md +++ b/packages/undo-manager/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.7.0 (2024-09-05) + ## 1.6.0 (2024-08-21) ## 1.5.0 (2024-08-07) diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 3607f6f6a990ca..1d3a169cab8cd2 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.6.0", + "version": "1.7.0-prerelease", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/CHANGELOG.md b/packages/url/CHANGELOG.md index f9af22f9fa7447..fc3082dd1bd0c6 100644 --- a/packages/url/CHANGELOG.md +++ b/packages/url/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/url/package.json b/packages/url/package.json index e83c05e594e5f9..c9fa20ac37d13a 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/CHANGELOG.md b/packages/viewport/CHANGELOG.md index 8ce0b7b1ffb750..1bc96013d724bb 100644 --- a/packages/viewport/CHANGELOG.md +++ b/packages/viewport/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.7.0 (2024-09-05) + ## 6.6.0 (2024-08-21) ## 6.5.0 (2024-08-07) diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 7575c63256b632..c228846712d662 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.6.0", + "version": "6.7.0-prerelease", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/CHANGELOG.md b/packages/warning/CHANGELOG.md index ca176032261544..bb7df7b6330625 100644 --- a/packages/warning/CHANGELOG.md +++ b/packages/warning/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.7.0 (2024-09-05) + ## 3.6.0 (2024-08-21) ## 3.5.0 (2024-08-07) diff --git a/packages/warning/package.json b/packages/warning/package.json index b18ad5ffc51678..e57af47a84ae4d 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.6.0", + "version": "3.7.0-prerelease", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/CHANGELOG.md b/packages/widgets/CHANGELOG.md index e95c3904f97e1e..be1af839314954 100644 --- a/packages/widgets/CHANGELOG.md +++ b/packages/widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/widgets/package.json b/packages/widgets/package.json index c7fbb82eb0cb1d..70192ecd36bf79 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/CHANGELOG.md b/packages/wordcount/CHANGELOG.md index 33eb27b885ab48..0a5e3ae4d3b206 100644 --- a/packages/wordcount/CHANGELOG.md +++ b/packages/wordcount/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-09-05) + ## 4.6.0 (2024-08-21) ## 4.5.0 (2024-08-07) diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index 55cbfe3311d285..5ea29a55d5062c 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 05066fadf3bbd82d8e564c362625585ef4a41397 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 5 Sep 2024 03:40:05 +0000 Subject: [PATCH 0691/1908] chore(release): publish - @wordpress/a11y@4.7.0 - @wordpress/annotations@3.7.0 - @wordpress/api-fetch@7.7.0 - @wordpress/autop@4.7.0 - @wordpress/babel-plugin-import-jsx-pragma@5.7.0 - @wordpress/babel-plugin-makepot@6.7.0 - @wordpress/babel-preset-default@8.7.0 - @wordpress/base-styles@5.7.0 - @wordpress/blob@4.7.0 - @wordpress/block-directory@5.7.0 - @wordpress/block-editor@14.2.0 - @wordpress/block-library@9.7.0 - @wordpress/block-serialization-default-parser@5.7.0 - @wordpress/block-serialization-spec-parser@5.7.0 - @wordpress/blocks@13.7.0 - @wordpress/browserslist-config@6.7.0 - @wordpress/commands@1.7.0 - @wordpress/components@28.7.0 - @wordpress/compose@7.7.0 - @wordpress/core-commands@1.7.0 - @wordpress/core-data@7.7.0 - @wordpress/create-block@4.50.0 - @wordpress/create-block-interactive-template@2.7.0 - @wordpress/create-block-tutorial-template@4.7.0 - @wordpress/customize-widgets@5.7.0 - @wordpress/data@10.7.0 - @wordpress/data-controls@4.7.0 - @wordpress/dataviews@4.3.0 - @wordpress/date@5.7.0 - @wordpress/dependency-extraction-webpack-plugin@6.7.0 - @wordpress/deprecated@4.7.0 - @wordpress/docgen@2.7.0 - @wordpress/dom@4.7.0 - @wordpress/dom-ready@4.7.0 - @wordpress/e2e-test-utils@11.7.0 - @wordpress/e2e-test-utils-playwright@1.7.0 - @wordpress/e2e-tests@8.7.0 - @wordpress/edit-post@8.7.0 - @wordpress/edit-site@6.7.0 - @wordpress/edit-widgets@6.7.0 - @wordpress/editor@14.7.0 - @wordpress/element@6.7.0 - @wordpress/env@10.7.0 - @wordpress/escape-html@3.7.0 - @wordpress/eslint-plugin@21.0.0 - @wordpress/format-library@5.7.0 - @wordpress/hooks@4.7.0 - @wordpress/html-entities@4.7.0 - @wordpress/i18n@5.7.0 - @wordpress/icons@10.7.0 - @wordpress/interactivity@6.7.0 - @wordpress/interactivity-router@2.7.0 - @wordpress/interface@6.7.0 - @wordpress/is-shallow-equal@5.7.0 - @wordpress/jest-console@8.7.0 - @wordpress/jest-preset-default@12.7.0 - @wordpress/jest-puppeteer-axe@7.7.0 - @wordpress/keyboard-shortcuts@5.7.0 - @wordpress/keycodes@4.7.0 - @wordpress/lazy-import@2.7.0 - @wordpress/list-reusable-blocks@5.7.0 - @wordpress/media-utils@5.7.0 - @wordpress/notices@5.7.0 - @wordpress/npm-package-json-lint-config@5.7.0 - @wordpress/nux@9.7.0 - @wordpress/patterns@2.7.0 - @wordpress/plugins@7.7.0 - @wordpress/postcss-plugins-preset@5.7.0 - @wordpress/postcss-themes@6.7.0 - @wordpress/preferences@4.7.0 - @wordpress/preferences-persistence@2.7.0 - @wordpress/prettier-config@4.7.0 - @wordpress/primitives@4.7.0 - @wordpress/priority-queue@3.7.0 - @wordpress/private-apis@1.7.0 - @wordpress/project-management-automation@2.7.0 - @wordpress/react-i18n@4.7.0 - @wordpress/readable-js-assets-webpack-plugin@3.7.0 - @wordpress/redux-routine@5.7.0 - @wordpress/reusable-blocks@5.7.0 - @wordpress/rich-text@7.7.0 - @wordpress/router@1.7.0 - @wordpress/scripts@29.0.0 - @wordpress/server-side-render@5.7.0 - @wordpress/shortcode@4.7.0 - @wordpress/style-engine@2.7.0 - @wordpress/stylelint-config@22.7.0 - @wordpress/sync@1.7.0 - @wordpress/token-list@3.7.0 - @wordpress/undo-manager@1.7.0 - @wordpress/url@4.7.0 - @wordpress/viewport@6.7.0 - @wordpress/warning@3.7.0 - @wordpress/widgets@4.7.0 - @wordpress/wordcount@4.7.0 --- package-lock.json | 188 +++++++++--------- packages/a11y/package.json | 2 +- packages/annotations/package.json | 2 +- packages/api-fetch/package.json | 2 +- packages/autop/package.json | 2 +- .../package.json | 2 +- packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/package.json | 2 +- packages/base-styles/package.json | 2 +- packages/blob/package.json | 2 +- packages/block-directory/package.json | 2 +- packages/block-editor/package.json | 2 +- packages/block-library/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/blocks/package.json | 2 +- packages/browserslist-config/package.json | 2 +- packages/commands/package.json | 2 +- packages/components/package.json | 2 +- packages/compose/package.json | 2 +- packages/core-commands/package.json | 2 +- packages/core-data/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/create-block/package.json | 2 +- packages/customize-widgets/package.json | 2 +- packages/data-controls/package.json | 2 +- packages/data/package.json | 2 +- packages/dataviews/package.json | 2 +- packages/date/package.json | 2 +- .../package.json | 2 +- packages/deprecated/package.json | 2 +- packages/docgen/package.json | 2 +- packages/dom-ready/package.json | 2 +- packages/dom/package.json | 2 +- .../e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/package.json | 2 +- packages/edit-post/package.json | 2 +- packages/edit-site/package.json | 2 +- packages/edit-widgets/package.json | 2 +- packages/editor/package.json | 2 +- packages/element/package.json | 2 +- packages/env/package.json | 2 +- packages/escape-html/package.json | 2 +- packages/eslint-plugin/package.json | 2 +- packages/format-library/package.json | 2 +- packages/hooks/package.json | 2 +- packages/html-entities/package.json | 2 +- packages/i18n/package.json | 2 +- packages/icons/package.json | 2 +- packages/interactivity-router/package.json | 2 +- packages/interactivity/package.json | 2 +- packages/interface/package.json | 2 +- packages/is-shallow-equal/package.json | 2 +- packages/jest-console/package.json | 2 +- packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/package.json | 2 +- packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/package.json | 2 +- packages/notices/package.json | 2 +- .../npm-package-json-lint-config/package.json | 2 +- packages/nux/package.json | 2 +- packages/patterns/package.json | 2 +- packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/package.json | 2 +- packages/preferences/package.json | 2 +- packages/prettier-config/package.json | 2 +- packages/primitives/package.json | 2 +- packages/priority-queue/package.json | 2 +- packages/private-apis/package.json | 2 +- .../package.json | 2 +- packages/react-i18n/package.json | 2 +- .../package.json | 2 +- packages/redux-routine/package.json | 2 +- packages/reusable-blocks/package.json | 2 +- packages/rich-text/package.json | 2 +- packages/router/package.json | 2 +- packages/scripts/package.json | 2 +- packages/server-side-render/package.json | 2 +- packages/shortcode/package.json | 2 +- packages/style-engine/package.json | 2 +- packages/stylelint-config/package.json | 2 +- packages/sync/package.json | 2 +- packages/token-list/package.json | 2 +- packages/undo-manager/package.json | 2 +- packages/url/package.json | 2 +- packages/viewport/package.json | 2 +- packages/warning/package.json | 2 +- packages/widgets/package.json | 2 +- packages/wordcount/package.json | 2 +- 96 files changed, 189 insertions(+), 189 deletions(-) diff --git a/package-lock.json b/package-lock.json index 10ebadc05aa36b..0b5b92da05fa1d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52283,7 +52283,7 @@ }, "packages/a11y": { "name": "@wordpress/a11y", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52297,7 +52297,7 @@ }, "packages/annotations": { "name": "@wordpress/annotations", - "version": "3.6.0", + "version": "3.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52325,7 +52325,7 @@ }, "packages/api-fetch": { "name": "@wordpress/api-fetch", - "version": "7.6.0", + "version": "7.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52339,7 +52339,7 @@ }, "packages/autop": { "name": "@wordpress/autop", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52351,7 +52351,7 @@ }, "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.6.0", + "version": "5.7.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52364,7 +52364,7 @@ }, "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", - "version": "6.6.0", + "version": "6.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52382,7 +52382,7 @@ }, "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", - "version": "8.6.0", + "version": "8.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52405,7 +52405,7 @@ }, "packages/base-styles": { "name": "@wordpress/base-styles", - "version": "5.6.0", + "version": "5.7.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52415,7 +52415,7 @@ }, "packages/blob": { "name": "@wordpress/blob", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52427,7 +52427,7 @@ }, "packages/block-directory": { "name": "@wordpress/block-directory", - "version": "5.6.0", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52462,7 +52462,7 @@ }, "packages/block-editor": { "name": "@wordpress/block-editor", - "version": "14.1.0", + "version": "14.2.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52561,7 +52561,7 @@ }, "packages/block-library": { "name": "@wordpress/block-library", - "version": "9.6.1", + "version": "9.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52627,7 +52627,7 @@ }, "packages/block-serialization-default-parser": { "name": "@wordpress/block-serialization-default-parser", - "version": "5.6.0", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52639,7 +52639,7 @@ }, "packages/block-serialization-spec-parser": { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.6.0", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "pegjs": "^0.10.0", @@ -52652,7 +52652,7 @@ }, "packages/blocks": { "name": "@wordpress/blocks", - "version": "13.6.0", + "version": "13.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52706,7 +52706,7 @@ }, "packages/browserslist-config": { "name": "@wordpress/browserslist-config", - "version": "6.6.0", + "version": "6.7.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52716,7 +52716,7 @@ }, "packages/commands": { "name": "@wordpress/commands", - "version": "1.6.0", + "version": "1.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52889,7 +52889,7 @@ }, "packages/components": { "name": "@wordpress/components", - "version": "28.6.0", + "version": "28.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -53010,7 +53010,7 @@ }, "packages/compose": { "name": "@wordpress/compose", - "version": "7.6.0", + "version": "7.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53047,7 +53047,7 @@ }, "packages/core-commands": { "name": "@wordpress/core-commands", - "version": "1.6.0", + "version": "1.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53075,7 +53075,7 @@ }, "packages/core-data": { "name": "@wordpress/core-data", - "version": "7.6.0", + "version": "7.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53120,7 +53120,7 @@ }, "packages/create-block": { "name": "@wordpress/create-block", - "version": "4.49.0", + "version": "4.50.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53148,7 +53148,7 @@ }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", - "version": "4.6.0", + "version": "4.7.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -53158,7 +53158,7 @@ }, "packages/customize-widgets": { "name": "@wordpress/customize-widgets", - "version": "5.6.1", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53196,7 +53196,7 @@ }, "packages/data": { "name": "@wordpress/data", - "version": "10.6.0", + "version": "10.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53225,7 +53225,7 @@ }, "packages/data-controls": { "name": "@wordpress/data-controls", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53243,7 +53243,7 @@ }, "packages/dataviews": { "name": "@wordpress/dataviews", - "version": "4.2.0", + "version": "4.3.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -53300,7 +53300,7 @@ }, "packages/date": { "name": "@wordpress/date", - "version": "5.6.0", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53315,7 +53315,7 @@ }, "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.6.0", + "version": "6.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53331,7 +53331,7 @@ }, "packages/deprecated": { "name": "@wordpress/deprecated", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53344,7 +53344,7 @@ }, "packages/docgen": { "name": "@wordpress/docgen", - "version": "2.6.0", + "version": "2.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53366,7 +53366,7 @@ }, "packages/dom": { "name": "@wordpress/dom", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53379,7 +53379,7 @@ }, "packages/dom-ready": { "name": "@wordpress/dom-ready", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53391,7 +53391,7 @@ }, "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", - "version": "11.6.0", + "version": "11.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53414,7 +53414,7 @@ }, "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.6.0", + "version": "1.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53442,7 +53442,7 @@ }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", - "version": "8.6.0", + "version": "8.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53482,7 +53482,7 @@ }, "packages/edit-post": { "name": "@wordpress/edit-post", - "version": "8.6.1", + "version": "8.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53529,7 +53529,7 @@ }, "packages/edit-site": { "name": "@wordpress/edit-site", - "version": "6.6.1", + "version": "6.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53591,7 +53591,7 @@ }, "packages/edit-widgets": { "name": "@wordpress/edit-widgets", - "version": "6.6.1", + "version": "6.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53634,7 +53634,7 @@ }, "packages/editor": { "name": "@wordpress/editor", - "version": "14.6.0", + "version": "14.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53695,7 +53695,7 @@ }, "packages/element": { "name": "@wordpress/element", - "version": "6.6.0", + "version": "6.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53714,7 +53714,7 @@ }, "packages/env": { "name": "@wordpress/env", - "version": "10.6.0", + "version": "10.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53856,7 +53856,7 @@ }, "packages/escape-html": { "name": "@wordpress/escape-html", - "version": "3.6.0", + "version": "3.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53868,7 +53868,7 @@ }, "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", - "version": "20.3.0", + "version": "21.0.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53911,7 +53911,7 @@ }, "packages/format-library": { "name": "@wordpress/format-library", - "version": "5.6.0", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53939,7 +53939,7 @@ }, "packages/hooks": { "name": "@wordpress/hooks", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53951,7 +53951,7 @@ }, "packages/html-entities": { "name": "@wordpress/html-entities", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53963,7 +53963,7 @@ }, "packages/i18n": { "name": "@wordpress/i18n", - "version": "5.6.0", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53983,7 +53983,7 @@ }, "packages/icons": { "name": "@wordpress/icons", - "version": "10.6.0", + "version": "10.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53997,7 +53997,7 @@ }, "packages/interactivity": { "name": "@wordpress/interactivity", - "version": "6.6.0", + "version": "6.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@preact/signals": "^1.2.2", @@ -54010,7 +54010,7 @@ }, "packages/interactivity-router": { "name": "@wordpress/interactivity-router", - "version": "2.6.0", + "version": "2.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/interactivity": "file:../interactivity" @@ -54046,7 +54046,7 @@ }, "packages/interface": { "name": "@wordpress/interface", - "version": "6.6.0", + "version": "6.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54075,7 +54075,7 @@ }, "packages/is-shallow-equal": { "name": "@wordpress/is-shallow-equal", - "version": "5.6.0", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54087,7 +54087,7 @@ }, "packages/jest-console": { "name": "@wordpress/jest-console", - "version": "8.6.0", + "version": "8.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54104,7 +54104,7 @@ }, "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", - "version": "12.6.0", + "version": "12.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54122,7 +54122,7 @@ }, "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.6.0", + "version": "7.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54145,7 +54145,7 @@ }, "packages/keyboard-shortcuts": { "name": "@wordpress/keyboard-shortcuts", - "version": "5.6.0", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54163,7 +54163,7 @@ }, "packages/keycodes": { "name": "@wordpress/keycodes", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54176,7 +54176,7 @@ }, "packages/lazy-import": { "name": "@wordpress/lazy-import", - "version": "2.6.0", + "version": "2.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54191,7 +54191,7 @@ }, "packages/list-reusable-blocks": { "name": "@wordpress/list-reusable-blocks", - "version": "5.6.0", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54214,7 +54214,7 @@ }, "packages/media-utils": { "name": "@wordpress/media-utils", - "version": "5.6.0", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54230,7 +54230,7 @@ }, "packages/notices": { "name": "@wordpress/notices", - "version": "5.6.0", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54247,7 +54247,7 @@ }, "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.6.0", + "version": "5.7.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54260,7 +54260,7 @@ }, "packages/nux": { "name": "@wordpress/nux", - "version": "9.6.0", + "version": "9.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54283,7 +54283,7 @@ }, "packages/patterns": { "name": "@wordpress/patterns", - "version": "2.6.0", + "version": "2.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54313,7 +54313,7 @@ }, "packages/plugins": { "name": "@wordpress/plugins", - "version": "7.6.0", + "version": "7.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54336,7 +54336,7 @@ }, "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", - "version": "5.6.0", + "version": "5.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54353,7 +54353,7 @@ }, "packages/postcss-themes": { "name": "@wordpress/postcss-themes", - "version": "6.6.0", + "version": "6.7.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54366,7 +54366,7 @@ }, "packages/preferences": { "name": "@wordpress/preferences", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54392,7 +54392,7 @@ }, "packages/preferences-persistence": { "name": "@wordpress/preferences-persistence", - "version": "2.6.0", + "version": "2.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54405,7 +54405,7 @@ }, "packages/prettier-config": { "name": "@wordpress/prettier-config", - "version": "4.6.0", + "version": "4.7.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54418,7 +54418,7 @@ }, "packages/primitives": { "name": "@wordpress/primitives", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54435,7 +54435,7 @@ }, "packages/priority-queue": { "name": "@wordpress/priority-queue", - "version": "3.6.0", + "version": "3.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54448,7 +54448,7 @@ }, "packages/private-apis": { "name": "@wordpress/private-apis", - "version": "1.6.0", + "version": "1.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54460,7 +54460,7 @@ }, "packages/project-management-automation": { "name": "@wordpress/project-management-automation", - "version": "2.6.0", + "version": "2.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54490,7 +54490,7 @@ }, "packages/react-i18n": { "name": "@wordpress/react-i18n", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54646,7 +54646,7 @@ }, "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.6.0", + "version": "3.7.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54659,7 +54659,7 @@ }, "packages/redux-routine": { "name": "@wordpress/redux-routine", - "version": "5.6.0", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54704,7 +54704,7 @@ }, "packages/reusable-blocks": { "name": "@wordpress/reusable-blocks", - "version": "5.6.0", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54731,7 +54731,7 @@ }, "packages/rich-text": { "name": "@wordpress/rich-text", - "version": "7.6.0", + "version": "7.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54755,7 +54755,7 @@ }, "packages/router": { "name": "@wordpress/router", - "version": "1.6.0", + "version": "1.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54774,7 +54774,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "28.6.0", + "version": "29.0.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55229,7 +55229,7 @@ }, "packages/server-side-render": { "name": "@wordpress/server-side-render", - "version": "5.6.0", + "version": "5.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55255,7 +55255,7 @@ }, "packages/shortcode": { "name": "@wordpress/shortcode", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55268,7 +55268,7 @@ }, "packages/style-engine": { "name": "@wordpress/style-engine", - "version": "2.6.0", + "version": "2.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55281,7 +55281,7 @@ }, "packages/stylelint-config": { "name": "@wordpress/stylelint-config", - "version": "22.6.0", + "version": "22.7.0", "dev": true, "license": "MIT", "dependencies": { @@ -55298,7 +55298,7 @@ }, "packages/sync": { "name": "@wordpress/sync", - "version": "1.6.0", + "version": "1.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55319,7 +55319,7 @@ }, "packages/token-list": { "name": "@wordpress/token-list", - "version": "3.6.0", + "version": "3.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -55331,7 +55331,7 @@ }, "packages/undo-manager": { "name": "@wordpress/undo-manager", - "version": "1.6.0", + "version": "1.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55344,7 +55344,7 @@ }, "packages/url": { "name": "@wordpress/url", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55357,7 +55357,7 @@ }, "packages/viewport": { "name": "@wordpress/viewport", - "version": "6.6.0", + "version": "6.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55375,7 +55375,7 @@ }, "packages/warning": { "name": "@wordpress/warning", - "version": "3.6.0", + "version": "3.7.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55384,7 +55384,7 @@ }, "packages/widgets": { "name": "@wordpress/widgets", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55412,7 +55412,7 @@ }, "packages/wordcount": { "name": "@wordpress/wordcount", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" diff --git a/packages/a11y/package.json b/packages/a11y/package.json index dc35e8a47b534b..88123b3c6c7126 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/package.json b/packages/annotations/package.json index d8fa386cb3707e..c189dcc11fd09f 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.7.0-prerelease", + "version": "3.7.0", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index cf40a5a23ac4e2..76d797f4ddfa57 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.7.0-prerelease", + "version": "7.7.0", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/package.json b/packages/autop/package.json index 220e6d78bd6675..4e1cf577ebd09c 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index c343d8e2ab0061..1af6bdf93cb044 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index f2a74f7982f486..a7c18d891538d1 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.7.0-prerelease", + "version": "6.7.0", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 19122df83f2948..be5b3786346eb2 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.7.0-prerelease", + "version": "8.7.0", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index f17404a4896bdb..6839a8081e04a8 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/package.json b/packages/blob/package.json index 2af9c8c1b65775..3dea70c9771976 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 86a293c39d186c..39f239edfcb44a 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 972187c13e6cf0..d3064c78dbe658 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.2.0-prerelease", + "version": "14.2.0", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 16d11a57a5bde7..4d0212490858c9 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.7.0-prerelease", + "version": "9.7.0", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 72782dec49fdb9..cac606bd7bd1ee 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 828a9781dad8e7..d48d1846e79095 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 8df16682e40997..f371ecc087af41 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.7.0-prerelease", + "version": "13.7.0", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index da69f2a773f518..c51d7318170c4e 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.7.0-prerelease", + "version": "6.7.0", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/package.json b/packages/commands/package.json index 938afdce00ed95..88b9b86f4b3aeb 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.7.0-prerelease", + "version": "1.7.0", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/package.json b/packages/components/package.json index 5048541645ad44..17209986c0f17c 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.7.0-prerelease", + "version": "28.7.0", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/package.json b/packages/compose/package.json index 911b06b3f6f15e..4b68841d1777e6 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.7.0-prerelease", + "version": "7.7.0", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 43bb231fb5ada5..bae1e4c211cf0b 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.7.0-prerelease", + "version": "1.7.0", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 4b14bfce8ebdc7..ddb2d2ef091778 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.7.0-prerelease", + "version": "7.7.0", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index ddf0e50af79b60..667d3998ba820d 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.7.0-prerelease", + "version": "2.7.0", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index 7638f46580c446..64a8a90bc167c0 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/package.json b/packages/create-block/package.json index bbaadf957122c4..2103a85c5894f2 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.50.0-prerelease", + "version": "4.50.0", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 0e0d1245d42346..a8b50cf9cb318c 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 0b7387c34eb520..e97e59b74700cd 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/package.json b/packages/data/package.json index f4fbc2cb7280d8..84ad7a7973bc49 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.7.0-prerelease", + "version": "10.7.0", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index bdffbaffcb22b9..e327a217435c52 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.3.0-prerelease", + "version": "4.3.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/package.json b/packages/date/package.json index 7bdca4b813190c..488db71cfd693a 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index 37767cdb37b52d..f720a1df826e80 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.7.0-prerelease", + "version": "6.7.0", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 36610fdcc79885..ed2f9434539efe 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 93e17d24f58d29..38a228d50a8e0f 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.7.0-prerelease", + "version": "2.7.0", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 275843061ba832..89acde8f2b1245 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/package.json b/packages/dom/package.json index 25bec8b42cf5c4..dd05677fcb9303 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 07ff68cbb10174..1bb80bc4cc7643 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.7.0-prerelease", + "version": "1.7.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index 6974d0e4dc7e26..02cee410f33d66 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.7.0-prerelease", + "version": "11.7.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 20dd8753011535..81e7fa1802c65b 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.7.0-prerelease", + "version": "8.7.0", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 5965a0348b98b1..0d8e0b28f7c7c5 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.7.0-prerelease", + "version": "8.7.0", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 1678b16c194eb7..43bcf68aa68e68 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.7.0-prerelease", + "version": "6.7.0", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index c7616de2090b8d..d24857f0f8a0ce 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.7.0-prerelease", + "version": "6.7.0", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/package.json b/packages/editor/package.json index 6405b55693853b..a9d486b74e79cf 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.7.0-prerelease", + "version": "14.7.0", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/package.json b/packages/element/package.json index ef9c1d64a4d18b..d6062abe6ecf61 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.7.0-prerelease", + "version": "6.7.0", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/package.json b/packages/env/package.json index 0b1c76a1627da9..7f3b15b1e15622 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.7.0-prerelease", + "version": "10.7.0", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 08513c1cdb711a..8dd1a66cf2d5e9 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.7.0-prerelease", + "version": "3.7.0", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index fb756e3788ca76..73996275c9154f 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "21.0.0-prerelease", + "version": "21.0.0", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/package.json b/packages/format-library/package.json index b3ca6bcb187954..780f513bdb0374 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/package.json b/packages/hooks/package.json index c74488d78c3d16..51074af0d239b0 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index a6fea5015d93cc..30e3c1728307d7 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 2ea131d18b7597..fb3c488c1a4dea 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/package.json b/packages/icons/package.json index 24473645663673..ab23fef8eff667 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.7.0-prerelease", + "version": "10.7.0", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 796581950866ca..53b68068c528a0 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.7.0-prerelease", + "version": "2.7.0", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index a81a87549f07bc..3e29d9aabeeab9 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.7.0-prerelease", + "version": "6.7.0", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/package.json b/packages/interface/package.json index e4397f72ac730d..d15d648eaef446 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "6.7.0-prerelease", + "version": "6.7.0", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 7851c57b8e625d..553c3182bb5668 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 28005427da2e43..4381a0f287235f 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.7.0-prerelease", + "version": "8.7.0", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index c1daabe124076f..27638c711d4d1e 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.7.0-prerelease", + "version": "12.7.0", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 1d7a5c582d0070..b8ccbfcd36beff 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.7.0-prerelease", + "version": "7.7.0", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index f7968035b42d81..dd560424b66ff7 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 8d5a55a39977fe..5d8ec0545d7e3f 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index d668e2e30517c8..62aab79635e9c4 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.7.0-prerelease", + "version": "2.7.0", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index be97fc57765b19..839532327faa24 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index a52150dc88d0b4..b1737ff39e4bcd 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/package.json b/packages/notices/package.json index 43e684393915de..a4e2c5ea8d98c1 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index f8d10f9e9f4505..ad88e3fd442a1d 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/package.json b/packages/nux/package.json index 0449093f6ba13c..7a8e565d163aa2 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.7.0-prerelease", + "version": "9.7.0", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 9cd2ae339da9f4..6d67aa7ef3ac9e 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.7.0-prerelease", + "version": "2.7.0", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 7c18507d16863b..9cc58fc5096be2 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.7.0-prerelease", + "version": "7.7.0", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 4d13e9ccf4bfc5..d012dde494958e 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index 5350bc7d021a25..29e617382161ed 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.7.0-prerelease", + "version": "6.7.0", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index df7863073795ca..a318979abed2a1 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.7.0-prerelease", + "version": "2.7.0", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/package.json b/packages/preferences/package.json index 93cc4d653ece1a..5b12d274af30ae 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 87aff7454f9f56..f6c7797f2b6e7f 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 91467745a06300..8296c6348e9bef 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index cbca16771ae351..c8d7cbe1cebb9a 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.7.0-prerelease", + "version": "3.7.0", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index ff31a9533bdb70..3a3dd1aeab5706 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.7.0-prerelease", + "version": "1.7.0", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 0a6a938ebfc3ce..2e33d7c44d6cf4 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.7.0-prerelease", + "version": "2.7.0", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index d2ddf5a66ed4dd..d39fc7bba4ba5e 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index 894363c76f1221..285bcc27ba0a62 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.7.0-prerelease", + "version": "3.7.0", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 5a88268219c263..1efebcb92de7f8 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 971b1a9b2c44e7..8c15057189dc9a 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index ace76b50432c88..a5a96c77175c1f 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.7.0-prerelease", + "version": "7.7.0", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/package.json b/packages/router/package.json index 3498ff54c05157..bcc709bbac5d30 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.7.0-prerelease", + "version": "1.7.0", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index e7a461d72a87ce..35547682ae32b3 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "29.0.0-prerelease", + "version": "29.0.0", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index 30948ce80270e4..9ace449e3fe966 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.7.0-prerelease", + "version": "5.7.0", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index 867dc0eba27fd4..10e368d06c9955 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 0e2fd9d8287610..982ac1c1fa89db 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.7.0-prerelease", + "version": "2.7.0", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 54b79e2775d327..19e6f19bfd2f87 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "22.7.0-prerelease", + "version": "22.7.0", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/package.json b/packages/sync/package.json index f6bf88d7057662..ba8c433e880c3b 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.7.0-prerelease", + "version": "1.7.0", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 84d22c0cc4051d..1a06b76ccb111b 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.7.0-prerelease", + "version": "3.7.0", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 1d3a169cab8cd2..4574d94f46d7e1 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.7.0-prerelease", + "version": "1.7.0", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/package.json b/packages/url/package.json index c9fa20ac37d13a..c8360c81008fa2 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/package.json b/packages/viewport/package.json index c228846712d662..69fe9c8695c6ce 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.7.0-prerelease", + "version": "6.7.0", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/package.json b/packages/warning/package.json index e57af47a84ae4d..1095d2efd75621 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.7.0-prerelease", + "version": "3.7.0", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 70192ecd36bf79..595bad0f733652 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index 5ea29a55d5062c..4f6fe750e3fad6 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 13af7fd1958ff5dcd7e28f6b7c7b7d280a39ae51 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 5 Sep 2024 09:23:27 +0400 Subject: [PATCH 0692/1908] Pattern: Remove unused method returned from 'mapSelect' (#65073) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- packages/block-library/src/block/edit.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/block-library/src/block/edit.js b/packages/block-library/src/block/edit.js index af9c99876e9d20..5c90361e6bb435 100644 --- a/packages/block-library/src/block/edit.js +++ b/packages/block-library/src/block/edit.js @@ -194,19 +194,15 @@ function ReusableBlockEdit( { hasPatternOverridesSource, } = useSelect( ( select ) => { - const { - getBlocks, - getSettings, - getBlockEditingMode: _getBlockEditingMode, - } = select( blockEditorStore ); + const { getBlocks, getSettings, getBlockEditingMode } = + select( blockEditorStore ); const { getBlockBindingsSource } = unlock( select( blocksStore ) ); // For editing link to the site editor if the theme and user permissions support it. return { innerBlocks: getBlocks( patternClientId ), - getBlockEditingMode: _getBlockEditingMode, onNavigateToEntityRecord: getSettings().onNavigateToEntityRecord, - editingMode: _getBlockEditingMode( patternClientId ), + editingMode: getBlockEditingMode( patternClientId ), hasPatternOverridesSource: !! getBlockBindingsSource( 'core/pattern-overrides' ), From 3d8b6e549c41003c5cb70b1e4e83aa2d65a6dce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Thu, 5 Sep 2024 09:30:12 +0200 Subject: [PATCH 0693/1908] DataViews storybook: better styles for combined fields story (#65078) --- .../src/components/dataviews/stories/fixtures.tsx | 10 +++++++++- .../src/components/dataviews/stories/index.story.tsx | 7 +++++++ .../src/components/dataviews/stories/style.css | 4 ++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 packages/dataviews/src/components/dataviews/stories/style.css diff --git a/packages/dataviews/src/components/dataviews/stories/fixtures.tsx b/packages/dataviews/src/components/dataviews/stories/fixtures.tsx index 2ab02ec728e5e0..ff098209b34684 100644 --- a/packages/dataviews/src/components/dataviews/stories/fixtures.tsx +++ b/packages/dataviews/src/components/dataviews/stories/fixtures.tsx @@ -547,7 +547,15 @@ export const themeData: Theme[] = [ export const themeFields: Field< Theme >[] = [ { id: 'slug', label: 'Slug' }, { id: 'name', label: 'Name' }, - { id: 'description', label: 'Description' }, + { + id: 'description', + label: 'Description', + render: ( { item } ) => ( + <span className="theme-field-description"> + { item.description } + </span> + ), + }, { id: 'requires', label: 'Requires at least' }, { id: 'tested', label: 'Tested up to' }, { diff --git a/packages/dataviews/src/components/dataviews/stories/index.story.tsx b/packages/dataviews/src/components/dataviews/stories/index.story.tsx index 645c6d7ddcd922..8d5c0aabd5eb73 100644 --- a/packages/dataviews/src/components/dataviews/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataviews/stories/index.story.tsx @@ -19,6 +19,8 @@ import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../../../constants'; import { filterSortAndPaginate } from '../../../filter-and-sort-data-view'; import type { View } from '../../../types'; +import './style.css'; + const meta = { title: 'DataViews/DataViews', component: DataViews, @@ -144,6 +146,11 @@ export const CombinedFields = () => { direction: 'vertical', }, ], + styles: { + theme: { + maxWidth: 300, + }, + }, }, } ); const { data: shownData, paginationInfo } = useMemo( () => { diff --git a/packages/dataviews/src/components/dataviews/stories/style.css b/packages/dataviews/src/components/dataviews/stories/style.css new file mode 100644 index 00000000000000..7c0c6565a6edf4 --- /dev/null +++ b/packages/dataviews/src/components/dataviews/stories/style.css @@ -0,0 +1,4 @@ +.theme-field-description { + text-wrap: balance; + text-wrap: pretty; +} \ No newline at end of file From 29e344c51f6f3073bbccfbbac16cf9ac5031f1b4 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 5 Sep 2024 09:49:17 +0200 Subject: [PATCH 0694/1908] Composite: remove store prop and useCompositeStore hook (#64723) * Composite: remove store prop and useCompositeStore hook Instead, expose props directly on top-level component * Add tsx extension to context * Update usage examples * Update legacy implementation * Remove from private APIs * Update and simplify Storybook * Obfuscate store type in Composite context * Remove store prop from Composite * Update README * Update comment * Add Context subcomponent to Storybook * Inherit default story args in each story * CHANGELOG * Add SlotFillProvider to Storybook code snippet * Add extra comment to the context store * Better `rtl` default value and docs --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/composite/README.md | 25 +- .../src/composite/{context.ts => context.tsx} | 3 +- .../components/src/composite/group-label.tsx | 2 +- packages/components/src/composite/group.tsx | 2 +- packages/components/src/composite/hover.tsx | 2 +- packages/components/src/composite/index.tsx | 45 +-- packages/components/src/composite/item.tsx | 2 +- .../components/src/composite/legacy/index.tsx | 10 +- packages/components/src/composite/row.tsx | 2 +- packages/components/src/composite/store.ts | 46 --- .../src/composite/stories/index.story.tsx | 351 +++++++++--------- .../src/composite/stories/utils.tsx | 76 ---- .../components/src/composite/typeahead.tsx | 2 +- packages/components/src/composite/types.ts | 28 +- packages/components/src/private-apis.ts | 2 - packages/components/src/slot-fill/index.tsx | 1 + .../dataviews-filters/search-widget.tsx | 3 +- 18 files changed, 236 insertions(+), 367 deletions(-) rename packages/components/src/composite/{context.ts => context.tsx} (75%) delete mode 100644 packages/components/src/composite/store.ts delete mode 100644 packages/components/src/composite/stories/utils.tsx diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 535f49ae00b11c..699f63e94b9808 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -78,6 +78,7 @@ - `Composite` V2: fix Storybook docgen ([#64682](https://github.com/WordPress/gutenberg/pull/64682)). - `Composite` V2: add "With Slot Fill" example ([#65051](https://github.com/WordPress/gutenberg/pull/65051)). - `Composite` V2: accept store props on top-level component ([#64832](https://github.com/WordPress/gutenberg/pull/64832)). +- `Composite` V2: remove `store` prop and `useCompositeStore` hook ([#64723](https://github.com/WordPress/gutenberg/pull/64723)). ## 28.6.0 (2024-08-21) diff --git a/packages/components/src/composite/README.md b/packages/components/src/composite/README.md index 35881d815cf1bc..bde28d4fbbfe8b 100644 --- a/packages/components/src/composite/README.md +++ b/packages/components/src/composite/README.md @@ -9,10 +9,9 @@ This feature is still experimental. “Experimental” means this is an early im ## Usage ```jsx -import { Composite, useCompositeStore } from '@wordpress/components'; +import { Composite } from '@wordpress/components'; -const store = useCompositeStore(); -<Composite store={store}> +<Composite> <Composite.Group> <Composite.GroupLabel>Label</Composite.GroupLabel> <Composite.Item>Item 1</Composite.Item> @@ -21,11 +20,11 @@ const store = useCompositeStore(); </Composite> ``` -## Hooks +## Components -### `useCompositeStore` +### `Composite` -Creates a composite store. +Renders a composite widget. #### Props @@ -131,20 +130,6 @@ This only affects the composite widget behavior. You still need to set `dir="rtl - Required: no - Default: `false` -## Components - -### `Composite` - -Renders a composite widget. - -#### Props - -##### `store`: `CompositeStore<CompositeStoreItem>` - -Object returned by the `useCompositeStore` hook. - -- Required: yes - ##### `render`: `RenderProp<React.HTMLAttributes<any> & { ref?: React.Ref<any> | undefined; }> | React.ReactElement<any, string | React.JSXElementConstructor<any>>` Allows the component to be rendered as a different HTML element or React component. The value can be a React element or a function that takes in the original component props and gives back a React element with the props merged. diff --git a/packages/components/src/composite/context.ts b/packages/components/src/composite/context.tsx similarity index 75% rename from packages/components/src/composite/context.ts rename to packages/components/src/composite/context.tsx index 69a052c5bfba19..4a8b22a712b031 100644 --- a/packages/components/src/composite/context.ts +++ b/packages/components/src/composite/context.tsx @@ -8,7 +8,6 @@ import { createContext, useContext } from '@wordpress/element'; */ import type { CompositeContextProps } from './types'; -export const CompositeContext = - createContext< CompositeContextProps >( undefined ); +export const CompositeContext = createContext< CompositeContextProps >( {} ); export const useCompositeContext = () => useContext( CompositeContext ); diff --git a/packages/components/src/composite/group-label.tsx b/packages/components/src/composite/group-label.tsx index 26d043cd0a1400..17070dbb86bf81 100644 --- a/packages/components/src/composite/group-label.tsx +++ b/packages/components/src/composite/group-label.tsx @@ -22,7 +22,7 @@ export const CompositeGroupLabel = forwardRef< const context = useCompositeContext(); return ( <Ariakit.CompositeGroupLabel - store={ context?.store } + store={ context.store as Ariakit.CompositeStore } { ...props } ref={ ref } /> diff --git a/packages/components/src/composite/group.tsx b/packages/components/src/composite/group.tsx index a6b1b8b3f5254a..ae21ca6f11dd92 100644 --- a/packages/components/src/composite/group.tsx +++ b/packages/components/src/composite/group.tsx @@ -22,7 +22,7 @@ export const CompositeGroup = forwardRef< const context = useCompositeContext(); return ( <Ariakit.CompositeGroup - store={ context?.store } + store={ context.store as Ariakit.CompositeStore } { ...props } ref={ ref } /> diff --git a/packages/components/src/composite/hover.tsx b/packages/components/src/composite/hover.tsx index 76a240e0767009..ca0bd9d8f6aa12 100644 --- a/packages/components/src/composite/hover.tsx +++ b/packages/components/src/composite/hover.tsx @@ -22,7 +22,7 @@ export const CompositeHover = forwardRef< const context = useCompositeContext(); return ( <Ariakit.CompositeHover - store={ context?.store } + store={ context.store as Ariakit.CompositeStore } { ...props } ref={ ref } /> diff --git a/packages/components/src/composite/index.tsx b/packages/components/src/composite/index.tsx index 629010d271e811..e9e97072261fbf 100644 --- a/packages/components/src/composite/index.tsx +++ b/packages/components/src/composite/index.tsx @@ -16,6 +16,7 @@ import * as Ariakit from '@ariakit/react'; /** * WordPress dependencies */ +import { isRTL } from '@wordpress/i18n'; import { useMemo, forwardRef } from '@wordpress/element'; /** @@ -38,10 +39,9 @@ import type { CompositeProps } from './types'; * * @example * ```jsx - * import { Composite, useCompositeStore } from '@wordpress/components'; + * import { Composite } from '@wordpress/components'; * - * const store = useCompositeStore(); - * <Composite store={store}> + * <Composite> * <Composite.Item>Item 1</Composite.Item> * <Composite.Item>Item 2</Composite.Item> * </Composite> @@ -62,21 +62,18 @@ export const Composite = Object.assign( focusShift = false, virtualFocus = false, orientation = 'both', - rtl = false, + rtl = isRTL(), // Composite component props children, disabled = false, - // To be removed - store: storeProp, - // Rest props ...props }, ref ) { - const newStore = Ariakit.useCompositeStore( { + const store = Ariakit.useCompositeStore( { activeId, defaultActiveId, setActiveId, @@ -88,8 +85,6 @@ export const Composite = Object.assign( rtl, } ); - const store = storeProp || newStore; - const contextValue = useMemo( () => ( { store, @@ -116,10 +111,9 @@ export const Composite = Object.assign( * * @example * ```jsx - * import { Composite, useCompositeStore } from '@wordpress/components'; + * import { Composite } from '@wordpress/components'; * - * const store = useCompositeStore(); - * <Composite store={store}> + * <Composite> * <Composite.Group> * <Composite.GroupLabel>Label</Composite.GroupLabel> * <Composite.Item>Item 1</Composite.Item> @@ -138,10 +132,9 @@ export const Composite = Object.assign( * * @example * ```jsx - * import { Composite, useCompositeStore } from '@wordpress/components'; + * import { Composite } from '@wordpress/components'; * - * const store = useCompositeStore(); - * <Composite store={store}> + * <Composite> * <Composite.Group> * <Composite.GroupLabel>Label</Composite.GroupLabel> * <Composite.Item>Item 1</Composite.Item> @@ -158,10 +151,9 @@ export const Composite = Object.assign( * * @example * ```jsx - * import { Composite, useCompositeStore } from '@wordpress/components'; + * import { Composite } from '@wordpress/components'; * - * const store = useCompositeStore(); - * <Composite store={store}> + * <Composite> * <Composite.Item>Item 1</Composite.Item> * <Composite.Item>Item 2</Composite.Item> * <Composite.Item>Item 3</Composite.Item> @@ -176,10 +168,9 @@ export const Composite = Object.assign( * * @example * ```jsx - * import { Composite, useCompositeStore } from '@wordpress/components'; + * import { Composite } from '@wordpress/components'; * - * const store = useCompositeStore(); - * <Composite store={store}> + * <Composite> * <Composite.Row> * <Composite.Item>Item 1.1</Composite.Item> * <Composite.Item>Item 1.2</Composite.Item> @@ -201,10 +192,9 @@ export const Composite = Object.assign( * * @example * ```jsx - * import { Composite, useCompositeStore } from '@wordpress/components'; + * import { Composite } from '@wordpress/components'; * - * const store = useCompositeStore(); - * <Composite store={store}> + * <Composite> * <Composite.Hover render={ <Composite.Item /> }> * Item 1 * </Composite.Hover> @@ -224,10 +214,9 @@ export const Composite = Object.assign( * * @example * ```jsx - * import { Composite, useCompositeStore } from '@wordpress/components'; + * import { Composite } from '@wordpress/components'; * - * const store = useCompositeStore(); - * <Composite store={store} render={ <CompositeTypeahead /> }> + * <Composite render={ <CompositeTypeahead /> }> * <Composite.Item>Item 1</Composite.Item> * <Composite.Item>Item 2</Composite.Item> * </Composite> diff --git a/packages/components/src/composite/item.tsx b/packages/components/src/composite/item.tsx index 8067c222c1c97f..6d75b90f0baaaa 100644 --- a/packages/components/src/composite/item.tsx +++ b/packages/components/src/composite/item.tsx @@ -22,7 +22,7 @@ export const CompositeItem = forwardRef< const context = useCompositeContext(); return ( <Ariakit.CompositeItem - store={ context?.store } + store={ context.store as Ariakit.CompositeStore } { ...props } ref={ ref } /> diff --git a/packages/components/src/composite/legacy/index.tsx b/packages/components/src/composite/legacy/index.tsx index 41ecc6ceb3f66b..cff564af1f8e7a 100644 --- a/packages/components/src/composite/legacy/index.tsx +++ b/packages/components/src/composite/legacy/index.tsx @@ -13,6 +13,11 @@ * @see https://ariakit.org/components/composite */ +/** + * External dependencies + */ +import * as Ariakit from '@ariakit/react'; + /** * WordPress dependencies */ @@ -22,7 +27,6 @@ import { forwardRef } from '@wordpress/element'; * Internal dependencies */ import { Composite as Current } from '..'; -import { useCompositeStore } from '../store'; import { useInstanceId } from '@wordpress/compose'; type Orientation = 'horizontal' | 'vertical'; @@ -79,7 +83,7 @@ export interface LegacyStateOptions { type Component = React.FunctionComponent< any >; -type CompositeStore = ReturnType< typeof useCompositeStore >; +type CompositeStore = ReturnType< typeof Ariakit.useCompositeStore >; type CompositeStoreState = { store: CompositeStore }; export type CompositeState = CompositeStoreState & Required< Pick< LegacyStateOptions, 'baseId' > >; @@ -180,7 +184,7 @@ export function useCompositeState( return { baseId: useInstanceId( Composite, 'composite', baseId ), - store: useCompositeStore( { + store: Ariakit.useCompositeStore( { defaultActiveId, rtl, orientation, diff --git a/packages/components/src/composite/row.tsx b/packages/components/src/composite/row.tsx index cbb9f80045de76..a082af03ad6785 100644 --- a/packages/components/src/composite/row.tsx +++ b/packages/components/src/composite/row.tsx @@ -22,7 +22,7 @@ export const CompositeRow = forwardRef< const context = useCompositeContext(); return ( <Ariakit.CompositeRow - store={ context?.store } + store={ context.store as Ariakit.CompositeStore } { ...props } ref={ ref } /> diff --git a/packages/components/src/composite/store.ts b/packages/components/src/composite/store.ts deleted file mode 100644 index acf24b96cb8128..00000000000000 --- a/packages/components/src/composite/store.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** - * External dependencies - */ -import * as Ariakit from '@ariakit/react'; - -/** - * Internal dependencies - */ -import type { CompositeStoreProps } from './types'; - -// Props are already documented in TypeScript types. -// eslint-disable-next-line jsdoc/require-param -/** - * Creates a composite store. - * - * @example - * ```jsx - * import { Composite, useCompositeStore } from '@wordpress/components'; - * - * const store = useCompositeStore(); - * <Composite store={store}> - * <Composite.Item>Item</Composite.Item> - * <Composite.Item>Item</Composite.Item> - * <Composite.Item>Item</Composite.Item> - * </Composite> - * ``` - */ -export function useCompositeStore( { - focusLoop = false, - focusWrap = false, - focusShift = false, - virtualFocus = false, - orientation = 'both', - rtl = false, - ...props -}: CompositeStoreProps = {} ) { - return Ariakit.useCompositeStore( { - focusLoop, - focusWrap, - focusShift, - virtualFocus, - orientation, - rtl, - ...props, - } ); -} diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx index 2fdec079255490..b8552840d66cf1 100644 --- a/packages/components/src/composite/stories/index.story.tsx +++ b/packages/components/src/composite/stories/index.story.tsx @@ -1,12 +1,11 @@ /** * External dependencies */ -import type { Meta, StoryFn, StoryContext } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react'; /** * WordPress dependencies */ -import { isRTL } from '@wordpress/i18n'; import { useContext, useMemo } from '@wordpress/element'; /** @@ -14,15 +13,11 @@ import { useContext, useMemo } from '@wordpress/element'; */ import { createSlotFill, Provider as SlotFillProvider } from '../../slot-fill'; import { Composite } from '..'; -import { useCompositeStore } from '../store'; -import { UseCompositeStorePlaceholder, transform } from './utils'; -const meta: Meta< typeof UseCompositeStorePlaceholder > = { +const meta: Meta< typeof Composite > = { title: 'Components/Composite (V2)', - component: UseCompositeStorePlaceholder, + component: Composite, subcomponents: { - // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - Composite, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 'Composite.Group': Composite.Group, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 @@ -35,8 +30,12 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { 'Composite.Hover': Composite.Hover, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 'Composite.Typeahead': Composite.Typeahead, + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + 'Composite.Context': Composite.Context, }, argTypes: { + children: { control: { type: null } }, + render: { control: { type: null } }, setActiveId: { control: { type: null } }, focusLoop: { control: 'select', @@ -52,7 +51,6 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { controls: { expanded: true }, docs: { canvas: { sourceState: 'shown' }, - source: { transform }, }, }, decorators: [ @@ -93,116 +91,111 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { }; export default meta; -export const Default: StoryFn< typeof UseCompositeStorePlaceholder > = ( - storeProps -) => { - const rtl = isRTL(); - const store = useCompositeStore( { rtl, ...storeProps } ); - - return ( - <Composite store={ store }> - <Composite.Item>Item one</Composite.Item> - <Composite.Item>Item two</Composite.Item> - <Composite.Item>Item three</Composite.Item> - </Composite> - ); +export const Default: StoryObj< typeof Composite > = { + args: { + children: ( + <> + <Composite.Item>Item one</Composite.Item> + <Composite.Item>Item two</Composite.Item> + <Composite.Item>Item three</Composite.Item> + </> + ), + }, }; -export const Groups: StoryFn< typeof UseCompositeStorePlaceholder > = ( - storeProps -) => { - const rtl = isRTL(); - const store = useCompositeStore( { rtl, ...storeProps } ); - - return ( - <Composite store={ store }> - <Composite.Group> - <Composite.GroupLabel>Group one</Composite.GroupLabel> - <Composite.Item>Item 1.1</Composite.Item> - <Composite.Item>Item 1.2</Composite.Item> - </Composite.Group> - <Composite.Group> - <Composite.GroupLabel>Group two</Composite.GroupLabel> - <Composite.Item>Item 2.1</Composite.Item> - <Composite.Item>Item 2.1</Composite.Item> - </Composite.Group> - </Composite> - ); +export const Groups: StoryObj< typeof Composite > = { + ...Default, + args: { + ...Default.args, + children: ( + <> + <Composite.Group> + <Composite.GroupLabel>Group one</Composite.GroupLabel> + <Composite.Item>Item 1.1</Composite.Item> + <Composite.Item>Item 1.2</Composite.Item> + </Composite.Group> + <Composite.Group> + <Composite.GroupLabel>Group two</Composite.GroupLabel> + <Composite.Item>Item 2.1</Composite.Item> + <Composite.Item>Item 2.1</Composite.Item> + </Composite.Group> + </> + ), + }, }; -export const Grid: StoryFn< typeof UseCompositeStorePlaceholder > = ( - storeProps -) => { - const rtl = isRTL(); - const store = useCompositeStore( { rtl, ...storeProps } ); - - return ( - <Composite role="grid" store={ store } aria-label="Composite"> - <Composite.Row role="row"> - <Composite.Item role="gridcell">Item A1</Composite.Item> - <Composite.Item role="gridcell">Item A2</Composite.Item> - <Composite.Item role="gridcell">Item A3</Composite.Item> - </Composite.Row> - <Composite.Row role="row"> - <Composite.Item role="gridcell">Item B1</Composite.Item> - <Composite.Item role="gridcell">Item B2</Composite.Item> - <Composite.Item role="gridcell">Item B3</Composite.Item> - </Composite.Row> - <Composite.Row role="row"> - <Composite.Item role="gridcell">Item C1</Composite.Item> - <Composite.Item role="gridcell">Item C2</Composite.Item> - <Composite.Item role="gridcell">Item C3</Composite.Item> - </Composite.Row> - </Composite> - ); +export const Grid: StoryObj< typeof Composite > = { + ...Default, + args: { + ...Default.args, + role: 'grid', + 'aria-label': 'Composite', + children: ( + <> + <Composite.Row role="row"> + <Composite.Item role="gridcell">Item A1</Composite.Item> + <Composite.Item role="gridcell">Item A2</Composite.Item> + <Composite.Item role="gridcell">Item A3</Composite.Item> + </Composite.Row> + <Composite.Row role="row"> + <Composite.Item role="gridcell">Item B1</Composite.Item> + <Composite.Item role="gridcell">Item B2</Composite.Item> + <Composite.Item role="gridcell">Item B3</Composite.Item> + </Composite.Row> + <Composite.Row role="row"> + <Composite.Item role="gridcell">Item C1</Composite.Item> + <Composite.Item role="gridcell">Item C2</Composite.Item> + <Composite.Item role="gridcell">Item C3</Composite.Item> + </Composite.Row> + </> + ), + }, }; -export const Hover: StoryFn< typeof UseCompositeStorePlaceholder > = ( - storeProps -) => { - const rtl = isRTL(); - const store = useCompositeStore( { rtl, ...storeProps } ); - - return ( - <Composite store={ store }> - <Composite.Hover render={ <Composite.Item /> }> - Hover item one - </Composite.Hover> - <Composite.Hover render={ <Composite.Item /> }> - Hover item two - </Composite.Hover> - <Composite.Hover render={ <Composite.Item /> }> - Hover item three - </Composite.Hover> - </Composite> - ); -}; -Hover.parameters = { - docs: { - description: { - story: 'Elements in the composite widget will receive focus on mouse move and lose focus to the composite base element on mouse leave.', +export const Hover: StoryObj< typeof Composite > = { + ...Default, + args: { + ...Default.args, + children: ( + <> + <Composite.Hover render={ <Composite.Item /> }> + Hover item one + </Composite.Hover> + <Composite.Hover render={ <Composite.Item /> }> + Hover item two + </Composite.Hover> + <Composite.Hover render={ <Composite.Item /> }> + Hover item three + </Composite.Hover> + </> + ), + }, + parameters: { + docs: { + description: { + story: 'Elements in the composite widget will receive focus on mouse move and lose focus to the composite base element on mouse leave.', + }, }, }, }; -export const Typeahead: StoryFn< typeof UseCompositeStorePlaceholder > = ( - storeProps -) => { - const rtl = isRTL(); - const store = useCompositeStore( { rtl, ...storeProps } ); - - return ( - <Composite store={ store } render={ <Composite.Typeahead /> }> - <Composite.Item>Apple</Composite.Item> - <Composite.Item>Banana</Composite.Item> - <Composite.Item>Peach</Composite.Item> - </Composite> - ); -}; -Typeahead.parameters = { - docs: { - description: { - story: 'When focus in on the composite widget, hitting printable character keys will move focus to the next composite item that begins with the input characters.', +export const Typeahead: StoryObj< typeof Composite > = { + args: { + ...Default.args, + render: <Composite.Typeahead />, + children: ( + <> + <Composite.Item>Apple</Composite.Item> + <Composite.Item>Banana</Composite.Item> + <Composite.Item>Peach</Composite.Item> + </> + ), + }, + parameters: { + docs: { + description: { + story: 'When focus in on the composite widget, hitting printable character keys will move focus to the next composite item that begins with the input characters.', + }, }, }, }; @@ -257,82 +250,106 @@ const Fill = ( { children }: { children: React.ReactNode } ) => { ); }; -export const WithSlotFill: StoryFn< typeof UseCompositeStorePlaceholder > = ( - props -) => { - return ( - <SlotFillProvider> - <Composite { ...props }> +export const WithSlotFill: StoryObj< typeof Composite > = { + ...Default, + args: { + ...Default.args, + children: ( + <> <Composite.Item>Item one (direct child)</Composite.Item> <Slot /> <Composite.Item>Item four (direct child)</Composite.Item> - </Composite> + </> + ), + }, + decorators: [ + ( Story ) => { + return ( + <SlotFillProvider> + <Story /> - <Fill> - <Composite.Item>Item two (from slot fill)</Composite.Item> - <Composite.Item>Item three (from slot fill)</Composite.Item> - </Fill> - </SlotFillProvider> - ); -}; -WithSlotFill.args = { - ...Default.args, -}; -WithSlotFill.parameters = { - docs: { - description: { - story: 'When rendering Composite components across a SlotFill, the Composite.Context should be manually forwarded from the Slot to the Fill component.', + <Fill> + <Composite.Item> + Item two (from slot fill) + </Composite.Item> + <Composite.Item> + Item three (from slot fill) + </Composite.Item> + </Fill> + </SlotFillProvider> + ); }, - source: { - transform: ( code: string, storyContext: StoryContext ) => { - return `const ExampleSlotFill = createSlotFill( 'Example' ); + ], + parameters: { + docs: { + description: { + story: 'When rendering Composite components across a SlotFill, the Composite.Context should be manually forwarded from the Slot to the Fill component.', + }, + source: { + transform: ( code: string ) => { + return `const ExampleSlotFill = createSlotFill( 'Example' ); const Slot = () => { - const compositeContext = useContext( Composite.Context ); + const compositeContext = useContext( Composite.Context ); - // Forward the Slot's composite context to the Fill via fillProps, so that - // Composite components rendered inside the Fill can work as expected. - const fillProps = useMemo( - () => ( { - forwardedContext: [ - [ Composite.Context.Provider, { value: compositeContext } ], - ], - } ), - [ compositeContext ] - ); + // Forward the Slot's composite context to the Fill via fillProps, so that + // Composite components rendered inside the Fill can work as expected. + const fillProps = useMemo( + () => ( { + forwardedContext: [ + [ Composite.Context.Provider, { value: compositeContext } ], + ], + } ), + [ compositeContext ] + ); - return ( - <ExampleSlotFill.Slot - fillProps={ fillProps } - bubblesVirtually - style={ { display: 'contents' } } - /> - ); + return ( + <ExampleSlotFill.Slot + fillProps={ fillProps } + bubblesVirtually + style={ { display: 'contents' } } + /> + ); }; const Fill = ( { children } ) => { - const innerMarkup = <>{ children }</>; + const innerMarkup = <>{ children }</>; - return ( - <ExampleSlotFill.Fill> - { ( fillProps ) => { - const { forwardedContext = [] } = fillProps; + return ( + <ExampleSlotFill.Fill> + { ( fillProps ) => { + const { forwardedContext = [] } = fillProps; - // Render all context providers forwarded by the Slot via fillProps. - return forwardedContext.reduce( - ( inner, [ Provider, props ] ) => ( - <Provider { ...props }>{ inner }</Provider> - ), - innerMarkup - ); - } } - </ExampleSlotFill.Fill> - ); + // Render all context providers forwarded by the Slot via fillProps. + return forwardedContext.reduce( + ( inner, [ Provider, props ] ) => ( + <Provider { ...props }>{ inner }</Provider> + ), + innerMarkup + ); + } } + </ExampleSlotFill.Fill> + ); }; // In a separate component: -${ transform( code, storyContext ) }`; +<SlotFillProvider> + ${ + // Add one level of indentation to match the surrounding code. + code.replaceAll( '\n', '\n ' ) + } + + <Fill> + <Composite.Item> + Item two (from slot fill) + </Composite.Item> + <Composite.Item> + Item three (from slot fill) + </Composite.Item> + </Fill> +</SlotFillProvider>`; + }, }, }, }, diff --git a/packages/components/src/composite/stories/utils.tsx b/packages/components/src/composite/stories/utils.tsx deleted file mode 100644 index f2f197877ff76d..00000000000000 --- a/packages/components/src/composite/stories/utils.tsx +++ /dev/null @@ -1,76 +0,0 @@ -/** - * External dependencies - */ -import type { StoryContext } from '@storybook/react'; - -/** - * Internal dependencies - */ -import type { CompositeStoreProps } from '../types'; - -/** - * Renders a widget based on the WAI-ARIA [`composite`](https://w3c.github.io/aria/#composite) - * role, which provides a single tab stop on the page and arrow key navigation - * through the focusable descendants. - * - * ```jsx - * import { Composite, useCompositeStore } from '@wordpress/components'; - * - * const store = useCompositeStore(); - * <Composite store={ store }> - * <Composite.Item>Item 1</Composite.Item> - * <Composite.Item>Item 2</Composite.Item> - * </Composite> - * ``` - */ -export function UseCompositeStorePlaceholder( props: CompositeStoreProps ) { - return ( - <dl> - { Object.entries( props ).map( ( [ name, value ] ) => ( - <> - <dt>{ name }</dt> - <dd>{ JSON.stringify( value ) }</dd> - </> - ) ) } - </dl> - ); -} -UseCompositeStorePlaceholder.displayName = 'useCompositeStore'; - -// The output generated by Storybook for these components is -// messy, so we apply this transform to make it more useful -// for anyone reading the docs. -export function transform( code: string, context: StoryContext ) { - const storeConfig = ` ${ JSON.stringify( context.args, null, 2 ) } `; - const formattedStoreConfig = storeConfig.replace( ' {} ', '' ); - return [ - // Include a setup line, showing how to make use of - // `useCompositeStore` to convert store options into - // a composite store prop. - `const store = useCompositeStore(${ formattedStoreConfig });`, - '', - 'return (', - ' ' + - code - // The generated output includes a full dump of everything - // in the store; the reader probably isn't interested in - // what that looks like, so instead we drop all of that - // in favor of the store generated above. - .replaceAll( /store=\{\{[\s\S]*?\}\}/g, 'store={ store }' ) - // Now we tidy the output by removing any unnecessary - // whitespace... - .replaceAll( /<Composite\w+[\s\S]*?>/g, ( match ) => - match.replaceAll( /\s+\s/g, ' ' ) - ) - // ...including around <Composite*> children... - .replaceAll( - />\s*(\w[\w ]*?)\s*<\//g, - ( _, value ) => `>${ value }</` - ) - // ...and inside JSX definitions. - .replaceAll( '} >', '}>' ) - // Finally we indent everything to make it more readable. - .replaceAll( /\n/g, '\n ' ), - ');', - ].join( '\n' ); -} diff --git a/packages/components/src/composite/typeahead.tsx b/packages/components/src/composite/typeahead.tsx index d5bb7e6e2e4cc5..771d58bcb6c25c 100644 --- a/packages/components/src/composite/typeahead.tsx +++ b/packages/components/src/composite/typeahead.tsx @@ -22,7 +22,7 @@ export const CompositeTypeahead = forwardRef< const context = useCompositeContext(); return ( <Ariakit.CompositeTypeahead - store={ context?.store } + store={ context.store as Ariakit.CompositeStore } { ...props } ref={ ref } /> diff --git a/packages/components/src/composite/types.ts b/packages/components/src/composite/types.ts index fcde842e1cba77..ed95c7f0253b33 100644 --- a/packages/components/src/composite/types.ts +++ b/packages/components/src/composite/types.ts @@ -3,16 +3,18 @@ */ import type * as Ariakit from '@ariakit/react'; -export type CompositeContextProps = - | { - /** - * Object returned by the `useCompositeStore` hook. - */ - store: Ariakit.CompositeStore; - } - | undefined; +export type CompositeContextProps = { + /** + * The component store, used for advanced usage of the component. + * + * _Note: Using the store directly is not recommended. Instead, use the props + * exposed by the `Composite` component._ + * + */ + store?: unknown; +}; -export type CompositeStoreProps = { +type CompositeStoreProps = { /** * The current active item `id`. The active item is the element within the * composite widget that has either DOM or virtual focus (in case @@ -117,22 +119,18 @@ export type CompositeStoreProps = { */ orientation?: Ariakit.CompositeStoreProps[ 'orientation' ]; /** - * Determines how the `store`'s `next` and `previous` functions will behave. + * Controls how the previous and next items are determined. * If `rtl` is set to `true`, they will be inverted. * * This only affects the composite widget behavior. You still need to set * `dir="rtl"` on HTML/CSS. * - * @default false + * @default `isRtl()` */ rtl?: Ariakit.CompositeStoreProps[ 'rtl' ]; }; export type CompositeProps = CompositeStoreProps & { - /** - * Object returned by the `useCompositeStore` hook. - */ - store?: Ariakit.CompositeStore; /** * Allows the component to be rendered as a different HTML element or React * component. The value can be a React element or a function that takes in the diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index 7bcab0e052e022..b4e4b3a16d4ff9 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -2,7 +2,6 @@ * Internal dependencies */ import { Composite } from './composite'; -import { useCompositeStore } from './composite/store'; import { positionToPlacement as __experimentalPopoverLegacyPositionToPlacement } from './popover/utils'; import { createPrivateSlotFill } from './slot-fill'; import { DropdownMenuV2 } from './dropdown-menu-v2'; @@ -20,7 +19,6 @@ lock( privateApis, { CompositeRowV2: Composite.Row, CompositeTypeaheadV2: Composite.Typeahead, CompositeHoverV2: Composite.Hover, - useCompositeStoreV2: useCompositeStore, __experimentalPopoverLegacyPositionToPlacement, createPrivateSlotFill, ComponentsContext, diff --git a/packages/components/src/slot-fill/index.tsx b/packages/components/src/slot-fill/index.tsx index b2df054973a5ba..03ed33a67f13b6 100644 --- a/packages/components/src/slot-fill/index.tsx +++ b/packages/components/src/slot-fill/index.tsx @@ -71,6 +71,7 @@ export function Provider( { </SlotFillProvider> ); } +Provider.displayName = 'SlotFillProvider'; export function createSlotFill( key: SlotKey ) { const baseName = typeof key === 'symbol' ? key.description : key; diff --git a/packages/dataviews/src/components/dataviews-filters/search-widget.tsx b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx index 24ef3b5594b413..c11c789218cd1e 100644 --- a/packages/dataviews/src/components/dataviews-filters/search-widget.tsx +++ b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx @@ -126,8 +126,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) { ) } onFocusVisible={ () => { // `onFocusVisible` needs the `Composite` component to be focusable, - // which is implicitly achieved via the `virtualFocus: true` option - // in the `useCompositeStore` hook. + // which is implicitly achieved via the `virtualFocus` prop. if ( ! activeCompositeId && filter.elements.length ) { setActiveCompositeId( generateFilterElementCompositeItemId( From 90a7c7e49bb79204b8745610bc691dfce51aeeae Mon Sep 17 00:00:00 2001 From: Kai Hao <kevin830726@gmail.com> Date: Thu, 5 Sep 2024 15:51:36 +0800 Subject: [PATCH 0695/1908] Allow dropping multiple images to the image block (#65030) co-authored-by: kevin940726 <kevin940726@git.wordpress.org>Co-authored-by: ramonjd <ramonopoly@git.wordpress.org>Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>Co-authored-by: andrewserong <andrewserong@git.wordpress.org>Co-authored-by: swissspidy <swissspidy@git.wordpress.org>Co-authored-by: richtabor <richtabor@git.wordpress.org> * Allow dropping multiple images to the image block * Check for canInsert and file type * Separate the list callback --- .../components/media-placeholder/README.md | 4 +- .../src/components/media-placeholder/index.js | 5 +- packages/block-library/src/image/edit.js | 63 +++++++++++++++++-- packages/block-library/src/image/utils.js | 14 ++++- 4 files changed, 77 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/components/media-placeholder/README.md b/packages/block-editor/src/components/media-placeholder/README.md index 6cb00206d93d72..68fcf150c4edc4 100644 --- a/packages/block-editor/src/components/media-placeholder/README.md +++ b/packages/block-editor/src/components/media-placeholder/README.md @@ -198,9 +198,9 @@ Callback called when urls can be configured. No media insertion from url will be ### handleUpload -When set to false the handling of the upload is left to the calling component. +When the value is set to `false` or returned as `false`, the handling of the upload is left to the consumer component. The function signature accepts an array containing the files to be uploaded. -- Type: `Boolean` +- Type: `Boolean|Function` - Required: No - Default: `true` - Platform: Web diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index a5b4eb0bf19b3f..bbf546a3953f32 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -172,7 +172,10 @@ export function MediaPlaceholder( { }; const onFilesUpload = ( files ) => { - if ( ! handleUpload ) { + if ( + ! handleUpload || + ( typeof handleUpload === 'function' && ! handleUpload( files ) ) + ) { return onSelect( files ); } onFilesPreUpload( files ); diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index b7c25595dcfccf..ae8461a6b1cf4c 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -6,8 +6,8 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { isBlobURL } from '@wordpress/blob'; -import { store as blocksStore } from '@wordpress/blocks'; +import { isBlobURL, createBlobURL } from '@wordpress/blob'; +import { store as blocksStore, createBlock } from '@wordpress/blocks'; import { Placeholder } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; import { @@ -31,6 +31,7 @@ import { useResizeObserver } from '@wordpress/compose'; import { unlock } from '../lock-unlock'; import { useUploadMediaFromBlobURL } from '../utils/hooks'; import Image from './image'; +import { isValidFileType } from './utils'; /** * Module constants @@ -109,6 +110,7 @@ export function ImageEdit( { metadata, } = attributes; const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob ); + const figureRef = useRef(); const [ contentResizeListener, { width: containerWidth } ] = useResizeObserver(); @@ -123,7 +125,7 @@ export function ImageEdit( { captionRef.current = caption; }, [ caption ] ); - const { __unstableMarkNextChangeAsNotPersistent } = + const { __unstableMarkNextChangeAsNotPersistent, replaceBlock } = useDispatch( blockEditorStore ); useEffect( () => { @@ -138,7 +140,12 @@ export function ImageEdit( { } }, [ __unstableMarkNextChangeAsNotPersistent, align, setAttributes ] ); - const { getSettings } = useSelect( blockEditorStore ); + const { + getSettings, + getBlockRootClientId, + getBlockName, + canInsertBlockType, + } = useSelect( blockEditorStore ); const blockEditingMode = useBlockEditingMode(); const { createErrorNotice } = useDispatch( noticesStore ); @@ -152,7 +159,52 @@ export function ImageEdit( { } ); } + function onSelectImagesList( images ) { + const win = figureRef.current?.ownerDocument.defaultView; + + if ( images.every( ( file ) => file instanceof win.File ) ) { + /** @type {File[]} */ + const files = images; + const rootClientId = getBlockRootClientId( clientId ); + + if ( files.some( ( file ) => ! isValidFileType( file ) ) ) { + // Copied from the same notice in the gallery block. + createErrorNotice( + __( + 'If uploading to a gallery all files need to be image formats' + ), + { id: 'gallery-upload-invalid-file', type: 'snackbar' } + ); + } + + const imageBlocks = files + .filter( ( file ) => isValidFileType( file ) ) + .map( ( file ) => + createBlock( 'core/image', { + blob: createBlobURL( file ), + } ) + ); + + if ( getBlockName( rootClientId ) === 'core/gallery' ) { + replaceBlock( clientId, imageBlocks ); + } else if ( canInsertBlockType( 'core/gallery', rootClientId ) ) { + const galleryBlock = createBlock( + 'core/gallery', + {}, + imageBlocks + ); + + replaceBlock( clientId, galleryBlock ); + } + } + } + function onSelectImage( media ) { + if ( Array.isArray( media ) ) { + onSelectImagesList( media ); + return; + } + if ( ! media || ! media.url ) { setAttributes( { url: undefined, @@ -296,7 +348,7 @@ export function ImageEdit( { Object.keys( borderProps.style ).length > 0 ), } ); - const blockProps = useBlockProps( { className: classes } ); + const blockProps = useBlockProps( { ref: figureRef, className: classes } ); // Much of this description is duplicated from MediaPlaceholder. const { lockUrlControls = false, lockUrlControlsMessage } = useSelect( @@ -394,6 +446,7 @@ export function ImageEdit( { placeholder={ placeholder } accept="image/*" allowedTypes={ ALLOWED_MEDIA_TYPES } + handleUpload={ ( files ) => files.length === 1 } value={ { id, src } } mediaPreview={ mediaPreview } disableMediaButtons={ temporaryURL || url } diff --git a/packages/block-library/src/image/utils.js b/packages/block-library/src/image/utils.js index 1ef7973b4e57a3..1541c3daac3aab 100644 --- a/packages/block-library/src/image/utils.js +++ b/packages/block-library/src/image/utils.js @@ -1,7 +1,7 @@ /** * Internal dependencies */ -import { NEW_TAB_REL } from './constants'; +import { NEW_TAB_REL, ALLOWED_MEDIA_TYPES } from './constants'; /** * Evaluates a CSS aspect-ratio property value as a number. @@ -81,3 +81,15 @@ export function getImageSizeAttributes( image, size ) { return {}; } + +/** + * Checks if the file has a valid file type. + * + * @param {File} file - The file to check. + * @return {boolean} - Returns true if the file has a valid file type, otherwise false. + */ +export function isValidFileType( file ) { + return ALLOWED_MEDIA_TYPES.some( + ( mediaType ) => file.type.indexOf( mediaType ) === 0 + ); +} From 1d2f1759e28c04d2cf4f76446e033a5ef23c65c5 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 5 Sep 2024 12:48:18 +0400 Subject: [PATCH 0696/1908] Core Data: Fix the 'query._fields' property check inside 'getEntityRecord' resolver (#65079) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/core-data/src/resolvers.js | 2 +- packages/core-data/src/test/resolvers.js | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index d1aaf0b447cfed..20270ef7f6cff5 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -155,7 +155,7 @@ export const getEntityRecord = } ); - if ( query !== undefined ) { + if ( query !== undefined && query._fields ) { query = { ...query, include: [ key ] }; // The resolution cache won't consider query as reusable based on the diff --git a/packages/core-data/src/test/resolvers.js b/packages/core-data/src/test/resolvers.js index 946b795726d2a2..f15bee3b3c2b9b 100644 --- a/packages/core-data/src/test/resolvers.js +++ b/packages/core-data/src/test/resolvers.js @@ -80,7 +80,6 @@ describe( 'getEntityRecord', () => { it( 'accepts a query that overrides default api path', async () => { const query = { context: 'view', _envelope: '1' }; - const queryObj = { include: [ 'post' ], ...query }; const select = { hasEntityRecords: jest.fn( () => {} ), @@ -98,13 +97,6 @@ describe( 'getEntityRecord', () => { query )( { dispatch, select, registry } ); - // Check resolution cache for an existing entity that fulfills the request with query. - expect( select.hasEntityRecords ).toHaveBeenCalledWith( - 'root', - 'postType', - queryObj - ); - // Trigger apiFetch, test that the query is present in the url. expect( triggerFetch ).toHaveBeenCalledWith( { path: '/wp/v2/types/post?context=view&_envelope=1', @@ -116,7 +108,7 @@ describe( 'getEntityRecord', () => { 'root', 'postType', POST_TYPE, - queryObj + query ); // Locks should have been acquired and released. From 05a12ebe7357e7ee12d921953a07fb51b87f31db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Thu, 5 Sep 2024 11:14:03 +0200 Subject: [PATCH 0697/1908] DataViews: enable all layouts for combined fields storybook (#65082) --- .../dataviews/stories/index.story.tsx | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/packages/dataviews/src/components/dataviews/stories/index.story.tsx b/packages/dataviews/src/components/dataviews/stories/index.story.tsx index 8d5c0aabd5eb73..3b3e1326115b0e 100644 --- a/packages/dataviews/src/components/dataviews/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataviews/stories/index.story.tsx @@ -17,7 +17,7 @@ import { } from './fixtures'; import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../../../constants'; import { filterSortAndPaginate } from '../../../filter-and-sort-data-view'; -import type { View } from '../../../types'; +import type { CombinedField, View } from '../../../types'; import './style.css'; @@ -134,24 +134,39 @@ export const FieldsNoSortableNoHidable = () => { }; export const CombinedFields = () => { - const [ view, setView ] = useState< View >( { - ...DEFAULT_VIEW, - fields: [ 'theme', 'requires', 'tested' ], - layout: { - combinedFields: [ - { - id: 'theme', - label: 'Theme', - children: [ 'name', 'description' ], - direction: 'vertical', - }, - ], - styles: { - theme: { - maxWidth: 300, + const defaultLayoutsThemes = { + table: { + fields: [ 'theme', 'requires', 'tested' ], + layout: { + primaryField: 'name', + combinedFields: [ + { + id: 'theme', + label: 'Theme', + children: [ 'name', 'description' ], + direction: 'vertical', + }, + ] as CombinedField[], + styles: { + theme: { + maxWidth: 300, + }, }, }, }, + grid: { + fields: [ 'description', 'requires', 'tested' ], + layout: { primaryField: 'name', columnFields: [ 'description' ] }, + }, + list: { + fields: [ 'requires', 'tested' ], + layout: { primaryField: 'name' }, + }, + }; + const [ view, setView ] = useState< View >( { + ...DEFAULT_VIEW, + fields: defaultLayoutsThemes.table.fields, + layout: defaultLayoutsThemes.table.layout, } ); const { data: shownData, paginationInfo } = useMemo( () => { return filterSortAndPaginate( themeData, view, themeFields ); @@ -165,7 +180,7 @@ export const CombinedFields = () => { view={ view } fields={ themeFields } onChangeView={ setView } - defaultLayouts={ { table: {} } } + defaultLayouts={ defaultLayoutsThemes } /> ); }; From 7cf62f7e55edab0386f01795f7217c9dc06ba032 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 5 Sep 2024 14:00:34 +0200 Subject: [PATCH 0698/1908] Composite: stabilize APIs (#63569) * Use public export instead of private API * Remove Composite from private APIs * Refactor previously missed occurrences * CHANGELOG * Update CHANGELOG * Export Composite as public component * Fix ref type * Update CHANGELOG * Update Storybook * Remove experimental callout in README --- .../downloadable-block-list-item/index.js | 9 +++---- .../downloadable-blocks-list/index.js | 4 +-- .../components/block-pattern-setup/index.js | 14 +++------- .../components/block-patterns-list/index.js | 11 +++----- .../pattern-transformations-menu.js | 11 +++----- .../global-styles/shadow-panel-components.js | 12 ++------- .../src/components/inserter-listbox/index.js | 5 +--- .../src/components/inserter-listbox/item.js | 16 +++--------- .../src/components/inserter-listbox/row.js | 11 ++------ .../inserter/media-tab/media-list.js | 5 +--- .../inserter/media-tab/media-preview.js | 9 +++---- packages/components/CHANGELOG.md | 8 ++++++ packages/components/src/composite/README.md | 4 --- .../composite/legacy/stories/index.story.tsx | 3 ++- .../src/composite/stories/index.story.tsx | 3 +-- packages/components/src/index.ts | 1 + packages/components/src/private-apis.ts | 7 ----- .../dataviews-filters/search-widget.tsx | 22 ++++------------ .../src/dataviews-layouts/list/index.tsx | 26 ++++++++----------- .../add-custom-template-modal-content.js | 11 +++----- .../src/components/style-book/index.js | 11 +++----- 21 files changed, 60 insertions(+), 143 deletions(-) diff --git a/packages/block-directory/src/components/downloadable-block-list-item/index.js b/packages/block-directory/src/components/downloadable-block-list-item/index.js index 45a2930ad656e3..ac587dc2d6d0cc 100644 --- a/packages/block-directory/src/components/downloadable-block-list-item/index.js +++ b/packages/block-directory/src/components/downloadable-block-list-item/index.js @@ -6,7 +6,7 @@ import { Button, Spinner, VisuallyHidden, - privateApis as componentsPrivateApis, + Composite, } from '@wordpress/components'; import { createInterpolateElement } from '@wordpress/element'; import { decodeEntities } from '@wordpress/html-entities'; @@ -20,9 +20,6 @@ import BlockRatings from '../block-ratings'; import DownloadableBlockIcon from '../downloadable-block-icon'; import DownloadableBlockNotice from '../downloadable-block-notice'; import { store as blockDirectoryStore } from '../../store'; -import { unlock } from '../../lock-unlock'; - -const { CompositeItemV2: CompositeItem } = unlock( componentsPrivateApis ); // Return the appropriate block item label, given the block data and status. function getDownloadableBlockLabel( @@ -93,7 +90,7 @@ function DownloadableBlockListItem( { item, onClick } ) { } return ( - <CompositeItem + <Composite.Item render={ <Button // TODO: Switch to `true` (40px size) if possible @@ -162,7 +159,7 @@ function DownloadableBlockListItem( { item, onClick } ) { </> ) } </span> - </CompositeItem> + </Composite.Item> ); } diff --git a/packages/block-directory/src/components/downloadable-blocks-list/index.js b/packages/block-directory/src/components/downloadable-blocks-list/index.js index 3911c3297376db..3e44aa423bfa5e 100644 --- a/packages/block-directory/src/components/downloadable-blocks-list/index.js +++ b/packages/block-directory/src/components/downloadable-blocks-list/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { privateApis as componentsPrivateApis } from '@wordpress/components'; +import { Composite } from '@wordpress/components'; import { getBlockType } from '@wordpress/blocks'; import { useDispatch } from '@wordpress/data'; @@ -11,9 +11,7 @@ import { useDispatch } from '@wordpress/data'; */ import DownloadableBlockListItem from '../downloadable-block-list-item'; import { store as blockDirectoryStore } from '../../store'; -import { unlock } from '../../lock-unlock'; -const { CompositeV2: Composite } = unlock( componentsPrivateApis ); const noop = () => {}; function DownloadableBlocksList( { items, onHover = noop, onSelect } ) { diff --git a/packages/block-editor/src/components/block-pattern-setup/index.js b/packages/block-editor/src/components/block-pattern-setup/index.js index 6ec3f79b5f703b..83cceca7a20a79 100644 --- a/packages/block-editor/src/components/block-pattern-setup/index.js +++ b/packages/block-editor/src/components/block-pattern-setup/index.js @@ -3,10 +3,7 @@ */ import { useDispatch } from '@wordpress/data'; import { cloneBlock } from '@wordpress/blocks'; -import { - VisuallyHidden, - privateApis as componentsPrivateApis, -} from '@wordpress/components'; +import { Composite, VisuallyHidden } from '@wordpress/components'; import { useState } from '@wordpress/element'; import { useInstanceId } from '@wordpress/compose'; @@ -20,11 +17,6 @@ import BlockPreview from '../block-preview'; import SetupToolbar from './setup-toolbar'; import usePatternsSetup from './use-patterns-setup'; import { VIEWMODES } from './constants'; -import { unlock } from '../../lock-unlock'; - -const { CompositeV2: Composite, CompositeItemV2: CompositeItem } = unlock( - componentsPrivateApis -); const SetupContent = ( { viewMode, @@ -88,7 +80,7 @@ function BlockPattern( { pattern, onSelect, showTitles } ) { ); return ( <div className={ `${ baseClassName }__list-item` }> - <CompositeItem + <Composite.Item render={ <div aria-describedby={ @@ -116,7 +108,7 @@ function BlockPattern( { pattern, onSelect, showTitles } ) { { description } </VisuallyHidden> ) } - </CompositeItem> + </Composite.Item> </div> ); } diff --git a/packages/block-editor/src/components/block-patterns-list/index.js b/packages/block-editor/src/components/block-patterns-list/index.js index 47deb777a84aab..2609cc2db97a13 100644 --- a/packages/block-editor/src/components/block-patterns-list/index.js +++ b/packages/block-editor/src/components/block-patterns-list/index.js @@ -9,9 +9,9 @@ import clsx from 'clsx'; import { cloneBlock } from '@wordpress/blocks'; import { useEffect, useState, forwardRef, useMemo } from '@wordpress/element'; import { + Composite, VisuallyHidden, Tooltip, - privateApis as componentsPrivateApis, __experimentalHStack as HStack, } from '@wordpress/components'; import { useInstanceId } from '@wordpress/compose'; @@ -21,16 +21,11 @@ import { Icon, symbol } from '@wordpress/icons'; /** * Internal dependencies */ -import { unlock } from '../../lock-unlock'; import BlockPreview from '../block-preview'; import InserterDraggableBlocks from '../inserter-draggable-blocks'; import BlockPatternsPaging from '../block-patterns-paging'; import { INSERTER_PATTERN_TYPES } from '../inserter/block-patterns-tab/utils'; -const { CompositeV2: Composite, CompositeItemV2: CompositeItem } = unlock( - componentsPrivateApis -); - const WithToolTip = ( { showTooltip, title, children } ) => { if ( showTooltip ) { return <Tooltip text={ title }>{ children }</Tooltip>; @@ -105,7 +100,7 @@ function BlockPattern( { } title={ pattern.title } > - <CompositeItem + <Composite.Item render={ <div role="option" @@ -174,7 +169,7 @@ function BlockPattern( { { pattern.description } </VisuallyHidden> ) } - </CompositeItem> + </Composite.Item> </WithToolTip> </div> ) } diff --git a/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js b/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js index c2e7fa88a879be..7d66e19a214a28 100644 --- a/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js +++ b/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js @@ -7,11 +7,11 @@ import { useInstanceId, useViewportMatch } from '@wordpress/compose'; import { chevronRight } from '@wordpress/icons'; import { + Composite, MenuGroup, MenuItem, Popover, VisuallyHidden, - privateApis as componentsPrivateApis, } from '@wordpress/components'; /** @@ -19,11 +19,6 @@ import { */ import BlockPreview from '../block-preview'; import useTransformedPatterns from './use-transformed-patterns'; -import { unlock } from '../../lock-unlock'; - -const { CompositeV2: Composite, CompositeItemV2: CompositeItem } = unlock( - componentsPrivateApis -); function PatternTransformationsMenu( { blocks, @@ -107,7 +102,7 @@ function BlockPattern( { pattern, onSelect } ) { ); return ( <div className={ `${ baseClassName }-list__list-item` }> - <CompositeItem + <Composite.Item render={ <div role="option" @@ -127,7 +122,7 @@ function BlockPattern( { pattern, onSelect } ) { <div className={ `${ baseClassName }-list__item-title` }> { pattern.title } </div> - </CompositeItem> + </Composite.Item> { !! pattern.description && ( <VisuallyHidden id={ descriptionId }> { pattern.description } diff --git a/packages/block-editor/src/components/global-styles/shadow-panel-components.js b/packages/block-editor/src/components/global-styles/shadow-panel-components.js index 0f30f769f7b102..1ed367e3c3ad0e 100644 --- a/packages/block-editor/src/components/global-styles/shadow-panel-components.js +++ b/packages/block-editor/src/components/global-styles/shadow-panel-components.js @@ -10,7 +10,7 @@ import { Button, FlexItem, Dropdown, - privateApis as componentsPrivateApis, + Composite, } from '@wordpress/components'; import { useMemo } from '@wordpress/element'; import { shadow as shadowIcon, Icon, check } from '@wordpress/icons'; @@ -20,11 +20,6 @@ import { shadow as shadowIcon, Icon, check } from '@wordpress/icons'; */ import clsx from 'clsx'; -/** - * Internal dependencies - */ -import { unlock } from '../../lock-unlock'; - /** * Shared reference to an empty array for cases where it is important to avoid * returning a new array reference on every invocation. @@ -32,9 +27,6 @@ import { unlock } from '../../lock-unlock'; * @type {Array} */ const EMPTY_ARRAY = []; -const { CompositeItemV2: CompositeItem, CompositeV2: Composite } = unlock( - componentsPrivateApis -); export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) { const shadows = useShadowPresets( settings ); @@ -88,7 +80,7 @@ export function ShadowPresets( { presets, activeShadow, onSelect } ) { export function ShadowIndicator( { type, label, isActive, onSelect, shadow } ) { return ( - <CompositeItem + <Composite.Item role="option" aria-label={ label } aria-selected={ isActive } diff --git a/packages/block-editor/src/components/inserter-listbox/index.js b/packages/block-editor/src/components/inserter-listbox/index.js index f1168f67fd6113..bc833b0e4c36b1 100644 --- a/packages/block-editor/src/components/inserter-listbox/index.js +++ b/packages/block-editor/src/components/inserter-listbox/index.js @@ -1,19 +1,16 @@ /** * WordPress dependencies */ -import { privateApis as componentsPrivateApis } from '@wordpress/components'; +import { Composite } from '@wordpress/components'; /** * Internal dependencies */ -import { unlock } from '../../lock-unlock'; export { default as InserterListboxGroup } from './group'; export { default as InserterListboxRow } from './row'; export { default as InserterListboxItem } from './item'; -const { CompositeV2: Composite } = unlock( componentsPrivateApis ); - function InserterListbox( { children } ) { return ( <Composite focusShift focusWrap="horizontal" render={ <></> }> diff --git a/packages/block-editor/src/components/inserter-listbox/item.js b/packages/block-editor/src/components/inserter-listbox/item.js index 825c3fdfc353c6..69c316bdbbccef 100644 --- a/packages/block-editor/src/components/inserter-listbox/item.js +++ b/packages/block-editor/src/components/inserter-listbox/item.js @@ -1,28 +1,18 @@ /** * WordPress dependencies */ -import { - Button, - privateApis as componentsPrivateApis, -} from '@wordpress/components'; +import { Button, Composite } from '@wordpress/components'; import { forwardRef } from '@wordpress/element'; -/** - * Internal dependencies - */ -import { unlock } from '../../lock-unlock'; - -const { CompositeItemV2: CompositeItem } = unlock( componentsPrivateApis ); - function InserterListboxItem( { isFirst, as: Component, children, ...props }, ref ) { return ( - <CompositeItem + <Composite.Item ref={ ref } role="option" - // Use the CompositeItem `accessibleWhenDisabled` prop + // Use the Composite.Item `accessibleWhenDisabled` prop // over Button's `isFocusable`. The latter was shown to // cause an issue with tab order in the inserter list. accessibleWhenDisabled diff --git a/packages/block-editor/src/components/inserter-listbox/row.js b/packages/block-editor/src/components/inserter-listbox/row.js index f9827f08b3fa39..bafdbf8f5593c1 100644 --- a/packages/block-editor/src/components/inserter-listbox/row.js +++ b/packages/block-editor/src/components/inserter-listbox/row.js @@ -2,17 +2,10 @@ * WordPress dependencies */ import { forwardRef } from '@wordpress/element'; -import { privateApis as componentsPrivateApis } from '@wordpress/components'; - -/** - * Internal dependencies - */ -import { unlock } from '../../lock-unlock'; - -const { CompositeGroupV2: CompositeGroup } = unlock( componentsPrivateApis ); +import { Composite } from '@wordpress/components'; function InserterListboxRow( props, ref ) { - return <CompositeGroup role="presentation" ref={ ref } { ...props } />; + return <Composite.Group role="presentation" ref={ ref } { ...props } />; } export default forwardRef( InserterListboxRow ); diff --git a/packages/block-editor/src/components/inserter/media-tab/media-list.js b/packages/block-editor/src/components/inserter/media-tab/media-list.js index 9d03b3086176f0..73f38cfc306fbc 100644 --- a/packages/block-editor/src/components/inserter/media-tab/media-list.js +++ b/packages/block-editor/src/components/inserter/media-tab/media-list.js @@ -1,16 +1,13 @@ /** * WordPress dependencies */ -import { privateApis as componentsPrivateApis } from '@wordpress/components'; +import { Composite } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ import { MediaPreview } from './media-preview'; -import { unlock } from '../../../lock-unlock'; - -const { CompositeV2: Composite } = unlock( componentsPrivateApis ); function MediaList( { mediaList, diff --git a/packages/block-editor/src/components/inserter/media-tab/media-preview.js b/packages/block-editor/src/components/inserter/media-tab/media-preview.js index be0058fe022118..4416b710302cef 100644 --- a/packages/block-editor/src/components/inserter/media-tab/media-preview.js +++ b/packages/block-editor/src/components/inserter/media-tab/media-preview.js @@ -16,7 +16,7 @@ import { Flex, FlexItem, Button, - privateApis as componentsPrivateApis, + Composite, __experimentalVStack as VStack, } from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; @@ -33,7 +33,6 @@ import { isBlobURL } from '@wordpress/blob'; import InserterDraggableBlocks from '../../inserter-draggable-blocks'; import { getBlockAndPreviewFromMedia } from './utils'; import { store as blockEditorStore } from '../../../store'; -import { unlock } from '../../../lock-unlock'; const ALLOWED_MEDIA_TYPES = [ 'image' ]; const MAXIMUM_TITLE_LENGTH = 25; @@ -43,8 +42,6 @@ const MEDIA_OPTIONS_POPOVER_PROPS = { 'block-editor-inserter__media-list__item-preview-options__popover', }; -const { CompositeItemV2: CompositeItem } = unlock( componentsPrivateApis ); - function MediaPreviewOptions( { category, media } ) { if ( ! category.getReportUrl ) { return null; @@ -249,7 +246,7 @@ export function MediaPreview( { media, onClick, category } ) { onMouseLeave={ onMouseLeave } > <Tooltip text={ truncatedTitle || title }> - <CompositeItem + <Composite.Item render={ <div aria-label={ title } @@ -267,7 +264,7 @@ export function MediaPreview( { media, onClick, category } ) { </div> ) } </div> - </CompositeItem> + </Composite.Item> </Tooltip> { ! isInserting && ( <MediaPreviewOptions diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 699f63e94b9808..499a3b69c06a2b 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,14 @@ ## Unreleased +### New Features + +- `Composite`: add stable version of the component ([#63569](https://github.com/WordPress/gutenberg/pull/63569)). + +### Internal + +- `Composite`: Remove from private APIs ([#63569](https://github.com/WordPress/gutenberg/pull/63569)). + ## 28.7.0 (2024-09-05) ### Deprecations diff --git a/packages/components/src/composite/README.md b/packages/components/src/composite/README.md index bde28d4fbbfe8b..de710bd2ab6272 100644 --- a/packages/components/src/composite/README.md +++ b/packages/components/src/composite/README.md @@ -1,9 +1,5 @@ # `Composite` -<div class="callout callout-alert"> -This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. -</div> - `Composite` provides a single tab stop on the page and allows navigation through the focusable descendants with arrow keys. This abstract component is based on the [WAI-ARIA Composite Role⁠](https://w3c.github.io/aria/#composite). ## Usage diff --git a/packages/components/src/composite/legacy/stories/index.story.tsx b/packages/components/src/composite/legacy/stories/index.story.tsx index e46d656a16810e..1b8e07e9bbf560 100644 --- a/packages/components/src/composite/legacy/stories/index.story.tsx +++ b/packages/components/src/composite/legacy/stories/index.story.tsx @@ -15,7 +15,8 @@ import { import { UseCompositeStatePlaceholder, transform } from './utils'; const meta: Meta< typeof UseCompositeStatePlaceholder > = { - title: 'Components/Composite', + title: 'Components (Deprecated)/Composite (Unstable)', + id: 'components-composite-unstable', component: UseCompositeStatePlaceholder, subcomponents: { Composite, diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx index b8552840d66cf1..d6e4999407e993 100644 --- a/packages/components/src/composite/stories/index.story.tsx +++ b/packages/components/src/composite/stories/index.story.tsx @@ -15,7 +15,7 @@ import { createSlotFill, Provider as SlotFillProvider } from '../../slot-fill'; import { Composite } from '..'; const meta: Meta< typeof Composite > = { - title: 'Components/Composite (V2)', + title: 'Components/Composite', component: Composite, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 @@ -46,7 +46,6 @@ const meta: Meta< typeof Composite > = { options: [ true, false, 'horizontal', 'vertical', 'both' ], }, }, - tags: [ 'status-private' ], parameters: { controls: { expanded: true }, docs: { diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index 3ddfbd05cd6581..32195ebc444ce6 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -66,6 +66,7 @@ export { CompositeItem as __unstableCompositeItem, useCompositeState as __unstableUseCompositeState, } from './composite/legacy'; +export { Composite } from './composite'; export { ConfirmDialog as __experimentalConfirmDialog } from './confirm-dialog'; export { default as CustomSelectControl } from './custom-select-control'; export { default as Dashicon } from './dashicon'; diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index b4e4b3a16d4ff9..b6e033ab24ab74 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -1,7 +1,6 @@ /** * Internal dependencies */ -import { Composite } from './composite'; import { positionToPlacement as __experimentalPopoverLegacyPositionToPlacement } from './popover/utils'; import { createPrivateSlotFill } from './slot-fill'; import { DropdownMenuV2 } from './dropdown-menu-v2'; @@ -13,12 +12,6 @@ import { lock } from './lock-unlock'; export const privateApis = {}; lock( privateApis, { - CompositeV2: Composite, - CompositeGroupV2: Composite.Group, - CompositeItemV2: Composite.Item, - CompositeRowV2: Composite.Row, - CompositeTypeaheadV2: Composite.Typeahead, - CompositeHoverV2: Composite.Hover, __experimentalPopoverLegacyPositionToPlacement, createPrivateSlotFill, ComponentsContext, diff --git a/packages/dataviews/src/components/dataviews-filters/search-widget.tsx b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx index c11c789218cd1e..459b68990753c1 100644 --- a/packages/dataviews/src/components/dataviews-filters/search-widget.tsx +++ b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx @@ -11,27 +11,15 @@ import removeAccents from 'remove-accents'; import { useInstanceId } from '@wordpress/compose'; import { __, sprintf } from '@wordpress/i18n'; import { useState, useMemo, useDeferredValue } from '@wordpress/element'; -import { - VisuallyHidden, - Icon, - privateApis as componentsPrivateApis, -} from '@wordpress/components'; +import { VisuallyHidden, Icon, Composite } from '@wordpress/components'; import { search, check } from '@wordpress/icons'; import { SVG, Circle } from '@wordpress/primitives'; /** * Internal dependencies */ -import { unlock } from '../../lock-unlock'; import type { Filter, NormalizedFilter, View } from '../../types'; -const { - CompositeV2: Composite, - CompositeItemV2: CompositeItem, - CompositeHoverV2: CompositeHover, - CompositeTypeaheadV2: CompositeTypeahead, -} = unlock( componentsPrivateApis ); - interface SearchWidgetProps { view: View; filter: NormalizedFilter; @@ -136,13 +124,13 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) { ); } } } - render={ <CompositeTypeahead /> } + render={ <Composite.Typeahead /> } > { filter.elements.map( ( element ) => ( - <CompositeHover + <Composite.Hover key={ element.value } render={ - <CompositeItem + <Composite.Item id={ generateFilterElementCompositeItemId( baseId, element.value @@ -212,7 +200,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) { ) } </span> <span>{ element.label }</span> - </CompositeHover> + </Composite.Hover> ) ) } </Composite> ); diff --git a/packages/dataviews/src/dataviews-layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx index 00146c3ee35220..8a3f6a297338c8 100644 --- a/packages/dataviews/src/dataviews-layouts/list/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/list/index.tsx @@ -14,6 +14,7 @@ import { privateApis as componentsPrivateApis, Spinner, VisuallyHidden, + Composite, } from '@wordpress/components'; import { useCallback, @@ -48,12 +49,7 @@ interface ListViewItemProps< Item > { onDropdownTriggerKeyDown: React.KeyboardEventHandler< HTMLButtonElement >; } -const { - CompositeV2: Composite, - CompositeItemV2: CompositeItem, - CompositeRowV2: CompositeRow, - DropdownMenuV2: DropdownMenu, -} = unlock( componentsPrivateApis ); +const { DropdownMenuV2: DropdownMenu } = unlock( componentsPrivateApis ); function generateItemWrapperCompositeId( idPrefix: string ) { return `${ idPrefix }-item-wrapper`; @@ -92,7 +88,7 @@ function PrimaryActionGridCell< Item >( { return 'RenderModal' in primaryAction ? ( <div role="gridcell" key={ primaryAction.id }> - <CompositeItem + <Composite.Item id={ compositeItemId } render={ <Button @@ -111,11 +107,11 @@ function PrimaryActionGridCell< Item >( { closeModal={ () => setIsModalOpen( false ) } /> ) } - </CompositeItem> + </Composite.Item> </div> ) : ( <div role="gridcell" key={ primaryAction.id }> - <CompositeItem + <Composite.Item id={ compositeItemId } render={ <Button @@ -144,7 +140,7 @@ function ListItem< Item >( { visibleFields, onDropdownTriggerKeyDown, }: ListViewItemProps< Item > ) { - const itemRef = useRef< HTMLElement >( null ); + const itemRef = useRef< HTMLDivElement >( null ); const labelId = `${ idPrefix }-label`; const descriptionId = `${ idPrefix }-description`; @@ -192,7 +188,7 @@ function ListItem< Item >( { ) : null; return ( - <CompositeRow + <Composite.Row ref={ itemRef } render={ <li /> } role="row" @@ -209,7 +205,7 @@ function ListItem< Item >( { spacing={ 0 } > <div role="gridcell"> - <CompositeItem + <Composite.Item render={ <div /> } role="button" id={ generateItemWrapperCompositeId( idPrefix ) } @@ -260,7 +256,7 @@ function ListItem< Item >( { </div> </VStack> </HStack> - </CompositeItem> + </Composite.Item> </div> { eligibleActions?.length > 0 && ( <HStack @@ -282,7 +278,7 @@ function ListItem< Item >( { <div role="gridcell"> <DropdownMenu trigger={ - <CompositeItem + <Composite.Item id={ generateDropdownTriggerCompositeId( idPrefix ) } @@ -311,7 +307,7 @@ function ListItem< Item >( { </HStack> ) } </HStack> - </CompositeRow> + </Composite.Row> ); } diff --git a/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js b/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js index f63a980954e36c..4993f12153b9e4 100644 --- a/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js +++ b/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js @@ -9,7 +9,7 @@ import { FlexItem, SearchControl, TextHighlight, - privateApis as componentsPrivateApis, + Composite, __experimentalText as Text, __experimentalVStack as VStack, } from '@wordpress/components'; @@ -20,13 +20,8 @@ import { useDebouncedInput } from '@wordpress/compose'; /** * Internal dependencies */ -import { unlock } from '../../lock-unlock'; import { mapToIHasNameAndId } from './utils'; -const { CompositeV2: Composite, CompositeItemV2: CompositeItem } = unlock( - componentsPrivateApis -); - const EMPTY_ARRAY = []; function SuggestionListItem( { @@ -38,7 +33,7 @@ function SuggestionListItem( { const baseCssClass = 'edit-site-custom-template-modal__suggestions_list__list-item'; return ( - <CompositeItem + <Composite.Item render={ <Button // TODO: Switch to `true` (40px size) if possible @@ -75,7 +70,7 @@ function SuggestionListItem( { { suggestion.link } </Text> ) } - </CompositeItem> + </Composite.Item> ); } diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index c4c2fa45d2bed7..64503dcf7a6dbb 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -8,6 +8,7 @@ import clsx from 'clsx'; */ import { Disabled, + Composite, privateApis as componentsPrivateApis, } from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; @@ -45,11 +46,7 @@ const { } = unlock( blockEditorPrivateApis ); const { mergeBaseAndUserConfigs } = unlock( editorPrivateApis ); -const { - CompositeV2: Composite, - CompositeItemV2: CompositeItem, - Tabs, -} = unlock( componentsPrivateApis ); +const { Tabs } = unlock( componentsPrivateApis ); // The content area of the Style Book is rendered within an iframe so that global styles // are applied to elements within the entire content area. To support elements that are @@ -433,7 +430,7 @@ const Example = ( { id, title, blocks, isSelected, onClick } ) => { return ( <div role="row"> <div role="gridcell"> - <CompositeItem + <Composite.Item className={ clsx( 'edit-site-style-book__example', { 'is-selected': isSelected, } ) } @@ -463,7 +460,7 @@ const Example = ( { id, title, blocks, isSelected, onClick } ) => { </ExperimentalBlockEditorProvider> </Disabled> </div> - </CompositeItem> + </Composite.Item> </div> </div> ); From 8b452c27f5858bdad67b3a7228d38aed515294a0 Mon Sep 17 00:00:00 2001 From: Rich Tabor <hi@richtabor.com> Date: Thu, 5 Sep 2024 08:31:45 -0400 Subject: [PATCH 0699/1908] Fix blurry edge along editor header with Distraction Free (#64277) * use box-shadow instead of border * revert post-preview break-mobile * Fix Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/block-editor/src/components/block-toolbar/style.scss | 2 +- packages/editor/src/components/header/style.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index 0c2ed94c01e3f0..98538d5d1d053d 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -70,7 +70,7 @@ // Raise the specificity. &.components-accessible-toolbar { border: none; - border-bottom: $border-width solid $gray-200; + box-shadow: 0 $border-width 0 0 rgba($color: #000, $alpha: 0.133); // 0.133 = $gray-200 but with alpha. border-radius: 0; } diff --git a/packages/editor/src/components/header/style.scss b/packages/editor/src/components/header/style.scss index 99c9cc70e166e4..8712121fff3ea6 100644 --- a/packages/editor/src/components/header/style.scss +++ b/packages/editor/src/components/header/style.scss @@ -243,7 +243,7 @@ width: 100%; @include break-medium { - border-bottom: 1px solid #e0e0e0; + box-shadow: 0 $border-width 0 0 rgba($color: #000, $alpha: 0.133); // 0.133 = $gray-200 but with alpha. position: absolute; } From f4cad964fb1c848f8fff98309b1f4f21aad4d456 Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Thu, 5 Sep 2024 16:01:54 +0200 Subject: [PATCH 0700/1908] Media Utils: Add TypeScript support and export more utils (#64784) Co-authored-by: Nik Tsekouras <ntsekouras@outlook.com> --- packages/editor/tsconfig.json | 1 + packages/media-utils/CHANGELOG.md | 4 + packages/media-utils/README.md | 71 +++++- packages/media-utils/package.json | 3 +- packages/media-utils/src/index.js | 2 - packages/media-utils/src/index.ts | 9 + .../src/utils/flatten-form-data.ts | 33 +++ .../src/utils/get-mime-types-array.ts | 29 +++ packages/media-utils/src/utils/index.js | 1 - .../src/utils/test/flatten-form-data.ts | 49 ++++ .../src/utils/test/get-mime-types-array.ts | 47 ++++ .../src/utils/test/upload-error.ts | 24 ++ .../{upload-media.test.js => upload-media.ts} | 123 ++++------ .../src/utils/test/validate-file-size.ts | 70 ++++++ .../utils/test/validate-mime-type-for-user.ts | 37 +++ .../src/utils/test/validate-mime-type.ts | 57 +++++ .../src/utils/transform-attachment.ts | 24 ++ packages/media-utils/src/utils/types.ts | 207 ++++++++++++++++ .../media-utils/src/utils/upload-error.ts | 26 ++ .../media-utils/src/utils/upload-media.js | 232 ------------------ .../media-utils/src/utils/upload-media.ts | 149 +++++++++++ .../media-utils/src/utils/upload-to-server.ts | 38 +++ .../src/utils/validate-file-size.ts | 44 ++++ .../src/utils/validate-mime-type-for-user.ts | 46 ++++ .../src/utils/validate-mime-type.ts | 43 ++++ packages/media-utils/tsconfig.json | 17 ++ tsconfig.json | 1 + 27 files changed, 1074 insertions(+), 313 deletions(-) delete mode 100644 packages/media-utils/src/index.js create mode 100644 packages/media-utils/src/index.ts create mode 100644 packages/media-utils/src/utils/flatten-form-data.ts create mode 100644 packages/media-utils/src/utils/get-mime-types-array.ts delete mode 100644 packages/media-utils/src/utils/index.js create mode 100644 packages/media-utils/src/utils/test/flatten-form-data.ts create mode 100644 packages/media-utils/src/utils/test/get-mime-types-array.ts create mode 100644 packages/media-utils/src/utils/test/upload-error.ts rename packages/media-utils/src/utils/test/{upload-media.test.js => upload-media.ts} (58%) create mode 100644 packages/media-utils/src/utils/test/validate-file-size.ts create mode 100644 packages/media-utils/src/utils/test/validate-mime-type-for-user.ts create mode 100644 packages/media-utils/src/utils/test/validate-mime-type.ts create mode 100644 packages/media-utils/src/utils/transform-attachment.ts create mode 100644 packages/media-utils/src/utils/types.ts create mode 100644 packages/media-utils/src/utils/upload-error.ts delete mode 100644 packages/media-utils/src/utils/upload-media.js create mode 100644 packages/media-utils/src/utils/upload-media.ts create mode 100644 packages/media-utils/src/utils/upload-to-server.ts create mode 100644 packages/media-utils/src/utils/validate-file-size.ts create mode 100644 packages/media-utils/src/utils/validate-mime-type-for-user.ts create mode 100644 packages/media-utils/src/utils/validate-mime-type.ts create mode 100644 packages/media-utils/tsconfig.json diff --git a/packages/editor/tsconfig.json b/packages/editor/tsconfig.json index 8dfdf2ba7f2d5c..55d79babd1dacc 100644 --- a/packages/editor/tsconfig.json +++ b/packages/editor/tsconfig.json @@ -25,6 +25,7 @@ { "path": "../i18n" }, { "path": "../icons" }, { "path": "../keycodes" }, + { "path": "../media-utils" }, { "path": "../notices" }, { "path": "../plugins" }, { "path": "../private-apis" }, diff --git a/packages/media-utils/CHANGELOG.md b/packages/media-utils/CHANGELOG.md index 7ab4d4a5794d88..26282b6b2bda21 100644 --- a/packages/media-utils/CHANGELOG.md +++ b/packages/media-utils/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### New Features + +- Rewrite in TypeScript, exporting all the individual utility functions. + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/media-utils/README.md b/packages/media-utils/README.md index 6c2384061a5f6f..1adc15186078a5 100644 --- a/packages/media-utils/README.md +++ b/packages/media-utils/README.md @@ -13,6 +13,75 @@ npm install @wordpress/media-utils --save _This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for such language features and APIs, you should include [the polyfill shipped in `@wordpress/babel-preset-default`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/babel-preset-default#polyfill) in your code._ +## API + +<!-- START TOKEN(Autogenerated API docs) --> + +### Attachment + +Undocumented declaration. + +### MediaUpload + +Undocumented declaration. + +### RestAttachment + +Undocumented declaration. + +### transformAttachment + +Transforms an attachment object from the REST API shape into the shape expected by the block editor and other consumers. + +_Parameters_ + +- _attachment_ `RestAttachment`: REST API attachment object. + +### uploadMedia + +Upload a media file when the file upload button is activated or when adding a file to the editor via drag & drop. + +_Parameters_ + +- _$0_ `UploadMediaArgs`: Parameters object passed to the function. +- _$0.allowedTypes_ `UploadMediaArgs[ 'allowedTypes' ]`: Array with the types of media that can be uploaded, if unset all types are allowed. +- _$0.additionalData_ `UploadMediaArgs[ 'additionalData' ]`: Additional data to include in the request. +- _$0.filesList_ `UploadMediaArgs[ 'filesList' ]`: List of files. +- _$0.maxUploadFileSize_ `UploadMediaArgs[ 'maxUploadFileSize' ]`: Maximum upload size in bytes allowed for the site. +- _$0.onError_ `UploadMediaArgs[ 'onError' ]`: Function called when an error happens. +- _$0.onFileChange_ `UploadMediaArgs[ 'onFileChange' ]`: Function called each time a file or a temporary representation of the file is available. +- _$0.wpAllowedMimeTypes_ `UploadMediaArgs[ 'wpAllowedMimeTypes' ]`: List of allowed mime types and file extensions. +- _$0.signal_ `UploadMediaArgs[ 'signal' ]`: Abort signal. + +### validateFileSize + +Verifies whether the file is within the file upload size limits for the site. + +_Parameters_ + +- _file_ `File`: File object. +- _maxUploadFileSize_ `number`: Maximum upload size in bytes allowed for the site. + +### validateMimeType + +Verifies if the caller (e.g. a block) supports this mime type. + +_Parameters_ + +- _file_ `File`: File object. +- _allowedTypes_ `string[]`: List of allowed mime types. + +### validateMimeTypeForUser + +Verifies if the user is allowed to upload this mime type. + +_Parameters_ + +- _file_ `File`: File object. +- _wpAllowedMimeTypes_ `Record< string, string > | null`: List of allowed mime types and file extensions. + +<!-- END TOKEN(Autogenerated API docs) --> + ## Usage ### uploadMedia @@ -43,7 +112,7 @@ Beware that first onFileChange is called with temporary blob URLs and then with ### MediaUpload Media upload component provides a UI button that allows users to open the WordPress media library. It is normally used in conjunction with the filter `editor.MediaUpload`. -The component follows the interface specified in [https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/media-upload/README.md](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/media-upload/README.md), and more details regarding its usage can be checked there. +The component follows the interface specified in <https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/media-upload/README.md>, and more details regarding its usage can be checked there. ## Contributing to this package diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index b1737ff39e4bcd..1cfe019e89d0a6 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -14,7 +14,7 @@ "repository": { "type": "git", "url": "https://github.com/WordPress/gutenberg.git", - "directory": "packages/url" + "directory": "packages/media-utils" }, "bugs": { "url": "https://github.com/WordPress/gutenberg/issues" @@ -25,6 +25,7 @@ }, "main": "build/index.js", "module": "build-module/index.js", + "types": "build-types", "dependencies": { "@babel/runtime": "^7.16.0", "@wordpress/api-fetch": "file:../api-fetch", diff --git a/packages/media-utils/src/index.js b/packages/media-utils/src/index.js deleted file mode 100644 index 590a7f4c9d188d..00000000000000 --- a/packages/media-utils/src/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export * from './components'; -export * from './utils'; diff --git a/packages/media-utils/src/index.ts b/packages/media-utils/src/index.ts new file mode 100644 index 00000000000000..c37814afe7c48f --- /dev/null +++ b/packages/media-utils/src/index.ts @@ -0,0 +1,9 @@ +export * from './components'; + +export { uploadMedia } from './utils/upload-media'; +export { transformAttachment } from './utils/transform-attachment'; +export { validateFileSize } from './utils/validate-file-size'; +export { validateMimeType } from './utils/validate-mime-type'; +export { validateMimeTypeForUser } from './utils/validate-mime-type-for-user'; + +export type { Attachment, RestAttachment } from './utils/types'; diff --git a/packages/media-utils/src/utils/flatten-form-data.ts b/packages/media-utils/src/utils/flatten-form-data.ts new file mode 100644 index 00000000000000..594f172ef7eb2c --- /dev/null +++ b/packages/media-utils/src/utils/flatten-form-data.ts @@ -0,0 +1,33 @@ +/** + * Determines whether the passed argument appears to be a plain object. + * + * @param data The object to inspect. + */ +function isPlainObject( data: unknown ): data is Record< string, unknown > { + return ( + data !== null && + typeof data === 'object' && + Object.getPrototypeOf( data ) === Object.prototype + ); +} + +/** + * Recursively flatten data passed to form data, to allow using multi-level objects. + * + * @param {FormData} formData Form data object. + * @param {string} key Key to amend to form data object + * @param {string|Object} data Data to be amended to form data. + */ +export function flattenFormData( + formData: FormData, + key: string, + data: string | undefined | Record< string, string > +) { + if ( isPlainObject( data ) ) { + for ( const [ name, value ] of Object.entries( data ) ) { + flattenFormData( formData, `${ key }[${ name }]`, value ); + } + } else if ( data !== undefined ) { + formData.append( key, String( data ) ); + } +} diff --git a/packages/media-utils/src/utils/get-mime-types-array.ts b/packages/media-utils/src/utils/get-mime-types-array.ts new file mode 100644 index 00000000000000..d4940d36cd6ae5 --- /dev/null +++ b/packages/media-utils/src/utils/get-mime-types-array.ts @@ -0,0 +1,29 @@ +/** + * Browsers may use unexpected mime types, and they differ from browser to browser. + * This function computes a flexible array of mime types from the mime type structured provided by the server. + * Converts { jpg|jpeg|jpe: "image/jpeg" } into [ "image/jpeg", "image/jpg", "image/jpeg", "image/jpe" ] + * + * @param {?Object} wpMimeTypesObject Mime type object received from the server. + * Extensions are keys separated by '|' and values are mime types associated with an extension. + * + * @return An array of mime types or null + */ +export function getMimeTypesArray( + wpMimeTypesObject?: Record< string, string > | null +) { + if ( ! wpMimeTypesObject ) { + return null; + } + return Object.entries( wpMimeTypesObject ).flatMap( + ( [ extensionsString, mime ] ) => { + const [ type ] = mime.split( '/' ); + const extensions = extensionsString.split( '|' ); + return [ + mime, + ...extensions.map( + ( extension ) => `${ type }/${ extension }` + ), + ]; + } + ); +} diff --git a/packages/media-utils/src/utils/index.js b/packages/media-utils/src/utils/index.js deleted file mode 100644 index 509b62f1e88648..00000000000000 --- a/packages/media-utils/src/utils/index.js +++ /dev/null @@ -1 +0,0 @@ -export { uploadMedia } from './upload-media'; diff --git a/packages/media-utils/src/utils/test/flatten-form-data.ts b/packages/media-utils/src/utils/test/flatten-form-data.ts new file mode 100644 index 00000000000000..458dfd26c8f6ed --- /dev/null +++ b/packages/media-utils/src/utils/test/flatten-form-data.ts @@ -0,0 +1,49 @@ +/** + * Internal dependencies + */ +import { flattenFormData } from '../flatten-form-data'; + +describe( 'flattenFormData', () => { + it( 'should flatten nested data structure', () => { + const data = new FormData(); + + class RichTextData { + toString() { + return 'i am rich text'; + } + } + + const additionalData = { + foo: null, + bar: 1234, + meta: { + nested: 'foo', + dothis: true, + dothat: false, + supermeta: { + nested: 'baz', + }, + }, + customClass: new RichTextData(), + }; + + for ( const [ key, value ] of Object.entries( additionalData ) ) { + flattenFormData( + data, + key, + value as Parameters< typeof flattenFormData >[ 2 ] + ); + } + + const actual = Object.fromEntries( data.entries() ); + expect( actual ).toStrictEqual( { + bar: '1234', + foo: 'null', + 'meta[dothat]': 'false', + 'meta[dothis]': 'true', + 'meta[nested]': 'foo', + 'meta[supermeta][nested]': 'baz', + customClass: 'i am rich text', + } ); + } ); +} ); diff --git a/packages/media-utils/src/utils/test/get-mime-types-array.ts b/packages/media-utils/src/utils/test/get-mime-types-array.ts new file mode 100644 index 00000000000000..156955373bd0da --- /dev/null +++ b/packages/media-utils/src/utils/test/get-mime-types-array.ts @@ -0,0 +1,47 @@ +/** + * Internal dependencies + */ +import { getMimeTypesArray } from '../get-mime-types-array'; + +describe( 'getMimeTypesArray', () => { + it( 'should return null if it is "falsy" e.g: undefined or null', () => { + expect( getMimeTypesArray( null ) ).toEqual( null ); + expect( getMimeTypesArray( undefined ) ).toEqual( null ); + } ); + + it( 'should return an empty array if an empty object is passed', () => { + expect( getMimeTypesArray( {} ) ).toEqual( [] ); + } ); + + it( 'should return the type plus a new mime type with type and subtype with the extension if a type is passed', () => { + expect( getMimeTypesArray( { ext: 'chicken' } ) ).toEqual( [ + 'chicken', + 'chicken/ext', + ] ); + } ); + + it( 'should return the mime type passed and a new mime type with type and the extension as subtype', () => { + expect( getMimeTypesArray( { ext: 'chicken/ribs' } ) ).toEqual( [ + 'chicken/ribs', + 'chicken/ext', + ] ); + } ); + + it( 'should return the mime type passed and an additional mime type per extension supported', () => { + expect( getMimeTypesArray( { 'jpg|jpeg|jpe': 'image/jpeg' } ) ).toEqual( + [ 'image/jpeg', 'image/jpg', 'image/jpeg', 'image/jpe' ] + ); + } ); + + it( 'should handle multiple mime types', () => { + expect( + getMimeTypesArray( { 'ext|aaa': 'chicken/ribs', aaa: 'bbb' } ) + ).toEqual( [ + 'chicken/ribs', + 'chicken/ext', + 'chicken/aaa', + 'bbb', + 'bbb/aaa', + ] ); + } ); +} ); diff --git a/packages/media-utils/src/utils/test/upload-error.ts b/packages/media-utils/src/utils/test/upload-error.ts new file mode 100644 index 00000000000000..4d5f025ed8cf39 --- /dev/null +++ b/packages/media-utils/src/utils/test/upload-error.ts @@ -0,0 +1,24 @@ +/** + * Internal dependencies + */ +import { UploadError } from '../upload-error'; + +describe( 'UploadError', () => { + it( 'holds error code and file name', () => { + const file = new File( [], 'example.jpg', { + lastModified: 1234567891, + type: 'image/jpeg', + } ); + + const error = new UploadError( { + code: 'some_error', + message: 'An error occurred', + file, + } ); + + expect( error ).toStrictEqual( expect.any( Error ) ); + expect( error.code ).toBe( 'some_error' ); + expect( error.message ).toBe( 'An error occurred' ); + expect( error.file ).toBe( file ); + } ); +} ); diff --git a/packages/media-utils/src/utils/test/upload-media.test.js b/packages/media-utils/src/utils/test/upload-media.ts similarity index 58% rename from packages/media-utils/src/utils/test/upload-media.test.js rename to packages/media-utils/src/utils/test/upload-media.ts index fa9adc9f408815..b5075255ad4c81 100644 --- a/packages/media-utils/src/utils/test/upload-media.test.js +++ b/packages/media-utils/src/utils/test/upload-media.ts @@ -1,19 +1,18 @@ -/** - * WordPress dependencies - */ -import { createBlobURL } from '@wordpress/blob'; -import apiFetch from '@wordpress/api-fetch'; - /** * Internal dependencies */ -import { uploadMedia, getMimeTypesArray } from '../upload-media'; +import { uploadMedia } from '../upload-media'; +import { UploadError } from '../upload-error'; +import { uploadToServer } from '../upload-to-server'; + +jest.mock( '../upload-to-server', () => ( { + uploadToServer: jest.fn(), +} ) ); jest.mock( '@wordpress/blob', () => ( { createBlobURL: jest.fn(), revokeBlobURL: jest.fn(), } ) ); -jest.mock( '@wordpress/api-fetch', () => jest.fn() ); const xmlFile = new window.File( [ 'fake_file' ], 'test.xml', { type: 'text/xml', @@ -23,6 +22,10 @@ const imageFile = new window.File( [ 'fake_file' ], 'test.jpeg', { } ); describe( 'uploadMedia', () => { + afterEach( () => { + jest.clearAllMocks(); + } ); + it( 'should do nothing on no files', async () => { const onError = jest.fn(); const onFileChange = jest.fn(); @@ -33,7 +36,7 @@ describe( 'uploadMedia', () => { } ); expect( onError ).not.toHaveBeenCalled(); - expect( onFileChange ).not.toHaveBeenCalled(); + expect( uploadToServer ).not.toHaveBeenCalled(); } ); it( 'should error if allowedTypes contains a partial mime type and the validation fails', async () => { @@ -47,11 +50,14 @@ describe( 'uploadMedia', () => { } ); expect( onError ).toHaveBeenCalledWith( - expect.objectContaining( { + new UploadError( { code: 'MIME_TYPE_NOT_SUPPORTED', + message: + 'test.xml: Sorry, this file type is not supported here.', + file: xmlFile, } ) ); - expect( onFileChange ).not.toHaveBeenCalled(); + expect( uploadToServer ).not.toHaveBeenCalled(); } ); it( 'should error if allowedTypes contains a complete mime type and the validation fails', async () => { @@ -65,17 +71,17 @@ describe( 'uploadMedia', () => { } ); expect( onError ).toHaveBeenCalledWith( - expect.objectContaining( { + new UploadError( { code: 'MIME_TYPE_NOT_SUPPORTED', + message: + 'test.jpeg: Sorry, this file type is not supported here.', + file: xmlFile, } ) ); - expect( onFileChange ).not.toHaveBeenCalled(); + expect( uploadToServer ).not.toHaveBeenCalled(); } ); it( 'should work if allowedTypes contains a complete mime type and the validation succeeds', async () => { - createBlobURL.mockReturnValue( 'blob:fake_blob' ); - apiFetch.mockResolvedValue( { title: { raw: 'Test' } } ); - const onError = jest.fn(); const onFileChange = jest.fn(); await uploadMedia( { @@ -83,10 +89,11 @@ describe( 'uploadMedia', () => { filesList: [ imageFile ], onError, onFileChange, + wpAllowedMimeTypes: { jpeg: 'image/jpeg' }, } ); expect( onError ).not.toHaveBeenCalled(); - expect( onFileChange ).toHaveBeenCalledTimes( 2 ); + expect( uploadToServer ).toHaveBeenCalled(); } ); it( 'should error if allowedTypes contains multiple types and the validation fails', async () => { @@ -100,17 +107,17 @@ describe( 'uploadMedia', () => { } ); expect( onError ).toHaveBeenCalledWith( - expect.objectContaining( { + new UploadError( { code: 'MIME_TYPE_NOT_SUPPORTED', + message: + 'test.xml: Sorry, this file type is not supported here.', + file: xmlFile, } ) ); - expect( onFileChange ).not.toHaveBeenCalled(); + expect( uploadToServer ).not.toHaveBeenCalled(); } ); it( 'should work if allowedTypes contains multiple types and the validation succeeds', async () => { - createBlobURL.mockReturnValue( 'blob:fake_blob' ); - apiFetch.mockResolvedValue( { title: { raw: 'Test' } } ); - const onError = jest.fn(); const onFileChange = jest.fn(); await uploadMedia( { @@ -118,16 +125,14 @@ describe( 'uploadMedia', () => { filesList: [ imageFile ], onError, onFileChange, + wpAllowedMimeTypes: { jpeg: 'image/jpeg', mp4: 'video/mp4' }, } ); expect( onError ).not.toHaveBeenCalled(); - expect( onFileChange ).toHaveBeenCalledTimes( 2 ); + expect( uploadToServer ).toHaveBeenCalled(); } ); it( 'should only fail the invalid file and still allow others to succeed when uploading multiple files', async () => { - createBlobURL.mockReturnValue( 'blob:fake_blob' ); - apiFetch.mockResolvedValue( { title: { raw: 'Test' } } ); - const onError = jest.fn(); const onFileChange = jest.fn(); await uploadMedia( { @@ -135,15 +140,18 @@ describe( 'uploadMedia', () => { filesList: [ imageFile, xmlFile ], onError, onFileChange, + wpAllowedMimeTypes: { jpeg: 'image/jpeg' }, } ); expect( onError ).toHaveBeenCalledWith( - expect.objectContaining( { + new UploadError( { code: 'MIME_TYPE_NOT_SUPPORTED', + message: + 'test.xml: Sorry, you are not allowed to upload this file type.', file: xmlFile, } ) ); - expect( onFileChange ).toHaveBeenCalledTimes( 2 ); + expect( uploadToServer ).toHaveBeenCalledTimes( 1 ); } ); it( 'should error if the file size is greater than the maximum', async () => { @@ -155,19 +163,22 @@ describe( 'uploadMedia', () => { maxUploadFileSize: 1, onError, onFileChange, + wpAllowedMimeTypes: { jpeg: 'image/jpeg' }, } ); expect( onError ).toHaveBeenCalledWith( - expect.objectContaining( { + new UploadError( { code: 'SIZE_ABOVE_LIMIT', + message: + 'test.jpeg: This file exceeds the maximum upload size for this site.', + file: imageFile, } ) ); - expect( onFileChange ).not.toHaveBeenCalled(); + expect( uploadToServer ).not.toHaveBeenCalled(); } ); it( 'should call error handler with the correct error object if file type is not allowed for user', async () => { const onError = jest.fn(); - const onFileChange = jest.fn(); await uploadMedia( { allowedTypes: [ 'image' ], filesList: [ imageFile ], @@ -176,53 +187,13 @@ describe( 'uploadMedia', () => { } ); expect( onError ).toHaveBeenCalledWith( - expect.objectContaining( { + new UploadError( { code: 'MIME_TYPE_NOT_ALLOWED_FOR_USER', + message: + 'test.jpeg: Sorry, you are not allowed to upload this file type.', + file: imageFile, } ) ); - expect( onFileChange ).not.toHaveBeenCalled(); - } ); -} ); - -describe( 'getMimeTypesArray', () => { - it( 'should return the parameter passed if it is "falsy" e.g: undefined or null', () => { - expect( getMimeTypesArray( null ) ).toEqual( null ); - expect( getMimeTypesArray( undefined ) ).toEqual( undefined ); - } ); - - it( 'should return an empty array if an empty object is passed', () => { - expect( getMimeTypesArray( {} ) ).toEqual( [] ); - } ); - - it( 'should return the type plus a new mime type with type and subtype with the extension if a type is passed', () => { - expect( getMimeTypesArray( { ext: 'chicken' } ) ).toEqual( [ - 'chicken', - 'chicken/ext', - ] ); - } ); - - it( 'should return the mime type passed and a new mime type with type and the extension as subtype', () => { - expect( getMimeTypesArray( { ext: 'chicken/ribs' } ) ).toEqual( [ - 'chicken/ribs', - 'chicken/ext', - ] ); - } ); - - it( 'should return the mime type passed and an additional mime type per extension supported', () => { - expect( getMimeTypesArray( { 'jpg|jpeg|jpe': 'image/jpeg' } ) ).toEqual( - [ 'image/jpeg', 'image/jpg', 'image/jpeg', 'image/jpe' ] - ); - } ); - - it( 'should handle multiple mime types', () => { - expect( - getMimeTypesArray( { 'ext|aaa': 'chicken/ribs', aaa: 'bbb' } ) - ).toEqual( [ - 'chicken/ribs', - 'chicken/ext', - 'chicken/aaa', - 'bbb', - 'bbb/aaa', - ] ); + expect( uploadToServer ).not.toHaveBeenCalled(); } ); } ); diff --git a/packages/media-utils/src/utils/test/validate-file-size.ts b/packages/media-utils/src/utils/test/validate-file-size.ts new file mode 100644 index 00000000000000..31d6af0e7e4a55 --- /dev/null +++ b/packages/media-utils/src/utils/test/validate-file-size.ts @@ -0,0 +1,70 @@ +/** + * Internal dependencies + */ +import { validateFileSize } from '../validate-file-size'; +import { UploadError } from '../upload-error'; + +const imageFile = new window.File( [ 'fake_file' ], 'test.jpeg', { + type: 'image/jpeg', +} ); + +const emptyFile = new window.File( [], 'test.jpeg', { + type: 'image/jpeg', +} ); + +describe( 'validateFileSize', () => { + afterEach( () => { + jest.clearAllMocks(); + } ); + + it( 'should error if the file is empty', () => { + expect( () => { + validateFileSize( emptyFile ); + } ).toThrow( + new UploadError( { + code: 'EMPTY_FILE', + message: 'test.jpeg: This file is empty.', + file: imageFile, + } ) + ); + } ); + + it( 'should error if the file is is greater than the maximum', () => { + expect( () => { + validateFileSize( imageFile, 2 ); + } ).toThrow( + new UploadError( { + code: 'SIZE_ABOVE_LIMIT', + message: + 'test.jpeg: This file exceeds the maximum upload size for this site.', + file: imageFile, + } ) + ); + } ); + + it( 'should not error if the file is below the limit', () => { + expect( () => { + validateFileSize( imageFile, 100 ); + } ).not.toThrow( + new UploadError( { + code: 'SIZE_ABOVE_LIMIT', + message: + 'test.jpeg: This file exceeds the maximum upload size for this site.', + file: imageFile, + } ) + ); + } ); + + it( 'should not error if there is no limit', () => { + expect( () => { + validateFileSize( imageFile ); + } ).not.toThrow( + new UploadError( { + code: 'SIZE_ABOVE_LIMIT', + message: + 'test.jpeg: This file exceeds the maximum upload size for this site.', + file: imageFile, + } ) + ); + } ); +} ); diff --git a/packages/media-utils/src/utils/test/validate-mime-type-for-user.ts b/packages/media-utils/src/utils/test/validate-mime-type-for-user.ts new file mode 100644 index 00000000000000..d2566566862142 --- /dev/null +++ b/packages/media-utils/src/utils/test/validate-mime-type-for-user.ts @@ -0,0 +1,37 @@ +/** + * Internal dependencies + */ +import { validateMimeTypeForUser } from '../validate-mime-type-for-user'; +import { UploadError } from '../upload-error'; + +const imageFile = new window.File( [ 'fake_file' ], 'test.jpeg', { + type: 'image/jpeg', +} ); + +describe( 'validateMimeTypeForUser', () => { + afterEach( () => { + jest.clearAllMocks(); + } ); + + it( 'should not error if wpAllowedMimeTypes is null or missing', async () => { + expect( () => { + validateMimeTypeForUser( imageFile ); + } ).not.toThrow(); + expect( () => { + validateMimeTypeForUser( imageFile, null ); + } ).not.toThrow(); + } ); + + it( 'should error if file type is not allowed for user', async () => { + expect( () => { + validateMimeTypeForUser( imageFile, { aac: 'audio/aac' } ); + } ).toThrow( + new UploadError( { + code: 'MIME_TYPE_NOT_ALLOWED_FOR_USER', + message: + 'test.jpeg: Sorry, you are not allowed to upload this file type.', + file: imageFile, + } ) + ); + } ); +} ); diff --git a/packages/media-utils/src/utils/test/validate-mime-type.ts b/packages/media-utils/src/utils/test/validate-mime-type.ts new file mode 100644 index 00000000000000..a83cdcefe5f99a --- /dev/null +++ b/packages/media-utils/src/utils/test/validate-mime-type.ts @@ -0,0 +1,57 @@ +/** + * Internal dependencies + */ +import { validateMimeType } from '../validate-mime-type'; +import { UploadError } from '../upload-error'; + +const xmlFile = new window.File( [ 'fake_file' ], 'test.xml', { + type: 'text/xml', +} ); +const imageFile = new window.File( [ 'fake_file' ], 'test.jpeg', { + type: 'image/jpeg', +} ); + +describe( 'validateMimeType', () => { + afterEach( () => { + jest.clearAllMocks(); + } ); + + it( 'should error if allowedTypes contains a partial mime type and the validation fails', async () => { + expect( () => { + validateMimeType( xmlFile, [ 'image' ] ); + } ).toThrow( + new UploadError( { + code: 'MIME_TYPE_NOT_SUPPORTED', + message: + 'test.xml: Sorry, this file type is not supported here.', + file: xmlFile, + } ) + ); + } ); + + it( 'should error if allowedTypes contains a complete mime type and the validation fails', async () => { + expect( () => { + validateMimeType( imageFile, [ 'image/gif' ] ); + } ).toThrow( + new UploadError( { + code: 'MIME_TYPE_NOT_SUPPORTED', + message: + 'test.jpeg: Sorry, this file type is not supported here.', + file: xmlFile, + } ) + ); + } ); + + it( 'should error if allowedTypes contains multiple types and the validation fails', async () => { + expect( () => { + validateMimeType( xmlFile, [ 'video', 'image' ] ); + } ).toThrow( + new UploadError( { + code: 'MIME_TYPE_NOT_SUPPORTED', + message: + 'test.xml: Sorry, this file type is not supported here.', + file: xmlFile, + } ) + ); + } ); +} ); diff --git a/packages/media-utils/src/utils/transform-attachment.ts b/packages/media-utils/src/utils/transform-attachment.ts new file mode 100644 index 00000000000000..a97287872f24af --- /dev/null +++ b/packages/media-utils/src/utils/transform-attachment.ts @@ -0,0 +1,24 @@ +/** + * Internal dependencies + */ +import type { Attachment, RestAttachment } from './types'; + +/** + * Transforms an attachment object from the REST API shape into the shape expected by the block editor and other consumers. + * + * @param attachment REST API attachment object. + */ +export function transformAttachment( attachment: RestAttachment ): Attachment { + // eslint-disable-next-line camelcase + const { alt_text, source_url, ...savedMediaProps } = attachment; + return { + ...savedMediaProps, + alt: attachment.alt_text, + caption: attachment.caption?.raw ?? '', + title: attachment.title.raw, + url: attachment.source_url, + poster: + attachment._embedded?.[ 'wp:featuredmedia' ]?.[ 0 ]?.source_url || + undefined, + }; +} diff --git a/packages/media-utils/src/utils/types.ts b/packages/media-utils/src/utils/types.ts new file mode 100644 index 00000000000000..e05536400a7604 --- /dev/null +++ b/packages/media-utils/src/utils/types.ts @@ -0,0 +1,207 @@ +/** + * A media attachment object in a REST API context. + * + * Simplified version of what's defined in the wp-types package. + * + * @see https://www.npmjs.com/package/wp-types + */ +interface WP_REST_API_Attachment { + /** + * Unique identifier for the attachment. + */ + id: number; + /** + * The ID of the featured media for the post. + */ + featured_media: number; + /** + * URL to the attachment. + */ + link: string; + /** + * The date the attachment was published, in the site's timezone. + */ + date: string; + /** + * The date the attachment was published, as GMT. + */ + date_gmt: string; + /** + * The date the attachment was last modified, in the site's timezone. + */ + modified: string; + /** + * The date the attachment was last modified, as GMT. + */ + modified_gmt: string; + /** + * An alphanumeric identifier for the attachment unique to its type. + */ + slug: string; + /** + * A named status for the attachment. + */ + status: string; + /** + * Type of Post for the attachment. + */ + type: 'attachment'; + /** + * Alternative text to display when attachment is not displayed. + */ + alt_text: string; + /** + * The attachment caption. + */ + caption: { + /** + * Caption for the attachment, as it exists in the database. Only present when using the 'edit' context. + */ + raw?: string; + /** + * HTML caption for the attachment, transformed for display. + */ + rendered: string; + }; + /** + * The attachment description. + */ + description: { + /** + * Description for the attachment, as it exists in the database. Only present when using the 'edit' context. + */ + raw?: string; + /** + * HTML description for the attachment, transformed for display. + */ + rendered: string; + }; + /** + * Attachment type. + */ + media_type: 'image' | 'file'; + /** + * The attachment MIME type. + */ + mime_type: string; + /** + * Details about the media file, specific to its type. + */ + media_details: { + [ k: string ]: unknown; + }; + /** + * The ID for the associated post of the attachment. + */ + post: number | null; + /** + * URL to the original attachment file. + */ + source_url: string; + /** + * List of the missing image sizes of the attachment. Only present when using the 'edit' context. + */ + missing_image_sizes?: string[]; + /** + * Permalink template for the attachment. Only present when using the 'edit' context and the post type is public. + */ + permalink_template?: string; + /** + * Slug automatically generated from the attachment title. Only present when using the 'edit' context and the post type is public. + */ + generated_slug?: string; + /** + * An array of the class names for the post container element. + */ + class_list: string[]; + /** + * The title for the attachment. + */ + title: { + /** + * Title for the attachment, as it exists in the database. Only present when using the 'edit' context. + */ + raw?: string; + /** + * HTML title for the attachment, transformed for display. + */ + rendered: string; + }; + /** + * The ID for the author of the attachment. + */ + author: number; + /** + * Whether or not comments are open on the attachment. + */ + comment_status: string; + /** + * Whether or not the attachment can be pinged. + */ + ping_status: string; + /** + * Meta fields. + */ + meta: + | [] + | { + [ k: string ]: unknown; + }; + /** + * The theme file to use to display the attachment. + */ + template: string; + _links: { + [ k: string ]: { + href: string; + embeddable?: boolean; + [ k: string ]: unknown; + }[]; + }; + /** + * The embedded representation of relations. Only present when the '_embed' query parameter is set. + */ + _embedded?: { + /** + * The author of the post. + */ + author: unknown[]; + /** + * The featured image post. + */ + 'wp:featuredmedia'?: WP_REST_API_Attachment[]; + [ k: string ]: unknown; + }; + [ k: string ]: unknown; +} + +/** + * REST API attachment object with additional fields added by this project. + */ +export interface RestAttachment extends WP_REST_API_Attachment {} + +type BetterOmit< T, K extends PropertyKey > = { + [ P in keyof T as P extends K ? never : P ]: T[ P ]; +}; + +/** + * Transformed attachment object. + */ +export type Attachment = BetterOmit< + RestAttachment, + 'alt_text' | 'source_url' | 'caption' | 'title' +> & { + alt: WP_REST_API_Attachment[ 'alt_text' ]; + caption: WP_REST_API_Attachment[ 'caption' ][ 'raw' ] & string; + title: WP_REST_API_Attachment[ 'title' ][ 'raw' ]; + url: WP_REST_API_Attachment[ 'source_url' ]; + poster?: WP_REST_API_Attachment[ 'source_url' ]; +}; + +export type OnChangeHandler = ( attachments: Partial< Attachment >[] ) => void; +export type OnSuccessHandler = ( attachments: Partial< Attachment >[] ) => void; +export type OnErrorHandler = ( error: Error ) => void; + +export type CreateRestAttachment = Partial< RestAttachment >; + +export type AdditionalData = BetterOmit< CreateRestAttachment, 'meta' >; diff --git a/packages/media-utils/src/utils/upload-error.ts b/packages/media-utils/src/utils/upload-error.ts new file mode 100644 index 00000000000000..d712e9dcdb6966 --- /dev/null +++ b/packages/media-utils/src/utils/upload-error.ts @@ -0,0 +1,26 @@ +interface UploadErrorArgs { + code: string; + message: string; + file: File; + cause?: Error; +} + +/** + * MediaError class. + * + * Small wrapper around the `Error` class + * to hold an error code and a reference to a file object. + */ +export class UploadError extends Error { + code: string; + file: File; + + constructor( { code, message, file, cause }: UploadErrorArgs ) { + super( message, { cause } ); + + Object.setPrototypeOf( this, new.target.prototype ); + + this.code = code; + this.file = file; + } +} diff --git a/packages/media-utils/src/utils/upload-media.js b/packages/media-utils/src/utils/upload-media.js deleted file mode 100644 index e3c9b95d5c25cd..00000000000000 --- a/packages/media-utils/src/utils/upload-media.js +++ /dev/null @@ -1,232 +0,0 @@ -/** - * WordPress dependencies - */ -import apiFetch from '@wordpress/api-fetch'; -import { createBlobURL, revokeBlobURL } from '@wordpress/blob'; -import { __, sprintf } from '@wordpress/i18n'; - -const noop = () => {}; - -/** - * Browsers may use unexpected mime types, and they differ from browser to browser. - * This function computes a flexible array of mime types from the mime type structured provided by the server. - * Converts { jpg|jpeg|jpe: "image/jpeg" } into [ "image/jpeg", "image/jpg", "image/jpeg", "image/jpe" ] - * The computation of this array instead of directly using the object, - * solves the problem in chrome where mp3 files have audio/mp3 as mime type instead of audio/mpeg. - * https://bugs.chromium.org/p/chromium/issues/detail?id=227004 - * - * @param {?Object} wpMimeTypesObject Mime type object received from the server. - * Extensions are keys separated by '|' and values are mime types associated with an extension. - * - * @return {?Array} An array of mime types or the parameter passed if it was "falsy". - */ -export function getMimeTypesArray( wpMimeTypesObject ) { - if ( ! wpMimeTypesObject ) { - return wpMimeTypesObject; - } - return Object.entries( wpMimeTypesObject ) - .map( ( [ extensionsString, mime ] ) => { - const [ type ] = mime.split( '/' ); - const extensions = extensionsString.split( '|' ); - return [ - mime, - ...extensions.map( - ( extension ) => `${ type }/${ extension }` - ), - ]; - } ) - .flat(); -} - -/** - * Media Upload is used by audio, image, gallery, video, and file blocks to - * handle uploading a media file when a file upload button is activated. - * - * TODO: future enhancement to add an upload indicator. - * - * @param {Object} $0 Parameters object passed to the function. - * @param {?Array} $0.allowedTypes Array with the types of media that can be uploaded, if unset all types are allowed. - * @param {?Object} $0.additionalData Additional data to include in the request. - * @param {Array} $0.filesList List of files. - * @param {?number} $0.maxUploadFileSize Maximum upload size in bytes allowed for the site. - * @param {Function} $0.onError Function called when an error happens. - * @param {Function} $0.onFileChange Function called each time a file or a temporary representation of the file is available. - * @param {?Object} $0.wpAllowedMimeTypes List of allowed mime types and file extensions. - */ -export async function uploadMedia( { - allowedTypes, - additionalData = {}, - filesList, - maxUploadFileSize, - onError = noop, - onFileChange, - wpAllowedMimeTypes = null, -} ) { - // Cast filesList to array. - const files = [ ...filesList ]; - - const filesSet = []; - const setAndUpdateFiles = ( idx, value ) => { - revokeBlobURL( filesSet[ idx ]?.url ); - filesSet[ idx ] = value; - onFileChange( filesSet.filter( Boolean ) ); - }; - - // Allowed type specified by consumer. - const isAllowedType = ( fileType ) => { - if ( ! allowedTypes ) { - return true; - } - return allowedTypes.some( ( allowedType ) => { - // If a complete mimetype is specified verify if it matches exactly the mime type of the file. - if ( allowedType.includes( '/' ) ) { - return allowedType === fileType; - } - // Otherwise a general mime type is used and we should verify if the file mimetype starts with it. - return fileType.startsWith( `${ allowedType }/` ); - } ); - }; - - // Allowed types for the current WP_User. - const allowedMimeTypesForUser = getMimeTypesArray( wpAllowedMimeTypes ); - const isAllowedMimeTypeForUser = ( fileType ) => { - return allowedMimeTypesForUser.includes( fileType ); - }; - - const validFiles = []; - - for ( const mediaFile of files ) { - // Verify if user is allowed to upload this mime type. - // Defer to the server when type not detected. - if ( - allowedMimeTypesForUser && - mediaFile.type && - ! isAllowedMimeTypeForUser( mediaFile.type ) - ) { - onError( { - code: 'MIME_TYPE_NOT_ALLOWED_FOR_USER', - message: sprintf( - // translators: %s: file name. - __( - '%s: Sorry, you are not allowed to upload this file type.' - ), - mediaFile.name - ), - file: mediaFile, - } ); - continue; - } - - // Check if the block supports this mime type. - // Defer to the server when type not detected. - if ( mediaFile.type && ! isAllowedType( mediaFile.type ) ) { - onError( { - code: 'MIME_TYPE_NOT_SUPPORTED', - message: sprintf( - // translators: %s: file name. - __( '%s: Sorry, this file type is not supported here.' ), - mediaFile.name - ), - file: mediaFile, - } ); - continue; - } - - // Verify if file is greater than the maximum file upload size allowed for the site. - if ( maxUploadFileSize && mediaFile.size > maxUploadFileSize ) { - onError( { - code: 'SIZE_ABOVE_LIMIT', - message: sprintf( - // translators: %s: file name. - __( - '%s: This file exceeds the maximum upload size for this site.' - ), - mediaFile.name - ), - file: mediaFile, - } ); - continue; - } - - // Don't allow empty files to be uploaded. - if ( mediaFile.size <= 0 ) { - onError( { - code: 'EMPTY_FILE', - message: sprintf( - // translators: %s: file name. - __( '%s: This file is empty.' ), - mediaFile.name - ), - file: mediaFile, - } ); - continue; - } - - validFiles.push( mediaFile ); - - // Set temporary URL to create placeholder media file, this is replaced - // with final file from media gallery when upload is `done` below. - filesSet.push( { url: createBlobURL( mediaFile ) } ); - onFileChange( filesSet ); - } - - for ( let idx = 0; idx < validFiles.length; ++idx ) { - const mediaFile = validFiles[ idx ]; - try { - const savedMedia = await createMediaFromFile( - mediaFile, - additionalData - ); - // eslint-disable-next-line camelcase - const { alt_text, source_url, ...savedMediaProps } = savedMedia; - const mediaObject = { - ...savedMediaProps, - alt: savedMedia.alt_text, - caption: savedMedia.caption?.raw ?? '', - title: savedMedia.title.raw, - url: savedMedia.source_url, - }; - setAndUpdateFiles( idx, mediaObject ); - } catch ( error ) { - // Reset to empty on failure. - setAndUpdateFiles( idx, null ); - let message; - if ( error.message ) { - message = error.message; - } else { - message = sprintf( - // translators: %s: file name - __( 'Error while uploading file %s to the media library.' ), - mediaFile.name - ); - } - onError( { - code: 'GENERAL', - message, - file: mediaFile, - } ); - } - } -} - -/** - * @param {File} file Media File to Save. - * @param {?Object} additionalData Additional data to include in the request. - * - * @return {Promise} Media Object Promise. - */ -function createMediaFromFile( file, additionalData ) { - // Create upload payload. - const data = new window.FormData(); - data.append( 'file', file, file.name || file.type.replace( '/', '.' ) ); - if ( additionalData ) { - Object.entries( additionalData ).forEach( ( [ key, value ] ) => - data.append( key, value ) - ); - } - return apiFetch( { - path: '/wp/v2/media', - body: data, - method: 'POST', - } ); -} diff --git a/packages/media-utils/src/utils/upload-media.ts b/packages/media-utils/src/utils/upload-media.ts new file mode 100644 index 00000000000000..1bc861cfb3b607 --- /dev/null +++ b/packages/media-utils/src/utils/upload-media.ts @@ -0,0 +1,149 @@ +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; +import { createBlobURL, revokeBlobURL } from '@wordpress/blob'; + +/** + * Internal dependencies + */ +import type { + AdditionalData, + Attachment, + OnChangeHandler, + OnErrorHandler, + OnSuccessHandler, +} from './types'; +import { uploadToServer } from './upload-to-server'; +import { validateMimeType } from './validate-mime-type'; +import { validateMimeTypeForUser } from './validate-mime-type-for-user'; +import { validateFileSize } from './validate-file-size'; +import { UploadError } from './upload-error'; + +interface UploadMediaArgs { + // Additional data to include in the request. + additionalData?: AdditionalData; + // Array with the types of media that can be uploaded, if unset all types are allowed. + allowedTypes?: string[]; + // List of files. + filesList: File[]; + // Maximum upload size in bytes allowed for the site. + maxUploadFileSize?: number; + // Function called when an error happens. + onError?: OnErrorHandler; + // Function called each time a file or a temporary representation of the file is available. + onFileChange?: OnChangeHandler; + // Function called once a file has completely finished uploading, including thumbnails. + onSuccess?: OnSuccessHandler; + // List of allowed mime types and file extensions. + wpAllowedMimeTypes?: Record< string, string > | null; + // Abort signal. + signal?: AbortSignal; +} + +/** + * Upload a media file when the file upload button is activated + * or when adding a file to the editor via drag & drop. + * + * @param $0 Parameters object passed to the function. + * @param $0.allowedTypes Array with the types of media that can be uploaded, if unset all types are allowed. + * @param $0.additionalData Additional data to include in the request. + * @param $0.filesList List of files. + * @param $0.maxUploadFileSize Maximum upload size in bytes allowed for the site. + * @param $0.onError Function called when an error happens. + * @param $0.onFileChange Function called each time a file or a temporary representation of the file is available. + * @param $0.wpAllowedMimeTypes List of allowed mime types and file extensions. + * @param $0.signal Abort signal. + */ +export function uploadMedia( { + wpAllowedMimeTypes, + allowedTypes, + additionalData = {}, + filesList, + maxUploadFileSize, + onError, + onFileChange, + signal, +}: UploadMediaArgs ) { + const validFiles = []; + + const filesSet: Array< Partial< Attachment > | null > = []; + const setAndUpdateFiles = ( index: number, value: Attachment | null ) => { + if ( filesSet[ index ]?.url ) { + revokeBlobURL( filesSet[ index ].url ); + } + filesSet[ index ] = value; + onFileChange?.( + filesSet.filter( ( attachment ) => attachment !== null ) + ); + }; + + for ( const mediaFile of filesList ) { + // Verify if user is allowed to upload this mime type. + // Defer to the server when type not detected. + try { + validateMimeTypeForUser( mediaFile, wpAllowedMimeTypes ); + } catch ( error: unknown ) { + onError?.( error as Error ); + continue; + } + + // Check if the caller (e.g. a block) supports this mime type. + // Defer to the server when type not detected. + try { + validateMimeType( mediaFile, allowedTypes ); + } catch ( error: unknown ) { + onError?.( error as Error ); + continue; + } + + // Verify if file is greater than the maximum file upload size allowed for the site. + try { + validateFileSize( mediaFile, maxUploadFileSize ); + } catch ( error: unknown ) { + onError?.( error as Error ); + continue; + } + + validFiles.push( mediaFile ); + + // Set temporary URL to create placeholder media file, this is replaced + // with final file from media gallery when upload is `done` below. + filesSet.push( { url: createBlobURL( mediaFile ) } ); + onFileChange?.( filesSet as Array< Partial< Attachment > > ); + } + + validFiles.map( async ( file, index ) => { + try { + const attachment = await uploadToServer( + file, + additionalData, + signal + ); + setAndUpdateFiles( index, attachment ); + } catch ( error ) { + // Reset to empty on failure. + setAndUpdateFiles( index, null ); + + let message; + if ( error instanceof Error ) { + message = error.message; + } else { + message = sprintf( + // translators: %s: file name + __( 'Error while uploading file %s to the media library.' ), + file.name + ); + } + + onError?.( + new UploadError( { + code: 'GENERAL', + message, + file, + cause: error instanceof Error ? error : undefined, + } ) + ); + } + } ); +} diff --git a/packages/media-utils/src/utils/upload-to-server.ts b/packages/media-utils/src/utils/upload-to-server.ts new file mode 100644 index 00000000000000..7aa4243d5ccfd4 --- /dev/null +++ b/packages/media-utils/src/utils/upload-to-server.ts @@ -0,0 +1,38 @@ +/** + * WordPress dependencies + */ +import apiFetch from '@wordpress/api-fetch'; + +/** + * Internal dependencies + */ +import { flattenFormData } from './flatten-form-data'; +import { transformAttachment } from './transform-attachment'; +import type { CreateRestAttachment, RestAttachment } from './types'; + +export async function uploadToServer( + file: File, + additionalData: CreateRestAttachment = {}, + signal?: AbortSignal +) { + // Create upload payload. + const data = new FormData(); + data.append( 'file', file, file.name || file.type.replace( '/', '.' ) ); + for ( const [ key, value ] of Object.entries( additionalData ) ) { + flattenFormData( + data, + key, + value as string | Record< string, string > | undefined + ); + } + + return transformAttachment( + await apiFetch< RestAttachment >( { + // This allows the video block to directly get a video's poster image. + path: '/wp/v2/media?_embed=wp:featuredmedia', + body: data, + method: 'POST', + signal, + } ) + ); +} diff --git a/packages/media-utils/src/utils/validate-file-size.ts b/packages/media-utils/src/utils/validate-file-size.ts new file mode 100644 index 00000000000000..cc34462b268dda --- /dev/null +++ b/packages/media-utils/src/utils/validate-file-size.ts @@ -0,0 +1,44 @@ +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { UploadError } from './upload-error'; + +/** + * Verifies whether the file is within the file upload size limits for the site. + * + * @param file File object. + * @param maxUploadFileSize Maximum upload size in bytes allowed for the site. + */ +export function validateFileSize( file: File, maxUploadFileSize?: number ) { + // Don't allow empty files to be uploaded. + if ( file.size <= 0 ) { + throw new UploadError( { + code: 'EMPTY_FILE', + message: sprintf( + // translators: %s: file name. + __( '%s: This file is empty.' ), + file.name + ), + file, + } ); + } + + if ( maxUploadFileSize && file.size > maxUploadFileSize ) { + throw new UploadError( { + code: 'SIZE_ABOVE_LIMIT', + message: sprintf( + // translators: %s: file name. + __( + '%s: This file exceeds the maximum upload size for this site.' + ), + file.name + ), + file, + } ); + } +} diff --git a/packages/media-utils/src/utils/validate-mime-type-for-user.ts b/packages/media-utils/src/utils/validate-mime-type-for-user.ts new file mode 100644 index 00000000000000..858c583561978e --- /dev/null +++ b/packages/media-utils/src/utils/validate-mime-type-for-user.ts @@ -0,0 +1,46 @@ +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { UploadError } from './upload-error'; +import { getMimeTypesArray } from './get-mime-types-array'; + +/** + * Verifies if the user is allowed to upload this mime type. + * + * @param file File object. + * @param wpAllowedMimeTypes List of allowed mime types and file extensions. + */ +export function validateMimeTypeForUser( + file: File, + wpAllowedMimeTypes?: Record< string, string > | null +) { + // Allowed types for the current WP_User. + const allowedMimeTypesForUser = getMimeTypesArray( wpAllowedMimeTypes ); + + if ( ! allowedMimeTypesForUser ) { + return; + } + + const isAllowedMimeTypeForUser = allowedMimeTypesForUser.includes( + file.type + ); + + if ( file.type && ! isAllowedMimeTypeForUser ) { + throw new UploadError( { + code: 'MIME_TYPE_NOT_ALLOWED_FOR_USER', + message: sprintf( + // translators: %s: file name. + __( + '%s: Sorry, you are not allowed to upload this file type.' + ), + file.name + ), + file, + } ); + } +} diff --git a/packages/media-utils/src/utils/validate-mime-type.ts b/packages/media-utils/src/utils/validate-mime-type.ts new file mode 100644 index 00000000000000..2d99455d7b60f1 --- /dev/null +++ b/packages/media-utils/src/utils/validate-mime-type.ts @@ -0,0 +1,43 @@ +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { UploadError } from './upload-error'; + +/** + * Verifies if the caller (e.g. a block) supports this mime type. + * + * @param file File object. + * @param allowedTypes List of allowed mime types. + */ +export function validateMimeType( file: File, allowedTypes?: string[] ) { + if ( ! allowedTypes ) { + return; + } + + // Allowed type specified by consumer. + const isAllowedType = allowedTypes.some( ( allowedType ) => { + // If a complete mimetype is specified verify if it matches exactly the mime type of the file. + if ( allowedType.includes( '/' ) ) { + return allowedType === file.type; + } + // Otherwise a general mime type is used, and we should verify if the file mimetype starts with it. + return file.type.startsWith( `${ allowedType }/` ); + } ); + + if ( file.type && ! isAllowedType ) { + throw new UploadError( { + code: 'MIME_TYPE_NOT_SUPPORTED', + message: sprintf( + // translators: %s: file name. + __( '%s: Sorry, this file type is not supported here.' ), + file.name + ), + file, + } ); + } +} diff --git a/packages/media-utils/tsconfig.json b/packages/media-utils/tsconfig.json new file mode 100644 index 00000000000000..8559f1507b7235 --- /dev/null +++ b/packages/media-utils/tsconfig.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types", + "types": [ "gutenberg-env" ], + "checkJs": false + }, + "include": [ "src/**/*" ], + "references": [ + { "path": "../api-fetch" }, + { "path": "../blob" }, + { "path": "../element" }, + { "path": "../i18n" } + ] +} diff --git a/tsconfig.json b/tsconfig.json index cf986ddbee72bf..6be31e9b61bef8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -35,6 +35,7 @@ { "path": "packages/is-shallow-equal" }, { "path": "packages/keycodes" }, { "path": "packages/lazy-import" }, + { "path": "packages/media-utils" }, { "path": "packages/notices" }, { "path": "packages/plugins" }, { "path": "packages/prettier-config" }, From f7fd3684f2be3633746153b1301e26e3231b69e1 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Thu, 5 Sep 2024 16:14:31 +0200 Subject: [PATCH 0701/1908] Block Bindings: Fix empty strings placeholders in post meta bindings (#65089) * Contemplate empty strings as truthy * Add e2e test for empty values Co-authored-by: zaguiini <zaguiini@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> --- packages/e2e-tests/plugins/block-bindings.php | 10 ++++++ packages/editor/src/bindings/post-meta.js | 2 +- .../editor/various/block-bindings.spec.js | 32 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/packages/e2e-tests/plugins/block-bindings.php b/packages/e2e-tests/plugins/block-bindings.php index b2eb9d797610d5..143feb240ac2ef 100644 --- a/packages/e2e-tests/plugins/block-bindings.php +++ b/packages/e2e-tests/plugins/block-bindings.php @@ -41,6 +41,16 @@ function gutenberg_test_block_bindings_registration() { 'default' => '#url-custom-field', ) ); + register_meta( + 'post', + 'empty_field', + array( + 'show_in_rest' => true, + 'type' => 'string', + 'single' => true, + 'default' => '', + ) + ); register_meta( 'post', '_protected_field', diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index 4de8396d4c13bb..7618ba6c360236 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -22,7 +22,7 @@ export default { for ( const [ attributeName, source ] of Object.entries( bindings ) ) { // Use the key if the value is not set. newValues[ attributeName ] = - meta?.[ source.args.key ] || source.args.key; + meta?.[ source.args.key ] ?? source.args.key; } return newValues; }, diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index 2799315a10b220..6e36b6ad5dd335 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -1278,6 +1278,38 @@ test.describe( 'Block bindings', () => { ).toHaveText( 'fallback value' ); } ); + test( 'should show the prompt placeholder in field with empty value', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'paragraph default content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { key: 'empty_field' }, + }, + }, + }, + }, + } ); + + const paragraphBlock = editor.canvas.getByRole( 'document', { + // Aria-label is changed for empty paragraphs. + name: 'Add empty_field', + } ); + + await expect( paragraphBlock ).toBeEmpty(); + + const placeholder = paragraphBlock.locator( 'span' ); + await expect( placeholder ).toHaveAttribute( + 'data-rich-text-placeholder', + 'Add empty_field' + ); + } ); + test( 'should not show the value of a protected meta field', async ( { editor, } ) => { From 9c459852f9dc498e0856c622cc28785b7830a045 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Fri, 6 Sep 2024 01:07:40 +1000 Subject: [PATCH 0702/1908] Page editor: double-click to edit template part (#65024) Adds a doubleclick handler to template part block if the content has `contentOnly` editing mode. Also tighten up the doubleclick handler that triggers the edit template modal. It should not trigger when clicking on template parts now that there's a second double click handler. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> --- .../src/template-part/edit/inner-blocks.js | 21 ++++++++++++++++++- .../edit-template-blocks-notification.js | 5 ++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/template-part/edit/inner-blocks.js b/packages/block-library/src/template-part/edit/inner-blocks.js index 2c246809ab2d49..8582caba4cde47 100644 --- a/packages/block-library/src/template-part/edit/inner-blocks.js +++ b/packages/block-library/src/template-part/edit/inner-blocks.js @@ -100,6 +100,12 @@ function EditableTemplatePartInnerBlocks( { tagName: TagName, blockProps, } ) { + const onNavigateToEntityRecord = useSelect( + ( select ) => + select( blockEditorStore ).getSettings().onNavigateToEntityRecord, + [] + ); + const [ blocks, onInput, onChange ] = useEntityBlockEditor( 'postType', 'wp_template_part', @@ -114,7 +120,20 @@ function EditableTemplatePartInnerBlocks( { layout: useLayout( layout ), } ); - return <TagName { ...innerBlocksProps } />; + const blockEditingMode = useBlockEditingMode(); + + const customProps = + blockEditingMode === 'contentOnly' && onNavigateToEntityRecord + ? { + onDoubleClick: () => + onNavigateToEntityRecord( { + postId: id, + postType: 'wp_template_part', + } ), + } + : {}; + + return <TagName { ...innerBlocksProps } { ...customProps } />; } export default function TemplatePartInnerBlocks( { diff --git a/packages/editor/src/components/visual-editor/edit-template-blocks-notification.js b/packages/editor/src/components/visual-editor/edit-template-blocks-notification.js index 449834e3ab61cf..3ccbe79127c013 100644 --- a/packages/editor/src/components/visual-editor/edit-template-blocks-notification.js +++ b/packages/editor/src/components/visual-editor/edit-template-blocks-notification.js @@ -55,7 +55,10 @@ export default function EditTemplateBlocksNotification( { contentRef } ) { return; } - if ( ! event.target.classList.contains( 'is-root-container' ) ) { + if ( + ! event.target.classList.contains( 'is-root-container' ) || + event.target.dataset?.type === 'core/template-part' + ) { return; } setIsDialogOpen( true ); From 2fe092ebcc901d0da4062e162d0723f4bd75b34b Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 5 Sep 2024 17:36:36 +0200 Subject: [PATCH 0703/1908] Composite: deprecate legacy, unstable version (#63572) * Add deprecated tags to JSDocs * Add deprecated console warnings * Update unit tests to expect the warnings * CHANGELOG * Remove mention of store hook --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 + .../components/src/composite/legacy/index.tsx | 73 +++++++++++++++++-- .../src/composite/legacy/test/index.tsx | 58 ++++++++++++++- 3 files changed, 126 insertions(+), 9 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 499a3b69c06a2b..35549e8cb77998 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Deprecations + +- Deprecate `__unstableComposite`, `__unstableCompositeGroup`, `__unstableCompositeItem` and `__unstableUseCompositeState`. Consumers of the package should use the stable `Composite` component instead ([#63572](https://github.com/WordPress/gutenberg/pull/63572)). + ### New Features - `Composite`: add stable version of the component ([#63569](https://github.com/WordPress/gutenberg/pull/63569)). diff --git a/packages/components/src/composite/legacy/index.tsx b/packages/components/src/composite/legacy/index.tsx index cff564af1f8e7a..22ddff6572dd01 100644 --- a/packages/components/src/composite/legacy/index.tsx +++ b/packages/components/src/composite/legacy/index.tsx @@ -22,12 +22,13 @@ import * as Ariakit from '@ariakit/react'; * WordPress dependencies */ import { forwardRef } from '@wordpress/element'; +import { useInstanceId } from '@wordpress/compose'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies */ import { Composite as Current } from '..'; -import { useInstanceId } from '@wordpress/compose'; type Orientation = 'horizontal' | 'vertical'; @@ -123,12 +124,31 @@ function mapLegacyStatePropsToComponentProps( return legacyProps; } +const LEGACY_TO_NEW_DISPLAY_NAME = { + __unstableComposite: 'Composite', + __unstableCompositeGroup: 'Composite.Group or Composite.Row', + __unstableCompositeItem: 'Composite.Item', + __unstableUseCompositeState: 'Composite', +}; + function proxyComposite< C extends Component >( ProxiedComponent: C | React.ForwardRefExoticComponent< C >, propMap: Record< string, string > = {} ): CompositeComponent< C > { - const displayName = ProxiedComponent.displayName; + const displayName = ProxiedComponent.displayName ?? ''; + const Component = ( legacyProps: CompositeStateProps ) => { + deprecated( `wp.components.${ displayName }`, { + since: '6.7', + alternative: LEGACY_TO_NEW_DISPLAY_NAME.hasOwnProperty( + displayName + ) + ? LEGACY_TO_NEW_DISPLAY_NAME[ + displayName as keyof typeof LEGACY_TO_NEW_DISPLAY_NAME + ] + : undefined, + } ); + const { store, ...rest } = mapLegacyStatePropsToComponentProps( legacyProps ); const props = rest as ComponentProps< C >; @@ -153,7 +173,7 @@ function proxyComposite< C extends Component >( // `CompositeRow`, but this has been split into two different // components. We handle that difference by checking on the // provided role, and returning the appropriate component. -const unproxiedCompositeGroup = forwardRef< +const UnproxiedCompositeGroup = forwardRef< any, React.ComponentPropsWithoutRef< typeof Current.Group | typeof Current.Row > >( ( { role, ...props }, ref ) => { @@ -161,15 +181,52 @@ const unproxiedCompositeGroup = forwardRef< return <Component ref={ ref } role={ role } { ...props } />; } ); -export const Composite = proxyComposite( Current, { baseId: 'id' } ); -export const CompositeGroup = proxyComposite( unproxiedCompositeGroup ); -export const CompositeItem = proxyComposite( Current.Item, { - focusable: 'accessibleWhenDisabled', -} ); +/** + * _Note: please use the `Composite` component instead._ + * + * @deprecated + */ +export const Composite = proxyComposite( + Object.assign( Current, { displayName: '__unstableComposite' } ), + { baseId: 'id' } +); +/** + * _Note: please use the `Composite.Row` or `Composite.Group` components instead._ + * + * @deprecated + */ +export const CompositeGroup = proxyComposite( + Object.assign( UnproxiedCompositeGroup, { + displayName: '__unstableCompositeGroup', + } ) +); +/** + * _Note: please use the `Composite.Item` component instead._ + * + * @deprecated + */ +export const CompositeItem = proxyComposite( + Object.assign( Current.Item, { + displayName: '__unstableCompositeItem', + } ), + { + focusable: 'accessibleWhenDisabled', + } +); +/** + * _Note: please use the `Composite` component instead._ + * + * @deprecated + */ export function useCompositeState( legacyStateOptions: LegacyStateOptions = {} ): CompositeState { + deprecated( `wp.components.__unstableUseCompositeState`, { + since: '6.7', + alternative: LEGACY_TO_NEW_DISPLAY_NAME.__unstableUseCompositeState, + } ); + const { baseId, currentId: defaultActiveId, diff --git a/packages/components/src/composite/legacy/test/index.tsx b/packages/components/src/composite/legacy/test/index.tsx index 07398e54b27ca3..c034d31442ca8d 100644 --- a/packages/components/src/composite/legacy/test/index.tsx +++ b/packages/components/src/composite/legacy/test/index.tsx @@ -1,7 +1,12 @@ /** * External dependencies */ -import { queryByAttribute, render, screen } from '@testing-library/react'; +import { + queryByAttribute, + render, + screen, + renderHook, +} from '@testing-library/react'; import { press, waitFor } from '@ariakit/test'; /** @@ -156,6 +161,57 @@ function getShiftTestItems() { }; } +// Checking for deprecation warnings before other tests because the `deprecated` +// utility only fires a console.warn the first time a component is rendered. +describe( 'Shows a deprecation warning', () => { + it( 'useCompositeState', () => { + renderHook( () => useCompositeState() ); + expect( console ).toHaveWarnedWith( + 'wp.components.__unstableUseCompositeState is deprecated since version 6.7. Please use Composite instead.' + ); + } ); + it( 'Composite', () => { + const Test = () => { + const props = useCompositeState(); + return <Composite { ...props } />; + }; + render( <Test /> ); + expect( console ).toHaveWarnedWith( + 'wp.components.__unstableComposite is deprecated since version 6.7. Please use Composite instead.' + ); + } ); + it( 'CompositeItem', () => { + const Test = () => { + const props = useCompositeState(); + return ( + <Composite { ...props }> + <CompositeItem { ...props } /> + </Composite> + ); + }; + render( <Test /> ); + expect( console ).toHaveWarnedWith( + 'wp.components.__unstableCompositeItem is deprecated since version 6.7. Please use Composite.Item instead.' + ); + } ); + it( 'CompositeGroup', () => { + const Test = () => { + const props = useCompositeState(); + return ( + <Composite { ...props }> + <CompositeGroup { ...props }> + <CompositeItem { ...props } /> + </CompositeGroup> + </Composite> + ); + }; + render( <Test /> ); + expect( console ).toHaveWarnedWith( + 'wp.components.__unstableCompositeGroup is deprecated since version 6.7. Please use Composite.Group or Composite.Row instead.' + ); + } ); +} ); + describe.each( [ [ 'With "spread" state', From bc96d19a2d87a268a12efde0acbc2fbe028701b5 Mon Sep 17 00:00:00 2001 From: Rafael Gallani <galani.rafael@gmail.com> Date: Thu, 5 Sep 2024 13:34:18 -0300 Subject: [PATCH 0704/1908] Site Title, Post Title: Fix typography for blocks with `a` children (#64911) * Apply styles for element + `a` child when present * Inherit styles from parent element when present * Add missing `-font-family` attribute selector --- .../block-library/src/post-title/block.json | 5 +++- .../block-library/src/post-title/style.scss | 24 +++++++++++++++++++ .../block-library/src/site-title/block.json | 5 +++- .../block-library/src/site-title/style.scss | 24 +++++++++++++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/post-title/block.json b/packages/block-library/src/post-title/block.json index ecb5053d6cd39e..5e7d3eee9dd11d 100644 --- a/packages/block-library/src/post-title/block.json +++ b/packages/block-library/src/post-title/block.json @@ -80,5 +80,8 @@ } } }, - "style": "wp-block-post-title" + "style": "wp-block-post-title", + "selectors": { + "typography": ".wp-block-post-title, .wp-block-post-title > a" + } } diff --git a/packages/block-library/src/post-title/style.scss b/packages/block-library/src/post-title/style.scss index abeb4454bcb2c5..5d0e3407105bd4 100644 --- a/packages/block-library/src/post-title/style.scss +++ b/packages/block-library/src/post-title/style.scss @@ -3,6 +3,30 @@ // This block has customizable padding, border-box makes that more predictable. box-sizing: border-box; + &[style*="font-weight"] :where(a) { + font-weight: inherit; + } + &[class*="-font-family"] :where(a), + &[style*="font-family"] :where(a) { + font-family: inherit; + } + &[class*="-font-size"] :where(a), + &[style*="font-size"] :where(a) { + font-size: inherit; + } + &[style*="line-height"] :where(a) { + line-height: inherit; + } + &[style*="font-style"] :where(a) { + font-style: inherit; + } + &[style*="letter-spacing"] :where(a) { + letter-spacing: inherit; + } + &[style*="text-decoration"] :where(a) { + text-decoration: inherit; + } + a { display: inline-block; } diff --git a/packages/block-library/src/site-title/block.json b/packages/block-library/src/site-title/block.json index c75b1bc229beb9..dbb484c74a1e45 100644 --- a/packages/block-library/src/site-title/block.json +++ b/packages/block-library/src/site-title/block.json @@ -75,5 +75,8 @@ } }, "editorStyle": "wp-block-site-title-editor", - "style": "wp-block-site-title" + "style": "wp-block-site-title", + "selectors": { + "typography": ".wp-block-site-title > span, .wp-block-site-title > a" + } } diff --git a/packages/block-library/src/site-title/style.scss b/packages/block-library/src/site-title/style.scss index f292326cc3259f..8647f3d9b2947c 100644 --- a/packages/block-library/src/site-title/style.scss +++ b/packages/block-library/src/site-title/style.scss @@ -2,6 +2,30 @@ // This block has customizable padding, border-box makes that more predictable. box-sizing: border-box; + &[style*="font-weight"] :where(a) { + font-weight: inherit; + } + &[class*="-font-family"] :where(a), + &[style*="font-family"] :where(a) { + font-family: inherit; + } + &[class*="-font-size"] :where(a), + &[style*="font-size"] :where(a) { + font-size: inherit; + } + &[style*="line-height"] :where(a) { + line-height: inherit; + } + &[style*="font-style"] :where(a) { + font-style: inherit; + } + &[style*="letter-spacing"] :where(a) { + letter-spacing: inherit; + } + &[style*="text-decoration"] :where(a) { + text-decoration: inherit; + } + :where(a) { color: inherit; } From e40447e274390fa76ae01d2db19be2dc7db6504f Mon Sep 17 00:00:00 2001 From: David Arenas <david.arenas@automattic.com> Date: Thu, 5 Sep 2024 18:35:24 +0200 Subject: [PATCH 0705/1908] Interactivity API: Prevent calling `proxifyContext` over an already-proxified context inside the `wp-context` directive (#65090) * Do not store the proxified context inside `currentValue.current`. * Update changelog Co-authored-by: DAreRodz <darerodz@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/interactivity/CHANGELOG.md | 4 ++++ packages/interactivity/src/directives.tsx | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index b410eb270358f0..b888f159c00867 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- Prevent calling `proxifyContext` over an already-proxified context inside `wp-context` ([#65090](https://github.com/WordPress/gutenberg/pull/65090)). + ## 6.7.0 (2024-09-05) ### Enhancements diff --git a/packages/interactivity/src/directives.tsx b/packages/interactivity/src/directives.tsx index 715bc2ea7b16b6..b41d50722e3765 100644 --- a/packages/interactivity/src/directives.tsx +++ b/packages/interactivity/src/directives.tsx @@ -290,11 +290,10 @@ export default () => { currentValue.current, deepClone( value ) as object ); - currentValue.current = proxifyContext( + result[ namespace ] = proxifyContext( currentValue.current, inheritedValue[ namespace ] ); - result[ namespace ] = currentValue.current; } return result; }, [ defaultEntry, inheritedValue ] ); From d2db0f982268598b5efbd5306d5f410b529dc3d1 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 5 Sep 2024 17:24:54 +0000 Subject: [PATCH 0706/1908] Update Changelog for 19.2.0-rc.1 --- changelog.txt | 356 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 356 insertions(+) diff --git a/changelog.txt b/changelog.txt index 0fb2b93056b9bc..dc0a2487f725ff 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,361 @@ == Changelog == += 19.2.0-rc.1 = + + +## Changelog + +### Enhancements + +- Add: Reorder control at the field level on the new view configuration UI. ([64381](https://github.com/WordPress/gutenberg/pull/64381)) +- Core Data Types: `recordId` can be a number. ([64796](https://github.com/WordPress/gutenberg/pull/64796)) +- Core Data: Derive collection totals for unbound queries. ([64772](https://github.com/WordPress/gutenberg/pull/64772)) +- Create Block: Set minimum supported WordPress version to 6.6. ([64920](https://github.com/WordPress/gutenberg/pull/64920)) +- Dataviews Filter search widget: Do not use Composite store. ([64985](https://github.com/WordPress/gutenberg/pull/64985)) +- Dataviews list view: Do not use Composite store. ([64987](https://github.com/WordPress/gutenberg/pull/64987)) +- Move bulk actions menu to the Footer, consolidate with floating toolbar and total items display. ([64268](https://github.com/WordPress/gutenberg/pull/64268)) +- Try: Update block warnings. ([64997](https://github.com/WordPress/gutenberg/pull/64997)) + +#### Components +- Add variants to InputControl prefix/suffix wrappers. ([64824](https://github.com/WordPress/gutenberg/pull/64824)) +- AlignmentMatrixControl: Do not use Composite store. ([64850](https://github.com/WordPress/gutenberg/pull/64850)) +- CircularOptionPicker: Stop using composite store. ([64833](https://github.com/WordPress/gutenberg/pull/64833)) +- Composite: Accept store props on top level component. ([64832](https://github.com/WordPress/gutenberg/pull/64832)) +- DataViews: Adds two new stories for edge cases. ([64975](https://github.com/WordPress/gutenberg/pull/64975)) +- Decrease standard padding to 12px. ([64708](https://github.com/WordPress/gutenberg/pull/64708)) +- DropdownMenuV2: Add GroupLabel subcomponent. ([64854](https://github.com/WordPress/gutenberg/pull/64854)) +- DropdownMenuV2: Update animation. ([64868](https://github.com/WordPress/gutenberg/pull/64868)) +- DropdownMenuV2: Use overloaded naming conventions. ([64654](https://github.com/WordPress/gutenberg/pull/64654)) +- InputControl: Tighten gap between input and prefix/suffix. ([64908](https://github.com/WordPress/gutenberg/pull/64908)) +- Navigator: Polish Storybook examples. ([64798](https://github.com/WordPress/gutenberg/pull/64798)) +- Navigator: Remove location history, simplify internal logic. ([64675](https://github.com/WordPress/gutenberg/pull/64675)) +- UnitControl: Update unit select styles. ([64712](https://github.com/WordPress/gutenberg/pull/64712)) +- Update hard-coded border-radius instances. ([64693](https://github.com/WordPress/gutenberg/pull/64693)) +- Update modal animation. ([64580](https://github.com/WordPress/gutenberg/pull/64580)) + +#### Block bindings +- Add warning in attributes connected to invalid sources. ([65002](https://github.com/WordPress/gutenberg/pull/65002)) +- Allow only admin users to create and modify bindings by default. ([64570](https://github.com/WordPress/gutenberg/pull/64570)) +- Lock editing in fields in editor if meta fields panel is opened. ([64738](https://github.com/WordPress/gutenberg/pull/64738)) +- Rely on `Text` component instead of `Truncate` in bindings panel. ([65007](https://github.com/WordPress/gutenberg/pull/65007)) +- Remove `getPlaceholder` API and rely on `key` argument or source label. ([64910](https://github.com/WordPress/gutenberg/pull/64910)) + +#### Block Editor +- Add 'Reset' option to MediaReplaceFlow component. ([64826](https://github.com/WordPress/gutenberg/pull/64826)) +- Block Patterns List: Do not use Composite store. ([64983](https://github.com/WordPress/gutenberg/pull/64983)) +- Remove the Shuffle block toolbar button. ([64954](https://github.com/WordPress/gutenberg/pull/64954)) +- Show block icon in contentOnly toolbar. ([64694](https://github.com/WordPress/gutenberg/pull/64694)) + +#### Block Library +- Cover Block: Move Clear Media button from Inspector Controls to Block Controls. ([64630](https://github.com/WordPress/gutenberg/pull/64630)) +- Improve Social Icons setup and appending. ([64877](https://github.com/WordPress/gutenberg/pull/64877)) +- Pagination Block: Fix inconsistent margins between editor and frontend. ([64874](https://github.com/WordPress/gutenberg/pull/64874)) +- Tag Cloud: Improve state of block with no tags. ([63774](https://github.com/WordPress/gutenberg/pull/63774)) + +#### Block Locking +- ContentOnly: Add support for block styles on top-level contentOnly locked blocks. ([64872](https://github.com/WordPress/gutenberg/pull/64872)) +- Only show title in content only toolbar if has title value. ([64840](https://github.com/WordPress/gutenberg/pull/64840)) +- Remove ability to crop image if content only mode. ([64838](https://github.com/WordPress/gutenberg/pull/64838)) +- Rename Alt to Alternative Text in content only image toolbar. ([64841](https://github.com/WordPress/gutenberg/pull/64841)) + +#### Interactivity API +- Categories Block: Add iAPI directive for client-side routing. ([64907](https://github.com/WordPress/gutenberg/pull/64907)) +- Improve internal `deepMerge` function. ([64879](https://github.com/WordPress/gutenberg/pull/64879)) + +#### Global Styles +- Hide typeset button when there are no typesets available. ([64515](https://github.com/WordPress/gutenberg/pull/64515)) +- Use four color palette colors instead of five for useStylesPreviewColors. ([64700](https://github.com/WordPress/gutenberg/pull/64700)) + +#### Zoom Out +- Add "Edit" button to Zoom Out mode toolbar. ([64571](https://github.com/WordPress/gutenberg/pull/64571)) +- Double click block to exit zoom out mode. ([64573](https://github.com/WordPress/gutenberg/pull/64573)) + +#### Design Tools +- Comment Edit Link: Add Border Block Support. ([64239](https://github.com/WordPress/gutenberg/pull/64239)) +- Comment Reply Link: Add border support. ([64271](https://github.com/WordPress/gutenberg/pull/64271)) + +#### Icons +- Add thumbs up and down icons. ([65004](https://github.com/WordPress/gutenberg/pull/65004)) + +#### Site Editor +- Apply radius scale in the editor. ([64930](https://github.com/WordPress/gutenberg/pull/64930)) + +#### Post Editor +- Post publish upload media dialog: Handle upload errors. ([64823](https://github.com/WordPress/gutenberg/pull/64823)) + +#### Typography +- Fluid typography: Allow individual preset overrides. ([64790](https://github.com/WordPress/gutenberg/pull/64790)) + +#### Media +- Add experiment for client-side media processing. ([64650](https://github.com/WordPress/gutenberg/pull/64650)) + +#### REST API +- Core Data: Resolve entity collection user permissions. ([64504](https://github.com/WordPress/gutenberg/pull/64504)) + +#### Block Transforms +- Details block: Add transform from any block type. ([63422](https://github.com/WordPress/gutenberg/pull/63422)) + + +### New APIs + +#### Extensibility +- Editor: Add extensibility to PreviewOptions v2. ([64644](https://github.com/WordPress/gutenberg/pull/64644)) + + +### Bug Fixes + +- Add safeguard to `mediaUploadMiddleware`. ([64843](https://github.com/WordPress/gutenberg/pull/64843)) +- Allow multi-select on iOS Safari/touch devices. ([63671](https://github.com/WordPress/gutenberg/pull/63671)) +- Fix Modify content-locked menu item not showing if the block is not selected. ([61605](https://github.com/WordPress/gutenberg/pull/61605)) +- Fix editor error in Safari due to availability of checkVisibility method. ([65069](https://github.com/WordPress/gutenberg/pull/65069)) +- Fix: Pagination arrows are pointing in the wrong direction in RTL languages. ([64962](https://github.com/WordPress/gutenberg/pull/64962)) +- Footnotes: Only replace attribute if footnotes were detected. ([63935](https://github.com/WordPress/gutenberg/pull/63935)) +- Paste: Fix image paste from Google Forms. ([64502](https://github.com/WordPress/gutenberg/pull/64502)) +- Revert Focus pattern inserter search when activating zoom out inserter. ([64748](https://github.com/WordPress/gutenberg/pull/64748)) + +#### Block Library +- De-duplicate block toolbar icons for patterns. ([65054](https://github.com/WordPress/gutenberg/pull/65054)) +- Fix: Page list: Pages without a title has no link text. ([64297](https://github.com/WordPress/gutenberg/pull/64297)) +- Position BlockToolbar below all of the selected block's descendants. ([62711](https://github.com/WordPress/gutenberg/pull/62711)) +- Site Logo Block: Fix non-admin users seeing zero character. ([65010](https://github.com/WordPress/gutenberg/pull/65010)) +- Site Logo: Fix loader alignment issue. ([64919](https://github.com/WordPress/gutenberg/pull/64919)) +- Template Part: Hide Advanced panel for non-admin users. ([64721](https://github.com/WordPress/gutenberg/pull/64721)) +- Video Block: Fix layout issue. ([64834](https://github.com/WordPress/gutenberg/pull/64834)) + +#### Components +- ColorPalette utils: Do not normalize undefined color values. ([64969](https://github.com/WordPress/gutenberg/pull/64969)) +- DatePicker: Restore round radius for event dot. ([65031](https://github.com/WordPress/gutenberg/pull/65031)) +- DropdownMenuV2: Fix active and focus-visible item glitches. ([64942](https://github.com/WordPress/gutenberg/pull/64942)) +- DropdownMenuV2: Remove flashing styles when moving focus with keyboard. ([64873](https://github.com/WordPress/gutenberg/pull/64873)) +- Fixes "delete" action in DataViews' storybook. ([64901](https://github.com/WordPress/gutenberg/pull/64901)) +- Navigator: Fix isInitial, refine focusSelector logic. ([64786](https://github.com/WordPress/gutenberg/pull/64786)) +- Range control: Restore bottom margin rule. ([65035](https://github.com/WordPress/gutenberg/pull/65035)) + +#### Post Editor +- Add back editor-post-locked-modal to post lock component. ([64257](https://github.com/WordPress/gutenberg/pull/64257)) +- Add context to `View` string in post actions. ([65046](https://github.com/WordPress/gutenberg/pull/65046)) +- Apply space below content using a pseudo-element instead of padding-bottom. ([64639](https://github.com/WordPress/gutenberg/pull/64639)) +- Post Title: Fix pasting in Safari. ([64671](https://github.com/WordPress/gutenberg/pull/64671)) +- Post Title: Move selection at the end after pasting over the text. ([64665](https://github.com/WordPress/gutenberg/pull/64665)) +- Post publish upload media dialog: Fix silent failure. ([64741](https://github.com/WordPress/gutenberg/pull/64741)) + +#### Data Views +- DataViews: Fix field reordering and visibility logic. ([64999](https://github.com/WordPress/gutenberg/pull/64999)) +- Fix actions scrim in list layout. ([64696](https://github.com/WordPress/gutenberg/pull/64696)) +- Fix data views style inheritance. ([64933](https://github.com/WordPress/gutenberg/pull/64933)) +- Fix: Impossible to see pagination on viewports between small and medium. ([64844](https://github.com/WordPress/gutenberg/pull/64844)) +- List layout: Update broken styles. ([64837](https://github.com/WordPress/gutenberg/pull/64837)) + +#### Block Editor +- Add conditions when the Shuffle button can be displayed. ([64888](https://github.com/WordPress/gutenberg/pull/64888)) +- Inserter: Fix subtle media insertion error. ([65057](https://github.com/WordPress/gutenberg/pull/65057)) +- Post Editor: Fix click space after post content to append. ([64992](https://github.com/WordPress/gutenberg/pull/64992)) +- Writing flow: Fix triple click inside text blocks. ([64928](https://github.com/WordPress/gutenberg/pull/64928)) + +#### Global Styles +- Adjust spacing of background panel. ([64880](https://github.com/WordPress/gutenberg/pull/64880)) +- Cast globalFluid value to boolean. ([64882](https://github.com/WordPress/gutenberg/pull/64882)) +- Fix site editor broken when fontWeight is not defined or is an integer in theme.json or theme styles. ([64953](https://github.com/WordPress/gutenberg/pull/64953)) +- Fixes the default fluid value on the UI based on the global typography fluid value. ([64803](https://github.com/WordPress/gutenberg/pull/64803)) + +#### Block bindings +- Change placeholder when attribute is bound. ([64903](https://github.com/WordPress/gutenberg/pull/64903)) +- Fix empty custom fields not being editable in bindings. ([64881](https://github.com/WordPress/gutenberg/pull/64881)) + +#### CSS & Styling +- Featured Image Block: Reduce CSS specificity. ([64463](https://github.com/WordPress/gutenberg/pull/64463)) +- Retain the same specificity for non iframed selectors. ([64534](https://github.com/WordPress/gutenberg/pull/64534)) + +#### Patterns +- Pass 'blocks' as inner blocks value. ([65029](https://github.com/WordPress/gutenberg/pull/65029)) + +#### Synced Patterns +- Pattern: Don't render block controls when an entity is missing. ([65028](https://github.com/WordPress/gutenberg/pull/65028)) + +#### Site Editor +- DataViews: Fix pattern title direction in RTL languages. ([64967](https://github.com/WordPress/gutenberg/pull/64967)) + +#### NUX +- Fix visibility of the template Welcome Guide in the Site Editor. ([64789](https://github.com/WordPress/gutenberg/pull/64789)) + +#### Document Settings +- Fix: Adjust Site URL Styles to Prevent Overflow in Pre-Publish Component. ([64745](https://github.com/WordPress/gutenberg/pull/64745)) + +#### Zoom Out +- Focus selected block in editor canvas when clicking edit button on zoom out mode toolbar. ([64725](https://github.com/WordPress/gutenberg/pull/64725)) + +#### Templates API +- Make plugin-registered templates overriden by themes to fall back to plugin-registered title and description. ([64610](https://github.com/WordPress/gutenberg/pull/64610)) + +#### Block Style Variations +- Block Styles: Ensure unique classname generation for variations. ([64511](https://github.com/WordPress/gutenberg/pull/64511)) + +#### Distraction Free +- Make Distraction Free not conditional on viewport width. ([63949](https://github.com/WordPress/gutenberg/pull/63949)) + +#### Media +- Limit the max width of image to its container size. ([63341](https://github.com/WordPress/gutenberg/pull/63341)) + + +### Accessibility + +#### Components +- AlignmentMatrixControl: Simplify styles and markup. ([64827](https://github.com/WordPress/gutenberg/pull/64827)) +- TimePicker: Use ToggleGroupControl for AM/PM toggle. ([64800](https://github.com/WordPress/gutenberg/pull/64800)) + +#### Block Editor +- Layout content and wide width controls: Remove confusing icon and clarify labels. ([64891](https://github.com/WordPress/gutenberg/pull/64891)) + +#### Font Library +- Font Library Modal: Group font variations as a list. ([64029](https://github.com/WordPress/gutenberg/pull/64029)) + +#### Post Editor +- Fix the post summary Status toggle button accessibility. ([63988](https://github.com/WordPress/gutenberg/pull/63988)) + + +### Performance + +- Core Data: Avoid loops in 'registry.batch' calls. ([64955](https://github.com/WordPress/gutenberg/pull/64955)) +- Core data: Performance: Fix receive user permissions. ([64894](https://github.com/WordPress/gutenberg/pull/64894)) +- Reusable blocks: Fix performance of __experimentalGetAllowedPatterns. ([64871](https://github.com/WordPress/gutenberg/pull/64871)) + +#### Site Editor +- Add 'OPTIONS /page' to preloaded paths. ([64890](https://github.com/WordPress/gutenberg/pull/64890)) +- Editor: Don't use selector shortcuts for the Site data. ([64884](https://github.com/WordPress/gutenberg/pull/64884)) + +#### Block Library +- Media & Text: Don't use background-image. ([64981](https://github.com/WordPress/gutenberg/pull/64981)) + +#### Post Editor +- Editor: Remove create template permission check in 'VisualEditor'. ([64905](https://github.com/WordPress/gutenberg/pull/64905)) + +#### Block Editor +- Inserter: Use lighter grammar parse to check allowed status. ([64902](https://github.com/WordPress/gutenberg/pull/64902)) + +#### Patterns +- Shuffle: Don't call '__experimentalGetAllowedPatterns' for every block. ([64736](https://github.com/WordPress/gutenberg/pull/64736)) + + +### Experiments + +#### Zoom Out +- Add new zoom out experiment. ([65048](https://github.com/WordPress/gutenberg/pull/65048)) +- Remove the experiment that connects zoom out to the pattern inserter. ([65045](https://github.com/WordPress/gutenberg/pull/65045)) + + +### Documentation + +- Add a new section to the SlotFill reference to show how to conditionally render Fills. ([64807](https://github.com/WordPress/gutenberg/pull/64807)) +- Added Global Documentation in several php file. ([64956](https://github.com/WordPress/gutenberg/pull/64956)) +- Components: Move displayName assignment to top-level files. ([64793](https://github.com/WordPress/gutenberg/pull/64793)) +- Composite: Add context-forwarding with SlotFill example. ([65051](https://github.com/WordPress/gutenberg/pull/65051)) +- Composite: Fix Storybook docgen. ([64682](https://github.com/WordPress/gutenberg/pull/64682)) +- Corrected HTML Syntax for Closing Tags in api-reference.md file. ([64778](https://github.com/WordPress/gutenberg/pull/64778)) +- DataViews docs: Fix typo in `direction` values. ([64973](https://github.com/WordPress/gutenberg/pull/64973)) +- DataViews: Add story about combining fields. ([64984](https://github.com/WordPress/gutenberg/pull/64984)) +- DataViews: Document combined fields. ([64904](https://github.com/WordPress/gutenberg/pull/64904)) +- Dataviews docs: Layout properties checks and link. ([64918](https://github.com/WordPress/gutenberg/pull/64918)) +- Docs/iAPI: Fix wrong code snippets in API reference. ([64416](https://github.com/WordPress/gutenberg/pull/64416)) +- Docs: Update design resources to indicate edit isn't free. ([64792](https://github.com/WordPress/gutenberg/pull/64792)) +- PluginSidebarMoreMenuItem: Update example, screenshot and description. ([64761](https://github.com/WordPress/gutenberg/pull/64761)) +- Provide better examples and remove outdating site edit references for the MainDashboardButton SlotFill. ([64753](https://github.com/WordPress/gutenberg/pull/64753)) +- Removing ryanwelcher as a documentation codeowner because my inbox is dead. ([64762](https://github.com/WordPress/gutenberg/pull/64762)) +- Storybook: Hide deprecated `__next36pxDefaultSize` prop. ([64806](https://github.com/WordPress/gutenberg/pull/64806)) +- Update screenshot and description for PluginSidebar slot. ([64759](https://github.com/WordPress/gutenberg/pull/64759)) +- Update text to match code examples. ([64751](https://github.com/WordPress/gutenberg/pull/64751)) +- Update the import for PluginBlockSettingsMenuItem. ([64758](https://github.com/WordPress/gutenberg/pull/64758)) +- Updated Several Typos in Doc files. ([64787](https://github.com/WordPress/gutenberg/pull/64787)) +- [Docs]: Update Usage Example for block variation picker: Fix Import from Wrong Package. ([55555](https://github.com/WordPress/gutenberg/pull/55555)) + + +### Code Quality + +- Button: Add lint rule for 40px size prop usage. ([64835](https://github.com/WordPress/gutenberg/pull/64835)) +- Dataviews filter: Move resetValueOnSelect prop to combobox item. ([64852](https://github.com/WordPress/gutenberg/pull/64852)) +- Rename refs to fix tons of 'Mutating a value' errors in react-compiler. ([64718](https://github.com/WordPress/gutenberg/pull/64718)) +- Rich text: Add comment on placeholder approach. ([64945](https://github.com/WordPress/gutenberg/pull/64945)) +- SelectControl: Fix remaining 40px size violations. ([64831](https://github.com/WordPress/gutenberg/pull/64831)) +- Simplify useResizeObserver. ([64820](https://github.com/WordPress/gutenberg/pull/64820)) +- Typography: Backport comment changes only. ([64859](https://github.com/WordPress/gutenberg/pull/64859)) +- UnitControl: Add lint rule for 40px size prop usage. ([64520](https://github.com/WordPress/gutenberg/pull/64520)) +- UnitControl: Move to stricter lint rule for 40px size adherence. ([65017](https://github.com/WordPress/gutenberg/pull/65017)) +- Use rectIntersect instead of a custom argument to rectUnion. ([64855](https://github.com/WordPress/gutenberg/pull/64855)) + +#### Site Editor +- Add Custom Template modal: Do not use Composite store. ([65044](https://github.com/WordPress/gutenberg/pull/65044)) +- Add units to avoid console warning. ([64810](https://github.com/WordPress/gutenberg/pull/64810)) +- Edit Site Layout: Remove redundant fullResizer. ([64821](https://github.com/WordPress/gutenberg/pull/64821)) +- Remove unused 'useSiteEditorSettings' hook. ([64892](https://github.com/WordPress/gutenberg/pull/64892)) +- Style Book: Do not use Composite store. ([65047](https://github.com/WordPress/gutenberg/pull/65047)) + +#### Block Editor +- Block Inserter Listbox: Do not use Composite store. ([65042](https://github.com/WordPress/gutenberg/pull/65042)) +- Block Inserter Media List: Do not use Composite store. ([65043](https://github.com/WordPress/gutenberg/pull/65043)) +- Block Pattern Setup: Do not use Composite store. ([65039](https://github.com/WordPress/gutenberg/pull/65039)) +- Global Styles Shadow Panel: Do not use Composite store. ([65041](https://github.com/WordPress/gutenberg/pull/65041)) +- Pattern Transformations Menu: Do not use Composite store. ([65040](https://github.com/WordPress/gutenberg/pull/65040)) + +#### Zoom Out +- Add selector for getting section root clientId. ([65001](https://github.com/WordPress/gutenberg/pull/65001)) +- Don't pass 'rootClientId' to block lock selectors. ([64887](https://github.com/WordPress/gutenberg/pull/64887)) +- Fix error and improve privacy of sectionRootClientId setting. ([65000](https://github.com/WordPress/gutenberg/pull/65000)) + +#### Components +- AlignmentMatrixControl: Promote to stable. ([60913](https://github.com/WordPress/gutenberg/pull/60913)) +- Deprecate `DimensionControl`. ([64951](https://github.com/WordPress/gutenberg/pull/64951)) + +#### Block Library +- Block Bindings: Fix ESLint warnings. ([64684](https://github.com/WordPress/gutenberg/pull/64684)) +- Video Block: Remove custom CSS code for placeholder style. ([64861](https://github.com/WordPress/gutenberg/pull/64861)) + +#### Global Styles +- Allow referenced zero value and simplify getValueFromObjectPath calls. ([64836](https://github.com/WordPress/gutenberg/pull/64836)) +- Navigator: Replace deprecated NavigatorToParentButton with NavigatorBackButton. ([64775](https://github.com/WordPress/gutenberg/pull/64775)) + +#### Block Directory +- Downloadable Block List: Do not use composite store. ([65038](https://github.com/WordPress/gutenberg/pull/65038)) + +#### Design Tools +- Color panel hook: Rename to remove ambiguity. ([64993](https://github.com/WordPress/gutenberg/pull/64993)) + + +### Tools + +- Add remaining i18n rules to recommended ESLint ruleset. ([64710](https://github.com/WordPress/gutenberg/pull/64710)) +- Scripts: Added chunk filename in webpack configuration to avoid reading stale files. ([58176](https://github.com/WordPress/gutenberg/pull/58176)) +- Scripts: Import CSS files before optimization. ([61121](https://github.com/WordPress/gutenberg/pull/61121)) +- Scripts: Update `puppeteer-core` dependency. ([64597](https://github.com/WordPress/gutenberg/pull/64597)) + +#### Testing +- Flaky Test: Fix "Sorting" test in new-templates-list.spec.js. ([64776](https://github.com/WordPress/gutenberg/pull/64776)) +- Revert "Downgrade node 22(.5) unit tests to 22.4 (#63728)". ([63758](https://github.com/WordPress/gutenberg/pull/63758)) + + +### Various + +- Dataviews docs: Fixed property name for defaultLayouts settings. ([64897](https://github.com/WordPress/gutenberg/pull/64897)) +- task: Remove dcalhoun code owner. ([64886](https://github.com/WordPress/gutenberg/pull/64886)) + + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @Imran92: Fix site editor broken when fontWeight is not defined or is an integer in theme.json or theme styles. ([64953](https://github.com/WordPress/gutenberg/pull/64953)) +- @jacobcassidy: Scripts: Update `puppeteer-core` dependency. ([64597](https://github.com/WordPress/gutenberg/pull/64597)) +- @jawadmalikdev: [Docs]: Update Usage Example for block variation picker: Fix Import from Wrong Package. ([55555](https://github.com/WordPress/gutenberg/pull/55555)) +- @lezama: Editor: Add extensibility to PreviewOptions v2. ([64644](https://github.com/WordPress/gutenberg/pull/64644)) +- @rithik56: Scripts: Added chunk filename in webpack configuration to avoid reading stale files. ([58176](https://github.com/WordPress/gutenberg/pull/58176)) +- @rohitmathur-7: Cover Block: Move Clear Media button from Inspector Controls to Block Controls. ([64630](https://github.com/WordPress/gutenberg/pull/64630)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @afercia @akasunil @Aljullu @andrewserong @atachibana @benoitchantre @carolinan @cbravobernal @ciampo @DAreRodz @dcalhoun @desrosj @dsas @ellatrix @fullofcaffeine @getdave @gziolo @Imran92 @imrraaj @jacobcassidy @jameskoster @jasmussen @jawadmalikdev @jeryj @jorgefilipecosta @jsnajdr @juanmaguitar @kevin940726 @lezama @Mamaduka @matiasbenedetto @mirka @noisysocks @ntsekouras @oandregal @ockham @ramonjd @richtabor @rithik56 @rohitmathur-7 @ryanwelcher @SantosGuillamot @scruffian @sgomes @shail-mehta @spacedmonkey @stokesman @swissspidy @t-hamano @talldan @tjcafferkey @tyxla + + = 19.1.0 = ## Changelog From 57c59d1109f8c475eb2899dd7a4b1d5061a1df69 Mon Sep 17 00:00:00 2001 From: Devansh Chaudhary <58871818+devansh016@users.noreply.github.com> Date: Thu, 5 Sep 2024 23:07:57 +0530 Subject: [PATCH 0707/1908] Automatically add tel to phone number when linking url (#64865) Co-authored-by: devansh016 <devansh2002@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> --- packages/format-library/src/link/index.js | 9 ++++- packages/url/README.md | 18 +++++++++ packages/url/src/index.js | 1 + packages/url/src/is-phone-number.js | 19 +++++++++ packages/url/src/test/index.js | 47 +++++++++++++++++++++++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 packages/url/src/is-phone-number.js diff --git a/packages/format-library/src/link/index.js b/packages/format-library/src/link/index.js index ce1af0a36268ec..ef7008451698ae 100644 --- a/packages/format-library/src/link/index.js +++ b/packages/format-library/src/link/index.js @@ -12,7 +12,7 @@ import { insert, create, } from '@wordpress/rich-text'; -import { isURL, isEmail } from '@wordpress/url'; +import { isURL, isEmail, isPhoneNumber } from '@wordpress/url'; import { RichTextToolbarButton, RichTextShortcut, @@ -104,6 +104,13 @@ function Edit( { attributes: { url: `mailto:${ text }` }, } ) ); + } else if ( ! isActive && text && isPhoneNumber( text ) ) { + onChange( + applyFormat( value, { + type: name, + attributes: { url: `tel:${ text.replace( /\D/g, '' ) }` }, + } ) + ); } else { if ( target ) { setOpenedBy( { diff --git a/packages/url/README.md b/packages/url/README.md index 70e8579acc5182..0e4628669d11f2 100644 --- a/packages/url/README.md +++ b/packages/url/README.md @@ -322,6 +322,24 @@ _Returns_ - `boolean`: Whether or not it looks like an email. +### isPhoneNumber + +Determines whether the given string looks like a phone number. + +_Usage_ + +```js +const isPhoneNumber = isPhoneNumber( '+1 (555) 123-4567' ); // true +``` + +_Parameters_ + +- _phoneNumber_ `string`: The string to scrutinize. + +_Returns_ + +- `boolean`: Whether or not it looks like a phone number. + ### isURL Determines whether the given string looks like a URL. diff --git a/packages/url/src/index.js b/packages/url/src/index.js index 141e19d3fa55fd..378334ba131a6a 100644 --- a/packages/url/src/index.js +++ b/packages/url/src/index.js @@ -1,5 +1,6 @@ export { isURL } from './is-url'; export { isEmail } from './is-email'; +export { isPhoneNumber } from './is-phone-number'; export { getProtocol } from './get-protocol'; export { isValidProtocol } from './is-valid-protocol'; export { getAuthority } from './get-authority'; diff --git a/packages/url/src/is-phone-number.js b/packages/url/src/is-phone-number.js new file mode 100644 index 00000000000000..857b468bc52398 --- /dev/null +++ b/packages/url/src/is-phone-number.js @@ -0,0 +1,19 @@ +const PHONE_REGEXP = /^(tel:)?(\+)?\d{6,15}$/; + +/** + * Determines whether the given string looks like a phone number. + * + * @param {string} phoneNumber The string to scrutinize. + * + * @example + * ```js + * const isPhoneNumber = isPhoneNumber('+1 (555) 123-4567'); // true + * ``` + * + * @return {boolean} Whether or not it looks like a phone number. + */ +export function isPhoneNumber( phoneNumber ) { + // Remove any seperator from phone number. + phoneNumber = phoneNumber.replace( /[-.() ]/g, '' ); + return PHONE_REGEXP.test( phoneNumber ); +} diff --git a/packages/url/src/test/index.js b/packages/url/src/test/index.js index bd48105baed96d..4fc3d5e2970d67 100644 --- a/packages/url/src/test/index.js +++ b/packages/url/src/test/index.js @@ -17,6 +17,7 @@ import { hasQueryArg, isEmail, isURL, + isPhoneNumber, isValidAuthority, isValidFragment, isValidPath, @@ -73,6 +74,52 @@ describe( 'isEmail', () => { ); } ); +describe( 'isPhoneNumber', () => { + it.each( [ + '+1 (555) 123-4567', + '(555) 123-4567', + '555-123-4567', + '5551234567', + '+91 987 654 3210', + '123-456-7890', + '(123) 456-7890', + '123 456 7890', + '123.456.7890', + '+1 123 456 7890', + '1234567890', + '+44 791 112 3456', + '(123) 4567', + '+1 (123) 45678901', + '12-34-56', + '123456789012345', + '+12 3456789012345', + 'tel:+1-123-456-7890', + ] )( + 'returns true when given things that look like a phone number: %s', + ( phoneNumber ) => { + expect( isPhoneNumber( phoneNumber ) ).toBe( true ); + } + ); + + it.each( [ + 'not a phone number', + '123', + '1234', + '12345', + '+91 123', + 'abc-def-ghij', + 'a123456789b', + '12-34-5', + 'tel:911', + 'tel:12345', + ] )( + "returns false when given things that don't look like a phone number: %s", + ( phoneNumber ) => { + expect( isPhoneNumber( phoneNumber ) ).toBe( false ); + } + ); +} ); + describe( 'getProtocol', () => { it( 'returns the protocol part of a URL', () => { expect( From 9523fb4a6d568f34a217c9cab45f29413c4904f7 Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Thu, 5 Sep 2024 21:24:58 +0200 Subject: [PATCH 0708/1908] Add new Media section to preferences modal (#64846) --- packages/edit-post/src/index.js | 7 + packages/edit-site/src/index.js | 7 + .../src/components/preferences-modal/index.js | 386 ++++++++++-------- 3 files changed, 228 insertions(+), 172 deletions(-) diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index 10f4a9838c8dad..51abac654da295 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -73,6 +73,13 @@ export function initializeEditor( isPublishSidebarEnabled: true, } ); + if ( window.__experimentalMediaProcessing ) { + dispatch( preferencesStore ).setDefaults( 'core/media', { + requireApproval: true, + optimizeOnUpload: true, + } ); + } + dispatch( blocksStore ).reapplyBlockTypeFilters(); // Check if the block list view should be open by default. diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 9face28c1bfe19..4ed5b96e3844d1 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -81,6 +81,13 @@ export function initializeEditor( id, settings ) { showListViewByDefault: false, } ); + if ( window.__experimentalMediaProcessing ) { + dispatch( preferencesStore ).setDefaults( 'core/media', { + requireApproval: true, + optimizeOnUpload: true, + } ); + } + dispatch( editSiteStore ).updateSettings( settings ); // Keep the defaultTemplateTypes in the core/editor settings too, diff --git a/packages/editor/src/components/preferences-modal/index.js b/packages/editor/src/components/preferences-modal/index.js index f3378d76d994b2..e7cc637dd0aed0 100644 --- a/packages/editor/src/components/preferences-modal/index.js +++ b/packages/editor/src/components/preferences-modal/index.js @@ -59,212 +59,254 @@ export default function EditorPreferencesModal( { extraSections = {} } ) { const { set: setPreference } = useDispatch( preferencesStore ); const sections = useMemo( - () => [ - { - name: 'general', - tabLabel: __( 'General' ), - content: ( - <> - <PreferencesModalSection title={ __( 'Interface' ) }> - <PreferenceToggleControl - scope="core" - featureName="showListViewByDefault" - help={ __( - 'Opens the List View sidebar by default.' - ) } - label={ __( 'Always open List View' ) } - /> - { showBlockBreadcrumbsOption && ( + () => + [ + { + name: 'general', + tabLabel: __( 'General' ), + content: ( + <> + <PreferencesModalSection + title={ __( 'Interface' ) } + > <PreferenceToggleControl scope="core" - featureName="showBlockBreadcrumbs" + featureName="showListViewByDefault" help={ __( - 'Display the block hierarchy trail at the bottom of the editor.' + 'Opens the List View sidebar by default.' ) } - label={ __( 'Show block breadcrumbs' ) } + label={ __( 'Always open List View' ) } /> - ) } - <PreferenceToggleControl - scope="core" - featureName="allowRightClickOverrides" - help={ __( - 'Allows contextual List View menus via right-click, overriding browser defaults.' - ) } - label={ __( - 'Allow right-click contextual menus' - ) } - /> - </PreferencesModalSection> - <PreferencesModalSection - title={ __( 'Document settings' ) } - description={ __( - 'Select what settings are shown in the document panel.' - ) } - > - <EnablePluginDocumentSettingPanelOption.Slot /> - <PostTaxonomies - taxonomyWrapper={ ( content, taxonomy ) => ( - <EnablePanelOption - label={ taxonomy.labels.menu_name } - panelName={ `taxonomy-panel-${ taxonomy.slug }` } + { showBlockBreadcrumbsOption && ( + <PreferenceToggleControl + scope="core" + featureName="showBlockBreadcrumbs" + help={ __( + 'Display the block hierarchy trail at the bottom of the editor.' + ) } + label={ __( 'Show block breadcrumbs' ) } /> ) } - /> - <PostFeaturedImageCheck> - <EnablePanelOption - label={ __( 'Featured image' ) } - panelName="featured-image" - /> - </PostFeaturedImageCheck> - <PostExcerptCheck> - <EnablePanelOption - label={ __( 'Excerpt' ) } - panelName="post-excerpt" - /> - </PostExcerptCheck> - <PostTypeSupportCheck - supportKeys={ [ 'comments', 'trackbacks' ] } - > - <EnablePanelOption - label={ __( 'Discussion' ) } - panelName="discussion-panel" - /> - </PostTypeSupportCheck> - <PageAttributesCheck> - <EnablePanelOption - label={ __( 'Page attributes' ) } - panelName="page-attributes" + <PreferenceToggleControl + scope="core" + featureName="allowRightClickOverrides" + help={ __( + 'Allows contextual List View menus via right-click, overriding browser defaults.' + ) } + label={ __( + 'Allow right-click contextual menus' + ) } /> - </PageAttributesCheck> - </PreferencesModalSection> - { isLargeViewport && ( + </PreferencesModalSection> <PreferencesModalSection - title={ __( 'Publishing' ) } + title={ __( 'Document settings' ) } + description={ __( + 'Select what settings are shown in the document panel.' + ) } > - <EnablePublishSidebarOption - help={ __( - 'Review settings, such as visibility and tags.' + <EnablePluginDocumentSettingPanelOption.Slot /> + <PostTaxonomies + taxonomyWrapper={ ( content, taxonomy ) => ( + <EnablePanelOption + label={ taxonomy.labels.menu_name } + panelName={ `taxonomy-panel-${ taxonomy.slug }` } + /> ) } - label={ __( 'Enable pre-publish checks' ) } /> + <PostFeaturedImageCheck> + <EnablePanelOption + label={ __( 'Featured image' ) } + panelName="featured-image" + /> + </PostFeaturedImageCheck> + <PostExcerptCheck> + <EnablePanelOption + label={ __( 'Excerpt' ) } + panelName="post-excerpt" + /> + </PostExcerptCheck> + <PostTypeSupportCheck + supportKeys={ [ 'comments', 'trackbacks' ] } + > + <EnablePanelOption + label={ __( 'Discussion' ) } + panelName="discussion-panel" + /> + </PostTypeSupportCheck> + <PageAttributesCheck> + <EnablePanelOption + label={ __( 'Page attributes' ) } + panelName="page-attributes" + /> + </PageAttributesCheck> </PreferencesModalSection> - ) } - { extraSections?.general } - </> - ), - }, - { - name: 'appearance', - tabLabel: __( 'Appearance' ), - content: ( - <PreferencesModalSection - title={ __( 'Appearance' ) } - description={ __( - 'Customize the editor interface to suit your needs.' - ) } - > - <PreferenceToggleControl - scope="core" - featureName="fixedToolbar" - onToggle={ () => - setPreference( - 'core', - 'distractionFree', - false - ) - } - help={ __( - 'Access all block and document tools in a single place.' - ) } - label={ __( 'Top toolbar' ) } - /> - <PreferenceToggleControl - scope="core" - featureName="distractionFree" - onToggle={ () => { - setPreference( 'core', 'fixedToolbar', true ); - setIsInserterOpened( false ); - setIsListViewOpened( false ); - } } - help={ __( - 'Reduce visual distractions by hiding the toolbar and other elements to focus on writing.' - ) } - label={ __( 'Distraction free' ) } - /> - <PreferenceToggleControl - scope="core" - featureName="focusMode" - help={ __( - 'Highlights the current block and fades other content.' + { isLargeViewport && ( + <PreferencesModalSection + title={ __( 'Publishing' ) } + > + <EnablePublishSidebarOption + help={ __( + 'Review settings, such as visibility and tags.' + ) } + label={ __( + 'Enable pre-publish checks' + ) } + /> + </PreferencesModalSection> ) } - label={ __( 'Spotlight mode' ) } - /> - { extraSections?.appearance } - </PreferencesModalSection> - ), - }, - { - name: 'accessibility', - tabLabel: __( 'Accessibility' ), - content: ( - <> + { extraSections?.general } + </> + ), + }, + { + name: 'appearance', + tabLabel: __( 'Appearance' ), + content: ( <PreferencesModalSection - title={ __( 'Navigation' ) } + title={ __( 'Appearance' ) } description={ __( - 'Optimize the editing experience for enhanced control.' + 'Customize the editor interface to suit your needs.' ) } > <PreferenceToggleControl scope="core" - featureName="keepCaretInsideBlock" + featureName="fixedToolbar" + onToggle={ () => + setPreference( + 'core', + 'distractionFree', + false + ) + } help={ __( - 'Keeps the text cursor within the block boundaries, aiding users with screen readers by preventing unintentional cursor movement outside the block.' - ) } - label={ __( - 'Contain text cursor inside block' + 'Access all block and document tools in a single place.' ) } + label={ __( 'Top toolbar' ) } /> - </PreferencesModalSection> - <PreferencesModalSection title={ __( 'Interface' ) }> <PreferenceToggleControl scope="core" - featureName="showIconLabels" - label={ __( 'Show button text labels' ) } + featureName="distractionFree" + onToggle={ () => { + setPreference( + 'core', + 'fixedToolbar', + true + ); + setIsInserterOpened( false ); + setIsListViewOpened( false ); + } } help={ __( - 'Show text instead of icons on buttons across the interface.' + 'Reduce visual distractions by hiding the toolbar and other elements to focus on writing.' ) } + label={ __( 'Distraction free' ) } /> - </PreferencesModalSection> - </> - ), - }, - { - name: 'blocks', - tabLabel: __( 'Blocks' ), - content: ( - <> - <PreferencesModalSection title={ __( 'Inserter' ) }> <PreferenceToggleControl scope="core" - featureName="mostUsedBlocks" + featureName="focusMode" help={ __( - 'Adds a category with the most frequently used blocks in the inserter.' + 'Highlights the current block and fades other content.' ) } - label={ __( 'Show most used blocks' ) } + label={ __( 'Spotlight mode' ) } /> + { extraSections?.appearance } </PreferencesModalSection> - <PreferencesModalSection - title={ __( 'Manage block visibility' ) } - description={ __( - "Disable blocks that you don't want to appear in the inserter. They can always be toggled back on later." - ) } - > - <BlockManager /> - </PreferencesModalSection> - </> - ), - }, - ], + ), + }, + { + name: 'accessibility', + tabLabel: __( 'Accessibility' ), + content: ( + <> + <PreferencesModalSection + title={ __( 'Navigation' ) } + description={ __( + 'Optimize the editing experience for enhanced control.' + ) } + > + <PreferenceToggleControl + scope="core" + featureName="keepCaretInsideBlock" + help={ __( + 'Keeps the text cursor within the block boundaries, aiding users with screen readers by preventing unintentional cursor movement outside the block.' + ) } + label={ __( + 'Contain text cursor inside block' + ) } + /> + </PreferencesModalSection> + <PreferencesModalSection + title={ __( 'Interface' ) } + > + <PreferenceToggleControl + scope="core" + featureName="showIconLabels" + label={ __( 'Show button text labels' ) } + help={ __( + 'Show text instead of icons on buttons across the interface.' + ) } + /> + </PreferencesModalSection> + </> + ), + }, + { + name: 'blocks', + tabLabel: __( 'Blocks' ), + content: ( + <> + <PreferencesModalSection title={ __( 'Inserter' ) }> + <PreferenceToggleControl + scope="core" + featureName="mostUsedBlocks" + help={ __( + 'Adds a category with the most frequently used blocks in the inserter.' + ) } + label={ __( 'Show most used blocks' ) } + /> + </PreferencesModalSection> + <PreferencesModalSection + title={ __( 'Manage block visibility' ) } + description={ __( + "Disable blocks that you don't want to appear in the inserter. They can always be toggled back on later." + ) } + > + <BlockManager /> + </PreferencesModalSection> + </> + ), + }, + window.__experimentalMediaProcessing && { + name: 'media', + tabLabel: __( 'Media' ), + content: ( + <> + <PreferencesModalSection + title={ __( 'General' ) } + description={ __( + 'Customize options related to the media upload flow.' + ) } + > + <PreferenceToggleControl + scope="core/media" + featureName="optimizeOnUpload" + help={ __( + 'Compress media items before uploading to the server.' + ) } + label={ __( 'Pre-upload compression' ) } + /> + <PreferenceToggleControl + scope="core/media" + featureName="requireApproval" + help={ __( + 'Require approval step when optimizing existing media.' + ) } + label={ __( 'Approval step' ) } + /> + </PreferencesModalSection> + </> + ), + }, + ].filter( Boolean ), [ showBlockBreadcrumbsOption, extraSections, From 1a8aa20d057e6bd623d3ff8178b2d67de2845dcc Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Fri, 6 Sep 2024 16:45:26 +1000 Subject: [PATCH 0709/1908] Cover: Explicitly set isUserOverlayColor to false when media is updated (#65105) Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: huubl <huubl@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> --- packages/block-library/src/cover/deprecated.js | 5 +++-- packages/block-library/src/cover/edit/index.js | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/cover/deprecated.js b/packages/block-library/src/cover/deprecated.js index c5f430eead685f..5e5fc64d12c16f 100644 --- a/packages/block-library/src/cover/deprecated.js +++ b/packages/block-library/src/cover/deprecated.js @@ -400,8 +400,9 @@ const v12 = { supports: v12BlockSupports, isEligible( attributes ) { return ( - attributes.customOverlayColor !== undefined || - attributes.overlayColor !== undefined + ( attributes.customOverlayColor !== undefined || + attributes.overlayColor !== undefined ) && + attributes.isUserOverlayColor === undefined ); }, migrate( attributes ) { diff --git a/packages/block-library/src/cover/edit/index.js b/packages/block-library/src/cover/edit/index.js index 3f68c08b632ace..ec62bd58a2c33a 100644 --- a/packages/block-library/src/cover/edit/index.js +++ b/packages/block-library/src/cover/edit/index.js @@ -143,7 +143,10 @@ function CoverEdit( { averageBackgroundColor ); __unstableMarkNextChangeAsNotPersistent(); - setAttributes( { isDark: newIsDark } ); + setAttributes( { + isDark: newIsDark, + isUserOverlayColor: isUserOverlayColor || false, + } ); } )(); // Disable reason: Update the block only when the featured image changes. // eslint-disable-next-line react-hooks/exhaustive-deps @@ -201,6 +204,7 @@ function CoverEdit( { useFeaturedImage: undefined, dimRatio: newDimRatio, isDark: newIsDark, + isUserOverlayColor: isUserOverlayColor || false, } ); }; From db44c137bcf9d848f8f95c6a34fd3540866b6006 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Fri, 6 Sep 2024 09:56:26 +0200 Subject: [PATCH 0710/1908] Update: Rephrase "Force page reload" and move to Advanced (#65081) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update: Rephrase "Force page reload" and move to Advanced * Linting. * Update help text. * Update packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> * Update packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js --------- Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> Unlinked contributors: jarekmorawski, michaelpick. Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: luisherranz <luisherranz@git.wordpress.org> Co-authored-by: joedolson <joedolson@git.wordpress.org> --- .../src/query/edit/enhanced-pagination-modal.js | 4 ++-- .../inspector-controls/enhanced-pagination-control.js | 6 +++--- .../src/query/edit/inspector-controls/index.js | 11 ++--------- .../block-library/src/query/edit/query-content.js | 7 +++++++ 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/block-library/src/query/edit/enhanced-pagination-modal.js b/packages/block-library/src/query/edit/enhanced-pagination-modal.js index f33c45646e536b..38167f7259380c 100644 --- a/packages/block-library/src/query/edit/enhanced-pagination-modal.js +++ b/packages/block-library/src/query/edit/enhanced-pagination-modal.js @@ -42,7 +42,7 @@ export default function EnhancedPaginationModal( { }; let notice = __( - 'If you still want to prevent full page reloads, remove that block, then disable "Force page reload" again in the Query Block settings.' + 'If you still want to prevent full page reloads, remove that block, then disable "Reload full page" again in the Query Block settings.' ); if ( hasBlocksFromPlugins ) { notice = @@ -63,7 +63,7 @@ export default function EnhancedPaginationModal( { return ( isOpen && ( <Modal - title={ __( 'Query block: Force page reload enabled' ) } + title={ __( 'Query block: Reload full page enabled' ) } className="wp-block-query__enhanced-pagination-modal" aria={ { describedby: modalDescriptionId, diff --git a/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js b/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js index e1001cda4dab39..9d47d67e61d781 100644 --- a/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js +++ b/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js @@ -25,11 +25,11 @@ export default function EnhancedPaginationControl( { ); } else if ( enhancedPagination ) { help = __( - "Browsing between pages won't require a full page reload, unless non-compatible blocks are detected." + 'Reload the full page—instead of just the posts list—when visitors navigate between pages.' ); } else if ( hasUnsupportedBlocks ) { help = __( - "Force page reload can't be disabled because there are non-compatible blocks inside the Query block." + 'Enhancement disabled because there are non-compatible blocks inside the Query block.' ); } @@ -37,7 +37,7 @@ export default function EnhancedPaginationControl( { <> <ToggleControl __nextHasNoMarginBottom - label={ __( 'Force page reload' ) } + label={ __( 'Reload full page' ) } help={ help } checked={ ! enhancedPagination && ! fullPageClientSideNavigation diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index 2601430329092f..010e57b2da4fc6 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -25,7 +25,6 @@ import AuthorControl from './author-control'; import ParentControl from './parent-control'; import { TaxonomyControls } from './taxonomy-controls'; import StickyControl from './sticky-control'; -import EnhancedPaginationControl from './enhanced-pagination-control'; import CreateNewPostLink from './create-new-post-link'; import PerPageControl from './per-page-control'; import OffsetControl from './offset-controls'; @@ -43,9 +42,8 @@ import { useToolsPanelDropdownMenuProps } from '../../../utils/hooks'; const { BlockInfo } = unlock( blockEditorPrivateApis ); export default function QueryInspectorControls( props ) { - const { attributes, setQuery, setDisplayLayout, setAttributes, clientId } = - props; - const { query, displayLayout, enhancedPagination } = attributes; + const { attributes, setQuery, setDisplayLayout } = props; + const { query, displayLayout } = attributes; const { order, orderBy, @@ -262,11 +260,6 @@ export default function QueryInspectorControls( props ) { } /> ) } - <EnhancedPaginationControl - enhancedPagination={ enhancedPagination } - setAttributes={ setAttributes } - clientId={ clientId } - /> </PanelBody> ) } { ! inherit && showDisplayPanel && ( diff --git a/packages/block-library/src/query/edit/query-content.js b/packages/block-library/src/query/edit/query-content.js index 949ffc653420fe..4624b3b96049e9 100644 --- a/packages/block-library/src/query/edit/query-content.js +++ b/packages/block-library/src/query/edit/query-content.js @@ -18,6 +18,7 @@ import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies */ +import EnhancedPaginationControl from './inspector-controls/enhanced-pagination-control'; import QueryToolbar from './query-toolbar'; import QueryInspectorControls from './inspector-controls'; import EnhancedPaginationModal from './enhanced-pagination-modal'; @@ -36,6 +37,7 @@ export default function QueryContent( { queryId, query, displayLayout, + enhancedPagination, tagName: TagName = 'div', query: { inherit } = {}, } = attributes; @@ -161,6 +163,11 @@ export default function QueryContent( { } help={ htmlElementMessages[ TagName ] } /> + <EnhancedPaginationControl + enhancedPagination={ enhancedPagination } + setAttributes={ setAttributes } + clientId={ clientId } + /> </InspectorControls> <TagName { ...innerBlocksProps } /> </> From 6bbdd1e649ad5c12f62f2d42c1d22e50e1fc84c5 Mon Sep 17 00:00:00 2001 From: Ben Dwyer <ben@scruffian.com> Date: Fri, 6 Sep 2024 08:57:59 +0100 Subject: [PATCH 0711/1908] Zoom Out: Force device type to Desktop whenever zoom out is invoked (#64476) --- packages/editor/src/store/selectors.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index 8b0dfd4b370c41..f890dcac397326 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -1276,9 +1276,15 @@ export function getRenderingMode( state ) { * * @return {string} Device type. */ -export function getDeviceType( state ) { - return state.deviceType; -} +export const getDeviceType = createRegistrySelector( + ( select ) => ( state ) => { + const editorMode = select( blockEditorStore ).__unstableGetEditorMode(); + if ( editorMode === 'zoom-out' ) { + return 'Desktop'; + } + return state.deviceType; + } +); /** * Returns true if the list view is opened. From 7051a8f23d8c2b39a7c6cdc1536ad498d6ce39b0 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 6 Sep 2024 12:25:28 +0400 Subject: [PATCH 0712/1908] Block Editor: Remove the 'PrivateInserter' component (#65111) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../block-editor/src/components/inserter/index.js | 14 ++++---------- packages/block-editor/src/private-apis.js | 2 -- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/components/inserter/index.js b/packages/block-editor/src/components/inserter/index.js index d3e7dba0df6838..1af81d0231a1a8 100644 --- a/packages/block-editor/src/components/inserter/index.js +++ b/packages/block-editor/src/components/inserter/index.js @@ -9,7 +9,7 @@ import clsx from 'clsx'; import { speak } from '@wordpress/a11y'; import { __, _x, sprintf } from '@wordpress/i18n'; import { Dropdown, Button } from '@wordpress/components'; -import { forwardRef, Component } from '@wordpress/element'; +import { Component } from '@wordpress/element'; import { withDispatch, withSelect } from '@wordpress/data'; import { compose, ifCondition } from '@wordpress/compose'; import { createBlock, store as blocksStore } from '@wordpress/blocks'; @@ -76,7 +76,7 @@ const defaultRenderToggle = ( { ); }; -class PrivateInserter extends Component { +class Inserter extends Component { constructor() { super( ...arguments ); @@ -222,7 +222,7 @@ class PrivateInserter extends Component { } } -export const ComposedPrivateInserter = compose( [ +export default compose( [ withSelect( ( select, { clientId, rootClientId, shouldDirectInsert = true } ) => { const { @@ -418,10 +418,4 @@ export const ComposedPrivateInserter = compose( [ ( { hasItems, isAppender, rootClientId, clientId } ) => hasItems || ( ! isAppender && ! rootClientId && ! clientId ) ), -] )( PrivateInserter ); - -const Inserter = forwardRef( ( props, ref ) => { - return <ComposedPrivateInserter ref={ ref } { ...props } />; -} ); - -export default Inserter; +] )( Inserter ); diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 404c94940058ad..12f477a95a196b 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -6,7 +6,6 @@ import { ExperimentalBlockEditorProvider } from './components/provider'; import { lock } from './lock-unlock'; import { getRichTextValues } from './components/rich-text/get-rich-text-values'; import ResizableBoxPopover from './components/resizable-box-popover'; -import { ComposedPrivateInserter as PrivateInserter } from './components/inserter'; import { default as PrivateQuickInserter } from './components/inserter/quick-inserter'; import { extractWords, @@ -60,7 +59,6 @@ lock( privateApis, { ExperimentalBlockEditorProvider, getDuotoneFilter, getRichTextValues, - PrivateInserter, PrivateQuickInserter, extractWords, getNormalizedSearchTerms, From 0fc06de23449b518fa8412d7dcab738c0805df45 Mon Sep 17 00:00:00 2001 From: Vipul Gupta <55375170+vipul0425@users.noreply.github.com> Date: Fri, 6 Sep 2024 14:27:46 +0530 Subject: [PATCH 0713/1908] Fix: Button Replace remaining 40px default size violations [Block Editor 1]. (#65034) * feat: Adds 40px height in multiple usage warning. * feat: Adds 4px size in invalid warining. * feat: Adds the 40px size in block compare component. * feat: Makes the __next40pxDefaultSize true in block mover and breadcrumbs. * fix: block compare default size. * fix: Invlid warning button size. * fix: Adds size prop to breadcrumb buttons. * fix: Updates the snapshot. * refactor: Removes extra button [custom styles. --- Co-authored-by: vipul0425 <vipulgupta003@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../src/components/block-breadcrumb/index.js | 8 ++--- .../components/block-breadcrumb/style.scss | 31 +------------------ .../components/block-compare/block-view.js | 3 +- .../test/__snapshots__/block-view.js.snap | 2 +- .../block-edit/multiple-usage-warning.js | 6 ++-- .../block-list/block-invalid-warning.js | 3 +- .../src/components/block-mover/button.js | 3 +- .../src/components/block-mover/index.js | 3 +- 8 files changed, 10 insertions(+), 49 deletions(-) diff --git a/packages/block-editor/src/components/block-breadcrumb/index.js b/packages/block-editor/src/components/block-breadcrumb/index.js index 8a70616d358d9e..440d9611d278be 100644 --- a/packages/block-editor/src/components/block-breadcrumb/index.js +++ b/packages/block-editor/src/components/block-breadcrumb/index.js @@ -66,10 +66,8 @@ function BlockBreadcrumb( { rootLabelText } ) { > { hasSelection && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + size="small" className="block-editor-block-breadcrumb__button" - variant="tertiary" onClick={ () => { // Find the block editor wrapper for the selected block const blockEditor = blockRef.current?.closest( @@ -96,10 +94,8 @@ function BlockBreadcrumb( { rootLabelText } ) { { parents.map( ( parentClientId ) => ( <li key={ parentClientId }> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + size="small" className="block-editor-block-breadcrumb__button" - variant="tertiary" onClick={ () => selectBlock( parentClientId ) } > <BlockTitle diff --git a/packages/block-editor/src/components/block-breadcrumb/style.scss b/packages/block-editor/src/components/block-breadcrumb/style.scss index 78d422d7b09978..af56971fe4c5c9 100644 --- a/packages/block-editor/src/components/block-breadcrumb/style.scss +++ b/packages/block-editor/src/components/block-breadcrumb/style.scss @@ -22,40 +22,11 @@ } } -.block-editor-block-breadcrumb__button.components-button { - height: $button-size-small; - line-height: $button-size-small; - padding: 0; - position: relative; - - &:hover:not(:disabled) { - text-decoration: underline; - box-shadow: none; - } - - &:focus { - box-shadow: none; - } - - &:focus::before { - content: ""; - display: block; - position: absolute; - border-radius: $radius-small; - top: $border-width; - right: $border-width; - bottom: $border-width; - left: $border-width; - - @include button-style__focus(); - } -} - .block-editor-block-breadcrumb__current { cursor: default; } -.block-editor-block-breadcrumb__button.components-button, +.block-editor-block-breadcrumb__button.block-editor-block-breadcrumb__button, .block-editor-block-breadcrumb__current { color: $gray-900; padding: 0 $grid-unit-10; diff --git a/packages/block-editor/src/components/block-compare/block-view.js b/packages/block-editor/src/components/block-compare/block-view.js index 55492fb2d76ae9..48a13540e78425 100644 --- a/packages/block-editor/src/components/block-compare/block-view.js +++ b/packages/block-editor/src/components/block-compare/block-view.js @@ -31,8 +31,7 @@ export default function BlockView( { <div className="block-editor-block-compare__action"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="secondary" tabIndex="0" onClick={ action } diff --git a/packages/block-editor/src/components/block-compare/test/__snapshots__/block-view.js.snap b/packages/block-editor/src/components/block-compare/test/__snapshots__/block-view.js.snap index f8abe9753c0310..c90f2bac7365ab 100644 --- a/packages/block-editor/src/components/block-compare/test/__snapshots__/block-view.js.snap +++ b/packages/block-editor/src/components/block-compare/test/__snapshots__/block-view.js.snap @@ -30,7 +30,7 @@ exports[`BlockView should match snapshot 1`] = ` class="block-editor-block-compare__action" > <button - class="components-button is-secondary" + class="components-button is-next-40px-default-size is-secondary" tabindex="0" type="button" > diff --git a/packages/block-editor/src/components/block-edit/multiple-usage-warning.js b/packages/block-editor/src/components/block-edit/multiple-usage-warning.js index bff12342904537..ac83b0e5c11315 100644 --- a/packages/block-editor/src/components/block-edit/multiple-usage-warning.js +++ b/packages/block-editor/src/components/block-edit/multiple-usage-warning.js @@ -24,8 +24,7 @@ export function MultipleUsageWarning( { <Warning actions={ [ <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize key="find-original" variant="secondary" onClick={ () => selectBlock( originalBlockClientId ) } @@ -33,8 +32,7 @@ export function MultipleUsageWarning( { { __( 'Find original' ) } </Button>, <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize key="remove" variant="secondary" onClick={ () => onReplace( [] ) } diff --git a/packages/block-editor/src/components/block-list/block-invalid-warning.js b/packages/block-editor/src/components/block-list/block-invalid-warning.js index fb235cbce9ca21..a35ecaf6bae8eb 100644 --- a/packages/block-editor/src/components/block-list/block-invalid-warning.js +++ b/packages/block-editor/src/components/block-list/block-invalid-warning.js @@ -101,8 +101,7 @@ export default function BlockInvalidWarning( { clientId } ) { <Warning actions={ [ <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize key="recover" onClick={ convert.toRecoveredBlock } variant="primary" diff --git a/packages/block-editor/src/components/block-mover/button.js b/packages/block-editor/src/components/block-mover/button.js index 98c0aff79eff38..76b46701758e8d 100644 --- a/packages/block-editor/src/components/block-mover/button.js +++ b/packages/block-editor/src/components/block-mover/button.js @@ -129,8 +129,7 @@ const BlockMoverButton = forwardRef( return ( <> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize ref={ ref } className={ clsx( 'block-editor-block-mover-button', diff --git a/packages/block-editor/src/components/block-mover/index.js b/packages/block-editor/src/components/block-mover/index.js index 1e846227c793bd..4e993252ef974f 100644 --- a/packages/block-editor/src/components/block-mover/index.js +++ b/packages/block-editor/src/components/block-mover/index.js @@ -87,8 +87,7 @@ function BlockMover( { <BlockDraggable clientIds={ clientIds } fadeWhenDisabled> { ( draggableProps ) => ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize icon={ dragHandle } className="block-editor-block-mover__drag-handle" label={ __( 'Drag' ) } From 6403b32a00be3b4438a3641b5efe8fadd72ff575 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Fri, 6 Sep 2024 11:28:23 +0200 Subject: [PATCH 0714/1908] Restore: Move to trash button in Document settings (#65087) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- .../editor/src/components/post-trash/check.js | 7 +++++-- .../editor/src/components/post-trash/index.js | 18 +++++++++++------- .../src/components/sidebar/post-summary.js | 2 ++ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/packages/editor/src/components/post-trash/check.js b/packages/editor/src/components/post-trash/check.js index 8f51df175c898c..7edc7c0f18c273 100644 --- a/packages/editor/src/components/post-trash/check.js +++ b/packages/editor/src/components/post-trash/check.js @@ -8,6 +8,7 @@ import { store as coreStore } from '@wordpress/core-data'; * Internal dependencies */ import { store as editorStore } from '../../store'; +import { GLOBAL_POST_TYPES } from '../../store/constants'; /** * Wrapper component that renders its children only if the post can trashed. @@ -34,10 +35,12 @@ export default function PostTrashCheck( { children } ) { : false; return { - canTrashPost: ( ! isNew || postId ) && canUserDelete, + canTrashPost: + ( ! isNew || postId ) && + canUserDelete && + ! GLOBAL_POST_TYPES.includes( postType ), }; }, [] ); - if ( ! canTrashPost ) { return null; } diff --git a/packages/editor/src/components/post-trash/index.js b/packages/editor/src/components/post-trash/index.js index c29dfd66a2d8ca..ddb1776d479db9 100644 --- a/packages/editor/src/components/post-trash/index.js +++ b/packages/editor/src/components/post-trash/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; import { Button, __experimentalConfirmDialog as ConfirmDialog, @@ -13,6 +13,7 @@ import { useState } from '@wordpress/element'; * Internal dependencies */ import { store as editorStore } from '../../store'; +import PostTrashCheck from './check'; /** * Displays the Post Trash Button and Confirm Dialog in the Editor. @@ -20,12 +21,13 @@ import { store as editorStore } from '../../store'; * @return {JSX.Element|null} The rendered PostTrash component. */ export default function PostTrash() { - const { isNew, isDeleting, postId } = useSelect( ( select ) => { + const { isNew, isDeleting, postId, title } = useSelect( ( select ) => { const store = select( editorStore ); return { isNew: store.isEditedPostNew(), isDeleting: store.isDeletingPost(), postId: store.getCurrentPostId(), + title: store.getCurrentPostAttribute( 'title' ), }; }, [] ); const { trashPost } = useDispatch( editorStore ); @@ -41,7 +43,7 @@ export default function PostTrash() { }; return ( - <> + <PostTrashCheck> <Button __next40pxDefaultSize className="editor-post-trash" @@ -60,12 +62,14 @@ export default function PostTrash() { onConfirm={ handleConfirm } onCancel={ () => setShowConfirmDialog( false ) } confirmButtonText={ __( 'Move to trash' ) } - size="medium" + size="small" > - { __( - 'Are you sure you want to move this post to the trash?' + { sprintf( + // translators: %s: The item's title. + __( 'Are you sure you want to move "%s" to the trash?' ), + title ) } </ConfirmDialog> - </> + </PostTrashCheck> ); } diff --git a/packages/editor/src/components/sidebar/post-summary.js b/packages/editor/src/components/sidebar/post-summary.js index b19848f2247063..b7fc6efab11cea 100644 --- a/packages/editor/src/components/sidebar/post-summary.js +++ b/packages/editor/src/components/sidebar/post-summary.js @@ -28,6 +28,7 @@ import PostsPerPage from '../posts-per-page'; import SiteDiscussion from '../site-discussion'; import { store as editorStore } from '../../store'; import { PrivatePostLastRevision } from '../post-last-revision'; +import PostTrash from '../post-trash'; /** * Module Constants @@ -87,6 +88,7 @@ export default function PostSummary( { onActionPerformed } ) { <SiteDiscussion /> <PostFormatPanel /> </VStack> + <PostTrash /> { fills } </VStack> ) } From a7c4e2645416325ac0c26ba70b810866613eef18 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 6 Sep 2024 12:04:34 +0200 Subject: [PATCH 0715/1908] `@wordpress/components`: add local copy of `use-lilius` (#65097) * Add local copy of `use-lilus` * Remove external use-lilius dependency * Add use-lilius unit tests * Add credits and license * Add library version * CHANGELOG * Move license to source file * Change repository URL * Add more context to why we're making a local copy * Fix import order --- Unlinked contributors: its-danny. Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- package-lock.json | 22 - packages/components/CHANGELOG.md | 1 + packages/components/package.json | 1 - .../components/src/date-time/date/index.tsx | 2 +- .../src/date-time/date/test/use-lilius.ts | 417 ++++++++++++++++++ .../src/date-time/date/use-lilius/index.ts | 394 +++++++++++++++++ 6 files changed, 813 insertions(+), 24 deletions(-) create mode 100644 packages/components/src/date-time/date/test/use-lilius.ts create mode 100644 packages/components/src/date-time/date/use-lilius/index.ts diff --git a/package-lock.json b/package-lock.json index 0b5b92da05fa1d..fdfaf033b93653 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49586,18 +49586,6 @@ "react": ">=16.8" } }, - "node_modules/use-lilius": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/use-lilius/-/use-lilius-2.0.5.tgz", - "integrity": "sha512-IbPjJe4T6B0zQV6ahftVtHvCAxi6RAuDpEcO8TmnHh4nBtx7JbGdpbgXWOUj/9YjrzEbdT/lW7JWcBVbX3MbrA==", - "dependencies": { - "date-fns": "^3.6.0" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, "node_modules/use-memo-one": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.1.tgz", @@ -52936,7 +52924,6 @@ "re-resizable": "^6.4.0", "react-colorful": "^5.3.1", "remove-accents": "^0.5.0", - "use-lilius": "^2.0.5", "uuid": "^9.0.1" }, "engines": { @@ -67803,7 +67790,6 @@ "re-resizable": "^6.4.0", "react-colorful": "^5.3.1", "remove-accents": "^0.5.0", - "use-lilius": "^2.0.5", "uuid": "^9.0.1" }, "dependencies": { @@ -94041,14 +94027,6 @@ "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.9.tgz", "integrity": "sha512-CL/29uS74AwreI/f2oz2hLTW7ZqVeV5+gxFeGudzQrgkCytrHw33G4KbnQOrRlAEzzAFXi7dDLMC9zhWcVpzmw==" }, - "use-lilius": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/use-lilius/-/use-lilius-2.0.5.tgz", - "integrity": "sha512-IbPjJe4T6B0zQV6ahftVtHvCAxi6RAuDpEcO8TmnHh4nBtx7JbGdpbgXWOUj/9YjrzEbdT/lW7JWcBVbX3MbrA==", - "requires": { - "date-fns": "^3.6.0" - } - }, "use-memo-one": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.1.tgz", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 35549e8cb77998..0293522cf9263e 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -13,6 +13,7 @@ ### Internal - `Composite`: Remove from private APIs ([#63569](https://github.com/WordPress/gutenberg/pull/63569)). +- use local copy of `use-lilius` instead of `npm` dependency ([#65097](https://github.com/WordPress/gutenberg/pull/65097)). ## 28.7.0 (2024-09-05) diff --git a/packages/components/package.json b/packages/components/package.json index 17209986c0f17c..8337d6dd8857f4 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -75,7 +75,6 @@ "re-resizable": "^6.4.0", "react-colorful": "^5.3.1", "remove-accents": "^0.5.0", - "use-lilius": "^2.0.5", "uuid": "^9.0.1" }, "peerDependencies": { diff --git a/packages/components/src/date-time/date/index.tsx b/packages/components/src/date-time/date/index.tsx index 75bfbb76ba2116..33fc736564d5e6 100644 --- a/packages/components/src/date-time/date/index.tsx +++ b/packages/components/src/date-time/date/index.tsx @@ -1,7 +1,6 @@ /** * External dependencies */ -import { useLilius } from 'use-lilius'; import { format, isSameDay, @@ -29,6 +28,7 @@ import { useState, useRef, useEffect } from '@wordpress/element'; /** * Internal dependencies */ +import { useLilius } from './use-lilius'; import type { DatePickerProps } from '../types'; import { Wrapper, diff --git a/packages/components/src/date-time/date/test/use-lilius.ts b/packages/components/src/date-time/date/test/use-lilius.ts new file mode 100644 index 00000000000000..31b81fa11bb74b --- /dev/null +++ b/packages/components/src/date-time/date/test/use-lilius.ts @@ -0,0 +1,417 @@ +/** + * External dependencies + */ +import { act, renderHook } from '@testing-library/react'; +import { addYears, getYear, set, startOfToday, subYears } from 'date-fns'; + +/** + * Internal dependencies + */ +import { Month, useLilius } from '../use-lilius'; + +const getDate = ( { + year = 1999, + month = Month.NOVEMBER, + date = 24, + hours = 0, + minutes = 0, + seconds = 0, + milliseconds = 0, +}: { + year?: number; + month?: number; + date?: number; + hours?: number; + minutes?: number; + seconds?: number; + milliseconds?: number; +} = {} ) => { + return set( new Date(), { + year, + month, + date, + hours, + minutes, + seconds, + milliseconds, + } ); +}; + +describe( 'helpers', () => { + describe( 'clearTime', () => { + it( 'returns a copy of the given date with the time set to 00:00:00:00', () => { + const { result } = renderHook( () => useLilius() ); + + const date = getDate( { hours: 7, minutes: 30 } ); + + expect( result.current.clearTime( date ) ).toStrictEqual( + set( date, { + hours: 0, + minutes: 0, + seconds: 0, + milliseconds: 0, + } ) + ); + } ); + } ); + + describe( 'inRange', () => { + it( 'returns whether or not a date is between 2 other dates (inclusive)', () => { + const { result } = renderHook( () => useLilius() ); + + const date = getDate(); + const min = subYears( date, 1 ); + const max = addYears( date, 1 ); + + expect( result.current.inRange( date, min, max ) ).toBe( true ); + expect( + result.current.inRange( addYears( date, 10 ), min, max ) + ).toBe( false ); + } ); + } ); +} ); + +describe( 'viewing', () => { + describe( 'viewing', () => { + it( 'returns the date represented in the calendar matrix', () => { + const date = getDate(); + + const { result } = renderHook( () => + useLilius( { viewing: date } ) + ); + + expect( result.current.viewing ).toStrictEqual( date ); + } ); + } ); + + describe( 'setViewing', () => { + it( 'sets the date represented in the calendar matrix', () => { + const { result } = renderHook( () => useLilius() ); + + const date = getDate(); + + act( () => result.current.setViewing( date ) ); + expect( result.current.viewing ).toStrictEqual( date ); + } ); + } ); + + describe( 'viewToday', () => { + it( 'sets the viewing date to today', () => { + const { result } = renderHook( () => + useLilius( { viewing: getDate( { year: 1999 } ) } ) + ); + + act( () => result.current.viewToday() ); + expect( result.current.viewing ).toStrictEqual( startOfToday() ); + } ); + } ); + + describe( 'viewMonth', () => { + it( 'sets the viewing date to the given month', () => { + const date = getDate( { month: Month.JANUARY } ); + + const { result } = renderHook( () => + useLilius( { viewing: date } ) + ); + + act( () => result.current.viewMonth( Month.FEBRUARY ) ); + expect( result.current.viewing ).toStrictEqual( + set( date, { month: Month.FEBRUARY } ) + ); + } ); + } ); + + describe( 'viewPreviousMonth', () => { + it( 'sets the viewing date to the month before the current', () => { + const { result } = renderHook( () => useLilius() ); + + const date = getDate( { month: Month.OCTOBER } ); + + act( () => result.current.setViewing( date ) ); + act( () => result.current.viewPreviousMonth() ); + expect( result.current.viewing ).toStrictEqual( + set( date, { month: Month.SEPTEMBER } ) + ); + } ); + + it( 'wraps to december of the previous year if the current month is january', () => { + const { result } = renderHook( () => useLilius() ); + + const date = getDate( { month: Month.JANUARY } ); + + act( () => result.current.setViewing( date ) ); + act( () => result.current.viewPreviousMonth() ); + expect( result.current.viewing ).toStrictEqual( + set( date, { + month: Month.DECEMBER, + year: getYear( date ) - 1, + } ) + ); + } ); + } ); + + describe( 'viewNextMonth', () => { + it( 'sets the viewing date to the month after the current', () => { + const { result } = renderHook( () => useLilius() ); + + const date = getDate( { month: Month.OCTOBER } ); + + act( () => result.current.setViewing( date ) ); + act( () => result.current.viewNextMonth() ); + expect( result.current.viewing ).toStrictEqual( + set( date, { month: Month.NOVEMBER } ) + ); + } ); + + it( 'wraps to january of the next year if the current month is december', () => { + const { result } = renderHook( () => useLilius() ); + + const date = getDate( { month: Month.DECEMBER } ); + + act( () => result.current.setViewing( date ) ); + act( () => result.current.viewNextMonth() ); + expect( result.current.viewing ).toStrictEqual( + set( date, { month: Month.JANUARY, year: getYear( date ) + 1 } ) + ); + } ); + } ); + + describe( 'viewYear', () => { + it( 'sets the viewing date to the given year', () => { + const date = getDate( { year: 1999 } ); + + const { result } = renderHook( () => + useLilius( { viewing: date } ) + ); + + act( () => result.current.viewYear( 1997 ) ); + expect( result.current.viewing ).toStrictEqual( + set( date, { year: 1997 } ) + ); + } ); + } ); + + describe( 'viewPreviousYear', () => { + it( 'sets the viewing date to the year before the current', () => { + const date = getDate( { year: 1999 } ); + + const { result } = renderHook( () => + useLilius( { viewing: date } ) + ); + + act( () => result.current.viewPreviousYear() ); + expect( result.current.viewing ).toStrictEqual( + set( date, { year: 1998 } ) + ); + } ); + } ); + + describe( 'viewNextYear', () => { + it( 'sets the viewing date to the year after the current', () => { + const date = getDate( { year: 1999 } ); + + const { result } = renderHook( () => + useLilius( { viewing: date } ) + ); + + act( () => result.current.viewNextYear() ); + expect( result.current.viewing ).toStrictEqual( + set( date, { year: 2000 } ) + ); + } ); + } ); +} ); + +describe( 'selected', () => { + describe( 'selected', () => { + it( 'returns the dates currently selected', () => { + const date = getDate(); + + const { result } = renderHook( () => + useLilius( { + selected: [ date ], + } ) + ); + + expect( result.current.selected ).toStrictEqual( [ date ] ); + } ); + } ); + + describe( 'clearSelected', () => { + it( 'resets the selected dates to []', () => { + const { result } = renderHook( () => useLilius() ); + + const date = getDate(); + + act( () => + result.current.selectRange( + set( date, { date: 1 } ), + set( date, { date: 5 } ) + ) + ); + expect( result.current.selected.length ).toBe( 5 ); + + act( () => result.current.clearSelected() ); + expect( result.current.selected.length ).toBe( 0 ); + } ); + } ); + + describe( 'isSelected', () => { + it( 'returns whether or not a date has been selected', () => { + const date = getDate(); + + const { result } = renderHook( () => + useLilius( { + selected: [ date ], + } ) + ); + + expect( result.current.isSelected( date ) ).toBe( true ); + } ); + } ); + + describe( 'select', () => { + it( 'selects a date', () => { + const { result } = renderHook( () => useLilius() ); + + const date = getDate(); + + act( () => result.current.select( date ) ); + expect( result.current.isSelected( date ) ).toBe( true ); + } ); + + it( 'selects multiple dates', () => { + const { result } = renderHook( () => useLilius() ); + + const dateOne = getDate( { date: 1 } ); + const dateTwo = getDate( { date: 2 } ); + + act( () => result.current.select( [ dateOne, dateTwo ] ) ); + expect( result.current.isSelected( dateOne ) ).toBe( true ); + expect( result.current.isSelected( dateTwo ) ).toBe( true ); + } ); + } ); + + describe( 'deselect', () => { + it( 'deselects a date', () => { + const { result } = renderHook( () => useLilius() ); + + const date = getDate(); + + act( () => result.current.select( date ) ); + act( () => result.current.deselect( date ) ); + expect( result.current.isSelected( date ) ).toBe( false ); + } ); + + it( 'deselects multiple dates', () => { + const { result } = renderHook( () => useLilius() ); + + const dateOne = getDate( { date: 1 } ); + const dateTwo = getDate( { date: 2 } ); + + act( () => result.current.select( [ dateOne, dateTwo ] ) ); + act( () => result.current.deselect( [ dateOne, dateTwo ] ) ); + expect( result.current.isSelected( dateOne ) ).toBe( false ); + expect( result.current.isSelected( dateTwo ) ).toBe( false ); + } ); + } ); + + describe( 'toggle', () => { + it( 'toggles the selection of a date', () => { + const { result } = renderHook( () => useLilius() ); + + const date = getDate(); + + act( () => result.current.toggle( date ) ); + expect( result.current.isSelected( date ) ).toBe( true ); + + act( () => result.current.toggle( date ) ); + expect( result.current.isSelected( date ) ).toBe( false ); + } ); + } ); + + describe( 'selectRange', () => { + it( 'selects a range of dates (inclusive)', () => { + const { result } = renderHook( () => useLilius() ); + + const date = getDate(); + + const first = set( date, { date: 1 } ); + const second = set( date, { date: 2 } ); + const third = set( date, { date: 3 } ); + + act( () => result.current.selectRange( first, third ) ); + + expect( result.current.selected.length ).toBe( 3 ); + expect( result.current.isSelected( first ) ).toBe( true ); + expect( result.current.isSelected( second ) ).toBe( true ); + expect( result.current.isSelected( third ) ).toBe( true ); + } ); + } ); + + describe( 'deselectRange', () => { + it( 'deselects a range of dates (inclusive)', () => { + const { result } = renderHook( () => useLilius() ); + + const date = getDate(); + + act( () => + result.current.selectRange( + set( date, { date: 1 } ), + set( date, { date: 3 } ) + ) + ); + act( () => + result.current.deselectRange( + set( date, { date: 1 } ), + set( date, { date: 3 } ) + ) + ); + + expect( result.current.selected.length ).toBe( 0 ); + expect( + result.current.isSelected( set( date, { date: 1 } ) ) + ).toBe( false ); + expect( + result.current.isSelected( set( date, { date: 2 } ) ) + ).toBe( false ); + expect( + result.current.isSelected( set( date, { date: 3 } ) ) + ).toBe( false ); + } ); + } ); +} ); + +describe( 'calendar', () => { + it( 'returns a matrix of days based on the current viewing date', () => { + const { result } = renderHook( () => + useLilius( { viewing: new Date( 1582, Month.OCTOBER, 1 ) } ) + ); + + expect( result.current.calendar![ 0 ][ 0 ][ 0 ] ).toStrictEqual( + new Date( 1582, Month.SEPTEMBER, 26 ) + ); + expect( result.current.calendar![ 0 ][ 0 ][ 5 ] ).toStrictEqual( + new Date( 1582, Month.OCTOBER, 1 ) + ); + expect( result.current.calendar![ 0 ][ 5 ][ 6 ] ).toStrictEqual( + new Date( 1582, Month.NOVEMBER, 6 ) + ); + } ); + + it( 'supports returning multiple months', () => { + const { result } = renderHook( () => + useLilius( { + viewing: new Date( 1582, Month.OCTOBER, 1 ), + numberOfMonths: 2, + } ) + ); + + expect( result.current.calendar![ 0 ][ 0 ][ 0 ] ).toStrictEqual( + new Date( 1582, Month.SEPTEMBER, 26 ) + ); + expect( result.current.calendar![ 1 ][ 0 ][ 0 ] ).toStrictEqual( + new Date( 1582, Month.OCTOBER, 31 ) + ); + } ); +} ); diff --git a/packages/components/src/date-time/date/use-lilius/index.ts b/packages/components/src/date-time/date/use-lilius/index.ts new file mode 100644 index 00000000000000..2da204b3c76419 --- /dev/null +++ b/packages/components/src/date-time/date/use-lilius/index.ts @@ -0,0 +1,394 @@ +/** + * This source is a local copy of the use-lilius library, since the original + * library is not actively maintained. + * @see https://github.com/WordPress/gutenberg/discussions/64968 + * + * use-lilius@2.0.5 + * https://github.com/Avarios/use-lilius + * + * The MIT License (MIT) + * + * Copyright (c) 2021-Present Danny Tatom + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * External dependencies + */ +import { + addMonths, + addYears, + eachDayOfInterval, + eachMonthOfInterval, + eachWeekOfInterval, + endOfMonth, + endOfWeek, + isAfter, + isBefore, + isEqual, + set, + setMonth, + setYear, + startOfMonth, + startOfToday, + startOfWeek, + subMonths, + subYears, +} from 'date-fns'; + +/** + * WordPress dependencies + */ +import { useCallback, useMemo, useState } from '@wordpress/element'; + +export enum Month { + JANUARY, + FEBRUARY, + MARCH, + APRIL, + MAY, + JUNE, + JULY, + AUGUST, + SEPTEMBER, + OCTOBER, + NOVEMBER, + DECEMBER, +} + +export enum Day { + SUNDAY, + MONDAY, + TUESDAY, + WEDNESDAY, + THURSDAY, + FRIDAY, + SATURDAY, +} + +export interface Options { + /** + * What day a week starts on within the calendar matrix. + * + * @default Day.SUNDAY + */ + weekStartsOn?: Day; + + /** + * The initial viewing date. + * + * @default new Date() + */ + viewing?: Date; + + /** + * The initial date(s) selection. + * + * @default [] + */ + selected?: Date[]; + + /** + * The number of months in the calendar. + * + * @default 1 + */ + numberOfMonths?: number; +} + +export interface Returns { + /** + * Returns a copy of the given date with the time set to 00:00:00:00. + */ + clearTime: ( date: Date ) => Date; + + /** + * Returns whether or not a date is between 2 other dates (inclusive). + */ + inRange: ( date: Date, min: Date, max: Date ) => boolean; + + /** + * The date represented in the calendar matrix. Note that + * the month and year are the only parts used. + */ + viewing: Date; + + /** + * Set the date represented in the calendar matrix. Note that + * the month and year are the only parts used. + */ + setViewing: React.Dispatch< React.SetStateAction< Date > >; + + /** + * Set the viewing date to today. + */ + viewToday: () => void; + + /** + * Set the viewing date to the given month. + */ + viewMonth: ( month: Month ) => void; + + /** + * Set the viewing date to the month before the current. + */ + viewPreviousMonth: () => void; + + /** + * Set the viewing date to the month after the current. + */ + viewNextMonth: () => void; + + /** + * Set the viewing date to the given year. + */ + viewYear: ( year: number ) => void; + + /** + * Set the viewing date to the year before the current. + */ + viewPreviousYear: () => void; + + /** + * Set the viewing date to the year after the current. + */ + viewNextYear: () => void; + + /** + * The dates currently selected. + */ + selected: Date[]; + + /** + * Override the currently selected dates. + */ + setSelected: React.Dispatch< React.SetStateAction< Date[] > >; + + /** + * Reset the selected dates to []. + */ + clearSelected: () => void; + + /** + * Determine whether or not a date has been selected. + */ + isSelected: ( date: Date ) => boolean; + + /** + * Select one or more dates. + */ + select: ( date: Date | Date[], replaceExisting?: boolean ) => void; + + /** + * Deselect one or more dates. + */ + deselect: ( date: Date | Date[] ) => void; + + /** + * Toggle the selection of a date. + */ + toggle: ( date: Date, replaceExisting?: boolean ) => void; + + /** + * Select a range of dates (inclusive). + */ + selectRange: ( start: Date, end: Date, replaceExisting?: boolean ) => void; + + /** + * Deselect a range of dates (inclusive). + */ + deselectRange: ( start: Date, end: Date ) => void; + + /** + * A matrix of days based on the current viewing date. + */ + calendar: Date[][][]; +} + +const inRange = ( date: Date, min: Date, max: Date ) => + ( isEqual( date, min ) || isAfter( date, min ) ) && + ( isEqual( date, max ) || isBefore( date, max ) ); + +const clearTime = ( date: Date ) => + set( date, { hours: 0, minutes: 0, seconds: 0, milliseconds: 0 } ); + +export const useLilius = ( { + weekStartsOn = Day.SUNDAY, + viewing: initialViewing = new Date(), + selected: initialSelected = [], + numberOfMonths = 1, +}: Options = {} ): Returns => { + const [ viewing, setViewing ] = useState< Date >( initialViewing ); + + const viewToday = useCallback( + () => setViewing( startOfToday() ), + [ setViewing ] + ); + + const viewMonth = useCallback( + ( month: Month ) => setViewing( ( v ) => setMonth( v, month ) ), + [] + ); + + const viewPreviousMonth = useCallback( + () => setViewing( ( v ) => subMonths( v, 1 ) ), + [] + ); + + const viewNextMonth = useCallback( + () => setViewing( ( v ) => addMonths( v, 1 ) ), + [] + ); + + const viewYear = useCallback( + ( year: number ) => setViewing( ( v ) => setYear( v, year ) ), + [] + ); + + const viewPreviousYear = useCallback( + () => setViewing( ( v ) => subYears( v, 1 ) ), + [] + ); + + const viewNextYear = useCallback( + () => setViewing( ( v ) => addYears( v, 1 ) ), + [] + ); + + const [ selected, setSelected ] = useState< Date[] >( + initialSelected.map( clearTime ) + ); + + const clearSelected = () => setSelected( [] ); + + const isSelected = useCallback( + ( date: Date ) => + selected.findIndex( ( s ) => isEqual( s, date ) ) > -1, + [ selected ] + ); + + const select = useCallback( + ( date: Date | Date[], replaceExisting?: boolean ) => { + if ( replaceExisting ) { + setSelected( Array.isArray( date ) ? date : [ date ] ); + } else { + setSelected( ( selectedItems ) => + selectedItems.concat( + Array.isArray( date ) ? date : [ date ] + ) + ); + } + }, + [] + ); + + const deselect = useCallback( + ( date: Date | Date[] ) => + setSelected( ( selectedItems ) => + Array.isArray( date ) + ? selectedItems.filter( + ( s ) => + ! date + .map( ( d ) => d.getTime() ) + .includes( s.getTime() ) + ) + : selectedItems.filter( ( s ) => ! isEqual( s, date ) ) + ), + [] + ); + + const toggle = useCallback( + ( date: Date, replaceExisting?: boolean ) => + isSelected( date ) + ? deselect( date ) + : select( date, replaceExisting ), + [ deselect, isSelected, select ] + ); + + const selectRange = useCallback( + ( start: Date, end: Date, replaceExisting?: boolean ) => { + if ( replaceExisting ) { + setSelected( eachDayOfInterval( { start, end } ) ); + } else { + setSelected( ( selectedItems ) => + selectedItems.concat( eachDayOfInterval( { start, end } ) ) + ); + } + }, + [] + ); + + const deselectRange = useCallback( ( start: Date, end: Date ) => { + setSelected( ( selectedItems ) => + selectedItems.filter( + ( s ) => + ! eachDayOfInterval( { start, end } ) + .map( ( d ) => d.getTime() ) + .includes( s.getTime() ) + ) + ); + }, [] ); + + const calendar = useMemo< Date[][][] >( + () => + eachMonthOfInterval( { + start: startOfMonth( viewing ), + end: endOfMonth( addMonths( viewing, numberOfMonths - 1 ) ), + } ).map( ( month ) => + eachWeekOfInterval( + { + start: startOfMonth( month ), + end: endOfMonth( month ), + }, + { weekStartsOn } + ).map( ( week ) => + eachDayOfInterval( { + start: startOfWeek( week, { weekStartsOn } ), + end: endOfWeek( week, { weekStartsOn } ), + } ) + ) + ), + [ viewing, weekStartsOn, numberOfMonths ] + ); + + return { + clearTime, + inRange, + viewing, + setViewing, + viewToday, + viewMonth, + viewPreviousMonth, + viewNextMonth, + viewYear, + viewPreviousYear, + viewNextYear, + selected, + setSelected, + clearSelected, + isSelected, + select, + deselect, + toggle, + selectRange, + deselectRange, + calendar, + }; +}; From e706d67c7482e752a4adaae3e0b0449234e19902 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 6 Sep 2024 14:21:45 +0400 Subject: [PATCH 0716/1908] Block Editor: Use the tooltip from a button in 'ButtonBlockAppender' (#65113) * Block Editor: Use the tooltip from a button in 'ButtonBlockAppender' * Remove visually hidden element Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../components/button-block-appender/index.js | 41 ++++++++----------- 1 file changed, 16 insertions(+), 25 deletions(-) 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 9cd745ac5eb3d6..c4a6854c6d6cc4 100644 --- a/packages/block-editor/src/components/button-block-appender/index.js +++ b/packages/block-editor/src/components/button-block-appender/index.js @@ -6,7 +6,7 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { Button, Tooltip, VisuallyHidden } from '@wordpress/components'; +import { Button } from '@wordpress/components'; import { forwardRef, useRef } from '@wordpress/element'; import { _x, sprintf } from '@wordpress/i18n'; import { Icon, plus } from '@wordpress/icons'; @@ -43,22 +43,22 @@ function ButtonBlockAppender( blockTitle, hasSingleBlockType, } ) => { - let label; - if ( hasSingleBlockType ) { - label = sprintf( - // translators: %s: the name of the block when there is only one - _x( 'Add %s', 'directly add the only allowed block' ), - blockTitle - ); - } else { - label = _x( - 'Add block', - 'Generic label for block inserter button' - ); - } const isToggleButton = ! hasSingleBlockType; + const label = hasSingleBlockType + ? sprintf( + // translators: %s: the name of the block when there is only one + _x( + 'Add %s', + 'directly add the only allowed block' + ), + blockTitle + ) + : _x( + 'Add block', + 'Generic label for block inserter button' + ); - let inserterButton = ( + return ( <Button // TODO: Switch to `true` (40px size) if possible __next40pxDefaultSize={ false } @@ -76,20 +76,11 @@ function ButtonBlockAppender( // eslint-disable-next-line no-restricted-syntax disabled={ disabled } label={ label } + showTooltip > - { ! hasSingleBlockType && ( - <VisuallyHidden as="span">{ label }</VisuallyHidden> - ) } <Icon icon={ plus } /> </Button> ); - - if ( isToggleButton || hasSingleBlockType ) { - inserterButton = ( - <Tooltip text={ label }>{ inserterButton }</Tooltip> - ); - } - return inserterButton; } } isAppender /> From 95c19951b11667fabc12b90c3f6affa3a73dd5bd Mon Sep 17 00:00:00 2001 From: Maggie <maggie.cabrera@automattic.com> Date: Fri, 6 Sep 2024 14:56:13 +0100 Subject: [PATCH 0717/1908] Zoom out: Try vertical displacement when dragging a pattern between existing patterns/sections (#63896) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * create a function to check when we can add the separators Attempt to define sectionClientIds Pass sectionClientIds to isSectionBlock Rename sectionClientIds to sectionRootClientIds check if it's zoom out mode, add some CSS to the separator expand separators when the insertion point is changed fix animation only open the first separator if the insertion point index is 0 conditionally render the separators and animate them using framer instead of on class change remove unused code refactor separators do displacement on drag * Don’t show seperator if opertation is not insert * Fix bug where rootClientId was not within sectionRoot * Ignore Group operations on drag in Zoom Out mode * Check for ZoomOut separators when firing onDragEnd * Refine function to detect zoom out separator * Update detection based on data attribute * Make generic * Add comment for clarity * Improve code comments * Remove blue line inserter in ZoomOutmode * Move logic into consuming hook * Consume new API for getting root * Move pure function * Fix background showing through * Add UI feedback on dragover separator --------- Co-authored-by: Dave Smith <getdavemail@gmail.com> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../src/components/block-list/content.scss | 21 ++++ .../src/components/block-list/index.js | 97 +++++++++------ .../block-list/zoom-out-separator.js | 110 ++++++++++++++++++ .../src/components/block-tools/index.js | 2 +- .../block-tools/zoom-out-mode-inserters.js | 12 -- .../components/use-block-drop-zone/index.js | 34 +++++- .../compose/src/hooks/use-drop-zone/index.js | 2 + 7 files changed, 226 insertions(+), 52 deletions(-) create mode 100644 packages/block-editor/src/components/block-list/zoom-out-separator.js diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index 95bb610da9967c..3f4b4c508aeb02 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -453,3 +453,24 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b margin-bottom: auto; } } + +.block-editor-block-list__zoom-out-separator { + /* same color as the iframe's background */ + background: $gray-300; + // Additional -1px is required to avoid sub pixel rounding errors allowing background to show. + margin-left: -1px; + margin-right: -1px; + transition: background-color 0.3s ease; + + &.is-dragged-over { + background: $gray-400; + } +} + +// In Post Editor allow the separator to occupy the full width by ignoring (cancelling out) the global padding. +.has-global-padding > .block-editor-block-list__zoom-out-separator, +.block-editor-block-list__layout.is-root-container.has-global-padding > .block-editor-block-list__zoom-out-separator { + max-width: none; + // Additional -1px is required to avoid sub pixel rounding errors allowing background to show. + margin: 0 calc(-1 * var(--wp--style--root--padding-right) - 1px) 0 calc(-1 * var(--wp--style--root--padding-left) - 1px) !important; +} diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index 37dba80511d920..ea6128f1534642 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -39,6 +39,7 @@ import { DEFAULT_BLOCK_EDIT_CONTEXT, } from '../block-edit/context'; import { useTypingObserver } from '../observe-typing'; +import { ZoomOutSeparator } from './zoom-out-separator'; import { unlock } from '../../lock-unlock'; export const IntersectionObserver = createContext(); @@ -174,49 +175,55 @@ function Items( { // function on every render. const hasAppender = CustomAppender !== false; const hasCustomAppender = !! CustomAppender; - const { order, selectedBlocks, visibleBlocks, shouldRenderAppender } = - useSelect( - ( select ) => { - const { - getSettings, - getBlockOrder, - getSelectedBlockClientId, - getSelectedBlockClientIds, - __unstableGetVisibleBlocks, - getTemplateLock, - getBlockEditingMode, - __unstableGetEditorMode, - } = select( blockEditorStore ); - - const _order = getBlockOrder( rootClientId ); + const { + order, + isZoomOut, + selectedBlocks, + visibleBlocks, + shouldRenderAppender, + } = useSelect( + ( select ) => { + const { + getSettings, + getBlockOrder, + getSelectedBlockClientId, + getSelectedBlockClientIds, + __unstableGetVisibleBlocks, + getTemplateLock, + getBlockEditingMode, + __unstableGetEditorMode, + } = select( blockEditorStore ); - if ( getSettings().__unstableIsPreviewMode ) { - return { - order: _order, - selectedBlocks: EMPTY_ARRAY, - visibleBlocks: EMPTY_SET, - }; - } + const _order = getBlockOrder( rootClientId ); - const selectedBlockClientId = getSelectedBlockClientId(); + if ( getSettings().__unstableIsPreviewMode ) { return { order: _order, - selectedBlocks: getSelectedBlockClientIds(), - visibleBlocks: __unstableGetVisibleBlocks(), - shouldRenderAppender: - hasAppender && - __unstableGetEditorMode() !== 'zoom-out' && - ( hasCustomAppender - ? ! getTemplateLock( rootClientId ) && - getBlockEditingMode( rootClientId ) !== 'disabled' - : rootClientId === selectedBlockClientId || - ( ! rootClientId && - ! selectedBlockClientId && - ! _order.length ) ), + selectedBlocks: EMPTY_ARRAY, + visibleBlocks: EMPTY_SET, }; - }, - [ rootClientId, hasAppender, hasCustomAppender ] - ); + } + + const selectedBlockClientId = getSelectedBlockClientId(); + return { + order: _order, + selectedBlocks: getSelectedBlockClientIds(), + visibleBlocks: __unstableGetVisibleBlocks(), + isZoomOut: __unstableGetEditorMode() === 'zoom-out', + shouldRenderAppender: + hasAppender && + __unstableGetEditorMode() !== 'zoom-out' && + ( hasCustomAppender + ? ! getTemplateLock( rootClientId ) && + getBlockEditingMode( rootClientId ) !== 'disabled' + : rootClientId === selectedBlockClientId || + ( ! rootClientId && + ! selectedBlockClientId && + ! _order.length ) ), + }; + }, + [ rootClientId, hasAppender, hasCustomAppender ] + ); return ( <LayoutProvider value={ layout }> @@ -230,10 +237,24 @@ function Items( { ! selectedBlocks.includes( clientId ) } > + { isZoomOut && ( + <ZoomOutSeparator + clientId={ clientId } + rootClientId={ rootClientId } + position="top" + /> + ) } <BlockListBlock rootClientId={ rootClientId } clientId={ clientId } /> + { isZoomOut && ( + <ZoomOutSeparator + clientId={ clientId } + rootClientId={ rootClientId } + position="bottom" + /> + ) } </AsyncModeProvider> ) ) } { order.length < 1 && placeholder } diff --git a/packages/block-editor/src/components/block-list/zoom-out-separator.js b/packages/block-editor/src/components/block-list/zoom-out-separator.js new file mode 100644 index 00000000000000..be5af549630607 --- /dev/null +++ b/packages/block-editor/src/components/block-list/zoom-out-separator.js @@ -0,0 +1,110 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ +import { + __unstableMotion as motion, + __unstableAnimatePresence as AnimatePresence, +} from '@wordpress/components'; +import { useReducedMotion } from '@wordpress/compose'; +import { useSelect } from '@wordpress/data'; +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; + +export function ZoomOutSeparator( { + clientId, + rootClientId = '', + position = 'top', +} ) { + const [ isDraggedOver, setIsDraggedOver ] = useState( false ); + const { + sectionRootClientId, + sectionClientIds, + blockInsertionPoint, + blockInsertionPointVisible, + } = useSelect( ( select ) => { + const { + getBlockInsertionPoint, + getBlockOrder, + isBlockInsertionPointVisible, + getSectionRootClientId, + } = unlock( select( blockEditorStore ) ); + + const root = getSectionRootClientId(); + const sectionRootClientIds = getBlockOrder( root ); + return { + sectionRootClientId: root, + sectionClientIds: sectionRootClientIds, + blockOrder: getBlockOrder( root ), + blockInsertionPoint: getBlockInsertionPoint(), + blockInsertionPointVisible: isBlockInsertionPointVisible(), + }; + }, [] ); + + const isReducedMotion = useReducedMotion(); + + if ( ! clientId ) { + return; + } + + let isVisible = false; + + const isSectionBlock = + rootClientId === sectionRootClientId && + sectionClientIds && + sectionClientIds.includes( clientId ); + + if ( ! isSectionBlock ) { + return null; + } + + if ( position === 'top' ) { + isVisible = + blockInsertionPointVisible && + blockInsertionPoint.index === 0 && + clientId === sectionClientIds[ blockInsertionPoint.index ]; + } + + if ( position === 'bottom' ) { + isVisible = + blockInsertionPointVisible && + clientId === sectionClientIds[ blockInsertionPoint.index - 1 ]; + } + + return ( + <AnimatePresence> + { isVisible && ( + <motion.div + as="button" + layout={ ! isReducedMotion } + initial={ { height: 0 } } + animate={ { height: '120px' } } + exit={ { height: 0 } } + transition={ { + type: 'tween', + duration: 0.2, + ease: [ 0.6, 0, 0.4, 1 ], + } } + className={ clsx( + 'block-editor-block-list__zoom-out-separator', + { + 'is-dragged-over': isDraggedOver, + } + ) } + data-is-insertion-point="true" + onDragOver={ () => setIsDraggedOver( true ) } + onDragLeave={ () => setIsDraggedOver( false ) } + ></motion.div> + ) } + </AnimatePresence> + ); +} diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 163c35b54e4381..24f60dbbf970aa 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -202,7 +202,7 @@ export default function BlockTools( { // eslint-disable-next-line jsx-a11y/no-static-element-interactions <div { ...props } onKeyDown={ onKeyDown }> <InsertionPointOpenRef.Provider value={ useRef( false ) }> - { ! isTyping && ( + { ! isTyping && ! isZoomOutMode && ( <InsertionPoint __unstableContentRef={ __unstableContentRef } /> diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js index 30d51654b77cf4..79f8be3f9cfe97 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js @@ -88,18 +88,6 @@ function ZoomOutModeInserters() { previousClientId={ previousClientId } nextClientId={ nextClientId } > - { shouldRenderInsertionPoint && ( - <div - style={ { - borderRadius: '0', - height: '12px', - opacity: 1, - transform: 'translateY(-50%)', - width: '100%', - } } - className="block-editor-block-list__insertion-point-indicator" - /> - ) } { ! shouldRenderInsertionPoint && ( <ZoomOutModeInserterButton isVisible={ isSelected || isHovered } 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 5af82915233703..ff4d52aaa493bc 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 @@ -274,6 +274,23 @@ export function isDropTargetValid( return areBlocksAllowed && targetMatchesDraggedBlockParents; } +/** + * Checks if the given element is an insertion point. + * + * @param {EventTarget|null} targetToCheck - The element to check. + * @param {Document} ownerDocument - The owner document of the element. + * @return {boolean} True if the element is a insertion point, false otherwise. + */ +function isInsertionPoint( targetToCheck, ownerDocument ) { + const { defaultView } = ownerDocument; + + return !! ( + defaultView && + targetToCheck instanceof defaultView.HTMLElement && + targetToCheck.dataset.isInsertionPoint + ); +} + /** * @typedef {Object} WPBlockDropZoneConfig * @property {?HTMLElement} dropZoneElement Optional element to be used as the drop zone. @@ -422,6 +439,10 @@ export default function useBlockDropZone( { const [ targetIndex, operation, nearestSide ] = dropTargetPosition; + if ( isZoomOutMode() && operation !== 'insert' ) { + return; + } + if ( operation === 'group' ) { const targetBlock = blocks[ targetIndex ]; const areAllImages = [ @@ -521,7 +542,18 @@ export default function useBlockDropZone( { // https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget throttled( event, event.currentTarget.ownerDocument ); }, - onDragLeave() { + onDragLeave( event ) { + const { ownerDocument } = event.currentTarget; + + // If the drag event is leaving the drop zone and entering an insertion point, + // do not hide the insertion point as it is conceptually within the dropzone. + if ( + isInsertionPoint( event.relatedTarget, ownerDocument ) || + isInsertionPoint( event.target, ownerDocument ) + ) { + return; + } + throttled.cancel(); hideInsertionPoint(); }, diff --git a/packages/compose/src/hooks/use-drop-zone/index.js b/packages/compose/src/hooks/use-drop-zone/index.js index b537f0a5ab6227..c570c034415923 100644 --- a/packages/compose/src/hooks/use-drop-zone/index.js +++ b/packages/compose/src/hooks/use-drop-zone/index.js @@ -86,6 +86,7 @@ export default function useDropZone( { */ function isElementInZone( targetToCheck ) { const { defaultView } = ownerDocument; + if ( ! targetToCheck || ! defaultView || @@ -165,6 +166,7 @@ export default function useDropZone( { // zone. // Note: This is not entirely reliable in Safari due to this bug // https://bugs.webkit.org/show_bug.cgi?id=66547 + if ( isElementInZone( event.relatedTarget ) ) { return; } From c90f1c5d1bb9fe376122774c9e807174ebe77b9d Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Fri, 6 Sep 2024 21:08:44 +0530 Subject: [PATCH 0718/1908] Fix: Button: Replace remaining 40px default size violations [Block library 1] (#65033) * Fix legacy comments to use 40px default button size * Fix the embed placeholder button to use 40px default button size * Fix freeform block to use 40px default button size * Fix missing block to use 40px default button size * Revert the instance for modal fullscreen button size This is being reverted because we need to resolve this first - https://github.com/WordPress/gutenberg/pull/65033#discussion_r1746056089 Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/block-library/src/comments/edit/comments-legacy.js | 3 +-- packages/block-library/src/embed/embed-placeholder.js | 6 ++---- packages/block-library/src/freeform/modal.js | 6 ++---- packages/block-library/src/missing/edit.js | 3 +-- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/packages/block-library/src/comments/edit/comments-legacy.js b/packages/block-library/src/comments/edit/comments-legacy.js index b5a12e34343dac..dbe89a4e3a83e1 100644 --- a/packages/block-library/src/comments/edit/comments-legacy.js +++ b/packages/block-library/src/comments/edit/comments-legacy.js @@ -29,8 +29,7 @@ export default function CommentsLegacy( { const actions = [ <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize key="convert" onClick={ () => void setAttributes( { legacy: false } ) } variant="primary" diff --git a/packages/block-library/src/embed/embed-placeholder.js b/packages/block-library/src/embed/embed-placeholder.js index 9a26060a294120..1626aca5c9c9cb 100644 --- a/packages/block-library/src/embed/embed-placeholder.js +++ b/packages/block-library/src/embed/embed-placeholder.js @@ -66,16 +66,14 @@ const EmbedPlaceholder = ( { justify="flex-start" > <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="secondary" onClick={ tryAgain } > { _x( 'Try again', 'button label' ) } </Button>{ ' ' } <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="secondary" onClick={ fallback } > diff --git a/packages/block-library/src/freeform/modal.js b/packages/block-library/src/freeform/modal.js index 1768022377a432..aad79473b172b2 100644 --- a/packages/block-library/src/freeform/modal.js +++ b/packages/block-library/src/freeform/modal.js @@ -123,8 +123,7 @@ export default function ModalEdit( props ) { > <FlexItem> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" onClick={ onClose } > @@ -133,8 +132,7 @@ export default function ModalEdit( props ) { </FlexItem> <FlexItem> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" onClick={ () => { setAttributes( { diff --git a/packages/block-library/src/missing/edit.js b/packages/block-library/src/missing/edit.js index 70b032cb9a2fe8..e7744839b08889 100644 --- a/packages/block-library/src/missing/edit.js +++ b/packages/block-library/src/missing/edit.js @@ -50,8 +50,7 @@ export default function MissingEdit( { attributes, clientId } ) { const convertToHtmlButton = ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize key="convert" onClick={ convertToHTML } variant="primary" From 219be48235dd578496a64dae53757182a5571a96 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Fri, 6 Sep 2024 21:12:14 +0530 Subject: [PATCH 0719/1908] Fix: Button: Replace remaining 40px default size violation [Block library] (#65075) * Fix navigation-link block to use button to default 40px size * Fix navigation deleted create new menu button to use 40px default size * Fix navigation overlay menu icon button to use 40px default size * Fix the navigation menu delete button to use 40px default size button * Fix navigation placeholder start empty to use button as default 40px size * Fix responsive navigation overlay menu open button to use default 40px size * Fix navigation responsive close button to use 40px default size * Add the !important to override the overlay menu preview style Ref - https://github.com/WordPress/gutenberg/pull/65075#discussion_r1746282734 * Refactor the comment for the !important style Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/block-library/src/navigation-link/link-ui.js | 3 +-- .../src/navigation/edit/deleted-navigation-warning.js | 3 +-- packages/block-library/src/navigation/edit/index.js | 3 +-- .../src/navigation/edit/navigation-menu-delete-control.js | 3 +-- .../block-library/src/navigation/edit/placeholder/index.js | 3 +-- .../block-library/src/navigation/edit/responsive-wrapper.js | 6 ++---- packages/block-library/src/navigation/editor.scss | 6 +++++- 7 files changed, 12 insertions(+), 15 deletions(-) diff --git a/packages/block-library/src/navigation-link/link-ui.js b/packages/block-library/src/navigation-link/link-ui.js index 1d303843644474..ee238c71ed28e0 100644 --- a/packages/block-library/src/navigation-link/link-ui.js +++ b/packages/block-library/src/navigation-link/link-ui.js @@ -310,8 +310,7 @@ const LinkUITools = ( { setAddingBlock, focusAddBlockButton } ) => { return ( <VStack className="link-ui-tools"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize ref={ addBlockButtonRef } icon={ plus } onClick={ ( e ) => { diff --git a/packages/block-library/src/navigation/edit/deleted-navigation-warning.js b/packages/block-library/src/navigation/edit/deleted-navigation-warning.js index 8950a700ace513..b0521f16cfb5d5 100644 --- a/packages/block-library/src/navigation/edit/deleted-navigation-warning.js +++ b/packages/block-library/src/navigation/edit/deleted-navigation-warning.js @@ -16,8 +16,7 @@ function DeletedNavigationWarning( { onCreateNew } ) { { button: ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize onClick={ onCreateNew } variant="link" /> diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js index c9ce17eea6b1ab..ae7dd60bd0c5ba 100644 --- a/packages/block-library/src/navigation/edit/index.js +++ b/packages/block-library/src/navigation/edit/index.js @@ -591,8 +591,7 @@ function Navigation( { { isResponsive && ( <> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className={ overlayMenuPreviewClasses } onClick={ () => { setOverlayMenuPreview( diff --git a/packages/block-library/src/navigation/edit/navigation-menu-delete-control.js b/packages/block-library/src/navigation/edit/navigation-menu-delete-control.js index a75ad1dd00cce2..e95e07ab778c2f 100644 --- a/packages/block-library/src/navigation/edit/navigation-menu-delete-control.js +++ b/packages/block-library/src/navigation/edit/navigation-menu-delete-control.js @@ -19,8 +19,7 @@ export default function NavigationMenuDeleteControl( { onDelete } ) { return ( <> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="wp-block-navigation-delete-menu-button" variant="secondary" isDestructive diff --git a/packages/block-library/src/navigation/edit/placeholder/index.js b/packages/block-library/src/navigation/edit/placeholder/index.js index f4d01b73e1fbbd..7b989de1490afb 100644 --- a/packages/block-library/src/navigation/edit/placeholder/index.js +++ b/packages/block-library/src/navigation/edit/placeholder/index.js @@ -76,8 +76,7 @@ export default function NavigationPlaceholder( { { canUserCreateNavigationMenus && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" onClick={ onCreateEmpty } > diff --git a/packages/block-library/src/navigation/edit/responsive-wrapper.js b/packages/block-library/src/navigation/edit/responsive-wrapper.js index 328152723026f5..886e808965ce4b 100644 --- a/packages/block-library/src/navigation/edit/responsive-wrapper.js +++ b/packages/block-library/src/navigation/edit/responsive-wrapper.js @@ -79,8 +79,7 @@ export default function ResponsiveWrapper( { <> { ! isOpen && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize aria-haspopup="true" aria-label={ hasIcon && __( 'Open menu' ) } className={ openButtonClasses } @@ -102,8 +101,7 @@ export default function ResponsiveWrapper( { > <div { ...dialogProps }> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="wp-block-navigation__responsive-container-close" aria-label={ hasIcon && __( 'Close menu' ) } onClick={ () => onToggle( false ) } diff --git a/packages/block-library/src/navigation/editor.scss b/packages/block-library/src/navigation/editor.scss index a8d135656e44a1..1d37186e4ae98b 100644 --- a/packages/block-library/src/navigation/editor.scss +++ b/packages/block-library/src/navigation/editor.scss @@ -563,7 +563,11 @@ body.editor-styles-wrapper .wp-block-navigation__responsive-container.is-menu-op width: 100%; background-color: $gray-100; padding: 0 $grid-unit-30; - height: $grid-unit-40 * 2; + + // Adding !important to override default 40px size. + // Ref - https://github.com/WordPress/gutenberg/pull/65075#discussion_r1746282734 + height: $grid-unit-40 * 2 !important; + margin-bottom: $grid-unit-15; &.open { From 886c2b41191ef951e9a2843ed1f43c1a506e49c1 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Sat, 7 Sep 2024 11:52:17 +1000 Subject: [PATCH 0720/1908] Locked Templates: blocks with contentOnly locking should not be transformable (#64917) In the block-switcher, hide the drop down with block transforms and variation if a selected block, or one of multiple, is content locked. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../src/components/block-inspector/index.js | 1 - .../src/components/block-switcher/index.js | 22 ++++++++++++++++--- .../src/components/block-toolbar/index.js | 13 ++++++++--- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index 1986ad8730c121..a18556f2fa5bd9 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -72,7 +72,6 @@ function BlockInspectorLockedBlocks( { topLevelLockedBlock } ) { { ...blockInformation } className={ blockInformation.isSynced && 'is-synced' } /> - <BlockVariationTransforms blockClientId={ topLevelLockedBlock } /> <BlockInfo.Slot /> { hasBlockStyles && ( <BlockStylesPanel clientId={ topLevelLockedBlock } /> diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js index c8ee422091ad1f..98e7f7b2d21420 100644 --- a/packages/block-editor/src/components/block-switcher/index.js +++ b/packages/block-editor/src/components/block-switcher/index.js @@ -198,6 +198,7 @@ const BlockIndicator = ( { icon, showTitle, blockTitle } ) => ( export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { const { + hasContentOnlyLocking, canRemove, hasBlockStyles, icon, @@ -206,8 +207,12 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { isTemplate, } = useSelect( ( select ) => { - const { getBlocksByClientId, getBlockAttributes, canRemoveBlocks } = - select( blockEditorStore ); + const { + getTemplateLock, + getBlocksByClientId, + getBlockAttributes, + canRemoveBlocks, + } = select( blockEditorStore ); const { getBlockStyles, getBlockType, getActiveBlockVariation } = select( blocksStore ); const _blocks = getBlocksByClientId( clientIds ); @@ -219,6 +224,7 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { const blockType = getBlockType( firstBlockName ); let _icon; + let _hasTemplateLock; if ( _isSingleBlockSelected ) { const match = getActiveBlockVariation( firstBlockName, @@ -226,9 +232,14 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { ); // Take into account active block variations. _icon = match?.icon || blockType.icon; + _hasTemplateLock = + getTemplateLock( clientIds[ 0 ] ) === 'contentOnly'; } else { const isSelectionOfSameType = new Set( _blocks.map( ( { name } ) => name ) ).size === 1; + _hasTemplateLock = clientIds.some( + ( id ) => getTemplateLock( id ) === 'contentOnly' + ); // When selection consists of blocks of multiple types, display an // appropriate icon to communicate the non-uniformity. _icon = isSelectionOfSameType ? blockType.icon : copy; @@ -244,6 +255,7 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { _isSingleBlockSelected && isReusableBlock( _blocks[ 0 ] ), isTemplate: _isSingleBlockSelected && isTemplatePart( _blocks[ 0 ] ), + hasContentOnlyLocking: _hasTemplateLock, }; }, [ clientIds ] @@ -252,6 +264,7 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { clientId: clientIds?.[ 0 ], maximumLength: 35, } ); + if ( invalidBlocks ) { return null; } @@ -261,7 +274,10 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { ? blockTitle : __( 'Multiple blocks selected' ); - const hideDropdown = disabled || ( ! hasBlockStyles && ! canRemove ); + const hideDropdown = + disabled || + ( ! hasBlockStyles && ! canRemove ) || + hasContentOnlyLocking; if ( hideDropdown ) { return ( diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index b14ceb50590495..6c4789cb2924f2 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -66,6 +66,7 @@ export function PrivateBlockToolbar( { showParentSelector, isUsingBindings, hasParentPattern, + hasContentOnlyLocking, } = useSelect( ( select ) => { const { getBlockName, @@ -76,6 +77,7 @@ export function PrivateBlockToolbar( { getBlockEditingMode, getBlockAttributes, getBlockParentsByBlockName, + getTemplateLock, } = select( blockEditorStore ); const selectedBlockClientIds = getSelectedBlockClientIds(); const selectedBlockClientId = selectedBlockClientIds[ 0 ]; @@ -103,6 +105,10 @@ export function PrivateBlockToolbar( { .length > 0 ); + // If one or more selected blocks are locked, do not show the BlockGroupToolbar. + const _hasTemplateLock = selectedBlockClientIds.some( + ( id ) => getTemplateLock( id ) === 'contentOnly' + ); return { blockClientId: selectedBlockClientId, blockClientIds: selectedBlockClientIds, @@ -123,6 +129,7 @@ export function PrivateBlockToolbar( { _isDefaultEditingMode, isUsingBindings: _isUsingBindings, hasParentPattern: _hasParentPattern, + hasContentOnlyLocking: _hasTemplateLock, }; }, [] ); @@ -205,9 +212,9 @@ export function PrivateBlockToolbar( { </ToolbarGroup> </div> ) } - { shouldShowVisualToolbar && isMultiToolbar && ( - <BlockGroupToolbar /> - ) } + { ! hasContentOnlyLocking && + shouldShowVisualToolbar && + isMultiToolbar && <BlockGroupToolbar /> } { shouldShowVisualToolbar && ( <> <BlockControls.Slot From fa78b66aea850d13e0621d0fcc6ddaf5ca3772f4 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Mon, 9 Sep 2024 09:41:03 +1000 Subject: [PATCH 0721/1908] Patterns: add opt out preference to the 'Choose a Pattern' modal when adding a page (#65026) * Adds a preference to disable the loading of the Choose a pattern modal when adding new pages. * Return an empty array from the memoized value of useStartPatterns() so that the preferences modal has a value to test. * Don't reset the `isClosed` value in the same editor session. This prevents the modal popping open between page > template part > page navigation. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jakobtrost <jtgreyd@git.wordpress.org> Co-authored-by: johnstonphilip <johnstonphilip@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: MattrCoUk <cambabutonono@git.wordpress.org> Co-authored-by: jasonbahl <jasonbahl@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> Co-authored-by: Blindmikey <blindmikey@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: luminuu <luminuu@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: jordesign <jordesign@git.wordpress.org> --- packages/edit-post/src/index.js | 1 + packages/edit-site/src/index.js | 1 + packages/edit-site/src/posts.js | 1 + .../src/components/preferences-modal/index.js | 13 +++++ .../components/start-page-options/index.js | 54 ++++++++++--------- 5 files changed, 44 insertions(+), 26 deletions(-) diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index 51abac654da295..daf789cb0a2ec9 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -70,6 +70,7 @@ export function initializeEditor( showBlockBreadcrumbs: true, showIconLabels: false, showListViewByDefault: false, + enableChoosePatternModal: true, isPublishSidebarEnabled: true, } ); diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 4ed5b96e3844d1..1aceecc4d8b1fc 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -79,6 +79,7 @@ export function initializeEditor( id, settings ) { openPanels: [ 'post-status' ], showBlockBreadcrumbs: true, showListViewByDefault: false, + enableChoosePatternModal: true, } ); if ( window.__experimentalMediaProcessing ) { diff --git a/packages/edit-site/src/posts.js b/packages/edit-site/src/posts.js index 9e2582ac23328a..78d823b56c4c11 100644 --- a/packages/edit-site/src/posts.js +++ b/packages/edit-site/src/posts.js @@ -72,6 +72,7 @@ export function initializePostsDashboard( id, settings ) { openPanels: [ 'post-status' ], showBlockBreadcrumbs: true, showListViewByDefault: false, + enableChoosePatternModal: true, } ); dispatch( editSiteStore ).updateSettings( settings ); diff --git a/packages/editor/src/components/preferences-modal/index.js b/packages/editor/src/components/preferences-modal/index.js index e7cc637dd0aed0..a8cfd8245522cd 100644 --- a/packages/editor/src/components/preferences-modal/index.js +++ b/packages/editor/src/components/preferences-modal/index.js @@ -26,6 +26,7 @@ import PageAttributesCheck from '../page-attributes/check'; import PostTypeSupportCheck from '../post-type-support-check'; import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; +import { useStartPatterns } from '../start-page-options'; const { PreferencesModal, @@ -57,6 +58,7 @@ export default function EditorPreferencesModal( { extraSections = {} } ) { const { setIsListViewOpened, setIsInserterOpened } = useDispatch( editorStore ); const { set: setPreference } = useDispatch( preferencesStore ); + const hasStarterPatterns = !! useStartPatterns().length; const sections = useMemo( () => @@ -97,6 +99,16 @@ export default function EditorPreferencesModal( { extraSections = {} } ) { 'Allow right-click contextual menus' ) } /> + { hasStarterPatterns && ( + <PreferenceToggleControl + scope="core" + featureName="enableChoosePatternModal" + help={ __( + 'Shows starter patterns when creating a new page.' + ) } + label={ __( 'Show starter patterns' ) } + /> + ) } </PreferencesModalSection> <PreferencesModalSection title={ __( 'Document settings' ) } @@ -314,6 +326,7 @@ export default function EditorPreferencesModal( { extraSections = {} } ) { setIsListViewOpened, setPreference, isLargeViewport, + hasStarterPatterns, ] ); diff --git a/packages/editor/src/components/start-page-options/index.js b/packages/editor/src/components/start-page-options/index.js index d888d1ccc4342d..07fee67fbed19b 100644 --- a/packages/editor/src/components/start-page-options/index.js +++ b/packages/editor/src/components/start-page-options/index.js @@ -3,7 +3,7 @@ */ import { Modal } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { useState, useMemo, useEffect } from '@wordpress/element'; +import { useState, useMemo } from '@wordpress/element'; import { store as blockEditorStore, __experimentalBlockPatternsList as BlockPatternsList, @@ -12,6 +12,8 @@ import { useSelect, useDispatch } from '@wordpress/data'; import { useAsyncList } from '@wordpress/compose'; import { store as coreStore } from '@wordpress/core-data'; import { __unstableSerializeAndClean } from '@wordpress/blocks'; +import { store as preferencesStore } from '@wordpress/preferences'; +import { store as interfaceStore } from '@wordpress/interface'; /** * Internal dependencies @@ -19,7 +21,7 @@ import { __unstableSerializeAndClean } from '@wordpress/blocks'; import { store as editorStore } from '../../store'; import { TEMPLATE_POST_TYPE } from '../../store/constants'; -function useStartPatterns() { +export function useStartPatterns() { // A pattern is a start pattern if it includes 'core/post-content' in its blockTypes, // and it has no postTypes declared and the current post type is page or if // the current post type is part of the postTypes declared. @@ -45,8 +47,14 @@ function useStartPatterns() { ); return useMemo( () => { - // filter patterns without postTypes declared if the current postType is page - // or patterns that declare the current postType in its post type array. + if ( ! blockPatternsWithPostContentBlockType?.length ) { + return []; + } + + /* + * Filter patterns without postTypes declared if the current postType is page + * or patterns that declare the current postType in its post type array. + */ return blockPatternsWithPostContentBlockType.filter( ( pattern ) => { return ( ( postType === 'page' && ! pattern.postTypes ) || @@ -110,30 +118,24 @@ function StartPageOptionsModal( { onClose } ) { export default function StartPageOptions() { const [ isClosed, setIsClosed ] = useState( false ); - const { shouldEnableModal, postType, postId } = useSelect( ( select ) => { - const { - isEditedPostDirty, - isEditedPostEmpty, - getCurrentPostType, - getCurrentPostId, - } = select( editorStore ); - const _postType = getCurrentPostType(); - - return { - shouldEnableModal: - ! isEditedPostDirty() && - isEditedPostEmpty() && - TEMPLATE_POST_TYPE !== _postType, - postType: _postType, - postId: getCurrentPostId(), - }; + const shouldEnableModal = useSelect( ( select ) => { + const { isEditedPostDirty, isEditedPostEmpty, getCurrentPostType } = + select( editorStore ); + const preferencesModalActive = + select( interfaceStore ).isModalActive( 'editor/preferences' ); + const choosePatternModalEnabled = select( preferencesStore ).get( + 'core', + 'enableChoosePatternModal' + ); + return ( + choosePatternModalEnabled && + ! preferencesModalActive && + ! isEditedPostDirty() && + isEditedPostEmpty() && + TEMPLATE_POST_TYPE !== getCurrentPostType() + ); }, [] ); - useEffect( () => { - // Should reset the modal state when navigating to a new page/post. - setIsClosed( false ); - }, [ postType, postId ] ); - if ( ! shouldEnableModal || isClosed ) { return null; } From 82bc72dedd2815fbc0d407782fde2a12c4139a7e Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Mon, 9 Sep 2024 11:57:21 +1000 Subject: [PATCH 0722/1908] Preferences: Fix back button on mobile (#65141) Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../src/components/preferences-modal-tabs/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/preferences/src/components/preferences-modal-tabs/index.js b/packages/preferences/src/components/preferences-modal-tabs/index.js index f70430367cc617..d87e565f5e3364 100644 --- a/packages/preferences/src/components/preferences-modal-tabs/index.js +++ b/packages/preferences/src/components/preferences-modal-tabs/index.js @@ -110,7 +110,7 @@ export default function PreferencesModalTabs( { sections } ) { return ( <NavigatorButton key={ tab.name } - path={ tab.name } + path={ `/${ tab.name }` } as={ Item } isAction > @@ -142,7 +142,7 @@ export default function PreferencesModalTabs( { sections } ) { return ( <NavigatorScreen key={ `${ section.name }-menu` } - path={ section.name } + path={ `/${ section.name }` } > <Card isBorderless size="large"> <CardHeader From 168d3c5e3fdb62ecf34528720a12631ba83e0ea4 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Mon, 9 Sep 2024 13:47:19 +0530 Subject: [PATCH 0723/1908] Fix: Button: Replace remaining 40px default size violation [Block library 3] (#65110) * Fix the modal button for page list to use default 40px button size * Fix convert page list to navigation links edit button to use 40px default size * Fix enable comments form to use 40px default button size * Fix featured image block open media library button to use 40px default sizee * Fix site-logo block to use 40px default button size * Fix social link apply link button to use 40px default size * Revert social link apply button size to todo state --- .../block-library/src/page-list/convert-to-links-modal.js | 6 ++---- packages/block-library/src/page-list/edit.js | 3 +-- packages/block-library/src/post-comments-form/form.js | 3 +-- packages/block-library/src/post-featured-image/edit.js | 3 +-- packages/block-library/src/site-logo/edit.js | 6 ++---- packages/block-library/src/social-link/edit.js | 2 +- 6 files changed, 8 insertions(+), 15 deletions(-) diff --git a/packages/block-library/src/page-list/convert-to-links-modal.js b/packages/block-library/src/page-list/convert-to-links-modal.js index b56b3bf7c6b4f1..f2ab425a1ef10a 100644 --- a/packages/block-library/src/page-list/convert-to-links-modal.js +++ b/packages/block-library/src/page-list/convert-to-links-modal.js @@ -32,16 +32,14 @@ export function ConvertToLinksModal( { onClick, onClose, disabled } ) { </p> <div className="wp-block-page-list-modal-buttons"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" onClick={ onClose } > { __( 'Cancel' ) } </Button> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" accessibleWhenDisabled disabled={ disabled } diff --git a/packages/block-library/src/page-list/edit.js b/packages/block-library/src/page-list/edit.js index 750d5a1ad8b92a..31e400b8676717 100644 --- a/packages/block-library/src/page-list/edit.js +++ b/packages/block-library/src/page-list/edit.js @@ -342,8 +342,7 @@ export default function PageListEdit( { <PanelBody title={ __( 'Edit this menu' ) }> <p>{ convertDescription }</p> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" accessibleWhenDisabled disabled={ ! hasResolvedPages } diff --git a/packages/block-library/src/post-comments-form/form.js b/packages/block-library/src/post-comments-form/form.js index 882282a53c6afc..20f0ebca61ead6 100644 --- a/packages/block-library/src/post-comments-form/form.js +++ b/packages/block-library/src/post-comments-form/form.js @@ -84,8 +84,7 @@ const CommentsForm = ( { postId, postType } ) => { if ( 'closed' === commentStatus ) { const actions = [ <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize key="enableComments" onClick={ () => setCommentStatus( 'open' ) } variant="primary" diff --git a/packages/block-library/src/post-featured-image/edit.js b/packages/block-library/src/post-featured-image/edit.js index ff777f707330df..dff34379e4f3b4 100644 --- a/packages/block-library/src/post-featured-image/edit.js +++ b/packages/block-library/src/post-featured-image/edit.js @@ -308,8 +308,7 @@ export default function PostFeaturedImageEdit( { mediaLibraryButton={ ( { open } ) => { return ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize icon={ upload } variant="primary" label={ label } diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index 1d541ba35d6313..dc95d5906d7345 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -627,8 +627,7 @@ export default function LogoEdit( { render={ ( { open } ) => ( <div className="block-library-site-logo__inspector-upload-container"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize onClick={ open } variant="secondary" > @@ -674,8 +673,7 @@ export default function LogoEdit( { mediaLibraryButton={ ( { open } ) => { return ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize icon={ upload } variant="primary" label={ __( 'Choose logo' ) } diff --git a/packages/block-library/src/social-link/edit.js b/packages/block-library/src/social-link/edit.js index f6d46731a399f3..65d85c0400116f 100644 --- a/packages/block-library/src/social-link/edit.js +++ b/packages/block-library/src/social-link/edit.js @@ -81,7 +81,7 @@ const SocialLinkURLPopover = ( { /> </div> <Button - // TODO: Switch to `true` (40px size) if possible + // TODO: Switch to `true` (40px size) if possible. __next40pxDefaultSize={ false } icon={ keyboardReturn } label={ __( 'Apply' ) } From 6dae3c7ff60adf71922a607b71f11b0fe0737fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Mon, 9 Sep 2024 11:03:40 +0200 Subject: [PATCH 0724/1908] DataViews: remove unused `.dataviews-view-table__cell-content-wrapper:empty` style rule (#65084) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/dataviews/src/dataviews-layouts/table/style.scss | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/dataviews/src/dataviews-layouts/table/style.scss b/packages/dataviews/src/dataviews-layouts/table/style.scss index dd091db4ec99f5..ea2c614e4339df 100644 --- a/packages/dataviews/src/dataviews-layouts/table/style.scss +++ b/packages/dataviews/src/dataviews-layouts/table/style.scss @@ -171,10 +171,6 @@ } } -.dataviews-view-table__cell-content-wrapper:empty { - display: none; -} - /* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ @container (max-width: 430px) { .dataviews-view-table tr td:first-child, From 1d33b4e8227f70bc68e37f94d4d009d7a0bd5af6 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Mon, 9 Sep 2024 14:49:25 +0200 Subject: [PATCH 0725/1908] Media placeholders: Add "drag" to the text. (#65149) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../block-editor/src/components/media-placeholder/index.js | 6 +++--- packages/block-library/src/image/edit.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index bbf546a3953f32..4d41289f324c0f 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -323,15 +323,15 @@ export function MediaPlaceholder( { if ( isAudio ) { instructions = __( - 'Upload an audio file, pick one from your media library, or add one with a URL.' + 'Upload or drag an audio file here, or pick one from your library.' ); } else if ( isImage ) { instructions = __( - 'Upload an image file, pick one from your media library, or add one with a URL.' + 'Upload or drag an image file here, or pick one from your library.' ); } else if ( isVideo ) { instructions = __( - 'Upload a video file, pick one from your media library, or add one with a URL.' + 'Upload or drag a video file here, or pick one from your library.' ); } } diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index ae8461a6b1cf4c..f9aed8d93f95a0 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -393,7 +393,7 @@ export function ImageEdit( { instructions={ ! lockUrlControls && __( - 'Upload an image file, pick one from your media library, or add one with a URL.' + 'Upload or drag an image file here, or pick one from your library.' ) } style={ { From 7376a6318edd9a831421eecd3b540e0769137f75 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 9 Sep 2024 18:00:56 +0400 Subject: [PATCH 0726/1908] Block Editor: Remove reset styles RTL from the iframe (#65150) Unlinked contributors: realthemes. Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../src/components/iframe/get-compatibility-styles.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/iframe/get-compatibility-styles.js b/packages/block-editor/src/components/iframe/get-compatibility-styles.js index ab80e0e8eb43ea..0eae82b11e01f8 100644 --- a/packages/block-editor/src/components/iframe/get-compatibility-styles.js +++ b/packages/block-editor/src/components/iframe/get-compatibility-styles.js @@ -40,7 +40,12 @@ export function getCompatibilityStyles() { // Don't try to add the reset styles, which were removed as a dependency // from `edit-blocks` for the iframe since we don't need to reset admin // styles. - if ( ownerNode.id === 'wp-reset-editor-styles-css' ) { + if ( + [ + 'wp-reset-editor-styles-css', + 'wp-reset-editor-styles-rtl-css', + ].includes( ownerNode.id ) + ) { return accumulator; } From 2f92b590290ef39ea0907e35bc1e335543e16e26 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Mon, 9 Sep 2024 17:19:54 +0100 Subject: [PATCH 0727/1908] Add prompt for drag and drop in Patterns tab in Zoom Out mode (#65115) * Add prompt for drag and drop * Remove icon and update styles * Use components and tweak * Avoid muted variant --- .../pattern-category-previews.js | 57 +++++++++++++------ .../src/components/inserter/style.scss | 4 ++ 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js index 3703381b23a140..913be6a5129736 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js @@ -17,6 +17,7 @@ import { __experimentalText as Text, FlexBlock, } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -32,6 +33,7 @@ import { myPatternsCategory, INSERTER_PATTERN_TYPES, } from './utils'; +import { store as blockEditorStore } from '../../../store'; const noop = () => {}; @@ -42,6 +44,11 @@ export function PatternCategoryPreviews( { category, showTitlesAsTooltip, } ) { + const isZoomOutMode = useSelect( + ( select ) => + select( blockEditorStore ).__unstableGetEditorMode() === 'zoom-out', + [] + ); const [ allPatterns, , onClickPattern ] = usePatternsState( onInsert, rootClientId, @@ -163,23 +170,39 @@ export function PatternCategoryPreviews( { </Text> ) } </VStack> - - { currentCategoryPatterns.length > 0 && ( - <BlockPatternsList - ref={ scrollContainerRef } - shownPatterns={ pagingProps.categoryPatternsAsyncList } - blockPatterns={ pagingProps.categoryPatterns } - onClickPattern={ onClickPattern } - onHover={ onHover } - label={ category.label } - orientation="vertical" - category={ category.name } - isDraggable - showTitlesAsTooltip={ showTitlesAsTooltip } - patternFilter={ patternSourceFilter } - pagingProps={ pagingProps } - /> - ) } + <VStack spacing={ 4 }> + { currentCategoryPatterns.length > 0 && ( + <> + { isZoomOutMode && ( + <Text + size="12" + as="p" + className="block-editor-inserter__help-text" + > + { __( + 'Drag and drop patterns into the canvas.' + ) } + </Text> + ) } + <BlockPatternsList + ref={ scrollContainerRef } + shownPatterns={ + pagingProps.categoryPatternsAsyncList + } + blockPatterns={ pagingProps.categoryPatterns } + onClickPattern={ onClickPattern } + onHover={ onHover } + label={ category.label } + orientation="vertical" + category={ category.name } + isDraggable + showTitlesAsTooltip={ showTitlesAsTooltip } + patternFilter={ patternSourceFilter } + pagingProps={ pagingProps } + /> + </> + ) } + </VStack> </> ); } diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index bd3ac3f961b88a..18389dc7e923c5 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -709,3 +709,7 @@ $block-inserter-tabs-height: 44px; } } } + +.block-editor-tabbed-sidebar__tabpanel .block-editor-inserter__help-text { + padding: 0 $grid-unit-30; +} From 6108be0fd33b3ef2a7a1b9faf4ce817f693c6b5b Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 9 Sep 2024 20:36:12 +0400 Subject: [PATCH 0728/1908] Upgrade Playwright to v1.47 (#65156) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> --- package-lock.json | 48 +++++++++++++++++------------------ package.json | 2 +- packages/scripts/package.json | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/package-lock.json b/package-lock.json index fdfaf033b93653..807fa042d2bd94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -99,7 +99,7 @@ "@octokit/rest": "16.26.0", "@octokit/types": "6.34.0", "@octokit/webhooks-types": "5.8.0", - "@playwright/test": "1.46.0", + "@playwright/test": "1.47.0", "@pmmmwh/react-refresh-webpack-plugin": "0.5.11", "@react-native/babel-preset": "0.73.10", "@react-native/metro-babel-transformer": "0.73.10", @@ -6950,12 +6950,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.46.0.tgz", - "integrity": "sha512-/QYft5VArOrGRP5pgkrfKksqsKA6CEFyGQ/gjNe6q0y4tZ1aaPfq4gIjudr1s3D+pXyrPRdsy4opKDrjBabE5w==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.0.tgz", + "integrity": "sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA==", "dev": true, "dependencies": { - "playwright": "1.46.0" + "playwright": "1.47.0" }, "bin": { "playwright": "cli.js" @@ -41081,12 +41081,12 @@ "dev": true }, "node_modules/playwright": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.0.tgz", - "integrity": "sha512-XYJ5WvfefWONh1uPAUAi0H2xXV5S3vrtcnXe6uAOgdGi3aSpqOSXX08IAjXW34xitfuOJsvXU5anXZxPSEQiJw==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.0.tgz", + "integrity": "sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==", "dev": true, "dependencies": { - "playwright-core": "1.46.0" + "playwright-core": "1.47.0" }, "bin": { "playwright": "cli.js" @@ -41099,9 +41099,9 @@ } }, "node_modules/playwright-core": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.0.tgz", - "integrity": "sha512-9Y/d5UIwuJk8t3+lhmMSAJyNP1BUC/DqP3cQJDQQL/oWqAiuPTLgy7Q5dzglmTLwcBRdetzgNM/gni7ckfTr6A==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0.tgz", + "integrity": "sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -54834,7 +54834,7 @@ "npm": ">=8.19.2" }, "peerDependencies": { - "@playwright/test": "^1.46.0", + "@playwright/test": "^1.47.0", "react": "^18.0.0", "react-dom": "^18.0.0" } @@ -60247,12 +60247,12 @@ } }, "@playwright/test": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.46.0.tgz", - "integrity": "sha512-/QYft5VArOrGRP5pgkrfKksqsKA6CEFyGQ/gjNe6q0y4tZ1aaPfq4gIjudr1s3D+pXyrPRdsy4opKDrjBabE5w==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.0.tgz", + "integrity": "sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA==", "dev": true, "requires": { - "playwright": "1.46.0" + "playwright": "1.47.0" } }, "@pmmmwh/react-refresh-webpack-plugin": { @@ -87571,19 +87571,19 @@ "dev": true }, "playwright": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.0.tgz", - "integrity": "sha512-XYJ5WvfefWONh1uPAUAi0H2xXV5S3vrtcnXe6uAOgdGi3aSpqOSXX08IAjXW34xitfuOJsvXU5anXZxPSEQiJw==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.0.tgz", + "integrity": "sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==", "dev": true, "requires": { "fsevents": "2.3.2", - "playwright-core": "1.46.0" + "playwright-core": "1.47.0" } }, "playwright-core": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.0.tgz", - "integrity": "sha512-9Y/d5UIwuJk8t3+lhmMSAJyNP1BUC/DqP3cQJDQQL/oWqAiuPTLgy7Q5dzglmTLwcBRdetzgNM/gni7ckfTr6A==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0.tgz", + "integrity": "sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==", "dev": true }, "please-upgrade-node": { diff --git a/package.json b/package.json index a67b376f3dbdc1..977929555f7dc6 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "@octokit/rest": "16.26.0", "@octokit/types": "6.34.0", "@octokit/webhooks-types": "5.8.0", - "@playwright/test": "1.46.0", + "@playwright/test": "1.47.0", "@pmmmwh/react-refresh-webpack-plugin": "0.5.11", "@react-native/babel-preset": "0.73.10", "@react-native/metro-babel-transformer": "0.73.10", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 35547682ae32b3..6661e9876683fa 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -94,7 +94,7 @@ "webpack-dev-server": "^4.15.1" }, "peerDependencies": { - "@playwright/test": "^1.46.0", + "@playwright/test": "^1.47.0", "react": "^18.0.0", "react-dom": "^18.0.0" }, From a89c8bdf121b076c3efd1dcc25170a03f10f17b8 Mon Sep 17 00:00:00 2001 From: David Arenas <david.arenas@automattic.com> Date: Mon, 9 Sep 2024 18:55:40 +0200 Subject: [PATCH 0729/1908] Interactivity API: Update iterable signals when `deepMerge()` adds new properties (#65135) * Add failing test * Fix `deepMerge` implementation * Update changelog * Move iterable signal updating outside `for...in` loop Co-authored-by: DAreRodz <darerodz@git.wordpress.org> Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- packages/interactivity/CHANGELOG.md | 1 + packages/interactivity/src/proxies/state.ts | 14 +++++++++++--- .../interactivity/src/proxies/test/deep-merge.ts | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index b888f159c00867..9ea269fa269ad0 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -5,6 +5,7 @@ ### Bug Fixes - Prevent calling `proxifyContext` over an already-proxified context inside `wp-context` ([#65090](https://github.com/WordPress/gutenberg/pull/65090)). +- Update iterable signals when `deepMerge()` adds new properties ([#65135](https://github.com/WordPress/gutenberg/pull/65135)). ## 6.7.0 (2024-09-05) diff --git a/packages/interactivity/src/proxies/state.ts b/packages/interactivity/src/proxies/state.ts index 323cd306bf9acf..ec49c4b27c4adb 100644 --- a/packages/interactivity/src/proxies/state.ts +++ b/packages/interactivity/src/proxies/state.ts @@ -276,13 +276,17 @@ const deepMergeRecursive = ( override: boolean = true ) => { if ( isPlainObject( target ) && isPlainObject( source ) ) { + let hasNewKeys = false; for ( const key in source ) { + const isNew = ! ( key in target ); + hasNewKeys = hasNewKeys || isNew; + const desc = Object.getOwnPropertyDescriptor( source, key ); if ( typeof desc?.get === 'function' || typeof desc?.set === 'function' ) { - if ( override || ! ( key in target ) ) { + if ( override || isNew ) { Object.defineProperty( target, key, { ...desc, configurable: true, @@ -296,12 +300,12 @@ const deepMergeRecursive = ( } } } else if ( isPlainObject( source[ key ] ) ) { - if ( ! ( key in target ) ) { + if ( isNew ) { target[ key ] = {}; } deepMergeRecursive( target[ key ], source[ key ], override ); - } else if ( override || ! ( key in target ) ) { + } else if ( override || isNew ) { Object.defineProperty( target, key, desc! ); const proxy = getProxyFromObject( target ); @@ -311,6 +315,10 @@ const deepMergeRecursive = ( } } } + + if ( hasNewKeys && objToIterable.has( target ) ) { + objToIterable.get( target )!.value++; + } } }; diff --git a/packages/interactivity/src/proxies/test/deep-merge.ts b/packages/interactivity/src/proxies/test/deep-merge.ts index b24d9b6781cfe2..bf31c4b552133c 100644 --- a/packages/interactivity/src/proxies/test/deep-merge.ts +++ b/packages/interactivity/src/proxies/test/deep-merge.ts @@ -374,5 +374,20 @@ describe( 'Interactivity API', () => { expect( spy ).toHaveBeenCalledTimes( 3 ); } ); + + it( 'should update iterable signals when new keys are added', () => { + const target = proxifyState< any >( 'test', { a: 1, b: 2 } ); + const source = { a: 1, b: 2, c: 3 }; + + const spy = jest.fn( () => Object.keys( target ) ); + effect( spy ); + + expect( spy ).toHaveBeenCalledTimes( 1 ); + + deepMerge( target, source, false ); + + expect( spy ).toHaveBeenCalledTimes( 2 ); + expect( spy ).toHaveLastReturnedWith( [ 'a', 'b', 'c' ] ); + } ); } ); } ); From 312fa6ef8cb6f5d7e06be2e334e19048423a36b2 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Tue, 10 Sep 2024 05:40:28 +0800 Subject: [PATCH 0730/1908] Editor topbar: reorder the actions on the right (#65163) * Editor - move publish button to penultimate position * Widgets - Move Save button to penultimate position * Reorder global styles/settings pinned items --- packages/edit-widgets/src/components/header/index.js | 2 +- packages/editor/src/components/editor/index.js | 2 +- packages/editor/src/components/header/index.js | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/edit-widgets/src/components/header/index.js b/packages/edit-widgets/src/components/header/index.js index 0aadec83d5d2f3..80dda479d59ed6 100644 --- a/packages/edit-widgets/src/components/header/index.js +++ b/packages/edit-widgets/src/components/header/index.js @@ -61,8 +61,8 @@ function Header() { ) } </div> <div className="edit-widgets-header__actions"> - <SaveButton /> <PinnedItems.Slot scope="core/edit-widgets" /> + <SaveButton /> <MoreMenu /> </div> </div> diff --git a/packages/editor/src/components/editor/index.js b/packages/editor/src/components/editor/index.js index b094c3ceb44376..21becea43cd7ee 100644 --- a/packages/editor/src/components/editor/index.js +++ b/packages/editor/src/components/editor/index.js @@ -74,11 +74,11 @@ function Editor( { <EditorInterface { ...props }> { extraContent } </EditorInterface> + { children } <Sidebar onActionPerformed={ onActionPerformed } extraPanels={ extraSidebarPanels } /> - { children } </ExperimentalEditorProvider> ) } </> diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index b8eda30c721860..2e045ad7329428 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -142,6 +142,9 @@ function Header( { forceIsAutosaveable={ forceIsDirty } /> <PostViewLink /> + { ( isWideViewport || ! showIconLabels ) && ( + <PinnedItems.Slot scope="core" /> + ) } { ! customSaveButton && ( <PostPublishButtonOrToggle forceIsDirty={ forceIsDirty } @@ -151,9 +154,6 @@ function Header( { /> ) } { customSaveButton } - { ( isWideViewport || ! showIconLabels ) && ( - <PinnedItems.Slot scope="core" /> - ) } <MoreMenu /> </motion.div> </div> From 537fb1800ce2784388ec3d130a37bd26f6f2f62f Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Mon, 9 Sep 2024 23:56:59 +0200 Subject: [PATCH 0731/1908] Add `useEvent` and `useObserveElementSize` to `@wordpress/compose` (#64943) * Simplify useResizeObserver * Loop through all resize entries * Add `useEvent` util. * Add `useObserveElementSize` util. * Simplify `useResizeObserver` by using `useEvent` and `useObserveElementSize`. * Switch to layout effect and accept refs too. * Prevent initial re-render in ResizeElement. * Better error message. * Improved example of useEvent. * Update packages/compose/src/hooks/use-event/index.ts Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com> * Sync docs. * Avoid redundant resize listener calls. * Switch to structural check. * Improve example. * Fix docs. * Make `useObserveElementSize` generic. * New API that returns a ref. * Make utility private for now. * Mark legacy `useResizeObserver` as such. * Rename `useObserveElementSize` to `useResizeObserver`. * Add return type. * Add signature as overload. * Add support for legacy API. * Move into subdirectory. * Minor import fix. * Fix docgen to support overloads (will pick up the first function signature). * Replace legacy utility with the new one. * Apply feedback. * Clean up and document. * Added changelog entries. --------- Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/compose/CHANGELOG.md | 9 +- packages/compose/README.md | 52 ++++++-- packages/compose/src/hooks/use-event/index.ts | 51 ++++++++ .../{ => _legacy}/index.native.js | 0 .../{ => _legacy}/index.tsx | 44 +++---- .../{ => _legacy}/test/index.native.js | 2 +- .../src/hooks/use-resize-observer/index.ts | 119 ++++++++++++++++++ packages/compose/src/index.js | 1 + packages/docgen/lib/get-type-annotation.js | 4 + 9 files changed, 238 insertions(+), 44 deletions(-) create mode 100644 packages/compose/src/hooks/use-event/index.ts rename packages/compose/src/hooks/use-resize-observer/{ => _legacy}/index.native.js (100%) rename packages/compose/src/hooks/use-resize-observer/{ => _legacy}/index.tsx (86%) rename packages/compose/src/hooks/use-resize-observer/{ => _legacy}/test/index.native.js (96%) create mode 100644 packages/compose/src/hooks/use-resize-observer/index.ts diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index 2683fe8d79be70..cc0d7ef333f0d6 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +### New Features + +- `useEvent`: a new utility that creates a stable callback function that has access to the latest state and can be used within event handlers and effect callbacks ([#64943](https://github.com/WordPress/gutenberg/pull/64943)). +- `useResizeObserver`: new and improved version of the utility (legacy API is still supported) ([#64943](https://github.com/WordPress/gutenberg/pull/64943)). + ## 7.7.0 (2024-09-05) ## 7.6.0 (2024-08-21) @@ -205,8 +210,8 @@ ### Breaking Changes -- Drop support for Internet Explorer 11 ([#31110](https://github.com/WordPress/gutenberg/pull/31110)). Learn more at https://make.wordpress.org/core/2021/04/22/ie-11-support-phase-out-plan/. -- Increase the minimum Node.js version to v12 matching Long Term Support releases ([#31270](https://github.com/WordPress/gutenberg/pull/31270)). Learn more at https://nodejs.org/en/about/releases/. +- Drop support for Internet Explorer 11 ([#31110](https://github.com/WordPress/gutenberg/pull/31110)). Learn more at <https://make.wordpress.org/core/2021/04/22/ie-11-support-phase-out-plan/>. +- Increase the minimum Node.js version to v12 matching Long Term Support releases ([#31270](https://github.com/WordPress/gutenberg/pull/31270)). Learn more at <https://nodejs.org/en/about/releases/>. ## 3.25.0 (2021-03-17) diff --git a/packages/compose/README.md b/packages/compose/README.md index 0da853ad75c5af..b4e20a79bab0cc 100644 --- a/packages/compose/README.md +++ b/packages/compose/README.md @@ -305,6 +305,29 @@ _Returns_ - `import('react').RefCallback<HTMLElement>`: Element Ref. +### useEvent + +Creates a stable callback function that has access to the latest state and can be used within event handlers and effect callbacks. Throws when used in the render phase. + +_Usage_ + +```tsx +function Component( props ) { + const onClick = useEvent( props.onClick ); + useEffect( () => { + onClick(); + // Won't trigger the effect again when props.onClick is updated. + }, [ onClick ] ); + // Won't re-render Button when props.onClick is updated (if `Button` is + // wrapped in `React.memo`). + return <Button onClick={ onClick } />; +} +``` + +_Parameters_ + +- _callback_ `T`: The callback function to wrap. + ### useFocusableIframe Dispatches a bubbling focus event when the iframe receives focus. Use `onFocus` as usual on the iframe or a parent element. @@ -500,23 +523,30 @@ _Returns_ ### useResizeObserver -Hook which allows to listen to the resize event of any target element when it changes size. \_Note: `useResizeObserver` will report `null` sizes until after first render. +Sets up a [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/Resize_Observer_API) for an HTML or SVG element. + +Pass the returned setter as a callback ref to the React element you want to observe, or use it in layout effects for advanced use cases. _Usage_ -```js -const App = () => { - const [ resizeListener, sizes ] = useResizeObserver(); +```tsx +const setElement = useResizeObserver( + ( resizeObserverEntries ) => console.log( resizeObserverEntries ), + { box: 'border-box' } +); +<div ref={ setElement } />; - return ( - <div> - { resizeListener } - Your content here - </div> - ); -}; +// The setter can be used in other ways, for example: +useLayoutEffect( () => { + setElement( document.querySelector( `data-element-id="${ elementId }"` ) ); +}, [ elementId ] ); ``` +_Parameters_ + +- _callback_ `ResizeObserverCallback`: The `ResizeObserver` callback - [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/ResizeObserver#callback). +- _options_ `ResizeObserverOptions`: Options passed to `ResizeObserver.observe` when called - [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/observe#options). Changes will be ignored. + ### useStateWithHistory useState with undo/redo history. diff --git a/packages/compose/src/hooks/use-event/index.ts b/packages/compose/src/hooks/use-event/index.ts new file mode 100644 index 00000000000000..d381bcb595bf65 --- /dev/null +++ b/packages/compose/src/hooks/use-event/index.ts @@ -0,0 +1,51 @@ +/** + * WordPress dependencies + */ +import { useRef, useInsertionEffect, useCallback } from '@wordpress/element'; + +/** + * Any function. + */ +export type AnyFunction = ( ...args: any ) => any; + +/** + * Creates a stable callback function that has access to the latest state and + * can be used within event handlers and effect callbacks. Throws when used in + * the render phase. + * + * @param callback The callback function to wrap. + * + * @example + * + * ```tsx + * function Component( props ) { + * const onClick = useEvent( props.onClick ); + * useEffect( () => { + * onClick(); + * // Won't trigger the effect again when props.onClick is updated. + * }, [ onClick ] ); + * // Won't re-render Button when props.onClick is updated (if `Button` is + * // wrapped in `React.memo`). + * return <Button onClick={ onClick } />; + * } + * ``` + */ +export default function useEvent< T extends AnyFunction >( + /** + * The callback function to wrap. + */ + callback?: T +) { + const ref = useRef< AnyFunction | undefined >( () => { + throw new Error( + 'Callbacks created with `useEvent` cannot be called during rendering.' + ); + } ); + useInsertionEffect( () => { + ref.current = callback; + } ); + return useCallback< AnyFunction >( + ( ...args ) => ref.current?.( ...args ), + [] + ) as T; +} diff --git a/packages/compose/src/hooks/use-resize-observer/index.native.js b/packages/compose/src/hooks/use-resize-observer/_legacy/index.native.js similarity index 100% rename from packages/compose/src/hooks/use-resize-observer/index.native.js rename to packages/compose/src/hooks/use-resize-observer/_legacy/index.native.js diff --git a/packages/compose/src/hooks/use-resize-observer/index.tsx b/packages/compose/src/hooks/use-resize-observer/_legacy/index.tsx similarity index 86% rename from packages/compose/src/hooks/use-resize-observer/index.tsx rename to packages/compose/src/hooks/use-resize-observer/_legacy/index.tsx index 05461bb2468b07..b44bd841964164 100644 --- a/packages/compose/src/hooks/use-resize-observer/index.tsx +++ b/packages/compose/src/hooks/use-resize-observer/_legacy/index.tsx @@ -6,14 +6,13 @@ import type { ReactElement } from 'react'; /** * WordPress dependencies */ -import { - useCallback, - useLayoutEffect, - useRef, - useState, -} from '@wordpress/element'; +import { useCallback, useRef, useState } from '@wordpress/element'; +/** + * Internal dependencies + */ +import useResizeObserver from '../index'; -type ObservedSize = { +export type ObservedSize = { width: number | null; height: number | null; }; @@ -84,28 +83,10 @@ type ResizeElementProps = { }; function ResizeElement( { onResize }: ResizeElementProps ) { - const resizeElementRef = useRef< HTMLDivElement >( null ); - const resizeCallbackRef = useRef( onResize ); - - useLayoutEffect( () => { - resizeCallbackRef.current = onResize; - }, [ onResize ] ); - - useLayoutEffect( () => { - const resizeElement = resizeElementRef.current as HTMLDivElement; - const resizeObserver = new ResizeObserver( ( entries ) => { - for ( const entry of entries ) { - const newSize = extractSize( entry ); - resizeCallbackRef.current( newSize ); - } - } ); - - resizeObserver.observe( resizeElement ); - - return () => { - resizeObserver.unobserve( resizeElement ); - }; - }, [] ); + const resizeElementRef = useResizeObserver( ( entries ) => { + const newSize = extractSize( entries.at( -1 )! ); // Entries are never empty. + onResize( newSize ); + } ); return ( <div @@ -141,7 +122,10 @@ const NULL_SIZE: ObservedSize = { width: null, height: null }; * }; * ``` */ -export default function useResizeObserver(): [ ReactElement, ObservedSize ] { +export default function useLegacyResizeObserver(): [ + ReactElement, + ObservedSize, +] { const [ size, setSize ] = useState( NULL_SIZE ); // Using a ref to track the previous width / height to avoid unnecessary renders. diff --git a/packages/compose/src/hooks/use-resize-observer/test/index.native.js b/packages/compose/src/hooks/use-resize-observer/_legacy/test/index.native.js similarity index 96% rename from packages/compose/src/hooks/use-resize-observer/test/index.native.js rename to packages/compose/src/hooks/use-resize-observer/_legacy/test/index.native.js index 6370b3f9cd054b..8ff90d0c778fd4 100644 --- a/packages/compose/src/hooks/use-resize-observer/test/index.native.js +++ b/packages/compose/src/hooks/use-resize-observer/_legacy/test/index.native.js @@ -7,7 +7,7 @@ import { View } from 'react-native'; /** * Internal dependencies */ -import useResizeObserver from '../'; +import useResizeObserver from '..'; const TestComponent = ( { onLayout } ) => { const [ resizeObserver, sizes ] = useResizeObserver(); diff --git a/packages/compose/src/hooks/use-resize-observer/index.ts b/packages/compose/src/hooks/use-resize-observer/index.ts new file mode 100644 index 00000000000000..2a76b2aa6ab590 --- /dev/null +++ b/packages/compose/src/hooks/use-resize-observer/index.ts @@ -0,0 +1,119 @@ +/** + * WordPress dependencies + */ +import { useRef } from '@wordpress/element'; +/** + * Internal dependencies + */ +import useEvent from '../use-event'; +import type { ObservedSize } from './_legacy'; +import _useLegacyResizeObserver from './_legacy'; +/** + * External dependencies + */ +import type { ReactElement } from 'react'; + +// This is the current implementation of `useResizeObserver`. +// +// The legacy implementation is still supported for backwards compatibility. +// This is achieved by overloading the exported function with both signatures, +// and detecting which API is being used at runtime. +function _useResizeObserver< T extends HTMLElement >( + callback: ResizeObserverCallback, + resizeObserverOptions: ResizeObserverOptions = {} +): ( element?: T | null ) => void { + const callbackEvent = useEvent( callback ); + + const observedElementRef = useRef< T | null >(); + const resizeObserverRef = useRef< ResizeObserver >(); + return useEvent( ( element?: T | null ) => { + if ( element === observedElementRef.current ) { + return; + } + observedElementRef.current = element; + + // Set up `ResizeObserver`. + resizeObserverRef.current ??= new ResizeObserver( callbackEvent ); + const { current: resizeObserver } = resizeObserverRef; + + // Unobserve previous element. + if ( observedElementRef.current ) { + resizeObserver.unobserve( observedElementRef.current ); + } + + // Observe new element. + if ( element ) { + resizeObserver.observe( element, resizeObserverOptions ); + } + } ); +} + +/** + * Sets up a [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/Resize_Observer_API) + * for an HTML or SVG element. + * + * Pass the returned setter as a callback ref to the React element you want + * to observe, or use it in layout effects for advanced use cases. + * + * @example + * + * ```tsx + * const setElement = useResizeObserver( + * ( resizeObserverEntries ) => console.log( resizeObserverEntries ), + * { box: 'border-box' } + * ); + * <div ref={ setElement } />; + * + * // The setter can be used in other ways, for example: + * useLayoutEffect( () => { + * setElement( document.querySelector( `data-element-id="${ elementId }"` ) ); + * }, [ elementId ] ); + * ``` + * + * @param callback The `ResizeObserver` callback - [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/ResizeObserver#callback). + * @param options Options passed to `ResizeObserver.observe` when called - [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/observe#options). Changes will be ignored. + */ +export default function useResizeObserver< T extends Element >( + /** + * The `ResizeObserver` callback - [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/ResizeObserver#callback). + */ + callback: ResizeObserverCallback, + /** + * Options passed to `ResizeObserver.observe` when called - [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/observe#options). Changes will be ignored. + */ + options?: ResizeObserverOptions +): ( element?: T | null ) => void; + +/** + * **This is a legacy API and should not be used.** + * + * @deprecated Use the other `useResizeObserver` API instead: `const ref = useResizeObserver( ( entries ) => { ... } )`. + * + * Hook which allows to listen to the resize event of any target element when it changes size. + * _Note: `useResizeObserver` will report `null` sizes until after first render. + * + * @example + * + * ```js + * const App = () => { + * const [ resizeListener, sizes ] = useResizeObserver(); + * + * return ( + * <div> + * { resizeListener } + * Your content here + * </div> + * ); + * }; + * ``` + */ +export default function useResizeObserver(): [ ReactElement, ObservedSize ]; + +export default function useResizeObserver< T extends HTMLElement >( + callback?: ResizeObserverCallback, + options: ResizeObserverOptions = {} +): ( ( element?: T | null ) => void ) | [ ReactElement, ObservedSize ] { + return callback + ? _useResizeObserver( callback, options ) + : _useLegacyResizeObserver(); +} diff --git a/packages/compose/src/index.js b/packages/compose/src/index.js index f7e1d1618f97fb..29a9aa61737440 100644 --- a/packages/compose/src/index.js +++ b/packages/compose/src/index.js @@ -25,6 +25,7 @@ export { default as useCopyOnClick } from './hooks/use-copy-on-click'; export { default as useCopyToClipboard } from './hooks/use-copy-to-clipboard'; export { default as __experimentalUseDialog } from './hooks/use-dialog'; export { default as useDisabled } from './hooks/use-disabled'; +export { default as useEvent } from './hooks/use-event'; export { default as __experimentalUseDragging } from './hooks/use-dragging'; export { default as useFocusOnMount } from './hooks/use-focus-on-mount'; export { default as __experimentalUseFocusOutside } from './hooks/use-focus-outside'; diff --git a/packages/docgen/lib/get-type-annotation.js b/packages/docgen/lib/get-type-annotation.js index b844c86ef7958a..5e72724952f29e 100644 --- a/packages/docgen/lib/get-type-annotation.js +++ b/packages/docgen/lib/get-type-annotation.js @@ -401,6 +401,10 @@ function getTypeAnnotation( typeAnnotation ) { * TODO: Remove the special-casing here once we're able to infer the types from TypeScript itself. */ function unwrapWrappedSelectors( token ) { + if ( babelTypes.isTSDeclareFunction( token ) ) { + return token; + } + if ( babelTypes.isFunctionDeclaration( token ) ) { return token; } From aca9273fd451cd9f264dd8116f9816e5b7ec3487 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Tue, 10 Sep 2024 11:22:35 +0530 Subject: [PATCH 0732/1908] Add the embed figcaption inside the figure tag (#64970) Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/block-library/src/embed/edit.js | 7 ------ .../block-library/src/embed/embed-preview.js | 24 +++++++++++++++++-- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/packages/block-library/src/embed/edit.js b/packages/block-library/src/embed/edit.js index 6978e144794047..da3dac3e3d62b5 100644 --- a/packages/block-library/src/embed/edit.js +++ b/packages/block-library/src/embed/edit.js @@ -14,7 +14,6 @@ import { embedContentIcon } from './icons'; import EmbedLoading from './embed-loading'; import EmbedPlaceholder from './embed-placeholder'; import EmbedPreview from './embed-preview'; -import { Caption } from '../utils/caption'; /** * External dependencies @@ -277,14 +276,8 @@ const EmbedEdit = ( props ) => { icon={ icon } label={ label } insertBlocksAfter={ insertBlocksAfter } - /> - <Caption attributes={ attributes } setAttributes={ setAttributes } - isSelected={ isSelected } - insertBlocksAfter={ insertBlocksAfter } - label={ __( 'Embed caption text' ) } - showToolbarButton={ isSelected } /> </View> </> diff --git a/packages/block-library/src/embed/embed-preview.js b/packages/block-library/src/embed/embed-preview.js index d53f1148cee13c..6ef10df08a8c24 100644 --- a/packages/block-library/src/embed/embed-preview.js +++ b/packages/block-library/src/embed/embed-preview.js @@ -21,6 +21,7 @@ import { getAuthority } from '@wordpress/url'; * Internal dependencies */ import WpEmbedPreview from './wp-embed-preview'; +import { Caption } from '../utils/caption'; class EmbedPreview extends Component { constructor() { @@ -52,8 +53,19 @@ class EmbedPreview extends Component { } render() { - const { preview, previewable, url, type, className, icon, label } = - this.props; + const { + preview, + previewable, + url, + type, + className, + icon, + label, + insertBlocksAfter, + attributes, + setAttributes, + isSelected, + } = this.props; const { scripts } = preview; const { interactive } = this.state; @@ -123,6 +135,14 @@ class EmbedPreview extends Component { </p> </Placeholder> ) } + <Caption + attributes={ attributes } + setAttributes={ setAttributes } + isSelected={ isSelected } + insertBlocksAfter={ insertBlocksAfter } + label={ __( 'Embed caption text' ) } + showToolbarButton={ isSelected } + /> </figure> ); } From cc133bfae5fe1b575e754fbcd71ff3505a448a35 Mon Sep 17 00:00:00 2001 From: Bernie Reiter <96308+ockham@users.noreply.github.com> Date: Tue, 10 Sep 2024 09:41:32 +0200 Subject: [PATCH 0733/1908] Build: Include Core blocks' `render` and `variations` files (#63311) If a Core block's `block.json` contains a `render` and/or `variations` field that points to a PHP file name, copy those files to the build directory. Co-authored-by: ockham <bernhard-reiter@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/scripts/config/webpack.config.js | 51 ++-------------- packages/scripts/utils/config.js | 13 ++-- packages/scripts/utils/index.js | 2 + .../scripts/utils/php-file-paths-plugin.js | 60 +++++++++++++++++++ tools/webpack/blocks.js | 37 +++++++++--- 5 files changed, 103 insertions(+), 60 deletions(-) create mode 100644 packages/scripts/utils/php-file-paths-plugin.js diff --git a/packages/scripts/config/webpack.config.js b/packages/scripts/config/webpack.config.js index 4c60e3859207de..91ef19fc27ed6b 100644 --- a/packages/scripts/config/webpack.config.js +++ b/packages/scripts/config/webpack.config.js @@ -13,7 +13,6 @@ const RtlCssPlugin = require( 'rtlcss-webpack-plugin' ); const TerserPlugin = require( 'terser-webpack-plugin' ); const { realpathSync } = require( 'fs' ); const { sync: glob } = require( 'fast-glob' ); -const { validate } = require( 'schema-utils' ); /** * WordPress dependencies @@ -32,11 +31,11 @@ const { hasPostCSSConfig, getWordPressSrcDirectory, getWebpackEntryPoints, - getPhpFilePaths, getAsBooleanFromENV, getBlockJsonModuleFields, getBlockJsonScriptFields, fromProjectRoot, + PhpFilePathsPlugin, } = require( '../utils' ); const isProduction = process.env.NODE_ENV === 'production'; @@ -50,49 +49,6 @@ const hasExperimentalModulesFlag = getAsBooleanFromENV( 'WP_EXPERIMENTAL_MODULES' ); -const phpFilePathsPluginSchema = { - type: 'object', - properties: { - props: { - type: 'array', - items: { - type: 'string', - }, - }, - }, -}; - -/** - * The plugin recomputes PHP file paths once on each compilation. It is necessary to avoid repeating processing - * when filtering every discovered PHP file in the source folder. This is the most performant way to ensure that - * changes in `block.json` files are picked up in watch mode. - */ -class PhpFilePathsPlugin { - /** - * PHP file paths from `render` and `variations` props found in `block.json` files. - * - * @type {string[]} - */ - static paths; - - constructor( options = {} ) { - validate( phpFilePathsPluginSchema, options, { - name: 'PHP File Paths Plugin', - baseDataPath: 'options', - } ); - - this.options = options; - } - - apply( compiler ) { - const pluginName = this.constructor.name; - - compiler.hooks.thisCompilation.tap( pluginName, () => { - this.constructor.paths = getPhpFilePaths( this.options.props ); - } ); - } -} - const cssLoaders = [ { loader: MiniCSSExtractPlugin.loader, @@ -345,7 +301,10 @@ const scriptConfig = { cleanStaleWebpackAssets: false, } ), - new PhpFilePathsPlugin( { props: [ 'render', 'variations' ] } ), + new PhpFilePathsPlugin( { + context: getWordPressSrcDirectory(), + props: [ 'render', 'variations' ], + } ), new CopyWebpackPlugin( { patterns: [ { diff --git a/packages/scripts/utils/config.js b/packages/scripts/utils/config.js index 7196c0376377d4..dfb44730438c4a 100644 --- a/packages/scripts/utils/config.js +++ b/packages/scripts/utils/config.js @@ -351,22 +351,23 @@ function getWebpackEntryPoints( buildType ) { /** * Returns the list of PHP file paths found in `block.json` files for the given props. * - * @param {string[]} props The props to search for in the `block.json` files. + * @param {string} context The path to search for `block.json` files. + * @param {string[]} props The props to search for in the `block.json` files. * @return {string[]} The list of PHP file paths. */ -function getPhpFilePaths( props ) { +function getPhpFilePaths( context, props ) { // Continue only if the source directory exists. - if ( ! hasProjectFile( getWordPressSrcDirectory() ) ) { + if ( ! hasProjectFile( context ) ) { return []; } // Checks whether any block metadata files can be detected in the defined source directory. const blockMetadataFiles = glob( '**/block.json', { absolute: true, - cwd: fromProjectRoot( getWordPressSrcDirectory() ), + cwd: fromProjectRoot( context ), } ); - const srcDirectory = fromProjectRoot( getWordPressSrcDirectory() + sep ); + const srcDirectory = fromProjectRoot( context + sep ); return blockMetadataFiles.flatMap( ( blockMetadataFile ) => { const blockJson = JSON.parse( readFileSync( blockMetadataFile ) ); @@ -396,7 +397,7 @@ function getPhpFilePaths( props ) { ) }" listed in "${ blockMetadataFile.replace( fromProjectRoot( sep ), '' - ) }". File is located outside of the "${ getWordPressSrcDirectory() }" directory.` + ) }". File is located outside of the "${ context }" directory.` ) ); continue; diff --git a/packages/scripts/utils/index.js b/packages/scripts/utils/index.js index dc4008b16197d6..cb7e592f83d554 100644 --- a/packages/scripts/utils/index.js +++ b/packages/scripts/utils/index.js @@ -29,6 +29,7 @@ const { getBlockJsonModuleFields, getBlockJsonScriptFields, } = require( './block-json' ); +const { PhpFilePathsPlugin } = require( './php-file-paths-plugin' ); module.exports = { fromProjectRoot, @@ -55,5 +56,6 @@ module.exports = { hasPostCSSConfig, hasPrettierConfig, hasProjectFile, + PhpFilePathsPlugin, spawnScript, }; diff --git a/packages/scripts/utils/php-file-paths-plugin.js b/packages/scripts/utils/php-file-paths-plugin.js new file mode 100644 index 00000000000000..6f95dae6505a80 --- /dev/null +++ b/packages/scripts/utils/php-file-paths-plugin.js @@ -0,0 +1,60 @@ +/** + * External dependencies + */ +const { validate } = require( 'schema-utils' ); + +/** + * Internal dependencies + */ +const { getPhpFilePaths } = require( './config' ); + +const phpFilePathsPluginSchema = { + type: 'object', + properties: { + context: { + type: 'string', + }, + props: { + type: 'array', + items: { + type: 'string', + }, + }, + }, +}; + +/** + * The plugin recomputes PHP file paths once on each compilation. It is necessary to avoid repeating processing + * when filtering every discovered PHP file in the source folder. This is the most performant way to ensure that + * changes in `block.json` files are picked up in watch mode. + */ +class PhpFilePathsPlugin { + /** + * PHP file paths from `render` and `variations` props found in `block.json` files. + * + * @type {string[]} + */ + static paths; + + constructor( options = {} ) { + validate( phpFilePathsPluginSchema, options, { + name: 'PHP File Paths Plugin', + baseDataPath: 'options', + } ); + + this.options = options; + } + + apply( compiler ) { + const pluginName = this.constructor.name; + + compiler.hooks.thisCompilation.tap( pluginName, () => { + this.constructor.paths = getPhpFilePaths( + this.options.context, + this.options.props + ); + } ); + } +} + +module.exports = { PhpFilePathsPlugin }; diff --git a/tools/webpack/blocks.js b/tools/webpack/blocks.js index 36329d39c1212b..fa0c6123dbcdba 100644 --- a/tools/webpack/blocks.js +++ b/tools/webpack/blocks.js @@ -4,11 +4,13 @@ const CopyWebpackPlugin = require( 'copy-webpack-plugin' ); const { join, sep } = require( 'path' ); const fastGlob = require( 'fast-glob' ); +const { realpathSync } = require( 'fs' ); /** * WordPress dependencies */ const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' ); +const { PhpFilePathsPlugin } = require( '@wordpress/scripts/utils' ); /** * Internal dependencies @@ -90,6 +92,10 @@ module.exports = [ plugins: [ ...plugins, new DependencyExtractionWebpackPlugin( { injectPolyfill: false } ), + new PhpFilePathsPlugin( { + context: './packages/block-library/src/', + props: [ 'render', 'variations' ], + } ), new CopyWebpackPlugin( { patterns: [].concat( [ @@ -127,17 +133,32 @@ module.exports = [ 'build/widgets/blocks/', } ).flatMap( ( [ from, to ] ) => [ { - from: `${ from }/**/index.php`, + from: `${ from }/**/*.php`, to( { absoluteFilename } ) { - const [ , dirname ] = absoluteFilename.match( - new RegExp( - `([\\w-]+)${ escapeRegExp( - sep - ) }index\\.php$` + const [ , dirname, basename ] = + absoluteFilename.match( + new RegExp( + `([\\w-]+)${ escapeRegExp( + sep + ) }([\\w-]+)\\.php$` + ) + ); + + if ( basename === 'index' ) { + return join( to, `${ dirname }.php` ); + } + return join( to, dirname, `${ basename }.php` ); + }, + filter: ( filepath ) => { + return ( + filepath.endsWith( sep + 'index.php' ) || + PhpFilePathsPlugin.paths.includes( + realpathSync( filepath ).replace( + /\\/g, + '/' + ) ) ); - - return join( to, `${ dirname }.php` ); }, transform: ( content ) => { const prefix = 'gutenberg_'; From 23e8bafcd5eee2446023f5cb03489b3d3826a5e3 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 10 Sep 2024 12:33:15 +0400 Subject: [PATCH 0734/1908] Core Data: Batch remaining actions in resolvers (#65176) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- packages/core-data/src/resolvers.js | 66 ++++++++++++++++------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 20270ef7f6cff5..9229673903623a 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -755,7 +755,7 @@ export const getUserPatternCategories = export const getNavigationFallbackId = () => - async ( { dispatch, select } ) => { + async ( { dispatch, select, registry } ) => { const fallback = await apiFetch( { path: addQueryArgs( '/wp-block-editor/v1/navigation-fallback', { _embed: true, @@ -764,9 +764,13 @@ export const getNavigationFallbackId = const record = fallback?._embedded?.self; - dispatch.receiveNavigationFallbackId( fallback?.id ); + registry.batch( () => { + dispatch.receiveNavigationFallbackId( fallback?.id ); + + if ( ! record ) { + return; + } - if ( record ) { // If the fallback is already in the store, don't invalidate navigation queries. // Otherwise, invalidate the cache for the scenario where there were no Navigation // posts in the state and the fallback created one. @@ -790,7 +794,7 @@ export const getNavigationFallbackId = 'wp_navigation', fallback.id, ] ); - } + } ); }; export const getDefaultTemplateId = @@ -817,7 +821,7 @@ export const getDefaultTemplateId = */ export const getRevisions = ( kind, name, recordKey, query = {} ) => - async ( { dispatch } ) => { + async ( { dispatch, registry } ) => { const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); const entityConfig = configs.find( ( config ) => config.name === name && config.kind === kind @@ -884,32 +888,36 @@ export const getRevisions = } ); } - dispatch.receiveRevisions( - kind, - name, - recordKey, - records, - query, - false, - meta - ); + registry.batch( () => { + dispatch.receiveRevisions( + kind, + name, + recordKey, + records, + query, + false, + meta + ); - // When requesting all fields, the list of results can be used to - // resolve the `getRevision` selector in addition to `getRevisions`. - if ( ! query?._fields && ! query.context ) { - const key = entityConfig.key || DEFAULT_ENTITY_KEY; - const resolutionsArgs = records - .filter( ( record ) => record[ key ] ) - .map( ( record ) => [ - kind, - name, - recordKey, - record[ key ], - ] ); + // When requesting all fields, the list of results can be used to + // resolve the `getRevision` selector in addition to `getRevisions`. + if ( ! query?._fields && ! query.context ) { + const key = entityConfig.key || DEFAULT_ENTITY_KEY; + const resolutionsArgs = records + .filter( ( record ) => record[ key ] ) + .map( ( record ) => [ + kind, + name, + recordKey, + record[ key ], + ] ); - dispatch.startResolutions( 'getRevision', resolutionsArgs ); - dispatch.finishResolutions( 'getRevision', resolutionsArgs ); - } + dispatch.finishResolutions( + 'getRevision', + resolutionsArgs + ); + } + } ); } }; From 8b4ca3437a086bf7dae71c81561f3e90b1dc0e67 Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini <26530524+zaguiini@users.noreply.github.com> Date: Tue, 10 Sep 2024 05:54:03 -0300 Subject: [PATCH 0735/1908] Block Bindings: Prioritize existing placeholder over bindingsPlaceholder (#65154) Co-authored-by: zaguiini <zaguiini@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/block-editor/src/components/rich-text/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 732b8dbf2c089c..ed53270b679f7a 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -334,7 +334,7 @@ export function RichTextWrapper( selectionStart, selectionEnd, onSelectionChange, - placeholder: bindingsPlaceholder || placeholder, + placeholder: placeholder || bindingsPlaceholder, __unstableIsSelected: isSelected, __unstableDisableFormats: disableFormats, preserveWhiteSpace, @@ -406,7 +406,7 @@ export function RichTextWrapper( aria-readonly={ shouldDisableEditing } { ...props } aria-label={ - bindingsPlaceholder || props[ 'aria-label' ] || placeholder + props[ 'aria-label' ] || placeholder || bindingsPlaceholder } { ...autocompleteProps } ref={ useMergeRefs( [ From cdeb12eabf71ecf7c057f7499252b42eddef857c Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 10 Sep 2024 18:45:08 +0900 Subject: [PATCH 0736/1908] Modal: Decrease close button size (#65131) * Modal: Decrease close button size * Remove close button offset * Update story example to show real-life usage * Update header action button size in Freeform block * Add spacer to component itself * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/block-library/src/freeform/modal.js | 3 +-- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/modal/index.tsx | 23 +++++++++++++------ .../src/modal/stories/index.story.tsx | 22 +++++++----------- packages/components/src/modal/style.scss | 5 ---- 5 files changed, 29 insertions(+), 28 deletions(-) diff --git a/packages/block-library/src/freeform/modal.js b/packages/block-library/src/freeform/modal.js index aad79473b172b2..4ed4ef4d3a07ca 100644 --- a/packages/block-library/src/freeform/modal.js +++ b/packages/block-library/src/freeform/modal.js @@ -25,8 +25,7 @@ function ModalAuxiliaryActions( { onClick, isModalFullScreen } ) { return ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + size="small" onClick={ onClick } icon={ fullscreen } isPressed={ isModalFullScreen } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 0293522cf9263e..8c656f4adb48bb 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -10,6 +10,10 @@ - `Composite`: add stable version of the component ([#63569](https://github.com/WordPress/gutenberg/pull/63569)). +### Enhancements + +- `Modal`: Decrease close button size and remove horizontal offset ([#65131](https://github.com/WordPress/gutenberg/pull/65131)). + ### Internal - `Composite`: Remove from private APIs ([#63569](https://github.com/WordPress/gutenberg/pull/63569)). diff --git a/packages/components/src/modal/index.tsx b/packages/components/src/modal/index.tsx index e1f103b98c2735..7d988a0e7240b3 100644 --- a/packages/components/src/modal/index.tsx +++ b/packages/components/src/modal/index.tsx @@ -37,6 +37,7 @@ import Button from '../button'; import StyleProvider from '../style-provider'; import type { ModalProps } from './types'; import { withIgnoreIMEEvents } from '../utils/with-ignore-ime-events'; +import { Spacer } from '../spacer'; // Used to track and dismiss the prior modal when another opens unless nested. type Dismissers = Set< @@ -323,13 +324,21 @@ function UnforwardedModal( </div> { headerActions } { isDismissible && ( - <Button - onClick={ onRequestClose } - icon={ close } - label={ - closeButtonLabel || __( 'Close' ) - } - /> + <> + <Spacer + marginBottom={ 0 } + marginLeft={ 3 } + /> + <Button + size="small" + onClick={ onRequestClose } + icon={ close } + label={ + closeButtonLabel || + __( 'Close' ) + } + /> + </> ) } </div> ) } diff --git a/packages/components/src/modal/stories/index.story.tsx b/packages/components/src/modal/stories/index.story.tsx index 60a53947116fac..f180de0dc06a46 100644 --- a/packages/components/src/modal/stories/index.story.tsx +++ b/packages/components/src/modal/stories/index.story.tsx @@ -7,7 +7,7 @@ import type { StoryFn, Meta } from '@storybook/react'; * WordPress dependencies */ import { useState } from '@wordpress/element'; -import { starEmpty, starFilled } from '@wordpress/icons'; +import { fullscreen } from '@wordpress/icons'; /** * Internal dependencies @@ -103,22 +103,16 @@ WithsizeSmall.args = { }; WithsizeSmall.storyName = 'With size: small'; -const LikeButton = () => { - const [ isLiked, setIsLiked ] = useState( false ); - return ( - <Button - icon={ isLiked ? starFilled : starEmpty } - label="Like" - onClick={ () => setIsLiked( ! isLiked ) } - /> - ); -}; - +/** + * The `headerActions` prop can be used to add auxiliary actions to the header, for example a fullscreen mode toggle. + */ export const WithHeaderActions: StoryFn< typeof Modal > = Template.bind( {} ); WithHeaderActions.args = { ...Default.args, - headerActions: <LikeButton />, - isDismissible: false, + headerActions: ( + <Button icon={ fullscreen } label="Fullscreen mode" size="small" /> + ), + children: <div style={ { height: '200px' } } />, }; WithHeaderActions.parameters = { ...Default.parameters, diff --git a/packages/components/src/modal/style.scss b/packages/components/src/modal/style.scss index 47d5df116d8865..8c7c8416f0190b 100644 --- a/packages/components/src/modal/style.scss +++ b/packages/components/src/modal/style.scss @@ -116,11 +116,6 @@ margin: 0; } - .components-button { - position: relative; - left: $grid-unit-10; - } - .components-modal__content.has-scrolled-content:not(.hide-header) & { border-bottom-color: $gray-300; } From 619296f673da08c05f2578220dd73cc778109188 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 10 Sep 2024 18:55:25 +0900 Subject: [PATCH 0737/1908] Normalize spacing in Layout hook controls (#65132) * Cover block: Normalize spacing in Layout controls * Tweak code comments Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/block-editor/src/hooks/layout.scss | 22 +++++-------------- .../block-editor/src/layouts/constrained.js | 16 ++++++++------ 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/packages/block-editor/src/hooks/layout.scss b/packages/block-editor/src/hooks/layout.scss index 3eedd1f629a633..0ce3bc0577640f 100644 --- a/packages/block-editor/src/hooks/layout.scss +++ b/packages/block-editor/src/hooks/layout.scss @@ -1,23 +1,13 @@ -.block-editor-hooks__layout-controls-units { - display: flex; - flex-direction: column; - gap: $grid-unit-20; -} - -.block-editor-block-inspector .block-editor-hooks__layout-controls-unit-input { - margin-bottom: 0; -} - -.block-editor-hooks__layout-controls-reset { - display: flex; - justify-content: flex-end; - margin-bottom: $grid-unit-30; +.block-editor-hooks__layout-constrained { + .components-base-control { + margin-bottom: 0; // Cancel out margins added by block inspector + } } -.block-editor-hooks__layout-controls-helptext { +.block-editor-hooks__layout-constrained-helptext { color: $gray-700; font-size: $helptext-font-size; - margin-bottom: $grid-unit-20; + margin-bottom: 0; // Cancel out margins added by common.css } .block-editor-hooks__flex-layout-justification-controls, diff --git a/packages/block-editor/src/layouts/constrained.js b/packages/block-editor/src/layouts/constrained.js index 21aca422a315ff..7bf6badf008709 100644 --- a/packages/block-editor/src/layouts/constrained.js +++ b/packages/block-editor/src/layouts/constrained.js @@ -7,6 +7,7 @@ import { __experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper, + __experimentalVStack as VStack, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { @@ -70,12 +71,14 @@ export default { availableUnits: availableUnits || [ '%', 'px', 'em', 'rem', 'vw' ], } ); return ( - <> + <VStack + spacing={ 4 } + className="block-editor-hooks__layout-constrained" + > { allowCustomContentAndWideSize && ( - <div className="block-editor-hooks__layout-controls-units"> + <> <UnitControl __next40pxDefaultSize - className="block-editor-hooks__layout-controls-unit-input" label={ __( 'Content width' ) } labelPosition="top" value={ contentSize || wideSize || '' } @@ -98,7 +101,6 @@ export default { /> <UnitControl __next40pxDefaultSize - className="block-editor-hooks__layout-controls-unit-input" label={ __( 'Wide width' ) } labelPosition="top" value={ wideSize || contentSize || '' } @@ -119,12 +121,12 @@ export default { </InputControlPrefixWrapper> } /> - <p className="block-editor-hooks__layout-controls-helptext"> + <p className="block-editor-hooks__layout-constrained-helptext"> { __( 'Customize the width for all elements that are assigned to the center or wide columns.' ) } </p> - </div> + </> ) } { allowJustification && ( <ToggleGroupControl @@ -148,7 +150,7 @@ export default { ) } </ToggleGroupControl> ) } - </> + </VStack> ); }, toolBarControls: function DefaultLayoutToolbarControls( { From ecf010306a33b2bcdd5f4c2fb29edf36f9cec71a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= <grzegorz@gziolo.pl> Date: Tue, 10 Sep 2024 12:26:36 +0200 Subject: [PATCH 0738/1908] =?UTF-8?q?Revert=20"Block=20Bindings:=20Priorit?= =?UTF-8?q?ize=20existing=20placeholder=20over=20bindingsPlacehol=E2=80=A6?= =?UTF-8?q?"=20(#65190)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 8b4ca3437a086bf7dae71c81561f3e90b1dc0e67. --- packages/block-editor/src/components/rich-text/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index ed53270b679f7a..732b8dbf2c089c 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -334,7 +334,7 @@ export function RichTextWrapper( selectionStart, selectionEnd, onSelectionChange, - placeholder: placeholder || bindingsPlaceholder, + placeholder: bindingsPlaceholder || placeholder, __unstableIsSelected: isSelected, __unstableDisableFormats: disableFormats, preserveWhiteSpace, @@ -406,7 +406,7 @@ export function RichTextWrapper( aria-readonly={ shouldDisableEditing } { ...props } aria-label={ - props[ 'aria-label' ] || placeholder || bindingsPlaceholder + bindingsPlaceholder || props[ 'aria-label' ] || placeholder } { ...autocompleteProps } ref={ useMergeRefs( [ From b758ccabdfd808fe9579a1543e6cff2edfaebf3e Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 10 Sep 2024 14:36:11 +0400 Subject: [PATCH 0739/1908] Create Block: Update the minimum required PHP version to 7.2 (#65166) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- .../plugin-templates/$slug.php.mustache | 2 +- .../plugin-templates/$slug.php.mustache | 2 +- packages/create-block/lib/templates/es5/$slug.php.mustache | 2 +- packages/create-block/lib/templates/plugin/$slug.php.mustache | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/create-block-interactive-template/plugin-templates/$slug.php.mustache b/packages/create-block-interactive-template/plugin-templates/$slug.php.mustache index 56f660ce2b1257..48469aa7d0d931 100644 --- a/packages/create-block-interactive-template/plugin-templates/$slug.php.mustache +++ b/packages/create-block-interactive-template/plugin-templates/$slug.php.mustache @@ -9,7 +9,7 @@ {{/description}} * Version: {{version}} * Requires at least: 6.6 - * Requires PHP: 7.0 + * Requires PHP: 7.2 {{#author}} * Author: {{author}} {{/author}} diff --git a/packages/create-block-tutorial-template/plugin-templates/$slug.php.mustache b/packages/create-block-tutorial-template/plugin-templates/$slug.php.mustache index bcc7f7537d95a8..7ce4be3f7cc739 100644 --- a/packages/create-block-tutorial-template/plugin-templates/$slug.php.mustache +++ b/packages/create-block-tutorial-template/plugin-templates/$slug.php.mustache @@ -9,7 +9,7 @@ {{/description}} * Version: {{version}} * Requires at least: 6.6 - * Requires PHP: 7.0 + * Requires PHP: 7.2 {{#author}} * Author: {{author}} {{/author}} diff --git a/packages/create-block/lib/templates/es5/$slug.php.mustache b/packages/create-block/lib/templates/es5/$slug.php.mustache index a67c3ad55d3fec..825fd1bfd8b5aa 100644 --- a/packages/create-block/lib/templates/es5/$slug.php.mustache +++ b/packages/create-block/lib/templates/es5/$slug.php.mustache @@ -8,7 +8,7 @@ * Description: {{description}} {{/description}} * Requires at least: 6.6 - * Requires PHP: 7.0 + * Requires PHP: 7.2 * Version: {{version}} {{#author}} * Author: {{author}} diff --git a/packages/create-block/lib/templates/plugin/$slug.php.mustache b/packages/create-block/lib/templates/plugin/$slug.php.mustache index 4524477ba73df2..75666af3a850b2 100644 --- a/packages/create-block/lib/templates/plugin/$slug.php.mustache +++ b/packages/create-block/lib/templates/plugin/$slug.php.mustache @@ -8,7 +8,7 @@ * Description: {{description}} {{/description}} * Requires at least: 6.6 - * Requires PHP: 7.0 + * Requires PHP: 7.2 * Version: {{version}} {{#author}} * Author: {{author}} From 57e0b9cb658669e2bcc8d4cb2daa537e7d678d4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Gomes?= <mail@sgomes.com> Date: Tue, 10 Sep 2024 12:08:48 +0100 Subject: [PATCH 0740/1908] Post publish upload media dialog: handle more block types (#65122) * Post publish upload media dialog: handle more block types * Deduplicate uploads and media filenames * Correctly create File object for fetched media * media-util.js: review suggestions * Add more JSDoc * Fix wrong types * Allow all uploads to finish, even if some fail Co-authored-by: sgomes <sergiomdgomes@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../post-publish-panel/maybe-upload-media.js | 197 +++++++++++++----- .../post-publish-panel/media-util.js | 87 ++++++++ .../post-publish-panel/test/media-util.js | 118 +++++++++++ 3 files changed, 354 insertions(+), 48 deletions(-) create mode 100644 packages/editor/src/components/post-publish-panel/media-util.js create mode 100644 packages/editor/src/components/post-publish-panel/test/media-util.js diff --git a/packages/editor/src/components/post-publish-panel/maybe-upload-media.js b/packages/editor/src/components/post-publish-panel/maybe-upload-media.js index b090e25cd4dbff..6b252b9f2b399e 100644 --- a/packages/editor/src/components/post-publish-panel/maybe-upload-media.js +++ b/packages/editor/src/components/post-publish-panel/maybe-upload-media.js @@ -14,6 +14,11 @@ import { store as blockEditorStore } from '@wordpress/block-editor'; import { useState } from '@wordpress/element'; import { isBlobURL } from '@wordpress/blob'; +/** + * Internal dependencies + */ +import { fetchMedia } from './media-util'; + function flattenBlocks( blocks ) { const result = []; @@ -25,7 +30,53 @@ function flattenBlocks( blocks ) { return result; } -function Image( block ) { +/** + * Determine whether a block has external media. + * + * Different blocks use different attribute names (and potentially + * different logic as well) in determining whether the media is + * present, and whether it's external. + * + * @param {{name: string, attributes: Object}} block The block. + * @return {boolean?} Whether the block has external media + */ +function hasExternalMedia( block ) { + if ( block.name === 'core/image' || block.name === 'core/cover' ) { + return block.attributes.url && ! block.attributes.id; + } + + if ( block.name === 'core/media-text' ) { + return block.attributes.mediaUrl && ! block.attributes.mediaId; + } + + return undefined; +} + +/** + * Retrieve media info from a block. + * + * Different blocks use different attribute names, so we need this + * function to normalize things into a consistent naming scheme. + * + * @param {{name: string, attributes: Object}} block The block. + * @return {{url: ?string, alt: ?string, id: ?number}} The media info for the block. + */ +function getMediaInfo( block ) { + if ( block.name === 'core/image' || block.name === 'core/cover' ) { + const { url, alt, id } = block.attributes; + return { url, alt, id }; + } + + if ( block.name === 'core/media-text' ) { + const { mediaUrl: url, mediaAlt: alt, mediaId: id } = block.attributes; + return { url, alt, id }; + } + + return {}; +} + +// Image component to represent a single image in the upload dialog. +function Image( { clientId, alt, url } ) { const { selectBlock } = useDispatch( blockEditorStore ); return ( <motion.img @@ -33,17 +84,17 @@ function Image( block ) { role="button" aria-label={ __( 'Select image block.' ) } onClick={ () => { - selectBlock( block.clientId ); + selectBlock( clientId ); } } onKeyDown={ ( event ) => { if ( event.key === 'Enter' || event.key === ' ' ) { - selectBlock( block.clientId ); + selectBlock( clientId ); event.preventDefault(); } } } - key={ block.clientId } - alt={ block.attributes.alt } - src={ block.attributes.url } + key={ clientId } + alt={ alt } + src={ url } animate={ { opacity: 1 } } exit={ { opacity: 0, scale: 0 } } style={ { @@ -58,7 +109,7 @@ function Image( block ) { ); } -export default function PostFormatPanel() { +export default function MaybeUploadMediaPanel() { const [ isUploading, setIsUploading ] = useState( false ); const [ isAnimating, setIsAnimating ] = useState( false ); const [ hadUploadError, setHadUploadError ] = useState( false ); @@ -69,15 +120,14 @@ export default function PostFormatPanel() { } ), [] ); - const externalImages = flattenBlocks( editorBlocks ).filter( - ( block ) => - block.name === 'core/image' && - block.attributes.url && - ! block.attributes.id + + // Get a list of blocks with external media. + const blocksWithExternalMedia = flattenBlocks( editorBlocks ).filter( + ( block ) => hasExternalMedia( block ) ); const { updateBlockAttributes } = useDispatch( blockEditorStore ); - if ( ! mediaUpload || ! externalImages.length ) { + if ( ! mediaUpload || ! blocksWithExternalMedia.length ) { return null; } @@ -88,43 +138,86 @@ export default function PostFormatPanel() { </span>, ]; + /** + * Update an individual block to point to newly-added library media. + * + * Different blocks use different attribute names, so we need this + * function to ensure we modify the correct attributes for each type. + * + * @param {{name: string, attributes: Object}} block The block. + * @param {{id: number, url: string}} media Media library file info. + */ + function updateBlockWithUploadedMedia( block, media ) { + if ( block.name === 'core/image' || block.name === 'core/cover' ) { + updateBlockAttributes( block.clientId, { + id: media.id, + url: media.url, + } ); + } + + if ( block.name === 'core/media-text' ) { + updateBlockAttributes( block.clientId, { + mediaId: media.id, + mediaUrl: media.url, + } ); + } + } + + // Handle fetching and uploading all external media in the post. function uploadImages() { setIsUploading( true ); setHadUploadError( false ); - Promise.all( - externalImages.map( ( image ) => - window - .fetch( - image.attributes.url.includes( '?' ) - ? image.attributes.url - : image.attributes.url + '?' - ) - .then( ( response ) => response.blob() ) - .then( ( blob ) => - new Promise( ( resolve, reject ) => { - mediaUpload( { - filesList: [ blob ], - onFileChange: ( [ media ] ) => { - if ( isBlobURL( media.url ) ) { - return; - } - - updateBlockAttributes( image.clientId, { - id: media.id, - url: media.url, - } ); - resolve(); - }, - onError() { - reject(); - }, - } ); - } ).then( () => setIsAnimating( true ) ) - ) - .catch( () => { - setHadUploadError( true ); - } ) + + // Multiple blocks can be using the same URL, so we + // should ensure we only fetch and upload each of them once. + const mediaUrls = new Set( + blocksWithExternalMedia.map( ( block ) => { + const { url } = getMediaInfo( block ); + return url; + } ) + ); + + // Create an upload promise for each URL, that we can wait for in all + // blocks that make use of that media. + const uploadPromises = Object.fromEntries( + Object.entries( fetchMedia( [ ...mediaUrls ] ) ).map( + ( [ url, filePromise ] ) => { + const uploadPromise = filePromise.then( + ( blob ) => + new Promise( ( resolve, reject ) => { + mediaUpload( { + filesList: [ blob ], + onFileChange: ( [ media ] ) => { + if ( isBlobURL( media.url ) ) { + return; + } + + resolve( media ); + }, + onError() { + reject(); + }, + } ); + } ) + ); + + return [ url, uploadPromise ]; + } ) + ); + + // Wait for all blocks to be updated with library media. + Promise.allSettled( + blocksWithExternalMedia.map( ( block ) => { + const { url } = getMediaInfo( block ); + + return uploadPromises[ url ] + .then( ( media ) => + updateBlockWithUploadedMedia( block, media ) + ) + .then( () => setIsAnimating( true ) ) + .catch( () => setHadUploadError( true ) ); + } ) ).finally( () => { setIsUploading( false ); } ); @@ -147,8 +240,16 @@ export default function PostFormatPanel() { <AnimatePresence onExitComplete={ () => setIsAnimating( false ) } > - { externalImages.map( ( image ) => { - return <Image key={ image.clientId } { ...image } />; + { blocksWithExternalMedia.map( ( block ) => { + const { url, alt } = getMediaInfo( block ); + return ( + <Image + key={ block.clientId } + clientId={ block.clientId } + url={ url } + alt={ alt } + /> + ); } ) } </AnimatePresence> { isUploading || isAnimating ? ( diff --git a/packages/editor/src/components/post-publish-panel/media-util.js b/packages/editor/src/components/post-publish-panel/media-util.js new file mode 100644 index 00000000000000..995802b0eebb44 --- /dev/null +++ b/packages/editor/src/components/post-publish-panel/media-util.js @@ -0,0 +1,87 @@ +/** + * External dependencies + */ +import { v4 as uuid } from 'uuid'; + +/** + * WordPress dependencies + */ +import { getFilename } from '@wordpress/url'; + +/** + * Generate a list of unique basenames given a list of URLs. + * + * We want all basenames to be unique, since sometimes the extension + * doesn't reflect the mime type, and may end up getting changed by + * the server, on upload. + * + * @param {string[]} urls The list of URLs + * @return {Record< string, string >} A URL => basename record. + */ +export function generateUniqueBasenames( urls ) { + const basenames = new Set(); + + return Object.fromEntries( + urls.map( ( url ) => { + // We prefer to match the remote filename, if possible. + const filename = getFilename( url ); + let basename = ''; + + if ( filename ) { + const parts = filename.split( '.' ); + if ( parts.length > 1 ) { + // Assume the last part is the extension. + parts.pop(); + } + basename = parts.join( '.' ); + } + + if ( ! basename ) { + // It looks like we don't have a basename, so let's use a UUID. + basename = uuid(); + } + + if ( basenames.has( basename ) ) { + // Append a UUID to deduplicate the basename. + // The server will try to deduplicate on its own if we don't do this, + // but it may run into a race condition + // (see https://github.com/WordPress/gutenberg/issues/64899). + // Deduplicating the filenames before uploading is safer. + basename = `${ basename }-${ uuid() }`; + } + + basenames.add( basename ); + + return [ url, basename ]; + } ) + ); +} + +/** + * Fetch a list of URLs, turning those into promises for files with + * unique filenames. + * + * @param {string[]} urls The list of URLs + * @return {Record< string, Promise< File > >} A URL => File promise record. + */ +export function fetchMedia( urls ) { + return Object.fromEntries( + Object.entries( generateUniqueBasenames( urls ) ).map( + ( [ url, basename ] ) => { + const filePromise = window + .fetch( url.includes( '?' ) ? url : url + '?' ) + .then( ( response ) => response.blob() ) + .then( ( blob ) => { + // The server will reject the upload if it doesn't have an extension, + // even though it'll rewrite the file name to match the mime type. + // Here we provide it with a safe extension to get it past that check. + return new File( [ blob ], `${ basename }.png`, { + type: blob.type, + } ); + } ); + + return [ url, filePromise ]; + } + ) + ); +} diff --git a/packages/editor/src/components/post-publish-panel/test/media-util.js b/packages/editor/src/components/post-publish-panel/test/media-util.js new file mode 100644 index 00000000000000..b91583cc3f17b3 --- /dev/null +++ b/packages/editor/src/components/post-publish-panel/test/media-util.js @@ -0,0 +1,118 @@ +/** + * Internal dependencies + */ +import { generateUniqueBasenames } from '../media-util'; + +describe( 'generateUniqueBasenames', () => { + it( 'should prefer the original basenames', () => { + const urls = [ + 'https://example.com/images/image1.jpg', + 'https://example.com/images/image2.jpg', + 'https://example.com/images/image3.jpg', + 'https://example.com/images/image4.jpg', + ]; + + expect( generateUniqueBasenames( urls ) ).toEqual( { + 'https://example.com/images/image1.jpg': 'image1', + 'https://example.com/images/image2.jpg': 'image2', + 'https://example.com/images/image3.jpg': 'image3', + 'https://example.com/images/image4.jpg': 'image4', + } ); + } ); + + it( 'should handle filenames with no extensions', () => { + const urls = [ + 'https://example.com/images/image1', + 'https://example.com/images/image2', + 'https://example.com/images/image3', + 'https://example.com/images/image4', + ]; + + expect( generateUniqueBasenames( urls ) ).toEqual( { + 'https://example.com/images/image1': 'image1', + 'https://example.com/images/image2': 'image2', + 'https://example.com/images/image3': 'image3', + 'https://example.com/images/image4': 'image4', + } ); + } ); + + it( 'should handle query parameters correctly', () => { + const urls = [ + 'https://example.com/images/image1.jpg?a=notafile.npg', + 'https://example.com/images/image2.jpg?a=notafile.npg', + 'https://example.com/images/image3.jpg?a=notafile.npg', + 'https://example.com/images/image4.jpg?a=notafile.npg', + ]; + + expect( generateUniqueBasenames( urls ) ).toEqual( { + 'https://example.com/images/image1.jpg?a=notafile.npg': 'image1', + 'https://example.com/images/image2.jpg?a=notafile.npg': 'image2', + 'https://example.com/images/image3.jpg?a=notafile.npg': 'image3', + 'https://example.com/images/image4.jpg?a=notafile.npg': 'image4', + } ); + } ); + + it( 'should deduplicate identical filenames', () => { + const urls = [ + 'https://example.com/image1/image.jpg', + 'https://example.com/image2/image.jpg', + 'https://example.com/image3/image.jpg', + 'https://example.com/image4/image.jpg', + ]; + + const results = generateUniqueBasenames( urls ); + const resultLength = Object.entries( results ).length; + expect( resultLength ).toBe( urls.length ); + + const basenames = new Set( Object.values( results ) ); + expect( basenames.size ).toBe( resultLength ); + } ); + + it( 'should deduplicate identical basenames', () => { + const urls = [ + 'https://example.com/images/image.jpg', + 'https://example.com/images/image.png', + 'https://example.com/images/image.webp', + 'https://example.com/images/image.avif', + ]; + + const results = generateUniqueBasenames( urls ); + const resultLength = Object.entries( results ).length; + expect( resultLength ).toBe( urls.length ); + + const basenames = new Set( Object.values( results ) ); + expect( basenames.size ).toBe( resultLength ); + } ); + + it( 'should deduplicate filenames without extensions', () => { + const urls = [ + 'https://example.com/image1/image', + 'https://example.com/image2/image', + 'https://example.com/image3/image', + 'https://example.com/image4/image', + ]; + + const results = generateUniqueBasenames( urls ); + const resultLength = Object.entries( results ).length; + expect( resultLength ).toBe( urls.length ); + + const basenames = new Set( Object.values( results ) ); + expect( basenames.size ).toBe( resultLength ); + } ); + + it( 'should deduplicate paths with no filename', () => { + const urls = [ + 'https://example.com/image1/dir/', + 'https://example.com/image2/dir/', + 'https://example.com/image3/dir/', + 'https://example.com/image4/dir/', + ]; + + const results = generateUniqueBasenames( urls ); + const resultLength = Object.entries( results ).length; + expect( resultLength ).toBe( urls.length ); + + const basenames = new Set( Object.values( results ) ); + expect( basenames.size ).toBe( resultLength ); + } ); +} ); From a925dcd9baeb6602633ade2f17eef2d2ba12b79e Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 10 Sep 2024 15:34:01 +0400 Subject: [PATCH 0741/1908] Compose: Correctly call timeout cleanup (#65184) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/hooks/use-focus-on-mount/index.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/compose/src/hooks/use-focus-on-mount/index.js b/packages/compose/src/hooks/use-focus-on-mount/index.js index 77bee27772d2d0..bb02eb78e5689a 100644 --- a/packages/compose/src/hooks/use-focus-on-mount/index.js +++ b/packages/compose/src/hooks/use-focus-on-mount/index.js @@ -64,19 +64,17 @@ export default function useFocusOnMount( focusOnMount = 'firstElement' ) { return; } - if ( focusOnMountRef.current === 'firstElement' ) { - timerIdRef.current = setTimeout( () => { - const firstTabbable = focus.tabbable.find( node )[ 0 ]; - - if ( firstTabbable ) { - setFocus( firstTabbable ); - } - }, 0 ); - + if ( focusOnMountRef.current !== 'firstElement' ) { + setFocus( node ); return; } - setFocus( node ); + timerIdRef.current = setTimeout( () => { + const firstTabbable = focus.tabbable.find( node )[ 0 ]; + if ( firstTabbable ) { + setFocus( firstTabbable ); + } + }, 0 ); return () => { if ( timerIdRef.current ) { From ff0c475764fc048782f5698127212af5279ddc62 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Tue, 10 Sep 2024 18:02:44 +0530 Subject: [PATCH 0742/1908] Fix: Button: Replace remaining 40px default size violation [Block library 4] (#65143) * Fix query placeholder button size to use 40px default size * Fix template part placeholder to use default 40px button size * Fix video block poster image to use 40px default button size * Fix video poster image remove button to use 40px default size * Fix video track list buttons to use 40px default size * Fix enhanced pagination modal to use 40px default button size Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../src/query/edit/enhanced-pagination-modal.js | 3 +-- .../block-library/src/query/edit/query-placeholder.js | 6 ++---- .../block-library/src/template-part/edit/placeholder.js | 6 ++---- packages/block-library/src/video/edit.js | 6 ++---- packages/block-library/src/video/tracks-editor.js | 9 +++------ 5 files changed, 10 insertions(+), 20 deletions(-) diff --git a/packages/block-library/src/query/edit/enhanced-pagination-modal.js b/packages/block-library/src/query/edit/enhanced-pagination-modal.js index 38167f7259380c..332cc337bb0f67 100644 --- a/packages/block-library/src/query/edit/enhanced-pagination-modal.js +++ b/packages/block-library/src/query/edit/enhanced-pagination-modal.js @@ -76,8 +76,7 @@ export default function EnhancedPaginationModal( { <VStack alignment="right" spacing={ 5 }> <span id={ modalDescriptionId }>{ notice }</span> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" onClick={ closeModal } > diff --git a/packages/block-library/src/query/edit/query-placeholder.js b/packages/block-library/src/query/edit/query-placeholder.js index 098c29f0ec512b..631eb64de07157 100644 --- a/packages/block-library/src/query/edit/query-placeholder.js +++ b/packages/block-library/src/query/edit/query-placeholder.js @@ -79,8 +79,7 @@ export default function QueryPlaceholder( { > { !! hasPatterns && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" onClick={ openPatternSelectionModal } > @@ -89,8 +88,7 @@ export default function QueryPlaceholder( { ) } <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="secondary" onClick={ () => { setIsStartingBlank( true ); diff --git a/packages/block-library/src/template-part/edit/placeholder.js b/packages/block-library/src/template-part/edit/placeholder.js index d54401c2327fbb..0b8a980b8b7e3a 100644 --- a/packages/block-library/src/template-part/edit/placeholder.js +++ b/packages/block-library/src/template-part/edit/placeholder.js @@ -75,8 +75,7 @@ export default function TemplatePartPlaceholder( { { ! isResolving && !! ( templateParts.length || blockPatterns.length ) && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" onClick={ onOpenSelectionModal } > @@ -86,8 +85,7 @@ export default function TemplatePartPlaceholder( { { ! isResolving && isBlockBasedTheme && canCreateTemplatePart && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="secondary" onClick={ () => { setShowTitleModal( true ); diff --git a/packages/block-library/src/video/edit.js b/packages/block-library/src/video/edit.js index d72dd5463cde33..ba6b4c869aefcb 100644 --- a/packages/block-library/src/video/edit.js +++ b/packages/block-library/src/video/edit.js @@ -232,8 +232,7 @@ function VideoEdit( { } render={ ( { open } ) => ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" onClick={ open } ref={ posterImageButton } @@ -262,8 +261,7 @@ function VideoEdit( { </p> { !! poster && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize onClick={ onRemovePoster } variant="tertiary" > diff --git a/packages/block-library/src/video/tracks-editor.js b/packages/block-library/src/video/tracks-editor.js index 079ffd9fc46f82..d01e365985bc96 100644 --- a/packages/block-library/src/video/tracks-editor.js +++ b/packages/block-library/src/video/tracks-editor.js @@ -58,8 +58,7 @@ function TrackList( { tracks, onEditPress } ) { > <span>{ track.label } </span> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" onClick={ () => onEditPress( index ) } aria-label={ sprintf( @@ -147,8 +146,7 @@ function SingleTrackEditor( { track, onChange, onClose, onRemove } ) { /> <HStack className="block-library-video-tracks-editor__single-track-editor-buttons-container"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="secondary" onClick={ () => { const changes = {}; @@ -177,8 +175,7 @@ function SingleTrackEditor( { track, onChange, onClose, onRemove } ) { { __( 'Close' ) } </Button> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize isDestructive variant="link" onClick={ onRemove } From bf6427261b0bf65dd7fb355be77ba9043d0e1fe1 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:00:17 +0200 Subject: [PATCH 0743/1908] Fix unintentional block toolbar shadow. (#65182) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../block-editor/src/components/block-toolbar/style.scss | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index 98538d5d1d053d..40d748dd0a1568 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -70,10 +70,13 @@ // Raise the specificity. &.components-accessible-toolbar { border: none; - box-shadow: 0 $border-width 0 0 rgba($color: #000, $alpha: 0.133); // 0.133 = $gray-200 but with alpha. border-radius: 0; } + &.is-unstyled { + box-shadow: 0 $border-width 0 0 rgba($color: #000, $alpha: 0.133); // 0.133 = $gray-200 but with alpha. + } + .block-editor-block-toolbar { overflow: auto; overflow-y: hidden; From 28035372db467b3a095a2b3f8402f710a033cd29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Juh=C3=A9=20Lluveras?= <contact@albertjuhe.com> Date: Tue, 10 Sep 2024 16:05:38 +0200 Subject: [PATCH 0744/1908] Fix some docblock types related to the Template Registration API (#65187) * Fix some docblock types related to the Template Registration API * Add backport-changelog entry * Revert "Add backport-changelog entry" This reverts commit 71ea479d9adb7794fec67c324643265d684c89b8. * Fix wrong docblock comment * Update lib/compat/wordpress-6.7/block-templates.php Co-authored-by: Nik Tsekouras <ntsekouras@outlook.com> --------- Co-authored-by: Nik Tsekouras <ntsekouras@outlook.com> --- lib/compat/wordpress-6.7/block-templates.php | 4 ++-- .../wordpress-6.7/class-wp-block-templates-registry.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/compat/wordpress-6.7/block-templates.php b/lib/compat/wordpress-6.7/block-templates.php index e270ab226c1d9f..d1f2859070b8b4 100644 --- a/lib/compat/wordpress-6.7/block-templates.php +++ b/lib/compat/wordpress-6.7/block-templates.php @@ -10,7 +10,6 @@ * Register a template. * * @param string $template_name Template name in the form of `plugin_uri//template_name`. - * @param array|string $args Object type or array of object types with which the taxonomy should be associated. * @param array|string $args { * @type string $title Optional. Title of the template as it will be shown in the Site Editor * and other UI elements. @@ -33,7 +32,8 @@ function wp_register_block_template( $template_name, $args = array() ) { * Unregister a template. * * @param string $template_name Template name in the form of `plugin_uri//template_name`. - * @return true|WP_Error True on success, WP_Error on failure or if the template doesn't exist. + * @return WP_Block_Template|WP_Error The unregistered template object on success, WP_Error object on failure or if + * the template doesn't exist. */ function wp_unregister_block_template( $template_name ) { return WP_Block_Templates_Registry::get_instance()->unregister( $template_name ); diff --git a/lib/compat/wordpress-6.7/class-wp-block-templates-registry.php b/lib/compat/wordpress-6.7/class-wp-block-templates-registry.php index db53f735e13b3d..92673c0bf50f90 100644 --- a/lib/compat/wordpress-6.7/class-wp-block-templates-registry.php +++ b/lib/compat/wordpress-6.7/class-wp-block-templates-registry.php @@ -36,7 +36,7 @@ final class WP_Block_Templates_Registry { * * @param string $template_name Template name including namespace. * @param array $args Optional. Array of template arguments. - * @return WP_Block_Template|WP_Error The registered template on success, or false on failure. + * @return WP_Block_Template|WP_Error The registered template on success, or WP_Error on failure. */ public function register( $template_name, $args = array() ) { @@ -100,7 +100,7 @@ public function register( $template_name, $args = array() ) { * * @since 6.7.0 * - * @return WP_Block_Template[]|false Associative array of `$template_name => $template` pairs. + * @return WP_Block_Template[] Associative array of `$template_name => $template` pairs. */ public function get_all_registered() { return $this->registered_templates; @@ -112,7 +112,7 @@ public function get_all_registered() { * @since 6.7.0 * * @param string $template_name Template name including namespace. - * @return WP_Block_Template|null|false The registered template, or null if it is not registered. + * @return WP_Block_Template|null The registered template, or null if it is not registered. */ public function get_registered( $template_name ) { if ( ! $this->is_registered( $template_name ) ) { @@ -216,7 +216,7 @@ public function is_registered( $template_name ) { * @since 6.7.0 * * @param string $template_name Template name including namespace. - * @return WP_Block_Template|false The unregistered template on success, or false on failure. + * @return WP_Block_Template|WP_Error The unregistered template on success, or WP_Error on failure. */ public function unregister( $template_name ) { if ( ! $this->is_registered( $template_name ) ) { From 56c996f89d4cceb47e2211de609a912ad977fa67 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Tue, 10 Sep 2024 16:07:23 +0200 Subject: [PATCH 0745/1908] Inserter: fix loading indicator for reusable blocks (#64839) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: sathyapulse <sathyapulse@git.wordpress.org> --- .../block-editor/src/store/private-selectors.js | 8 +++++--- .../provider/use-block-editor-settings.js | 17 +++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 7e323cee6581ae..b72ebd18183377 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -422,9 +422,11 @@ const EMPTY_ARRAY = []; export const getReusableBlocks = createRegistrySelector( ( select ) => ( state ) => { const reusableBlocksSelect = state.settings[ reusableBlocksSelectKey ]; - return reusableBlocksSelect - ? reusableBlocksSelect( select ) - : state.settings.__experimentalReusableBlocks ?? EMPTY_ARRAY; + return ( + ( reusableBlocksSelect + ? reusableBlocksSelect( select ) + : state.settings.__experimentalReusableBlocks ) ?? EMPTY_ARRAY + ); } ); diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 868ff08b3d0709..12a67e44262b21 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -26,15 +26,20 @@ import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; import { useGlobalStylesContext } from '../global-styles-provider'; -const EMPTY_BLOCKS_LIST = []; const EMPTY_OBJECT = {}; function __experimentalReusableBlocksSelect( select ) { - return ( - select( coreStore ).getEntityRecords( 'postType', 'wp_block', { - per_page: -1, - } ) ?? EMPTY_BLOCKS_LIST - ); + const { getEntityRecords, hasFinishedResolution } = select( coreStore ); + const reusableBlocks = getEntityRecords( 'postType', 'wp_block', { + per_page: -1, + } ); + return hasFinishedResolution( 'getEntityRecords', [ + 'postType', + 'wp_block', + { per_page: -1 }, + ] ) + ? reusableBlocks + : undefined; } const BLOCK_EDITOR_SETTINGS = [ From 1c44c4102acfe464f1523a12cf2207660b5868ee Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 10 Sep 2024 23:09:14 +0900 Subject: [PATCH 0746/1908] Pattern Inserter: Fix pattern list overflow (#65192) * Pattern Inserter: Fix pattern list overflow * Remove VStack component Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- .../pattern-category-previews.js | 60 +++++++++---------- .../src/components/inserter/style.scss | 2 +- 2 files changed, 28 insertions(+), 34 deletions(-) diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js index 913be6a5129736..61716f616dafa9 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js @@ -170,39 +170,33 @@ export function PatternCategoryPreviews( { </Text> ) } </VStack> - <VStack spacing={ 4 }> - { currentCategoryPatterns.length > 0 && ( - <> - { isZoomOutMode && ( - <Text - size="12" - as="p" - className="block-editor-inserter__help-text" - > - { __( - 'Drag and drop patterns into the canvas.' - ) } - </Text> - ) } - <BlockPatternsList - ref={ scrollContainerRef } - shownPatterns={ - pagingProps.categoryPatternsAsyncList - } - blockPatterns={ pagingProps.categoryPatterns } - onClickPattern={ onClickPattern } - onHover={ onHover } - label={ category.label } - orientation="vertical" - category={ category.name } - isDraggable - showTitlesAsTooltip={ showTitlesAsTooltip } - patternFilter={ patternSourceFilter } - pagingProps={ pagingProps } - /> - </> - ) } - </VStack> + { currentCategoryPatterns.length > 0 && ( + <> + { isZoomOutMode && ( + <Text + size="12" + as="p" + className="block-editor-inserter__help-text" + > + { __( 'Drag and drop patterns into the canvas.' ) } + </Text> + ) } + <BlockPatternsList + ref={ scrollContainerRef } + shownPatterns={ pagingProps.categoryPatternsAsyncList } + blockPatterns={ pagingProps.categoryPatterns } + onClickPattern={ onClickPattern } + onHover={ onHover } + label={ category.label } + orientation="vertical" + category={ category.name } + isDraggable + showTitlesAsTooltip={ showTitlesAsTooltip } + patternFilter={ patternSourceFilter } + pagingProps={ pagingProps } + /> + </> + ) } </> ); } diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index 18389dc7e923c5..289acecb5c1c33 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -711,5 +711,5 @@ $block-inserter-tabs-height: 44px; } .block-editor-tabbed-sidebar__tabpanel .block-editor-inserter__help-text { - padding: 0 $grid-unit-30; + padding: 0 $grid-unit-30 $grid-unit-20; } From 1cc30c5cac8c4ba33e0b61c4de20ed618a4166b9 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 10 Sep 2024 18:21:42 +0400 Subject: [PATCH 0747/1908] Editor: Optimize global styles permission check (#65177) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../components/global-styles-provider/index.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js index 8426593d8f5f51..8268997d1f1def 100644 --- a/packages/editor/src/components/global-styles-provider/index.js +++ b/packages/editor/src/components/global-styles-provider/index.js @@ -146,13 +146,17 @@ function useGlobalStylesUserConfig() { function useGlobalStylesBaseConfig() { const baseConfig = useSelect( ( select ) => { - const { __experimentalGetCurrentThemeBaseGlobalStyles, canUser } = - select( coreStore ); - - return ( - canUser( 'read', { kind: 'root', name: 'theme' } ) && - __experimentalGetCurrentThemeBaseGlobalStyles() - ); + const { + __experimentalGetCurrentThemeBaseGlobalStyles, + getCurrentTheme, + canUser, + } = select( coreStore ); + const currentTheme = getCurrentTheme(); + + return currentTheme && + canUser( 'read', 'global-styles/themes', currentTheme.stylesheet ) + ? __experimentalGetCurrentThemeBaseGlobalStyles() + : undefined; }, [] ); return [ !! baseConfig, baseConfig ]; From 3922c1fdea553d990659b39fdd3d64faba213dce Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Tue, 10 Sep 2024 09:55:42 -0500 Subject: [PATCH 0748/1908] Revert "Block Insertion: Clear the insertion point when selecting a different block or clearing block selection (#64048)" (#65208) This reverts commit c73aa361c4bd82d8b3ee004e5195a22158cad1bf. --- .../block-editor/src/components/inserter/quick-inserter.js | 5 +---- packages/block-editor/src/store/reducer.js | 2 -- packages/editor/src/components/inserter-sidebar/index.js | 7 ++----- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/block-editor/src/components/inserter/quick-inserter.js b/packages/block-editor/src/components/inserter/quick-inserter.js index 0852c562828a4b..e28ae1f3896c45 100644 --- a/packages/block-editor/src/components/inserter/quick-inserter.js +++ b/packages/block-editor/src/components/inserter/quick-inserter.js @@ -9,7 +9,7 @@ import clsx from 'clsx'; import { useState, useEffect } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { Button, SearchControl } from '@wordpress/components'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -82,8 +82,6 @@ export default function QuickInserter( { } }, [ setInserterIsOpened ] ); - const { showInsertionPoint } = useDispatch( blockEditorStore ); - // When clicking Browse All select the appropriate block so as // the insertion point can work as expected. const onBrowseAll = () => { @@ -93,7 +91,6 @@ export default function QuickInserter( { filterValue, onSelect, } ); - showInsertionPoint( rootClientId, insertionIndex ); }; let maxBlockPatterns = 0; diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 91d853a50a6a42..cd4569c45e5801 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1624,8 +1624,6 @@ export function insertionPoint( state = null, action ) { } case 'HIDE_INSERTION_POINT': - case 'CLEAR_SELECTED_BLOCK': - case 'SELECT_BLOCK': return null; } diff --git a/packages/editor/src/components/inserter-sidebar/index.js b/packages/editor/src/components/inserter-sidebar/index.js index fef5e54e52f68f..b98770b7afe8fa 100644 --- a/packages/editor/src/components/inserter-sidebar/index.js +++ b/packages/editor/src/components/inserter-sidebar/index.js @@ -22,7 +22,6 @@ const { PrivateInserterLibrary } = unlock( blockEditorPrivateApis ); export default function InserterSidebar() { const { - blockInsertionPoint, blockSectionRootClientId, inserterSidebarToggleRef, insertionPoint, @@ -35,7 +34,6 @@ export default function InserterSidebar() { isPublishSidebarOpened, } = unlock( select( editorStore ) ); const { - getBlockInsertionPoint, getBlockRootClientId, __unstableGetEditorMode, getSectionRootClientId, @@ -53,7 +51,6 @@ export default function InserterSidebar() { return getBlockRootClientId(); }; return { - blockInsertionPoint: getBlockInsertionPoint(), inserterSidebarToggleRef: getInserterSidebarToggleRef(), insertionPoint: getInsertionPoint(), showMostUsedBlocks: get( 'core', 'mostUsedBlocks' ), @@ -92,9 +89,9 @@ export default function InserterSidebar() { showInserterHelpPanel shouldFocusBlock={ isMobileViewport } rootClientId={ - blockSectionRootClientId ?? blockInsertionPoint.rootClientId + blockSectionRootClientId ?? insertionPoint.rootClientId } - __experimentalInsertionIndex={ blockInsertionPoint.index } + __experimentalInsertionIndex={ insertionPoint.insertionIndex } onSelect={ insertionPoint.onSelect } __experimentalInitialTab={ insertionPoint.tab } __experimentalInitialCategory={ insertionPoint.category } From dd34d48c6f00f32b5d81b9ddd6460a80d401037d Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Tue, 10 Sep 2024 17:07:07 +0200 Subject: [PATCH 0749/1908] Fix: Moving a page to the trash on the site editor does not goes back to the pages list (#65119) co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/browser-url/index.js | 40 +------------------ .../src/components/browser-url/test/index.js | 10 +---- packages/editor/README.md | 4 ++ .../editor/src/components/post-trash/index.js | 17 +++++--- .../src/components/sidebar/post-summary.js | 4 +- 5 files changed, 22 insertions(+), 53 deletions(-) diff --git a/packages/edit-post/src/components/browser-url/index.js b/packages/edit-post/src/components/browser-url/index.js index 5f389c4c82818f..12292cb8447217 100644 --- a/packages/edit-post/src/components/browser-url/index.js +++ b/packages/edit-post/src/components/browser-url/index.js @@ -17,22 +17,6 @@ export function getPostEditURL( postId ) { return addQueryArgs( 'post.php', { post: postId, action: 'edit' } ); } -/** - * Returns the Post's Trashed URL. - * - * @param {number} postId Post ID. - * @param {string} postType Post Type. - * - * @return {string} Post trashed URL. - */ -export function getPostTrashedURL( postId, postType ) { - return addQueryArgs( 'edit.php', { - trashed: 1, - post_type: postType, - ids: postId, - } ); -} - export class BrowserURL extends Component { constructor() { super( ...arguments ); @@ -43,17 +27,9 @@ export class BrowserURL extends Component { } componentDidUpdate( prevProps ) { - const { postId, postStatus, postType, isSavingPost, hasHistory } = - this.props; + const { postId, postStatus, hasHistory } = this.props; const { historyId } = this.state; - // Posts are still dirty while saving so wait for saving to finish - // to avoid the unsaved changes warning when trashing posts. - if ( postStatus === 'trash' && ! isSavingPost ) { - this.setTrashURL( postId, postType ); - return; - } - if ( ( postId !== prevProps.postId || postId !== historyId ) && postStatus !== 'auto-draft' && @@ -64,16 +40,6 @@ export class BrowserURL extends Component { } } - /** - * Navigates the browser to the post trashed URL to show a notice about the trashed post. - * - * @param {number} postId Post ID. - * @param {string} postType Post Type. - */ - setTrashURL( postId, postType ) { - window.location.href = getPostTrashedURL( postId, postType ); - } - /** * Replaces the browser URL with a post editor link for the given post ID. * @@ -101,7 +67,7 @@ export class BrowserURL extends Component { } export default withSelect( ( select ) => { - const { getCurrentPost, isSavingPost } = select( editorStore ); + const { getCurrentPost } = select( editorStore ); const post = getCurrentPost(); let { id, status, type } = post; const isTemplate = [ 'wp_template', 'wp_template_part' ].includes( type ); @@ -112,7 +78,5 @@ export default withSelect( ( select ) => { return { postId: id, postStatus: status, - postType: type, - isSavingPost: isSavingPost(), }; } )( BrowserURL ); diff --git a/packages/edit-post/src/components/browser-url/test/index.js b/packages/edit-post/src/components/browser-url/test/index.js index d4b09fc29d7eff..01522680419fe2 100644 --- a/packages/edit-post/src/components/browser-url/test/index.js +++ b/packages/edit-post/src/components/browser-url/test/index.js @@ -6,7 +6,7 @@ import { render } from '@testing-library/react'; /** * Internal dependencies */ -import { getPostEditURL, getPostTrashedURL, BrowserURL } from '../'; +import { getPostEditURL, BrowserURL } from '../'; describe( 'getPostEditURL', () => { it( 'should generate relative path with post and action arguments', () => { @@ -16,14 +16,6 @@ describe( 'getPostEditURL', () => { } ); } ); -describe( 'getPostTrashedURL', () => { - it( 'should generate relative path with post and action arguments', () => { - const url = getPostTrashedURL( 1, 'page' ); - - expect( url ).toBe( 'edit.php?trashed=1&post_type=page&ids=1' ); - } ); -} ); - describe( 'BrowserURL', () => { let replaceStateSpy; diff --git a/packages/editor/README.md b/packages/editor/README.md index ebd4af31e287d8..d18513b151beae 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -1471,6 +1471,10 @@ Undocumented declaration. Displays the Post Trash Button and Confirm Dialog in the Editor. +_Parameters_ + +- _An_ `?{onActionPerformed: Object}`: object containing the onActionPerformed function. + _Returns_ - `JSX.Element|null`: The rendered PostTrash component. diff --git a/packages/editor/src/components/post-trash/index.js b/packages/editor/src/components/post-trash/index.js index ddb1776d479db9..743512e9efd7d4 100644 --- a/packages/editor/src/components/post-trash/index.js +++ b/packages/editor/src/components/post-trash/index.js @@ -6,7 +6,7 @@ import { Button, __experimentalConfirmDialog as ConfirmDialog, } from '@wordpress/components'; -import { useSelect, useDispatch } from '@wordpress/data'; +import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; import { useState } from '@wordpress/element'; /** @@ -18,9 +18,11 @@ import PostTrashCheck from './check'; /** * Displays the Post Trash Button and Confirm Dialog in the Editor. * + * @param {?{onActionPerformed: Object}} An object containing the onActionPerformed function. * @return {JSX.Element|null} The rendered PostTrash component. */ -export default function PostTrash() { +export default function PostTrash( { onActionPerformed } ) { + const registry = useRegistry(); const { isNew, isDeleting, postId, title } = useSelect( ( select ) => { const store = select( editorStore ); return { @@ -37,11 +39,16 @@ export default function PostTrash() { return null; } - const handleConfirm = () => { + const handleConfirm = async () => { setShowConfirmDialog( false ); - trashPost(); + await trashPost(); + const item = await registry + .resolveSelect( editorStore ) + .getCurrentPost(); + // After the post is trashed, we want to trigger the onActionPerformed callback, so the user is redirect + // to the post view depending on if the user is on post editor or site editor. + onActionPerformed?.( 'move-to-trash', [ item ] ); }; - return ( <PostTrashCheck> <Button diff --git a/packages/editor/src/components/sidebar/post-summary.js b/packages/editor/src/components/sidebar/post-summary.js index b7fc6efab11cea..72f1080770fd9d 100644 --- a/packages/editor/src/components/sidebar/post-summary.js +++ b/packages/editor/src/components/sidebar/post-summary.js @@ -88,7 +88,9 @@ export default function PostSummary( { onActionPerformed } ) { <SiteDiscussion /> <PostFormatPanel /> </VStack> - <PostTrash /> + <PostTrash + onActionPerformed={ onActionPerformed } + /> { fills } </VStack> ) } From 07c7821b07e5d2b2abaa86f6737dd486da26383e Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:28:57 +0200 Subject: [PATCH 0750/1908] Remove es-module-shims and wp-importmap-polyfill (#65210) These are no longer used in Core or Gutenberg. See https://core.trac.wordpress.org/ticket/60970. This only seems to have existed in the 6.5 compat directory, removed in #64096. --- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> --- package-lock.json | 13 +------------ package.json | 3 +-- tools/webpack/interactivity.js | 16 ++-------------- 3 files changed, 4 insertions(+), 28 deletions(-) diff --git a/package-lock.json b/package-lock.json index 807fa042d2bd94..b9e116f15388be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -79,8 +79,7 @@ "@wordpress/viewport": "file:packages/viewport", "@wordpress/warning": "file:packages/warning", "@wordpress/widgets": "file:packages/widgets", - "@wordpress/wordcount": "file:packages/wordcount", - "es-module-shims": "^1.8.2" + "@wordpress/wordcount": "file:packages/wordcount" }, "devDependencies": { "@actions/core": "1.9.1", @@ -24843,11 +24842,6 @@ "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", "dev": true }, - "node_modules/es-module-shims": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/es-module-shims/-/es-module-shims-1.8.2.tgz", - "integrity": "sha512-7vIYVzpOhXtpc3Yn03itB+GSgVZFW7oL4kdydA+iL+IEi7HiSLBUxM05QFw4SxTl6e++pMpGqZPo2+vdNs3TbA==" - }, "node_modules/es-set-tostringtag": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", @@ -75264,11 +75258,6 @@ "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", "dev": true }, - "es-module-shims": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/es-module-shims/-/es-module-shims-1.8.2.tgz", - "integrity": "sha512-7vIYVzpOhXtpc3Yn03itB+GSgVZFW7oL4kdydA+iL+IEi7HiSLBUxM05QFw4SxTl6e++pMpGqZPo2+vdNs3TbA==" - }, "es-set-tostringtag": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", diff --git a/package.json b/package.json index 977929555f7dc6..22cdf2ce7acc88 100644 --- a/package.json +++ b/package.json @@ -91,8 +91,7 @@ "@wordpress/viewport": "file:packages/viewport", "@wordpress/warning": "file:packages/warning", "@wordpress/widgets": "file:packages/widgets", - "@wordpress/wordcount": "file:packages/wordcount", - "es-module-shims": "^1.8.2" + "@wordpress/wordcount": "file:packages/wordcount" }, "devDependencies": { "@actions/core": "1.9.1", diff --git a/tools/webpack/interactivity.js b/tools/webpack/interactivity.js index cbde31171fe26e..7f5c7f64a09d7f 100644 --- a/tools/webpack/interactivity.js +++ b/tools/webpack/interactivity.js @@ -2,7 +2,7 @@ * External dependencies */ const { join } = require( 'path' ); -const CopyWebpackPlugin = require( 'copy-webpack-plugin' ); + /** * WordPress dependencies */ @@ -66,19 +66,7 @@ module.exports = { }, ], }, - plugins: [ - ...plugins, - // TODO: Move it to a different Webpack file. - new CopyWebpackPlugin( { - patterns: [ - { - from: './node_modules/es-module-shims/dist/es-module-shims.wasm.js', - to: './build/modules/importmap-polyfill.min.js', - }, - ], - } ), - new DependencyExtractionWebpackPlugin(), - ], + plugins: [ ...plugins, new DependencyExtractionWebpackPlugin() ], watchOptions: { ignored: [ '**/node_modules' ], aggregateTimeout: 500, From 98c65eaf268b86175d51cbb91c35e4111a7950ef Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:02:49 +1000 Subject: [PATCH 0751/1908] Drag and Drop: When dragging a mix of video, audio, and image blocks, create individual blocks as appropriate (#65144) * Drag and Drop: When dragging a mix of video, audio, and image blocks, create individual blocks as appropriate * Consolidate into the fallback transform for the File block Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> --- packages/block-library/src/file/transforms.js | 32 +++++++++++++++---- .../block-library/src/image/transforms.js | 23 ------------- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/packages/block-library/src/file/transforms.js b/packages/block-library/src/file/transforms.js index b925e80e595033..c381a62f783866 100644 --- a/packages/block-library/src/file/transforms.js +++ b/packages/block-library/src/file/transforms.js @@ -24,12 +24,32 @@ const transforms = { const blobURL = createBlobURL( file ); // File will be uploaded in componentDidMount() - blocks.push( - createBlock( 'core/file', { - blob: blobURL, - fileName: file.name, - } ) - ); + if ( file.type.startsWith( 'video/' ) ) { + blocks.push( + createBlock( 'core/video', { + blob: createBlobURL( file ), + } ) + ); + } else if ( file.type.startsWith( 'image/' ) ) { + blocks.push( + createBlock( 'core/image', { + blob: createBlobURL( file ), + } ) + ); + } else if ( file.type.startsWith( 'audio/' ) ) { + blocks.push( + createBlock( 'core/audio', { + blob: createBlobURL( file ), + } ) + ); + } else { + blocks.push( + createBlock( 'core/file', { + blob: blobURL, + fileName: file.name, + } ) + ); + } } ); return blocks; diff --git a/packages/block-library/src/image/transforms.js b/packages/block-library/src/image/transforms.js index 0e1dfb6ee9da44..347d2408280170 100644 --- a/packages/block-library/src/image/transforms.js +++ b/packages/block-library/src/image/transforms.js @@ -3,9 +3,6 @@ */ import { createBlobURL, isBlobURL } from '@wordpress/blob'; import { createBlock, getBlockAttributes } from '@wordpress/blocks'; -import { dispatch } from '@wordpress/data'; -import { store as noticesStore } from '@wordpress/notices'; -import { __ } from '@wordpress/i18n'; export function stripFirstImage( attributes, { shortcode } ) { const { body } = document.implementation.createHTMLDocument( '' ); @@ -138,26 +135,6 @@ const transforms = { // creating a new gallery. type: 'files', isMatch( files ) { - // The following check is intended to catch non-image files when dropped together with images. - if ( - files.some( - ( file ) => file.type.indexOf( 'image/' ) === 0 - ) && - files.some( - ( file ) => file.type.indexOf( 'image/' ) !== 0 - ) - ) { - const { createErrorNotice } = dispatch( noticesStore ); - createErrorNotice( - __( - 'If uploading to a gallery all files need to be image formats' - ), - { - id: 'gallery-transform-invalid-file', - type: 'snackbar', - } - ); - } return files.every( ( file ) => file.type.indexOf( 'image/' ) === 0 ); From da8f8743c22bd9b188a742886367b0a6a25746ed Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Wed, 11 Sep 2024 10:40:44 +0800 Subject: [PATCH 0752/1908] Disallow setting grid block rows/columns to zero (#65217) * Disallow setting grid block rows/columns to zero * Prevent issues with grid block column/row count by ensuring a proper minimum Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/block-editor/src/layouts/grid.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/layouts/grid.js b/packages/block-editor/src/layouts/grid.js index 7ab5c7ebbc8c3d..d1f6fdd785089b 100644 --- a/packages/block-editor/src/layouts/grid.js +++ b/packages/block-editor/src/layouts/grid.js @@ -74,7 +74,8 @@ export default { // In the experiment we want to also show column control in Auto mode, and // the minimum width control in Manual mode. const showColumnsControl = - window.__experimentalEnableGridInteractivity || layout?.columnCount; + window.__experimentalEnableGridInteractivity || + !! layout?.columnCount; const showMinWidthControl = window.__experimentalEnableGridInteractivity || ! layout?.columnCount; @@ -317,7 +318,7 @@ function GridLayoutColumnsAndRowsControl( { const defaultNewColumnCount = isManualPlacement ? 1 : undefined; const newColumnCount = - value === '' + value === '' || value === '0' ? defaultNewColumnCount : parseInt( value, 10 ); onChange( { @@ -327,7 +328,7 @@ function GridLayoutColumnsAndRowsControl( { } else { // Don't allow unsetting the column count. const newColumnCount = - value === '' + value === '' || value === '0' ? 1 : parseInt( value, 10 ); onChange( { @@ -337,7 +338,7 @@ function GridLayoutColumnsAndRowsControl( { } } } value={ columnCount } - min={ 0 } + min={ 1 } label={ __( 'Columns' ) } hideLabelFromVision={ ! window.__experimentalEnableGridInteractivity || @@ -355,7 +356,7 @@ function GridLayoutColumnsAndRowsControl( { onChange={ ( value ) => { // Don't allow unsetting the row count. const newRowCount = - value === '' + value === '' || value === '0' ? 1 : parseInt( value, 10 ); onChange( { @@ -364,21 +365,24 @@ function GridLayoutColumnsAndRowsControl( { } ); } } value={ rowCount } - min={ 0 } + min={ 1 } label={ __( 'Rows' ) } /> ) : ( <RangeControl __next40pxDefaultSize __nextHasNoMarginBottom - value={ columnCount ?? 0 } + value={ columnCount ?? 1 } onChange={ ( value ) => onChange( { ...layout, - columnCount: value, + columnCount: + value === '' || value === '0' + ? 1 + : value, } ) } - min={ 0 } + min={ 1 } max={ 16 } withInputField={ false } label={ __( 'Columns' ) } From ec58c51108f03e4a03046d763d4c830347da91bf Mon Sep 17 00:00:00 2001 From: Vipul Gupta <55375170+vipul0425@users.noreply.github.com> Date: Wed, 11 Sep 2024 08:18:32 +0530 Subject: [PATCH 0753/1908] Image: Adds the block controls for uploading image. (#64320) * feat: Adds the block controls for uploading image. * feat: Adds the size based placeholder logic. * fix: The layout design for small images and adds grid support. * refactor: Remove resize observer and add lockURLControls support. * refactor: Make use of the existing MediaReplaceFlow component. * fix: The mediaPlaceholder location after merge. * fix: The initial flash in small size. * feat: Removes the redundant css and redefine the placeholder logic. * fix: Adressed the PR feedbacks. * fix: Removes the effective width logic and moves observer inside of placeholder. * fix: The e2e test failures * Update packages/block-library/src/image/edit.js Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> --------- Co-authored-by: vipul0425 <vipulgupta003@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> --- packages/block-library/src/image/edit.js | 31 ++++++++++----- packages/block-library/src/image/editor.scss | 40 +------------------ packages/block-library/src/image/image.js | 42 ++++++++++++-------- 3 files changed, 48 insertions(+), 65 deletions(-) diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index f9aed8d93f95a0..660d99bc748ab0 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -12,8 +12,8 @@ import { Placeholder } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; import { BlockIcon, - MediaPlaceholder, useBlockProps, + MediaPlaceholder, store as blockEditorStore, __experimentalUseBorderProps as useBorderProps, __experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles, @@ -109,12 +109,18 @@ export function ImageEdit( { align, metadata, } = attributes; + const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob ); const figureRef = useRef(); const [ contentResizeListener, { width: containerWidth } ] = useResizeObserver(); + const [ placeholderResizeListener, { width: placeholderWidth } ] = + useResizeObserver(); + + const isSmallContainer = placeholderWidth && placeholderWidth < 160; + const altRef = useRef(); useEffect( () => { altRef.current = alt; @@ -387,11 +393,15 @@ export function ImageEdit( { [ borderProps.className ]: !! borderProps.className && ! isSingleSelected, } ) } - withIllustration - icon={ lockUrlControls ? pluginsIcon : icon } - label={ __( 'Image' ) } + icon={ + ! isSmallContainer && + ( lockUrlControls ? pluginsIcon : icon ) + } + withIllustration={ ! isSingleSelected || isSmallContainer } + label={ ! isSmallContainer && __( 'Image' ) } instructions={ ! lockUrlControls && + ! isSmallContainer && __( 'Upload or drag an image file here, or pick one from your library.' ) @@ -408,13 +418,12 @@ export function ImageEdit( { ...shadowProps.style, } } > - { lockUrlControls ? ( - <span className="block-bindings-media-placeholder-message"> - { lockUrlControlsMessage } - </span> - ) : ( - content - ) } + { lockUrlControls && + ! isSmallContainer && + lockUrlControlsMessage } + + { ! lockUrlControls && ! isSmallContainer && content } + { placeholderResizeListener } </Placeholder> ); }; diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss index 636741c7d9ddbb..d143e6604d1e73 100644 --- a/packages/block-library/src/image/editor.scss +++ b/packages/block-library/src/image/editor.scss @@ -1,44 +1,8 @@ // Provide special styling for the placeholder. // @todo this particular minimal style of placeholder could be componentized further. .wp-block-image.wp-block-image { - - // Show Placeholder style on-select. - &.is-selected .block-editor-media-placeholder { - // Block UI appearance. - color: $gray-900; - background-color: $white; - box-shadow: inset 0 0 0 $border-width $gray-900; - border: none; - - // Disable any duotone filter applied in the selected state. - filter: none !important; - - > svg { - opacity: 0; - } - - .components-placeholder__illustration { - display: none; - } - - &::before { - opacity: 0; - } - } - .block-bindings-media-placeholder-message { - opacity: 0; - } - &.is-selected .block-bindings-media-placeholder-message { - opacity: 1; - } - - // Remove the transition while we still have a legacy placeholder style. - // Otherwise the content jumps between the 1px placeholder border, and any inherited custom - // parent border that may get applied when you deselect. - .components-placeholder__label, - .components-placeholder__instructions, - .components-button { - transition: none; + .block-editor-media-placeholder.is-small { + min-height: 60px; } } diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 2de316f78ba5d8..f79f078b1eef82 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -556,6 +556,24 @@ export default function Image( { const showBlockControls = showUrlInput || allowCrop || showCoverControls; + const mediaReplaceFlow = isSingleSelected && + ! isEditingImage && + ! lockUrlControls && ( + <BlockControls group="other"> + <MediaReplaceFlow + mediaId={ id } + mediaURL={ url } + allowedTypes={ ALLOWED_MEDIA_TYPES } + accept="image/*" + onSelect={ onSelectImage } + onSelectURL={ onSelectURL } + onError={ onUploadError } + name={ ! url ? __( 'Add image' ) : __( 'Replace' ) } + onReset={ () => onSelectImage( undefined ) } + /> + </BlockControls> + ); + const controls = ( <> { showBlockControls && ( @@ -592,20 +610,6 @@ export default function Image( { ) } </BlockControls> ) } - { isSingleSelected && ! isEditingImage && ! lockUrlControls && ( - <BlockControls group="other"> - <MediaReplaceFlow - mediaId={ id } - mediaURL={ url } - allowedTypes={ ALLOWED_MEDIA_TYPES } - accept="image/*" - onSelect={ onSelectImage } - onSelectURL={ onSelectURL } - onError={ onUploadError } - onReset={ () => onSelectImage( undefined ) } - /> - </BlockControls> - ) } { isSingleSelected && externalBlob && ( <BlockControls> <ToolbarGroup> @@ -1029,12 +1033,18 @@ export default function Image( { } if ( ! url && ! temporaryURL ) { - // Add all controls if the image attributes are connected. - return metadata?.bindings ? controls : sizeControls; + return ( + <> + { mediaReplaceFlow } + { /* Add all controls if the image attributes are connected. */ } + { metadata?.bindings ? controls : sizeControls } + </> + ); } return ( <> + { mediaReplaceFlow } { controls } { img } From 6a60081909d1dfbbb608e7b069dec3eb6881e37e Mon Sep 17 00:00:00 2001 From: Kai Hao <kevin830726@gmail.com> Date: Wed, 11 Sep 2024 10:51:28 +0800 Subject: [PATCH 0754/1908] Fix resizing to max width in classic themes (#64819) co-authored-by: kevin940726 <kevin940726@git.wordpress.org>Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org>Co-authored-by: andrewserong <andrewserong@git.wordpress.org>Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> * Fix resizing to max width in classic themes * Fix padding and max-width * Reverse the condition * Try ignoring if layout doesn't exist --- packages/block-library/src/image/edit.js | 24 +++++++++----- packages/block-library/src/image/editor.scss | 5 +++ packages/block-library/src/image/image.js | 9 +++--- .../src/image/use-max-width-observer.js | 32 +++++++++++++++++++ 4 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 packages/block-library/src/image/use-max-width-observer.js diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index 660d99bc748ab0..16ec296554d743 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -23,7 +23,6 @@ import { useEffect, useRef, useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { image as icon, plugins as pluginsIcon } from '@wordpress/icons'; import { store as noticesStore } from '@wordpress/notices'; -import { useResizeObserver } from '@wordpress/compose'; /** * Internal dependencies @@ -32,6 +31,7 @@ import { unlock } from '../lock-unlock'; import { useUploadMediaFromBlobURL } from '../utils/hooks'; import Image from './image'; import { isValidFileType } from './utils'; +import { useMaxWidthObserver } from './use-max-width-observer'; /** * Module constants @@ -111,10 +111,15 @@ export function ImageEdit( { } = attributes; const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob ); - const figureRef = useRef(); - const [ contentResizeListener, { width: containerWidth } ] = - useResizeObserver(); + const containerRef = useRef(); + // Only observe the max width from the parent container when the parent layout is not flex nor grid. + // This won't work for them because the container width changes with the image. + // TODO: Find a way to observe the container width for flex and grid layouts. + const isMaxWidthContainerWidth = + ! parentLayout || + ( parentLayout.type !== 'flex' && parentLayout.type !== 'grid' ); + const [ maxWidthObserver, maxContentWidth ] = useMaxWidthObserver(); const [ placeholderResizeListener, { width: placeholderWidth } ] = useResizeObserver(); @@ -166,7 +171,7 @@ export function ImageEdit( { } function onSelectImagesList( images ) { - const win = figureRef.current?.ownerDocument.defaultView; + const win = containerRef.current?.ownerDocument.defaultView; if ( images.every( ( file ) => file instanceof win.File ) ) { /** @type {File[]} */ @@ -354,7 +359,10 @@ export function ImageEdit( { Object.keys( borderProps.style ).length > 0 ), } ); - const blockProps = useBlockProps( { ref: figureRef, className: classes } ); + const blockProps = useBlockProps( { + ref: containerRef, + className: classes, + } ); // Much of this description is duplicated from MediaPlaceholder. const { lockUrlControls = false, lockUrlControlsMessage } = useSelect( @@ -445,7 +453,7 @@ export function ImageEdit( { clientId={ clientId } blockEditingMode={ blockEditingMode } parentLayoutType={ parentLayout?.type } - containerWidth={ containerWidth } + maxContentWidth={ maxContentWidth } /> <MediaPlaceholder icon={ <BlockIcon icon={ icon } /> } @@ -464,7 +472,7 @@ export function ImageEdit( { { // The listener cannot be placed as the first element as it will break the in-between inserter. // See https://github.com/WordPress/gutenberg/blob/71134165868298fc15e22896d0c28b41b3755ff7/packages/block-editor/src/components/block-list/use-in-between-inserter.js#L120 - contentResizeListener + isSingleSelected && isMaxWidthContainerWidth && maxWidthObserver } </> ); diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss index d143e6604d1e73..34f65d690d3d74 100644 --- a/packages/block-library/src/image/editor.scss +++ b/packages/block-library/src/image/editor.scss @@ -113,6 +113,11 @@ figure.wp-block-image:not(.wp-block) { text-align: center; } +// Relatively position the alignment container to support the content resizer. +.wp-block[data-align]:has(> .wp-block-image) { + position: relative; +} + .wp-block-image__crop-area { position: relative; max-width: 100%; diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index f79f078b1eef82..60d83f89129070 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -108,7 +108,7 @@ export default function Image( { clientId, blockEditingMode, parentLayoutType, - containerWidth, + maxContentWidth, } ) { const { url = '', @@ -938,7 +938,7 @@ export default function Image( { // @todo It would be good to revisit this once a content-width variable // becomes available. const maxWidthBuffer = maxWidth * 2.5; - const maxContentWidth = containerWidth || maxWidthBuffer; + const maxResizeWidth = maxContentWidth || maxWidthBuffer; let showRightHandle = false; let showLeftHandle = false; @@ -984,9 +984,9 @@ export default function Image( { } } showHandle={ isSingleSelected } minWidth={ minWidth } - maxWidth={ maxContentWidth } + maxWidth={ maxResizeWidth } minHeight={ minHeight } - maxHeight={ maxContentWidth / ratio } + maxHeight={ maxResizeWidth / ratio } lockAspectRatio={ ratio } enable={ { top: false, @@ -1000,6 +1000,7 @@ export default function Image( { // Clear hardcoded width if the resized width is close to the max-content width. if ( + maxContentWidth && // Only do this if the image is bigger than the container to prevent it from being squished. // TODO: Remove this check if the image support setting 100% width. naturalWidth >= maxContentWidth && diff --git a/packages/block-library/src/image/use-max-width-observer.js b/packages/block-library/src/image/use-max-width-observer.js new file mode 100644 index 00000000000000..684392537fac7a --- /dev/null +++ b/packages/block-library/src/image/use-max-width-observer.js @@ -0,0 +1,32 @@ +/** + * WordPress dependencies + */ +import { useRef } from '@wordpress/element'; +import { useResizeObserver } from '@wordpress/compose'; + +function useMaxWidthObserver() { + const [ contentResizeListener, { width } ] = useResizeObserver(); + const observerRef = useRef(); + + const maxWidthObserver = ( + <div + // Some themes set max-width on blocks. + className="wp-block" + aria-hidden="true" + style={ { + position: 'absolute', + inset: 0, + width: '100%', + height: 0, + margin: 0, + } } + ref={ observerRef } + > + { contentResizeListener } + </div> + ); + + return [ maxWidthObserver, width ]; +} + +export { useMaxWidthObserver }; From 2f939a7f9047ed9b632ac4fb0d593d0cf9588ce9 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 11 Sep 2024 12:44:22 +0900 Subject: [PATCH 0755/1908] Fix image block crash (#65222) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/image/edit.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index 16ec296554d743..d44dc73abfd855 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -23,6 +23,7 @@ import { useEffect, useRef, useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { image as icon, plugins as pluginsIcon } from '@wordpress/icons'; import { store as noticesStore } from '@wordpress/notices'; +import { useResizeObserver } from '@wordpress/compose'; /** * Internal dependencies From 20ca80f48c1b022305164cdbb16baf1329d785f4 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 11 Sep 2024 10:24:18 +0200 Subject: [PATCH 0756/1908] DatePicker: better hover/focus styles (#65117) * DatePicker: better hover/focus styles * CHANGELOG * Use after pseudo-element to avoid conflict with calendar event dot * Make event dots compatible with high contrast mode * Apply box sizing utility * Use themed colors * Use translate to prevent event dot from jumping --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++ .../components/src/date-time/date/styles.ts | 42 ++++++++++++++----- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 8c656f4adb48bb..8a9151e3fdc05e 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -14,6 +14,10 @@ - `Modal`: Decrease close button size and remove horizontal offset ([#65131](https://github.com/WordPress/gutenberg/pull/65131)). +### Bug Fixes + +- `DatePicker`: better hover/focus styles ([#65117](https://github.com/WordPress/gutenberg/pull/65117)). + ### Internal - `Composite`: Remove from private APIs ([#63569](https://github.com/WordPress/gutenberg/pull/63569)). diff --git a/packages/components/src/date-time/date/styles.ts b/packages/components/src/date-time/date/styles.ts index bffc8ae35d2a64..84405854827ec9 100644 --- a/packages/components/src/date-time/date/styles.ts +++ b/packages/components/src/date-time/date/styles.ts @@ -7,13 +7,13 @@ import styled from '@emotion/styled'; * Internal dependencies */ import Button from '../../button'; -import { COLORS, CONFIG } from '../../utils'; +import { boxSizingReset, COLORS, CONFIG } from '../../utils'; import { HStack } from '../../h-stack'; import { Heading } from '../../heading'; import { space } from '../../utils/space'; export const Wrapper = styled.div` - box-sizing: border-box; + ${ boxSizingReset } `; export const Navigator = styled( HStack )` @@ -38,7 +38,7 @@ export const Calendar = styled.div` `; export const DayOfWeek = styled.div` - color: ${ COLORS.gray[ 700 ] }; + color: ${ COLORS.theme.gray[ 700 ] }; font-size: ${ CONFIG.fontSize }; line-height: ${ CONFIG.fontLineHeightBase }; @@ -90,15 +90,34 @@ export const DayButton = styled( Button, { ${ ( props ) => props.isSelected && ` - background: ${ COLORS.theme.accent }; - color: ${ COLORS.white }; + background: ${ COLORS.theme.accent }; + + &, + &:hover:not(:disabled, [aria-disabled=true]) { + color: ${ COLORS.theme.accentInverted }; + } + + &:focus:not(:disabled), + &:focus:not(:disabled) { + border: ${ CONFIG.borderWidthFocus } solid currentColor; + } + + /* Highlight the selected day for high-contrast mode */ + &::after { + content: ''; + position: absolute; + pointer-events: none; + inset: 0; + border-radius: inherit; + border: 1px solid transparent; + } ` } ${ ( props ) => ! props.isSelected && props.isToday && ` - background: ${ COLORS.gray[ 200 ] }; + background: ${ COLORS.theme.gray[ 200 ] }; ` } } @@ -106,15 +125,16 @@ export const DayButton = styled( Button, { props.hasEvents && ` ::before { - background: ${ props.isSelected ? COLORS.white : COLORS.theme.accent }; + border: 2px solid ${ + props.isSelected + ? COLORS.theme.accentInverted + : COLORS.theme.accent + }; border-radius: ${ CONFIG.radiusRound }; - bottom: 2px; content: " "; - height: 4px; left: 50%; - margin-left: -2px; position: absolute; - width: 4px; + transform: translate(-50%, 9px); } ` } `; From 5daa582f7fa20f28daabf546e1686c016432b04f Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 11 Sep 2024 11:05:07 +0200 Subject: [PATCH 0757/1908] Navigator Screen: warn if path doesn't follow a URL-like scheme (#65231) * Navigator Screen: warn if path doesn't follow the expected scheme * Add test * CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/navigator/navigator-screen/component.tsx | 7 +++++++ packages/components/src/navigator/test/index.tsx | 8 ++++++++ 3 files changed, 16 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 8a9151e3fdc05e..55c85565f522aa 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -12,6 +12,7 @@ ### Enhancements +- `Navigator`: warn if a screen's `path` doesn't follow a URL-like scheme ([#65231](https://github.com/WordPress/gutenberg/pull/65231)). - `Modal`: Decrease close button size and remove horizontal offset ([#65131](https://github.com/WordPress/gutenberg/pull/65131)). ### Bug Fixes diff --git a/packages/components/src/navigator/navigator-screen/component.tsx b/packages/components/src/navigator/navigator-screen/component.tsx index be5c4bfaf41ec4..5882f271d4518f 100644 --- a/packages/components/src/navigator/navigator-screen/component.tsx +++ b/packages/components/src/navigator/navigator-screen/component.tsx @@ -17,6 +17,7 @@ import { import { useMergeRefs } from '@wordpress/compose'; import { isRTL as isRTLFn } from '@wordpress/i18n'; import { escapeAttribute } from '@wordpress/escape-html'; +import warning from '@wordpress/warning'; /** * Internal dependencies @@ -33,6 +34,12 @@ function UnconnectedNavigatorScreen( props: WordPressComponentProps< NavigatorScreenProps, 'div', false >, forwardedRef: ForwardedRef< any > ) { + if ( ! /^\//.test( props.path ) ) { + warning( + 'wp.components.NavigatorScreen: the `path` should follow a URL-like scheme; it should start with and be separated by the `/` character.' + ); + } + const screenId = useId(); const { children, className, path, ...otherProps } = useContextSystem( props, diff --git a/packages/components/src/navigator/test/index.tsx b/packages/components/src/navigator/test/index.tsx index 9b9b257ea09681..820942a22644ba 100644 --- a/packages/components/src/navigator/test/index.tsx +++ b/packages/components/src/navigator/test/index.tsx @@ -642,6 +642,14 @@ describe( 'Navigator', () => { ).toHaveAttribute( 'id', INVALID_HTML_ATTRIBUTE.escaped ); } ); + it( 'should warn if the `path` prop does not follow the required format', () => { + render( <NavigatorScreen path="not-valid">Test</NavigatorScreen> ); + + expect( console ).toHaveWarnedWith( + 'wp.components.NavigatorScreen: the `path` should follow a URL-like scheme; it should start with and be separated by the `/` character.' + ); + } ); + it( 'should match correctly paths with named arguments', async () => { const user = userEvent.setup(); From 3d5dacd3ed50fb2cba64cf62781a8859716e3738 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:45:50 +0200 Subject: [PATCH 0758/1908] Populate block context with inherited post type from template slug (#65062) * Inherit post type from template slug * Move map outside of `useSelect` Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- .../editor/src/components/provider/index.js | 52 +++++++++++++++---- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index aaf25621d3324b..11b1478d58434a 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -4,7 +4,11 @@ import { useEffect, useLayoutEffect, useMemo } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; -import { EntityProvider, useEntityBlockEditor } from '@wordpress/core-data'; +import { + EntityProvider, + useEntityBlockEditor, + store as coreStore, +} from '@wordpress/core-data'; import { BlockEditorProvider, BlockContextProvider, @@ -48,7 +52,6 @@ const noop = () => {}; */ const NON_CONTEXTUAL_POST_TYPES = [ 'wp_block', - 'wp_template', 'wp_navigation', 'wp_template_part', ]; @@ -161,31 +164,59 @@ export const ExperimentalEditorProvider = withRegistryProvider( BlockEditorProviderComponent = ExperimentalBlockEditorProvider, __unstableTemplate: template, } ) => { - const { editorSettings, selection, isReady, mode } = useSelect( - ( select ) => { + const { editorSettings, selection, isReady, mode, postTypes } = + useSelect( ( select ) => { const { getEditorSettings, getEditorSelection, getRenderingMode, __unstableIsEditorReady, } = select( editorStore ); + const { getPostTypes } = select( coreStore ); + return { editorSettings: getEditorSettings(), isReady: __unstableIsEditorReady(), mode: getRenderingMode(), selection: getEditorSelection(), + postTypes: getPostTypes( { per_page: -1 } ), }; - }, - [] - ); + }, [] ); const shouldRenderTemplate = !! template && mode !== 'post-only'; const rootLevelPost = shouldRenderTemplate ? template : post; const defaultBlockContext = useMemo( () => { - const postContext = + const postContext = {}; + // If it is a template, try to inherit the post type from the slug. + if ( post.type === 'wp_template' ) { + if ( ! post.is_custom ) { + const [ kind ] = post.slug.split( '-' ); + switch ( kind ) { + case 'page': + postContext.postType = 'page'; + break; + case 'single': + // Infer the post type from the slug. + const postTypesSlugs = + postTypes?.map( ( entity ) => entity.slug ) || + []; + const match = post.slug.match( + `^single-(${ postTypesSlugs.join( + '|' + ) })(?:-.+)?$` + ); + if ( match ) { + postContext.postType = match[ 1 ]; + } + break; + } + } + } else if ( ! NON_CONTEXTUAL_POST_TYPES.includes( rootLevelPost.type ) || shouldRenderTemplate - ? { postId: post.id, postType: post.type } - : {}; + ) { + postContext.postId = post.id; + postContext.postType = post.type; + } return { ...postContext, @@ -200,6 +231,7 @@ export const ExperimentalEditorProvider = withRegistryProvider( post.type, rootLevelPost.type, rootLevelPost.slug, + postTypes, ] ); const { id, type } = rootLevelPost; const blockEditorSettings = useBlockEditorSettings( From b2766478255b83b9a44be72bceaa843734778be2 Mon Sep 17 00:00:00 2001 From: Akshat Kakkad <87222220+AKSHAT2802@users.noreply.github.com> Date: Wed, 11 Sep 2024 15:48:58 +0530 Subject: [PATCH 0759/1908] Remove Warning and add notice for Navigation (#63921) Co-authored-by: AKSHAT2802 <akshat2802@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../edit/deleted-navigation-warning.js | 42 ++++++++++--------- .../edit/menu-inspector-controls.js | 4 +- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/packages/block-library/src/navigation/edit/deleted-navigation-warning.js b/packages/block-library/src/navigation/edit/deleted-navigation-warning.js index b0521f16cfb5d5..22d1e339c5c004 100644 --- a/packages/block-library/src/navigation/edit/deleted-navigation-warning.js +++ b/packages/block-library/src/navigation/edit/deleted-navigation-warning.js @@ -2,28 +2,32 @@ * WordPress dependencies */ import { Warning } from '@wordpress/block-editor'; -import { Button } from '@wordpress/components'; +import { Button, Notice } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { createInterpolateElement } from '@wordpress/element'; -function DeletedNavigationWarning( { onCreateNew } ) { - return ( - <Warning> - { createInterpolateElement( - __( - 'Navigation Menu has been deleted or is unavailable. <button>Create a new Menu?</button>' - ), - { - button: ( - <Button - __next40pxDefaultSize - onClick={ onCreateNew } - variant="link" - /> - ), - } - ) } - </Warning> +function DeletedNavigationWarning( { onCreateNew, isNotice = false } ) { + const message = createInterpolateElement( + __( + 'Navigation Menu has been deleted or is unavailable. <button>Create a new Menu?</button>' + ), + { + button: ( + <Button + __next40pxDefaultSize + onClick={ onCreateNew } + variant="link" + /> + ), + } + ); + + return isNotice ? ( + <Notice status="warning" isDismissible={ false }> + { message } + </Notice> + ) : ( + <Warning>{ message }</Warning> ); } diff --git a/packages/block-library/src/navigation/edit/menu-inspector-controls.js b/packages/block-library/src/navigation/edit/menu-inspector-controls.js index e21655eef90715..8f6c2e47fe7759 100644 --- a/packages/block-library/src/navigation/edit/menu-inspector-controls.js +++ b/packages/block-library/src/navigation/edit/menu-inspector-controls.js @@ -94,7 +94,9 @@ const MainContent = ( { const { navigationMenu } = useNavigationMenu( currentMenuId ); if ( currentMenuId && isNavigationMenuMissing ) { - return <DeletedNavigationWarning onCreateNew={ onCreateNew } />; + return ( + <DeletedNavigationWarning onCreateNew={ onCreateNew } isNotice /> + ); } if ( isLoading ) { From f8a19eb08945a9fd26d5bda49b1e2c94857ea827 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Wed, 11 Sep 2024 13:15:29 +0200 Subject: [PATCH 0760/1908] Build: Prepare build for more script modules (#65064) - Rename the "interactivity" webpack build to "script modules". - Output script-modules builds to `build-module` folder (adjacent to the `build` folder currently used for scripts). - Add `wpScriptModulesExports` package.json field to packages with script modules and use it for script module builds. This follows the same basic syntax as [package.json `exports` fields](https://nodejs.org/api/packages.html#exports). Multiple module entrypoints can be exposed per package. However, it remains a custom field, so it is clear that these entrypoints are not intended for general consumption. In the future, module-only packages (interactivity, interactivity-router) can switch to using exports directly and likely add `type: module`. - There are some difficulties with webpack recognizing `wpScriptModulesExports` directly, so packages are inspected programmatically in order to generate webpack script modules entrypoints. - Adjust script module registration accordingly to find the generated script modules. --- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .github/workflows/bundle-size.yml | 2 +- bin/build-plugin-zip.sh | 1 + lib/interactivity-api.php | 4 +- package-lock.json | 1 + package.json | 1 + packages/block-library/package.json | 7 + packages/block-library/src/file/index.php | 2 +- packages/block-library/src/image/index.php | 2 +- .../block-library/src/navigation/index.php | 2 +- packages/block-library/src/query/index.php | 2 +- packages/block-library/src/search/index.php | 2 +- packages/interactivity-router/package.json | 1 + packages/interactivity/package.json | 4 + tools/webpack/interactivity.js | 74 ---------- tools/webpack/script-modules.js | 133 ++++++++++++++++++ webpack.config.js | 4 +- 16 files changed, 158 insertions(+), 84 deletions(-) delete mode 100644 tools/webpack/interactivity.js create mode 100644 tools/webpack/script-modules.js diff --git a/.github/workflows/bundle-size.yml b/.github/workflows/bundle-size.yml index 6106eee492c32a..499a2c020255cb 100644 --- a/.github/workflows/bundle-size.yml +++ b/.github/workflows/bundle-size.yml @@ -52,5 +52,5 @@ jobs: - uses: preactjs/compressed-size-action@f780fd104362cfce9e118f9198df2ee37d12946c # v2.6.0 with: repo-token: '${{ secrets.GITHUB_TOKEN }}' - pattern: '{build/**/*.min.js,build/**/*.css}' + pattern: '{build/**/*.min.js,build/**/*.css,build-module/**/*.min.js}' clean-script: 'distclean' diff --git a/bin/build-plugin-zip.sh b/bin/build-plugin-zip.sh index 4ba931c4a4aeb6..ad627e05f0c693 100755 --- a/bin/build-plugin-zip.sh +++ b/bin/build-plugin-zip.sh @@ -98,6 +98,7 @@ zip -r gutenberg.zip \ packages/block-serialization-default-parser/*.php \ post-content.php \ $build_files \ + build-module \ readme.txt \ changelog.txt \ README.md diff --git a/lib/interactivity-api.php b/lib/interactivity-api.php index 6f04a3ba8fc927..90535f1ebaa42f 100644 --- a/lib/interactivity-api.php +++ b/lib/interactivity-api.php @@ -16,14 +16,14 @@ function gutenberg_reregister_interactivity_script_modules() { wp_register_script_module( '@wordpress/interactivity', - gutenberg_url( '/build/interactivity/' . ( SCRIPT_DEBUG ? 'debug.min.js' : 'index.min.js' ) ), + gutenberg_url( '/build-module/' . ( SCRIPT_DEBUG ? 'interactivity/debug.min.js' : 'interactivity/index.min.js' ) ), array(), $default_version ); wp_register_script_module( '@wordpress/interactivity-router', - gutenberg_url( '/build/interactivity/router.min.js' ), + gutenberg_url( '/build-module/interactivity-router/index.min.js' ), array( '@wordpress/interactivity' ), $default_version ); diff --git a/package-lock.json b/package-lock.json index b9e116f15388be..769ef050834203 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46,6 +46,7 @@ "@wordpress/i18n": "file:packages/i18n", "@wordpress/icons": "file:packages/icons", "@wordpress/interactivity": "file:packages/interactivity", + "@wordpress/interactivity-router": "file:packages/interactivity-router", "@wordpress/interface": "file:packages/interface", "@wordpress/is-shallow-equal": "file:packages/is-shallow-equal", "@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts", diff --git a/package.json b/package.json index 22cdf2ce7acc88..e757aaa0f44b48 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "@wordpress/i18n": "file:packages/i18n", "@wordpress/icons": "file:packages/icons", "@wordpress/interactivity": "file:packages/interactivity", + "@wordpress/interactivity-router": "file:packages/interactivity-router", "@wordpress/interface": "file:packages/interface", "@wordpress/is-shallow-equal": "file:packages/is-shallow-equal", "@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts", diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 4d0212490858c9..1353ef24c77d89 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -30,6 +30,13 @@ "src/**/*.scss", "{src,build,build-module}/*/init.js" ], + "wpScriptModuleExports": { + "./file/view": "./build-module/file/view.js", + "./image/view": "./build-module/image/view.js", + "./navigation/view": "./build-module/navigation/view.js", + "./query/view": "./build-module/query/view.js", + "./search/view": "./build-module/search/view.js" + }, "dependencies": { "@babel/runtime": "^7.16.0", "@wordpress/a11y": "file:../a11y", diff --git a/packages/block-library/src/file/index.php b/packages/block-library/src/file/index.php index 87910f0e66a0cf..85cc840201da59 100644 --- a/packages/block-library/src/file/index.php +++ b/packages/block-library/src/file/index.php @@ -21,7 +21,7 @@ function render_block_core_file( $attributes, $content ) { if ( ! empty( $attributes['displayPreview'] ) ) { $suffix = wp_scripts_get_suffix(); if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) { - $module_url = gutenberg_url( '/build/interactivity/file.min.js' ); + $module_url = gutenberg_url( '/build-module/block-library/file/view.min.js' ); } wp_register_script_module( diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index 75f0d404e4820c..abbb03c0952452 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -72,7 +72,7 @@ function render_block_core_image( $attributes, $content, $block ) { ) { $suffix = wp_scripts_get_suffix(); if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) { - $module_url = gutenberg_url( '/build/interactivity/image.min.js' ); + $module_url = gutenberg_url( '/build-module/block-library/image/view.min.js' ); } wp_register_script_module( diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index ccadd5c4a222d4..ec72b03b6906f0 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -624,7 +624,7 @@ private static function handle_view_script_module_loading( $attributes, $block, if ( static::is_interactive( $attributes, $inner_blocks ) ) { $suffix = wp_scripts_get_suffix(); if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) { - $module_url = gutenberg_url( '/build/interactivity/navigation.min.js' ); + $module_url = gutenberg_url( '/build-module/block-library/navigation/view.min.js' ); } wp_register_script_module( diff --git a/packages/block-library/src/query/index.php b/packages/block-library/src/query/index.php index 6cc57dc08388c6..d10db26529854e 100644 --- a/packages/block-library/src/query/index.php +++ b/packages/block-library/src/query/index.php @@ -26,7 +26,7 @@ function render_block_core_query( $attributes, $content, $block ) { if ( $is_interactive ) { $suffix = wp_scripts_get_suffix(); if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) { - $module_url = gutenberg_url( '/build/interactivity/query.min.js' ); + $module_url = gutenberg_url( '/build-module/block-library/query/view.min.js' ); } wp_register_script_module( diff --git a/packages/block-library/src/search/index.php b/packages/block-library/src/search/index.php index 39b8591c86600f..fb09cdd36406e8 100644 --- a/packages/block-library/src/search/index.php +++ b/packages/block-library/src/search/index.php @@ -82,7 +82,7 @@ function render_block_core_search( $attributes ) { if ( $is_expandable_searchfield ) { $suffix = wp_scripts_get_suffix(); if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) { - $module_url = gutenberg_url( '/build/interactivity/search.min.js' ); + $module_url = gutenberg_url( '/build-module/block-library/search/view.min.js' ); } wp_register_script_module( diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 53b68068c528a0..db85c0d8bdba3b 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -26,6 +26,7 @@ "module": "build-module/index.js", "react-native": "src/index", "types": "build-types", + "wpScriptModuleExports": "./build-module/index.js", "dependencies": { "@wordpress/interactivity": "file:../interactivity" }, diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 3e29d9aabeeab9..6be9f3c4a0d7d8 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -26,6 +26,10 @@ "module": "build-module/index.js", "react-native": "src/index", "types": "build-types", + "wpScriptModuleExports": { + ".": "./build-module/index.js", + "./debug": "./build-module/debug.js" + }, "dependencies": { "@preact/signals": "^1.2.2", "preact": "^10.19.3" diff --git a/tools/webpack/interactivity.js b/tools/webpack/interactivity.js deleted file mode 100644 index 7f5c7f64a09d7f..00000000000000 --- a/tools/webpack/interactivity.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * External dependencies - */ -const { join } = require( 'path' ); - -/** - * WordPress dependencies - */ -const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' ); - -/** - * Internal dependencies - */ -const { baseConfig, plugins } = require( './shared' ); - -module.exports = { - ...baseConfig, - name: 'interactivity', - entry: { - index: './packages/interactivity', - debug: './packages/interactivity/src/debug', - router: './packages/interactivity-router', - navigation: './packages/block-library/src/navigation/view.js', - query: './packages/block-library/src/query/view.js', - image: './packages/block-library/src/image/view.js', - file: './packages/block-library/src/file/view.js', - search: './packages/block-library/src/search/view.js', - }, - experiments: { - outputModule: true, - }, - output: { - devtoolNamespace: 'wp', - filename: './build/interactivity/[name].min.js', - library: { - type: 'module', - }, - path: join( __dirname, '..', '..' ), - environment: { module: true }, - module: true, - chunkFormat: 'module', - }, - resolve: { - extensions: [ '.js', '.ts', '.tsx' ], - }, - module: { - rules: [ - { - test: /\.(j|t)sx?$/, - exclude: /node_modules/, - use: [ - { - loader: require.resolve( 'babel-loader' ), - options: { - cacheDirectory: - process.env.BABEL_CACHE_DIRECTORY || true, - babelrc: false, - configFile: false, - presets: [ - '@babel/preset-typescript', - '@babel/preset-react', - ], - }, - }, - ], - }, - ], - }, - plugins: [ ...plugins, new DependencyExtractionWebpackPlugin() ], - watchOptions: { - ignored: [ '**/node_modules' ], - aggregateTimeout: 500, - }, -}; diff --git a/tools/webpack/script-modules.js b/tools/webpack/script-modules.js new file mode 100644 index 00000000000000..57652e0be28e2b --- /dev/null +++ b/tools/webpack/script-modules.js @@ -0,0 +1,133 @@ +/** + * External dependencies + */ +const { join } = require( 'path' ); + +/** + * WordPress dependencies + */ +const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' ); + +/** + * Internal dependencies + */ +const { baseConfig, plugins } = require( './shared' ); + +const WORDPRESS_NAMESPACE = '@wordpress/'; +const { createRequire } = require( 'node:module' ); + +const rootURL = new URL( '..', `file://${ __dirname }` ); +const fromRootRequire = createRequire( rootURL ); + +/** @type {Iterable<[string, string]>} */ +const iterableDeps = Object.entries( + fromRootRequire( './package.json' ).dependencies +); + +/** @type {Map<string, string>} */ +const gutenbergScriptModules = new Map(); +for ( const [ packageName, versionSpecifier ] of iterableDeps ) { + if ( + ! packageName.startsWith( WORDPRESS_NAMESPACE ) || + ! versionSpecifier.startsWith( 'file:' ) || + packageName.startsWith( WORDPRESS_NAMESPACE + 'react-native' ) + ) { + continue; + } + + const packageRequire = createRequire( + // Remove the leading "file:" specifier to build a package URL. + new URL( `${ versionSpecifier.substring( 5 ) }/`, rootURL ) + ); + + const depPackageJson = packageRequire( './package.json' ); + if ( ! Object.hasOwn( depPackageJson, 'wpScriptModuleExports' ) ) { + continue; + } + + const moduleName = packageName.substring( WORDPRESS_NAMESPACE.length ); + let { wpScriptModuleExports } = depPackageJson; + + // Special handling for { "wpScriptModuleExports": "./build-module/index.js" }. + if ( typeof wpScriptModuleExports === 'string' ) { + wpScriptModuleExports = { '.': wpScriptModuleExports }; + } + + if ( Object.getPrototypeOf( wpScriptModuleExports ) !== Object.prototype ) { + throw new Error( 'wpScriptModuleExports must be an object' ); + } + + for ( const [ exportName, exportPath ] of Object.entries( + wpScriptModuleExports + ) ) { + if ( typeof exportPath !== 'string' ) { + throw new Error( 'wpScriptModuleExports paths must be strings' ); + } + + if ( ! exportPath.startsWith( './' ) ) { + throw new Error( + 'wpScriptModuleExports paths must start with "./"' + ); + } + + const name = + exportName === '.' ? 'index' : exportName.replace( /^\.\/?/, '' ); + + gutenbergScriptModules.set( + `${ moduleName }/${ name }`, + packageRequire.resolve( exportPath ) + ); + } +} + +module.exports = { + ...baseConfig, + name: 'script-modules', + entry: Object.fromEntries( gutenbergScriptModules.entries() ), + experiments: { + outputModule: true, + }, + output: { + devtoolNamespace: 'wp', + filename: './build-module/[name].min.js', + library: { + type: 'module', + }, + path: join( __dirname, '..', '..' ), + environment: { module: true }, + module: true, + chunkFormat: 'module', + asyncChunks: false, + }, + resolve: { + extensions: [ '.js', '.ts', '.tsx' ], + }, + module: { + rules: [ + { + test: /\.(j|t)sx?$/, + exclude: /node_modules/, + use: [ + { + loader: require.resolve( 'babel-loader' ), + options: { + cacheDirectory: + process.env.BABEL_CACHE_DIRECTORY || true, + babelrc: false, + configFile: false, + presets: [ + '@babel/preset-typescript', + '@babel/preset-react', + ], + }, + }, + ], + }, + ], + }, + plugins: [ ...plugins, new DependencyExtractionWebpackPlugin() ], + watchOptions: { + ignored: [ '**/node_modules' ], + aggregateTimeout: 500, + }, +}; diff --git a/webpack.config.js b/webpack.config.js index 45b22cc5354dcf..51889b06d1eb44 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -3,13 +3,13 @@ */ const blocksConfig = require( './tools/webpack/blocks' ); const developmentConfigs = require( './tools/webpack/development' ); -const interactivity = require( './tools/webpack/interactivity' ); +const scriptModules = require( './tools/webpack/script-modules' ); const packagesConfig = require( './tools/webpack/packages' ); const vendorsConfig = require( './tools/webpack/vendors' ); module.exports = [ ...blocksConfig, - interactivity, + scriptModules, packagesConfig, ...developmentConfigs, ...vendorsConfig, From 0c0e605c763908543529f119f08b783a94e2b41c Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Wed, 11 Sep 2024 15:48:58 +0200 Subject: [PATCH 0761/1908] Add @wordpress/fields package (#65230) Co-authored-by: gigitux <gigitux@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- docs/manifest.json | 6 +++ package-lock.json | 26 ++++++++++++ package.json | 1 + .../lib/util.js | 1 + packages/fields/.npmrc | 1 + packages/fields/CHANGELOG.md | 5 +++ packages/fields/README.md | 27 ++++++++++++ packages/fields/package.json | 41 +++++++++++++++++++ packages/fields/src/index.ts | 0 packages/fields/tsconfig.json | 11 +++++ packages/private-apis/src/implementation.js | 1 + tools/webpack/packages.js | 1 + tsconfig.json | 1 + 13 files changed, 122 insertions(+) create mode 100644 packages/fields/.npmrc create mode 100644 packages/fields/CHANGELOG.md create mode 100644 packages/fields/README.md create mode 100644 packages/fields/package.json create mode 100644 packages/fields/src/index.ts create mode 100644 packages/fields/tsconfig.json diff --git a/docs/manifest.json b/docs/manifest.json index e4eba19d99fa29..d7f74d47995b63 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1697,6 +1697,12 @@ "markdown_source": "../packages/eslint-plugin/README.md", "parent": "packages" }, + { + "title": "@wordpress/fields", + "slug": "packages-fields", + "markdown_source": "../packages/fields/README.md", + "parent": "packages" + }, { "title": "@wordpress/format-library", "slug": "packages-format-library", diff --git a/package-lock.json b/package-lock.json index 769ef050834203..5f393e700c2892 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,6 +40,7 @@ "@wordpress/editor": "file:packages/editor", "@wordpress/element": "file:packages/element", "@wordpress/escape-html": "file:packages/escape-html", + "@wordpress/fields": "file:packages/fields", "@wordpress/format-library": "file:packages/format-library", "@wordpress/hooks": "file:packages/hooks", "@wordpress/html-entities": "file:packages/html-entities", @@ -17029,6 +17030,10 @@ "resolved": "packages/eslint-plugin", "link": true }, + "node_modules/@wordpress/fields": { + "resolved": "packages/fields", + "link": true + }, "node_modules/@wordpress/format-library": { "resolved": "packages/format-library", "link": true @@ -53891,6 +53896,21 @@ } } }, + "packages/fields": { + "name": "@wordpress/fields", + "version": "0.0.1", + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "^7.16.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, "packages/format-library": { "name": "@wordpress/format-library", "version": "5.7.0", @@ -68448,6 +68468,12 @@ "requireindex": "^1.2.0" } }, + "@wordpress/fields": { + "version": "file:packages/fields", + "requires": { + "@babel/runtime": "^7.16.0" + } + }, "@wordpress/format-library": { "version": "file:packages/format-library", "requires": { diff --git a/package.json b/package.json index e757aaa0f44b48..9236dbfb47adee 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "@wordpress/editor": "file:packages/editor", "@wordpress/element": "file:packages/element", "@wordpress/escape-html": "file:packages/escape-html", + "@wordpress/fields": "file:packages/fields", "@wordpress/format-library": "file:packages/format-library", "@wordpress/hooks": "file:packages/hooks", "@wordpress/html-entities": "file:packages/html-entities", diff --git a/packages/dependency-extraction-webpack-plugin/lib/util.js b/packages/dependency-extraction-webpack-plugin/lib/util.js index ee5c2face1b9d1..fcc6e5a0ed1731 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/util.js +++ b/packages/dependency-extraction-webpack-plugin/lib/util.js @@ -9,6 +9,7 @@ const BUNDLED_PACKAGES = [ '@wordpress/interface', '@wordpress/sync', '@wordpress/undo-manager', + '@wordpress/fields', ]; /** diff --git a/packages/fields/.npmrc b/packages/fields/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/fields/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/fields/CHANGELOG.md b/packages/fields/CHANGELOG.md new file mode 100644 index 00000000000000..e04ce921cdfdc4 --- /dev/null +++ b/packages/fields/CHANGELOG.md @@ -0,0 +1,5 @@ +<!-- Learn how to maintain this file at https://github.com/WordPress/gutenberg/tree/HEAD/packages#maintaining-changelogs. --> + +## Unreleased + +Initial release. diff --git a/packages/fields/README.md b/packages/fields/README.md new file mode 100644 index 00000000000000..c5044d1e9fdd2f --- /dev/null +++ b/packages/fields/README.md @@ -0,0 +1,27 @@ +# Fields + +This package provides core elements for the DataView library, designed to simplify the creation and management of data display elements in WordPress. + +## Installation + +Install the module + +```bash +npm install @wordpress/fields --save +``` + +## Usage + +<!-- START TOKEN(Autogenerated API docs) --> + +Nothing to document. + +<!-- END TOKEN(Autogenerated API docs) --> + +## Contributing to this package + +This is an individual package that's part of the Gutenberg project. The project is organized as a monorepo. It's made up of multiple self-contained software packages, each with a specific purpose. The packages in this monorepo are published to [npm](https://www.npmjs.com/) and used by [WordPress](https://make.wordpress.org/core/) as well as other software projects. + +To find out more about contributing to this package or Gutenberg as a whole, please read the project's main [contributor guide](https://github.com/WordPress/gutenberg/tree/HEAD/CONTRIBUTING.md). + +<br /><br /><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p> diff --git a/packages/fields/package.json b/packages/fields/package.json new file mode 100644 index 00000000000000..4d5d33a10e5ed5 --- /dev/null +++ b/packages/fields/package.json @@ -0,0 +1,41 @@ +{ + "name": "@wordpress/fields", + "version": "0.0.1", + "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", + "author": "The WordPress Contributors", + "license": "GPL-2.0-or-later", + "keywords": [ + "wordpress", + "gutenberg", + "dataviews" + ], + "homepage": "https://github.com/WordPress/gutenberg/tree/HEAD/packages/fields/README.md", + "repository": { + "type": "git", + "url": "https://github.com/WordPress/gutenberg.git", + "directory": "packages/fields" + }, + "bugs": { + "url": "https://github.com/WordPress/gutenberg/issues" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "main": "build/index.js", + "module": "build-module/index.js", + "types": "build-types", + "sideEffects": [ + "build-style/**", + "src/**/*.scss" + ], + "dependencies": { + "@babel/runtime": "^7.16.0" + }, + "peerDependencies": { + "react": "^18.0.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/fields/src/index.ts b/packages/fields/src/index.ts new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/packages/fields/tsconfig.json b/packages/fields/tsconfig.json new file mode 100644 index 00000000000000..79aa09d0ad56e3 --- /dev/null +++ b/packages/fields/tsconfig.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types", + "checkJs": false + }, + "references": [], + "include": [ "src" ] +} diff --git a/packages/private-apis/src/implementation.js b/packages/private-apis/src/implementation.js index c268e46f669cbf..13ee9873e899de 100644 --- a/packages/private-apis/src/implementation.js +++ b/packages/private-apis/src/implementation.js @@ -31,6 +31,7 @@ const CORE_MODULES_USING_PRIVATE_APIS = [ '@wordpress/reusable-blocks', '@wordpress/router', '@wordpress/dataviews', + '@wordpress/fields', ]; /** diff --git a/tools/webpack/packages.js b/tools/webpack/packages.js index 055665c2feb1c8..a1610d0a5ba54e 100644 --- a/tools/webpack/packages.js +++ b/tools/webpack/packages.js @@ -34,6 +34,7 @@ const BUNDLED_PACKAGES = [ '@wordpress/interface', '@wordpress/sync', '@wordpress/undo-manager', + '@wordpress/fields', ]; // PHP files in packages that have to be copied during build. diff --git a/tsconfig.json b/tsconfig.json index 6be31e9b61bef8..3ab54f66019bca 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,6 +25,7 @@ { "path": "packages/element" }, { "path": "packages/escape-html" }, { "path": "packages/eslint-plugin" }, + { "path": "packages/fields" }, { "path": "packages/hooks" }, { "path": "packages/html-entities" }, { "path": "packages/html-entities" }, From e1ad8c216c0c782bc007e29cf15f82213645f865 Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Wed, 11 Sep 2024 17:24:01 +0200 Subject: [PATCH 0762/1908] Improve Tabs indicator animation and related utils (#64926) * Refactor utils and switch Tabs indicator animation to `transform`. * docs tweak * Update packages/components/src/tabs/styles.ts Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> * Add RTL support. * Addressed @ciampo's comments. * Correct for antialiasing rounding. * Make antialiasing adjustment optional. * Use larger base value and revert antialiasing adjustment code. * DRY RTL * Remove RTL story (redundant since Storybook has a dynamic setting to test RTL). * Fix bug. * Fix bug (for real this time). * Add changelog entry. * De-cleverfy code. * Sync useResizeObserver with #64943 and make useTrackElementOffsetRect resilient. * Deduplicate utility and clean up. * DRY antialiasing factor. * Changelogs. --------- Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 5 + packages/components/src/tabs/styles.ts | 51 +++- packages/components/src/tabs/tablist.tsx | 9 +- packages/components/src/utils/element-rect.ts | 223 ++++++++---------- 4 files changed, 143 insertions(+), 145 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 55c85565f522aa..67a63b8b656461 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- `Tabs`: indicator positioning under RTL direction ([#64926](https://github.com/WordPress/gutenberg/pull/64926)). + ### Deprecations - Deprecate `__unstableComposite`, `__unstableCompositeGroup`, `__unstableCompositeItem` and `__unstableUseCompositeState`. Consumers of the package should use the stable `Composite` component instead ([#63572](https://github.com/WordPress/gutenberg/pull/63572)). @@ -21,6 +25,7 @@ ### Internal +- `Tabs`: improved performance of the indicator animation ([#64926](https://github.com/WordPress/gutenberg/pull/64926)). - `Composite`: Remove from private APIs ([#63569](https://github.com/WordPress/gutenberg/pull/63569)). - use local copy of `use-lilius` instead of `npm` dependency ([#65097](https://github.com/WordPress/gutenberg/pull/65097)). diff --git a/packages/components/src/tabs/styles.ts b/packages/components/src/tabs/styles.ts index fcdb43512d82f9..a6425f9ab31e45 100644 --- a/packages/components/src/tabs/styles.ts +++ b/packages/components/src/tabs/styles.ts @@ -22,36 +22,65 @@ export const TabListWrapper = styled.div` text-align: start; } - @media not ( prefers-reduced-motion: reduce ) { + @media not ( prefers-reduced-motion ) { &.is-animation-enabled::after { - transition-property: left, top, width, height; + transition-property: transform; transition-duration: 0.2s; transition-timing-function: ease-out; } } + --direction-factor: 1; + --direction-origin-x: left; + --indicator-start: var( --indicator-left ); + &:dir( rtl ) { + --direction-factor: -1; + --direction-origin-x: right; + --indicator-start: var( --indicator-right ); + } &::after { content: ''; position: absolute; pointer-events: none; + transform-origin: var( --direction-origin-x ) top; // Windows high contrast mode. outline: 2px solid transparent; outline-offset: -1px; } - &:not( [aria-orientation='vertical'] )::after { - bottom: 0; - left: var( --indicator-left ); - width: var( --indicator-width ); - height: 0; - border-bottom: var( --wp-admin-border-width-focus ) solid - ${ COLORS.theme.accent }; + + /* Using a large value to avoid antialiasing rounding issues + when scaling in the transform, see: https://stackoverflow.com/a/52159123 */ + --antialiasing-factor: 100; + &:not( [aria-orientation='vertical'] ) { + &::after { + bottom: 0; + height: 0; + width: calc( var( --antialiasing-factor ) * 1px ); + transform: translateX( + calc( + var( --indicator-start ) * var( --direction-factor ) * + 1px + ) + ) + scaleX( + calc( + var( --indicator-width ) / var( --antialiasing-factor ) + ) + ); + border-bottom: var( --wp-admin-border-width-focus ) solid + ${ COLORS.theme.accent }; + } } &[aria-orientation='vertical']::after { z-index: -1; + top: 0; left: 0; width: 100%; - top: var( --indicator-top ); - height: var( --indicator-height ); + width: calc( var( --antialiasing-factor ) * 1px ); + transform: translateY( calc( var( --indicator-top ) * 1px ) ) + scaleY( + calc( var( --indicator-height ) / var( --antialiasing-factor ) ) + ); background-color: ${ COLORS.theme.gray[ 100 ] }; } `; diff --git a/packages/components/src/tabs/tablist.tsx b/packages/components/src/tabs/tablist.tsx index 80ed9b4c5bea2f..2977d6a6283708 100644 --- a/packages/components/src/tabs/tablist.tsx +++ b/packages/components/src/tabs/tablist.tsx @@ -78,10 +78,11 @@ export const TabList = forwardRef< onBlur={ onBlur } { ...otherProps } style={ { - '--indicator-left': `${ indicatorPosition.left }px`, - '--indicator-top': `${ indicatorPosition.top }px`, - '--indicator-width': `${ indicatorPosition.width }px`, - '--indicator-height': `${ indicatorPosition.height }px`, + '--indicator-top': indicatorPosition.top, + '--indicator-right': indicatorPosition.right, + '--indicator-left': indicatorPosition.left, + '--indicator-width': indicatorPosition.width, + '--indicator-height': indicatorPosition.height, ...otherProps.style, } } className={ clsx( diff --git a/packages/components/src/utils/element-rect.ts b/packages/components/src/utils/element-rect.ts index 9f6eb120b32fc5..550ec35b0bc932 100644 --- a/packages/components/src/utils/element-rect.ts +++ b/packages/components/src/utils/element-rect.ts @@ -2,134 +2,37 @@ /** * WordPress dependencies */ -import { useRef, useEffect, useState } from '@wordpress/element'; +import { useLayoutEffect, useRef, useState } from '@wordpress/element'; +import { useResizeObserver } from '@wordpress/compose'; /** * Internal dependencies */ import { useEvent } from './hooks/use-event'; /** - * `useTrackElementRectUpdates` options. + * The position and dimensions of an element, relative to its offset parent. */ -export type UseTrackElementRectUpdatesOptions = { +export type ElementOffsetRect = { /** - * Whether to trigger the callback when an element's ResizeObserver is - * first set up, including when the target element changes. - * - * @default true + * The distance from the top edge of the offset parent to the top edge of + * the element. */ - fireOnElementInit?: boolean; -}; - -/** - * Tracks an element's "rect" (size and position) and fires `onRect` for all - * of its discrete values. The element can be changed dynamically and **it - * must not be stored in a ref**. Instead, it should be stored in a React - * state or equivalent. - * - * By default, `onRect` is called initially for the target element (including - * when the target element changes), not only on size or position updates. - * This allows consumers of the hook to always be in sync with all rect values - * of the target element throughout its lifetime. This behavior can be - * disabled by setting the `fireOnElementInit` option to `false`. - * - * Under the hood, it sets up a `ResizeObserver` that tracks the element. The - * target element can be changed dynamically, and the observer will be - * updated accordingly. - * - * @example - * - * ```tsx - * const [ targetElement, setTargetElement ] = useState< HTMLElement | null >(); - * - * useTrackElementRectUpdates( targetElement, ( element ) => { - * console.log( 'Element resized:', element ); - * } ); - * - * <div ref={ setTargetElement } />; - * ``` - */ -export function useTrackElementRectUpdates( + top: number; /** - * The target element to observe. It can be changed dynamically. + * The distance from the right edge of the offset parent to the right edge + * of the element. */ - targetElement: HTMLElement | undefined | null, + right: number; /** - * Callback to fire when the element is resized. It will also be - * called when the observer is set up, unless `fireOnElementInit` is - * set to `false`. + * The distance from the bottom edge of the offset parent to the bottom edge + * of the element. */ - onRect: ( - /** - * The element being tracked at the time of this update. - */ - element: HTMLElement, - /** - * The list of - * [`ResizeObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry) - * objects passed to the `ResizeObserver.observe` callback. This list - * won't be available when the observer is set up, and only on updates. - */ - resizeObserverEntries?: ResizeObserverEntry[] - ) => void, - { fireOnElementInit = true }: UseTrackElementRectUpdatesOptions = {} -) { - const onRectEvent = useEvent( onRect ); - - const observedElementRef = useRef< HTMLElement | null >(); - const resizeObserverRef = useRef< ResizeObserver >(); - - // TODO: could this be a layout effect? - useEffect( () => { - if ( targetElement === observedElementRef.current ) { - return; - } - - observedElementRef.current = targetElement; - - // Set up a ResizeObserver. - if ( ! resizeObserverRef.current ) { - resizeObserverRef.current = new ResizeObserver( ( entries ) => { - if ( observedElementRef.current ) { - onRectEvent( observedElementRef.current, entries ); - } - } ); - } - const { current: resizeObserver } = resizeObserverRef; - - // Observe new element. - if ( targetElement ) { - if ( fireOnElementInit ) { - // TODO: investigate if this can be removed, - // see: https://stackoverflow.com/a/60026394 - onRectEvent( targetElement ); - } - resizeObserver.observe( targetElement ); - } - - return () => { - // Unobserve previous element. - if ( observedElementRef.current ) { - resizeObserver.unobserve( observedElementRef.current ); - } - }; - }, [ fireOnElementInit, onRectEvent, targetElement ] ); -} - -/** - * The position and dimensions of an element, relative to its offset parent. - */ -export type ElementOffsetRect = { + bottom: number; /** * The distance from the left edge of the offset parent to the left edge of * the element. */ left: number; - /** - * The distance from the top edge of the offset parent to the top edge of - * the element. - */ - top: number; /** * The width of the element. */ @@ -144,51 +47,111 @@ export type ElementOffsetRect = { * An `ElementOffsetRect` object with all values set to zero. */ export const NULL_ELEMENT_OFFSET_RECT = { - left: 0, top: 0, + right: 0, + bottom: 0, + left: 0, width: 0, height: 0, } satisfies ElementOffsetRect; /** * Returns the position and dimensions of an element, relative to its offset - * parent. This is useful in contexts where `getBoundingClientRect` is not - * suitable, such as when the element is transformed. + * parent, with subpixel precision. Values reflect the real measures before any + * potential scaling distortions along the X and Y axes. * - * **Note:** the `left` and `right` values are adjusted due to a limitation - * in the way the browser calculates the offset position of the element, - * which can cause unwanted scrollbars to appear. This adjustment makes the - * values potentially inaccurate within a range of 1 pixel. + * Useful in contexts where plain `getBoundingClientRect` calls or `ResizeObserver` + * entries are not suitable, such as when the element is transformed, and when + * `element.offset<Top|Left|Width|Height>` methods are not precise enough. + * + * **Note:** in some contexts, like when the scale is 0, this method will fail + * because it's impossible to calculate a scaling ratio. When that happens, it + * will return `undefined`. */ export function getElementOffsetRect( element: HTMLElement -): ElementOffsetRect { +): ElementOffsetRect | undefined { + // Position and dimension values computed with `getBoundingClientRect` have + // subpixel precision, but are affected by distortions since they represent + // the "real" measures, or in other words, the actual final values as rendered + // by the browser. + const rect = element.getBoundingClientRect(); + if ( rect.width === 0 || rect.height === 0 ) { + return; + } + const offsetParentRect = + element.offsetParent?.getBoundingClientRect() ?? + NULL_ELEMENT_OFFSET_RECT; + + // Computed widths and heights have subpixel precision, and are not affected + // by distortions. + const computedWidth = parseFloat( getComputedStyle( element ).width ); + const computedHeight = parseFloat( getComputedStyle( element ).height ); + + // We can obtain the current scale factor for the element by comparing "computed" + // dimensions with the "real" ones. + const scaleX = computedWidth / rect.width; + const scaleY = computedHeight / rect.height; + return { - // The adjustments mentioned in the documentation above are necessary - // because `offsetLeft` and `offsetTop` are rounded to the nearest pixel, - // which can result in a position mismatch that causes unwanted overflow. - // For context, see: https://github.com/WordPress/gutenberg/pull/61979 - left: Math.max( element.offsetLeft - 1, 0 ), - top: Math.max( element.offsetTop - 1, 0 ), - // This is a workaround to obtain these values with a sub-pixel precision, - // since `offsetWidth` and `offsetHeight` are rounded to the nearest pixel. - width: parseFloat( getComputedStyle( element ).width ), - height: parseFloat( getComputedStyle( element ).height ), + // To obtain the adjusted values for the position: + // 1. Compute the element's position relative to the offset parent. + // 2. Correct for the scale factor. + top: ( rect.top - offsetParentRect?.top ) * scaleY, + right: ( offsetParentRect?.right - rect.right ) * scaleX, + bottom: ( offsetParentRect?.bottom - rect.bottom ) * scaleY, + left: ( rect.left - offsetParentRect?.left ) * scaleX, + // Computed dimensions don't need any adjustments. + width: computedWidth, + height: computedHeight, }; } +const POLL_RATE = 100; + /** * Tracks the position and dimensions of an element, relative to its offset * parent. The element can be changed dynamically. + * + * **Note:** sometimes, the measurement will fail (see `getElementOffsetRect`'s + * documentation for more details). When that happens, this hook will attempt + * to measure again after a frame, and if that fails, it will poll every 100 + * milliseconds until it succeeds. */ export function useTrackElementOffsetRect( targetElement: HTMLElement | undefined | null ) { const [ indicatorPosition, setIndicatorPosition ] = useState< ElementOffsetRect >( NULL_ELEMENT_OFFSET_RECT ); + const intervalRef = useRef< ReturnType< typeof setInterval > >(); + + const measure = useEvent( () => { + if ( targetElement ) { + const elementOffsetRect = getElementOffsetRect( targetElement ); + if ( elementOffsetRect ) { + setIndicatorPosition( elementOffsetRect ); + clearInterval( intervalRef.current ); + return true; + } + } else { + clearInterval( intervalRef.current ); + } + return false; + } ); + + const setElement = useResizeObserver( () => { + if ( ! measure() ) { + requestAnimationFrame( () => { + if ( ! measure() ) { + intervalRef.current = setInterval( measure, POLL_RATE ); + } + } ); + } + } ); - useTrackElementRectUpdates( targetElement, ( element ) => - setIndicatorPosition( getElementOffsetRect( element ) ) + useLayoutEffect( + () => setElement( targetElement ), + [ setElement, targetElement ] ); return indicatorPosition; From f1aa523c9d2349dcf3315464b30b659178a0677e Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Wed, 11 Sep 2024 12:36:16 -0500 Subject: [PATCH 0763/1908] Fix Content Only Toolbar icon focus style (#64940) Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- .../src/components/block-switcher/style.scss | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/packages/block-editor/src/components/block-switcher/style.scss b/packages/block-editor/src/components/block-switcher/style.scss index 823a656668a621..3dc2a7d591c926 100644 --- a/packages/block-editor/src/components/block-switcher/style.scss +++ b/packages/block-editor/src/components/block-switcher/style.scss @@ -55,30 +55,6 @@ } } -// Style this the same as the block buttons in the library. -// Needs specificity to override the icon button. -.block-editor-block-toolbar .components-toolbar-group .components-button.block-editor-block-switcher__no-switcher-icon.has-icon.has-icon, -.block-editor-block-toolbar .components-toolbar .components-button.block-editor-block-switcher__no-switcher-icon.has-icon.has-icon, -.block-editor-block-toolbar .components-toolbar-group .components-button.block-editor-block-switcher__toggle.has-icon.has-icon, -.block-editor-block-toolbar .components-toolbar .components-button.block-editor-block-switcher__toggle.has-icon.has-icon { - .block-editor-block-icon { - height: 100%; - position: relative; - margin: 0 auto; - display: flex; - align-items: center; - min-width: 100%; - } - - // Position the focus style correctly. - &::before { - top: $grid-unit-10; - right: $grid-unit-10; - bottom: $grid-unit-10; - left: $grid-unit-10; - } -} - .components-popover.block-editor-block-switcher__popover .components-popover__content { min-width: 300px; } From a15a93d373ad6008d1af56725b7fa4b736561002 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 12 Sep 2024 03:08:25 +0900 Subject: [PATCH 0764/1908] Remove colons from control labels (#65205) * Remove colons from control labels in docs * Remove label colon from Archives block * Remove label colon in Latest Posts block * Fix label in Legacy Widget block * Shorten to "Legacy widget" and update test Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- docs/reference-guides/block-api/block-context.md | 2 +- packages/block-library/src/archives/edit.js | 2 +- packages/block-library/src/latest-posts/edit.js | 2 +- packages/components/src/select-control/README.md | 4 ++-- .../src/blocks/legacy-widget/edit/widget-type-selector.js | 2 +- test/e2e/specs/widgets/customizing-widgets.spec.js | 4 +--- 6 files changed, 7 insertions(+), 9 deletions(-) diff --git a/docs/reference-guides/block-api/block-context.md b/docs/reference-guides/block-api/block-context.md index 5fdc670fe60403..09c33dfb71b7c3 100644 --- a/docs/reference-guides/block-api/block-context.md +++ b/docs/reference-guides/block-api/block-context.md @@ -141,7 +141,7 @@ export default function Edit( props ) { return ( <div> <TextControl - label={ __( 'Record ID:' ) } + label={ __( 'Record ID' ) } value={ recordId } onChange={ ( val ) => setAttributes( { recordId: Number( val ) } ) diff --git a/packages/block-library/src/archives/edit.js b/packages/block-library/src/archives/edit.js index ee9bf60fb77ec0..60b8715988ed94 100644 --- a/packages/block-library/src/archives/edit.js +++ b/packages/block-library/src/archives/edit.js @@ -53,7 +53,7 @@ export default function ArchivesEdit( { attributes, setAttributes } ) { <SelectControl __next40pxDefaultSize __nextHasNoMarginBottom - label={ __( 'Group by:' ) } + label={ __( 'Group by' ) } options={ [ { label: __( 'Year' ), value: 'yearly' }, { label: __( 'Month' ), value: 'monthly' }, diff --git a/packages/block-library/src/latest-posts/edit.js b/packages/block-library/src/latest-posts/edit.js index b02747bb1c1d8e..ab792ae0e353db 100644 --- a/packages/block-library/src/latest-posts/edit.js +++ b/packages/block-library/src/latest-posts/edit.js @@ -243,7 +243,7 @@ export default function LatestPostsEdit( { attributes, setAttributes } ) { { displayPostContent && ( <RadioControl className="wp-block-latest-posts__post-content-radio" - label={ __( 'Show:' ) } + label={ __( 'Show' ) } selected={ displayPostContentRadio } options={ [ { label: __( 'Excerpt' ), value: 'excerpt' }, diff --git a/packages/components/src/select-control/README.md b/packages/components/src/select-control/README.md index 6c3ecda886a188..c240243408fab3 100644 --- a/packages/components/src/select-control/README.md +++ b/packages/components/src/select-control/README.md @@ -103,7 +103,7 @@ Render a user interface to select multiple users from a list. ```jsx <SelectControl multiple - label={ __( 'Select some users:' ) } + label={ __( 'User' ) } value={ this.state.users } // e.g: value = [ 'a', 'c' ] onChange={ ( users ) => { this.setState( { users } ); @@ -126,7 +126,7 @@ const [ item, setItem ] = useState( '' ); // ... <SelectControl - label={ __( 'Select an item:' ) } + label={ __( 'My dinosaur' ) } value={ item } // e.g: value = 'a' onChange={ ( selection ) => { setItem( selection ) } } __nextHasNoMarginBottom diff --git a/packages/widgets/src/blocks/legacy-widget/edit/widget-type-selector.js b/packages/widgets/src/blocks/legacy-widget/edit/widget-type-selector.js index d543b7b4b08d80..432588f6aea85f 100644 --- a/packages/widgets/src/blocks/legacy-widget/edit/widget-type-selector.js +++ b/packages/widgets/src/blocks/legacy-widget/edit/widget-type-selector.js @@ -29,7 +29,7 @@ export default function WidgetTypeSelector( { selectedId, onSelect } ) { <SelectControl __next40pxDefaultSize __nextHasNoMarginBottom - label={ __( 'Select a legacy widget to display:' ) } + label={ __( 'Legacy widget' ) } value={ selectedId ?? '' } options={ [ { value: '', label: __( 'Select widget' ) }, diff --git a/test/e2e/specs/widgets/customizing-widgets.spec.js b/test/e2e/specs/widgets/customizing-widgets.spec.js index 34400ea00976e2..53b4da7be2d61f 100644 --- a/test/e2e/specs/widgets/customizing-widgets.spec.js +++ b/test/e2e/specs/widgets/customizing-widgets.spec.js @@ -358,9 +358,7 @@ test.describe( 'Widgets Customizer', () => { const legacyWidgetBlock = await widgetsCustomizerPage.addBlock( 'Legacy Widget' ); await page - .locator( - 'role=combobox[name="Select a legacy widget to display:"i]' - ) + .locator( 'role=combobox[name="Legacy widget"i]' ) .selectOption( 'test_widget' ); await expect( From 8a7df39e11758aade23c586b435830a5d35aa5f2 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Wed, 11 Sep 2024 20:13:48 +0200 Subject: [PATCH 0765/1908] Fix: Moving the last page item to the the trash causes a crash. (#65236) co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/dataviews/src/dataviews-layouts/list/index.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/dataviews/src/dataviews-layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx index 8a3f6a297338c8..fb46521fe217b7 100644 --- a/packages/dataviews/src/dataviews-layouts/list/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/list/index.tsx @@ -395,6 +395,9 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) { data.length - 1, Math.max( 0, targetIndex ) ); + if ( ! data[ clampedIndex ] ) { + return; + } const itemIdPrefix = generateCompositeItemIdPrefix( data[ clampedIndex ] ); From 8a74d31f28e4d5ddc6f21be1bc2134e675d2913f Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 12 Sep 2024 06:14:31 +0900 Subject: [PATCH 0766/1908] Normalize block inspector controls spacing (#64526) * Try block inspector controls spacing normalization * Decrease specificity * Add changelog * Grid block: Fix when experimental grid interactivity * Remove adjustment for bottom padding * Revert "Add changelog" This reverts commit 7939750f87b2d35d3f54deab4c8c91df5d49e2c8. * Remove unnecessary margin on Layout hook toggle (#65133) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/block-inspector/style.scss | 6 ++-- packages/block-editor/src/hooks/layout.js | 1 - packages/block-editor/src/hooks/layout.scss | 4 --- packages/block-editor/src/layouts/grid.js | 29 ++++++++++--------- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/packages/block-editor/src/components/block-inspector/style.scss b/packages/block-editor/src/components/block-inspector/style.scss index cf7131722722c1..bdbf3660d9619e 100644 --- a/packages/block-editor/src/components/block-inspector/style.scss +++ b/packages/block-editor/src/components/block-inspector/style.scss @@ -11,10 +11,8 @@ } .components-base-control { - margin-bottom: #{ $grid-unit-30 }; - - &:last-child { - margin-bottom: $grid-unit-10; + &:where(:not(:last-child)) { + margin-bottom: $grid-unit-20; } } diff --git a/packages/block-editor/src/hooks/layout.js b/packages/block-editor/src/hooks/layout.js index 2ea8c5f37c9e77..22d916d7b791bf 100644 --- a/packages/block-editor/src/hooks/layout.js +++ b/packages/block-editor/src/hooks/layout.js @@ -233,7 +233,6 @@ function LayoutPanelPure( { <> <ToggleControl __nextHasNoMarginBottom - className="block-editor-hooks__toggle-control" label={ __( 'Inner blocks use content width' ) } checked={ layoutType?.name === 'constrained' || diff --git a/packages/block-editor/src/hooks/layout.scss b/packages/block-editor/src/hooks/layout.scss index 0ce3bc0577640f..400b09490bbe51 100644 --- a/packages/block-editor/src/hooks/layout.scss +++ b/packages/block-editor/src/hooks/layout.scss @@ -17,7 +17,3 @@ margin-bottom: $grid-unit-10; } } - -.block-editor-hooks__toggle-control.block-editor-hooks__toggle-control { - margin-bottom: $grid-unit-20; -} diff --git a/packages/block-editor/src/layouts/grid.js b/packages/block-editor/src/layouts/grid.js index d1f6fdd785089b..f1573b5c949603 100644 --- a/packages/block-editor/src/layouts/grid.js +++ b/packages/block-editor/src/layouts/grid.js @@ -13,6 +13,7 @@ import { __experimentalToggleGroupControlOption as ToggleGroupControlOption, __experimentalUnitControl as UnitControl, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, + __experimentalVStack as VStack, } from '@wordpress/components'; import { useState } from '@wordpress/element'; @@ -85,19 +86,21 @@ export default { layout={ layout } onChange={ onChange } /> - { showColumnsControl && ( - <GridLayoutColumnsAndRowsControl - layout={ layout } - onChange={ onChange } - allowSizingOnChildren={ allowSizingOnChildren } - /> - ) } - { showMinWidthControl && ( - <GridLayoutMinimumWidthControl - layout={ layout } - onChange={ onChange } - /> - ) } + <VStack spacing={ 4 }> + { showColumnsControl && ( + <GridLayoutColumnsAndRowsControl + layout={ layout } + onChange={ onChange } + allowSizingOnChildren={ allowSizingOnChildren } + /> + ) } + { showMinWidthControl && ( + <GridLayoutMinimumWidthControl + layout={ layout } + onChange={ onChange } + /> + ) } + </VStack> </> ); }, From d5ab90aada146ecbb1249fa493543358779f3f29 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 11 Sep 2024 23:22:17 +0000 Subject: [PATCH 0767/1908] Bump plugin version to 19.2.0 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 117f4168524d8a..c9c6e09a8092bf 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.2.0-rc.1 + * Version: 19.2.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 5f393e700c2892..c10f94d37dc8ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.2.0-rc.1", + "version": "19.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.2.0-rc.1", + "version": "19.2.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 9236dbfb47adee..29e5f10b6f7a50 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.2.0-rc.1", + "version": "19.2.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From e9d31c255ce0dbf20d5ed0b6484ec74813393521 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 11 Sep 2024 23:46:14 +0000 Subject: [PATCH 0768/1908] Update Changelog for 19.2.0 --- changelog.txt | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index dc0a2487f725ff..b0e6c8e907582e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,6 @@ == Changelog == -= 19.2.0-rc.1 = - += 19.2.0 = ## Changelog @@ -40,6 +39,12 @@ - Rely on `Text` component instead of `Truncate` in bindings panel. ([65007](https://github.com/WordPress/gutenberg/pull/65007)) - Remove `getPlaceholder` API and rely on `key` argument or source label. ([64910](https://github.com/WordPress/gutenberg/pull/64910)) +#### Data Views +- Add: Reorder control at the field level on the new view configuration UI. ([64381](https://github.com/WordPress/gutenberg/pull/64381)) +- Dataviews Filter search widget: Do not use Composite store. ([64985](https://github.com/WordPress/gutenberg/pull/64985)) +- Dataviews list view: Do not use Composite store. ([64987](https://github.com/WordPress/gutenberg/pull/64987)) +- Move bulk actions menu to the Footer, consolidate with floating toolbar and total items display. ([64268](https://github.com/WordPress/gutenberg/pull/64268)) + #### Block Editor - Add 'Reset' option to MediaReplaceFlow component. ([64826](https://github.com/WordPress/gutenberg/pull/64826)) - Block Patterns List: Do not use Composite store. ([64983](https://github.com/WordPress/gutenberg/pull/64983)) @@ -106,12 +111,14 @@ - Add safeguard to `mediaUploadMiddleware`. ([64843](https://github.com/WordPress/gutenberg/pull/64843)) - Allow multi-select on iOS Safari/touch devices. ([63671](https://github.com/WordPress/gutenberg/pull/63671)) +- Core Data: Fix the 'query._fields' property check inside 'getEntityRecord' resolver. ([65079](https://github.com/WordPress/gutenberg/pull/65079)) - Fix Modify content-locked menu item not showing if the block is not selected. ([61605](https://github.com/WordPress/gutenberg/pull/61605)) - Fix editor error in Safari due to availability of checkVisibility method. ([65069](https://github.com/WordPress/gutenberg/pull/65069)) - Fix: Pagination arrows are pointing in the wrong direction in RTL languages. ([64962](https://github.com/WordPress/gutenberg/pull/64962)) - Footnotes: Only replace attribute if footnotes were detected. ([63935](https://github.com/WordPress/gutenberg/pull/63935)) - Paste: Fix image paste from Google Forms. ([64502](https://github.com/WordPress/gutenberg/pull/64502)) - Revert Focus pattern inserter search when activating zoom out inserter. ([64748](https://github.com/WordPress/gutenberg/pull/64748)) +- Try: Update block warnings. ([64997](https://github.com/WordPress/gutenberg/pull/64997)) #### Block Library - De-duplicate block toolbar icons for patterns. ([65054](https://github.com/WordPress/gutenberg/pull/65054)) @@ -175,6 +182,9 @@ #### Site Editor - DataViews: Fix pattern title direction in RTL languages. ([64967](https://github.com/WordPress/gutenberg/pull/64967)) +#### Typography +- Site Title, Post Title: Fix typography for blocks with `a` children. ([64911](https://github.com/WordPress/gutenberg/pull/64911)) + #### NUX - Fix visibility of the template Welcome Guide in the Site Editor. ([64789](https://github.com/WordPress/gutenberg/pull/64789)) @@ -223,6 +233,9 @@ - Add 'OPTIONS /page' to preloaded paths. ([64890](https://github.com/WordPress/gutenberg/pull/64890)) - Editor: Don't use selector shortcuts for the Site data. ([64884](https://github.com/WordPress/gutenberg/pull/64884)) +#### Interactivity API +- Prevent calling `proxifyContext` with context proxies inside `wp-context`. ([65090](https://github.com/WordPress/gutenberg/pull/65090)) + #### Block Library - Media & Text: Don't use background-image. ([64981](https://github.com/WordPress/gutenberg/pull/64981)) @@ -353,7 +366,7 @@ The following PRs were merged by first-time contributors: The following contributors merged PRs in this release: -@aaronrobertshaw @afercia @akasunil @Aljullu @andrewserong @atachibana @benoitchantre @carolinan @cbravobernal @ciampo @DAreRodz @dcalhoun @desrosj @dsas @ellatrix @fullofcaffeine @getdave @gziolo @Imran92 @imrraaj @jacobcassidy @jameskoster @jasmussen @jawadmalikdev @jeryj @jorgefilipecosta @jsnajdr @juanmaguitar @kevin940726 @lezama @Mamaduka @matiasbenedetto @mirka @noisysocks @ntsekouras @oandregal @ockham @ramonjd @richtabor @rithik56 @rohitmathur-7 @ryanwelcher @SantosGuillamot @scruffian @sgomes @shail-mehta @spacedmonkey @stokesman @swissspidy @t-hamano @talldan @tjcafferkey @tyxla +@aaronrobertshaw @afercia @akasunil @Aljullu @andrewserong @atachibana @benoitchantre @carolinan @cbravobernal @ciampo @DAreRodz @dcalhoun @desrosj @dsas @ellatrix @fullofcaffeine @getdave @gziolo @Imran92 @imrraaj @jacobcassidy @jameskoster @jasmussen @jawadmalikdev @jeryj @jorgefilipecosta @jsnajdr @juanmaguitar @kevin940726 @lezama @Mamaduka @matiasbenedetto @mirka @noisysocks @ntsekouras @oandregal @ockham @rafaelgallani @ramonjd @richtabor @rithik56 @rohitmathur-7 @ryanwelcher @SantosGuillamot @scruffian @sgomes @shail-mehta @spacedmonkey @stokesman @swissspidy @t-hamano @talldan @tjcafferkey @tyxla = 19.1.0 = From f073eb1f9f3b900ca347c7c8132fc7646f1bfaea Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Thu, 12 Sep 2024 10:07:56 +0530 Subject: [PATCH 0769/1908] Add the spacing for horizontal and vertical for block gap on buttons block (#64971) Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: AKSHAT2802 <akshat2802@git.wordpress.org> Co-authored-by: Nyiriland <nyiriland@git.wordpress.org> --- packages/block-library/src/buttons/block.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/buttons/block.json b/packages/block-library/src/buttons/block.json index 220f6ef8fd1e27..bb4c370158ad5b 100644 --- a/packages/block-library/src/buttons/block.json +++ b/packages/block-library/src/buttons/block.json @@ -21,7 +21,7 @@ } }, "spacing": { - "blockGap": true, + "blockGap": [ "horizontal", "vertical" ], "padding": true, "margin": [ "top", "bottom" ], "__experimentalDefaultControls": { From f1403c4a925ac4df875259f41a71a9f97a8e2dca Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 12 Sep 2024 11:59:30 +0400 Subject: [PATCH 0770/1908] Plugin: Remove 'function_exists' checks for methods with 'gutenberg' prefix (#65260) * Plugin: Remove 'function_exists' checks for methods with 'gutenberg' prefix * Move code into the correct compat file Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- lib/compat/wordpress-6.6/rest-api.php | 160 ++++++++++++++++---------- lib/experimental/blocks.php | 57 +++++---- lib/rest-api.php | 62 ++-------- 3 files changed, 134 insertions(+), 145 deletions(-) diff --git a/lib/compat/wordpress-6.6/rest-api.php b/lib/compat/wordpress-6.6/rest-api.php index fee9c71b86c070..eadd3b1d376a72 100644 --- a/lib/compat/wordpress-6.6/rest-api.php +++ b/lib/compat/wordpress-6.6/rest-api.php @@ -88,76 +88,116 @@ function gutenberg_register_global_styles_revisions_endpoints() { add_action( 'rest_api_init', 'gutenberg_register_global_styles_revisions_endpoints' ); -if ( ! function_exists( 'gutenberg_register_wp_rest_themes_stylesheet_directory_uri_field' ) ) { - /** - * Adds `stylesheet_uri` fields to WP_REST_Themes_Controller class. - */ - function gutenberg_register_wp_rest_themes_stylesheet_directory_uri_field() { - register_rest_field( - 'theme', - 'stylesheet_uri', - array( - 'get_callback' => function ( $item ) { - if ( ! empty( $item['stylesheet'] ) ) { - $theme = wp_get_theme( $item['stylesheet'] ); - $current_theme = wp_get_theme(); - if ( $theme->get_stylesheet() === $current_theme->get_stylesheet() ) { - return get_stylesheet_directory_uri(); - } else { - return $theme->get_stylesheet_directory_uri(); - } +/** + * Adds `stylesheet_uri` fields to WP_REST_Themes_Controller class. + */ +function gutenberg_register_wp_rest_themes_stylesheet_directory_uri_field() { + register_rest_field( + 'theme', + 'stylesheet_uri', + array( + 'get_callback' => function ( $item ) { + if ( ! empty( $item['stylesheet'] ) ) { + $theme = wp_get_theme( $item['stylesheet'] ); + $current_theme = wp_get_theme(); + if ( $theme->get_stylesheet() === $current_theme->get_stylesheet() ) { + return get_stylesheet_directory_uri(); + } else { + return $theme->get_stylesheet_directory_uri(); } + } - return null; - }, - 'schema' => array( - 'type' => 'string', - 'description' => __( 'The uri for the theme\'s stylesheet directory.', 'gutenberg' ), - 'format' => 'uri', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - ) - ); - } + return null; + }, + 'schema' => array( + 'type' => 'string', + 'description' => __( 'The uri for the theme\'s stylesheet directory.', 'gutenberg' ), + 'format' => 'uri', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + ) + ); } add_action( 'rest_api_init', 'gutenberg_register_wp_rest_themes_stylesheet_directory_uri_field' ); -if ( ! function_exists( 'gutenberg_register_wp_rest_themes_template_directory_uri_field' ) ) { - /** - * Adds `template_uri` fields to WP_REST_Themes_Controller class. - */ - function gutenberg_register_wp_rest_themes_template_directory_uri_field() { - register_rest_field( - 'theme', - 'template_uri', - array( - 'get_callback' => function ( $item ) { - if ( ! empty( $item['stylesheet'] ) ) { - $theme = wp_get_theme( $item['stylesheet'] ); - $current_theme = wp_get_theme(); - if ( $theme->get_stylesheet() === $current_theme->get_stylesheet() ) { - return get_template_directory_uri(); - } else { - return $theme->get_template_directory_uri(); - } +/** + * Adds `template_uri` fields to WP_REST_Themes_Controller class. + */ +function gutenberg_register_wp_rest_themes_template_directory_uri_field() { + register_rest_field( + 'theme', + 'template_uri', + array( + 'get_callback' => function ( $item ) { + if ( ! empty( $item['stylesheet'] ) ) { + $theme = wp_get_theme( $item['stylesheet'] ); + $current_theme = wp_get_theme(); + if ( $theme->get_stylesheet() === $current_theme->get_stylesheet() ) { + return get_template_directory_uri(); + } else { + return $theme->get_template_directory_uri(); } + } - return null; - }, - 'schema' => array( - 'type' => 'string', - 'description' => __( 'The uri for the theme\'s template directory. If this is a child theme, this refers to the parent theme, otherwise this is the same as the theme\'s stylesheet directory.', 'gutenberg' ), - 'format' => 'uri', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - ) - ); - } + return null; + }, + 'schema' => array( + 'type' => 'string', + 'description' => __( 'The uri for the theme\'s template directory. If this is a child theme, this refers to the parent theme, otherwise this is the same as the theme\'s stylesheet directory.', 'gutenberg' ), + 'format' => 'uri', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + ) + ); } add_action( 'rest_api_init', 'gutenberg_register_wp_rest_themes_template_directory_uri_field' ); +/** + * Adds `template` and `template_lock` fields to WP_REST_Post_Types_Controller class. + */ +function gutenberg_register_wp_rest_post_types_controller_fields() { + register_rest_field( + 'type', + 'template', + array( + 'get_callback' => function ( $item ) { + $post_type = get_post_type_object( $item['slug'] ); + if ( ! empty( $post_type ) ) { + return $post_type->template ?? array(); + } + }, + 'schema' => array( + 'type' => 'array', + 'description' => __( 'The block template associated with the post type.', 'gutenberg' ), + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + ) + ); + register_rest_field( + 'type', + 'template_lock', + array( + 'get_callback' => function ( $item ) { + $post_type = get_post_type_object( $item['slug'] ); + if ( ! empty( $post_type ) ) { + return ! empty( $post_type->template_lock ) ? $post_type->template_lock : false; + } + }, + 'schema' => array( + 'type' => array( 'string', 'boolean' ), + 'enum' => array( 'all', 'insert', 'contentOnly', false ), + 'description' => __( 'The template_lock associated with the post type, or false if none.', 'gutenberg' ), + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + ) + ); +} +add_action( 'rest_api_init', 'gutenberg_register_wp_rest_post_types_controller_fields' ); + /** * Preload theme and global styles paths to avoid flash of variation styles in post editor. * diff --git a/lib/experimental/blocks.php b/lib/experimental/blocks.php index bfe57c26b3ecab..68113276ec1c06 100644 --- a/lib/experimental/blocks.php +++ b/lib/experimental/blocks.php @@ -78,45 +78,42 @@ function wp_enqueue_block_view_script( $block_name, $args ) { } } -/* +/** + * Registers a new block style for one or more block types. + * * WP_Block_Styles_Registry was marked as `final` in core so it cannot be * updated via Gutenberg to allow registration of a style across multiple * block types as well as with an optional style object. This function will * support the desired functionality until the styles registry can be updated * in core. + * + * @param string|array $block_name Block type name including namespace or array of namespaced block type names. + * @param array $style_properties Array containing the properties of the style name, label, + * style_handle (name of the stylesheet to be enqueued), + * inline_style (string containing the CSS to be added), + * style_data (theme.json-like object to generate CSS from). + * + * @return bool True if all block styles were registered with success and false otherwise. */ -if ( ! function_exists( 'gutenberg_register_block_style' ) ) { - /** - * Registers a new block style for one or more block types. - * - * @param string|array $block_name Block type name including namespace or array of namespaced block type names. - * @param array $style_properties Array containing the properties of the style name, label, - * style_handle (name of the stylesheet to be enqueued), - * inline_style (string containing the CSS to be added), - * style_data (theme.json-like object to generate CSS from). - * - * @return bool True if all block styles were registered with success and false otherwise. - */ - function gutenberg_register_block_style( $block_name, $style_properties ) { - if ( ! is_string( $block_name ) && ! is_array( $block_name ) ) { - _doing_it_wrong( - __METHOD__, - __( 'Block name must be a string or array.', 'gutenberg' ), - '6.6.0' - ); +function gutenberg_register_block_style( $block_name, $style_properties ) { + if ( ! is_string( $block_name ) && ! is_array( $block_name ) ) { + _doing_it_wrong( + __METHOD__, + __( 'Block name must be a string or array.', 'gutenberg' ), + '6.6.0' + ); - return false; - } + return false; + } - $block_names = is_string( $block_name ) ? array( $block_name ) : $block_name; - $result = true; + $block_names = is_string( $block_name ) ? array( $block_name ) : $block_name; + $result = true; - foreach ( $block_names as $name ) { - if ( ! WP_Block_Styles_Registry::get_instance()->register( $name, $style_properties ) ) { - $result = false; - } + foreach ( $block_names as $name ) { + if ( ! WP_Block_Styles_Registry::get_instance()->register( $name, $style_properties ) ) { + $result = false; } - - return $result; } + + return $result; } diff --git a/lib/rest-api.php b/lib/rest-api.php index ea87f424637048..0becbc4a72d356 100644 --- a/lib/rest-api.php +++ b/lib/rest-api.php @@ -19,60 +19,12 @@ function gutenberg_register_global_styles_endpoints() { } add_action( 'rest_api_init', 'gutenberg_register_global_styles_endpoints' ); -if ( ! function_exists( 'gutenberg_register_edit_site_export_controller_endpoints' ) ) { - /** - * Registers the Edit Site Export REST API routes. - */ - function gutenberg_register_edit_site_export_controller_endpoints() { - $edit_site_export_controller = new WP_REST_Edit_Site_Export_Controller_Gutenberg(); - $edit_site_export_controller->register_routes(); - } -} - -add_action( 'rest_api_init', 'gutenberg_register_edit_site_export_controller_endpoints' ); -if ( ! function_exists( 'gutenberg_register_wp_rest_post_types_controller_fields' ) ) { - /** - * Adds `template` and `template_lock` fields to WP_REST_Post_Types_Controller class. - */ - function gutenberg_register_wp_rest_post_types_controller_fields() { - register_rest_field( - 'type', - 'template', - array( - 'get_callback' => function ( $item ) { - $post_type = get_post_type_object( $item['slug'] ); - if ( ! empty( $post_type ) ) { - return $post_type->template ?? array(); - } - }, - 'schema' => array( - 'type' => 'array', - 'description' => __( 'The block template associated with the post type.', 'gutenberg' ), - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - ) - ); - register_rest_field( - 'type', - 'template_lock', - array( - 'get_callback' => function ( $item ) { - $post_type = get_post_type_object( $item['slug'] ); - if ( ! empty( $post_type ) ) { - return ! empty( $post_type->template_lock ) ? $post_type->template_lock : false; - } - }, - 'schema' => array( - 'type' => array( 'string', 'boolean' ), - 'enum' => array( 'all', 'insert', 'contentOnly', false ), - 'description' => __( 'The template_lock associated with the post type, or false if none.', 'gutenberg' ), - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - ) - ); - } +/** + * Registers the Edit Site Export REST API routes. + */ +function gutenberg_register_edit_site_export_controller_endpoints() { + $edit_site_export_controller = new WP_REST_Edit_Site_Export_Controller_Gutenberg(); + $edit_site_export_controller->register_routes(); } -add_action( 'rest_api_init', 'gutenberg_register_wp_rest_post_types_controller_fields' ); +add_action( 'rest_api_init', 'gutenberg_register_edit_site_export_controller_endpoints' ); From d649865283aff3545f9754a01c92982e37602dc8 Mon Sep 17 00:00:00 2001 From: Mikey Binns <38146638+mikeybinns@users.noreply.github.com> Date: Thu, 12 Sep 2024 10:16:15 +0100 Subject: [PATCH 0771/1908] Scripts: Update stylelint dependency and the default config (#64828) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update stylelint deps to latest and convert deprecated rules to @stylistic * prevent extra rules being added * fix rule name change * fix scss overwrite bug * fix stylelint disables/enables * migrate stylistic styles to separate configs to make it easy to opt out for consumers * fix: switch stylistic config dep for plugin * use require.resolve for stylelint recommended config * fix stylelint unit tests * fix global mocks for node env * use correct configs for tests * add type checking for configs * convert tests to esm * remove unnecessary await * fix stylelint tests * remove experimental-vm-modules flag * revert jest globals changes * move utils to folder * update readme * update changelogs --------- Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> Unlinked contributors: 75th, vicobot-0815. Co-authored-by: mikeybinns <mikeybinns@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: jacobcassidy <jacobcassidy@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: paulschreiber <paulschreiber@git.wordpress.org> Co-authored-by: stein2nd <stein2nd@git.wordpress.org> --- .eslintrc.js | 6 + .stylelintrc.json | 6 +- package-lock.json | 1396 ++++++++++++----- packages/base-styles/_mixins.scss | 4 +- .../block-library/src/buttons/editor.scss | 4 +- packages/block-library/src/buttons/style.scss | 4 +- packages/scripts/CHANGELOG.md | 6 + packages/scripts/config/.stylelintrc.json | 2 +- packages/scripts/package.json | 2 +- packages/stylelint-config/CHANGELOG.md | 14 + packages/stylelint-config/README.md | 30 +- packages/stylelint-config/index.js | 70 +- packages/stylelint-config/package.json | 7 +- packages/stylelint-config/scss-stylistic.js | 16 + packages/stylelint-config/scss.js | 16 +- packages/stylelint-config/stylistic.js | 72 + .../stylelint-config/test/.stylelintignore | 1 + .../stylelint-config/test/.stylelintrc.json | 13 +- .../test/.stylelintrc.tests.json | 13 + .../test/__snapshots__/commenting.js.snap | 20 +- .../test/__snapshots__/functions.js.snap | 2 + .../test/__snapshots__/index.js.snap | 6 +- .../test/__snapshots__/media-queries.js.snap | 86 +- .../test/__snapshots__/properties.js.snap | 46 +- .../test/__snapshots__/scss.js.snap | 58 +- .../test/__snapshots__/selectors-scss.js.snap | 12 + .../test/__snapshots__/selectors.js.snap | 30 +- .../test/__snapshots__/structure.js.snap | 66 +- .../test/__snapshots__/values.js.snap | 28 +- packages/stylelint-config/test/commenting.js | 27 +- packages/stylelint-config/test/functions.js | 27 +- packages/stylelint-config/test/index.js | 27 +- .../test/media-queries-invalid.css | 2 +- .../stylelint-config/test/media-queries.js | 27 +- packages/stylelint-config/test/properties.js | 27 +- packages/stylelint-config/test/scss.js | 27 +- .../stylelint-config/test/selectors-scss.js | 27 +- packages/stylelint-config/test/selectors.js | 27 +- packages/stylelint-config/test/structure.js | 27 +- packages/stylelint-config/test/themes.js | 18 +- packages/stylelint-config/test/utils/index.js | 34 + packages/stylelint-config/test/values.js | 27 +- .../stylelint-config/test/vendor-prefixes.js | 18 +- 43 files changed, 1505 insertions(+), 873 deletions(-) create mode 100644 packages/stylelint-config/scss-stylistic.js create mode 100644 packages/stylelint-config/stylistic.js create mode 100644 packages/stylelint-config/test/.stylelintignore create mode 100644 packages/stylelint-config/test/.stylelintrc.tests.json create mode 100644 packages/stylelint-config/test/utils/index.js diff --git a/.eslintrc.js b/.eslintrc.js index caf01b7cbd71d4..b5349d2de0a1ff 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -216,6 +216,12 @@ module.exports = { }, ], 'no-restricted-syntax': [ 'error', ...restrictedSyntax ], + 'jsdoc/check-tag-names': [ + 'error', + { + definedTags: [ 'jest-environment' ], + }, + ], }, overrides: [ { diff --git a/.stylelintrc.json b/.stylelintrc.json index 663befa2e4ce06..557376e02c4062 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -1,5 +1,5 @@ { - "extends": "@wordpress/stylelint-config/scss", + "extends": "@wordpress/stylelint-config/scss-stylistic", "rules": { "at-rule-empty-line-before": null, "at-rule-no-unknown": null, @@ -21,7 +21,7 @@ } ], "font-weight-notation": null, - "max-line-length": null, + "@stylistic/max-line-length": null, "no-descending-specificity": null, "property-disallowed-list": [ [ "order" ], @@ -34,7 +34,7 @@ "value-keyword-case": null, "scss/operator-no-unspaced": null, "scss/selector-no-redundant-nesting-selector": null, - "scss/at-import-partial-extension": null, + "scss/load-partial-extension": null, "scss/no-global-function-names": null, "scss/comment-no-empty": null, "scss/at-extend-no-missing-placeholder": null, diff --git a/package-lock.json b/package-lock.json index c10f94d37dc8ba..32819be602f721 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4099,6 +4099,92 @@ "node": ">=0.1.90" } }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.1.tgz", + "integrity": "sha512-lSquqZCHxDfuTg/Sk2hiS0mcSFCEBuj49JfzPHJogDBT0mGCyY5A1AQzBWngitrp7i1/HAZpIgzF/VjhOEIJIg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.1" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.1.tgz", + "integrity": "sha512-UBqaiu7kU0lfvaP982/o3khfXccVlHPWp0/vwwiIgDF0GmqqqxoiXC/6FCjlS9u92f7CoEz6nXKQnrn1kIAkOw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-3.0.1.tgz", + "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.1", + "@csstools/css-tokenizer": "^3.0.1" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-4.0.0.tgz", + "integrity": "sha512-189nelqtPd8++phaHNwYovKZI0FOzH1vQEE3QhHHkNIGrg5fSs9CbYP3RvfEH5geztnIA9Jwq91wyOIwAW5JIQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.1.0" + } + }, "node_modules/@dabh/diagnostics": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", @@ -4119,6 +4205,16 @@ "node": ">=10.0.0" } }, + "node_modules/@dual-bundle/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/@egjs/hammerjs": { "version": "2.0.17", "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", @@ -13364,6 +13460,34 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@stylistic/stylelint-plugin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-3.0.1.tgz", + "integrity": "sha512-j3mH8HSw2Rob/KJFWZ627w3CQ8gQqVHtzCdPeEffUg5vOgpz4rgrR+Xw2kU0OQCDcdW8Y1nKfdXKKjM5Rn8X0g==", + "dev": true, + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.0", + "@csstools/css-tokenizer": "^3.0.0", + "@csstools/media-query-list-parser": "^3.0.0", + "is-plain-object": "^5.0.0", + "postcss-selector-parser": "^6.1.2", + "postcss-value-parser": "^4.2.0", + "style-search": "^0.1.0", + "stylelint": "^16.8.2" + }, + "engines": { + "node": "^18.12 || >=20.9" + }, + "peerDependencies": { + "stylelint": "^16.8.0" + } + }, + "node_modules/@stylistic/stylelint-plugin/node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", @@ -21021,27 +21145,6 @@ "node": ">=0.10.0" } }, - "node_modules/clone-regexp": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-2.2.0.tgz", - "integrity": "sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==", - "dev": true, - "dependencies": { - "is-regexp": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone-regexp/node_modules/is-regexp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-2.1.0.tgz", - "integrity": "sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/clone-response": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", @@ -22654,6 +22757,15 @@ "postcss": "^8.0.9" } }, + "node_modules/css-functions-list": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.2.tgz", + "integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==", + "dev": true, + "engines": { + "node": ">=12 || >=16" + } + }, "node_modules/css-loader": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.2.0.tgz", @@ -26049,18 +26161,6 @@ "node": ">= 8" } }, - "node_modules/execall": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/execall/-/execall-2.0.0.tgz", - "integrity": "sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==", - "dev": true, - "dependencies": { - "clone-regexp": "^2.1.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -26565,10 +26665,13 @@ } }, "node_modules/fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } }, "node_modules/fastq": { "version": "1.6.0", @@ -27059,9 +27162,9 @@ } }, "node_modules/flatted": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.0.tgz", - "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/flow-enums-runtime": { @@ -28993,12 +29096,15 @@ } }, "node_modules/html-tags": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", - "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/html-webpack-plugin": { @@ -29458,15 +29564,6 @@ "node": ">=4" } }, - "node_modules/import-lazy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", - "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -32390,9 +32487,9 @@ } }, "node_modules/keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "dependencies": { "json-buffer": "3.0.1" @@ -32442,9 +32539,9 @@ } }, "node_modules/known-css-properties": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.24.0.tgz", - "integrity": "sha512-RTSoaUAfLvpR357vWzAz/50Q/BmHfmE6ETSWfutT0AJiw10e6CmcdYRQJlLRd95B53D0Y2aD1jSxD3V3ySF+PA==", + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.34.0.tgz", + "integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==", "dev": true }, "node_modules/kuler": { @@ -37968,12 +38065,6 @@ "node": ">=0.10.0" } }, - "node_modules/normalize-selector": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", - "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", - "dev": true - }, "node_modules/normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", @@ -40997,9 +41088,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -41822,31 +41913,67 @@ "dev": true }, "node_modules/postcss-resolve-nested-selector": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", - "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", + "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", "dev": true }, "node_modules/postcss-safe-parser": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", - "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.0.tgz", + "integrity": "sha512-ovehqRNVCpuFzbXoTb4qLtyzK3xn3t/CUBxOs8LsnQjQrShaB4lKiHoVqY8ANaC0hBMHq5QVWk77rwGklFUDrg==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "engines": { - "node": ">=12.0" + "node": ">=18.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-scss": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", + "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-scss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "engines": { + "node": ">=12.0" }, "peerDependencies": { - "postcss": "^8.3.3" + "postcss": "^8.4.29" } }, "node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -47314,128 +47441,135 @@ } }, "node_modules/stylelint": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.2.0.tgz", - "integrity": "sha512-i0DrmDXFNpDsWiwx6SPRs4/pyw4kvZgqpDGvsTslQMY7hpUl6r33aQvNSn6cnTg2wtZ9rreFElI7XAKpOWi1vQ==", + "version": "16.8.2", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.8.2.tgz", + "integrity": "sha512-fInKATippQhcSm7AB+T32GpI+626yohrg33GkFT/5jzliUw5qhlwZq2UQQwgl3HsHrf09oeARi0ZwgY/UWEv9A==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.0", + "@csstools/css-tokenizer": "^3.0.0", + "@csstools/media-query-list-parser": "^3.0.0", + "@csstools/selector-specificity": "^4.0.0", + "@dual-bundle/import-meta-resolve": "^4.1.0", "balanced-match": "^2.0.0", - "colord": "^2.9.2", - "cosmiconfig": "^7.0.1", - "debug": "^4.3.3", - "execall": "^2.0.0", - "fast-glob": "^3.2.7", - "fastest-levenshtein": "^1.0.12", - "file-entry-cache": "^6.0.1", - "get-stdin": "^8.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^9.0.0", + "css-functions-list": "^3.2.2", + "css-tree": "^2.3.1", + "debug": "^4.3.6", + "fast-glob": "^3.3.2", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^9.0.0", "global-modules": "^2.0.0", - "globby": "^11.0.4", + "globby": "^11.1.0", "globjoin": "^0.1.4", - "html-tags": "^3.1.0", - "ignore": "^5.2.0", - "import-lazy": "^4.0.0", + "html-tags": "^3.3.1", + "ignore": "^5.3.2", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.24.0", + "known-css-properties": "^0.34.0", "mathml-tag-names": "^2.1.3", - "meow": "^9.0.0", - "micromatch": "^4.0.4", + "meow": "^13.2.0", + "micromatch": "^4.0.7", "normalize-path": "^3.0.0", - "normalize-selector": "^0.2.0", - "picocolors": "^1.0.0", - "postcss": "^8.3.11", - "postcss-media-query-parser": "^0.2.3", - "postcss-resolve-nested-selector": "^0.1.1", - "postcss-safe-parser": "^6.0.0", - "postcss-selector-parser": "^6.0.7", - "postcss-value-parser": "^4.1.0", + "picocolors": "^1.0.1", + "postcss": "^8.4.41", + "postcss-resolve-nested-selector": "^0.1.6", + "postcss-safe-parser": "^7.0.0", + "postcss-selector-parser": "^6.1.2", + "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", - "specificity": "^0.4.1", "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "style-search": "^0.1.0", + "strip-ansi": "^7.1.0", + "supports-hyperlinks": "^3.0.0", "svg-tags": "^1.0.0", - "table": "^6.7.5", - "v8-compile-cache": "^2.3.0", - "write-file-atomic": "^3.0.3" + "table": "^6.8.2", + "write-file-atomic": "^5.0.1" }, "bin": { - "stylelint": "bin/stylelint.js" + "stylelint": "bin/stylelint.mjs" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" + "node": ">=18.12.0" } }, - "node_modules/stylelint-config-recommended": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-6.0.0.tgz", - "integrity": "sha512-ZorSSdyMcxWpROYUvLEMm0vSZud2uB7tX1hzBZwvVY9SV/uly4AvvJPPhCcymZL3fcQhEQG5AELmrxWqtmzacw==", - "dev": true, - "peerDependencies": { - "stylelint": "^14.0.0" - } + "node_modules/stylelint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, - "node_modules/stylelint-config-recommended-scss": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-5.0.2.tgz", - "integrity": "sha512-b14BSZjcwW0hqbzm9b0S/ScN2+3CO3O4vcMNOw2KGf8lfVSwJ4p5TbNEXKwKl1+0FMtgRXZj6DqVUe/7nGnuBg==", + "node_modules/stylelint/node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true + }, + "node_modules/stylelint/node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "dev": true, "dependencies": { - "postcss-scss": "^4.0.2", - "stylelint-config-recommended": "^6.0.0", - "stylelint-scss": "^4.0.0" + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" }, - "peerDependencies": { - "stylelint": "^14.0.0" - } - }, - "node_modules/stylelint-config-recommended-scss/node_modules/postcss-scss": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.3.tgz", - "integrity": "sha512-j4KxzWovfdHsyxwl1BxkUal/O4uirvHgdzMKS1aWJBAV0qh2qj5qAZqpeBfVUYGWv+4iK9Az7SPyZ4fyNju1uA==", - "dev": true, "engines": { - "node": ">=12.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "url": "https://github.com/sponsors/d-fischer" }, "peerDependencies": { - "postcss": "^8.3.3" + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/stylelint-scss": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-4.1.0.tgz", - "integrity": "sha512-BNYTo7MMamhFOlcaAWp2dMpjg6hPyM/FFqfDIYzmYVLMmQJqc8lWRIiTqP4UX5bresj9Vo0dKC6odSh43VP2NA==", + "node_modules/stylelint/node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", "dev": true, "dependencies": { - "lodash": "^4.17.21", - "postcss-media-query-parser": "^0.2.3", - "postcss-resolve-nested-selector": "^0.1.1", - "postcss-selector-parser": "^6.0.6", - "postcss-value-parser": "^4.1.0" + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" }, - "peerDependencies": { - "stylelint": "^14.0.0" + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, - "node_modules/stylelint-scss/node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/stylelint/node_modules/balanced-match": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", - "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", - "dev": true + "node_modules/stylelint/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } }, "node_modules/stylelint/node_modules/emoji-regex": { "version": "8.0.0", @@ -47443,16 +47577,75 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/stylelint/node_modules/get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "node_modules/stylelint/node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, "engines": { - "node": ">=10" + "node": ">=8.6.0" + } + }, + "node_modules/stylelint/node_modules/file-entry-cache": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.0.0.tgz", + "integrity": "sha512-6MgEugi8p2tiUhqO7GnPsmbCCzj0YRCwwaTbpGRyKZesjRSzkqkAE9fPp7V2yMs5hwfgbQLgdvSSkGNg1s5Uvw==", + "dev": true, + "dependencies": { + "flat-cache": "^5.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=18" + } + }, + "node_modules/stylelint/node_modules/flat-cache": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", + "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", + "dev": true, + "dependencies": { + "flatted": "^3.3.1", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/stylelint/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stylelint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylelint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" } }, "node_modules/stylelint/node_modules/is-fullwidth-code-point": { @@ -47464,45 +47657,68 @@ "node": ">=8" } }, - "node_modules/stylelint/node_modules/meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "node_modules/stylelint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" + "argparse": "^2.0.1" }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/stylelint/node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/stylelint/node_modules/meow": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stylelint/node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "node_modules/stylelint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/stylelint/node_modules/postcss": { + "version": "8.4.41", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", + "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" }, "engines": { - "node": ">=10" + "node": "^10 || ^12 || >=14" } }, "node_modules/stylelint/node_modules/postcss-value-parser": { @@ -47520,6 +47736,27 @@ "node": ">=8" } }, + "node_modules/stylelint/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/stylelint/node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/stylelint/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -47534,28 +47771,84 @@ "node": ">=8" } }, - "node_modules/stylelint/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "node_modules/stylelint/node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" + } + }, + "node_modules/stylelint/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/stylelint/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/stylelint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylelint/node_modules/supports-hyperlinks": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz", + "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/stylelint/node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/stylis": { @@ -47748,9 +48041,9 @@ } }, "node_modules/table": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", - "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", + "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", "dev": true, "dependencies": { "ajv": "^8.0.1", @@ -54833,7 +55126,7 @@ "sass-loader": "^12.1.0", "schema-utils": "^4.2.0", "source-map-loader": "^3.0.0", - "stylelint": "^14.2.0", + "stylelint": "^16.8.2", "terser-webpack-plugin": "^5.3.9", "url-loader": "^4.1.1", "webpack": "^5.88.2", @@ -55287,15 +55580,116 @@ "dev": true, "license": "MIT", "dependencies": { - "stylelint-config-recommended": "^6.0.0", - "stylelint-config-recommended-scss": "^5.0.2" + "@stylistic/stylelint-plugin": "^3.0.1", + "stylelint-config-recommended": "^14.0.1", + "stylelint-config-recommended-scss": "^14.1.0" }, "engines": { "node": ">=18.12.0", "npm": ">=8.19.2" }, "peerDependencies": { - "stylelint": "^14.2" + "stylelint": "^16.8.2" + } + }, + "packages/stylelint-config/node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "packages/stylelint-config/node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "packages/stylelint-config/node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "packages/stylelint-config/node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/stylelint-config/node_modules/stylelint-config-recommended": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", + "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.1.0" + } + }, + "packages/stylelint-config/node_modules/stylelint-config-recommended-scss": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.1.0.tgz", + "integrity": "sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg==", + "dev": true, + "dependencies": { + "postcss-scss": "^4.0.9", + "stylelint-config-recommended": "^14.0.1", + "stylelint-scss": "^6.4.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "postcss": "^8.3.3", + "stylelint": "^16.6.1" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + } + } + }, + "packages/stylelint-config/node_modules/stylelint-scss": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.5.1.tgz", + "integrity": "sha512-ZLqdqihm6uDYkrsOeD6YWb+stZI8Wn92kUNDhE4M+g9g1aCnRv0JlOrttFiAJJwaNzpdQgX3YJb5vDQXVuO9Ww==", + "dev": true, + "dependencies": { + "css-tree": "2.3.1", + "is-plain-object": "5.0.0", + "known-css-properties": "^0.34.0", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.4", + "postcss-selector-parser": "^6.1.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.0.2" } }, "packages/sync": { @@ -58171,6 +58565,30 @@ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true }, + "@csstools/css-parser-algorithms": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.1.tgz", + "integrity": "sha512-lSquqZCHxDfuTg/Sk2hiS0mcSFCEBuj49JfzPHJogDBT0mGCyY5A1AQzBWngitrp7i1/HAZpIgzF/VjhOEIJIg==", + "dev": true + }, + "@csstools/css-tokenizer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.1.tgz", + "integrity": "sha512-UBqaiu7kU0lfvaP982/o3khfXccVlHPWp0/vwwiIgDF0GmqqqxoiXC/6FCjlS9u92f7CoEz6nXKQnrn1kIAkOw==", + "dev": true + }, + "@csstools/media-query-list-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-3.0.1.tgz", + "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==", + "dev": true + }, + "@csstools/selector-specificity": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-4.0.0.tgz", + "integrity": "sha512-189nelqtPd8++phaHNwYovKZI0FOzH1vQEE3QhHHkNIGrg5fSs9CbYP3RvfEH5geztnIA9Jwq91wyOIwAW5JIQ==", + "dev": true + }, "@dabh/diagnostics": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", @@ -58188,6 +58606,12 @@ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true }, + "@dual-bundle/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", + "dev": true + }, "@egjs/hammerjs": { "version": "2.0.17", "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", @@ -64755,6 +65179,30 @@ "file-system-cache": "2.3.0" } }, + "@stylistic/stylelint-plugin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-3.0.1.tgz", + "integrity": "sha512-j3mH8HSw2Rob/KJFWZ627w3CQ8gQqVHtzCdPeEffUg5vOgpz4rgrR+Xw2kU0OQCDcdW8Y1nKfdXKKjM5Rn8X0g==", + "dev": true, + "requires": { + "@csstools/css-parser-algorithms": "^3.0.0", + "@csstools/css-tokenizer": "^3.0.0", + "@csstools/media-query-list-parser": "^3.0.0", + "is-plain-object": "^5.0.0", + "postcss-selector-parser": "^6.1.2", + "postcss-value-parser": "^4.2.0", + "style-search": "^0.1.0", + "stylelint": "^16.8.2" + }, + "dependencies": { + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + } + } + }, "@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", @@ -69017,7 +69465,7 @@ "sass-loader": "^12.1.0", "schema-utils": "^4.2.0", "source-map-loader": "^3.0.0", - "stylelint": "^14.2.0", + "stylelint": "^16.8.2", "terser-webpack-plugin": "^5.3.9", "url-loader": "^4.1.1", "webpack": "^5.88.2", @@ -69331,8 +69779,71 @@ "@wordpress/stylelint-config": { "version": "file:packages/stylelint-config", "requires": { - "stylelint-config-recommended": "^6.0.0", - "stylelint-config-recommended-scss": "^5.0.2" + "@stylistic/stylelint-plugin": "^3.0.1", + "stylelint-config-recommended": "^14.0.1", + "stylelint-config-recommended-scss": "^14.1.0" + }, + "dependencies": { + "css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "requires": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + } + }, + "mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true + }, + "stylelint-config-recommended": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", + "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", + "dev": true + }, + "stylelint-config-recommended-scss": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.1.0.tgz", + "integrity": "sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg==", + "dev": true, + "requires": { + "postcss-scss": "^4.0.9", + "stylelint-config-recommended": "^14.0.1", + "stylelint-scss": "^6.4.0" + } + }, + "stylelint-scss": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.5.1.tgz", + "integrity": "sha512-ZLqdqihm6uDYkrsOeD6YWb+stZI8Wn92kUNDhE4M+g9g1aCnRv0JlOrttFiAJJwaNzpdQgX3YJb5vDQXVuO9Ww==", + "dev": true, + "requires": { + "css-tree": "2.3.1", + "is-plain-object": "5.0.0", + "known-css-properties": "^0.34.0", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.4", + "postcss-selector-parser": "^6.1.1", + "postcss-value-parser": "^4.2.0" + } + } } }, "@wordpress/sync": { @@ -72328,23 +72839,6 @@ } } }, - "clone-regexp": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-2.2.0.tgz", - "integrity": "sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==", - "dev": true, - "requires": { - "is-regexp": "^2.0.0" - }, - "dependencies": { - "is-regexp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-2.1.0.tgz", - "integrity": "sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==", - "dev": true - } - } - }, "clone-response": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", @@ -73621,6 +74115,12 @@ "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", "dev": true }, + "css-functions-list": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.2.tgz", + "integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==", + "dev": true + }, "css-loader": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.2.0.tgz", @@ -76156,15 +76656,6 @@ } } }, - "execall": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/execall/-/execall-2.0.0.tgz", - "integrity": "sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==", - "dev": true, - "requires": { - "clone-regexp": "^2.1.0" - } - }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -76577,9 +77068,9 @@ } }, "fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true }, "fastq": { @@ -76968,9 +77459,9 @@ } }, "flatted": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.0.tgz", - "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "flow-enums-runtime": { @@ -78434,9 +78925,9 @@ } }, "html-tags": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", - "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", "dev": true }, "html-webpack-plugin": { @@ -78758,12 +79249,6 @@ } } }, - "import-lazy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", - "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", - "dev": true - }, "import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -80917,9 +81402,9 @@ } }, "keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "requires": { "json-buffer": "3.0.1" @@ -80957,9 +81442,9 @@ "dev": true }, "known-css-properties": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.24.0.tgz", - "integrity": "sha512-RTSoaUAfLvpR357vWzAz/50Q/BmHfmE6ETSWfutT0AJiw10e6CmcdYRQJlLRd95B53D0Y2aD1jSxD3V3ySF+PA==", + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.34.0.tgz", + "integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==", "dev": true }, "kuler": { @@ -85267,12 +85752,6 @@ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true }, - "normalize-selector": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", - "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", - "dev": true - }, "normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", @@ -87530,9 +88009,9 @@ "integrity": "sha512-SO+NP5argMoJVCWcYiOofPUeEWDIM47FNCBJtp6uJ8PpjtBcudYJTzCbCMit5dzmfSLCoijzEwIXOqPqD45xQg==" }, "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" }, "picomatch": { "version": "2.3.1", @@ -88122,21 +88601,27 @@ } }, "postcss-resolve-nested-selector": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", - "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", + "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", "dev": true }, "postcss-safe-parser": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", - "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.0.tgz", + "integrity": "sha512-ovehqRNVCpuFzbXoTb4qLtyzK3xn3t/CUBxOs8LsnQjQrShaB4lKiHoVqY8ANaC0hBMHq5QVWk77rwGklFUDrg==", + "dev": true + }, + "postcss-scss": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", + "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", "dev": true }, "postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, "requires": { "cssesc": "^3.0.0", @@ -92312,68 +92797,152 @@ } }, "stylelint": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.2.0.tgz", - "integrity": "sha512-i0DrmDXFNpDsWiwx6SPRs4/pyw4kvZgqpDGvsTslQMY7hpUl6r33aQvNSn6cnTg2wtZ9rreFElI7XAKpOWi1vQ==", + "version": "16.8.2", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.8.2.tgz", + "integrity": "sha512-fInKATippQhcSm7AB+T32GpI+626yohrg33GkFT/5jzliUw5qhlwZq2UQQwgl3HsHrf09oeARi0ZwgY/UWEv9A==", "dev": true, "requires": { + "@csstools/css-parser-algorithms": "^3.0.0", + "@csstools/css-tokenizer": "^3.0.0", + "@csstools/media-query-list-parser": "^3.0.0", + "@csstools/selector-specificity": "^4.0.0", + "@dual-bundle/import-meta-resolve": "^4.1.0", "balanced-match": "^2.0.0", - "colord": "^2.9.2", - "cosmiconfig": "^7.0.1", - "debug": "^4.3.3", - "execall": "^2.0.0", - "fast-glob": "^3.2.7", - "fastest-levenshtein": "^1.0.12", - "file-entry-cache": "^6.0.1", - "get-stdin": "^8.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^9.0.0", + "css-functions-list": "^3.2.2", + "css-tree": "^2.3.1", + "debug": "^4.3.6", + "fast-glob": "^3.3.2", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^9.0.0", "global-modules": "^2.0.0", - "globby": "^11.0.4", + "globby": "^11.1.0", "globjoin": "^0.1.4", - "html-tags": "^3.1.0", - "ignore": "^5.2.0", - "import-lazy": "^4.0.0", + "html-tags": "^3.3.1", + "ignore": "^5.3.2", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.24.0", + "known-css-properties": "^0.34.0", "mathml-tag-names": "^2.1.3", - "meow": "^9.0.0", - "micromatch": "^4.0.4", + "meow": "^13.2.0", + "micromatch": "^4.0.7", "normalize-path": "^3.0.0", - "normalize-selector": "^0.2.0", - "picocolors": "^1.0.0", - "postcss": "^8.3.11", - "postcss-media-query-parser": "^0.2.3", - "postcss-resolve-nested-selector": "^0.1.1", - "postcss-safe-parser": "^6.0.0", - "postcss-selector-parser": "^6.0.7", - "postcss-value-parser": "^4.1.0", + "picocolors": "^1.0.1", + "postcss": "^8.4.41", + "postcss-resolve-nested-selector": "^0.1.6", + "postcss-safe-parser": "^7.0.0", + "postcss-selector-parser": "^6.1.2", + "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", - "specificity": "^0.4.1", "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "style-search": "^0.1.0", + "strip-ansi": "^7.1.0", + "supports-hyperlinks": "^3.0.0", "svg-tags": "^1.0.0", - "table": "^6.7.5", - "v8-compile-cache": "^2.3.0", - "write-file-atomic": "^3.0.3" + "table": "^6.8.2", + "write-file-atomic": "^5.0.1" }, "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "balanced-match": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", "dev": true }, + "cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "requires": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + } + }, + "css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "requires": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + } + }, + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "file-entry-cache": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.0.0.tgz", + "integrity": "sha512-6MgEugi8p2tiUhqO7GnPsmbCCzj0YRCwwaTbpGRyKZesjRSzkqkAE9fPp7V2yMs5hwfgbQLgdvSSkGNg1s5Uvw==", + "dev": true, + "requires": { + "flat-cache": "^5.0.0" + } + }, + "flat-cache": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", + "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", + "dev": true, + "requires": { + "flatted": "^3.3.1", + "keyv": "^4.5.4" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true }, "is-fullwidth-code-point": { @@ -92382,36 +92951,42 @@ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, - "meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" + "argparse": "^2.0.1" } }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "meow": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "postcss": { + "version": "8.4.41", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", + "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", "dev": true, "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" } }, "postcss-value-parser": { @@ -92426,6 +93001,18 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -92435,74 +93022,67 @@ "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } } }, - "type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + } + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-hyperlinks": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz", + "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==", + "dev": true, + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + } }, "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, "requires": { "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "signal-exit": "^4.0.1" } } } }, - "stylelint-config-recommended": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-6.0.0.tgz", - "integrity": "sha512-ZorSSdyMcxWpROYUvLEMm0vSZud2uB7tX1hzBZwvVY9SV/uly4AvvJPPhCcymZL3fcQhEQG5AELmrxWqtmzacw==", - "dev": true - }, - "stylelint-config-recommended-scss": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-5.0.2.tgz", - "integrity": "sha512-b14BSZjcwW0hqbzm9b0S/ScN2+3CO3O4vcMNOw2KGf8lfVSwJ4p5TbNEXKwKl1+0FMtgRXZj6DqVUe/7nGnuBg==", - "dev": true, - "requires": { - "postcss-scss": "^4.0.2", - "stylelint-config-recommended": "^6.0.0", - "stylelint-scss": "^4.0.0" - }, - "dependencies": { - "postcss-scss": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.3.tgz", - "integrity": "sha512-j4KxzWovfdHsyxwl1BxkUal/O4uirvHgdzMKS1aWJBAV0qh2qj5qAZqpeBfVUYGWv+4iK9Az7SPyZ4fyNju1uA==", - "dev": true - } - } - }, - "stylelint-scss": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-4.1.0.tgz", - "integrity": "sha512-BNYTo7MMamhFOlcaAWp2dMpjg6hPyM/FFqfDIYzmYVLMmQJqc8lWRIiTqP4UX5bresj9Vo0dKC6odSh43VP2NA==", - "dev": true, - "requires": { - "lodash": "^4.17.21", - "postcss-media-query-parser": "^0.2.3", - "postcss-resolve-nested-selector": "^0.1.1", - "postcss-selector-parser": "^6.0.6", - "postcss-value-parser": "^4.1.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, "stylis": { "version": "4.0.13", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz", @@ -92647,9 +93227,9 @@ } }, "table": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", - "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", + "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", "dev": true, "requires": { "ajv": "^8.0.1", diff --git a/packages/base-styles/_mixins.scss b/packages/base-styles/_mixins.scss index ebccbe0e5e8aee..91017c8bb99320 100644 --- a/packages/base-styles/_mixins.scss +++ b/packages/base-styles/_mixins.scss @@ -512,7 +512,7 @@ @mixin gradient-colors-deprecated() { // Our classes uses the same values we set for gradient value attributes. - /* stylelint-disable function-comma-space-after -- We can not use spacing because of WP multi site kses rule. */ + /* stylelint-disable @stylistic/function-comma-space-after -- We can not use spacing because of WP multi site kses rule. */ .has-vivid-green-cyan-to-vivid-cyan-blue-gradient-background { background: linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%); } @@ -540,7 +540,7 @@ .has-midnight-gradient-background { background: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%); } - /* stylelint-enable function-comma-space-after */ + /* stylelint-enable @stylistic/function-comma-space-after */ } @mixin custom-scrollbars-on-hover($handle-color, $handle-color-hover) { diff --git a/packages/block-library/src/buttons/editor.scss b/packages/block-library/src/buttons/editor.scss index 1aa775fd1d6483..f0a1e930d40bb8 100644 --- a/packages/block-library/src/buttons/editor.scss +++ b/packages/block-library/src/buttons/editor.scss @@ -33,14 +33,14 @@ $blocks-block__margin: 0.5em; // // This back compat rule is ignored if the user decides to use the // newer justification options on the button block, hence the :not. - /* stylelint-disable indentation -- Disable the stylelint rule, otherwise this selector is ugly! */ + /* stylelint-disable @stylistic/indentation -- Disable the stylelint rule, otherwise this selector is ugly! */ &:not( .is-content-justification-space-between, .is-content-justification-right, .is-content-justification-left, .is-content-justification-center ) .wp-block[data-align="center"] { - /* stylelint-enable indentation */ + /* stylelint-enable @stylistic/indentation */ margin-left: auto; margin-right: auto; margin-top: 0; diff --git a/packages/block-library/src/buttons/style.scss b/packages/block-library/src/buttons/style.scss index 7e8bd61b03eaf9..8492553bd50b81 100644 --- a/packages/block-library/src/buttons/style.scss +++ b/packages/block-library/src/buttons/style.scss @@ -55,14 +55,14 @@ $blocks-block__margin: 0.5em; // // This back compat rule is ignored if the user decides to use the // newer justification options on the button block, hence the :not. - /* stylelint-disable indentation -- Disable the stylelint rule, otherwise this selector is ugly! */ + /* stylelint-disable @stylistic/indentation -- Disable the stylelint rule, otherwise this selector is ugly! */ &:not( .is-content-justification-space-between, .is-content-justification-right, .is-content-justification-left, .is-content-justification-center ) .wp-block-button.aligncenter { - /* stylelint-enable indentation */ + /* stylelint-enable @stylistic/indentation */ margin-left: auto; margin-right: auto; width: 100%; diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index ea8a59d1ad2ad4..43fe001351bc2c 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased + +### Breaking Changes + +- Updated `stylelint` dependency to `^16.8.2` ([#64828](https://github.com/WordPress/gutenberg/pull/64828)). +- Switched default config from `@wordpress/stylelint-config/scss` to use `@wordpress/stylelint-config/scss-stylistic` to keep stylistic rules ([#64828](https://github.com/WordPress/gutenberg/pull/64828)). + ## 29.0.0 (2024-09-05) ### Breaking Changes diff --git a/packages/scripts/config/.stylelintrc.json b/packages/scripts/config/.stylelintrc.json index 1cfc8fc10ea564..96c4ccca749050 100644 --- a/packages/scripts/config/.stylelintrc.json +++ b/packages/scripts/config/.stylelintrc.json @@ -1,5 +1,5 @@ { - "extends": "@wordpress/stylelint-config/scss", + "extends": "@wordpress/stylelint-config/scss-stylistic", "rules": { "selector-class-pattern": null } diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 6661e9876683fa..d9e74d0c71826a 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -85,7 +85,7 @@ "sass-loader": "^12.1.0", "schema-utils": "^4.2.0", "source-map-loader": "^3.0.0", - "stylelint": "^14.2.0", + "stylelint": "^16.8.2", "terser-webpack-plugin": "^5.3.9", "url-loader": "^4.1.1", "webpack": "^5.88.2", diff --git a/packages/stylelint-config/CHANGELOG.md b/packages/stylelint-config/CHANGELOG.md index 9cb29690af289e..4cc05e02105ff7 100644 --- a/packages/stylelint-config/CHANGELOG.md +++ b/packages/stylelint-config/CHANGELOG.md @@ -2,6 +2,20 @@ ## Unreleased +### Breaking Changes + +- Updated `stylelint` peer dependency requirement to `^16.8.2` ([#64828](https://github.com/WordPress/gutenberg/pull/64828)). +- Updated `stylelint-config-recommended` to `^14.0.1` and disabled new rules ([#64828](https://github.com/WordPress/gutenberg/pull/64828)). +- Updated `stylelint-config-recommended-scss` to `^14.1.0` and disabled new rules ([#64828](https://github.com/WordPress/gutenberg/pull/64828)). +- Added `@stylistic/stylelint-plugin` dependency at `^3.0.1` ([#64828](https://github.com/WordPress/gutenberg/pull/64828)). +- Migrated stylelint's deprecated rules from v15 to use `@stylistic/stylelint-plugin` ([#64828](https://github.com/WordPress/gutenberg/pull/64828)). For more information, see the [stylelint migration guide](https://stylelint.io/migration-guide/to-15). To migrate your rule overrides, you just need to add `@stylistic/` in front of the rule names. +- Created new `stylistic` and `scss-stylistic` configs ([#64828](https://github.com/WordPress/gutenberg/pull/64828)). If you want to continue using the exact same rule set as before, you should use these, however if you currently use something like `stylelint-config-prettier` to disable formatting rules, you will want to use the non-stylistic configs (using the same names as before). +- `scss/at-import-partial-extension` has been renamed ([#64828](https://github.com/WordPress/gutenberg/pull/64828)). You must convert this rule to `scss/load-partial-extension` instead (name only change). + +### Bug Fixes + +- Fixes `declaration-block-no-duplicate-properties` in the `scss` config to use the same value as the base config ([#64828](https://github.com/WordPress/gutenberg/pull/64828)). + ## 22.7.0 (2024-09-05) ## 22.6.0 (2024-08-21) diff --git a/packages/stylelint-config/README.md b/packages/stylelint-config/README.md index c6d69a9d183489..5d760dddc8f920 100644 --- a/packages/stylelint-config/README.md +++ b/packages/stylelint-config/README.md @@ -30,16 +30,38 @@ If you've globally installed `@wordpress/stylelint-config` using the `-g` flag, ## Presets -In addition to the default preset, there is also a SCSS preset. This preset extends both `@wordpress/stylelint-config` and [`stylelint-config-recommended-scss`](https://github.com/kristerkari/stylelint-config-recommended-scss). +In addition to the default preset, there is also a SCSS preset and 2 stylistic variant presets. ### SCSS +This preset extends both `@wordpress/stylelint-config` and [`stylelint-config-recommended-scss`](https://github.com/kristerkari/stylelint-config-recommended-scss). + ```json { "extends": [ "@wordpress/stylelint-config/scss" ] } ``` +### Stylistic + +This preset extends `@wordpress/stylelint-config` and adds stylistic rules such as `indentation`. + +```json +{ + "extends": [ "@wordpress/stylelint-config/stylistic" ] +} +``` + +### SCSS Stylistic + +This preset extends`@wordpress/stylelint-config`, `@wordpress/stylelint-config/stylistic` and `@wordpress/stylelint-config/scss`, and adapts some stylistic rules for SCSS. + +```json +{ + "extends": [ "@wordpress/stylelint-config/scss-stylistic" ] +} +``` + ## Extending the config Simply add a `"rules"` key to your config and add your overrides there. @@ -48,10 +70,10 @@ For example, to change the `indentation` to four spaces and turn off the `number ```json { - "extends": "@wordpress/stylelint-config", + "extends": "@wordpress/stylelint-config/stylistic", "rules": { - "indentation": 4, - "number-leading-zero": null + "@stylistic/indentation": 4, + "@stylistic/number-leading-zero": null } } ``` diff --git a/packages/stylelint-config/index.js b/packages/stylelint-config/index.js index 0ab4f954cb35bf..3e5e00b05a2a49 100644 --- a/packages/stylelint-config/index.js +++ b/packages/stylelint-config/index.js @@ -1,7 +1,8 @@ 'use strict'; +/** @type {import('stylelint').Config} */ module.exports = { - extends: 'stylelint-config-recommended', + extends: [ 'stylelint-config-recommended' ].map( require.resolve ), rules: { 'at-rule-empty-line-before': [ 'always', @@ -10,15 +11,7 @@ module.exports = { ignore: [ 'after-comment' ], }, ], - 'at-rule-name-case': 'lower', - 'at-rule-name-space-after': 'always-single-line', 'at-rule-no-unknown': true, - 'at-rule-semicolon-newline-after': 'always', - 'block-closing-brace-newline-after': 'always', - 'block-closing-brace-newline-before': 'always', - 'block-opening-brace-newline-after': 'always', - 'block-opening-brace-space-before': 'always', - 'color-hex-case': 'lower', 'color-hex-length': 'short', 'color-named': 'never', 'comment-empty-line-before': [ @@ -27,20 +20,12 @@ module.exports = { ignore: [ 'stylelint-commands' ], }, ], - 'declaration-bang-space-after': 'never', - 'declaration-bang-space-before': 'always', 'declaration-block-no-duplicate-properties': [ true, { ignore: [ 'consecutive-duplicates' ], }, ], - 'declaration-block-semicolon-newline-after': 'always', - 'declaration-block-semicolon-space-before': 'never', - 'declaration-block-trailing-semicolon': 'always', - 'declaration-colon-newline-after': 'always-multi-line', - 'declaration-colon-space-after': 'always-single-line', - 'declaration-colon-space-before': 'never', 'declaration-property-unit-allowed-list': { 'line-height': [ 'px' ], }, @@ -51,51 +36,20 @@ module.exports = { ignore: [ 'relative' ], }, ], - 'function-comma-space-after': 'always', - 'function-comma-space-before': 'never', - 'function-max-empty-lines': 1, 'function-name-case': [ 'lower', { ignoreFunctions: [ '/^DXImageTransform.Microsoft.*$/' ], }, ], - 'function-parentheses-space-inside': 'never', 'function-url-quotes': 'never', - 'function-whitespace-after': 'always', - indentation: 'tab', 'length-zero-no-unit': true, - 'max-empty-lines': 2, - 'max-line-length': [ - 80, - { - ignore: 'non-comments', - ignorePattern: [ - '/(https?://[0-9,a-z]*.*)|(^description\\:.+)|(^tags\\:.+)/i', - ], - }, - ], - 'media-feature-colon-space-after': 'always', - 'media-feature-colon-space-before': 'never', - 'media-feature-range-operator-space-after': 'always', - 'media-feature-range-operator-space-before': 'always', - 'media-query-list-comma-newline-after': 'always-multi-line', - 'media-query-list-comma-space-after': 'always-single-line', - 'media-query-list-comma-space-before': 'never', - 'no-eol-whitespace': true, - 'no-missing-end-of-source-newline': true, - 'number-leading-zero': 'always', - 'number-no-trailing-zeros': true, - 'property-case': 'lower', 'rule-empty-line-before': [ 'always', { ignore: [ 'after-comment' ], }, ], - 'selector-attribute-brackets-space-inside': 'never', - 'selector-attribute-operator-space-after': 'never', - 'selector-attribute-operator-space-before': 'never', 'selector-attribute-quotes': 'always', 'selector-class-pattern': [ '^([a-z][a-z0-9]*)(-[a-z0-9]+)*$', @@ -111,21 +65,15 @@ module.exports = { 'Selector should use lowercase and separate words with hyphens (selector-id-pattern)', }, ], - 'selector-combinator-space-after': 'always', - 'selector-combinator-space-before': 'always', - 'selector-list-comma-newline-after': 'always', - 'selector-list-comma-space-before': 'never', - 'selector-max-empty-lines': 0, - 'selector-pseudo-class-case': 'lower', - 'selector-pseudo-class-parentheses-space-inside': 'never', - 'selector-pseudo-element-case': 'lower', 'selector-pseudo-element-colon-notation': 'double', 'selector-type-case': 'lower', - 'string-quotes': 'double', - 'unit-case': 'lower', 'value-keyword-case': 'lower', - 'value-list-comma-newline-after': 'always-multi-line', - 'value-list-comma-space-after': 'always-single-line', - 'value-list-comma-space-before': 'never', + + /* Disable new rules from stylelint-config-recommended 7 > 14 */ + 'function-no-unknown': null, + 'keyframe-block-no-duplicate-selectors': null, + 'annotation-no-unknown': null, + 'selector-anb-no-unmatchable': null, + 'media-query-no-invalid': null, }, }; diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 19e6f19bfd2f87..53051078b9b863 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -32,11 +32,12 @@ ], "main": "index.js", "dependencies": { - "stylelint-config-recommended": "^6.0.0", - "stylelint-config-recommended-scss": "^5.0.2" + "@stylistic/stylelint-plugin": "^3.0.1", + "stylelint-config-recommended": "^14.0.1", + "stylelint-config-recommended-scss": "^14.1.0" }, "peerDependencies": { - "stylelint": "^14.2" + "stylelint": "^16.8.2" }, "npmpackagejsonlint": { "extends": "@wordpress/npm-package-json-lint-config", diff --git a/packages/stylelint-config/scss-stylistic.js b/packages/stylelint-config/scss-stylistic.js new file mode 100644 index 00000000000000..5d9bbb50c7b66a --- /dev/null +++ b/packages/stylelint-config/scss-stylistic.js @@ -0,0 +1,16 @@ +'use strict'; + +/** @type {import('stylelint').Config} */ +module.exports = { + extends: [ './stylistic', './scss' ].map( require.resolve ), + rules: { + '@stylistic/block-opening-brace-space-before': 'always', + '@stylistic/block-closing-brace-newline-after': [ + 'always', + { + ignoreAtRules: [ 'if', 'else' ], + }, + ], + '@stylistic/at-rule-name-space-after': 'always', + }, +}; diff --git a/packages/stylelint-config/scss.js b/packages/stylelint-config/scss.js index 09940642b218b1..3f0aacce31d5a2 100644 --- a/packages/stylelint-config/scss.js +++ b/packages/stylelint-config/scss.js @@ -1,5 +1,6 @@ 'use strict'; +/** @type {import('stylelint').Config} */ module.exports = { extends: [ './', 'stylelint-config-recommended-scss' ].map( require.resolve @@ -18,19 +19,18 @@ module.exports = { }, ], - 'block-opening-brace-space-before': 'always', - 'block-closing-brace-newline-after': [ - 'always', - { - ignoreAtRules: [ 'if', 'else' ], - }, - ], - 'at-rule-name-space-after': 'always', 'scss/at-else-closing-brace-newline-after': 'always-last-in-chain', 'scss/at-else-closing-brace-space-after': 'always-intermediate', 'scss/at-else-empty-line-before': 'never', 'scss/at-if-closing-brace-newline-after': 'always-last-in-chain', 'scss/at-if-closing-brace-space-after': 'always-intermediate', 'scss/selector-no-redundant-nesting-selector': true, + /* This value gets overwritten by stylelint-config-recommended-scss so we need to set it again. */ + 'declaration-block-no-duplicate-properties': [ + true, + { + ignore: [ 'consecutive-duplicates' ], + }, + ], }, }; diff --git a/packages/stylelint-config/stylistic.js b/packages/stylelint-config/stylistic.js new file mode 100644 index 00000000000000..54a1a2ca63dd7a --- /dev/null +++ b/packages/stylelint-config/stylistic.js @@ -0,0 +1,72 @@ +'use strict'; + +/** @type {import('stylelint').Config} */ +module.exports = { + extends: [ './' ].map( require.resolve ), + plugins: [ '@stylistic/stylelint-plugin' ], + rules: { + '@stylistic/at-rule-name-case': 'lower', + '@stylistic/at-rule-name-space-after': 'always-single-line', + '@stylistic/at-rule-semicolon-newline-after': 'always', + '@stylistic/block-closing-brace-newline-after': 'always', + '@stylistic/block-closing-brace-newline-before': 'always', + '@stylistic/block-opening-brace-newline-after': 'always', + '@stylistic/block-opening-brace-space-before': 'always', + '@stylistic/color-hex-case': 'lower', + '@stylistic/declaration-bang-space-after': 'never', + '@stylistic/declaration-bang-space-before': 'always', + '@stylistic/declaration-block-semicolon-newline-after': 'always', + '@stylistic/declaration-block-semicolon-space-before': 'never', + '@stylistic/declaration-block-trailing-semicolon': 'always', + '@stylistic/declaration-colon-newline-after': 'always-multi-line', + '@stylistic/declaration-colon-space-after': 'always-single-line', + '@stylistic/declaration-colon-space-before': 'never', + '@stylistic/function-comma-space-after': 'always', + '@stylistic/function-comma-space-before': 'never', + '@stylistic/function-max-empty-lines': 1, + '@stylistic/function-parentheses-space-inside': 'never', + '@stylistic/function-whitespace-after': 'always', + '@stylistic/indentation': 'tab', + '@stylistic/max-empty-lines': 2, + '@stylistic/max-line-length': [ + 80, + { + ignore: 'non-comments', + ignorePattern: [ + '/(https?://[0-9,a-z]*.*)|(^description\\:.+)|(^tags\\:.+)/i', + ], + }, + ], + '@stylistic/media-feature-colon-space-after': 'always', + '@stylistic/media-feature-colon-space-before': 'never', + '@stylistic/media-feature-range-operator-space-after': 'always', + '@stylistic/media-feature-range-operator-space-before': 'always', + '@stylistic/media-query-list-comma-newline-after': 'always-multi-line', + '@stylistic/media-query-list-comma-space-after': 'always-single-line', + '@stylistic/media-query-list-comma-space-before': 'never', + '@stylistic/no-eol-whitespace': true, + '@stylistic/no-missing-end-of-source-newline': true, + '@stylistic/number-leading-zero': 'always', + '@stylistic/number-no-trailing-zeros': true, + '@stylistic/property-case': 'lower', + '@stylistic/selector-attribute-brackets-space-inside': 'never', + '@stylistic/selector-attribute-operator-space-after': 'never', + '@stylistic/selector-attribute-operator-space-before': 'never', + '@stylistic/selector-combinator-space-after': 'always', + '@stylistic/selector-combinator-space-before': 'always', + '@stylistic/selector-list-comma-newline-after': 'always', + '@stylistic/selector-list-comma-space-before': 'never', + '@stylistic/selector-max-empty-lines': 0, + '@stylistic/selector-pseudo-class-case': 'lower', + '@stylistic/selector-pseudo-class-parentheses-space-inside': 'never', + '@stylistic/selector-pseudo-element-case': 'lower', + '@stylistic/string-quotes': 'double', + '@stylistic/unit-case': 'lower', + '@stylistic/value-list-comma-newline-after': 'always-multi-line', + '@stylistic/value-list-comma-space-after': 'always-single-line', + '@stylistic/value-list-comma-space-before': 'never', + + /* Add back deprecated rule from stylelint-config-recommended */ + '@stylistic/no-extra-semicolons': true, + }, +}; diff --git a/packages/stylelint-config/test/.stylelintignore b/packages/stylelint-config/test/.stylelintignore new file mode 100644 index 00000000000000..f74c877ecba44c --- /dev/null +++ b/packages/stylelint-config/test/.stylelintignore @@ -0,0 +1 @@ +# This file needs to exist so test files have a way to unignore the files in this folder. diff --git a/packages/stylelint-config/test/.stylelintrc.json b/packages/stylelint-config/test/.stylelintrc.json index 1ea6c83527d288..059284930a130c 100644 --- a/packages/stylelint-config/test/.stylelintrc.json +++ b/packages/stylelint-config/test/.stylelintrc.json @@ -1,4 +1,13 @@ { - "extends": "@wordpress/stylelint-config/scss", - "ignoreFiles": [ "*-invalid.scss" ] + "extends": "./.stylelintrc.tests.json", + "overrides": [ + { + "files": [ "*.scss", "**/*.scss" ], + "ignoreFiles": [ "*-invalid.scss" ] + }, + { + "files": [ "*.css", "**/*.css" ], + "ignoreFiles": [ "*-invalid.css" ] + } + ] } diff --git a/packages/stylelint-config/test/.stylelintrc.tests.json b/packages/stylelint-config/test/.stylelintrc.tests.json new file mode 100644 index 00000000000000..c80288c8dc8bb7 --- /dev/null +++ b/packages/stylelint-config/test/.stylelintrc.tests.json @@ -0,0 +1,13 @@ +{ + "rules": {}, + "overrides": [ + { + "files": [ "*.scss", "**/*.scss" ], + "extends": "@wordpress/stylelint-config/scss-stylistic" + }, + { + "files": [ "*.css", "**/*.css" ], + "extends": "@wordpress/stylelint-config/stylistic" + } + ] +} diff --git a/packages/stylelint-config/test/__snapshots__/commenting.js.snap b/packages/stylelint-config/test/__snapshots__/commenting.js.snap index 4eaddcac0148c5..ab191a80e1e73b 100644 --- a/packages/stylelint-config/test/__snapshots__/commenting.js.snap +++ b/packages/stylelint-config/test/__snapshots__/commenting.js.snap @@ -2,8 +2,19 @@ exports[`flags warnings with invalid commenting css snapshot matches warnings 1`] = ` [ + { + "column": 131, + "endColumn": 132, + "endLine": 24, + "line": 24, + "rule": "@stylistic/max-line-length", + "severity": "error", + "text": "Expected line length to be no more than 80 characters (@stylistic/max-line-length)", + }, { "column": 1, + "endColumn": 3, + "endLine": 14, "line": 9, "rule": "comment-empty-line-before", "severity": "error", @@ -11,17 +22,12 @@ exports[`flags warnings with invalid commenting css snapshot matches warnings 1` }, { "column": 1, + "endColumn": 44, + "endLine": 18, "line": 18, "rule": "comment-empty-line-before", "severity": "error", "text": "Expected empty line before comment (comment-empty-line-before)", }, - { - "column": 131, - "line": 24, - "rule": "max-line-length", - "severity": "error", - "text": "Expected line length to be no more than 80 characters (max-line-length)", - }, ] `; diff --git a/packages/stylelint-config/test/__snapshots__/functions.js.snap b/packages/stylelint-config/test/__snapshots__/functions.js.snap index 2a559eaea33171..aa3ee40e69cc66 100644 --- a/packages/stylelint-config/test/__snapshots__/functions.js.snap +++ b/packages/stylelint-config/test/__snapshots__/functions.js.snap @@ -4,6 +4,8 @@ exports[`flags warnings with invalid functions css snapshot matches warnings 1`] [ { "column": 9, + "endColumn": 13, + "endLine": 4, "line": 4, "rule": "function-name-case", "severity": "error", diff --git a/packages/stylelint-config/test/__snapshots__/index.js.snap b/packages/stylelint-config/test/__snapshots__/index.js.snap index ec660349951647..10c35b02e0e937 100644 --- a/packages/stylelint-config/test/__snapshots__/index.js.snap +++ b/packages/stylelint-config/test/__snapshots__/index.js.snap @@ -4,10 +4,12 @@ exports[`flags warnings with invalid css snapshot matches warnings 1`] = ` [ { "column": 7, + "endColumn": 8, + "endLine": 2, "line": 2, - "rule": "number-leading-zero", + "rule": "@stylistic/number-leading-zero", "severity": "error", - "text": "Expected a leading zero (number-leading-zero)", + "text": "Expected a leading zero (@stylistic/number-leading-zero)", }, ] `; diff --git a/packages/stylelint-config/test/__snapshots__/media-queries.js.snap b/packages/stylelint-config/test/__snapshots__/media-queries.js.snap index 298e30bb24b9c8..93bcf3c13d399c 100644 --- a/packages/stylelint-config/test/__snapshots__/media-queries.js.snap +++ b/packages/stylelint-config/test/__snapshots__/media-queries.js.snap @@ -2,82 +2,104 @@ exports[`flags warnings with invalid media queries css snapshot matches warnings 1`] = ` [ - { - "column": 1, - "line": 31, - "rule": "at-rule-no-unknown", - "severity": "error", - "text": "Unexpected unknown at-rule "@mdia" (at-rule-no-unknown)", - }, { "column": 26, + "endColumn": 27, + "endLine": 1, "line": 1, - "rule": "media-feature-colon-space-after", + "rule": "@stylistic/media-feature-colon-space-after", "severity": "error", - "text": "Expected single space after ":" (media-feature-colon-space-after)", + "text": "Expected single space after ":" (@stylistic/media-feature-colon-space-after)", }, { "column": 27, + "endColumn": 28, + "endLine": 6, "line": 6, - "rule": "media-feature-colon-space-after", + "rule": "@stylistic/media-feature-colon-space-after", "severity": "error", - "text": "Expected single space after ":" (media-feature-colon-space-after)", + "text": "Expected single space after ":" (@stylistic/media-feature-colon-space-after)", }, { "column": 27, + "endColumn": 28, + "endLine": 6, "line": 6, - "rule": "media-feature-colon-space-before", - "severity": "error", - "text": "Unexpected whitespace before ":" (media-feature-colon-space-before)", - }, - { - "column": 17, - "line": 11, - "rule": "media-feature-name-no-unknown", + "rule": "@stylistic/media-feature-colon-space-before", "severity": "error", - "text": "Unexpected unknown media feature name "max-width 699px" (media-feature-name-no-unknown)", + "text": "Unexpected whitespace before ":" (@stylistic/media-feature-colon-space-before)", }, { "column": 28, + "endColumn": 29, + "endLine": 16, "line": 16, - "rule": "media-feature-range-operator-space-after", + "rule": "@stylistic/media-feature-range-operator-space-after", "severity": "error", - "text": "Expected single space after range operator (media-feature-range-operator-space-after)", + "text": "Expected single space after range operator (@stylistic/media-feature-range-operator-space-after)", }, { "column": 29, + "endColumn": 30, + "endLine": 21, "line": 21, - "rule": "media-feature-range-operator-space-after", + "rule": "@stylistic/media-feature-range-operator-space-after", "severity": "error", - "text": "Expected single space after range operator (media-feature-range-operator-space-after)", + "text": "Expected single space after range operator (@stylistic/media-feature-range-operator-space-after)", }, { "column": 25, + "endColumn": 26, + "endLine": 16, "line": 16, - "rule": "media-feature-range-operator-space-before", + "rule": "@stylistic/media-feature-range-operator-space-before", "severity": "error", - "text": "Expected single space before range operator (media-feature-range-operator-space-before)", + "text": "Expected single space before range operator (@stylistic/media-feature-range-operator-space-before)", }, { "column": 25, + "endColumn": 26, + "endLine": 26, "line": 26, - "rule": "media-feature-range-operator-space-before", + "rule": "@stylistic/media-feature-range-operator-space-before", "severity": "error", - "text": "Expected single space before range operator (media-feature-range-operator-space-before)", + "text": "Expected single space before range operator (@stylistic/media-feature-range-operator-space-before)", }, { "column": 27, + "endColumn": 28, + "endLine": 36, "line": 36, - "rule": "media-query-list-comma-space-before", + "rule": "@stylistic/media-query-list-comma-space-before", "severity": "error", - "text": "Unexpected whitespace before "," (media-query-list-comma-space-before)", + "text": "Unexpected whitespace before "," (@stylistic/media-query-list-comma-space-before)", }, { "column": 27, + "endColumn": 28, + "endLine": 40, "line": 40, - "rule": "media-query-list-comma-space-before", + "rule": "@stylistic/media-query-list-comma-space-before", + "severity": "error", + "text": "Unexpected whitespace before "," (@stylistic/media-query-list-comma-space-before)", + }, + { + "column": 1, + "endColumn": 6, + "endLine": 31, + "line": 31, + "rule": "at-rule-no-unknown", + "severity": "error", + "text": "Unexpected unknown at-rule "@mdia" (at-rule-no-unknown)", + }, + { + "column": 17, + "endColumn": 24, + "endLine": 11, + "line": 11, + "rule": "media-feature-name-no-unknown", "severity": "error", - "text": "Unexpected whitespace before "," (media-query-list-comma-space-before)", + "text": "Unexpected unknown media feature name "unknown" (media-feature-name-no-unknown)", }, ] `; diff --git a/packages/stylelint-config/test/__snapshots__/properties.js.snap b/packages/stylelint-config/test/__snapshots__/properties.js.snap index 9bb0ab23954845..a0c36aa885e1f8 100644 --- a/packages/stylelint-config/test/__snapshots__/properties.js.snap +++ b/packages/stylelint-config/test/__snapshots__/properties.js.snap @@ -4,13 +4,35 @@ exports[`flags warnings with invalid properties css snapshot matches warnings 1` [ { "column": 13, + "endColumn": 14, + "endLine": 2, "line": 2, - "rule": "color-hex-case", + "rule": "@stylistic/color-hex-case", "severity": "error", - "text": "Expected "#FFFFFF" to be "#ffffff" (color-hex-case)", + "text": "Expected "#FFFFFF" to be "#ffffff" (@stylistic/color-hex-case)", }, { "column": 13, + "endColumn": 14, + "endLine": 2, + "line": 2, + "rule": "@stylistic/declaration-colon-space-after", + "severity": "error", + "text": "Expected single space after ":" with a single-line declaration (@stylistic/declaration-colon-space-after)", + }, + { + "column": 17, + "endColumn": 19, + "endLine": 4, + "line": 4, + "rule": "@stylistic/unit-case", + "severity": "error", + "text": "Expected "PX" to be "px" (@stylistic/unit-case)", + }, + { + "column": 13, + "endColumn": 20, + "endLine": 2, "line": 2, "rule": "color-hex-length", "severity": "error", @@ -18,34 +40,26 @@ exports[`flags warnings with invalid properties css snapshot matches warnings 1` }, { "column": 2, + "endColumn": 8, + "endLine": 5, "line": 5, "rule": "declaration-block-no-shorthand-property-overrides", "severity": "error", "text": "Unexpected shorthand "margin" after "margin-left" (declaration-block-no-shorthand-property-overrides)", }, - { - "column": 13, - "line": 2, - "rule": "declaration-colon-space-after", - "severity": "error", - "text": "Expected single space after ":" with a single-line declaration (declaration-colon-space-after)", - }, { "column": 2, + "endColumn": 7, + "endLine": 6, "line": 6, "rule": "property-no-unknown", "severity": "error", "text": "Unexpected unknown property "argin" (property-no-unknown)", }, - { - "column": 15, - "line": 4, - "rule": "unit-case", - "severity": "error", - "text": "Expected "PX" to be "px" (unit-case)", - }, { "column": 11, + "endColumn": 16, + "endLine": 3, "line": 3, "rule": "value-keyword-case", "severity": "error", diff --git a/packages/stylelint-config/test/__snapshots__/scss.js.snap b/packages/stylelint-config/test/__snapshots__/scss.js.snap index dd199336323ffe..a1abeef86ac963 100644 --- a/packages/stylelint-config/test/__snapshots__/scss.js.snap +++ b/packages/stylelint-config/test/__snapshots__/scss.js.snap @@ -2,8 +2,37 @@ exports[`flags warnings with invalid scss snapshot matches warnings 1`] = ` [ + { + "column": 5, + "endColumn": 6, + "endLine": 14, + "line": 14, + "rule": "@stylistic/block-opening-brace-space-before", + "severity": "error", + "text": "Expected single space before "{" (@stylistic/block-opening-brace-space-before)", + }, + { + "column": 7, + "endColumn": 8, + "endLine": 31, + "line": 31, + "rule": "@stylistic/number-leading-zero", + "severity": "error", + "text": "Expected a leading zero (@stylistic/number-leading-zero)", + }, + { + "column": 15, + "endColumn": 16, + "endLine": 28, + "line": 28, + "rule": "@stylistic/no-extra-semicolons", + "severity": "error", + "text": "Unexpected extra semicolon (@stylistic/no-extra-semicolons)", + }, { "column": 1, + "endColumn": 6, + "endLine": 14, "line": 14, "rule": "scss/at-else-empty-line-before", "severity": "error", @@ -11,6 +40,8 @@ exports[`flags warnings with invalid scss snapshot matches warnings 1`] = ` }, { "column": 2, + "endColumn": 3, + "endLine": 12, "line": 12, "rule": "scss/at-if-closing-brace-newline-after", "severity": "error", @@ -18,6 +49,8 @@ exports[`flags warnings with invalid scss snapshot matches warnings 1`] = ` }, { "column": 2, + "endColumn": 3, + "endLine": 12, "line": 12, "rule": "scss/at-if-closing-brace-space-after", "severity": "error", @@ -25,6 +58,8 @@ exports[`flags warnings with invalid scss snapshot matches warnings 1`] = ` }, { "column": 1, + "endColumn": 9, + "endLine": 1, "line": 1, "rule": "scss/at-rule-no-unknown", "severity": "error", @@ -32,31 +67,12 @@ exports[`flags warnings with invalid scss snapshot matches warnings 1`] = ` }, { "column": 2, + "endColumn": 15, + "endLine": 22, "line": 22, "rule": "at-rule-empty-line-before", "severity": "error", "text": "Unexpected empty line before at-rule (at-rule-empty-line-before)", }, - { - "column": 5, - "line": 14, - "rule": "block-opening-brace-space-before", - "severity": "error", - "text": "Expected single space before "{" (block-opening-brace-space-before)", - }, - { - "column": 15, - "line": 28, - "rule": "no-extra-semicolons", - "severity": "error", - "text": "Unexpected extra semicolon (no-extra-semicolons)", - }, - { - "column": 7, - "line": 31, - "rule": "number-leading-zero", - "severity": "error", - "text": "Expected a leading zero (number-leading-zero)", - }, ] `; diff --git a/packages/stylelint-config/test/__snapshots__/selectors-scss.js.snap b/packages/stylelint-config/test/__snapshots__/selectors-scss.js.snap index 31cbf77098ec63..ea1746c5383622 100644 --- a/packages/stylelint-config/test/__snapshots__/selectors-scss.js.snap +++ b/packages/stylelint-config/test/__snapshots__/selectors-scss.js.snap @@ -4,6 +4,8 @@ exports[`flags warnings with invalid selectors scss snapshot matches warnings 1` [ { "column": 2, + "endColumn": 3, + "endLine": 3, "line": 3, "rule": "scss/selector-no-redundant-nesting-selector", "severity": "error", @@ -11,6 +13,8 @@ exports[`flags warnings with invalid selectors scss snapshot matches warnings 1` }, { "column": 2, + "endColumn": 3, + "endLine": 10, "line": 10, "rule": "scss/selector-no-redundant-nesting-selector", "severity": "error", @@ -18,6 +22,8 @@ exports[`flags warnings with invalid selectors scss snapshot matches warnings 1` }, { "column": 2, + "endColumn": 3, + "endLine": 17, "line": 17, "rule": "scss/selector-no-redundant-nesting-selector", "severity": "error", @@ -25,6 +31,8 @@ exports[`flags warnings with invalid selectors scss snapshot matches warnings 1` }, { "column": 2, + "endColumn": 3, + "endLine": 24, "line": 24, "rule": "scss/selector-no-redundant-nesting-selector", "severity": "error", @@ -32,6 +40,8 @@ exports[`flags warnings with invalid selectors scss snapshot matches warnings 1` }, { "column": 2, + "endColumn": 3, + "endLine": 31, "line": 31, "rule": "scss/selector-no-redundant-nesting-selector", "severity": "error", @@ -39,6 +49,8 @@ exports[`flags warnings with invalid selectors scss snapshot matches warnings 1` }, { "column": 10, + "endColumn": 11, + "endLine": 31, "line": 31, "rule": "selector-pseudo-element-colon-notation", "severity": "error", diff --git a/packages/stylelint-config/test/__snapshots__/selectors.js.snap b/packages/stylelint-config/test/__snapshots__/selectors.js.snap index 42242da99d4519..f39edbfdb3fa51 100644 --- a/packages/stylelint-config/test/__snapshots__/selectors.js.snap +++ b/packages/stylelint-config/test/__snapshots__/selectors.js.snap @@ -2,8 +2,19 @@ exports[`flags warnings with invalid selectors css snapshot matches warnings 1`] = ` [ + { + "column": 12, + "endColumn": 13, + "endLine": 17, + "line": 17, + "rule": "@stylistic/string-quotes", + "severity": "error", + "text": "Expected double quotes (@stylistic/string-quotes)", + }, { "column": 15, + "endColumn": 19, + "endLine": 18, "line": 18, "rule": "declaration-property-unit-allowed-list", "severity": "error", @@ -11,6 +22,8 @@ exports[`flags warnings with invalid selectors css snapshot matches warnings 1`] }, { "column": 1, + "endColumn": 11, + "endLine": 25, "line": 25, "rule": "selector-class-pattern", "severity": "error", @@ -18,6 +31,8 @@ exports[`flags warnings with invalid selectors css snapshot matches warnings 1`] }, { "column": 1, + "endColumn": 13, + "endLine": 1, "line": 1, "rule": "selector-id-pattern", "severity": "error", @@ -25,6 +40,8 @@ exports[`flags warnings with invalid selectors css snapshot matches warnings 1`] }, { "column": 1, + "endColumn": 14, + "endLine": 5, "line": 5, "rule": "selector-id-pattern", "severity": "error", @@ -32,6 +49,8 @@ exports[`flags warnings with invalid selectors css snapshot matches warnings 1`] }, { "column": 4, + "endColumn": 17, + "endLine": 9, "line": 9, "rule": "selector-id-pattern", "severity": "error", @@ -39,6 +58,8 @@ exports[`flags warnings with invalid selectors css snapshot matches warnings 1`] }, { "column": 1, + "endColumn": 10, + "endLine": 21, "line": 21, "rule": "selector-id-pattern", "severity": "error", @@ -46,17 +67,12 @@ exports[`flags warnings with invalid selectors css snapshot matches warnings 1`] }, { "column": 10, + "endColumn": 11, + "endLine": 29, "line": 29, "rule": "selector-pseudo-element-colon-notation", "severity": "error", "text": "Expected double colon pseudo-element notation (selector-pseudo-element-colon-notation)", }, - { - "column": 12, - "line": 17, - "rule": "string-quotes", - "severity": "error", - "text": "Expected double quotes (string-quotes)", - }, ] `; diff --git a/packages/stylelint-config/test/__snapshots__/structure.js.snap b/packages/stylelint-config/test/__snapshots__/structure.js.snap index b41ef9131547fc..c59cfb0fc29186 100644 --- a/packages/stylelint-config/test/__snapshots__/structure.js.snap +++ b/packages/stylelint-config/test/__snapshots__/structure.js.snap @@ -4,59 +4,75 @@ exports[`flags warnings with invalid structure css snapshot matches warnings 1`] [ { "column": 45, + "endColumn": 46, + "endLine": 7, "line": 7, - "rule": "block-closing-brace-newline-before", + "rule": "@stylistic/block-closing-brace-newline-before", "severity": "error", - "text": "Expected newline before "}" (block-closing-brace-newline-before)", + "text": "Expected newline before "}" (@stylistic/block-closing-brace-newline-before)", }, { "column": 14, + "endColumn": 15, + "endLine": 7, "line": 7, - "rule": "block-opening-brace-newline-after", + "rule": "@stylistic/block-opening-brace-newline-after", "severity": "error", - "text": "Expected newline after "{" (block-opening-brace-newline-after)", + "text": "Expected newline after "{" (@stylistic/block-opening-brace-newline-after)", }, { "column": 32, + "endColumn": 33, + "endLine": 7, "line": 7, - "rule": "declaration-block-semicolon-newline-after", + "rule": "@stylistic/declaration-block-semicolon-newline-after", "severity": "error", - "text": "Expected newline after ";" (declaration-block-semicolon-newline-after)", + "text": "Expected newline after ";" (@stylistic/declaration-block-semicolon-newline-after)", }, { - "column": 12, - "line": 1, - "rule": "selector-list-comma-newline-after", + "column": 3, + "endColumn": 4, + "endLine": 4, + "line": 4, + "rule": "@stylistic/indentation", "severity": "error", - "text": "Expected newline after "," (selector-list-comma-newline-after)", + "text": "Expected indentation of 0 tabs (@stylistic/indentation)", }, { - "column": 25, - "line": 1, - "rule": "selector-list-comma-newline-after", + "column": 3, + "endColumn": 20, + "endLine": 2, + "line": 2, + "rule": "@stylistic/indentation", "severity": "error", - "text": "Expected newline after "," (selector-list-comma-newline-after)", + "text": "Expected indentation of 1 tab (@stylistic/indentation)", }, { "column": 3, - "line": 4, - "rule": "indentation", + "endColumn": 15, + "endLine": 3, + "line": 3, + "rule": "@stylistic/indentation", "severity": "error", - "text": "Expected indentation of 0 tabs (indentation)", + "text": "Expected indentation of 1 tab (@stylistic/indentation)", }, { - "column": 3, - "line": 2, - "rule": "indentation", + "column": 12, + "endColumn": 13, + "endLine": 1, + "line": 1, + "rule": "@stylistic/selector-list-comma-newline-after", "severity": "error", - "text": "Expected indentation of 1 tab (indentation)", + "text": "Expected newline after "," (@stylistic/selector-list-comma-newline-after)", }, { - "column": 3, - "line": 3, - "rule": "indentation", + "column": 25, + "endColumn": 26, + "endLine": 1, + "line": 1, + "rule": "@stylistic/selector-list-comma-newline-after", "severity": "error", - "text": "Expected indentation of 1 tab (indentation)", + "text": "Expected newline after "," (@stylistic/selector-list-comma-newline-after)", }, ] `; diff --git a/packages/stylelint-config/test/__snapshots__/values.js.snap b/packages/stylelint-config/test/__snapshots__/values.js.snap index 2331e0364e5c73..95c34fcbfc8d44 100644 --- a/packages/stylelint-config/test/__snapshots__/values.js.snap +++ b/packages/stylelint-config/test/__snapshots__/values.js.snap @@ -4,20 +4,26 @@ exports[`flags warnings with invalid values css snapshot matches warnings 1`] = [ { "column": 16, + "endColumn": 17, + "endLine": 2, "line": 2, - "rule": "declaration-block-trailing-semicolon", + "rule": "@stylistic/declaration-block-trailing-semicolon", "severity": "error", - "text": "Expected a trailing semicolon (declaration-block-trailing-semicolon)", + "text": "Expected a trailing semicolon (@stylistic/declaration-block-trailing-semicolon)", }, { "column": 13, + "endColumn": 14, + "endLine": 2, "line": 2, - "rule": "declaration-colon-space-after", + "rule": "@stylistic/declaration-colon-space-after", "severity": "error", - "text": "Expected single space after ":" with a single-line declaration (declaration-colon-space-after)", + "text": "Expected single space after ":" with a single-line declaration (@stylistic/declaration-colon-space-after)", }, { "column": 15, + "endColumn": 20, + "endLine": 12, "line": 12, "rule": "declaration-property-unit-allowed-list", "severity": "error", @@ -25,6 +31,8 @@ exports[`flags warnings with invalid values css snapshot matches warnings 1`] = }, { "column": 15, + "endColumn": 30, + "endLine": 10, "line": 10, "rule": "font-family-name-quotes", "severity": "error", @@ -32,13 +40,17 @@ exports[`flags warnings with invalid values css snapshot matches warnings 1`] = }, { "column": 15, + "endColumn": 19, + "endLine": 11, "line": 11, "rule": "font-weight-notation", "severity": "error", - "text": "Expected numeric font-weight notation (font-weight-notation)", + "text": "Expected "bold" to be "700" (font-weight-notation)", }, { "column": 11, + "endColumn": 13, + "endLine": 6, "line": 6, "rule": "length-zero-no-unit", "severity": "error", @@ -46,6 +58,8 @@ exports[`flags warnings with invalid values css snapshot matches warnings 1`] = }, { "column": 15, + "endColumn": 17, + "endLine": 6, "line": 6, "rule": "length-zero-no-unit", "severity": "error", @@ -53,6 +67,8 @@ exports[`flags warnings with invalid values css snapshot matches warnings 1`] = }, { "column": 24, + "endColumn": 26, + "endLine": 6, "line": 6, "rule": "length-zero-no-unit", "severity": "error", @@ -60,6 +76,8 @@ exports[`flags warnings with invalid values css snapshot matches warnings 1`] = }, { "column": 1, + "endColumn": 10, + "endLine": 15, "line": 15, "rule": "no-duplicate-selectors", "severity": "error", diff --git a/packages/stylelint-config/test/commenting.js b/packages/stylelint-config/test/commenting.js index 1a23a47434fc10..dde02f605faf14 100644 --- a/packages/stylelint-config/test/commenting.js +++ b/packages/stylelint-config/test/commenting.js @@ -1,30 +1,14 @@ -/** - * External dependencies - */ -const fs = require( 'fs' ), - stylelint = require( 'stylelint' ); - /** * Internal dependencies */ -const config = require( '../' ), - validCss = fs.readFileSync( - './packages/stylelint-config/test/commenting-valid.css', - 'utf-8' - ), - invalidCss = fs.readFileSync( - './packages/stylelint-config/test/commenting-invalid.css', - 'utf-8' - ); +const utils = require( './utils' ); +const getStylelintResult = utils.getStylelintResult; describe( 'flags no warnings with valid commenting css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: validCss, - config, - } ); + result = getStylelintResult( './commenting-valid.css' ); } ); it( 'did not error', () => { @@ -42,10 +26,7 @@ describe( 'flags warnings with invalid commenting css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: invalidCss, - config, - } ); + result = getStylelintResult( './commenting-invalid.css' ); } ); it( 'did error', () => { diff --git a/packages/stylelint-config/test/functions.js b/packages/stylelint-config/test/functions.js index 38b0fbf37a3a87..d6fb2a7ddf84e0 100644 --- a/packages/stylelint-config/test/functions.js +++ b/packages/stylelint-config/test/functions.js @@ -1,30 +1,14 @@ -/** - * External dependencies - */ -const fs = require( 'fs' ), - stylelint = require( 'stylelint' ); - /** * Internal dependencies */ -const config = require( '../' ), - validCss = fs.readFileSync( - './packages/stylelint-config/test/functions-valid.css', - 'utf-8' - ), - invalidCss = fs.readFileSync( - './packages/stylelint-config/test/functions-invalid.css', - 'utf-8' - ); +const utils = require( './utils' ); +const getStylelintResult = utils.getStylelintResult; describe( 'flags no warnings with valid functions css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: validCss, - config, - } ); + result = getStylelintResult( './functions-valid.css' ); } ); it( 'did not error', () => { @@ -42,10 +26,7 @@ describe( 'flags warnings with invalid functions css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: invalidCss, - config, - } ); + result = getStylelintResult( './functions-invalid.css' ); } ); it( 'did error', () => { diff --git a/packages/stylelint-config/test/index.js b/packages/stylelint-config/test/index.js index dfc857e8a45041..d974a9ac110f73 100644 --- a/packages/stylelint-config/test/index.js +++ b/packages/stylelint-config/test/index.js @@ -1,30 +1,14 @@ -/** - * External dependencies - */ -const fs = require( 'fs' ), - stylelint = require( 'stylelint' ); - /** * Internal dependencies */ -const config = require( '../' ), - validCss = fs.readFileSync( - './packages/stylelint-config/test/css-valid.css', - 'utf-8' - ), - invalidCss = fs.readFileSync( - './packages/stylelint-config/test/css-invalid.css', - 'utf-8' - ); +const utils = require( './utils' ); +const getStylelintResult = utils.getStylelintResult; describe( 'flags no warnings with valid css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: validCss, - config, - } ); + result = getStylelintResult( './css-valid.css' ); } ); it( 'did not error', () => { @@ -42,10 +26,7 @@ describe( 'flags warnings with invalid css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: invalidCss, - config, - } ); + result = getStylelintResult( './css-invalid.css' ); } ); it( 'did error', () => { diff --git a/packages/stylelint-config/test/media-queries-invalid.css b/packages/stylelint-config/test/media-queries-invalid.css index c89a2776bb807b..8fff7111065e0f 100644 --- a/packages/stylelint-config/test/media-queries-invalid.css +++ b/packages/stylelint-config/test/media-queries-invalid.css @@ -8,7 +8,7 @@ /* Your selectors */ } -@media all and (max-width 699px) { +@media all and (unknown) { /* Your selectors */ } diff --git a/packages/stylelint-config/test/media-queries.js b/packages/stylelint-config/test/media-queries.js index a3b59aa0fb5413..6b8390e7933b99 100644 --- a/packages/stylelint-config/test/media-queries.js +++ b/packages/stylelint-config/test/media-queries.js @@ -1,30 +1,14 @@ -/** - * External dependencies - */ -const fs = require( 'fs' ), - stylelint = require( 'stylelint' ); - /** * Internal dependencies */ -const config = require( '../' ), - validCss = fs.readFileSync( - './packages/stylelint-config/test/media-queries-valid.css', - 'utf-8' - ), - invalidCss = fs.readFileSync( - './packages/stylelint-config/test/media-queries-invalid.css', - 'utf-8' - ); +const utils = require( './utils' ); +const getStylelintResult = utils.getStylelintResult; describe( 'flags no warnings with valid media queries css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: validCss, - config, - } ); + result = getStylelintResult( './media-queries-valid.css' ); } ); it( 'did not error', () => { @@ -42,10 +26,7 @@ describe( 'flags warnings with invalid media queries css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: invalidCss, - config, - } ); + result = getStylelintResult( './media-queries-invalid.css' ); } ); it( 'did error', () => { diff --git a/packages/stylelint-config/test/properties.js b/packages/stylelint-config/test/properties.js index 35cedc7697515d..51dded0543d438 100644 --- a/packages/stylelint-config/test/properties.js +++ b/packages/stylelint-config/test/properties.js @@ -1,30 +1,14 @@ -/** - * External dependencies - */ -const fs = require( 'fs' ), - stylelint = require( 'stylelint' ); - /** * Internal dependencies */ -const config = require( '../' ), - validCss = fs.readFileSync( - './packages/stylelint-config/test/properties-valid.css', - 'utf-8' - ), - invalidCss = fs.readFileSync( - './packages/stylelint-config/test/properties-invalid.css', - 'utf-8' - ); +const utils = require( './utils' ); +const getStylelintResult = utils.getStylelintResult; describe( 'flags no warnings with valid properties css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: validCss, - config, - } ); + result = getStylelintResult( './properties-valid.css' ); } ); it( 'did not error', () => { @@ -42,10 +26,7 @@ describe( 'flags warnings with invalid properties css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: invalidCss, - config, - } ); + result = getStylelintResult( './properties-invalid.css' ); } ); it( 'did error', () => { diff --git a/packages/stylelint-config/test/scss.js b/packages/stylelint-config/test/scss.js index 9372d502b0d8a4..efe01c3d0f2cc0 100644 --- a/packages/stylelint-config/test/scss.js +++ b/packages/stylelint-config/test/scss.js @@ -1,30 +1,14 @@ -/** - * External dependencies - */ -const fs = require( 'fs' ), - stylelint = require( 'stylelint' ); - /** * Internal dependencies */ -const config = require( '../scss' ), - validScss = fs.readFileSync( - './packages/stylelint-config/test/scss-valid.scss', - 'utf-8' - ), - invalidScss = fs.readFileSync( - './packages/stylelint-config/test/scss-invalid.scss', - 'utf-8' - ); +const utils = require( './utils' ); +const getStylelintResult = utils.getStylelintResult; describe( 'flags no warnings with valid scss', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: validScss, - config, - } ); + result = getStylelintResult( './scss-valid.scss' ); } ); it( 'did not error', () => { @@ -42,10 +26,7 @@ describe( 'flags warnings with invalid scss', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: invalidScss, - config, - } ); + result = getStylelintResult( './scss-invalid.scss' ); } ); it( 'did error', () => { diff --git a/packages/stylelint-config/test/selectors-scss.js b/packages/stylelint-config/test/selectors-scss.js index 94a85ff86543e0..5ec1f2fbd1b427 100644 --- a/packages/stylelint-config/test/selectors-scss.js +++ b/packages/stylelint-config/test/selectors-scss.js @@ -1,30 +1,14 @@ -/** - * External dependencies - */ -const fs = require( 'fs' ), - stylelint = require( 'stylelint' ); - /** * Internal dependencies */ -const config = require( '../scss' ), - validScss = fs.readFileSync( - './packages/stylelint-config/test/selectors-valid.scss', - 'utf-8' - ), - invalidScss = fs.readFileSync( - './packages/stylelint-config/test/selectors-invalid.scss', - 'utf-8' - ); +const utils = require( './utils' ); +const getStylelintResult = utils.getStylelintResult; describe( 'flags no warnings with valid selectors scss', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: validScss, - config, - } ); + result = getStylelintResult( './selectors-valid.scss' ); } ); it( 'did not error', () => { @@ -42,10 +26,7 @@ describe( 'flags warnings with invalid selectors scss', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: invalidScss, - config, - } ); + result = getStylelintResult( './selectors-invalid.scss' ); } ); it( 'did error', () => { diff --git a/packages/stylelint-config/test/selectors.js b/packages/stylelint-config/test/selectors.js index 337d1d00eed311..276ac875489613 100644 --- a/packages/stylelint-config/test/selectors.js +++ b/packages/stylelint-config/test/selectors.js @@ -1,30 +1,14 @@ -/** - * External dependencies - */ -const fs = require( 'fs' ), - stylelint = require( 'stylelint' ); - /** * Internal dependencies */ -const config = require( '../' ), - validCss = fs.readFileSync( - './packages/stylelint-config/test/selectors-valid.css', - 'utf-8' - ), - invalidCss = fs.readFileSync( - './packages/stylelint-config/test/selectors-invalid.css', - 'utf-8' - ); +const utils = require( './utils' ); +const getStylelintResult = utils.getStylelintResult; describe( 'flags no warnings with valid selectors css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: validCss, - config, - } ); + result = getStylelintResult( './selectors-valid.css' ); } ); it( 'did not error', () => { @@ -42,10 +26,7 @@ describe( 'flags warnings with invalid selectors css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: invalidCss, - config, - } ); + result = getStylelintResult( './selectors-invalid.css' ); } ); it( 'did error', () => { diff --git a/packages/stylelint-config/test/structure.js b/packages/stylelint-config/test/structure.js index 7ec03a3b667bac..29dc22a35daf14 100644 --- a/packages/stylelint-config/test/structure.js +++ b/packages/stylelint-config/test/structure.js @@ -1,30 +1,14 @@ -/** - * External dependencies - */ -const fs = require( 'fs' ), - stylelint = require( 'stylelint' ); - /** * Internal dependencies */ -const config = require( '../' ), - validCss = fs.readFileSync( - './packages/stylelint-config/test/structure-valid.css', - 'utf-8' - ), - invalidCss = fs.readFileSync( - './packages/stylelint-config/test/structure-invalid.css', - 'utf-8' - ); +const utils = require( './utils' ); +const getStylelintResult = utils.getStylelintResult; describe( 'flags no warnings with valid structure css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: validCss, - config, - } ); + result = getStylelintResult( './structure-valid.css' ); } ); it( 'did not error', () => { @@ -42,10 +26,7 @@ describe( 'flags warnings with invalid structure css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: invalidCss, - config, - } ); + result = getStylelintResult( './structure-invalid.css' ); } ); it( 'did error', () => { diff --git a/packages/stylelint-config/test/themes.js b/packages/stylelint-config/test/themes.js index f0016832b24d7b..0a25c6e871df7e 100644 --- a/packages/stylelint-config/test/themes.js +++ b/packages/stylelint-config/test/themes.js @@ -1,26 +1,14 @@ -/** - * External dependencies - */ -const fs = require( 'fs' ), - stylelint = require( 'stylelint' ); - /** * Internal dependencies */ -const config = require( '../' ), - validCss = fs.readFileSync( - './packages/stylelint-config/test/themes-valid.css', - 'utf-8' - ); +const utils = require( './utils' ); +const getStylelintResult = utils.getStylelintResult; describe( 'flags no warnings with valid css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: validCss, - config, - } ); + result = getStylelintResult( './themes-valid.css' ); } ); it( 'did not error', () => { diff --git a/packages/stylelint-config/test/utils/index.js b/packages/stylelint-config/test/utils/index.js new file mode 100644 index 00000000000000..c24e04f0a67a45 --- /dev/null +++ b/packages/stylelint-config/test/utils/index.js @@ -0,0 +1,34 @@ +/** + * External dependencies + */ +const util = require( 'node:util' ), + path = require( 'node:path' ), + childProcess = require( 'node:child_process' ); + +const execute = util.promisify( childProcess.exec ); + +const generateStylelintCommand = ( filename ) => + 'npx stylelint ' + + path.resolve( __dirname, '../', filename ) + + ' -c' + + path.resolve( __dirname, '../', './.stylelintrc.tests.json' ) + + ' --formatter json' + + ' --ignore-path ' + + path.resolve( __dirname, '../', './.stylelintignore' ); + +module.exports = { + getStylelintResult: ( filename ) => + execute( generateStylelintCommand( filename ) ) + .then( ( { stderr } ) => { + return { + errored: false, + results: JSON.parse( stderr ), + }; + } ) + .catch( ( { stderr } ) => { + return { + errored: true, + results: JSON.parse( stderr ), + }; + } ), +}; diff --git a/packages/stylelint-config/test/values.js b/packages/stylelint-config/test/values.js index 97cbc58e02f3b4..749a50a94c2044 100644 --- a/packages/stylelint-config/test/values.js +++ b/packages/stylelint-config/test/values.js @@ -1,30 +1,14 @@ -/** - * External dependencies - */ -const fs = require( 'fs' ), - stylelint = require( 'stylelint' ); - /** * Internal dependencies */ -const config = require( '../' ), - validCss = fs.readFileSync( - './packages/stylelint-config/test/values-valid.css', - 'utf-8' - ), - invalidCss = fs.readFileSync( - './packages/stylelint-config/test/values-invalid.css', - 'utf-8' - ); +const utils = require( './utils' ); +const getStylelintResult = utils.getStylelintResult; describe( 'flags no warnings with valid values css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: validCss, - config, - } ); + result = getStylelintResult( './values-valid.css' ); } ); it( 'did not error', () => { @@ -42,10 +26,7 @@ describe( 'flags warnings with invalid values css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: invalidCss, - config, - } ); + result = getStylelintResult( './values-invalid.css' ); } ); it( 'did error', () => { diff --git a/packages/stylelint-config/test/vendor-prefixes.js b/packages/stylelint-config/test/vendor-prefixes.js index e3ec4d2a7e5dfc..bc3e1f571aee57 100644 --- a/packages/stylelint-config/test/vendor-prefixes.js +++ b/packages/stylelint-config/test/vendor-prefixes.js @@ -1,26 +1,14 @@ -/** - * External dependencies - */ -const fs = require( 'fs' ), - stylelint = require( 'stylelint' ); - /** * Internal dependencies */ -const config = require( '../' ), - validCss = fs.readFileSync( - './packages/stylelint-config/test/vendor-prefixes-valid.css', - 'utf-8' - ); +const utils = require( './utils' ); +const getStylelintResult = utils.getStylelintResult; describe( 'flags no warnings with valid vendor prefixes css', () => { let result; beforeEach( () => { - result = stylelint.lint( { - code: validCss, - config, - } ); + result = getStylelintResult( './vendor-prefixes-valid.css' ); } ); it( 'did not error', () => { From 0e671a2eca9c78dfdb45b2149ce9e3fb5bf3ae4a Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Thu, 12 Sep 2024 10:18:02 +0100 Subject: [PATCH 0772/1908] Show top level sections in List View in Zoom Out mode (#65202) * Show top level sections in List View * Recompute enabled clientIds when editorMode changes * Revert initial changes * Avoid special conditional for Zoom Out mode --- .../block-editor/src/components/list-view/index.js | 11 +++-------- packages/block-editor/src/store/private-selectors.js | 1 + 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/list-view/index.js b/packages/block-editor/src/components/list-view/index.js index 1493fa655a5aac..87599ea870913b 100644 --- a/packages/block-editor/src/components/list-view/index.js +++ b/packages/block-editor/src/components/list-view/index.js @@ -119,20 +119,16 @@ function ListViewComponent( const blockIndexes = useListViewBlockIndexes( clientIdsTree ); const { getBlock } = useSelect( blockEditorStore ); - const { visibleBlockCount, shouldShowInnerBlocks } = useSelect( + const { visibleBlockCount } = useSelect( ( select ) => { - const { - getGlobalBlockCount, - getClientIdsOfDescendants, - __unstableGetEditorMode, - } = select( blockEditorStore ); + const { getGlobalBlockCount, getClientIdsOfDescendants } = + select( blockEditorStore ); const draggedBlockCount = draggedClientIds?.length > 0 ? getClientIdsOfDescendants( draggedClientIds ).length + 1 : 0; return { visibleBlockCount: getGlobalBlockCount() - draggedBlockCount, - shouldShowInnerBlocks: __unstableGetEditorMode() !== 'zoom-out', }; }, [ draggedClientIds ] @@ -397,7 +393,6 @@ function ListViewComponent( fixedListWindow={ fixedListWindow } selectedClientIds={ selectedClientIds } isExpanded={ isExpanded } - shouldShowInnerBlocks={ shouldShowInnerBlocks } showAppender={ showAppender } /> </ListViewContext.Provider> diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index b72ebd18183377..d76f90bc94ffe1 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -114,6 +114,7 @@ export const getEnabledClientIdsTree = createSelector( state.blockEditingModes, state.settings.templateLock, state.blockListSettings, + state.editorMode, ] ); From 394288f5343b92738ab086b97f62e15262845a35 Mon Sep 17 00:00:00 2001 From: Akshat Kakkad <87222220+AKSHAT2802@users.noreply.github.com> Date: Thu, 12 Sep 2024 15:23:49 +0530 Subject: [PATCH 0773/1908] Add __next40pxDefaultSize for files in editor 4 (#65140) * Add __next40pxDefaultSize in button for editor 3 files * address feedback Co-authored-by: AKSHAT2802 <akshat2802@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../editor/src/components/start-template-options/index.js | 3 +-- packages/editor/src/components/table-of-contents/index.js | 3 +-- packages/editor/src/components/text-editor/index.js | 3 +-- packages/editor/src/components/text-editor/style.scss | 2 +- packages/editor/src/dataviews/actions/reset-post.tsx | 6 ++---- packages/editor/src/dataviews/actions/trash-post.tsx | 6 ++---- 6 files changed, 8 insertions(+), 15 deletions(-) diff --git a/packages/editor/src/components/start-template-options/index.js b/packages/editor/src/components/start-template-options/index.js index e86531272b54fd..3651c5c029a2c7 100644 --- a/packages/editor/src/components/start-template-options/index.js +++ b/packages/editor/src/components/start-template-options/index.js @@ -156,8 +156,7 @@ function StartModal( { slug, isCustom, onClose, postType } ) { > <FlexItem> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" onClick={ onClose } > diff --git a/packages/editor/src/components/table-of-contents/index.js b/packages/editor/src/components/table-of-contents/index.js index f2c79fb0347446..6fd83557b13ab7 100644 --- a/packages/editor/src/components/table-of-contents/index.js +++ b/packages/editor/src/components/table-of-contents/index.js @@ -30,8 +30,7 @@ function TableOfContents( contentClassName="table-of-contents__popover" renderToggle={ ( { isOpen, onToggle } ) => ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize { ...props } ref={ ref } onClick={ hasBlocks ? onToggle : undefined } diff --git a/packages/editor/src/components/text-editor/index.js b/packages/editor/src/components/text-editor/index.js index 6bfe2a5375a35e..fa0688859b5a69 100644 --- a/packages/editor/src/components/text-editor/index.js +++ b/packages/editor/src/components/text-editor/index.js @@ -40,8 +40,7 @@ export default function TextEditor( { autoFocus = false } ) { <div className="editor-text-editor__toolbar"> <h2>{ __( 'Editing code' ) }</h2> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" onClick={ () => switchEditorMode( 'visual' ) } shortcut={ shortcut } diff --git a/packages/editor/src/components/text-editor/style.scss b/packages/editor/src/components/text-editor/style.scss index c8589fed6de6e3..9b2748e08fc5cf 100644 --- a/packages/editor/src/components/text-editor/style.scss +++ b/packages/editor/src/components/text-editor/style.scss @@ -63,7 +63,7 @@ } h2 { - line-height: $button-size; + line-height: $button-size-next-default-40px; margin: 0 auto 0 0; font-size: $default-font-size; color: $gray-900; diff --git a/packages/editor/src/dataviews/actions/reset-post.tsx b/packages/editor/src/dataviews/actions/reset-post.tsx index 64396e45c392ff..d0b5521a34833d 100644 --- a/packages/editor/src/dataviews/actions/reset-post.tsx +++ b/packages/editor/src/dataviews/actions/reset-post.tsx @@ -114,8 +114,7 @@ const resetPost: Action< Post > = { </Text> <HStack justify="right"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" onClick={ closeModal } disabled={ isBusy } @@ -124,8 +123,7 @@ const resetPost: Action< Post > = { { __( 'Cancel' ) } </Button> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" onClick={ async () => { setIsBusy( true ); diff --git a/packages/editor/src/dataviews/actions/trash-post.tsx b/packages/editor/src/dataviews/actions/trash-post.tsx index 1e2b3639dddc83..befbfb0ee7ffba 100644 --- a/packages/editor/src/dataviews/actions/trash-post.tsx +++ b/packages/editor/src/dataviews/actions/trash-post.tsx @@ -67,8 +67,7 @@ const trashPost: Action< PostWithPermissions > = { </Text> <HStack justify="right"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" onClick={ closeModal } disabled={ isBusy } @@ -77,8 +76,7 @@ const trashPost: Action< PostWithPermissions > = { { __( 'Cancel' ) } </Button> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" onClick={ async () => { setIsBusy( true ); From a76c4759f2989e9107984379bf3b61ae9bfd3c58 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Thu, 12 Sep 2024 10:56:01 +0100 Subject: [PATCH 0774/1908] Close inserter on exiting Zoom Out to edit (#65194) * Use experimental setting in single call location * Close inserter on double click to exit Zoom Out * Avoid additional store subscription --- .../use-block-props/use-zoom-out-mode-exit.js | 14 +++++++++++++- .../src/components/block-tools/zoom-out-toolbar.js | 11 +++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js b/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js index bb6edd066f06f1..1944cfde96c7f3 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { useDispatch } from '@wordpress/data'; +import { useSelect, useDispatch } from '@wordpress/data'; import { useRefEffect } from '@wordpress/compose'; /** @@ -16,6 +16,10 @@ import { unlock } from '../../../lock-unlock'; * @param {string} clientId Block client ID. */ export function useZoomOutModeExit( { editorMode } ) { + const getSettings = useSelect( + ( select ) => select( blockEditorStore ).getSettings + ); + const { __unstableSetEditorMode } = unlock( useDispatch( blockEditorStore ) ); @@ -29,6 +33,14 @@ export function useZoomOutModeExit( { editorMode } ) { function onDoubleClick( event ) { if ( ! event.defaultPrevented ) { event.preventDefault(); + + const { __experimentalSetIsInserterOpened } = getSettings(); + + if ( + typeof __experimentalSetIsInserterOpened === 'function' + ) { + __experimentalSetIsInserterOpened( false ); + } __unstableSetEditorMode( 'edit' ); } } diff --git a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js index 0d3df9e20dfc54..a3c46c4b4c970a 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js @@ -31,7 +31,12 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { getPreviousBlockClientId, canRemoveBlock, canMoveBlock, + getSettings, } = select( blockEditorStore ); + + const { __experimentalSetIsInserterOpened: setIsInserterOpened } = + getSettings(); + const { getBlockType } = select( blocksStore ); const { name } = getBlock( clientId ); const blockType = getBlockType( name ); @@ -63,6 +68,7 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { isPrevBlockTemplatePart, canRemove: canRemoveBlock( clientId ), canMove: canMoveBlock( clientId ), + setIsInserterOpened, }; }, [ clientId ] @@ -75,6 +81,7 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { isPrevBlockTemplatePart, canRemove, canMove, + setIsInserterOpened, } = selected; const { removeBlock, __unstableSetEditorMode } = @@ -132,6 +139,10 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { icon={ edit } label={ __( 'Edit' ) } onClick={ () => { + // Setting may be undefined. + if ( typeof setIsInserterOpened === 'function' ) { + setIsInserterOpened( false ); + } __unstableSetEditorMode( 'edit' ); __unstableContentRef.current?.focus(); } } From 1a60dff84c2effe1a3461d582de8238a7cd0d81f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:30:27 +0200 Subject: [PATCH 0775/1908] Make `wordpress/fields` a private package (#65269) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- docs/manifest.json | 6 ------ packages/fields/package.json | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/manifest.json b/docs/manifest.json index d7f74d47995b63..e4eba19d99fa29 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1697,12 +1697,6 @@ "markdown_source": "../packages/eslint-plugin/README.md", "parent": "packages" }, - { - "title": "@wordpress/fields", - "slug": "packages-fields", - "markdown_source": "../packages/fields/README.md", - "parent": "packages" - }, { "title": "@wordpress/format-library", "slug": "packages-format-library", diff --git a/packages/fields/package.json b/packages/fields/package.json index 4d5d33a10e5ed5..e953b34264901f 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -9,6 +9,7 @@ "gutenberg", "dataviews" ], + "private": true, "homepage": "https://github.com/WordPress/gutenberg/tree/HEAD/packages/fields/README.md", "repository": { "type": "git", From 9bdfebfa6760fcc9f1d11a185ecb2940d475fcb5 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:33:24 +0200 Subject: [PATCH 0776/1908] Build Plugin: Simplify and improve zip contents (#65232) Include all of /build directory. Behavior is largely unchanged but logic is simplified. Exclude directory entries. Directory structure is preserved but irrelevant directory attributes are excluded. --- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- bin/build-plugin-zip.sh | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/bin/build-plugin-zip.sh b/bin/build-plugin-zip.sh index ad627e05f0c693..c823ca6a8017f1 100755 --- a/bin/build-plugin-zip.sh +++ b/bin/build-plugin-zip.sh @@ -78,26 +78,15 @@ npm run build php bin/generate-gutenberg-php.php > gutenberg.tmp.php mv gutenberg.tmp.php gutenberg.php -build_files=$( - ls build/*/*.{js,js.map,css,asset.php} \ - build/block-library/blocks/*.php \ - build/block-library/blocks/*/block.json \ - build/block-library/blocks/*/*.{js,js.map,css,asset.php} \ - build/edit-widgets/blocks/*/block.json \ - build/widgets/blocks/*.php \ - build/widgets/blocks/*/block.json \ - build/style-engine/*.php \ -) - - # Generate the plugin zip file. status "Creating archive... 🎁" -zip -r gutenberg.zip \ +zip --recurse-paths --no-dir-entries \ + gutenberg.zip \ gutenberg.php \ lib \ packages/block-serialization-default-parser/*.php \ post-content.php \ - $build_files \ + build \ build-module \ readme.txt \ changelog.txt \ From f88e6297fa3b3b9de3586e63f0fe12db88afb8eb Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:57:58 +0200 Subject: [PATCH 0777/1908] A11y: Add Script Module (#65101) Add a `@wordpress/a11y` WordPress Script Module. The script module has the same public API as the `wp-a11y` script. - The `domReady` package should not be necessary. Since modules are deferred, setup can be called directly when the module is evaluated. - There is no i18n script module at this time. The necessary string "Notifications" is translated on the server and passed to the package via script module data. - Most of the changes here are moving some functions around so that the script and the module form of this package rely on the same underlying implementations. --- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- lib/experimental/script-modules.php | 27 +++++++ packages/a11y/README.md | 2 +- packages/a11y/package.json | 1 + packages/a11y/src/index.js | 75 +---------------- packages/a11y/src/index.native.js | 2 +- packages/a11y/src/module/index.ts | 25 ++++++ .../a11y/src/{ => shared}/add-container.js | 0 .../add-intro-text.ts} | 10 +-- packages/a11y/src/{ => shared}/clear.js | 0 .../a11y/src/{ => shared}/filter-message.js | 0 packages/a11y/src/shared/index.js | 81 +++++++++++++++++++ .../{ => shared}/test/add-container.test.js | 0 .../a11y/src/{ => shared}/test/clear.test.js | 0 .../{ => shared}/test/filter-message.test.js | 0 packages/a11y/src/test/index.test.js | 8 +- .../lib/util.js | 7 +- 16 files changed, 151 insertions(+), 87 deletions(-) create mode 100644 packages/a11y/src/module/index.ts rename packages/a11y/src/{ => shared}/add-container.js (100%) rename packages/a11y/src/{add-intro-text.js => shared/add-intro-text.ts} (83%) rename packages/a11y/src/{ => shared}/clear.js (100%) rename packages/a11y/src/{ => shared}/filter-message.js (100%) create mode 100644 packages/a11y/src/shared/index.js rename packages/a11y/src/{ => shared}/test/add-container.test.js (100%) rename packages/a11y/src/{ => shared}/test/clear.test.js (100%) rename packages/a11y/src/{ => shared}/test/filter-message.test.js (100%) diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index 5a14e1418ed6de..a113df02b9d758 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -200,3 +200,30 @@ function gutenberg_dequeue_module( $module_identifier ) { _deprecated_function( __FUNCTION__, 'Gutenberg 17.6.0', 'wp_dequeue_script_module' ); wp_script_modules()->dequeue( $module_identifier ); } + +/** + * Registers Gutenberg Script Modules. + * + * @since 19.3 + */ +function gutenberg_register_script_modules() { + // When in production, use the plugin's version as the default asset version; + // else (for development or test) default to use the current time. + $default_version = defined( 'GUTENBERG_VERSION' ) && ! SCRIPT_DEBUG ? GUTENBERG_VERSION : time(); + + wp_deregister_script_module( '@wordpress/a11y' ); + wp_register_script_module( + '@wordpress/a11y', + gutenberg_url( 'build-module/a11y/index.min.js' ), + array(), + $default_version + ); + add_filter( + 'script_module_data_@wordpress/a11y', + function ( $data ) { + $data['i18n'] = array( 'Notifications' => __( 'Notifications', 'default' ) ); + return $data; + } + ); +} +add_action( 'init', 'gutenberg_register_script_modules' ); diff --git a/packages/a11y/README.md b/packages/a11y/README.md index 0f40d9edd010ed..755396d2bb8f09 100644 --- a/packages/a11y/README.md +++ b/packages/a11y/README.md @@ -39,7 +39,7 @@ speak( 'The message you want to send to the ARIA live region', 'assertive' ); _Parameters_ - _message_ `string`: The message to be announced by assistive technologies. -- _ariaLive_ `[string]`: The politeness level for aria-live; default: 'polite'. +- _ariaLive_ `['polite'|'assertive']`: The politeness level for aria-live; default: 'polite'. <!-- END TOKEN(Autogenerated API docs) --> diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 88123b3c6c7126..327d6b9ff07167 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -28,6 +28,7 @@ "module": "build-module/index.js", "react-native": "src/index", "types": "build-types", + "wpScriptModuleExports": "./build-module/module/index.js", "dependencies": { "@babel/runtime": "^7.16.0", "@wordpress/dom-ready": "file:../dom-ready", diff --git a/packages/a11y/src/index.js b/packages/a11y/src/index.js index 957c76500c4344..59e93da780bd81 100644 --- a/packages/a11y/src/index.js +++ b/packages/a11y/src/index.js @@ -2,87 +2,20 @@ * WordPress dependencies */ import domReady from '@wordpress/dom-ready'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import addIntroText from './add-intro-text'; -import addContainer from './add-container'; -import clear from './clear'; -import filterMessage from './filter-message'; +import { makeSetupFunction } from './shared/index'; +export { speak } from './shared/index'; /** * Create the live regions. */ -export function setup() { - const introText = document.getElementById( 'a11y-speak-intro-text' ); - const containerAssertive = document.getElementById( - 'a11y-speak-assertive' - ); - const containerPolite = document.getElementById( 'a11y-speak-polite' ); - - if ( introText === null ) { - addIntroText(); - } - - if ( containerAssertive === null ) { - addContainer( 'assertive' ); - } - - if ( containerPolite === null ) { - addContainer( 'polite' ); - } -} +export const setup = makeSetupFunction( __( 'Notifications' ) ); /** * Run setup on domReady. */ domReady( setup ); - -/** - * Allows you to easily announce dynamic interface updates to screen readers using ARIA live regions. - * This module is inspired by the `speak` function in `wp-a11y.js`. - * - * @param {string} message The message to be announced by assistive technologies. - * @param {string} [ariaLive] The politeness level for aria-live; default: 'polite'. - * - * @example - * ```js - * import { speak } from '@wordpress/a11y'; - * - * // For polite messages that shouldn't interrupt what screen readers are currently announcing. - * speak( 'The message you want to send to the ARIA live region' ); - * - * // For assertive messages that should interrupt what screen readers are currently announcing. - * speak( 'The message you want to send to the ARIA live region', 'assertive' ); - * ``` - */ -export function speak( message, ariaLive ) { - /* - * Clear previous messages to allow repeated strings being read out and hide - * the explanatory text from assistive technologies. - */ - clear(); - - message = filterMessage( message ); - - const introText = document.getElementById( 'a11y-speak-intro-text' ); - const containerAssertive = document.getElementById( - 'a11y-speak-assertive' - ); - const containerPolite = document.getElementById( 'a11y-speak-polite' ); - - if ( containerAssertive && ariaLive === 'assertive' ) { - containerAssertive.textContent = message; - } else if ( containerPolite ) { - containerPolite.textContent = message; - } - - /* - * Make the explanatory text available to assistive technologies by removing - * the 'hidden' HTML attribute. - */ - if ( introText ) { - introText.removeAttribute( 'hidden' ); - } -} diff --git a/packages/a11y/src/index.native.js b/packages/a11y/src/index.native.js index f6f53b6343adb0..e17597a8b2747d 100644 --- a/packages/a11y/src/index.native.js +++ b/packages/a11y/src/index.native.js @@ -1,7 +1,7 @@ /** * Internal dependencies */ -import filterMessage from './filter-message'; +import filterMessage from './shared/filter-message'; /** * Update the ARIA live notification area text node. diff --git a/packages/a11y/src/module/index.ts b/packages/a11y/src/module/index.ts new file mode 100644 index 00000000000000..a2c87f397f4875 --- /dev/null +++ b/packages/a11y/src/module/index.ts @@ -0,0 +1,25 @@ +/** + * Internal dependencies + */ +import { makeSetupFunction } from '../shared/index'; +export { speak } from '../shared/index'; + +// Without an i18n Script Module, "Notifications" (the only localized text used in this module) +// will be translated on the server and provided as script-module data. +let notificationsText = 'Notifications'; +try { + const textContent = document.getElementById( + 'wp-script-module-data-@wordpress/a11y' + )?.textContent; + if ( textContent ) { + const parsed = JSON.parse( textContent ); + notificationsText = parsed?.i18n?.Notifications ?? notificationsText; + } +} catch {} + +/** + * Create the live regions. + */ +export const setup = makeSetupFunction( notificationsText ); + +setup(); diff --git a/packages/a11y/src/add-container.js b/packages/a11y/src/shared/add-container.js similarity index 100% rename from packages/a11y/src/add-container.js rename to packages/a11y/src/shared/add-container.js diff --git a/packages/a11y/src/add-intro-text.js b/packages/a11y/src/shared/add-intro-text.ts similarity index 83% rename from packages/a11y/src/add-intro-text.js rename to packages/a11y/src/shared/add-intro-text.ts index 2bcf453ec44c8e..6bd97c887664d3 100644 --- a/packages/a11y/src/add-intro-text.js +++ b/packages/a11y/src/shared/add-intro-text.ts @@ -1,22 +1,18 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; - /** * Build the explanatory text to be placed before the aria live regions. * * This text is initially hidden from assistive technologies by using a `hidden` * HTML attribute which is then removed once a message fills the aria-live regions. * + * @param {string} introTextContent The translated intro text content. * @return {HTMLParagraphElement} The explanatory text HTML element. */ -export default function addIntroText() { +export default function addIntroText( introTextContent: string ) { const introText = document.createElement( 'p' ); introText.id = 'a11y-speak-intro-text'; introText.className = 'a11y-speak-intro-text'; - introText.textContent = __( 'Notifications' ); + introText.textContent = introTextContent; introText.setAttribute( 'style', diff --git a/packages/a11y/src/clear.js b/packages/a11y/src/shared/clear.js similarity index 100% rename from packages/a11y/src/clear.js rename to packages/a11y/src/shared/clear.js diff --git a/packages/a11y/src/filter-message.js b/packages/a11y/src/shared/filter-message.js similarity index 100% rename from packages/a11y/src/filter-message.js rename to packages/a11y/src/shared/filter-message.js diff --git a/packages/a11y/src/shared/index.js b/packages/a11y/src/shared/index.js new file mode 100644 index 00000000000000..a05f891f428561 --- /dev/null +++ b/packages/a11y/src/shared/index.js @@ -0,0 +1,81 @@ +/** + * Internal dependencies + */ +import addContainer from './add-container'; +import addIntroText from './add-intro-text'; +import clear from './clear'; +import filterMessage from './filter-message'; + +/** + * Create the live regions. + * @param {string} introTextContent The intro text content. + */ +export function makeSetupFunction( introTextContent ) { + return function setup() { + const introText = document.getElementById( 'a11y-speak-intro-text' ); + const containerAssertive = document.getElementById( + 'a11y-speak-assertive' + ); + const containerPolite = document.getElementById( 'a11y-speak-polite' ); + + if ( introText === null ) { + addIntroText( introTextContent ); + } + + if ( containerAssertive === null ) { + addContainer( 'assertive' ); + } + + if ( containerPolite === null ) { + addContainer( 'polite' ); + } + }; +} + +/** + * Allows you to easily announce dynamic interface updates to screen readers using ARIA live regions. + * This module is inspired by the `speak` function in `wp-a11y.js`. + * + * @param {string} message The message to be announced by assistive technologies. + * @param {'polite'|'assertive'} [ariaLive] The politeness level for aria-live; default: 'polite'. + * + * @example + * ```js + * import { speak } from '@wordpress/a11y'; + * + * // For polite messages that shouldn't interrupt what screen readers are currently announcing. + * speak( 'The message you want to send to the ARIA live region' ); + * + * // For assertive messages that should interrupt what screen readers are currently announcing. + * speak( 'The message you want to send to the ARIA live region', 'assertive' ); + * ``` + */ +export function speak( message, ariaLive ) { + /* + * Clear previous messages to allow repeated strings being read out and hide + * the explanatory text from assistive technologies. + */ + clear(); + + message = filterMessage( message ); + + const introText = document.getElementById( 'a11y-speak-intro-text' ); + const containerAssertive = document.getElementById( + 'a11y-speak-assertive' + ); + const containerPolite = document.getElementById( 'a11y-speak-polite' ); + + if ( containerAssertive && ariaLive === 'assertive' ) { + containerAssertive.textContent = message; + } else if ( containerPolite ) { + containerPolite.textContent = message; + } + + /* + * Make the explanatory text available to assistive technologies by removing + * the 'hidden' HTML attribute. + */ + if ( introText ) { + introText.removeAttribute( 'hidden' ); + } +} diff --git a/packages/a11y/src/test/add-container.test.js b/packages/a11y/src/shared/test/add-container.test.js similarity index 100% rename from packages/a11y/src/test/add-container.test.js rename to packages/a11y/src/shared/test/add-container.test.js diff --git a/packages/a11y/src/test/clear.test.js b/packages/a11y/src/shared/test/clear.test.js similarity index 100% rename from packages/a11y/src/test/clear.test.js rename to packages/a11y/src/shared/test/clear.test.js diff --git a/packages/a11y/src/test/filter-message.test.js b/packages/a11y/src/shared/test/filter-message.test.js similarity index 100% rename from packages/a11y/src/test/filter-message.test.js rename to packages/a11y/src/shared/test/filter-message.test.js diff --git a/packages/a11y/src/test/index.test.js b/packages/a11y/src/test/index.test.js index 4815baa2205047..0f6b9d0bd572ed 100644 --- a/packages/a11y/src/test/index.test.js +++ b/packages/a11y/src/test/index.test.js @@ -7,10 +7,10 @@ import domReady from '@wordpress/dom-ready'; * Internal dependencies */ import { setup, speak } from '../'; -import clear from '../clear'; -import filterMessage from '../filter-message'; +import clear from '../shared/clear'; +import filterMessage from '../shared/filter-message'; -jest.mock( '../clear', () => { +jest.mock( '../shared/clear', () => { return jest.fn(); } ); jest.mock( '@wordpress/dom-ready', () => { @@ -18,7 +18,7 @@ jest.mock( '@wordpress/dom-ready', () => { callback(); } ); } ); -jest.mock( '../filter-message', () => { +jest.mock( '../shared/filter-message', () => { return jest.fn( ( message ) => { return message; } ); diff --git a/packages/dependency-extraction-webpack-plugin/lib/util.js b/packages/dependency-extraction-webpack-plugin/lib/util.js index fcc6e5a0ed1731..cc999860244760 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/util.js +++ b/packages/dependency-extraction-webpack-plugin/lib/util.js @@ -90,9 +90,10 @@ function defaultRequestToExternalModule( request ) { return `module ${ request }`; } - if ( request === '@wordpress/interactivity-router' ) { - // Assumes this is usually going to be used as a dynamic import. - return `import ${ request }`; + switch ( request ) { + case '@wordpress/interactivity-router': + case '@wordpress/a11y': + return `import ${ request }`; } const isWordPressScript = Boolean( defaultRequestToExternal( request ) ); From 92661e7b46ac01f7d7226764e18abafe2cf5d5d8 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 12 Sep 2024 20:00:59 +0900 Subject: [PATCH 0778/1908] Build Tooling: Correctly generate PHP files for server-side rendering of blocks on Windows OS (#65248) * Build Tooling: Correctly generate PHP files for server-side rendering of blocks on Windows OS * Don't use prefix Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- tools/webpack/blocks.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/webpack/blocks.js b/tools/webpack/blocks.js index fa0c6123dbcdba..a7866b61a6a1f4 100644 --- a/tools/webpack/blocks.js +++ b/tools/webpack/blocks.js @@ -2,7 +2,7 @@ * External dependencies */ const CopyWebpackPlugin = require( 'copy-webpack-plugin' ); -const { join, sep } = require( 'path' ); +const { join, sep, basename } = require( 'path' ); const fastGlob = require( 'fast-glob' ); const { realpathSync } = require( 'fs' ); @@ -135,7 +135,7 @@ module.exports = [ { from: `${ from }/**/*.php`, to( { absoluteFilename } ) { - const [ , dirname, basename ] = + const [ , dirname, fileBasename ] = absoluteFilename.match( new RegExp( `([\\w-]+)${ escapeRegExp( @@ -143,15 +143,18 @@ module.exports = [ ) }([\\w-]+)\\.php$` ) ); - - if ( basename === 'index' ) { + if ( fileBasename === 'index' ) { return join( to, `${ dirname }.php` ); } - return join( to, dirname, `${ basename }.php` ); + return join( + to, + dirname, + `${ fileBasename }.php` + ); }, filter: ( filepath ) => { return ( - filepath.endsWith( sep + 'index.php' ) || + basename( filepath ) === 'index.php' || PhpFilePathsPlugin.paths.includes( realpathSync( filepath ).replace( /\\/g, From 297e9cafba7e574e3c45f9c9fab91d2476ac9c10 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 12 Sep 2024 20:08:23 +0900 Subject: [PATCH 0779/1908] Form Input: Don't use `flex-direction: row-reverse` for checkbox field (#64232) * Form Input: Don't use `flex-direction: row-reverse` for checkbox field * Don't create v2 variable * Fix fixtures * Update fixtures * Split fixtures * Integrate fixtures * Remove unneccesary fixtures * Add base fixtures for text-like inputs All variations of the simple texts input field are added here to match the approach taken in the deprecation fixtures. * Add base fixtures for checkbox, radio, and textarea inputs * Add fallback style for old markup --------- Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: aristath <aristath@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../src/form-input/deprecated.js | 115 +++++++++++++++++- packages/block-library/src/form-input/edit.js | 28 +++-- packages/block-library/src/form-input/save.js | 16 ++- .../block-library/src/form-input/style.scss | 17 +-- .../fixtures/blocks/core__form-input.html | 17 +++ .../fixtures/blocks/core__form-input.json | 52 ++++++++ .../blocks/core__form-input.parsed.json | 72 +++++++++++ .../blocks/core__form-input.serialized.html | 16 +++ .../blocks/core__form-input__checkbox.html | 3 + .../blocks/core__form-input__checkbox.json | 15 +++ .../core__form-input__checkbox.parsed.json | 14 +++ ...core__form-input__checkbox.serialized.html | 3 + ...__form-input__checkbox__deprecated-v1.html | 7 ++ ...__form-input__checkbox__deprecated-v1.json | 15 +++ ...input__checkbox__deprecated-v1.parsed.json | 13 ++ ...t__checkbox__deprecated-v1.serialized.html | 3 + ...__form-input__checkbox__deprecated-v2.html | 8 ++ ...__form-input__checkbox__deprecated-v2.json | 15 +++ ...input__checkbox__deprecated-v2.parsed.json | 13 ++ ...t__checkbox__deprecated-v2.serialized.html | 3 + .../core__form-input__deprecated-v1.html | 30 +++++ .../core__form-input__deprecated-v1.json | 52 ++++++++ ...ore__form-input__deprecated-v1.parsed.json | 72 +++++++++++ ..._form-input__deprecated-v1.serialized.html | 16 +++ .../blocks/core__form-input__radio.html | 3 + .../blocks/core__form-input__radio.json | 15 +++ .../core__form-input__radio.parsed.json | 14 +++ .../core__form-input__radio.serialized.html | 3 + ...ore__form-input__radio__deprecated-v1.html | 7 ++ ...ore__form-input__radio__deprecated-v1.json | 15 +++ ...rm-input__radio__deprecated-v1.parsed.json | 13 ++ ...nput__radio__deprecated-v1.serialized.html | 3 + ...ore__form-input__radio__deprecated-v2.html | 8 ++ ...ore__form-input__radio__deprecated-v2.json | 15 +++ ...rm-input__radio__deprecated-v2.parsed.json | 13 ++ ...nput__radio__deprecated-v2.serialized.html | 3 + .../blocks/core__form-input__textarea.html | 3 + .../blocks/core__form-input__textarea.json | 15 +++ .../core__form-input__textarea.parsed.json | 13 ++ ...core__form-input__textarea.serialized.html | 3 + ...__form-input__textarea__deprecated-v1.html | 6 + ...__form-input__textarea__deprecated-v1.json | 15 +++ ...input__textarea__deprecated-v1.parsed.json | 13 ++ ...t__textarea__deprecated-v1.serialized.html | 3 + 44 files changed, 775 insertions(+), 23 deletions(-) create mode 100644 test/integration/fixtures/blocks/core__form-input__checkbox.html create mode 100644 test/integration/fixtures/blocks/core__form-input__checkbox.json create mode 100644 test/integration/fixtures/blocks/core__form-input__checkbox.parsed.json create mode 100644 test/integration/fixtures/blocks/core__form-input__checkbox.serialized.html create mode 100644 test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.html create mode 100644 test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.json create mode 100644 test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.parsed.json create mode 100644 test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.serialized.html create mode 100644 test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.html create mode 100644 test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.json create mode 100644 test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.parsed.json create mode 100644 test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.serialized.html create mode 100644 test/integration/fixtures/blocks/core__form-input__radio.html create mode 100644 test/integration/fixtures/blocks/core__form-input__radio.json create mode 100644 test/integration/fixtures/blocks/core__form-input__radio.parsed.json create mode 100644 test/integration/fixtures/blocks/core__form-input__radio.serialized.html create mode 100644 test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.html create mode 100644 test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.json create mode 100644 test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.parsed.json create mode 100644 test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.serialized.html create mode 100644 test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.html create mode 100644 test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.json create mode 100644 test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.parsed.json create mode 100644 test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.serialized.html create mode 100644 test/integration/fixtures/blocks/core__form-input__textarea.html create mode 100644 test/integration/fixtures/blocks/core__form-input__textarea.json create mode 100644 test/integration/fixtures/blocks/core__form-input__textarea.parsed.json create mode 100644 test/integration/fixtures/blocks/core__form-input__textarea.serialized.html create mode 100644 test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.html create mode 100644 test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.json create mode 100644 test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.parsed.json create mode 100644 test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.serialized.html diff --git a/packages/block-library/src/form-input/deprecated.js b/packages/block-library/src/form-input/deprecated.js index 9cd49d5b0011be..451cc704a42d55 100644 --- a/packages/block-library/src/form-input/deprecated.js +++ b/packages/block-library/src/form-input/deprecated.js @@ -9,6 +9,7 @@ import removeAccents from 'remove-accents'; */ import { RichText, + useBlockProps, __experimentalGetBorderClassesAndStyles as getBorderClassesAndStyles, __experimentalGetColorClassesAndStyles as getColorClassesAndStyles, } from '@wordpress/block-editor'; @@ -26,6 +27,118 @@ const getNameFromLabelV1 = ( content ) => { ); }; +const v2 = { + attributes: { + type: { + type: 'string', + default: 'text', + }, + name: { + type: 'string', + }, + label: { + type: 'string', + default: 'Label', + selector: '.wp-block-form-input__label-content', + source: 'html', + __experimentalRole: 'content', + }, + inlineLabel: { + type: 'boolean', + default: false, + }, + required: { + type: 'boolean', + default: false, + selector: '.wp-block-form-input__input', + source: 'attribute', + attribute: 'required', + }, + placeholder: { + type: 'string', + selector: '.wp-block-form-input__input', + source: 'attribute', + attribute: 'placeholder', + __experimentalRole: 'content', + }, + value: { + type: 'string', + default: '', + selector: 'input', + source: 'attribute', + attribute: 'value', + }, + visibilityPermissions: { + type: 'string', + default: 'all', + }, + }, + supports: { + anchor: true, + reusable: false, + spacing: { + margin: [ 'top', 'bottom' ], + }, + __experimentalBorder: { + radius: true, + __experimentalSkipSerialization: true, + __experimentalDefaultControls: { + radius: true, + }, + }, + }, + save( { attributes } ) { + const { type, name, label, inlineLabel, required, placeholder, value } = + attributes; + + const borderProps = getBorderClassesAndStyles( attributes ); + const colorProps = getColorClassesAndStyles( attributes ); + + const inputStyle = { + ...borderProps.style, + ...colorProps.style, + }; + + const inputClasses = clsx( + 'wp-block-form-input__input', + colorProps.className, + borderProps.className + ); + const TagName = type === 'textarea' ? 'textarea' : 'input'; + + const blockProps = useBlockProps.save(); + + if ( 'hidden' === type ) { + return <input type={ type } name={ name } value={ value } />; + } + + return ( + <div { ...blockProps }> + { /* eslint-disable jsx-a11y/label-has-associated-control */ } + <label + className={ clsx( 'wp-block-form-input__label', { + 'is-label-inline': inlineLabel, + } ) } + > + <span className="wp-block-form-input__label-content"> + <RichText.Content value={ label } /> + </span> + <TagName + className={ inputClasses } + type={ 'textarea' === type ? undefined : type } + name={ name || getNameFromLabelV1( label ) } + required={ required } + aria-required={ required } + placeholder={ placeholder || undefined } + style={ inputStyle } + /> + </label> + { /* eslint-enable jsx-a11y/label-has-associated-control */ } + </div> + ); + }, +}; + // Version without wrapper div in saved markup // See: https://github.com/WordPress/gutenberg/pull/56507 const v1 = { @@ -137,6 +250,6 @@ const v1 = { }, }; -const deprecated = [ v1 ]; +const deprecated = [ v2, v1 ]; export default deprecated; diff --git a/packages/block-library/src/form-input/edit.js b/packages/block-library/src/form-input/edit.js index 6939443011ee5b..5f3713e83975f1 100644 --- a/packages/block-library/src/form-input/edit.js +++ b/packages/block-library/src/form-input/edit.js @@ -31,6 +31,9 @@ function InputFieldBlock( { attributes, setAttributes, className } ) { ref.current.focus(); } + // Note: radio inputs aren't implemented yet. + const isCheckboxOrRadio = type === 'checkbox' || type === 'radio'; + const controls = ( <> { 'hidden' !== type && ( @@ -81,6 +84,18 @@ function InputFieldBlock( { attributes, setAttributes, className } ) { </> ); + const content = ( + <RichText + tagName="span" + className="wp-block-form-input__label-content" + value={ label } + onChange={ ( newLabel ) => setAttributes( { label: newLabel } ) } + aria-label={ label ? __( 'Label' ) : __( 'Empty label' ) } + data-empty={ ! label } + placeholder={ __( 'Type the label for this input' ) } + /> + ); + if ( 'hidden' === type ) { return ( <> @@ -111,17 +126,7 @@ function InputFieldBlock( { attributes, setAttributes, className } ) { 'is-label-inline': inlineLabel || 'checkbox' === type, } ) } > - <RichText - tagName="span" - className="wp-block-form-input__label-content" - value={ label } - onChange={ ( newLabel ) => - setAttributes( { label: newLabel } ) - } - aria-label={ label ? __( 'Label' ) : __( 'Empty label' ) } - data-empty={ label ? false : true } - placeholder={ __( 'Type the label for this input' ) } - /> + { ! isCheckboxOrRadio && content } <TagName type={ 'textarea' === type ? undefined : type } className={ clsx( @@ -147,6 +152,7 @@ function InputFieldBlock( { attributes, setAttributes, className } ) { ...colorProps.style, } } /> + { isCheckboxOrRadio && content } </span> </div> ); diff --git a/packages/block-library/src/form-input/save.js b/packages/block-library/src/form-input/save.js index c408e06923ca9f..941c23dc2014d1 100644 --- a/packages/block-library/src/form-input/save.js +++ b/packages/block-library/src/form-input/save.js @@ -55,6 +55,9 @@ export default function save( { attributes } ) { const blockProps = useBlockProps.save(); + // Note: radio inputs aren't implemented yet. + const isCheckboxOrRadio = type === 'checkbox' || type === 'radio'; + if ( 'hidden' === type ) { return <input type={ type } name={ name } value={ value } />; } @@ -67,9 +70,11 @@ export default function save( { attributes } ) { 'is-label-inline': inlineLabel, } ) } > - <span className="wp-block-form-input__label-content"> - <RichText.Content value={ label } /> - </span> + { ! isCheckboxOrRadio && ( + <span className="wp-block-form-input__label-content"> + <RichText.Content value={ label } /> + </span> + ) } <TagName className={ inputClasses } type={ 'textarea' === type ? undefined : type } @@ -79,6 +84,11 @@ export default function save( { attributes } ) { placeholder={ placeholder || undefined } style={ inputStyle } /> + { isCheckboxOrRadio && ( + <span className="wp-block-form-input__label-content"> + <RichText.Content value={ label } /> + </span> + ) } </label> { /* eslint-enable jsx-a11y/label-has-associated-control */ } </div> diff --git a/packages/block-library/src/form-input/style.scss b/packages/block-library/src/form-input/style.scss index f9e1753cf0a7b7..7b1ac53cc89c01 100644 --- a/packages/block-library/src/form-input/style.scss +++ b/packages/block-library/src/form-input/style.scss @@ -15,16 +15,17 @@ } } - /* - Small tweak to left-align the checkbox. - Even though `:has` is not currently supported in Firefox, this is a small tweak - and does not affect the functionality of the block or the user's experience. - There will be a minor inconsistency between browsers. However, it's more important to provide - a better experience for 80+% of users, until Firefox catches up and supports `:has`. - */ &:has(input[type="checkbox"]) { + flex-direction: row; width: fit-content; - /* stylelint-disable-next-line declaration-property-value-allowed-list -- This should be refactored to not use the row-reverse value. */ + + .wp-block-form-input__label-content { + margin: 0; + } + } + + &:has(.wp-block-form-input__label-content + input[type="checkbox"]) { + /* stylelint-disable-next-line declaration-property-value-allowed-list -- This style is required for old markup. */ flex-direction: row-reverse; } } diff --git a/test/integration/fixtures/blocks/core__form-input.html b/test/integration/fixtures/blocks/core__form-input.html index 33f1fe88c2c6a1..81ff6cf53534e8 100644 --- a/test/integration/fixtures/blocks/core__form-input.html +++ b/test/integration/fixtures/blocks/core__form-input.html @@ -1,3 +1,20 @@ <!-- wp:form-input --> <div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="text" name="label" aria-required="false"/></label></div> <!-- /wp:form-input --> + +<!-- wp:form-input {"type":"email"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="email" name="label" aria-required="false"/></label></div> +<!-- /wp:form-input --> + +<!-- wp:form-input {"type":"number"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="number" name="label" aria-required="false"/></label></div> +<!-- /wp:form-input --> + +<!-- wp:form-input {"type":"tel"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="tel" name="label" aria-required="false"/></label></div> +<!-- /wp:form-input --> + +<!-- wp:form-input {"type":"url"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="url" name="label" aria-required="false"/></label></div> +<!-- /wp:form-input --> + diff --git a/test/integration/fixtures/blocks/core__form-input.json b/test/integration/fixtures/blocks/core__form-input.json index fee4df284f1156..2d9865ef735562 100644 --- a/test/integration/fixtures/blocks/core__form-input.json +++ b/test/integration/fixtures/blocks/core__form-input.json @@ -11,5 +11,57 @@ "visibilityPermissions": "all" }, "innerBlocks": [] + }, + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "email", + "label": "Label", + "inlineLabel": false, + "required": false, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] + }, + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "number", + "label": "Label", + "inlineLabel": false, + "required": false, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] + }, + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "tel", + "label": "Label", + "inlineLabel": false, + "required": false, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] + }, + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "url", + "label": "Label", + "inlineLabel": false, + "required": false, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] } ] diff --git a/test/integration/fixtures/blocks/core__form-input.parsed.json b/test/integration/fixtures/blocks/core__form-input.parsed.json index 5470c653c403b5..439943df2841c8 100644 --- a/test/integration/fixtures/blocks/core__form-input.parsed.json +++ b/test/integration/fixtures/blocks/core__form-input.parsed.json @@ -7,5 +7,77 @@ "innerContent": [ "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label\"><span class=\"wp-block-form-input__label-content\">Label</span><input class=\"wp-block-form-input__input\" type=\"text\" name=\"label\" aria-required=\"false\"/></label></div>\n" ] + }, + { + "blockName": null, + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n\n", + "innerContent": [ "\n\n" ] + }, + { + "blockName": "core/form-input", + "attrs": { + "type": "email" + }, + "innerBlocks": [], + "innerHTML": "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label\"><span class=\"wp-block-form-input__label-content\">Label</span><input class=\"wp-block-form-input__input\" type=\"email\" name=\"label\" aria-required=\"false\"/></label></div>\n", + "innerContent": [ + "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label\"><span class=\"wp-block-form-input__label-content\">Label</span><input class=\"wp-block-form-input__input\" type=\"email\" name=\"label\" aria-required=\"false\"/></label></div>\n" + ] + }, + { + "blockName": null, + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n\n", + "innerContent": [ "\n\n" ] + }, + { + "blockName": "core/form-input", + "attrs": { + "type": "number" + }, + "innerBlocks": [], + "innerHTML": "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label\"><span class=\"wp-block-form-input__label-content\">Label</span><input class=\"wp-block-form-input__input\" type=\"number\" name=\"label\" aria-required=\"false\"/></label></div>\n", + "innerContent": [ + "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label\"><span class=\"wp-block-form-input__label-content\">Label</span><input class=\"wp-block-form-input__input\" type=\"number\" name=\"label\" aria-required=\"false\"/></label></div>\n" + ] + }, + { + "blockName": null, + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n\n", + "innerContent": [ "\n\n" ] + }, + { + "blockName": "core/form-input", + "attrs": { + "type": "tel" + }, + "innerBlocks": [], + "innerHTML": "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label\"><span class=\"wp-block-form-input__label-content\">Label</span><input class=\"wp-block-form-input__input\" type=\"tel\" name=\"label\" aria-required=\"false\"/></label></div>\n", + "innerContent": [ + "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label\"><span class=\"wp-block-form-input__label-content\">Label</span><input class=\"wp-block-form-input__input\" type=\"tel\" name=\"label\" aria-required=\"false\"/></label></div>\n" + ] + }, + { + "blockName": null, + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n\n", + "innerContent": [ "\n\n" ] + }, + { + "blockName": "core/form-input", + "attrs": { + "type": "url" + }, + "innerBlocks": [], + "innerHTML": "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label\"><span class=\"wp-block-form-input__label-content\">Label</span><input class=\"wp-block-form-input__input\" type=\"url\" name=\"label\" aria-required=\"false\"/></label></div>\n", + "innerContent": [ + "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label\"><span class=\"wp-block-form-input__label-content\">Label</span><input class=\"wp-block-form-input__input\" type=\"url\" name=\"label\" aria-required=\"false\"/></label></div>\n" + ] } ] diff --git a/test/integration/fixtures/blocks/core__form-input.serialized.html b/test/integration/fixtures/blocks/core__form-input.serialized.html index 33f1fe88c2c6a1..d66cedcf9215b8 100644 --- a/test/integration/fixtures/blocks/core__form-input.serialized.html +++ b/test/integration/fixtures/blocks/core__form-input.serialized.html @@ -1,3 +1,19 @@ <!-- wp:form-input --> <div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="text" name="label" aria-required="false"/></label></div> <!-- /wp:form-input --> + +<!-- wp:form-input {"type":"email"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="email" name="label" aria-required="false"/></label></div> +<!-- /wp:form-input --> + +<!-- wp:form-input {"type":"number"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="number" name="label" aria-required="false"/></label></div> +<!-- /wp:form-input --> + +<!-- wp:form-input {"type":"tel"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="tel" name="label" aria-required="false"/></label></div> +<!-- /wp:form-input --> + +<!-- wp:form-input {"type":"url"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="url" name="label" aria-required="false"/></label></div> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__checkbox.html b/test/integration/fixtures/blocks/core__form-input__checkbox.html new file mode 100644 index 00000000000000..fd08525a17eb33 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__checkbox.html @@ -0,0 +1,3 @@ +<!-- wp:form-input {"type":"checkbox","inlineLabel":true} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label is-label-inline"><input class="wp-block-form-input__input" type="checkbox" name="label" required aria-required="true"/><span class="wp-block-form-input__label-content">Label</span></label></div> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__checkbox.json b/test/integration/fixtures/blocks/core__form-input__checkbox.json new file mode 100644 index 00000000000000..cc86ecd2a9080b --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__checkbox.json @@ -0,0 +1,15 @@ +[ + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "checkbox", + "label": "Label", + "inlineLabel": true, + "required": true, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__checkbox.parsed.json b/test/integration/fixtures/blocks/core__form-input__checkbox.parsed.json new file mode 100644 index 00000000000000..60b7b7dd37b091 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__checkbox.parsed.json @@ -0,0 +1,14 @@ +[ + { + "blockName": "core/form-input", + "attrs": { + "type": "checkbox", + "inlineLabel": true + }, + "innerBlocks": [], + "innerHTML": "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label is-label-inline\"><input class=\"wp-block-form-input__input\" type=\"checkbox\" name=\"label\" required aria-required=\"true\"/><span class=\"wp-block-form-input__label-content\">Label</span></label></div>\n", + "innerContent": [ + "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label is-label-inline\"><input class=\"wp-block-form-input__input\" type=\"checkbox\" name=\"label\" required aria-required=\"true\"/><span class=\"wp-block-form-input__label-content\">Label</span></label></div>\n" + ] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__checkbox.serialized.html b/test/integration/fixtures/blocks/core__form-input__checkbox.serialized.html new file mode 100644 index 00000000000000..fd08525a17eb33 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__checkbox.serialized.html @@ -0,0 +1,3 @@ +<!-- wp:form-input {"type":"checkbox","inlineLabel":true} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label is-label-inline"><input class="wp-block-form-input__input" type="checkbox" name="label" required aria-required="true"/><span class="wp-block-form-input__label-content">Label</span></label></div> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.html b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.html new file mode 100644 index 00000000000000..bd64e201e19185 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.html @@ -0,0 +1,7 @@ +<!-- wp:form-input {"type":"checkbox"} --> +<label class="wp-block-form-input__label"> + <span class="wp-block-form-input__label-content">Label</span> + <input class="wp-block-form-input__input" type="checkbox" name="label" aria-required="false"/> +</label> +<!-- /wp:form-input --> + diff --git a/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.json b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.json new file mode 100644 index 00000000000000..162304dc84b0c2 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.json @@ -0,0 +1,15 @@ +[ + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "checkbox", + "label": "Label", + "inlineLabel": false, + "required": false, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.parsed.json b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.parsed.json new file mode 100644 index 00000000000000..2a2490e5c12607 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core/form-input", + "attrs": { + "type": "checkbox" + }, + "innerBlocks": [], + "innerHTML": "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<input class=\"wp-block-form-input__input\" type=\"checkbox\" name=\"label\" aria-required=\"false\"/>\n</label>\n", + "innerContent": [ + "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<input class=\"wp-block-form-input__input\" type=\"checkbox\" name=\"label\" aria-required=\"false\"/>\n</label>\n" + ] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.serialized.html b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.serialized.html new file mode 100644 index 00000000000000..66705934019701 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v1.serialized.html @@ -0,0 +1,3 @@ +<!-- wp:form-input {"type":"checkbox"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><input class="wp-block-form-input__input" type="checkbox" name="label" aria-required="false"/><span class="wp-block-form-input__label-content">Label</span></label></div> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.html b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.html new file mode 100644 index 00000000000000..3f1de1c6028470 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.html @@ -0,0 +1,8 @@ +<!-- wp:form-input {"type":"checkbox"} --> +<div class="wp-block-form-input"> + <label class="wp-block-form-input__label"> + <span class="wp-block-form-input__label-content">Label</span> + <input class="wp-block-form-input__input" type="checkbox" name="label" aria-required="false"/> + </label> +</div> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.json b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.json new file mode 100644 index 00000000000000..162304dc84b0c2 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.json @@ -0,0 +1,15 @@ +[ + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "checkbox", + "label": "Label", + "inlineLabel": false, + "required": false, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.parsed.json b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.parsed.json new file mode 100644 index 00000000000000..dfa57c0755f685 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core/form-input", + "attrs": { + "type": "checkbox" + }, + "innerBlocks": [], + "innerHTML": "\n<div class=\"wp-block-form-input\">\n\t<label class=\"wp-block-form-input__label\">\n\t\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t\t<input class=\"wp-block-form-input__input\" type=\"checkbox\" name=\"label\" aria-required=\"false\"/>\n\t</label>\n</div>\n", + "innerContent": [ + "\n<div class=\"wp-block-form-input\">\n\t<label class=\"wp-block-form-input__label\">\n\t\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t\t<input class=\"wp-block-form-input__input\" type=\"checkbox\" name=\"label\" aria-required=\"false\"/>\n\t</label>\n</div>\n" + ] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.serialized.html b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.serialized.html new file mode 100644 index 00000000000000..66705934019701 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__checkbox__deprecated-v2.serialized.html @@ -0,0 +1,3 @@ +<!-- wp:form-input {"type":"checkbox"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><input class="wp-block-form-input__input" type="checkbox" name="label" aria-required="false"/><span class="wp-block-form-input__label-content">Label</span></label></div> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__deprecated-v1.html b/test/integration/fixtures/blocks/core__form-input__deprecated-v1.html index 08ea6618386200..5f043b0b2ef644 100644 --- a/test/integration/fixtures/blocks/core__form-input__deprecated-v1.html +++ b/test/integration/fixtures/blocks/core__form-input__deprecated-v1.html @@ -4,3 +4,33 @@ <input class="wp-block-form-input__input" type="text" name="label" aria-required="false"/> </label> <!-- /wp:form-input --> + + +<!-- wp:form-input {"type":"email"} --> +<label class="wp-block-form-input__label"> + <span class="wp-block-form-input__label-content">Label</span> + <input class="wp-block-form-input__input" type="email" name="label" aria-required="false"/> +</label> +<!-- /wp:form-input --> + +<!-- wp:form-input {"type":"number"} --> +<label class="wp-block-form-input__label"> + <span class="wp-block-form-input__label-content">Label</span> + <input class="wp-block-form-input__input" type="number" name="label" aria-required="false"/> +</label> +<!-- /wp:form-input --> + +<!-- wp:form-input {"type":"tel"} --> +<label class="wp-block-form-input__label"> + <span class="wp-block-form-input__label-content">Label</span> + <input class="wp-block-form-input__input" type="tel" name="label" aria-required="false"/> +</label> +<!-- /wp:form-input --> + +<!-- wp:form-input {"type":"url"} --> +<label class="wp-block-form-input__label"> + <span class="wp-block-form-input__label-content">Label</span> + <input class="wp-block-form-input__input" type="url" name="label" aria-required="false"/> +</label> +<!-- /wp:form-input --> + diff --git a/test/integration/fixtures/blocks/core__form-input__deprecated-v1.json b/test/integration/fixtures/blocks/core__form-input__deprecated-v1.json index fee4df284f1156..2d9865ef735562 100644 --- a/test/integration/fixtures/blocks/core__form-input__deprecated-v1.json +++ b/test/integration/fixtures/blocks/core__form-input__deprecated-v1.json @@ -11,5 +11,57 @@ "visibilityPermissions": "all" }, "innerBlocks": [] + }, + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "email", + "label": "Label", + "inlineLabel": false, + "required": false, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] + }, + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "number", + "label": "Label", + "inlineLabel": false, + "required": false, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] + }, + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "tel", + "label": "Label", + "inlineLabel": false, + "required": false, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] + }, + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "url", + "label": "Label", + "inlineLabel": false, + "required": false, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] } ] diff --git a/test/integration/fixtures/blocks/core__form-input__deprecated-v1.parsed.json b/test/integration/fixtures/blocks/core__form-input__deprecated-v1.parsed.json index 645337cbfdb4a1..963614974675d5 100644 --- a/test/integration/fixtures/blocks/core__form-input__deprecated-v1.parsed.json +++ b/test/integration/fixtures/blocks/core__form-input__deprecated-v1.parsed.json @@ -7,5 +7,77 @@ "innerContent": [ "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<input class=\"wp-block-form-input__input\" type=\"text\" name=\"label\" aria-required=\"false\"/>\n</label>\n" ] + }, + { + "blockName": null, + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n\n\n", + "innerContent": [ "\n\n\n" ] + }, + { + "blockName": "core/form-input", + "attrs": { + "type": "email" + }, + "innerBlocks": [], + "innerHTML": "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<input class=\"wp-block-form-input__input\" type=\"email\" name=\"label\" aria-required=\"false\"/>\n</label>\n", + "innerContent": [ + "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<input class=\"wp-block-form-input__input\" type=\"email\" name=\"label\" aria-required=\"false\"/>\n</label>\n" + ] + }, + { + "blockName": null, + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n\n", + "innerContent": [ "\n\n" ] + }, + { + "blockName": "core/form-input", + "attrs": { + "type": "number" + }, + "innerBlocks": [], + "innerHTML": "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<input class=\"wp-block-form-input__input\" type=\"number\" name=\"label\" aria-required=\"false\"/>\n</label>\n", + "innerContent": [ + "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<input class=\"wp-block-form-input__input\" type=\"number\" name=\"label\" aria-required=\"false\"/>\n</label>\n" + ] + }, + { + "blockName": null, + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n\n", + "innerContent": [ "\n\n" ] + }, + { + "blockName": "core/form-input", + "attrs": { + "type": "tel" + }, + "innerBlocks": [], + "innerHTML": "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<input class=\"wp-block-form-input__input\" type=\"tel\" name=\"label\" aria-required=\"false\"/>\n</label>\n", + "innerContent": [ + "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<input class=\"wp-block-form-input__input\" type=\"tel\" name=\"label\" aria-required=\"false\"/>\n</label>\n" + ] + }, + { + "blockName": null, + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n\n", + "innerContent": [ "\n\n" ] + }, + { + "blockName": "core/form-input", + "attrs": { + "type": "url" + }, + "innerBlocks": [], + "innerHTML": "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<input class=\"wp-block-form-input__input\" type=\"url\" name=\"label\" aria-required=\"false\"/>\n</label>\n", + "innerContent": [ + "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<input class=\"wp-block-form-input__input\" type=\"url\" name=\"label\" aria-required=\"false\"/>\n</label>\n" + ] } ] diff --git a/test/integration/fixtures/blocks/core__form-input__deprecated-v1.serialized.html b/test/integration/fixtures/blocks/core__form-input__deprecated-v1.serialized.html index 33f1fe88c2c6a1..d66cedcf9215b8 100644 --- a/test/integration/fixtures/blocks/core__form-input__deprecated-v1.serialized.html +++ b/test/integration/fixtures/blocks/core__form-input__deprecated-v1.serialized.html @@ -1,3 +1,19 @@ <!-- wp:form-input --> <div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="text" name="label" aria-required="false"/></label></div> <!-- /wp:form-input --> + +<!-- wp:form-input {"type":"email"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="email" name="label" aria-required="false"/></label></div> +<!-- /wp:form-input --> + +<!-- wp:form-input {"type":"number"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="number" name="label" aria-required="false"/></label></div> +<!-- /wp:form-input --> + +<!-- wp:form-input {"type":"tel"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="tel" name="label" aria-required="false"/></label></div> +<!-- /wp:form-input --> + +<!-- wp:form-input {"type":"url"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><input class="wp-block-form-input__input" type="url" name="label" aria-required="false"/></label></div> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__radio.html b/test/integration/fixtures/blocks/core__form-input__radio.html new file mode 100644 index 00000000000000..1e6c76424334fb --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__radio.html @@ -0,0 +1,3 @@ +<!-- wp:form-input {"type":"radio","inlineLabel":true} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label is-label-inline"><input class="wp-block-form-input__input" type="radio" name="label" required aria-required="true"/><span class="wp-block-form-input__label-content">Label</span></label></div> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__radio.json b/test/integration/fixtures/blocks/core__form-input__radio.json new file mode 100644 index 00000000000000..18cec11e3305b1 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__radio.json @@ -0,0 +1,15 @@ +[ + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "radio", + "label": "Label", + "inlineLabel": true, + "required": true, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__radio.parsed.json b/test/integration/fixtures/blocks/core__form-input__radio.parsed.json new file mode 100644 index 00000000000000..8dbb5b5a09942a --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__radio.parsed.json @@ -0,0 +1,14 @@ +[ + { + "blockName": "core/form-input", + "attrs": { + "type": "radio", + "inlineLabel": true + }, + "innerBlocks": [], + "innerHTML": "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label is-label-inline\"><input class=\"wp-block-form-input__input\" type=\"radio\" name=\"label\" required aria-required=\"true\"/><span class=\"wp-block-form-input__label-content\">Label</span></label></div>\n", + "innerContent": [ + "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label is-label-inline\"><input class=\"wp-block-form-input__input\" type=\"radio\" name=\"label\" required aria-required=\"true\"/><span class=\"wp-block-form-input__label-content\">Label</span></label></div>\n" + ] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__radio.serialized.html b/test/integration/fixtures/blocks/core__form-input__radio.serialized.html new file mode 100644 index 00000000000000..1e6c76424334fb --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__radio.serialized.html @@ -0,0 +1,3 @@ +<!-- wp:form-input {"type":"radio","inlineLabel":true} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label is-label-inline"><input class="wp-block-form-input__input" type="radio" name="label" required aria-required="true"/><span class="wp-block-form-input__label-content">Label</span></label></div> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.html b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.html new file mode 100644 index 00000000000000..8c41e02f10f04a --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.html @@ -0,0 +1,7 @@ +<!-- wp:form-input {"type":"radio"} --> +<label class="wp-block-form-input__label"> + <span class="wp-block-form-input__label-content">Label</span> + <input class="wp-block-form-input__input" type="radio" name="label" aria-required="false"/> +</label> +<!-- /wp:form-input --> + diff --git a/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.json b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.json new file mode 100644 index 00000000000000..113ce01f7ab7ef --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.json @@ -0,0 +1,15 @@ +[ + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "radio", + "label": "Label", + "inlineLabel": false, + "required": false, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.parsed.json b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.parsed.json new file mode 100644 index 00000000000000..7433a6c7e9c508 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core/form-input", + "attrs": { + "type": "radio" + }, + "innerBlocks": [], + "innerHTML": "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<input class=\"wp-block-form-input__input\" type=\"radio\" name=\"label\" aria-required=\"false\"/>\n</label>\n", + "innerContent": [ + "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<input class=\"wp-block-form-input__input\" type=\"radio\" name=\"label\" aria-required=\"false\"/>\n</label>\n" + ] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.serialized.html b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.serialized.html new file mode 100644 index 00000000000000..be1ae98e023107 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v1.serialized.html @@ -0,0 +1,3 @@ +<!-- wp:form-input {"type":"radio"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><input class="wp-block-form-input__input" type="radio" name="label" aria-required="false"/><span class="wp-block-form-input__label-content">Label</span></label></div> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.html b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.html new file mode 100644 index 00000000000000..a1c1b58f9b7fc5 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.html @@ -0,0 +1,8 @@ +<!-- wp:form-input {"type":"radio"} --> +<div class="wp-block-form-input"> + <label class="wp-block-form-input__label"> + <span class="wp-block-form-input__label-content">Label</span> + <input class="wp-block-form-input__input" type="radio" name="label" aria-required="false"/> + </label> +</div> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.json b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.json new file mode 100644 index 00000000000000..113ce01f7ab7ef --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.json @@ -0,0 +1,15 @@ +[ + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "radio", + "label": "Label", + "inlineLabel": false, + "required": false, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.parsed.json b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.parsed.json new file mode 100644 index 00000000000000..14c7828b1c890d --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core/form-input", + "attrs": { + "type": "radio" + }, + "innerBlocks": [], + "innerHTML": "\n<div class=\"wp-block-form-input\">\n\t<label class=\"wp-block-form-input__label\">\n\t\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t\t<input class=\"wp-block-form-input__input\" type=\"radio\" name=\"label\" aria-required=\"false\"/>\n\t</label>\n</div>\n", + "innerContent": [ + "\n<div class=\"wp-block-form-input\">\n\t<label class=\"wp-block-form-input__label\">\n\t\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t\t<input class=\"wp-block-form-input__input\" type=\"radio\" name=\"label\" aria-required=\"false\"/>\n\t</label>\n</div>\n" + ] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.serialized.html b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.serialized.html new file mode 100644 index 00000000000000..be1ae98e023107 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__radio__deprecated-v2.serialized.html @@ -0,0 +1,3 @@ +<!-- wp:form-input {"type":"radio"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><input class="wp-block-form-input__input" type="radio" name="label" aria-required="false"/><span class="wp-block-form-input__label-content">Label</span></label></div> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__textarea.html b/test/integration/fixtures/blocks/core__form-input__textarea.html new file mode 100644 index 00000000000000..b39e1c8b51166f --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__textarea.html @@ -0,0 +1,3 @@ +<!-- wp:form-input {"type":"textarea"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><textarea class="wp-block-form-input__input" name="label" required aria-required="true"></textarea></label></div> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__textarea.json b/test/integration/fixtures/blocks/core__form-input__textarea.json new file mode 100644 index 00000000000000..62ae6f76a0e9d2 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__textarea.json @@ -0,0 +1,15 @@ +[ + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "textarea", + "label": "Label", + "inlineLabel": false, + "required": true, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__textarea.parsed.json b/test/integration/fixtures/blocks/core__form-input__textarea.parsed.json new file mode 100644 index 00000000000000..3f76a2194f27e4 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__textarea.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core/form-input", + "attrs": { + "type": "textarea" + }, + "innerBlocks": [], + "innerHTML": "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label\"><span class=\"wp-block-form-input__label-content\">Label</span><textarea class=\"wp-block-form-input__input\" name=\"label\" required aria-required=\"true\"></textarea></label></div>\n", + "innerContent": [ + "\n<div class=\"wp-block-form-input\"><label class=\"wp-block-form-input__label\"><span class=\"wp-block-form-input__label-content\">Label</span><textarea class=\"wp-block-form-input__input\" name=\"label\" required aria-required=\"true\"></textarea></label></div>\n" + ] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__textarea.serialized.html b/test/integration/fixtures/blocks/core__form-input__textarea.serialized.html new file mode 100644 index 00000000000000..b39e1c8b51166f --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__textarea.serialized.html @@ -0,0 +1,3 @@ +<!-- wp:form-input {"type":"textarea"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><textarea class="wp-block-form-input__input" name="label" required aria-required="true"></textarea></label></div> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.html b/test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.html new file mode 100644 index 00000000000000..8f7722f81ccc57 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.html @@ -0,0 +1,6 @@ +<!-- wp:form-input {"type":"textarea"} --> +<label class="wp-block-form-input__label"> + <span class="wp-block-form-input__label-content">Label</span> + <textarea class="wp-block-form-input__input" name="label" aria-required="false"></textarea> +</label> +<!-- /wp:form-input --> diff --git a/test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.json b/test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.json new file mode 100644 index 00000000000000..398106d8de1caf --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.json @@ -0,0 +1,15 @@ +[ + { + "name": "core/form-input", + "isValid": true, + "attributes": { + "type": "textarea", + "label": "Label", + "inlineLabel": false, + "required": false, + "value": "", + "visibilityPermissions": "all" + }, + "innerBlocks": [] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.parsed.json b/test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.parsed.json new file mode 100644 index 00000000000000..e5e11f26d99606 --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.parsed.json @@ -0,0 +1,13 @@ +[ + { + "blockName": "core/form-input", + "attrs": { + "type": "textarea" + }, + "innerBlocks": [], + "innerHTML": "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<textarea class=\"wp-block-form-input__input\" name=\"label\" aria-required=\"false\"></textarea>\n</label>\n", + "innerContent": [ + "\n<label class=\"wp-block-form-input__label\">\n\t<span class=\"wp-block-form-input__label-content\">Label</span>\n\t<textarea class=\"wp-block-form-input__input\" name=\"label\" aria-required=\"false\"></textarea>\n</label>\n" + ] + } +] diff --git a/test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.serialized.html b/test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.serialized.html new file mode 100644 index 00000000000000..530403c4964fae --- /dev/null +++ b/test/integration/fixtures/blocks/core__form-input__textarea__deprecated-v1.serialized.html @@ -0,0 +1,3 @@ +<!-- wp:form-input {"type":"textarea"} --> +<div class="wp-block-form-input"><label class="wp-block-form-input__label"><span class="wp-block-form-input__label-content">Label</span><textarea class="wp-block-form-input__input" name="label" aria-required="false"></textarea></label></div> +<!-- /wp:form-input --> From 33bdcbc97e4839e9bf69d01046f99b1490b28f66 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:36:59 +0200 Subject: [PATCH 0780/1908] Remove babel from script-modules build (#65279) Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- tools/webpack/script-modules.js | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/tools/webpack/script-modules.js b/tools/webpack/script-modules.js index 57652e0be28e2b..18287c96d83c8a 100644 --- a/tools/webpack/script-modules.js +++ b/tools/webpack/script-modules.js @@ -102,29 +102,6 @@ module.exports = { resolve: { extensions: [ '.js', '.ts', '.tsx' ], }, - module: { - rules: [ - { - test: /\.(j|t)sx?$/, - exclude: /node_modules/, - use: [ - { - loader: require.resolve( 'babel-loader' ), - options: { - cacheDirectory: - process.env.BABEL_CACHE_DIRECTORY || true, - babelrc: false, - configFile: false, - presets: [ - '@babel/preset-typescript', - '@babel/preset-react', - ], - }, - }, - ], - }, - ], - }, plugins: [ ...plugins, new DependencyExtractionWebpackPlugin() ], watchOptions: { ignored: [ '**/node_modules' ], From 33682989255dbceeab2ce67775b8f0c7a05b55de Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Thu, 12 Sep 2024 14:04:35 +0200 Subject: [PATCH 0781/1908] Switch from UglifyJS to Terser to build the polyfill script (#65278) Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: sgomes <sergiomdgomes@git.wordpress.org> --- package-lock.json | 19 ++++++++++--------- package.json | 2 +- packages/babel-preset-default/bin/index.js | 14 +++++++------- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index 32819be602f721..c3ae05f3a6bbe2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -245,9 +245,9 @@ "storybook-source-link": "2.0.9", "strip-json-comments": "5.0.0", "style-loader": "3.2.1", + "terser": "5.32.0", "terser-webpack-plugin": "5.3.9", "typescript": "5.5.3", - "uglify-js": "3.13.7", "uuid": "9.0.1", "webdriverio": "8.16.20", "webpack": "5.88.2", @@ -48431,10 +48431,9 @@ } }, "node_modules/terser": { - "version": "5.31.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", - "integrity": "sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw==", - "license": "BSD-2-Clause", + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.32.0.tgz", + "integrity": "sha512-v3Gtw3IzpBJ0ugkxEX8U0W6+TnPKRRCWGh1jC/iM/e3Ki5+qvO1L1EAZ56bZasc64aXHwRHNIQEzm6//i5cemQ==", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -49267,6 +49266,7 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.7.tgz", "integrity": "sha512-1Psi2MmnZJbnEsgJJIlfnd7tFlJfitusmR7zDI8lXlFI0ACD4/Rm/xdrU8bh6zF0i74aiVoBtkRiFulkrmh3AA==", "dev": true, + "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" }, @@ -93531,9 +93531,9 @@ } }, "terser": { - "version": "5.31.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", - "integrity": "sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw==", + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.32.0.tgz", + "integrity": "sha512-v3Gtw3IzpBJ0ugkxEX8U0W6+TnPKRRCWGh1jC/iM/e3Ki5+qvO1L1EAZ56bZasc64aXHwRHNIQEzm6//i5cemQ==", "requires": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -94155,7 +94155,8 @@ "version": "3.13.7", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.7.tgz", "integrity": "sha512-1Psi2MmnZJbnEsgJJIlfnd7tFlJfitusmR7zDI8lXlFI0ACD4/Rm/xdrU8bh6zF0i74aiVoBtkRiFulkrmh3AA==", - "dev": true + "dev": true, + "optional": true }, "unbox-primitive": { "version": "1.0.2", diff --git a/package.json b/package.json index 29e5f10b6f7a50..46d2b42f267abb 100644 --- a/package.json +++ b/package.json @@ -257,9 +257,9 @@ "storybook-source-link": "2.0.9", "strip-json-comments": "5.0.0", "style-loader": "3.2.1", + "terser": "5.32.0", "terser-webpack-plugin": "5.3.9", "typescript": "5.5.3", - "uglify-js": "3.13.7", "uuid": "9.0.1", "webdriverio": "8.16.20", "webpack": "5.88.2", diff --git a/packages/babel-preset-default/bin/index.js b/packages/babel-preset-default/bin/index.js index 54c35564d43d74..0e0e66b450c1d6 100755 --- a/packages/babel-preset-default/bin/index.js +++ b/packages/babel-preset-default/bin/index.js @@ -4,7 +4,7 @@ * External dependencies */ const builder = require( 'core-js-builder' ); -const { minify } = require( 'uglify-js' ); +const { minify } = require( 'terser' ); const { writeFile } = require( 'fs' ).promises; builder( { @@ -18,15 +18,15 @@ builder( { targets: require( '@wordpress/browserslist-config' ), filename: './build/polyfill.js', } ) - .then( async ( code ) => { - const output = minify( code, { + .then( ( code ) => + minify( code, { output: { comments: ( node, comment ) => - comment.value.indexOf( 'License' ) >= 0, + comment.value.toLowerCase().includes( 'license' ), }, - } ); - await writeFile( './build/polyfill.min.js', output.code ); - } ) + } ) + ) + .then( ( output ) => writeFile( './build/polyfill.min.js', output.code ) ) .catch( ( error ) => { // eslint-disable-next-line no-console console.log( error ); From 0cbc7be68742378b1dd3ef88d51ece2079ca88f0 Mon Sep 17 00:00:00 2001 From: Ilya Gayze <ilya.gayze@gmail.com> Date: Thu, 12 Sep 2024 15:11:42 +0300 Subject: [PATCH 0782/1908] Fix typo in Slot Fills documentation (#65275) Unlinked contributors: greenworld. Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- docs/reference-guides/slotfills/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference-guides/slotfills/README.md b/docs/reference-guides/slotfills/README.md index bab08dc34c40c1..874a3a69096b81 100644 --- a/docs/reference-guides/slotfills/README.md +++ b/docs/reference-guides/slotfills/README.md @@ -166,7 +166,7 @@ import { __ } from '@wordpress/i18n'; */ const SiteEditorDocumentSettingPanel = () => { // Retrieve information about the current post type. - const { isViewable } = useSelect( ( select ) => { + const isViewable = useSelect( ( select ) => { const postTypeName = select( editorStore ).getCurrentPostType(); const postTypeObject = select( coreStore ).getPostType( postTypeName ); From a18d8310309bad51a39a8a99be66ffd36b056fe9 Mon Sep 17 00:00:00 2001 From: Akshat Kakkad <87222220+AKSHAT2802@users.noreply.github.com> Date: Thu, 12 Sep 2024 18:28:42 +0530 Subject: [PATCH 0783/1908] Add props for buttons in editor 2 (#65083) * Add __next40pxDefaultSize for editor 2 files * Update packages/editor/src/components/post-publish-panel/index.js Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> * update test snapshots --------- Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> Co-authored-by: AKSHAT2802 <akshat2802@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/editor/src/components/post-format/index.js | 3 +-- packages/editor/src/components/post-last-revision/index.js | 3 +-- packages/editor/src/components/post-locked-modal/index.js | 6 ++---- packages/editor/src/components/post-publish-panel/index.js | 3 +-- .../post-publish-panel/maybe-post-format-panel.js | 3 +-- .../src/components/post-publish-panel/maybe-upload-media.js | 3 +-- .../post-publish-panel/test/__snapshots__/index.js.snap | 4 ++-- 7 files changed, 9 insertions(+), 16 deletions(-) diff --git a/packages/editor/src/components/post-format/index.js b/packages/editor/src/components/post-format/index.js index 34e86a15b9d7fa..8f7423239600f2 100644 --- a/packages/editor/src/components/post-format/index.js +++ b/packages/editor/src/components/post-format/index.js @@ -100,8 +100,7 @@ export default function PostFormat() { { suggestion && suggestion.id !== postFormat && ( <p className="editor-post-format__suggestion"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="link" onClick={ () => onUpdatePostFormat( suggestion.id ) diff --git a/packages/editor/src/components/post-last-revision/index.js b/packages/editor/src/components/post-last-revision/index.js index b47ddb3acddd5a..c0ce37198c951d 100644 --- a/packages/editor/src/components/post-last-revision/index.js +++ b/packages/editor/src/components/post-last-revision/index.js @@ -36,8 +36,7 @@ function PostLastRevision() { return ( <PostLastRevisionCheck> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize href={ addQueryArgs( 'revision.php', { revision: lastRevisionId, } ) } diff --git a/packages/editor/src/components/post-locked-modal/index.js b/packages/editor/src/components/post-locked-modal/index.js index afb0d48e1a133a..7bfa2d23fd9808 100644 --- a/packages/editor/src/components/post-locked-modal/index.js +++ b/packages/editor/src/components/post-locked-modal/index.js @@ -257,8 +257,7 @@ export default function PostLockedModal() { > { ! isTakeover && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" href={ unlockUrl } > @@ -266,8 +265,7 @@ export default function PostLockedModal() { </Button> ) } <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" href={ allPostsUrl } > diff --git a/packages/editor/src/components/post-publish-panel/index.js b/packages/editor/src/components/post-publish-panel/index.js index 3e411e91db4724..f0e9a55eae0609 100644 --- a/packages/editor/src/components/post-publish-panel/index.js +++ b/packages/editor/src/components/post-publish-panel/index.js @@ -78,8 +78,7 @@ export class PostPublishPanel extends Component { <div className="editor-post-publish-panel__header"> { isPostPublish ? ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + size="compact" onClick={ onClose } icon={ closeSmall } label={ __( 'Close panel' ) } diff --git a/packages/editor/src/components/post-publish-panel/maybe-post-format-panel.js b/packages/editor/src/components/post-publish-panel/maybe-post-format-panel.js index 6320390d9da5cc..a81168808f1af7 100644 --- a/packages/editor/src/components/post-publish-panel/maybe-post-format-panel.js +++ b/packages/editor/src/components/post-publish-panel/maybe-post-format-panel.js @@ -25,8 +25,7 @@ const PostFormatSuggestion = ( { onUpdatePostFormat, } ) => ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="link" onClick={ () => onUpdatePostFormat( suggestedPostFormat ) } > diff --git a/packages/editor/src/components/post-publish-panel/maybe-upload-media.js b/packages/editor/src/components/post-publish-panel/maybe-upload-media.js index 6b252b9f2b399e..8c8d757c583399 100644 --- a/packages/editor/src/components/post-publish-panel/maybe-upload-media.js +++ b/packages/editor/src/components/post-publish-panel/maybe-upload-media.js @@ -256,8 +256,7 @@ export default function MaybeUploadMediaPanel() { <Spinner /> ) : ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" onClick={ uploadImages } > diff --git a/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap b/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap index 9331376d7f9c35..1dd75fffaa7b6a 100644 --- a/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap +++ b/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap @@ -60,7 +60,7 @@ exports[`PostPublishPanel should render the post-publish panel if the post is pu > <button aria-label="Close panel" - class="components-button has-icon" + class="components-button is-compact has-icon" type="button" > <svg @@ -252,7 +252,7 @@ exports[`PostPublishPanel should render the post-publish panel if the post is sc > <button aria-label="Close panel" - class="components-button has-icon" + class="components-button is-compact has-icon" type="button" > <svg From 4c316952eb0d4bf23275a6c7d3bd2e50853bdd06 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Thu, 12 Sep 2024 16:13:00 +0200 Subject: [PATCH 0784/1908] Update: Remove unused css selectors. (#65276) co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-editor/src/components/inserter/style.scss | 9 --------- 1 file changed, 9 deletions(-) diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index 289acecb5c1c33..e772a67a131388 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -155,15 +155,6 @@ $block-inserter-tabs-height: 44px; text-align: right; } -.block-editor-inserter__manage-reusable-blocks-container { - margin: auto $grid-unit-20 $grid-unit-20; -} - -.block-editor-inserter__manage-reusable-blocks { - justify-content: center; - width: 100%; -} - .block-editor-inserter__no-results, .block-editor-inserter__patterns-loading { padding: $grid-unit-40; From 67fe7b00f49d77baccf58ba1ac4105b93396ee0a Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Thu, 12 Sep 2024 15:17:57 +0100 Subject: [PATCH 0785/1908] Add Zoom Out toggle to editor header when experiment enabled (#65183) * Add toggle when experiment active * Add new square icon * Use new icon * Remove zoom out desktop 50% from device preview dropdown * Fix console error for stroke-width to strokeWidth --------- Co-authored-by: Jerry Jones <jones.jeremydavid@gmail.com> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../editor/src/components/header/index.js | 9 ++ .../src/components/preview-dropdown/index.js | 110 +++++------------- .../src/components/zoom-out-toggle/index.js | 34 ++++++ packages/icons/src/index.js | 1 + packages/icons/src/library/square.js | 18 +++ 5 files changed, 88 insertions(+), 84 deletions(-) create mode 100644 packages/editor/src/components/zoom-out-toggle/index.js create mode 100644 packages/icons/src/library/square.js diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index 2e045ad7329428..a838b95258ca6a 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -22,6 +22,7 @@ import PostPublishButtonOrToggle from '../post-publish-button/post-publish-butto import PostSavedState from '../post-saved-state'; import PostViewLink from '../post-view-link'; import PreviewDropdown from '../preview-dropdown'; +import ZoomOutToggle from '../zoom-out-toggle'; import { store as editorStore } from '../../store'; const toolbarVariations = { @@ -48,6 +49,9 @@ function Header( { title, icon, } ) { + const zoomOutExperimentEnabled = + window.__experimentalEnableZoomOutExperiment; + const isWideViewport = useViewportMatch( 'large' ); const isLargeViewport = useViewportMatch( 'medium' ); const isTooNarrowForDocumentBar = useMediaQuery( '(max-width: 403px)' ); @@ -142,9 +146,13 @@ function Header( { forceIsAutosaveable={ forceIsDirty } /> <PostViewLink /> + + { zoomOutExperimentEnabled && <ZoomOutToggle /> } + { ( isWideViewport || ! showIconLabels ) && ( <PinnedItems.Slot scope="core" /> ) } + { ! customSaveButton && ( <PostPublishButtonOrToggle forceIsDirty={ forceIsDirty } @@ -153,6 +161,7 @@ function Header( { } /> ) } + { customSaveButton } <MoreMenu /> </motion.div> diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js index 5acaa351c9bb7e..ecc5bc610a3027 100644 --- a/packages/editor/src/components/preview-dropdown/index.js +++ b/packages/editor/src/components/preview-dropdown/index.js @@ -19,9 +19,7 @@ import { __ } from '@wordpress/i18n'; import { desktop, mobile, tablet, external } from '@wordpress/icons'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -import { useEffect, useRef } from '@wordpress/element'; import { store as preferencesStore } from '@wordpress/preferences'; -import { store as blockEditorStore } from '@wordpress/block-editor'; import { ActionItem } from '@wordpress/interface'; /** @@ -31,49 +29,21 @@ import { store as editorStore } from '../../store'; import PostPreviewButton from '../post-preview-button'; export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { - const { - deviceType, - editorMode, - homeUrl, - isTemplate, - isViewable, - showIconLabels, - } = useSelect( ( select ) => { - const { getDeviceType, getCurrentPostType } = select( editorStore ); - const { getEntityRecord, getPostType } = select( coreStore ); - const { get } = select( preferencesStore ); - const { __unstableGetEditorMode } = select( blockEditorStore ); - const _currentPostType = getCurrentPostType(); - return { - deviceType: getDeviceType(), - editorMode: __unstableGetEditorMode(), - homeUrl: getEntityRecord( 'root', '__unstableBase' )?.home, - isTemplate: _currentPostType === 'wp_template', - isViewable: getPostType( _currentPostType )?.viewable ?? false, - showIconLabels: get( 'core', 'showIconLabels' ), - }; - }, [] ); + const { deviceType, homeUrl, isTemplate, isViewable, showIconLabels } = + useSelect( ( select ) => { + const { getDeviceType, getCurrentPostType } = select( editorStore ); + const { getEntityRecord, getPostType } = select( coreStore ); + const { get } = select( preferencesStore ); + const _currentPostType = getCurrentPostType(); + return { + deviceType: getDeviceType(), + homeUrl: getEntityRecord( 'root', '__unstableBase' )?.home, + isTemplate: _currentPostType === 'wp_template', + isViewable: getPostType( _currentPostType )?.viewable ?? false, + showIconLabels: get( 'core', 'showIconLabels' ), + }; + }, [] ); const { setDeviceType } = useDispatch( editorStore ); - const { __unstableSetEditorMode } = useDispatch( blockEditorStore ); - - /** - * Save the original editing mode in a ref to restore it when we exit zoom out. - */ - const originalEditingModeRef = useRef( editorMode ); - useEffect( () => { - if ( editorMode !== 'zoom-out' ) { - originalEditingModeRef.current = editorMode; - } - - return () => { - if ( - editorMode === 'zoom-out' && - editorMode !== originalEditingModeRef.current - ) { - __unstableSetEditorMode( originalEditingModeRef.current ); - } - }; - }, [ editorMode, __unstableSetEditorMode ] ); const isMobile = useViewportMatch( 'medium', '<' ); if ( isMobile ) { @@ -112,44 +82,17 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { label: __( 'Desktop' ), icon: desktop, }, + { + value: 'Tablet', + label: __( 'Tablet' ), + icon: tablet, + }, + { + value: 'Mobile', + label: __( 'Mobile' ), + icon: mobile, + }, ]; - if ( window.__experimentalEnableZoomOutExperiment ) { - choices.push( { - value: 'ZoomOut', - label: __( 'Desktop (50%)' ), - icon: desktop, - } ); - } - choices.push( { - value: 'Tablet', - label: __( 'Tablet' ), - icon: tablet, - } ); - choices.push( { - value: 'Mobile', - label: __( 'Mobile' ), - icon: mobile, - } ); - - const previewValue = editorMode === 'zoom-out' ? 'ZoomOut' : deviceType; - - /** - * Handles the selection of a device type. - * - * @param {string} value The device type. - */ - const onSelect = ( value ) => { - let newEditorMode = originalEditingModeRef.current; - - if ( value === 'ZoomOut' ) { - newEditorMode = 'zoom-out'; - setDeviceType( 'Desktop' ); - } else { - setDeviceType( value ); - } - - __unstableSetEditorMode( newEditorMode ); - }; return ( <DropdownMenu @@ -161,7 +104,6 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { toggleProps={ toggleProps } menuProps={ menuProps } icon={ deviceIcons[ deviceType.toLowerCase() ] } - text={ editorMode === 'zoom-out' ? __( '50%' ) : undefined } label={ __( 'View' ) } disableOpenOnArrowDown={ disabled } > @@ -170,8 +112,8 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { <MenuGroup> <MenuItemsChoice choices={ choices } - value={ previewValue } - onSelect={ onSelect } + value={ deviceType } + onSelect={ setDeviceType } /> </MenuGroup> { isTemplate && ( diff --git a/packages/editor/src/components/zoom-out-toggle/index.js b/packages/editor/src/components/zoom-out-toggle/index.js new file mode 100644 index 00000000000000..e8c7b1e50510ab --- /dev/null +++ b/packages/editor/src/components/zoom-out-toggle/index.js @@ -0,0 +1,34 @@ +/** + * WordPress dependencies + */ +import { Button } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +import { useDispatch, useSelect } from '@wordpress/data'; +import { store as blockEditorStore } from '@wordpress/block-editor'; +import { square as zoomOutIcon } from '@wordpress/icons'; + +const ZoomOutToggle = () => { + const { isZoomOutMode } = useSelect( ( select ) => ( { + isZoomOutMode: + select( blockEditorStore ).__unstableGetEditorMode() === 'zoom-out', + } ) ); + + const { __unstableSetEditorMode } = useDispatch( blockEditorStore ); + + const handleZoomOut = () => { + __unstableSetEditorMode( isZoomOutMode ? 'edit' : 'zoom-out' ); + }; + + return ( + <Button + onClick={ handleZoomOut } + icon={ zoomOutIcon } + label={ __( 'Toggle Zoom Out' ) } + isPressed={ isZoomOutMode } + size="compact" + /> + ); +}; + +export default ZoomOutToggle; diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index 11b3da927f3644..d60ca5a74eb5bd 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -242,6 +242,7 @@ export { default as store } from './library/store'; export { default as stretchFullWidth } from './library/stretch-full-width'; export { default as styles } from './library/styles'; export { default as shipping } from './library/shipping'; +export { default as square } from './library/square'; export { default as stretchWide } from './library/stretch-wide'; export { default as subscript } from './library/subscript'; export { default as superscript } from './library/superscript'; diff --git a/packages/icons/src/library/square.js b/packages/icons/src/library/square.js new file mode 100644 index 00000000000000..843a8d2d5261dd --- /dev/null +++ b/packages/icons/src/library/square.js @@ -0,0 +1,18 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const square = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"> + <Path + fill="none" + d="M5.75 12.75V18.25H11.25M12.75 5.75H18.25V11.25" + stroke="currentColor" + strokeWidth="1.5" + strokeLinecap="square" + /> + </SVG> +); + +export default square; From eba5eb7c94125c2199930512ed0731675b36562b Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 12 Sep 2024 16:18:13 +0200 Subject: [PATCH 0786/1908] Block Bindings: Try gap 0 on attribute items. (#65277) * Try gap 0 * Use vstack property Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/block-editor/src/hooks/block-bindings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 3b59de2238b968..be632cd4db3a25 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -98,7 +98,7 @@ function BlockBindingsAttribute( { attribute, binding } ) { unlock( blocksPrivateApis ).getBlockBindingsSource( sourceName ); const isSourceInvalid = ! sourceProps; return ( - <VStack className="block-editor-bindings__item"> + <VStack className="block-editor-bindings__item" spacing={ 0 }> <Text truncate>{ attribute }</Text> { !! binding && ( <Text From d329bfb23807f422d44731b8b031832e5afa8488 Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Thu, 12 Sep 2024 16:30:48 +0200 Subject: [PATCH 0787/1908] [Fields] Migrate store and actions from editor package to fields package (#65261) Co-authored-by: gigitux <gigitux@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- package-lock.json | 46 +++++++++- packages/editor/package.json | 1 + .../src/dataviews/store/private-actions.ts | 18 ++-- packages/editor/tsconfig.json | 1 + packages/fields/README.md | 48 ++++++++++- packages/fields/package.json | 23 ++++- .../base-post}/duplicate-post.native.tsx | 0 .../src/actions/base-post}/duplicate-post.tsx | 6 +- .../fields/src/actions/base-post/index.ts | 5 ++ .../base-post}/reorder-page.native.tsx | 0 .../src/actions/base-post}/reorder-page.tsx | 4 +- .../src/actions/base-post}/view-post.tsx | 2 +- packages/fields/src/actions/common/index.ts | 2 + .../common}/permanently-delete-post.tsx | 4 +- .../actions/common}/view-post-revisions.tsx | 2 +- packages/fields/src/actions/index.ts | 3 + .../actions/pattern}/duplicate-pattern.tsx | 2 +- .../pattern}/export-pattern.native.tsx | 0 .../src/actions/pattern}/export-pattern.tsx | 4 +- packages/fields/src/actions/pattern/index.ts | 3 + packages/fields/src/actions/utils.ts | 66 ++++++++++++++ packages/fields/src/fields/index.ts | 2 + packages/fields/src/fields/order/index.ts | 18 ++++ packages/fields/src/fields/title/index.ts | 21 +++++ packages/fields/src/index.native.ts | 2 + packages/fields/src/index.ts | 2 + packages/fields/src/lock-unlock.ts | 9 ++ packages/fields/src/types.ts | 85 +++++++++++++++++++ packages/fields/src/wordpress-editor.d.ts | 1 + packages/fields/tsconfig.json | 22 ++++- 30 files changed, 376 insertions(+), 26 deletions(-) rename packages/{editor/src/dataviews/actions => fields/src/actions/base-post}/duplicate-post.native.tsx (100%) rename packages/{editor/src/dataviews/actions => fields/src/actions/base-post}/duplicate-post.tsx (96%) create mode 100644 packages/fields/src/actions/base-post/index.ts rename packages/{editor/src/dataviews/actions => fields/src/actions/base-post}/reorder-page.native.tsx (100%) rename packages/{editor/src/dataviews/actions => fields/src/actions/base-post}/reorder-page.tsx (96%) rename packages/{editor/src/dataviews/actions => fields/src/actions/base-post}/view-post.tsx (92%) create mode 100644 packages/fields/src/actions/common/index.ts rename packages/{editor/src/dataviews/actions => fields/src/actions/common}/permanently-delete-post.tsx (96%) rename packages/{editor/src/dataviews/actions => fields/src/actions/common}/view-post-revisions.tsx (96%) create mode 100644 packages/fields/src/actions/index.ts rename packages/{editor/src/dataviews/actions => fields/src/actions/pattern}/duplicate-pattern.tsx (95%) rename packages/{editor/src/dataviews/actions => fields/src/actions/pattern}/export-pattern.native.tsx (100%) rename packages/{editor/src/dataviews/actions => fields/src/actions/pattern}/export-pattern.tsx (95%) create mode 100644 packages/fields/src/actions/pattern/index.ts create mode 100644 packages/fields/src/actions/utils.ts create mode 100644 packages/fields/src/fields/index.ts create mode 100644 packages/fields/src/fields/order/index.ts create mode 100644 packages/fields/src/fields/title/index.ts create mode 100644 packages/fields/src/index.native.ts create mode 100644 packages/fields/src/lock-unlock.ts create mode 100644 packages/fields/src/types.ts create mode 100644 packages/fields/src/wordpress-editor.d.ts diff --git a/package-lock.json b/package-lock.json index c3ae05f3a6bbe2..49d1ad6b123b76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53933,6 +53933,7 @@ "@wordpress/deprecated": "file:../deprecated", "@wordpress/dom": "file:../dom", "@wordpress/element": "file:../element", + "@wordpress/fields": "file:../fields", "@wordpress/hooks": "file:../hooks", "@wordpress/html-entities": "file:../html-entities", "@wordpress/i18n": "file:../i18n", @@ -54194,7 +54195,27 @@ "version": "0.0.1", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "^7.16.0", + "@wordpress/blob": "file:../blob", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/dataviews": "file:../dataviews", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/patterns": "file:../patterns", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", + "change-case": "4.1.2", + "client-zip": "^2.4.5" }, "engines": { "node": ">=18.12.0", @@ -68738,6 +68759,7 @@ "@wordpress/deprecated": "file:../deprecated", "@wordpress/dom": "file:../dom", "@wordpress/element": "file:../element", + "@wordpress/fields": "file:../fields", "@wordpress/hooks": "file:../hooks", "@wordpress/html-entities": "file:../html-entities", "@wordpress/i18n": "file:../i18n", @@ -68919,7 +68941,27 @@ "@wordpress/fields": { "version": "file:packages/fields", "requires": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "^7.16.0", + "@wordpress/blob": "file:../blob", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/dataviews": "file:../dataviews", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/patterns": "file:../patterns", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", + "change-case": "4.1.2", + "client-zip": "^2.4.5" } }, "@wordpress/format-library": { diff --git a/packages/editor/package.json b/packages/editor/package.json index a9d486b74e79cf..2e01aff3a0aa5f 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -47,6 +47,7 @@ "@wordpress/deprecated": "file:../deprecated", "@wordpress/dom": "file:../dom", "@wordpress/element": "file:../element", + "@wordpress/fields": "file:../fields", "@wordpress/hooks": "file:../hooks", "@wordpress/html-entities": "file:../html-entities", "@wordpress/i18n": "file:../i18n", diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index a9101e57dd08b5..e685493641f3b8 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -8,22 +8,24 @@ import { doAction } from '@wordpress/hooks'; /** * Internal dependencies */ -import deletePost from '../actions/delete-post'; -import duplicatePattern from '../actions/duplicate-pattern'; import duplicateTemplatePart from '../actions/duplicate-template-part'; -import exportPattern from '../actions/export-pattern'; import resetPost from '../actions/reset-post'; import trashPost from '../actions/trash-post'; -import permanentlyDeletePost from '../actions/permanently-delete-post'; import renamePost from '../actions/rename-post'; -import reorderPage from '../actions/reorder-page'; import restorePost from '../actions/restore-post'; import type { PostType } from '../types'; import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; -import duplicatePost from '../actions/duplicate-post'; -import viewPostRevisions from '../actions/view-post-revisions'; -import viewPost from '../actions/view-post'; +import { + viewPost, + viewPostRevisions, + duplicatePost, + duplicatePattern, + reorderPage, + exportPattern, + permanentlyDeletePost, +} from '@wordpress/fields'; +import deletePost from '../actions/delete-post'; export function registerEntityAction< Item >( kind: string, diff --git a/packages/editor/tsconfig.json b/packages/editor/tsconfig.json index 55d79babd1dacc..3c45fbcb10db3d 100644 --- a/packages/editor/tsconfig.json +++ b/packages/editor/tsconfig.json @@ -20,6 +20,7 @@ { "path": "../deprecated" }, { "path": "../dom" }, { "path": "../element" }, + { "path": "../fields" }, { "path": "../hooks" }, { "path": "../html-entities" }, { "path": "../i18n" }, diff --git a/packages/fields/README.md b/packages/fields/README.md index c5044d1e9fdd2f..842fab02606af8 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -14,7 +14,53 @@ npm install @wordpress/fields --save <!-- START TOKEN(Autogenerated API docs) --> -Nothing to document. +### duplicatePattern + +Undocumented declaration. + +### duplicatePost + +Undocumented declaration. + +### duplicatePostNative + +Undocumented declaration. + +### exportPattern + +Undocumented declaration. + +### exportPatternNative + +Undocumented declaration. + +### orderField + +Undocumented declaration. + +### permanentlyDeletePost + +Undocumented declaration. + +### reorderPage + +Undocumented declaration. + +### reorderPageNative + +Undocumented declaration. + +### titleField + +Undocumented declaration. + +### viewPost + +Undocumented declaration. + +### viewPostRevisions + +Undocumented declaration. <!-- END TOKEN(Autogenerated API docs) --> diff --git a/packages/fields/package.json b/packages/fields/package.json index e953b34264901f..2e417c9f4de570 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -25,13 +25,34 @@ }, "main": "build/index.js", "module": "build-module/index.js", + "react-native": "src/index", "types": "build-types", "sideEffects": [ "build-style/**", "src/**/*.scss" ], "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "^7.16.0", + "@wordpress/blob": "file:../blob", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/dataviews": "file:../dataviews", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/patterns": "file:../patterns", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", + "change-case": "4.1.2", + "client-zip": "^2.4.5" }, "peerDependencies": { "react": "^18.0.0" diff --git a/packages/editor/src/dataviews/actions/duplicate-post.native.tsx b/packages/fields/src/actions/base-post/duplicate-post.native.tsx similarity index 100% rename from packages/editor/src/dataviews/actions/duplicate-post.native.tsx rename to packages/fields/src/actions/base-post/duplicate-post.native.tsx diff --git a/packages/editor/src/dataviews/actions/duplicate-post.tsx b/packages/fields/src/actions/base-post/duplicate-post.tsx similarity index 96% rename from packages/editor/src/dataviews/actions/duplicate-post.tsx rename to packages/fields/src/actions/base-post/duplicate-post.tsx index 0979d30da39519..0035a40c009342 100644 --- a/packages/editor/src/dataviews/actions/duplicate-post.tsx +++ b/packages/fields/src/actions/base-post/duplicate-post.tsx @@ -18,9 +18,9 @@ import type { Action } from '@wordpress/dataviews'; /** * Internal dependencies */ -import { getItemTitle } from '../../dataviews/actions/utils'; -import type { CoreDataError, BasePost } from '../types'; -import { titleField } from '../fields'; +import { titleField } from '../../fields'; +import type { BasePost, CoreDataError } from '../../types'; +import { getItemTitle } from '../utils'; const fields = [ titleField ]; const formDuplicateAction = { diff --git a/packages/fields/src/actions/base-post/index.ts b/packages/fields/src/actions/base-post/index.ts new file mode 100644 index 00000000000000..7541be86c48b1f --- /dev/null +++ b/packages/fields/src/actions/base-post/index.ts @@ -0,0 +1,5 @@ +export { default as viewPost } from './view-post'; +export { default as reorderPage } from './reorder-page'; +export { default as reorderPageNative } from './reorder-page.native'; +export { default as duplicatePost } from './duplicate-post'; +export { default as duplicatePostNative } from './duplicate-post.native'; diff --git a/packages/editor/src/dataviews/actions/reorder-page.native.tsx b/packages/fields/src/actions/base-post/reorder-page.native.tsx similarity index 100% rename from packages/editor/src/dataviews/actions/reorder-page.native.tsx rename to packages/fields/src/actions/base-post/reorder-page.native.tsx diff --git a/packages/editor/src/dataviews/actions/reorder-page.tsx b/packages/fields/src/actions/base-post/reorder-page.tsx similarity index 96% rename from packages/editor/src/dataviews/actions/reorder-page.tsx rename to packages/fields/src/actions/base-post/reorder-page.tsx index 1820884d8d8c73..7f3bca59c471ce 100644 --- a/packages/editor/src/dataviews/actions/reorder-page.tsx +++ b/packages/fields/src/actions/base-post/reorder-page.tsx @@ -17,8 +17,8 @@ import type { Action, RenderModalProps } from '@wordpress/dataviews'; /** * Internal dependencies */ -import type { CoreDataError, BasePost } from '../types'; -import { orderField } from '../fields'; +import type { CoreDataError, BasePost } from '../../types'; +import { orderField } from '../../fields'; const fields = [ orderField ]; const formOrderAction = { diff --git a/packages/editor/src/dataviews/actions/view-post.tsx b/packages/fields/src/actions/base-post/view-post.tsx similarity index 92% rename from packages/editor/src/dataviews/actions/view-post.tsx rename to packages/fields/src/actions/base-post/view-post.tsx index 187faffafb5d3c..8c581877e473bb 100644 --- a/packages/editor/src/dataviews/actions/view-post.tsx +++ b/packages/fields/src/actions/base-post/view-post.tsx @@ -8,7 +8,7 @@ import type { Action } from '@wordpress/dataviews'; /** * Internal dependencies */ -import type { BasePost } from '../types'; +import type { BasePost } from '../../types'; const viewPost: Action< BasePost > = { id: 'view-post', diff --git a/packages/fields/src/actions/common/index.ts b/packages/fields/src/actions/common/index.ts new file mode 100644 index 00000000000000..3590b2e270892e --- /dev/null +++ b/packages/fields/src/actions/common/index.ts @@ -0,0 +1,2 @@ +export { default as viewPostRevisions } from './view-post-revisions'; +export { default as permanentlyDeletePost } from './permanently-delete-post'; diff --git a/packages/editor/src/dataviews/actions/permanently-delete-post.tsx b/packages/fields/src/actions/common/permanently-delete-post.tsx similarity index 96% rename from packages/editor/src/dataviews/actions/permanently-delete-post.tsx rename to packages/fields/src/actions/common/permanently-delete-post.tsx index afbb84ae12c74c..e0c1de96871f1f 100644 --- a/packages/editor/src/dataviews/actions/permanently-delete-post.tsx +++ b/packages/fields/src/actions/common/permanently-delete-post.tsx @@ -10,8 +10,8 @@ import { trash } from '@wordpress/icons'; /** * Internal dependencies */ -import { getItemTitle, isTemplateOrTemplatePart } from './utils'; -import type { CoreDataError, PostWithPermissions } from '../types'; +import { getItemTitle, isTemplateOrTemplatePart } from '../utils'; +import type { CoreDataError, PostWithPermissions } from '../../types'; const permanentlyDeletePost: Action< PostWithPermissions > = { id: 'permanently-delete', diff --git a/packages/editor/src/dataviews/actions/view-post-revisions.tsx b/packages/fields/src/actions/common/view-post-revisions.tsx similarity index 96% rename from packages/editor/src/dataviews/actions/view-post-revisions.tsx rename to packages/fields/src/actions/common/view-post-revisions.tsx index 875b925b94f070..617a5263a707d6 100644 --- a/packages/editor/src/dataviews/actions/view-post-revisions.tsx +++ b/packages/fields/src/actions/common/view-post-revisions.tsx @@ -8,7 +8,7 @@ import type { Action } from '@wordpress/dataviews'; /** * Internal dependencies */ -import type { Post } from '../types'; +import type { Post } from '../../types'; const viewPostRevisions: Action< Post > = { id: 'view-post-revisions', diff --git a/packages/fields/src/actions/index.ts b/packages/fields/src/actions/index.ts new file mode 100644 index 00000000000000..cf4fd6833f3fbe --- /dev/null +++ b/packages/fields/src/actions/index.ts @@ -0,0 +1,3 @@ +export * from './base-post'; +export * from './common'; +export * from './pattern'; diff --git a/packages/editor/src/dataviews/actions/duplicate-pattern.tsx b/packages/fields/src/actions/pattern/duplicate-pattern.tsx similarity index 95% rename from packages/editor/src/dataviews/actions/duplicate-pattern.tsx rename to packages/fields/src/actions/pattern/duplicate-pattern.tsx index 98f43a27c3628c..7c71a271997f15 100644 --- a/packages/editor/src/dataviews/actions/duplicate-pattern.tsx +++ b/packages/fields/src/actions/pattern/duplicate-pattern.tsx @@ -10,7 +10,7 @@ import type { Action } from '@wordpress/dataviews'; * Internal dependencies */ import { unlock } from '../../lock-unlock'; -import type { Pattern } from '../types'; +import type { Pattern } from '../../types'; // Patterns. const { CreatePatternModalContents, useDuplicatePatternProps } = diff --git a/packages/editor/src/dataviews/actions/export-pattern.native.tsx b/packages/fields/src/actions/pattern/export-pattern.native.tsx similarity index 100% rename from packages/editor/src/dataviews/actions/export-pattern.native.tsx rename to packages/fields/src/actions/pattern/export-pattern.native.tsx diff --git a/packages/editor/src/dataviews/actions/export-pattern.tsx b/packages/fields/src/actions/pattern/export-pattern.tsx similarity index 95% rename from packages/editor/src/dataviews/actions/export-pattern.tsx rename to packages/fields/src/actions/pattern/export-pattern.tsx index b6be83eeda84b4..b0f6c3335544c1 100644 --- a/packages/editor/src/dataviews/actions/export-pattern.tsx +++ b/packages/fields/src/actions/pattern/export-pattern.tsx @@ -15,8 +15,8 @@ import type { Action } from '@wordpress/dataviews'; /** * Internal dependencies */ -import type { Pattern } from '../types'; -import { getItemTitle } from './utils'; +import type { Pattern } from '../../types'; +import { getItemTitle } from '../utils'; function getJsonFromItem( item: Pattern ) { return JSON.stringify( diff --git a/packages/fields/src/actions/pattern/index.ts b/packages/fields/src/actions/pattern/index.ts new file mode 100644 index 00000000000000..827c2ce365c2c5 --- /dev/null +++ b/packages/fields/src/actions/pattern/index.ts @@ -0,0 +1,3 @@ +export { default as duplicatePattern } from './duplicate-pattern'; +export { default as exportPattern } from './export-pattern'; +export { default as exportPatternNative } from './export-pattern.native'; diff --git a/packages/fields/src/actions/utils.ts b/packages/fields/src/actions/utils.ts new file mode 100644 index 00000000000000..14e8edae4be048 --- /dev/null +++ b/packages/fields/src/actions/utils.ts @@ -0,0 +1,66 @@ +/** + * WordPress dependencies + */ +import { decodeEntities } from '@wordpress/html-entities'; + +/** + * Internal dependencies + */ +import type { Post, TemplatePart, Template } from '../types'; + +export const TEMPLATE_POST_TYPE = 'wp_template'; +export const TEMPLATE_PART_POST_TYPE = 'wp_template_part'; +export const TEMPLATE_ORIGINS = { + custom: 'custom', + theme: 'theme', + plugin: 'plugin', +}; + +export function isTemplate( post: Post ): post is Template { + return post.type === TEMPLATE_POST_TYPE; +} + +export function isTemplatePart( post: Post ): post is TemplatePart { + return post.type === TEMPLATE_PART_POST_TYPE; +} + +export function isTemplateOrTemplatePart( + p: Post +): p is Template | TemplatePart { + return p.type === TEMPLATE_POST_TYPE || p.type === TEMPLATE_PART_POST_TYPE; +} + +export function getItemTitle( item: Post ) { + if ( typeof item.title === 'string' ) { + return decodeEntities( item.title ); + } + if ( 'rendered' in item.title ) { + return decodeEntities( item.title.rendered ); + } + if ( 'raw' in item.title ) { + return decodeEntities( item.title.raw ); + } + return ''; +} + +/** + * Check if a template is removable. + * + * @param template The template entity to check. + * @return Whether the template is removable. + */ +export function isTemplateRemovable( template: Template | TemplatePart ) { + if ( ! template ) { + return false; + } + // In patterns list page we map the templates parts to a different object + // than the one returned from the endpoint. This is why we need to check for + // two props whether is custom or has a theme file. + return ( + [ template.source, template.source ].includes( + TEMPLATE_ORIGINS.custom + ) && + ! Boolean( template.type === 'wp_template' && template?.plugin ) && + ! template.has_theme_file + ); +} diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts new file mode 100644 index 00000000000000..63ff87842fa4c9 --- /dev/null +++ b/packages/fields/src/fields/index.ts @@ -0,0 +1,2 @@ +export { default as titleField } from './title'; +export { default as orderField } from './order'; diff --git a/packages/fields/src/fields/order/index.ts b/packages/fields/src/fields/order/index.ts new file mode 100644 index 00000000000000..2fc0a216dcfa03 --- /dev/null +++ b/packages/fields/src/fields/order/index.ts @@ -0,0 +1,18 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; + +const orderField: Field< BasePost > = { + type: 'integer', + id: 'menu_order', + label: __( 'Order' ), + description: __( 'Determines the order of pages.' ), +}; + +export default orderField; diff --git a/packages/fields/src/fields/title/index.ts b/packages/fields/src/fields/title/index.ts new file mode 100644 index 00000000000000..5332f476f8ff58 --- /dev/null +++ b/packages/fields/src/fields/title/index.ts @@ -0,0 +1,21 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import { getItemTitle } from '../../actions/utils'; + +const titleField: Field< BasePost > = { + type: 'text', + id: 'title', + label: __( 'Title' ), + placeholder: __( 'No title' ), + getValue: ( { item } ) => getItemTitle( item ), +}; + +export default titleField; diff --git a/packages/fields/src/index.native.ts b/packages/fields/src/index.native.ts new file mode 100644 index 00000000000000..e4d3134d72f847 --- /dev/null +++ b/packages/fields/src/index.native.ts @@ -0,0 +1,2 @@ +export * from './actions/base-post/duplicate-post.native'; +export * from './actions/base-post/reorder-page.native'; diff --git a/packages/fields/src/index.ts b/packages/fields/src/index.ts index e69de29bb2d1d6..4c721b85b61a40 100644 --- a/packages/fields/src/index.ts +++ b/packages/fields/src/index.ts @@ -0,0 +1,2 @@ +export * from './fields'; +export * from './actions'; diff --git a/packages/fields/src/lock-unlock.ts b/packages/fields/src/lock-unlock.ts new file mode 100644 index 00000000000000..2b5dcc4a506311 --- /dev/null +++ b/packages/fields/src/lock-unlock.ts @@ -0,0 +1,9 @@ +/** + * WordPress dependencies + */ +import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; +export const { lock, unlock } = + __dangerousOptInToUnstableAPIsOnlyForCoreModules( + 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', + '@wordpress/fields' + ); diff --git a/packages/fields/src/types.ts b/packages/fields/src/types.ts new file mode 100644 index 00000000000000..664c2dd417201c --- /dev/null +++ b/packages/fields/src/types.ts @@ -0,0 +1,85 @@ +type PostStatus = + | 'published' + | 'draft' + | 'pending' + | 'private' + | 'future' + | 'auto-draft' + | 'trash'; + +export interface CommonPost { + status?: PostStatus; + title: string | { rendered: string } | { raw: string }; + content: string | { raw: string; rendered: string }; + type: string; + id: string | number; + blocks?: Object[]; + _links?: Links; +} + +interface Links { + 'predecessor-version'?: { href: string; id: number }[]; + 'version-history'?: { href: string; count: number }[]; + [ key: string ]: { href: string }[] | undefined; +} + +export interface BasePost extends CommonPost { + comment_status?: 'open' | 'closed'; + excerpt?: string | { raw: string; rendered: string }; + meta?: Record< string, any >; + parent?: number; + password?: string; + template?: string; + format?: string; + featured_media?: number; + menu_order?: number; + ping_status?: 'open' | 'closed'; + link?: string; +} + +export interface Template extends CommonPost { + type: 'wp_template'; + is_custom: boolean; + source: string; + origin: string; + plugin?: string; + has_theme_file: boolean; + id: string; +} + +export interface TemplatePart extends CommonPost { + type: 'wp_template_part'; + source: string; + origin: string; + has_theme_file: boolean; + id: string; + area: string; +} + +export interface Pattern extends CommonPost { + slug: string; + title: { raw: string }; + wp_pattern_sync_status: string; +} + +export type Post = Template | TemplatePart | Pattern | BasePost; + +export type PostWithPermissions = Post & { + permissions: { + delete: boolean; + update: boolean; + }; +}; + +export interface PostType { + slug: string; + viewable: boolean; + supports?: { + 'page-attributes'?: boolean; + title?: boolean; + revisions?: boolean; + }; +} + +// Will be unnecessary after typescript 5.0 upgrade. +export type CoreDataError = { message?: string; code?: string }; diff --git a/packages/fields/src/wordpress-editor.d.ts b/packages/fields/src/wordpress-editor.d.ts new file mode 100644 index 00000000000000..915dacd5f05a9c --- /dev/null +++ b/packages/fields/src/wordpress-editor.d.ts @@ -0,0 +1 @@ +declare module '@wordpress/editor'; diff --git a/packages/fields/tsconfig.json b/packages/fields/tsconfig.json index 79aa09d0ad56e3..c55be59acf40f0 100644 --- a/packages/fields/tsconfig.json +++ b/packages/fields/tsconfig.json @@ -6,6 +6,24 @@ "declarationDir": "build-types", "checkJs": false }, - "references": [], - "include": [ "src" ] + "references": [ + { "path": "../components" }, + { "path": "../compose" }, + { "path": "../data" }, + { "path": "../element" }, + { "path": "../i18n" }, + { "path": "../icons" }, + { "path": "../primitives" }, + { "path": "../private-apis" }, + { "path": "../warning" }, + { "path": "../url" }, + { "path": "../notices" }, + { "path": "../dataviews" }, + { "path": "../blob" }, + { "path": "../core-data" }, + { "path": "../hooks" }, + { "path": "../html-entities" } + ], + "include": [ "src" ], + "exclude": [ "@wordpress/editor" ] } From fb4ba2613f2c9c21fa64f7d9b3b9cd160a238d71 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Thu, 12 Sep 2024 16:29:00 +0100 Subject: [PATCH 0788/1908] Align popover alt variant styling with block toolbar (#65263) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/popover/style.scss | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 67a63b8b656461..a04f7e3f276b96 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Bug Fixes - `Tabs`: indicator positioning under RTL direction ([#64926](https://github.com/WordPress/gutenberg/pull/64926)). +- `Popover`: Update `toolbar` variant radius to match block toolbar ([#65263](https://github.com/WordPress/gutenberg/pull/65263)). ### Deprecations diff --git a/packages/components/src/popover/style.scss b/packages/components/src/popover/style.scss index 01b0eb91161422..bfab8978864b34 100644 --- a/packages/components/src/popover/style.scss +++ b/packages/components/src/popover/style.scss @@ -27,9 +27,10 @@ $shadow-popover-border-top-only-alternate: 0 #{-$border-width} 0 $gray-900; box-sizing: border-box; width: min-content; - // Alternate treatment for popovers that put them at elevation zero with high contrast. + // Alternate treatment for popovers that put them at elevation zero with high contrast and smaller radius. .is-alternate & { box-shadow: $shadow-popover-border-default-alternate; + border-radius: $radius-small; } // A style that gives the popover no visible ui. From 6d32f4fc128b88431c63faa64889fcdc5b7c0a91 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 13 Sep 2024 00:57:48 +0900 Subject: [PATCH 0789/1908] BoxControl: Fix critical error when null value is passed (#65287) * BoxControl: Fix critical error when null value is passed * Add Changelog entry * Update packages/components/src/box-control/utils.ts Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com> --------- Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/box-control/utils.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index a04f7e3f276b96..04858e448da7f0 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -29,6 +29,7 @@ - `Tabs`: improved performance of the indicator animation ([#64926](https://github.com/WordPress/gutenberg/pull/64926)). - `Composite`: Remove from private APIs ([#63569](https://github.com/WordPress/gutenberg/pull/63569)). - use local copy of `use-lilius` instead of `npm` dependency ([#65097](https://github.com/WordPress/gutenberg/pull/65097)). +- `BoxControl`: Fix critical error when null value is passed ([#65287](https://github.com/WordPress/gutenberg/pull/65287)). ## 28.7.0 (2024-09-05) diff --git a/packages/components/src/box-control/utils.ts b/packages/components/src/box-control/utils.ts index e480c9a9f4674a..73c7f4a6a46cfb 100644 --- a/packages/components/src/box-control/utils.ts +++ b/packages/components/src/box-control/utils.ts @@ -179,7 +179,7 @@ export function isValuesMixed( */ export function isValuesDefined( values?: BoxControlValue ) { return ( - values !== undefined && + values && Object.values( values ).filter( // Switching units when input is empty causes values only // containing units. This gives false positive on mixed values From a89527495af5969b7a5670e6814a06682543ae14 Mon Sep 17 00:00:00 2001 From: Akshat Kakkad <87222220+AKSHAT2802@users.noreply.github.com> Date: Fri, 13 Sep 2024 01:44:38 +0530 Subject: [PATCH 0790/1908] Add props for buttons in editor 1 (#65068) * Add props for buttons in editor 1 * Address feedback * remove extra class name and extra styles Co-authored-by: AKSHAT2802 <akshat2802@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/editor/src/components/block-manager/index.js | 3 +-- packages/editor/src/components/editor-history/redo.js | 3 +-- packages/editor/src/components/editor-history/undo.js | 3 +-- packages/editor/src/components/error-boundary/index.js | 7 +------ packages/editor/src/components/post-excerpt/panel.js | 4 +--- .../editor/src/components/post-featured-image/index.js | 9 +++------ .../editor/src/components/post-featured-image/style.scss | 6 +----- 7 files changed, 9 insertions(+), 26 deletions(-) diff --git a/packages/editor/src/components/block-manager/index.js b/packages/editor/src/components/block-manager/index.js index 0f70812e268de4..b3bc1c6f9b0e82 100644 --- a/packages/editor/src/components/block-manager/index.js +++ b/packages/editor/src/components/block-manager/index.js @@ -67,8 +67,7 @@ function BlockManager( { numberOfHiddenBlocks ) } <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="link" onClick={ () => enableAllBlockTypes( blockTypes ) } > diff --git a/packages/editor/src/components/editor-history/redo.js b/packages/editor/src/components/editor-history/redo.js index ef46ff6bc78e2c..46a263bb89926b 100644 --- a/packages/editor/src/components/editor-history/redo.js +++ b/packages/editor/src/components/editor-history/redo.js @@ -25,8 +25,7 @@ function EditorHistoryRedo( props, ref ) { const { redo } = useDispatch( editorStore ); return ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize { ...props } ref={ ref } icon={ ! isRTL() ? redoIcon : undoIcon } diff --git a/packages/editor/src/components/editor-history/undo.js b/packages/editor/src/components/editor-history/undo.js index 0c28f8c8231f8f..6ba6055706e993 100644 --- a/packages/editor/src/components/editor-history/undo.js +++ b/packages/editor/src/components/editor-history/undo.js @@ -21,8 +21,7 @@ function EditorHistoryUndo( props, ref ) { const { undo } = useDispatch( editorStore ); return ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize { ...props } ref={ ref } icon={ ! isRTL() ? undoIcon : redoIcon } diff --git a/packages/editor/src/components/error-boundary/index.js b/packages/editor/src/components/error-boundary/index.js index 30cc6b970f3066..d43af5a556b67b 100644 --- a/packages/editor/src/components/error-boundary/index.js +++ b/packages/editor/src/components/error-boundary/index.js @@ -29,12 +29,7 @@ function getContent() { function CopyButton( { text, children } ) { const ref = useCopyToClipboard( text ); return ( - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - variant="secondary" - ref={ ref } - > + <Button __next40pxDefaultSize variant="secondary" ref={ ref }> { children } </Button> ); diff --git a/packages/editor/src/components/post-excerpt/panel.js b/packages/editor/src/components/post-excerpt/panel.js index 9a37e9134775aa..9c09796f467040 100644 --- a/packages/editor/src/components/post-excerpt/panel.js +++ b/packages/editor/src/components/post-excerpt/panel.js @@ -198,9 +198,7 @@ function PrivateExcerpt() { ref={ setPopoverAnchor } renderToggle={ ( { onToggle } ) => ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - className="editor-post-excerpt__dropdown__trigger" + __next40pxDefaultSize onClick={ onToggle } variant="link" > diff --git a/packages/editor/src/components/post-featured-image/index.js b/packages/editor/src/components/post-featured-image/index.js index b6d44bd668cf75..9907eb5dd0f22d 100644 --- a/packages/editor/src/components/post-featured-image/index.js +++ b/packages/editor/src/components/post-featured-image/index.js @@ -160,8 +160,7 @@ function PostFeaturedImage( { render={ ( { open } ) => ( <div className="editor-post-featured-image__container"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize ref={ toggleRef } className={ ! featuredImageId @@ -202,8 +201,7 @@ function PostFeaturedImage( { { !! featuredImageId && ( <HStack className="editor-post-featured-image__actions"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="editor-post-featured-image__action" onClick={ open } aria-haspopup="dialog" @@ -211,8 +209,7 @@ function PostFeaturedImage( { { __( 'Replace' ) } </Button> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="editor-post-featured-image__action" onClick={ () => { onRemoveImage(); diff --git a/packages/editor/src/components/post-featured-image/style.scss b/packages/editor/src/components/post-featured-image/style.scss index 3a537471b42f29..a14c2ea73a63c1 100644 --- a/packages/editor/src/components/post-featured-image/style.scss +++ b/packages/editor/src/components/post-featured-image/style.scss @@ -53,7 +53,7 @@ } .editor-post-featured-image__preview { - height: auto; + height: auto !important; outline: $border-width solid rgba($black, 0.1); .editor-post-featured-image__preview-image { @@ -65,10 +65,6 @@ } .editor-post-featured-image__toggle { - height: 100%; - line-height: 20px; - padding: $grid-unit-10 0; - text-align: center; box-shadow: inset 0 0 0 $border-width $gray-400; } From 1664022139daa11353788a3ef59686fa7f58b262 Mon Sep 17 00:00:00 2001 From: Rohit Mathur <62138457+rohitmathur-7@users.noreply.github.com> Date: Fri, 13 Sep 2024 08:12:39 +0530 Subject: [PATCH 0791/1908] Grid: In RTL languages, the resize handles point in the opposite direction (#64995) * Fixed the RTL resizing issue * Removed comment, fix spacing * Added else condition * Revert "Fixed the RTL resizing issue" This reverts commit 39cfde5052c71712e4d0f6337f39c523e3830785. * Updated left and right values for justification Co-authored-by: rohitmathur-7 <rohitmathur7@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- .../block-editor/src/components/grid/grid-item-resizer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/grid/grid-item-resizer.js b/packages/block-editor/src/components/grid/grid-item-resizer.js index da3eb824fe92e5..1277ac2a239531 100644 --- a/packages/block-editor/src/components/grid/grid-item-resizer.js +++ b/packages/block-editor/src/components/grid/grid-item-resizer.js @@ -73,8 +73,8 @@ function GridItemResizerInner( { }, [ blockElement, rootBlockElement ] ); const justification = { - right: 'flex-start', - left: 'flex-end', + right: 'left', + left: 'right', }; const alignment = { From 632d8d62e8f8621c2771b266c1d2a68477bb3ca1 Mon Sep 17 00:00:00 2001 From: Madhu Dollu <madhusudhan.dollu@gmail.com> Date: Fri, 13 Sep 2024 12:09:33 +0530 Subject: [PATCH 0792/1908] Spacing control: Replace sides dropdwon with link button (#65193) * replace sides dropdown with link button for spacing control * remove sides dropdown * lowercase the link button tooltip * fix unit tests --- .../components/spacing-sizes-control/index.js | 23 ++--- .../spacing-sizes-control/linked-button.js | 32 +++++++ .../sides-dropdown/index.js | 91 ------------------- .../spacing-sizes-control/test/utils.js | 29 +++--- .../components/spacing-sizes-control/utils.js | 23 +---- 5 files changed, 61 insertions(+), 137 deletions(-) create mode 100644 packages/block-editor/src/components/spacing-sizes-control/linked-button.js delete mode 100644 packages/block-editor/src/components/spacing-sizes-control/sides-dropdown/index.js diff --git a/packages/block-editor/src/components/spacing-sizes-control/index.js b/packages/block-editor/src/components/spacing-sizes-control/index.js index 6886670f541155..6ca143d14706ac 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/index.js +++ b/packages/block-editor/src/components/spacing-sizes-control/index.js @@ -7,7 +7,7 @@ import { __experimentalVStack as VStack, } from '@wordpress/components'; import { useState } from '@wordpress/element'; -import { __, _x, sprintf } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; /** * Internal dependencies @@ -15,7 +15,7 @@ import { __, _x, sprintf } from '@wordpress/i18n'; import AxialInputControls from './input-controls/axial'; import SeparatedInputControls from './input-controls/separated'; import SingleInputControl from './input-controls/single'; -import SidesDropdown from './sides-dropdown'; +import LinkedButton from './linked-button'; import useSpacingSizes from './hooks/use-spacing-sizes'; import { ALL_SIDES, @@ -47,6 +47,10 @@ export default function SpacingSizesControl( { const [ view, setView ] = useState( getInitialView( inputValues, sides ) ); + const toggleLinked = () => { + setView( view === VIEWS.axial ? VIEWS.custom : VIEWS.axial ); + }; + const handleOnChange = ( nextValue ) => { const newValues = { ...values, ...nextValue }; onChange( newValues ); @@ -91,12 +95,6 @@ export default function SpacingSizesControl( { sideLabel ).trim(); - const dropdownLabelText = sprintf( - // translators: %s: The current spacing property e.g. "Padding", "Margin". - _x( '%s options', 'Button label to reveal side configuration options' ), - labelProp - ); - return ( <fieldset className="spacing-sizes-control"> <HStack className="spacing-sizes-control__header"> @@ -107,11 +105,10 @@ export default function SpacingSizesControl( { { label } </BaseControl.VisualLabel> { ! hasOneSide && ! hasOnlyAxialSides && ( - <SidesDropdown - label={ dropdownLabelText } - onChange={ setView } - sides={ sides } - value={ view } + <LinkedButton + label={ labelProp } + onClick={ toggleLinked } + isLinked={ view === VIEWS.axial } /> ) } </HStack> diff --git a/packages/block-editor/src/components/spacing-sizes-control/linked-button.js b/packages/block-editor/src/components/spacing-sizes-control/linked-button.js new file mode 100644 index 00000000000000..e9ca68aaa2b31d --- /dev/null +++ b/packages/block-editor/src/components/spacing-sizes-control/linked-button.js @@ -0,0 +1,32 @@ +/** + * WordPress dependencies + */ +import { Button, Tooltip } from '@wordpress/components'; +import { link, linkOff } from '@wordpress/icons'; +import { __, sprintf } from '@wordpress/i18n'; + +export default function LinkedButton( { isLinked, ...props } ) { + const label = isLinked + ? sprintf( + // translators: 1. Type of spacing being modified (padding, margin, etc). + __( 'Unlink %1$s' ), + props.label.toLowerCase() + ).trim() + : sprintf( + // translators: 1. Type of spacing being modified (padding, margin, etc). + __( 'Link %1$s' ), + props.label.toLowerCase() + ).trim(); + + return ( + <Tooltip text={ label }> + <Button + { ...props } + size="small" + icon={ isLinked ? link : linkOff } + iconSize={ 24 } + aria-label={ label } + /> + </Tooltip> + ); +} diff --git a/packages/block-editor/src/components/spacing-sizes-control/sides-dropdown/index.js b/packages/block-editor/src/components/spacing-sizes-control/sides-dropdown/index.js deleted file mode 100644 index e399efa5b44674..00000000000000 --- a/packages/block-editor/src/components/spacing-sizes-control/sides-dropdown/index.js +++ /dev/null @@ -1,91 +0,0 @@ -/** - * WordPress dependencies - */ -import { DropdownMenu, Icon, MenuGroup, MenuItem } from '@wordpress/components'; -import { check } from '@wordpress/icons'; - -/** - * Internal dependencies - */ -import { getSupportedMenuItems, VIEWS } from '../utils'; - -const checkIcon = <Icon icon={ check } size={ 24 } />; - -export default function SidesDropdown( { - label: labelProp, - onChange, - sides, - value, -} ) { - if ( ! sides || ! sides.length ) { - return; - } - - const supportedItems = getSupportedMenuItems( sides ); - const sideIcon = supportedItems[ value ].icon; - const { custom: customItem, ...menuItems } = supportedItems; - - return ( - <DropdownMenu - icon={ sideIcon } - label={ labelProp } - className="spacing-sizes-control__dropdown" - toggleProps={ { size: 'small' } } - > - { ( { onClose } ) => { - return ( - <> - <MenuGroup> - { Object.entries( menuItems ).map( - ( [ slug, { label, icon } ] ) => { - const isSelected = value === slug; - return ( - <MenuItem - key={ slug } - icon={ icon } - iconPosition="left" - isSelected={ isSelected } - role="menuitemradio" - onClick={ () => { - onChange( slug ); - onClose(); - } } - suffix={ - isSelected - ? checkIcon - : undefined - } - > - { label } - </MenuItem> - ); - } - ) } - </MenuGroup> - { !! customItem && ( - <MenuGroup> - <MenuItem - icon={ customItem.icon } - iconPosition="left" - isSelected={ value === VIEWS.custom } - role="menuitemradio" - onClick={ () => { - onChange( VIEWS.custom ); - onClose(); - } } - suffix={ - value === VIEWS.custom - ? checkIcon - : undefined - } - > - { customItem.label } - </MenuItem> - </MenuGroup> - ) } - </> - ); - } } - </DropdownMenu> - ); -} diff --git a/packages/block-editor/src/components/spacing-sizes-control/test/utils.js b/packages/block-editor/src/components/spacing-sizes-control/test/utils.js index a631cbfcff3ef1..22191b4e1a8de9 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/test/utils.js +++ b/packages/block-editor/src/components/spacing-sizes-control/test/utils.js @@ -373,8 +373,8 @@ describe( 'getInitialView', () => { getInitialView( { top: '1em', right: '10px' }, ALL_SIDES ) ).toBe( VIEWS.custom ); } ); - it( 'should not return custom view if there is only a single side value', () => { - expect( getInitialView( { top: '1em' }, ALL_SIDES ) ).not.toBe( + it( 'should return custom view if there is only a single side value', () => { + expect( getInitialView( { top: '1em' }, ALL_SIDES ) ).toBe( VIEWS.custom ); } ); @@ -387,20 +387,19 @@ describe( 'getInitialView', () => { ); } ); - it( 'should return the single side view if there is only a single side value set and supported sides > 1', () => { - expect( getInitialView( { top: '1em' }, ALL_SIDES ) ).toBe( - VIEWS.top - ); - expect( getInitialView( { right: '1em' }, ALL_SIDES ) ).toBe( - VIEWS.right - ); - expect( getInitialView( { bottom: '1em' }, ALL_SIDES ) ).toBe( - VIEWS.bottom - ); - expect( getInitialView( { left: '1em' }, ALL_SIDES ) ).toBe( - VIEWS.left - ); + it( 'should return single side when only single side supported and no value defined', () => { + expect( getInitialView( {}, [ 'top' ] ) ).toBe( VIEWS.top ); + } ); + + it( 'should return single side when only single side supported and all values defined', () => { + expect( + getInitialView( + { top: '1em', right: '2em', bottom: '1em', left: '2em' }, + [ 'top' ] + ) + ).toBe( VIEWS.top ); } ); + it( 'should return single side view when only one side is supported', () => { expect( getInitialView( { top: '1em' }, [ 'top' ] ) ).toBe( VIEWS.top diff --git a/packages/block-editor/src/components/spacing-sizes-control/utils.js b/packages/block-editor/src/components/spacing-sizes-control/utils.js index 91c5a91934f6e3..df2da0d93d0609 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/utils.js +++ b/packages/block-editor/src/components/spacing-sizes-control/utils.js @@ -364,6 +364,11 @@ export function getInitialView( values = {}, sides ) { const hasNoValuesAndBalancedSides = ! sideValues.length && hasBalancedSidesSupport( sides ); + // Only single side supported and no value defined. + if ( sides?.length === 1 ) { + return sides[ 0 ]; + } + if ( hasAxisSupport( sides ) && ( hasMatchingAxialValues || hasNoValuesAndBalancedSides ) @@ -371,24 +376,6 @@ export function getInitialView( values = {}, sides ) { return VIEWS.axial; } - // Single side. - // - Ensure the side returned is the first side that has a value. - if ( sideValues.length === 1 ) { - let side; - - Object.entries( values ).some( ( [ key, value ] ) => { - side = key; - return value !== undefined; - } ); - - return side; - } - - // Only single side supported and no value defined. - if ( sides?.length === 1 && ! sideValues.length ) { - return sides[ 0 ]; - } - // Default to the Custom (separated sides) view. return VIEWS.custom; } From 33e2fadeebe32a64a946106488120b6f559d3deb Mon Sep 17 00:00:00 2001 From: Mikey Binns <38146638+mikeybinns@users.noreply.github.com> Date: Fri, 13 Sep 2024 11:34:14 +0100 Subject: [PATCH 0793/1908] Styleling config: Fix stylelint config missing files for npm (#65313) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add stylistic configs to packaged files --------- Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> Co-authored-by: mikeybinns <mikeybinns@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/stylelint-config/package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 53051078b9b863..874ec2af0c664d 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -28,7 +28,9 @@ "LICENSE", "README.md", "index.js", - "scss.js" + "scss.js", + "scss-stylistic.js", + "stylistic.js" ], "main": "index.js", "dependencies": { From dfc28b08c077818cda4b7ac29cc7efebfa865aba Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Fri, 13 Sep 2024 13:59:10 +0200 Subject: [PATCH 0794/1908] Patterns: Change deprecated social icons for standard in e2e (#65312) * Change deprecated social icons for standard * Update more tests * Update test/e2e/specs/editor/various/adding-patterns.spec.js Co-authored-by: Kai Hao <kevin830726@gmail.com> * One more spec * Update snapshots * Revert changes to post-editor.spec.js --------- Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- ...ing-from-the-global-inserter-1-chromium.txt | 18 +++++++++++++----- ...pping-from-the-global-inserter-1-webkit.txt | 18 +++++++++++++----- .../editor/various/adding-patterns.spec.js | 8 +++----- .../editor/various/inserting-blocks.spec.js | 4 ++-- 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-chromium.txt b/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-chromium.txt index 45d99c7c27e6fe..753c30a0926707 100644 --- a/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-chromium.txt +++ b/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-chromium.txt @@ -2,10 +2,18 @@ <p>Dummy text</p> <!-- /wp:paragraph --> -<!-- wp:social-links {"customIconColor":"#ffffff","iconColorValue":"#ffffff","customIconBackgroundColor":"#3962e3","iconBackgroundColorValue":"#3962e3","metadata":{"categories":["call-to-action"],"patternName":"core/social-links-shared-background-color","name":"Social links with a shared background color"},"className":"has-icon-color"} --> -<ul class="wp-block-social-links has-icon-color has-icon-background-color"><!-- wp:social-link {"url":"https://wordpress.org","service":"wordpress"} /--> +<!-- wp:query {"queryId":1,"query":{"perPage":3,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","author":"","search":"","exclude":[],"sticky":"","inherit":false},"metadata":{"categories":["posts"],"patternName":"core/query-standard-posts","name":"Standard"}} --> +<div class="wp-block-query"><!-- wp:post-template --> +<!-- wp:post-title {"isLink":true} /--> -<!-- wp:social-link {"url":"#","service":"chain"} /--> +<!-- wp:post-featured-image {"isLink":true,"align":"wide"} /--> -<!-- wp:social-link {"url":"#","service":"mail"} /--></ul> -<!-- /wp:social-links --> \ No newline at end of file +<!-- wp:post-excerpt /--> + +<!-- wp:separator {"opacity":"css"} --> +<hr class="wp-block-separator has-css-opacity"/> +<!-- /wp:separator --> + +<!-- wp:post-date /--> +<!-- /wp:post-template --></div> +<!-- /wp:query --> \ No newline at end of file diff --git a/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-webkit.txt b/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-webkit.txt index 45d99c7c27e6fe..753c30a0926707 100644 --- a/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-webkit.txt +++ b/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-webkit.txt @@ -2,10 +2,18 @@ <p>Dummy text</p> <!-- /wp:paragraph --> -<!-- wp:social-links {"customIconColor":"#ffffff","iconColorValue":"#ffffff","customIconBackgroundColor":"#3962e3","iconBackgroundColorValue":"#3962e3","metadata":{"categories":["call-to-action"],"patternName":"core/social-links-shared-background-color","name":"Social links with a shared background color"},"className":"has-icon-color"} --> -<ul class="wp-block-social-links has-icon-color has-icon-background-color"><!-- wp:social-link {"url":"https://wordpress.org","service":"wordpress"} /--> +<!-- wp:query {"queryId":1,"query":{"perPage":3,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","author":"","search":"","exclude":[],"sticky":"","inherit":false},"metadata":{"categories":["posts"],"patternName":"core/query-standard-posts","name":"Standard"}} --> +<div class="wp-block-query"><!-- wp:post-template --> +<!-- wp:post-title {"isLink":true} /--> -<!-- wp:social-link {"url":"#","service":"chain"} /--> +<!-- wp:post-featured-image {"isLink":true,"align":"wide"} /--> -<!-- wp:social-link {"url":"#","service":"mail"} /--></ul> -<!-- /wp:social-links --> \ No newline at end of file +<!-- wp:post-excerpt /--> + +<!-- wp:separator {"opacity":"css"} --> +<hr class="wp-block-separator has-css-opacity"/> +<!-- /wp:separator --> + +<!-- wp:post-date /--> +<!-- /wp:post-template --></div> +<!-- /wp:query --> \ No newline at end of file diff --git a/test/e2e/specs/editor/various/adding-patterns.spec.js b/test/e2e/specs/editor/various/adding-patterns.spec.js index 2846c7adac271f..35192dd364dc66 100644 --- a/test/e2e/specs/editor/various/adding-patterns.spec.js +++ b/test/e2e/specs/editor/various/adding-patterns.spec.js @@ -14,15 +14,13 @@ test.describe( 'adding patterns', () => { await page.getByRole( 'tab', { name: 'Patterns' } ).click(); await page.fill( 'role=region[name="Block Library"i] >> role=searchbox[name="Search for blocks and patterns"i]', - 'Social links with a shared background color' + 'Standard' ); - await page.click( - 'role=option[name="Social links with a shared background color"i]' - ); + await page.getByRole( 'option', { name: 'Standard' } ).click(); await expect.poll( editor.getBlocks ).toMatchObject( [ { - name: 'core/social-links', + name: 'core/query', }, ] ); } ); diff --git a/test/e2e/specs/editor/various/inserting-blocks.spec.js b/test/e2e/specs/editor/various/inserting-blocks.spec.js index 1a443152800dec..b4f23c8b8e2bbf 100644 --- a/test/e2e/specs/editor/various/inserting-blocks.spec.js +++ b/test/e2e/specs/editor/various/inserting-blocks.spec.js @@ -194,7 +194,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { 'role=region[name="Editor top bar"i] >> role=button[name="Toggle block inserter"i]' ); - const PATTERN_NAME = 'Social links with a shared background color'; + const PATTERN_NAME = 'Standard'; await page.fill( 'role=region[name="Block Library"i] >> role=searchbox[name="Search for blocks and patterns"i]', @@ -350,7 +350,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { 'role=region[name="Editor top bar"i] >> role=button[name="Toggle block inserter"i]' ); - const PATTERN_NAME = 'Social links with a shared background color'; + const PATTERN_NAME = 'Standard'; await page.fill( 'role=region[name="Block Library"i] >> role=searchbox[name="Search for blocks and patterns"i]', From 12660ca05ef04dd0e774c943e78ac4147af2b5ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 13 Sep 2024 15:13:56 +0200 Subject: [PATCH 0795/1908] DataViews: improve UX of bundled views for Pages (#65295) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: Souptik2001 <souptik@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: SaxonF <saxonafletcher@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../src/components/post-list/index.js | 50 ++++++++- .../sidebar-dataviews/default-views.js | 104 ++++++++---------- 2 files changed, 95 insertions(+), 59 deletions(-) diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index bbfece24518495..6738310ff6021b 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -179,6 +179,7 @@ function getItemId( item ) { export default function PostList( { postType } ) { const [ view, setView ] = useView( postType ); + const defaultViews = useDefaultViews( { postType } ); const history = useHistory(); const location = useLocation(); const { @@ -202,7 +203,26 @@ export default function PostList( { postType } ) { [ history ] ); - const { isLoading: isLoadingFields, fields } = usePostFields( view.type ); + const getActiveViewFilters = ( views, match ) => { + const found = views.find( ( { slug } ) => slug === match ); + return found?.filters ?? []; + }; + + const { isLoading: isLoadingFields, fields: _fields } = usePostFields( + view.type + ); + const fields = useMemo( () => { + const activeViewFilters = getActiveViewFilters( + defaultViews, + activeView + ).map( ( { field } ) => field ); + return _fields.map( ( field ) => ( { + ...field, + elements: activeViewFilters.includes( field.id ) + ? [] + : field.elements, + } ) ); + }, [ _fields, defaultViews, activeView ] ); const queryArgs = useMemo( () => { const filters = {}; @@ -225,6 +245,32 @@ export default function PostList( { postType } ) { filters.author_exclude = filter.value; } } ); + + // The bundled views want data filtered without displaying the filter. + const activeViewFilters = getActiveViewFilters( + defaultViews, + activeView + ); + activeViewFilters.forEach( ( filter ) => { + if ( + filter.field === 'status' && + filter.operator === OPERATOR_IS_ANY + ) { + filters.status = filter.value; + } + if ( + filter.field === 'author' && + filter.operator === OPERATOR_IS_ANY + ) { + filters.author = filter.value; + } else if ( + filter.field === 'author' && + filter.operator === OPERATOR_IS_NONE + ) { + filters.author_exclude = filter.value; + } + } ); + // We want to provide a different default item for the status filter // than the REST API provides. if ( ! filters.status || filters.status === '' ) { @@ -240,7 +286,7 @@ export default function PostList( { postType } ) { search: view.search, ...filters, }; - }, [ view ] ); + }, [ view, activeView, defaultViews ] ); const { records, isResolving: isLoadingData, diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index e5db492fce17d0..658fa319e9c667 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -88,76 +88,66 @@ export function useDefaultViews( { postType } ) { title: __( 'Published' ), slug: 'published', icon: published, - view: { - ...DEFAULT_POST_BASE, - filters: [ - { - field: 'status', - operator: OPERATOR_IS_ANY, - value: 'publish', - }, - ], - }, + view: DEFAULT_POST_BASE, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_ANY, + value: 'publish', + }, + ], }, { title: __( 'Scheduled' ), slug: 'future', icon: scheduled, - view: { - ...DEFAULT_POST_BASE, - filters: [ - { - field: 'status', - operator: OPERATOR_IS_ANY, - value: 'future', - }, - ], - }, + view: DEFAULT_POST_BASE, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_ANY, + value: 'future', + }, + ], }, { title: __( 'Drafts' ), slug: 'drafts', icon: drafts, - view: { - ...DEFAULT_POST_BASE, - filters: [ - { - field: 'status', - operator: OPERATOR_IS_ANY, - value: 'draft', - }, - ], - }, + view: DEFAULT_POST_BASE, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_ANY, + value: 'draft', + }, + ], }, { title: __( 'Pending' ), slug: 'pending', icon: pending, - view: { - ...DEFAULT_POST_BASE, - filters: [ - { - field: 'status', - operator: OPERATOR_IS_ANY, - value: 'pending', - }, - ], - }, + view: DEFAULT_POST_BASE, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_ANY, + value: 'pending', + }, + ], }, { title: __( 'Private' ), slug: 'private', icon: notAllowed, - view: { - ...DEFAULT_POST_BASE, - filters: [ - { - field: 'status', - operator: OPERATOR_IS_ANY, - value: 'private', - }, - ], - }, + view: DEFAULT_POST_BASE, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_ANY, + value: 'private', + }, + ], }, { title: __( 'Trash' ), @@ -167,14 +157,14 @@ export function useDefaultViews( { postType } ) { ...DEFAULT_POST_BASE, type: LAYOUT_TABLE, layout: defaultLayouts[ LAYOUT_TABLE ].layout, - filters: [ - { - field: 'status', - operator: OPERATOR_IS_ANY, - value: 'trash', - }, - ], }, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_ANY, + value: 'trash', + }, + ], }, ]; }, [ labels ] ); From b0abc74391809c33675471070660ed2519f22c9b Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Fri, 13 Sep 2024 06:37:53 -0700 Subject: [PATCH 0796/1908] Split content view with meta boxes (#64351) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use iframe even with metaboxes * Split content view when metaboxes are open * Fix styling issues Co-authored-by: t-hamano <wildworks@git.wordpress.org> * Update e2e tests Co-authored-by: ellatrix <ellatrix@git.wordpress.org> * Make metaboxes a details element in short viewports * Make metabox area resizable when viewport isn’t short * Tweak details element usage * Add max-height when resized by user * Hide metabox area if all metaboxes are hidden * Persist toggle and height state in user preferences * Wrap contents and rename things The added wrapping element was due to Safari clipping the drop-shadow when `overflow: auto` was on the component root. * Make visual editor stacking context when iframed with metaboxes * Omit meta box area when empty instead of hiding it * Fix meta boxes content appearing in front of UI * Use split views only when canvas is iframed * Don’t omit main meta box area unless all locations aren’t visible --------- Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: torounit <toro_unit@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: arnaudbroes <arnaudbroes@git.wordpress.org> --- .../edit-post/src/components/layout/index.js | 128 +++++++++++++++++- .../src/components/layout/style.scss | 70 +++++++++- .../components/layout/use-should-iframe.js | 11 +- packages/edit-post/src/store/selectors.js | 1 - .../specs/editor/plugins/meta-boxes.spec.js | 18 ++- .../editor/plugins/wp-editor-meta-box.spec.js | 2 +- .../editor/various/publish-button.spec.js | 7 +- 7 files changed, 205 insertions(+), 32 deletions(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 185f97ba45a56f..2cbf5c32e814b8 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -24,7 +24,12 @@ import { } from '@wordpress/block-editor'; import { PluginArea } from '@wordpress/plugins'; import { __, sprintf } from '@wordpress/i18n'; -import { useCallback, useMemo } from '@wordpress/element'; +import { + useCallback, + useLayoutEffect, + useMemo, + useRef, +} from '@wordpress/element'; import { store as noticesStore } from '@wordpress/notices'; import { store as preferencesStore } from '@wordpress/preferences'; import { @@ -36,8 +41,8 @@ import { privateApis as blockLibraryPrivateApis } from '@wordpress/block-library import { addQueryArgs } from '@wordpress/url'; import { decodeEntities } from '@wordpress/html-entities'; import { store as coreStore } from '@wordpress/core-data'; -import { SlotFillProvider } from '@wordpress/components'; -import { useViewportMatch } from '@wordpress/compose'; +import { ResizableBox, SlotFillProvider } from '@wordpress/components'; +import { useMediaQuery, useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies @@ -151,6 +156,118 @@ function useEditorStyles() { ] ); } +/** + * @param {Object} props + * @param {boolean} props.isLegacy True when the editor canvas is not in an iframe. + */ +function MetaBoxesMain( { isLegacy } ) { + const [ isOpen, openHeight, hasAnyVisible ] = useSelect( ( select ) => { + const { get } = select( preferencesStore ); + const { isMetaBoxLocationVisible } = select( editPostStore ); + return [ + get( 'core/edit-post', 'metaBoxesMainIsOpen' ), + get( 'core/edit-post', 'metaBoxesMainOpenHeight' ), + isMetaBoxLocationVisible( 'normal' ) || + isMetaBoxLocationVisible( 'advanced' ) || + isMetaBoxLocationVisible( 'side' ), + ]; + }, [] ); + const { set: setPreference } = useDispatch( preferencesStore ); + const resizableBoxRef = useRef(); + const isShort = useMediaQuery( '(max-height: 549px)' ); + + const isAutoHeight = openHeight === undefined; + // In case a user size is set stops the default max-height from applying. + useLayoutEffect( () => { + if ( ! isLegacy && hasAnyVisible && ! isShort && ! isAutoHeight ) { + resizableBoxRef.current.resizable.classList.add( 'has-user-size' ); + } + }, [ isAutoHeight, isShort, hasAnyVisible, isLegacy ] ); + + if ( ! hasAnyVisible ) { + return; + } + + const className = 'edit-post-meta-boxes-main'; + const contents = ( + <div + className={ clsx( + // The class name 'edit-post-layout__metaboxes' is retained because some plugins use it. + 'edit-post-layout__metaboxes', + ! isLegacy && 'edit-post-meta-boxes-main__liner' + ) } + > + <MetaBoxes location="normal" /> + <MetaBoxes location="advanced" /> + </div> + ); + + if ( isLegacy ) { + return contents; + } + + if ( isShort ) { + return ( + <details + className={ className } + open={ isOpen } + onToggle={ ( { target } ) => { + setPreference( + 'core/edit-post', + 'metaBoxesMainIsOpen', + target.open + ); + } } + > + <summary>{ __( 'Meta Boxes' ) }</summary> + { contents } + </details> + ); + } + return ( + <ResizableBox + className={ className } + defaultSize={ { height: openHeight } } + ref={ resizableBoxRef } + enable={ { + top: true, + right: false, + bottom: false, + left: false, + topLeft: false, + topRight: false, + bottomRight: false, + bottomLeft: false, + } } + // This is overriden by an !important rule that applies until user resizes. + maxHeight="100%" + bounds="parent" + boundsByDirection + // Avoids hiccups while dragging over objects like iframes and ensures that + // the event to end the drag is captured by the target (resize handle) + // whether or not it’s under the pointer. + onPointerDown={ ( { pointerId, target } ) => { + target.setPointerCapture( pointerId ); + } } + onResizeStart={ ( event, direction, elementRef ) => { + // Avoids height jumping in case it’s limited by max-height. + elementRef.style.height = `${ elementRef.offsetHeight }px`; + // Stops initial max-height from being applied. + elementRef.classList.add( 'has-user-size' ); + } } + onResizeStop={ () => { + setPreference( + 'core/edit-post', + 'metaBoxesMainOpenHeight', + resizableBoxRef.current.state.height + ); + } } + > + { contents } + </ResizableBox> + ); +} + function Layout( { postId: initialPostId, postType: initialPostType, @@ -355,10 +472,7 @@ function Layout( { extraContent={ ! isDistractionFree && showMetaBoxes && ( - <div className="edit-post-layout__metaboxes"> - <MetaBoxes location="normal" /> - <MetaBoxes location="advanced" /> - </div> + <MetaBoxesMain isLegacy={ ! shouldIframe } /> ) } > diff --git a/packages/edit-post/src/components/layout/style.scss b/packages/edit-post/src/components/layout/style.scss index 5fdaceaa002be9..5392a7e9da4d95 100644 --- a/packages/edit-post/src/components/layout/style.scss +++ b/packages/edit-post/src/components/layout/style.scss @@ -1,6 +1,70 @@ -.edit-post-layout__metaboxes { - flex-shrink: 0; - clear: both; +.edit-post-meta-boxes-main { + filter: drop-shadow(0 -1px rgba($color: #000, $alpha: 0.133)); // 0.133 = $gray-200 but with alpha. + background-color: $white; + clear: both; // This is seemingly only needed in case the canvas is not iframe’d. + + &:not(details) { + padding-top: 23px; + max-height: 100%; + + &:not(.has-user-size) { + max-height: 50% !important; + } + } + + // The component renders as a details element in short viewports. + &:is(details) { + & > summary { + cursor: pointer; + color: $gray-900; + background-color: $white; + height: $button-size-compact; + line-height: $button-size-compact; + font-size: 13px; + padding-left: $grid-unit-30; + box-shadow: 0 $border-width $gray-300; + } + + &[open] > summary { + position: sticky; + top: 0; + z-index: 1; + } + } + + & .components-resizable-box__handle-top { + top: 0; + box-shadow: 0 $border-width $gray-300; + } + & .components-resizable-box__side-handle::before { + border-radius: 0; + top: 0; + height: $border-width; + } + & .components-resizable-box__handle::after { + background-color: $gray-300; + box-shadow: none; + border-radius: 4px; + height: $grid-unit-05; + top: calc(50% - #{$grid-unit-05} / 2); + width: 100px; + right: calc(50% - 50px); + } +} + +.edit-post-meta-boxes-main__liner { + overflow: auto; + max-height: 100%; + // Keep the contents behind the resize handle or details summary. + isolation: isolate; +} + +.has-metaboxes .editor-visual-editor { + flex: 1; + + &.is-iframed { + isolation: isolate; + } } // Adjust the position of the notices diff --git a/packages/edit-post/src/components/layout/use-should-iframe.js b/packages/edit-post/src/components/layout/use-should-iframe.js index 248ea53109f250..e36a4773c4a1fd 100644 --- a/packages/edit-post/src/components/layout/use-should-iframe.js +++ b/packages/edit-post/src/components/layout/use-should-iframe.js @@ -6,11 +6,6 @@ import { useSelect } from '@wordpress/data'; import { store as blocksStore } from '@wordpress/blocks'; import { store as blockEditorStore } from '@wordpress/block-editor'; -/** - * Internal dependencies - */ -import { store as editPostStore } from '../../store'; - const isGutenbergPlugin = globalThis.IS_GUTENBERG_PLUGIN ? true : false; export function useShouldIframe() { @@ -18,7 +13,6 @@ export function useShouldIframe() { isBlockBasedTheme, hasV3BlocksOnly, isEditingTemplate, - hasMetaBoxes, isZoomOutMode, } = useSelect( ( select ) => { const { getEditorSettings, getCurrentPostType } = select( editorStore ); @@ -31,14 +25,13 @@ export function useShouldIframe() { return type.apiVersion >= 3; } ), isEditingTemplate: getCurrentPostType() === 'wp_template', - hasMetaBoxes: select( editPostStore ).hasMetaBoxes(), isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', }; }, [] ); return ( - ( ( hasV3BlocksOnly || ( isGutenbergPlugin && isBlockBasedTheme ) ) && - ! hasMetaBoxes ) || + hasV3BlocksOnly || + ( isGutenbergPlugin && isBlockBasedTheme ) || isEditingTemplate || isZoomOutMode ); diff --git a/packages/edit-post/src/store/selectors.js b/packages/edit-post/src/store/selectors.js index da1f9959e32e91..5bea6e7d35eb62 100644 --- a/packages/edit-post/src/store/selectors.js +++ b/packages/edit-post/src/store/selectors.js @@ -379,7 +379,6 @@ export const isMetaBoxLocationVisible = createRegistrySelector( isMetaBoxLocationActive( state, location ) && getMetaBoxesPerLocation( state, location )?.some( ( { id } ) => { return select( editorStore ).isEditorPanelEnabled( - state, `meta-box-${ id }` ); } ) diff --git a/test/e2e/specs/editor/plugins/meta-boxes.spec.js b/test/e2e/specs/editor/plugins/meta-boxes.spec.js index 1b7adc18760ff8..511b3837f80303 100644 --- a/test/e2e/specs/editor/plugins/meta-boxes.spec.js +++ b/test/e2e/specs/editor/plugins/meta-boxes.spec.js @@ -26,7 +26,7 @@ test.describe( 'Meta boxes', () => { await expect( saveDraft ).toBeDisabled(); // Add title to enable valid non-empty post save. - await page + await editor.canvas .getByRole( 'textbox', { name: 'Add title' } ) .fill( 'Hello Meta' ); @@ -44,7 +44,7 @@ test.describe( 'Meta boxes', () => { page, } ) => { // Publish a post so there's something for the latest posts dynamic block to render. - await page + await editor.canvas .getByRole( 'textbox', { name: 'Add title' } ) .fill( 'A published post' ); await page.keyboard.press( 'Enter' ); @@ -53,7 +53,7 @@ test.describe( 'Meta boxes', () => { // Publish a post with the latest posts dynamic block. await admin.createNewPost(); - await page + await editor.canvas .getByRole( 'textbox', { name: 'Add title' } ) .fill( 'Dynamic block test' ); await editor.insertBlock( { name: 'core/latest-posts' } ); @@ -70,10 +70,12 @@ test.describe( 'Meta boxes', () => { editor, page, } ) => { - await page + await editor.canvas .getByRole( 'textbox', { name: 'Add title' } ) .fill( 'A published post' ); - await page.getByRole( 'button', { name: 'Add default block' } ).click(); + await editor.canvas + .getByRole( 'button', { name: 'Add default block' } ) + .click(); await page.keyboard.type( 'Excerpt from content.' ); const postId = await editor.publishPost(); @@ -89,9 +91,11 @@ test.describe( 'Meta boxes', () => { page, } ) => { await editor.openDocumentSettingsSidebar(); - await page.getByRole( 'button', { name: 'Add default block' } ).click(); + await editor.canvas + .getByRole( 'button', { name: 'Add default block' } ) + .click(); await page.keyboard.type( 'Excerpt from content.' ); - await page + await editor.canvas .getByRole( 'textbox', { name: 'Add title' } ) .fill( 'A published post' ); diff --git a/test/e2e/specs/editor/plugins/wp-editor-meta-box.spec.js b/test/e2e/specs/editor/plugins/wp-editor-meta-box.spec.js index 710e06b35e124f..c5eafdafe918db 100644 --- a/test/e2e/specs/editor/plugins/wp-editor-meta-box.spec.js +++ b/test/e2e/specs/editor/plugins/wp-editor-meta-box.spec.js @@ -20,7 +20,7 @@ test.describe( 'WP Editor Meta Boxes', () => { await admin.createNewPost(); // Add title to enable valid non-empty post save. - await page + await editor.canvas .locator( 'role=textbox[name="Add title"i]' ) .type( 'Hello Meta' ); diff --git a/test/e2e/specs/editor/various/publish-button.spec.js b/test/e2e/specs/editor/various/publish-button.spec.js index 631ddcd0fe61ba..cdc9c1a9936361 100644 --- a/test/e2e/specs/editor/various/publish-button.spec.js +++ b/test/e2e/specs/editor/various/publish-button.spec.js @@ -70,13 +70,12 @@ test.describe( 'Post publish button', () => { admin, page, requestUtils, + editor, } ) => { await requestUtils.activatePlugin( 'gutenberg-test-plugin-meta-box' ); await admin.createNewPost(); - await page - .getByRole( 'textbox', { - name: 'Add title', - } ) + await editor.canvas + .getByRole( 'textbox', { name: 'Add title' } ) .fill( 'Test post' ); const topBar = page.getByRole( 'region', { name: 'Editor top bar' } ); From 9e88d8666d097eeaa307009c726ab35cfc940d5a Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Sat, 14 Sep 2024 00:30:30 +1000 Subject: [PATCH 0797/1908] Update minimum required version in PHP. (#65301) * Update minimum required version in PHP. * Use a constant. * Test plugin meta data and constant match. * Set constant incorrectly to demonstrate failing tests. * Use regex to extract the constant. * Match the version in the constant and plugin meta. Co-authored-by: peterwilsoncc <peterwilsoncc@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- gutenberg.php | 6 +++-- .../class-test-plugin-version-meta-test.php | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 phpunit/class-test-plugin-version-meta-test.php diff --git a/gutenberg.php b/gutenberg.php index c9c6e09a8092bf..342c61fb56cd13 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -15,6 +15,8 @@ ### BEGIN AUTO-GENERATED DEFINES defined( 'GUTENBERG_DEVELOPMENT_MODE' ) or define( 'GUTENBERG_DEVELOPMENT_MODE', true ); ### END AUTO-GENERATED DEFINES +defined( 'GUTENBERG_MINIMUM_WP_VERSION' ) or define( 'GUTENBERG_MINIMUM_WP_VERSION', '6.5' ); + gutenberg_pre_init(); @@ -26,7 +28,7 @@ function gutenberg_wordpress_version_notice() { echo '<div class="error"><p>'; /* translators: %s: Minimum required version */ - printf( __( 'Gutenberg requires WordPress %s or later to function properly. Please upgrade WordPress before activating Gutenberg.', 'gutenberg' ), '5.9' ); + printf( __( 'Gutenberg requires WordPress %s or later to function properly. Please upgrade WordPress before activating Gutenberg.', 'gutenberg' ), GUTENBERG_MINIMUM_WP_VERSION ); echo '</p></div>'; deactivate_plugins( array( 'gutenberg/gutenberg.php' ) ); @@ -67,7 +69,7 @@ function gutenberg_pre_init() { // Compare against major release versions (X.Y) rather than minor (X.Y.Z) // unless a minor release is the actual minimum requirement. WordPress reports // X.Y for its major releases. - if ( version_compare( $version, '5.9', '<' ) ) { + if ( version_compare( $version, GUTENBERG_MINIMUM_WP_VERSION, '<' ) ) { add_action( 'admin_notices', 'gutenberg_wordpress_version_notice' ); return; } diff --git a/phpunit/class-test-plugin-version-meta-test.php b/phpunit/class-test-plugin-version-meta-test.php new file mode 100644 index 00000000000000..f0dadf873166fd --- /dev/null +++ b/phpunit/class-test-plugin-version-meta-test.php @@ -0,0 +1,26 @@ +<?php +/** + * Unit tests covering the version checks in the plugin file. + * + * @package Gutenberg + */ +class Test_PluginMetaData_Test extends WP_UnitTestCase { + /** + * Test the minimum WordPress version check. + * + * Ensures the constant defined as the minimum required version of WordPress + * matches the minimum version defined in the plugin header. + */ + public function test_minimum_required_wordpress_version() { + $file_meta = get_file_data( __DIR__ . '/../gutenberg.php', array( 'RequiresWP' => 'Requires at least' ) ); + /* + * Gutenberg.php isn't loaded in the test environment. + * + * Read the file directly and use regex to extract the constant. + */ + preg_match( '/GUTENBERG_MINIMUM_WP_VERSION\', \'(.*?)\'/', file_get_contents( __DIR__ . '/../gutenberg.php' ), $matches ); + $version_in_file = $matches[1]; + + $this->assertSame( $file_meta['RequiresWP'], $version_in_file, 'The minimum required WordPress version does not match the plugin header.' ); + } +} From 257d26aecc8abaac6edad3876aede23603be3efe Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 13 Sep 2024 23:53:34 +0900 Subject: [PATCH 0798/1908] DimensionsPanel: Apply 40px default size to UI when no spacing preset is available (#65300) * DimensionsPanel: Apply 40px default size to UI when no spacing preset is available * Revert unnecessary change Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../src/components/global-styles/dimensions-panel.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/block-editor/src/components/global-styles/dimensions-panel.js b/packages/block-editor/src/components/global-styles/dimensions-panel.js index 8430703aec966d..ce508a5ebc89e5 100644 --- a/packages/block-editor/src/components/global-styles/dimensions-panel.js +++ b/packages/block-editor/src/components/global-styles/dimensions-panel.js @@ -531,6 +531,7 @@ export default function DimensionsPanel( { > { ! showSpacingPresetsControl && ( <BoxControl + __next40pxDefaultSize values={ paddingValues } onChange={ setPaddingValues } label={ __( 'Padding' ) } @@ -571,6 +572,7 @@ export default function DimensionsPanel( { > { ! showSpacingPresetsControl && ( <BoxControl + __next40pxDefaultSize values={ marginValues } onChange={ setMarginValues } inputProps={ inputProps } @@ -617,6 +619,7 @@ export default function DimensionsPanel( { { ! showSpacingPresetsControl && ( isAxialGap ? ( <BoxControl + __next40pxDefaultSize label={ __( 'Block spacing' ) } min={ 0 } onChange={ setGapValues } From 8a815ee716341372cf32b51d62dbbf9ddd174a4f Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Fri, 13 Sep 2024 20:05:11 +0300 Subject: [PATCH 0799/1908] DataViews: Use Dropdown for views config dialog (#65314) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../dataviews-view-config/index.tsx | 48 +++++++++---------- .../dataviews-view-config/style.scss | 15 +++--- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index c01c72d2ebc699..48fdf6906b0774 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -8,7 +8,7 @@ import type { ChangeEvent } from 'react'; */ import { Button, - Popover, + Dropdown, __experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControlOption as ToggleGroupControlOption, __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, @@ -24,7 +24,7 @@ import { BaseControl, } from '@wordpress/components'; import { __, _x, sprintf } from '@wordpress/i18n'; -import { memo, useContext, useState, useMemo } from '@wordpress/element'; +import { memo, useContext, useMemo } from '@wordpress/element'; import { chevronDown, chevronUp, cog, seen, unseen } from '@wordpress/icons'; import warning from '@wordpress/warning'; @@ -549,34 +549,32 @@ function _DataViewsViewConfig( { setDensity: React.Dispatch< React.SetStateAction< number > >; defaultLayouts?: SupportedLayouts; } ) { - const [ isShowingViewPopover, setIsShowingViewPopover ] = - useState< boolean >( false ); - return ( <> <ViewTypeMenu defaultLayouts={ defaultLayouts } /> - <div> - <Button - size="compact" - icon={ cog } - label={ _x( 'View options', 'View is used as a noun' ) } - onClick={ () => setIsShowingViewPopover( true ) } - /> - { isShowingViewPopover && ( - <Popover - placement="bottom-end" - onClose={ () => { - setIsShowingViewPopover( false ); - } } - focusOnMount - > - <DataviewsViewConfigContent - density={ density } - setDensity={ setDensity } + <Dropdown + popoverProps={ { placement: 'bottom-end', offset: 9 } } + contentClassName="dataviews-view-config" + renderToggle={ ( { onToggle } ) => { + return ( + <Button + size="compact" + icon={ cog } + label={ _x( + 'View options', + 'View is used as a noun' + ) } + onClick={ onToggle } /> - </Popover> + ); + } } + renderContent={ () => ( + <DataviewsViewConfigContent + density={ density } + setDensity={ setDensity } + /> ) } - </div> + /> </> ); } diff --git a/packages/dataviews/src/components/dataviews-view-config/style.scss b/packages/dataviews/src/components/dataviews-view-config/style.scss index 4c01de6b8994e6..c7d07fe7866bcf 100644 --- a/packages/dataviews/src/components/dataviews-view-config/style.scss +++ b/packages/dataviews/src/components/dataviews-view-config/style.scss @@ -1,11 +1,14 @@ .dataviews-view-config { - width: 320px; - /* stylelint-disable-next-line property-no-unknown -- the linter needs to be updated to accepted the container-type property */ - container-type: inline-size; - padding: $grid-unit-20; - font-size: $default-font-size; - line-height: $default-line-height; + .components-popover__content { + width: 320px; + /* stylelint-disable-next-line property-no-unknown -- the linter needs to be updated to accepted the container-type property */ + container-type: inline-size; + padding: $grid-unit-20; + font-size: $default-font-size; + line-height: $default-line-height; + } } + .dataviews-view-config__sort-direction .components-toggle-group-control-option-base { text-transform: uppercase; } From e1020339adca55fa73d33020dbf28cf779e387da Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Sat, 14 Sep 2024 00:40:23 +0400 Subject: [PATCH 0800/1908] Block Editor: Use static access for selector in 'useZoomOutModeExit' (#65337) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../block-list/use-block-props/use-zoom-out-mode-exit.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js b/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js index 1944cfde96c7f3..d0001bd3b33c68 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js @@ -16,10 +16,7 @@ import { unlock } from '../../../lock-unlock'; * @param {string} clientId Block client ID. */ export function useZoomOutModeExit( { editorMode } ) { - const getSettings = useSelect( - ( select ) => select( blockEditorStore ).getSettings - ); - + const { getSettings } = useSelect( blockEditorStore ); const { __unstableSetEditorMode } = unlock( useDispatch( blockEditorStore ) ); @@ -51,6 +48,6 @@ export function useZoomOutModeExit( { editorMode } ) { node.removeEventListener( 'dblclick', onDoubleClick ); }; }, - [ editorMode, __unstableSetEditorMode ] + [ editorMode, getSettings, __unstableSetEditorMode ] ); } From 1df91fb8289db22837ab68030ef7d87c90a2ed72 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Fri, 13 Sep 2024 23:13:32 +0200 Subject: [PATCH 0801/1908] Add: Typography styling support to the navigation submenu block. (#65060) co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: cuemarie <plari@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- .../block-library/src/navigation-submenu/block.json | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index b9cae44550181c..0e0de9d4f8a507 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -493,7 +493,7 @@ Add a submenu to your navigation. ([Source](https://github.com/WordPress/gutenbe - **Name:** core/navigation-submenu - **Category:** design - **Parent:** core/navigation -- **Supports:** interactivity (clientNavigation), ~~html~~, ~~reusable~~ +- **Supports:** interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~ - **Attributes:** description, id, isTopLevelItem, kind, label, opensInNewTab, rel, title, type, url ## Page Break diff --git a/packages/block-library/src/navigation-submenu/block.json b/packages/block-library/src/navigation-submenu/block.json index 0bcf8a1a47f384..e767b60aec3a6c 100644 --- a/packages/block-library/src/navigation-submenu/block.json +++ b/packages/block-library/src/navigation-submenu/block.json @@ -59,6 +59,19 @@ "supports": { "reusable": false, "html": false, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, "interactivity": { "clientNavigation": true } From b10ca396e14fc0e9a8dbad583d64cef7b8fbb0c3 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Sun, 15 Sep 2024 01:12:19 +0900 Subject: [PATCH 0802/1908] Editor: Use hooks instead of HoC in `BlockManager` (#65349) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/block-manager/index.js | 114 ++++++++---------- 1 file changed, 49 insertions(+), 65 deletions(-) diff --git a/packages/editor/src/components/block-manager/index.js b/packages/editor/src/components/block-manager/index.js index b3bc1c6f9b0e82..4a1145839976f9 100644 --- a/packages/editor/src/components/block-manager/index.js +++ b/packages/editor/src/components/block-manager/index.js @@ -2,11 +2,11 @@ * WordPress dependencies */ import { store as blocksStore } from '@wordpress/blocks'; -import { withSelect, withDispatch } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import { SearchControl, Button } from '@wordpress/components'; import { __, _n, sprintf } from '@wordpress/i18n'; import { useEffect, useState } from '@wordpress/element'; -import { useDebounce, compose } from '@wordpress/compose'; +import { useDebounce } from '@wordpress/compose'; import { speak } from '@wordpress/a11y'; import { store as preferencesStore } from '@wordpress/preferences'; @@ -17,21 +17,48 @@ import { unlock } from '../../lock-unlock'; import { store as editorStore } from '../../store'; import BlockManagerCategory from './category'; -function BlockManager( { - blockTypes, - categories, - hasBlockSupport, - isMatchingSearchTerm, - numberOfHiddenBlocks, - enableAllBlockTypes, -} ) { +export default function BlockManager() { const debouncedSpeak = useDebounce( speak, 500 ); const [ search, setSearch ] = useState( '' ); + const { showBlockTypes } = unlock( useDispatch( editorStore ) ); - // Filtering occurs here (as opposed to `withSelect`) to avoid - // wasted renders by consequence of `Array#filter` producing - // a new value reference on each call. - blockTypes = blockTypes.filter( + const { + blockTypes, + categories, + hasBlockSupport, + isMatchingSearchTerm, + numberOfHiddenBlocks, + } = useSelect( ( select ) => { + // Some hidden blocks become unregistered + // by removing for instance the plugin that registered them, yet + // they're still remain as hidden by the user's action. + // We consider "hidden", blocks which were hidden and + // are still registered. + const _blockTypes = select( blocksStore ).getBlockTypes(); + const hiddenBlockTypes = ( + select( preferencesStore ).get( 'core', 'hiddenBlockTypes' ) ?? [] + ).filter( ( hiddenBlock ) => { + return _blockTypes.some( + ( registeredBlock ) => registeredBlock.name === hiddenBlock + ); + } ); + + return { + blockTypes: _blockTypes, + categories: select( blocksStore ).getCategories(), + hasBlockSupport: select( blocksStore ).hasBlockSupport, + isMatchingSearchTerm: select( blocksStore ).isMatchingSearchTerm, + numberOfHiddenBlocks: + Array.isArray( hiddenBlockTypes ) && hiddenBlockTypes.length, + }; + }, [] ); + + function enableAllBlockTypes( newBlockTypes ) { + const blockNames = newBlockTypes.map( ( { name } ) => name ); + showBlockTypes( blockNames ); + } + + const filteredBlockTypes = blockTypes.filter( ( blockType ) => hasBlockSupport( blockType, 'inserter', true ) && ( ! search || isMatchingSearchTerm( blockType, search ) ) && @@ -44,14 +71,14 @@ function BlockManager( { if ( ! search ) { return; } - const count = blockTypes.length; + const count = filteredBlockTypes.length; const resultsFoundMessage = sprintf( /* translators: %d: number of results. */ _n( '%d result found.', '%d results found.', count ), count ); debouncedSpeak( resultsFoundMessage ); - }, [ blockTypes.length, search, debouncedSpeak ] ); + }, [ filteredBlockTypes?.length, search, debouncedSpeak ] ); return ( <div className="editor-block-manager__content"> @@ -69,7 +96,9 @@ function BlockManager( { <Button __next40pxDefaultSize variant="link" - onClick={ () => enableAllBlockTypes( blockTypes ) } + onClick={ () => + enableAllBlockTypes( filteredBlockTypes ) + } > { __( 'Reset' ) } </Button> @@ -89,7 +118,7 @@ function BlockManager( { aria-label={ __( 'Available block types' ) } className="editor-block-manager__results" > - { blockTypes.length === 0 && ( + { filteredBlockTypes.length === 0 && ( <p className="editor-block-manager__no-results"> { __( 'No blocks found.' ) } </p> @@ -98,7 +127,7 @@ function BlockManager( { <BlockManagerCategory key={ category.slug } title={ category.title } - blockTypes={ blockTypes.filter( + blockTypes={ filteredBlockTypes.filter( ( blockType ) => blockType.category === category.slug ) } @@ -106,7 +135,7 @@ function BlockManager( { ) ) } <BlockManagerCategory title={ __( 'Uncategorized' ) } - blockTypes={ blockTypes.filter( + blockTypes={ filteredBlockTypes.filter( ( { category } ) => ! category ) } /> @@ -114,48 +143,3 @@ function BlockManager( { </div> ); } - -export default compose( [ - withSelect( ( select ) => { - const { - getBlockTypes, - getCategories, - hasBlockSupport, - isMatchingSearchTerm, - } = select( blocksStore ); - const { get } = select( preferencesStore ); - - // Some hidden blocks become unregistered - // by removing for instance the plugin that registered them, yet - // they're still remain as hidden by the user's action. - // We consider "hidden", blocks which were hidden and - // are still registered. - const blockTypes = getBlockTypes(); - const hiddenBlockTypes = ( - get( 'core', 'hiddenBlockTypes' ) ?? [] - ).filter( ( hiddenBlock ) => { - return blockTypes.some( - ( registeredBlock ) => registeredBlock.name === hiddenBlock - ); - } ); - const numberOfHiddenBlocks = - Array.isArray( hiddenBlockTypes ) && hiddenBlockTypes.length; - - return { - blockTypes, - categories: getCategories(), - hasBlockSupport, - isMatchingSearchTerm, - numberOfHiddenBlocks, - }; - } ), - withDispatch( ( dispatch ) => { - const { showBlockTypes } = unlock( dispatch( editorStore ) ); - return { - enableAllBlockTypes: ( blockTypes ) => { - const blockNames = blockTypes.map( ( { name } ) => name ); - showBlockTypes( blockNames ); - }, - }; - } ), -] )( BlockManager ); From 9f7966610ed14a6e00b832a3c97e1d10caf25d7c Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:33:11 +1000 Subject: [PATCH 0803/1908] Global Styles: refactor site background controls and move site global styles into Background group (#65304) Expose background styles in the top level global styles navigation menu. Background is now underneath color. Refactor background image controls and their styles into a dedicated component. This is in preparation for adding colors and other background controls later. Co-authored-by: amitraj2203 <amitraj2203@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../background-image-control/index.js | 741 +++++++++++++++++ .../background-image-control/style.scss | 170 ++++ .../background-image-control/test/index.js | 47 ++ .../global-styles/background-panel.js | 749 +----------------- .../src/components/global-styles/style.scss | 168 ---- .../global-styles/test/background-panel.js | 48 +- packages/block-editor/src/style.scss | 1 + .../src/components/global-styles/root-menu.js | 16 + .../global-styles/screen-background.js | 37 + .../components/global-styles/screen-layout.js | 16 +- .../src/components/global-styles/ui.js | 5 + packages/icons/src/index.js | 1 + packages/icons/src/library/background.js | 16 + 13 files changed, 1057 insertions(+), 958 deletions(-) create mode 100644 packages/block-editor/src/components/background-image-control/index.js create mode 100644 packages/block-editor/src/components/background-image-control/style.scss create mode 100644 packages/block-editor/src/components/background-image-control/test/index.js create mode 100644 packages/edit-site/src/components/global-styles/screen-background.js create mode 100644 packages/icons/src/library/background.js diff --git a/packages/block-editor/src/components/background-image-control/index.js b/packages/block-editor/src/components/background-image-control/index.js new file mode 100644 index 00000000000000..2703aa3988d64e --- /dev/null +++ b/packages/block-editor/src/components/background-image-control/index.js @@ -0,0 +1,741 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ +import { + ToggleControl, + __experimentalToggleGroupControl as ToggleGroupControl, + __experimentalToggleGroupControlOption as ToggleGroupControlOption, + __experimentalUnitControl as UnitControl, + __experimentalVStack as VStack, + DropZone, + FlexItem, + FocalPointPicker, + MenuItem, + VisuallyHidden, + __experimentalItemGroup as ItemGroup, + __experimentalHStack as HStack, + __experimentalTruncate as Truncate, + Dropdown, + Placeholder, + Spinner, + __experimentalDropdownContentWrapper as DropdownContentWrapper, +} from '@wordpress/components'; +import { __, _x, sprintf } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; +import { getFilename } from '@wordpress/url'; +import { useRef, useState, useEffect, useMemo } from '@wordpress/element'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { focus } from '@wordpress/dom'; +import { isBlobURL } from '@wordpress/blob'; + +/** + * Internal dependencies + */ +import { getResolvedValue } from '../global-styles/utils'; +import { hasBackgroundImageValue } from '../global-styles/background-panel'; +import { setImmutably } from '../../utils/object'; +import MediaReplaceFlow from '../media-replace-flow'; +import { store as blockEditorStore } from '../../store'; + +import { + globalStylesDataKey, + globalStylesLinksDataKey, +} from '../../store/private-keys'; + +const IMAGE_BACKGROUND_TYPE = 'image'; + +const BACKGROUND_POPOVER_PROPS = { + placement: 'left-start', + offset: 36, + shift: true, + className: 'block-editor-global-styles-background-panel__popover', +}; +const noop = () => {}; + +/** + * Get the help text for the background size control. + * + * @param {string} value backgroundSize value. + * @return {string} Translated help text. + */ +function backgroundSizeHelpText( value ) { + if ( value === 'cover' || value === undefined ) { + return __( 'Image covers the space evenly.' ); + } + if ( value === 'contain' ) { + return __( 'Image is contained without distortion.' ); + } + return __( 'Image has a fixed width.' ); +} + +/** + * Converts decimal x and y coords from FocalPointPicker to percentage-based values + * to use as backgroundPosition value. + * + * @param {{x?:number, y?:number}} value FocalPointPicker coords. + * @return {string} backgroundPosition value. + */ +export const coordsToBackgroundPosition = ( value ) => { + if ( ! value || ( isNaN( value.x ) && isNaN( value.y ) ) ) { + return undefined; + } + + const x = isNaN( value.x ) ? 0.5 : value.x; + const y = isNaN( value.y ) ? 0.5 : value.y; + + return `${ x * 100 }% ${ y * 100 }%`; +}; + +/** + * Converts backgroundPosition value to x and y coords for FocalPointPicker. + * + * @param {string} value backgroundPosition value. + * @return {{x?:number, y?:number}} FocalPointPicker coords. + */ +export const backgroundPositionToCoords = ( value ) => { + if ( ! value ) { + return { x: undefined, y: undefined }; + } + + let [ x, y ] = value.split( ' ' ).map( ( v ) => parseFloat( v ) / 100 ); + x = isNaN( x ) ? undefined : x; + y = isNaN( y ) ? x : y; + + return { x, y }; +}; + +function InspectorImagePreviewItem( { + as = 'span', + imgUrl, + toggleProps = {}, + filename, + label, + className, + onToggleCallback = noop, +} ) { + useEffect( () => { + if ( typeof toggleProps?.isOpen !== 'undefined' ) { + onToggleCallback( toggleProps?.isOpen ); + } + }, [ toggleProps?.isOpen, onToggleCallback ] ); + return ( + <ItemGroup as={ as } className={ className } { ...toggleProps }> + <HStack + justify="flex-start" + as="span" + className="block-editor-global-styles-background-panel__inspector-preview-inner" + > + { imgUrl && ( + <span + className="block-editor-global-styles-background-panel__inspector-image-indicator-wrapper" + aria-hidden + > + <span + className="block-editor-global-styles-background-panel__inspector-image-indicator" + style={ { + backgroundImage: `url(${ imgUrl })`, + } } + /> + </span> + ) } + <FlexItem as="span" style={ imgUrl ? {} : { flexGrow: 1 } }> + <Truncate + numberOfLines={ 1 } + className="block-editor-global-styles-background-panel__inspector-media-replace-title" + > + { label } + </Truncate> + <VisuallyHidden as="span"> + { imgUrl + ? sprintf( + /* translators: %s: file name */ + __( 'Background image: %s' ), + filename || label + ) + : __( 'No background image selected' ) } + </VisuallyHidden> + </FlexItem> + </HStack> + </ItemGroup> + ); +} + +function BackgroundControlsPanel( { + label, + filename, + url: imgUrl, + children, + onToggle: onToggleCallback = noop, + hasImageValue, +} ) { + if ( ! hasImageValue ) { + return; + } + + const imgLabel = + label || getFilename( imgUrl ) || __( 'Add background image' ); + + return ( + <Dropdown + popoverProps={ BACKGROUND_POPOVER_PROPS } + renderToggle={ ( { onToggle, isOpen } ) => { + const toggleProps = { + onClick: onToggle, + className: + 'block-editor-global-styles-background-panel__dropdown-toggle', + 'aria-expanded': isOpen, + 'aria-label': __( + 'Background size, position and repeat options.' + ), + isOpen, + }; + return ( + <InspectorImagePreviewItem + imgUrl={ imgUrl } + filename={ filename } + label={ imgLabel } + toggleProps={ toggleProps } + as="button" + onToggleCallback={ onToggleCallback } + /> + ); + } } + renderContent={ () => ( + <DropdownContentWrapper + className="block-editor-global-styles-background-panel__dropdown-content-wrapper" + paddingSize="medium" + > + { children } + </DropdownContentWrapper> + ) } + /> + ); +} + +function LoadingSpinner() { + return ( + <Placeholder className="block-editor-global-styles-background-panel__loading"> + <Spinner /> + </Placeholder> + ); +} + +function BackgroundImageControls( { + onChange, + style, + inheritedValue, + onRemoveImage = noop, + onResetImage = noop, + displayInPanel, + defaultValues, +} ) { + const [ isUploading, setIsUploading ] = useState( false ); + const { getSettings } = useSelect( blockEditorStore ); + + const { id, title, url } = style?.background?.backgroundImage || { + ...inheritedValue?.background?.backgroundImage, + }; + const replaceContainerRef = useRef(); + const { createErrorNotice } = useDispatch( noticesStore ); + const onUploadError = ( message ) => { + createErrorNotice( message, { type: 'snackbar' } ); + setIsUploading( false ); + }; + + const resetBackgroundImage = () => + onChange( + setImmutably( + style, + [ 'background', 'backgroundImage' ], + undefined + ) + ); + + const onSelectMedia = ( media ) => { + if ( ! media || ! media.url ) { + resetBackgroundImage(); + setIsUploading( false ); + return; + } + + if ( isBlobURL( media.url ) ) { + setIsUploading( true ); + return; + } + + // For media selections originated from a file upload. + if ( + ( media.media_type && + media.media_type !== IMAGE_BACKGROUND_TYPE ) || + ( ! media.media_type && + media.type && + media.type !== IMAGE_BACKGROUND_TYPE ) + ) { + onUploadError( + __( 'Only images can be used as a background image.' ) + ); + return; + } + + const sizeValue = + style?.background?.backgroundSize || defaultValues?.backgroundSize; + const positionValue = style?.background?.backgroundPosition; + onChange( + setImmutably( style, [ 'background' ], { + ...style?.background, + backgroundImage: { + url: media.url, + id: media.id, + source: 'file', + title: media.title || undefined, + }, + backgroundPosition: + /* + * A background image uploaded and set in the editor receives a default background position of '50% 0', + * when the background image size is the equivalent of "Tile". + * This is to increase the chance that the image's focus point is visible. + * This is in-editor only to assist with the user experience. + */ + ! positionValue && ( 'auto' === sizeValue || ! sizeValue ) + ? '50% 0' + : positionValue, + backgroundSize: sizeValue, + } ) + ); + setIsUploading( false ); + }; + + // Drag and drop callback, restricting image to one. + const onFilesDrop = ( filesList ) => { + if ( filesList?.length > 1 ) { + onUploadError( + __( 'Only one image can be used as a background image.' ) + ); + return; + } + getSettings().mediaUpload( { + allowedTypes: [ IMAGE_BACKGROUND_TYPE ], + filesList, + onFileChange( [ image ] ) { + onSelectMedia( image ); + }, + onError: onUploadError, + } ); + }; + + const hasValue = hasBackgroundImageValue( style ); + + const closeAndFocus = () => { + const [ toggleButton ] = focus.tabbable.find( + replaceContainerRef.current + ); + // Focus the toggle button and close the dropdown menu. + // This ensures similar behaviour as to selecting an image, where the dropdown is + // closed and focus is redirected to the dropdown toggle button. + toggleButton?.focus(); + toggleButton?.click(); + }; + + const onRemove = () => + onChange( + setImmutably( style, [ 'background' ], { + backgroundImage: 'none', + } ) + ); + const canRemove = ! hasValue && hasBackgroundImageValue( inheritedValue ); + const imgLabel = + title || getFilename( url ) || __( 'Add background image' ); + + return ( + <div + ref={ replaceContainerRef } + className="block-editor-global-styles-background-panel__image-tools-panel-item" + > + { isUploading && <LoadingSpinner /> } + <MediaReplaceFlow + mediaId={ id } + mediaURL={ url } + allowedTypes={ [ IMAGE_BACKGROUND_TYPE ] } + accept="image/*" + onSelect={ onSelectMedia } + popoverProps={ { + className: clsx( { + 'block-editor-global-styles-background-panel__media-replace-popover': + displayInPanel, + } ), + } } + name={ + <InspectorImagePreviewItem + className="block-editor-global-styles-background-panel__image-preview" + imgUrl={ url } + filename={ title } + label={ imgLabel } + /> + } + variant="secondary" + onError={ onUploadError } + onReset={ () => { + closeAndFocus(); + onResetImage(); + } } + > + { canRemove && ( + <MenuItem + onClick={ () => { + closeAndFocus(); + onRemove(); + onRemoveImage(); + } } + > + { __( 'Remove' ) } + </MenuItem> + ) } + </MediaReplaceFlow> + <DropZone + onFilesDrop={ onFilesDrop } + label={ __( 'Drop to upload' ) } + /> + </div> + ); +} + +function BackgroundSizeControls( { + onChange, + style, + inheritedValue, + defaultValues, +} ) { + const sizeValue = + style?.background?.backgroundSize || + inheritedValue?.background?.backgroundSize; + const repeatValue = + style?.background?.backgroundRepeat || + inheritedValue?.background?.backgroundRepeat; + const imageValue = + style?.background?.backgroundImage?.url || + inheritedValue?.background?.backgroundImage?.url; + const isUploadedImage = style?.background?.backgroundImage?.id; + const positionValue = + style?.background?.backgroundPosition || + inheritedValue?.background?.backgroundPosition; + const attachmentValue = + style?.background?.backgroundAttachment || + inheritedValue?.background?.backgroundAttachment; + + /* + * Set default values for uploaded images. + * The default values are passed by the consumer. + * Block-level controls may have different defaults to root-level controls. + * A falsy value is treated by default as `auto` (Tile). + */ + let currentValueForToggle = + ! sizeValue && isUploadedImage + ? defaultValues?.backgroundSize + : sizeValue || 'auto'; + /* + * The incoming value could be a value + unit, e.g. '20px'. + * In this case set the value to 'tile'. + */ + currentValueForToggle = ! [ 'cover', 'contain', 'auto' ].includes( + currentValueForToggle + ) + ? 'auto' + : currentValueForToggle; + /* + * If the current value is `cover` and the repeat value is `undefined`, then + * the toggle should be unchecked as the default state. Otherwise, the toggle + * should reflect the current repeat value. + */ + const repeatCheckedValue = ! ( + repeatValue === 'no-repeat' || + ( currentValueForToggle === 'cover' && repeatValue === undefined ) + ); + + const updateBackgroundSize = ( next ) => { + // When switching to 'contain' toggle the repeat off. + let nextRepeat = repeatValue; + let nextPosition = positionValue; + + if ( next === 'contain' ) { + nextRepeat = 'no-repeat'; + nextPosition = undefined; + } + + if ( next === 'cover' ) { + nextRepeat = undefined; + nextPosition = undefined; + } + + if ( + ( currentValueForToggle === 'cover' || + currentValueForToggle === 'contain' ) && + next === 'auto' + ) { + nextRepeat = undefined; + /* + * A background image uploaded and set in the editor (an image with a record id), + * receives a default background position of '50% 0', + * when the toggle switches to "Tile". This is to increase the chance that + * the image's focus point is visible. + * This is in-editor only to assist with the user experience. + */ + if ( !! style?.background?.backgroundImage?.id ) { + nextPosition = '50% 0'; + } + } + + /* + * Next will be null when the input is cleared, + * in which case the value should be 'auto'. + */ + if ( ! next && currentValueForToggle === 'auto' ) { + next = 'auto'; + } + + onChange( + setImmutably( style, [ 'background' ], { + ...style?.background, + backgroundPosition: nextPosition, + backgroundRepeat: nextRepeat, + backgroundSize: next, + } ) + ); + }; + + const updateBackgroundPosition = ( next ) => { + onChange( + setImmutably( + style, + [ 'background', 'backgroundPosition' ], + coordsToBackgroundPosition( next ) + ) + ); + }; + + const toggleIsRepeated = () => + onChange( + setImmutably( + style, + [ 'background', 'backgroundRepeat' ], + repeatCheckedValue === true ? 'no-repeat' : 'repeat' + ) + ); + + const toggleScrollWithPage = () => + onChange( + setImmutably( + style, + [ 'background', 'backgroundAttachment' ], + attachmentValue === 'fixed' ? 'scroll' : 'fixed' + ) + ); + + // Set a default background position for non-site-wide, uploaded images with a size of 'contain'. + const backgroundPositionValue = + ! positionValue && isUploadedImage && 'contain' === sizeValue + ? defaultValues?.backgroundPosition + : positionValue; + + return ( + <VStack spacing={ 3 } className="single-column"> + <FocalPointPicker + __nextHasNoMarginBottom + label={ __( 'Focal point' ) } + url={ imageValue } + value={ backgroundPositionToCoords( backgroundPositionValue ) } + onChange={ updateBackgroundPosition } + /> + <ToggleControl + __nextHasNoMarginBottom + label={ __( 'Fixed background' ) } + checked={ attachmentValue === 'fixed' } + onChange={ toggleScrollWithPage } + /> + <ToggleGroupControl + __nextHasNoMarginBottom + size="__unstable-large" + label={ __( 'Size' ) } + value={ currentValueForToggle } + onChange={ updateBackgroundSize } + isBlock + help={ backgroundSizeHelpText( + sizeValue || defaultValues?.backgroundSize + ) } + > + <ToggleGroupControlOption + key="cover" + value="cover" + label={ _x( + 'Cover', + 'Size option for background image control' + ) } + /> + <ToggleGroupControlOption + key="contain" + value="contain" + label={ _x( + 'Contain', + 'Size option for background image control' + ) } + /> + <ToggleGroupControlOption + key="tile" + value="auto" + label={ _x( + 'Tile', + 'Size option for background image control' + ) } + /> + </ToggleGroupControl> + <HStack justify="flex-start" spacing={ 2 } as="span"> + <UnitControl + aria-label={ __( 'Background image width' ) } + onChange={ updateBackgroundSize } + value={ sizeValue } + size="__unstable-large" + __unstableInputWidth="100px" + min={ 0 } + placeholder={ __( 'Auto' ) } + disabled={ + currentValueForToggle !== 'auto' || + currentValueForToggle === undefined + } + /> + <ToggleControl + __nextHasNoMarginBottom + label={ __( 'Repeat' ) } + checked={ repeatCheckedValue } + onChange={ toggleIsRepeated } + disabled={ currentValueForToggle === 'cover' } + /> + </HStack> + </VStack> + ); +} + +export default function BackgroundImagePanel( { + value, + onChange, + inheritedValue = value, + settings, + defaultValues = {}, +} ) { + /* + * Resolve any inherited "ref" pointers. + * Should the block editor need resolved, inherited values + * across all controls, this could be abstracted into a hook, + * e.g., useResolveGlobalStyle + */ + const { globalStyles, _links } = useSelect( ( select ) => { + const { getSettings } = select( blockEditorStore ); + const _settings = getSettings(); + return { + globalStyles: _settings[ globalStylesDataKey ], + _links: _settings[ globalStylesLinksDataKey ], + }; + }, [] ); + const resolvedInheritedValue = useMemo( () => { + const resolvedValues = { + background: {}, + }; + + if ( ! inheritedValue?.background ) { + return inheritedValue; + } + + Object.entries( inheritedValue?.background ).forEach( + ( [ key, backgroundValue ] ) => { + resolvedValues.background[ key ] = getResolvedValue( + backgroundValue, + { + styles: globalStyles, + _links, + } + ); + } + ); + return resolvedValues; + }, [ globalStyles, _links, inheritedValue ] ); + + const resetBackground = () => + onChange( setImmutably( value, [ 'background' ], {} ) ); + + const { title, url } = value?.background?.backgroundImage || { + ...resolvedInheritedValue?.background?.backgroundImage, + }; + const hasImageValue = + hasBackgroundImageValue( value ) || + hasBackgroundImageValue( resolvedInheritedValue ); + + const imageValue = + value?.background?.backgroundImage || + inheritedValue?.background?.backgroundImage; + + const shouldShowBackgroundImageControls = + hasImageValue && + 'none' !== imageValue && + ( settings?.background?.backgroundSize || + settings?.background?.backgroundPosition || + settings?.background?.backgroundRepeat ); + + const [ isDropDownOpen, setIsDropDownOpen ] = useState( false ); + + return ( + <div + className={ clsx( + 'block-editor-global-styles-background-panel__inspector-media-replace-container', + { + 'is-open': isDropDownOpen, + } + ) } + > + { shouldShowBackgroundImageControls ? ( + <BackgroundControlsPanel + label={ title } + filename={ title } + url={ url } + onToggle={ setIsDropDownOpen } + hasImageValue={ hasImageValue } + > + <VStack spacing={ 3 } className="single-column"> + <BackgroundImageControls + onChange={ onChange } + style={ value } + inheritedValue={ resolvedInheritedValue } + displayInPanel + onResetImage={ () => { + setIsDropDownOpen( false ); + resetBackground(); + } } + onRemoveImage={ () => setIsDropDownOpen( false ) } + defaultValues={ defaultValues } + /> + <BackgroundSizeControls + onChange={ onChange } + style={ value } + defaultValues={ defaultValues } + inheritedValue={ resolvedInheritedValue } + /> + </VStack> + </BackgroundControlsPanel> + ) : ( + <BackgroundImageControls + onChange={ onChange } + style={ value } + inheritedValue={ resolvedInheritedValue } + defaultValues={ defaultValues } + onResetImage={ () => { + setIsDropDownOpen( false ); + resetBackground(); + } } + onRemoveImage={ () => setIsDropDownOpen( false ) } + /> + ) } + </div> + ); +} diff --git a/packages/block-editor/src/components/background-image-control/style.scss b/packages/block-editor/src/components/background-image-control/style.scss new file mode 100644 index 00000000000000..cde8044c24c121 --- /dev/null +++ b/packages/block-editor/src/components/background-image-control/style.scss @@ -0,0 +1,170 @@ +.block-editor-global-styles-background-panel__inspector-media-replace-container { + border: $border-width solid $gray-300; + border-radius: $radius-small; + // Full width. ToolsPanel lays out children in a grid. + grid-column: 1 / -1; + + &.is-open { + background-color: $gray-100; + } + + .block-editor-global-styles-background-panel__image-tools-panel-item { + flex-grow: 1; + border: 0; + + .components-dropdown { + display: block; + } + } + + .block-editor-global-styles-background-panel__inspector-preview-inner { + height: 100%; + } + + .components-dropdown { + display: block; + height: 36px; + } +} + +.block-editor-global-styles-background-panel__image-tools-panel-item { + border: $border-width solid $gray-300; + + // Full width. ToolsPanel lays out children in a grid. + grid-column: 1 / -1; + + // Ensure the dropzone is positioned to the size of the item. + position: relative; + + // Since there is no option to skip rendering the drag'n'drop icon in drop + // zone, we hide it for now. + .components-drop-zone__content-icon { + display: none; + } + + .components-dropdown { + display: block; + height: 36px; + } + + button.components-button { + color: $gray-900; + width: 100%; + display: block; + + &:hover { + color: var(--wp-admin-theme-color); + } + + &:focus { + box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + } + } + + .block-editor-global-styles-background-panel__loading { + height: 100%; + position: absolute; + z-index: 1; + width: 100%; + padding: 10px 0 0 0; + + svg { + margin: 0; + } + } +} + +.block-editor-global-styles-background-panel__image-preview-content, +.block-editor-global-styles-background-panel__dropdown-toggle { + height: 100%; + width: 100%; + padding-left: $grid-unit-15; +} + +.block-editor-global-styles-background-panel__dropdown-toggle { + cursor: pointer; + background: transparent; + border: none; +} + +.block-editor-global-styles-background-panel__inspector-media-replace-title { + word-break: break-all; + // The Button component is white-space: nowrap, and that won't work with line-clamp. + white-space: normal; + + // Without this, the ellipsis can sometimes be partially hidden by the Button padding. + text-align: start; + text-align-last: center; +} + +.block-editor-global-styles-background-panel__inspector-preview-inner { + .block-editor-global-styles-background-panel__inspector-image-indicator-wrapper { + width: 20px; + height: 20px; + min-width: auto; + } +} + +.block-editor-global-styles-background-panel__inspector-image-indicator { + background-size: cover; + border-radius: $radius-round; + width: 20px; + height: 20px; + display: block; + position: relative; +} + +.block-editor-global-styles-background-panel__inspector-image-indicator::after { + content: ""; + position: absolute; + top: -1px; + left: -1px; + bottom: -1px; + right: -1px; + border-radius: $radius-round; + box-shadow: inset 0 0 0 $border-width rgba(0, 0, 0, 0.2); + // Show a thin outline in Windows high contrast mode, otherwise the button is invisible. + border: 1px solid transparent; + box-sizing: inherit; +} + +.block-editor-global-styles-background-panel__dropdown-content-wrapper { + min-width: 260px; + overflow-x: hidden; + + .components-focal-point-picker-wrapper { + background-color: $gray-100; + width: 100%; + border-radius: $radius-small; + border: $border-width solid $gray-300; + } + + .components-focal-point-picker__media--image { + max-height: 180px; + } + + // Override focal picker to avoid a double border. + .components-focal-point-picker::after { + content: none; + } +} + +// Push control panel into the background when the media modal is open. +.modal-open .block-editor-global-styles-background-panel__popover { + z-index: z-index(".block-editor-global-styles-background-panel__popover"); +} + +.block-editor-global-styles-background-panel__media-replace-popover { + .components-popover__content { + // width of block-editor-global-styles-background-panel__dropdown-content-wrapper minus padding. + width: 226px; + } + + .components-button { + padding: 0 $grid-unit-10; + } + + .components-button .components-menu-items__item-icon.has-icon-right { + margin-left: $grid-unit-30 - $grid-unit-10; + } +} diff --git a/packages/block-editor/src/components/background-image-control/test/index.js b/packages/block-editor/src/components/background-image-control/test/index.js new file mode 100644 index 00000000000000..ebadad97eda022 --- /dev/null +++ b/packages/block-editor/src/components/background-image-control/test/index.js @@ -0,0 +1,47 @@ +/** + * Internal dependencies + */ + +import { backgroundPositionToCoords, coordsToBackgroundPosition } from '../'; + +describe( 'backgroundPositionToCoords', () => { + it( 'should return the correct coordinates for a percentage value using 2-value syntax', () => { + expect( backgroundPositionToCoords( '25% 75%' ) ).toEqual( { + x: 0.25, + y: 0.75, + } ); + } ); + + it( 'should return the correct coordinates for a percentage using 1-value syntax', () => { + expect( backgroundPositionToCoords( '50%' ) ).toEqual( { + x: 0.5, + y: 0.5, + } ); + } ); + + it( 'should return undefined coords in given an empty value', () => { + expect( backgroundPositionToCoords( '' ) ).toEqual( { + x: undefined, + y: undefined, + } ); + } ); + + it( 'should return undefined coords in given a string that cannot be converted', () => { + expect( backgroundPositionToCoords( 'apples' ) ).toEqual( { + x: undefined, + y: undefined, + } ); + } ); +} ); + +describe( 'coordsToBackgroundPosition', () => { + it( 'should return the correct background position for a set of coordinates', () => { + expect( coordsToBackgroundPosition( { x: 0.25, y: 0.75 } ) ).toBe( + '25% 75%' + ); + } ); + + it( 'should return undefined if no coordinates are provided', () => { + expect( coordsToBackgroundPosition( {} ) ).toBeUndefined(); + } ); +} ); diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index 93fed5780e454d..c66ea01bce5498 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -1,71 +1,22 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - /** * WordPress dependencies */ import { __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, - ToggleControl, - __experimentalToggleGroupControl as ToggleGroupControl, - __experimentalToggleGroupControlOption as ToggleGroupControlOption, - __experimentalUnitControl as UnitControl, - __experimentalVStack as VStack, - DropZone, - FlexItem, - FocalPointPicker, - MenuItem, - VisuallyHidden, - __experimentalItemGroup as ItemGroup, - __experimentalHStack as HStack, - __experimentalTruncate as Truncate, - Dropdown, - Placeholder, - Spinner, - __experimentalDropdownContentWrapper as DropdownContentWrapper, } from '@wordpress/components'; -import { __, _x, sprintf } from '@wordpress/i18n'; -import { store as noticesStore } from '@wordpress/notices'; -import { getFilename } from '@wordpress/url'; -import { - useCallback, - Platform, - useRef, - useState, - useEffect, - useMemo, -} from '@wordpress/element'; -import { useDispatch, useSelect } from '@wordpress/data'; -import { focus } from '@wordpress/dom'; -import { isBlobURL } from '@wordpress/blob'; - +import { useCallback, Platform } from '@wordpress/element'; /** * Internal dependencies */ -import { useToolsPanelDropdownMenuProps, getResolvedValue } from './utils'; +import BackgroundImageControl from '../background-image-control'; +import { useToolsPanelDropdownMenuProps } from './utils'; import { setImmutably } from '../../utils/object'; -import MediaReplaceFlow from '../media-replace-flow'; -import { store as blockEditorStore } from '../../store'; - -import { - globalStylesDataKey, - globalStylesLinksDataKey, -} from '../../store/private-keys'; +import { __ } from '@wordpress/i18n'; -const IMAGE_BACKGROUND_TYPE = 'image'; const DEFAULT_CONTROLS = { backgroundImage: true, }; -const BACKGROUND_POPOVER_PROPS = { - placement: 'left-start', - offset: 36, - shift: true, - className: 'block-editor-global-styles-background-panel__popover', -}; -const noop = () => {}; /** * Checks site settings to see if the background panel may be used. @@ -110,567 +61,6 @@ export function hasBackgroundImageValue( style ) { ); } -/** - * Get the help text for the background size control. - * - * @param {string} value backgroundSize value. - * @return {string} Translated help text. - */ -function backgroundSizeHelpText( value ) { - if ( value === 'cover' || value === undefined ) { - return __( 'Image covers the space evenly.' ); - } - if ( value === 'contain' ) { - return __( 'Image is contained without distortion.' ); - } - return __( 'Image has a fixed width.' ); -} - -/** - * Converts decimal x and y coords from FocalPointPicker to percentage-based values - * to use as backgroundPosition value. - * - * @param {{x?:number, y?:number}} value FocalPointPicker coords. - * @return {string} backgroundPosition value. - */ -export const coordsToBackgroundPosition = ( value ) => { - if ( ! value || ( isNaN( value.x ) && isNaN( value.y ) ) ) { - return undefined; - } - - const x = isNaN( value.x ) ? 0.5 : value.x; - const y = isNaN( value.y ) ? 0.5 : value.y; - - return `${ x * 100 }% ${ y * 100 }%`; -}; - -/** - * Converts backgroundPosition value to x and y coords for FocalPointPicker. - * - * @param {string} value backgroundPosition value. - * @return {{x?:number, y?:number}} FocalPointPicker coords. - */ -export const backgroundPositionToCoords = ( value ) => { - if ( ! value ) { - return { x: undefined, y: undefined }; - } - - let [ x, y ] = value.split( ' ' ).map( ( v ) => parseFloat( v ) / 100 ); - x = isNaN( x ) ? undefined : x; - y = isNaN( y ) ? x : y; - - return { x, y }; -}; - -function InspectorImagePreviewItem( { - as = 'span', - imgUrl, - toggleProps = {}, - filename, - label, - className, - onToggleCallback = noop, -} ) { - useEffect( () => { - if ( typeof toggleProps?.isOpen !== 'undefined' ) { - onToggleCallback( toggleProps?.isOpen ); - } - }, [ toggleProps?.isOpen, onToggleCallback ] ); - return ( - <ItemGroup as={ as } className={ className } { ...toggleProps }> - <HStack - justify="flex-start" - as="span" - className="block-editor-global-styles-background-panel__inspector-preview-inner" - > - { imgUrl && ( - <span - className="block-editor-global-styles-background-panel__inspector-image-indicator-wrapper" - aria-hidden - > - <span - className="block-editor-global-styles-background-panel__inspector-image-indicator" - style={ { - backgroundImage: `url(${ imgUrl })`, - } } - /> - </span> - ) } - <FlexItem as="span" style={ imgUrl ? {} : { flexGrow: 1 } }> - <Truncate - numberOfLines={ 1 } - className="block-editor-global-styles-background-panel__inspector-media-replace-title" - > - { label } - </Truncate> - <VisuallyHidden as="span"> - { imgUrl - ? sprintf( - /* translators: %s: file name */ - __( 'Background image: %s' ), - filename || label - ) - : __( 'No background image selected' ) } - </VisuallyHidden> - </FlexItem> - </HStack> - </ItemGroup> - ); -} - -function BackgroundControlsPanel( { - label, - filename, - url: imgUrl, - children, - onToggle: onToggleCallback = noop, - hasImageValue, -} ) { - if ( ! hasImageValue ) { - return; - } - - const imgLabel = - label || getFilename( imgUrl ) || __( 'Add background image' ); - - return ( - <Dropdown - popoverProps={ BACKGROUND_POPOVER_PROPS } - renderToggle={ ( { onToggle, isOpen } ) => { - const toggleProps = { - onClick: onToggle, - className: - 'block-editor-global-styles-background-panel__dropdown-toggle', - 'aria-expanded': isOpen, - 'aria-label': __( - 'Background size, position and repeat options.' - ), - isOpen, - }; - return ( - <InspectorImagePreviewItem - imgUrl={ imgUrl } - filename={ filename } - label={ imgLabel } - toggleProps={ toggleProps } - as="button" - onToggleCallback={ onToggleCallback } - /> - ); - } } - renderContent={ () => ( - <DropdownContentWrapper - className="block-editor-global-styles-background-panel__dropdown-content-wrapper" - paddingSize="medium" - > - { children } - </DropdownContentWrapper> - ) } - /> - ); -} - -function LoadingSpinner() { - return ( - <Placeholder className="block-editor-global-styles-background-panel__loading"> - <Spinner /> - </Placeholder> - ); -} - -function BackgroundImageControls( { - onChange, - style, - inheritedValue, - onRemoveImage = noop, - onResetImage = noop, - displayInPanel, - defaultValues, -} ) { - const [ isUploading, setIsUploading ] = useState( false ); - const { getSettings } = useSelect( blockEditorStore ); - - const { id, title, url } = style?.background?.backgroundImage || { - ...inheritedValue?.background?.backgroundImage, - }; - const replaceContainerRef = useRef(); - const { createErrorNotice } = useDispatch( noticesStore ); - const onUploadError = ( message ) => { - createErrorNotice( message, { type: 'snackbar' } ); - setIsUploading( false ); - }; - - const resetBackgroundImage = () => - onChange( - setImmutably( - style, - [ 'background', 'backgroundImage' ], - undefined - ) - ); - - const onSelectMedia = ( media ) => { - if ( ! media || ! media.url ) { - resetBackgroundImage(); - setIsUploading( false ); - return; - } - - if ( isBlobURL( media.url ) ) { - setIsUploading( true ); - return; - } - - // For media selections originated from a file upload. - if ( - ( media.media_type && - media.media_type !== IMAGE_BACKGROUND_TYPE ) || - ( ! media.media_type && - media.type && - media.type !== IMAGE_BACKGROUND_TYPE ) - ) { - onUploadError( - __( 'Only images can be used as a background image.' ) - ); - return; - } - - const sizeValue = - style?.background?.backgroundSize || defaultValues?.backgroundSize; - const positionValue = style?.background?.backgroundPosition; - onChange( - setImmutably( style, [ 'background' ], { - ...style?.background, - backgroundImage: { - url: media.url, - id: media.id, - source: 'file', - title: media.title || undefined, - }, - backgroundPosition: - /* - * A background image uploaded and set in the editor receives a default background position of '50% 0', - * when the background image size is the equivalent of "Tile". - * This is to increase the chance that the image's focus point is visible. - * This is in-editor only to assist with the user experience. - */ - ! positionValue && ( 'auto' === sizeValue || ! sizeValue ) - ? '50% 0' - : positionValue, - backgroundSize: sizeValue, - } ) - ); - setIsUploading( false ); - }; - - // Drag and drop callback, restricting image to one. - const onFilesDrop = ( filesList ) => { - if ( filesList?.length > 1 ) { - onUploadError( - __( 'Only one image can be used as a background image.' ) - ); - return; - } - getSettings().mediaUpload( { - allowedTypes: [ IMAGE_BACKGROUND_TYPE ], - filesList, - onFileChange( [ image ] ) { - onSelectMedia( image ); - }, - onError: onUploadError, - } ); - }; - - const hasValue = hasBackgroundImageValue( style ); - - const closeAndFocus = () => { - const [ toggleButton ] = focus.tabbable.find( - replaceContainerRef.current - ); - // Focus the toggle button and close the dropdown menu. - // This ensures similar behaviour as to selecting an image, where the dropdown is - // closed and focus is redirected to the dropdown toggle button. - toggleButton?.focus(); - toggleButton?.click(); - }; - - const onRemove = () => - onChange( - setImmutably( style, [ 'background' ], { - backgroundImage: 'none', - } ) - ); - const canRemove = ! hasValue && hasBackgroundImageValue( inheritedValue ); - const imgLabel = - title || getFilename( url ) || __( 'Add background image' ); - - return ( - <div - ref={ replaceContainerRef } - className="block-editor-global-styles-background-panel__image-tools-panel-item" - > - { isUploading && <LoadingSpinner /> } - <MediaReplaceFlow - mediaId={ id } - mediaURL={ url } - allowedTypes={ [ IMAGE_BACKGROUND_TYPE ] } - accept="image/*" - onSelect={ onSelectMedia } - popoverProps={ { - className: clsx( { - 'block-editor-global-styles-background-panel__media-replace-popover': - displayInPanel, - } ), - } } - name={ - <InspectorImagePreviewItem - className="block-editor-global-styles-background-panel__image-preview" - imgUrl={ url } - filename={ title } - label={ imgLabel } - /> - } - variant="secondary" - onError={ onUploadError } - onReset={ () => { - closeAndFocus(); - onResetImage(); - } } - > - { canRemove && ( - <MenuItem - onClick={ () => { - closeAndFocus(); - onRemove(); - onRemoveImage(); - } } - > - { __( 'Remove' ) } - </MenuItem> - ) } - </MediaReplaceFlow> - <DropZone - onFilesDrop={ onFilesDrop } - label={ __( 'Drop to upload' ) } - /> - </div> - ); -} - -function BackgroundSizeControls( { - onChange, - style, - inheritedValue, - defaultValues, -} ) { - const sizeValue = - style?.background?.backgroundSize || - inheritedValue?.background?.backgroundSize; - const repeatValue = - style?.background?.backgroundRepeat || - inheritedValue?.background?.backgroundRepeat; - const imageValue = - style?.background?.backgroundImage?.url || - inheritedValue?.background?.backgroundImage?.url; - const isUploadedImage = style?.background?.backgroundImage?.id; - const positionValue = - style?.background?.backgroundPosition || - inheritedValue?.background?.backgroundPosition; - const attachmentValue = - style?.background?.backgroundAttachment || - inheritedValue?.background?.backgroundAttachment; - - /* - * Set default values for uploaded images. - * The default values are passed by the consumer. - * Block-level controls may have different defaults to root-level controls. - * A falsy value is treated by default as `auto` (Tile). - */ - let currentValueForToggle = - ! sizeValue && isUploadedImage - ? defaultValues?.backgroundSize - : sizeValue || 'auto'; - /* - * The incoming value could be a value + unit, e.g. '20px'. - * In this case set the value to 'tile'. - */ - currentValueForToggle = ! [ 'cover', 'contain', 'auto' ].includes( - currentValueForToggle - ) - ? 'auto' - : currentValueForToggle; - /* - * If the current value is `cover` and the repeat value is `undefined`, then - * the toggle should be unchecked as the default state. Otherwise, the toggle - * should reflect the current repeat value. - */ - const repeatCheckedValue = ! ( - repeatValue === 'no-repeat' || - ( currentValueForToggle === 'cover' && repeatValue === undefined ) - ); - - const updateBackgroundSize = ( next ) => { - // When switching to 'contain' toggle the repeat off. - let nextRepeat = repeatValue; - let nextPosition = positionValue; - - if ( next === 'contain' ) { - nextRepeat = 'no-repeat'; - nextPosition = undefined; - } - - if ( next === 'cover' ) { - nextRepeat = undefined; - nextPosition = undefined; - } - - if ( - ( currentValueForToggle === 'cover' || - currentValueForToggle === 'contain' ) && - next === 'auto' - ) { - nextRepeat = undefined; - /* - * A background image uploaded and set in the editor (an image with a record id), - * receives a default background position of '50% 0', - * when the toggle switches to "Tile". This is to increase the chance that - * the image's focus point is visible. - * This is in-editor only to assist with the user experience. - */ - if ( !! style?.background?.backgroundImage?.id ) { - nextPosition = '50% 0'; - } - } - - /* - * Next will be null when the input is cleared, - * in which case the value should be 'auto'. - */ - if ( ! next && currentValueForToggle === 'auto' ) { - next = 'auto'; - } - - onChange( - setImmutably( style, [ 'background' ], { - ...style?.background, - backgroundPosition: nextPosition, - backgroundRepeat: nextRepeat, - backgroundSize: next, - } ) - ); - }; - - const updateBackgroundPosition = ( next ) => { - onChange( - setImmutably( - style, - [ 'background', 'backgroundPosition' ], - coordsToBackgroundPosition( next ) - ) - ); - }; - - const toggleIsRepeated = () => - onChange( - setImmutably( - style, - [ 'background', 'backgroundRepeat' ], - repeatCheckedValue === true ? 'no-repeat' : 'repeat' - ) - ); - - const toggleScrollWithPage = () => - onChange( - setImmutably( - style, - [ 'background', 'backgroundAttachment' ], - attachmentValue === 'fixed' ? 'scroll' : 'fixed' - ) - ); - - // Set a default background position for non-site-wide, uploaded images with a size of 'contain'. - const backgroundPositionValue = - ! positionValue && isUploadedImage && 'contain' === sizeValue - ? defaultValues?.backgroundPosition - : positionValue; - - return ( - <VStack spacing={ 3 } className="single-column"> - <FocalPointPicker - __nextHasNoMarginBottom - label={ __( 'Focal point' ) } - url={ imageValue } - value={ backgroundPositionToCoords( backgroundPositionValue ) } - onChange={ updateBackgroundPosition } - /> - <ToggleControl - __nextHasNoMarginBottom - label={ __( 'Fixed background' ) } - checked={ attachmentValue === 'fixed' } - onChange={ toggleScrollWithPage } - /> - <ToggleGroupControl - __nextHasNoMarginBottom - size="__unstable-large" - label={ __( 'Size' ) } - value={ currentValueForToggle } - onChange={ updateBackgroundSize } - isBlock - help={ backgroundSizeHelpText( - sizeValue || defaultValues?.backgroundSize - ) } - > - <ToggleGroupControlOption - key="cover" - value="cover" - label={ _x( - 'Cover', - 'Size option for background image control' - ) } - /> - <ToggleGroupControlOption - key="contain" - value="contain" - label={ _x( - 'Contain', - 'Size option for background image control' - ) } - /> - <ToggleGroupControlOption - key="tile" - value="auto" - label={ _x( - 'Tile', - 'Size option for background image control' - ) } - /> - </ToggleGroupControl> - <HStack justify="flex-start" spacing={ 2 } as="span"> - <UnitControl - aria-label={ __( 'Background image width' ) } - onChange={ updateBackgroundSize } - value={ sizeValue } - size="__unstable-large" - __unstableInputWidth="100px" - min={ 0 } - placeholder={ __( 'Auto' ) } - disabled={ - currentValueForToggle !== 'auto' || - currentValueForToggle === undefined - } - /> - <ToggleControl - __nextHasNoMarginBottom - label={ __( 'Repeat' ) } - checked={ repeatCheckedValue } - onChange={ toggleIsRepeated } - disabled={ currentValueForToggle === 'cover' } - /> - </HStack> - </VStack> - ); -} - function BackgroundToolsPanel( { resetAllFilter, onChange, @@ -697,54 +87,20 @@ function BackgroundToolsPanel( { ); } -export default function BackgroundPanel( { +export default function BackgroundImagePanel( { as: Wrapper = BackgroundToolsPanel, value, onChange, - inheritedValue = value, + inheritedValue, settings, panelId, defaultControls = DEFAULT_CONTROLS, defaultValues = {}, headerLabel = __( 'Background image' ), } ) { - /* - * Resolve any inherited "ref" pointers. - * Should the block editor need resolved, inherited values - * across all controls, this could be abstracted into a hook, - * e.g., useResolveGlobalStyle - */ - const { globalStyles, _links } = useSelect( ( select ) => { - const { getSettings } = select( blockEditorStore ); - const _settings = getSettings(); - return { - globalStyles: _settings[ globalStylesDataKey ], - _links: _settings[ globalStylesLinksDataKey ], - }; - }, [] ); - const resolvedInheritedValue = useMemo( () => { - const resolvedValues = { - background: {}, - }; - - if ( ! inheritedValue?.background ) { - return inheritedValue; - } - - Object.entries( inheritedValue?.background ).forEach( - ( [ key, backgroundValue ] ) => { - resolvedValues.background[ key ] = getResolvedValue( - backgroundValue, - { - styles: globalStyles, - _links, - } - ); - } - ); - return resolvedValues; - }, [ globalStyles, _links, inheritedValue ] ); - + const showBackgroundImageControl = useHasBackgroundPanel( settings ); + const resetBackground = () => + onChange( setImmutably( value, [ 'background' ], {} ) ); const resetAllFilter = useCallback( ( previousValue ) => { return { ...previousValue, @@ -752,29 +108,6 @@ export default function BackgroundPanel( { }; }, [] ); - const resetBackground = () => - onChange( setImmutably( value, [ 'background' ], {} ) ); - - const { title, url } = value?.background?.backgroundImage || { - ...resolvedInheritedValue?.background?.backgroundImage, - }; - const hasImageValue = - hasBackgroundImageValue( value ) || - hasBackgroundImageValue( resolvedInheritedValue ); - - const imageValue = - value?.background?.backgroundImage || - inheritedValue?.background?.backgroundImage; - - const shouldShowBackgroundImageControls = - hasImageValue && - 'none' !== imageValue && - ( settings?.background?.backgroundSize || - settings?.background?.backgroundPosition || - settings?.background?.backgroundRepeat ); - - const [ isDropDownOpen, setIsDropDownOpen ] = useState( false ); - return ( <Wrapper resetAllFilter={ resetAllFilter } @@ -783,14 +116,7 @@ export default function BackgroundPanel( { panelId={ panelId } headerLabel={ headerLabel } > - <div - className={ clsx( - 'block-editor-global-styles-background-panel__inspector-media-replace-container', - { - 'is-open': isDropDownOpen, - } - ) } - > + { showBackgroundImageControl && ( <ToolsPanelItem hasValue={ () => !! value?.background } label={ __( 'Image' ) } @@ -798,53 +124,16 @@ export default function BackgroundPanel( { isShownByDefault={ defaultControls.backgroundImage } panelId={ panelId } > - { shouldShowBackgroundImageControls ? ( - <BackgroundControlsPanel - label={ title } - filename={ title } - url={ url } - onToggle={ setIsDropDownOpen } - hasImageValue={ hasImageValue } - > - <VStack spacing={ 3 } className="single-column"> - <BackgroundImageControls - onChange={ onChange } - style={ value } - inheritedValue={ resolvedInheritedValue } - displayInPanel - onResetImage={ () => { - setIsDropDownOpen( false ); - resetBackground(); - } } - onRemoveImage={ () => - setIsDropDownOpen( false ) - } - defaultValues={ defaultValues } - /> - <BackgroundSizeControls - onChange={ onChange } - panelId={ panelId } - style={ value } - defaultValues={ defaultValues } - inheritedValue={ resolvedInheritedValue } - /> - </VStack> - </BackgroundControlsPanel> - ) : ( - <BackgroundImageControls - onChange={ onChange } - style={ value } - inheritedValue={ resolvedInheritedValue } - defaultValues={ defaultValues } - onResetImage={ () => { - setIsDropDownOpen( false ); - resetBackground(); - } } - onRemoveImage={ () => setIsDropDownOpen( false ) } - /> - ) } + <BackgroundImageControl + value={ value } + onChange={ onChange } + settings={ settings } + inheritedValue={ inheritedValue } + defaultControls={ defaultControls } + defaultValues={ defaultValues } + /> </ToolsPanelItem> - </div> + ) } </Wrapper> ); } diff --git a/packages/block-editor/src/components/global-styles/style.scss b/packages/block-editor/src/components/global-styles/style.scss index 1cebbfe7a85d4d..3ba4f81d09daf4 100644 --- a/packages/block-editor/src/components/global-styles/style.scss +++ b/packages/block-editor/src/components/global-styles/style.scss @@ -70,171 +70,3 @@ /*rtl:ignore*/ direction: ltr; } - - -.block-editor-global-styles-background-panel__inspector-media-replace-container { - border: $border-width solid $gray-300; - border-radius: $radius-small; - // Full width. ToolsPanel lays out children in a grid. - grid-column: 1 / -1; - - &.is-open { - background-color: $gray-100; - } - - .block-editor-global-styles-background-panel__image-tools-panel-item { - flex-grow: 1; - border: 0; - .components-dropdown { - display: block; - } - } - - .block-editor-global-styles-background-panel__inspector-preview-inner { - height: 100%; - } - - .components-dropdown { - display: block; - height: 36px; - } -} - -.block-editor-global-styles-background-panel__image-tools-panel-item { - border: $border-width solid $gray-300; - - // Full width. ToolsPanel lays out children in a grid. - grid-column: 1 / -1; - - // Ensure the dropzone is positioned to the size of the item. - position: relative; - - // Since there is no option to skip rendering the drag'n'drop icon in drop - // zone, we hide it for now. - .components-drop-zone__content-icon { - display: none; - } - - .components-dropdown { - display: block; - height: 36px; - } - - button.components-button { - color: $gray-900; - width: 100%; - display: block; - - &:hover { - color: var(--wp-admin-theme-color); - } - - &:focus { - box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - } - } - - .block-editor-global-styles-background-panel__loading { - height: 100%; - position: absolute; - z-index: 1; - width: 100%; - padding: 10px 0 0 0; - svg { - margin: 0; - } - } -} - -.block-editor-global-styles-background-panel__image-preview-content, -.block-editor-global-styles-background-panel__dropdown-toggle { - height: 100%; - width: 100%; - padding-left: $grid-unit-15; -} - -.block-editor-global-styles-background-panel__dropdown-toggle { - cursor: pointer; - background: transparent; - border: none; -} - -.block-editor-global-styles-background-panel__inspector-media-replace-title { - word-break: break-all; - // The Button component is white-space: nowrap, and that won't work with line-clamp. - white-space: normal; - - // Without this, the ellipsis can sometimes be partially hidden by the Button padding. - text-align: start; - text-align-last: center; -} - -.block-editor-global-styles-background-panel__inspector-preview-inner { - .block-editor-global-styles-background-panel__inspector-image-indicator-wrapper { - width: 20px; - height: 20px; - min-width: auto; - } -} - -.block-editor-global-styles-background-panel__inspector-image-indicator { - background-size: cover; - border-radius: $radius-round; - width: 20px; - height: 20px; - display: block; - position: relative; -} - -.block-editor-global-styles-background-panel__inspector-image-indicator::after { - content: ""; - position: absolute; - top: -1px; - left: -1px; - bottom: -1px; - right: -1px; - border-radius: $radius-round; - box-shadow: inset 0 0 0 $border-width rgba(0, 0, 0, 0.2); - // Show a thin outline in Windows high contrast mode, otherwise the button is invisible. - border: 1px solid transparent; - box-sizing: inherit; -} - -.block-editor-global-styles-background-panel__dropdown-content-wrapper { - min-width: 260px; - overflow-x: hidden; - - .components-focal-point-picker-wrapper { - background-color: $gray-100; - width: 100%; - border-radius: $radius-small; - border: $border-width solid $gray-300; - } - - .components-focal-point-picker__media--image { - max-height: 180px; - } - - // Override focal picker to avoid a double border. - .components-focal-point-picker::after { - content: none; - } -} - -// Push control panel into the background when the media modal is open. -.modal-open .block-editor-global-styles-background-panel__popover { - z-index: z-index(".block-editor-global-styles-background-panel__popover"); -} - -.block-editor-global-styles-background-panel__media-replace-popover { - .components-popover__content { - // width of block-editor-global-styles-background-panel__dropdown-content-wrapper minus padding. - width: 226px; - } - .components-button { - padding: 0 $grid-unit-10; - } - .components-button .components-menu-items__item-icon.has-icon-right { - margin-left: $grid-unit-30 - $grid-unit-10; - } -} diff --git a/packages/block-editor/src/components/global-styles/test/background-panel.js b/packages/block-editor/src/components/global-styles/test/background-panel.js index d0b3a8ad601700..ad2c55e747f705 100644 --- a/packages/block-editor/src/components/global-styles/test/background-panel.js +++ b/packages/block-editor/src/components/global-styles/test/background-panel.js @@ -2,53 +2,7 @@ * Internal dependencies */ -import { - backgroundPositionToCoords, - coordsToBackgroundPosition, - hasBackgroundImageValue, -} from '../background-panel'; - -describe( 'backgroundPositionToCoords', () => { - it( 'should return the correct coordinates for a percentage value using 2-value syntax', () => { - expect( backgroundPositionToCoords( '25% 75%' ) ).toEqual( { - x: 0.25, - y: 0.75, - } ); - } ); - - it( 'should return the correct coordinates for a percentage using 1-value syntax', () => { - expect( backgroundPositionToCoords( '50%' ) ).toEqual( { - x: 0.5, - y: 0.5, - } ); - } ); - - it( 'should return undefined coords in given an empty value', () => { - expect( backgroundPositionToCoords( '' ) ).toEqual( { - x: undefined, - y: undefined, - } ); - } ); - - it( 'should return undefined coords in given a string that cannot be converted', () => { - expect( backgroundPositionToCoords( 'apples' ) ).toEqual( { - x: undefined, - y: undefined, - } ); - } ); -} ); - -describe( 'coordsToBackgroundPosition', () => { - it( 'should return the correct background position for a set of coordinates', () => { - expect( coordsToBackgroundPosition( { x: 0.25, y: 0.75 } ) ).toBe( - '25% 75%' - ); - } ); - - it( 'should return undefined if no coordinates are provided', () => { - expect( coordsToBackgroundPosition( {} ) ).toBeUndefined(); - } ); -} ); +import { hasBackgroundImageValue } from '../background-panel'; describe( 'hasBackgroundImageValue', () => { it( 'should return `true` when id and url exist', () => { diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index feaabbbda94426..e6ec77b55a0ec5 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -1,4 +1,5 @@ @import "./autocompleters/style.scss"; +@import "./components/background-image-control/style.scss"; @import "./components/block-alignment-control/style.scss"; @import "./components/block-canvas/style.scss"; @import "./components/block-icon/style.scss"; diff --git a/packages/edit-site/src/components/global-styles/root-menu.js b/packages/edit-site/src/components/global-styles/root-menu.js index 6db4621299f1e2..183686bb52d825 100644 --- a/packages/edit-site/src/components/global-styles/root-menu.js +++ b/packages/edit-site/src/components/global-styles/root-menu.js @@ -3,6 +3,7 @@ */ import { __experimentalItemGroup as ItemGroup } from '@wordpress/components'; import { + background, typography, color, layout, @@ -23,11 +24,17 @@ const { useHasColorPanel, useGlobalSetting, useSettingsForBlockElement, + useHasBackgroundPanel, } = unlock( blockEditorPrivateApis ); function RootMenu() { const [ rawSettings ] = useGlobalSetting( '' ); const settings = useSettingsForBlockElement( rawSettings ); + /* + * Use the raw settings to determine if the background panel should be displayed, + * as the background panel is not dependent on the block element settings. + */ + const hasBackgroundPanel = useHasBackgroundPanel( rawSettings ); const hasTypographyPanel = useHasTypographyPanel( settings ); const hasColorPanel = useHasColorPanel( settings ); const hasShadowPanel = true; // useHasShadowPanel( settings ); @@ -55,6 +62,15 @@ function RootMenu() { { __( 'Colors' ) } </NavigationButtonAsItem> ) } + { hasBackgroundPanel && ( + <NavigationButtonAsItem + icon={ background } + path="/background" + aria-label={ __( 'Background styles' ) } + > + { __( 'Background' ) } + </NavigationButtonAsItem> + ) } { hasShadowPanel && ( <NavigationButtonAsItem icon={ shadowIcon } diff --git a/packages/edit-site/src/components/global-styles/screen-background.js b/packages/edit-site/src/components/global-styles/screen-background.js new file mode 100644 index 00000000000000..df6492ba892976 --- /dev/null +++ b/packages/edit-site/src/components/global-styles/screen-background.js @@ -0,0 +1,37 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; +import { __experimentalText as Text } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import BackgroundPanel from './background-panel'; +import ScreenHeader from './header'; +import { unlock } from '../../lock-unlock'; + +const { useHasBackgroundPanel, useGlobalSetting } = unlock( + blockEditorPrivateApis +); + +function ScreenBackground() { + const [ settings ] = useGlobalSetting( '' ); + const hasBackgroundPanel = useHasBackgroundPanel( settings ); + return ( + <> + <ScreenHeader + title={ __( 'Background' ) } + description={ + <Text> + { __( 'Set styles for the site’s background.' ) } + </Text> + } + /> + { hasBackgroundPanel && <BackgroundPanel /> } + </> + ); +} + +export default ScreenBackground; diff --git a/packages/edit-site/src/components/global-styles/screen-layout.js b/packages/edit-site/src/components/global-styles/screen-layout.js index 1e68309fe01866..b6fa9f18f18dee 100644 --- a/packages/edit-site/src/components/global-styles/screen-layout.js +++ b/packages/edit-site/src/components/global-styles/screen-layout.js @@ -8,31 +8,21 @@ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; * Internal dependencies */ import DimensionsPanel from './dimensions-panel'; -import BackgroundPanel from './background-panel'; import ScreenHeader from './header'; import { unlock } from '../../lock-unlock'; -const { - useHasBackgroundPanel, - useHasDimensionsPanel, - useGlobalSetting, - useSettingsForBlockElement, -} = unlock( blockEditorPrivateApis ); +const { useHasDimensionsPanel, useGlobalSetting, useSettingsForBlockElement } = + unlock( blockEditorPrivateApis ); function ScreenLayout() { const [ rawSettings ] = useGlobalSetting( '' ); const settings = useSettingsForBlockElement( rawSettings ); const hasDimensionsPanel = useHasDimensionsPanel( settings ); - /* - * Use the raw settings to determine if the background panel should be displayed, - * as the background panel is not dependent on the block element settings. - */ - const hasBackgroundPanel = useHasBackgroundPanel( rawSettings ); + return ( <> <ScreenHeader title={ __( 'Layout' ) } /> { hasDimensionsPanel && <DimensionsPanel /> } - { hasBackgroundPanel && <BackgroundPanel /> } </> ); } diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index 54bd4f97390a8f..60d7e314d7776a 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -38,6 +38,7 @@ import FontSize from './font-sizes/font-size'; import FontSizes from './font-sizes/font-sizes'; import ScreenColors from './screen-colors'; import ScreenColorPalette from './screen-color-palette'; +import ScreenBackground from './screen-background'; import { ScreenShadows, ScreenShadowsEdit } from './screen-shadows'; import ScreenLayout from './screen-layout'; import ScreenStyleVariations from './screen-style-variations'; @@ -372,6 +373,10 @@ function GlobalStylesUI() { <ScreenRevisions /> </GlobalStylesNavigationScreen> + <GlobalStylesNavigationScreen path="/background"> + <ScreenBackground /> + </GlobalStylesNavigationScreen> + { blocks.map( ( block ) => ( <GlobalStylesNavigationScreen key={ 'menu-block-' + block.name } diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index d60ca5a74eb5bd..e9b48331365135 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -16,6 +16,7 @@ export { default as arrowUp } from './library/arrow-up'; export { default as atSymbol } from './library/at-symbol'; export { default as aspectRatio } from './library/aspect-ratio'; export { default as audio } from './library/audio'; +export { default as background } from './library/background'; export { default as backup } from './library/backup'; export { default as blockDefault } from './library/block-default'; export { default as blockMeta } from './library/block-meta'; diff --git a/packages/icons/src/library/background.js b/packages/icons/src/library/background.js new file mode 100644 index 00000000000000..173b609354380d --- /dev/null +++ b/packages/icons/src/library/background.js @@ -0,0 +1,16 @@ +/** + * WordPress dependencies + */ +import { Path, SVG } from '@wordpress/primitives'; + +const background = ( + <SVG width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"> + <Path + fillRule="evenodd" + clipRule="evenodd" + d="M11.53 4.47a.75.75 0 1 0-1.06 1.06l8 8a.75.75 0 1 0 1.06-1.06l-8-8Zm5 1a.75.75 0 1 0-1.06 1.06l2 2a.75.75 0 1 0 1.06-1.06l-2-2Zm-11.06 10a.75.75 0 0 1 1.06 0l2 2a.75.75 0 1 1-1.06 1.06l-2-2a.75.75 0 0 1 0-1.06Zm.06-5a.75.75 0 0 0-1.06 1.06l8 8a.75.75 0 1 0 1.06-1.06l-8-8Zm-.06-3a.75.75 0 0 1 1.06 0l10 10a.75.75 0 1 1-1.06 1.06l-10-10a.75.75 0 0 1 0-1.06Zm3.06-2a.75.75 0 0 0-1.06 1.06l10 10a.75.75 0 1 0 1.06-1.06l-10-10Z" + /> + </SVG> +); + +export default background; From 45d33f076ee64737b67cea84f2c405cc194b2543 Mon Sep 17 00:00:00 2001 From: Carolina Nymark <myazalea@hotmail.com> Date: Mon, 16 Sep 2024 04:57:28 +0200 Subject: [PATCH 0804/1908] Query loop / Post template: Enable post format filter (#64167) Enables filtering the query loop result by post format. To allow querying a given post format, a new parameter, `format` is added to a new compatibility class called `Gutenberg_REST_Posts_Controller_6_7`, which extends the core class `WP_REST_Posts_Controller`. Query loop block: - Adds a new parameter, `format`, to the `query` attribute in block.json. - Adds a new `FormatControls` that uses a list of supported post formats inside a `FormTokenField`. This control is placed in the `Filters` panel in the block settings sidebar. - Adds a new utility function `gutenberg_add_format_query_vars_to_query_loop_block` to ensure that the Query loop block can pass the new `format` argument correctly to `WP_Query`. This function is hooked into `query_loop_block_query_vars`. Post Template block: The new `format` parameter is passed from the query loop block to the post template block as part of the `query` attribute. --------- Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: dmsnell <dmsnell@git.wordpress.org> Co-authored-by: TimothyBJacobs <timothyblynjacobs@git.wordpress.org> Co-authored-by: nickbohle <nickbohle@git.wordpress.org> Co-authored-by: SergeyBiryukov <sergeybiryukov@git.wordpress.org> Co-authored-by: justintadlock <greenshady@git.wordpress.org> --- backport-changelog/6.7/7314.md | 3 + lib/compat/wordpress-6.7/blocks.php | 60 ++ ...ss-gutenberg-rest-posts-controller-6-7.php | 698 ++++++++++++++++++ lib/compat/wordpress-6.7/post-formats.php | 24 + lib/load.php | 2 + .../block-library/src/post-template/edit.js | 6 + packages/block-library/src/query/block.json | 3 +- .../inspector-controls/format-controls.js | 90 +++ .../query/edit/inspector-controls/index.js | 57 +- packages/block-library/src/query/utils.js | 17 +- .../fixtures/blocks/core__query.json | 3 +- 11 files changed, 958 insertions(+), 5 deletions(-) create mode 100644 backport-changelog/6.7/7314.md create mode 100644 lib/compat/wordpress-6.7/class-gutenberg-rest-posts-controller-6-7.php create mode 100644 lib/compat/wordpress-6.7/post-formats.php create mode 100644 packages/block-library/src/query/edit/inspector-controls/format-controls.js diff --git a/backport-changelog/6.7/7314.md b/backport-changelog/6.7/7314.md new file mode 100644 index 00000000000000..7d75cdff0f9075 --- /dev/null +++ b/backport-changelog/6.7/7314.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7314 + +* https://github.com/WordPress/gutenberg/pull/64167 diff --git a/lib/compat/wordpress-6.7/blocks.php b/lib/compat/wordpress-6.7/blocks.php index 18d21621be7197..6b9526f8056fd3 100644 --- a/lib/compat/wordpress-6.7/blocks.php +++ b/lib/compat/wordpress-6.7/blocks.php @@ -43,3 +43,63 @@ function gutenberg_filter_block_type_metadata_settings_allow_variations_php_file return $settings; } add_filter( 'block_type_metadata_settings', 'gutenberg_filter_block_type_metadata_settings_allow_variations_php_file', 10, 2 ); + +/** + * Adds post format query vars to the query loop block's WP_Query when the block's attributes call for them. + * + * @see 'query_loop_block_query_vars' + * + * @param array $query The query vars. + * @param WP_Block $block Block instance. + * @return array The filtered query vars. + */ +function gutenberg_add_format_query_vars_to_query_loop_block( $query, $block ) { + // Return early if there is no format or if the format is not an array. + if ( empty( $block->context['query']['format'] ) || ! is_array( $block->context['query']['format'] ) ) { + return $query; + } + + $formats = $block->context['query']['format']; + $tax_query = array( 'relation' => 'OR' ); + + // The default post format, 'standard', is not stored in the database. + // If 'standard' is part of the request, the query needs to exclude all post items that + // have a format assigned. + if ( in_array( 'standard', $formats, true ) ) { + $tax_query[] = array( + 'taxonomy' => 'post_format', + 'field' => 'slug', + 'terms' => array(), + 'operator' => 'NOT EXISTS', + ); + // Remove the standard format, since it cannot be queried. + unset( $formats[ array_search( 'standard', $formats, true ) ] ); + } + + // Add any remaining formats to the tax query. + if ( ! empty( $formats ) ) { + // Add the post-format- prefix. + $terms = array_map( + static function ( $format ) { + return 'post-format-' . $format; + }, + $formats + ); + + $tax_query[] = array( + 'taxonomy' => 'post_format', + 'field' => 'slug', + 'terms' => $terms, + 'operator' => 'IN', + ); + } + + // This condition is intended to prevent $tax_query from being added to $query + // if it only contains the relation. + if ( count( $tax_query ) > 1 ) { + $query['tax_query'][] = $tax_query; + } + + return $query; +} +add_filter( 'query_loop_block_query_vars', 'gutenberg_add_format_query_vars_to_query_loop_block', 10, 2 ); diff --git a/lib/compat/wordpress-6.7/class-gutenberg-rest-posts-controller-6-7.php b/lib/compat/wordpress-6.7/class-gutenberg-rest-posts-controller-6-7.php new file mode 100644 index 00000000000000..c7de4371c94f56 --- /dev/null +++ b/lib/compat/wordpress-6.7/class-gutenberg-rest-posts-controller-6-7.php @@ -0,0 +1,698 @@ +<?php +/** + * REST API: Gutenberg_REST_Posts_Controller_6_7 class + * + * @package WordPress + * @subpackage REST_API + * @since 6.7.0 + */ + +/** + * Extend the core WP_REST_Posts_Controller class to add support for post formats. + * + * @see WP_REST_Controller + */ +class Gutenberg_REST_Posts_Controller_6_7 extends WP_REST_Posts_Controller { + /** + * Post type. + * + * @since 4.7.0 + * @var string + */ + protected $post_type; + + /** + * Retrieves a collection of posts. + * + * @since 4.7.0 + * @since 6.7.0 Added support for the `format` query parameter. + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items( $request ) { + // Ensure a search string is set in case the orderby is set to 'relevance'. + if ( ! empty( $request['orderby'] ) && 'relevance' === $request['orderby'] && empty( $request['search'] ) ) { + return new WP_Error( + 'rest_no_search_term_defined', + __( 'You need to define a search term to order by relevance.' ), + array( 'status' => 400 ) + ); + } + + // Ensure an include parameter is set in case the orderby is set to 'include'. + if ( ! empty( $request['orderby'] ) && 'include' === $request['orderby'] && empty( $request['include'] ) ) { + return new WP_Error( + 'rest_orderby_include_missing_include', + __( 'You need to define an include parameter to order by include.' ), + array( 'status' => 400 ) + ); + } + + // Retrieve the list of registered collection query parameters. + $registered = $this->get_collection_params(); + $args = array(); + + /* + * This array defines mappings between public API query parameters whose + * values are accepted as-passed, and their internal WP_Query parameter + * name equivalents (some are the same). Only values which are also + * present in $registered will be set. + */ + $parameter_mappings = array( + 'author' => 'author__in', + 'author_exclude' => 'author__not_in', + 'exclude' => 'post__not_in', + 'include' => 'post__in', + 'menu_order' => 'menu_order', + 'offset' => 'offset', + 'order' => 'order', + 'orderby' => 'orderby', + 'page' => 'paged', + 'parent' => 'post_parent__in', + 'parent_exclude' => 'post_parent__not_in', + 'search' => 's', + 'search_columns' => 'search_columns', + 'slug' => 'post_name__in', + 'status' => 'post_status', + ); + + /* + * For each known parameter which is both registered and present in the request, + * set the parameter's value on the query $args. + */ + foreach ( $parameter_mappings as $api_param => $wp_param ) { + if ( isset( $registered[ $api_param ], $request[ $api_param ] ) ) { + $args[ $wp_param ] = $request[ $api_param ]; + } + } + + // Check for & assign any parameters which require special handling or setting. + $args['date_query'] = array(); + + if ( isset( $registered['before'], $request['before'] ) ) { + $args['date_query'][] = array( + 'before' => $request['before'], + 'column' => 'post_date', + ); + } + + if ( isset( $registered['modified_before'], $request['modified_before'] ) ) { + $args['date_query'][] = array( + 'before' => $request['modified_before'], + 'column' => 'post_modified', + ); + } + + if ( isset( $registered['after'], $request['after'] ) ) { + $args['date_query'][] = array( + 'after' => $request['after'], + 'column' => 'post_date', + ); + } + + if ( isset( $registered['modified_after'], $request['modified_after'] ) ) { + $args['date_query'][] = array( + 'after' => $request['modified_after'], + 'column' => 'post_modified', + ); + } + + // Ensure our per_page parameter overrides any provided posts_per_page filter. + if ( isset( $registered['per_page'] ) ) { + $args['posts_per_page'] = $request['per_page']; + } + + if ( isset( $registered['sticky'], $request['sticky'] ) ) { + $sticky_posts = get_option( 'sticky_posts', array() ); + if ( ! is_array( $sticky_posts ) ) { + $sticky_posts = array(); + } + if ( $request['sticky'] ) { + /* + * As post__in will be used to only get sticky posts, + * we have to support the case where post__in was already + * specified. + */ + $args['post__in'] = $args['post__in'] ? array_intersect( $sticky_posts, $args['post__in'] ) : $sticky_posts; + + /* + * If we intersected, but there are no post IDs in common, + * WP_Query won't return "no posts" for post__in = array() + * so we have to fake it a bit. + */ + if ( ! $args['post__in'] ) { + $args['post__in'] = array( 0 ); + } + } elseif ( $sticky_posts ) { + /* + * As post___not_in will be used to only get posts that + * are not sticky, we have to support the case where post__not_in + * was already specified. + */ + $args['post__not_in'] = array_merge( $args['post__not_in'], $sticky_posts ); + } + } + + $args = $this->prepare_tax_query( $args, $request ); + + if ( ! empty( $request['format'] ) ) { + $formats = $request['format']; + $tax_query = array( 'relation' => 'OR' ); + + // The default post format, 'standard', is not stored in the database. + // If 'standard' is part of the request, the query needs to exclude all post items that + // have a format assigned. + if ( in_array( 'standard', $formats, true ) ) { + $tax_query[] = array( + 'taxonomy' => 'post_format', + 'field' => 'slug', + 'terms' => array(), + 'operator' => 'NOT EXISTS', + ); + // Remove the standard format, since it cannot be queried. + unset( $formats[ array_search( 'standard', $formats, true ) ] ); + } + + // Add any remaining formats to the tax query. + if ( ! empty( $formats ) ) { + // Add the post-format- prefix. + $terms = array_map( + static function ( $format ) { + return 'post-format-' . $format; + }, + $formats + ); + + $tax_query[] = array( + 'taxonomy' => 'post_format', + 'field' => 'slug', + 'terms' => $terms, + 'operator' => 'IN', + ); + } + + // Enable filtering by both post formats and other taxonomies by combining them with AND. + if ( isset( $args['tax_query'] ) ) { + $args['tax_query'][] = array( + 'relation' => 'AND', + $tax_query, + ); + } else { + $args['tax_query'] = $tax_query; + } + } + + // Force the post_type argument, since it's not a user input variable. + $args['post_type'] = $this->post_type; + + /** + * Filters WP_Query arguments when querying posts via the REST API. + * + * The dynamic portion of the hook name, `$this->post_type`, refers to the post type slug. + * + * Possible hook names include: + * + * - `rest_post_query` + * - `rest_page_query` + * - `rest_attachment_query` + * + * Enables adding extra arguments or setting defaults for a post collection request. + * + * @since 4.7.0 + * @since 5.7.0 Moved after the `tax_query` query arg is generated. + * + * @link https://developer.wordpress.org/reference/classes/wp_query/ + * + * @param array $args Array of arguments for WP_Query. + * @param WP_REST_Request $request The REST API request. + */ + $args = apply_filters( "rest_{$this->post_type}_query", $args, $request ); + $query_args = $this->prepare_items_query( $args, $request ); + + $posts_query = new WP_Query(); + $query_result = $posts_query->query( $query_args ); + + // Allow access to all password protected posts if the context is edit. + if ( 'edit' === $request['context'] ) { + add_filter( 'post_password_required', array( $this, 'check_password_required' ), 10, 2 ); + } + + $posts = array(); + + update_post_author_caches( $query_result ); + update_post_parent_caches( $query_result ); + + if ( post_type_supports( $this->post_type, 'thumbnail' ) ) { + update_post_thumbnail_cache( $posts_query ); + } + + foreach ( $query_result as $post ) { + if ( ! $this->check_read_permission( $post ) ) { + continue; + } + + $data = $this->prepare_item_for_response( $post, $request ); + $posts[] = $this->prepare_response_for_collection( $data ); + } + + // Reset filter. + if ( 'edit' === $request['context'] ) { + remove_filter( 'post_password_required', array( $this, 'check_password_required' ) ); + } + + $page = (int) $query_args['paged']; + $total_posts = $posts_query->found_posts; + + if ( $total_posts < 1 && $page > 1 ) { + // Out-of-bounds, run the query again without LIMIT for total count. + unset( $query_args['paged'] ); + + $count_query = new WP_Query(); + $count_query->query( $query_args ); + $total_posts = $count_query->found_posts; + } + + $max_pages = (int) ceil( $total_posts / (int) $posts_query->query_vars['posts_per_page'] ); + + if ( $page > $max_pages && $total_posts > 0 ) { + return new WP_Error( + 'rest_post_invalid_page_number', + __( 'The page number requested is larger than the number of pages available.' ), + array( 'status' => 400 ) + ); + } + + $response = rest_ensure_response( $posts ); + + $response->header( 'X-WP-Total', (int) $total_posts ); + $response->header( 'X-WP-TotalPages', (int) $max_pages ); + + $request_params = $request->get_query_params(); + $collection_url = rest_url( rest_get_route_for_post_type_items( $this->post_type ) ); + $base = add_query_arg( urlencode_deep( $request_params ), $collection_url ); + + if ( $page > 1 ) { + $prev_page = $page - 1; + + if ( $prev_page > $max_pages ) { + $prev_page = $max_pages; + } + + $prev_link = add_query_arg( 'page', $prev_page, $base ); + $response->link_header( 'prev', $prev_link ); + } + if ( $max_pages > $page ) { + $next_page = $page + 1; + $next_link = add_query_arg( 'page', $next_page, $base ); + + $response->link_header( 'next', $next_link ); + } + + return $response; + } + + /** + * Retrieves the query params for the posts collection. + * + * @since 4.7.0 + * @since 5.4.0 The `tax_relation` query parameter was added. + * @since 5.7.0 The `modified_after` and `modified_before` query parameters were added. + * @since 6.7.0 The `format` query parameter was added. + * + * @return array Collection parameters. + */ + public function get_collection_params() { + $query_params = parent::get_collection_params(); + + $query_params['context']['default'] = 'view'; + + $query_params['after'] = array( + 'description' => __( 'Limit response to posts published after a given ISO8601 compliant date.' ), + 'type' => 'string', + 'format' => 'date-time', + ); + + $query_params['modified_after'] = array( + 'description' => __( 'Limit response to posts modified after a given ISO8601 compliant date.' ), + 'type' => 'string', + 'format' => 'date-time', + ); + + if ( post_type_supports( $this->post_type, 'author' ) ) { + $query_params['author'] = array( + 'description' => __( 'Limit result set to posts assigned to specific authors.' ), + 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), + 'default' => array(), + ); + $query_params['author_exclude'] = array( + 'description' => __( 'Ensure result set excludes posts assigned to specific authors.' ), + 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), + 'default' => array(), + ); + } + + $query_params['before'] = array( + 'description' => __( 'Limit response to posts published before a given ISO8601 compliant date.' ), + 'type' => 'string', + 'format' => 'date-time', + ); + + $query_params['modified_before'] = array( + 'description' => __( 'Limit response to posts modified before a given ISO8601 compliant date.' ), + 'type' => 'string', + 'format' => 'date-time', + ); + + $query_params['exclude'] = array( + 'description' => __( 'Ensure result set excludes specific IDs.' ), + 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), + 'default' => array(), + ); + + $query_params['include'] = array( + 'description' => __( 'Limit result set to specific IDs.' ), + 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), + 'default' => array(), + ); + + if ( 'page' === $this->post_type || post_type_supports( $this->post_type, 'page-attributes' ) ) { + $query_params['menu_order'] = array( + 'description' => __( 'Limit result set to posts with a specific menu_order value.' ), + 'type' => 'integer', + ); + } + + $query_params['offset'] = array( + 'description' => __( 'Offset the result set by a specific number of items.' ), + 'type' => 'integer', + ); + + $query_params['order'] = array( + 'description' => __( 'Order sort attribute ascending or descending.' ), + 'type' => 'string', + 'default' => 'desc', + 'enum' => array( 'asc', 'desc' ), + ); + + $query_params['orderby'] = array( + 'description' => __( 'Sort collection by post attribute.' ), + 'type' => 'string', + 'default' => 'date', + 'enum' => array( + 'author', + 'date', + 'id', + 'include', + 'modified', + 'parent', + 'relevance', + 'slug', + 'include_slugs', + 'title', + ), + ); + + if ( 'page' === $this->post_type || post_type_supports( $this->post_type, 'page-attributes' ) ) { + $query_params['orderby']['enum'][] = 'menu_order'; + } + + $post_type = get_post_type_object( $this->post_type ); + + if ( $post_type->hierarchical || 'attachment' === $this->post_type ) { + $query_params['parent'] = array( + 'description' => __( 'Limit result set to items with particular parent IDs.' ), + 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), + 'default' => array(), + ); + $query_params['parent_exclude'] = array( + 'description' => __( 'Limit result set to all items except those of a particular parent ID.' ), + 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), + 'default' => array(), + ); + } + + $query_params['search_columns'] = array( + 'default' => array(), + 'description' => __( 'Array of column names to be searched.' ), + 'type' => 'array', + 'items' => array( + 'enum' => array( 'post_title', 'post_content', 'post_excerpt' ), + 'type' => 'string', + ), + ); + + $query_params['slug'] = array( + 'description' => __( 'Limit result set to posts with one or more specific slugs.' ), + 'type' => 'array', + 'items' => array( + 'type' => 'string', + ), + ); + + $query_params['status'] = array( + 'default' => 'publish', + 'description' => __( 'Limit result set to posts assigned one or more statuses.' ), + 'type' => 'array', + 'items' => array( + 'enum' => array_merge( array_keys( get_post_stati() ), array( 'any' ) ), + 'type' => 'string', + ), + 'sanitize_callback' => array( $this, 'sanitize_post_statuses' ), + ); + + $query_params = $this->prepare_taxonomy_limit_schema( $query_params ); + + if ( 'post' === $this->post_type ) { + $query_params['sticky'] = array( + 'description' => __( 'Limit result set to items that are sticky.' ), + 'type' => 'boolean', + ); + } + + if ( post_type_supports( $this->post_type, 'post-formats' ) ) { + $query_params['format'] = array( + 'description' => __( 'Limit result set to items assigned one or more given formats.' ), + 'type' => 'array', + 'uniqueItems' => true, + 'items' => array( + 'enum' => array_values( get_post_format_slugs() ), + 'type' => 'string', + ), + ); + } + + /** + * Filters collection parameters for the posts controller. + * + * The dynamic part of the filter `$this->post_type` refers to the post + * type slug for the controller. + * + * This filter registers the collection parameter, but does not map the + * collection parameter to an internal WP_Query parameter. Use the + * `rest_{$this->post_type}_query` filter to set WP_Query parameters. + * + * @since 4.7.0 + * + * @param array $query_params JSON Schema-formatted collection parameters. + * @param WP_Post_Type $post_type Post type object. + */ + return apply_filters( "rest_{$this->post_type}_collection_params", $query_params, $post_type ); + } + + /** + * Prepares the 'tax_query' for a collection of posts. + * + * @since 5.7.0 + * + * @param array $args WP_Query arguments. + * @param WP_REST_Request $request Full details about the request. + * @return array Updated query arguments. + */ + private function prepare_tax_query( array $args, WP_REST_Request $request ) { + $relation = $request['tax_relation']; + + if ( $relation ) { + $args['tax_query'] = array( 'relation' => $relation ); + } + + $taxonomies = wp_list_filter( + get_object_taxonomies( $this->post_type, 'objects' ), + array( 'show_in_rest' => true ) + ); + + foreach ( $taxonomies as $taxonomy ) { + $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; + + $tax_include = $request[ $base ]; + $tax_exclude = $request[ $base . '_exclude' ]; + + if ( $tax_include ) { + $terms = array(); + $include_children = false; + $operator = 'IN'; + + if ( rest_is_array( $tax_include ) ) { + $terms = $tax_include; + } elseif ( rest_is_object( $tax_include ) ) { + $terms = empty( $tax_include['terms'] ) ? array() : $tax_include['terms']; + $include_children = ! empty( $tax_include['include_children'] ); + + if ( isset( $tax_include['operator'] ) && 'AND' === $tax_include['operator'] ) { + $operator = 'AND'; + } + } + + if ( $terms ) { + $args['tax_query'][] = array( + 'taxonomy' => $taxonomy->name, + 'field' => 'term_id', + 'terms' => $terms, + 'include_children' => $include_children, + 'operator' => $operator, + ); + } + } + + if ( $tax_exclude ) { + $terms = array(); + $include_children = false; + + if ( rest_is_array( $tax_exclude ) ) { + $terms = $tax_exclude; + } elseif ( rest_is_object( $tax_exclude ) ) { + $terms = empty( $tax_exclude['terms'] ) ? array() : $tax_exclude['terms']; + $include_children = ! empty( $tax_exclude['include_children'] ); + } + + if ( $terms ) { + $args['tax_query'][] = array( + 'taxonomy' => $taxonomy->name, + 'field' => 'term_id', + 'terms' => $terms, + 'include_children' => $include_children, + 'operator' => 'NOT IN', + ); + } + } + } + + return $args; + } + + /** + * Prepares the collection schema for including and excluding items by terms. + * + * @since 5.7.0 + * + * @param array $query_params Collection schema. + * @return array Updated schema. + */ + private function prepare_taxonomy_limit_schema( array $query_params ) { + $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) ); + + if ( ! $taxonomies ) { + return $query_params; + } + + $query_params['tax_relation'] = array( + 'description' => __( 'Limit result set based on relationship between multiple taxonomies.' ), + 'type' => 'string', + 'enum' => array( 'AND', 'OR' ), + ); + + $limit_schema = array( + 'type' => array( 'object', 'array' ), + 'oneOf' => array( + array( + 'title' => __( 'Term ID List' ), + 'description' => __( 'Match terms with the listed IDs.' ), + 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), + ), + array( + 'title' => __( 'Term ID Taxonomy Query' ), + 'description' => __( 'Perform an advanced term query.' ), + 'type' => 'object', + 'properties' => array( + 'terms' => array( + 'description' => __( 'Term IDs.' ), + 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), + 'default' => array(), + ), + 'include_children' => array( + 'description' => __( 'Whether to include child terms in the terms limiting the result set.' ), + 'type' => 'boolean', + 'default' => false, + ), + ), + 'additionalProperties' => false, + ), + ), + ); + + $include_schema = array_merge( + array( + /* translators: %s: Taxonomy name. */ + 'description' => __( 'Limit result set to items with specific terms assigned in the %s taxonomy.' ), + ), + $limit_schema + ); + // 'operator' is supported only for 'include' queries. + $include_schema['oneOf'][1]['properties']['operator'] = array( + 'description' => __( 'Whether items must be assigned all or any of the specified terms.' ), + 'type' => 'string', + 'enum' => array( 'AND', 'OR' ), + 'default' => 'OR', + ); + + $exclude_schema = array_merge( + array( + /* translators: %s: Taxonomy name. */ + 'description' => __( 'Limit result set to items except those with specific terms assigned in the %s taxonomy.' ), + ), + $limit_schema + ); + + foreach ( $taxonomies as $taxonomy ) { + $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; + $base_exclude = $base . '_exclude'; + + $query_params[ $base ] = $include_schema; + $query_params[ $base ]['description'] = sprintf( $query_params[ $base ]['description'], $base ); + + $query_params[ $base_exclude ] = $exclude_schema; + $query_params[ $base_exclude ]['description'] = sprintf( $query_params[ $base_exclude ]['description'], $base ); + + if ( ! $taxonomy->hierarchical ) { + unset( $query_params[ $base ]['oneOf'][1]['properties']['include_children'] ); + unset( $query_params[ $base_exclude ]['oneOf'][1]['properties']['include_children'] ); + } + } + + return $query_params; + } +} diff --git a/lib/compat/wordpress-6.7/post-formats.php b/lib/compat/wordpress-6.7/post-formats.php new file mode 100644 index 00000000000000..d3de5b83957e29 --- /dev/null +++ b/lib/compat/wordpress-6.7/post-formats.php @@ -0,0 +1,24 @@ +<?php +/** + * Shims for changes to post formats until they are merged in all + * versions of WordPress which Gutenberg supports. + * + * @package gutenberg + */ + +/** + * Registers the extension of the WP_REST_Posts_Controller class, + * to add support for post formats. + */ +function gutenberg_post_format_rest_posts_controller( $args ) { + /** + * This hook runs before support values are available via `post_type_supports`. + * Check registration arguments for REST API controller override. + */ + if ( ! empty( $args['supports'] ) && in_array( 'post-formats', $args['supports'], true ) ) { + $args['rest_controller_class'] = 'Gutenberg_REST_Posts_Controller_6_7'; + } + + return $args; +} +add_filter( 'register_post_type_args', 'gutenberg_post_format_rest_posts_controller', 10 ); diff --git a/lib/load.php b/lib/load.php index 6ac2bd61f1de49..c26160eba2b67d 100644 --- a/lib/load.php +++ b/lib/load.php @@ -41,6 +41,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.6/rest-api.php'; // WordPress 6.7 compat. + require __DIR__ . '/compat/wordpress-6.7/class-gutenberg-rest-posts-controller-6-7.php'; require __DIR__ . '/compat/wordpress-6.7/class-gutenberg-rest-templates-controller-6-7.php'; require __DIR__ . '/compat/wordpress-6.7/class-gutenberg-rest-server.php'; require __DIR__ . '/compat/wordpress-6.7/rest-api.php'; @@ -109,6 +110,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.7/script-modules.php'; require __DIR__ . '/compat/wordpress-6.7/class-wp-block-templates-registry.php'; require __DIR__ . '/compat/wordpress-6.7/compat.php'; +require __DIR__ . '/compat/wordpress-6.7/post-formats.php'; // Experimental features. require __DIR__ . '/experimental/block-editor-settings-mobile.php'; diff --git a/packages/block-library/src/post-template/edit.js b/packages/block-library/src/post-template/edit.js index 70f960a2197430..a9e279ee2c3052 100644 --- a/packages/block-library/src/post-template/edit.js +++ b/packages/block-library/src/post-template/edit.js @@ -90,6 +90,7 @@ export default function PostTemplateEdit( { taxQuery, parents, pages, + format, // We gather extra query args to pass to the REST API call. // This way extenders of Query Loop can add their own query args, // and have accurate previews in the editor. @@ -163,6 +164,10 @@ export default function PostTemplateEdit( { if ( parents?.length ) { query.parent = parents; } + if ( format?.length ) { + query.format = format; + } + // If sticky is not set, it will return all posts in the results. // If sticky is set to `only`, it will limit the results to sticky posts only. // If it is anything else, it will exclude sticky posts from results. For the record the value stored is `exclude`. @@ -205,6 +210,7 @@ export default function PostTemplateEdit( { templateSlug, taxQuery, parents, + format, restQueryArgs, previewPostType, ] diff --git a/packages/block-library/src/query/block.json b/packages/block-library/src/query/block.json index b602032df36005..9eb84959638236 100644 --- a/packages/block-library/src/query/block.json +++ b/packages/block-library/src/query/block.json @@ -25,7 +25,8 @@ "sticky": "", "inherit": true, "taxQuery": null, - "parents": [] + "parents": [], + "format": [] } }, "tagName": { diff --git a/packages/block-library/src/query/edit/inspector-controls/format-controls.js b/packages/block-library/src/query/edit/inspector-controls/format-controls.js new file mode 100644 index 00000000000000..d26fd9d81ce6f7 --- /dev/null +++ b/packages/block-library/src/query/edit/inspector-controls/format-controls.js @@ -0,0 +1,90 @@ +/** + * WordPress dependencies + */ +import { FormTokenField } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { __ } from '@wordpress/i18n'; + +// All WP post formats, sorted alphabetically by translated name. +// Value is the post format slug. Label is the name. +const POST_FORMATS = [ + { value: 'aside', label: __( 'Aside' ) }, + { value: 'audio', label: __( 'Audio' ) }, + { value: 'chat', label: __( 'Chat' ) }, + { value: 'gallery', label: __( 'Gallery' ) }, + { value: 'image', label: __( 'Image' ) }, + { value: 'link', label: __( 'Link' ) }, + { value: 'quote', label: __( 'Quote' ) }, + { value: 'standard', label: __( 'Standard' ) }, + { value: 'status', label: __( 'Status' ) }, + { value: 'video', label: __( 'Video' ) }, +].sort( ( a, b ) => { + const normalizedA = a.label.toUpperCase(); + const normalizedB = b.label.toUpperCase(); + + if ( normalizedA < normalizedB ) { + return -1; + } + if ( normalizedA > normalizedB ) { + return 1; + } + return 0; +} ); + +// A helper function to convert translatable post format names into their static values. +function formatNamesToValues( names, formats ) { + return names + .map( ( name ) => { + return formats.find( + ( item ) => + item.label.toLocaleLowerCase() === name.toLocaleLowerCase() + )?.value; + } ) + .filter( Boolean ); +} + +export default function FormatControls( { onChange, query: { format } } ) { + // 'format' is expected to be an array. If it is not an array, for example + // if a user has manually entered an invalid value in the block markup, + // convert it to an array to prevent JavaScript errors. + const normalizedFormats = Array.isArray( format ) ? format : [ format ]; + + const { supportedFormats } = useSelect( ( select ) => { + const themeSupports = select( coreStore ).getThemeSupports(); + return { + supportedFormats: themeSupports.formats, + }; + }, [] ); + + const formats = POST_FORMATS.filter( ( item ) => + supportedFormats.includes( item.value ) + ); + + const values = normalizedFormats + .map( + ( name ) => formats.find( ( item ) => item.value === name )?.label + ) + .filter( Boolean ); + + const suggestions = formats + .filter( ( item ) => ! format.includes( item.value ) ) + .map( ( item ) => item.label ); + + return ( + <FormTokenField + label={ __( 'Formats' ) } + value={ values } + suggestions={ suggestions } + onChange={ ( newValues ) => { + onChange( { + format: formatNamesToValues( newValues, formats ), + } ); + } } + __experimentalShowHowTo={ false } + __experimentalExpandOnFocus + __nextHasNoMarginBottom + __next40pxDefaultSize + /> + ); +} diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index 010e57b2da4fc6..6c246ab89b3b37 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -12,6 +12,8 @@ import { __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; import { __ } from '@wordpress/i18n'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { debounce } from '@wordpress/compose'; @@ -24,6 +26,7 @@ import OrderControl from './order-control'; import AuthorControl from './author-control'; import ParentControl from './parent-control'; import { TaxonomyControls } from './taxonomy-controls'; +import FormatControls from './format-controls'; import StickyControl from './sticky-control'; import CreateNewPostLink from './create-new-post-link'; import PerPageControl from './per-page-control'; @@ -56,10 +59,15 @@ export default function QueryInspectorControls( props ) { inherit, taxQuery, parents, + format, } = query; const allowedControls = useAllowedControls( attributes ); const [ showSticky, setShowSticky ] = useState( postType === 'post' ); - const { postTypesTaxonomiesMap, postTypesSelectOptions } = usePostTypes(); + const { + postTypesTaxonomiesMap, + postTypesSelectOptions, + postTypeFormatSupportMap, + } = usePostTypes(); const taxonomies = useTaxonomies( postType ); const isPostTypeHierarchical = useIsPostTypeHierarchical( postType ); useEffect( () => { @@ -88,6 +96,13 @@ export default function QueryInspectorControls( props ) { } // We need to reset `parents` because they are tied to each post type. updateQuery.parents = []; + // Post types can register post format support with `add_post_type_support`. + // But we need to reset the `format` property when switching to post types + // that do not support post formats. + const hasFormatSupport = postTypeFormatSupportMap[ newValue ]; + if ( ! hasFormatSupport ) { + updateQuery.format = []; + } setQuery( updateQuery ); }; const [ querySearch, setQuerySearch ] = useState( query.search ); @@ -132,11 +147,36 @@ export default function QueryInspectorControls( props ) { isControlAllowed( allowedControls, 'parents' ) && isPostTypeHierarchical; + const postTypeHasFormatSupport = postTypeFormatSupportMap[ postType ]; + const showFormatControl = useSelect( + ( select ) => { + // Check if the post type supports post formats and if the control is allowed. + if ( + ! postTypeHasFormatSupport || + ! isControlAllowed( allowedControls, 'format' ) + ) { + return false; + } + + const themeSupports = select( coreStore ).getThemeSupports(); + + // If there are no supported formats, getThemeSupports still includes the default 'standard' format, + // and in this case the control should not be shown since the user has no other formats to choose from. + return ( + themeSupports.formats && + themeSupports.formats.length > 0 && + themeSupports.formats.some( ( type ) => type !== 'standard' ) + ); + }, + [ allowedControls, postTypeHasFormatSupport ] + ); + const showFiltersPanel = showTaxControl || showAuthorControl || showSearchControl || - showParentControl; + showParentControl || + showFormatControl; const dropdownMenuProps = useToolsPanelDropdownMenuProps(); const showPostCountControl = isControlAllowed( @@ -313,6 +353,7 @@ export default function QueryInspectorControls( props ) { parents: [], search: '', taxQuery: null, + format: [], } ); setQuerySearch( '' ); } } @@ -374,6 +415,18 @@ export default function QueryInspectorControls( props ) { /> </ToolsPanelItem> ) } + { showFormatControl && ( + <ToolsPanelItem + hasValue={ () => !! format?.length } + label={ __( 'Formats' ) } + onDeselect={ () => setQuery( { format: [] } ) } + > + <FormatControls + onChange={ setQuery } + query={ query } + /> + </ToolsPanelItem> + ) } </ToolsPanel> ) } </> diff --git a/packages/block-library/src/query/utils.js b/packages/block-library/src/query/utils.js index 2e9412b1683cb0..68da2573bab0f6 100644 --- a/packages/block-library/src/query/utils.js +++ b/packages/block-library/src/query/utils.js @@ -94,6 +94,7 @@ export const mapToIHasNameAndId = ( entities, path ) => { * Returns a helper object that contains: * 1. An `options` object from the available post types, to be passed to a `SelectControl`. * 2. A helper map with available taxonomies per post type. + * 3. A helper map with post format support per post type. * * @return {Object} The helper object related to post types. */ @@ -124,7 +125,21 @@ export const usePostTypes = () => { } ) ), [ postTypes ] ); - return { postTypesTaxonomiesMap, postTypesSelectOptions }; + const postTypeFormatSupportMap = useMemo( () => { + if ( ! postTypes?.length ) { + return {}; + } + return postTypes.reduce( ( accumulator, type ) => { + accumulator[ type.slug ] = + type.supports?.[ 'post-formats' ] || false; + return accumulator; + }, {} ); + }, [ postTypes ] ); + return { + postTypesTaxonomiesMap, + postTypesSelectOptions, + postTypeFormatSupportMap, + }; }; /** diff --git a/test/integration/fixtures/blocks/core__query.json b/test/integration/fixtures/blocks/core__query.json index b050aaa2b5b1fd..a5ee4523128df8 100644 --- a/test/integration/fixtures/blocks/core__query.json +++ b/test/integration/fixtures/blocks/core__query.json @@ -16,7 +16,8 @@ "sticky": "", "inherit": true, "taxQuery": null, - "parents": [] + "parents": [], + "format": [] }, "tagName": "div", "enhancedPagination": false From ea0ea782b827cb0a9f1e4a3672394ae7f95bb411 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Mon, 16 Sep 2024 02:03:54 -0500 Subject: [PATCH 0805/1908] Put Replace in own group to give it borders (#64849) Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> --- packages/block-library/src/image/image.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 60d83f89129070..1673d36e463d5a 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -559,7 +559,8 @@ export default function Image( { const mediaReplaceFlow = isSingleSelected && ! isEditingImage && ! lockUrlControls && ( - <BlockControls group="other"> + // For contentOnly mode, put this button in its own area so it has borders around it. + <BlockControls group={ isContentOnlyMode ? 'inline' : 'other' }> <MediaReplaceFlow mediaId={ id } mediaURL={ url } From d9e30752dfc03abd2242e6205b8bb83fa5686edb Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Mon, 16 Sep 2024 09:27:24 +0200 Subject: [PATCH 0806/1908] Pass the comments query paged arg to functions (#63698) Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: ockham <bernhard-reiter@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/block-library/src/comments-pagination-next/index.php | 2 +- .../block-library/src/comments-pagination-previous/index.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/comments-pagination-next/index.php b/packages/block-library/src/comments-pagination-next/index.php index cb8350e561b6e4..14a323df3a13ae 100644 --- a/packages/block-library/src/comments-pagination-next/index.php +++ b/packages/block-library/src/comments-pagination-next/index.php @@ -37,7 +37,7 @@ function render_block_core_comments_pagination_next( $attributes, $content, $blo $label .= $pagination_arrow; } - $next_comments_link = get_next_comments_link( $label, $max_page ); + $next_comments_link = get_next_comments_link( $label, $max_page, $comment_vars['paged'] ); remove_filter( 'next_posts_link_attributes', $filter_link_attributes ); diff --git a/packages/block-library/src/comments-pagination-previous/index.php b/packages/block-library/src/comments-pagination-previous/index.php index 092a28da677922..b70a9f609da9f0 100644 --- a/packages/block-library/src/comments-pagination-previous/index.php +++ b/packages/block-library/src/comments-pagination-previous/index.php @@ -29,7 +29,8 @@ function render_block_core_comments_pagination_previous( $attributes, $content, }; add_filter( 'previous_comments_link_attributes', $filter_link_attributes ); - $previous_comments_link = get_previous_comments_link( $label ); + $comment_vars = build_comment_query_vars_from_block( $block ); + $previous_comments_link = get_previous_comments_link( $label, $comment_vars['paged'] ); remove_filter( 'previous_comments_link_attributes', $filter_link_attributes ); From 38e74db14c27f4ae075eebcf12ee846fcd20fd8b Mon Sep 17 00:00:00 2001 From: Damon Cook <colorful-tones@users.noreply.github.com> Date: Mon, 16 Sep 2024 04:33:38 -0400 Subject: [PATCH 0807/1908] Add JSDoc block for getSectionRootClientId in block editor package (#65219) * Add JSDoc block for getSectionRootClientId in block editor * Apply suggestions from code review Co-authored-by: Dave Smith <getdavemail@gmail.com> --------- Co-authored-by: Dave Smith <getdavemail@gmail.com> --- packages/block-editor/src/store/private-selectors.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index d76f90bc94ffe1..01ad8f69febc9e 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -548,6 +548,15 @@ export function isZoomOutMode( state ) { return state.editorMode === 'zoom-out'; } +/** + * Retrieves the client ID of the block which contains the blocks + * acting as "sections" in the editor. This is typically the "main content" + * of the template/post. + * + * @param {Object} state Editor state. + * + * @return {string|undefined} The section root client ID or undefined if not set. + */ export function getSectionRootClientId( state ) { return state.settings?.[ sectionRootClientIdKey ]; } From 4ca78cdf8ec71ba62dbf4403662202872d8e5888 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 16 Sep 2024 19:35:24 +0900 Subject: [PATCH 0808/1908] Fix Tabs styling in Font Library modal (#65330) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../global-styles/font-library-modal/index.js | 52 +++++++++---------- .../font-library-modal/style.scss | 19 ++++--- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/index.js b/packages/edit-site/src/components/global-styles/font-library-modal/index.js index 5af4be90fecdcf..495652f144275e 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/index.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/index.js @@ -66,8 +66,8 @@ function FontLibraryModal( { isFullScreen className="font-library-modal" > - <div className="font-library-modal__tabs"> - <Tabs defaultTabId={ defaultTabId }> + <Tabs defaultTabId={ defaultTabId }> + <div className="font-library-modal__tablist"> <Tabs.TabList> { tabs.map( ( { id, title } ) => ( <Tabs.Tab key={ id } tabId={ id }> @@ -75,30 +75,30 @@ function FontLibraryModal( { </Tabs.Tab> ) ) } </Tabs.TabList> - { tabs.map( ( { id } ) => { - let contents; - switch ( id ) { - case 'upload-fonts': - contents = <UploadFonts />; - break; - case 'installed-fonts': - contents = <InstalledFonts />; - break; - default: - contents = <FontCollection slug={ id } />; - } - return ( - <Tabs.TabPanel - key={ id } - tabId={ id } - focusable={ false } - > - { contents } - </Tabs.TabPanel> - ); - } ) } - </Tabs> - </div> + </div> + { tabs.map( ( { id } ) => { + let contents; + switch ( id ) { + case 'upload-fonts': + contents = <UploadFonts />; + break; + case 'installed-fonts': + contents = <InstalledFonts />; + break; + default: + contents = <FontCollection slug={ id } />; + } + return ( + <Tabs.TabPanel + key={ id } + tabId={ id } + focusable={ false } + > + { contents } + </Tabs.TabPanel> + ); + } ) } + </Tabs> </Modal> ); } diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss index a9a0784cbcb5a1..8d6f8a3c9b0af3 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss +++ b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss @@ -129,18 +129,17 @@ $footer-height: 70px; padding-bottom: $grid-unit-20; } -.font-library-modal__tabs { - [role="tablist"] { - position: sticky; - top: 0; - border-bottom: 1px solid $gray-300; - background: $white; - margin: 0 #{$grid-unit-40 * -1}; - padding: 0 $grid-unit-20; - z-index: 1; - } +.font-library-modal__tablist { + position: sticky; + top: 0; + border-bottom: 1px solid $gray-300; + background: $white; + margin: 0 #{$grid-unit-40 * -1}; + padding: 0 $grid-unit-20; + z-index: 1; } + .font-library-modal__upload-area { align-items: center; display: flex; From c80fc61804e99268eec4441e2915b33368c30b18 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Mon, 16 Sep 2024 17:38:43 +0530 Subject: [PATCH 0809/1908] Fix: Button: Replace remaining 40px default size violation [Edit Site 2] (#65258) * Fix font library modal fonts to use 40px default button size * Fix install font button to use default 40px size * Fix the installed fonts button size to use 40px default * Fix upload font button size to use 40px default size * Fix add the default button 40px size for randomize color pallete button * Fix edit site style revision button to use 40px default size * Fix edit site shadow components buttons to use default 40px size * Fix the style for the button height on the font library modal * Add !important to override the button size for 40px Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../global-styles/font-library-modal/font-card.js | 3 +-- .../font-library-modal/font-collection.js | 3 +-- .../font-library-modal/installed-fonts.js | 6 ++---- .../global-styles/font-library-modal/style.scss | 12 ++++++++++-- .../global-styles/font-library-modal/upload-fonts.js | 3 +-- .../src/components/global-styles/palette.js | 3 +-- .../screen-revisions/revisions-buttons.js | 3 +-- .../components/global-styles/shadows-edit-panel.js | 12 ++++-------- 8 files changed, 21 insertions(+), 24 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js index 735179588d0723..579c6564fdf3e7 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js @@ -28,8 +28,7 @@ function FontCard( { font, onClick, variantsText, navigatorPath } ) { return ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize onClick={ () => { onClick(); if ( navigatorPath ) { diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js index f2184f7e406049..ce7b4c1766c64f 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js @@ -472,8 +472,7 @@ function FontCollection( { slug } ) { className="font-library-modal__footer" > <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" onClick={ handleInstall } isBusy={ isInstalling } diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js index f42f71095420b5..8cb023fff08e96 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js @@ -437,8 +437,7 @@ function InstalledFonts() { { isInstalling && <ProgressBar /> } { shouldDisplayDeleteButton && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize isDestructive variant="tertiary" onClick={ handleUninstallClick } @@ -447,8 +446,7 @@ function InstalledFonts() { </Button> ) } <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" onClick={ handleUpdate } disabled={ ! fontFamiliesHasChanges } diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss index 8d6f8a3c9b0af3..e8c48ca2c30bf8 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss +++ b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss @@ -94,7 +94,11 @@ $footer-height: 70px; .font-library-modal__font-card { border: $border-width solid $gray-200; width: 100%; - height: auto; + + // Override the default 40px height set by the Button component. + // Ref - https://github.com/WordPress/gutenberg/pull/65258#discussion_r1756147260 + height: auto !important; + padding: $grid-unit-20; margin-top: -1px; /* To collapse the margin with the previous element */ @@ -144,7 +148,11 @@ $footer-height: 70px; align-items: center; display: flex; justify-content: center; - height: $grid-unit-80 * 4; // 256px + + // Override the default 40px height set by the Button component. + // Ref - https://github.com/WordPress/gutenberg/pull/65258#discussion_r1756155039 + height: $grid-unit-80 * 4 !important; // 256px + width: 100%; } diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/upload-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/upload-fonts.js index d2ec234ab444c5..807f2aa354c25a 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/upload-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/upload-fonts.js @@ -230,8 +230,7 @@ function UploadFonts() { onChange={ onFilesUpload } render={ ( { openFileDialog } ) => ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="font-library-modal__upload-area" onClick={ openFileDialog } > diff --git a/packages/edit-site/src/components/global-styles/palette.js b/packages/edit-site/src/components/global-styles/palette.js index 7d2ea0c1cfa0ed..4afb9d88feb3e9 100644 --- a/packages/edit-site/src/components/global-styles/palette.js +++ b/packages/edit-site/src/components/global-styles/palette.js @@ -87,8 +87,7 @@ function Palette( { name } ) { { window.__experimentalEnableColorRandomizer && themeColors?.length > 0 && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="secondary" icon={ shuffle } onClick={ randomizeThemeColors } diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js b/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js index 84f074b8d00c09..5d7c3f6cbded0a 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js +++ b/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js @@ -162,8 +162,7 @@ function RevisionsButtons( { aria-current={ isSelected } > <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="edit-site-global-styles-screen-revisions__revision-button" accessibleWhenDisabled disabled={ isSelected } diff --git a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js index 77bbdb88221167..cf49d8c28ebcb9 100644 --- a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js +++ b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js @@ -234,8 +234,7 @@ export default function ShadowsEditPanel() { > <FlexItem> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" onClick={ () => setIsRenameModalVisible( false ) @@ -246,8 +245,7 @@ export default function ShadowsEditPanel() { </FlexItem> <FlexItem> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" type="submit" > @@ -381,8 +379,7 @@ function ShadowItem( { shadow, onChange, canRemove, onRemove } ) { <HStack align="center" justify="flex-start" spacing={ 0 }> <FlexItem style={ { flexGrow: 1 } }> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize icon={ shadowIcon } { ...toggleProps } > @@ -394,8 +391,7 @@ function ShadowItem( { shadow, onChange, canRemove, onRemove } ) { { canRemove && ( <FlexItem> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize icon={ reset } { ...removeButtonProps } /> From edd41488c6692bfaefb7f31adb13b04740f96bd4 Mon Sep 17 00:00:00 2001 From: louwie17 <lourensschep@gmail.com> Date: Mon, 16 Sep 2024 16:21:30 +0200 Subject: [PATCH 0810/1908] Convert EmbedPreview component to functional component (#51325) * Convert EmbedPreview component to functional component * Update interactive condition and move call inline versus within useEffect Unlinked contributors: louwie17. Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../block-library/src/embed/embed-preview.js | 208 ++++++++---------- 1 file changed, 96 insertions(+), 112 deletions(-) diff --git a/packages/block-library/src/embed/embed-preview.js b/packages/block-library/src/embed/embed-preview.js index 6ef10df08a8c24..1a230faf0c3d57 100644 --- a/packages/block-library/src/embed/embed-preview.js +++ b/packages/block-library/src/embed/embed-preview.js @@ -14,7 +14,7 @@ import clsx from 'clsx'; import { __, sprintf } from '@wordpress/i18n'; import { Placeholder, SandBox } from '@wordpress/components'; import { BlockIcon } from '@wordpress/block-editor'; -import { Component } from '@wordpress/element'; +import { useState } from '@wordpress/element'; import { getAuthority } from '@wordpress/url'; /** @@ -23,129 +23,113 @@ import { getAuthority } from '@wordpress/url'; import WpEmbedPreview from './wp-embed-preview'; import { Caption } from '../utils/caption'; -class EmbedPreview extends Component { - constructor() { - super( ...arguments ); - this.hideOverlay = this.hideOverlay.bind( this ); - this.state = { - interactive: false, - }; - } - - static getDerivedStateFromProps( nextProps, state ) { - if ( ! nextProps.isSelected && state.interactive ) { - // We only want to change this when the block is not selected, because changing it when - // the block becomes selected makes the overlap disappear too early. Hiding the overlay - // happens on mouseup when the overlay is clicked. - return { interactive: false }; - } +export default function EmbedPreview( { + preview, + previewable, + url, + type, + isSelected, + className, + icon, + label, + insertBlocksAfter, + attributes, + setAttributes, +} ) { + const [ interactive, setInteractive ] = useState( false ); - return null; + if ( ! isSelected && interactive ) { + // We only want to change this when the block is not selected, because changing it when + // the block becomes selected makes the overlap disappear too early. Hiding the overlay + // happens on mouseup when the overlay is clicked. + setInteractive( false ); } - hideOverlay() { + const hideOverlay = () => { // This is called onMouseUp on the overlay. We can't respond to the `isSelected` prop // changing, because that happens on mouse down, and the overlay immediately disappears, // and the mouse event can end up in the preview content. We can't use onClick on // the overlay to hide it either, because then the editor misses the mouseup event, and // thinks we're multi-selecting blocks. - this.setState( { interactive: true } ); - } + setInteractive( true ); + }; - render() { - const { - preview, - previewable, - url, - type, - className, - icon, - label, - insertBlocksAfter, - attributes, - setAttributes, - isSelected, - } = this.props; - const { scripts } = preview; - const { interactive } = this.state; + const { scripts } = preview; - const html = 'photo' === type ? getPhotoHtml( preview ) : preview.html; - const embedSourceUrl = getAuthority( url ); - const iframeTitle = sprintf( - // translators: %s: host providing embed content e.g: www.youtube.com - __( 'Embedded content from %s' ), - embedSourceUrl - ); - const sandboxClassnames = clsx( - type, - className, - 'wp-block-embed__wrapper' - ); + const html = 'photo' === type ? getPhotoHtml( preview ) : preview.html; + const embedSourceUrl = getAuthority( url ); + const iframeTitle = sprintf( + // translators: %s: host providing embed content e.g: www.youtube.com + __( 'Embedded content from %s' ), + embedSourceUrl + ); + const sandboxClassnames = clsx( + type, + className, + 'wp-block-embed__wrapper' + ); - // Disabled because the overlay div doesn't actually have a role or functionality - // as far as the user is concerned. We're just catching the first click so that - // the block can be selected without interacting with the embed preview that the overlay covers. - /* eslint-disable jsx-a11y/no-static-element-interactions */ - const embedWrapper = - 'wp-embed' === type ? ( - <WpEmbedPreview html={ html } /> - ) : ( - <div className="wp-block-embed__wrapper"> - <SandBox - html={ html } - scripts={ scripts } - title={ iframeTitle } - type={ sandboxClassnames } - onFocus={ this.hideOverlay } + // Disabled because the overlay div doesn't actually have a role or functionality + // as far as the user is concerned. We're just catching the first click so that + // the block can be selected without interacting with the embed preview that the overlay covers. + /* eslint-disable jsx-a11y/no-static-element-interactions */ + const embedWrapper = + 'wp-embed' === type ? ( + <WpEmbedPreview html={ html } /> + ) : ( + <div className="wp-block-embed__wrapper"> + <SandBox + html={ html } + scripts={ scripts } + title={ iframeTitle } + type={ sandboxClassnames } + onFocus={ hideOverlay } + /> + { ! interactive && ( + <div + className="block-library-embed__interactive-overlay" + onMouseUp={ hideOverlay } /> - { ! interactive && ( - <div - className="block-library-embed__interactive-overlay" - onMouseUp={ this.hideOverlay } - /> - ) } - </div> - ); - /* eslint-enable jsx-a11y/no-static-element-interactions */ - - return ( - <figure - className={ clsx( className, 'wp-block-embed', { - 'is-type-video': 'video' === type, - } ) } - > - { previewable ? ( - embedWrapper - ) : ( - <Placeholder - icon={ <BlockIcon icon={ icon } showColors /> } - label={ label } - > - <p className="components-placeholder__error"> - <a href={ url }>{ url }</a> - </p> - <p className="components-placeholder__error"> - { sprintf( - /* translators: %s: host providing embed content e.g: www.youtube.com */ - __( - "Embedded content from %s can't be previewed in the editor." - ), - embedSourceUrl - ) } - </p> - </Placeholder> ) } - <Caption - attributes={ attributes } - setAttributes={ setAttributes } - isSelected={ isSelected } - insertBlocksAfter={ insertBlocksAfter } - label={ __( 'Embed caption text' ) } - showToolbarButton={ isSelected } - /> - </figure> + </div> ); - } -} + /* eslint-enable jsx-a11y/no-static-element-interactions */ -export default EmbedPreview; + return ( + <figure + className={ clsx( className, 'wp-block-embed', { + 'is-type-video': 'video' === type, + } ) } + > + { previewable ? ( + embedWrapper + ) : ( + <Placeholder + icon={ <BlockIcon icon={ icon } showColors /> } + label={ label } + > + <p className="components-placeholder__error"> + <a href={ url }>{ url }</a> + </p> + <p className="components-placeholder__error"> + { sprintf( + /* translators: %s: host providing embed content e.g: www.youtube.com */ + __( + "Embedded content from %s can't be previewed in the editor." + ), + embedSourceUrl + ) } + </p> + </Placeholder> + ) } + <Caption + attributes={ attributes } + setAttributes={ setAttributes } + isSelected={ isSelected } + insertBlocksAfter={ insertBlocksAfter } + label={ __( 'Embed caption text' ) } + showToolbarButton={ isSelected } + /> + </figure> + ); +} From e2d7722ec6430fe5fb5aea6ed122ca9508499d26 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Mon, 16 Sep 2024 16:37:10 +0100 Subject: [PATCH 0811/1908] Update Card radius (#65053) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/card/card/component.tsx | 2 +- packages/components/src/card/styles.ts | 2 +- .../card/test/__snapshots__/index.tsx.snap | 108 +++++++++--------- .../components/src/utils/config-values.js | 1 - .../components/global-styles/screen-root.js | 10 +- .../src/components/global-styles/style.scss | 8 ++ 7 files changed, 72 insertions(+), 60 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 04858e448da7f0..1473cf5f5df40e 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -19,6 +19,7 @@ - `Navigator`: warn if a screen's `path` doesn't follow a URL-like scheme ([#65231](https://github.com/WordPress/gutenberg/pull/65231)). - `Modal`: Decrease close button size and remove horizontal offset ([#65131](https://github.com/WordPress/gutenberg/pull/65131)). +- `Card`: Adopt radius scale ([#65053](https://github.com/WordPress/gutenberg/pull/65053)). ### Bug Fixes diff --git a/packages/components/src/card/card/component.tsx b/packages/components/src/card/card/component.tsx index 8fefc33bd48027..e459f9abb9275b 100644 --- a/packages/components/src/card/card/component.tsx +++ b/packages/components/src/card/card/component.tsx @@ -34,7 +34,7 @@ function UnconnectedCard( size, ...otherProps } = useCard( props ); - const elevationBorderRadius = isRounded ? CONFIG.cardBorderRadius : 0; + const elevationBorderRadius = isRounded ? CONFIG.radiusLarge : 0; const cx = useCx(); diff --git a/packages/components/src/card/styles.ts b/packages/components/src/card/styles.ts index fa70b19054e2fc..df0fe4eb7ed720 100644 --- a/packages/components/src/card/styles.ts +++ b/packages/components/src/card/styles.ts @@ -12,7 +12,7 @@ import { COLORS, CONFIG } from '../utils'; // (as opposed to the `border` property), the value of the border radius needs // to be adjusted by removing 1px (this is because the `box-shadow` renders // as an "outer radius"). -const adjustedBorderRadius = `calc(${ CONFIG.cardBorderRadius } - 1px)`; +const adjustedBorderRadius = `calc(${ CONFIG.radiusLarge } - 1px)`; export const Card = css` box-shadow: 0 0 0 1px ${ CONFIG.surfaceBorderColor }; diff --git a/packages/components/src/card/test/__snapshots__/index.tsx.snap b/packages/components/src/card/test/__snapshots__/index.tsx.snap index cc1a754e1d37c9..e9073edba3e3e4 100644 --- a/packages/components/src/card/test/__snapshots__/index.tsx.snap +++ b/packages/components/src/card/test/__snapshots__/index.tsx.snap @@ -8,8 +8,8 @@ Snapshot Diff: @@ -1,8 +1,8 @@ <div> <div -- class="components-card__body components-card-body css-d0qyo2-PolymorphicDiv-Body-borderRadius-medium e19lxcc00" -+ class="components-scrollable components-card__body components-card-body css-vpf7zs-PolymorphicDiv-Scrollable-scrollableScrollbar-scrollY-Body-borderRadius-medium e19lxcc00" +- class="components-card__body components-card-body css-12jqy32-PolymorphicDiv-Body-borderRadius-medium e19lxcc00" ++ class="components-scrollable components-card__body components-card-body css-26nv7r-PolymorphicDiv-Scrollable-scrollableScrollbar-scrollY-Body-borderRadius-medium e19lxcc00" data-wp-c16t="true" data-wp-component="CardBody" > @@ -25,8 +25,8 @@ Snapshot Diff: @@ -1,8 +1,8 @@ <div> <div -- class="components-card__body components-card-body css-d0qyo2-PolymorphicDiv-Body-borderRadius-medium e19lxcc00" -+ class="components-card__body components-card-body css-4zm8r0-PolymorphicDiv-Body-borderRadius-medium-shady e19lxcc00" +- class="components-card__body components-card-body css-12jqy32-PolymorphicDiv-Body-borderRadius-medium e19lxcc00" ++ class="components-card__body components-card-body css-1j7lja1-PolymorphicDiv-Body-borderRadius-medium-shady e19lxcc00" data-wp-c16t="true" data-wp-component="CardBody" > @@ -42,8 +42,8 @@ Snapshot Diff: @@ -1,8 +1,8 @@ <div> <div -- class="components-flex components-card__footer components-card-footer css-1l4bmbt-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-medium e19lxcc00" -+ class="components-flex components-card__footer components-card-footer css-8pv7rj-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-medium-shady e19lxcc00" +- class="components-flex components-card__footer components-card-footer css-19sc0cg-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-medium e19lxcc00" ++ class="components-flex components-card__footer components-card-footer css-14budie-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-medium-shady e19lxcc00" data-wp-c16t="true" data-wp-component="CardFooter" > @@ -59,8 +59,8 @@ Snapshot Diff: @@ -1,8 +1,8 @@ <div> <div -- class="components-flex components-card__footer components-card-footer css-1l4bmbt-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-medium e19lxcc00" -+ class="components-flex components-card__footer components-card-footer css-1hguscv-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-medium e19lxcc00" +- class="components-flex components-card__footer components-card-footer css-19sc0cg-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-medium e19lxcc00" ++ class="components-flex components-card__footer components-card-footer css-2io175-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-medium e19lxcc00" data-wp-c16t="true" data-wp-component="CardFooter" > @@ -76,8 +76,8 @@ Snapshot Diff: @@ -1,8 +1,8 @@ <div> <div -- class="components-flex components-card__header components-card-header css-1tfuk0d-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-medium e19lxcc00" -+ class="components-flex components-card__header components-card-header css-10qs2ur-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-medium-shady e19lxcc00" +- class="components-flex components-card__header components-card-header css-1qwshfy-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-medium e19lxcc00" ++ class="components-flex components-card__header components-card-header css-1bzc8bz-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-medium-shady e19lxcc00" data-wp-c16t="true" data-wp-component="CardHeader" > @@ -96,16 +96,16 @@ Snapshot Diff: class="css-76dw7d-PolymorphicDiv-Content e19lxcc00" > <div -- class="components-flex components-card__header components-card-header css-1tfuk0d-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-medium e19lxcc00" -+ class="components-flex components-card__header components-card-header css-d1c2bv-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-large e19lxcc00" +- class="components-flex components-card__header components-card-header css-1qwshfy-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-medium e19lxcc00" ++ class="components-flex components-card__header components-card-header css-1t2zg3y-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-large e19lxcc00" data-wp-c16t="true" data-wp-component="CardHeader" > Header </div> <div -- class="components-card__body components-card-body css-d0qyo2-PolymorphicDiv-Body-borderRadius-medium e19lxcc00" -+ class="components-card__body components-card-body css-kub9fa-PolymorphicDiv-Body-borderRadius-large e19lxcc00" +- class="components-card__body components-card-body css-12jqy32-PolymorphicDiv-Body-borderRadius-medium e19lxcc00" ++ class="components-card__body components-card-body css-e0vrqx-PolymorphicDiv-Body-borderRadius-large e19lxcc00" data-wp-c16t="true" data-wp-component="CardBody" > @@ -122,7 +122,7 @@ Snapshot Diff: Array [ Object { "background-color": "#fff", -- "border-radius": "calc(2px - 1px)", +- "border-radius": "calc(8px - 1px)", "box-shadow": "0 0 0 1px rgba(0, 0, 0, 0.1)", "color": "#1e1e1e", "outline": "none", @@ -141,24 +141,24 @@ Snapshot Diff: class="css-76dw7d-PolymorphicDiv-Content e19lxcc00" > <div -- class="components-flex components-card__header components-card-header css-1xfrxuu-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-large-borderless e19lxcc00" -+ class="components-flex components-card__header components-card-header css-1mitrbv-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-small e19lxcc00" +- class="components-flex components-card__header components-card-header css-ubn8f6-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-large-borderless e19lxcc00" ++ class="components-flex components-card__header components-card-header css-1t1rswf-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-small e19lxcc00" data-wp-c16t="true" data-wp-component="CardHeader" > Header </div> <div -- class="components-card__body components-card-body css-kub9fa-PolymorphicDiv-Body-borderRadius-large e19lxcc00" -+ class="components-card__body components-card-body css-d0qyo2-PolymorphicDiv-Body-borderRadius-medium e19lxcc00" +- class="components-card__body components-card-body css-e0vrqx-PolymorphicDiv-Body-borderRadius-large e19lxcc00" ++ class="components-card__body components-card-body css-12jqy32-PolymorphicDiv-Body-borderRadius-medium e19lxcc00" data-wp-c16t="true" data-wp-component="CardBody" > Body </div> <div -- class="components-flex components-card__footer components-card-footer css-8o7z5w-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-large-borderless e19lxcc00" -+ class="components-flex components-card__footer components-card-footer css-1umuqb4-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-xSmallCardPadding e19lxcc00" +- class="components-flex components-card__footer components-card-footer css-167csgt-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-large-borderless e19lxcc00" ++ class="components-flex components-card__footer components-card-footer css-1kcgqsk-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-xSmallCardPadding e19lxcc00" data-wp-c16t="true" data-wp-component="CardFooter" > @@ -174,8 +174,8 @@ Snapshot Diff: @@ -1,30 +1,30 @@ <div> <div -- class="components-surface components-card css-5ubhkm-PolymorphicDiv-Surface-getBorders-primary-Card-boxShadowless-rounded e19lxcc00" -+ class="components-surface components-card css-1lc0qq8-PolymorphicDiv-Surface-getBorders-primary-Card-rounded e19lxcc00" +- class="components-surface components-card css-1hs39fv-PolymorphicDiv-Surface-getBorders-primary-Card-boxShadowless-rounded e19lxcc00" ++ class="components-surface components-card css-1c6nh8q-PolymorphicDiv-Surface-getBorders-primary-Card-rounded e19lxcc00" data-wp-c16t="true" data-wp-component="Card" > @@ -183,24 +183,24 @@ Snapshot Diff: class="css-76dw7d-PolymorphicDiv-Content e19lxcc00" > <div -- class="components-flex components-card__header components-card-header css-1xfrxuu-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-large-borderless e19lxcc00" -+ class="components-flex components-card__header components-card-header css-1mitrbv-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-small e19lxcc00" +- class="components-flex components-card__header components-card-header css-ubn8f6-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-large-borderless e19lxcc00" ++ class="components-flex components-card__header components-card-header css-1t1rswf-PolymorphicDiv-Flex-base-ItemsRow-Header-borderRadius-borderColor-small e19lxcc00" data-wp-c16t="true" data-wp-component="CardHeader" > Header </div> <div -- class="components-card__body components-card-body css-kub9fa-PolymorphicDiv-Body-borderRadius-large e19lxcc00" -+ class="components-card__body components-card-body css-1djcdvu-PolymorphicDiv-Body-borderRadius-small e19lxcc00" +- class="components-card__body components-card-body css-e0vrqx-PolymorphicDiv-Body-borderRadius-large e19lxcc00" ++ class="components-card__body components-card-body css-hms9n9-PolymorphicDiv-Body-borderRadius-small e19lxcc00" data-wp-c16t="true" data-wp-component="CardBody" > Body </div> <div -- class="components-flex components-card__footer components-card-footer css-8o7z5w-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-large-borderless e19lxcc00" -+ class="components-flex components-card__footer components-card-footer css-1awxp6o-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-small e19lxcc00" +- class="components-flex components-card__footer components-card-footer css-167csgt-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-large-borderless e19lxcc00" ++ class="components-flex components-card__footer components-card-footer css-18yn3ff-PolymorphicDiv-Flex-base-ItemsRow-Footer-borderRadius-borderColor-small e19lxcc00" data-wp-c16t="true" data-wp-component="CardFooter" > @@ -215,7 +215,7 @@ exports[`Card Card component should render correctly 1`] = ` position: relative; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1); outline: none; - border-radius: calc(2px - 1px); + border-radius: calc(8px - 1px); } .emotion-2 { @@ -254,13 +254,13 @@ exports[`Card Card component should render correctly 1`] = ` } .emotion-4:first-of-type { - border-top-left-radius: calc(2px - 1px); - border-top-right-radius: calc(2px - 1px); + border-top-left-radius: calc(8px - 1px); + border-top-right-radius: calc(8px - 1px); } .emotion-4:last-of-type { - border-bottom-left-radius: calc(2px - 1px); - border-bottom-right-radius: calc(2px - 1px); + border-bottom-left-radius: calc(8px - 1px); + border-bottom-right-radius: calc(8px - 1px); } .emotion-6 { @@ -271,13 +271,13 @@ exports[`Card Card component should render correctly 1`] = ` } .emotion-6:first-of-type { - border-top-left-radius: calc(2px - 1px); - border-top-right-radius: calc(2px - 1px); + border-top-left-radius: calc(8px - 1px); + border-top-right-radius: calc(8px - 1px); } .emotion-6:last-of-type { - border-bottom-left-radius: calc(2px - 1px); - border-bottom-right-radius: calc(2px - 1px); + border-bottom-left-radius: calc(8px - 1px); + border-bottom-right-radius: calc(8px - 1px); } .emotion-10 { @@ -306,13 +306,13 @@ exports[`Card Card component should render correctly 1`] = ` } .emotion-14:first-of-type { - border-top-left-radius: calc(2px - 1px); - border-top-right-radius: calc(2px - 1px); + border-top-left-radius: calc(8px - 1px); + border-top-right-radius: calc(8px - 1px); } .emotion-14:last-of-type { - border-bottom-left-radius: calc(2px - 1px); - border-bottom-right-radius: calc(2px - 1px); + border-bottom-left-radius: calc(8px - 1px); + border-bottom-right-radius: calc(8px - 1px); } .emotion-16 { @@ -347,13 +347,13 @@ exports[`Card Card component should render correctly 1`] = ` } .emotion-16:first-of-type { - border-top-left-radius: calc(2px - 1px); - border-top-right-radius: calc(2px - 1px); + border-top-left-radius: calc(8px - 1px); + border-top-right-radius: calc(8px - 1px); } .emotion-16:last-of-type { - border-bottom-left-radius: calc(2px - 1px); - border-bottom-right-radius: calc(2px - 1px); + border-bottom-left-radius: calc(8px - 1px); + border-bottom-right-radius: calc(8px - 1px); } .emotion-18 { @@ -370,7 +370,7 @@ exports[`Card Card component should render correctly 1`] = ` left: 0; right: 0; top: 0; - border-radius: 2px; + border-radius: 8px; } @media not ( prefers-reduced-motion ) { @@ -469,15 +469,15 @@ Snapshot Diff: </div> <div aria-hidden="true" -- class="components-elevation css-1dd80bh-PolymorphicDiv-Elevation-sx-Base-sx-Base-elevationClassName e19lxcc00" -+ class="components-elevation css-1jg41yu-PolymorphicDiv-Elevation-sx-Base-sx-Base-elevationClassName e19lxcc00" +- class="components-elevation css-a91pvj-PolymorphicDiv-Elevation-sx-Base-sx-Base-elevationClassName e19lxcc00" ++ class="components-elevation css-1q4cuxd-PolymorphicDiv-Elevation-sx-Base-sx-Base-elevationClassName e19lxcc00" data-wp-c16t="true" data-wp-component="Elevation" /> <div aria-hidden="true" -- class="components-elevation css-iuptql-PolymorphicDiv-Elevation-sx-Base-sx-Base-elevationClassName e19lxcc00" -+ class="components-elevation css-1jg41yu-PolymorphicDiv-Elevation-sx-Base-sx-Base-elevationClassName e19lxcc00" +- class="components-elevation css-5u83fl-PolymorphicDiv-Elevation-sx-Base-sx-Base-elevationClassName e19lxcc00" ++ class="components-elevation css-1q4cuxd-PolymorphicDiv-Elevation-sx-Base-sx-Base-elevationClassName e19lxcc00" data-wp-c16t="true" data-wp-component="Elevation" /> @@ -497,7 +497,7 @@ exports[`Card Card component should warn when the isElevated prop is passed 1`] position: relative; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1); outline: none; - border-radius: calc(2px - 1px); + border-radius: calc(8px - 1px); } .emotion-2 { @@ -518,7 +518,7 @@ exports[`Card Card component should warn when the isElevated prop is passed 1`] left: 0; right: 0; top: 0; - border-radius: 2px; + border-radius: 8px; } @media not ( prefers-reduced-motion ) { @@ -542,7 +542,7 @@ exports[`Card Card component should warn when the isElevated prop is passed 1`] left: 0; right: 0; top: 0; - border-radius: 2px; + border-radius: 8px; } @media not ( prefers-reduced-motion ) { diff --git a/packages/components/src/utils/config-values.js b/packages/components/src/utils/config-values.js index f76c1291a8b319..4d7ed859e89edd 100644 --- a/packages/components/src/utils/config-values.js +++ b/packages/components/src/utils/config-values.js @@ -68,7 +68,6 @@ export default Object.assign( {}, CONTROL_PROPS, TOGGLE_GROUP_CONTROL_PROPS, { fontWeight: 'normal', fontWeightHeading: '600', gridBase: '4px', - cardBorderRadius: '2px', cardPaddingXSmall: `${ space( 2 ) }`, cardPaddingSmall: `${ space( 4 ) }`, cardPaddingMedium: `${ space( 4 ) } ${ space( 6 ) }`, diff --git a/packages/edit-site/src/components/global-styles/screen-root.js b/packages/edit-site/src/components/global-styles/screen-root.js index 4146b32b57e3db..d5b29eca5549c5 100644 --- a/packages/edit-site/src/components/global-styles/screen-root.js +++ b/packages/edit-site/src/components/global-styles/screen-root.js @@ -53,11 +53,15 @@ function ScreenRoot() { }, [] ); return ( - <Card size="small" className="edit-site-global-styles-screen-root"> + <Card + size="small" + className="edit-site-global-styles-screen-root" + isRounded={ false } + > <CardBody> <VStack spacing={ 4 }> - <Card> - <CardMedia> + <Card className="edit-site-global-styles-screen-root__active-style-tile"> + <CardMedia className="edit-site-global-styles-screen-root__active-style-tile-preview"> <PreviewStyles /> </CardMedia> </Card> diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss index 9bab48e308947a..5574fe52d81f58 100644 --- a/packages/edit-site/src/components/global-styles/style.scss +++ b/packages/edit-site/src/components/global-styles/style.scss @@ -221,3 +221,11 @@ fill: currentColor; } +.edit-site-global-styles-screen-root__active-style-tile { + // Todo: revisit use of Card component and/or remove override + // The &#{&} is a workaround for the specificity of the Card component. + &#{&}, + &#{&} .edit-site-global-styles-screen-root__active-style-tile-preview { + border-radius: $radius-small; + } +} From 2ac16e02378b66e38213022e3f38aace698a885a Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 17 Sep 2024 01:28:35 +0900 Subject: [PATCH 0812/1908] Docs: Update the content of the API version 3 section in the Block API Reference (#65375) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> --- docs/reference-guides/block-api/block-api-versions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference-guides/block-api/block-api-versions.md b/docs/reference-guides/block-api/block-api-versions.md index b4b11e7c23c7cc..d89362777ca58c 100644 --- a/docs/reference-guides/block-api/block-api-versions.md +++ b/docs/reference-guides/block-api/block-api-versions.md @@ -3,7 +3,7 @@ This document lists the changes made between the different API versions. ## Version 3 (>= WordPress 6.3) -- The post editor will be iframed if all registered blocks have a Block API version 3 or higher and the editor has no classic meta boxes below the blocks. Adding version 3 support means that the block should work inside an iframe, though the block may still be rendered outside the iframe if not all blocks support version 3. +- The post editor will be iframed if all registered blocks have a Block API version 3 or higher. Adding version 3 support means that the block should work inside an iframe, though the block may still be rendered outside the iframe if not all blocks support version 3. ## Version 2 (>= WordPress 5.6) From c0e3ad898f67792d48c5e3b45f14b7a2c189722b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:21:20 -0400 Subject: [PATCH 0813/1908] Bump the react-native group across 1 directory with 2 updates (#65321) Bumps the react-native group with 2 updates in the / directory: [actions/setup-java](https://github.com/actions/setup-java) and [gradle/actions](https://github.com/gradle/actions). Updates `actions/setup-java` from 4.2.2 to 4.3.0 - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/6a0805fcefea3d4657a47ac4c165951e33482018...2dfa2011c5b2a0f1489bf9e433881c92c1631f88) Updates `gradle/actions` from 4.0.0 to 4.1.0 - [Release notes](https://github.com/gradle/actions/releases) - [Commits](https://github.com/gradle/actions/compare/af1da67850ed9a4cedd57bfd976089dd991e2582...d156388eb19639ec20ade50009f3d199ce1e2808) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor dependency-group: react-native - dependency-name: gradle/actions dependency-type: direct:production update-type: version-update:semver-minor dependency-group: react-native ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/rnmobile-android-runner.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index 3efd7d79ee2276..2c3998c2952808 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -28,7 +28,7 @@ jobs: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Java - uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 + uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # v4.3.0 with: distribution: 'corretto' java-version: '17' @@ -47,7 +47,7 @@ jobs: run: npm run native test:e2e:setup - name: Gradle cache - uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 + uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0 - name: AVD cache uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 From 788bb9e948477dc33a96d4e480833131650d5e67 Mon Sep 17 00:00:00 2001 From: Grant Kinney <creativecoder@users.noreply.github.com> Date: Mon, 16 Sep 2024 19:01:57 -0500 Subject: [PATCH 0814/1908] DocumentBar: replace icon with post type label (#65170) * Adds post type label to DocumentBar * Removes the post type icon from the DocumentBar * Try fixing one of the e2e tests * Remove IconType import and add typedef * Adds font-weight to heading and uses darker grey for constrast * Adjusts title overflow so it dosen't apply to post type label * Moves font weight to h1 * Try fixing more e2e tests * Fix another e2e * Add fix for mid screensizes when Back button is present * Hide post type label on small screen sizes --------- Co-authored-by: creativecoder <grantmkin@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../editor-canvas-container/index.js | 25 ++----- .../edit-site/src/components/editor/index.js | 6 +- packages/editor/README.md | 2 +- .../src/components/document-bar/index.js | 70 ++++++++----------- .../src/components/document-bar/style.scss | 48 +++++++++---- .../src/components/editor-interface/index.js | 2 - .../editor/src/components/header/index.js | 3 +- .../various/post-editor-template-mode.spec.js | 2 +- .../specs/site-editor/command-center.spec.js | 2 +- .../site-editor/template-registration.spec.js | 4 +- test/e2e/specs/site-editor/title.spec.js | 4 +- 11 files changed, 79 insertions(+), 89 deletions(-) diff --git a/packages/edit-site/src/components/editor-canvas-container/index.js b/packages/edit-site/src/components/editor-canvas-container/index.js index 75a04b5887d75f..36a3a5b43e5cd2 100644 --- a/packages/edit-site/src/components/editor-canvas-container/index.js +++ b/packages/edit-site/src/components/editor-canvas-container/index.js @@ -9,7 +9,7 @@ import { import { ESCAPE } from '@wordpress/keycodes'; import { __ } from '@wordpress/i18n'; import { useDispatch, useSelect } from '@wordpress/data'; -import { backup, closeSmall, seen } from '@wordpress/icons'; +import { closeSmall } from '@wordpress/icons'; import { useFocusOnMount, useFocusReturn } from '@wordpress/compose'; import { store as preferencesStore } from '@wordpress/preferences'; import { @@ -32,24 +32,15 @@ const { EditorContentSlotFill, ResizableEditor } = unlock( editorPrivateApis ); * * @return {Object} Translated string for the view title and associated icon, both defaulting to ''. */ -function getEditorCanvasContainerTitleAndIcon( view ) { +function getEditorCanvasContainerTitle( view ) { switch ( view ) { case 'style-book': - return { - title: __( 'Style Book' ), - icon: seen, - }; + return __( 'Style Book' ); case 'global-styles-revisions': case 'global-styles-revisions:style-book': - return { - title: __( 'Style Revisions' ), - icon: backup, - }; + return __( 'Style Revisions' ); default: - return { - title: '', - icon: '', - }; + return ''; } } @@ -118,9 +109,7 @@ function EditorCanvasContainer( { return null; } - const { title } = getEditorCanvasContainerTitleAndIcon( - editorCanvasContainerView - ); + const title = getEditorCanvasContainerTitle( editorCanvasContainerView ); const shouldShowCloseButton = onClose || closeButtonLabel; return ( @@ -158,4 +147,4 @@ function useHasEditorCanvasContainer() { } export default EditorCanvasContainer; -export { useHasEditorCanvasContainer, getEditorCanvasContainerTitleAndIcon }; +export { useHasEditorCanvasContainer, getEditorCanvasContainerTitle }; diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 4be3c960bb4a34..b99a7cd78ed371 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -37,7 +37,7 @@ import PluginTemplateSettingPanel from '../plugin-template-setting-panel'; import GlobalStylesSidebar from '../global-styles-sidebar'; import { isPreviewingTheme } from '../../utils/is-previewing-theme'; import { - getEditorCanvasContainerTitleAndIcon, + getEditorCanvasContainerTitle, useHasEditorCanvasContainer, } from '../editor-canvas-container'; import SaveButton from '../save-button'; @@ -204,8 +204,7 @@ export default function EditSiteEditor( { isPostsList = false } ) { ); // Replace the title and icon displayed in the DocumentBar when there's an overlay visible. - const { title, icon } = - getEditorCanvasContainerTitleAndIcon( editorCanvasView ); + const title = getEditorCanvasContainerTitle( editorCanvasView ); const isReady = ! isLoading; const transition = { @@ -238,7 +237,6 @@ export default function EditSiteEditor( { isPostsList = false } ) { customSavePanel={ _isPreviewingTheme && <SavePanel /> } forceDisableBlockTools={ ! hasDefaultEditorCanvasView } title={ title } - icon={ icon } iframeProps={ iframeProps } onActionPerformed={ onActionPerformed } extraSidebarPanels={ diff --git a/packages/editor/README.md b/packages/editor/README.md index d18513b151beae..2acb98ef13642c 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -266,7 +266,7 @@ _Parameters_ - _props_ `Object`: The component props. - _props.title_ `string`: A title for the document, defaulting to the document or template title currently being edited. -- _props.icon_ `import("@wordpress/components").IconType`: An icon for the document, defaulting to an icon for document or template currently being edited. +- _props.icon_ `IconType`: An icon for the document, no default. (A default icon indicating the document post type is no longer used.) _Returns_ diff --git a/packages/editor/src/components/document-bar/index.js b/packages/editor/src/components/document-bar/index.js index f71cbce23fdafb..904a877734cef9 100644 --- a/packages/editor/src/components/document-bar/index.js +++ b/packages/editor/src/components/document-bar/index.js @@ -6,7 +6,7 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { __, isRTL, sprintf } from '@wordpress/i18n'; +import { __, isRTL } from '@wordpress/i18n'; import { useSelect, useDispatch } from '@wordpress/data'; import { Button, @@ -28,18 +28,8 @@ import { decodeEntities } from '@wordpress/html-entities'; */ import { TEMPLATE_POST_TYPES, GLOBAL_POST_TYPES } from '../../store/constants'; import { store as editorStore } from '../../store'; -import { unlock } from '../../lock-unlock'; -const TYPE_LABELS = { - // translators: 1: Pattern title. - wp_pattern: __( 'Editing pattern: %s' ), - // translators: 1: Navigation menu title. - wp_navigation: __( 'Editing navigation menu: %s' ), - // translators: 1: Template title. - wp_template: __( 'Editing template: %s' ), - // translators: 1: Template part title. - wp_template_part: __( 'Editing template part: %s' ), -}; +/** @typedef {import("@wordpress/components").IconType} IconType */ const MotionButton = motion( Button ); @@ -52,21 +42,21 @@ const MotionButton = motion( Button ); * ```jsx * <DocumentBar /> * ``` - * @param {Object} props The component props. - * @param {string} props.title A title for the document, defaulting to the document or - * template title currently being edited. - * @param {import("@wordpress/components").IconType} props.icon An icon for the document, defaulting to an icon for document - * or template currently being edited. + * @param {Object} props The component props. + * @param {string} props.title A title for the document, defaulting to the document or + * template title currently being edited. + * @param {IconType} props.icon An icon for the document, no default. + * (A default icon indicating the document post type is no longer used.) * * @return {JSX.Element} The rendered DocumentBar component. */ export default function DocumentBar( props ) { const { postType, + postTypeLabel, documentTitle, isNotFound, isUnsyncedPattern, - templateIcon, templateTitle, onNavigateToPreviousEntityRecord, } = useSelect( ( select ) => { @@ -76,8 +66,11 @@ export default function DocumentBar( props ) { getEditorSettings, __experimentalGetTemplateInfo: getTemplateInfo, } = select( editorStore ); - const { getEditedEntityRecord, isResolving: isResolvingSelector } = - select( coreStore ); + const { + getEditedEntityRecord, + getPostType, + isResolving: isResolvingSelector, + } = select( coreStore ); const _postType = getCurrentPostType(); const _postId = getCurrentPostId(); const _document = getEditedEntityRecord( @@ -86,8 +79,11 @@ export default function DocumentBar( props ) { _postId ); const _templateInfo = getTemplateInfo( _document ); + const _postTypeLabel = getPostType( _postType )?.labels?.singular_name; + return { postType: _postType, + postTypeLabel: _postTypeLabel, documentTitle: _document.title, isNotFound: ! _document && @@ -98,12 +94,6 @@ export default function DocumentBar( props ) { _postId ), isUnsyncedPattern: _document?.wp_pattern_sync_status === 'unsynced', - templateIcon: unlock( select( editorStore ) ).getPostIcon( - _postType, - { - area: _document?.area, - } - ), templateTitle: _templateInfo.title, onNavigateToPreviousEntityRecord: getEditorSettings().onNavigateToPreviousEntityRecord, @@ -118,7 +108,7 @@ export default function DocumentBar( props ) { const hasBackButton = !! onNavigateToPreviousEntityRecord; const entityTitle = isTemplate ? templateTitle : documentTitle; const title = props.title || entityTitle; - const icon = props.icon || templateIcon; + const icon = props.icon; const mountedRef = useRef( false ); useEffect( () => { @@ -187,20 +177,18 @@ export default function DocumentBar( props ) { isReducedMotion ? { duration: 0 } : undefined } > - <BlockIcon icon={ icon } /> - <Text - size="body" - as="h1" - aria-label={ - ! props.title && TYPE_LABELS[ postType ] - ? // eslint-disable-next-line @wordpress/valid-sprintf - sprintf( TYPE_LABELS[ postType ], title ) - : undefined - } - > - { title - ? decodeEntities( title ) - : __( 'No title' ) } + { icon && <BlockIcon icon={ icon } /> } + <Text size="body" as="h1"> + <span className="editor-document-bar__post-title"> + { title + ? decodeEntities( title ) + : __( 'No title' ) } + </span> + { postTypeLabel && ! props.title && ( + <span className="editor-document-bar__post-type-label"> + { '· ' + decodeEntities( postTypeLabel ) } + </span> + ) } </Text> </motion.div> <span className="editor-document-bar__shortcut"> diff --git a/packages/editor/src/components/document-bar/style.scss b/packages/editor/src/components/document-bar/style.scss index bc39d68df338ac..3e5fbf5f4b1ae1 100644 --- a/packages/editor/src/components/document-bar/style.scss +++ b/packages/editor/src/components/document-bar/style.scss @@ -25,6 +25,14 @@ background: $gray-200; } } + + &.has-back-button { + @media screen and (min-width: #{ ($break-medium) }) and (max-width: #{ ($break-large) }) { + .editor-document-bar__post-type-label { + display: none; + } + } + } } .editor-document-bar__command { @@ -34,34 +42,44 @@ } .editor-document-bar__title { - flex: 1; overflow: hidden; color: $gray-900; - gap: $grid-unit-05; - display: flex; - justify-content: center; - align-items: center; + margin: 0 auto; + max-width: 70%; // Offset the layout based on the width of the ⌘K label. This ensures the title is centrally aligned. @include break-medium() { padding-left: $grid-unit-30; } + h1 { + display: flex; + align-items: center; + justify-content: center; + font-weight: 400; + white-space: nowrap; + overflow: hidden; + } +} + +.editor-document-bar__post-title { + color: currentColor; + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + .editor-document-bar.is-global & { color: var(--wp-block-synced-color); } +} - .block-editor-block-icon { - min-width: $grid-unit-30; - flex-shrink: 0; - } +.editor-document-bar__post-type-label { + flex: 0; + color: $gray-800; + padding-left: $grid-unit-05; - h1 { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 70%; - color: currentColor; + @media screen and (max-width: #{ ($break-small) }) { + display: none; } } diff --git a/packages/editor/src/components/editor-interface/index.js b/packages/editor/src/components/editor-interface/index.js index 848767f856ce7b..284c9772d7bd6f 100644 --- a/packages/editor/src/components/editor-interface/index.js +++ b/packages/editor/src/components/editor-interface/index.js @@ -58,7 +58,6 @@ export default function EditorInterface( { customSavePanel, forceDisableBlockTools, title, - icon, iframeProps, } ) { const { @@ -140,7 +139,6 @@ export default function EditorInterface( { customSaveButton={ customSaveButton } forceDisableBlockTools={ forceDisableBlockTools } title={ title } - icon={ icon } /> ) } diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index a838b95258ca6a..b1b8f2fc1ee32b 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -47,7 +47,6 @@ function Header( { forceDisableBlockTools, setEntitiesSavedStatesCallback, title, - icon, } ) { const zoomOutExperimentEnabled = window.__experimentalEnableZoomOutExperiment; @@ -121,7 +120,7 @@ function Header( { variants={ toolbarVariations } transition={ { type: 'tween' } } > - <DocumentBar title={ title } icon={ icon } /> + <DocumentBar title={ title } /> </motion.div> ) } <motion.div diff --git a/test/e2e/specs/editor/various/post-editor-template-mode.spec.js b/test/e2e/specs/editor/various/post-editor-template-mode.spec.js index d46062eded07be..981f8ccbbd5d38 100644 --- a/test/e2e/specs/editor/various/post-editor-template-mode.spec.js +++ b/test/e2e/specs/editor/various/post-editor-template-mode.spec.js @@ -196,7 +196,7 @@ class PostEditorTemplateMode { ); const title = this.editorTopBar.getByRole( 'heading', { - name: 'Editing template: Single Entries', + name: 'Single Entries', } ); await expect( title ).toBeVisible(); diff --git a/test/e2e/specs/site-editor/command-center.spec.js b/test/e2e/specs/site-editor/command-center.spec.js index fce951ca767bed..5b049cda252a8b 100644 --- a/test/e2e/specs/site-editor/command-center.spec.js +++ b/test/e2e/specs/site-editor/command-center.spec.js @@ -47,7 +47,7 @@ test.describe( 'Site editor command palette', () => { page .getByRole( 'region', { name: 'Editor top bar' } ) .getByRole( 'heading', { level: 1 } ) - ).toHaveText( 'Index' ); + ).toContainText( 'Index' ); } ); test( 'Open the command palette and navigate to Customize CSS', async ( { diff --git a/test/e2e/specs/site-editor/template-registration.spec.js b/test/e2e/specs/site-editor/template-registration.spec.js index ba9667358b3142..90e56645813c30 100644 --- a/test/e2e/specs/site-editor/template-registration.spec.js +++ b/test/e2e/specs/site-editor/template-registration.spec.js @@ -108,7 +108,7 @@ test.describe( 'Block template registration', () => { } ); // Swap template. - await page.getByRole( 'button', { name: 'Post' } ).click(); + await page.getByRole( 'button', { name: 'Post', exact: true } ).click(); await page.getByRole( 'button', { name: 'Template options' } ).click(); await page.getByRole( 'menuitem', { name: 'Swap template' } ).click(); await page.getByText( 'Plugin Template' ).click(); @@ -135,7 +135,7 @@ test.describe( 'Block template registration', () => { } ); // Swap template. - await page.getByRole( 'button', { name: 'Post' } ).click(); + await page.getByRole( 'button', { name: 'Post', exact: true } ).click(); await page.getByRole( 'button', { name: 'Template options' } ).click(); await page.getByRole( 'menuitem', { name: 'Swap template' } ).click(); await page.getByText( 'Custom', { exact: true } ).click(); diff --git a/test/e2e/specs/site-editor/title.spec.js b/test/e2e/specs/site-editor/title.spec.js index 3224c519f4f9e8..8f6c5252c9f41b 100644 --- a/test/e2e/specs/site-editor/title.spec.js +++ b/test/e2e/specs/site-editor/title.spec.js @@ -25,7 +25,7 @@ test.describe( 'Site editor title', () => { const title = page .getByRole( 'region', { name: 'Editor top bar' } ) .getByRole( 'heading', { - name: 'Editing template: Index', + name: 'Index', } ); await expect( title ).toBeVisible(); @@ -44,7 +44,7 @@ test.describe( 'Site editor title', () => { const title = page .getByRole( 'region', { name: 'Editor top bar' } ) .getByRole( 'heading', { - name: 'Editing template part: header', + name: 'header', } ); await expect( title ).toBeVisible(); From 46d898e29cb5e18d76f60287fdeecf795fc1984d Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 16 Sep 2024 17:45:06 -0700 Subject: [PATCH 0815/1908] Global Styles: Update REST controller override method and backport changes from Core (#65259) Global Styles: Update REST controller override method: Update unit tests; Update class with Core's WP_REST_Global_Styles_Controller; Inherit WP_REST_Posts_Controller, make methods public et. al; Add 6.6+ post args to register post filter; Overwrite Core endpoints with $override when registering routes. --------- Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: spacedmonkey <spacedmonkey@git.wordpress.org> --- ...est-global-styles-controller-gutenberg.php | 163 ++++++------------ lib/rest-api.php | 22 ++- ...lobal-styles-controller-gutenberg-test.php | 8 +- 3 files changed, 79 insertions(+), 114 deletions(-) diff --git a/lib/class-wp-rest-global-styles-controller-gutenberg.php b/lib/class-wp-rest-global-styles-controller-gutenberg.php index 421408e6f20b4a..e33304e596e129 100644 --- a/lib/class-wp-rest-global-styles-controller-gutenberg.php +++ b/lib/class-wp-rest-global-styles-controller-gutenberg.php @@ -13,25 +13,30 @@ /** * Base Global Styles REST API Controller. */ -class WP_REST_Global_Styles_Controller_Gutenberg extends WP_REST_Controller { +class WP_REST_Global_Styles_Controller_Gutenberg extends WP_REST_Posts_Controller { /** - * Post type. + * Whether the controller supports batching. * - * @since 5.9.0 - * @var string + * @since 6.6.0 + * @var array */ - protected $post_type; + protected $allow_batch = array( 'v1' => false ); /** * Constructor. * * @since 5.9.0 */ - public function __construct() { - $this->namespace = 'wp/v2'; - $this->rest_base = 'global-styles'; - $this->post_type = 'wp_global_styles'; + /** + * Constructor. + * + * @since 6.6.0 + * + * @param string $post_type Post type. + */ + public function __construct( $post_type = 'wp_global_styles' ) { + parent::__construct( $post_type ); } /** @@ -54,8 +59,14 @@ public function register_routes() { 'type' => 'string', ), ), + 'allow_batch' => $this->allow_batch, ), - ) + ), + /* + * $override is set to true to avoid conflicts with the core endpoint. + * Do not sync to WordPress core. + */ + true ); // List themes global styles. @@ -65,8 +76,10 @@ public function register_routes() { sprintf( '/%s/themes/(?P<stylesheet>%s)', $this->rest_base, - // Matches theme's directory: `/themes/<subdirectory>/<theme>/` or `/themes/<theme>/`. - // Excludes invalid directory name characters: `/:<>*?"|`. + /* + * Matches theme's directory: `/themes/<subdirectory>/<theme>/` or `/themes/<theme>/`. + * Excludes invalid directory name characters: `/:<>*?"|`. + */ '[^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?' ), array( @@ -81,8 +94,14 @@ public function register_routes() { 'sanitize_callback' => array( $this, '_sanitize_global_styles_callback' ), ), ), + 'allow_batch' => $this->allow_batch, ), - ) + ), + /* + * $override is set to true to avoid conflicts with the core endpoint. + * Do not sync to WordPress core. + */ + true ); // Lists/updates a single global style variation based on the given id. @@ -108,8 +127,14 @@ public function register_routes() { 'permission_callback' => array( $this, 'update_item_permissions_check' ), 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) + 'schema' => array( $this, 'get_public_item_schema' ), + 'allow_batch' => $this->allow_batch, + ), + /* + * $override is set to true to avoid conflicts with the core endpoint. + * Do not sync to WordPress core. + */ + true ); } @@ -196,28 +221,10 @@ public function get_item_permissions_check( $request ) { * @param WP_Post $post Post object. * @return bool Whether the post can be read. */ - protected function check_read_permission( $post ) { + public function check_read_permission( $post ) { return current_user_can( 'read_post', $post->ID ); } - /** - * Returns the given global styles config. - * - * @since 5.9.0 - * - * @param WP_REST_Request $request The request instance. - * - * @return WP_REST_Response|WP_Error - */ - public function get_item( $request ) { - $post = $this->get_post( $request['id'] ); - if ( is_wp_error( $post ) ) { - return $post; - } - - return $this->prepare_item_for_response( $post, $request ); - } - /** * Checks if a given request has access to write a single global styles config. * @@ -243,61 +250,12 @@ public function update_item_permissions_check( $request ) { return true; } - /** - * Checks if a global style can be edited. - * - * @since 5.9.0 - * - * @param WP_Post $post Post object. - * @return bool Whether the post can be edited. - */ - protected function check_update_permission( $post ) { - return current_user_can( 'edit_post', $post->ID ); - } - - /** - * Updates a single global style config. - * - * @since 5.9.0 - * @since 6.2.0 Added validation of styles.css property. - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function update_item( $request ) { - $post_before = $this->get_post( $request['id'] ); - if ( is_wp_error( $post_before ) ) { - return $post_before; - } - - $changes = $this->prepare_item_for_database( $request ); - if ( is_wp_error( $changes ) ) { - return $changes; - } - - $result = wp_update_post( wp_slash( (array) $changes ), true, false ); - if ( is_wp_error( $result ) ) { - return $result; - } - - $post = get_post( $request['id'] ); - $fields_update = $this->update_additional_fields_for_object( $post, $request ); - if ( is_wp_error( $fields_update ) ) { - return $fields_update; - } - - wp_after_insert_post( $post, true, $post_before ); - - $response = $this->prepare_item_for_response( $post, $request ); - - return rest_ensure_response( $response ); - } - /** * Prepares a single global styles config for update. * * @since 5.9.0 * @since 6.2.0 Added validation of styles.css property. + * @since 6.6.0 Added registration of block style variations from theme.json sources (theme.json, user theme.json, partials). * * @param WP_REST_Request $request Request object. * @return stdClass|WP_Error Prepared item on success. WP_Error on when the custom CSS is not valid. @@ -394,10 +352,12 @@ public function prepare_item_for_response( $post, $request ) { // phpcs:ignore V } if ( rest_is_field_included( 'title.rendered', $fields ) ) { add_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); + add_filter( 'private_title_format', array( $this, 'protected_title_format' ) ); $data['title']['rendered'] = get_the_title( $post->ID ); remove_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); + remove_filter( 'private_title_format', array( $this, 'protected_title_format' ) ); } if ( rest_is_field_included( 'settings', $fields ) ) { @@ -426,7 +386,7 @@ public function prepare_item_for_response( $post, $request ) { // phpcs:ignore V } $response->add_links( $links ); if ( ! empty( $links['self']['href'] ) ) { - $actions = $this->get_available_actions(); + $actions = $this->get_available_actions( $post, $request ); $self = $links['self']['href']; foreach ( $actions as $rel ) { $response->add_link( $rel, $self ); @@ -450,9 +410,12 @@ protected function prepare_links( $id ) { $base = sprintf( '%s/%s', $this->namespace, $this->rest_base ); $links = array( - 'self' => array( + 'self' => array( 'href' => rest_url( trailingslashit( $base ) . $id ), ), + 'about' => array( + 'href' => rest_url( 'wp/v2/types/' . $this->post_type ), + ), ); if ( post_type_supports( $this->post_type, 'revisions' ) ) { @@ -473,13 +436,16 @@ protected function prepare_links( $id ) { * * @since 5.9.0 * @since 6.2.0 Added 'edit-css' action. + * @since 6.6.0 Added $post and $request parameters. * + * @param WP_Post $post Post object. + * @param WP_REST_Request $request Request object. * @return array List of link relations. */ - protected function get_available_actions() { + protected function get_available_actions( $post, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable $rels = array(); - $post_type = get_post_type_object( $this->post_type ); + $post_type = get_post_type_object( $post->post_type ); if ( current_user_can( $post_type->cap->publish_posts ) ) { $rels[] = 'https://api.w.org/action-publish'; } @@ -491,21 +457,6 @@ protected function get_available_actions() { return $rels; } - /** - * Overwrites the default protected title format. - * - * By default, WordPress will show password protected posts with a title of - * "Protected: %s", as the REST API communicates the protected status of a post - * in a machine readable format, we remove the "Protected: " prefix. - * - * @since 5.9.0 - * - * @return string Protected title format. - */ - public function protected_title_format() { - return '%s'; - } - /** * Retrieves the query params for the global styles collection. * @@ -589,7 +540,7 @@ public function get_theme_item_permissions_check( $request ) { // phpcs:ignore V /* * Verify if the current user has edit_theme_options capability. - * This capability is required to edit/view/delete templates. + * This capability is required to edit/view/delete global styles. */ if ( ! current_user_can( 'edit_theme_options' ) ) { return new WP_Error( @@ -623,8 +574,8 @@ public function get_theme_item( $request ) { } $theme = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( 'theme' ); - $data = array(); $fields = $this->get_fields_for_response( $request ); + $data = array(); if ( rest_is_field_included( 'settings', $fields ) ) { $data['settings'] = $theme->get_settings(); @@ -669,7 +620,7 @@ public function get_theme_items_permissions_check( $request ) { // phpcs:ignore /* * Verify if the current user has edit_theme_options capability. - * This capability is required to edit/view/delete templates. + * This capability is required to edit/view/delete global styles. */ if ( ! current_user_can( 'edit_theme_options' ) ) { return new WP_Error( diff --git a/lib/rest-api.php b/lib/rest-api.php index 0becbc4a72d356..ac020e243ec056 100644 --- a/lib/rest-api.php +++ b/lib/rest-api.php @@ -11,14 +11,24 @@ } /** - * Registers the Global Styles REST API routes. + * Overrides the REST controller for the `wp_global_styles` post type. + * + * @param array $args Array of arguments for registering a post type. + * See the register_post_type() function for accepted arguments. + * @param string $post_type Post type key. + * + * @return array Array of arguments for registering a post type. */ -function gutenberg_register_global_styles_endpoints() { - $global_styles_controller = new WP_REST_Global_Styles_Controller_Gutenberg(); - $global_styles_controller->register_routes(); -} -add_action( 'rest_api_init', 'gutenberg_register_global_styles_endpoints' ); +function gutenberg_override_global_styles_endpoint( array $args ): array { + $args['rest_controller_class'] = 'WP_REST_Global_Styles_Controller_Gutenberg'; + $args['revisions_rest_controller_class'] = 'Gutenberg_REST_Global_Styles_Revisions_Controller_6_6'; + $args['late_route_registration'] = true; + $args['show_in_rest'] = true; + $args['rest_base'] = 'global-styles'; + return $args; +} +add_filter( 'register_wp_global_styles_post_type_args', 'gutenberg_override_global_styles_endpoint', 10, 2 ); /** * Registers the Edit Site Export REST API routes. diff --git a/phpunit/class-wp-rest-global-styles-controller-gutenberg-test.php b/phpunit/class-wp-rest-global-styles-controller-gutenberg-test.php index 3fd0bb21ce562b..85731a7dff5206 100644 --- a/phpunit/class-wp-rest-global-styles-controller-gutenberg-test.php +++ b/phpunit/class-wp-rest-global-styles-controller-gutenberg-test.php @@ -79,6 +79,10 @@ public static function wpTearDownAfterClass() { * @covers WP_REST_Global_Styles_Controller_Gutenberg::register_routes */ public function test_register_routes() { + // Register routes so that they overwrite identical Core routes. + $global_styles_controller = new WP_REST_Global_Styles_Controller_Gutenberg(); + $global_styles_controller->register_routes(); + $routes = rest_get_server()->get_routes(); $this->assertArrayHasKey( '/wp/v2/global-styles/(?P<id>[\/\w-]+)', @@ -86,7 +90,7 @@ public function test_register_routes() { 'Single global style based on the given ID route does not exist' ); $this->assertCount( - 4, // Double core because both sets get registered in the plugin. + 2, $routes['/wp/v2/global-styles/(?P<id>[\/\w-]+)'], 'Single global style based on the given ID route does not have exactly two elements' ); @@ -96,7 +100,7 @@ public function test_register_routes() { 'Theme global styles route does not exist' ); $this->assertCount( - 2, // Double core because both sets get registered in the plugin. + 1, $routes['/wp/v2/global-styles/themes/(?P<stylesheet>[^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)'], 'Theme global styles route does not have exactly one element' ); From d32a5b627fd083360b94885d9ba08d452afa7f3f Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 17 Sep 2024 11:04:05 +0900 Subject: [PATCH 0816/1908] BoxControl: Add lint rule for 40px size prop usage (#65341) * BoxControl: Add lint rule for 40px size prop usage * Add to readme Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .eslintrc.js | 1 + packages/components/src/box-control/README.md | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index b5349d2de0a1ff..2e92b495691873 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -321,6 +321,7 @@ module.exports = { ...[ 'BorderBoxControl', 'BorderControl', + 'BoxControl', 'ComboboxControl', 'CustomSelectControl', 'DimensionControl', diff --git a/packages/components/src/box-control/README.md b/packages/components/src/box-control/README.md index 2fd214b79157f7..b03b03a85466ae 100644 --- a/packages/components/src/box-control/README.md +++ b/packages/components/src/box-control/README.md @@ -100,3 +100,10 @@ A handler for onMouseOver events. A handler for onMouseOut events. - Required: No + +### `__next40pxDefaultSize`: `boolean` + +Start opting into the larger default size that will become the default size in a future version. + +- Required: No +- Default: `false` From 5b037d7afddae7b4af7301d5dd0ace967e64a73b Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 17 Sep 2024 11:06:33 +0900 Subject: [PATCH 0817/1908] ButtonGroup: Fix story to show what the component does (#65336) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../src/button-group/stories/index.story.tsx | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/packages/components/src/button-group/stories/index.story.tsx b/packages/components/src/button-group/stories/index.story.tsx index 958a0d137763e9..f6af2416977f40 100644 --- a/packages/components/src/button-group/stories/index.story.tsx +++ b/packages/components/src/button-group/stories/index.story.tsx @@ -1,7 +1,7 @@ /** * External dependencies */ -import type { Meta, StoryFn } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react'; /** * Internal dependencies @@ -22,18 +22,13 @@ const meta: Meta< typeof ButtonGroup > = { }; export default meta; -const Template: StoryFn< typeof ButtonGroup > = ( args ) => { - const style = { margin: '0 4px' }; - return ( - <ButtonGroup { ...args }> - <Button variant="primary" style={ style }> - Button 1 - </Button> - <Button variant="primary" style={ style }> - Button 2 - </Button> - </ButtonGroup> - ); +export const Default: StoryObj< typeof ButtonGroup > = { + args: { + children: ( + <> + <Button variant="primary">Button 1</Button> + <Button>Button 2</Button> + </> + ), + }, }; - -export const Default: StoryFn< typeof ButtonGroup > = Template.bind( {} ); From 1a23ed6b08b4e7204ac02592c6a137f6edd8d84c Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Tue, 17 Sep 2024 12:52:19 +1000 Subject: [PATCH 0818/1908] Image cropping: skip making an API request if there are no changes to apply (#65384) Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- .../src/components/image-editor/use-save-image.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/block-editor/src/components/image-editor/use-save-image.js b/packages/block-editor/src/components/image-editor/use-save-image.js index ff91a9794ca158..094ce1600545b5 100644 --- a/packages/block-editor/src/components/image-editor/use-save-image.js +++ b/packages/block-editor/src/components/image-editor/use-save-image.js @@ -54,6 +54,13 @@ export default function useSaveImage( { } ); } + if ( modifiers.length === 0 ) { + // No changes to apply. + setIsInProgress( false ); + onFinishEditing(); + return; + } + apiFetch( { path: `/wp/v2/media/${ id }/edit`, method: 'POST', From f82bc32212f2708851bd10e3c2d803994cd3cb3c Mon Sep 17 00:00:00 2001 From: Akshat Kakkad <87222220+AKSHAT2802@users.noreply.github.com> Date: Tue, 17 Sep 2024 10:25:33 +0530 Subject: [PATCH 0819/1908] Add __next40pxDefaultSize for files in editor 3 (#65139) * Add __next40pxDefaultSize for files in editor 3 * Address feedback * change font size to 13 px * Revert classic-theme.js changes as it will be a seperate PR and revert 13px size in style as it is default * Wrap copy button in InputControlSuffixWrapper Co-authored-by: AKSHAT2802 <akshat2802@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../hierarchical-term-selector.js | 3 +-- .../post-taxonomies/most-used-terms.js | 3 +-- .../src/components/post-taxonomies/style.scss | 4 ---- packages/editor/src/components/post-url/index.js | 16 +++++++++------- .../src/components/save-publish-panels/index.js | 8 ++------ 5 files changed, 13 insertions(+), 21 deletions(-) diff --git a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js index 4913cef9b4c86f..071453f4f3f626 100644 --- a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js +++ b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js @@ -428,8 +428,7 @@ export function HierarchicalTermSelector( { slug } ) { { ! loading && hasCreateAction && ( <FlexItem> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize onClick={ onToggleForm } className="editor-post-taxonomies__hierarchical-terms-add" aria-expanded={ showForm } diff --git a/packages/editor/src/components/post-taxonomies/most-used-terms.js b/packages/editor/src/components/post-taxonomies/most-used-terms.js index e42337b54e444f..639e5752c80013 100644 --- a/packages/editor/src/components/post-taxonomies/most-used-terms.js +++ b/packages/editor/src/components/post-taxonomies/most-used-terms.js @@ -62,8 +62,7 @@ export default function MostUsedTerms( { onSelect, taxonomy } ) { { terms.map( ( term ) => ( <li key={ term.id }> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="link" onClick={ () => onSelect( term ) } > diff --git a/packages/editor/src/components/post-taxonomies/style.scss b/packages/editor/src/components/post-taxonomies/style.scss index ce912573c79488..2d888baee04131 100644 --- a/packages/editor/src/components/post-taxonomies/style.scss +++ b/packages/editor/src/components/post-taxonomies/style.scss @@ -34,8 +34,4 @@ display: inline-block; margin-right: $grid-unit-10; } - - .components-button { - font-size: 12px; - } } diff --git a/packages/editor/src/components/post-url/index.js b/packages/editor/src/components/post-url/index.js index 5ed3155388c8cc..8d072fa2eeb5d2 100644 --- a/packages/editor/src/components/post-url/index.js +++ b/packages/editor/src/components/post-url/index.js @@ -11,6 +11,7 @@ import { Button, __experimentalInputControl as InputControl, __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper, + __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper, __experimentalVStack as VStack, } from '@wordpress/components'; import { store as noticesStore } from '@wordpress/notices'; @@ -109,13 +110,14 @@ export default function PostURL( { onClose } ) { </InputControlPrefixWrapper> } suffix={ - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - icon={ copySmall } - ref={ copyButtonRef } - label={ __( 'Copy' ) } - /> + <InputControlSuffixWrapper variant="control"> + <Button + icon={ copySmall } + ref={ copyButtonRef } + size="small" + label="Copy" + /> + </InputControlSuffixWrapper> } label={ __( 'Link' ) } hideLabelFromVision diff --git a/packages/editor/src/components/save-publish-panels/index.js b/packages/editor/src/components/save-publish-panels/index.js index d559f13fd96a45..d95d9f35928906 100644 --- a/packages/editor/src/components/save-publish-panels/index.js +++ b/packages/editor/src/components/save-publish-panels/index.js @@ -71,10 +71,8 @@ export default function SavePublishPanels( { unmountableContent = ( <div className="editor-layout__toggle-publish-panel"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="secondary" - className="editor-layout__toggle-publish-panel-button" onClick={ togglePublishSidebar } aria-expanded={ false } > @@ -86,10 +84,8 @@ export default function SavePublishPanels( { unmountableContent = ( <div className="editor-layout__toggle-entities-saved-states-panel"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="secondary" - className="editor-layout__toggle-entities-saved-states-panel-button" onClick={ openEntitiesSavedStates } aria-expanded={ false } disabled={ ! isDirty } From 3a2f74f8449460cdf842a368ea369d5abdc978e0 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 17 Sep 2024 10:06:49 +0200 Subject: [PATCH 0820/1908] Rename edit-post__fade-in-animation and unify keyframe definitions (#65377) * Remove duplicate keyframe definition across packages * Deprecate edit-post__fade-in-animation, replace with animation__fade-in * Add animation__fade-out mixin --- packages/base-styles/_animations.scss | 42 ++++++++++++++++++- .../src/components/list-view/style.scss | 2 +- .../src/utils/test/transform-styles.js | 2 +- packages/components/src/modal/style.scss | 4 +- packages/edit-post/src/style.scss | 16 ------- packages/edit-site/src/style.scss | 16 ------- .../playground/fullpage/style.lazy.scss | 16 ------- 7 files changed, 44 insertions(+), 54 deletions(-) diff --git a/packages/base-styles/_animations.scss b/packages/base-styles/_animations.scss index ce1f935b7d4d5b..8706d185aa221b 100644 --- a/packages/base-styles/_animations.scss +++ b/packages/base-styles/_animations.scss @@ -1,5 +1,37 @@ -@mixin edit-post__fade-in-animation($speed: 0.08s, $delay: 0s) { - animation: edit-post__fade-in-animation $speed linear $delay; +@mixin keyframes($name) { + @keyframes #{$name} { + @content; + } +} + +@mixin animation__fade-in($speed: 0.08s, $delay: 0s) { + @include keyframes(__wp-base-styles-fade-in) { + from { + opacity: 0; + } + to { + opacity: 1; + } + } + + + animation: __wp-base-styles-fade-in $speed linear $delay; + animation-fill-mode: forwards; + @include reduce-motion("animation"); +} + +@mixin animation__fade-out($speed: 0.08s, $delay: 0s) { + @include keyframes(__wp-base-styles-fade-out) { + from { + opacity: 1; + } + to { + opacity: 0; + } + } + + + animation: __wp-base-styles-fade-out $speed linear $delay; animation-fill-mode: forwards; @include reduce-motion("animation"); } @@ -8,3 +40,9 @@ transition: all 0.5s cubic-bezier(0.65, 0, 0.45, 1); @include reduce-motion("transition"); } + +// Deprecated +@mixin edit-post__fade-in-animation($speed: 0.08s, $delay: 0s) { + @warn "The `edit-post__fade-in-animation` mixin is deprecated. Use `animation__fade-in` instead."; + @include animation__fade-in($speed, $delay); +} diff --git a/packages/block-editor/src/components/list-view/style.scss b/packages/block-editor/src/components/list-view/style.scss index 3d25597d2af904..05a04abfd110b4 100644 --- a/packages/block-editor/src/components/list-view/style.scss +++ b/packages/block-editor/src/components/list-view/style.scss @@ -272,7 +272,7 @@ &.is-visible .block-editor-list-view-block-contents { opacity: 1; - @include edit-post__fade-in-animation; + @include animation__fade-in; } .block-editor-block-icon { diff --git a/packages/block-editor/src/utils/test/transform-styles.js b/packages/block-editor/src/utils/test/transform-styles.js index 3a68cc63c248ec..efe92cea63d0ff 100644 --- a/packages/block-editor/src/utils/test/transform-styles.js +++ b/packages/block-editor/src/utils/test/transform-styles.js @@ -293,7 +293,7 @@ describe( 'transformStyles', () => { it( 'should ignore keyframes', () => { const input = ` - @keyframes edit-post__fade-in-animation { + @keyframes __wp-base-styles-fade-in { from { opacity: 0; } diff --git a/packages/components/src/modal/style.scss b/packages/components/src/modal/style.scss index 8c7c8416f0190b..3790e0b7368a64 100644 --- a/packages/components/src/modal/style.scss +++ b/packages/components/src/modal/style.scss @@ -8,8 +8,8 @@ background-color: rgba($black, 0.35); z-index: z-index(".components-modal__screen-overlay"); display: flex; - // This animates the appearance of the white background. - @include edit-post__fade-in-animation(); + // This animates the appearance of the backdrop. + @include animation__fade-in(); } // The modal window element. diff --git a/packages/edit-post/src/style.scss b/packages/edit-post/src/style.scss index f77c8122ca2e55..7230d7b2b15e66 100644 --- a/packages/edit-post/src/style.scss +++ b/packages/edit-post/src/style.scss @@ -3,22 +3,6 @@ @import "./components/meta-boxes/meta-boxes-area/style.scss"; @import "./components/welcome-guide/style.scss"; -/** - * Animations - */ - -// These keyframes should not be part of the _animations.scss mixins file. -// Because keyframe animations can't be defined as mixins properly, they are duplicated. -// Since hey are intended only for the editor, we add them here instead. -@keyframes edit-post__fade-in-animation { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - body.js.block-editor-page { @include wp-admin-reset( ".block-editor" ); } diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 473deaeedc5908..4e9e1071e3a77a 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -91,20 +91,4 @@ body.js.site-editor-php { } } -/** - * Animations - */ - -// These keyframes should not be part of the _animations.scss mixins file. -// Because keyframe animations can't be defined as mixins properly, they are duplicated. -// Since they are intended only for the editor, we add them here instead. -@keyframes edit-post__fade-in-animation { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - @include wordpress-admin-schemes(); diff --git a/storybook/stories/playground/fullpage/style.lazy.scss b/storybook/stories/playground/fullpage/style.lazy.scss index 6d28c1d3c81635..0249011c3e960e 100644 --- a/storybook/stories/playground/fullpage/style.lazy.scss +++ b/storybook/stories/playground/fullpage/style.lazy.scss @@ -46,19 +46,3 @@ display: block; } } - -/** - * Animations - */ - -// These keyframes should not be part of the _animations.scss mixins file. -// Because keyframe animations can't be defined as mixins properly, they are duplicated. -// Since hey are intended only for the editor, we add them here instead. -@keyframes edit-post__fade-in-animation { - from { - opacity: 0; - } - to { - opacity: 1; - } -} From 524516dec6dcc0044fa795b7fd73c2caea3692ae Mon Sep 17 00:00:00 2001 From: dhruvang21 <105810308+dhruvang21@users.noreply.github.com> Date: Tue, 17 Sep 2024 13:56:26 +0530 Subject: [PATCH 0821/1908] Add __next40pxDefaultSize for edit-widgets files (#65367) --- .../edit-widgets/src/components/error-boundary/index.js | 7 +------ .../src/components/secondary-sidebar/inserter-sidebar.js | 3 +-- .../src/components/secondary-sidebar/list-view-sidebar.js | 3 +-- .../edit-widgets/src/components/sidebar/widget-areas.js | 3 +-- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/edit-widgets/src/components/error-boundary/index.js b/packages/edit-widgets/src/components/error-boundary/index.js index e6ed91926da3ef..ff12bfe5fdf478 100644 --- a/packages/edit-widgets/src/components/error-boundary/index.js +++ b/packages/edit-widgets/src/components/error-boundary/index.js @@ -11,12 +11,7 @@ import { doAction } from '@wordpress/hooks'; function CopyButton( { text, children } ) { const ref = useCopyToClipboard( text ); return ( - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - variant="secondary" - ref={ ref } - > + <Button __next40pxDefaultSize variant="secondary" ref={ ref }> { children } </Button> ); diff --git a/packages/edit-widgets/src/components/secondary-sidebar/inserter-sidebar.js b/packages/edit-widgets/src/components/secondary-sidebar/inserter-sidebar.js index 085ca38a3e182a..156a15e2f460ca 100644 --- a/packages/edit-widgets/src/components/secondary-sidebar/inserter-sidebar.js +++ b/packages/edit-widgets/src/components/secondary-sidebar/inserter-sidebar.js @@ -44,8 +44,7 @@ export default function InserterSidebar() { > <TagName className="edit-widgets-layout__inserter-panel-header"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize icon={ close } onClick={ closeInserter } label={ __( 'Close block inserter' ) } diff --git a/packages/edit-widgets/src/components/secondary-sidebar/list-view-sidebar.js b/packages/edit-widgets/src/components/secondary-sidebar/list-view-sidebar.js index 9822f3ff00bc74..1bb850393ad023 100644 --- a/packages/edit-widgets/src/components/secondary-sidebar/list-view-sidebar.js +++ b/packages/edit-widgets/src/components/secondary-sidebar/list-view-sidebar.js @@ -51,8 +51,7 @@ export default function ListViewSidebar() { <div className="edit-widgets-editor__list-view-panel-header"> <strong>{ __( 'List View' ) }</strong> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize icon={ closeSmall } label={ __( 'Close' ) } onClick={ closeListView } diff --git a/packages/edit-widgets/src/components/sidebar/widget-areas.js b/packages/edit-widgets/src/components/sidebar/widget-areas.js index 3bcba478eefe8e..c7b49c10b97464 100644 --- a/packages/edit-widgets/src/components/sidebar/widget-areas.js +++ b/packages/edit-widgets/src/components/sidebar/widget-areas.js @@ -66,8 +66,7 @@ export default function WidgetAreas( { selectedWidgetAreaId } ) { ) } { ! selectedWidgetArea && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize href={ addQueryArgs( 'customize.php', { 'autofocus[panel]': 'widgets', return: window.location.pathname, From afbb659ed61a07e0b8e98cdd57e64363d1d62910 Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Tue, 17 Sep 2024 13:48:05 +0200 Subject: [PATCH 0822/1908] Tabs: fix vertical indicator (#65385) * Fix vertical indicator * Add changelog entry Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/tabs/styles.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 1473cf5f5df40e..2f9f0fd03458ec 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -4,6 +4,7 @@ ### Bug Fixes +- `Tabs`: restore vertical indicator ([#65385](https://github.com/WordPress/gutenberg/pull/65385)). - `Tabs`: indicator positioning under RTL direction ([#64926](https://github.com/WordPress/gutenberg/pull/64926)). - `Popover`: Update `toolbar` variant radius to match block toolbar ([#65263](https://github.com/WordPress/gutenberg/pull/65263)). diff --git a/packages/components/src/tabs/styles.ts b/packages/components/src/tabs/styles.ts index a6425f9ab31e45..c00943b180f637 100644 --- a/packages/components/src/tabs/styles.ts +++ b/packages/components/src/tabs/styles.ts @@ -76,7 +76,7 @@ export const TabListWrapper = styled.div` top: 0; left: 0; width: 100%; - width: calc( var( --antialiasing-factor ) * 1px ); + height: calc( var( --antialiasing-factor ) * 1px ); transform: translateY( calc( var( --indicator-top ) * 1px ) ) scaleY( calc( var( --indicator-height ) / var( --antialiasing-factor ) ) From 99fefd79c2644f65fb885fad82e0c11e7593eca0 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:59:21 +0900 Subject: [PATCH 0823/1908] Don't force iframe editor when gutenberg plugin and block theme are enabled (#65372) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> --- .../components/layout/use-should-iframe.js | 43 +++++++------------ 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/packages/edit-post/src/components/layout/use-should-iframe.js b/packages/edit-post/src/components/layout/use-should-iframe.js index e36a4773c4a1fd..9fed30c07b37e3 100644 --- a/packages/edit-post/src/components/layout/use-should-iframe.js +++ b/packages/edit-post/src/components/layout/use-should-iframe.js @@ -6,33 +6,22 @@ import { useSelect } from '@wordpress/data'; import { store as blocksStore } from '@wordpress/blocks'; import { store as blockEditorStore } from '@wordpress/block-editor'; -const isGutenbergPlugin = globalThis.IS_GUTENBERG_PLUGIN ? true : false; - export function useShouldIframe() { - const { - isBlockBasedTheme, - hasV3BlocksOnly, - isEditingTemplate, - isZoomOutMode, - } = useSelect( ( select ) => { - const { getEditorSettings, getCurrentPostType } = select( editorStore ); - const { __unstableGetEditorMode } = select( blockEditorStore ); - const { getBlockTypes } = select( blocksStore ); - const editorSettings = getEditorSettings(); - return { - isBlockBasedTheme: editorSettings.__unstableIsBlockBasedTheme, - hasV3BlocksOnly: getBlockTypes().every( ( type ) => { - return type.apiVersion >= 3; - } ), - isEditingTemplate: getCurrentPostType() === 'wp_template', - isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', - }; - }, [] ); - - return ( - hasV3BlocksOnly || - ( isGutenbergPlugin && isBlockBasedTheme ) || - isEditingTemplate || - isZoomOutMode + const { hasV3BlocksOnly, isEditingTemplate, isZoomOutMode } = useSelect( + ( select ) => { + const { getCurrentPostType } = select( editorStore ); + const { __unstableGetEditorMode } = select( blockEditorStore ); + const { getBlockTypes } = select( blocksStore ); + return { + hasV3BlocksOnly: getBlockTypes().every( ( type ) => { + return type.apiVersion >= 3; + } ), + isEditingTemplate: getCurrentPostType() === 'wp_template', + isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', + }; + }, + [] ); + + return hasV3BlocksOnly || isEditingTemplate || isZoomOutMode; } From be8f9b62dbab28974f84c438a27d26880abb5e7a Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini <26530524+zaguiini@users.noreply.github.com> Date: Tue, 17 Sep 2024 09:17:05 -0300 Subject: [PATCH 0824/1908] Combobox Control: Add placeholder attribute (#65254) * Combobox Control: Add placeholder attribute * Remove placeholder from default story * Change placeholder type description and add it to README * Add CHANGELOG entry --- packages/components/CHANGELOG.md | 1 + packages/components/src/combobox-control/README.md | 7 +++++++ packages/components/src/combobox-control/index.tsx | 2 ++ packages/components/src/combobox-control/types.ts | 4 ++++ 4 files changed, 14 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 2f9f0fd03458ec..8d9ee39833577b 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -15,6 +15,7 @@ ### New Features - `Composite`: add stable version of the component ([#63569](https://github.com/WordPress/gutenberg/pull/63569)). +- `ComboboxControl`: add support for `placeholder` attribute ([#65254](https://github.com/WordPress/gutenberg/pull/65254)). ### Enhancements diff --git a/packages/components/src/combobox-control/README.md b/packages/components/src/combobox-control/README.md index 61611f82fee233..5831c5ec2832c2 100644 --- a/packages/components/src/combobox-control/README.md +++ b/packages/components/src/combobox-control/README.md @@ -111,6 +111,13 @@ If the control is clicked, the dropdown will expand regardless of this prop. - Required: No - Default: `true` +### placeholder + +If passed, the combobox input will show a placeholder string if no values are present. + +- Type: `string` +- Required: No + #### __experimentalRenderItem Custom renderer invoked for each option in the suggestion list. The render prop receives as its argument an object containing, under the `item` key, the single option's data (directly from the array of data passed to the `options` prop). diff --git a/packages/components/src/combobox-control/index.tsx b/packages/components/src/combobox-control/index.tsx index fc3ecccf0b6599..5c6725a51b435d 100644 --- a/packages/components/src/combobox-control/index.tsx +++ b/packages/components/src/combobox-control/index.tsx @@ -129,6 +129,7 @@ function ComboboxControl( props: ComboboxControlProps ) { }, __experimentalRenderItem, expandOnFocus = true, + placeholder, } = useDeprecated36pxDefaultSizeProp( props ); const [ value, setValue ] = useControlledValue( { @@ -340,6 +341,7 @@ function ComboboxControl( props: ComboboxControlProps ) { className="components-combobox-control__input" instanceId={ instanceId } ref={ inputContainer } + placeholder={ placeholder } value={ isExpanded ? inputValue : currentLabel } onFocus={ onFocus } onBlur={ onBlur } diff --git a/packages/components/src/combobox-control/types.ts b/packages/components/src/combobox-control/types.ts index 10adf8c0ff0ef6..470b38c35e2c8a 100644 --- a/packages/components/src/combobox-control/types.ts +++ b/packages/components/src/combobox-control/types.ts @@ -82,4 +82,8 @@ export type ComboboxControlProps = Pick< * The current value of the control. */ value?: string | null; + /** + * If passed, the combobox input will show a placeholder string if no values are present. + */ + placeholder?: string; }; From 05660fe9b2abf4e0f1cd74e9821cb7742772e327 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Tue, 17 Sep 2024 15:33:11 +0200 Subject: [PATCH 0825/1908] a11y: Print script module live regions in page HTML (#65380) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix issues where @wordpress/a11y script module `speak` may not be detected and announced by accessibility software, in particular when dynamically loading the module. Accessibility software needs to detect the live regions in order to announce them. The `@wordpress/a11y` script module was adding the live regions to the DOM correctly when the module was loaded, but when loaded dynamically (via `import( '@wordpress/a11y' ).then( /*…*/ )` ) the live region changes would happen before the live region was detected by accessibility software and the announcements would not happen. The `@wordpress/a11y` script module is updated so that it does not inject the live regions into the DOM but expects them to be present on the page. A hook is added to inject the necessary HTML for the live regions when the @wordpress/a11y script module may be present (enqueued or in the import map). This has a few additional advantages: - Accessibility software correctly detects the live regions. - The DOM does not need to be modified immediately on page load. - The (gzipped) size of the script module is reduced by 416B (~46%). The `wp-a11y` script shares the same DOM elements. It includes protection to prevent injecting duplicate elements. --- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- lib/experimental/script-modules.php | 49 ++++++++++++++++--- packages/a11y/src/index.js | 25 ++++++++-- packages/a11y/src/module/index.ts | 22 ++------- .../src/{shared => script}/add-container.js | 0 .../src/{shared => script}/add-intro-text.ts | 10 ++-- .../test/add-container.test.js | 0 packages/a11y/src/shared/index.js | 28 ----------- 7 files changed, 75 insertions(+), 59 deletions(-) rename packages/a11y/src/{shared => script}/add-container.js (100%) rename packages/a11y/src/{shared => script}/add-intro-text.ts (83%) rename packages/a11y/src/{shared => script}/test/add-container.test.js (100%) diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index a113df02b9d758..f65bc1704dd890 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -201,6 +201,45 @@ function gutenberg_dequeue_module( $module_identifier ) { wp_script_modules()->dequeue( $module_identifier ); } +/** + * Prints HTML for the a11y Script Module. + * + * a11y relies on some DOM elements to use as ARIA live regions. + * Ideally, these elements are part of the initial HTML of the page + * so that accessibility tools can find them and observe updates. + */ +function gutenberg_a11y_script_module_html() { + $a11y_module_available = false; + + $get_marked_for_enqueue = new ReflectionMethod( 'WP_Script_Modules', 'get_marked_for_enqueue' ); + $get_marked_for_enqueue->setAccessible( true ); + $get_import_map = new ReflectionMethod( 'WP_Script_Modules', 'get_import_map' ); + $get_import_map->setAccessible( true ); + + foreach ( array_keys( $get_marked_for_enqueue->invoke( wp_script_modules() ) ) as $id ) { + if ( '@wordpress/a11y' === $id ) { + $a11y_module_available = true; + break; + } + } + if ( ! $a11y_module_available ) { + foreach ( array_keys( $get_import_map->invoke( wp_script_modules() )['imports'] ) as $id ) { + if ( '@wordpress/a11y' === $id ) { + $a11y_module_available = true; + break; + } + } + } + if ( ! $a11y_module_available ) { + return; + } + echo '<div style="position:absolute;margin:-1px;padding:0;height:1px;width:1px;overflow:hidden;clip-path:inset(50%);border:0;word-wrap:normal !important;">' + . '<p id="a11y-speak-intro-text" class="a11y-speak-intro-text" hidden>' . esc_html__( 'Notifications', 'default' ) . '</p>' + . '<div id="a11y-speak-assertive" class="a11y-speak-region" aria-live="assertive" aria-relevant="additions text" aria-atomic="true"></div>' + . '<div id="a11y-speak-polite" class="a11y-speak-region" aria-live="polite" aria-relevant="additions text" aria-atomic="true"></div>' + . '</div>'; +} + /** * Registers Gutenberg Script Modules. * @@ -218,12 +257,8 @@ function gutenberg_register_script_modules() { array(), $default_version ); - add_filter( - 'script_module_data_@wordpress/a11y', - function ( $data ) { - $data['i18n'] = array( 'Notifications' => __( 'Notifications', 'default' ) ); - return $data; - } - ); + + add_action( 'wp_footer', 'gutenberg_a11y_script_module_html' ); + add_action( 'admin_footer', 'gutenberg_a11y_script_module_html' ); } add_action( 'init', 'gutenberg_register_script_modules' ); diff --git a/packages/a11y/src/index.js b/packages/a11y/src/index.js index 59e93da780bd81..cdc3be10545155 100644 --- a/packages/a11y/src/index.js +++ b/packages/a11y/src/index.js @@ -2,18 +2,37 @@ * WordPress dependencies */ import domReady from '@wordpress/dom-ready'; -import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import { makeSetupFunction } from './shared/index'; +import addContainer from './script/add-container'; +import addIntroText from './script/add-intro-text'; + export { speak } from './shared/index'; /** * Create the live regions. */ -export const setup = makeSetupFunction( __( 'Notifications' ) ); +export function setup() { + const introText = document.getElementById( 'a11y-speak-intro-text' ); + const containerAssertive = document.getElementById( + 'a11y-speak-assertive' + ); + const containerPolite = document.getElementById( 'a11y-speak-polite' ); + + if ( introText === null ) { + addIntroText(); + } + + if ( containerAssertive === null ) { + addContainer( 'assertive' ); + } + + if ( containerPolite === null ) { + addContainer( 'polite' ); + } +} /** * Run setup on domReady. diff --git a/packages/a11y/src/module/index.ts b/packages/a11y/src/module/index.ts index a2c87f397f4875..a06882f068dd3a 100644 --- a/packages/a11y/src/module/index.ts +++ b/packages/a11y/src/module/index.ts @@ -1,25 +1,11 @@ /** * Internal dependencies */ -import { makeSetupFunction } from '../shared/index'; export { speak } from '../shared/index'; -// Without an i18n Script Module, "Notifications" (the only localized text used in this module) -// will be translated on the server and provided as script-module data. -let notificationsText = 'Notifications'; -try { - const textContent = document.getElementById( - 'wp-script-module-data-@wordpress/a11y' - )?.textContent; - if ( textContent ) { - const parsed = JSON.parse( textContent ); - notificationsText = parsed?.i18n?.Notifications ?? notificationsText; - } -} catch {} - /** - * Create the live regions. + * This no-op function is exported to provide compatibility with the `wp-a11y` Script. + * + * Filters should inject the relevant HTML on page load instead of requiring setup. */ -export const setup = makeSetupFunction( notificationsText ); - -setup(); +export const setup = () => {}; diff --git a/packages/a11y/src/shared/add-container.js b/packages/a11y/src/script/add-container.js similarity index 100% rename from packages/a11y/src/shared/add-container.js rename to packages/a11y/src/script/add-container.js diff --git a/packages/a11y/src/shared/add-intro-text.ts b/packages/a11y/src/script/add-intro-text.ts similarity index 83% rename from packages/a11y/src/shared/add-intro-text.ts rename to packages/a11y/src/script/add-intro-text.ts index 6bd97c887664d3..2bcf453ec44c8e 100644 --- a/packages/a11y/src/shared/add-intro-text.ts +++ b/packages/a11y/src/script/add-intro-text.ts @@ -1,18 +1,22 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + /** * Build the explanatory text to be placed before the aria live regions. * * This text is initially hidden from assistive technologies by using a `hidden` * HTML attribute which is then removed once a message fills the aria-live regions. * - * @param {string} introTextContent The translated intro text content. * @return {HTMLParagraphElement} The explanatory text HTML element. */ -export default function addIntroText( introTextContent: string ) { +export default function addIntroText() { const introText = document.createElement( 'p' ); introText.id = 'a11y-speak-intro-text'; introText.className = 'a11y-speak-intro-text'; - introText.textContent = introTextContent; + introText.textContent = __( 'Notifications' ); introText.setAttribute( 'style', diff --git a/packages/a11y/src/shared/test/add-container.test.js b/packages/a11y/src/script/test/add-container.test.js similarity index 100% rename from packages/a11y/src/shared/test/add-container.test.js rename to packages/a11y/src/script/test/add-container.test.js diff --git a/packages/a11y/src/shared/index.js b/packages/a11y/src/shared/index.js index a05f891f428561..2b6353720d0add 100644 --- a/packages/a11y/src/shared/index.js +++ b/packages/a11y/src/shared/index.js @@ -1,37 +1,9 @@ /** * Internal dependencies */ -import addContainer from './add-container'; -import addIntroText from './add-intro-text'; import clear from './clear'; import filterMessage from './filter-message'; -/** - * Create the live regions. - * @param {string} introTextContent The intro text content. - */ -export function makeSetupFunction( introTextContent ) { - return function setup() { - const introText = document.getElementById( 'a11y-speak-intro-text' ); - const containerAssertive = document.getElementById( - 'a11y-speak-assertive' - ); - const containerPolite = document.getElementById( 'a11y-speak-polite' ); - - if ( introText === null ) { - addIntroText( introTextContent ); - } - - if ( containerAssertive === null ) { - addContainer( 'assertive' ); - } - - if ( containerPolite === null ) { - addContainer( 'polite' ); - } - }; -} - /** * Allows you to easily announce dynamic interface updates to screen readers using ARIA live regions. * This module is inspired by the `speak` function in `wp-a11y.js`. From 59595f6d0f44d7cce27c20df8f8b58a72f021afa Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Tue, 17 Sep 2024 15:54:27 +0200 Subject: [PATCH 0826/1908] Fix the shadows Range control accessibility and usability (#63908) * Use real labels instaed of headings or aria-labels. * Simplify by removing RangeControl. * Remove unnecessary HStack and className. * Remove no longer used hasNegativeRange prop. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../global-styles/shadows-edit-panel.js | 69 ++----------------- 1 file changed, 7 insertions(+), 62 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js index cf49d8c28ebcb9..ec1dd1a900c3bf 100644 --- a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js +++ b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js @@ -13,7 +13,6 @@ import { __experimentalItemGroup as ItemGroup, __experimentalInputControl as InputControl, __experimentalUnitControl as UnitControl, - __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, __experimentalGrid as Grid, __experimentalDropdownContentWrapper as DropdownContentWrapper, __experimentalUseNavigator as useNavigator, @@ -21,7 +20,6 @@ import { __experimentalToggleGroupControlOption as ToggleGroupControlOption, __experimentalConfirmDialog as ConfirmDialog, Dropdown, - RangeControl, Button, Flex, FlexItem, @@ -35,7 +33,6 @@ import { plus, shadow as shadowIcon, reset, - settings, moreVertical, } from '@wordpress/icons'; import { useState, useMemo } from '@wordpress/element'; @@ -51,7 +48,6 @@ import { getShadowParts, shadowStringToObject, shadowObjectToString, - CUSTOM_VALUE_SETTINGS, } from './shadow-utils'; const { useGlobalSetting } = unlock( blockEditorPrivateApis ); @@ -464,13 +460,11 @@ function ShadowPopover( { shadowObj, onChange } ) { <ShadowInputControl label={ __( 'X Position' ) } value={ shadowObj.x } - hasNegativeRange onChange={ ( value ) => onShadowChange( 'x', value ) } /> <ShadowInputControl label={ __( 'Y Position' ) } value={ shadowObj.y } - hasNegativeRange onChange={ ( value ) => onShadowChange( 'y', value ) } /> <ShadowInputControl @@ -481,7 +475,6 @@ function ShadowPopover( { shadowObj, onChange } ) { <ShadowInputControl label={ __( 'Spread' ) } value={ shadowObj.spread } - hasNegativeRange onChange={ ( value ) => onShadowChange( 'spread', value ) } /> </Grid> @@ -489,16 +482,7 @@ function ShadowPopover( { shadowObj, onChange } ) { ); } -function ShadowInputControl( { label, value, onChange, hasNegativeRange } ) { - const [ isCustomInput, setIsCustomInput ] = useState( false ); - const [ parsedQuantity, parsedUnit ] = - parseQuantityAndUnitFromRawValue( value ); - - const sliderOnChange = ( next ) => { - onChange( - next !== undefined ? [ next, parsedUnit || 'px' ].join( '' ) : '0px' - ); - }; +function ShadowInputControl( { label, value, onChange } ) { const onValueChange = ( next ) => { const isNumeric = next !== undefined && ! isNaN( parseFloat( next ) ); const nextValue = isNumeric ? next : '0px'; @@ -506,50 +490,11 @@ function ShadowInputControl( { label, value, onChange, hasNegativeRange } ) { }; return ( - <VStack justify="flex-start"> - <HStack justify="space-between"> - <Subtitle>{ label }</Subtitle> - <Button - label={ __( 'Use custom size' ) } - icon={ settings } - onClick={ () => { - setIsCustomInput( ! isCustomInput ); - } } - isPressed={ isCustomInput } - size="small" - /> - </HStack> - { isCustomInput ? ( - <UnitControl - label={ label } - hideLabelFromVision - __next40pxDefaultSize - value={ value } - onChange={ onValueChange } - /> - ) : ( - <RangeControl - value={ parsedQuantity ?? 0 } - onChange={ sliderOnChange } - withInputField={ false } - __next40pxDefaultSize - __nextHasNoMarginBottom - min={ - hasNegativeRange - ? -( - CUSTOM_VALUE_SETTINGS[ parsedUnit ?? 'px' ] - ?.max ?? 10 - ) - : 0 - } - max={ - CUSTOM_VALUE_SETTINGS[ parsedUnit ?? 'px' ]?.max ?? 10 - } - step={ - CUSTOM_VALUE_SETTINGS[ parsedUnit ?? 'px' ]?.step ?? 0.1 - } - /> - ) } - </VStack> + <UnitControl + label={ label } + __next40pxDefaultSize + value={ value } + onChange={ onValueChange } + /> ); } From fe276a946e1faf6704e678abd700c499e357aa79 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Tue, 17 Sep 2024 15:56:46 +0200 Subject: [PATCH 0827/1908] Fix accessibility of the hooked blocks toggles. (#63133) Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: joedolson <joedolson@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/block-editor/src/hooks/block-hooks.js | 17 +++-------------- .../block-editor/src/hooks/block-hooks.scss | 9 --------- 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/packages/block-editor/src/hooks/block-hooks.js b/packages/block-editor/src/hooks/block-hooks.js index b1fab1b124f8dc..04a2313b629ba7 100644 --- a/packages/block-editor/src/hooks/block-hooks.js +++ b/packages/block-editor/src/hooks/block-hooks.js @@ -3,18 +3,14 @@ */ import { __ } from '@wordpress/i18n'; import { Fragment, useMemo } from '@wordpress/element'; -import { - __experimentalHStack as HStack, - PanelBody, - ToggleControl, -} from '@wordpress/components'; +import { PanelBody, ToggleControl } from '@wordpress/components'; import { createBlock, store as blocksStore } from '@wordpress/blocks'; import { useDispatch, useSelect } from '@wordpress/data'; /** * Internal dependencies */ -import { BlockIcon, InspectorControls } from '../components'; +import { InspectorControls } from '../components'; import { store as blockEditorStore } from '../store'; const EMPTY_OBJECT = {}; @@ -204,14 +200,7 @@ function BlockHooksControlPure( { __nextHasNoMarginBottom checked={ checked } key={ block.title } - label={ - <HStack justify="flex-start"> - <BlockIcon - icon={ block.icon } - /> - <span>{ block.title }</span> - </HStack> - } + label={ block.title } onChange={ () => { if ( ! checked ) { // Create and insert block. diff --git a/packages/block-editor/src/hooks/block-hooks.scss b/packages/block-editor/src/hooks/block-hooks.scss index c8f2027483ccf3..03cabd638d8684 100644 --- a/packages/block-editor/src/hooks/block-hooks.scss +++ b/packages/block-editor/src/hooks/block-hooks.scss @@ -1,13 +1,4 @@ .block-editor-hooks__block-hooks { - /** - * Since we're displaying the block icon alongside the block name, - * we need to right-align the toggle. - */ - .components-toggle-control .components-h-stack { - /* stylelint-disable-next-line declaration-property-value-allowed-list -- This should be refactored to not use the row-reverse value. */ - flex-direction: row-reverse; - } - /** * Un-reverse the flex direction for the toggle's label. */ From 2943dd3adfa4e1ad33b980760277377df9ac0f91 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 17 Sep 2024 23:03:13 +0900 Subject: [PATCH 0828/1908] Post Summary Panel: Restore `height:auto` for toggle buttons (#65362) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/editor/src/components/post-panel-row/style.scss | 1 + packages/editor/src/components/post-status/index.js | 1 + packages/editor/src/components/post-status/style.scss | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/packages/editor/src/components/post-panel-row/style.scss b/packages/editor/src/components/post-panel-row/style.scss index f76c586850500e..53e0c645f6f069 100644 --- a/packages/editor/src/components/post-panel-row/style.scss +++ b/packages/editor/src/components/post-panel-row/style.scss @@ -28,6 +28,7 @@ white-space: normal; text-wrap: balance; // Fallback for Safari. text-wrap: pretty; + height: auto; min-height: $button-size-compact; } diff --git a/packages/editor/src/components/post-status/index.js b/packages/editor/src/components/post-status/index.js index 1d3050e7e3dd6b..c2bf038875354d 100644 --- a/packages/editor/src/components/post-status/index.js +++ b/packages/editor/src/components/post-status/index.js @@ -173,6 +173,7 @@ export default function PostStatus() { focusOnMount renderToggle={ ( { onToggle, isOpen } ) => ( <Button + className="editor-post-status__toggle" variant="tertiary" size="compact" onClick={ onToggle } diff --git a/packages/editor/src/components/post-status/style.scss b/packages/editor/src/components/post-status/style.scss index c601d887d68c7f..670dc5fc35999a 100644 --- a/packages/editor/src/components/post-status/style.scss +++ b/packages/editor/src/components/post-status/style.scss @@ -4,6 +4,11 @@ &.is-read-only { padding: 6px 12px; } + + .editor-post-status__toggle.editor-post-status__toggle { + padding-top: $grid-unit-05; + padding-bottom: $grid-unit-05; + } } .editor-change-status__password-fieldset, From c114b250912678db621de3f8951f4b1041d20219 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 17 Sep 2024 23:21:48 +0900 Subject: [PATCH 0829/1908] Revert "Don't force iframe editor when gutenberg plugin and block theme are enabled (#65372)" (#65402) This reverts commit 99fefd79c2644f65fb885fad82e0c11e7593eca0. Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../components/layout/use-should-iframe.js | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/packages/edit-post/src/components/layout/use-should-iframe.js b/packages/edit-post/src/components/layout/use-should-iframe.js index 9fed30c07b37e3..e36a4773c4a1fd 100644 --- a/packages/edit-post/src/components/layout/use-should-iframe.js +++ b/packages/edit-post/src/components/layout/use-should-iframe.js @@ -6,22 +6,33 @@ import { useSelect } from '@wordpress/data'; import { store as blocksStore } from '@wordpress/blocks'; import { store as blockEditorStore } from '@wordpress/block-editor'; +const isGutenbergPlugin = globalThis.IS_GUTENBERG_PLUGIN ? true : false; + export function useShouldIframe() { - const { hasV3BlocksOnly, isEditingTemplate, isZoomOutMode } = useSelect( - ( select ) => { - const { getCurrentPostType } = select( editorStore ); - const { __unstableGetEditorMode } = select( blockEditorStore ); - const { getBlockTypes } = select( blocksStore ); - return { - hasV3BlocksOnly: getBlockTypes().every( ( type ) => { - return type.apiVersion >= 3; - } ), - isEditingTemplate: getCurrentPostType() === 'wp_template', - isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', - }; - }, - [] - ); + const { + isBlockBasedTheme, + hasV3BlocksOnly, + isEditingTemplate, + isZoomOutMode, + } = useSelect( ( select ) => { + const { getEditorSettings, getCurrentPostType } = select( editorStore ); + const { __unstableGetEditorMode } = select( blockEditorStore ); + const { getBlockTypes } = select( blocksStore ); + const editorSettings = getEditorSettings(); + return { + isBlockBasedTheme: editorSettings.__unstableIsBlockBasedTheme, + hasV3BlocksOnly: getBlockTypes().every( ( type ) => { + return type.apiVersion >= 3; + } ), + isEditingTemplate: getCurrentPostType() === 'wp_template', + isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', + }; + }, [] ); - return hasV3BlocksOnly || isEditingTemplate || isZoomOutMode; + return ( + hasV3BlocksOnly || + ( isGutenbergPlugin && isBlockBasedTheme ) || + isEditingTemplate || + isZoomOutMode + ); } From 6b7345fbaaedac8952274d821b23033b14e55a86 Mon Sep 17 00:00:00 2001 From: Farid Abdulhadi <98262343+farid-hadi@users.noreply.github.com> Date: Tue, 17 Sep 2024 16:22:10 +0200 Subject: [PATCH 0830/1908] Docs: fix minor typos in Build your first block tutorial (#64961) * Docs: minor changes under Prerequisites in Build first block tutorial * Docs: fix minor typos in Build first block tutorial --- docs/getting-started/tutorial.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/getting-started/tutorial.md b/docs/getting-started/tutorial.md index aac507d4c573f4..4e43241f63fb16 100644 --- a/docs/getting-started/tutorial.md +++ b/docs/getting-started/tutorial.md @@ -25,7 +25,7 @@ To complete this tutorial, you will need: If you don't have one or more of these items, the [Block Development Environment](https://developer.wordpress.org/block-editor/getting-started/devenv/) documentation will help you get started. Come back here once you are all set up. <div class="callout callout-info"> - This tutorial uses <a href="https://developer.wordpress.org/block-editor/getting-started/devenv/get-started-with-wp-env/"><code>wp-env</code></a> to create a local WordPress development environment. However, feel free to use alternate local development tools if you already have one that you prefer. + This tutorial uses <a href="https://developer.wordpress.org/block-editor/getting-started/devenv/get-started-with-wp-env/"><code>wp-env</code></a> to create a local WordPress development environment. However, feel free to use any development environment that meets the abovementioned prerequisites. </div> ## Scaffolding the block @@ -250,7 +250,7 @@ At this point, the block's icon and description are correct, and block supports ### Updating edit.js -The [`edit.js`](https://developer.wordpress.org/block-editor/getting-started/fundamentals/file-structure-of-a-block/#edit-js) file controls how the block functions and appears in the Editor. Right now, the user sees the message " Copyright Date Block – hello from the editor!". Let's change that. +The [`edit.js`](https://developer.wordpress.org/block-editor/getting-started/fundamentals/file-structure-of-a-block/#edit-js) file controls how the block functions and appears in the Editor. Right now, the user sees the message "Copyright Date Block – hello from the editor!". Let's change that. Open the file and see that the `Edit()` function returns a paragraph tag with the default message. @@ -647,10 +647,10 @@ While the Editor looks great, the starting year functionality has yet to be adde Start by adding a variable called `$display_date` and replicate what you did in the `Edit()` function above. -This variable should display the value of the `startingYear` attribute and the `$current_year` variable separated by an em dash, or just the `$current_year` is the `showStartingYear` attribute is `false`. +This variable should display the value of the `startingYear` attribute and the `$current_year` variable separated by an em dash, or just the `$current_year` if the `showStartingYear` attribute is `false`. <div class="callout callout-tip"> - <p>Three variables are exposed in the <code>render.php</code>, which you can use to customize the block's output:</p> + <p>Three variables are exposed in <code>render.php</code>, which you can use to customize the block's output:</p> <ul> <li><code>$attributes</code> (array): The block attributes.</li> <li><code>$content</code> (string): The block default content.</li> From 6fa0bc195ffa475fc9de4a01b42ade5a5e0869d2 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Tue, 17 Sep 2024 16:05:03 +0100 Subject: [PATCH 0831/1908] Apply elevation scale in components package (#65159) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: keoshi <keoshi@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/base-styles/_variables.scss | 8 ++++---- packages/components/CHANGELOG.md | 8 ++++++++ .../components/src/custom-select-control-v2/styles.ts | 1 + packages/components/src/dropdown-menu-v2/styles.ts | 2 +- packages/components/src/form-toggle/style.scss | 1 + packages/components/src/popover/style.scss | 2 +- .../src/range-control/styles/range-control-styles.ts | 1 + packages/components/src/resizable-box/style.scss | 2 +- packages/components/src/snackbar/style.scss | 2 +- packages/components/src/tooltip/style.scss | 1 + packages/components/src/utils/config-values.js | 8 ++++---- 11 files changed, 24 insertions(+), 12 deletions(-) diff --git a/packages/base-styles/_variables.scss b/packages/base-styles/_variables.scss index 0f0c9e6d019ba3..35092033c552bd 100644 --- a/packages/base-styles/_variables.scss +++ b/packages/base-styles/_variables.scss @@ -55,16 +55,16 @@ $radius-round: 50%; // For circles and ovals. */ // For sections and containers that group related content and controls, which may overlap other content. Example: Preview Frame. -$elevation-x-small: 0 0.7px 1px rgba($black, 0.1), 0 1.2px 1.7px -0.2px rgba($black, 0.1), 0 2.3px 3.3px -0.5px rgba($black, 0.1); +$elevation-x-small: 0 1px 1px rgba($black, 0.03), 0 1px 2px rgba($black, 0.02), 0 3px 3px rgba($black, 0.02), 0 4px 4px rgba($black, 0.01); // For components that provide contextual feedback without being intrusive. Generally non-interruptive. Example: Tooltips, Snackbar. -$elevation-small: 0 0.7px 1px 0 rgba(0, 0, 0, 0.12), 0 2.2px 3.7px -0.2px rgba(0, 0, 0, 0.12), 0 5.3px 7.3px -0.5px rgba(0, 0, 0, 0.12); +$elevation-small: 0 1px 2px rgba($black, 0.05), 0 2px 3px rgba($black, 0.04), 0 6px 6px rgba($black, 0.03), 0 8px 8px rgba($black, 0.02); // For components that offer additional actions. Example: Menus, Command Palette -$elevation-medium: 0 0.7px 1px 0 rgba(0, 0, 0, 0.14), 0 4.2px 5.7px -0.2px rgba(0, 0, 0, 0.14), 0 7.3px 9.3px -0.5px rgba(0, 0, 0, 0.14); +$elevation-medium: 0 2px 3px rgba($black, 0.05), 0 4px 5px rgba($black, 0.04), 0 12px 12px rgba($black, 0.03), 0 16px 16px rgba($black, 0.02); // For components that confirm decisions or handle necessary interruptions. Example: Modals. -$elevation-large: 0 0.7px 1px rgba($black, 0.15), 0 2.7px 3.8px -0.2px rgba($black, 0.15), 0 5.5px 7.8px -0.3px rgba($black, 0.15), 0.1px 11.5px 16.4px -0.5px rgba($black, 0.15); +$elevation-large: 0 5px 15px rgba($black, 0.08), 0 15px 27px rgba($black, 0.07), 0 30px 36px rgba($black, 0.04), 0 50px 43px rgba($black, 0.02); /** * Dimensions. diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 8d9ee39833577b..c705257a827c5e 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -21,6 +21,14 @@ - `Navigator`: warn if a screen's `path` doesn't follow a URL-like scheme ([#65231](https://github.com/WordPress/gutenberg/pull/65231)). - `Modal`: Decrease close button size and remove horizontal offset ([#65131](https://github.com/WordPress/gutenberg/pull/65131)). +- `CustomSelectControl V2`: Adopt elevation scale ([#65159](https://github.com/WordPress/gutenberg/pull/65159)). +- `DropdownMenu V2`: Adopt elevation scale ([#65159](https://github.com/WordPress/gutenberg/pull/65159)). +- `FormToggle`: Adopt elevation scale ([#65159](https://github.com/WordPress/gutenberg/pull/65159)). +- `Popover`: Adopt elevation scale ([#65159](https://github.com/WordPress/gutenberg/pull/65159)). +- `RangeControl`: Adopt elevation scale ([#65159](https://github.com/WordPress/gutenberg/pull/65159)). +- `ResizeableBox`: Adopt elevation scale ([#65159](https://github.com/WordPress/gutenberg/pull/65159)). +- `Snackbar`: Adopt elevation scale ([#65159](https://github.com/WordPress/gutenberg/pull/65159)). +- `Tooltip`: Adopt elevation scale ([#65159](https://github.com/WordPress/gutenberg/pull/65159)). - `Card`: Adopt radius scale ([#65053](https://github.com/WordPress/gutenberg/pull/65053)). ### Bug Fixes diff --git a/packages/components/src/custom-select-control-v2/styles.ts b/packages/components/src/custom-select-control-v2/styles.ts index c82d6eba2e1a76..2b8bdb9946b7c9 100644 --- a/packages/components/src/custom-select-control-v2/styles.ts +++ b/packages/components/src/custom-select-control-v2/styles.ts @@ -120,6 +120,7 @@ export const SelectPopover = styled( Ariakit.SelectPopover )` background-color: ${ COLORS.theme.background }; border-radius: ${ CONFIG.radiusSmall }; border: 1px solid ${ COLORS.theme.foreground }; + box-shadow: ${ CONFIG.elevationMedium }; /* z-index(".components-popover") */ z-index: 1000000; diff --git a/packages/components/src/dropdown-menu-v2/styles.ts b/packages/components/src/dropdown-menu-v2/styles.ts index 55020fbcd41354..b25613e9feb52b 100644 --- a/packages/components/src/dropdown-menu-v2/styles.ts +++ b/packages/components/src/dropdown-menu-v2/styles.ts @@ -37,7 +37,7 @@ const DIVIDER_COLOR = COLORS.theme.gray[ 200 ]; const LIGHTER_TEXT_COLOR = COLORS.theme.gray[ 700 ]; const LIGHT_BACKGROUND_COLOR = COLORS.theme.gray[ 100 ]; const TOOLBAR_VARIANT_BORDER_COLOR = COLORS.theme.foreground; -const DEFAULT_BOX_SHADOW = `0 0 0 ${ CONFIG.borderWidth } ${ DEFAULT_BORDER_COLOR }, ${ CONFIG.elevationXSmall }`; +const DEFAULT_BOX_SHADOW = `0 0 0 ${ CONFIG.borderWidth } ${ DEFAULT_BORDER_COLOR }, ${ CONFIG.elevationMedium }`; const TOOLBAR_VARIANT_BOX_SHADOW = `0 0 0 ${ CONFIG.borderWidth } ${ TOOLBAR_VARIANT_BORDER_COLOR }`; const GRID_TEMPLATE_COLS = 'minmax( 0, max-content ) 1fr'; diff --git a/packages/components/src/form-toggle/style.scss b/packages/components/src/form-toggle/style.scss index dd7888403b34d4..900874b59004b8 100644 --- a/packages/components/src/form-toggle/style.scss +++ b/packages/components/src/form-toggle/style.scss @@ -60,6 +60,7 @@ $transition-duration: 0.2s; $transition-duration background-color ease-out; @include reduce-motion("transition"); background-color: $gray-900; + box-shadow: $elevation-x-small; // Transparent border acts as a fill in Windows High Contrast Mode. border: math.div($toggle-thumb-size, 2) solid transparent; diff --git a/packages/components/src/popover/style.scss b/packages/components/src/popover/style.scss index bfab8978864b34..601e9ebb7675f5 100644 --- a/packages/components/src/popover/style.scss +++ b/packages/components/src/popover/style.scss @@ -22,7 +22,7 @@ $shadow-popover-border-top-only-alternate: 0 #{-$border-width} 0 $gray-900; .components-popover__content { background: $white; - box-shadow: $shadow-popover-border-default, $elevation-x-small; + box-shadow: $shadow-popover-border-default, $elevation-medium; border-radius: $radius-medium; box-sizing: border-box; width: min-content; diff --git a/packages/components/src/range-control/styles/range-control-styles.ts b/packages/components/src/range-control/styles/range-control-styles.ts index e2b651bd317da5..dae1d0de3ddb66 100644 --- a/packages/components/src/range-control/styles/range-control-styles.ts +++ b/packages/components/src/range-control/styles/range-control-styles.ts @@ -239,6 +239,7 @@ export const Thumb = styled.span< ThumbProps >` position: absolute; user-select: none; width: 100%; + box-shadow: ${ CONFIG.elevationXSmall }; ${ thumbColor }; ${ thumbFocus }; diff --git a/packages/components/src/resizable-box/style.scss b/packages/components/src/resizable-box/style.scss index 2e709a5bbb382d..3c9efd27136460 100644 --- a/packages/components/src/resizable-box/style.scss +++ b/packages/components/src/resizable-box/style.scss @@ -35,7 +35,7 @@ $resize-handler-container-size: $resize-handler-size + ($grid-unit-05 * 2); // M top: calc(50% - #{ceil($resize-handler-size * 0.5)}); right: calc(50% - #{ceil($resize-handler-size * 0.5)}); - box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) $components-color-accent; + box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) $components-color-accent, $elevation-x-small; // Only visible in Windows High Contrast mode. outline: 2px solid transparent; } diff --git a/packages/components/src/snackbar/style.scss b/packages/components/src/snackbar/style.scss index e7f29267d6f6db..1e76a1666411e7 100644 --- a/packages/components/src/snackbar/style.scss +++ b/packages/components/src/snackbar/style.scss @@ -4,7 +4,7 @@ background: rgba($black, 0.85); // Emulates #1e1e1e closely. backdrop-filter: blur($grid-unit-20) saturate(180%); border-radius: $radius-medium; - box-shadow: $elevation-x-small; + box-shadow: $elevation-small; color: $white; padding: $grid-unit-15 ($grid-unit-05 * 5); width: 100%; diff --git a/packages/components/src/tooltip/style.scss b/packages/components/src/tooltip/style.scss index eaac8b3ad1c7f6..e84946e4a9176c 100644 --- a/packages/components/src/tooltip/style.scss +++ b/packages/components/src/tooltip/style.scss @@ -8,6 +8,7 @@ font-size: 12px; padding: $grid-unit-05 $grid-unit-10; z-index: z-index(".components-tooltip"); + box-shadow: $elevation-small; } .components-tooltip__shortcut { diff --git a/packages/components/src/utils/config-values.js b/packages/components/src/utils/config-values.js index 4d7ed859e89edd..2040f479a231c2 100644 --- a/packages/components/src/utils/config-values.js +++ b/packages/components/src/utils/config-values.js @@ -72,10 +72,10 @@ export default Object.assign( {}, CONTROL_PROPS, TOGGLE_GROUP_CONTROL_PROPS, { cardPaddingSmall: `${ space( 4 ) }`, cardPaddingMedium: `${ space( 4 ) } ${ space( 6 ) }`, cardPaddingLarge: `${ space( 6 ) } ${ space( 8 ) }`, - elevationXSmall: `0 0.7px 1px rgba(0, 0, 0, 0.1), 0 1.2px 1.7px -0.2px rgba(0, 0, 0, 0.1), 0 2.3px 3.3px -0.5px rgba(0, 0, 0, 0.1)`, - elevationSmall: `0 0.7px 1px 0 rgba(0, 0, 0, 0.12), 0 2.2px 3.7px -0.2px rgba(0, 0, 0, 0.12), 0 5.3px 7.3px -0.5px rgba(0, 0, 0, 0.12)`, - elevationMedium: `0 0.7px 1px 0 rgba(0, 0, 0, 0.14), 0 4.2px 5.7px -0.2px rgba(0, 0, 0, 0.14), 0 7.3px 9.3px -0.5px rgba(0, 0, 0, 0.14)`, - elevationLarge: `0 0.7px 1px rgba(0, 0, 0, 0.15), 0 2.7px 3.8px -0.2px rgba(0, 0, 0, 0.15), 0 5.5px 7.8px -0.3px rgba(0, 0, 0, 0.15), 0.1px 11.5px 16.4px -0.5px rgba(0, 0, 0, 0.15)`, + elevationXSmall: `0 1px 1px rgba(0, 0, 0, 0.03), 0 1px 2px rgba(0, 0, 0, 0.02), 0 3px 3px rgba(0, 0, 0, 0.02), 0 4px 4px rgba(0, 0, 0, 0.01)`, + elevationSmall: `0 1px 2px rgba(0, 0, 0, 0.05), 0 2px 3px rgba(0, 0, 0, 0.04), 0 6px 6px rgba(0, 0, 0, 0.03), 0 8px 8px rgba(0, 0, 0, 0.02)`, + elevationMedium: `0 2px 3px rgba(0, 0, 0, 0.05), 0 4px 5px rgba(0, 0, 0, 0.04), 0 12px 12px rgba(0, 0, 0, 0.03), 0 16px 16px rgba(0, 0, 0, 0.02)`, + elevationLarge: `0 5px 15px rgba(0, 0, 0, 0.08), 0 15px 27px rgba(0, 0, 0, 0.07), 0 30px 36px rgba(0, 0, 0, 0.04), 0 50px 43px rgba(0, 0, 0, 0.02)`, surfaceBackgroundColor: COLORS.white, surfaceBackgroundSubtleColor: '#F3F3F3', surfaceBackgroundTintColor: '#F5F5F5', From 256fa3f93e7ef70625232ade855a0dbb36e03599 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Tue, 17 Sep 2024 17:33:31 +0200 Subject: [PATCH 0832/1908] Interactivity API: Use a11y Script Module in Gutenberg (#65123) Fix an issue where accessibility texts were always "" (empty string) in the Interactivity Router. Use the new `@wordpress/a11y` script module for accessibility in the Interactivity Router. The change to use the new script module is behind a Gutenberg-only feature flag. Pass static localization texts via script module data passing instead of through the Interactivity API store. --- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: michalczaplinski <czapla@git.wordpress.org> --- lib/interactivity-api.php | 36 +++++++- package-lock.json | 2 + packages/interactivity-router/package.json | 1 + packages/interactivity-router/src/index.ts | 94 ++++++++++++++++++--- packages/interactivity-router/tsconfig.json | 2 +- 5 files changed, 118 insertions(+), 17 deletions(-) diff --git a/lib/interactivity-api.php b/lib/interactivity-api.php index 90535f1ebaa42f..c00d68bc70e8e2 100644 --- a/lib/interactivity-api.php +++ b/lib/interactivity-api.php @@ -24,9 +24,41 @@ function gutenberg_reregister_interactivity_script_modules() { wp_register_script_module( '@wordpress/interactivity-router', gutenberg_url( '/build-module/interactivity-router/index.min.js' ), - array( '@wordpress/interactivity' ), + array( + array( + 'id' => '@wordpress/a11y', + 'import' => 'dynamic', + ), + '@wordpress/interactivity', + ), $default_version ); } - add_action( 'init', 'gutenberg_reregister_interactivity_script_modules' ); + +/** + * Adds script data to the interactivity-router script module. + * + * This filter is registered conditionally anticipating a WordPress Core change to add the script module data. + * The filter runs on 'after_setup_theme' (when Core registers Interactivity and Script Modules hooks) + * to ensure that the conditional registration happens after Core and correctly determine whether + * the filter should be added. + * + * @see https://github.com/WordPress/wordpress-develop/pull/7304 + */ +function gutenberg_register_interactivity_script_module_data_hooks() { + if ( ! has_filter( 'script_module_data_@wordpress/interactivity-router', array( wp_interactivity(), 'filter_script_module_interactivity_router_data' ) ) ) { + add_filter( + 'script_module_data_@wordpress/interactivity-router', + function ( $data ) { + if ( ! isset( $data['i18n'] ) ) { + $data['i18n'] = array(); + } + $data['i18n']['loading'] = __( 'Loading page, please wait.', 'default' ); + $data['i18n']['loaded'] = __( 'Page Loaded.', 'default' ); + return $data; + } + ); + } +} +add_action( 'after_setup_theme', 'gutenberg_register_interactivity_script_module_data_hooks', 20 ); diff --git a/package-lock.json b/package-lock.json index 49d1ad6b123b76..dcdc5043ac6d88 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54329,6 +54329,7 @@ "version": "2.7.0", "license": "GPL-2.0-or-later", "dependencies": { + "@wordpress/a11y": "file:../a11y", "@wordpress/interactivity": "file:../interactivity" }, "engines": { @@ -69038,6 +69039,7 @@ "@wordpress/interactivity-router": { "version": "file:packages/interactivity-router", "requires": { + "@wordpress/a11y": "file:../a11y", "@wordpress/interactivity": "file:../interactivity" } }, diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index db85c0d8bdba3b..7282ee0b00f9c9 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -28,6 +28,7 @@ "types": "build-types", "wpScriptModuleExports": "./build-module/index.js", "dependencies": { + "@wordpress/a11y": "file:../a11y", "@wordpress/interactivity": "file:../interactivity" }, "publishConfig": { diff --git a/packages/interactivity-router/src/index.ts b/packages/interactivity-router/src/index.ts index c6e1087b038a55..3bd44c7aebd71f 100644 --- a/packages/interactivity-router/src/index.ts +++ b/packages/interactivity-router/src/index.ts @@ -209,16 +209,37 @@ const isValidEvent = ( event: MouseEvent ) => // Variable to store the current navigation. let navigatingTo = ''; -export const { state, actions } = store( 'core/router', { +let hasLoadedNavigationTextsData = false; +const navigationTexts = { + loading: 'Loading page, please wait.', + loaded: 'Page Loaded.', +}; + +interface Store { + state: { + url: string; + navigation: { + hasStarted: boolean; + hasFinished: boolean; + message: string; + texts?: { + loading?: string; + loaded?: string; + }; + }; + }; + actions: { + navigate: ( href: string, options?: NavigateOptions ) => void; + prefetch: ( url: string, options?: PrefetchOptions ) => void; + }; +} + +export const { state, actions } = store< Store >( 'core/router', { state: { url: window.location.href, navigation: { hasStarted: false, hasFinished: false, - texts: { - loading: '', - loaded: '', - }, message: '', }, }, @@ -275,7 +296,7 @@ export const { state, actions } = store( 'core/router', { navigation.hasFinished = false; } if ( screenReaderAnnouncement ) { - navigation.message = navigation.texts.loading; + a11ySpeak( 'loading' ); } }, 400 ); @@ -315,14 +336,7 @@ export const { state, actions } = store( 'core/router', { } if ( screenReaderAnnouncement ) { - // Announce that the page has been loaded. If the message is the - // same, we use a no-break space similar to the @wordpress/a11y - // package: https://github.com/WordPress/gutenberg/blob/c395242b8e6ee20f8b06c199e4fc2920d7018af1/packages/a11y/src/filter-message.js#L20-L26 - navigation.message = - navigation.texts.loaded + - ( navigation.message === navigation.texts.loaded - ? '\u00A0' - : '' ); + a11ySpeak( 'loaded' ); } // Scroll to the anchor if exits in the link. @@ -363,6 +377,58 @@ export const { state, actions } = store( 'core/router', { }, } ); +/** + * Announces a message to screen readers. + * + * This is a wrapper around the `@wordpress/a11y` package's `speak` function. It handles importing + * the package on demand and should be used instead of calling `ally.speak` direacly. + * + * @param messageKey The message to be announced by assistive technologies. + */ +function a11ySpeak( messageKey: keyof typeof navigationTexts ) { + if ( ! hasLoadedNavigationTextsData ) { + hasLoadedNavigationTextsData = true; + const content = document.getElementById( + 'wp-script-module-data-@wordpress/interactivity-router' + )?.textContent; + if ( content ) { + try { + const parsed = JSON.parse( content ); + if ( typeof parsed?.i18n?.loading === 'string' ) { + navigationTexts.loading = parsed.i18n.loading; + } + if ( typeof parsed?.i18n?.loaded === 'string' ) { + navigationTexts.loaded = parsed.i18n.loaded; + } + } catch {} + } else { + // Fallback to localized strings from Interactivity API state. + if ( state.navigation.texts?.loading ) { + navigationTexts.loading = state.navigation.texts.loading; + } + if ( state.navigation.texts?.loaded ) { + navigationTexts.loaded = state.navigation.texts.loaded; + } + } + } + + const message = navigationTexts[ messageKey ]; + + if ( globalThis.IS_GUTENBERG_PLUGIN ) { + import( '@wordpress/a11y' ).then( + ( { speak } ) => speak( message ), + // Ignore failures to load the a11y module. + () => {} + ); + } else { + state.navigation.message = + // Announce that the page has been loaded. If the message is the + // same, we use a no-break space similar to the @wordpress/a11y + // package: https://github.com/WordPress/gutenberg/blob/c395242b8e6ee20f8b06c199e4fc2920d7018af1/packages/a11y/src/filter-message.js#L20-L26 + message + ( state.navigation.message === message ? '\u00A0' : '' ); + } +} + // Add click and prefetch to all links. if ( globalThis.IS_GUTENBERG_PLUGIN ) { if ( navigationMode === 'fullPage' ) { diff --git a/packages/interactivity-router/tsconfig.json b/packages/interactivity-router/tsconfig.json index eff80af2f28db3..f601a26a86f5f4 100644 --- a/packages/interactivity-router/tsconfig.json +++ b/packages/interactivity-router/tsconfig.json @@ -7,6 +7,6 @@ "checkJs": false, "strict": false }, - "references": [ { "path": "../interactivity" } ], + "references": [ { "path": "../a11y" }, { "path": "../interactivity" } ], "include": [ "src/**/*" ] } From 93af2ddb463fade01a0d16d82631e43760d72b82 Mon Sep 17 00:00:00 2001 From: Javier Arce <javierarce@users.noreply.github.com> Date: Tue, 17 Sep 2024 18:38:51 +0200 Subject: [PATCH 0833/1908] Icons: Adds bell and bell-unread icons (#65324) * Icons: Adds bell and bell-unread icons and updates the CHANGELOG file --------- Co-authored-by: javierarce <javiarce@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/icons/CHANGELOG.md | 4 ++++ packages/icons/src/index.js | 2 ++ packages/icons/src/library/bell-unread.js | 13 +++++++++++++ packages/icons/src/library/bell.js | 16 ++++++++++++++++ 4 files changed, 35 insertions(+) create mode 100644 packages/icons/src/library/bell-unread.js create mode 100644 packages/icons/src/library/bell.js diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index 32bbd88181e369..a59229e1b0eba7 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### New Features + +- Add new `bell` and `bell-unread` icons. + ## 10.7.0 (2024-09-05) ## 10.6.0 (2024-08-21) diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index e9b48331365135..9ab41bd3620279 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -18,6 +18,8 @@ export { default as aspectRatio } from './library/aspect-ratio'; export { default as audio } from './library/audio'; export { default as background } from './library/background'; export { default as backup } from './library/backup'; +export { default as bell } from './library/bell'; +export { default as bellUnread } from './library/bell-unread'; export { default as blockDefault } from './library/block-default'; export { default as blockMeta } from './library/block-meta'; export { default as blockTable } from './library/block-table'; diff --git a/packages/icons/src/library/bell-unread.js b/packages/icons/src/library/bell-unread.js new file mode 100644 index 00000000000000..96c209ddb09f6d --- /dev/null +++ b/packages/icons/src/library/bell-unread.js @@ -0,0 +1,13 @@ +/** + * WordPress dependencies + */ +import { SVG, Path, Circle } from '@wordpress/primitives'; + +const bellUnread = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M13.969 4.39A5.088 5.088 0 0 0 12 4C9.2 4 7 6.2 7 9v2.5c0 1.353-.17 2.368-.976 3-.267.209-.602.376-1.024.5v1h14v-1c-.422-.124-.757-.291-1.024-.5-.806-.632-.976-1.647-.976-3V11c-.53 0-1.037-.103-1.5-.29v.79c0 .93.066 1.98.515 2.897l.053.103H7.932l.053-.103c.449-.917.515-1.967.515-2.897V9c0-1.972 1.528-3.5 3.5-3.5.43 0 .838.072 1.214.206.167-.488.425-.933.755-1.316Zm-3.961 13.618c0-.176.023-.346.065-.508h3.854A1.996 1.996 0 0 1 12 20a1.991 1.991 0 0 1-1.992-1.992Z" /> + <Circle cx="17" cy="7" r="2.5" /> + </SVG> +); + +export default bellUnread; diff --git a/packages/icons/src/library/bell.js b/packages/icons/src/library/bell.js new file mode 100644 index 00000000000000..910488ee3035a5 --- /dev/null +++ b/packages/icons/src/library/bell.js @@ -0,0 +1,16 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const bell = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path + fillRule="evenodd" + clipRule="evenodd" + d="M17 11.5c0 1.353.17 2.368.976 3 .266.209.602.376 1.024.5v1H5v-1c.422-.124.757-.291 1.024-.5.806-.632.976-1.647.976-3V9c0-2.8 2.2-5 5-5s5 2.2 5 5v2.5ZM15.5 9v2.5c0 .93.066 1.98.515 2.897l.053.103H7.932a4.018 4.018 0 0 0 .053-.103c.449-.917.515-1.967.515-2.897V9c0-1.972 1.528-3.5 3.5-3.5s3.5 1.528 3.5 3.5Zm-5.492 9.008c0-.176.023-.346.065-.508h3.854A1.996 1.996 0 0 1 12 20c-1.1 0-1.992-.892-1.992-1.992Z" + /> + </SVG> +); + +export default bell; From 636710ba98514345009d7aab2de1dc5471c69a2c Mon Sep 17 00:00:00 2001 From: David Arenas <david.arenas@automattic.com> Date: Tue, 17 Sep 2024 19:42:52 +0200 Subject: [PATCH 0834/1908] Interactivity API: Refactor context proxies (#64713) * Move `proxifyContext` to proxies folder * Move context handlers outside * Remove unused code * Update comment * Add TODO comment * Remove unused code and rename `k` arg to `key` * Replace `updateContext` with `deepMerge` * Throw when calling `proxifyContext` on a context proxy * Add unit tests * Update changelog * Added new tests to validate behavior with proxified state. Also included more descriptive error messages for re-proxification attempts. --------- Co-authored-by: DAreRodz <darerodz@git.wordpress.org> Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: luisherranz <luisherranz@git.wordpress.org> --- packages/interactivity/CHANGELOG.md | 4 + packages/interactivity/src/directives.tsx | 135 +------- packages/interactivity/src/proxies/context.ts | 69 +++++ packages/interactivity/src/proxies/index.ts | 1 + .../src/proxies/test/context-proxy.ts | 291 ++++++++++++++++++ 5 files changed, 369 insertions(+), 131 deletions(-) create mode 100644 packages/interactivity/src/proxies/context.ts create mode 100644 packages/interactivity/src/proxies/test/context-proxy.ts diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 9ea269fa269ad0..6e8fbc6b74e08d 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Refactor internal context proxies implementation ([#64713](https://github.com/WordPress/gutenberg/pull/64713)). + ### Bug Fixes - Prevent calling `proxifyContext` over an already-proxified context inside `wp-context` ([#65090](https://github.com/WordPress/gutenberg/pull/65090)). diff --git a/packages/interactivity/src/directives.tsx b/packages/interactivity/src/directives.tsx index b41d50722e3765..cde39d830499a2 100644 --- a/packages/interactivity/src/directives.tsx +++ b/packages/interactivity/src/directives.tsx @@ -6,10 +6,6 @@ */ import { h as createElement, type RefObject } from 'preact'; import { useContext, useMemo, useRef } from 'preact/hooks'; -/** - * Internal dependencies - */ -import { proxifyState, peek } from './proxies'; /** * Internal dependencies @@ -24,131 +20,7 @@ import { } from './utils'; import { directive, getEvaluate, type DirectiveEntry } from './hooks'; import { getScope } from './scopes'; - -// Assigned objects should be ignored during proxification. -const contextAssignedObjects = new WeakMap(); - -// Store the context proxy and fallback for each object in the context. -const contextObjectToProxy = new WeakMap(); -const contextProxyToObject = new WeakMap(); -const contextObjectToFallback = new WeakMap(); - -const descriptor = Reflect.getOwnPropertyDescriptor; - -/** - * Wrap a context object with a proxy to reproduce the context stack. The proxy - * uses the passed `inherited` context as a fallback to look up for properties - * that don't exist in the given context. Also, updated properties are modified - * where they are defined, or added to the main context when they don't exist. - * - * By default, all plain objects inside the context are wrapped, unless it is - * listed in the `ignore` option. - * - * @param current Current context. - * @param inherited Inherited context, used as fallback. - * - * @return The wrapped context object. - */ -const proxifyContext = ( current: object, inherited: object = {} ): object => { - // Update the fallback object reference when it changes. - contextObjectToFallback.set( current, inherited ); - if ( ! contextObjectToProxy.has( current ) ) { - const proxy = new Proxy( current, { - get: ( target: object, k: string ) => { - const fallback = contextObjectToFallback.get( current ); - // Always subscribe to prop changes in the current context. - const currentProp = target[ k ]; - - // Return the inherited prop when missing in target. - if ( ! ( k in target ) && k in fallback ) { - return fallback[ k ]; - } - - // Proxify plain objects that were not directly assigned. - if ( - k in target && - ! contextAssignedObjects.get( target )?.has( k ) && - isPlainObject( currentProp ) - ) { - return proxifyContext( currentProp ); - } - - // Return the stored proxy for `currentProp` when it exists. - if ( contextObjectToProxy.has( currentProp ) ) { - return contextObjectToProxy.get( currentProp ); - } - - /* - * For other cases, return the value from target, also - * subscribing to changes in the parent context when the current - * prop is not defined. - */ - return k in target ? currentProp : fallback[ k ]; - }, - set: ( target, k, value ) => { - const fallback = contextObjectToFallback.get( current ); - const obj = - k in target || ! ( k in fallback ) ? target : fallback; - - /* - * Assigned object values should not be proxified so they point - * to the original object and don't inherit unexpected - * properties. - */ - if ( value && typeof value === 'object' ) { - if ( ! contextAssignedObjects.has( obj ) ) { - contextAssignedObjects.set( obj, new Set() ); - } - contextAssignedObjects.get( obj ).add( k ); - } - - /* - * When the value is a proxy, it's because it comes from the - * context, so the inner value is assigned instead. - */ - if ( contextProxyToObject.has( value ) ) { - const innerValue = contextProxyToObject.get( value ); - obj[ k ] = innerValue; - } else { - obj[ k ] = value; - } - - return true; - }, - ownKeys: ( target ) => [ - ...new Set( [ - ...Object.keys( contextObjectToFallback.get( current ) ), - ...Object.keys( target ), - ] ), - ], - getOwnPropertyDescriptor: ( target, k ) => - descriptor( target, k ) || - descriptor( contextObjectToFallback.get( current ), k ), - } ); - contextObjectToProxy.set( current, proxy ); - contextProxyToObject.set( proxy, current ); - } - return contextObjectToProxy.get( current ); -}; - -/** - * Recursively update values within a context object. - * - * @param target A context instance. - * @param source Object with properties to update in `target`. - */ -const updateContext = ( target: any, source: any ) => { - for ( const k in source ) { - if ( - isPlainObject( peek( target, k ) ) && - isPlainObject( source[ k ] ) - ) { - updateContext( peek( target, k ) as object, source[ k ] ); - } else if ( ! ( k in target ) ) { - target[ k ] = source[ k ]; - } - } -}; +import { proxifyState, proxifyContext, deepMerge } from './proxies'; /** * Recursively clone the passed object. @@ -286,9 +158,10 @@ export default () => { `The value of data-wp-context in "${ namespace }" store must be a valid stringified JSON object.` ); } - updateContext( + deepMerge( currentValue.current, - deepClone( value ) as object + deepClone( value ) as object, + false ); result[ namespace ] = proxifyContext( currentValue.current, diff --git a/packages/interactivity/src/proxies/context.ts b/packages/interactivity/src/proxies/context.ts new file mode 100644 index 00000000000000..64517c91a6940e --- /dev/null +++ b/packages/interactivity/src/proxies/context.ts @@ -0,0 +1,69 @@ +const contextObjectToProxy = new WeakMap(); +const contextObjectToFallback = new WeakMap(); +const contextProxies = new WeakSet(); + +const descriptor = Reflect.getOwnPropertyDescriptor; + +// TODO: Use the proxy registry to avoid multiple proxies on the same object. +const contextHandlers: ProxyHandler< object > = { + get: ( target, key ) => { + const fallback = contextObjectToFallback.get( target ); + // Always subscribe to prop changes in the current context. + const currentProp = target[ key ]; + + /* + * Return the value from `target` if it exists, or from `fallback` + * otherwise. This way, in the case the property doesn't exist either in + * `target` or `fallback`, it also subscribes to changes in the parent + * context. + */ + return key in target ? currentProp : fallback[ key ]; + }, + set: ( target, key, value ) => { + const fallback = contextObjectToFallback.get( target ); + + // If the property exists in the current context, modify it. Otherwise, + // add it to the current context. + const obj = key in target || ! ( key in fallback ) ? target : fallback; + obj[ key ] = value; + + return true; + }, + ownKeys: ( target ) => [ + ...new Set( [ + ...Object.keys( contextObjectToFallback.get( target ) ), + ...Object.keys( target ), + ] ), + ], + getOwnPropertyDescriptor: ( target, key ) => + descriptor( target, key ) || + descriptor( contextObjectToFallback.get( target ), key ), +}; + +/** + * Wrap a context object with a proxy to reproduce the context stack. The proxy + * uses the passed `inherited` context as a fallback to look up for properties + * that don't exist in the given context. Also, updated properties are modified + * where they are defined, or added to the main context when they don't exist. + * + * @param current Current context. + * @param inherited Inherited context, used as fallback. + * + * @return The wrapped context object. + */ +export const proxifyContext = ( + current: object, + inherited: object = {} +): object => { + if ( contextProxies.has( current ) ) { + throw Error( 'This object cannot be proxified.' ); + } + // Update the fallback object reference when it changes. + contextObjectToFallback.set( current, inherited ); + if ( ! contextObjectToProxy.has( current ) ) { + const proxy = new Proxy( current, contextHandlers ); + contextObjectToProxy.set( current, proxy ); + contextProxies.add( proxy ); + } + return contextObjectToProxy.get( current ); +}; diff --git a/packages/interactivity/src/proxies/index.ts b/packages/interactivity/src/proxies/index.ts index 1a495de6b469fe..168e6467fc7016 100644 --- a/packages/interactivity/src/proxies/index.ts +++ b/packages/interactivity/src/proxies/index.ts @@ -3,3 +3,4 @@ */ export { proxifyState, peek, deepMerge } from './state'; export { proxifyStore } from './store'; +export { proxifyContext } from './context'; diff --git a/packages/interactivity/src/proxies/test/context-proxy.ts b/packages/interactivity/src/proxies/test/context-proxy.ts new file mode 100644 index 00000000000000..306b3e4a8aa94f --- /dev/null +++ b/packages/interactivity/src/proxies/test/context-proxy.ts @@ -0,0 +1,291 @@ +/** + * External dependencies + */ +import { effect } from '@preact/signals'; + +/** + * Internal dependencies + */ +import { proxifyContext, proxifyState } from '../'; + +describe( 'Interactivity API', () => { + describe( 'context proxy', () => { + describe( 'get', () => { + it( 'should inherit props from its fallback', () => { + const fallback: any = proxifyContext( { a: 1 }, {} ); + const context: any = proxifyContext( { b: 2 }, fallback ); + + expect( context.a ).toBe( 1 ); + expect( context.b ).toBe( 2 ); + } ); + + it( "should inherit props from its fallback's fallback", () => { + const fallback2: any = proxifyContext( { a: 1 }, {} ); + const fallback1: any = proxifyContext( { b: 2 }, fallback2 ); + const context: any = proxifyContext( { c: 3 }, fallback1 ); + + expect( context.a ).toBe( 1 ); + expect( context.b ).toBe( 2 ); + expect( context.c ).toBe( 3 ); + } ); + + it( 'should list all inherited props', () => { + const fallback2: any = proxifyContext( { a: 1 }, {} ); + const fallback1: any = proxifyContext( { b: 2 }, fallback2 ); + const context: any = proxifyContext( { c: 3 }, fallback1 ); + + expect( Object.entries( context ) ).toEqual( [ + [ 'a', 1 ], + [ 'b', 2 ], + [ 'c', 3 ], + ] ); + } ); + + it( 'should shadow properties defined in its fallback', () => { + const fallback: any = proxifyContext( + { prop: 'fallback' }, + {} + ); + const context: any = proxifyContext( + { prop: 'context' }, + fallback + ); + + expect( context.prop ).toBe( 'context' ); + } ); + + it( 'should not inherit properties from nested objects', () => { + const fallback: any = proxifyContext( { obj: { a: 1 } }, {} ); + const context: any = proxifyContext( + { obj: { b: 2 } }, + fallback + ); + + expect( 'a' in context.obj ).toBe( false ); + expect( context.obj.b ).toBe( 2 ); + } ); + + it( 'should work with the proxified state', () => { + const state = proxifyState( 'test', { a: 1 } ); + const fallback: any = proxifyContext( state, {} ); + const context: any = proxifyContext( state, fallback ); + + expect( context.a ).toBe( 1 ); + } ); + } ); + + describe( 'set', () => { + it( 'should modify props defined in it', () => { + const fallback: any = proxifyContext( + { prop: 'fallback' }, + {} + ); + const context: any = proxifyContext( + { prop: 'context' }, + fallback + ); + + context.prop = 'modified'; + + expect( context.prop ).toBe( 'modified' ); + expect( fallback.prop ).toBe( 'fallback' ); + } ); + + it( 'should modify props inherited from its fallback', () => { + const fallback: any = proxifyContext( + { prop: 'fallback' }, + {} + ); + const context: any = proxifyContext( {}, fallback ); + + context.prop = 'modified'; + + expect( context.prop ).toBe( 'modified' ); + expect( fallback.prop ).toBe( 'modified' ); + } ); + + it( 'should see changes in inherited props', () => { + const fallback: any = proxifyContext( + { prop: 'fallback' }, + {} + ); + const context: any = proxifyContext( {}, fallback ); + + fallback.prop = 'modified'; + + expect( context.prop ).toBe( 'modified' ); + expect( fallback.prop ).toBe( 'modified' ); + } ); + + it( 'should create non-inherited props in itself', () => { + const fallback: any = proxifyContext( {}, {} ); + const context: any = proxifyContext( {}, fallback ); + + context.prop = 'modified'; + + expect( context.prop ).toBe( 'modified' ); + expect( fallback.prop ).toBeUndefined(); + } ); + + it( 'should work with the proxified state', () => { + const state = proxifyState( 'test', { a: 1 } ); + const fallback: any = proxifyContext( state, {} ); + const context: any = proxifyContext( {}, fallback ); + + context.a = 2; + + expect( context.a ).toBe( 2 ); + expect( state.a ).toBe( 2 ); + } ); + } ); + + describe( 'computations', () => { + it( 'should subscribe to changes in the current context', () => { + const fallback: any = proxifyContext( + proxifyState( 'test', { fromFallback: 'fallback' } ), + {} + ); + const context: any = proxifyContext( + proxifyState( 'test', { fromContext: 'context' } ), + fallback + ); + + const spy = jest.fn( () => context.fromContext ); + effect( spy ); + + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( context.fromContext ).toBe( 'context' ); + + context.fromContext = 'modified'; + + expect( spy ).toHaveBeenCalledTimes( 2 ); + expect( context.fromContext ).toBe( 'modified' ); + } ); + + it( 'should subscribe to changes in inherited values', () => { + const fallback: any = proxifyContext( + proxifyState( 'test', { fromFallback: 'fallback' } ), + {} + ); + const context: any = proxifyContext( + proxifyState( 'test', { fromContext: 'context' } ), + fallback + ); + + const spy = jest.fn( () => context.fromFallback ); + effect( spy ); + + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( context.fromFallback ).toBe( 'fallback' ); + + fallback.fromFallback = 'modified'; + + expect( spy ).toHaveBeenCalledTimes( 2 ); + expect( context.fromFallback ).toBe( 'modified' ); + } ); + + it( 'should subscribe to undefined props added to the context', () => { + const fallback: any = proxifyContext( + proxifyState( 'test', {} ), + {} + ); + const context: any = proxifyContext( + proxifyState( 'test', {} ), + fallback + ); + + const spy = jest.fn( () => context.fromContext ); + effect( spy ); + + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( context.fromContext ).toBeUndefined(); + + context.fromContext = 'added'; + + expect( spy ).toHaveBeenCalledTimes( 2 ); + expect( context.fromContext ).toBe( 'added' ); + } ); + + it( 'should subscribe to undefined props added to the fallback', () => { + const fallback: any = proxifyContext( + proxifyState( 'test', {} ), + {} + ); + const context: any = proxifyContext( + proxifyState( 'test', {} ), + fallback + ); + + const spy = jest.fn( () => context.fromFallback ); + effect( spy ); + + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( context.fromFallback ).toBeUndefined(); + + fallback.fromFallback = 'added'; + + expect( spy ).toHaveBeenCalledTimes( 2 ); + expect( context.fromFallback ).toBe( 'added' ); + } ); + + it( 'should subscribe to shadowed props', () => { + const fallbackState: any = proxifyState( 'test', {} ); + const fallback: any = proxifyContext( fallbackState, {} ); + + const contextState: any = proxifyState( 'test', {} ); + const context: any = proxifyContext( contextState, fallback ); + + const spy = jest.fn( () => context.prop ); + effect( spy ); + + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( context.prop ).toBeUndefined(); + + fallbackState.prop = 'fromFallback'; + + expect( spy ).toHaveBeenCalledTimes( 2 ); + expect( context.prop ).toBe( 'fromFallback' ); + + contextState.prop = 'fromContext'; + + expect( spy ).toHaveBeenCalledTimes( 3 ); + expect( context.prop ).toBe( 'fromContext' ); + } ); + + it( 'should subscribe to any changes in listed props', () => { + const fallback: any = proxifyContext( + proxifyState( 'test', {} ), + {} + ); + const context: any = proxifyContext( + proxifyState( 'test', {} ), + fallback + ); + + const spy = jest.fn( () => Object.keys( context ) ); + effect( spy ); + + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( Object.keys( context ) ).toEqual( [] ); + + context.fromContext = 'added'; + fallback.fromFallback = 'added'; + + expect( spy ).toHaveBeenCalledTimes( 3 ); + expect( Object.keys( context ).sort() ).toEqual( [ + 'fromContext', + 'fromFallback', + ] ); + } ); + } ); + + describe( 'proxifyContext', () => { + it( 'should throw when trying to re-proxify a proxy object', () => { + const context = proxifyContext( {}, {} ); + expect( () => proxifyContext( context, {} ) ).toThrow( + 'This object cannot be proxified.' + ); + } ); + } ); + } ); +} ); From 893181e9e9c16b52d85a2d4e8be902cafdb73d6f Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Tue, 17 Sep 2024 13:22:31 -0700 Subject: [PATCH 0835/1908] Block bindings: Bring bindings UI in Site Editor (#64072) * Initial commit. Add meta field to post types. * Add post meta * Add todos * Add fields in all postType * WIP: Add first version to link templates and entities * Revert "WIP: Add first version to link templates and entities" This reverts commit a43e39194f25d39e69426b15a2b9036022f301d3. * Only expose public fields * Add subtype to meta properties * Render the appropriate fields depending on the postType in templates * Use context postType when available * Fetch the data on render, preventing one click needed * Yoda conditions.. * Try: Expose registered meta fields in schema * Try: Create a resolver to get registered post meta * Use rest namespace * Move actions and selectors to private. * Add unlocking and import * Merge useSelect * Fix duplicated * Add object_subtype to schema * Update docs to object_subtype * Add explanatory comment * Block Bindings: Use default values in connected custom fields in templates (#65128) * Abstract `getMetadata` and use it in `getValues` * Adapt e2e tests * Update e2e --------- Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> * Try removing all object subtype * Fix e2e * Update code * Fix `useSelect` warning * Remove old comment * Remove support for generic templates * Revert changes to e2e tests --------- Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: TimothyBJacobs <timothyblynjacobs@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> Co-authored-by: spacedmonkey <spacedmonkey@git.wordpress.org> --- .../block-editor/src/hooks/block-bindings.js | 101 ++++++++++-------- packages/core-data/src/index.js | 2 + packages/core-data/src/private-actions.js | 16 +++ packages/core-data/src/private-selectors.ts | 12 +++ packages/core-data/src/reducer.js | 20 ++++ packages/core-data/src/resolvers.js | 26 +++++ packages/core-data/src/selectors.ts | 1 + packages/e2e-tests/plugins/block-bindings.php | 2 +- packages/editor/src/bindings/post-meta.js | 46 +++++--- .../editor/various/block-bindings.spec.js | 34 +++--- 10 files changed, 184 insertions(+), 76 deletions(-) create mode 100644 packages/core-data/src/private-actions.js diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index be632cd4db3a25..a0bd8820d36c5d 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -31,6 +31,8 @@ import { store as blockEditorStore } from '../store'; const { DropdownMenuV2 } = unlock( componentsPrivateApis ); +const EMPTY_OBJECT = {}; + const useToolsPanelDropdownMenuProps = () => { const isMobile = useViewportMatch( 'medium', '<' ); return ! isMobile @@ -182,11 +184,66 @@ function EditableBlockBindingsPanelItems( { export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { const registry = useRegistry(); const blockContext = useContext( BlockContext ); - const { bindings } = metadata || {}; const { removeAllBlockBindings } = useBlockBindingsUtils(); const bindableAttributes = getBindableAttributes( blockName ); const dropdownMenuProps = useToolsPanelDropdownMenuProps(); + // `useSelect` is used purposely here to ensure `getFieldsList` + // is updated whenever there are updates in block context. + // `source.getFieldsList` may also call a selector via `registry.select`. + const _fieldsList = {}; + const { fieldsList, canUpdateBlockBindings } = useSelect( + ( select ) => { + if ( ! bindableAttributes || bindableAttributes.length === 0 ) { + return EMPTY_OBJECT; + } + const { getBlockBindingsSources } = unlock( blocksPrivateApis ); + const registeredSources = getBlockBindingsSources(); + Object.entries( registeredSources ).forEach( + ( [ sourceName, { getFieldsList, usesContext } ] ) => { + if ( getFieldsList ) { + // Populate context. + const context = {}; + if ( usesContext?.length ) { + for ( const key of usesContext ) { + context[ key ] = blockContext[ key ]; + } + } + const sourceList = getFieldsList( { + registry, + context, + } ); + // Only add source if the list is not empty. + if ( sourceList ) { + _fieldsList[ sourceName ] = { ...sourceList }; + } + } + } + ); + return { + fieldsList: + Object.values( _fieldsList ).length > 0 + ? _fieldsList + : EMPTY_OBJECT, + canUpdateBlockBindings: + select( blockEditorStore ).getSettings() + .canUpdateBlockBindings, + }; + }, + [ blockContext, bindableAttributes, registry ] + ); + // Return early if there are no bindable attributes. + if ( ! bindableAttributes || bindableAttributes.length === 0 ) { + return null; + } + // Remove empty sources from the list of fields. + Object.entries( fieldsList ).forEach( ( [ key, value ] ) => { + if ( ! Object.keys( value ).length ) { + delete fieldsList[ key ]; + } + } ); + // Filter bindings to only show bindable attributes and remove pattern overrides. + const { bindings } = metadata || {}; const filteredBindings = { ...bindings }; Object.keys( filteredBindings ).forEach( ( key ) => { if ( @@ -197,48 +254,6 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { } } ); - const { canUpdateBlockBindings } = useSelect( ( select ) => { - return { - canUpdateBlockBindings: - select( blockEditorStore ).getSettings().canUpdateBlockBindings, - }; - }, [] ); - - if ( ! bindableAttributes || bindableAttributes.length === 0 ) { - return null; - } - - const fieldsList = {}; - const { getBlockBindingsSources } = unlock( blocksPrivateApis ); - const registeredSources = getBlockBindingsSources(); - Object.entries( registeredSources ).forEach( - ( [ sourceName, { getFieldsList, usesContext } ] ) => { - if ( getFieldsList ) { - // Populate context. - const context = {}; - if ( usesContext?.length ) { - for ( const key of usesContext ) { - context[ key ] = blockContext[ key ]; - } - } - const sourceList = getFieldsList( { - registry, - context, - } ); - // Only add source if the list is not empty. - if ( sourceList ) { - fieldsList[ sourceName ] = { ...sourceList }; - } - } - } - ); - // Remove empty sources. - Object.entries( fieldsList ).forEach( ( [ key, value ] ) => { - if ( ! Object.keys( value ).length ) { - delete fieldsList[ key ]; - } - } ); - // Lock the UI when the user can't update bindings or there are no fields to connect to. const readOnly = ! canUpdateBlockBindings || ! Object.keys( fieldsList ).length; diff --git a/packages/core-data/src/index.js b/packages/core-data/src/index.js index ad6adec0203c59..99507a914f377b 100644 --- a/packages/core-data/src/index.js +++ b/packages/core-data/src/index.js @@ -10,6 +10,7 @@ import reducer from './reducer'; import * as selectors from './selectors'; import * as privateSelectors from './private-selectors'; import * as actions from './actions'; +import * as privateActions from './private-actions'; import * as resolvers from './resolvers'; import createLocksActions from './locks/actions'; import { @@ -79,6 +80,7 @@ const storeConfig = () => ( { */ export const store = createReduxStore( STORE_NAME, storeConfig() ); unlock( store ).registerPrivateSelectors( privateSelectors ); +unlock( store ).registerPrivateActions( privateActions ); register( store ); // Register store after unlocking private selectors to allow resolvers to use them. export { default as EntityProvider } from './entity-provider'; diff --git a/packages/core-data/src/private-actions.js b/packages/core-data/src/private-actions.js new file mode 100644 index 00000000000000..df76d2693e54f3 --- /dev/null +++ b/packages/core-data/src/private-actions.js @@ -0,0 +1,16 @@ +/** + * Returns an action object used in signalling that the registered post meta + * fields for a post type have been received. + * + * @param {string} postType Post type slug. + * @param {Object} registeredPostMeta Registered post meta. + * + * @return {Object} Action object. + */ +export function receiveRegisteredPostMeta( postType, registeredPostMeta ) { + return { + type: 'RECEIVE_REGISTERED_POST_META', + postType, + registeredPostMeta, + }; +} diff --git a/packages/core-data/src/private-selectors.ts b/packages/core-data/src/private-selectors.ts index 841f4ee2ef460d..b2f6fa7def9858 100644 --- a/packages/core-data/src/private-selectors.ts +++ b/packages/core-data/src/private-selectors.ts @@ -93,3 +93,15 @@ export function getEntityRecordPermissions( ) { return getEntityRecordsPermissions( state, kind, name, id )[ 0 ]; } + +/** + * Returns the registered post meta fields for a given post type. + * + * @param state Data state. + * @param postType Post type. + * + * @return Registered post meta fields. + */ +export function getRegisteredPostMeta( state: State, postType: string ) { + return state.registeredPostMeta?.[ postType ] ?? {}; +} diff --git a/packages/core-data/src/reducer.js b/packages/core-data/src/reducer.js index 97a8cc59041534..9748355fc5caf6 100644 --- a/packages/core-data/src/reducer.js +++ b/packages/core-data/src/reducer.js @@ -628,6 +628,25 @@ export function defaultTemplates( state = {}, action ) { return state; } +/** + * Reducer returning an object of registered post meta. + * + * @param {Object} state Current state. + * @param {Object} action Dispatched action. + * + * @return {Object} Updated state. + */ +export function registeredPostMeta( state = {}, action ) { + switch ( action.type ) { + case 'RECEIVE_REGISTERED_POST_META': + return { + ...state, + [ action.postType ]: action.registeredPostMeta, + }; + } + return state; +} + export default combineReducers( { terms, users, @@ -649,4 +668,5 @@ export default combineReducers( { userPatternCategories, navigationFallbackId, defaultTemplates, + registeredPostMeta, } ); diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 9229673903623a..ce8c2db7a53b4a 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -984,3 +984,29 @@ export const getRevision = dispatch.receiveRevisions( kind, name, recordKey, record, query ); } }; + +/** + * Requests a specific post type options from the REST API. + * + * @param {string} postType Post type slug. + */ +export const getRegisteredPostMeta = + ( postType ) => + async ( { dispatch, resolveSelect } ) => { + try { + const { + rest_namespace: restNamespace = 'wp/v2', + rest_base: restBase, + } = ( await resolveSelect.getPostType( postType ) ) || {}; + const options = await apiFetch( { + path: `${ restNamespace }/${ restBase }/?context=edit`, + method: 'OPTIONS', + } ); + dispatch.receiveRegisteredPostMeta( + postType, + options?.schema?.properties?.meta?.properties + ); + } catch { + dispatch.receiveRegisteredPostMeta( postType, false ); + } + }; diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index aeec14782ce4fb..ba22723f951f4e 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -47,6 +47,7 @@ export interface State { navigationFallbackId: EntityRecordKey; userPatternCategories: Array< UserPatternCategory >; defaultTemplates: Record< string, string >; + registeredPostMeta: Record< string, { postType: string } >; } type EntityRecordKey = string | number; diff --git a/packages/e2e-tests/plugins/block-bindings.php b/packages/e2e-tests/plugins/block-bindings.php index 143feb240ac2ef..8951255d516bfc 100644 --- a/packages/e2e-tests/plugins/block-bindings.php +++ b/packages/e2e-tests/plugins/block-bindings.php @@ -28,7 +28,7 @@ function gutenberg_test_block_bindings_registration() { 'show_in_rest' => true, 'type' => 'string', 'single' => true, - 'default' => 'Value of the text_custom_field', + 'default' => 'Value of the text custom field', ) ); register_meta( diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index 7618ba6c360236..0562c1f7adf07d 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -7,22 +7,43 @@ import { store as coreDataStore } from '@wordpress/core-data'; * Internal dependencies */ import { store as editorStore } from '../store'; +import { unlock } from '../lock-unlock'; + +function getMetadata( registry, context ) { + let metaFields = {}; + const { type } = registry.select( editorStore ).getCurrentPost(); + const { getEditedEntityRecord } = registry.select( coreDataStore ); + const { getRegisteredPostMeta } = unlock( + registry.select( coreDataStore ) + ); + + if ( type === 'wp_template' ) { + const fields = getRegisteredPostMeta( context?.postType ); + // Populate the `metaFields` object with the default values. + Object.entries( fields || {} ).forEach( ( [ key, props ] ) => { + metaFields[ key ] = props.default; + } ); + } else { + metaFields = getEditedEntityRecord( + 'postType', + context?.postType, + context?.postId + ).meta; + } + + return metaFields; +} export default { name: 'core/post-meta', getValues( { registry, context, bindings } ) { - const meta = registry - .select( coreDataStore ) - .getEditedEntityRecord( - 'postType', - context?.postType, - context?.postId - )?.meta; + const metaFields = getMetadata( registry, context ); + const newValues = {}; for ( const [ attributeName, source ] of Object.entries( bindings ) ) { // Use the key if the value is not set. newValues[ attributeName ] = - meta?.[ source.args.key ] ?? source.args.key; + metaFields?.[ source.args.key ] ?? source.args.key; } return newValues; }, @@ -82,19 +103,14 @@ export default { return true; }, getFieldsList( { registry, context } ) { - const metaFields = registry - .select( coreDataStore ) - .getEditedEntityRecord( - 'postType', - context?.postType, - context?.postId - ).meta; + const metaFields = getMetadata( registry, context ); if ( ! metaFields || ! Object.keys( metaFields ).length ) { return null; } // Remove footnotes or private keys from the list of fields. + // TODO: Remove this once we retrieve the fields from 'types' endpoint in post or page editor. return Object.fromEntries( Object.entries( metaFields ).filter( ( [ key ] ) => key !== 'footnotes' && key.charAt( 0 ) !== '_' diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index 6e36b6ad5dd335..c556c469698ebd 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -1231,14 +1231,14 @@ test.describe( 'Block bindings', () => { name: 'Block: Paragraph', } ); await expect( paragraphBlock ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); // Check the frontend shows the value of the custom field. const previewPage = await editor.openPreviewPage(); await expect( previewPage.locator( '#paragraph-binding' ) - ).toHaveText( 'Value of the text_custom_field' ); + ).toHaveText( 'Value of the text custom field' ); } ); test( "should show the value of the key when custom field doesn't exist", async ( { @@ -1400,7 +1400,7 @@ test.describe( 'Block bindings', () => { .locator( '[data-type="core/paragraph"]' ) .all(); await expect( initialParagraph ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); await expect( newEmptyParagraph ).toHaveText( '' ); await expect( newEmptyParagraph ).toBeEditable(); @@ -1510,7 +1510,7 @@ test.describe( 'Block bindings', () => { name: 'Block: Paragraph', } ); await expect( paragraphBlock ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); } ); } ); @@ -1538,14 +1538,14 @@ test.describe( 'Block bindings', () => { name: 'Block: Heading', } ); await expect( headingBlock ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); // Check the frontend shows the value of the custom field. const previewPage = await editor.openPreviewPage(); await expect( previewPage.locator( '#heading-binding' ) - ).toHaveText( 'Value of the text_custom_field' ); + ).toHaveText( 'Value of the text custom field' ); } ); test( 'should add empty paragraph block when pressing enter', async ( { @@ -1584,7 +1584,7 @@ test.describe( 'Block bindings', () => { 'core/heading' ); await expect( initialHeading ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); // Second block should be an empty paragraph block. await expect( newEmptyParagraph ).toHaveAttribute( @@ -1642,7 +1642,7 @@ test.describe( 'Block bindings', () => { .getByRole( 'textbox' ); await buttonBlock.click(); await expect( buttonBlock ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); // Check the frontend shows the value of the custom field. @@ -1651,7 +1651,7 @@ test.describe( 'Block bindings', () => { '#button-text-binding a' ); await expect( buttonDom ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); await expect( buttonDom ).toHaveAttribute( 'href', @@ -1731,7 +1731,7 @@ test.describe( 'Block bindings', () => { '#button-multiple-bindings a' ); await expect( buttonDom ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); await expect( buttonDom ).toHaveAttribute( 'href', @@ -1778,7 +1778,7 @@ test.describe( 'Block bindings', () => { .all(); // First block should be the original block. await expect( initialButton ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); // Second block should be an empty paragraph block. await expect( newEmptyButton ).toHaveText( '' ); @@ -1943,7 +1943,7 @@ test.describe( 'Block bindings', () => { .getByRole( 'tabpanel', { name: 'Settings' } ) .getByLabel( 'Alternative text' ) .inputValue(); - expect( altValue ).toBe( 'Value of the text_custom_field' ); + expect( altValue ).toBe( 'Value of the text custom field' ); // Check the frontend uses the value of the custom field. const previewPage = await editor.openPreviewPage(); @@ -1956,7 +1956,7 @@ test.describe( 'Block bindings', () => { ); await expect( imageDom ).toHaveAttribute( 'alt', - 'Value of the text_custom_field' + 'Value of the text custom field' ); await expect( imageDom ).toHaveAttribute( 'title', @@ -2013,7 +2013,7 @@ test.describe( 'Block bindings', () => { .getByRole( 'tabpanel', { name: 'Settings' } ) .getByLabel( 'Title attribute' ) .inputValue(); - expect( titleValue ).toBe( 'Value of the text_custom_field' ); + expect( titleValue ).toBe( 'Value of the text custom field' ); // Check the frontend uses the value of the custom field. const previewPage = await editor.openPreviewPage(); @@ -2030,7 +2030,7 @@ test.describe( 'Block bindings', () => { ); await expect( imageDom ).toHaveAttribute( 'title', - 'Value of the text_custom_field' + 'Value of the text custom field' ); } ); @@ -2077,7 +2077,7 @@ test.describe( 'Block bindings', () => { .getByRole( 'tabpanel', { name: 'Settings' } ) .getByLabel( 'Alternative text' ) .inputValue(); - expect( altValue ).toBe( 'Value of the text_custom_field' ); + expect( altValue ).toBe( 'Value of the text custom field' ); // Title input should have the original value. const advancedButton = page @@ -2107,7 +2107,7 @@ test.describe( 'Block bindings', () => { ); await expect( imageDom ).toHaveAttribute( 'alt', - 'Value of the text_custom_field' + 'Value of the text custom field' ); await expect( imageDom ).toHaveAttribute( 'title', From 672299058c9341b821f198c7bdd03a4c094a0bf8 Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Tue, 17 Sep 2024 13:31:14 -0700 Subject: [PATCH 0836/1908] Target Hints: Add missing param sanitization (#65280) --- backport-changelog/6.7/7139.md | 1 + .../class-gutenberg-rest-server.php | 38 +++++++++++++------ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/backport-changelog/6.7/7139.md b/backport-changelog/6.7/7139.md index 9023695102a919..b5b0090fbaa563 100644 --- a/backport-changelog/6.7/7139.md +++ b/backport-changelog/6.7/7139.md @@ -1,3 +1,4 @@ https://github.com/WordPress/wordpress-develop/pull/7139 * https://github.com/WordPress/gutenberg/pull/64504 +* https://github.com/WordPress/gutenberg/pull/65280 diff --git a/lib/compat/wordpress-6.7/class-gutenberg-rest-server.php b/lib/compat/wordpress-6.7/class-gutenberg-rest-server.php index 8374e8dc1fa23f..efdc41289dfac2 100644 --- a/lib/compat/wordpress-6.7/class-gutenberg-rest-server.php +++ b/lib/compat/wordpress-6.7/class-gutenberg-rest-server.php @@ -95,17 +95,33 @@ public static function get_response_links( $response ) { continue; } - $match = $server->match_request_to_handler( $request ); - if ( ! is_wp_error( $match ) ) { - $response = new WP_REST_Response(); - $response->set_matched_route( $match[0] ); - $response->set_matched_handler( $match[1] ); - $headers = rest_send_allow_header( $response, $server, $request )->get_headers(); - - foreach ( $headers as $name => $value ) { - $name = WP_REST_Request::canonicalize_header_name( $name ); - $attributes['targetHints'][ $name ] = array_map( 'trim', explode( ',', $value ) ); - } + $matched = $server->match_request_to_handler( $request ); + + if ( is_wp_error( $matched ) ) { + $data[ $rel ][] = $attributes; + continue; + } + + if ( is_wp_error( $request->has_valid_params() ) ) { + $data[ $rel ][] = $attributes; + continue; + } + + if ( is_wp_error( $request->sanitize_params() ) ) { + $data[ $rel ][] = $attributes; + continue; + } + + list( $route, $handler ) = $matched; + + $response = new WP_REST_Response(); + $response->set_matched_route( $route ); + $response->set_matched_handler( $handler ); + $headers = rest_send_allow_header( $response, $server, $request )->get_headers(); + + foreach ( $headers as $name => $value ) { + $name = WP_REST_Request::canonicalize_header_name( $name ); + $attributes['targetHints'][ $name ] = array_map( 'trim', explode( ',', $value ) ); } $data[ $rel ][] = $attributes; From 7f9c3402f8bbfd0895c688371f53bd66797c1a90 Mon Sep 17 00:00:00 2001 From: Bernie Reiter <96308+ockham@users.noreply.github.com> Date: Tue, 17 Sep 2024 22:38:09 +0200 Subject: [PATCH 0837/1908] Categories List block: Add dropdown for taxonomies (#65272) Add a new `taxonomy` attribute to the Categories List block, and a dropdown to the block inspector to set that attribute. For backwards compatibility, the attribute defaults to `category`. Furthermore, rename the block to "Terms List". Unlinked contributors: MikeB8s, sophiegyo. Co-authored-by: ockham <bernhard-reiter@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: Julianoe <julianoe@git.wordpress.org> Co-authored-by: celloexpressions <celloexpressions@git.wordpress.org> Co-authored-by: skorasaurus <skorasaurus@git.wordpress.org> Co-authored-by: ms-studio <targz-1@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: justintadlock <greenshady@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: joedolson <joedolson@git.wordpress.org> Co-authored-by: coreyworrell <coreyw@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 6 +- .../block-library/src/categories/block.json | 9 +- packages/block-library/src/categories/edit.js | 97 +++++++++++++------ .../block-library/src/categories/index.php | 30 ++++-- .../fixtures/blocks/core__categories.json | 1 + 5 files changed, 99 insertions(+), 44 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 0e0de9d4f8a507..66f713b3aa40fc 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -72,14 +72,14 @@ A calendar of your site’s posts. ([Source](https://github.com/WordPress/gutenb - **Supports:** align, color (background, link, text), interactivity (clientNavigation), typography (fontSize, lineHeight) - **Attributes:** month, year -## Categories List +## Terms List -Display a list of all categories. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/categories)) +Display a list of all terms of a given taxonomy. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/categories)) - **Name:** core/categories - **Category:** widgets - **Supports:** align, interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~ -- **Attributes:** displayAsDropdown, label, showEmpty, showHierarchy, showLabel, showOnlyTopLevel, showPostCounts +- **Attributes:** displayAsDropdown, label, showEmpty, showHierarchy, showLabel, showOnlyTopLevel, showPostCounts, taxonomy ## Code diff --git a/packages/block-library/src/categories/block.json b/packages/block-library/src/categories/block.json index 460fbef92fdab2..bfd8461f8eda43 100644 --- a/packages/block-library/src/categories/block.json +++ b/packages/block-library/src/categories/block.json @@ -2,11 +2,16 @@ "$schema": "https://schemas.wp.org/trunk/block.json", "apiVersion": 3, "name": "core/categories", - "title": "Categories List", + "title": "Terms List", "category": "widgets", - "description": "Display a list of all categories.", + "description": "Display a list of all terms of a given taxonomy.", + "keywords": [ "categories" ], "textdomain": "default", "attributes": { + "taxonomy": { + "type": "string", + "default": "category" + }, "displayAsDropdown": { "type": "boolean", "default": false diff --git a/packages/block-library/src/categories/edit.js b/packages/block-library/src/categories/edit.js index 48d505eeb75aee..ccbf9194339408 100644 --- a/packages/block-library/src/categories/edit.js +++ b/packages/block-library/src/categories/edit.js @@ -9,6 +9,7 @@ import clsx from 'clsx'; import { PanelBody, Placeholder, + SelectControl, Spinner, ToggleControl, VisuallyHidden, @@ -20,7 +21,7 @@ import { RichText, } from '@wordpress/block-editor'; import { decodeEntities } from '@wordpress/html-entities'; -import { __ } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; import { pin } from '@wordpress/icons'; import { useEntityRecords } from '@wordpress/core-data'; @@ -33,19 +34,33 @@ export default function CategoriesEdit( { showEmpty, label, showLabel, + taxonomy: taxonomySlug, }, setAttributes, className, } ) { const selectId = useInstanceId( CategoriesEdit, 'blocks-category-select' ); + + const { records: allTaxonomies, isResolvingTaxonomies } = useEntityRecords( + 'root', + 'taxonomy' + ); + + const taxonomies = allTaxonomies?.filter( ( t ) => t.visibility.public ); + + const taxonomy = taxonomies?.find( ( t ) => t.slug === taxonomySlug ); + + const isHierarchicalTaxonomy = + ! isResolvingTaxonomies && taxonomy?.hierarchical; + const query = { per_page: -1, hide_empty: ! showEmpty, context: 'view' }; - if ( showOnlyTopLevel ) { + if ( isHierarchicalTaxonomy && showOnlyTopLevel ) { query.parent = 0; } const { records: categories, isResolving } = useEntityRecords( 'taxonomy', - 'category', + taxonomySlug, query ); @@ -66,7 +81,7 @@ export default function CategoriesEdit( { ! name ? __( '(Untitled)' ) : decodeEntities( name ).trim(); const renderCategoryList = () => { - const parentId = showHierarchy ? 0 : null; + const parentId = isHierarchicalTaxonomy && showHierarchy ? 0 : null; const categoriesList = getCategoriesList( parentId ); return categoriesList.map( ( category ) => renderCategoryListItem( category ) @@ -82,19 +97,21 @@ export default function CategoriesEdit( { { renderCategoryName( name ) } </a> { showPostCounts && ` (${ count })` } - { showHierarchy && !! childCategories.length && ( - <ul className="children"> - { childCategories.map( ( childCategory ) => - renderCategoryListItem( childCategory ) - ) } - </ul> - ) } + { isHierarchicalTaxonomy && + showHierarchy && + !! childCategories.length && ( + <ul className="children"> + { childCategories.map( ( childCategory ) => + renderCategoryListItem( childCategory ) + ) } + </ul> + ) } </li> ); }; const renderCategoryDropdown = () => { - const parentId = showHierarchy ? 0 : null; + const parentId = isHierarchicalTaxonomy && showHierarchy ? 0 : null; const categoriesList = getCategoriesList( parentId ); return ( <> @@ -102,7 +119,7 @@ export default function CategoriesEdit( { <RichText className="wp-block-categories__label" aria-label={ __( 'Label text' ) } - placeholder={ __( 'Categories' ) } + placeholder={ taxonomy.name } withoutInteractiveFormatting value={ label } onChange={ ( html ) => @@ -111,11 +128,17 @@ export default function CategoriesEdit( { /> ) : ( <VisuallyHidden as="label" htmlFor={ selectId }> - { label ? label : __( 'Categories' ) } + { label ? label : taxonomy.name } </VisuallyHidden> ) } <select id={ selectId }> - <option>{ __( 'Select Category' ) }</option> + <option> + { sprintf( + /* translators: %s: taxonomy's singular name */ + __( 'Select %s' ), + taxonomy.labels.singular_name + ) } + </option> { categoriesList.map( ( category ) => renderCategoryDropdownItem( category, 0 ) ) } @@ -133,7 +156,8 @@ export default function CategoriesEdit( { { renderCategoryName( name ) } { showPostCounts && ` (${ count })` } </option>, - showHierarchy && + isHierarchicalTaxonomy && + showHierarchy && !! childCategories.length && childCategories.map( ( childCategory ) => renderCategoryDropdownItem( childCategory, level + 1 ) @@ -161,6 +185,21 @@ export default function CategoriesEdit( { <TagName { ...blockProps }> <InspectorControls> <PanelBody title={ __( 'Settings' ) }> + { Array.isArray( taxonomies ) && ( + <SelectControl + __nextHasNoMarginBottom + __next40pxDefaultSize + label={ __( 'Taxonomy' ) } + options={ taxonomies.map( ( t ) => ( { + label: t.name, + value: t.slug, + } ) ) } + value={ taxonomySlug } + onChange={ ( selectedTaxonomy ) => + setAttributes( { taxonomy: selectedTaxonomy } ) + } + /> + ) } <ToggleControl __nextHasNoMarginBottom label={ __( 'Display as dropdown' ) } @@ -182,19 +221,21 @@ export default function CategoriesEdit( { checked={ showPostCounts } onChange={ toggleAttribute( 'showPostCounts' ) } /> + { isHierarchicalTaxonomy && ( + <ToggleControl + __nextHasNoMarginBottom + label={ __( 'Show only top level terms' ) } + checked={ showOnlyTopLevel } + onChange={ toggleAttribute( 'showOnlyTopLevel' ) } + /> + ) } <ToggleControl __nextHasNoMarginBottom - label={ __( 'Show only top level categories' ) } - checked={ showOnlyTopLevel } - onChange={ toggleAttribute( 'showOnlyTopLevel' ) } - /> - <ToggleControl - __nextHasNoMarginBottom - label={ __( 'Show empty categories' ) } + label={ __( 'Show empty terms' ) } checked={ showEmpty } onChange={ toggleAttribute( 'showEmpty' ) } /> - { ! showOnlyTopLevel && ( + { isHierarchicalTaxonomy && ! showOnlyTopLevel && ( <ToggleControl __nextHasNoMarginBottom label={ __( 'Show hierarchy' ) } @@ -205,16 +246,12 @@ export default function CategoriesEdit( { </PanelBody> </InspectorControls> { isResolving && ( - <Placeholder icon={ pin } label={ __( 'Categories' ) }> + <Placeholder icon={ pin } label={ __( 'Terms' ) }> <Spinner /> </Placeholder> ) } { ! isResolving && categories?.length === 0 && ( - <p> - { __( - 'Your site does not have any posts, so there is nothing to display here at the moment.' - ) } - </p> + <p>{ taxonomy.labels.no_terms }</p> ) } { ! isResolving && categories?.length > 0 && diff --git a/packages/block-library/src/categories/index.php b/packages/block-library/src/categories/index.php index 5c0cc63415cb78..e15f662bdfbb9b 100644 --- a/packages/block-library/src/categories/index.php +++ b/packages/block-library/src/categories/index.php @@ -21,11 +21,14 @@ function render_block_core_categories( $attributes, $content, $block ) { static $block_id = 0; ++$block_id; + $taxonomy = get_taxonomy( $attributes['taxonomy'] ); + $args = array( 'echo' => false, 'hierarchical' => ! empty( $attributes['showHierarchy'] ), 'orderby' => 'name', 'show_count' => ! empty( $attributes['showPostCounts'] ), + 'taxonomy' => $attributes['taxonomy'], 'title_li' => '', 'hide_empty' => empty( $attributes['showEmpty'] ), ); @@ -36,13 +39,20 @@ function render_block_core_categories( $attributes, $content, $block ) { if ( ! empty( $attributes['displayAsDropdown'] ) ) { $id = 'wp-block-categories-' . $block_id; $args['id'] = $id; - $args['show_option_none'] = __( 'Select Category' ); - $show_label = empty( $attributes['showLabel'] ) ? ' screen-reader-text' : ''; - $default_label = __( 'Categories' ); - $label_text = ! empty( $attributes['label'] ) ? $attributes['label'] : $default_label; - $wrapper_markup = '<div %1$s><label class="wp-block-categories__label' . $show_label . '" for="' . esc_attr( $id ) . '">' . $label_text . '</label>%2$s</div>'; - $items_markup = wp_dropdown_categories( $args ); - $type = 'dropdown'; + $args['name'] = $taxonomy->query_var; + $args['value_field'] = 'slug'; + $args['show_option_none'] = sprintf( + /* translators: %s: taxonomy's singular name */ + __( 'Select %s' ), + $taxonomy->labels->singular_name + ); + + $show_label = empty( $attributes['showLabel'] ) ? ' screen-reader-text' : ''; + $default_label = $taxonomy->label; + $label_text = ! empty( $attributes['label'] ) ? $attributes['label'] : $default_label; + $wrapper_markup = '<div %1$s><label class="wp-block-categories__label' . $show_label . '" for="' . esc_attr( $id ) . '">' . $label_text . '</label>%2$s</div>'; + $items_markup = wp_dropdown_categories( $args ); + $type = 'dropdown'; if ( ! is_admin() ) { // Inject the dropdown script immediately after the select dropdown. @@ -54,6 +64,8 @@ function render_block_core_categories( $attributes, $content, $block ) { ); } } else { + $args['show_option_none'] = $taxonomy->labels->no_terms; + $wrapper_markup = '<ul %1$s>%2$s</ul>'; $items_markup = wp_list_categories( $args ); $type = 'list'; @@ -92,8 +104,8 @@ function build_dropdown_script_block_core_categories( $dropdown_id ) { ( function() { var dropdown = document.getElementById( '<?php echo esc_js( $dropdown_id ); ?>' ); function onCatChange() { - if ( dropdown.options[ dropdown.selectedIndex ].value > 0 ) { - location.href = "<?php echo esc_url( home_url() ); ?>/?cat=" + dropdown.options[ dropdown.selectedIndex ].value; + if ( dropdown.options[ dropdown.selectedIndex ].value !== -1 ) { + location.href = "<?php echo esc_url( home_url() ); ?>/?" + dropdown.name + '=' + dropdown.options[ dropdown.selectedIndex ].value; } } dropdown.onchange = onCatChange; diff --git a/test/integration/fixtures/blocks/core__categories.json b/test/integration/fixtures/blocks/core__categories.json index 5d271aa5c84990..698105d8921341 100644 --- a/test/integration/fixtures/blocks/core__categories.json +++ b/test/integration/fixtures/blocks/core__categories.json @@ -3,6 +3,7 @@ "name": "core/categories", "isValid": true, "attributes": { + "taxonomy": "category", "displayAsDropdown": false, "showHierarchy": false, "showPostCounts": false, From f77a46674dcf775f1f9b4f234679bb12c9a888a4 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:41:47 +1000 Subject: [PATCH 0838/1908] Global Styles: allow read access to users with `edit_posts` capabilities (#65071) Allows any role that can edit a post, including custom post types, or edit theme options to read global styles from the API and in the editor. This enables read-only access to global styles in the post editor. Adds test coverage. --------- Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: spacedmonkey <spacedmonkey@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: peterwilsoncc <peterwilsoncc@git.wordpress.org> Co-authored-by: kraftner <kraftner@git.wordpress.org> --- backport-changelog/6.7/7336.md | 3 + ...est-global-styles-controller-gutenberg.php | 51 ++++++----- lib/compat/wordpress-6.7/rest-api.php | 23 +++++ packages/core-data/src/resolvers.js | 4 +- .../global-styles-provider/index.js | 86 +++++++++++-------- ...lobal-styles-controller-gutenberg-test.php | 69 ++++++++++++++- 6 files changed, 168 insertions(+), 68 deletions(-) create mode 100644 backport-changelog/6.7/7336.md diff --git a/backport-changelog/6.7/7336.md b/backport-changelog/6.7/7336.md new file mode 100644 index 00000000000000..7cb2e26d7eeb95 --- /dev/null +++ b/backport-changelog/6.7/7336.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7336 + +* https://github.com/WordPress/gutenberg/pull/65071 diff --git a/lib/class-wp-rest-global-styles-controller-gutenberg.php b/lib/class-wp-rest-global-styles-controller-gutenberg.php index e33304e596e129..1f6543fa184283 100644 --- a/lib/class-wp-rest-global-styles-controller-gutenberg.php +++ b/lib/class-wp-rest-global-styles-controller-gutenberg.php @@ -532,27 +532,39 @@ public function get_item_schema() { * Checks if a given request has access to read a single theme global styles config. * * @since 5.9.0 + * @since 6.7.0 Allow users with edit post capabilities to view theme global styles. * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. */ public function get_theme_item_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable + /* + * Verify if the current user has edit_posts capability. + */ + if ( current_user_can( 'edit_posts' ) ) { + return true; + } + + foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) { + if ( current_user_can( $post_type->cap->edit_posts ) ) { + return true; + } + } /* * Verify if the current user has edit_theme_options capability. - * This capability is required to edit/view/delete global styles. */ - if ( ! current_user_can( 'edit_theme_options' ) ) { - return new WP_Error( - 'rest_cannot_manage_global_styles', - __( 'Sorry, you are not allowed to access the global styles on this site.', 'gutenberg' ), - array( - 'status' => rest_authorization_required_code(), - ) - ); + if ( current_user_can( 'edit_theme_options' ) ) { + return true; } - return true; + return new WP_Error( + 'rest_cannot_read_global_styles', + __( 'Sorry, you are not allowed to access the global styles on this site.', 'gutenberg' ), + array( + 'status' => rest_authorization_required_code(), + ) + ); } /** @@ -616,23 +628,8 @@ public function get_theme_item( $request ) { * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. */ - public function get_theme_items_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable - - /* - * Verify if the current user has edit_theme_options capability. - * This capability is required to edit/view/delete global styles. - */ - if ( ! current_user_can( 'edit_theme_options' ) ) { - return new WP_Error( - 'rest_cannot_manage_global_styles', - __( 'Sorry, you are not allowed to access the global styles on this site.', 'gutenberg' ), - array( - 'status' => rest_authorization_required_code(), - ) - ); - } - - return true; + public function get_theme_items_permissions_check( $request ) { + return $this->get_theme_item_permissions_check( $request ); } /** diff --git a/lib/compat/wordpress-6.7/rest-api.php b/lib/compat/wordpress-6.7/rest-api.php index c5e2927198da0c..313367594caae0 100644 --- a/lib/compat/wordpress-6.7/rest-api.php +++ b/lib/compat/wordpress-6.7/rest-api.php @@ -114,3 +114,26 @@ function gutenberg_override_default_rest_server() { return 'Gutenberg_REST_Server'; } add_filter( 'wp_rest_server_class', 'gutenberg_override_default_rest_server', 1 ); + + +/** + * Filters the arguments for registering a wp_global_styles post type. + * Note when syncing to Core: the capabilities should be updates for `wp_global_styles` in the wp-includes/post.php. + * + * @since 6.7.0 + * + * @param array $args Array of arguments for registering a post type. + * See the register_post_type() function for accepted arguments. + * @param string $post_type Post type key. + * + * @return array Array of arguments for registering a post type. + */ +function gutenberg_register_post_type_args_for_wp_global_styles( $args, $post_type ) { + if ( 'wp_global_styles' === $post_type ) { + $args['capabilities']['read'] = 'edit_posts'; + } + + return $args; +} + +add_filter( 'register_post_type_args', 'gutenberg_register_post_type_args_for_wp_global_styles', 10, 2 ); diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index ce8c2db7a53b4a..6cc7df27f48b1f 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -645,7 +645,7 @@ export const __experimentalGetCurrentThemeBaseGlobalStyles = async ( { resolveSelect, dispatch } ) => { const currentTheme = await resolveSelect.getCurrentTheme(); const themeGlobalStyles = await apiFetch( { - path: `/wp/v2/global-styles/themes/${ currentTheme.stylesheet }`, + path: `/wp/v2/global-styles/themes/${ currentTheme.stylesheet }?context=view`, } ); dispatch.__experimentalReceiveThemeBaseGlobalStyles( currentTheme.stylesheet, @@ -658,7 +658,7 @@ export const __experimentalGetCurrentThemeGlobalStylesVariations = async ( { resolveSelect, dispatch } ) => { const currentTheme = await resolveSelect.getCurrentTheme(); const variations = await apiFetch( { - path: `/wp/v2/global-styles/themes/${ currentTheme.stylesheet }/variations`, + path: `/wp/v2/global-styles/themes/${ currentTheme.stylesheet }/variations?context=view`, } ); dispatch.__experimentalReceiveThemeGlobalStyleVariations( currentTheme.stylesheet, diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js index 8268997d1f1def..6f2d8177056cb1 100644 --- a/packages/editor/src/components/global-styles-provider/index.js +++ b/packages/editor/src/components/global-styles-provider/index.js @@ -46,24 +46,38 @@ export function mergeBaseAndUserConfigs( base, user ) { function useGlobalStylesUserConfig() { const { globalStylesId, isReady, settings, styles, _links } = useSelect( ( select ) => { - const { getEditedEntityRecord, hasFinishedResolution, canUser } = - select( coreStore ); + const { + getEntityRecord, + getEditedEntityRecord, + hasFinishedResolution, + canUser, + } = select( coreStore ); const _globalStylesId = select( coreStore ).__experimentalGetCurrentGlobalStylesId(); - const record = - _globalStylesId && - canUser( 'read', { - kind: 'root', - name: 'globalStyles', - id: _globalStylesId, - } ) - ? getEditedEntityRecord( - 'root', - 'globalStyles', - _globalStylesId - ) - : undefined; + let record; + const userCanEditGlobalStyles = canUser( 'update', { + kind: 'root', + name: 'globalStyles', + id: _globalStylesId, + } ); + + if ( _globalStylesId ) { + if ( userCanEditGlobalStyles ) { + record = getEditedEntityRecord( + 'root', + 'globalStyles', + _globalStylesId + ); + } else { + record = getEntityRecord( + 'root', + 'globalStyles', + _globalStylesId, + { context: 'view' } + ); + } + } let hasResolved = false; if ( @@ -71,13 +85,22 @@ function useGlobalStylesUserConfig() { '__experimentalGetCurrentGlobalStylesId' ) ) { - hasResolved = _globalStylesId - ? hasFinishedResolution( 'getEditedEntityRecord', [ - 'root', - 'globalStyles', - _globalStylesId, - ] ) - : true; + if ( _globalStylesId ) { + hasResolved = userCanEditGlobalStyles + ? hasFinishedResolution( 'getEditedEntityRecord', [ + 'root', + 'globalStyles', + _globalStylesId, + ] ) + : hasFinishedResolution( 'getEntityRecord', [ + 'root', + 'globalStyles', + _globalStylesId, + { context: 'view' }, + ] ); + } else { + hasResolved = true; + } } return { @@ -145,20 +168,11 @@ function useGlobalStylesUserConfig() { } function useGlobalStylesBaseConfig() { - const baseConfig = useSelect( ( select ) => { - const { - __experimentalGetCurrentThemeBaseGlobalStyles, - getCurrentTheme, - canUser, - } = select( coreStore ); - const currentTheme = getCurrentTheme(); - - return currentTheme && - canUser( 'read', 'global-styles/themes', currentTheme.stylesheet ) - ? __experimentalGetCurrentThemeBaseGlobalStyles() - : undefined; - }, [] ); - + const baseConfig = useSelect( + ( select ) => + select( coreStore ).__experimentalGetCurrentThemeBaseGlobalStyles(), + [] + ); return [ !! baseConfig, baseConfig ]; } diff --git a/phpunit/class-wp-rest-global-styles-controller-gutenberg-test.php b/phpunit/class-wp-rest-global-styles-controller-gutenberg-test.php index 85731a7dff5206..c9453f4bd8e5c3 100644 --- a/phpunit/class-wp-rest-global-styles-controller-gutenberg-test.php +++ b/phpunit/class-wp-rest-global-styles-controller-gutenberg-test.php @@ -12,11 +12,21 @@ class WP_REST_Global_Styles_Controller_Gutenberg_Test extends WP_Test_REST_Contr */ protected static $admin_id; + /** + * @var int + */ + protected static $editor_id; + /** * @var int */ protected static $subscriber_id; + /** + * @var int + */ + protected static $theme_manager_id; + /** * @var int */ @@ -44,12 +54,30 @@ public static function wpSetupBeforeClass( $factory ) { ) ); + self::$editor_id = $factory->user->create( + array( + 'role' => 'editor', + ) + ); + self::$subscriber_id = $factory->user->create( array( 'role' => 'subscriber', ) ); + self::$theme_manager_id = $factory->user->create( + array( + 'role' => 'subscriber', + ) + ); + + // Add the 'edit_theme_options' capability to the theme manager (subscriber). + $theme_manager_id = get_user_by( 'id', self::$theme_manager_id ); + if ( $theme_manager_id instanceof WP_User ) { + $theme_manager_id->add_cap( 'edit_theme_options' ); + } + // This creates the global styles for the current theme. self::$global_styles_id = $factory->post->create( array( @@ -72,7 +100,9 @@ public static function wpSetupBeforeClass( $factory ) { */ public static function wpTearDownAfterClass() { self::delete_user( self::$admin_id ); + self::delete_user( self::$editor_id ); self::delete_user( self::$subscriber_id ); + self::delete_user( self::$theme_manager_id ); } /** @@ -195,17 +225,50 @@ public function test_get_theme_item_no_user() { wp_set_current_user( 0 ); $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/themes/emptytheme' ); $response = rest_get_server()->dispatch( $request ); - $this->assertErrorResponse( 'rest_cannot_manage_global_styles', $response, 401 ); + $this->assertErrorResponse( 'rest_cannot_read_global_styles', $response, 401 ); } /** * @covers WP_REST_Global_Styles_Controller_Gutenberg::get_theme_item */ - public function test_get_theme_item_permission_check() { + public function test_get_theme_item_subscriber_permission_check() { wp_set_current_user( self::$subscriber_id ); + switch_theme( 'emptytheme' ); + $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/themes/emptytheme' ); + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_cannot_read_global_styles', $response, 403 ); + } + + /** + * @covers WP_REST_Global_Styles_Controller_Gutenberg::get_theme_item + */ + public function test_get_theme_item_editor_permission_check() { + wp_set_current_user( self::$editor_id ); + switch_theme( 'emptytheme' ); $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/themes/emptytheme' ); $response = rest_get_server()->dispatch( $request ); - $this->assertErrorResponse( 'rest_cannot_manage_global_styles', $response, 403 ); + // Checks that the response has the expected keys. + $data = $response->get_data(); + $links = $response->get_links(); + $this->assertArrayHasKey( 'settings', $data, 'Data does not have "settings" key' ); + $this->assertArrayHasKey( 'styles', $data, 'Data does not have "styles" key' ); + $this->assertArrayHasKey( 'self', $links, 'Links do not have a "self" key' ); + } + + /** + * @covers WP_REST_Global_Styles_Controller_Gutenberg::get_theme_item + */ + public function test_get_theme_item_theme_options_manager_permission_check() { + wp_set_current_user( self::$theme_manager_id ); + switch_theme( 'emptytheme' ); + $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/themes/emptytheme' ); + $response = rest_get_server()->dispatch( $request ); + // Checks that the response has the expected keys. + $data = $response->get_data(); + $links = $response->get_links(); + $this->assertArrayHasKey( 'settings', $data, 'Data does not have "settings" key' ); + $this->assertArrayHasKey( 'styles', $data, 'Data does not have "styles" key' ); + $this->assertArrayHasKey( 'self', $links, 'Links do not have a "self" key' ); } /** From d67b83f54efda21d4a59827f30eb7a370e521582 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:42:42 +1000 Subject: [PATCH 0839/1908] Typography: Make title blocks apply typographic styles consistently (#65307) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: vcanales <vcanales@git.wordpress.org> Co-authored-by: justintadlock <greenshady@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../block-library/src/post-title/block.json | 5 +--- .../block-library/src/post-title/style.scss | 25 +++---------------- .../block-library/src/site-title/block.json | 5 +--- .../block-library/src/site-title/style.scss | 25 +++---------------- 4 files changed, 10 insertions(+), 50 deletions(-) diff --git a/packages/block-library/src/post-title/block.json b/packages/block-library/src/post-title/block.json index 5e7d3eee9dd11d..ecb5053d6cd39e 100644 --- a/packages/block-library/src/post-title/block.json +++ b/packages/block-library/src/post-title/block.json @@ -80,8 +80,5 @@ } } }, - "style": "wp-block-post-title", - "selectors": { - "typography": ".wp-block-post-title, .wp-block-post-title > a" - } + "style": "wp-block-post-title" } diff --git a/packages/block-library/src/post-title/style.scss b/packages/block-library/src/post-title/style.scss index 5d0e3407105bd4..8dfd25b1a0786b 100644 --- a/packages/block-library/src/post-title/style.scss +++ b/packages/block-library/src/post-title/style.scss @@ -3,31 +3,14 @@ // This block has customizable padding, border-box makes that more predictable. box-sizing: border-box; - &[style*="font-weight"] :where(a) { - font-weight: inherit; - } - &[class*="-font-family"] :where(a), - &[style*="font-family"] :where(a) { + :where(a) { + display: inline-block; font-family: inherit; - } - &[class*="-font-size"] :where(a), - &[style*="font-size"] :where(a) { font-size: inherit; - } - &[style*="line-height"] :where(a) { - line-height: inherit; - } - &[style*="font-style"] :where(a) { font-style: inherit; - } - &[style*="letter-spacing"] :where(a) { + font-weight: inherit; letter-spacing: inherit; - } - &[style*="text-decoration"] :where(a) { + line-height: inherit; text-decoration: inherit; } - - a { - display: inline-block; - } } diff --git a/packages/block-library/src/site-title/block.json b/packages/block-library/src/site-title/block.json index dbb484c74a1e45..c75b1bc229beb9 100644 --- a/packages/block-library/src/site-title/block.json +++ b/packages/block-library/src/site-title/block.json @@ -75,8 +75,5 @@ } }, "editorStyle": "wp-block-site-title-editor", - "style": "wp-block-site-title", - "selectors": { - "typography": ".wp-block-site-title > span, .wp-block-site-title > a" - } + "style": "wp-block-site-title" } diff --git a/packages/block-library/src/site-title/style.scss b/packages/block-library/src/site-title/style.scss index 8647f3d9b2947c..3b332e35c65237 100644 --- a/packages/block-library/src/site-title/style.scss +++ b/packages/block-library/src/site-title/style.scss @@ -2,31 +2,14 @@ // This block has customizable padding, border-box makes that more predictable. box-sizing: border-box; - &[style*="font-weight"] :where(a) { - font-weight: inherit; - } - &[class*="-font-family"] :where(a), - &[style*="font-family"] :where(a) { + :where(a) { + color: inherit; font-family: inherit; - } - &[class*="-font-size"] :where(a), - &[style*="font-size"] :where(a) { font-size: inherit; - } - &[style*="line-height"] :where(a) { - line-height: inherit; - } - &[style*="font-style"] :where(a) { font-style: inherit; - } - &[style*="letter-spacing"] :where(a) { + font-weight: inherit; letter-spacing: inherit; - } - &[style*="text-decoration"] :where(a) { + line-height: inherit; text-decoration: inherit; } - - :where(a) { - color: inherit; - } } From 07c6a1faf3319d69f036c1161d6faad91a7fffe8 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Tue, 17 Sep 2024 21:27:24 -0700 Subject: [PATCH 0840/1908] Post Editor: Support keyboard resizing of meta boxes pane (#65325) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use a custom resize handle to support keyboard use Also computes maximum resize height taking into account notices * Avoid pane’s `width` becoming fixed * Fix aria-valuenow updates from `onResize` * Respect reduced motion preference * Correct typo * Revamp resize handle button hover/focus transition * Use border-radius/width instead of clip-path * Use variable based on grid unit for resize handle height * Remove unnecessary max-height rule Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../edit-post/src/components/layout/index.js | 150 ++++++++++++++++-- .../src/components/layout/style.scss | 49 +++--- 2 files changed, 162 insertions(+), 37 deletions(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 2cbf5c32e814b8..e6451c6a4a4082 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -26,9 +26,10 @@ import { PluginArea } from '@wordpress/plugins'; import { __, sprintf } from '@wordpress/i18n'; import { useCallback, - useLayoutEffect, useMemo, + useId, useRef, + useState, } from '@wordpress/element'; import { store as noticesStore } from '@wordpress/notices'; import { store as preferencesStore } from '@wordpress/preferences'; @@ -41,8 +42,17 @@ import { privateApis as blockLibraryPrivateApis } from '@wordpress/block-library import { addQueryArgs } from '@wordpress/url'; import { decodeEntities } from '@wordpress/html-entities'; import { store as coreStore } from '@wordpress/core-data'; -import { ResizableBox, SlotFillProvider } from '@wordpress/components'; -import { useMediaQuery, useViewportMatch } from '@wordpress/compose'; +import { + ResizableBox, + SlotFillProvider, + Tooltip, + VisuallyHidden, +} from '@wordpress/components'; +import { + useMediaQuery, + useRefEffect, + useViewportMatch, +} from '@wordpress/compose'; /** * Internal dependencies @@ -176,13 +186,41 @@ function MetaBoxesMain( { isLegacy } ) { const resizableBoxRef = useRef(); const isShort = useMediaQuery( '(max-height: 549px)' ); - const isAutoHeight = openHeight === undefined; - // In case a user size is set stops the default max-height from applying. - useLayoutEffect( () => { - if ( ! isLegacy && hasAnyVisible && ! isShort && ! isAutoHeight ) { - resizableBoxRef.current.resizable.classList.add( 'has-user-size' ); + const [ { min, max }, setHeightConstraints ] = useState( () => ( {} ) ); + // Keeps the resizable area’s size constraints updated taking into account + // editor notices. The constraints are also used to derive the value for the + // aria-valuenow attribute on the seperator. + const effectSizeConstraints = useRefEffect( ( node ) => { + const container = node.closest( + '.interface-interface-skeleton__content' + ); + const noticeLists = container.querySelectorAll( + ':scope > .components-notice-list' + ); + const resizeHandle = container.querySelector( + '.edit-post-meta-boxes-main__resize-handle' + ); + const actualize = () => { + const fullHeight = container.offsetHeight; + let nextMax = fullHeight; + for ( const element of noticeLists ) { + nextMax -= element.offsetHeight; + } + const nextMin = resizeHandle.offsetHeight; + setHeightConstraints( { min: nextMin, max: nextMax } ); + }; + const observer = new window.ResizeObserver( actualize ); + observer.observe( container ); + for ( const element of noticeLists ) { + observer.observe( element ); } - }, [ isAutoHeight, isShort, hasAnyVisible, isLegacy ] ); + return () => observer.disconnect(); + }, [] ); + + const separatorRef = useRef(); + const separatorHelpId = useId(); + + const [ isUntouched, setIsUntouched ] = useState( true ); if ( ! hasAnyVisible ) { return; @@ -206,6 +244,18 @@ function MetaBoxesMain( { isLegacy } ) { return contents; } + const isAutoHeight = openHeight === undefined; + let usedMax = '50%'; // Approximation before max has a value. + if ( max !== undefined ) { + // Halves the available max height until a user height is set. + usedMax = isAutoHeight && isUntouched ? max / 2 : max; + } + + const getAriaValueNow = ( height ) => + Math.round( ( ( height - min ) / ( max - min ) ) * 100 ); + const usedAriaValueNow = + max === undefined || isAutoHeight ? 50 : getAriaValueNow( openHeight ); + if ( isShort ) { return ( <details @@ -224,6 +274,35 @@ function MetaBoxesMain( { isLegacy } ) { </details> ); } + + // TODO: Support more/all keyboard interactions from the window splitter pattern: + // https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/ + const onSeparatorKeyDown = ( event ) => { + const delta = { ArrowUp: 20, ArrowDown: -20 }[ event.key ]; + if ( delta ) { + const { resizable } = resizableBoxRef.current; + const fromHeight = isAutoHeight + ? resizable.offsetHeight + : openHeight; + const nextHeight = Math.min( + max, + Math.max( min, delta + fromHeight ) + ); + resizableBoxRef.current.updateSize( { + height: nextHeight, + // Oddly, if left unspecified a subsequent drag gesture applies a fixed + // width and the pane fails to shrink/grow with parent width changes from + // sidebars opening/closing or window resizes. + width: 'auto', + } ); + setPreference( + 'core/edit-post', + 'metaBoxesMainOpenHeight', + nextHeight + ); + } + }; + return ( <ResizableBox className={ className } @@ -239,8 +318,8 @@ function MetaBoxesMain( { isLegacy } ) { bottomRight: false, bottomLeft: false, } } - // This is overriden by an !important rule that applies until user resizes. - maxHeight="100%" + minHeight={ min } + maxHeight={ usedMax } bounds="parent" boundsByDirection // Avoids hiccups while dragging over objects like iframes and ensures that @@ -250,19 +329,58 @@ function MetaBoxesMain( { isLegacy } ) { target.setPointerCapture( pointerId ); } } onResizeStart={ ( event, direction, elementRef ) => { - // Avoids height jumping in case it’s limited by max-height. - elementRef.style.height = `${ elementRef.offsetHeight }px`; - // Stops initial max-height from being applied. - elementRef.classList.add( 'has-user-size' ); + if ( isAutoHeight ) { + const heightNow = elementRef.offsetHeight; + // Sets the starting height to avoid visual jumps in height and + // aria-valuenow being `NaN` for the first (few) resize events. + resizableBoxRef.current.updateSize( { height: heightNow } ); + // Causes `maxHeight` to update to full `max` value instead of half. + setIsUntouched( false ); + } + } } + onResize={ () => { + const { height } = resizableBoxRef.current.state; + const separator = separatorRef.current; + separator.ariaValueNow = getAriaValueNow( height ); } } onResizeStop={ () => { + const nextHeight = resizableBoxRef.current.state.height; setPreference( 'core/edit-post', 'metaBoxesMainOpenHeight', - resizableBoxRef.current.state.height + nextHeight ); } } + handleClasses={ { + top: 'edit-post-meta-boxes-main__resize-handle', + } } + handleComponent={ { + top: ( + <> + <Tooltip text={ __( 'Drag to resize' ) }> + { /* Disable reason: aria-valuenow is supported by separator role. */ } + { /* eslint-disable-next-line jsx-a11y/role-supports-aria-props */ } + <button + ref={ separatorRef } + aria-label={ __( 'Drag to resize' ) } + aria-describedby={ separatorHelpId } + onKeyDown={ onSeparatorKeyDown } + // Disable reason: buttons are allowed to be separator role. + // eslint-disable-next-line jsx-a11y/no-interactive-element-to-noninteractive-role + role="separator" + aria-valuenow={ usedAriaValueNow } + /> + </Tooltip> + <VisuallyHidden id={ separatorHelpId }> + { __( + 'Use up and down arrow keys to resize the metabox panel.' + ) } + </VisuallyHidden> + </> + ), + } } > + <meta ref={ effectSizeConstraints } /> { contents } </ResizableBox> ); diff --git a/packages/edit-post/src/components/layout/style.scss b/packages/edit-post/src/components/layout/style.scss index 5392a7e9da4d95..5d0a9a29c329ca 100644 --- a/packages/edit-post/src/components/layout/style.scss +++ b/packages/edit-post/src/components/layout/style.scss @@ -1,15 +1,12 @@ +$resize-handle-height: $grid-unit-30; + .edit-post-meta-boxes-main { filter: drop-shadow(0 -1px rgba($color: #000, $alpha: 0.133)); // 0.133 = $gray-200 but with alpha. background-color: $white; clear: both; // This is seemingly only needed in case the canvas is not iframe’d. &:not(details) { - padding-top: 23px; - max-height: 100%; - - &:not(.has-user-size) { - max-height: 50% !important; - } + padding-top: $resize-handle-height; } // The component renders as a details element in short viewports. @@ -31,24 +28,34 @@ z-index: 1; } } +} - & .components-resizable-box__handle-top { - top: 0; - box-shadow: 0 $border-width $gray-300; - } - & .components-resizable-box__side-handle::before { - border-radius: 0; - top: 0; - height: $border-width; - } - & .components-resizable-box__handle::after { +.edit-post-meta-boxes-main__resize-handle { + display: flex; + // The position is absolute by default inline style of ResizableBox. + inset: 0 0 auto 0; + height: $resize-handle-height; + box-shadow: 0 $border-width $gray-300; + + & > button { + appearance: none; + cursor: inherit; + margin: auto; + padding: 0; + border: none; + outline: none; background-color: $gray-300; - box-shadow: none; - border-radius: 4px; + width: $grid-unit-80; height: $grid-unit-05; - top: calc(50% - #{$grid-unit-05} / 2); - width: 100px; - right: calc(50% - 50px); + border-radius: $radius-small; + transition: width 0.3s ease-out; + @include reduce-motion("transition"); + } + + &:hover > button, + > button:focus { + background-color: var(--wp-admin-theme-color); + width: $grid-unit-80 + $grid-unit-20; } } From 338940a77d5b9152f276e5ec31db01b4ba2d7332 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:23:46 +1000 Subject: [PATCH 0841/1908] DataViews Sidebar: Display item count on DataViews sidebar (#65223) This PR pulls across @Souptik2001's work from https://github.com/WordPress/gutenberg/pull/62028 and using useEntityRecords to get record counts. It also: - Adds a `navigationItemSuffix` prop to DataViewItem so that consumers can pass a suffix to the SidebarNavigationItem component. - Refactors custom count hook to include default dataviews that it doesn't affect other components Reduce RHS padding Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: Souptik2001 <souptik@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Unlinked contributors: finitelydope, jarekmorawski. --- .../sidebar-dataviews/dataview-item.js | 2 + .../sidebar-dataviews/default-views.js | 46 ++++++++++++++++++- .../src/components/sidebar-dataviews/index.js | 9 +++- .../components/sidebar-dataviews/style.scss | 4 ++ 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js b/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js index 1e12d6706d81b5..1a96fdc0591439 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js +++ b/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js @@ -27,6 +27,7 @@ export default function DataViewItem( { isActive, isCustom, suffix, + navigationItemSuffix, } ) { const { params: { postType }, @@ -55,6 +56,7 @@ export default function DataViewItem( { <SidebarNavigationItem icon={ iconToUse } { ...linkInfo } + suffix={ navigationItemSuffix } aria-current={ isActive ? 'true' : undefined } > { title } diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 658fa319e9c667..20f61e451b21fa 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -13,7 +13,7 @@ import { notAllowed, } from '@wordpress/icons'; import { useSelect } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; +import { store as coreStore, useEntityRecords } from '@wordpress/core-data'; import { useMemo } from '@wordpress/element'; /** @@ -68,6 +68,50 @@ const DEFAULT_POST_BASE = { layout: defaultLayouts[ LAYOUT_LIST ].layout, }; +export function useDefaultViewsWithItemCounts( { postType } ) { + const defaultViews = useDefaultViews( { postType } ); + const { records, totalItems } = useEntityRecords( 'postType', postType, { + per_page: -1, + status: [ 'any', 'trash' ], + } ); + + return useMemo( () => { + if ( ! defaultViews ) { + return []; + } + + // If there are no records, return the default views with no counts. + if ( ! records ) { + return defaultViews; + } + + const counts = { + drafts: records.filter( ( record ) => record.status === 'draft' ) + .length, + future: records.filter( ( record ) => record.status === 'future' ) + .length, + pending: records.filter( ( record ) => record.status === 'pending' ) + .length, + private: records.filter( ( record ) => record.status === 'private' ) + .length, + published: records.filter( + ( record ) => record.status === 'publish' + ).length, + trash: records.filter( ( record ) => record.status === 'trash' ) + .length, + }; + + // All items excluding trashed items as per the default "all" status query. + counts.all = totalItems ? totalItems - counts.trash : 0; + + // Filter out views with > 0 item counts. + return defaultViews.map( ( _view ) => { + _view.count = counts[ _view.slug ]; + return _view; + } ); + }, [ defaultViews, records, totalItems ] ); +} + export function useDefaultViews( { postType } ) { const labels = useSelect( ( select ) => { diff --git a/packages/edit-site/src/components/sidebar-dataviews/index.js b/packages/edit-site/src/components/sidebar-dataviews/index.js index 86420c4eec1d1f..3f7f5b965fce71 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/index.js +++ b/packages/edit-site/src/components/sidebar-dataviews/index.js @@ -7,7 +7,7 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies */ -import { useDefaultViews } from './default-views'; +import { useDefaultViewsWithItemCounts } from './default-views'; import { unlock } from '../../lock-unlock'; import DataViewItem from './dataview-item'; import CustomDataViewsList from './custom-dataviews-list'; @@ -18,7 +18,9 @@ export default function DataViewsSidebarContent() { const { params: { postType, activeView = 'all', isCustom = 'false' }, } = useLocation(); - const defaultViews = useDefaultViews( { postType } ); + + const defaultViews = useDefaultViewsWithItemCounts( { postType } ); + if ( ! postType ) { return null; } @@ -34,6 +36,9 @@ export default function DataViewsSidebarContent() { slug={ dataview.slug } title={ dataview.title } icon={ dataview.icon } + navigationItemSuffix={ + <span>{ dataview.count }</span> + } type={ dataview.view.type } isActive={ ! isCustomBoolean && diff --git a/packages/edit-site/src/components/sidebar-dataviews/style.scss b/packages/edit-site/src/components/sidebar-dataviews/style.scss index 14e6bf1d03fca8..3473c8e20e1a45 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/style.scss +++ b/packages/edit-site/src/components/sidebar-dataviews/style.scss @@ -15,6 +15,10 @@ min-width: initial; } + .edit-site-sidebar-navigation-item.with-suffix { + padding-right: $grid-unit-10; + } + &:hover, &:focus, &[aria-current] { From 5f77458225b0ce1d4e5fdb2b1113a374d8bed189 Mon Sep 17 00:00:00 2001 From: Madhu Dollu <madhusudhan.dollu@gmail.com> Date: Wed, 18 Sep 2024 13:09:52 +0530 Subject: [PATCH 0842/1908] fix the issue where block spacing control not shown when only one side is set (#65371) --- .../spacing-sizes-control/test/utils.js | 43 ++++++++----------- .../components/spacing-sizes-control/utils.js | 27 +++++++++--- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/packages/block-editor/src/components/spacing-sizes-control/test/utils.js b/packages/block-editor/src/components/spacing-sizes-control/test/utils.js index 22191b4e1a8de9..a8440bb5be8caf 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/test/utils.js +++ b/packages/block-editor/src/components/spacing-sizes-control/test/utils.js @@ -378,41 +378,34 @@ describe( 'getInitialView', () => { VIEWS.custom ); } ); - } ); - - describe( 'Single side view', () => { - it( 'should return single side when only single side supported', () => { + it( 'should return custom view even if only single side supported', () => { expect( getInitialView( { top: '1em' }, [ 'top' ] ) ).toBe( - VIEWS.top + VIEWS.custom + ); + expect( getInitialView( { right: '1em' }, [ 'right' ] ) ).toBe( + VIEWS.custom + ); + expect( getInitialView( { bottom: '1em' }, [ 'bottom' ] ) ).toBe( + VIEWS.custom + ); + expect( getInitialView( { left: '1em' }, [ 'left' ] ) ).toBe( + VIEWS.custom ); } ); + } ); + describe( 'Single side view', () => { it( 'should return single side when only single side supported and no value defined', () => { expect( getInitialView( {}, [ 'top' ] ) ).toBe( VIEWS.top ); } ); - it( 'should return single side when only single side supported and all values defined', () => { + it( 'should return single side when only single side supported and has only axial sides', () => { expect( - getInitialView( - { top: '1em', right: '2em', bottom: '1em', left: '2em' }, - [ 'top' ] - ) + getInitialView( { top: '1em' }, [ 'horizontal', 'vertical' ] ) ).toBe( VIEWS.top ); - } ); - - it( 'should return single side view when only one side is supported', () => { - expect( getInitialView( { top: '1em' }, [ 'top' ] ) ).toBe( - VIEWS.top - ); - expect( getInitialView( { right: '1em' }, [ 'right' ] ) ).toBe( - VIEWS.right - ); - expect( getInitialView( { bottom: '1em' }, [ 'bottom' ] ) ).toBe( - VIEWS.bottom - ); - expect( getInitialView( { left: '1em' }, [ 'left' ] ) ).toBe( - VIEWS.left - ); + expect( + getInitialView( { left: '4em' }, [ 'horizontal', 'vertical' ] ) + ).toBe( VIEWS.left ); } ); } ); } ); diff --git a/packages/block-editor/src/components/spacing-sizes-control/utils.js b/packages/block-editor/src/components/spacing-sizes-control/utils.js index df2da0d93d0609..046bee98761bf2 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/utils.js +++ b/packages/block-editor/src/components/spacing-sizes-control/utils.js @@ -363,11 +363,10 @@ export function getInitialView( values = {}, sides ) { top === bottom && left === right && ( !! top || !! left ); const hasNoValuesAndBalancedSides = ! sideValues.length && hasBalancedSidesSupport( sides ); - - // Only single side supported and no value defined. - if ( sides?.length === 1 ) { - return sides[ 0 ]; - } + const hasOnlyAxialSides = + sides?.includes( 'horizontal' ) && + sides?.includes( 'vertical' ) && + sides?.length === 2; if ( hasAxisSupport( sides ) && @@ -376,6 +375,24 @@ export function getInitialView( values = {}, sides ) { return VIEWS.axial; } + // Only axial sides are supported and single value defined. + // - Ensure the side returned is the first side that has a value. + if ( hasOnlyAxialSides && sideValues.length === 1 ) { + let side; + + Object.entries( values ).some( ( [ key, value ] ) => { + side = key; + return value !== undefined; + } ); + + return side; + } + + // Only single side supported and no value defined. + if ( sides?.length === 1 && ! sideValues.length ) { + return sides[ 0 ]; + } + // Default to the Custom (separated sides) view. return VIEWS.custom; } From b818be2eb208072b6b0a2d0fe63e9c7cef5c3cb5 Mon Sep 17 00:00:00 2001 From: Maggie <maggie.cabrera@automattic.com> Date: Wed, 18 Sep 2024 09:59:27 +0100 Subject: [PATCH 0843/1908] remove zoom out experiment (#65404) --- lib/experimental/editor-settings.php | 3 --- lib/experiments-page.php | 11 ----------- packages/editor/src/components/header/index.js | 5 +---- 3 files changed, 1 insertion(+), 18 deletions(-) diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index 919be2e6e34a45..126382f85a513e 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -34,9 +34,6 @@ function gutenberg_enable_experiments() { if ( $gutenberg_experiments && array_key_exists( 'gutenberg-media-processing', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalMediaProcessing = true', 'before' ); } - if ( $gutenberg_experiments && array_key_exists( 'gutenberg-zoom-out-experiment', $gutenberg_experiments ) ) { - wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableZoomOutExperiment = true', 'before' ); - } } add_action( 'admin_init', 'gutenberg_enable_experiments' ); diff --git a/lib/experiments-page.php b/lib/experiments-page.php index 5acd5f0f192364..27a54b920f4d52 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -175,17 +175,6 @@ function gutenberg_initialize_experiments_settings() { ) ); - add_settings_field( - 'gutenberg-zoom-out-experiment', - __( 'Zoom out experiments', 'gutenberg' ), - 'gutenberg_display_experiment_field', - 'gutenberg-experiments', - 'gutenberg_experiments_section', - array( - 'label' => __( 'Enable zoom out experiments; shows zoom out in the device preview and other zoom out experiments.', 'gutenberg' ), - 'id' => 'gutenberg-zoom-out-experiment', - ) - ); register_setting( 'gutenberg-experiments', 'gutenberg-experiments' diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index b1b8f2fc1ee32b..8f9d130c8b7173 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -48,9 +48,6 @@ function Header( { setEntitiesSavedStatesCallback, title, } ) { - const zoomOutExperimentEnabled = - window.__experimentalEnableZoomOutExperiment; - const isWideViewport = useViewportMatch( 'large' ); const isLargeViewport = useViewportMatch( 'medium' ); const isTooNarrowForDocumentBar = useMediaQuery( '(max-width: 403px)' ); @@ -146,7 +143,7 @@ function Header( { /> <PostViewLink /> - { zoomOutExperimentEnabled && <ZoomOutToggle /> } + <ZoomOutToggle /> { ( isWideViewport || ! showIconLabels ) && ( <PinnedItems.Slot scope="core" /> From 98b8d415830fa9ebf7b4b0a2b95d65b9fd1e813a Mon Sep 17 00:00:00 2001 From: Vipul Gupta <55375170+vipul0425@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:39:59 +0530 Subject: [PATCH 0844/1908] Fix: Button Replace remaining 40px default size violations [Block Editor 4] (#65257) * fix: Inserter lightbox's button to use 40px default size. * fix: Pattern Explorer Sidebar's button to use 40px default size. * fix: Block Pattern's button to use 40px default size. * fix: Media Preview's button to use 40px default size. * fix: Media Tab's button to use 40px default size. * fix: Quick Inserter's button to use 40px default size. Co-authored-by: vipul0425 <vipulgupta003@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../block-editor/src/components/inserter-listbox/item.js | 6 +----- .../block-patterns-explorer/pattern-explorer-sidebar.js | 3 +-- .../src/components/inserter/block-patterns-tab/index.js | 3 +-- .../src/components/inserter/media-tab/media-preview.js | 6 ++---- .../src/components/inserter/media-tab/media-tab.js | 3 +-- .../block-editor/src/components/inserter/quick-inserter.js | 3 +-- packages/block-editor/src/components/inserter/style.scss | 1 - 7 files changed, 7 insertions(+), 18 deletions(-) diff --git a/packages/block-editor/src/components/inserter-listbox/item.js b/packages/block-editor/src/components/inserter-listbox/item.js index 69c316bdbbccef..06c266d793d2ff 100644 --- a/packages/block-editor/src/components/inserter-listbox/item.js +++ b/packages/block-editor/src/components/inserter-listbox/item.js @@ -33,11 +33,7 @@ function InserterListboxItem( return children( propsWithTabIndex ); } return ( - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - { ...propsWithTabIndex } - > + <Button __next40pxDefaultSize { ...propsWithTabIndex }> { children } </Button> ); diff --git a/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js b/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js index 95de775e48eef8..d258c24da10cfb 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js +++ b/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js @@ -15,8 +15,7 @@ function PatternCategoriesList( { { patternCategories.map( ( { name, label } ) => { return ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize key={ name } label={ label } className={ `${ baseClassName }__categories-list__item` } diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/index.js b/packages/block-editor/src/components/inserter/block-patterns-tab/index.js index 0db78cec24dcb2..141ebf8cc84016 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/index.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/index.js @@ -61,8 +61,7 @@ function BlockPatternsTab( { { children } </CategoryTabs> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="block-editor-inserter__patterns-explore-button" onClick={ () => setShowPatternsExplorer( true ) } variant="secondary" diff --git a/packages/block-editor/src/components/inserter/media-tab/media-preview.js b/packages/block-editor/src/components/inserter/media-tab/media-preview.js index 4416b710302cef..64088f45fa1c39 100644 --- a/packages/block-editor/src/components/inserter/media-tab/media-preview.js +++ b/packages/block-editor/src/components/inserter/media-tab/media-preview.js @@ -100,8 +100,7 @@ function InsertExternalImageModal( { onClose, onSubmit } ) { > <FlexItem> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" onClick={ onClose } > @@ -110,8 +109,7 @@ function InsertExternalImageModal( { onClose, onSubmit } ) { </FlexItem> <FlexItem> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" onClick={ onSubmit } > diff --git a/packages/block-editor/src/components/inserter/media-tab/media-tab.js b/packages/block-editor/src/components/inserter/media-tab/media-tab.js index 07fce9ee6d80b0..ca901a127e5b42 100644 --- a/packages/block-editor/src/components/inserter/media-tab/media-tab.js +++ b/packages/block-editor/src/components/inserter/media-tab/media-tab.js @@ -71,8 +71,7 @@ function MediaTab( { allowedTypes={ ALLOWED_MEDIA_TYPES } render={ ( { open } ) => ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize onClick={ ( event ) => { // Safari doesn't emit a focus event on button elements when // clicked and we need to manually focus the button here. diff --git a/packages/block-editor/src/components/inserter/quick-inserter.js b/packages/block-editor/src/components/inserter/quick-inserter.js index e28ae1f3896c45..4a79ad6b1f083c 100644 --- a/packages/block-editor/src/components/inserter/quick-inserter.js +++ b/packages/block-editor/src/components/inserter/quick-inserter.js @@ -138,8 +138,7 @@ export default function QuickInserter( { { setInserterIsOpened && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="block-editor-inserter__quick-inserter-expand" onClick={ onBrowseAll } aria-label={ __( diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index e772a67a131388..3ce088901bce57 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -410,7 +410,6 @@ $block-inserter-tabs-height: 44px; background: $gray-900; color: $white; width: 100%; - height: ($button-size + $grid-unit-10); border-radius: 0; &:hover { From be80309da1ed651a1f09c8fb5f6cb969c446ff68 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 18 Sep 2024 11:58:06 +0200 Subject: [PATCH 0845/1908] Add safety check for `$comment_vars['paged']` (#65435) Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: michalczaplinski <czapla@git.wordpress.org> --- packages/block-library/src/comments-pagination-next/index.php | 2 +- .../block-library/src/comments-pagination-previous/index.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/comments-pagination-next/index.php b/packages/block-library/src/comments-pagination-next/index.php index 14a323df3a13ae..0fd9519a56d304 100644 --- a/packages/block-library/src/comments-pagination-next/index.php +++ b/packages/block-library/src/comments-pagination-next/index.php @@ -37,7 +37,7 @@ function render_block_core_comments_pagination_next( $attributes, $content, $blo $label .= $pagination_arrow; } - $next_comments_link = get_next_comments_link( $label, $max_page, $comment_vars['paged'] ); + $next_comments_link = get_next_comments_link( $label, $max_page, $comment_vars['paged'] ?? null ); remove_filter( 'next_posts_link_attributes', $filter_link_attributes ); diff --git a/packages/block-library/src/comments-pagination-previous/index.php b/packages/block-library/src/comments-pagination-previous/index.php index b70a9f609da9f0..ba9bef97ad34d9 100644 --- a/packages/block-library/src/comments-pagination-previous/index.php +++ b/packages/block-library/src/comments-pagination-previous/index.php @@ -30,7 +30,7 @@ function render_block_core_comments_pagination_previous( $attributes, $content, add_filter( 'previous_comments_link_attributes', $filter_link_attributes ); $comment_vars = build_comment_query_vars_from_block( $block ); - $previous_comments_link = get_previous_comments_link( $label, $comment_vars['paged'] ); + $previous_comments_link = get_previous_comments_link( $label, $comment_vars['paged'] ?? null ); remove_filter( 'previous_comments_link_attributes', $filter_link_attributes ); From f67e39b0e9add93b8504dbce245b04c3871307a0 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 18 Sep 2024 12:38:38 +0200 Subject: [PATCH 0846/1908] Unit tests: mock matchMedia to enforce prefers-reduce-motion (#65438) * Add global matchMedia mock for prefers-reduced-motion * Update DotTip snapshots --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../dot-tip/test/__snapshots__/index.js.snap | 2 +- test/unit/jest.config.js | 5 ++++- test/unit/mocks/match-media.js | 22 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 test/unit/mocks/match-media.js diff --git a/packages/nux/src/components/dot-tip/test/__snapshots__/index.js.snap b/packages/nux/src/components/dot-tip/test/__snapshots__/index.js.snap index dbea46e35fb091..90edc7a19990a0 100644 --- a/packages/nux/src/components/dot-tip/test/__snapshots__/index.js.snap +++ b/packages/nux/src/components/dot-tip/test/__snapshots__/index.js.snap @@ -7,7 +7,7 @@ exports[`DotTip should render correctly 1`] = ` data-wp-c16t="true" data-wp-component="Popover" role="dialog" - style="position: absolute; top: 0px; left: 0px; opacity: 1; transform: translateX(0px) translateY(0px) translateX(0em) scale(1) translateZ(0); transform-origin: 0% 50% 0;" + style="position: absolute; top: 0px; left: 0px; transform: none;" tabindex="-1" > <div diff --git a/test/unit/jest.config.js b/test/unit/jest.config.js index 30f94485396432..8564d4116691fd 100644 --- a/test/unit/jest.config.js +++ b/test/unit/jest.config.js @@ -19,7 +19,10 @@ module.exports = { '<rootDir>/test/unit/config/global-mocks.js', '<rootDir>/test/unit/config/gutenberg-env.js', ], - setupFilesAfterEnv: [ '<rootDir>/test/unit/config/testing-library.js' ], + setupFilesAfterEnv: [ + '<rootDir>/test/unit/config/testing-library.js', + '<rootDir>/test/unit/mocks/match-media.js', + ], testEnvironmentOptions: { url: 'http://localhost/', }, diff --git a/test/unit/mocks/match-media.js b/test/unit/mocks/match-media.js new file mode 100644 index 00000000000000..3a9ff7b901ff15 --- /dev/null +++ b/test/unit/mocks/match-media.js @@ -0,0 +1,22 @@ +// Mock `matchMedia` so that all animations are skipped, +// since js-dom does not fully support CSS animations. +// Example: https://github.com/jsdom/jsdom/issues/3239 +const originalMatchMedia = window.matchMedia; +const mockedMatchMedia = jest.fn( ( query ) => { + if ( /prefers-reduced-motion/.test( query ) ) { + return { + ...originalMatchMedia( query ), + matches: true, + }; + } + + return originalMatchMedia( query ); +} ); + +beforeAll( () => { + window.matchMedia = jest.fn( mockedMatchMedia ); +} ); + +afterAll( () => { + window.matchMedia = originalMatchMedia; +} ); From 2607bd3948cc99fa8c8e1f0688f9d592a6deb6d6 Mon Sep 17 00:00:00 2001 From: Maggie <maggie.cabrera@automattic.com> Date: Wed, 18 Sep 2024 11:39:00 +0100 Subject: [PATCH 0847/1908] hide zoom out on smaller viewports (#65437) --- packages/editor/src/components/header/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index 8f9d130c8b7173..cd8e5336b0ba07 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -143,7 +143,7 @@ function Header( { /> <PostViewLink /> - <ZoomOutToggle /> + { isWideViewport && <ZoomOutToggle /> } { ( isWideViewport || ! showIconLabels ) && ( <PinnedItems.Slot scope="core" /> From c754c783a9004db678fcfebd9a21a22820f2115c Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 18 Sep 2024 13:24:41 +0200 Subject: [PATCH 0848/1908] Block Bindings: Use post meta label from `register_meta` in block bindings workflows (#65099) * Initial commit. Add meta field to post types. * Add post meta * Add todos * Add fields in all postType * WIP: Add first version to link templates and entities * Revert "WIP: Add first version to link templates and entities" This reverts commit a43e39194f25d39e69426b15a2b9036022f301d3. * Only expose public fields * Add subtype to meta properties * Render the appropriate fields depending on the postType in templates * Use context postType when available * Fetch the data on render, preventing one click needed * Yoda conditions.. * Try: Expose registered meta fields in schema * Try: Create a resolver to get registered post meta * Use rest namespace * Move actions and selectors to private. * Merge useSelect * Fix duplicated * Add object_subtype to schema * Update docs to object_subtype * Add explanatory comment * Block Bindings: Use default values in connected custom fields in templates (#65128) * Abstract `getMetadata` and use it in `getValues` * Adapt e2e tests * Update e2e --------- Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> * Try removing all object subtype * Fix e2e * Update code * Fix `useSelect` warning * Remove old comment * Remove support for generic templates * Revert changes to e2e tests * Change the value returned by `getFieldsList` to include label * Use label in bindings panel * Use label in rich text placeholders * Add filter to include `label` * Use title instead of label in schema * Add safety check * Adapt branch after rebase * Remove extra spaces * Don't rely on key outside of post meta * Remove key from bindings component * Read title instead of label * Add backport to changelog * Update translator comment --------- Unlinked contributors: dannyreaktiv. Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> --- backport-changelog/6.7/7298.md | 3 ++ lib/compat/wordpress-6.7/block-bindings.php | 32 +++++++++++ .../src/components/rich-text/index.js | 25 +++++++-- .../block-editor/src/hooks/block-bindings.js | 17 +++--- packages/editor/src/bindings/post-meta.js | 54 +++++++++++++------ 5 files changed, 103 insertions(+), 28 deletions(-) create mode 100644 backport-changelog/6.7/7298.md diff --git a/backport-changelog/6.7/7298.md b/backport-changelog/6.7/7298.md new file mode 100644 index 00000000000000..4c01ef5d4f46e6 --- /dev/null +++ b/backport-changelog/6.7/7298.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7298 + +* https://github.com/WordPress/gutenberg/pull/65099 \ No newline at end of file diff --git a/lib/compat/wordpress-6.7/block-bindings.php b/lib/compat/wordpress-6.7/block-bindings.php index 9e82c1843f35a0..a8f68c0f0f04ea 100644 --- a/lib/compat/wordpress-6.7/block-bindings.php +++ b/lib/compat/wordpress-6.7/block-bindings.php @@ -53,3 +53,35 @@ function gutenberg_add_can_update_block_bindings_editor_setting( $editor_setting } add_filter( 'block_editor_settings_all', 'gutenberg_add_can_update_block_bindings_editor_setting', 10 ); + +/** + * Add `label` to `register_meta`. + * + * @param array $args Array of arguments for registering meta. + * @return array Modified arguments array including `label`. + */ +function gutenberg_update_meta_args_with_label( $args ) { + // Don't update schema when label isn't provided. + if ( ! isset( $args['label'] ) ) { + return $args; + } + + $schema = array( 'title' => $args['label'] ); + if ( ! is_array( $args['show_in_rest'] ) ) { + $args['show_in_rest'] = array( + 'schema' => $schema, + ); + return $args; + } + + if ( ! empty( $args['show_in_rest']['schema'] ) ) { + $args['show_in_rest']['schema'] = array_merge( $args['show_in_rest']['schema'], $schema ); + } else { + $args['show_in_rest']['schema'] = $schema; + } + + return $args; +} + +// Priority must be lower than 10 to ensure the label is not removed. +add_filter( 'register_meta_args', 'gutenberg_update_meta_args_with_label', 5, 1 ); diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 732b8dbf2c089c..387f388b8fdad6 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -125,6 +125,7 @@ export function RichTextWrapper( const { clientId, isSelected: isBlockSelected, name: blockName } = context; const blockBindings = context[ blockBindingsKey ]; const blockContext = useContext( BlockContext ); + const registry = useRegistry(); const selector = ( select ) => { // Avoid subscribing to the block editor store if the block is not // selected. @@ -178,6 +179,10 @@ export function RichTextWrapper( const blockBindingsSource = getBlockBindingsSource( relatedBinding.source ); + const fieldsList = blockBindingsSource?.getFieldsList?.( { + registry, + context: blockContext, + } ); const _disableBoundBlock = ! blockBindingsSource?.canUserEditValue?.( { @@ -186,12 +191,16 @@ export function RichTextWrapper( args: relatedBinding.args, } ); + const bindingKey = + fieldsList?.[ relatedBinding?.args?.key ]?.label ?? + blockBindingsSource?.label; + const _bindingsPlaceholder = _disableBoundBlock - ? relatedBinding?.args?.key || blockBindingsSource?.label + ? bindingKey : sprintf( - /* translators: %s: source label or key */ + /* translators: %s: connected field label or source label */ __( 'Add %s' ), - relatedBinding?.args?.key || blockBindingsSource?.label + bindingKey ); return { @@ -201,7 +210,14 @@ export function RichTextWrapper( _bindingsPlaceholder, }; }, - [ blockBindings, identifier, blockName, blockContext, adjustedValue ] + [ + blockBindings, + identifier, + blockName, + blockContext, + registry, + adjustedValue, + ] ); const shouldDisableEditing = readOnly || disableBoundBlock; @@ -371,7 +387,6 @@ export function RichTextWrapper( element.focus(); } - const registry = useRegistry(); const TagName = tagName; return ( <> diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index a0bd8820d36c5d..33284b4cd27fd5 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -61,7 +61,7 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) { { registeredSources[ name ].label } </DropdownMenuV2.GroupLabel> ) } - { Object.entries( fields ).map( ( [ key, value ] ) => ( + { Object.entries( fields ).map( ( [ key, args ] ) => ( <DropdownMenuV2.RadioItem key={ key } onChange={ () => @@ -77,10 +77,10 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) { checked={ key === currentKey } > <DropdownMenuV2.ItemLabel> - { key } + { args?.label } </DropdownMenuV2.ItemLabel> <DropdownMenuV2.ItemHelpText> - { value } + { args?.value } </DropdownMenuV2.ItemHelpText> </DropdownMenuV2.RadioItem> ) ) } @@ -94,7 +94,7 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) { ); } -function BlockBindingsAttribute( { attribute, binding } ) { +function BlockBindingsAttribute( { attribute, binding, fieldsList } ) { const { source: sourceName, args } = binding || {}; const sourceProps = unlock( blocksPrivateApis ).getBlockBindingsSource( sourceName ); @@ -110,14 +110,16 @@ function BlockBindingsAttribute( { attribute, binding } ) { > { isSourceInvalid ? __( 'Invalid source' ) - : args?.key || sourceProps?.label || sourceName } + : fieldsList?.[ sourceName ]?.[ args?.key ]?.label || + sourceProps?.label || + sourceName } </Text> ) } </VStack> ); } -function ReadOnlyBlockBindingsPanelItems( { bindings } ) { +function ReadOnlyBlockBindingsPanelItems( { bindings, fieldsList } ) { return ( <> { Object.entries( bindings ).map( ( [ attribute, binding ] ) => ( @@ -125,6 +127,7 @@ function ReadOnlyBlockBindingsPanelItems( { bindings } ) { <BlockBindingsAttribute attribute={ attribute } binding={ binding } + fieldsList={ fieldsList } /> </Item> ) ) } @@ -164,6 +167,7 @@ function EditableBlockBindingsPanelItems( { <BlockBindingsAttribute attribute={ attribute } binding={ binding } + fieldsList={ fieldsList } /> </Item> } @@ -276,6 +280,7 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { { readOnly ? ( <ReadOnlyBlockBindingsPanelItems bindings={ filteredBindings } + fieldsList={ fieldsList } /> ) : ( <EditableBlockBindingsPanelItems diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index 0562c1f7adf07d..20013bd8f246bb 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -9,20 +9,20 @@ import { store as coreDataStore } from '@wordpress/core-data'; import { store as editorStore } from '../store'; import { unlock } from '../lock-unlock'; -function getMetadata( registry, context ) { +function getMetadata( registry, context, registeredFields ) { let metaFields = {}; const { type } = registry.select( editorStore ).getCurrentPost(); const { getEditedEntityRecord } = registry.select( coreDataStore ); - const { getRegisteredPostMeta } = unlock( - registry.select( coreDataStore ) - ); if ( type === 'wp_template' ) { - const fields = getRegisteredPostMeta( context?.postType ); // Populate the `metaFields` object with the default values. - Object.entries( fields || {} ).forEach( ( [ key, props ] ) => { - metaFields[ key ] = props.default; - } ); + Object.entries( registeredFields || {} ).forEach( + ( [ key, props ] ) => { + if ( props.default ) { + metaFields[ key ] = props.default; + } + } + ); } else { metaFields = getEditedEntityRecord( 'postType', @@ -37,13 +37,20 @@ function getMetadata( registry, context ) { export default { name: 'core/post-meta', getValues( { registry, context, bindings } ) { - const metaFields = getMetadata( registry, context ); + const { getRegisteredPostMeta } = unlock( + registry.select( coreDataStore ) + ); + const registeredFields = getRegisteredPostMeta( context?.postType ); + const metaFields = getMetadata( registry, context, registeredFields ); const newValues = {}; for ( const [ attributeName, source ] of Object.entries( bindings ) ) { - // Use the key if the value is not set. + // Use the value, the field label, or the field key. + const metaKey = source.args.key; newValues[ attributeName ] = - metaFields?.[ source.args.key ] ?? source.args.key; + metaFields?.[ metaKey ] ?? + registeredFields?.[ metaKey ]?.title ?? + metaKey; } return newValues; }, @@ -103,18 +110,31 @@ export default { return true; }, getFieldsList( { registry, context } ) { - const metaFields = getMetadata( registry, context ); + const { getRegisteredPostMeta } = unlock( + registry.select( coreDataStore ) + ); + const registeredFields = getRegisteredPostMeta( context?.postType ); + const metaFields = getMetadata( registry, context, registeredFields ); if ( ! metaFields || ! Object.keys( metaFields ).length ) { return null; } - // Remove footnotes or private keys from the list of fields. - // TODO: Remove this once we retrieve the fields from 'types' endpoint in post or page editor. return Object.fromEntries( - Object.entries( metaFields ).filter( - ( [ key ] ) => key !== 'footnotes' && key.charAt( 0 ) !== '_' - ) + Object.entries( metaFields ) + // Remove footnotes or private keys from the list of fields. + .filter( + ( [ key ] ) => + key !== 'footnotes' && key.charAt( 0 ) !== '_' + ) + // Return object with label and value. + .map( ( [ key, value ] ) => [ + key, + { + label: registeredFields?.[ key ]?.title || key, + value, + }, + ] ) ); }, }; From 5aafffcb17ada0a1262d6ef6fcd6bc5eac41eb74 Mon Sep 17 00:00:00 2001 From: Bernie Reiter <96308+ockham@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:08:08 +0200 Subject: [PATCH 0849/1908] Terms List block: Add Categories-specific variation (#65434) Add two variations to the Terms List block (i.e. `core/categories` -- previously named "Categories List"): One for Categories, and another one for all other taxonomies. This is mostly for better discoverability of what used to be the Categories List block under its new name. Co-authored-by: ockham <bernhard-reiter@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> --- packages/block-library/src/categories/edit.js | 4 +- .../block-library/src/categories/index.js | 2 + .../src/categories/variations.js | 40 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 packages/block-library/src/categories/variations.js diff --git a/packages/block-library/src/categories/edit.js b/packages/block-library/src/categories/edit.js index ccbf9194339408..8bd2769b0ec711 100644 --- a/packages/block-library/src/categories/edit.js +++ b/packages/block-library/src/categories/edit.js @@ -196,7 +196,9 @@ export default function CategoriesEdit( { } ) ) } value={ taxonomySlug } onChange={ ( selectedTaxonomy ) => - setAttributes( { taxonomy: selectedTaxonomy } ) + setAttributes( { + taxonomy: selectedTaxonomy, + } ) } /> ) } diff --git a/packages/block-library/src/categories/index.js b/packages/block-library/src/categories/index.js index 8cdcad450862a2..d30c55667d106e 100644 --- a/packages/block-library/src/categories/index.js +++ b/packages/block-library/src/categories/index.js @@ -9,6 +9,7 @@ import { category as icon } from '@wordpress/icons'; import initBlock from '../utils/init-block'; import metadata from './block.json'; import edit from './edit'; +import variations from './variations'; const { name } = metadata; @@ -18,6 +19,7 @@ export const settings = { icon, example: {}, edit, + variations, }; export const init = () => initBlock( { name, metadata, settings } ); diff --git a/packages/block-library/src/categories/variations.js b/packages/block-library/src/categories/variations.js new file mode 100644 index 00000000000000..94f3fb8efa6b9a --- /dev/null +++ b/packages/block-library/src/categories/variations.js @@ -0,0 +1,40 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { category as icon } from '@wordpress/icons'; + +const variations = [ + { + name: 'terms', + title: __( 'Terms List' ), + icon, + attributes: { + // We need to set an attribute here that will be set when inserting the block. + // We cannot leave this empty, as that would be interpreted as the default value, + // which is `category` -- for which we're defining a distinct variation below, + // for backwards compatibility reasons. + // The logical fallback is thus the only other built-in and public taxonomy: Tags. + taxonomy: 'post_tag', + }, + isActive: ( blockAttributes ) => + // This variation is used for any taxonomy other than `category`. + blockAttributes.taxonomy !== 'category', + }, + { + name: 'categories', + title: __( 'Categories List' ), + description: __( 'Display a list of all categories.' ), + icon, + attributes: { + taxonomy: 'category', + }, + isActive: [ 'taxonomy' ], + // The following is needed to prevent "Terms List" from showing up twice in the inserter + // (once for the block, once for the variation). Fortunately, it does not collide with + // `categories` being the default value of the `taxonomy` attribute. + isDefault: true, + }, +]; + +export default variations; From 4b2672081cb80694675b8663f279c3d11d989e47 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Wed, 18 Sep 2024 13:39:08 +0100 Subject: [PATCH 0850/1908] Use custom block name in inspector controls when available (#65398) * Output name when available * i18n improvement --- .../src/components/block-card/index.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/block-card/index.js b/packages/block-editor/src/components/block-card/index.js index 8196f7688d4b50..4d40fe07d55471 100644 --- a/packages/block-editor/src/components/block-card/index.js +++ b/packages/block-editor/src/components/block-card/index.js @@ -13,7 +13,7 @@ import { __experimentalVStack as VStack, } from '@wordpress/components'; import { chevronLeft, chevronRight } from '@wordpress/icons'; -import { __, isRTL } from '@wordpress/i18n'; +import { __, isRTL, sprintf } from '@wordpress/i18n'; import { useSelect, useDispatch } from '@wordpress/data'; /** @@ -22,7 +22,7 @@ import { useSelect, useDispatch } from '@wordpress/data'; import BlockIcon from '../block-icon'; import { store as blockEditorStore } from '../../store'; -function BlockCard( { title, icon, description, blockType, className } ) { +function BlockCard( { title, icon, description, blockType, className, name } ) { if ( blockType ) { deprecated( '`blockType` property in `BlockCard component`', { since: '5.7', @@ -65,7 +65,16 @@ function BlockCard( { title, icon, description, blockType, className } ) { ) } <BlockIcon icon={ icon } showColors /> <VStack spacing={ 1 }> - <h2 className="block-editor-block-card__title">{ title }</h2> + <h2 className="block-editor-block-card__title"> + { name?.length + ? sprintf( + // translators: %1$s: Custom block name. %2$s: Block title. + __( '%1$s (%2$s)' ), + name, + title + ) + : title } + </h2> { description && ( <Text className="block-editor-block-card__description"> { description } From a8b606b9303ac2c8f03ca911b893621b0eecf6ca Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 18 Sep 2024 22:22:12 +0900 Subject: [PATCH 0851/1908] BoxControl: Unify input filed width whether linked or not (#65348) * BoxControl: Unify input filed width whether linked or not * Update changelog Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/box-control/all-input-control.tsx | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index c705257a827c5e..0a1f5f1866bc05 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -7,6 +7,7 @@ - `Tabs`: restore vertical indicator ([#65385](https://github.com/WordPress/gutenberg/pull/65385)). - `Tabs`: indicator positioning under RTL direction ([#64926](https://github.com/WordPress/gutenberg/pull/64926)). - `Popover`: Update `toolbar` variant radius to match block toolbar ([#65263](https://github.com/WordPress/gutenberg/pull/65263)). +- `BoxControl`: Unify input filed width whether linked or not ([#65348](https://github.com/WordPress/gutenberg/pull/65348)). ### Deprecations diff --git a/packages/components/src/box-control/all-input-control.tsx b/packages/components/src/box-control/all-input-control.tsx index fb65014dfaf0f5..e9166ff7f692e8 100644 --- a/packages/components/src/box-control/all-input-control.tsx +++ b/packages/components/src/box-control/all-input-control.tsx @@ -10,7 +10,6 @@ import { FlexedRangeControl, StyledUnitControl, } from './styles/box-control-styles'; -import { HStack } from '../h-stack'; import type { BoxControlInputControlProps } from './types'; import { parseQuantityAndUnitFromRawValue } from '../unit-control'; import { @@ -72,7 +71,7 @@ export default function AllInputControl( { }; return ( - <HStack> + <> <StyledUnitControl { ...props } __next40pxDefaultSize={ __next40pxDefaultSize } @@ -104,6 +103,6 @@ export default function AllInputControl( { value={ parsedQuantity ?? 0 } withInputField={ false } /> - </HStack> + </> ); } From 4e7e9f7e5f608737ea134a3cafb8d5e52fdb3faa Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 18 Sep 2024 15:24:12 +0200 Subject: [PATCH 0852/1908] Modal: add exit animation (#65203) * Add modal out animation * Add backup timeout * Update animation specs * Add easing argument to animation utils * Use shared config value for animation duration * Update comment * Move exit animation logic to separate hook * Use global React namespace to distinguish between react and native events * Remove extra ms * CHANGELOG * Use promises instead of callback arguments * Resolve instead of rejecting when no frame element is defined * Add 20% margin to the animation timeout * Add warning if frame ref is missing --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/base-styles/_animations.scss | 8 +- packages/components/CHANGELOG.md | 1 + packages/components/src/modal/index.tsx | 40 +++++--- packages/components/src/modal/style.scss | 29 +++++- packages/components/src/modal/types.ts | 24 ++--- .../src/modal/use-modal-exit-animation.ts | 99 +++++++++++++++++++ 6 files changed, 165 insertions(+), 36 deletions(-) create mode 100644 packages/components/src/modal/use-modal-exit-animation.ts diff --git a/packages/base-styles/_animations.scss b/packages/base-styles/_animations.scss index 8706d185aa221b..b17478ed24f040 100644 --- a/packages/base-styles/_animations.scss +++ b/packages/base-styles/_animations.scss @@ -4,7 +4,7 @@ } } -@mixin animation__fade-in($speed: 0.08s, $delay: 0s) { +@mixin animation__fade-in($speed: 0.08s, $delay: 0s, $easing: linear) { @include keyframes(__wp-base-styles-fade-in) { from { opacity: 0; @@ -15,12 +15,12 @@ } - animation: __wp-base-styles-fade-in $speed linear $delay; + animation: __wp-base-styles-fade-in $speed $easing $delay; animation-fill-mode: forwards; @include reduce-motion("animation"); } -@mixin animation__fade-out($speed: 0.08s, $delay: 0s) { +@mixin animation__fade-out($speed: 0.08s, $delay: 0s, $easing: linear) { @include keyframes(__wp-base-styles-fade-out) { from { opacity: 1; @@ -31,7 +31,7 @@ } - animation: __wp-base-styles-fade-out $speed linear $delay; + animation: __wp-base-styles-fade-out $speed $easing $delay; animation-fill-mode: forwards; @include reduce-motion("animation"); } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 0a1f5f1866bc05..4dd18914a7acb5 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -30,6 +30,7 @@ - `ResizeableBox`: Adopt elevation scale ([#65159](https://github.com/WordPress/gutenberg/pull/65159)). - `Snackbar`: Adopt elevation scale ([#65159](https://github.com/WordPress/gutenberg/pull/65159)). - `Tooltip`: Adopt elevation scale ([#65159](https://github.com/WordPress/gutenberg/pull/65159)). +- `Modal`: add exit animation for internally triggered events ([#65203](https://github.com/WordPress/gutenberg/pull/65203)). - `Card`: Adopt radius scale ([#65053](https://github.com/WordPress/gutenberg/pull/65053)). ### Bug Fixes diff --git a/packages/components/src/modal/index.tsx b/packages/components/src/modal/index.tsx index 7d988a0e7240b3..7d55c9a4d5d1e6 100644 --- a/packages/components/src/modal/index.tsx +++ b/packages/components/src/modal/index.tsx @@ -2,7 +2,6 @@ * External dependencies */ import clsx from 'clsx'; -import type { ForwardedRef, KeyboardEvent, RefObject, UIEvent } from 'react'; /** * WordPress dependencies @@ -38,10 +37,11 @@ import StyleProvider from '../style-provider'; import type { ModalProps } from './types'; import { withIgnoreIMEEvents } from '../utils/with-ignore-ime-events'; import { Spacer } from '../spacer'; +import { useModalExitAnimation } from './use-modal-exit-animation'; // Used to track and dismiss the prior modal when another opens unless nested. type Dismissers = Set< - RefObject< ModalProps[ 'onRequestClose' ] | undefined > + React.RefObject< ModalProps[ 'onRequestClose' ] | undefined > >; const ModalContext = createContext< Dismissers >( new Set() ); @@ -50,7 +50,7 @@ const bodyOpenClasses = new Map< string, number >(); function UnforwardedModal( props: ModalProps, - forwardedRef: ForwardedRef< HTMLDivElement > + forwardedRef: React.ForwardedRef< HTMLDivElement > ) { const { bodyOpenClassName = 'modal-open', @@ -70,7 +70,7 @@ function UnforwardedModal( closeButtonLabel, children, style, - overlayClassName, + overlayClassName: overlayClassnameProp, className, contentLabel, onKeyDown, @@ -184,6 +184,9 @@ function UnforwardedModal( }; }, [ bodyOpenClassName ] ); + const { closeModal, frameRef, frameStyle, overlayClassname } = + useModalExitAnimation(); + // Calls the isContentScrollable callback when the Modal children container resizes. useLayoutEffect( () => { if ( ! window.ResizeObserver || ! childrenContainerRef.current ) { @@ -200,21 +203,21 @@ function UnforwardedModal( }; }, [ isContentScrollable, childrenContainerRef ] ); - function handleEscapeKeyDown( event: KeyboardEvent< HTMLDivElement > ) { + function handleEscapeKeyDown( + event: React.KeyboardEvent< HTMLDivElement > + ) { if ( shouldCloseOnEsc && ( event.code === 'Escape' || event.key === 'Escape' ) && ! event.defaultPrevented ) { event.preventDefault(); - if ( onRequestClose ) { - onRequestClose( event ); - } + closeModal().then( () => onRequestClose( event ) ); } } const onContentContainerScroll = useCallback( - ( e: UIEvent< HTMLDivElement > ) => { + ( e: React.UIEvent< HTMLDivElement > ) => { const scrollY = e?.currentTarget?.scrollTop ?? -1; if ( ! hasScrolledContent && scrollY > 0 ) { @@ -248,7 +251,7 @@ function UnforwardedModal( const isSameTarget = target === pressTarget; pressTarget = null; if ( button === 0 && isSameTarget ) { - onRequestClose(); + closeModal().then( () => onRequestClose() ); } }, }; @@ -259,7 +262,8 @@ function UnforwardedModal( ref={ useMergeRefs( [ ref, forwardedRef ] ) } className={ clsx( 'components-modal__screen-overlay', - overlayClassName + overlayClassname, + overlayClassnameProp ) } onKeyDown={ withIgnoreIMEEvents( handleEscapeKeyDown ) } { ...( shouldCloseOnClickOutside ? overlayPressHandlers : {} ) } @@ -271,8 +275,12 @@ function UnforwardedModal( sizeClass, className ) } - style={ style } + style={ { + ...frameStyle, + ...style, + } } ref={ useMergeRefs( [ + frameRef, constrainedTabbingRef, focusReturnRef, focusOnMount !== 'firstContentElement' @@ -331,7 +339,13 @@ function UnforwardedModal( /> <Button size="small" - onClick={ onRequestClose } + onClick={ ( + event: React.MouseEvent< HTMLButtonElement > + ) => + closeModal().then( () => + onRequestClose( event ) + ) + } icon={ close } label={ closeButtonLabel || diff --git a/packages/components/src/modal/style.scss b/packages/components/src/modal/style.scss index 3790e0b7368a64..70959f69392d1c 100644 --- a/packages/components/src/modal/style.scss +++ b/packages/components/src/modal/style.scss @@ -10,6 +10,13 @@ display: flex; // This animates the appearance of the backdrop. @include animation__fade-in(); + + &.is-animating-out { + // Note: it's important that the fade-out animation doesn't end after the + // modal frame's disappear animation, because the component will be removed + // from the DOM when that animation ends. + @include animation__fade-out($delay: 80ms); + } } // The modal window element. @@ -25,10 +32,17 @@ // Have the content element fill the vertical space yet not overflow. display: flex; // Animate the modal frame/contents appearing on the page. - animation: components-modal__appear-animation 0.26s cubic-bezier(0.29, 0, 0, 1); + animation-name: components-modal__appear-animation; + animation-duration: var(--modal-frame-animation-duration); animation-fill-mode: forwards; + animation-timing-function: cubic-bezier(0.29, 0, 0, 1); @include reduce-motion("animation"); + .components-modal__screen-overlay.is-animating-out & { + animation-name: components-modal__disappear-animation; + animation-timing-function: cubic-bezier(1, 0, 0.2, 1); + } + // Show a centered modal on bigger screens. @include break-small() { border-radius: $radius-large; @@ -88,6 +102,19 @@ } } +// Note: this animation is also used in the animationend JS event listener. +// Make sure that the animation name is kept in sync across the two files. +@keyframes components-modal__disappear-animation { + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.9); + } +} + // Fix header to the top so it is always there to provide context to the modal // if the content needs to be scrolled (for example, on the keyboard shortcuts // modal screen). diff --git a/packages/components/src/modal/types.ts b/packages/components/src/modal/types.ts index 0a422718b1be14..f6f35eec85fc73 100644 --- a/packages/components/src/modal/types.ts +++ b/packages/components/src/modal/types.ts @@ -1,15 +1,3 @@ -/** - * External dependencies - */ -import type { - AriaRole, - CSSProperties, - ReactNode, - KeyboardEventHandler, - KeyboardEvent, - SyntheticEvent, -} from 'react'; - /** * WordPress dependencies */ @@ -42,7 +30,7 @@ export type ModalProps = { /** * The children elements. */ - children: ReactNode; + children: React.ReactNode; /** * If this property is added, it will an additional class name to the modal * content `div`. @@ -77,7 +65,7 @@ export type ModalProps = { * * @default null */ - headerActions?: ReactNode; + headerActions?: React.ReactNode; /** * If this property is added, an icon will be added before the title. @@ -108,12 +96,12 @@ export type ModalProps = { /** * Handle the key down on the modal frame `div`. */ - onKeyDown?: KeyboardEventHandler< HTMLDivElement >; + onKeyDown?: React.KeyboardEventHandler< HTMLDivElement >; /** * This function is called to indicate that the modal should be closed. */ onRequestClose: ( - event?: KeyboardEvent< HTMLDivElement > | SyntheticEvent + event?: React.KeyboardEvent< HTMLDivElement > | React.SyntheticEvent ) => void; /** * If this property is added, it will an additional class name to the modal @@ -126,7 +114,7 @@ export type ModalProps = { * * @default 'dialog' */ - role?: AriaRole; + role?: React.AriaRole; /** * If this property is added, it will determine whether the modal requests * to close when a mouse click occurs outside of the modal content. @@ -144,7 +132,7 @@ export type ModalProps = { /** * If this property is added, it will be added to the modal frame `div`. */ - style?: CSSProperties; + style?: React.CSSProperties; /** * This property is used as the modal header's title. * diff --git a/packages/components/src/modal/use-modal-exit-animation.ts b/packages/components/src/modal/use-modal-exit-animation.ts new file mode 100644 index 00000000000000..729b4f9ea6f86c --- /dev/null +++ b/packages/components/src/modal/use-modal-exit-animation.ts @@ -0,0 +1,99 @@ +/** + * WordPress dependencies + */ +import { useReducedMotion } from '@wordpress/compose'; +import { useCallback, useRef, useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { CONFIG } from '../utils'; +import warning from '@wordpress/warning'; + +// Animation duration (ms) extracted to JS in order to be used on a setTimeout. +const FRAME_ANIMATION_DURATION = CONFIG.transitionDuration; +const FRAME_ANIMATION_DURATION_NUMBER = Number.parseInt( + CONFIG.transitionDuration +); + +const EXIT_ANIMATION_NAME = 'components-modal__disappear-animation'; + +export function useModalExitAnimation() { + const frameRef = useRef< HTMLDivElement >(); + const [ isAnimatingOut, setIsAnimatingOut ] = useState( false ); + const isReducedMotion = useReducedMotion(); + + const closeModal = useCallback( + () => + new Promise< void >( ( closeModalResolve ) => { + // Grab a "stable" reference of the frame element, since + // the value held by the react ref might change at runtime. + const frameEl = frameRef.current; + + if ( isReducedMotion ) { + closeModalResolve(); + return; + } + + if ( ! frameEl ) { + warning( + "wp.components.Modal: the Modal component can't be closed with an exit animation because of a missing reference to the modal frame element." + ); + closeModalResolve(); + return; + } + + let handleAnimationEnd: + | undefined + | ( ( e: AnimationEvent ) => void ); + + const startAnimation = () => + new Promise< void >( ( animationResolve ) => { + handleAnimationEnd = ( e: AnimationEvent ) => { + if ( e.animationName === EXIT_ANIMATION_NAME ) { + animationResolve(); + } + }; + + frameEl.addEventListener( + 'animationend', + handleAnimationEnd + ); + setIsAnimatingOut( true ); + } ); + const animationTimeout = () => + new Promise< void >( ( timeoutResolve ) => { + setTimeout( + () => timeoutResolve(), + // Allow an extra 20% of the animation duration for the + // animationend event to fire, in case the animation frame is + // slightly delayes by some other events in the event loop. + FRAME_ANIMATION_DURATION_NUMBER * 1.2 + ); + } ); + + Promise.race( [ startAnimation(), animationTimeout() ] ).then( + () => { + if ( handleAnimationEnd ) { + frameEl.removeEventListener( + 'animationend', + handleAnimationEnd + ); + } + setIsAnimatingOut( false ); + closeModalResolve(); + } + ); + } ), + [ isReducedMotion ] + ); + + return { + overlayClassname: isAnimatingOut ? 'is-animating-out' : undefined, + frameRef, + frameStyle: { + '--modal-frame-animation-duration': `${ FRAME_ANIMATION_DURATION }`, + }, + closeModal, + }; +} From 48079e9a094d8825f3463848a5ddc65b14e44f83 Mon Sep 17 00:00:00 2001 From: Rahul Harpal <51887323+rahulharpal1603@users.noreply.github.com> Date: Wed, 18 Sep 2024 19:06:50 +0530 Subject: [PATCH 0853/1908] URLInput: Replace input with InputControl (#65158) * replace input with InputControl * change the code so that the suffix prop remains undefined if not assigned any component * Update packages/block-editor/src/components/link-control/index.js skips passing a prop when suffix isn't needed. Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> * Update index.js * minor changes, removed unnecessary comments * retrigger checks * added the newlines back for better readability * Made LinkControl and Social Icons Consistent, fixed the auto-fill highlight issue and finally cleaned up the CSS which was irrelevant after replacing input tag with InputControl * Lint Issues Fix * More CSS cleanup plus misc cleanup * CSS cleanup --------- Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> Co-authored-by: rahulharpal1603 <rahulharpal@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../src/components/link-control/index.js | 33 +++++++++++-------- .../components/link-control/search-input.js | 2 ++ .../src/components/link-control/style.scss | 22 ------------- .../src/components/url-input/index.js | 9 ++--- .../src/components/url-input/style.scss | 29 ++-------------- .../block-library/src/social-link/edit.js | 18 ++++++---- 6 files changed, 40 insertions(+), 73 deletions(-) diff --git a/packages/block-editor/src/components/link-control/index.js b/packages/block-editor/src/components/link-control/index.js index 2024aca998caac..f9e2e0bc6d790e 100644 --- a/packages/block-editor/src/components/link-control/index.js +++ b/packages/block-editor/src/components/link-control/index.js @@ -12,6 +12,7 @@ import { Notice, TextControl, __experimentalHStack as HStack, + __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useRef, useState, useEffect } from '@wordpress/element'; @@ -383,7 +384,7 @@ function LinkControl( { value={ internalControlValue?.title } onChange={ setInternalTextInputValue } onKeyDown={ handleSubmitWithEnter } - size="__unstable-large" + __next40pxDefaultSize /> ) } <LinkControlSearchInput @@ -404,20 +405,24 @@ function LinkControl( { createSuggestionButtonText } hideLabelFromVision={ ! showTextControl } + suffix={ + showActions ? undefined : ( + <InputControlSuffixWrapper variant="control"> + <Button + onClick={ + isDisabled ? noop : handleSubmit + } + label={ __( 'Submit' ) } + icon={ keyboardReturn } + className="block-editor-link-control__search-submit" + aria-disabled={ isDisabled } + size="small" + /> + </InputControlSuffixWrapper> + ) + } + props /> - { ! showActions && ( - <div className="block-editor-link-control__search-enter"> - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - onClick={ isDisabled ? noop : handleSubmit } - label={ __( 'Submit' ) } - icon={ keyboardReturn } - className="block-editor-link-control__search-submit" - aria-disabled={ isDisabled } - /> - </div> - ) } </div> { errorMessage && ( <Notice diff --git a/packages/block-editor/src/components/link-control/search-input.js b/packages/block-editor/src/components/link-control/search-input.js index 3a5dcd4148e951..f41884092e4894 100644 --- a/packages/block-editor/src/components/link-control/search-input.js +++ b/packages/block-editor/src/components/link-control/search-input.js @@ -43,6 +43,7 @@ const LinkControlSearchInput = forwardRef( withURLSuggestion = true, createSuggestionButtonText, hideLabelFromVision = false, + suffix, }, ref ) => { @@ -147,6 +148,7 @@ const LinkControlSearchInput = forwardRef( } } } ref={ ref } + suffix={ suffix } /> { children } </div> diff --git a/packages/block-editor/src/components/link-control/style.scss b/packages/block-editor/src/components/link-control/style.scss index b0a5f6af2651b3..16493e1a5aa7f0 100644 --- a/packages/block-editor/src/components/link-control/style.scss +++ b/packages/block-editor/src/components/link-control/style.scss @@ -72,34 +72,12 @@ $block-editor-link-control-number-of-actions: 1; color: $gray-900; } - input[type="text"], - // Specificity overide of URLInput defaults. - &.block-editor-url-input input[type="text"].block-editor-url-input__input { - @include input-control; - display: block; - border: $border-width solid $gray-600; - height: $button-size-next-default-40px; // components do not properly support unstable-large yet. - margin: 0; - padding: $grid-unit-10 $button-size-next-default-40px $grid-unit-10 $grid-unit-20; - position: relative; - width: 100%; - - .has-actions & { - padding-right: $grid-unit-20; - } - } } .block-editor-link-control__search-error { margin: -$grid-unit-20 * 0.5 $grid-unit-20 $grid-unit-20; // negative margin to bring the error a bit closer to the button } -.block-editor-link-control__search-enter { - position: absolute; - right: 19px; // specific to place the button properly. - top: 3px; -} - .block-editor-link-control__search-actions { padding: $grid-unit-10 $grid-unit-20 $grid-unit-20; } diff --git a/packages/block-editor/src/components/url-input/index.js b/packages/block-editor/src/components/url-input/index.js index 9a5c589a44a047..25c033e88749bb 100644 --- a/packages/block-editor/src/components/url-input/index.js +++ b/packages/block-editor/src/components/url-input/index.js @@ -12,6 +12,7 @@ import { UP, DOWN, ENTER, TAB } from '@wordpress/keycodes'; import { BaseControl, Button, + __experimentalInputControl as InputControl, Spinner, withSpokenMessages, Popover, @@ -234,8 +235,8 @@ class URLInput extends Component { this.suggestionsRequest = request; } - onChange( event ) { - this.props.onChange( event.target.value ); + onChange( newValue ) { + this.props.onChange( newValue ); } onFocus() { @@ -448,7 +449,6 @@ class URLInput extends Component { id: inputId, value, required: true, - className: 'block-editor-url-input__input', type: 'text', onChange: this.onChange, onFocus: this.onFocus, @@ -464,6 +464,7 @@ class URLInput extends Component { ? `${ suggestionOptionIdPrefix }-${ selectedSuggestion }` : undefined, ref: this.inputRef, + suffix: this.props.suffix, }; if ( renderControl ) { @@ -472,7 +473,7 @@ class URLInput extends Component { return ( <BaseControl __nextHasNoMarginBottom { ...controlProps }> - <input { ...inputProps } /> + <InputControl { ...inputProps } __next40pxDefaultSize /> { loading && <Spinner /> } </BaseControl> ); diff --git a/packages/block-editor/src/components/url-input/style.scss b/packages/block-editor/src/components/url-input/style.scss index 5afb22269765e2..155a594bae5f23 100644 --- a/packages/block-editor/src/components/url-input/style.scss +++ b/packages/block-editor/src/components/url-input/style.scss @@ -9,33 +9,14 @@ $input-size: 300px; position: relative; padding: 1px; - input[type="text"] { - width: 100%; - @include break-small() { - width: $input-size; - } - padding: $input-padding; - margin-left: 0; - margin-right: 0; - - /* Fonts smaller than 16px causes mobile safari to zoom. */ - font-size: $mobile-text-min-font-size; - @include break-small { - font-size: $default-font-size; - } - - &::-ms-clear { - display: none; - } + @include break-small() { + min-width: $input-size; + width: auto; } &.is-full-width { width: 100%; - .block-editor-url-input__input[type="text"] { - width: 100%; - } - &__suggestions { width: 100%; } @@ -49,10 +30,6 @@ $input-size: 300px; } } -.block-editor-url-input__input[type="text"] { - @include input-control; -} - // Suggestions .block-editor-url-input__suggestions { max-height: 200px; diff --git a/packages/block-library/src/social-link/edit.js b/packages/block-library/src/social-link/edit.js index 65d85c0400116f..47af181bfe17e8 100644 --- a/packages/block-library/src/social-link/edit.js +++ b/packages/block-library/src/social-link/edit.js @@ -22,6 +22,7 @@ import { PanelBody, PanelRow, TextControl, + __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { keyboardReturn } from '@wordpress/icons'; @@ -78,15 +79,18 @@ const SocialLinkURLPopover = ( { } removeBlock( clientId ); } } + suffix={ + <InputControlSuffixWrapper variant="control"> + <Button + icon={ keyboardReturn } + label={ __( 'Apply' ) } + type="submit" + size="small" + /> + </InputControlSuffixWrapper> + } /> </div> - <Button - // TODO: Switch to `true` (40px size) if possible. - __next40pxDefaultSize={ false } - icon={ keyboardReturn } - label={ __( 'Apply' ) } - type="submit" - /> </form> </URLPopover> ); From b6ba559938d32a152ff05a04522392039953b05e Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini <26530524+zaguiini@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:51:17 -0300 Subject: [PATCH 0854/1908] ComboboxControl: Add more unit tests (#65255) * Combobox Control: Do not clear values when focusing the textbox * Call onFilterValueChange on blur if no value is selected * Clear inputValue on the background to avoid suggestion flickering * Revert "Clear inputValue on the background to avoid suggestion flickering" This reverts commit 43158d2274c63b61898f448e9c10f9258555bfc0. * Revert "Call onFilterValueChange on blur if no value is selected" This reverts commit 2a628726b57f0d1442b783fe15d94ee84d5c1dbf. * Revert "Combobox Control: Do not clear values when focusing the textbox" This reverts commit 0423a7ee48d6319c2b5e86f6cbf3c36f4c637a5b. * Tweak tests --------- Co-authored-by: Lena Morita <lena@jaguchi.com> Co-authored-by: zaguiini <zaguiini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/combobox-control/test/index.tsx | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/packages/components/src/combobox-control/test/index.tsx b/packages/components/src/combobox-control/test/index.tsx index adc76590c24538..639407ac998ed2 100644 --- a/packages/components/src/combobox-control/test/index.tsx +++ b/packages/components/src/combobox-control/test/index.tsx @@ -188,6 +188,46 @@ describe.each( [ expect( input ).toHaveValue( targetOption.label ); } ); + it( 'calls onFilterValueChange whenever the textbox changes', async () => { + const user = userEvent.setup(); + const onFilterValueChangeSpy = jest.fn(); + render( + <Component + options={ timezones } + label={ defaultLabelText } + onFilterValueChange={ onFilterValueChangeSpy } + /> + ); + + const input = getInput( defaultLabelText ); + + await user.type( input, 'a' ); + expect( onFilterValueChangeSpy ).toHaveBeenCalledWith( 'a' ); + } ); + + it( 'clears the textbox value if there is no selected value on blur', async () => { + const user = userEvent.setup(); + const onFilterValueChangeSpy = jest.fn(); + render( + <Component + options={ timezones } + label={ defaultLabelText } + onFilterValueChange={ onFilterValueChangeSpy } + /> + ); + const input = getInput( defaultLabelText ); + + await user.type( input, 'a' ); + expect( input ).toHaveValue( 'a' ); + + // Blur and focus the input. + await user.tab(); + await user.click( input ); + + expect( input ).toHaveValue( '' ); + expect( onFilterValueChangeSpy ).toHaveBeenLastCalledWith( '' ); + } ); + it( 'should select the correct option from a search', async () => { const user = await userEvent.setup(); const targetOption = timezones[ 13 ]; From e40612b7d642e312c1dee42866d295e3347669ea Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:13:05 +0200 Subject: [PATCH 0855/1908] Block Bindings: Improve getRegisteredPostMeta resolver (#65450) * Do nothing when request fails * Update `State.registeredPostMeta` Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/core-data/src/resolvers.js | 11 ++++++++--- packages/core-data/src/selectors.ts | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 6cc7df27f48b1f..91a73a0b3511c2 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -993,20 +993,25 @@ export const getRevision = export const getRegisteredPostMeta = ( postType ) => async ( { dispatch, resolveSelect } ) => { + let options; try { const { rest_namespace: restNamespace = 'wp/v2', rest_base: restBase, } = ( await resolveSelect.getPostType( postType ) ) || {}; - const options = await apiFetch( { + options = await apiFetch( { path: `${ restNamespace }/${ restBase }/?context=edit`, method: 'OPTIONS', } ); + } catch ( error ) { + // Do nothing if the request comes back with an API error. + return; + } + + if ( options ) { dispatch.receiveRegisteredPostMeta( postType, options?.schema?.properties?.meta?.properties ); - } catch { - dispatch.receiveRegisteredPostMeta( postType, false ); } }; diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index ba22723f951f4e..9acadd5c0c0e70 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -47,7 +47,7 @@ export interface State { navigationFallbackId: EntityRecordKey; userPatternCategories: Array< UserPatternCategory >; defaultTemplates: Record< string, string >; - registeredPostMeta: Record< string, { postType: string } >; + registeredPostMeta: Record< string, Object >; } type EntityRecordKey = string | number; From 6a6b3a3c27a201d2dc47348db90b346c85d93f64 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:13:42 +0200 Subject: [PATCH 0856/1908] Block Bindings: Always prioritize using context in post meta source logic (#65449) * Use `getCurrentPostType` * Change conditional to prioritize context Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/editor/src/bindings/post-meta.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index 20013bd8f246bb..572cd0b525a003 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -11,10 +11,16 @@ import { unlock } from '../lock-unlock'; function getMetadata( registry, context, registeredFields ) { let metaFields = {}; - const { type } = registry.select( editorStore ).getCurrentPost(); + const type = registry.select( editorStore ).getCurrentPostType(); const { getEditedEntityRecord } = registry.select( coreDataStore ); - if ( type === 'wp_template' ) { + if ( context?.postType && context?.postId ) { + metaFields = getEditedEntityRecord( + 'postType', + context?.postType, + context?.postId + ).meta; + } else if ( type === 'wp_template' ) { // Populate the `metaFields` object with the default values. Object.entries( registeredFields || {} ).forEach( ( [ key, props ] ) => { @@ -23,12 +29,6 @@ function getMetadata( registry, context, registeredFields ) { } } ); - } else { - metaFields = getEditedEntityRecord( - 'postType', - context?.postType, - context?.postId - ).meta; } return metaFields; From 54da44d444b7dbc031171aa8a461f34b5d115065 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:14:21 +0200 Subject: [PATCH 0857/1908] Remove extra filtering of block bindings empty sources (#65447) Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/block-editor/src/hooks/block-bindings.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 33284b4cd27fd5..ea0d4cbb7fb5bf 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -218,7 +218,7 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { context, } ); // Only add source if the list is not empty. - if ( sourceList ) { + if ( Object.keys( sourceList || {} ).length ) { _fieldsList[ sourceName ] = { ...sourceList }; } } @@ -240,12 +240,6 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { if ( ! bindableAttributes || bindableAttributes.length === 0 ) { return null; } - // Remove empty sources from the list of fields. - Object.entries( fieldsList ).forEach( ( [ key, value ] ) => { - if ( ! Object.keys( value ).length ) { - delete fieldsList[ key ]; - } - } ); // Filter bindings to only show bindable attributes and remove pattern overrides. const { bindings } = metadata || {}; const filteredBindings = { ...bindings }; From dac8767321030e3a69111882178060bf3f2ed4c3 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:39:13 +0200 Subject: [PATCH 0858/1908] Platform docs: Upgrade dependencies (#65445) --- platform-docs/package-lock.json | 382 ++++++++++++++++++-------------- 1 file changed, 221 insertions(+), 161 deletions(-) diff --git a/platform-docs/package-lock.json b/platform-docs/package-lock.json index 79783f1c1d5a1c..9ebc6258ce71c4 100644 --- a/platform-docs/package-lock.json +++ b/platform-docs/package-lock.json @@ -3365,24 +3365,6 @@ "@types/ms": "*" } }, - "node_modules/@types/eslint": { - "version": "8.56.5", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.5.tgz", - "integrity": "sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw==", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -3645,9 +3627,10 @@ } }, "node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" }, "node_modules/@types/ws": { "version": "8.5.10", @@ -3863,10 +3846,11 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", "peerDependencies": { "acorn": "^8" } @@ -3908,15 +3892,15 @@ } }, "node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -4284,9 +4268,10 @@ } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -4296,7 +4281,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -4310,6 +4295,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -4318,6 +4304,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -4325,7 +4312,8 @@ "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/bonjour-service": { "version": "1.2.1", @@ -4875,9 +4863,10 @@ } }, "node_modules/compressible/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", + "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -4979,6 +4968,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -5438,12 +5428,12 @@ "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==" }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -5591,6 +5581,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -5607,6 +5598,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -5735,9 +5727,10 @@ } }, "node_modules/docusaurus-lunr-search/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" }, "node_modules/docusaurus-lunr-search/node_modules/bail": { "version": "1.0.5", @@ -5925,7 +5918,8 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, "node_modules/electron-to-chromium": { "version": "1.4.704", @@ -5960,17 +5954,19 @@ } }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/enhanced-resolve": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", - "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -6217,6 +6213,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -6269,37 +6266,37 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -6335,9 +6332,10 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "license": "MIT" }, "node_modules/express/node_modules/range-parser": { "version": "1.2.1", @@ -6388,6 +6386,12 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "license": "MIT" + }, "node_modules/fast-url-parser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", @@ -6523,12 +6527,13 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -6543,6 +6548,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -6550,7 +6556,8 @@ "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/find-cache-dir": { "version": "4.0.0", @@ -6770,6 +6777,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -7212,9 +7220,10 @@ } }, "node_modules/hast-util-from-parse5/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" }, "node_modules/hast-util-from-parse5/node_modules/unist-util-stringify-position": { "version": "2.0.3", @@ -7383,9 +7392,10 @@ } }, "node_modules/hast-util-raw/node_modules/vfile-location": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.2.tgz", - "integrity": "sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" @@ -7439,9 +7449,10 @@ } }, "node_modules/hast-util-select/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" }, "node_modules/hast-util-select/node_modules/unist-util-visit": { "version": "2.0.3", @@ -7594,9 +7605,9 @@ } }, "node_modules/hast-util-to-jsx-runtime/node_modules/inline-style-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", - "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", "license": "MIT" }, "node_modules/hast-util-to-jsx-runtime/node_modules/property-information": { @@ -7619,12 +7630,12 @@ } }, "node_modules/hast-util-to-jsx-runtime/node_modules/style-to-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.6.tgz", - "integrity": "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz", + "integrity": "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==", "license": "MIT", "dependencies": { - "inline-style-parser": "0.2.3" + "inline-style-parser": "0.2.4" } }, "node_modules/hast-util-to-parse5": { @@ -7748,9 +7759,10 @@ } }, "node_modules/hastscript/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" }, "node_modules/he": { "version": "1.2.0", @@ -7987,6 +7999,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -8074,6 +8087,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -9281,6 +9295,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -9297,9 +9312,13 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -10994,11 +11013,12 @@ ] }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -11009,6 +11029,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -11115,9 +11136,10 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/multicast-dns": { "version": "7.2.5", @@ -11279,9 +11301,13 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -11320,6 +11346,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -11508,9 +11535,10 @@ } }, "node_modules/parse-entities/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" }, "node_modules/parse-json": { "version": "5.2.0", @@ -11609,9 +11637,10 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "license": "MIT", "dependencies": { "isarray": "0.0.1" } @@ -12452,11 +12481,12 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -12523,6 +12553,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -12537,6 +12568,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -13392,7 +13424,8 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/sax": { "version": "1.3.0", @@ -13462,9 +13495,9 @@ } }, "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -13488,9 +13521,10 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -13514,6 +13548,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -13521,17 +13556,23 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, "node_modules/send/node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -13635,14 +13676,15 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" @@ -13667,7 +13709,8 @@ "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" }, "node_modules/shallow-clone": { "version": "3.0.1", @@ -13732,6 +13775,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -13919,6 +13963,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -13960,9 +14005,10 @@ } }, "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -14378,9 +14424,10 @@ } }, "node_modules/to-vfile/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" }, "node_modules/to-vfile/node_modules/unist-util-stringify-position": { "version": "2.0.3", @@ -14426,6 +14473,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -14476,6 +14524,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -14488,6 +14537,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -14496,6 +14546,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -14734,6 +14785,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -14991,12 +15043,12 @@ } }, "node_modules/vfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", - "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" }, "funding": { @@ -15056,25 +15108,25 @@ } }, "node_modules/webpack": { - "version": "5.90.3", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", - "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==", + "version": "5.94.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", + "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", + "license": "MIT", "dependencies": { - "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", + "acorn-import-attributes": "^1.9.5", "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", @@ -15082,7 +15134,7 @@ "schema-utils": "^3.2.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.0", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { @@ -15244,9 +15296,9 @@ } }, "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -15308,6 +15360,12 @@ "ajv": "^6.9.1" } }, + "node_modules/webpack/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, "node_modules/webpack/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -15463,9 +15521,10 @@ } }, "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -15579,9 +15638,10 @@ } }, "node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "license": "MIT", "engines": { "node": ">=12.20" }, From 594a948037a762e5217490d182b0ab0dc46cb537 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu <me@andreidraganescu.info> Date: Wed, 18 Sep 2024 19:09:18 +0300 Subject: [PATCH 0859/1908] remove zoom out toggle when editor is not iframed (#65452) --- packages/editor/src/components/editor-interface/index.js | 1 + packages/editor/src/components/header/index.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/editor-interface/index.js b/packages/editor/src/components/editor-interface/index.js index 284c9772d7bd6f..645e5fb6f53a26 100644 --- a/packages/editor/src/components/editor-interface/index.js +++ b/packages/editor/src/components/editor-interface/index.js @@ -139,6 +139,7 @@ export default function EditorInterface( { customSaveButton={ customSaveButton } forceDisableBlockTools={ forceDisableBlockTools } title={ title } + isEditorIframed={ ! disableIframe } /> ) } diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index cd8e5336b0ba07..fb034ba8bb8574 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -47,6 +47,7 @@ function Header( { forceDisableBlockTools, setEntitiesSavedStatesCallback, title, + isEditorIframed, } ) { const isWideViewport = useViewportMatch( 'large' ); const isLargeViewport = useViewportMatch( 'medium' ); @@ -143,7 +144,7 @@ function Header( { /> <PostViewLink /> - { isWideViewport && <ZoomOutToggle /> } + { isEditorIframed && isWideViewport && <ZoomOutToggle /> } { ( isWideViewport || ! showIconLabels ) && ( <PinnedItems.Slot scope="core" /> From bf639061fe54dfde3d1f80c9ddbaf02eba52fe31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Gomes?= <mail@sgomes.com> Date: Wed, 18 Sep 2024 17:13:38 +0100 Subject: [PATCH 0860/1908] Packages: only add polyfills where needed (#65292) * Packages: only add polyfills where needed * Attempt to fix interactivity-router * Switch to using magic comments * Remove previous experiment * Clean up changelog, comments and option name * Fix small typo in babel plugin comment * Tweak comment preservation regex * Simplify buffer check Co-authored-by: Jon Surrell <sirreal@users.noreply.github.com> * Fix outdated comment * Use Internal header for babel preset changelog * Add unit test for DEWP * Add babel plugin test * Update babel plugin readme * Simplify DEWP test Co-authored-by: Jon Surrell <sirreal@users.noreply.github.com> --------- Co-authored-by: sgomes <sergiomdgomes@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- bin/packages/get-babel-config.js | 2 + packages/babel-preset-default/CHANGELOG.md | 4 +- packages/babel-preset-default/README.md | 2 +- packages/babel-preset-default/bin/index.js | 11 ++-- packages/babel-preset-default/index.js | 14 +++++ .../polyfill-exclusions.js | 10 ++++ .../babel-preset-default/replace-polyfills.js | 59 +++++++++++++++++++ .../test/fixtures/polyfill.js | 6 ++ packages/babel-preset-default/test/index.js | 18 ++++++ .../lib/index.js | 34 ++++++++--- .../test/__snapshots__/build.js.snap | 14 +++++ .../fixtures/polyfill-magic-comment/index.js | 3 + .../polyfill-magic-comment/webpack.config.js | 8 +++ tools/webpack/packages.js | 2 +- tools/webpack/shared.js | 2 +- 15 files changed, 173 insertions(+), 16 deletions(-) create mode 100644 packages/babel-preset-default/polyfill-exclusions.js create mode 100644 packages/babel-preset-default/replace-polyfills.js create mode 100644 packages/babel-preset-default/test/fixtures/polyfill.js create mode 100644 packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment/index.js create mode 100644 packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment/webpack.config.js diff --git a/bin/packages/get-babel-config.js b/bin/packages/get-babel-config.js index 91fe4b07d325e6..9427549cafaba6 100644 --- a/bin/packages/get-babel-config.js +++ b/bin/packages/get-babel-config.js @@ -11,6 +11,8 @@ module.exports = ( environment = '', file ) => { name: `WP_BUILD_${ environment.toUpperCase() }`, }, }; + // Add `/* wp:polyfill */` magic comment where needed. + callerOpts.caller.addPolyfillComments = true; switch ( environment ) { case 'main': // To be merged as a presetEnv option. diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index 70a740f60cad38..c8c3fdb66ecb0e 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -1,6 +1,8 @@ <!-- Learn how to maintain this file at https://github.com/WordPress/gutenberg/tree/HEAD/packages#maintaining-changelogs. --> -## Unreleased +## Internal + +- Added `addPolyfillComments` option. When used, it will automatically add magic comments to mark files that need `wp-polyfill`. ## 8.7.0 (2024-09-05) diff --git a/packages/babel-preset-default/README.md b/packages/babel-preset-default/README.md index fb853a73ea3c8b..301d2583dcf865 100644 --- a/packages/babel-preset-default/README.md +++ b/packages/babel-preset-default/README.md @@ -43,7 +43,7 @@ For example, if you'd like to use a new language feature proposal which has not There is a complementary `build/polyfill.js` (minified version – `build/polyfill.min.js`) file available that polyfills ECMAScript features missing in the [browsers supported](https://make.wordpress.org/core/handbook/best-practices/browser-support/) by the WordPress project ([#31279](https://github.com/WordPress/gutenberg/pull/31279)). It's a drop-in replacement for the deprecated `@babel/polyfill` package, and it's also based on [`core-js`](https://github.com/zloirock/core-js) project. -This needs to be included before all your compiled Babel code. You can either prepend it to your compiled code or include it in a `<script>` before it. +This needs to be included in some cases, if the features being used require polyfills. You can either prepend it to your compiled code or include it in a `<script>` before it. #### TC39 Proposals diff --git a/packages/babel-preset-default/bin/index.js b/packages/babel-preset-default/bin/index.js index 0e0e66b450c1d6..041ab0143a5ae4 100755 --- a/packages/babel-preset-default/bin/index.js +++ b/packages/babel-preset-default/bin/index.js @@ -7,13 +7,14 @@ const builder = require( 'core-js-builder' ); const { minify } = require( 'terser' ); const { writeFile } = require( 'fs' ).promises; +/** + * Internal dependencies + */ +const exclusions = require( '../polyfill-exclusions' ); + builder( { modules: [ 'es.', 'web.' ], - exclude: [ - // This is an IE-only feature which we don't use, and don't want to polyfill. - // @see https://github.com/WordPress/gutenberg/pull/49234 - 'web.immediate', - ], + exclude: exclusions, summary: { console: { size: true, modules: true } }, targets: require( '@wordpress/browserslist-config' ), filename: './build/polyfill.js', diff --git a/packages/babel-preset-default/index.js b/packages/babel-preset-default/index.js index 45ec6473be3cbc..468c2cce812f69 100644 --- a/packages/babel-preset-default/index.js +++ b/packages/babel-preset-default/index.js @@ -3,6 +3,12 @@ */ const browserslist = require( 'browserslist' ); +/** + * Internal dependencies + */ +const exclusions = require( './polyfill-exclusions' ); +const replacePolyfills = require( './replace-polyfills' ); + module.exports = ( api ) => { let wpBuildOpts = {}; const isWPBuild = ( name ) => @@ -27,6 +33,13 @@ module.exports = ( api ) => { 'proposal-nullish-coalescing-operator', 'proposal-logical-assignment-operators', ], + ...( wpBuildOpts.addPolyfillComments + ? { + useBuiltIns: 'usage', + exclude: exclusions, + corejs: require( 'core-js/package.json' ).version, + } + : {} ), }; if ( isTestEnv ) { @@ -82,6 +95,7 @@ module.exports = ( api ) => { }, ], maybeGetPluginTransformRuntime(), + wpBuildOpts.addPolyfillComments && replacePolyfills, ].filter( Boolean ), }; }; diff --git a/packages/babel-preset-default/polyfill-exclusions.js b/packages/babel-preset-default/polyfill-exclusions.js new file mode 100644 index 00000000000000..507396c930b99c --- /dev/null +++ b/packages/babel-preset-default/polyfill-exclusions.js @@ -0,0 +1,10 @@ +module.exports = [ + // Ignore excessively strict polyfilling of `Array.prototype.push` to work + // around an obscure bug involving non-writable arrays. + // See https://issues.chromium.org/issues/42202623 for the details of the + // bug that leads to the polyfilling, and which we are choosing to ignore. + 'es.array.push', + // This is an IE-only feature which we don't use, and don't want to polyfill. + // @see https://github.com/WordPress/gutenberg/pull/49234 + 'web.immediate', +]; diff --git a/packages/babel-preset-default/replace-polyfills.js b/packages/babel-preset-default/replace-polyfills.js new file mode 100644 index 00000000000000..a3a68cc5f84e90 --- /dev/null +++ b/packages/babel-preset-default/replace-polyfills.js @@ -0,0 +1,59 @@ +// Babel plugin that looks for `core-js` imports (or requires) +// and replaces them with magic comments to mark the file as +// depending on wp-polyfill. +function replacePolyfills() { + return { + pre() { + this.hasAddedPolyfills = false; + }, + visitor: { + Program: { + exit( path ) { + if ( this.hasAddedPolyfills ) { + // Add magic comment to top of file. + path.addComment( 'leading', ' wp:polyfill ' ); + } + }, + }, + // Handle `import` syntax. + ImportDeclaration( path ) { + const source = path?.node?.source; + const name = source?.value || ''; + + // Look for imports from `core-js`. + if ( name.startsWith( 'core-js/' ) ) { + // Remove import. + path.remove(); + this.hasAddedPolyfills = true; + } + }, + + // Handle `require` syntax. + CallExpression( path ) { + const callee = path?.node?.callee; + const arg = path?.node?.arguments[ 0 ]; + + if ( + ! callee || + ! arg || + callee.type !== 'Identifier' || + callee.name !== 'require' + ) { + return; + } + + // Look for requires for `core-js`. + if ( + arg.type === 'StringLiteral' && + arg.value.startsWith( 'core-js/' ) + ) { + // Remove import. + path.remove(); + this.hasAddedPolyfills = true; + } + }, + }, + }; +} + +module.exports = replacePolyfills; diff --git a/packages/babel-preset-default/test/fixtures/polyfill.js b/packages/babel-preset-default/test/fixtures/polyfill.js new file mode 100644 index 00000000000000..14a4fb20f14fa4 --- /dev/null +++ b/packages/babel-preset-default/test/fixtures/polyfill.js @@ -0,0 +1,6 @@ +// Note: this fixture may need to be updated when the browserslist or the +// core-js dependencies are updated. +// It should always test a feature that is supported, but requires +// a polyfill to work across all supported browsers. +const foo = new URLSearchParams(); +window.fooSize = foo.size; diff --git a/packages/babel-preset-default/test/index.js b/packages/babel-preset-default/test/index.js index 0a411cd4247975..4a23d13544b278 100644 --- a/packages/babel-preset-default/test/index.js +++ b/packages/babel-preset-default/test/index.js @@ -24,4 +24,22 @@ describe( 'Babel preset default', () => { expect( output.code ).toMatchSnapshot(); } ); + + test( 'transpilation includes magic comment when using the addPolyfillComments option', () => { + const filename = path.join( __dirname, '/fixtures/polyfill.js' ); + const input = readFileSync( filename ); + + const output = transform( input, { + filename, + configFile: false, + envName: 'production', + presets: [ babelPresetDefault ], + caller: { + name: 'WP_BUILD_MAIN', + addPolyfillComments: true, + }, + } ); + + expect( output.code ).toContain( '/* wp:polyfill */' ); + } ); } ); diff --git a/packages/dependency-extraction-webpack-plugin/lib/index.js b/packages/dependency-extraction-webpack-plugin/lib/index.js index 0e6f8a5fbc6ccc..575882a1dfbebe 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/index.js +++ b/packages/dependency-extraction-webpack-plugin/lib/index.js @@ -269,7 +269,7 @@ class DependencyExtractionWebpackPlugin { } } - // Go through the assets and hash the sources. We can't just use + // Prepare to hash the sources. We can't just use // `chunk.contentHash` because that's not updated when // assets are minified. In practice the hash is updated by // `RealContentHashPlugin` after minification, but it only modifies @@ -278,12 +278,32 @@ class DependencyExtractionWebpackPlugin { const { hashFunction, hashDigest, hashDigestLength } = compilation.outputOptions; - const contentHash = chunkFiles - .sort() - .reduce( ( hash, filename ) => { - const asset = compilation.getAsset( filename ); - return hash.update( asset.source.buffer() ); - }, createHash( hashFunction ) ) + const hashBuilder = createHash( hashFunction ); + + const processContentsForHash = ( content ) => { + hashBuilder.update( content ); + }; + + // Prepare to look for magic comments, in order to decide whether + // `wp-polyfill` is needed. + const processContentsForMagicComments = ( content ) => { + if ( content.includes( '/* wp:polyfill */' ) ) { + chunkStaticDeps.add( 'wp-polyfill' ); + } + }; + + // Go through the assets to process the sources. + // This allows us to generate hashes, as well as look for magic comments. + chunkFiles.sort().forEach( ( filename ) => { + const asset = compilation.getAsset( filename ); + const content = asset.source.buffer(); + + processContentsForHash( content ); + processContentsForMagicComments( content ); + } ); + + // Finalise hash. + const contentHash = hashBuilder .digest( hashDigest ) .slice( 0, hashDigestLength ); diff --git a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap index d3090daa89a476..c4b450683572e8 100644 --- a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap +++ b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap @@ -235,6 +235,13 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`overrides\` should ] `; +exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comment\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` +"<?php return array('dependencies' => array('wp-polyfill'), 'version' => '9725ab782f6b09598d3d', 'type' => 'module'); +" +`; + +exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comment\` should produce expected output: External modules should match snapshot 1`] = `[]`; + exports[`DependencyExtractionWebpackPlugin modules Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'a.asset.php' should match snapshot 1`] = ` "<?php return array('dependencies' => array('@wordpress/blob'), 'version' => 'a1906cfc819b623c86f8', 'type' => 'module'); " @@ -619,6 +626,13 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`overrides\` should ] `; +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comment\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` +"<?php return array('dependencies' => array('wp-polyfill'), 'version' => '464c785b5c938d4fde3f'); +" +`; + +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comment\` should produce expected output: External modules should match snapshot 1`] = `[]`; + exports[`DependencyExtractionWebpackPlugin scripts Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'a.asset.php' should match snapshot 1`] = ` "<?php return array('dependencies' => array('wp-blob'), 'version' => 'd3cda564b538b44d38ef'); " diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment/index.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment/index.js new file mode 100644 index 00000000000000..d98678f44cb697 --- /dev/null +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment/index.js @@ -0,0 +1,3 @@ +/* wp:polyfill */ + +// Nothing else, really. diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment/webpack.config.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment/webpack.config.js new file mode 100644 index 00000000000000..bfffff3ae78319 --- /dev/null +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment/webpack.config.js @@ -0,0 +1,8 @@ +/** + * Internal dependencies + */ +const DependencyExtractionWebpackPlugin = require( '../../..' ); + +module.exports = { + plugins: [ new DependencyExtractionWebpackPlugin() ], +}; diff --git a/tools/webpack/packages.js b/tools/webpack/packages.js index a1610d0a5ba54e..76d460cafc15d0 100644 --- a/tools/webpack/packages.js +++ b/tools/webpack/packages.js @@ -146,7 +146,7 @@ module.exports = { }, plugins: [ ...plugins, - new DependencyExtractionWebpackPlugin( { injectPolyfill: true } ), + new DependencyExtractionWebpackPlugin( { injectPolyfill: false } ), new CopyWebpackPlugin( { patterns: gutenbergPackages .map( ( packageName ) => ( { diff --git a/tools/webpack/shared.js b/tools/webpack/shared.js index f30d3a830f3eb1..c8c5b05c7d151b 100644 --- a/tools/webpack/shared.js +++ b/tools/webpack/shared.js @@ -25,7 +25,7 @@ const baseConfig = { parallel: true, terserOptions: { output: { - comments: /translators:/i, + comments: /(translators:|wp:polyfill)/i, }, compress: { passes: 2, From 623f2686969f8cf95083cb564e3284428f272560 Mon Sep 17 00:00:00 2001 From: Sarah Norris <1645628+mikachan@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:31:23 +0100 Subject: [PATCH 0861/1908] Query Loop: Default to querying posts when on singular content (#65067) * Fix linter warnings * Replace the postType if current post type is different * Remove currentPostType logic * Default to posts if is_singular * Update test_rendering_post_template_with_main_query_loop_already_started test * Add test for query loop not inside a singular query * Revert changes to QueryContent * Show query type control only when on a template * Move template logic to QueryInspectorControls * Ensure inherit value is updated when not in a template * Update comment * Rename showDefaultControl to isTemplate * Get postType from context * Add a check for singular content based on available post type * Move inherit reset to a useEffect * Move isTemplate logic to QueryContent * Fix lint warnings Unlinked contributors: alaczek, autumnfjeld. Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> Co-authored-by: creativecoder <grantmkin@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../block-library/src/post-template/index.php | 5 ++ packages/block-library/src/query/block.json | 1 + .../query/edit/inspector-controls/index.js | 20 ++++-- .../src/query/edit/query-content.js | 43 ++++++++++-- phpunit/blocks/render-post-template-test.php | 70 +++++++++++++++++-- 5 files changed, 122 insertions(+), 17 deletions(-) diff --git a/packages/block-library/src/post-template/index.php b/packages/block-library/src/post-template/index.php index 9126355c096a57..64cdd156a54310 100644 --- a/packages/block-library/src/post-template/index.php +++ b/packages/block-library/src/post-template/index.php @@ -64,6 +64,11 @@ function render_block_core_post_template( $attributes, $content, $block ) { if ( in_the_loop() ) { $query = clone $wp_query; $query->rewind_posts(); + + // If in a single post of any post type, default to the 'post' post type. + if ( is_singular() ) { + query_posts( array( 'post_type' => 'post' ) ); + } } else { $query = $wp_query; } diff --git a/packages/block-library/src/query/block.json b/packages/block-library/src/query/block.json index 9eb84959638236..22bfa7b713801c 100644 --- a/packages/block-library/src/query/block.json +++ b/packages/block-library/src/query/block.json @@ -41,6 +41,7 @@ "default": false } }, + "usesContext": [ "postType" ], "providesContext": { "queryId": "queryId", "query": "query", diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index 6c246ab89b3b37..4085128e9aef1a 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -45,7 +45,7 @@ import { useToolsPanelDropdownMenuProps } from '../../../utils/hooks'; const { BlockInfo } = unlock( blockEditorPrivateApis ); export default function QueryInspectorControls( props ) { - const { attributes, setQuery, setDisplayLayout } = props; + const { attributes, setQuery, setDisplayLayout, isTemplate } = props; const { query, displayLayout } = attributes; const { order, @@ -103,6 +103,7 @@ export default function QueryInspectorControls( props ) { if ( ! hasFormatSupport ) { updateQuery.format = []; } + setQuery( updateQuery ); }; const [ querySearch, setQuerySearch ] = useState( query.search ); @@ -118,20 +119,25 @@ export default function QueryInspectorControls( props ) { onChangeDebounced(); return onChangeDebounced.cancel; }, [ querySearch, onChangeDebounced ] ); - const showInheritControl = isControlAllowed( allowedControls, 'inherit' ); + + const showInheritControl = + isTemplate && isControlAllowed( allowedControls, 'inherit' ); const showPostTypeControl = - ! inherit && isControlAllowed( allowedControls, 'postType' ); + ( ! inherit && isControlAllowed( allowedControls, 'postType' ) ) || + ! isTemplate; const postTypeControlLabel = __( 'Post type' ); const postTypeControlHelp = __( 'Select the type of content to display: posts, pages, or custom post types.' ); const showColumnsControl = false; const showOrderControl = - ! inherit && isControlAllowed( allowedControls, 'order' ); + ( ! inherit && isControlAllowed( allowedControls, 'order' ) ) || + ! isTemplate; const showStickyControl = - ! inherit && - showSticky && - isControlAllowed( allowedControls, 'sticky' ); + ( ! inherit && + showSticky && + isControlAllowed( allowedControls, 'sticky' ) ) || + ( showSticky && ! isTemplate ); const showSettingsPanel = showInheritControl || showPostTypeControl || diff --git a/packages/block-library/src/query/edit/query-content.js b/packages/block-library/src/query/edit/query-content.js index 4624b3b96049e9..8b3ff09b17934b 100644 --- a/packages/block-library/src/query/edit/query-content.js +++ b/packages/block-library/src/query/edit/query-content.js @@ -3,7 +3,7 @@ */ import { useSelect, useDispatch } from '@wordpress/data'; import { useInstanceId } from '@wordpress/compose'; -import { useEffect } from '@wordpress/element'; +import { useEffect, useCallback } from '@wordpress/element'; import { BlockControls, InspectorControls, @@ -32,6 +32,7 @@ export default function QueryContent( { openPatternSelectionModal, name, clientId, + context, } ) { const { queryId, @@ -41,6 +42,7 @@ export default function QueryContent( { tagName: TagName = 'div', query: { inherit } = {}, } = attributes; + const { postType } = context; const { __unstableMarkNextChangeAsNotPersistent } = useDispatch( blockEditorStore ); const instanceId = useInstanceId( QueryContent ); @@ -48,6 +50,16 @@ export default function QueryContent( { const innerBlocksProps = useInnerBlocksProps( blockProps, { template: TEMPLATE, } ); + const isTemplate = useSelect( + ( select ) => { + const currentTemplate = + select( coreStore ).__experimentalGetTemplateForLink()?.type; + const isInTemplate = 'wp_template' === currentTemplate; + const isInSingularContent = postType !== undefined; + return isInTemplate && ! isInSingularContent; + }, + [ postType ] + ); const { postsPerPage } = useSelect( ( select ) => { const { getSettings } = select( blockEditorStore ); const { getEntityRecord, getEntityRecordEdits, canUser } = @@ -81,6 +93,10 @@ export default function QueryContent( { // Changes in query property (which is an object) need to be in the same callback, // because updates are batched after the render and changes in different query properties // would cause to override previous wanted changes. + const updateQuery = useCallback( + ( newQuery ) => setAttributes( { query: { ...query, ...newQuery } } ), + [ query, setAttributes ] + ); useEffect( () => { const newQuery = {}; // When we inherit from global query always need to set the `perPage` @@ -90,11 +106,24 @@ export default function QueryContent( { } else if ( ! query.perPage && postsPerPage ) { newQuery.perPage = postsPerPage; } + // We need to reset the `inherit` value if not in a template, as queries + // are not inherited when outside a template (e.g. when in singular content). + if ( ! isTemplate && query.inherit ) { + newQuery.inherit = false; + } if ( !! Object.keys( newQuery ).length ) { __unstableMarkNextChangeAsNotPersistent(); updateQuery( newQuery ); } - }, [ query.perPage, postsPerPage, inherit ] ); + }, [ + query.perPage, + postsPerPage, + inherit, + isTemplate, + query.inherit, + __unstableMarkNextChangeAsNotPersistent, + updateQuery, + ] ); // We need this for multi-query block pagination. // Query parameters for each block are scoped to their ID. useEffect( () => { @@ -102,9 +131,12 @@ export default function QueryContent( { __unstableMarkNextChangeAsNotPersistent(); setAttributes( { queryId: instanceId } ); } - }, [ queryId, instanceId ] ); - const updateQuery = ( newQuery ) => - setAttributes( { query: { ...query, ...newQuery } } ); + }, [ + queryId, + instanceId, + __unstableMarkNextChangeAsNotPersistent, + setAttributes, + ] ); const updateDisplayLayout = ( newDisplayLayout ) => setAttributes( { displayLayout: { ...displayLayout, ...newDisplayLayout }, @@ -135,6 +167,7 @@ export default function QueryContent( { setDisplayLayout={ updateDisplayLayout } setAttributes={ setAttributes } clientId={ clientId } + isTemplate={ isTemplate } /> </InspectorControls> <BlockControls> diff --git a/phpunit/blocks/render-post-template-test.php b/phpunit/blocks/render-post-template-test.php index e375758044681a..6241f6f0605164 100644 --- a/phpunit/blocks/render-post-template-test.php +++ b/phpunit/blocks/render-post-template-test.php @@ -113,9 +113,10 @@ public function test_rendering_post_template_with_main_query_loop() { } /** - * Tests that the `core/post-template` block does not tamper with the main query loop when rendering within a post + * Tests that the `core/post-template` block does not tamper with the main query loop when rendering within a single post * as the main query loop has already been started. In this case, the main query object needs to be cloned to * prevent an infinite loop. + * Also tests that the default query returns posts of the 'post' post type when in a single post of any post type. */ public function test_rendering_post_template_with_main_query_loop_already_started() { global $wp_query, $wp_the_query; @@ -127,10 +128,18 @@ public function test_rendering_post_template_with_main_query_loop_already_starte $content .= '<!-- /wp:post-template -->'; $content .= '<!-- /wp:query -->'; - $expected = '<ul class="alignwide wp-block-post-template is-layout-flow wp-block-post-template-is-layout-flow wp-block-query-is-layout-flow">'; - $expected .= '<li class="wp-block-post post-' . self::$post->ID . ' post type-post status-publish format-standard hentry category-uncategorized">'; - $expected .= '<h2 class="wp-block-post-title">' . self::$post->post_title . '</h2>'; - $expected .= '</li>'; + $expected = '<ul class="alignwide wp-block-post-template is-layout-flow wp-block-post-template-is-layout-flow wp-block-query-is-layout-flow">'; + + // Find all the posts of the 'post' post type. + $wp_query_posts = new WP_Query( array( 'post_type' => 'post' ) ); + + while ( $wp_query_posts->have_posts() ) { + $wp_query_posts->the_post(); + $expected .= '<li class="wp-block-post post-' . get_the_ID() . ' post type-post status-publish format-standard hentry category-uncategorized">'; + $expected .= '<h2 class="wp-block-post-title">' . get_the_title() . '</h2>'; + $expected .= '</li>'; + } + $expected .= '</ul>'; // Update the post's content to have a query block for the same query as the main query. @@ -156,4 +165,55 @@ public function test_rendering_post_template_with_main_query_loop_already_starte $this->assertSame( $expected, $output, 'Unexpected parsed post content' ); } + + /** + * Tests that the `core/post-template` block rewinds the default query when not in a single post of any post type. + */ + public function test_rendering_post_template_with_main_query_loop_not_single_post() { + global $wp_query, $wp_the_query; + + // Query block with post template block. + $content = '<!-- wp:query {"query":{"inherit":true}} -->'; + $content .= '<!-- wp:post-template {"align":"wide"} -->'; + $content .= '<!-- wp:post-title /-->'; + $content .= '<!-- /wp:post-template -->'; + $content .= '<!-- /wp:query -->'; + + $expected = '<ul class="alignwide wp-block-post-template is-layout-flow wp-block-post-template-is-layout-flow wp-block-query-is-layout-flow">'; + + // Find all the posts of the 'post' post type. + $wp_query_posts = new WP_Query( array( 'post_type' => 'post' ) ); + + while ( $wp_query_posts->have_posts() ) { + $wp_query_posts->the_post(); + $expected .= '<li class="wp-block-post post-' . get_the_ID() . ' post type-post status-publish format-standard hentry category-uncategorized">'; + $expected .= '<h2 class="wp-block-post-title">' . get_the_title() . '</h2>'; + $expected .= '</li>'; + } + + $expected .= '</ul>'; + + // Update the post's content to have a query block for the same query as the main query. + wp_update_post( + array( + 'ID' => self::$post->ID, + 'post_content' => $content, + 'post_content_filtered' => $content, + ) + ); + + // Set main query to all posts. + $wp_query = new WP_Query( array( 'post_type' => 'post' ) ); + $wp_the_query = $wp_query; + + // Get post content within main query loop. + $output = ''; + while ( $wp_query->have_posts() ) { + $wp_query->the_post(); + + $output = get_echo( 'the_content' ); + } + + $this->assertSame( $expected, $output, 'Unexpected parsed post content' ); + } } From fa406d5ae97984154990ea5769aeca677bcc8958 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:58:08 +1000 Subject: [PATCH 0862/1908] Build zip artifact on release and wp production branches. (#65471) --- .github/workflows/build-plugin-zip.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-plugin-zip.yml b/.github/workflows/build-plugin-zip.yml index 603d6123df1ea2..ce830c04f651d8 100644 --- a/.github/workflows/build-plugin-zip.yml +++ b/.github/workflows/build-plugin-zip.yml @@ -3,7 +3,10 @@ name: Build Gutenberg Plugin Zip on: pull_request: push: - branches: [trunk] + branches: + - trunk + - 'release/**' + - 'wp/**' workflow_dispatch: inputs: version: From 95bdc2f1f5213abdf123c0039ebcf0797a7b5e8e Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 19 Sep 2024 01:57:31 +0000 Subject: [PATCH 0863/1908] Bump plugin version to 19.3.0-rc.1 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 342c61fb56cd13..8dddcfeccd5282 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.2.0 + * Version: 19.3.0-rc.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index dcdc5043ac6d88..421f1418cd5f25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.2.0", + "version": "19.3.0-rc.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.2.0", + "version": "19.3.0-rc.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 46d2b42f267abb..a4cc002adbf8e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.2.0", + "version": "19.3.0-rc.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 19047d6b85da25c0400a3c7990bf04d5106be1ce Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 19 Sep 2024 02:13:29 +0000 Subject: [PATCH 0864/1908] Update Changelog for 19.3.0-rc.1 --- changelog.txt | 271 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) diff --git a/changelog.txt b/changelog.txt index b0e6c8e907582e..dca31f9afc622e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,276 @@ == Changelog == += 19.3.0-rc.1 = + +## Changelog + +### Features + +#### Zoom Out +- Remove experimental flag. ([65404](https://github.com/WordPress/gutenberg/pull/65404)) + +### Enhancements + +- Create Block: Update the minimum required PHP version to 7.2. ([65166](https://github.com/WordPress/gutenberg/pull/65166)) +- DataViews: remove unused `.dataviews-view-table__cell-content-wrapper:Empty` style rule. ([65084](https://github.com/WordPress/gutenberg/pull/65084)) +- Media Utils: Add TypeScript support and export more utils. ([64784](https://github.com/WordPress/gutenberg/pull/64784)) +- Media placeholders: Add "drag" to the text. ([65149](https://github.com/WordPress/gutenberg/pull/65149)) +- Restore: Move to trash button in Document settings. ([65087](https://github.com/WordPress/gutenberg/pull/65087)) +- Inspector Controls: Use custom block name in inspector controls when available. ([65398](https://github.com/WordPress/gutenberg/pull/65398)) +- Plugin: Don't force iframe editor when gutenberg plugin and block theme are enabled. ([65372](https://github.com/WordPress/gutenberg/pull/65372)) +- Icons: Adds bell and bell-unread icons. ([65324](https://github.com/WordPress/gutenberg/pull/65324)) +- Editor topbar: Reorder the actions on the right. ([65163](https://github.com/WordPress/gutenberg/pull/65163)) +- Patterns: Add opt out preference to the 'Choose a Pattern' modal when adding a page. ([65026](https://github.com/WordPress/gutenberg/pull/65026)) +- Locked Templates: Blocks with contentOnly locking should not be transformable. ([64917](https://github.com/WordPress/gutenberg/pull/64917)) +- Block Locking: Add border to Replace item in content only image toolbar. ([64849](https://github.com/WordPress/gutenberg/pull/64849)) + +#### Components +- Styling: Apply elevation scale in components package. ([65159](https://github.com/WordPress/gutenberg/pull/65159)) +- Tabs: Improve Tabs indicator animation and related utils. ([64926](https://github.com/WordPress/gutenberg/pull/64926)) +- Modal + - Add exit animation. ([65203](https://github.com/WordPress/gutenberg/pull/65203)) + - Decrease close button size. ([65131](https://github.com/WordPress/gutenberg/pull/65131)) +- Navigator Screen: Warn if path doesn't follow a URL-like scheme. ([65231](https://github.com/WordPress/gutenberg/pull/65231)) +- Card: Update Card radius. ([65053](https://github.com/WordPress/gutenberg/pull/65053)) +- Combobox Control: Add placeholder attribute. ([65254](https://github.com/WordPress/gutenberg/pull/65254)) + +#### Block Library +- Allow dropping multiple images to the image block. ([65030](https://github.com/WordPress/gutenberg/pull/65030)) +- Categories List block: Add dropdown for taxonomies. ([65272](https://github.com/WordPress/gutenberg/pull/65272)) +- Image: Adds the block controls for uploading image. ([64320](https://github.com/WordPress/gutenberg/pull/64320)) +- Remove colons from control labels. ([65205](https://github.com/WordPress/gutenberg/pull/65205)) +- Terms List block: Add Categories-specific variation. ([65434](https://github.com/WordPress/gutenberg/pull/65434)) + +#### Zoom Out +- Add Zoom Out toggle to editor header when experiment enabled. ([65183](https://github.com/WordPress/gutenberg/pull/65183)) +- Add prompt for drag and drop in Patterns tab in Zoom Out mode. ([65115](https://github.com/WordPress/gutenberg/pull/65115)) +- Close inserter on exiting Zoom Out to edit. ([65194](https://github.com/WordPress/gutenberg/pull/65194)) +- Show top level sections in List View. ([65202](https://github.com/WordPress/gutenberg/pull/65202)) +- Try vertical displacement when dragging a pattern between existing patterns/sections. ([63896](https://github.com/WordPress/gutenberg/pull/63896)) + +#### Block Editor +- Link Editing: Automatically add tel to phone number when linking URL. ([64865](https://github.com/WordPress/gutenberg/pull/64865)) +thub.com/WordPress/gutenberg/pull/65300)) +- Drag and Drop: When dragging a mix of video, audio, and image blocks, create individual blocks as appropriate. ([65144](https://github.com/WordPress/gutenberg/pull/65144)) +- URLInput: Replace input with InputControl. ([65158](https://github.com/WordPress/gutenberg/pull/65158)) +- Normalize block inspector controls spacing. ([64526](https://github.com/WordPress/gutenberg/pull/64526)) + +#### Post Editor +- Add new Media section to preferences modal. ([64846](https://github.com/WordPress/gutenberg/pull/64846)) +- DocumentBar: Replace icon with post type label. ([65170](https://github.com/WordPress/gutenberg/pull/65170)) +- Page editor: Double-click to edit template part. ([65024](https://github.com/WordPress/gutenberg/pull/65024)) +- Post publish upload media dialog: Handle more block types. ([65122](https://github.com/WordPress/gutenberg/pull/65122)) + +#### Block bindings +- Populate block context with inherited post type from template slug. ([65062](https://github.com/WordPress/gutenberg/pull/65062)) +- Try gap 0 on attribute items. ([65277](https://github.com/WordPress/gutenberg/pull/65277)) +- Use post meta label from `register_meta` in block bindings workflows. ([65099](https://github.com/WordPress/gutenberg/pull/65099)) + +#### Global Styles +- Refactor site background controls and move site global styles into Background group. ([65304](https://github.com/WordPress/gutenberg/pull/65304)) +- Spacing control: Replace sides dropdwon with link button. ([65193](https://github.com/WordPress/gutenberg/pull/65193)) + +#### Data Views +- DataViews Sidebar: Display item count on DataViews sidebar. ([65223](https://github.com/WordPress/gutenberg/pull/65223)) +- DataViews: Improve UX of bundled views for Pages. ([65295](https://github.com/WordPress/gutenberg/pull/65295)) + +#### Interactivity API +- Refactor context proxies. ([64713](https://github.com/WordPress/gutenberg/pull/64713)) +- Update: Rephrase "Force page reload" and move to Advanced. ([65081](https://github.com/WordPress/gutenberg/pull/65081)) + +#### REST API +- Global Styles: Allow read access to users with `edit_posts` capabilities. ([65071](https://github.com/WordPress/gutenberg/pull/65071)) +- Query loop / Post template: Enable post format filter. ([64167](https://github.com/WordPress/gutenberg/pull/64167)) + +### New APIs +- Add @wordpress/fields package. + - Introduce the package. ([65230](https://github.com/WordPress/gutenberg/pull/65230)) + - Make the package private. ([65269](https://github.com/WordPress/gutenberg/pull/65269)) + +### Bug Fixes + +- Align popover alt variant styling with block toolbar. ([65263](https://github.com/WordPress/gutenberg/pull/65263)) +- Compose: Correctly call timer cleanup in 'useFocusOnMount'. ([65184](https://github.com/WordPress/gutenberg/pull/65184)) +- Fix some docblock types related to the Template Registration API. ([65187](https://github.com/WordPress/gutenberg/pull/65187)) +- Fix the issue where block spacing control not shown. ([65371](https://github.com/WordPress/gutenberg/pull/65371)) +- Fix unintentional block toolbar shadow. ([65182](https://github.com/WordPress/gutenberg/pull/65182)) +- Fix: Moving a page to the trash on the site editor does not goes back to the pages list. ([65119](https://github.com/WordPress/gutenberg/pull/65119)) +- Fix: Moving the last page item to the the trash causes a crash. ([65236](https://github.com/WordPress/gutenberg/pull/65236)) +- Preferences: Fix back button on mobile. ([65141](https://github.com/WordPress/gutenberg/pull/65141)) +- Revert "Don't force iframe editor when gutenberg plugin and block the me are enabled (#65372)". ([65402](https://github.com/WordPress/gutenberg/pull/65402)) +- Post Summary Panel: Restore `height:Auto` for toggle buttons. ([65362](https://github.com/WordPress/gutenberg/pull/65362)) +- Fix Tabs styling in Font Library modal. ([65330](https://github.com/WordPress/gutenberg/pull/65330)) +- E2E: Change deprecated social icons for standard in end-to-end. ([65312](https://github.com/WordPress/gutenberg/pull/65312)) +- Typography: Make title blocks apply typographic styles consistently. ([65307](https://github.com/WordPress/gutenberg/pull/65307)) +- Target Hints REST API: Add missing param sanitization. ([65280](https://github.com/WordPress/gutenberg/pull/65280)) +- Interactivity API: Update iterable signals when `deepMerge()` adds new properties. ([65135](https://github.com/WordPress/gutenberg/pull/65135)) +- Navigation Menus: Typography styling support to the navigation submenu block. ([65060](https://github.com/WordPress/gutenberg/pull/65060)) +- Grid: In RTL languages, the resize handles point in the opposite direction. ([64995](https://github.com/WordPress/gutenberg/pull/64995)) +- Block Locking: Fix Content Only Toolbar icon focus style. ([64940](https://github.com/WordPress/gutenberg/pull/64940)) +- Image: Fix resizing to max width in classic themes. ([64819](https://github.com/WordPress/gutenberg/pull/64819)) +- Meta Boxes: Try split content view. ([64351](https://github.com/WordPress/gutenberg/pull/64351)) +- Distraction Free: Fix blurry edge along editor header. ([64277](https://github.com/WordPress/gutenberg/pull/64277)) + +#### Block Library +- Comments Pagination: Fix warning returned by comments pagination blocks. ([65435](https://github.com/WordPress/gutenberg/pull/65435)) +- Cover: Explicitly set isUserOverlayColor to false when media is updated. ([65105](https://github.com/WordPress/gutenberg/pull/65105)) +- Disallow setting grid block rows/columns to zero. ([65217](https://github.com/WordPress/gutenberg/pull/65217)) +- Fix image block crash. ([65222](https://github.com/WordPress/gutenberg/pull/65222)) +- Fix: Buttons block: Block spacing value does not apply to both vertical and horizontal alignment. ([64971](https://github.com/WordPress/gutenberg/pull/64971)) +- Fix: Embed blocks: Figcaption inserted via toolbar not nested within figure element - #64960. ([64970](https://github.com/WordPress/gutenberg/pull/64970)) +- Image cropping: Skip making an API request if there are no changes to apply. ([65384](https://github.com/WordPress/gutenberg/pull/65384)) +- Comments Pagination: Pass the comments query `paged` arg to functions `get_next_comments_link` and `get_previous_comments_link`. ([63698](https://github.com/WordPress/gutenberg/pull/63698)) +- Query Loop: Default to querying posts when on singular content. ([65067](https://github.com/WordPress/gutenberg/pull/65067)) + +#### Block Editor +- Inserter: Fix loading indicator for reusable blocks. ([64839](https://github.com/WordPress/gutenberg/pull/64839)) +- Normalize spacing in Layout hook controls. ([65132](https://github.com/WordPress/gutenberg/pull/65132)) +- Pattern Inserter: Fix pattern list overflow. ([65192](https://github.com/WordPress/gutenberg/pull/65192)) +- Remove reset styles RTL from the iframe. ([65150](https://github.com/WordPress/gutenberg/pull/65150)) +- Revert "Block Insertion: Clear the insertion point when selecting a d…. ([65208](https://github.com/WordPress/gutenberg/pull/65208)) + +#### Components +- BoxControl: Unify input filed width whether linked or not. ([65348](https://github.com/WordPress/gutenberg/pull/65348)) +- ComboboxControl: Add more unit tests. ([65255](https://github.com/WordPress/gutenberg/pull/65255)) +- Fix: Button Replace remaining 40px default size violations [Edit widgets]. ([65367](https://github.com/WordPress/gutenberg/pull/65367)) +- Tabs: Fix vertical indicator. ([65385](https://github.com/WordPress/gutenberg/pull/65385)) + +#### Block bindings +- Fix empty strings placeholders in post meta bindings. ([65089](https://github.com/WordPress/gutenberg/pull/65089)) +- Prioritize existing `placeholder` over `bindingsPlaceholder`. ([65154](https://github.com/WordPress/gutenberg/pull/65154)) +- Revert "Block Bindings: Prioritize existing `placeholder` over `bindingsPlaceholder`". ([65190](https://github.com/WordPress/gutenberg/pull/65190)) + +#### Zoom Out +- Force device type to Desktop whenever zoom out is invoked. ([64476](https://github.com/WordPress/gutenberg/pull/64476)) +- Hide toolbar icon on smaller viewports. ([65437](https://github.com/WordPress/gutenberg/pull/65437)) +- Remove zoom out toggle when editor is not iframed. ([65452](https://github.com/WordPress/gutenberg/pull/65452)) + +### Accessibility + +- A11y: Add script-module. ([65101](https://github.com/WordPress/gutenberg/pull/65101)) +- Interactivity API: Use a11y Script Module in Gutenberg. ([65123](https://github.com/WordPress/gutenberg/pull/65123)) +- Script Modules API: Print script module live regions HTML in page HTML. ([65380](https://github.com/WordPress/gutenberg/pull/65380)) +- Post Editor: Support keyboard resizing of meta boxes pane. ([65325](https://github.com/WordPress/gutenberg/pull/65325)) +- DatePicker: Better hover/focus styles. ([65117](https://github.com/WordPress/gutenberg/pull/65117)) +- Form Input: Don't use `flex-direction: Row-reverse` for checkbox field. ([64232](https://github.com/WordPress/gutenberg/pull/64232)) +- Navigation Menus: Remove Warning and add notice for Navigation. ([63921](https://github.com/WordPress/gutenberg/pull/63921)) +- Global Styles: Fix the shadows Range control accessibility and usability. ([63908](https://github.com/WordPress/gutenberg/pull/63908)) +- Block Editor: Fix accessibility of the hooked blocks toggles. ([63133](https://github.com/WordPress/gutenberg/pull/63133)) + + +### Performance + +- Core Data: Batch remaining actions in resolvers. ([65176](https://github.com/WordPress/gutenberg/pull/65176)) +- Block Editor: Use static access for selector in 'useZoomOutModeExit'. ([65337](https://github.com/WordPress/gutenberg/pull/65337)) +- Editor: Optimize global styles permission check. ([65177](https://github.com/WordPress/gutenberg/pull/65177)) + + +### Experiments + +- Block bindings REST API: Bring bindings UI in Site Editor. ([64072](https://github.com/WordPress/gutenberg/pull/64072)) + + +### Documentation + +- Add JSDoc block for getSectionRootClientId in block editor package. ([65219](https://github.com/WordPress/gutenberg/pull/65219)) +- ButtonGroup: Fix story to show what the component does. ([65336](https://github.com/WordPress/gutenberg/pull/65336)) +- DataViews storybook + - Better styles for combined fields story. ([65078](https://github.com/WordPress/gutenberg/pull/65078)) + - Enable all layouts for combined fields storybook. ([65082](https://github.com/WordPress/gutenberg/pull/65082)) +- Docs: Fix minor typos in Build your first block tutorial. ([64961](https://github.com/WordPress/gutenberg/pull/64961)) +- Docs: Update the content of the API version 3 section in the Block API Reference. ([65375](https://github.com/WordPress/gutenberg/pull/65375)) +- Fix typo in Slot Fills documentation. ([65275](https://github.com/WordPress/gutenberg/pull/65275)) + + +### Code Quality + +- Components: Transition to the new 40px default size. + - Button: + - Add __next40pxDefaultSize for files in editor 3. ([65139](https://github.com/WordPress/gutenberg/pull/65139)) + - Add __next40pxDefaultSize for files in editor 4. ([65140](https://github.com/WordPress/gutenberg/pull/65140)) + - Add props for buttons in editor 1. ([65068](https://github.com/WordPress/gutenberg/pull/65068)) + - Add props for buttons in editor 2. ([65083](https://github.com/WordPress/gutenberg/pull/65083)) + - Fix: Replace remaining 40px default size violations [Block Editor 4]. ([65257](https://github.com/WordPress/gutenberg/pull/65257)) + - Fix: Replace remaining 40px default size violation [Block library 3]. ([65110](https://github.com/WordPress/gutenberg/pull/65110)) + - Fix: Replace remaining 40px default size violation [Block library 4]. ([65143](https://github.com/WordPress/gutenberg/pull/65143)) + - Fix: Replace remaining 40px default size violation [Block library]. ([65075](https://github.com/WordPress/gutenberg/pull/65075)) + - Fix: Replace remaining 40px default size violation [Edit Site 2]. ([65258](https://github.com/WordPress/gutenberg/pull/65258)) + - Fix: Replace remaining 40px default size violations [Block library 1]. ([65033](https://github.com/WordPress/gutenberg/pull/65033)) + - Fix: Replace remaining 40px default size violations [Block Editor 1]. ([65034](https://github.com/WordPress/gutenberg/pull/65034)) + - BoxControl + - Add lint rule for 40px size prop usage. ([65341](https://github.com/WordPress/gutenberg/pull/65341)) + - DimensionsPanel: Apply 40px default size to UI when no spacing preset is available. ([65300](https://gi +- Add `useEvent` and revamped `useResizeObserver` to `@wordpress/compose`. ([64943](https://github.com/WordPress/gutenberg/pull/64943)) +- DataViews: Use Dropdown for views configuration dialog. ([65314](https://github.com/WordPress/gutenberg/pull/65314)) +- Platform docs: Upgrade dependencies. ([65445](https://github.com/WordPress/gutenberg/pull/65445)) +- Rename edit-post__fade-in-animation and unify keyframe definitions. ([65377](https://github.com/WordPress/gutenberg/pull/65377)) +- Update minimum required version in PHP. ([65301](https://github.com/WordPress/gutenberg/pull/65301)) +- Editor: Use hooks instead of HoC in `BlockManager`. ([65349](https://github.com/WordPress/gutenberg/pull/65349)) +- Data Views Fields: Migrate store and actions from editor package to fields package. ([65261](https://github.com/WordPress/gutenberg/pull/65261)) +- Plugin: Remove 'function_exists' checks for methods with 'gutenberg' prefix. ([65260](https://github.com/WordPress/gutenberg/pull/65260)) +- Global Styles: Update REST controller override method and backport changes from Core. ([65259](https://github.com/WordPress/gutenberg/pull/65259)) +- Patterns: Remove unused method returned from 'mapSelect'. ([65073](https://github.com/WordPress/gutenberg/pull/65073)) +- Embed: Convert EmbedPreview component to functional component. ([51325](https://github.com/WordPress/gutenberg/pull/51325)) + +#### Components +- BoxControl: Fix critical error when null value is passed. ([65287](https://github.com/WordPress/gutenberg/pull/65287)) +- Composite: + - Deprecate legacy, unstable version. ([63572](https://github.com/WordPress/gutenberg/pull/63572)) + - Remove store prop and useCompositeStore hook. ([64723](https://github.com/WordPress/gutenberg/pull/64723)) + - Stabilize APIs. ([63569](https://github.com/WordPress/gutenberg/pull/63569)) +- `@wordpress/components`: Add local copy of `use-lilius`. ([65097](https://github.com/WordPress/gutenberg/pull/65097)) + +#### Block bindings +- Always prioritize using context in post meta source logic. ([65449](https://github.com/WordPress/gutenberg/pull/65449)) +- Improve getRegisteredPostMeta resolver. ([65450](https://github.com/WordPress/gutenberg/pull/65450)) +- Remove extra filtering of empty sources. ([65447](https://github.com/WordPress/gutenberg/pull/65447)) + +#### Block Editor +- Remove the 'PrivateInserter' component. ([65111](https://github.com/WordPress/gutenberg/pull/65111)) +- Use the tooltip from a button in 'ButtonBlockAppender'. ([65113](https://github.com/WordPress/gutenberg/pull/65113)) +- Remove unused css selectors. ([65276](https://github.com/WordPress/gutenberg/pull/65276)) + +### Tools + +- Scripts: Update stylelint dependency and the default configuration. ([64828](https://github.com/WordPress/gutenberg/pull/64828)) +- Styleling config: Fix stylelint configuration missing files for npm. ([65313](https://github.com/WordPress/gutenberg/pull/65313)) + +#### Build Tooling +- Build Plugin: Simplify and improve zip contents. ([65232](https://github.com/WordPress/gutenberg/pull/65232)) +- Build zip artifact on release and wp production branches. ([65471](https://github.com/WordPress/gutenberg/pull/65471)) +- Build: Include Core blocks' `render` and `variations` files. ([63311](https://github.com/WordPress/gutenberg/pull/63311)) +- Script Modules + - Prepare build for more script modules. ([65064](https://github.com/WordPress/gutenberg/pull/65064)) + - Remove babel from script-modules build. ([65279](https://github.com/WordPress/gutenberg/pull/65279)) + - Remove es-module shims and importmap-polyfill. ([65210](https://github.com/WordPress/gutenberg/pull/65210)) +- Correctly generate PHP files for server-side rendering of blocks on Windows OS. ([65248](https://github.com/WordPress/gutenberg/pull/65248)) +- Packages: Only add polyfills where needed. ([65292](https://github.com/WordPress/gutenberg/pull/65292)) +- Switch from UglifyJS to Terser to build the polyfill script. ([65278](https://github.com/WordPress/gutenberg/pull/65278)) + +#### Testing +- Unit tests: Mock matchMedia to enforce prefers-reduce-motion. ([65438](https://github.com/WordPress/gutenberg/pull/65438)) +- Upgrade Playwright to v1.47. ([65156](https://github.com/WordPress/gutenberg/pull/65156)) + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @AKSHAT2802: Add __next40pxDefaultSize for files in editor 4. ([65140](https://github.com/WordPress/gutenberg/pull/65140)) +- @devansh016: Automatically add tel to phone number when linking URL. ([64865](https://github.com/WordPress/gutenberg/pull/64865)) +- @dhruvang21: Fix: Button Replace remaining 40px default size violations [Edit widgets]. ([65367](https://github.com/WordPress/gutenberg/pull/65367)) +- @farid-hadi: Docs: Fix minor typos in Build your first block tutorial. ([64961](https://github.com/WordPress/gutenberg/pull/64961)) +- @greenworld: Fix typo in Slot Fills documentation. ([65275](https://github.com/WordPress/gutenberg/pull/65275)) +- @louwie17: Convert EmbedPreview component to functional component. ([51325](https://github.com/WordPress/gutenberg/pull/51325)) +- @rahulharpal1603: URLInput: Replace input with InputControl. ([65158](https://github.com/WordPress/gutenberg/pull/65158)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @afercia @AKSHAT2802 @Aljullu @andrewserong @carolinan @cbravobernal @ciampo @colorful-tones @creativecoder @DaniGuardiola @DAreRodz @devansh016 @dhruvang21 @ellatrix @farid-hadi @getdave @gigitux @greenworld @gziolo @hbhalodia @jameskoster @jasmussen @javierarce @jeryj @jorgefilipecosta @jsnajdr @kevin940726 @louwie17 @madhusudhand @MaggieCabrera @Mamaduka @mikeybinns @mirka @ntsekouras @oandregal @ockham @peterwilsoncc @rahulharpal1603 @ramonjd @richtabor @rohitmathur-7 @SantosGuillamot @scruffian @sgomes @sirreal @stokesman @swissspidy @t-hamano @talldan @vipul0425 @zaguiini + + = 19.2.0 = ## Changelog From 958b4c76476e967b0269abb9322c30f3622025dd Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 19 Sep 2024 02:29:11 +0000 Subject: [PATCH 0865/1908] Update changelog files --- packages/a11y/CHANGELOG.md | 2 ++ packages/a11y/package.json | 2 +- packages/annotations/CHANGELOG.md | 2 ++ packages/annotations/package.json | 2 +- packages/api-fetch/CHANGELOG.md | 2 ++ packages/api-fetch/package.json | 2 +- packages/autop/CHANGELOG.md | 2 ++ packages/autop/package.json | 2 +- packages/babel-plugin-import-jsx-pragma/CHANGELOG.md | 2 ++ packages/babel-plugin-import-jsx-pragma/package.json | 2 +- packages/babel-plugin-makepot/CHANGELOG.md | 2 ++ packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/package.json | 2 +- packages/base-styles/CHANGELOG.md | 2 ++ packages/base-styles/package.json | 2 +- packages/blob/CHANGELOG.md | 2 ++ packages/blob/package.json | 2 +- packages/block-directory/CHANGELOG.md | 2 ++ packages/block-directory/package.json | 2 +- packages/block-editor/CHANGELOG.md | 2 ++ packages/block-editor/package.json | 2 +- packages/block-library/CHANGELOG.md | 2 ++ packages/block-library/package.json | 2 +- packages/block-serialization-default-parser/CHANGELOG.md | 2 ++ packages/block-serialization-default-parser/package.json | 2 +- packages/block-serialization-spec-parser/CHANGELOG.md | 2 ++ packages/block-serialization-spec-parser/package.json | 2 +- packages/blocks/CHANGELOG.md | 2 ++ packages/blocks/package.json | 2 +- packages/browserslist-config/CHANGELOG.md | 2 ++ packages/browserslist-config/package.json | 2 +- packages/commands/CHANGELOG.md | 2 ++ packages/commands/package.json | 2 +- packages/components/CHANGELOG.md | 2 ++ packages/components/package.json | 2 +- packages/compose/CHANGELOG.md | 2 ++ packages/compose/package.json | 2 +- packages/core-commands/CHANGELOG.md | 2 ++ packages/core-commands/package.json | 2 +- packages/core-data/CHANGELOG.md | 2 ++ packages/core-data/package.json | 2 +- packages/create-block-interactive-template/CHANGELOG.md | 2 ++ packages/create-block-interactive-template/package.json | 2 +- packages/create-block-tutorial-template/CHANGELOG.md | 2 ++ packages/create-block-tutorial-template/package.json | 2 +- packages/create-block/CHANGELOG.md | 2 ++ packages/create-block/package.json | 2 +- packages/customize-widgets/CHANGELOG.md | 2 ++ packages/customize-widgets/package.json | 2 +- packages/data-controls/CHANGELOG.md | 2 ++ packages/data-controls/package.json | 2 +- packages/data/CHANGELOG.md | 2 ++ packages/data/package.json | 2 +- packages/dataviews/CHANGELOG.md | 2 ++ packages/dataviews/package.json | 2 +- packages/date/CHANGELOG.md | 2 ++ packages/date/package.json | 2 +- packages/dependency-extraction-webpack-plugin/CHANGELOG.md | 2 ++ packages/dependency-extraction-webpack-plugin/package.json | 2 +- packages/deprecated/CHANGELOG.md | 2 ++ packages/deprecated/package.json | 2 +- packages/docgen/CHANGELOG.md | 2 ++ packages/docgen/package.json | 2 +- packages/dom-ready/CHANGELOG.md | 2 ++ packages/dom-ready/package.json | 2 +- packages/dom/CHANGELOG.md | 2 ++ packages/dom/package.json | 2 +- packages/e2e-test-utils-playwright/CHANGELOG.md | 2 ++ packages/e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/CHANGELOG.md | 2 ++ packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/CHANGELOG.md | 2 ++ packages/e2e-tests/package.json | 2 +- packages/edit-post/CHANGELOG.md | 2 ++ packages/edit-post/package.json | 2 +- packages/edit-site/CHANGELOG.md | 2 ++ packages/edit-site/package.json | 2 +- packages/edit-widgets/CHANGELOG.md | 2 ++ packages/edit-widgets/package.json | 2 +- packages/editor/CHANGELOG.md | 2 ++ packages/editor/package.json | 2 +- packages/element/CHANGELOG.md | 2 ++ packages/element/package.json | 2 +- packages/env/CHANGELOG.md | 2 ++ packages/env/package.json | 2 +- packages/escape-html/CHANGELOG.md | 2 ++ packages/escape-html/package.json | 2 +- packages/eslint-plugin/CHANGELOG.md | 2 ++ packages/eslint-plugin/package.json | 2 +- packages/format-library/CHANGELOG.md | 2 ++ packages/format-library/package.json | 2 +- packages/hooks/CHANGELOG.md | 2 ++ packages/hooks/package.json | 2 +- packages/html-entities/CHANGELOG.md | 2 ++ packages/html-entities/package.json | 2 +- packages/i18n/CHANGELOG.md | 2 ++ packages/i18n/package.json | 2 +- packages/icons/CHANGELOG.md | 2 ++ packages/icons/package.json | 2 +- packages/interactivity-router/CHANGELOG.md | 2 ++ packages/interactivity-router/package.json | 2 +- packages/interactivity/CHANGELOG.md | 2 ++ packages/interactivity/package.json | 2 +- packages/interface/CHANGELOG.md | 2 ++ packages/interface/package.json | 2 +- packages/is-shallow-equal/CHANGELOG.md | 2 ++ packages/is-shallow-equal/package.json | 2 +- packages/jest-console/CHANGELOG.md | 2 ++ packages/jest-console/package.json | 2 +- packages/jest-preset-default/CHANGELOG.md | 2 ++ packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/CHANGELOG.md | 2 ++ packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/CHANGELOG.md | 2 ++ packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/CHANGELOG.md | 2 ++ packages/keycodes/package.json | 2 +- packages/lazy-import/CHANGELOG.md | 2 ++ packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/CHANGELOG.md | 2 ++ packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/CHANGELOG.md | 2 ++ packages/media-utils/package.json | 2 +- packages/notices/CHANGELOG.md | 2 ++ packages/notices/package.json | 2 +- packages/npm-package-json-lint-config/CHANGELOG.md | 2 ++ packages/npm-package-json-lint-config/package.json | 2 +- packages/nux/CHANGELOG.md | 2 ++ packages/nux/package.json | 2 +- packages/patterns/CHANGELOG.md | 2 ++ packages/patterns/package.json | 2 +- packages/plugins/CHANGELOG.md | 2 ++ packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/CHANGELOG.md | 2 ++ packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/CHANGELOG.md | 2 ++ packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/CHANGELOG.md | 2 ++ packages/preferences-persistence/package.json | 2 +- packages/preferences/CHANGELOG.md | 2 ++ packages/preferences/package.json | 2 +- packages/prettier-config/CHANGELOG.md | 2 ++ packages/prettier-config/package.json | 2 +- packages/primitives/CHANGELOG.md | 2 ++ packages/primitives/package.json | 2 +- packages/priority-queue/CHANGELOG.md | 2 ++ packages/priority-queue/package.json | 2 +- packages/private-apis/CHANGELOG.md | 2 ++ packages/private-apis/package.json | 2 +- packages/project-management-automation/CHANGELOG.md | 2 ++ packages/project-management-automation/package.json | 2 +- packages/react-i18n/CHANGELOG.md | 2 ++ packages/react-i18n/package.json | 2 +- packages/readable-js-assets-webpack-plugin/CHANGELOG.md | 2 ++ packages/readable-js-assets-webpack-plugin/package.json | 2 +- packages/redux-routine/CHANGELOG.md | 2 ++ packages/redux-routine/package.json | 2 +- packages/reusable-blocks/CHANGELOG.md | 2 ++ packages/reusable-blocks/package.json | 2 +- packages/rich-text/CHANGELOG.md | 2 ++ packages/rich-text/package.json | 2 +- packages/router/CHANGELOG.md | 2 ++ packages/router/package.json | 2 +- packages/scripts/CHANGELOG.md | 2 ++ packages/scripts/package.json | 2 +- packages/server-side-render/CHANGELOG.md | 2 ++ packages/server-side-render/package.json | 2 +- packages/shortcode/CHANGELOG.md | 2 ++ packages/shortcode/package.json | 2 +- packages/style-engine/CHANGELOG.md | 2 ++ packages/style-engine/package.json | 2 +- packages/stylelint-config/CHANGELOG.md | 2 ++ packages/stylelint-config/package.json | 2 +- packages/sync/CHANGELOG.md | 2 ++ packages/sync/package.json | 2 +- packages/token-list/CHANGELOG.md | 2 ++ packages/token-list/package.json | 2 +- packages/undo-manager/CHANGELOG.md | 2 ++ packages/undo-manager/package.json | 2 +- packages/url/CHANGELOG.md | 2 ++ packages/url/package.json | 2 +- packages/viewport/CHANGELOG.md | 2 ++ packages/viewport/package.json | 2 +- packages/warning/CHANGELOG.md | 2 ++ packages/warning/package.json | 2 +- packages/widgets/CHANGELOG.md | 2 ++ packages/widgets/package.json | 2 +- packages/wordcount/CHANGELOG.md | 2 ++ packages/wordcount/package.json | 2 +- 189 files changed, 283 insertions(+), 95 deletions(-) diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index 36973cce020f33..626488313977d1 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 327d6b9ff07167..b1faa8dc0b2603 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/CHANGELOG.md b/packages/annotations/CHANGELOG.md index 6211cf30688e5c..7ac3e50c3fd8b6 100644 --- a/packages/annotations/CHANGELOG.md +++ b/packages/annotations/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.8.0 (2024-09-19) + ## 3.7.0 (2024-09-05) ## 3.6.0 (2024-08-21) diff --git a/packages/annotations/package.json b/packages/annotations/package.json index c189dcc11fd09f..3d3f60867cc92c 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.7.0", + "version": "3.8.0-prerelease", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/CHANGELOG.md b/packages/api-fetch/CHANGELOG.md index 01b37d4e14a7d1..7c333170b6cc11 100644 --- a/packages/api-fetch/CHANGELOG.md +++ b/packages/api-fetch/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.8.0 (2024-09-19) + ## 7.7.0 (2024-09-05) ## 7.6.0 (2024-08-21) diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 76d797f4ddfa57..96657c57402c85 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.7.0", + "version": "7.8.0-prerelease", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/CHANGELOG.md b/packages/autop/CHANGELOG.md index ed19f1ceafbc58..4bb494dcfff5c0 100644 --- a/packages/autop/CHANGELOG.md +++ b/packages/autop/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/autop/package.json b/packages/autop/package.json index 4e1cf577ebd09c..ca0fd3f00d0623 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md index c916b788243a06..5a68cf8eb40400 100644 --- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md +++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index 1af6bdf93cb044..788cebe10ddf06 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/CHANGELOG.md b/packages/babel-plugin-makepot/CHANGELOG.md index e7345f314d5788..d878e1fb6b020c 100644 --- a/packages/babel-plugin-makepot/CHANGELOG.md +++ b/packages/babel-plugin-makepot/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.8.0 (2024-09-19) + ## 6.7.0 (2024-09-05) ## 6.6.0 (2024-08-21) diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index a7c18d891538d1..1e3e950fb9fc73 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.7.0", + "version": "6.8.0-prerelease", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index be5b3786346eb2..5ee37cfb105c24 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.7.0", + "version": "8.8.0-prerelease", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/CHANGELOG.md b/packages/base-styles/CHANGELOG.md index cad2f94c98da7b..ea6b765aea3f11 100644 --- a/packages/base-styles/CHANGELOG.md +++ b/packages/base-styles/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index 6839a8081e04a8..c6a873e94191a9 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md index f95598025a8b68..c13c6e6faf6ac8 100644 --- a/packages/blob/CHANGELOG.md +++ b/packages/blob/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/blob/package.json b/packages/blob/package.json index 3dea70c9771976..cffd5985680eca 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/CHANGELOG.md b/packages/block-directory/CHANGELOG.md index 70914f293ca998..8c25431f1b5b5e 100644 --- a/packages/block-directory/CHANGELOG.md +++ b/packages/block-directory/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 39f239edfcb44a..fdc69ffefcebbf 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index da44ebc4149f58..db61ff05e3c1ad 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.3.0 (2024-09-19) + ## 14.2.0 (2024-09-05) ## 14.1.0 (2024-08-21) diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index d3064c78dbe658..fb0f3423b483ff 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.2.0", + "version": "14.3.0-prerelease", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index 4ee3ebc7564b53..08accf8c36d9e5 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.8.0 (2024-09-19) + ## 9.7.0 (2024-09-05) ## 9.6.0 (2024-08-21) diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 1353ef24c77d89..afe4dd960f7c6c 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.7.0", + "version": "9.8.0-prerelease", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/CHANGELOG.md b/packages/block-serialization-default-parser/CHANGELOG.md index 9dd0bd70309764..47e1db147942ff 100644 --- a/packages/block-serialization-default-parser/CHANGELOG.md +++ b/packages/block-serialization-default-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index cac606bd7bd1ee..b4317c163474bc 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/CHANGELOG.md b/packages/block-serialization-spec-parser/CHANGELOG.md index b8d02b5348e1b6..173ce09db51e2b 100644 --- a/packages/block-serialization-spec-parser/CHANGELOG.md +++ b/packages/block-serialization-spec-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index d48d1846e79095..0640578fb5cc4b 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 0755d5170d1b32..838983c17233ea 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 13.8.0 (2024-09-19) + ## 13.7.0 (2024-09-05) ## 13.6.0 (2024-08-21) diff --git a/packages/blocks/package.json b/packages/blocks/package.json index f371ecc087af41..45b31db7cea663 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.7.0", + "version": "13.8.0-prerelease", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/CHANGELOG.md b/packages/browserslist-config/CHANGELOG.md index b8ee58633b7ef2..cbe4763ea32706 100644 --- a/packages/browserslist-config/CHANGELOG.md +++ b/packages/browserslist-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.8.0 (2024-09-19) + ## 6.7.0 (2024-09-05) ## 6.6.0 (2024-08-21) diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index c51d7318170c4e..26d5a6820b7284 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.7.0", + "version": "6.8.0-prerelease", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/CHANGELOG.md b/packages/commands/CHANGELOG.md index bde7767a0f61f6..b8f45c79470040 100644 --- a/packages/commands/CHANGELOG.md +++ b/packages/commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.8.0 (2024-09-19) + ## 1.7.0 (2024-09-05) ## 1.6.0 (2024-08-21) diff --git a/packages/commands/package.json b/packages/commands/package.json index 88b9b86f4b3aeb..ea3139bc0d0bc7 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.7.0", + "version": "1.8.0-prerelease", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 4dd18914a7acb5..d7e8b191229893 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 28.8.0 (2024-09-19) + ### Bug Fixes - `Tabs`: restore vertical indicator ([#65385](https://github.com/WordPress/gutenberg/pull/65385)). diff --git a/packages/components/package.json b/packages/components/package.json index 8337d6dd8857f4..24576297776395 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.7.0", + "version": "28.8.0-prerelease", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index cc0d7ef333f0d6..18c21a65b9b124 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.8.0 (2024-09-19) + ### New Features - `useEvent`: a new utility that creates a stable callback function that has access to the latest state and can be used within event handlers and effect callbacks ([#64943](https://github.com/WordPress/gutenberg/pull/64943)). diff --git a/packages/compose/package.json b/packages/compose/package.json index 4b68841d1777e6..30f9eacbea191a 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.7.0", + "version": "7.8.0-prerelease", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/CHANGELOG.md b/packages/core-commands/CHANGELOG.md index 02871d4f31e135..2d8d93373f4c5e 100644 --- a/packages/core-commands/CHANGELOG.md +++ b/packages/core-commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.8.0 (2024-09-19) + ## 1.7.0 (2024-09-05) ## 1.6.0 (2024-08-21) diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index bae1e4c211cf0b..944feaa3425fa7 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.7.0", + "version": "1.8.0-prerelease", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md index 6286a55291a54f..fcedd5d1100661 100644 --- a/packages/core-data/CHANGELOG.md +++ b/packages/core-data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.8.0 (2024-09-19) + ## 7.7.0 (2024-09-05) ## 7.6.0 (2024-08-21) diff --git a/packages/core-data/package.json b/packages/core-data/package.json index ddb2d2ef091778..ae1a5a5928d244 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.7.0", + "version": "7.8.0-prerelease", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/CHANGELOG.md b/packages/create-block-interactive-template/CHANGELOG.md index c044dfff15e3ac..348c8466836c69 100644 --- a/packages/create-block-interactive-template/CHANGELOG.md +++ b/packages/create-block-interactive-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.8.0 (2024-09-19) + ## 2.7.0 (2024-09-05) ### Enhancements diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index 667d3998ba820d..2e8b50d8521436 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.7.0", + "version": "2.8.0-prerelease", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/CHANGELOG.md b/packages/create-block-tutorial-template/CHANGELOG.md index 0fe0f748b8804d..e93bc0270ba953 100644 --- a/packages/create-block-tutorial-template/CHANGELOG.md +++ b/packages/create-block-tutorial-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ### Enhancements diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index 64a8a90bc167c0..a55a328c51842f 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index 99e7b1fd37a33a..d3a8c1c75dd3fb 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.51.0 (2024-09-19) + ## 4.50.0 (2024-09-05) ### Enhancements diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 2103a85c5894f2..ffed77a5db0f0d 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.50.0", + "version": "4.51.0-prerelease", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/CHANGELOG.md b/packages/customize-widgets/CHANGELOG.md index 4e0d5a37553577..061b656c892c79 100644 --- a/packages/customize-widgets/CHANGELOG.md +++ b/packages/customize-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index a8b50cf9cb318c..35a3c438f2886b 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/CHANGELOG.md b/packages/data-controls/CHANGELOG.md index e6af7fdcb6e240..3d16450a7825b4 100644 --- a/packages/data-controls/CHANGELOG.md +++ b/packages/data-controls/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index e97e59b74700cd..38c74b42e9f8d5 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index 4ba90611c2a787..f9ebf9eb17a68c 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.8.0 (2024-09-19) + ## 10.7.0 (2024-09-05) ## 10.6.0 (2024-08-21) diff --git a/packages/data/package.json b/packages/data/package.json index 84ad7a7973bc49..0cc2495a5dc743 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.7.0", + "version": "10.8.0-prerelease", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 1e323714c4d5f7..6ce337d726e083 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 (2024-09-19) + ## 4.3.0 (2024-09-05) ## 4.2.0 (2024-08-21) diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index e327a217435c52..a9e5f5be7ebf7f 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.3.0", + "version": "4.4.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md index e19aa08ab6fe50..8c28ff83d53ed8 100644 --- a/packages/date/CHANGELOG.md +++ b/packages/date/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/date/package.json b/packages/date/package.json index 488db71cfd693a..51e1da0e94229a 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index 1da5f074301fd6..85498d539317f3 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.8.0 (2024-09-19) + ## 6.7.0 (2024-09-05) ## 6.6.0 (2024-08-21) diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index f720a1df826e80..237e0d1c475cf6 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.7.0", + "version": "6.8.0-prerelease", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/CHANGELOG.md b/packages/deprecated/CHANGELOG.md index 673567a2a3e492..945bf44ad6a653 100644 --- a/packages/deprecated/CHANGELOG.md +++ b/packages/deprecated/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index ed2f9434539efe..c892ed6e269d49 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/CHANGELOG.md b/packages/docgen/CHANGELOG.md index 3aefc7cae99ae2..3e966fc4518d75 100644 --- a/packages/docgen/CHANGELOG.md +++ b/packages/docgen/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.8.0 (2024-09-19) + ## 2.7.0 (2024-09-05) ## 2.6.0 (2024-08-21) diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 38a228d50a8e0f..43a582b0819ef1 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.7.0", + "version": "2.8.0-prerelease", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/CHANGELOG.md b/packages/dom-ready/CHANGELOG.md index f3290182dff5c2..265e7b5947061a 100644 --- a/packages/dom-ready/CHANGELOG.md +++ b/packages/dom-ready/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 89acde8f2b1245..d07d86d1d5e068 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/CHANGELOG.md b/packages/dom/CHANGELOG.md index 1857e3d51cb70f..77f85a59cada84 100644 --- a/packages/dom/CHANGELOG.md +++ b/packages/dom/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/dom/package.json b/packages/dom/package.json index dd05677fcb9303..c28e756972b356 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/CHANGELOG.md b/packages/e2e-test-utils-playwright/CHANGELOG.md index eb3cbd95fe3ad0..b53821f46eefef 100644 --- a/packages/e2e-test-utils-playwright/CHANGELOG.md +++ b/packages/e2e-test-utils-playwright/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.8.0 (2024-09-19) + ## 1.7.0 (2024-09-05) ## 1.6.0 (2024-08-21) diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 1bb80bc4cc7643..da1df3d4b21443 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.7.0", + "version": "1.8.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index b22c016a799bc5..98c17f5b6ecb01 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 11.8.0 (2024-09-19) + ## 11.7.0 (2024-09-05) ## 11.6.0 (2024-08-21) diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index 02cee410f33d66..cfa2c8e7120da8 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.7.0", + "version": "11.8.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md index a7ba03f05f4668..3fe696deaabb53 100644 --- a/packages/e2e-tests/CHANGELOG.md +++ b/packages/e2e-tests/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.8.0 (2024-09-19) + ## 8.7.0 (2024-09-05) ## 8.6.0 (2024-08-21) diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 81e7fa1802c65b..f4960e156bd8ff 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.7.0", + "version": "8.8.0-prerelease", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index cd4b4a36295f07..3eb52f26e65012 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.8.0 (2024-09-19) + ## 8.7.0 (2024-09-05) ## 8.6.0 (2024-08-21) diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 0d8e0b28f7c7c5..55abf9cb8d235a 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.7.0", + "version": "8.8.0-prerelease", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/CHANGELOG.md b/packages/edit-site/CHANGELOG.md index 025d2389e4b01d..b14fb6dcd6d3e8 100644 --- a/packages/edit-site/CHANGELOG.md +++ b/packages/edit-site/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.8.0 (2024-09-19) + ## 6.7.0 (2024-09-05) ## 6.6.0 (2024-08-21) diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 43bcf68aa68e68..2284aae3a0e23c 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.7.0", + "version": "6.8.0-prerelease", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/CHANGELOG.md b/packages/edit-widgets/CHANGELOG.md index f1cbcef0667d7c..6115fc42560f82 100644 --- a/packages/edit-widgets/CHANGELOG.md +++ b/packages/edit-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.8.0 (2024-09-19) + ## 6.7.0 (2024-09-05) ## 6.6.0 (2024-08-21) diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index d24857f0f8a0ce..d5f58474f5c162 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.7.0", + "version": "6.8.0-prerelease", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index b380c2fd296d55..6f31c1735021f6 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.8.0 (2024-09-19) + ## 14.7.0 (2024-09-05) ## 14.6.0 (2024-08-21) diff --git a/packages/editor/package.json b/packages/editor/package.json index 2e01aff3a0aa5f..c2b35baee86d30 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.7.0", + "version": "14.8.0-prerelease", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/CHANGELOG.md b/packages/element/CHANGELOG.md index ccfa6a6021d71f..ee63e4b5e70fa8 100644 --- a/packages/element/CHANGELOG.md +++ b/packages/element/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.8.0 (2024-09-19) + ## 6.7.0 (2024-09-05) ## 6.6.0 (2024-08-21) diff --git a/packages/element/package.json b/packages/element/package.json index d6062abe6ecf61..32cdfd3eb1b248 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.7.0", + "version": "6.8.0-prerelease", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md index b3dcf350596a0f..0b32fd808d9603 100644 --- a/packages/env/CHANGELOG.md +++ b/packages/env/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.8.0 (2024-09-19) + ## 10.7.0 (2024-09-05) ## 10.6.0 (2024-08-21) diff --git a/packages/env/package.json b/packages/env/package.json index 7f3b15b1e15622..c25fa43d5f3926 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.7.0", + "version": "10.8.0-prerelease", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/CHANGELOG.md b/packages/escape-html/CHANGELOG.md index 490cbdb184f5b1..c13edebda4480a 100644 --- a/packages/escape-html/CHANGELOG.md +++ b/packages/escape-html/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.8.0 (2024-09-19) + ## 3.7.0 (2024-09-05) ## 3.6.0 (2024-08-21) diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 8dd1a66cf2d5e9..4f577fe4dbdd82 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.7.0", + "version": "3.8.0-prerelease", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 14d44d21acda9f..725872f8bf1011 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 21.1.0 (2024-09-19) + ## 21.0.0 (2024-09-05) ### Breaking Changes diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 73996275c9154f..64203cbf4ced85 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "21.0.0", + "version": "21.1.0-prerelease", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/CHANGELOG.md b/packages/format-library/CHANGELOG.md index c003ac587fcdfa..11a32094cffeab 100644 --- a/packages/format-library/CHANGELOG.md +++ b/packages/format-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/format-library/package.json b/packages/format-library/package.json index 780f513bdb0374..a12fa54977a061 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/CHANGELOG.md b/packages/hooks/CHANGELOG.md index de9e11c38fe905..0e162b64513d26 100644 --- a/packages/hooks/CHANGELOG.md +++ b/packages/hooks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 51074af0d239b0..1e148a6dd88bb6 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/CHANGELOG.md b/packages/html-entities/CHANGELOG.md index 6887a70b391f98..e49251a8653624 100644 --- a/packages/html-entities/CHANGELOG.md +++ b/packages/html-entities/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 30e3c1728307d7..b13077930659be 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index d2bf7ad7ea7eb3..928a0d6d0ef74b 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/i18n/package.json b/packages/i18n/package.json index fb3c488c1a4dea..4a1c56ed38d38c 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index a59229e1b0eba7..be047e2181d4a5 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.8.0 (2024-09-19) + ### New Features - Add new `bell` and `bell-unread` icons. diff --git a/packages/icons/package.json b/packages/icons/package.json index ab23fef8eff667..672a0382e96f84 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.7.0", + "version": "10.8.0-prerelease", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/CHANGELOG.md b/packages/interactivity-router/CHANGELOG.md index 00c47f3ed074b6..1f8e91dec05474 100644 --- a/packages/interactivity-router/CHANGELOG.md +++ b/packages/interactivity-router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.8.0 (2024-09-19) + ## 2.7.0 (2024-09-05) ## 2.6.0 (2024-08-21) diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 7282ee0b00f9c9..4b76c4492e2dc1 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.7.0", + "version": "2.8.0-prerelease", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 6e8fbc6b74e08d..6989bcdc0c802c 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.8.0 (2024-09-19) + ### Enhancements - Refactor internal context proxies implementation ([#64713](https://github.com/WordPress/gutenberg/pull/64713)). diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 6be9f3c4a0d7d8..7b7ef3fa5f9de9 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.7.0", + "version": "6.8.0-prerelease", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index 64f8c370bb6ece..f5e0d5e74762af 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.8.0 (2024-09-19) + ## 6.7.0 (2024-09-05) ## 6.6.0 (2024-08-21) diff --git a/packages/interface/package.json b/packages/interface/package.json index d15d648eaef446..be14bb394694ca 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "6.7.0", + "version": "6.8.0-prerelease", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/CHANGELOG.md b/packages/is-shallow-equal/CHANGELOG.md index 81f2c4b164a3ab..ef424aaeebf220 100644 --- a/packages/is-shallow-equal/CHANGELOG.md +++ b/packages/is-shallow-equal/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 553c3182bb5668..72ee0392f9a2ef 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/CHANGELOG.md b/packages/jest-console/CHANGELOG.md index 7f7f80b815a850..2ed1dc24299f45 100644 --- a/packages/jest-console/CHANGELOG.md +++ b/packages/jest-console/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.8.0 (2024-09-19) + ## 8.7.0 (2024-09-05) ## 8.6.0 (2024-08-21) diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 4381a0f287235f..6c93d48d31877e 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.7.0", + "version": "8.8.0-prerelease", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md index e48d25dc1e6424..a3ecded683cd17 100644 --- a/packages/jest-preset-default/CHANGELOG.md +++ b/packages/jest-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 12.8.0 (2024-09-19) + ## 12.7.0 (2024-09-05) ## 12.6.0 (2024-08-21) diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 27638c711d4d1e..f5a853ff924d98 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.7.0", + "version": "12.8.0-prerelease", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/CHANGELOG.md b/packages/jest-puppeteer-axe/CHANGELOG.md index 572b4aa137a141..3e61ea09412d63 100644 --- a/packages/jest-puppeteer-axe/CHANGELOG.md +++ b/packages/jest-puppeteer-axe/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.8.0 (2024-09-19) + ## 7.7.0 (2024-09-05) ## 7.6.0 (2024-08-21) diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index b8ccbfcd36beff..2bdefd24ce73f3 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.7.0", + "version": "7.8.0-prerelease", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/CHANGELOG.md b/packages/keyboard-shortcuts/CHANGELOG.md index fe3506ea4a5f19..356e850692af4d 100644 --- a/packages/keyboard-shortcuts/CHANGELOG.md +++ b/packages/keyboard-shortcuts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index dd560424b66ff7..d9e168b2310efb 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/CHANGELOG.md b/packages/keycodes/CHANGELOG.md index 51050728f2f5a3..a578adb34bd3d3 100644 --- a/packages/keycodes/CHANGELOG.md +++ b/packages/keycodes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 5d8ec0545d7e3f..d8702f985b1b26 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/CHANGELOG.md b/packages/lazy-import/CHANGELOG.md index daea6da3404d3f..6853a036fdaa50 100644 --- a/packages/lazy-import/CHANGELOG.md +++ b/packages/lazy-import/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.8.0 (2024-09-19) + ## 2.7.0 (2024-09-05) ## 2.6.0 (2024-08-21) diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index 62aab79635e9c4..00bad5d72d9e86 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.7.0", + "version": "2.8.0-prerelease", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/CHANGELOG.md b/packages/list-reusable-blocks/CHANGELOG.md index 9f62523fd94e11..852f30a2999175 100644 --- a/packages/list-reusable-blocks/CHANGELOG.md +++ b/packages/list-reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 839532327faa24..11e0496cfeade9 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/CHANGELOG.md b/packages/media-utils/CHANGELOG.md index 26282b6b2bda21..a25bdf05596f86 100644 --- a/packages/media-utils/CHANGELOG.md +++ b/packages/media-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ### New Features - Rewrite in TypeScript, exporting all the individual utility functions. diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 1cfe019e89d0a6..8a7c0e9e994b52 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/CHANGELOG.md b/packages/notices/CHANGELOG.md index f32648df69728e..dbff0c69b7449d 100644 --- a/packages/notices/CHANGELOG.md +++ b/packages/notices/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/notices/package.json b/packages/notices/package.json index a4e2c5ea8d98c1..f0cd3743007c4b 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/CHANGELOG.md b/packages/npm-package-json-lint-config/CHANGELOG.md index 24dfd09fff55a2..ecf89f4df64717 100644 --- a/packages/npm-package-json-lint-config/CHANGELOG.md +++ b/packages/npm-package-json-lint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index ad88e3fd442a1d..6c662b9030e79e 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/CHANGELOG.md b/packages/nux/CHANGELOG.md index 85feaa73dbc239..51a49b1bf9314c 100644 --- a/packages/nux/CHANGELOG.md +++ b/packages/nux/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.8.0 (2024-09-19) + ## 9.7.0 (2024-09-05) ## 9.6.0 (2024-08-21) diff --git a/packages/nux/package.json b/packages/nux/package.json index 7a8e565d163aa2..650206a94921f7 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.7.0", + "version": "9.8.0-prerelease", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/CHANGELOG.md b/packages/patterns/CHANGELOG.md index eaef3c431d6687..1579dd646228ff 100644 --- a/packages/patterns/CHANGELOG.md +++ b/packages/patterns/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.8.0 (2024-09-19) + ## 2.7.0 (2024-09-05) ## 2.6.0 (2024-08-21) diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 6d67aa7ef3ac9e..f90dae85a8dbce 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.7.0", + "version": "2.8.0-prerelease", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/CHANGELOG.md b/packages/plugins/CHANGELOG.md index c2c010c8881150..18d5e1a38567dc 100644 --- a/packages/plugins/CHANGELOG.md +++ b/packages/plugins/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.8.0 (2024-09-19) + ## 7.7.0 (2024-09-05) ## 7.6.0 (2024-08-21) diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 9cc58fc5096be2..b4dd77907862bd 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.7.0", + "version": "7.8.0-prerelease", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/CHANGELOG.md b/packages/postcss-plugins-preset/CHANGELOG.md index b16c9284417a31..e4441308f0fe40 100644 --- a/packages/postcss-plugins-preset/CHANGELOG.md +++ b/packages/postcss-plugins-preset/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index d012dde494958e..74ff1d8ba0fba3 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/CHANGELOG.md b/packages/postcss-themes/CHANGELOG.md index 774c2edf77e0c3..c7d61b14eadf18 100644 --- a/packages/postcss-themes/CHANGELOG.md +++ b/packages/postcss-themes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.8.0 (2024-09-19) + ## 6.7.0 (2024-09-05) ## 6.6.0 (2024-08-21) diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index 29e617382161ed..ea91b90bf3c4da 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.7.0", + "version": "6.8.0-prerelease", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/CHANGELOG.md b/packages/preferences-persistence/CHANGELOG.md index a4a3081901bf52..79a755f40bfd5b 100644 --- a/packages/preferences-persistence/CHANGELOG.md +++ b/packages/preferences-persistence/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.8.0 (2024-09-19) + ## 2.7.0 (2024-09-05) ## 2.6.0 (2024-08-21) diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index a318979abed2a1..f22e18b5742a6d 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.7.0", + "version": "2.8.0-prerelease", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/CHANGELOG.md b/packages/preferences/CHANGELOG.md index 7d87ce93868757..840c476e8ece81 100644 --- a/packages/preferences/CHANGELOG.md +++ b/packages/preferences/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/preferences/package.json b/packages/preferences/package.json index 5b12d274af30ae..045170b81a9f63 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/CHANGELOG.md b/packages/prettier-config/CHANGELOG.md index e0e01d2b7f3ac8..28d178a87f980b 100644 --- a/packages/prettier-config/CHANGELOG.md +++ b/packages/prettier-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index f6c7797f2b6e7f..fc074bec70526b 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/CHANGELOG.md b/packages/primitives/CHANGELOG.md index 48db582f65e109..f0bd389bb08b73 100644 --- a/packages/primitives/CHANGELOG.md +++ b/packages/primitives/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 8296c6348e9bef..74795ab64ae5e5 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/CHANGELOG.md b/packages/priority-queue/CHANGELOG.md index a7f1257b8f6b49..1c343e2cd0e818 100644 --- a/packages/priority-queue/CHANGELOG.md +++ b/packages/priority-queue/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.8.0 (2024-09-19) + ## 3.7.0 (2024-09-05) ## 3.6.0 (2024-08-21) diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index c8d7cbe1cebb9a..74c1330cb85c16 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.7.0", + "version": "3.8.0-prerelease", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/CHANGELOG.md b/packages/private-apis/CHANGELOG.md index cd6449dc774ce7..f7807d3667b8a8 100644 --- a/packages/private-apis/CHANGELOG.md +++ b/packages/private-apis/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.8.0 (2024-09-19) + ## 1.7.0 (2024-09-05) ## 1.6.0 (2024-08-21) diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index 3a3dd1aeab5706..7445a8b4a9a493 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.7.0", + "version": "1.8.0-prerelease", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/CHANGELOG.md b/packages/project-management-automation/CHANGELOG.md index 167e68512b3dfc..797d6e3a9cfe2d 100644 --- a/packages/project-management-automation/CHANGELOG.md +++ b/packages/project-management-automation/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.8.0 (2024-09-19) + ## 2.7.0 (2024-09-05) ## 2.6.0 (2024-08-21) diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 2e33d7c44d6cf4..295869594f4329 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.7.0", + "version": "2.8.0-prerelease", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/CHANGELOG.md b/packages/react-i18n/CHANGELOG.md index d0c0dbe7079f4e..cdab707f520dc1 100644 --- a/packages/react-i18n/CHANGELOG.md +++ b/packages/react-i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index d39fc7bba4ba5e..4bc44c08499148 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md index 8147d5c3b3475f..5f28f282f760f8 100644 --- a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md +++ b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.8.0 (2024-09-19) + ## 3.7.0 (2024-09-05) ## 3.6.0 (2024-08-21) diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index 285bcc27ba0a62..845f6abd1e8349 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.7.0", + "version": "3.8.0-prerelease", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/CHANGELOG.md b/packages/redux-routine/CHANGELOG.md index bd03c25219ddbc..82c3b1b4c2e92b 100644 --- a/packages/redux-routine/CHANGELOG.md +++ b/packages/redux-routine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 1efebcb92de7f8..fdb06030a0f91b 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/CHANGELOG.md b/packages/reusable-blocks/CHANGELOG.md index 33f4ef529587f2..9ea28faa2e6c9e 100644 --- a/packages/reusable-blocks/CHANGELOG.md +++ b/packages/reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 8c15057189dc9a..2b402b86a1ea88 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/CHANGELOG.md b/packages/rich-text/CHANGELOG.md index cee6ada55f7b61..e456968e24875b 100644 --- a/packages/rich-text/CHANGELOG.md +++ b/packages/rich-text/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.8.0 (2024-09-19) + ## 7.7.0 (2024-09-05) ## 7.6.0 (2024-08-21) diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index a5a96c77175c1f..7388f2b61dcb39 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.7.0", + "version": "7.8.0-prerelease", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index 02871d4f31e135..2d8d93373f4c5e 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.8.0 (2024-09-19) + ## 1.7.0 (2024-09-05) ## 1.6.0 (2024-08-21) diff --git a/packages/router/package.json b/packages/router/package.json index bcc709bbac5d30..e3eed8e3389fe9 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.7.0", + "version": "1.8.0-prerelease", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 43fe001351bc2c..d24f9dfc7c02a4 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 30.0.0 (2024-09-19) + ### Breaking Changes diff --git a/packages/scripts/package.json b/packages/scripts/package.json index d9e74d0c71826a..2c5e4a0c0e1563 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "29.0.0", + "version": "30.0.0-prerelease", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/CHANGELOG.md b/packages/server-side-render/CHANGELOG.md index d576f09c8e34b7..5acfc6a5cacae6 100644 --- a/packages/server-side-render/CHANGELOG.md +++ b/packages/server-side-render/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.8.0 (2024-09-19) + ## 5.7.0 (2024-09-05) ## 5.6.0 (2024-08-21) diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index 9ace449e3fe966..cecd82927b10c0 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.7.0", + "version": "5.8.0-prerelease", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/CHANGELOG.md b/packages/shortcode/CHANGELOG.md index 6abdd3c52f6d74..cc11e7806f00f4 100644 --- a/packages/shortcode/CHANGELOG.md +++ b/packages/shortcode/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index 10e368d06c9955..6d63c0d459b2df 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md index a5292bfdd6c191..43598ca011863e 100644 --- a/packages/style-engine/CHANGELOG.md +++ b/packages/style-engine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.8.0 (2024-09-19) + ## 2.7.0 (2024-09-05) ## 2.6.0 (2024-08-21) diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 982ac1c1fa89db..5c5d4258092d7d 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.7.0", + "version": "2.8.0-prerelease", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/CHANGELOG.md b/packages/stylelint-config/CHANGELOG.md index 4cc05e02105ff7..7ba3f7fd28dd7c 100644 --- a/packages/stylelint-config/CHANGELOG.md +++ b/packages/stylelint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 23.0.0 (2024-09-19) + ### Breaking Changes - Updated `stylelint` peer dependency requirement to `^16.8.2` ([#64828](https://github.com/WordPress/gutenberg/pull/64828)). diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 874ec2af0c664d..0ca05a84d0e598 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "22.7.0", + "version": "23.0.0-prerelease", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/CHANGELOG.md b/packages/sync/CHANGELOG.md index 071974be2a3a88..4b4978c4eab1ba 100644 --- a/packages/sync/CHANGELOG.md +++ b/packages/sync/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.8.0 (2024-09-19) + ## 1.7.0 (2024-09-05) ## 1.6.0 (2024-08-21) diff --git a/packages/sync/package.json b/packages/sync/package.json index ba8c433e880c3b..3b3cba875c1d42 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.7.0", + "version": "1.8.0-prerelease", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/CHANGELOG.md b/packages/token-list/CHANGELOG.md index 7258699a5322ae..068047bb7f8a58 100644 --- a/packages/token-list/CHANGELOG.md +++ b/packages/token-list/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.8.0 (2024-09-19) + ## 3.7.0 (2024-09-05) ## 3.6.0 (2024-08-21) diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 1a06b76ccb111b..4c3e1e50ecc074 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.7.0", + "version": "3.8.0-prerelease", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/CHANGELOG.md b/packages/undo-manager/CHANGELOG.md index cbe86921a489d2..a8ad0c1d7fbf0c 100644 --- a/packages/undo-manager/CHANGELOG.md +++ b/packages/undo-manager/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.8.0 (2024-09-19) + ## 1.7.0 (2024-09-05) ## 1.6.0 (2024-08-21) diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 4574d94f46d7e1..0f48b9f06d796f 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.7.0", + "version": "1.8.0-prerelease", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/CHANGELOG.md b/packages/url/CHANGELOG.md index fc3082dd1bd0c6..491eaf2e7b8ad2 100644 --- a/packages/url/CHANGELOG.md +++ b/packages/url/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/url/package.json b/packages/url/package.json index c8360c81008fa2..2a743f6349c22c 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/CHANGELOG.md b/packages/viewport/CHANGELOG.md index 1bc96013d724bb..58850208f348c5 100644 --- a/packages/viewport/CHANGELOG.md +++ b/packages/viewport/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.8.0 (2024-09-19) + ## 6.7.0 (2024-09-05) ## 6.6.0 (2024-08-21) diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 69fe9c8695c6ce..4b733228dcdeed 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.7.0", + "version": "6.8.0-prerelease", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/CHANGELOG.md b/packages/warning/CHANGELOG.md index bb7df7b6330625..248b318d7b576c 100644 --- a/packages/warning/CHANGELOG.md +++ b/packages/warning/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.8.0 (2024-09-19) + ## 3.7.0 (2024-09-05) ## 3.6.0 (2024-08-21) diff --git a/packages/warning/package.json b/packages/warning/package.json index 1095d2efd75621..f00b92304dba9a 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.7.0", + "version": "3.8.0-prerelease", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/CHANGELOG.md b/packages/widgets/CHANGELOG.md index be1af839314954..cf3d8c8eac0c2d 100644 --- a/packages/widgets/CHANGELOG.md +++ b/packages/widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 595bad0f733652..79e4fefb28e215 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/CHANGELOG.md b/packages/wordcount/CHANGELOG.md index 0a5e3ae4d3b206..79a5a75b3ef833 100644 --- a/packages/wordcount/CHANGELOG.md +++ b/packages/wordcount/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.8.0 (2024-09-19) + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index 4f6fe750e3fad6..af49ecd5cee6ea 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From fe25bf19feddeb6675d01067f9dab0b5d9087048 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 19 Sep 2024 02:31:04 +0000 Subject: [PATCH 0866/1908] chore(release): publish - @wordpress/a11y@4.8.0 - @wordpress/annotations@3.8.0 - @wordpress/api-fetch@7.8.0 - @wordpress/autop@4.8.0 - @wordpress/babel-plugin-import-jsx-pragma@5.8.0 - @wordpress/babel-plugin-makepot@6.8.0 - @wordpress/babel-preset-default@8.8.0 - @wordpress/base-styles@5.8.0 - @wordpress/blob@4.8.0 - @wordpress/block-directory@5.8.0 - @wordpress/block-editor@14.3.0 - @wordpress/block-library@9.8.0 - @wordpress/block-serialization-default-parser@5.8.0 - @wordpress/block-serialization-spec-parser@5.8.0 - @wordpress/blocks@13.8.0 - @wordpress/browserslist-config@6.8.0 - @wordpress/commands@1.8.0 - @wordpress/components@28.8.0 - @wordpress/compose@7.8.0 - @wordpress/core-commands@1.8.0 - @wordpress/core-data@7.8.0 - @wordpress/create-block@4.51.0 - @wordpress/create-block-interactive-template@2.8.0 - @wordpress/create-block-tutorial-template@4.8.0 - @wordpress/customize-widgets@5.8.0 - @wordpress/data@10.8.0 - @wordpress/data-controls@4.8.0 - @wordpress/dataviews@4.4.0 - @wordpress/date@5.8.0 - @wordpress/dependency-extraction-webpack-plugin@6.8.0 - @wordpress/deprecated@4.8.0 - @wordpress/docgen@2.8.0 - @wordpress/dom@4.8.0 - @wordpress/dom-ready@4.8.0 - @wordpress/e2e-test-utils@11.8.0 - @wordpress/e2e-test-utils-playwright@1.8.0 - @wordpress/e2e-tests@8.8.0 - @wordpress/edit-post@8.8.0 - @wordpress/edit-site@6.8.0 - @wordpress/edit-widgets@6.8.0 - @wordpress/editor@14.8.0 - @wordpress/element@6.8.0 - @wordpress/env@10.8.0 - @wordpress/escape-html@3.8.0 - @wordpress/eslint-plugin@21.1.0 - @wordpress/format-library@5.8.0 - @wordpress/hooks@4.8.0 - @wordpress/html-entities@4.8.0 - @wordpress/i18n@5.8.0 - @wordpress/icons@10.8.0 - @wordpress/interactivity@6.8.0 - @wordpress/interactivity-router@2.8.0 - @wordpress/interface@6.8.0 - @wordpress/is-shallow-equal@5.8.0 - @wordpress/jest-console@8.8.0 - @wordpress/jest-preset-default@12.8.0 - @wordpress/jest-puppeteer-axe@7.8.0 - @wordpress/keyboard-shortcuts@5.8.0 - @wordpress/keycodes@4.8.0 - @wordpress/lazy-import@2.8.0 - @wordpress/list-reusable-blocks@5.8.0 - @wordpress/media-utils@5.8.0 - @wordpress/notices@5.8.0 - @wordpress/npm-package-json-lint-config@5.8.0 - @wordpress/nux@9.8.0 - @wordpress/patterns@2.8.0 - @wordpress/plugins@7.8.0 - @wordpress/postcss-plugins-preset@5.8.0 - @wordpress/postcss-themes@6.8.0 - @wordpress/preferences@4.8.0 - @wordpress/preferences-persistence@2.8.0 - @wordpress/prettier-config@4.8.0 - @wordpress/primitives@4.8.0 - @wordpress/priority-queue@3.8.0 - @wordpress/private-apis@1.8.0 - @wordpress/project-management-automation@2.8.0 - @wordpress/react-i18n@4.8.0 - @wordpress/readable-js-assets-webpack-plugin@3.8.0 - @wordpress/redux-routine@5.8.0 - @wordpress/reusable-blocks@5.8.0 - @wordpress/rich-text@7.8.0 - @wordpress/router@1.8.0 - @wordpress/scripts@30.0.0 - @wordpress/server-side-render@5.8.0 - @wordpress/shortcode@4.8.0 - @wordpress/style-engine@2.8.0 - @wordpress/stylelint-config@23.0.0 - @wordpress/sync@1.8.0 - @wordpress/token-list@3.8.0 - @wordpress/undo-manager@1.8.0 - @wordpress/url@4.8.0 - @wordpress/viewport@6.8.0 - @wordpress/warning@3.8.0 - @wordpress/widgets@4.8.0 - @wordpress/wordcount@4.8.0 --- package-lock.json | 188 +++++++++--------- packages/a11y/package.json | 2 +- packages/annotations/package.json | 2 +- packages/api-fetch/package.json | 2 +- packages/autop/package.json | 2 +- .../package.json | 2 +- packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/package.json | 2 +- packages/base-styles/package.json | 2 +- packages/blob/package.json | 2 +- packages/block-directory/package.json | 2 +- packages/block-editor/package.json | 2 +- packages/block-library/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/blocks/package.json | 2 +- packages/browserslist-config/package.json | 2 +- packages/commands/package.json | 2 +- packages/components/package.json | 2 +- packages/compose/package.json | 2 +- packages/core-commands/package.json | 2 +- packages/core-data/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/create-block/package.json | 2 +- packages/customize-widgets/package.json | 2 +- packages/data-controls/package.json | 2 +- packages/data/package.json | 2 +- packages/dataviews/package.json | 2 +- packages/date/package.json | 2 +- .../package.json | 2 +- packages/deprecated/package.json | 2 +- packages/docgen/package.json | 2 +- packages/dom-ready/package.json | 2 +- packages/dom/package.json | 2 +- .../e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/package.json | 2 +- packages/edit-post/package.json | 2 +- packages/edit-site/package.json | 2 +- packages/edit-widgets/package.json | 2 +- packages/editor/package.json | 2 +- packages/element/package.json | 2 +- packages/env/package.json | 2 +- packages/escape-html/package.json | 2 +- packages/eslint-plugin/package.json | 2 +- packages/format-library/package.json | 2 +- packages/hooks/package.json | 2 +- packages/html-entities/package.json | 2 +- packages/i18n/package.json | 2 +- packages/icons/package.json | 2 +- packages/interactivity-router/package.json | 2 +- packages/interactivity/package.json | 2 +- packages/interface/package.json | 2 +- packages/is-shallow-equal/package.json | 2 +- packages/jest-console/package.json | 2 +- packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/package.json | 2 +- packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/package.json | 2 +- packages/notices/package.json | 2 +- .../npm-package-json-lint-config/package.json | 2 +- packages/nux/package.json | 2 +- packages/patterns/package.json | 2 +- packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/package.json | 2 +- packages/preferences/package.json | 2 +- packages/prettier-config/package.json | 2 +- packages/primitives/package.json | 2 +- packages/priority-queue/package.json | 2 +- packages/private-apis/package.json | 2 +- .../package.json | 2 +- packages/react-i18n/package.json | 2 +- .../package.json | 2 +- packages/redux-routine/package.json | 2 +- packages/reusable-blocks/package.json | 2 +- packages/rich-text/package.json | 2 +- packages/router/package.json | 2 +- packages/scripts/package.json | 2 +- packages/server-side-render/package.json | 2 +- packages/shortcode/package.json | 2 +- packages/style-engine/package.json | 2 +- packages/stylelint-config/package.json | 2 +- packages/sync/package.json | 2 +- packages/token-list/package.json | 2 +- packages/undo-manager/package.json | 2 +- packages/url/package.json | 2 +- packages/viewport/package.json | 2 +- packages/warning/package.json | 2 +- packages/widgets/package.json | 2 +- packages/wordcount/package.json | 2 +- 96 files changed, 189 insertions(+), 189 deletions(-) diff --git a/package-lock.json b/package-lock.json index 421f1418cd5f25..f61d8acd98274c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52564,7 +52564,7 @@ }, "packages/a11y": { "name": "@wordpress/a11y", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52578,7 +52578,7 @@ }, "packages/annotations": { "name": "@wordpress/annotations", - "version": "3.7.0", + "version": "3.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52606,7 +52606,7 @@ }, "packages/api-fetch": { "name": "@wordpress/api-fetch", - "version": "7.7.0", + "version": "7.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52620,7 +52620,7 @@ }, "packages/autop": { "name": "@wordpress/autop", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52632,7 +52632,7 @@ }, "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.7.0", + "version": "5.8.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52645,7 +52645,7 @@ }, "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", - "version": "6.7.0", + "version": "6.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52663,7 +52663,7 @@ }, "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", - "version": "8.7.0", + "version": "8.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52686,7 +52686,7 @@ }, "packages/base-styles": { "name": "@wordpress/base-styles", - "version": "5.7.0", + "version": "5.8.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52696,7 +52696,7 @@ }, "packages/blob": { "name": "@wordpress/blob", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52708,7 +52708,7 @@ }, "packages/block-directory": { "name": "@wordpress/block-directory", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52743,7 +52743,7 @@ }, "packages/block-editor": { "name": "@wordpress/block-editor", - "version": "14.2.0", + "version": "14.3.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52842,7 +52842,7 @@ }, "packages/block-library": { "name": "@wordpress/block-library", - "version": "9.7.0", + "version": "9.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52908,7 +52908,7 @@ }, "packages/block-serialization-default-parser": { "name": "@wordpress/block-serialization-default-parser", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52920,7 +52920,7 @@ }, "packages/block-serialization-spec-parser": { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "pegjs": "^0.10.0", @@ -52933,7 +52933,7 @@ }, "packages/blocks": { "name": "@wordpress/blocks", - "version": "13.7.0", + "version": "13.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52987,7 +52987,7 @@ }, "packages/browserslist-config": { "name": "@wordpress/browserslist-config", - "version": "6.7.0", + "version": "6.8.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52997,7 +52997,7 @@ }, "packages/commands": { "name": "@wordpress/commands", - "version": "1.7.0", + "version": "1.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53170,7 +53170,7 @@ }, "packages/components": { "name": "@wordpress/components", - "version": "28.7.0", + "version": "28.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -53290,7 +53290,7 @@ }, "packages/compose": { "name": "@wordpress/compose", - "version": "7.7.0", + "version": "7.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53327,7 +53327,7 @@ }, "packages/core-commands": { "name": "@wordpress/core-commands", - "version": "1.7.0", + "version": "1.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53355,7 +53355,7 @@ }, "packages/core-data": { "name": "@wordpress/core-data", - "version": "7.7.0", + "version": "7.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53400,7 +53400,7 @@ }, "packages/create-block": { "name": "@wordpress/create-block", - "version": "4.50.0", + "version": "4.51.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53428,7 +53428,7 @@ }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", - "version": "4.7.0", + "version": "4.8.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -53438,7 +53438,7 @@ }, "packages/customize-widgets": { "name": "@wordpress/customize-widgets", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53476,7 +53476,7 @@ }, "packages/data": { "name": "@wordpress/data", - "version": "10.7.0", + "version": "10.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53505,7 +53505,7 @@ }, "packages/data-controls": { "name": "@wordpress/data-controls", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53523,7 +53523,7 @@ }, "packages/dataviews": { "name": "@wordpress/dataviews", - "version": "4.3.0", + "version": "4.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -53580,7 +53580,7 @@ }, "packages/date": { "name": "@wordpress/date", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53595,7 +53595,7 @@ }, "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.7.0", + "version": "6.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53611,7 +53611,7 @@ }, "packages/deprecated": { "name": "@wordpress/deprecated", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53624,7 +53624,7 @@ }, "packages/docgen": { "name": "@wordpress/docgen", - "version": "2.7.0", + "version": "2.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53646,7 +53646,7 @@ }, "packages/dom": { "name": "@wordpress/dom", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53659,7 +53659,7 @@ }, "packages/dom-ready": { "name": "@wordpress/dom-ready", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53671,7 +53671,7 @@ }, "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", - "version": "11.7.0", + "version": "11.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53694,7 +53694,7 @@ }, "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.7.0", + "version": "1.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53722,7 +53722,7 @@ }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", - "version": "8.7.0", + "version": "8.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53762,7 +53762,7 @@ }, "packages/edit-post": { "name": "@wordpress/edit-post", - "version": "8.7.0", + "version": "8.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53809,7 +53809,7 @@ }, "packages/edit-site": { "name": "@wordpress/edit-site", - "version": "6.7.0", + "version": "6.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53871,7 +53871,7 @@ }, "packages/edit-widgets": { "name": "@wordpress/edit-widgets", - "version": "6.7.0", + "version": "6.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53914,7 +53914,7 @@ }, "packages/editor": { "name": "@wordpress/editor", - "version": "14.7.0", + "version": "14.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53976,7 +53976,7 @@ }, "packages/element": { "name": "@wordpress/element", - "version": "6.7.0", + "version": "6.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53995,7 +53995,7 @@ }, "packages/env": { "name": "@wordpress/env", - "version": "10.7.0", + "version": "10.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54137,7 +54137,7 @@ }, "packages/escape-html": { "name": "@wordpress/escape-html", - "version": "3.7.0", + "version": "3.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54149,7 +54149,7 @@ }, "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", - "version": "21.0.0", + "version": "21.1.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54227,7 +54227,7 @@ }, "packages/format-library": { "name": "@wordpress/format-library", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54255,7 +54255,7 @@ }, "packages/hooks": { "name": "@wordpress/hooks", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54267,7 +54267,7 @@ }, "packages/html-entities": { "name": "@wordpress/html-entities", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54279,7 +54279,7 @@ }, "packages/i18n": { "name": "@wordpress/i18n", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54299,7 +54299,7 @@ }, "packages/icons": { "name": "@wordpress/icons", - "version": "10.7.0", + "version": "10.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54313,7 +54313,7 @@ }, "packages/interactivity": { "name": "@wordpress/interactivity", - "version": "6.7.0", + "version": "6.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@preact/signals": "^1.2.2", @@ -54326,7 +54326,7 @@ }, "packages/interactivity-router": { "name": "@wordpress/interactivity-router", - "version": "2.7.0", + "version": "2.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/a11y": "file:../a11y", @@ -54363,7 +54363,7 @@ }, "packages/interface": { "name": "@wordpress/interface", - "version": "6.7.0", + "version": "6.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54392,7 +54392,7 @@ }, "packages/is-shallow-equal": { "name": "@wordpress/is-shallow-equal", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54404,7 +54404,7 @@ }, "packages/jest-console": { "name": "@wordpress/jest-console", - "version": "8.7.0", + "version": "8.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54421,7 +54421,7 @@ }, "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", - "version": "12.7.0", + "version": "12.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54439,7 +54439,7 @@ }, "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.7.0", + "version": "7.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54462,7 +54462,7 @@ }, "packages/keyboard-shortcuts": { "name": "@wordpress/keyboard-shortcuts", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54480,7 +54480,7 @@ }, "packages/keycodes": { "name": "@wordpress/keycodes", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54493,7 +54493,7 @@ }, "packages/lazy-import": { "name": "@wordpress/lazy-import", - "version": "2.7.0", + "version": "2.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54508,7 +54508,7 @@ }, "packages/list-reusable-blocks": { "name": "@wordpress/list-reusable-blocks", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54531,7 +54531,7 @@ }, "packages/media-utils": { "name": "@wordpress/media-utils", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54547,7 +54547,7 @@ }, "packages/notices": { "name": "@wordpress/notices", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54564,7 +54564,7 @@ }, "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.7.0", + "version": "5.8.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54577,7 +54577,7 @@ }, "packages/nux": { "name": "@wordpress/nux", - "version": "9.7.0", + "version": "9.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54600,7 +54600,7 @@ }, "packages/patterns": { "name": "@wordpress/patterns", - "version": "2.7.0", + "version": "2.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54630,7 +54630,7 @@ }, "packages/plugins": { "name": "@wordpress/plugins", - "version": "7.7.0", + "version": "7.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54653,7 +54653,7 @@ }, "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", - "version": "5.7.0", + "version": "5.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54670,7 +54670,7 @@ }, "packages/postcss-themes": { "name": "@wordpress/postcss-themes", - "version": "6.7.0", + "version": "6.8.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54683,7 +54683,7 @@ }, "packages/preferences": { "name": "@wordpress/preferences", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54709,7 +54709,7 @@ }, "packages/preferences-persistence": { "name": "@wordpress/preferences-persistence", - "version": "2.7.0", + "version": "2.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54722,7 +54722,7 @@ }, "packages/prettier-config": { "name": "@wordpress/prettier-config", - "version": "4.7.0", + "version": "4.8.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54735,7 +54735,7 @@ }, "packages/primitives": { "name": "@wordpress/primitives", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54752,7 +54752,7 @@ }, "packages/priority-queue": { "name": "@wordpress/priority-queue", - "version": "3.7.0", + "version": "3.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54765,7 +54765,7 @@ }, "packages/private-apis": { "name": "@wordpress/private-apis", - "version": "1.7.0", + "version": "1.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54777,7 +54777,7 @@ }, "packages/project-management-automation": { "name": "@wordpress/project-management-automation", - "version": "2.7.0", + "version": "2.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54807,7 +54807,7 @@ }, "packages/react-i18n": { "name": "@wordpress/react-i18n", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54963,7 +54963,7 @@ }, "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.7.0", + "version": "3.8.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54976,7 +54976,7 @@ }, "packages/redux-routine": { "name": "@wordpress/redux-routine", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55021,7 +55021,7 @@ }, "packages/reusable-blocks": { "name": "@wordpress/reusable-blocks", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55048,7 +55048,7 @@ }, "packages/rich-text": { "name": "@wordpress/rich-text", - "version": "7.7.0", + "version": "7.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55072,7 +55072,7 @@ }, "packages/router": { "name": "@wordpress/router", - "version": "1.7.0", + "version": "1.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55091,7 +55091,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "29.0.0", + "version": "30.0.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55546,7 +55546,7 @@ }, "packages/server-side-render": { "name": "@wordpress/server-side-render", - "version": "5.7.0", + "version": "5.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55572,7 +55572,7 @@ }, "packages/shortcode": { "name": "@wordpress/shortcode", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55585,7 +55585,7 @@ }, "packages/style-engine": { "name": "@wordpress/style-engine", - "version": "2.7.0", + "version": "2.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55598,7 +55598,7 @@ }, "packages/stylelint-config": { "name": "@wordpress/stylelint-config", - "version": "22.7.0", + "version": "23.0.0", "dev": true, "license": "MIT", "dependencies": { @@ -55716,7 +55716,7 @@ }, "packages/sync": { "name": "@wordpress/sync", - "version": "1.7.0", + "version": "1.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55737,7 +55737,7 @@ }, "packages/token-list": { "name": "@wordpress/token-list", - "version": "3.7.0", + "version": "3.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -55749,7 +55749,7 @@ }, "packages/undo-manager": { "name": "@wordpress/undo-manager", - "version": "1.7.0", + "version": "1.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55762,7 +55762,7 @@ }, "packages/url": { "name": "@wordpress/url", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55775,7 +55775,7 @@ }, "packages/viewport": { "name": "@wordpress/viewport", - "version": "6.7.0", + "version": "6.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55793,7 +55793,7 @@ }, "packages/warning": { "name": "@wordpress/warning", - "version": "3.7.0", + "version": "3.8.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55802,7 +55802,7 @@ }, "packages/widgets": { "name": "@wordpress/widgets", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55830,7 +55830,7 @@ }, "packages/wordcount": { "name": "@wordpress/wordcount", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" diff --git a/packages/a11y/package.json b/packages/a11y/package.json index b1faa8dc0b2603..d3337485a18284 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 3d3f60867cc92c..edaae0ca7617bd 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.8.0-prerelease", + "version": "3.8.0", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 96657c57402c85..54fb852a75402e 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.8.0-prerelease", + "version": "7.8.0", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/package.json b/packages/autop/package.json index ca0fd3f00d0623..49ddffcf79f9ce 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index 788cebe10ddf06..d06a750eb0d91e 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index 1e3e950fb9fc73..5c9cbb1384796b 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.8.0-prerelease", + "version": "6.8.0", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 5ee37cfb105c24..f0f015cb2203f7 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.8.0-prerelease", + "version": "8.8.0", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index c6a873e94191a9..c6ab374e1f5dd3 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/package.json b/packages/blob/package.json index cffd5985680eca..cbcf04ecf64882 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index fdc69ffefcebbf..beef057bf05f04 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index fb0f3423b483ff..a135f126d7eb3c 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.3.0-prerelease", + "version": "14.3.0", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/package.json b/packages/block-library/package.json index afe4dd960f7c6c..aa9daf62dda63a 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.8.0-prerelease", + "version": "9.8.0", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index b4317c163474bc..60e638120952d8 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 0640578fb5cc4b..ab73fa1689ad67 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 45b31db7cea663..b2c24928b7c344 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.8.0-prerelease", + "version": "13.8.0", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 26d5a6820b7284..cae627c406e817 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.8.0-prerelease", + "version": "6.8.0", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/package.json b/packages/commands/package.json index ea3139bc0d0bc7..769931293bd2fd 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.8.0-prerelease", + "version": "1.8.0", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/package.json b/packages/components/package.json index 24576297776395..98eb4c5de0430d 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.8.0-prerelease", + "version": "28.8.0", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/package.json b/packages/compose/package.json index 30f9eacbea191a..f52ac9956a75c1 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.8.0-prerelease", + "version": "7.8.0", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 944feaa3425fa7..8334ef97c9244d 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.8.0-prerelease", + "version": "1.8.0", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/package.json b/packages/core-data/package.json index ae1a5a5928d244..b0eadbcea26039 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.8.0-prerelease", + "version": "7.8.0", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index 2e8b50d8521436..ad30a4b7e01955 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.8.0-prerelease", + "version": "2.8.0", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index a55a328c51842f..67b0c9554ed988 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/package.json b/packages/create-block/package.json index ffed77a5db0f0d..e1522c887deef8 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.51.0-prerelease", + "version": "4.51.0", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 35a3c438f2886b..05edab039844b5 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 38c74b42e9f8d5..5d4d06d3c13cd8 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/package.json b/packages/data/package.json index 0cc2495a5dc743..11396fe33e0876 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.8.0-prerelease", + "version": "10.8.0", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index a9e5f5be7ebf7f..6265d88a4ad82f 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.4.0-prerelease", + "version": "4.4.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/package.json b/packages/date/package.json index 51e1da0e94229a..ad957a6393e1c8 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index 237e0d1c475cf6..a9368e1eb18259 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.8.0-prerelease", + "version": "6.8.0", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index c892ed6e269d49..245d459fb842e5 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 43a582b0819ef1..9bd4581859193f 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.8.0-prerelease", + "version": "2.8.0", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index d07d86d1d5e068..9f4ffbcf61e410 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/package.json b/packages/dom/package.json index c28e756972b356..6707de05992697 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index da1df3d4b21443..f8e31ddc3c359a 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.8.0-prerelease", + "version": "1.8.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index cfa2c8e7120da8..eeb0e66cb62a78 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.8.0-prerelease", + "version": "11.8.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index f4960e156bd8ff..2ce38150c96a00 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.8.0-prerelease", + "version": "8.8.0", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 55abf9cb8d235a..1e5cbb13892a17 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.8.0-prerelease", + "version": "8.8.0", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 2284aae3a0e23c..ef1cdaaa6a5c76 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.8.0-prerelease", + "version": "6.8.0", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index d5f58474f5c162..f0cc613aa40fc2 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.8.0-prerelease", + "version": "6.8.0", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/package.json b/packages/editor/package.json index c2b35baee86d30..29cbffcfb72221 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.8.0-prerelease", + "version": "14.8.0", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/package.json b/packages/element/package.json index 32cdfd3eb1b248..56759cdc23d91b 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.8.0-prerelease", + "version": "6.8.0", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/package.json b/packages/env/package.json index c25fa43d5f3926..b1ea172a4303d9 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.8.0-prerelease", + "version": "10.8.0", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 4f577fe4dbdd82..8f68366006ce7c 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.8.0-prerelease", + "version": "3.8.0", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 64203cbf4ced85..4902acd2bcd0ae 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "21.1.0-prerelease", + "version": "21.1.0", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/package.json b/packages/format-library/package.json index a12fa54977a061..03b1047d3fb9d8 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 1e148a6dd88bb6..cf8e0a791a7471 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index b13077930659be..7196df00a8cd6a 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 4a1c56ed38d38c..2e92335914271b 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/package.json b/packages/icons/package.json index 672a0382e96f84..c1c1682ed6750f 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.8.0-prerelease", + "version": "10.8.0", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 4b76c4492e2dc1..8314d7b1b70d56 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.8.0-prerelease", + "version": "2.8.0", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 7b7ef3fa5f9de9..5b6ce90fc5184e 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.8.0-prerelease", + "version": "6.8.0", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/package.json b/packages/interface/package.json index be14bb394694ca..932c3fde03de4d 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "6.8.0-prerelease", + "version": "6.8.0", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 72ee0392f9a2ef..462b97bda17214 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 6c93d48d31877e..d55ce881a09566 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.8.0-prerelease", + "version": "8.8.0", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index f5a853ff924d98..72be60b0f3376c 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.8.0-prerelease", + "version": "12.8.0", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 2bdefd24ce73f3..69fb9cfa181f44 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.8.0-prerelease", + "version": "7.8.0", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index d9e168b2310efb..038e15ebc1532b 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index d8702f985b1b26..d63d5757dcbf31 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index 00bad5d72d9e86..758c1b5934a955 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.8.0-prerelease", + "version": "2.8.0", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 11e0496cfeade9..03c1c11af9e49f 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 8a7c0e9e994b52..e90ab5a98e87d6 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/package.json b/packages/notices/package.json index f0cd3743007c4b..09056f5fe6818c 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index 6c662b9030e79e..38080c1e09d834 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/package.json b/packages/nux/package.json index 650206a94921f7..8bc5bfea622f09 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.8.0-prerelease", + "version": "9.8.0", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/package.json b/packages/patterns/package.json index f90dae85a8dbce..e3563325f95fa7 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.8.0-prerelease", + "version": "2.8.0", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/package.json b/packages/plugins/package.json index b4dd77907862bd..e9e9bc0667f9a1 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.8.0-prerelease", + "version": "7.8.0", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 74ff1d8ba0fba3..67c030b3a10706 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index ea91b90bf3c4da..864056ee0d61e5 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.8.0-prerelease", + "version": "6.8.0", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index f22e18b5742a6d..a82a883e2b5747 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.8.0-prerelease", + "version": "2.8.0", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/package.json b/packages/preferences/package.json index 045170b81a9f63..fbd2cc46033ee7 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index fc074bec70526b..27a72866e6126d 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 74795ab64ae5e5..2119fc70b11d1c 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 74c1330cb85c16..a60c61528bd5ee 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.8.0-prerelease", + "version": "3.8.0", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index 7445a8b4a9a493..957eec5e34b49e 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.8.0-prerelease", + "version": "1.8.0", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 295869594f4329..e4e1a345f05567 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.8.0-prerelease", + "version": "2.8.0", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 4bc44c08499148..dd4e513e333830 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index 845f6abd1e8349..7901045e659b28 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.8.0-prerelease", + "version": "3.8.0", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index fdb06030a0f91b..8e151e7d6bbfa3 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 2b402b86a1ea88..3e5e9cfb0ca77d 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 7388f2b61dcb39..a7e8e4b173c154 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.8.0-prerelease", + "version": "7.8.0", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/package.json b/packages/router/package.json index e3eed8e3389fe9..5efc014ee221c9 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.8.0-prerelease", + "version": "1.8.0", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 2c5e4a0c0e1563..f1546a9ff7b7e1 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.0.0-prerelease", + "version": "30.0.0", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index cecd82927b10c0..6b6be2fb7e88d5 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.8.0-prerelease", + "version": "5.8.0", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index 6d63c0d459b2df..c16f22d5023cfb 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 5c5d4258092d7d..49327c487b2322 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.8.0-prerelease", + "version": "2.8.0", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 0ca05a84d0e598..8aa35643b3d7e7 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "23.0.0-prerelease", + "version": "23.0.0", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/package.json b/packages/sync/package.json index 3b3cba875c1d42..b96133c749ad30 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.8.0-prerelease", + "version": "1.8.0", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 4c3e1e50ecc074..346623f3df1735 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.8.0-prerelease", + "version": "3.8.0", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 0f48b9f06d796f..1147efbb72a59d 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.8.0-prerelease", + "version": "1.8.0", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/package.json b/packages/url/package.json index 2a743f6349c22c..d04b42a2e19fb4 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 4b733228dcdeed..1a5d1a1c7f5b44 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.8.0-prerelease", + "version": "6.8.0", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/package.json b/packages/warning/package.json index f00b92304dba9a..ded853e825cb0c 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.8.0-prerelease", + "version": "3.8.0", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 79e4fefb28e215..ccc2995650d81c 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index af49ecd5cee6ea..c8b610c9ccffe9 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From a90e35b0c4fe34acd87a2b205f66976771121dd2 Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Thu, 19 Sep 2024 06:41:48 +0200 Subject: [PATCH 0867/1908] Fix `useResizeObserver` bugs (#65389) * Rename "_legacy" dir to "legacy" * Fix circular dependency issue * Fix bug that caused elements to not be unobserved. * Add changelog * Remove changelog entry Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/hooks/use-resize-observer/index.ts | 45 ++----------------- .../{_legacy => legacy}/index.native.js | 0 .../{_legacy => legacy}/index.tsx | 2 +- .../{_legacy => legacy}/test/index.native.js | 0 .../use-resize-observer.ts | 43 ++++++++++++++++++ 5 files changed, 47 insertions(+), 43 deletions(-) rename packages/compose/src/hooks/use-resize-observer/{_legacy => legacy}/index.native.js (100%) rename packages/compose/src/hooks/use-resize-observer/{_legacy => legacy}/index.tsx (98%) rename packages/compose/src/hooks/use-resize-observer/{_legacy => legacy}/test/index.native.js (100%) create mode 100644 packages/compose/src/hooks/use-resize-observer/use-resize-observer.ts diff --git a/packages/compose/src/hooks/use-resize-observer/index.ts b/packages/compose/src/hooks/use-resize-observer/index.ts index 2a76b2aa6ab590..1bd0f074cc49f2 100644 --- a/packages/compose/src/hooks/use-resize-observer/index.ts +++ b/packages/compose/src/hooks/use-resize-observer/index.ts @@ -1,53 +1,14 @@ -/** - * WordPress dependencies - */ -import { useRef } from '@wordpress/element'; /** * Internal dependencies */ -import useEvent from '../use-event'; -import type { ObservedSize } from './_legacy'; -import _useLegacyResizeObserver from './_legacy'; +import { useResizeObserver as _useResizeObserver } from './use-resize-observer'; +import type { ObservedSize } from './legacy'; +import _useLegacyResizeObserver from './legacy'; /** * External dependencies */ import type { ReactElement } from 'react'; -// This is the current implementation of `useResizeObserver`. -// -// The legacy implementation is still supported for backwards compatibility. -// This is achieved by overloading the exported function with both signatures, -// and detecting which API is being used at runtime. -function _useResizeObserver< T extends HTMLElement >( - callback: ResizeObserverCallback, - resizeObserverOptions: ResizeObserverOptions = {} -): ( element?: T | null ) => void { - const callbackEvent = useEvent( callback ); - - const observedElementRef = useRef< T | null >(); - const resizeObserverRef = useRef< ResizeObserver >(); - return useEvent( ( element?: T | null ) => { - if ( element === observedElementRef.current ) { - return; - } - observedElementRef.current = element; - - // Set up `ResizeObserver`. - resizeObserverRef.current ??= new ResizeObserver( callbackEvent ); - const { current: resizeObserver } = resizeObserverRef; - - // Unobserve previous element. - if ( observedElementRef.current ) { - resizeObserver.unobserve( observedElementRef.current ); - } - - // Observe new element. - if ( element ) { - resizeObserver.observe( element, resizeObserverOptions ); - } - } ); -} - /** * Sets up a [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/Resize_Observer_API) * for an HTML or SVG element. diff --git a/packages/compose/src/hooks/use-resize-observer/_legacy/index.native.js b/packages/compose/src/hooks/use-resize-observer/legacy/index.native.js similarity index 100% rename from packages/compose/src/hooks/use-resize-observer/_legacy/index.native.js rename to packages/compose/src/hooks/use-resize-observer/legacy/index.native.js diff --git a/packages/compose/src/hooks/use-resize-observer/_legacy/index.tsx b/packages/compose/src/hooks/use-resize-observer/legacy/index.tsx similarity index 98% rename from packages/compose/src/hooks/use-resize-observer/_legacy/index.tsx rename to packages/compose/src/hooks/use-resize-observer/legacy/index.tsx index b44bd841964164..fe765810982226 100644 --- a/packages/compose/src/hooks/use-resize-observer/_legacy/index.tsx +++ b/packages/compose/src/hooks/use-resize-observer/legacy/index.tsx @@ -10,7 +10,7 @@ import { useCallback, useRef, useState } from '@wordpress/element'; /** * Internal dependencies */ -import useResizeObserver from '../index'; +import { useResizeObserver } from '../use-resize-observer'; export type ObservedSize = { width: number | null; diff --git a/packages/compose/src/hooks/use-resize-observer/_legacy/test/index.native.js b/packages/compose/src/hooks/use-resize-observer/legacy/test/index.native.js similarity index 100% rename from packages/compose/src/hooks/use-resize-observer/_legacy/test/index.native.js rename to packages/compose/src/hooks/use-resize-observer/legacy/test/index.native.js diff --git a/packages/compose/src/hooks/use-resize-observer/use-resize-observer.ts b/packages/compose/src/hooks/use-resize-observer/use-resize-observer.ts new file mode 100644 index 00000000000000..4c1031b9839dc3 --- /dev/null +++ b/packages/compose/src/hooks/use-resize-observer/use-resize-observer.ts @@ -0,0 +1,43 @@ +/** + * WordPress dependencies + */ +import { useRef } from '@wordpress/element'; +/** + * Internal dependencies + */ +import useEvent from '../use-event'; + +// This is the current implementation of `useResizeObserver`. +// +// The legacy implementation is still supported for backwards compatibility. +// This is achieved by overloading the exported function with both signatures, +// and detecting which API is being used at runtime. +export function useResizeObserver< T extends HTMLElement >( + callback: ResizeObserverCallback, + resizeObserverOptions: ResizeObserverOptions = {} +): ( element?: T | null ) => void { + const callbackEvent = useEvent( callback ); + + const observedElementRef = useRef< T | null >(); + const resizeObserverRef = useRef< ResizeObserver >(); + return useEvent( ( element?: T | null ) => { + if ( element === observedElementRef.current ) { + return; + } + + // Set up `ResizeObserver`. + resizeObserverRef.current ??= new ResizeObserver( callbackEvent ); + const { current: resizeObserver } = resizeObserverRef; + + // Unobserve previous element. + if ( observedElementRef.current ) { + resizeObserver.unobserve( observedElementRef.current ); + } + + // Observe new element. + observedElementRef.current = element; + if ( element ) { + resizeObserver.observe( element, resizeObserverOptions ); + } + } ); +} From 610aabe26fe113603fece27db5cd2a90a3fe62b4 Mon Sep 17 00:00:00 2001 From: Robert Anderson <robert@noisysocks.com> Date: Thu, 19 Sep 2024 17:17:15 +1000 Subject: [PATCH 0868/1908] Revert "Make `wordpress/fields` a private package (#65269)" (#65477) This reverts commit 1a60dff84c2effe1a3461d582de8238a7cd0d81f. Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- docs/manifest.json | 6 ++++++ packages/fields/package.json | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/manifest.json b/docs/manifest.json index e4eba19d99fa29..d7f74d47995b63 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1697,6 +1697,12 @@ "markdown_source": "../packages/eslint-plugin/README.md", "parent": "packages" }, + { + "title": "@wordpress/fields", + "slug": "packages-fields", + "markdown_source": "../packages/fields/README.md", + "parent": "packages" + }, { "title": "@wordpress/format-library", "slug": "packages-format-library", diff --git a/packages/fields/package.json b/packages/fields/package.json index 2e417c9f4de570..ba687e6db1bc87 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -9,7 +9,6 @@ "gutenberg", "dataviews" ], - "private": true, "homepage": "https://github.com/WordPress/gutenberg/tree/HEAD/packages/fields/README.md", "repository": { "type": "git", From 6daffdb140f342bb9ffa4c66b082d68237fd7acc Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Thu, 19 Sep 2024 10:28:04 +0200 Subject: [PATCH 0869/1908] Swap position of the Pre-publish checks buttons. (#65317) * Swap position of the Pre-publish checks buttons. * Adjust test. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../components/post-publish-button/index.js | 19 +-------- .../components/post-publish-panel/index.js | 30 +++++++++---- .../components/post-publish-panel/style.scss | 4 +- .../test/__snapshots__/index.js.snap | 42 +++++++++---------- .../editor/various/publish-panel.spec.js | 4 +- 5 files changed, 48 insertions(+), 51 deletions(-) diff --git a/packages/editor/src/components/post-publish-button/index.js b/packages/editor/src/components/post-publish-button/index.js index 0460b27b616e81..71e18a4d6a9c82 100644 --- a/packages/editor/src/components/post-publish-button/index.js +++ b/packages/editor/src/components/post-publish-button/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { Button } from '@wordpress/components'; -import { Component, createRef } from '@wordpress/element'; +import { Component } from '@wordpress/element'; import { withSelect, withDispatch } from '@wordpress/data'; import { compose } from '@wordpress/compose'; @@ -17,7 +17,6 @@ const noop = () => {}; export class PostPublishButton extends Component { constructor( props ) { super( props ); - this.buttonNode = createRef(); this.createOnClick = this.createOnClick.bind( this ); this.closeEntitiesSavedStates = @@ -28,21 +27,6 @@ export class PostPublishButton extends Component { }; } - componentDidMount() { - if ( this.props.focusOnMount ) { - // This timeout is necessary to make sure the `useEffect` hook of - // `useFocusReturn` gets the correct element (the button that opens the - // PostPublishPanel) otherwise it will get this button. - this.timeoutID = setTimeout( () => { - this.buttonNode.current.focus(); - }, 0 ); - } - } - - componentWillUnmount() { - clearTimeout( this.timeoutID ); - } - createOnClick( callback ) { return ( ...args ) => { const { hasNonPostEntityChanges, setEntitiesSavedStatesCallback } = @@ -182,7 +166,6 @@ export class PostPublishButton extends Component { return ( <> <Button - ref={ this.buttonNode } { ...componentProps } className={ `${ componentProps.className } editor-post-publish-button__button` } size="compact" diff --git a/packages/editor/src/components/post-publish-panel/index.js b/packages/editor/src/components/post-publish-panel/index.js index f0e9a55eae0609..6a2d393e20c4ba 100644 --- a/packages/editor/src/components/post-publish-panel/index.js +++ b/packages/editor/src/components/post-publish-panel/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { Component } from '@wordpress/element'; +import { Component, createRef } from '@wordpress/element'; import { Button, Spinner, @@ -27,6 +27,20 @@ export class PostPublishPanel extends Component { constructor() { super( ...arguments ); this.onSubmit = this.onSubmit.bind( this ); + this.cancelButtonNode = createRef(); + } + + componentDidMount() { + // This timeout is necessary to make sure the `useEffect` hook of + // `useFocusReturn` gets the correct element (the button that opens the + // PostPublishPanel) otherwise it will get this button. + this.timeoutID = setTimeout( () => { + this.cancelButtonNode.current.focus(); + }, 0 ); + } + + componentWillUnmount() { + clearTimeout( this.timeoutID ); } componentDidUpdate( prevProps ) { @@ -85,15 +99,9 @@ export class PostPublishPanel extends Component { /> ) : ( <> - <div className="editor-post-publish-panel__header-publish-button"> - <PostPublishButton - focusOnMount - onSubmit={ this.onSubmit } - forceIsDirty={ forceIsDirty } - /> - </div> <div className="editor-post-publish-panel__header-cancel-button"> <Button + ref={ this.cancelButtonNode } accessibleWhenDisabled disabled={ isSavingNonPostEntityChanges } onClick={ onClose } @@ -103,6 +111,12 @@ export class PostPublishPanel extends Component { { __( 'Cancel' ) } </Button> </div> + <div className="editor-post-publish-panel__header-publish-button"> + <PostPublishButton + onSubmit={ this.onSubmit } + forceIsDirty={ forceIsDirty } + /> + </div> </> ) } </div> diff --git a/packages/editor/src/components/post-publish-panel/style.scss b/packages/editor/src/components/post-publish-panel/style.scss index 9892cf5430f9a2..7b075717651781 100644 --- a/packages/editor/src/components/post-publish-panel/style.scss +++ b/packages/editor/src/components/post-publish-panel/style.scss @@ -68,12 +68,12 @@ } .editor-post-publish-panel__header-publish-button { - padding-right: $grid-unit-05; + padding-left: $grid-unit-05; justify-content: center; } .editor-post-publish-panel__header-cancel-button { - padding-left: $grid-unit-05; + padding-right: $grid-unit-05; } .editor-post-publish-panel__header-published { diff --git a/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap b/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap index 1dd75fffaa7b6a..b074159ac423d4 100644 --- a/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap +++ b/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap @@ -433,24 +433,24 @@ exports[`PostPublishPanel should render the pre-publish panel if post status is class="editor-post-publish-panel__header" > <div - class="editor-post-publish-panel__header-publish-button" + class="editor-post-publish-panel__header-cancel-button" > <button - aria-disabled="true" - class="components-button editor-post-publish-button editor-post-publish-button__button is-primary is-compact" + class="components-button is-secondary is-compact" type="button" > - Submit for Review + Cancel </button> </div> <div - class="editor-post-publish-panel__header-cancel-button" + class="editor-post-publish-panel__header-publish-button" > <button - class="components-button is-secondary is-compact" + aria-disabled="true" + class="components-button editor-post-publish-button editor-post-publish-button__button is-primary is-compact" type="button" > - Cancel + Submit for Review </button> </div> </div> @@ -586,24 +586,24 @@ exports[`PostPublishPanel should render the pre-publish panel if the post is not class="editor-post-publish-panel__header" > <div - class="editor-post-publish-panel__header-publish-button" + class="editor-post-publish-panel__header-cancel-button" > <button - aria-disabled="true" - class="components-button editor-post-publish-button editor-post-publish-button__button is-primary is-compact" + class="components-button is-secondary is-compact" type="button" > - Submit for Review + Cancel </button> </div> <div - class="editor-post-publish-panel__header-cancel-button" + class="editor-post-publish-panel__header-publish-button" > <button - class="components-button is-secondary is-compact" + aria-disabled="true" + class="components-button editor-post-publish-button editor-post-publish-button__button is-primary is-compact" type="button" > - Cancel + Submit for Review </button> </div> </div> @@ -783,24 +783,24 @@ exports[`PostPublishPanel should render the spinner if the post is being saved 1 class="editor-post-publish-panel__header" > <div - class="editor-post-publish-panel__header-publish-button" + class="editor-post-publish-panel__header-cancel-button" > <button - aria-disabled="true" - class="components-button editor-post-publish-button editor-post-publish-button__button is-primary is-compact" + class="components-button is-secondary is-compact" type="button" > - Submit for Review + Cancel </button> </div> <div - class="editor-post-publish-panel__header-cancel-button" + class="editor-post-publish-panel__header-publish-button" > <button - class="components-button is-secondary is-compact" + aria-disabled="true" + class="components-button editor-post-publish-button editor-post-publish-button__button is-primary is-compact" type="button" > - Cancel + Submit for Review </button> </div> </div> diff --git a/test/e2e/specs/editor/various/publish-panel.spec.js b/test/e2e/specs/editor/various/publish-panel.spec.js index 534fea5289c9e1..1fe94ff334f3b2 100644 --- a/test/e2e/specs/editor/various/publish-panel.spec.js +++ b/test/e2e/specs/editor/various/publish-panel.spec.js @@ -58,7 +58,7 @@ test.describe( 'Post publish panel', () => { ).toBeFocused(); } ); - test( 'should move focus to the publish button in the panel', async ( { + test( 'should move focus to the cancel button in the panel', async ( { editor, page, } ) => { @@ -74,7 +74,7 @@ test.describe( 'Post publish panel', () => { page .getByRole( 'region', { name: 'Editor publish' } ) .locator( ':focus' ) - ).toHaveText( 'Publish' ); + ).toHaveText( 'Cancel' ); } ); test( 'should focus on the post list after publishing', async ( { From eb715c2c80f456ad2a3b20266550610b81524969 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Thu, 19 Sep 2024 14:46:45 +0530 Subject: [PATCH 0870/1908] Fix: Button: Replace remaining 40px default size violation [Edit Site 1] (#65226) * Fix custom template modal button suggestion list to use default 40px button height * Fix the add new template modal item button to use 40px default size * Fix editor canvas close button to use 40px default button size * Fix add the editor index back button for edit site to use 40px default size * Fix the copy error button size for error boundry warning to use 40px default size Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../add-new-template/add-custom-template-modal-content.js | 3 +-- .../edit-site/src/components/add-new-template/index.js | 3 +-- .../src/components/editor-canvas-container/index.js | 3 +-- packages/edit-site/src/components/editor/index.js | 3 +-- .../edit-site/src/components/error-boundary/warning.js | 7 +------ 5 files changed, 5 insertions(+), 14 deletions(-) diff --git a/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js b/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js index 4993f12153b9e4..69f1925c7b0e44 100644 --- a/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js +++ b/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js @@ -36,8 +36,7 @@ function SuggestionListItem( { <Composite.Item render={ <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize role="option" className={ baseCssClass } onClick={ () => diff --git a/packages/edit-site/src/components/add-new-template/index.js b/packages/edit-site/src/components/add-new-template/index.js index 933ea6df1198bb..bb0acbe62cd659 100644 --- a/packages/edit-site/src/components/add-new-template/index.js +++ b/packages/edit-site/src/components/add-new-template/index.js @@ -107,8 +107,7 @@ function TemplateListItem( { } ) { return ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className={ className } onClick={ onClick } label={ description } diff --git a/packages/edit-site/src/components/editor-canvas-container/index.js b/packages/edit-site/src/components/editor-canvas-container/index.js index 36a3a5b43e5cd2..c55d6b188e1a25 100644 --- a/packages/edit-site/src/components/editor-canvas-container/index.js +++ b/packages/edit-site/src/components/editor-canvas-container/index.js @@ -125,8 +125,7 @@ function EditorCanvasContainer( { > { shouldShowCloseButton && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="edit-site-editor-canvas-container__close-button" icon={ closeSmall } label={ closeButtonLabel || __( 'Close' ) } diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index b99a7cd78ed371..72f796845c567e 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -256,8 +256,7 @@ export default function EditSiteEditor( { isPostsList = false } ) { whileTap="tap" > <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize label={ __( 'Open Navigation' ) } showTooltip tooltipPosition="middle right" diff --git a/packages/edit-site/src/components/error-boundary/warning.js b/packages/edit-site/src/components/error-boundary/warning.js index b03c99f46f03b1..c4090c7e6b1190 100644 --- a/packages/edit-site/src/components/error-boundary/warning.js +++ b/packages/edit-site/src/components/error-boundary/warning.js @@ -9,12 +9,7 @@ import { useCopyToClipboard } from '@wordpress/compose'; function CopyButton( { text, children } ) { const ref = useCopyToClipboard( text ); return ( - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - variant="secondary" - ref={ ref } - > + <Button __next40pxDefaultSize variant="secondary" ref={ ref }> { children } </Button> ); From 001241bbb3ff1b0c24c025815d7897ef353d2d74 Mon Sep 17 00:00:00 2001 From: David Arenas <david.arenas@automattic.com> Date: Thu, 19 Sep 2024 12:12:19 +0200 Subject: [PATCH 0871/1908] Interactivity API: Add `getServerState()` and `getServerContext()` (#65151) * Expose client and server context from provider * Create `getServerContext` * Add simple test for server context * Implement `getServerState` * Add tests for read-only state proxies * Add e2e tests for `getServerState()` * Avoid PHPCS UndefinedVariable error * Add e2e tests for `getServerContext` WIP * Finish e2e tests for `getServerContext()` * Update `getServerState()` tests * Revert "Add simple test for server context" This reverts commit 7e6f530a72dd9117946dd7e7fa9ab5c29f01d13d. * Update TSDocs Co-authored-by: DAreRodz <darerodz@git.wordpress.org> Co-authored-by: luisherranz <luisherranz@git.wordpress.org> Co-authored-by: sethrubenstein <smrubenstein@git.wordpress.org> Co-authored-by: michalczaplinski <czapla@git.wordpress.org> --- .../directive-priorities/view.js | 4 +- .../get-server-context/block.json | 15 ++ .../get-server-context/render.php | 51 +++++ .../get-server-context/view.asset.php | 9 + .../get-server-context/view.js | 46 ++++ .../get-server-state/block.json | 15 ++ .../get-server-state/render.php | 50 +++++ .../get-server-state/view.asset.php | 9 + .../get-server-state/view.js | 33 +++ packages/interactivity/src/directives.tsx | 43 ++-- packages/interactivity/src/hooks.tsx | 6 +- packages/interactivity/src/index.ts | 4 +- packages/interactivity/src/proxies/state.ts | 35 ++- .../src/proxies/test/state-proxy.ts | 199 +++++++++++++++++- packages/interactivity/src/scopes.ts | 44 ++++ packages/interactivity/src/store.ts | 35 +++ .../interactivity/get-sever-context.spec.ts | 166 +++++++++++++++ .../interactivity/get-sever-state.spec.ts | 119 +++++++++++ 18 files changed, 858 insertions(+), 25 deletions(-) create mode 100644 packages/e2e-tests/plugins/interactive-blocks/get-server-context/block.json create mode 100644 packages/e2e-tests/plugins/interactive-blocks/get-server-context/render.php create mode 100644 packages/e2e-tests/plugins/interactive-blocks/get-server-context/view.asset.php create mode 100644 packages/e2e-tests/plugins/interactive-blocks/get-server-context/view.js create mode 100644 packages/e2e-tests/plugins/interactive-blocks/get-server-state/block.json create mode 100644 packages/e2e-tests/plugins/interactive-blocks/get-server-state/render.php create mode 100644 packages/e2e-tests/plugins/interactive-blocks/get-server-state/view.asset.php create mode 100644 packages/e2e-tests/plugins/interactive-blocks/get-server-state/view.js create mode 100644 test/e2e/specs/interactivity/get-sever-context.spec.ts create mode 100644 test/e2e/specs/interactivity/get-sever-state.spec.ts diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-priorities/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-priorities/view.js index 5a46908f77d87b..77f2f25c5f9a41 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-priorities/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-priorities/view.js @@ -41,13 +41,13 @@ directive( 'test-context', ( { context: { Provider }, props: { children } } ) => { executionProof( 'context' ); - const value = { + const client = { [ namespace ]: proxifyState( namespace, { attribute: 'from context', text: 'from context', } ), }; - return h( Provider, { value }, children ); + return h( Provider, { value: { client } }, children ); }, { priority: 8 } ); diff --git a/packages/e2e-tests/plugins/interactive-blocks/get-server-context/block.json b/packages/e2e-tests/plugins/interactive-blocks/get-server-context/block.json new file mode 100644 index 00000000000000..c635846328b9e4 --- /dev/null +++ b/packages/e2e-tests/plugins/interactive-blocks/get-server-context/block.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "test/get-server-context", + "title": "E2E Interactivity tests - getServerContext", + "category": "text", + "icon": "heart", + "description": "", + "supports": { + "interactivity": true + }, + "textdomain": "e2e-interactivity", + "viewScriptModule": "file:./view.js", + "render": "file:./render.php" +} diff --git a/packages/e2e-tests/plugins/interactive-blocks/get-server-context/render.php b/packages/e2e-tests/plugins/interactive-blocks/get-server-context/render.php new file mode 100644 index 00000000000000..a71ced20dc46a1 --- /dev/null +++ b/packages/e2e-tests/plugins/interactive-blocks/get-server-context/render.php @@ -0,0 +1,51 @@ +<?php +/** + * HTML for testing the getServerContext() function. + * + * @package gutenberg-test-interactive-blocks + * + * @phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable + */ + +$link1 = $attributes['links']['modified']; +$link2 = $attributes['links']['newProps']; +$parent_ctx = $attributes['parentContext']; +$child_ctx = $attributes['childContext']; +?> + +<nav + data-testid="navigate" + data-wp-interactive="test/get-server-context" + data-wp-on--click="actions.navigate" +> + <a data-testid="modified" href="<?php echo esc_url( $link1 ); ?>">modified</a> + <a data-testid="newProps" href="<?php echo esc_url( $link2 ); ?>">newProps</a> +</nav> + +<div + data-wp-interactive="test/get-server-context" + data-wp-router-region="server-context" + data-wp-watch="callbacks.updateServerContextParent" + <?php echo wp_interactivity_data_wp_context( $parent_ctx ); ?> +> + <div + data-wp-watch="callbacks.updateServerContextChild" + <?php echo wp_interactivity_data_wp_context( $child_ctx ); ?> + > + <div data-testid="prop" data-wp-text="context.prop"></div> + <div data-testid="nested.prop" data-wp-text="context.nested.prop"></div> + <div data-testid="newProp" data-wp-text="context.newProp"></div> + <div data-testid="nested.newProp" data-wp-text="context.nested.newProp"></div> + <div data-testid="inherited.prop" data-wp-text="context.inherited.prop"></div> + <div data-testid="inherited.newProp" data-wp-text="context.inherited.newProp"></div> + + <button + data-testid="tryToModifyServerContext" + <?php echo wp_interactivity_data_wp_context( array( 'result' => 'modify' ) ); ?> + data-wp-on--click="actions.attemptModification" + data-wp-text="context.result"> + > + modify + </button> + </div> +</div> diff --git a/packages/e2e-tests/plugins/interactive-blocks/get-server-context/view.asset.php b/packages/e2e-tests/plugins/interactive-blocks/get-server-context/view.asset.php new file mode 100644 index 00000000000000..bdaec8d1b67a9d --- /dev/null +++ b/packages/e2e-tests/plugins/interactive-blocks/get-server-context/view.asset.php @@ -0,0 +1,9 @@ +<?php return array( + 'dependencies' => array( + '@wordpress/interactivity', + array( + 'id' => '@wordpress/interactivity-router', + 'import' => 'dynamic', + ), + ), +); diff --git a/packages/e2e-tests/plugins/interactive-blocks/get-server-context/view.js b/packages/e2e-tests/plugins/interactive-blocks/get-server-context/view.js new file mode 100644 index 00000000000000..83f016e2eac16a --- /dev/null +++ b/packages/e2e-tests/plugins/interactive-blocks/get-server-context/view.js @@ -0,0 +1,46 @@ +/** + * WordPress dependencies + */ +import { store, getContext, getServerContext } from '@wordpress/interactivity'; + +store( 'test/get-server-context', { + actions: { + *navigate( e ) { + e.preventDefault(); + const { actions } = yield import( + '@wordpress/interactivity-router' + ); + yield actions.navigate( e.target.href ); + }, + attemptModification() { + try { + getServerContext().prop = 'updated from client'; + getContext().result = 'unexpectedly modified ❌'; + } catch ( e ) { + getContext().result = 'not modified ✅'; + } + }, + }, + callbacks: { + updateServerContextParent() { + const ctx = getContext(); + const { prop, newProp, nested, inherited } = getServerContext(); + ctx.prop = prop; + ctx.newProp = newProp; + ctx.nested.prop = nested.prop; + ctx.nested.newProp = nested.newProp; + ctx.inherited.prop = inherited.prop; + ctx.inherited.newProp = inherited.newProp; + }, + updateServerContextChild() { + const ctx = getContext(); + const { prop, newProp, nested, inherited } = getServerContext(); + ctx.prop = prop; + ctx.newProp = newProp; + ctx.nested.prop = nested.prop; + ctx.nested.newProp = nested.newProp; + ctx.inherited.prop = inherited.prop; + ctx.inherited.newProp = inherited.newProp; + }, + }, +} ); diff --git a/packages/e2e-tests/plugins/interactive-blocks/get-server-state/block.json b/packages/e2e-tests/plugins/interactive-blocks/get-server-state/block.json new file mode 100644 index 00000000000000..abf76eb9beddcc --- /dev/null +++ b/packages/e2e-tests/plugins/interactive-blocks/get-server-state/block.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "test/get-server-state", + "title": "E2E Interactivity tests - getServerState", + "category": "text", + "icon": "heart", + "description": "", + "supports": { + "interactivity": true + }, + "textdomain": "e2e-interactivity", + "viewScriptModule": "file:./view.js", + "render": "file:./render.php" +} diff --git a/packages/e2e-tests/plugins/interactive-blocks/get-server-state/render.php b/packages/e2e-tests/plugins/interactive-blocks/get-server-state/render.php new file mode 100644 index 00000000000000..abc4efd8272d5b --- /dev/null +++ b/packages/e2e-tests/plugins/interactive-blocks/get-server-state/render.php @@ -0,0 +1,50 @@ +<?php +/** + * HTML for testing the getServerState() function. + * + * @package gutenberg-test-interactive-blocks + * + * @phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable + */ + +if ( isset( $attributes['state'] ) ) { + wp_interactivity_state( 'test/get-server-state', $attributes['state'] ); +} +?> + +<div + data-wp-interactive="test/get-server-state" + data-wp-watch="callbacks.updateState" +> + <div data-testid="prop" data-wp-text="state.prop"></div> + <div data-testid="nested.prop" data-wp-text="state.nested.prop"></div> + <div data-testid="newProp" data-wp-text="state.newProp"></div> + <div data-testid="nested.newProp" data-wp-text="state.nested.newProp"></div> + + <button + data-testid="tryToModifyServerState" + <?php echo wp_interactivity_data_wp_context( array( 'result' => 'modify' ) ); ?> + data-wp-on--click="actions.attemptModification" + data-wp-text="context.result"> + > + modify + </button> + + + <nav> + <?php + if ( isset( $attributes['links'] ) ) { + foreach ( $attributes['links'] as $key => $link ) { + $i = $key += 1; + echo <<<HTML + <a + data-testid="link $i" + data-wp-on--click="actions.navigate" + href="$link" + >link $i</a> +HTML; + } + } + ?> + </nav> +</div> diff --git a/packages/e2e-tests/plugins/interactive-blocks/get-server-state/view.asset.php b/packages/e2e-tests/plugins/interactive-blocks/get-server-state/view.asset.php new file mode 100644 index 00000000000000..bdaec8d1b67a9d --- /dev/null +++ b/packages/e2e-tests/plugins/interactive-blocks/get-server-state/view.asset.php @@ -0,0 +1,9 @@ +<?php return array( + 'dependencies' => array( + '@wordpress/interactivity', + array( + 'id' => '@wordpress/interactivity-router', + 'import' => 'dynamic', + ), + ), +); diff --git a/packages/e2e-tests/plugins/interactive-blocks/get-server-state/view.js b/packages/e2e-tests/plugins/interactive-blocks/get-server-state/view.js new file mode 100644 index 00000000000000..db2992ec4a5863 --- /dev/null +++ b/packages/e2e-tests/plugins/interactive-blocks/get-server-state/view.js @@ -0,0 +1,33 @@ +/** + * WordPress dependencies + */ +import { store, getServerState, getContext } from '@wordpress/interactivity'; + +const { state } = store( 'test/get-server-state', { + actions: { + *navigate( e ) { + e.preventDefault(); + const { actions } = yield import( + '@wordpress/interactivity-router' + ); + yield actions.navigate( e.target.href ); + }, + attemptModification() { + try { + getServerState().prop = 'updated from client'; + getContext().result = 'unexpectedly modified ❌'; + } catch ( e ) { + getContext().result = 'not modified ✅'; + } + }, + }, + callbacks: { + updateState() { + const { prop, newProp, nested } = getServerState(); + state.prop = prop; + state.newProp = newProp; + state.nested.prop = nested.prop; + state.nested.newProp = nested.newProp; + }, + }, +} ); diff --git a/packages/interactivity/src/directives.tsx b/packages/interactivity/src/directives.tsx index cde39d830499a2..340880954683da 100644 --- a/packages/interactivity/src/directives.tsx +++ b/packages/interactivity/src/directives.tsx @@ -142,14 +142,19 @@ export default () => { const defaultEntry = context.find( ( { suffix } ) => suffix === 'default' ); - const inheritedValue = useContext( inheritedContext ); + const { client: inheritedClient, server: inheritedServer } = + useContext( inheritedContext ); const ns = defaultEntry!.namespace; - const currentValue = useRef( proxifyState( ns, {} ) ); + const client = useRef( proxifyState( ns, {} ) ); + const server = useRef( proxifyState( ns, {}, { readOnly: true } ) ); // No change should be made if `defaultEntry` does not exist. const contextStack = useMemo( () => { - const result = { ...inheritedValue }; + const result = { + client: { ...inheritedClient }, + server: { ...inheritedServer }, + }; if ( defaultEntry ) { const { namespace, value } = defaultEntry; // Check that the value is a JSON object. Send a console warning if not. @@ -159,17 +164,22 @@ export default () => { ); } deepMerge( - currentValue.current, + client.current, deepClone( value ) as object, false ); - result[ namespace ] = proxifyContext( - currentValue.current, - inheritedValue[ namespace ] + deepMerge( server.current, deepClone( value ) as object ); + result.client[ namespace ] = proxifyContext( + client.current, + inheritedClient[ namespace ] + ); + result.server[ namespace ] = proxifyContext( + server.current, + inheritedServer[ namespace ] ); } return result; - }, [ defaultEntry, inheritedValue ] ); + }, [ defaultEntry, inheritedClient, inheritedServer ] ); return createElement( Provider, { value: contextStack }, children ); }, @@ -563,17 +573,24 @@ export default () => { suffix === 'default' ? 'item' : kebabToCamelCase( suffix ); const itemContext = proxifyContext( proxifyState( namespace, {} ), - inheritedValue[ namespace ] + inheritedValue.client[ namespace ] ); const mergedContext = { - ...inheritedValue, - [ namespace ]: itemContext, + client: { + ...inheritedValue.client, + [ namespace ]: itemContext, + }, + server: { ...inheritedValue.server }, }; // Set the item after proxifying the context. - mergedContext[ namespace ][ itemProp ] = item; + mergedContext.client[ namespace ][ itemProp ] = item; - const scope = { ...getScope(), context: mergedContext }; + const scope = { + ...getScope(), + context: mergedContext.client, + serverContext: mergedContext.server, + }; const key = eachKey ? getEvaluate( { scope } )( eachKey[ 0 ] ) : item; diff --git a/packages/interactivity/src/hooks.tsx b/packages/interactivity/src/hooks.tsx index 215da8afef9b5b..44dc2645da2c80 100644 --- a/packages/interactivity/src/hooks.tsx +++ b/packages/interactivity/src/hooks.tsx @@ -93,7 +93,7 @@ interface DirectivesProps { } // Main context. -const context = createContext< any >( {} ); +const context = createContext< any >( { client: {}, server: {} } ); // WordPress Directives. const directiveCallbacks: Record< string, DirectiveCallback > = {}; @@ -253,7 +253,9 @@ const Directives = ( { // element ref, state and props. const scope = useRef< Scope >( {} as Scope ).current; scope.evaluate = useCallback( getEvaluate( { scope } ), [] ); - scope.context = useContext( context ); + const { client, server } = useContext( context ); + scope.context = client; + scope.serverContext = server; /* eslint-disable react-hooks/rules-of-hooks */ scope.ref = previousScope?.ref || useRef( null ); /* eslint-enable react-hooks/rules-of-hooks */ diff --git a/packages/interactivity/src/index.ts b/packages/interactivity/src/index.ts index 336c2a97226db7..9d013e4e744ed5 100644 --- a/packages/interactivity/src/index.ts +++ b/packages/interactivity/src/index.ts @@ -16,8 +16,8 @@ import { getNamespace } from './namespaces'; import { parseServerData, populateServerData } from './store'; import { proxifyState } from './proxies'; -export { store, getConfig } from './store'; -export { getContext, getElement } from './scopes'; +export { store, getConfig, getServerState } from './store'; +export { getContext, getServerContext, getElement } from './scopes'; export { withScope, useWatch, diff --git a/packages/interactivity/src/proxies/state.ts b/packages/interactivity/src/proxies/state.ts index ec49c4b27c4adb..c91d8f6ab90a5b 100644 --- a/packages/interactivity/src/proxies/state.ts +++ b/packages/interactivity/src/proxies/state.ts @@ -46,6 +46,8 @@ const proxyToProps: WeakMap< export const hasPropSignal = ( proxy: object, key: string ) => proxyToProps.has( proxy ) && proxyToProps.get( proxy )!.has( key ); +const readOnlyProxies = new WeakSet(); + /** * Returns the {@link PropSignal | `PropSignal`} instance associated with the * specified prop in the passed proxy. @@ -77,8 +79,11 @@ const getPropSignal = ( if ( get ) { prop.setGetter( get ); } else { + const readOnly = readOnlyProxies.has( proxy ); prop.setValue( - shouldProxy( value ) ? proxifyState( ns, value ) : value + shouldProxy( value ) + ? proxifyState( ns, value, { readOnly } ) + : value ); } } @@ -148,6 +153,9 @@ const stateHandlers: ProxyHandler< object > = { value: unknown, receiver: object ): boolean { + if ( readOnlyProxies.has( receiver ) ) { + return false; + } setNamespace( getNamespaceFromProxy( receiver ) ); try { return Reflect.set( target, key, value, receiver ); @@ -161,6 +169,10 @@ const stateHandlers: ProxyHandler< object > = { key: string, desc: PropertyDescriptor ): boolean { + if ( readOnlyProxies.has( getProxyFromObject( target )! ) ) { + return false; + } + const isNew = ! ( key in target ); const result = Reflect.defineProperty( target, key, desc ); @@ -199,6 +211,10 @@ const stateHandlers: ProxyHandler< object > = { }, deleteProperty( target: object, key: string ): boolean { + if ( readOnlyProxies.has( getProxyFromObject( target )! ) ) { + return false; + } + const result = Reflect.deleteProperty( target, key ); if ( result ) { @@ -230,8 +246,10 @@ const stateHandlers: ProxyHandler< object > = { * Returns the proxy associated with the given state object, creating it if it * does not exist. * - * @param namespace The namespace that will be associated to this proxy. - * @param obj The object to proxify. + * @param namespace The namespace that will be associated to this proxy. + * @param obj The object to proxify. + * @param options Options. + * @param options.readOnly Read-only. * * @throws Error if the object cannot be proxified. Use {@link shouldProxy} to * check if a proxy can be created for a specific object. @@ -240,8 +258,15 @@ const stateHandlers: ProxyHandler< object > = { */ export const proxifyState = < T extends object >( namespace: string, - obj: T -): T => createProxy( namespace, obj, stateHandlers ) as T; + obj: T, + options?: { readOnly?: boolean } +): T => { + const proxy = createProxy( namespace, obj, stateHandlers ) as T; + if ( options?.readOnly ) { + readOnlyProxies.add( proxy ); + } + return proxy; +}; /** * Reads the value of the specified property without subscribing to it. diff --git a/packages/interactivity/src/proxies/test/state-proxy.ts b/packages/interactivity/src/proxies/test/state-proxy.ts index 92500189fc8309..4b0d2b0a708c3a 100644 --- a/packages/interactivity/src/proxies/test/state-proxy.ts +++ b/packages/interactivity/src/proxies/test/state-proxy.ts @@ -9,7 +9,7 @@ import { effect } from '@preact/signals'; /** * Internal dependencies */ -import { proxifyState, peek } from '../'; +import { proxifyState, peek, deepMerge } from '../'; import { setScope, resetScope, getContext, getElement } from '../../scopes'; import { setNamespace, resetNamespace } from '../../namespaces'; @@ -1265,5 +1265,202 @@ describe( 'Interactivity API', () => { expect( x ).toBe( undefined ); } ); } ); + + describe( 'read-only', () => { + it( "should not allow modifying a prop's value", () => { + const readOnlyState = proxifyState( + 'test', + { prop: 'value', nested: { prop: 'value' } }, + { readOnly: true } + ); + + expect( () => { + readOnlyState.prop = 'new value'; + } ).toThrow(); + expect( () => { + readOnlyState.nested.prop = 'new value'; + } ).toThrow(); + } ); + + it( 'should not allow modifying a prop descriptor', () => { + const readOnlyState = proxifyState( + 'test', + { prop: 'value', nested: { prop: 'value' } }, + { readOnly: true } + ); + + expect( () => { + Object.defineProperty( readOnlyState, 'prop', { + get: () => 'value from getter', + writable: true, + enumerable: false, + } ); + } ).toThrow(); + expect( () => { + Object.defineProperty( readOnlyState.nested, 'prop', { + get: () => 'value from getter', + writable: true, + enumerable: false, + } ); + } ).toThrow(); + } ); + + it( 'should not allow adding new props', () => { + const readOnlyState = proxifyState< any >( + 'test', + { prop: 'value', nested: { prop: 'value' } }, + { readOnly: true } + ); + + expect( () => { + readOnlyState.newProp = 'value'; + } ).toThrow(); + expect( () => { + readOnlyState.nested.newProp = 'value'; + } ).toThrow(); + } ); + + it( 'should not allow removing props', () => { + const readOnlyState = proxifyState< any >( + 'test', + { prop: 'value', nested: { prop: 'value' } }, + { readOnly: true } + ); + + expect( () => { + delete readOnlyState.prop; + } ).toThrow(); + expect( () => { + delete readOnlyState.nested.prop; + } ).toThrow(); + } ); + + it( 'should not allow adding items to an array', () => { + const readOnlyState = proxifyState( + 'test', + { array: [ 1, 2, 3 ], nested: { array: [ 1, 2, 3 ] } }, + { readOnly: true } + ); + + expect( () => readOnlyState.array.push( 4 ) ).toThrow(); + expect( () => readOnlyState.nested.array.push( 4 ) ).toThrow(); + } ); + + it( 'should not allow removing items from an array', () => { + const readOnlyState = proxifyState( + 'test', + { array: [ 1, 2, 3 ], nested: { array: [ 1, 2, 3 ] } }, + { readOnly: true } + ); + + expect( () => readOnlyState.array.pop() ).toThrow(); + expect( () => readOnlyState.nested.array.pop() ).toThrow(); + } ); + + it( 'should allow subscribing to prop changes', () => { + const readOnlyState = proxifyState( + 'test', + { + prop: 'value', + nested: { prop: 'value' }, + }, + { readOnly: true } + ); + + const spy1 = jest.fn( () => readOnlyState.prop ); + const spy2 = jest.fn( () => readOnlyState.nested.prop ); + + effect( spy1 ); + effect( spy2 ); + expect( spy1 ).toHaveBeenCalledTimes( 1 ); + expect( spy2 ).toHaveBeenCalledTimes( 1 ); + expect( spy1 ).toHaveLastReturnedWith( 'value' ); + expect( spy2 ).toHaveLastReturnedWith( 'value' ); + + deepMerge( readOnlyState, { prop: 'new value' } ); + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 1 ); + expect( spy1 ).toHaveLastReturnedWith( 'new value' ); + expect( spy2 ).toHaveLastReturnedWith( 'value' ); + + deepMerge( readOnlyState, { nested: { prop: 'new value' } } ); + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 2 ); + expect( spy1 ).toHaveLastReturnedWith( 'new value' ); + expect( spy2 ).toHaveLastReturnedWith( 'new value' ); + } ); + + it( 'should allow subscribing to new props', () => { + const readOnlyState = proxifyState< any >( + 'test', + { + prop: 'value', + nested: { prop: 'value' }, + }, + { readOnly: true } + ); + + const spy1 = jest.fn( () => readOnlyState.newProp ); + const spy2 = jest.fn( () => readOnlyState.nested.newProp ); + + effect( spy1 ); + effect( spy2 ); + expect( spy1 ).toHaveBeenCalledTimes( 1 ); + expect( spy2 ).toHaveBeenCalledTimes( 1 ); + expect( spy1 ).toHaveLastReturnedWith( undefined ); + expect( spy2 ).toHaveLastReturnedWith( undefined ); + + deepMerge( readOnlyState, { newProp: 'value' } ); + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 1 ); + expect( spy1 ).toHaveLastReturnedWith( 'value' ); + expect( spy2 ).toHaveLastReturnedWith( undefined ); + + deepMerge( readOnlyState, { nested: { newProp: 'value' } } ); + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 2 ); + expect( spy1 ).toHaveLastReturnedWith( 'value' ); + expect( spy2 ).toHaveLastReturnedWith( 'value' ); + } ); + + it( 'should allow subscribing to array changes', () => { + const readOnlyState = proxifyState< any >( + 'test', + { + array: [ 1, 2, 3 ], + nested: { array: [ 1, 2, 3 ] }, + }, + { readOnly: true } + ); + + const spy1 = jest.fn( () => readOnlyState.array[ 0 ] ); + const spy2 = jest.fn( () => readOnlyState.nested.array[ 0 ] ); + + effect( spy1 ); + effect( spy2 ); + expect( spy1 ).toHaveBeenCalledTimes( 1 ); + expect( spy2 ).toHaveBeenCalledTimes( 1 ); + expect( spy1 ).toHaveLastReturnedWith( 1 ); + expect( spy2 ).toHaveLastReturnedWith( 1 ); + + deepMerge( readOnlyState, { array: [ 4, 5, 6 ] } ); + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 1 ); + expect( spy1 ).toHaveLastReturnedWith( 4 ); + expect( spy2 ).toHaveLastReturnedWith( 1 ); + + deepMerge( readOnlyState, { nested: { array: [] } } ); + + expect( spy1 ).toHaveBeenCalledTimes( 2 ); + expect( spy2 ).toHaveBeenCalledTimes( 2 ); + expect( spy1 ).toHaveLastReturnedWith( 4 ); + expect( spy2 ).toHaveLastReturnedWith( undefined ); + } ); + } ); } ); } ); diff --git a/packages/interactivity/src/scopes.ts b/packages/interactivity/src/scopes.ts index 2e78755ec4bbe6..722305f6bee112 100644 --- a/packages/interactivity/src/scopes.ts +++ b/packages/interactivity/src/scopes.ts @@ -12,6 +12,7 @@ import type { Evaluate } from './hooks'; export interface Scope { evaluate: Evaluate; context: object; + serverContext: object; ref: RefObject< HTMLElement >; attributes: createElement.JSX.HTMLAttributes; } @@ -96,3 +97,46 @@ export const getElement = () => { attributes: deepImmutable( attributes ), } ); }; + +/** + * Retrieves the part of the inherited context defined and updated from the + * server. + * + * The object returned is read-only, and includes the context defined in PHP + * with `wp_interactivity_data_wp_context()`, including the corresponding + * inherited properties. When `actions.navigate()` is called, this object is + * updated to reflect the changes in the new visited page, without affecting the + * context returned by `getContext()`. Directives can subscribe to those changes + * to update the context if needed. + * + * @example + * ```js + * store('...', { + * callbacks: { + * updateServerContext() { + * const context = getContext(); + * const serverContext = getServerContext(); + * // Override some property with the new value that came from the server. + * context.overridableProp = serverContext.overridableProp; + * }, + * }, + * }); + * ``` + * + * @param namespace Store namespace. By default, the namespace where the calling + * function exists is used. + * @return The server context content. + */ +export const getServerContext = < T extends object >( + namespace?: string +): T => { + const scope = getScope(); + if ( globalThis.SCRIPT_DEBUG ) { + if ( ! scope ) { + throw Error( + 'Cannot call `getServerContext()` when there is no scope. If you are using an async function, please consider using a generator instead. If you are using some sort of async callbacks, like `setTimeout`, please wrap the callback with `withScope(callback)`.' + ); + } + } + return scope.serverContext[ namespace || getNamespace() ]; +}; diff --git a/packages/interactivity/src/store.ts b/packages/interactivity/src/store.ts index c74764b902e194..b1ad07459c62c0 100644 --- a/packages/interactivity/src/store.ts +++ b/packages/interactivity/src/store.ts @@ -12,6 +12,7 @@ export const stores = new Map(); const rawStores = new Map(); const storeLocks = new Map(); const storeConfigs = new Map(); +const serverStates = new Map(); /** * Get the defined config for the store with the passed namespace. @@ -22,6 +23,39 @@ const storeConfigs = new Map(); export const getConfig = ( namespace?: string ) => storeConfigs.get( namespace || getNamespace() ) || {}; +/** + * Get the part of the state defined and updated from the server. + * + * The object returned is read-only, and includes the state defined in PHP with + * `wp_interactivity_state()`. When using `actions.navigate()`, this object is + * updated to reflect the changes in its properites, without affecting the state + * returned by `store()`. Directives can subscribe to those changes to update + * the state if needed. + * + * @example + * ```js + * const { state } = store('myStore', { + * callbacks: { + * updateServerState() { + * const serverState = getServerState(); + * // Override some property with the new value that came from the server. + * state.overridableProp = serverState.overridableProp; + * }, + * }, + * }); + * ``` + * + * @param namespace Store's namespace from which to retrieve the server state. + * @return The server state for the given namespace. + */ +export const getServerState = ( namespace?: string ) => { + const ns = namespace || getNamespace(); + if ( ! serverStates.has( ns ) ) { + serverStates.set( ns, proxifyState( ns, {}, { readOnly: true } ) ); + } + return serverStates.get( ns ); +}; + interface StoreOptions { /** * Property to block/unblock private store namespaces. @@ -187,6 +221,7 @@ export const populateServerData = ( data?: { Object.entries( data!.state ).forEach( ( [ namespace, state ] ) => { const st = store< any >( namespace, {}, { lock: universalUnlock } ); deepMerge( st.state, state, false ); + deepMerge( getServerState( namespace ), state ); } ); } if ( isPlainObject( data?.config ) ) { diff --git a/test/e2e/specs/interactivity/get-sever-context.spec.ts b/test/e2e/specs/interactivity/get-sever-context.spec.ts new file mode 100644 index 00000000000000..d7bc4075f97604 --- /dev/null +++ b/test/e2e/specs/interactivity/get-sever-context.spec.ts @@ -0,0 +1,166 @@ +/** + * Internal dependencies + */ +import { test, expect } from './fixtures'; + +test.describe( 'getServerContext()', () => { + test.beforeAll( async ( { interactivityUtils: utils } ) => { + const parent = { + prop: 'parent', + nested: { + prop: 'parent', + }, + inherited: { + prop: 'parent', + }, + }; + + const parentModified = { + prop: 'parentModified', + nested: { + prop: 'parentModified', + }, + inherited: { + prop: 'parentModified', + }, + }; + + const parentNewProps = { + prop: 'parent', + newProp: 'parent', + nested: { + prop: 'parent', + newProp: 'parent', + }, + inherited: { + prop: 'parent', + newProp: 'parent', + }, + }; + + const child = { + prop: 'child', + nested: { + prop: 'child', + }, + }; + + const childModified = { + prop: 'childModified', + nested: { + prop: 'childModified', + }, + }; + + const childNewProps = { + prop: 'child', + newProp: 'child', + nested: { + prop: 'child', + newProp: 'child', + }, + }; + + await utils.activatePlugins(); + const link1 = await utils.addPostWithBlock( 'test/get-server-context', { + alias: 'getServerContext() - modified', + attributes: { + parentContext: parentModified, + childContext: childModified, + }, + } ); + const link2 = await utils.addPostWithBlock( 'test/get-server-context', { + alias: 'getServerContext() - new props', + attributes: { + parentContext: parentNewProps, + childContext: childNewProps, + }, + } ); + await utils.addPostWithBlock( 'test/get-server-context', { + alias: 'getServerContext() - main', + attributes: { + links: { modified: link1, newProps: link2 }, + parentContext: parent, + childContext: child, + }, + } ); + } ); + + test.beforeEach( async ( { interactivityUtils: utils, page } ) => { + await page.goto( utils.getLink( 'getServerContext() - main' ) ); + } ); + + test.afterAll( async ( { interactivityUtils: utils } ) => { + await utils.deactivatePlugins(); + await utils.deleteAllPosts(); + } ); + + test( 'should update modified props on navigation', async ( { page } ) => { + const prop = page.getByTestId( 'prop' ); + const nestedProp = page.getByTestId( 'nested.prop' ); + const inheritedProp = page.getByTestId( 'inherited.prop' ); + + await expect( prop ).toHaveText( 'child' ); + await expect( nestedProp ).toHaveText( 'child' ); + await expect( inheritedProp ).toHaveText( 'parent' ); + + await page.getByTestId( 'modified' ).click(); + + await expect( prop ).toHaveText( 'childModified' ); + await expect( nestedProp ).toHaveText( 'childModified' ); + await expect( inheritedProp ).toHaveText( 'parentModified' ); + + await page.goBack(); + + await expect( prop ).toHaveText( 'child' ); + await expect( nestedProp ).toHaveText( 'child' ); + await expect( inheritedProp ).toHaveText( 'parent' ); + } ); + + test( 'should add new props on navigation', async ( { page } ) => { + const newProp = page.getByTestId( 'newProp' ); + const nestedNewProp = page.getByTestId( 'nested.newProp' ); + const inheritedNewProp = page.getByTestId( 'inherited.newProp' ); + + await expect( newProp ).toBeEmpty(); + await expect( nestedNewProp ).toBeEmpty(); + await expect( inheritedNewProp ).toBeEmpty(); + + await page.getByTestId( 'newProps' ).click(); + + await expect( newProp ).toHaveText( 'child' ); + await expect( nestedNewProp ).toHaveText( 'child' ); + await expect( inheritedNewProp ).toHaveText( 'parent' ); + } ); + + test( 'should keep new props on navigation', async ( { page } ) => { + const newProp = page.getByTestId( 'newProp' ); + const nestedNewProp = page.getByTestId( 'nested.newProp' ); + const inheritedNewProp = page.getByTestId( 'inherited.newProp' ); + + await page.getByTestId( 'newProps' ).click(); + + await expect( newProp ).toHaveText( 'child' ); + await expect( nestedNewProp ).toHaveText( 'child' ); + await expect( inheritedNewProp ).toHaveText( 'parent' ); + + await page.goBack(); + + await expect( newProp ).toHaveText( 'child' ); + await expect( nestedNewProp ).toHaveText( 'child' ); + await expect( inheritedNewProp ).toHaveText( 'parent' ); + } ); + + test( 'should prevent any manual modifications', async ( { page } ) => { + const prop = page.getByTestId( 'prop' ); + const button = page.getByTestId( 'tryToModifyServerContext' ); + + await expect( prop ).toHaveText( 'child' ); + await expect( button ).toHaveText( 'modify' ); + + await button.click(); + + await expect( prop ).toHaveText( 'child' ); + await expect( button ).toHaveText( 'not modified ✅' ); + } ); +} ); diff --git a/test/e2e/specs/interactivity/get-sever-state.spec.ts b/test/e2e/specs/interactivity/get-sever-state.spec.ts new file mode 100644 index 00000000000000..16406c1d824463 --- /dev/null +++ b/test/e2e/specs/interactivity/get-sever-state.spec.ts @@ -0,0 +1,119 @@ +/** + * Internal dependencies + */ +import { test, expect } from './fixtures'; + +test.describe( 'getServerState()', () => { + test.beforeAll( async ( { interactivityUtils: utils } ) => { + await utils.activatePlugins(); + const link1 = await utils.addPostWithBlock( 'test/get-server-state', { + alias: 'getServerState() - link 1', + attributes: { + state: { + prop: 'link 1', + newProp: 'link 1', + nested: { + prop: 'link 1', + newProp: 'link 1', + }, + }, + }, + } ); + const link2 = await utils.addPostWithBlock( 'test/get-server-state', { + alias: 'getServerState() - link 2', + attributes: { + state: { + prop: 'link 2', + newProp: 'link 2', + nested: { + prop: 'link 2', + newProp: 'link 2', + }, + }, + }, + } ); + await utils.addPostWithBlock( 'test/get-server-state', { + alias: 'getServerState() - main', + attributes: { + title: 'Main', + links: [ link1, link2 ], + state: { + prop: 'main', + nested: { + prop: 'main', + }, + }, + }, + } ); + } ); + + test.beforeEach( async ( { interactivityUtils: utils, page } ) => { + await page.goto( utils.getLink( 'getServerState() - main' ) ); + } ); + + test.afterAll( async ( { interactivityUtils: utils } ) => { + await utils.deactivatePlugins(); + await utils.deleteAllPosts(); + } ); + + test( 'should update existing state props on navigation', async ( { + page, + } ) => { + const prop = page.getByTestId( 'prop' ); + const nestedProp = page.getByTestId( 'nested.prop' ); + + await expect( prop ).toHaveText( 'main' ); + await expect( nestedProp ).toHaveText( 'main' ); + + await page.getByTestId( 'link 1' ).click(); + + await expect( prop ).toHaveText( 'link 1' ); + await expect( nestedProp ).toHaveText( 'link 1' ); + + await page.goBack(); + await expect( prop ).toHaveText( 'main' ); + await expect( nestedProp ).toHaveText( 'main' ); + + await page.getByTestId( 'link 2' ).click(); + + await expect( prop ).toHaveText( 'link 2' ); + await expect( nestedProp ).toHaveText( 'link 2' ); + } ); + + test( 'should add new state props and keep them on navigation', async ( { + page, + } ) => { + const newProp = page.getByTestId( 'newProp' ); + const nestedNewProp = page.getByTestId( 'nested.newProp' ); + + await expect( newProp ).toBeEmpty(); + await expect( nestedNewProp ).toBeEmpty(); + + await page.getByTestId( 'link 1' ).click(); + + await expect( newProp ).toHaveText( 'link 1' ); + await expect( nestedNewProp ).toHaveText( 'link 1' ); + + await page.goBack(); + await expect( newProp ).toHaveText( 'link 1' ); + await expect( nestedNewProp ).toHaveText( 'link 1' ); + + await page.getByTestId( 'link 2' ).click(); + + await expect( newProp ).toHaveText( 'link 2' ); + await expect( nestedNewProp ).toHaveText( 'link 2' ); + } ); + + test( 'should prevent any manual modifications', async ( { page } ) => { + const prop = page.getByTestId( 'prop' ); + const button = page.getByTestId( 'tryToModifyServerState' ); + + await expect( prop ).toHaveText( 'main' ); + await expect( button ).toHaveText( 'modify' ); + + await button.click(); + + await expect( prop ).toHaveText( 'main' ); + await expect( button ).toHaveText( 'not modified ✅' ); + } ); +} ); From 02e0ff3528c8a161c0e2c91df463ddafd3969490 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 19 Sep 2024 13:18:29 +0300 Subject: [PATCH 0872/1908] Components: Cleanup unused ToggleGroupControl config values (#65456) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../toggle-group-control-option-base/styles.ts | 2 +- packages/components/src/utils/config-values.js | 16 +--------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts b/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts index 86efc5224077f4..020468991225c1 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts +++ b/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts @@ -70,7 +70,7 @@ export const buttonView = ( { } &:active { - background: ${ CONFIG.toggleGroupControlBackgroundColor }; + background: ${ CONFIG.controlBackgroundColor }; } ${ isDeselectable && deselectable } diff --git a/packages/components/src/utils/config-values.js b/packages/components/src/utils/config-values.js index 2040f479a231c2..1bc3945f9b3b16 100644 --- a/packages/components/src/utils/config-values.js +++ b/packages/components/src/utils/config-values.js @@ -7,18 +7,13 @@ import { COLORS } from './colors-values'; const CONTROL_HEIGHT = '36px'; const CONTROL_PROPS = { - controlSurfaceColor: COLORS.white, - controlTextActiveColor: COLORS.theme.accent, - // These values should be shared with TextControl. controlPaddingX: 12, controlPaddingXSmall: 8, controlPaddingXLarge: 12 * 1.3334, // TODO: Deprecate controlBackgroundColor: COLORS.white, - controlBoxShadow: 'transparent', controlBoxShadowFocus: `0 0 0 0.5px ${ COLORS.theme.accent }`, - controlDestructiveBorderColor: COLORS.alert.red, controlHeight: CONTROL_HEIGHT, controlHeightXSmall: `calc( ${ CONTROL_HEIGHT } * 0.6 )`, controlHeightSmall: `calc( ${ CONTROL_HEIGHT } * 0.8 )`, @@ -26,18 +21,9 @@ const CONTROL_PROPS = { controlHeightXLarge: `calc( ${ CONTROL_HEIGHT } * 1.4 )`, }; -const TOGGLE_GROUP_CONTROL_PROPS = { - toggleGroupControlBackgroundColor: CONTROL_PROPS.controlBackgroundColor, - toggleGroupControlBorderColor: COLORS.ui.border, - toggleGroupControlBackdropBackgroundColor: - CONTROL_PROPS.controlSurfaceColor, - toggleGroupControlBackdropBorderColor: COLORS.ui.border, - toggleGroupControlButtonColorActive: CONTROL_PROPS.controlBackgroundColor, -}; - // Using Object.assign to avoid creating circular references when emitting // TypeScript type declarations. -export default Object.assign( {}, CONTROL_PROPS, TOGGLE_GROUP_CONTROL_PROPS, { +export default Object.assign( {}, CONTROL_PROPS, { colorDivider: 'rgba(0, 0, 0, 0.1)', colorScrollbarThumb: 'rgba(0, 0, 0, 0.2)', colorScrollbarThumbHover: 'rgba(0, 0, 0, 0.5)', From e68646a0503d32807a152f2f494e295676259d45 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Thu, 19 Sep 2024 12:28:10 +0200 Subject: [PATCH 0873/1908] Babel preset: Add missing files to package (#65481) Fix an issue where some files are not included in the published package: @wordpress/babel-preset-default@8.8.0 --- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: sgomes <sergiomdgomes@git.wordpress.org> --- packages/babel-preset-default/CHANGELOG.md | 12 ++++++++++-- packages/babel-preset-default/package.json | 4 +++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index c8c3fdb66ecb0e..b31be6ffd8d56d 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -1,8 +1,16 @@ <!-- Learn how to maintain this file at https://github.com/WordPress/gutenberg/tree/HEAD/packages#maintaining-changelogs. --> -## Internal +## Unreleased -- Added `addPolyfillComments` option. When used, it will automatically add magic comments to mark files that need `wp-polyfill`. +### Bug Fixes + +- Fix a bug in 8.8.1 due to missing files in the published package ([#65481](https://github.com/WordPress/gutenberg/pull/65481)). + +## 8.8.0 (2024-09-19) + +### Internal + +- Added `addPolyfillComments` option. When used, it will automatically add magic comments to mark files that need `wp-polyfill` ([#65292](https://github.com/WordPress/gutenberg/pull/65292)). ## 8.7.0 (2024-09-05) diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index f0f015cb2203f7..1203586ec20292 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -26,7 +26,9 @@ }, "files": [ "build", - "index.js" + "index.js", + "polyfill-exclusions.js", + "replace-polyfills.js" ], "main": "index.js", "dependencies": { From f8dffcf2e82365078b2251ae8383404d632b6abf Mon Sep 17 00:00:00 2001 From: Andrei Draganescu <me@andreidraganescu.info> Date: Thu, 19 Sep 2024 13:35:35 +0300 Subject: [PATCH 0874/1908] Handle zoom out when changing device preview (#65444) --- packages/editor/src/components/preview-dropdown/index.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js index ecc5bc610a3027..38565f4b04abed 100644 --- a/packages/editor/src/components/preview-dropdown/index.js +++ b/packages/editor/src/components/preview-dropdown/index.js @@ -26,6 +26,7 @@ import { ActionItem } from '@wordpress/interface'; * Internal dependencies */ import { store as editorStore } from '../../store'; +import { store as blockEditorStore } from '@wordpress/block-editor'; import PostPreviewButton from '../post-preview-button'; export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { @@ -44,6 +45,12 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { }; }, [] ); const { setDeviceType } = useDispatch( editorStore ); + const { __unstableSetEditorMode } = useDispatch( blockEditorStore ); + + const handleDevicePreviewChange = ( newDeviceType ) => { + setDeviceType( newDeviceType ); + __unstableSetEditorMode( 'edit' ); + }; const isMobile = useViewportMatch( 'medium', '<' ); if ( isMobile ) { @@ -113,7 +120,7 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { <MenuItemsChoice choices={ choices } value={ deviceType } - onSelect={ setDeviceType } + onSelect={ handleDevicePreviewChange } /> </MenuGroup> { isTemplate && ( From d912271fb57a171936613ad8e1543ae9878c3495 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 19 Sep 2024 13:08:39 +0200 Subject: [PATCH 0875/1908] Search block: reset size correctly when clearing unit control (#65468) * Search block: reset size correctly when clearing unit control * Make empty string handling more explicit --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/block-library/src/search/edit.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/block-library/src/search/edit.js b/packages/block-library/src/search/edit.js index e2f3bb3999e42c..d4ed5b7e3a4055 100644 --- a/packages/block-library/src/search/edit.js +++ b/packages/block-library/src/search/edit.js @@ -424,13 +424,12 @@ export default function SearchEdit( { } step={ 1 } onChange={ ( newWidth ) => { - const filteredWidth = - widthUnit === '%' && - parseInt( newWidth, 10 ) > 100 - ? 100 - : newWidth; + const parsedNewWidth = + newWidth === '' + ? undefined + : parseInt( newWidth, 10 ); setAttributes( { - width: parseInt( filteredWidth, 10 ), + width: parsedNewWidth, } ); } } onUnitChange={ ( newUnit ) => { @@ -566,7 +565,11 @@ export default function SearchEdit( { <ResizableBox size={ { - width: `${ width }${ widthUnit }`, + width: + width === undefined + ? 'auto' + : `${ width }${ widthUnit }`, + height: 'auto', } } className={ clsx( 'wp-block-search__inside-wrapper', From 74707b6b4c55cb103324e8a19b175c4942094398 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Thu, 19 Sep 2024 14:32:37 +0200 Subject: [PATCH 0876/1908] Make the Settings panel toggle button show its keyboard shortcut in its tooltip (#65322) * Make the Settings panel toggle button show its keyboard shortcut in its tooltip. * Do not pass shortcut prop to PluginSidebar and simplify. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/editor/src/components/plugin-sidebar/index.js | 7 +------ .../src/components/complementary-area-toggle/index.js | 4 ++++ .../interface/src/components/complementary-area/index.js | 1 + 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/editor/src/components/plugin-sidebar/index.js b/packages/editor/src/components/plugin-sidebar/index.js index b9c0177e30fc42..56a954cadffb69 100644 --- a/packages/editor/src/components/plugin-sidebar/index.js +++ b/packages/editor/src/components/plugin-sidebar/index.js @@ -3,7 +3,6 @@ */ import { useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; -import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts'; import { ComplementaryArea } from '@wordpress/interface'; /** @@ -77,12 +76,9 @@ import { store as editorStore } from '../../store'; * ``` */ export default function PluginSidebar( { className, ...props } ) { - const { postTitle, shortcut } = useSelect( ( select ) => { + const { postTitle } = useSelect( ( select ) => { return { postTitle: select( editorStore ).getEditedPostAttribute( 'title' ), - shortcut: select( - keyboardShortcutsStore - ).getShortcutRepresentation( 'core/editor/toggle-sidebar' ), }; }, [] ); return ( @@ -91,7 +87,6 @@ export default function PluginSidebar( { className, ...props } ) { className="editor-sidebar" smallScreenTitle={ postTitle || __( '(no title)' ) } scope="core" - toggleShortcut={ shortcut } { ...props } /> ); diff --git a/packages/interface/src/components/complementary-area-toggle/index.js b/packages/interface/src/components/complementary-area-toggle/index.js index b6690b7df5fc5d..15f9e48d71083e 100644 --- a/packages/interface/src/components/complementary-area-toggle/index.js +++ b/packages/interface/src/components/complementary-area-toggle/index.js @@ -17,6 +17,7 @@ function ComplementaryAreaToggle( { icon, selectedIcon, name, + shortcut, ...props } ) { const ComponentToUse = as; @@ -26,8 +27,10 @@ function ComplementaryAreaToggle( { identifier, [ identifier, scope ] ); + const { enableComplementaryArea, disableComplementaryArea } = useDispatch( interfaceStore ); + return ( <ComponentToUse icon={ selectedIcon && isSelected ? selectedIcon : icon } @@ -39,6 +42,7 @@ function ComplementaryAreaToggle( { enableComplementaryArea( scope, identifier ); } } } + shortcut={ shortcut } { ...props } /> ); diff --git a/packages/interface/src/components/complementary-area/index.js b/packages/interface/src/components/complementary-area/index.js index 363a6ee9dea76c..d9fa8e71acb23a 100644 --- a/packages/interface/src/components/complementary-area/index.js +++ b/packages/interface/src/components/complementary-area/index.js @@ -275,6 +275,7 @@ function ComplementaryArea( { showTooltip={ ! showIconLabels } variant={ showIconLabels ? 'tertiary' : undefined } size="compact" + shortcut={ toggleShortcut } /> ) } </PinnedItems> From 2205e9e9f8aae8a2cfd542f7d57296e651dc12cb Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Thu, 19 Sep 2024 13:39:43 +0100 Subject: [PATCH 0877/1908] Make sections contentOnly in Zoom Out (#65396) --- packages/block-editor/src/store/selectors.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 30fdb76bdbe787..5780b2afe2a672 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2926,6 +2926,7 @@ export const getBlockEditingMode = createRegistrySelector( if ( clientId === null ) { clientId = ''; } + // In zoom-out mode, override the behavior set by // __unstableSetBlockEditingMode to only allow editing the top-level // sections. @@ -2943,9 +2944,13 @@ export const getBlockEditingMode = createRegistrySelector( state, sectionRootClientId ); - if ( ! sectionsClientIds?.includes( clientId ) ) { - return 'disabled'; + + // Sections are always contentOnly. + if ( sectionsClientIds?.includes( clientId ) ) { + return 'contentOnly'; } + + return 'disabled'; } const blockEditingMode = state.blockEditingModes.get( clientId ); From 2ddd1145ff8674796532188b2e2fc8883071f387 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Thu, 19 Sep 2024 14:22:42 +0100 Subject: [PATCH 0878/1908] Hide block transforms in contentOnly mode for non-content blocks (#65394) * Hide transforms in contentOnly * Apply only to non-content blocks Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- .../block-variation-transforms/index.js | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-variation-transforms/index.js b/packages/block-editor/src/components/block-variation-transforms/index.js index 97a3f980541842..8f29effb14e679 100644 --- a/packages/block-editor/src/components/block-variation-transforms/index.js +++ b/packages/block-editor/src/components/block-variation-transforms/index.js @@ -140,19 +140,30 @@ function VariationsToggleGroupControl( { function __experimentalBlockVariationTransforms( { blockClientId } ) { const { updateBlockAttributes } = useDispatch( blockEditorStore ); - const { activeBlockVariation, variations } = useSelect( + const { activeBlockVariation, variations, isContentOnly } = useSelect( ( select ) => { - const { getActiveBlockVariation, getBlockVariations } = - select( blocksStore ); - const { getBlockName, getBlockAttributes } = + const { + getActiveBlockVariation, + getBlockVariations, + __experimentalHasContentRoleAttribute, + } = select( blocksStore ); + const { getBlockName, getBlockAttributes, getBlockEditingMode } = select( blockEditorStore ); + const name = blockClientId && getBlockName( blockClientId ); + + const isContentBlock = + __experimentalHasContentRoleAttribute( name ); + return { activeBlockVariation: getActiveBlockVariation( name, getBlockAttributes( blockClientId ) ), variations: name && getBlockVariations( name, 'transform' ), + isContentOnly: + getBlockEditingMode( blockClientId ) === 'contentOnly' && + ! isContentBlock, }; }, [ blockClientId ] @@ -181,8 +192,7 @@ function __experimentalBlockVariationTransforms( { blockClientId } ) { } ); }; - // Skip rendering if there are no variations - if ( ! variations?.length ) { + if ( ! variations?.length || isContentOnly ) { return null; } From 56bfef82bb93d2bba226e0631aed03eb16057cfd Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Thu, 19 Sep 2024 15:37:29 +0200 Subject: [PATCH 0879/1908] Remove `useEvent` from components package (#65388) * Replace imports of `useEvent` with `@wordpress/compose` * Remove `useEvent` from components package Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/src/utils/element-rect.ts | 6 +-- .../components/src/utils/hooks/use-event.ts | 38 ------------------- .../src/utils/hooks/use-on-value-update.ts | 5 +-- 3 files changed, 2 insertions(+), 47 deletions(-) delete mode 100644 packages/components/src/utils/hooks/use-event.ts diff --git a/packages/components/src/utils/element-rect.ts b/packages/components/src/utils/element-rect.ts index 550ec35b0bc932..a96c25ecfac949 100644 --- a/packages/components/src/utils/element-rect.ts +++ b/packages/components/src/utils/element-rect.ts @@ -3,11 +3,7 @@ * WordPress dependencies */ import { useLayoutEffect, useRef, useState } from '@wordpress/element'; -import { useResizeObserver } from '@wordpress/compose'; -/** - * Internal dependencies - */ -import { useEvent } from './hooks/use-event'; +import { useEvent, useResizeObserver } from '@wordpress/compose'; /** * The position and dimensions of an element, relative to its offset parent. diff --git a/packages/components/src/utils/hooks/use-event.ts b/packages/components/src/utils/hooks/use-event.ts deleted file mode 100644 index eefac9478a8b4f..00000000000000 --- a/packages/components/src/utils/hooks/use-event.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* eslint-disable jsdoc/require-param */ -/** - * WordPress dependencies - */ -import { useRef, useInsertionEffect, useCallback } from '@wordpress/element'; - -/** - * Any function. - */ -export type AnyFunction = ( ...args: any ) => any; - -/** - * Creates a stable callback function that has access to the latest state and - * can be used within event handlers and effect callbacks. Throws when used in - * the render phase. - * - * @example - * - * ```tsx - * function Component(props) { - * const onClick = useEvent(props.onClick); - * React.useEffect(() => {}, [onClick]); - * } - * ``` - */ -export function useEvent< T extends AnyFunction >( callback?: T ) { - const ref = useRef< AnyFunction | undefined >( () => { - throw new Error( 'Cannot call an event handler while rendering.' ); - } ); - useInsertionEffect( () => { - ref.current = callback; - } ); - return useCallback< AnyFunction >( - ( ...args ) => ref.current?.( ...args ), - [] - ) as T; -} -/* eslint-enable jsdoc/require-param */ diff --git a/packages/components/src/utils/hooks/use-on-value-update.ts b/packages/components/src/utils/hooks/use-on-value-update.ts index 5726f3977daf04..05c7173d092fac 100644 --- a/packages/components/src/utils/hooks/use-on-value-update.ts +++ b/packages/components/src/utils/hooks/use-on-value-update.ts @@ -2,11 +2,8 @@ /** * WordPress dependencies */ +import { useEvent } from '@wordpress/compose'; import { useRef, useEffect } from '@wordpress/element'; -/** - * Internal dependencies - */ -import { useEvent } from './use-event'; /** * Context object for the `onUpdate` callback of `useOnValueUpdate`. From 3910eab3e8db99a4e049a838549d908f22e2ac95 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 19 Sep 2024 16:59:56 +0200 Subject: [PATCH 0880/1908] Dataviews config dropdown: remove style overrides (#65373) * Remove duplicate classname * Use `DropdownContentWrapper` and avoid style overrides * Extract popover props to const object * Move Dropdown under DataviewsViewConfigDropdown component * Add aria-expanded and aria-controls attributes to the dropdown toggle * Sort imports * Move DATAVIEWS_CONFIG_POPOVER_PROPS declaration at the top of the file * Do not memoize popover props --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../dataviews-view-config/index.tsx | 92 +++++++++++-------- .../dataviews-view-config/style.scss | 13 +-- 2 files changed, 57 insertions(+), 48 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index 48fdf6906b0774..02e81b2b0913d8 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -8,6 +8,7 @@ import type { ChangeEvent } from 'react'; */ import { Button, + __experimentalDropdownContentWrapper as DropdownContentWrapper, Dropdown, __experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControlOption as ToggleGroupControlOption, @@ -27,6 +28,7 @@ import { __, _x, sprintf } from '@wordpress/i18n'; import { memo, useContext, useMemo } from '@wordpress/element'; import { chevronDown, chevronUp, cog, seen, unseen } from '@wordpress/icons'; import warning from '@wordpress/warning'; +import { useInstanceId } from '@wordpress/compose'; /** * Internal dependencies @@ -55,6 +57,8 @@ interface ViewTypeMenuProps { defaultLayouts?: SupportedLayouts; } +const DATAVIEWS_CONFIG_POPOVER_PROPS = { placement: 'bottom-end', offset: 9 }; + function ViewTypeMenu( { defaultLayouts = { list: {}, grid: {}, table: {} }, }: ViewTypeMenuProps ) { @@ -510,7 +514,7 @@ function SettingsSection( { ); } -function DataviewsViewConfigContent( { +function DataviewsViewConfigDropdown( { density, setDensity, }: { @@ -518,25 +522,52 @@ function DataviewsViewConfigContent( { setDensity: React.Dispatch< React.SetStateAction< number > >; } ) { const { view } = useContext( DataViewsContext ); + const popoverId = useInstanceId( + _DataViewsViewConfig, + 'dataviews-view-config-dropdown' + ); + return ( - <VStack className="dataviews-view-config" spacing={ 6 }> - <SettingsSection title={ __( 'Appearance' ) }> - <HStack expanded className="is-divided-in-two"> - <SortFieldControl /> - <SortDirectionControl /> - </HStack> - { view.type === LAYOUT_GRID && ( - <DensityPicker - density={ density } - setDensity={ setDensity } + <Dropdown + popoverProps={ { + ...DATAVIEWS_CONFIG_POPOVER_PROPS, + id: popoverId, + } } + renderToggle={ ( { onToggle, isOpen } ) => { + return ( + <Button + size="compact" + icon={ cog } + label={ _x( 'View options', 'View is used as a noun' ) } + onClick={ onToggle } + aria-expanded={ isOpen ? 'true' : 'false' } + aria-controls={ popoverId } /> - ) } - <ItemsPerPageControl /> - </SettingsSection> - <SettingsSection title={ __( 'Properties' ) }> - <FieldControl /> - </SettingsSection> - </VStack> + ); + } } + renderContent={ () => ( + <DropdownContentWrapper paddingSize="medium"> + <VStack className="dataviews-view-config" spacing={ 6 }> + <SettingsSection title={ __( 'Appearance' ) }> + <HStack expanded className="is-divided-in-two"> + <SortFieldControl /> + <SortDirectionControl /> + </HStack> + { view.type === LAYOUT_GRID && ( + <DensityPicker + density={ density } + setDensity={ setDensity } + /> + ) } + <ItemsPerPageControl /> + </SettingsSection> + <SettingsSection title={ __( 'Properties' ) }> + <FieldControl /> + </SettingsSection> + </VStack> + </DropdownContentWrapper> + ) } + /> ); } @@ -552,28 +583,9 @@ function _DataViewsViewConfig( { return ( <> <ViewTypeMenu defaultLayouts={ defaultLayouts } /> - <Dropdown - popoverProps={ { placement: 'bottom-end', offset: 9 } } - contentClassName="dataviews-view-config" - renderToggle={ ( { onToggle } ) => { - return ( - <Button - size="compact" - icon={ cog } - label={ _x( - 'View options', - 'View is used as a noun' - ) } - onClick={ onToggle } - /> - ); - } } - renderContent={ () => ( - <DataviewsViewConfigContent - density={ density } - setDensity={ setDensity } - /> - ) } + <DataviewsViewConfigDropdown + density={ density } + setDensity={ setDensity } /> </> ); diff --git a/packages/dataviews/src/components/dataviews-view-config/style.scss b/packages/dataviews/src/components/dataviews-view-config/style.scss index c7d07fe7866bcf..7fff110337ee3a 100644 --- a/packages/dataviews/src/components/dataviews-view-config/style.scss +++ b/packages/dataviews/src/components/dataviews-view-config/style.scss @@ -1,12 +1,9 @@ .dataviews-view-config { - .components-popover__content { - width: 320px; - /* stylelint-disable-next-line property-no-unknown -- the linter needs to be updated to accepted the container-type property */ - container-type: inline-size; - padding: $grid-unit-20; - font-size: $default-font-size; - line-height: $default-line-height; - } + width: 320px; + /* stylelint-disable-next-line property-no-unknown -- the linter needs to be updated to accepted the container-type property */ + container-type: inline-size; + font-size: $default-font-size; + line-height: $default-line-height; } .dataviews-view-config__sort-direction .components-toggle-group-control-option-base { From cbcc28c5511dc87b81bca515b2e88fc1ec55e7e9 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 19 Sep 2024 17:58:34 +0100 Subject: [PATCH 0881/1908] Select Mode: Use the content-only behavior in select mode (#65204) Also since it repurposes what select mode is for, this PR removes the specific keyboard navigation behavior that we had (a request that some a11y folks made as well). It also removes the confusing "move to" feature for several reasons, first it was based on the old keyboard navigation behavior and it was causing confusion for the users. Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> --- .../data/data-core-block-editor.md | 18 +- packages/base-styles/_z-index.scss | 5 - .../src/components/block-actions/index.js | 14 +- .../src/components/block-inspector/index.js | 174 +++++----- .../src/components/block-list/block.js | 29 +- .../src/components/block-list/content.scss | 52 +-- .../src/components/block-list/index.js | 50 ++- .../block-list/use-block-props/index.js | 10 +- .../use-block-props/use-nav-mode-exit.js | 46 --- .../block-settings-menu-controls/index.js | 15 - .../block-settings-dropdown.js | 8 - .../block-tools/block-selection-button.js | 302 ------------------ .../block-tools/block-toolbar-breadcrumb.js | 51 --- .../src/components/block-tools/index.js | 10 - .../components/block-tools/insertion-point.js | 5 +- .../src/components/block-tools/style.scss | 82 ----- .../block-tools/use-show-block-tools.js | 14 +- .../block-tools/zoom-out-toolbar.js | 14 +- .../src/components/inner-blocks/content.scss | 13 - .../src/components/inner-blocks/index.js | 17 +- .../components/list-view/block-contents.js | 29 +- .../src/components/list-view/style.scss | 14 - .../src/components/tool-selector/index.js | 20 +- .../src/components/tool-selector/style.scss | 5 + .../components/use-block-commands/index.js | 58 ---- .../components/writing-flow/use-tab-nav.js | 40 +-- packages/block-editor/src/content.scss | 1 - packages/block-editor/src/store/actions.js | 27 +- .../src/store/private-selectors.js | 68 +++- packages/block-editor/src/store/reducer.js | 26 -- packages/block-editor/src/store/selectors.js | 57 +++- .../src/store/test/private-selectors.js | 34 ++ .../block-editor/src/store/test/selectors.js | 84 ++++- packages/block-editor/src/store/utils.js | 1 + packages/components/CHANGELOG.md | 1 + .../src/menu-items-choice/style.scss | 2 + .../content-only-settings-menu.js | 21 +- .../disable-non-page-content-blocks.js | 54 ++-- .../provider/use-post-content-blocks.js | 42 +++ .../src/blocks/legacy-widget/edit/index.js | 10 +- .../editor/various/block-moving-mode.spec.js | 155 --------- .../various/keyboard-navigable-blocks.spec.js | 126 +------- .../various/shortcut-focus-toolbar.spec.js | 26 -- .../specs/editor/various/writing-flow.spec.js | 78 +---- test/e2e/specs/site-editor/navigation.spec.js | 13 - .../specs/widgets/customizing-widgets.spec.js | 10 - 46 files changed, 475 insertions(+), 1456 deletions(-) delete mode 100644 packages/block-editor/src/components/block-list/use-block-props/use-nav-mode-exit.js delete mode 100644 packages/block-editor/src/components/block-tools/block-selection-button.js delete mode 100644 packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js delete mode 100644 packages/block-editor/src/components/inner-blocks/content.scss create mode 100644 packages/editor/src/components/provider/use-post-content-blocks.js delete mode 100644 test/e2e/specs/editor/various/block-moving-mode.spec.js diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index c6552ef431cef8..4b3ca78f74d299 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -857,15 +857,9 @@ _Returns_ ### hasBlockMovingClientId -Returns whether block moving mode is enabled. - -_Parameters_ - -- _state_ `Object`: Editor state. - -_Returns_ +> **Deprecated** -- `string`: Client Id of moving block. +Returns whether block moving mode is enabled. ### hasDraggedInnerBlock @@ -1661,11 +1655,13 @@ _Returns_ ### setBlockMovingClientId -Action that enables or disables the block moving mode. +> **Deprecated** -_Parameters_ +Set the block moving client ID. -- _hasBlockMovingClientId_ `string|null`: Enable/Disable block moving mode. +_Returns_ + +- `Object`: Action object. ### setBlockVisibility diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index cc99df6dbeaafc..77238c6f386084 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -8,7 +8,6 @@ $z-layers: ( ".block-editor-block-switcher__arrow": 1, ".block-editor-block-list__block {core/image aligned wide or fullwide}": 20, ".block-library-classic__toolbar": 31, // When scrolled to top this toolbar needs to sit over block-editor-block-toolbar - ".block-editor-block-list__block-selection-button": 22, ".components-form-toggle__input": 1, ".editor-text-editor__toolbar": 1, @@ -70,10 +69,6 @@ $z-layers: ( // Below the media library backdrop (.media-modal-backdrop), which has a z-index of 159900. ".block-editor-global-styles-background-panel__popover": 159900 - 10, - // Small screen inner blocks overlay must be displayed above drop zone, - // settings menu, and movers. - ".block-editor-block-list__layout.has-overlay::after": 60, - // The toolbar, when contextual, should be above any adjacent nested block click overlays. ".block-editor-block-contextual-toolbar": 61, diff --git a/packages/block-editor/src/components/block-actions/index.js b/packages/block-editor/src/components/block-actions/index.js index 5e12165c679424..f06c8addedad50 100644 --- a/packages/block-editor/src/components/block-actions/index.js +++ b/packages/block-editor/src/components/block-actions/index.js @@ -29,7 +29,6 @@ export default function BlockActions( { getBlockRootClientId, getBlocksByClientId, getDirectInsertBlock, - canMoveBlocks, canRemoveBlocks, } = select( blockEditorStore ); @@ -44,7 +43,6 @@ export default function BlockActions( { : null; return { - canMove: canMoveBlocks( clientIds ), canRemove: canRemoveBlocks( clientIds ), canInsertBlock: canInsertDefaultBlock || !! directInsertBlock, canCopyStyles: blocks.every( ( block ) => { @@ -67,8 +65,7 @@ export default function BlockActions( { ); const { getBlocksByClientId, getBlocks } = useSelect( blockEditorStore ); - const { canMove, canRemove, canInsertBlock, canCopyStyles, canDuplicate } = - selected; + const { canRemove, canInsertBlock, canCopyStyles, canDuplicate } = selected; const { removeBlocks, @@ -77,9 +74,6 @@ export default function BlockActions( { insertAfterBlock, insertBeforeBlock, flashBlock, - setBlockMovingClientId, - setNavigationMode, - selectBlock, } = useDispatch( blockEditorStore ); const notifyCopy = useNotifyCopy(); @@ -89,7 +83,6 @@ export default function BlockActions( { canCopyStyles, canDuplicate, canInsertBlock, - canMove, canRemove, onDuplicate() { return duplicateBlocks( clientIds, updateSelection ); @@ -103,11 +96,6 @@ export default function BlockActions( { onInsertAfter() { insertAfterBlock( clientIds[ clientIds.length - 1 ] ); }, - onMoveTo() { - setNavigationMode( true ); - selectBlock( clientIds[ 0 ] ); - setBlockMovingClientId( clientIds[ 0 ] ); - }, onGroup() { if ( ! clientIds.length ) { return; diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index a18556f2fa5bd9..475d4f6a4b8c2e 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -40,83 +40,36 @@ function BlockStylesPanel( { clientId } ) { ); } -function BlockInspectorLockedBlocks( { topLevelLockedBlock } ) { - const contentClientIds = useSelect( - ( select ) => { - const { - getClientIdsOfDescendants, - getBlockName, - getBlockEditingMode, - } = select( blockEditorStore ); - return getClientIdsOfDescendants( topLevelLockedBlock ).filter( - ( clientId ) => - getBlockName( clientId ) !== 'core/list-item' && - getBlockEditingMode( clientId ) === 'contentOnly' - ); - }, - [ topLevelLockedBlock ] - ); - const hasBlockStyles = useSelect( - ( select ) => { - const { getBlockName } = select( blockEditorStore ); - const { getBlockStyles } = select( blocksStore ); - return !! getBlockStyles( getBlockName( topLevelLockedBlock ) ) - ?.length; - }, - [ topLevelLockedBlock ] - ); - const blockInformation = useBlockDisplayInformation( topLevelLockedBlock ); - return ( - <div className="block-editor-block-inspector"> - <BlockCard - { ...blockInformation } - className={ blockInformation.isSynced && 'is-synced' } - /> - <BlockInfo.Slot /> - { hasBlockStyles && ( - <BlockStylesPanel clientId={ topLevelLockedBlock } /> - ) } - { contentClientIds.length > 0 && ( - <PanelBody title={ __( 'Content' ) }> - <BlockQuickNavigation clientIds={ contentClientIds } /> - </PanelBody> - ) } - </div> - ); -} - const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { const { count, selectedBlockName, selectedBlockClientId, blockType, - topLevelLockedBlock, + isSectionBlock, } = useSelect( ( select ) => { const { getSelectedBlockClientId, getSelectedBlockCount, getBlockName, - getContentLockingParent, - getTemplateLock, + getParentSectionBlock, + isSectionBlock: _isSectionBlock, } = unlock( select( blockEditorStore ) ); const _selectedBlockClientId = getSelectedBlockClientId(); + const renderedBlockClientId = + getParentSectionBlock( _selectedBlockClientId ) || + getSelectedBlockClientId(); const _selectedBlockName = - _selectedBlockClientId && getBlockName( _selectedBlockClientId ); + renderedBlockClientId && getBlockName( renderedBlockClientId ); const _blockType = _selectedBlockName && getBlockType( _selectedBlockName ); return { count: getSelectedBlockCount(), - selectedBlockClientId: _selectedBlockClientId, + selectedBlockClientId: renderedBlockClientId, selectedBlockName: _selectedBlockName, blockType: _blockType, - topLevelLockedBlock: - getContentLockingParent( _selectedBlockClientId ) || - ( getTemplateLock( _selectedBlockClientId ) === 'contentOnly' || - _selectedBlockName === 'core/block' - ? _selectedBlockClientId - : undefined ), + isSectionBlock: _isSectionBlock( renderedBlockClientId ), }; }, [] ); @@ -136,7 +89,7 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { blockName: selectedBlockName, } ); - if ( count > 1 ) { + if ( count > 1 && ! isSectionBlock ) { return ( <div className="block-editor-block-inspector"> <MultiSelectionInspector /> @@ -194,13 +147,6 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { } return null; } - if ( topLevelLockedBlock ) { - return ( - <BlockInspectorLockedBlocks - topLevelLockedBlock={ topLevelLockedBlock } - /> - ); - } return ( <BlockInspectorSingleBlockWrapper @@ -219,6 +165,7 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { <BlockInspectorSingleBlock clientId={ selectedBlockClientId } blockName={ blockType.name } + isSectionBlock={ isSectionBlock } /> </BlockInspectorSingleBlockWrapper> ); @@ -260,9 +207,13 @@ const AnimatedContainer = ( { ); }; -const BlockInspectorSingleBlock = ( { clientId, blockName } ) => { +const BlockInspectorSingleBlock = ( { + clientId, + blockName, + isSectionBlock, +} ) => { const availableTabs = useInspectorControlsTabs( blockName ); - const showTabs = availableTabs?.length > 1; + const showTabs = ! isSectionBlock && availableTabs?.length > 1; const hasBlockStyles = useSelect( ( select ) => { @@ -274,6 +225,26 @@ const BlockInspectorSingleBlock = ( { clientId, blockName } ) => { ); const blockInformation = useBlockDisplayInformation( clientId ); const borderPanelLabel = useBorderPanelLabel( { blockName } ); + const contentClientIds = useSelect( + ( select ) => { + // Avoid unnecessary subscription. + if ( ! isSectionBlock ) { + return; + } + + const { + getClientIdsOfDescendants, + getBlockName, + getBlockEditingMode, + } = select( blockEditorStore ); + return getClientIdsOfDescendants( clientId ).filter( + ( current ) => + getBlockName( current ) !== 'core/list-item' && + getBlockEditingMode( current ) === 'contentOnly' + ); + }, + [ isSectionBlock, clientId ] + ); return ( <div className="block-editor-block-inspector"> @@ -296,35 +267,48 @@ const BlockInspectorSingleBlock = ( { clientId, blockName } ) => { { hasBlockStyles && ( <BlockStylesPanel clientId={ clientId } /> ) } - <InspectorControls.Slot /> - <InspectorControls.Slot group="list" /> - <InspectorControls.Slot - group="color" - label={ __( 'Color' ) } - className="color-block-support-panel__inner-wrapper" - /> - <InspectorControls.Slot - group="background" - label={ __( 'Background image' ) } - /> - <InspectorControls.Slot - group="typography" - label={ __( 'Typography' ) } - /> - <InspectorControls.Slot - group="dimensions" - label={ __( 'Dimensions' ) } - /> - <InspectorControls.Slot - group="border" - label={ borderPanelLabel } - /> - <InspectorControls.Slot group="styles" /> - <PositionControls /> - <InspectorControls.Slot group="bindings" /> - <div> - <AdvancedControls /> - </div> + + { contentClientIds && contentClientIds?.length > 0 && ( + <PanelBody title={ __( 'Content' ) }> + <BlockQuickNavigation + clientIds={ contentClientIds } + /> + </PanelBody> + ) } + + { ! isSectionBlock && ( + <> + <InspectorControls.Slot /> + <InspectorControls.Slot group="list" /> + <InspectorControls.Slot + group="color" + label={ __( 'Color' ) } + className="color-block-support-panel__inner-wrapper" + /> + <InspectorControls.Slot + group="background" + label={ __( 'Background image' ) } + /> + <InspectorControls.Slot + group="typography" + label={ __( 'Typography' ) } + /> + <InspectorControls.Slot + group="dimensions" + label={ __( 'Dimensions' ) } + /> + <InspectorControls.Slot + group="border" + label={ borderPanelLabel } + /> + <InspectorControls.Slot group="styles" /> + <PositionControls /> + <InspectorControls.Slot group="bindings" /> + <div> + <AdvancedControls /> + </div> + </> + ) } </> ) } <SkipToSelectedBlock key="back" /> diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index deda4e3b9d0897..90c39649319dc8 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -549,6 +549,7 @@ function BlockListBlockProvider( props ) { getBlockMode, isSelectionEnabled, getTemplateLock, + isSectionBlock: _isSectionBlock, getBlockWithoutAttributes, getBlockAttributes, canRemoveBlock, @@ -571,8 +572,6 @@ function BlockListBlockProvider( props ) { __unstableSelectionHasUnmergeableBlock, isBlockBeingDragged, isDragging, - hasBlockMovingClientId, - canInsertBlockType, __unstableHasActiveBlockOverlayActive, __unstableGetEditorMode, getSelectedBlocksInitialCaretPosition, @@ -632,7 +631,6 @@ function BlockListBlockProvider( props ) { clientId, checkDeep ); - const movingClientId = hasBlockMovingClientId(); const blockEditingMode = getBlockEditingMode( clientId ); const multiple = hasBlockSupport( blockName, 'multiple', true ); @@ -653,7 +651,7 @@ function BlockListBlockProvider( props ) { mode: getBlockMode( clientId ), isSelectionEnabled: isSelectionEnabled(), isLocked: !! getTemplateLock( rootClientId ), - templateLock: getTemplateLock( clientId ), + isSectionBlock: _isSectionBlock( clientId ), canRemove, canMove, isSelected: _isSelected, @@ -681,11 +679,9 @@ function BlockListBlockProvider( props ) { hasOverlay: __unstableHasActiveBlockOverlayActive( clientId ) && ! isDragging(), - initialPosition: - _isSelected && - ( editorMode === 'edit' || editorMode === 'zoom-out' ) // Don't recalculate the initialPosition when toggling in/out of zoom-out mode - ? getSelectedBlocksInitialCaretPosition() - : undefined, + initialPosition: _isSelected + ? getSelectedBlocksInitialCaretPosition() + : undefined, isHighlighted: isBlockHighlighted( clientId ), isMultiSelected, isPartiallySelected: @@ -694,13 +690,6 @@ function BlockListBlockProvider( props ) { ! __unstableSelectionHasUnmergeableBlock(), isDragging: isBlockBeingDragged( clientId ), hasChildSelected: isAncestorOfSelectedBlock, - isBlockMovingMode: !! movingClientId, - canInsertMovingBlock: - movingClientId && - canInsertBlockType( - getBlockName( movingClientId ), - rootClientId - ), isEditingDisabled: blockEditingMode === 'disabled', hasEditableOutline: blockEditingMode !== 'disabled' && @@ -745,9 +734,7 @@ function BlockListBlockProvider( props ) { isReusable, isDragging, hasChildSelected, - isBlockMovingMode, - canInsertMovingBlock, - templateLock, + isSectionBlock, isEditingDisabled, hasEditableOutline, className, @@ -792,9 +779,7 @@ function BlockListBlockProvider( props ) { isReusable, isDragging, hasChildSelected, - isBlockMovingMode, - canInsertMovingBlock, - templateLock, + isSectionBlock, isEditingDisabled, hasEditableOutline, isTemporarilyEditingAsBlocks, diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index 3f4b4c508aeb02..3e3865e689beac 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -80,7 +80,6 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b // since things like border-radius need to be able to be set on the block itself. .block-editor-block-list__block.is-highlighted, .block-editor-block-list__block.is-highlighted ~ .is-multi-selected, - &.is-navigate-mode .block-editor-block-list__block.is-selected, .block-editor-block-list__block:not([contenteditable="true"]):focus { outline: none; @@ -92,34 +91,6 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b } } - // Moving blocks using keyboard (Ellipsis > Move). - & .is-block-moving-mode.block-editor-block-list__block.is-selected { - - &::after { - content: ""; - position: absolute; - z-index: 0; - pointer-events: none; - transition: - border-color 0.1s linear, - border-style 0.1s linear, - box-shadow 0.1s linear; - right: 0; - left: 0; - top: -$default-block-margin * 0.5; - border-radius: $radius-small; - border-top: 4px solid $gray-400; - bottom: auto; - box-shadow: none; - } - } - - & .is-block-moving-mode.can-insert-moving-block.block-editor-block-list__block.is-selected { - &::after { - border-color: var(--wp-admin-theme-color); - } - } - // Ensure an accurate partial text selection. // To do this, we disable text selection on the main container, then re-enable it only on the // elements that actually get selected. @@ -134,14 +105,6 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b } } -.is-block-moving-mode.block-editor-block-list__block-selection-button { - // Should be invisible but not unfocusable. - opacity: 0; - font-size: 1px; - height: 1px; - padding: 0; -} - .block-editor-block-list__layout .block-editor-block-list__block { // With `position: static`, Safari marks a full-width selection rectangle, including margins. // With `position: relative`, Safari marks an inline selection rectangle, similar to that of @@ -223,19 +186,6 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b background-color: transparent; } - // Reusable blocks clickthrough overlays. - &.is-reusable > .block-editor-inner-blocks > .block-editor-block-list__layout.has-overlay { - // Remove only the top click overlay. - &::after { - display: none; - } - - // Restore it for subsequent. - .block-editor-block-list__layout.has-overlay::after { - display: block; - } - } - // Reusable blocks parent border. &.is-reusable.has-child-selected::after { box-shadow: 0 0 0 1px var(--wp-admin-theme-color); @@ -307,7 +257,7 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b } } -.is-root-container:not([inert]) .block-editor-block-list__block.is-reusable.is-selected .block-editor-block-list__block.has-editable-outline::after { +.is-root-container:not([inert]) .block-editor-block-list__block.is-selected .block-editor-block-list__block.has-editable-outline::after { animation-name: block-editor-is-editable__animation; animation-duration: 0.8s; animation-timing-function: ease-out; diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index ea6128f1534642..e2e019d4a9bf69 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -47,26 +47,17 @@ const pendingBlockVisibilityUpdatesPerRegistry = new WeakMap(); function Root( { className, ...settings } ) { const isLargeViewport = useViewportMatch( 'medium' ); - const { - isOutlineMode, - isFocusMode, - editorMode, - temporarilyEditingAsBlocks, - } = useSelect( ( select ) => { - const { - getSettings, - __unstableGetEditorMode, - getTemporarilyEditingAsBlocks, - isTyping, - } = unlock( select( blockEditorStore ) ); - const { outlineMode, focusMode } = getSettings(); - return { - isOutlineMode: outlineMode && ! isTyping(), - isFocusMode: focusMode, - editorMode: __unstableGetEditorMode(), - temporarilyEditingAsBlocks: getTemporarilyEditingAsBlocks(), - }; - }, [] ); + const { isOutlineMode, isFocusMode, temporarilyEditingAsBlocks } = + useSelect( ( select ) => { + const { getSettings, getTemporarilyEditingAsBlocks, isTyping } = + unlock( select( blockEditorStore ) ); + const { outlineMode, focusMode } = getSettings(); + return { + isOutlineMode: outlineMode && ! isTyping(), + isFocusMode: focusMode, + temporarilyEditingAsBlocks: getTemporarilyEditingAsBlocks(), + }; + }, [] ); const registry = useRegistry(); const { setBlockVisibility } = useDispatch( blockEditorStore ); @@ -115,7 +106,6 @@ function Root( { className, ...settings } ) { className: clsx( 'is-root-container', className, { 'is-outline-mode': isOutlineMode, 'is-focus-mode': isFocusMode && isLargeViewport, - 'is-navigate-mode': editorMode === 'navigation', } ), }, settings @@ -192,7 +182,8 @@ function Items( { getTemplateLock, getBlockEditingMode, __unstableGetEditorMode, - } = select( blockEditorStore ); + isSectionBlock, + } = unlock( select( blockEditorStore ) ); const _order = getBlockOrder( rootClientId ); @@ -211,15 +202,16 @@ function Items( { visibleBlocks: __unstableGetVisibleBlocks(), isZoomOut: __unstableGetEditorMode() === 'zoom-out', shouldRenderAppender: + ! isSectionBlock( rootClientId ) && + getBlockEditingMode( rootClientId ) !== 'disabled' && + ! getTemplateLock( rootClientId ) && hasAppender && __unstableGetEditorMode() !== 'zoom-out' && - ( hasCustomAppender - ? ! getTemplateLock( rootClientId ) && - getBlockEditingMode( rootClientId ) !== 'disabled' - : rootClientId === selectedBlockClientId || - ( ! rootClientId && - ! selectedBlockClientId && - ! _order.length ) ), + ( hasCustomAppender || + rootClientId === selectedBlockClientId || + ( ! rootClientId && + ! selectedBlockClientId && + ! _order.length ) ), }; }, [ rootClientId, hasAppender, hasCustomAppender ] diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index c3a279a618b5da..1cf1d4908b0768 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -25,7 +25,6 @@ import { } from '../../block-edit/context'; import { useFocusHandler } from './use-focus-handler'; import { useEventHandlers } from './use-selected-block-event-handlers'; -import { useNavModeExit } from './use-nav-mode-exit'; import { useZoomOutModeExit } from './use-zoom-out-mode-exit'; import { useBlockRefProvider } from './use-block-refs'; import { useIntersectionObserver } from './use-intersection-observer'; @@ -98,13 +97,11 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { isReusable, isDragging, hasChildSelected, - isBlockMovingMode, - canInsertMovingBlock, isEditingDisabled, hasEditableOutline, isTemporarilyEditingAsBlocks, defaultClassName, - templateLock, + isSectionBlock, } = useContext( PrivateBlockContext ); // translators: %s: Type of block (i.e. Text, Image etc) @@ -116,7 +113,6 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { useBlockRefProvider( clientId ), useFocusHandler( clientId ), useEventHandlers( { clientId, isSelected } ), - useNavModeExit( clientId ), useZoomOutModeExit( { editorMode } ), useIsHovered( { clientId } ), useIntersectionObserver(), @@ -124,7 +120,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { useDisabled( { isDisabled: ! hasOverlay } ), useFlashEditableBlocks( { clientId, - isEnabled: name === 'core/block' || templateLock === 'contentOnly', + isEnabled: isSectionBlock, } ), useScrollIntoView( { isSelected } ), ] ); @@ -182,8 +178,6 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { 'is-reusable': isReusable, 'is-dragging': isDragging, 'has-child-selected': hasChildSelected, - 'is-block-moving-mode': isBlockMovingMode, - 'can-insert-moving-block': canInsertMovingBlock, 'is-editing-disabled': isEditingDisabled, 'has-editable-outline': hasEditableOutline, 'has-negative-margin': hasNegativeMargin, diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-nav-mode-exit.js b/packages/block-editor/src/components/block-list/use-block-props/use-nav-mode-exit.js deleted file mode 100644 index aa9c0a630c5bd7..00000000000000 --- a/packages/block-editor/src/components/block-list/use-block-props/use-nav-mode-exit.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect, useDispatch } from '@wordpress/data'; -import { useRefEffect } from '@wordpress/compose'; - -/** - * Internal dependencies - */ -import { store as blockEditorStore } from '../../../store'; - -/** - * Allows navigation mode to be exited by clicking in the selected block. - * - * @param {string} clientId Block client ID. - */ -export function useNavModeExit( clientId ) { - const { isNavigationMode, isBlockSelected } = useSelect( blockEditorStore ); - const { setNavigationMode, selectBlock } = useDispatch( blockEditorStore ); - return useRefEffect( - ( node ) => { - function onMouseDown( event ) { - // Don't select a block if it's already handled by a child - // block. - if ( isNavigationMode() && ! event.defaultPrevented ) { - // Prevent focus from moving to the block. - event.preventDefault(); - - // When clicking on a selected block, exit navigation mode. - if ( isBlockSelected( clientId ) ) { - setNavigationMode( false ); - } else { - selectBlock( clientId ); - } - } - } - - node.addEventListener( 'mousedown', onMouseDown ); - - return () => { - node.removeEventListener( 'mousedown', onMouseDown ); - }; - }, - [ clientId, isNavigationMode, isBlockSelected, setNavigationMode ] - ); -} diff --git a/packages/block-editor/src/components/block-settings-menu-controls/index.js b/packages/block-editor/src/components/block-settings-menu-controls/index.js index 39063db4f52e02..4ebce4172e9b37 100644 --- a/packages/block-editor/src/components/block-settings-menu-controls/index.js +++ b/packages/block-editor/src/components/block-settings-menu-controls/index.js @@ -4,12 +4,9 @@ import { createSlotFill, MenuGroup, - MenuItem, __experimentalStyleProvider as StyleProvider, } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; -import { pipe } from '@wordpress/compose'; -import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -96,18 +93,6 @@ const BlockSettingsMenuControlsSlot = ( { fillProps, clientIds = null } ) => { /> ) } { fills } - { fillProps?.canMove && - ! fillProps?.onlyBlock && - ! isContentOnly && ( - <MenuItem - onClick={ pipe( - fillProps?.onClose, - fillProps?.onMoveTo - ) } - > - { __( 'Move to' ) } - </MenuItem> - ) } { selectedClientIds.length === 1 && ( <ModifyContentLockMenuItem clientId={ selectedClientIds[ 0 ] } diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index 069bd2c9ff1ee4..fff5acc7b79c46 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -58,7 +58,6 @@ export function BlockSettingsDropdown( { const firstBlockClientId = clientIds[ 0 ]; const { firstParentClientId, - onlyBlock, parentBlockType, previousBlockClientId, selectedBlockClientIds, @@ -67,7 +66,6 @@ export function BlockSettingsDropdown( { } = useSelect( ( select ) => { const { - getBlockCount, getBlockName, getBlockRootClientId, getPreviousBlockClientId, @@ -86,7 +84,6 @@ export function BlockSettingsDropdown( { return { firstParentClientId: _firstParentClientId, - onlyBlock: 1 === getBlockCount( _firstParentClientId ), parentBlockType: _firstParentClientId && ( getActiveBlockVariation( @@ -195,7 +192,6 @@ export function BlockSettingsDropdown( { canCopyStyles, canDuplicate, canInsertBlock, - canMove, canRemove, onDuplicate, onInsertAfter, @@ -203,7 +199,6 @@ export function BlockSettingsDropdown( { onRemove, onCopy, onPasteStyles, - onMoveTo, } ) => ( <DropdownMenu icon={ moreVertical } @@ -294,9 +289,6 @@ export function BlockSettingsDropdown( { <BlockSettingsMenuControls.Slot fillProps={ { onClose, - canMove, - onMoveTo, - onlyBlock, count, firstBlockClientId, } } diff --git a/packages/block-editor/src/components/block-tools/block-selection-button.js b/packages/block-editor/src/components/block-tools/block-selection-button.js deleted file mode 100644 index 9c6c22181ef2ac..00000000000000 --- a/packages/block-editor/src/components/block-tools/block-selection-button.js +++ /dev/null @@ -1,302 +0,0 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - -/** - * WordPress dependencies - */ -import { dragHandle } from '@wordpress/icons'; -import { Button, Flex, FlexItem } from '@wordpress/components'; -import { useSelect, useDispatch } from '@wordpress/data'; -import { forwardRef, useEffect } from '@wordpress/element'; -import { - BACKSPACE, - DELETE, - UP, - DOWN, - LEFT, - RIGHT, - TAB, - ESCAPE, - ENTER, - SPACE, -} from '@wordpress/keycodes'; -import { - __experimentalGetAccessibleBlockLabel as getAccessibleBlockLabel, - store as blocksStore, -} from '@wordpress/blocks'; -import { speak } from '@wordpress/a11y'; -import { focus } from '@wordpress/dom'; -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import BlockTitle from '../block-title'; -import BlockIcon from '../block-icon'; -import { store as blockEditorStore } from '../../store'; -import BlockDraggable from '../block-draggable'; -import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; - -/** - * Block selection button component, displaying the label of the block. If the block - * descends from a root block, a button is displayed enabling the user to select - * the root block. - * - * @param {string} props Component props. - * @param {string} props.clientId Client ID of block. - * @param {Object} ref Reference to the component. - * - * @return {Component} The component to be rendered. - */ -function BlockSelectionButton( { clientId, rootClientId }, ref ) { - const selected = useSelect( - ( select ) => { - const { - getBlock, - getBlockIndex, - hasBlockMovingClientId, - getBlockListSettings, - __unstableGetEditorMode, - getNextBlockClientId, - getPreviousBlockClientId, - canMoveBlock, - } = select( blockEditorStore ); - const { getActiveBlockVariation, getBlockType } = - select( blocksStore ); - const index = getBlockIndex( clientId ); - const { name, attributes } = getBlock( clientId ); - const blockType = getBlockType( name ); - const orientation = - getBlockListSettings( rootClientId )?.orientation; - const match = getActiveBlockVariation( name, attributes ); - - return { - blockMovingMode: hasBlockMovingClientId(), - editorMode: __unstableGetEditorMode(), - icon: match?.icon || blockType.icon, - label: getAccessibleBlockLabel( - blockType, - attributes, - index + 1, - orientation - ), - canMove: canMoveBlock( clientId, rootClientId ), - getNextBlockClientId, - getPreviousBlockClientId, - }; - }, - [ clientId, rootClientId ] - ); - const { label, icon, blockMovingMode, editorMode, canMove } = selected; - const { setNavigationMode, removeBlock } = useDispatch( blockEditorStore ); - - // Focus the breadcrumb in navigation mode. - useEffect( () => { - if ( editorMode === 'navigation' ) { - ref.current.focus(); - speak( label ); - } - }, [ label, editorMode ] ); - const blockElement = useBlockElement( clientId ); - - const { - hasBlockMovingClientId, - getBlockIndex, - getBlockRootClientId, - getClientIdsOfDescendants, - getSelectedBlockClientId, - getMultiSelectedBlocksEndClientId, - getPreviousBlockClientId, - getNextBlockClientId, - } = useSelect( blockEditorStore ); - const { - selectBlock, - clearSelectedBlock, - setBlockMovingClientId, - moveBlockToPosition, - } = useDispatch( blockEditorStore ); - - function onKeyDown( event ) { - const { keyCode } = event; - const isUp = keyCode === UP; - const isDown = keyCode === DOWN; - const isLeft = keyCode === LEFT; - const isRight = keyCode === RIGHT; - const isTab = keyCode === TAB; - const isEscape = keyCode === ESCAPE; - const isEnter = keyCode === ENTER; - const isSpace = keyCode === SPACE; - const isShift = event.shiftKey; - - if ( keyCode === BACKSPACE || keyCode === DELETE ) { - removeBlock( clientId ); - event.preventDefault(); - return; - } - - const selectedBlockClientId = getSelectedBlockClientId(); - const selectionEndClientId = getMultiSelectedBlocksEndClientId(); - const selectionBeforeEndClientId = getPreviousBlockClientId( - selectionEndClientId || selectedBlockClientId - ); - const selectionAfterEndClientId = getNextBlockClientId( - selectionEndClientId || selectedBlockClientId - ); - - const navigateUp = ( isTab && isShift ) || isUp; - const navigateDown = ( isTab && ! isShift ) || isDown; - // Move out of current nesting level (no effect if at root level). - const navigateOut = isLeft; - // Move into next nesting level (no effect if the current block has no innerBlocks). - const navigateIn = isRight; - - let focusedBlockUid; - if ( navigateUp ) { - focusedBlockUid = selectionBeforeEndClientId; - } else if ( navigateDown ) { - focusedBlockUid = selectionAfterEndClientId; - } else if ( navigateOut ) { - focusedBlockUid = - getBlockRootClientId( selectedBlockClientId ) ?? - selectedBlockClientId; - } else if ( navigateIn ) { - focusedBlockUid = - getClientIdsOfDescendants( selectedBlockClientId )[ 0 ] ?? - selectedBlockClientId; - } - const startingBlockClientId = hasBlockMovingClientId(); - if ( isEscape && startingBlockClientId && ! event.defaultPrevented ) { - setBlockMovingClientId( null ); - event.preventDefault(); - } - if ( ( isEnter || isSpace ) && startingBlockClientId ) { - const sourceRoot = getBlockRootClientId( startingBlockClientId ); - const destRoot = getBlockRootClientId( selectedBlockClientId ); - const sourceBlockIndex = getBlockIndex( startingBlockClientId ); - let destinationBlockIndex = getBlockIndex( selectedBlockClientId ); - if ( - sourceBlockIndex < destinationBlockIndex && - sourceRoot === destRoot - ) { - destinationBlockIndex -= 1; - } - moveBlockToPosition( - startingBlockClientId, - sourceRoot, - destRoot, - destinationBlockIndex - ); - selectBlock( startingBlockClientId ); - setBlockMovingClientId( null ); - } - // Prevent the block from being moved into itself. - if ( - startingBlockClientId && - selectedBlockClientId === startingBlockClientId && - navigateIn - ) { - return; - } - if ( navigateDown || navigateUp || navigateOut || navigateIn ) { - if ( focusedBlockUid ) { - event.preventDefault(); - selectBlock( focusedBlockUid ); - } else if ( isTab && selectedBlockClientId ) { - let nextTabbable; - - if ( navigateDown ) { - nextTabbable = blockElement; - do { - nextTabbable = focus.tabbable.findNext( nextTabbable ); - } while ( - nextTabbable && - blockElement.contains( nextTabbable ) - ); - - if ( ! nextTabbable ) { - nextTabbable = - blockElement.ownerDocument.defaultView.frameElement; - nextTabbable = focus.tabbable.findNext( nextTabbable ); - } - } else { - nextTabbable = focus.tabbable.findPrevious( blockElement ); - } - - if ( nextTabbable ) { - event.preventDefault(); - nextTabbable.focus(); - clearSelectedBlock(); - } - } - } - } - - const classNames = clsx( - 'block-editor-block-list__block-selection-button', - { - 'is-block-moving-mode': !! blockMovingMode, - } - ); - - const dragHandleLabel = __( 'Drag' ); - const showBlockDraggable = canMove && editorMode === 'navigation'; - - return ( - <div className={ classNames }> - <Flex - justify="center" - className="block-editor-block-list__block-selection-button__content" - > - <FlexItem> - <BlockIcon icon={ icon } showColors /> - </FlexItem> - { showBlockDraggable && ( - <FlexItem> - <BlockDraggable clientIds={ [ clientId ] }> - { ( draggableProps ) => ( - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - icon={ dragHandle } - className="block-selection-button_drag-handle" - label={ dragHandleLabel } - // Should not be able to tab to drag handle as this - // button can only be used with a pointer device. - tabIndex="-1" - { ...draggableProps } - /> - ) } - </BlockDraggable> - </FlexItem> - ) } - { editorMode === 'navigation' && ( - <FlexItem> - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - ref={ ref } - onClick={ - editorMode === 'navigation' - ? () => setNavigationMode( false ) - : undefined - } - onKeyDown={ onKeyDown } - label={ label } - showTooltip={ false } - className="block-selection-button_select-button" - > - <BlockTitle - clientId={ clientId } - maximumLength={ 35 } - /> - </Button> - </FlexItem> - ) } - </Flex> - </div> - ); -} - -export default forwardRef( BlockSelectionButton ); diff --git a/packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js b/packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js deleted file mode 100644 index ae03bdb4f51647..00000000000000 --- a/packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - -/** - * WordPress dependencies - */ -import { forwardRef } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import BlockSelectionButton from './block-selection-button'; -import { PrivateBlockPopover } from '../block-popover'; -import useBlockToolbarPopoverProps from './use-block-toolbar-popover-props'; -import useSelectedBlockToolProps from './use-selected-block-tool-props'; - -function BlockToolbarBreadcrumb( { clientId, __unstableContentRef }, ref ) { - const { - capturingClientId, - isInsertionPointVisible, - lastClientId, - rootClientId, - } = useSelectedBlockToolProps( clientId ); - - const popoverProps = useBlockToolbarPopoverProps( { - contentElement: __unstableContentRef?.current, - clientId, - } ); - - return ( - <PrivateBlockPopover - clientId={ capturingClientId || clientId } - bottomClientId={ lastClientId } - className={ clsx( 'block-editor-block-list__block-popover', { - 'is-insertion-point-visible': isInsertionPointVisible, - } ) } - resize={ false } - { ...popoverProps } - > - <BlockSelectionButton - ref={ ref } - clientId={ clientId } - rootClientId={ rootClientId } - /> - </PrivateBlockPopover> - ); -} - -export default forwardRef( BlockToolbarBreadcrumb ); diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 24f60dbbf970aa..099323925384b8 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -19,7 +19,6 @@ import { default as InsertionPoint, } from './insertion-point'; import BlockToolbarPopover from './block-toolbar-popover'; -import BlockToolbarBreadcrumb from './block-toolbar-breadcrumb'; import ZoomOutPopover from './zoom-out-popover'; import { store as blockEditorStore } from '../../store'; import usePopoverScroll from '../block-popover/use-popover-scroll'; @@ -78,7 +77,6 @@ export default function BlockTools( { const { getGroupingBlockName } = useSelect( blocksStore ); const { showEmptyBlockSideInserter, - showBreadcrumb, showBlockToolbarPopover, showZoomOutToolbar, } = useShowBlockTools(); @@ -223,14 +221,6 @@ export default function BlockTools( { /> ) } - { showBreadcrumb && ( - <BlockToolbarBreadcrumb - ref={ blockSelectionButtonRef } - __unstableContentRef={ __unstableContentRef } - clientId={ clientId } - /> - ) } - { showZoomOutToolbar && ( <ZoomOutPopover __unstableContentRef={ __unstableContentRef } 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 469f7e53908cb4..891a32eaa5dc9c 100644 --- a/packages/block-editor/src/components/block-tools/insertion-point.js +++ b/packages/block-editor/src/components/block-tools/insertion-point.js @@ -37,7 +37,6 @@ function InbetweenInsertionPointPopover( { rootClientId, isInserterShown, isDistractionFree, - isNavigationMode, isZoomOutMode, } = useSelect( ( select ) => { const { @@ -48,7 +47,6 @@ function InbetweenInsertionPointPopover( { getPreviousBlockClientId, getNextBlockClientId, getSettings, - isNavigationMode: _isNavigationMode, __unstableGetEditorMode, } = select( blockEditorStore ); const insertionPoint = getBlockInsertionPoint(); @@ -78,7 +76,6 @@ function InbetweenInsertionPointPopover( { getBlockListSettings( insertionPoint.rootClientId ) ?.orientation || 'vertical', rootClientId: insertionPoint.rootClientId, - isNavigationMode: _isNavigationMode(), isDistractionFree: settings.isDistractionFree, isInserterShown: insertionPoint?.__unstableWithInserter, isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', @@ -144,7 +141,7 @@ function InbetweenInsertionPointPopover( { }, }; - if ( isDistractionFree && ! isNavigationMode ) { + if ( isDistractionFree ) { return null; } diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index 9f1325d7f95a1a..a3d9153273e983 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -84,84 +84,6 @@ } } -/** - * Block Label for Navigation/Selection Mode - */ - -.block-editor-block-list__block-selection-button { - display: inline-flex; - padding: 0 $grid-unit-15; - z-index: z-index(".block-editor-block-list__block-selection-button"); - - // Dark block UI appearance. - border-radius: $radius-small; - background-color: $gray-900; - - font-size: $default-font-size; - height: $block-toolbar-height; - - .block-editor-block-list__block-selection-button__content { - margin: auto; - display: inline-flex; - align-items: center; - - > .components-flex__item { - margin-right: $grid-unit-15 * 0.5; - } - } - .components-button.has-icon.block-selection-button_drag-handle { - cursor: grab; - padding: 0; - height: $grid-unit-30; - min-width: $grid-unit-30; - margin-left: -2px; - - // Drag handle is smaller than the others. - svg { - min-width: 18px; - min-height: 18px; - } - } - - .block-editor-block-icon { - font-size: $default-font-size; - color: $white; - height: $block-toolbar-height; - } - - // The button here has a special style to appear as a toolbar. - .components-button { - min-width: $button-size; - color: $white; - height: $block-toolbar-height; - - // When button is focused, it receives a box-shadow instead of the border. - &:focus { - box-shadow: none; - border: none; - } - - &:active { - color: $white; - } - - // Make sure the button has no hover style when it's disabled. - &[aria-disabled="true"]:hover { - color: $white; - } - - display: flex; - } - .block-selection-button_select-button.components-button { - padding: 0; - } - - .block-editor-block-mover { - background: unset; - border: none; - } -} - // Hide the popover block editor list while dragging. // Using a hacky animation to delay hiding the element. // It's needed because if we hide the element immediately upon dragging, @@ -178,14 +100,10 @@ .components-popover.block-editor-block-list__block-popover { // Position the block toolbar. - .block-editor-block-list__block-selection-button, .block-editor-block-contextual-toolbar { pointer-events: all; margin-top: $grid-unit-10; margin-bottom: $grid-unit-10; - } - - .block-editor-block-contextual-toolbar { border: $border-width solid $gray-900; border-radius: $radius-small; overflow: visible; // allow the parent selector to be visible diff --git a/packages/block-editor/src/components/block-tools/use-show-block-tools.js b/packages/block-editor/src/components/block-tools/use-show-block-tools.js index 07e0ebd16a64b0..02a8f0583bcddf 100644 --- a/packages/block-editor/src/components/block-tools/use-show-block-tools.js +++ b/packages/block-editor/src/components/block-tools/use-show-block-tools.js @@ -22,7 +22,6 @@ export function useShowBlockTools() { getBlock, getBlockMode, getSettings, - hasMultiSelection, __unstableGetEditorMode, isTyping, } = select( blockEditorStore ); @@ -42,29 +41,20 @@ export function useShowBlockTools() { ! isTyping() && editorMode === 'edit' && isEmptyDefaultBlock; - const maybeShowBreadcrumb = - hasSelectedBlock && - ! hasMultiSelection() && - editorMode === 'navigation'; - const isZoomOut = editorMode === 'zoom-out'; const _showZoomOutToolbar = isZoomOut && block?.attributes?.align === 'full' && - ! _showEmptyBlockSideInserter && - ! maybeShowBreadcrumb; + ! _showEmptyBlockSideInserter; const _showBlockToolbarPopover = ! _showZoomOutToolbar && ! getSettings().hasFixedToolbar && ! _showEmptyBlockSideInserter && hasSelectedBlock && - ! isEmptyDefaultBlock && - ! maybeShowBreadcrumb; + ! isEmptyDefaultBlock; return { showEmptyBlockSideInserter: _showEmptyBlockSideInserter, - showBreadcrumb: - ! _showEmptyBlockSideInserter && maybeShowBreadcrumb, showBlockToolbarPopover: _showBlockToolbarPopover, showZoomOutToolbar: _showZoomOutToolbar, }; diff --git a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js index a3c46c4b4c970a..560bfc6ebb58d6 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js @@ -1,8 +1,3 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - /** * WordPress dependencies */ @@ -26,7 +21,6 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { ( select ) => { const { getBlock, - hasBlockMovingClientId, getNextBlockClientId, getPreviousBlockClientId, canRemoveBlock, @@ -62,7 +56,6 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { } return { - blockMovingMode: hasBlockMovingClientId(), isBlockTemplatePart, isNextBlockTemplatePart, isPrevBlockTemplatePart, @@ -75,7 +68,6 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { ); const { - blockMovingMode, isBlockTemplatePart, isNextBlockTemplatePart, isPrevBlockTemplatePart, @@ -87,15 +79,11 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { const { removeBlock, __unstableSetEditorMode } = useDispatch( blockEditorStore ); - const classNames = clsx( 'zoom-out-toolbar', { - 'is-block-moving-mode': !! blockMovingMode, - } ); - const showBlockDraggable = canMove && ! isBlockTemplatePart; return ( <NavigableToolbar - className={ classNames } + className="zoom-out-toolbar" /* translators: accessibility text for the block toolbar */ aria-label={ __( 'Block tools' ) } // The variant is applied as "toolbar" when undefined, which is the black border style of the dropdown from the toolbar popover. diff --git a/packages/block-editor/src/components/inner-blocks/content.scss b/packages/block-editor/src/components/inner-blocks/content.scss deleted file mode 100644 index 05259ede35daaa..00000000000000 --- a/packages/block-editor/src/components/inner-blocks/content.scss +++ /dev/null @@ -1,13 +0,0 @@ -// Add clickable overlay to blocks with nesting. -// This makes it easy to select all layers of the block. -.block-editor-block-list__layout.has-overlay { - &::after { - content: ""; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: z-index(".block-editor-block-list__layout.has-overlay::after"); - } -} diff --git a/packages/block-editor/src/components/inner-blocks/index.js b/packages/block-editor/src/components/inner-blocks/index.js index 0d35b459190fef..1583031a8ea18d 100644 --- a/packages/block-editor/src/components/inner-blocks/index.js +++ b/packages/block-editor/src/components/inner-blocks/index.js @@ -195,14 +195,11 @@ export function useInnerBlocksProps( props = {}, options = {} ) { ( select ) => { const { getBlockName, - isBlockSelected, - hasSelectedInnerBlock, __unstableGetEditorMode, getTemplateLock, getBlockRootClientId, getBlockEditingMode, getBlockSettings, - isDragging, getSectionRootClientId, } = unlock( select( blockEditorStore ) ); let _isDropZoneDisabled; @@ -213,8 +210,6 @@ export function useInnerBlocksProps( props = {}, options = {} ) { const { hasBlockSupport, getBlockType } = select( blocksStore ); const blockName = getBlockName( clientId ); - const enableClickThrough = - __unstableGetEditorMode() === 'navigation'; const blockEditingMode = getBlockEditingMode( clientId ); const parentClientId = getBlockRootClientId( clientId ); const [ defaultLayout ] = getBlockSettings( clientId, 'layout' ); @@ -236,12 +231,6 @@ export function useInnerBlocksProps( props = {}, options = {} ) { '__experimentalExposeControlsToChildren', false ), - hasOverlay: - blockName !== 'core/template' && - ! isBlockSelected( clientId ) && - ! hasSelectedInnerBlock( clientId, true ) && - enableClickThrough && - ! isDragging(), name: blockName, blockType: getBlockType( blockName ), parentLock: getTemplateLock( parentClientId ), @@ -254,7 +243,6 @@ export function useInnerBlocksProps( props = {}, options = {} ) { ); const { __experimentalCaptureToolbars, - hasOverlay, name, blockType, parentLock, @@ -299,10 +287,7 @@ export function useInnerBlocksProps( props = {}, options = {} ) { className: clsx( props.className, 'block-editor-block-list__layout', - __unstableDisableLayoutClassNames ? '' : layoutClassNames, - { - 'has-overlay': hasOverlay, - } + __unstableDisableLayoutClassNames ? '' : layoutClassNames ), children: clientId ? ( <InnerBlocks { ...innerBlocksProps } clientId={ clientId } /> diff --git a/packages/block-editor/src/components/list-view/block-contents.js b/packages/block-editor/src/components/list-view/block-contents.js index 91bfbd7eddaa03..0ed2b162b127b8 100644 --- a/packages/block-editor/src/components/list-view/block-contents.js +++ b/packages/block-editor/src/components/list-view/block-contents.js @@ -1,12 +1,6 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - /** * WordPress dependencies */ -import { useSelect } from '@wordpress/data'; import { forwardRef } from '@wordpress/element'; /** @@ -14,7 +8,6 @@ import { forwardRef } from '@wordpress/element'; */ import ListViewBlockSelectButton from './block-select-button'; import BlockDraggable from '../block-draggable'; -import { store as blockEditorStore } from '../../store'; import { useListViewContext } from './context'; const ListViewBlockContents = forwardRef( @@ -34,29 +27,9 @@ const ListViewBlockContents = forwardRef( ref ) => { const { clientId } = block; - - const { blockMovingClientId, selectedBlockInBlockEditor } = useSelect( - ( select ) => { - const { hasBlockMovingClientId, getSelectedBlockClientId } = - select( blockEditorStore ); - return { - blockMovingClientId: hasBlockMovingClientId(), - selectedBlockInBlockEditor: getSelectedBlockClientId(), - }; - }, - [] - ); - const { AdditionalBlockContent, insertedBlock, setInsertedBlock } = useListViewContext(); - const isBlockMoveTarget = - blockMovingClientId && selectedBlockInBlockEditor === clientId; - - const className = clsx( 'block-editor-list-view-block-contents', { - 'is-dropping-before': isBlockMoveTarget, - } ); - // Only include all selected blocks if the currently clicked on block // is one of the selected blocks. This ensures that if a user attempts // to drag a block that isn't part of the selection, they're still able @@ -82,7 +55,7 @@ const ListViewBlockContents = forwardRef( { ( { draggable, onDragStart, onDragEnd } ) => ( <ListViewBlockSelectButton ref={ ref } - className={ className } + className="block-editor-list-view-block-contents" block={ block } onClick={ onClick } onToggleExpanded={ onToggleExpanded } diff --git a/packages/block-editor/src/components/list-view/style.scss b/packages/block-editor/src/components/list-view/style.scss index 05a04abfd110b4..3ad6d3bd4aab51 100644 --- a/packages/block-editor/src/components/list-view/style.scss +++ b/packages/block-editor/src/components/list-view/style.scss @@ -217,20 +217,6 @@ position: relative; white-space: nowrap; - &.is-dropping-before::before { - content: ""; - position: absolute; - pointer-events: none; - transition: - border-color 0.1s linear, - border-style 0.1s linear, - box-shadow 0.1s linear; - top: -2px; - right: 0; - left: 0; - border-top: 4px solid var(--wp-admin-theme-color); - } - .components-modal__content & { padding-left: 0; padding-right: 0; diff --git a/packages/block-editor/src/components/tool-selector/index.js b/packages/block-editor/src/components/tool-selector/index.js index 4ec777a911cc73..bf55c78caf489a 100644 --- a/packages/block-editor/src/components/tool-selector/index.js +++ b/packages/block-editor/src/components/tool-selector/index.js @@ -45,7 +45,7 @@ function ToolSelector( props, ref ) { __next40pxDefaultSize={ false } { ...props } ref={ ref } - icon={ mode === 'navigation' ? selectIcon : editIcon } + icon={ mode === 'navigation' ? editIcon : selectIcon } aria-expanded={ isOpen } aria-haspopup="true" onClick={ onToggle } @@ -56,7 +56,11 @@ function ToolSelector( props, ref ) { popoverProps={ { placement: 'bottom-start' } } renderContent={ () => ( <> - <NavigableMenu role="menu" aria-label={ __( 'Tools' ) }> + <NavigableMenu + className="block-editor-tool-selector__menu" + role="menu" + aria-label={ __( 'Tools' ) } + > <MenuItemsChoice value={ mode === 'navigation' ? 'navigation' : 'edit' @@ -67,19 +71,23 @@ function ToolSelector( props, ref ) { value: 'edit', label: ( <> - <Icon icon={ editIcon } /> - { __( 'Edit' ) } + { selectIcon } + { __( 'Design' ) } </> ), + info: __( + 'Full control over layout and styling.' + ), }, { value: 'navigation', label: ( <> - { selectIcon } - { __( 'Select' ) } + <Icon icon={ editIcon } /> + { __( 'Edit' ) } </> ), + info: __( 'Focus on content.' ), }, ] } /> diff --git a/packages/block-editor/src/components/tool-selector/style.scss b/packages/block-editor/src/components/tool-selector/style.scss index 03774fe0f6b9d3..07ca91d346d907 100644 --- a/packages/block-editor/src/components/tool-selector/style.scss +++ b/packages/block-editor/src/components/tool-selector/style.scss @@ -8,3 +8,8 @@ color: $gray-700; min-width: 280px; } + +.block-editor-tool-selector__menu .components-menu-item__info { + margin-left: $grid-unit-30 + $grid-unit-15; // icon size + margin + text-align: left; +} diff --git a/packages/block-editor/src/components/use-block-commands/index.js b/packages/block-editor/src/components/use-block-commands/index.js index 8a09999ecdff3c..c88ec4e5378926 100644 --- a/packages/block-editor/src/components/use-block-commands/index.js +++ b/packages/block-editor/src/components/use-block-commands/index.js @@ -16,7 +16,6 @@ import { plus as add, group, ungroup, - moveTo as move, } from '@wordpress/icons'; /** @@ -127,59 +126,6 @@ export const useTransformCommands = () => { return { isLoading: false, commands }; }; -const useActionsCommands = () => { - const { clientIds } = useSelect( ( select ) => { - const { getSelectedBlockClientIds } = select( blockEditorStore ); - const selectedBlockClientIds = getSelectedBlockClientIds(); - - return { - clientIds: selectedBlockClientIds, - }; - }, [] ); - - const { getBlockRootClientId, canMoveBlocks, getBlockCount } = - useSelect( blockEditorStore ); - - const { setBlockMovingClientId, setNavigationMode, selectBlock } = - useDispatch( blockEditorStore ); - - if ( ! clientIds || clientIds.length < 1 ) { - return { isLoading: false, commands: [] }; - } - - const rootClientId = getBlockRootClientId( clientIds[ 0 ] ); - - const canMove = - canMoveBlocks( clientIds ) && getBlockCount( rootClientId ) !== 1; - - const commands = []; - - if ( canMove ) { - commands.push( { - name: 'move-to', - label: __( 'Move to' ), - callback: () => { - setNavigationMode( true ); - selectBlock( clientIds[ 0 ] ); - setBlockMovingClientId( clientIds[ 0 ] ); - }, - icon: move, - } ); - } - - return { - isLoading: false, - commands: commands.map( ( command ) => ( { - ...command, - name: 'core/block-editor/action-' + command.name, - callback: ( { close } ) => { - command.callback(); - close(); - }, - } ) ), - }; -}; - const useQuickActionsCommands = () => { const { clientIds, isUngroupable, isGroupable } = useSelect( ( select ) => { const { @@ -344,10 +290,6 @@ export const useBlockCommands = () => { name: 'core/block-editor/blockTransforms', hook: useTransformCommands, } ); - useCommandLoader( { - name: 'core/block-editor/blockActions', - hook: useActionsCommands, - } ); useCommandLoader( { name: 'core/block-editor/blockQuickActions', hook: useQuickActionsCommands, diff --git a/packages/block-editor/src/components/writing-flow/use-tab-nav.js b/packages/block-editor/src/components/writing-flow/use-tab-nav.js index b321d7c8d29957..3788c7021fd664 100644 --- a/packages/block-editor/src/components/writing-flow/use-tab-nav.js +++ b/packages/block-editor/src/components/writing-flow/use-tab-nav.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { focus, isFormElement } from '@wordpress/dom'; -import { TAB, ESCAPE } from '@wordpress/keycodes'; +import { TAB } from '@wordpress/keycodes'; import { useSelect, useDispatch } from '@wordpress/data'; import { useRefEffect, useMergeRefs } from '@wordpress/compose'; import { useRef } from '@wordpress/element'; @@ -21,19 +21,9 @@ export default function useTabNav() { const { hasMultiSelection, getSelectedBlockClientId, getBlockCount } = useSelect( blockEditorStore ); - const { setNavigationMode, setLastFocus } = unlock( - useDispatch( blockEditorStore ) - ); - const isNavigationMode = useSelect( - ( select ) => select( blockEditorStore ).isNavigationMode(), - [] - ); - + const { setLastFocus } = unlock( useDispatch( blockEditorStore ) ); const { getLastFocus } = unlock( useSelect( blockEditorStore ) ); - // Don't allow tabbing to this element in Navigation mode. - const focusCaptureTabIndex = ! isNavigationMode ? '0' : undefined; - // Reference that holds the a flag for enabling or disabling // capturing on the focus capture elements. const noCaptureRef = useRef(); @@ -56,8 +46,6 @@ export default function useTabNav() { .focus(); } } else { - setNavigationMode( true ); - const canvasElement = container.current.ownerDocument === event.target.ownerDocument ? container.current @@ -82,7 +70,7 @@ export default function useTabNav() { const before = ( <div ref={ focusCaptureBeforeRef } - tabIndex={ focusCaptureTabIndex } + tabIndex="0" onFocus={ onFocusCapture } /> ); @@ -90,7 +78,7 @@ export default function useTabNav() { const after = ( <div ref={ focusCaptureAfterRef } - tabIndex={ focusCaptureTabIndex } + tabIndex="0" onFocus={ onFocusCapture } /> ); @@ -101,12 +89,6 @@ export default function useTabNav() { return; } - if ( event.keyCode === ESCAPE && ! hasMultiSelection() ) { - event.preventDefault(); - setNavigationMode( true ); - return; - } - // In Edit mode, Tab should focus the first tabbable element after // the content, which is normally the sidebar (with block controls) // and Shift+Tab should focus the first tabbable element before the @@ -119,20 +101,6 @@ export default function useTabNav() { const isShift = event.shiftKey; const direction = isShift ? 'findPrevious' : 'findNext'; - - if ( ! hasMultiSelection() && ! getSelectedBlockClientId() ) { - // Preserve the behaviour of entering navigation mode when - // tabbing into the content without a block selection. - // `onFocusCapture` already did this previously, but we need to - // do it again here because after clearing block selection, - // focus land on the writing flow container and pressing Tab - // will no longer send focus through the focus capture element. - if ( event.target === node ) { - setNavigationMode( true ); - } - return; - } - const nextTabbable = focus.tabbable[ direction ]( event.target ); // We want to constrain the tabbing to the block and its child blocks. diff --git a/packages/block-editor/src/content.scss b/packages/block-editor/src/content.scss index 36d428dca6b762..1ef4e118fb1bbe 100644 --- a/packages/block-editor/src/content.scss +++ b/packages/block-editor/src/content.scss @@ -8,7 +8,6 @@ @import "./components/button-block-appender/content.scss"; @import "./components/default-block-appender/content.scss"; @import "./components/iframe/content.scss"; -@import "./components/inner-blocks/content.scss"; @import "./components/media-placeholder/content.scss"; @import "./components/plain-text/content.scss"; @import "./components/rich-text/content.scss"; diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index e91f997ca67837..ee11838395ec5c 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1728,23 +1728,24 @@ export const __unstableSetEditorMode = }; /** - * Action that enables or disables the block moving mode. + * Set the block moving client ID. * - * @param {string|null} hasBlockMovingClientId Enable/Disable block moving mode. + * @deprecated + * + * @return {Object} Action object. */ -export const setBlockMovingClientId = - ( hasBlockMovingClientId = null ) => - ( { dispatch } ) => { - dispatch( { type: 'SET_BLOCK_MOVING_MODE', hasBlockMovingClientId } ); - - if ( hasBlockMovingClientId ) { - speak( - __( - 'Use the Tab key and Arrow keys to choose new block location. Use Left and Right Arrow keys to move between nesting levels. Once location is selected press Enter or Space to move the block.' - ) - ); +export function setBlockMovingClientId() { + deprecated( + 'wp.data.dispatch( "core/block-editor" ).setBlockMovingClientId', + { + since: '6.7', + hint: 'Block moving mode feature has been removed', } + ); + return { + type: 'DO_NOTHING', }; +} /** * Action that duplicates a list of blocks. diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 01ad8f69febc9e..0e77e8e2ed433d 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -15,6 +15,7 @@ import { getBlockName, getTemplateLock, getClientIdsWithDescendants, + isNavigationMode, } from './selectors'; import { checkAllowListRecursive, @@ -479,19 +480,74 @@ export const getContentLockingParent = createSelector( ( state, clientId ) => { let current = clientId; let result; - while ( ( current = state.blocks.parents.get( current ) ) ) { - if ( - getBlockName( state, current ) === 'core/block' || - getTemplateLock( state, current ) === 'contentOnly' - ) { + while ( + ! result && + ( current = state.blocks.parents.get( current ) ) + ) { + if ( getTemplateLock( state, current ) === 'contentOnly' ) { result = current; } } return result; }, - ( state ) => [ state.blocks.parents, state.blockListSettings ] + ( state ) => [ + state.blocks.parents, + state.blockListSettings, + state.settings.templateLock, + ] ); +/** + * Retrieves the client ID of the parent section block. + * + * @param {Object} state Global application state. + * @param {Object} clientId Client Id of the block. + * + * @return {?string} Client ID of the ancestor block that is content locking the block. + */ +export const getParentSectionBlock = createSelector( + ( state, clientId ) => { + let current = clientId; + let result; + while ( + ! result && + ( current = state.blocks.parents.get( current ) ) + ) { + if ( isSectionBlock( state, current ) ) { + result = current; + } + } + return result; + }, + ( state ) => [ + state.blocks.parents, + state.blocks.order, + state.blockListSettings, + state.editorMode, + state.settings.templateLock, + state.blocks.byClientId, + getSectionRootClientId( state ), + ] +); + +/** + * Retrieves the client ID is a content locking parent + * + * @param {Object} state Global application state. + * @param {Object} clientId Client Id of the block. + * + * @return {boolean} Whether the block is a content locking parent. + */ +export function isSectionBlock( state, clientId ) { + const sectionRootClientId = getSectionRootClientId( state ); + const sectionClientIds = getBlockOrder( state, sectionRootClientId ); + return ( + getBlockName( state, clientId ) === 'core/block' || + getTemplateLock( state, clientId ) === 'contentOnly' || + ( isNavigationMode( state ) && sectionClientIds.includes( clientId ) ) + ); +} + /** * Retrieves the client ID of the block that is content locked but is * currently being temporarily edited as a non-locked block. diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index cd4569c45e5801..3a99d18ef17ee3 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1795,11 +1795,6 @@ export const blockListSettings = ( state = {}, action ) => { * @return {string} Updated state. */ export function editorMode( state = 'edit', action ) { - // Let inserting block in navigation mode always trigger Edit mode. - if ( action.type === 'INSERT_BLOCKS' && state === 'navigation' ) { - return 'edit'; - } - if ( action.type === 'SET_EDITOR_MODE' ) { return action.mode; } @@ -1807,26 +1802,6 @@ export function editorMode( state = 'edit', action ) { return state; } -/** - * Reducer returning whether the block moving mode is enabled or not. - * - * @param {string|null} state Current state. - * @param {Object} action Dispatched action. - * - * @return {string|null} Updated state. - */ -export function hasBlockMovingClientId( state = null, action ) { - if ( action.type === 'SET_BLOCK_MOVING_MODE' ) { - return action.hasBlockMovingClientId; - } - - if ( action.type === 'SET_EDITOR_MODE' ) { - return null; - } - - return state; -} - /** * Reducer return an updated state representing the most recent block attribute * update. The state is structured as an object where the keys represent the @@ -2104,7 +2079,6 @@ const combinedReducers = combineReducers( { lastBlockAttributesChange, lastFocus, editorMode, - hasBlockMovingClientId, expandedBlock, highlightedBlock, lastBlockInserted, diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 5780b2afe2a672..806e2b5f5993eb 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -38,6 +38,8 @@ import { getTemporarilyEditingAsBlocks, getTemporarilyEditingFocusModeToRevert, getSectionRootClientId, + isSectionBlock, + getParentSectionBlock, } from './private-selectors'; /** @@ -1582,6 +1584,11 @@ const canInsertBlockTypeUnmemoized = ( return false; } + const _isSectionBlock = !! isSectionBlock( state, rootClientId ); + if ( _isSectionBlock ) { + return false; + } + if ( getBlockEditingMode( state, rootClientId ?? '' ) === 'disabled' ) { return false; } @@ -1733,6 +1740,11 @@ export function canRemoveBlock( state, clientId ) { return false; } + const isBlockWithinSection = !! getParentSectionBlock( state, clientId ); + if ( isBlockWithinSection ) { + return false; + } + return getBlockEditingMode( state, rootClientId ) !== 'disabled'; } @@ -2674,12 +2686,17 @@ export function __unstableGetEditorMode( state ) { /** * Returns whether block moving mode is enabled. * - * @param {Object} state Editor state. - * - * @return {string} Client Id of moving block. + * @deprecated */ -export function hasBlockMovingClientId( state ) { - return state.hasBlockMovingClientId; +export function hasBlockMovingClientId() { + deprecated( + 'wp.data.select( "core/block-editor" ).hasBlockMovingClientId', + { + since: '6.7', + hint: 'Block moving mode feature has been removed', + } + ); + return false; } /** @@ -2862,11 +2879,9 @@ export function __unstableHasActiveBlockOverlayActive( state, clientId ) { '__experimentalDisableBlockOverlay', false ); - const shouldEnableIfUnselected = - editorMode === 'navigation' || - ( blockSupportDisable - ? false - : areInnerBlocksControlled( state, clientId ) ); + const shouldEnableIfUnselected = blockSupportDisable + ? false + : areInnerBlocksControlled( state, clientId ); return ( shouldEnableIfUnselected && @@ -2960,9 +2975,29 @@ export const getBlockEditingMode = createRegistrySelector( if ( ! clientId ) { return 'default'; } + const sectionRootClientId = getSectionRootClientId( state ); + if ( + editorMode === 'navigation' && + clientId === sectionRootClientId + ) { + return 'default'; + } + const sectionsClientIds = getBlockOrder( + state, + sectionRootClientId + ); const rootClientId = getBlockRootClientId( state, clientId ); const templateLock = getTemplateLock( state, rootClientId ); - if ( templateLock === 'contentOnly' ) { + if ( + templateLock === 'contentOnly' || + editorMode === 'navigation' + ) { + // Sections should always be contentOnly in navigation mode. + // This will also cause them to display in List View providing + // a structure. + if ( sectionsClientIds.includes( clientId ) ) { + return 'contentOnly'; + } const name = getBlockName( state, clientId ); const isContent = select( blocksStore ).__experimentalHasContentRoleAttribute( diff --git a/packages/block-editor/src/store/test/private-selectors.js b/packages/block-editor/src/store/test/private-selectors.js index 45432b750bb9eb..5f427e79cf6999 100644 --- a/packages/block-editor/src/store/test/private-selectors.js +++ b/packages/block-editor/src/store/test/private-selectors.js @@ -394,6 +394,10 @@ describe( 'private selectors', () => { parents: new Map( [ [ '6cf70164-9097-4460-bcbf-200560546988', '' ], ] ), + order: new Map( [ + [ '6cf70164-9097-4460-bcbf-200560546988', [] ], + [ '', [ '6cf70164-9097-4460-bcbf-200560546988' ] ], + ] ), }, blockEditingModes: new Map(), }; @@ -424,6 +428,21 @@ describe( 'private selectors', () => { 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', ], ] ), + + order: new Map( [ + [ + 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', + [ + '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', + 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', + ], + ], + [ + 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', + [ '4c2b7140-fffd-44b4-b2a7-820c670a6514' ], + ], + [ '', [ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337' ] ], + ] ), }, blockEditingModes: new Map( [ [ '', 'disabled' ], @@ -461,6 +480,21 @@ describe( 'private selectors', () => { 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', ], ] ), + order: new Map( [ + [ + 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', + [ '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f' ], + ], + [ + '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', + [ 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c' ], + ], + [ + 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', + [ '4c2b7140-fffd-44b4-b2a7-820c670a6514' ], + ], + [ '', [ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337' ] ], + ] ), }, blockEditingModes: new Map( [ [ '', 'disabled' ], diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index 85006621c4701e..04899a9ee243fd 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -2694,6 +2694,7 @@ describe( 'selectors', () => { byClientId: new Map(), attributes: new Map(), parents: new Map(), + order: new Map(), }, blockListSettings: {}, settings: { @@ -2711,6 +2712,7 @@ describe( 'selectors', () => { blocks: { byClientId: new Map(), attributes: new Map(), + order: new Map(), }, blockListSettings: {}, settings: { @@ -2728,6 +2730,7 @@ describe( 'selectors', () => { byClientId: new Map(), attributes: new Map(), parents: new Map(), + order: new Map(), }, blockListSettings: {}, settings: {}, @@ -2748,6 +2751,7 @@ describe( 'selectors', () => { byClientId: new Map(), attributes: new Map(), parents: new Map(), + order: new Map(), }, blockListSettings: {}, settings: {}, @@ -2772,6 +2776,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: {}, settings: {}, @@ -2796,6 +2801,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: { block1: {}, @@ -2822,6 +2828,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: { block1: {}, @@ -2848,6 +2855,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: { block1: { @@ -2876,6 +2884,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: { block1: { @@ -2904,6 +2913,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: {}, settings: {}, @@ -2932,6 +2942,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: { block1: { @@ -2960,6 +2971,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: {}, settings: {}, @@ -2976,6 +2988,7 @@ describe( 'selectors', () => { byClientId: new Map(), attributes: new Map(), parents: new Map(), + order: new Map(), }, blockListSettings: {}, settings: {}, @@ -2992,7 +3005,7 @@ describe( 'selectors', () => { byClientId: new Map( Object.entries( { block1: { name: 'core/test-block-ancestor' }, - block2: { name: 'core/block' }, + block2: { name: 'core/block1' }, } ) ), attributes: new Map( @@ -3006,6 +3019,10 @@ describe( 'selectors', () => { block2: 'block1', } ) ), + order: new Map( [ + [ '', [ 'block1' ] ], + [ 'block1', [ 'block2' ] ], + ] ), }, blockListSettings: { block1: {}, @@ -3023,6 +3040,37 @@ describe( 'selectors', () => { ).toBe( true ); } ); + it( 'should prevent blocks from being inserted within sections', () => { + const state = { + blocks: { + byClientId: new Map( + Object.entries( { + block1: { name: 'core/block' }, // reusable blocks are always sections. + } ) + ), + attributes: new Map( + Object.entries( { + block1: {}, + } ) + ), + parents: new Map( + Object.entries( { + block1: '', + } ) + ), + order: new Map( [ [ '', [ 'block1' ] ] ] ), + }, + blockListSettings: { + block1: {}, + }, + settings: {}, + blockEditingModes: new Map(), + }; + expect( + canInsertBlockType( state, 'core/test-block-a', 'block1' ) + ).toBe( false ); + } ); + it( 'should allow blocks to be inserted if both parent and ancestor restrictions are met', () => { const state = { blocks: { @@ -3046,6 +3094,11 @@ describe( 'selectors', () => { block3: 'block2', } ) ), + order: new Map( [ + [ '', [ 'block1' ] ], + [ 'block1', [ 'block2' ] ], + [ 'block2', [ 'block3' ] ], + ] ), }, blockListSettings: { block1: {}, @@ -3086,6 +3139,11 @@ describe( 'selectors', () => { block3: 'block2', } ) ), + order: new Map( [ + [ '', [ 'block1' ] ], + [ 'block1', [ 'block2' ] ], + [ 'block2', [ 'block3' ] ], + ] ), }, blockListSettings: { block1: {}, @@ -3126,6 +3184,11 @@ describe( 'selectors', () => { block3: 'block2', } ) ), + order: new Map( [ + [ '', [ 'block1' ] ], + [ 'block1', [ 'block2' ] ], + [ 'block2', [ 'block3' ] ], + ] ), }, blockListSettings: { block1: {}, @@ -3159,11 +3222,14 @@ describe( 'selectors', () => { block2: {}, } ) ), - parents: new Map( - Object.entries( { - block2: 'block1', - } ) - ), + order: new Map( [ + [ '', [ 'block1' ] ], + [ 'block1', [ 'block2' ] ], + ] ), + parents: new Map( [ + [ 'block2', 'block1' ], + [ 'block1', '' ], + ] ), }, blockListSettings: { block1: {}, @@ -3203,6 +3269,10 @@ describe( 'selectors', () => { block2: 'block1', } ) ), + order: new Map( [ + [ '', [ 'block1' ] ], + [ 'block1', [ 'block2' ] ], + ] ), }, blockListSettings: { block1: {}, @@ -3240,6 +3310,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: { 1: { @@ -3273,6 +3344,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: { 1: { diff --git a/packages/block-editor/src/store/utils.js b/packages/block-editor/src/store/utils.js index b630912a5163d6..af991608238e2e 100644 --- a/packages/block-editor/src/store/utils.js +++ b/packages/block-editor/src/store/utils.js @@ -117,5 +117,6 @@ export function getInsertBlockTypeDependants( state, rootClientId ) { state.settings.allowedBlockTypes, state.settings.templateLock, state.blockEditingModes, + state.editorMode, ]; } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index d7e8b191229893..6607700b2d2c25 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -9,6 +9,7 @@ - `Tabs`: restore vertical indicator ([#65385](https://github.com/WordPress/gutenberg/pull/65385)). - `Tabs`: indicator positioning under RTL direction ([#64926](https://github.com/WordPress/gutenberg/pull/64926)). - `Popover`: Update `toolbar` variant radius to match block toolbar ([#65263](https://github.com/WordPress/gutenberg/pull/65263)). +- `MenuItemsChoice`: Allow menu items height to adapt to its content ([#65204](https://github.com/WordPress/gutenberg/pull/65204)). - `BoxControl`: Unify input filed width whether linked or not ([#65348](https://github.com/WordPress/gutenberg/pull/65348)). ### Deprecations diff --git a/packages/components/src/menu-items-choice/style.scss b/packages/components/src/menu-items-choice/style.scss index 5de8363be0d6e8..383eb4066ba86b 100644 --- a/packages/components/src/menu-items-choice/style.scss +++ b/packages/components/src/menu-items-choice/style.scss @@ -1,5 +1,7 @@ .components-menu-items-choice, .components-menu-items-choice.components-button { + height: auto; + svg { margin-right: $grid-unit-15; } diff --git a/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js b/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js index fcf7adfa77635c..c772a062b9e3be 100644 --- a/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js +++ b/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js @@ -17,21 +17,17 @@ import { __, _x } from '@wordpress/i18n'; */ import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; +import usePostContentBlocks from '../provider/use-post-content-blocks'; function ContentOnlySettingsMenuItems( { clientId, onClose } ) { + const postContentBlocks = usePostContentBlocks(); const { entity, onNavigateToEntityRecord, canEditTemplates } = useSelect( ( select ) => { const { - getBlockEditingMode, getBlockParentsByBlockName, getSettings, getBlockAttributes, } = select( blockEditorStore ); - const contentOnly = - getBlockEditingMode( clientId ) === 'contentOnly'; - if ( ! contentOnly ) { - return {}; - } const patternParent = getBlockParentsByBlockName( clientId, 'core/block', @@ -48,10 +44,14 @@ function ContentOnlySettingsMenuItems( { clientId, onClose } ) { } else { const { getCurrentTemplateId } = select( editorStore ); const templateId = getCurrentTemplateId(); - const { getContentLockingParent } = unlock( + const { getBlockParents } = unlock( select( blockEditorStore ) ); - if ( ! getContentLockingParent( clientId ) && templateId ) { + if ( + ! getBlockParents( clientId ).some( ( parent ) => + postContentBlocks.includes( parent ) + ) + ) { record = select( coreStore ).getEntityRecord( 'postType', 'wp_template', @@ -59,6 +59,9 @@ function ContentOnlySettingsMenuItems( { clientId, onClose } ) { ); } } + if ( ! record ) { + return {}; + } const _canEditTemplates = select( coreStore ).canUser( 'create', { kind: 'postType', name: 'wp_template', @@ -70,7 +73,7 @@ function ContentOnlySettingsMenuItems( { clientId, onClose } ) { getSettings().onNavigateToEntityRecord, }; }, - [ clientId ] + [ clientId, postContentBlocks ] ); if ( ! entity ) { diff --git a/packages/editor/src/components/provider/disable-non-page-content-blocks.js b/packages/editor/src/components/provider/disable-non-page-content-blocks.js index 9abb0e14079d5e..ae4fd1075fc261 100644 --- a/packages/editor/src/components/provider/disable-non-page-content-blocks.js +++ b/packages/editor/src/components/provider/disable-non-page-content-blocks.js @@ -3,52 +3,32 @@ */ import { useSelect, useRegistry } from '@wordpress/data'; import { store as blockEditorStore } from '@wordpress/block-editor'; -import { useEffect, useMemo } from '@wordpress/element'; -import { applyFilters } from '@wordpress/hooks'; +import { useEffect } from '@wordpress/element'; /** * Internal dependencies */ -import { store as editorStore } from '../../store'; -import { unlock } from '../../lock-unlock'; - -const POST_CONTENT_BLOCK_TYPES = [ - 'core/post-title', - 'core/post-featured-image', - 'core/post-content', -]; +import usePostContentBlocks from './use-post-content-blocks'; /** * Component that when rendered, makes it so that the site editor allows only * page content to be edited. */ export default function DisableNonPageContentBlocks() { - const contentOnlyBlockTypes = useMemo( - () => [ - ...applyFilters( - 'editor.postContentBlockTypes', - POST_CONTENT_BLOCK_TYPES - ), - 'core/template-part', - ], - [] - ); - - // Note that there are two separate subscriptions because the result for each - // returns a new array. - const contentOnlyIds = useSelect( + const contentOnlyIds = usePostContentBlocks(); + const templateParts = useSelect( ( select ) => { + const { getBlocksByName } = select( blockEditorStore ); + return getBlocksByName( 'core/template-part' ); + }, [] ); + const disabledIds = useSelect( ( select ) => { - const { getPostBlocksByName } = unlock( select( editorStore ) ); - return getPostBlocksByName( contentOnlyBlockTypes ); + const { getBlockOrder } = select( blockEditorStore ); + return templateParts.flatMap( ( clientId ) => + getBlockOrder( clientId ) + ); }, - [ contentOnlyBlockTypes ] + [ templateParts ] ); - const disabledIds = useSelect( ( select ) => { - const { getBlocksByName, getBlockOrder } = select( blockEditorStore ); - return getBlocksByName( 'core/template-part' ).flatMap( ( clientId ) => - getBlockOrder( clientId ) - ); - }, [] ); const registry = useRegistry(); @@ -61,6 +41,9 @@ export default function DisableNonPageContentBlocks() { for ( const clientId of contentOnlyIds ) { setBlockEditingMode( clientId, 'contentOnly' ); } + for ( const clientId of templateParts ) { + setBlockEditingMode( clientId, 'contentOnly' ); + } for ( const clientId of disabledIds ) { setBlockEditingMode( clientId, 'disabled' ); } @@ -72,12 +55,15 @@ export default function DisableNonPageContentBlocks() { for ( const clientId of contentOnlyIds ) { unsetBlockEditingMode( clientId ); } + for ( const clientId of templateParts ) { + unsetBlockEditingMode( clientId ); + } for ( const clientId of disabledIds ) { unsetBlockEditingMode( clientId ); } } ); }; - }, [ contentOnlyIds, disabledIds, registry ] ); + }, [ templateParts, contentOnlyIds, disabledIds, registry ] ); return null; } diff --git a/packages/editor/src/components/provider/use-post-content-blocks.js b/packages/editor/src/components/provider/use-post-content-blocks.js new file mode 100644 index 00000000000000..bdd277157e47e0 --- /dev/null +++ b/packages/editor/src/components/provider/use-post-content-blocks.js @@ -0,0 +1,42 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; +import { useMemo } from '@wordpress/element'; +import { applyFilters } from '@wordpress/hooks'; + +/** + * Internal dependencies + */ +import { store as editorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; + +const POST_CONTENT_BLOCK_TYPES = [ + 'core/post-title', + 'core/post-featured-image', + 'core/post-content', +]; + +export default function usePostContentBlocks() { + const contentOnlyBlockTypes = useMemo( + () => [ + ...applyFilters( + 'editor.postContentBlockTypes', + POST_CONTENT_BLOCK_TYPES + ), + ], + [] + ); + + // Note that there are two separate subscriptions because the result for each + // returns a new array. + const contentOnlyIds = useSelect( + ( select ) => { + const { getPostBlocksByName } = unlock( select( editorStore ) ); + return getPostBlocksByName( contentOnlyBlockTypes ); + }, + [ contentOnlyBlockTypes ] + ); + + return contentOnlyIds; +} diff --git a/packages/widgets/src/blocks/legacy-widget/edit/index.js b/packages/widgets/src/blocks/legacy-widget/edit/index.js index f371786c106d6f..c5ca43211e58e6 100644 --- a/packages/widgets/src/blocks/legacy-widget/edit/index.js +++ b/packages/widgets/src/blocks/legacy-widget/edit/index.js @@ -11,13 +11,11 @@ import { BlockControls, InspectorControls, BlockIcon, - store as blockEditorStore, } from '@wordpress/block-editor'; import { Flex, FlexBlock, Spinner, Placeholder } from '@wordpress/components'; import { brush as brushIcon } from '@wordpress/icons'; import { __ } from '@wordpress/i18n'; import { useState, useCallback } from '@wordpress/element'; -import { useSelect } from '@wordpress/data'; import { useEntityRecord } from '@wordpress/core-data'; /** @@ -102,11 +100,6 @@ function NotEmpty( { const { record: widgetType, hasResolved: hasResolvedWidgetType } = useEntityRecord( 'root', 'widgetType', widgetTypeId ); - const isNavigationMode = useSelect( - ( select ) => select( blockEditorStore ).isNavigationMode(), - [] - ); - const setInstance = useCallback( ( nextInstance ) => { setAttributes( { instance: nextInstance } ); }, [] ); @@ -130,8 +123,7 @@ function NotEmpty( { ); } - const mode = - idBase && ( isNavigationMode || ! isSelected ) ? 'preview' : 'edit'; + const mode = idBase && ! isSelected ? 'preview' : 'edit'; return ( <> diff --git a/test/e2e/specs/editor/various/block-moving-mode.spec.js b/test/e2e/specs/editor/various/block-moving-mode.spec.js deleted file mode 100644 index 5b8ef6bdcd051b..00000000000000 --- a/test/e2e/specs/editor/various/block-moving-mode.spec.js +++ /dev/null @@ -1,155 +0,0 @@ -/** - * WordPress dependencies - */ -const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); - -test.describe( 'Block moving mode', () => { - test.beforeEach( async ( { admin } ) => { - await admin.createNewPost(); - } ); - - test.afterEach( async ( { requestUtils } ) => { - await requestUtils.deleteAllPosts(); - } ); - - test( 'can move block', async ( { editor, page } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { content: 'First Paragraph' }, - } ); - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { content: 'Second Paragraph' }, - } ); - - // Move the second block in front of the first block. - await editor.showBlockToolbar(); - await page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Options' } ) - .click(); - await page.getByRole( 'menuitem', { name: 'Move to' } ).click(); - await page.keyboard.press( 'ArrowUp' ); - await page.keyboard.press( 'Enter' ); - - await expect.poll( editor.getBlocks ).toMatchObject( [ - { - name: 'core/paragraph', - attributes: { content: 'Second Paragraph' }, - }, - { - name: 'core/paragraph', - attributes: { content: 'First Paragraph' }, - }, - ] ); - } ); - - test( 'can move block in the nested block', async ( { editor, page } ) => { - // Create two group blocks with some blocks. - await editor.insertBlock( { name: 'core/group' } ); - await editor.canvas - .locator( - 'role=button[name="Group: Gather blocks in a container."i]' - ) - .click(); - await page.keyboard.press( 'ArrowDown' ); - await page.keyboard.press( 'Enter' ); - await page.getByRole( 'option', { name: 'Paragraph' } ).click(); - await page.keyboard.type( 'First Paragraph' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.type( 'Second Paragraph' ); - - await editor.insertBlock( { name: 'core/group' } ); - await editor.canvas - .locator( - 'role=button[name="Group: Gather blocks in a container."i]' - ) - .click(); - await page.keyboard.press( 'ArrowDown' ); - await page.keyboard.press( 'Enter' ); - await page.getByRole( 'option', { name: 'Paragraph' } ).click(); - await page.keyboard.type( 'Third Paragraph' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.type( 'Fourth Paragraph' ); - - // Move a paragraph block in the first group block into the second group block. - const paragraphBlock = editor.canvas.locator( - 'text="First Paragraph"' - ); - await paragraphBlock.focus(); - await editor.showBlockToolbar(); - await page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Options' } ) - .click(); - await page.getByRole( 'menuitem', { name: 'Move to' } ).click(); - await page.keyboard.press( 'ArrowLeft' ); // Select the first group block. - await page.keyboard.press( 'ArrowDown' ); // Select the second group block. - await page.keyboard.press( 'ArrowRight' ); // Enter the second group block. - await page.keyboard.press( 'ArrowDown' ); // Move down in the second group block. - await page.keyboard.press( 'Enter' ); - - await expect.poll( editor.getBlocks ).toMatchObject( [ - { - name: 'core/group', - innerBlocks: [ - { - name: 'core/paragraph', - attributes: { content: 'Second Paragraph' }, - }, - ], - }, - { - name: 'core/group', - innerBlocks: [ - { - name: 'core/paragraph', - attributes: { content: 'Third Paragraph' }, - }, - { - name: 'core/paragraph', - attributes: { content: 'First Paragraph' }, - }, - { - name: 'core/paragraph', - attributes: { content: 'Fourth Paragraph' }, - }, - ], - }, - ] ); - } ); - - test( 'can not move inside its own block', async ( { editor, page } ) => { - // Create a paragraph block and a group block. - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { content: 'First Paragraph' }, - } ); - await editor.insertBlock( { name: 'core/group' } ); - await editor.canvas - .locator( - 'role=button[name="Group: Gather blocks in a container."i]' - ) - .click(); - await page.keyboard.press( 'ArrowDown' ); - await page.keyboard.press( 'Enter' ); - await page.getByRole( 'option', { name: 'Paragraph' } ).click(); - await page.keyboard.type( 'Second Paragraph' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.type( 'Third Paragraph' ); - - // Trying to move the group block into its own. - const groupBlock = editor.canvas.locator( - 'role=document[name="Block: Group"i]' - ); - await groupBlock.focus(); - await editor.showBlockToolbar(); - await page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Options' } ) - .click(); - await page.getByRole( 'menuitem', { name: 'Move to' } ).click(); - await page.keyboard.press( 'ArrowRight' ); - await expect( groupBlock ).toHaveClass( /is-selected/ ); - } ); -} ); diff --git a/test/e2e/specs/editor/various/keyboard-navigable-blocks.spec.js b/test/e2e/specs/editor/various/keyboard-navigable-blocks.spec.js index 6a7125d04f7a6a..e1ca121040b974 100644 --- a/test/e2e/specs/editor/various/keyboard-navigable-blocks.spec.js +++ b/test/e2e/specs/editor/various/keyboard-navigable-blocks.spec.js @@ -17,108 +17,26 @@ test.describe( 'Order of block keyboard navigation', () => { await editor.openDocumentSettingsSidebar(); } ); - test( 'permits tabbing through paragraph blocks in the expected order', async ( { + test( 'permits tabbing through the block toolbar of the paragraph block', async ( { editor, KeyboardNavigableBlocks, page, + pageUtils, } ) => { - const paragraphBlocks = [ 'Paragraph 0', 'Paragraph 1', 'Paragraph 2' ]; - - // Create 3 paragraphs blocks with some content. - for ( const paragraphBlock of paragraphBlocks ) { + // Insert three paragraph blocks. + for ( let i = 0; i < 3; i++ ) { await editor.insertBlock( { name: 'core/paragraph' } ); - await page.keyboard.type( paragraphBlock ); + await page.keyboard.type( `Paragraph ${ i + 1 }` ); } - - // Select the middle block. + // Select the middle paragraph block. await page.keyboard.press( 'ArrowUp' ); await editor.showBlockToolbar(); - await KeyboardNavigableBlocks.navigateToContentEditorTop(); - await KeyboardNavigableBlocks.tabThroughParagraphBlock( 'Paragraph 1' ); - - // Repeat the same steps to ensure that there is no change introduced in how the focus is handled. - // This prevents the previous regression explained in: https://github.com/WordPress/gutenberg/issues/11773. - await KeyboardNavigableBlocks.navigateToContentEditorTop(); - await KeyboardNavigableBlocks.tabThroughParagraphBlock( 'Paragraph 1' ); - } ); - - test( 'allows tabbing in navigation mode if no block is selected', async ( { - editor, - KeyboardNavigableBlocks, - page, - } ) => { - const paragraphBlocks = [ '0', '1' ]; - - // Create 2 paragraphs blocks with some content. - for ( const paragraphBlock of paragraphBlocks ) { - await editor.insertBlock( { name: 'core/paragraph' } ); - await page.keyboard.type( paragraphBlock ); - } - - // Clear the selected block. - const paragraph = editor.canvas - .locator( '[data-type="core/paragraph"]' ) - .getByText( '1' ); - const box = await paragraph.boundingBox(); - await page.mouse.click( box.x - 1, box.y ); - - await page.keyboard.press( 'Tab' ); - await KeyboardNavigableBlocks.expectLabelToHaveFocus( 'Add title' ); - - await page.keyboard.press( 'Tab' ); - await KeyboardNavigableBlocks.expectLabelToHaveFocus( - 'Paragraph Block. Row 1. 0' - ); - - await page.keyboard.press( 'Tab' ); - await KeyboardNavigableBlocks.expectLabelToHaveFocus( - 'Paragraph Block. Row 2. 1' - ); - - await page.keyboard.press( 'Tab' ); - await KeyboardNavigableBlocks.expectLabelToHaveFocus( 'Post' ); - } ); - - test( 'allows tabbing in navigation mode if no block is selected (reverse)', async ( { - editor, - KeyboardNavigableBlocks, - page, - pageUtils, - } ) => { - const paragraphBlocks = [ '0', '1' ]; - - // Create 2 paragraphs blocks with some content. - for ( const paragraphBlock of paragraphBlocks ) { - await editor.insertBlock( { name: 'core/paragraph' } ); - await page.keyboard.type( paragraphBlock ); - } - - // Clear the selected block. - const paragraph = editor.canvas - .locator( '[data-type="core/paragraph"]' ) - .getByText( '1' ); - const box = await paragraph.boundingBox(); - await page.mouse.click( box.x - 1, box.y ); - - // Put focus behind the block list. - await page.evaluate( () => { - document - .querySelector( '.interface-interface-skeleton__sidebar' ) - .focus(); - } ); - - await pageUtils.pressKeys( 'shift+Tab' ); - await KeyboardNavigableBlocks.expectLabelToHaveFocus( - 'Paragraph Block. Row 2. 1' - ); - await pageUtils.pressKeys( 'shift+Tab' ); + await KeyboardNavigableBlocks.navigateThroughBlockToolbar(); + await page.keyboard.press( 'Tab' ); await KeyboardNavigableBlocks.expectLabelToHaveFocus( - 'Paragraph Block. Row 1. 0' + 'Block: Paragraph' ); - - await pageUtils.pressKeys( 'shift+Tab' ); - await KeyboardNavigableBlocks.expectLabelToHaveFocus( 'Add title' ); } ); test( 'should navigate correctly with multi selection', async ( { @@ -208,31 +126,7 @@ class KeyboardNavigableBlocks { expect( ariaLabel ).toBe( label ); } - async navigateToContentEditorTop() { - // Use 'Ctrl+`' to return to the top of the editor. - await this.pageUtils.pressKeys( 'ctrl+`', { times: 5 } ); - } - - async tabThroughParagraphBlock( paragraphText ) { - await this.tabThroughBlockToolbar(); - - await this.page.keyboard.press( 'Tab' ); - await this.expectLabelToHaveFocus( 'Block: Paragraph' ); - - const activeElement = this.editor.canvas.locator( ':focus' ); - - await expect( activeElement ).toHaveText( paragraphText ); - - await this.page.keyboard.press( 'Tab' ); - await this.expectLabelToHaveFocus( 'Block' ); - - // Need to shift+tab here to end back in the block. If not, we'll be in the next region and it will only require 4 region jumps instead of 5. - await this.pageUtils.pressKeys( 'shift+Tab' ); - await this.expectLabelToHaveFocus( 'Block: Paragraph' ); - } - - async tabThroughBlockToolbar() { - await this.page.keyboard.press( 'Tab' ); + async navigateThroughBlockToolbar() { await this.expectLabelToHaveFocus( 'Paragraph' ); await this.page.keyboard.press( 'ArrowRight' ); diff --git a/test/e2e/specs/editor/various/shortcut-focus-toolbar.spec.js b/test/e2e/specs/editor/various/shortcut-focus-toolbar.spec.js index a8e49f7a6b84dd..cfaf4e0be9188f 100644 --- a/test/e2e/specs/editor/various/shortcut-focus-toolbar.spec.js +++ b/test/e2e/specs/editor/various/shortcut-focus-toolbar.spec.js @@ -50,32 +50,6 @@ test.describe( 'Focus toolbar shortcut (alt + F10)', () => { await expect( toolbarUtils.documentToolbarTooltip ).toBeHidden(); } ); - test( 'Focuses correct toolbar in default view options in select mode', async ( { - editor, - page, - toolbarUtils, - } ) => { - // Test: Focus the document toolbar from title - await toolbarUtils.useSelectMode(); - await toolbarUtils.moveToToolbarShortcut(); - await expect( toolbarUtils.documentToolbarButton ).toBeFocused(); - - // Test: Focus the top level toolbar from empty block - await editor.insertBlock( { name: 'core/paragraph' } ); - await toolbarUtils.useSelectMode(); - await toolbarUtils.moveToToolbarShortcut(); - await expect( toolbarUtils.documentToolbarButton ).toBeFocused(); - - // Test: Focus the top level toolbar from paragraph block - await editor.insertBlock( { name: 'core/paragraph' } ); - await page.keyboard.type( - 'Focus top level toolbar from paragraph block in select mode.' - ); - await toolbarUtils.useSelectMode(); - await toolbarUtils.moveToToolbarShortcut(); - await expect( toolbarUtils.documentToolbarButton ).toBeFocused(); - } ); - test.describe( 'In Top Toolbar option:', () => { test.beforeEach( async ( { editor } ) => { // Ensure the fixed toolbar option is on diff --git a/test/e2e/specs/editor/various/writing-flow.spec.js b/test/e2e/specs/editor/various/writing-flow.spec.js index bd1552ad4cb66a..4077d6dcc58200 100644 --- a/test/e2e/specs/editor/various/writing-flow.spec.js +++ b/test/e2e/specs/editor/various/writing-flow.spec.js @@ -106,48 +106,6 @@ test.describe( 'Writing Flow (@firefox, @webkit)', () => { ] ); } ); - test( 'Should navigate between inner and root blocks in navigation mode', async ( { - page, - writingFlowUtils, - } ) => { - await writingFlowUtils.addDemoContent(); - - // Switch to navigation mode. - await page.keyboard.press( 'Escape' ); - // Arrow up to Columns block. - await page.keyboard.press( 'ArrowUp' ); - await expect - .poll( writingFlowUtils.getActiveBlockName ) - .toBe( 'core/columns' ); - // Arrow right into Column block. - await page.keyboard.press( 'ArrowRight' ); - await expect - .poll( writingFlowUtils.getActiveBlockName ) - .toBe( 'core/column' ); - // Arrow down to reach second Column block. - await page.keyboard.press( 'ArrowDown' ); - // Arrow right again into Paragraph block. - await page.keyboard.press( 'ArrowRight' ); - await expect - .poll( writingFlowUtils.getActiveBlockName ) - .toBe( 'core/paragraph' ); - // Arrow left back to Column block. - await page.keyboard.press( 'ArrowLeft' ); - await expect - .poll( writingFlowUtils.getActiveBlockName ) - .toBe( 'core/column' ); - // Arrow left back to Columns block. - await page.keyboard.press( 'ArrowLeft' ); - await expect - .poll( writingFlowUtils.getActiveBlockName ) - .toBe( 'core/columns' ); - // Arrow up to first paragraph. - await page.keyboard.press( 'ArrowUp' ); - await expect - .poll( writingFlowUtils.getActiveBlockName ) - .toBe( 'core/paragraph' ); - } ); - test( 'should navigate around inline boundaries', async ( { editor, page, @@ -958,32 +916,6 @@ test.describe( 'Writing Flow (@firefox, @webkit)', () => { <!-- /wp:table -->` ); } ); - test( 'escape should set select mode and then focus the canvas', async ( { - page, - writingFlowUtils, - } ) => { - await page.keyboard.press( 'Enter' ); - await page.keyboard.type( 'Random Paragraph' ); - - // First escape enters navigation mode. - await page.keyboard.press( 'Escape' ); - const navigationButton = page.getByLabel( - 'Paragraph Block. Row 1. Random Paragraph' - ); - await expect( navigationButton ).toBeVisible(); - await expect - .poll( writingFlowUtils.getActiveBlockName ) - .toBe( 'core/paragraph' ); - - // Second escape should send focus to the canvas - await page.keyboard.press( 'Escape' ); - // The navigation button should be hidden. - await expect( navigationButton ).toBeHidden(); - await expect( - page.getByRole( 'region', { name: 'Editor content' } ) - ).toBeFocused(); - } ); - // Checks for regressions of https://github.com/WordPress/gutenberg/issues/40091. test( 'does not deselect the block when selecting text outside the editor canvas', async ( { editor, @@ -1222,11 +1154,11 @@ class WritingFlowUtils { 'role=listbox[name="Blocks"i] >> role=option[name="Paragraph"i]' ); await this.page.keyboard.type( '2nd col' ); // If this text is too long, it may wrap to a new line and cause test failure. That's why we're using "2nd" instead of "Second" here. - - await this.page.keyboard.press( 'Escape' ); // Enter navigation mode. - await this.page.keyboard.press( 'ArrowLeft' ); // Move to the column block. - await this.page.keyboard.press( 'ArrowLeft' ); // Move to the columns block. - await this.page.keyboard.press( 'Enter' ); // Enter edit mode with the columns block selected. + await this.editor.showBlockToolbar(); + await this.page.keyboard.press( 'Shift+Tab' ); // Move to toolbar to select parent + await this.page.keyboard.press( 'Enter' ); // Selects the column block. + await this.page.keyboard.press( 'Shift+Tab' ); // Move to toolbar to select parent + await this.page.keyboard.press( 'Enter' ); // Selects the columns block. await this.page.keyboard.press( 'Enter' ); // Creates a paragraph after the columns block. await this.page.keyboard.type( 'Second paragraph' ); } diff --git a/test/e2e/specs/site-editor/navigation.spec.js b/test/e2e/specs/site-editor/navigation.spec.js index 4db860b703892c..1b92ef2e850e67 100644 --- a/test/e2e/specs/site-editor/navigation.spec.js +++ b/test/e2e/specs/site-editor/navigation.spec.js @@ -83,19 +83,6 @@ test.describe( 'Site editor navigation', () => { // The button role should have been removed from the iframe. await expect( editorCanvasButton ).toBeHidden(); - // Test to make sure a Tab keypress works as expected. - // As of this writing, we are in select mode and a tab - // keypress will reveal the header template select mode - // button. This test is not documenting that we _want_ - // that action, but checking that we are within the site - // editor and keypresses work as intened. - await pageUtils.pressKeys( 'Tab' ); - await expect( - page.getByRole( 'button', { - name: 'Template Part Block. Row 1. header', - } ) - ).toBeFocused(); - // Test: We can go back to the main navigation from the editor frame // Move to the document toolbar await pageUtils.pressKeys( 'alt+F10' ); diff --git a/test/e2e/specs/widgets/customizing-widgets.spec.js b/test/e2e/specs/widgets/customizing-widgets.spec.js index 53b4da7be2d61f..38e9d3ee2c58ab 100644 --- a/test/e2e/specs/widgets/customizing-widgets.spec.js +++ b/test/e2e/specs/widgets/customizing-widgets.spec.js @@ -465,16 +465,6 @@ test.describe( 'Widgets Customizer', () => { await expect( paragraphBlock ).toBeVisible(); await paragraphBlock.focus(); - - // Expect pressing the Escape key to enter navigation mode, - // but not close the editor. - await page.keyboard.press( 'Escape' ); - await expect( - page.locator( - 'css=.block-editor-block-list__layout.is-navigate-mode' - ) - ).toBeVisible(); - await expect( paragraphBlock ).toBeVisible(); } ); test( 'should move (inner) blocks to another sidebar', async ( { From f0cd2174238a40bbc15812e9270bed6336fb8be8 Mon Sep 17 00:00:00 2001 From: Michal <mmczaplinski@gmail.com> Date: Thu, 19 Sep 2024 22:20:41 +0200 Subject: [PATCH 0882/1908] DEWP: Handle cyclical module dependencies (#65291) * Add tests for cyclical dependencies * Add the externals and make the test fail * Add cycle detection in dependency path checking Enhanced the dependency resolution logic to detect cycles in the module graph, preventing infinite loops during static dependency path checks. Introduced a Set to track visited blocks and avoid revisiting them. * Revert changes * Propose static WeakSet/WeakMap implementation. * Add CHANGELOG entry * Remove redundant plugin config in test * Revert "Remove redundant plugin config in test" This reverts commit b5e33dbc0e6db4d4aab07de4d52b42ae6b9672ee. * Remove redundant plugin config in test * Updated the snapshot files --------- Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- .../CHANGELOG.md | 4 ++ .../lib/index.js | 46 +++++++++++++++++-- .../test/__snapshots__/build.js.snap | 33 +++++++++++++ .../test/fixtures/cyclic-external-deps/a.js | 8 ++++ .../fixtures/cyclic-external-deps/index.js | 18 ++++++++ .../cyclic-external-deps/webpack.config.js | 8 ++++ 6 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/a.js create mode 100644 packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/index.js create mode 100644 packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index 85498d539317f3..1c0aa630495a0b 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- Fix a bug where cycles in dependent modules could enter infinite recursion ([#65291](https://github.com/WordPress/gutenberg/pull/65291)). + ## 6.8.0 (2024-09-19) ## 6.7.0 (2024-09-05) diff --git a/packages/dependency-extraction-webpack-plugin/lib/index.js b/packages/dependency-extraction-webpack-plugin/lib/index.js index 575882a1dfbebe..529fb339d15a14 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/index.js +++ b/packages/dependency-extraction-webpack-plugin/lib/index.js @@ -369,6 +369,9 @@ class DependencyExtractionWebpackPlugin { } } + static #staticDepsCurrent = new WeakSet(); + static #staticDepsCache = new WeakMap(); + /** * Can we trace a line of static dependencies from an entry to a module * @@ -378,6 +381,20 @@ class DependencyExtractionWebpackPlugin { * @return {boolean} True if there is a static import path to the root */ static hasStaticDependencyPathToRoot( compilation, block ) { + if ( DependencyExtractionWebpackPlugin.#staticDepsCache.has( block ) ) { + return DependencyExtractionWebpackPlugin.#staticDepsCache.get( + block + ); + } + + if ( + DependencyExtractionWebpackPlugin.#staticDepsCurrent.has( block ) + ) { + return false; + } + + DependencyExtractionWebpackPlugin.#staticDepsCurrent.add( block ); + const incomingConnections = [ ...compilation.moduleGraph.getIncomingConnections( block ), ].filter( @@ -391,6 +408,13 @@ class DependencyExtractionWebpackPlugin { // If we don't have non-entry, non-library incoming connections, // we've reached a root of if ( ! incomingConnections.length ) { + DependencyExtractionWebpackPlugin.#staticDepsCache.set( + block, + true + ); + DependencyExtractionWebpackPlugin.#staticDepsCurrent.delete( + block + ); return true; } @@ -409,16 +433,28 @@ class DependencyExtractionWebpackPlugin { // All the dependencies were Async, the module was reached via a dynamic import if ( ! staticDependentModules.length ) { + DependencyExtractionWebpackPlugin.#staticDepsCache.set( + block, + false + ); + DependencyExtractionWebpackPlugin.#staticDepsCurrent.delete( + block + ); return false; } // Continue to explore any static dependencies - return staticDependentModules.some( ( parentStaticDependentModule ) => - DependencyExtractionWebpackPlugin.hasStaticDependencyPathToRoot( - compilation, - parentStaticDependentModule - ) + const result = staticDependentModules.some( + ( parentStaticDependentModule ) => + DependencyExtractionWebpackPlugin.hasStaticDependencyPathToRoot( + compilation, + parentStaticDependentModule + ) ); + + DependencyExtractionWebpackPlugin.#staticDepsCache.set( block, result ); + DependencyExtractionWebpackPlugin.#staticDepsCurrent.delete( block ); + return result; } } diff --git a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap index c4b450683572e8..903c9658250b17 100644 --- a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap +++ b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap @@ -55,6 +55,21 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-dynamic-depe ] `; +exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-external-deps\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` +"<?php return array('dependencies' => array(array('id' => '@wordpress/interactivity', 'import' => 'dynamic')), 'version' => 'e1033c1bd62e8cb8d4c9', 'type' => 'module'); +" +`; + +exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-external-deps\` should produce expected output: External modules should match snapshot 1`] = ` +[ + { + "externalType": "module", + "request": "@wordpress/interactivity", + "userRequest": "@wordpress/interactivity", + }, +] +`; + exports[`DependencyExtractionWebpackPlugin modules Webpack \`dynamic-import\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` "<?php return array('dependencies' => array(array('id' => '@wordpress/blob', 'import' => 'dynamic')), 'version' => '4f59b7847b70a07b2710', 'type' => 'module'); " @@ -419,6 +434,24 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-dynamic-depe ] `; +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-external-deps\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` +"<?php return array('dependencies' => array('wp-interactivity'), 'version' => '455f3cab924853d41b8b'); +" +`; + +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-external-deps\` should produce expected output: External modules should match snapshot 1`] = ` +[ + { + "externalType": "window", + "request": [ + "wp", + "interactivity", + ], + "userRequest": "@wordpress/interactivity", + }, +] +`; + exports[`DependencyExtractionWebpackPlugin scripts Webpack \`dynamic-import\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` "<?php return array('dependencies' => array('wp-blob'), 'version' => 'c0e8a6f22065ea096606'); " diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/a.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/a.js new file mode 100644 index 00000000000000..1f0edffe27efd3 --- /dev/null +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/a.js @@ -0,0 +1,8 @@ +/** + * Internal dependencies + */ +import { someFunction } from '.'; + +someFunction(); + +export const a = 'test'; diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/index.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/index.js new file mode 100644 index 00000000000000..01d7eff466bfbd --- /dev/null +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/index.js @@ -0,0 +1,18 @@ +/** + * Internal dependencies + */ +import { a } from './a'; + +/** + * WordPress dependencies + */ +import { store } from '@wordpress/interactivity'; + +export const someFunction = () => { + store( 'test', { + state: { + a, + }, + } ); + return a; +}; diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js new file mode 100644 index 00000000000000..bfffff3ae78319 --- /dev/null +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js @@ -0,0 +1,8 @@ +/** + * Internal dependencies + */ +const DependencyExtractionWebpackPlugin = require( '../../..' ); + +module.exports = { + plugins: [ new DependencyExtractionWebpackPlugin() ], +}; From cc29fd1b10b7f787b8e24e6a8a26544f0946f929 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Fri, 20 Sep 2024 10:50:14 +1000 Subject: [PATCH 0883/1908] Command Palette: "Add new page" within the site editor creates new page in site editor (#65476) The add page command will now create a new page depending on context: in the post editor it will redirect to `postType=page` in the post editor as it did previously. In the site editor however, it will open a new page without redirecting to the post editor. --------- Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- package-lock.json | 2 + packages/core-commands/package.json | 1 + .../src/admin-navigation-commands.js | 85 +++++++++++++++++-- .../specs/site-editor/command-center.spec.js | 6 +- 4 files changed, 85 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index f61d8acd98274c..035018e97f13f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53340,6 +53340,7 @@ "@wordpress/html-entities": "file:../html-entities", "@wordpress/i18n": "file:../i18n", "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", "@wordpress/private-apis": "file:../private-apis", "@wordpress/router": "file:../router", "@wordpress/url": "file:../url" @@ -68362,6 +68363,7 @@ "@wordpress/html-entities": "file:../html-entities", "@wordpress/i18n": "file:../i18n", "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", "@wordpress/private-apis": "file:../private-apis", "@wordpress/router": "file:../router", "@wordpress/url": "file:../url" diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 8334ef97c9244d..a2d3c76ebe5d9c 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -37,6 +37,7 @@ "@wordpress/html-entities": "file:../html-entities", "@wordpress/i18n": "file:../i18n", "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", "@wordpress/private-apis": "file:../private-apis", "@wordpress/router": "file:../router", "@wordpress/url": "file:../url" diff --git a/packages/core-commands/src/admin-navigation-commands.js b/packages/core-commands/src/admin-navigation-commands.js index 0ffa7ba7eb6285..be5e19386b65b4 100644 --- a/packages/core-commands/src/admin-navigation-commands.js +++ b/packages/core-commands/src/admin-navigation-commands.js @@ -1,9 +1,83 @@ /** * WordPress dependencies */ -import { useCommand } from '@wordpress/commands'; +import { useCommand, useCommandLoader } from '@wordpress/commands'; import { __ } from '@wordpress/i18n'; import { plus } from '@wordpress/icons'; +import { getPath } from '@wordpress/url'; +import { store as coreStore } from '@wordpress/core-data'; +import { useDispatch } from '@wordpress/data'; +import { useMemo } from '@wordpress/element'; +import { store as noticesStore } from '@wordpress/notices'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; + +/** + * Internal dependencies + */ +import { unlock } from './lock-unlock'; + +const { useHistory } = unlock( routerPrivateApis ); + +function useAddNewPageCommand() { + const isSiteEditor = getPath( window.location.href )?.includes( + 'site-editor.php' + ); + const history = useHistory(); + const { saveEntityRecord } = useDispatch( coreStore ); + const { createErrorNotice } = useDispatch( noticesStore ); + + const createPageEntity = async ( { close } ) => { + try { + const page = await saveEntityRecord( + 'postType', + 'page', + { + status: 'draft', + }, + { + throwOnError: true, + } + ); + if ( page?.id ) { + history.push( { + postId: page.id, + postType: 'page', + canvas: 'edit', + } ); + } + } catch ( error ) { + const errorMessage = + error.message && error.code !== 'unknown_error' + ? error.message + : __( 'An error occurred while creating the item.' ); + + createErrorNotice( errorMessage, { + type: 'snackbar', + } ); + } finally { + close(); + } + }; + + const commands = useMemo( () => { + const addNewPage = isSiteEditor + ? createPageEntity + : () => ( document.location.href = 'post-new.php?post_type=page' ); + return [ + { + name: 'core/add-new-page', + label: __( 'Add new page' ), + icon: plus, + callback: addNewPage, + }, + ]; + }, [ createPageEntity, isSiteEditor ] ); + + return { + isLoading: false, + commands, + }; +} export function useAdminNavigationCommands() { useCommand( { @@ -14,12 +88,9 @@ export function useAdminNavigationCommands() { document.location.href = 'post-new.php'; }, } ); - useCommand( { + + useCommandLoader( { name: 'core/add-new-page', - label: __( 'Add new page' ), - icon: plus, - callback: () => { - document.location.href = 'post-new.php?post_type=page'; - }, + hook: useAddNewPageCommand, } ); } diff --git a/test/e2e/specs/site-editor/command-center.spec.js b/test/e2e/specs/site-editor/command-center.spec.js index 5b049cda252a8b..19318081aa171b 100644 --- a/test/e2e/specs/site-editor/command-center.spec.js +++ b/test/e2e/specs/site-editor/command-center.spec.js @@ -28,10 +28,12 @@ test.describe( 'Site editor command palette', () => { await page.keyboard.type( 'new page' ); await page.getByRole( 'option', { name: 'Add new page' } ).click(); await expect( page ).toHaveURL( - '/wp-admin/post-new.php?post_type=page' + /\/wp-admin\/site-editor.php\?postId=(\d+)&postType=page&canvas=edit/ ); await expect( - editor.canvas.getByRole( 'textbox', { name: 'Add title' } ) + editor.canvas + .getByLabel( 'Block: Title' ) + .locator( '[data-rich-text-placeholder="No title"]' ) ).toBeVisible(); } ); From 8bc4b6214d33e53fb031f7b4f245ef5bd2bb8082 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:04:13 +1000 Subject: [PATCH 0884/1908] Time To Read: Add block example --- packages/block-library/src/post-time-to-read/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/post-time-to-read/index.js b/packages/block-library/src/post-time-to-read/index.js index 95b379f55f0b3f..039923161ca81d 100644 --- a/packages/block-library/src/post-time-to-read/index.js +++ b/packages/block-library/src/post-time-to-read/index.js @@ -12,6 +12,7 @@ export { metadata, name }; export const settings = { icon, edit, + example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); From 1bbe4c4936a7961d5482e826d5d59aa996906e17 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:51:30 +1000 Subject: [PATCH 0885/1908] Revert: Time To Read: Add block example (#65510) This reverts commit 8bc4b6214d33e53fb031f7b4f245ef5bd2bb8082. Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- packages/block-library/src/post-time-to-read/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-library/src/post-time-to-read/index.js b/packages/block-library/src/post-time-to-read/index.js index 039923161ca81d..95b379f55f0b3f 100644 --- a/packages/block-library/src/post-time-to-read/index.js +++ b/packages/block-library/src/post-time-to-read/index.js @@ -12,7 +12,6 @@ export { metadata, name }; export const settings = { icon, edit, - example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); From 5e37a1316d0a39bc880bf6efff9b9f26db381690 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Fri, 20 Sep 2024 11:43:45 +0200 Subject: [PATCH 0886/1908] useToolsPanel: calculate menuItems in layout effect to avoid painting intermediate state (#65494) * useToolsPanel: calculate menuItems in layout effect to avoid painting intermediate state * useToolsPanel: remove setState deps, calculate derived values in layout effects * ToolsPanelItem: also use layout effect to prevent loops * Changelog entry Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 + .../src/tools-panel/tools-panel-item/hook.ts | 13 +- .../src/tools-panel/tools-panel/hook.ts | 131 ++++++++---------- 3 files changed, 68 insertions(+), 80 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 6607700b2d2c25..03d6eb30e336b0 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- `ToolsPanel`: avoid paining intermediate unfinished states ([#65494](https://github.com/WordPress/gutenberg/pull/65494)). + ## 28.8.0 (2024-09-19) ### Bug Fixes diff --git a/packages/components/src/tools-panel/tools-panel-item/hook.ts b/packages/components/src/tools-panel/tools-panel-item/hook.ts index 1e33e7c6740ded..27a0ceb27e7ce7 100644 --- a/packages/components/src/tools-panel/tools-panel-item/hook.ts +++ b/packages/components/src/tools-panel/tools-panel-item/hook.ts @@ -2,12 +2,7 @@ * WordPress dependencies */ import { usePrevious } from '@wordpress/compose'; -import { - useCallback, - useEffect, - useLayoutEffect, - useMemo, -} from '@wordpress/element'; +import { useCallback, useLayoutEffect, useMemo } from '@wordpress/element'; /** * Internal dependencies @@ -101,7 +96,7 @@ export function useToolsPanelItem( deregisterPanelItem, ] ); - useEffect( () => { + useLayoutEffect( () => { if ( hasMatchingPanel ) { registerResetAllFilter( resetAllFilterCallback ); } @@ -127,7 +122,7 @@ export function useToolsPanelItem( const isValueSet = hasValue(); // Notify the panel when an item's value has changed except for optional // items without value because the item should not cause itself to hide. - useEffect( () => { + useLayoutEffect( () => { if ( ! isShownByDefault && ! isValueSet ) { return; } @@ -143,7 +138,7 @@ export function useToolsPanelItem( // Determine if the panel item's corresponding menu is being toggled and // trigger appropriate callback if it is. - useEffect( () => { + useLayoutEffect( () => { // We check whether this item is currently registered as items rendered // via fills can persist through the parent panel being remounted. // See: https://github.com/WordPress/gutenberg/pull/45673 diff --git a/packages/components/src/tools-panel/tools-panel/hook.ts b/packages/components/src/tools-panel/tools-panel/hook.ts index 931bf2494e6e34..d67d732d4df671 100644 --- a/packages/components/src/tools-panel/tools-panel/hook.ts +++ b/packages/components/src/tools-panel/tools-panel/hook.ts @@ -3,7 +3,7 @@ */ import { useCallback, - useEffect, + useLayoutEffect, useMemo, useRef, useState, @@ -101,7 +101,7 @@ export function useToolsPanel( // the resetAll task. Without this, the flag is cleared after the first // control updates and forces a rerender with subsequent controls then // believing they need to reset, unfortunately using stale data. - useEffect( () => { + useLayoutEffect( () => { if ( wasResetting ) { isResettingRef.current = false; } @@ -114,76 +114,66 @@ export function useToolsPanel( ResetAllFilter[] >( [] ); - const registerPanelItem = useCallback( - ( item: ToolsPanelItem ) => { - // Add item to panel items. - setPanelItems( ( items ) => { - const newItems = [ ...items ]; - // If an item with this label has already been registered, remove it - // first. This can happen when an item is moved between the default - // and optional groups. - const existingIndex = newItems.findIndex( - ( oldItem ) => oldItem.label === item.label - ); - if ( existingIndex !== -1 ) { - newItems.splice( existingIndex, 1 ); - } - return [ ...newItems, item ]; - } ); + const registerPanelItem = useCallback( ( item: ToolsPanelItem ) => { + // Add item to panel items. + setPanelItems( ( items ) => { + const newItems = [ ...items ]; + // If an item with this label has already been registered, remove it + // first. This can happen when an item is moved between the default + // and optional groups. + const existingIndex = newItems.findIndex( + ( oldItem ) => oldItem.label === item.label + ); + if ( existingIndex !== -1 ) { + newItems.splice( existingIndex, 1 ); + } + return [ ...newItems, item ]; + } ); - // Track the initial order of item registration. This is used for - // maintaining menu item order later. - setMenuItemOrder( ( items ) => { - if ( items.includes( item.label ) ) { - return items; - } + // Track the initial order of item registration. This is used for + // maintaining menu item order later. + setMenuItemOrder( ( items ) => { + if ( items.includes( item.label ) ) { + return items; + } - return [ ...items, item.label ]; - } ); - }, - [ setPanelItems, setMenuItemOrder ] - ); + return [ ...items, item.label ]; + } ); + }, [] ); // Panels need to deregister on unmount to avoid orphans in menu state. // This is an issue when panel items are being injected via SlotFills. - const deregisterPanelItem = useCallback( - ( label: string ) => { - // When switching selections between components injecting matching - // controls, e.g. both panels have a "padding" control, the - // deregistration of the first panel doesn't occur until after the - // registration of the next. - setPanelItems( ( items ) => { - const newItems = [ ...items ]; - const index = newItems.findIndex( - ( item ) => item.label === label - ); - if ( index !== -1 ) { - newItems.splice( index, 1 ); - } - return newItems; - } ); - }, - [ setPanelItems ] - ); + const deregisterPanelItem = useCallback( ( label: string ) => { + // When switching selections between components injecting matching + // controls, e.g. both panels have a "padding" control, the + // deregistration of the first panel doesn't occur until after the + // registration of the next. + setPanelItems( ( items ) => { + const newItems = [ ...items ]; + const index = newItems.findIndex( + ( item ) => item.label === label + ); + if ( index !== -1 ) { + newItems.splice( index, 1 ); + } + return newItems; + } ); + }, [] ); const registerResetAllFilter = useCallback( ( newFilter: ResetAllFilter ) => { - setResetAllFilters( ( filters ) => { - return [ ...filters, newFilter ]; - } ); + setResetAllFilters( ( filters ) => [ ...filters, newFilter ] ); }, - [ setResetAllFilters ] + [] ); const deregisterResetAllFilter = useCallback( ( filterToRemove: ResetAllFilter ) => { - setResetAllFilters( ( filters ) => { - return filters.filter( - ( filter ) => filter !== filterToRemove - ); - } ); + setResetAllFilters( ( filters ) => + filters.filter( ( filter ) => filter !== filterToRemove ) + ); }, - [ setResetAllFilters ] + [] ); // Manage and share display state of menu items representing child controls. @@ -193,17 +183,16 @@ export function useToolsPanel( } ); // Setup menuItems state as panel items register themselves. - useEffect( () => { - setMenuItems( ( prevState ) => { - const items = generateMenuItems( { + useLayoutEffect( () => { + setMenuItems( ( currentMenuItems ) => + generateMenuItems( { panelItems, shouldReset: false, - currentMenuItems: prevState, + currentMenuItems, menuItemOrder, - } ); - return items; - } ); - }, [ panelItems, setMenuItems, menuItemOrder ] ); + } ) + ); + }, [ panelItems, menuItemOrder ] ); // Updates the status of the panel’s menu items. For default items the // value represents whether it differs from the default and for optional @@ -225,7 +214,7 @@ export function useToolsPanel( return newState; } ); }, - [ setMenuItems ] + [] ); // Whether all optional menu items are hidden or not must be tracked @@ -235,7 +224,7 @@ export function useToolsPanel( const [ areAllOptionalControlsHidden, setAreAllOptionalControlsHidden ] = useState( false ); - useEffect( () => { + useLayoutEffect( () => { if ( isMenuItemTypeEmpty( menuItems?.default ) && ! isMenuItemTypeEmpty( menuItems?.optional ) @@ -245,7 +234,7 @@ export function useToolsPanel( ).some( ( [ , isSelected ] ) => isSelected ); setAreAllOptionalControlsHidden( allControlsHidden ); } - }, [ menuItems, setAreAllOptionalControlsHidden ] ); + }, [ menuItems ] ); const cx = useCx(); const classes = useMemo( () => { @@ -297,7 +286,7 @@ export function useToolsPanel( setMenuItems( newMenuItems ); }, - [ menuItems, panelItems, setMenuItems ] + [ menuItems, panelItems ] ); // Resets display of children and executes resetAll callback if available. @@ -314,7 +303,7 @@ export function useToolsPanel( shouldReset: true, } ); setMenuItems( resetMenuItems ); - }, [ panelItems, resetAllFilters, resetAll, setMenuItems, menuItemOrder ] ); + }, [ panelItems, resetAllFilters, resetAll, menuItemOrder ] ); // Assist ItemGroup styling when there are potentially hidden placeholder // items by identifying first & last items that are toggled on for display. From 27fe9522dda47bc1f2d0aec74e6eafa8c1eeb84a Mon Sep 17 00:00:00 2001 From: dhruvang21 <105810308+dhruvang21@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:40:10 +0530 Subject: [PATCH 0887/1908] Added keywords to query loop block (#65515) * Add keywords to query loop block * Update keyword post types to custom post types Co-authored-by: Sarah Norris <1645628+mikachan@users.noreply.github.com> --------- Co-authored-by: dhruvang21 <dhruvang21@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> --- packages/block-library/src/query/block.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/query/block.json b/packages/block-library/src/query/block.json index 22bfa7b713801c..b2225192c6b218 100644 --- a/packages/block-library/src/query/block.json +++ b/packages/block-library/src/query/block.json @@ -5,6 +5,7 @@ "title": "Query Loop", "category": "theme", "description": "An advanced block that allows displaying post types based on different query parameters and visual configurations.", + "keywords": [ "posts", "list", "blog", "blogs", "custom post types" ], "textdomain": "default", "attributes": { "queryId": { From e9c38589390678f2fa97a16223394492cae7b389 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Fri, 20 Sep 2024 12:14:12 +0100 Subject: [PATCH 0888/1908] Select Mode: Blocks outside the main sections root should be disabled (#65518) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> --- packages/block-editor/src/store/selectors.js | 73 ++++++++---- .../block-editor/src/store/test/selectors.js | 105 ++++++++++++++++-- 2 files changed, 150 insertions(+), 28 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 806e2b5f5993eb..20d6627398886c 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2901,6 +2901,14 @@ export function __unstableIsWithinBlockOverlay( state, clientId ) { return false; } +function isWithinBlock( state, clientId, parentClientId ) { + let parent = state.blocks.parents.get( clientId ); + while ( !! parent && parent !== parentClientId ) { + parent = state.blocks.parents.get( parent ); + } + return parent === parentClientId; +} + /** * @typedef {import('../components/block-editing-mode').BlockEditingMode} BlockEditingMode */ @@ -2968,36 +2976,58 @@ export const getBlockEditingMode = createRegistrySelector( return 'disabled'; } + if ( editorMode === 'navigation' ) { + const sectionRootClientId = getSectionRootClientId( state ); + + // The root section is "default mode" + if ( clientId === sectionRootClientId ) { + return 'default'; + } + + // Sections should always be contentOnly in navigation mode. + const sectionsClientIds = getBlockOrder( + state, + sectionRootClientId + ); + if ( sectionsClientIds.includes( clientId ) ) { + return 'contentOnly'; + } + + // Blocks outside sections should be disabled. + const isWithinSectionRoot = isWithinBlock( + state, + clientId, + sectionRootClientId + ); + if ( ! isWithinSectionRoot ) { + return 'disabled'; + } + + // The rest of the blocks depend on whether they are content blocks or not. + // This "flattens" the sections tree. + const name = getBlockName( state, clientId ); + const isContent = + select( blocksStore ).__experimentalHasContentRoleAttribute( + name + ); + return isContent ? 'contentOnly' : 'disabled'; + } + + // In normal mode, consider that an explicitely set editing mode takes over. const blockEditingMode = state.blockEditingModes.get( clientId ); if ( blockEditingMode ) { return blockEditingMode; } + + // In normal mode, top level is default mode. if ( ! clientId ) { return 'default'; } - const sectionRootClientId = getSectionRootClientId( state ); - if ( - editorMode === 'navigation' && - clientId === sectionRootClientId - ) { - return 'default'; - } - const sectionsClientIds = getBlockOrder( - state, - sectionRootClientId - ); + const rootClientId = getBlockRootClientId( state, clientId ); const templateLock = getTemplateLock( state, rootClientId ); - if ( - templateLock === 'contentOnly' || - editorMode === 'navigation' - ) { - // Sections should always be contentOnly in navigation mode. - // This will also cause them to display in List View providing - // a structure. - if ( sectionsClientIds.includes( clientId ) ) { - return 'contentOnly'; - } + // If the parent of the block is contentOnly locked, check whether it's a content block. + if ( templateLock === 'contentOnly' ) { const name = getBlockName( state, clientId ); const isContent = select( blocksStore ).__experimentalHasContentRoleAttribute( @@ -3005,6 +3035,7 @@ export const getBlockEditingMode = createRegistrySelector( ); return isContent ? 'contentOnly' : 'disabled'; } + // Otherwise, check if there's an ancestor that is contentOnly const parentMode = getBlockEditingMode( state, rootClientId ); return parentMode === 'contentOnly' ? 'default' : parentMode; } diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index 04899a9ee243fd..2895f6573dc54f 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -15,6 +15,7 @@ import { select, dispatch } from '@wordpress/data'; */ import * as selectors from '../selectors'; import { store } from '../'; +import { sectionRootClientIdKey } from '../private-keys'; const { getBlockName, @@ -4382,12 +4383,28 @@ describe( 'getBlockEditingMode', () => { settings: {}, blocks: { byClientId: new Map( [ - [ '6cf70164-9097-4460-bcbf-200560546988', {} ], // Header - [ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', {} ], // Group - [ 'b26fc763-417d-4f01-b81c-2ec61e14a972', {} ], // | Post Title - [ '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', {} ], // | Post Content - [ 'b3247f75-fd94-4fef-97f9-5bfd162cc416', {} ], // | | Paragraph - [ 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', {} ], // | | Paragraph + [ + '6cf70164-9097-4460-bcbf-200560546988', + { name: 'core/template-part' }, + ], // Header + [ + 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', + { name: 'core/group' }, + ], // Group + [ + 'b26fc763-417d-4f01-b81c-2ec61e14a972', + { name: 'core/post-title' }, + ], // | Post Title + [ + '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', + { name: 'core/group' }, + ], // | Group + [ 'b3247f75-fd94-4fef-97f9-5bfd162cc416', { name: 'core/p' } ], // | | Paragraph + [ 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', { name: 'core/p' } ], // | | Paragraph + [ + '9b9c5c3f-2e46-4f02-9e14-9fed515b958s', + { name: 'core/group' }, + ], // | | Group ] ), order: new Map( [ [ @@ -4411,10 +4428,12 @@ describe( 'getBlockEditingMode', () => { [ 'b3247f75-fd94-4fef-97f9-5bfd162cc416', 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', + '9b9c5c3f-2e46-4f02-9e14-9fed515b958s', ], ], [ 'b3247f75-fd94-4fef-97f9-5bfd162cc416', [] ], [ 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', [] ], + [ '9b9c5c3f-2e46-4f02-9e14-9fed515b958s', [] ], ] ), parents: new Map( [ [ '6cf70164-9097-4460-bcbf-200560546988', '' ], @@ -4435,6 +4454,10 @@ describe( 'getBlockEditingMode', () => { 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', ], + [ + '9b9c5c3f-2e46-4f02-9e14-9fed515b958s', + '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', + ], ] ), }, blockListSettings: { @@ -4444,7 +4467,18 @@ describe( 'getBlockEditingMode', () => { blockEditingModes: new Map( [] ), }; - const __experimentalHasContentRoleAttribute = jest.fn( () => false ); + const navigationModeStateWithRootSection = { + ...baseState, + editorMode: 'navigation', + settings: { + [ sectionRootClientIdKey ]: 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', // The group is the "main" container + }, + }; + + const __experimentalHasContentRoleAttribute = jest.fn( ( name ) => { + // consider paragraphs as content blocks. + return name === 'core/p'; + } ); getBlockEditingMode.registry = { select: jest.fn( () => ( { __experimentalHasContentRoleAttribute, @@ -4573,4 +4607,61 @@ describe( 'getBlockEditingMode', () => { getBlockEditingMode( state, 'b3247f75-fd94-4fef-97f9-5bfd162cc416' ) ).toBe( 'contentOnly' ); } ); + + it( 'in navigation mode, the root section container is default', () => { + expect( + getBlockEditingMode( + navigationModeStateWithRootSection, + 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337' + ) + ).toBe( 'default' ); + } ); + + it( 'in navigation mode, anything outside the section container is disabled', () => { + expect( + getBlockEditingMode( + navigationModeStateWithRootSection, + '6cf70164-9097-4460-bcbf-200560546988' + ) + ).toBe( 'disabled' ); + } ); + + it( 'in navigation mode, sections are contentOnly', () => { + expect( + getBlockEditingMode( + navigationModeStateWithRootSection, + 'b26fc763-417d-4f01-b81c-2ec61e14a972' + ) + ).toBe( 'contentOnly' ); + expect( + getBlockEditingMode( + navigationModeStateWithRootSection, + '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f' + ) + ).toBe( 'contentOnly' ); + } ); + + it( 'in navigation mode, blocks with content attributes within sections are contentOnly', () => { + expect( + getBlockEditingMode( + navigationModeStateWithRootSection, + 'b3247f75-fd94-4fef-97f9-5bfd162cc416' + ) + ).toBe( 'contentOnly' ); + expect( + getBlockEditingMode( + navigationModeStateWithRootSection, + 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c' + ) + ).toBe( 'contentOnly' ); + } ); + + it( 'in navigation mode, blocks without content attributes within sections are disabled', () => { + expect( + getBlockEditingMode( + navigationModeStateWithRootSection, + '9b9c5c3f-2e46-4f02-9e14-9fed515b958s' + ) + ).toBe( 'disabled' ); + } ); } ); From ff112d76363fb3a89c8ab4e3c6fcfa52c37bd3ff Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Fri, 20 Sep 2024 13:46:47 +0200 Subject: [PATCH 0889/1908] Block Bindings: Remove key fallback in bindings get values and rely on source label (#65517) * Always fall back to source label * Adapt e2e tests Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- .../src/hooks/use-bindings-attributes.js | 5 ++-- .../editor/various/block-bindings.spec.js | 26 +------------------ 2 files changed, 3 insertions(+), 28 deletions(-) diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index e1ebf5fda6b8ee..ac045004cc654b 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -162,9 +162,8 @@ export const withBlockBindingSupport = createHigherOrderComponent( let values = {}; if ( ! source.getValues ) { Object.keys( bindings ).forEach( ( attr ) => { - // Default to the `key` or the source label when `getValues` doesn't exist - values[ attr ] = - bindings[ attr ].args?.key || source.label; + // Default to the the source label when `getValues` doesn't exist. + values[ attr ] = source.label; } ); } else { values = source.getValues( { diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index c556c469698ebd..90a5d2b1da9f10 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -66,7 +66,7 @@ test.describe( 'Block bindings', () => { ); } ); - test( 'should show the key of the custom field in server sources with key', async ( { + test( 'should always show the source label in server-only sources', async ( { editor, } ) => { await editor.insertBlock( { @@ -86,30 +86,6 @@ test.describe( 'Block bindings', () => { const paragraphBlock = editor.canvas.getByRole( 'document', { name: 'Block: Paragraph', } ); - await expect( paragraphBlock ).toHaveText( - 'text_custom_field' - ); - } ); - - test( 'should show the source label in server sources without key', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - content: 'paragraph default content', - metadata: { - bindings: { - content: { - source: 'core/server-source', - }, - }, - }, - }, - } ); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); await expect( paragraphBlock ).toHaveText( 'Server Source' ); } ); From 2632234b2bdd6ef8e8b89e7521d370cfa0041764 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:39:28 +0200 Subject: [PATCH 0890/1908] Script Modules: Centralize registration (#65460) Rework how Script Modules are registered in Gutenberg. Script Module registration is handled in one central place. A combined assets file is used for Script Modules and registration. This means that dependencies and versions will be used correctly and kept up-to-date while avoiding repeated file reads. Block library Script Module assets that are enqueued on demand _are registered in a centralized location_. The assets are enqueued on demand. **This requires a Core change** since the block library PHP files are synced to Core and also require centralized Script Module registration (https://github.com/WordPress/wordpress-develop/pull/7360). This solves a problem where Gutenberg-specific code was being shipped in Core through block-library. The block library Script Module asset Module IDs are renamed to indicate they are view files and align with the naming from #65064: @wordpress/block-library/query is @wordpress/block-library/query/view (indicating it is a view file). --- This is sufficient to change Script Modules to use Gutenberg in a backwards compatible way: - `@wordpress/ineractivity` and `@wordpress/interactivity-router` were registered on `wp_enqueue_scripts`. That action fires after the `wp_default_scripts` used here. Registering an already registered Script Module is a no-op. This change registers first. - The only other Script Modules currently available in Core are from the block library. Those have been registered conditionally on use. The ID is changed here, so there's little risk of the wrong version being used. There is a Core companion PR that will be necessary to land: https://github.com/WordPress/wordpress-develop/pull/7360 --- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- .github/workflows/unit-test.yml | 5 +- backport-changelog/6.7/7360.md | 3 ++ lib/client-assets.php | 50 +++++++++++++++++++ lib/experimental/script-modules.php | 25 +--------- lib/interactivity-api.php | 31 ------------ packages/block-library/src/file/index.php | 13 +---- packages/block-library/src/image/index.php | 14 +----- .../block-library/src/navigation/index.php | 13 +---- packages/block-library/src/query/index.php | 22 +------- packages/block-library/src/search/index.php | 13 +---- tools/webpack/script-modules.js | 12 +++-- 11 files changed, 72 insertions(+), 129 deletions(-) create mode 100644 backport-changelog/6.7/7360.md diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index c0f70070908c1c..b80804b824e3cd 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -135,7 +135,9 @@ jobs: uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: build-assets - path: ./build/ + path: | + ./build/ + ./build-module/ test-php: name: PHP ${{ matrix.php }}${{ matrix.multisite && ' multisite' || '' }}${{ matrix.wordpress != '' && format( ' (WP {0}) ', matrix.wordpress ) || '' }} on ubuntu-latest @@ -212,7 +214,6 @@ jobs: uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: build-assets - path: ./build - name: Docker debug information run: | diff --git a/backport-changelog/6.7/7360.md b/backport-changelog/6.7/7360.md new file mode 100644 index 00000000000000..b2fb8efd624b93 --- /dev/null +++ b/backport-changelog/6.7/7360.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7360 + +* https://github.com/WordPress/gutenberg/pull/65460 diff --git a/lib/client-assets.php b/lib/client-assets.php index 62e874d6b06c82..2343530e5595a7 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -601,6 +601,56 @@ function gutenberg_register_vendor_scripts( $scripts ) { } add_action( 'wp_default_scripts', 'gutenberg_register_vendor_scripts' ); +/** + * Registers or re-registers Gutenberg Script Modules. + * + * Script modules that are registered by Core will be re-registered by Gutenberg. + * + * @since 19.3.0 + */ +function gutenberg_default_script_modules() { + /* + * Expects multidimensional array like: + * + * 'interactivity/index.min.js' => array('dependencies' => array(…), 'version' => '…'), + * 'interactivity/debug.min.js' => array('dependencies' => array(…), 'version' => '…'), + * 'interactivity-router/index.min.js' => … + */ + $assets = include gutenberg_dir_path() . '/build-module/assets.php'; + + foreach ( $assets as $file_name => $script_module_data ) { + /* + * Build the WordPress Script Module ID from the file name. + * Prepend `@wordpress/` and remove extensions and `/index` if present: + * - interactivity/index.min.js => @wordpress/interactivity + * - interactivity/debug.min.js => @wordpress/interactivity/debug + * - block-library/query/view.js => @wordpress/block-library/query/view + */ + $script_module_id = '@wordpress/' . preg_replace( '~(?:/index)?\.min\.js$~D', '', $file_name, 1 ); + switch ( $script_module_id ) { + /* + * Interactivity exposes two entrypoints, "/index" and "/debug". + * "/debug" should replalce "/index" in devlopment. + */ + case '@wordpress/interactivity/debug': + if ( ! SCRIPT_DEBUG ) { + continue 2; + } + $script_module_id = '@wordpress/interactivity'; + break; + case '@wordpress/interactivity': + if ( SCRIPT_DEBUG ) { + continue 2; + } + break; + } + + $path = gutenberg_url( "build-module/{$file_name}" ); + wp_register_script_module( $script_module_id, $path, $script_module_data['dependencies'], $script_module_data['version'] ); + } +} +remove_action( 'wp_default_scripts', 'wp_default_script_modules' ); +add_action( 'wp_default_scripts', 'gutenberg_default_script_modules' ); /* * Always remove the Core action hook while gutenberg_enqueue_stored_styles() exists to avoid styles being printed twice. diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index f65bc1704dd890..fe23786fc03621 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -239,26 +239,5 @@ function gutenberg_a11y_script_module_html() { . '<div id="a11y-speak-polite" class="a11y-speak-region" aria-live="polite" aria-relevant="additions text" aria-atomic="true"></div>' . '</div>'; } - -/** - * Registers Gutenberg Script Modules. - * - * @since 19.3 - */ -function gutenberg_register_script_modules() { - // When in production, use the plugin's version as the default asset version; - // else (for development or test) default to use the current time. - $default_version = defined( 'GUTENBERG_VERSION' ) && ! SCRIPT_DEBUG ? GUTENBERG_VERSION : time(); - - wp_deregister_script_module( '@wordpress/a11y' ); - wp_register_script_module( - '@wordpress/a11y', - gutenberg_url( 'build-module/a11y/index.min.js' ), - array(), - $default_version - ); - - add_action( 'wp_footer', 'gutenberg_a11y_script_module_html' ); - add_action( 'admin_footer', 'gutenberg_a11y_script_module_html' ); -} -add_action( 'init', 'gutenberg_register_script_modules' ); +add_action( 'wp_footer', 'gutenberg_a11y_script_module_html' ); +add_action( 'admin_footer', 'gutenberg_a11y_script_module_html' ); diff --git a/lib/interactivity-api.php b/lib/interactivity-api.php index c00d68bc70e8e2..ff68936f054a7e 100644 --- a/lib/interactivity-api.php +++ b/lib/interactivity-api.php @@ -5,37 +5,6 @@ * @package gutenberg */ -/** - * Deregisters the Core Interactivity API Modules and replace them - * with the ones from the Gutenberg plugin. - */ -function gutenberg_reregister_interactivity_script_modules() { - $default_version = defined( 'GUTENBERG_VERSION' ) && ! SCRIPT_DEBUG ? GUTENBERG_VERSION : time(); - wp_deregister_script_module( '@wordpress/interactivity' ); - wp_deregister_script_module( '@wordpress/interactivity-router' ); - - wp_register_script_module( - '@wordpress/interactivity', - gutenberg_url( '/build-module/' . ( SCRIPT_DEBUG ? 'interactivity/debug.min.js' : 'interactivity/index.min.js' ) ), - array(), - $default_version - ); - - wp_register_script_module( - '@wordpress/interactivity-router', - gutenberg_url( '/build-module/interactivity-router/index.min.js' ), - array( - array( - 'id' => '@wordpress/a11y', - 'import' => 'dynamic', - ), - '@wordpress/interactivity', - ), - $default_version - ); -} -add_action( 'init', 'gutenberg_reregister_interactivity_script_modules' ); - /** * Adds script data to the interactivity-router script module. * diff --git a/packages/block-library/src/file/index.php b/packages/block-library/src/file/index.php index 85cc840201da59..8ea668d56d8545 100644 --- a/packages/block-library/src/file/index.php +++ b/packages/block-library/src/file/index.php @@ -19,18 +19,7 @@ function render_block_core_file( $attributes, $content ) { // If it's interactive, enqueue the script module and add the directives. if ( ! empty( $attributes['displayPreview'] ) ) { - $suffix = wp_scripts_get_suffix(); - if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) { - $module_url = gutenberg_url( '/build-module/block-library/file/view.min.js' ); - } - - wp_register_script_module( - '@wordpress/block-library/file', - isset( $module_url ) ? $module_url : includes_url( "blocks/file/view{$suffix}.js" ), - array( '@wordpress/interactivity' ), - defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' ) - ); - wp_enqueue_script_module( '@wordpress/block-library/file' ); + wp_enqueue_script_module( '@wordpress/block-library/file/view' ); $processor = new WP_HTML_Tag_Processor( $content ); $processor->next_tag(); diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index abbb03c0952452..5d7815a1f2f3fb 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -70,19 +70,7 @@ function render_block_core_image( $attributes, $content, $block ) { isset( $lightbox_settings['enabled'] ) && true === $lightbox_settings['enabled'] ) { - $suffix = wp_scripts_get_suffix(); - if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) { - $module_url = gutenberg_url( '/build-module/block-library/image/view.min.js' ); - } - - wp_register_script_module( - '@wordpress/block-library/image', - isset( $module_url ) ? $module_url : includes_url( "blocks/image/view{$suffix}.js" ), - array( '@wordpress/interactivity' ), - defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' ) - ); - - wp_enqueue_script_module( '@wordpress/block-library/image' ); + wp_enqueue_script_module( '@wordpress/block-library/image/view' ); /* * This render needs to happen in a filter with priority 15 to ensure that diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index ec72b03b6906f0..10fec84ed59d9c 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -622,18 +622,7 @@ private static function get_nav_element_directives( $is_interactive ) { */ private static function handle_view_script_module_loading( $attributes, $block, $inner_blocks ) { if ( static::is_interactive( $attributes, $inner_blocks ) ) { - $suffix = wp_scripts_get_suffix(); - if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) { - $module_url = gutenberg_url( '/build-module/block-library/navigation/view.min.js' ); - } - - wp_register_script_module( - '@wordpress/block-library/navigation', - isset( $module_url ) ? $module_url : includes_url( "blocks/navigation/view{$suffix}.js" ), - array( '@wordpress/interactivity' ), - defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' ) - ); - wp_enqueue_script_module( '@wordpress/block-library/navigation' ); + wp_enqueue_script_module( '@wordpress/block-library/navigation/view' ); } } diff --git a/packages/block-library/src/query/index.php b/packages/block-library/src/query/index.php index d10db26529854e..043f351e11d7f1 100644 --- a/packages/block-library/src/query/index.php +++ b/packages/block-library/src/query/index.php @@ -24,27 +24,7 @@ function render_block_core_query( $attributes, $content, $block ) { // Enqueue the script module and add the necessary directives if the block is // interactive. if ( $is_interactive ) { - $suffix = wp_scripts_get_suffix(); - if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) { - $module_url = gutenberg_url( '/build-module/block-library/query/view.min.js' ); - } - - wp_register_script_module( - '@wordpress/block-library/query', - isset( $module_url ) ? $module_url : includes_url( "blocks/query/view{$suffix}.js" ), - array( - array( - 'id' => '@wordpress/interactivity', - 'import' => 'static', - ), - array( - 'id' => '@wordpress/interactivity-router', - 'import' => 'dynamic', - ), - ), - defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' ) - ); - wp_enqueue_script_module( '@wordpress/block-library/query' ); + wp_enqueue_script_module( '@wordpress/block-library/query/view' ); $p = new WP_HTML_Tag_Processor( $content ); if ( $p->next_tag() ) { diff --git a/packages/block-library/src/search/index.php b/packages/block-library/src/search/index.php index fb09cdd36406e8..e4259bb0ce2c7f 100644 --- a/packages/block-library/src/search/index.php +++ b/packages/block-library/src/search/index.php @@ -80,18 +80,7 @@ function render_block_core_search( $attributes ) { // If it's interactive, enqueue the script module and add the directives. $is_expandable_searchfield = 'button-only' === $button_position; if ( $is_expandable_searchfield ) { - $suffix = wp_scripts_get_suffix(); - if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) { - $module_url = gutenberg_url( '/build-module/block-library/search/view.min.js' ); - } - - wp_register_script_module( - '@wordpress/block-library/search', - isset( $module_url ) ? $module_url : includes_url( "blocks/search/view{$suffix}.js" ), - array( '@wordpress/interactivity' ), - defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' ) - ); - wp_enqueue_script_module( '@wordpress/block-library/search' ); + wp_enqueue_script_module( '@wordpress/block-library/search/view' ); $input->set_attribute( 'data-wp-bind--aria-hidden', '!context.isSearchInputVisible' ); $input->set_attribute( 'data-wp-bind--tabindex', 'state.tabindex' ); diff --git a/tools/webpack/script-modules.js b/tools/webpack/script-modules.js index 18287c96d83c8a..021f11f5f5ed95 100644 --- a/tools/webpack/script-modules.js +++ b/tools/webpack/script-modules.js @@ -89,11 +89,11 @@ module.exports = { }, output: { devtoolNamespace: 'wp', - filename: './build-module/[name].min.js', + filename: '[name].min.js', library: { type: 'module', }, - path: join( __dirname, '..', '..' ), + path: join( __dirname, '..', '..', 'build-module' ), environment: { module: true }, module: true, chunkFormat: 'module', @@ -102,7 +102,13 @@ module.exports = { resolve: { extensions: [ '.js', '.ts', '.tsx' ], }, - plugins: [ ...plugins, new DependencyExtractionWebpackPlugin() ], + plugins: [ + ...plugins, + new DependencyExtractionWebpackPlugin( { + combineAssets: true, + combinedOutputFile: `./assets.php`, + } ), + ], watchOptions: { ignored: [ '**/node_modules' ], aggregateTimeout: 500, From 0d2ebd0c5b5198ef8946aae62886960efd87df9e Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Fri, 20 Sep 2024 14:32:45 +0100 Subject: [PATCH 0891/1908] Decouple "zoom/scaling the canvas" from zoom out mode (without mode rename) (#65482) * Use separate state for Zoom Level Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> # Conflicts: # packages/block-editor/src/components/block-tools/zoom-out-toolbar.js # packages/block-editor/src/components/tool-selector/index.js # packages/block-editor/src/store/reducer.js # packages/edit-site/src/components/global-styles/screen-style-variations.js # packages/editor/src/components/visual-editor/index.js * Refactor useZoomOut hook to use new state # Conflicts: # packages/block-editor/src/hooks/use-zoom-out.js * Use Zoom and Editor Mode in Toggle * Only hide footer when zoom level is set # Conflicts: # packages/editor/src/components/editor-interface/index.js * Adjust double click to exit zoom out mode * Standardise nomenclature * More standardisation of nomenclature * Reduce complexity of state and actions * Fix accidental breakage of Styles panel zoom * Fix hook * Reduce hook to single effect --- packages/block-editor/README.md | 4 +- .../use-block-props/use-zoom-out-mode-exit.js | 10 ++-- .../block-tools/zoom-out-toolbar.js | 7 ++- .../src/components/tool-selector/index.js | 5 +- .../block-editor/src/hooks/use-zoom-out.js | 48 ++++++++----------- .../block-editor/src/store/private-actions.js | 23 +++++++++ .../src/store/private-selectors.js | 20 ++++++++ packages/block-editor/src/store/reducer.js | 20 ++++++++ .../src/components/editor-interface/index.js | 10 ++-- .../src/components/visual-editor/index.js | 14 +++--- .../src/components/zoom-out-toggle/index.js | 23 ++++++--- 11 files changed, 133 insertions(+), 51 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index a474d1df7e56d0..75d7e8879572d4 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -1027,11 +1027,11 @@ _Parameters_ ### useZoomOut -A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode. +A hook used to set the zoomed out view, invoking the hook sets the mode. _Parameters_ -- _zoomOut_ `boolean`: If we should enter into zoomOut mode or not +- _zoomOut_ `boolean`: If we should zoom out or not. ### Warning diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js b/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js index d0001bd3b33c68..92c54bac9b806d 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js @@ -16,14 +16,17 @@ import { unlock } from '../../../lock-unlock'; * @param {string} clientId Block client ID. */ export function useZoomOutModeExit( { editorMode } ) { - const { getSettings } = useSelect( blockEditorStore ); - const { __unstableSetEditorMode } = unlock( + const { getSettings, isZoomOut } = unlock( useSelect( blockEditorStore ) ); + const { __unstableSetEditorMode, resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); return useRefEffect( ( node ) => { - if ( editorMode !== 'zoom-out' ) { + // In "compose" mode. + const composeMode = editorMode === 'zoom-out' && isZoomOut(); + + if ( ! composeMode ) { return; } @@ -39,6 +42,7 @@ export function useZoomOutModeExit( { editorMode } ) { __experimentalSetIsInserterOpened( false ); } __unstableSetEditorMode( 'edit' ); + resetZoomLevel(); } } diff --git a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js index 560bfc6ebb58d6..b8736de11481a0 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js @@ -15,6 +15,7 @@ import BlockDraggable from '../block-draggable'; import BlockMover from '../block-mover'; import Shuffle from '../block-toolbar/shuffle'; import NavigableToolbar from '../navigable-toolbar'; +import { unlock } from '../../lock-unlock'; export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { const selected = useSelect( @@ -76,8 +77,9 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { setIsInserterOpened, } = selected; - const { removeBlock, __unstableSetEditorMode } = - useDispatch( blockEditorStore ); + const { removeBlock, __unstableSetEditorMode, resetZoomLevel } = unlock( + useDispatch( blockEditorStore ) + ); const showBlockDraggable = canMove && ! isBlockTemplatePart; @@ -132,6 +134,7 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { setIsInserterOpened( false ); } __unstableSetEditorMode( 'edit' ); + resetZoomLevel(); __unstableContentRef.current?.focus(); } } /> diff --git a/packages/block-editor/src/components/tool-selector/index.js b/packages/block-editor/src/components/tool-selector/index.js index bf55c78caf489a..53fab037ba3684 100644 --- a/packages/block-editor/src/components/tool-selector/index.js +++ b/packages/block-editor/src/components/tool-selector/index.js @@ -18,6 +18,7 @@ import { Icon, edit as editIcon } from '@wordpress/icons'; * Internal dependencies */ import { store as blockEditorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; const selectIcon = ( <SVG @@ -35,7 +36,9 @@ function ToolSelector( props, ref ) { ( select ) => select( blockEditorStore ).__unstableGetEditorMode(), [] ); - const { __unstableSetEditorMode } = useDispatch( blockEditorStore ); + const { __unstableSetEditorMode } = unlock( + useDispatch( blockEditorStore ) + ); return ( <Dropdown diff --git a/packages/block-editor/src/hooks/use-zoom-out.js b/packages/block-editor/src/hooks/use-zoom-out.js index d7e21ec1be0578..2a1b43060c00a9 100644 --- a/packages/block-editor/src/hooks/use-zoom-out.js +++ b/packages/block-editor/src/hooks/use-zoom-out.js @@ -8,46 +8,40 @@ import { useEffect, useRef } from '@wordpress/element'; * Internal dependencies */ import { store as blockEditorStore } from '../store'; +import { unlock } from '../lock-unlock'; /** - * A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode. + * A hook used to set the zoomed out view, invoking the hook sets the mode. * - * @param {boolean} zoomOut If we should enter into zoomOut mode or not + * @param {boolean} zoomOut If we should zoom out or not. */ export function useZoomOut( zoomOut = true ) { - const { __unstableSetEditorMode } = useDispatch( blockEditorStore ); - const { __unstableGetEditorMode } = useSelect( blockEditorStore ); + const { setZoomLevel } = unlock( useDispatch( blockEditorStore ) ); + const { isZoomOut } = unlock( useSelect( blockEditorStore ) ); - const originalEditingModeRef = useRef( null ); - const mode = __unstableGetEditorMode(); + const originalIsZoomOutRef = useRef( null ); useEffect( () => { // Only set this on mount so we know what to return to when we unmount. - if ( ! originalEditingModeRef.current ) { - originalEditingModeRef.current = mode; + if ( ! originalIsZoomOutRef.current ) { + originalIsZoomOutRef.current = isZoomOut(); } - return () => { - // We need to use __unstableGetEditorMode() here and not `mode`, as mode may not update on unmount - if ( - __unstableGetEditorMode() === 'zoom-out' && - __unstableGetEditorMode() !== originalEditingModeRef.current - ) { - __unstableSetEditorMode( originalEditingModeRef.current ); - } - }; - }, [] ); - - // The effect opens the zoom-out view if we want it open and it's not currently in zoom-out mode. - useEffect( () => { - if ( zoomOut && mode !== 'zoom-out' ) { - __unstableSetEditorMode( 'zoom-out' ); + // The effect opens the zoom-out view if we want it open and the canvas is not currently zoomed-out. + if ( zoomOut && isZoomOut() === false ) { + setZoomLevel( 50 ); } else if ( ! zoomOut && - __unstableGetEditorMode() === 'zoom-out' && - originalEditingModeRef.current !== mode + isZoomOut() && + originalIsZoomOutRef.current !== isZoomOut() ) { - __unstableSetEditorMode( originalEditingModeRef.current ); + setZoomLevel( originalIsZoomOutRef.current ? 50 : 100 ); } - }, [ __unstableGetEditorMode, __unstableSetEditorMode, zoomOut ] ); // Mode is deliberately excluded from the dependencies so that the effect does not run when mode changes. + + return () => { + if ( isZoomOut() && isZoomOut() !== originalIsZoomOutRef.current ) { + setZoomLevel( originalIsZoomOutRef.current ? 50 : 100 ); + } + }; + }, [ isZoomOut, setZoomLevel, zoomOut ] ); } diff --git a/packages/block-editor/src/store/private-actions.js b/packages/block-editor/src/store/private-actions.js index dc57d61fd6b76c..441a07202c42ac 100644 --- a/packages/block-editor/src/store/private-actions.js +++ b/packages/block-editor/src/store/private-actions.js @@ -383,3 +383,26 @@ export const modifyContentLockBlock = focusModeToRevert ); }; + +/** + * Sets the zoom level. + * + * @param {number} zoom the new zoom level + * @return {Object} Action object. + */ +export function setZoomLevel( zoom = 100 ) { + return { + type: 'SET_ZOOM_LEVEL', + zoom, + }; +} + +/** + * Resets the Zoom state. + * @return {Object} Action object. + */ +export function resetZoomLevel() { + return { + type: 'RESET_ZOOM_LEVEL', + }; +} diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 0e77e8e2ed433d..d8955bd6342c4c 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -616,3 +616,23 @@ export function isZoomOutMode( state ) { export function getSectionRootClientId( state ) { return state.settings?.[ sectionRootClientIdKey ]; } + +/** + * Returns the zoom out state. + * + * @param {Object} state Global application state. + * @return {boolean} The zoom out state. + */ +export function getZoomLevel( state ) { + return state.zoomLevel; +} + +/** + * Returns whether the editor is considered zoomed out. + * + * @param {Object} state Global application state. + * @return {boolean} Whether the editor is zoomed. + */ +export function isZoomOut( state ) { + return getZoomLevel( state ) < 100; +} diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 3a99d18ef17ee3..827a2141f44c1c 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -2060,6 +2060,25 @@ export function hoveredBlockClientId( state = false, action ) { return state; } +/** + * Reducer setting zoom out state. + * + * @param {boolean} state Current state. + * @param {Object} action Dispatched action. + * + * @return {boolean} Updated state. + */ +export function zoomLevel( state = 100, action ) { + switch ( action.type ) { + case 'SET_ZOOM_LEVEL': + return action.zoom; + case 'RESET_ZOOM_LEVEL': + return 100; + } + + return state; +} + const combinedReducers = combineReducers( { blocks, isDragging, @@ -2092,6 +2111,7 @@ const combinedReducers = combineReducers( { openedBlockSettingsMenu, registeredInserterMediaCategories, hoveredBlockClientId, + zoomLevel, } ); function withAutomaticChangeReset( reducer ) { diff --git a/packages/editor/src/components/editor-interface/index.js b/packages/editor/src/components/editor-interface/index.js index 645e5fb6f53a26..0709b91175712d 100644 --- a/packages/editor/src/components/editor-interface/index.js +++ b/packages/editor/src/components/editor-interface/index.js @@ -32,6 +32,8 @@ import TextEditor from '../text-editor'; import VisualEditor from '../visual-editor'; import EditorContentSlotFill from './content-slot-fill'; +import { unlock } from '../../lock-unlock'; + const interfaceLabels = { /* translators: accessibility text for the editor top bar landmark region. */ header: __( 'Editor top bar' ), @@ -71,12 +73,13 @@ export default function EditorInterface( { nextShortcut, showBlockBreadcrumbs, documentLabel, - blockEditorMode, + isZoomOut, } = useSelect( ( select ) => { const { get } = select( preferencesStore ); const { getEditorSettings, getPostTypeLabel } = select( editorStore ); const editorSettings = getEditorSettings(); const postTypeLabel = getPostTypeLabel(); + const { isZoomOut: _isZoomOut } = unlock( select( blockEditorStore ) ); return { mode: select( editorStore ).getEditorMode(), @@ -94,8 +97,7 @@ export default function EditorInterface( { showBlockBreadcrumbs: get( 'core', 'showBlockBreadcrumbs' ), // translators: Default label for the Document in the Block Breadcrumb. documentLabel: postTypeLabel || _x( 'Document', 'noun' ), - blockEditorMode: - select( blockEditorStore ).__unstableGetEditorMode(), + isZoomOut: _isZoomOut(), }; }, [] ); const isLargeViewport = useViewportMatch( 'medium' ); @@ -206,7 +208,7 @@ export default function EditorInterface( { isLargeViewport && showBlockBreadcrumbs && isRichEditingEnabled && - blockEditorMode !== 'zoom-out' && + ! isZoomOut && mode === 'visual' && ( <BlockBreadcrumb rootLabelText={ documentLabel } /> ) diff --git a/packages/editor/src/components/visual-editor/index.js b/packages/editor/src/components/visual-editor/index.js index 2ff115272d614b..88d2dac8ffd77c 100644 --- a/packages/editor/src/components/visual-editor/index.js +++ b/packages/editor/src/components/visual-editor/index.js @@ -174,17 +174,19 @@ function VisualEditor( { hasRootPaddingAwareAlignments, themeHasDisabledLayoutStyles, themeSupportsLayout, - isZoomOutMode, + isZoomedOut, } = useSelect( ( select ) => { - const { getSettings, __unstableGetEditorMode } = - select( blockEditorStore ); + const { getSettings, isZoomOut: _isZoomOut } = unlock( + select( blockEditorStore ) + ); + const _settings = getSettings(); return { themeHasDisabledLayoutStyles: _settings.disableLayoutStyles, themeSupportsLayout: _settings.supportsLayout, hasRootPaddingAwareAlignments: _settings.__experimentalFeatures?.useRootPaddingAwareAlignments, - isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', + isZoomedOut: _isZoomOut(), }; }, [] ); @@ -336,7 +338,7 @@ function VisualEditor( { ] ); const zoomOutProps = - isZoomOutMode && ! isTabletViewport + isZoomedOut && ! isTabletViewport ? { scale: 'default', frameSize: '48px', @@ -355,7 +357,7 @@ function VisualEditor( { // Disable resizing in mobile viewport. ! isMobileViewport && // Dsiable resizing in zoomed-out mode. - ! isZoomOutMode; + ! isZoomedOut; const shouldIframe = ! disableIframe || [ 'Tablet', 'Mobile' ].includes( deviceType ); diff --git a/packages/editor/src/components/zoom-out-toggle/index.js b/packages/editor/src/components/zoom-out-toggle/index.js index e8c7b1e50510ab..214b1c51fd6255 100644 --- a/packages/editor/src/components/zoom-out-toggle/index.js +++ b/packages/editor/src/components/zoom-out-toggle/index.js @@ -8,16 +8,27 @@ import { useDispatch, useSelect } from '@wordpress/data'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { square as zoomOutIcon } from '@wordpress/icons'; +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; + const ZoomOutToggle = () => { - const { isZoomOutMode } = useSelect( ( select ) => ( { - isZoomOutMode: - select( blockEditorStore ).__unstableGetEditorMode() === 'zoom-out', + const { isZoomOut } = useSelect( ( select ) => ( { + isZoomOut: unlock( select( blockEditorStore ) ).isZoomOut(), } ) ); - const { __unstableSetEditorMode } = useDispatch( blockEditorStore ); + const { resetZoomLevel, setZoomLevel, __unstableSetEditorMode } = unlock( + useDispatch( blockEditorStore ) + ); const handleZoomOut = () => { - __unstableSetEditorMode( isZoomOutMode ? 'edit' : 'zoom-out' ); + if ( isZoomOut ) { + resetZoomLevel(); + } else { + setZoomLevel( 50 ); + } + __unstableSetEditorMode( isZoomOut ? 'edit' : 'zoom-out' ); }; return ( @@ -25,7 +36,7 @@ const ZoomOutToggle = () => { onClick={ handleZoomOut } icon={ zoomOutIcon } label={ __( 'Toggle Zoom Out' ) } - isPressed={ isZoomOutMode } + isPressed={ isZoomOut } size="compact" /> ); From eaf2258cdeed35a4d3c690d66892981a85c4d9ed Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Fri, 20 Sep 2024 15:19:34 +0100 Subject: [PATCH 0892/1908] =?UTF-8?q?Revert=20"useToolsPanel:=20calculate?= =?UTF-8?q?=20menuItems=20in=20layout=20effect=20to=20avoid=20painting?= =?UTF-8?q?=E2=80=A6"=20(#65533)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 5e37a1316d0a39bc880bf6efff9b9f26db381690. --- packages/components/CHANGELOG.md | 4 - .../src/tools-panel/tools-panel-item/hook.ts | 13 +- .../src/tools-panel/tools-panel/hook.ts | 131 ++++++++++-------- 3 files changed, 80 insertions(+), 68 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 03d6eb30e336b0..6607700b2d2c25 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,10 +2,6 @@ ## Unreleased -### Bug Fixes - -- `ToolsPanel`: avoid paining intermediate unfinished states ([#65494](https://github.com/WordPress/gutenberg/pull/65494)). - ## 28.8.0 (2024-09-19) ### Bug Fixes diff --git a/packages/components/src/tools-panel/tools-panel-item/hook.ts b/packages/components/src/tools-panel/tools-panel-item/hook.ts index 27a0ceb27e7ce7..1e33e7c6740ded 100644 --- a/packages/components/src/tools-panel/tools-panel-item/hook.ts +++ b/packages/components/src/tools-panel/tools-panel-item/hook.ts @@ -2,7 +2,12 @@ * WordPress dependencies */ import { usePrevious } from '@wordpress/compose'; -import { useCallback, useLayoutEffect, useMemo } from '@wordpress/element'; +import { + useCallback, + useEffect, + useLayoutEffect, + useMemo, +} from '@wordpress/element'; /** * Internal dependencies @@ -96,7 +101,7 @@ export function useToolsPanelItem( deregisterPanelItem, ] ); - useLayoutEffect( () => { + useEffect( () => { if ( hasMatchingPanel ) { registerResetAllFilter( resetAllFilterCallback ); } @@ -122,7 +127,7 @@ export function useToolsPanelItem( const isValueSet = hasValue(); // Notify the panel when an item's value has changed except for optional // items without value because the item should not cause itself to hide. - useLayoutEffect( () => { + useEffect( () => { if ( ! isShownByDefault && ! isValueSet ) { return; } @@ -138,7 +143,7 @@ export function useToolsPanelItem( // Determine if the panel item's corresponding menu is being toggled and // trigger appropriate callback if it is. - useLayoutEffect( () => { + useEffect( () => { // We check whether this item is currently registered as items rendered // via fills can persist through the parent panel being remounted. // See: https://github.com/WordPress/gutenberg/pull/45673 diff --git a/packages/components/src/tools-panel/tools-panel/hook.ts b/packages/components/src/tools-panel/tools-panel/hook.ts index d67d732d4df671..931bf2494e6e34 100644 --- a/packages/components/src/tools-panel/tools-panel/hook.ts +++ b/packages/components/src/tools-panel/tools-panel/hook.ts @@ -3,7 +3,7 @@ */ import { useCallback, - useLayoutEffect, + useEffect, useMemo, useRef, useState, @@ -101,7 +101,7 @@ export function useToolsPanel( // the resetAll task. Without this, the flag is cleared after the first // control updates and forces a rerender with subsequent controls then // believing they need to reset, unfortunately using stale data. - useLayoutEffect( () => { + useEffect( () => { if ( wasResetting ) { isResettingRef.current = false; } @@ -114,66 +114,76 @@ export function useToolsPanel( ResetAllFilter[] >( [] ); - const registerPanelItem = useCallback( ( item: ToolsPanelItem ) => { - // Add item to panel items. - setPanelItems( ( items ) => { - const newItems = [ ...items ]; - // If an item with this label has already been registered, remove it - // first. This can happen when an item is moved between the default - // and optional groups. - const existingIndex = newItems.findIndex( - ( oldItem ) => oldItem.label === item.label - ); - if ( existingIndex !== -1 ) { - newItems.splice( existingIndex, 1 ); - } - return [ ...newItems, item ]; - } ); + const registerPanelItem = useCallback( + ( item: ToolsPanelItem ) => { + // Add item to panel items. + setPanelItems( ( items ) => { + const newItems = [ ...items ]; + // If an item with this label has already been registered, remove it + // first. This can happen when an item is moved between the default + // and optional groups. + const existingIndex = newItems.findIndex( + ( oldItem ) => oldItem.label === item.label + ); + if ( existingIndex !== -1 ) { + newItems.splice( existingIndex, 1 ); + } + return [ ...newItems, item ]; + } ); - // Track the initial order of item registration. This is used for - // maintaining menu item order later. - setMenuItemOrder( ( items ) => { - if ( items.includes( item.label ) ) { - return items; - } + // Track the initial order of item registration. This is used for + // maintaining menu item order later. + setMenuItemOrder( ( items ) => { + if ( items.includes( item.label ) ) { + return items; + } - return [ ...items, item.label ]; - } ); - }, [] ); + return [ ...items, item.label ]; + } ); + }, + [ setPanelItems, setMenuItemOrder ] + ); // Panels need to deregister on unmount to avoid orphans in menu state. // This is an issue when panel items are being injected via SlotFills. - const deregisterPanelItem = useCallback( ( label: string ) => { - // When switching selections between components injecting matching - // controls, e.g. both panels have a "padding" control, the - // deregistration of the first panel doesn't occur until after the - // registration of the next. - setPanelItems( ( items ) => { - const newItems = [ ...items ]; - const index = newItems.findIndex( - ( item ) => item.label === label - ); - if ( index !== -1 ) { - newItems.splice( index, 1 ); - } - return newItems; - } ); - }, [] ); + const deregisterPanelItem = useCallback( + ( label: string ) => { + // When switching selections between components injecting matching + // controls, e.g. both panels have a "padding" control, the + // deregistration of the first panel doesn't occur until after the + // registration of the next. + setPanelItems( ( items ) => { + const newItems = [ ...items ]; + const index = newItems.findIndex( + ( item ) => item.label === label + ); + if ( index !== -1 ) { + newItems.splice( index, 1 ); + } + return newItems; + } ); + }, + [ setPanelItems ] + ); const registerResetAllFilter = useCallback( ( newFilter: ResetAllFilter ) => { - setResetAllFilters( ( filters ) => [ ...filters, newFilter ] ); + setResetAllFilters( ( filters ) => { + return [ ...filters, newFilter ]; + } ); }, - [] + [ setResetAllFilters ] ); const deregisterResetAllFilter = useCallback( ( filterToRemove: ResetAllFilter ) => { - setResetAllFilters( ( filters ) => - filters.filter( ( filter ) => filter !== filterToRemove ) - ); + setResetAllFilters( ( filters ) => { + return filters.filter( + ( filter ) => filter !== filterToRemove + ); + } ); }, - [] + [ setResetAllFilters ] ); // Manage and share display state of menu items representing child controls. @@ -183,16 +193,17 @@ export function useToolsPanel( } ); // Setup menuItems state as panel items register themselves. - useLayoutEffect( () => { - setMenuItems( ( currentMenuItems ) => - generateMenuItems( { + useEffect( () => { + setMenuItems( ( prevState ) => { + const items = generateMenuItems( { panelItems, shouldReset: false, - currentMenuItems, + currentMenuItems: prevState, menuItemOrder, - } ) - ); - }, [ panelItems, menuItemOrder ] ); + } ); + return items; + } ); + }, [ panelItems, setMenuItems, menuItemOrder ] ); // Updates the status of the panel’s menu items. For default items the // value represents whether it differs from the default and for optional @@ -214,7 +225,7 @@ export function useToolsPanel( return newState; } ); }, - [] + [ setMenuItems ] ); // Whether all optional menu items are hidden or not must be tracked @@ -224,7 +235,7 @@ export function useToolsPanel( const [ areAllOptionalControlsHidden, setAreAllOptionalControlsHidden ] = useState( false ); - useLayoutEffect( () => { + useEffect( () => { if ( isMenuItemTypeEmpty( menuItems?.default ) && ! isMenuItemTypeEmpty( menuItems?.optional ) @@ -234,7 +245,7 @@ export function useToolsPanel( ).some( ( [ , isSelected ] ) => isSelected ); setAreAllOptionalControlsHidden( allControlsHidden ); } - }, [ menuItems ] ); + }, [ menuItems, setAreAllOptionalControlsHidden ] ); const cx = useCx(); const classes = useMemo( () => { @@ -286,7 +297,7 @@ export function useToolsPanel( setMenuItems( newMenuItems ); }, - [ menuItems, panelItems ] + [ menuItems, panelItems, setMenuItems ] ); // Resets display of children and executes resetAll callback if available. @@ -303,7 +314,7 @@ export function useToolsPanel( shouldReset: true, } ); setMenuItems( resetMenuItems ); - }, [ panelItems, resetAllFilters, resetAll, menuItemOrder ] ); + }, [ panelItems, resetAllFilters, resetAll, setMenuItems, menuItemOrder ] ); // Assist ItemGroup styling when there are potentially hidden placeholder // items by identifying first & last items that are toggled on for display. From 8e795580bdd03724f0a894a34418ea58e208b3e3 Mon Sep 17 00:00:00 2001 From: Vipul Gupta <55375170+vipul0425@users.noreply.github.com> Date: Fri, 20 Sep 2024 21:10:10 +0530 Subject: [PATCH 0893/1908] fix: Makes the edit mode persistent in top toolbar mode. (#65511) Co-authored-by: vipul0425 <vipulgupta003@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- packages/editor/src/components/document-tools/index.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/editor/src/components/document-tools/index.js b/packages/editor/src/components/document-tools/index.js index 54121652bbf131..6a8c20c8d70551 100644 --- a/packages/editor/src/components/document-tools/index.js +++ b/packages/editor/src/components/document-tools/index.js @@ -38,10 +38,8 @@ function DocumentTools( { className, disableBlockTools = false } ) { listViewShortcut, inserterSidebarToggleRef, listViewToggleRef, - hasFixedToolbar, showIconLabels, } = useSelect( ( select ) => { - const { getSettings } = select( blockEditorStore ); const { get } = select( preferencesStore ); const { isListViewOpened, @@ -60,7 +58,6 @@ function DocumentTools( { className, disableBlockTools = false } ) { ), inserterSidebarToggleRef: getInserterSidebarToggleRef(), listViewToggleRef: getListViewToggleRef(), - hasFixedToolbar: getSettings().hasFixedToolbar, showIconLabels: get( 'core', 'showIconLabels' ), isDistractionFree: get( 'core', 'distractionFree' ), isVisualMode: getEditorMode() === 'visual', @@ -137,7 +134,7 @@ function DocumentTools( { className, disableBlockTools = false } ) { ) } { ( isWideViewport || ! showIconLabels ) && ( <> - { isLargeViewport && ! hasFixedToolbar && ( + { isLargeViewport && ( <ToolbarItem as={ ToolSelector } showTooltip={ ! showIconLabels } From 2c4d4d6e2233abc500d6e02325a1c32783876ee1 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Fri, 20 Sep 2024 17:33:13 +0100 Subject: [PATCH 0894/1908] Select Mode: Prevent the inbetween inserter from triggering within sections (#65529) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../src/components/block-list/use-in-between-inserter.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 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 bb307816fd1501..2b76804785a576 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 @@ -11,6 +11,7 @@ import { isRTL } from '@wordpress/i18n'; */ import { store as blockEditorStore } from '../../store'; import { InsertionPointOpenRef } from '../block-tools/insertion-point'; +import { unlock } from '../../lock-unlock'; export function useInBetweenInserter() { const openRef = useContext( InsertionPointOpenRef ); @@ -31,7 +32,8 @@ export function useInBetweenInserter() { getBlockEditingMode, getBlockName, getBlockAttributes, - } = useSelect( blockEditorStore ); + getParentSectionBlock, + } = unlock( useSelect( blockEditorStore ) ); const { showInsertionPoint, hideInsertionPoint } = useDispatch( blockEditorStore ); @@ -133,7 +135,8 @@ export function useInBetweenInserter() { const clientId = element.id.slice( 'block-'.length ); if ( ! clientId || - __unstableIsWithinBlockOverlay( clientId ) + __unstableIsWithinBlockOverlay( clientId ) || + !! getParentSectionBlock( clientId ) ) { return; } From b36cbf4a1c7ad8d3a1a7a38871e153bec9497a4b Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Fri, 20 Sep 2024 17:49:35 +0100 Subject: [PATCH 0895/1908] Fix grid layout padding on small screens (#64878) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/dataviews/src/components/dataviews/style.scss | 1 - packages/dataviews/src/dataviews-layouts/grid/style.scss | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/dataviews/src/components/dataviews/style.scss b/packages/dataviews/src/components/dataviews/style.scss index 8909c7cf1c7cfd..aa8fbcfb009c05 100644 --- a/packages/dataviews/src/components/dataviews/style.scss +++ b/packages/dataviews/src/components/dataviews/style.scss @@ -80,7 +80,6 @@ padding: $grid-unit-15 $grid-unit-30; } - .dataviews-view-grid, .dataviews-no-results, .dataviews-loading { padding-left: $grid-unit-30; diff --git a/packages/dataviews/src/dataviews-layouts/grid/style.scss b/packages/dataviews/src/dataviews-layouts/grid/style.scss index 5fab362b0b47b6..6286ed94685a04 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/style.scss +++ b/packages/dataviews/src/dataviews-layouts/grid/style.scss @@ -163,3 +163,11 @@ .dataviews-view-grid__card.is-selected .dataviews-selection-checkbox { top: $grid-unit-10; } + +/* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ +@container (max-width: 430px) { + .dataviews-view-grid { + padding-left: $grid-unit-30; + padding-right: $grid-unit-30; + } +} From b1d925530d22a8531a0f9c32ffe8ec4430005ab7 Mon Sep 17 00:00:00 2001 From: Sarah Norris <1645628+mikachan@users.noreply.github.com> Date: Fri, 20 Sep 2024 17:50:41 +0100 Subject: [PATCH 0896/1908] Query Loop: Remove is_singular() check and fix test (#65483) * Replace query_posts() with set() * Fix test_rendering_post_template_with_main_query_loop_already_started test * Remove is_singular check Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: jffng <jffng@git.wordpress.org> Co-authored-by: David Herrera <697432+dlh01@users.noreply.github.com> --- packages/block-library/src/post-template/index.php | 5 ----- phpunit/blocks/render-post-template-test.php | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/block-library/src/post-template/index.php b/packages/block-library/src/post-template/index.php index 64cdd156a54310..9126355c096a57 100644 --- a/packages/block-library/src/post-template/index.php +++ b/packages/block-library/src/post-template/index.php @@ -64,11 +64,6 @@ function render_block_core_post_template( $attributes, $content, $block ) { if ( in_the_loop() ) { $query = clone $wp_query; $query->rewind_posts(); - - // If in a single post of any post type, default to the 'post' post type. - if ( is_singular() ) { - query_posts( array( 'post_type' => 'post' ) ); - } } else { $query = $wp_query; } diff --git a/phpunit/blocks/render-post-template-test.php b/phpunit/blocks/render-post-template-test.php index 6241f6f0605164..e929e459654fe7 100644 --- a/phpunit/blocks/render-post-template-test.php +++ b/phpunit/blocks/render-post-template-test.php @@ -122,7 +122,7 @@ public function test_rendering_post_template_with_main_query_loop_already_starte global $wp_query, $wp_the_query; // Query block with post template block. - $content = '<!-- wp:query {"query":{"inherit":true}} -->'; + $content = '<!-- wp:query {"query":{"inherit":false}} -->'; $content .= '<!-- wp:post-template {"align":"wide"} -->'; $content .= '<!-- wp:post-title /-->'; $content .= '<!-- /wp:post-template -->'; From 219065c3be5881a68a8667fda9c04c7b7f546763 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Sat, 21 Sep 2024 05:04:37 +0900 Subject: [PATCH 0897/1908] Command Palette: Fix "Add new page" command for hybrid theme (#65534) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/admin-navigation-commands.js | 79 +++++++++++-------- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/packages/core-commands/src/admin-navigation-commands.js b/packages/core-commands/src/admin-navigation-commands.js index be5e19386b65b4..c0d8bb084b46ad 100644 --- a/packages/core-commands/src/admin-navigation-commands.js +++ b/packages/core-commands/src/admin-navigation-commands.js @@ -6,8 +6,8 @@ import { __ } from '@wordpress/i18n'; import { plus } from '@wordpress/icons'; import { getPath } from '@wordpress/url'; import { store as coreStore } from '@wordpress/core-data'; -import { useDispatch } from '@wordpress/data'; -import { useMemo } from '@wordpress/element'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { useCallback, useMemo } from '@wordpress/element'; import { store as noticesStore } from '@wordpress/notices'; import { privateApis as routerPrivateApis } from '@wordpress/router'; @@ -23,46 +23,55 @@ function useAddNewPageCommand() { 'site-editor.php' ); const history = useHistory(); + const isBlockBasedTheme = useSelect( ( select ) => { + return select( coreStore ).getCurrentTheme()?.is_block_theme; + }, [] ); const { saveEntityRecord } = useDispatch( coreStore ); const { createErrorNotice } = useDispatch( noticesStore ); - const createPageEntity = async ( { close } ) => { - try { - const page = await saveEntityRecord( - 'postType', - 'page', - { - status: 'draft', - }, - { - throwOnError: true, + const createPageEntity = useCallback( + async ( { close } ) => { + try { + const page = await saveEntityRecord( + 'postType', + 'page', + { + status: 'draft', + }, + { + throwOnError: true, + } + ); + if ( page?.id ) { + history.push( { + postId: page.id, + postType: 'page', + canvas: 'edit', + } ); } - ); - if ( page?.id ) { - history.push( { - postId: page.id, - postType: 'page', - canvas: 'edit', + } catch ( error ) { + const errorMessage = + error.message && error.code !== 'unknown_error' + ? error.message + : __( 'An error occurred while creating the item.' ); + + createErrorNotice( errorMessage, { + type: 'snackbar', } ); + } finally { + close(); } - } catch ( error ) { - const errorMessage = - error.message && error.code !== 'unknown_error' - ? error.message - : __( 'An error occurred while creating the item.' ); - - createErrorNotice( errorMessage, { - type: 'snackbar', - } ); - } finally { - close(); - } - }; + }, + [ createErrorNotice, history, saveEntityRecord ] + ); const commands = useMemo( () => { - const addNewPage = isSiteEditor - ? createPageEntity - : () => ( document.location.href = 'post-new.php?post_type=page' ); + const addNewPage = + isSiteEditor && isBlockBasedTheme + ? createPageEntity + : () => + ( document.location.href = + 'post-new.php?post_type=page' ); return [ { name: 'core/add-new-page', @@ -71,7 +80,7 @@ function useAddNewPageCommand() { callback: addNewPage, }, ]; - }, [ createPageEntity, isSiteEditor ] ); + }, [ createPageEntity, isSiteEditor, isBlockBasedTheme ] ); return { isLoading: false, From e691b04fff49023687919e31184f20f8862fa13c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:27:11 -0700 Subject: [PATCH 0898/1908] DataViews documentation: add high-level graph explaining DataViews and data sources interaction (#65457) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: juanmaguitar <juanmaguitar@git.wordpress.org> --- packages/dataviews/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 3ce895680a15c5..95b8fc898555c3 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -2,6 +2,10 @@ DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.). +DataViews is data agnostic, it can work with data coming from a static (JSON file) or dynamic source (HTTP Request) — it just requires the data to be an array of objects that have an unique identifier. Consumers are responsible to query the data source appropiately based on the DataViews props: + +![DataViews flow](https://developer.wordpress.org/files/2024/09/368600071-20aa078f-7c3d-406d-8dd0-8b764addd22a.png "DataViews flow") + ## Installation Install the module From da16125f6f6d7099207fc3d5d2da2ed8c2927022 Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Sat, 21 Sep 2024 23:11:17 +0200 Subject: [PATCH 0899/1908] BoxControl: Promote to stable (#65469) * Minor docs tweaks. * Export without experimental prefix * Replace references across gutenberg * Replace import example in a README * Auto-format README with prettier * Move Storybook stories and add redirect * Add deprecated hint to experimental export * Add changelog entries Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../global-styles/dimensions-panel.js | 2 +- packages/components/CHANGELOG.md | 2 ++ packages/components/src/box-control/README.md | 21 ++++++++----------- packages/components/src/box-control/index.tsx | 8 +++---- .../src/box-control/stories/index.story.tsx | 2 +- packages/components/src/box-control/types.ts | 6 +++--- packages/components/src/index.ts | 2 ++ .../src/tools-panel/tools-panel/README.md | 20 +++++++++--------- storybook/manager-head.html | 1 + 9 files changed, 33 insertions(+), 31 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/dimensions-panel.js b/packages/block-editor/src/components/global-styles/dimensions-panel.js index ce508a5ebc89e5..4c52de6a3d7d11 100644 --- a/packages/block-editor/src/components/global-styles/dimensions-panel.js +++ b/packages/block-editor/src/components/global-styles/dimensions-panel.js @@ -10,7 +10,7 @@ import { __ } from '@wordpress/i18n'; import { __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, - __experimentalBoxControl as BoxControl, + BoxControl, __experimentalUnitControl as UnitControl, __experimentalUseCustomUnits as useCustomUnits, __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper, diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 6607700b2d2c25..90481e58edd7bb 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -15,6 +15,7 @@ ### Deprecations - Deprecate `__unstableComposite`, `__unstableCompositeGroup`, `__unstableCompositeItem` and `__unstableUseCompositeState`. Consumers of the package should use the stable `Composite` component instead ([#63572](https://github.com/WordPress/gutenberg/pull/63572)). +- `__experimentalBoxControl` can now be imported as a stable `BoxControl` ([#65469](https://github.com/WordPress/gutenberg/pull/65469)). ### New Features @@ -35,6 +36,7 @@ - `Tooltip`: Adopt elevation scale ([#65159](https://github.com/WordPress/gutenberg/pull/65159)). - `Modal`: add exit animation for internally triggered events ([#65203](https://github.com/WordPress/gutenberg/pull/65203)). - `Card`: Adopt radius scale ([#65053](https://github.com/WordPress/gutenberg/pull/65053)). +- `BoxControl`: promote to stable ([#65469](https://github.com/WordPress/gutenberg/pull/65469)). ### Bug Fixes diff --git a/packages/components/src/box-control/README.md b/packages/components/src/box-control/README.md index b03b03a85466ae..77176b49eeb6d8 100644 --- a/packages/components/src/box-control/README.md +++ b/packages/components/src/box-control/README.md @@ -1,18 +1,14 @@ # BoxControl -<div class="callout callout-alert"> -This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. -</div> - -BoxControl components let users set values for Top, Right, Bottom, and Left. This can be used as an input control for values like `padding` or `margin`. +A control that lets users set values for top, right, bottom, and left. Can be used as an input control for values like `padding` or `margin`. ## Usage ```jsx import { useState } from 'react'; -import { __experimentalBoxControl as BoxControl } from '@wordpress/components'; +import { BoxControl } from '@wordpress/components'; -const Example = () => { +function Example() { const [ values, setValues ] = useState( { top: '50px', left: '10%', @@ -26,23 +22,24 @@ const Example = () => { onChange={ ( nextValues ) => setValues( nextValues ) } /> ); -}; +} ``` ## Props + ### `allowReset`: `boolean` If this property is true, a button to reset the box control is rendered. -- Required: No -- Default: `true` +- Required: No +- Default: `true` ### `splitOnAxis`: `boolean` If this property is true, when the box control is unlinked, vertical and horizontal controls can be used instead of updating individual sides. -- Required: No -- Default: `false` +- Required: No +- Default: `false` ### `inputProps`: `object` diff --git a/packages/components/src/box-control/index.tsx b/packages/components/src/box-control/index.tsx index 9c3452d4ccb806..41e95aa88bea37 100644 --- a/packages/components/src/box-control/index.tsx +++ b/packages/components/src/box-control/index.tsx @@ -47,14 +47,14 @@ function useUniqueId( idProp?: string ) { } /** - * BoxControl components let users set values for Top, Right, Bottom, and Left. - * This can be used as an input control for values like `padding` or `margin`. + * A control that lets users set values for top, right, bottom, and left. Can be + * used as an input control for values like `padding` or `margin`. * * ```jsx - * import { __experimentalBoxControl as BoxControl } from '@wordpress/components'; + * import { BoxControl } from '@wordpress/components'; * import { useState } from '@wordpress/element'; * - * const Example = () => { + * function Example() { * const [ values, setValues ] = useState( { * top: '50px', * left: '10%', diff --git a/packages/components/src/box-control/stories/index.story.tsx b/packages/components/src/box-control/stories/index.story.tsx index 1b6604048f6d52..783f9d047b1bb0 100644 --- a/packages/components/src/box-control/stories/index.story.tsx +++ b/packages/components/src/box-control/stories/index.story.tsx @@ -14,7 +14,7 @@ import { useState } from '@wordpress/element'; import BoxControl from '../'; const meta: Meta< typeof BoxControl > = { - title: 'Components (Experimental)/BoxControl', + title: 'Components/BoxControl', component: BoxControl, argTypes: { values: { control: { type: null } }, diff --git a/packages/components/src/box-control/types.ts b/packages/components/src/box-control/types.ts index eeb72df14bb9c1..5f4071aeed88a7 100644 --- a/packages/components/src/box-control/types.ts +++ b/packages/components/src/box-control/types.ts @@ -37,13 +37,13 @@ export type BoxControlProps = Pick< /** * Props for the internal `UnitControl` components. * - * @default `{ min: 0 }` + * @default { min: 0 } */ inputProps?: UnitControlPassthroughProps; /** * Heading label for the control. * - * @default `__( 'Box Control' )` + * @default __( 'Box Control' ) */ label?: string; /** @@ -53,7 +53,7 @@ export type BoxControlProps = Pick< /** * The `top`, `right`, `bottom`, and `left` box dimension values to use when the control is reset. * - * @default `{ top: undefined, right: undefined, bottom: undefined, left: undefined }` + * @default { top: undefined, right: undefined, bottom: undefined, left: undefined } */ resetValues?: BoxControlValue; /** diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index 32195ebc444ce6..a59d258012807d 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -40,7 +40,9 @@ export { } from './border-box-control'; export { BorderControl as __experimentalBorderControl } from './border-control'; export { + /** @deprecated Import `BoxControl` instead. */ default as __experimentalBoxControl, + default as BoxControl, applyValueToSides as __experimentalApplyValueToSides, } from './box-control'; export { default as Button } from './button'; diff --git a/packages/components/src/tools-panel/tools-panel/README.md b/packages/components/src/tools-panel/tools-panel/README.md index df41b623eefb6c..1daa7537335e1c 100644 --- a/packages/components/src/tools-panel/tools-panel/README.md +++ b/packages/components/src/tools-panel/tools-panel/README.md @@ -60,7 +60,7 @@ import styled from '@emotion/styled'; * WordPress dependencies */ import { - __experimentalBoxControl as BoxControl, + BoxControl, __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, __experimentalUnitControl as UnitControl, @@ -91,8 +91,8 @@ export function DimensionPanel() { return ( <ToolsPanel label={ __( 'Dimensions' ) } resetAll={ resetAll }> <PanelDescription> - Select dimensions or spacing related settings from the - menu for additional controls. + Select dimensions or spacing related settings from the menu for + additional controls. </PanelDescription> <SingleColumnItem hasValue={ () => !! height } @@ -154,8 +154,8 @@ export function DimensionPanel() { Flags that the items in this ToolsPanel will be contained within an inner wrapper element allowing the panel to lay them out accordingly. -- Required: No -- Default: `false` +- Required: No +- Default: `false` ### `dropdownMenuProps`: `{}` @@ -176,7 +176,7 @@ The heading level of the panel's header. Text to be displayed within the panel's header and as the `aria-label` for the panel's dropdown menu. -- Required: Yes +- Required: Yes ### `panelId`: `string | null` @@ -185,13 +185,13 @@ to restrict panel items. When a `panelId` is set, items can only register themselves if the `panelId` is explicitly `null` or the item's `panelId` matches exactly. -- Required: No +- Required: No ### `resetAll`: `( filters?: ResetAllFilter[] ) => void` A function to call when the `Reset all` menu option is selected. As an argument, it receives an array containing the `resetAllFilter` callbacks of all the valid registered `ToolsPanelItems`. -- Required: Yes +- Required: Yes ### `shouldRenderPlaceholderItems`: `boolean` @@ -201,5 +201,5 @@ placeholder content (instead of `null`) when they are toggled off and hidden. Note that placeholder items won't apply the `className` that would be normally applied to a visible `ToolsPanelItem` via the `className` prop. -- Required: No -- Default: `false` +- Required: No +- Default: `false` diff --git a/storybook/manager-head.html b/storybook/manager-head.html index ebf2d6891ba0bb..7293248ae3e472 100644 --- a/storybook/manager-head.html +++ b/storybook/manager-head.html @@ -2,6 +2,7 @@ ( function redirectIfStoryMoved() { const PREVIOUSLY_EXPERIMENTAL_COMPONENTS = [ 'alignmentmatrixcontrol', + 'boxcontrol', 'customselectcontrol-v2', 'dimensioncontrol', 'navigation', From 93edca04f68ae899f1271dc98547904abeb77ad0 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 23 Sep 2024 11:10:30 +1000 Subject: [PATCH 0900/1908] Time To Read: Add block example (#65512) --- packages/block-library/src/post-time-to-read/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/post-time-to-read/index.js b/packages/block-library/src/post-time-to-read/index.js index 95b379f55f0b3f..039923161ca81d 100644 --- a/packages/block-library/src/post-time-to-read/index.js +++ b/packages/block-library/src/post-time-to-read/index.js @@ -12,6 +12,7 @@ export { metadata, name }; export const settings = { icon, edit, + example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); From e76923fb26968534b5a8a4cb0c738fc633ddeb5d Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 23 Sep 2024 11:19:32 +1000 Subject: [PATCH 0901/1908] Avatar: Add block example (#65509) --- packages/block-library/src/avatar/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/avatar/index.js b/packages/block-library/src/avatar/index.js index d318450aec3903..0b3ad9c62c4e30 100644 --- a/packages/block-library/src/avatar/index.js +++ b/packages/block-library/src/avatar/index.js @@ -16,6 +16,7 @@ export { metadata, name }; export const settings = { icon, edit, + example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); From 42090cab97df447241b8f28da7db04825877023f Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Mon, 23 Sep 2024 02:31:50 +0000 Subject: [PATCH 0902/1908] Bump plugin version to 19.3.0-rc.2 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 8dddcfeccd5282..e15cb113ea65a1 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.3.0-rc.1 + * Version: 19.3.0-rc.2 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 035018e97f13f1..f5293bdf00ca04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.3.0-rc.1", + "version": "19.3.0-rc.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.3.0-rc.1", + "version": "19.3.0-rc.2", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index a4cc002adbf8e7..4b81f249be76c2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.3.0-rc.1", + "version": "19.3.0-rc.2", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 5b6e6cbd2375f45249876b49accf72b86361a351 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 23 Sep 2024 12:34:45 +1000 Subject: [PATCH 0903/1908] Table of Contents: Try maintaining block example attributes (#65549) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/table-of-contents/block.json | 53 ++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/table-of-contents/block.json b/packages/block-library/src/table-of-contents/block.json index 451d245d867b07..5eb6e729d3f03e 100644 --- a/packages/block-library/src/table-of-contents/block.json +++ b/packages/block-library/src/table-of-contents/block.json @@ -62,6 +62,57 @@ } } }, - "example": {}, + "example": { + "innerBlocks": [ + { + "name": "core/heading", + "attributes": { + "level": 2, + "content": "Heading" + } + }, + { + "name": "core/heading", + "attributes": { + "level": 3, + "content": "Subheading" + } + }, + { + "name": "core/heading", + "attributes": { + "level": 2, + "content": "Heading" + } + }, + { + "name": "core/heading", + "attributes": { + "level": 3, + "content": "Subheading" + } + } + ], + "attributes": { + "headings": [ + { + "content": "Heading", + "level": 2 + }, + { + "content": "Subheading", + "level": 3 + }, + { + "content": "Heading", + "level": 2 + }, + { + "content": "Subheading", + "level": 3 + } + ] + } + }, "style": "wp-block-table-of-contents" } From 4b2b2a55ffdda7851f07509572d8a1ef540af488 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Mon, 23 Sep 2024 02:50:12 +0000 Subject: [PATCH 0904/1908] Update Changelog for 19.3.0-rc.2 --- changelog.txt | 275 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) diff --git a/changelog.txt b/changelog.txt index dca31f9afc622e..b04fa0e9bbf8e2 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,280 @@ == Changelog == += 19.3.0-rc.2 = + +## Changelog + +### Features + +#### Zoom Out +- Remove experimental flag. ([65404](https://github.com/WordPress/gutenberg/pull/65404)) + +### Enhancements + +- Create Block: Update the minimum required PHP version to 7.2. ([65166](https://github.com/WordPress/gutenberg/pull/65166)) +- DataViews: remove unused `.dataviews-view-table__cell-content-wrapper:Empty` style rule. ([65084](https://github.com/WordPress/gutenberg/pull/65084)) +- Media Utils: Add TypeScript support and export more utils. ([64784](https://github.com/WordPress/gutenberg/pull/64784)) +- Media placeholders: Add "drag" to the text. ([65149](https://github.com/WordPress/gutenberg/pull/65149)) +- Restore: Move to trash button in Document settings. ([65087](https://github.com/WordPress/gutenberg/pull/65087)) +- Inspector Controls: Use custom block name in inspector controls when available. ([65398](https://github.com/WordPress/gutenberg/pull/65398)) +- Icons: Adds bell and bell-unread icons. ([65324](https://github.com/WordPress/gutenberg/pull/65324)) +- Editor topbar: Reorder the actions on the right. ([65163](https://github.com/WordPress/gutenberg/pull/65163)) +- Patterns: Add opt out preference to the 'Choose a Pattern' modal when adding a page. ([65026](https://github.com/WordPress/gutenberg/pull/65026)) +- Locked Templates: Blocks with contentOnly locking should not be transformable. ([64917](https://github.com/WordPress/gutenberg/pull/64917)) +- Block Locking: Add border to Replace item in content only image toolbar. ([64849](https://github.com/WordPress/gutenberg/pull/64849)) + +#### Components +- Styling: Apply elevation scale in components package. ([65159](https://github.com/WordPress/gutenberg/pull/65159)) +- Tabs: Improve Tabs indicator animation and related utils. ([64926](https://github.com/WordPress/gutenberg/pull/64926)) +- Modal + - Add exit animation. ([65203](https://github.com/WordPress/gutenberg/pull/65203)) + - Decrease close button size. ([65131](https://github.com/WordPress/gutenberg/pull/65131)) +- Navigator Screen: Warn if path doesn't follow a URL-like scheme. ([65231](https://github.com/WordPress/gutenberg/pull/65231)) +- Card: Update Card radius. ([65053](https://github.com/WordPress/gutenberg/pull/65053)) +- Combobox Control: Add placeholder attribute. ([65254](https://github.com/WordPress/gutenberg/pull/65254)) + +#### Block Library +- Allow dropping multiple images to the image block. ([65030](https://github.com/WordPress/gutenberg/pull/65030)) +- Categories List block: Add dropdown for taxonomies. ([65272](https://github.com/WordPress/gutenberg/pull/65272)) +- Image: Adds the block controls for uploading image. ([64320](https://github.com/WordPress/gutenberg/pull/64320)) +- Remove colons from control labels. ([65205](https://github.com/WordPress/gutenberg/pull/65205)) +- Terms List block: Add Categories-specific variation. ([65434](https://github.com/WordPress/gutenberg/pull/65434)) + +#### Zoom Out +- Add Zoom Out toggle to editor header when experiment enabled. ([65183](https://github.com/WordPress/gutenberg/pull/65183)) +- Add prompt for drag and drop in Patterns tab in Zoom Out mode. ([65115](https://github.com/WordPress/gutenberg/pull/65115)) +- Close inserter on exiting Zoom Out to edit. ([65194](https://github.com/WordPress/gutenberg/pull/65194)) +- Show top level sections in List View. ([65202](https://github.com/WordPress/gutenberg/pull/65202)) +- Try vertical displacement when dragging a pattern between existing patterns/sections. ([63896](https://github.com/WordPress/gutenberg/pull/63896)) + +#### Block Editor +- Link Editing: Automatically add tel to phone number when linking URL. ([64865](https://github.com/WordPress/gutenberg/pull/64865)) +thub.com/WordPress/gutenberg/pull/65300)) +- Drag and Drop: When dragging a mix of video, audio, and image blocks, create individual blocks as appropriate. ([65144](https://github.com/WordPress/gutenberg/pull/65144)) +- URLInput: Replace input with InputControl. ([65158](https://github.com/WordPress/gutenberg/pull/65158)) +- Normalize block inspector controls spacing. ([64526](https://github.com/WordPress/gutenberg/pull/64526)) + +#### Post Editor +- Add new Media section to preferences modal. ([64846](https://github.com/WordPress/gutenberg/pull/64846)) +- DocumentBar: Replace icon with post type label. ([65170](https://github.com/WordPress/gutenberg/pull/65170)) +- Page editor: Double-click to edit template part. ([65024](https://github.com/WordPress/gutenberg/pull/65024)) +- Post publish upload media dialog: Handle more block types. ([65122](https://github.com/WordPress/gutenberg/pull/65122)) + +#### Block bindings +- Populate block context with inherited post type from template slug. ([65062](https://github.com/WordPress/gutenberg/pull/65062)) +- Try gap 0 on attribute items. ([65277](https://github.com/WordPress/gutenberg/pull/65277)) +- Use post meta label from `register_meta` in block bindings workflows. ([65099](https://github.com/WordPress/gutenberg/pull/65099)) + +#### Global Styles +- Refactor site background controls and move site global styles into Background group. ([65304](https://github.com/WordPress/gutenberg/pull/65304)) +- Spacing control: Replace sides dropdwon with link button. ([65193](https://github.com/WordPress/gutenberg/pull/65193)) + +#### Data Views +- DataViews Sidebar: Display item count on DataViews sidebar. ([65223](https://github.com/WordPress/gutenberg/pull/65223)) +- DataViews: Improve UX of bundled views for Pages. ([65295](https://github.com/WordPress/gutenberg/pull/65295)) + +#### Interactivity API +- Refactor context proxies. ([64713](https://github.com/WordPress/gutenberg/pull/64713)) +- Update: Rephrase "Force page reload" and move to Advanced. ([65081](https://github.com/WordPress/gutenberg/pull/65081)) + +#### REST API +- Global Styles: Allow read access to users with `edit_posts` capabilities. ([65071](https://github.com/WordPress/gutenberg/pull/65071)) +- Query loop / Post template: Enable post format filter. ([64167](https://github.com/WordPress/gutenberg/pull/64167)) + +### New APIs +- Add @wordpress/fields package. + - Introduce the package. ([65230](https://github.com/WordPress/gutenberg/pull/65230)) + - Make the package private. ([65269](https://github.com/WordPress/gutenberg/pull/65269)) +- Interactivity API: Add `getServerState()` and `getServerContext()`. ([65151](https://github.com/WordPress/gutenberg/pull/65151)) + +### Bug Fixes + +- Align popover alt variant styling with block toolbar. ([65263](https://github.com/WordPress/gutenberg/pull/65263)) +- Compose: Correctly call timer cleanup in 'useFocusOnMount'. ([65184](https://github.com/WordPress/gutenberg/pull/65184)) +- Fix some docblock types related to the Template Registration API. ([65187](https://github.com/WordPress/gutenberg/pull/65187)) +- Fix the issue where block spacing control not shown. ([65371](https://github.com/WordPress/gutenberg/pull/65371)) +- Fix unintentional block toolbar shadow. ([65182](https://github.com/WordPress/gutenberg/pull/65182)) +- Fix: Moving a page to the trash on the site editor does not goes back to the pages list. ([65119](https://github.com/WordPress/gutenberg/pull/65119)) +- Fix: Moving the last page item to the the trash causes a crash. ([65236](https://github.com/WordPress/gutenberg/pull/65236)) +- Preferences: Fix back button on mobile. ([65141](https://github.com/WordPress/gutenberg/pull/65141)) +- Post Summary Panel: Restore `height:Auto` for toggle buttons. ([65362](https://github.com/WordPress/gutenberg/pull/65362)) +- Fix Tabs styling in Font Library modal. ([65330](https://github.com/WordPress/gutenberg/pull/65330)) +- E2E: Change deprecated social icons for standard in end-to-end. ([65312](https://github.com/WordPress/gutenberg/pull/65312)) +- Typography: Make title blocks apply typographic styles consistently. ([65307](https://github.com/WordPress/gutenberg/pull/65307)) +- Target Hints REST API: Add missing param sanitization. ([65280](https://github.com/WordPress/gutenberg/pull/65280)) +- Interactivity API: Update iterable signals when `deepMerge()` adds new properties. ([65135](https://github.com/WordPress/gutenberg/pull/65135)) +- Navigation Menus: Typography styling support to the navigation submenu block. ([65060](https://github.com/WordPress/gutenberg/pull/65060)) +- Grid: In RTL languages, the resize handles point in the opposite direction. ([64995](https://github.com/WordPress/gutenberg/pull/64995)) +- Block Locking: Fix Content Only Toolbar icon focus style. ([64940](https://github.com/WordPress/gutenberg/pull/64940)) +- Image: Fix resizing to max width in classic themes. ([64819](https://github.com/WordPress/gutenberg/pull/64819)) +- Meta Boxes: Try split content view. ([64351](https://github.com/WordPress/gutenberg/pull/64351)) +- Distraction Free: Fix blurry edge along editor header. ([64277](https://github.com/WordPress/gutenberg/pull/64277)) + +#### Block Library +- Comments Pagination: Fix warning returned by comments pagination blocks. ([65435](https://github.com/WordPress/gutenberg/pull/65435)) +- Cover: Explicitly set isUserOverlayColor to false when media is updated. ([65105](https://github.com/WordPress/gutenberg/pull/65105)) +- Disallow setting grid block rows/columns to zero. ([65217](https://github.com/WordPress/gutenberg/pull/65217)) +- Fix image block crash. ([65222](https://github.com/WordPress/gutenberg/pull/65222)) +- Fix: Buttons block: Block spacing value does not apply to both vertical and horizontal alignment. ([64971](https://github.com/WordPress/gutenberg/pull/64971)) +- Fix: Embed blocks: Figcaption inserted via toolbar not nested within figure element - #64960. ([64970](https://github.com/WordPress/gutenberg/pull/64970)) +- Image cropping: Skip making an API request if there are no changes to apply. ([65384](https://github.com/WordPress/gutenberg/pull/65384)) +- Comments Pagination: Pass the comments query `paged` arg to functions `get_next_comments_link` and `get_previous_comments_link`. ([63698](https://github.com/WordPress/gutenberg/pull/63698)) +- Query Loop + - Default to querying posts when on singular content. ([65067](https://github.com/WordPress/gutenberg/pull/65067)) + - Remove is_singular() check and fix test. ([65483](https://github.com/WordPress/gutenberg/pull/65483)) + +#### Block Editor +- Inserter: Fix loading indicator for reusable blocks. ([64839](https://github.com/WordPress/gutenberg/pull/64839)) +- Normalize spacing in Layout hook controls. ([65132](https://github.com/WordPress/gutenberg/pull/65132)) +- Pattern Inserter: Fix pattern list overflow. ([65192](https://github.com/WordPress/gutenberg/pull/65192)) +- Remove reset styles RTL from the iframe. ([65150](https://github.com/WordPress/gutenberg/pull/65150)) +- Revert "Block Insertion: Clear the insertion point when selecting a d…. ([65208](https://github.com/WordPress/gutenberg/pull/65208)) + +#### Components +- BoxControl: Unify input filed width whether linked or not. ([65348](https://github.com/WordPress/gutenberg/pull/65348)) +- ComboboxControl: Add more unit tests. ([65255](https://github.com/WordPress/gutenberg/pull/65255)) +- Fix: Button Replace remaining 40px default size violations [Edit widgets]. ([65367](https://github.com/WordPress/gutenberg/pull/65367)) +- Tabs: Fix vertical indicator. ([65385](https://github.com/WordPress/gutenberg/pull/65385)) + +#### Block bindings +- Fix empty strings placeholders in post meta bindings. ([65089](https://github.com/WordPress/gutenberg/pull/65089)) +- Remove key fallback in bindings get values and rely on source label. ([65517](https://github.com/WordPress/gutenberg/pull/65517)) + +#### Zoom Out +- Force device type to Desktop whenever zoom out is invoked. ([64476](https://github.com/WordPress/gutenberg/pull/64476)) +- Hide toolbar icon on smaller viewports. ([65437](https://github.com/WordPress/gutenberg/pull/65437)) +- Remove zoom out toggle when editor is not iframed. ([65452](https://github.com/WordPress/gutenberg/pull/65452)) + +### Accessibility + +- A11y: Add script-module. ([65101](https://github.com/WordPress/gutenberg/pull/65101)) +- Interactivity API: Use a11y Script Module in Gutenberg. ([65123](https://github.com/WordPress/gutenberg/pull/65123)) +- Script Modules API: Print script module live regions HTML in page HTML. ([65380](https://github.com/WordPress/gutenberg/pull/65380)) +- DatePicker: Better hover/focus styles. ([65117](https://github.com/WordPress/gutenberg/pull/65117)) +- Form Input: Don't use `flex-direction: Row-reverse` for checkbox field. ([64232](https://github.com/WordPress/gutenberg/pull/64232)) +- Navigation Menus: Remove Warning and add notice for Navigation. ([63921](https://github.com/WordPress/gutenberg/pull/63921)) +- Global Styles: Fix the shadows Range control accessibility and usability. ([63908](https://github.com/WordPress/gutenberg/pull/63908)) +- Block Editor: Fix accessibility of the hooked blocks toggles. ([63133](https://github.com/WordPress/gutenberg/pull/63133)) + + +#### Post Editor +- Support keyboard resizing of meta boxes pane. ([65325](https://github.com/WordPress/gutenberg/pull/65325)) +- Swap position of the Pre-publish checks buttons. ([65317](https://github.com/WordPress/gutenberg/pull/65317)) + + +### Performance + +- Core Data: Batch remaining actions in resolvers. ([65176](https://github.com/WordPress/gutenberg/pull/65176)) +- Block Editor: Use static access for selector in 'useZoomOutModeExit'. ([65337](https://github.com/WordPress/gutenberg/pull/65337)) +- Editor: Optimize global styles permission check. ([65177](https://github.com/WordPress/gutenberg/pull/65177)) + + +### Experiments + +- Block bindings REST API: Bring bindings UI in Site Editor. ([64072](https://github.com/WordPress/gutenberg/pull/64072)) + + +### Documentation + +- Add JSDoc block for getSectionRootClientId in block editor package. ([65219](https://github.com/WordPress/gutenberg/pull/65219)) +- ButtonGroup: Fix story to show what the component does. ([65336](https://github.com/WordPress/gutenberg/pull/65336)) +- DataViews storybook + - Better styles for combined fields story. ([65078](https://github.com/WordPress/gutenberg/pull/65078)) + - Enable all layouts for combined fields storybook. ([65082](https://github.com/WordPress/gutenberg/pull/65082)) +- Docs: Fix minor typos in Build your first block tutorial. ([64961](https://github.com/WordPress/gutenberg/pull/64961)) +- Docs: Update the content of the API version 3 section in the Block API Reference. ([65375](https://github.com/WordPress/gutenberg/pull/65375)) +- Fix typo in Slot Fills documentation. ([65275](https://github.com/WordPress/gutenberg/pull/65275)) + + +### Code Quality + +- Components: Transition to the new 40px default size. + - Button: + - Add __next40pxDefaultSize for files in editor 3. ([65139](https://github.com/WordPress/gutenberg/pull/65139)) + - Add __next40pxDefaultSize for files in editor 4. ([65140](https://github.com/WordPress/gutenberg/pull/65140)) + - Add props for buttons in editor 1. ([65068](https://github.com/WordPress/gutenberg/pull/65068)) + - Add props for buttons in editor 2. ([65083](https://github.com/WordPress/gutenberg/pull/65083)) + - Fix: Replace remaining 40px default size violations [Block Editor 4]. ([65257](https://github.com/WordPress/gutenberg/pull/65257)) + - Fix: Replace remaining 40px default size violation [Block library 3]. ([65110](https://github.com/WordPress/gutenberg/pull/65110)) + - Fix: Replace remaining 40px default size violation [Block library 4]. ([65143](https://github.com/WordPress/gutenberg/pull/65143)) + - Fix: Replace remaining 40px default size violation [Block library]. ([65075](https://github.com/WordPress/gutenberg/pull/65075)) + - Fix: Replace remaining 40px default size violation [Edit Site 2]. ([65258](https://github.com/WordPress/gutenberg/pull/65258)) + - Fix: Replace remaining 40px default size violations [Block library 1]. ([65033](https://github.com/WordPress/gutenberg/pull/65033)) + - Fix: Replace remaining 40px default size violations [Block Editor 1]. ([65034](https://github.com/WordPress/gutenberg/pull/65034)) + - BoxControl + - Add lint rule for 40px size prop usage. ([65341](https://github.com/WordPress/gutenberg/pull/65341)) + - DimensionsPanel: Apply 40px default size to UI when no spacing preset is available. ([65300](https://github.com/WordPress/gutenberg/pull/65300)) +- Add `useEvent` and revamped `useResizeObserver` to `@wordpress/compose`. ([64943](https://github.com/WordPress/gutenberg/pull/64943)) +- DataViews: Use Dropdown for views configuration dialog. ([65314](https://github.com/WordPress/gutenberg/pull/65314)) +- Platform docs: Upgrade dependencies. ([65445](https://github.com/WordPress/gutenberg/pull/65445)) +- Rename edit-post__fade-in-animation and unify keyframe definitions. ([65377](https://github.com/WordPress/gutenberg/pull/65377)) +- Update minimum required version in PHP. ([65301](https://github.com/WordPress/gutenberg/pull/65301)) +- Editor: Use hooks instead of HoC in `BlockManager`. ([65349](https://github.com/WordPress/gutenberg/pull/65349)) +- Data Views Fields: Migrate store and actions from editor package to fields package. ([65261](https://github.com/WordPress/gutenberg/pull/65261)) +- Plugin: Remove 'function_exists' checks for methods with 'gutenberg' prefix. ([65260](https://github.com/WordPress/gutenberg/pull/65260)) +- Global Styles: Update REST controller override method and backport changes from Core. ([65259](https://github.com/WordPress/gutenberg/pull/65259)) +- Patterns: Remove unused method returned from 'mapSelect'. ([65073](https://github.com/WordPress/gutenberg/pull/65073)) +- Embed: Convert EmbedPreview component to functional component. ([51325](https://github.com/WordPress/gutenberg/pull/51325)) + +#### Components +- BoxControl: Fix critical error when null value is passed. ([65287](https://github.com/WordPress/gutenberg/pull/65287)) +- Composite: + - Deprecate legacy, unstable version. ([63572](https://github.com/WordPress/gutenberg/pull/63572)) + - Remove store prop and useCompositeStore hook. ([64723](https://github.com/WordPress/gutenberg/pull/64723)) + - Stabilize APIs. ([63569](https://github.com/WordPress/gutenberg/pull/63569)) +- `@wordpress/components`: Add local copy of `use-lilius`. ([65097](https://github.com/WordPress/gutenberg/pull/65097)) + +#### Block bindings +- Always prioritize using context in post meta source logic. ([65449](https://github.com/WordPress/gutenberg/pull/65449)) +- Improve getRegisteredPostMeta resolver. ([65450](https://github.com/WordPress/gutenberg/pull/65450)) +- Remove extra filtering of empty sources. ([65447](https://github.com/WordPress/gutenberg/pull/65447)) + +#### Block Editor +- Remove the 'PrivateInserter' component. ([65111](https://github.com/WordPress/gutenberg/pull/65111)) +- Use the tooltip from a button in 'ButtonBlockAppender'. ([65113](https://github.com/WordPress/gutenberg/pull/65113)) +- Remove unused css selectors. ([65276](https://github.com/WordPress/gutenberg/pull/65276)) + +### Tools + +- Scripts: Update stylelint dependency and the default configuration. ([64828](https://github.com/WordPress/gutenberg/pull/64828)) +- Styleling config: Fix stylelint configuration missing files for npm. ([65313](https://github.com/WordPress/gutenberg/pull/65313)) + +#### Build Tooling +- Build Plugin: Simplify and improve zip contents. ([65232](https://github.com/WordPress/gutenberg/pull/65232)) +- Build zip artifact on release and wp production branches. ([65471](https://github.com/WordPress/gutenberg/pull/65471)) +- Build: Include Core blocks' `render` and `variations` files. ([63311](https://github.com/WordPress/gutenberg/pull/63311)) +- Script Modules + - Prepare build for more script modules. ([65064](https://github.com/WordPress/gutenberg/pull/65064)) + - Remove babel from script-modules build. ([65279](https://github.com/WordPress/gutenberg/pull/65279)) + - Remove es-module shims and importmap-polyfill. ([65210](https://github.com/WordPress/gutenberg/pull/65210)) +- Correctly generate PHP files for server-side rendering of blocks on Windows OS. ([65248](https://github.com/WordPress/gutenberg/pull/65248)) +- Packages: Only add polyfills where needed. ([65292](https://github.com/WordPress/gutenberg/pull/65292)) +- Switch from UglifyJS to Terser to build the polyfill script. ([65278](https://github.com/WordPress/gutenberg/pull/65278)) + +#### Testing +- Unit tests: Mock matchMedia to enforce prefers-reduce-motion. ([65438](https://github.com/WordPress/gutenberg/pull/65438)) +- Upgrade Playwright to v1.47. ([65156](https://github.com/WordPress/gutenberg/pull/65156)) + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @AKSHAT2802: Add __next40pxDefaultSize for files in editor 4. ([65140](https://github.com/WordPress/gutenberg/pull/65140)) +- @devansh016: Automatically add tel to phone number when linking URL. ([64865](https://github.com/WordPress/gutenberg/pull/64865)) +- @dhruvang21: Fix: Button Replace remaining 40px default size violations [Edit widgets]. ([65367](https://github.com/WordPress/gutenberg/pull/65367)) +- @farid-hadi: Docs: Fix minor typos in Build your first block tutorial. ([64961](https://github.com/WordPress/gutenberg/pull/64961)) +- @greenworld: Fix typo in Slot Fills documentation. ([65275](https://github.com/WordPress/gutenberg/pull/65275)) +- @louwie17: Convert EmbedPreview component to functional component. ([51325](https://github.com/WordPress/gutenberg/pull/51325)) +- @rahulharpal1603: URLInput: Replace input with InputControl. ([65158](https://github.com/WordPress/gutenberg/pull/65158)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @afercia @AKSHAT2802 @Aljullu @andrewserong @carolinan @cbravobernal @ciampo @colorful-tones @creativecoder @DaniGuardiola @DAreRodz @devansh016 @dhruvang21 @ellatrix @farid-hadi @getdave @gigitux @greenworld @gziolo @hbhalodia @jameskoster @jasmussen @javierarce @jeryj @jorgefilipecosta @jsnajdr @kevin940726 @louwie17 @madhusudhand @MaggieCabrera @Mamaduka @mikeybinns @mirka @ntsekouras @oandregal @ockham @peterwilsoncc @rahulharpal1603 @ramonjd @richtabor @rohitmathur-7 @SantosGuillamot @scruffian @sgomes @sirreal @stokesman @swissspidy @t-hamano @talldan @vipul0425 @zaguiini + + = 19.3.0-rc.1 = ## Changelog From 7cdf002a49c1c4ed3aec46111ace013d0f5a2e70 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:15:02 +1000 Subject: [PATCH 0905/1908] Post Navigation Link: Add block examples (#65552) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/post-navigation-link/block.json | 6 ++++++ .../src/post-navigation-link/variations.js | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/packages/block-library/src/post-navigation-link/block.json b/packages/block-library/src/post-navigation-link/block.json index ce733759846fee..5f1b295119822a 100644 --- a/packages/block-library/src/post-navigation-link/block.json +++ b/packages/block-library/src/post-navigation-link/block.json @@ -34,6 +34,12 @@ "default": "" } }, + "example": { + "attributes": { + "label": "Next post", + "arrow": "arrow" + } + }, "usesContext": [ "postType" ], "supports": { "reusable": false, diff --git a/packages/block-library/src/post-navigation-link/variations.js b/packages/block-library/src/post-navigation-link/variations.js index 945d6eb550f276..4f52b21338af1e 100644 --- a/packages/block-library/src/post-navigation-link/variations.js +++ b/packages/block-library/src/post-navigation-link/variations.js @@ -15,6 +15,12 @@ const variations = [ icon: next, attributes: { type: 'next' }, scope: [ 'inserter', 'transform' ], + example: { + attributes: { + label: 'Next post', + arrow: 'arrow', + }, + }, }, { name: 'post-previous', @@ -25,6 +31,12 @@ const variations = [ icon: previous, attributes: { type: 'previous' }, scope: [ 'inserter', 'transform' ], + example: { + attributes: { + label: 'Previous post', + arrow: 'arrow', + }, + }, }, ]; From 2dc9bc5d2349de9c5eeceb30e74a886bb6130226 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:16:33 +1000 Subject: [PATCH 0906/1908] Term Description: Add block example (#65553) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/term-description/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/term-description/index.js b/packages/block-library/src/term-description/index.js index 0ff710a91f5d50..330ca05bd174e1 100644 --- a/packages/block-library/src/term-description/index.js +++ b/packages/block-library/src/term-description/index.js @@ -16,6 +16,7 @@ export { metadata, name }; export const settings = { icon, edit, + example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); From dad62c622eadfdf71640fb9677aad8e14359ca3e Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:21:44 +1000 Subject: [PATCH 0907/1908] Query Title: Add block example (#65554) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/query-title/block.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/block-library/src/query-title/block.json b/packages/block-library/src/query-title/block.json index de3e60214685c2..5d5c9113bda084 100644 --- a/packages/block-library/src/query-title/block.json +++ b/packages/block-library/src/query-title/block.json @@ -29,6 +29,11 @@ "default": true } }, + "example": { + "attributes": { + "type": "search" + } + }, "supports": { "align": [ "wide", "full" ], "html": false, From 4209ffdb8e7f61d822c23860cd6dc3812ba97c31 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 23 Sep 2024 16:21:16 +1000 Subject: [PATCH 0908/1908] Query Pagination: Add block example (#65556) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/query-pagination/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/query-pagination/index.js b/packages/block-library/src/query-pagination/index.js index b113a8384b043b..158106c4ac185a 100644 --- a/packages/block-library/src/query-pagination/index.js +++ b/packages/block-library/src/query-pagination/index.js @@ -20,6 +20,7 @@ export const settings = { edit, save, deprecated, + example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); From 5284920adb7c34e6c7e1fd9637932dc22472ddc6 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 23 Sep 2024 16:22:00 +1000 Subject: [PATCH 0909/1908] Query No Results: Add block example (#65555) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/query-no-results/block.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/block-library/src/query-no-results/block.json b/packages/block-library/src/query-no-results/block.json index 8f3ba56adcc36a..2f656594afa306 100644 --- a/packages/block-library/src/query-no-results/block.json +++ b/packages/block-library/src/query-no-results/block.json @@ -8,6 +8,16 @@ "parent": [ "core/query" ], "textdomain": "default", "usesContext": [ "queryId", "query" ], + "example": { + "innerBlocks": [ + { + "name": "core/paragraph", + "attributes": { + "content": "No posts were found." + } + } + ] + }, "supports": { "align": true, "reusable": false, From 5afd08f7e8cbf4ed96956e893995f5a0f969ce92 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 23 Sep 2024 17:14:19 +1000 Subject: [PATCH 0910/1908] Comments Title: Add block example (#65557) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/comments-title/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/comments-title/index.js b/packages/block-library/src/comments-title/index.js index 86bdab0dbccbff..69b8228eab892b 100644 --- a/packages/block-library/src/comments-title/index.js +++ b/packages/block-library/src/comments-title/index.js @@ -18,6 +18,7 @@ export const settings = { icon, edit, deprecated, + example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); From 842b86a1e3c9f26ec7e0cd27dace1ee899787fcc Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 23 Sep 2024 18:00:07 +1000 Subject: [PATCH 0911/1908] Comment Author Name: Add block example (#65558) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/comment-author-name/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/comment-author-name/index.js b/packages/block-library/src/comment-author-name/index.js index 4d85bbebe047be..5bcb6896564807 100644 --- a/packages/block-library/src/comment-author-name/index.js +++ b/packages/block-library/src/comment-author-name/index.js @@ -18,6 +18,7 @@ export const settings = { icon, edit, deprecated, + example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); From a1f8bb5139a746a695700c1dff927addfee8ea3f Mon Sep 17 00:00:00 2001 From: Luis Herranz <luisherranz@gmail.com> Date: Mon, 23 Sep 2024 12:21:29 +0200 Subject: [PATCH 0912/1908] iAPI: Refactor types and add a "Core Concepts - Using TypeScript" guide (#64577) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial version * Add a section with instructions to install the package * Add basic create-block template for typescript * Fix all the types * Reorganize the sections on how to type the store * Add a test for when the store is divided into multiple parts * Update the example of when the store is divided into multiple parts * Try a `typed` function to type promises * Refactor derived state and async actions * Add an example casting the entire state * Add entry to the changelog * Add last section and conclusion * Remove the template * Add basic JSDoc for the typed function * Export `typed` * Delete template from manifest * Add the skeleton for TypeScript variant of the template * Add types and global state to the template * Add the scaffolding section again * Add a note and `@since` annotation to the `typed` function to ensure people don’t use it before WP 6.7 * Added typescript guide to the README of Core Concepts, toc.json and manifest.json * Improve iapi type "tests" * Add tsconfig for type tests * REVERTME: Introduce intentional type error * Revert "REVERTME: Introduce intentional type error" This reverts commit ac5590f0244148a75db0871c16e34548642b10f6. * fixup! Merge branch 'trunk' into iapi-docs-typescript-guide * Remove typed function * Remove references to `typed` function from docs * Update and fix changelog --------- Co-authored-by: Grzegorz Ziółkowski <grzegorz@gziolo.pl> Co-authored-by: JuanMa Garrido <juanma.garrido@gmail.com> Co-authored-by: Jon Surrell <sirreal@users.noreply.github.com> Co-authored-by: JuanMa <juanma.garrido@automattic.com> Co-authored-by: luisherranz <luisherranz@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: juanmaguitar <juanmaguitar@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: adamziel <zieladam@git.wordpress.org> Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: spencerfinnell <spencerfinnell@git.wordpress.org> Co-authored-by: ryanwelcher <welcher@git.wordpress.org> --- docs/manifest.json | 6 + .../interactivity-api/core-concepts/README.md | 2 + .../core-concepts/using-typescript.md | 746 ++++++++++++++++++ docs/toc.json | 3 + .../CHANGELOG.md | 6 +- .../README.md | 2 +- .../block-templates/README.md.mustache | 2 - .../block-templates/render.php.mustache | 23 +- .../block-templates/style.scss.mustache | 15 + .../block-templates/view.js.mustache | 19 +- .../block-templates/view.ts.mustache | 46 ++ .../index.js | 11 +- packages/interactivity/CHANGELOG.md | 1 + packages/interactivity/src/hooks.tsx | 10 +- packages/interactivity/src/store.ts | 63 +- packages/interactivity/src/test/store.ts | 286 +++++++ packages/interactivity/tsconfig.test.json | 13 + tsconfig.json | 1 + 18 files changed, 1230 insertions(+), 25 deletions(-) create mode 100644 docs/reference-guides/interactivity-api/core-concepts/using-typescript.md create mode 100644 packages/create-block-interactive-template/block-templates/view.ts.mustache create mode 100644 packages/interactivity/src/test/store.ts create mode 100644 packages/interactivity/tsconfig.test.json diff --git a/docs/manifest.json b/docs/manifest.json index d7f74d47995b63..d76717fbdedfc1 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -521,6 +521,12 @@ "markdown_source": "../docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md", "parent": "core-concepts" }, + { + "title": "Using TypeScript", + "slug": "using-typescript", + "markdown_source": "../docs/reference-guides/interactivity-api/core-concepts/using-typescript.md", + "parent": "core-concepts" + }, { "title": "Quick start guide", "slug": "iapi-quick-start-guide", diff --git a/docs/reference-guides/interactivity-api/core-concepts/README.md b/docs/reference-guides/interactivity-api/core-concepts/README.md index f4e6891c4ff165..695a4d622f6c52 100644 --- a/docs/reference-guides/interactivity-api/core-concepts/README.md +++ b/docs/reference-guides/interactivity-api/core-concepts/README.md @@ -7,3 +7,5 @@ This section provides some guides on important concepts and mental models relate 2. **[Understanding global state, local context and derived state](/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md):** The guide explains how to effectively use global state, local context, and derived state within the Interactivity API emphasizing the importance of choosing the appropriate state management technique based on the scope and requirements of your data. 3. **[Server-side rendering: Processing directives on the server](/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md):** The Interactivity API allows WordPress to use server-side rendering to create interactive and state-aware HTML, smoothly connected with client-side features while maintaining performance and SEO benefits. + +4. **[Using TypeScript](/docs/reference-guides/interactivity-api/core-concepts/using-typescript.md):** This guide will walk you through the process of using TypeScript with Interactivity API stores, covering everything from basic type definitions to advanced techniques for handling complex store structures. diff --git a/docs/reference-guides/interactivity-api/core-concepts/using-typescript.md b/docs/reference-guides/interactivity-api/core-concepts/using-typescript.md new file mode 100644 index 00000000000000..ed0bdd88211d11 --- /dev/null +++ b/docs/reference-guides/interactivity-api/core-concepts/using-typescript.md @@ -0,0 +1,746 @@ +# Using TypeScript + +The Interactivity API provides robust support for TypeScript, enabling developers to build type-safe stores to enhance the development experience with static type checking, improved code completion, and simplified refactoring. This guide will walk you through the process of using TypeScript with Interactivity API stores, covering everything from basic type definitions to advanced techniques for handling complex store structures. + +These are the core principles of TypeScript's interaction with the Interactivity API: + +- **Inferred client types**: When you create a store using the `store` function, TypeScript automatically infers the types of the store's properties (`state`, `actions`, etc.). This means that you can often get away with just writing plain JavaScript objects, and TypeScript will figure out the types for you. +- **Explicit server types**: When dealing with data defined on the server, like local context or the initial values of the global state, you can explicitly define its types to ensure that everything is correctly typed. +- **Mutiple store parts**: Even if your store is split into multiple parts, you can define or infer the types of each part of the store and then merge them into a single type that represents the entire store. +- **Typed external stores**: You can import typed stores from external namespaces, allowing you to use other plugins' functionality with type safety. + +## Installing `@wordpress/interactivity` locally + +If you haven't done so already, you need to install the package `@wordpress/interactivity` locally so TypeScript can use its types in your IDE. You can do this using the following command: + +`npm install @wordpress/interactivity` + +It is also a good practice to keep that package updated. + +## Scaffolding a new typed interactive block + +If you want to explore an example of an interactive block using TypeScript in your local environment, you can use the `@wordpress/create-block-interactive-template`. + +Start by ensuring you have Node.js and `npm` installed on your computer. Review the [Node.js development environment](https://developer.wordpress.org/block-editor/getting-started/devenv/nodejs-development-environment/) guide if not. + +Next, use the [`@wordpress/create-block`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-create-block/) package and the [`@wordpress/create-block-interactive-template`](https://www.npmjs.com/package/@wordpress/create-block-interactive-template) template to scaffold the block. + +Choose the folder where you want to create the plugin, execute the following command in the terminal from within that folder, and choose the `typescript` variant when asked. + +``` +npx @wordpress/create-block@latest --template @wordpress/create-block-interactive-template +``` + +**Important**: Do not provide a slug in the terminal. Otherwise, `create-block` will not ask you which variant you want to choose and it will select the default non-TypeScript variant by default. + +Finally, you can keep following the instructions in the [Getting Started Guide](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/iapi-quick-start-guide/) as the rest of the instructions remain the same. + +## Typing the store + +Depending on the structure of your store and your preference, there are three options you can choose from to generate your store's types: + +1. Infer the types from your client store definition. +2. Manually type the server state, but infer the rest from your client store definition. +3. Manually write all the types. + +### 1. Infer the types from your client store definition + +When you create a store using the `store` function, TypeScript automatically infers the types of the store's properties (`state`, `actions`, `callbacks`, etc.). This means that you can often get away with just writing plain JavaScript objects, and TypeScript will figure out the correct types for you. + +Let's start with a basic example of a counter block. We will define the store in the `view.ts` file of the block, which contains the initial global state, an action and a callback. + +```ts +// view.ts +const myStore = store( 'myCounterPlugin', { + state: { + counter: 0, + }, + actions: { + increment() { + myStore.state.counter += 1; + }, + }, + callbacks: { + log() { + console.log( `counter: ${ myStore.state.counter }` ); + }, + }, +} ); +``` + +If you inspect the types of `myStore` using TypeScript, you will see that TypeScript has been able to infer the types correctly. + +```ts +const myStore: { + state: { + counter: number; + }; + actions: { + increment(): void; + }; + callbacks: { + log(): void; + }; +}; +``` + +You can also destructure the `state`, `actions` and `callbacks` properties, and the types will still work correctly. + +```ts +const { state } = store( 'myCounterPlugin', { + state: { + counter: 0, + }, + actions: { + increment() { + state.counter += 1; + }, + }, + callbacks: { + log() { + console.log( `counter: ${ state.counter }` ); + }, + }, +} ); +``` + +In conclusion, inferring the types is useful when you have a simple store defined in a single call to the `store` function and you do not need to type any state that has been initialized on the server. + +### 2. Manually type the server state, but infer the rest from your client store definition + +The global state that is initialized on the server with the `wp_interactivity_state` function doesn't exist on your client store definition and, therefore, needs to be manually typed. But if you don't want to define all the types of your store, you can infer the types of your client store definition and merge them with the types of your server initialized state. + +_Please, visit [the Server-side Rendering guide](/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md) to learn more about `wp_interactivity_state` and how directives are processed on the server._ + +Following our previous example, let's move our `counter` state initialization to the server. + +```php +wp_interactivity_state( 'myCounterPlugin', array( + 'counter' => 1, +)); +``` + +Now, let's define the server state types and merge it with the types inferred from the client store definition. + +```ts +// Types the server state. +type ServerState = { + state: { + counter: number; + }; +}; + +// Defines the store in a variable to be able to extract its type later. +const storeDef = { + actions: { + increment() { + state.counter += 1; + }, + }, + callbacks: { + log() { + console.log( `counter: ${ state.counter }` ); + }, + }, +}; + +// Merges the types of the server state and the client store definition. +type Store = ServerState & typeof storeDef; + +// Injects the final types when calling the `store` function. +const { state } = store< Store >( 'myCounterPlugin', storeDef ); +``` + +Alternatively, if you don't mind typing the entire state including both the values defined on the server and the values defined on the client, you can cast the `state` property and let TypeScript infer the rest of the store. + +Let's imagine you have an additional property in the client global state called `product`. + +```ts +type State = { + counter: number; // The server state. + product: number; // The client state. +}; + +const { state } = store( 'myCounterPlugin', { + state: { + product: 2, + } as State, // Casts the entire state manually. + actions: { + increment() { + state.counter * state.product; + }, + }, +} ); +``` + +That's it. Now, TypeScript will infer the types of the `actions` and `callbacks` properties from the store definition, but it will use the type `State` for the `state` property so it contains the correct types from both the client and server definitions. + +In conclusion, this approach is useful when you have a server state that needs to be manually typed, but you still want to infer the types of the rest of the store. + +### 3. Manually write all the types + +If you prefer to define all the types of the store manually instead of letting TypeScript infer them from your client store definition, you can do that too. You simply need to pass them to the `store` function. + +```ts +// Defines the store types. +interface Store { + state: { + counter: number; // Initial server state + }; + actions: { + increment(): void; + }; + callbacks: { + log(): void; + }; +} + +// Pass the types when calling the `store` function. +const { state } = store< Store >( 'myCounterPlugin', { + actions: { + increment() { + state.counter += 1; + }, + }, + callbacks: { + log() { + console.log( `counter: ${ state.counter }` ); + }, + }, +} ); +``` + +That's it! In conclusion, this approach is useful when you want to control all the types of your store and you don't mind writing them by hand. + +## Typing the local context + +The initial local context is defined on the server using the `data-wp-context` directive. + +```html +<div data-wp-context='{ "counter": 0 }'>...</div> +``` + +For that reason, you need to define its type manually and pass it to the `getContext` function to ensure the returned properties are correctly typed. + +```ts +// Defines the types of your context. +type MyContext = { + counter: number; +}; + +store( 'myCounterPlugin', { + actions: { + increment() { + // Passes it to the getContext function. + const context = getContext< MyContext >(); + // Now `context` is properly typed. + context.counter += 1; + }, + }, +} ); +``` + +To avoid having to pass the context types over and over, you can also define a typed function and use that function instead of `getContext`. + +```ts +// Defines the types of your context. +type MyContext = { + counter: number; +}; + +// Defines a typed function. You only have to do this once. +const getMyContext = getContext< MyContext >; + +store( 'myCounterPlugin', { + actions: { + increment() { + // Use your typed function. + const context = getMyContext(); + // Now `context` is properly typed. + context.counter += 1; + }, + }, +} ); +``` + +That's it! Now you can access the context properties with the correct types. + +## Typing the derived state + +The derived state is data that is calculated based on the global state or local context. In the client store definition, it is defined using a getter in the `state` object. + +_Please, visit the [Understanding global state, local context and derived state](./undestanding-global-state-local-context-and-derived-state.md) guide to learn more about how derived state works in the Interactivity API._ + +Following our previous example, let's create a derived state that is the double of our counter. + +```ts +type MyContext = { + counter: number; +}; + +const myStore = store( 'myCounterPlugin', { + state: { + get double() { + const { counter } = getContext< MyContext >(); + return counter * 2; + }, + }, + actions: { + increment() { + state.counter += 1; // This type is number. + }, + }, +} ); +``` + +Normally, when the derived state depends on the local context, TypeScript will be able to infer the correct types: + +```ts +const myStore: { + state: { + readonly double: number; + }; + actions: { + increment(): void; + }; +}; +``` + +But when the return value of the derived state depends directly on some part of the global state, TypeScript will not be able to infer the types because it will claim that it has a circular reference. + +For example, in this case, TypeScript cannot infer the type of `state.double` because it depends on `state.counter`, and the type of `state` is not completed until the type of `state.double` is defined, creating a circular reference. + +```ts +const { state } = store( 'myCounterPlugin', { + state: { + counter: 0, + get double() { + // TypeScript can't infer this return type because it depends on `state`. + return state.counter * 2; + }, + }, + actions: { + increment() { + state.counter += 1; // This type is now unknown. + }, + }, +} ); +``` + +In this case, depending on your TypeScript configuration, TypeScript will either warn you about a circular reference or simply add the `any` type to the `state` property. + +However, solving this problem is easy; we simply need to manually provide TypeScript with the return type of that getter. Once we do that, the circular reference disappears, and TypeScript can once again infer all the `state` types. + +```ts +const { state } = store( 'myCounterPlugin', { + state: { + counter: 1, + get double(): number { + return state.counter * 2; + }, + }, + actions: { + increment() { + state.counter += 1; // Correctly inferred! + }, + }, +} ); +``` + +These are now the correct inferred types for the previous store. + +```ts +const myStore: { + state: { + counter: number; + readonly double: number; + }; + actions: { + increment(): void; + }; +}; +``` + +When using `wp_interactivity_state` in the server, remember that you also need to define the initial value of your derived state, like this: + +```php +wp_interactivity_state( 'myCounterPlugin', array( + 'counter' => 1, + 'double' => 2, +)); +``` + +But if you are inferring the types, you don't need to manually define the type of the derived state because it already exists in your client's store definition. + +```ts +// You don't need to type `state.double` here. +type ServerState = { + state: { + counter: number; + }; +}; + +// The `state.double` type is inferred from here. +const storeDef = { + state: { + get double(): number { + return state.counter * 2; + }, + }, + actions: { + increment() { + state.counter += 1; + }, + }, +}; + +// Merges the types of the server state and the client store definition. +type Store = ServerState & typeof storeDef; + +// Injects the final types when calling the `store` function. +const { state } = store< Store >( 'myCounterPlugin', storeDef ); +``` + +That's it! Now you can access the derived state properties with the correct types. + +## Typing asynchronous actions + +Another thing to keep in mind when using TypeScript with the Interactivity API is that asynchronous actions must be defined with generators instead of async functions. + +The reason for using generators in the Interactivity API's asynchronous actions is to be able to restore the scope from the initially triggered action once the asynchronous action continues its execution after yielding. But this is a syntax change only, otherwise, **these functions operate just like regular async functions**, and the inferred types from the `store` function reflect this. + +Following our previous example, let's add an asynchronous action to the store. + +```ts +const { state } = store( 'myCounterPlugin', { + state: { + counter: 0, + get double(): number { + return state.counter * 2; + }, + }, + actions: { + increment() { + state.counter += 1; + }, + *delayedIncrement() { + yield new Promise( ( r ) => setTimeout( r, 1000 ) ); + state.counter += 1; + }, + }, +} ); +``` + +The inferred types for this store are: + +```ts +const myStore: { + state: { + counter: number; + readonly double: number; + }; + actions: { + increment(): void; + // This behaves like a regular async function. + delayedIncrement(): Promise< void >; + }; +}; +``` + +This also means that you can use your async actions in external functions, and TypeScript will correctly use the async function types. + +```ts +const someAsyncFunction = async () => { + // This works fine and it's correctly typed. + await actions.delayedIncrement( 2000 ); +}; +``` + +When you are not inferring types but manually writing the types for your entire store, you can use async function types for your async actions. + +```ts +type Store = { + state: { + counter: number; + readonly double: number; + }; + actions: { + increment(): void; + delayedIncrement(): Promise< void >; // You can use async functions here. + }; +}; +``` + +There's something to keep in mind when when using asynchronous actions. Just like with the derived state, if the asynchronous action needs to return a value and this value directly depends on some part of the global state, TypeScript will not be able to infer the type due to a circular reference. + + ```ts + const { state, actions } = store( 'myCounterPlugin', { + state: { + counter: 0, + }, + actions: { + *delayedReturn() { + yield new Promise( ( r ) => setTimeout( r, 1000 ) ); + return state.counter; // TypeScript can't infer this return type. + }, + }, + } ); + ``` + + In this case, just as we did with the derived state, we must manually type the return value of the generator. + + ```ts + const { state, actions } = store( 'myCounterPlugin', { + state: { + counter: 0, + }, + actions: { + *delayedReturn(): Generator< uknown, number, uknown > { + yield new Promise( ( r ) => setTimeout( r, 1000 ) ); + return state.counter; // Now this is correctly inferred. + }, + }, + } ); + ``` + + That's it! Remember that the return type of a Generator is the second generic argument: `Generator< unknown, ReturnType, unknown >`. + +## Typing stores that are divided into multiple parts + +Sometimes, stores can be divided into different files. This can happen when different blocks share the same namespace, with each block loading the part of the store it needs. + +Let's look at an example of two blocks: + +- `todo-list`: A block that displays a list of todos. +- `add-post-to-todo`: A block that shows a button to add a new todo item to the list with the text "Read {$post_title}". + +First, let's initialize the global and derived state of the `todo-list` block on the server. + +```php +<?php +// todo-list-block/render.php +$todos = array( 'Buy milk', 'Walk the dog' ); +wp_interactivity_state( 'myTodoPlugin', array( + 'todos' => $todos, + 'filter' => 'all', + 'filteredTodos' => $todos, +)); +?> + +<!-- HTML markup... --> +``` + +Now, let's type the server state and add the client store definition. Remember, `filteredTodos` is derived state, so you don't need to type it manually. + +```ts +// todo-list-block/view.ts +type ServerState = { + state: { + todos: string[]; + filter: 'all' | 'completed'; + }; +}; + +const todoList = { + state: { + get filteredTodos(): string[] { + return state.filter === 'completed' + ? state.todos.filter( ( todo ) => todo.includes( '✅' ) ) + : state.todos; + }, + }, + actions: { + addTodo( todo: string ) { + state.todos.push( todo ); + }, + }, +}; + +// Merges the inferred types with the server state types. +export type TodoList = ServerState & typeof todoList; + +// Injects the final types when calling the `store` function. +const { state } = store< TodoList >( 'myTodoPlugin', todoList ); +``` + +So far, so good. Now let's create our `add-post-to-todo` block. + +First, let's add the current post title to the server state. + +```php +<?php +// add-post-to-todo-block/render.php +wp_interactivity_state( 'myTodoPlugin', array( + 'postTitle' => get_the_title(), +)); +?> + +<!-- HTML markup... --> +``` + +Now, let's type that server state and add the client store definition. + +```ts +// add-post-to-todo-block/view.ts +type ServerState = { + state: { + postTitle: string; + }; +}; + +const addPostToTodo = { + actions: { + addPostToTodo() { + const todo = `Read: ${ state.postTitle }`.trim(); + if ( ! state.todos.includes( todo ) ) { + actions.addTodo( todo ); + } + }, + }, +}; + +// Merges the inferred types with the server state types. +type Store = ServerState & typeof addPostToTodo; + +// Injects the final types when calling the `store` function. +const { state, actions } = store< Store >( 'myTodoPlugin', addPostToTodo ); +``` + +This works fine in the browser, but TypeScript will complain that, in this block, `state` and `actions` do not include `state.todos` and `actions.addtodo`. + +To fix this, we need to import the `TodoList` type from the `todo-list` block and merge it with the other types. + +```ts +import type { TodoList } from '../todo-list-block/view'; + +// ... + +// Merges the inferred types inferred the server state types. +type Store = TodoList & ServerState & typeof addPostToTodo; +``` + +That's it! Now TypeScript will know that `state.todos` and `actions.addTodo` are available in the `add-post-to-todo` block. + +This approach allows the `add-post-to-todo` block to interact with the existing todo list while maintaining type safety and adding its own functionality to the shared store. + +If you need to use the `add-post-to-todo` types in the `todo-list` block, you simply have to export its types and import them in the other `view.ts` file. + +Finally, if you prefer to define all types manually instead of inferring them, you can define them in a separate file and import that definition into each of your store parts. Here's how you could do that for our todo list example: + +```ts +// types.ts +interface Store { + state: { + todos: string[]; + filter: 'all' | 'completed'; + filtered: string[]; + postTitle: string; + }; + actions: { + addTodo( todo: string ): void; + addPostToTodo(): void; + }; +} + +export default Store; +``` + +```ts +// todo-list-block/view.ts +import type Store from '../types'; + +const { state } = store< Store >( 'myTodoPlugin', { + // Everything is correctly typed here +} ); +``` + +```ts +// add-post-to-todo-block/view.ts +import type Store from '../types'; + +const { state, actions } = store< Store >( 'myTodoPlugin', { + // Everything is correctly typed here +} ); +``` + +This approach allows you to have full control over your types and ensures consistency across all parts of your store. It's particularly useful when you have a complex store structure or when you want to enforce a specific interface across multiple blocks or components. + +## Importing and exporting typed stores + +In the Interactivity API, stores from other namespaces can be accessed using the `store` function. + +Let's go back to our `todo-list` block example, but this time, let's imagine that the `add-post-to-todo` block belongs to a different plugin and therefore will use a different namespace. + +```ts +// Import the store of the `todo-list` block. +const myTodoPlugin = store( 'myTodoPlugin' ); + +store( 'myAddPostToTodoPlugin', { + actions: { + addPostToTodo() { + const todo = `Read: ${ state.postTitle }`.trim(); + if ( ! myTodoPlugin.state.todos.includes( todo ) ) { + myTodoPlugin.actions.addTodo( todo ); + } + }, + }, +} ); +``` + +This works fine in the browser, but TypeScript will complain that `myTodoPlugin.state` and `myTodoPlugin.actions` are not typed. + +To fix that, the `myTodoPlugin` plugin can export the result of calling the `store` function with the correct types, and make that available using a script module. + +```ts +// Export the already typed state and actions. +export const { state, actions } = store< TodoList >( 'myTodoPlugin', { + // ... +} ); +``` + +Now, the `add-post-to-todo` block can import the typed store from the `myTodoPlugin` script module, and it not only ensures that the store will be loaded, but that it also contains the correct types. + +```ts +import { store } from '@wordpress/interactivity'; +import { + state as todoState, + actions as todoActions, +} from 'my-todo-plugin-module'; + +store( 'myAddPostToTodoPlugin', { + actions: { + addPostToTodo() { + const todo = `Read: ${ state.postTitle }`.trim(); + if ( ! todoState.todos.includes( todo ) ) { + todoActions.addTodo( todo ); + } + }, + }, +} ); +``` + +Remember that you will need to declare the `my-todo-plugin-module` script module as a dependency. + +If the other store is optional and you don't want to load it eagerly, a dynamic import can be used instead of a static import. + +```ts +import { store } from '@wordpress/interactivity'; + +store( 'myAddPostToTodoPlugin', { + actions: { + *addPostToTodo() { + const todoPlugin = yield import( 'my-todo-plugin-module' ); + const todo = `Read: ${ state.postTitle }`.trim(); + if ( ! todoPlugin.state.todos.includes( todo ) ) { + todoPlugin.actions.addTodo( todo ); + } + }, + }, +} ); +``` + +## Conclusion + +In this guide, we explored different approaches to typing the Interactivity API stores, from inferring types automatically to manually defining them. We also covered how to handle server-initialized state, local context, and derived state, as well as how to type asynchronous actions. + +Remember that the choice between inferring types and manually defining them depends on your specific needs and the complexity of your store. Whichever approach you choose, TypeScript will help you build better and more reliable interactive blocks. diff --git a/docs/toc.json b/docs/toc.json index 719ffa344e3744..0d4689811b26ec 100644 --- a/docs/toc.json +++ b/docs/toc.json @@ -214,6 +214,9 @@ }, { "docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md": [] + }, + { + "docs/reference-guides/interactivity-api/core-concepts/using-typescript.md": [] } ] }, diff --git a/packages/create-block-interactive-template/CHANGELOG.md b/packages/create-block-interactive-template/CHANGELOG.md index 348c8466836c69..24dcfd52b7b586 100644 --- a/packages/create-block-interactive-template/CHANGELOG.md +++ b/packages/create-block-interactive-template/CHANGELOG.md @@ -1,9 +1,11 @@ <!-- Learn how to maintain this file at https://github.com/WordPress/gutenberg/tree/HEAD/packages#maintaining-changelogs. --> -## Unreleased - ## 2.8.0 (2024-09-19) +### Enhancements + +- Added TypeScript variant of the template ([#64577](https://github.com/WordPress/gutenberg/pull/64577)). + ## 2.7.0 (2024-09-05) ### Enhancements diff --git a/packages/create-block-interactive-template/README.md b/packages/create-block-interactive-template/README.md index 4417c647495c4c..b50adb49265245 100644 --- a/packages/create-block-interactive-template/README.md +++ b/packages/create-block-interactive-template/README.md @@ -1,6 +1,6 @@ # Create Block Interactive Template -This is a template for [`@wordpress/create-block`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/create-block/README.md) to create interactive blocks +This is a template for [`@wordpress/create-block`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/create-block/README.md) to create interactive blocks. ## Usage diff --git a/packages/create-block-interactive-template/block-templates/README.md.mustache b/packages/create-block-interactive-template/block-templates/README.md.mustache index 3e64ce8f629a3c..4a13743750f748 100644 --- a/packages/create-block-interactive-template/block-templates/README.md.mustache +++ b/packages/create-block-interactive-template/block-templates/README.md.mustache @@ -3,6 +3,4 @@ > **Note** > Check the [Interactivity API Reference docs in the Block Editor handbook](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/) to learn more about the Interactivity API. -{{#isBasicVariant}} This block has been created with the `create-block-interactive-template` and shows a basic structure of an interactive block that uses the Interactivity API. -{{/isBasicVariant}} \ No newline at end of file diff --git a/packages/create-block-interactive-template/block-templates/render.php.mustache b/packages/create-block-interactive-template/block-templates/render.php.mustache index 3a41a2981cd8cf..4f84b30dbcdbdd 100644 --- a/packages/create-block-interactive-template/block-templates/render.php.mustache +++ b/packages/create-block-interactive-template/block-templates/render.php.mustache @@ -1,4 +1,3 @@ -{{#isBasicVariant}} <?php /** * PHP file to use when rendering the block type on the server to show on the front end. @@ -11,8 +10,19 @@ * @see https://github.com/WordPress/gutenberg/blob/trunk/docs/reference-guides/block-api/block-metadata.md#render */ -// Generate unique id for aria-controls. +// Generates a unique id for aria-controls. $unique_id = wp_unique_id( 'p-' ); + +// Adds the global state. +wp_interactivity_state( + '{{namespace}}', + array( + 'isDark' => false, + 'darkText' => esc_html__( 'Switch to Light', '{{textdomain}}' ), + 'lightText' => esc_html__( 'Switch to Dark', '{{textdomain}}' ), + 'themeText' => esc_html__( 'Switch to Dark', '{{textdomain}}' ), + ) +); ?> <div @@ -20,9 +30,15 @@ $unique_id = wp_unique_id( 'p-' ); data-wp-interactive="{{namespace}}" <?php echo wp_interactivity_data_wp_context( array( 'isOpen' => false ) ); ?> data-wp-watch="callbacks.logIsOpen" + data-wp-class--dark-theme="state.isDark" > <button - data-wp-on--click="actions.toggle" + data-wp-on--click="actions.toggleTheme" + data-wp-text="state.themeText" + ></button> + + <button + data-wp-on--click="actions.toggleOpen" data-wp-bind--aria-expanded="context.isOpen" aria-controls="<?php echo esc_attr( $unique_id ); ?>" > @@ -38,4 +54,3 @@ $unique_id = wp_unique_id( 'p-' ); ?> </p> </div> -{{/isBasicVariant}} diff --git a/packages/create-block-interactive-template/block-templates/style.scss.mustache b/packages/create-block-interactive-template/block-templates/style.scss.mustache index 1c73fa1c38ff94..c8aa9f232136e2 100644 --- a/packages/create-block-interactive-template/block-templates/style.scss.mustache +++ b/packages/create-block-interactive-template/block-templates/style.scss.mustache @@ -9,4 +9,19 @@ font-size: 1em; background: #ffff001a; padding: 1em; + + &.dark-theme { + background: #333; + color: #fff; + + button { + background: #555; + color: #fff; + border: 1px solid #777; + } + + p { + color: #ddd; + } + } } diff --git a/packages/create-block-interactive-template/block-templates/view.js.mustache b/packages/create-block-interactive-template/block-templates/view.js.mustache index b4bae3939461dd..3fcf1ba365d265 100644 --- a/packages/create-block-interactive-template/block-templates/view.js.mustache +++ b/packages/create-block-interactive-template/block-templates/view.js.mustache @@ -1,15 +1,23 @@ -{{#isBasicVariant}} +{{#isDefaultVariant}} /** * WordPress dependencies */ -import { store, getContext } from "@wordpress/interactivity"; +import { store, getContext } from '@wordpress/interactivity'; -store( '{{namespace}}', { +const { state } = store( '{{namespace}}', { + state: { + get themeText() { + return state.isDark ? state.darkText : state.lightText; + } + }, actions: { - toggle: () => { + toggleOpen() { const context = getContext(); context.isOpen = ! context.isOpen; }, + toggleTheme() { + state.isDark = ! state.isDark; + } }, callbacks: { logIsOpen: () => { @@ -19,5 +27,4 @@ store( '{{namespace}}', { }, }, } ); - -{{/isBasicVariant}} +{{/isDefaultVariant}} diff --git a/packages/create-block-interactive-template/block-templates/view.ts.mustache b/packages/create-block-interactive-template/block-templates/view.ts.mustache new file mode 100644 index 00000000000000..11670442d73704 --- /dev/null +++ b/packages/create-block-interactive-template/block-templates/view.ts.mustache @@ -0,0 +1,46 @@ +{{#isTypescriptVariant}} +/** + * WordPress dependencies + */ +import { store, getContext } from '@wordpress/interactivity'; + +type ServerState = { + state: { + isDark: boolean; + darkText: string; + lightText: string; + }; +}; + +type Context = { + isOpen: boolean; +}; + +const storeDef = { + state: { + get themeText(): string { + return state.isDark ? state.darkText : state.lightText; + } + }, + actions: { + toggleOpen() { + const context = getContext< Context >(); + context.isOpen = ! context.isOpen; + }, + toggleTheme() { + state.isDark = ! state.isDark; + } + }, + callbacks: { + logIsOpen: () => { + const { isOpen } = getContext< Context >(); + // Log the value of `isOpen` each time it changes. + console.log( `Is open: ${ isOpen }` ); + }, + }, +}; + +type Store = ServerState & typeof storeDef; + +const { state } = store< Store >( '{{namespace}}', storeDef ); +{{/isTypescriptVariant}} diff --git a/packages/create-block-interactive-template/index.js b/packages/create-block-interactive-template/index.js index bb203b7023e281..94f615df2747f2 100644 --- a/packages/create-block-interactive-template/index.js +++ b/packages/create-block-interactive-template/index.js @@ -7,7 +7,7 @@ module.exports = { defaultValues: { slug: 'example-interactive', title: 'Example Interactive', - description: 'An interactive block with the Interactivity API', + description: 'An interactive block with the Interactivity API.', dashicon: 'media-interactive', npmDependencies: [ '@wordpress/interactivity' ], customPackageJSON: { files: [ '[^.]*' ] }, @@ -24,7 +24,14 @@ module.exports = { }, }, variants: { - basic: {}, + default: {}, + typescript: { + slug: 'example-interactive-typescript', + title: 'Example Interactive TypeScript', + description: + 'An interactive block with the Interactivity API using TypeScript.', + viewScriptModule: 'file:./view.ts', + }, }, pluginTemplatesPath: join( __dirname, 'plugin-templates' ), blockTemplatesPath: join( __dirname, 'block-templates' ), diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 6989bcdc0c802c..42f311973709dd 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -6,6 +6,7 @@ ### Enhancements +- Improve TypeScript support for generators ([#64577](https://github.com/WordPress/gutenberg/pull/64577)). - Refactor internal context proxies implementation ([#64713](https://github.com/WordPress/gutenberg/pull/64713)). ### Bug Fixes diff --git a/packages/interactivity/src/hooks.tsx b/packages/interactivity/src/hooks.tsx index 44dc2645da2c80..6b55ec014aa799 100644 --- a/packages/interactivity/src/hooks.tsx +++ b/packages/interactivity/src/hooks.tsx @@ -190,9 +190,13 @@ const resolve = ( path: string, namespace: string ) => { } let resolvedStore = stores.get( namespace ); if ( typeof resolvedStore === 'undefined' ) { - resolvedStore = store( namespace, undefined, { - lock: universalUnlock, - } ); + resolvedStore = store( + namespace, + {}, + { + lock: universalUnlock, + } + ); } const current = { ...resolvedStore, diff --git a/packages/interactivity/src/store.ts b/packages/interactivity/src/store.ts index b1ad07459c62c0..b147e0f61163bf 100644 --- a/packages/interactivity/src/store.ts +++ b/packages/interactivity/src/store.ts @@ -84,6 +84,42 @@ interface StoreOptions { lock?: boolean | string; } +type Prettify< T > = { [ K in keyof T ]: T[ K ] } & {}; +type DeepPartial< T > = T extends object + ? { [ P in keyof T ]?: DeepPartial< T[ P ] > } + : T; +type DeepPartialState< T extends { state: object } > = Omit< T, 'state' > & { + state?: DeepPartial< T[ 'state' ] >; +}; +type ConvertGeneratorToPromise< T > = T extends ( + ...args: infer A +) => Generator< any, infer R, any > + ? ( ...args: A ) => Promise< R > + : never; +type ConvertGeneratorsToPromises< T > = { + [ K in keyof T ]: T[ K ] extends ( ...args: any[] ) => any + ? ConvertGeneratorToPromise< T[ K ] > extends never + ? T[ K ] + : ConvertGeneratorToPromise< T[ K ] > + : T[ K ] extends object + ? Prettify< ConvertGeneratorsToPromises< T[ K ] > > + : T[ K ]; +}; +type ConvertPromiseToGenerator< T > = T extends ( + ...args: infer A +) => Promise< infer R > + ? ( ...args: A ) => Generator< any, R, any > + : never; +type ConvertPromisesToGenerators< T > = { + [ K in keyof T ]: T[ K ] extends ( ...args: any[] ) => any + ? ConvertPromiseToGenerator< T[ K ] > extends never + ? T[ K ] + : ConvertPromiseToGenerator< T[ K ] > + : T[ K ] extends object + ? Prettify< ConvertPromisesToGenerators< T[ K ] > > + : T[ K ]; +}; + export const universalUnlock = 'I acknowledge that using a private store means my plugin will inevitably break on the next store release.'; @@ -132,17 +168,34 @@ export const universalUnlock = * * @return A reference to the namespace content. */ -export function store< S extends object = {} >( + +// Overload for when the types are inferred. +export function store< T extends object >( + namespace: string, + storePart: T, + options?: StoreOptions +): Prettify< ConvertGeneratorsToPromises< T > >; + +// Overload for when types are passed via generics and they contain state. +export function store< T extends { state: object } >( + namespace: string, + storePart: ConvertPromisesToGenerators< DeepPartialState< T > >, + options?: StoreOptions +): Prettify< ConvertGeneratorsToPromises< T > >; + +// Overload for when types are passed via generics and they don't contain state. +export function store< T extends object >( namespace: string, - storePart?: S, + storePart: ConvertPromisesToGenerators< T >, options?: StoreOptions -): S; +): Prettify< ConvertGeneratorsToPromises< T > >; +// Overload for when types are divided into multiple parts. export function store< T extends object >( namespace: string, - storePart?: T, + storePart: ConvertPromisesToGenerators< DeepPartial< T > >, options?: StoreOptions -): T; +): Prettify< ConvertGeneratorsToPromises< T > >; export function store( namespace: string, diff --git a/packages/interactivity/src/test/store.ts b/packages/interactivity/src/test/store.ts new file mode 100644 index 00000000000000..1092001db03143 --- /dev/null +++ b/packages/interactivity/src/test/store.ts @@ -0,0 +1,286 @@ +/** + * Internal dependencies + */ +import { store } from '../store'; + +describe( 'Interactivity API', () => { + describe( 'store', () => { + it( 'dummy test', () => { + expect( true ).toBe( true ); + } ); + + describe( 'types', () => { + describe( 'the whole store can be inferred', () => { + // eslint-disable-next-line no-unused-expressions + async () => { + const myStore = store( 'test', { + state: { + clientValue: 1, + get derived(): number { + return myStore.state.clientValue; + }, + }, + actions: { + sync( n: number ) { + return n; + }, + *async( n: number ) { + const n1: number = + yield myStore.actions.sync( n ); + return myStore.state.derived + n1 + n; + }, + }, + } ); + + myStore.state.clientValue satisfies number; + myStore.state.derived satisfies number; + + // @ts-expect-error + myStore.state.nonExistent satisfies number; + myStore.actions.sync( 1 ) satisfies number; + myStore.actions.async( 1 ) satisfies Promise< number >; + ( await myStore.actions.async( 1 ) ) satisfies number; + + // @ts-expect-error + myStore.actions.nonExistent() satisfies {}; + }; + } ); + + describe( 'the whole store can be manually typed', () => { + // eslint-disable-next-line no-unused-expressions + async () => { + interface Store { + state: { + clientValue: number; + serverValue: number; + readonly derived: number; + }; + actions: { + sync: ( n: number ) => number; + async: ( n: number ) => Promise< number >; + }; + } + + const myStore = store< Store >( 'test', { + state: { + clientValue: 1, + // @ts-expect-error + nonExistent: 2, + get derived(): number { + return myStore.state.serverValue; + }, + }, + actions: { + sync( n ) { + return n; + }, + *async( n ): Generator< unknown, number, unknown > { + const n1 = myStore.actions.sync( n ); + return myStore.state.derived + n1 + n; + }, + }, + } ); + + myStore.state.clientValue satisfies number; + myStore.state.serverValue satisfies number; + myStore.state.derived satisfies number; + // @ts-expect-error + myStore.state.nonExistent satisfies number; + myStore.actions.sync( 1 ) satisfies number; + myStore.actions.async( 1 ) satisfies Promise< number >; + ( await myStore.actions.async( 1 ) ) satisfies number; + // @ts-expect-error + myStore.actions.nonExistent(); + }; + } ); + + describe( 'the server state can be typed and the rest inferred', () => { + // eslint-disable-next-line no-unused-expressions + async () => { + type ServerStore = { + state: { + serverValue: number; + }; + }; + + const clientStore = { + state: { + clientValue: 1, + get derived(): number { + return myStore.state.serverValue; + }, + }, + actions: { + sync( n: number ) { + return n; + }, + *async( + n: number + ): Generator< unknown, number, number > { + const n1: number = + yield myStore.actions.sync( n ); + return myStore.state.derived + n1 + n; + }, + }, + }; + + type Store = ServerStore & typeof clientStore; + + const myStore = store< Store >( 'test', clientStore ); + + myStore.state.clientValue satisfies number; + myStore.state.serverValue satisfies number; + myStore.state.derived satisfies number; + // @ts-expect-error + myStore.state.nonExistent satisfies number; + myStore.actions.sync( 1 ) satisfies number; + myStore.actions.async( 1 ) satisfies Promise< number >; + ( await myStore.actions.async( 1 ) ) satisfies number; + // @ts-expect-error + myStore.actions.nonExistent(); + }; + } ); + + describe( 'the state can be casted and the rest inferred', () => { + // eslint-disable-next-line no-unused-expressions + async () => { + type State = { + clientValue: number; + serverValue: number; + derived: number; + }; + + const myStore = store( 'test', { + state: { + clientValue: 1, + get derived(): number { + return myStore.state.serverValue; + }, + } as State, + actions: { + sync( n: number ) { + return n; + }, + *async( + n: number + ): Generator< unknown, number, number > { + const n1: number = + yield myStore.actions.sync( n ); + return myStore.state.derived + n1 + n; + }, + }, + } ); + + myStore.state.clientValue satisfies number; + myStore.state.serverValue satisfies number; + myStore.state.derived satisfies number; + // @ts-expect-error + myStore.state.nonExistent satisfies number; + myStore.actions.sync( 1 ) satisfies number; + myStore.actions.async( 1 ) satisfies Promise< number >; + ( await myStore.actions.async( 1 ) ) satisfies number; + // @ts-expect-error + myStore.actions.nonExistent() satisfies {}; + }; + } ); + + describe( 'the whole store can be manually typed even if doesnt contain state', () => { + // eslint-disable-next-line no-unused-expressions + async () => { + interface Store { + actions: { + sync: ( n: number ) => number; + async: ( n: number ) => Promise< number >; + }; + callbacks: { + existent: number; + }; + } + + const myStore = store< Store >( 'test', { + actions: { + sync( n ) { + return n; + }, + *async( n ): Generator< unknown, number, number > { + const n1: number = + yield myStore.actions.sync( n ); + return n1 + n; + }, + }, + callbacks: { + existent: 1, + // @ts-expect-error + nonExistent: 1, + }, + } ); + + // @ts-expect-error + myStore.state.nonExistent satisfies number; + myStore.actions.sync( 1 ) satisfies number; + myStore.actions.async( 1 ) satisfies Promise< number >; + ( await myStore.actions.async( 1 ) ) satisfies number; + myStore.callbacks.existent satisfies number; + // @ts-expect-error + myStore.callbacks.nonExistent satisfies number; + // @ts-expect-error + myStore.actions.nonExistent() satisfies {}; + }; + } ); + + describe( 'the store can be divided into multiple parts', () => { + // eslint-disable-next-line no-unused-expressions + async () => { + type ServerState = { + state: { + serverValue: number; + }; + }; + + const firstStorePart = { + state: { + clientValue1: 1, + }, + actions: { + incrementValue1( n = 1 ) { + myStore.state.clientValue1 += n; + }, + }, + }; + + type FirstStorePart = typeof firstStorePart; + + const secondStorePart = { + state: { + clientValue2: 'test', + }, + actions: { + *asyncAction() { + return ( + myStore.state.clientValue1 + + myStore.state.serverValue + ); + }, + }, + }; + + type Store = ServerState & + FirstStorePart & + typeof secondStorePart; + + const myStore = store< Store >( 'test', firstStorePart ); + store( 'test', secondStorePart ); + + myStore.state.clientValue1 satisfies number; + myStore.state.clientValue2 satisfies string; + myStore.actions.incrementValue1( 1 ); + myStore.actions.asyncAction() satisfies Promise< number >; + ( await myStore.actions.asyncAction() ) satisfies number; + + // @ts-expect-error + myStore.state.nonExistent satisfies {}; + }; + } ); + } ); + } ); +} ); diff --git a/packages/interactivity/tsconfig.test.json b/packages/interactivity/tsconfig.test.json new file mode 100644 index 00000000000000..6a90abc2ba2210 --- /dev/null +++ b/packages/interactivity/tsconfig.test.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "noEmit": true, + "emitDeclarationOnly": false, + "types": [ "jest" ] + }, + "references": [ { "path": "./tsconfig.json" } ], + "files": [ "src/test/store.ts" ], + "exclude": [] +} diff --git a/tsconfig.json b/tsconfig.json index 3ab54f66019bca..8821ef4404e3b5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -32,6 +32,7 @@ { "path": "packages/i18n" }, { "path": "packages/icons" }, { "path": "packages/interactivity" }, + { "path": "packages/interactivity/tsconfig.test.json" }, { "path": "packages/interactivity-router" }, { "path": "packages/is-shallow-equal" }, { "path": "packages/keycodes" }, From 7f87eef0ea040be05a02e03b1b5a67f3f77af892 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 23 Sep 2024 12:43:12 +0200 Subject: [PATCH 0913/1908] Global Styles: remove navigator screen overrides (#65522) --- .../src/components/global-styles-sidebar/style.scss | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/edit-site/src/components/global-styles-sidebar/style.scss b/packages/edit-site/src/components/global-styles-sidebar/style.scss index b76192ddfcb5ca..4ca87bf200f178 100644 --- a/packages/edit-site/src/components/global-styles-sidebar/style.scss +++ b/packages/edit-site/src/components/global-styles-sidebar/style.scss @@ -22,14 +22,7 @@ flex-direction: column; min-height: 100%; - &__panel, - &__navigator-provider { - display: flex; - flex-direction: column; - flex: 1; - } - - &__navigator-screen { + &__panel { flex: 1; } } From 51d0f20679f22474cea3b4742e1b83d63508a2bb Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 23 Sep 2024 13:46:16 +0100 Subject: [PATCH 0914/1908] Select Mode: Updates to the block toolbar (#65485) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: noisysocks <noisysocks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../block-controls/use-has-block-controls.js | 35 --- .../components/block-parent-selector/index.js | 23 +- .../block-settings-dropdown.js | 218 ++++++++++-------- .../src/components/block-switcher/index.js | 67 +++--- .../src/components/block-toolbar/index.js | 56 ++--- .../src/components/block-toolbar/style.scss | 11 +- .../block-toolbar/use-has-block-toolbar.js | 50 ++-- .../src/store/private-selectors.js | 1 + packages/block-editor/src/store/utils.js | 2 + 9 files changed, 224 insertions(+), 239 deletions(-) delete mode 100644 packages/block-editor/src/components/block-controls/use-has-block-controls.js diff --git a/packages/block-editor/src/components/block-controls/use-has-block-controls.js b/packages/block-editor/src/components/block-controls/use-has-block-controls.js deleted file mode 100644 index f7884cc1882ed5..00000000000000 --- a/packages/block-editor/src/components/block-controls/use-has-block-controls.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * WordPress dependencies - */ -import { __experimentalUseSlotFills as useSlotFills } from '@wordpress/components'; -import warning from '@wordpress/warning'; - -/** - * Internal dependencies - */ -import groups from './groups'; - -export function useHasAnyBlockControls() { - let hasAnyBlockControls = false; - for ( const group in groups ) { - // It is safe to violate the rules of hooks here as the `groups` object - // is static and will not change length between renders. Do not return - // early as that will cause the hook to be called a different number of - // times between renders. - // eslint-disable-next-line react-hooks/rules-of-hooks - if ( useHasBlockControls( group ) ) { - hasAnyBlockControls = true; - } - } - return hasAnyBlockControls; -} - -export function useHasBlockControls( group = 'default' ) { - const Slot = groups[ group ]?.Slot; - const fills = useSlotFills( Slot?.__unstableName ); - if ( ! Slot ) { - warning( `Unknown BlockControls group "${ group }" provided.` ); - return null; - } - return !! fills?.length; -} diff --git a/packages/block-editor/src/components/block-parent-selector/index.js b/packages/block-editor/src/components/block-parent-selector/index.js index 80b314eeb42e5c..9090de42f8b7d7 100644 --- a/packages/block-editor/src/components/block-parent-selector/index.js +++ b/packages/block-editor/src/components/block-parent-selector/index.js @@ -14,6 +14,7 @@ import useBlockDisplayInformation from '../use-block-display-information'; import BlockIcon from '../block-icon'; import { useShowHoveredOrFocusedGestures } from '../block-toolbar/utils'; import { store as blockEditorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; /** * Block parent selector component, displaying the hierarchy of the @@ -23,24 +24,26 @@ import { store as blockEditorStore } from '../../store'; */ export default function BlockParentSelector() { const { selectBlock } = useDispatch( blockEditorStore ); - const { firstParentClientId, isVisible } = useSelect( ( select ) => { + const { parentClientId, isVisible } = useSelect( ( select ) => { const { getBlockName, getBlockParents, getSelectedBlockClientId, getBlockEditingMode, - } = select( blockEditorStore ); + getParentSectionBlock, + } = unlock( select( blockEditorStore ) ); const { hasBlockSupport } = select( blocksStore ); const selectedBlockClientId = getSelectedBlockClientId(); + const parentSection = getParentSectionBlock( selectedBlockClientId ); const parents = getBlockParents( selectedBlockClientId ); - const _firstParentClientId = parents[ parents.length - 1 ]; - const parentBlockName = getBlockName( _firstParentClientId ); + const _parentClientId = parentSection ?? parents[ parents.length - 1 ]; + const parentBlockName = getBlockName( _parentClientId ); const _parentBlockType = getBlockType( parentBlockName ); return { - firstParentClientId: _firstParentClientId, + parentClientId: _parentClientId, isVisible: - _firstParentClientId && - getBlockEditingMode( _firstParentClientId ) === 'default' && + _parentClientId && + getBlockEditingMode( _parentClientId ) !== 'disabled' && hasBlockSupport( _parentBlockType, '__experimentalParentSelector', @@ -48,7 +51,7 @@ export default function BlockParentSelector() { ), }; }, [] ); - const blockInformation = useBlockDisplayInformation( firstParentClientId ); + const blockInformation = useBlockDisplayInformation( parentClientId ); // Allows highlighting the parent block outline when focusing or hovering // the parent block selector within the child. @@ -65,13 +68,13 @@ export default function BlockParentSelector() { return ( <div className="block-editor-block-parent-selector" - key={ firstParentClientId } + key={ parentClientId } ref={ nodeRef } { ...showHoveredOrFocusedGestures } > <ToolbarButton className="block-editor-block-parent-selector__button" - onClick={ () => selectBlock( firstParentClientId ) } + onClick={ () => selectBlock( parentClientId ) } label={ sprintf( /* translators: %s: Name of the block's parent. */ __( 'Select parent block: %s' ), diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index fff5acc7b79c46..ac2b99ac2bb620 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -183,6 +183,9 @@ export function BlockSettingsDropdown( { } } + const shouldShowBlockParentMenuItem = + ! parentBlockIsSelected && !! firstParentClientId; + return ( <BlockActions clientIds={ clientIds } @@ -199,25 +202,39 @@ export function BlockSettingsDropdown( { onRemove, onCopy, onPasteStyles, - } ) => ( - <DropdownMenu - icon={ moreVertical } - label={ __( 'Options' ) } - className="block-editor-block-settings-menu" - popoverProps={ POPOVER_PROPS } - open={ open } - onToggle={ onToggle } - noIcons - { ...props } - > - { ( { onClose } ) => ( - <> - <MenuGroup> - <__unstableBlockSettingsMenuFirstItem.Slot - fillProps={ { onClose } } - /> - { ! parentBlockIsSelected && - !! firstParentClientId && ( + } ) => { + // It is possible that some plugins register fills for this menu + // even if Core doesn't render anything in the block settings menu. + // in which case, we may want to render the menu anyway. + // That said for now, we can start more conservative. + const isEmpty = + ! canRemove && + ! canDuplicate && + ! canInsertBlock && + isContentOnly; + + if ( isEmpty ) { + return null; + } + + return ( + <DropdownMenu + icon={ moreVertical } + label={ __( 'Options' ) } + className="block-editor-block-settings-menu" + popoverProps={ POPOVER_PROPS } + open={ open } + onToggle={ onToggle } + noIcons + { ...props } + > + { ( { onClose } ) => ( + <> + <MenuGroup> + <__unstableBlockSettingsMenuFirstItem.Slot + fillProps={ { onClose } } + /> + { shouldShowBlockParentMenuItem && ( <BlockParentSelectorMenuItem parentClientId={ firstParentClientId @@ -225,98 +242,103 @@ export function BlockSettingsDropdown( { parentBlockType={ parentBlockType } /> ) } - { count === 1 && ( - <BlockHTMLConvertButton - clientId={ firstBlockClientId } - /> - ) } - { ! isContentOnly && ( - <CopyMenuItem - clientIds={ clientIds } - onCopy={ onCopy } - shortcut={ displayShortcut.primary( - 'c' - ) } - /> - ) } - { canDuplicate && ( - <MenuItem - onClick={ pipe( - onClose, - onDuplicate, - updateSelectionAfterDuplicate - ) } - shortcut={ shortcuts.duplicate } - > - { __( 'Duplicate' ) } - </MenuItem> - ) } - { canInsertBlock && ! isContentOnly && ( - <> + { count === 1 && ( + <BlockHTMLConvertButton + clientId={ firstBlockClientId } + /> + ) } + { ! isContentOnly && ( + <CopyMenuItem + clientIds={ clientIds } + onCopy={ onCopy } + shortcut={ displayShortcut.primary( + 'c' + ) } + /> + ) } + { canDuplicate && ( <MenuItem onClick={ pipe( onClose, - onInsertBefore + onDuplicate, + updateSelectionAfterDuplicate ) } - shortcut={ shortcuts.insertBefore } + shortcut={ shortcuts.duplicate } > - { __( 'Add before' ) } + { __( 'Duplicate' ) } + </MenuItem> + ) } + { canInsertBlock && ! isContentOnly && ( + <> + <MenuItem + onClick={ pipe( + onClose, + onInsertBefore + ) } + shortcut={ + shortcuts.insertBefore + } + > + { __( 'Add before' ) } + </MenuItem> + <MenuItem + onClick={ pipe( + onClose, + onInsertAfter + ) } + shortcut={ + shortcuts.insertAfter + } + > + { __( 'Add after' ) } + </MenuItem> + </> + ) } + </MenuGroup> + { canCopyStyles && ! isContentOnly && ( + <MenuGroup> + <CopyMenuItem + clientIds={ clientIds } + onCopy={ onCopy } + label={ __( 'Copy styles' ) } + /> + <MenuItem onClick={ onPasteStyles }> + { __( 'Paste styles' ) } </MenuItem> + </MenuGroup> + ) } + <BlockSettingsMenuControls.Slot + fillProps={ { + onClose, + count, + firstBlockClientId, + } } + clientIds={ clientIds } + /> + { typeof children === 'function' + ? children( { onClose } ) + : Children.map( ( child ) => + cloneElement( child, { onClose } ) + ) } + { canRemove && ( + <MenuGroup> <MenuItem onClick={ pipe( onClose, - onInsertAfter + onRemove, + updateSelectionAfterRemove ) } - shortcut={ shortcuts.insertAfter } + shortcut={ shortcuts.remove } > - { __( 'Add after' ) } + { __( 'Delete' ) } </MenuItem> - </> + </MenuGroup> ) } - </MenuGroup> - { canCopyStyles && ! isContentOnly && ( - <MenuGroup> - <CopyMenuItem - clientIds={ clientIds } - onCopy={ onCopy } - label={ __( 'Copy styles' ) } - /> - <MenuItem onClick={ onPasteStyles }> - { __( 'Paste styles' ) } - </MenuItem> - </MenuGroup> - ) } - <BlockSettingsMenuControls.Slot - fillProps={ { - onClose, - count, - firstBlockClientId, - } } - clientIds={ clientIds } - /> - { typeof children === 'function' - ? children( { onClose } ) - : Children.map( ( child ) => - cloneElement( child, { onClose } ) - ) } - { canRemove && ( - <MenuGroup> - <MenuItem - onClick={ pipe( - onClose, - onRemove, - updateSelectionAfterRemove - ) } - shortcut={ shortcuts.remove } - > - { __( 'Delete' ) } - </MenuItem> - </MenuGroup> - ) } - </> - ) } - </DropdownMenu> - ) } + </> + ) } + </DropdownMenu> + ); + } } </BlockActions> ); } diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js index 98e7f7b2d21420..79f33bd30d7537 100644 --- a/packages/block-editor/src/components/block-switcher/index.js +++ b/packages/block-editor/src/components/block-switcher/index.js @@ -35,36 +35,40 @@ function BlockSwitcherDropdownMenuContents( { clientIds, hasBlockStyles, canRemove, - isUsingBindings, } ) { const { replaceBlocks, multiSelect, updateBlockAttributes } = useDispatch( blockEditorStore ); - const { possibleBlockTransformations, patterns, blocks } = useSelect( - ( select ) => { - const { - getBlocksByClientId, - getBlockRootClientId, - getBlockTransformItems, - __experimentalGetPatternTransformItems, - } = select( blockEditorStore ); - const rootClientId = getBlockRootClientId( - Array.isArray( clientIds ) ? clientIds[ 0 ] : clientIds - ); - const _blocks = getBlocksByClientId( clientIds ); - return { - blocks: _blocks, - possibleBlockTransformations: getBlockTransformItems( - _blocks, - rootClientId - ), - patterns: __experimentalGetPatternTransformItems( - _blocks, - rootClientId - ), - }; - }, - [ clientIds ] - ); + const { possibleBlockTransformations, patterns, blocks, isUsingBindings } = + useSelect( + ( select ) => { + const { + getBlockAttributes, + getBlocksByClientId, + getBlockRootClientId, + getBlockTransformItems, + __experimentalGetPatternTransformItems, + } = select( blockEditorStore ); + const rootClientId = getBlockRootClientId( clientIds[ 0 ] ); + const _blocks = getBlocksByClientId( clientIds ); + return { + blocks: _blocks, + possibleBlockTransformations: getBlockTransformItems( + _blocks, + rootClientId + ), + patterns: __experimentalGetPatternTransformItems( + _blocks, + rootClientId + ), + isUsingBindings: clientIds.every( + ( clientId ) => + !! getBlockAttributes( clientId )?.metadata + ?.bindings + ), + }; + }, + [ clientIds ] + ); const blockVariationTransformations = useBlockVariationTransforms( { clientIds, blocks, @@ -196,7 +200,7 @@ const BlockIndicator = ( { icon, showTitle, blockTitle } ) => ( </> ); -export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { +export const BlockSwitcher = ( { clientIds } ) => { const { hasContentOnlyLocking, canRemove, @@ -205,6 +209,7 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { invalidBlocks, isReusable, isTemplate, + isDisabled, } = useSelect( ( select ) => { const { @@ -212,6 +217,7 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { getBlocksByClientId, getBlockAttributes, canRemoveBlocks, + getBlockEditingMode, } = select( blockEditorStore ); const { getBlockStyles, getBlockType, getActiveBlockVariation } = select( blocksStore ); @@ -222,6 +228,7 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { const [ { name: firstBlockName } ] = _blocks; const _isSingleBlockSelected = _blocks.length === 1; const blockType = getBlockType( firstBlockName ); + const editingMode = getBlockEditingMode( clientIds[ 0 ] ); let _icon; let _hasTemplateLock; @@ -256,6 +263,7 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { isTemplate: _isSingleBlockSelected && isTemplatePart( _blocks[ 0 ] ), hasContentOnlyLocking: _hasTemplateLock, + isDisabled: editingMode !== 'default', }; }, [ clientIds ] @@ -275,7 +283,7 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { : __( 'Multiple blocks selected' ); const hideDropdown = - disabled || + isDisabled || ( ! hasBlockStyles && ! canRemove ) || hasContentOnlyLocking; @@ -339,7 +347,6 @@ export const BlockSwitcher = ( { clientIds, disabled, isUsingBindings } ) => { clientIds={ clientIds } hasBlockStyles={ hasBlockStyles } canRemove={ canRemove } - isUsingBindings={ isUsingBindings } /> ) } </DropdownMenu> diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 6c4789cb2924f2..2ac2cbb12ff352 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -35,6 +35,7 @@ import { store as blockEditorStore } from '../../store'; import __unstableBlockNameContext from './block-name-context'; import NavigableToolbar from '../navigable-toolbar'; import { useHasBlockToolbar } from './use-has-block-toolbar'; +import { unlock } from '../../lock-unlock'; /** * Renders the block toolbar. @@ -58,7 +59,6 @@ export function PrivateBlockToolbar( { const { blockClientId, blockClientIds, - isContentOnlyEditingMode, isDefaultEditingMode, blockType, toolbarKey, @@ -78,12 +78,14 @@ export function PrivateBlockToolbar( { getBlockAttributes, getBlockParentsByBlockName, getTemplateLock, - } = select( blockEditorStore ); + getParentSectionBlock, + } = unlock( select( blockEditorStore ) ); const selectedBlockClientIds = getSelectedBlockClientIds(); const selectedBlockClientId = selectedBlockClientIds[ 0 ]; const parents = getBlockParents( selectedBlockClientId ); - const firstParentClientId = parents[ parents.length - 1 ]; - const parentBlockName = getBlockName( firstParentClientId ); + const parentSection = getParentSectionBlock( selectedBlockClientId ); + const parentClientId = parentSection ?? parents[ parents.length - 1 ]; + const parentBlockName = getBlockName( parentClientId ); const parentBlockType = getBlockType( parentBlockName ); const editingMode = getBlockEditingMode( selectedBlockClientId ); const _isDefaultEditingMode = editingMode === 'default'; @@ -112,21 +114,19 @@ export function PrivateBlockToolbar( { return { blockClientId: selectedBlockClientId, blockClientIds: selectedBlockClientIds, - isContentOnlyEditingMode: editingMode === 'contentOnly', isDefaultEditingMode: _isDefaultEditingMode, blockType: selectedBlockClientId && getBlockType( _blockName ), shouldShowVisualToolbar: isValid && isVisual, - toolbarKey: `${ selectedBlockClientId }${ firstParentClientId }`, + toolbarKey: `${ selectedBlockClientId }${ parentClientId }`, showParentSelector: parentBlockType && - getBlockEditingMode( firstParentClientId ) === 'default' && + getBlockEditingMode( parentClientId ) !== 'disabled' && hasBlockSupport( parentBlockType, '__experimentalParentSelector', true ) && - selectedBlockClientIds.length === 1 && - _isDefaultEditingMode, + selectedBlockClientIds.length === 1, isUsingBindings: _isUsingBindings, hasParentPattern: _hasParentPattern, hasContentOnlyLocking: _hasTemplateLock, @@ -179,36 +179,26 @@ export function PrivateBlockToolbar( { key={ toolbarKey } > <div ref={ toolbarWrapperRef } className={ innerClasses }> - { ! isMultiToolbar && - isLargeViewport && - isDefaultEditingMode && <BlockParentSelector /> } + { ! isMultiToolbar && isLargeViewport && ( + <BlockParentSelector /> + ) } { ( shouldShowVisualToolbar || isMultiToolbar ) && - ( isDefaultEditingMode || - ( isContentOnlyEditingMode && ! hasParentPattern ) || - isSynced ) && ( + ! hasParentPattern && ( <div ref={ nodeRef } { ...showHoveredOrFocusedGestures } > <ToolbarGroup className="block-editor-block-toolbar__block-controls"> - <BlockSwitcher + <BlockSwitcher clientIds={ blockClientIds } /> + { ! isMultiToolbar && isDefaultEditingMode && ( + <BlockLockToolbar + clientId={ blockClientId } + /> + ) } + <BlockMover clientIds={ blockClientIds } - disabled={ ! isDefaultEditingMode } - isUsingBindings={ isUsingBindings } + hideDragHandle={ hideDragHandle } /> - { isDefaultEditingMode && ( - <> - { ! isMultiToolbar && ( - <BlockLockToolbar - clientId={ blockClientId } - /> - ) } - <BlockMover - clientIds={ blockClientIds } - hideDragHandle={ hideDragHandle } - /> - </> - ) } </ToolbarGroup> </div> ) } @@ -242,9 +232,7 @@ export function PrivateBlockToolbar( { </> ) } <BlockEditVisuallyButton clientIds={ blockClientIds } /> - { isDefaultEditingMode && ( - <BlockSettingsMenu clientIds={ blockClientIds } /> - ) } + <BlockSettingsMenu clientIds={ blockClientIds } /> </div> </NavigableToolbar> ); diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index 40d748dd0a1568..2a0f68a6976686 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -52,9 +52,18 @@ > :last-child, > :last-child .components-toolbar-group, - > :last-child .components-toolbar { + > :last-child .components-toolbar, + // If the last toolbar group is empty, + // we need to remove the double border from the penultimate one. + &:has(> :last-child:empty) > :nth-last-child(2), + &:has(> :last-child:empty) > :nth-last-child(2) .components-toolbar-group, + &:has(> :last-child:empty) > :nth-last-child(2) .components-toolbar { border-right: none; } + + .components-toolbar-group:empty { + display: none; + } } .block-editor-block-contextual-toolbar { diff --git a/packages/block-editor/src/components/block-toolbar/use-has-block-toolbar.js b/packages/block-editor/src/components/block-toolbar/use-has-block-toolbar.js index c4e228f8a3c07b..80ce3691147834 100644 --- a/packages/block-editor/src/components/block-toolbar/use-has-block-toolbar.js +++ b/packages/block-editor/src/components/block-toolbar/use-has-block-toolbar.js @@ -7,7 +7,6 @@ import { getBlockType, hasBlockSupport } from '@wordpress/blocks'; * Internal dependencies */ import { store as blockEditorStore } from '../../store'; -import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls'; /** * Returns true if the block toolbar should be shown. @@ -15,40 +14,29 @@ import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls * @return {boolean} Whether the block toolbar component will be rendered. */ export function useHasBlockToolbar() { - const { isToolbarEnabled, isDefaultEditingMode } = useSelect( - ( select ) => { - const { - getBlockEditingMode, - getBlockName, - getBlockSelectionStart, - } = select( blockEditorStore ); + const { isToolbarEnabled, isBlockDisabled } = useSelect( ( select ) => { + const { getBlockEditingMode, getBlockName, getBlockSelectionStart } = + select( blockEditorStore ); - // we only care about the 1st selected block - // for the toolbar, so we use getBlockSelectionStart - // instead of getSelectedBlockClientIds - const selectedBlockClientId = getBlockSelectionStart(); + // we only care about the 1st selected block + // for the toolbar, so we use getBlockSelectionStart + // instead of getSelectedBlockClientIds + const selectedBlockClientId = getBlockSelectionStart(); - const blockType = - selectedBlockClientId && - getBlockType( getBlockName( selectedBlockClientId ) ); + const blockType = + selectedBlockClientId && + getBlockType( getBlockName( selectedBlockClientId ) ); - return { - isToolbarEnabled: - blockType && - hasBlockSupport( blockType, '__experimentalToolbar', true ), - isDefaultEditingMode: - getBlockEditingMode( selectedBlockClientId ) === 'default', - }; - }, - [] - ); + return { + isToolbarEnabled: + blockType && + hasBlockSupport( blockType, '__experimentalToolbar', true ), + isBlockDisabled: + getBlockEditingMode( selectedBlockClientId ) === 'disabled', + }; + }, [] ); - const hasAnyBlockControls = useHasAnyBlockControls(); - - if ( - ! isToolbarEnabled || - ( ! isDefaultEditingMode && ! hasAnyBlockControls ) - ) { + if ( ! isToolbarEnabled || isBlockDisabled ) { return false; } diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index d8955bd6342c4c..9e99176819ae89 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -116,6 +116,7 @@ export const getEnabledClientIdsTree = createSelector( state.settings.templateLock, state.blockListSettings, state.editorMode, + getSectionRootClientId( state ), ] ); diff --git a/packages/block-editor/src/store/utils.js b/packages/block-editor/src/store/utils.js index af991608238e2e..79e15255e6cc15 100644 --- a/packages/block-editor/src/store/utils.js +++ b/packages/block-editor/src/store/utils.js @@ -10,6 +10,7 @@ import { parse as grammarParse } from '@wordpress/block-serialization-default-pa import { selectBlockPatternsKey } from './private-keys'; import { unlock } from '../lock-unlock'; import { STORE_NAME } from './constants'; +import { getSectionRootClientId } from './private-selectors'; export const withRootClientIdOptionKey = Symbol( 'withRootClientId' ); @@ -118,5 +119,6 @@ export function getInsertBlockTypeDependants( state, rootClientId ) { state.settings.templateLock, state.blockEditingModes, state.editorMode, + getSectionRootClientId( state ), ]; } From 058cc63c53daaa794618ec1a1dd2fa4819cde1da Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 23 Sep 2024 13:47:18 +0100 Subject: [PATCH 0915/1908] Editor: Remove edit template menu item from block settings menu in blocks outside template. (#65560) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- .../content-only-settings-menu.js | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js b/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js index c772a062b9e3be..af0e9b30ae83b4 100644 --- a/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js +++ b/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js @@ -27,7 +27,10 @@ function ContentOnlySettingsMenuItems( { clientId, onClose } ) { getBlockParentsByBlockName, getSettings, getBlockAttributes, + getBlockParents, } = select( blockEditorStore ); + const { getCurrentTemplateId, getRenderingMode } = + select( editorStore ); const patternParent = getBlockParentsByBlockName( clientId, 'core/block', @@ -41,23 +44,17 @@ function ContentOnlySettingsMenuItems( { clientId, onClose } ) { 'wp_block', getBlockAttributes( patternParent ).ref ); - } else { - const { getCurrentTemplateId } = select( editorStore ); - const templateId = getCurrentTemplateId(); - const { getBlockParents } = unlock( - select( blockEditorStore ) + } else if ( + getRenderingMode() === 'template-locked' && + ! getBlockParents( clientId ).some( ( parent ) => + postContentBlocks.includes( parent ) + ) + ) { + record = select( coreStore ).getEntityRecord( + 'postType', + 'wp_template', + getCurrentTemplateId() ); - if ( - ! getBlockParents( clientId ).some( ( parent ) => - postContentBlocks.includes( parent ) - ) - ) { - record = select( coreStore ).getEntityRecord( - 'postType', - 'wp_template', - templateId - ); - } } if ( ! record ) { return {}; From 4a91d3263ef4061c9477529ad71700e8cabc8b63 Mon Sep 17 00:00:00 2001 From: dhruvang21 <105810308+dhruvang21@users.noreply.github.com> Date: Mon, 23 Sep 2024 18:19:13 +0530 Subject: [PATCH 0916/1908] Fixed the focus cutoff of the editor buttons in the widgets editor (#65395) * Fix the focus cutoff of the editor buttons * Add height to fix focus cutoff * Use header height variable Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> --------- Co-authored-by: dhruvang21 <dhruvang21@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/edit-widgets/src/components/header/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/edit-widgets/src/components/header/style.scss b/packages/edit-widgets/src/components/header/style.scss index 6e5d8de8142f42..7bd3c41a6a22ad 100644 --- a/packages/edit-widgets/src/components/header/style.scss +++ b/packages/edit-widgets/src/components/header/style.scss @@ -82,6 +82,7 @@ padding-right: $grid-unit-10; padding-left: $grid-unit-20; overflow: hidden; + height: $header-height; } .edit-widgets-header__title { From 7493185addae2ba9bb1506a24e5b6db47e27f4a1 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 24 Sep 2024 10:38:39 +1000 Subject: [PATCH 0917/1908] Comment Content: Add block example (#65559) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/comment-content/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/comment-content/index.js b/packages/block-library/src/comment-content/index.js index 130f1d30125559..aefcef75acf8ae 100644 --- a/packages/block-library/src/comment-content/index.js +++ b/packages/block-library/src/comment-content/index.js @@ -16,6 +16,7 @@ export { metadata, name }; export const settings = { icon, edit, + example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); From 096c883495ab41876b8d2c8252e88575e8900e32 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 24 Sep 2024 03:00:16 +0200 Subject: [PATCH 0918/1908] Global styles: do not navigate twice to home screen when opening the sidebar (#65523) * Global styles: do not navigate twice to home screen on sidebar load * Remove whole default block Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- .../edit-site/src/components/global-styles/ui.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index 60d7e314d7776a..bc6906a769af48 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -272,19 +272,6 @@ function GlobalStylesEditorCanvasContainerLink() { goTo( '/' ); } break; - default: - /* - * Example: the user has navigated to "Browse styles" or elsewhere - * and changes the editorCanvasContainerView, e.g., closes the style book. - * The panel should not be affected. - * Exclude revisions panel from this behavior, - * as it should close when the editorCanvasContainerView doesn't correspond. - */ - if ( path !== '/' && ! isRevisionsOpen ) { - return; - } - goTo( '/' ); - break; } }, [ editorCanvasContainerView, isRevisionsOpen, goTo ] ); } From 69d77a12f5650f1804bc206acc3be862e5029a6f Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Tue, 24 Sep 2024 13:42:48 +1000 Subject: [PATCH 0919/1908] Link autocompleter: decode post title HTML entities (#65589) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: MadtownLems <madtownlems@git.wordpress.org> --- packages/block-editor/src/autocompleters/link.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/autocompleters/link.js b/packages/block-editor/src/autocompleters/link.js index ce9af28f19d000..fb64cb151294d6 100644 --- a/packages/block-editor/src/autocompleters/link.js +++ b/packages/block-editor/src/autocompleters/link.js @@ -6,6 +6,7 @@ import apiFetch from '@wordpress/api-fetch'; import { addQueryArgs } from '@wordpress/url'; import { Icon, page, post } from '@wordpress/icons'; +import { decodeEntities } from '@wordpress/html-entities'; const SHOWN_SUGGESTIONS = 10; @@ -46,7 +47,7 @@ function createLinkCompleter() { key="icon" icon={ item.subtype === 'page' ? page : post } /> - { item.title } + { decodeEntities( item.title ) } </> ); }, From 842f67ddbadc21e1400fbada663ed4136f8e28ed Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Tue, 24 Sep 2024 08:30:52 +0200 Subject: [PATCH 0920/1908] useToolsPanel: calculate derived state in reducer to prevent too many renders (#65564) Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 + .../src/tools-panel/tools-panel/hook.ts | 384 ++++++++++-------- 2 files changed, 225 insertions(+), 163 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 90481e58edd7bb..001b2d0b4230e9 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- `ToolsPanel`: atomic one-step state update when (un)registering panels ([#65564](https://github.com/WordPress/gutenberg/pull/65564)). + ## 28.8.0 (2024-09-19) ### Bug Fixes diff --git a/packages/components/src/tools-panel/tools-panel/hook.ts b/packages/components/src/tools-panel/tools-panel/hook.ts index 931bf2494e6e34..583a079ab20026 100644 --- a/packages/components/src/tools-panel/tools-panel/hook.ts +++ b/packages/components/src/tools-panel/tools-panel/hook.ts @@ -5,8 +5,8 @@ import { useCallback, useEffect, useMemo, + useReducer, useRef, - useState, } from '@wordpress/element'; /** @@ -27,14 +27,40 @@ import type { const DEFAULT_COLUMNS = 2; +type PanelItemsState = { + panelItems: ToolsPanelItem[]; + menuItemOrder: string[]; + menuItems: ToolsPanelMenuItems; +}; + +type PanelItemsAction = + | { type: 'REGISTER_PANEL'; item: ToolsPanelItem } + | { type: 'UNREGISTER_PANEL'; label: string } + | { + type: 'UPDATE_VALUE'; + group: ToolsPanelMenuItemKey; + label: string; + value: boolean; + } + | { type: 'TOGGLE_VALUE'; label: string } + | { type: 'RESET_ALL' }; + +function emptyMenuItems(): ToolsPanelMenuItems { + return { default: {}, optional: {} }; +} + +function emptyState(): PanelItemsState { + return { panelItems: [], menuItemOrder: [], menuItems: emptyMenuItems() }; +} + const generateMenuItems = ( { panelItems, shouldReset, currentMenuItems, menuItemOrder, }: ToolsPanelMenuItemsConfig ) => { - const newMenuItems: ToolsPanelMenuItems = { default: {}, optional: {} }; - const menuItems: ToolsPanelMenuItems = { default: {}, optional: {} }; + const newMenuItems: ToolsPanelMenuItems = emptyMenuItems(); + const menuItems: ToolsPanelMenuItems = emptyMenuItems(); panelItems.forEach( ( { hasValue, isShownByDefault, label } ) => { const group = isShownByDefault ? 'default' : 'optional'; @@ -75,9 +101,149 @@ const generateMenuItems = ( { return menuItems; }; +function panelItemsReducer( + panelItems: ToolsPanelItem[], + action: PanelItemsAction +) { + switch ( action.type ) { + case 'REGISTER_PANEL': { + const newItems = [ ...panelItems ]; + // If an item with this label has already been registered, remove it + // first. This can happen when an item is moved between the default + // and optional groups. + const existingIndex = newItems.findIndex( + ( oldItem ) => oldItem.label === action.item.label + ); + if ( existingIndex !== -1 ) { + newItems.splice( existingIndex, 1 ); + } + newItems.push( action.item ); + return newItems; + } + case 'UNREGISTER_PANEL': { + const index = panelItems.findIndex( + ( item ) => item.label === action.label + ); + if ( index !== -1 ) { + const newItems = [ ...panelItems ]; + newItems.splice( index, 1 ); + return newItems; + } + return panelItems; + } + default: + return panelItems; + } +} + +function menuItemOrderReducer( + menuItemOrder: string[], + action: PanelItemsAction +) { + switch ( action.type ) { + case 'REGISTER_PANEL': { + // Track the initial order of item registration. This is used for + // maintaining menu item order later. + if ( menuItemOrder.includes( action.item.label ) ) { + return menuItemOrder; + } + + return [ ...menuItemOrder, action.item.label ]; + } + default: + return menuItemOrder; + } +} + +function menuItemsReducer( state: PanelItemsState, action: PanelItemsAction ) { + switch ( action.type ) { + case 'REGISTER_PANEL': + case 'UNREGISTER_PANEL': + // generate new menu items from original `menuItems` and updated `panelItems` and `menuItemOrder` + return generateMenuItems( { + currentMenuItems: state.menuItems, + panelItems: state.panelItems, + menuItemOrder: state.menuItemOrder, + shouldReset: false, + } ); + case 'RESET_ALL': + return generateMenuItems( { + panelItems: state.panelItems, + menuItemOrder: state.menuItemOrder, + shouldReset: true, + } ); + case 'UPDATE_VALUE': { + const oldValue = state.menuItems[ action.group ][ action.label ]; + if ( action.value === oldValue ) { + return state.menuItems; + } + return { + ...state.menuItems, + [ action.group ]: { + ...state.menuItems[ action.group ], + [ action.label ]: action.value, + }, + }; + } + case 'TOGGLE_VALUE': { + const currentItem = state.panelItems.find( + ( item ) => item.label === action.label + ); + + if ( ! currentItem ) { + return state.menuItems; + } + + const menuGroup = currentItem.isShownByDefault + ? 'default' + : 'optional'; + + const newMenuItems = { + ...state.menuItems, + [ menuGroup ]: { + ...state.menuItems[ menuGroup ], + [ action.label ]: + ! state.menuItems[ menuGroup ][ action.label ], + }, + }; + return newMenuItems; + } + + default: + return state.menuItems; + } +} + +function panelReducer( state: PanelItemsState, action: PanelItemsAction ) { + const panelItems = panelItemsReducer( state.panelItems, action ); + const menuItemOrder = menuItemOrderReducer( state.menuItemOrder, action ); + // `menuItemsReducer` is a bit unusual because it generates new state from original `menuItems` + // and the updated `panelItems` and `menuItemOrder`. + const menuItems = menuItemsReducer( + { panelItems, menuItemOrder, menuItems: state.menuItems }, + action + ); + + return { panelItems, menuItemOrder, menuItems }; +} + +function resetAllFiltersReducer( + filters: ResetAllFilter[], + action: { type: 'REGISTER' | 'UNREGISTER'; filter: ResetAllFilter } +) { + switch ( action.type ) { + case 'REGISTER': + return [ ...filters, action.filter ]; + case 'UNREGISTER': + return filters.filter( ( f ) => f !== action.filter ); + default: + return filters; + } +} + const isMenuItemTypeEmpty = ( - obj?: ToolsPanelMenuItems[ ToolsPanelMenuItemKey ] -) => obj && Object.keys( obj ).length === 0; + obj: ToolsPanelMenuItems[ ToolsPanelMenuItemKey ] +) => Object.keys( obj ).length === 0; export function useToolsPanel( props: WordPressComponentProps< ToolsPanelProps, 'div' > @@ -108,103 +274,43 @@ export function useToolsPanel( }, [ wasResetting ] ); // Allow panel items to register themselves. - const [ panelItems, setPanelItems ] = useState< ToolsPanelItem[] >( [] ); - const [ menuItemOrder, setMenuItemOrder ] = useState< string[] >( [] ); - const [ resetAllFilters, setResetAllFilters ] = useState< - ResetAllFilter[] - >( [] ); - - const registerPanelItem = useCallback( - ( item: ToolsPanelItem ) => { - // Add item to panel items. - setPanelItems( ( items ) => { - const newItems = [ ...items ]; - // If an item with this label has already been registered, remove it - // first. This can happen when an item is moved between the default - // and optional groups. - const existingIndex = newItems.findIndex( - ( oldItem ) => oldItem.label === item.label - ); - if ( existingIndex !== -1 ) { - newItems.splice( existingIndex, 1 ); - } - return [ ...newItems, item ]; - } ); - - // Track the initial order of item registration. This is used for - // maintaining menu item order later. - setMenuItemOrder( ( items ) => { - if ( items.includes( item.label ) ) { - return items; - } + const [ { panelItems, menuItems }, panelDispatch ] = useReducer( + panelReducer, + undefined, + emptyState + ); - return [ ...items, item.label ]; - } ); - }, - [ setPanelItems, setMenuItemOrder ] + const [ resetAllFilters, dispatchResetAllFilters ] = useReducer( + resetAllFiltersReducer, + [] ); + const registerPanelItem = useCallback( ( item: ToolsPanelItem ) => { + // Add item to panel items. + panelDispatch( { type: 'REGISTER_PANEL', item } ); + }, [] ); + // Panels need to deregister on unmount to avoid orphans in menu state. // This is an issue when panel items are being injected via SlotFills. - const deregisterPanelItem = useCallback( - ( label: string ) => { - // When switching selections between components injecting matching - // controls, e.g. both panels have a "padding" control, the - // deregistration of the first panel doesn't occur until after the - // registration of the next. - setPanelItems( ( items ) => { - const newItems = [ ...items ]; - const index = newItems.findIndex( - ( item ) => item.label === label - ); - if ( index !== -1 ) { - newItems.splice( index, 1 ); - } - return newItems; - } ); - }, - [ setPanelItems ] - ); - - const registerResetAllFilter = useCallback( - ( newFilter: ResetAllFilter ) => { - setResetAllFilters( ( filters ) => { - return [ ...filters, newFilter ]; - } ); - }, - [ setResetAllFilters ] - ); + const deregisterPanelItem = useCallback( ( label: string ) => { + // When switching selections between components injecting matching + // controls, e.g. both panels have a "padding" control, the + // deregistration of the first panel doesn't occur until after the + // registration of the next. + panelDispatch( { type: 'UNREGISTER_PANEL', label } ); + }, [] ); + + const registerResetAllFilter = useCallback( ( filter: ResetAllFilter ) => { + dispatchResetAllFilters( { type: 'REGISTER', filter } ); + }, [] ); const deregisterResetAllFilter = useCallback( - ( filterToRemove: ResetAllFilter ) => { - setResetAllFilters( ( filters ) => { - return filters.filter( - ( filter ) => filter !== filterToRemove - ); - } ); + ( filter: ResetAllFilter ) => { + dispatchResetAllFilters( { type: 'UNREGISTER', filter } ); }, - [ setResetAllFilters ] + [] ); - // Manage and share display state of menu items representing child controls. - const [ menuItems, setMenuItems ] = useState< ToolsPanelMenuItems >( { - default: {}, - optional: {}, - } ); - - // Setup menuItems state as panel items register themselves. - useEffect( () => { - setMenuItems( ( prevState ) => { - const items = generateMenuItems( { - panelItems, - shouldReset: false, - currentMenuItems: prevState, - menuItemOrder, - } ); - return items; - } ); - }, [ panelItems, setMenuItems, menuItemOrder ] ); - // Updates the status of the panel’s menu items. For default items the // value represents whether it differs from the default and for optional // items whether the item is shown. @@ -214,38 +320,24 @@ export function useToolsPanel( label: string, group: ToolsPanelMenuItemKey = 'default' ) => { - setMenuItems( ( items ) => { - const newState = { - ...items, - [ group ]: { - ...items[ group ], - [ label ]: value, - }, - }; - return newState; - } ); + panelDispatch( { type: 'UPDATE_VALUE', group, label, value } ); }, - [ setMenuItems ] + [] ); // Whether all optional menu items are hidden or not must be tracked // in order to later determine if the panel display is empty and handle // conditional display of a plus icon to indicate the presence of further // menu items. - const [ areAllOptionalControlsHidden, setAreAllOptionalControlsHidden ] = - useState( false ); - - useEffect( () => { - if ( - isMenuItemTypeEmpty( menuItems?.default ) && - ! isMenuItemTypeEmpty( menuItems?.optional ) - ) { - const allControlsHidden = ! Object.entries( - menuItems.optional - ).some( ( [ , isSelected ] ) => isSelected ); - setAreAllOptionalControlsHidden( allControlsHidden ); - } - }, [ menuItems, setAreAllOptionalControlsHidden ] ); + const areAllOptionalControlsHidden = useMemo( () => { + return ( + isMenuItemTypeEmpty( menuItems.default ) && + ! isMenuItemTypeEmpty( menuItems.optional ) && + Object.values( menuItems.optional ).every( + ( isSelected ) => ! isSelected + ) + ); + }, [ menuItems ] ); const cx = useCx(); const classes = useMemo( () => { @@ -253,9 +345,7 @@ export function useToolsPanel( hasInnerWrapper && styles.ToolsPanelWithInnerWrapper( DEFAULT_COLUMNS ); const emptyStyle = - isMenuItemTypeEmpty( menuItems?.default ) && - areAllOptionalControlsHidden && - styles.ToolsPanelHiddenInnerWrapper; + areAllOptionalControlsHidden && styles.ToolsPanelHiddenInnerWrapper; return cx( styles.ToolsPanel( DEFAULT_COLUMNS ), @@ -263,42 +353,13 @@ export function useToolsPanel( emptyStyle, className ); - }, [ - areAllOptionalControlsHidden, - className, - cx, - hasInnerWrapper, - menuItems, - ] ); + }, [ areAllOptionalControlsHidden, className, cx, hasInnerWrapper ] ); // Toggle the checked state of a menu item which is then used to determine // display of the item within the panel. - const toggleItem = useCallback( - ( label: string ) => { - const currentItem = panelItems.find( - ( item ) => item.label === label - ); - - if ( ! currentItem ) { - return; - } - - const menuGroup = currentItem.isShownByDefault - ? 'default' - : 'optional'; - - const newMenuItems = { - ...menuItems, - [ menuGroup ]: { - ...menuItems[ menuGroup ], - [ label ]: ! menuItems[ menuGroup ][ label ], - }, - }; - - setMenuItems( newMenuItems ); - }, - [ menuItems, panelItems, setMenuItems ] - ); + const toggleItem = useCallback( ( label: string ) => { + panelDispatch( { type: 'TOGGLE_VALUE', label } ); + }, [] ); // Resets display of children and executes resetAll callback if available. const resetAllItems = useCallback( () => { @@ -308,20 +369,15 @@ export function useToolsPanel( } // Turn off display of all non-default items. - const resetMenuItems = generateMenuItems( { - panelItems, - menuItemOrder, - shouldReset: true, - } ); - setMenuItems( resetMenuItems ); - }, [ panelItems, resetAllFilters, resetAll, setMenuItems, menuItemOrder ] ); + panelDispatch( { type: 'RESET_ALL' } ); + }, [ resetAllFilters, resetAll ] ); // Assist ItemGroup styling when there are potentially hidden placeholder // items by identifying first & last items that are toggled on for display. const getFirstVisibleItemLabel = ( items: ToolsPanelItem[] ) => { const optionalItems = menuItems.optional || {}; const firstItem = items.find( - ( item ) => item.isShownByDefault || !! optionalItems[ item.label ] + ( item ) => item.isShownByDefault || optionalItems[ item.label ] ); return firstItem?.label; @@ -332,6 +388,8 @@ export function useToolsPanel( [ ...panelItems ].reverse() ); + const hasMenuItems = panelItems.length > 0; + const panelContext = useMemo( () => ( { areAllOptionalControlsHidden, @@ -339,7 +397,7 @@ export function useToolsPanel( deregisterResetAllFilter, firstDisplayedItem, flagItemCustomization, - hasMenuItems: !! panelItems.length, + hasMenuItems, isResetting: isResettingRef.current, lastDisplayedItem, menuItems, @@ -359,7 +417,7 @@ export function useToolsPanel( lastDisplayedItem, menuItems, panelId, - panelItems, + hasMenuItems, registerResetAllFilter, registerPanelItem, shouldRenderPlaceholderItems, From 0844af0547d6853ea9184b85f3908f8a7e9802a0 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Tue, 24 Sep 2024 10:55:47 +0200 Subject: [PATCH 0921/1908] Connected blocks, add backdrop-color. (#65233) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> --- .../block-editor/src/components/block-toolbar/style.scss | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index 2a0f68a6976686..ae03eeed1a817c 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -37,6 +37,13 @@ border-right: $border-width solid $gray-300; } + &.is-connected { + .block-editor-block-switcher .components-button::before { + background: color-mix(in srgb, var(--wp-block-synced-color) 10%, transparent); + border-radius: $radius-small; + } + } + &.is-synced, &.is-connected { .block-editor-block-switcher .components-button .block-editor-block-icon { From 2a80118931756c72b5cb5d1b728117ddb6749ffc Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Tue, 24 Sep 2024 11:06:11 +0200 Subject: [PATCH 0922/1908] Block Bindings: Fix passing bindings context to `canUserEditValue` (#65599) * Pass updated context as `context` prop * Use `updatedContext` in pattern overrides Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- .../src/hooks/use-bindings-attributes.js | 53 +++++++++---------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index ac045004cc654b..9f9234ad47d103 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -103,11 +103,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( const sources = useSelect( ( select ) => unlock( select( blocksStore ) ).getAllBlockBindingsSources() ); - const { name, clientId } = props; - const hasParentPattern = !! props.context[ 'pattern/overrides' ]; - const hasPatternOverridesDefaultBinding = - props.attributes.metadata?.bindings?.[ DEFAULT_ATTRIBUTE ] - ?.source === 'core/pattern-overrides'; + const { name, clientId, context, setAttributes } = props; const blockBindings = useMemo( () => replacePatternOverrideDefaultBindings( @@ -121,6 +117,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( // used purposely here to ensure `boundAttributes` is updated whenever // there are attribute updates. // `source.getValues` may also call a selector via `registry.select`. + const updatedContext = { ...context }; const boundAttributes = useSelect( () => { if ( ! blockBindings ) { return; @@ -139,6 +136,11 @@ export const withBlockBindingSupport = createHigherOrderComponent( continue; } + // Populate context. + for ( const key of source.usesContext || [] ) { + updatedContext[ key ] = blockContext[ key ]; + } + blockBindingsBySource.set( source, { ...blockBindingsBySource.get( source ), [ attributeName ]: { @@ -149,15 +151,6 @@ export const withBlockBindingSupport = createHigherOrderComponent( if ( blockBindingsBySource.size ) { for ( const [ source, bindings ] of blockBindingsBySource ) { - // Populate context. - const context = {}; - - if ( source.usesContext?.length ) { - for ( const key of source.usesContext ) { - context[ key ] = blockContext[ key ]; - } - } - // Get values in batch if the source supports it. let values = {}; if ( ! source.getValues ) { @@ -168,7 +161,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( } else { values = source.getValues( { registry, - context, + context: updatedContext, clientId, bindings, } ); @@ -190,9 +183,19 @@ export const withBlockBindingSupport = createHigherOrderComponent( } return attributes; - }, [ blockBindings, name, clientId, blockContext, registry, sources ] ); - - const { setAttributes } = props; + }, [ + blockBindings, + name, + clientId, + updatedContext, + registry, + sources, + ] ); + + const hasParentPattern = !! updatedContext[ 'pattern/overrides' ]; + const hasPatternOverridesDefaultBinding = + props.attributes.metadata?.bindings?.[ DEFAULT_ATTRIBUTE ] + ?.source === 'core/pattern-overrides'; const _setAttributes = useCallback( ( nextAttributes ) => { @@ -236,18 +239,9 @@ export const withBlockBindingSupport = createHigherOrderComponent( source, bindings, ] of blockBindingsBySource ) { - // Populate context. - const context = {}; - - if ( source.usesContext?.length ) { - for ( const key of source.usesContext ) { - context[ key ] = blockContext[ key ]; - } - } - source.setValues( { registry, - context, + context: updatedContext, clientId, bindings, } ); @@ -277,7 +271,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( blockBindings, name, clientId, - blockContext, + updatedContext, setAttributes, sources, hasPatternOverridesDefaultBinding, @@ -291,6 +285,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( { ...props } attributes={ { ...props.attributes, ...boundAttributes } } setAttributes={ _setAttributes } + context={ updatedContext } /> </> ); From efd622d95ebd6721c844949d57c559de67b17101 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 24 Sep 2024 11:43:32 +0200 Subject: [PATCH 0923/1908] Navigator: fix isInitial logic (#65527) * Navigator: fix isInitial logic * CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/navigator/navigator-provider/component.tsx | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 001b2d0b4230e9..34522f79572652 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Bug Fixes - `ToolsPanel`: atomic one-step state update when (un)registering panels ([#65564](https://github.com/WordPress/gutenberg/pull/65564)). +- `Navigator`: fix `isInitial` logic ([#65527](https://github.com/WordPress/gutenberg/pull/65527)). ## 28.8.0 (2024-09-19) diff --git a/packages/components/src/navigator/navigator-provider/component.tsx b/packages/components/src/navigator/navigator-provider/component.tsx index ebcb247c574830..01254b743f87d0 100644 --- a/packages/components/src/navigator/navigator-provider/component.tsx +++ b/packages/components/src/navigator/navigator-provider/component.tsx @@ -66,7 +66,7 @@ function goTo( options: NavigateOptions = {} ) { const { focusSelectors } = state; - const currentLocation = { ...state.currentLocation, isInitial: false }; + const currentLocation = { ...state.currentLocation }; const { // Default assignments @@ -114,6 +114,7 @@ function goTo( return { currentLocation: { ...restOptions, + isInitial: false, path, isBack, hasRestoredFocus: false, @@ -129,7 +130,7 @@ function goToParent( options: NavigateToParentOptions = {} ) { const { screens, focusSelectors } = state; - const currentLocation = { ...state.currentLocation, isInitial: false }; + const currentLocation = { ...state.currentLocation }; const currentPath = currentLocation.path; if ( currentPath === undefined ) { return { currentLocation, focusSelectors }; From 8357fceaf5acf26777770741975a1f5ad67619b3 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 24 Sep 2024 19:26:48 +0900 Subject: [PATCH 0924/1908] Site Editor: Make resizable frame compatible with RTL languages (#65545) * Site Editor: Make resizable frame compatible with RTL languages * Update packages/edit-site/src/components/resizable-frame/index.js Co-authored-by: Mitchell Austin <mr.fye@oneandthesame.net> * Fix dragging behaviour --------- Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> --- .../src/components/resizable-frame/index.js | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/edit-site/src/components/resizable-frame/index.js b/packages/edit-site/src/components/resizable-frame/index.js index b589a3861c75d3..b5aae01918e691 100644 --- a/packages/edit-site/src/components/resizable-frame/index.js +++ b/packages/edit-site/src/components/resizable-frame/index.js @@ -14,7 +14,7 @@ import { } from '@wordpress/components'; import { useInstanceId, useReducedMotion } from '@wordpress/compose'; import { useDispatch, useSelect } from '@wordpress/data'; -import { __ } from '@wordpress/i18n'; +import { __, isRTL } from '@wordpress/i18n'; /** * Internal dependencies @@ -171,7 +171,10 @@ function ResizableFrame( { event.preventDefault(); const step = 20 * ( event.shiftKey ? 5 : 1 ); - const delta = step * ( event.key === 'ArrowLeft' ? 1 : -1 ); + const delta = + step * + ( event.key === 'ArrowLeft' ? 1 : -1 ) * + ( isRTL() ? -1 : 1 ); const newWidth = Math.min( Math.max( FRAME_MIN_WIDTH, @@ -200,15 +203,17 @@ function ResizableFrame( { const resizeHandleVariants = { hidden: { opacity: 0, - left: 0, + ...( isRTL() ? { right: 0 } : { left: 0 } ), }, visible: { opacity: 1, - left: -14, // Account for the handle's width. + // Account for the handle's width. + ...( isRTL() ? { right: -14 } : { left: -14 } ), }, active: { opacity: 1, - left: -14, // Account for the handle's width. + // Account for the handle's width. + ...( isRTL() ? { right: -14 } : { left: -14 } ), scaleY: 1.3, }, }; @@ -246,10 +251,11 @@ function ResizableFrame( { size={ frameSize } enable={ { top: false, - right: false, bottom: false, // Resizing will be disabled until the editor content is loaded. - left: isReady, + ...( isRTL() + ? { right: isReady, left: false } + : { left: isReady, right: false } ), topRight: false, bottomRight: false, bottomLeft: false, @@ -269,7 +275,7 @@ function ResizableFrame( { onMouseOver={ () => setShouldShowHandle( true ) } onMouseOut={ () => setShouldShowHandle( false ) } handleComponent={ { - left: canvasMode === 'view' && ( + [ isRTL() ? 'right' : 'left' ]: canvasMode === 'view' && ( <> <Tooltip text={ __( 'Drag to resize' ) }> { /* Disable reason: role="separator" does in fact support aria-valuenow */ } From 82dff1321f83329e1ba00b945a67d97edc291870 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 24 Sep 2024 19:27:28 +0900 Subject: [PATCH 0925/1908] Don't show tooltip in zoom out toggle button when showIconLabels is true (#65573) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> --- packages/editor/src/components/zoom-out-toggle/index.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/zoom-out-toggle/index.js b/packages/editor/src/components/zoom-out-toggle/index.js index 214b1c51fd6255..dd4669d04bec18 100644 --- a/packages/editor/src/components/zoom-out-toggle/index.js +++ b/packages/editor/src/components/zoom-out-toggle/index.js @@ -7,6 +7,7 @@ import { __ } from '@wordpress/i18n'; import { useDispatch, useSelect } from '@wordpress/data'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { square as zoomOutIcon } from '@wordpress/icons'; +import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies @@ -14,8 +15,12 @@ import { square as zoomOutIcon } from '@wordpress/icons'; import { unlock } from '../../lock-unlock'; const ZoomOutToggle = () => { - const { isZoomOut } = useSelect( ( select ) => ( { + const { isZoomOut, showIconLabels } = useSelect( ( select ) => ( { isZoomOut: unlock( select( blockEditorStore ) ).isZoomOut(), + showIconLabels: select( preferencesStore ).get( + 'core', + 'showIconLabels' + ), } ) ); const { resetZoomLevel, setZoomLevel, __unstableSetEditorMode } = unlock( @@ -38,6 +43,7 @@ const ZoomOutToggle = () => { label={ __( 'Toggle Zoom Out' ) } isPressed={ isZoomOut } size="compact" + showTooltip={ ! showIconLabels } /> ); }; From 228ab3aa8ce5ae1578ddd6980ecceab63ce2ae3f Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 24 Sep 2024 19:28:36 +0900 Subject: [PATCH 0926/1908] Resizable Editor: Make the editor resizable with arrow keys (#65546) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- .../editor/src/components/resizable-editor/resize-handle.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/editor/src/components/resizable-editor/resize-handle.js b/packages/editor/src/components/resizable-editor/resize-handle.js index dbba31f6f998ba..ccd903d0f3a172 100644 --- a/packages/editor/src/components/resizable-editor/resize-handle.js +++ b/packages/editor/src/components/resizable-editor/resize-handle.js @@ -15,6 +15,11 @@ export default function ResizeHandle( { direction, resizeWidthBy } ) { function handleKeyDown( event ) { const { keyCode } = event; + if ( keyCode !== LEFT && keyCode !== RIGHT ) { + return; + } + event.preventDefault(); + if ( ( direction === 'left' && keyCode === LEFT ) || ( direction === 'right' && keyCode === RIGHT ) From 8a658c85107e5811c55506bbe85b9480992bfd27 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 24 Sep 2024 12:24:18 +0100 Subject: [PATCH 0927/1908] Components: Simplify MenuGroup component styles (#65561) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ .../src/dropdown-menu/stories/index.story.tsx | 3 +++ .../src/dropdown/stories/index.story.tsx | 1 + packages/components/src/dropdown/style.scss | 23 ++++++++----------- packages/components/src/menu-group/style.scss | 5 +++- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 34522f79572652..71aa08d6934034 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -7,6 +7,10 @@ - `ToolsPanel`: atomic one-step state update when (un)registering panels ([#65564](https://github.com/WordPress/gutenberg/pull/65564)). - `Navigator`: fix `isInitial` logic ([#65527](https://github.com/WordPress/gutenberg/pull/65527)). +### Enhancements + +- `MenuGroup`: Simplify the MenuGroup styles within dropdown menus. ([#65561](https://github.com/WordPress/gutenberg/pull/65561)). + ## 28.8.0 (2024-09-19) ### Bug Fixes diff --git a/packages/components/src/dropdown-menu/stories/index.story.tsx b/packages/components/src/dropdown-menu/stories/index.story.tsx index b6bc11ddec9abf..dd4907bd0b96b1 100644 --- a/packages/components/src/dropdown-menu/stories/index.story.tsx +++ b/packages/components/src/dropdown-menu/stories/index.story.tsx @@ -96,6 +96,9 @@ export const WithChildren: StoryObj< typeof DropdownMenu > = { icon: more, children: ( { onClose } ) => ( <> + <MenuItem icon={ arrowUp } onClick={ onClose }> + Standalone Item + </MenuItem> <MenuGroup> <MenuItem icon={ arrowUp } onClick={ onClose }> Move Up diff --git a/packages/components/src/dropdown/stories/index.story.tsx b/packages/components/src/dropdown/stories/index.story.tsx index c6fe5014ffdc2a..0f07664787cc33 100644 --- a/packages/components/src/dropdown/stories/index.story.tsx +++ b/packages/components/src/dropdown/stories/index.story.tsx @@ -99,6 +99,7 @@ export const WithMenuItems: StoryObj< typeof Dropdown > = { ...Default.args, renderContent: () => ( <> + <MenuItem>Standalone Item</MenuItem> <MenuGroup label="Group 1"> <MenuItem>Item 1</MenuItem> <MenuItem>Item 2</MenuItem> diff --git a/packages/components/src/dropdown/style.scss b/packages/components/src/dropdown/style.scss index 8a5b0e0a0a6a28..d7ae7963f7ed8c 100644 --- a/packages/components/src/dropdown/style.scss +++ b/packages/components/src/dropdown/style.scss @@ -5,6 +5,16 @@ .components-dropdown__content { .components-popover__content { padding: $grid-unit-10; + + &:has(.components-menu-group) { + padding: 0; + + .components-dropdown-menu__menu > .components-menu-item__button, + > .components-menu-item__button { + margin: $grid-unit-10; + width: auto; + } + } } [role="menuitem"] { @@ -13,22 +23,9 @@ .components-menu-group { padding: $grid-unit-10; - margin-top: 0; - margin-bottom: 0; - margin-left: -$grid-unit-10; - margin-right: -$grid-unit-10; - - &:first-child { - margin-top: -$grid-unit-10; - } - - &:last-child { - margin-bottom: -$grid-unit-10; - } } .components-menu-group + .components-menu-group { - margin-top: 0; border-top: $border-width solid $gray-400; padding: $grid-unit-10; } diff --git a/packages/components/src/menu-group/style.scss b/packages/components/src/menu-group/style.scss index d9412c504940b3..744e3f74c5b955 100644 --- a/packages/components/src/menu-group/style.scss +++ b/packages/components/src/menu-group/style.scss @@ -1,5 +1,4 @@ .components-menu-group + .components-menu-group { - margin-top: $grid-unit-10; padding-top: $grid-unit-10; border-top: $border-width solid $gray-900; @@ -10,6 +9,10 @@ } } +.components-menu-group:has(> div:empty) { + display: none; +} + .components-menu-group__label { padding: 0 $grid-unit-10; margin-top: $grid-unit-05; From cf78cf014d766b32cbb7326f948cc7381c411289 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 24 Sep 2024 12:26:47 +0100 Subject: [PATCH 0928/1908] Inserter: Update how we compute the actual insertion point for blocks (#65490) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../components/inserter/block-types-tab.js | 2 +- .../inserter/hooks/use-block-types-state.js | 48 +++++++++---- .../inserter/hooks/use-insertion-point.js | 35 +++++++--- .../inserter/hooks/use-patterns-state.js | 2 +- .../inserter/media-tab/media-preview.js | 8 ++- .../inserter/test/block-types-tab.native.js | 67 ------------------ .../src/store/private-selectors.js | 38 ++++++++++ packages/block-editor/src/store/selectors.js | 70 +++++-------------- packages/block-editor/src/store/utils.js | 3 +- 9 files changed, 122 insertions(+), 151 deletions(-) delete mode 100644 packages/block-editor/src/components/inserter/test/block-types-tab.native.js diff --git a/packages/block-editor/src/components/inserter/block-types-tab.js b/packages/block-editor/src/components/inserter/block-types-tab.js index 50a8b46b46427c..844d5dd341437e 100644 --- a/packages/block-editor/src/components/inserter/block-types-tab.js +++ b/packages/block-editor/src/components/inserter/block-types-tab.js @@ -186,7 +186,7 @@ export function BlockTypesTab( continue; } - if ( rootClientId && item.rootClientId === rootClientId ) { + if ( rootClientId && item.isAllowedInCurrentRoot ) { itemsForCurrentRoot.push( item ); } else { itemsRemaining.push( item ); diff --git a/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js b/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js index 8db23267eee8f4..6f11060c75c494 100644 --- a/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js +++ b/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js @@ -2,19 +2,23 @@ * WordPress dependencies */ import { + getBlockType, createBlock, createBlocksFromInnerBlocksTemplate, store as blocksStore, parse, } from '@wordpress/blocks'; -import { useSelect } from '@wordpress/data'; +import { useSelect, useDispatch } from '@wordpress/data'; import { useCallback, useMemo } from '@wordpress/element'; +import { store as noticesStore } from '@wordpress/notices'; +import { __, sprintf } from '@wordpress/i18n'; /** * Internal dependencies */ import { store as blockEditorStore } from '../../../store'; -import { withRootClientIdOptionKey } from '../../../store/utils'; +import { isFiltered } from '../../../store/utils'; +import { unlock } from '../../../lock-unlock'; /** * Retrieves the block types inserter state. @@ -26,7 +30,7 @@ import { withRootClientIdOptionKey } from '../../../store/utils'; */ const useBlockTypesState = ( rootClientId, onInsert, isQuick ) => { const options = useMemo( - () => ( { [ withRootClientIdOptionKey ]: ! isQuick } ), + () => ( { [ isFiltered ]: !! isQuick } ), [ isQuick ] ); const [ items ] = useSelect( @@ -38,6 +42,10 @@ const useBlockTypesState = ( rootClientId, onInsert, isQuick ) => { ], [ rootClientId, options ] ); + const { getClosestAllowedInsertionPoint } = unlock( + useSelect( blockEditorStore ) + ); + const { createErrorNotice } = useDispatch( noticesStore ); const [ categories, collections ] = useSelect( ( select ) => { const { getCategories, getCollections } = select( blocksStore ); @@ -46,16 +54,29 @@ const useBlockTypesState = ( rootClientId, onInsert, isQuick ) => { const onSelectItem = useCallback( ( - { - name, - initialAttributes, - innerBlocks, - syncStatus, - content, - rootClientId: _rootClientId, - }, + { name, initialAttributes, innerBlocks, syncStatus, content }, shouldFocusBlock ) => { + const destinationClientId = getClosestAllowedInsertionPoint( + name, + rootClientId + ); + if ( destinationClientId === null ) { + const title = getBlockType( name )?.title ?? name; + createErrorNotice( + sprintf( + /* translators: %s: block pattern title. */ + __( 'Block "%s" can\'t be inserted.' ), + title + ), + { + type: 'snackbar', + id: 'inserter-notice', + } + ); + return; + } + const insertedBlock = syncStatus === 'unsynced' ? parse( content, { @@ -66,15 +87,14 @@ const useBlockTypesState = ( rootClientId, onInsert, isQuick ) => { initialAttributes, createBlocksFromInnerBlocksTemplate( innerBlocks ) ); - onInsert( insertedBlock, undefined, shouldFocusBlock, - _rootClientId + destinationClientId ); }, - [ onInsert ] + [ onInsert, getClosestAllowedInsertionPoint, rootClientId ] ); return [ items, categories, collections, onSelectItem ]; diff --git a/packages/block-editor/src/components/inserter/hooks/use-insertion-point.js b/packages/block-editor/src/components/inserter/hooks/use-insertion-point.js index 24074ec5004565..0cd71bf77b9830 100644 --- a/packages/block-editor/src/components/inserter/hooks/use-insertion-point.js +++ b/packages/block-editor/src/components/inserter/hooks/use-insertion-point.js @@ -71,7 +71,11 @@ function useInsertionPoint( { selectBlockOnInsert = true, } ) { const registry = useRegistry(); - const { getSelectedBlock } = useSelect( blockEditorStore ); + const { + getSelectedBlock, + getClosestAllowedInsertionPoint, + isBlockInsertionPointVisible, + } = unlock( useSelect( blockEditorStore ) ); const { destinationRootClientId, destinationIndex } = useSelect( ( select ) => { const { @@ -193,21 +197,30 @@ function useInsertionPoint( { const onToggleInsertionPoint = useCallback( ( item ) => { - if ( item?.hasOwnProperty( 'rootClientId' ) ) { - showInsertionPoint( - item.rootClientId, - getIndex( { - destinationRootClientId, - destinationIndex, - rootClientId: item.rootClientId, - registry, - } ) - ); + if ( item && ! isBlockInsertionPointVisible() ) { + const allowedDestinationRootClientId = + getClosestAllowedInsertionPoint( + item.name, + destinationRootClientId + ); + if ( allowedDestinationRootClientId !== null ) { + showInsertionPoint( + allowedDestinationRootClientId, + getIndex( { + destinationRootClientId, + destinationIndex, + rootClientId: allowedDestinationRootClientId, + registry, + } ) + ); + } } else { hideInsertionPoint(); } }, [ + getClosestAllowedInsertionPoint, + isBlockInsertionPointVisible, showInsertionPoint, hideInsertionPoint, destinationRootClientId, diff --git a/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js b/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js index 6483dc58ae8b97..f8b083d4eedf19 100644 --- a/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js +++ b/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js @@ -87,7 +87,7 @@ const usePatternsState = ( onInsert, rootClientId, selectedCategory ) => { ), { type: 'snackbar', - id: 'block-pattern-inserted-notice', + id: 'inserter-notice', } ); }, diff --git a/packages/block-editor/src/components/inserter/media-tab/media-preview.js b/packages/block-editor/src/components/inserter/media-tab/media-preview.js index 64088f45fa1c39..a890e5fe8dc132 100644 --- a/packages/block-editor/src/components/inserter/media-tab/media-preview.js +++ b/packages/block-editor/src/components/inserter/media-tab/media-preview.js @@ -184,13 +184,16 @@ export function MediaPreview( { media, onClick, category } ) { } ); createSuccessNotice( __( 'Image uploaded and inserted.' ), - { type: 'snackbar' } + { type: 'snackbar', id: 'inserter-notice' } ); setIsInserting( false ); }, allowedTypes: ALLOWED_MEDIA_TYPES, onError( message ) { - createErrorNotice( message, { type: 'snackbar' } ); + createErrorNotice( message, { + type: 'snackbar', + id: 'inserter-notice', + } ); setIsInserting( false ); }, } ); @@ -281,6 +284,7 @@ export function MediaPreview( { media, onClick, category } ) { onClick( cloneBlock( block ) ); createSuccessNotice( __( 'Image inserted.' ), { type: 'snackbar', + id: 'inserter-notice', } ); setShowExternalUploadModal( false ); } } diff --git a/packages/block-editor/src/components/inserter/test/block-types-tab.native.js b/packages/block-editor/src/components/inserter/test/block-types-tab.native.js deleted file mode 100644 index 925570130359a6..00000000000000 --- a/packages/block-editor/src/components/inserter/test/block-types-tab.native.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * External dependencies - */ -import { render } from 'test/helpers'; - -/** - * WordPress dependencies - */ -import { useSelect } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import items from './fixtures'; -import BlockTypesTab from '../block-types-tab'; - -jest.mock( '../hooks/use-clipboard-block' ); -jest.mock( '@wordpress/data/src/components/use-select' ); - -const selectMock = { - getCategories: jest.fn().mockReturnValue( [] ), - getCollections: jest.fn().mockReturnValue( [] ), - getInserterItems: jest.fn().mockReturnValue( [] ), - canInsertBlockType: jest.fn(), - getBlockType: jest.fn(), - getClipboard: jest.fn(), - getSettings: jest.fn( () => ( { impressions: {} } ) ), -}; - -describe( 'BlockTypesTab component', () => { - beforeEach( () => { - useSelect.mockImplementation( ( callback ) => - callback( () => selectMock ) - ); - } ); - - it( 'renders without crashing', () => { - const component = render( - <BlockTypesTab - rootClientId={ 0 } - onSelect={ jest.fn() } - listProps={ { contentContainerStyle: {} } } - /> - ); - expect( component ).toBeTruthy(); - } ); - - it( 'shows block items', () => { - selectMock.getInserterItems.mockReturnValue( items ); - - const blockItems = items.filter( - ( { id, category } ) => - category !== 'reusable' && id !== 'core-embed/a-paragraph-embed' - ); - const component = render( - <BlockTypesTab - rootClientId={ 0 } - onSelect={ jest.fn() } - listProps={ { contentContainerStyle: {} } } - /> - ); - - blockItems.forEach( ( item ) => { - expect( component.getByText( item.title ) ).toBeTruthy(); - } ); - } ); -} ); diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 9e99176819ae89..02a37b94ec27ff 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -16,6 +16,7 @@ import { getTemplateLock, getClientIdsWithDescendants, isNavigationMode, + getBlockRootClientId, } from './selectors'; import { checkAllowListRecursive, @@ -637,3 +638,40 @@ export function getZoomLevel( state ) { export function isZoomOut( state ) { return getZoomLevel( state ) < 100; } + +/** + * Finds the closest block where the block is allowed to be inserted. + * + * @param {Object} state Editor state. + * @param {string} name Block name. + * @param {string} clientId Default insertion point. + * + * @return {string} clientID of the closest container when the block name can be inserted. + */ +export function getClosestAllowedInsertionPoint( state, name, clientId = '' ) { + // If we're trying to insert at the root level and it's not allowed + // Try the section root instead. + if ( ! clientId ) { + if ( canInsertBlockType( state, name, clientId ) ) { + return clientId; + } + + const sectionRootClientId = getSectionRootClientId( state ); + if ( + sectionRootClientId && + canInsertBlockType( state, name, sectionRootClientId ) + ) { + return sectionRootClientId; + } + return null; + } + + // Traverse the block tree up until we find a place where we can insert. + let current = clientId; + while ( current !== null && ! canInsertBlockType( state, name, current ) ) { + const parentClientId = getBlockRootClientId( state, current ); + current = parentClientId; + } + + return current; +} diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 20d6627398886c..3163bb5257a9ad 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -21,7 +21,7 @@ import { createSelector, createRegistrySelector } from '@wordpress/data'; * Internal dependencies */ import { - withRootClientIdOptionKey, + isFiltered, checkAllowListRecursive, checkAllowList, getAllPatternsDependants, @@ -80,7 +80,9 @@ const EMPTY_ARRAY = []; */ const EMPTY_SET = new Set(); -const EMPTY_OBJECT = {}; +const DEFAULT_INSERTER_OPTIONS = { + [ isFiltered ]: true, +}; /** * Returns a block's name given its client ID, or null if no block exists with @@ -2008,7 +2010,7 @@ const buildBlockTypeItem = */ export const getInserterItems = createRegistrySelector( ( select ) => createSelector( - ( state, rootClientId = null, options = EMPTY_OBJECT ) => { + ( state, rootClientId = null, options = DEFAULT_INSERTER_OPTIONS ) => { const buildReusableBlockInserterItem = ( reusableBlock ) => { const icon = ! reusableBlock.wp_pattern_sync_status ? { @@ -2056,56 +2058,7 @@ export const getInserterItems = createRegistrySelector( ( select ) => ) .map( buildBlockTypeInserterItem ); - if ( options[ withRootClientIdOptionKey ] ) { - blockTypeInserterItems = blockTypeInserterItems.reduce( - ( accumulator, item ) => { - item.rootClientId = rootClientId ?? ''; - - while ( - ! canInsertBlockTypeUnmemoized( - state, - item.name, - item.rootClientId - ) - ) { - if ( ! item.rootClientId ) { - let sectionRootClientId; - try { - sectionRootClientId = - getSectionRootClientId( state ); - } catch ( e ) {} - if ( - sectionRootClientId && - canInsertBlockTypeUnmemoized( - state, - item.name, - sectionRootClientId - ) - ) { - item.rootClientId = sectionRootClientId; - } else { - delete item.rootClientId; - } - break; - } else { - const parentClientId = getBlockRootClientId( - state, - item.rootClientId - ); - item.rootClientId = parentClientId; - } - } - - // We could also add non insertable items and gray them out. - if ( item.hasOwnProperty( 'rootClientId' ) ) { - accumulator.push( item ); - } - - return accumulator; - }, - [] - ); - } else { + if ( options[ isFiltered ] !== false ) { blockTypeInserterItems = blockTypeInserterItems.filter( ( blockType ) => canIncludeBlockTypeInInserter( @@ -2114,6 +2067,17 @@ export const getInserterItems = createRegistrySelector( ( select ) => rootClientId ) ); + } else { + blockTypeInserterItems = blockTypeInserterItems.map( + ( blockType ) => ( { + ...blockType, + isAllowedInCurrentRoot: canIncludeBlockTypeInInserter( + state, + blockType, + rootClientId + ), + } ) + ); } const items = blockTypeInserterItems.reduce( diff --git a/packages/block-editor/src/store/utils.js b/packages/block-editor/src/store/utils.js index 79e15255e6cc15..9b83a8f74cf9aa 100644 --- a/packages/block-editor/src/store/utils.js +++ b/packages/block-editor/src/store/utils.js @@ -12,8 +12,7 @@ import { unlock } from '../lock-unlock'; import { STORE_NAME } from './constants'; import { getSectionRootClientId } from './private-selectors'; -export const withRootClientIdOptionKey = Symbol( 'withRootClientId' ); - +export const isFiltered = Symbol( 'isFiltered' ); const parsedPatternCache = new WeakMap(); const grammarMapCache = new WeakMap(); From df5eaed851c7effe459aa2a5f6cdf41cd3648104 Mon Sep 17 00:00:00 2001 From: Vipul Gupta <55375170+vipul0425@users.noreply.github.com> Date: Tue, 24 Sep 2024 17:15:19 +0530 Subject: [PATCH 0929/1908] Fix: Button Replace remaining 40px default size violations [Block Editor 3] (#65225) * Fix: Global Styles component to use 40px default size. * Fix: Block variation picket to use 40px default size. * Fix: Block variation transform to use 40px default size. * Fix: color gradient dropdown and block appender button to use 40px default size. * fix: shadowpanel clear button * fix: Button Block appender issues. * fix: Coverts shadow panel Buttons to normal html buttons. * Update packages/block-library/src/group/editor.scss Co-authored-by: Lena Morita <lena@jaguchi.com> * Update packages/block-library/src/group/editor.scss Co-authored-by: Lena Morita <lena@jaguchi.com> * feat: Add tootlip tu shadow button. --------- Co-authored-by: vipul0425 <vipulgupta003@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../block-variation-picker/index.js | 3 +- .../block-variation-transforms/index.js | 4 +- .../button-block-appender/content.scss | 5 -- .../components/button-block-appender/index.js | 3 +- .../components/colors-gradients/dropdown.js | 6 +- .../components/global-styles/color-panel.js | 6 +- .../components/global-styles/filters-panel.js | 3 +- .../global-styles/shadow-panel-components.js | 61 +++++++++---------- .../src/components/global-styles/style.scss | 5 ++ packages/block-library/src/group/editor.scss | 4 +- 10 files changed, 42 insertions(+), 58 deletions(-) diff --git a/packages/block-editor/src/components/block-variation-picker/index.js b/packages/block-editor/src/components/block-variation-picker/index.js index ecdf8b23bec3fe..f3687a305e84fd 100644 --- a/packages/block-editor/src/components/block-variation-picker/index.js +++ b/packages/block-editor/src/components/block-variation-picker/index.js @@ -64,8 +64,7 @@ function BlockVariationPicker( { { allowSkip && ( <div className="block-editor-block-variation-picker__skip"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="link" onClick={ () => onSelect() } > diff --git a/packages/block-editor/src/components/block-variation-transforms/index.js b/packages/block-editor/src/components/block-variation-transforms/index.js index 8f29effb14e679..ca5e8e79348db8 100644 --- a/packages/block-editor/src/components/block-variation-transforms/index.js +++ b/packages/block-editor/src/components/block-variation-transforms/index.js @@ -35,8 +35,8 @@ function VariationsButtons( { </VisuallyHidden> { variations.map( ( variation ) => ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize + size="compact" key={ variation.name } icon={ <BlockIcon icon={ variation.icon } showColors /> } isPressed={ selectedValue === variation.name } diff --git a/packages/block-editor/src/components/button-block-appender/content.scss b/packages/block-editor/src/components/button-block-appender/content.scss index e462278c07c104..f5486d3f6f6086 100644 --- a/packages/block-editor/src/components/button-block-appender/content.scss +++ b/packages/block-editor/src/components/button-block-appender/content.scss @@ -8,11 +8,6 @@ color: $gray-900; box-shadow: inset 0 0 0 $border-width $gray-900; - // Needs specificity to override button styles. - &.components-button.components-button { - padding: $grid-unit-15; - } - .is-dark-theme & { color: $light-gray-placeholder; box-shadow: inset 0 0 0 $border-width $light-gray-placeholder; 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 c4a6854c6d6cc4..53b15e2fd2cfdd 100644 --- a/packages/block-editor/src/components/button-block-appender/index.js +++ b/packages/block-editor/src/components/button-block-appender/index.js @@ -60,8 +60,7 @@ function ButtonBlockAppender( return ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize ref={ mergedInserterButtonRef } onFocus={ onFocus } tabIndex={ tabIndex } diff --git a/packages/block-editor/src/components/colors-gradients/dropdown.js b/packages/block-editor/src/components/colors-gradients/dropdown.js index d3cf59a2a5e6e6..71b27c06e7ccfc 100644 --- a/packages/block-editor/src/components/colors-gradients/dropdown.js +++ b/packages/block-editor/src/components/colors-gradients/dropdown.js @@ -88,11 +88,7 @@ const renderToggle = }; return ( - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - { ...toggleProps } - > + <Button __next40pxDefaultSize { ...toggleProps }> <LabeledColorIndicator colorValue={ colorValue } label={ label } diff --git a/packages/block-editor/src/components/global-styles/color-panel.js b/packages/block-editor/src/components/global-styles/color-panel.js index 87c19adedbb27b..a55a7b331bd0dd 100644 --- a/packages/block-editor/src/components/global-styles/color-panel.js +++ b/packages/block-editor/src/components/global-styles/color-panel.js @@ -239,11 +239,7 @@ function ColorPanelDropdown( { }; return ( - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - { ...toggleProps } - > + <Button __next40pxDefaultSize { ...toggleProps }> <LabeledColorIndicators indicators={ indicators } label={ label } diff --git a/packages/block-editor/src/components/global-styles/filters-panel.js b/packages/block-editor/src/components/global-styles/filters-panel.js index de6e58b3334f13..581661e0c84071 100644 --- a/packages/block-editor/src/components/global-styles/filters-panel.js +++ b/packages/block-editor/src/components/global-styles/filters-panel.js @@ -190,8 +190,7 @@ export default function FiltersPanel( { return ( <ItemGroup isBordered isSeparated> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize { ...toggleProps } > <LabeledColorIndicator diff --git a/packages/block-editor/src/components/global-styles/shadow-panel-components.js b/packages/block-editor/src/components/global-styles/shadow-panel-components.js index 1ed367e3c3ad0e..1cfdff0be286ee 100644 --- a/packages/block-editor/src/components/global-styles/shadow-panel-components.js +++ b/packages/block-editor/src/components/global-styles/shadow-panel-components.js @@ -11,6 +11,7 @@ import { FlexItem, Dropdown, Composite, + Tooltip, } from '@wordpress/components'; import { useMemo } from '@wordpress/element'; import { shadow as shadowIcon, Icon, check } from '@wordpress/icons'; @@ -42,8 +43,7 @@ export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) { /> <div className="block-editor-global-styles__clear-shadow"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" onClick={ () => onShadowChange( undefined ) } > @@ -80,32 +80,31 @@ export function ShadowPresets( { presets, activeShadow, onSelect } ) { export function ShadowIndicator( { type, label, isActive, onSelect, shadow } ) { return ( - <Composite.Item - role="option" - aria-label={ label } - aria-selected={ isActive } - className={ clsx( 'block-editor-global-styles__shadow__item', { - 'is-active': isActive, - } ) } - render={ - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - className={ clsx( - 'block-editor-global-styles__shadow-indicator', - { - unset: type === 'unset', - } - ) } - onClick={ onSelect } - label={ label } - style={ { boxShadow: shadow } } - showTooltip - > - { isActive && <Icon icon={ check } /> } - </Button> - } - /> + <Tooltip text={ label }> + <Composite.Item + role="option" + aria-label={ label } + aria-selected={ isActive } + className={ clsx( 'block-editor-global-styles__shadow__item', { + 'is-active': isActive, + } ) } + render={ + <button + className={ clsx( + 'block-editor-global-styles__shadow-indicator', + { + unset: type === 'unset', + } + ) } + onClick={ onSelect } + style={ { boxShadow: shadow } } + aria-label={ label } + > + { isActive && <Icon icon={ check } /> } + </button> + } + /> + </Tooltip> ); } @@ -143,11 +142,7 @@ function renderShadowToggle() { }; return ( - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - { ...toggleProps } - > + <Button __next40pxDefaultSize { ...toggleProps }> <HStack justify="flex-start"> <Icon className="block-editor-global-styles__toggle-icon" diff --git a/packages/block-editor/src/components/global-styles/style.scss b/packages/block-editor/src/components/global-styles/style.scss index 3ba4f81d09daf4..e0782fdb01b1d0 100644 --- a/packages/block-editor/src/components/global-styles/style.scss +++ b/packages/block-editor/src/components/global-styles/style.scss @@ -37,10 +37,15 @@ // These styles are similar to the color palette. .block-editor-global-styles__shadow-indicator { + appearance: none; + background: none; color: $gray-800; border: $gray-200 $border-width solid; border-radius: $radius-small; cursor: pointer; + display: inline-flex; + align-items: center; + padding: 0; height: $button-size-small + 2 * $border-width; diff --git a/packages/block-library/src/group/editor.scss b/packages/block-library/src/group/editor.scss index 11beecbab0eb68..739a9cd0cf852e 100644 --- a/packages/block-library/src/group/editor.scss +++ b/packages/block-library/src/group/editor.scss @@ -39,9 +39,9 @@ &::after { content: ""; display: flex; - flex: 1 0 $grid-unit-60; + flex: 1 0 $button-size-next-default-40px; pointer-events: none; - min-height: $grid-unit-60 - $border-width - $border-width; + min-height: $button-size-next-default-40px - $border-width - $border-width; border: $border-width dashed currentColor; } From a644eb35518c307d9130ac9367ff160e14a3e8d5 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 24 Sep 2024 05:07:18 -0700 Subject: [PATCH 0930/1908] RichText: Fix JSDoc block typos (#65607) --- packages/rich-text/src/create.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rich-text/src/create.js b/packages/rich-text/src/create.js index 0b0a269509e7ec..898bdfa73b330e 100644 --- a/packages/rich-text/src/create.js +++ b/packages/rich-text/src/create.js @@ -431,7 +431,7 @@ export function removeReservedCharacters( string ) { /** * Creates a Rich Text value from a DOM element and range. * - * @param {Object} $1 Named argements. + * @param {Object} $1 Named arguments. * @param {Element} [$1.element] Element to create value from. * @param {Range} [$1.range] Range to create value from. * @param {boolean} [$1.isEditableTree] @@ -591,7 +591,7 @@ function createFromElement( { element, range, isEditableTree } ) { /** * Gets the attributes of an element in object shape. * - * @param {Object} $1 Named argements. + * @param {Object} $1 Named arguments. * @param {Element} $1.element Element to get attributes from. * * @return {Object|void} Attribute object or `undefined` if the element has no From 4f5380effdf5c370780cce9492cdba815315ec2c Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Tue, 24 Sep 2024 13:37:16 +0100 Subject: [PATCH 0931/1908] Stabilise role attribute property and related functions (#65484) * Update usages * Update related functions * Remove unwanted alias * Properly deprecate the experimental method * Deprecate and ensure backwards compatibility * Make selector private * Ensure serializer works backwards compat * Ensure experiment API method still exposed on blocks package * Add hint for updating role attribute * Remove unlock * Improve readability of proxying * Add hint to serializer * use stabilised selector for the content role for edit mode * Attempt locking to fix unit test * Ensure mock returns correct value --------- Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> --- .../test/use-transformed.patterns.js | 6 +-- .../components/block-switcher/test/utils.js | 6 +-- .../src/components/block-switcher/utils.js | 2 +- .../block-variation-transforms/index.js | 13 +++--- packages/block-editor/src/store/selectors.js | 21 +++++----- .../src/store/test/private-selectors.js | 4 +- .../block-editor/src/store/test/selectors.js | 22 +++++----- packages/block-library/src/audio/block.json | 8 ++-- packages/block-library/src/button/block.json | 10 ++--- .../block-library/src/categories/block.json | 2 +- packages/block-library/src/embed/block.json | 12 +++--- packages/block-library/src/file/block.json | 2 +- .../block-library/src/form-input/block.json | 4 +- .../src/form-input/deprecated.js | 8 ++-- packages/block-library/src/heading/block.json | 2 +- .../block-library/src/heading/deprecated.js | 2 +- packages/block-library/src/image/block.json | 14 +++---- .../block-library/src/image/deprecated.js | 36 ++++++++--------- .../block-library/src/list-item/block.json | 2 +- packages/block-library/src/list/block.json | 4 +- packages/block-library/src/list/deprecated.js | 16 ++++---- .../block-library/src/media-text/block.json | 10 ++--- .../src/media-text/deprecated.js | 10 ++--- .../block-library/src/paragraph/block.json | 2 +- .../block-library/src/preformatted/block.json | 2 +- .../block-library/src/pullquote/block.json | 4 +- .../block-library/src/pullquote/deprecated.js | 4 +- packages/block-library/src/quote/block.json | 4 +- .../block-library/src/quote/deprecated.js | 8 ++-- packages/block-library/src/search/block.json | 6 +-- packages/block-library/src/verse/block.json | 2 +- .../block-library/src/verse/deprecated.js | 2 +- packages/block-library/src/video/block.json | 10 ++--- packages/blocks/README.md | 13 ++++++ packages/blocks/src/api/index.js | 1 + packages/blocks/src/api/serializer.js | 11 +++++ packages/blocks/src/api/test/serializer.js | 2 +- packages/blocks/src/api/test/utils.js | 40 ++++++------------- packages/blocks/src/api/utils.js | 33 ++++++++++++--- .../blocks/src/store/private-selectors.js | 39 ++++++++++++++++++ packages/blocks/src/store/selectors.js | 31 +++++--------- .../core-data/src/test/entity-provider.js | 2 +- 42 files changed, 250 insertions(+), 182 deletions(-) diff --git a/packages/block-editor/src/components/block-switcher/test/use-transformed.patterns.js b/packages/block-editor/src/components/block-switcher/test/use-transformed.patterns.js index 05ce545667d464..4d63c763174791 100644 --- a/packages/block-editor/src/components/block-switcher/test/use-transformed.patterns.js +++ b/packages/block-editor/src/components/block-switcher/test/use-transformed.patterns.js @@ -20,15 +20,15 @@ describe( 'use-transformed-patterns', () => { }, content: { type: 'boolean', - __experimentalRole: 'content', + role: 'content', }, level: { type: 'number', - __experimentalRole: 'content', + role: 'content', }, color: { type: 'string', - __experimentalRole: 'other', + role: 'other', }, }, save() {}, diff --git a/packages/block-editor/src/components/block-switcher/test/utils.js b/packages/block-editor/src/components/block-switcher/test/utils.js index 38009601e16468..eafe5e8a4d9378 100644 --- a/packages/block-editor/src/components/block-switcher/test/utils.js +++ b/packages/block-editor/src/components/block-switcher/test/utils.js @@ -18,15 +18,15 @@ describe( 'BlockSwitcher - utils', () => { }, content: { type: 'boolean', - __experimentalRole: 'content', + role: 'content', }, level: { type: 'number', - __experimentalRole: 'content', + role: 'content', }, color: { type: 'string', - __experimentalRole: 'other', + role: 'other', }, }, save() {}, diff --git a/packages/block-editor/src/components/block-switcher/utils.js b/packages/block-editor/src/components/block-switcher/utils.js index ebd95fc460e33e..49257a2126cbe5 100644 --- a/packages/block-editor/src/components/block-switcher/utils.js +++ b/packages/block-editor/src/components/block-switcher/utils.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { __experimentalGetBlockAttributesNamesByRole as getBlockAttributesNamesByRole } from '@wordpress/blocks'; +import { getBlockAttributesNamesByRole } from '@wordpress/blocks'; /** * Try to find a matching block by a block's name in a provided diff --git a/packages/block-editor/src/components/block-variation-transforms/index.js b/packages/block-editor/src/components/block-variation-transforms/index.js index ca5e8e79348db8..5850fc52b37b68 100644 --- a/packages/block-editor/src/components/block-variation-transforms/index.js +++ b/packages/block-editor/src/components/block-variation-transforms/index.js @@ -21,6 +21,7 @@ import { chevronDown } from '@wordpress/icons'; */ import BlockIcon from '../block-icon'; import { store as blockEditorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; function VariationsButtons( { className, @@ -142,18 +143,16 @@ function __experimentalBlockVariationTransforms( { blockClientId } ) { const { updateBlockAttributes } = useDispatch( blockEditorStore ); const { activeBlockVariation, variations, isContentOnly } = useSelect( ( select ) => { - const { - getActiveBlockVariation, - getBlockVariations, - __experimentalHasContentRoleAttribute, - } = select( blocksStore ); + const { getActiveBlockVariation, getBlockVariations } = + select( blocksStore ); + const { getBlockName, getBlockAttributes, getBlockEditingMode } = select( blockEditorStore ); const name = blockClientId && getBlockName( blockClientId ); - const isContentBlock = - __experimentalHasContentRoleAttribute( name ); + const { hasContentRoleAttribute } = unlock( select( blocksStore ) ); + const isContentBlock = hasContentRoleAttribute( name ); return { activeBlockVariation: getActiveBlockVariation( diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 3163bb5257a9ad..a73785edfefd16 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2443,7 +2443,7 @@ export const __experimentalGetPatternsByBlockTypes = createRegistrySelector( * Determines the items that appear in the available pattern transforms list. * * For now we only handle blocks without InnerBlocks and take into account - * the `__experimentalRole` property of blocks' attributes for the transformation. + * the `role` property of blocks' attributes for the transformation. * * We return the first set of possible eligible block patterns, * by checking the `blockTypes` property. We still have to recurse through @@ -2465,7 +2465,7 @@ export const __experimentalGetPatternTransformItems = createRegistrySelector( } /** * For now we only handle blocks without InnerBlocks and take into account - * the `__experimentalRole` property of blocks' attributes for the transformation. + * the `role` property of blocks' attributes for the transformation. * Note that the blocks have been retrieved through `getBlock`, which doesn't * return the inner blocks of an inner block controller, so we still need * to check for this case too. @@ -2970,10 +2970,11 @@ export const getBlockEditingMode = createRegistrySelector( // The rest of the blocks depend on whether they are content blocks or not. // This "flattens" the sections tree. const name = getBlockName( state, clientId ); - const isContent = - select( blocksStore ).__experimentalHasContentRoleAttribute( - name - ); + const { hasContentRoleAttribute } = unlock( + select( blocksStore ) + ); + const isContent = hasContentRoleAttribute( name ); + return isContent ? 'contentOnly' : 'disabled'; } @@ -2993,10 +2994,10 @@ export const getBlockEditingMode = createRegistrySelector( // If the parent of the block is contentOnly locked, check whether it's a content block. if ( templateLock === 'contentOnly' ) { const name = getBlockName( state, clientId ); - const isContent = - select( blocksStore ).__experimentalHasContentRoleAttribute( - name - ); + const { hasContentRoleAttribute } = unlock( + select( blocksStore ) + ); + const isContent = hasContentRoleAttribute( name ); return isContent ? 'contentOnly' : 'disabled'; } // Otherwise, check if there's an ancestor that is contentOnly diff --git a/packages/block-editor/src/store/test/private-selectors.js b/packages/block-editor/src/store/test/private-selectors.js index 5f427e79cf6999..cbb75daa4baaa0 100644 --- a/packages/block-editor/src/store/test/private-selectors.js +++ b/packages/block-editor/src/store/test/private-selectors.js @@ -124,10 +124,10 @@ describe( 'private selectors', () => { blockEditingModes: new Map( [] ), }; - const __experimentalHasContentRoleAttribute = jest.fn( () => false ); + const hasContentRoleAttribute = jest.fn( () => false ); getBlockEditingMode.registry = { select: jest.fn( () => ( { - __experimentalHasContentRoleAttribute, + hasContentRoleAttribute, } ) ), }; diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index 2895f6573dc54f..ebf23789fec311 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -16,6 +16,7 @@ import { select, dispatch } from '@wordpress/data'; import * as selectors from '../selectors'; import { store } from '../'; import { sectionRootClientIdKey } from '../private-keys'; +import { lock } from '../../lock-unlock'; const { getBlockName, @@ -4475,14 +4476,14 @@ describe( 'getBlockEditingMode', () => { }, }; - const __experimentalHasContentRoleAttribute = jest.fn( ( name ) => { - // consider paragraphs as content blocks. - return name === 'core/p'; - } ); + const hasContentRoleAttribute = jest.fn( () => false ); + + const fauxPrivateAPIs = {}; + + lock( fauxPrivateAPIs, { hasContentRoleAttribute } ); + getBlockEditingMode.registry = { - select: jest.fn( () => ( { - __experimentalHasContentRoleAttribute, - } ) ), + select: jest.fn( () => fauxPrivateAPIs ), }; it( 'should return default by default', () => { @@ -4586,7 +4587,7 @@ describe( 'getBlockEditingMode', () => { }, }, }; - __experimentalHasContentRoleAttribute.mockReturnValueOnce( false ); + hasContentRoleAttribute.mockReturnValueOnce( false ); expect( getBlockEditingMode( state, 'b3247f75-fd94-4fef-97f9-5bfd162cc416' ) ).toBe( 'disabled' ); @@ -4602,7 +4603,7 @@ describe( 'getBlockEditingMode', () => { }, }, }; - __experimentalHasContentRoleAttribute.mockReturnValueOnce( true ); + hasContentRoleAttribute.mockReturnValueOnce( true ); expect( getBlockEditingMode( state, 'b3247f75-fd94-4fef-97f9-5bfd162cc416' ) ).toBe( 'contentOnly' ); @@ -4642,12 +4643,15 @@ describe( 'getBlockEditingMode', () => { } ); it( 'in navigation mode, blocks with content attributes within sections are contentOnly', () => { + hasContentRoleAttribute.mockReturnValueOnce( true ); expect( getBlockEditingMode( navigationModeStateWithRootSection, 'b3247f75-fd94-4fef-97f9-5bfd162cc416' ) ).toBe( 'contentOnly' ); + + hasContentRoleAttribute.mockReturnValueOnce( true ); expect( getBlockEditingMode( navigationModeStateWithRootSection, diff --git a/packages/block-library/src/audio/block.json b/packages/block-library/src/audio/block.json index bee2ff6d534a70..9b77efee23cce2 100644 --- a/packages/block-library/src/audio/block.json +++ b/packages/block-library/src/audio/block.json @@ -10,24 +10,24 @@ "attributes": { "blob": { "type": "string", - "__experimentalRole": "local" + "role": "local" }, "src": { "type": "string", "source": "attribute", "selector": "audio", "attribute": "src", - "__experimentalRole": "content" + "role": "content" }, "caption": { "type": "rich-text", "source": "rich-text", "selector": "figcaption", - "__experimentalRole": "content" + "role": "content" }, "id": { "type": "number", - "__experimentalRole": "content" + "role": "content" }, "autoplay": { "type": "boolean", diff --git a/packages/block-library/src/button/block.json b/packages/block-library/src/button/block.json index d0f90b93467c9d..2c1c05baa20dd3 100644 --- a/packages/block-library/src/button/block.json +++ b/packages/block-library/src/button/block.json @@ -26,34 +26,34 @@ "source": "attribute", "selector": "a", "attribute": "href", - "__experimentalRole": "content" + "role": "content" }, "title": { "type": "string", "source": "attribute", "selector": "a,button", "attribute": "title", - "__experimentalRole": "content" + "role": "content" }, "text": { "type": "rich-text", "source": "rich-text", "selector": "a,button", - "__experimentalRole": "content" + "role": "content" }, "linkTarget": { "type": "string", "source": "attribute", "selector": "a", "attribute": "target", - "__experimentalRole": "content" + "role": "content" }, "rel": { "type": "string", "source": "attribute", "selector": "a", "attribute": "rel", - "__experimentalRole": "content" + "role": "content" }, "placeholder": { "type": "string" diff --git a/packages/block-library/src/categories/block.json b/packages/block-library/src/categories/block.json index bfd8461f8eda43..3609bdf9ab97c0 100644 --- a/packages/block-library/src/categories/block.json +++ b/packages/block-library/src/categories/block.json @@ -34,7 +34,7 @@ }, "label": { "type": "string", - "__experimentalRole": "content" + "role": "content" }, "showLabel": { "type": "boolean", diff --git a/packages/block-library/src/embed/block.json b/packages/block-library/src/embed/block.json index a42aafbab4b0b9..5bfb63b0fa9e94 100644 --- a/packages/block-library/src/embed/block.json +++ b/packages/block-library/src/embed/block.json @@ -9,21 +9,21 @@ "attributes": { "url": { "type": "string", - "__experimentalRole": "content" + "role": "content" }, "caption": { "type": "rich-text", "source": "rich-text", "selector": "figcaption", - "__experimentalRole": "content" + "role": "content" }, "type": { "type": "string", - "__experimentalRole": "content" + "role": "content" }, "providerNameSlug": { "type": "string", - "__experimentalRole": "content" + "role": "content" }, "allowResponsive": { "type": "boolean", @@ -32,12 +32,12 @@ "responsive": { "type": "boolean", "default": false, - "__experimentalRole": "content" + "role": "content" }, "previewable": { "type": "boolean", "default": true, - "__experimentalRole": "content" + "role": "content" } }, "supports": { diff --git a/packages/block-library/src/file/block.json b/packages/block-library/src/file/block.json index 0526120c4dfc1e..bf0082c576dd16 100644 --- a/packages/block-library/src/file/block.json +++ b/packages/block-library/src/file/block.json @@ -13,7 +13,7 @@ }, "blob": { "type": "string", - "__experimentalRole": "local" + "role": "local" }, "href": { "type": "string" diff --git a/packages/block-library/src/form-input/block.json b/packages/block-library/src/form-input/block.json index 53aa0be6744cb9..386c90ac207ad4 100644 --- a/packages/block-library/src/form-input/block.json +++ b/packages/block-library/src/form-input/block.json @@ -23,7 +23,7 @@ "default": "Label", "selector": ".wp-block-form-input__label-content", "source": "rich-text", - "__experimentalRole": "content" + "role": "content" }, "inlineLabel": { "type": "boolean", @@ -41,7 +41,7 @@ "selector": ".wp-block-form-input__input", "source": "attribute", "attribute": "placeholder", - "__experimentalRole": "content" + "role": "content" }, "value": { "type": "string", diff --git a/packages/block-library/src/form-input/deprecated.js b/packages/block-library/src/form-input/deprecated.js index 451cc704a42d55..d974cca387a188 100644 --- a/packages/block-library/src/form-input/deprecated.js +++ b/packages/block-library/src/form-input/deprecated.js @@ -41,7 +41,7 @@ const v2 = { default: 'Label', selector: '.wp-block-form-input__label-content', source: 'html', - __experimentalRole: 'content', + role: 'content', }, inlineLabel: { type: 'boolean', @@ -59,7 +59,7 @@ const v2 = { selector: '.wp-block-form-input__input', source: 'attribute', attribute: 'placeholder', - __experimentalRole: 'content', + role: 'content', }, value: { type: 'string', @@ -155,7 +155,7 @@ const v1 = { default: 'Label', selector: '.wp-block-form-input__label-content', source: 'html', - __experimentalRole: 'content', + role: 'content', }, inlineLabel: { type: 'boolean', @@ -173,7 +173,7 @@ const v1 = { selector: '.wp-block-form-input__input', source: 'attribute', attribute: 'placeholder', - __experimentalRole: 'content', + role: 'content', }, value: { type: 'string', diff --git a/packages/block-library/src/heading/block.json b/packages/block-library/src/heading/block.json index 6e43a18cfba452..2276bcbbb50172 100644 --- a/packages/block-library/src/heading/block.json +++ b/packages/block-library/src/heading/block.json @@ -15,7 +15,7 @@ "type": "rich-text", "source": "rich-text", "selector": "h1,h2,h3,h4,h5,h6", - "__experimentalRole": "content" + "role": "content" }, "level": { "type": "number", diff --git a/packages/block-library/src/heading/deprecated.js b/packages/block-library/src/heading/deprecated.js index a97415712bf07c..76b175ac44fc40 100644 --- a/packages/block-library/src/heading/deprecated.js +++ b/packages/block-library/src/heading/deprecated.js @@ -259,7 +259,7 @@ const v5 = { source: 'html', selector: 'h1,h2,h3,h4,h5,h6', default: '', - __experimentalRole: 'content', + role: 'content', }, level: { type: 'number', diff --git a/packages/block-library/src/image/block.json b/packages/block-library/src/image/block.json index 6417879164a22b..f441a6e893290b 100644 --- a/packages/block-library/src/image/block.json +++ b/packages/block-library/src/image/block.json @@ -11,14 +11,14 @@ "attributes": { "blob": { "type": "string", - "__experimentalRole": "local" + "role": "local" }, "url": { "type": "string", "source": "attribute", "selector": "img", "attribute": "src", - "__experimentalRole": "content" + "role": "content" }, "alt": { "type": "string", @@ -26,13 +26,13 @@ "selector": "img", "attribute": "alt", "default": "", - "__experimentalRole": "content" + "role": "content" }, "caption": { "type": "rich-text", "source": "rich-text", "selector": "figcaption", - "__experimentalRole": "content" + "role": "content" }, "lightbox": { "type": "object", @@ -45,14 +45,14 @@ "source": "attribute", "selector": "img", "attribute": "title", - "__experimentalRole": "content" + "role": "content" }, "href": { "type": "string", "source": "attribute", "selector": "figure > a", "attribute": "href", - "__experimentalRole": "content" + "role": "content" }, "rel": { "type": "string", @@ -68,7 +68,7 @@ }, "id": { "type": "number", - "__experimentalRole": "content" + "role": "content" }, "width": { "type": "string" diff --git a/packages/block-library/src/image/deprecated.js b/packages/block-library/src/image/deprecated.js index 135463a377131f..6c1db75c5e2aa5 100644 --- a/packages/block-library/src/image/deprecated.js +++ b/packages/block-library/src/image/deprecated.js @@ -559,7 +559,7 @@ const v6 = { source: 'attribute', selector: 'img', attribute: 'src', - __experimentalRole: 'content', + role: 'content', }, alt: { type: 'string', @@ -567,27 +567,27 @@ const v6 = { selector: 'img', attribute: 'alt', default: '', - __experimentalRole: 'content', + role: 'content', }, caption: { type: 'string', source: 'html', selector: 'figcaption', - __experimentalRole: 'content', + role: 'content', }, title: { type: 'string', source: 'attribute', selector: 'img', attribute: 'title', - __experimentalRole: 'content', + role: 'content', }, href: { type: 'string', source: 'attribute', selector: 'figure > a', attribute: 'href', - __experimentalRole: 'content', + role: 'content', }, rel: { type: 'string', @@ -603,7 +603,7 @@ const v6 = { }, id: { type: 'number', - __experimentalRole: 'content', + role: 'content', }, width: { type: 'number', @@ -762,7 +762,7 @@ const v7 = { source: 'attribute', selector: 'img', attribute: 'src', - __experimentalRole: 'content', + role: 'content', }, alt: { type: 'string', @@ -770,27 +770,27 @@ const v7 = { selector: 'img', attribute: 'alt', default: '', - __experimentalRole: 'content', + role: 'content', }, caption: { type: 'string', source: 'html', selector: 'figcaption', - __experimentalRole: 'content', + role: 'content', }, title: { type: 'string', source: 'attribute', selector: 'img', attribute: 'title', - __experimentalRole: 'content', + role: 'content', }, href: { type: 'string', source: 'attribute', selector: 'figure > a', attribute: 'href', - __experimentalRole: 'content', + role: 'content', }, rel: { type: 'string', @@ -806,7 +806,7 @@ const v7 = { }, id: { type: 'number', - __experimentalRole: 'content', + role: 'content', }, width: { type: 'number', @@ -962,7 +962,7 @@ const v8 = { source: 'attribute', selector: 'img', attribute: 'src', - __experimentalRole: 'content', + role: 'content', }, alt: { type: 'string', @@ -970,27 +970,27 @@ const v8 = { selector: 'img', attribute: 'alt', default: '', - __experimentalRole: 'content', + role: 'content', }, caption: { type: 'string', source: 'html', selector: 'figcaption', - __experimentalRole: 'content', + role: 'content', }, title: { type: 'string', source: 'attribute', selector: 'img', attribute: 'title', - __experimentalRole: 'content', + role: 'content', }, href: { type: 'string', source: 'attribute', selector: 'figure > a', attribute: 'href', - __experimentalRole: 'content', + role: 'content', }, rel: { type: 'string', @@ -1006,7 +1006,7 @@ const v8 = { }, id: { type: 'number', - __experimentalRole: 'content', + role: 'content', }, width: { type: 'string', diff --git a/packages/block-library/src/list-item/block.json b/packages/block-library/src/list-item/block.json index a4bf2351d97509..6eb30cfe6d0af0 100644 --- a/packages/block-library/src/list-item/block.json +++ b/packages/block-library/src/list-item/block.json @@ -16,7 +16,7 @@ "type": "rich-text", "source": "rich-text", "selector": "li", - "__experimentalRole": "content" + "role": "content" } }, "supports": { diff --git a/packages/block-library/src/list/block.json b/packages/block-library/src/list/block.json index ea07a0eb542df3..4a86def8d687b4 100644 --- a/packages/block-library/src/list/block.json +++ b/packages/block-library/src/list/block.json @@ -12,7 +12,7 @@ "ordered": { "type": "boolean", "default": false, - "__experimentalRole": "content" + "role": "content" }, "values": { "type": "string", @@ -21,7 +21,7 @@ "multiline": "li", "__unstableMultilineWrapperTags": [ "ol", "ul" ], "default": "", - "__experimentalRole": "content" + "role": "content" }, "type": { "type": "string" diff --git a/packages/block-library/src/list/deprecated.js b/packages/block-library/src/list/deprecated.js index edb04dff27c904..13804b7040ed46 100644 --- a/packages/block-library/src/list/deprecated.js +++ b/packages/block-library/src/list/deprecated.js @@ -14,7 +14,7 @@ const v0 = { ordered: { type: 'boolean', default: false, - __experimentalRole: 'content', + role: 'content', }, values: { type: 'string', @@ -23,7 +23,7 @@ const v0 = { multiline: 'li', __unstableMultilineWrapperTags: [ 'ol', 'ul' ], default: '', - __experimentalRole: 'content', + role: 'content', }, type: { type: 'string', @@ -74,7 +74,7 @@ const v1 = { ordered: { type: 'boolean', default: false, - __experimentalRole: 'content', + role: 'content', }, values: { type: 'string', @@ -83,7 +83,7 @@ const v1 = { multiline: 'li', __unstableMultilineWrapperTags: [ 'ol', 'ul' ], default: '', - __experimentalRole: 'content', + role: 'content', }, type: { type: 'string', @@ -144,7 +144,7 @@ const v2 = { ordered: { type: 'boolean', default: false, - __experimentalRole: 'content', + role: 'content', }, values: { type: 'string', @@ -153,7 +153,7 @@ const v2 = { multiline: 'li', __unstableMultilineWrapperTags: [ 'ol', 'ul' ], default: '', - __experimentalRole: 'content', + role: 'content', }, type: { type: 'string', @@ -225,7 +225,7 @@ const v3 = { ordered: { type: 'boolean', default: false, - __experimentalRole: 'content', + role: 'content', }, values: { type: 'string', @@ -234,7 +234,7 @@ const v3 = { multiline: 'li', __unstableMultilineWrapperTags: [ 'ol', 'ul' ], default: '', - __experimentalRole: 'content', + role: 'content', }, type: { type: 'string', diff --git a/packages/block-library/src/media-text/block.json b/packages/block-library/src/media-text/block.json index 42384c0c4478e0..0c2cfc4a14995a 100644 --- a/packages/block-library/src/media-text/block.json +++ b/packages/block-library/src/media-text/block.json @@ -18,7 +18,7 @@ "selector": "figure img", "attribute": "alt", "default": "", - "__experimentalRole": "content" + "role": "content" }, "mediaPosition": { "type": "string", @@ -26,14 +26,14 @@ }, "mediaId": { "type": "number", - "__experimentalRole": "content" + "role": "content" }, "mediaUrl": { "type": "string", "source": "attribute", "selector": "figure video,figure img", "attribute": "src", - "__experimentalRole": "content" + "role": "content" }, "mediaLink": { "type": "string" @@ -52,7 +52,7 @@ "source": "attribute", "selector": "figure a", "attribute": "href", - "__experimentalRole": "content" + "role": "content" }, "rel": { "type": "string", @@ -68,7 +68,7 @@ }, "mediaType": { "type": "string", - "__experimentalRole": "content" + "role": "content" }, "mediaWidth": { "type": "number", diff --git a/packages/block-library/src/media-text/deprecated.js b/packages/block-library/src/media-text/deprecated.js index 54c6f863311ffe..24f239a41ed295 100644 --- a/packages/block-library/src/media-text/deprecated.js +++ b/packages/block-library/src/media-text/deprecated.js @@ -172,29 +172,29 @@ const v6Attributes = { selector: 'figure img', attribute: 'alt', default: '', - __experimentalRole: 'content', + role: 'content', }, mediaId: { type: 'number', - __experimentalRole: 'content', + role: 'content', }, mediaUrl: { type: 'string', source: 'attribute', selector: 'figure video,figure img', attribute: 'src', - __experimentalRole: 'content', + role: 'content', }, href: { type: 'string', source: 'attribute', selector: 'figure a', attribute: 'href', - __experimentalRole: 'content', + role: 'content', }, mediaType: { type: 'string', - __experimentalRole: 'content', + role: 'content', }, }; diff --git a/packages/block-library/src/paragraph/block.json b/packages/block-library/src/paragraph/block.json index f16a7cf0411443..7e004019cbf282 100644 --- a/packages/block-library/src/paragraph/block.json +++ b/packages/block-library/src/paragraph/block.json @@ -15,7 +15,7 @@ "type": "rich-text", "source": "rich-text", "selector": "p", - "__experimentalRole": "content" + "role": "content" }, "dropCap": { "type": "boolean", diff --git a/packages/block-library/src/preformatted/block.json b/packages/block-library/src/preformatted/block.json index a1726ee8b0d43c..c25b8ce37093a5 100644 --- a/packages/block-library/src/preformatted/block.json +++ b/packages/block-library/src/preformatted/block.json @@ -12,7 +12,7 @@ "source": "rich-text", "selector": "pre", "__unstablePreserveWhiteSpace": true, - "__experimentalRole": "content" + "role": "content" } }, "supports": { diff --git a/packages/block-library/src/pullquote/block.json b/packages/block-library/src/pullquote/block.json index 0935f9759668d5..271bba74d0252a 100644 --- a/packages/block-library/src/pullquote/block.json +++ b/packages/block-library/src/pullquote/block.json @@ -11,13 +11,13 @@ "type": "rich-text", "source": "rich-text", "selector": "p", - "__experimentalRole": "content" + "role": "content" }, "citation": { "type": "rich-text", "source": "rich-text", "selector": "cite", - "__experimentalRole": "content" + "role": "content" }, "textAlign": { "type": "string" diff --git a/packages/block-library/src/pullquote/deprecated.js b/packages/block-library/src/pullquote/deprecated.js index 6e6f49da91c6a3..18e47997550782 100644 --- a/packages/block-library/src/pullquote/deprecated.js +++ b/packages/block-library/src/pullquote/deprecated.js @@ -75,14 +75,14 @@ const v5 = { source: 'html', selector: 'blockquote', multiline: 'p', - __experimentalRole: 'content', + role: 'content', }, citation: { type: 'string', source: 'html', selector: 'cite', default: '', - __experimentalRole: 'content', + role: 'content', }, textAlign: { type: 'string', diff --git a/packages/block-library/src/quote/block.json b/packages/block-library/src/quote/block.json index 0f9ec97422f64b..2ae37f9f36f766 100644 --- a/packages/block-library/src/quote/block.json +++ b/packages/block-library/src/quote/block.json @@ -14,13 +14,13 @@ "selector": "blockquote", "multiline": "p", "default": "", - "__experimentalRole": "content" + "role": "content" }, "citation": { "type": "rich-text", "source": "rich-text", "selector": "cite", - "__experimentalRole": "content" + "role": "content" }, "textAlign": { "type": "string" diff --git a/packages/block-library/src/quote/deprecated.js b/packages/block-library/src/quote/deprecated.js index 77098b6e753139..4d3efd28e3a22c 100644 --- a/packages/block-library/src/quote/deprecated.js +++ b/packages/block-library/src/quote/deprecated.js @@ -70,14 +70,14 @@ const v4 = { selector: 'blockquote', multiline: 'p', default: '', - __experimentalRole: 'content', + role: 'content', }, citation: { type: 'string', source: 'html', selector: 'cite', default: '', - __experimentalRole: 'content', + role: 'content', }, align: { type: 'string', @@ -138,14 +138,14 @@ const v3 = { selector: 'blockquote', multiline: 'p', default: '', - __experimentalRole: 'content', + role: 'content', }, citation: { type: 'string', source: 'html', selector: 'cite', default: '', - __experimentalRole: 'content', + role: 'content', }, align: { type: 'string', diff --git a/packages/block-library/src/search/block.json b/packages/block-library/src/search/block.json index dac4c6b488a97e..c5af5a29d21beb 100644 --- a/packages/block-library/src/search/block.json +++ b/packages/block-library/src/search/block.json @@ -10,7 +10,7 @@ "attributes": { "label": { "type": "string", - "__experimentalRole": "content" + "role": "content" }, "showLabel": { "type": "boolean", @@ -19,7 +19,7 @@ "placeholder": { "type": "string", "default": "", - "__experimentalRole": "content" + "role": "content" }, "width": { "type": "number" @@ -29,7 +29,7 @@ }, "buttonText": { "type": "string", - "__experimentalRole": "content" + "role": "content" }, "buttonPosition": { "type": "string", diff --git a/packages/block-library/src/verse/block.json b/packages/block-library/src/verse/block.json index 387ff3dfe17123..81cccd72965b1a 100644 --- a/packages/block-library/src/verse/block.json +++ b/packages/block-library/src/verse/block.json @@ -13,7 +13,7 @@ "source": "rich-text", "selector": "pre", "__unstablePreserveWhiteSpace": true, - "__experimentalRole": "content" + "role": "content" }, "textAlign": { "type": "string" diff --git a/packages/block-library/src/verse/deprecated.js b/packages/block-library/src/verse/deprecated.js index 7e3c96bc80cd98..bd4edc46738c5c 100644 --- a/packages/block-library/src/verse/deprecated.js +++ b/packages/block-library/src/verse/deprecated.js @@ -46,7 +46,7 @@ const v2 = { selector: 'pre', default: '', __unstablePreserveWhiteSpace: true, - __experimentalRole: 'content', + role: 'content', }, textAlign: { type: 'string', diff --git a/packages/block-library/src/video/block.json b/packages/block-library/src/video/block.json index 1d3dc75961e8f1..d2dcd95365c3b5 100644 --- a/packages/block-library/src/video/block.json +++ b/packages/block-library/src/video/block.json @@ -18,7 +18,7 @@ "type": "rich-text", "source": "rich-text", "selector": "figcaption", - "__experimentalRole": "content" + "role": "content" }, "controls": { "type": "boolean", @@ -29,7 +29,7 @@ }, "id": { "type": "number", - "__experimentalRole": "content" + "role": "content" }, "loop": { "type": "boolean", @@ -58,14 +58,14 @@ }, "blob": { "type": "string", - "__experimentalRole": "local" + "role": "local" }, "src": { "type": "string", "source": "attribute", "selector": "video", "attribute": "src", - "__experimentalRole": "content" + "role": "content" }, "playsInline": { "type": "boolean", @@ -74,7 +74,7 @@ "attribute": "playsinline" }, "tracks": { - "__experimentalRole": "content", + "role": "content", "type": "array", "items": { "type": "object" diff --git a/packages/blocks/README.md b/packages/blocks/README.md index d724f986b0ca81..b607286f1e73c7 100644 --- a/packages/blocks/README.md +++ b/packages/blocks/README.md @@ -102,6 +102,19 @@ _Returns_ - `Object`: All block attributes. +### getBlockAttributesNamesByRole + +Filter block attributes by `role` and return their names. + +_Parameters_ + +- _name_ `string`: Block attribute's name. +- _role_ `string`: The role of a block attribute. + +_Returns_ + +- `string[]`: The attribute names that have the provided role. + ### getBlockContent Given a block object, returns the Block's Inner HTML markup. diff --git a/packages/blocks/src/api/index.js b/packages/blocks/src/api/index.js index 803467cb2187e2..e7ab69af71103a 100644 --- a/packages/blocks/src/api/index.js +++ b/packages/blocks/src/api/index.js @@ -155,6 +155,7 @@ export { getBlockLabel as __experimentalGetBlockLabel, getAccessibleBlockLabel as __experimentalGetAccessibleBlockLabel, __experimentalSanitizeBlockAttributes, + getBlockAttributesNamesByRole, __experimentalGetBlockAttributesNamesByRole, } from './utils'; diff --git a/packages/blocks/src/api/serializer.js b/packages/blocks/src/api/serializer.js index 2e7246ce9584a9..f1fb28e9d9a361 100644 --- a/packages/blocks/src/api/serializer.js +++ b/packages/blocks/src/api/serializer.js @@ -10,6 +10,7 @@ import { import { hasFilter, applyFilters } from '@wordpress/hooks'; import isShallowEqual from '@wordpress/is-shallow-equal'; import { removep } from '@wordpress/autop'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies @@ -238,7 +239,17 @@ export function getCommentAttributes( blockType, attributes ) { } // Ignore all local attributes + if ( attributeSchema.role === 'local' ) { + return accumulator; + } + if ( attributeSchema.__experimentalRole === 'local' ) { + deprecated( '__experimentalRole attribute', { + since: '6.7', + version: '6.8', + alternative: 'role attribute', + hint: `Check the block.json of the ${ blockType?.name } block.`, + } ); return accumulator; } diff --git a/packages/blocks/src/api/test/serializer.js b/packages/blocks/src/api/test/serializer.js index 7fed23041daaa6..3c1cbd6d1e74ff 100644 --- a/packages/blocks/src/api/test/serializer.js +++ b/packages/blocks/src/api/test/serializer.js @@ -155,7 +155,7 @@ describe( 'block serializer', () => { attributes: { blob: { type: 'string', - __experimentalRole: 'local', + role: 'local', }, url: { type: 'string', diff --git a/packages/blocks/src/api/test/utils.js b/packages/blocks/src/api/test/utils.js index 9bfef69c4c1428..ad76e89aafe5f0 100644 --- a/packages/blocks/src/api/test/utils.js +++ b/packages/blocks/src/api/test/utils.js @@ -13,7 +13,7 @@ import { getAccessibleBlockLabel, getBlockLabel, __experimentalSanitizeBlockAttributes, - __experimentalGetBlockAttributesNamesByRole, + getBlockAttributesNamesByRole, } from '../utils'; const noop = () => {}; @@ -309,7 +309,7 @@ describe( 'sanitizeBlockAttributes', () => { } ); } ); -describe( '__experimentalGetBlockAttributesNamesByRole', () => { +describe( 'getBlockAttributesNamesByRole', () => { beforeAll( () => { registerBlockType( 'core/test-block-1', { attributes: { @@ -318,15 +318,15 @@ describe( '__experimentalGetBlockAttributesNamesByRole', () => { }, content: { type: 'boolean', - __experimentalRole: 'content', + role: 'content', }, level: { type: 'number', - __experimentalRole: 'content', + role: 'content', }, color: { type: 'string', - __experimentalRole: 'other', + role: 'other', }, }, save: noop, @@ -357,42 +357,28 @@ describe( '__experimentalGetBlockAttributesNamesByRole', () => { ].forEach( unregisterBlockType ); } ); it( 'should return empty array if block has no attributes', () => { - expect( - __experimentalGetBlockAttributesNamesByRole( 'core/test-block-3' ) - ).toEqual( [] ); + expect( getBlockAttributesNamesByRole( 'core/test-block-3' ) ).toEqual( + [] + ); } ); it( 'should return all attribute names if no role is provided', () => { - expect( - __experimentalGetBlockAttributesNamesByRole( 'core/test-block-1' ) - ).toEqual( + expect( getBlockAttributesNamesByRole( 'core/test-block-1' ) ).toEqual( expect.arrayContaining( [ 'align', 'content', 'level', 'color' ] ) ); } ); it( 'should return proper results with existing attributes and provided role', () => { expect( - __experimentalGetBlockAttributesNamesByRole( - 'core/test-block-1', - 'content' - ) + getBlockAttributesNamesByRole( 'core/test-block-1', 'content' ) ).toEqual( expect.arrayContaining( [ 'content', 'level' ] ) ); expect( - __experimentalGetBlockAttributesNamesByRole( - 'core/test-block-1', - 'other' - ) + getBlockAttributesNamesByRole( 'core/test-block-1', 'other' ) ).toEqual( [ 'color' ] ); expect( - __experimentalGetBlockAttributesNamesByRole( - 'core/test-block-1', - 'not-exists' - ) + getBlockAttributesNamesByRole( 'core/test-block-1', 'not-exists' ) ).toEqual( [] ); // A block with no `role` in any attributes. expect( - __experimentalGetBlockAttributesNamesByRole( - 'core/test-block-2', - 'content' - ) + getBlockAttributesNamesByRole( 'core/test-block-2', 'content' ) ).toEqual( [] ); } ); } ); diff --git a/packages/blocks/src/api/utils.js b/packages/blocks/src/api/utils.js index a68937586f9273..20f0f6a85ed091 100644 --- a/packages/blocks/src/api/utils.js +++ b/packages/blocks/src/api/utils.js @@ -12,6 +12,7 @@ import { Component, isValidElement } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { __unstableStripHTML as stripHTML } from '@wordpress/dom'; import { RichTextData } from '@wordpress/rich-text'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies @@ -332,7 +333,7 @@ export function __experimentalSanitizeBlockAttributes( name, attributes ) { * * @return {string[]} The attribute names that have the provided role. */ -export function __experimentalGetBlockAttributesNamesByRole( name, role ) { +export function getBlockAttributesNamesByRole( name, role ) { const attributes = getBlockType( name )?.attributes; if ( ! attributes ) { return []; @@ -341,12 +342,34 @@ export function __experimentalGetBlockAttributesNamesByRole( name, role ) { if ( ! role ) { return attributesNames; } - return attributesNames.filter( - ( attributeName ) => - attributes[ attributeName ]?.__experimentalRole === role - ); + + return attributesNames.filter( ( attributeName ) => { + const attribute = attributes[ attributeName ]; + if ( attribute?.role === role ) { + return true; + } + if ( attribute?.__experimentalRole === role ) { + deprecated( '__experimentalRole attribute', { + since: '6.7', + version: '6.8', + alternative: 'role attribute', + hint: `Check the block.json of the ${ name } block.`, + } ); + return true; + } + return false; + } ); } +export const __experimentalGetBlockAttributesNamesByRole = ( ...args ) => { + deprecated( '__experimentalGetBlockAttributesNamesByRole', { + since: '6.7', + version: '6.8', + alternative: 'getBlockAttributesNamesByRole', + } ); + return getBlockAttributesNamesByRole( ...args ); +}; + /** * Return a new object with the specified keys omitted. * diff --git a/packages/blocks/src/store/private-selectors.js b/packages/blocks/src/store/private-selectors.js index 4cded8268ae97c..81bdc1fca2c420 100644 --- a/packages/blocks/src/store/private-selectors.js +++ b/packages/blocks/src/store/private-selectors.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { createSelector } from '@wordpress/data'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies @@ -209,3 +210,41 @@ export function getAllBlockBindingsSources( state ) { export function getBlockBindingsSource( state, sourceName ) { return state.blockBindingsSources[ sourceName ]; } + +/** + * Determines if any of the block type's attributes have + * the content role attribute. + * + * @param {Object} state Data state. + * @param {string} blockTypeName Block type name. + * @return {boolean} Whether block type has content role attribute. + */ +export const hasContentRoleAttribute = createSelector( + ( state, blockTypeName ) => { + const blockType = getBlockType( state, blockTypeName ); + if ( ! blockType ) { + return false; + } + + return Object.entries( blockType.attributes ).some( + ( [ , { role, __experimentalRole } ] ) => { + if ( role === 'content' ) { + return true; + } + if ( __experimentalRole === 'content' ) { + deprecated( '__experimentalRole attribute', { + since: '6.7', + version: '6.8', + alternative: 'role attribute', + hint: `Check the block.json of the ${ blockTypeName } block.`, + } ); + return true; + } + return false; + } + ); + }, + ( state, blockTypeName ) => [ + state.blockTypes[ blockTypeName ]?.attributes, + ] +); diff --git a/packages/blocks/src/store/selectors.js b/packages/blocks/src/store/selectors.js index e97048e92b0c07..6d38af389e3129 100644 --- a/packages/blocks/src/store/selectors.js +++ b/packages/blocks/src/store/selectors.js @@ -8,11 +8,13 @@ import removeAccents from 'remove-accents'; */ import { createSelector } from '@wordpress/data'; import { RichTextData } from '@wordpress/rich-text'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies */ import { getValueFromObjectPath, matchesAttributes } from './utils'; +import { hasContentRoleAttribute as privateHasContentRoleAttribute } from './private-selectors'; /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */ /** @typedef {import('../api/registration').WPBlockVariationScope} WPBlockVariationScope */ @@ -822,23 +824,12 @@ export const hasChildBlocksWithInserterSupport = ( state, blockName ) => { } ); }; -/** - * DO-NOT-USE in production. - * This selector is created for internal/experimental only usage and may be - * removed anytime without any warning, causing breakage on any plugin or theme invoking it. - */ -export const __experimentalHasContentRoleAttribute = createSelector( - ( state, blockTypeName ) => { - const blockType = getBlockType( state, blockTypeName ); - if ( ! blockType ) { - return false; - } - - return Object.entries( blockType.attributes ).some( - ( [ , { __experimentalRole } ] ) => __experimentalRole === 'content' - ); - }, - ( state, blockTypeName ) => [ - state.blockTypes[ blockTypeName ]?.attributes, - ] -); +export const __experimentalHasContentRoleAttribute = ( ...args ) => { + deprecated( '__experimentalHasContentRoleAttribute', { + since: '6.7', + version: '6.8', + alternative: 'hasContentRoleAttribute', + hint: 'This is a private selector.', + } ); + return privateHasContentRoleAttribute( ...args ); +}; diff --git a/packages/core-data/src/test/entity-provider.js b/packages/core-data/src/test/entity-provider.js index 6b0b7bd5ef77a8..4dc0d8a51663e8 100644 --- a/packages/core-data/src/test/entity-provider.js +++ b/packages/core-data/src/test/entity-provider.js @@ -104,7 +104,7 @@ describe( 'useEntityBlockEditor', () => { source: 'html', selector: 'p', default: '', - __experimentalRole: 'content', + role: 'content', }, }, title: 'block title', From 1def0f6b4ddab54e49629837ff557c2a117815e8 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Tue, 24 Sep 2024 14:42:07 +0200 Subject: [PATCH 0932/1908] Remove one occurrence of the verb Toggle from Zoom out control. (#65609) Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- packages/editor/src/components/zoom-out-toggle/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/zoom-out-toggle/index.js b/packages/editor/src/components/zoom-out-toggle/index.js index dd4669d04bec18..b89bf15546f0d8 100644 --- a/packages/editor/src/components/zoom-out-toggle/index.js +++ b/packages/editor/src/components/zoom-out-toggle/index.js @@ -40,7 +40,7 @@ const ZoomOutToggle = () => { <Button onClick={ handleZoomOut } icon={ zoomOutIcon } - label={ __( 'Toggle Zoom Out' ) } + label={ __( 'Zoom Out' ) } isPressed={ isZoomOut } size="compact" showTooltip={ ! showIconLabels } From 327ff86cea14377610edcfdb921f7450510e3477 Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini <26530524+zaguiini@users.noreply.github.com> Date: Tue, 24 Sep 2024 09:43:28 -0300 Subject: [PATCH 0933/1908] Block Bindings: Prioritize existing placeholder over bindingsPlaceholder (#65220) * Pass data-custom-placeholder prop to all RichText instances that are modifying the placeholder prop * Use placeholder if data-custom-placeholder is true * Add test * Only use placeholder if aria-label is not defined * Prioritize custom placeholder in aria-label * Fix Cover block test * Revert aria-label changes * Try: Read block attribute in bindings placeholder * Revert changes to placeholder prop * Fix after rebase * Explicitly return `null` for empty values --------- Co-authored-by: zaguiini <zaguiini@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- .../src/components/rich-text/index.js | 35 ++++++++++++++----- .../editor/various/block-bindings.spec.js | 35 ++++++++++++++++++- 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 387f388b8fdad6..9c67476ed0ea63 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -165,7 +165,7 @@ export function RichTextWrapper( isBlockSelected, ] ); - const { disableBoundBlock, bindingsPlaceholder } = useSelect( + const { disableBoundBlock, bindingsPlaceholder, bindingsLabel } = useSelect( ( select ) => { if ( ! blockBindings?.[ identifier ] || @@ -179,10 +179,6 @@ export function RichTextWrapper( const blockBindingsSource = getBlockBindingsSource( relatedBinding.source ); - const fieldsList = blockBindingsSource?.getFieldsList?.( { - registry, - context: blockContext, - } ); const _disableBoundBlock = ! blockBindingsSource?.canUserEditValue?.( { @@ -191,6 +187,22 @@ export function RichTextWrapper( args: relatedBinding.args, } ); + // Don't modify placeholders if value is not empty. + if ( adjustedValue.length > 0 ) { + return { + disableBoundBlock: _disableBoundBlock, + // Null values will make them fall back to the default behavior. + bindingsPlaceholder: null, + bindingsLabel: null, + }; + } + + const { getBlockAttributes } = select( blockEditorStore ); + const blockAttributes = getBlockAttributes( clientId ); + const fieldsList = blockBindingsSource?.getFieldsList?.( { + registry, + context: blockContext, + } ); const bindingKey = fieldsList?.[ relatedBinding?.args?.key ]?.label ?? blockBindingsSource?.label; @@ -202,12 +214,19 @@ export function RichTextWrapper( __( 'Add %s' ), bindingKey ); + const _bindingsLabel = _disableBoundBlock + ? relatedBinding?.args?.key || blockBindingsSource?.label + : sprintf( + /* translators: %s: source label or key */ + __( 'Empty %s; start writing to edit its value' ), + relatedBinding?.args?.key || blockBindingsSource?.label + ); return { disableBoundBlock: _disableBoundBlock, bindingsPlaceholder: - ( ! adjustedValue || adjustedValue.length === 0 ) && - _bindingsPlaceholder, + blockAttributes?.placeholder || _bindingsPlaceholder, + bindingsLabel: _bindingsLabel, }; }, [ @@ -421,7 +440,7 @@ export function RichTextWrapper( aria-readonly={ shouldDisableEditing } { ...props } aria-label={ - bindingsPlaceholder || props[ 'aria-label' ] || placeholder + bindingsLabel || props[ 'aria-label' ] || placeholder } { ...autocompleteProps } ref={ useMergeRefs( [ diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index 90a5d2b1da9f10..010d173e760ca9 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -1254,6 +1254,39 @@ test.describe( 'Block bindings', () => { ).toHaveText( 'fallback value' ); } ); + test( 'should prioritize the placeholder attribute over the placeholder generated by the bindings API', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + placeholder: 'My custom placeholder', + content: 'paragraph default content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { key: 'empty_field' }, + }, + }, + }, + }, + } ); + + const paragraphBlock = editor.canvas.getByRole( 'document', { + // Aria-label is changed for empty paragraphs. + name: 'Empty empty_field; start writing to edit its value', + } ); + + await expect( paragraphBlock ).toBeEmpty(); + + const placeholder = paragraphBlock.locator( 'span' ); + await expect( placeholder ).toHaveAttribute( + 'data-rich-text-placeholder', + 'My custom placeholder' + ); + } ); + test( 'should show the prompt placeholder in field with empty value', async ( { editor, } ) => { @@ -1274,7 +1307,7 @@ test.describe( 'Block bindings', () => { const paragraphBlock = editor.canvas.getByRole( 'document', { // Aria-label is changed for empty paragraphs. - name: 'Add empty_field', + name: 'Empty empty_field; start writing to edit its value', } ); await expect( paragraphBlock ).toBeEmpty(); From 67e72757fe37df24a130c17f77064ce3a213722d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor?= <27339341+priethor@users.noreply.github.com> Date: Tue, 24 Sep 2024 15:06:39 +0200 Subject: [PATCH 0934/1908] Label enforcer: add `Gutenberg plugin` to the list of single required labels (#65253) * Update enforce-pr-labels.yml * Update enforce-pr-labels.yml --- .github/workflows/enforce-pr-labels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/enforce-pr-labels.yml b/.github/workflows/enforce-pr-labels.yml index 093eb9a325e365..7493459a6ff35c 100644 --- a/.github/workflows/enforce-pr-labels.yml +++ b/.github/workflows/enforce-pr-labels.yml @@ -12,7 +12,7 @@ jobs: with: mode: exactly count: 1 - labels: '[Type] Automated Testing, [Type] Breaking Change, [Type] Bug, [Type] Build Tooling, [Type] Code Quality, [Type] Copy, [Type] Developer Documentation, [Type] Enhancement, [Type] Experimental, [Type] Feature, [Type] New API, [Type] Task, [Type] Technical Prototype, [Type] Performance, [Type] Project Management, [Type] Regression, [Type] Security, [Type] WP Core Ticket, Backport from WordPress Core' + labels: '[Type] Automated Testing, [Type] Breaking Change, [Type] Bug, [Type] Build Tooling, [Type] Code Quality, [Type] Copy, [Type] Developer Documentation, [Type] Enhancement, [Type] Experimental, [Type] Feature, [Type] New API, [Type] Task, [Type] Technical Prototype, [Type] Performance, [Type] Project Management, [Type] Regression, [Type] Security, [Type] WP Core Ticket, Backport from WordPress Core, Gutenberg Plugin' add_comment: true message: "**Warning: Type of PR label mismatch**\n\n To merge this PR, it requires {{ errorString }} {{ count }} label indicating the type of PR. Other labels are optional and not being checked here. \n- **Type-related labels to choose from**: {{ provided }}.\n- **Labels found**: {{ applied }}.\n\nRead more about [Type labels in Gutenberg](https://github.com/WordPress/gutenberg/labels?q=type). Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task." exit_type: failure From 5bb17f02d3db22cc4f1d297520d1a5642e79786c Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 24 Sep 2024 06:53:02 -0700 Subject: [PATCH 0935/1908] Blocks: Update '__experimentalHasContentRoleAttribute' deprecation (#65616) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/blocks/src/store/selectors.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/blocks/src/store/selectors.js b/packages/blocks/src/store/selectors.js index 6d38af389e3129..79e88073ba20de 100644 --- a/packages/blocks/src/store/selectors.js +++ b/packages/blocks/src/store/selectors.js @@ -828,7 +828,6 @@ export const __experimentalHasContentRoleAttribute = ( ...args ) => { deprecated( '__experimentalHasContentRoleAttribute', { since: '6.7', version: '6.8', - alternative: 'hasContentRoleAttribute', hint: 'This is a private selector.', } ); return privateHasContentRoleAttribute( ...args ); From 203880af1fb940d9656e0623afff9ca50d3128e6 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Tue, 24 Sep 2024 16:45:18 +0200 Subject: [PATCH 0936/1908] Only use `canUserEditValue` when `setValues` is defined (#65566) Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- packages/blocks/src/store/reducer.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index fbcec7a619cf63..4aa0b922e090fd 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -404,7 +404,9 @@ export function blockBindingsSources( state = {}, action ) { ), getValues: action.getValues, setValues: action.setValues, - canUserEditValue: action.canUserEditValue, + // Only set `canUserEditValue` if `setValues` is also defined. + canUserEditValue: + action.setValues && action.canUserEditValue, getFieldsList: action.getFieldsList, }, }; From f56dbeb9257c19acf6fbd8b45d87ae8a841624da Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 24 Sep 2024 08:52:52 -0700 Subject: [PATCH 0937/1908] Blocks: Don't memoize 'hasContentRoleAttribute' selector (#65617) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- .../blocks/src/store/private-selectors.js | 49 +++++++++---------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/packages/blocks/src/store/private-selectors.js b/packages/blocks/src/store/private-selectors.js index 81bdc1fca2c420..d5665323859e40 100644 --- a/packages/blocks/src/store/private-selectors.js +++ b/packages/blocks/src/store/private-selectors.js @@ -219,32 +219,27 @@ export function getBlockBindingsSource( state, sourceName ) { * @param {string} blockTypeName Block type name. * @return {boolean} Whether block type has content role attribute. */ -export const hasContentRoleAttribute = createSelector( - ( state, blockTypeName ) => { - const blockType = getBlockType( state, blockTypeName ); - if ( ! blockType ) { +export const hasContentRoleAttribute = ( state, blockTypeName ) => { + const blockType = getBlockType( state, blockTypeName ); + if ( ! blockType ) { + return false; + } + + return Object.values( blockType.attributes ).some( + ( { role, __experimentalRole } ) => { + if ( role === 'content' ) { + return true; + } + if ( __experimentalRole === 'content' ) { + deprecated( '__experimentalRole attribute', { + since: '6.7', + version: '6.8', + alternative: 'role attribute', + hint: `Check the block.json of the ${ blockTypeName } block.`, + } ); + return true; + } return false; } - - return Object.entries( blockType.attributes ).some( - ( [ , { role, __experimentalRole } ] ) => { - if ( role === 'content' ) { - return true; - } - if ( __experimentalRole === 'content' ) { - deprecated( '__experimentalRole attribute', { - since: '6.7', - version: '6.8', - alternative: 'role attribute', - hint: `Check the block.json of the ${ blockTypeName } block.`, - } ); - return true; - } - return false; - } - ); - }, - ( state, blockTypeName ) => [ - state.blockTypes[ blockTypeName ]?.attributes, - ] -); + ); +}; From 892d9a54d8c299e4819f9eb10f544967b657bbbf Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Tue, 24 Sep 2024 18:47:11 +0200 Subject: [PATCH 0938/1908] Export `useResizeObserver` React Native version directly (#65588) * Export React Native version. * Add changelog entry * Simplify re-export. Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/compose/CHANGELOG.md | 4 ++++ .../compose/src/hooks/use-resize-observer/index.native.js | 1 + 2 files changed, 5 insertions(+) create mode 100644 packages/compose/src/hooks/use-resize-observer/index.native.js diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index 18c21a65b9b124..28269dca692a4f 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- `useResizeObserver`: export legacy API at top-level for React Native ([#65588](https://github.com/WordPress/gutenberg/pull/65588)). + ## 7.8.0 (2024-09-19) ### New Features diff --git a/packages/compose/src/hooks/use-resize-observer/index.native.js b/packages/compose/src/hooks/use-resize-observer/index.native.js new file mode 100644 index 00000000000000..79eb3e569e332a --- /dev/null +++ b/packages/compose/src/hooks/use-resize-observer/index.native.js @@ -0,0 +1 @@ +export { default } from './legacy/index.native'; From c1fe4824c1b961006921f697b8c8c85de3694d97 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 24 Sep 2024 18:12:41 +0100 Subject: [PATCH 0939/1908] Inserter: Always show the list of all patterns in the inserter (#65611) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../inserter/hooks/use-patterns-state.js | 69 ++++++++++++++++--- .../src/components/inserter/menu.js | 4 +- .../src/components/inserter/quick-inserter.js | 5 +- .../src/store/private-selectors.js | 35 ++++++++-- .../editor/various/allowed-patterns.spec.js | 13 ++-- 5 files changed, 101 insertions(+), 25 deletions(-) diff --git a/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js b/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js index f8b083d4eedf19..13dae7f2ed7c0d 100644 --- a/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js +++ b/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js @@ -11,33 +11,66 @@ import { store as noticesStore } from '@wordpress/notices'; * Internal dependencies */ import { store as blockEditorStore } from '../../../store'; +import { unlock } from '../../../lock-unlock'; import { INSERTER_PATTERN_TYPES } from '../block-patterns-tab/utils'; +import { getParsedPattern } from '../../../store/utils'; /** * Retrieves the block patterns inserter state. * * @param {Function} onInsert function called when inserter a list of blocks. * @param {string=} rootClientId Insertion's root client ID. - * * @param {string} selectedCategory The selected pattern category. + * @param {boolean} isQuick For the quick inserter render only allowed patterns. + * * @return {Array} Returns the patterns state. (patterns, categories, onSelect handler) */ -const usePatternsState = ( onInsert, rootClientId, selectedCategory ) => { - const { patternCategories, patterns, userPatternCategories } = useSelect( +const usePatternsState = ( + onInsert, + rootClientId, + selectedCategory, + isQuick +) => { + const { patternCategories, allPatterns, userPatternCategories } = useSelect( ( select ) => { - const { __experimentalGetAllowedPatterns, getSettings } = - select( blockEditorStore ); + const { + getAllPatterns, + getSettings, + __experimentalGetAllowedPatterns, + } = unlock( select( blockEditorStore ) ); const { __experimentalUserPatternCategories, __experimentalBlockPatternCategories, } = getSettings(); return { - patterns: __experimentalGetAllowedPatterns( rootClientId ), + allPatterns: isQuick + ? __experimentalGetAllowedPatterns() + : getAllPatterns(), userPatternCategories: __experimentalUserPatternCategories, patternCategories: __experimentalBlockPatternCategories, }; }, - [ rootClientId ] + [ isQuick ] + ); + const { getClosestAllowedInsertionPointForPattern } = unlock( + useSelect( blockEditorStore ) + ); + + const patterns = useMemo( + () => + isQuick + ? allPatterns + : allPatterns + .filter( ( { inserter = true } ) => !! inserter ) + .map( ( pattern ) => { + return { + ...pattern, + get blocks() { + return getParsedPattern( pattern ).blocks; + }, + }; + } ), + [ isQuick, allPatterns ] ); const allCategories = useMemo( () => { @@ -58,6 +91,15 @@ const usePatternsState = ( onInsert, rootClientId, selectedCategory ) => { const { createSuccessNotice } = useDispatch( noticesStore ); const onClickPattern = useCallback( ( pattern, blocks ) => { + const destinationRootClientId = isQuick + ? rootClientId + : getClosestAllowedInsertionPointForPattern( + pattern, + rootClientId + ); + if ( destinationRootClientId === null ) { + return; + } const patternBlocks = pattern.type === INSERTER_PATTERN_TYPES.user && pattern.syncStatus !== 'unsynced' @@ -77,7 +119,9 @@ const usePatternsState = ( onInsert, rootClientId, selectedCategory ) => { } return clonedBlock; } ), - pattern.name + pattern.name, + false, + destinationRootClientId ); createSuccessNotice( sprintf( @@ -91,7 +135,14 @@ const usePatternsState = ( onInsert, rootClientId, selectedCategory ) => { } ); }, - [ createSuccessNotice, onInsert, selectedCategory ] + [ + createSuccessNotice, + onInsert, + selectedCategory, + rootClientId, + getClosestAllowedInsertionPointForPattern, + isQuick, + ] ); return [ patterns, allCategories, onClickPattern ]; diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index faf2c20514f67a..4bc26196cb5243 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -114,9 +114,9 @@ function InserterMenu( ); const onInsertPattern = useCallback( - ( blocks, patternName ) => { + ( blocks, patternName, ...args ) => { onToggleInsertionPoint( false ); - onInsertBlocks( blocks, { patternName } ); + onInsertBlocks( blocks, { patternName }, ...args ); onSelect(); }, [ onInsertBlocks, onSelect ] diff --git a/packages/block-editor/src/components/inserter/quick-inserter.js b/packages/block-editor/src/components/inserter/quick-inserter.js index 4a79ad6b1f083c..f40af12feddf4f 100644 --- a/packages/block-editor/src/components/inserter/quick-inserter.js +++ b/packages/block-editor/src/components/inserter/quick-inserter.js @@ -47,10 +47,11 @@ export default function QuickInserter( { onInsertBlocks, true ); - const [ patterns ] = usePatternsState( onInsertBlocks, - destinationRootClientId + destinationRootClientId, + undefined, + true ); const { setInserterIsOpened, insertionIndex } = useSelect( diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 02a37b94ec27ff..a98c5af93c86a9 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -642,24 +642,30 @@ export function isZoomOut( state ) { /** * Finds the closest block where the block is allowed to be inserted. * - * @param {Object} state Editor state. - * @param {string} name Block name. - * @param {string} clientId Default insertion point. + * @param {Object} state Editor state. + * @param {string[] | string} name Block name or names. + * @param {string} clientId Default insertion point. * * @return {string} clientID of the closest container when the block name can be inserted. */ export function getClosestAllowedInsertionPoint( state, name, clientId = '' ) { + const blockNames = Array.isArray( name ) ? name : [ name ]; + const areBlockNamesAllowedInClientId = ( id ) => + blockNames.every( ( currentName ) => + canInsertBlockType( state, currentName, id ) + ); + // If we're trying to insert at the root level and it's not allowed // Try the section root instead. if ( ! clientId ) { - if ( canInsertBlockType( state, name, clientId ) ) { + if ( areBlockNamesAllowedInClientId( clientId ) ) { return clientId; } const sectionRootClientId = getSectionRootClientId( state ); if ( sectionRootClientId && - canInsertBlockType( state, name, sectionRootClientId ) + areBlockNamesAllowedInClientId( sectionRootClientId ) ) { return sectionRootClientId; } @@ -668,10 +674,27 @@ export function getClosestAllowedInsertionPoint( state, name, clientId = '' ) { // Traverse the block tree up until we find a place where we can insert. let current = clientId; - while ( current !== null && ! canInsertBlockType( state, name, current ) ) { + while ( current !== null && ! areBlockNamesAllowedInClientId( current ) ) { const parentClientId = getBlockRootClientId( state, current ); current = parentClientId; } return current; } + +export function getClosestAllowedInsertionPointForPattern( + state, + pattern, + clientId +) { + const { allowedBlockTypes } = getSettings( state ); + const isAllowed = checkAllowListRecursive( + getGrammar( pattern ), + allowedBlockTypes + ); + if ( ! isAllowed ) { + return null; + } + const names = getGrammar( pattern ).map( ( { blockName: name } ) => name ); + return getClosestAllowedInsertionPoint( state, names, clientId ); +} diff --git a/test/e2e/specs/editor/various/allowed-patterns.spec.js b/test/e2e/specs/editor/various/allowed-patterns.spec.js index e592f776c61dd8..894f143d19bb82 100644 --- a/test/e2e/specs/editor/various/allowed-patterns.spec.js +++ b/test/e2e/specs/editor/various/allowed-patterns.spec.js @@ -14,10 +14,7 @@ test.describe( 'Allowed Patterns', () => { ); } ); - test( 'should show all patterns when all blocks are allowed', async ( { - admin, - page, - } ) => { + test( 'should show all patterns by default', async ( { admin, page } ) => { await admin.createNewPost(); await page .getByRole( 'toolbar', { name: 'Document tools' } ) @@ -57,7 +54,7 @@ test.describe( 'Allowed Patterns', () => { ); } ); - test( 'should show only allowed patterns', async ( { + test( 'should show all patterns even if not allowed', async ( { admin, page, } ) => { @@ -80,7 +77,11 @@ test.describe( 'Allowed Patterns', () => { page .getByRole( 'listbox', { name: 'Block patterns' } ) .getByRole( 'option' ) - ).toHaveText( [ 'Test: Single heading' ] ); + ).toHaveText( [ + 'Test: Single heading', + 'Test: Single paragraph', + 'Test: Paragraph inside group', + ] ); } ); } ); } ); From 8178234dc3e99c2bf81c9591167e157c12c043de Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 25 Sep 2024 09:55:26 +1000 Subject: [PATCH 0940/1908] Revert "DataViews Sidebar: Display item count on DataViews sidebar" (#65625) This reverts commit 338940a77d5b9152f276e5ec31db01b4ba2d7332. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- .../sidebar-dataviews/dataview-item.js | 2 - .../sidebar-dataviews/default-views.js | 46 +------------------ .../src/components/sidebar-dataviews/index.js | 9 +--- .../components/sidebar-dataviews/style.scss | 4 -- 4 files changed, 3 insertions(+), 58 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js b/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js index 1a96fdc0591439..1e12d6706d81b5 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js +++ b/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js @@ -27,7 +27,6 @@ export default function DataViewItem( { isActive, isCustom, suffix, - navigationItemSuffix, } ) { const { params: { postType }, @@ -56,7 +55,6 @@ export default function DataViewItem( { <SidebarNavigationItem icon={ iconToUse } { ...linkInfo } - suffix={ navigationItemSuffix } aria-current={ isActive ? 'true' : undefined } > { title } diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 20f61e451b21fa..658fa319e9c667 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -13,7 +13,7 @@ import { notAllowed, } from '@wordpress/icons'; import { useSelect } from '@wordpress/data'; -import { store as coreStore, useEntityRecords } from '@wordpress/core-data'; +import { store as coreStore } from '@wordpress/core-data'; import { useMemo } from '@wordpress/element'; /** @@ -68,50 +68,6 @@ const DEFAULT_POST_BASE = { layout: defaultLayouts[ LAYOUT_LIST ].layout, }; -export function useDefaultViewsWithItemCounts( { postType } ) { - const defaultViews = useDefaultViews( { postType } ); - const { records, totalItems } = useEntityRecords( 'postType', postType, { - per_page: -1, - status: [ 'any', 'trash' ], - } ); - - return useMemo( () => { - if ( ! defaultViews ) { - return []; - } - - // If there are no records, return the default views with no counts. - if ( ! records ) { - return defaultViews; - } - - const counts = { - drafts: records.filter( ( record ) => record.status === 'draft' ) - .length, - future: records.filter( ( record ) => record.status === 'future' ) - .length, - pending: records.filter( ( record ) => record.status === 'pending' ) - .length, - private: records.filter( ( record ) => record.status === 'private' ) - .length, - published: records.filter( - ( record ) => record.status === 'publish' - ).length, - trash: records.filter( ( record ) => record.status === 'trash' ) - .length, - }; - - // All items excluding trashed items as per the default "all" status query. - counts.all = totalItems ? totalItems - counts.trash : 0; - - // Filter out views with > 0 item counts. - return defaultViews.map( ( _view ) => { - _view.count = counts[ _view.slug ]; - return _view; - } ); - }, [ defaultViews, records, totalItems ] ); -} - export function useDefaultViews( { postType } ) { const labels = useSelect( ( select ) => { diff --git a/packages/edit-site/src/components/sidebar-dataviews/index.js b/packages/edit-site/src/components/sidebar-dataviews/index.js index 3f7f5b965fce71..86420c4eec1d1f 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/index.js +++ b/packages/edit-site/src/components/sidebar-dataviews/index.js @@ -7,7 +7,7 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies */ -import { useDefaultViewsWithItemCounts } from './default-views'; +import { useDefaultViews } from './default-views'; import { unlock } from '../../lock-unlock'; import DataViewItem from './dataview-item'; import CustomDataViewsList from './custom-dataviews-list'; @@ -18,9 +18,7 @@ export default function DataViewsSidebarContent() { const { params: { postType, activeView = 'all', isCustom = 'false' }, } = useLocation(); - - const defaultViews = useDefaultViewsWithItemCounts( { postType } ); - + const defaultViews = useDefaultViews( { postType } ); if ( ! postType ) { return null; } @@ -36,9 +34,6 @@ export default function DataViewsSidebarContent() { slug={ dataview.slug } title={ dataview.title } icon={ dataview.icon } - navigationItemSuffix={ - <span>{ dataview.count }</span> - } type={ dataview.view.type } isActive={ ! isCustomBoolean && diff --git a/packages/edit-site/src/components/sidebar-dataviews/style.scss b/packages/edit-site/src/components/sidebar-dataviews/style.scss index 3473c8e20e1a45..14e6bf1d03fca8 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/style.scss +++ b/packages/edit-site/src/components/sidebar-dataviews/style.scss @@ -15,10 +15,6 @@ min-width: initial; } - .edit-site-sidebar-navigation-item.with-suffix { - padding-right: $grid-unit-10; - } - &:hover, &:focus, &[aria-current] { From 1dc56a9873668194a7c50849ee2e22d3d89c8f1c Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 25 Sep 2024 12:49:51 +1000 Subject: [PATCH 0941/1908] Header: remove unused property `isZoomedOutView` in `useSelect()` (#65628) Some light formatting/spelling changes Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- .../editor/src/components/header/index.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index fb034ba8bb8574..aca91daaac7324 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -7,7 +7,6 @@ import { __unstableMotion as motion } from '@wordpress/components'; import { store as preferencesStore } from '@wordpress/preferences'; import { useState } from '@wordpress/element'; import { PinnedItems } from '@wordpress/interface'; -import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Internal dependencies @@ -65,7 +64,6 @@ function Header( { getEditorSettings, isPublishSidebarOpened: _isPublishSidebarOpened, } = select( editorStore ); - const { __unstableGetEditorMode } = select( blockEditorStore ); return { isTextEditor: getEditorMode() === 'text', @@ -74,7 +72,6 @@ function Header( { hasFixedToolbar: getPreference( 'core', 'fixedToolbar' ), isNestedEntity: !! getEditorSettings().onNavigateToPreviousEntityRecord, - isZoomedOutView: __unstableGetEditorMode() === 'zoom-out', }; }, [] ); @@ -83,9 +80,10 @@ function Header( { const hasCenter = isBlockToolsCollapsed && ! isTooNarrowForDocumentBar; const hasBackButton = useHasBackButton(); - - // The edit-post-header classname is only kept for backward compatibilty - // as some plugins might be relying on its presence. + /* + * The edit-post-header classname is only kept for backward compatability + * as some plugins might be relying on its presence. + */ return ( <div className="editor-header edit-post-header"> { hasBackButton && ( @@ -127,11 +125,13 @@ function Header( { className="editor-header__settings" > { ! customSaveButton && ! isPublishSidebarOpened && ( - // This button isn't completely hidden by the publish sidebar. - // We can't hide the whole toolbar when the publish sidebar is open because - // we want to prevent mounting/unmounting the PostPublishButtonOrToggle DOM node. - // We track that DOM node to return focus to the PostPublishButtonOrToggle - // when the publish sidebar has been closed. + /* + * This button isn't completely hidden by the publish sidebar. + * We can't hide the whole toolbar when the publish sidebar is open because + * we want to prevent mounting/unmounting the PostPublishButtonOrToggle DOM node. + * We track that DOM node to return focus to the PostPublishButtonOrToggle + * when the publish sidebar has been closed. + */ <PostSavedState forceIsDirty={ forceIsDirty } /> ) } <PreviewDropdown From b5129a24f8d4f272cf6c21d208f6157af17eb2b0 Mon Sep 17 00:00:00 2001 From: Carolina Nymark <myazalea@hotmail.com> Date: Wed, 25 Sep 2024 05:28:41 +0200 Subject: [PATCH 0942/1908] Query loop format controls: Fix JavaScript error (#65551) Fixes a JavaScript error in FormatControls by ensuring that the correct constant is used when populating the suggestions in the FormTokenField. Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- .../src/query/edit/inspector-controls/format-controls.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/query/edit/inspector-controls/format-controls.js b/packages/block-library/src/query/edit/inspector-controls/format-controls.js index d26fd9d81ce6f7..15c95f3bbba2e2 100644 --- a/packages/block-library/src/query/edit/inspector-controls/format-controls.js +++ b/packages/block-library/src/query/edit/inspector-controls/format-controls.js @@ -68,7 +68,7 @@ export default function FormatControls( { onChange, query: { format } } ) { .filter( Boolean ); const suggestions = formats - .filter( ( item ) => ! format.includes( item.value ) ) + .filter( ( item ) => ! normalizedFormats.includes( item.value ) ) .map( ( item ) => item.label ); return ( From e94673a356b9231028642c105ae20deb76b76b9d Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 25 Sep 2024 15:39:12 +1000 Subject: [PATCH 0943/1908] PHP unit tests: remove WP_RUN_CORE_TESTS const (#65631) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- phpunit/bootstrap.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/phpunit/bootstrap.php b/phpunit/bootstrap.php index 5d078193f0c3bf..36746d05669519 100644 --- a/phpunit/bootstrap.php +++ b/phpunit/bootstrap.php @@ -24,12 +24,6 @@ define( 'GUTENBERG_DIR_TESTDATA', __DIR__ . '/data/' ); define( 'GUTENBERG_DIR_TESTFIXTURES', __DIR__ . '/fixtures/' ); -// Pretend that these are Core unit tests. This is needed so that -// wp_theme_has_theme_json() does not cache its return value between each test. -if ( ! defined( 'WP_RUN_CORE_TESTS' ) ) { - define( 'WP_RUN_CORE_TESTS', true ); -} - // Require composer dependencies. require_once dirname( __DIR__ ) . '/vendor/autoload.php'; From f8dd3338651cdd81d1c4b9e5e98b514034526070 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 25 Sep 2024 05:50:51 +0000 Subject: [PATCH 0944/1908] Bump plugin version to 19.3.0 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index e15cb113ea65a1..466509dcf6b585 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.3.0-rc.2 + * Version: 19.3.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index f5293bdf00ca04..a40aa8aab49340 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.3.0-rc.2", + "version": "19.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.3.0-rc.2", + "version": "19.3.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 4b81f249be76c2..5ecd0ef57b3516 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.3.0-rc.2", + "version": "19.3.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 15455d698a27852048bfdf84768c776f511477e2 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 25 Sep 2024 06:00:10 +0000 Subject: [PATCH 0945/1908] Update Changelog for 19.3.0 --- changelog.txt | 285 ++------------------------------------------------ 1 file changed, 7 insertions(+), 278 deletions(-) diff --git a/changelog.txt b/changelog.txt index b04fa0e9bbf8e2..b802a88a14202c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,6 @@ == Changelog == -= 19.3.0-rc.2 = += 19.3.0 = ## Changelog @@ -22,6 +22,7 @@ - Patterns: Add opt out preference to the 'Choose a Pattern' modal when adding a page. ([65026](https://github.com/WordPress/gutenberg/pull/65026)) - Locked Templates: Blocks with contentOnly locking should not be transformable. ([64917](https://github.com/WordPress/gutenberg/pull/64917)) - Block Locking: Add border to Replace item in content only image toolbar. ([64849](https://github.com/WordPress/gutenberg/pull/64849)) +- DataViews: Improve UX of bundled views for Pages. ([65295](https://github.com/WordPress/gutenberg/pull/65295)) #### Components - Styling: Apply elevation scale in components package. ([65159](https://github.com/WordPress/gutenberg/pull/65159)) @@ -49,7 +50,6 @@ #### Block Editor - Link Editing: Automatically add tel to phone number when linking URL. ([64865](https://github.com/WordPress/gutenberg/pull/64865)) -thub.com/WordPress/gutenberg/pull/65300)) - Drag and Drop: When dragging a mix of video, audio, and image blocks, create individual blocks as appropriate. ([65144](https://github.com/WordPress/gutenberg/pull/65144)) - URLInput: Replace input with InputControl. ([65158](https://github.com/WordPress/gutenberg/pull/65158)) - Normalize block inspector controls spacing. ([64526](https://github.com/WordPress/gutenberg/pull/64526)) @@ -69,10 +69,6 @@ thub.com/WordPress/gutenberg/pull/65300)) - Refactor site background controls and move site global styles into Background group. ([65304](https://github.com/WordPress/gutenberg/pull/65304)) - Spacing control: Replace sides dropdwon with link button. ([65193](https://github.com/WordPress/gutenberg/pull/65193)) -#### Data Views -- DataViews Sidebar: Display item count on DataViews sidebar. ([65223](https://github.com/WordPress/gutenberg/pull/65223)) -- DataViews: Improve UX of bundled views for Pages. ([65295](https://github.com/WordPress/gutenberg/pull/65295)) - #### Interactivity API - Refactor context proxies. ([64713](https://github.com/WordPress/gutenberg/pull/64713)) - Update: Rephrase "Force page reload" and move to Advanced. ([65081](https://github.com/WordPress/gutenberg/pull/65081)) @@ -122,13 +118,14 @@ thub.com/WordPress/gutenberg/pull/65300)) - Query Loop - Default to querying posts when on singular content. ([65067](https://github.com/WordPress/gutenberg/pull/65067)) - Remove is_singular() check and fix test. ([65483](https://github.com/WordPress/gutenberg/pull/65483)) + - Format controls: Fix JavaScript error. ([65551](https://github.com/WordPress/gutenberg/pull/65551)) #### Block Editor - Inserter: Fix loading indicator for reusable blocks. ([64839](https://github.com/WordPress/gutenberg/pull/64839)) - Normalize spacing in Layout hook controls. ([65132](https://github.com/WordPress/gutenberg/pull/65132)) - Pattern Inserter: Fix pattern list overflow. ([65192](https://github.com/WordPress/gutenberg/pull/65192)) - Remove reset styles RTL from the iframe. ([65150](https://github.com/WordPress/gutenberg/pull/65150)) -- Revert "Block Insertion: Clear the insertion point when selecting a d…. ([65208](https://github.com/WordPress/gutenberg/pull/65208)) +- Revert "Block Insertion: Clear the insertion point when selecting a different block or clearing block selection (https://github.com/WordPress/gutenberg/pull/64048)" ([65208](https://github.com/WordPress/gutenberg/pull/65208)) #### Components - BoxControl: Unify input filed width whether linked or not. ([65348](https://github.com/WordPress/gutenberg/pull/65348)) @@ -139,6 +136,9 @@ thub.com/WordPress/gutenberg/pull/65300)) #### Block bindings - Fix empty strings placeholders in post meta bindings. ([65089](https://github.com/WordPress/gutenberg/pull/65089)) - Remove key fallback in bindings get values and rely on source label. ([65517](https://github.com/WordPress/gutenberg/pull/65517)) +- Fix passing bindings context to `canUserEditValue`. ([65599](https://github.com/WordPress/gutenberg/pull/65599)) +- Prioritize existing placeholder over bindingsPlaceholder. ([65220](https://github.com/WordPress/gutenberg/pull/65220)) +- Only use `canUserEditValue` when `setValues` is defined. ([65565](https://github.com/WordPress/gutenberg/pull/65566)) #### Zoom Out - Force device type to Desktop whenever zoom out is invoked. ([64476](https://github.com/WordPress/gutenberg/pull/64476)) @@ -275,277 +275,6 @@ The following contributors merged PRs in this release: @aaronrobertshaw @afercia @AKSHAT2802 @Aljullu @andrewserong @carolinan @cbravobernal @ciampo @colorful-tones @creativecoder @DaniGuardiola @DAreRodz @devansh016 @dhruvang21 @ellatrix @farid-hadi @getdave @gigitux @greenworld @gziolo @hbhalodia @jameskoster @jasmussen @javierarce @jeryj @jorgefilipecosta @jsnajdr @kevin940726 @louwie17 @madhusudhand @MaggieCabrera @Mamaduka @mikeybinns @mirka @ntsekouras @oandregal @ockham @peterwilsoncc @rahulharpal1603 @ramonjd @richtabor @rohitmathur-7 @SantosGuillamot @scruffian @sgomes @sirreal @stokesman @swissspidy @t-hamano @talldan @vipul0425 @zaguiini -= 19.3.0-rc.1 = - -## Changelog - -### Features - -#### Zoom Out -- Remove experimental flag. ([65404](https://github.com/WordPress/gutenberg/pull/65404)) - -### Enhancements - -- Create Block: Update the minimum required PHP version to 7.2. ([65166](https://github.com/WordPress/gutenberg/pull/65166)) -- DataViews: remove unused `.dataviews-view-table__cell-content-wrapper:Empty` style rule. ([65084](https://github.com/WordPress/gutenberg/pull/65084)) -- Media Utils: Add TypeScript support and export more utils. ([64784](https://github.com/WordPress/gutenberg/pull/64784)) -- Media placeholders: Add "drag" to the text. ([65149](https://github.com/WordPress/gutenberg/pull/65149)) -- Restore: Move to trash button in Document settings. ([65087](https://github.com/WordPress/gutenberg/pull/65087)) -- Inspector Controls: Use custom block name in inspector controls when available. ([65398](https://github.com/WordPress/gutenberg/pull/65398)) -- Plugin: Don't force iframe editor when gutenberg plugin and block theme are enabled. ([65372](https://github.com/WordPress/gutenberg/pull/65372)) -- Icons: Adds bell and bell-unread icons. ([65324](https://github.com/WordPress/gutenberg/pull/65324)) -- Editor topbar: Reorder the actions on the right. ([65163](https://github.com/WordPress/gutenberg/pull/65163)) -- Patterns: Add opt out preference to the 'Choose a Pattern' modal when adding a page. ([65026](https://github.com/WordPress/gutenberg/pull/65026)) -- Locked Templates: Blocks with contentOnly locking should not be transformable. ([64917](https://github.com/WordPress/gutenberg/pull/64917)) -- Block Locking: Add border to Replace item in content only image toolbar. ([64849](https://github.com/WordPress/gutenberg/pull/64849)) - -#### Components -- Styling: Apply elevation scale in components package. ([65159](https://github.com/WordPress/gutenberg/pull/65159)) -- Tabs: Improve Tabs indicator animation and related utils. ([64926](https://github.com/WordPress/gutenberg/pull/64926)) -- Modal - - Add exit animation. ([65203](https://github.com/WordPress/gutenberg/pull/65203)) - - Decrease close button size. ([65131](https://github.com/WordPress/gutenberg/pull/65131)) -- Navigator Screen: Warn if path doesn't follow a URL-like scheme. ([65231](https://github.com/WordPress/gutenberg/pull/65231)) -- Card: Update Card radius. ([65053](https://github.com/WordPress/gutenberg/pull/65053)) -- Combobox Control: Add placeholder attribute. ([65254](https://github.com/WordPress/gutenberg/pull/65254)) - -#### Block Library -- Allow dropping multiple images to the image block. ([65030](https://github.com/WordPress/gutenberg/pull/65030)) -- Categories List block: Add dropdown for taxonomies. ([65272](https://github.com/WordPress/gutenberg/pull/65272)) -- Image: Adds the block controls for uploading image. ([64320](https://github.com/WordPress/gutenberg/pull/64320)) -- Remove colons from control labels. ([65205](https://github.com/WordPress/gutenberg/pull/65205)) -- Terms List block: Add Categories-specific variation. ([65434](https://github.com/WordPress/gutenberg/pull/65434)) - -#### Zoom Out -- Add Zoom Out toggle to editor header when experiment enabled. ([65183](https://github.com/WordPress/gutenberg/pull/65183)) -- Add prompt for drag and drop in Patterns tab in Zoom Out mode. ([65115](https://github.com/WordPress/gutenberg/pull/65115)) -- Close inserter on exiting Zoom Out to edit. ([65194](https://github.com/WordPress/gutenberg/pull/65194)) -- Show top level sections in List View. ([65202](https://github.com/WordPress/gutenberg/pull/65202)) -- Try vertical displacement when dragging a pattern between existing patterns/sections. ([63896](https://github.com/WordPress/gutenberg/pull/63896)) - -#### Block Editor -- Link Editing: Automatically add tel to phone number when linking URL. ([64865](https://github.com/WordPress/gutenberg/pull/64865)) -thub.com/WordPress/gutenberg/pull/65300)) -- Drag and Drop: When dragging a mix of video, audio, and image blocks, create individual blocks as appropriate. ([65144](https://github.com/WordPress/gutenberg/pull/65144)) -- URLInput: Replace input with InputControl. ([65158](https://github.com/WordPress/gutenberg/pull/65158)) -- Normalize block inspector controls spacing. ([64526](https://github.com/WordPress/gutenberg/pull/64526)) - -#### Post Editor -- Add new Media section to preferences modal. ([64846](https://github.com/WordPress/gutenberg/pull/64846)) -- DocumentBar: Replace icon with post type label. ([65170](https://github.com/WordPress/gutenberg/pull/65170)) -- Page editor: Double-click to edit template part. ([65024](https://github.com/WordPress/gutenberg/pull/65024)) -- Post publish upload media dialog: Handle more block types. ([65122](https://github.com/WordPress/gutenberg/pull/65122)) - -#### Block bindings -- Populate block context with inherited post type from template slug. ([65062](https://github.com/WordPress/gutenberg/pull/65062)) -- Try gap 0 on attribute items. ([65277](https://github.com/WordPress/gutenberg/pull/65277)) -- Use post meta label from `register_meta` in block bindings workflows. ([65099](https://github.com/WordPress/gutenberg/pull/65099)) - -#### Global Styles -- Refactor site background controls and move site global styles into Background group. ([65304](https://github.com/WordPress/gutenberg/pull/65304)) -- Spacing control: Replace sides dropdwon with link button. ([65193](https://github.com/WordPress/gutenberg/pull/65193)) - -#### Data Views -- DataViews Sidebar: Display item count on DataViews sidebar. ([65223](https://github.com/WordPress/gutenberg/pull/65223)) -- DataViews: Improve UX of bundled views for Pages. ([65295](https://github.com/WordPress/gutenberg/pull/65295)) - -#### Interactivity API -- Refactor context proxies. ([64713](https://github.com/WordPress/gutenberg/pull/64713)) -- Update: Rephrase "Force page reload" and move to Advanced. ([65081](https://github.com/WordPress/gutenberg/pull/65081)) - -#### REST API -- Global Styles: Allow read access to users with `edit_posts` capabilities. ([65071](https://github.com/WordPress/gutenberg/pull/65071)) -- Query loop / Post template: Enable post format filter. ([64167](https://github.com/WordPress/gutenberg/pull/64167)) - -### New APIs -- Add @wordpress/fields package. - - Introduce the package. ([65230](https://github.com/WordPress/gutenberg/pull/65230)) - - Make the package private. ([65269](https://github.com/WordPress/gutenberg/pull/65269)) - -### Bug Fixes - -- Align popover alt variant styling with block toolbar. ([65263](https://github.com/WordPress/gutenberg/pull/65263)) -- Compose: Correctly call timer cleanup in 'useFocusOnMount'. ([65184](https://github.com/WordPress/gutenberg/pull/65184)) -- Fix some docblock types related to the Template Registration API. ([65187](https://github.com/WordPress/gutenberg/pull/65187)) -- Fix the issue where block spacing control not shown. ([65371](https://github.com/WordPress/gutenberg/pull/65371)) -- Fix unintentional block toolbar shadow. ([65182](https://github.com/WordPress/gutenberg/pull/65182)) -- Fix: Moving a page to the trash on the site editor does not goes back to the pages list. ([65119](https://github.com/WordPress/gutenberg/pull/65119)) -- Fix: Moving the last page item to the the trash causes a crash. ([65236](https://github.com/WordPress/gutenberg/pull/65236)) -- Preferences: Fix back button on mobile. ([65141](https://github.com/WordPress/gutenberg/pull/65141)) -- Revert "Don't force iframe editor when gutenberg plugin and block the me are enabled (#65372)". ([65402](https://github.com/WordPress/gutenberg/pull/65402)) -- Post Summary Panel: Restore `height:Auto` for toggle buttons. ([65362](https://github.com/WordPress/gutenberg/pull/65362)) -- Fix Tabs styling in Font Library modal. ([65330](https://github.com/WordPress/gutenberg/pull/65330)) -- E2E: Change deprecated social icons for standard in end-to-end. ([65312](https://github.com/WordPress/gutenberg/pull/65312)) -- Typography: Make title blocks apply typographic styles consistently. ([65307](https://github.com/WordPress/gutenberg/pull/65307)) -- Target Hints REST API: Add missing param sanitization. ([65280](https://github.com/WordPress/gutenberg/pull/65280)) -- Interactivity API: Update iterable signals when `deepMerge()` adds new properties. ([65135](https://github.com/WordPress/gutenberg/pull/65135)) -- Navigation Menus: Typography styling support to the navigation submenu block. ([65060](https://github.com/WordPress/gutenberg/pull/65060)) -- Grid: In RTL languages, the resize handles point in the opposite direction. ([64995](https://github.com/WordPress/gutenberg/pull/64995)) -- Block Locking: Fix Content Only Toolbar icon focus style. ([64940](https://github.com/WordPress/gutenberg/pull/64940)) -- Image: Fix resizing to max width in classic themes. ([64819](https://github.com/WordPress/gutenberg/pull/64819)) -- Meta Boxes: Try split content view. ([64351](https://github.com/WordPress/gutenberg/pull/64351)) -- Distraction Free: Fix blurry edge along editor header. ([64277](https://github.com/WordPress/gutenberg/pull/64277)) - -#### Block Library -- Comments Pagination: Fix warning returned by comments pagination blocks. ([65435](https://github.com/WordPress/gutenberg/pull/65435)) -- Cover: Explicitly set isUserOverlayColor to false when media is updated. ([65105](https://github.com/WordPress/gutenberg/pull/65105)) -- Disallow setting grid block rows/columns to zero. ([65217](https://github.com/WordPress/gutenberg/pull/65217)) -- Fix image block crash. ([65222](https://github.com/WordPress/gutenberg/pull/65222)) -- Fix: Buttons block: Block spacing value does not apply to both vertical and horizontal alignment. ([64971](https://github.com/WordPress/gutenberg/pull/64971)) -- Fix: Embed blocks: Figcaption inserted via toolbar not nested within figure element - #64960. ([64970](https://github.com/WordPress/gutenberg/pull/64970)) -- Image cropping: Skip making an API request if there are no changes to apply. ([65384](https://github.com/WordPress/gutenberg/pull/65384)) -- Comments Pagination: Pass the comments query `paged` arg to functions `get_next_comments_link` and `get_previous_comments_link`. ([63698](https://github.com/WordPress/gutenberg/pull/63698)) -- Query Loop: Default to querying posts when on singular content. ([65067](https://github.com/WordPress/gutenberg/pull/65067)) - -#### Block Editor -- Inserter: Fix loading indicator for reusable blocks. ([64839](https://github.com/WordPress/gutenberg/pull/64839)) -- Normalize spacing in Layout hook controls. ([65132](https://github.com/WordPress/gutenberg/pull/65132)) -- Pattern Inserter: Fix pattern list overflow. ([65192](https://github.com/WordPress/gutenberg/pull/65192)) -- Remove reset styles RTL from the iframe. ([65150](https://github.com/WordPress/gutenberg/pull/65150)) -- Revert "Block Insertion: Clear the insertion point when selecting a d…. ([65208](https://github.com/WordPress/gutenberg/pull/65208)) - -#### Components -- BoxControl: Unify input filed width whether linked or not. ([65348](https://github.com/WordPress/gutenberg/pull/65348)) -- ComboboxControl: Add more unit tests. ([65255](https://github.com/WordPress/gutenberg/pull/65255)) -- Fix: Button Replace remaining 40px default size violations [Edit widgets]. ([65367](https://github.com/WordPress/gutenberg/pull/65367)) -- Tabs: Fix vertical indicator. ([65385](https://github.com/WordPress/gutenberg/pull/65385)) - -#### Block bindings -- Fix empty strings placeholders in post meta bindings. ([65089](https://github.com/WordPress/gutenberg/pull/65089)) -- Prioritize existing `placeholder` over `bindingsPlaceholder`. ([65154](https://github.com/WordPress/gutenberg/pull/65154)) -- Revert "Block Bindings: Prioritize existing `placeholder` over `bindingsPlaceholder`". ([65190](https://github.com/WordPress/gutenberg/pull/65190)) - -#### Zoom Out -- Force device type to Desktop whenever zoom out is invoked. ([64476](https://github.com/WordPress/gutenberg/pull/64476)) -- Hide toolbar icon on smaller viewports. ([65437](https://github.com/WordPress/gutenberg/pull/65437)) -- Remove zoom out toggle when editor is not iframed. ([65452](https://github.com/WordPress/gutenberg/pull/65452)) - -### Accessibility - -- A11y: Add script-module. ([65101](https://github.com/WordPress/gutenberg/pull/65101)) -- Interactivity API: Use a11y Script Module in Gutenberg. ([65123](https://github.com/WordPress/gutenberg/pull/65123)) -- Script Modules API: Print script module live regions HTML in page HTML. ([65380](https://github.com/WordPress/gutenberg/pull/65380)) -- Post Editor: Support keyboard resizing of meta boxes pane. ([65325](https://github.com/WordPress/gutenberg/pull/65325)) -- DatePicker: Better hover/focus styles. ([65117](https://github.com/WordPress/gutenberg/pull/65117)) -- Form Input: Don't use `flex-direction: Row-reverse` for checkbox field. ([64232](https://github.com/WordPress/gutenberg/pull/64232)) -- Navigation Menus: Remove Warning and add notice for Navigation. ([63921](https://github.com/WordPress/gutenberg/pull/63921)) -- Global Styles: Fix the shadows Range control accessibility and usability. ([63908](https://github.com/WordPress/gutenberg/pull/63908)) -- Block Editor: Fix accessibility of the hooked blocks toggles. ([63133](https://github.com/WordPress/gutenberg/pull/63133)) - - -### Performance - -- Core Data: Batch remaining actions in resolvers. ([65176](https://github.com/WordPress/gutenberg/pull/65176)) -- Block Editor: Use static access for selector in 'useZoomOutModeExit'. ([65337](https://github.com/WordPress/gutenberg/pull/65337)) -- Editor: Optimize global styles permission check. ([65177](https://github.com/WordPress/gutenberg/pull/65177)) - - -### Experiments - -- Block bindings REST API: Bring bindings UI in Site Editor. ([64072](https://github.com/WordPress/gutenberg/pull/64072)) - - -### Documentation - -- Add JSDoc block for getSectionRootClientId in block editor package. ([65219](https://github.com/WordPress/gutenberg/pull/65219)) -- ButtonGroup: Fix story to show what the component does. ([65336](https://github.com/WordPress/gutenberg/pull/65336)) -- DataViews storybook - - Better styles for combined fields story. ([65078](https://github.com/WordPress/gutenberg/pull/65078)) - - Enable all layouts for combined fields storybook. ([65082](https://github.com/WordPress/gutenberg/pull/65082)) -- Docs: Fix minor typos in Build your first block tutorial. ([64961](https://github.com/WordPress/gutenberg/pull/64961)) -- Docs: Update the content of the API version 3 section in the Block API Reference. ([65375](https://github.com/WordPress/gutenberg/pull/65375)) -- Fix typo in Slot Fills documentation. ([65275](https://github.com/WordPress/gutenberg/pull/65275)) - - -### Code Quality - -- Components: Transition to the new 40px default size. - - Button: - - Add __next40pxDefaultSize for files in editor 3. ([65139](https://github.com/WordPress/gutenberg/pull/65139)) - - Add __next40pxDefaultSize for files in editor 4. ([65140](https://github.com/WordPress/gutenberg/pull/65140)) - - Add props for buttons in editor 1. ([65068](https://github.com/WordPress/gutenberg/pull/65068)) - - Add props for buttons in editor 2. ([65083](https://github.com/WordPress/gutenberg/pull/65083)) - - Fix: Replace remaining 40px default size violations [Block Editor 4]. ([65257](https://github.com/WordPress/gutenberg/pull/65257)) - - Fix: Replace remaining 40px default size violation [Block library 3]. ([65110](https://github.com/WordPress/gutenberg/pull/65110)) - - Fix: Replace remaining 40px default size violation [Block library 4]. ([65143](https://github.com/WordPress/gutenberg/pull/65143)) - - Fix: Replace remaining 40px default size violation [Block library]. ([65075](https://github.com/WordPress/gutenberg/pull/65075)) - - Fix: Replace remaining 40px default size violation [Edit Site 2]. ([65258](https://github.com/WordPress/gutenberg/pull/65258)) - - Fix: Replace remaining 40px default size violations [Block library 1]. ([65033](https://github.com/WordPress/gutenberg/pull/65033)) - - Fix: Replace remaining 40px default size violations [Block Editor 1]. ([65034](https://github.com/WordPress/gutenberg/pull/65034)) - - BoxControl - - Add lint rule for 40px size prop usage. ([65341](https://github.com/WordPress/gutenberg/pull/65341)) - - DimensionsPanel: Apply 40px default size to UI when no spacing preset is available. ([65300](https://gi -- Add `useEvent` and revamped `useResizeObserver` to `@wordpress/compose`. ([64943](https://github.com/WordPress/gutenberg/pull/64943)) -- DataViews: Use Dropdown for views configuration dialog. ([65314](https://github.com/WordPress/gutenberg/pull/65314)) -- Platform docs: Upgrade dependencies. ([65445](https://github.com/WordPress/gutenberg/pull/65445)) -- Rename edit-post__fade-in-animation and unify keyframe definitions. ([65377](https://github.com/WordPress/gutenberg/pull/65377)) -- Update minimum required version in PHP. ([65301](https://github.com/WordPress/gutenberg/pull/65301)) -- Editor: Use hooks instead of HoC in `BlockManager`. ([65349](https://github.com/WordPress/gutenberg/pull/65349)) -- Data Views Fields: Migrate store and actions from editor package to fields package. ([65261](https://github.com/WordPress/gutenberg/pull/65261)) -- Plugin: Remove 'function_exists' checks for methods with 'gutenberg' prefix. ([65260](https://github.com/WordPress/gutenberg/pull/65260)) -- Global Styles: Update REST controller override method and backport changes from Core. ([65259](https://github.com/WordPress/gutenberg/pull/65259)) -- Patterns: Remove unused method returned from 'mapSelect'. ([65073](https://github.com/WordPress/gutenberg/pull/65073)) -- Embed: Convert EmbedPreview component to functional component. ([51325](https://github.com/WordPress/gutenberg/pull/51325)) - -#### Components -- BoxControl: Fix critical error when null value is passed. ([65287](https://github.com/WordPress/gutenberg/pull/65287)) -- Composite: - - Deprecate legacy, unstable version. ([63572](https://github.com/WordPress/gutenberg/pull/63572)) - - Remove store prop and useCompositeStore hook. ([64723](https://github.com/WordPress/gutenberg/pull/64723)) - - Stabilize APIs. ([63569](https://github.com/WordPress/gutenberg/pull/63569)) -- `@wordpress/components`: Add local copy of `use-lilius`. ([65097](https://github.com/WordPress/gutenberg/pull/65097)) - -#### Block bindings -- Always prioritize using context in post meta source logic. ([65449](https://github.com/WordPress/gutenberg/pull/65449)) -- Improve getRegisteredPostMeta resolver. ([65450](https://github.com/WordPress/gutenberg/pull/65450)) -- Remove extra filtering of empty sources. ([65447](https://github.com/WordPress/gutenberg/pull/65447)) - -#### Block Editor -- Remove the 'PrivateInserter' component. ([65111](https://github.com/WordPress/gutenberg/pull/65111)) -- Use the tooltip from a button in 'ButtonBlockAppender'. ([65113](https://github.com/WordPress/gutenberg/pull/65113)) -- Remove unused css selectors. ([65276](https://github.com/WordPress/gutenberg/pull/65276)) - -### Tools - -- Scripts: Update stylelint dependency and the default configuration. ([64828](https://github.com/WordPress/gutenberg/pull/64828)) -- Styleling config: Fix stylelint configuration missing files for npm. ([65313](https://github.com/WordPress/gutenberg/pull/65313)) - -#### Build Tooling -- Build Plugin: Simplify and improve zip contents. ([65232](https://github.com/WordPress/gutenberg/pull/65232)) -- Build zip artifact on release and wp production branches. ([65471](https://github.com/WordPress/gutenberg/pull/65471)) -- Build: Include Core blocks' `render` and `variations` files. ([63311](https://github.com/WordPress/gutenberg/pull/63311)) -- Script Modules - - Prepare build for more script modules. ([65064](https://github.com/WordPress/gutenberg/pull/65064)) - - Remove babel from script-modules build. ([65279](https://github.com/WordPress/gutenberg/pull/65279)) - - Remove es-module shims and importmap-polyfill. ([65210](https://github.com/WordPress/gutenberg/pull/65210)) -- Correctly generate PHP files for server-side rendering of blocks on Windows OS. ([65248](https://github.com/WordPress/gutenberg/pull/65248)) -- Packages: Only add polyfills where needed. ([65292](https://github.com/WordPress/gutenberg/pull/65292)) -- Switch from UglifyJS to Terser to build the polyfill script. ([65278](https://github.com/WordPress/gutenberg/pull/65278)) - -#### Testing -- Unit tests: Mock matchMedia to enforce prefers-reduce-motion. ([65438](https://github.com/WordPress/gutenberg/pull/65438)) -- Upgrade Playwright to v1.47. ([65156](https://github.com/WordPress/gutenberg/pull/65156)) - -## First-time contributors - -The following PRs were merged by first-time contributors: - -- @AKSHAT2802: Add __next40pxDefaultSize for files in editor 4. ([65140](https://github.com/WordPress/gutenberg/pull/65140)) -- @devansh016: Automatically add tel to phone number when linking URL. ([64865](https://github.com/WordPress/gutenberg/pull/64865)) -- @dhruvang21: Fix: Button Replace remaining 40px default size violations [Edit widgets]. ([65367](https://github.com/WordPress/gutenberg/pull/65367)) -- @farid-hadi: Docs: Fix minor typos in Build your first block tutorial. ([64961](https://github.com/WordPress/gutenberg/pull/64961)) -- @greenworld: Fix typo in Slot Fills documentation. ([65275](https://github.com/WordPress/gutenberg/pull/65275)) -- @louwie17: Convert EmbedPreview component to functional component. ([51325](https://github.com/WordPress/gutenberg/pull/51325)) -- @rahulharpal1603: URLInput: Replace input with InputControl. ([65158](https://github.com/WordPress/gutenberg/pull/65158)) - - -## Contributors - -The following contributors merged PRs in this release: - -@aaronrobertshaw @afercia @AKSHAT2802 @Aljullu @andrewserong @carolinan @cbravobernal @ciampo @colorful-tones @creativecoder @DaniGuardiola @DAreRodz @devansh016 @dhruvang21 @ellatrix @farid-hadi @getdave @gigitux @greenworld @gziolo @hbhalodia @jameskoster @jasmussen @javierarce @jeryj @jorgefilipecosta @jsnajdr @kevin940726 @louwie17 @madhusudhand @MaggieCabrera @Mamaduka @mikeybinns @mirka @ntsekouras @oandregal @ockham @peterwilsoncc @rahulharpal1603 @ramonjd @richtabor @rohitmathur-7 @SantosGuillamot @scruffian @sgomes @sirreal @stokesman @swissspidy @t-hamano @talldan @vipul0425 @zaguiini - - = 19.2.0 = ## Changelog From efcefc57095842ef3894bae1c1eccf7d02a78c37 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 25 Sep 2024 17:05:44 +1000 Subject: [PATCH 0946/1908] Comments Pagination Numbers: Add block example (#65635) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/comments-pagination-numbers/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/comments-pagination-numbers/index.js b/packages/block-library/src/comments-pagination-numbers/index.js index 3fd903e2d9ef48..f769f54b4ac034 100644 --- a/packages/block-library/src/comments-pagination-numbers/index.js +++ b/packages/block-library/src/comments-pagination-numbers/index.js @@ -16,6 +16,7 @@ export { metadata, name }; export const settings = { icon, edit, + example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); From c8e5657b5d77285cd0dae5feb03071d3c225220d Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 25 Sep 2024 17:07:14 +1000 Subject: [PATCH 0947/1908] Comment Date: Add block example (#65632) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/comment-date/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/comment-date/index.js b/packages/block-library/src/comment-date/index.js index fddae539acfa34..d95c0a958f9ed8 100644 --- a/packages/block-library/src/comment-date/index.js +++ b/packages/block-library/src/comment-date/index.js @@ -18,6 +18,7 @@ export const settings = { icon, edit, deprecated, + example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); From 02a884f22ec7b654028c2c720ac43e0afa23eaaa Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 25 Sep 2024 17:12:32 +1000 Subject: [PATCH 0948/1908] Comment Pagination: Add previous and next link block examples (#65633) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../block-library/src/comments-pagination-next/block.json | 5 +++++ .../src/comments-pagination-previous/block.json | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/packages/block-library/src/comments-pagination-next/block.json b/packages/block-library/src/comments-pagination-next/block.json index 22e20bfa8dbf2d..3f7ebe677328d5 100644 --- a/packages/block-library/src/comments-pagination-next/block.json +++ b/packages/block-library/src/comments-pagination-next/block.json @@ -12,6 +12,11 @@ "type": "string" } }, + "example": { + "attributes": { + "label": "Comments Next Page" + } + }, "usesContext": [ "postId", "comments/paginationArrow" ], "supports": { "reusable": false, diff --git a/packages/block-library/src/comments-pagination-previous/block.json b/packages/block-library/src/comments-pagination-previous/block.json index 0871b000c569dd..eb5203af33c866 100644 --- a/packages/block-library/src/comments-pagination-previous/block.json +++ b/packages/block-library/src/comments-pagination-previous/block.json @@ -12,6 +12,11 @@ "type": "string" } }, + "example": { + "attributes": { + "label": "Comments Previous Page" + } + }, "usesContext": [ "postId", "comments/paginationArrow" ], "supports": { "reusable": false, From b681b5063add14746f7cee34de21493532e401b5 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 25 Sep 2024 17:55:56 +1000 Subject: [PATCH 0949/1908] Comment Links: Add block examples (#65601) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/comment-edit-link/index.js | 1 + packages/block-library/src/comment-reply-link/index.js | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/block-library/src/comment-edit-link/index.js b/packages/block-library/src/comment-edit-link/index.js index 6639dda86a7a40..ffe8c98a75dfd9 100644 --- a/packages/block-library/src/comment-edit-link/index.js +++ b/packages/block-library/src/comment-edit-link/index.js @@ -16,6 +16,7 @@ export { metadata, name }; export const settings = { icon, edit, + example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); diff --git a/packages/block-library/src/comment-reply-link/index.js b/packages/block-library/src/comment-reply-link/index.js index c04f8ce7b1bba5..a8287f6b08ff35 100644 --- a/packages/block-library/src/comment-reply-link/index.js +++ b/packages/block-library/src/comment-reply-link/index.js @@ -16,6 +16,7 @@ export { metadata, name }; export const settings = { edit, icon, + example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); From 195c7ef7ee12d2178aeb025aea9f0b54dcf8685c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20W=C3=BCnsch?= <soerenwrede@gmail.com> Date: Wed, 25 Sep 2024 14:39:05 +0200 Subject: [PATCH 0950/1908] Docs: Remove PHPDoc for non-existing argument (#65640) Co-authored-by: Soean <soean@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- lib/rest-api.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/rest-api.php b/lib/rest-api.php index ac020e243ec056..7570bb19737233 100644 --- a/lib/rest-api.php +++ b/lib/rest-api.php @@ -13,9 +13,8 @@ /** * Overrides the REST controller for the `wp_global_styles` post type. * - * @param array $args Array of arguments for registering a post type. + * @param array $args Array of arguments for registering a post type. * See the register_post_type() function for accepted arguments. - * @param string $post_type Post type key. * * @return array Array of arguments for registering a post type. */ From 4e53371c9a715b95af2c3fed1608bb1d8e31347f Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 25 Sep 2024 15:26:12 +0200 Subject: [PATCH 0951/1908] Block Bindings: Unify logic in `getPostMetaFields` function (#65462) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Move logic to `getPostMetaFields` function * Update comment to use third-person Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> * Remove extra space from comment object Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> * Use props variable --------- Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/editor/src/bindings/post-meta.js | 107 ++++++++++++---------- 1 file changed, 58 insertions(+), 49 deletions(-) diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index 572cd0b525a003..fae010e72d1c8b 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -9,26 +9,65 @@ import { store as coreDataStore } from '@wordpress/core-data'; import { store as editorStore } from '../store'; import { unlock } from '../lock-unlock'; -function getMetadata( registry, context, registeredFields ) { - let metaFields = {}; - const type = registry.select( editorStore ).getCurrentPostType(); +/** + * Gets a list of post meta fields with their values and labels + * to be consumed in the needed callbacks. + * If the value is not available based on context, like in templates, + * it falls back to the default value, label, or key. + * + * @param {Object} registry The registry context exposed through `useRegistry`. + * @param {Object} context The context provided. + * @return {Object} List of post meta fields with their value and label. + * + * @example + * ```js + * { + * field_1_key: { + * label: 'Field 1 Label', + * value: 'Field 1 Value', + * }, + * field_2_key: { + * label: 'Field 2 Label', + * value: 'Field 2 Value', + * }, + * ... + * } + * ``` + */ +function getPostMetaFields( registry, context ) { const { getEditedEntityRecord } = registry.select( coreDataStore ); + const { getRegisteredPostMeta } = unlock( + registry.select( coreDataStore ) + ); + let entityMetaValues; + // Try to get the current entity meta values. if ( context?.postType && context?.postId ) { - metaFields = getEditedEntityRecord( + entityMetaValues = getEditedEntityRecord( 'postType', context?.postType, context?.postId ).meta; - } else if ( type === 'wp_template' ) { - // Populate the `metaFields` object with the default values. - Object.entries( registeredFields || {} ).forEach( - ( [ key, props ] ) => { - if ( props.default ) { - metaFields[ key ] = props.default; - } - } - ); + } + + const registeredFields = getRegisteredPostMeta( context?.postType ); + const metaFields = {}; + Object.entries( registeredFields || {} ).forEach( ( [ key, props ] ) => { + // Don't include footnotes or private fields. + if ( key !== 'footnotes' && key.charAt( 0 ) !== '_' ) { + metaFields[ key ] = { + label: props.title || key, + value: + // When using the entity value, an empty string IS a valid value. + entityMetaValues?.[ key ] ?? + // When using the default, an empty string IS NOT a valid value. + ( props.default || undefined ), + }; + } + } ); + + if ( ! Object.keys( metaFields || {} ).length ) { + return null; } return metaFields; @@ -37,20 +76,15 @@ function getMetadata( registry, context, registeredFields ) { export default { name: 'core/post-meta', getValues( { registry, context, bindings } ) { - const { getRegisteredPostMeta } = unlock( - registry.select( coreDataStore ) - ); - const registeredFields = getRegisteredPostMeta( context?.postType ); - const metaFields = getMetadata( registry, context, registeredFields ); + const metaFields = getPostMetaFields( registry, context ); const newValues = {}; for ( const [ attributeName, source ] of Object.entries( bindings ) ) { // Use the value, the field label, or the field key. - const metaKey = source.args.key; - newValues[ attributeName ] = - metaFields?.[ metaKey ] ?? - registeredFields?.[ metaKey ]?.title ?? - metaKey; + const fieldKey = source.args.key; + const { value: fieldValue, label: fieldLabel } = + metaFields?.[ fieldKey ] || {}; + newValues[ attributeName ] = fieldValue ?? fieldLabel ?? fieldKey; } return newValues; }, @@ -110,31 +144,6 @@ export default { return true; }, getFieldsList( { registry, context } ) { - const { getRegisteredPostMeta } = unlock( - registry.select( coreDataStore ) - ); - const registeredFields = getRegisteredPostMeta( context?.postType ); - const metaFields = getMetadata( registry, context, registeredFields ); - - if ( ! metaFields || ! Object.keys( metaFields ).length ) { - return null; - } - - return Object.fromEntries( - Object.entries( metaFields ) - // Remove footnotes or private keys from the list of fields. - .filter( - ( [ key ] ) => - key !== 'footnotes' && key.charAt( 0 ) !== '_' - ) - // Return object with label and value. - .map( ( [ key, value ] ) => [ - key, - { - label: registeredFields?.[ key ]?.title || key, - value, - }, - ] ) - ); + return getPostMetaFields( registry, context ); }, }; From a08020096403b2a97863d071e815d980cebf826a Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 25 Sep 2024 16:15:18 +0200 Subject: [PATCH 0952/1908] Only pass context included in `usesContext` from block bindings (#65618) - Only pass context included in `usesContext` Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- .../block-editor/src/components/rich-text/index.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 9c67476ed0ea63..46ddb2b70a113d 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -179,11 +179,17 @@ export function RichTextWrapper( const blockBindingsSource = getBlockBindingsSource( relatedBinding.source ); + const blockBindingsContext = {}; + if ( blockBindingsSource?.usesContext?.length ) { + for ( const key of blockBindingsSource.usesContext ) { + blockBindingsContext[ key ] = blockContext[ key ]; + } + } const _disableBoundBlock = ! blockBindingsSource?.canUserEditValue?.( { select, - context: blockContext, + context: blockBindingsContext, args: relatedBinding.args, } ); @@ -201,7 +207,7 @@ export function RichTextWrapper( const blockAttributes = getBlockAttributes( clientId ); const fieldsList = blockBindingsSource?.getFieldsList?.( { registry, - context: blockContext, + context: blockBindingsContext, } ); const bindingKey = fieldsList?.[ relatedBinding?.args?.key ]?.label ?? From 69e00bd3375e2ed13fba8955b7b7298c15a47cb2 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 25 Sep 2024 23:39:33 +0900 Subject: [PATCH 0953/1908] LinkControl: Fix unneeded `props` prop (#65650) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- packages/block-editor/src/components/link-control/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/components/link-control/index.js b/packages/block-editor/src/components/link-control/index.js index f9e2e0bc6d790e..f0de14f3d68210 100644 --- a/packages/block-editor/src/components/link-control/index.js +++ b/packages/block-editor/src/components/link-control/index.js @@ -421,7 +421,6 @@ function LinkControl( { </InputControlSuffixWrapper> ) } - props /> </div> { errorMessage && ( From cb44f51ad33d703015816e53aa98616b41ead2ea Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Wed, 25 Sep 2024 17:00:53 +0200 Subject: [PATCH 0954/1908] Migrate store and actions from editor package to fields package #2 (#65289) Co-authored-by: gigitux <gigitux@git.wordpress.org> Co-authored-by: louwie17 <louwie17@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- package-lock.json | 2 + .../src/dataviews/actions/delete-post.tsx | 109 ------- .../src/dataviews/actions/reset-post.tsx | 147 --------- packages/editor/src/dataviews/fields/index.ts | 26 -- .../src/dataviews/store/private-actions.ts | 14 +- packages/fields/README.md | 20 ++ packages/fields/package.json | 1 + .../fields/src/actions/base-post/index.ts | 5 - packages/fields/src/actions/common/index.ts | 2 - packages/fields/src/actions/delete-post.tsx | 203 ++++++++++++ .../{pattern => }/duplicate-pattern.tsx | 4 +- .../{base-post => }/duplicate-post.native.tsx | 0 .../{base-post => }/duplicate-post.tsx | 6 +- .../{pattern => }/export-pattern.native.tsx | 0 .../actions/{pattern => }/export-pattern.tsx | 4 +- packages/fields/src/actions/index.ts | 18 +- packages/fields/src/actions/pattern/index.ts | 3 - .../{common => }/permanently-delete-post.tsx | 4 +- .../src}/actions/rename-post.tsx | 11 +- .../{base-post => }/reorder-page.native.tsx | 0 .../actions/{base-post => }/reorder-page.tsx | 4 +- packages/fields/src/actions/reset-post.tsx | 300 ++++++++++++++++++ .../src}/actions/restore-post.tsx | 0 .../src}/actions/trash-post.tsx | 0 .../{common => }/view-post-revisions.tsx | 2 +- .../src/actions/{base-post => }/view-post.tsx | 2 +- packages/fields/src/index.native.ts | 4 +- packages/fields/src/mutation/index.ts | 184 +++++++++++ packages/fields/src/types.ts | 1 + packages/fields/src/wordpress-editor.d.ts | 1 - packages/fields/tsconfig.json | 4 +- 31 files changed, 755 insertions(+), 326 deletions(-) delete mode 100644 packages/editor/src/dataviews/actions/delete-post.tsx delete mode 100644 packages/editor/src/dataviews/actions/reset-post.tsx delete mode 100644 packages/editor/src/dataviews/fields/index.ts delete mode 100644 packages/fields/src/actions/base-post/index.ts delete mode 100644 packages/fields/src/actions/common/index.ts create mode 100644 packages/fields/src/actions/delete-post.tsx rename packages/fields/src/actions/{pattern => }/duplicate-pattern.tsx (91%) rename packages/fields/src/actions/{base-post => }/duplicate-post.native.tsx (100%) rename packages/fields/src/actions/{base-post => }/duplicate-post.tsx (96%) rename packages/fields/src/actions/{pattern => }/export-pattern.native.tsx (100%) rename packages/fields/src/actions/{pattern => }/export-pattern.tsx (95%) delete mode 100644 packages/fields/src/actions/pattern/index.ts rename packages/fields/src/actions/{common => }/permanently-delete-post.tsx (96%) rename packages/{editor/src/dataviews => fields/src}/actions/rename-post.tsx (97%) rename packages/fields/src/actions/{base-post => }/reorder-page.native.tsx (100%) rename packages/fields/src/actions/{base-post => }/reorder-page.tsx (96%) create mode 100644 packages/fields/src/actions/reset-post.tsx rename packages/{editor/src/dataviews => fields/src}/actions/restore-post.tsx (100%) rename packages/{editor/src/dataviews => fields/src}/actions/trash-post.tsx (100%) rename packages/fields/src/actions/{common => }/view-post-revisions.tsx (96%) rename packages/fields/src/actions/{base-post => }/view-post.tsx (92%) create mode 100644 packages/fields/src/mutation/index.ts delete mode 100644 packages/fields/src/wordpress-editor.d.ts diff --git a/package-lock.json b/package-lock.json index a40aa8aab49340..93da356b222be4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54197,6 +54197,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", + "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", "@wordpress/blocks": "file:../blocks", "@wordpress/components": "file:../components", @@ -68945,6 +68946,7 @@ "version": "file:packages/fields", "requires": { "@babel/runtime": "^7.16.0", + "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", "@wordpress/blocks": "file:../blocks", "@wordpress/components": "file:../components", diff --git a/packages/editor/src/dataviews/actions/delete-post.tsx b/packages/editor/src/dataviews/actions/delete-post.tsx deleted file mode 100644 index 381c2964f943f6..00000000000000 --- a/packages/editor/src/dataviews/actions/delete-post.tsx +++ /dev/null @@ -1,109 +0,0 @@ -/** - * WordPress dependencies - */ -import { trash } from '@wordpress/icons'; -import { useDispatch } from '@wordpress/data'; -import { __, _n, sprintf } from '@wordpress/i18n'; -import { useState } from '@wordpress/element'; -import { - Button, - __experimentalText as Text, - __experimentalHStack as HStack, - __experimentalVStack as VStack, -} from '@wordpress/components'; -// @ts-ignore -import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; -import type { Action } from '@wordpress/dataviews'; -import type { StoreDescriptor } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import { - isTemplateRemovable, - getItemTitle, - isTemplateOrTemplatePart, -} from './utils'; -// @ts-ignore -import { store as editorStore } from '../../store'; -import { unlock } from '../../lock-unlock'; -import type { Post } from '../types'; - -const { PATTERN_TYPES } = unlock( patternsPrivateApis ); - -// This action is used for templates, patterns and template parts. -// Every other post type uses the similar `trashPostAction` which -// moves the post to trash. -const deletePostAction: Action< Post > = { - id: 'delete-post', - label: __( 'Delete' ), - isPrimary: true, - icon: trash, - isEligible( post ) { - if ( isTemplateOrTemplatePart( post ) ) { - return isTemplateRemovable( post ); - } - // We can only remove user patterns. - return post.type === PATTERN_TYPES.user; - }, - supportsBulk: true, - hideModalHeader: true, - RenderModal: ( { items, closeModal, onActionPerformed } ) => { - const [ isBusy, setIsBusy ] = useState( false ); - const { removeTemplates } = unlock( - useDispatch( editorStore as StoreDescriptor ) - ); - return ( - <VStack spacing="5"> - <Text> - { items.length > 1 - ? sprintf( - // translators: %d: number of items to delete. - _n( - 'Delete %d item?', - 'Delete %d items?', - items.length - ), - items.length - ) - : sprintf( - // translators: %s: The template or template part's titles - __( 'Delete "%s"?' ), - getItemTitle( items[ 0 ] ) - ) } - </Text> - <HStack justify="right"> - <Button - variant="tertiary" - onClick={ closeModal } - disabled={ isBusy } - accessibleWhenDisabled - __next40pxDefaultSize - > - { __( 'Cancel' ) } - </Button> - <Button - variant="primary" - onClick={ async () => { - setIsBusy( true ); - await removeTemplates( items, { - allowUndo: false, - } ); - onActionPerformed?.( items ); - setIsBusy( false ); - closeModal?.(); - } } - isBusy={ isBusy } - disabled={ isBusy } - accessibleWhenDisabled - __next40pxDefaultSize - > - { __( 'Delete' ) } - </Button> - </HStack> - </VStack> - ); - }, -}; - -export default deletePostAction; diff --git a/packages/editor/src/dataviews/actions/reset-post.tsx b/packages/editor/src/dataviews/actions/reset-post.tsx deleted file mode 100644 index d0b5521a34833d..00000000000000 --- a/packages/editor/src/dataviews/actions/reset-post.tsx +++ /dev/null @@ -1,147 +0,0 @@ -/** - * WordPress dependencies - */ -import { backup } from '@wordpress/icons'; -import { useDispatch } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; -import { __, sprintf } from '@wordpress/i18n'; -import { store as noticesStore } from '@wordpress/notices'; -import { useState } from '@wordpress/element'; -import { - Button, - __experimentalText as Text, - __experimentalHStack as HStack, - __experimentalVStack as VStack, -} from '@wordpress/components'; -import type { Action } from '@wordpress/dataviews'; -import type { StoreDescriptor } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import { TEMPLATE_POST_TYPE, TEMPLATE_ORIGINS } from '../../store/constants'; -import { store as editorStore } from '../../store'; -import { unlock } from '../../lock-unlock'; -import type { Post, CoreDataError } from '../types'; -import { isTemplateOrTemplatePart, getItemTitle } from './utils'; - -const resetPost: Action< Post > = { - id: 'reset-post', - label: __( 'Reset' ), - isEligible: ( item ) => { - return ( - isTemplateOrTemplatePart( item ) && - item?.source === TEMPLATE_ORIGINS.custom && - ( Boolean( item.type === 'wp_template' && item?.plugin ) || - item?.has_theme_file ) - ); - }, - icon: backup, - supportsBulk: true, - hideModalHeader: true, - RenderModal: ( { items, closeModal, onActionPerformed } ) => { - const [ isBusy, setIsBusy ] = useState( false ); - const { revertTemplate } = unlock( - useDispatch( editorStore as StoreDescriptor ) - ); - const { saveEditedEntityRecord } = useDispatch( coreStore ); - const { createSuccessNotice, createErrorNotice } = - useDispatch( noticesStore ); - const onConfirm = async () => { - try { - for ( const template of items ) { - await revertTemplate( template, { - allowUndo: false, - } ); - await saveEditedEntityRecord( - 'postType', - template.type, - template.id - ); - } - createSuccessNotice( - items.length > 1 - ? sprintf( - /* translators: The number of items. */ - __( '%s items reset.' ), - items.length - ) - : sprintf( - /* translators: The template/part's name. */ - __( '"%s" reset.' ), - getItemTitle( items[ 0 ] ) - ), - { - type: 'snackbar', - id: 'revert-template-action', - } - ); - } catch ( error ) { - let fallbackErrorMessage; - if ( items[ 0 ].type === TEMPLATE_POST_TYPE ) { - fallbackErrorMessage = - items.length === 1 - ? __( - 'An error occurred while reverting the template.' - ) - : __( - 'An error occurred while reverting the templates.' - ); - } else { - fallbackErrorMessage = - items.length === 1 - ? __( - 'An error occurred while reverting the template part.' - ) - : __( - 'An error occurred while reverting the template parts.' - ); - } - - const typedError = error as CoreDataError; - const errorMessage = - typedError.message && typedError.code !== 'unknown_error' - ? typedError.message - : fallbackErrorMessage; - - createErrorNotice( errorMessage, { type: 'snackbar' } ); - } - }; - return ( - <VStack spacing="5"> - <Text> - { __( 'Reset to default and clear all customizations?' ) } - </Text> - <HStack justify="right"> - <Button - __next40pxDefaultSize - variant="tertiary" - onClick={ closeModal } - disabled={ isBusy } - accessibleWhenDisabled - > - { __( 'Cancel' ) } - </Button> - <Button - __next40pxDefaultSize - variant="primary" - onClick={ async () => { - setIsBusy( true ); - await onConfirm(); - onActionPerformed?.( items ); - setIsBusy( false ); - closeModal?.(); - } } - isBusy={ isBusy } - disabled={ isBusy } - accessibleWhenDisabled - > - { __( 'Reset' ) } - </Button> - </HStack> - </VStack> - ); - }, -}; - -export default resetPost; diff --git a/packages/editor/src/dataviews/fields/index.ts b/packages/editor/src/dataviews/fields/index.ts deleted file mode 100644 index b215172eaf7f02..00000000000000 --- a/packages/editor/src/dataviews/fields/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import type { Field } from '@wordpress/dataviews'; - -/** - * Internal dependencies - */ -import type { BasePost } from '../types'; -import { getItemTitle } from '../actions/utils'; - -export const titleField: Field< BasePost > = { - type: 'text', - id: 'title', - label: __( 'Title' ), - placeholder: __( 'No title' ), - getValue: ( { item } ) => getItemTitle( item ), -}; - -export const orderField: Field< BasePost > = { - type: 'integer', - id: 'menu_order', - label: __( 'Order' ), - description: __( 'Determines the order of pages.' ), -}; diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index e685493641f3b8..10f2b9ce872d5a 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -8,11 +8,6 @@ import { doAction } from '@wordpress/hooks'; /** * Internal dependencies */ -import duplicateTemplatePart from '../actions/duplicate-template-part'; -import resetPost from '../actions/reset-post'; -import trashPost from '../actions/trash-post'; -import renamePost from '../actions/rename-post'; -import restorePost from '../actions/restore-post'; import type { PostType } from '../types'; import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; @@ -24,8 +19,13 @@ import { reorderPage, exportPattern, permanentlyDeletePost, + restorePost, + trashPost, + renamePost, + resetPost, + deletePost, } from '@wordpress/fields'; -import deletePost from '../actions/delete-post'; +import duplicateTemplatePart from '../actions/duplicate-template-part'; export function registerEntityAction< Item >( kind: string, @@ -117,8 +117,8 @@ export const registerPostTypeActions = ? reorderPage : undefined, postTypeConfig.slug === 'wp_block' ? exportPattern : undefined, - resetPost, restorePost, + resetPost, deletePost, trashPost, permanentlyDeletePost, diff --git a/packages/fields/README.md b/packages/fields/README.md index 842fab02606af8..b4e45103600da6 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -14,6 +14,10 @@ npm install @wordpress/fields --save <!-- START TOKEN(Autogenerated API docs) --> +### deletePost + +Undocumented declaration. + ### duplicatePattern Undocumented declaration. @@ -42,6 +46,10 @@ Undocumented declaration. Undocumented declaration. +### renamePost + +Undocumented declaration. + ### reorderPage Undocumented declaration. @@ -50,10 +58,22 @@ Undocumented declaration. Undocumented declaration. +### resetPost + +Undocumented declaration. + +### restorePost + +Undocumented declaration. + ### titleField Undocumented declaration. +### trashPost + +Undocumented declaration. + ### viewPost Undocumented declaration. diff --git a/packages/fields/package.json b/packages/fields/package.json index ba687e6db1bc87..3da913d1ee9ae5 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -32,6 +32,7 @@ ], "dependencies": { "@babel/runtime": "^7.16.0", + "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", "@wordpress/blocks": "file:../blocks", "@wordpress/components": "file:../components", diff --git a/packages/fields/src/actions/base-post/index.ts b/packages/fields/src/actions/base-post/index.ts deleted file mode 100644 index 7541be86c48b1f..00000000000000 --- a/packages/fields/src/actions/base-post/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { default as viewPost } from './view-post'; -export { default as reorderPage } from './reorder-page'; -export { default as reorderPageNative } from './reorder-page.native'; -export { default as duplicatePost } from './duplicate-post'; -export { default as duplicatePostNative } from './duplicate-post.native'; diff --git a/packages/fields/src/actions/common/index.ts b/packages/fields/src/actions/common/index.ts deleted file mode 100644 index 3590b2e270892e..00000000000000 --- a/packages/fields/src/actions/common/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as viewPostRevisions } from './view-post-revisions'; -export { default as permanentlyDeletePost } from './permanently-delete-post'; diff --git a/packages/fields/src/actions/delete-post.tsx b/packages/fields/src/actions/delete-post.tsx new file mode 100644 index 00000000000000..c5ab866e12479e --- /dev/null +++ b/packages/fields/src/actions/delete-post.tsx @@ -0,0 +1,203 @@ +/** + * WordPress dependencies + */ +import { trash } from '@wordpress/icons'; +import { __, _n, sprintf } from '@wordpress/i18n'; +import { useState } from '@wordpress/element'; +import { + Button, + __experimentalText as Text, + __experimentalHStack as HStack, + __experimentalVStack as VStack, +} from '@wordpress/components'; +// @ts-ignore +import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; +import type { Action } from '@wordpress/dataviews'; +import { decodeEntities } from '@wordpress/html-entities'; + +/** + * Internal dependencies + */ +import { + getItemTitle, + isTemplateOrTemplatePart, + isTemplateRemovable, +} from './utils'; +import type { Pattern, Template, TemplatePart } from '../types'; +import type { NoticeSettings } from '../mutation'; +import { deletePostWithNotices } from '../mutation'; +import { unlock } from '../lock-unlock'; + +const { PATTERN_TYPES } = unlock( patternsPrivateApis ); + +// This action is used for templates, patterns and template parts. +// Every other post type uses the similar `trashPostAction` which +// moves the post to trash. +const deletePostAction: Action< Template | TemplatePart | Pattern > = { + id: 'delete-post', + label: __( 'Delete' ), + isPrimary: true, + icon: trash, + isEligible( post ) { + if ( isTemplateOrTemplatePart( post ) ) { + return isTemplateRemovable( post ); + } + // We can only remove user patterns. + return post.type === PATTERN_TYPES.user; + }, + supportsBulk: true, + hideModalHeader: true, + RenderModal: ( { items, closeModal, onActionPerformed } ) => { + const [ isBusy, setIsBusy ] = useState( false ); + const isResetting = items.every( + ( item ) => isTemplateOrTemplatePart( item ) && item?.has_theme_file + ); + return ( + <VStack spacing="5"> + <Text> + { items.length > 1 + ? sprintf( + // translators: %d: number of items to delete. + _n( + 'Delete %d item?', + 'Delete %d items?', + items.length + ), + items.length + ) + : sprintf( + // translators: %s: The template or template part's titles + __( 'Delete "%s"?' ), + getItemTitle( items[ 0 ] ) + ) } + </Text> + <HStack justify="right"> + <Button + variant="tertiary" + onClick={ closeModal } + disabled={ isBusy } + accessibleWhenDisabled + __next40pxDefaultSize + > + { __( 'Cancel' ) } + </Button> + <Button + variant="primary" + onClick={ async () => { + setIsBusy( true ); + const notice: NoticeSettings< + Template | TemplatePart | Pattern + > = { + success: { + messages: { + getMessage: ( item ) => { + return isResetting + ? sprintf( + /* translators: The template/part's name. */ + __( '"%s" reset.' ), + decodeEntities( + getItemTitle( item ) + ) + ) + : sprintf( + /* translators: The template/part's name. */ + __( '"%s" deleted.' ), + decodeEntities( + getItemTitle( item ) + ) + ); + }, + getBatchMessage: () => { + return isResetting + ? __( 'Items reset.' ) + : __( 'Items deleted.' ); + }, + }, + }, + error: { + messages: { + getMessage: ( error ) => { + if ( error.size === 1 ) { + return [ ...error ][ 0 ]; + } + return isResetting + ? __( + 'An error occurred while reverting the item.' + ) + : __( + 'An error occurred while deleting the item.' + ); + }, + getBatchMessage: ( errors ) => { + if ( errors.size === 0 ) { + return isResetting + ? __( + 'An error occurred while reverting the items.' + ) + : __( + 'An error occurred while deleting the items.' + ); + } + + if ( errors.size === 1 ) { + return isResetting + ? sprintf( + /* translators: %s: an error message */ + __( + 'An error occurred while reverting the items: %s' + ), + [ ...errors ][ 0 ] + ) + : sprintf( + /* translators: %s: an error message */ + __( + 'An error occurred while deleting the items: %s' + ), + [ ...errors ][ 0 ] + ); + } + + return isResetting + ? sprintf( + /* translators: %s: a list of comma separated error messages */ + __( + 'Some errors occurred while reverting the items: %s' + ), + [ ...errors ].join( + ',' + ) + ) + : sprintf( + /* translators: %s: a list of comma separated error messages */ + __( + 'Some errors occurred while deleting the items: %s' + ), + [ ...errors ].join( + ',' + ) + ); + }, + }, + }, + }; + + await deletePostWithNotices( items, notice, { + onActionPerformed, + } ); + setIsBusy( false ); + closeModal?.(); + } } + isBusy={ isBusy } + disabled={ isBusy } + accessibleWhenDisabled + __next40pxDefaultSize + > + { __( 'Delete' ) } + </Button> + </HStack> + </VStack> + ); + }, +}; + +export default deletePostAction; diff --git a/packages/fields/src/actions/pattern/duplicate-pattern.tsx b/packages/fields/src/actions/duplicate-pattern.tsx similarity index 91% rename from packages/fields/src/actions/pattern/duplicate-pattern.tsx rename to packages/fields/src/actions/duplicate-pattern.tsx index 7c71a271997f15..bf2820f951dbad 100644 --- a/packages/fields/src/actions/pattern/duplicate-pattern.tsx +++ b/packages/fields/src/actions/duplicate-pattern.tsx @@ -9,8 +9,8 @@ import type { Action } from '@wordpress/dataviews'; /** * Internal dependencies */ -import { unlock } from '../../lock-unlock'; -import type { Pattern } from '../../types'; +import { unlock } from '../lock-unlock'; +import type { Pattern } from '../types'; // Patterns. const { CreatePatternModalContents, useDuplicatePatternProps } = diff --git a/packages/fields/src/actions/base-post/duplicate-post.native.tsx b/packages/fields/src/actions/duplicate-post.native.tsx similarity index 100% rename from packages/fields/src/actions/base-post/duplicate-post.native.tsx rename to packages/fields/src/actions/duplicate-post.native.tsx diff --git a/packages/fields/src/actions/base-post/duplicate-post.tsx b/packages/fields/src/actions/duplicate-post.tsx similarity index 96% rename from packages/fields/src/actions/base-post/duplicate-post.tsx rename to packages/fields/src/actions/duplicate-post.tsx index 0035a40c009342..d153073f4b6c12 100644 --- a/packages/fields/src/actions/base-post/duplicate-post.tsx +++ b/packages/fields/src/actions/duplicate-post.tsx @@ -18,9 +18,9 @@ import type { Action } from '@wordpress/dataviews'; /** * Internal dependencies */ -import { titleField } from '../../fields'; -import type { BasePost, CoreDataError } from '../../types'; -import { getItemTitle } from '../utils'; +import { titleField } from '../fields'; +import type { BasePost, CoreDataError } from '../types'; +import { getItemTitle } from './utils'; const fields = [ titleField ]; const formDuplicateAction = { diff --git a/packages/fields/src/actions/pattern/export-pattern.native.tsx b/packages/fields/src/actions/export-pattern.native.tsx similarity index 100% rename from packages/fields/src/actions/pattern/export-pattern.native.tsx rename to packages/fields/src/actions/export-pattern.native.tsx diff --git a/packages/fields/src/actions/pattern/export-pattern.tsx b/packages/fields/src/actions/export-pattern.tsx similarity index 95% rename from packages/fields/src/actions/pattern/export-pattern.tsx rename to packages/fields/src/actions/export-pattern.tsx index b0f6c3335544c1..b6be83eeda84b4 100644 --- a/packages/fields/src/actions/pattern/export-pattern.tsx +++ b/packages/fields/src/actions/export-pattern.tsx @@ -15,8 +15,8 @@ import type { Action } from '@wordpress/dataviews'; /** * Internal dependencies */ -import type { Pattern } from '../../types'; -import { getItemTitle } from '../utils'; +import type { Pattern } from '../types'; +import { getItemTitle } from './utils'; function getJsonFromItem( item: Pattern ) { return JSON.stringify( diff --git a/packages/fields/src/actions/index.ts b/packages/fields/src/actions/index.ts index cf4fd6833f3fbe..08e22836e68fd1 100644 --- a/packages/fields/src/actions/index.ts +++ b/packages/fields/src/actions/index.ts @@ -1,3 +1,15 @@ -export * from './base-post'; -export * from './common'; -export * from './pattern'; +export { default as viewPost } from './view-post'; +export { default as reorderPage } from './reorder-page'; +export { default as reorderPageNative } from './reorder-page.native'; +export { default as duplicatePost } from './duplicate-post'; +export { default as duplicatePostNative } from './duplicate-post.native'; +export { default as renamePost } from './rename-post'; +export { default as resetPost } from './reset-post'; +export { default as duplicatePattern } from './duplicate-pattern'; +export { default as exportPattern } from './export-pattern'; +export { default as exportPatternNative } from './export-pattern.native'; +export { default as viewPostRevisions } from './view-post-revisions'; +export { default as permanentlyDeletePost } from './permanently-delete-post'; +export { default as restorePost } from './restore-post'; +export { default as trashPost } from './trash-post'; +export { default as deletePost } from './delete-post'; diff --git a/packages/fields/src/actions/pattern/index.ts b/packages/fields/src/actions/pattern/index.ts deleted file mode 100644 index 827c2ce365c2c5..00000000000000 --- a/packages/fields/src/actions/pattern/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { default as duplicatePattern } from './duplicate-pattern'; -export { default as exportPattern } from './export-pattern'; -export { default as exportPatternNative } from './export-pattern.native'; diff --git a/packages/fields/src/actions/common/permanently-delete-post.tsx b/packages/fields/src/actions/permanently-delete-post.tsx similarity index 96% rename from packages/fields/src/actions/common/permanently-delete-post.tsx rename to packages/fields/src/actions/permanently-delete-post.tsx index e0c1de96871f1f..afbb84ae12c74c 100644 --- a/packages/fields/src/actions/common/permanently-delete-post.tsx +++ b/packages/fields/src/actions/permanently-delete-post.tsx @@ -10,8 +10,8 @@ import { trash } from '@wordpress/icons'; /** * Internal dependencies */ -import { getItemTitle, isTemplateOrTemplatePart } from '../utils'; -import type { CoreDataError, PostWithPermissions } from '../../types'; +import { getItemTitle, isTemplateOrTemplatePart } from './utils'; +import type { CoreDataError, PostWithPermissions } from '../types'; const permanentlyDeletePost: Action< PostWithPermissions > = { id: 'permanently-delete', diff --git a/packages/editor/src/dataviews/actions/rename-post.tsx b/packages/fields/src/actions/rename-post.tsx similarity index 97% rename from packages/editor/src/dataviews/actions/rename-post.tsx rename to packages/fields/src/actions/rename-post.tsx index ef9da271111ea2..da1fd46669f0df 100644 --- a/packages/editor/src/dataviews/actions/rename-post.tsx +++ b/packages/fields/src/actions/rename-post.tsx @@ -19,17 +19,16 @@ import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies */ -import { - TEMPLATE_ORIGINS, - TEMPLATE_PART_POST_TYPE, - TEMPLATE_POST_TYPE, -} from '../../store/constants'; -import { unlock } from '../../lock-unlock'; + +import { unlock } from '../lock-unlock'; import { getItemTitle, isTemplateRemovable, isTemplate, isTemplatePart, + TEMPLATE_ORIGINS, + TEMPLATE_PART_POST_TYPE, + TEMPLATE_POST_TYPE, } from './utils'; import type { CoreDataError, PostWithPermissions } from '../types'; diff --git a/packages/fields/src/actions/base-post/reorder-page.native.tsx b/packages/fields/src/actions/reorder-page.native.tsx similarity index 100% rename from packages/fields/src/actions/base-post/reorder-page.native.tsx rename to packages/fields/src/actions/reorder-page.native.tsx diff --git a/packages/fields/src/actions/base-post/reorder-page.tsx b/packages/fields/src/actions/reorder-page.tsx similarity index 96% rename from packages/fields/src/actions/base-post/reorder-page.tsx rename to packages/fields/src/actions/reorder-page.tsx index 7f3bca59c471ce..1820884d8d8c73 100644 --- a/packages/fields/src/actions/base-post/reorder-page.tsx +++ b/packages/fields/src/actions/reorder-page.tsx @@ -17,8 +17,8 @@ import type { Action, RenderModalProps } from '@wordpress/dataviews'; /** * Internal dependencies */ -import type { CoreDataError, BasePost } from '../../types'; -import { orderField } from '../../fields'; +import type { CoreDataError, BasePost } from '../types'; +import { orderField } from '../fields'; const fields = [ orderField ]; const formOrderAction = { diff --git a/packages/fields/src/actions/reset-post.tsx b/packages/fields/src/actions/reset-post.tsx new file mode 100644 index 00000000000000..105d7b283b8334 --- /dev/null +++ b/packages/fields/src/actions/reset-post.tsx @@ -0,0 +1,300 @@ +/** + * WordPress dependencies + */ +import { backup } from '@wordpress/icons'; +import { dispatch, select, useDispatch } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { __, sprintf } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; +import { useState } from '@wordpress/element'; +// @ts-ignore +import { parse, __unstableSerializeAndClean } from '@wordpress/blocks'; +import { + Button, + __experimentalText as Text, + __experimentalHStack as HStack, + __experimentalVStack as VStack, +} from '@wordpress/components'; +import type { Action } from '@wordpress/dataviews'; +import { addQueryArgs } from '@wordpress/url'; +import apiFetch from '@wordpress/api-fetch'; + +/** + * Internal dependencies + */ +import { + getItemTitle, + isTemplateOrTemplatePart, + TEMPLATE_ORIGINS, + TEMPLATE_POST_TYPE, +} from './utils'; +import type { CoreDataError, Template, TemplatePart } from '../types'; + +const isTemplateRevertable = ( + templateOrTemplatePart: Template | TemplatePart +) => { + if ( ! templateOrTemplatePart ) { + return false; + } + + return ( + templateOrTemplatePart.source === TEMPLATE_ORIGINS.custom && + ( Boolean( templateOrTemplatePart?.plugin ) || + templateOrTemplatePart?.has_theme_file ) + ); +}; + +/** + * Copied - pasted from https://github.com/WordPress/gutenberg/blob/bf1462ad37d4637ebbf63270b9c244b23c69e2a8/packages/editor/src/store/private-actions.js#L233-L365 + * + * @param {Object} template The template to revert. + * @param {Object} [options] + * @param {boolean} [options.allowUndo] Whether to allow the user to undo + * reverting the template. Default true. + */ +const revertTemplate = async ( + template: TemplatePart | Template, + { allowUndo = true } = {} +) => { + const noticeId = 'edit-site-template-reverted'; + dispatch( noticesStore ).removeNotice( noticeId ); + if ( ! isTemplateRevertable( template ) ) { + dispatch( noticesStore ).createErrorNotice( + __( 'This template is not revertable.' ), + { + type: 'snackbar', + } + ); + return; + } + + try { + const templateEntityConfig = select( coreStore ).getEntityConfig( + 'postType', + template.type + ); + + if ( ! templateEntityConfig ) { + dispatch( noticesStore ).createErrorNotice( + __( + 'The editor has encountered an unexpected error. Please reload.' + ), + { type: 'snackbar' } + ); + return; + } + + const fileTemplatePath = addQueryArgs( + `${ templateEntityConfig.baseURL }/${ template.id }`, + { context: 'edit', source: template.origin } + ); + + const fileTemplate = ( await apiFetch( { + path: fileTemplatePath, + } ) ) as any; + if ( ! fileTemplate ) { + dispatch( noticesStore ).createErrorNotice( + __( + 'The editor has encountered an unexpected error. Please reload.' + ), + { type: 'snackbar' } + ); + return; + } + + const serializeBlocks = ( { blocks: blocksForSerialization = [] } ) => + __unstableSerializeAndClean( blocksForSerialization ); + + const edited = select( coreStore ).getEditedEntityRecord( + 'postType', + template.type, + template.id + ) as any; + + // We are fixing up the undo level here to make sure we can undo + // the revert in the header toolbar correctly. + dispatch( coreStore ).editEntityRecord( + 'postType', + template.type, + template.id, + { + content: serializeBlocks, // Required to make the `undo` behave correctly. + blocks: edited.blocks, // Required to revert the blocks in the editor. + source: 'custom', // required to avoid turning the editor into a dirty state + }, + { + undoIgnore: true, // Required to merge this edit with the last undo level. + } + ); + + const blocks = parse( fileTemplate?.content?.raw ); + + dispatch( coreStore ).editEntityRecord( + 'postType', + template.type, + fileTemplate.id, + { + content: serializeBlocks, + blocks, + source: 'theme', + } + ); + + if ( allowUndo ) { + const undoRevert = () => { + dispatch( coreStore ).editEntityRecord( + 'postType', + template.type, + edited.id, + { + content: serializeBlocks, + blocks: edited.blocks, + source: 'custom', + } + ); + }; + + dispatch( noticesStore ).createSuccessNotice( + __( 'Template reset.' ), + { + type: 'snackbar', + id: noticeId, + actions: [ + { + label: __( 'Undo' ), + onClick: undoRevert, + }, + ], + } + ); + } + } catch ( error: any ) { + const errorMessage = + error.message && error.code !== 'unknown_error' + ? error.message + : __( 'Template revert failed. Please reload.' ); + + dispatch( noticesStore ).createErrorNotice( errorMessage, { + type: 'snackbar', + } ); + } +}; + +const resetPostAction: Action< Template | TemplatePart > = { + id: 'reset-post', + label: __( 'Reset' ), + isEligible: ( item ) => { + return ( + isTemplateOrTemplatePart( item ) && + item?.source === TEMPLATE_ORIGINS.custom && + ( Boolean( item.type === 'wp_template' && item?.plugin ) || + item?.has_theme_file ) + ); + }, + icon: backup, + supportsBulk: true, + hideModalHeader: true, + RenderModal: ( { items, closeModal, onActionPerformed } ) => { + const [ isBusy, setIsBusy ] = useState( false ); + + const { saveEditedEntityRecord } = useDispatch( coreStore ); + const { createSuccessNotice, createErrorNotice } = + useDispatch( noticesStore ); + const onConfirm = async () => { + try { + for ( const template of items ) { + await revertTemplate( template, { + allowUndo: false, + } ); + await saveEditedEntityRecord( + 'postType', + template.type, + template.id + ); + } + createSuccessNotice( + items.length > 1 + ? sprintf( + /* translators: The number of items. */ + __( '%s items reset.' ), + items.length + ) + : sprintf( + /* translators: The template/part's name. */ + __( '"%s" reset.' ), + getItemTitle( items[ 0 ] ) + ), + { + type: 'snackbar', + id: 'revert-template-action', + } + ); + } catch ( error ) { + let fallbackErrorMessage; + if ( items[ 0 ].type === TEMPLATE_POST_TYPE ) { + fallbackErrorMessage = + items.length === 1 + ? __( + 'An error occurred while reverting the template.' + ) + : __( + 'An error occurred while reverting the templates.' + ); + } else { + fallbackErrorMessage = + items.length === 1 + ? __( + 'An error occurred while reverting the template part.' + ) + : __( + 'An error occurred while reverting the template parts.' + ); + } + + const typedError = error as CoreDataError; + const errorMessage = + typedError.message && typedError.code !== 'unknown_error' + ? typedError.message + : fallbackErrorMessage; + + createErrorNotice( errorMessage, { type: 'snackbar' } ); + } + }; + return ( + <VStack spacing="5"> + <Text> + { __( 'Reset to default and clear all customizations?' ) } + </Text> + <HStack justify="right"> + <Button + __next40pxDefaultSize + variant="tertiary" + onClick={ closeModal } + disabled={ isBusy } + accessibleWhenDisabled + > + { __( 'Cancel' ) } + </Button> + <Button + __next40pxDefaultSize + variant="primary" + onClick={ async () => { + setIsBusy( true ); + await onConfirm(); + onActionPerformed?.( items ); + setIsBusy( false ); + closeModal?.(); + } } + isBusy={ isBusy } + disabled={ isBusy } + accessibleWhenDisabled + > + { __( 'Reset' ) } + </Button> + </HStack> + </VStack> + ); + }, +}; + +export default resetPostAction; diff --git a/packages/editor/src/dataviews/actions/restore-post.tsx b/packages/fields/src/actions/restore-post.tsx similarity index 100% rename from packages/editor/src/dataviews/actions/restore-post.tsx rename to packages/fields/src/actions/restore-post.tsx diff --git a/packages/editor/src/dataviews/actions/trash-post.tsx b/packages/fields/src/actions/trash-post.tsx similarity index 100% rename from packages/editor/src/dataviews/actions/trash-post.tsx rename to packages/fields/src/actions/trash-post.tsx diff --git a/packages/fields/src/actions/common/view-post-revisions.tsx b/packages/fields/src/actions/view-post-revisions.tsx similarity index 96% rename from packages/fields/src/actions/common/view-post-revisions.tsx rename to packages/fields/src/actions/view-post-revisions.tsx index 617a5263a707d6..875b925b94f070 100644 --- a/packages/fields/src/actions/common/view-post-revisions.tsx +++ b/packages/fields/src/actions/view-post-revisions.tsx @@ -8,7 +8,7 @@ import type { Action } from '@wordpress/dataviews'; /** * Internal dependencies */ -import type { Post } from '../../types'; +import type { Post } from '../types'; const viewPostRevisions: Action< Post > = { id: 'view-post-revisions', diff --git a/packages/fields/src/actions/base-post/view-post.tsx b/packages/fields/src/actions/view-post.tsx similarity index 92% rename from packages/fields/src/actions/base-post/view-post.tsx rename to packages/fields/src/actions/view-post.tsx index 8c581877e473bb..187faffafb5d3c 100644 --- a/packages/fields/src/actions/base-post/view-post.tsx +++ b/packages/fields/src/actions/view-post.tsx @@ -8,7 +8,7 @@ import type { Action } from '@wordpress/dataviews'; /** * Internal dependencies */ -import type { BasePost } from '../../types'; +import type { BasePost } from '../types'; const viewPost: Action< BasePost > = { id: 'view-post', diff --git a/packages/fields/src/index.native.ts b/packages/fields/src/index.native.ts index e4d3134d72f847..33a26e3c2e6e27 100644 --- a/packages/fields/src/index.native.ts +++ b/packages/fields/src/index.native.ts @@ -1,2 +1,2 @@ -export * from './actions/base-post/duplicate-post.native'; -export * from './actions/base-post/reorder-page.native'; +export * from './actions/duplicate-post.native'; +export * from './actions/reorder-page.native'; diff --git a/packages/fields/src/mutation/index.ts b/packages/fields/src/mutation/index.ts new file mode 100644 index 00000000000000..80e399d74e9479 --- /dev/null +++ b/packages/fields/src/mutation/index.ts @@ -0,0 +1,184 @@ +/** + * WordPress dependencies + */ +import { store as noticesStore } from '@wordpress/notices'; +import { store as coreStore } from '@wordpress/core-data'; +import { dispatch } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import type { CoreDataError, Post } from '../types'; + +const getErrorMessagesFromPromises = < T >( + allSettledResults: PromiseSettledResult< T >[] +) => { + const errorMessages = new Set< string >(); + // If there was at lease one failure. + if ( allSettledResults.length === 1 ) { + const typedError = allSettledResults[ 0 ] as { + reason?: CoreDataError; + }; + if ( typedError.reason?.message ) { + errorMessages.add( typedError.reason.message ); + } + } else { + const failedPromises = allSettledResults.filter( + ( { status } ) => status === 'rejected' + ); + for ( const failedPromise of failedPromises ) { + const typedError = failedPromise as { + reason?: CoreDataError; + }; + if ( typedError.reason?.message ) { + errorMessages.add( typedError.reason.message ); + } + } + } + return errorMessages; +}; + +export type NoticeSettings< T extends Post > = { + success: { + id?: string; + type?: string; + messages: { + getMessage: ( posts: T ) => string; + getBatchMessage: ( posts: T[] ) => string; + }; + }; + error: { + id?: string; + type?: string; + messages: { + getMessage: ( errors: Set< string > ) => string; + getBatchMessage: ( errors: Set< string > ) => string; + }; + }; +}; + +export const deletePostWithNotices = async < T extends Post >( + posts: T[], + notice: NoticeSettings< T >, + callbacks: { + onActionPerformed?: ( posts: T[] ) => void; + onActionError?: () => void; + } +) => { + const { createSuccessNotice, createErrorNotice } = dispatch( noticesStore ); + const { deleteEntityRecord } = dispatch( coreStore ); + const allSettledResults = await Promise.allSettled( + posts.map( ( post ) => { + return deleteEntityRecord( + 'postType', + post.type, + post.id, + { force: true }, + { throwOnError: true } + ); + } ) + ); + // If all the promises were fulfilled with success. + if ( allSettledResults.every( ( { status } ) => status === 'fulfilled' ) ) { + let successMessage; + if ( allSettledResults.length === 1 ) { + successMessage = notice.success.messages.getMessage( posts[ 0 ] ); + } else { + successMessage = notice.success.messages.getBatchMessage( posts ); + } + createSuccessNotice( successMessage, { + type: notice.success.type ?? 'snackbar', + id: notice.success.id, + } ); + callbacks.onActionPerformed?.( posts ); + } else { + const errorMessages = getErrorMessagesFromPromises( allSettledResults ); + let errorMessage = ''; + if ( allSettledResults.length === 1 ) { + errorMessage = notice.error.messages.getMessage( errorMessages ); + } else { + errorMessage = + notice.error.messages.getBatchMessage( errorMessages ); + } + + createErrorNotice( errorMessage, { + type: notice.error.type ?? 'snackbar', + id: notice.error.id, + } ); + callbacks.onActionError?.(); + } +}; + +export const editPostWithNotices = async < T extends Post >( + postsWithUpdates: { + originalPost: T; + changes: Partial< T >; + }[], + notice: NoticeSettings< T >, + callbacks: { + onActionPerformed?: ( posts: T[] ) => void; + onActionError?: () => void; + } +) => { + const { createSuccessNotice, createErrorNotice } = dispatch( noticesStore ); + const { editEntityRecord, saveEditedEntityRecord } = dispatch( coreStore ); + await Promise.allSettled( + postsWithUpdates.map( ( post ) => { + return editEntityRecord( + 'postType', + post.originalPost.type, + post.originalPost.id, + { + ...post.changes, + } + ); + } ) + ); + const allSettledResults = await Promise.allSettled( + postsWithUpdates.map( ( post ) => { + return saveEditedEntityRecord( + 'postType', + post.originalPost.type, + post.originalPost.id, + { + throwOnError: true, + } + ); + } ) + ); + // If all the promises were fulfilled with success. + if ( allSettledResults.every( ( { status } ) => status === 'fulfilled' ) ) { + let successMessage; + if ( allSettledResults.length === 1 ) { + successMessage = notice.success.messages.getMessage( + postsWithUpdates[ 0 ].originalPost + ); + } else { + successMessage = notice.success.messages.getBatchMessage( + postsWithUpdates.map( ( post ) => post.originalPost ) + ); + } + createSuccessNotice( successMessage, { + type: notice.success.type ?? 'snackbar', + id: notice.success.id, + } ); + callbacks.onActionPerformed?.( + postsWithUpdates.map( ( post ) => post.originalPost ) + ); + } else { + const errorMessages = getErrorMessagesFromPromises( allSettledResults ); + let errorMessage = ''; + if ( allSettledResults.length === 1 ) { + errorMessage = notice.error.messages.getMessage( errorMessages ); + } else { + errorMessage = + notice.error.messages.getBatchMessage( errorMessages ); + } + + createErrorNotice( errorMessage, { + type: notice.error.type ?? 'snackbar', + id: notice.error.id, + } ); + callbacks.onActionError?.(); + } +}; diff --git a/packages/fields/src/types.ts b/packages/fields/src/types.ts index 664c2dd417201c..a5ed9596b07dfd 100644 --- a/packages/fields/src/types.ts +++ b/packages/fields/src/types.ts @@ -54,6 +54,7 @@ export interface TemplatePart extends CommonPost { has_theme_file: boolean; id: string; area: string; + plugin?: string; } export interface Pattern extends CommonPost { diff --git a/packages/fields/src/wordpress-editor.d.ts b/packages/fields/src/wordpress-editor.d.ts deleted file mode 100644 index 915dacd5f05a9c..00000000000000 --- a/packages/fields/src/wordpress-editor.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module '@wordpress/editor'; diff --git a/packages/fields/tsconfig.json b/packages/fields/tsconfig.json index c55be59acf40f0..69dbd076d05747 100644 --- a/packages/fields/tsconfig.json +++ b/packages/fields/tsconfig.json @@ -7,6 +7,7 @@ "checkJs": false }, "references": [ + { "path": "../api-fetch" }, { "path": "../components" }, { "path": "../compose" }, { "path": "../data" }, @@ -24,6 +25,5 @@ { "path": "../hooks" }, { "path": "../html-entities" } ], - "include": [ "src" ], - "exclude": [ "@wordpress/editor" ] + "include": [ "src" ] } From d21a2d152b39e10b389075b983387598c27de352 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 25 Sep 2024 08:17:15 -0700 Subject: [PATCH 0955/1908] Block Editor: Don't memoize 'getContentLockingParent' and 'getParentSectionBlock' selectors (#65649) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../src/store/private-selectors.js | 66 ++++++------------- 1 file changed, 21 insertions(+), 45 deletions(-) diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index a98c5af93c86a9..7af83bed44b0db 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -474,69 +474,45 @@ export function getExpandedBlock( state ) { * with the provided client ID. * * @param {Object} state Global application state. - * @param {Object} clientId Client Id of the block. + * @param {string} clientId Client Id of the block. * * @return {?string} Client ID of the ancestor block that is content locking the block. */ -export const getContentLockingParent = createSelector( - ( state, clientId ) => { - let current = clientId; - let result; - while ( - ! result && - ( current = state.blocks.parents.get( current ) ) - ) { - if ( getTemplateLock( state, current ) === 'contentOnly' ) { - result = current; - } +export const getContentLockingParent = ( state, clientId ) => { + let current = clientId; + let result; + while ( ! result && ( current = state.blocks.parents.get( current ) ) ) { + if ( getTemplateLock( state, current ) === 'contentOnly' ) { + result = current; } - return result; - }, - ( state ) => [ - state.blocks.parents, - state.blockListSettings, - state.settings.templateLock, - ] -); + } + return result; +}; /** * Retrieves the client ID of the parent section block. * * @param {Object} state Global application state. - * @param {Object} clientId Client Id of the block. + * @param {string} clientId Client Id of the block. * * @return {?string} Client ID of the ancestor block that is content locking the block. */ -export const getParentSectionBlock = createSelector( - ( state, clientId ) => { - let current = clientId; - let result; - while ( - ! result && - ( current = state.blocks.parents.get( current ) ) - ) { - if ( isSectionBlock( state, current ) ) { - result = current; - } +export const getParentSectionBlock = ( state, clientId ) => { + let current = clientId; + let result; + while ( ! result && ( current = state.blocks.parents.get( current ) ) ) { + if ( isSectionBlock( state, current ) ) { + result = current; } - return result; - }, - ( state ) => [ - state.blocks.parents, - state.blocks.order, - state.blockListSettings, - state.editorMode, - state.settings.templateLock, - state.blocks.byClientId, - getSectionRootClientId( state ), - ] -); + } + return result; +}; /** * Retrieves the client ID is a content locking parent * * @param {Object} state Global application state. - * @param {Object} clientId Client Id of the block. + * @param {string} clientId Client Id of the block. * * @return {boolean} Whether the block is a content locking parent. */ From 7b5071548fa50a5008303f10351a8ccb6a796fdd Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 26 Sep 2024 00:39:11 +0900 Subject: [PATCH 0956/1908] Zoom out: Move the toggle button to before the device preview dropdown (#65446) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- packages/editor/src/components/header/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index aca91daaac7324..b5ec9032aac596 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -134,6 +134,9 @@ function Header( { */ <PostSavedState forceIsDirty={ forceIsDirty } /> ) } + + { isEditorIframed && isWideViewport && <ZoomOutToggle /> } + <PreviewDropdown forceIsAutosaveable={ forceIsDirty } disabled={ isNestedEntity } @@ -144,8 +147,6 @@ function Header( { /> <PostViewLink /> - { isEditorIframed && isWideViewport && <ZoomOutToggle /> } - { ( isWideViewport || ! showIconLabels ) && ( <PinnedItems.Slot scope="core" /> ) } From 0bfec0f91843b993a929e6aafe9548cf07690eea Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Wed, 25 Sep 2024 18:44:30 +0300 Subject: [PATCH 0957/1908] DatePicker: Use compact button size (#65653) * DatePicker: Use compact button size * CHANGELOG Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/date-time/date/index.tsx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 71aa08d6934034..08e1027f3e7870 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -10,6 +10,7 @@ ### Enhancements - `MenuGroup`: Simplify the MenuGroup styles within dropdown menus. ([#65561](https://github.com/WordPress/gutenberg/pull/65561)). +- `DatePicker`: Use compact button size. ([#65653](https://github.com/WordPress/gutenberg/pull/65653)). ## 28.8.0 (2024-09-19) diff --git a/packages/components/src/date-time/date/index.tsx b/packages/components/src/date-time/date/index.tsx index 33fc736564d5e6..5a565ee38cec59 100644 --- a/packages/components/src/date-time/date/index.tsx +++ b/packages/components/src/date-time/date/index.tsx @@ -125,6 +125,7 @@ export function DatePicker( { ) ); } } + size="compact" /> <NavigatorHeading level={ 3 }> <strong> @@ -150,6 +151,7 @@ export function DatePicker( { ) ); } } + size="compact" /> </Navigator> <Calendar From 0c097a37c283f333ff90c55b48fe838c524580da Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 26 Sep 2024 01:23:04 +0900 Subject: [PATCH 0958/1908] Zoom out: Reset zoom out level when device type is changed (#65652) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: AhmarZaidi <ahmarzaidi@git.wordpress.org> --- packages/editor/src/components/preview-dropdown/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js index 38565f4b04abed..0fbb2beb62665e 100644 --- a/packages/editor/src/components/preview-dropdown/index.js +++ b/packages/editor/src/components/preview-dropdown/index.js @@ -28,6 +28,7 @@ import { ActionItem } from '@wordpress/interface'; import { store as editorStore } from '../../store'; import { store as blockEditorStore } from '@wordpress/block-editor'; import PostPreviewButton from '../post-preview-button'; +import { unlock } from '../../lock-unlock'; export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { const { deviceType, homeUrl, isTemplate, isViewable, showIconLabels } = @@ -46,10 +47,12 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { }, [] ); const { setDeviceType } = useDispatch( editorStore ); const { __unstableSetEditorMode } = useDispatch( blockEditorStore ); + const { resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); const handleDevicePreviewChange = ( newDeviceType ) => { setDeviceType( newDeviceType ); __unstableSetEditorMode( 'edit' ); + resetZoomLevel(); }; const isMobile = useViewportMatch( 'medium', '<' ); From c6025de88cd29dc3fe7b1fa528d39a26c1c1fd9a Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 25 Sep 2024 18:46:33 +0200 Subject: [PATCH 0959/1908] Use `registry` instead of `select` in `canUserEditValue` (#65659) --- .../src/components/rich-text/index.js | 2 +- packages/block-library/src/button/edit.js | 5 +-- packages/block-library/src/image/edit.js | 5 +-- packages/block-library/src/image/image.js | 9 +++--- packages/editor/src/bindings/post-meta.js | 32 +++++++++++-------- 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 46ddb2b70a113d..1a412a3b2d7eb4 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -188,7 +188,7 @@ export function RichTextWrapper( const _disableBoundBlock = ! blockBindingsSource?.canUserEditValue?.( { - select, + registry, context: blockBindingsContext, args: relatedBinding.args, } ); diff --git a/packages/block-library/src/button/edit.js b/packages/block-library/src/button/edit.js index d7b8e6486c3c66..2749199d1092ae 100644 --- a/packages/block-library/src/button/edit.js +++ b/packages/block-library/src/button/edit.js @@ -48,7 +48,7 @@ import { store as blocksStore, } from '@wordpress/blocks'; import { useMergeRefs, useRefEffect } from '@wordpress/compose'; -import { useSelect, useDispatch } from '@wordpress/data'; +import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; const LINK_SETTINGS = [ ...LinkControl.DEFAULT_LINK_SETTINGS, @@ -190,6 +190,7 @@ function ButtonEdit( props ) { const colorProps = useColorProps( attributes ); const spacingProps = useSpacingProps( attributes ); const shadowProps = useShadowProps( attributes ); + const registry = useRegistry(); const ref = useRef(); const richTextRef = useRef(); const blockProps = useBlockProps( { @@ -248,7 +249,7 @@ function ButtonEdit( props ) { lockUrlControls: !! metadata?.bindings?.url && ! blockBindingsSource?.canUserEditValue?.( { - select, + registry, context, args: metadata?.bindings?.url?.args, } ), diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index d44dc73abfd855..454b49dfb58b32 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -9,7 +9,7 @@ import clsx from 'clsx'; import { isBlobURL, createBlobURL } from '@wordpress/blob'; import { store as blocksStore, createBlock } from '@wordpress/blocks'; import { Placeholder } from '@wordpress/components'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { useDispatch, useSelect, useRegistry } from '@wordpress/data'; import { BlockIcon, useBlockProps, @@ -113,6 +113,7 @@ export function ImageEdit( { const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob ); + const registry = useRegistry(); const containerRef = useRef(); // Only observe the max width from the parent container when the parent layout is not flex nor grid. // This won't work for them because the container width changes with the image. @@ -380,7 +381,7 @@ export function ImageEdit( { lockUrlControls: !! metadata?.bindings?.url && ! blockBindingsSource?.canUserEditValue?.( { - select, + registry, context, args: metadata?.bindings?.url?.args, } ), diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 1673d36e463d5a..f0d2f00a68d531 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -17,7 +17,7 @@ import { Placeholder, } from '@wordpress/components'; import { useViewportMatch } from '@wordpress/compose'; -import { useSelect, useDispatch } from '@wordpress/data'; +import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; import { BlockControls, InspectorControls, @@ -134,6 +134,7 @@ export default function Image( { const numericWidth = width ? parseInt( width, 10 ) : undefined; const numericHeight = height ? parseInt( height, 10 ) : undefined; + const registry = useRegistry(); const imageRef = useRef(); const { allowResize = true } = context; const { getBlock, getSettings } = useSelect( blockEditorStore ); @@ -496,7 +497,7 @@ export default function Image( { lockUrlControls: !! urlBinding && ! urlBindingSource?.canUserEditValue?.( { - select, + registry, context, args: urlBinding?.args, } ), @@ -511,7 +512,7 @@ export default function Image( { lockAltControls: !! altBinding && ! altBindingSource?.canUserEditValue?.( { - select, + registry, context, args: altBinding?.args, } ), @@ -525,7 +526,7 @@ export default function Image( { lockTitleControls: !! titleBinding && ! titleBindingSource?.canUserEditValue?.( { - select, + registry, context, args: titleBinding?.args, } ), diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index fae010e72d1c8b..4cd05f594daf74 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -99,14 +99,15 @@ export default { meta: newMeta, } ); }, - canUserEditValue( { select, context, args } ) { + canUserEditValue( { registry, context, args } ) { // Lock editing in query loop. if ( context?.query || context?.queryId ) { return false; } const postType = - context?.postType || select( editorStore ).getCurrentPostType(); + context?.postType || + registry.select( editorStore ).getCurrentPostType(); // Check that editing is happening in the post editor and not a template. if ( postType === 'wp_template' ) { @@ -115,28 +116,31 @@ export default { // Check that the custom field is not protected and available in the REST API. // Empty string or `false` could be a valid value, so we need to check if the field value is undefined. - const fieldValue = select( coreDataStore ).getEntityRecord( - 'postType', - postType, - context?.postId - )?.meta?.[ args.key ]; + const fieldValue = registry + .select( coreDataStore ) + .getEntityRecord( 'postType', postType, context?.postId )?.meta?.[ + args.key + ]; if ( fieldValue === undefined ) { return false; } // Check that custom fields metabox is not enabled. - const areCustomFieldsEnabled = - select( editorStore ).getEditorSettings().enableCustomFields; + const areCustomFieldsEnabled = registry + .select( editorStore ) + .getEditorSettings().enableCustomFields; if ( areCustomFieldsEnabled ) { return false; } // Check that the user has the capability to edit post meta. - const canUserEdit = select( coreDataStore ).canUser( 'update', { - kind: 'postType', - name: context?.postType, - id: context?.postId, - } ); + const canUserEdit = registry + .select( coreDataStore ) + .canUser( 'update', { + kind: 'postType', + name: context?.postType, + id: context?.postId, + } ); if ( ! canUserEdit ) { return false; } From 05607f785ea7c653ef831a15e6b28985ae0fbd2a Mon Sep 17 00:00:00 2001 From: Cris Busquets <busquets.cris@gmail.com> Date: Wed, 25 Sep 2024 18:49:13 +0200 Subject: [PATCH 0960/1908] Adds envelope icon (#65638) Co-authored-by: crisbusquets <cbusquets1989@git.wordpress.org> --- packages/icons/CHANGELOG.md | 2 ++ packages/icons/src/index.js | 1 + packages/icons/src/library/envelope.js | 16 ++++++++++++++++ 3 files changed, 19 insertions(+) create mode 100644 packages/icons/src/library/envelope.js diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index be047e2181d4a5..08c7ab95b4b4a1 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -6,6 +6,8 @@ ### New Features +- Add new `envelope` icon. + - Add new `bell` and `bell-unread` icons. ## 10.7.0 (2024-09-05) diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index 9ab41bd3620279..e61be2cc86bcd3 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -79,6 +79,7 @@ export { default as drawerLeft } from './library/drawer-left'; export { default as drawerRight } from './library/drawer-right'; export { default as download } from './library/download'; export { default as edit } from './library/edit'; +export { default as envelope } from './library/envelope'; export { default as external } from './library/external'; export { default as file } from './library/file'; export { default as filter } from './library/filter'; diff --git a/packages/icons/src/library/envelope.js b/packages/icons/src/library/envelope.js new file mode 100644 index 00000000000000..45064b35785ec1 --- /dev/null +++ b/packages/icons/src/library/envelope.js @@ -0,0 +1,16 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const envelope = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path + fillRule="evenodd" + clipRule="evenodd" + d="M3 7c0-1.1.9-2 2-2h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7Zm2-.5h14c.3 0 .5.2.5.5v1L12 13.5 4.5 7.9V7c0-.3.2-.5.5-.5Zm-.5 3.3V17c0 .3.2.5.5.5h14c.3 0 .5-.2.5-.5V9.8L12 15.4 4.5 9.8Z" + /> + </SVG> +); + +export default envelope; From 79a8904156237b9121feb10bd06886ff32115f66 Mon Sep 17 00:00:00 2001 From: Vipul Gupta <55375170+vipul0425@users.noreply.github.com> Date: Wed, 25 Sep 2024 22:20:18 +0530 Subject: [PATCH 0961/1908] Fix: Button Replace remaining 40px default size violations [Block Directory] (#65467) * fix: The button height for install button and keep as HTML. * Refactor downloadable list item to vanilla button * Remove unnecessary comment * Update package-lock.json --------- Co-authored-by: vipul0425 <vipulgupta003@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- package-lock.json | 6 +- packages/block-directory/package.json | 3 +- .../downloadable-block-list-item/index.js | 137 +++++++++--------- .../downloadable-block-list-item/style.scss | 33 +++-- .../downloadable-blocks-panel/style.scss | 3 - .../src/plugins/get-install-missing/index.js | 3 +- .../get-install-missing/install-button.js | 3 +- 7 files changed, 101 insertions(+), 87 deletions(-) diff --git a/package-lock.json b/package-lock.json index 93da356b222be4..c13e4cf2096cd0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52730,7 +52730,8 @@ "@wordpress/plugins": "file:../plugins", "@wordpress/private-apis": "file:../private-apis", "@wordpress/url": "file:../url", - "change-case": "^4.1.2" + "change-case": "^4.1.2", + "clsx": "^2.1.1" }, "engines": { "node": ">=18.12.0", @@ -67941,7 +67942,8 @@ "@wordpress/plugins": "file:../plugins", "@wordpress/private-apis": "file:../private-apis", "@wordpress/url": "file:../url", - "change-case": "^4.1.2" + "change-case": "^4.1.2", + "clsx": "^2.1.1" } }, "@wordpress/block-editor": { diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index beef057bf05f04..974125a5f3f2c3 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -45,7 +45,8 @@ "@wordpress/plugins": "file:../plugins", "@wordpress/private-apis": "file:../private-apis", "@wordpress/url": "file:../url", - "change-case": "^4.1.2" + "change-case": "^4.1.2", + "clsx": "^2.1.1" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/block-directory/src/components/downloadable-block-list-item/index.js b/packages/block-directory/src/components/downloadable-block-list-item/index.js index ac587dc2d6d0cc..7a5f479174ab25 100644 --- a/packages/block-directory/src/components/downloadable-block-list-item/index.js +++ b/packages/block-directory/src/components/downloadable-block-list-item/index.js @@ -1,9 +1,14 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + /** * WordPress dependencies */ import { __, _n, sprintf } from '@wordpress/i18n'; import { - Button, + Tooltip, Spinner, VisuallyHidden, Composite, @@ -89,77 +94,75 @@ function DownloadableBlockListItem( { item, onClick } ) { statusText = __( 'Installing…' ); } + const itemLabel = getDownloadableBlockLabel( item, { + hasNotice, + isInstalled, + isInstalling, + } ); + return ( - <Composite.Item - render={ - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - accessibleWhenDisabled - type="button" - role="option" - className="block-directory-downloadable-block-list-item" - isBusy={ isInstalling } - onClick={ ( event ) => { - event.preventDefault(); - onClick(); - } } - label={ getDownloadableBlockLabel( item, { - hasNotice, - isInstalled, - isInstalling, - } ) } - showTooltip - tooltipPosition="top center" - /> - } - disabled={ isInstalling || ! isInstallable } - > - <div className="block-directory-downloadable-block-list-item__icon"> - <DownloadableBlockIcon icon={ icon } title={ title } /> - { isInstalling ? ( - <span className="block-directory-downloadable-block-list-item__spinner"> - <Spinner /> - </span> - ) : ( - <BlockRatings rating={ rating } /> + <Tooltip placement="top" text={ itemLabel }> + <Composite.Item + className={ clsx( + 'block-directory-downloadable-block-list-item', + isInstalling && 'is-installing' ) } - </div> - <span className="block-directory-downloadable-block-list-item__details"> - <span className="block-directory-downloadable-block-list-item__title"> - { createInterpolateElement( - sprintf( - /* translators: %1$s: block title, %2$s: author name. */ - __( '%1$s <span>by %2$s</span>' ), - decodeEntities( title ), - author - ), - { - span: ( - <span className="block-directory-downloadable-block-list-item__author" /> + accessibleWhenDisabled + disabled={ isInstalling || ! isInstallable } + onClick={ ( event ) => { + event.preventDefault(); + onClick(); + } } + aria-label={ itemLabel } + type="button" + role="option" + > + <div className="block-directory-downloadable-block-list-item__icon"> + <DownloadableBlockIcon icon={ icon } title={ title } /> + { isInstalling ? ( + <span className="block-directory-downloadable-block-list-item__spinner"> + <Spinner /> + </span> + ) : ( + <BlockRatings rating={ rating } /> + ) } + </div> + <span className="block-directory-downloadable-block-list-item__details"> + <span className="block-directory-downloadable-block-list-item__title"> + { createInterpolateElement( + sprintf( + /* translators: %1$s: block title, %2$s: author name. */ + __( '%1$s <span>by %2$s</span>' ), + decodeEntities( title ), + author ), - } + { + span: ( + <span className="block-directory-downloadable-block-list-item__author" /> + ), + } + ) } + </span> + { hasNotice ? ( + <DownloadableBlockNotice block={ item } /> + ) : ( + <> + <span className="block-directory-downloadable-block-list-item__desc"> + { !! statusText + ? statusText + : decodeEntities( description ) } + </span> + { isInstallable && + ! ( isInstalled || isInstalling ) && ( + <VisuallyHidden> + { __( 'Install block' ) } + </VisuallyHidden> + ) } + </> ) } </span> - { hasNotice ? ( - <DownloadableBlockNotice block={ item } /> - ) : ( - <> - <span className="block-directory-downloadable-block-list-item__desc"> - { !! statusText - ? statusText - : decodeEntities( description ) } - </span> - { isInstallable && - ! ( isInstalled || isInstalling ) && ( - <VisuallyHidden> - { __( 'Install block' ) } - </VisuallyHidden> - ) } - </> - ) } - </span> - </Composite.Item> + </Composite.Item> + </Tooltip> ); } diff --git a/packages/block-directory/src/components/downloadable-block-list-item/style.scss b/packages/block-directory/src/components/downloadable-block-list-item/style.scss index 8f95297bd9ef0d..fa5e5906cb1b9f 100644 --- a/packages/block-directory/src/components/downloadable-block-list-item/style.scss +++ b/packages/block-directory/src/components/downloadable-block-list-item/style.scss @@ -1,10 +1,21 @@ .block-directory-downloadable-block-list-item { - padding: $grid-unit-15; + & + & { + margin-top: $grid-unit-05; + } + + display: grid; + grid-template-columns: auto 1fr; + width: 100%; height: auto; + padding: $grid-unit-15; + margin: 0; + + appearance: none; + background: none; + border: 0; text-align: left; - display: grid; - grid-template-columns: auto 1fr; + transition: box-shadow 0.1s linear; // The item contains absolutely positioned items. // Set `position: relative` on the parent to prevent overflow issues @@ -12,13 +23,20 @@ // See: https://github.com/WordPress/gutenberg/issues/63384 position: relative; + + &:not([aria-disabled="true"]) { + cursor: pointer; + } + &:hover { @include button-style__focus(); } - &.is-busy { - background: transparent; + &[data-focus-visible] { + @include button-style__focus(); + } + &.is-installing { .block-directory-downloadable-block-list-item__author { border: 0; clip: rect(1px, 1px, 1px, 1px); @@ -33,11 +51,6 @@ word-wrap: normal !important; } } - - &:disabled, - &[aria-disabled] { - opacity: 1; - } } .block-directory-downloadable-block-list-item__icon { diff --git a/packages/block-directory/src/components/downloadable-blocks-panel/style.scss b/packages/block-directory/src/components/downloadable-blocks-panel/style.scss index ff3fdb9ea8e319..f4df5ad4abda53 100644 --- a/packages/block-directory/src/components/downloadable-blocks-panel/style.scss +++ b/packages/block-directory/src/components/downloadable-blocks-panel/style.scss @@ -32,6 +32,3 @@ margin-top: 0; } -.block-directory-downloadable-blocks-panel button { - margin-top: $grid-unit-05; -} diff --git a/packages/block-directory/src/plugins/get-install-missing/index.js b/packages/block-directory/src/plugins/get-install-missing/index.js index 8b192cbe8fdc49..43c051cb9aa371 100644 --- a/packages/block-directory/src/plugins/get-install-missing/index.js +++ b/packages/block-directory/src/plugins/get-install-missing/index.js @@ -101,8 +101,7 @@ const ModifiedWarning = ( { originalBlock, ...props } ) => { ); actions.push( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize key="convert" onClick={ convertToHTML } variant="tertiary" diff --git a/packages/block-directory/src/plugins/get-install-missing/install-button.js b/packages/block-directory/src/plugins/get-install-missing/install-button.js index 3b05b53a380b9a..ec4a48dd39bf53 100644 --- a/packages/block-directory/src/plugins/get-install-missing/install-button.js +++ b/packages/block-directory/src/plugins/get-install-missing/install-button.js @@ -22,8 +22,7 @@ export default function InstallButton( { attributes, block, clientId } ) { return ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize onClick={ () => installBlockType( block ).then( ( success ) => { if ( success ) { From e321b5af6d95884bc38cbd27890753255b477f6a Mon Sep 17 00:00:00 2001 From: VATALIYA PARTH <88878890+PARTHVATALIYA@users.noreply.github.com> Date: Wed, 25 Sep 2024 22:30:47 +0530 Subject: [PATCH 0962/1908] Fix: Button Replace remaining 40px default size violations [Block Editor 5] (#65361) * Fix: inspector control tabs to use 40px default button size * Fix: inspector popover header to use 40px default button size * Fix: link control to use 40px default button size * Fix: list view to use 40px default button size * Fix: media placeholder to use 40px default button size * Add size attribute to inspector popover header and list view * Revert the changes for submit button * Replace button component * Remove override CSS * Remove __next40pxDefaultSize prop Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> * Remove __next40pxDefaultSize prop Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> --------- Co-authored-by: PARTHVATALIYA <parthvataliya@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/block-inspector/style.scss | 2 + .../inspector-controls-tabs/index.js | 41 ++++++++++--------- .../inspector-popover-header/index.js | 6 +-- .../inspector-popover-header/style.scss | 13 ------ .../src/components/link-control/index.js | 6 +-- .../link-control/settings-drawer.js | 3 +- .../list-view/block-select-button.js | 7 +--- .../src/components/list-view/style.scss | 9 ++++ .../src/components/media-placeholder/index.js | 18 +++----- 9 files changed, 45 insertions(+), 60 deletions(-) diff --git a/packages/block-editor/src/components/block-inspector/style.scss b/packages/block-editor/src/components/block-inspector/style.scss index bdbf3660d9619e..92a9a0dd03ab35 100644 --- a/packages/block-editor/src/components/block-inspector/style.scss +++ b/packages/block-editor/src/components/block-inspector/style.scss @@ -49,4 +49,6 @@ .block-editor-block-inspector__tab-item { flex: 1 1 0px; + display: flex; + justify-content: center; } diff --git a/packages/block-editor/src/components/inspector-controls-tabs/index.js b/packages/block-editor/src/components/inspector-controls-tabs/index.js index 601854373b7eb0..c8d9536aeb9caf 100644 --- a/packages/block-editor/src/components/inspector-controls-tabs/index.js +++ b/packages/block-editor/src/components/inspector-controls-tabs/index.js @@ -2,7 +2,8 @@ * WordPress dependencies */ import { - Button, + Icon, + Tooltip, privateApis as componentsPrivateApis, } from '@wordpress/components'; import { store as preferencesStore } from '@wordpress/preferences'; @@ -43,27 +44,27 @@ export default function InspectorControlsTabs( { <div className="block-editor-block-inspector__tabs"> <Tabs defaultTabId={ initialTabName } key={ clientId }> <Tabs.TabList> - { tabs.map( ( tab ) => ( - <Tabs.Tab - key={ tab.name } - tabId={ tab.name } - render={ - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - icon={ - ! showIconLabels ? tab.icon : undefined - } - label={ - ! showIconLabels ? tab.title : undefined - } + { tabs.map( ( tab ) => + showIconLabels ? ( + <Tabs.Tab + key={ tab.name } + tabId={ tab.name } + className={ tab.className } + > + { tab.title } + </Tabs.Tab> + ) : ( + <Tooltip text={ tab.title } key={ tab.name }> + <Tabs.Tab + tabId={ tab.name } className={ tab.className } + aria-label={ tab.title } > - { showIconLabels && tab.title } - </Button> - } - /> - ) ) } + <Icon icon={ tab.icon } /> + </Tabs.Tab> + </Tooltip> + ) + ) } </Tabs.TabList> <Tabs.TabPanel tabId={ TAB_SETTINGS.name } focusable={ false }> <SettingsTab showAdvancedControls={ !! blockName } /> diff --git a/packages/block-editor/src/components/inspector-popover-header/index.js b/packages/block-editor/src/components/inspector-popover-header/index.js index d543ab0298cc62..cf6bf0d3d6796e 100644 --- a/packages/block-editor/src/components/inspector-popover-header/index.js +++ b/packages/block-editor/src/components/inspector-popover-header/index.js @@ -31,8 +31,7 @@ export default function InspectorPopoverHeader( { <Spacer /> { actions.map( ( { label, icon, onClick } ) => ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + size="small" key={ label } className="block-editor-inspector-popover-header__action" label={ label } @@ -45,8 +44,7 @@ export default function InspectorPopoverHeader( { ) ) } { onClose && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + size="small" className="block-editor-inspector-popover-header__action" label={ __( 'Close' ) } icon={ closeSmall } diff --git a/packages/block-editor/src/components/inspector-popover-header/style.scss b/packages/block-editor/src/components/inspector-popover-header/style.scss index ebb76aab23e28a..1ce9ec07f64094 100644 --- a/packages/block-editor/src/components/inspector-popover-header/style.scss +++ b/packages/block-editor/src/components/inspector-popover-header/style.scss @@ -1,16 +1,3 @@ .block-editor-inspector-popover-header { margin-bottom: $grid-unit-20; } - -[class].block-editor-inspector-popover-header__action { - height: $icon-size; - - &.has-icon { - min-width: $icon-size; - padding: 0; - } - - &:not(.has-icon) { - text-decoration: underline; - } -} diff --git a/packages/block-editor/src/components/link-control/index.js b/packages/block-editor/src/components/link-control/index.js index f0de14f3d68210..0f2ae4a0e05d26 100644 --- a/packages/block-editor/src/components/link-control/index.js +++ b/packages/block-editor/src/components/link-control/index.js @@ -474,16 +474,14 @@ function LinkControl( { className="block-editor-link-control__search-actions" > <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" onClick={ handleCancel } > { __( 'Cancel' ) } </Button> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" onClick={ isDisabled ? noop : handleSubmit } className="block-editor-link-control__search-submit" diff --git a/packages/block-editor/src/components/link-control/settings-drawer.js b/packages/block-editor/src/components/link-control/settings-drawer.js index d8bffbd553f81b..935a50ac99a6f7 100644 --- a/packages/block-editor/src/components/link-control/settings-drawer.js +++ b/packages/block-editor/src/components/link-control/settings-drawer.js @@ -25,8 +25,7 @@ function LinkSettingsDrawer( { children, settingsOpen, setSettingsOpen } ) { return ( <> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="block-editor-link-control__drawer-toggle" aria-expanded={ settingsOpen } onClick={ () => setSettingsOpen( ! settingsOpen ) } diff --git a/packages/block-editor/src/components/list-view/block-select-button.js b/packages/block-editor/src/components/list-view/block-select-button.js index fbfa06ee10936b..3b21fd4a04e6d0 100644 --- a/packages/block-editor/src/components/list-view/block-select-button.js +++ b/packages/block-editor/src/components/list-view/block-select-button.js @@ -7,7 +7,6 @@ import clsx from 'clsx'; * WordPress dependencies */ import { - Button, __experimentalHStack as HStack, __experimentalTruncate as Truncate, } from '@wordpress/components'; @@ -82,9 +81,7 @@ function ListViewBlockSelectButton( } return ( - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + <a className={ clsx( 'block-editor-list-view-block-select-button', className @@ -156,7 +153,7 @@ function ListViewBlockSelectButton( </span> ) } </HStack> - </Button> + </a> ); } diff --git a/packages/block-editor/src/components/list-view/style.scss b/packages/block-editor/src/components/list-view/style.scss index 3ad6d3bd4aab51..297fb9d0a6a2e8 100644 --- a/packages/block-editor/src/components/list-view/style.scss +++ b/packages/block-editor/src/components/list-view/style.scss @@ -216,6 +216,15 @@ text-align: left; position: relative; white-space: nowrap; + border-radius: 2px; + box-sizing: border-box; + color: inherit; + font-family: inherit; + font-size: 13px; + font-weight: 400; + margin: 0; + text-decoration: none; + transition: box-shadow 0.1s linear; .components-modal__content & { padding-left: 0; diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index 4d41289f324c0f..9482c9f4181747 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -87,8 +87,7 @@ const URLSelectionUI = ( { src, onChangeSrc, onSelectURL } ) => { return ( <div className="block-editor-media-placeholder__url-input-container"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="block-editor-media-placeholder__button" onClick={ openURLInput } isPressed={ isURLInputVisible } @@ -389,8 +388,7 @@ export function MediaPlaceholder( { return ( onCancel && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="block-editor-media-placeholder__cancel-button" title={ __( 'Cancel' ) } variant="link" @@ -419,8 +417,7 @@ export function MediaPlaceholder( { onToggleFeaturedImage && ( <div className="block-editor-media-placeholder__url-input-container"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="block-editor-media-placeholder__button" onClick={ onToggleFeaturedImage } variant="secondary" @@ -436,8 +433,7 @@ export function MediaPlaceholder( { const defaultButton = ( { open } ) => { return ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="secondary" onClick={ () => { open(); @@ -477,8 +473,7 @@ export function MediaPlaceholder( { const content = ( <> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" className={ clsx( 'block-editor-media-placeholder__button', @@ -508,8 +503,7 @@ export function MediaPlaceholder( { <FormFileUpload render={ ( { openFileDialog } ) => ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize onClick={ openFileDialog } variant="primary" className={ clsx( From 1bf76ccbdaac86a6188270d0825b8ae510422e41 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 25 Sep 2024 19:18:53 +0200 Subject: [PATCH 0963/1908] Only pass usesContext properties to block bindings editor APIs (#65661) Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/block-editor/src/hooks/use-bindings-attributes.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index 9f9234ad47d103..0fb8c38ce28d3e 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -117,7 +117,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( // used purposely here to ensure `boundAttributes` is updated whenever // there are attribute updates. // `source.getValues` may also call a selector via `registry.select`. - const updatedContext = { ...context }; + const updatedContext = {}; const boundAttributes = useSelect( () => { if ( ! blockBindings ) { return; @@ -285,7 +285,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( { ...props } attributes={ { ...props.attributes, ...boundAttributes } } setAttributes={ _setAttributes } - context={ updatedContext } + context={ { ...context, ...updatedContext } } /> </> ); From 0a09968b49ea8fce73e02bd64b47c33b578f649f Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 25 Sep 2024 19:32:10 +0200 Subject: [PATCH 0964/1908] Block Bindings: Fix editing protected custom fields in block bindings (#65658) * Use `getPostMetaFields` in `canUserEditValue` * Add e2e test Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- packages/e2e-tests/plugins/block-bindings.php | 7 ++--- packages/editor/src/bindings/post-meta.js | 9 ++----- .../editor/various/block-bindings.spec.js | 27 +++++++++++++++++++ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/packages/e2e-tests/plugins/block-bindings.php b/packages/e2e-tests/plugins/block-bindings.php index 8951255d516bfc..0629a397286023 100644 --- a/packages/e2e-tests/plugins/block-bindings.php +++ b/packages/e2e-tests/plugins/block-bindings.php @@ -55,9 +55,10 @@ function gutenberg_test_block_bindings_registration() { 'post', '_protected_field', array( - 'type' => 'string', - 'single' => true, - 'default' => 'protected field value', + 'type' => 'string', + 'show_in_rest' => true, + 'single' => true, + 'default' => 'protected field value', ) ); register_meta( diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index 4cd05f594daf74..267d01003b80c4 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -114,14 +114,9 @@ export default { return false; } - // Check that the custom field is not protected and available in the REST API. + const fieldValue = getPostMetaFields( registry, context )?.[ args.key ] + ?.value; // Empty string or `false` could be a valid value, so we need to check if the field value is undefined. - const fieldValue = registry - .select( coreDataStore ) - .getEntityRecord( 'postType', postType, context?.postId )?.meta?.[ - args.key - ]; - if ( fieldValue === undefined ) { return false; } diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index 010d173e760ca9..f172a424bb1729 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -2390,6 +2390,33 @@ test.describe( 'Block bindings', () => { previewPage.locator( '#image-alt-binding img' ) ).toHaveAttribute( 'alt', 'new value' ); } ); + + test( 'should not be possible to edit the value of the protected custom fields', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'paragraph default content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { key: '_protected_field' }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + + await expect( paragraphBlock ).toHaveAttribute( + 'contenteditable', + 'false' + ); + } ); } ); } ); From 893d6848d3b125eb4b43c42f1d552b020cf3c3c3 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 26 Sep 2024 02:51:12 +0900 Subject: [PATCH 0965/1908] MediaPlaceholder: Use InputControl in URL popover (#65656) * MediaPlaceholder: Use InputControl in URL popover * Tweak width in mobile Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../components/media-placeholder/content.scss | 22 ++---------- .../src/components/media-placeholder/index.js | 34 +++++++++---------- 2 files changed, 20 insertions(+), 36 deletions(-) diff --git a/packages/block-editor/src/components/media-placeholder/content.scss b/packages/block-editor/src/components/media-placeholder/content.scss index eeb2928df80baf..2f7bb2e673f12e 100644 --- a/packages/block-editor/src/components/media-placeholder/content.scss +++ b/packages/block-editor/src/components/media-placeholder/content.scss @@ -1,27 +1,11 @@ .block-editor-media-placeholder__url-input-form { - display: flex; - - // Selector requires a lot of specificity to override base styles. - input[type="url"].block-editor-media-placeholder__url-input-field { - width: 100%; - min-width: 200px; - - @include break-small() { - width: 300px; - } - - flex-grow: 1; - border: none; - border-radius: 0; - margin: 2px; + min-width: 260px; + @include break-small() { + width: 300px; } } -.block-editor-media-placeholder__url-input-submit-button { - flex-shrink: 1; -} - .block-editor-media-placeholder__cancel-button.is-link { margin: 1em; display: block; diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index 9482c9f4181747..f16e4317227235 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -11,6 +11,8 @@ import { FormFileUpload, Placeholder, DropZone, + __experimentalInputControl as InputControl, + __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper, withFilters, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; @@ -42,21 +44,23 @@ const InsertFromURLPopover = ( { className="block-editor-media-placeholder__url-input-form" onSubmit={ onSubmit } > - <input - className="block-editor-media-placeholder__url-input-field" - type="text" - aria-label={ __( 'URL' ) } + <InputControl + __next40pxDefaultSize + label={ __( 'URL' ) } + hideLabelFromVision placeholder={ __( 'Paste or type URL' ) } onChange={ onChange } value={ src } - /> - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - className="block-editor-media-placeholder__url-input-submit-button" - icon={ keyboardReturn } - label={ __( 'Apply' ) } - type="submit" + suffix={ + <InputControlSuffixWrapper variant="control"> + <Button + size="small" + icon={ keyboardReturn } + label={ __( 'Apply' ) } + type="submit" + /> + </InputControlSuffixWrapper> + } /> </form> </URLPopover> @@ -166,10 +170,6 @@ export function MediaPlaceholder( { ); }; - const onChangeSrc = ( event ) => { - setSrc( event.target.value ); - }; - const onFilesUpload = ( files ) => { if ( ! handleUpload || @@ -405,7 +405,7 @@ export function MediaPlaceholder( { onSelectURL && ( <URLSelectionUI src={ src } - onChangeSrc={ onChangeSrc } + onChangeSrc={ setSrc } onSelectURL={ onSelectURL } /> ) From 0ee3ed6c45019edaacddbad54f6f06ad4271443d Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 25 Sep 2024 20:01:37 +0200 Subject: [PATCH 0966/1908] Block Bindings: Fix showing bindings field values in theme templates (#65639) * Move `is_custom` check to page case * Check themeSlug in conditional * Use `post.slug` directly Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- .../editor/src/components/provider/index.js | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 11b1478d58434a..0c45dbc5e7199c 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -188,26 +188,19 @@ export const ExperimentalEditorProvider = withRegistryProvider( const postContext = {}; // If it is a template, try to inherit the post type from the slug. if ( post.type === 'wp_template' ) { - if ( ! post.is_custom ) { - const [ kind ] = post.slug.split( '-' ); - switch ( kind ) { - case 'page': - postContext.postType = 'page'; - break; - case 'single': - // Infer the post type from the slug. - const postTypesSlugs = - postTypes?.map( ( entity ) => entity.slug ) || - []; - const match = post.slug.match( - `^single-(${ postTypesSlugs.join( - '|' - ) })(?:-.+)?$` - ); - if ( match ) { - postContext.postType = match[ 1 ]; - } - break; + if ( post.slug === 'page' ) { + postContext.postType = 'page'; + } else if ( post.slug === 'single' ) { + postContext.postType = 'post'; + } else if ( post.slug.split( '-' )[ 0 ] === 'single' ) { + // If the slug is single-{postType}, infer the post type from the slug. + const postTypesSlugs = + postTypes?.map( ( entity ) => entity.slug ) || []; + const match = post.slug.match( + `^single-(${ postTypesSlugs.join( '|' ) })(?:-.+)?$` + ); + if ( match ) { + postContext.postType = match[ 1 ]; } } } else if ( From d9551aa23046725fd76db5842520eadaeeb155f4 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Wed, 25 Sep 2024 13:08:14 -0500 Subject: [PATCH 0967/1908] Revert "Allow multi-select on iOS Safari/touch devices (#63671)" (#65414) This reverts commit 6aeba745bcba51621310a318e8dccfdf3eb4c92e. --- .../use-focus-first-element.js | 1 - .../event-listeners/paste-handler.js | 7 +- .../src/components/rich-text/index.js | 14 +--- .../src/components/writing-flow/index.js | 2 - .../components/writing-flow/use-arrow-nav.js | 11 +-- .../writing-flow/use-event-redirect.js | 72 ------------------- .../src/components/writing-flow/use-input.js | 37 +--------- .../components/writing-flow/use-select-all.js | 19 +---- .../writing-flow/use-selection-observer.js | 17 +---- .../src/components/writing-flow/utils.js | 30 -------- packages/dom/src/dom/place-caret-at-edge.js | 12 ++-- .../component/event-listeners/copy-handler.js | 17 ++--- .../event-listeners/input-and-selection.js | 19 +++-- .../editor/various/block-deletion.spec.js | 11 ++- .../editor/various/pattern-overrides.spec.js | 4 +- 15 files changed, 36 insertions(+), 237 deletions(-) delete mode 100644 packages/block-editor/src/components/writing-flow/use-event-redirect.js diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js b/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js index a6308f48005f9d..27f72d1a100d3e 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js @@ -68,7 +68,6 @@ export function useFocusFirstElement( { clientId, initialPosition } ) { textInputs[ isReverse ? textInputs.length - 1 : 0 ] || ref.current; if ( ! isInsideRootBlock( ref.current, target ) ) { - ownerDocument.defaultView.getSelection().removeAllRanges(); ref.current.focus(); return; } diff --git a/packages/block-editor/src/components/rich-text/event-listeners/paste-handler.js b/packages/block-editor/src/components/rich-text/event-listeners/paste-handler.js index 9266cd25537545..59633f4750ff92 100644 --- a/packages/block-editor/src/components/rich-text/event-listeners/paste-handler.js +++ b/packages/block-editor/src/components/rich-text/event-listeners/paste-handler.js @@ -26,15 +26,10 @@ export default ( props ) => ( element ) => { preserveWhiteSpace, pastePlainText, } = props.current; - const { ownerDocument } = element; - const { defaultView } = ownerDocument; - const { anchorNode, focusNode } = defaultView.getSelection(); - const containsSelection = - element.contains( anchorNode ) && element.contains( focusNode ); // The event listener is attached to the window, so we need to check if // the target is the element. - if ( ! containsSelection ) { + if ( event.target !== element ) { return; } diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 1a412a3b2d7eb4..83cf5e564c68be 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -397,19 +397,7 @@ export function RichTextWrapper( const inputEvents = useRef( new Set() ); function onFocus() { - let element = anchorRef.current; - - if ( ! element ) { - return; - } - - // Writing flow might be editable, so we should make sure focus goes to - // the root editable element. - while ( element.parentElement?.isContentEditable ) { - element = element.parentElement; - } - - element.focus(); + anchorRef.current?.focus(); } const TagName = tagName; diff --git a/packages/block-editor/src/components/writing-flow/index.js b/packages/block-editor/src/components/writing-flow/index.js index cea3e4b19707dd..7e6b36b0e22143 100644 --- a/packages/block-editor/src/components/writing-flow/index.js +++ b/packages/block-editor/src/components/writing-flow/index.js @@ -23,7 +23,6 @@ import useSelectionObserver from './use-selection-observer'; import useClickSelection from './use-click-selection'; import useInput from './use-input'; import useClipboardHandler from './use-clipboard-handler'; -import useEventRedirect from './use-event-redirect'; import { store as blockEditorStore } from '../../store'; export function useWritingFlow() { @@ -66,7 +65,6 @@ export function useWritingFlow() { }, [ hasMultiSelection ] ), - useEventRedirect(), ] ), after, ]; diff --git a/packages/block-editor/src/components/writing-flow/use-arrow-nav.js b/packages/block-editor/src/components/writing-flow/use-arrow-nav.js index fda5a0133ee00c..44051b324ff64d 100644 --- a/packages/block-editor/src/components/writing-flow/use-arrow-nav.js +++ b/packages/block-editor/src/components/writing-flow/use-arrow-nav.js @@ -19,7 +19,6 @@ import { useRefEffect } from '@wordpress/compose'; */ import { getBlockClientId, isInSameBlock } from '../../utils/dom'; import { store as blockEditorStore } from '../../store'; -import { getSelectionRoot } from './utils'; /** * Returns true if the element should consider edge navigation upon a keyboard @@ -191,7 +190,8 @@ export default function useArrowNav() { return; } - const { keyCode, shiftKey, ctrlKey, altKey, metaKey } = event; + const { keyCode, target, shiftKey, ctrlKey, altKey, metaKey } = + event; const isUp = keyCode === UP; const isDown = keyCode === DOWN; const isLeft = keyCode === LEFT; @@ -233,11 +233,6 @@ export default function useArrowNav() { return; } - const target = - ownerDocument.activeElement === node - ? getSelectionRoot( ownerDocument ) - : event.target; - // Abort if our current target is not a candidate for navigation // (e.g. preserve native input behaviors). if ( ! isNavigationCandidate( target, keyCode, hasModifier ) ) { @@ -279,7 +274,6 @@ export default function useArrowNav() { ( altKey ? isHorizontalEdge( target, isReverseDir ) : true ) && ! keepCaretInsideBlock ) { - node.contentEditable = false; const closestTabbable = getClosestTabbable( target, isReverse, @@ -303,7 +297,6 @@ export default function useArrowNav() { isHorizontalEdge( target, isReverseDir ) && ! keepCaretInsideBlock ) { - node.contentEditable = false; const closestTabbable = getClosestTabbable( target, isReverseDir, diff --git a/packages/block-editor/src/components/writing-flow/use-event-redirect.js b/packages/block-editor/src/components/writing-flow/use-event-redirect.js deleted file mode 100644 index b8dcd7eda69697..00000000000000 --- a/packages/block-editor/src/components/writing-flow/use-event-redirect.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * WordPress dependencies - */ -import { useRefEffect } from '@wordpress/compose'; - -/** - * Internal dependencies - */ -import { getSelectionRoot } from './utils'; - -/** - * Whenever content editable is enabled on writing flow, it will have focus, so - * we need to dispatch some events to the root of the selection to ensure - * compatibility with rich text. In the future, perhaps the rich text event - * handlers should be attached to the window instead. - * - * Alternatively, we could try to find a way to always maintain rich text focus. - */ -export default function useEventRedirect() { - return useRefEffect( ( node ) => { - function onInput( event ) { - if ( event.target !== node ) { - return; - } - - const { ownerDocument } = node; - const { defaultView } = ownerDocument; - const prototype = Object.getPrototypeOf( event ); - const constructorName = prototype.constructor.name; - const Constructor = defaultView[ constructorName ]; - const root = getSelectionRoot( ownerDocument ); - - if ( ! root || root === node ) { - return; - } - - const init = {}; - - for ( const key in event ) { - init[ key ] = event[ key ]; - } - - init.bubbles = false; - - const newEvent = new Constructor( event.type, init ); - const cancelled = ! root.dispatchEvent( newEvent ); - - if ( cancelled ) { - event.preventDefault(); - } - } - - const events = [ - 'beforeinput', - 'input', - 'compositionstart', - 'compositionend', - 'compositionupdate', - 'keydown', - ]; - - events.forEach( ( eventType ) => { - node.addEventListener( eventType, onInput ); - } ); - - return () => { - events.forEach( ( eventType ) => { - node.removeEventListener( eventType, onInput ); - } ); - }; - }, [] ); -} diff --git a/packages/block-editor/src/components/writing-flow/use-input.js b/packages/block-editor/src/components/writing-flow/use-input.js index 31c5d769834c01..0f10cc9c2d1c75 100644 --- a/packages/block-editor/src/components/writing-flow/use-input.js +++ b/packages/block-editor/src/components/writing-flow/use-input.js @@ -16,7 +16,6 @@ import { * Internal dependencies */ import { store as blockEditorStore } from '../../store'; -import { getSelectionRoot } from './utils'; /** * Handles input for selections across blocks. @@ -50,24 +49,7 @@ export default function useInput() { // DOM. This will cause React errors (and the DOM should only be // altered in a controlled fashion). if ( node.contentEditable === 'true' ) { - const selection = node.ownerDocument.defaultView.getSelection(); - const range = selection.rangeCount - ? selection.getRangeAt( 0 ) - : null; - const root = getSelectionRoot( node.ownerDocument ); - - // If selection is contained within a nested editable, allow - // input. We need to ensure that selection is maintained. - if ( root ) { - node.contentEditable = false; - root.focus(); - selection.removeAllRanges(); - if ( range ) { - selection.addRange( range ); - } - } else { - event.preventDefault(); - } + event.preventDefault(); } } @@ -77,23 +59,6 @@ export default function useInput() { } if ( ! hasMultiSelection() ) { - const { ownerDocument } = node; - if ( node === ownerDocument.activeElement ) { - if ( event.key === 'End' || event.key === 'Home' ) { - const selectionRoot = getSelectionRoot( ownerDocument ); - const selection = - ownerDocument.defaultView.getSelection(); - selection.selectAllChildren( selectionRoot ); - const method = - event.key === 'End' - ? 'collapseToEnd' - : 'collapseToStart'; - selection[ method ](); - event.preventDefault(); - return; - } - } - if ( event.keyCode === ENTER ) { if ( event.shiftKey || __unstableIsFullySelected() ) { return; diff --git a/packages/block-editor/src/components/writing-flow/use-select-all.js b/packages/block-editor/src/components/writing-flow/use-select-all.js index 5a7acb3a8783a4..c56549acf54ad5 100644 --- a/packages/block-editor/src/components/writing-flow/use-select-all.js +++ b/packages/block-editor/src/components/writing-flow/use-select-all.js @@ -10,7 +10,6 @@ import { useRefEffect } from '@wordpress/compose'; * Internal dependencies */ import { store as blockEditorStore } from '../../store'; -import { getSelectionRoot } from './utils'; export default function useSelectAll() { const { getBlockOrder, getSelectedBlockClientIds, getBlockRootClientId } = @@ -24,27 +23,12 @@ export default function useSelectAll() { return; } - const selectionRoot = getSelectionRoot( node.ownerDocument ); const selectedClientIds = getSelectedBlockClientIds(); - // Abort if there is selection, but it is not within a block. - if ( selectionRoot && ! selectedClientIds.length ) { - return; - } - if ( - selectionRoot && selectedClientIds.length < 2 && - ! isEntirelySelected( selectionRoot ) + ! isEntirelySelected( event.target ) ) { - if ( node === node.ownerDocument.activeElement ) { - event.preventDefault(); - node.ownerDocument.defaultView - .getSelection() - .selectAllChildren( selectionRoot ); - return; - } - return; } @@ -61,7 +45,6 @@ export default function useSelectAll() { node.ownerDocument.defaultView .getSelection() .removeAllRanges(); - node.contentEditable = 'false'; selectBlock( rootClientId ); } return; diff --git a/packages/block-editor/src/components/writing-flow/use-selection-observer.js b/packages/block-editor/src/components/writing-flow/use-selection-observer.js index 8ecba461d1025f..c7ce5d259d875a 100644 --- a/packages/block-editor/src/components/writing-flow/use-selection-observer.js +++ b/packages/block-editor/src/components/writing-flow/use-selection-observer.js @@ -107,12 +107,8 @@ function getRichTextElement( node ) { export default function useSelectionObserver() { const { multiSelect, selectBlock, selectionChange } = useDispatch( blockEditorStore ); - const { - getBlockParents, - getBlockSelectionStart, - isMultiSelecting, - getSelectedBlockClientId, - } = useSelect( blockEditorStore ); + const { getBlockParents, getBlockSelectionStart, isMultiSelecting } = + useSelect( blockEditorStore ); return useRefEffect( ( node ) => { const { ownerDocument } = node; @@ -195,17 +191,10 @@ export default function useSelectionObserver() { return; } - setContentEditableWrapper( - node, - !! ( startClientId && endClientId ) - ); - const isSingularSelection = startClientId === endClientId; if ( isSingularSelection ) { if ( ! isMultiSelecting() ) { - if ( getSelectedBlockClientId() !== startClientId ) { - selectBlock( startClientId ); - } + selectBlock( startClientId ); } else { multiSelect( startClientId, startClientId ); } diff --git a/packages/block-editor/src/components/writing-flow/utils.js b/packages/block-editor/src/components/writing-flow/utils.js index 0cd41eedd3f6f1..2a2010854ed205 100644 --- a/packages/block-editor/src/components/writing-flow/utils.js +++ b/packages/block-editor/src/components/writing-flow/utils.js @@ -116,33 +116,3 @@ function toPlainText( html ) { // Merge any consecutive line breaks return plainText.replace( /\n\n+/g, '\n\n' ); } - -/** - * Gets the current content editable root element based on the selection. - * @param {Document} ownerDocument - * @return {Element|undefined} The content editable root element. - */ -export function getSelectionRoot( ownerDocument ) { - const { defaultView } = ownerDocument; - const { anchorNode, focusNode } = defaultView.getSelection(); - - if ( ! anchorNode || ! focusNode ) { - return; - } - - const anchorElement = ( - anchorNode.nodeType === anchorNode.ELEMENT_NODE - ? anchorNode - : anchorNode.parentElement - ).closest( '[contenteditable]' ); - - if ( ! anchorElement ) { - return; - } - - if ( ! anchorElement.contains( focusNode ) ) { - return; - } - - return anchorElement; -} diff --git a/packages/dom/src/dom/place-caret-at-edge.js b/packages/dom/src/dom/place-caret-at-edge.js index 013a64d076e559..4075fc7c439586 100644 --- a/packages/dom/src/dom/place-caret-at-edge.js +++ b/packages/dom/src/dom/place-caret-at-edge.js @@ -67,14 +67,7 @@ export default function placeCaretAtEdge( container, isReverse, x ) { return; } - const { ownerDocument } = container; - const { defaultView } = ownerDocument; - assertIsDefined( defaultView, 'defaultView' ); - const selection = defaultView.getSelection(); - assertIsDefined( selection, 'selection' ); - if ( ! container.isContentEditable ) { - selection.removeAllRanges(); return; } @@ -86,6 +79,11 @@ export default function placeCaretAtEdge( container, isReverse, x ) { return; } + const { ownerDocument } = container; + const { defaultView } = ownerDocument; + assertIsDefined( defaultView, 'defaultView' ); + const selection = defaultView.getSelection(); + assertIsDefined( selection, 'selection' ); selection.removeAllRanges(); selection.addRange( range ); } diff --git a/packages/rich-text/src/component/event-listeners/copy-handler.js b/packages/rich-text/src/component/event-listeners/copy-handler.js index 1a92237bb4c5b4..0cc1594c3ab914 100644 --- a/packages/rich-text/src/component/event-listeners/copy-handler.js +++ b/packages/rich-text/src/component/event-listeners/copy-handler.js @@ -2,21 +2,18 @@ * Internal dependencies */ import { toHTMLString } from '../../to-html-string'; +import { isCollapsed } from '../../is-collapsed'; import { slice } from '../../slice'; -import { remove } from '../../remove'; import { getTextContent } from '../../get-text-content'; export default ( props ) => ( element ) => { function onCopy( event ) { - const { record, createRecord, handleChange } = props.current; + const { record } = props.current; const { ownerDocument } = element; - const { defaultView } = ownerDocument; - const { anchorNode, focusNode, isCollapsed } = - defaultView.getSelection(); - const containsSelection = - element.contains( anchorNode ) && element.contains( focusNode ); - - if ( isCollapsed || ! containsSelection ) { + if ( + isCollapsed( record.current ) || + ! element.contains( ownerDocument.activeElement ) + ) { return; } @@ -29,7 +26,7 @@ export default ( props ) => ( element ) => { event.preventDefault(); if ( event.type === 'cut' ) { - handleChange( remove( createRecord() ) ); + ownerDocument.execCommand( 'delete' ); } } diff --git a/packages/rich-text/src/component/event-listeners/input-and-selection.js b/packages/rich-text/src/component/event-listeners/input-and-selection.js index 11dcdb0d8ff9ab..621f1c59fab04e 100644 --- a/packages/rich-text/src/component/event-listeners/input-and-selection.js +++ b/packages/rich-text/src/component/event-listeners/input-and-selection.js @@ -114,13 +114,14 @@ export default ( props ) => ( element ) => { return; } - const { anchorNode, focusNode } = defaultView.getSelection(); - const containsSelection = - element.contains( anchorNode ) && - element.contains( focusNode ) && - ownerDocument.activeElement.contains( element ); - - if ( ! containsSelection ) { + // Ensure the active element is the rich text element. + if ( ownerDocument.activeElement !== element ) { + // If it is not, we can stop listening for selection changes. We + // resume listening when the element is focused. + ownerDocument.removeEventListener( + 'selectionchange', + handleSelectionChange + ); return; } @@ -254,9 +255,5 @@ export default ( props ) => ( element ) => { element.removeEventListener( 'compositionstart', onCompositionStart ); element.removeEventListener( 'compositionend', onCompositionEnd ); element.removeEventListener( 'focus', onFocus ); - ownerDocument.removeEventListener( - 'selectionchange', - handleSelectionChange - ); }; }; diff --git a/test/e2e/specs/editor/various/block-deletion.spec.js b/test/e2e/specs/editor/various/block-deletion.spec.js index 00b51a94668d50..9346412c46bcb2 100644 --- a/test/e2e/specs/editor/various/block-deletion.spec.js +++ b/test/e2e/specs/editor/various/block-deletion.spec.js @@ -287,16 +287,15 @@ test.describe( 'Block deletion', () => { await expect.poll( editor.getBlocks ).toMatchObject( [ { name: 'core/paragraph', attributes: { content: 'First' } }, { name: 'core/paragraph', attributes: { content: 'Second' } }, + { name: 'core/paragraph', attributes: { content: '' } }, ] ); // Ensure that the newly created empty block is focused. - await expect.poll( editor.getBlocks ).toHaveLength( 2 ); + await expect.poll( editor.getBlocks ).toHaveLength( 3 ); await expect( - editor.canvas - .getByRole( 'document', { - name: 'Block: Paragraph', - } ) - .nth( 1 ) + editor.canvas.getByRole( 'document', { + name: 'Empty block', + } ) ).toBeFocused(); } ); diff --git a/test/e2e/specs/editor/various/pattern-overrides.spec.js b/test/e2e/specs/editor/various/pattern-overrides.spec.js index 83f2f880f3bf1b..5fbd0e66b5fd02 100644 --- a/test/e2e/specs/editor/various/pattern-overrides.spec.js +++ b/test/e2e/specs/editor/various/pattern-overrides.spec.js @@ -150,7 +150,7 @@ test.describe( 'Pattern Overrides', () => { name: 'Block: Paragraph', } ); // Ensure the first pattern is selected. - await editor.selectBlocks( patternBlocks.first() ); + await patternBlocks.first().selectText(); await expect( paragraphs.first() ).not.toHaveAttribute( 'inert', 'true' @@ -168,7 +168,7 @@ test.describe( 'Pattern Overrides', () => { await page.keyboard.type( 'I would word it this way' ); // Ensure the second pattern is selected. - await editor.selectBlocks( patternBlocks.last() ); + await patternBlocks.last().selectText(); await patternBlocks .last() .getByRole( 'document', { From 4a625e5f097056d5f23c1a68385b3327573727bf Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Thu, 26 Sep 2024 00:02:01 +0530 Subject: [PATCH 0968/1908] Fix: Button: Replace remaining 40px default size violation [Edit Site 3] (#65309) * Fix patterns link button title to use 40px default size * Fix open save panel button default size to 40px * Fix editor sidebar buttons to use 40px defualt size * Fix data views create new views buttons to use 40px default size * Fix site hub buttons to use 40px default button size --------- Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/page-patterns/fields.js | 3 +-- .../src/components/save-panel/index.js | 3 +-- .../src/components/sidebar-button/index.js | 3 +-- .../sidebar-dataviews/add-new-view.js | 6 ++---- .../edit-site/src/components/site-hub/index.js | 18 ++++++------------ 5 files changed, 11 insertions(+), 22 deletions(-) diff --git a/packages/edit-site/src/components/page-patterns/fields.js b/packages/edit-site/src/components/page-patterns/fields.js index ff9c0dbe81a047..88de0c1fa39b01 100644 --- a/packages/edit-site/src/components/page-patterns/fields.js +++ b/packages/edit-site/src/components/page-patterns/fields.js @@ -133,8 +133,7 @@ function TitleField( { item } ) { title ) : ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="link" onClick={ onClick } // Required for the grid's roving tab index system. diff --git a/packages/edit-site/src/components/save-panel/index.js b/packages/edit-site/src/components/save-panel/index.js index babcf72181a1af..9b00a39fd78948 100644 --- a/packages/edit-site/src/components/save-panel/index.js +++ b/packages/edit-site/src/components/save-panel/index.js @@ -150,8 +150,7 @@ export default function SavePanel() { } ) } > <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="secondary" className="edit-site-editor__toggle-save-panel-button" onClick={ () => setIsSaveViewOpened( true ) } diff --git a/packages/edit-site/src/components/sidebar-button/index.js b/packages/edit-site/src/components/sidebar-button/index.js index d7030597dac503..64c6efb891f462 100644 --- a/packages/edit-site/src/components/sidebar-button/index.js +++ b/packages/edit-site/src/components/sidebar-button/index.js @@ -11,8 +11,7 @@ import { Button } from '@wordpress/components'; export default function SidebarButton( props ) { return ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize { ...props } className={ clsx( 'edit-site-sidebar-button', props.className ) } /> diff --git a/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js b/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js index 3e369db9b2a821..62956ccd18960d 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js +++ b/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js @@ -88,8 +88,7 @@ function AddNewItemModalContent( { type, setIsAdding } ) { /> <HStack justify="right"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" onClick={ () => { setIsAdding( false ); @@ -99,8 +98,7 @@ function AddNewItemModalContent( { type, setIsAdding } ) { </Button> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" type="submit" aria-disabled={ ! title || isSaving } diff --git a/packages/edit-site/src/components/site-hub/index.js b/packages/edit-site/src/components/site-hub/index.js index 7fe929d20a1db2..8cb3502493cff0 100644 --- a/packages/edit-site/src/components/site-hub/index.js +++ b/packages/edit-site/src/components/site-hub/index.js @@ -62,8 +62,7 @@ const SiteHub = memo( ) } > <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize ref={ ref } href={ dashboardLink } label={ __( 'Go to the Dashboard' ) } @@ -80,8 +79,7 @@ const SiteHub = memo( <HStack> <div className="edit-site-site-hub__title"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="link" href={ homeUrl } target="_blank" @@ -101,8 +99,7 @@ const SiteHub = memo( className="edit-site-site-hub__actions" > <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="edit-site-site-hub_toggle-command-center" icon={ search } onClick={ () => openCommandCenter() } @@ -149,8 +146,7 @@ export const SiteHubMobile = memo( ) } > <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize ref={ ref } label={ __( 'Go to Site Editor' ) } className="edit-site-layout__view-mode-toggle" @@ -170,8 +166,7 @@ export const SiteHubMobile = memo( <HStack> <div className="edit-site-site-hub__title"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="link" href={ homeUrl } target="_blank" @@ -186,8 +181,7 @@ export const SiteHubMobile = memo( className="edit-site-site-hub__actions" > <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="edit-site-site-hub_toggle-command-center" icon={ search } onClick={ () => openCommandCenter() } From b08b18be960a48b370e90cf2e8438573ac617742 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Thu, 26 Sep 2024 00:05:40 +0530 Subject: [PATCH 0969/1908] Plugin: Fix small typo in readme.txt file (#65634) Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: Soean <soean@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index c5ef1231b183ee..4bd7ddc36d6e9b 100644 --- a/readme.txt +++ b/readme.txt @@ -55,7 +55,7 @@ To report a security issue, please visit the [WordPress HackerOne](https://hacke = Do I have to use the Gutenberg plugin to get access to these features? = -Not necessarily. Each version of WordPress after 5.0 has included features from the Gutenberg plugin, which are known collectively as the <a href="https://wordpress.org/documentation/article/wordpress-block-editor/">WordPress Editor</a>. You are likely already benefitting from stable features! +Not necessarily. Each version of WordPress after 5.0 has included features from the Gutenberg plugin, which are known collectively as the <a href="https://wordpress.org/documentation/article/wordpress-block-editor/">WordPress Editor</a>. You are likely already benefiting from stable features! But if you want cutting edge beta features, including more experimental items, you will need to use the plugin. You can <a href="https://wordpress.org/news/2021/04/become-an-early-adopter-with-the-gutenberg-plugin/">read more here</a> to help decide whether the plugin is right for you. From e33271c96c14be4172ddaa696a03f96738e062c7 Mon Sep 17 00:00:00 2001 From: Brad Jorsch <anomiex@users.noreply.github.com> Date: Wed, 25 Sep 2024 15:02:06 -0400 Subject: [PATCH 0970/1908] DEWP: Check for magic comments before minification (#65582) Look for magic wp:polyfill comments before minification. Avoids having to configure Terser to preserve these comments, and also avoids having them in the minified JS. Minifiers run in the processAssets hook at the `PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE` stage. If we hook at the `PROCESS_ASSETS_STAGE_OPTIMIZE_COMPATIBILITY` stage to check for the magic comments, we don't have to worry about configuring Terser to preserve them (and won't have to have them making the output slightly larger either). --------- Co-authored-by: anomiex <bjorsch@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: sgomes <sergiomdgomes@git.wordpress.org> --- .../CHANGELOG.md | 4 ++ .../lib/index.js | 71 ++++++++++++++++++- .../test/__snapshots__/build.js.snap | 14 ++++ .../polyfill-magic-comment-minified/index.js | 3 + .../webpack.config.js | 11 +++ tools/webpack/shared.js | 2 +- 6 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment-minified/index.js create mode 100644 packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment-minified/webpack.config.js diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index 1c0aa630495a0b..7c8f74d2906fed 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Detection of magic comments is now done before minification ([#65582](https://github.com/WordPress/gutenberg/pull/65582)). + ### Bug Fixes - Fix a bug where cycles in dependent modules could enter infinite recursion ([#65291](https://github.com/WordPress/gutenberg/pull/65291)). diff --git a/packages/dependency-extraction-webpack-plugin/lib/index.js b/packages/dependency-extraction-webpack-plugin/lib/index.js index 529fb339d15a14..cf780d7370dcfc 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/index.js +++ b/packages/dependency-extraction-webpack-plugin/lib/index.js @@ -162,6 +162,14 @@ class DependencyExtractionWebpackPlugin { compiler.hooks.thisCompilation.tap( this.constructor.name, ( compilation ) => { + compilation.hooks.processAssets.tap( + { + name: this.constructor.name, + stage: compiler.webpack.Compilation + .PROCESS_ASSETS_STAGE_OPTIMIZE_COMPATIBILITY, + }, + () => this.checkForMagicComments( compilation ) + ); compilation.hooks.processAssets.tap( { name: this.constructor.name, @@ -174,6 +182,60 @@ class DependencyExtractionWebpackPlugin { ); } + /** + * Check for magic comments before minification, so minification doesn't have to preserve them. + * @param {webpack.Compilation} compilation + */ + checkForMagicComments( compilation ) { + // Accumulate all entrypoint chunks, some of them shared + const entrypointChunks = new Set(); + for ( const entrypoint of compilation.entrypoints.values() ) { + for ( const chunk of entrypoint.chunks ) { + entrypointChunks.add( chunk ); + } + } + + // Process each entrypoint chunk independently + for ( const chunk of entrypointChunks ) { + const chunkFiles = Array.from( chunk.files ); + + const jsExtensionRegExp = this.useModules ? /\.m?js$/i : /\.js$/i; + + const chunkJSFile = chunkFiles.find( ( f ) => + jsExtensionRegExp.test( f ) + ); + if ( ! chunkJSFile ) { + // There's no JS file in this chunk, no work for us. Typically a `style.css` from cache group. + continue; + } + + // Prepare to look for magic comments, in order to decide whether + // `wp-polyfill` is needed. + const processContentsForMagicComments = ( content ) => { + const magicComments = []; + + if ( content.includes( '/* wp:polyfill */' ) ) { + magicComments.push( 'wp-polyfill' ); + } + + return magicComments; + }; + + // Go through the assets to process the sources. + // This allows us to look for magic comments. + chunkFiles.sort().forEach( ( filename ) => { + const asset = compilation.getAsset( filename ); + const content = asset.source.buffer(); + + const wpMagicComments = + processContentsForMagicComments( content ); + compilation.updateAsset( filename, ( v ) => v, { + wpMagicComments, + } ); + } ); + } + } + /** @param {webpack.Compilation} compilation */ addAssets( compilation ) { const { @@ -286,8 +348,11 @@ class DependencyExtractionWebpackPlugin { // Prepare to look for magic comments, in order to decide whether // `wp-polyfill` is needed. - const processContentsForMagicComments = ( content ) => { - if ( content.includes( '/* wp:polyfill */' ) ) { + const handleMagicComments = ( info ) => { + if ( ! info ) { + return; + } + if ( info.includes( 'wp-polyfill' ) ) { chunkStaticDeps.add( 'wp-polyfill' ); } }; @@ -299,7 +364,7 @@ class DependencyExtractionWebpackPlugin { const content = asset.source.buffer(); processContentsForHash( content ); - processContentsForMagicComments( content ); + handleMagicComments( asset.info.wpMagicComments ); } ); // Finalise hash. diff --git a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap index 903c9658250b17..f0d418851103ba 100644 --- a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap +++ b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap @@ -257,6 +257,13 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comm exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comment\` should produce expected output: External modules should match snapshot 1`] = `[]`; +exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comment-minified\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` +"<?php return array('dependencies' => array('wp-polyfill'), 'version' => '31d6cfe0d16ae931b73c', 'type' => 'module'); +" +`; + +exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comment-minified\` should produce expected output: External modules should match snapshot 1`] = `[]`; + exports[`DependencyExtractionWebpackPlugin modules Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'a.asset.php' should match snapshot 1`] = ` "<?php return array('dependencies' => array('@wordpress/blob'), 'version' => 'a1906cfc819b623c86f8', 'type' => 'module'); " @@ -666,6 +673,13 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comm exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comment\` should produce expected output: External modules should match snapshot 1`] = `[]`; +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comment-minified\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` +"<?php return array('dependencies' => array('wp-polyfill'), 'version' => '31d6cfe0d16ae931b73c'); +" +`; + +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comment-minified\` should produce expected output: External modules should match snapshot 1`] = `[]`; + exports[`DependencyExtractionWebpackPlugin scripts Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'a.asset.php' should match snapshot 1`] = ` "<?php return array('dependencies' => array('wp-blob'), 'version' => 'd3cda564b538b44d38ef'); " diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment-minified/index.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment-minified/index.js new file mode 100644 index 00000000000000..d98678f44cb697 --- /dev/null +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment-minified/index.js @@ -0,0 +1,3 @@ +/* wp:polyfill */ + +// Nothing else, really. diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment-minified/webpack.config.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment-minified/webpack.config.js new file mode 100644 index 00000000000000..be01328d675d0a --- /dev/null +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment-minified/webpack.config.js @@ -0,0 +1,11 @@ +/** + * Internal dependencies + */ +const DependencyExtractionWebpackPlugin = require( '../../..' ); + +module.exports = { + optimization: { + minimize: true, + }, + plugins: [ new DependencyExtractionWebpackPlugin() ], +}; diff --git a/tools/webpack/shared.js b/tools/webpack/shared.js index c8c5b05c7d151b..f30d3a830f3eb1 100644 --- a/tools/webpack/shared.js +++ b/tools/webpack/shared.js @@ -25,7 +25,7 @@ const baseConfig = { parallel: true, terserOptions: { output: { - comments: /(translators:|wp:polyfill)/i, + comments: /translators:/i, }, compress: { passes: 2, From 8857e607894d7bb0d7d57372face893328200618 Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Wed, 25 Sep 2024 23:57:48 +0200 Subject: [PATCH 0971/1908] BorderBoxControl: Promote to stable (#65586) * Update README and JSDoc * Export without experimental prefix * Move Storybook stories and add redirect * Update imports * Add changelog entries * Fix typo in story. * Make `enableStyle` `true` by default in story. * Fix changelog * Fix changelog Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../components/global-styles/border-panel.js | 2 +- packages/components/CHANGELOG.md | 5 ++ .../border-box-control/README.md | 48 +++++++++---------- .../border-box-control/component.tsx | 17 ++----- .../stories/index.story.tsx | 3 +- packages/components/src/index.ts | 2 + storybook/manager-head.html | 1 + 7 files changed, 36 insertions(+), 42 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/border-panel.js b/packages/block-editor/src/components/global-styles/border-panel.js index cc7a464f8634a9..aea8e67f5b5944 100644 --- a/packages/block-editor/src/components/global-styles/border-panel.js +++ b/packages/block-editor/src/components/global-styles/border-panel.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { - __experimentalBorderBoxControl as BorderBoxControl, + BorderBoxControl, __experimentalHasSplitBorders as hasSplitBorders, __experimentalIsDefinedBorder as isDefinedBorder, __experimentalToolsPanel as ToolsPanel, diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 08e1027f3e7870..c3bd150703fc03 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -7,8 +7,13 @@ - `ToolsPanel`: atomic one-step state update when (un)registering panels ([#65564](https://github.com/WordPress/gutenberg/pull/65564)). - `Navigator`: fix `isInitial` logic ([#65527](https://github.com/WordPress/gutenberg/pull/65527)). +### Deprecations + +- `__experimentalBorderBoxControl` can now be imported as a stable `BorderBoxControl` ([#65586](https://github.com/WordPress/gutenberg/pull/65586)). + ### Enhancements +- `BorderBoxControl`: promote to stable ([#65586](https://github.com/WordPress/gutenberg/pull/65586)). - `MenuGroup`: Simplify the MenuGroup styles within dropdown menus. ([#65561](https://github.com/WordPress/gutenberg/pull/65561)). - `DatePicker`: Use compact button size. ([#65653](https://github.com/WordPress/gutenberg/pull/65653)). diff --git a/packages/components/src/border-box-control/border-box-control/README.md b/packages/components/src/border-box-control/border-box-control/README.md index 5ec2263bf16741..e67a1386103c1a 100644 --- a/packages/components/src/border-box-control/border-box-control/README.md +++ b/packages/components/src/border-box-control/border-box-control/README.md @@ -1,12 +1,7 @@ # BorderBoxControl -<div class="callout callout-alert"> -This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. -</div> -<br /> - -This component provides users with the ability to configure a single "flat" -border or separate borders per side. +An input control for the color, style, and width of the border of a box. The +border can be customized as a whole, or individually for each side of the box. ## Development guidelines @@ -28,7 +23,7 @@ show "Mixed" placeholder text. ```jsx import { useState } from 'react'; -import { __experimentalBorderBoxControl as BorderBoxControl } from '@wordpress/components'; +import { BorderBoxControl } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; const colors = [ @@ -76,35 +71,35 @@ colors are organized by multiple origins. Each color may be an object containing a `name` and `color` value. -- Required: No -- Default: `[]` +- Required: No +- Default: `[]` ### `disableCustomColors`: `boolean` This toggles the ability to choose custom colors. -- Required: No +- Required: No ### `enableAlpha`: `boolean` This controls whether the alpha channel will be offered when selecting custom colors. -- Required: No -- Default: `false` +- Required: No +- Default: `false` ### `enableStyle`: `boolean` This controls whether to support border style selections. -- Required: No -- Default: `true` +- Required: No +- Default: `true` ### `hideLabelFromVision`: `boolean` Provides control over whether the label will only be visible to screen readers. -- Required: No +- Required: No ### `label`: `string` @@ -113,7 +108,7 @@ If provided, a label will be generated using this as the content. _Whether it is visible only to screen readers is controlled via `hideLabelFromVision`._ -- Required: No +- Required: No ### `onChange`: `( value?: Object ) => void` @@ -123,7 +118,7 @@ borders, or `undefined`. _Note: The will be `undefined` if a user clears all borders._ -- Required: Yes +- Required: Yes ### `popoverPlacement`: `string` @@ -133,21 +128,21 @@ By default, popovers are displayed relative to the button that initiated the pop The available base placements are 'top', 'right', 'bottom', 'left'. Each of these base placements has an alignment in the form -start and -end. For example, 'right-start', or 'bottom-end'. These allow you to align the tooltip to the edges of the button, rather than centering it. -- Required: No +- Required: No ### `popoverOffset`: `number` The space between the popover and the control wrapper. -- Required: No +- Required: No ### `size`: `string` Size of the control. -- Required: No -- Default: `default` -- Allowed values: `default`, `__unstable-large` +- Required: No +- Default: `default` +- Allowed values: `default`, `__unstable-large` ### `value`: `Object` @@ -158,6 +153,7 @@ properties or a "split" border which defines the previous properties but for each side; `top`, `right`, `bottom`, and `left`. Examples: + ```js const flatBorder = { color: '#72aee6', style: 'solid', width: '1px' }; const splitBorders = { @@ -168,11 +164,11 @@ const splitBorders = { }; ``` -- Required: No +- Required: No ### `__next40pxDefaultSize`: `boolean` Start opting into the larger default height that will become the default size in a future version. -- Required: No -- Default: `false` +- Required: No +- Default: `false` diff --git a/packages/components/src/border-box-control/border-box-control/component.tsx b/packages/components/src/border-box-control/border-box-control/component.tsx index 26967ad7f63ddb..1dd3437aa50de4 100644 --- a/packages/components/src/border-box-control/border-box-control/component.tsx +++ b/packages/components/src/border-box-control/border-box-control/component.tsx @@ -147,22 +147,11 @@ const UnconnectedBorderBoxControl = ( }; /** - * The `BorderBoxControl` effectively has two view states. The first, a "linked" - * view, allows configuration of a flat border via a single `BorderControl`. - * The second, a "split" view, contains a `BorderControl` for each side - * as well as a visualizer for the currently selected borders. Each view also - * contains a button to toggle between the two. - * - * When switching from the "split" view to "linked", if the individual side - * borders are not consistent, the "linked" view will display any border - * properties selections that are consistent while showing a mixed state for - * those that aren't. For example, if all borders had the same color and style - * but different widths, then the border dropdown in the "linked" view's - * `BorderControl` would show that consistent color and style but the "linked" - * view's width input would show "Mixed" placeholder text. + * An input control for the color, style, and width of the border of a box. The + * border can be customized as a whole, or individually for each side of the box. * * ```jsx - * import { __experimentalBorderBoxControl as BorderBoxControl } from '@wordpress/components'; + * import { BorderBoxControl } from '@wordpress/components'; * import { __ } from '@wordpress/i18n'; * * const colors = [ diff --git a/packages/components/src/border-box-control/stories/index.story.tsx b/packages/components/src/border-box-control/stories/index.story.tsx index 5b5d7f311208c0..5341dacab646eb 100644 --- a/packages/components/src/border-box-control/stories/index.story.tsx +++ b/packages/components/src/border-box-control/stories/index.story.tsx @@ -16,7 +16,7 @@ import Button from '../../button'; import { BorderBoxControl } from '../'; const meta: Meta< typeof BorderBoxControl > = { - title: 'Components (Experimental)/BorderBoxControl', + title: 'Components/BorderBoxControl', component: BorderBoxControl, argTypes: { onChange: { action: 'onChange' }, @@ -83,4 +83,5 @@ export const Default = Template.bind( {} ); Default.args = { colors, label: 'Borders', + enableStyle: true, }; diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index a59d258012807d..200225148a0a49 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -33,7 +33,9 @@ export { } from './autocomplete'; export { default as BaseControl, useBaseControlProps } from './base-control'; export { + /** @deprecated Import `BorderBoxControl` instead. */ BorderBoxControl as __experimentalBorderBoxControl, + BorderBoxControl, hasSplitBorders as __experimentalHasSplitBorders, isDefinedBorder as __experimentalIsDefinedBorder, isEmptyBorder as __experimentalIsEmptyBorder, diff --git a/storybook/manager-head.html b/storybook/manager-head.html index 7293248ae3e472..f3eaef13509218 100644 --- a/storybook/manager-head.html +++ b/storybook/manager-head.html @@ -2,6 +2,7 @@ ( function redirectIfStoryMoved() { const PREVIOUSLY_EXPERIMENTAL_COMPONENTS = [ 'alignmentmatrixcontrol', + 'borderboxcontrol', 'boxcontrol', 'customselectcontrol-v2', 'dimensioncontrol', From 057af4ab0a77fe5c7b8615818540b70e43e0856a Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 26 Sep 2024 10:34:09 +1000 Subject: [PATCH 0972/1908] Query Pagination Numbers: Add block example (#65636) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/query-pagination-numbers/index.js | 1 + packages/block-library/src/query-pagination/index.js | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/query-pagination-numbers/index.js b/packages/block-library/src/query-pagination-numbers/index.js index 3fd903e2d9ef48..f769f54b4ac034 100644 --- a/packages/block-library/src/query-pagination-numbers/index.js +++ b/packages/block-library/src/query-pagination-numbers/index.js @@ -16,6 +16,7 @@ export { metadata, name }; export const settings = { icon, edit, + example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); diff --git a/packages/block-library/src/query-pagination/index.js b/packages/block-library/src/query-pagination/index.js index 158106c4ac185a..b113a8384b043b 100644 --- a/packages/block-library/src/query-pagination/index.js +++ b/packages/block-library/src/query-pagination/index.js @@ -20,7 +20,6 @@ export const settings = { edit, save, deprecated, - example: {}, }; export const init = () => initBlock( { name, metadata, settings } ); From 8c5a0b6a4f5e0802d0c84d1f8e6e4934c7a449b3 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 26 Sep 2024 12:45:38 +1000 Subject: [PATCH 0973/1908] Packages documentation: minor typo corrections (#65664) --- packages/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/README.md b/packages/README.md index e780d006f70fbd..b8d2c913a91b9d 100644 --- a/packages/README.md +++ b/packages/README.md @@ -58,7 +58,7 @@ When creating a new package, you need to provide at least the following: Initial release. ``` -To ensure your package is recognised, you should also _manually_ add your new package to the root `package.json` file and then run `npm install` to update the dependencies. +To ensure your package is recognized, you should also _manually_ add your new package to the root `package.json` file and then run `npm install` to update the dependencies. ## Managing Dependencies @@ -104,7 +104,7 @@ Next, you need to run `npm install` in the root of the project to ensure that `p This is the most confusing part of working with [monorepo] which causes a lot of hassles for contributors. The most successful strategy so far is to do the following: 1. First, remove the existing dependency as described in the previous section. -2. Next, add the same dependency back as described in the first section of this chapter. This time it wil get the latest version applied unless you enforce a different version explicitly. +2. Next, add the same dependency back as described in the first section of this chapter. This time it will get the latest version applied unless you enforce a different version explicitly. ### Development Dependencies @@ -152,9 +152,9 @@ It's very important to have a good plan for what a new package will include. All ## Maintaining Changelogs -In maintaining dozens of npm packages, it can be tough to keep track of changes. To simplify the release process, each package includes a `CHANGELOG.md` file which details all published releases and the unreleased ("Unreleased") changes, if any exist. +When maintaining dozens of npm packages, it can be tough to keep track of changes. To simplify the release process, each package includes a `CHANGELOG.md` file which details all published releases and the unreleased ("Unreleased") changes, if any exist. -For each pull request, you should always include relevant changes in a "Unreleased" heading at the top of the file. You should add the heading if it doesn't already exist. +For each pull request, you should always include relevant changes under an "Unreleased" heading at the top of the file. You should add the heading if it doesn't already exist. _Example:_ @@ -200,7 +200,7 @@ Gutenberg uses TypeScript by running the TypeScript compiler (`tsc`) on select p These packages benefit from type checking and produced type declarations in the published packages. To opt-in to TypeScript tooling, packages should include a `tsconfig.json` file in the package root and add an entry to the root `tsconfig.json` references. -The changes will indicate that the package has opted-in and will be included in the TypeScript build process. +The changes will indicate that the package has opted in and will be included in the TypeScript build process. A `tsconfig.json` file should look like the following (comments are not necessary): From 36790842f46566e3e0ff777e5284f348f3dafe76 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Thu, 26 Sep 2024 09:35:31 +0200 Subject: [PATCH 0974/1908] Improve the Query Loop block display settings labels. (#65524) Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../block-library/src/query/edit/inspector-controls/index.js | 4 ++-- .../src/query/edit/inspector-controls/pages-control.js | 2 +- .../src/query/edit/inspector-controls/per-page-control.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index 4085128e9aef1a..3128c3526926f9 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -321,7 +321,7 @@ export default function QueryInspectorControls( props ) { dropdownMenuProps={ dropdownMenuProps } > <ToolsPanelItem - label={ __( 'Items' ) } + label={ __( 'Items per page' ) } hasValue={ () => perPage > 0 } > <PerPageControl @@ -341,7 +341,7 @@ export default function QueryInspectorControls( props ) { /> </ToolsPanelItem> <ToolsPanelItem - label={ __( 'Max Pages to Show' ) } + label={ __( 'Max pages to show' ) } hasValue={ () => pages > 0 } onDeselect={ () => setQuery( { pages: 0 } ) } > diff --git a/packages/block-library/src/query/edit/inspector-controls/pages-control.js b/packages/block-library/src/query/edit/inspector-controls/pages-control.js index cde61453ea844d..06c6e32b66ad2a 100644 --- a/packages/block-library/src/query/edit/inspector-controls/pages-control.js +++ b/packages/block-library/src/query/edit/inspector-controls/pages-control.js @@ -8,7 +8,7 @@ export const PagesControl = ( { pages, onChange } ) => { return ( <NumberControl __next40pxDefaultSize - label={ __( 'Max pages' ) } + label={ __( 'Max pages to show' ) } value={ pages } min={ 0 } onChange={ ( newPages ) => { diff --git a/packages/block-library/src/query/edit/inspector-controls/per-page-control.js b/packages/block-library/src/query/edit/inspector-controls/per-page-control.js index 3e0dfbf50b70bd..933bb0851e6257 100644 --- a/packages/block-library/src/query/edit/inspector-controls/per-page-control.js +++ b/packages/block-library/src/query/edit/inspector-controls/per-page-control.js @@ -12,7 +12,7 @@ const PerPageControl = ( { perPage, offset = 0, onChange } ) => { <RangeControl __next40pxDefaultSize __nextHasNoMarginBottom - label={ __( 'Posts per page' ) } + label={ __( 'Items per page' ) } min={ MIN_POSTS_PER_PAGE } max={ MAX_POSTS_PER_PAGE } onChange={ ( newPerPage ) => { From 69efbca3ba4522b9b11c56a5e517d123fe9a9071 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 26 Sep 2024 09:49:47 +0200 Subject: [PATCH 0975/1908] Navigator: add support for exit animation (#64777) * Refactor screen logic for better clarity and hook deps * Add exit animation, rewrite screen animations / DOM rendering logic * Only add inset CSS rule when animating out * Parametrise animation * CHANGELOG * Add fallback timeout * Mention wrapper height in README * Use `useReducedMotion()` hook instead of custom logic * Extract useScreenAnimatePresence hook, tidy up * Forward animationEnd * Add `setWrapperHeight` functionality via context * Use `clip` instead of `hidden` for overflow-x * Less aggressive clipping for screens that are animating out * Better sizing styles for screen, to keep it more stable while transitioning out * Refine internal animation logic for less jumpy animations * Remove unnecessary Storybook styles * Change wording * Improve logic: - more clear animation status names - apply CSS animation only while effectively animating - fix bug in the animationEnd callback which was matching animation end events too loosely, thus causing glitches * Add timeout fallback for in animations too * Fix animation delay for forwards.out animation * Use display: grid instead of absolute positioning to set provider min height Remove unnecessary import * Simplify navigatorScreenAnimation * Remove unnecessary state element ref * Use "start" and "end" instead of "backwards" and "forwards" * Do not rely on `usePrevious` * Use CSS transitions * Fix Storybook example * Revert "Use CSS transitions" This reverts commit 946f9c953232b788f58050d2a94d9d131527a180. * Switch to data-attributes for less runtime emotion calculations * Add back fallback animation timeout * Move CHANGELOG entry to unreleased section * Clean up code, reduce diff for easier reviewing --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../navigator/navigator-provider/README.md | 6 +- .../navigator/navigator-screen/component.tsx | 84 +++++---- .../use-screen-animate-presence.ts | 177 ++++++++++++++++++ .../src/navigator/stories/index.story.tsx | 11 +- packages/components/src/navigator/styles.ts | 151 +++++++++++---- 6 files changed, 346 insertions(+), 84 deletions(-) create mode 100644 packages/components/src/navigator/navigator-screen/use-screen-animate-presence.ts diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index c3bd150703fc03..94633ec7078108 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -16,6 +16,7 @@ - `BorderBoxControl`: promote to stable ([#65586](https://github.com/WordPress/gutenberg/pull/65586)). - `MenuGroup`: Simplify the MenuGroup styles within dropdown menus. ([#65561](https://github.com/WordPress/gutenberg/pull/65561)). - `DatePicker`: Use compact button size. ([#65653](https://github.com/WordPress/gutenberg/pull/65653)). +- `Navigator`: add support for exit animation ([#64777](https://github.com/WordPress/gutenberg/pull/64777)). ## 28.8.0 (2024-09-19) diff --git a/packages/components/src/navigator/navigator-provider/README.md b/packages/components/src/navigator/navigator-provider/README.md index 35bf7a69720be2..b9bc8f0c6bcdc9 100644 --- a/packages/components/src/navigator/navigator-provider/README.md +++ b/packages/components/src/navigator/navigator-provider/README.md @@ -33,7 +33,7 @@ const MyNavigation = () => ( ); ``` -**Important note** +### Hierarchical `path`s `Navigator` assumes that screens are organized hierarchically according to their `path`, which should follow a URL-like scheme where each path segment starts with and is separated by the `/` character. @@ -47,6 +47,10 @@ For example: - `/parent/:param` is a child of `/parent` as well. - if the current screen has a `path` with value `/parent/child/grand-child`, when going "back" `Navigator` will try to recursively navigate the path hierarchy until a matching screen (or the root `/`) is found. +### Height and animations + +Due to how `NavigatorScreen` animations work, it is recommended that the `NavigatorProvider` component is assigned a `height` to prevent some potential UI jumps while moving across screens. + ## Props The component accepts the following props: diff --git a/packages/components/src/navigator/navigator-screen/component.tsx b/packages/components/src/navigator/navigator-screen/component.tsx index 5882f271d4518f..f2d2c26e576c27 100644 --- a/packages/components/src/navigator/navigator-screen/component.tsx +++ b/packages/components/src/navigator/navigator-screen/component.tsx @@ -15,7 +15,6 @@ import { useId, } from '@wordpress/element'; import { useMergeRefs } from '@wordpress/compose'; -import { isRTL as isRTLFn } from '@wordpress/i18n'; import { escapeAttribute } from '@wordpress/escape-html'; import warning from '@wordpress/warning'; @@ -29,6 +28,7 @@ import { View } from '../../view'; import { NavigatorContext } from '../context'; import * as styles from '../styles'; import type { NavigatorScreenProps } from '../types'; +import { useScreenAnimatePresence } from './use-screen-animate-presence'; function UnconnectedNavigatorScreen( props: WordPressComponentProps< NavigatorScreenProps, 'div', false >, @@ -41,16 +41,24 @@ function UnconnectedNavigatorScreen( } const screenId = useId(); - const { children, className, path, ...otherProps } = useContextSystem( - props, - 'NavigatorScreen' - ); + + const { + children, + className, + path, + onAnimationEnd: onAnimationEndProp, + ...otherProps + } = useContextSystem( props, 'NavigatorScreen' ); const { location, match, addScreen, removeScreen } = useContext( NavigatorContext ); + const { isInitial, isBack, focusTargetSelector, skipFocus } = location; + const isMatch = match === screenId; const wrapperRef = useRef< HTMLDivElement >( null ); + const skipAnimationAndFocusRestoration = !! isInitial && ! isBack; + // Register / unregister screen with the navigator context. useEffect( () => { const screen = { id: screenId, @@ -60,31 +68,28 @@ function UnconnectedNavigatorScreen( return () => removeScreen( screen ); }, [ screenId, path, addScreen, removeScreen ] ); - const isRTL = isRTLFn(); - const { isInitial, isBack } = location; + // Animation. + const { animationStyles, shouldRenderScreen, screenProps } = + useScreenAnimatePresence( { + isMatch, + isBack, + onAnimationEnd: onAnimationEndProp, + skipAnimation: skipAnimationAndFocusRestoration, + } ); + const cx = useCx(); const classes = useMemo( - () => - cx( - styles.navigatorScreen( { - isInitial, - isBack, - isRTL, - } ), - className - ), - [ className, cx, isInitial, isBack, isRTL ] + () => cx( styles.navigatorScreen, animationStyles, className ), + [ className, cx, animationStyles ] ); + // Focus restoration const locationRef = useRef( location ); - useEffect( () => { locationRef.current = location; }, [ location ] ); - - // Focus restoration - const isInitialLocation = location.isInitial && ! location.isBack; useEffect( () => { + const wrapperEl = wrapperRef.current; // Only attempt to restore focus: // - if the current location is not the initial one (to avoid moving focus on page load) // - when the screen becomes visible @@ -92,20 +97,20 @@ function UnconnectedNavigatorScreen( // - if focus hasn't already been restored for the current location // - if the `skipFocus` option is not set to `true`. This is useful when we trigger the navigation outside of NavigatorScreen. if ( - isInitialLocation || + skipAnimationAndFocusRestoration || ! isMatch || - ! wrapperRef.current || + ! wrapperEl || locationRef.current.hasRestoredFocus || - location.skipFocus + skipFocus ) { return; } - const activeElement = wrapperRef.current.ownerDocument.activeElement; + const activeElement = wrapperEl.ownerDocument.activeElement; // If an element is already focused within the wrapper do not focus the // element. This prevents inputs or buttons from losing focus unnecessarily. - if ( wrapperRef.current.contains( activeElement ) ) { + if ( wrapperEl.contains( activeElement ) ) { return; } @@ -113,33 +118,36 @@ function UnconnectedNavigatorScreen( // When navigating back, if a selector is provided, use it to look for the // target element (assumed to be a node inside the current NavigatorScreen) - if ( location.isBack && location.focusTargetSelector ) { - elementToFocus = wrapperRef.current.querySelector( - location.focusTargetSelector - ); + if ( isBack && focusTargetSelector ) { + elementToFocus = wrapperEl.querySelector( focusTargetSelector ); } // If the previous query didn't run or find any element to focus, fallback // to the first tabbable element in the screen (or the screen itself). if ( ! elementToFocus ) { - const [ firstTabbable ] = focus.tabbable.find( wrapperRef.current ); - elementToFocus = firstTabbable ?? wrapperRef.current; + const [ firstTabbable ] = focus.tabbable.find( wrapperEl ); + elementToFocus = firstTabbable ?? wrapperEl; } locationRef.current.hasRestoredFocus = true; elementToFocus.focus(); }, [ - isInitialLocation, + skipAnimationAndFocusRestoration, isMatch, - location.isBack, - location.focusTargetSelector, - location.skipFocus, + isBack, + focusTargetSelector, + skipFocus, ] ); const mergedWrapperRef = useMergeRefs( [ forwardedRef, wrapperRef ] ); - return isMatch ? ( - <View ref={ mergedWrapperRef } className={ classes } { ...otherProps }> + return shouldRenderScreen ? ( + <View + ref={ mergedWrapperRef } + className={ classes } + { ...screenProps } + { ...otherProps } + > { children } </View> ) : null; diff --git a/packages/components/src/navigator/navigator-screen/use-screen-animate-presence.ts b/packages/components/src/navigator/navigator-screen/use-screen-animate-presence.ts new file mode 100644 index 00000000000000..af5a47ee12df4c --- /dev/null +++ b/packages/components/src/navigator/navigator-screen/use-screen-animate-presence.ts @@ -0,0 +1,177 @@ +/** + * WordPress dependencies + */ +import { + useState, + useEffect, + useLayoutEffect, + useCallback, +} from '@wordpress/element'; +import { useReducedMotion } from '@wordpress/compose'; +import { isRTL as isRTLFn } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import * as styles from '../styles'; + +// Possible values: +// - 'INITIAL': the initial state +// - 'ANIMATING_IN': start enter animation +// - 'IN': enter animation has ended +// - 'ANIMATING_OUT': start exit animation +// - 'OUT': the exit animation has ended +type AnimationStatus = + | 'INITIAL' + | 'ANIMATING_IN' + | 'IN' + | 'ANIMATING_OUT' + | 'OUT'; + +// Allow an extra 20% of the total animation duration to account for potential +// event loop delays. +const ANIMATION_TIMEOUT_MARGIN = 1.2; + +const isEnterAnimation = ( + animationDirection: 'end' | 'start', + animationStatus: AnimationStatus, + animationName: string +) => + animationStatus === 'ANIMATING_IN' && + animationName === styles.ANIMATION_END_NAMES[ animationDirection ].in; + +const isExitAnimation = ( + animationDirection: 'end' | 'start', + animationStatus: AnimationStatus, + animationName: string +) => + animationStatus === 'ANIMATING_OUT' && + animationName === styles.ANIMATION_END_NAMES[ animationDirection ].out; + +export function useScreenAnimatePresence( { + isMatch, + skipAnimation, + isBack, + onAnimationEnd, +}: { + isMatch: boolean; + skipAnimation: boolean; + isBack?: boolean; + onAnimationEnd?: React.AnimationEventHandler< Element >; +} ) { + const isRTL = isRTLFn(); + const prefersReducedMotion = useReducedMotion(); + + const [ animationStatus, setAnimationStatus ] = + useState< AnimationStatus >( 'INITIAL' ); + + // Start enter and exit animations when the screen is selected or deselected. + // The animation status is set to `IN` or `OUT` immediately if the animation + // should be skipped. + const becameSelected = + animationStatus !== 'ANIMATING_IN' && + animationStatus !== 'IN' && + isMatch; + const becameUnselected = + animationStatus !== 'ANIMATING_OUT' && + animationStatus !== 'OUT' && + ! isMatch; + useLayoutEffect( () => { + if ( becameSelected ) { + setAnimationStatus( + skipAnimation || prefersReducedMotion ? 'IN' : 'ANIMATING_IN' + ); + } else if ( becameUnselected ) { + setAnimationStatus( + skipAnimation || prefersReducedMotion ? 'OUT' : 'ANIMATING_OUT' + ); + } + }, [ + becameSelected, + becameUnselected, + skipAnimation, + prefersReducedMotion, + ] ); + + // Animation attributes (derived state). + const animationDirection = + ( isRTL && isBack ) || ( ! isRTL && ! isBack ) ? 'end' : 'start'; + const isAnimatingIn = animationStatus === 'ANIMATING_IN'; + const isAnimatingOut = animationStatus === 'ANIMATING_OUT'; + let animationType: 'in' | 'out' | undefined; + if ( isAnimatingIn ) { + animationType = 'in'; + } else if ( isAnimatingOut ) { + animationType = 'out'; + } + + const onScreenAnimationEnd = useCallback( + ( e: React.AnimationEvent< HTMLElement > ) => { + onAnimationEnd?.( e ); + + if ( + isExitAnimation( + animationDirection, + animationStatus, + e.animationName + ) + ) { + // When the exit animation ends on an unselected screen, set the + // status to 'OUT' to remove the screen contents from the DOM. + setAnimationStatus( 'OUT' ); + } else if ( + isEnterAnimation( + animationDirection, + animationStatus, + e.animationName + ) + ) { + // When the enter animation ends on a selected screen, set the + // status to 'IN' to ensure the screen is rendered in the DOM. + setAnimationStatus( 'IN' ); + } + }, + [ onAnimationEnd, animationStatus, animationDirection ] + ); + + // Fallback timeout to ensure that the logic is applied even if the + // `animationend` event is not triggered. + useEffect( () => { + let animationTimeout: number | undefined; + + if ( isAnimatingOut ) { + animationTimeout = window.setTimeout( () => { + setAnimationStatus( 'OUT' ); + animationTimeout = undefined; + }, styles.TOTAL_ANIMATION_DURATION.OUT * ANIMATION_TIMEOUT_MARGIN ); + } else if ( isAnimatingIn ) { + animationTimeout = window.setTimeout( () => { + setAnimationStatus( 'IN' ); + animationTimeout = undefined; + }, styles.TOTAL_ANIMATION_DURATION.IN * ANIMATION_TIMEOUT_MARGIN ); + } + + return () => { + if ( animationTimeout ) { + window.clearTimeout( animationTimeout ); + animationTimeout = undefined; + } + }; + }, [ isAnimatingOut, isAnimatingIn ] ); + + return { + animationStyles: styles.navigatorScreenAnimation, + // Render the screen's contents in the DOM not only when the screen is + // selected, but also while it is animating out. + shouldRenderScreen: + isMatch || + animationStatus === 'IN' || + animationStatus === 'ANIMATING_OUT', + screenProps: { + onAnimationEnd: onScreenAnimationEnd, + 'data-animation-direction': animationDirection, + 'data-animation-type': animationType, + 'data-skip-animation': skipAnimation || undefined, + }, + } as const; +} diff --git a/packages/components/src/navigator/stories/index.story.tsx b/packages/components/src/navigator/stories/index.story.tsx index 30b9c71a368c1a..8edac7e7b81686 100644 --- a/packages/components/src/navigator/stories/index.story.tsx +++ b/packages/components/src/navigator/stories/index.story.tsx @@ -36,12 +36,12 @@ const meta: Meta< typeof NavigatorProvider > = { return ( <> <style>{ ` - /* These attributes are a private implementation detail of the - Navigator component. Do not use outside of its source code. */ + /* The data-wp-component attribute is a private implementation + * detail of the Navigator component. Do not use outside of + * its source code. + */ [data-wp-component="NavigatorProvider"] { - height: calc(100vh - 2rem); - max-height: 250px; - + height: 250px; } [data-wp-component="NavigatorScreen"]:not([data-sticky]) { padding: 8px; @@ -167,6 +167,7 @@ export const SkipFocus: StoryObj< typeof NavigatorProvider > = { outline: '1px solid black', outlineOffset: '-1px', marginBlockEnd: '1rem', + display: 'contents', } } > <NavigatorScreen path="/"> diff --git a/packages/components/src/navigator/styles.ts b/packages/components/src/navigator/styles.ts index 0203edbdf1816a..fd355bf4dd48fb 100644 --- a/packages/components/src/navigator/styles.ts +++ b/packages/components/src/navigator/styles.ts @@ -4,68 +4,139 @@ import { css, keyframes } from '@emotion/react'; export const navigatorProviderWrapper = css` + position: relative; /* Prevents horizontal overflow while animating screen transitions */ - overflow-x: hidden; - /* Mark this subsection of the DOM as isolated, providing performance benefits - * by limiting calculations of layout, style and paint to a DOM subtree rather - * than the entire page. + overflow-x: clip; + /* + * Mark this DOM subtree as isolated when it comes to layout calculations, + * providing performance benefits. */ - contain: content; + contain: layout; + + display: grid; + grid-template-columns: 1fr; + grid-template-rows: 1fr; + align-items: start; `; -const fadeInFromRight = keyframes( { - '0%': { +const fadeIn = keyframes( { + from: { opacity: 0, - transform: `translateX( 50px )`, }, - '100%': { opacity: 1, transform: 'none' }, } ); -const fadeInFromLeft = keyframes( { - '0%': { +const fadeOut = keyframes( { + to: { opacity: 0, - transform: `translateX( -50px )`, }, - '100%': { opacity: 1, transform: 'none' }, } ); -type NavigatorScreenAnimationProps = { - isInitial?: boolean; - isBack?: boolean; - isRTL: boolean; +export const slideFromRight = keyframes( { + from: { + transform: 'translateX(100px)', + }, +} ); + +export const slideToLeft = keyframes( { + to: { + transform: 'translateX(-80px)', + }, +} ); + +export const slideFromLeft = keyframes( { + from: { + transform: 'translateX(-100px)', + }, +} ); + +export const slideToRight = keyframes( { + to: { + transform: 'translateX(80px)', + }, +} ); + +const FADE = { + DURATION: 70, + EASING: 'linear', + DELAY: { + IN: 70, + OUT: 40, + }, +}; +const SLIDE = { + DURATION: 300, + EASING: 'cubic-bezier(0.33, 0, 0, 1)', +}; + +export const TOTAL_ANIMATION_DURATION = { + IN: Math.max( FADE.DURATION + FADE.DELAY.IN, SLIDE.DURATION ), + OUT: Math.max( FADE.DURATION + FADE.DELAY.OUT, SLIDE.DURATION ), }; -const navigatorScreenAnimation = ( { - isInitial, - isBack, - isRTL, -}: NavigatorScreenAnimationProps ) => { - if ( isInitial && ! isBack ) { - return; - } +export const ANIMATION_END_NAMES = { + end: { + in: slideFromRight.name, + out: slideToLeft.name, + }, + start: { + in: slideFromLeft.name, + out: slideToRight.name, + }, +}; - const animationName = - ( isRTL && isBack ) || ( ! isRTL && ! isBack ) - ? fadeInFromRight - : fadeInFromLeft; +const ANIMATION = { + end: { + in: css` + ${ FADE.DURATION }ms ${ FADE.EASING } ${ FADE.DELAY + .IN }ms both ${ fadeIn }, ${ SLIDE.DURATION }ms ${ SLIDE.EASING } both ${ slideFromRight } + `, + out: css` + ${ FADE.DURATION }ms ${ FADE.EASING } ${ FADE.DELAY + .OUT }ms both ${ fadeOut }, ${ SLIDE.DURATION }ms ${ SLIDE.EASING } both ${ slideToLeft } + `, + }, + start: { + in: css` + ${ FADE.DURATION }ms ${ FADE.EASING } ${ FADE.DELAY + .IN }ms both ${ fadeIn }, ${ SLIDE.DURATION }ms ${ SLIDE.EASING } both ${ slideFromLeft } + `, + out: css` + ${ FADE.DURATION }ms ${ FADE.EASING } ${ FADE.DELAY + .OUT }ms both ${ fadeOut }, ${ SLIDE.DURATION }ms ${ SLIDE.EASING } both ${ slideToRight } + `, + }, +} as const; +export const navigatorScreenAnimation = css` + z-index: 1; - return css` - animation-duration: 0.14s; - animation-timing-function: ease-in-out; - will-change: transform, opacity; - animation-name: ${ animationName }; + &[data-animation-type='out'] { + z-index: 0; + } - @media ( prefers-reduced-motion ) { - animation-duration: 0s; + @media not ( prefers-reduced-motion ) { + &:not( [data-skip-animation] ) { + ${ ( [ 'start', 'end' ] as const ).map( ( direction ) => + ( [ 'in', 'out' ] as const ).map( + ( type ) => css` + &[data-animation-direction='${ direction }'][data-animation-type='${ type }'] { + animation: ${ ANIMATION[ direction ][ type ] }; + } + ` + ) + ) } } - `; -}; + } +`; -export const navigatorScreen = ( props: NavigatorScreenAnimationProps ) => css` +export const navigatorScreen = css` /* Ensures horizontal overflow is visually accessible */ overflow-x: auto; /* In case the root has a height, it should not be exceeded */ max-height: 100%; + box-sizing: border-box; + + position: relative; - ${ navigatorScreenAnimation( props ) } + grid-column: 1 / -1; + grid-row: 1 / -1; `; From 427a8d05b77edb3d94271de7583ce6cf440f70c2 Mon Sep 17 00:00:00 2001 From: Manzoor Wani <manzoorwani.jk@gmail.com> Date: Thu, 26 Sep 2024 01:44:45 -0700 Subject: [PATCH 0976/1908] Fix aria-checked attribute not set for plugin settings buttons in Options dropdown (#65667) Co-authored-by: manzoorwanijk <manzoorwanijk@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../complementary-area-toggle/index.js | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/packages/interface/src/components/complementary-area-toggle/index.js b/packages/interface/src/components/complementary-area-toggle/index.js index 15f9e48d71083e..2f8d8dd413674b 100644 --- a/packages/interface/src/components/complementary-area-toggle/index.js +++ b/packages/interface/src/components/complementary-area-toggle/index.js @@ -10,6 +10,25 @@ import { useDispatch, useSelect } from '@wordpress/data'; import { store as interfaceStore } from '../../store'; import complementaryAreaContext from '../complementary-area-context'; +/** + * Whether the role supports checked state. + * + * @param {import('react').AriaRole} role Role. + * @return {boolean} Whether the role supports checked state. + * @see https://www.w3.org/TR/wai-aria-1.1/#aria-checked + */ +function roleSupportsCheckedState( role ) { + return [ + 'checkbox', + 'option', + 'radio', + 'switch', + 'menuitemcheckbox', + 'menuitemradio', + 'treeitem', + ].includes( role ); +} + function ComplementaryAreaToggle( { as = Button, scope, @@ -35,6 +54,10 @@ function ComplementaryAreaToggle( { <ComponentToUse icon={ selectedIcon && isSelected ? selectedIcon : icon } aria-controls={ identifier.replace( '/', ':' ) } + // Make sure aria-checked matches spec https://www.w3.org/TR/wai-aria-1.1/#aria-checked + aria-checked={ + roleSupportsCheckedState( props.role ) ? isSelected : undefined + } onClick={ () => { if ( isSelected ) { disableComplementaryArea( scope ); From d0bcf79685a55653476d2d5868de5ab2f2857ca6 Mon Sep 17 00:00:00 2001 From: dhruvang21 <105810308+dhruvang21@users.noreply.github.com> Date: Thu, 26 Sep 2024 14:59:27 +0530 Subject: [PATCH 0977/1908] Fix: Button Replace remaining 40px default size violations [Block Editor 2] (#65308) * Add __next40pxDefaultSize for block-editor 2 files * Add size compact to buttons * Remove style overrides --------- Co-authored-by: dhruvang21 <dhruvang21@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> --- .../components/block-navigation/dropdown.js | 3 +- .../block-pattern-setup/setup-toolbar.js | 15 +++----- .../components/block-patterns-paging/index.js | 15 ++++---- .../block-patterns-paging/style.scss | 37 +++++-------------- .../block-quick-navigation/index.js | 3 +- 5 files changed, 25 insertions(+), 48 deletions(-) diff --git a/packages/block-editor/src/components/block-navigation/dropdown.js b/packages/block-editor/src/components/block-navigation/dropdown.js index 035a38604b0293..0bf8fd05320188 100644 --- a/packages/block-editor/src/components/block-navigation/dropdown.js +++ b/packages/block-editor/src/components/block-navigation/dropdown.js @@ -27,8 +27,7 @@ function BlockNavigationDropdownToggle( { } ) { return ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize { ...props } ref={ innerRef } icon={ listView } diff --git a/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js b/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js index c551c2e1632bcf..d571e0fef5dcc3 100644 --- a/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js +++ b/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js @@ -18,8 +18,7 @@ import { VIEWMODES } from './constants'; const Actions = ( { onBlockPatternSelect } ) => ( <div className="block-editor-block-pattern-setup__actions"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" onClick={ onBlockPatternSelect } > @@ -36,8 +35,7 @@ const CarouselNavigation = ( { } ) => ( <div className="block-editor-block-pattern-setup__navigation"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + size="compact" icon={ isRTL() ? chevronRight : chevronLeft } label={ __( 'Previous pattern' ) } onClick={ handlePrevious } @@ -45,8 +43,7 @@ const CarouselNavigation = ( { accessibleWhenDisabled /> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + size="compact" icon={ isRTL() ? chevronLeft : chevronRight } label={ __( 'Next pattern' ) } onClick={ handleNext } @@ -69,16 +66,14 @@ const SetupToolbar = ( { const displayControls = ( <div className="block-editor-block-pattern-setup__display-controls"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + size="compact" icon={ stretchFullWidth } label={ __( 'Carousel view' ) } onClick={ () => setViewMode( VIEWMODES.carousel ) } isPressed={ isCarouselView } /> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + size="compact" icon={ grid } label={ __( 'Grid view' ) } onClick={ () => setViewMode( VIEWMODES.grid ) } diff --git a/packages/block-editor/src/components/block-patterns-paging/index.js b/packages/block-editor/src/components/block-patterns-paging/index.js index ce1fa8b93df735..e4d7ce49b90f3e 100644 --- a/packages/block-editor/src/components/block-patterns-paging/index.js +++ b/packages/block-editor/src/components/block-patterns-paging/index.js @@ -38,24 +38,24 @@ export default function Pagination( { className="block-editor-patterns__grid-pagination-previous" > <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } variant="tertiary" onClick={ () => changePage( 1 ) } disabled={ currentPage === 1 } aria-label={ __( 'First page' ) } + size="compact" accessibleWhenDisabled + className="block-editor-patterns__grid-pagination-button" > <span>«</span> </Button> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } variant="tertiary" onClick={ () => changePage( currentPage - 1 ) } disabled={ currentPage === 1 } aria-label={ __( 'Previous page' ) } + size="compact" accessibleWhenDisabled + className="block-editor-patterns__grid-pagination-button" > <span>‹</span> </Button> @@ -74,13 +74,13 @@ export default function Pagination( { className="block-editor-patterns__grid-pagination-next" > <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } variant="tertiary" onClick={ () => changePage( currentPage + 1 ) } disabled={ currentPage === numPages } aria-label={ __( 'Next page' ) } + size="compact" accessibleWhenDisabled + className="block-editor-patterns__grid-pagination-button" > <span>›</span> </Button> @@ -89,8 +89,9 @@ export default function Pagination( { onClick={ () => changePage( numPages ) } disabled={ currentPage === numPages } aria-label={ __( 'Last page' ) } - size="default" + size="compact" accessibleWhenDisabled + className="block-editor-patterns__grid-pagination-button" > <span>»</span> </Button> diff --git a/packages/block-editor/src/components/block-patterns-paging/style.scss b/packages/block-editor/src/components/block-patterns-paging/style.scss index f5f34d821233aa..85d39f9a36577c 100644 --- a/packages/block-editor/src/components/block-patterns-paging/style.scss +++ b/packages/block-editor/src/components/block-patterns-paging/style.scss @@ -4,37 +4,20 @@ border-top: 1px solid $gray-800; padding: $grid-unit-05; justify-content: center; - .components-button.is-tertiary { - width: auto; - height: $button-size-compact; - justify-content: center; - - &:disabled { - color: $gray-600; - background: none; - } - - &:hover:not(:disabled) { - color: $white; - background-color: $gray-700; - } - } } } .show-icon-labels { - .block-editor-patterns__grid-pagination { - .components-button { - width: auto; - // Hide the button icons when labels are set to display... - span { - display: none; - } - // ... and display labels. - // Uses ::before as ::after is already used for active tab styling. - &::before { - content: attr(aria-label); - } + .block-editor-patterns__grid-pagination-button { + width: auto; + // Hide the button icons when labels are set to display... + span { + display: none; + } + // ... and display labels. + // Uses ::before as ::after is already used for active tab styling. + &::before { + content: attr(aria-label); } } } diff --git a/packages/block-editor/src/components/block-quick-navigation/index.js b/packages/block-editor/src/components/block-quick-navigation/index.js index 4f22c2a266722d..fdb3475b3e180f 100644 --- a/packages/block-editor/src/components/block-quick-navigation/index.js +++ b/packages/block-editor/src/components/block-quick-navigation/index.js @@ -59,8 +59,7 @@ function BlockQuickNavigationItem( { clientId, onSelect } ) { return ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize isPressed={ isSelected } onClick={ async () => { await selectBlock( clientId ); From 57e4be73066a420f0151c48cdcf33905579c0e67 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Thu, 26 Sep 2024 11:39:46 +0200 Subject: [PATCH 0978/1908] Move a11y HTML printing code to 6.7 compat directory (#65620) - Ensure that the HTML printing for the @wordpress/a11y script module does not conflict with Core. - Move the @wordpress/a11y script module code to the 6.7 compat directory. The a11y script module HTML printing filters are set conditionally. If Core would set them, Gutenberg does not. This ensures that duplicate HTML elements (with identical element IDs) are not added to the page. This is necessary for compatibility with WordPress 6.7 that adds the @wordpress/a11y Script Module. See https://core.trac.wordpress.org/changeset/59089. --- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: michalczaplinski <czapla@git.wordpress.org> --- lib/compat/wordpress-6.7/script-modules.php | 43 +++++++++++++++++++++ lib/experimental/script-modules.php | 41 -------------------- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/lib/compat/wordpress-6.7/script-modules.php b/lib/compat/wordpress-6.7/script-modules.php index 0a440ec81688d2..2282a3d4bd5acd 100644 --- a/lib/compat/wordpress-6.7/script-modules.php +++ b/lib/compat/wordpress-6.7/script-modules.php @@ -102,3 +102,46 @@ function () { }, 20 ); + +/** + * Prints HTML for the a11y Script Module. + * + * a11y relies on some DOM elements to use as ARIA live regions. + * Ideally, these elements are part of the initial HTML of the page + * so that accessibility tools can find them and observe updates. + */ +function gutenberg_a11y_script_module_html() { + $a11y_module_available = false; + + $get_marked_for_enqueue = new ReflectionMethod( 'WP_Script_Modules', 'get_marked_for_enqueue' ); + $get_marked_for_enqueue->setAccessible( true ); + $get_import_map = new ReflectionMethod( 'WP_Script_Modules', 'get_import_map' ); + $get_import_map->setAccessible( true ); + + foreach ( array_keys( $get_marked_for_enqueue->invoke( wp_script_modules() ) ) as $id ) { + if ( '@wordpress/a11y' === $id ) { + $a11y_module_available = true; + break; + } + } + if ( ! $a11y_module_available ) { + foreach ( array_keys( $get_import_map->invoke( wp_script_modules() )['imports'] ) as $id ) { + if ( '@wordpress/a11y' === $id ) { + $a11y_module_available = true; + break; + } + } + } + if ( ! $a11y_module_available ) { + return; + } + echo '<div style="position:absolute;margin:-1px;padding:0;height:1px;width:1px;overflow:hidden;clip-path:inset(50%);border:0;word-wrap:normal !important;">' + . '<p id="a11y-speak-intro-text" class="a11y-speak-intro-text" hidden>' . esc_html__( 'Notifications', 'default' ) . '</p>' + . '<div id="a11y-speak-assertive" class="a11y-speak-region" aria-live="assertive" aria-relevant="additions text" aria-atomic="true"></div>' + . '<div id="a11y-speak-polite" class="a11y-speak-region" aria-live="polite" aria-relevant="additions text" aria-atomic="true"></div>' + . '</div>'; +} +if ( ! method_exists( 'WP_Script_Modules', 'print_a11y_script_module_html' ) ) { + add_action( 'wp_footer', 'gutenberg_a11y_script_module_html' ); + add_action( 'admin_footer', 'gutenberg_a11y_script_module_html' ); +} diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index fe23786fc03621..5a14e1418ed6de 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -200,44 +200,3 @@ function gutenberg_dequeue_module( $module_identifier ) { _deprecated_function( __FUNCTION__, 'Gutenberg 17.6.0', 'wp_dequeue_script_module' ); wp_script_modules()->dequeue( $module_identifier ); } - -/** - * Prints HTML for the a11y Script Module. - * - * a11y relies on some DOM elements to use as ARIA live regions. - * Ideally, these elements are part of the initial HTML of the page - * so that accessibility tools can find them and observe updates. - */ -function gutenberg_a11y_script_module_html() { - $a11y_module_available = false; - - $get_marked_for_enqueue = new ReflectionMethod( 'WP_Script_Modules', 'get_marked_for_enqueue' ); - $get_marked_for_enqueue->setAccessible( true ); - $get_import_map = new ReflectionMethod( 'WP_Script_Modules', 'get_import_map' ); - $get_import_map->setAccessible( true ); - - foreach ( array_keys( $get_marked_for_enqueue->invoke( wp_script_modules() ) ) as $id ) { - if ( '@wordpress/a11y' === $id ) { - $a11y_module_available = true; - break; - } - } - if ( ! $a11y_module_available ) { - foreach ( array_keys( $get_import_map->invoke( wp_script_modules() )['imports'] ) as $id ) { - if ( '@wordpress/a11y' === $id ) { - $a11y_module_available = true; - break; - } - } - } - if ( ! $a11y_module_available ) { - return; - } - echo '<div style="position:absolute;margin:-1px;padding:0;height:1px;width:1px;overflow:hidden;clip-path:inset(50%);border:0;word-wrap:normal !important;">' - . '<p id="a11y-speak-intro-text" class="a11y-speak-intro-text" hidden>' . esc_html__( 'Notifications', 'default' ) . '</p>' - . '<div id="a11y-speak-assertive" class="a11y-speak-region" aria-live="assertive" aria-relevant="additions text" aria-atomic="true"></div>' - . '<div id="a11y-speak-polite" class="a11y-speak-region" aria-live="polite" aria-relevant="additions text" aria-atomic="true"></div>' - . '</div>'; -} -add_action( 'wp_footer', 'gutenberg_a11y_script_module_html' ); -add_action( 'admin_footer', 'gutenberg_a11y_script_module_html' ); From 3b99bb64914fdee642f89320355a2297726b27dd Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 26 Sep 2024 12:49:17 +0300 Subject: [PATCH 0979/1908] Editor: Consistent external media pre-publish image/button sizes (#65668) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../src/components/post-publish-panel/maybe-upload-media.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/editor/src/components/post-publish-panel/maybe-upload-media.js b/packages/editor/src/components/post-publish-panel/maybe-upload-media.js index 8c8d757c583399..32ea69c425e0b5 100644 --- a/packages/editor/src/components/post-publish-panel/maybe-upload-media.js +++ b/packages/editor/src/components/post-publish-panel/maybe-upload-media.js @@ -98,8 +98,8 @@ function Image( { clientId, alt, url } ) { animate={ { opacity: 1 } } exit={ { opacity: 0, scale: 0 } } style={ { - width: '36px', - height: '36px', + width: '32px', + height: '32px', objectFit: 'cover', borderRadius: '2px', cursor: 'pointer', @@ -256,7 +256,7 @@ export default function MaybeUploadMediaPanel() { <Spinner /> ) : ( <Button - __next40pxDefaultSize + size="compact" variant="primary" onClick={ uploadImages } > From 76448eee2ee44fc1e72589748b9b36de2d1268b9 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 26 Sep 2024 15:55:19 +0400 Subject: [PATCH 0980/1908] Block Editor: Fix README for FontFamilyControl component (#65660) Unlinked contributors: mr660. Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-editor/src/components/font-family/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/font-family/README.md b/packages/block-editor/src/components/font-family/README.md index 63965f509ba534..57697f595cc800 100644 --- a/packages/block-editor/src/components/font-family/README.md +++ b/packages/block-editor/src/components/font-family/README.md @@ -1,5 +1,9 @@ # FontFamilyControl +<div class="callout callout-alert"> +This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +</div> + FontFamilyControl is a React component that renders a UI that allows users to select a font family. The component renders a user interface that allows the user to select from a set of predefined font families as defined by the `typography.fontFamilies` presets. Optionally, you can provide a `fontFamilies` prop that overrides the predefined font families. @@ -10,7 +14,7 @@ Optionally, you can provide a `fontFamilies` prop that overrides the predefined ```jsx import { useState } from 'react'; -import { FontFamilyControl } from '@wordpress/block-editor'; +import { __experimentalFontFamilyControl as FontFamilyControl } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; // ... From 5df96133f050d8a56525bf68c55a10de8d61089d Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Thu, 26 Sep 2024 13:05:12 +0100 Subject: [PATCH 0981/1908] Add type tokens (#65418) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/base-styles/_mixins.scss | 68 ++++++++++++++++++++++++++++ packages/base-styles/_variables.scss | 54 +++++++++++++++++----- 2 files changed, 111 insertions(+), 11 deletions(-) diff --git a/packages/base-styles/_mixins.scss b/packages/base-styles/_mixins.scss index 91017c8bb99320..65f98bf6f15bfc 100644 --- a/packages/base-styles/_mixins.scss +++ b/packages/base-styles/_mixins.scss @@ -1,6 +1,74 @@ @import "./functions"; @import "./long-content-fade"; +/** + * Typography + */ + +@mixin _text-heading() { + font-family: $font-family-headings; + font-weight: $font-weight-medium; +} + +@mixin _text-body() { + font-family: $font-family-body; + font-weight: $font-weight-regular; +} + +@mixin heading-small() { + @include _text-heading(); + font-size: $font-size-x-small; + line-height: $line-height-x-small; +} + +@mixin heading-medium() { + @include _text-heading(); + font-size: $font-size-medium; + line-height: $line-height-small; +} + +@mixin heading-large() { + @include _text-heading(); + font-size: $font-size-large; + line-height: $line-height-small; +} + +@mixin heading-x-large() { + @include _text-heading(); + font-size: $font-size-x-large; + line-height: $line-height-medium; +} + +@mixin heading-2x-large() { + @include _text-heading(); + font-size: $font-size-2x-large; + line-height: $font-line-height-2x-large; +} + +@mixin body-small() { + @include _text-body(); + font-size: $font-size-small; + line-height: $line-height-x-small; +} + +@mixin body-medium() { + @include _text-body(); + font-size: $font-size-medium; + line-height: $line-height-small; +} + +@mixin body-large() { + @include _text-body(); + font-size: $font-size-large; + line-height: $line-height-medium; +} + +@mixin body-x-large() { + @include _text-body(); + font-size: $font-size-x-large; + line-height: $line-height-x-large; +} + /** * Breakpoint mixins */ diff --git a/packages/base-styles/_variables.scss b/packages/base-styles/_variables.scss index 35092033c552bd..ec0bdf91f2489d 100644 --- a/packages/base-styles/_variables.scss +++ b/packages/base-styles/_variables.scss @@ -12,15 +12,37 @@ * Fonts & basic variables. */ -$default-font: -apple-system, BlinkMacSystemFont,"Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell,"Helvetica Neue", sans-serif; -$default-font-size: 13px; -$default-line-height: 1.4; -$editor-html-font: Menlo, Consolas, monaco, monospace; -$editor-font-size: 16px; -$default-block-margin: 28px; // This value provides a consistent, contiguous spacing between blocks. -$text-editor-font-size: 15px; -$editor-line-height: 1.8; -$mobile-text-min-font-size: 16px; // Any font size below 16px will cause Mobile Safari to "zoom in". +$default-font: -apple-system, BlinkMacSystemFont,"Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell,"Helvetica Neue", sans-serif; // Todo: deprecate in favor of $family variables +$default-line-height: 1.4; // Todo: deprecate in favor of $line-height tokens + +/** + * Typography + */ + +// Sizes +$font-size-x-small: 11px; +$font-size-small: 12px; +$font-size-medium: 13px; +$font-size-large: 15px; +$font-size-x-large: 20px; +$font-size-2x-large: 32px; + +// Line heights +$font-line-height-x-small: 16px; +$font-line-height-small: 20px; +$font-line-height-medium: 24px; +$font-line-height-large: 28px; +$font-line-height-x-large: 32px; +$font-line-height-2x-large: 40px; + +// Weights +$font-weight-regular: 400; +$font-weight-medium: 500; + +// Families +$font-family-headings: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +$font-family-body: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +$font-family-mono: Menlo, Consolas, monaco, monospace; /** * Grid System. @@ -91,7 +113,12 @@ $spinner-size: 16px; $canvas-padding: $grid-unit-20; /** - * Editor widths. + * Mobile specific styles + */ +$mobile-text-min-font-size: 16px; // Any font size below 16px will cause Mobile Safari to "zoom in". + +/** + * Editor styles. */ $sidebar-width: 280px; @@ -99,6 +126,11 @@ $content-width: 840px; $wide-content-width: 1100px; $widget-area-width: 700px; $secondary-sidebar-width: 350px; +$editor-font-size: 16px; +$default-block-margin: 28px; // This value provides a consistent, contiguous spacing between blocks. +$text-editor-font-size: 15px; +$editor-line-height: 1.8; +$editor-html-font: $font-family-mono; /** * Block & Editor UI. @@ -117,7 +149,7 @@ $block-padding: 14px; // Used to define space between block footprint and surrou $radius-block-ui: $radius-small; $shadow-popover: $elevation-x-small; $shadow-modal: $elevation-large; - +$default-font-size: $font-size-medium; /** * Block paddings. From 7d883a45cb865bfabf686787cd08dd21626b8835 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Thu, 26 Sep 2024 14:14:02 +0200 Subject: [PATCH 0982/1908] Update to use a11y script module package in Core. (#65539) Update the interactivity-router package to use the @wordpress/a11y module for its aria-live regions. This was behind a Gutenberg-only flag. Since the a11y module is landing in Core in 6.7, the flag can be removed to always use the a11y module. See https://github.com/WordPress/wordpress-develop/pull/7304. --- packages/interactivity-router/src/index.ts | 30 ++++++++-------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/packages/interactivity-router/src/index.ts b/packages/interactivity-router/src/index.ts index 3bd44c7aebd71f..b2e8e2d4395dcd 100644 --- a/packages/interactivity-router/src/index.ts +++ b/packages/interactivity-router/src/index.ts @@ -221,11 +221,6 @@ interface Store { navigation: { hasStarted: boolean; hasFinished: boolean; - message: string; - texts?: { - loading?: string; - loaded?: string; - }; }; }; actions: { @@ -240,7 +235,6 @@ export const { state, actions } = store< Store >( 'core/router', { navigation: { hasStarted: false, hasFinished: false, - message: '', }, }, actions: { @@ -403,10 +397,16 @@ function a11ySpeak( messageKey: keyof typeof navigationTexts ) { } catch {} } else { // Fallback to localized strings from Interactivity API state. + // @todo This block is for Core < 6.7.0. Remove when support is dropped. + + // @ts-expect-error if ( state.navigation.texts?.loading ) { + // @ts-expect-error navigationTexts.loading = state.navigation.texts.loading; } + // @ts-expect-error if ( state.navigation.texts?.loaded ) { + // @ts-expect-error navigationTexts.loaded = state.navigation.texts.loaded; } } @@ -414,19 +414,11 @@ function a11ySpeak( messageKey: keyof typeof navigationTexts ) { const message = navigationTexts[ messageKey ]; - if ( globalThis.IS_GUTENBERG_PLUGIN ) { - import( '@wordpress/a11y' ).then( - ( { speak } ) => speak( message ), - // Ignore failures to load the a11y module. - () => {} - ); - } else { - state.navigation.message = - // Announce that the page has been loaded. If the message is the - // same, we use a no-break space similar to the @wordpress/a11y - // package: https://github.com/WordPress/gutenberg/blob/c395242b8e6ee20f8b06c199e4fc2920d7018af1/packages/a11y/src/filter-message.js#L20-L26 - message + ( state.navigation.message === message ? '\u00A0' : '' ); - } + import( '@wordpress/a11y' ).then( + ( { speak } ) => speak( message ), + // Ignore failures to load the a11y module. + () => {} + ); } // Add click and prefetch to all links. From f624423d1dde5249b6899c4d2f4b1ecc944a207e Mon Sep 17 00:00:00 2001 From: Phil Webster <pwebster33@gmail.com> Date: Thu, 26 Sep 2024 08:53:28 -0400 Subject: [PATCH 0983/1908] Block Editor: Validate options for the 'HeadingLevelDropdown' component (#65425) Co-authored-by: philwp <philwebs@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> --- .../src/components/block-heading-level-dropdown/index.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-heading-level-dropdown/index.js b/packages/block-editor/src/components/block-heading-level-dropdown/index.js index 71cb2ede989b5b..6b9bad09978a50 100644 --- a/packages/block-editor/src/components/block-heading-level-dropdown/index.js +++ b/packages/block-editor/src/components/block-heading-level-dropdown/index.js @@ -40,12 +40,18 @@ export default function HeadingLevelDropdown( { value, onChange, } ) { + const validOptions = options + .filter( + ( option ) => option === 0 || HEADING_LEVELS.includes( option ) + ) + .sort( ( a, b ) => a - b ); // Sorts numerically in ascending order; + return ( <ToolbarDropdownMenu popoverProps={ POPOVER_PROPS } icon={ <HeadingLevelIcon level={ value } /> } label={ __( 'Change level' ) } - controls={ options.map( ( targetLevel ) => { + controls={ validOptions.map( ( targetLevel ) => { const isActive = targetLevel === value; return { icon: <HeadingLevelIcon level={ targetLevel } />, From 79efa22c8c4d7413914b0403987ba0f569108d0f Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 26 Sep 2024 15:07:26 +0200 Subject: [PATCH 0984/1908] Navigator: internal refactor in preparation for stabilization (#65671) * Rename navigator-provider internal folder to navigator * Rename internal NavigatorProvider variables to Navigator * Remove default exports * Remove JSDocs from individual component files * Move exports to legacy.ts file, including JSDocs * Undo folder rename as it was causing a different doc manifest --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/src/index.ts | 2 +- packages/components/src/navigator/index.ts | 6 - packages/components/src/navigator/legacy.ts | 172 ++++++++++++++++++ .../navigator-back-button/component.tsx | 36 ---- .../navigator/navigator-button/component.tsx | 35 ---- .../navigator-provider/component.tsx | 12 +- .../navigator/navigator-screen/component.tsx | 36 ---- .../navigator-to-parent-button/component.tsx | 8 - .../src/navigator/stories/index.story.tsx | 2 +- .../components/src/navigator/test/index.tsx | 2 +- packages/components/src/navigator/types.ts | 2 +- 11 files changed, 182 insertions(+), 131 deletions(-) delete mode 100644 packages/components/src/navigator/index.ts create mode 100644 packages/components/src/navigator/legacy.ts diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index 200225148a0a49..37ba116a7f679e 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -131,7 +131,7 @@ export { NavigatorBackButton as __experimentalNavigatorBackButton, NavigatorToParentButton as __experimentalNavigatorToParentButton, useNavigator as __experimentalUseNavigator, -} from './navigator'; +} from './navigator/legacy'; export { default as Notice } from './notice'; export { default as __experimentalNumberControl } from './number-control'; export { default as NoticeList } from './notice/list'; diff --git a/packages/components/src/navigator/index.ts b/packages/components/src/navigator/index.ts deleted file mode 100644 index 130edc2ae52eb8..00000000000000 --- a/packages/components/src/navigator/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { NavigatorProvider } from './navigator-provider/component'; -export { NavigatorScreen } from './navigator-screen/component'; -export { NavigatorButton } from './navigator-button/component'; -export { NavigatorBackButton } from './navigator-back-button/component'; -export { NavigatorToParentButton } from './navigator-to-parent-button/component'; -export { useNavigator } from './use-navigator'; diff --git a/packages/components/src/navigator/legacy.ts b/packages/components/src/navigator/legacy.ts new file mode 100644 index 00000000000000..54bc9e13829b16 --- /dev/null +++ b/packages/components/src/navigator/legacy.ts @@ -0,0 +1,172 @@ +/** + * Internal dependencies + */ +import { Navigator as InternalNavigator } from './navigator-provider/component'; +import { NavigatorScreen as InternalNavigatorScreen } from './navigator-screen/component'; +import { NavigatorButton as InternalNavigatorButton } from './navigator-button/component'; +import { NavigatorBackButton as InternalNavigatorBackButton } from './navigator-back-button/component'; +import { NavigatorToParentButton as InternalNavigatorToParentButton } from './navigator-to-parent-button/component'; +export { useNavigator } from './use-navigator'; + +/** + * The `NavigatorProvider` component allows rendering nested views/panels/menus + * (via the `NavigatorScreen` component and navigate between these different + * view (via the `NavigatorButton` and `NavigatorBackButton` components or the + * `useNavigator` hook). + * + * ```jsx + * import { + * __experimentalNavigatorProvider as NavigatorProvider, + * __experimentalNavigatorScreen as NavigatorScreen, + * __experimentalNavigatorButton as NavigatorButton, + * __experimentalNavigatorBackButton as NavigatorBackButton, + * } from '@wordpress/components'; + * + * const MyNavigation = () => ( + * <NavigatorProvider initialPath="/"> + * <NavigatorScreen path="/"> + * <p>This is the home screen.</p> + * <NavigatorButton path="/child"> + * Navigate to child screen. + * </NavigatorButton> + * </NavigatorScreen> + * + * <NavigatorScreen path="/child"> + * <p>This is the child screen.</p> + * <NavigatorBackButton> + * Go back + * </NavigatorBackButton> + * </NavigatorScreen> + * </NavigatorProvider> + * ); + * ``` + */ +export const NavigatorProvider = Object.assign( InternalNavigator, { + displayName: 'NavigatorProvider', +} ); + +/** + * The `NavigatorScreen` component represents a single view/screen/panel and + * should be used in combination with the `NavigatorProvider`, the + * `NavigatorButton` and the `NavigatorBackButton` components (or the `useNavigator` + * hook). + * + * @example + * ```jsx + * import { + * __experimentalNavigatorProvider as NavigatorProvider, + * __experimentalNavigatorScreen as NavigatorScreen, + * __experimentalNavigatorButton as NavigatorButton, + * __experimentalNavigatorBackButton as NavigatorBackButton, + * } from '@wordpress/components'; + * + * const MyNavigation = () => ( + * <NavigatorProvider initialPath="/"> + * <NavigatorScreen path="/"> + * <p>This is the home screen.</p> + * <NavigatorButton path="/child"> + * Navigate to child screen. + * </NavigatorButton> + * </NavigatorScreen> + * + * <NavigatorScreen path="/child"> + * <p>This is the child screen.</p> + * <NavigatorBackButton> + * Go back + * </NavigatorBackButton> + * </NavigatorScreen> + * </NavigatorProvider> + * ); + * ``` + */ +export const NavigatorScreen = Object.assign( InternalNavigatorScreen, { + displayName: 'NavigatorScreen', +} ); + +/** + * The `NavigatorButton` component can be used to navigate to a screen and should + * be used in combination with the `NavigatorProvider`, the `NavigatorScreen` + * and the `NavigatorBackButton` components (or the `useNavigator` hook). + * + * @example + * ```jsx + * import { + * __experimentalNavigatorProvider as NavigatorProvider, + * __experimentalNavigatorScreen as NavigatorScreen, + * __experimentalNavigatorButton as NavigatorButton, + * __experimentalNavigatorBackButton as NavigatorBackButton, + * } from '@wordpress/components'; + * + * const MyNavigation = () => ( + * <NavigatorProvider initialPath="/"> + * <NavigatorScreen path="/"> + * <p>This is the home screen.</p> + * <NavigatorButton path="/child"> + * Navigate to child screen. + * </NavigatorButton> + * </NavigatorScreen> + * + * <NavigatorScreen path="/child"> + * <p>This is the child screen.</p> + * <NavigatorBackButton> + * Go back + * </NavigatorBackButton> + * </NavigatorScreen> + * </NavigatorProvider> + * ); + * ``` + */ +export const NavigatorButton = Object.assign( InternalNavigatorButton, { + displayName: 'NavigatorButton', +} ); + +/** + * The `NavigatorBackButton` component can be used to navigate to a screen and + * should be used in combination with the `NavigatorProvider`, the + * `NavigatorScreen` and the `NavigatorButton` components (or the `useNavigator` + * hook). + * + * @example + * ```jsx + * import { + * __experimentalNavigatorProvider as NavigatorProvider, + * __experimentalNavigatorScreen as NavigatorScreen, + * __experimentalNavigatorButton as NavigatorButton, + * __experimentalNavigatorBackButton as NavigatorBackButton, + * } from '@wordpress/components'; + * + * const MyNavigation = () => ( + * <NavigatorProvider initialPath="/"> + * <NavigatorScreen path="/"> + * <p>This is the home screen.</p> + * <NavigatorButton path="/child"> + * Navigate to child screen. + * </NavigatorButton> + * </NavigatorScreen> + * + * <NavigatorScreen path="/child"> + * <p>This is the child screen.</p> + * <NavigatorBackButton> + * Go back (to parent) + * </NavigatorBackButton> + * </NavigatorScreen> + * </NavigatorProvider> + * ); + * ``` + */ +export const NavigatorBackButton = Object.assign( InternalNavigatorBackButton, { + displayName: 'NavigatorBackButton', +} ); + +/** + * _Note: this component is deprecated. Please use the `NavigatorBackButton` + * component instead._ + * + * @deprecated + */ +export const NavigatorToParentButton = Object.assign( + InternalNavigatorToParentButton, + { + displayName: 'NavigatorToParentButton', + } +); diff --git a/packages/components/src/navigator/navigator-back-button/component.tsx b/packages/components/src/navigator/navigator-back-button/component.tsx index 88ed45b643a13d..9e8d98a963d25b 100644 --- a/packages/components/src/navigator/navigator-back-button/component.tsx +++ b/packages/components/src/navigator/navigator-back-button/component.tsx @@ -21,43 +21,7 @@ function UnconnectedNavigatorBackButton( return <View ref={ forwardedRef } { ...navigatorBackButtonProps } />; } -/** - * The `NavigatorBackButton` component can be used to navigate to a screen and - * should be used in combination with the `NavigatorProvider`, the - * `NavigatorScreen` and the `NavigatorButton` components (or the `useNavigator` - * hook). - * - * @example - * ```jsx - * import { - * __experimentalNavigatorProvider as NavigatorProvider, - * __experimentalNavigatorScreen as NavigatorScreen, - * __experimentalNavigatorButton as NavigatorButton, - * __experimentalNavigatorBackButton as NavigatorBackButton, - * } from '@wordpress/components'; - * - * const MyNavigation = () => ( - * <NavigatorProvider initialPath="/"> - * <NavigatorScreen path="/"> - * <p>This is the home screen.</p> - * <NavigatorButton path="/child"> - * Navigate to child screen. - * </NavigatorButton> - * </NavigatorScreen> - * - * <NavigatorScreen path="/child"> - * <p>This is the child screen.</p> - * <NavigatorBackButton> - * Go back (to parent) - * </NavigatorBackButton> - * </NavigatorScreen> - * </NavigatorProvider> - * ); - * ``` - */ export const NavigatorBackButton = contextConnect( UnconnectedNavigatorBackButton, 'NavigatorBackButton' ); - -export default NavigatorBackButton; diff --git a/packages/components/src/navigator/navigator-button/component.tsx b/packages/components/src/navigator/navigator-button/component.tsx index 1b84a2315c04d3..7c14c8108e82c4 100644 --- a/packages/components/src/navigator/navigator-button/component.tsx +++ b/packages/components/src/navigator/navigator-button/component.tsx @@ -21,42 +21,7 @@ function UnconnectedNavigatorButton( return <View ref={ forwardedRef } { ...navigatorButtonProps } />; } -/** - * The `NavigatorButton` component can be used to navigate to a screen and should - * be used in combination with the `NavigatorProvider`, the `NavigatorScreen` - * and the `NavigatorBackButton` components (or the `useNavigator` hook). - * - * @example - * ```jsx - * import { - * __experimentalNavigatorProvider as NavigatorProvider, - * __experimentalNavigatorScreen as NavigatorScreen, - * __experimentalNavigatorButton as NavigatorButton, - * __experimentalNavigatorBackButton as NavigatorBackButton, - * } from '@wordpress/components'; - * - * const MyNavigation = () => ( - * <NavigatorProvider initialPath="/"> - * <NavigatorScreen path="/"> - * <p>This is the home screen.</p> - * <NavigatorButton path="/child"> - * Navigate to child screen. - * </NavigatorButton> - * </NavigatorScreen> - * - * <NavigatorScreen path="/child"> - * <p>This is the child screen.</p> - * <NavigatorBackButton> - * Go back - * </NavigatorBackButton> - * </NavigatorScreen> - * </NavigatorProvider> - * ); - * ``` - */ export const NavigatorButton = contextConnect( UnconnectedNavigatorButton, 'NavigatorButton' ); - -export default NavigatorButton; diff --git a/packages/components/src/navigator/navigator-provider/component.tsx b/packages/components/src/navigator/navigator-provider/component.tsx index 01254b743f87d0..604034a9525577 100644 --- a/packages/components/src/navigator/navigator-provider/component.tsx +++ b/packages/components/src/navigator/navigator-provider/component.tsx @@ -21,7 +21,7 @@ import { View } from '../../view'; import { NavigatorContext } from '../context'; import * as styles from '../styles'; import type { - NavigatorProviderProps, + NavigatorProps, NavigatorLocation, NavigatorContext as NavigatorContextType, NavigateOptions, @@ -213,8 +213,8 @@ function routerReducer( }; } -function UnconnectedNavigatorProvider( - props: WordPressComponentProps< NavigatorProviderProps, 'div' >, +function UnconnectedNavigator( + props: WordPressComponentProps< NavigatorProps, 'div' >, forwardedRef: ForwardedRef< any > ) { const { @@ -321,9 +321,9 @@ function UnconnectedNavigatorProvider( * ); * ``` */ -export const NavigatorProvider = contextConnect( - UnconnectedNavigatorProvider, +export const Navigator = contextConnect( + UnconnectedNavigator, 'NavigatorProvider' ); -export default NavigatorProvider; +export default Navigator; diff --git a/packages/components/src/navigator/navigator-screen/component.tsx b/packages/components/src/navigator/navigator-screen/component.tsx index f2d2c26e576c27..16cc0df24e35dd 100644 --- a/packages/components/src/navigator/navigator-screen/component.tsx +++ b/packages/components/src/navigator/navigator-screen/component.tsx @@ -153,43 +153,7 @@ function UnconnectedNavigatorScreen( ) : null; } -/** - * The `NavigatorScreen` component represents a single view/screen/panel and - * should be used in combination with the `NavigatorProvider`, the - * `NavigatorButton` and the `NavigatorBackButton` components (or the `useNavigator` - * hook). - * - * @example - * ```jsx - * import { - * __experimentalNavigatorProvider as NavigatorProvider, - * __experimentalNavigatorScreen as NavigatorScreen, - * __experimentalNavigatorButton as NavigatorButton, - * __experimentalNavigatorBackButton as NavigatorBackButton, - * } from '@wordpress/components'; - * - * const MyNavigation = () => ( - * <NavigatorProvider initialPath="/"> - * <NavigatorScreen path="/"> - * <p>This is the home screen.</p> - * <NavigatorButton path="/child"> - * Navigate to child screen. - * </NavigatorButton> - * </NavigatorScreen> - * - * <NavigatorScreen path="/child"> - * <p>This is the child screen.</p> - * <NavigatorBackButton> - * Go back - * </NavigatorBackButton> - * </NavigatorScreen> - * </NavigatorProvider> - * ); - * ``` - */ export const NavigatorScreen = contextConnect( UnconnectedNavigatorScreen, 'NavigatorScreen' ); - -export default NavigatorScreen; diff --git a/packages/components/src/navigator/navigator-to-parent-button/component.tsx b/packages/components/src/navigator/navigator-to-parent-button/component.tsx index fcbadea03cf7bb..161370a4323f48 100644 --- a/packages/components/src/navigator/navigator-to-parent-button/component.tsx +++ b/packages/components/src/navigator/navigator-to-parent-button/component.tsx @@ -23,15 +23,7 @@ function UnconnectedNavigatorToParentButton( return <NavigatorBackButton ref={ forwardedRef } { ...props } />; } -/** - * _Note: this component is deprecated. Please use the `NavigatorBackButton` - * component instead._ - * - * @deprecated - */ export const NavigatorToParentButton = contextConnect( UnconnectedNavigatorToParentButton, 'NavigatorToParentButton' ); - -export default NavigatorToParentButton; diff --git a/packages/components/src/navigator/stories/index.story.tsx b/packages/components/src/navigator/stories/index.story.tsx index 8edac7e7b81686..f703969320ca57 100644 --- a/packages/components/src/navigator/stories/index.story.tsx +++ b/packages/components/src/navigator/stories/index.story.tsx @@ -14,7 +14,7 @@ import { NavigatorButton, NavigatorBackButton, useNavigator, -} from '..'; +} from '../legacy'; import { HStack } from '../../h-stack'; const meta: Meta< typeof NavigatorProvider > = { diff --git a/packages/components/src/navigator/test/index.tsx b/packages/components/src/navigator/test/index.tsx index 820942a22644ba..81ffd8d69208d7 100644 --- a/packages/components/src/navigator/test/index.tsx +++ b/packages/components/src/navigator/test/index.tsx @@ -21,7 +21,7 @@ import { NavigatorBackButton, NavigatorToParentButton, useNavigator, -} from '..'; +} from '../legacy'; import type { NavigateOptions } from '../types'; const INVALID_HTML_ATTRIBUTE = { diff --git a/packages/components/src/navigator/types.ts b/packages/components/src/navigator/types.ts index 855787b4d0a193..ad26d3f1c9f490 100644 --- a/packages/components/src/navigator/types.ts +++ b/packages/components/src/navigator/types.ts @@ -86,7 +86,7 @@ export type NavigatorContext = Navigator & { match?: string; }; -export type NavigatorProviderProps = { +export type NavigatorProps = { /** * The initial active path. */ From e0c5a598a8aa23dc045864a65c7b967547a01439 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Thu, 26 Sep 2024 14:13:44 +0100 Subject: [PATCH 0985/1908] Update elevation in the site editor (#65410) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../src/components/block-draggable/style.scss | 4 ++-- packages/edit-site/src/components/layout/style.scss | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/block-draggable/style.scss b/packages/block-editor/src/components/block-draggable/style.scss index 349afa2c3563c0..f716f2d32a1d40 100644 --- a/packages/block-editor/src/components/block-draggable/style.scss +++ b/packages/block-editor/src/components/block-draggable/style.scss @@ -8,7 +8,7 @@ .block-editor-block-draggable-chip { background-color: $gray-900; border-radius: $radius-small; - box-shadow: 0 6px 8px rgba($black, 0.3); + box-shadow: $elevation-small; color: $white; cursor: grabbing; display: inline-flex; @@ -77,6 +77,6 @@ .block-editor-block-draggable-chip__disabled.block-editor-block-draggable-chip__disabled { background-color: $gray-700; opacity: 1; - box-shadow: 0 4px 8px rgba($black, 0.2); + box-shadow: $elevation-small; } } diff --git a/packages/edit-site/src/components/layout/style.scss b/packages/edit-site/src/components/layout/style.scss index b2d929a7943dbf..27a3f7b99bf7e2 100644 --- a/packages/edit-site/src/components/layout/style.scss +++ b/packages/edit-site/src/components/layout/style.scss @@ -114,14 +114,18 @@ width: calc(100% - #{$canvas-padding}); .edit-site-resizable-frame__inner-content { - box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.8), 0 8px 10px -6px rgba(0, 0, 0, 0.8); - transition: border-radius 0.4s; + box-shadow: $elevation-x-small; + transition: border-radius, box-shadow 0.4s; // This ensure the radius work properly. overflow: hidden; .edit-site-layout:not(.is-full-canvas) & { border-radius: $radius-large; } + + &:hover { + box-shadow: $elevation-large; + } } } @@ -246,6 +250,7 @@ html.canvas-mode-edit-transition::view-transition-group(toggle) { flex-grow: 1; margin: 0; overflow: hidden; + box-shadow: $elevation-x-small; @include break-medium() { border-radius: 8px; margin: $canvas-padding $canvas-padding $canvas-padding 0; From 4482cd345d8ce2d56618f4715d58f8abfa348594 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 26 Sep 2024 22:58:13 +0900 Subject: [PATCH 0986/1908] Paste Handler: Try to fix pasting text with formatting (#63779) * Paste Handler: Try to fix pasting text with formatting * Refactor e2e test * Simplify e2e test Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: hellofromtonya <hellofromtonya@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: rfischmann <rfischmann@git.wordpress.org> Co-authored-by: bph <bph@git.wordpress.org> --- .../event-listeners/paste-handler.js | 4 ++-- ...aste-link-to-formatted-text-1-chromium.txt | 3 +++ .../editor/various/copy-cut-paste.spec.js | 21 +++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 test/e2e/specs/editor/various/__snapshots__/Copy-cut-paste-should-paste-link-to-formatted-text-1-chromium.txt diff --git a/packages/block-editor/src/components/rich-text/event-listeners/paste-handler.js b/packages/block-editor/src/components/rich-text/event-listeners/paste-handler.js index 59633f4750ff92..ef1833bda88e63 100644 --- a/packages/block-editor/src/components/rich-text/event-listeners/paste-handler.js +++ b/packages/block-editor/src/components/rich-text/event-listeners/paste-handler.js @@ -28,8 +28,8 @@ export default ( props ) => ( element ) => { } = props.current; // The event listener is attached to the window, so we need to check if - // the target is the element. - if ( event.target !== element ) { + // the target is the element or inside the element. + if ( ! element.contains( event.target ) ) { return; } diff --git a/test/e2e/specs/editor/various/__snapshots__/Copy-cut-paste-should-paste-link-to-formatted-text-1-chromium.txt b/test/e2e/specs/editor/various/__snapshots__/Copy-cut-paste-should-paste-link-to-formatted-text-1-chromium.txt new file mode 100644 index 00000000000000..73ed4090549910 --- /dev/null +++ b/test/e2e/specs/editor/various/__snapshots__/Copy-cut-paste-should-paste-link-to-formatted-text-1-chromium.txt @@ -0,0 +1,3 @@ +<!-- wp:paragraph --> +<p><strong>t<a href="https://wordpress.org/gutenberg">es</a>t</strong></p> +<!-- /wp:paragraph --> \ No newline at end of file diff --git a/test/e2e/specs/editor/various/copy-cut-paste.spec.js b/test/e2e/specs/editor/various/copy-cut-paste.spec.js index 33a65e6f5a1195..bca062b06416a1 100644 --- a/test/e2e/specs/editor/various/copy-cut-paste.spec.js +++ b/test/e2e/specs/editor/various/copy-cut-paste.spec.js @@ -565,6 +565,27 @@ test.describe( 'Copy/cut/paste', () => { ] ); } ); + test( 'should paste link to formatted text', async ( { + page, + pageUtils, + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { content: '<strong>test</strong>' }, + } ); + await page.keyboard.press( 'ArrowRight' ); + await page.keyboard.press( 'ArrowRight' ); + await pageUtils.pressKeys( 'shift+ArrowRight' ); + await pageUtils.pressKeys( 'shift+ArrowRight' ); + pageUtils.setClipboardData( { + plainText: 'https://wordpress.org/gutenberg', + html: 'https://wordpress.org/gutenberg', + } ); + await pageUtils.pressKeys( 'primary+v' ); + expect( await editor.getEditedPostContent() ).toMatchSnapshot(); + } ); + test( 'should auto-link', async ( { pageUtils, editor } ) => { await editor.insertBlock( { name: 'core/paragraph', From b1f07db58b9b9dcf5068a7e88e63dbf845cef91b Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:16:59 +0300 Subject: [PATCH 0987/1908] Guide: Update finish button to use the new default size (#65680) * Guide: Update finish button to use the new default size * CHANGELOG Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/guide/index.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 94633ec7078108..73f005b653841a 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -17,6 +17,7 @@ - `MenuGroup`: Simplify the MenuGroup styles within dropdown menus. ([#65561](https://github.com/WordPress/gutenberg/pull/65561)). - `DatePicker`: Use compact button size. ([#65653](https://github.com/WordPress/gutenberg/pull/65653)). - `Navigator`: add support for exit animation ([#64777](https://github.com/WordPress/gutenberg/pull/64777)). +- `Guide`: Update finish button to use the new default size ([#65680](https://github.com/WordPress/gutenberg/pull/65680)). ## 28.8.0 (2024-09-19) diff --git a/packages/components/src/guide/index.tsx b/packages/components/src/guide/index.tsx index 0ca5957fd3a656..121c9f22330e88 100644 --- a/packages/components/src/guide/index.tsx +++ b/packages/components/src/guide/index.tsx @@ -164,6 +164,7 @@ function Guide( { className="components-guide__finish-button" variant="primary" onClick={ onFinish } + __next40pxDefaultSize > { finishButtonText } </Button> From 3fd5a61ecd2405580f70881d575bb8261944cde7 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:35:28 +0300 Subject: [PATCH 0988/1908] Block Directory: Fix downloadable block item alignment (#65677) * Block Directory: Fix downloadable block item alignment * Add a comment to explain the extra margin Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> * Fix indentation --------- Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../src/components/downloadable-block-list-item/style.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/block-directory/src/components/downloadable-block-list-item/style.scss b/packages/block-directory/src/components/downloadable-block-list-item/style.scss index fa5e5906cb1b9f..6fce5e1b5b32a7 100644 --- a/packages/block-directory/src/components/downloadable-block-list-item/style.scss +++ b/packages/block-directory/src/components/downloadable-block-list-item/style.scss @@ -69,6 +69,11 @@ align-items: center; justify-content: center; } + + .is-installing & { + // Adding an extra 6px to avoid the UI from jumping when the rating bar gets hidden + margin-right: $grid-unit-20 + 6px; + } } .block-directory-block-ratings { From 1cfb0707a0bb4a99d7b53450bd0cf51077db9af3 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 26 Sep 2024 19:28:14 +0300 Subject: [PATCH 0989/1908] BorderControl: Use `__next40pxDefaultSize` prop for Reset button (#65682) * BorderControl: Use __next40pxDefaultSize prop for Reset button * CHANGELOG Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/border-control/border-control-dropdown/component.tsx | 1 + packages/components/src/border-control/styles.ts | 1 - 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 73f005b653841a..d34b411833468f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -18,6 +18,7 @@ - `DatePicker`: Use compact button size. ([#65653](https://github.com/WordPress/gutenberg/pull/65653)). - `Navigator`: add support for exit animation ([#64777](https://github.com/WordPress/gutenberg/pull/64777)). - `Guide`: Update finish button to use the new default size ([#65680](https://github.com/WordPress/gutenberg/pull/65680)). +- `BorderControl`: Use `__next40pxDefaultSize` prop for Reset button ([#65682](https://github.com/WordPress/gutenberg/pull/65682)). ## 28.8.0 (2024-09-19) diff --git a/packages/components/src/border-control/border-control-dropdown/component.tsx b/packages/components/src/border-control/border-control-dropdown/component.tsx index b2951054e624e7..d84d6bea77335b 100644 --- a/packages/components/src/border-control/border-control-dropdown/component.tsx +++ b/packages/components/src/border-control/border-control-dropdown/component.tsx @@ -237,6 +237,7 @@ const BorderControlDropdown = ( onReset(); onClose(); } } + __next40pxDefaultSize > { __( 'Reset' ) } </Button> diff --git a/packages/components/src/border-control/styles.ts b/packages/components/src/border-control/styles.ts index 2c77a2d21465d6..a678b6f362308a 100644 --- a/packages/components/src/border-control/styles.ts +++ b/packages/components/src/border-control/styles.ts @@ -156,7 +156,6 @@ export const resetButton = css` border-top: ${ CONFIG.borderWidth } solid ${ COLORS.gray[ 400 ] }; border-top-left-radius: 0; border-top-right-radius: 0; - height: 40px; } `; From cb90a76027d4cfcd8b7f6110afea322ead38d24a Mon Sep 17 00:00:00 2001 From: Juliette <663378+jrfnl@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:44:31 +0200 Subject: [PATCH 0990/1908] GH Actions: run the tests against PHP 8.3 (#65357) * GH Actions: run the tests against PHP 8.3 PHP 8.3 was released nearly a year ago. It is unclear to me why the PHP tests are not being run against PHP 8.3, so let's fix this. * GH Actions/test-php: remove redundant step This should have been removed when support for PHP < 7.2 was dropped. --------- Co-authored-by: jrfnl <jrf@git.wordpress.org> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/unit-test.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index b80804b824e3cd..f866b2ccf336e0 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -155,6 +155,7 @@ jobs: - '8.0' - '8.1' - '8.2' + - '8.3' multisite: [false, true] wordpress: [''] # Latest WordPress version. include: @@ -163,7 +164,7 @@ jobs: wordpress: 'previous major version' - php: '7.4' wordpress: 'previous major version' - - php: '8.2' + - php: '8.3' wordpress: 'previous major version' env: @@ -197,12 +198,6 @@ jobs: - name: Override PHP version in composer.json run: composer config platform.php ${{ matrix.php }} - # The spatie/phpunit-watcher package is not compatible with PHP < 7.2. - # It must be removed before running the tests. - - name: Remove incompatible Composer packages - if: ${{ matrix.php < '7.2' }} - run: composer remove spatie/phpunit-watcher --dev --no-update - # Since Composer dependencies are installed using `composer update` and no lock file is in version control, # passing a custom cache suffix ensures that the cache is flushed at least once per week. - name: Install Composer dependencies From f9aa29a1016d357d69c8652b8a4da451979c832a Mon Sep 17 00:00:00 2001 From: Juliette <663378+jrfnl@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:48:13 +0200 Subject: [PATCH 0991/1908] Composer: prevent a lock file from being created (#65359) Composer 1.10.0 introduced a `lock` config option, which, when set to `false` will prevent a `composer.lock` file from being created and will ignore it when one exists. This is a useful option for packages like Gutenberg where the `lock` file has no meaning. It also makes life more straight-forward for contributors as they don't have to remember that for this repo they should use `composer update` instead of `composer install`. Both will now work the same. Refs: https://getcomposer.org/doc/06-config.md#lock Co-authored-by: jrfnl <jrf@git.wordpress.org> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 3571377bd58bd7..4450fd12379ab2 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,8 @@ "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true, "composer/installers": true - } + }, + "lock": false }, "require-dev": { "phpcompatibility/phpcompatibility-wp": "^2.1.3", From dfe58ac83c852d1658f8fd31df2eb974b83006f1 Mon Sep 17 00:00:00 2001 From: Juliette <663378+jrfnl@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:49:39 +0200 Subject: [PATCH 0992/1908] Composer: update minimum required PHPUnit Polyfills (#65355) For compatibility with the WP Core tests, the same (minimum) version of the PHPUnit Polyfills should be required. This has been v1.1.0 since over a year ago. Ref: https://core.trac.wordpress.org/ticket/59150 Co-authored-by: jrfnl <jrf@git.wordpress.org> Co-authored-by: anton-vlasenko <antonvlasenko@git.wordpress.org> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4450fd12379ab2..a8444028bf0a1f 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ "wp-coding-standards/wpcs": "^3.0", "sirbrillig/phpcs-variable-analysis": "^2.8", "spatie/phpunit-watcher": "^1.23", - "yoast/phpunit-polyfills": "^1.0", + "yoast/phpunit-polyfills": "^1.1.0", "gutenberg/gutenberg-coding-standards": "@dev" }, "repositories": [ From 9220e7a0a9f3608743d3ceb029438488a19f4d1e Mon Sep 17 00:00:00 2001 From: Juliette <663378+jrfnl@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:54:50 +0200 Subject: [PATCH 0993/1908] Composer: allow composer/installers 2.x (#65356) Composer released the first version of `composer/installers` 2.x over three years ago. The 2.x range has a minimum PHP version of PHP 7.2. While WordPress and Gutenberg still supported PHP < 7.2, the requirement could have been set to `^1.0 || ^2.0`, but as support for PHP < 7.2 has now been dropped, I see no reason not to require the package at `^2.0` outright. Having said that, there may still be other plugins out there which don't allow for the `composer/installers` 2.x package yet and if one such plugins would be installed as a dependency alongside Gutenberg, this would lead to an unresolvable conflict when running `composer install` for such a project. So with that in mind, I'm erring on the side of caution and propose to change the requirements to `^1.0 || ^2.0`. Note: this will also get rid of a PHP 8.4 deprecation notice when running various Composer commands. Refs: * https://github.com/composer/installers/blob/main/CHANGELOG.md * https://github.com/composer/installers/releases Co-authored-by: jrfnl <jrf@git.wordpress.org> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a8444028bf0a1f..982a71a975223d 100644 --- a/composer.json +++ b/composer.json @@ -44,7 +44,7 @@ } ], "require": { - "composer/installers": "~1.0" + "composer/installers": "^1.0 || ^2.0" }, "scripts": { "format": "phpcbf --standard=phpcs.xml.dist --report-summary --report-source", From c75d114db9961d65d5ef8e1cc7140240207de8ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:55:45 -0400 Subject: [PATCH 0994/1908] Bump the github-actions group across 1 directory with 3 updates (#65679) Bumps the github-actions group with 3 updates in the / directory: [actions/checkout](https://github.com/actions/checkout), [actions/setup-node](https://github.com/actions/setup-node) and [ruby/setup-ruby](https://github.com/ruby/setup-ruby). Updates `actions/checkout` from 4.1.7 to 4.2.0 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...d632683dd7b4114ad314bca15554477dd762a938) Updates `actions/setup-node` from 4.0.3 to 4.0.4 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/1e60f620b9541d16bece96c5465dc8ee9832be0b...0a44ba7841725637a19e28fa30b79a866c81b0a6) Updates `ruby/setup-ruby` from 1.190.0 to 1.194.0 - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb) - [Commits](https://github.com/ruby/setup-ruby/compare/a6e6f86333f0a2523ece813039b8b4be04560854...c04af2bb7258bb6a03df1d3c1865998ac9390972) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/build-plugin-zip.yml | 14 +++++++------- .github/workflows/bundle-size.yml | 4 ++-- .github/workflows/check-backport-changelog.yml | 2 +- .github/workflows/check-components-changelog.yml | 2 +- .github/workflows/cherry-pick-wp-release.yml | 2 +- .github/workflows/create-block.yml | 2 +- .github/workflows/end2end-test.yml | 4 ++-- .github/workflows/gradle-wrapper-validation.yml | 2 +- .github/workflows/performance.yml | 2 +- .github/workflows/publish-npm-packages.yml | 10 +++++----- .github/workflows/pull-request-automation.yml | 4 ++-- .github/workflows/rnmobile-android-runner.yml | 2 +- .github/workflows/rnmobile-ios-runner.yml | 4 ++-- .github/workflows/static-checks.yml | 4 ++-- .github/workflows/storybook-pages.yml | 2 +- .github/workflows/sync-backport-changelog.yml | 2 +- .github/workflows/unit-test.yml | 12 ++++++------ .../workflows/upload-release-to-plugin-repo.yml | 2 +- 18 files changed, 38 insertions(+), 38 deletions(-) diff --git a/.github/workflows/build-plugin-zip.yml b/.github/workflows/build-plugin-zip.yml index ce830c04f651d8..0f813267b586bd 100644 --- a/.github/workflows/build-plugin-zip.yml +++ b/.github/workflows/build-plugin-zip.yml @@ -72,7 +72,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: token: ${{ secrets.GUTENBERG_TOKEN }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -168,13 +168,13 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: ref: ${{ needs.bump-version.outputs.release_branch || github.ref }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Node.js - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version-file: '.nvmrc' check-latest: true @@ -225,7 +225,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 2 ref: ${{ needs.bump-version.outputs.release_branch }} @@ -314,14 +314,14 @@ jobs: if: ${{ endsWith( needs.bump-version.outputs.new_version, '-rc.1' ) }} steps: - name: Checkout (for CLI) - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: path: main ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Checkout (for publishing) - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: path: publish # Later, we switch this branch in the script that publishes packages. @@ -336,7 +336,7 @@ jobs: git config user.email gutenberg@wordpress.org - name: Setup Node.js - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version-file: 'main/.nvmrc' registry-url: 'https://registry.npmjs.org' diff --git a/.github/workflows/bundle-size.yml b/.github/workflows/bundle-size.yml index 499a2c020255cb..e24b30eea7ba7c 100644 --- a/.github/workflows/bundle-size.yml +++ b/.github/workflows/bundle-size.yml @@ -37,13 +37,13 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 1 show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Node.js - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version-file: '.nvmrc' check-latest: true diff --git a/.github/workflows/check-backport-changelog.yml b/.github/workflows/check-backport-changelog.yml index 366bad9fdbc247..cf07b1a3936b97 100644 --- a/.github/workflows/check-backport-changelog.yml +++ b/.github/workflows/check-backport-changelog.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest if: ${{ !contains(github.event.pull_request.labels.*.name, 'No Core Sync Required') && !contains(github.event.pull_request.labels.*.name, 'Backport from WordPress Core') }} steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: ref: ${{ github.event.pull_request.head.ref }} repository: ${{ github.event.pull_request.head.repo.full_name }} diff --git a/.github/workflows/check-components-changelog.yml b/.github/workflows/check-components-changelog.yml index 1f6863b4a486e1..40fbfe22bea568 100644 --- a/.github/workflows/check-components-changelog.yml +++ b/.github/workflows/check-components-changelog.yml @@ -22,7 +22,7 @@ jobs: - name: 'Get PR commit count' run: echo "PR_COMMIT_COUNT=$(( ${{ github.event.pull_request.commits }} + 1 ))" >> "${GITHUB_ENV}" - name: Checkout code - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: ref: ${{ github.event.pull_request.head.ref }} repository: ${{ github.event.pull_request.head.repo.full_name }} diff --git a/.github/workflows/cherry-pick-wp-release.yml b/.github/workflows/cherry-pick-wp-release.yml index b43b0cc267314d..11688a7cfba980 100644 --- a/.github/workflows/cherry-pick-wp-release.yml +++ b/.github/workflows/cherry-pick-wp-release.yml @@ -70,7 +70,7 @@ jobs: - name: Checkout repository if: env.cherry_pick == 'true' - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: token: ${{ secrets.GUTENBERG_TOKEN }} fetch-depth: 0 diff --git a/.github/workflows/create-block.yml b/.github/workflows/create-block.yml index 0de1b9ee6566ae..d20b3e353c31e4 100644 --- a/.github/workflows/create-block.yml +++ b/.github/workflows/create-block.yml @@ -24,7 +24,7 @@ jobs: os: ['macos-latest', 'ubuntu-latest', 'windows-latest'] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/end2end-test.yml b/.github/workflows/end2end-test.yml index 99166989cd68ca..bbf033222a4b31 100644 --- a/.github/workflows/end2end-test.yml +++ b/.github/workflows/end2end-test.yml @@ -27,7 +27,7 @@ jobs: totalParts: [8] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -102,7 +102,7 @@ jobs: steps: # Checkout defaults to using the branch which triggered the event, which # isn't necessarily `trunk` (e.g. in the case of a merge). - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 8cc11b9bd913bb..4715e1e09c2b83 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -6,7 +6,7 @@ jobs: name: 'Validation' runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - uses: gradle/wrapper-validation-action@v3 diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index 98615b93b8a176..9c4bee3af473c8 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -33,7 +33,7 @@ jobs: WP_ARTIFACTS_PATH: ${{ github.workspace }}/artifacts steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/publish-npm-packages.yml b/.github/workflows/publish-npm-packages.yml index a24e5012474025..66f8130ece2f06 100644 --- a/.github/workflows/publish-npm-packages.yml +++ b/.github/workflows/publish-npm-packages.yml @@ -31,7 +31,7 @@ jobs: steps: - name: Checkout (for CLI) if: ${{ github.event.inputs.release_type != 'wp' }} - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: path: cli ref: trunk @@ -39,7 +39,7 @@ jobs: - name: Checkout (for publishing) if: ${{ github.event.inputs.release_type != 'wp' }} - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: path: publish # Later, we switch this branch in the script that publishes packages. @@ -49,7 +49,7 @@ jobs: - name: Checkout (for publishing WP major version) if: ${{ github.event.inputs.release_type == 'wp' && github.event.inputs.wp_version }} - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: path: publish ref: wp/${{ github.event.inputs.wp_version }} @@ -67,7 +67,7 @@ jobs: - name: Setup Node.js if: ${{ github.event.inputs.release_type != 'wp' }} - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version-file: 'cli/.nvmrc' registry-url: 'https://registry.npmjs.org' @@ -75,7 +75,7 @@ jobs: - name: Setup Node.js (for WP major version) if: ${{ github.event.inputs.release_type == 'wp' && github.event.inputs.wp_version }} - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version-file: 'publish/.nvmrc' registry-url: 'https://registry.npmjs.org' diff --git a/.github/workflows/pull-request-automation.yml b/.github/workflows/pull-request-automation.yml index 996bb1667ada57..2006eafd81cc7d 100644 --- a/.github/workflows/pull-request-automation.yml +++ b/.github/workflows/pull-request-automation.yml @@ -12,13 +12,13 @@ jobs: steps: # Checkout defaults to using the branch which triggered the event, which # isn't necessarily `trunk` (e.g. in the case of a merge). - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Node.js - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version-file: '.nvmrc' check-latest: true diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index 2c3998c2952808..917ee6144087e6 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -23,7 +23,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/rnmobile-ios-runner.yml b/.github/workflows/rnmobile-ios-runner.yml index 2926e494b09f89..cf065ad1cdf7db 100644 --- a/.github/workflows/rnmobile-ios-runner.yml +++ b/.github/workflows/rnmobile-ios-runner.yml @@ -23,11 +23,11 @@ jobs: native-test-name: [gutenberg-editor-rendering] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0 + - uses: ruby/setup-ruby@c04af2bb7258bb6a03df1d3c1865998ac9390972 # v1.194.0 with: # `.ruby-version` file location working-directory: packages/react-native-editor/ios diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml index 1efd248bf7f306..1af2bb0ec79275 100644 --- a/.github/workflows/static-checks.yml +++ b/.github/workflows/static-checks.yml @@ -22,12 +22,12 @@ jobs: if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Node.js - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version-file: '.nvmrc' check-latest: true diff --git a/.github/workflows/storybook-pages.yml b/.github/workflows/storybook-pages.yml index 65dd46b3a76108..83f7fdb96f9262 100644 --- a/.github/workflows/storybook-pages.yml +++ b/.github/workflows/storybook-pages.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/sync-backport-changelog.yml b/.github/workflows/sync-backport-changelog.yml index bbc5663cf715be..b71d9440c38a1f 100644 --- a/.github/workflows/sync-backport-changelog.yml +++ b/.github/workflows/sync-backport-changelog.yml @@ -20,7 +20,7 @@ jobs: ) steps: - name: Checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 2 # Fetch the last two commits to compare changes - name: Check for changes in backport-changelog diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index f866b2ccf336e0..bfa35492589a48 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -70,7 +70,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -121,7 +121,7 @@ jobs: name: Build JavaScript assets for PHP unit tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -173,7 +173,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -278,7 +278,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -348,7 +348,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/upload-release-to-plugin-repo.yml b/.github/workflows/upload-release-to-plugin-repo.yml index 81a9c4739ac19b..d09e2af3dd2135 100644 --- a/.github/workflows/upload-release-to-plugin-repo.yml +++ b/.github/workflows/upload-release-to-plugin-repo.yml @@ -96,7 +96,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: ref: ${{ matrix.branch }} token: ${{ secrets.GUTENBERG_TOKEN }} From 0ed82aec5f97a6e5fc06d0654f645865d8484caa Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Thu, 26 Sep 2024 13:37:37 -0500 Subject: [PATCH 0995/1908] Move insertionPoint state to block-editor store/rename existing insertionPoint to insertionCue (#65098) * Renames state.insertionPoint to state.insertionCue in the block editor store and related action/reducers. * Adds state.insertionPoint to store when an insertion point is manually passed. * Dispatching the block editor setInsertionPoint from editor action setIsInserterOpened. * Clear insertionPoint state on SELECT_BLOCK --- .../data/data-core-block-editor.md | 4 +- .../reference-guides/data/data-core-editor.md | 4 + .../block-list/zoom-out-separator.js | 32 ++++++-- .../block-tools/zoom-out-mode-inserters.js | 13 ++-- .../inserter/hooks/use-insertion-point.js | 13 +++- .../src/components/inserter/quick-inserter.js | 4 +- .../block-editor/src/store/private-actions.js | 14 ++++ .../src/store/private-selectors.js | 10 +++ packages/block-editor/src/store/reducer.js | 24 +++++- packages/block-editor/src/store/selectors.js | 15 ++-- .../src/store/test/private-actions.js | 15 ++++ .../block-editor/src/store/test/reducer.js | 44 ++++++++++- .../block-editor/src/store/test/selectors.js | 16 ++-- packages/edit-post/src/store/selectors.js | 2 +- packages/edit-site/src/store/selectors.js | 2 +- .../src/components/inserter-sidebar/index.js | 19 ++--- packages/editor/src/store/actions.js | 29 +++++-- .../editor/src/store/private-selectors.js | 4 +- packages/editor/src/store/test/actions.js | 76 +++++++++++++++++++ packages/editor/src/store/test/reducer.js | 22 ------ 20 files changed, 277 insertions(+), 85 deletions(-) diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index 4b3ca78f74d299..956e8dd010581a 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -262,7 +262,7 @@ _Returns_ ### getBlockInsertionPoint -Returns the insertion point, the index at which the new inserted block would be placed. Defaults to the last index. +Returns the location of the insertion cue. Defaults to the last index. _Parameters_ @@ -982,7 +982,7 @@ _Returns_ ### isBlockInsertionPointVisible -Returns true if we should show the block insertion point. +Returns true if the block insertion point is visible. _Parameters_ diff --git a/docs/reference-guides/data/data-core-editor.md b/docs/reference-guides/data/data-core-editor.md index 4fea2c51fa54f3..a4c1a59f0c4231 100644 --- a/docs/reference-guides/data/data-core-editor.md +++ b/docs/reference-guides/data/data-core-editor.md @@ -1422,6 +1422,10 @@ _Parameters_ - _value_ `boolean|Object`: Whether the inserter should be opened (true) or closed (false). To specify an insertion point, use an object. - _value.rootClientId_ `string`: The root client ID to insert at. - _value.insertionIndex_ `number`: The index to insert at. +- _value.filterValue_ `string`: A query to filter the inserter results. +- _value.onSelect_ `Function`: A callback when an item is selected. +- _value.tab_ `string`: The tab to open in the inserter. +- _value.category_ `string`: The category to initialize in the inserter. _Returns_ diff --git a/packages/block-editor/src/components/block-list/zoom-out-separator.js b/packages/block-editor/src/components/block-list/zoom-out-separator.js index be5af549630607..984e29546c213b 100644 --- a/packages/block-editor/src/components/block-list/zoom-out-separator.js +++ b/packages/block-editor/src/components/block-list/zoom-out-separator.js @@ -29,14 +29,16 @@ export function ZoomOutSeparator( { const { sectionRootClientId, sectionClientIds, - blockInsertionPoint, + insertionPoint, blockInsertionPointVisible, + blockInsertionPoint, } = useSelect( ( select ) => { const { - getBlockInsertionPoint, + getInsertionPoint, getBlockOrder, - isBlockInsertionPointVisible, getSectionRootClientId, + isBlockInsertionPointVisible, + getBlockInsertionPoint, } = unlock( select( blockEditorStore ) ); const root = getSectionRootClientId(); @@ -45,6 +47,7 @@ export function ZoomOutSeparator( { sectionRootClientId: root, sectionClientIds: sectionRootClientIds, blockOrder: getBlockOrder( root ), + insertionPoint: getInsertionPoint(), blockInsertionPoint: getBlockInsertionPoint(), blockInsertionPointVisible: isBlockInsertionPointVisible(), }; @@ -67,17 +70,30 @@ export function ZoomOutSeparator( { return null; } + const hasTopInsertionPoint = + insertionPoint?.index === 0 && + clientId === sectionClientIds[ insertionPoint.index ]; + const hasBottomInsertionPoint = + insertionPoint && + insertionPoint.hasOwnProperty( 'index' ) && + clientId === sectionClientIds[ insertionPoint.index - 1 ]; + // We want to show the zoom out separator in either of these conditions: + // 1. If the inserter has an insertion index set + // 2. We are dragging a pattern over an insertion point if ( position === 'top' ) { isVisible = - blockInsertionPointVisible && - blockInsertionPoint.index === 0 && - clientId === sectionClientIds[ blockInsertionPoint.index ]; + hasTopInsertionPoint || + ( blockInsertionPointVisible && + blockInsertionPoint.index === 0 && + clientId === sectionClientIds[ blockInsertionPoint.index ] ); } if ( position === 'bottom' ) { isVisible = - blockInsertionPointVisible && - clientId === sectionClientIds[ blockInsertionPoint.index - 1 ]; + hasBottomInsertionPoint || + ( blockInsertionPointVisible && + clientId === + sectionClientIds[ blockInsertionPoint.index - 1 ] ); } return ( diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js index 79f8be3f9cfe97..4d47c136defab0 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js @@ -16,7 +16,7 @@ function ZoomOutModeInserters() { const [ isReady, setIsReady ] = useState( false ); const { hasSelection, - blockInsertionPoint, + insertionPoint, blockOrder, blockInsertionPointVisible, setInserterIsOpened, @@ -26,20 +26,20 @@ function ZoomOutModeInserters() { } = useSelect( ( select ) => { const { getSettings, - getBlockInsertionPoint, + getInsertionPoint, getBlockOrder, getSelectionStart, getSelectedBlockClientId, getHoveredBlockClientId, - isBlockInsertionPointVisible, getSectionRootClientId, + isBlockInsertionPointVisible, } = unlock( select( blockEditorStore ) ); const root = getSectionRootClientId(); return { hasSelection: !! getSelectionStart().clientId, - blockInsertionPoint: getBlockInsertionPoint(), + insertionPoint: getInsertionPoint(), blockOrder: getBlockOrder( root ), blockInsertionPointVisible: isBlockInsertionPointVisible(), sectionRootClientId: root, @@ -50,7 +50,8 @@ function ZoomOutModeInserters() { }; }, [] ); - const { showInsertionPoint } = useDispatch( blockEditorStore ); + // eslint-disable-next-line @wordpress/no-unused-vars-before-return + const { showInsertionPoint } = unlock( useDispatch( blockEditorStore ) ); // Defer the initial rendering to avoid the jumps due to the animation. useEffect( () => { @@ -68,7 +69,7 @@ function ZoomOutModeInserters() { return [ undefined, ...blockOrder ].map( ( clientId, index ) => { const shouldRenderInsertionPoint = - blockInsertionPointVisible && blockInsertionPoint.index === index; + blockInsertionPointVisible && insertionPoint?.index === index; const previousClientId = clientId; const nextClientId = blockOrder[ index ]; diff --git a/packages/block-editor/src/components/inserter/hooks/use-insertion-point.js b/packages/block-editor/src/components/inserter/hooks/use-insertion-point.js index 0cd71bf77b9830..de814152c620b0 100644 --- a/packages/block-editor/src/components/inserter/hooks/use-insertion-point.js +++ b/packages/block-editor/src/components/inserter/hooks/use-insertion-point.js @@ -83,15 +83,24 @@ function useInsertionPoint( { getBlockRootClientId, getBlockIndex, getBlockOrder, - } = select( blockEditorStore ); + getInsertionPoint, + } = unlock( select( blockEditorStore ) ); const selectedBlockClientId = getSelectedBlockClientId(); - let _destinationRootClientId = rootClientId; let _destinationIndex; + const insertionPoint = getInsertionPoint(); if ( insertionIndex !== undefined ) { // Insert into a specific index. _destinationIndex = insertionIndex; + } else if ( + insertionPoint && + insertionPoint.hasOwnProperty( 'index' ) + ) { + _destinationRootClientId = insertionPoint?.rootClientId + ? insertionPoint.rootClientId + : rootClientId; + _destinationIndex = insertionPoint.index; } else if ( clientId ) { // Insert after a specific client ID. _destinationIndex = getBlockIndex( clientId ); diff --git a/packages/block-editor/src/components/inserter/quick-inserter.js b/packages/block-editor/src/components/inserter/quick-inserter.js index f40af12feddf4f..7c7f836842b418 100644 --- a/packages/block-editor/src/components/inserter/quick-inserter.js +++ b/packages/block-editor/src/components/inserter/quick-inserter.js @@ -87,10 +87,10 @@ export default function QuickInserter( { // the insertion point can work as expected. const onBrowseAll = () => { setInserterIsOpened( { - rootClientId, - insertionIndex, filterValue, onSelect, + rootClientId, + insertionIndex, } ); }; diff --git a/packages/block-editor/src/store/private-actions.js b/packages/block-editor/src/store/private-actions.js index 441a07202c42ac..5571db0ce91066 100644 --- a/packages/block-editor/src/store/private-actions.js +++ b/packages/block-editor/src/store/private-actions.js @@ -359,6 +359,20 @@ export function expandBlock( clientId ) { }; } +/** + * @param {Object} value + * @param {string} value.rootClientId The root client ID to insert at. + * @param {number} value.index The index to insert at. + * + * @return {Object} Action object. + */ +export function setInsertionPoint( value ) { + return { + type: 'SET_INSERTION_POINT', + value, + }; +} + /** * Temporarily modify/unlock the content-only block for editions. * diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 7af83bed44b0db..c3228980310656 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -674,3 +674,13 @@ export function getClosestAllowedInsertionPointForPattern( const names = getGrammar( pattern ).map( ( { blockName: name } ) => name ); return getClosestAllowedInsertionPoint( state, names, clientId ); } + +/** + * Where the point where the next block will be inserted into. + * + * @param {Object} state + * @return {Object} where the insertion point in the block editor is or null if none is set. + */ +export function getInsertionPoint( state ) { + return state.insertionPoint; +} diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 827a2141f44c1c..f6445f8a3681c9 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1601,7 +1601,7 @@ export function blocksMode( state = {}, action ) { * * @return {Object} Updated state. */ -export function insertionPoint( state = null, action ) { +export function insertionCue( state = null, action ) { switch ( action.type ) { case 'SHOW_INSERTION_POINT': { const { @@ -2066,7 +2066,7 @@ export function hoveredBlockClientId( state = false, action ) { * @param {boolean} state Current state. * @param {Object} action Dispatched action. * - * @return {boolean} Updated state. + * @return {number} Updated state. */ export function zoomLevel( state = 100, action ) { switch ( action.type ) { @@ -2079,6 +2079,25 @@ export function zoomLevel( state = 100, action ) { return state; } +/** + * Reducer setting the insertion point + * + * @param {boolean} state Current state. + * @param {Object} action Dispatched action. + * + * @return {Object} Updated state. + */ +export function insertionPoint( state = null, action ) { + switch ( action.type ) { + case 'SET_INSERTION_POINT': + return action.value; + case 'SELECT_BLOCK': + return null; + } + + return state; +} + const combinedReducers = combineReducers( { blocks, isDragging, @@ -2092,6 +2111,7 @@ const combinedReducers = combineReducers( { blocksMode, blockListSettings, insertionPoint, + insertionCue, template, settings, preferences, diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index a73785edfefd16..7bb002661565bd 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -1454,8 +1454,7 @@ export function isCaretWithinFormattedText() { } /** - * Returns the insertion point, the index at which the new inserted block would - * be placed. Defaults to the last index. + * Returns the location of the insertion cue. Defaults to the last index. * * @param {Object} state Editor state. * @@ -1466,11 +1465,11 @@ export const getBlockInsertionPoint = createSelector( let rootClientId, index; const { - insertionPoint, + insertionCue, selection: { selectionEnd }, } = state; - if ( insertionPoint !== null ) { - return insertionPoint; + if ( insertionCue !== null ) { + return insertionCue; } const { clientId } = selectionEnd; @@ -1485,7 +1484,7 @@ export const getBlockInsertionPoint = createSelector( return { rootClientId, index }; }, ( state ) => [ - state.insertionPoint, + state.insertionCue, state.selection.selectionEnd.clientId, state.blocks.parents, state.blocks.order, @@ -1493,14 +1492,14 @@ export const getBlockInsertionPoint = createSelector( ); /** - * Returns true if we should show the block insertion point. + * Returns true if the block insertion point is visible. * * @param {Object} state Global application state. * * @return {?boolean} Whether the insertion point is visible or not. */ export function isBlockInsertionPointVisible( state ) { - return state.insertionPoint !== null; + return state.insertionCue !== null; } /** diff --git a/packages/block-editor/src/store/test/private-actions.js b/packages/block-editor/src/store/test/private-actions.js index 7576b95866306a..d54a519c9056b6 100644 --- a/packages/block-editor/src/store/test/private-actions.js +++ b/packages/block-editor/src/store/test/private-actions.js @@ -6,6 +6,7 @@ import { showBlockInterface, expandBlock, __experimentalUpdateSettings, + setInsertionPoint, setOpenedBlockSettingsMenu, startDragging, stopDragging, @@ -123,4 +124,18 @@ describe( 'private actions', () => { } ); } ); } ); + + describe( 'setInsertionPoint', () => { + it( 'should return the SET_INSERTION_POINT action', () => { + expect( + setInsertionPoint( { + rootClientId: '', + index: '123', + } ) + ).toEqual( { + type: 'SET_INSERTION_POINT', + value: { rootClientId: '', index: '123' }, + } ); + } ); + } ); } ); diff --git a/packages/block-editor/src/store/test/reducer.js b/packages/block-editor/src/store/test/reducer.js index cd472fa59ac724..1f1b9a9143d981 100644 --- a/packages/block-editor/src/store/test/reducer.js +++ b/packages/block-editor/src/store/test/reducer.js @@ -28,6 +28,7 @@ import { isMultiSelecting, preferences, blocksMode, + insertionCue, insertionPoint, template, blockListSettings, @@ -2378,15 +2379,15 @@ describe( 'state', () => { } ); } ); - describe( 'insertionPoint', () => { + describe( 'insertionCue', () => { it( 'should default to null', () => { - const state = insertionPoint( undefined, {} ); + const state = insertionCue( undefined, {} ); expect( state ).toBe( null ); } ); it( 'should set insertion point', () => { - const state = insertionPoint( null, { + const state = insertionCue( null, { type: 'SHOW_INSERTION_POINT', rootClientId: 'clientId1', index: 0, @@ -2403,7 +2404,7 @@ describe( 'state', () => { rootClientId: 'clientId1', index: 0, } ); - const state = insertionPoint( original, { + const state = insertionCue( original, { type: 'HIDE_INSERTION_POINT', } ); @@ -3485,4 +3486,39 @@ describe( 'state', () => { expect( state ).toBe( null ); } ); } ); + + describe( 'insertionPoint', () => { + it( 'should default to null', () => { + const state = insertionPoint( undefined, {} ); + + expect( state ).toBe( null ); + } ); + + it( 'should set insertion point', () => { + const state = insertionPoint( null, { + type: 'SET_INSERTION_POINT', + value: { + rootClientId: 'clientId1', + index: 4, + }, + } ); + + expect( state ).toEqual( { + rootClientId: 'clientId1', + index: 4, + } ); + } ); + + it( 'should clear the insertion point on block selection', () => { + const original = deepFreeze( { + rootClientId: 'clientId1', + index: 4, + } ); + const state = insertionPoint( original, { + type: 'SELECT_BLOCK', + } ); + + expect( state ).toBe( null ); + } ); + } ); } ); diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index ebf23789fec311..a08c2e0dde1508 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -2425,7 +2425,7 @@ describe( 'selectors', () => { } ) ), }, - insertionPoint: { + insertionCue: { rootClientId: undefined, index: 0, }, @@ -2466,7 +2466,7 @@ describe( 'selectors', () => { } ) ), }, - insertionPoint: null, + insertionCue: null, }; expect( getBlockInsertionPoint( state ) ).toEqual( { @@ -2504,7 +2504,7 @@ describe( 'selectors', () => { } ) ), }, - insertionPoint: null, + insertionCue: null, }; const insertionPoint1 = getBlockInsertionPoint( state ); @@ -2546,7 +2546,7 @@ describe( 'selectors', () => { } ) ), }, - insertionPoint: null, + insertionCue: null, }; expect( getBlockInsertionPoint( state ) ).toEqual( { @@ -2588,7 +2588,7 @@ describe( 'selectors', () => { } ) ), }, - insertionPoint: null, + insertionCue: null, }; expect( getBlockInsertionPoint( state ) ).toEqual( { @@ -2630,7 +2630,7 @@ describe( 'selectors', () => { } ) ), }, - insertionPoint: null, + insertionCue: null, }; expect( getBlockInsertionPoint( state ) ).toEqual( { @@ -2643,7 +2643,7 @@ describe( 'selectors', () => { describe( 'isBlockInsertionPointVisible', () => { it( 'should return false if no assigned insertion point', () => { const state = { - insertionPoint: null, + insertionCue: null, }; expect( isBlockInsertionPointVisible( state ) ).toBe( false ); @@ -2651,7 +2651,7 @@ describe( 'selectors', () => { it( 'should return true if assigned insertion point', () => { const state = { - insertionPoint: { + insertionCue: { rootClientId: undefined, index: 5, }, diff --git a/packages/edit-post/src/store/selectors.js b/packages/edit-post/src/store/selectors.js index 5bea6e7d35eb62..8d85249e8100ba 100644 --- a/packages/edit-post/src/store/selectors.js +++ b/packages/edit-post/src/store/selectors.js @@ -506,7 +506,7 @@ export const __experimentalGetInsertionPoint = createRegistrySelector( version: '6.7', } ); - return unlock( select( editorStore ) ).getInsertionPoint(); + return unlock( select( editorStore ) ).getInserter(); } ); diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js index 3f7bbea0be7d25..ddef4a71d0a915 100644 --- a/packages/edit-site/src/store/selectors.js +++ b/packages/edit-site/src/store/selectors.js @@ -213,7 +213,7 @@ export const __experimentalGetInsertionPoint = createRegistrySelector( version: '6.7', } ); - return unlock( select( editorStore ) ).getInsertionPoint(); + return unlock( select( editorStore ) ).getInserter(); } ); diff --git a/packages/editor/src/components/inserter-sidebar/index.js b/packages/editor/src/components/inserter-sidebar/index.js index b98770b7afe8fa..5cace042fae58c 100644 --- a/packages/editor/src/components/inserter-sidebar/index.js +++ b/packages/editor/src/components/inserter-sidebar/index.js @@ -24,13 +24,13 @@ export default function InserterSidebar() { const { blockSectionRootClientId, inserterSidebarToggleRef, - insertionPoint, + inserter, showMostUsedBlocks, sidebarIsOpened, } = useSelect( ( select ) => { const { getInserterSidebarToggleRef, - getInsertionPoint, + getInserter, isPublishSidebarOpened, } = unlock( select( editorStore ) ); const { @@ -52,7 +52,7 @@ export default function InserterSidebar() { }; return { inserterSidebarToggleRef: getInserterSidebarToggleRef(), - insertionPoint: getInsertionPoint(), + inserter: getInserter(), showMostUsedBlocks: get( 'core', 'mostUsedBlocks' ), blockSectionRootClientId: getBlockSectionRootClientId(), sidebarIsOpened: !! ( @@ -88,14 +88,11 @@ export default function InserterSidebar() { showMostUsedBlocks={ showMostUsedBlocks } showInserterHelpPanel shouldFocusBlock={ isMobileViewport } - rootClientId={ - blockSectionRootClientId ?? insertionPoint.rootClientId - } - __experimentalInsertionIndex={ insertionPoint.insertionIndex } - onSelect={ insertionPoint.onSelect } - __experimentalInitialTab={ insertionPoint.tab } - __experimentalInitialCategory={ insertionPoint.category } - __experimentalFilterValue={ insertionPoint.filterValue } + rootClientId={ blockSectionRootClientId } + onSelect={ inserter.onSelect } + __experimentalInitialTab={ inserter.tab } + __experimentalInitialCategory={ inserter.category } + __experimentalFilterValue={ inserter.filterValue } onPatternCategorySelection={ sidebarIsOpened ? () => disableComplementaryArea( 'core' ) diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index 59faa6b5b73624..4b519a9d8f6cc3 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -26,7 +26,7 @@ import { getNotificationArgumentsForSaveFail, getNotificationArgumentsForTrashFail, } from './utils/notice-builder'; - +import { unlock } from '../lock-unlock'; /** * Returns an action generator used in signalling that editor has initialized with * the specified post object and editor settings. @@ -726,15 +726,32 @@ export function removeEditorPanel( panelName ) { * use an object. * @param {string} value.rootClientId The root client ID to insert at. * @param {number} value.insertionIndex The index to insert at. + * @param {string} value.filterValue A query to filter the inserter results. + * @param {Function} value.onSelect A callback when an item is selected. + * @param {string} value.tab The tab to open in the inserter. + * @param {string} value.category The category to initialize in the inserter. * * @return {Object} Action object. */ -export function setIsInserterOpened( value ) { - return { - type: 'SET_IS_INSERTER_OPENED', - value, +export const setIsInserterOpened = + ( value ) => + ( { dispatch, registry } ) => { + if ( + typeof value === 'object' && + value.hasOwnProperty( 'rootClientId' ) && + value.hasOwnProperty( 'insertionIndex' ) + ) { + unlock( registry.dispatch( blockEditorStore ) ).setInsertionPoint( { + rootClientId: value.rootClientId, + index: value.insertionIndex, + } ); + } + + dispatch( { + type: 'SET_IS_INSERTER_OPENED', + value, + } ); }; -} /** * Returns an action object used to open/close the list view. diff --git a/packages/editor/src/store/private-selectors.js b/packages/editor/src/store/private-selectors.js index 357a7344f631d4..9bc065436c10bb 100644 --- a/packages/editor/src/store/private-selectors.js +++ b/packages/editor/src/store/private-selectors.js @@ -37,13 +37,13 @@ const EMPTY_INSERTION_POINT = { }; /** - * Get the insertion point for the inserter. + * Get the inserter. * * @param {Object} state Global application state. * * @return {Object} The root client ID, index to insert at and starting filter value. */ -export const getInsertionPoint = createRegistrySelector( ( select ) => +export const getInserter = createRegistrySelector( ( select ) => createSelector( ( state ) => { if ( typeof state.blockInserterPanel === 'object' ) { diff --git a/packages/editor/src/store/test/actions.js b/packages/editor/src/store/test/actions.js index fae30c6fc271ec..206c60a159d04f 100644 --- a/packages/editor/src/store/test/actions.js +++ b/packages/editor/src/store/test/actions.js @@ -576,4 +576,80 @@ describe( 'Editor actions', () => { ).toBe( true ); } ); } ); + + describe( 'setIsInserterOpened', () => { + it( 'should open and close the inserter', () => { + const registry = createRegistryWithStores(); + + registry.dispatch( editorStore ).setIsInserterOpened( true ); + + expect( registry.select( editorStore ).isInserterOpened() ).toBe( + true + ); + + registry.dispatch( editorStore ).setIsInserterOpened( false ); + + expect( registry.select( editorStore ).isInserterOpened() ).toBe( + false + ); + } ); + + it( 'the list view should close when the inserter is opened', () => { + const registry = createRegistryWithStores(); + + registry.dispatch( editorStore ).setIsListViewOpened( true ); + expect( registry.select( editorStore ).isListViewOpened() ).toBe( + true + ); + expect( registry.select( editorStore ).isInserterOpened() ).toBe( + false + ); + + registry.dispatch( editorStore ).setIsInserterOpened( true ); + expect( registry.select( editorStore ).isInserterOpened() ).toBe( + true + ); + expect( registry.select( editorStore ).isListViewOpened() ).toBe( + false + ); + } ); + } ); + + describe( 'setIsListViewOpened', () => { + it( 'should open and close the list view', () => { + const registry = createRegistryWithStores(); + + registry.dispatch( editorStore ).setIsListViewOpened( true ); + + expect( registry.select( editorStore ).isListViewOpened() ).toBe( + true + ); + + registry.dispatch( editorStore ).setIsListViewOpened( false ); + + expect( registry.select( editorStore ).isListViewOpened() ).toBe( + false + ); + } ); + + it( 'the inserter should close when the list view is opened', () => { + const registry = createRegistryWithStores(); + + registry.dispatch( editorStore ).setIsInserterOpened( true ); + expect( registry.select( editorStore ).isInserterOpened() ).toBe( + true + ); + expect( registry.select( editorStore ).isListViewOpened() ).toBe( + false + ); + + registry.dispatch( editorStore ).setIsListViewOpened( true ); + expect( registry.select( editorStore ).isListViewOpened() ).toBe( + true + ); + expect( registry.select( editorStore ).isInserterOpened() ).toBe( + false + ); + } ); + } ); } ); diff --git a/packages/editor/src/store/test/reducer.js b/packages/editor/src/store/test/reducer.js index b4fd013c6b4d42..3971ad30c9de74 100644 --- a/packages/editor/src/store/test/reducer.js +++ b/packages/editor/src/store/test/reducer.js @@ -18,7 +18,6 @@ import { blockInserterPanel, listViewPanel, } from '../reducer'; -import { setIsInserterOpened } from '../actions'; describe( 'state', () => { describe( 'hasSameKeys()', () => { @@ -298,15 +297,6 @@ describe( 'state', () => { expect( blockInserterPanel( true, {} ) ).toBe( true ); } ); - it( 'should set the open state of the inserter panel', () => { - expect( - blockInserterPanel( false, setIsInserterOpened( true ) ) - ).toBe( true ); - expect( - blockInserterPanel( true, setIsInserterOpened( false ) ) - ).toBe( false ); - } ); - it( 'should close the inserter when opening the list view panel', () => { expect( blockInserterPanel( true, { @@ -349,17 +339,5 @@ describe( 'state', () => { } ) ).toBe( false ); } ); - - it( 'should close the list view when opening the inserter panel', () => { - expect( listViewPanel( true, setIsInserterOpened( true ) ) ).toBe( - false - ); - } ); - - it( 'should not change the state when closing the inserter panel', () => { - expect( listViewPanel( true, setIsInserterOpened( false ) ) ).toBe( - true - ); - } ); } ); } ); From 93323fd1a3cecd0771ead22b16a9661c53be6212 Mon Sep 17 00:00:00 2001 From: Kai Hao <kevin830726@gmail.com> Date: Fri, 27 Sep 2024 14:18:41 +0800 Subject: [PATCH 0996/1908] Fix unable to remove empty blocks on merge (#65262) Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: kspilarski <kel-dc@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> * Fix unable to remove empty blocks on merge * Update to the stabilized API * Rename the utils --- .../src/components/block-list/block.js | 58 ++++++++--- packages/blocks/src/api/index.js | 2 + packages/blocks/src/api/utils.js | 68 ++++++++++--- .../editor/various/splitting-merging.spec.js | 97 +++++++++++++++++++ 4 files changed, 200 insertions(+), 25 deletions(-) diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 90c39649319dc8..2cecd941dfa3bb 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -25,6 +25,7 @@ import { getBlockDefaultClassName, hasBlockSupport, store as blocksStore, + privateApis as blocksPrivateApis, } from '@wordpress/blocks'; import { withFilters } from '@wordpress/components'; import { withDispatch, useDispatch, useSelect } from '@wordpress/data'; @@ -46,6 +47,8 @@ import { PrivateBlockContext } from './private-block-context'; import { unlock } from '../../lock-unlock'; +const { isUnmodifiedBlockContent } = unlock( blocksPrivateApis ); + /** * Merges wrapper props with special handling for classNames and styles. * @@ -350,12 +353,48 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => { removeBlock( _clientId ); } else { registry.batch( () => { + const firstBlock = getBlock( firstClientId ); + const isFirstBlockContentUnmodified = + isUnmodifiedBlockContent( firstBlock ); + const defaultBlockName = getDefaultBlockName(); + const replacement = switchToBlockType( + firstBlock, + defaultBlockName + ); + const canTransformToDefaultBlock = + !! replacement?.length && + replacement.every( ( block ) => + canInsertBlockType( block.name, _clientId ) + ); + if ( + isFirstBlockContentUnmodified && + canTransformToDefaultBlock + ) { + // Step 1: If the block is empty and can be transformed to the default block type. + replaceBlocks( + firstClientId, + replacement, + changeSelection + ); + } else if ( + isFirstBlockContentUnmodified && + firstBlock.name === defaultBlockName + ) { + // Step 2: If the block is empty and is already the default block type. + removeBlock( firstClientId ); + const nextBlockClientId = + getNextBlockClientId( clientId ); + if ( nextBlockClientId ) { + selectBlock( nextBlockClientId ); + } + } else if ( canInsertBlockType( - getBlockName( firstClientId ), + firstBlock.name, targetRootClientId ) ) { + // Step 3: If the block can be moved up. moveBlocksToPosition( [ firstClientId ], _clientId, @@ -363,21 +402,17 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => { getBlockIndex( _clientId ) ); } else { - const replacement = switchToBlockType( - getBlock( firstClientId ), - getDefaultBlockName() - ); - - if ( - replacement && - replacement.length && + const canLiftAndTransformToDefaultBlock = + !! replacement?.length && replacement.every( ( block ) => canInsertBlockType( block.name, targetRootClientId ) - ) - ) { + ); + + if ( canLiftAndTransformToDefaultBlock ) { + // Step 4: If the block can be transformed to the default block type and moved up. insertBlocks( replacement, getBlockIndex( _clientId ), @@ -386,6 +421,7 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => { ); removeBlock( firstClientId, false ); } else { + // Step 5: Continue the default behavior. switchToDefaultOrRemove(); } } diff --git a/packages/blocks/src/api/index.js b/packages/blocks/src/api/index.js index e7ab69af71103a..e23f347fe4fee8 100644 --- a/packages/blocks/src/api/index.js +++ b/packages/blocks/src/api/index.js @@ -8,6 +8,7 @@ import { getBlockBindingsSource, getBlockBindingsSources, } from './registration'; +import { isUnmodifiedBlockContent } from './utils'; // The blocktype is the most important concept within the block API. It defines // all aspects of the block configuration and its interfaces, including `edit` @@ -183,4 +184,5 @@ lock( privateApis, { unregisterBlockBindingsSource, getBlockBindingsSource, getBlockBindingsSources, + isUnmodifiedBlockContent, } ); diff --git a/packages/blocks/src/api/utils.js b/packages/blocks/src/api/utils.js index 20f0f6a85ed091..7bace4ff84c29b 100644 --- a/packages/blocks/src/api/utils.js +++ b/packages/blocks/src/api/utils.js @@ -30,6 +30,30 @@ extend( [ namesPlugin, a11yPlugin ] ); */ const ICON_COLORS = [ '#191e23', '#f8f9f9' ]; +/** + * Determines whether the block's attribute is equal to the default attribute + * which means the attribute is unmodified. + * @param {Object} attributeDefinition The attribute's definition of the block type. + * @param {*} value The attribute's value. + * @return {boolean} Whether the attribute is unmodified. + */ +function isUnmodifiedAttribute( attributeDefinition, value ) { + // Every attribute that has a default must match the default. + if ( attributeDefinition.hasOwnProperty( 'default' ) ) { + return value === attributeDefinition.default; + } + + // The rich text type is a bit different from the rest because it + // has an implicit default value of an empty RichTextData instance, + // so check the length of the value. + if ( attributeDefinition.type === 'rich-text' ) { + return ! value?.length; + } + + // Every attribute that doesn't have a default should be undefined. + return value === undefined; +} + /** * Determines whether the block's attributes are equal to the default attributes * which means the block is unmodified. @@ -43,20 +67,7 @@ export function isUnmodifiedBlock( block ) { ( [ key, definition ] ) => { const value = block.attributes[ key ]; - // Every attribute that has a default must match the default. - if ( definition.hasOwnProperty( 'default' ) ) { - return value === definition.default; - } - - // The rich text type is a bit different from the rest because it - // has an implicit default value of an empty RichTextData instance, - // so check the length of the value. - if ( definition.type === 'rich-text' ) { - return ! value?.length; - } - - // Every attribute that doesn't have a default should be undefined. - return value === undefined; + return isUnmodifiedAttribute( definition, value ); } ); } @@ -73,6 +84,35 @@ export function isUnmodifiedDefaultBlock( block ) { return block.name === getDefaultBlockName() && isUnmodifiedBlock( block ); } +/** + * Determines whether the block content is unmodified. A block content is + * considered unmodified if all the attributes that have a role of 'content' + * are equal to the default attributes (or undefined). + * If the block does not have any attributes with a role of 'content', it + * will be considered unmodified if all the attributes are equal to the default + * attributes (or undefined). + * + * @param {WPBlock} block Block Object + * @return {boolean} Whether the block content is unmodified. + */ +export function isUnmodifiedBlockContent( block ) { + const contentAttributes = getBlockAttributesNamesByRole( + block.name, + 'content' + ); + + if ( contentAttributes.length === 0 ) { + return isUnmodifiedBlock( block ); + } + + return contentAttributes.every( ( key ) => { + const definition = getBlockType( block.name )?.attributes[ key ]; + const value = block.attributes[ key ]; + + return isUnmodifiedAttribute( definition, value ); + } ); +} + /** * Function that checks if the parameter is a valid icon. * diff --git a/test/e2e/specs/editor/various/splitting-merging.spec.js b/test/e2e/specs/editor/various/splitting-merging.spec.js index 29e7e5d64522c9..eba9f1d3163fd5 100644 --- a/test/e2e/specs/editor/various/splitting-merging.spec.js +++ b/test/e2e/specs/editor/various/splitting-merging.spec.js @@ -373,6 +373,103 @@ test.describe( 'splitting and merging blocks (@firefox, @webkit)', () => { ); } ); + // Fix for https://github.com/WordPress/gutenberg/issues/65174. + test( 'should handle unwrapping and merging blocks with empty contents', async ( { + editor, + page, + } ) => { + const emptyAlignedParagraph = { + name: 'core/paragraph', + attributes: { content: '', align: 'center', dropCap: false }, + innerBlocks: [], + }; + const emptyAlignedHeading = { + name: 'core/heading', + attributes: { content: '', textAlign: 'center', level: 2 }, + innerBlocks: [], + }; + const headingWithContent = { + name: 'core/heading', + attributes: { content: 'heading', level: 2 }, + innerBlocks: [], + }; + const placeholderBlock = { name: 'core/separator' }; + await editor.insertBlock( { + name: 'core/group', + innerBlocks: [ + emptyAlignedParagraph, + emptyAlignedHeading, + headingWithContent, + placeholderBlock, + ], + } ); + await editor.canvas + .getByRole( 'document', { name: 'Empty block' } ) + .focus(); + + await page.keyboard.press( 'Backspace' ); + await expect + .poll( editor.getBlocks, 'Remove the default empty block' ) + .toEqual( [ + { + name: 'core/group', + attributes: { tagName: 'div' }, + innerBlocks: [ + emptyAlignedHeading, + headingWithContent, + expect.objectContaining( placeholderBlock ), + ], + }, + ] ); + + // Move the caret to the beginning of the empty heading block. + await page.keyboard.press( 'ArrowDown' ); + await page.keyboard.press( 'Backspace' ); + await expect + .poll( + editor.getBlocks, + 'Convert the non-default empty block to a default block' + ) + .toEqual( [ + { + name: 'core/group', + attributes: { tagName: 'div' }, + innerBlocks: [ + emptyAlignedParagraph, + headingWithContent, + expect.objectContaining( placeholderBlock ), + ], + }, + ] ); + await page.keyboard.press( 'Backspace' ); + await expect.poll( editor.getBlocks ).toEqual( [ + { + name: 'core/group', + attributes: { tagName: 'div' }, + innerBlocks: [ + headingWithContent, + expect.objectContaining( placeholderBlock ), + ], + }, + ] ); + + // Move the caret to the beginning of the "heading" heading block. + await page.keyboard.press( 'ArrowDown' ); + await page.keyboard.press( 'Backspace' ); + await expect + .poll( editor.getBlocks, 'Lift the non-empty non-default block' ) + .toEqual( [ + headingWithContent, + { + name: 'core/group', + attributes: { tagName: 'div' }, + innerBlocks: [ + expect.objectContaining( placeholderBlock ), + ], + }, + ] ); + } ); + test.describe( 'test restore selection when merge produces more than one block', () => { const snap1 = [ { From ebb58c858addf8268d1c171b9ac85f4b55e0553b Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Fri, 27 Sep 2024 10:24:01 +0200 Subject: [PATCH 0997/1908] Hooks: add support for async filters and actions (#64204) * Hooks: add support for async filters and actions * Unit tests for doing/didAction/Filter --- packages/hooks/CHANGELOG.md | 4 + packages/hooks/README.md | 2 + packages/hooks/src/createCurrentHook.js | 7 +- packages/hooks/src/createDoingHook.js | 10 +- packages/hooks/src/createHooks.js | 10 +- packages/hooks/src/createRunHook.js | 57 +++++---- packages/hooks/src/index.js | 6 +- packages/hooks/src/test/index.test.js | 150 ++++++++++++++++++++++++ 8 files changed, 211 insertions(+), 35 deletions(-) diff --git a/packages/hooks/CHANGELOG.md b/packages/hooks/CHANGELOG.md index 0e162b64513d26..060e061b5c2843 100644 --- a/packages/hooks/CHANGELOG.md +++ b/packages/hooks/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### New Features + +- added new `doActionAsync` and `applyFiltersAsync` functions to run hooks in async mode ([#64204](https://github.com/WordPress/gutenberg/pull/64204)). + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/hooks/README.md b/packages/hooks/README.md index 3e9897c79952cd..f80d2e63af37ba 100644 --- a/packages/hooks/README.md +++ b/packages/hooks/README.md @@ -41,7 +41,9 @@ One notable difference between the JS and PHP hooks API is that in the JS versio - `removeAllActions( 'hookName' )` - `removeAllFilters( 'hookName' )` - `doAction( 'hookName', arg1, arg2, moreArgs, finalArg )` +- `doActionAsync( 'hookName', arg1, arg2, moreArgs, finalArg )` - `applyFilters( 'hookName', content, arg1, arg2, moreArgs, finalArg )` +- `applyFiltersAsync( 'hookName', content, arg1, arg2, moreArgs, finalArg )` - `doingAction( 'hookName' )` - `doingFilter( 'hookName' )` - `didAction( 'hookName' )` diff --git a/packages/hooks/src/createCurrentHook.js b/packages/hooks/src/createCurrentHook.js index 634901fe55f63a..3ada0322496004 100644 --- a/packages/hooks/src/createCurrentHook.js +++ b/packages/hooks/src/createCurrentHook.js @@ -11,11 +11,8 @@ function createCurrentHook( hooks, storeKey ) { return function currentHook() { const hooksStore = hooks[ storeKey ]; - - return ( - hooksStore.__current[ hooksStore.__current.length - 1 ]?.name ?? - null - ); + const currentArray = Array.from( hooksStore.__current ); + return currentArray.at( -1 )?.name ?? null; }; } diff --git a/packages/hooks/src/createDoingHook.js b/packages/hooks/src/createDoingHook.js index 652ab06b4ba728..9fccf38171f332 100644 --- a/packages/hooks/src/createDoingHook.js +++ b/packages/hooks/src/createDoingHook.js @@ -24,13 +24,13 @@ function createDoingHook( hooks, storeKey ) { // If the hookName was not passed, check for any current hook. if ( 'undefined' === typeof hookName ) { - return 'undefined' !== typeof hooksStore.__current[ 0 ]; + return hooksStore.__current.size > 0; } - // Return the __current hook. - return hooksStore.__current[ 0 ] - ? hookName === hooksStore.__current[ 0 ].name - : false; + // Find if the `hookName` hook is in `__current`. + return Array.from( hooksStore.__current ).some( + ( hook ) => hook.name === hookName + ); }; } diff --git a/packages/hooks/src/createHooks.js b/packages/hooks/src/createHooks.js index 361383a3a97fc9..1f9b1a8206b020 100644 --- a/packages/hooks/src/createHooks.js +++ b/packages/hooks/src/createHooks.js @@ -20,11 +20,11 @@ export class _Hooks { constructor() { /** @type {import('.').Store} actions */ this.actions = Object.create( null ); - this.actions.__current = []; + this.actions.__current = new Set(); /** @type {import('.').Store} filters */ this.filters = Object.create( null ); - this.filters.__current = []; + this.filters.__current = new Set(); this.addAction = createAddHook( this, 'actions' ); this.addFilter = createAddHook( this, 'filters' ); @@ -34,8 +34,10 @@ export class _Hooks { this.hasFilter = createHasHook( this, 'filters' ); this.removeAllActions = createRemoveHook( this, 'actions', true ); this.removeAllFilters = createRemoveHook( this, 'filters', true ); - this.doAction = createRunHook( this, 'actions' ); - this.applyFilters = createRunHook( this, 'filters', true ); + this.doAction = createRunHook( this, 'actions', false, false ); + this.doActionAsync = createRunHook( this, 'actions', false, true ); + this.applyFilters = createRunHook( this, 'filters', true, false ); + this.applyFiltersAsync = createRunHook( this, 'filters', true, true ); this.currentAction = createCurrentHook( this, 'actions' ); this.currentFilter = createCurrentHook( this, 'filters' ); this.doingAction = createDoingHook( this, 'actions' ); diff --git a/packages/hooks/src/createRunHook.js b/packages/hooks/src/createRunHook.js index c2bf6fd187ce08..f2a56dbdc0d717 100644 --- a/packages/hooks/src/createRunHook.js +++ b/packages/hooks/src/createRunHook.js @@ -3,15 +3,15 @@ * registered to a hook of the specified type, optionally returning the final * value of the call chain. * - * @param {import('.').Hooks} hooks Hooks instance. + * @param {import('.').Hooks} hooks Hooks instance. * @param {import('.').StoreKey} storeKey - * @param {boolean} [returnFirstArg=false] Whether each hook callback is expected to - * return its first argument. + * @param {boolean} returnFirstArg Whether each hook callback is expected to return its first argument. + * @param {boolean} async Whether the hook callback should be run asynchronously * * @return {(hookName:string, ...args: unknown[]) => undefined|unknown} Function that runs hook callbacks. */ -function createRunHook( hooks, storeKey, returnFirstArg = false ) { - return function runHooks( hookName, ...args ) { +function createRunHook( hooks, storeKey, returnFirstArg, async ) { + return function runHook( hookName, ...args ) { const hooksStore = hooks[ storeKey ]; if ( ! hooksStore[ hookName ] ) { @@ -42,26 +42,43 @@ function createRunHook( hooks, storeKey, returnFirstArg = false ) { currentIndex: 0, }; - hooksStore.__current.push( hookInfo ); - - while ( hookInfo.currentIndex < handlers.length ) { - const handler = handlers[ hookInfo.currentIndex ]; - - const result = handler.callback.apply( null, args ); - if ( returnFirstArg ) { - args[ 0 ] = result; + async function asyncRunner() { + try { + hooksStore.__current.add( hookInfo ); + let result = returnFirstArg ? args[ 0 ] : undefined; + while ( hookInfo.currentIndex < handlers.length ) { + const handler = handlers[ hookInfo.currentIndex ]; + result = await handler.callback.apply( null, args ); + if ( returnFirstArg ) { + args[ 0 ] = result; + } + hookInfo.currentIndex++; + } + return returnFirstArg ? result : undefined; + } finally { + hooksStore.__current.delete( hookInfo ); } - - hookInfo.currentIndex++; } - hooksStore.__current.pop(); - - if ( returnFirstArg ) { - return args[ 0 ]; + function syncRunner() { + try { + hooksStore.__current.add( hookInfo ); + let result = returnFirstArg ? args[ 0 ] : undefined; + while ( hookInfo.currentIndex < handlers.length ) { + const handler = handlers[ hookInfo.currentIndex ]; + result = handler.callback.apply( null, args ); + if ( returnFirstArg ) { + args[ 0 ] = result; + } + hookInfo.currentIndex++; + } + return returnFirstArg ? result : undefined; + } finally { + hooksStore.__current.delete( hookInfo ); + } } - return undefined; + return ( async ? asyncRunner : syncRunner )(); }; } diff --git a/packages/hooks/src/index.js b/packages/hooks/src/index.js index 653a9537145d91..1d13397e406c6b 100644 --- a/packages/hooks/src/index.js +++ b/packages/hooks/src/index.js @@ -25,7 +25,7 @@ import createHooks from './createHooks'; */ /** - * @typedef {Record<string, Hook> & {__current: Current[]}} Store + * @typedef {Record<string, Hook> & {__current: Set<Current>}} Store */ /** @@ -48,7 +48,9 @@ const { removeAllActions, removeAllFilters, doAction, + doActionAsync, applyFilters, + applyFiltersAsync, currentAction, currentFilter, doingAction, @@ -70,7 +72,9 @@ export { removeAllActions, removeAllFilters, doAction, + doActionAsync, applyFilters, + applyFiltersAsync, currentAction, currentFilter, doingAction, diff --git a/packages/hooks/src/test/index.test.js b/packages/hooks/src/test/index.test.js index 9b7eb3b8e0e223..5fdaf5fc7207a1 100644 --- a/packages/hooks/src/test/index.test.js +++ b/packages/hooks/src/test/index.test.js @@ -12,7 +12,9 @@ import { removeAllActions, removeAllFilters, doAction, + doActionAsync, applyFilters, + applyFiltersAsync, currentAction, currentFilter, doingAction, @@ -943,3 +945,151 @@ test( 'checking hasFilter with named callbacks and removeAllActions', () => { expect( hasFilter( 'test.filter', 'my_callback' ) ).toBe( false ); expect( hasFilter( 'test.filter', 'my_second_callback' ) ).toBe( false ); } ); + +describe( 'async filter', () => { + test( 'runs all registered handlers', async () => { + addFilter( 'test.async.filter', 'callback_plus1', ( value ) => { + return new Promise( ( r ) => + setTimeout( () => r( value + 1 ), 10 ) + ); + } ); + addFilter( 'test.async.filter', 'callback_times2', ( value ) => { + return new Promise( ( r ) => + setTimeout( () => r( value * 2 ), 10 ) + ); + } ); + + expect( await applyFiltersAsync( 'test.async.filter', 2 ) ).toBe( 6 ); + } ); + + test( 'aborts when handler throws an error', async () => { + const sqrt = jest.fn( async ( value ) => { + if ( value < 0 ) { + throw new Error( 'cannot pass negative value to sqrt' ); + } + return Math.sqrt( value ); + } ); + + const plus1 = jest.fn( async ( value ) => { + return value + 1; + } ); + + addFilter( 'test.async.filter', 'callback_sqrt', sqrt ); + addFilter( 'test.async.filter', 'callback_plus1', plus1 ); + + await expect( + applyFiltersAsync( 'test.async.filter', -1 ) + ).rejects.toThrow( 'cannot pass negative value to sqrt' ); + expect( sqrt ).toHaveBeenCalledTimes( 1 ); + expect( plus1 ).not.toHaveBeenCalled(); + } ); + + test( 'is correctly tracked by doingFilter and didFilter', async () => { + addFilter( 'test.async.filter', 'callback_doing', async ( value ) => { + await new Promise( ( r ) => setTimeout( () => r(), 10 ) ); + expect( doingFilter( 'test.async.filter' ) ).toBe( true ); + return value; + } ); + + expect( doingFilter( 'test.async.filter' ) ).toBe( false ); + expect( didFilter( 'test.async.filter' ) ).toBe( 0 ); + await applyFiltersAsync( 'test.async.filter', 0 ); + expect( doingFilter( 'test.async.filter' ) ).toBe( false ); + expect( didFilter( 'test.async.filter' ) ).toBe( 1 ); + } ); + + test( 'is correctly tracked when multiple filters run at once', async () => { + addFilter( 'test.async.filter1', 'callback_doing', async ( value ) => { + await new Promise( ( r ) => setTimeout( () => r(), 10 ) ); + expect( doingFilter( 'test.async.filter1' ) ).toBe( true ); + await new Promise( ( r ) => setTimeout( () => r(), 10 ) ); + return value; + } ); + addFilter( 'test.async.filter2', 'callback_doing', async ( value ) => { + await new Promise( ( r ) => setTimeout( () => r(), 10 ) ); + expect( doingFilter( 'test.async.filter2' ) ).toBe( true ); + await new Promise( ( r ) => setTimeout( () => r(), 10 ) ); + return value; + } ); + + await Promise.all( [ + applyFiltersAsync( 'test.async.filter1', 0 ), + applyFiltersAsync( 'test.async.filter2', 0 ), + ] ); + } ); +} ); + +describe( 'async action', () => { + test( 'runs all registered handlers sequentially', async () => { + const outputs = []; + const action1 = async () => { + outputs.push( 1 ); + await new Promise( ( r ) => setTimeout( () => r(), 10 ) ); + outputs.push( 2 ); + }; + + const action2 = async () => { + outputs.push( 3 ); + await new Promise( ( r ) => setTimeout( () => r(), 10 ) ); + outputs.push( 4 ); + }; + + addAction( 'test.async.action', 'action1', action1 ); + addAction( 'test.async.action', 'action2', action2 ); + + await doActionAsync( 'test.async.action' ); + expect( outputs ).toEqual( [ 1, 2, 3, 4 ] ); + } ); + + test( 'aborts when handler throws an error', async () => { + const outputs = []; + const action1 = async () => { + throw new Error( 'aborting' ); + }; + + const action2 = async () => { + outputs.push( 3 ); + await new Promise( ( r ) => setTimeout( () => r(), 10 ) ); + outputs.push( 4 ); + }; + + addAction( 'test.async.action', 'action1', action1 ); + addAction( 'test.async.action', 'action2', action2 ); + + await expect( doActionAsync( 'test.async.action' ) ).rejects.toThrow( + 'aborting' + ); + expect( outputs ).toEqual( [] ); + } ); + + test( 'is correctly tracked by doingAction and didAction', async () => { + addAction( 'test.async.action', 'callback_doing', async () => { + await new Promise( ( r ) => setTimeout( () => r(), 10 ) ); + expect( doingAction( 'test.async.action' ) ).toBe( true ); + } ); + + expect( doingAction( 'test.async.action' ) ).toBe( false ); + expect( didAction( 'test.async.action' ) ).toBe( 0 ); + await doActionAsync( 'test.async.action', 0 ); + expect( doingAction( 'test.async.action' ) ).toBe( false ); + expect( didAction( 'test.async.action' ) ).toBe( 1 ); + } ); + + test( 'is correctly tracked when multiple actions run at once', async () => { + addAction( 'test.async.action1', 'callback_doing', async () => { + await new Promise( ( r ) => setTimeout( () => r(), 10 ) ); + expect( doingAction( 'test.async.action1' ) ).toBe( true ); + await new Promise( ( r ) => setTimeout( () => r(), 10 ) ); + } ); + addAction( 'test.async.action2', 'callback_doing', async () => { + await new Promise( ( r ) => setTimeout( () => r(), 10 ) ); + expect( doingAction( 'test.async.action2' ) ).toBe( true ); + await new Promise( ( r ) => setTimeout( () => r(), 10 ) ); + } ); + + await Promise.all( [ + doActionAsync( 'test.async.action1', 0 ), + doActionAsync( 'test.async.action2', 0 ), + ] ); + } ); +} ); From ae1c989558079c705be7e5ecbd36fc596c9c23ae Mon Sep 17 00:00:00 2001 From: dhruvang21 <105810308+dhruvang21@users.noreply.github.com> Date: Fri, 27 Sep 2024 17:10:24 +0530 Subject: [PATCH 0998/1908] Added: DropZone when sitelogo is present (#65596) * Add: DropZone when sitelogo is present * Add canUserEdit condition in dropzone Co-authored-by: dhruvang21 <dhruvang21@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --------- Co-authored-by: Sarah Norris <1645628+mikachan@users.noreply.github.com> --- packages/block-library/src/site-logo/edit.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index dc95d5906d7345..36c217c1bf0c79 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -564,6 +564,7 @@ export default function LogoEdit( { iconId={ siteIconId } canUserEdit={ canUserEdit } /> + { canUserEdit && <DropZone onFilesDrop={ onFilesDrop } /> } </> ); } From 2659751cb8316b036de37ce3988829158c354a92 Mon Sep 17 00:00:00 2001 From: djcowan <dj.cowan@icloud.com> Date: Fri, 27 Sep 2024 22:01:48 +1000 Subject: [PATCH 0999/1908] RichText: Update JSDoc block for to-html-string (#65688) Co-authored-by: djcowan <djcowan@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/rich-text/README.md | 2 +- packages/rich-text/src/to-html-string.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rich-text/README.md b/packages/rich-text/README.md index 3c3abc422fa5f9..033a4f2c747abe 100644 --- a/packages/rich-text/README.md +++ b/packages/rich-text/README.md @@ -430,7 +430,7 @@ Create an HTML string from a Rich Text value. _Parameters_ -- _$1_ `Object`: Named argements. +- _$1_ `Object`: Named arguments. - _$1.value_ `RichTextValue`: Rich text value. - _$1.preserveWhiteSpace_ `[boolean]`: Preserves newlines if true. diff --git a/packages/rich-text/src/to-html-string.js b/packages/rich-text/src/to-html-string.js index 35089003f0b3fb..f770dfdefc128a 100644 --- a/packages/rich-text/src/to-html-string.js +++ b/packages/rich-text/src/to-html-string.js @@ -19,7 +19,7 @@ import { toTree } from './to-tree'; /** * Create an HTML string from a Rich Text value. * - * @param {Object} $1 Named argements. + * @param {Object} $1 Named arguments. * @param {RichTextValue} $1.value Rich text value. * @param {boolean} [$1.preserveWhiteSpace] Preserves newlines if true. * From 3155ab7fff75f4204faaa5bb621811f492905dc6 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Fri, 27 Sep 2024 13:40:25 +0100 Subject: [PATCH 1000/1908] Add prompt to zoom out separator (#65392) * Add prompt to separator * updated the text to be animated too and to have contextual messageing - drop or insert * Fix font size * Scale font size based on zoom scale * Force font weight reset * Remove dynamic text * adds a color to the test which somehow gets the same color as the babacground after rebase on trunk * bogus change for our pipeline * revert bogus change for our pipeline to restart --------- Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../src/components/block-list/content.scss | 12 ++++++++++++ .../components/block-list/zoom-out-separator.js | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index 3e3865e689beac..c5fda109d8b67d 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -411,6 +411,18 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b margin-left: -1px; margin-right: -1px; transition: background-color 0.3s ease; + display: flex; + align-items: center; + justify-content: center; + font-size: $default-font-size; + font-family: $default-font; + color: $black; + font-weight: normal; + + .is-zoomed-out & { + // Scale the font size based on the zoom level. + font-size: calc(#{$default-font-size} * ( 2 - var(--wp-block-editor-iframe-zoom-out-scale) )); + } &.is-dragged-over { background: $gray-400; diff --git a/packages/block-editor/src/components/block-list/zoom-out-separator.js b/packages/block-editor/src/components/block-list/zoom-out-separator.js index 984e29546c213b..9e0d087c2267cd 100644 --- a/packages/block-editor/src/components/block-list/zoom-out-separator.js +++ b/packages/block-editor/src/components/block-list/zoom-out-separator.js @@ -13,6 +13,7 @@ import { import { useReducedMotion } from '@wordpress/compose'; import { useSelect } from '@wordpress/data'; import { useState } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -119,7 +120,19 @@ export function ZoomOutSeparator( { data-is-insertion-point="true" onDragOver={ () => setIsDraggedOver( true ) } onDragLeave={ () => setIsDraggedOver( false ) } - ></motion.div> + > + <motion.div + initial={ { opacity: 0 } } + animate={ { opacity: 1 } } + exit={ { opacity: 0 } } + transition={ { + type: 'tween', + duration: 0.1, + } } + > + { __( 'Drop pattern.' ) } + </motion.div> + </motion.div> ) } </AnimatePresence> ); From cc0b3d3ae350e9f87527371ef9a761f27409d329 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 27 Sep 2024 22:04:34 +0900 Subject: [PATCH 1001/1908] Editor Canvas: Tweal close button (#65694) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../edit-site/src/components/editor-canvas-container/index.js | 2 +- .../edit-site/src/components/editor-canvas-container/style.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/editor-canvas-container/index.js b/packages/edit-site/src/components/editor-canvas-container/index.js index c55d6b188e1a25..ac1083e69abd7e 100644 --- a/packages/edit-site/src/components/editor-canvas-container/index.js +++ b/packages/edit-site/src/components/editor-canvas-container/index.js @@ -125,7 +125,7 @@ function EditorCanvasContainer( { > { shouldShowCloseButton && ( <Button - __next40pxDefaultSize + size="compact" className="edit-site-editor-canvas-container__close-button" icon={ closeSmall } label={ closeButtonLabel || __( 'Close' ) } diff --git a/packages/edit-site/src/components/editor-canvas-container/style.scss b/packages/edit-site/src/components/editor-canvas-container/style.scss index 7df2b0ceca552f..80d6a909d0c952 100644 --- a/packages/edit-site/src/components/editor-canvas-container/style.scss +++ b/packages/edit-site/src/components/editor-canvas-container/style.scss @@ -29,7 +29,7 @@ .edit-site-editor-canvas-container__close-button { position: absolute; right: $grid-unit-10; - top: math.div($grid-unit-60 - $button-size, 2); // ( tab height - button size ) / 2 + top: $grid-unit-10; z-index: 1; background: $white; } From de01da21b2b966ed58d11719e4fbc8b7bf114719 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 27 Sep 2024 22:07:02 +0900 Subject: [PATCH 1002/1908] Tweak entity save panel button (#65695) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../components/entities-saved-states/index.js | 18 ++++++++++-------- .../entities-saved-states/style.scss | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/editor/src/components/entities-saved-states/index.js b/packages/editor/src/components/entities-saved-states/index.js index 8c0d59573a44d9..ba84ef2b392f5b 100644 --- a/packages/editor/src/components/entities-saved-states/index.js +++ b/packages/editor/src/components/entities-saved-states/index.js @@ -128,11 +128,21 @@ export function EntitiesSavedStatesExtensible( { aria-describedby={ renderDialog ? dialogDescription : undefined } > <Flex className="entities-saved-states__panel-header" gap={ 2 }> + <FlexItem + isBlock + as={ Button } + variant="secondary" + size="compact" + onClick={ dismissPanel } + > + { __( 'Cancel' ) } + </FlexItem> <FlexItem isBlock as={ Button } ref={ saveButtonRef } variant="primary" + size="compact" disabled={ ! saveEnabled } accessibleWhenDisabled onClick={ () => @@ -147,14 +157,6 @@ export function EntitiesSavedStatesExtensible( { > { saveLabel } </FlexItem> - <FlexItem - isBlock - as={ Button } - variant="secondary" - onClick={ dismissPanel } - > - { __( 'Cancel' ) } - </FlexItem> </Flex> <div className="entities-saved-states__text-prompt"> diff --git a/packages/editor/src/components/entities-saved-states/style.scss b/packages/editor/src/components/entities-saved-states/style.scss index 981a0d92e5ff6b..e2c320678c322a 100644 --- a/packages/editor/src/components/entities-saved-states/style.scss +++ b/packages/editor/src/components/entities-saved-states/style.scss @@ -1,8 +1,8 @@ .entities-saved-states__panel-header { box-sizing: border-box; background: $white; - padding-left: $grid-unit-10; - padding-right: $grid-unit-10; + padding-left: $grid-unit-20; + padding-right: $grid-unit-20; height: $header-height; border-bottom: $border-width solid $gray-300; } From 3e0d294d59a60f0e87539a5465237262e239be38 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Fri, 27 Sep 2024 16:29:49 +0200 Subject: [PATCH 1003/1908] Stabilize the PreSavePost and SavePost filters (#64198) * Stabilize the PreSavePost and SavePost filters * Use lowercase names * Use async hooks --- packages/edit-post/src/store/actions.js | 23 ++++++--------- packages/editor/src/store/actions.js | 37 +++++++++++++++++-------- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/packages/edit-post/src/store/actions.js b/packages/edit-post/src/store/actions.js index d00f7472382f80..1dc0401baf21c3 100644 --- a/packages/edit-post/src/store/actions.js +++ b/packages/edit-post/src/store/actions.js @@ -8,7 +8,7 @@ import { privateApis as editorPrivateApis, } from '@wordpress/editor'; import deprecated from '@wordpress/deprecated'; -import { addFilter } from '@wordpress/hooks'; +import { addAction } from '@wordpress/hooks'; import { store as coreStore } from '@wordpress/core-data'; /** @@ -478,21 +478,14 @@ export const initializeMetaBoxes = metaBoxesInitialized = true; // Save metaboxes on save completion, except for autosaves. - addFilter( - 'editor.__unstableSavePost', + addAction( + 'editor.savePost', 'core/edit-post/save-metaboxes', - ( previous, options ) => - previous.then( () => { - if ( options.isAutosave ) { - return; - } - - if ( ! select.hasMetaBoxes() ) { - return; - } - - return dispatch.requestMetaBoxUpdates(); - } ) + async ( options ) => { + if ( ! options.isAutosave && select.hasMetaBoxes() ) { + await dispatch.requestMetaBoxUpdates(); + } + } ); dispatch( { diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index 4b519a9d8f6cc3..fa720e1fc7d347 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -12,7 +12,11 @@ import { import { store as noticesStore } from '@wordpress/notices'; import { store as coreStore } from '@wordpress/core-data'; import { store as blockEditorStore } from '@wordpress/block-editor'; -import { applyFilters } from '@wordpress/hooks'; +import { + applyFilters, + applyFiltersAsync, + doActionAsync, +} from '@wordpress/hooks'; import { store as preferencesStore } from '@wordpress/preferences'; import { __ } from '@wordpress/i18n'; @@ -184,7 +188,7 @@ export const savePost = } const previousRecord = select.getCurrentPost(); - const edits = { + let edits = { id: previousRecord.id, ...registry .select( coreStore ) @@ -199,9 +203,9 @@ export const savePost = let error = false; try { - error = await applyFilters( - 'editor.__unstablePreSavePost', - Promise.resolve( false ), + edits = await applyFiltersAsync( + 'editor.preSavePost', + edits, options ); } catch ( err ) { @@ -236,14 +240,25 @@ export const savePost = ); } + // Run the hook with legacy unstable name for backward compatibility if ( ! error ) { - await applyFilters( - 'editor.__unstableSavePost', - Promise.resolve(), - options - ).catch( ( err ) => { + try { + await applyFilters( + 'editor.__unstableSavePost', + Promise.resolve(), + options + ); + } catch ( err ) { error = err; - } ); + } + } + + if ( ! error ) { + try { + await doActionAsync( 'editor.savePost', options ); + } catch ( err ) { + error = err; + } } dispatch( { type: 'REQUEST_POST_UPDATE_FINISH', options } ); From 6f0fd8ee03f4c39838de7d88dbb9ed6010c082e8 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 27 Sep 2024 17:07:22 +0200 Subject: [PATCH 1004/1908] Navigator: stabilize and export APIs (#64613) * Remove experimental status from Storybook * NavigatorProvider => Navigator (internally) * Move legacy exports to separate file * Export overloaded notation * Use overloaded notation in Storybook * Use overloaded notation in unit tests (skipping deprecated component for now) * Update docs manifest.json * Navigator: update docs * Navigator.BackButton: update docs * NavigatorToParentButton: delete README * Navigator.Button: update docs * NavigatorScreen: update docs * Restore `NavigatorToParentButton` test * Use dot notation in context namespaces too * Use named export for `NavigatorToParentButton` too * Fixup docs manifest * Export stable version from components package * CHANGELOG * Change index.ts extension to tsx to allow Storybook to extract JSDocs better, remove duplicate JSDocs * Remove unnecessary and mispelled display name for top-level `Navigator` * Remove @example tag from top-level export * Clean up unused imports * Fix storybook styles * Update new section of the docs * Update more docs * Update deprecation warning * Update and align docs * Fix tests warning checks * Typo * Fix useContextSystem names * Remove mentions of the `useNavigator` hook * useNavigator JSDocs * Move all READMEs under the main README * Move README to component's root folder * Update types JSDocs to match README * Update docs manifest * Fix JSDocs typos, grammar, and broken links. * Update storybook selector --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- docs/manifest.json | 30 +--- packages/components/CHANGELOG.md | 1 + packages/components/src/index.ts | 1 + packages/components/src/navigator/README.md | 168 ++++++++++++++++++ packages/components/src/navigator/index.tsx | 131 ++++++++++++++ packages/components/src/navigator/legacy.ts | 15 +- .../navigator/navigator-back-button/README.md | 15 -- .../navigator-back-button/component.tsx | 2 +- .../navigator/navigator-back-button/hook.ts | 2 +- .../src/navigator/navigator-button/README.md | 38 ---- .../navigator/navigator-button/component.tsx | 2 +- .../src/navigator/navigator-button/hook.ts | 2 +- .../navigator/navigator-provider/README.md | 98 ---------- .../src/navigator/navigator-screen/README.md | 33 ---- .../navigator/navigator-screen/component.tsx | 6 +- .../navigator-to-parent-button/README.md | 17 -- .../navigator-to-parent-button/component.tsx | 7 +- .../component.tsx | 44 +---- .../src/navigator/stories/index.story.tsx | 98 +++++----- packages/components/src/navigator/styles.ts | 2 +- .../components/src/navigator/test/index.tsx | 94 +++++----- packages/components/src/navigator/types.ts | 18 ++ .../components/src/navigator/use-navigator.ts | 5 +- storybook/manager-head.html | 1 + 24 files changed, 445 insertions(+), 385 deletions(-) create mode 100644 packages/components/src/navigator/README.md create mode 100644 packages/components/src/navigator/index.tsx delete mode 100644 packages/components/src/navigator/navigator-back-button/README.md delete mode 100644 packages/components/src/navigator/navigator-button/README.md delete mode 100644 packages/components/src/navigator/navigator-provider/README.md delete mode 100644 packages/components/src/navigator/navigator-screen/README.md delete mode 100644 packages/components/src/navigator/navigator-to-parent-button/README.md rename packages/components/src/navigator/{navigator-provider => navigator}/component.tsx (84%) diff --git a/docs/manifest.json b/docs/manifest.json index d76717fbdedfc1..8387b9079694c0 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1098,33 +1098,9 @@ "parent": "components" }, { - "title": "NavigatorBackButton", - "slug": "navigator-back-button", - "markdown_source": "../packages/components/src/navigator/navigator-back-button/README.md", - "parent": "components" - }, - { - "title": "NavigatorButton", - "slug": "navigator-button", - "markdown_source": "../packages/components/src/navigator/navigator-button/README.md", - "parent": "components" - }, - { - "title": "NavigatorProvider", - "slug": "navigator-provider", - "markdown_source": "../packages/components/src/navigator/navigator-provider/README.md", - "parent": "components" - }, - { - "title": "NavigatorScreen", - "slug": "navigator-screen", - "markdown_source": "../packages/components/src/navigator/navigator-screen/README.md", - "parent": "components" - }, - { - "title": "NavigatorToParentButton", - "slug": "navigator-to-parent-button", - "markdown_source": "../packages/components/src/navigator/navigator-to-parent-button/README.md", + "title": "Navigator", + "slug": "navigator", + "markdown_source": "../packages/components/src/navigator/README.md", "parent": "components" }, { diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index d34b411833468f..8ef1c7c3bd2002 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -19,6 +19,7 @@ - `Navigator`: add support for exit animation ([#64777](https://github.com/WordPress/gutenberg/pull/64777)). - `Guide`: Update finish button to use the new default size ([#65680](https://github.com/WordPress/gutenberg/pull/65680)). - `BorderControl`: Use `__next40pxDefaultSize` prop for Reset button ([#65682](https://github.com/WordPress/gutenberg/pull/65682)). +- `Navigator`: stabilize APIs ([#64613](https://github.com/WordPress/gutenberg/pull/64613)). ## 28.8.0 (2024-09-19) diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index 37ba116a7f679e..cc3c0265c42208 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -132,6 +132,7 @@ export { NavigatorToParentButton as __experimentalNavigatorToParentButton, useNavigator as __experimentalUseNavigator, } from './navigator/legacy'; +export { Navigator, useNavigator } from './navigator'; export { default as Notice } from './notice'; export { default as __experimentalNumberControl } from './number-control'; export { default as NoticeList } from './notice/list'; diff --git a/packages/components/src/navigator/README.md b/packages/components/src/navigator/README.md new file mode 100644 index 00000000000000..00b1cfaeebe0f7 --- /dev/null +++ b/packages/components/src/navigator/README.md @@ -0,0 +1,168 @@ +# `Navigator` + +`Navigator` is a collection components that allow rendering nested views/panels/menus (via the `Navigator.Screen` component) and navigate between them (via the `Navigator.Button` and `Navigator.BackButton` components). + +## Usage + +```jsx +import { Navigator } from '@wordpress/components'; + +const MyNavigation = () => ( + <Navigator initialPath="/"> + <Navigator.Screen path="/"> + <p>This is the home screen.</p> + <Navigator.Button path="/child"> + Navigate to child screen. + </Navigator.Button> + </Navigator.Screen> + <Navigator.Screen path="/child"> + <p>This is the child screen.</p> + <Navigator.BackButton>Go back</Navigator.BackButton> + </Navigator.Screen> + </Navigator> +); +``` + +### Hierarchical `path`s + +`Navigator` assumes that screens are organized hierarchically according to their `path`, which should follow a URL-like scheme where each path segment starts with and is separated by the `/` character. + +`Navigator` will treat "back" navigations as going to the parent screen — it is, therefore, the responsibility of the consumer of the component to create the correct screen hierarchy. + +For example: + +- `/` is the root of all paths. There should always be a screen with `path="/"`; +- `/parent/child` is a child of `/parent`; +- `/parent/child/grand-child` is a child of `/parent/child`; +- `/parent/:param` is a child of `/parent` as well; +- if the current screen has a `path="/parent/child/grand-child"`, when going "back" `Navigator` will try to recursively navigate the path hierarchy until a matching screen (or the root `/`) is found. + +### Height and animations + +Due to how `Navigator.Screen` animations work, it is recommended that the `Navigator` component is assigned a `height` to prevent some potential UI jumps while moving across screens. + +### Individual components + +`Navigator` is comprised of four individual components: + +- `Navigator`: a wrapper component and context provider. It holds the main logic for hiding and showing screens. +- `Navigator.Screen`: represents a single view/screen/panel; +- `Navigator.Button`: renders a button that allows navigating to a different `Navigator.Screen`; +- `Navigator.BackButton`: renders a button that allows navigating to the parent `Navigator.Screen` (see the section above about hierarchical paths). + +For advanced usages, consumers can use the `useNavigator` hook. + +#### `Navigator` + +##### Props + +###### `initialPath`: `string` + +The initial active path. + +- Required: Yes + +###### `children`: `string` + +The children elements. + +- Required: Yes + +#### `Navigator.Screen` + +###### `path`: `string` + +The screen's path, matched against the current path stored in the navigator. + +`Navigator` assumes that screens are organized hierarchically according to their `path`, which should follow a URL-like scheme where each path segment starts with and is separated by the `/` character. + +`Navigator` will treat "back" navigations as going to the parent screen — it is, therefore, the responsibility of the consumer of the component to create the correct screen hierarchy. + +For example: + +- `/` is the root of all paths. There should always be a screen with `path="/"`. +- `/parent/child` is a child of `/parent`. +- `/parent/child/grand-child` is a child of `/parent/child`. +- `/parent/:param` is a child of `/parent` as well. +- if the current screen has a `path` with value `/parent/child/grand-child`, when going "back" `Navigator` will try to recursively navigate the path hierarchy until a matching screen (or the root `/`) is found. + +- Required: Yes + +###### `children`: `string` + +The children elements. + +- Required: Yes + +##### `Navigator.Button` + +###### `path`: `string` + +The path of the screen to navigate to. The value of this prop needs to be [a valid value for an HTML attribute](https://html.spec.whatwg.org/multipage/syntax.html#attributes-2). + +- Required: Yes + +###### `attributeName`: `string` + +The HTML attribute used to identify the `Navigator.Button`, which is used by `Navigator` to restore focus. + +- Required: No +- Default: `id` + +###### `children`: `string` + +The children elements. + +- Required: No + +###### Inherited props + +`Navigator.Button` also inherits all of the [`Button` props](/packages/components/src/button/README.md#props), except for `href` and `target`. + +##### `Navigator.BackButton` + +###### `children`: `string` + +The children elements. + +- Required: No + +###### Inherited props + +`Navigator.BackButton` also inherits all of the [`Button` props](/packages/components/src/button/README.md#props), except for `href` and `target`. + +###### `useNavigator` + +You can retrieve a `navigator` instance by using the `useNavigator` hook. + +The `navigator` instance has a few properties: + +###### `goTo`: `( path: string, options: NavigateOptions ) => void` + +The `goTo` function allows navigating to a given path. The second argument can augment the navigation operations with different options. + +The available options are: + +- `focusTargetSelector`: `string`. An optional property used to specify the CSS selector used to restore focus on the matching element when navigating back; +- `isBack`: `boolean`. An optional property used to specify whether the navigation should be considered as backwards (thus enabling focus restoration when possible, and causing the animation to be backwards too); +- `skipFocus`: `boolean`. An optional property used to opt out of `Navigator`'s focus management, useful when the consumer of the component wants to manage focus themselves; + +###### `goBack`: `( path: string, options: NavigateOptions ) => void` + +The `goBack` function allows navigating to the parent screen. Parent/child navigation only works if the paths you define are hierarchical (see note above). + +When a match is not found, the function will try to recursively navigate the path hierarchy until a matching screen (or the root `/`) is found. + +The available options are the same as for the `goTo` method, except for the `isBack` property, which is not available for the `goBack` method. + +###### `location`: `NavigatorLocation` + +The `location` object represents the current location, and has a few properties: + +- `path`: `string`. The path associated to the location. +- `isBack`: `boolean`. A flag that is `true` when the current location was reached by navigating backwards. +- `isInitial`: `boolean`. A flag that is `true` only for the initial location. + +###### `params`: `Record< string, string | string[] >` + +The parsed record of parameters from the current location. For example if the current screen path is `/product/:productId` and the location is `/product/123`, then `params` will be `{ productId: '123' }`. diff --git a/packages/components/src/navigator/index.tsx b/packages/components/src/navigator/index.tsx new file mode 100644 index 00000000000000..1d9ae95441e01a --- /dev/null +++ b/packages/components/src/navigator/index.tsx @@ -0,0 +1,131 @@ +/** + * Internal dependencies + */ +import { Navigator as TopLevelNavigator } from './navigator/component'; +import { NavigatorScreen } from './navigator-screen/component'; +import { NavigatorButton } from './navigator-button/component'; +import { NavigatorBackButton } from './navigator-back-button/component'; +export { useNavigator } from './use-navigator'; + +/** + * The `Navigator` component allows rendering nested views/panels/menus + * (via the `Navigator.Screen` component) and navigate between them + * (via the `Navigator.Button` and `Navigator.BackButton` components). + * + * ```jsx + * import { Navigator } from '@wordpress/components'; + * + * const MyNavigation = () => ( + * <Navigator initialPath="/"> + * <Navigator.Screen path="/"> + * <p>This is the home screen.</p> + * <Navigator.Button path="/child"> + * Navigate to child screen. + * </Navigator.Button> + * </Navigator.Screen> + * + * <Navigator.Screen path="/child"> + * <p>This is the child screen.</p> + * <Navigator.BackButton> + * Go back + * </Navigator.BackButton> + * </Navigator.Screen> + * </Navigator> + * ); + * ``` + */ +export const Navigator = Object.assign( TopLevelNavigator, { + /** + * The `Navigator.Screen` component represents a single view/screen/panel and + * should be used in combination with the `Navigator`, the `Navigator.Button` + * and the `Navigator.BackButton` components. + * + * @example + * ```jsx + * import { Navigator } from '@wordpress/components'; + * + * const MyNavigation = () => ( + * <Navigator initialPath="/"> + * <Navigator.Screen path="/"> + * <p>This is the home screen.</p> + * <Navigator.Button path="/child"> + * Navigate to child screen. + * </Navigator.Button> + * </Navigator.Screen> + * + * <Navigator.Screen path="/child"> + * <p>This is the child screen.</p> + * <Navigator.BackButton> + * Go back + * </Navigator.BackButton> + * </Navigator.Screen> + * </Navigator> + * ); + * ``` + */ + Screen: Object.assign( NavigatorScreen, { + displayName: 'Navigator.Screen', + } ), + /** + * The `Navigator.Button` component can be used to navigate to a screen and + * should be used in combination with the `Navigator`, the `Navigator.Screen` + * and the `Navigator.BackButton` components. + * + * @example + * ```jsx + * import { Navigator } from '@wordpress/components'; + * + * const MyNavigation = () => ( + * <Navigator initialPath="/"> + * <Navigator.Screen path="/"> + * <p>This is the home screen.</p> + * <Navigator.Button path="/child"> + * Navigate to child screen. + * </Navigator.Button> + * </Navigator.Screen> + * + * <Navigator.Screen path="/child"> + * <p>This is the child screen.</p> + * <Navigator.BackButton> + * Go back + * </Navigator.BackButton> + * </Navigator.Screen> + * </Navigator> + * ); + * ``` + */ + Button: Object.assign( NavigatorButton, { + displayName: 'Navigator.Button', + } ), + /** + * The `Navigator.BackButton` component can be used to navigate to a screen and + * should be used in combination with the `Navigator`, the `Navigator.Screen` + * and the `Navigator.Button` components. + * + * @example + * ```jsx + * import { Navigator } from '@wordpress/components'; + * + * const MyNavigation = () => ( + * <Navigator initialPath="/"> + * <Navigator.Screen path="/"> + * <p>This is the home screen.</p> + * <Navigator.Button path="/child"> + * Navigate to child screen. + * </Navigator.Button> + * </Navigator.Screen> + * + * <Navigator.Screen path="/child"> + * <p>This is the child screen.</p> + * <Navigator.BackButton> + * Go back + * </Navigator.BackButton> + * </Navigator.Screen> + * </Navigator> + * ); + * ``` + */ + BackButton: Object.assign( NavigatorBackButton, { + displayName: 'Navigator.BackButton', + } ), +} ); diff --git a/packages/components/src/navigator/legacy.ts b/packages/components/src/navigator/legacy.ts index 54bc9e13829b16..1caa5380fc049e 100644 --- a/packages/components/src/navigator/legacy.ts +++ b/packages/components/src/navigator/legacy.ts @@ -1,7 +1,7 @@ /** * Internal dependencies */ -import { Navigator as InternalNavigator } from './navigator-provider/component'; +import { Navigator as InternalNavigator } from './navigator/component'; import { NavigatorScreen as InternalNavigatorScreen } from './navigator-screen/component'; import { NavigatorButton as InternalNavigatorButton } from './navigator-button/component'; import { NavigatorBackButton as InternalNavigatorBackButton } from './navigator-back-button/component'; @@ -10,9 +10,8 @@ export { useNavigator } from './use-navigator'; /** * The `NavigatorProvider` component allows rendering nested views/panels/menus - * (via the `NavigatorScreen` component and navigate between these different - * view (via the `NavigatorButton` and `NavigatorBackButton` components or the - * `useNavigator` hook). + * (via the `NavigatorScreen` component and navigate between them + * (via the `NavigatorButton` and `NavigatorBackButton` components). * * ```jsx * import { @@ -48,8 +47,7 @@ export const NavigatorProvider = Object.assign( InternalNavigator, { /** * The `NavigatorScreen` component represents a single view/screen/panel and * should be used in combination with the `NavigatorProvider`, the - * `NavigatorButton` and the `NavigatorBackButton` components (or the `useNavigator` - * hook). + * `NavigatorButton` and the `NavigatorBackButton` components. * * @example * ```jsx @@ -86,7 +84,7 @@ export const NavigatorScreen = Object.assign( InternalNavigatorScreen, { /** * The `NavigatorButton` component can be used to navigate to a screen and should * be used in combination with the `NavigatorProvider`, the `NavigatorScreen` - * and the `NavigatorBackButton` components (or the `useNavigator` hook). + * and the `NavigatorBackButton` components. * * @example * ```jsx @@ -123,8 +121,7 @@ export const NavigatorButton = Object.assign( InternalNavigatorButton, { /** * The `NavigatorBackButton` component can be used to navigate to a screen and * should be used in combination with the `NavigatorProvider`, the - * `NavigatorScreen` and the `NavigatorButton` components (or the `useNavigator` - * hook). + * `NavigatorScreen` and the `NavigatorButton` components. * * @example * ```jsx diff --git a/packages/components/src/navigator/navigator-back-button/README.md b/packages/components/src/navigator/navigator-back-button/README.md deleted file mode 100644 index 01d4221be536e5..00000000000000 --- a/packages/components/src/navigator/navigator-back-button/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# `NavigatorBackButton` - -<div class="callout callout-alert"> -This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. -</div> - -The `NavigatorBackButton` component can be used to navigate to a screen and should be used in combination with the [`NavigatorProvider`](/packages/components/src/navigator/navigator-provider/README.md), the [`NavigatorScreen`](/packages/components/src/navigator/navigator-screen/README.md) and the [`NavigatorButton`](/packages/components/src/navigator/navigator-button/README.md) components (or the `useNavigator` hook). - -## Usage - -Refer to [the `NavigatorProvider` component](/packages/components/src/navigator/navigator-provider/README.md#usage) for a usage example. - -### Inherited props - -`NavigatorBackButton` also inherits all of the [`Button` props](/packages/components/src/button/README.md#props), except for `href` and `target`. diff --git a/packages/components/src/navigator/navigator-back-button/component.tsx b/packages/components/src/navigator/navigator-back-button/component.tsx index 9e8d98a963d25b..b5c4de7df78a85 100644 --- a/packages/components/src/navigator/navigator-back-button/component.tsx +++ b/packages/components/src/navigator/navigator-back-button/component.tsx @@ -23,5 +23,5 @@ function UnconnectedNavigatorBackButton( export const NavigatorBackButton = contextConnect( UnconnectedNavigatorBackButton, - 'NavigatorBackButton' + 'Navigator.BackButton' ); diff --git a/packages/components/src/navigator/navigator-back-button/hook.ts b/packages/components/src/navigator/navigator-back-button/hook.ts index 9ddc095292190a..d6fcd39647bff9 100644 --- a/packages/components/src/navigator/navigator-back-button/hook.ts +++ b/packages/components/src/navigator/navigator-back-button/hook.ts @@ -20,7 +20,7 @@ export function useNavigatorBackButton( as = Button, ...otherProps - } = useContextSystem( props, 'NavigatorBackButton' ); + } = useContextSystem( props, 'Navigator.BackButton' ); const { goBack } = useNavigator(); const handleClick: React.MouseEventHandler< HTMLButtonElement > = diff --git a/packages/components/src/navigator/navigator-button/README.md b/packages/components/src/navigator/navigator-button/README.md deleted file mode 100644 index 72154ec317da44..00000000000000 --- a/packages/components/src/navigator/navigator-button/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# `NavigatorButton` - -<div class="callout callout-alert"> -This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. -</div> - -The `NavigatorButton` component can be used to navigate to a screen and should be used in combination with the [`NavigatorProvider`](/packages/components/src/navigator/navigator-provider/README.md), the [`NavigatorScreen`](/packages/components/src/navigator/navigator-screen/README.md) and the [`NavigatorBackButton`](/packages/components/src/navigator/navigator-back-button/README.md) components (or the `useNavigator` hook). - -## Usage - -Refer to [the `NavigatorProvider` component](/packages/components/src/navigator/navigator-provider/README.md#usage) for a usage example. - -## Props - -The component accepts the following props: - -### `attributeName`: `string` - -The HTML attribute used to identify the `NavigatorButton`, which is used by `Navigator` to restore focus. - -- Required: No -- Default: `id` - -### `onClick`: `React.MouseEventHandler< HTMLElement >` - -The callback called in response to a `click` event. - -- Required: No - -### `path`: `string` - -The path of the screen to navigate to. The value of this prop needs to be [a valid value for an HTML attribute](https://html.spec.whatwg.org/multipage/syntax.html#attributes-2). - -- Required: Yes - -### Inherited props - -`NavigatorButton` also inherits all of the [`Button` props](/packages/components/src/button/README.md#props), except for `href` and `target`. diff --git a/packages/components/src/navigator/navigator-button/component.tsx b/packages/components/src/navigator/navigator-button/component.tsx index 7c14c8108e82c4..a6dc7963376723 100644 --- a/packages/components/src/navigator/navigator-button/component.tsx +++ b/packages/components/src/navigator/navigator-button/component.tsx @@ -23,5 +23,5 @@ function UnconnectedNavigatorButton( export const NavigatorButton = contextConnect( UnconnectedNavigatorButton, - 'NavigatorButton' + 'Navigator.Button' ); diff --git a/packages/components/src/navigator/navigator-button/hook.ts b/packages/components/src/navigator/navigator-button/hook.ts index 3e39b05661e1b2..59d2aaa65662d7 100644 --- a/packages/components/src/navigator/navigator-button/hook.ts +++ b/packages/components/src/navigator/navigator-button/hook.ts @@ -25,7 +25,7 @@ export function useNavigatorButton( as = Button, attributeName = 'id', ...otherProps - } = useContextSystem( props, 'NavigatorButton' ); + } = useContextSystem( props, 'Navigator.Button' ); const escapedPath = escapeAttribute( path ); diff --git a/packages/components/src/navigator/navigator-provider/README.md b/packages/components/src/navigator/navigator-provider/README.md deleted file mode 100644 index b9bc8f0c6bcdc9..00000000000000 --- a/packages/components/src/navigator/navigator-provider/README.md +++ /dev/null @@ -1,98 +0,0 @@ -# `NavigatorProvider` - -<div class="callout callout-alert"> -This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. -</div> - -The `NavigatorProvider` component allows rendering nested views/panels/menus (via the [`NavigatorScreen` component](/packages/components/src/navigator/navigator-screen/README.md)) and navigate between these different states (via the [`NavigatorButton`](/packages/components/src/navigator/navigator-button/README.md), [`NavigatorToParentButton`](/packages/components/src/navigator/navigator-to-parent-button/README.md) and [`NavigatorBackButton`](/packages/components/src/navigator/navigator-back-button/README.md) components or the `useNavigator` hook). The Global Styles sidebar is an example of this. - -## Usage - -```jsx -import { - __experimentalNavigatorProvider as NavigatorProvider, - __experimentalNavigatorScreen as NavigatorScreen, - __experimentalNavigatorButton as NavigatorButton, - __experimentalNavigatorBackButton as NavigatorBackButton, -} from '@wordpress/components'; - -const MyNavigation = () => ( - <NavigatorProvider initialPath="/"> - <NavigatorScreen path="/"> - <p>This is the home screen.</p> - <NavigatorButton path="/child"> - Navigate to child screen. - </NavigatorButton> - </NavigatorScreen> - - <NavigatorScreen path="/child"> - <p>This is the child screen.</p> - <NavigatorBackButton>Go back</NavigatorBackButton> - </NavigatorScreen> - </NavigatorProvider> -); -``` - -### Hierarchical `path`s - -`Navigator` assumes that screens are organized hierarchically according to their `path`, which should follow a URL-like scheme where each path segment starts with and is separated by the `/` character. - -`Navigator` will treat "back" navigations as going to the parent screen — it is therefore responsibility of the consumer of the component to create the correct screen hierarchy. - -For example: - -- `/` is the root of all paths. There should always be a screen with `path="/"`. -- `/parent/child` is a child of `/parent`. -- `/parent/child/grand-child` is a child of `/parent/child`. -- `/parent/:param` is a child of `/parent` as well. -- if the current screen has a `path` with value `/parent/child/grand-child`, when going "back" `Navigator` will try to recursively navigate the path hierarchy until a matching screen (or the root `/`) is found. - -### Height and animations - -Due to how `NavigatorScreen` animations work, it is recommended that the `NavigatorProvider` component is assigned a `height` to prevent some potential UI jumps while moving across screens. - -## Props - -The component accepts the following props: - -### `initialPath`: `string` - -The initial active path. - -- Required: No - -## The `navigator` object - -You can retrieve a `navigator` instance by using the `useNavigator` hook. - -The `navigator` instance has a few properties: - -### `goTo`: `( path: string, options: NavigateOptions ) => void` - -The `goTo` function allows navigating to a given path. The second argument can augment the navigation operations with different options. - -The available options are: - -- `focusTargetSelector`: `string`. An optional property used to specify the CSS selector used to restore focus on the matching element when navigating back; -- `isBack`: `boolean`. An optional property used to specify whether the navigation should be considered as backwards (thus enabling focus restoration when possible, and causing the animation to be backwards too); -- `skipFocus`: `boolean`. An optional property used to opt out of `Navigator`'s focus management, useful when the consumer of the component wants to manage focus themselves; - -### `goBack`: `( path: string, options: NavigateOptions ) => void` - -The `goBack` function allows navigating to the parent screen. Parent/child navigation only works if the paths you define are hierarchical (see note above). - -When a match is not found, the function will try to recursively navigate the path hierarchy until a matching screen (or the root `/`) are found. - -The available options are the same as for the `goTo` method, except for the `isBack` property, which is not available for the `goBack` method. - -### `location`: `NavigatorLocation` - -The `location` object represent the current location, and has a few properties: - -- `path`: `string`. The path associated to the location. -- `isBack`: `boolean`. A flag that is `true` when the current location was reached by navigating backwards. -- `isInitial`: `boolean`. A flag that is `true` only for the initial location. - -### `params`: `Record< string, string | string[] >` - -The parsed record of parameters from the current location. For example if the current screen path is `/product/:productId` and the location is `/product/123`, then `params` will be `{ productId: '123' }`. diff --git a/packages/components/src/navigator/navigator-screen/README.md b/packages/components/src/navigator/navigator-screen/README.md deleted file mode 100644 index 583da461cd3c27..00000000000000 --- a/packages/components/src/navigator/navigator-screen/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# `NavigatorScreen` - -<div class="callout callout-alert"> -This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. -</div> - -The `NavigatorScreen` component represents a single view/screen/panel and should be used in combination with the [`NavigatorProvider`](/packages/components/src/navigator/navigator-provider/README.md), the [`NavigatorButton`](/packages/components/src/navigator/navigator-button/README.md) and the [`NavigatorBackButton`](/packages/components/src/navigator/navigator-back-button/README.md) components (or the `useNavigator` hook). - -## Usage - -Refer to [the `NavigatorProvider` component](/packages/components/src/navigator/navigator-provider/README.md#usage) for a usage example. - -## Props - -The component accepts the following props: - -### `path`: `string` - -The screen"s path, matched against the current path stored in the navigator. - -`Navigator` assumes that screens are organized hierarchically according to their `path`, which should follow a URL-like scheme where each path segment starts with and is separated by the `/` character. - -`Navigator` will treat "back" navigations as going to the parent screen — it is therefore responsibility of the consumer of the component to create the correct screen hierarchy. - -For example: - -- `/` is the root of all paths. There should always be a screen with `path="/"`. -- `/parent/child` is a child of `/parent`. -- `/parent/child/grand-child` is a child of `/parent/child`. -- `/parent/:param` is a child of `/parent` as well. -- if the current screen has a `path` with value `/parent/child/grand-child`, when going "back" `Navigator` will try to recursively navigate the path hierarchy until a matching screen (or the root `/`) is found. - -- Required: Yes diff --git a/packages/components/src/navigator/navigator-screen/component.tsx b/packages/components/src/navigator/navigator-screen/component.tsx index 16cc0df24e35dd..fe0d81b90a17be 100644 --- a/packages/components/src/navigator/navigator-screen/component.tsx +++ b/packages/components/src/navigator/navigator-screen/component.tsx @@ -36,7 +36,7 @@ function UnconnectedNavigatorScreen( ) { if ( ! /^\//.test( props.path ) ) { warning( - 'wp.components.NavigatorScreen: the `path` should follow a URL-like scheme; it should start with and be separated by the `/` character.' + 'wp.components.Navigator.Screen: the `path` should follow a URL-like scheme; it should start with and be separated by the `/` character.' ); } @@ -48,7 +48,7 @@ function UnconnectedNavigatorScreen( path, onAnimationEnd: onAnimationEndProp, ...otherProps - } = useContextSystem( props, 'NavigatorScreen' ); + } = useContextSystem( props, 'Navigator.Screen' ); const { location, match, addScreen, removeScreen } = useContext( NavigatorContext ); @@ -155,5 +155,5 @@ function UnconnectedNavigatorScreen( export const NavigatorScreen = contextConnect( UnconnectedNavigatorScreen, - 'NavigatorScreen' + 'Navigator.Screen' ); diff --git a/packages/components/src/navigator/navigator-to-parent-button/README.md b/packages/components/src/navigator/navigator-to-parent-button/README.md deleted file mode 100644 index 0100ea9b8d2e1f..00000000000000 --- a/packages/components/src/navigator/navigator-to-parent-button/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# `NavigatorToParentButton` - -<div class="callout callout-alert"> -This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. -</div> - -This component is deprecated. Please use the [`NavigatorBackButton`](/packages/components/src/navigator/navigator-back-button/README.md) component instead. - -The `NavigatorToParentButton` component can be used to navigate to a screen and should be used in combination with the [`NavigatorProvider`](/packages/components/src/navigator/navigator-provider/README.md), the [`NavigatorScreen`](/packages/components/src/navigator/navigator-screen/README.md) and the [`NavigatorButton`](/packages/components/src/navigator/navigator-button/README.md) components (or the `useNavigator` hook). - -## Usage - -Refer to [the `NavigatorProvider` component](/packages/components/src/navigator/navigator-provider/README.md#usage) for a usage example. - -### Inherited props - -`NavigatorToParentButton` also inherits all of the [`Button` props](/packages/components/src/button/README.md#props), except for `href` and `target`. diff --git a/packages/components/src/navigator/navigator-to-parent-button/component.tsx b/packages/components/src/navigator/navigator-to-parent-button/component.tsx index 161370a4323f48..f1c2d27e2284a1 100644 --- a/packages/components/src/navigator/navigator-to-parent-button/component.tsx +++ b/packages/components/src/navigator/navigator-to-parent-button/component.tsx @@ -17,13 +17,16 @@ function UnconnectedNavigatorToParentButton( ) { deprecated( 'wp.components.NavigatorToParentButton', { since: '6.7', - alternative: 'wp.components.NavigatorBackButton', + alternative: 'wp.components.Navigator.BackButton', } ); return <NavigatorBackButton ref={ forwardedRef } { ...props } />; } +/** + * @deprecated + */ export const NavigatorToParentButton = contextConnect( UnconnectedNavigatorToParentButton, - 'NavigatorToParentButton' + 'Navigator.ToParentButton' ); diff --git a/packages/components/src/navigator/navigator-provider/component.tsx b/packages/components/src/navigator/navigator/component.tsx similarity index 84% rename from packages/components/src/navigator/navigator-provider/component.tsx rename to packages/components/src/navigator/navigator/component.tsx index 604034a9525577..bd49b3682fb144 100644 --- a/packages/components/src/navigator/navigator-provider/component.tsx +++ b/packages/components/src/navigator/navigator/component.tsx @@ -222,7 +222,7 @@ function UnconnectedNavigator( children, className, ...otherProps - } = useContextSystem( props, 'NavigatorProvider' ); + } = useContextSystem( props, 'Navigator' ); const [ routerState, dispatch ] = useReducer( routerReducer, @@ -275,7 +275,7 @@ function UnconnectedNavigator( const cx = useCx(); const classes = useMemo( - () => cx( styles.navigatorProviderWrapper, className ), + () => cx( styles.navigatorWrapper, className ), [ className, cx ] ); @@ -288,42 +288,4 @@ function UnconnectedNavigator( ); } -/** - * The `NavigatorProvider` component allows rendering nested views/panels/menus - * (via the `NavigatorScreen` component and navigate between these different - * view (via the `NavigatorButton` and `NavigatorBackButton` components or the - * `useNavigator` hook). - * - * ```jsx - * import { - * __experimentalNavigatorProvider as NavigatorProvider, - * __experimentalNavigatorScreen as NavigatorScreen, - * __experimentalNavigatorButton as NavigatorButton, - * __experimentalNavigatorBackButton as NavigatorBackButton, - * } from '@wordpress/components'; - * - * const MyNavigation = () => ( - * <NavigatorProvider initialPath="/"> - * <NavigatorScreen path="/"> - * <p>This is the home screen.</p> - * <NavigatorButton path="/child"> - * Navigate to child screen. - * </NavigatorButton> - * </NavigatorScreen> - * - * <NavigatorScreen path="/child"> - * <p>This is the child screen.</p> - * <NavigatorBackButton> - * Go back - * </NavigatorBackButton> - * </NavigatorScreen> - * </NavigatorProvider> - * ); - * ``` - */ -export const Navigator = contextConnect( - UnconnectedNavigator, - 'NavigatorProvider' -); - -export default Navigator; +export const Navigator = contextConnect( UnconnectedNavigator, 'Navigator' ); diff --git a/packages/components/src/navigator/stories/index.story.tsx b/packages/components/src/navigator/stories/index.story.tsx index f703969320ca57..e9e342bb0d2eee 100644 --- a/packages/components/src/navigator/stories/index.story.tsx +++ b/packages/components/src/navigator/stories/index.story.tsx @@ -8,20 +8,20 @@ import type { Meta, StoryObj } from '@storybook/react'; */ import Button from '../../button'; import { VStack } from '../../v-stack'; -import { - NavigatorProvider, - NavigatorScreen, - NavigatorButton, - NavigatorBackButton, - useNavigator, -} from '../legacy'; import { HStack } from '../../h-stack'; - -const meta: Meta< typeof NavigatorProvider > = { - component: NavigatorProvider, - // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - subcomponents: { NavigatorScreen, NavigatorButton, NavigatorBackButton }, - title: 'Components (Experimental)/Navigator', +import { Navigator, useNavigator } from '../'; + +const meta: Meta< typeof Navigator > = { + component: Navigator, + subcomponents: { + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + Screen: Navigator.Screen, + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + Button: Navigator.Button, + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + BackButton: Navigator.BackButton, + }, + title: 'Components/Navigator', argTypes: { as: { control: { type: null } }, children: { control: { type: null } }, @@ -40,10 +40,10 @@ const meta: Meta< typeof NavigatorProvider > = { * detail of the Navigator component. Do not use outside of * its source code. */ - [data-wp-component="NavigatorProvider"] { + [data-wp-component="Navigator"] { height: 250px; } - [data-wp-component="NavigatorScreen"]:not([data-sticky]) { + [data-wp-component="Navigator.Screen"] { padding: 8px; } ` }</style> @@ -55,55 +55,55 @@ const meta: Meta< typeof NavigatorProvider > = { }; export default meta; -export const Default: StoryObj< typeof NavigatorProvider > = { +export const Default: StoryObj< typeof Navigator > = { args: { initialPath: '/', children: ( <> - <NavigatorScreen path="/"> + <Navigator.Screen path="/"> <h2>This is the home screen.</h2> <VStack alignment="left"> - <NavigatorButton variant="primary" path="/child"> + <Navigator.Button variant="primary" path="/child"> Go to child screen. - </NavigatorButton> + </Navigator.Button> - <NavigatorButton variant="primary" path="/product/1"> + <Navigator.Button variant="primary" path="/product/1"> Go to dynamic path screen with id 1. - </NavigatorButton> + </Navigator.Button> - <NavigatorButton variant="primary" path="/product/2"> + <Navigator.Button variant="primary" path="/product/2"> Go to dynamic path screen with id 2. - </NavigatorButton> + </Navigator.Button> </VStack> - </NavigatorScreen> + </Navigator.Screen> - <NavigatorScreen path="/child"> + <Navigator.Screen path="/child"> <h2>This is the child screen.</h2> <HStack spacing={ 2 } alignment="left"> - <NavigatorBackButton variant="secondary"> + <Navigator.BackButton variant="secondary"> Go back - </NavigatorBackButton> + </Navigator.BackButton> - <NavigatorButton + <Navigator.Button variant="primary" path="/child/grandchild" > Go to grand child screen. - </NavigatorButton> + </Navigator.Button> </HStack> - </NavigatorScreen> + </Navigator.Screen> - <NavigatorScreen path="/child/grandchild"> + <Navigator.Screen path="/child/grandchild"> <h2>This is the grand child screen.</h2> - <NavigatorBackButton variant="secondary"> + <Navigator.BackButton variant="secondary"> Go back - </NavigatorBackButton> - </NavigatorScreen> + </Navigator.BackButton> + </Navigator.Screen> - <NavigatorScreen path="/product/:id"> + <Navigator.Screen path="/product/:id"> <DynamicScreen /> - </NavigatorScreen> + </Navigator.Screen> </> ), }, @@ -119,14 +119,14 @@ function DynamicScreen() { This screen can parse params dynamically. The current id is:{ ' ' } { params.id } </p> - <NavigatorBackButton variant="secondary"> + <Navigator.BackButton variant="secondary"> Go back - </NavigatorBackButton> + </Navigator.BackButton> </> ); } -export const WithNestedInitialPath: StoryObj< typeof NavigatorProvider > = { +export const WithNestedInitialPath: StoryObj< typeof Navigator > = { ...Default, args: { ...Default.args, @@ -138,7 +138,7 @@ const NavigatorButtonWithSkipFocus = ( { path, onClick, ...props -}: React.ComponentProps< typeof NavigatorButton > ) => { +}: React.ComponentProps< typeof Navigator.Button > ) => { const { goTo } = useNavigator(); return ( @@ -156,7 +156,7 @@ const NavigatorButtonWithSkipFocus = ( { ); }; -export const SkipFocus: StoryObj< typeof NavigatorProvider > = { +export const SkipFocus: StoryObj< typeof Navigator > = { args: { initialPath: '/', children: ( @@ -170,19 +170,19 @@ export const SkipFocus: StoryObj< typeof NavigatorProvider > = { display: 'contents', } } > - <NavigatorScreen path="/"> + <Navigator.Screen path="/"> <h2>Home screen</h2> - <NavigatorButton variant="primary" path="/child"> + <Navigator.Button variant="primary" path="/child"> Go to child screen. - </NavigatorButton> - </NavigatorScreen> + </Navigator.Button> + </Navigator.Screen> - <NavigatorScreen path="/child"> + <Navigator.Screen path="/child"> <h2>Child screen</h2> - <NavigatorBackButton variant="secondary"> + <Navigator.BackButton variant="secondary"> Go back to home screen - </NavigatorBackButton> - </NavigatorScreen> + </Navigator.BackButton> + </Navigator.Screen> </div> <NavigatorButtonWithSkipFocus path="/child"> diff --git a/packages/components/src/navigator/styles.ts b/packages/components/src/navigator/styles.ts index fd355bf4dd48fb..167d4ac07de3d6 100644 --- a/packages/components/src/navigator/styles.ts +++ b/packages/components/src/navigator/styles.ts @@ -3,7 +3,7 @@ */ import { css, keyframes } from '@emotion/react'; -export const navigatorProviderWrapper = css` +export const navigatorWrapper = css` position: relative; /* Prevents horizontal overflow while animating screen transitions */ overflow-x: clip; diff --git a/packages/components/src/navigator/test/index.tsx b/packages/components/src/navigator/test/index.tsx index 81ffd8d69208d7..cab6e9a4cdadff 100644 --- a/packages/components/src/navigator/test/index.tsx +++ b/packages/components/src/navigator/test/index.tsx @@ -14,14 +14,8 @@ import { useState } from '@wordpress/element'; * Internal dependencies */ import Button from '../../button'; -import { - NavigatorProvider, - NavigatorScreen, - NavigatorButton, - NavigatorBackButton, - NavigatorToParentButton, - useNavigator, -} from '../legacy'; +import { Navigator, useNavigator } from '..'; +import { NavigatorToParentButton } from '../legacy'; import type { NavigateOptions } from '../types'; const INVALID_HTML_ATTRIBUTE = { @@ -76,11 +70,11 @@ function CustomNavigatorButton( { path, onClick, ...props -}: Omit< ComponentPropsWithoutRef< typeof NavigatorButton >, 'onClick' > & { +}: Omit< ComponentPropsWithoutRef< typeof Navigator.Button >, 'onClick' > & { onClick?: CustomTestOnClickHandler; } ) { return ( - <NavigatorButton + <Navigator.Button onClick={ () => { // Used to spy on the values passed to `navigator.goTo`. onClick?.( { type: 'goTo', path } ); @@ -95,7 +89,7 @@ function CustomNavigatorGoToBackButton( { path, onClick, ...props -}: Omit< ComponentPropsWithoutRef< typeof NavigatorButton >, 'onClick' > & { +}: Omit< ComponentPropsWithoutRef< typeof Navigator.Button >, 'onClick' > & { onClick?: CustomTestOnClickHandler; } ) { const { goTo } = useNavigator(); @@ -115,7 +109,7 @@ function CustomNavigatorGoToSkipFocusButton( { path, onClick, ...props -}: Omit< ComponentPropsWithoutRef< typeof NavigatorButton >, 'onClick' > & { +}: Omit< ComponentPropsWithoutRef< typeof Navigator.Button >, 'onClick' > & { onClick?: CustomTestOnClickHandler; } ) { const { goTo } = useNavigator(); @@ -134,11 +128,14 @@ function CustomNavigatorGoToSkipFocusButton( { function CustomNavigatorBackButton( { onClick, ...props -}: Omit< ComponentPropsWithoutRef< typeof NavigatorBackButton >, 'onClick' > & { +}: Omit< + ComponentPropsWithoutRef< typeof Navigator.BackButton >, + 'onClick' +> & { onClick?: CustomTestOnClickHandler; } ) { return ( - <NavigatorBackButton + <Navigator.BackButton onClick={ () => { // Used to spy on the values passed to `navigator.goBack`. onClick?.( { type: 'goBack' } ); @@ -151,7 +148,10 @@ function CustomNavigatorBackButton( { function CustomNavigatorToParentButton( { onClick, ...props -}: Omit< ComponentPropsWithoutRef< typeof NavigatorBackButton >, 'onClick' > & { +}: Omit< + ComponentPropsWithoutRef< typeof Navigator.BackButton >, + 'onClick' +> & { onClick?: CustomTestOnClickHandler; } ) { return ( @@ -194,13 +194,13 @@ const ProductScreen = ( { const { params } = useNavigator(); return ( - <NavigatorScreen path={ PATHS.PRODUCT_PATTERN }> + <Navigator.Screen path={ PATHS.PRODUCT_PATTERN }> <p>{ SCREEN_TEXT.product }</p> <p>Product ID is { params.productId }</p> <CustomNavigatorBackButton onClick={ onBackButtonClick }> { BUTTON_TEXT.back } </CustomNavigatorBackButton> - </NavigatorScreen> + </Navigator.Screen> ); }; @@ -215,8 +215,8 @@ const MyNavigation = ( { const [ outerInputValue, setOuterInputValue ] = useState( '' ); return ( <> - <NavigatorProvider initialPath={ initialPath }> - <NavigatorScreen path={ PATHS.HOME }> + <Navigator initialPath={ initialPath }> + <Navigator.Screen path={ PATHS.HOME }> <p>{ SCREEN_TEXT.home }</p> { /* * A button useful to test focus restoration. This button is the first @@ -254,9 +254,9 @@ const MyNavigation = ( { > { BUTTON_TEXT.toInvalidHtmlPathScreen } </CustomNavigatorButton> - </NavigatorScreen> + </Navigator.Screen> - <NavigatorScreen path={ PATHS.CHILD }> + <Navigator.Screen path={ PATHS.CHILD }> <p>{ SCREEN_TEXT.child }</p> { /* * A button useful to test focus restoration. This button is the first @@ -286,30 +286,30 @@ const MyNavigation = ( { } } value={ innerInputValue } /> - </NavigatorScreen> + </Navigator.Screen> - <NavigatorScreen path={ PATHS.NESTED }> + <Navigator.Screen path={ PATHS.NESTED }> <p>{ SCREEN_TEXT.nested }</p> <CustomNavigatorBackButton onClick={ onNavigatorButtonClick } > { BUTTON_TEXT.back } </CustomNavigatorBackButton> - </NavigatorScreen> + </Navigator.Screen> <ProductScreen onBackButtonClick={ onNavigatorButtonClick } /> - <NavigatorScreen path={ PATHS.INVALID_HTML_ATTRIBUTE }> + <Navigator.Screen path={ PATHS.INVALID_HTML_ATTRIBUTE }> <p>{ SCREEN_TEXT.invalidHtmlPath }</p> <CustomNavigatorBackButton onClick={ onNavigatorButtonClick } > { BUTTON_TEXT.back } </CustomNavigatorBackButton> - </NavigatorScreen> + </Navigator.Screen> - { /* A `NavigatorScreen` with `path={ PATHS.NOT_FOUND }` is purposefully not included. */ } - </NavigatorProvider> + { /* A `Navigator.Screen` with `path={ PATHS.NOT_FOUND }` is purposefully not included. */ } + </Navigator> <label htmlFor="test-input-outer">Outer input</label> <input @@ -334,8 +334,8 @@ const MyHierarchicalNavigation = ( { } ) => { return ( <> - <NavigatorProvider initialPath={ initialPath }> - <NavigatorScreen path={ PATHS.HOME }> + <Navigator initialPath={ initialPath }> + <Navigator.Screen path={ PATHS.HOME }> <p>{ SCREEN_TEXT.home }</p> { /* * A button useful to test focus restoration. This button is the first @@ -349,9 +349,9 @@ const MyHierarchicalNavigation = ( { > { BUTTON_TEXT.toChildScreen } </CustomNavigatorButton> - </NavigatorScreen> + </Navigator.Screen> - <NavigatorScreen path={ PATHS.CHILD }> + <Navigator.Screen path={ PATHS.CHILD }> <p>{ SCREEN_TEXT.child }</p> { /* * A button useful to test focus restoration. This button is the first @@ -370,9 +370,9 @@ const MyHierarchicalNavigation = ( { > { BUTTON_TEXT.back } </CustomNavigatorBackButton> - </NavigatorScreen> + </Navigator.Screen> - <NavigatorScreen path={ PATHS.NESTED }> + <Navigator.Screen path={ PATHS.NESTED }> <p>{ SCREEN_TEXT.nested }</p> <CustomNavigatorBackButton onClick={ onNavigatorButtonClick } @@ -385,14 +385,14 @@ const MyHierarchicalNavigation = ( { > { BUTTON_TEXT.backUsingGoTo } </CustomNavigatorGoToBackButton> - </NavigatorScreen> + </Navigator.Screen> <CustomNavigatorGoToSkipFocusButton path={ PATHS.NESTED } onClick={ onNavigatorButtonClick } > { BUTTON_TEXT.goToWithSkipFocus } </CustomNavigatorGoToSkipFocusButton> - </NavigatorProvider> + </Navigator> </> ); }; @@ -406,8 +406,8 @@ const MyDeprecatedNavigation = ( { } ) => { return ( <> - <NavigatorProvider initialPath={ initialPath }> - <NavigatorScreen path={ PATHS.HOME }> + <Navigator initialPath={ initialPath }> + <Navigator.Screen path={ PATHS.HOME }> <p>{ SCREEN_TEXT.home }</p> { /* * A button useful to test focus restoration. This button is the first @@ -421,9 +421,9 @@ const MyDeprecatedNavigation = ( { > { BUTTON_TEXT.toChildScreen } </CustomNavigatorButton> - </NavigatorScreen> + </Navigator.Screen> - <NavigatorScreen path={ PATHS.CHILD }> + <Navigator.Screen path={ PATHS.CHILD }> <p>{ SCREEN_TEXT.child }</p> { /* * A button useful to test focus restoration. This button is the first @@ -442,17 +442,17 @@ const MyDeprecatedNavigation = ( { > { BUTTON_TEXT.back } </CustomNavigatorToParentButton> - </NavigatorScreen> + </Navigator.Screen> - <NavigatorScreen path={ PATHS.NESTED }> + <Navigator.Screen path={ PATHS.NESTED }> <p>{ SCREEN_TEXT.nested }</p> <CustomNavigatorToParentButtonAlternative onClick={ onNavigatorButtonClick } > { BUTTON_TEXT.back } </CustomNavigatorToParentButtonAlternative> - </NavigatorScreen> - </NavigatorProvider> + </Navigator.Screen> + </Navigator> </> ); }; @@ -643,10 +643,10 @@ describe( 'Navigator', () => { } ); it( 'should warn if the `path` prop does not follow the required format', () => { - render( <NavigatorScreen path="not-valid">Test</NavigatorScreen> ); + render( <Navigator.Screen path="not-valid">Test</Navigator.Screen> ); expect( console ).toHaveWarnedWith( - 'wp.components.NavigatorScreen: the `path` should follow a URL-like scheme; it should start with and be separated by the `/` character.' + 'wp.components.Navigator.Screen: the `path` should follow a URL-like scheme; it should start with and be separated by the `/` character.' ); } ); @@ -880,7 +880,7 @@ describe( 'Navigator', () => { // Rendering `NavigatorToParentButton` logs a deprecation notice expect( console ).toHaveWarnedWith( - 'wp.components.NavigatorToParentButton is deprecated since version 6.7. Please use wp.components.NavigatorBackButton instead.' + 'wp.components.NavigatorToParentButton is deprecated since version 6.7. Please use wp.components.Navigator.BackButton instead.' ); } ); diff --git a/packages/components/src/navigator/types.ts b/packages/components/src/navigator/types.ts index ad26d3f1c9f490..aeb5fd3b12c7fb 100644 --- a/packages/components/src/navigator/types.ts +++ b/packages/components/src/navigator/types.ts @@ -100,6 +100,24 @@ export type NavigatorProps = { export type NavigatorScreenProps = { /** * The screen's path, matched against the current path stored in the navigator. + * + * `Navigator` assumes that screens are organized hierarchically according + * to their `path`, which should follow a URL-like scheme where each path + * segment starts with and is separated by the `/` character. + * + * `Navigator` will treat "back" navigations as going to the parent screen — + * it is, therefore, the responsibility of the consumer of the component to + * create the correct screen hierarchy. + * + * For example: + * - `/` is the root of all paths. There should always be a screen with + * `path="/"`; + * - `/parent/child` is a child of `/parent`; + * - `/parent/child/grand-child` is a child of `/parent/child`; + * - `/parent/:param` is a child of `/parent` as well; + * - if the current screen has a `path="/parent/child/grand-child"`, when + * going "back" `Navigator` will try to recursively navigate the path + * hierarchy until a matching screen (or the root `/`) is found. */ path: string; /** diff --git a/packages/components/src/navigator/use-navigator.ts b/packages/components/src/navigator/use-navigator.ts index 7ac35d73150d32..1ea99f3f1c857d 100644 --- a/packages/components/src/navigator/use-navigator.ts +++ b/packages/components/src/navigator/use-navigator.ts @@ -10,7 +10,10 @@ import { NavigatorContext } from './context'; import type { Navigator } from './types'; /** - * Retrieves a `navigator` instance. + * Retrieves a `navigator` instance. This hook provides advanced functionality, + * such as imperatively navigating to a new location (with options like + * navigating back or skipping focus restoration) and accessing the current + * location and path parameters. */ export function useNavigator(): Navigator { const { location, params, goTo, goBack, goToParent } = diff --git a/storybook/manager-head.html b/storybook/manager-head.html index f3eaef13509218..8525e48fffa585 100644 --- a/storybook/manager-head.html +++ b/storybook/manager-head.html @@ -7,6 +7,7 @@ 'customselectcontrol-v2', 'dimensioncontrol', 'navigation', + 'navigator', 'progressbar', 'theme', ]; From 85ec9d0d740104462adc4a159c6938acba02d8ca Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Fri, 27 Sep 2024 16:29:07 +0100 Subject: [PATCH 1005/1908] Update icon in home button (#65497) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: paaljoachim <paaljoachim@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- packages/edit-site/src/components/editor/index.js | 4 ++-- packages/edit-site/src/components/editor/style.scss | 4 ++++ packages/icons/CHANGELOG.md | 1 + packages/icons/src/index.js | 2 ++ packages/icons/src/library/arrow-down-right.js | 12 ++++++++++++ packages/icons/src/library/arrow-up-left.js | 12 ++++++++++++ 6 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 packages/icons/src/library/arrow-down-right.js create mode 100644 packages/icons/src/library/arrow-up-left.js diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 72f796845c567e..855225081236c8 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -22,7 +22,7 @@ import { store as noticesStore } from '@wordpress/notices'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { store as preferencesStore } from '@wordpress/preferences'; import { decodeEntities } from '@wordpress/html-entities'; -import { Icon, homeButton } from '@wordpress/icons'; +import { Icon, arrowUpLeft } from '@wordpress/icons'; /** * Internal dependencies @@ -291,7 +291,7 @@ export default function EditSiteEditor( { isPostsList = false } ) { ) } variants={ toggleHomeIconVariants } > - <Icon icon={ homeButton } /> + <Icon icon={ arrowUpLeft } /> </motion.div> </motion.div> ) diff --git a/packages/edit-site/src/components/editor/style.scss b/packages/edit-site/src/components/editor/style.scss index 10efff92af6434..a6cc5084966947 100644 --- a/packages/edit-site/src/components/editor/style.scss +++ b/packages/edit-site/src/components/editor/style.scss @@ -69,6 +69,10 @@ background-color: hsla(0, 0%, 80%); pointer-events: none; + svg { + fill: currentColor; + } + &.has-site-icon { background-color: hsla(0, 0%, 100%, 0.6); -webkit-backdrop-filter: saturate(180%) blur(15px); diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index 08c7ab95b4b4a1..ddf850dd116819 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -9,6 +9,7 @@ - Add new `envelope` icon. - Add new `bell` and `bell-unread` icons. +- Add new `arrowUpLeft` and `arrowDownRight` icons. ## 10.7.0 (2024-09-05) diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index e61be2cc86bcd3..586911ffc746b2 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -10,9 +10,11 @@ export { default as alignNone } from './library/align-none'; export { default as alignRight } from './library/align-right'; export { default as archive } from './library/archive'; export { default as arrowDown } from './library/arrow-down'; +export { default as arrowDownRight } from './library/arrow-down-right'; export { default as arrowLeft } from './library/arrow-left'; export { default as arrowRight } from './library/arrow-right'; export { default as arrowUp } from './library/arrow-up'; +export { default as arrowUpLeft } from './library/arrow-up-left'; export { default as atSymbol } from './library/at-symbol'; export { default as aspectRatio } from './library/aspect-ratio'; export { default as audio } from './library/audio'; diff --git a/packages/icons/src/library/arrow-down-right.js b/packages/icons/src/library/arrow-down-right.js new file mode 100644 index 00000000000000..3755b63873cefc --- /dev/null +++ b/packages/icons/src/library/arrow-down-right.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const arrowDownRight = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M10 18h8v-8h-1.5v5.5L7 6 6 7l9.5 9.5H10V18Z" /> + </SVG> +); + +export default arrowDownRight; diff --git a/packages/icons/src/library/arrow-up-left.js b/packages/icons/src/library/arrow-up-left.js new file mode 100644 index 00000000000000..1b3686f6ec1e62 --- /dev/null +++ b/packages/icons/src/library/arrow-up-left.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const arrowUpLeft = ( + <SVG width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"> + <Path d="M14 6H6v8h1.5V8.5L17 18l1-1-9.5-9.5H14V6Z" /> + </SVG> +); + +export default arrowUpLeft; From 03d93b4624a42d795da71317ed731396e19acdd2 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Fri, 27 Sep 2024 20:05:01 +0200 Subject: [PATCH 1006/1908] Block Bindings: Refactor e2e tests (#65526) * WIP: Add script to block bindings tests * Add first version of block bindings test theme * Register movie CPT * Create structure for tests * Remove current specs * Share data between server and client * Add `getValues` tests * Move checks for paragraph locking * Wrap tests that should lock editing * Add setValues e2e tests * Add tests for `getFieldsList` * Add tests for rich text workflows * Add remaining use cases * Use one complete source * Add tests for CPT template * Fix label test * Add attributes panel tests * Add dropdown post meta tests * Add post meta tests for custom templates * Add e2e tests in movie post * Add template for posts * Rename specs * Fix post-meta tests * Check post meta in the frontend * Update theme definition * Populate `setValues` * Check image title locking Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- packages/e2e-tests/plugins/block-bindings.php | 133 +- .../e2e-tests/plugins/block-bindings/index.js | 55 + .../editor/various/block-bindings.spec.js | 2451 ----------------- .../block-bindings/custom-sources.spec.js | 1204 ++++++++ .../various/block-bindings/post-meta.spec.js | 551 ++++ .../block-bindings/index.php | 9 + .../block-bindings/style.css | 15 + .../templates/custom-template.html | 3 + .../block-bindings/templates/index.html | 8 + .../templates/single-movie.html | 2 + .../block-bindings/templates/single.html | 2 + .../block-bindings/theme.json | 18 + 12 files changed, 1979 insertions(+), 2472 deletions(-) create mode 100644 packages/e2e-tests/plugins/block-bindings/index.js delete mode 100644 test/e2e/specs/editor/various/block-bindings.spec.js create mode 100644 test/e2e/specs/editor/various/block-bindings/custom-sources.spec.js create mode 100644 test/e2e/specs/editor/various/block-bindings/post-meta.spec.js create mode 100644 test/gutenberg-test-themes/block-bindings/index.php create mode 100644 test/gutenberg-test-themes/block-bindings/style.css create mode 100644 test/gutenberg-test-themes/block-bindings/templates/custom-template.html create mode 100644 test/gutenberg-test-themes/block-bindings/templates/index.html create mode 100644 test/gutenberg-test-themes/block-bindings/templates/single-movie.html create mode 100644 test/gutenberg-test-themes/block-bindings/templates/single.html create mode 100644 test/gutenberg-test-themes/block-bindings/theme.json diff --git a/packages/e2e-tests/plugins/block-bindings.php b/packages/e2e-tests/plugins/block-bindings.php index 0629a397286023..ffbe50ab3cc902 100644 --- a/packages/e2e-tests/plugins/block-bindings.php +++ b/packages/e2e-tests/plugins/block-bindings.php @@ -8,67 +8,158 @@ */ /** -* Register custom fields and custom block bindings sources. -*/ + * Code necessary for testing block bindings: + * - Enqueues a custom script to register sources in the client. + * - Registers sources in the server. + * - Registers a custom post type and custom fields. + */ function gutenberg_test_block_bindings_registration() { + // Define fields list. + $upload_dir = wp_upload_dir(); + $testing_url = $upload_dir['url'] . '/1024x768_e2e_test_image_size.jpeg'; + $fields_list = array( + 'text_field' => array( + 'label' => 'Text Field Label', + 'value' => 'Text Field Value', + ), + 'url_field' => array( + 'label' => 'URL Field Label', + 'value' => $testing_url, + ), + 'empty_field' => array( + 'label' => 'Empty Field Label', + 'value' => '', + ), + ); + + // Enqueue a custom script for the plugin. + wp_enqueue_script( + 'gutenberg-test-block-bindings', + plugins_url( 'block-bindings/index.js', __FILE__ ), + array( + 'wp-blocks', + 'wp-private-apis', + ), + filemtime( plugin_dir_path( __FILE__ ) . 'block-bindings/index.js' ), + true + ); + + // Pass data to the script. + wp_localize_script( + 'gutenberg-test-block-bindings', + 'testingBindings', + array( + 'fieldsList' => $fields_list, + ) + ); + // Register custom block bindings sources. register_block_bindings_source( - 'core/server-source', + 'testing/complete-source', + array( + 'label' => 'Complete Source', + 'get_value_callback' => function ( $source_args ) use ( $fields_list ) { + if ( ! isset( $source_args['key'] ) || ! isset( $fields_list[ $source_args['key'] ] ) ) { + return null; + } + return $fields_list[ $source_args['key'] ]['value']; }, + ) + ); + register_block_bindings_source( + 'testing/server-only-source', array( 'label' => 'Server Source', 'get_value_callback' => function () {}, ) ); - // Register custom fields. + // Register "movie" custom post type. + register_post_type( + 'movie', + array( + 'label' => 'Movie', + 'public' => true, + 'supports' => array( 'title', 'editor', 'comments', 'revisions', 'trackbacks', 'author', 'excerpt', 'page-attributes', 'thumbnail', 'custom-fields', 'post-formats' ), + 'has_archive' => true, + 'show_in_rest' => true, + ) + ); + + // Register global custom fields. register_meta( 'post', 'text_custom_field', array( + 'default' => 'Value of the text custom field', 'show_in_rest' => true, - 'type' => 'string', 'single' => true, - 'default' => 'Value of the text custom field', + 'type' => 'string', ) ); register_meta( 'post', 'url_custom_field', array( + 'default' => '#url-custom-field', 'show_in_rest' => true, - 'type' => 'string', 'single' => true, - 'default' => '#url-custom-field', + 'type' => 'string', ) ); + // Register CPT custom fields. register_meta( 'post', - 'empty_field', + 'movie_field', array( - 'show_in_rest' => true, - 'type' => 'string', - 'single' => true, - 'default' => '', + 'label' => 'Movie field label', + 'default' => 'Movie field default value', + 'object_subtype' => 'movie', + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + ) + ); + register_meta( + 'post', + 'field_with_only_label', + array( + 'label' => 'Field with only label', + 'object_subtype' => 'movie', + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + ) + ); + register_meta( + 'post', + 'field_without_label_or_default', + array( + 'object_subtype' => 'movie', + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', ) ); register_meta( 'post', '_protected_field', array( - 'type' => 'string', - 'show_in_rest' => true, - 'single' => true, - 'default' => 'protected field value', + 'default' => 'Protected field value', + 'object_subtype' => 'movie', + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', ) ); register_meta( 'post', 'show_in_rest_false_field', array( - 'show_in_rest' => false, - 'type' => 'string', - 'single' => true, - 'default' => 'show_in_rest false field value', + 'default' => 'show_in_rest false field value', + 'object_subtype' => 'movie', + 'show_in_rest' => false, + 'single' => true, + 'type' => 'string', ) ); } diff --git a/packages/e2e-tests/plugins/block-bindings/index.js b/packages/e2e-tests/plugins/block-bindings/index.js new file mode 100644 index 00000000000000..dfdc706b69c64d --- /dev/null +++ b/packages/e2e-tests/plugins/block-bindings/index.js @@ -0,0 +1,55 @@ +const { unlock } = + wp.privateApis.__dangerousOptInToUnstableAPIsOnlyForCoreModules( + 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', + '@wordpress/blocks' + ); + +const { registerBlockBindingsSource } = unlock( wp.blocks.privateApis ); +const { fieldsList } = window.testingBindings || {}; + +const getValues = ( { bindings } ) => { + const newValues = {}; + for ( const [ attributeName, source ] of Object.entries( bindings ) ) { + newValues[ attributeName ] = fieldsList[ source.args.key ]?.value; + } + return newValues; +}; +const setValues = ( { registry, bindings } ) => { + Object.values( bindings ).forEach( ( { args, newValue } ) => { + // Example of what could be done. + registry.dispatch( 'core' ).editEntityRecord( 'postType', 'post', 1, { + meta: { [ args?.key ]: newValue }, + } ); + } ); +}; + +registerBlockBindingsSource( { + name: 'testing/complete-source', + label: 'Complete Source', + getValues, + setValues, + canUserEditValue: () => true, + getFieldsList: () => fieldsList, +} ); + +registerBlockBindingsSource( { + name: 'testing/can-user-edit-false', + label: 'Can User Edit: False', + getValues, + setValues, + canUserEditValue: () => false, +} ); + +registerBlockBindingsSource( { + name: 'testing/can-user-edit-undefined', + label: 'Can User Edit: Undefined', + getValues, + setValues, +} ); + +registerBlockBindingsSource( { + name: 'testing/set-values-undefined', + label: 'Set Values: Undefined', + getValues, + canUserEditValue: () => true, +} ); diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js deleted file mode 100644 index f172a424bb1729..00000000000000 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ /dev/null @@ -1,2451 +0,0 @@ -/** - * External dependencies - */ -const path = require( 'path' ); -/** - * WordPress dependencies - */ -const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); - -test.describe( 'Block bindings', () => { - let imagePlaceholderSrc; - let imageCustomFieldSrc; - test.beforeAll( async ( { requestUtils } ) => { - await requestUtils.activateTheme( 'emptytheme' ); - await requestUtils.activatePlugin( 'gutenberg-test-block-bindings' ); - await requestUtils.deleteAllMedia(); - const placeholderMedia = await requestUtils.uploadMedia( - path.join( './test/e2e/assets', '10x10_e2e_test_image_z9T8jK.png' ) - ); - imagePlaceholderSrc = placeholderMedia.source_url; - } ); - - test.afterEach( async ( { requestUtils } ) => { - await requestUtils.deleteAllPosts(); - } ); - - test.afterAll( async ( { requestUtils } ) => { - await requestUtils.deleteAllMedia(); - await requestUtils.activateTheme( 'twentytwentyone' ); - await requestUtils.deactivatePlugin( 'gutenberg-test-block-bindings' ); - } ); - - test.describe( 'Template context', () => { - test.beforeEach( async ( { admin, editor } ) => { - await admin.visitSiteEditor( { - postId: 'emptytheme//index', - postType: 'wp_template', - canvas: 'edit', - } ); - await editor.openDocumentSettingsSidebar(); - } ); - - test.describe( 'Paragraph', () => { - test( 'should show the key of the custom field in post meta', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - content: 'paragraph default content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - await expect( paragraphBlock ).toHaveText( - 'text_custom_field' - ); - } ); - - test( 'should always show the source label in server-only sources', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - content: 'paragraph default content', - metadata: { - bindings: { - content: { - source: 'core/server-source', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - await expect( paragraphBlock ).toHaveText( 'Server Source' ); - } ); - - test( 'should lock the appropriate controls with a registered source', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - content: 'paragraph default content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - await paragraphBlock.click(); - - // Alignment controls exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Align text' } ) - ).toBeVisible(); - - // Format controls don't exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Bold', - } ) - ).toBeHidden(); - - // Paragraph is not editable. - await expect( paragraphBlock ).toHaveAttribute( - 'contenteditable', - 'false' - ); - } ); - - test( 'should lock the appropriate controls when source is not defined', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - content: 'paragraph default content', - metadata: { - bindings: { - content: { - source: 'plugin/undefined-source', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - await paragraphBlock.click(); - - // Alignment controls exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Align text' } ) - ).toBeVisible(); - - // Format controls don't exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Bold', - } ) - ).toBeHidden(); - - // Paragraph is not editable. - await expect( paragraphBlock ).toHaveAttribute( - 'contenteditable', - 'false' - ); - } ); - } ); - - test.describe( 'Heading', () => { - test( 'should show the key of the custom field', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/heading', - attributes: { - content: 'heading default content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const headingBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Heading', - } ); - await expect( headingBlock ).toHaveText( 'text_custom_field' ); - } ); - - test( 'should lock the appropriate controls with a registered source', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/heading', - attributes: { - content: 'heading default content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const headingBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Heading', - } ); - await headingBlock.click(); - - // Alignment controls exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Align text' } ) - ).toBeVisible(); - - // Format controls don't exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Bold', - } ) - ).toBeHidden(); - - // Heading is not editable. - await expect( headingBlock ).toHaveAttribute( - 'contenteditable', - 'false' - ); - } ); - - test( 'should lock the appropriate controls when source is not defined', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/heading', - attributes: { - content: 'heading default content', - metadata: { - bindings: { - content: { - source: 'plugin/undefined-source', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const headingBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Heading', - } ); - await headingBlock.click(); - - // Alignment controls exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Align text' } ) - ).toBeVisible(); - - // Format controls don't exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Bold', - } ) - ).toBeHidden(); - - // Heading is not editable. - await expect( headingBlock ).toHaveAttribute( - 'contenteditable', - 'false' - ); - } ); - } ); - - test.describe( 'Button', () => { - test( 'should show the key of the custom field when text is bound', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/buttons', - innerBlocks: [ - { - name: 'core/button', - attributes: { - text: 'button default text', - url: '#default-url', - metadata: { - bindings: { - text: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - }, - ], - } ); - const buttonBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Button', - exact: true, - } ); - await expect( buttonBlock ).toHaveText( 'text_custom_field' ); - } ); - - test( 'should lock text controls when text is bound to a registered source', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/buttons', - innerBlocks: [ - { - name: 'core/button', - attributes: { - text: 'button default text', - url: '#default-url', - metadata: { - bindings: { - text: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - }, - ], - } ); - const buttonBlock = editor.canvas - .getByRole( 'document', { - name: 'Block: Button', - exact: true, - } ) - .getByRole( 'textbox' ); - await buttonBlock.click(); - - // Alignment controls exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Align text' } ) - ).toBeVisible(); - - // Format controls don't exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Bold', - } ) - ).toBeHidden(); - - // Button is not editable. - await expect( buttonBlock ).toHaveAttribute( - 'contenteditable', - 'false' - ); - - // Link controls exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Unlink' } ) - ).toBeVisible(); - } ); - - test( 'should lock text controls when text is bound to an undefined source', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/buttons', - innerBlocks: [ - { - name: 'core/button', - attributes: { - text: 'button default text', - url: '#default-url', - metadata: { - bindings: { - text: { - source: 'plugin/undefined-source', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - }, - ], - } ); - const buttonBlock = editor.canvas - .getByRole( 'document', { - name: 'Block: Button', - exact: true, - } ) - .getByRole( 'textbox' ); - await buttonBlock.click(); - - // Alignment controls exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Align text' } ) - ).toBeVisible(); - - // Format controls don't exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Bold', - } ) - ).toBeHidden(); - - // Button is not editable. - await expect( buttonBlock ).toHaveAttribute( - 'contenteditable', - 'false' - ); - - // Link controls exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Unlink' } ) - ).toBeVisible(); - } ); - - test( 'should lock url controls when url is bound to a registered source', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/buttons', - innerBlocks: [ - { - name: 'core/button', - attributes: { - text: 'button default text', - url: '#default-url', - metadata: { - bindings: { - url: { - source: 'core/post-meta', - args: { key: 'url_custom_field' }, - }, - }, - }, - }, - }, - ], - } ); - const buttonBlock = editor.canvas - .getByRole( 'document', { - name: 'Block: Button', - exact: true, - } ) - .getByRole( 'textbox' ); - await buttonBlock.click(); - - // Format controls exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Bold', - } ) - ).toBeVisible(); - - // Button is editable. - await expect( buttonBlock ).toHaveAttribute( - 'contenteditable', - 'true' - ); - - // Link controls don't exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Link' } ) - ).toBeHidden(); - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Unlink' } ) - ).toBeHidden(); - } ); - - test( 'should lock url controls when url is bound to an undefined source', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/buttons', - innerBlocks: [ - { - name: 'core/button', - attributes: { - text: 'button default text', - url: '#default-url', - metadata: { - bindings: { - url: { - source: 'plugin/undefined-source', - args: { key: 'url_custom_field' }, - }, - }, - }, - }, - }, - ], - } ); - const buttonBlock = editor.canvas - .getByRole( 'document', { - name: 'Block: Button', - exact: true, - } ) - .getByRole( 'textbox' ); - await buttonBlock.click(); - - // Format controls exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Bold', - } ) - ).toBeVisible(); - - // Button is editable. - await expect( buttonBlock ).toHaveAttribute( - 'contenteditable', - 'true' - ); - - // Link controls don't exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Link' } ) - ).toBeHidden(); - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Unlink' } ) - ).toBeHidden(); - } ); - - test( 'should lock url and text controls when both are bound', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/buttons', - innerBlocks: [ - { - name: 'core/button', - attributes: { - text: 'button default text', - url: '#default-url', - metadata: { - bindings: { - text: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - url: { - source: 'core/post-meta', - args: { key: 'url_custom_field' }, - }, - }, - }, - }, - }, - ], - } ); - const buttonBlock = editor.canvas - .getByRole( 'document', { - name: 'Block: Button', - exact: true, - } ) - .getByRole( 'textbox' ); - await buttonBlock.click(); - - // Alignment controls are visible. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Align text' } ) - ).toBeVisible(); - - // Format controls don't exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Bold', - } ) - ).toBeHidden(); - - // Button is not editable. - await expect( buttonBlock ).toHaveAttribute( - 'contenteditable', - 'false' - ); - - // Link controls don't exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Link' } ) - ).toBeHidden(); - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Unlink' } ) - ).toBeHidden(); - } ); - } ); - - test.describe( 'Image', () => { - test( 'should show the upload form when url is not bound', async ( { - editor, - } ) => { - await editor.insertBlock( { name: 'core/image' } ); - const imageBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Image', - } ); - await imageBlock.click(); - await expect( - imageBlock.getByRole( 'button', { name: 'Upload' } ) - ).toBeVisible(); - } ); - - test( 'should NOT show the upload form when url is bound to a registered source', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/image', - attributes: { - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - metadata: { - bindings: { - url: { - source: 'core/post-meta', - args: { key: 'url_custom_field' }, - }, - }, - }, - }, - } ); - const imageBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Image', - } ); - await imageBlock.click(); - await expect( - imageBlock.getByRole( 'button', { name: 'Upload' } ) - ).toBeHidden(); - } ); - - test( 'should NOT show the upload form when url is bound to an undefined source', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/image', - attributes: { - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - metadata: { - bindings: { - url: { - source: 'plugin/undefined-source', - args: { key: 'url_custom_field' }, - }, - }, - }, - }, - } ); - const imageBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Image', - } ); - await imageBlock.click(); - await expect( - imageBlock.getByRole( 'button', { name: 'Upload' } ) - ).toBeHidden(); - } ); - - test( 'should lock url controls when url is bound to a registered source', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/image', - attributes: { - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - metadata: { - bindings: { - url: { - source: 'core/post-meta', - args: { key: 'url_custom_field' }, - }, - }, - }, - }, - } ); - const imageBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Image', - } ); - await imageBlock.click(); - - // Replace controls don't exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Replace', - } ) - ).toBeHidden(); - - // Image placeholder doesn't show the upload button. - await expect( - imageBlock.getByRole( 'button', { name: 'Upload' } ) - ).toBeHidden(); - - // Alt textarea is enabled and with the original value. - await expect( - page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - ).toBeEnabled(); - const altValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - .inputValue(); - expect( altValue ).toBe( 'default alt value' ); - - // Title input is enabled and with the original value. - await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByRole( 'button', { name: 'Advanced' } ) - .click(); - - await expect( - page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - ).toBeEnabled(); - const titleValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - .inputValue(); - expect( titleValue ).toBe( 'default title value' ); - } ); - - test( 'should lock url controls when url is bound to an undefined source', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/image', - attributes: { - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - metadata: { - bindings: { - url: { - source: 'plugin/undefined-source', - args: { key: 'url_custom_field' }, - }, - }, - }, - }, - } ); - const imageBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Image', - } ); - await imageBlock.click(); - - // Replace controls don't exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Replace', - } ) - ).toBeHidden(); - - // Image placeholder doesn't show the upload button. - await expect( - imageBlock.getByRole( 'button', { name: 'Upload' } ) - ).toBeHidden(); - - // Alt textarea is enabled and with the original value. - await expect( - page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - ).toBeEnabled(); - const altValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - .inputValue(); - expect( altValue ).toBe( 'default alt value' ); - - // Title input is enabled and with the original value. - await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByRole( 'button', { name: 'Advanced' } ) - .click(); - - await expect( - page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - ).toBeEnabled(); - const titleValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - .inputValue(); - expect( titleValue ).toBe( 'default title value' ); - } ); - - test( 'should disable alt textarea when alt is bound to a registered source', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/image', - attributes: { - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - metadata: { - bindings: { - alt: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const imageBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Image', - } ); - await imageBlock.click(); - - // Replace controls exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Replace', - } ) - ).toBeVisible(); - - // Alt textarea is disabled and with the custom field value. - await expect( - page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - ).toHaveAttribute( 'readonly' ); - const altValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - .inputValue(); - expect( altValue ).toBe( 'text_custom_field' ); - - // Title input is enabled and with the original value. - await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByRole( 'button', { name: 'Advanced' } ) - .click(); - await expect( - page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - ).toBeEnabled(); - const titleValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - .inputValue(); - expect( titleValue ).toBe( 'default title value' ); - } ); - - test( 'should disable alt textarea when alt is bound to an undefined source', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/image', - attributes: { - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - metadata: { - bindings: { - alt: { - source: 'plguin/undefined-source', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const imageBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Image', - } ); - await imageBlock.click(); - - // Replace controls exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Replace', - } ) - ).toBeVisible(); - - // Alt textarea is disabled and with the custom field value. - await expect( - page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - ).toHaveAttribute( 'readonly' ); - const altValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - .inputValue(); - expect( altValue ).toBe( 'default alt value' ); - - // Title input is enabled and with the original value. - await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByRole( 'button', { name: 'Advanced' } ) - .click(); - await expect( - page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - ).toBeEnabled(); - const titleValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - .inputValue(); - expect( titleValue ).toBe( 'default title value' ); - } ); - - test( 'should disable title input when title is bound to a registered source', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/image', - attributes: { - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - metadata: { - bindings: { - title: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const imageBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Image', - } ); - await imageBlock.click(); - - // Replace controls exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Replace', - } ) - ).toBeVisible(); - - // Alt textarea is enabled and with the original value. - await expect( - page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - ).toBeEnabled(); - const altValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - .inputValue(); - expect( altValue ).toBe( 'default alt value' ); - - // Title input is disabled and with the custom field value. - await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByRole( 'button', { name: 'Advanced' } ) - .click(); - await expect( - page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - ).toHaveAttribute( 'readonly' ); - const titleValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - .inputValue(); - expect( titleValue ).toBe( 'text_custom_field' ); - } ); - - test( 'should disable title input when title is bound to an undefined source', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/image', - attributes: { - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - metadata: { - bindings: { - title: { - source: 'plugin/undefined-source', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const imageBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Image', - } ); - await imageBlock.click(); - - // Replace controls exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Replace', - } ) - ).toBeVisible(); - - // Alt textarea is enabled and with the original value. - await expect( - page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - ).toBeEnabled(); - const altValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - .inputValue(); - expect( altValue ).toBe( 'default alt value' ); - - // Title input is disabled and with the custom field value. - await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByRole( 'button', { name: 'Advanced' } ) - .click(); - await expect( - page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - ).toHaveAttribute( 'readonly' ); - const titleValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - .inputValue(); - expect( titleValue ).toBe( 'default title value' ); - } ); - - test( 'Multiple bindings should lock the appropriate controls', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/image', - attributes: { - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - metadata: { - bindings: { - url: { - source: 'core/post-meta', - args: { key: 'url_custom_field' }, - }, - alt: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const imageBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Image', - } ); - await imageBlock.click(); - - // Replace controls don't exist. - await expect( - page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Replace', - } ) - ).toBeHidden(); - - // Image placeholder doesn't show the upload button. - await expect( - imageBlock.getByRole( 'button', { name: 'Upload' } ) - ).toBeHidden(); - - // Alt textarea is disabled and with the custom field value. - await expect( - page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - ).toHaveAttribute( 'readonly' ); - const altValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - .inputValue(); - expect( altValue ).toBe( 'text_custom_field' ); - - // Title input is enabled and with the original value. - await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByRole( 'button', { name: 'Advanced' } ) - .click(); - await expect( - page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - ).toBeEnabled(); - const titleValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - .inputValue(); - expect( titleValue ).toBe( 'default title value' ); - } ); - } ); - } ); - - test.describe( 'Post/page context', () => { - test.beforeEach( async ( { admin } ) => { - await admin.createNewPost( { title: 'Test bindings' } ); - } ); - test.describe( 'Paragraph', () => { - test( 'should show the value of the custom field when exists', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - anchor: 'paragraph-binding', - content: 'paragraph default content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - await expect( paragraphBlock ).toHaveText( - 'Value of the text custom field' - ); - - // Check the frontend shows the value of the custom field. - const previewPage = await editor.openPreviewPage(); - await expect( - previewPage.locator( '#paragraph-binding' ) - ).toHaveText( 'Value of the text custom field' ); - } ); - - test( "should show the value of the key when custom field doesn't exist", async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - anchor: 'paragraph-binding', - content: 'fallback value', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'non_existing_custom_field' }, - }, - }, - }, - }, - } ); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - await expect( paragraphBlock ).toHaveText( - 'non_existing_custom_field' - ); - // Paragraph is not editable. - await expect( paragraphBlock ).toHaveAttribute( - 'contenteditable', - 'false' - ); - - // Check the frontend doesn't show the content. - const previewPage = await editor.openPreviewPage(); - await expect( - previewPage.locator( '#paragraph-binding' ) - ).toHaveText( 'fallback value' ); - } ); - - test( 'should prioritize the placeholder attribute over the placeholder generated by the bindings API', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - placeholder: 'My custom placeholder', - content: 'paragraph default content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'empty_field' }, - }, - }, - }, - }, - } ); - - const paragraphBlock = editor.canvas.getByRole( 'document', { - // Aria-label is changed for empty paragraphs. - name: 'Empty empty_field; start writing to edit its value', - } ); - - await expect( paragraphBlock ).toBeEmpty(); - - const placeholder = paragraphBlock.locator( 'span' ); - await expect( placeholder ).toHaveAttribute( - 'data-rich-text-placeholder', - 'My custom placeholder' - ); - } ); - - test( 'should show the prompt placeholder in field with empty value', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - content: 'paragraph default content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'empty_field' }, - }, - }, - }, - }, - } ); - - const paragraphBlock = editor.canvas.getByRole( 'document', { - // Aria-label is changed for empty paragraphs. - name: 'Empty empty_field; start writing to edit its value', - } ); - - await expect( paragraphBlock ).toBeEmpty(); - - const placeholder = paragraphBlock.locator( 'span' ); - await expect( placeholder ).toHaveAttribute( - 'data-rich-text-placeholder', - 'Add empty_field' - ); - } ); - - test( 'should not show the value of a protected meta field', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - anchor: 'paragraph-binding', - content: 'fallback value', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: '_protected_field' }, - }, - }, - }, - }, - } ); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - await expect( paragraphBlock ).toHaveText( '_protected_field' ); - // Check the frontend doesn't show the content. - const previewPage = await editor.openPreviewPage(); - await expect( - previewPage.locator( '#paragraph-binding' ) - ).toHaveText( 'fallback value' ); - } ); - - test( 'should not show the value of a meta field with `show_in_rest` false', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - anchor: 'paragraph-binding', - content: 'fallback value', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'show_in_rest_false_field' }, - }, - }, - }, - }, - } ); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - await expect( paragraphBlock ).toHaveText( - 'show_in_rest_false_field' - ); - // Check the frontend doesn't show the content. - const previewPage = await editor.openPreviewPage(); - await expect( - previewPage.locator( '#paragraph-binding' ) - ).toHaveText( 'fallback value' ); - } ); - - test( 'should add empty paragraph block when pressing enter', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - content: 'paragraph default content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - // Select the paragraph and press Enter at the end of it. - const paragraph = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - await editor.selectBlocks( paragraph ); - await page.keyboard.press( 'End' ); - await page.keyboard.press( 'Enter' ); - const [ initialParagraph, newEmptyParagraph ] = - await editor.canvas - .locator( '[data-type="core/paragraph"]' ) - .all(); - await expect( initialParagraph ).toHaveText( - 'Value of the text custom field' - ); - await expect( newEmptyParagraph ).toHaveText( '' ); - await expect( newEmptyParagraph ).toBeEditable(); - } ); - - test( 'should NOT be possible to edit the value of the custom field when it is protected', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - anchor: 'protected-field-binding', - content: 'fallback value', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: '_protected_field' }, - }, - }, - }, - }, - } ); - - const protectedFieldBlock = editor.canvas.getByRole( - 'document', - { - name: 'Block: Paragraph', - } - ); - - await expect( protectedFieldBlock ).toHaveAttribute( - 'contenteditable', - 'false' - ); - } ); - - test( 'should NOT be possible to edit the value of the custom field when it is not shown in the REST API', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - anchor: 'show-in-rest-false-binding', - content: 'fallback value', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'show_in_rest_false_field' }, - }, - }, - }, - }, - } ); - - const showInRestFalseBlock = editor.canvas.getByRole( - 'document', - { - name: 'Block: Paragraph', - } - ); - - await expect( showInRestFalseBlock ).toHaveAttribute( - 'contenteditable', - 'false' - ); - } ); - test( 'should show a selector for content', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - } ); - await page.getByLabel( 'Attributes options' ).click(); - const contentAttribute = page.getByRole( 'menuitemcheckbox', { - name: 'Show content', - } ); - await expect( contentAttribute ).toBeVisible(); - } ); - test( 'should use a selector to update the content', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - content: 'fallback value', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'undefined_field' }, - }, - }, - }, - }, - } ); - await page.getByRole( 'button', { name: 'content' } ).click(); - - await page - .getByRole( 'menuitemradio' ) - .filter( { hasText: 'text_custom_field' } ) - .click(); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - await expect( paragraphBlock ).toHaveText( - 'Value of the text custom field' - ); - } ); - } ); - - test.describe( 'Heading', () => { - test( 'should show the value of the custom field', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/heading', - attributes: { - anchor: 'heading-binding', - content: 'heading default content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const headingBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Heading', - } ); - await expect( headingBlock ).toHaveText( - 'Value of the text custom field' - ); - - // Check the frontend shows the value of the custom field. - const previewPage = await editor.openPreviewPage(); - await expect( - previewPage.locator( '#heading-binding' ) - ).toHaveText( 'Value of the text custom field' ); - } ); - - test( 'should add empty paragraph block when pressing enter', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/heading', - attributes: { - anchor: 'heading-binding', - content: 'heading default content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - - // Select the heading and press Enter at the end of it. - const heading = editor.canvas.getByRole( 'document', { - name: 'Block: Heading', - } ); - await editor.selectBlocks( heading ); - await page.keyboard.press( 'End' ); - await page.keyboard.press( 'Enter' ); - // Can't use `editor.getBlocks` because it doesn't return the meta value shown in the editor. - const [ initialHeading, newEmptyParagraph ] = - await editor.canvas.locator( '[data-block]' ).all(); - // First block should be the original block. - await expect( initialHeading ).toHaveAttribute( - 'data-type', - 'core/heading' - ); - await expect( initialHeading ).toHaveText( - 'Value of the text custom field' - ); - // Second block should be an empty paragraph block. - await expect( newEmptyParagraph ).toHaveAttribute( - 'data-type', - 'core/paragraph' - ); - await expect( newEmptyParagraph ).toHaveText( '' ); - await expect( newEmptyParagraph ).toBeEditable(); - } ); - test( 'should show a selector for content', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/heading', - } ); - await page.getByLabel( 'Attributes options' ).click(); - const contentAttribute = page.getByRole( 'menuitemcheckbox', { - name: 'Show content', - } ); - await expect( contentAttribute ).toBeVisible(); - } ); - } ); - - test.describe( 'Button', () => { - test( 'should show the value of the custom field when text is bound', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/buttons', - innerBlocks: [ - { - name: 'core/button', - attributes: { - anchor: 'button-text-binding', - text: 'button default text', - url: '#default-url', - metadata: { - bindings: { - text: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - }, - ], - } ); - const buttonBlock = editor.canvas - .getByRole( 'document', { - name: 'Block: Button', - exact: true, - } ) - .getByRole( 'textbox' ); - await buttonBlock.click(); - await expect( buttonBlock ).toHaveText( - 'Value of the text custom field' - ); - - // Check the frontend shows the value of the custom field. - const previewPage = await editor.openPreviewPage(); - const buttonDom = previewPage.locator( - '#button-text-binding a' - ); - await expect( buttonDom ).toHaveText( - 'Value of the text custom field' - ); - await expect( buttonDom ).toHaveAttribute( - 'href', - '#default-url' - ); - } ); - - test( 'should use the value of the custom field when url is bound', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/buttons', - innerBlocks: [ - { - name: 'core/button', - attributes: { - anchor: 'button-url-binding', - text: 'button default text', - url: '#default-url', - metadata: { - bindings: { - url: { - source: 'core/post-meta', - args: { key: 'url_custom_field' }, - }, - }, - }, - }, - }, - ], - } ); - - // Check the frontend shows the original value of the custom field. - const previewPage = await editor.openPreviewPage(); - const buttonDom = previewPage.locator( - '#button-url-binding a' - ); - await expect( buttonDom ).toHaveText( 'button default text' ); - await expect( buttonDom ).toHaveAttribute( - 'href', - '#url-custom-field' - ); - } ); - - test( 'should use the values of the custom fields when text and url are bound', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/buttons', - innerBlocks: [ - { - name: 'core/button', - attributes: { - anchor: 'button-multiple-bindings', - text: 'button default text', - url: '#default-url', - metadata: { - bindings: { - text: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - url: { - source: 'core/post-meta', - args: { key: 'url_custom_field' }, - }, - }, - }, - }, - }, - ], - } ); - - // Check the frontend uses the values of the custom fields. - const previewPage = await editor.openPreviewPage(); - const buttonDom = previewPage.locator( - '#button-multiple-bindings a' - ); - await expect( buttonDom ).toHaveText( - 'Value of the text custom field' - ); - await expect( buttonDom ).toHaveAttribute( - 'href', - '#url-custom-field' - ); - } ); - - test( 'should add empty button block when pressing enter', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/buttons', - innerBlocks: [ - { - name: 'core/button', - attributes: { - anchor: 'button-text-binding', - text: 'button default text', - url: '#default-url', - metadata: { - bindings: { - text: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - }, - ], - } ); - await editor.canvas - .getByRole( 'document', { - name: 'Block: Button', - exact: true, - } ) - .getByRole( 'textbox' ) - .click(); - await page.keyboard.press( 'End' ); - await page.keyboard.press( 'Enter' ); - const [ initialButton, newEmptyButton ] = await editor.canvas - .locator( '[data-type="core/button"]' ) - .all(); - // First block should be the original block. - await expect( initialButton ).toHaveText( - 'Value of the text custom field' - ); - // Second block should be an empty paragraph block. - await expect( newEmptyButton ).toHaveText( '' ); - await expect( newEmptyButton ).toBeEditable(); - } ); - test( 'should show a selector for url, text, linkTarget and rel', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/buttons', - innerBlocks: [ - { - name: 'core/button', - }, - ], - } ); - await editor.canvas - .getByRole( 'document', { - name: 'Block: Button', - exact: true, - } ) - .getByRole( 'textbox' ) - .click(); - await page - .getByRole( 'tabpanel', { - name: 'Settings', - } ) - .getByLabel( 'Attributes options' ) - .click(); - const urlAttribute = page.getByRole( 'menuitemcheckbox', { - name: 'Show url', - } ); - await expect( urlAttribute ).toBeVisible(); - const textAttribute = page.getByRole( 'menuitemcheckbox', { - name: 'Show text', - } ); - await expect( textAttribute ).toBeVisible(); - const linkTargetAttribute = page.getByRole( - 'menuitemcheckbox', - { - name: 'Show linkTarget', - } - ); - await expect( linkTargetAttribute ).toBeVisible(); - const relAttribute = page.getByRole( 'menuitemcheckbox', { - name: 'Show rel', - } ); - await expect( relAttribute ).toBeVisible(); - } ); - } ); - - test.describe( 'Image', () => { - test.beforeAll( async ( { requestUtils } ) => { - const customFieldMedia = await requestUtils.uploadMedia( - path.join( - './test/e2e/assets', - '1024x768_e2e_test_image_size.jpeg' - ) - ); - imageCustomFieldSrc = customFieldMedia.source_url; - } ); - - test.beforeEach( async ( { editor, page, requestUtils } ) => { - const postId = await editor.publishPost(); - await requestUtils.rest( { - method: 'POST', - path: '/wp/v2/posts/' + postId, - data: { - meta: { - url_custom_field: imageCustomFieldSrc, - }, - }, - } ); - await page.reload(); - } ); - test( 'should show the value of the custom field when url is bound', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/image', - attributes: { - anchor: 'image-url-binding', - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - metadata: { - bindings: { - url: { - source: 'core/post-meta', - args: { key: 'url_custom_field' }, - }, - }, - }, - }, - } ); - const imageBlockImg = editor.canvas - .getByRole( 'document', { - name: 'Block: Image', - } ) - .locator( 'img' ); - await expect( imageBlockImg ).toHaveAttribute( - 'src', - imageCustomFieldSrc - ); - - // Check the frontend uses the value of the custom field. - const previewPage = await editor.openPreviewPage(); - const imageDom = previewPage.locator( - '#image-url-binding img' - ); - await expect( imageDom ).toHaveAttribute( - 'src', - imageCustomFieldSrc - ); - await expect( imageDom ).toHaveAttribute( - 'alt', - 'default alt value' - ); - await expect( imageDom ).toHaveAttribute( - 'title', - 'default title value' - ); - } ); - - test( 'should show value of the custom field in the alt textarea when alt is bound', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/image', - attributes: { - anchor: 'image-alt-binding', - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - metadata: { - bindings: { - alt: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const imageBlockImg = editor.canvas - .getByRole( 'document', { - name: 'Block: Image', - } ) - .locator( 'img' ); - await imageBlockImg.click(); - - // Image src is the placeholder. - await expect( imageBlockImg ).toHaveAttribute( - 'src', - imagePlaceholderSrc - ); - - // Alt textarea should have the custom field value. - const altValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - .inputValue(); - expect( altValue ).toBe( 'Value of the text custom field' ); - - // Check the frontend uses the value of the custom field. - const previewPage = await editor.openPreviewPage(); - const imageDom = previewPage.locator( - '#image-alt-binding img' - ); - await expect( imageDom ).toHaveAttribute( - 'src', - imagePlaceholderSrc - ); - await expect( imageDom ).toHaveAttribute( - 'alt', - 'Value of the text custom field' - ); - await expect( imageDom ).toHaveAttribute( - 'title', - 'default title value' - ); - } ); - - test( 'should show value of the custom field in the title input when title is bound', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/image', - attributes: { - anchor: 'image-title-binding', - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - metadata: { - bindings: { - title: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const imageBlockImg = editor.canvas - .getByRole( 'document', { - name: 'Block: Image', - } ) - .locator( 'img' ); - await imageBlockImg.click(); - - // Image src is the placeholder. - await expect( imageBlockImg ).toHaveAttribute( - 'src', - imagePlaceholderSrc - ); - - // Title input should have the custom field value. - const advancedButton = page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByRole( 'button', { - name: 'Advanced', - } ); - const isAdvancedPanelOpen = - await advancedButton.getAttribute( 'aria-expanded' ); - if ( isAdvancedPanelOpen === 'false' ) { - await advancedButton.click(); - } - const titleValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - .inputValue(); - expect( titleValue ).toBe( 'Value of the text custom field' ); - - // Check the frontend uses the value of the custom field. - const previewPage = await editor.openPreviewPage(); - const imageDom = previewPage.locator( - '#image-title-binding img' - ); - await expect( imageDom ).toHaveAttribute( - 'src', - imagePlaceholderSrc - ); - await expect( imageDom ).toHaveAttribute( - 'alt', - 'default alt value' - ); - await expect( imageDom ).toHaveAttribute( - 'title', - 'Value of the text custom field' - ); - } ); - - test( 'Multiple bindings should show the value of the custom fields', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/image', - attributes: { - anchor: 'image-multiple-bindings', - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - metadata: { - bindings: { - url: { - source: 'core/post-meta', - args: { key: 'url_custom_field' }, - }, - alt: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const imageBlockImg = editor.canvas - .getByRole( 'document', { - name: 'Block: Image', - } ) - .locator( 'img' ); - await imageBlockImg.click(); - - // Image src is the custom field value. - await expect( imageBlockImg ).toHaveAttribute( - 'src', - imageCustomFieldSrc - ); - - // Alt textarea should have the custom field value. - const altValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ) - .inputValue(); - expect( altValue ).toBe( 'Value of the text custom field' ); - - // Title input should have the original value. - const advancedButton = page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByRole( 'button', { - name: 'Advanced', - } ); - const isAdvancedPanelOpen = - await advancedButton.getAttribute( 'aria-expanded' ); - if ( isAdvancedPanelOpen === 'false' ) { - await advancedButton.click(); - } - const titleValue = await page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Title attribute' ) - .inputValue(); - expect( titleValue ).toBe( 'default title value' ); - - // Check the frontend uses the values of the custom fields. - const previewPage = await editor.openPreviewPage(); - const imageDom = previewPage.locator( - '#image-multiple-bindings img' - ); - await expect( imageDom ).toHaveAttribute( - 'src', - imageCustomFieldSrc - ); - await expect( imageDom ).toHaveAttribute( - 'alt', - 'Value of the text custom field' - ); - await expect( imageDom ).toHaveAttribute( - 'title', - 'default title value' - ); - } ); - test( 'should show a selector for url, id, title and alt', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/image', - } ); - await page - .getByRole( 'tabpanel', { - name: 'Settings', - } ) - .getByLabel( 'Attributes options' ) - .click(); - const urlAttribute = page.getByRole( 'menuitemcheckbox', { - name: 'Show url', - } ); - await expect( urlAttribute ).toBeVisible(); - const idAttribute = page.getByRole( 'menuitemcheckbox', { - name: 'Show id', - } ); - await expect( idAttribute ).toBeVisible(); - const titleAttribute = page.getByRole( 'menuitemcheckbox', { - name: 'Show title', - } ); - await expect( titleAttribute ).toBeVisible(); - const altAttribute = page.getByRole( 'menuitemcheckbox', { - name: 'Show alt', - } ); - await expect( altAttribute ).toBeVisible(); - } ); - } ); - - test.describe( 'Edit custom fields', () => { - test( 'should be possible to edit the value of the custom field from the paragraph', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - anchor: 'paragraph-binding', - content: 'paragraph default content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - - await expect( paragraphBlock ).toHaveAttribute( - 'contenteditable', - 'true' - ); - await paragraphBlock.fill( 'new value' ); - // Check that the paragraph content attribute didn't change. - const [ paragraphBlockObject ] = await editor.getBlocks(); - expect( paragraphBlockObject.attributes.content ).toBe( - 'paragraph default content' - ); - // Check the value of the custom field is being updated by visiting the frontend. - const previewPage = await editor.openPreviewPage(); - await expect( - previewPage.locator( '#paragraph-binding' ) - ).toHaveText( 'new value' ); - } ); - - // Related issue: https://github.com/WordPress/gutenberg/issues/62347 - test( 'should be possible to use symbols and numbers as the custom field value', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - anchor: 'paragraph-binding', - content: 'paragraph default content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - - await expect( paragraphBlock ).toHaveAttribute( - 'contenteditable', - 'true' - ); - await paragraphBlock.fill( '$10.00' ); - // Check the value of the custom field is being updated by visiting the frontend. - const previewPage = await editor.openPreviewPage(); - await expect( - previewPage.locator( '#paragraph-binding' ) - ).toHaveText( '$10.00' ); - } ); - - test( 'should be possible to edit the value of the url custom field from the button', async ( { - editor, - page, - pageUtils, - } ) => { - await editor.insertBlock( { - name: 'core/buttons', - innerBlocks: [ - { - name: 'core/button', - attributes: { - anchor: 'button-url-binding', - text: 'button default text', - url: '#default-url', - metadata: { - bindings: { - url: { - source: 'core/post-meta', - args: { key: 'url_custom_field' }, - }, - }, - }, - }, - }, - ], - } ); - - // Edit the url. - const buttonBlock = editor.canvas - .getByRole( 'document', { - name: 'Block: Button', - exact: true, - } ) - .getByRole( 'textbox' ); - await buttonBlock.click(); - await page - .getByRole( 'button', { name: 'Edit link', exact: true } ) - .click(); - await page - .getByPlaceholder( 'Search or type URL' ) - .fill( '#url-custom-field-modified' ); - await pageUtils.pressKeys( 'Enter' ); - - // Check that the button url attribute didn't change. - const [ buttonsObject ] = await editor.getBlocks(); - expect( buttonsObject.innerBlocks[ 0 ].attributes.url ).toBe( - '#default-url' - ); - // Check the value of the custom field is being updated by visiting the frontend. - const previewPage = await editor.openPreviewPage(); - await expect( - previewPage.locator( '#button-url-binding a' ) - ).toHaveAttribute( 'href', '#url-custom-field-modified' ); - } ); - - test( 'should be possible to edit the value of the url custom field from the image', async ( { - editor, - page, - pageUtils, - requestUtils, - } ) => { - const customFieldMedia = await requestUtils.uploadMedia( - path.join( - './test/e2e/assets', - '1024x768_e2e_test_image_size.jpeg' - ) - ); - imageCustomFieldSrc = customFieldMedia.source_url; - - await editor.insertBlock( { - name: 'core/image', - attributes: { - anchor: 'image-url-binding', - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - metadata: { - bindings: { - url: { - source: 'core/post-meta', - args: { key: 'url_custom_field' }, - }, - }, - }, - }, - } ); - - // Edit image url. - await page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { - name: 'Replace', - } ) - .click(); - await page - .getByRole( 'button', { name: 'Edit link', exact: true } ) - .click(); - await page - .getByPlaceholder( 'Search or type URL' ) - .fill( imageCustomFieldSrc ); - await pageUtils.pressKeys( 'Enter' ); - - // Check that the image url attribute didn't change and still uses the placeholder. - const [ imageBlockObject ] = await editor.getBlocks(); - expect( imageBlockObject.attributes.url ).toBe( - imagePlaceholderSrc - ); - - // Check the value of the custom field is being updated by visiting the frontend. - const previewPage = await editor.openPreviewPage(); - await expect( - previewPage.locator( '#image-url-binding img' ) - ).toHaveAttribute( 'src', imageCustomFieldSrc ); - } ); - - test( 'should be possible to edit the value of the text custom field from the image alt', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/image', - attributes: { - anchor: 'image-alt-binding', - url: imagePlaceholderSrc, - alt: 'default alt value', - metadata: { - bindings: { - alt: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, - } ); - const imageBlockImg = editor.canvas - .getByRole( 'document', { - name: 'Block: Image', - } ) - .locator( 'img' ); - await imageBlockImg.click(); - - // Edit the custom field value in the alt textarea. - const altInputArea = page - .getByRole( 'tabpanel', { name: 'Settings' } ) - .getByLabel( 'Alternative text' ); - await expect( altInputArea ).not.toHaveAttribute( 'readonly' ); - await altInputArea.fill( 'new value' ); - - // Check that the image alt attribute didn't change. - const [ imageBlockObject ] = await editor.getBlocks(); - expect( imageBlockObject.attributes.alt ).toBe( - 'default alt value' - ); - // Check the value of the custom field is being updated by visiting the frontend. - const previewPage = await editor.openPreviewPage(); - await expect( - previewPage.locator( '#image-alt-binding img' ) - ).toHaveAttribute( 'alt', 'new value' ); - } ); - - test( 'should not be possible to edit the value of the protected custom fields', async ( { - editor, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - content: 'paragraph default content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { key: '_protected_field' }, - }, - }, - }, - }, - } ); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - - await expect( paragraphBlock ).toHaveAttribute( - 'contenteditable', - 'false' - ); - } ); - } ); - } ); - - test.describe( 'Sources registration', () => { - test.beforeEach( async ( { admin } ) => { - await admin.createNewPost( { title: 'Test bindings' } ); - } ); - - test( 'should show the label of a source only registered in the server', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - metadata: { - bindings: { - content: { - source: 'core/server-source', - }, - }, - }, - }, - } ); - - const bindingsPanel = page.locator( - '.block-editor-bindings__panel' - ); - await expect( bindingsPanel ).toContainText( 'Server Source' ); - } ); - } ); -} ); diff --git a/test/e2e/specs/editor/various/block-bindings/custom-sources.spec.js b/test/e2e/specs/editor/various/block-bindings/custom-sources.spec.js new file mode 100644 index 00000000000000..d6563ce9cb5f5f --- /dev/null +++ b/test/e2e/specs/editor/various/block-bindings/custom-sources.spec.js @@ -0,0 +1,1204 @@ +/** + * External dependencies + */ +const path = require( 'path' ); +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.describe( 'Registered sources', () => { + let imagePlaceholderSrc; + let testingImgSrc; + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( + 'gutenberg-test-themes/block-bindings' + ); + await requestUtils.activatePlugin( 'gutenberg-test-block-bindings' ); + await requestUtils.deleteAllMedia(); + const placeholderMedia = await requestUtils.uploadMedia( + path.join( './test/e2e/assets', '10x10_e2e_test_image_z9T8jK.png' ) + ); + imagePlaceholderSrc = placeholderMedia.source_url; + + const testingImgMedia = await requestUtils.uploadMedia( + path.join( + './test/e2e/assets', + '1024x768_e2e_test_image_size.jpeg' + ) + ); + testingImgSrc = testingImgMedia.source_url; + } ); + + test.beforeEach( async ( { admin } ) => { + await admin.createNewPost( { title: 'Test bindings' } ); + } ); + + test.afterEach( async ( { requestUtils } ) => { + await requestUtils.deleteAllPosts(); + } ); + + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.deleteAllMedia(); + await requestUtils.activateTheme( 'twentytwentyone' ); + await requestUtils.deactivatePlugin( 'gutenberg-test-block-bindings' ); + } ); + + test.describe( 'getValues', () => { + test( 'should show the returned value in paragraph content', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + anchor: 'connected-paragraph', + content: 'paragraph default content', + metadata: { + bindings: { + content: { + source: 'testing/complete-source', + args: { key: 'text_field' }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( 'Text Field Value' ); + + // Check the frontend shows the value of the custom field. + const previewPage = await editor.openPreviewPage(); + await expect( + previewPage.locator( '#connected-paragraph' ) + ).toHaveText( 'Text Field Value' ); + } ); + test( 'should show the returned value in heading content', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/heading', + attributes: { + anchor: 'connected-heading', + content: 'heading default content', + metadata: { + bindings: { + content: { + source: 'testing/complete-source', + args: { key: 'text_field' }, + }, + }, + }, + }, + } ); + const headingBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Heading', + } ); + await expect( headingBlock ).toHaveText( 'Text Field Value' ); + + // Check the frontend shows the value of the custom field. + const previewPage = await editor.openPreviewPage(); + await expect( + previewPage.locator( '#connected-heading' ) + ).toHaveText( 'Text Field Value' ); + } ); + test( 'should show the returned values in button attributes', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/buttons', + innerBlocks: [ + { + name: 'core/button', + attributes: { + anchor: 'connected-button', + text: 'button default text', + url: '#default-url', + metadata: { + bindings: { + text: { + source: 'testing/complete-source', + args: { key: 'text_field' }, + }, + url: { + source: 'testing/complete-source', + args: { key: 'url_field' }, + }, + }, + }, + }, + }, + ], + } ); + + // Check the frontend uses the values of the custom fields. + const previewPage = await editor.openPreviewPage(); + const buttonDom = previewPage.locator( '#connected-button a' ); + await expect( buttonDom ).toHaveText( 'Text Field Value' ); + await expect( buttonDom ).toHaveAttribute( 'href', testingImgSrc ); + } ); + test( 'should show the returned values in image attributes', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/image', + attributes: { + anchor: 'connected-image', + url: imagePlaceholderSrc, + alt: 'default alt value', + title: 'default title value', + metadata: { + bindings: { + url: { + source: 'testing/complete-source', + args: { key: 'url_field' }, + }, + alt: { + source: 'testing/complete-source', + args: { key: 'text_field' }, + }, + }, + }, + }, + } ); + const imageBlockImg = editor.canvas + .getByRole( 'document', { + name: 'Block: Image', + } ) + .locator( 'img' ); + await imageBlockImg.click(); + + // Image src is the custom field value. + await expect( imageBlockImg ).toHaveAttribute( + 'src', + testingImgSrc + ); + + // Alt textarea should have the custom field value. + const altValue = await page + .getByRole( 'tabpanel', { name: 'Settings' } ) + .getByLabel( 'Alternative text' ) + .inputValue(); + expect( altValue ).toBe( 'Text Field Value' ); + + // Title input should have the original value. + const advancedButton = page + .getByRole( 'tabpanel', { name: 'Settings' } ) + .getByRole( 'button', { + name: 'Advanced', + } ); + const isAdvancedPanelOpen = + await advancedButton.getAttribute( 'aria-expanded' ); + if ( isAdvancedPanelOpen === 'false' ) { + await advancedButton.click(); + } + const titleValue = await page + .getByRole( 'tabpanel', { name: 'Settings' } ) + .getByLabel( 'Title attribute' ) + .inputValue(); + expect( titleValue ).toBe( 'default title value' ); + + // Check the frontend uses the values of the custom fields. + const previewPage = await editor.openPreviewPage(); + const imageDom = previewPage.locator( '#connected-image img' ); + await expect( imageDom ).toHaveAttribute( 'src', testingImgSrc ); + await expect( imageDom ).toHaveAttribute( + 'alt', + 'Text Field Value' + ); + await expect( imageDom ).toHaveAttribute( + 'title', + 'default title value' + ); + } ); + test( 'should fall back to source label when `getValues` is undefined', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'paragraph default content', + metadata: { + bindings: { + content: { + source: 'testing/server-only-source', + args: { key: 'text_field' }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( 'Server Source' ); + } ); + test( 'should fall back to null when `getValues` is undefined in URL attributes', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/image', + attributes: { + metadata: { + bindings: { + url: { + source: 'testing/server-only-source', + args: { key: 'url_field' }, + }, + }, + }, + }, + } ); + const imageBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Image', + } ); + await expect( + imageBlock.locator( '.components-placeholder__fieldset' ) + ).toHaveText( 'Connected to Server Source' ); + } ); + } ); + + test.describe( 'should lock editing', () => { + // Logic reused accross all the tests that check paragraph editing is locked. + async function testParagraphControlsAreLocked( { + source, + editor, + page, + } ) { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'paragraph default content', + metadata: { + bindings: { + content: { + source, + args: { key: 'text_field' }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await paragraphBlock.click(); + + // Alignment controls exist. + await expect( + page + .getByRole( 'toolbar', { name: 'Block tools' } ) + .getByRole( 'button', { name: 'Align text' } ) + ).toBeVisible(); + + // Format controls don't exist. + await expect( + page + .getByRole( 'toolbar', { name: 'Block tools' } ) + .getByRole( 'button', { + name: 'Bold', + } ) + ).toBeHidden(); + + // Paragraph is not editable. + await expect( paragraphBlock ).toHaveAttribute( + 'contenteditable', + 'false' + ); + } + test.describe( 'canUserEditValue returns false', () => { + test( 'paragraph', async ( { editor, page } ) => { + await testParagraphControlsAreLocked( { + source: 'testing/can-user-edit-false', + editor, + page, + } ); + } ); + test( 'heading', async ( { editor, page } ) => { + await editor.insertBlock( { + name: 'core/heading', + attributes: { + content: 'heading default content', + metadata: { + bindings: { + content: { + source: 'testing/can-user-edit-false', + args: { key: 'text_field' }, + }, + }, + }, + }, + } ); + const headingBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Heading', + } ); + await headingBlock.click(); + + // Alignment controls exist. + await expect( + page + .getByRole( 'toolbar', { name: 'Block tools' } ) + .getByRole( 'button', { name: 'Align text' } ) + ).toBeVisible(); + + // Format controls don't exist. + await expect( + page + .getByRole( 'toolbar', { name: 'Block tools' } ) + .getByRole( 'button', { + name: 'Bold', + } ) + ).toBeHidden(); + + // Heading is not editable. + await expect( headingBlock ).toHaveAttribute( + 'contenteditable', + 'false' + ); + } ); + test( 'button', async ( { editor, page } ) => { + await editor.insertBlock( { + name: 'core/buttons', + innerBlocks: [ + { + name: 'core/button', + attributes: { + text: 'button default text', + url: '#default-url', + metadata: { + bindings: { + text: { + source: 'testing/can-user-edit-false', + args: { key: 'text_field' }, + }, + url: { + source: 'testing/can-user-edit-false', + args: { key: 'url_field' }, + }, + }, + }, + }, + }, + ], + } ); + const buttonBlock = editor.canvas + .getByRole( 'document', { + name: 'Block: Button', + exact: true, + } ) + .getByRole( 'textbox' ); + await buttonBlock.click(); + + // Alignment controls are visible. + await expect( + page + .getByRole( 'toolbar', { name: 'Block tools' } ) + .getByRole( 'button', { name: 'Align text' } ) + ).toBeVisible(); + + // Format controls don't exist. + await expect( + page + .getByRole( 'toolbar', { name: 'Block tools' } ) + .getByRole( 'button', { + name: 'Bold', + } ) + ).toBeHidden(); + + // Button is not editable. + await expect( buttonBlock ).toHaveAttribute( + 'contenteditable', + 'false' + ); + + // Link controls don't exist. + await expect( + page + .getByRole( 'toolbar', { name: 'Block tools' } ) + .getByRole( 'button', { name: 'Link' } ) + ).toBeHidden(); + await expect( + page + .getByRole( 'toolbar', { name: 'Block tools' } ) + .getByRole( 'button', { name: 'Unlink' } ) + ).toBeHidden(); + } ); + test( 'image', async ( { editor, page } ) => { + await editor.insertBlock( { + name: 'core/image', + attributes: { + url: imagePlaceholderSrc, + alt: 'default alt value', + title: 'default title value', + metadata: { + bindings: { + url: { + source: 'testing/can-user-edit-false', + args: { key: 'url_field' }, + }, + alt: { + source: 'testing/can-user-edit-false', + args: { key: 'text_field' }, + }, + title: { + source: 'testing/can-user-edit-false', + args: { key: 'text_field' }, + }, + }, + }, + }, + } ); + const imageBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Image', + } ); + await imageBlock.click(); + + // Replace controls don't exist. + await expect( + page + .getByRole( 'toolbar', { name: 'Block tools' } ) + .getByRole( 'button', { + name: 'Replace', + } ) + ).toBeHidden(); + + // Image placeholder doesn't show the upload button. + await expect( + imageBlock.getByRole( 'button', { name: 'Upload' } ) + ).toBeHidden(); + + // Alt textarea is disabled and with the custom field value. + await expect( + page + .getByRole( 'tabpanel', { name: 'Settings' } ) + .getByLabel( 'Alternative text' ) + ).toHaveAttribute( 'readonly' ); + const altValue = await page + .getByRole( 'tabpanel', { name: 'Settings' } ) + .getByLabel( 'Alternative text' ) + .inputValue(); + expect( altValue ).toBe( 'Text Field Value' ); + + // Title input is enabled and with the original value. + await page + .getByRole( 'tabpanel', { name: 'Settings' } ) + .getByRole( 'button', { name: 'Advanced' } ) + .click(); + await expect( + page + .getByRole( 'tabpanel', { name: 'Settings' } ) + .getByLabel( 'Title attribute' ) + ).toHaveAttribute( 'readonly' ); + const titleValue = await page + .getByRole( 'tabpanel', { name: 'Settings' } ) + .getByLabel( 'Title attribute' ) + .inputValue(); + expect( titleValue ).toBe( 'Text Field Value' ); + } ); + } ); + // The following tests just check the paragraph and assume is the case for the rest of the blocks. + test( 'canUserEditValue is not defined', async ( { editor, page } ) => { + await testParagraphControlsAreLocked( { + source: 'testing/can-user-edit-undefined', + editor, + page, + } ); + } ); + test( 'setValues is not defined', async ( { editor, page } ) => { + await testParagraphControlsAreLocked( { + source: 'testing/complete-source-undefined', + editor, + page, + } ); + } ); + test( 'source is not defined', async ( { editor, page } ) => { + await testParagraphControlsAreLocked( { + source: 'testing/undefined-source', + editor, + page, + } ); + } ); + } ); + + // Use `core/post-meta` source to test editing to avoid overcomplicating custom sources. + // It needs a source that can be consumed and edited from the server and the editor. + test.describe( 'setValues', () => { + test( 'should be possible to edit the value from paragraph content', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + anchor: 'connected-paragraph', + content: 'paragraph default content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { key: 'text_custom_field' }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + + await expect( paragraphBlock ).toHaveAttribute( + 'contenteditable', + 'true' + ); + await paragraphBlock.fill( 'new value' ); + // Check that the paragraph content attribute didn't change. + const [ paragraphBlockObject ] = await editor.getBlocks(); + expect( paragraphBlockObject.attributes.content ).toBe( + 'paragraph default content' + ); + // Check the value of the custom field is being updated by visiting the frontend. + const previewPage = await editor.openPreviewPage(); + await expect( + previewPage.locator( '#connected-paragraph' ) + ).toHaveText( 'new value' ); + } ); + // Related issue: https://github.com/WordPress/gutenberg/issues/62347 + test( 'should be possible to use symbols and numbers as the custom field value', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + anchor: 'paragraph-binding', + content: 'paragraph default content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { key: 'text_custom_field' }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + + await expect( paragraphBlock ).toHaveAttribute( + 'contenteditable', + 'true' + ); + await paragraphBlock.fill( '$10.00' ); + // Check the value of the custom field is being updated by visiting the frontend. + const previewPage = await editor.openPreviewPage(); + await expect( + previewPage.locator( '#paragraph-binding' ) + ).toHaveText( '$10.00' ); + } ); + test( 'should be possible to edit the value of the url custom field from the button', async ( { + editor, + page, + pageUtils, + } ) => { + await editor.insertBlock( { + name: 'core/buttons', + innerBlocks: [ + { + name: 'core/button', + attributes: { + anchor: 'button-url-binding', + text: 'button default text', + url: '#default-url', + metadata: { + bindings: { + url: { + source: 'core/post-meta', + args: { key: 'url_custom_field' }, + }, + }, + }, + }, + }, + ], + } ); + + // Edit the url. + const buttonBlock = editor.canvas + .getByRole( 'document', { + name: 'Block: Button', + exact: true, + } ) + .getByRole( 'textbox' ); + await buttonBlock.click(); + await page + .getByRole( 'button', { name: 'Edit link', exact: true } ) + .click(); + await page + .getByPlaceholder( 'Search or type URL' ) + .fill( '#url-custom-field-modified' ); + await pageUtils.pressKeys( 'Enter' ); + + // Check that the button url attribute didn't change. + const [ buttonsObject ] = await editor.getBlocks(); + expect( buttonsObject.innerBlocks[ 0 ].attributes.url ).toBe( + '#default-url' + ); + // Check the value of the custom field is being updated by visiting the frontend. + const previewPage = await editor.openPreviewPage(); + await expect( + previewPage.locator( '#button-url-binding a' ) + ).toHaveAttribute( 'href', '#url-custom-field-modified' ); + } ); + test( 'should be possible to edit the value of the url custom field from the image', async ( { + editor, + page, + pageUtils, + requestUtils, + } ) => { + const customFieldMedia = await requestUtils.uploadMedia( + path.join( + './test/e2e/assets', + '1024x768_e2e_test_image_size.jpeg' + ) + ); + testingImgSrc = customFieldMedia.source_url; + + await editor.insertBlock( { + name: 'core/image', + attributes: { + anchor: 'image-url-binding', + url: imagePlaceholderSrc, + alt: 'default alt value', + title: 'default title value', + metadata: { + bindings: { + url: { + source: 'core/post-meta', + args: { key: 'url_custom_field' }, + }, + }, + }, + }, + } ); + + // Edit image url. + await page + .getByRole( 'toolbar', { name: 'Block tools' } ) + .getByRole( 'button', { + name: 'Replace', + } ) + .click(); + await page + .getByRole( 'button', { name: 'Edit link', exact: true } ) + .click(); + await page + .getByPlaceholder( 'Search or type URL' ) + .fill( testingImgSrc ); + await pageUtils.pressKeys( 'Enter' ); + + // Check that the image url attribute didn't change and still uses the placeholder. + const [ imageBlockObject ] = await editor.getBlocks(); + expect( imageBlockObject.attributes.url ).toBe( + imagePlaceholderSrc + ); + + // Check the value of the custom field is being updated by visiting the frontend. + const previewPage = await editor.openPreviewPage(); + await expect( + previewPage.locator( '#image-url-binding img' ) + ).toHaveAttribute( 'src', testingImgSrc ); + } ); + test( 'should be possible to edit the value of the text custom field from the image alt', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/image', + attributes: { + anchor: 'image-alt-binding', + url: imagePlaceholderSrc, + alt: 'default alt value', + metadata: { + bindings: { + alt: { + source: 'core/post-meta', + args: { key: 'text_custom_field' }, + }, + }, + }, + }, + } ); + const imageBlockImg = editor.canvas + .getByRole( 'document', { + name: 'Block: Image', + } ) + .locator( 'img' ); + await imageBlockImg.click(); + + // Edit the custom field value in the alt textarea. + const altInputArea = page + .getByRole( 'tabpanel', { name: 'Settings' } ) + .getByLabel( 'Alternative text' ); + await expect( altInputArea ).not.toHaveAttribute( 'readonly' ); + await altInputArea.fill( 'new value' ); + + // Check that the image alt attribute didn't change. + const [ imageBlockObject ] = await editor.getBlocks(); + expect( imageBlockObject.attributes.alt ).toBe( + 'default alt value' + ); + // Check the value of the custom field is being updated by visiting the frontend. + const previewPage = await editor.openPreviewPage(); + await expect( + previewPage.locator( '#image-alt-binding img' ) + ).toHaveAttribute( 'alt', 'new value' ); + } ); + } ); + + test.describe( 'getFieldsList', () => { + test( 'should be possible to update attribute value through bindings UI', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + } ); + await page.getByLabel( 'Attributes options' ).click(); + await page + .getByRole( 'menuitemcheckbox', { + name: 'Show content', + } ) + .click(); + await page.getByRole( 'button', { name: 'content' } ).click(); + await page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'Text Field Label' } ) + .click(); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( 'Text Field Value' ); + } ); + test( 'should be possible to connect the paragraph content', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + } ); + await page.getByLabel( 'Attributes options' ).click(); + const contentAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show content', + } ); + await expect( contentAttribute ).toBeVisible(); + } ); + test( 'should be possible to connect the heading content', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/heading', + } ); + await page.getByLabel( 'Attributes options' ).click(); + const contentAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show content', + } ); + await expect( contentAttribute ).toBeVisible(); + } ); + test( 'should be possible to connect the button supported attributes', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/buttons', + innerBlocks: [ + { + name: 'core/button', + }, + ], + } ); + await editor.canvas + .getByRole( 'document', { + name: 'Block: Button', + exact: true, + } ) + .getByRole( 'textbox' ) + .click(); + await page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByLabel( 'Attributes options' ) + .click(); + const urlAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show url', + } ); + await expect( urlAttribute ).toBeVisible(); + const textAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show text', + } ); + await expect( textAttribute ).toBeVisible(); + const linkTargetAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show linkTarget', + } ); + await expect( linkTargetAttribute ).toBeVisible(); + const relAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show rel', + } ); + await expect( relAttribute ).toBeVisible(); + // Check not supported attributes are not included. + const tagNameAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show tagName', + } ); + await expect( tagNameAttribute ).toBeHidden(); + } ); + test( 'should be possible to connect the image supported attributes', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/image', + } ); + await page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByLabel( 'Attributes options' ) + .click(); + const urlAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show url', + } ); + await expect( urlAttribute ).toBeVisible(); + const idAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show id', + } ); + await expect( idAttribute ).toBeVisible(); + const titleAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show title', + } ); + await expect( titleAttribute ).toBeVisible(); + const altAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show alt', + } ); + await expect( altAttribute ).toBeVisible(); + // Check not supported attributes are not included. + const linkClassAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show linkClass', + } ); + await expect( linkClassAttribute ).toBeHidden(); + } ); + test( 'should show all the available fields in the dropdown UI', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'default value', + metadata: { + bindings: { + content: { + source: 'testing/complete-source', + args: { key: 'text_field' }, + }, + }, + }, + }, + } ); + await page.getByRole( 'button', { name: 'content' } ).click(); + const textField = page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'Text Field Label' } ); + await expect( textField ).toBeVisible(); + await expect( textField ).toBeChecked(); + const urlField = page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'URL Field Label' } ); + await expect( urlField ).toBeVisible(); + await expect( urlField ).not.toBeChecked(); + } ); + test( 'should show the connected fields in the attributes panel', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'default value', + metadata: { + bindings: { + content: { + source: 'testing/complete-source', + args: { key: 'text_field' }, + }, + }, + }, + }, + } ); + const contentButton = page.getByRole( 'button', { + name: 'content', + } ); + await expect( contentButton ).toContainText( 'Text Field Label' ); + } ); + } ); + + test.describe( 'RichText workflows', () => { + test( 'should add empty paragraph block when pressing enter in paragraph', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'paragraph default content', + metadata: { + bindings: { + content: { + source: 'testing/complete-source', + args: { key: 'text_field' }, + }, + }, + }, + }, + } ); + // Select the paragraph and press Enter at the end of it. + const paragraph = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await editor.selectBlocks( paragraph ); + await page.keyboard.press( 'End' ); + await page.keyboard.press( 'Enter' ); + const [ initialParagraph, newEmptyParagraph ] = await editor.canvas + .locator( '[data-type="core/paragraph"]' ) + .all(); + await expect( initialParagraph ).toHaveText( 'Text Field Value' ); + await expect( newEmptyParagraph ).toHaveText( '' ); + await expect( newEmptyParagraph ).toBeEditable(); + } ); + test( 'should add empty paragraph block when pressing enter in heading', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/heading', + attributes: { + anchor: 'heading-binding', + content: 'heading default content', + metadata: { + bindings: { + content: { + source: 'testing/complete-source', + args: { key: 'text_field' }, + }, + }, + }, + }, + } ); + + // Select the heading and press Enter at the end of it. + const heading = editor.canvas.getByRole( 'document', { + name: 'Block: Heading', + } ); + await editor.selectBlocks( heading ); + await page.keyboard.press( 'End' ); + await page.keyboard.press( 'Enter' ); + // Can't use `editor.getBlocks` because it doesn't return the meta value shown in the editor. + const [ initialHeading, newEmptyParagraph ] = await editor.canvas + .locator( '[data-block]' ) + .all(); + // First block should be the original block. + await expect( initialHeading ).toHaveAttribute( + 'data-type', + 'core/heading' + ); + await expect( initialHeading ).toHaveText( 'Text Field Value' ); + // Second block should be an empty paragraph block. + await expect( newEmptyParagraph ).toHaveAttribute( + 'data-type', + 'core/paragraph' + ); + await expect( newEmptyParagraph ).toHaveText( '' ); + await expect( newEmptyParagraph ).toBeEditable(); + } ); + test( 'should add empty button block when pressing enter in button', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/buttons', + innerBlocks: [ + { + name: 'core/button', + attributes: { + anchor: 'button-text-binding', + text: 'button default text', + url: '#default-url', + metadata: { + bindings: { + text: { + source: 'testing/complete-source', + args: { key: 'text_field' }, + }, + }, + }, + }, + }, + ], + } ); + await editor.canvas + .getByRole( 'document', { + name: 'Block: Button', + exact: true, + } ) + .getByRole( 'textbox' ) + .click(); + await page.keyboard.press( 'End' ); + await page.keyboard.press( 'Enter' ); + const [ initialButton, newEmptyButton ] = await editor.canvas + .locator( '[data-type="core/button"]' ) + .all(); + // First block should be the original block. + await expect( initialButton ).toHaveText( 'Text Field Value' ); + // Second block should be an empty paragraph block. + await expect( newEmptyButton ).toHaveText( '' ); + await expect( newEmptyButton ).toBeEditable(); + } ); + test( 'should show placeholder prompt when value is empty and can edit', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'paragraph default content', + metadata: { + bindings: { + content: { + source: 'testing/complete-source', + args: { key: 'empty_field' }, + }, + }, + }, + }, + } ); + + const paragraphBlock = editor.canvas.getByRole( 'document', { + // Aria-label is changed for empty paragraphs. + name: 'Empty empty_field; start writing to edit its value', + } ); + + await expect( paragraphBlock ).toBeEmpty(); + + const placeholder = paragraphBlock.locator( 'span' ); + await expect( placeholder ).toHaveAttribute( + 'data-rich-text-placeholder', + 'Add Empty Field Label' + ); + } ); + test( 'should show source label when value is empty, cannot edit, and `getFieldsList` is undefined', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'paragraph default content', + metadata: { + bindings: { + content: { + source: 'testing/can-user-edit-false', + args: { key: 'empty_field' }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + // Aria-label is changed for empty paragraphs. + name: 'empty_field', + } ); + await expect( paragraphBlock ).toBeEmpty(); + const placeholder = paragraphBlock.locator( 'span' ); + await expect( placeholder ).toHaveAttribute( + 'data-rich-text-placeholder', + 'Can User Edit: False' + ); + } ); + test( 'should show placeholder attribute over bindings placeholder', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + placeholder: 'My custom placeholder', + content: 'paragraph default content', + metadata: { + bindings: { + content: { + source: 'testing/complete-source', + args: { key: 'empty_field' }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + // Aria-label is changed for empty paragraphs. + name: 'empty_field', + } ); + + await expect( paragraphBlock ).toBeEmpty(); + + const placeholder = paragraphBlock.locator( 'span' ); + await expect( placeholder ).toHaveAttribute( + 'data-rich-text-placeholder', + 'My custom placeholder' + ); + } ); + } ); + + test( 'should show the label of a source only registered in the server in blocks connected', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + metadata: { + bindings: { + content: { + source: 'testing/server-only-source', + }, + }, + }, + }, + } ); + + const contentButton = page.getByRole( 'button', { + name: 'content', + } ); + await expect( contentButton ).toContainText( 'Server Source' ); + } ); + test( 'should show an "Invalid source" warning for not registered sources', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + metadata: { + bindings: { + content: { + source: 'testing/undefined-source', + }, + }, + }, + }, + } ); + + const contentButton = page.getByRole( 'button', { + name: 'content', + } ); + await expect( contentButton ).toContainText( 'Invalid source' ); + } ); +} ); diff --git a/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js b/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js new file mode 100644 index 00000000000000..d82def6feb66bf --- /dev/null +++ b/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js @@ -0,0 +1,551 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.describe( 'Post Meta source', () => { + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( + 'gutenberg-test-themes/block-bindings' + ); + await requestUtils.activatePlugin( 'gutenberg-test-block-bindings' ); + } ); + + test.afterEach( async ( { requestUtils } ) => { + await requestUtils.deleteAllPosts(); + } ); + + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.deleteAllMedia(); + await requestUtils.activateTheme( 'twentytwentyone' ); + await requestUtils.deactivatePlugin( 'gutenberg-test-block-bindings' ); + } ); + + test.describe( 'Movie CPT template', () => { + test.beforeEach( async ( { admin, editor } ) => { + await admin.visitSiteEditor( { + postId: 'gutenberg-test-themes/block-bindings//single-movie', + postType: 'wp_template', + canvas: 'edit', + } ); + await editor.openDocumentSettingsSidebar(); + } ); + + test.describe( 'Block attributes values', () => { + test( 'should not be possible to edit connected blocks', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'fallback content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { + key: 'movie_field', + }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveAttribute( + 'contenteditable', + 'false' + ); + } ); + test( 'should show the default value if it is defined', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'fallback content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { + key: 'movie_field', + }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( + 'Movie field default value' + ); + } ); + test( 'should fall back to the field label if the default value is not defined', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'fallback content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { + key: 'field_with_only_label', + }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( + 'Field with only label' + ); + } ); + test( 'should fall back to the field key if the field label is not defined', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'fallback content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { + key: 'field_without_label_or_default', + }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( + 'field_without_label_or_default' + ); + } ); + } ); + + test.describe( 'Attributes panel', () => { + test( 'should show the field label if it is defined', async ( { + editor, + page, + } ) => { + /** + * Create connection manually until this issue is solved: + * https://github.com/WordPress/gutenberg/pull/65604 + * + * Once solved, block with the binding can be directly inserted. + */ + await editor.insertBlock( { + name: 'core/paragraph', + } ); + await page.getByLabel( 'Attributes options' ).click(); + await page + .getByRole( 'menuitemcheckbox', { + name: 'Show content', + } ) + .click(); + const contentBinding = page.getByRole( 'button', { + name: 'content', + } ); + await contentBinding.click(); + await page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'Movie field label' } ) + .click(); + await expect( contentBinding ).toContainText( + 'Movie field label' + ); + } ); + test( 'should fall back to the field key if the field label is not defined', async ( { + editor, + page, + } ) => { + /** + * Create connection manually until this issue is solved: + * https://github.com/WordPress/gutenberg/pull/65604 + * + * Once solved, block with the binding can be directly inserted. + */ + await editor.insertBlock( { + name: 'core/paragraph', + } ); + await page.getByLabel( 'Attributes options' ).click(); + await page + .getByRole( 'menuitemcheckbox', { + name: 'Show content', + } ) + .click(); + const contentBinding = page.getByRole( 'button', { + name: 'content', + } ); + await contentBinding.click(); + await page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'field_without_label_or_default' } ) + .click(); + await expect( contentBinding ).toContainText( + 'field_without_label_or_default' + ); + } ); + } ); + + test.describe( 'Fields list dropdown', () => { + // Insert block and open the dropdown for every test. + test.beforeEach( async ( { editor, page } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + } ); + await page.getByLabel( 'Attributes options' ).click(); + await page + .getByRole( 'menuitemcheckbox', { + name: 'Show content', + } ) + .click(); + await page + .getByRole( 'button', { + name: 'content', + } ) + .click(); + } ); + + test( 'should include movie fields in UI to connect attributes', async ( { + page, + } ) => { + const movieField = page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'Movie field label' } ); + await expect( movieField ).toBeVisible(); + } ); + test( 'should include global fields in UI to connect attributes', async ( { + page, + } ) => { + const globalField = page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'text_custom_field' } ); + await expect( globalField ).toBeVisible(); + } ); + test( 'should not include protected fields', async ( { page } ) => { + // Ensure the fields have loaded by checking the field is visible. + const globalField = page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'text_custom_field' } ); + await expect( globalField ).toBeVisible(); + // Check the protected fields are not visible. + const protectedField = page + .getByRole( 'menuitemradio' ) + .filter( { hasText: '_protected_field' } ); + await expect( protectedField ).toBeHidden(); + const showInRestFalseField = page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'show_in_rest_false_field' } ); + await expect( showInRestFalseField ).toBeHidden(); + } ); + test( 'should show the default value if it is defined', async ( { + page, + } ) => { + const fieldButton = page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'Movie field label' } ); + await expect( fieldButton ).toContainText( + 'Movie field default value' + ); + } ); + test( 'should not show anything if the default value is not defined', async ( { + page, + } ) => { + const fieldButton = page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'Field with only label' } ); + // Check it only contains the field label. + await expect( fieldButton ).toHaveText( + 'Field with only label' + ); + } ); + } ); + } ); + + test.describe( 'Custom template', () => { + test.beforeEach( async ( { admin, editor } ) => { + await admin.visitSiteEditor( { + postId: 'gutenberg-test-themes/block-bindings//custom-template', + postType: 'wp_template', + canvas: 'edit', + } ); + await editor.openDocumentSettingsSidebar(); + } ); + + test( 'should not include post meta fields in UI to connect attributes', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'fallback content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { + key: 'text_custom_field', + }, + }, + }, + }, + }, + } ); + await page + .getByRole( 'button', { + name: 'content', + } ) + .click(); + // Check the fields registered by other sources are there. + const customSourceField = page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'Text Field Label' } ); + await expect( customSourceField ).toBeVisible(); + // Check the post meta fields are not visible. + const globalField = page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'text_custom_field' } ); + await expect( globalField ).toBeHidden(); + const movieField = page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'Movie field label' } ); + await expect( movieField ).toBeHidden(); + } ); + test( 'should show the key in attributes connected to post meta', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'fallback content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { + key: 'text_custom_field', + }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( 'text_custom_field' ); + } ); + } ); + + test.describe( 'Movie CPT post', () => { + test.beforeEach( async ( { admin } ) => { + // CHECK HOW TO CREATE A MOVIE. + await admin.createNewPost( { + postType: 'movie', + title: 'Test bindings', + } ); + } ); + + test( 'should show the custom field value of that specific post', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + anchor: 'connected-paragraph', + content: 'fallback content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { + key: 'movie_field', + }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( + 'Movie field default value' + ); + // Check the frontend shows the value of the custom field. + const previewPage = await editor.openPreviewPage(); + await expect( + previewPage.locator( '#connected-paragraph' ) + ).toHaveText( 'Movie field default value' ); + } ); + test( 'should fall back to the key when custom field is not accessible', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'fallback content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { + key: 'unaccessible_field', + }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( 'unaccessible_field' ); + await expect( paragraphBlock ).toHaveAttribute( + 'contenteditable', + 'false' + ); + } ); + test( 'should not show or edit the value of a protected field', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'fallback content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { + key: '_protected_field', + }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( '_protected_field' ); + await expect( paragraphBlock ).toHaveAttribute( + 'contenteditable', + 'false' + ); + } ); + test( 'should not show or edit the value of a field with `show_in_rest` set to false', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'fallback content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { + key: 'show_in_rest_false_field', + }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( + 'show_in_rest_false_field' + ); + await expect( paragraphBlock ).toHaveAttribute( + 'contenteditable', + 'false' + ); + } ); + test( 'should be possible to edit the value of the connected custom fields', async ( { + editor, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + anchor: 'connected-paragraph', + content: 'fallback content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { + key: 'movie_field', + }, + }, + }, + }, + }, + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( + 'Movie field default value' + ); + await expect( paragraphBlock ).toHaveAttribute( + 'contenteditable', + 'true' + ); + await paragraphBlock.fill( 'new value' ); + // Check that the paragraph content attribute didn't change. + const [ paragraphBlockObject ] = await editor.getBlocks(); + expect( paragraphBlockObject.attributes.content ).toBe( + 'fallback content' + ); + // Check the value of the custom field is being updated by visiting the frontend. + const previewPage = await editor.openPreviewPage(); + await expect( + previewPage.locator( '#connected-paragraph' ) + ).toHaveText( 'new value' ); + } ); + test( 'should be possible to connect movie fields through the attributes panel', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + } ); + await page.getByLabel( 'Attributes options' ).click(); + await page + .getByRole( 'menuitemcheckbox', { + name: 'Show content', + } ) + .click(); + await page + .getByRole( 'button', { + name: 'content', + } ) + .click(); + const movieField = page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'Movie field label' } ); + await expect( movieField ).toBeVisible(); + } ); + } ); +} ); diff --git a/test/gutenberg-test-themes/block-bindings/index.php b/test/gutenberg-test-themes/block-bindings/index.php new file mode 100644 index 00000000000000..0c6530acc1aaff --- /dev/null +++ b/test/gutenberg-test-themes/block-bindings/index.php @@ -0,0 +1,9 @@ +<?php +/** + * Theme index.php file. + * + * @package Gutenberg + */ + +// Silence is golden. +return; diff --git a/test/gutenberg-test-themes/block-bindings/style.css b/test/gutenberg-test-themes/block-bindings/style.css new file mode 100644 index 00000000000000..a6b91a613da6e6 --- /dev/null +++ b/test/gutenberg-test-themes/block-bindings/style.css @@ -0,0 +1,15 @@ +/* +Theme Name: Block Bindings +Theme URI: https://github.com/wordpress/gutenberg/ +Author: the WordPress team +Description: Block bindings test theme. +Requires at least: 6.7 +Tested up to: 6.7 +Requires PHP: 7.2 +Version: 1.0 +License: GNU General Public License v2 or later +License URI: http://www.gnu.org/licenses/gpl-2.0.html +Text Domain: block-bindings +Block bindings WordPress Theme, (C) 2024 WordPress.org +Block bindings is distributed under the terms of the GNU GPL. +*/ diff --git a/test/gutenberg-test-themes/block-bindings/templates/custom-template.html b/test/gutenberg-test-themes/block-bindings/templates/custom-template.html new file mode 100644 index 00000000000000..a8602b1c679a8c --- /dev/null +++ b/test/gutenberg-test-themes/block-bindings/templates/custom-template.html @@ -0,0 +1,3 @@ +<!-- wp:heading --> +<h2 class="wp-block-heading">Custom template</h2> +<!-- /wp:heading --> diff --git a/test/gutenberg-test-themes/block-bindings/templates/index.html b/test/gutenberg-test-themes/block-bindings/templates/index.html new file mode 100644 index 00000000000000..ab136ac8df9a7d --- /dev/null +++ b/test/gutenberg-test-themes/block-bindings/templates/index.html @@ -0,0 +1,8 @@ +<!-- wp:query {"queryId":1,"query":{"offset":0,"postType":"post","order":"desc","orderBy":"date","author":"","search":"","sticky":""}} --> +<div class="wp-block-query"> + <!-- wp:post-template --> + <!-- wp:post-title {"isLink":true} /--> + <!-- wp:post-excerpt /--> + <!-- /wp:post-template --> +</div> +<!-- /wp:query --> diff --git a/test/gutenberg-test-themes/block-bindings/templates/single-movie.html b/test/gutenberg-test-themes/block-bindings/templates/single-movie.html new file mode 100644 index 00000000000000..cd05d5fe917fea --- /dev/null +++ b/test/gutenberg-test-themes/block-bindings/templates/single-movie.html @@ -0,0 +1,2 @@ +<!-- wp:post-title /--> +<!-- wp:post-content {"layout":{"inherit":true}} /--> diff --git a/test/gutenberg-test-themes/block-bindings/templates/single.html b/test/gutenberg-test-themes/block-bindings/templates/single.html new file mode 100644 index 00000000000000..cd05d5fe917fea --- /dev/null +++ b/test/gutenberg-test-themes/block-bindings/templates/single.html @@ -0,0 +1,2 @@ +<!-- wp:post-title /--> +<!-- wp:post-content {"layout":{"inherit":true}} /--> diff --git a/test/gutenberg-test-themes/block-bindings/theme.json b/test/gutenberg-test-themes/block-bindings/theme.json new file mode 100644 index 00000000000000..c996b014328398 --- /dev/null +++ b/test/gutenberg-test-themes/block-bindings/theme.json @@ -0,0 +1,18 @@ +{ + "$schema": "../../../schemas/json/theme.json", + "version": 3, + "settings": { + "appearanceTools": true, + "layout": { + "contentSize": "840px", + "wideSize": "1100px" + } + }, + "customTemplates": [ + { + "name": "custom-template", + "title": "Custom", + "postTypes": [ "post", "movie" ] + } + ] +} From faa6968936e8d996acafb8fd846d3ca08dad7088 Mon Sep 17 00:00:00 2001 From: Jeff Ong <jonger4@gmail.com> Date: Fri, 27 Sep 2024 14:44:50 -0400 Subject: [PATCH 1007/1908] Remove additional Typeset screen and surface typesets in the typography panel (#65579) * Remove additional Typeset screen and surface typesets in the typography panel. * Merge custom and theme font families in getFontFamilyFromSetting. --- .../global-styles/screen-typeset.js | 42 -------- .../global-styles/screen-typography.js | 4 +- .../global-styles/typeset-button.js | 100 ------------------ .../src/components/global-styles/ui.js | 5 - 4 files changed, 2 insertions(+), 149 deletions(-) delete mode 100644 packages/edit-site/src/components/global-styles/screen-typeset.js delete mode 100644 packages/edit-site/src/components/global-styles/typeset-button.js diff --git a/packages/edit-site/src/components/global-styles/screen-typeset.js b/packages/edit-site/src/components/global-styles/screen-typeset.js deleted file mode 100644 index ce754121dfe1b5..00000000000000 --- a/packages/edit-site/src/components/global-styles/screen-typeset.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { useSelect } from '@wordpress/data'; -import { store as editorStore } from '@wordpress/editor'; -import { __experimentalVStack as VStack } from '@wordpress/components'; - -/** - * Internal dependencies - */ -import TypographyVariations from './variations/variations-typography'; -import ScreenHeader from './header'; -import FontFamilies from './font-families'; - -function ScreenTypeset() { - const fontLibraryEnabled = useSelect( - ( select ) => - select( editorStore ).getEditorSettings().fontLibraryEnabled, - [] - ); - - return ( - <> - <ScreenHeader - title={ __( 'Typesets' ) } - description={ __( - 'Fonts and typographic styling applied across the site.' - ) } - /> - <div className="edit-site-global-styles-screen"> - <VStack spacing={ 7 }> - <TypographyVariations /> - - { fontLibraryEnabled && <FontFamilies /> } - </VStack> - </div> - </> - ); -} - -export default ScreenTypeset; diff --git a/packages/edit-site/src/components/global-styles/screen-typography.js b/packages/edit-site/src/components/global-styles/screen-typography.js index c23592c51a6a2a..70acf9e7ae3d4c 100644 --- a/packages/edit-site/src/components/global-styles/screen-typography.js +++ b/packages/edit-site/src/components/global-styles/screen-typography.js @@ -11,8 +11,8 @@ import { store as editorStore } from '@wordpress/editor'; */ import TypographyElements from './typography-elements'; import ScreenHeader from './header'; +import TypographyVariations from './variations/variations-typography'; import FontSizesCount from './font-sizes/font-sizes-count'; -import TypesetButton from './typeset-button'; import FontFamilies from './font-families'; function ScreenTypography() { @@ -32,7 +32,7 @@ function ScreenTypography() { /> <div className="edit-site-global-styles-screen"> <VStack spacing={ 7 }> - <TypesetButton /> + <TypographyVariations title={ __( 'Typesets' ) } /> { fontLibraryEnabled && <FontFamilies /> } <TypographyElements /> <FontSizesCount /> diff --git a/packages/edit-site/src/components/global-styles/typeset-button.js b/packages/edit-site/src/components/global-styles/typeset-button.js deleted file mode 100644 index bcd450def06f8e..00000000000000 --- a/packages/edit-site/src/components/global-styles/typeset-button.js +++ /dev/null @@ -1,100 +0,0 @@ -/** - * WordPress dependencies - */ -import { isRTL, __ } from '@wordpress/i18n'; -import { - __experimentalItemGroup as ItemGroup, - __experimentalVStack as VStack, - __experimentalHStack as HStack, - FlexItem, -} from '@wordpress/components'; -import { store as coreStore } from '@wordpress/core-data'; -import { useSelect } from '@wordpress/data'; -import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; -import { privateApis as editorPrivateApis } from '@wordpress/editor'; -import { useMemo, useContext } from '@wordpress/element'; -import { Icon, chevronLeft, chevronRight } from '@wordpress/icons'; - -/** - * Internal dependencies - */ -import FontLibraryProvider from './font-library-modal/context'; -import { getFontFamilies } from './utils'; -import { NavigationButtonAsItem } from './navigation-button'; -import Subtitle from './subtitle'; -import { unlock } from '../../lock-unlock'; -import { - filterObjectByProperties, - useCurrentMergeThemeStyleVariationsWithUserConfig, -} from '../../hooks/use-theme-style-variations/use-theme-style-variations-by-property'; - -const { GlobalStylesContext } = unlock( blockEditorPrivateApis ); -const { mergeBaseAndUserConfigs } = unlock( editorPrivateApis ); - -function TypesetButton() { - const propertiesToFilter = [ 'typography' ]; - const typographyVariations = - useCurrentMergeThemeStyleVariationsWithUserConfig( propertiesToFilter ); - const hasTypographyVariations = typographyVariations?.length > 1; - const { base, user: userConfig } = useContext( GlobalStylesContext ); - const config = mergeBaseAndUserConfigs( base, userConfig ); - const allFontFamilies = getFontFamilies( config ); - const hasFonts = - allFontFamilies.filter( ( font ) => font !== null ).length > 0; - const variations = useSelect( ( select ) => { - return select( - coreStore - ).__experimentalGetCurrentThemeGlobalStylesVariations(); - }, [] ); - const userTypographyConfig = filterObjectByProperties( - userConfig, - 'typography' - ); - - const title = useMemo( () => { - if ( Object.keys( userTypographyConfig ).length === 0 ) { - return __( 'Default' ); - } - const activeVariation = variations?.find( ( variation ) => { - return ( - JSON.stringify( - filterObjectByProperties( variation, 'typography' ) - ) === JSON.stringify( userTypographyConfig ) - ); - } ); - if ( activeVariation ) { - return activeVariation.title; - } - return allFontFamilies.map( ( font ) => font?.name ).join( ', ' ); - }, [ allFontFamilies, userTypographyConfig, variations ] ); - - return ( - hasTypographyVariations && - hasFonts && ( - <VStack spacing={ 2 }> - <HStack justify="space-between"> - <Subtitle level={ 3 }>{ __( 'Typeset' ) }</Subtitle> - </HStack> - <ItemGroup isBordered isSeparated> - <NavigationButtonAsItem - path="/typography/typeset" - aria-label={ __( 'Typeset' ) } - > - <HStack direction="row"> - <FlexItem>{ title }</FlexItem> - <Icon - icon={ isRTL() ? chevronLeft : chevronRight } - /> - </HStack> - </NavigationButtonAsItem> - </ItemGroup> - </VStack> - ) - ); -} - -export default ( { ...props } ) => ( - <FontLibraryProvider> - <TypesetButton { ...props } /> - </FontLibraryProvider> -); diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index bc6906a769af48..b1550d2a245131 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -32,7 +32,6 @@ import { } from './screen-block-list'; import ScreenBlock from './screen-block'; import ScreenTypography from './screen-typography'; -import ScreenTypeset from './screen-typeset'; import ScreenTypographyElement from './screen-typography-element'; import FontSize from './font-sizes/font-size'; import FontSizes from './font-sizes/font-sizes'; @@ -312,10 +311,6 @@ function GlobalStylesUI() { <FontSize /> </GlobalStylesNavigationScreen> - <GlobalStylesNavigationScreen path="/typography/typeset"> - <ScreenTypeset /> - </GlobalStylesNavigationScreen> - <GlobalStylesNavigationScreen path="/typography/text"> <ScreenTypographyElement element="text" /> </GlobalStylesNavigationScreen> From 5ac6838a49df476ba0d1aec0c881698c2433c7c4 Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Sat, 28 Sep 2024 15:49:52 +0200 Subject: [PATCH 1008/1908] Use proper named `File` when uploading external images (#65693) --- .../src/components/inserter/media-tab/media-preview.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/inserter/media-tab/media-preview.js b/packages/block-editor/src/components/inserter/media-tab/media-preview.js index a890e5fe8dc132..070a850d430cca 100644 --- a/packages/block-editor/src/components/inserter/media-tab/media-preview.js +++ b/packages/block-editor/src/components/inserter/media-tab/media-preview.js @@ -26,6 +26,7 @@ import { moreVertical, external } from '@wordpress/icons'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as noticesStore } from '@wordpress/notices'; import { isBlobURL } from '@wordpress/blob'; +import { getFilename } from '@wordpress/url'; /** * Internal dependencies @@ -167,8 +168,13 @@ export function MediaPreview( { media, onClick, category } ) { .fetch( url ) .then( ( response ) => response.blob() ) .then( ( blob ) => { + const fileName = getFilename( url ) || 'image.jpg'; + const file = new File( [ blob ], fileName, { + type: blob.type, + } ); + settings.mediaUpload( { - filesList: [ blob ], + filesList: [ file ], additionalData: { caption }, onFileChange( [ img ] ) { if ( isBlobURL( img.url ) ) { From 88d60e4f64b2391ba9e2965a721ade86aec0809b Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Sat, 28 Sep 2024 20:51:04 +0200 Subject: [PATCH 1009/1908] Fix output buffering for cross-origin isolation (#65701) --- lib/experimental/media/load.php | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/lib/experimental/media/load.php b/lib/experimental/media/load.php index 5cb16d84e1d8d9..bcb02accf62a6b 100644 --- a/lib/experimental/media/load.php +++ b/lib/experimental/media/load.php @@ -186,6 +186,24 @@ function gutenberg_rest_get_attachment_filesize( array $post ): ?int { return null; } +/** + * Filters the list of rewrite rules formatted for output to an .htaccess file. + * + * Adds support for serving wasm-vips locally. + * + * @param string $rules mod_rewrite Rewrite rules formatted for .htaccess. + * @return string Filtered rewrite rules. + */ +function gutenberg_filter_mod_rewrite_rules( string $rules ): string { + $rules .= "\n# BEGIN Gutenberg client-side media processing experiment\n" . + "AddType application/wasm wasm\n" . + "# END Gutenberg client-side media processing experiment\n"; + + return $rules; +} + +add_filter( 'mod_rewrite_rules', 'gutenberg_filter_mod_rewrite_rules' ); + /** * Enables cross-origin isolation in the block editor. * @@ -236,16 +254,11 @@ function gutenberg_start_cross_origin_isolation_output_buffer(): void { $coep = $is_safari ? 'require-corp' : 'credentialless'; ob_start( - function ( string $output, ?int $phase ) use ( $coep ): string { - // Only send the header when the buffer is not being cleaned. - if ( ( $phase & PHP_OUTPUT_HANDLER_CLEAN ) === 0 ) { - header( 'Cross-Origin-Opener-Policy: same-origin' ); - header( "Cross-Origin-Embedder-Policy: $coep" ); - - $output = gutenberg_add_crossorigin_attributes( $output ); - } + function ( string $output ) use ( $coep ): string { + header( 'Cross-Origin-Opener-Policy: same-origin' ); + header( "Cross-Origin-Embedder-Policy: $coep" ); - return $output; + return gutenberg_add_crossorigin_attributes( $output ); } ); } From 743144b22de4c972b6b32a628257dda1644178ca Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Sun, 29 Sep 2024 09:05:58 -0700 Subject: [PATCH 1010/1908] =?UTF-8?q?Omit=20meta=20boxes=20on=20=E2=80=9Cd?= =?UTF-8?q?esign=E2=80=9D=20type=20posts=20(#64990)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlinked contributors: smerriman, ericdye, laurelfulford. Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: lgladdy <lgladdy@git.wordpress.org> Co-authored-by: MadtownLems <madtownlems@git.wordpress.org> --- .../edit-post/src/components/layout/index.js | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index e6451c6a4a4082..66fa9dd5d93b8a 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -398,7 +398,7 @@ function Layout( { const shouldIframe = useShouldIframe(); const { createErrorNotice } = useDispatch( noticesStore ); const { - currentPost, + currentPost: { postId: currentPostId, postType: currentPostType }, onNavigateToEntityRecord, onNavigateToPreviousEntityRecord, } = useNavigateToEntityRecord( @@ -406,6 +406,7 @@ function Layout( { initialPostType, 'post-only' ); + const isEditingTemplate = currentPostType === 'wp_template'; const { mode, isFullscreenActive, @@ -415,7 +416,6 @@ function Layout( { isDistractionFree, showMetaBoxes, hasHistory, - isEditingTemplate, isWelcomeGuideVisible, templateId, } = useSelect( @@ -428,7 +428,7 @@ function Layout( { const supportsTemplateMode = settings.supportsTemplateMode; const isViewable = - getPostType( currentPost.postType )?.viewable ?? false; + getPostType( currentPostType )?.viewable ?? false; const canViewTemplate = canUser( 'read', { kind: 'postType', name: 'wp_template', @@ -444,21 +444,19 @@ function Layout( { showIconLabels: get( 'core', 'showIconLabels' ), isDistractionFree: get( 'core', 'distractionFree' ), showMetaBoxes: + ! DESIGN_POST_TYPES.includes( currentPostType ) && select( editorStore ).getRenderingMode() === 'post-only', - isEditingTemplate: - select( editorStore ).getCurrentPostType() === - 'wp_template', isWelcomeGuideVisible: isFeatureActive( 'welcomeGuide' ), templateId: supportsTemplateMode && isViewable && canViewTemplate && - currentPost.postType !== 'wp_template' + ! isEditingTemplate ? getEditedPostTemplateId() : null, }; }, - [ settings.supportsTemplateMode, currentPost.postType ] + [ currentPostType, isEditingTemplate, settings.supportsTemplateMode ] ); // Set the right context for the command palette @@ -568,12 +566,12 @@ function Layout( { <SlotFillProvider> <ErrorBoundary> <CommandMenu /> - <WelcomeGuide postType={ currentPost.postType } /> + <WelcomeGuide postType={ currentPostType } /> <Editor settings={ editorSettings } initialEdits={ initialEdits } - postType={ currentPost.postType } - postId={ currentPost.postId } + postType={ currentPostType } + postId={ currentPostId } templateId={ templateId } className={ className } styles={ styles } @@ -585,7 +583,7 @@ function Layout( { autoFocus={ ! isWelcomeGuideVisible } onActionPerformed={ onActionPerformed } extraSidebarPanels={ - ! isEditingTemplate && <MetaBoxes location="side" /> + showMetaBoxes && <MetaBoxes location="side" /> } extraContent={ ! isDistractionFree && From 66bd5e2273ea7c1d1ae6033b4779ab354013ac6d Mon Sep 17 00:00:00 2001 From: Vicente Canales <1157901+vcanales@users.noreply.github.com> Date: Sun, 29 Sep 2024 21:59:37 -0300 Subject: [PATCH 1011/1908] Revert "Font Library: Group fonts by source (#63211)" (#65590) * Revert "Font Library: Group fonts by source (#63211)" * update typography screen description * update screen description Co-authored-by: vcanales <vcanales@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../components/global-styles/font-families.js | 33 +++---------------- .../global-styles/screen-typography.js | 2 +- 2 files changed, 6 insertions(+), 29 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-families.js b/packages/edit-site/src/components/global-styles/font-families.js index 6a554b136317dd..5332478823c210 100644 --- a/packages/edit-site/src/components/global-styles/font-families.js +++ b/packages/edit-site/src/components/global-styles/font-families.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { __, _x } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; import { __experimentalText as Text, __experimentalItemGroup as ItemGroup, @@ -61,14 +61,9 @@ function FontFamilies() { ) } <VStack spacing={ 4 }> - { themeFonts.length > 0 && ( - <VStack> - <Subtitle level={ 3 }> - { - /* translators: Heading for a list of fonts provided by the theme. */ - _x( 'Theme', 'font source' ) - } - </Subtitle> + { [ ...themeFonts, ...customFonts ].length > 0 && ( + <> + <Subtitle level={ 3 }>{ __( 'Fonts' ) }</Subtitle> <ItemGroup size="large" isBordered isSeparated> { themeFonts.map( ( font ) => ( <FontFamilyItem @@ -77,25 +72,7 @@ function FontFamilies() { /> ) ) } </ItemGroup> - </VStack> - ) } - { customFonts.length > 0 && ( - <VStack> - <Subtitle level={ 3 }> - { - /* translators: Heading for a list of fonts installed by the user. */ - _x( 'Custom', 'font source' ) - } - </Subtitle> - <ItemGroup size="large" isBordered isSeparated> - { customFonts.map( ( font ) => ( - <FontFamilyItem - key={ font.slug } - font={ font } - /> - ) ) } - </ItemGroup> - </VStack> + </> ) } { ! hasFonts && ( <VStack> diff --git a/packages/edit-site/src/components/global-styles/screen-typography.js b/packages/edit-site/src/components/global-styles/screen-typography.js index 70acf9e7ae3d4c..3739e3234258bd 100644 --- a/packages/edit-site/src/components/global-styles/screen-typography.js +++ b/packages/edit-site/src/components/global-styles/screen-typography.js @@ -27,7 +27,7 @@ function ScreenTypography() { <ScreenHeader title={ __( 'Typography' ) } description={ __( - 'Typography styles and the application of those styles on site elements.' + 'Available fonts, typographic styles, and the application of those styles.' ) } /> <div className="edit-site-global-styles-screen"> From 65e7db0eb668c2890728963ed51c78ba174c3325 Mon Sep 17 00:00:00 2001 From: Jason Shoemaker <30575277+spadeshoe@users.noreply.github.com> Date: Sun, 29 Sep 2024 18:01:59 -0700 Subject: [PATCH 1012/1908] updates LayoutTypeSwitcher to use ToggleGroupControl (#65498) * updates LayoutTypeSwitcher to useToggleGroupControl * updates label and corrects LayoutTypeSwitcher component misconfiguration Co-authored-by: spadeshoe <spdft@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/block-editor/src/hooks/layout.js | 29 +++++++++++++---------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/hooks/layout.js b/packages/block-editor/src/hooks/layout.js index 22d916d7b791bf..54a376a0c6a4f7 100644 --- a/packages/block-editor/src/hooks/layout.js +++ b/packages/block-editor/src/hooks/layout.js @@ -11,8 +11,8 @@ import { addFilter } from '@wordpress/hooks'; import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks'; import { useSelect } from '@wordpress/data'; import { - Button, - ButtonGroup, + __experimentalToggleGroupControl as ToggleGroupControl, + __experimentalToggleGroupControlOption as ToggleGroupControlOption, ToggleControl, PanelBody, privateApis as componentsPrivateApis, @@ -315,21 +315,26 @@ export default { function LayoutTypeSwitcher( { type, onChange } ) { return ( - <ButtonGroup> + <ToggleGroupControl + __next40pxDefaultSize + isBlock + label={ __( 'Layout type' ) } + __nextHasNoMarginBottom + hideLabelFromVision + isAdaptiveWidth + value={ type } + onChange={ onChange } + > { getLayoutTypes().map( ( { name, label } ) => { return ( - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + <ToggleGroupControlOption key={ name } - isPressed={ type === name } - onClick={ () => onChange( name ) } - > - { label } - </Button> + value={ name } + label={ label } + /> ); } ) } - </ButtonGroup> + </ToggleGroupControl> ); } From 56f6deb5d31bd68dcfa40b217cfe30107e73468e Mon Sep 17 00:00:00 2001 From: Bernie Reiter <96308+ockham@users.noreply.github.com> Date: Mon, 30 Sep 2024 03:39:17 +0200 Subject: [PATCH 1013/1908] Navigation block: Use `apply_block_hooks_to_content()` (#65703) * Navigation block: Use apply-block-hooks-to-content * WPCS Co-authored-by: ockham <bernhard-reiter@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/block-library/src/navigation/index.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index 10fec84ed59d9c..fa9bb5a56f8012 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -1499,9 +1499,15 @@ function block_core_navigation_mock_parsed_block( $inner_blocks, $post ) { */ function block_core_navigation_insert_hooked_blocks( $inner_blocks, $post ) { $mock_navigation_block = block_core_navigation_mock_parsed_block( $inner_blocks, $post ); - $hooked_blocks = get_hooked_blocks(); - $before_block_visitor = null; - $after_block_visitor = null; + + if ( function_exists( 'apply_block_hooks_to_content' ) ) { + $mock_navigation_block_markup = serialize_block( $mock_navigation_block ); + return apply_block_hooks_to_content( $mock_navigation_block_markup, $post, 'insert_hooked_blocks' ); + } + + $hooked_blocks = get_hooked_blocks(); + $before_block_visitor = null; + $after_block_visitor = null; if ( ! empty( $hooked_blocks ) || has_filter( 'hooked_block_types' ) ) { $before_block_visitor = make_before_block_visitor( $hooked_blocks, $post, 'insert_hooked_blocks' ); From 0ae80bcb8de64df1b5b71d07191802b8c51fbf74 Mon Sep 17 00:00:00 2001 From: Carolina Nymark <myazalea@hotmail.com> Date: Mon, 30 Sep 2024 09:07:44 +0200 Subject: [PATCH 1014/1908] Categories block: Escape label (#65540) * Categories block: Escape label Escape the label attribute before output inside the label HTML element, using esc_html(). * Categories: Switch escaping function Escape the label with wp_kses_post() instead of esc_html to allow some HTML tags and to be consistent with escaping other labels in other blocks. Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- packages/block-library/src/categories/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/categories/index.php b/packages/block-library/src/categories/index.php index e15f662bdfbb9b..60a29713b4660d 100644 --- a/packages/block-library/src/categories/index.php +++ b/packages/block-library/src/categories/index.php @@ -49,7 +49,7 @@ function render_block_core_categories( $attributes, $content, $block ) { $show_label = empty( $attributes['showLabel'] ) ? ' screen-reader-text' : ''; $default_label = $taxonomy->label; - $label_text = ! empty( $attributes['label'] ) ? $attributes['label'] : $default_label; + $label_text = ! empty( $attributes['label'] ) ? wp_kses_post( $attributes['label'] ) : $default_label; $wrapper_markup = '<div %1$s><label class="wp-block-categories__label' . $show_label . '" for="' . esc_attr( $id ) . '">' . $label_text . '</label>%2$s</div>'; $items_markup = wp_dropdown_categories( $args ); $type = 'dropdown'; From cd701e94ceffea7ef2f423274a2f77025bcfa1a6 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Mon, 30 Sep 2024 17:40:32 +1000 Subject: [PATCH 1015/1908] Style book: create static categories (#65430) This commit creates a static category map based on list defined in Style Book: Iterate on presentation and design. #53431. It also: - Sorts examples based on static categories and their subcategories - Introduces simple layout for subcategories (under theme) - Adds unit tests for utils - Converts utils to TypeScript Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: vcanales <vcanales@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../src/components/style-book/categories.ts | 91 ++++++++ .../src/components/style-book/constants.ts | 191 +++++++++++++++ .../src/components/style-book/examples.ts | 63 +++++ .../src/components/style-book/index.js | 221 ++++++------------ .../components/style-book/test/categories.js | 171 ++++++++++++++ .../src/components/style-book/types.ts | 27 +++ test/e2e/specs/site-editor/style-book.spec.js | 3 - 7 files changed, 609 insertions(+), 158 deletions(-) create mode 100644 packages/edit-site/src/components/style-book/categories.ts create mode 100644 packages/edit-site/src/components/style-book/constants.ts create mode 100644 packages/edit-site/src/components/style-book/examples.ts create mode 100644 packages/edit-site/src/components/style-book/test/categories.js create mode 100644 packages/edit-site/src/components/style-book/types.ts diff --git a/packages/edit-site/src/components/style-book/categories.ts b/packages/edit-site/src/components/style-book/categories.ts new file mode 100644 index 00000000000000..2c1b627c6d0c60 --- /dev/null +++ b/packages/edit-site/src/components/style-book/categories.ts @@ -0,0 +1,91 @@ +/** + * WordPress dependencies + */ +import { getCategories } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import type { + BlockExample, + StyleBookCategory, + CategoryExamples, +} from './types'; +import { + STYLE_BOOK_CATEGORIES, + STYLE_BOOK_THEME_SUBCATEGORIES, +} from './constants'; + +/** + * Returns category examples for a given category definition and list of examples. + * @param {StyleBookCategory} categoryDefinition The category definition. + * @param {BlockExample[]} examples An array of block examples. + * @return {CategoryExamples|undefined} An object containing the category examples. + */ +export function getExamplesByCategory( + categoryDefinition: StyleBookCategory, + examples: BlockExample[] +): CategoryExamples | undefined { + if ( ! categoryDefinition?.slug || ! examples?.length ) { + return; + } + + if ( categoryDefinition?.subcategories?.length ) { + return categoryDefinition.subcategories.reduce( + ( acc, subcategoryDefinition ) => { + const subcategoryExamples = getExamplesByCategory( + subcategoryDefinition, + examples + ); + if ( subcategoryExamples ) { + acc.subcategories = [ + ...acc.subcategories, + subcategoryExamples, + ]; + } + return acc; + }, + { + title: categoryDefinition.title, + slug: categoryDefinition.slug, + subcategories: [], + } + ); + } + + const blocksToInclude = categoryDefinition?.blocks || []; + const blocksToExclude = categoryDefinition?.exclude || []; + const categoryExamples = examples.filter( ( example ) => { + return ( + ! blocksToExclude.includes( example.name ) && + ( example.category === categoryDefinition.slug || + blocksToInclude.includes( example.name ) ) + ); + } ); + + if ( ! categoryExamples.length ) { + return; + } + + return { + title: categoryDefinition.title, + slug: categoryDefinition.slug, + examples: categoryExamples, + }; +} + +/** + * Returns category examples for a given category definition and list of examples. + * + * @return {StyleBookCategory[]} An array of top-level category definitions. + */ +export function getTopLevelStyleBookCategories(): StyleBookCategory[] { + const reservedCategories = [ + ...STYLE_BOOK_THEME_SUBCATEGORIES, + ...STYLE_BOOK_CATEGORIES, + ].map( ( { slug } ) => slug ); + const extraCategories = getCategories().filter( + ( { slug } ) => ! reservedCategories.includes( slug ) + ); + return [ ...STYLE_BOOK_CATEGORIES, ...extraCategories ]; +} diff --git a/packages/edit-site/src/components/style-book/constants.ts b/packages/edit-site/src/components/style-book/constants.ts new file mode 100644 index 00000000000000..fc06d8f1409f0d --- /dev/null +++ b/packages/edit-site/src/components/style-book/constants.ts @@ -0,0 +1,191 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { StyleBookCategory } from './types'; + +export const STYLE_BOOK_THEME_SUBCATEGORIES: Omit< + StyleBookCategory, + 'subcategories' +>[] = [ + { + slug: 'site-identity', + title: __( 'Site Identity' ), + blocks: [ 'core/site-logo', 'core/site-title', 'core/site-tagline' ], + }, + { + slug: 'design', + title: __( 'Design' ), + blocks: [ 'core/navigation', 'core/avatar', 'core/post-time-to-read' ], + exclude: [ 'core/home-link', 'core/navigation-link' ], + }, + { + slug: 'posts', + title: __( 'Posts' ), + blocks: [ + 'core/post-title', + 'core/post-excerpt', + 'core/post-author', + 'core/post-author-name', + 'core/post-author-biography', + 'core/post-date', + 'core/post-terms', + 'core/term-description', + 'core/query-title', + 'core/query-no-results', + 'core/query-pagination', + 'core/query-numbers', + ], + }, + { + slug: 'comments', + title: __( 'Comments' ), + blocks: [ + 'core/comments-title', + 'core/comments-pagination', + 'core/comments-pagination-numbers', + 'core/comments', + 'core/comments-author-name', + 'core/comment-content', + 'core/comment-date', + 'core/comment-edit-link', + 'core/comment-reply-link', + 'core/comment-template', + 'core/post-comments-count', + 'core/post-comments-link', + ], + }, +]; + +export const STYLE_BOOK_CATEGORIES: StyleBookCategory[] = [ + { + slug: 'text', + title: __( 'Text' ), + blocks: [ + 'core/post-content', + 'core/home-link', + 'core/navigation-link', + ], + }, + { + slug: 'colors', + title: __( 'Colors' ), + blocks: [ 'custom/colors' ], + }, + { + slug: 'theme', + title: __( 'Theme' ), + subcategories: STYLE_BOOK_THEME_SUBCATEGORIES, + }, + { + slug: 'media', + title: __( 'Media' ), + blocks: [ 'core/post-featured-image' ], + }, + { + slug: 'widgets', + title: __( 'Widgets' ), + blocks: [], + }, + { + slug: 'embed', + title: __( 'Embeds' ), + include: [], + }, +]; + +// The content area of the Style Book is rendered within an iframe so that global styles +// are applied to elements within the entire content area. To support elements that are +// not part of the block previews, such as headings and layout for the block previews, +// additional CSS rules need to be passed into the iframe. These are hard-coded below. +// Note that button styles are unset, and then focus rules from the `Button` component are +// applied to the `button` element, targeted via `.edit-site-style-book__example`. +// This is to ensure that browser default styles for buttons are not applied to the previews. +export const STYLE_BOOK_IFRAME_STYLES = ` + // Forming a "block formatting context" to prevent margin collapsing. + // @see https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context + .is-root-container { + display: flow-root; + } + + body { + position: relative; + padding: 32px !important; + } + + .edit-site-style-book__examples { + max-width: 1200px; + margin: 0 auto; + } + + .edit-site-style-book__example { + max-width: 900px; + border-radius: 2px; + cursor: pointer; + display: flex; + flex-direction: column; + gap: 40px; + padding: 16px; + width: 100%; + box-sizing: border-box; + scroll-margin-top: 32px; + scroll-margin-bottom: 32px; + margin: 0 auto 40px auto; + } + + .edit-site-style-book__example.is-selected { + box-shadow: 0 0 0 1px var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba)); + } + + .edit-site-style-book__example:focus:not(:disabled) { + box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba)); + outline: 3px solid transparent; + } + + .edit-site-style-book__examples.is-wide .edit-site-style-book__example { + flex-direction: row; + } + + .edit-site-style-book__subcategory-title, + .edit-site-style-book__example-title { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; + font-size: 11px; + font-weight: 500; + line-height: normal; + margin: 0; + text-align: left; + text-transform: uppercase; + } + + .edit-site-style-book__subcategory-title { + font-size: 16px; + margin-bottom: 40px; + border-bottom: 1px solid #ddd; + padding-bottom: 8px; + } + + .edit-site-style-book__examples.is-wide .edit-site-style-book__example-title { + text-align: right; + width: 120px; + } + + .edit-site-style-book__example-preview { + width: 100%; + } + + .edit-site-style-book__example-preview .block-editor-block-list__insertion-point, + .edit-site-style-book__example-preview .block-list-appender { + display: none; + } + + .edit-site-style-book__example-preview .is-root-container > .wp-block:first-child { + margin-top: 0; + } + .edit-site-style-book__example-preview .is-root-container > .wp-block:last-child { + margin-bottom: 0; + } +`; diff --git a/packages/edit-site/src/components/style-book/examples.ts b/packages/edit-site/src/components/style-book/examples.ts new file mode 100644 index 00000000000000..80807b10374c68 --- /dev/null +++ b/packages/edit-site/src/components/style-book/examples.ts @@ -0,0 +1,63 @@ +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; +import { + getBlockType, + getBlockTypes, + getBlockFromExample, + createBlock, +} from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import type { BlockExample } from './types'; + +/** + * Returns a list of examples for registered block types. + * + * @return {BlockExample[]} An array of block examples. + */ +export function getExamples(): BlockExample[] { + const nonHeadingBlockExamples = getBlockTypes() + .filter( ( blockType ) => { + const { name, example, supports } = blockType; + return ( + name !== 'core/heading' && + !! example && + supports.inserter !== false + ); + } ) + .map( ( blockType ) => ( { + name: blockType.name, + title: blockType.title, + category: blockType.category, + blocks: getBlockFromExample( blockType.name, blockType.example ), + } ) ); + const isHeadingBlockRegistered = !! getBlockType( 'core/heading' ); + + if ( ! isHeadingBlockRegistered ) { + return nonHeadingBlockExamples; + } + + // Use our own example for the Heading block so that we can show multiple + // heading levels. + const headingsExample = { + name: 'core/heading', + title: __( 'Headings' ), + category: 'text', + blocks: [ 1, 2, 3, 4, 5, 6 ].map( ( level ) => { + return createBlock( 'core/heading', { + content: sprintf( + // translators: %d: heading level e.g: "1", "2", "3" + __( 'Heading %d' ), + level + ), + level, + } ); + } ), + }; + + return [ headingsExample, ...nonHeadingBlockExamples ]; +} diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 64503dcf7a6dbb..e68474e19f407f 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -12,13 +12,6 @@ import { privateApis as componentsPrivateApis, } from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; -import { - getCategories, - getBlockType, - getBlockTypes, - getBlockFromExample, - createBlock, -} from '@wordpress/blocks'; import { BlockList, privateApis as blockEditorPrivateApis, @@ -37,6 +30,12 @@ import { ENTER, SPACE } from '@wordpress/keycodes'; */ import { unlock } from '../../lock-unlock'; import EditorCanvasContainer from '../editor-canvas-container'; +import { STYLE_BOOK_IFRAME_STYLES } from './constants'; +import { + getExamplesByCategory, + getTopLevelStyleBookCategories, +} from './categories'; +import { getExamples } from './examples'; const { ExperimentalBlockEditorProvider, @@ -48,126 +47,10 @@ const { mergeBaseAndUserConfigs } = unlock( editorPrivateApis ); const { Tabs } = unlock( componentsPrivateApis ); -// The content area of the Style Book is rendered within an iframe so that global styles -// are applied to elements within the entire content area. To support elements that are -// not part of the block previews, such as headings and layout for the block previews, -// additional CSS rules need to be passed into the iframe. These are hard-coded below. -// Note that button styles are unset, and then focus rules from the `Button` component are -// applied to the `button` element, targeted via `.edit-site-style-book__example`. -// This is to ensure that browser default styles for buttons are not applied to the previews. -const STYLE_BOOK_IFRAME_STYLES = ` - .edit-site-style-book__examples { - max-width: 900px; - margin: 0 auto; - } - - .edit-site-style-book__example { - border-radius: 2px; - cursor: pointer; - display: flex; - flex-direction: column; - gap: 40px; - margin-bottom: 40px; - padding: 16px; - width: 100%; - box-sizing: border-box; - scroll-margin-top: 32px; - scroll-margin-bottom: 32px; - } - - .edit-site-style-book__example.is-selected { - box-shadow: 0 0 0 1px var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba)); - } - - .edit-site-style-book__example:focus:not(:disabled) { - box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba)); - outline: 3px solid transparent; - } - - .edit-site-style-book__examples.is-wide .edit-site-style-book__example { - flex-direction: row; - } - - .edit-site-style-book__example-title { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; - font-size: 11px; - font-weight: 500; - line-height: normal; - margin: 0; - text-align: left; - text-transform: uppercase; - } - - .edit-site-style-book__examples.is-wide .edit-site-style-book__example-title { - text-align: right; - width: 120px; - } - - .edit-site-style-book__example-preview { - width: 100%; - } - - .edit-site-style-book__example-preview .block-editor-block-list__insertion-point, - .edit-site-style-book__example-preview .block-list-appender { - display: none; - } - - .edit-site-style-book__example-preview .is-root-container > .wp-block:first-child { - margin-top: 0; - } - .edit-site-style-book__example-preview .is-root-container > .wp-block:last-child { - margin-bottom: 0; - } -`; - function isObjectEmpty( object ) { return ! object || Object.keys( object ).length === 0; } -function getExamples() { - const nonHeadingBlockExamples = getBlockTypes() - .filter( ( blockType ) => { - const { name, example, supports } = blockType; - return ( - name !== 'core/heading' && - !! example && - supports.inserter !== false - ); - } ) - .map( ( blockType ) => ( { - name: blockType.name, - title: blockType.title, - category: blockType.category, - blocks: getBlockFromExample( blockType.name, blockType.example ), - } ) ); - - const isHeadingBlockRegistered = !! getBlockType( 'core/heading' ); - - if ( ! isHeadingBlockRegistered ) { - return nonHeadingBlockExamples; - } - - // Use our own example for the Heading block so that we can show multiple - // heading levels. - const headingsExample = { - name: 'core/heading', - title: __( 'Headings' ), - category: 'text', - blocks: [ 1, 2, 3, 4, 5, 6 ].map( ( level ) => { - return createBlock( 'core/heading', { - content: sprintf( - // translators: %d: heading level e.g: "1", "2", "3" - __( 'Heading %d' ), - level - ), - level, - } ); - } ), - }; - - return [ headingsExample, ...nonHeadingBlockExamples ]; -} - function StyleBook( { enableResizing = true, isSelected, @@ -184,17 +67,11 @@ function StyleBook( { const [ examples ] = useState( getExamples ); const tabs = useMemo( () => - getCategories() - .filter( ( category ) => - examples.some( - ( example ) => example.category === category.slug - ) + getTopLevelStyleBookCategories().filter( ( category ) => + examples.some( + ( example ) => example.category === category.slug ) - .map( ( category ) => ( { - name: category.slug, - title: category.title, - icon: category.icon, - } ) ), + ), [ examples ] ); const { base: baseConfig } = useContext( GlobalStylesContext ); @@ -248,8 +125,8 @@ function StyleBook( { <Tabs.TabList> { tabs.map( ( tab ) => ( <Tabs.Tab - tabId={ tab.name } - key={ tab.name } + tabId={ tab.slug } + key={ tab.slug } > { tab.title } </Tabs.Tab> @@ -257,12 +134,12 @@ function StyleBook( { </Tabs.TabList> { tabs.map( ( tab ) => ( <Tabs.TabPanel - key={ tab.name } - tabId={ tab.name } + key={ tab.slug } + tabId={ tab.slug } focusable={ false } > <StyleBookBody - category={ tab.name } + category={ tab.slug } examples={ examples } isSelected={ isSelected } onSelect={ onSelect } @@ -329,10 +206,6 @@ const StyleBookBody = ( { readonly: true, }; - const buttonModeStyles = onClick - ? 'body { cursor: pointer; } body * { pointer-events: none; }' - : ''; - return ( <Iframe className={ clsx( 'edit-site-style-book__iframe', { @@ -345,14 +218,9 @@ const StyleBookBody = ( { > <EditorStyles styles={ settings.styles } /> <style> - { - // Forming a "block formatting context" to prevent margin collapsing. - // @see https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context - `.is-root-container { display: flow-root; } - body { position: relative; padding: 32px !important; }` + - STYLE_BOOK_IFRAME_STYLES + - buttonModeStyles - } + { STYLE_BOOK_IFRAME_STYLES } + { !! onClick && + 'body { cursor: pointer; } body * { pointer-events: none; }' } </style> <Examples className={ clsx( 'edit-site-style-book__examples', { @@ -379,6 +247,16 @@ const StyleBookBody = ( { const Examples = memo( ( { className, examples, category, label, isSelected, onSelect } ) => { + const categoryDefinition = category + ? getTopLevelStyleBookCategories().find( + ( _category ) => _category.slug === category + ) + : null; + + const filteredExamples = categoryDefinition + ? getExamplesByCategory( categoryDefinition, examples ) + : { examples }; + return ( <Composite orientation="vertical" @@ -386,11 +264,8 @@ const Examples = memo( aria-label={ label } role="grid" > - { examples - .filter( ( example ) => - category ? example.category === category : true - ) - .map( ( example ) => ( + { !! filteredExamples?.examples?.length && + filteredExamples.examples.map( ( example ) => ( <Example key={ example.name } id={ `example-${ example.name }` } @@ -402,11 +277,47 @@ const Examples = memo( } } /> ) ) } + { !! filteredExamples?.subcategories?.length && + filteredExamples.subcategories.map( ( subcategory ) => ( + <Composite.Group + className="edit-site-style-book__subcategory" + key={ `subcategory-${ subcategory.slug }` } + > + <Composite.GroupLabel> + <h2 className="edit-site-style-book__subcategory-title"> + { subcategory.title } + </h2> + </Composite.GroupLabel> + <Subcategory + examples={ subcategory.examples } + isSelected={ isSelected } + onSelect={ onSelect } + /> + </Composite.Group> + ) ) } </Composite> ); } ); +const Subcategory = ( { examples, isSelected, onSelect } ) => { + return ( + !! examples?.length && + examples.map( ( example ) => ( + <Example + key={ example.name } + id={ `example-${ example.name }` } + title={ example.title } + blocks={ example.blocks } + isSelected={ isSelected( example.name ) } + onClick={ () => { + onSelect?.( example.name ); + } } + /> + ) ) + ); +}; + const Example = ( { id, title, blocks, isSelected, onClick } ) => { const originalSettings = useSelect( ( select ) => select( blockEditorStore ).getSettings(), diff --git a/packages/edit-site/src/components/style-book/test/categories.js b/packages/edit-site/src/components/style-book/test/categories.js new file mode 100644 index 00000000000000..5629689e260f89 --- /dev/null +++ b/packages/edit-site/src/components/style-book/test/categories.js @@ -0,0 +1,171 @@ +/** + * Internal dependencies + */ +import { + getExamplesByCategory, + getTopLevelStyleBookCategories, +} from '../categories'; +import { STYLE_BOOK_CATEGORIES } from '../constants'; + +jest.mock( '@wordpress/blocks', () => { + return { + getCategories() { + return [ + { + slug: 'text', + title: 'Text Registered', + icon: 'text', + }, + { + slug: 'design', + title: 'Design Registered', + icon: 'design', + }, + { + slug: 'funky', + title: 'Funky', + icon: 'funky', + }, + ]; + }, + }; +} ); + +// Fixtures +const exampleThemeBlocks = [ + { + name: 'core/post-content', + title: 'Post Content', + category: 'theme', + }, + { + name: 'core/post-terms', + title: 'Post Terms', + category: 'theme', + }, + { + name: 'core/home-link', + title: 'Home Link', + category: 'design', + }, + { + name: 'custom/colors', + title: 'Colors', + category: 'colors', + }, + { + name: 'core/site-logo', + title: 'Site Logo', + category: 'theme', + }, + { + name: 'core/site-title', + title: 'Site Title', + category: 'theme', + }, + { + name: 'core/site-tagline', + title: 'Site Tagline', + category: 'theme', + }, + { + name: 'core/group', + title: 'Group', + category: 'design', + }, + { + name: 'core/comments-pagination-numbers', + title: 'Comments Page Numbers', + category: 'theme', + }, + { + name: 'core/post-featured-image', + title: 'Featured Image', + category: 'theme', + }, +]; + +describe( 'utils', () => { + describe( 'getTopLevelStyleBookCategories', () => { + it( 'returns theme subcategories examples', () => { + expect( getTopLevelStyleBookCategories() ).toEqual( [ + ...STYLE_BOOK_CATEGORIES, + { + slug: 'funky', + title: 'Funky', + icon: 'funky', + }, + ] ); + } ); + } ); + + describe( 'getExamplesByCategory', () => { + it( 'returns theme subcategories examples', () => { + const themeCategory = STYLE_BOOK_CATEGORIES.find( + ( category ) => category.slug === 'theme' + ); + const themeCategoryExamples = getExamplesByCategory( + themeCategory, + exampleThemeBlocks + ); + + expect( themeCategoryExamples.slug ).toEqual( 'theme' ); + + const siteIdentity = themeCategoryExamples.subcategories.find( + ( subcategory ) => subcategory.slug === 'site-identity' + ); + expect( siteIdentity ).toEqual( { + title: 'Site Identity', + slug: 'site-identity', + examples: [ + { + name: 'core/site-logo', + title: 'Site Logo', + category: 'theme', + }, + { + name: 'core/site-title', + title: 'Site Title', + category: 'theme', + }, + { + name: 'core/site-tagline', + title: 'Site Tagline', + category: 'theme', + }, + ], + } ); + + const design = themeCategoryExamples.subcategories.find( + ( subcategory ) => subcategory.slug === 'design' + ); + expect( design ).toEqual( { + title: 'Design', + slug: 'design', + examples: [ + { + name: 'core/group', + title: 'Group', + category: 'design', + }, + ], + } ); + + const posts = themeCategoryExamples.subcategories.find( + ( subcategory ) => subcategory.slug === 'posts' + ); + + expect( posts ).toEqual( { + title: 'Posts', + slug: 'posts', + examples: [ + { + name: 'core/post-terms', + title: 'Post Terms', + category: 'theme', + }, + ], + } ); + } ); + } ); +} ); diff --git a/packages/edit-site/src/components/style-book/types.ts b/packages/edit-site/src/components/style-book/types.ts new file mode 100644 index 00000000000000..4729b38b1b2bb1 --- /dev/null +++ b/packages/edit-site/src/components/style-book/types.ts @@ -0,0 +1,27 @@ +type Block = { + name: string; + attributes: Record< string, unknown >; + innerBlocks?: Block[]; +}; + +export type StyleBookCategory = { + title: string; + slug: string; + blocks?: string[]; + exclude?: string[]; + subcategories?: StyleBookCategory[]; +}; + +export type BlockExample = { + name: string; + title: string; + category: string; + blocks: Block | Block[]; +}; + +export type CategoryExamples = { + title: string; + slug: string; + examples?: BlockExample[]; + subcategories?: CategoryExamples[]; +}; diff --git a/test/e2e/specs/site-editor/style-book.spec.js b/test/e2e/specs/site-editor/style-book.spec.js index c4e153e9b5e2fa..3f871d28ef941b 100644 --- a/test/e2e/specs/site-editor/style-book.spec.js +++ b/test/e2e/specs/site-editor/style-book.spec.js @@ -42,9 +42,6 @@ test.describe( 'Style Book', () => { test( 'should have tabs containing block examples', async ( { page } ) => { await expect( page.locator( 'role=tab[name="Text"i]' ) ).toBeVisible(); await expect( page.locator( 'role=tab[name="Media"i]' ) ).toBeVisible(); - await expect( - page.locator( 'role=tab[name="Design"i]' ) - ).toBeVisible(); await expect( page.locator( 'role=tab[name="Widgets"i]' ) ).toBeVisible(); From 5e47d4838b5b0c910ea3ff3e3679d57ae97a7cd1 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 30 Sep 2024 18:17:02 +0900 Subject: [PATCH 1016/1908] SelectControl: Add story for `prefix` slot (#65730) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/select-control/stories/index.story.tsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/components/src/select-control/stories/index.story.tsx b/packages/components/src/select-control/stories/index.story.tsx index 018f519e6b6d43..5e57a4eaecd5ab 100644 --- a/packages/components/src/select-control/stories/index.story.tsx +++ b/packages/components/src/select-control/stories/index.story.tsx @@ -12,6 +12,7 @@ import { useState } from '@wordpress/element'; * Internal dependencies */ import SelectControl from '../'; +import { InputControlPrefixWrapper } from '../../input-control/input-prefix-wrapper'; const meta: Meta< typeof SelectControl > = { title: 'Components/SelectControl', @@ -64,6 +65,7 @@ const SelectControlWithState: StoryFn< typeof SelectControl > = ( props ) => { export const Default = SelectControlWithState.bind( {} ); Default.args = { __nextHasNoMarginBottom: true, + label: 'Label', options: [ { value: '', label: 'Select an Option', disabled: true }, { value: 'a', label: 'Option A' }, @@ -76,7 +78,6 @@ export const WithLabelAndHelpText = SelectControlWithState.bind( {} ); WithLabelAndHelpText.args = { ...Default.args, help: 'Help text to explain the select control.', - label: 'Value', }; /** @@ -86,6 +87,7 @@ WithLabelAndHelpText.args = { export const WithCustomChildren = SelectControlWithState.bind( {} ); WithCustomChildren.args = { __nextHasNoMarginBottom: true, + label: 'Label', children: ( <> <option value="option-1">Option 1</option> @@ -104,8 +106,19 @@ WithCustomChildren.args = { ), }; +/** + * By default, the prefix is aligned with the edge of the input border, with no padding. + * If you want to apply standard padding in accordance with the size variant, wrap the element in the `<InputControlPrefixWrapper>` component. + */ +export const WithPrefix = SelectControlWithState.bind( {} ); +WithPrefix.args = { + ...Default.args, + prefix: <InputControlPrefixWrapper>Prefix:</InputControlPrefixWrapper>, +}; + export const Minimal = SelectControlWithState.bind( {} ); Minimal.args = { ...Default.args, variant: 'minimal', + hideLabelFromVision: true, }; From 6f8a67aa0936b9c66138bf072cc5d00179cc7780 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 30 Sep 2024 18:44:16 +0900 Subject: [PATCH 1017/1908] Button: Add `__next40pxDefaultSize` in dataviews, reusable-blocks, etc. (#65715) * Fix in Dataforms layouts * Fix in Patterns header * Fix in Patterns import popover * Fix in nux * Fix in ReusableBlockConvertButton * Update snapshot Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../dataviews/src/dataforms-layouts/panel/index.tsx | 4 +--- .../src/dataforms-layouts/panel/style.scss | 13 ------------- .../src/components/import-dropdown/index.js | 4 ++-- .../src/components/import-dropdown/style.scss | 5 +++++ .../src/components/import-form/index.js | 3 +-- .../src/components/import-form/style.scss | 1 - packages/list-reusable-blocks/src/style.scss | 4 ---- packages/nux/src/components/dot-tip/index.js | 6 ++---- .../dot-tip/test/__snapshots__/index.js.snap | 4 ++-- .../reusable-block-convert-button.js | 6 ++---- 10 files changed, 15 insertions(+), 35 deletions(-) diff --git a/packages/dataviews/src/dataforms-layouts/panel/index.tsx b/packages/dataviews/src/dataforms-layouts/panel/index.tsx index 9f118584998bd3..94e107dc20665a 100644 --- a/packages/dataviews/src/dataforms-layouts/panel/index.tsx +++ b/packages/dataviews/src/dataforms-layouts/panel/index.tsx @@ -44,12 +44,10 @@ function DropdownHeader( { <Spacer /> { onClose && ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - className="dataforms-layouts-panel__dropdown-header-action" label={ __( 'Close' ) } icon={ closeSmall } onClick={ onClose } + size="small" /> ) } </HStack> diff --git a/packages/dataviews/src/dataforms-layouts/panel/style.scss b/packages/dataviews/src/dataforms-layouts/panel/style.scss index e6840bed9d6e0b..ae69c4ff45243a 100644 --- a/packages/dataviews/src/dataforms-layouts/panel/style.scss +++ b/packages/dataviews/src/dataforms-layouts/panel/style.scss @@ -44,16 +44,3 @@ .dataforms-layouts-panel__dropdown-header { margin-bottom: $grid-unit-20; } - -[class].dataforms-layouts-panel__dropdown-header-action { - height: $icon-size; - - &.has-icon { - min-width: $icon-size; - padding: 0; - } - - &:not(.has-icon) { - text-decoration: underline; - } -} diff --git a/packages/list-reusable-blocks/src/components/import-dropdown/index.js b/packages/list-reusable-blocks/src/components/import-dropdown/index.js index d20ba9fcf10999..fdad08f80d213c 100644 --- a/packages/list-reusable-blocks/src/components/import-dropdown/index.js +++ b/packages/list-reusable-blocks/src/components/import-dropdown/index.js @@ -17,8 +17,8 @@ function ImportDropdown( { onUpload } ) { contentClassName="list-reusable-blocks-import-dropdown__content" renderToggle={ ( { isOpen, onToggle } ) => ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + size="compact" + className="list-reusable-blocks-import-dropdown__button" aria-expanded={ isOpen } onClick={ onToggle } variant="primary" diff --git a/packages/list-reusable-blocks/src/components/import-dropdown/style.scss b/packages/list-reusable-blocks/src/components/import-dropdown/style.scss index 8c2dc9c94bd71f..abef499a63b298 100644 --- a/packages/list-reusable-blocks/src/components/import-dropdown/style.scss +++ b/packages/list-reusable-blocks/src/components/import-dropdown/style.scss @@ -1,3 +1,8 @@ .list-reusable-blocks-import-dropdown__content .components-popover__content { padding: 10px; } + +[class].list-reusable-blocks-import-dropdown__button { + // Todo: Make core button height and gutenberg button height equal. + height: 30px; +} diff --git a/packages/list-reusable-blocks/src/components/import-form/index.js b/packages/list-reusable-blocks/src/components/import-form/index.js index b78869df61eb6c..ba6cffb956f04e 100644 --- a/packages/list-reusable-blocks/src/components/import-form/index.js +++ b/packages/list-reusable-blocks/src/components/import-form/index.js @@ -84,8 +84,7 @@ function ImportForm( { instanceId, onUpload } ) { </label> <input id={ inputId } type="file" onChange={ onChangeFile } /> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize type="submit" isBusy={ isLoading } accessibleWhenDisabled diff --git a/packages/list-reusable-blocks/src/components/import-form/style.scss b/packages/list-reusable-blocks/src/components/import-form/style.scss index 844130b7c5914a..e72d63fd2a4903 100644 --- a/packages/list-reusable-blocks/src/components/import-form/style.scss +++ b/packages/list-reusable-blocks/src/components/import-form/style.scss @@ -5,7 +5,6 @@ .list-reusable-blocks-import-form__button { margin-top: 10px; - margin-bottom: 10px; float: right; } diff --git a/packages/list-reusable-blocks/src/style.scss b/packages/list-reusable-blocks/src/style.scss index ad85c700586099..6767bd0bd7e158 100644 --- a/packages/list-reusable-blocks/src/style.scss +++ b/packages/list-reusable-blocks/src/style.scss @@ -6,10 +6,6 @@ align-items: center; position: relative; top: -3px; - // Todo: Make core button height and gutenberg button height equal. - .components-button { - height: 26px; - } } @include wordpress-admin-schemes(); diff --git a/packages/nux/src/components/dot-tip/index.js b/packages/nux/src/components/dot-tip/index.js index 80db7568b351b1..e2768789ad1fda 100644 --- a/packages/nux/src/components/dot-tip/index.js +++ b/packages/nux/src/components/dot-tip/index.js @@ -57,8 +57,7 @@ export function DotTip( { <p>{ children }</p> <p> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="link" onClick={ onDismiss } > @@ -66,8 +65,7 @@ export function DotTip( { </Button> </p> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + size="small" className="nux-dot-tip__disable" icon={ close } label={ __( 'Disable tips' ) } diff --git a/packages/nux/src/components/dot-tip/test/__snapshots__/index.js.snap b/packages/nux/src/components/dot-tip/test/__snapshots__/index.js.snap index 90edc7a19990a0..a160b7f6555768 100644 --- a/packages/nux/src/components/dot-tip/test/__snapshots__/index.js.snap +++ b/packages/nux/src/components/dot-tip/test/__snapshots__/index.js.snap @@ -19,7 +19,7 @@ exports[`DotTip should render correctly 1`] = ` </p> <p> <button - class="components-button is-link" + class="components-button is-next-40px-default-size is-link" type="button" > Got it @@ -27,7 +27,7 @@ exports[`DotTip should render correctly 1`] = ` </p> <button aria-label="Disable tips" - class="components-button nux-dot-tip__disable has-icon" + class="components-button nux-dot-tip__disable is-small has-icon" type="button" > <svg diff --git a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js index bceca4876654cf..e0d8592df4d8c3 100644 --- a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js +++ b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js @@ -191,8 +191,7 @@ export default function ReusableBlockConvertButton( { /> <HStack justify="right"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="tertiary" onClick={ () => { setIsModalOpen( false ); @@ -203,8 +202,7 @@ export default function ReusableBlockConvertButton( { </Button> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" type="submit" > From 20dc9b7d02d322fa66ce73b6e2bfef421d28c8cc Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Mon, 30 Sep 2024 12:46:57 +0300 Subject: [PATCH 1018/1908] Fix useInstanceId hook references (#65733) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/block-editor/src/hooks/duotone.js | 5 ++++- packages/block-editor/src/hooks/layout-child.js | 5 ++++- packages/block-editor/src/hooks/position.js | 5 ++++- packages/components/src/autocomplete/index.tsx | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index 51130ccb9ec2a4..dbd47831c42668 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -314,8 +314,11 @@ function useDuotoneStyles( { }, [ isValidFilter, blockElement, colors ] ); } +// Used for generating the instance ID +const DUOTONE_BLOCK_PROPS_REFERENCE = {}; + function useBlockProps( { clientId, name, style } ) { - const id = useInstanceId( useBlockProps ); + const id = useInstanceId( DUOTONE_BLOCK_PROPS_REFERENCE ); const selector = useMemo( () => { const blockType = getBlockType( name ); diff --git a/packages/block-editor/src/hooks/layout-child.js b/packages/block-editor/src/hooks/layout-child.js index 8beb50c1b82849..558d5e2cc626bf 100644 --- a/packages/block-editor/src/hooks/layout-child.js +++ b/packages/block-editor/src/hooks/layout-child.js @@ -17,6 +17,9 @@ import { GridItemMovers, } from '../components/grid'; +// Used for generating the instance ID +const LAYOUT_CHILD_BLOCK_PROPS_REFERENCE = {}; + function useBlockPropsChildLayoutStyles( { style } ) { const shouldRenderChildLayoutStyles = useSelect( ( select ) => { return ! select( blockEditorStore ).getSettings().disableLayoutStyles; @@ -32,7 +35,7 @@ function useBlockPropsChildLayoutStyles( { style } ) { } = layout; const parentLayout = useLayout() || {}; const { columnCount, minimumColumnWidth } = parentLayout; - const id = useInstanceId( useBlockPropsChildLayoutStyles ); + const id = useInstanceId( LAYOUT_CHILD_BLOCK_PROPS_REFERENCE ); const selector = `.wp-container-content-${ id }`; // Check that the grid layout attributes are of the correct type, so that we don't accidentally diff --git a/packages/block-editor/src/hooks/position.js b/packages/block-editor/src/hooks/position.js index 95a9c2198e4c71..bf1b730cd67d1a 100644 --- a/packages/block-editor/src/hooks/position.js +++ b/packages/block-editor/src/hooks/position.js @@ -310,6 +310,9 @@ export default { }, }; +// Used for generating the instance ID +const POSITION_BLOCK_PROPS_REFERENCE = {}; + function useBlockProps( { name, style } ) { const hasPositionBlockSupport = hasBlockSupport( name, @@ -318,7 +321,7 @@ function useBlockProps( { name, style } ) { const isPositionDisabled = useIsPositionDisabled( { name } ); const allowPositionStyles = hasPositionBlockSupport && ! isPositionDisabled; - const id = useInstanceId( useBlockProps ); + const id = useInstanceId( POSITION_BLOCK_PROPS_REFERENCE ); // Higher specificity to override defaults in editor UI. const positionSelector = `.wp-container-${ id }.wp-container-${ id }`; diff --git a/packages/components/src/autocomplete/index.tsx b/packages/components/src/autocomplete/index.tsx index ef0fefe199c2e3..ad930d3affdd14 100644 --- a/packages/components/src/autocomplete/index.tsx +++ b/packages/components/src/autocomplete/index.tsx @@ -72,6 +72,9 @@ const getNodeText = ( node: React.ReactNode ): string => { const EMPTY_FILTERED_OPTIONS: KeyedOption[] = []; +// Used for generating the instance ID +const AUTOCOMPLETE_HOOK_REFERENCE = {}; + export function useAutocomplete( { record, onChange, @@ -79,7 +82,7 @@ export function useAutocomplete( { completers, contentRef, }: UseAutocompleteProps ) { - const instanceId = useInstanceId( useAutocomplete ); + const instanceId = useInstanceId( AUTOCOMPLETE_HOOK_REFERENCE ); const [ selectedIndex, setSelectedIndex ] = useState( 0 ); const [ filteredOptions, setFilteredOptions ] = useState< From ad88b2271207264c1503f692222ba814daebfcf4 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:55:41 +0300 Subject: [PATCH 1019/1908] Edit Post: Remove unnecessary effect in InitPatternModal (#65734) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../src/components/init-pattern-modal/index.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/edit-post/src/components/init-pattern-modal/index.js b/packages/edit-post/src/components/init-pattern-modal/index.js index 5b94e838dbcad2..6c7cd269a27de9 100644 --- a/packages/edit-post/src/components/init-pattern-modal/index.js +++ b/packages/edit-post/src/components/init-pattern-modal/index.js @@ -11,12 +11,11 @@ import { ToggleControl, TextControl, } from '@wordpress/components'; -import { useEffect, useState } from '@wordpress/element'; +import { useState } from '@wordpress/element'; import { store as editorStore } from '@wordpress/editor'; export default function InitPatternModal() { const { editPost } = useDispatch( editorStore ); - const [ isModalOpen, setIsModalOpen ] = useState( false ); const [ syncType, setSyncType ] = useState( undefined ); const [ title, setTitle ] = useState( '' ); @@ -28,14 +27,9 @@ export default function InitPatternModal() { isNewPost: isCleanNewPost(), }; }, [] ); - - useEffect( () => { - if ( isNewPost && postType === 'wp_block' ) { - setIsModalOpen( true ); - } - // We only want the modal to open when the page is first loaded. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [] ); + const [ isModalOpen, setIsModalOpen ] = useState( () => + isNewPost && postType === 'wp_block' ? true : false + ); if ( postType !== 'wp_block' || ! isNewPost ) { return null; From 22e19b477428b586e851bc8b4ccf769254de00f2 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Mon, 30 Sep 2024 12:59:53 +0200 Subject: [PATCH 1020/1908] Block bindings: Refactor passing select and dispatch instead of full Registry. (#65710) * Try use select and dispatch instead of registry * Pass `select` to `canUserEditValue` * Pass `select` to `getFieldsList` * Fix `setValues` --------- Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> --- .../src/components/rich-text/index.js | 13 +- .../block-editor/src/hooks/block-bindings.js | 9 +- .../src/hooks/use-bindings-attributes.js | 129 +++++++++--------- packages/block-library/src/button/edit.js | 5 +- packages/block-library/src/image/edit.js | 5 +- packages/block-library/src/image/image.js | 9 +- .../e2e-tests/plugins/block-bindings/index.js | 4 +- .../editor/src/bindings/pattern-overrides.js | 57 ++++---- packages/editor/src/bindings/post-meta.js | 58 ++++---- 9 files changed, 138 insertions(+), 151 deletions(-) diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 83cf5e564c68be..26cd2a97b515ed 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -188,7 +188,7 @@ export function RichTextWrapper( const _disableBoundBlock = ! blockBindingsSource?.canUserEditValue?.( { - registry, + select, context: blockBindingsContext, args: relatedBinding.args, } ); @@ -206,7 +206,7 @@ export function RichTextWrapper( const { getBlockAttributes } = select( blockEditorStore ); const blockAttributes = getBlockAttributes( clientId ); const fieldsList = blockBindingsSource?.getFieldsList?.( { - registry, + select, context: blockBindingsContext, } ); const bindingKey = @@ -235,14 +235,7 @@ export function RichTextWrapper( bindingsLabel: _bindingsLabel, }; }, - [ - blockBindings, - identifier, - blockName, - blockContext, - registry, - adjustedValue, - ] + [ blockBindings, identifier, blockName, blockContext, adjustedValue ] ); const shouldDisableEditing = readOnly || disableBoundBlock; diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index ea0d4cbb7fb5bf..c258927f2fd6dc 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -12,7 +12,7 @@ import { __experimentalVStack as VStack, privateApis as componentsPrivateApis, } from '@wordpress/components'; -import { useRegistry, useSelect } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; import { useContext, Fragment } from '@wordpress/element'; import { useViewportMatch } from '@wordpress/compose'; @@ -186,7 +186,6 @@ function EditableBlockBindingsPanelItems( { } export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { - const registry = useRegistry(); const blockContext = useContext( BlockContext ); const { removeAllBlockBindings } = useBlockBindingsUtils(); const bindableAttributes = getBindableAttributes( blockName ); @@ -194,7 +193,7 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { // `useSelect` is used purposely here to ensure `getFieldsList` // is updated whenever there are updates in block context. - // `source.getFieldsList` may also call a selector via `registry.select`. + // `source.getFieldsList` may also call a selector via `select`. const _fieldsList = {}; const { fieldsList, canUpdateBlockBindings } = useSelect( ( select ) => { @@ -214,7 +213,7 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { } } const sourceList = getFieldsList( { - registry, + select, context, } ); // Only add source if the list is not empty. @@ -234,7 +233,7 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { .canUpdateBlockBindings, }; }, - [ blockContext, bindableAttributes, registry ] + [ blockContext, bindableAttributes ] ); // Return early if there are no bindable attributes. if ( ! bindableAttributes || bindableAttributes.length === 0 ) { diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index 0fb8c38ce28d3e..fdc617fda20c05 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -118,79 +118,81 @@ export const withBlockBindingSupport = createHigherOrderComponent( // there are attribute updates. // `source.getValues` may also call a selector via `registry.select`. const updatedContext = {}; - const boundAttributes = useSelect( () => { - if ( ! blockBindings ) { - return; - } + const boundAttributes = useSelect( + ( select ) => { + if ( ! blockBindings ) { + return; + } - const attributes = {}; + const attributes = {}; - const blockBindingsBySource = new Map(); + const blockBindingsBySource = new Map(); - for ( const [ attributeName, binding ] of Object.entries( - blockBindings - ) ) { - const { source: sourceName, args: sourceArgs } = binding; - const source = sources[ sourceName ]; - if ( ! source || ! canBindAttribute( name, attributeName ) ) { - continue; - } + for ( const [ attributeName, binding ] of Object.entries( + blockBindings + ) ) { + const { source: sourceName, args: sourceArgs } = binding; + const source = sources[ sourceName ]; + if ( + ! source || + ! canBindAttribute( name, attributeName ) + ) { + continue; + } - // Populate context. - for ( const key of source.usesContext || [] ) { - updatedContext[ key ] = blockContext[ key ]; - } + // Populate context. + for ( const key of source.usesContext || [] ) { + updatedContext[ key ] = blockContext[ key ]; + } - blockBindingsBySource.set( source, { - ...blockBindingsBySource.get( source ), - [ attributeName ]: { - args: sourceArgs, - }, - } ); - } + blockBindingsBySource.set( source, { + ...blockBindingsBySource.get( source ), + [ attributeName ]: { + args: sourceArgs, + }, + } ); + } - if ( blockBindingsBySource.size ) { - for ( const [ source, bindings ] of blockBindingsBySource ) { - // Get values in batch if the source supports it. - let values = {}; - if ( ! source.getValues ) { - Object.keys( bindings ).forEach( ( attr ) => { - // Default to the the source label when `getValues` doesn't exist. - values[ attr ] = source.label; - } ); - } else { - values = source.getValues( { - registry, - context: updatedContext, - clientId, - bindings, - } ); - } - for ( const [ attributeName, value ] of Object.entries( - values - ) ) { - if ( - attributeName === 'url' && - ( ! value || ! isURLLike( value ) ) - ) { - // Return null if value is not a valid URL. - attributes[ attributeName ] = null; + if ( blockBindingsBySource.size ) { + for ( const [ + source, + bindings, + ] of blockBindingsBySource ) { + // Get values in batch if the source supports it. + let values = {}; + if ( ! source.getValues ) { + Object.keys( bindings ).forEach( ( attr ) => { + // Default to the the source label when `getValues` doesn't exist. + values[ attr ] = source.label; + } ); } else { - attributes[ attributeName ] = value; + values = source.getValues( { + select, + context: updatedContext, + clientId, + bindings, + } ); + } + for ( const [ attributeName, value ] of Object.entries( + values + ) ) { + if ( + attributeName === 'url' && + ( ! value || ! isURLLike( value ) ) + ) { + // Return null if value is not a valid URL. + attributes[ attributeName ] = null; + } else { + attributes[ attributeName ] = value; + } } } } - } - return attributes; - }, [ - blockBindings, - name, - clientId, - updatedContext, - registry, - sources, - ] ); + return attributes; + }, + [ blockBindings, name, clientId, updatedContext, sources ] + ); const hasParentPattern = !! updatedContext[ 'pattern/overrides' ]; const hasPatternOverridesDefaultBinding = @@ -240,7 +242,8 @@ export const withBlockBindingSupport = createHigherOrderComponent( bindings, ] of blockBindingsBySource ) { source.setValues( { - registry, + select: registry.select, + dispatch: registry.dispatch, context: updatedContext, clientId, bindings, diff --git a/packages/block-library/src/button/edit.js b/packages/block-library/src/button/edit.js index 2749199d1092ae..d7b8e6486c3c66 100644 --- a/packages/block-library/src/button/edit.js +++ b/packages/block-library/src/button/edit.js @@ -48,7 +48,7 @@ import { store as blocksStore, } from '@wordpress/blocks'; import { useMergeRefs, useRefEffect } from '@wordpress/compose'; -import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; +import { useSelect, useDispatch } from '@wordpress/data'; const LINK_SETTINGS = [ ...LinkControl.DEFAULT_LINK_SETTINGS, @@ -190,7 +190,6 @@ function ButtonEdit( props ) { const colorProps = useColorProps( attributes ); const spacingProps = useSpacingProps( attributes ); const shadowProps = useShadowProps( attributes ); - const registry = useRegistry(); const ref = useRef(); const richTextRef = useRef(); const blockProps = useBlockProps( { @@ -249,7 +248,7 @@ function ButtonEdit( props ) { lockUrlControls: !! metadata?.bindings?.url && ! blockBindingsSource?.canUserEditValue?.( { - registry, + select, context, args: metadata?.bindings?.url?.args, } ), diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index 454b49dfb58b32..d44dc73abfd855 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -9,7 +9,7 @@ import clsx from 'clsx'; import { isBlobURL, createBlobURL } from '@wordpress/blob'; import { store as blocksStore, createBlock } from '@wordpress/blocks'; import { Placeholder } from '@wordpress/components'; -import { useDispatch, useSelect, useRegistry } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import { BlockIcon, useBlockProps, @@ -113,7 +113,6 @@ export function ImageEdit( { const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob ); - const registry = useRegistry(); const containerRef = useRef(); // Only observe the max width from the parent container when the parent layout is not flex nor grid. // This won't work for them because the container width changes with the image. @@ -381,7 +380,7 @@ export function ImageEdit( { lockUrlControls: !! metadata?.bindings?.url && ! blockBindingsSource?.canUserEditValue?.( { - registry, + select, context, args: metadata?.bindings?.url?.args, } ), diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index f0d2f00a68d531..1673d36e463d5a 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -17,7 +17,7 @@ import { Placeholder, } from '@wordpress/components'; import { useViewportMatch } from '@wordpress/compose'; -import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; +import { useSelect, useDispatch } from '@wordpress/data'; import { BlockControls, InspectorControls, @@ -134,7 +134,6 @@ export default function Image( { const numericWidth = width ? parseInt( width, 10 ) : undefined; const numericHeight = height ? parseInt( height, 10 ) : undefined; - const registry = useRegistry(); const imageRef = useRef(); const { allowResize = true } = context; const { getBlock, getSettings } = useSelect( blockEditorStore ); @@ -497,7 +496,7 @@ export default function Image( { lockUrlControls: !! urlBinding && ! urlBindingSource?.canUserEditValue?.( { - registry, + select, context, args: urlBinding?.args, } ), @@ -512,7 +511,7 @@ export default function Image( { lockAltControls: !! altBinding && ! altBindingSource?.canUserEditValue?.( { - registry, + select, context, args: altBinding?.args, } ), @@ -526,7 +525,7 @@ export default function Image( { lockTitleControls: !! titleBinding && ! titleBindingSource?.canUserEditValue?.( { - registry, + select, context, args: titleBinding?.args, } ), diff --git a/packages/e2e-tests/plugins/block-bindings/index.js b/packages/e2e-tests/plugins/block-bindings/index.js index dfdc706b69c64d..0bfc49041647de 100644 --- a/packages/e2e-tests/plugins/block-bindings/index.js +++ b/packages/e2e-tests/plugins/block-bindings/index.js @@ -14,10 +14,10 @@ const getValues = ( { bindings } ) => { } return newValues; }; -const setValues = ( { registry, bindings } ) => { +const setValues = ( { dispatch, bindings } ) => { Object.values( bindings ).forEach( ( { args, newValue } ) => { // Example of what could be done. - registry.dispatch( 'core' ).editEntityRecord( 'postType', 'post', 1, { + dispatch( 'core' ).editEntityRecord( 'postType', 'post', 1, { meta: { [ args?.key ]: newValue }, } ); } ); diff --git a/packages/editor/src/bindings/pattern-overrides.js b/packages/editor/src/bindings/pattern-overrides.js index 88c6c73bdc61c1..baa1f72f47694b 100644 --- a/packages/editor/src/bindings/pattern-overrides.js +++ b/packages/editor/src/bindings/pattern-overrides.js @@ -7,9 +7,9 @@ const CONTENT = 'content'; export default { name: 'core/pattern-overrides', - getValues( { registry, clientId, context, bindings } ) { + getValues( { select, clientId, context, bindings } ) { const patternOverridesContent = context[ 'pattern/overrides' ]; - const { getBlockAttributes } = registry.select( blockEditorStore ); + const { getBlockAttributes } = select( blockEditorStore ); const currentBlockAttributes = getBlockAttributes( clientId ); const overridesValues = {}; @@ -32,9 +32,9 @@ export default { } return overridesValues; }, - setValues( { registry, clientId, bindings } ) { + setValues( { select, dispatch, clientId, bindings } ) { const { getBlockAttributes, getBlockParentsByBlockName, getBlocks } = - registry.select( blockEditorStore ); + select( blockEditorStore ); const currentBlockAttributes = getBlockAttributes( clientId ); const blockName = currentBlockAttributes?.metadata?.name; if ( ! blockName ) { @@ -61,12 +61,10 @@ export default { const syncBlocksWithSameName = ( blocks ) => { for ( const block of blocks ) { if ( block.attributes?.metadata?.name === blockName ) { - registry - .dispatch( blockEditorStore ) - .updateBlockAttributes( - block.clientId, - attributes - ); + dispatch( blockEditorStore ).updateBlockAttributes( + block.clientId, + attributes + ); } syncBlocksWithSameName( block.innerBlocks ); } @@ -77,27 +75,26 @@ export default { } const currentBindingValue = getBlockAttributes( patternClientId )?.[ CONTENT ]; - registry - .dispatch( blockEditorStore ) - .updateBlockAttributes( patternClientId, { - [ CONTENT ]: { - ...currentBindingValue, - [ blockName ]: { - ...currentBindingValue?.[ blockName ], - ...Object.entries( attributes ).reduce( - ( acc, [ key, value ] ) => { - // TODO: We need a way to represent `undefined` in the serialized overrides. - // Also see: https://github.com/WordPress/gutenberg/pull/57249#discussion_r1452987871 - // We use an empty string to represent undefined for now until - // we support a richer format for overrides and the block bindings API. - acc[ key ] = value === undefined ? '' : value; - return acc; - }, - {} - ), - }, + + dispatch( blockEditorStore ).updateBlockAttributes( patternClientId, { + [ CONTENT ]: { + ...currentBindingValue, + [ blockName ]: { + ...currentBindingValue?.[ blockName ], + ...Object.entries( attributes ).reduce( + ( acc, [ key, value ] ) => { + // TODO: We need a way to represent `undefined` in the serialized overrides. + // Also see: https://github.com/WordPress/gutenberg/pull/57249#discussion_r1452987871 + // We use an empty string to represent undefined for now until + // we support a richer format for overrides and the block bindings API. + acc[ key ] = value === undefined ? '' : value; + return acc; + }, + {} + ), }, - } ); + }, + } ); }, canUserEditValue: () => true, }; diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index 267d01003b80c4..9198ac0fe41e1e 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -15,8 +15,8 @@ import { unlock } from '../lock-unlock'; * If the value is not available based on context, like in templates, * it falls back to the default value, label, or key. * - * @param {Object} registry The registry context exposed through `useRegistry`. - * @param {Object} context The context provided. + * @param {Object} select The select function from the data store. + * @param {Object} context The context provided. * @return {Object} List of post meta fields with their value and label. * * @example @@ -34,11 +34,9 @@ import { unlock } from '../lock-unlock'; * } * ``` */ -function getPostMetaFields( registry, context ) { - const { getEditedEntityRecord } = registry.select( coreDataStore ); - const { getRegisteredPostMeta } = unlock( - registry.select( coreDataStore ) - ); +function getPostMetaFields( select, context ) { + const { getEditedEntityRecord } = select( coreDataStore ); + const { getRegisteredPostMeta } = unlock( select( coreDataStore ) ); let entityMetaValues; // Try to get the current entity meta values. @@ -75,8 +73,8 @@ function getPostMetaFields( registry, context ) { export default { name: 'core/post-meta', - getValues( { registry, context, bindings } ) { - const metaFields = getPostMetaFields( registry, context ); + getValues( { select, context, bindings } ) { + const metaFields = getPostMetaFields( select, context ); const newValues = {}; for ( const [ attributeName, source ] of Object.entries( bindings ) ) { @@ -88,61 +86,61 @@ export default { } return newValues; }, - setValues( { registry, context, bindings } ) { + setValues( { dispatch, context, bindings } ) { const newMeta = {}; Object.values( bindings ).forEach( ( { args, newValue } ) => { newMeta[ args.key ] = newValue; } ); - registry - .dispatch( coreDataStore ) - .editEntityRecord( 'postType', context?.postType, context?.postId, { + + dispatch( coreDataStore ).editEntityRecord( + 'postType', + context?.postType, + context?.postId, + { meta: newMeta, - } ); + } + ); }, - canUserEditValue( { registry, context, args } ) { + canUserEditValue( { select, context, args } ) { // Lock editing in query loop. if ( context?.query || context?.queryId ) { return false; } const postType = - context?.postType || - registry.select( editorStore ).getCurrentPostType(); + context?.postType || select( editorStore ).getCurrentPostType(); // Check that editing is happening in the post editor and not a template. if ( postType === 'wp_template' ) { return false; } - const fieldValue = getPostMetaFields( registry, context )?.[ args.key ] + const fieldValue = getPostMetaFields( select, context )?.[ args.key ] ?.value; // Empty string or `false` could be a valid value, so we need to check if the field value is undefined. if ( fieldValue === undefined ) { return false; } // Check that custom fields metabox is not enabled. - const areCustomFieldsEnabled = registry - .select( editorStore ) - .getEditorSettings().enableCustomFields; + const areCustomFieldsEnabled = + select( editorStore ).getEditorSettings().enableCustomFields; if ( areCustomFieldsEnabled ) { return false; } // Check that the user has the capability to edit post meta. - const canUserEdit = registry - .select( coreDataStore ) - .canUser( 'update', { - kind: 'postType', - name: context?.postType, - id: context?.postId, - } ); + const canUserEdit = select( coreDataStore ).canUser( 'update', { + kind: 'postType', + name: context?.postType, + id: context?.postId, + } ); if ( ! canUserEdit ) { return false; } return true; }, - getFieldsList( { registry, context } ) { - return getPostMetaFields( registry, context ); + getFieldsList( { select, context } ) { + return getPostMetaFields( select, context ); }, }; From 76a389f2406125dfd13a6ecf900876695741bdea Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Mon, 30 Sep 2024 13:31:09 +0200 Subject: [PATCH 1021/1908] Openverse: prevent multiple insertions during upload (#65719) Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../inserter/media-tab/media-preview.js | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/components/inserter/media-tab/media-preview.js b/packages/block-editor/src/components/inserter/media-tab/media-preview.js index 070a850d430cca..319c25c01831c8 100644 --- a/packages/block-editor/src/components/inserter/media-tab/media-preview.js +++ b/packages/block-editor/src/components/inserter/media-tab/media-preview.js @@ -133,7 +133,8 @@ export function MediaPreview( { media, onClick, category } ) { ); const { createErrorNotice, createSuccessNotice } = useDispatch( noticesStore ); - const { getSettings } = useSelect( blockEditorStore ); + const { getSettings, getBlock } = useSelect( blockEditorStore ); + const { updateBlockAttributes } = useDispatch( blockEditorStore ); const onMediaInsert = useCallback( ( previewBlock ) => { @@ -180,18 +181,31 @@ export function MediaPreview( { media, onClick, category } ) { if ( isBlobURL( img.url ) ) { return; } - onClick( { - ...clonedBlock, - attributes: { + + if ( ! getBlock( clonedBlock.clientId ) ) { + // Ensure the block is only inserted once. + onClick( { + ...clonedBlock, + attributes: { + ...clonedBlock.attributes, + id: img.id, + url: img.url, + }, + } ); + + createSuccessNotice( + __( 'Image uploaded and inserted.' ), + { type: 'snackbar', id: 'inserter-notice' } + ); + } else { + // For subsequent calls, update the existing block. + updateBlockAttributes( clonedBlock.clientId, { ...clonedBlock.attributes, id: img.id, url: img.url, - }, - } ); - createSuccessNotice( - __( 'Image uploaded and inserted.' ), - { type: 'snackbar', id: 'inserter-notice' } - ); + } ); + } + setIsInserting( false ); }, allowedTypes: ALLOWED_MEDIA_TYPES, @@ -214,7 +228,9 @@ export function MediaPreview( { media, onClick, category } ) { getSettings, onClick, createSuccessNotice, + updateBlockAttributes, createErrorNotice, + getBlock, ] ); From b7bf13396a690971bd7d4f5c8754dc07a36549c6 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 30 Sep 2024 22:52:22 +0900 Subject: [PATCH 1022/1908] ToggleGroupControl: Fix arrow key navigation in RTL (#65735) * ToggleGroupControl: Fix arrow key navigation in RTL * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../toggle-group-control/as-radio-group.tsx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 8ef1c7c3bd2002..09f46b43a623ff 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,7 @@ - `ToolsPanel`: atomic one-step state update when (un)registering panels ([#65564](https://github.com/WordPress/gutenberg/pull/65564)). - `Navigator`: fix `isInitial` logic ([#65527](https://github.com/WordPress/gutenberg/pull/65527)). +- `ToggleGroupControl`: Fix arrow key navigation in RTL ([#65735](https://github.com/WordPress/gutenberg/pull/65735)). ### Deprecations diff --git a/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx b/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx index 6baadd65dc5ff6..c062e35cb2b72b 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx @@ -10,6 +10,7 @@ import { useStoreState } from '@ariakit/react'; */ import { useInstanceId } from '@wordpress/compose'; import { forwardRef, useMemo } from '@wordpress/element'; +import { isRTL } from '@wordpress/i18n'; /** * Internal dependencies @@ -65,6 +66,7 @@ function UnforwardedToggleGroupControlAsRadioGroup( defaultValue, value, setValue: wrappedOnChangeProp, + rtl: isRTL(), } ); const selectedValue = useStoreState( radio, 'value' ); From 37bceffa18cb6e6a89dcdfb68be79b81391f3266 Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Mon, 30 Sep 2024 21:25:58 +0200 Subject: [PATCH 1023/1908] `Tabs`: tweak sizing and overflow behavior of TabList (#64371) * Tweak sizing and overflow behavior of TabList. * Add size and overflow playground story. * Add "scroll into view" behavior to selected tabs. * fit-content only on horizontal orientation * Reduce specificity of `fit-content` to make it easier to override. * centered label only when orientation is horizontal * Remove unused file. * Fix inspector controls tabs. * Fix font library modal tabs. * Fix style-book tabs. * fix typo * Add changelog entry. * fix emotion being weird ugh * Prevent unwanted focusable container in Firefox. * Add fade effect. * Fix IntersectionObserver logic. * Feature detect IntersectionObserver to prevent tests from failing. * Add a bit of tolerance for scroll state detection. * Fix vertical indicator. * Better handling of vertical overflow. * Add a bit of scroll margin for better "scroll into view" experience. * Horizontal fade should only happen on horizontal direction. * Adjust for offset parent scroll state in `getElementOffsetRect`. * Better "scroll into view" positioning heuristics ("nearest"). * Invert use of before and after to remove z-index and fix related issues. * Make vertical indicator light blue as discussed. * Undo most overrides in pattern/media vertical tabs. * Clean up outdated styles previously needed for label wrapping. * Revert vertical indicator changes and some indicator patterns/media tabs styles * Revert vertical indicator bug fix * Add changelog entry * Remove outdated style. * Address feedback * Fix scroll bug * Improve automatic tab scrolling behavior. * Tweaks to prevent unit test failure and minor cleanup. * Undo unnecessary changes. * Improved story * Fix scroll jumping bug. * Scroll to active tab instead of selected (support `selectOnMove=false`). * Fix minor visual glitch with overflow fade out indicators. * Misc tweaks * Fix. * Fix changelog * Fix changelog but it's actually true * Fix changelog * Make Story Book tabs nicer. * Temp fix for scrollbar issue in Style Book tabs. * Fix scroll bug and clean up a little. * Simplify and clean up a bit more. * Fix merge issues. * Fix merge issues again. * Make inserter patterns/media changes more minimal * Fix outdated comment * Fix another typo in comment. * Minor cleanup. * Fix bad automatic merge. * ugh, fix again Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../src/components/inserter/style.scss | 28 ----- .../src/components/inserter/tabs.js | 78 ------------- .../inspector-controls-tabs/style.scss | 8 +- packages/components/CHANGELOG.md | 1 + .../src/tabs/stories/index.story.tsx | 106 ++++++++++++++++++ packages/components/src/tabs/styles.ts | 74 ++++++++---- packages/components/src/tabs/tablist.tsx | 86 +++++++++----- .../components/src/tabs/use-track-overflow.ts | 76 +++++++++++++ packages/components/src/utils/element-rect.ts | 22 +++- .../editor-canvas-container/style.scss | 2 +- .../global-styles/font-library-modal/index.js | 2 +- .../font-library-modal/style.scss | 6 +- .../src/components/style-book/index.js | 22 ++-- .../src/components/style-book/style.scss | 14 ++- .../src/components/sidebar/index.js | 6 +- 15 files changed, 346 insertions(+), 185 deletions(-) delete mode 100644 packages/block-editor/src/components/inserter/tabs.js create mode 100644 packages/components/src/tabs/use-track-overflow.ts diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index 3ce088901bce57..f3fa8d1e7df04b 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -257,39 +257,11 @@ $block-inserter-tabs-height: 44px; svg { fill: var(--wp-admin-theme-color); } - - &::after { - content: ""; - display: block; - outline: none; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - border-radius: $radius-small; - opacity: 0.04; - background: var(--wp-admin-theme-color); - height: 100%; - } - } - - &:focus-visible, - &:focus:not(:disabled) { - border-radius: $radius-small; - box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - // Windows high contrast mode. - outline: 2px solid transparent; - outline-offset: 0; } &::before { display: none; } - - &::after { - display: none; - } } } diff --git a/packages/block-editor/src/components/inserter/tabs.js b/packages/block-editor/src/components/inserter/tabs.js deleted file mode 100644 index b46e4bfdaf0148..00000000000000 --- a/packages/block-editor/src/components/inserter/tabs.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * WordPress dependencies - */ -import { - Button, - privateApis as componentsPrivateApis, -} from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import { forwardRef } from '@wordpress/element'; -import { closeSmall } from '@wordpress/icons'; - -/** - * Internal dependencies - */ -import { unlock } from '../../lock-unlock'; - -const { Tabs } = unlock( componentsPrivateApis ); - -const blocksTab = { - name: 'blocks', - /* translators: Blocks tab title in the block inserter. */ - title: __( 'Blocks' ), -}; -const patternsTab = { - name: 'patterns', - /* translators: Theme and Directory Patterns tab title in the block inserter. */ - title: __( 'Patterns' ), -}; - -const mediaTab = { - name: 'media', - /* translators: Media tab title in the block inserter. */ - title: __( 'Media' ), -}; - -function InserterTabs( { onSelect, children, onClose, selectedTab }, ref ) { - const tabs = [ blocksTab, patternsTab, mediaTab ]; - - return ( - <div className="block-editor-inserter__tabs" ref={ ref }> - <Tabs onSelect={ onSelect } selectedTabId={ selectedTab }> - <div className="block-editor-inserter__tablist-and-close-button"> - <Button - className="block-editor-inserter__close-button" - icon={ closeSmall } - label={ __( 'Close block inserter' ) } - onClick={ () => onClose() } - size="small" - /> - - <Tabs.TabList className="block-editor-inserter__tablist"> - { tabs.map( ( tab ) => ( - <Tabs.Tab - key={ tab.name } - tabId={ tab.name } - className="block-editor-inserter__tab" - > - { tab.title } - </Tabs.Tab> - ) ) } - </Tabs.TabList> - </div> - { tabs.map( ( tab ) => ( - <Tabs.TabPanel - key={ tab.name } - tabId={ tab.name } - focusable={ false } - className="block-editor-inserter__tabpanel" - > - { children } - </Tabs.TabPanel> - ) ) } - </Tabs> - </div> - ); -} - -export default forwardRef( InserterTabs ); diff --git a/packages/block-editor/src/components/inspector-controls-tabs/style.scss b/packages/block-editor/src/components/inspector-controls-tabs/style.scss index 863ac3d9bed03a..9c9b04f7b84734 100644 --- a/packages/block-editor/src/components/inspector-controls-tabs/style.scss +++ b/packages/block-editor/src/components/inspector-controls-tabs/style.scss @@ -1,7 +1,3 @@ -.show-icon-labels { - .block-editor-block-inspector__tabs [role="tablist"] { - .components-button { - justify-content: center; - } - } +.block-editor-block-inspector__tabs [role="tablist"] { + width: 100%; } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 09f46b43a623ff..f98f878080aa27 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -14,6 +14,7 @@ ### Enhancements +- `Tabs`: handle horizontal overflow and large tab lists gracefully ([#64371](https://github.com/WordPress/gutenberg/pull/64371)). - `BorderBoxControl`: promote to stable ([#65586](https://github.com/WordPress/gutenberg/pull/65586)). - `MenuGroup`: Simplify the MenuGroup styles within dropdown menus. ([#65561](https://github.com/WordPress/gutenberg/pull/65561)). - `DatePicker`: Use compact button size. ([#65653](https://github.com/WordPress/gutenberg/pull/65653)). diff --git a/packages/components/src/tabs/stories/index.story.tsx b/packages/components/src/tabs/stories/index.story.tsx index e5f113d93b7d0e..0f7e0d2c6ac75f 100644 --- a/packages/components/src/tabs/stories/index.story.tsx +++ b/packages/components/src/tabs/stories/index.story.tsx @@ -70,6 +70,112 @@ const Template: StoryFn< typeof Tabs > = ( props ) => { export const Default = Template.bind( {} ); +export const SizeAndOverflowPlayground: StoryFn< typeof Tabs > = ( props ) => { + const [ fullWidth, setFullWidth ] = useState( false ); + return ( + <div> + <div style={ { maxWidth: '40rem', marginBottom: '1rem' } }> + <p> + This story helps understand how the TabList component + behaves under different conditions. The container below + (with the dotted red border) can be horizontally resized, + and it has a bit of padding to be out of the way of the + TabList. + </p> + <p> + The button will toggle between full width (adding{ ' ' } + <code>width: 100%</code>) and the default width. + </p> + <p>Try the following:</p> + <ul> + <li> + <strong>Small container</strong> that causes tabs to + overflow with scroll. + </li> + <li> + <strong>Large container</strong> that exceeds the normal + width of the tabs. + <ul> + <li> + <strong> + With <code>width: 100%</code> + </strong>{ ' ' } + set on the TabList (tabs fill up the space). + </li> + <li> + <strong> + Without <code>width: 100%</code> + </strong>{ ' ' } + (defaults to <code>auto</code>) set on the + TabList (tabs take up space proportional to + their content). + </li> + </ul> + </li> + </ul> + </div> + <Button + style={ { marginBottom: '1rem' } } + variant="primary" + onClick={ () => setFullWidth( ! fullWidth ) } + > + { fullWidth + ? 'Remove width: 100% from TabList' + : 'Set width: 100% in TabList' } + </Button> + <Tabs { ...props }> + <div + style={ { + width: '20rem', + border: '2px dotted red', + padding: '1rem', + resize: 'horizontal', + overflow: 'auto', + } } + > + <Tabs.TabList + style={ { + maxWidth: '100%', + width: fullWidth ? '100%' : undefined, + } } + > + <Tabs.Tab tabId="tab1"> + Label with multiple words + </Tabs.Tab> + <Tabs.Tab tabId="tab2">Short</Tabs.Tab> + <Tabs.Tab tabId="tab3"> + Hippopotomonstrosesquippedaliophobia + </Tabs.Tab> + <Tabs.Tab tabId="tab4">Tab 4</Tabs.Tab> + <Tabs.Tab tabId="tab5">Tab 5</Tabs.Tab> + </Tabs.TabList> + </div> + <Tabs.TabPanel tabId="tab1"> + <p>Selected tab: Tab 1</p> + <p>(Label with multiple words)</p> + </Tabs.TabPanel> + <Tabs.TabPanel tabId="tab2"> + <p>Selected tab: Tab 2</p> + <p>(Short)</p> + </Tabs.TabPanel> + <Tabs.TabPanel tabId="tab3"> + <p>Selected tab: Tab 3</p> + <p>(Hippopotomonstrosesquippedaliophobia)</p> + </Tabs.TabPanel> + <Tabs.TabPanel tabId="tab4"> + <p>Selected tab: Tab 4</p> + </Tabs.TabPanel> + <Tabs.TabPanel tabId="tab5"> + <p>Selected tab: Tab 5</p> + </Tabs.TabPanel> + </Tabs> + </div> + ); +}; +SizeAndOverflowPlayground.args = { + defaultTabId: 'tab4', +}; + const VerticalTemplate: StoryFn< typeof Tabs > = ( props ) => { return ( <Tabs orientation="vertical" { ...props }> diff --git a/packages/components/src/tabs/styles.ts b/packages/components/src/tabs/styles.ts index c00943b180f637..283d6421f5b768 100644 --- a/packages/components/src/tabs/styles.ts +++ b/packages/components/src/tabs/styles.ts @@ -16,32 +16,40 @@ export const TabListWrapper = styled.div` align-items: stretch; flex-direction: row; text-align: center; + overflow-x: auto; &[aria-orientation='vertical'] { flex-direction: column; text-align: start; } - @media not ( prefers-reduced-motion ) { - &.is-animation-enabled::after { - transition-property: transform; - transition-duration: 0.2s; - transition-timing-function: ease-out; - } + :where( [aria-orientation='horizontal'] ) { + width: fit-content; } + --direction-factor: 1; - --direction-origin-x: left; + --direction-start: left; + --direction-end: right; --indicator-start: var( --indicator-left ); &:dir( rtl ) { --direction-factor: -1; - --direction-origin-x: right; + --direction-start: right; + --direction-end: left; --indicator-start: var( --indicator-right ); } - &::after { + + @media not ( prefers-reduced-motion ) { + &.is-animation-enabled::before { + transition-property: transform; + transition-duration: 0.2s; + transition-timing-function: ease-out; + } + } + &::before { content: ''; position: absolute; pointer-events: none; - transform-origin: var( --direction-origin-x ) top; + transform-origin: var( --direction-start ) top; // Windows high contrast mode. outline: 2px solid transparent; @@ -52,7 +60,31 @@ export const TabListWrapper = styled.div` when scaling in the transform, see: https://stackoverflow.com/a/52159123 */ --antialiasing-factor: 100; &:not( [aria-orientation='vertical'] ) { - &::after { + --fade-width: 4rem; + --fade-gradient-base: transparent 0%, black var( --fade-width ); + --fade-gradient-composed: var( --fade-gradient-base ), black 60%, + transparent 50%; + &.is-overflowing-first { + mask-image: linear-gradient( + to var( --direction-end ), + var( --fade-gradient-base ) + ); + } + &.is-overflowing-last { + mask-image: linear-gradient( + to var( --direction-start ), + var( --fade-gradient-base ) + ); + } + &.is-overflowing-first.is-overflowing-last { + mask-image: linear-gradient( + to right, + var( --fade-gradient-composed ) + ), + linear-gradient( to left, var( --fade-gradient-composed ) ); + } + + &::before { bottom: 0; height: 0; width: calc( var( --antialiasing-factor ) * 1px ); @@ -71,8 +103,7 @@ export const TabListWrapper = styled.div` ${ COLORS.theme.accent }; } } - &[aria-orientation='vertical']::after { - z-index: -1; + &[aria-orientation='vertical']::before { top: 0; left: 0; width: 100%; @@ -87,14 +118,14 @@ export const TabListWrapper = styled.div` export const Tab = styled( Ariakit.Tab )` & { + scroll-margin: 24px; + flex-grow: 1; + flex-shrink: 0; display: inline-flex; align-items: center; position: relative; border-radius: 0; - min-height: ${ space( - 12 - ) }; // Avoid fixed height to allow for long strings that go in multiple lines. - height: auto; + height: ${ space( 12 ) }; background: transparent; border: none; box-shadow: none; @@ -104,7 +135,6 @@ export const Tab = styled( Ariakit.Tab )` margin-left: 0; font-weight: 500; text-align: inherit; - hyphens: auto; color: ${ COLORS.theme.foreground }; &[aria-disabled='true'] { @@ -123,7 +153,7 @@ export const Tab = styled( Ariakit.Tab )` } // Focus. - &::before { + &::after { content: ''; position: absolute; top: ${ space( 3 ) }; @@ -146,7 +176,7 @@ export const Tab = styled( Ariakit.Tab )` } } - &:focus-visible::before { + &:focus-visible::after { opacity: 1; } } @@ -156,6 +186,10 @@ export const Tab = styled( Ariakit.Tab )` 10 ) }; // Avoid fixed height to allow for long strings that go in multiple lines. } + + [aria-orientation='horizontal'] & { + justify-content: center; + } `; export const TabPanel = styled( Ariakit.TabPanel )` diff --git a/packages/components/src/tabs/tablist.tsx b/packages/components/src/tabs/tablist.tsx index 2977d6a6283708..ae8daf60fc237c 100644 --- a/packages/components/src/tabs/tablist.tsx +++ b/packages/components/src/tabs/tablist.tsx @@ -8,7 +8,8 @@ import { useStoreState } from '@ariakit/react'; * WordPress dependencies */ import warning from '@wordpress/warning'; -import { forwardRef, useState } from '@wordpress/element'; +import { forwardRef, useLayoutEffect, useState } from '@wordpress/element'; +import { useMergeRefs } from '@wordpress/compose'; /** * Internal dependencies @@ -20,33 +21,58 @@ import type { WordPressComponentProps } from '../context'; import clsx from 'clsx'; import { useTrackElementOffsetRect } from '../utils/element-rect'; import { useOnValueUpdate } from '../utils/hooks/use-on-value-update'; +import { useTrackOverflow } from './use-track-overflow'; + +const SCROLL_MARGIN = 24; export const TabList = forwardRef< HTMLDivElement, WordPressComponentProps< TabListProps, 'div', false > >( function TabList( { children, ...otherProps }, ref ) { - const context = useTabsContext(); + const { store } = useTabsContext() ?? {}; + + const selectedId = useStoreState( store, 'selectedId' ); + const activeId = useStoreState( store, 'activeId' ); + const selectOnMove = useStoreState( store, 'selectOnMove' ); + const items = useStoreState( store, 'items' ); + const [ parent, setParent ] = useState< HTMLElement | null >(); + const refs = useMergeRefs( [ ref, setParent ] ); + const overflow = useTrackOverflow( parent, { + first: items?.at( 0 )?.element, + last: items?.at( -1 )?.element, + } ); - const tabStoreState = useStoreState( context?.store ); - const selectedId = tabStoreState?.selectedId; - const indicatorPosition = useTrackElementOffsetRect( - context?.store.item( selectedId )?.element + const selectedTabPosition = useTrackElementOffsetRect( + store?.item( selectedId )?.element ); const [ animationEnabled, setAnimationEnabled ] = useState( false ); - useOnValueUpdate( - selectedId, - ( { previousValue } ) => previousValue && setAnimationEnabled( true ) - ); + useOnValueUpdate( selectedId, ( { previousValue } ) => { + if ( previousValue ) { + setAnimationEnabled( true ); + } + } ); - if ( ! context || ! tabStoreState ) { - warning( '`Tabs.TabList` must be wrapped in a `Tabs` component.' ); - return null; - } + // Make sure selected tab is scrolled into view. + useLayoutEffect( () => { + if ( ! parent || ! selectedTabPosition ) { + return; + } + + const { scrollLeft: parentScroll } = parent; + const parentWidth = parent.getBoundingClientRect().width; + const { left: childLeft, width: childWidth } = selectedTabPosition; - const { store } = context; - const { activeId, selectOnMove } = tabStoreState; - const { setActiveId } = store; + const parentRightEdge = parentScroll + parentWidth; + const childRightEdge = childLeft + childWidth; + const rightOverflow = childRightEdge + SCROLL_MARGIN - parentRightEdge; + const leftOverflow = parentScroll - ( childLeft - SCROLL_MARGIN ); + if ( leftOverflow > 0 ) { + parent.scrollLeft = parentScroll - leftOverflow; + } else if ( rightOverflow > 0 ) { + parent.scrollLeft = parentScroll + rightOverflow; + } + }, [ parent, selectedTabPosition ] ); const onBlur = () => { if ( ! selectOnMove ) { @@ -58,35 +84,43 @@ export const TabList = forwardRef< // that the selected tab will receive keyboard focus when tabbing back into // the tablist. if ( selectedId !== activeId ) { - setActiveId( selectedId ); + store?.setActiveId( selectedId ); } }; + if ( ! store ) { + warning( '`Tabs.TabList` must be wrapped in a `Tabs` component.' ); + return null; + } + return ( <Ariakit.TabList - ref={ ref } + ref={ refs } store={ store } render={ <TabListWrapper onTransitionEnd={ ( event ) => { - if ( event.pseudoElement === '::after' ) { + if ( event.pseudoElement === '::before' ) { setAnimationEnabled( false ); } } } /> } onBlur={ onBlur } + tabIndex={ -1 } { ...otherProps } style={ { - '--indicator-top': indicatorPosition.top, - '--indicator-right': indicatorPosition.right, - '--indicator-left': indicatorPosition.left, - '--indicator-width': indicatorPosition.width, - '--indicator-height': indicatorPosition.height, + '--indicator-top': selectedTabPosition.top, + '--indicator-right': selectedTabPosition.right, + '--indicator-left': selectedTabPosition.left, + '--indicator-width': selectedTabPosition.width, + '--indicator-height': selectedTabPosition.height, ...otherProps.style, } } className={ clsx( - animationEnabled ? 'is-animation-enabled' : '', + overflow.first && 'is-overflowing-first', + overflow.last && 'is-overflowing-last', + animationEnabled && 'is-animation-enabled', otherProps.className ) } > diff --git a/packages/components/src/tabs/use-track-overflow.ts b/packages/components/src/tabs/use-track-overflow.ts new file mode 100644 index 00000000000000..5f6504e6875212 --- /dev/null +++ b/packages/components/src/tabs/use-track-overflow.ts @@ -0,0 +1,76 @@ +/* eslint-disable jsdoc/require-param */ +/** + * WordPress dependencies + */ +import { useState, useEffect } from '@wordpress/element'; +import { useEvent } from '@wordpress/compose'; + +/** + * Tracks if an element contains overflow and on which end by tracking the + * first and last child elements with an `IntersectionObserver` in relation + * to the parent element. + * + * Note that the returned value will only indicate whether the first or last + * element is currently "going out of bounds" but not whether it happens on + * the X or Y axis. + */ +export function useTrackOverflow( + parent: HTMLElement | undefined | null, + children: { + first: HTMLElement | undefined | null; + last: HTMLElement | undefined | null; + } +) { + const [ first, setFirst ] = useState( false ); + const [ last, setLast ] = useState( false ); + const [ observer, setObserver ] = useState< IntersectionObserver >(); + + const callback: IntersectionObserverCallback = useEvent( ( entries ) => { + for ( const entry of entries ) { + if ( entry.target === children.first ) { + setFirst( ! entry.isIntersecting ); + } + if ( entry.target === children.last ) { + setLast( ! entry.isIntersecting ); + } + } + } ); + + useEffect( () => { + if ( ! parent || ! window.IntersectionObserver ) { + return; + } + const newObserver = new IntersectionObserver( callback, { + root: parent, + threshold: 0.9, + } ); + setObserver( newObserver ); + + return () => newObserver.disconnect(); + }, [ callback, parent ] ); + + useEffect( () => { + if ( ! observer ) { + return; + } + + if ( children.first ) { + observer.observe( children.first ); + } + if ( children.last ) { + observer.observe( children.last ); + } + + return () => { + if ( children.first ) { + observer.unobserve( children.first ); + } + if ( children.last ) { + observer.unobserve( children.last ); + } + }; + }, [ children.first, children.last, observer ] ); + + return { first, last }; +} +/* eslint-enable jsdoc/require-param */ diff --git a/packages/components/src/utils/element-rect.ts b/packages/components/src/utils/element-rect.ts index a96c25ecfac949..4c60e4ba51c48a 100644 --- a/packages/components/src/utils/element-rect.ts +++ b/packages/components/src/utils/element-rect.ts @@ -75,9 +75,11 @@ export function getElementOffsetRect( if ( rect.width === 0 || rect.height === 0 ) { return; } + const offsetParent = element.offsetParent; const offsetParentRect = - element.offsetParent?.getBoundingClientRect() ?? - NULL_ELEMENT_OFFSET_RECT; + offsetParent?.getBoundingClientRect() ?? NULL_ELEMENT_OFFSET_RECT; + const offsetParentScrollX = offsetParent?.scrollLeft ?? 0; + const offsetParentScrollY = offsetParent?.scrollTop ?? 0; // Computed widths and heights have subpixel precision, and are not affected // by distortions. @@ -93,10 +95,18 @@ export function getElementOffsetRect( // To obtain the adjusted values for the position: // 1. Compute the element's position relative to the offset parent. // 2. Correct for the scale factor. - top: ( rect.top - offsetParentRect?.top ) * scaleY, - right: ( offsetParentRect?.right - rect.right ) * scaleX, - bottom: ( offsetParentRect?.bottom - rect.bottom ) * scaleY, - left: ( rect.left - offsetParentRect?.left ) * scaleX, + // 3. Adjust for the scroll position of the offset parent. + top: + ( rect.top - offsetParentRect?.top ) * scaleY + offsetParentScrollY, + right: + ( offsetParentRect?.right - rect.right ) * scaleX - + offsetParentScrollX, + bottom: + ( offsetParentRect?.bottom - rect.bottom ) * scaleY - + offsetParentScrollY, + left: + ( rect.left - offsetParentRect?.left ) * scaleX + + offsetParentScrollX, // Computed dimensions don't need any adjustments. width: computedWidth, height: computedHeight, diff --git a/packages/edit-site/src/components/editor-canvas-container/style.scss b/packages/edit-site/src/components/editor-canvas-container/style.scss index 80d6a909d0c952..0bdbc2bbe32355 100644 --- a/packages/edit-site/src/components/editor-canvas-container/style.scss +++ b/packages/edit-site/src/components/editor-canvas-container/style.scss @@ -30,6 +30,6 @@ position: absolute; right: $grid-unit-10; top: $grid-unit-10; - z-index: 1; + z-index: 2; background: $white; } diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/index.js b/packages/edit-site/src/components/global-styles/font-library-modal/index.js index 495652f144275e..27093e0ef1cbba 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/index.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/index.js @@ -67,7 +67,7 @@ function FontLibraryModal( { className="font-library-modal" > <Tabs defaultTabId={ defaultTabId }> - <div className="font-library-modal__tablist"> + <div className="font-library-modal__tablist-container"> <Tabs.TabList> { tabs.map( ( { id, title } ) => ( <Tabs.Tab key={ id } tabId={ id }> diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss index e8c48ca2c30bf8..7d94376ac8d942 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss +++ b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss @@ -133,7 +133,7 @@ $footer-height: 70px; padding-bottom: $grid-unit-20; } -.font-library-modal__tablist { +.font-library-modal__tablist-container { position: sticky; top: 0; border-bottom: 1px solid $gray-300; @@ -141,6 +141,10 @@ $footer-height: 70px; margin: 0 #{$grid-unit-40 * -1}; padding: 0 $grid-unit-20; z-index: 1; + + [role="tablist"] { + margin-bottom: -1px; + } } diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index e68474e19f407f..7b85c320e20c99 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -122,16 +122,18 @@ function StyleBook( { { showTabs ? ( <div className="edit-site-style-book__tabs"> <Tabs> - <Tabs.TabList> - { tabs.map( ( tab ) => ( - <Tabs.Tab - tabId={ tab.slug } - key={ tab.slug } - > - { tab.title } - </Tabs.Tab> - ) ) } - </Tabs.TabList> + <div className="edit-site-style-book__tablist-container"> + <Tabs.TabList> + { tabs.map( ( tab ) => ( + <Tabs.Tab + tabId={ tab.slug } + key={ tab.slug } + > + { tab.title } + </Tabs.Tab> + ) ) } + </Tabs.TabList> + </div> { tabs.map( ( tab ) => ( <Tabs.TabPanel key={ tab.slug } diff --git a/packages/edit-site/src/components/style-book/style.scss b/packages/edit-site/src/components/style-book/style.scss index ab66ec288da310..3e0c6466438a22 100644 --- a/packages/edit-site/src/components/style-book/style.scss +++ b/packages/edit-site/src/components/style-book/style.scss @@ -17,12 +17,16 @@ } } -.edit-site-style-book__tabs { - [role="tablist"] { - background: $white; - color: $gray-900; - } +.edit-site-style-book__tablist-container { + background: $white; + width: 100%; + padding-right: 56px; + display: flex; + position: absolute; + z-index: 1; +} +.edit-site-style-book__tabs { [role="tabpanel"] { bottom: 0; left: 0; diff --git a/packages/edit-widgets/src/components/sidebar/index.js b/packages/edit-widgets/src/components/sidebar/index.js index f08ee81a0d19cc..79a47b18c7bf12 100644 --- a/packages/edit-widgets/src/components/sidebar/index.js +++ b/packages/edit-widgets/src/components/sidebar/index.js @@ -28,7 +28,7 @@ const SIDEBAR_ACTIVE_BY_DEFAULT = Platform.select( { const BLOCK_INSPECTOR_IDENTIFIER = 'edit-widgets/block-inspector'; -// Widget areas were one called block areas, so use 'edit-widgets/block-areas' +// Widget areas were once called block areas, so use 'edit-widgets/block-areas' // for backwards compatibility. const WIDGET_AREAS_IDENTIFIER = 'edit-widgets/block-areas'; @@ -192,10 +192,10 @@ export default function Sidebar() { const { enableComplementaryArea } = useDispatch( interfaceStore ); - // `newSelectedTabId` could technically be falsey if no tab is selected (i.e. + // `newSelectedTabId` could technically be falsy if no tab is selected (i.e. // the initial render) or when we don't want a tab displayed (i.e. the // sidebar is closed). These cases should both be covered by the `!!` check - // below, so we shouldn't need any additional falsey handling. + // below, so we shouldn't need any additional falsy handling. const onTabSelect = useCallback( ( newSelectedTabId ) => { if ( !! newSelectedTabId ) { From 1a477196e64d7739ab619229af5c68bd68722bbe Mon Sep 17 00:00:00 2001 From: Matias Ventura <mv@matiasventura.com> Date: Mon, 30 Sep 2024 22:01:41 +0200 Subject: [PATCH 1024/1908] Update tools menus with Write / Design order (#65721) * Update tools menus: - Write / Design order - Change description copy * update tools help text --------- Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: provenself <provenself@git.wordpress.org> --- .../src/components/tool-selector/index.js | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/block-editor/src/components/tool-selector/index.js b/packages/block-editor/src/components/tool-selector/index.js index 53fab037ba3684..fbaf8af5fac688 100644 --- a/packages/block-editor/src/components/tool-selector/index.js +++ b/packages/block-editor/src/components/tool-selector/index.js @@ -71,33 +71,31 @@ function ToolSelector( props, ref ) { onSelect={ __unstableSetEditorMode } choices={ [ { - value: 'edit', + value: 'navigation', label: ( <> - { selectIcon } - { __( 'Design' ) } + <Icon icon={ editIcon } /> + { __( 'Write' ) } </> ), - info: __( - 'Full control over layout and styling.' - ), + info: __( 'Focus on content.' ), }, { - value: 'navigation', + value: 'edit', label: ( <> - <Icon icon={ editIcon } /> - { __( 'Edit' ) } + { selectIcon } + { __( 'Design' ) } </> ), - info: __( 'Focus on content.' ), + info: __( 'Edit layout and styles.' ), }, ] } /> </NavigableMenu> <div className="block-editor-tool-selector__help"> { __( - 'Tools provide different interactions for selecting, navigating, and editing blocks. Toggle between select and edit by pressing Escape and Enter.' + 'Tools provide different sets of interactions for blocks. Toggle between simplified content tools (Write) and advanced visual editing tools (Design).' ) } </div> </> From 5128f040606f8c7de1f8cee6ba7c7ed8676efe52 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Mon, 30 Sep 2024 15:06:49 -0500 Subject: [PATCH 1025/1908] Only show zoom out inserters on block selection (#65759) Removes code related to showing/hiding inserters on hover. --- .../src/components/block-tools/style.scss | 8 -------- .../zoom-out-mode-inserter-button.js | 19 ++----------------- .../block-tools/zoom-out-mode-inserters.js | 17 ++++------------- 3 files changed, 6 insertions(+), 38 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index a3d9153273e983..b7586a6715dcc6 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -202,11 +202,3 @@ border: none; } } - -.block-editor-block-tools__zoom-out-mode-inserter-button { - visibility: hidden; - - &.is-visible { - visibility: visible; - } -} diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserter-button.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserter-button.js index 8ea80a53830135..961552caa66e01 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserter-button.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserter-button.js @@ -6,17 +6,11 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { useState } from '@wordpress/element'; import { Button } from '@wordpress/components'; import { plus } from '@wordpress/icons'; import { _x } from '@wordpress/i18n'; -function ZoomOutModeInserterButton( { isVisible, onClick } ) { - const [ - zoomOutModeInserterButtonHovered, - setZoomOutModeInserterButtonHovered, - ] = useState( false ); - +function ZoomOutModeInserterButton( { onClick } ) { return ( <Button variant="primary" @@ -24,18 +18,9 @@ function ZoomOutModeInserterButton( { isVisible, onClick } ) { size="compact" className={ clsx( 'block-editor-button-pattern-inserter__button', - 'block-editor-block-tools__zoom-out-mode-inserter-button', - { - 'is-visible': isVisible || zoomOutModeInserterButtonHovered, - } + 'block-editor-block-tools__zoom-out-mode-inserter-button' ) } onClick={ onClick } - onMouseOver={ () => { - setZoomOutModeInserterButtonHovered( true ); - } } - onMouseOut={ () => { - setZoomOutModeInserterButtonHovered( false ); - } } label={ _x( 'Add pattern', 'Generic label for pattern inserter button' diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js index 4d47c136defab0..c279cb36782028 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js @@ -22,7 +22,6 @@ function ZoomOutModeInserters() { setInserterIsOpened, sectionRootClientId, selectedBlockClientId, - hoveredBlockClientId, } = useSelect( ( select ) => { const { getSettings, @@ -30,7 +29,6 @@ function ZoomOutModeInserters() { getBlockOrder, getSelectionStart, getSelectedBlockClientId, - getHoveredBlockClientId, getSectionRootClientId, isBlockInsertionPointVisible, } = unlock( select( blockEditorStore ) ); @@ -46,7 +44,6 @@ function ZoomOutModeInserters() { setInserterIsOpened: getSettings().__experimentalSetIsInserterOpened, selectedBlockClientId: getSelectedBlockClientId(), - hoveredBlockClientId: getHoveredBlockClientId(), }; }, [] ); @@ -63,7 +60,7 @@ function ZoomOutModeInserters() { }; }, [] ); - if ( ! isReady ) { + if ( ! isReady || ! hasSelection ) { return null; } @@ -75,13 +72,8 @@ function ZoomOutModeInserters() { const nextClientId = blockOrder[ index ]; const isSelected = - hasSelection && - ( selectedBlockClientId === previousClientId || - selectedBlockClientId === nextClientId ); - - const isHovered = - hoveredBlockClientId === previousClientId || - hoveredBlockClientId === nextClientId; + selectedBlockClientId === previousClientId || + selectedBlockClientId === nextClientId; return ( <BlockPopoverInbetween @@ -89,9 +81,8 @@ function ZoomOutModeInserters() { previousClientId={ previousClientId } nextClientId={ nextClientId } > - { ! shouldRenderInsertionPoint && ( + { ! shouldRenderInsertionPoint && isSelected && ( <ZoomOutModeInserterButton - isVisible={ isSelected || isHovered } onClick={ () => { setInserterIsOpened( { rootClientId: sectionRootClientId, From 1c081c8834c08fc6ace7780caf12e19cadf76666 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Tue, 1 Oct 2024 02:06:44 +0200 Subject: [PATCH 1026/1908] Block Bindings: Open the stable editor APIs (#65713) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Try use select and dispatch instead of registry * Fix `setValues` * Open `useBlockBindingsUtils` * Open registration APIs * Restrict `getFieldsList` API * Update `useBlockBindingsUtils` docs * Update register/unregister bindings docs * Simplify API functions examples Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> * Update docs * Update comments --------- Co-authored-by: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/block-editor/README.md | 42 ++++++++++++ .../src/components/rich-text/index.js | 4 +- .../block-editor/src/hooks/block-bindings.js | 10 +-- packages/block-editor/src/private-apis.js | 2 - .../block-editor/src/utils/block-bindings.js | 47 +++++++++++++ packages/block-editor/src/utils/index.js | 1 + packages/block-library/src/block/edit.js | 3 +- packages/block-library/src/button/edit.js | 9 ++- packages/block-library/src/image/edit.js | 9 ++- packages/block-library/src/image/image.js | 3 +- packages/blocks/README.md | 66 +++++++++++++++++++ packages/blocks/src/api/index.js | 18 ++--- packages/blocks/src/api/registration.js | 20 +++--- packages/blocks/src/store/reducer.js | 9 ++- .../e2e-tests/plugins/block-bindings/index.js | 8 +-- packages/editor/src/bindings/api.js | 3 +- .../editor/src/hooks/pattern-overrides.js | 3 +- .../components/pattern-overrides-controls.js | 5 +- 18 files changed, 199 insertions(+), 63 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 75d7e8879572d4..32ba4598c4f92d 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -839,6 +839,48 @@ _Related_ - <https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/url-popover/README.md> +### useBlockBindingsUtils + +Retrieves the existing utils needed to update the block `bindings` metadata. They can be used to create, modify, or remove connections from the existing block attributes. + +It contains the following utils: + +- `updateBlockBindings`: Updates the value of the bindings connected to block attributes. It can be used to remove a specific binding by setting the value to `undefined`. +- `removeAllBlockBindings`: Removes the bindings property of the `metadata` attribute. + +_Usage_ + +```js +import { useBlockBindingsUtils } from '@wordpress/block-editor'; +const { updateBlockBindings, removeAllBlockBindings } = useBlockBindingsUtils(); + +// Update url and alt attributes. +updateBlockBindings( { + url: { + source: 'core/post-meta', + args: { + key: 'url_custom_field', + }, + }, + alt: { + source: 'core/post-meta', + args: { + key: 'text_custom_field', + }, + }, +} ); + +// Remove binding from url attribute. +updateBlockBindings( { url: undefined } ); + +// Remove bindings from all attributes. +removeAllBlockBindings(); +``` + +_Returns_ + +- `?WPBlockBindingsUtils`: Object containing the block bindings utils. + ### useBlockCommands Undocumented declaration. diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 26cd2a97b515ed..8a5d99a7eb9f0a 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -20,7 +20,7 @@ import { removeFormat, } from '@wordpress/rich-text'; import { Popover } from '@wordpress/components'; -import { store as blocksStore } from '@wordpress/blocks'; +import { getBlockBindingsSource } from '@wordpress/blocks'; import deprecated from '@wordpress/deprecated'; import { __, sprintf } from '@wordpress/i18n'; @@ -39,7 +39,6 @@ import FormatEdit from './format-edit'; import { getAllowedFormats } from './utils'; import { Content, valueToHTMLString } from './content'; import { withDeprecations } from './with-deprecations'; -import { unlock } from '../../lock-unlock'; import { canBindBlock } from '../../hooks/use-bindings-attributes'; import BlockContext from '../block-context'; @@ -175,7 +174,6 @@ export function RichTextWrapper( } const relatedBinding = blockBindings[ identifier ]; - const { getBlockBindingsSource } = unlock( select( blocksStore ) ); const blockBindingsSource = getBlockBindingsSource( relatedBinding.source ); diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index c258927f2fd6dc..5c002613831ce1 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -2,7 +2,10 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { privateApis as blocksPrivateApis } from '@wordpress/blocks'; +import { + getBlockBindingsSource, + getBlockBindingsSources, +} from '@wordpress/blocks'; import { __experimentalItemGroup as ItemGroup, __experimentalItem as Item, @@ -47,7 +50,6 @@ const useToolsPanelDropdownMenuProps = () => { }; function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) { - const { getBlockBindingsSources } = unlock( blocksPrivateApis ); const registeredSources = getBlockBindingsSources(); const { updateBlockBindings } = useBlockBindingsUtils(); const currentKey = binding?.args?.key; @@ -96,8 +98,7 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) { function BlockBindingsAttribute( { attribute, binding, fieldsList } ) { const { source: sourceName, args } = binding || {}; - const sourceProps = - unlock( blocksPrivateApis ).getBlockBindingsSource( sourceName ); + const sourceProps = getBlockBindingsSource( sourceName ); const isSourceInvalid = ! sourceProps; return ( <VStack className="block-editor-bindings__item" spacing={ 0 }> @@ -200,7 +201,6 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { if ( ! bindableAttributes || bindableAttributes.length === 0 ) { return EMPTY_OBJECT; } - const { getBlockBindingsSources } = unlock( blocksPrivateApis ); const registeredSources = getBlockBindingsSources(); Object.entries( registeredSources ).forEach( ( [ sourceName, { getFieldsList, usesContext } ] ) => { diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 12f477a95a196b..7205bef5798ec1 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -47,7 +47,6 @@ import { PrivatePublishDateTimePicker } from './components/publish-date-time-pic import useSpacingSizes from './components/spacing-sizes-control/hooks/use-spacing-sizes'; import useBlockDisplayTitle from './components/block-title/use-block-display-title'; import TabbedSidebar from './components/tabbed-sidebar'; -import { useBlockBindingsUtils } from './utils/block-bindings'; /** * Private @wordpress/block-editor APIs. @@ -92,6 +91,5 @@ lock( privateApis, { useBlockDisplayTitle, __unstableBlockStyleVariationOverridesWithConfig, setBackgroundStyleDefaults, - useBlockBindingsUtils, sectionRootClientIdKey, } ); diff --git a/packages/block-editor/src/utils/block-bindings.js b/packages/block-editor/src/utils/block-bindings.js index b3daf4f4b36b43..db4de9d39cb253 100644 --- a/packages/block-editor/src/utils/block-bindings.js +++ b/packages/block-editor/src/utils/block-bindings.js @@ -13,6 +13,53 @@ function isObjectEmpty( object ) { return ! object || Object.keys( object ).length === 0; } +/** + * Contains utils to update the block `bindings` metadata. + * + * @typedef {Object} WPBlockBindingsUtils + * + * @property {Function} updateBlockBindings Updates the value of the bindings connected to block attributes. + * @property {Function} removeAllBlockBindings Removes the bindings property of the `metadata` attribute. + */ + +/** + * Retrieves the existing utils needed to update the block `bindings` metadata. + * They can be used to create, modify, or remove connections from the existing block attributes. + * + * It contains the following utils: + * - `updateBlockBindings`: Updates the value of the bindings connected to block attributes. It can be used to remove a specific binding by setting the value to `undefined`. + * - `removeAllBlockBindings`: Removes the bindings property of the `metadata` attribute. + * + * @return {?WPBlockBindingsUtils} Object containing the block bindings utils. + * + * @example + * ```js + * import { useBlockBindingsUtils } from '@wordpress/block-editor' + * const { updateBlockBindings, removeAllBlockBindings } = useBlockBindingsUtils(); + * + * // Update url and alt attributes. + * updateBlockBindings( { + * url: { + * source: 'core/post-meta', + * args: { + * key: 'url_custom_field', + * }, + * }, + * alt: { + * source: 'core/post-meta', + * args: { + * key: 'text_custom_field', + * }, + * }, + * } ); + * + * // Remove binding from url attribute. + * updateBlockBindings( { url: undefined } ); + * + * // Remove bindings from all attributes. + * removeAllBlockBindings(); + * ``` + */ export function useBlockBindingsUtils() { const { clientId } = useBlockEditContext(); const { updateBlockAttributes } = useDispatch( blockEditorStore ); diff --git a/packages/block-editor/src/utils/index.js b/packages/block-editor/src/utils/index.js index 6f53ba585e5ecb..1b5aa769a13b28 100644 --- a/packages/block-editor/src/utils/index.js +++ b/packages/block-editor/src/utils/index.js @@ -1,2 +1,3 @@ export { default as transformStyles } from './transform-styles'; export { default as getPxFromCssUnit } from './get-px-from-css-unit'; +export { useBlockBindingsUtils } from './block-bindings'; diff --git a/packages/block-library/src/block/edit.js b/packages/block-library/src/block/edit.js index 5c90361e6bb435..104b07157cba74 100644 --- a/packages/block-library/src/block/edit.js +++ b/packages/block-library/src/block/edit.js @@ -32,7 +32,7 @@ import { InnerBlocks, } from '@wordpress/block-editor'; import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; -import { store as blocksStore } from '@wordpress/blocks'; +import { getBlockBindingsSource } from '@wordpress/blocks'; /** * Internal dependencies @@ -196,7 +196,6 @@ function ReusableBlockEdit( { ( select ) => { const { getBlocks, getSettings, getBlockEditingMode } = select( blockEditorStore ); - const { getBlockBindingsSource } = unlock( select( blocksStore ) ); // For editing link to the site editor if the theme and user permissions support it. return { innerBlocks: getBlocks( patternClientId ), diff --git a/packages/block-library/src/button/edit.js b/packages/block-library/src/button/edit.js index d7b8e6486c3c66..3539fd54f4eece 100644 --- a/packages/block-library/src/button/edit.js +++ b/packages/block-library/src/button/edit.js @@ -9,7 +9,6 @@ import clsx from 'clsx'; import { NEW_TAB_TARGET, NOFOLLOW_REL } from './constants'; import { getUpdatedLinkAttributes } from './get-updated-link-attributes'; import removeAnchorTag from '../utils/remove-anchor-tag'; -import { unlock } from '../lock-unlock'; /** * WordPress dependencies @@ -45,7 +44,7 @@ import { createBlock, cloneBlock, getDefaultBlockName, - store as blocksStore, + getBlockBindingsSource, } from '@wordpress/blocks'; import { useMergeRefs, useRefEffect } from '@wordpress/compose'; import { useSelect, useDispatch } from '@wordpress/data'; @@ -240,9 +239,9 @@ function ButtonEdit( props ) { return {}; } - const blockBindingsSource = unlock( - select( blocksStore ) - ).getBlockBindingsSource( metadata?.bindings?.url?.source ); + const blockBindingsSource = getBlockBindingsSource( + metadata?.bindings?.url?.source + ); return { lockUrlControls: diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index d44dc73abfd855..360c4b8e6127b8 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -7,7 +7,7 @@ import clsx from 'clsx'; * WordPress dependencies */ import { isBlobURL, createBlobURL } from '@wordpress/blob'; -import { store as blocksStore, createBlock } from '@wordpress/blocks'; +import { createBlock, getBlockBindingsSource } from '@wordpress/blocks'; import { Placeholder } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; import { @@ -28,7 +28,6 @@ import { useResizeObserver } from '@wordpress/compose'; /** * Internal dependencies */ -import { unlock } from '../lock-unlock'; import { useUploadMediaFromBlobURL } from '../utils/hooks'; import Image from './image'; import { isValidFileType } from './utils'; @@ -372,9 +371,9 @@ export function ImageEdit( { return {}; } - const blockBindingsSource = unlock( - select( blocksStore ) - ).getBlockBindingsSource( metadata?.bindings?.url?.source ); + const blockBindingsSource = getBlockBindingsSource( + metadata?.bindings?.url?.source + ); return { lockUrlControls: diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 1673d36e463d5a..89bf31f92664b9 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -34,7 +34,7 @@ import { useEffect, useMemo, useState, useRef } from '@wordpress/element'; import { __, _x, sprintf, isRTL } from '@wordpress/i18n'; import { DOWN } from '@wordpress/keycodes'; import { getFilename } from '@wordpress/url'; -import { switchToBlockType, store as blocksStore } from '@wordpress/blocks'; +import { getBlockBindingsSource, switchToBlockType } from '@wordpress/blocks'; import { crop, overlayText, upload } from '@wordpress/icons'; import { store as noticesStore } from '@wordpress/notices'; import { store as coreStore } from '@wordpress/core-data'; @@ -476,7 +476,6 @@ export default function Image( { if ( ! isSingleSelected ) { return {}; } - const { getBlockBindingsSource } = unlock( select( blocksStore ) ); const { url: urlBinding, alt: altBinding, diff --git a/packages/blocks/README.md b/packages/blocks/README.md index b607286f1e73c7..c5a754f88d4929 100644 --- a/packages/blocks/README.md +++ b/packages/blocks/README.md @@ -115,6 +115,26 @@ _Returns_ - `string[]`: The attribute names that have the provided role. +### getBlockBindingsSource + +Returns a registered block bindings source by its name. + +_Parameters_ + +- _name_ `string`: Block bindings source name. + +_Returns_ + +- `?Object`: Block bindings source. + +### getBlockBindingsSources + +Returns all registered block bindings sources. + +_Returns_ + +- `Array`: Block bindings sources. + ### getBlockContent Given a block object, returns the Block's Inner HTML markup. @@ -492,6 +512,36 @@ _Returns_ - `Array`: A list of blocks. +### registerBlockBindingsSource + +Registers a new block bindings source with an object defining its behavior. Once registered, the source is available to be connected to the supported block attributes. + +_Usage_ + +```js +import { _x } from '@wordpress/i18n'; +import { registerBlockBindingsSource } from '@wordpress/blocks'; + +registerBlockBindingsSource( { + name: 'plugin/my-custom-source', + label: _x( 'My Custom Source', 'block bindings source' ), + usesContext: [ 'postType' ], + getValues: getSourceValues, + setValues: updateMyCustomValuesInBatch, + canUserEditValue: () => true, +} ); +``` + +_Parameters_ + +- _source_ `Object`: Properties of the source to be registered. +- _source.name_ `string`: The unique and machine-readable name. +- _source.label_ `[string]`: Human-readable label. Optional when it is defined in the server. +- _source.usesContext_ `[Array]`: Optional array of context needed by the source only in the editor. +- _source.getValues_ `[Function]`: Optional function to get the values from the source. +- _source.setValues_ `[Function]`: Optional function to update multiple values connected to the source. +- _source.canUserEditValue_ `[Function]`: Optional function to determine if the user can edit the value. + ### registerBlockCollection Registers a new block collection to group blocks in the same namespace in the inserter. @@ -793,6 +843,22 @@ _Returns_ - `Array`: Updated Block list. +### unregisterBlockBindingsSource + +Unregisters a block bindings source by providing its name. + +_Usage_ + +```js +import { unregisterBlockBindingsSource } from '@wordpress/blocks'; + +unregisterBlockBindingsSource( 'plugin/my-custom-source' ); +``` + +_Parameters_ + +- _name_ `string`: The name of the block bindings source to unregister. + ### unregisterBlockStyle Unregisters a block style for the given block. diff --git a/packages/blocks/src/api/index.js b/packages/blocks/src/api/index.js index e23f347fe4fee8..0b38b8e29e68a0 100644 --- a/packages/blocks/src/api/index.js +++ b/packages/blocks/src/api/index.js @@ -2,12 +2,6 @@ * Internal dependencies */ import { lock } from '../lock-unlock'; -import { - registerBlockBindingsSource, - unregisterBlockBindingsSource, - getBlockBindingsSource, - getBlockBindingsSources, -} from './registration'; import { isUnmodifiedBlockContent } from './utils'; // The blocktype is the most important concept within the block API. It defines @@ -147,6 +141,10 @@ export { unregisterBlockStyle, registerBlockVariation, unregisterBlockVariation, + registerBlockBindingsSource, + unregisterBlockBindingsSource, + getBlockBindingsSource, + getBlockBindingsSources, } from './registration'; export { isUnmodifiedBlock, @@ -179,10 +177,4 @@ export { } from './constants'; export const privateApis = {}; -lock( privateApis, { - registerBlockBindingsSource, - unregisterBlockBindingsSource, - getBlockBindingsSource, - getBlockBindingsSources, - isUnmodifiedBlockContent, -} ); +lock( privateApis, { isUnmodifiedBlockContent } ); diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index b0f5ae350759f0..f7d85cd816c9df 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -769,12 +769,11 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { * * @param {Object} source Properties of the source to be registered. * @param {string} source.name The unique and machine-readable name. - * @param {string} [source.label] Human-readable label. - * @param {Array} [source.usesContext] Array of context needed by the source only in the editor. - * @param {Function} [source.getValues] Function to get the values from the source. - * @param {Function} [source.setValues] Function to update multiple values connected to the source. - * @param {Function} [source.canUserEditValue] Function to determine if the user can edit the value. - * @param {Function} [source.getFieldsList] Function to get the lists of fields to expose in the connections panel. + * @param {string} [source.label] Human-readable label. Optional when it is defined in the server. + * @param {Array} [source.usesContext] Optional array of context needed by the source only in the editor. + * @param {Function} [source.getValues] Optional function to get the values from the source. + * @param {Function} [source.setValues] Optional function to update multiple values connected to the source. + * @param {Function} [source.canUserEditValue] Optional function to determine if the user can edit the value. * * @example * ```js @@ -784,8 +783,9 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { * registerBlockBindingsSource( { * name: 'plugin/my-custom-source', * label: _x( 'My Custom Source', 'block bindings source' ), - * getValues: () => getSourceValues(), - * setValues: () => updateMyCustomValuesInBatch(), + * usesContext: [ 'postType' ], + * getValues: getSourceValues, + * setValues: updateMyCustomValuesInBatch, * canUserEditValue: () => true, * } ); * ``` @@ -903,7 +903,7 @@ export const registerBlockBindingsSource = ( source ) => { }; /** - * Unregisters a block bindings source + * Unregisters a block bindings source by providing its name. * * @param {string} name The name of the block bindings source to unregister. * @@ -924,7 +924,7 @@ export function unregisterBlockBindingsSource( name ) { } /** - * Returns a registered block bindings source. + * Returns a registered block bindings source by its name. * * @param {string} name Block bindings source name. * diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 4aa0b922e090fd..7c7fb4763a1cb6 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -393,6 +393,13 @@ function getMergedUsesContext( existingUsesContext = [], newUsesContext = [] ) { export function blockBindingsSources( state = {}, action ) { switch ( action.type ) { case 'ADD_BLOCK_BINDINGS_SOURCE': + // Only open this API in Gutenberg and for `core/post-meta` for the moment. + let getFieldsList; + if ( globalThis.IS_GUTENBERG_PLUGIN ) { + getFieldsList = action.getFieldsList; + } else if ( action.name === 'core/post-meta' ) { + getFieldsList = action.getFieldsList; + } return { ...state, [ action.name ]: { @@ -407,7 +414,7 @@ export function blockBindingsSources( state = {}, action ) { // Only set `canUserEditValue` if `setValues` is also defined. canUserEditValue: action.setValues && action.canUserEditValue, - getFieldsList: action.getFieldsList, + getFieldsList, }, }; case 'ADD_BOOTSTRAPPED_BLOCK_BINDINGS_SOURCE': diff --git a/packages/e2e-tests/plugins/block-bindings/index.js b/packages/e2e-tests/plugins/block-bindings/index.js index 0bfc49041647de..c31502631307d0 100644 --- a/packages/e2e-tests/plugins/block-bindings/index.js +++ b/packages/e2e-tests/plugins/block-bindings/index.js @@ -1,10 +1,4 @@ -const { unlock } = - wp.privateApis.__dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', - '@wordpress/blocks' - ); - -const { registerBlockBindingsSource } = unlock( wp.blocks.privateApis ); +const { registerBlockBindingsSource } = wp.blocks; const { fieldsList } = window.testingBindings || {}; const getValues = ( { bindings } ) => { diff --git a/packages/editor/src/bindings/api.js b/packages/editor/src/bindings/api.js index 2cfed5168a143e..84003fab7eaf7b 100644 --- a/packages/editor/src/bindings/api.js +++ b/packages/editor/src/bindings/api.js @@ -2,8 +2,8 @@ * WordPress dependencies */ import { - privateApis as blocksPrivateApis, store as blocksStore, + registerBlockBindingsSource, } from '@wordpress/blocks'; import { dispatch } from '@wordpress/data'; @@ -25,7 +25,6 @@ import { unlock } from '../lock-unlock'; * ``` */ export function registerCoreBlockBindingsSources() { - const { registerBlockBindingsSource } = unlock( blocksPrivateApis ); registerBlockBindingsSource( patternOverrides ); registerBlockBindingsSource( postMeta ); } diff --git a/packages/editor/src/hooks/pattern-overrides.js b/packages/editor/src/hooks/pattern-overrides.js index 6f81f368351f38..8882856a89e0d9 100644 --- a/packages/editor/src/hooks/pattern-overrides.js +++ b/packages/editor/src/hooks/pattern-overrides.js @@ -6,7 +6,7 @@ import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; import { createHigherOrderComponent } from '@wordpress/compose'; import { useBlockEditingMode } from '@wordpress/block-editor'; import { useSelect } from '@wordpress/data'; -import { store as blocksStore } from '@wordpress/blocks'; +import { getBlockBindingsSource } from '@wordpress/blocks'; /** * Internal dependencies @@ -58,7 +58,6 @@ function ControlsWithStoreSubscription( props ) { const blockEditingMode = useBlockEditingMode(); const { hasPatternOverridesSource, isEditingSyncedPattern } = useSelect( ( select ) => { - const { getBlockBindingsSource } = unlock( select( blocksStore ) ); const { getCurrentPostType, getEditedPostAttribute } = select( editorStore ); diff --git a/packages/patterns/src/components/pattern-overrides-controls.js b/packages/patterns/src/components/pattern-overrides-controls.js index 28dd8788a390c6..5207348c7bd7c6 100644 --- a/packages/patterns/src/components/pattern-overrides-controls.js +++ b/packages/patterns/src/components/pattern-overrides-controls.js @@ -4,7 +4,7 @@ import { useState, useId } from '@wordpress/element'; import { InspectorControls, - privateApis as blockEditorPrivateApis, + useBlockBindingsUtils, } from '@wordpress/block-editor'; import { BaseControl, Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; @@ -17,9 +17,6 @@ import { AllowOverridesModal, DisallowOverridesModal, } from './allow-overrides-modal'; -import { unlock } from '../lock-unlock'; - -const { useBlockBindingsUtils } = unlock( blockEditorPrivateApis ); function PatternOverridesControls( { attributes, From 022139bc84ab4683c710ca50cd7847a5db93dec7 Mon Sep 17 00:00:00 2001 From: Robert Anderson <robert@noisysocks.com> Date: Tue, 1 Oct 2024 11:24:14 +1000 Subject: [PATCH 1027/1908] Update versions-in-wordpress.md --- docs/contributors/versions-in-wordpress.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/contributors/versions-in-wordpress.md b/docs/contributors/versions-in-wordpress.md index 8c4debb8b696f6..62347f2d644a61 100644 --- a/docs/contributors/versions-in-wordpress.md +++ b/docs/contributors/versions-in-wordpress.md @@ -6,6 +6,7 @@ If anything looks incorrect here, please bring it up in #core-editor in [WordPre | Gutenberg Versions | WordPress Version | | ------------------ | ----------------- | +| 18.6-19.3 | 6.7 | | 17.8-18.5 | 6.6.1 | | 17.8-18.5 | 6.6 | | 16.8-17.7 | 6.5.5 | From f5d309948114765c25797e7ed382b1d14cc8622b Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:42:13 +0900 Subject: [PATCH 1028/1908] List view: fix miscolored icons (#65707) * List view: fix miscolored icons * Add forced-colors media query Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../block-editor/src/components/list-view/style.scss | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/block-editor/src/components/list-view/style.scss b/packages/block-editor/src/components/list-view/style.scss index 297fb9d0a6a2e8..2916622efabee9 100644 --- a/packages/block-editor/src/components/list-view/style.scss +++ b/packages/block-editor/src/components/list-view/style.scss @@ -41,6 +41,15 @@ &:hover { color: var(--wp-admin-theme-color); } + + svg { + fill: currentColor; + // Optimizate for high contrast modes. + // See also https://blogs.windows.com/msedgedev/2020/09/17/styling-for-windows-high-contrast-with-new-standards-for-forced-colors/. + @media (forced-colors: active) { + fill: CanvasText; + } + } } &:not(.is-selected) .block-editor-list-view-block-select-button { From 40ceb006ef32ec2df655a664c0021cc7e5965d23 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:49:00 +0900 Subject: [PATCH 1029/1908] Buttons: add box-sizing:border-box rule (#65716) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/block-library/src/buttons/style.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/block-library/src/buttons/style.scss b/packages/block-library/src/buttons/style.scss index 8492553bd50b81..e563f3957f3746 100644 --- a/packages/block-library/src/buttons/style.scss +++ b/packages/block-library/src/buttons/style.scss @@ -2,6 +2,8 @@ $blocks-block__margin: 0.5em; .wp-block-buttons { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; &.is-vertical { flex-direction: column; From 6f98f5125f9a01f0783c52ac4a9fff2601914df4 Mon Sep 17 00:00:00 2001 From: davy440 <divjotdavy@gmail.com> Date: Tue, 1 Oct 2024 01:02:13 -0400 Subject: [PATCH 1030/1908] Update block-filters.md (#64959) * Update block-filters.md Added description for `blocks.getBlockAttributes` filter * Modified example and provided additional info * modified example and provided additional info Explained the parameters accepted by the filter callback function. * modified example and provided additional info Fixed parameter names. * Update docs/reference-guides/filters/block-filters.md Thanks Co-authored-by: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> * Update docs/reference-guides/filters/block-filters.md thanks for fix Co-authored-by: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> * Update docs/reference-guides/filters/block-filters.md thanks for fix Co-authored-by: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> * Update docs/reference-guides/filters/block-filters.md thanks for fix Co-authored-by: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> * Update docs/reference-guides/filters/block-filters.md thanks for fix Co-authored-by: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> * Update docs/reference-guides/filters/block-filters.md Thanks for the suggestion. Not aware of the format since it's my first time. Co-authored-by: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> --------- Co-authored-by: davy440 <indithemes@git.wordpress.org> Co-authored-by: akasunil <sunil25393@git.wordpress.org> --- .../reference-guides/filters/block-filters.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/reference-guides/filters/block-filters.md b/docs/reference-guides/filters/block-filters.md index 637cecadf1402b..f1952ef9bf86f8 100644 --- a/docs/reference-guides/filters/block-filters.md +++ b/docs/reference-guides/filters/block-filters.md @@ -294,6 +294,31 @@ Used to filter an individual transform result from block transformation. All of Called immediately after the default parsing of a block's attributes and before validation to allow a plugin to manipulate attribute values in time for validation and/or the initial values rendering of the block in the editor. +The callback function for this filter accepts 4 parameters: +- `blockAttributes` (`Object`): All block attributes. +- `blockType` (`Object`): The block type. +- `innerHTML` (`string`): Raw block content. +- `attributes` (`object`): Known block attributes (from delimiters). + +In the example below, we use the `blocks.getBlockAttributes` filter to lock the position of all paragraph blocks on a page. + +```js +// Our filter function +function lockParagraphs( blockAttributes, blockType, innerHTML, attributes ) { + if('core/paragraph' === blockType.name) { + blockAttributes['lock'] = {move: true} + } + return blockAttributes; +} + +// Add the filter +wp.hooks.addFilter( + 'blocks.getBlockAttributes', + 'my-plugin/lock-paragraphs', + lockParagraphs +); +``` + ### `editor.BlockEdit` Used to modify the block's `edit` component. It receives the original block `BlockEdit` component and returns a new wrapped component. From 1bf729a2dce576ae41921a80e97069470a2de4ae Mon Sep 17 00:00:00 2001 From: Andrei Draganescu <me@andreidraganescu.info> Date: Tue, 1 Oct 2024 08:12:37 +0300 Subject: [PATCH 1031/1908] limit zoom out toggle to specific post types (#65732) Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> --- packages/editor/src/components/header/index.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index b5ec9032aac596..f49ada48997ce5 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -57,15 +57,18 @@ function Header( { showIconLabels, hasFixedToolbar, isNestedEntity, + postType, } = useSelect( ( select ) => { const { get: getPreference } = select( preferencesStore ); const { getEditorMode, getEditorSettings, + getCurrentPostType, isPublishSidebarOpened: _isPublishSidebarOpened, } = select( editorStore ); return { + postType: getCurrentPostType(), isTextEditor: getEditorMode() === 'text', isPublishSidebarOpened: _isPublishSidebarOpened(), showIconLabels: getPreference( 'core', 'showIconLabels' ), @@ -75,6 +78,10 @@ function Header( { }; }, [] ); + const canBeZoomedOut = [ 'post', 'page', 'wp_template' ].includes( + postType + ); + const [ isBlockToolsCollapsed, setIsBlockToolsCollapsed ] = useState( true ); @@ -135,7 +142,9 @@ function Header( { <PostSavedState forceIsDirty={ forceIsDirty } /> ) } - { isEditorIframed && isWideViewport && <ZoomOutToggle /> } + { canBeZoomedOut && isEditorIframed && isWideViewport && ( + <ZoomOutToggle /> + ) } <PreviewDropdown forceIsAutosaveable={ forceIsDirty } From aa2c25a133ef04d9105a7110237a4a4cf480a9e6 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Tue, 1 Oct 2024 09:55:15 +0300 Subject: [PATCH 1032/1908] SearchControl: Fix rest props mutation (#65740) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/components/src/search-control/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/src/search-control/index.tsx b/packages/components/src/search-control/index.tsx index aac905e137e025..c41eda9b209b6c 100644 --- a/packages/components/src/search-control/index.tsx +++ b/packages/components/src/search-control/index.tsx @@ -67,7 +67,7 @@ function UnforwardedSearchControl( ) { // @ts-expect-error The `disabled` prop is not yet supported in the SearchControl component. // Work with the design team (@WordPress/gutenberg-design) if you need this feature. - delete restProps.disabled; + const { disabled, ...filteredRestProps } = restProps; const searchRef = useRef< HTMLInputElement >( null ); const instanceId = useInstanceId( @@ -117,7 +117,7 @@ function UnforwardedSearchControl( /> </SuffixItemWrapper> } - { ...restProps } + { ...filteredRestProps } /> </ContextSystemProvider> ); From df27bd934838d56271224c76d54402886b88160c Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:29:24 +0300 Subject: [PATCH 1033/1908] Edit Site: Fix useLink prop mutation (#65739) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/edit-site/src/components/routes/link.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/edit-site/src/components/routes/link.js b/packages/edit-site/src/components/routes/link.js index 4423eeeb1d6e8d..a34b37943a0799 100644 --- a/packages/edit-site/src/components/routes/link.js +++ b/packages/edit-site/src/components/routes/link.js @@ -33,14 +33,17 @@ export function useLink( params, state, shouldReplace = false ) { ...Object.keys( currentArgs ) ); + let extraParams = {}; if ( isPreviewingTheme() ) { - params = { - ...params, + extraParams = { wp_theme_preview: currentlyPreviewingTheme(), }; } - const newUrl = addQueryArgs( currentUrlWithoutArgs, params ); + const newUrl = addQueryArgs( currentUrlWithoutArgs, { + ...params, + ...extraParams, + } ); return { href: newUrl, From 72472a8720d349a4905dc8f90603321f52b135e6 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 1 Oct 2024 20:50:25 +0900 Subject: [PATCH 1034/1908] Button: Add `__next40pxDefaultSize` in block-editor 6 (#65742) * Fix in Skip to selected block * Fix in Tool selector * Fix in URLInputButton * Fix in URLInput * Remove dead code in FlexLayoutVerticalAlignmentControl Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../skip-to-selected-block/index.js | 3 +- .../skip-to-selected-block/style.scss | 9 --- .../src/components/tool-selector/index.js | 3 +- .../src/components/url-input/button.js | 28 +++++---- .../src/components/url-input/index.js | 3 +- .../src/components/url-input/style.scss | 6 -- packages/block-editor/src/layouts/flex.js | 63 +++---------------- 7 files changed, 29 insertions(+), 86 deletions(-) diff --git a/packages/block-editor/src/components/skip-to-selected-block/index.js b/packages/block-editor/src/components/skip-to-selected-block/index.js index dee7f37550e379..2b52433480f3e6 100644 --- a/packages/block-editor/src/components/skip-to-selected-block/index.js +++ b/packages/block-editor/src/components/skip-to-selected-block/index.js @@ -28,8 +28,7 @@ export default function SkipToSelectedBlock() { return selectedBlockClientId ? ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="secondary" className="block-editor-skip-to-selected-block" onClick={ onClick } diff --git a/packages/block-editor/src/components/skip-to-selected-block/style.scss b/packages/block-editor/src/components/skip-to-selected-block/style.scss index 075e9d3c522653..8a1933423e2f9e 100644 --- a/packages/block-editor/src/components/skip-to-selected-block/style.scss +++ b/packages/block-editor/src/components/skip-to-selected-block/style.scss @@ -3,18 +3,9 @@ top: -9999em; &:focus { - height: auto; - width: auto; - display: block; font-size: 14px; font-weight: 600; - padding: 15px 23px 14px; background: #f1f1f1; - color: var(--wp-admin-theme-color); - line-height: normal; - box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6); - text-decoration: none; - outline: none; z-index: z-index(".skip-to-selected-block"); } } diff --git a/packages/block-editor/src/components/tool-selector/index.js b/packages/block-editor/src/components/tool-selector/index.js index fbaf8af5fac688..fbbf03af7921a7 100644 --- a/packages/block-editor/src/components/tool-selector/index.js +++ b/packages/block-editor/src/components/tool-selector/index.js @@ -44,8 +44,7 @@ function ToolSelector( props, ref ) { <Dropdown renderToggle={ ( { isOpen, onToggle } ) => ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + size="compact" { ...props } ref={ ref } icon={ mode === 'navigation' ? editIcon : selectIcon } diff --git a/packages/block-editor/src/components/url-input/button.js b/packages/block-editor/src/components/url-input/button.js index 8170ea614ace26..560f5cd7d3d5db 100644 --- a/packages/block-editor/src/components/url-input/button.js +++ b/packages/block-editor/src/components/url-input/button.js @@ -3,7 +3,10 @@ */ import { __ } from '@wordpress/i18n'; import { Component } from '@wordpress/element'; -import { Button } from '@wordpress/components'; +import { + Button, + __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper, +} from '@wordpress/components'; import { link, keyboardReturn, arrowLeft } from '@wordpress/icons'; /** @@ -38,8 +41,7 @@ class URLInputButton extends Component { return ( <div className="block-editor-url-input__button"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + size="compact" icon={ link } label={ buttonLabel } onClick={ this.toggle } @@ -53,8 +55,7 @@ class URLInputButton extends Component { > <div className="block-editor-url-input__button-modal-line"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className="block-editor-url-input__back" icon={ arrowLeft } label={ __( 'Close' ) } @@ -63,13 +64,16 @@ class URLInputButton extends Component { <URLInput value={ url || '' } onChange={ onChange } - /> - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - icon={ keyboardReturn } - label={ __( 'Submit' ) } - type="submit" + suffix={ + <InputControlSuffixWrapper variant="control"> + <Button + size="small" + icon={ keyboardReturn } + label={ __( 'Submit' ) } + type="submit" + /> + </InputControlSuffixWrapper> + } /> </div> </form> diff --git a/packages/block-editor/src/components/url-input/index.js b/packages/block-editor/src/components/url-input/index.js index 25c033e88749bb..cb058be5c932f6 100644 --- a/packages/block-editor/src/components/url-input/index.js +++ b/packages/block-editor/src/components/url-input/index.js @@ -540,8 +540,7 @@ class URLInput extends Component { > { suggestions.map( ( suggestion, index ) => ( <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize { ...buildSuggestionItemProps( suggestion, index ) } key={ suggestion.id } className={ clsx( diff --git a/packages/block-editor/src/components/url-input/style.scss b/packages/block-editor/src/components/url-input/style.scss index 155a594bae5f23..ef37566f8e34e0 100644 --- a/packages/block-editor/src/components/url-input/style.scss +++ b/packages/block-editor/src/components/url-input/style.scss @@ -109,10 +109,4 @@ $input-size: 300px; flex-shrink: 1; min-width: 0; align-items: flex-start; - - .components-button { - flex-shrink: 0; - width: $button-size; - height: $button-size; - } } diff --git a/packages/block-editor/src/layouts/flex.js b/packages/block-editor/src/layouts/flex.js index dc7e9d1a167a19..81718449695651 100644 --- a/packages/block-editor/src/layouts/flex.js +++ b/packages/block-editor/src/layouts/flex.js @@ -12,7 +12,6 @@ import { arrowDown, } from '@wordpress/icons'; import { - Button, ToggleControl, Flex, FlexItem, @@ -110,7 +109,6 @@ export default { <FlexLayoutVerticalAlignmentControl layout={ layout } onChange={ onChange } - isToolbar /> ) } </BlockControls> @@ -190,11 +188,7 @@ export default { }, }; -function FlexLayoutVerticalAlignmentControl( { - layout, - onChange, - isToolbar = false, -} ) { +function FlexLayoutVerticalAlignmentControl( { layout, onChange } ) { const { orientation = 'horizontal' } = layout; const defaultVerticalAlignment = @@ -210,54 +204,17 @@ function FlexLayoutVerticalAlignmentControl( { verticalAlignment: value, } ); }; - if ( isToolbar ) { - return ( - <BlockVerticalAlignmentControl - onChange={ onVerticalAlignmentChange } - value={ verticalAlignment } - controls={ - orientation === 'horizontal' - ? [ 'top', 'center', 'bottom', 'stretch' ] - : [ 'top', 'center', 'bottom', 'space-between' ] - } - /> - ); - } - - const verticalAlignmentOptions = [ - { - value: 'flex-start', - label: __( 'Align items top' ), - }, - { - value: 'center', - label: __( 'Align items center' ), - }, - { - value: 'flex-end', - label: __( 'Align items bottom' ), - }, - ]; return ( - <fieldset className="block-editor-hooks__flex-layout-vertical-alignment-control"> - <legend>{ __( 'Vertical alignment' ) }</legend> - <div> - { verticalAlignmentOptions.map( ( value, icon, label ) => { - return ( - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - key={ value } - label={ label } - icon={ icon } - isPressed={ verticalAlignment === value } - onClick={ () => onVerticalAlignmentChange( value ) } - /> - ); - } ) } - </div> - </fieldset> + <BlockVerticalAlignmentControl + onChange={ onVerticalAlignmentChange } + value={ verticalAlignment } + controls={ + orientation === 'horizontal' + ? [ 'top', 'center', 'bottom', 'stretch' ] + : [ 'top', 'center', 'bottom', 'space-between' ] + } + /> ); } From 8e4aac8d2b435bb8ac74851ebff86cae1547a404 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 1 Oct 2024 14:47:37 +0200 Subject: [PATCH 1035/1908] Navigator: use stable export instead of experimental export (#65753) * Navigator: use stable export instead of experimental export * More clear export of useNavigator --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../inserter/mobile-tab-navigation.js | 23 +++++++--------- packages/components/src/index.ts | 7 +++-- .../components/global-styles-sidebar/index.js | 2 +- .../font-library-modal/font-card.js | 2 +- .../font-library-modal/font-collection.js | 18 ++++++------- .../font-library-modal/installed-fonts.js | 20 +++++++------- .../global-styles/font-sizes/font-size.js | 2 +- .../src/components/global-styles/header.js | 4 +-- .../global-styles/navigation-button.js | 7 +++-- .../global-styles/screen-revisions/index.js | 2 +- .../global-styles/shadows-edit-panel.js | 2 +- .../src/components/global-styles/ui.js | 11 ++++---- .../preferences-modal-tabs/index.js | 26 +++++++------------ 13 files changed, 57 insertions(+), 69 deletions(-) diff --git a/packages/block-editor/src/components/inserter/mobile-tab-navigation.js b/packages/block-editor/src/components/inserter/mobile-tab-navigation.js index fa8191cc5eaaa0..5f34c3c21d832f 100644 --- a/packages/block-editor/src/components/inserter/mobile-tab-navigation.js +++ b/packages/block-editor/src/components/inserter/mobile-tab-navigation.js @@ -10,10 +10,7 @@ import { __experimentalSpacer as Spacer, __experimentalHeading as Heading, __experimentalView as View, - __experimentalNavigatorProvider as NavigatorProvider, - __experimentalNavigatorScreen as NavigatorScreen, - __experimentalNavigatorButton as NavigatorButton, - __experimentalNavigatorBackButton as NavigatorBackButton, + Navigator, FlexBlock, } from '@wordpress/components'; import { Icon, chevronRight, chevronLeft } from '@wordpress/icons'; @@ -24,7 +21,7 @@ function ScreenHeader( { title } ) { <View> <Spacer marginBottom={ 0 } paddingX={ 4 } paddingY={ 3 }> <HStack spacing={ 2 }> - <NavigatorBackButton + <Navigator.BackButton style={ // TODO: This style override is also used in ToolsPanelHeader. // It should be supported out-of-the-box by Button. @@ -46,14 +43,14 @@ function ScreenHeader( { title } ) { export default function MobileTabNavigation( { categories, children } ) { return ( - <NavigatorProvider + <Navigator initialPath="/" className="block-editor-inserter__mobile-tab-navigation" > - <NavigatorScreen path="/"> + <Navigator.Screen path="/"> <ItemGroup> { categories.map( ( category ) => ( - <NavigatorButton + <Navigator.Button key={ category.name } path={ `/category/${ category.name }` } as={ Item } @@ -67,19 +64,19 @@ export default function MobileTabNavigation( { categories, children } ) { } /> </HStack> - </NavigatorButton> + </Navigator.Button> ) ) } </ItemGroup> - </NavigatorScreen> + </Navigator.Screen> { categories.map( ( category ) => ( - <NavigatorScreen + <Navigator.Screen key={ category.name } path={ `/category/${ category.name }` } > <ScreenHeader title={ __( 'Back' ) } /> { children( category ) } - </NavigatorScreen> + </Navigator.Screen> ) ) } - </NavigatorProvider> + </Navigator> ); } diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index cc3c0265c42208..fe3642f7700772 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -130,9 +130,12 @@ export { NavigatorButton as __experimentalNavigatorButton, NavigatorBackButton as __experimentalNavigatorBackButton, NavigatorToParentButton as __experimentalNavigatorToParentButton, - useNavigator as __experimentalUseNavigator, } from './navigator/legacy'; -export { Navigator, useNavigator } from './navigator'; +export { + Navigator, + useNavigator, + useNavigator as __experimentalUseNavigator, +} from './navigator'; export { default as Notice } from './notice'; export { default as __experimentalNumberControl } from './number-control'; export { default as NoticeList } from './notice/list'; diff --git a/packages/edit-site/src/components/global-styles-sidebar/index.js b/packages/edit-site/src/components/global-styles-sidebar/index.js index b314b5d7e75244..966005907cda4a 100644 --- a/packages/edit-site/src/components/global-styles-sidebar/index.js +++ b/packages/edit-site/src/components/global-styles-sidebar/index.js @@ -6,7 +6,7 @@ import { FlexBlock, Flex, Button, - __experimentalUseNavigator as useNavigator, + useNavigator, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { styles, seen, backup } from '@wordpress/icons'; diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js index 579c6564fdf3e7..61f8c28c77144f 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-card.js @@ -3,7 +3,7 @@ */ import { _n, sprintf, isRTL } from '@wordpress/i18n'; import { - __experimentalUseNavigator as useNavigator, + useNavigator, __experimentalText as Text, Button, Flex, diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js index ce7b4c1766c64f..caf339091de752 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js @@ -13,9 +13,7 @@ import { __experimentalText as Text, __experimentalHStack as HStack, __experimentalVStack as VStack, - __experimentalNavigatorProvider as NavigatorProvider, - __experimentalNavigatorScreen as NavigatorScreen, - __experimentalNavigatorBackButton as NavigatorBackButton, + Navigator, __experimentalHeading as Heading, Notice, SelectControl, @@ -284,11 +282,11 @@ function FontCollection( { slug } ) { { ! isLoading && ( <> - <NavigatorProvider + <Navigator initialPath="/" className="font-library-modal__tabpanel-layout" > - <NavigatorScreen path="/"> + <Navigator.Screen path="/"> <HStack justify="space-between"> <VStack> <Heading level={ 2 } size={ 13 }> @@ -378,11 +376,11 @@ function FontCollection( { slug } ) { </ul> { /* eslint-enable jsx-a11y/no-redundant-roles */ } </div> - </NavigatorScreen> + </Navigator.Screen> - <NavigatorScreen path="/fontFamily"> + <Navigator.Screen path="/fontFamily"> <Flex justify="flex-start"> - <NavigatorBackButton + <Navigator.BackButton icon={ isRTL() ? chevronRight : chevronLeft } @@ -463,8 +461,8 @@ function FontCollection( { slug } ) { { /* eslint-enable jsx-a11y/no-redundant-roles */ } </VStack> <Spacer margin={ 16 } /> - </NavigatorScreen> - </NavigatorProvider> + </Navigator.Screen> + </Navigator> { selectedFont && ( <Flex diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js index 8cb023fff08e96..b7666a66afe0b3 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js @@ -6,10 +6,8 @@ import { __experimentalConfirmDialog as ConfirmDialog, __experimentalHStack as HStack, __experimentalHeading as Heading, - __experimentalNavigatorProvider as NavigatorProvider, - __experimentalNavigatorScreen as NavigatorScreen, - __experimentalNavigatorBackButton as NavigatorBackButton, - __experimentalUseNavigator as useNavigator, + Navigator, + useNavigator, __experimentalSpacer as Spacer, __experimentalText as Text, __experimentalVStack as VStack, @@ -235,12 +233,12 @@ function InstalledFonts() { { ! isResolvingLibrary && ( <> - <NavigatorProvider + <Navigator initialPath={ libraryFontSelected ? '/fontFamily' : '/' } > - <NavigatorScreen path="/"> + <Navigator.Screen path="/"> <VStack spacing="8"> { notice && ( <Notice @@ -338,9 +336,9 @@ function InstalledFonts() { </VStack> ) } </VStack> - </NavigatorScreen> + </Navigator.Screen> - <NavigatorScreen path="/fontFamily"> + <Navigator.Screen path="/fontFamily"> <ConfirmDeleteDialog font={ libraryFontSelected } isOpen={ isConfirmDeleteOpen } @@ -353,7 +351,7 @@ function InstalledFonts() { /> <Flex justify="flex-start"> - <NavigatorBackButton + <Navigator.BackButton icon={ isRTL() ? chevronRight : chevronLeft } @@ -427,8 +425,8 @@ function InstalledFonts() { </ul> { /* eslint-enable jsx-a11y/no-redundant-roles */ } </VStack> - </NavigatorScreen> - </NavigatorProvider> + </Navigator.Screen> + </Navigator> <HStack justify="flex-end" diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js index 25ff6812d583c9..80b1ea55c405bc 100644 --- a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js @@ -5,7 +5,7 @@ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { __, sprintf } from '@wordpress/i18n'; import { __experimentalSpacer as Spacer, - __experimentalUseNavigator as useNavigator, + useNavigator, __experimentalView as View, __experimentalHStack as HStack, __experimentalVStack as VStack, diff --git a/packages/edit-site/src/components/global-styles/header.js b/packages/edit-site/src/components/global-styles/header.js index 1d9de84183aef7..1bbff8fb3d6a6d 100644 --- a/packages/edit-site/src/components/global-styles/header.js +++ b/packages/edit-site/src/components/global-styles/header.js @@ -7,7 +7,7 @@ import { __experimentalSpacer as Spacer, __experimentalHeading as Heading, __experimentalView as View, - __experimentalNavigatorBackButton as NavigatorBackButton, + Navigator, } from '@wordpress/components'; import { isRTL, __ } from '@wordpress/i18n'; import { chevronRight, chevronLeft } from '@wordpress/icons'; @@ -18,7 +18,7 @@ function ScreenHeader( { title, description, onBack } ) { <View> <Spacer marginBottom={ 0 } paddingX={ 4 } paddingY={ 3 }> <HStack spacing={ 2 }> - <NavigatorBackButton + <Navigator.BackButton icon={ isRTL() ? chevronRight : chevronLeft } size="small" label={ __( 'Back' ) } diff --git a/packages/edit-site/src/components/global-styles/navigation-button.js b/packages/edit-site/src/components/global-styles/navigation-button.js index 5bc8a50e0e2f45..62af9740e8ae1a 100644 --- a/packages/edit-site/src/components/global-styles/navigation-button.js +++ b/packages/edit-site/src/components/global-styles/navigation-button.js @@ -2,8 +2,7 @@ * WordPress dependencies */ import { - __experimentalNavigatorButton as NavigatorButton, - __experimentalNavigatorBackButton as NavigatorBackButton, + Navigator, __experimentalItem as Item, FlexItem, __experimentalHStack as HStack, @@ -29,11 +28,11 @@ function GenericNavigationButton( { icon, children, ...props } ) { } function NavigationButtonAsItem( props ) { - return <NavigatorButton as={ GenericNavigationButton } { ...props } />; + return <Navigator.Button as={ GenericNavigationButton } { ...props } />; } function NavigationBackButtonAsItem( props ) { - return <NavigatorBackButton as={ GenericNavigationButton } { ...props } />; + return <Navigator.BackButton as={ GenericNavigationButton } { ...props } />; } export { NavigationButtonAsItem, NavigationBackButtonAsItem }; diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/index.js b/packages/edit-site/src/components/global-styles/screen-revisions/index.js index de27e92113b554..89af705cd92504 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/index.js +++ b/packages/edit-site/src/components/global-styles/screen-revisions/index.js @@ -3,7 +3,7 @@ */ import { __, sprintf } from '@wordpress/i18n'; import { - __experimentalUseNavigator as useNavigator, + useNavigator, __experimentalConfirmDialog as ConfirmDialog, Spinner, } from '@wordpress/components'; diff --git a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js index ec1dd1a900c3bf..f12f960f6a36bb 100644 --- a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js +++ b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js @@ -15,7 +15,7 @@ import { __experimentalUnitControl as UnitControl, __experimentalGrid as Grid, __experimentalDropdownContentWrapper as DropdownContentWrapper, - __experimentalUseNavigator as useNavigator, + useNavigator, __experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControlOption as ToggleGroupControlOption, __experimentalConfirmDialog as ConfirmDialog, diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index b1550d2a245131..fbc3e461e6abb6 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -2,9 +2,8 @@ * WordPress dependencies */ import { - __experimentalNavigatorProvider as NavigatorProvider, - __experimentalNavigatorScreen as NavigatorScreen, - __experimentalUseNavigator as useNavigator, + Navigator, + useNavigator, createSlotFill, DropdownMenu, MenuGroup, @@ -124,7 +123,7 @@ function GlobalStylesActionMenu() { function GlobalStylesNavigationScreen( { className, ...props } ) { return ( - <NavigatorScreen + <Navigator.Screen className={ [ 'edit-site-global-styles-sidebar__navigator-screen', className, @@ -283,7 +282,7 @@ function GlobalStylesUI() { [] ); return ( - <NavigatorProvider + <Navigator className="edit-site-global-styles-sidebar__navigator-provider" initialPath="/" > @@ -385,7 +384,7 @@ function GlobalStylesUI() { <GlobalStylesActionMenu /> <GlobalStylesBlockLink /> <GlobalStylesEditorCanvasContainerLink /> - </NavigatorProvider> + </Navigator> ); } export { GlobalStylesMenuSlot }; diff --git a/packages/preferences/src/components/preferences-modal-tabs/index.js b/packages/preferences/src/components/preferences-modal-tabs/index.js index d87e565f5e3364..f73bdd7f029dc7 100644 --- a/packages/preferences/src/components/preferences-modal-tabs/index.js +++ b/packages/preferences/src/components/preferences-modal-tabs/index.js @@ -3,10 +3,7 @@ */ import { useViewportMatch } from '@wordpress/compose'; import { - __experimentalNavigatorProvider as NavigatorProvider, - __experimentalNavigatorScreen as NavigatorScreen, - __experimentalNavigatorButton as NavigatorButton, - __experimentalNavigatorBackButton as NavigatorBackButton, + Navigator, __experimentalItemGroup as ItemGroup, __experimentalItem as Item, __experimentalHStack as HStack, @@ -98,17 +95,14 @@ export default function PreferencesModalTabs( { sections } ) { ); } else { modalContent = ( - <NavigatorProvider - initialPath="/" - className="preferences__provider" - > - <NavigatorScreen path="/"> + <Navigator initialPath="/" className="preferences__provider"> + <Navigator.Screen path="/"> <Card isBorderless size="small"> <CardBody> <ItemGroup> { tabs.map( ( tab ) => { return ( - <NavigatorButton + <Navigator.Button key={ tab.name } path={ `/${ tab.name }` } as={ Item } @@ -130,17 +124,17 @@ export default function PreferencesModalTabs( { sections } ) { /> </FlexItem> </HStack> - </NavigatorButton> + </Navigator.Button> ); } ) } </ItemGroup> </CardBody> </Card> - </NavigatorScreen> + </Navigator.Screen> { sections.length && sections.map( ( section ) => { return ( - <NavigatorScreen + <Navigator.Screen key={ `${ section.name }-menu` } path={ `/${ section.name }` } > @@ -151,7 +145,7 @@ export default function PreferencesModalTabs( { sections } ) { size="small" gap="6" > - <NavigatorBackButton + <Navigator.BackButton icon={ isRTL() ? chevronRight @@ -165,10 +159,10 @@ export default function PreferencesModalTabs( { sections } ) { </CardHeader> <CardBody>{ section.content }</CardBody> </Card> - </NavigatorScreen> + </Navigator.Screen> ); } ) } - </NavigatorProvider> + </Navigator> ); } From f5378f6f63445b305728a1c44cfb6b4662fc19a2 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 1 Oct 2024 14:52:11 +0200 Subject: [PATCH 1036/1908] Navigator: fix README heading hierarchy (#65763) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/src/navigator/README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/components/src/navigator/README.md b/packages/components/src/navigator/README.md index 00b1cfaeebe0f7..b56a82e0524eef 100644 --- a/packages/components/src/navigator/README.md +++ b/packages/components/src/navigator/README.md @@ -70,6 +70,8 @@ The children elements. #### `Navigator.Screen` +##### Props + ###### `path`: `string` The screen's path, matched against the current path stored in the navigator. @@ -94,7 +96,9 @@ The children elements. - Required: Yes -##### `Navigator.Button` +#### `Navigator.Button` + +##### Props ###### `path`: `string` @@ -119,7 +123,9 @@ The children elements. `Navigator.Button` also inherits all of the [`Button` props](/packages/components/src/button/README.md#props), except for `href` and `target`. -##### `Navigator.BackButton` +#### `Navigator.BackButton` + +##### Props ###### `children`: `string` @@ -131,10 +137,12 @@ The children elements. `Navigator.BackButton` also inherits all of the [`Button` props](/packages/components/src/button/README.md#props), except for `href` and `target`. -###### `useNavigator` +#### `useNavigator` You can retrieve a `navigator` instance by using the `useNavigator` hook. +##### Props + The `navigator` instance has a few properties: ###### `goTo`: `( path: string, options: NavigateOptions ) => void` From 12cd503984b57a69aaa62349a20e8592bb87e5ec Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Tue, 1 Oct 2024 09:17:03 -0500 Subject: [PATCH 1037/1908] Remove editorMode from blockProps (#65326) --- .../src/components/block-list/block.js | 6 ---- .../block-list/use-block-props/index.js | 3 +- .../use-block-props/use-zoom-out-mode-exit.js | 30 ++++++++++++------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 2cecd941dfa3bb..783b45da932a3d 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -609,7 +609,6 @@ function BlockListBlockProvider( props ) { isBlockBeingDragged, isDragging, __unstableHasActiveBlockOverlayActive, - __unstableGetEditorMode, getSelectedBlocksInitialCaretPosition, } = unlock( select( blockEditorStore ) ); const blockWithoutAttributes = @@ -680,8 +679,6 @@ function BlockListBlockProvider( props ) { blocksWithSameName.length && blocksWithSameName[ 0 ] !== clientId; - const editorMode = __unstableGetEditorMode(); - return { ...previewContext, mode: getBlockMode( clientId ), @@ -708,7 +705,6 @@ function BlockListBlockProvider( props ) { ) && hasSelectedInnerBlock( clientId ), blockApiVersion: blockType?.apiVersion || 1, blockTitle: match?.title || blockType?.title, - editorMode, isSubtreeDisabled: blockEditingMode === 'disabled' && isBlockSubtreeDisabled( clientId ), @@ -755,7 +751,6 @@ function BlockListBlockProvider( props ) { themeSupportsLayout, isTemporarilyEditingAsBlocks, blockEditingMode, - editorMode, mayDisplayControls, mayDisplayParentControls, index, @@ -808,7 +803,6 @@ function BlockListBlockProvider( props ) { hasOverlay, initialPosition, blockEditingMode, - editorMode, isHighlighted, isMultiSelected, isPartiallySelected, diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index 1cf1d4908b0768..45fc1d9eb5ea12 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -85,7 +85,6 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { name, blockApiVersion, blockTitle, - editorMode, isSelected, isSubtreeDisabled, hasOverlay, @@ -113,7 +112,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { useBlockRefProvider( clientId ), useFocusHandler( clientId ), useEventHandlers( { clientId, isSelected } ), - useZoomOutModeExit( { editorMode } ), + useZoomOutModeExit(), useIsHovered( { clientId } ), useIntersectionObserver(), useMovingAnimation( { triggerAnimationOnChange: index, clientId } ), diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js b/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js index 92c54bac9b806d..494694952110bb 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js @@ -12,25 +12,27 @@ import { unlock } from '../../../lock-unlock'; /** * Allows Zoom Out mode to be exited by double clicking in the selected block. - * - * @param {string} clientId Block client ID. */ -export function useZoomOutModeExit( { editorMode } ) { - const { getSettings, isZoomOut } = unlock( useSelect( blockEditorStore ) ); +export function useZoomOutModeExit() { + const { getSettings, isZoomOut, __unstableGetEditorMode } = unlock( + useSelect( blockEditorStore ) + ); + const { __unstableSetEditorMode, resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); return useRefEffect( ( node ) => { - // In "compose" mode. - const composeMode = editorMode === 'zoom-out' && isZoomOut(); + function onDoubleClick( event ) { + // In "compose" mode. + const composeMode = + __unstableGetEditorMode() === 'zoom-out' && isZoomOut(); - if ( ! composeMode ) { - return; - } + if ( ! composeMode ) { + return; + } - function onDoubleClick( event ) { if ( ! event.defaultPrevented ) { event.preventDefault(); @@ -52,6 +54,12 @@ export function useZoomOutModeExit( { editorMode } ) { node.removeEventListener( 'dblclick', onDoubleClick ); }; }, - [ editorMode, getSettings, __unstableSetEditorMode ] + [ + getSettings, + __unstableSetEditorMode, + __unstableGetEditorMode, + isZoomOut, + resetZoomLevel, + ] ); } From 8477a6184055c3c8a62c77af354826645dcaf351 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Tue, 1 Oct 2024 16:28:08 +0100 Subject: [PATCH 1038/1908] Temp disable test for Classic Block Media issue (#65793) * Temp disable test * Sounds good. Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> --------- Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> --- test/e2e/specs/editor/blocks/classic.spec.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/e2e/specs/editor/blocks/classic.spec.js b/test/e2e/specs/editor/blocks/classic.spec.js index 95d39906b0d8bb..6896433a3575e4 100644 --- a/test/e2e/specs/editor/blocks/classic.spec.js +++ b/test/e2e/specs/editor/blocks/classic.spec.js @@ -39,7 +39,10 @@ test.describe( 'Classic', () => { await expect.poll( editor.getEditedPostContent ).toBe( 'test' ); } ); - test( 'should insert media, convert to blocks, and undo in one step', async ( { + // Reinitiate once this ticket is fixed: + // https://core.trac.wordpress.org/ticket/60666 + // eslint-disable-next-line playwright/no-skipped-test + test.skip( 'should insert media, convert to blocks, and undo in one step', async ( { editor, mediaUtils, page, From df81c28f6d9402c38b12faf22b3b028f4694eda7 Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Tue, 1 Oct 2024 18:10:02 +0200 Subject: [PATCH 1039/1908] BorderControl: Promote to stable (#65475) * Export without experimental prefix * Update README * Move Storybook stories and add redirect * Add changelog entries * Fix changelog. * Fix changelog (for real?) * Fix changelog * Apply feedback. * Fix changelog * Remove alpha story. * README fix. * Fix default in README * Fix changelog * Remove `showDropdownHeader` prop and the header itself. * Added `showDropdownHeader` as deprecated. * Remove deprecation warning * Add ignores to jsdocs. Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 5 +- .../border-control-dropdown/component.tsx | 15 ----- .../border-control/border-control/README.md | 62 ++++++++----------- .../border-control/component.tsx | 3 +- .../border-control/stories/index.story.tsx | 14 ++--- .../src/border-control/test/index.js | 17 +---- .../components/src/border-control/types.ts | 19 +++--- packages/components/src/index.ts | 6 +- storybook/manager-head.html | 1 + 9 files changed, 53 insertions(+), 89 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index f98f878080aa27..3baddb5cccadd6 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,22 +6,21 @@ - `ToolsPanel`: atomic one-step state update when (un)registering panels ([#65564](https://github.com/WordPress/gutenberg/pull/65564)). - `Navigator`: fix `isInitial` logic ([#65527](https://github.com/WordPress/gutenberg/pull/65527)). -- `ToggleGroupControl`: Fix arrow key navigation in RTL ([#65735](https://github.com/WordPress/gutenberg/pull/65735)). ### Deprecations +- `__experimentalBorderControl` can now be imported as a stable `BorderControl` ([#65475](https://github.com/WordPress/gutenberg/pull/65475)). - `__experimentalBorderBoxControl` can now be imported as a stable `BorderBoxControl` ([#65586](https://github.com/WordPress/gutenberg/pull/65586)). ### Enhancements -- `Tabs`: handle horizontal overflow and large tab lists gracefully ([#64371](https://github.com/WordPress/gutenberg/pull/64371)). +- `BorderControl`: promote to stable ([#65475](https://github.com/WordPress/gutenberg/pull/65475)). - `BorderBoxControl`: promote to stable ([#65586](https://github.com/WordPress/gutenberg/pull/65586)). - `MenuGroup`: Simplify the MenuGroup styles within dropdown menus. ([#65561](https://github.com/WordPress/gutenberg/pull/65561)). - `DatePicker`: Use compact button size. ([#65653](https://github.com/WordPress/gutenberg/pull/65653)). - `Navigator`: add support for exit animation ([#64777](https://github.com/WordPress/gutenberg/pull/64777)). - `Guide`: Update finish button to use the new default size ([#65680](https://github.com/WordPress/gutenberg/pull/65680)). - `BorderControl`: Use `__next40pxDefaultSize` prop for Reset button ([#65682](https://github.com/WordPress/gutenberg/pull/65682)). -- `Navigator`: stabilize APIs ([#64613](https://github.com/WordPress/gutenberg/pull/64613)). ## 28.8.0 (2024-09-19) diff --git a/packages/components/src/border-control/border-control-dropdown/component.tsx b/packages/components/src/border-control/border-control-dropdown/component.tsx index d84d6bea77335b..0223de66a4c78b 100644 --- a/packages/components/src/border-control/border-control-dropdown/component.tsx +++ b/packages/components/src/border-control/border-control-dropdown/component.tsx @@ -7,7 +7,6 @@ import type { CSSProperties } from 'react'; * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { closeSmall } from '@wordpress/icons'; /** * Internal dependencies @@ -17,12 +16,10 @@ import Button from '../../button'; import ColorIndicator from '../../color-indicator'; import ColorPalette from '../../color-palette'; import Dropdown from '../../dropdown'; -import { HStack } from '../../h-stack'; import { VStack } from '../../v-stack'; import type { WordPressComponentProps } from '../../context'; import { contextConnect } from '../../context'; import { useBorderControlDropdown } from './hook'; -import { StyledLabel } from '../../base-control/styles/base-control-styles'; import DropdownContentWrapper from '../../dropdown/dropdown-content-wrapper'; import type { ColorObject } from '../../color-palette/types'; @@ -149,7 +146,6 @@ const BorderControlDropdown = ( popoverContentClassName, popoverControlsClassName, resetButtonClassName, - showDropdownHeader, size, __unstablePopoverProps, ...otherProps @@ -197,17 +193,6 @@ const BorderControlDropdown = ( <> <DropdownContentWrapper paddingSize="medium"> <VStack className={ popoverControlsClassName } spacing={ 6 }> - { showDropdownHeader ? ( - <HStack> - <StyledLabel>{ __( 'Border color' ) }</StyledLabel> - <Button - size="small" - label={ __( 'Close border color' ) } - icon={ closeSmall } - onClick={ onClose } - /> - </HStack> - ) : undefined } <ColorPalette className={ popoverContentClassName } value={ color } diff --git a/packages/components/src/border-control/border-control/README.md b/packages/components/src/border-control/border-control/README.md index 74a212d00026bd..fbd0c10e418d5a 100644 --- a/packages/components/src/border-control/border-control/README.md +++ b/packages/components/src/border-control/border-control/README.md @@ -1,10 +1,6 @@ -# BorderControl +# BorderControl -<div class="callout callout-alert"> -This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. -</div> -<br /> -This component provides control over a border's color, style, and width. +An input control for a border's color, style, and width. ## Development guidelines @@ -21,7 +17,7 @@ a "shape" abstraction. ```jsx import { useState } from 'react'; -import { __experimentalBorderControl as BorderControl } from '@wordpress/components'; +import { BorderControl } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; const colors = [ @@ -58,41 +54,41 @@ colors are organized by multiple origins. Each color may be an object containing a `name` and `color` value. -- Required: No -- Default: `[]` +- Required: No +- Default: `[]` ### `disableCustomColors`: `boolean` This toggles the ability to choose custom colors. -- Required: No +- Required: No ### `disableUnits`: `boolean` This controls whether unit selection should be disabled. -- Required: No +- Required: No ### `enableAlpha`: `boolean` This controls whether the alpha channel will be offered when selecting custom colors. -- Required: No -- Default: `false` +- Required: No +- Default: `true` ### `enableStyle`: `boolean` This controls whether to support border style selection. -- Required: No -- Default: `true` +- Required: No +- Default: `true` ### `hideLabelFromVision`: `boolean` Provides control over whether the label will only be visible to screen readers. -- Required: No +- Required: No ### `isCompact`: `boolean` @@ -100,7 +96,7 @@ This flags the `BorderControl` to render with a more compact appearance. It restricts the width of the control and prevents it from expanding to take up additional space. -- Required: No +- Required: No ### `label`: `string` @@ -109,7 +105,7 @@ If provided, a label will be generated using this as the content. _Whether it is visible only to screen readers is controlled via `hideLabelFromVision`._ -- Required: No +- Required: No ### `onChange`: `( value?: Object ) => void` @@ -118,7 +114,7 @@ that selects or clears, border color, style, or width. _Note: the value may be `undefined` if a user clears all border properties._ -- Required: Yes +- Required: Yes ### `shouldSanitizeBorder`: `boolean` @@ -126,23 +122,16 @@ If opted into, sanitizing the border means that if no width or color have been selected, the border style is also cleared and `undefined` is returned as the new border value. -- Required: No -- Default: true - -### `showDropdownHeader`: `boolean` - -Whether or not to render a header for the border color and style picker -dropdown. The header includes a label for the color picker and a close button. - -- Required: No +- Required: No +- Default: `true` ### `size`: `string` Size of the control. -- Required: No -- Default: `default` -- Allowed values: `default`, `__unstable-large` +- Required: No +- Default: `default` +- Allowed values: `default`, `__unstable-large` ### `value`: `Object` @@ -150,6 +139,7 @@ An object representing a border or `undefined`. Used to set the current border configuration for this component. Example: + ```js { color: '#72aee6', @@ -158,25 +148,25 @@ Example: } ``` -- Required: No +- Required: No ### `width`: `CSSProperties[ 'width' ]` Controls the visual width of the `BorderControl`. It has no effect if the `isCompact` prop is set to `true`. -- Required: No +- Required: No ### `withSlider`: `boolean` Flags whether this `BorderControl` should also render a `RangeControl` for additional control over a border's width. -- Required: No +- Required: No ### `__next40pxDefaultSize`: `boolean` Start opting into the larger default height that will become the default size in a future version. -- Required: No -- Default: `false` +- Required: No +- Default: `false` diff --git a/packages/components/src/border-control/border-control/component.tsx b/packages/components/src/border-control/border-control/component.tsx index e2c96eaa9ffc0d..21be22c9dd55d8 100644 --- a/packages/components/src/border-control/border-control/component.tsx +++ b/packages/components/src/border-control/border-control/component.tsx @@ -91,7 +91,6 @@ const UnconnectedBorderControl = ( previousStyleSelection={ previousStyleSelection } - showDropdownHeader={ showDropdownHeader } __experimentalIsRenderedInSidebar={ __experimentalIsRenderedInSidebar } @@ -141,7 +140,7 @@ const UnconnectedBorderControl = ( * a "shape" abstraction. * * ```jsx - * import { __experimentalBorderControl as BorderControl } from '@wordpress/components'; + * import { BorderControl } from '@wordpress/components'; * import { __ } from '@wordpress/i18n'; * * const colors = [ diff --git a/packages/components/src/border-control/stories/index.story.tsx b/packages/components/src/border-control/stories/index.story.tsx index 9a5349d302c276..0756a18ac5c0e5 100644 --- a/packages/components/src/border-control/stories/index.story.tsx +++ b/packages/components/src/border-control/stories/index.story.tsx @@ -16,7 +16,7 @@ import { BorderControl } from '..'; import type { Border } from '../types'; const meta: Meta< typeof BorderControl > = { - title: 'Components (Experimental)/BorderControl', + title: 'Components/BorderControl', component: BorderControl, argTypes: { onChange: { @@ -93,6 +93,9 @@ export const Default = Template.bind( {} ); Default.args = { colors, label: 'Border', + enableAlpha: true, + enableStyle: true, + shouldSanitizeBorder: true, }; /** @@ -133,12 +136,3 @@ WithMultipleOrigins.args = { ...Default.args, colors: multipleOriginColors, }; - -/** - * Allow the alpha channel to be edited on each color. - */ -export const WithAlphaEnabled = Template.bind( {} ); -WithAlphaEnabled.args = { - ...Default.args, - enableAlpha: true, -}; diff --git a/packages/components/src/border-control/test/index.js b/packages/components/src/border-control/test/index.js index c41dce687cc522..000a89e14a40b3 100644 --- a/packages/components/src/border-control/test/index.js +++ b/packages/components/src/border-control/test/index.js @@ -148,19 +148,6 @@ describe( 'BorderControl', () => { expect( resetButton ).toBeInTheDocument(); } ); - it( 'should render color and style popover header', async () => { - const user = userEvent.setup(); - const props = createProps( { showDropdownHeader: true } ); - render( <BorderControl { ...props } /> ); - await openPopover( user ); - - const headerLabel = screen.getByText( 'Border color' ); - const closeButton = getButton( 'Close border color' ); - - expect( headerLabel ).toBeInTheDocument(); - expect( closeButton ).toBeInTheDocument(); - } ); - it( 'should not render style options when opted out of', async () => { const user = userEvent.setup(); const props = createProps( { enableStyle: false } ); @@ -346,10 +333,10 @@ describe( 'BorderControl', () => { it( 'should take no action when color and style popover is closed', async () => { const user = userEvent.setup(); - const props = createProps( { showDropdownHeader: true } ); + const props = createProps(); render( <BorderControl { ...props } /> ); await openPopover( user ); - await user.click( getButton( 'Close border color' ) ); + await user.keyboard( 'Escape' ); expect( props.onChange ).not.toHaveBeenCalled(); } ); diff --git a/packages/components/src/border-control/types.ts b/packages/components/src/border-control/types.ts index 5e028050d8e18e..8ab614907684d2 100644 --- a/packages/components/src/border-control/types.ts +++ b/packages/components/src/border-control/types.ts @@ -18,12 +18,19 @@ export type Border = { export type ColorProps = Pick< ColorPaletteProps, - 'colors' | 'enableAlpha' | '__experimentalIsRenderedInSidebar' + 'colors' | '__experimentalIsRenderedInSidebar' > & { /** * This toggles the ability to choose custom colors. */ disableCustomColors?: boolean; + /** + * This controls whether the alpha channel will be offered when selecting + * custom colors. + * + * @default true + */ + enableAlpha?: boolean; }; export type LabelProps = { @@ -78,9 +85,8 @@ export type BorderControlProps = ColorProps & */ shouldSanitizeBorder?: boolean; /** - * Whether or not to show the header for the border color and style - * picker dropdown. The header includes a label for the color picker - * and a close button. + * @deprecated This prop no longer has any effect. + * @ignore */ showDropdownHeader?: boolean; /** @@ -139,9 +145,8 @@ export type DropdownProps = ColorProps & */ previousStyleSelection?: string; /** - * Whether or not to render a header for the border color and style picker - * dropdown. The header includes a label for the color picker and a - * close button. + * @deprecated This prop no longer has any effect. + * @ignore */ showDropdownHeader?: boolean; }; diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index fe3642f7700772..69e76b0b91f43f 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -40,7 +40,11 @@ export { isDefinedBorder as __experimentalIsDefinedBorder, isEmptyBorder as __experimentalIsEmptyBorder, } from './border-box-control'; -export { BorderControl as __experimentalBorderControl } from './border-control'; +export { + /** @deprecated Import `BorderControl` instead. */ + BorderControl as __experimentalBorderControl, + BorderControl, +} from './border-control'; export { /** @deprecated Import `BoxControl` instead. */ default as __experimentalBoxControl, diff --git a/storybook/manager-head.html b/storybook/manager-head.html index 8525e48fffa585..dcafe36caefa72 100644 --- a/storybook/manager-head.html +++ b/storybook/manager-head.html @@ -3,6 +3,7 @@ const PREVIOUSLY_EXPERIMENTAL_COMPONENTS = [ 'alignmentmatrixcontrol', 'borderboxcontrol', + 'bordercontrol', 'boxcontrol', 'customselectcontrol-v2', 'dimensioncontrol', From 249f7014cda3e9b036a58911ec0149d67b136d36 Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Tue, 1 Oct 2024 19:04:02 +0200 Subject: [PATCH 1040/1908] ToggleGroupControl: improve animation (#65175) * Refactor utils and switch Tabs indicator animation to `transform`. * docs tweak * Update packages/components/src/tabs/styles.ts Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> * Add RTL support. * Addressed @ciampo's comments. * Correct for antialiasing rounding. * Make antialiasing adjustment optional. * Use larger base value and revert antialiasing adjustment code. * DRY RTL * Remove RTL story (redundant since Storybook has a dynamic setting to test RTL). * Fix bug. * Fix bug (for real this time). * Add changelog entry. * De-cleverfy code. * Sync useResizeObserver with #64943 and make useTrackElementOffsetRect resilient. * Deduplicate utility and clean up. * Minor Tabs code improvement. * Replace framer motion animation with faster CSS animation. * DRY antialiasing factor. * Changelogs. * Various improvements, fixes, and feedback addressed. * Simplify. * Simplify using derived state. * Add similar useOnValueUpdate detail to Tabs. * Fix skipping animation. * Add similar detail to Tabs animation. * Fix setState depth issue. * Fix unit test error. * Add changelog entries * Fix changelog * Update test snapshot. * Depends less on React. * Switch to layout effect for `useOnValueUpdate` * Switched to transform strategy. * Fix resizing bug. * Transition border-radius too. * Undo Tabs changes (no longer relevant). * DRY animation code. * Avoid useless re-runs in effect. * Rename `activeElement` -> `selectedElement` for clarity. * Rename `--indicator-` -> `--selected-` for accuracy. * Minor tweak. * Add safe defaults to CSS custom properties. * Tweak `useSubelementAnimation`. * Fix parent missing when there's no selected option. * Update snapshots * Add docs to utility. * Added note about border-radius. --------- Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 + .../test/__snapshots__/index.tsx.snap | 252 +++++++++++++++--- .../component.tsx | 37 +-- .../styles.ts | 11 - .../toggle-group-control/as-button-group.tsx | 28 +- .../toggle-group-control/as-radio-group.tsx | 28 +- .../toggle-group-control/component.tsx | 81 +++++- .../toggle-group-control/styles.ts | 41 +++ .../src/toggle-group-control/types.ts | 4 +- packages/components/src/utils/element-rect.ts | 19 +- .../src/utils/hooks/use-on-value-update.ts | 4 +- 11 files changed, 395 insertions(+), 114 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 3baddb5cccadd6..2d859184ae381b 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,8 @@ - `ToolsPanel`: atomic one-step state update when (un)registering panels ([#65564](https://github.com/WordPress/gutenberg/pull/65564)). - `Navigator`: fix `isInitial` logic ([#65527](https://github.com/WordPress/gutenberg/pull/65527)). +- `ToggleGroupControl`: Fix arrow key navigation in RTL ([#65735](https://github.com/WordPress/gutenberg/pull/65735)). +- `ToggleGroupControl`: indicator doesn't jump around when the layout around it changes ([#65175](https://github.com/WordPress/gutenberg/pull/65175)). ### Deprecations @@ -21,6 +23,8 @@ - `Navigator`: add support for exit animation ([#64777](https://github.com/WordPress/gutenberg/pull/64777)). - `Guide`: Update finish button to use the new default size ([#65680](https://github.com/WordPress/gutenberg/pull/65680)). - `BorderControl`: Use `__next40pxDefaultSize` prop for Reset button ([#65682](https://github.com/WordPress/gutenberg/pull/65682)). +- `Navigator`: stabilize APIs ([#64613](https://github.com/WordPress/gutenberg/pull/64613)). +- `ToggleGroupControl`: indicator animation is now more lightweight and performant ([#65175](https://github.com/WordPress/gutenberg/pull/65175)). ## 28.8.0 (2024-09-19) diff --git a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap index e9b4f4ca22ab85..6885263d09b23d 100644 --- a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap +++ b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap @@ -60,6 +60,55 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = outline-offset: -2px; } +@media not ( prefers-reduced-motion ) { + .emotion-8.is-animation-enabled::before { + transition-property: transform,border-radius; + transition-duration: 0.2s; + transition-timing-function: ease-out; + } +} + +.emotion-8::before { + content: ''; + position: absolute; + pointer-events: none; + background: #1e1e1e; + outline: 2px solid transparent; + outline-offset: -3px; + --antialiasing-factor: 100; + border-radius: calc( + 1px / + ( + var( --selected-width, 0 ) / + var( --antialiasing-factor ) + ) + )/1px; + left: -1px; + width: calc( var( --antialiasing-factor ) * 1px ); + height: calc( var( --selected-height, 0 ) * 1px ); + transform-origin: left top; + -webkit-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); + -moz-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); + -ms-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); + transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); +} + .emotion-10 { display: -webkit-inline-box; display: -webkit-inline-flex; @@ -150,17 +199,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = line-height: 1; } -.emotion-15 { - background: #1e1e1e; - border-radius: 1px; - position: absolute; - inset: 0; - z-index: 1; - outline: 2px solid transparent; - outline-offset: -3px; -} - -.emotion-18 { +.emotion-17 { -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; @@ -204,22 +243,22 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = } @media not ( prefers-reduced-motion ) { - .emotion-18 { + .emotion-17 { -webkit-transition: background 160ms linear,color 160ms linear,font-weight 60ms linear; transition: background 160ms linear,color 160ms linear,font-weight 60ms linear; } } -.emotion-18::-moz-focus-inner { +.emotion-17::-moz-focus-inner { border: 0; } -.emotion-18[disabled] { +.emotion-17[disabled] { opacity: 0.4; cursor: default; } -.emotion-18:active { +.emotion-17:active { background: #fff; } @@ -280,12 +319,6 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = </svg> </div> </button> - <div> - <div - class="emotion-15" - role="presentation" - /> - </div> </div> <div class="emotion-10 emotion-11" @@ -293,7 +326,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = <button aria-checked="false" aria-label="Lowercase" - class="emotion-18 components-toggle-group-control-option-base" + class="emotion-17 components-toggle-group-control-option-base" data-value="lowercase" data-wp-c16t="true" data-wp-component="ToggleGroupControlOptionBase" @@ -392,6 +425,55 @@ exports[`ToggleGroupControl controlled should render correctly with text options outline-offset: -2px; } +@media not ( prefers-reduced-motion ) { + .emotion-8.is-animation-enabled::before { + transition-property: transform,border-radius; + transition-duration: 0.2s; + transition-timing-function: ease-out; + } +} + +.emotion-8::before { + content: ''; + position: absolute; + pointer-events: none; + background: #1e1e1e; + outline: 2px solid transparent; + outline-offset: -3px; + --antialiasing-factor: 100; + border-radius: calc( + 1px / + ( + var( --selected-width, 0 ) / + var( --antialiasing-factor ) + ) + )/1px; + left: -1px; + width: calc( var( --antialiasing-factor ) * 1px ); + height: calc( var( --selected-height, 0 ) * 1px ); + transform-origin: left top; + -webkit-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); + -moz-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); + -ms-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); + transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); +} + .emotion-10 { display: -webkit-inline-box; display: -webkit-inline-flex; @@ -612,6 +694,55 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] outline-offset: -2px; } +@media not ( prefers-reduced-motion ) { + .emotion-8.is-animation-enabled::before { + transition-property: transform,border-radius; + transition-duration: 0.2s; + transition-timing-function: ease-out; + } +} + +.emotion-8::before { + content: ''; + position: absolute; + pointer-events: none; + background: #1e1e1e; + outline: 2px solid transparent; + outline-offset: -3px; + --antialiasing-factor: 100; + border-radius: calc( + 1px / + ( + var( --selected-width, 0 ) / + var( --antialiasing-factor ) + ) + )/1px; + left: -1px; + width: calc( var( --antialiasing-factor ) * 1px ); + height: calc( var( --selected-height, 0 ) * 1px ); + transform-origin: left top; + -webkit-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); + -moz-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); + -ms-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); + transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); +} + .emotion-10 { display: -webkit-inline-box; display: -webkit-inline-flex; @@ -702,17 +833,7 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] line-height: 1; } -.emotion-15 { - background: #1e1e1e; - border-radius: 1px; - position: absolute; - inset: 0; - z-index: 1; - outline: 2px solid transparent; - outline-offset: -3px; -} - -.emotion-18 { +.emotion-17 { -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; @@ -756,22 +877,22 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] } @media not ( prefers-reduced-motion ) { - .emotion-18 { + .emotion-17 { -webkit-transition: background 160ms linear,color 160ms linear,font-weight 60ms linear; transition: background 160ms linear,color 160ms linear,font-weight 60ms linear; } } -.emotion-18::-moz-focus-inner { +.emotion-17::-moz-focus-inner { border: 0; } -.emotion-18[disabled] { +.emotion-17[disabled] { opacity: 0.4; cursor: default; } -.emotion-18:active { +.emotion-17:active { background: #fff; } @@ -832,12 +953,6 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] </svg> </div> </button> - <div> - <div - class="emotion-15" - role="presentation" - /> - </div> </div> <div class="emotion-10 emotion-11" @@ -845,7 +960,7 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] <button aria-checked="false" aria-label="Lowercase" - class="emotion-18 components-toggle-group-control-option-base" + class="emotion-17 components-toggle-group-control-option-base" data-value="lowercase" data-wp-c16t="true" data-wp-component="ToggleGroupControlOptionBase" @@ -938,6 +1053,55 @@ exports[`ToggleGroupControl uncontrolled should render correctly with text optio outline-offset: -2px; } +@media not ( prefers-reduced-motion ) { + .emotion-8.is-animation-enabled::before { + transition-property: transform,border-radius; + transition-duration: 0.2s; + transition-timing-function: ease-out; + } +} + +.emotion-8::before { + content: ''; + position: absolute; + pointer-events: none; + background: #1e1e1e; + outline: 2px solid transparent; + outline-offset: -3px; + --antialiasing-factor: 100; + border-radius: calc( + 1px / + ( + var( --selected-width, 0 ) / + var( --antialiasing-factor ) + ) + )/1px; + left: -1px; + width: calc( var( --antialiasing-factor ) * 1px ); + height: calc( var( --selected-height, 0 ) * 1px ); + transform-origin: left top; + -webkit-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); + -moz-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); + -ms-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); + transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); +} + .emotion-10 { display: -webkit-inline-box; display: -webkit-inline-flex; diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx index 30d74e68913f22..d8604c59c540f0 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx @@ -3,13 +3,12 @@ */ import type { ForwardedRef } from 'react'; import * as Ariakit from '@ariakit/react'; -import { motion } from 'framer-motion'; /** * WordPress dependencies */ -import { useReducedMotion, useInstanceId } from '@wordpress/compose'; -import { useMemo } from '@wordpress/element'; +import { useInstanceId } from '@wordpress/compose'; +import { useLayoutEffect, useMemo, useRef } from '@wordpress/element'; /** * Internal dependencies @@ -27,12 +26,6 @@ import Tooltip from '../../tooltip'; const { ButtonContentView, LabelView } = styles; -const REDUCED_MOTION_TRANSITION_CONFIG = { - duration: 0, -}; - -const LAYOUT_ID = 'toggle-group-backdrop-shared-layout-id'; - const WithToolTip = ( { showTooltip, text, children }: WithToolTipProps ) => { if ( showTooltip && text ) { return ( @@ -58,7 +51,6 @@ function ToggleGroupControlOptionBase( >, forwardedRef: ForwardedRef< any > ) { - const shouldReduceMotion = useReducedMotion(); const toggleGroupControlContext = useToggleGroupControlContext(); const id = useInstanceId( @@ -107,7 +99,6 @@ function ToggleGroupControlOptionBase( ), [ cx, isDeselectable, isIcon, isPressed, size, className ] ); - const backdropClasses = useMemo( () => cx( styles.backdropView ), [ cx ] ); const buttonOnClick = () => { if ( isDeselectable && isPressed ) { @@ -124,8 +115,15 @@ function ToggleGroupControlOptionBase( ref: forwardedRef, }; + const labelRef = useRef< HTMLDivElement | null >( null ); + useLayoutEffect( () => { + if ( isPressed && labelRef.current ) { + toggleGroupControlContext.setSelectedElement( labelRef.current ); + } + }, [ isPressed, toggleGroupControlContext ] ); + return ( - <LabelView className={ labelViewClasses }> + <LabelView ref={ labelRef } className={ labelViewClasses }> <WithToolTip showTooltip={ showTooltip } text={ otherButtonProps[ 'aria-label' ] } @@ -163,21 +161,6 @@ function ToggleGroupControlOptionBase( </Ariakit.Radio> ) } </WithToolTip> - { /* Animated backdrop using framer motion's shared layout animation */ } - { isPressed ? ( - <motion.div layout layoutRoot> - <motion.div - className={ backdropClasses } - transition={ - shouldReduceMotion - ? REDUCED_MOTION_TRANSITION_CONFIG - : undefined - } - role="presentation" - layoutId={ LAYOUT_ID } - /> - </motion.div> - ) : null } </LabelView> ); } diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts b/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts index 020468991225c1..c0248f9b3f7f22 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts +++ b/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts @@ -119,14 +119,3 @@ const isIconStyles = ( { padding-right: 0; `; }; - -export const backdropView = css` - background: ${ COLORS.gray[ 900 ] }; - border-radius: ${ CONFIG.radiusXSmall }; - position: absolute; - inset: 0; - z-index: 1; - // Windows High Contrast mode will show this outline, but not the box-shadow. - outline: 2px solid transparent; - outline-offset: -3px; -`; diff --git a/packages/components/src/toggle-group-control/toggle-group-control/as-button-group.tsx b/packages/components/src/toggle-group-control/toggle-group-control/as-button-group.tsx index b3f56bccd07c5f..7ce762b6e71df2 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/as-button-group.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/as-button-group.tsx @@ -26,6 +26,7 @@ function UnforwardedToggleGroupControlAsButtonGroup( size, value: valueProp, id: idProp, + setSelectedElement, ...otherProps }: WordPressComponentProps< ToggleGroupControlMainControlProps, @@ -54,16 +55,23 @@ function UnforwardedToggleGroupControlAsButtonGroup( } ); const groupContextValue = useMemo( - () => - ( { - baseId, - value: selectedValue, - setValue: setSelectedValue, - isBlock: ! isAdaptiveWidth, - isDeselectable: true, - size, - } ) as ToggleGroupControlContextProps, - [ baseId, selectedValue, setSelectedValue, isAdaptiveWidth, size ] + (): ToggleGroupControlContextProps => ( { + baseId, + value: selectedValue, + setValue: setSelectedValue, + isBlock: ! isAdaptiveWidth, + isDeselectable: true, + size, + setSelectedElement, + } ), + [ + baseId, + selectedValue, + setSelectedValue, + isAdaptiveWidth, + size, + setSelectedElement, + ] ); return ( diff --git a/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx b/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx index c062e35cb2b72b..342f9f128defd9 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx @@ -33,6 +33,7 @@ function UnforwardedToggleGroupControlAsRadioGroup( size, value: valueProp, id: idProp, + setSelectedElement, ...otherProps }: WordPressComponentProps< ToggleGroupControlMainControlProps, @@ -73,15 +74,24 @@ function UnforwardedToggleGroupControlAsRadioGroup( const setValue = radio.setValue; const groupContextValue = useMemo( - () => - ( { - baseId, - isBlock: ! isAdaptiveWidth, - size, - value: selectedValue, - setValue, - } ) as ToggleGroupControlContextProps, - [ baseId, isAdaptiveWidth, size, selectedValue, setValue ] + (): ToggleGroupControlContextProps => ( { + baseId, + isBlock: ! isAdaptiveWidth, + size, + // @ts-expect-error - This is wrong and we should fix it. + value: selectedValue, + // @ts-expect-error - This is wrong and we should fix it. + setValue, + setSelectedElement, + } ), + [ + baseId, + isAdaptiveWidth, + selectedValue, + setSelectedElement, + setValue, + size, + ] ); return ( diff --git a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx index 1c86c93548f6df..5f8da76676293e 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx @@ -2,13 +2,11 @@ * External dependencies */ import type { ForwardedRef } from 'react'; -import { LayoutGroup } from 'framer-motion'; /** * WordPress dependencies */ -import { useInstanceId } from '@wordpress/compose'; -import { useMemo } from '@wordpress/element'; +import { useLayoutEffect, useMemo, useState } from '@wordpress/element'; /** * Internal dependencies @@ -22,6 +20,68 @@ import { VisualLabelWrapper } from './styles'; import * as styles from './styles'; import { ToggleGroupControlAsRadioGroup } from './as-radio-group'; import { ToggleGroupControlAsButtonGroup } from './as-button-group'; +import { useTrackElementOffsetRect } from '../../utils/element-rect'; +import { useOnValueUpdate } from '../../utils/hooks/use-on-value-update'; +import { useEvent, useMergeRefs } from '@wordpress/compose'; + +/** + * A utility used to animate something (e.g. an indicator for the selected option + * of a component). + * + * It works by tracking the position and size (i.e., the "rect") of a given subelement, + * typically the one that corresponds to the selected option, relative to its offset + * parent. Then it: + * + * - Keeps CSS variables with that information in the parent, so that the animation + * can be implemented with them. + * - Adds a `is-animation-enabled` CSS class when the element changes, so that the + * target (e.g. the indicator) can be animated to its new position. + * - Removes the `is-animation-enabled` class when the animation is done. + */ +function useSubelementAnimation( + subelement?: HTMLElement | null, + { + parent = subelement?.offsetParent as HTMLElement | null | undefined, + prefix = 'subelement', + transitionEndFilter, + }: { + parent?: HTMLElement | null | undefined; + prefix?: string; + transitionEndFilter?: ( event: TransitionEvent ) => boolean; + } = {} +) { + const rect = useTrackElementOffsetRect( subelement ); + + const setProperties = useEvent( () => { + ( Object.keys( rect ) as Array< keyof typeof rect > ).forEach( + ( property ) => + property !== 'element' && + parent?.style.setProperty( + `--${ prefix }-${ property }`, + String( rect[ property ] ) + ) + ); + } ); + useLayoutEffect( () => { + setProperties(); + }, [ rect, setProperties ] ); + useOnValueUpdate( rect.element, ( { previousValue } ) => { + // Only enable the animation when moving from one element to another. + if ( rect.element && previousValue ) { + parent?.classList.add( 'is-animation-enabled' ); + } + } ); + useLayoutEffect( () => { + function onTransitionEnd( event: TransitionEvent ) { + if ( transitionEndFilter?.( event ) ?? true ) { + parent?.classList.remove( 'is-animation-enabled' ); + } + } + parent?.addEventListener( 'transitionend', onTransitionEnd ); + return () => + parent?.removeEventListener( 'transitionend', onTransitionEnd ); + }, [ parent, transitionEndFilter ] ); +} function UnconnectedToggleGroupControl( props: WordPressComponentProps< ToggleGroupControlProps, 'div', false >, @@ -44,10 +104,18 @@ function UnconnectedToggleGroupControl( ...otherProps } = useContextSystem( props, 'ToggleGroupControl' ); - const baseId = useInstanceId( ToggleGroupControl, 'toggle-group-control' ); const normalizedSize = __next40pxDefaultSize && size === 'default' ? '__unstable-large' : size; + const [ selectedElement, setSelectedElement ] = useState< HTMLElement >(); + const [ controlElement, setControlElement ] = useState< HTMLElement >(); + const refs = useMergeRefs( [ setControlElement, forwardedRef ] ); + useSubelementAnimation( value ? selectedElement : undefined, { + parent: controlElement, + prefix: 'selected', + transitionEndFilter: ( event ) => event.pseudoElement === '::before', + } ); + const cx = useCx(); const classes = useMemo( @@ -81,15 +149,16 @@ function UnconnectedToggleGroupControl( ) } <MainControl { ...otherProps } + setSelectedElement={ setSelectedElement } className={ classes } isAdaptiveWidth={ isAdaptiveWidth } label={ label } onChange={ onChange } - ref={ forwardedRef } + ref={ refs } size={ normalizedSize } value={ value } > - <LayoutGroup id={ baseId }>{ children }</LayoutGroup> + { children } </MainControl> </BaseControl> ); diff --git a/packages/components/src/toggle-group-control/toggle-group-control/styles.ts b/packages/components/src/toggle-group-control/toggle-group-control/styles.ts index 8d01c150a45eaf..ee6122126f557f 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/styles.ts +++ b/packages/components/src/toggle-group-control/toggle-group-control/styles.ts @@ -26,6 +26,47 @@ export const toggleGroupControl = ( { ${ toggleGroupControlSize( size ) } ${ ! isDeselectable && enclosingBorders( isBlock ) } + + @media not ( prefers-reduced-motion ) { + &.is-animation-enabled::before { + transition-property: transform, border-radius; + transition-duration: 0.2s; + transition-timing-function: ease-out; + } + } + + &::before { + content: ''; + position: absolute; + pointer-events: none; + background: ${ COLORS.gray[ 900 ] }; + + // Windows High Contrast mode will show this outline, but not the box-shadow. + outline: 2px solid transparent; + outline-offset: -3px; + + /* Using a large value to avoid antialiasing rounding issues + when scaling in the transform, see: https://stackoverflow.com/a/52159123 */ + --antialiasing-factor: 100; + /* Adjusting the border radius to match the scaling in the x axis. */ + border-radius: calc( + ${ CONFIG.radiusXSmall } / + ( + var( --selected-width, 0 ) / + var( --antialiasing-factor ) + ) + ) / ${ CONFIG.radiusXSmall }; + left: -1px; // Correcting for border. + width: calc( var( --antialiasing-factor ) * 1px ); + height: calc( var( --selected-height, 0 ) * 1px ); + transform-origin: left top; + transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) + scaleX( + calc( + var( --selected-width, 0 ) / var( --antialiasing-factor ) + ) + ); + } `; const enclosingBorders = ( isBlock: ToggleGroupControlProps[ 'isBlock' ] ) => { diff --git a/packages/components/src/toggle-group-control/types.ts b/packages/components/src/toggle-group-control/types.ts index d49ef3cbb77cb4..2a4af680263dba 100644 --- a/packages/components/src/toggle-group-control/types.ts +++ b/packages/components/src/toggle-group-control/types.ts @@ -137,9 +137,11 @@ export type ToggleGroupControlContextProps = { size: ToggleGroupControlProps[ 'size' ]; value: ToggleGroupControlProps[ 'value' ]; setValue: ( newValue: string | number | undefined ) => void; + setSelectedElement: ( element: HTMLElement | undefined ) => void; }; export type ToggleGroupControlMainControlProps = Pick< ToggleGroupControlProps, 'children' | 'isAdaptiveWidth' | 'label' | 'size' | 'onChange' | 'value' ->; +> & + Pick< ToggleGroupControlContextProps, 'setSelectedElement' >; diff --git a/packages/components/src/utils/element-rect.ts b/packages/components/src/utils/element-rect.ts index 4c60e4ba51c48a..7c83db4428ca0f 100644 --- a/packages/components/src/utils/element-rect.ts +++ b/packages/components/src/utils/element-rect.ts @@ -9,6 +9,10 @@ import { useEvent, useResizeObserver } from '@wordpress/compose'; * The position and dimensions of an element, relative to its offset parent. */ export type ElementOffsetRect = { + /** + * The element the rect belongs to. + */ + element: HTMLElement | undefined; /** * The distance from the top edge of the offset parent to the top edge of * the element. @@ -43,6 +47,7 @@ export type ElementOffsetRect = { * An `ElementOffsetRect` object with all values set to zero. */ export const NULL_ELEMENT_OFFSET_RECT = { + element: undefined, top: 0, right: 0, bottom: 0, @@ -92,6 +97,7 @@ export function getElementOffsetRect( const scaleY = computedHeight / rect.height; return { + element, // To obtain the adjusted values for the position: // 1. Compute the element's position relative to the offset parent. // 2. Correct for the scale factor. @@ -119,6 +125,9 @@ const POLL_RATE = 100; * Tracks the position and dimensions of an element, relative to its offset * parent. The element can be changed dynamically. * + * When no element is provided (`null` or `undefined`), the hook will return + * a "null" rect, in which all values are `0` and `element` is `undefined`. + * * **Note:** sometimes, the measurement will fail (see `getElementOffsetRect`'s * documentation for more details). When that happens, this hook will attempt * to measure again after a frame, and if that fails, it will poll every 100 @@ -155,10 +164,12 @@ export function useTrackElementOffsetRect( } } ); - useLayoutEffect( - () => setElement( targetElement ), - [ setElement, targetElement ] - ); + useLayoutEffect( () => { + setElement( targetElement ); + if ( ! targetElement ) { + setIndicatorPosition( NULL_ELEMENT_OFFSET_RECT ); + } + }, [ setElement, targetElement ] ); return indicatorPosition; } diff --git a/packages/components/src/utils/hooks/use-on-value-update.ts b/packages/components/src/utils/hooks/use-on-value-update.ts index 05c7173d092fac..15cfc321359e7c 100644 --- a/packages/components/src/utils/hooks/use-on-value-update.ts +++ b/packages/components/src/utils/hooks/use-on-value-update.ts @@ -3,7 +3,7 @@ * WordPress dependencies */ import { useEvent } from '@wordpress/compose'; -import { useRef, useEffect } from '@wordpress/element'; +import { useRef, useLayoutEffect } from '@wordpress/element'; /** * Context object for the `onUpdate` callback of `useOnValueUpdate`. @@ -27,7 +27,7 @@ export function useOnValueUpdate< T >( ) { const previousValueRef = useRef( value ); const updateCallbackEvent = useEvent( onUpdate ); - useEffect( () => { + useLayoutEffect( () => { if ( previousValueRef.current !== value ) { updateCallbackEvent( { previousValue: previousValueRef.current, From e746a6c2bcfa68d6f3bcad21259d89cd08010f3f Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Tue, 1 Oct 2024 14:02:51 -0500 Subject: [PATCH 1041/1908] Fix focus loss when deleting selected block in zoom out mode (#65761) --- .../block-editor/src/components/block-tools/zoom-out-toolbar.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js index b8736de11481a0..f2c073117d2ce8 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js @@ -147,6 +147,7 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { label={ __( 'Delete' ) } onClick={ () => { removeBlock( clientId ); + __unstableContentRef.current?.focus(); } } /> ) } From 58e7844011cbb89bb020e187a62753451c9643ad Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 2 Oct 2024 04:45:57 +0900 Subject: [PATCH 1042/1908] Social Links: Fix block appender size (#65769) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> --- .../block-library/src/social-links/editor.scss | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/packages/block-library/src/social-links/editor.scss b/packages/block-library/src/social-links/editor.scss index f9491cc068f159..11f1ed86d11220 100644 --- a/packages/block-library/src/social-links/editor.scss +++ b/packages/block-library/src/social-links/editor.scss @@ -101,19 +101,10 @@ .wp-block-social-links .block-list-appender { position: static; // display inline. - .block-editor-button-block-appender.components-button.components-button { - padding: $grid-unit-10 - 2px; - } -} - -.wp-block-social-links { - &.has-small-icon-size .block-editor-button-block-appender.components-button.components-button { + .block-editor-button-block-appender { + height: 1.5em; + width: 1.5em; + font-size: inherit; padding: 0; } - &.has-large-icon-size .block-editor-button-block-appender.components-button.components-button { - padding: $grid-unit-20 - 2px; - } - &.has-huge-icon-size .block-editor-button-block-appender.components-button.components-button { - padding: $grid-unit-30 - 1px; - } } From 2f0f6b8bf50606ebb28937efd54e7342366e64f7 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:36:27 +1000 Subject: [PATCH 1043/1908] Revert "Temp disable test for Classic Block Media issue (#65793)" (#65809) This reverts commit 8477a6184055c3c8a62c77af354826645dcaf351. Co-authored-by: peterwilsoncc <peterwilsoncc@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- test/e2e/specs/editor/blocks/classic.spec.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/e2e/specs/editor/blocks/classic.spec.js b/test/e2e/specs/editor/blocks/classic.spec.js index 6896433a3575e4..95d39906b0d8bb 100644 --- a/test/e2e/specs/editor/blocks/classic.spec.js +++ b/test/e2e/specs/editor/blocks/classic.spec.js @@ -39,10 +39,7 @@ test.describe( 'Classic', () => { await expect.poll( editor.getEditedPostContent ).toBe( 'test' ); } ); - // Reinitiate once this ticket is fixed: - // https://core.trac.wordpress.org/ticket/60666 - // eslint-disable-next-line playwright/no-skipped-test - test.skip( 'should insert media, convert to blocks, and undo in one step', async ( { + test( 'should insert media, convert to blocks, and undo in one step', async ( { editor, mediaUtils, page, From c22ed15332bf4ebdbf00eda6112cccf37e81c8f3 Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Wed, 2 Oct 2024 02:26:46 +0200 Subject: [PATCH 1044/1908] Restore accidentally removed entries in changelog (components package) (#65804) Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 2d859184ae381b..4289866ce8b46f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -16,6 +16,7 @@ ### Enhancements +- `Tabs`: handle horizontal overflow and large tab lists gracefully ([#64371](https://github.com/WordPress/gutenberg/pull/64371)). - `BorderControl`: promote to stable ([#65475](https://github.com/WordPress/gutenberg/pull/65475)). - `BorderBoxControl`: promote to stable ([#65586](https://github.com/WordPress/gutenberg/pull/65586)). - `MenuGroup`: Simplify the MenuGroup styles within dropdown menus. ([#65561](https://github.com/WordPress/gutenberg/pull/65561)). From 41804e186cbfbbee75f7cfb1b53ca617c9c26625 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 2 Oct 2024 14:38:06 +1000 Subject: [PATCH 1045/1908] Global style revisions: remove unnecessary `goTo` navigation call (#65810) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/global-styles/screen-revisions/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/index.js b/packages/edit-site/src/components/global-styles/screen-revisions/index.js index 89af705cd92504..b980d199e7be30 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/index.js +++ b/packages/edit-site/src/components/global-styles/screen-revisions/index.js @@ -72,7 +72,6 @@ function ScreenRevisions() { ); const onCloseRevisions = () => { - goTo( '/' ); // Return to global styles main panel. const canvasContainerView = editorCanvasContainerView === 'global-styles-revisions:style-book' ? 'style-book' From 08052d42071822f435242ff0bd1cb33ce9cf7f19 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 2 Oct 2024 08:41:44 +0200 Subject: [PATCH 1046/1908] Block Bindings: Add `@since` tag in bindings apis JSDocs (#65796) * Add tag to `useBlockBindingsUtils` * Add since tag to the registration functions Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> --- packages/block-editor/README.md | 4 ++++ .../block-editor/src/utils/block-bindings.js | 2 ++ packages/blocks/README.md | 16 ++++++++++++++++ packages/blocks/src/api/registration.js | 8 ++++++++ 4 files changed, 30 insertions(+) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 32ba4598c4f92d..a6f3b8980cfd7a 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -881,6 +881,10 @@ _Returns_ - `?WPBlockBindingsUtils`: Object containing the block bindings utils. +_Changelog_ + +`6.7.0` Introduced in WordPress core. + ### useBlockCommands Undocumented declaration. diff --git a/packages/block-editor/src/utils/block-bindings.js b/packages/block-editor/src/utils/block-bindings.js index db4de9d39cb253..2deeb959371742 100644 --- a/packages/block-editor/src/utils/block-bindings.js +++ b/packages/block-editor/src/utils/block-bindings.js @@ -30,6 +30,8 @@ function isObjectEmpty( object ) { * - `updateBlockBindings`: Updates the value of the bindings connected to block attributes. It can be used to remove a specific binding by setting the value to `undefined`. * - `removeAllBlockBindings`: Removes the bindings property of the `metadata` attribute. * + * @since 6.7.0 Introduced in WordPress core. + * * @return {?WPBlockBindingsUtils} Object containing the block bindings utils. * * @example diff --git a/packages/blocks/README.md b/packages/blocks/README.md index c5a754f88d4929..f4805e1c60b381 100644 --- a/packages/blocks/README.md +++ b/packages/blocks/README.md @@ -127,6 +127,10 @@ _Returns_ - `?Object`: Block bindings source. +_Changelog_ + +`6.7.0` Introduced in WordPress core. + ### getBlockBindingsSources Returns all registered block bindings sources. @@ -135,6 +139,10 @@ _Returns_ - `Array`: Block bindings sources. +_Changelog_ + +`6.7.0` Introduced in WordPress core. + ### getBlockContent Given a block object, returns the Block's Inner HTML markup. @@ -542,6 +550,10 @@ _Parameters_ - _source.setValues_ `[Function]`: Optional function to update multiple values connected to the source. - _source.canUserEditValue_ `[Function]`: Optional function to determine if the user can edit the value. +_Changelog_ + +`6.7.0` Introduced in WordPress core. + ### registerBlockCollection Registers a new block collection to group blocks in the same namespace in the inserter. @@ -859,6 +871,10 @@ _Parameters_ - _name_ `string`: The name of the block bindings source to unregister. +_Changelog_ + +`6.7.0` Introduced in WordPress core. + ### unregisterBlockStyle Unregisters a block style for the given block. diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index f7d85cd816c9df..31be38b861c284 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -767,6 +767,8 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { * behavior. Once registered, the source is available to be connected * to the supported block attributes. * + * @since 6.7.0 Introduced in WordPress core. + * * @param {Object} source Properties of the source to be registered. * @param {string} source.name The unique and machine-readable name. * @param {string} [source.label] Human-readable label. Optional when it is defined in the server. @@ -905,6 +907,8 @@ export const registerBlockBindingsSource = ( source ) => { /** * Unregisters a block bindings source by providing its name. * + * @since 6.7.0 Introduced in WordPress core. + * * @param {string} name The name of the block bindings source to unregister. * * @example @@ -926,6 +930,8 @@ export function unregisterBlockBindingsSource( name ) { /** * Returns a registered block bindings source by its name. * + * @since 6.7.0 Introduced in WordPress core. + * * @param {string} name Block bindings source name. * * @return {?Object} Block bindings source. @@ -937,6 +943,8 @@ export function getBlockBindingsSource( name ) { /** * Returns all registered block bindings sources. * + * @since 6.7.0 Introduced in WordPress core. + * * @return {Array} Block bindings sources. */ export function getBlockBindingsSources() { From f97702c9de698b4f96534db358f7048f9a38e3c4 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu <me@andreidraganescu.info> Date: Wed, 2 Oct 2024 09:45:01 +0300 Subject: [PATCH 1047/1908] Resize cover block only in normal mode (#65731) * only show resize controls in normal rendering mode * get block editing mode from hook not prop - misread code elsewhere Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- packages/block-library/src/cover/edit/index.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/cover/edit/index.js b/packages/block-library/src/cover/edit/index.js index ec62bd58a2c33a..804027708881b6 100644 --- a/packages/block-library/src/cover/edit/index.js +++ b/packages/block-library/src/cover/edit/index.js @@ -18,6 +18,7 @@ import { useInnerBlocksProps, __experimentalUseGradient, store as blockEditorStore, + useBlockEditingMode, } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; import { useSelect, useDispatch } from '@wordpress/data'; @@ -278,6 +279,9 @@ function CoverEdit( { const isImageBackground = IMAGE_BACKGROUND_TYPE === backgroundType; const isVideoBackground = VIDEO_BACKGROUND_TYPE === backgroundType; + const blockEditingMode = useBlockEditingMode(); + const hasNonContentControls = blockEditingMode === 'default'; + const [ resizeListener, { height, width } ] = useResizeObserver(); const resizableBoxDimensions = useMemo( () => { return { @@ -447,7 +451,7 @@ function CoverEdit( { <> { blockControls } { inspectorControls } - { isSelected && ( + { hasNonContentControls && isSelected && ( <ResizableCoverPopover { ...resizableCoverProps } /> ) } <TagName @@ -576,7 +580,7 @@ function CoverEdit( { /> <div { ...innerBlocksProps } /> </TagName> - { isSelected && ( + { hasNonContentControls && isSelected && ( <ResizableCoverPopover { ...resizableCoverProps } /> ) } </> From 3edb5707e8701ee9bc12611ab094c1c2ec1ae73a Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 2 Oct 2024 08:21:51 +0100 Subject: [PATCH 1048/1908] Inserter: Fix Block visibility manager (#65700) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../inserter/hooks/use-patterns-state.js | 42 ++--- packages/block-editor/src/store/selectors.js | 155 ++++++++++++------ .../editor/various/allowed-patterns.spec.js | 8 +- 3 files changed, 123 insertions(+), 82 deletions(-) diff --git a/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js b/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js index 13dae7f2ed7c0d..91b34c0ec72c3d 100644 --- a/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js +++ b/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js @@ -13,7 +13,7 @@ import { store as noticesStore } from '@wordpress/notices'; import { store as blockEditorStore } from '../../../store'; import { unlock } from '../../../lock-unlock'; import { INSERTER_PATTERN_TYPES } from '../block-patterns-tab/utils'; -import { getParsedPattern } from '../../../store/utils'; +import { isFiltered } from '../../../store/utils'; /** * Retrieves the block patterns inserter state. @@ -31,48 +31,34 @@ const usePatternsState = ( selectedCategory, isQuick ) => { - const { patternCategories, allPatterns, userPatternCategories } = useSelect( + const options = useMemo( + () => ( { [ isFiltered ]: !! isQuick } ), + [ isQuick ] + ); + const { patternCategories, patterns, userPatternCategories } = useSelect( ( select ) => { - const { - getAllPatterns, - getSettings, - __experimentalGetAllowedPatterns, - } = unlock( select( blockEditorStore ) ); + const { getSettings, __experimentalGetAllowedPatterns } = unlock( + select( blockEditorStore ) + ); const { __experimentalUserPatternCategories, __experimentalBlockPatternCategories, } = getSettings(); return { - allPatterns: isQuick - ? __experimentalGetAllowedPatterns() - : getAllPatterns(), + patterns: __experimentalGetAllowedPatterns( + rootClientId, + options + ), userPatternCategories: __experimentalUserPatternCategories, patternCategories: __experimentalBlockPatternCategories, }; }, - [ isQuick ] + [ rootClientId, options ] ); const { getClosestAllowedInsertionPointForPattern } = unlock( useSelect( blockEditorStore ) ); - const patterns = useMemo( - () => - isQuick - ? allPatterns - : allPatterns - .filter( ( { inserter = true } ) => !! inserter ) - .map( ( pattern ) => { - return { - ...pattern, - get blocks() { - return getParsedPattern( pattern ).blocks; - }, - }; - } ), - [ isQuick, allPatterns ] - ); - const allCategories = useMemo( () => { const categories = [ ...patternCategories ]; userPatternCategories?.forEach( ( userCategory ) => { diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 7bb002661565bd..6cf6aae296141f 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -1540,6 +1540,59 @@ export function getTemplateLock( state, rootClientId ) { return getBlockListSettings( state, rootClientId )?.templateLock ?? false; } +/** + * Determines if the given block type is visible in the inserter. + * Note that this is different than whether a block is allowed to be inserted. + * In some cases, the block is not allowed in a given position but + * it should still be visible in the inserter to be able to add it + * to a different position. + * + * @param {Object} state Editor state. + * @param {string|Object} blockNameOrType The block type object, e.g., the response + * from the block directory; or a string name of + * an installed block type, e.g.' core/paragraph'. + * + * @return {boolean} Whether the given block type is allowed to be inserted. + */ +const isBlockVisibleInTheInserter = ( state, blockNameOrType ) => { + let blockType; + let blockName; + if ( blockNameOrType && 'object' === typeof blockNameOrType ) { + blockType = blockNameOrType; + blockName = blockNameOrType.name; + } else { + blockType = getBlockType( blockNameOrType ); + blockName = blockNameOrType; + } + if ( ! blockType ) { + return false; + } + + const { allowedBlockTypes } = getSettings( state ); + + const isBlockAllowedInEditor = checkAllowList( + allowedBlockTypes, + blockName, + true + ); + if ( ! isBlockAllowedInEditor ) { + return false; + } + + // If parent blocks are not visible, child blocks should be hidden too. + if ( !! blockType.parent?.length ) { + return blockType.parent.some( + ( name ) => + isBlockVisibleInTheInserter( state, name ) || + // Exception for blocks with post-content parent, + // the root level is often consider as "core/post-content". + // This exception should only apply to the post editor ideally though. + name === 'core/post-content' + ); + } + return true; +}; + /** * Determines if the given block type is allowed to be inserted into the block list. * This function is not exported and not memoized because using a memoized selector @@ -1558,6 +1611,10 @@ const canInsertBlockTypeUnmemoized = ( blockName, rootClientId = null ) => { + if ( ! isBlockVisibleInTheInserter( state, blockName ) ) { + return false; + } + let blockType; if ( blockName && 'object' === typeof blockName ) { blockType = blockName; @@ -1565,20 +1622,6 @@ const canInsertBlockTypeUnmemoized = ( } else { blockType = getBlockType( blockName ); } - if ( ! blockType ) { - return false; - } - - const { allowedBlockTypes } = getSettings( state ); - - const isBlockAllowedInEditor = checkAllowList( - allowedBlockTypes, - blockName, - true - ); - if ( ! isBlockAllowedInEditor ) { - return false; - } const isLocked = !! getTemplateLock( state, rootClientId ); if ( isLocked ) { @@ -1972,6 +2015,7 @@ const buildBlockTypeItem = description: blockType.description, category: blockType.category, keywords: blockType.keywords, + parent: blockType.parent, variations: inserterVariations, example: blockType.example, utility: 1, // Deprecated. @@ -2067,16 +2111,18 @@ export const getInserterItems = createRegistrySelector( ( select ) => ) ); } else { - blockTypeInserterItems = blockTypeInserterItems.map( - ( blockType ) => ( { + blockTypeInserterItems = blockTypeInserterItems + .filter( ( blockType ) => + isBlockVisibleInTheInserter( state, blockType ) + ) + .map( ( blockType ) => ( { ...blockType, isAllowedInCurrentRoot: canIncludeBlockTypeInInserter( state, blockType, rootClientId ), - } ) - ); + } ) ); } const items = blockTypeInserterItems.reduce( @@ -2348,37 +2394,50 @@ const getAllowedPatternsDependants = ( select ) => ( state, rootClientId ) => [ */ export const __experimentalGetAllowedPatterns = createRegistrySelector( ( select ) => { - return createSelector( ( state, rootClientId = null ) => { - const { getAllPatterns } = unlock( select( STORE_NAME ) ); - const patterns = getAllPatterns(); - const { allowedBlockTypes } = getSettings( state ); - const parsedPatterns = patterns - .filter( ( { inserter = true } ) => !! inserter ) - .map( ( pattern ) => { - return { - ...pattern, - get blocks() { - return getParsedPattern( pattern ).blocks; - }, - }; - } ); - - const availableParsedPatterns = parsedPatterns.filter( - ( pattern ) => - checkAllowListRecursive( - getGrammar( pattern ), - allowedBlockTypes - ) - ); - const patternsAllowed = availableParsedPatterns.filter( - ( pattern ) => - getGrammar( pattern ).every( ( { blockName: name } ) => - canInsertBlockType( state, name, rootClientId ) - ) - ); + return createSelector( + ( + state, + rootClientId = null, + options = DEFAULT_INSERTER_OPTIONS + ) => { + const { getAllPatterns } = unlock( select( STORE_NAME ) ); + const patterns = getAllPatterns(); + const { allowedBlockTypes } = getSettings( state ); + const parsedPatterns = patterns + .filter( ( { inserter = true } ) => !! inserter ) + .map( ( pattern ) => { + return { + ...pattern, + get blocks() { + return getParsedPattern( pattern ).blocks; + }, + }; + } ); + + const availableParsedPatterns = parsedPatterns.filter( + ( pattern ) => + checkAllowListRecursive( + getGrammar( pattern ), + allowedBlockTypes + ) + ); + const patternsAllowed = availableParsedPatterns.filter( + ( pattern ) => + getGrammar( pattern ).every( ( { blockName: name } ) => + options[ isFiltered ] !== false + ? canInsertBlockType( + state, + name, + rootClientId + ) + : isBlockVisibleInTheInserter( state, name ) + ) + ); - return patternsAllowed; - }, getAllowedPatternsDependants( select ) ); + return patternsAllowed; + }, + getAllowedPatternsDependants( select ) + ); } ); diff --git a/test/e2e/specs/editor/various/allowed-patterns.spec.js b/test/e2e/specs/editor/various/allowed-patterns.spec.js index 894f143d19bb82..83d44403d60ee2 100644 --- a/test/e2e/specs/editor/various/allowed-patterns.spec.js +++ b/test/e2e/specs/editor/various/allowed-patterns.spec.js @@ -54,7 +54,7 @@ test.describe( 'Allowed Patterns', () => { ); } ); - test( 'should show all patterns even if not allowed', async ( { + test( 'should hide patterns with only hidden blocks', async ( { admin, page, } ) => { @@ -77,11 +77,7 @@ test.describe( 'Allowed Patterns', () => { page .getByRole( 'listbox', { name: 'Block patterns' } ) .getByRole( 'option' ) - ).toHaveText( [ - 'Test: Single heading', - 'Test: Single paragraph', - 'Test: Paragraph inside group', - ] ); + ).toHaveText( [ 'Test: Single heading' ] ); } ); } ); } ); From 04d38bc497a7cbd747e0aff153d4626c8958b20a Mon Sep 17 00:00:00 2001 From: Matias Benedetto <matias.benedetto@gmail.com> Date: Wed, 2 Oct 2024 05:23:16 -0300 Subject: [PATCH 1049/1908] Avoid errors when a fontSize preset is not available (#65791) * Avoid errors when the fontSize is not available * remove goBack * Update packages/edit-site/src/components/global-styles/font-sizes/font-size.js --- Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: firoz2456 <firoz2456@git.wordpress.org> Co-authored-by: nith53 <nithins53@git.wordpress.org> Co-authored-by: benniledl <benniledl@git.wordpress.org> --- .../global-styles/font-sizes/font-size.js | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js index 80b1ea55c405bc..ef520a0163c037 100644 --- a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js @@ -15,7 +15,7 @@ import { ToggleControl, } from '@wordpress/components'; import { moreVertical } from '@wordpress/icons'; -import { useState } from '@wordpress/element'; +import { useState, useEffect } from '@wordpress/element'; /** * Internal dependencies @@ -36,7 +36,6 @@ function FontSize() { const { params: { origin, slug }, - goBack, goTo, } = useNavigator(); @@ -54,10 +53,10 @@ function FontSize() { // Whether the font size is fluid. If not defined, use the global fluid value of the theme. const isFluid = - fontSize.fluid !== undefined ? !! fontSize.fluid : !! globalFluid; + fontSize?.fluid !== undefined ? !! fontSize.fluid : !! globalFluid; // Whether custom fluid values are used. - const isCustomFluid = typeof fontSize.fluid === 'object'; + const isCustomFluid = typeof fontSize?.fluid === 'object'; const handleNameChange = ( value ) => { updateFontSize( 'name', value ); @@ -107,9 +106,6 @@ function FontSize() { }; const handleRemoveFontSize = () => { - // Navigate to the font sizes list. - goBack(); - const newFontSizes = sizes.filter( ( size ) => size.slug !== slug ); setFontSizes( { ...fontSizes, @@ -125,6 +121,18 @@ function FontSize() { setIsRenameDialogOpen( ! isRenameDialogOpen ); }; + // Navigate to the font sizes list if the font size is not available. + useEffect( () => { + if ( ! fontSize ) { + goTo( '/typography/font-sizes/', { isBack: true } ); + } + }, [ fontSize, goTo ] ); + + // Avoid rendering if the font size is not available. + if ( ! fontSize ) { + return null; + } + return ( <> <ConfirmDeleteFontSizeDialog From 79e6643ea0d7c4962a5f81baf1fee4ba4a53c710 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Wed, 2 Oct 2024 09:48:59 +0100 Subject: [PATCH 1050/1908] Hide Zoom Out inserter buttons when dragging (#65789) Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../src/components/block-tools/index.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 099323925384b8..bad331561317f8 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -34,7 +34,8 @@ function selector( select ) { getSettings, __unstableGetEditorMode, isTyping, - } = select( blockEditorStore ); + isDragging, + } = unlock( select( blockEditorStore ) ); const clientId = getSelectedBlockClientId() || getFirstMultiSelectedBlockClientId(); @@ -46,6 +47,7 @@ function selector( select ) { hasFixedToolbar: getSettings().hasFixedToolbar, isTyping: isTyping(), isZoomOutMode: editorMode === 'zoom-out', + isDragging: isDragging(), }; } @@ -63,10 +65,9 @@ export default function BlockTools( { __unstableContentRef, ...props } ) { - const { clientId, hasFixedToolbar, isTyping, isZoomOutMode } = useSelect( - selector, - [] - ); + const { clientId, hasFixedToolbar, isTyping, isZoomOutMode, isDragging } = + useSelect( selector, [] ); + const isMatch = useShortcutEventMatch(); const { getBlocksByClientId, @@ -241,7 +242,7 @@ export default function BlockTools( { name="__unstable-block-tools-after" ref={ blockToolbarAfterRef } /> - { isZoomOutMode && ( + { isZoomOutMode && ! isDragging && ( <ZoomOutModeInserters __unstableContentRef={ __unstableContentRef } /> From 32d56780405851e5d9dfe56cea85dd4fd2750e6c Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 2 Oct 2024 20:56:00 +0900 Subject: [PATCH 1051/1908] Fix: Shadow/Font size preset panel crashes the editor (#65765) * Fix: Shadow/Font size preset panel crashes the editor * Refactor logic Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../global-styles/font-sizes/font-size.js | 23 +++++++++---------- .../global-styles/shadows-edit-panel.js | 4 ++++ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js index ef520a0163c037..63310203ef05b1 100644 --- a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js @@ -51,6 +51,17 @@ function FontSize() { // Get the font size by slug. const fontSize = sizes.find( ( size ) => size.slug === slug ); + // Navigate to the font sizes list if the font size is not available. + useEffect( () => { + if ( ! fontSize ) { + goTo( '/typography/font-sizes/', { isBack: true } ); + } + }, [ fontSize, goTo ] ); + + if ( ! origin || ! slug || ! fontSize ) { + return null; + } + // Whether the font size is fluid. If not defined, use the global fluid value of the theme. const isFluid = fontSize?.fluid !== undefined ? !! fontSize.fluid : !! globalFluid; @@ -121,18 +132,6 @@ function FontSize() { setIsRenameDialogOpen( ! isRenameDialogOpen ); }; - // Navigate to the font sizes list if the font size is not available. - useEffect( () => { - if ( ! fontSize ) { - goTo( '/typography/font-sizes/', { isBack: true } ); - } - }, [ fontSize, goTo ] ); - - // Avoid rendering if the font size is not available. - if ( ! fontSize ) { - return null; - } - return ( <> <ConfirmDeleteFontSizeDialog diff --git a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js index f12f960f6a36bb..61bed62cff3d64 100644 --- a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js +++ b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js @@ -96,6 +96,10 @@ export default function ShadowsEditPanel() { const [ isRenameModalVisible, setIsRenameModalVisible ] = useState( false ); const [ shadowName, setShadowName ] = useState( selectedShadow.name ); + if ( ! category || ! slug ) { + return null; + } + const onShadowChange = ( shadow ) => { setSelectedShadow( { ...selectedShadow, shadow } ); const updatedShadows = shadows.map( ( s ) => From a4c88c2c25ef1ee47cf7a13b181c2c22f46e20b9 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 2 Oct 2024 14:22:10 +0200 Subject: [PATCH 1052/1908] Composite: always await initial render setup in unit tests (#65823) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/composite/legacy/test/index.tsx | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/packages/components/src/composite/legacy/test/index.tsx b/packages/components/src/composite/legacy/test/index.tsx index c034d31442ca8d..a118dbcfbadbb3 100644 --- a/packages/components/src/composite/legacy/test/index.tsx +++ b/packages/components/src/composite/legacy/test/index.tsx @@ -232,7 +232,7 @@ describe.each( [ <button>After</button> </> ); - renderAndValidate( <Test /> ); + await renderAndValidate( <Test /> ); await press.Tab(); expect( screen.getByText( 'Before' ) ).toHaveFocus(); @@ -260,7 +260,7 @@ describe.each( [ </Composite> ); }; - renderAndValidate( <Test /> ); + await renderAndValidate( <Test /> ); const { item1, item2, item3 } = getOneDimensionalItems(); @@ -289,7 +289,7 @@ describe.each( [ </Composite> ); }; - renderAndValidate( <Test /> ); + await renderAndValidate( <Test /> ); const { item1, item2, item3 } = getOneDimensionalItems(); expect( item2 ).toBeEnabled(); @@ -310,7 +310,7 @@ describe.each( [ } ) } /> ); - renderAndValidate( <Test /> ); + await renderAndValidate( <Test /> ); const { item1, item2, item3 } = getOneDimensionalItems(); expect( item1.id ).toMatch( 'test-id-1' ); @@ -327,7 +327,7 @@ describe.each( [ } ) } /> ); - renderAndValidate( <Test /> ); + await renderAndValidate( <Test /> ); const { item2 } = getOneDimensionalItems(); await press.Tab(); @@ -341,37 +341,37 @@ describe.each( [ ] )( '%s', ( _when, rtl ) => { const { previous, next, first, last } = getKeys( rtl ); - function useOneDimensionalTest( initialState?: InitialState ) { + async function useOneDimensionalTest( initialState?: InitialState ) { const Test = () => ( <OneDimensionalTest state={ useCompositeState( { rtl, ...initialState } ) } /> ); - renderAndValidate( <Test /> ); + await renderAndValidate( <Test /> ); return getOneDimensionalItems(); } - function useTwoDimensionalTest( initialState?: InitialState ) { + async function useTwoDimensionalTest( initialState?: InitialState ) { const Test = () => ( <TwoDimensionalTest state={ useCompositeState( { rtl, ...initialState } ) } /> ); - renderAndValidate( <Test /> ); + await renderAndValidate( <Test /> ); return getTwoDimensionalItems(); } - function useShiftTest( shift: boolean ) { + async function useShiftTest( shift: boolean ) { const Test = () => ( <ShiftTest state={ useCompositeState( { rtl, shift } ) } /> ); - renderAndValidate( <Test /> ); + await renderAndValidate( <Test /> ); return getShiftTestItems(); } describe( 'In one dimension', () => { test( 'All directions work with no orientation', async () => { - const { item1, item2, item3 } = useOneDimensionalTest(); + const { item1, item2, item3 } = await useOneDimensionalTest(); await press.Tab(); expect( item1 ).toHaveFocus(); @@ -406,7 +406,7 @@ describe.each( [ } ); test( 'Only left/right work with horizontal orientation', async () => { - const { item1, item2, item3 } = useOneDimensionalTest( { + const { item1, item2, item3 } = await useOneDimensionalTest( { orientation: 'horizontal', } ); @@ -435,7 +435,7 @@ describe.each( [ } ); test( 'Only up/down work with vertical orientation', async () => { - const { item1, item2, item3 } = useOneDimensionalTest( { + const { item1, item2, item3 } = await useOneDimensionalTest( { orientation: 'vertical', } ); @@ -464,7 +464,7 @@ describe.each( [ } ); test( 'Focus wraps with loop enabled', async () => { - const { item1, item2, item3 } = useOneDimensionalTest( { + const { item1, item2, item3 } = await useOneDimensionalTest( { loop: true, } ); @@ -488,7 +488,7 @@ describe.each( [ describe( 'In two dimensions', () => { test( 'All directions work as standard', async () => { const { itemA1, itemA2, itemA3, itemB1, itemB2, itemC1, itemC3 } = - useTwoDimensionalTest(); + await useTwoDimensionalTest(); await press.Tab(); expect( itemA1 ).toHaveFocus(); @@ -524,7 +524,7 @@ describe.each( [ test( 'Focus wraps around rows/columns with loop enabled', async () => { const { itemA1, itemA2, itemA3, itemB1, itemC1, itemC3 } = - useTwoDimensionalTest( { loop: true } ); + await useTwoDimensionalTest( { loop: true } ); await press.Tab(); expect( itemA1 ).toHaveFocus(); @@ -548,7 +548,7 @@ describe.each( [ test( 'Focus moves between rows/columns with wrap enabled', async () => { const { itemA1, itemA2, itemA3, itemB1, itemC1, itemC3 } = - useTwoDimensionalTest( { wrap: true } ); + await useTwoDimensionalTest( { wrap: true } ); await press.Tab(); expect( itemA1 ).toHaveFocus(); @@ -577,7 +577,7 @@ describe.each( [ } ); test( 'Focus wraps around start/end with loop and wrap enabled', async () => { - const { itemA1, itemC3 } = useTwoDimensionalTest( { + const { itemA1, itemC3 } = await useTwoDimensionalTest( { loop: true, wrap: true, } ); @@ -595,7 +595,8 @@ describe.each( [ } ); test( 'Focus shifts if vertical neighbour unavailable when shift enabled', async () => { - const { itemA1, itemB1, itemB2, itemC1 } = useShiftTest( true ); + const { itemA1, itemB1, itemB2, itemC1 } = + await useShiftTest( true ); await press.Tab(); expect( itemA1 ).toHaveFocus(); @@ -616,7 +617,7 @@ describe.each( [ } ); test( 'Focus does not shift if vertical neighbour unavailable when shift not enabled', async () => { - const { itemA1, itemB1, itemB2 } = useShiftTest( false ); + const { itemA1, itemB1, itemB2 } = await useShiftTest( false ); await press.Tab(); expect( itemA1 ).toHaveFocus(); From ce30c180d31d79b781a202ee4e06aae5f756a848 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 2 Oct 2024 14:22:34 +0200 Subject: [PATCH 1053/1908] Navigator: mark experimental exports as deprecated (#65802) * Navigator: mark experimental exports as deprecated * CHANGELOG * Update JSDocs deprecation alternatives suggestions --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/index.ts | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 4289866ce8b46f..2cb9849819bef4 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -13,6 +13,7 @@ - `__experimentalBorderControl` can now be imported as a stable `BorderControl` ([#65475](https://github.com/WordPress/gutenberg/pull/65475)). - `__experimentalBorderBoxControl` can now be imported as a stable `BorderBoxControl` ([#65586](https://github.com/WordPress/gutenberg/pull/65586)). +- `__experimentalNavigator*` components can now be imported as a stable `Navigator`. Similarly, the `__experimentalUseNavigator` hook can be imported as a stable `useNavigator` ([#65802](https://github.com/WordPress/gutenberg/pull/65802)). ### Enhancements diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index 69e76b0b91f43f..e82d6da70279e8 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -129,15 +129,21 @@ export { default as __experimentalNavigationGroup } from './navigation/group'; export { default as __experimentalNavigationItem } from './navigation/item'; export { default as __experimentalNavigationMenu } from './navigation/menu'; export { + /** @deprecated Import `Navigator` instead. */ NavigatorProvider as __experimentalNavigatorProvider, + /** @deprecated Import `Navigator` and use `Navigator.Screen` instead. */ NavigatorScreen as __experimentalNavigatorScreen, + /** @deprecated Import `Navigator` and use `Navigator.Button` instead. */ NavigatorButton as __experimentalNavigatorButton, + /** @deprecated Import `Navigator` and use `Navigator.BackButton` instead. */ NavigatorBackButton as __experimentalNavigatorBackButton, + /** @deprecated Import `Navigator` and use `Navigator.BackButton` instead. */ NavigatorToParentButton as __experimentalNavigatorToParentButton, } from './navigator/legacy'; export { Navigator, useNavigator, + /** @deprecated Import `useNavigator` instead. */ useNavigator as __experimentalUseNavigator, } from './navigator'; export { default as Notice } from './notice'; From df0acb0197d3c4648832b80a0dc8b30641f5d986 Mon Sep 17 00:00:00 2001 From: JuanMa <juanma.garrido@automattic.com> Date: Wed, 2 Oct 2024 14:48:52 +0100 Subject: [PATCH 1054/1908] Docs/interactivity api router package readme (#62062) * Updated intro to the package * removed examples and demos * update README.md * Query Loop reference * fixed typo * Wording improved * Interactivity API: Update and expand on the interactivity-router docs * Update the inline HTML in the callout --------- Co-authored-by: Michal Czaplinski <mmczaplinski@gmail.com> --- packages/interactivity-router/README.md | 139 ++++++++++++++++++------ 1 file changed, 107 insertions(+), 32 deletions(-) diff --git a/packages/interactivity-router/README.md b/packages/interactivity-router/README.md index 94b88e80886c90..efb52e59be2b5d 100644 --- a/packages/interactivity-router/README.md +++ b/packages/interactivity-router/README.md @@ -1,21 +1,32 @@ -# Interactivity Router +# `@wordpress/interactivity-router` -> **Note** -> This package is a extension of the API shared at [Proposal: The Interactivity API – A better developer experience in building interactive blocks](https://make.wordpress.org/core/2023/03/30/proposal-the-interactivity-api-a-better-developer-experience-in-building-interactive-blocks/). As part of an [Open Source project](https://developer.wordpress.org/block-editor/getting-started/faq/#the-gutenberg-project) we encourage participation in helping shape this API and the [discussions in GitHub](https://github.com/WordPress/gutenberg/discussions/categories/interactivity-api) is the best place to engage. +The package `@wordpress/interactivity-router` enables loading content from other pages without a full page reload. Currently, the only supported mode is "region-based". Full "client-side navigation" is still in experimental phase. -This package defines an Interactivity API store with the `core/router` namespace, exposing state and actions like `navigate` and `prefetch` to handle client-side navigations. +The package defines an Interactivity API store with the `core/router` namespace, exposing state and 2 actions: `navigate` and `prefetch` to handle client-side navigation. + +The `@wordpress/interactivity-router` package was [introduced in WordPress Core in v6.5](https://make.wordpress.org/core/2024/02/19/merge-announcement-interactivity-api/). This means this package is already bundled in Core in any version of WordPress higher than v6.5. + +<div class="callout callout-info"> + Check the <a href="https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/">Interactivity API Reference docs in the Block Editor handbook</a> to learn more about the Interactivity API. +</div> ## Usage -The package is intended to be imported dynamically in the `view.js` files of interactive blocks. +The package is intended to be imported dynamically in the `view.js` files of interactive blocks. This is done in in order to reduce the JS bundle size on the initial page load. ```js +/* view.js */ + import { store } from '@wordpress/interactivity'; -store( 'myblock', { +// This is how you would typically use the navigate() action in your block. +store( 'my-namespace/myblock', { actions: { - *navigate( e ) { + *goToPage( e ) { e.preventDefault(); + + // We import the package dynamically to reduce the initial JS bundle size. + // Async actions are defined as generators so the import() must be called with `yield`. const { actions } = yield import( '@wordpress/interactivity-router' ); @@ -25,52 +36,116 @@ store( 'myblock', { } ); ``` -## Frequently Asked Questions +Now, you can call `actions.navigate()` in your block's `view.js` file to navigate to a different page or e.g. pass it to a `data-wp-on--click` attribute. + +When loaded, this package [adds the following state and actions](https://github.com/WordPress/gutenberg/blob/ed7d78652526270b63976d7a970dba46a2bfcbb0/packages/interactivity-router/src/index.ts#L212) to the `core/router` store: + +```js +const { state, actions } = store( 'core/router', { + state: { + url: window.location.href, + navigation: { + hasStarted: false, + hasFinished: false, + texts: { + loading: '', + loaded: '', + }, + message: '', + }, + }, + actions: { + *navigate(href, options) {...}, + prefetch(url, options) {...}, + } +}) +``` + +<div class="callout callout-tip"> + The core "Query Loop" block is <a href="https://github.com/WordPress/gutenberg/blob/cd701e94ceffea7ef2f423274a2f77025bcfa1a6/packages/block-library/src/query/view.js#L35">using this package</a> to provide the <a href="https://github.com/WordPress/gutenberg/blob/cd701e94ceffea7ef2f423274a2f77025bcfa1a6/packages/block-library/src/query/index.php#L33">region-based navigation</a>. +</div> + +### Directives + +#### `data-wp-router-region` + +It defines a region that is updated on navigation. It requires a unique ID as the value and can only be used in root interactive elements, i.e., elements with `data-wp-interactive` that are not nested inside other elements with `data-wp-interactive`. + +Example: + +```html +<div data-wp-interactive="myblock" data-wp-router-region="main-list"> + <ul> + <li><a href="/post-1">Post 1</a></li> + <li><a href="/post-2">Post 2</a></li> + <li><a href="/post-3">Post 3</a></li> + </ul> + <a data-wp-on--click="actions.navigate" href="/page/2"> +</div> +``` + +### Actions + +#### `navigate` + +Navigates to the specified page. -At this point, some of the questions you have about the Interactivity API may be: +This function normalizes the passed `href`, fetches the page HTML if needed, and updates any interactive regions whose contents have changed in the new page. It also creates a new entry in the browser session history. -### What is this? +**Params** -This is the base of a new standard to create interactive blocks. Read [the proposal](https://make.wordpress.org/core/2023/03/30/proposal-the-interactivity-api-a-better-developer-experience-in-building-interactive-blocks/) to learn more about this. +```js +navigate( href: string, options: NavigateOptions = {} ) +``` -### Can I use it? +- `href`: The page `href`. +- `options`: Options object. + - `force`: If `true`, it forces re-fetching the URL. `navigate()` always caches the page, so if the page has been navigated to before, it will be used. Default is `false`. + - `html`: HTML string to be used instead of fetching the requested URL. + - `replace`: If `true`, it replaces the current entry in the browser session history. Default is `false`. + - `timeout`: Time until the navigation is aborted, in milliseconds. Default is `10000`. + - `loadingAnimation`: Whether an animation should be shown while navigating. Default to `true`. + - `screenReaderAnnouncement`: Whether a message for screen readers should be announced while navigating. Default to `true`. -You can test it, but it's still very experimental. +#### `prefetch` -### How do I get started? +Prefetches the page for the passed URL. The page is cached and can be used for navigation. -The best place to start with the Interactivity API is this [**Getting started guide**](https://github.com/WordPress/gutenberg/blob/trunk/packages/interactivity/docs/1-getting-started.md). There you'll will find a very quick start guide and the current requirements of the Interactivity API. +The function normalizes the URL and stores internally the fetch promise, to avoid triggering a second fetch for an ongoing request. -### Where can I ask questions? +**Params** -The [“Interactivity API” category](https://github.com/WordPress/gutenberg/discussions/categories/interactivity-api) in Gutenberg repo discussions is the best place to ask questions about the Interactivity API. +```js +prefetch( url: string, options: PrefetchOptions = {} ) +``` -### Where can I share my feedback about the API? +- `url`: The page `url`. +- `options`: Options object. -The [“Interactivity API” category](https://github.com/WordPress/gutenberg/discussions/categories/interactivity-api) in Gutenberg repo discussions is also the best place to share your feedback about the Interactivity API. + - `force`: If `true`, forces fetching the URL again. + - `html`: HTML string to be used instead of fetching the requested URL. + +### State + +`state.url` is a reactive property synchronized with the current URL. +Properties under `state.navigation` are meant for loading bar animations. ## Installation Install the module: ```bash -npm install @wordpress/interactivity --save +npm install @wordpress/interactivity-router --save ``` -_This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for such language features and APIs, you should include [the polyfill shipped in `@wordpress/babel-preset-default`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/babel-preset-default#polyfill) in your code._ - -## Docs & Examples +This step is only required if you use the Interactivity API outside WordPress. -**[Interactivity API Documentation](https://github.com/WordPress/gutenberg/tree/trunk/packages/interactivity/docs)** is the best place to learn about this proposal. Although it's still in progress, some key pages are already available: +Within WordPress, the package is already bundled in Core. To ensure it's enqueued, add `@wordpress/interactivity-router` to the dependency array of the script module. This process is often done automatically with tools like [`wp-scripts`](https://developer.wordpress.org/block-editor/getting-started/devenv/get-started-with-wp-scripts/). -- **[Getting Started Guide](https://github.com/WordPress/gutenberg/blob/trunk/packages/interactivity/docs/1-getting-started.md)**: Follow this Getting Started guide to learn how to scaffold a new project and create your first interactive blocks. -- **[API Reference](https://github.com/WordPress/gutenberg/blob/trunk/packages/interactivity/docs/2-api-reference.md)**: Check this page for technical detailed explanations and examples of the directives and the store. +Furthermore, this package assumes your code will run in an **ES2015+** environment. If you're using an environment with limited or no support for such language features and APIs, you should include the polyfill shipped in [`@wordpress/babel-preset-default`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/babel-preset-default#polyfill) in your code. -Here you have some more resources to learn/read more about the Interactivity API: +## License -- **[Interactivity API Discussions](https://github.com/WordPress/gutenberg/discussions/52882)** -- [Proposal: The Interactivity API – A better developer experience in building interactive blocks](https://make.wordpress.org/core/2023/03/30/proposal-the-interactivity-api-a-better-developer-experience-in-building-interactive-blocks/) -- Developer Hours sessions ([Americas](https://www.youtube.com/watch?v=RXNoyP2ZiS8&t=664s) & [APAC/EMEA](https://www.youtube.com/watch?v=6ghbrhyAcvA)) -- [wpmovies.dev](http://wpmovies.dev/) demo and its [wp-movies-demo](https://github.com/WordPress/wp-movies-demo) repo +Interactivity API proposal, as part of Gutenberg and the WordPress project is free software, and is released under the terms of the GNU General Public License version 2 or (at your option) any later version. See [LICENSE.md](https://github.com/WordPress/gutenberg/blob/trunk/LICENSE.md) for complete license. -<br /><br /><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p> +<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p> From 695600a5c4ab8b5f93ed896ed3b426e247107c57 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 2 Oct 2024 15:49:19 +0200 Subject: [PATCH 1055/1908] Composite: fix legacy implementation passing store prop (#65821) * Composite: fix legacy implementation passing store prop * Simplify code * Improve comment * Apply same fix to the top level Composite too * CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/composite/group-label.tsx | 12 +++++++----- packages/components/src/composite/group.tsx | 14 +++++++------- packages/components/src/composite/hover.tsx | 14 +++++++------- packages/components/src/composite/index.tsx | 7 ++++++- packages/components/src/composite/item.tsx | 14 +++++++------- packages/components/src/composite/row.tsx | 14 +++++++------- packages/components/src/composite/typeahead.tsx | 14 +++++++------- 8 files changed, 49 insertions(+), 41 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 2cb9849819bef4..4c00ea32bae2cb 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -8,6 +8,7 @@ - `Navigator`: fix `isInitial` logic ([#65527](https://github.com/WordPress/gutenberg/pull/65527)). - `ToggleGroupControl`: Fix arrow key navigation in RTL ([#65735](https://github.com/WordPress/gutenberg/pull/65735)). - `ToggleGroupControl`: indicator doesn't jump around when the layout around it changes ([#65175](https://github.com/WordPress/gutenberg/pull/65175)). +- `Composite`: fix legacy support for the store prop ([#65821](https://github.com/WordPress/gutenberg/pull/65821)). ### Deprecations diff --git a/packages/components/src/composite/group-label.tsx b/packages/components/src/composite/group-label.tsx index 17070dbb86bf81..7e3c6ffdc7759c 100644 --- a/packages/components/src/composite/group-label.tsx +++ b/packages/components/src/composite/group-label.tsx @@ -20,11 +20,13 @@ export const CompositeGroupLabel = forwardRef< WordPressComponentProps< CompositeGroupLabelProps, 'div', false > >( function CompositeGroupLabel( props, ref ) { const context = useCompositeContext(); + + // @ts-expect-error The store prop is undocumented and only used by the + // legacy compat layer. The `store` prop is documented, but its type is + // obfuscated to discourage its use outside of the component's internals. + const store = ( props.store ?? context.store ) as Ariakit.CompositeStore; + return ( - <Ariakit.CompositeGroupLabel - store={ context.store as Ariakit.CompositeStore } - { ...props } - ref={ ref } - /> + <Ariakit.CompositeGroupLabel store={ store } { ...props } ref={ ref } /> ); } ); diff --git a/packages/components/src/composite/group.tsx b/packages/components/src/composite/group.tsx index ae21ca6f11dd92..bcfb47e684613d 100644 --- a/packages/components/src/composite/group.tsx +++ b/packages/components/src/composite/group.tsx @@ -20,11 +20,11 @@ export const CompositeGroup = forwardRef< WordPressComponentProps< CompositeGroupProps, 'div', false > >( function CompositeGroup( props, ref ) { const context = useCompositeContext(); - return ( - <Ariakit.CompositeGroup - store={ context.store as Ariakit.CompositeStore } - { ...props } - ref={ ref } - /> - ); + + // @ts-expect-error The store prop is undocumented and only used by the + // legacy compat layer. The `store` prop is documented, but its type is + // obfuscated to discourage its use outside of the component's internals. + const store = ( props.store ?? context.store ) as Ariakit.CompositeStore; + + return <Ariakit.CompositeGroup store={ store } { ...props } ref={ ref } />; } ); diff --git a/packages/components/src/composite/hover.tsx b/packages/components/src/composite/hover.tsx index ca0bd9d8f6aa12..1507a1879cc19f 100644 --- a/packages/components/src/composite/hover.tsx +++ b/packages/components/src/composite/hover.tsx @@ -20,11 +20,11 @@ export const CompositeHover = forwardRef< WordPressComponentProps< CompositeHoverProps, 'div', false > >( function CompositeHover( props, ref ) { const context = useCompositeContext(); - return ( - <Ariakit.CompositeHover - store={ context.store as Ariakit.CompositeStore } - { ...props } - ref={ ref } - /> - ); + + // @ts-expect-error The store prop is undocumented and only used by the + // legacy compat layer. The `store` prop is documented, but its type is + // obfuscated to discourage its use outside of the component's internals. + const store = ( props.store ?? context.store ) as Ariakit.CompositeStore; + + return <Ariakit.CompositeGroup store={ store } { ...props } ref={ ref } />; } ); diff --git a/packages/components/src/composite/index.tsx b/packages/components/src/composite/index.tsx index e9e97072261fbf..8eb562f5bdab38 100644 --- a/packages/components/src/composite/index.tsx +++ b/packages/components/src/composite/index.tsx @@ -73,7 +73,10 @@ export const Composite = Object.assign( }, ref ) { - const store = Ariakit.useCompositeStore( { + // @ts-expect-error The store prop is undocumented and only used by the + // legacy compat layer. + const storeProp = props.store as Ariakit.CompositeStore; + const internalStore = Ariakit.useCompositeStore( { activeId, defaultActiveId, setActiveId, @@ -85,6 +88,8 @@ export const Composite = Object.assign( rtl, } ); + const store = storeProp ?? internalStore; + const contextValue = useMemo( () => ( { store, diff --git a/packages/components/src/composite/item.tsx b/packages/components/src/composite/item.tsx index 6d75b90f0baaaa..4a02f76039a5cf 100644 --- a/packages/components/src/composite/item.tsx +++ b/packages/components/src/composite/item.tsx @@ -20,11 +20,11 @@ export const CompositeItem = forwardRef< WordPressComponentProps< CompositeItemProps, 'button', false > >( function CompositeItem( props, ref ) { const context = useCompositeContext(); - return ( - <Ariakit.CompositeItem - store={ context.store as Ariakit.CompositeStore } - { ...props } - ref={ ref } - /> - ); + + // @ts-expect-error The store prop is undocumented and only used by the + // legacy compat layer. The `store` prop is documented, but its type is + // obfuscated to discourage its use outside of the component's internals. + const store = ( props.store ?? context.store ) as Ariakit.CompositeStore; + + return <Ariakit.CompositeItem store={ store } { ...props } ref={ ref } />; } ); diff --git a/packages/components/src/composite/row.tsx b/packages/components/src/composite/row.tsx index a082af03ad6785..1a88da557785e9 100644 --- a/packages/components/src/composite/row.tsx +++ b/packages/components/src/composite/row.tsx @@ -20,11 +20,11 @@ export const CompositeRow = forwardRef< WordPressComponentProps< CompositeRowProps, 'div', false > >( function CompositeRow( props, ref ) { const context = useCompositeContext(); - return ( - <Ariakit.CompositeRow - store={ context.store as Ariakit.CompositeStore } - { ...props } - ref={ ref } - /> - ); + + // @ts-expect-error The store prop is undocumented and only used by the + // legacy compat layer. The `store` prop is documented, but its type is + // obfuscated to discourage its use outside of the component's internals. + const store = ( props.store ?? context.store ) as Ariakit.CompositeStore; + + return <Ariakit.CompositeRow store={ store } { ...props } ref={ ref } />; } ); diff --git a/packages/components/src/composite/typeahead.tsx b/packages/components/src/composite/typeahead.tsx index 771d58bcb6c25c..519c59ea374e5d 100644 --- a/packages/components/src/composite/typeahead.tsx +++ b/packages/components/src/composite/typeahead.tsx @@ -20,11 +20,11 @@ export const CompositeTypeahead = forwardRef< WordPressComponentProps< CompositeTypeaheadProps, 'div', false > >( function CompositeTypeahead( props, ref ) { const context = useCompositeContext(); - return ( - <Ariakit.CompositeTypeahead - store={ context.store as Ariakit.CompositeStore } - { ...props } - ref={ ref } - /> - ); + + // @ts-expect-error The store prop is undocumented and only used by the + // legacy compat layer. The `store` prop is documented, but its type is + // obfuscated to discourage its use outside of the component's internals. + const store = ( props.store ?? context.store ) as Ariakit.CompositeStore; + + return <Ariakit.CompositeRow store={ store } { ...props } ref={ ref } />; } ); From 559391a6f1451e68124c9a18925ab784bca80e29 Mon Sep 17 00:00:00 2001 From: louwie17 <lourensschep@gmail.com> Date: Wed, 2 Oct 2024 10:55:56 -0300 Subject: [PATCH 1056/1908] DataForm - Add combined fields support (#65399) Co-authored-by: louwie17 <louwie17@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: gigitux <gigitux@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../dataform-combined-edit/index.tsx | 66 +++++++++++++++++++ .../dataform-combined-edit/style.scss | 12 ++++ .../dataform/stories/index.story.tsx | 65 ++++++++++++++++++ .../dataforms-layouts/get-visible-fields.ts | 29 ++++++++ .../src/dataforms-layouts/panel/index.tsx | 15 +++-- .../src/dataforms-layouts/regular/index.tsx | 15 +++-- packages/dataviews/src/normalize-fields.ts | 34 +++++++++- packages/dataviews/src/style.scss | 1 + packages/dataviews/src/types.ts | 38 ++++++++--- packages/dataviews/src/validation.ts | 2 +- 10 files changed, 252 insertions(+), 25 deletions(-) create mode 100644 packages/dataviews/src/components/dataform-combined-edit/index.tsx create mode 100644 packages/dataviews/src/components/dataform-combined-edit/style.scss create mode 100644 packages/dataviews/src/dataforms-layouts/get-visible-fields.ts diff --git a/packages/dataviews/src/components/dataform-combined-edit/index.tsx b/packages/dataviews/src/components/dataform-combined-edit/index.tsx new file mode 100644 index 00000000000000..6b2a752fa8de52 --- /dev/null +++ b/packages/dataviews/src/components/dataform-combined-edit/index.tsx @@ -0,0 +1,66 @@ +/** + * WordPress dependencies + */ +import { + __experimentalHStack as HStack, + __experimentalVStack as VStack, + __experimentalHeading as Heading, + __experimentalSpacer as Spacer, +} from '@wordpress/components'; + +/** + * Internal dependencies + */ +import type { DataFormCombinedEditProps, NormalizedField } from '../../types'; + +function Header( { title }: { title: string } ) { + return ( + <VStack className="dataforms-layouts__dropdown-header" spacing={ 4 }> + <HStack alignment="center"> + <Heading level={ 2 } size={ 13 }> + { title } + </Heading> + <Spacer /> + </HStack> + </VStack> + ); +} + +function DataFormCombinedEdit< Item >( { + field, + data, + onChange, + hideLabelFromVision, +}: DataFormCombinedEditProps< Item > ) { + const className = 'dataforms-combined-edit'; + const visibleChildren = ( field.children ?? [] ) + .map( ( fieldId ) => field.fields.find( ( { id } ) => id === fieldId ) ) + .filter( + ( childField ): childField is NormalizedField< Item > => + !! childField + ); + const children = visibleChildren.map( ( child ) => { + return ( + <div className="dataforms-combined-edit__field" key={ child.id }> + <child.Edit + data={ data } + field={ child } + onChange={ onChange } + /> + </div> + ); + } ); + + const Stack = field.direction === 'horizontal' ? HStack : VStack; + + return ( + <> + { ! hideLabelFromVision && <Header title={ field.label } /> } + <Stack spacing={ 4 } className={ className } as="fieldset"> + { children } + </Stack> + </> + ); +} + +export default DataFormCombinedEdit; diff --git a/packages/dataviews/src/components/dataform-combined-edit/style.scss b/packages/dataviews/src/components/dataform-combined-edit/style.scss new file mode 100644 index 00000000000000..0b59cbc9a47768 --- /dev/null +++ b/packages/dataviews/src/components/dataform-combined-edit/style.scss @@ -0,0 +1,12 @@ +.dataforms-layouts-panel__field-dropdown { + .dataforms-combined-edit { + border: none; + padding: 0; + } +} + +.dataforms-combined-edit { + &__field { + flex: 1 1 auto; + } +} diff --git a/packages/dataviews/src/components/dataform/stories/index.story.tsx b/packages/dataviews/src/components/dataform/stories/index.story.tsx index 7147b9c2342638..c929c21f1c21a9 100644 --- a/packages/dataviews/src/components/dataform/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataform/stories/index.story.tsx @@ -7,6 +7,7 @@ import { useState } from '@wordpress/element'; * Internal dependencies */ import DataForm from '../index'; +import type { CombinedFormField } from '../../../types'; const meta = { title: 'DataViews/DataForm', @@ -76,6 +77,11 @@ const fields = [ { value: 'published', label: 'Published' }, ], }, + { + id: 'password', + label: 'Password', + type: 'text' as const, + }, ]; export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { @@ -118,3 +124,62 @@ export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { /> ); }; + +const CombinedFieldsComponent = ( { + type = 'regular', + combinedFieldDirection = 'vertical', +}: { + type: 'panel' | 'regular'; + combinedFieldDirection: 'vertical' | 'horizontal'; +} ) => { + const [ post, setPost ] = useState( { + title: 'Hello, World!', + order: 2, + author: 1, + status: 'draft', + } ); + + const form = { + fields: [ 'title', 'status_and_visibility', 'order', 'author' ], + combinedFields: [ + { + id: 'status_and_visibility', + label: 'Status & Visibility', + children: [ 'status', 'password' ], + direction: combinedFieldDirection, + render: ( { item } ) => item.status, + }, + ] as CombinedFormField< any >[], + }; + + return ( + <DataForm + data={ post } + fields={ fields } + form={ { + ...form, + type, + } } + onChange={ ( edits ) => + setPost( ( prev ) => ( { + ...prev, + ...edits, + } ) ) + } + /> + ); +}; + +export const CombinedFields = { + title: 'DataViews/CombinedFields', + render: CombinedFieldsComponent, + argTypes: { + ...meta.argTypes, + combinedFieldDirection: { + control: { type: 'select' }, + description: + 'Chooses the direction of the combined field. "vertical" is the default layout.', + options: [ 'vertical', 'horizontal' ], + }, + }, +}; diff --git a/packages/dataviews/src/dataforms-layouts/get-visible-fields.ts b/packages/dataviews/src/dataforms-layouts/get-visible-fields.ts new file mode 100644 index 00000000000000..d95d59a88394e4 --- /dev/null +++ b/packages/dataviews/src/dataforms-layouts/get-visible-fields.ts @@ -0,0 +1,29 @@ +/** + * Internal dependencies + */ +import { normalizeCombinedFields } from '../normalize-fields'; +import type { + Field, + CombinedFormField, + NormalizedCombinedFormField, +} from '../types'; + +export function getVisibleFields< Item >( + fields: Field< Item >[], + formFields: string[] = [], + combinedFields?: CombinedFormField< Item >[] +): Field< Item >[] { + const visibleFields: Array< + Field< Item > | NormalizedCombinedFormField< Item > + > = [ ...fields ]; + if ( combinedFields ) { + visibleFields.push( + ...normalizeCombinedFields( combinedFields, fields ) + ); + } + return formFields + .map( ( fieldId ) => + visibleFields.find( ( { id } ) => id === fieldId ) + ) + .filter( ( field ): field is Field< Item > => !! field ); +} diff --git a/packages/dataviews/src/dataforms-layouts/panel/index.tsx b/packages/dataviews/src/dataforms-layouts/panel/index.tsx index 94e107dc20665a..5d3bbc532ad457 100644 --- a/packages/dataviews/src/dataforms-layouts/panel/index.tsx +++ b/packages/dataviews/src/dataforms-layouts/panel/index.tsx @@ -17,7 +17,8 @@ import { closeSmall } from '@wordpress/icons'; * Internal dependencies */ import { normalizeFields } from '../../normalize-fields'; -import type { DataFormProps, NormalizedField, Field } from '../../types'; +import { getVisibleFields } from '../get-visible-fields'; +import type { DataFormProps, NormalizedField } from '../../types'; interface FormFieldProps< Item > { data: Item; @@ -142,13 +143,13 @@ export default function FormPanel< Item >( { const visibleFields = useMemo( () => normalizeFields( - ( form.fields ?? [] ) - .map( ( fieldId ) => - fields.find( ( { id } ) => id === fieldId ) - ) - .filter( ( field ): field is Field< Item > => !! field ) + getVisibleFields< Item >( + fields, + form.fields, + form.combinedFields + ) ), - [ fields, form.fields ] + [ fields, form.fields, form.combinedFields ] ); return ( diff --git a/packages/dataviews/src/dataforms-layouts/regular/index.tsx b/packages/dataviews/src/dataforms-layouts/regular/index.tsx index 0ec427ae010032..57aa163b890e5f 100644 --- a/packages/dataviews/src/dataforms-layouts/regular/index.tsx +++ b/packages/dataviews/src/dataforms-layouts/regular/index.tsx @@ -8,7 +8,8 @@ import { useMemo } from '@wordpress/element'; * Internal dependencies */ import { normalizeFields } from '../../normalize-fields'; -import type { DataFormProps, Field } from '../../types'; +import { getVisibleFields } from '../get-visible-fields'; +import type { DataFormProps } from '../../types'; export default function FormRegular< Item >( { data, @@ -19,13 +20,13 @@ export default function FormRegular< Item >( { const visibleFields = useMemo( () => normalizeFields( - ( form.fields ?? [] ) - .map( ( fieldId ) => - fields.find( ( { id } ) => id === fieldId ) - ) - .filter( ( field ): field is Field< Item > => !! field ) + getVisibleFields< Item >( + fields, + form.fields, + form.combinedFields + ) ), - [ fields, form.fields ] + [ fields, form.fields, form.combinedFields ] ); return ( diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index 2d1cc0402bc206..5ef219e45a4787 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -2,8 +2,14 @@ * Internal dependencies */ import getFieldTypeDefinition from './field-types'; -import type { Field, NormalizedField } from './types'; +import type { + CombinedFormField, + Field, + NormalizedField, + NormalizedCombinedFormField, +} from './types'; import { getControl } from './dataform-controls'; +import DataFormCombinedEdit from './components/dataform-combined-edit'; /** * Apply default values and normalize the fields config. @@ -66,3 +72,29 @@ export function normalizeFields< Item >( }; } ); } + +/** + * Apply default values and normalize the fields config. + * + * @param combinedFields combined field list. + * @param fields Fields config. + * @return Normalized fields config. + */ +export function normalizeCombinedFields< Item >( + combinedFields: CombinedFormField< Item >[], + fields: Field< Item >[] +): NormalizedCombinedFormField< Item >[] { + return combinedFields.map( ( combinedField ) => { + return { + ...combinedField, + Edit: DataFormCombinedEdit, + fields: normalizeFields( + combinedField.children + .map( ( fieldId ) => + fields.find( ( { id } ) => id === fieldId ) + ) + .filter( ( field ): field is Field< Item > => !! field ) + ), + }; + } ); +} diff --git a/packages/dataviews/src/style.scss b/packages/dataviews/src/style.scss index 087e812fffa192..26c6ecea645f43 100644 --- a/packages/dataviews/src/style.scss +++ b/packages/dataviews/src/style.scss @@ -6,6 +6,7 @@ @import "./components/dataviews-item-actions/style.scss"; @import "./components/dataviews-selection-checkbox/style.scss"; @import "./components/dataviews-view-config/style.scss"; +@import "./components/dataform-combined-edit/style.scss"; @import "./dataviews-layouts/grid/style.scss"; @import "./dataviews-layouts/list/style.scss"; diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index e95a43994cd63d..bc44b57eaaecc6 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -174,14 +174,6 @@ export type Fields< Item > = Field< Item >[]; export type Data< Item > = Item[]; -/** - * The form configuration. - */ -export type Form = { - type?: 'regular' | 'panel'; - fields?: string[]; -}; - export type DataFormControlProps< Item > = { data: Item; field: NormalizedField< Item >; @@ -524,9 +516,37 @@ export interface SupportedLayouts { table?: Omit< ViewTable, 'type' >; } +export interface CombinedFormField< Item > extends CombinedField { + render?: ComponentType< { item: Item } >; +} + +export interface DataFormCombinedEditProps< Item > { + field: NormalizedCombinedFormField< Item >; + data: Item; + onChange: ( value: Record< string, any > ) => void; + hideLabelFromVision?: boolean; +} + +export type NormalizedCombinedFormField< Item > = CombinedFormField< Item > & { + fields: NormalizedField< Item >[]; + Edit?: ComponentType< DataFormCombinedEditProps< Item > >; +}; + +/** + * The form configuration. + */ +export type Form< Item > = { + type?: 'regular' | 'panel'; + fields?: string[]; + /** + * The fields to combine. + */ + combinedFields?: CombinedFormField< Item >[]; +}; + export interface DataFormProps< Item > { data: Item; fields: Field< Item >[]; - form: Form; + form: Form< Item >; onChange: ( value: Record< string, any > ) => void; } diff --git a/packages/dataviews/src/validation.ts b/packages/dataviews/src/validation.ts index cc0b031f6c96c6..41969a7960af65 100644 --- a/packages/dataviews/src/validation.ts +++ b/packages/dataviews/src/validation.ts @@ -7,7 +7,7 @@ import type { Field, Form } from './types'; export function isItemValid< Item >( item: Item, fields: Field< Item >[], - form: Form + form: Form< Item > ): boolean { const _fields = normalizeFields( fields.filter( ( { id } ) => !! form.fields?.includes( id ) ) From bed3a43fa9e8c9d7326411d522b251ac485a9447 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 2 Oct 2024 16:17:50 +0200 Subject: [PATCH 1057/1908] Customize widgets, edit post: refactor Button to new sizes (#65807) * Customize widgets, edit post: refactor Button usages to new component sizing * Update snapshots * Switch to compact size in the customize widgets welcome guide * Remove unused classnames, update snapshots --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/error-boundary/index.js | 7 +------ .../customize-widgets/src/components/inserter/index.js | 4 +--- .../src/components/welcome-guide/index.js | 4 +--- .../src/components/back-button/fullscreen-mode-close.js | 3 +-- .../test/__snapshots__/fullscreen-mode-close.js.snap | 2 +- .../edit-post/src/components/init-pattern-modal/index.js | 3 +-- .../components/preferences-modal/enable-custom-fields.js | 4 +--- .../test/__snapshots__/enable-custom-fields.js.snap | 4 ++-- 8 files changed, 9 insertions(+), 22 deletions(-) diff --git a/packages/customize-widgets/src/components/error-boundary/index.js b/packages/customize-widgets/src/components/error-boundary/index.js index 49867787afd059..0fff18a616d11c 100644 --- a/packages/customize-widgets/src/components/error-boundary/index.js +++ b/packages/customize-widgets/src/components/error-boundary/index.js @@ -11,12 +11,7 @@ import { doAction } from '@wordpress/hooks'; function CopyButton( { text, children } ) { const ref = useCopyToClipboard( text ); return ( - <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - variant="secondary" - ref={ ref } - > + <Button size="compact" variant="secondary" ref={ ref }> { children } </Button> ); diff --git a/packages/customize-widgets/src/components/inserter/index.js b/packages/customize-widgets/src/components/inserter/index.js index 41fc037cf673c9..4f271bef9e9a3f 100644 --- a/packages/customize-widgets/src/components/inserter/index.js +++ b/packages/customize-widgets/src/components/inserter/index.js @@ -37,9 +37,7 @@ function Inserter( { setIsOpened } ) { { __( 'Add a block' ) } </h2> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - className="customize-widgets-layout__inserter-panel-header-close-button" + size="small" icon={ closeSmall } onClick={ () => setIsOpened( false ) } aria-label={ __( 'Close inserter' ) } diff --git a/packages/customize-widgets/src/components/welcome-guide/index.js b/packages/customize-widgets/src/components/welcome-guide/index.js index 51c4d479be51ff..3f7b2f45d86b7a 100644 --- a/packages/customize-widgets/src/components/welcome-guide/index.js +++ b/packages/customize-widgets/src/components/welcome-guide/index.js @@ -43,9 +43,7 @@ export default function WelcomeGuide( { sidebar } ) { ) } </p> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - className="customize-widgets-welcome-guide__button" + size="compact" variant="primary" onClick={ () => toggle( 'core/customize-widgets', 'welcomeGuide' ) diff --git a/packages/edit-post/src/components/back-button/fullscreen-mode-close.js b/packages/edit-post/src/components/back-button/fullscreen-mode-close.js index 626212cbab0542..ffb64a8ba07035 100644 --- a/packages/edit-post/src/components/back-button/fullscreen-mode-close.js +++ b/packages/edit-post/src/components/back-button/fullscreen-mode-close.js @@ -91,8 +91,7 @@ function FullscreenModeClose( { showTooltip, icon, href, initialPost } ) { return ( <motion.div whileHover="expand"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize className={ classes } href={ buttonHref } label={ buttonLabel } diff --git a/packages/edit-post/src/components/back-button/test/__snapshots__/fullscreen-mode-close.js.snap b/packages/edit-post/src/components/back-button/test/__snapshots__/fullscreen-mode-close.js.snap index 900d822cdcc050..4f6d298952e70a 100644 --- a/packages/edit-post/src/components/back-button/test/__snapshots__/fullscreen-mode-close.js.snap +++ b/packages/edit-post/src/components/back-button/test/__snapshots__/fullscreen-mode-close.js.snap @@ -5,7 +5,7 @@ exports[`FullscreenModeClose when in full screen mode should display a default s <div> <a aria-label="Back" - class="components-button edit-post-fullscreen-mode-close" + class="components-button edit-post-fullscreen-mode-close is-next-40px-default-size" href="edit.php?" > <svg diff --git a/packages/edit-post/src/components/init-pattern-modal/index.js b/packages/edit-post/src/components/init-pattern-modal/index.js index 6c7cd269a27de9..4288557ec712d6 100644 --- a/packages/edit-post/src/components/init-pattern-modal/index.js +++ b/packages/edit-post/src/components/init-pattern-modal/index.js @@ -82,8 +82,7 @@ export default function InitPatternModal() { /> <HStack justify="right"> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="primary" type="submit" disabled={ ! title } diff --git a/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js b/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js index c32e337be58c0e..b8125e96c7c2cf 100644 --- a/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js +++ b/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js @@ -39,9 +39,7 @@ export function CustomFieldsConfirmation( { willEnable } ) { ) } </p> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } - className="edit-post-preferences-modal__custom-fields-confirmation-button" + __next40pxDefaultSize variant="secondary" isBusy={ isReloading } accessibleWhenDisabled diff --git a/packages/edit-post/src/components/preferences-modal/test/__snapshots__/enable-custom-fields.js.snap b/packages/edit-post/src/components/preferences-modal/test/__snapshots__/enable-custom-fields.js.snap index 567b2bcbf8f885..bf12d7d0d8facc 100644 --- a/packages/edit-post/src/components/preferences-modal/test/__snapshots__/enable-custom-fields.js.snap +++ b/packages/edit-post/src/components/preferences-modal/test/__snapshots__/enable-custom-fields.js.snap @@ -97,7 +97,7 @@ exports[`EnableCustomFieldsOption renders a checked checkbox and a confirmation A page reload is required for this change. Make sure your content is saved before reloading. </p> <button - class="components-button edit-post-preferences-modal__custom-fields-confirmation-button is-secondary" + class="components-button is-next-40px-default-size is-secondary" type="button" > Show & Reload Page @@ -300,7 +300,7 @@ exports[`EnableCustomFieldsOption renders an unchecked checkbox and a confirmati A page reload is required for this change. Make sure your content is saved before reloading. </p> <button - class="components-button edit-post-preferences-modal__custom-fields-confirmation-button is-secondary" + class="components-button is-next-40px-default-size is-secondary" type="button" > Hide & Reload Page From d660f373d4a72a4c372add1e07258d31e5d00bdf Mon Sep 17 00:00:00 2001 From: Au Pleguezuelo <auareyou@github.com> Date: Wed, 2 Oct 2024 17:18:18 -0400 Subject: [PATCH 1058/1908] Light branding for the reference site (#65764) * Update theme.js * auareyou changes Color changes and added static directory to swap out logo * Image swap * Typography * Update theme.js * Format storybook/theme.js * Logo lossless compression --------- Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> --- storybook/main.js | 1 + storybook/static/wp-logo@2x.png | Bin 0 -> 5395 bytes storybook/theme.js | 35 ++++++++++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 storybook/static/wp-logo@2x.png diff --git a/storybook/main.js b/storybook/main.js index 66e951b26b1de6..f111e9f5d8cd38 100644 --- a/storybook/main.js +++ b/storybook/main.js @@ -41,6 +41,7 @@ module.exports = { disableTelemetry: true, }, stories, + staticDirs: [ './static' ], addons: [ { name: '@storybook/addon-docs', diff --git a/storybook/static/wp-logo@2x.png b/storybook/static/wp-logo@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a95cd961902b01cbd7635676f703ba9da135642d GIT binary patch literal 5395 zcmV+u73}JXP)<h;3K|Lk000e1NJLTq00LM5004Xl0{{R3f*L;O0001-P)t-s0000e zC@>`}Fe4~1Bq=T=CoUr>FC!=~Bq%N;CNLx@Fd!f>A}22+DJ~-@E+Z)~BPcB+DK8`` zFC-~2Bq=W<C@v%@FC!-|BPcH;C@v!?E+Zx_ASf^*DJ~)@E+Q!|BquN+CNLl{Fd`{0 zBPlK-CoUr?E+Z)|BPlQ?B`_l?Fd`=|BquK-DJ~@_EhH%}BPcK<C@vx>E+i)}9Y%eH z0000qbW%=J03a}6aF3tAfKWgX&+q@QVDHaxuYbRg-`}86Aa9Rwa8MA>kk7DCP%w~> zug_r5UtfUFZyD`x000y6Nkl<ZcmeF#$D)HE5QX7E4C)}0p5X2M{ogRXV0yycalTcG z?tUsgLS;Jd7*i}6Q|1+00*Ik>r*?A86`e{Ezyqu{PA;iUMRx(Pc_Fvx_UKjs98}dG zn4xB6cN;F&<!B%~&SZ2QfE~MCR7NX0jfbPYY!p2LxHYRuspvAEdRc3b7TlCozqE9V z?8zf7xaPT$l?l`B^foO;04KZ@vSJk7hbL!W1bB64>#(ZQdAXEVoSjJv>*0Brt|okZ z_g;8utGgxJ(+lET_&dO}lZAdoA<G>v=hPjhmhy0?1u&MSsigoLCzmxQqrl6mLibJp zE4B!xtKi<@26gXv(i+nOz)K?w6Lo)9M;rFc%YvZ|Kv&bpvI^1)&H%NgB|umC(Y3>) zX_ecu0A2N&wz5JVVHC=O!>)W59uHSyCan*YwSulxxI=nWa5t)Dp`c`eZFj{^Vl=8% zmZ4NZS48?5ZM;gPCTp#RV}gY5+pF+fB>&mk!84@@o@Jq=jW>xjVM}{YBH|P!2^;sI zD<g6GOf6sEB2rU&pb!!NU-Ok$N8LIRd85?8Yna1WB569pDQ>f1HKFML>dMdwKM5{| zV1gW2VlkcY<yV`ylt3?72w$4$YX&-rlRFtg6D)+k(G%7mo%WOB1w1CKIeX`!r8v%f zab&wCjf@tU9>8Wi;Q%whw|U?H-Tt8ig?&pGb<_KuPIb}*IhB5{TPn%oi4rUV&pHle za@Q~$o@dhxbF`{S+3302wjnll&iW6<s|r~68s+W(+0uJomiu7L$y9VT8r3F*eR=Ku zO)GoXsxb9v<SAHEfOi9;i7om^9|TJ|Vai6&)mAx^VXtIIs417IgLE^q2vUgF4A|H= zGm@%JP)V1go?SQkq0cyC{YP$@S^KMbJpqe@waEsnO|~hO1vEvu!dP`()aq@<5m>Qb z!J*IG<d%uG^H(0Q>dD=cCZ!*8Gm{;%^o3tO&38~c>In5Xyp+OWlYy3br2%VSd27cK ziN?<Q3X1BX^jFq3XTZ3-K!tLKnTJh|DfNRT*ILytsU$5?*4$gT{)7vUUZ@4gpLl8< z;CQg81T+~K##)`K6x-|k!>Pr(yVR;4y&S6&qm*uS;>edwmc_25CHN&45x}Mxl7hfm zrO`;s-GTk*NF?}$nD`Cf>wSC;YPgmfR*gXd4Fk>!+q5-+<>YdXhesXrEpQE3zOdr! zZz-@wh4{j~+|*q<Yg%V%;VvVvc}${$Xr564KU$Sg!n76!30N;s3o#S<j=}#08FX~( zv$W7<Xkjz}mKAq;{sLQ~gt``bIqc=w4!{zVvC!`?SP3`x7&)eeVyJ~^4%)<;Yhe&7 zi4y8s=w9MtuLA+A!i@6;zBc}t#fK~{ta1Wd0Qf3_pyn0UkWxay4pXd#{7}ne+{FKD zF`hi9pJwR@SZf?C{r9ZCahP*gRdKvin`-Eqv9tFL*V52R<+Fu{$k#%&7GjE%m+=pt zzI*a^YuHVP2Z`ZkajgwnyMz@cMPf}3$t!yxSYoc{ND~s4y1OFenf`MTV(rx2`q!Ro zXr<vjO^rYl^R%#FTBy?@ajJuK2q<oe5^AroOQi1ge8V>Y5Tm<(IUm^VYSy?(74pGi z4-5__zmSFf#tjaH%{t=z=4>`KTOu~ErQuC4|CHF3sf9erSIZKu#Hkj@0dEB6D4@Sf zOl9K!ONbT)3*Jb4Xl`z5^1xzAmJzVXg)Rh(e5KreRYJj+$Q$k?W%?6GRw?gAriD6w zCnsN}Dg)b0a)YLX6+{$q?(CB<_aT)2(=1hbEU*3YW5yObV(aqSe>y+oH%Z5>mVh<w z=|d>}av}GA{#Duk{{i`n$YH{Fu`J8p(^=MV^${9wkHXeLm?7u~L;|fH=18r)jC-nu z5PmGw{+SZW7i_rob682}#&mjeDrPq(y{Ye~8X7pH8PL{-%fJene9Z7lcG!2_3h!-j z%wEGqcAqU)I#^$Zm+YjW^hvL(Qe|jiZjv8{elkbMmUQI}VA3M7TnW1$xZVNQ6*!EW z4pkzoBC;s9Zj{x9wftxm#JW7NDow6Rl!Kyd$o$V%j|C=_tJ}l=07njLvSp)y)kSO= z`VHf4m&iT1JT0sd35wtL<o#GnUPrVLZsI4DBhpIPwQR8NwVr^-HCiB>Qv`6Yd%8@a z%}(Btd#}CwZJo|h;QjL8HY=wFi0t`>jWm=#mV3_A!X5g7rec3eFO%$Dy49f)mVg~7 zA#f!vbIJNs4Vo*pf1vZo{O4Z}1k0&uL4_`mK!%^1^Bebr({y?Q9RRFOmz5$)!yxC5 zc*jHw^8%Y0)cbzQ<jp8k3#A9@fLe%3h+J{9>f{?@Q19f@I*V9NY8Y8<R)N&2<vg$7 zbV!ENpu%g>DGN1tTFn18WMXY6`oxg|%h5tn@SXIE3=6pyf)YY$KB<I1pu@l>smHB! zv`f-K5*6rjzJh~Ab9dy;t3eYUXUD)A)IA;EjGW!#tZu8OoA&6&0F%5qT3F?1;c_6# zQOGVbwNR8$$4-<Ghr%<Y7rWwHsz;69{wH}Gc-6Pg01KVo=%p{8xP_X{-J=s07<r=- z-&F!*oo*;y9FT^~wa^azR3AHUe@+YQp%V5wi6~(Q&e!aFVjV^Ru*8|f?+6z5`6M5# zd1`-^gvd{!egMu0>fC*+ocjZWT?9+_@A}wq)$44Qynz{_g+qsh{y{rY$+WCgpoFM} zsuFJGU1ugm2M!j^y*OBWU`D_y(1jc<e3=+np=pY{J4dk85seO3gof@EEQm`vT8OxA z30Ss&>L4f(Ed(XhweZhDXHUtpE**!!z{2Jxoe!P4kjn(??+6=>WrMZM0qg#6g@x2f zC2QMv<|<i5sqPy(4J@0bg`14Pwiv#&lFxaP`-m2bGYw*=E1}Z~Amc9gFtCbTu+T9f z2dqM>X0p}r(|{#69QfBAbC%_khPxB6BG41-{BJ6_7B2J*phK{T76v)f8p{#YKnV{( zJ{Tb|2dp|9EQt8a#D8qUy_HvTTfkKstiyw(u+qT_=}G$jLZCHoc<0;}!%~%_g#}yL zg7ZdFf8bzAFF8=cQ|x>~39a6X^ab@7B<}<)bW8-lQX895CRn??<XwCe_^XD*<ToT> zxeP6A6yU+UJRFZ$ObbN`Q43}5C|`PmhOv!<Mam5T7OP3+gEa#erNOcgPYGCci_XCw zWN6Wbm}7~d77`^STDS+tLXJh=hH9vUiWXLbd+Cx7!Alz)EL8J{fYqh6pru&VqinFc zcAyaqtl9$M7+X17v|)Nwh`ru2B_vu{2r6t;NVHIt5VTN~us}^f$wF%Z76c1=t{LTn z#iwToSTh?CD+1P6xakyFb(pvEH?~rPqqU(8p^lZWg$)akeMfgdT97&x?S@*EP{$6H z&_k&s=Y!Ge99WZN&oQttG%j>XX3f2QTv%V?H8@ybP)87~*jtJfa<(cVXsweCCCC^6 z3$EMgO8EJV7B1k-1}pDe3q=W03sDIrqA{?r?UIAl;c68I772}Q_UeXwuxg1{O-*DN zJD8Kj(dss|VReim2fjvAyRm~iqlL>mwGxx7hK$jg6D3r!6D0&#Fxz0#Z3$TB!&OAC zo(ouYm_s%70<fSH$qo{pHJnNbfG%qHniASy4A;UiJn?1_Co{BAln}HKl#qW;4dyvm zXtQecJiyXzQjZ=E7TTdv+JEEG4JxJwNigC=w9wu@q~}^F0Z1H3*JDB1OO#N>PL%NJ zBNp1ijGi%AvyzWU|0zrFm!Cdzuw>~g0)tjAw1zTo4T^=`;t=?Nfo-d#SS>2-p92pQ zEfgixw6GN=1h9Tylw*O-<dcjGz}oy<U@fjCT=8;4=Q&tH3<84|QVrvA2)Lq)+P$KL zcz*$ZQ0Jh069TSGX<@8I2^H)PI6kfNW^@2i4pw7J?6-WdAY?x+ShG*p1vDfD(mer- z5QB%{r$Dk+_RnM3spvw!PEo>v41pFJ2x0~QN(Xz~irW<}T!9jjIu=_}95k@X@LgM@ zcTpW{`D9?NLTE^r(<vQC4*_D(3A|yfd#i*Gd?B9$C4|5>z-Xg?!Yu2dc~&h};++7j zyz<Th38}ox<BaPIzzXoXKFz4Gh-^bi0@jv*MTqhF4P{t}nKx=7Dk0UvB`C{J*oTCB z18b5PS{qVM=N2;N3Z0g7UNBc!JRMkM73?FI&A7%fVnhReYsS1`EwUs@7FmA*N{E3i z4xDH)^oaa&Ed;NFvhan}`KueMBv>+{{`z>ZZ0are<wCF|qPFG|u;kn|9U%tk9zz@M zZ%JsyKU@nz2{Ev32Tp7;^mN>lpoJyD4ntpf+VxmP#8J`X*JIfy25Yq8WbqZG%DDrr zR#oD;J*~wr?`ld0BLS+MSCmjLhW%ne2{+OYRhCL&w}TcogqI?F+p{ECA~%Gr{1v1o z0ap81u%y?=wA|32ob9|f`nkO}_BaA##l=h7@aJ7GRS*g2B3CP#N3<}25>}96G5^tz zIf>o{UCap%e9iloR-ZG#vZ+T|Uk=u&K!u@Tfqk~0<=py>bP>UdbS>RNwggqQFs4F5 z=nd-)Y9Up^QN%dIw6LTpSV8_b)>&O-6I>d&+F$2xmUgY25qBwkI9N;AU)eqiEGO?@ zo2p!R1WRvN30Sh#o&ZO*5R?$&LKr9^gq|JxAYVREmC*_kvdD+2aOD6=Ml2oymc^dW zc*y+MK_co`3YJgR*s9ZWJ4UA$u=Iv&p<aF}0_#UsKfUcU7<Db&>tjMG*mH|4ukHBA z&y!I&-QEG0iVCTOtStlU3$8u5WM^chb2gX-CUah}-AO3J6@b{M62m_b?#sdU*d10- z6^#i4)eNeep)}UWHHZ>IXO(n7SMc$kJHL0s1bbVw1LP(Kx?r#-;d2I*Tdi=)ZLN%X zyM~apOXgtsT}7L$uWQLcG-<HRP%#~y*6{+!Z|VFwNG)`y1gxnX!7Nab@I(o-s!#Le z(m1Q{?u8jV-}wkXJ)Nq(KzcoUFZ@6@^{e<yL??ZZl}Twe5D$mrP~l!0?!}3Lma;lg zLKfKK5hIHM3xC6oYvF?W7YGHi=4ZGvX-b^F#Cx9cTP?V@b2cTAkohOJ&mTrqtY`g3 zXJqOhr%}IEHB<B{2v{0f(y+u|dUJGI$AJ<iwb0z07z5T0VWC=B(i|3*5Mvg0ne;bu z)xjth*0edJc@te-pRVmJ63+mkm0PQGvc=`W_&7MI4L^F1*~;gPT0Uwa)oAsG4eaa& zS(ZlyYLGvt{r=$qzlM)g(E?FIQRSp{8}Kylro5=>WYQ!NUgCV<O|kZN$8}@+Uo<b3 zfb=zIxf9teI~piW;)bWTzr=J})OXOE;&_KbZ351A_!7E=Cw@pW2_b8HP7AHFo)opP zlrY?jJb~i?TDYLtEqTZjKgkW&mBS<|wJH9jFE?WC+yJI&TLcW6!3|qkXaxt&lixUW z5l<zdnVS|4+j%jJyFq>XS_=)Q>SmN{x<c8B5|Si;d#8j-<-&ow5im$wTsz7)%63=2 zEK6_4Co#1DY-Q;s$n=j>KQb6!RsVm&=D}F){goX@tz~r9dmXP(R#y`^sGaz-G+K5X zC%%%$p%!~SoiuVcSKeQ_C^=#etmdSlm4?FAFl6o7w2l`gq*}NUCG17VDF!UAg@$04 zQNM5Uzh5V=N4ep~R}8QC5prLd2mJvN^<mbYg4LMyR%_H0_)COdZ5Wb!0Zz!YPNyj$ z_J6Df_*HW2839XZUr_8o%D}p^;oq<4gC%m4XS0v?I>=T2Ww3Y?&i-%`x?50p$@XfU z<T^?+DFPVq8&}jqQ9|O4Z6WxbX2Ej^Gt5>L!YE2eEv%ZMo0dUqm$oCOA=eBks2l>d z?tup#;a!KvS#b)Mx$_x)3uQf4(Qmjk>L_ar10XDFloE<aU@Q7c*cf@`fd;CDq<^;g zh!*8?@o{$ZCHtpknL6jYwGzGR{c<t8ahO-P@or8VHn*M)b!taWuMB`9w(iLHk91v> z1yHH2eZ^?;AKp=T0TzUSzFb#q2{#+L!x_Fv@OrnmW82dS$PJst`jh^)4&dicbKi3G zZg0mVXaA~fQd1KpBwG0AFqX9<gm2E?#qb->jd`--T+Ai#TgeQ@n-ju!lbk&kK$go; zLJVxxfUCKLwYO&P=1wQ9WfnKULT$||1wYZj&l3CIq`jwELe_evj`+5}{BL`Aw5m7^ zgaLTctVv8vty<ct^kQLea=-8YZi~orl3~IT;avHD574Wh4Cwrc&MT8JG%wkm2|m=G zo1LPd{rb6$9Y)6QGBt}AoCrSE&?c*}n1x~zHiC#Bn>JU5;B(n_gK+oqZyh)G<Tie5 zLayM86)UH|tBo3c5~^=%aBNONSy2HbYro5<1AEr$BdP7FJlA;u$;wl`iRtAeROQs` z!>}QMnB{W6)hD48NlItr3PjiGWcqzRohKn~)rSD~Ke7d)PeLha^}Uq<{tL39CVI7s zB^Y^J$;TW3EUPujy{wCNx&B%bHImaBzySNb`|{HeZ^6yWgLA<aqf{$%rvVILS&x=Z zi4{iz=wA!JP3DbQT>=3ps!C#ZkzNzMUR?yx-|E>8k-m}QA&VPN02HDYySZtgp5d3z zdLtG<w^uFo><>p#c{NA-yldp?Z%732nlg_KK6&q*_nuk57XjcksZ{5dj*%*O%V6hg x@6w*tCIWb0EWs@cU&aUK>+EjD5CFhW`v)S+^3-dh8~p$P002ovPDHLkV1hxt=*R#7 literal 0 HcmV?d00001 diff --git a/storybook/theme.js b/storybook/theme.js index c13de5b53d4f53..9e340119eb48f8 100644 --- a/storybook/theme.js +++ b/storybook/theme.js @@ -6,6 +6,37 @@ import { create } from '@storybook/theming/create'; export default create( { base: 'light', brandTitle: 'WordPress Components', - brandImage: - 'https://s.w.org/style/images/about/WordPress-logotype-wmark.png', + brandImage: './wp-logo@2x.png', + + // Typography + fontBase: + '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif', + fontCode: 'monospace', + + // + colorPrimary: '#3858E9', + colorSecondary: '#3858E9', + + // UI + appBg: '#ffffff', + appContentBg: '#ffffff', + appPreviewBg: '#ffffff', + appBorderColor: '#DCDCDE', + appBorderRadius: 4, + + // Text colors + textColor: '#10162F', + textInverseColor: '#ffffff', + + // Toolbar default and active colors + barTextColor: '#9E9E9E', + barSelectedColor: '#3858E9', + barHoverColor: '#3858E9', + barBg: '#ffffff', + + // Form colors + inputBg: '#ffffff', + inputBorder: '#10162F', + inputTextColor: '#10162F', + inputBorderRadius: 2, } ); From 8e3146f7bc4b6b4eff27a28f8fb8f0633c414276 Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Thu, 3 Oct 2024 02:53:20 +0200 Subject: [PATCH 1059/1908] `ToggleGroupControl`: clean up animation logic (#65808) * Clean up and misc improvements. * Add default to `transitionEndFilter`. * Rename `attribute` to `dataAttribute` and improve docs. * Update snapshot tests. Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../test/__snapshots__/index.tsx.snap | 8 +- .../toggle-group-control/component.tsx | 91 +++++++++++++------ .../toggle-group-control/styles.ts | 2 +- 3 files changed, 70 insertions(+), 31 deletions(-) diff --git a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap index 6885263d09b23d..d2d98eaba85e6f 100644 --- a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap +++ b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap @@ -61,7 +61,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = } @media not ( prefers-reduced-motion ) { - .emotion-8.is-animation-enabled::before { + .emotion-8[data-indicator-animated]::before { transition-property: transform,border-radius; transition-duration: 0.2s; transition-timing-function: ease-out; @@ -426,7 +426,7 @@ exports[`ToggleGroupControl controlled should render correctly with text options } @media not ( prefers-reduced-motion ) { - .emotion-8.is-animation-enabled::before { + .emotion-8[data-indicator-animated]::before { transition-property: transform,border-radius; transition-duration: 0.2s; transition-timing-function: ease-out; @@ -695,7 +695,7 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] } @media not ( prefers-reduced-motion ) { - .emotion-8.is-animation-enabled::before { + .emotion-8[data-indicator-animated]::before { transition-property: transform,border-radius; transition-duration: 0.2s; transition-timing-function: ease-out; @@ -1054,7 +1054,7 @@ exports[`ToggleGroupControl uncontrolled should render correctly with text optio } @media not ( prefers-reduced-motion ) { - .emotion-8.is-animation-enabled::before { + .emotion-8[data-indicator-animated]::before { transition-property: transform,border-radius; transition-duration: 0.2s; transition-timing-function: ease-out; diff --git a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx index 5f8da76676293e..cdf8a2c04eb0b8 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx @@ -20,43 +20,79 @@ import { VisualLabelWrapper } from './styles'; import * as styles from './styles'; import { ToggleGroupControlAsRadioGroup } from './as-radio-group'; import { ToggleGroupControlAsButtonGroup } from './as-button-group'; +import type { ElementOffsetRect } from '../../utils/element-rect'; import { useTrackElementOffsetRect } from '../../utils/element-rect'; import { useOnValueUpdate } from '../../utils/hooks/use-on-value-update'; import { useEvent, useMergeRefs } from '@wordpress/compose'; /** - * A utility used to animate something (e.g. an indicator for the selected option - * of a component). + * A utility used to animate something in a container component based on the "offset + * rect" (position relative to the container and size) of a subelement. For example, + * this is useful to render an indicator for the selected option of a component, and + * to animate it when the selected option changes. * - * It works by tracking the position and size (i.e., the "rect") of a given subelement, - * typically the one that corresponds to the selected option, relative to its offset - * parent. Then it: + * Takes in a container element and the up-to-date "offset rect" of the target + * subelement, obtained with `useTrackElementOffsetRect`. Then it does the following: * - * - Keeps CSS variables with that information in the parent, so that the animation - * can be implemented with them. - * - Adds a `is-animation-enabled` CSS class when the element changes, so that the - * target (e.g. the indicator) can be animated to its new position. - * - Removes the `is-animation-enabled` class when the animation is done. + * - Adds CSS variables with rect information to the container, so that the indicator + * can be rendered and animated with them. These are kept up-to-date, enabling CSS + * transitions on change. + * - Sets an attribute (`data-subelement-animated` by default) when the tracked + * element changes, so that the target (e.g. the indicator) can be animated to its + * new size and position. + * - Removes the attribute when the animation is done. + * + * The need for the attribute is due to the fact that the rect might update in + * situations other than when the tracked element changes, e.g. the tracked element + * might be resized. In such cases, there is no need to animate the indicator, and + * the change in size or position of the indicator needs to be reflected immediately. */ -function useSubelementAnimation( - subelement?: HTMLElement | null, +function useAnimatedOffsetRect( + /** + * The container element. + */ + container: HTMLElement | undefined, + /** + * The rect of the tracked element. + */ + rect: ElementOffsetRect, { - parent = subelement?.offsetParent as HTMLElement | null | undefined, prefix = 'subelement', - transitionEndFilter, + dataAttribute = `${ prefix }-animated`, + transitionEndFilter = () => true, }: { - parent?: HTMLElement | null | undefined; + /** + * The prefix used for the CSS variables, e.g. if `prefix` is `selected`, the + * CSS variables will be `--selected-top`, `--selected-left`, etc. + * @default 'subelement' + */ prefix?: string; + /** + * The name of the data attribute used to indicate that the animation is in + * progress. The `data-` prefix is added automatically. + * + * For example, if `dataAttribute` is `indicator-animated`, the attribute will + * be `data-indicator-animated`. + * @default `${ prefix }-animated` + */ + dataAttribute?: string; + /** + * A function that is called with the transition event and returns a boolean + * indicating whether the animation should be stopped. The default is a function + * that always returns `true`. + * + * For example, if the animated element is the `::before` pseudo-element, the + * function can be written as `( event ) => event.pseudoElement === '::before'`. + * @default () => true + */ transitionEndFilter?: ( event: TransitionEvent ) => boolean; } = {} ) { - const rect = useTrackElementOffsetRect( subelement ); - const setProperties = useEvent( () => { ( Object.keys( rect ) as Array< keyof typeof rect > ).forEach( ( property ) => property !== 'element' && - parent?.style.setProperty( + container?.style.setProperty( `--${ prefix }-${ property }`, String( rect[ property ] ) ) @@ -68,19 +104,19 @@ function useSubelementAnimation( useOnValueUpdate( rect.element, ( { previousValue } ) => { // Only enable the animation when moving from one element to another. if ( rect.element && previousValue ) { - parent?.classList.add( 'is-animation-enabled' ); + container?.setAttribute( `data-${ dataAttribute }`, '' ); } } ); useLayoutEffect( () => { function onTransitionEnd( event: TransitionEvent ) { - if ( transitionEndFilter?.( event ) ?? true ) { - parent?.classList.remove( 'is-animation-enabled' ); + if ( transitionEndFilter( event ) ) { + container?.removeAttribute( `data-${ dataAttribute }` ); } } - parent?.addEventListener( 'transitionend', onTransitionEnd ); + container?.addEventListener( 'transitionend', onTransitionEnd ); return () => - parent?.removeEventListener( 'transitionend', onTransitionEnd ); - }, [ parent, transitionEndFilter ] ); + container?.removeEventListener( 'transitionend', onTransitionEnd ); + }, [ dataAttribute, container, transitionEndFilter ] ); } function UnconnectedToggleGroupControl( @@ -110,9 +146,12 @@ function UnconnectedToggleGroupControl( const [ selectedElement, setSelectedElement ] = useState< HTMLElement >(); const [ controlElement, setControlElement ] = useState< HTMLElement >(); const refs = useMergeRefs( [ setControlElement, forwardedRef ] ); - useSubelementAnimation( value ? selectedElement : undefined, { - parent: controlElement, + const selectedRect = useTrackElementOffsetRect( + value ? selectedElement : undefined + ); + useAnimatedOffsetRect( controlElement, selectedRect, { prefix: 'selected', + dataAttribute: 'indicator-animated', transitionEndFilter: ( event ) => event.pseudoElement === '::before', } ); diff --git a/packages/components/src/toggle-group-control/toggle-group-control/styles.ts b/packages/components/src/toggle-group-control/toggle-group-control/styles.ts index ee6122126f557f..bb6efe476b2b2c 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/styles.ts +++ b/packages/components/src/toggle-group-control/toggle-group-control/styles.ts @@ -28,7 +28,7 @@ export const toggleGroupControl = ( { ${ ! isDeselectable && enclosingBorders( isBlock ) } @media not ( prefers-reduced-motion ) { - &.is-animation-enabled::before { + &[data-indicator-animated]::before { transition-property: transform, border-radius; transition-duration: 0.2s; transition-timing-function: ease-out; From 4186b74e7784bf96191231c371b9ef49945d62db Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 3 Oct 2024 07:55:50 +0200 Subject: [PATCH 1060/1908] Composite: add "With Tooltip" storybook example (#65817) * Composite: add "With Tooltip" storybook example * Only use one way to compose Tooltip and Composite * Simplify code (no need for custom render) * Rewrite Story JSDocs * Use third item as an example to render with a custom component * Do not use Button for thir composite item --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: diegohaz <hazdiego@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../src/composite/stories/index.story.tsx | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx index d6e4999407e993..c5518375df8a6f 100644 --- a/packages/components/src/composite/stories/index.story.tsx +++ b/packages/components/src/composite/stories/index.story.tsx @@ -13,6 +13,7 @@ import { useContext, useMemo } from '@wordpress/element'; */ import { createSlotFill, Provider as SlotFillProvider } from '../../slot-fill'; import { Composite } from '..'; +import { Tooltip } from '../../tooltip'; const meta: Meta< typeof Composite > = { title: 'Components/Composite', @@ -353,3 +354,44 @@ const Fill = ( { children } ) => { }, }, }; + +/** + * Combining the `Tooltip` and `Composite` component has a few caveats. And while there are a few ways to compose these two components, our recommendation is to render `Composite.Item` as a child of `Tooltip`. + * + * ```jsx + * // 🔴 Does not work + * <Composite.Item + * render={ + * <Tooltip text="Tooltip"> + * <button>Item</button> + * </Tooltip> + * } + * /> + * + * // 🟢 Good + * <Tooltip text="Tooltip one"> + * <Composite.Item> + * Item one + * </Composite.Item> + * </Tooltip> + * ``` + */ +export const WithTooltips: StoryObj< typeof Composite > = { + ...Default, + args: { + ...Default.args, + children: ( + <> + <Tooltip text="Tooltip one"> + <Composite.Item>Item one</Composite.Item> + </Tooltip> + <Tooltip text="Tooltip two"> + <Composite.Item>Item two</Composite.Item> + </Tooltip> + <Tooltip text="Tooltip three"> + <Composite.Item>Item three</Composite.Item> + </Tooltip> + </> + ), + }, +}; From 45ecb4e1e0d59a417ca98dc2eaf6c393de052cfc Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Thu, 3 Oct 2024 15:21:20 +0800 Subject: [PATCH 1061/1908] File block: Allow content only editing (#65787) Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- packages/block-library/src/file/block.json | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/block-library/src/file/block.json b/packages/block-library/src/file/block.json index bf0082c576dd16..2c5e888c2aff64 100644 --- a/packages/block-library/src/file/block.json +++ b/packages/block-library/src/file/block.json @@ -16,7 +16,8 @@ "role": "local" }, "href": { - "type": "string" + "type": "string", + "role": "content" }, "fileId": { "type": "string", @@ -27,13 +28,15 @@ "fileName": { "type": "rich-text", "source": "rich-text", - "selector": "a:not([download])" + "selector": "a:not([download])", + "role": "content" }, "textLinkHref": { "type": "string", "source": "attribute", "selector": "a:not([download])", - "attribute": "href" + "attribute": "href", + "role": "content" }, "textLinkTarget": { "type": "string", @@ -48,7 +51,8 @@ "downloadButtonText": { "type": "rich-text", "source": "rich-text", - "selector": "a[download]" + "selector": "a[download]", + "role": "content" }, "displayPreview": { "type": "boolean" From 0973cc8cedb9ae3bba7f7723f0ca5d4ea9a419d1 Mon Sep 17 00:00:00 2001 From: Filipe Varela <keoshi@keoshi.com> Date: Thu, 3 Oct 2024 08:23:47 +0100 Subject: [PATCH 1062/1908] Storybook: allow for case-agnostic filtering of icons (#65780) --- packages/icons/src/icon/stories/index.story.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/icons/src/icon/stories/index.story.js b/packages/icons/src/icon/stories/index.story.js index 8fda801f23884f..092434de43b4dc 100644 --- a/packages/icons/src/icon/stories/index.story.js +++ b/packages/icons/src/icon/stories/index.story.js @@ -47,7 +47,7 @@ const LibraryExample = () => { const filteredIcons = filter.length ? Object.fromEntries( Object.entries( availableIcons ).filter( ( [ name ] ) => - name.includes( filter ) + name.toLowerCase().includes( filter.toLowerCase() ) ) ) : availableIcons; From 23846c002f889e6403ee8bed8aeb5d6f08a74615 Mon Sep 17 00:00:00 2001 From: Amit Raj <77401999+amitraj2203@users.noreply.github.com> Date: Thu, 3 Oct 2024 14:55:59 +0530 Subject: [PATCH 1063/1908] Makes spacing consistent in zoom out vertical toolbar (#63994) * chore: Update block vertical toolbar height in variables and styles * Removed the variable and hardcoded the value. * Avoid changes to components package * use the button width scss variable --------- Co-authored-by: amitraj2203 <amitraj2203@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/block-editor/src/components/block-tools/style.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index b7586a6715dcc6..fe9da021b31823 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -201,4 +201,9 @@ background: none; border: none; } + + // Make the spacing consistent between controls. + .components-button { + height: $button-size-next-default-40px; + } } From f7c4cac57e3ef516400a2a30a15be3d7549dc3c0 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Thu, 3 Oct 2024 11:38:00 +0100 Subject: [PATCH 1064/1908] Filter UI: Remove popover max height (#65835) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/dataviews/src/components/dataviews-filters/style.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/dataviews/src/components/dataviews-filters/style.scss b/packages/dataviews/src/components/dataviews-filters/style.scss index ad834fb224e2e4..130ef8872615a5 100644 --- a/packages/dataviews/src/components/dataviews-filters/style.scss +++ b/packages/dataviews/src/components/dataviews-filters/style.scss @@ -160,7 +160,6 @@ } .dataviews-filters__search-widget-listbox { - max-height: $grid-unit * 23; padding: $grid-unit-05; overflow: auto; } From edcd976856aca48abf61ecca5e16322a8c3d16fc Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 3 Oct 2024 13:32:09 +0200 Subject: [PATCH 1065/1908] Composite: make items tabbable if active element gets removed (#65720) * Composite: make items tabbable when the active element is disconnected * Add unit test * Better test name * CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: diegohaz <hazdiego@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/composite/item.tsx | 20 ++- .../components/src/composite/test/index.tsx | 123 ++++++++++++++++++ 3 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 packages/components/src/composite/test/index.tsx diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 4c00ea32bae2cb..449abca7b6420c 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -9,6 +9,7 @@ - `ToggleGroupControl`: Fix arrow key navigation in RTL ([#65735](https://github.com/WordPress/gutenberg/pull/65735)). - `ToggleGroupControl`: indicator doesn't jump around when the layout around it changes ([#65175](https://github.com/WordPress/gutenberg/pull/65175)). - `Composite`: fix legacy support for the store prop ([#65821](https://github.com/WordPress/gutenberg/pull/65821)). +- `Composite`: make items tabbable if active element gets removed ([#65720](https://github.com/WordPress/gutenberg/pull/65720)). ### Deprecations diff --git a/packages/components/src/composite/item.tsx b/packages/components/src/composite/item.tsx index 4a02f76039a5cf..edbf0b92e039af 100644 --- a/packages/components/src/composite/item.tsx +++ b/packages/components/src/composite/item.tsx @@ -26,5 +26,23 @@ export const CompositeItem = forwardRef< // obfuscated to discourage its use outside of the component's internals. const store = ( props.store ?? context.store ) as Ariakit.CompositeStore; - return <Ariakit.CompositeItem store={ store } { ...props } ref={ ref } />; + // If the active item is not connected, Composite may end up in a state + // where none of the items are tabbable. In this case, we force all items to + // be tabbable, so that as soon as an item received focus, it becomes active + // and Composite goes back to working as expected. + const tabbable = Ariakit.useStoreState( store, ( state ) => { + return ( + state?.activeId !== null && + ! store?.item( state?.activeId )?.element?.isConnected + ); + } ); + + return ( + <Ariakit.CompositeItem + store={ store } + tabbable={ tabbable } + { ...props } + ref={ ref } + /> + ); } ); diff --git a/packages/components/src/composite/test/index.tsx b/packages/components/src/composite/test/index.tsx new file mode 100644 index 00000000000000..64619aaed01bd6 --- /dev/null +++ b/packages/components/src/composite/test/index.tsx @@ -0,0 +1,123 @@ +/** + * External dependencies + */ +import { queryByAttribute, render, screen } from '@testing-library/react'; +import { click, press, waitFor } from '@ariakit/test'; +import type { ComponentProps } from 'react'; + +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { Composite } from '..'; + +// This is necessary because of how Ariakit calculates page up and +// page down. Without this, nothing has a height, and so paging up +// and down doesn't behave as expected in tests. + +let clientHeightSpy: jest.SpiedGetter< + typeof HTMLElement.prototype.clientHeight +>; + +beforeAll( () => { + clientHeightSpy = jest + .spyOn( HTMLElement.prototype, 'clientHeight', 'get' ) + .mockImplementation( function getClientHeight( this: HTMLElement ) { + if ( this.tagName === 'BODY' ) { + return window.outerHeight; + } + return 50; + } ); +} ); + +afterAll( () => { + clientHeightSpy?.mockRestore(); +} ); + +async function renderAndValidate( ...args: Parameters< typeof render > ) { + const view = render( ...args ); + await waitFor( () => { + const activeButton = queryByAttribute( + 'data-active-item', + view.baseElement, + 'true' + ); + expect( activeButton ).not.toBeNull(); + } ); + return view; +} + +function RemoveItemTest( props: ComponentProps< typeof Composite > ) { + const [ showThirdItem, setShowThirdItem ] = useState( true ); + return ( + <> + <button>Focus trap before composite</button> + <Composite { ...props }> + <Composite.Item>Item 1</Composite.Item> + <Composite.Item>Item 2</Composite.Item> + { showThirdItem && <Composite.Item>Item 3</Composite.Item> } + </Composite> + <button onClick={ () => setShowThirdItem( ( value ) => ! value ) }> + Toggle third item + </button> + </> + ); +} + +describe( 'Composite', () => { + it( 'should remain focusable even when there are no elements in the DOM associated with the currently active ID', async () => { + await renderAndValidate( <RemoveItemTest /> ); + + const toggleButton = screen.getByRole( 'button', { + name: 'Toggle third item', + } ); + + await press.Tab(); + await press.Tab(); + + expect( + screen.getByRole( 'button', { name: 'Item 1' } ) + ).toHaveFocus(); + + await press.ArrowRight(); + await press.ArrowRight(); + + expect( + screen.getByRole( 'button', { name: 'Item 3' } ) + ).toHaveFocus(); + + await click( toggleButton ); + + expect( + screen.queryByRole( 'button', { name: 'Item 3' } ) + ).not.toBeInTheDocument(); + + await press.ShiftTab(); + + expect( + screen.getByRole( 'button', { name: 'Item 2' } ) + ).toHaveFocus(); + + await click( toggleButton ); + + expect( + screen.getByRole( 'button', { name: 'Item 3' } ) + ).toBeVisible(); + + await press.ShiftTab(); + + expect( + screen.getByRole( 'button', { name: 'Item 2' } ) + ).toHaveFocus(); + + await press.ArrowRight(); + + expect( + screen.getByRole( 'button', { name: 'Item 3' } ) + ).toHaveFocus(); + } ); +} ); From 20f35ddd8ad178ce0ee086048fed86300fdd5267 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Thu, 3 Oct 2024 19:37:22 +0800 Subject: [PATCH 1066/1908] Top Toolbar: Show document bar when no block is selected even if block tools are expanded (#65839) * Top Toolbar: Show document bar when no block is selected even if block tools are expanded * Change variable name to hasBlockSelection ---- Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: eatse21 <eatse@git.wordpress.org> --- packages/editor/src/components/header/index.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index f49ada48997ce5..631643f26d4d5f 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -1,6 +1,7 @@ /** * WordPress dependencies */ +import { store as blockEditorStore } from '@wordpress/block-editor'; import { useSelect } from '@wordpress/data'; import { useMediaQuery, useViewportMatch } from '@wordpress/compose'; import { __unstableMotion as motion } from '@wordpress/components'; @@ -52,12 +53,13 @@ function Header( { const isLargeViewport = useViewportMatch( 'medium' ); const isTooNarrowForDocumentBar = useMediaQuery( '(max-width: 403px)' ); const { + postType, isTextEditor, isPublishSidebarOpened, showIconLabels, hasFixedToolbar, + hasBlockSelection, isNestedEntity, - postType, } = useSelect( ( select ) => { const { get: getPreference } = select( preferencesStore ); const { @@ -73,6 +75,8 @@ function Header( { isPublishSidebarOpened: _isPublishSidebarOpened(), showIconLabels: getPreference( 'core', 'showIconLabels' ), hasFixedToolbar: getPreference( 'core', 'fixedToolbar' ), + hasBlockSelection: + !! select( blockEditorStore ).getBlockSelectionStart(), isNestedEntity: !! getEditorSettings().onNavigateToPreviousEntityRecord, }; @@ -85,7 +89,9 @@ function Header( { const [ isBlockToolsCollapsed, setIsBlockToolsCollapsed ] = useState( true ); - const hasCenter = isBlockToolsCollapsed && ! isTooNarrowForDocumentBar; + const hasCenter = + ( ! hasBlockSelection || isBlockToolsCollapsed ) && + ! isTooNarrowForDocumentBar; const hasBackButton = useHasBackButton(); /* * The edit-post-header classname is only kept for backward compatability From 3c77f80cd3492eedc656e12d341ed2fe64ab8514 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 3 Oct 2024 14:49:35 +0200 Subject: [PATCH 1067/1908] Remove user-select:text (#65662) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../src/components/block-list/content.scss | 10 ---------- packages/block-library/src/editor.scss | 1 - packages/block-library/src/post-content/editor.scss | 4 ---- 3 files changed, 15 deletions(-) delete mode 100644 packages/block-library/src/post-content/editor.scss diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index c5fda109d8b67d..6a88813b0c6049 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -91,14 +91,6 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b } } - // Ensure an accurate partial text selection. - // To do this, we disable text selection on the main container, then re-enable it only on the - // elements that actually get selected. - // To keep in mind: user-select is currently inherited to all nodes inside. - .has-multi-selection & { - user-select: none; - } - // Re-enable it on components inside. [class^="components-"] { user-select: text; @@ -117,11 +109,9 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b overflow-wrap: break-word; pointer-events: auto; - user-select: text; &.is-editing-disabled { pointer-events: none; - user-select: none; } &.has-negative-margin { diff --git a/packages/block-library/src/editor.scss b/packages/block-library/src/editor.scss index 0669a082b1086f..a16d5a6c2c69c7 100644 --- a/packages/block-library/src/editor.scss +++ b/packages/block-library/src/editor.scss @@ -55,7 +55,6 @@ @import "./query-pagination-numbers/editor.scss"; @import "./post-featured-image/editor.scss"; @import "./post-comments-form/editor.scss"; -@import "./post-content/editor.scss"; @import "./editor-elements.scss"; :root .editor-styles-wrapper { diff --git a/packages/block-library/src/post-content/editor.scss b/packages/block-library/src/post-content/editor.scss deleted file mode 100644 index 626774697aec5f..00000000000000 --- a/packages/block-library/src/post-content/editor.scss +++ /dev/null @@ -1,4 +0,0 @@ -// Disable text selection in the post content placeholder. -.wp-block-post-content.wp-block-post-content { - user-select: none; -} From ddf05d87e7a110952d491a520c91a3f7fee9bef1 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 3 Oct 2024 13:56:15 +0000 Subject: [PATCH 1068/1908] Bump plugin version to 19.4.0-rc.1 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 466509dcf6b585..c9f4a8fc580200 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.3.0 + * Version: 19.4.0-rc.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index c13e4cf2096cd0..c800d47891c180 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.3.0", + "version": "19.4.0-rc.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.3.0", + "version": "19.4.0-rc.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 5ecd0ef57b3516..b240c89e76d42d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.3.0", + "version": "19.4.0-rc.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 6a9f1aba6812f4bd0c9c0e3931e94a1335c79460 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 3 Oct 2024 14:04:53 +0000 Subject: [PATCH 1069/1908] Update changelog files --- packages/a11y/CHANGELOG.md | 2 ++ packages/a11y/package.json | 2 +- packages/annotations/CHANGELOG.md | 2 ++ packages/annotations/package.json | 2 +- packages/api-fetch/CHANGELOG.md | 2 ++ packages/api-fetch/package.json | 2 +- packages/autop/CHANGELOG.md | 2 ++ packages/autop/package.json | 2 +- packages/babel-plugin-import-jsx-pragma/CHANGELOG.md | 2 ++ packages/babel-plugin-import-jsx-pragma/package.json | 2 +- packages/babel-plugin-makepot/CHANGELOG.md | 2 ++ packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/CHANGELOG.md | 2 ++ packages/babel-preset-default/package.json | 2 +- packages/base-styles/CHANGELOG.md | 2 ++ packages/base-styles/package.json | 2 +- packages/blob/CHANGELOG.md | 2 ++ packages/blob/package.json | 2 +- packages/block-directory/CHANGELOG.md | 2 ++ packages/block-directory/package.json | 2 +- packages/block-editor/CHANGELOG.md | 2 ++ packages/block-editor/package.json | 2 +- packages/block-library/CHANGELOG.md | 2 ++ packages/block-library/package.json | 2 +- packages/block-serialization-default-parser/CHANGELOG.md | 2 ++ packages/block-serialization-default-parser/package.json | 2 +- packages/block-serialization-spec-parser/CHANGELOG.md | 2 ++ packages/block-serialization-spec-parser/package.json | 2 +- packages/blocks/CHANGELOG.md | 2 ++ packages/blocks/package.json | 2 +- packages/browserslist-config/CHANGELOG.md | 2 ++ packages/browserslist-config/package.json | 2 +- packages/commands/CHANGELOG.md | 2 ++ packages/commands/package.json | 2 +- packages/components/CHANGELOG.md | 2 ++ packages/components/package.json | 2 +- packages/compose/CHANGELOG.md | 2 ++ packages/compose/package.json | 2 +- packages/core-commands/CHANGELOG.md | 2 ++ packages/core-commands/package.json | 2 +- packages/core-data/CHANGELOG.md | 2 ++ packages/core-data/package.json | 2 +- packages/create-block-interactive-template/package.json | 2 +- packages/create-block-tutorial-template/CHANGELOG.md | 2 ++ packages/create-block-tutorial-template/package.json | 2 +- packages/create-block/CHANGELOG.md | 2 ++ packages/create-block/package.json | 2 +- packages/customize-widgets/CHANGELOG.md | 2 ++ packages/customize-widgets/package.json | 2 +- packages/data-controls/CHANGELOG.md | 2 ++ packages/data-controls/package.json | 2 +- packages/data/CHANGELOG.md | 2 ++ packages/data/package.json | 2 +- packages/dataviews/CHANGELOG.md | 2 ++ packages/dataviews/package.json | 2 +- packages/date/CHANGELOG.md | 2 ++ packages/date/package.json | 2 +- packages/dependency-extraction-webpack-plugin/CHANGELOG.md | 2 ++ packages/dependency-extraction-webpack-plugin/package.json | 2 +- packages/deprecated/CHANGELOG.md | 2 ++ packages/deprecated/package.json | 2 +- packages/docgen/CHANGELOG.md | 2 ++ packages/docgen/package.json | 2 +- packages/dom-ready/CHANGELOG.md | 2 ++ packages/dom-ready/package.json | 2 +- packages/dom/CHANGELOG.md | 2 ++ packages/dom/package.json | 2 +- packages/e2e-test-utils-playwright/CHANGELOG.md | 2 ++ packages/e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/CHANGELOG.md | 2 ++ packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/CHANGELOG.md | 2 ++ packages/e2e-tests/package.json | 2 +- packages/edit-post/CHANGELOG.md | 2 ++ packages/edit-post/package.json | 2 +- packages/edit-site/CHANGELOG.md | 2 ++ packages/edit-site/package.json | 2 +- packages/edit-widgets/CHANGELOG.md | 2 ++ packages/edit-widgets/package.json | 2 +- packages/editor/CHANGELOG.md | 2 ++ packages/editor/package.json | 2 +- packages/element/CHANGELOG.md | 2 ++ packages/element/package.json | 2 +- packages/env/CHANGELOG.md | 2 ++ packages/env/package.json | 2 +- packages/escape-html/CHANGELOG.md | 2 ++ packages/escape-html/package.json | 2 +- packages/eslint-plugin/CHANGELOG.md | 2 ++ packages/eslint-plugin/package.json | 2 +- packages/fields/CHANGELOG.md | 2 ++ packages/fields/package.json | 2 +- packages/format-library/CHANGELOG.md | 2 ++ packages/format-library/package.json | 2 +- packages/hooks/CHANGELOG.md | 2 ++ packages/hooks/package.json | 2 +- packages/html-entities/CHANGELOG.md | 2 ++ packages/html-entities/package.json | 2 +- packages/i18n/CHANGELOG.md | 2 ++ packages/i18n/package.json | 2 +- packages/icons/CHANGELOG.md | 2 ++ packages/icons/package.json | 2 +- packages/interactivity-router/CHANGELOG.md | 2 ++ packages/interactivity-router/package.json | 2 +- packages/interactivity/CHANGELOG.md | 2 ++ packages/interactivity/package.json | 2 +- packages/interface/CHANGELOG.md | 2 ++ packages/interface/package.json | 2 +- packages/is-shallow-equal/CHANGELOG.md | 2 ++ packages/is-shallow-equal/package.json | 2 +- packages/jest-console/CHANGELOG.md | 2 ++ packages/jest-console/package.json | 2 +- packages/jest-preset-default/CHANGELOG.md | 2 ++ packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/CHANGELOG.md | 2 ++ packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/CHANGELOG.md | 2 ++ packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/CHANGELOG.md | 2 ++ packages/keycodes/package.json | 2 +- packages/lazy-import/CHANGELOG.md | 2 ++ packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/CHANGELOG.md | 2 ++ packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/CHANGELOG.md | 2 ++ packages/media-utils/package.json | 2 +- packages/notices/CHANGELOG.md | 2 ++ packages/notices/package.json | 2 +- packages/npm-package-json-lint-config/CHANGELOG.md | 2 ++ packages/npm-package-json-lint-config/package.json | 2 +- packages/nux/CHANGELOG.md | 2 ++ packages/nux/package.json | 2 +- packages/patterns/CHANGELOG.md | 2 ++ packages/patterns/package.json | 2 +- packages/plugins/CHANGELOG.md | 2 ++ packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/CHANGELOG.md | 2 ++ packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/CHANGELOG.md | 2 ++ packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/CHANGELOG.md | 2 ++ packages/preferences-persistence/package.json | 2 +- packages/preferences/CHANGELOG.md | 2 ++ packages/preferences/package.json | 2 +- packages/prettier-config/CHANGELOG.md | 2 ++ packages/prettier-config/package.json | 2 +- packages/primitives/CHANGELOG.md | 2 ++ packages/primitives/package.json | 2 +- packages/priority-queue/CHANGELOG.md | 2 ++ packages/priority-queue/package.json | 2 +- packages/private-apis/CHANGELOG.md | 2 ++ packages/private-apis/package.json | 2 +- packages/project-management-automation/CHANGELOG.md | 2 ++ packages/project-management-automation/package.json | 2 +- packages/react-i18n/CHANGELOG.md | 2 ++ packages/react-i18n/package.json | 2 +- packages/readable-js-assets-webpack-plugin/CHANGELOG.md | 2 ++ packages/readable-js-assets-webpack-plugin/package.json | 2 +- packages/redux-routine/CHANGELOG.md | 2 ++ packages/redux-routine/package.json | 2 +- packages/reusable-blocks/CHANGELOG.md | 2 ++ packages/reusable-blocks/package.json | 2 +- packages/rich-text/CHANGELOG.md | 2 ++ packages/rich-text/package.json | 2 +- packages/router/CHANGELOG.md | 2 ++ packages/router/package.json | 2 +- packages/scripts/CHANGELOG.md | 2 ++ packages/scripts/package.json | 2 +- packages/server-side-render/CHANGELOG.md | 2 ++ packages/server-side-render/package.json | 2 +- packages/shortcode/CHANGELOG.md | 2 ++ packages/shortcode/package.json | 2 +- packages/style-engine/CHANGELOG.md | 2 ++ packages/style-engine/package.json | 2 +- packages/stylelint-config/CHANGELOG.md | 2 ++ packages/stylelint-config/package.json | 2 +- packages/sync/CHANGELOG.md | 2 ++ packages/sync/package.json | 2 +- packages/token-list/CHANGELOG.md | 2 ++ packages/token-list/package.json | 2 +- packages/undo-manager/CHANGELOG.md | 2 ++ packages/undo-manager/package.json | 2 +- packages/url/CHANGELOG.md | 2 ++ packages/url/package.json | 2 +- packages/viewport/CHANGELOG.md | 2 ++ packages/viewport/package.json | 2 +- packages/warning/CHANGELOG.md | 2 ++ packages/warning/package.json | 2 +- packages/widgets/CHANGELOG.md | 2 ++ packages/widgets/package.json | 2 +- packages/wordcount/CHANGELOG.md | 2 ++ packages/wordcount/package.json | 2 +- 191 files changed, 286 insertions(+), 96 deletions(-) diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index 626488313977d1..7da784818f78c8 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/a11y/package.json b/packages/a11y/package.json index d3337485a18284..d9b6c88bc783f6 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/CHANGELOG.md b/packages/annotations/CHANGELOG.md index 7ac3e50c3fd8b6..caf30a752bb986 100644 --- a/packages/annotations/CHANGELOG.md +++ b/packages/annotations/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.9.0 (2024-10-03) + ## 3.8.0 (2024-09-19) ## 3.7.0 (2024-09-05) diff --git a/packages/annotations/package.json b/packages/annotations/package.json index edaae0ca7617bd..9b6c0af4195487 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.8.0", + "version": "3.9.0-prerelease", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/CHANGELOG.md b/packages/api-fetch/CHANGELOG.md index 7c333170b6cc11..151afa5206c35c 100644 --- a/packages/api-fetch/CHANGELOG.md +++ b/packages/api-fetch/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.9.0 (2024-10-03) + ## 7.8.0 (2024-09-19) ## 7.7.0 (2024-09-05) diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 54fb852a75402e..20410c226aa970 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.8.0", + "version": "7.9.0-prerelease", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/CHANGELOG.md b/packages/autop/CHANGELOG.md index 4bb494dcfff5c0..b56c0ada46a919 100644 --- a/packages/autop/CHANGELOG.md +++ b/packages/autop/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/autop/package.json b/packages/autop/package.json index 49ddffcf79f9ce..30594cc8cd4500 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md index 5a68cf8eb40400..8f15b849096f66 100644 --- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md +++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index d06a750eb0d91e..453ba0586b3bb7 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/CHANGELOG.md b/packages/babel-plugin-makepot/CHANGELOG.md index d878e1fb6b020c..d307791a37424a 100644 --- a/packages/babel-plugin-makepot/CHANGELOG.md +++ b/packages/babel-plugin-makepot/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.9.0 (2024-10-03) + ## 6.8.0 (2024-09-19) ## 6.7.0 (2024-09-05) diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index 5c9cbb1384796b..1d519b806e2946 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.8.0", + "version": "6.9.0-prerelease", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index b31be6ffd8d56d..c577d6fd038bcf 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.9.0 (2024-10-03) + ### Bug Fixes - Fix a bug in 8.8.1 due to missing files in the published package ([#65481](https://github.com/WordPress/gutenberg/pull/65481)). diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 1203586ec20292..15cd827171f474 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.8.0", + "version": "8.9.0-prerelease", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/CHANGELOG.md b/packages/base-styles/CHANGELOG.md index ea6b765aea3f11..8e92ddeece4d20 100644 --- a/packages/base-styles/CHANGELOG.md +++ b/packages/base-styles/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index c6ab374e1f5dd3..0af745e39db4db 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md index c13c6e6faf6ac8..1631fe7e0618b3 100644 --- a/packages/blob/CHANGELOG.md +++ b/packages/blob/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/blob/package.json b/packages/blob/package.json index cbcf04ecf64882..067b7382a5513b 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/CHANGELOG.md b/packages/block-directory/CHANGELOG.md index 8c25431f1b5b5e..2677ce827c1d69 100644 --- a/packages/block-directory/CHANGELOG.md +++ b/packages/block-directory/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 974125a5f3f2c3..fbeeddafe875f0 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index db61ff05e3c1ad..5e3151285966e2 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.4.0 (2024-10-03) + ## 14.3.0 (2024-09-19) ## 14.2.0 (2024-09-05) diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index a135f126d7eb3c..4773dda51f54b8 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.3.0", + "version": "14.4.0-prerelease", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index 08accf8c36d9e5..5ffd428b6dbdcf 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.9.0 (2024-10-03) + ## 9.8.0 (2024-09-19) ## 9.7.0 (2024-09-05) diff --git a/packages/block-library/package.json b/packages/block-library/package.json index aa9daf62dda63a..b6a1154e9c8300 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.8.0", + "version": "9.9.0-prerelease", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/CHANGELOG.md b/packages/block-serialization-default-parser/CHANGELOG.md index 47e1db147942ff..4104f5282ce3fb 100644 --- a/packages/block-serialization-default-parser/CHANGELOG.md +++ b/packages/block-serialization-default-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 60e638120952d8..93e3a5a38049d2 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/CHANGELOG.md b/packages/block-serialization-spec-parser/CHANGELOG.md index 173ce09db51e2b..87c683849585e0 100644 --- a/packages/block-serialization-spec-parser/CHANGELOG.md +++ b/packages/block-serialization-spec-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index ab73fa1689ad67..87b5c051177c3f 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 838983c17233ea..7e163fec2ad161 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 13.9.0 (2024-10-03) + ## 13.8.0 (2024-09-19) ## 13.7.0 (2024-09-05) diff --git a/packages/blocks/package.json b/packages/blocks/package.json index b2c24928b7c344..7594840fb58d5b 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.8.0", + "version": "13.9.0-prerelease", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/CHANGELOG.md b/packages/browserslist-config/CHANGELOG.md index cbe4763ea32706..9dae2564c1a32e 100644 --- a/packages/browserslist-config/CHANGELOG.md +++ b/packages/browserslist-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.9.0 (2024-10-03) + ## 6.8.0 (2024-09-19) ## 6.7.0 (2024-09-05) diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index cae627c406e817..24adbde9c53e85 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.8.0", + "version": "6.9.0-prerelease", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/CHANGELOG.md b/packages/commands/CHANGELOG.md index b8f45c79470040..2b268bd66f404e 100644 --- a/packages/commands/CHANGELOG.md +++ b/packages/commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.9.0 (2024-10-03) + ## 1.8.0 (2024-09-19) ## 1.7.0 (2024-09-05) diff --git a/packages/commands/package.json b/packages/commands/package.json index 769931293bd2fd..70465b15f18b29 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.8.0", + "version": "1.9.0-prerelease", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 449abca7b6420c..1e9fdbe07c94e7 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 28.9.0 (2024-10-03) + ### Bug Fixes - `ToolsPanel`: atomic one-step state update when (un)registering panels ([#65564](https://github.com/WordPress/gutenberg/pull/65564)). diff --git a/packages/components/package.json b/packages/components/package.json index 98eb4c5de0430d..78af25cdff54a4 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.8.0", + "version": "28.9.0-prerelease", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index 28269dca692a4f..e94eed5a08677b 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.9.0 (2024-10-03) + ### Bug Fixes - `useResizeObserver`: export legacy API at top-level for React Native ([#65588](https://github.com/WordPress/gutenberg/pull/65588)). diff --git a/packages/compose/package.json b/packages/compose/package.json index f52ac9956a75c1..a10486fade88e9 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.8.0", + "version": "7.9.0-prerelease", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/CHANGELOG.md b/packages/core-commands/CHANGELOG.md index 2d8d93373f4c5e..bd259351a87999 100644 --- a/packages/core-commands/CHANGELOG.md +++ b/packages/core-commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.9.0 (2024-10-03) + ## 1.8.0 (2024-09-19) ## 1.7.0 (2024-09-05) diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index a2d3c76ebe5d9c..575ef291eea45e 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.8.0", + "version": "1.9.0-prerelease", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md index fcedd5d1100661..8a59c811840357 100644 --- a/packages/core-data/CHANGELOG.md +++ b/packages/core-data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.9.0 (2024-10-03) + ## 7.8.0 (2024-09-19) ## 7.7.0 (2024-09-05) diff --git a/packages/core-data/package.json b/packages/core-data/package.json index b0eadbcea26039..124f4bb6421fad 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.8.0", + "version": "7.9.0-prerelease", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index ad30a4b7e01955..2ff5f35ab3dce1 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.8.0", + "version": "2.9.0-prerelease", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/CHANGELOG.md b/packages/create-block-tutorial-template/CHANGELOG.md index e93bc0270ba953..9be4223c70f383 100644 --- a/packages/create-block-tutorial-template/CHANGELOG.md +++ b/packages/create-block-tutorial-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index 67b0c9554ed988..11b94a63b8889e 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index d3a8c1c75dd3fb..db161872fb9828 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.52.0 (2024-10-03) + ## 4.51.0 (2024-09-19) ## 4.50.0 (2024-09-05) diff --git a/packages/create-block/package.json b/packages/create-block/package.json index e1522c887deef8..4b6cc0d4cb3867 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.51.0", + "version": "4.52.0-prerelease", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/CHANGELOG.md b/packages/customize-widgets/CHANGELOG.md index 061b656c892c79..46064bac3391ec 100644 --- a/packages/customize-widgets/CHANGELOG.md +++ b/packages/customize-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 05edab039844b5..59cafbdb7edecf 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/CHANGELOG.md b/packages/data-controls/CHANGELOG.md index 3d16450a7825b4..6e70039bc74765 100644 --- a/packages/data-controls/CHANGELOG.md +++ b/packages/data-controls/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 5d4d06d3c13cd8..6c549e200d603b 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index f9ebf9eb17a68c..71db937ed73b48 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.9.0 (2024-10-03) + ## 10.8.0 (2024-09-19) ## 10.7.0 (2024-09-05) diff --git a/packages/data/package.json b/packages/data/package.json index 11396fe33e0876..15de6f05e7dabe 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.8.0", + "version": "10.9.0-prerelease", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 6ce337d726e083..7569cfb93ac0b6 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 (2024-10-03) + ## 4.4.0 (2024-09-19) ## 4.3.0 (2024-09-05) diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index 6265d88a4ad82f..ebd313da5ab253 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.4.0", + "version": "4.5.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md index 8c28ff83d53ed8..01e9cdc76984c8 100644 --- a/packages/date/CHANGELOG.md +++ b/packages/date/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/date/package.json b/packages/date/package.json index ad957a6393e1c8..f3f3682ca64b09 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index 7c8f74d2906fed..c9d127e899fd73 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.9.0 (2024-10-03) + ### Enhancements - Detection of magic comments is now done before minification ([#65582](https://github.com/WordPress/gutenberg/pull/65582)). diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index a9368e1eb18259..b3e628dfc0acbf 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.8.0", + "version": "6.9.0-prerelease", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/CHANGELOG.md b/packages/deprecated/CHANGELOG.md index 945bf44ad6a653..0fb389ad15d7e1 100644 --- a/packages/deprecated/CHANGELOG.md +++ b/packages/deprecated/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 245d459fb842e5..3732620632486c 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/CHANGELOG.md b/packages/docgen/CHANGELOG.md index 3e966fc4518d75..d01b1f9a9f62d7 100644 --- a/packages/docgen/CHANGELOG.md +++ b/packages/docgen/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.9.0 (2024-10-03) + ## 2.8.0 (2024-09-19) ## 2.7.0 (2024-09-05) diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 9bd4581859193f..530ec87af0b8b7 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.8.0", + "version": "2.9.0-prerelease", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/CHANGELOG.md b/packages/dom-ready/CHANGELOG.md index 265e7b5947061a..a14e6185202376 100644 --- a/packages/dom-ready/CHANGELOG.md +++ b/packages/dom-ready/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 9f4ffbcf61e410..6715a44205c7b6 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/CHANGELOG.md b/packages/dom/CHANGELOG.md index 77f85a59cada84..e5c95089da8c36 100644 --- a/packages/dom/CHANGELOG.md +++ b/packages/dom/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/dom/package.json b/packages/dom/package.json index 6707de05992697..2c794abc0a2c71 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/CHANGELOG.md b/packages/e2e-test-utils-playwright/CHANGELOG.md index b53821f46eefef..0c1833eed08495 100644 --- a/packages/e2e-test-utils-playwright/CHANGELOG.md +++ b/packages/e2e-test-utils-playwright/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.9.0 (2024-10-03) + ## 1.8.0 (2024-09-19) ## 1.7.0 (2024-09-05) diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index f8e31ddc3c359a..ac0c9d8d4de3f0 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.8.0", + "version": "1.9.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index 98c17f5b6ecb01..8a00b87a34dfd9 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 11.9.0 (2024-10-03) + ## 11.8.0 (2024-09-19) ## 11.7.0 (2024-09-05) diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index eeb0e66cb62a78..72c1589a399e51 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.8.0", + "version": "11.9.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md index 3fe696deaabb53..9d94db55206f10 100644 --- a/packages/e2e-tests/CHANGELOG.md +++ b/packages/e2e-tests/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.9.0 (2024-10-03) + ## 8.8.0 (2024-09-19) ## 8.7.0 (2024-09-05) diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 2ce38150c96a00..7ff65a2ee56cb6 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.8.0", + "version": "8.9.0-prerelease", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index 3eb52f26e65012..41a960ee4e5d27 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.9.0 (2024-10-03) + ## 8.8.0 (2024-09-19) ## 8.7.0 (2024-09-05) diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 1e5cbb13892a17..6269b80d482a23 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.8.0", + "version": "8.9.0-prerelease", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/CHANGELOG.md b/packages/edit-site/CHANGELOG.md index b14fb6dcd6d3e8..e2a728b3fc9ce9 100644 --- a/packages/edit-site/CHANGELOG.md +++ b/packages/edit-site/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.9.0 (2024-10-03) + ## 6.8.0 (2024-09-19) ## 6.7.0 (2024-09-05) diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index ef1cdaaa6a5c76..11a501377dcede 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.8.0", + "version": "6.9.0-prerelease", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/CHANGELOG.md b/packages/edit-widgets/CHANGELOG.md index 6115fc42560f82..80fde2bfec86e7 100644 --- a/packages/edit-widgets/CHANGELOG.md +++ b/packages/edit-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.9.0 (2024-10-03) + ## 6.8.0 (2024-09-19) ## 6.7.0 (2024-09-05) diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index f0cc613aa40fc2..8f920ecefa596d 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.8.0", + "version": "6.9.0-prerelease", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index 6f31c1735021f6..dbd2884ab88560 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.9.0 (2024-10-03) + ## 14.8.0 (2024-09-19) ## 14.7.0 (2024-09-05) diff --git a/packages/editor/package.json b/packages/editor/package.json index 29cbffcfb72221..15356fc279c62b 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.8.0", + "version": "14.9.0-prerelease", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/CHANGELOG.md b/packages/element/CHANGELOG.md index ee63e4b5e70fa8..c480f3a0469b53 100644 --- a/packages/element/CHANGELOG.md +++ b/packages/element/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.9.0 (2024-10-03) + ## 6.8.0 (2024-09-19) ## 6.7.0 (2024-09-05) diff --git a/packages/element/package.json b/packages/element/package.json index 56759cdc23d91b..afa90afa11539e 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.8.0", + "version": "6.9.0-prerelease", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md index 0b32fd808d9603..1adbc578b11e2f 100644 --- a/packages/env/CHANGELOG.md +++ b/packages/env/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.9.0 (2024-10-03) + ## 10.8.0 (2024-09-19) ## 10.7.0 (2024-09-05) diff --git a/packages/env/package.json b/packages/env/package.json index b1ea172a4303d9..9ccf40ed5400a4 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.8.0", + "version": "10.9.0-prerelease", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/CHANGELOG.md b/packages/escape-html/CHANGELOG.md index c13edebda4480a..2ba6cc20e2438f 100644 --- a/packages/escape-html/CHANGELOG.md +++ b/packages/escape-html/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.9.0 (2024-10-03) + ## 3.8.0 (2024-09-19) ## 3.7.0 (2024-09-05) diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 8f68366006ce7c..2f1690a8bcef92 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.8.0", + "version": "3.9.0-prerelease", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 725872f8bf1011..7425062a1cf10e 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 21.2.0 (2024-10-03) + ## 21.1.0 (2024-09-19) ## 21.0.0 (2024-09-05) diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 4902acd2bcd0ae..9b90ff3580f7a1 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "21.1.0", + "version": "21.2.0-prerelease", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/fields/CHANGELOG.md b/packages/fields/CHANGELOG.md index e04ce921cdfdc4..986cbcdec80568 100644 --- a/packages/fields/CHANGELOG.md +++ b/packages/fields/CHANGELOG.md @@ -2,4 +2,6 @@ ## Unreleased +## 0.1.0 (2024-10-03) + Initial release. diff --git a/packages/fields/package.json b/packages/fields/package.json index 3da913d1ee9ae5..037f58fc2882b0 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/fields", - "version": "0.0.1", + "version": "0.1.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/CHANGELOG.md b/packages/format-library/CHANGELOG.md index 11a32094cffeab..a2a23524a7a9a5 100644 --- a/packages/format-library/CHANGELOG.md +++ b/packages/format-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/format-library/package.json b/packages/format-library/package.json index 03b1047d3fb9d8..f430142cdbbf33 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/CHANGELOG.md b/packages/hooks/CHANGELOG.md index 060e061b5c2843..962a94056fbbd2 100644 --- a/packages/hooks/CHANGELOG.md +++ b/packages/hooks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ### New Features - added new `doActionAsync` and `applyFiltersAsync` functions to run hooks in async mode ([#64204](https://github.com/WordPress/gutenberg/pull/64204)). diff --git a/packages/hooks/package.json b/packages/hooks/package.json index cf8e0a791a7471..bd537189fe1c38 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/CHANGELOG.md b/packages/html-entities/CHANGELOG.md index e49251a8653624..99da545e4e9a93 100644 --- a/packages/html-entities/CHANGELOG.md +++ b/packages/html-entities/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 7196df00a8cd6a..b7f418d5067a56 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index 928a0d6d0ef74b..613da356ace7fb 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 2e92335914271b..fdc9319331208b 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index ddf850dd116819..b1b19fdfbc0f2f 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.9.0 (2024-10-03) + ## 10.8.0 (2024-09-19) ### New Features diff --git a/packages/icons/package.json b/packages/icons/package.json index c1c1682ed6750f..cc00704636dce0 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.8.0", + "version": "10.9.0-prerelease", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/CHANGELOG.md b/packages/interactivity-router/CHANGELOG.md index 1f8e91dec05474..7878796b9004cc 100644 --- a/packages/interactivity-router/CHANGELOG.md +++ b/packages/interactivity-router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.9.0 (2024-10-03) + ## 2.8.0 (2024-09-19) ## 2.7.0 (2024-09-05) diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 8314d7b1b70d56..005524b8610fc7 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.8.0", + "version": "2.9.0-prerelease", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 42f311973709dd..d35dfa7c81ae43 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.9.0 (2024-10-03) + ## 6.8.0 (2024-09-19) ### Enhancements diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 5b6ce90fc5184e..5539375122e0e4 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.8.0", + "version": "6.9.0-prerelease", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index f5e0d5e74762af..f590aeed5b6ccc 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.9.0 (2024-10-03) + ## 6.8.0 (2024-09-19) ## 6.7.0 (2024-09-05) diff --git a/packages/interface/package.json b/packages/interface/package.json index 932c3fde03de4d..916a75cb286da9 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "6.8.0", + "version": "6.9.0-prerelease", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/CHANGELOG.md b/packages/is-shallow-equal/CHANGELOG.md index ef424aaeebf220..44bbf38076085a 100644 --- a/packages/is-shallow-equal/CHANGELOG.md +++ b/packages/is-shallow-equal/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 462b97bda17214..f6ddb0f153f6a7 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/CHANGELOG.md b/packages/jest-console/CHANGELOG.md index 2ed1dc24299f45..440d41bcc2dc36 100644 --- a/packages/jest-console/CHANGELOG.md +++ b/packages/jest-console/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.9.0 (2024-10-03) + ## 8.8.0 (2024-09-19) ## 8.7.0 (2024-09-05) diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index d55ce881a09566..219db35b525f56 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.8.0", + "version": "8.9.0-prerelease", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md index a3ecded683cd17..137c03dce8c7ad 100644 --- a/packages/jest-preset-default/CHANGELOG.md +++ b/packages/jest-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 12.9.0 (2024-10-03) + ## 12.8.0 (2024-09-19) ## 12.7.0 (2024-09-05) diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 72be60b0f3376c..a4846a401b446c 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.8.0", + "version": "12.9.0-prerelease", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/CHANGELOG.md b/packages/jest-puppeteer-axe/CHANGELOG.md index 3e61ea09412d63..7e5503f13eddf1 100644 --- a/packages/jest-puppeteer-axe/CHANGELOG.md +++ b/packages/jest-puppeteer-axe/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.9.0 (2024-10-03) + ## 7.8.0 (2024-09-19) ## 7.7.0 (2024-09-05) diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 69fb9cfa181f44..faff90b0afc61d 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.8.0", + "version": "7.9.0-prerelease", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/CHANGELOG.md b/packages/keyboard-shortcuts/CHANGELOG.md index 356e850692af4d..2c23a099857a33 100644 --- a/packages/keyboard-shortcuts/CHANGELOG.md +++ b/packages/keyboard-shortcuts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 038e15ebc1532b..2585b02bf1c127 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/CHANGELOG.md b/packages/keycodes/CHANGELOG.md index a578adb34bd3d3..1ef044b263e1f3 100644 --- a/packages/keycodes/CHANGELOG.md +++ b/packages/keycodes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index d63d5757dcbf31..6efb197356575d 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/CHANGELOG.md b/packages/lazy-import/CHANGELOG.md index 6853a036fdaa50..c09059768e81a7 100644 --- a/packages/lazy-import/CHANGELOG.md +++ b/packages/lazy-import/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.9.0 (2024-10-03) + ## 2.8.0 (2024-09-19) ## 2.7.0 (2024-09-05) diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index 758c1b5934a955..937afab3d68ba7 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.8.0", + "version": "2.9.0-prerelease", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/CHANGELOG.md b/packages/list-reusable-blocks/CHANGELOG.md index 852f30a2999175..eb0b3a7cf6b48f 100644 --- a/packages/list-reusable-blocks/CHANGELOG.md +++ b/packages/list-reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 03c1c11af9e49f..95102c8a0c1e22 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/CHANGELOG.md b/packages/media-utils/CHANGELOG.md index a25bdf05596f86..20272be5b7d7be 100644 --- a/packages/media-utils/CHANGELOG.md +++ b/packages/media-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ### New Features diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index e90ab5a98e87d6..971dc40a8232fc 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/CHANGELOG.md b/packages/notices/CHANGELOG.md index dbff0c69b7449d..1c4f629fb2c345 100644 --- a/packages/notices/CHANGELOG.md +++ b/packages/notices/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/notices/package.json b/packages/notices/package.json index 09056f5fe6818c..fb818a061801d6 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/CHANGELOG.md b/packages/npm-package-json-lint-config/CHANGELOG.md index ecf89f4df64717..511f6e8f3b6c4e 100644 --- a/packages/npm-package-json-lint-config/CHANGELOG.md +++ b/packages/npm-package-json-lint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index 38080c1e09d834..0f33e57108b339 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/CHANGELOG.md b/packages/nux/CHANGELOG.md index 51a49b1bf9314c..19ddfd39b2156d 100644 --- a/packages/nux/CHANGELOG.md +++ b/packages/nux/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.9.0 (2024-10-03) + ## 9.8.0 (2024-09-19) ## 9.7.0 (2024-09-05) diff --git a/packages/nux/package.json b/packages/nux/package.json index 8bc5bfea622f09..816a9218ce6b65 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.8.0", + "version": "9.9.0-prerelease", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/CHANGELOG.md b/packages/patterns/CHANGELOG.md index 1579dd646228ff..e15ac90000ba4e 100644 --- a/packages/patterns/CHANGELOG.md +++ b/packages/patterns/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.9.0 (2024-10-03) + ## 2.8.0 (2024-09-19) ## 2.7.0 (2024-09-05) diff --git a/packages/patterns/package.json b/packages/patterns/package.json index e3563325f95fa7..3e2e96cd2bfa55 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.8.0", + "version": "2.9.0-prerelease", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/CHANGELOG.md b/packages/plugins/CHANGELOG.md index 18d5e1a38567dc..9b378eb71f5827 100644 --- a/packages/plugins/CHANGELOG.md +++ b/packages/plugins/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.9.0 (2024-10-03) + ## 7.8.0 (2024-09-19) ## 7.7.0 (2024-09-05) diff --git a/packages/plugins/package.json b/packages/plugins/package.json index e9e9bc0667f9a1..922cf572afd333 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.8.0", + "version": "7.9.0-prerelease", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/CHANGELOG.md b/packages/postcss-plugins-preset/CHANGELOG.md index e4441308f0fe40..f21d7016240e03 100644 --- a/packages/postcss-plugins-preset/CHANGELOG.md +++ b/packages/postcss-plugins-preset/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 67c030b3a10706..aec85f2952f116 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/CHANGELOG.md b/packages/postcss-themes/CHANGELOG.md index c7d61b14eadf18..19c2acccf0f750 100644 --- a/packages/postcss-themes/CHANGELOG.md +++ b/packages/postcss-themes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.9.0 (2024-10-03) + ## 6.8.0 (2024-09-19) ## 6.7.0 (2024-09-05) diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index 864056ee0d61e5..fedfca942c28bb 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.8.0", + "version": "6.9.0-prerelease", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/CHANGELOG.md b/packages/preferences-persistence/CHANGELOG.md index 79a755f40bfd5b..b3f4193fa0c9ee 100644 --- a/packages/preferences-persistence/CHANGELOG.md +++ b/packages/preferences-persistence/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.9.0 (2024-10-03) + ## 2.8.0 (2024-09-19) ## 2.7.0 (2024-09-05) diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index a82a883e2b5747..c88cc45540607f 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.8.0", + "version": "2.9.0-prerelease", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/CHANGELOG.md b/packages/preferences/CHANGELOG.md index 840c476e8ece81..114027eed2e228 100644 --- a/packages/preferences/CHANGELOG.md +++ b/packages/preferences/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/preferences/package.json b/packages/preferences/package.json index fbd2cc46033ee7..05feb1c96c834e 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/CHANGELOG.md b/packages/prettier-config/CHANGELOG.md index 28d178a87f980b..17b3fc88b5ccde 100644 --- a/packages/prettier-config/CHANGELOG.md +++ b/packages/prettier-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 27a72866e6126d..a20d8d93e776fa 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/CHANGELOG.md b/packages/primitives/CHANGELOG.md index f0bd389bb08b73..8c646a4dc6c5ca 100644 --- a/packages/primitives/CHANGELOG.md +++ b/packages/primitives/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 2119fc70b11d1c..9a28f05b6b2582 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/CHANGELOG.md b/packages/priority-queue/CHANGELOG.md index 1c343e2cd0e818..7254d4e3f37185 100644 --- a/packages/priority-queue/CHANGELOG.md +++ b/packages/priority-queue/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.9.0 (2024-10-03) + ## 3.8.0 (2024-09-19) ## 3.7.0 (2024-09-05) diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index a60c61528bd5ee..1104d9240cd3e7 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.8.0", + "version": "3.9.0-prerelease", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/CHANGELOG.md b/packages/private-apis/CHANGELOG.md index f7807d3667b8a8..bd13576ccbcd04 100644 --- a/packages/private-apis/CHANGELOG.md +++ b/packages/private-apis/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.9.0 (2024-10-03) + ## 1.8.0 (2024-09-19) ## 1.7.0 (2024-09-05) diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index 957eec5e34b49e..6d33d8a1c583ce 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.8.0", + "version": "1.9.0-prerelease", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/CHANGELOG.md b/packages/project-management-automation/CHANGELOG.md index 797d6e3a9cfe2d..c48bc76452a5a5 100644 --- a/packages/project-management-automation/CHANGELOG.md +++ b/packages/project-management-automation/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.9.0 (2024-10-03) + ## 2.8.0 (2024-09-19) ## 2.7.0 (2024-09-05) diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index e4e1a345f05567..bdaed741c9b331 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.8.0", + "version": "2.9.0-prerelease", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/CHANGELOG.md b/packages/react-i18n/CHANGELOG.md index cdab707f520dc1..fa1b416809ca5c 100644 --- a/packages/react-i18n/CHANGELOG.md +++ b/packages/react-i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index dd4e513e333830..c235912776ea36 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md index 5f28f282f760f8..c93a667a8faf00 100644 --- a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md +++ b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.9.0 (2024-10-03) + ## 3.8.0 (2024-09-19) ## 3.7.0 (2024-09-05) diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index 7901045e659b28..ada467c56f07f2 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.8.0", + "version": "3.9.0-prerelease", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/CHANGELOG.md b/packages/redux-routine/CHANGELOG.md index 82c3b1b4c2e92b..8154e640d3c98f 100644 --- a/packages/redux-routine/CHANGELOG.md +++ b/packages/redux-routine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 8e151e7d6bbfa3..362003cea44ff5 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/CHANGELOG.md b/packages/reusable-blocks/CHANGELOG.md index 9ea28faa2e6c9e..5e94ec24079144 100644 --- a/packages/reusable-blocks/CHANGELOG.md +++ b/packages/reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 3e5e9cfb0ca77d..5cda09658eea7a 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/CHANGELOG.md b/packages/rich-text/CHANGELOG.md index e456968e24875b..7fe0e351c6f5fe 100644 --- a/packages/rich-text/CHANGELOG.md +++ b/packages/rich-text/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.9.0 (2024-10-03) + ## 7.8.0 (2024-09-19) ## 7.7.0 (2024-09-05) diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index a7e8e4b173c154..3987bef8c8aa9f 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.8.0", + "version": "7.9.0-prerelease", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index 2d8d93373f4c5e..bd259351a87999 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.9.0 (2024-10-03) + ## 1.8.0 (2024-09-19) ## 1.7.0 (2024-09-05) diff --git a/packages/router/package.json b/packages/router/package.json index 5efc014ee221c9..9e0564538dc556 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.8.0", + "version": "1.9.0-prerelease", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index d24f9dfc7c02a4..e7b40a3c1f3463 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 30.1.0 (2024-10-03) + ## 30.0.0 (2024-09-19) diff --git a/packages/scripts/package.json b/packages/scripts/package.json index f1546a9ff7b7e1..9cbec54f67114f 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.0.0", + "version": "30.1.0-prerelease", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/CHANGELOG.md b/packages/server-side-render/CHANGELOG.md index 5acfc6a5cacae6..43de483ed7ae53 100644 --- a/packages/server-side-render/CHANGELOG.md +++ b/packages/server-side-render/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.9.0 (2024-10-03) + ## 5.8.0 (2024-09-19) ## 5.7.0 (2024-09-05) diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index 6b6be2fb7e88d5..7e9a49faf24f90 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.8.0", + "version": "5.9.0-prerelease", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/CHANGELOG.md b/packages/shortcode/CHANGELOG.md index cc11e7806f00f4..e3efee9b49779e 100644 --- a/packages/shortcode/CHANGELOG.md +++ b/packages/shortcode/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index c16f22d5023cfb..c8e721213510f1 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md index 43598ca011863e..3435553b63a713 100644 --- a/packages/style-engine/CHANGELOG.md +++ b/packages/style-engine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.9.0 (2024-10-03) + ## 2.8.0 (2024-09-19) ## 2.7.0 (2024-09-05) diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 49327c487b2322..77ba258045df32 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.8.0", + "version": "2.9.0-prerelease", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/CHANGELOG.md b/packages/stylelint-config/CHANGELOG.md index 7ba3f7fd28dd7c..ada350fe2fe577 100644 --- a/packages/stylelint-config/CHANGELOG.md +++ b/packages/stylelint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 23.1.0 (2024-10-03) + ## 23.0.0 (2024-09-19) ### Breaking Changes diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 8aa35643b3d7e7..2c02cf016b0e1c 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "23.0.0", + "version": "23.1.0-prerelease", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/CHANGELOG.md b/packages/sync/CHANGELOG.md index 4b4978c4eab1ba..00141ee08526d7 100644 --- a/packages/sync/CHANGELOG.md +++ b/packages/sync/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.9.0 (2024-10-03) + ## 1.8.0 (2024-09-19) ## 1.7.0 (2024-09-05) diff --git a/packages/sync/package.json b/packages/sync/package.json index b96133c749ad30..d9740c2e31deb1 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.8.0", + "version": "1.9.0-prerelease", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/CHANGELOG.md b/packages/token-list/CHANGELOG.md index 068047bb7f8a58..77fb52c6ddd2a2 100644 --- a/packages/token-list/CHANGELOG.md +++ b/packages/token-list/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.9.0 (2024-10-03) + ## 3.8.0 (2024-09-19) ## 3.7.0 (2024-09-05) diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 346623f3df1735..e09d5605f3d292 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.8.0", + "version": "3.9.0-prerelease", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/CHANGELOG.md b/packages/undo-manager/CHANGELOG.md index a8ad0c1d7fbf0c..7375a328e01e9d 100644 --- a/packages/undo-manager/CHANGELOG.md +++ b/packages/undo-manager/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.9.0 (2024-10-03) + ## 1.8.0 (2024-09-19) ## 1.7.0 (2024-09-05) diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 1147efbb72a59d..ba44aaaeb11c24 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.8.0", + "version": "1.9.0-prerelease", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/CHANGELOG.md b/packages/url/CHANGELOG.md index 491eaf2e7b8ad2..93be01f8540a2e 100644 --- a/packages/url/CHANGELOG.md +++ b/packages/url/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/url/package.json b/packages/url/package.json index d04b42a2e19fb4..e736189718c585 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/CHANGELOG.md b/packages/viewport/CHANGELOG.md index 58850208f348c5..c80489b94eac6a 100644 --- a/packages/viewport/CHANGELOG.md +++ b/packages/viewport/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.9.0 (2024-10-03) + ## 6.8.0 (2024-09-19) ## 6.7.0 (2024-09-05) diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 1a5d1a1c7f5b44..837eb3f36f7bf5 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.8.0", + "version": "6.9.0-prerelease", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/CHANGELOG.md b/packages/warning/CHANGELOG.md index 248b318d7b576c..dc56abe7208cb2 100644 --- a/packages/warning/CHANGELOG.md +++ b/packages/warning/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.9.0 (2024-10-03) + ## 3.8.0 (2024-09-19) ## 3.7.0 (2024-09-05) diff --git a/packages/warning/package.json b/packages/warning/package.json index ded853e825cb0c..b01b0f0d6f6030 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.8.0", + "version": "3.9.0-prerelease", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/CHANGELOG.md b/packages/widgets/CHANGELOG.md index cf3d8c8eac0c2d..aaa2e56d0c625c 100644 --- a/packages/widgets/CHANGELOG.md +++ b/packages/widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/widgets/package.json b/packages/widgets/package.json index ccc2995650d81c..6dcf29d2c34eef 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/CHANGELOG.md b/packages/wordcount/CHANGELOG.md index 79a5a75b3ef833..9eeefc104183df 100644 --- a/packages/wordcount/CHANGELOG.md +++ b/packages/wordcount/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-10-03) + ## 4.8.0 (2024-09-19) ## 4.7.0 (2024-09-05) diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index c8b610c9ccffe9..779306ee5b140d 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 4d309d5a570ce4489447eee24e0e00a447a80b50 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 3 Oct 2024 14:06:41 +0000 Subject: [PATCH 1070/1908] chore(release): publish - @wordpress/a11y@4.9.0 - @wordpress/annotations@3.9.0 - @wordpress/api-fetch@7.9.0 - @wordpress/autop@4.9.0 - @wordpress/babel-plugin-import-jsx-pragma@5.9.0 - @wordpress/babel-plugin-makepot@6.9.0 - @wordpress/babel-preset-default@8.9.0 - @wordpress/base-styles@5.9.0 - @wordpress/blob@4.9.0 - @wordpress/block-directory@5.9.0 - @wordpress/block-editor@14.4.0 - @wordpress/block-library@9.9.0 - @wordpress/block-serialization-default-parser@5.9.0 - @wordpress/block-serialization-spec-parser@5.9.0 - @wordpress/blocks@13.9.0 - @wordpress/browserslist-config@6.9.0 - @wordpress/commands@1.9.0 - @wordpress/components@28.9.0 - @wordpress/compose@7.9.0 - @wordpress/core-commands@1.9.0 - @wordpress/core-data@7.9.0 - @wordpress/create-block@4.52.0 - @wordpress/create-block-interactive-template@2.9.0 - @wordpress/create-block-tutorial-template@4.9.0 - @wordpress/customize-widgets@5.9.0 - @wordpress/data@10.9.0 - @wordpress/data-controls@4.9.0 - @wordpress/dataviews@4.5.0 - @wordpress/date@5.9.0 - @wordpress/dependency-extraction-webpack-plugin@6.9.0 - @wordpress/deprecated@4.9.0 - @wordpress/docgen@2.9.0 - @wordpress/dom@4.9.0 - @wordpress/dom-ready@4.9.0 - @wordpress/e2e-test-utils@11.9.0 - @wordpress/e2e-test-utils-playwright@1.9.0 - @wordpress/e2e-tests@8.9.0 - @wordpress/edit-post@8.9.0 - @wordpress/edit-site@6.9.0 - @wordpress/edit-widgets@6.9.0 - @wordpress/editor@14.9.0 - @wordpress/element@6.9.0 - @wordpress/env@10.9.0 - @wordpress/escape-html@3.9.0 - @wordpress/eslint-plugin@21.2.0 - @wordpress/fields@0.1.0 - @wordpress/format-library@5.9.0 - @wordpress/hooks@4.9.0 - @wordpress/html-entities@4.9.0 - @wordpress/i18n@5.9.0 - @wordpress/icons@10.9.0 - @wordpress/interactivity@6.9.0 - @wordpress/interactivity-router@2.9.0 - @wordpress/interface@6.9.0 - @wordpress/is-shallow-equal@5.9.0 - @wordpress/jest-console@8.9.0 - @wordpress/jest-preset-default@12.9.0 - @wordpress/jest-puppeteer-axe@7.9.0 - @wordpress/keyboard-shortcuts@5.9.0 - @wordpress/keycodes@4.9.0 - @wordpress/lazy-import@2.9.0 - @wordpress/list-reusable-blocks@5.9.0 - @wordpress/media-utils@5.9.0 - @wordpress/notices@5.9.0 - @wordpress/npm-package-json-lint-config@5.9.0 - @wordpress/nux@9.9.0 - @wordpress/patterns@2.9.0 - @wordpress/plugins@7.9.0 - @wordpress/postcss-plugins-preset@5.9.0 - @wordpress/postcss-themes@6.9.0 - @wordpress/preferences@4.9.0 - @wordpress/preferences-persistence@2.9.0 - @wordpress/prettier-config@4.9.0 - @wordpress/primitives@4.9.0 - @wordpress/priority-queue@3.9.0 - @wordpress/private-apis@1.9.0 - @wordpress/project-management-automation@2.9.0 - @wordpress/react-i18n@4.9.0 - @wordpress/readable-js-assets-webpack-plugin@3.9.0 - @wordpress/redux-routine@5.9.0 - @wordpress/reusable-blocks@5.9.0 - @wordpress/rich-text@7.9.0 - @wordpress/router@1.9.0 - @wordpress/scripts@30.1.0 - @wordpress/server-side-render@5.9.0 - @wordpress/shortcode@4.9.0 - @wordpress/style-engine@2.9.0 - @wordpress/stylelint-config@23.1.0 - @wordpress/sync@1.9.0 - @wordpress/token-list@3.9.0 - @wordpress/undo-manager@1.9.0 - @wordpress/url@4.9.0 - @wordpress/viewport@6.9.0 - @wordpress/warning@3.9.0 - @wordpress/widgets@4.9.0 - @wordpress/wordcount@4.9.0 --- package-lock.json | 190 +++++++++--------- packages/a11y/package.json | 2 +- packages/annotations/package.json | 2 +- packages/api-fetch/package.json | 2 +- packages/autop/package.json | 2 +- .../package.json | 2 +- packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/package.json | 2 +- packages/base-styles/package.json | 2 +- packages/blob/package.json | 2 +- packages/block-directory/package.json | 2 +- packages/block-editor/package.json | 2 +- packages/block-library/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/blocks/package.json | 2 +- packages/browserslist-config/package.json | 2 +- packages/commands/package.json | 2 +- packages/components/package.json | 2 +- packages/compose/package.json | 2 +- packages/core-commands/package.json | 2 +- packages/core-data/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/create-block/package.json | 2 +- packages/customize-widgets/package.json | 2 +- packages/data-controls/package.json | 2 +- packages/data/package.json | 2 +- packages/dataviews/package.json | 2 +- packages/date/package.json | 2 +- .../package.json | 2 +- packages/deprecated/package.json | 2 +- packages/docgen/package.json | 2 +- packages/dom-ready/package.json | 2 +- packages/dom/package.json | 2 +- .../e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/package.json | 2 +- packages/edit-post/package.json | 2 +- packages/edit-site/package.json | 2 +- packages/edit-widgets/package.json | 2 +- packages/editor/package.json | 2 +- packages/element/package.json | 2 +- packages/env/package.json | 2 +- packages/escape-html/package.json | 2 +- packages/eslint-plugin/package.json | 2 +- packages/fields/package.json | 2 +- packages/format-library/package.json | 2 +- packages/hooks/package.json | 2 +- packages/html-entities/package.json | 2 +- packages/i18n/package.json | 2 +- packages/icons/package.json | 2 +- packages/interactivity-router/package.json | 2 +- packages/interactivity/package.json | 2 +- packages/interface/package.json | 2 +- packages/is-shallow-equal/package.json | 2 +- packages/jest-console/package.json | 2 +- packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/package.json | 2 +- packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/package.json | 2 +- packages/notices/package.json | 2 +- .../npm-package-json-lint-config/package.json | 2 +- packages/nux/package.json | 2 +- packages/patterns/package.json | 2 +- packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/package.json | 2 +- packages/preferences/package.json | 2 +- packages/prettier-config/package.json | 2 +- packages/primitives/package.json | 2 +- packages/priority-queue/package.json | 2 +- packages/private-apis/package.json | 2 +- .../package.json | 2 +- packages/react-i18n/package.json | 2 +- .../package.json | 2 +- packages/redux-routine/package.json | 2 +- packages/reusable-blocks/package.json | 2 +- packages/rich-text/package.json | 2 +- packages/router/package.json | 2 +- packages/scripts/package.json | 2 +- packages/server-side-render/package.json | 2 +- packages/shortcode/package.json | 2 +- packages/style-engine/package.json | 2 +- packages/stylelint-config/package.json | 2 +- packages/sync/package.json | 2 +- packages/token-list/package.json | 2 +- packages/undo-manager/package.json | 2 +- packages/url/package.json | 2 +- packages/viewport/package.json | 2 +- packages/warning/package.json | 2 +- packages/widgets/package.json | 2 +- packages/wordcount/package.json | 2 +- 97 files changed, 191 insertions(+), 191 deletions(-) diff --git a/package-lock.json b/package-lock.json index c800d47891c180..48ffe440202c36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52564,7 +52564,7 @@ }, "packages/a11y": { "name": "@wordpress/a11y", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52578,7 +52578,7 @@ }, "packages/annotations": { "name": "@wordpress/annotations", - "version": "3.8.0", + "version": "3.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52606,7 +52606,7 @@ }, "packages/api-fetch": { "name": "@wordpress/api-fetch", - "version": "7.8.0", + "version": "7.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52620,7 +52620,7 @@ }, "packages/autop": { "name": "@wordpress/autop", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52632,7 +52632,7 @@ }, "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.8.0", + "version": "5.9.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52645,7 +52645,7 @@ }, "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", - "version": "6.8.0", + "version": "6.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52663,7 +52663,7 @@ }, "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", - "version": "8.8.0", + "version": "8.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52686,7 +52686,7 @@ }, "packages/base-styles": { "name": "@wordpress/base-styles", - "version": "5.8.0", + "version": "5.9.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52696,7 +52696,7 @@ }, "packages/blob": { "name": "@wordpress/blob", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52708,7 +52708,7 @@ }, "packages/block-directory": { "name": "@wordpress/block-directory", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52744,7 +52744,7 @@ }, "packages/block-editor": { "name": "@wordpress/block-editor", - "version": "14.3.0", + "version": "14.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52843,7 +52843,7 @@ }, "packages/block-library": { "name": "@wordpress/block-library", - "version": "9.8.0", + "version": "9.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52909,7 +52909,7 @@ }, "packages/block-serialization-default-parser": { "name": "@wordpress/block-serialization-default-parser", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -52921,7 +52921,7 @@ }, "packages/block-serialization-spec-parser": { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "pegjs": "^0.10.0", @@ -52934,7 +52934,7 @@ }, "packages/blocks": { "name": "@wordpress/blocks", - "version": "13.8.0", + "version": "13.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -52988,7 +52988,7 @@ }, "packages/browserslist-config": { "name": "@wordpress/browserslist-config", - "version": "6.8.0", + "version": "6.9.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52998,7 +52998,7 @@ }, "packages/commands": { "name": "@wordpress/commands", - "version": "1.8.0", + "version": "1.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53171,7 +53171,7 @@ }, "packages/components": { "name": "@wordpress/components", - "version": "28.8.0", + "version": "28.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -53291,7 +53291,7 @@ }, "packages/compose": { "name": "@wordpress/compose", - "version": "7.8.0", + "version": "7.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53328,7 +53328,7 @@ }, "packages/core-commands": { "name": "@wordpress/core-commands", - "version": "1.8.0", + "version": "1.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53357,7 +53357,7 @@ }, "packages/core-data": { "name": "@wordpress/core-data", - "version": "7.8.0", + "version": "7.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53402,7 +53402,7 @@ }, "packages/create-block": { "name": "@wordpress/create-block", - "version": "4.51.0", + "version": "4.52.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53430,7 +53430,7 @@ }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", - "version": "4.8.0", + "version": "4.9.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -53440,7 +53440,7 @@ }, "packages/customize-widgets": { "name": "@wordpress/customize-widgets", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53478,7 +53478,7 @@ }, "packages/data": { "name": "@wordpress/data", - "version": "10.8.0", + "version": "10.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53507,7 +53507,7 @@ }, "packages/data-controls": { "name": "@wordpress/data-controls", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53525,7 +53525,7 @@ }, "packages/dataviews": { "name": "@wordpress/dataviews", - "version": "4.4.0", + "version": "4.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -53582,7 +53582,7 @@ }, "packages/date": { "name": "@wordpress/date", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53597,7 +53597,7 @@ }, "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.8.0", + "version": "6.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53613,7 +53613,7 @@ }, "packages/deprecated": { "name": "@wordpress/deprecated", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53626,7 +53626,7 @@ }, "packages/docgen": { "name": "@wordpress/docgen", - "version": "2.8.0", + "version": "2.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53648,7 +53648,7 @@ }, "packages/dom": { "name": "@wordpress/dom", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53661,7 +53661,7 @@ }, "packages/dom-ready": { "name": "@wordpress/dom-ready", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53673,7 +53673,7 @@ }, "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", - "version": "11.8.0", + "version": "11.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53696,7 +53696,7 @@ }, "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.8.0", + "version": "1.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53724,7 +53724,7 @@ }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", - "version": "8.8.0", + "version": "8.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53764,7 +53764,7 @@ }, "packages/edit-post": { "name": "@wordpress/edit-post", - "version": "8.8.0", + "version": "8.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53811,7 +53811,7 @@ }, "packages/edit-site": { "name": "@wordpress/edit-site", - "version": "6.8.0", + "version": "6.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53873,7 +53873,7 @@ }, "packages/edit-widgets": { "name": "@wordpress/edit-widgets", - "version": "6.8.0", + "version": "6.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53916,7 +53916,7 @@ }, "packages/editor": { "name": "@wordpress/editor", - "version": "14.8.0", + "version": "14.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53978,7 +53978,7 @@ }, "packages/element": { "name": "@wordpress/element", - "version": "6.8.0", + "version": "6.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53997,7 +53997,7 @@ }, "packages/env": { "name": "@wordpress/env", - "version": "10.8.0", + "version": "10.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54139,7 +54139,7 @@ }, "packages/escape-html": { "name": "@wordpress/escape-html", - "version": "3.8.0", + "version": "3.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54151,7 +54151,7 @@ }, "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", - "version": "21.1.0", + "version": "21.2.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54194,7 +54194,7 @@ }, "packages/fields": { "name": "@wordpress/fields", - "version": "0.0.1", + "version": "0.1.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54230,7 +54230,7 @@ }, "packages/format-library": { "name": "@wordpress/format-library", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54258,7 +54258,7 @@ }, "packages/hooks": { "name": "@wordpress/hooks", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54270,7 +54270,7 @@ }, "packages/html-entities": { "name": "@wordpress/html-entities", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54282,7 +54282,7 @@ }, "packages/i18n": { "name": "@wordpress/i18n", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54302,7 +54302,7 @@ }, "packages/icons": { "name": "@wordpress/icons", - "version": "10.8.0", + "version": "10.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54316,7 +54316,7 @@ }, "packages/interactivity": { "name": "@wordpress/interactivity", - "version": "6.8.0", + "version": "6.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@preact/signals": "^1.2.2", @@ -54329,7 +54329,7 @@ }, "packages/interactivity-router": { "name": "@wordpress/interactivity-router", - "version": "2.8.0", + "version": "2.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/a11y": "file:../a11y", @@ -54366,7 +54366,7 @@ }, "packages/interface": { "name": "@wordpress/interface", - "version": "6.8.0", + "version": "6.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54395,7 +54395,7 @@ }, "packages/is-shallow-equal": { "name": "@wordpress/is-shallow-equal", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54407,7 +54407,7 @@ }, "packages/jest-console": { "name": "@wordpress/jest-console", - "version": "8.8.0", + "version": "8.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54424,7 +54424,7 @@ }, "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", - "version": "12.8.0", + "version": "12.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54442,7 +54442,7 @@ }, "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.8.0", + "version": "7.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54465,7 +54465,7 @@ }, "packages/keyboard-shortcuts": { "name": "@wordpress/keyboard-shortcuts", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54483,7 +54483,7 @@ }, "packages/keycodes": { "name": "@wordpress/keycodes", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54496,7 +54496,7 @@ }, "packages/lazy-import": { "name": "@wordpress/lazy-import", - "version": "2.8.0", + "version": "2.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54511,7 +54511,7 @@ }, "packages/list-reusable-blocks": { "name": "@wordpress/list-reusable-blocks", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54534,7 +54534,7 @@ }, "packages/media-utils": { "name": "@wordpress/media-utils", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54550,7 +54550,7 @@ }, "packages/notices": { "name": "@wordpress/notices", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54567,7 +54567,7 @@ }, "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.8.0", + "version": "5.9.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54580,7 +54580,7 @@ }, "packages/nux": { "name": "@wordpress/nux", - "version": "9.8.0", + "version": "9.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54603,7 +54603,7 @@ }, "packages/patterns": { "name": "@wordpress/patterns", - "version": "2.8.0", + "version": "2.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54633,7 +54633,7 @@ }, "packages/plugins": { "name": "@wordpress/plugins", - "version": "7.8.0", + "version": "7.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54656,7 +54656,7 @@ }, "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", - "version": "5.8.0", + "version": "5.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54673,7 +54673,7 @@ }, "packages/postcss-themes": { "name": "@wordpress/postcss-themes", - "version": "6.8.0", + "version": "6.9.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54686,7 +54686,7 @@ }, "packages/preferences": { "name": "@wordpress/preferences", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54712,7 +54712,7 @@ }, "packages/preferences-persistence": { "name": "@wordpress/preferences-persistence", - "version": "2.8.0", + "version": "2.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54725,7 +54725,7 @@ }, "packages/prettier-config": { "name": "@wordpress/prettier-config", - "version": "4.8.0", + "version": "4.9.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54738,7 +54738,7 @@ }, "packages/primitives": { "name": "@wordpress/primitives", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54755,7 +54755,7 @@ }, "packages/priority-queue": { "name": "@wordpress/priority-queue", - "version": "3.8.0", + "version": "3.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54768,7 +54768,7 @@ }, "packages/private-apis": { "name": "@wordpress/private-apis", - "version": "1.8.0", + "version": "1.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54780,7 +54780,7 @@ }, "packages/project-management-automation": { "name": "@wordpress/project-management-automation", - "version": "2.8.0", + "version": "2.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54810,7 +54810,7 @@ }, "packages/react-i18n": { "name": "@wordpress/react-i18n", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54966,7 +54966,7 @@ }, "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.8.0", + "version": "3.9.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54979,7 +54979,7 @@ }, "packages/redux-routine": { "name": "@wordpress/redux-routine", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55024,7 +55024,7 @@ }, "packages/reusable-blocks": { "name": "@wordpress/reusable-blocks", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55051,7 +55051,7 @@ }, "packages/rich-text": { "name": "@wordpress/rich-text", - "version": "7.8.0", + "version": "7.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55075,7 +55075,7 @@ }, "packages/router": { "name": "@wordpress/router", - "version": "1.8.0", + "version": "1.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55094,7 +55094,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "30.0.0", + "version": "30.1.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55549,7 +55549,7 @@ }, "packages/server-side-render": { "name": "@wordpress/server-side-render", - "version": "5.8.0", + "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55575,7 +55575,7 @@ }, "packages/shortcode": { "name": "@wordpress/shortcode", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55588,7 +55588,7 @@ }, "packages/style-engine": { "name": "@wordpress/style-engine", - "version": "2.8.0", + "version": "2.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55601,7 +55601,7 @@ }, "packages/stylelint-config": { "name": "@wordpress/stylelint-config", - "version": "23.0.0", + "version": "23.1.0", "dev": true, "license": "MIT", "dependencies": { @@ -55719,7 +55719,7 @@ }, "packages/sync": { "name": "@wordpress/sync", - "version": "1.8.0", + "version": "1.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55740,7 +55740,7 @@ }, "packages/token-list": { "name": "@wordpress/token-list", - "version": "3.8.0", + "version": "3.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -55752,7 +55752,7 @@ }, "packages/undo-manager": { "name": "@wordpress/undo-manager", - "version": "1.8.0", + "version": "1.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55765,7 +55765,7 @@ }, "packages/url": { "name": "@wordpress/url", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55778,7 +55778,7 @@ }, "packages/viewport": { "name": "@wordpress/viewport", - "version": "6.8.0", + "version": "6.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55796,7 +55796,7 @@ }, "packages/warning": { "name": "@wordpress/warning", - "version": "3.8.0", + "version": "3.9.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55805,7 +55805,7 @@ }, "packages/widgets": { "name": "@wordpress/widgets", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55833,7 +55833,7 @@ }, "packages/wordcount": { "name": "@wordpress/wordcount", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" diff --git a/packages/a11y/package.json b/packages/a11y/package.json index d9b6c88bc783f6..e3868dca8b6baf 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 9b6c0af4195487..ab482712954252 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.9.0-prerelease", + "version": "3.9.0", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 20410c226aa970..3ad4425db40309 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.9.0-prerelease", + "version": "7.9.0", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/package.json b/packages/autop/package.json index 30594cc8cd4500..9320cfc26213aa 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index 453ba0586b3bb7..47ecbcccd5eb2f 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index 1d519b806e2946..d04a20a7164594 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.9.0-prerelease", + "version": "6.9.0", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 15cd827171f474..f98ac198e22730 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.9.0-prerelease", + "version": "8.9.0", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index 0af745e39db4db..b1da65dde47970 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/package.json b/packages/blob/package.json index 067b7382a5513b..96d35105fc8246 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index fbeeddafe875f0..b1f0aaf2a599ad 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 4773dda51f54b8..1c6c313345d723 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.4.0-prerelease", + "version": "14.4.0", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/package.json b/packages/block-library/package.json index b6a1154e9c8300..ac25e1cdb815ab 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.9.0-prerelease", + "version": "9.9.0", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 93e3a5a38049d2..5dabca2d129452 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 87b5c051177c3f..38469f4d295298 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 7594840fb58d5b..644e428cb686b4 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.9.0-prerelease", + "version": "13.9.0", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 24adbde9c53e85..0c4d314203483b 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.9.0-prerelease", + "version": "6.9.0", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/package.json b/packages/commands/package.json index 70465b15f18b29..6fd5fdf9971e46 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.9.0-prerelease", + "version": "1.9.0", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/package.json b/packages/components/package.json index 78af25cdff54a4..0a2b7b0d0431be 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.9.0-prerelease", + "version": "28.9.0", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/package.json b/packages/compose/package.json index a10486fade88e9..83ffd1d2b364f1 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.9.0-prerelease", + "version": "7.9.0", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 575ef291eea45e..1eed9f5348145a 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.9.0-prerelease", + "version": "1.9.0", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 124f4bb6421fad..4037bd577c3233 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.9.0-prerelease", + "version": "7.9.0", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index 2ff5f35ab3dce1..e8b38dab906cca 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.9.0-prerelease", + "version": "2.9.0", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index 11b94a63b8889e..9eceb95dda83c5 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 4b6cc0d4cb3867..7c31cb57687f00 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.52.0-prerelease", + "version": "4.52.0", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 59cafbdb7edecf..7231de9ac1b18f 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 6c549e200d603b..cf4aab46c6daee 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/package.json b/packages/data/package.json index 15de6f05e7dabe..7ba4efc4592254 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.9.0-prerelease", + "version": "10.9.0", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index ebd313da5ab253..d5b465a3f7b2de 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.5.0-prerelease", + "version": "4.5.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/package.json b/packages/date/package.json index f3f3682ca64b09..3023e0cba30e51 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index b3e628dfc0acbf..2eb71b69864232 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.9.0-prerelease", + "version": "6.9.0", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 3732620632486c..2c7d69a11ea921 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 530ec87af0b8b7..2829246f9e4309 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.9.0-prerelease", + "version": "2.9.0", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 6715a44205c7b6..56913124da79f3 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/package.json b/packages/dom/package.json index 2c794abc0a2c71..c80beed815ea90 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index ac0c9d8d4de3f0..ebec29be94c89d 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.9.0-prerelease", + "version": "1.9.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index 72c1589a399e51..a91938f54dd52c 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.9.0-prerelease", + "version": "11.9.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 7ff65a2ee56cb6..714542e115c823 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.9.0-prerelease", + "version": "8.9.0", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 6269b80d482a23..dd2eaa5115bafb 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.9.0-prerelease", + "version": "8.9.0", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 11a501377dcede..bd86d74c686801 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.9.0-prerelease", + "version": "6.9.0", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 8f920ecefa596d..e9d0f18df460a6 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.9.0-prerelease", + "version": "6.9.0", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/package.json b/packages/editor/package.json index 15356fc279c62b..8781b0b992d94f 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.9.0-prerelease", + "version": "14.9.0", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/package.json b/packages/element/package.json index afa90afa11539e..dc96c5a83b182a 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.9.0-prerelease", + "version": "6.9.0", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/package.json b/packages/env/package.json index 9ccf40ed5400a4..ef0a9ca1832013 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.9.0-prerelease", + "version": "10.9.0", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 2f1690a8bcef92..b45f4c236f41eb 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.9.0-prerelease", + "version": "3.9.0", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 9b90ff3580f7a1..6638473b94b184 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "21.2.0-prerelease", + "version": "21.2.0", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/fields/package.json b/packages/fields/package.json index 037f58fc2882b0..d0dd29138c5e5f 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/fields", - "version": "0.1.0-prerelease", + "version": "0.1.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/package.json b/packages/format-library/package.json index f430142cdbbf33..fa2f45682a2b7c 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/package.json b/packages/hooks/package.json index bd537189fe1c38..841dcd33afb7fa 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index b7f418d5067a56..fe0c1314b1a387 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/package.json b/packages/i18n/package.json index fdc9319331208b..7dc84901cafea1 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/package.json b/packages/icons/package.json index cc00704636dce0..39395b2b76cb0b 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.9.0-prerelease", + "version": "10.9.0", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 005524b8610fc7..529d7a2ad1f32f 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.9.0-prerelease", + "version": "2.9.0", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 5539375122e0e4..417ec8a2d337ba 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.9.0-prerelease", + "version": "6.9.0", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/package.json b/packages/interface/package.json index 916a75cb286da9..cb55a37da29b54 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "6.9.0-prerelease", + "version": "6.9.0", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index f6ddb0f153f6a7..bd28c31fc750b2 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 219db35b525f56..a35f92896950fc 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.9.0-prerelease", + "version": "8.9.0", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index a4846a401b446c..1a64cc47294f31 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.9.0-prerelease", + "version": "12.9.0", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index faff90b0afc61d..71674e12e0df94 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.9.0-prerelease", + "version": "7.9.0", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 2585b02bf1c127..bf71b807329f77 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 6efb197356575d..cfff9c69844232 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index 937afab3d68ba7..8343dcfeed00be 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.9.0-prerelease", + "version": "2.9.0", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 95102c8a0c1e22..4971c35c947eb2 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 971dc40a8232fc..25bdb46a352bbb 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/package.json b/packages/notices/package.json index fb818a061801d6..b6712776778e13 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index 0f33e57108b339..abde4d2490cc9b 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/package.json b/packages/nux/package.json index 816a9218ce6b65..f633695d5490a2 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.9.0-prerelease", + "version": "9.9.0", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 3e2e96cd2bfa55..b9654af383f723 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.9.0-prerelease", + "version": "2.9.0", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 922cf572afd333..7772c7361cd5bc 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.9.0-prerelease", + "version": "7.9.0", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index aec85f2952f116..8e1db61b9668c2 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index fedfca942c28bb..e7752b3aaa3526 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.9.0-prerelease", + "version": "6.9.0", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index c88cc45540607f..1872840d8a8cc9 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.9.0-prerelease", + "version": "2.9.0", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/package.json b/packages/preferences/package.json index 05feb1c96c834e..722212c3d0d48b 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index a20d8d93e776fa..3f77e6bb125bb5 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 9a28f05b6b2582..4bf8849c0dba4a 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 1104d9240cd3e7..991d5a207c780c 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.9.0-prerelease", + "version": "3.9.0", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index 6d33d8a1c583ce..ada754f9405259 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.9.0-prerelease", + "version": "1.9.0", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index bdaed741c9b331..67ad670628efcd 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.9.0-prerelease", + "version": "2.9.0", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index c235912776ea36..acf4656d65496b 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index ada467c56f07f2..8f90b19356c4ee 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.9.0-prerelease", + "version": "3.9.0", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 362003cea44ff5..80857aa15908d0 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 5cda09658eea7a..8936c97e247683 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 3987bef8c8aa9f..f9ecb72cfb6d0e 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.9.0-prerelease", + "version": "7.9.0", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/package.json b/packages/router/package.json index 9e0564538dc556..7686f90a27c495 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.9.0-prerelease", + "version": "1.9.0", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 9cbec54f67114f..29fef4864a991d 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.1.0-prerelease", + "version": "30.1.0", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index 7e9a49faf24f90..d7dd1311a2f107 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.9.0-prerelease", + "version": "5.9.0", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index c8e721213510f1..b0e2f5eb34181d 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 77ba258045df32..80babe6bcd4ca5 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.9.0-prerelease", + "version": "2.9.0", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 2c02cf016b0e1c..3cb8b481dd4201 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "23.1.0-prerelease", + "version": "23.1.0", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/package.json b/packages/sync/package.json index d9740c2e31deb1..27f618f3345584 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.9.0-prerelease", + "version": "1.9.0", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/package.json b/packages/token-list/package.json index e09d5605f3d292..69c59f5ff582fb 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.9.0-prerelease", + "version": "3.9.0", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index ba44aaaeb11c24..c08951947ee377 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.9.0-prerelease", + "version": "1.9.0", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/package.json b/packages/url/package.json index e736189718c585..9fa2c416619cf2 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 837eb3f36f7bf5..cc990e6732ba86 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.9.0-prerelease", + "version": "6.9.0", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/package.json b/packages/warning/package.json index b01b0f0d6f6030..7499ced5cb962f 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.9.0-prerelease", + "version": "3.9.0", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 6dcf29d2c34eef..bf73872934da55 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index 779306ee5b140d..b813249f1f7d75 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From e37f4cc27e4d403927f5e544787df09005089e8e Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 3 Oct 2024 14:41:28 +0000 Subject: [PATCH 1071/1908] Update Changelog for 19.4.0-rc.1 --- changelog.txt | 337 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 337 insertions(+) diff --git a/changelog.txt b/changelog.txt index b802a88a14202c..06d92230737fc5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,342 @@ == Changelog == += 19.4.0-rc.1 = + + +## Changelog + +### Enhancements + +#### Block Library +- Added keywords to query loop block. ([65515](https://github.com/WordPress/gutenberg/pull/65515)) +- Added: DropZone when sitelogo is present. ([65596](https://github.com/WordPress/gutenberg/pull/65596)) +- Avatar: Add block example. ([65509](https://github.com/WordPress/gutenberg/pull/65509)) +- Buttons: add box-sizing:Border-box rule. ([65716](https://github.com/WordPress/gutenberg/pull/65716)) +- Comment Author Name: Add block example. ([65558](https://github.com/WordPress/gutenberg/pull/65558)) +- Comment Content: Add block example. ([65559](https://github.com/WordPress/gutenberg/pull/65559)) +- Comment Date: Add block example. ([65632](https://github.com/WordPress/gutenberg/pull/65632)) +- Comment Edit/Reply Links: Add block examples. ([65601](https://github.com/WordPress/gutenberg/pull/65601)) +- Comment Pagination: Add previous and next link block examples. ([65633](https://github.com/WordPress/gutenberg/pull/65633)) +- Comments Pagination Numbers: Add block example. ([65635](https://github.com/WordPress/gutenberg/pull/65635)) +- Comments Title: Add block example. ([65557](https://github.com/WordPress/gutenberg/pull/65557)) +- File block: Allow content only editing. ([65787](https://github.com/WordPress/gutenberg/pull/65787)) +- Navigation block: Use `apply_block_hooks_to_content()`. ([65703](https://github.com/WordPress/gutenberg/pull/65703)) +- Post Navigation Link: Add block examples. ([65552](https://github.com/WordPress/gutenberg/pull/65552)) +- Query No Results: Add block example. ([65555](https://github.com/WordPress/gutenberg/pull/65555)) +- Query Pagination Numbers: Add block example. ([65636](https://github.com/WordPress/gutenberg/pull/65636)) +- Query Pagination: Add block example. ([65556](https://github.com/WordPress/gutenberg/pull/65556)) +- Query Title: Add block example. ([65554](https://github.com/WordPress/gutenberg/pull/65554)) +- Revert: Time To Read: Add block example. ([65510](https://github.com/WordPress/gutenberg/pull/65510)) +- Table of Contents: Try maintaining block example attributes. ([65549](https://github.com/WordPress/gutenberg/pull/65549)) +- Term Description: Add block example. ([65553](https://github.com/WordPress/gutenberg/pull/65553)) +- Time To Read: Add block example. ([65512](https://github.com/WordPress/gutenberg/pull/65512)) + +#### Components +- Light branding for the reference site. ([65764](https://github.com/WordPress/gutenberg/pull/65764)) +- BorderControl: Use `__next40pxDefaultSize` prop for Reset button. ([65682](https://github.com/WordPress/gutenberg/pull/65682)) +- Composite: Always await initial render setup in unit tests. ([65823](https://github.com/WordPress/gutenberg/pull/65823)) +- DatePicker: Use compact button size. ([65653](https://github.com/WordPress/gutenberg/pull/65653)) +- Guide: Update finish button to use the new default size. ([65680](https://github.com/WordPress/gutenberg/pull/65680)) +- Navigator: Add support for exit animation. ([64777](https://github.com/WordPress/gutenberg/pull/64777)) +- Remove `useEvent` from components package. ([65388](https://github.com/WordPress/gutenberg/pull/65388)) +- Simplify MenuGroup component styles. ([65561](https://github.com/WordPress/gutenberg/pull/65561)) +- Storybook: Allow for case-agnostic filtering of icons. ([65780](https://github.com/WordPress/gutenberg/pull/65780)) +- ToggleGroupControl: Improve animation. ([65175](https://github.com/WordPress/gutenberg/pull/65175)) +- Tabs: Tweak sizing and overflow behavior of TabList. ([64371](https://github.com/WordPress/gutenberg/pull/64371)) + +#### Zoom Out +- Add prompt to zoom out separator. ([65392](https://github.com/WordPress/gutenberg/pull/65392)) +- Make sections `contentOnly` in Zoom Out. ([65396](https://github.com/WordPress/gutenberg/pull/65396)) +- Move the toggle button to before the device preview dropdown. ([65446](https://github.com/WordPress/gutenberg/pull/65446)) +- Only show zoom out inserters on block selection. ([65759](https://github.com/WordPress/gutenberg/pull/65759)) + +#### Block Editor +- Hide block transforms in contentOnly mode for non-content blocks. ([65394](https://github.com/WordPress/gutenberg/pull/65394)) +- Inserter: Always show the list of all patterns in the inserter. ([65611](https://github.com/WordPress/gutenberg/pull/65611)) +- MediaPlaceholder: Use InputControl in URL popover. ([65656](https://github.com/WordPress/gutenberg/pull/65656)) +- Use proper named `File` when uploading external images. ([65693](https://github.com/WordPress/gutenberg/pull/65693)) + +#### Data Views +- DataForm - Add combined fields support. ([65399](https://github.com/WordPress/gutenberg/pull/65399)) +- Filter UI: Remove popover max height. ([65835](https://github.com/WordPress/gutenberg/pull/65835)) +- Dataviews configuration dropdown: Remove style overrides. ([65373](https://github.com/WordPress/gutenberg/pull/65373)) + +#### Post Editor +- Edit Post: Remove unnecessary effect in `InitPatternModal`. ([65734](https://github.com/WordPress/gutenberg/pull/65734)) +- Editor: Consistent external media pre-publish image/button sizes. ([65668](https://github.com/WordPress/gutenberg/pull/65668)) + +#### Global Styles +- Editor Canvas: Tweak close button. ([65694](https://github.com/WordPress/gutenberg/pull/65694)) +- Style book: Create static categories. ([65430](https://github.com/WordPress/gutenberg/pull/65430)) + +#### Edit Mode +- Update tools menus with Write / Design order. ([65721](https://github.com/WordPress/gutenberg/pull/65721)) + +#### Select Mode +- Select Mode: Updates to the block toolbar. ([65485](https://github.com/WordPress/gutenberg/pull/65485)) +- Select Mode: Use the content-only behavior in select mode. ([65204](https://github.com/WordPress/gutenberg/pull/65204)) + +#### Icons +- Adds envelope icon. ([65638](https://github.com/WordPress/gutenberg/pull/65638)) + +#### Site Editor +- Global Styles: Remove navigator screen overrides. ([65522](https://github.com/WordPress/gutenberg/pull/65522)) +- Command Palette: "Add new page" within the site editor creates new page in site editor. ([65476](https://github.com/WordPress/gutenberg/pull/65476)) +- Update elevation in the site editor. ([65410](https://github.com/WordPress/gutenberg/pull/65410)) + +#### Block bindings +- Connected blocks, add backdrop-color. ([65233](https://github.com/WordPress/gutenberg/pull/65233)) + +#### Extensibility +- Stabilize the PreSavePost and SavePost filters. ([64198](https://github.com/WordPress/gutenberg/pull/64198)) + +#### Base Styles +- Base styles: Add type tokens. ([65418](https://github.com/WordPress/gutenberg/pull/65418)) + +#### Tools +- Composer: Allow composer/installers 2.x. ([65356](https://github.com/WordPress/gutenberg/pull/65356)) + +#### Block hooks +- Hooks: Add support for async filters and actions. ([64204](https://github.com/WordPress/gutenberg/pull/64204)) + +### New APIs + +- Revert "Make `wordpress/fields` a private package". ([65477](https://github.com/WordPress/gutenberg/pull/65477)) +- Stabilise role attribute property. ([65484](https://github.com/WordPress/gutenberg/pull/65484)) + +#### Block bindings +- Open the stable editor APIs. ([65713](https://github.com/WordPress/gutenberg/pull/65713)) + +#### Components +- Navigator: Stabilize and export APIs. ([64613](https://github.com/WordPress/gutenberg/pull/64613)) + +### Bug Fixes + +#### Components +- Block Editor: Validate options for the 'HeadingLevelDropdown' component. ([65425](https://github.com/WordPress/gutenberg/pull/65425)) +- Composite: Fix legacy implementation passing store prop. ([65821](https://github.com/WordPress/gutenberg/pull/65821)) +- Composite: Make items tabbable if active element gets removed. ([65720](https://github.com/WordPress/gutenberg/pull/65720)) +- Navigator: Fix isInitial logic. ([65527](https://github.com/WordPress/gutenberg/pull/65527)) +- Restore accidentally removed entries in changelog (components package). ([65804](https://github.com/WordPress/gutenberg/pull/65804)) +- useToolsPanel: Calculate derived state in reducer to prevent too many renders. ([65564](https://github.com/WordPress/gutenberg/pull/65564)) +- useToolsPanel: Calculate menuItems in layout effect to avoid painting intermediate state. ([65494](https://github.com/WordPress/gutenberg/pull/65494)) + +#### Zoom Out +- Fix focus loss when deleting selected block in zoom out mode. ([65761](https://github.com/WordPress/gutenberg/pull/65761)) +- Handle zoom out when changing device preview. ([65444](https://github.com/WordPress/gutenberg/pull/65444)) +- Hide Zoom Out Inserters when dragging into canvas. ([65789](https://github.com/WordPress/gutenberg/pull/65789)) +- Makes spacing consistent in zoom out vertical toolbar. ([63994](https://github.com/WordPress/gutenberg/pull/63994)) +- Remove one occurrence of the verb Toggle from Zoom out control. ([65609](https://github.com/WordPress/gutenberg/pull/65609)) +- Reset zoom out level when device type is changed. ([65652](https://github.com/WordPress/gutenberg/pull/65652)) +- Resize cover block only in normal mode. ([65731](https://github.com/WordPress/gutenberg/pull/65731)) + +#### Block Editor +- Fix unable to remove empty blocks on merge. ([65262](https://github.com/WordPress/gutenberg/pull/65262)) +- Inserter: Fix Block visibility manager. ([65700](https://github.com/WordPress/gutenberg/pull/65700)) +- Link autocompleter: Decode post title HTML entities. ([65589](https://github.com/WordPress/gutenberg/pull/65589)) +- Openverse: Prevent multiple insertions during upload. ([65719](https://github.com/WordPress/gutenberg/pull/65719)) +- Paste Handler: Try to fix pasting text with formatting. ([63779](https://github.com/WordPress/gutenberg/pull/63779)) +- Remove user-select:Text. ([65662](https://github.com/WordPress/gutenberg/pull/65662)) +- Editor: Remove edit template menu item from block settings menu in blocks outside template. ([65560](https://github.com/WordPress/gutenberg/pull/65560)) +- Top Toolbar: Show document bar when no block is selected even if block tools are expanded. ([65839](https://github.com/WordPress/gutenberg/pull/65839)) +- Revert "Allow multi-select on iOS Safari/touch devices". ([65414](https://github.com/WordPress/gutenberg/pull/65414)) + +#### Global Styles +- Avoid errors when a fontSize preset is not available. ([65791](https://github.com/WordPress/gutenberg/pull/65791)) +- Fix: Shadow/Font size preset panel crashes the editor. ([65765](https://github.com/WordPress/gutenberg/pull/65765)) +- Revert "Font Library: Group fonts by source (#63211)". ([65590](https://github.com/WordPress/gutenberg/pull/65590)) +- Tweak entity save panel button. ([65695](https://github.com/WordPress/gutenberg/pull/65695)) + +#### Block bindings +- Fix editing protected custom fields in block bindings. ([65658](https://github.com/WordPress/gutenberg/pull/65658)) +- Fix showing bindings field values in theme templates. ([65639](https://github.com/WordPress/gutenberg/pull/65639)) +- Only pass context included in `usesContext` from rich text component. ([65618](https://github.com/WordPress/gutenberg/pull/65618)) +- Use `registry` instead of `select` in `canUserEditValue`. ([65659](https://github.com/WordPress/gutenberg/pull/65659)) + +#### Block Library +- Categories block: Escape label. ([65540](https://github.com/WordPress/gutenberg/pull/65540)) +- Search block: Reset size correctly when clearing unit control. ([65468](https://github.com/WordPress/gutenberg/pull/65468)) +- Social Links: Fix block appender size. ([65769](https://github.com/WordPress/gutenberg/pull/65769)) + +#### Site Editor +- Fix: Makes edit mode selector persistent in top toolbar mode. ([65511](https://github.com/WordPress/gutenberg/pull/65511)) +- Global styles: Do not navigate twice to home screen when opening the sidebar. ([65523](https://github.com/WordPress/gutenberg/pull/65523)) +- Make resizable frame compatible with RTL languages. ([65545](https://github.com/WordPress/gutenberg/pull/65545)) +- Command Palette: Fix "Add new page" command for hybrid theme. ([65534](https://github.com/WordPress/gutenberg/pull/65534)) +- Export `useResizeObserver` React Native version directly. ([65588](https://github.com/WordPress/gutenberg/pull/65588)) +- Fix `useResizeObserver` bugs. ([65389](https://github.com/WordPress/gutenberg/pull/65389)) +- Fix aria-checked attribute not set for plugin settings buttons in Options dropdown. ([65667](https://github.com/WordPress/gutenberg/pull/65667)) +- Revert "useToolsPanel: Calculate menuItems in layout effect to avoid painting intermediate state". ([65533](https://github.com/WordPress/gutenberg/pull/65533)) + +#### Focus Mode +- Limit zoom out toggle to specific post types. ([65732](https://github.com/WordPress/gutenberg/pull/65732)) + +#### List View +- Fix miscolored icons. ([65707](https://github.com/WordPress/gutenberg/pull/65707)) + +#### Media +- Fix output buffering for cross-origin isolation. ([65701](https://github.com/WordPress/gutenberg/pull/65701)) + +#### Block Directory +- Fix downloadable block item alignment. ([65677](https://github.com/WordPress/gutenberg/pull/65677)) + +#### Typography +- Remove additional Typeset screen and surface typesets in the typography panel. ([65579](https://github.com/WordPress/gutenberg/pull/65579)) + +#### Widgets Editor +- Fixed the focus cutoff of the editor buttons in the widgets editor. ([65395](https://github.com/WordPress/gutenberg/pull/65395)) + +#### Post Editor +- Omit meta boxes on “design” type posts. ([64990](https://github.com/WordPress/gutenberg/pull/64990)) + +#### Data Views +- Fix grid layout padding on small screens. ([64878](https://github.com/WordPress/gutenberg/pull/64878)) + +#### Build Tools +- Babel preset: Add missing pkg files. ([65481](https://github.com/WordPress/gutenberg/pull/65481)) +- Temp disable test for Classic Block Media issue. ([65793](https://github.com/WordPress/gutenberg/pull/65793)) + +#### Select Mode +- Select Mode: Blocks outside the main sections root should be disabled. ([65518](https://github.com/WordPress/gutenberg/pull/65518)) +- Select Mode: Prevent the inbetween inserter from triggering within sections. ([65529](https://github.com/WordPress/gutenberg/pull/65529)) + +### Accessibility + +#### Post Editor +- Make the Settings panel toggle button show its keyboard shortcut in its tooltip. ([65322](https://github.com/WordPress/gutenberg/pull/65322)) +- Resizable Editor: Make the editor resizable with arrow keys. ([65546](https://github.com/WordPress/gutenberg/pull/65546)) + +#### Components +- ToggleGroupControl: Fix arrow key navigation in RTL. ([65735](https://github.com/WordPress/gutenberg/pull/65735)) + +#### Zoom Out +- Don't show tooltip in zoom out toggle button when showIconLabels is true. ([65573](https://github.com/WordPress/gutenberg/pull/65573)) + +#### Block Library +- Improve the Query Loop block display settings labels. ([65524](https://github.com/WordPress/gutenberg/pull/65524)) + +#### Block Editor +- Updates LayoutTypeSwitcher to use ToggleGroupControl. ([65498](https://github.com/WordPress/gutenberg/pull/65498)) + +#### Code Quality +- A11y: Move script module HTML printing to 6.7 compat. ([65620](https://github.com/WordPress/gutenberg/pull/65620)) +- Update to use a11y script module package in Core. ([65539](https://github.com/WordPress/gutenberg/pull/65539)) + +#### Site Editor +- Update icon in home button. ([65497](https://github.com/WordPress/gutenberg/pull/65497)) + +### Performance + +#### Block Library +- Script Modules: Centralize (re)registration. ([65460](https://github.com/WordPress/gutenberg/pull/65460)) + +#### Block Editor +- Remove editorMode from blockProps. ([65326](https://github.com/WordPress/gutenberg/pull/65326)) +- Move insertionPoint state to block-editor store/rename existing insertionPoint to insertionCue. ([65098](https://github.com/WordPress/gutenberg/pull/65098)) + + +### Documentation + +- Block Bindings: Add `@since` tag in bindings apis JSDocs. ([65796](https://github.com/WordPress/gutenberg/pull/65796)) +- Block Editor: Fix README for FontFamilyControl component. ([65660](https://github.com/WordPress/gutenberg/pull/65660)) +- Composite: Add "With Tooltip" storybook example. ([65817](https://github.com/WordPress/gutenberg/pull/65817)) +- DataViews documentation: Add high-level graph explaining DataViews and data sources interaction. ([65457](https://github.com/WordPress/gutenberg/pull/65457)) +- Docs/interactivity api router package readme. ([62062](https://github.com/WordPress/gutenberg/pull/62062)) +- Docs: Remove PHPDoc for non-existing parameter. ([65640](https://github.com/WordPress/gutenberg/pull/65640)) +- Navigator: Fix README heading hierarchy. ([65763](https://github.com/WordPress/gutenberg/pull/65763)) +- Packages documentation: Minor typo corrections. ([65664](https://github.com/WordPress/gutenberg/pull/65664)) +- Plugin: Fix small typo in readme.txt file. ([65634](https://github.com/WordPress/gutenberg/pull/65634)) +- RichText: Fix JSDoc block typos. ([65607](https://github.com/WordPress/gutenberg/pull/65607)) +- SelectControl: Add story for `prefix` slot. ([65730](https://github.com/WordPress/gutenberg/pull/65730)) +- Update JSDoc block for RichText package to-html-string. ([65688](https://github.com/WordPress/gutenberg/pull/65688)) +- Update block-filters.md. ([64959](https://github.com/WordPress/gutenberg/pull/64959)) +- iAPI: Refactor types and add a "Core Concepts - Using TypeScript" guide. ([64577](https://github.com/WordPress/gutenberg/pull/64577)) + +### Code Quality + +#### Components +- BorderBoxControl: Promote to stable. ([65586](https://github.com/WordPress/gutenberg/pull/65586)) +- BorderControl: Promote to stable. ([65475](https://github.com/WordPress/gutenberg/pull/65475)) +- BoxControl: Promote to stable. ([65469](https://github.com/WordPress/gutenberg/pull/65469)) +- Cleanup unused `ToggleGroupControl` configuration values. ([65456](https://github.com/WordPress/gutenberg/pull/65456)) +- Fix `useInstanceId` hook references. ([65733](https://github.com/WordPress/gutenberg/pull/65733)) +- Navigator: Internal refactor in preparation for stabilization. ([65671](https://github.com/WordPress/gutenberg/pull/65671)) +- Navigator: Mark experimental exports as deprecated. ([65802](https://github.com/WordPress/gutenberg/pull/65802)) +- SearchControl: Fix rest props mutation. ([65740](https://github.com/WordPress/gutenberg/pull/65740)) +- `ToggleGroupControl`: Clean up animation logic. ([65808](https://github.com/WordPress/gutenberg/pull/65808)) + +#### Block Editor +- Button: Add `__next40pxDefaultSize` in block-editor 6. ([65742](https://github.com/WordPress/gutenberg/pull/65742)) +- Decouple "zoom/scaling the canvas" from zoom out mode (without mode rename). ([65482](https://github.com/WordPress/gutenberg/pull/65482)) +- Don't memoize 'getContentLockingParent' and 'getParentSectionBlock' selectors. ([65649](https://github.com/WordPress/gutenberg/pull/65649)) +- Inserter: Update how we compute the actual insertion point for blocks. ([65490](https://github.com/WordPress/gutenberg/pull/65490)) +- LinkControl: Fix unneeded `props` prop. ([65650](https://github.com/WordPress/gutenberg/pull/65650)) +- Navigator: Use stable export instead of experimental export. ([65753](https://github.com/WordPress/gutenberg/pull/65753)) +- Button: Add `__next40pxDefaultSize` in dataviews, reusable-blocks, etc. ([65715](https://github.com/WordPress/gutenberg/pull/65715)) +- Fix: Button Replace remaining 40px default size violations [Block Directory]. ([65467](https://github.com/WordPress/gutenberg/pull/65467)) +- Fix: Button Replace remaining 40px default size violations [Block Editor 2]. ([65308](https://github.com/WordPress/gutenberg/pull/65308)) +- Fix: Button Replace remaining 40px default size violations [Block Editor 3]. ([65225](https://github.com/WordPress/gutenberg/pull/65225)) +- Fix: Button Replace remaining 40px default size violations [Block Editor 5]. ([65361](https://github.com/WordPress/gutenberg/pull/65361)) +- Fix: Button: Replace remaining 40px default size violation [Edit Site 1]. ([65226](https://github.com/WordPress/gutenberg/pull/65226)) +- Fix: Button: Replace remaining 40px default size violation [Edit Site 3]. ([65309](https://github.com/WordPress/gutenberg/pull/65309)) + +#### Block bindings +- Only pass `usesContext` properties to editor APIs. ([65661](https://github.com/WordPress/gutenberg/pull/65661)) +- Refactor passing select and dispatch instead of full Registry. ([65710](https://github.com/WordPress/gutenberg/pull/65710)) +- Unify logic in `getPostMetaFields` function. ([65462](https://github.com/WordPress/gutenberg/pull/65462)) + +#### Post Editor +- Customize widgets, edit post: Refactor Button to new sizes. ([65807](https://github.com/WordPress/gutenberg/pull/65807)) +- Header: Remove unused property `isZoomedOutView` in `useSelect()`. ([65628](https://github.com/WordPress/gutenberg/pull/65628)) + +#### Block Library +- Blocks: Don't memoize 'hasContentRoleAttribute' selector. ([65617](https://github.com/WordPress/gutenberg/pull/65617)) +- Blocks: Update '__experimentalHasContentRoleAttribute' deprecation. ([65616](https://github.com/WordPress/gutenberg/pull/65616)) + +#### Global Styles +- Global style revisions: Remove unnecessary `goTo` navigation call. ([65810](https://github.com/WordPress/gutenberg/pull/65810)) + +#### Site Editor +- Edit Site: Fix `useLink` prop mutation. ([65739](https://github.com/WordPress/gutenberg/pull/65739)) + +#### Data Views +- Migrate store/actions from editor package to fields package. ([65289](https://github.com/WordPress/gutenberg/pull/65289)) + + +### Tools + +#### Testing +- Block Bindings: Refactor end-to-end tests. ([65526](https://github.com/WordPress/gutenberg/pull/65526)) +- GH Actions: Run the tests against PHP 8.3. ([65357](https://github.com/WordPress/gutenberg/pull/65357)) +- Revert "Temp disable test for Classic Block Media issue.". ([65809](https://github.com/WordPress/gutenberg/pull/65809)) + +#### Build Tooling +- Composer: Prevent a lock file from being created. ([65359](https://github.com/WordPress/gutenberg/pull/65359)) +- Composer: Update minimum required PHPUnit Polyfills. ([65355](https://github.com/WordPress/gutenberg/pull/65355)) +- PHP unit tests: Remove WP_RUN_CORE_TESTS const. ([65631](https://github.com/WordPress/gutenberg/pull/65631)) +- DEWP: Check for magic comments before minification. ([65582](https://github.com/WordPress/gutenberg/pull/65582)) +- DEWP: Handle cyclical module dependencies. ([65291](https://github.com/WordPress/gutenberg/pull/65291)) +- Label enforcer: Add `Gutenberg plugin` to the list of single required labels. ([65253](https://github.com/WordPress/gutenberg/pull/65253)) + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @auareyou: Light branding for the reference site. ([65764](https://github.com/WordPress/gutenberg/pull/65764)) +- @crisbusquets: Adds envelope icon. ([65638](https://github.com/WordPress/gutenberg/pull/65638)) +- @davy440: Update block-filters.md. ([64959](https://github.com/WordPress/gutenberg/pull/64959)) +- @dhruvang21: Fix: Button Replace remaining 40px default size violations [Block Editor 2]. ([65308](https://github.com/WordPress/gutenberg/pull/65308)) +- @PARTHVATALIYA: Fix: Button Replace remaining 40px default size violations [Block Editor 5]. ([65361](https://github.com/WordPress/gutenberg/pull/65361)) +- @spadeshoe: Updates LayoutTypeSwitcher to use ToggleGroupControl. ([65498](https://github.com/WordPress/gutenberg/pull/65498)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @afercia @amitraj2203 @anomiex @auareyou @carolinan @cbravobernal @ciampo @crisbusquets @DaniGuardiola @davy440 @dhruvang21 @djcowan @draganescu @ellatrix @getdave @gigitux @hbhalodia @jameskoster @jasmussen @jeryj @jffng @jrfnl @jsnajdr @juanmaguitar @keoshi @kevin940726 @louwie17 @luisherranz @Mamaduka @manzoorwanijk @matiasbenedetto @michalczaplinski @mirka @mtias @noisysocks @oandregal @ockham @PARTHVATALIYA @peterwilsoncc @philwp @priethor @ramonjd @SantosGuillamot @shail-mehta @sirreal @Soean @spadeshoe @stokesman @swissspidy @t-hamano @talldan @tyxla @vcanales @vipul0425 @youknowriad + + = 19.3.0 = ## Changelog From 6e0b843a68e24c7df1863a4c26db0d8f3ec3be38 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Fri, 4 Oct 2024 01:52:32 +0900 Subject: [PATCH 1072/1908] Button: Move to stricter lint rule for 40px size adherence (#65840) * Fix last remaining instance * Button: Move to stricter lint rule * Tweak wording to account for `size` variants Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .eslintrc.js | 11 ++--------- .../src/components/post-template/classic-theme.js | 3 +-- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 2e92b495691873..211ddd9bc35860 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -322,6 +322,7 @@ module.exports = { 'BorderBoxControl', 'BorderControl', 'BoxControl', + 'Button', 'ComboboxControl', 'CustomSelectControl', 'DimensionControl', @@ -343,7 +344,7 @@ module.exports = { selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"][value.expression.value!=false])):not(:has(JSXAttribute[name.name="size"][value.value!="default"]))`, message: componentName + - ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', + ' should have the `__next40pxDefaultSize` prop when using the default size.', } ) ), { // Falsy `__next40pxDefaultSize` without a `render` prop. @@ -352,14 +353,6 @@ module.exports = { message: 'FormFileUpload should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', }, - // Temporary rules until all existing components have the `__next40pxDefaultSize` prop. - ...[ 'Button' ].map( ( componentName ) => ( { - // Not strict. Allows pre-existing __next40pxDefaultSize={ false } usage until they are all manually updated. - selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"])):not(:has(JSXAttribute[name.name="size"]))`, - message: - componentName + - ' should have the `__next40pxDefaultSize` prop to opt-in to the new default size.', - } ) ), ], }, }, diff --git a/packages/editor/src/components/post-template/classic-theme.js b/packages/editor/src/components/post-template/classic-theme.js index 8127a18909f5cc..4a65a9b4c75636 100644 --- a/packages/editor/src/components/post-template/classic-theme.js +++ b/packages/editor/src/components/post-template/classic-theme.js @@ -177,8 +177,7 @@ function PostTemplateDropdownContent( { onClose } ) { { canEdit && onNavigateToEntityRecord && ( <p> <Button - // TODO: Switch to `true` (40px size) if possible - __next40pxDefaultSize={ false } + __next40pxDefaultSize variant="link" onClick={ () => { onNavigateToEntityRecord( { From f4402db7da4f569f09bda39109778f295263975a Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Thu, 3 Oct 2024 12:11:53 -0500 Subject: [PATCH 1073/1908] Focus first section root block if no selected block and tabbing to zoom out canvas (#65843) --- .../components/writing-flow/use-tab-nav.js | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/writing-flow/use-tab-nav.js b/packages/block-editor/src/components/writing-flow/use-tab-nav.js index 3788c7021fd664..216e7b6e04ad57 100644 --- a/packages/block-editor/src/components/writing-flow/use-tab-nav.js +++ b/packages/block-editor/src/components/writing-flow/use-tab-nav.js @@ -19,10 +19,17 @@ export default function useTabNav() { const focusCaptureBeforeRef = useRef(); const focusCaptureAfterRef = useRef(); - const { hasMultiSelection, getSelectedBlockClientId, getBlockCount } = - useSelect( blockEditorStore ); + const { + hasMultiSelection, + getSelectedBlockClientId, + getBlockCount, + getBlockOrder, + getLastFocus, + getSectionRootClientId, + isZoomOut, + __unstableGetEditorMode, + } = unlock( useSelect( blockEditorStore ) ); const { setLastFocus } = unlock( useDispatch( blockEditorStore ) ); - const { getLastFocus } = unlock( useSelect( blockEditorStore ) ); // Reference that holds the a flag for enabling or disabling // capturing on the focus capture elements. @@ -45,6 +52,24 @@ export default function useTabNav() { ) .focus(); } + } + // In "compose" mode without a selected ID, we want to place focus on the section root when tabbing to the canvas. + else if ( __unstableGetEditorMode() === 'zoom-out' && isZoomOut() ) { + const sectionRootClientId = getSectionRootClientId(); + const sectionBlocks = getBlockOrder( sectionRootClientId ); + + // If we have section within the section root, focus the first one. + if ( sectionBlocks.length ) { + container.current + .querySelector( `[data-block="${ sectionBlocks[ 0 ] }"]` ) + .focus(); + } + // If we don't have any section blocks, focus the section root. + else { + container.current + .querySelector( `[data-block="${ sectionRootClientId }"]` ) + .focus(); + } } else { const canvasElement = container.current.ownerDocument === event.target.ownerDocument @@ -61,7 +86,6 @@ export default function useTabNav() { const next = isBefore ? tabbables[ 0 ] : tabbables[ tabbables.length - 1 ]; - next.focus(); } } From 46fdb6719d771e8886ac321a504b5bac21ee4b36 Mon Sep 17 00:00:00 2001 From: Utsav Patel <75293077+up1512001@users.noreply.github.com> Date: Thu, 3 Oct 2024 23:12:50 +0530 Subject: [PATCH 1074/1908] Post Terms: Fix fatal error when 'get_the_term_list' returns 'WP_Error' (#65848) Co-authored-by: up1512001 <up1512001@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: david-binda <davidbinda@git.wordpress.org> --- packages/block-library/src/post-terms/index.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/post-terms/index.php b/packages/block-library/src/post-terms/index.php index 69d7b04b096b53..60ffdcedf3268f 100644 --- a/packages/block-library/src/post-terms/index.php +++ b/packages/block-library/src/post-terms/index.php @@ -51,13 +51,19 @@ function render_block_core_post_terms( $attributes, $content, $block ) { $suffix = '<span class="wp-block-post-terms__suffix">' . $attributes['suffix'] . '</span>' . $suffix; } - return get_the_term_list( + $post_terms = get_the_term_list( $block->context['postId'], $attributes['term'], wp_kses_post( $prefix ), '<span class="wp-block-post-terms__separator">' . esc_html( $separator ) . '</span>', wp_kses_post( $suffix ) ); + + if ( is_wp_error( $post_terms ) ) { + return ''; + } + + return $post_terms; } /** From 078a5820f5c29c8d68d9b9152990fae2018b857c Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Fri, 4 Oct 2024 00:49:46 +0100 Subject: [PATCH 1075/1908] Type the router package (#65854) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- packages/router/CHANGELOG.md | 4 +++ packages/router/package.json | 1 + .../router/src/{history.js => history.ts} | 26 ++++++++++++------- packages/router/src/{index.js => index.ts} | 0 .../src/{lock-unlock.js => lock-unlock.ts} | 0 .../src/{private-apis.js => private-apis.ts} | 0 packages/router/src/{router.js => router.tsx} | 7 ++--- packages/router/tsconfig.json | 17 ++++++++++++ tsconfig.json | 1 + 9 files changed, 44 insertions(+), 12 deletions(-) rename packages/router/src/{history.js => history.ts} (75%) rename packages/router/src/{index.js => index.ts} (100%) rename packages/router/src/{lock-unlock.js => lock-unlock.ts} (100%) rename packages/router/src/{private-apis.js => private-apis.ts} (100%) rename packages/router/src/{router.js => router.tsx} (71%) create mode 100644 packages/router/tsconfig.json diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index bd259351a87999..0ce856ea20e88b 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Rewrite the package in typescript ([#65854](https://github.com/WordPress/gutenberg/pull/65854)). + ## 1.9.0 (2024-10-03) ## 1.8.0 (2024-09-19) diff --git a/packages/router/package.json b/packages/router/package.json index 7686f90a27c495..eadc360d8e0cbf 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "dependencies": { "@babel/runtime": "^7.16.0", "@wordpress/element": "file:../element", diff --git a/packages/router/src/history.js b/packages/router/src/history.ts similarity index 75% rename from packages/router/src/history.js rename to packages/router/src/history.ts index 3a04745923a817..e046522a751894 100644 --- a/packages/router/src/history.js +++ b/packages/router/src/history.ts @@ -1,13 +1,17 @@ /** * External dependencies */ -import { createBrowserHistory } from 'history'; +import { createBrowserHistory, type BrowserHistory } from 'history'; /** * WordPress dependencies */ import { buildQueryString } from '@wordpress/url'; +export interface EnhancedHistory extends BrowserHistory { + getLocationWithParams: () => Location; +} + const history = createBrowserHistory(); const originalHistoryPush = history.push; @@ -16,7 +20,7 @@ const originalHistoryReplace = history.replace; // Preserve the `wp_theme_preview` query parameter when navigating // around the Site Editor. // TODO: move this hack out of the router into Site Editor code. -function preserveThemePreview( params ) { +function preserveThemePreview( params: Record< string, any > ) { if ( params.hasOwnProperty( 'wp_theme_preview' ) ) { return params; } @@ -28,12 +32,15 @@ function preserveThemePreview( params ) { return { ...params, wp_theme_preview: currentThemePreview }; } -function push( params, state ) { +function push( params: Record< string, any >, state: Record< string, any > ) { const search = buildQueryString( preserveThemePreview( params ) ); return originalHistoryPush.call( history, { search }, state ); } -function replace( params, state ) { +function replace( + params: Record< string, any >, + state: Record< string, any > +) { const search = buildQueryString( preserveThemePreview( params ) ); return originalHistoryReplace.call( history, { search }, state ); } @@ -54,8 +61,9 @@ function getLocationWithParams() { return locationWithParams; } -history.push = push; -history.replace = replace; -history.getLocationWithParams = getLocationWithParams; - -export default history; +export default { + ...history, + push, + replace, + getLocationWithParams, +}; diff --git a/packages/router/src/index.js b/packages/router/src/index.ts similarity index 100% rename from packages/router/src/index.js rename to packages/router/src/index.ts diff --git a/packages/router/src/lock-unlock.js b/packages/router/src/lock-unlock.ts similarity index 100% rename from packages/router/src/lock-unlock.js rename to packages/router/src/lock-unlock.ts diff --git a/packages/router/src/private-apis.js b/packages/router/src/private-apis.ts similarity index 100% rename from packages/router/src/private-apis.js rename to packages/router/src/private-apis.ts diff --git a/packages/router/src/router.js b/packages/router/src/router.tsx similarity index 71% rename from packages/router/src/router.js rename to packages/router/src/router.tsx index 55807175a5bdd9..9a1d01aa5f8d88 100644 --- a/packages/router/src/router.js +++ b/packages/router/src/router.tsx @@ -11,9 +11,10 @@ import { * Internal dependencies */ import history from './history'; +import type { EnhancedHistory } from './history'; -const RoutesContext = createContext(); -const HistoryContext = createContext(); +const RoutesContext = createContext< Location | null >( null ); +const HistoryContext = createContext< EnhancedHistory >( history ); export function useLocation() { return useContext( RoutesContext ); @@ -23,7 +24,7 @@ export function useHistory() { return useContext( HistoryContext ); } -export function RouterProvider( { children } ) { +export function RouterProvider( { children }: { children: React.ReactNode } ) { const location = useSyncExternalStore( history.listen, history.getLocationWithParams, diff --git a/packages/router/tsconfig.json b/packages/router/tsconfig.json new file mode 100644 index 00000000000000..e4945eef8bac0c --- /dev/null +++ b/packages/router/tsconfig.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types", + "types": [ "gutenberg-env" ], + "allowJs": false, + "checkJs": false + }, + "references": [ + { "path": "../element" }, + { "path": "../private-apis" }, + { "path": "../url" } + ], + "include": [ "src/**/*" ] +} diff --git a/tsconfig.json b/tsconfig.json index 8821ef4404e3b5..4dafc0acc958c6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -49,6 +49,7 @@ { "path": "packages/redux-routine" }, { "path": "packages/report-flaky-tests" }, { "path": "packages/rich-text" }, + { "path": "packages/router" }, { "path": "packages/style-engine" }, { "path": "packages/sync" }, { "path": "packages/token-list" }, From 75c2147b96086d4d502b652a4a49bdc372bde33f Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 4 Oct 2024 09:19:54 +0400 Subject: [PATCH 1076/1908] Post Terms: Remove unnecessary 'get_the_terms' call (#65867) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: aristath <aristath@git.wordpress.org> --- packages/block-library/src/post-terms/index.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/block-library/src/post-terms/index.php b/packages/block-library/src/post-terms/index.php index 60ffdcedf3268f..3e7a05f10117e4 100644 --- a/packages/block-library/src/post-terms/index.php +++ b/packages/block-library/src/post-terms/index.php @@ -24,11 +24,6 @@ function render_block_core_post_terms( $attributes, $content, $block ) { return ''; } - $post_terms = get_the_terms( $block->context['postId'], $attributes['term'] ); - if ( is_wp_error( $post_terms ) || empty( $post_terms ) ) { - return ''; - } - $classes = array( 'taxonomy-' . $attributes['term'] ); if ( isset( $attributes['textAlign'] ) ) { $classes[] = 'has-text-align-' . $attributes['textAlign']; @@ -59,7 +54,7 @@ function render_block_core_post_terms( $attributes, $content, $block ) { wp_kses_post( $suffix ) ); - if ( is_wp_error( $post_terms ) ) { + if ( is_wp_error( $post_terms ) || empty( $post_terms ) ) { return ''; } From 18fdd2537564195d1492e16836d0a621283ad9b1 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Fri, 4 Oct 2024 10:19:57 +0100 Subject: [PATCH 1077/1908] Fix components coding standards in Zoom Out Toolbar (#65858) See https://github.com/WordPress/gutenberg/pull/63994#issuecomment-2391109041 Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/block-editor/src/components/block-tools/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index fe9da021b31823..bfb8b958f01ca6 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -203,7 +203,7 @@ } // Make the spacing consistent between controls. - .components-button { + .zoom-out-toolbar-button { height: $button-size-next-default-40px; } } From 3e37c60aa6beb2336003d0db4ce839b577250b3c Mon Sep 17 00:00:00 2001 From: Troy Chaplin <15524465+troychaplin@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:33:48 -0400 Subject: [PATCH 1078/1908] add: usage examples in core editor docs (#63768) * add: usage examples in core editor docs for editPost, getEditedPostAttribute, getCurrentPostType * change: updated examples to use i18n * fix: formatting * change: moved docs to correct location Co-authored-by: troychaplin <areziaal@git.wordpress.org> Co-authored-by: ryanwelcher <welcher@git.wordpress.org> --- .../reference-guides/data/data-core-editor.md | 51 +++++++++++++++++++ packages/editor/src/store/actions.js | 23 +++++++++ packages/editor/src/store/selectors.js | 21 ++++++++ 3 files changed, 95 insertions(+) diff --git a/docs/reference-guides/data/data-core-editor.md b/docs/reference-guides/data/data-core-editor.md index a4c1a59f0c4231..ac3413e694877b 100644 --- a/docs/reference-guides/data/data-core-editor.md +++ b/docs/reference-guides/data/data-core-editor.md @@ -248,6 +248,12 @@ _Returns_ Returns the post type of the post currently being edited. +_Usage_ + +```js +const currentPostType = wp.data.select( 'core/editor' ).getCurrentPostType(); +``` + _Parameters_ - _state_ `Object`: Global application state. @@ -284,6 +290,24 @@ _Returns_ Returns a single attribute of the post being edited, preferring the unsaved edit if one exists, but falling back to the attribute for the last known saved state of the post. +_Usage_ + +```js +// Get specific media size based on the featured media ID +// Note: change sizes?.large for any registered size +const getFeaturedMediaUrl = useSelect( ( select ) => { + const getFeaturedMediaId = + select( 'core/editor' ).getEditedPostAttribute( 'featured_media' ); + const getMedia = select( 'core' ).getMedia( getFeaturedMediaId ); + + return ( + getMedia?.media_details?.sizes?.large?.source_url || + getMedia?.source_url || + '' + ); +}, [] ); +``` + _Parameters_ - _state_ `Object`: Global application state. @@ -1154,11 +1178,38 @@ Disables the publish sidebar. Returns an action object used in signalling that attributes of the post have been edited. +_Usage_ + +```js +// Update the post title +wp.data.dispatch( 'core/editor' ).editPost( { title: `${ newTitle }` } ); +``` + +```js +// Get specific media size based on the featured media ID +// Note: change sizes?.large for any registered size +const getFeaturedMediaUrl = useSelect( ( select ) => { + const getFeaturedMediaId = + select( 'core/editor' ).getEditedPostAttribute( 'featured_media' ); + const getMedia = select( 'core' ).getMedia( getFeaturedMediaId ); + + return ( + getMedia?.media_details?.sizes?.large?.source_url || + getMedia?.source_url || + '' + ); +}, [] ); +``` + _Parameters_ - _edits_ `Object`: Post attributes to edit. - _options_ `Object`: Options for the edit. +_Returns_ + +- `Object`: Action object + ### enablePublishSidebar Enable the publish sidebar. diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index fa720e1fc7d347..f8a18fc86e5376 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -159,6 +159,29 @@ export function setEditedPost( postType, postId ) { * * @param {Object} edits Post attributes to edit. * @param {Object} options Options for the edit. + * + * @example + * ```js + * // Update the post title + * wp.data.dispatch( 'core/editor' ).editPost( { title: `${ newTitle }` } ); + * ``` + * + * @example + *```js + * // Get specific media size based on the featured media ID + * // Note: change sizes?.large for any registered size + * const getFeaturedMediaUrl = useSelect( ( select ) => { + * const getFeaturedMediaId = + * select( 'core/editor' ).getEditedPostAttribute( 'featured_media' ); + * const getMedia = select( 'core' ).getMedia( getFeaturedMediaId ); + * + * return ( + * getMedia?.media_details?.sizes?.large?.source_url || getMedia?.source_url || '' + * ); + * }, [] ); + * ``` + * + * @return {Object} Action object */ export const editPost = ( edits, options ) => diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index f890dcac397326..abb744ee5f2207 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -177,6 +177,11 @@ export const getCurrentPost = createRegistrySelector( * * @param {Object} state Global application state. * + * @example + * + *```js + * const currentPostType = wp.data.select( 'core/editor' ).getCurrentPostType(); + *``` * @return {string} Post type. */ export function getCurrentPostType( state ) { @@ -316,6 +321,22 @@ const getNestedEditedPostProperty = createSelector( * @param {Object} state Global application state. * @param {string} attributeName Post attribute name. * + * @example + * + *```js + * // Get specific media size based on the featured media ID + * // Note: change sizes?.large for any registered size + * const getFeaturedMediaUrl = useSelect( ( select ) => { + * const getFeaturedMediaId = + * select( 'core/editor' ).getEditedPostAttribute( 'featured_media' ); + * const getMedia = select( 'core' ).getMedia( getFeaturedMediaId ); + * + * return ( + * getMedia?.media_details?.sizes?.large?.source_url || getMedia?.source_url || '' + * ); + * }, [] ); + *``` + * * @return {*} Post attribute value. */ export function getEditedPostAttribute( state, attributeName ) { From 55849457a0689da86ff2c82aaf0963333ed92c1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Oct 2024 09:25:45 -0400 Subject: [PATCH 1079/1908] Bump actions/setup-java from 4.3.0 to 4.4.0 in the react-native group (#65651) Bumps the react-native group with 1 update: [actions/setup-java](https://github.com/actions/setup-java). Updates `actions/setup-java` from 4.3.0 to 4.4.0 - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/2dfa2011c5b2a0f1489bf9e433881c92c1631f88...b36c23c0d998641eff861008f374ee103c25ac73) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor dependency-group: react-native ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/rnmobile-android-runner.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index 917ee6144087e6..9392ba100af713 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -28,7 +28,7 @@ jobs: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Java - uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # v4.3.0 + uses: actions/setup-java@b36c23c0d998641eff861008f374ee103c25ac73 # v4.4.0 with: distribution: 'corretto' java-version: '17' From 300470afe6f8f51cc9963bbf92228b8c84b82019 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 4 Oct 2024 15:30:39 +0200 Subject: [PATCH 1080/1908] Update jsdom to 25.0.1 (#65879) * Update jsdom to 25.0.1 * Update package-lock.json --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- package-lock.json | 513 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 253 insertions(+), 262 deletions(-) diff --git a/package-lock.json b/package-lock.json index 48ffe440202c36..0de59cfd601aa4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23071,15 +23071,15 @@ } }, "node_modules/cssstyle": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz", - "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", "dev": true, "dependencies": { - "rrweb-cssom": "^0.6.0" + "rrweb-cssom": "^0.7.1" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/csstype": { @@ -23131,29 +23131,28 @@ } }, "node_modules/data-urls": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz", - "integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", "dev": true, "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.0" + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/data-urls/node_modules/tr46": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", - "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", "dev": true, "dependencies": { - "punycode": "^2.3.0" + "punycode": "^2.3.1" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/data-urls/node_modules/webidl-conversions": { @@ -23166,16 +23165,16 @@ } }, "node_modules/data-urls/node_modules/whatwg-url": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz", - "integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", "dev": true, "dependencies": { - "tr46": "^4.1.1", + "tr46": "^5.0.0", "webidl-conversions": "^7.0.0" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/date-fns": { @@ -24369,27 +24368,6 @@ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" }, - "node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, - "dependencies": { - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/domhandler": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", @@ -29032,15 +29010,15 @@ "integrity": "sha512-fvYTvdCFOWQupGxqkahrkA+ERBuMdzkxwtUdKrxR6rmMd4Pfl+iZ1QiQYoaZ0B/v0y59MOMnz3XFUWbT50/NWA==" }, "node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", "dev": true, "dependencies": { - "whatwg-encoding": "^2.0.0" + "whatwg-encoding": "^3.1.1" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/html-entities": { @@ -32169,40 +32147,38 @@ } }, "node_modules/jsdom": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz", - "integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==", + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", "dev": true, "dependencies": { - "abab": "^2.0.6", - "cssstyle": "^3.0.0", - "data-urls": "^4.0.0", + "cssstyle": "^4.1.0", + "data-urls": "^5.0.0", "decimal.js": "^10.4.3", - "domexception": "^4.0.0", "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.4", + "nwsapi": "^2.2.12", "parse5": "^7.1.2", - "rrweb-cssom": "^0.6.0", + "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.1", - "ws": "^8.13.0", - "xml-name-validator": "^4.0.0" + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=16" + "node": ">=18" }, "peerDependencies": { - "canvas": "^2.5.0" + "canvas": "^2.11.2" }, "peerDependenciesMeta": { "canvas": { @@ -32219,40 +32195,54 @@ "querystring": "^0.2.0" } }, - "node_modules/jsdom/node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "node_modules/jsdom/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" + "debug": "^4.3.4" }, "engines": { - "node": ">=6" + "node": ">= 14" } }, - "node_modules/jsdom/node_modules/tr46": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", - "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "node_modules/jsdom/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, "dependencies": { - "punycode": "^2.3.0" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=14" + "node": ">= 14" } }, - "node_modules/jsdom/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, "engines": { - "node": ">= 4.0.0" + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" } }, "node_modules/jsdom/node_modules/webidl-conversions": { @@ -32265,16 +32255,16 @@ } }, "node_modules/jsdom/node_modules/whatwg-url": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz", - "integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", "dev": true, "dependencies": { - "tr46": "^4.1.1", + "tr46": "^5.0.0", "webidl-conversions": "^7.0.0" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/jsdom/node_modules/ws": { @@ -38722,9 +38712,9 @@ } }, "node_modules/nwsapi": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", - "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", "dev": true }, "node_modules/nx": { @@ -42389,12 +42379,6 @@ "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", "dev": true }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, "node_modules/public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", @@ -42888,12 +42872,6 @@ "node": ">=0.4.x" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, "node_modules/queue": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", @@ -44948,9 +44926,9 @@ } }, "node_modules/rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", "dev": true }, "node_modules/rtlcss": { @@ -48701,6 +48679,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/tldts": { + "version": "6.1.50", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.50.tgz", + "integrity": "sha512-q9GOap6q3KCsLMdOjXhWU5jVZ8/1dIib898JBRLsN+tBhENpBDcAVQbE0epADOjw11FhQQy9AcbqKGBQPUfTQA==", + "dev": true, + "dependencies": { + "tldts-core": "^6.1.50" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.50", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.50.tgz", + "integrity": "sha512-na2EcZqmdA2iV9zHV7OHQDxxdciEpxrjbkp+aHmZgnZKHzoElLajP59np5/4+sare9fQBfixgvXKx8ev1d7ytw==", + "dev": true + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -48807,6 +48803,18 @@ "node": ">=6" } }, + "node_modules/tough-cookie": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "dev": true, + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -49798,16 +49806,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/url-template": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", @@ -50134,15 +50132,15 @@ "dev": true }, "node_modules/w3c-xmlserializer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "dev": true, "dependencies": { - "xml-name-validator": "^4.0.0" + "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/wait-port": { @@ -51756,15 +51754,15 @@ } }, "node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "dev": true, "dependencies": { "iconv-lite": "0.6.3" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/whatwg-fetch": { @@ -51773,12 +51771,12 @@ "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" }, "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "dev": true, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/whatwg-url": { @@ -52285,12 +52283,12 @@ "dev": true }, "node_modules/xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", "dev": true, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/xmlbuilder": { @@ -74397,12 +74395,12 @@ } }, "cssstyle": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz", - "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", "dev": true, "requires": { - "rrweb-cssom": "^0.6.0" + "rrweb-cssom": "^0.7.1" } }, "csstype": { @@ -74445,23 +74443,22 @@ "dev": true }, "data-urls": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz", - "integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", "dev": true, "requires": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.0" + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" }, "dependencies": { "tr46": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", - "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", "dev": true, "requires": { - "punycode": "^2.3.0" + "punycode": "^2.3.1" } }, "webidl-conversions": { @@ -74471,12 +74468,12 @@ "dev": true }, "whatwg-url": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz", - "integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", "dev": true, "requires": { - "tr46": "^4.1.1", + "tr46": "^5.0.0", "webidl-conversions": "^7.0.0" } } @@ -75353,23 +75350,6 @@ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" }, - "domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, - "requires": { - "webidl-conversions": "^7.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true - } - } - }, "domhandler": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", @@ -78931,12 +78911,12 @@ "integrity": "sha512-fvYTvdCFOWQupGxqkahrkA+ERBuMdzkxwtUdKrxR6rmMd4Pfl+iZ1QiQYoaZ0B/v0y59MOMnz3XFUWbT50/NWA==" }, "html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", "dev": true, "requires": { - "whatwg-encoding": "^2.0.0" + "whatwg-encoding": "^3.1.1" } }, "html-entities": { @@ -80659,7 +80639,7 @@ "@types/node": "*", "jest-mock": "^29.6.2", "jest-util": "^29.6.2", - "jsdom": "22.1.0" + "jsdom": "25.0.1" } }, "jest-environment-node": { @@ -81206,62 +81186,71 @@ "dev": true }, "jsdom": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz", - "integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==", + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", "dev": true, "requires": { - "abab": "^2.0.6", - "cssstyle": "^3.0.0", - "data-urls": "^4.0.0", + "cssstyle": "^4.1.0", + "data-urls": "^5.0.0", "decimal.js": "^10.4.3", - "domexception": "^4.0.0", "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.4", + "nwsapi": "^2.2.12", "parse5": "^7.1.2", - "rrweb-cssom": "^0.6.0", + "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.1", - "ws": "^8.13.0", - "xml-name-validator": "^4.0.0" + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" }, "dependencies": { - "tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" + "debug": "^4.3.4" } }, - "tr46": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", - "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, "requires": { - "punycode": "^2.3.0" + "agent-base": "^7.1.0", + "debug": "^4.3.4" } }, - "universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true + "https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "requires": { + "agent-base": "^7.0.2", + "debug": "4" + } + }, + "tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "requires": { + "punycode": "^2.3.1" + } }, "webidl-conversions": { "version": "7.0.0", @@ -81270,12 +81259,12 @@ "dev": true }, "whatwg-url": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz", - "integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", "dev": true, "requires": { - "tr46": "^4.1.1", + "tr46": "^5.0.0", "webidl-conversions": "^7.0.0" } }, @@ -86290,9 +86279,9 @@ "dev": true }, "nwsapi": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", - "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", "dev": true }, "nx": { @@ -88988,12 +88977,6 @@ "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", "dev": true }, - "psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, "public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", @@ -89340,12 +89323,6 @@ "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", "dev": true }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, "queue": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", @@ -90925,9 +90902,9 @@ "dev": true }, "rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", "dev": true }, "rtlcss": { @@ -93779,6 +93756,21 @@ "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", "dev": true }, + "tldts": { + "version": "6.1.50", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.50.tgz", + "integrity": "sha512-q9GOap6q3KCsLMdOjXhWU5jVZ8/1dIib898JBRLsN+tBhENpBDcAVQbE0epADOjw11FhQQy9AcbqKGBQPUfTQA==", + "dev": true, + "requires": { + "tldts-core": "^6.1.50" + } + }, + "tldts-core": { + "version": "6.1.50", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.50.tgz", + "integrity": "sha512-na2EcZqmdA2iV9zHV7OHQDxxdciEpxrjbkp+aHmZgnZKHzoElLajP59np5/4+sare9fQBfixgvXKx8ev1d7ytw==", + "dev": true + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -93863,6 +93855,15 @@ "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true }, + "tough-cookie": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "dev": true, + "requires": { + "tldts": "^6.1.32" + } + }, "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -94633,16 +94634,6 @@ } } }, - "url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "url-template": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", @@ -94863,12 +94854,12 @@ "dev": true }, "w3c-xmlserializer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "dev": true, "requires": { - "xml-name-validator": "^4.0.0" + "xml-name-validator": "^5.0.0" } }, "wait-port": { @@ -96045,9 +96036,9 @@ "dev": true }, "whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "dev": true, "requires": { "iconv-lite": "0.6.3" @@ -96059,9 +96050,9 @@ "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" }, "whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "dev": true }, "whatwg-url": { @@ -96468,9 +96459,9 @@ "dev": true }, "xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", "dev": true }, "xmlbuilder": { diff --git a/package.json b/package.json index b240c89e76d42d..5b8af1f99e7ad9 100644 --- a/package.json +++ b/package.json @@ -267,7 +267,7 @@ "worker-farm": "1.7.0" }, "overrides": { - "jsdom": "22.1.0" + "jsdom": "25.0.1" }, "scripts": { "build": "npm run build:packages && wp-scripts build", From 570a81dd24111c1f84618012f6d562785351b76e Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Fri, 4 Oct 2024 16:07:34 +0200 Subject: [PATCH 1081/1908] Clean up Tabs animation logic (#65878) * Clean up and misc improvements. * Move utility from ToggleGroupControl to utils. * Clean up Tabs.Tablist * Clean up ToggleGroupControl and update utility from latest trunk version * Clean up scroll utility * Remove unnecessary null. * CHANGELOG --------- Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 + packages/components/src/tabs/styles.ts | 17 +-- packages/components/src/tabs/tablist.tsx | 96 ++++++++-------- .../toggle-group-control/component.tsx | 101 +---------------- .../utils/hooks/use-animated-offset-rect.ts | 107 ++++++++++++++++++ 5 files changed, 171 insertions(+), 154 deletions(-) create mode 100644 packages/components/src/utils/hooks/use-animated-offset-rect.ts diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 1e9fdbe07c94e7..ffa67b39200282 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- `Tabs`: fix skipping indication animation glitch ([#65878](https://github.com/WordPress/gutenberg/pull/65878)). + ## 28.9.0 (2024-10-03) ### Bug Fixes diff --git a/packages/components/src/tabs/styles.ts b/packages/components/src/tabs/styles.ts index 283d6421f5b768..4f6b4a4c7c8dcb 100644 --- a/packages/components/src/tabs/styles.ts +++ b/packages/components/src/tabs/styles.ts @@ -30,16 +30,16 @@ export const TabListWrapper = styled.div` --direction-factor: 1; --direction-start: left; --direction-end: right; - --indicator-start: var( --indicator-left ); + --selected-start: var( --selected-left, 0 ); &:dir( rtl ) { --direction-factor: -1; --direction-start: right; --direction-end: left; - --indicator-start: var( --indicator-right ); + --selected-start: var( --selected-right, 0 ); } @media not ( prefers-reduced-motion ) { - &.is-animation-enabled::before { + &[data-indicator-animated]::before { transition-property: transform; transition-duration: 0.2s; transition-timing-function: ease-out; @@ -90,13 +90,14 @@ export const TabListWrapper = styled.div` width: calc( var( --antialiasing-factor ) * 1px ); transform: translateX( calc( - var( --indicator-start ) * var( --direction-factor ) * + var( --selected-start ) * var( --direction-factor ) * 1px ) ) scaleX( calc( - var( --indicator-width ) / var( --antialiasing-factor ) + var( --selected-width, 0 ) / + var( --antialiasing-factor ) ) ); border-bottom: var( --wp-admin-border-width-focus ) solid @@ -108,9 +109,11 @@ export const TabListWrapper = styled.div` left: 0; width: 100%; height: calc( var( --antialiasing-factor ) * 1px ); - transform: translateY( calc( var( --indicator-top ) * 1px ) ) + transform: translateY( calc( var( --selected-top, 0 ) * 1px ) ) scaleY( - calc( var( --indicator-height ) / var( --antialiasing-factor ) ) + calc( + var( --selected-height, 0 ) / var( --antialiasing-factor ) + ) ); background-color: ${ COLORS.theme.gray[ 100 ] }; } diff --git a/packages/components/src/tabs/tablist.tsx b/packages/components/src/tabs/tablist.tsx index ae8daf60fc237c..a861d3294aae66 100644 --- a/packages/components/src/tabs/tablist.tsx +++ b/packages/components/src/tabs/tablist.tsx @@ -19,11 +19,43 @@ import { useTabsContext } from './context'; import { TabListWrapper } from './styles'; import type { WordPressComponentProps } from '../context'; import clsx from 'clsx'; +import type { ElementOffsetRect } from '../utils/element-rect'; import { useTrackElementOffsetRect } from '../utils/element-rect'; -import { useOnValueUpdate } from '../utils/hooks/use-on-value-update'; import { useTrackOverflow } from './use-track-overflow'; +import { useAnimatedOffsetRect } from '../utils/hooks/use-animated-offset-rect'; -const SCROLL_MARGIN = 24; +const DEFAULT_SCROLL_MARGIN = 24; + +/** + * Scrolls a given parent element so that a given rect is visible. + * + * The scroll is updated initially and whenever the rect changes. + */ +function useScrollRectIntoView( + parent: HTMLElement | undefined, + rect: ElementOffsetRect, + { margin = DEFAULT_SCROLL_MARGIN } = {} +) { + useLayoutEffect( () => { + if ( ! parent || ! rect ) { + return; + } + + const { scrollLeft: parentScroll } = parent; + const parentWidth = parent.getBoundingClientRect().width; + const { left: childLeft, width: childWidth } = rect; + + const parentRightEdge = parentScroll + parentWidth; + const childRightEdge = childLeft + childWidth; + const rightOverflow = childRightEdge + margin - parentRightEdge; + const leftOverflow = parentScroll - ( childLeft - margin ); + if ( leftOverflow > 0 ) { + parent.scrollLeft = parentScroll - leftOverflow; + } else if ( rightOverflow > 0 ) { + parent.scrollLeft = parentScroll + rightOverflow; + } + }, [ margin, parent, rect ] ); +} export const TabList = forwardRef< HTMLDivElement, @@ -35,44 +67,27 @@ export const TabList = forwardRef< const activeId = useStoreState( store, 'activeId' ); const selectOnMove = useStoreState( store, 'selectOnMove' ); const items = useStoreState( store, 'items' ); - const [ parent, setParent ] = useState< HTMLElement | null >(); + const [ parent, setParent ] = useState< HTMLElement >(); const refs = useMergeRefs( [ ref, setParent ] ); + const selectedRect = useTrackElementOffsetRect( + store?.item( selectedId )?.element + ); + + // Track overflow to show scroll hints. const overflow = useTrackOverflow( parent, { first: items?.at( 0 )?.element, last: items?.at( -1 )?.element, } ); - const selectedTabPosition = useTrackElementOffsetRect( - store?.item( selectedId )?.element - ); - - const [ animationEnabled, setAnimationEnabled ] = useState( false ); - useOnValueUpdate( selectedId, ( { previousValue } ) => { - if ( previousValue ) { - setAnimationEnabled( true ); - } + // Size, position, and animate the indicator. + useAnimatedOffsetRect( parent, selectedRect, { + prefix: 'selected', + dataAttribute: 'indicator-animated', + transitionEndFilter: ( event ) => event.pseudoElement === '::before', } ); // Make sure selected tab is scrolled into view. - useLayoutEffect( () => { - if ( ! parent || ! selectedTabPosition ) { - return; - } - - const { scrollLeft: parentScroll } = parent; - const parentWidth = parent.getBoundingClientRect().width; - const { left: childLeft, width: childWidth } = selectedTabPosition; - - const parentRightEdge = parentScroll + parentWidth; - const childRightEdge = childLeft + childWidth; - const rightOverflow = childRightEdge + SCROLL_MARGIN - parentRightEdge; - const leftOverflow = parentScroll - ( childLeft - SCROLL_MARGIN ); - if ( leftOverflow > 0 ) { - parent.scrollLeft = parentScroll - leftOverflow; - } else if ( rightOverflow > 0 ) { - parent.scrollLeft = parentScroll + rightOverflow; - } - }, [ parent, selectedTabPosition ] ); + useScrollRectIntoView( parent, selectedRect ); const onBlur = () => { if ( ! selectOnMove ) { @@ -97,30 +112,13 @@ export const TabList = forwardRef< <Ariakit.TabList ref={ refs } store={ store } - render={ - <TabListWrapper - onTransitionEnd={ ( event ) => { - if ( event.pseudoElement === '::before' ) { - setAnimationEnabled( false ); - } - } } - /> - } + render={ <TabListWrapper /> } onBlur={ onBlur } tabIndex={ -1 } { ...otherProps } - style={ { - '--indicator-top': selectedTabPosition.top, - '--indicator-right': selectedTabPosition.right, - '--indicator-left': selectedTabPosition.left, - '--indicator-width': selectedTabPosition.width, - '--indicator-height': selectedTabPosition.height, - ...otherProps.style, - } } className={ clsx( overflow.first && 'is-overflowing-first', overflow.last && 'is-overflowing-last', - animationEnabled && 'is-animation-enabled', otherProps.className ) } > diff --git a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx index cdf8a2c04eb0b8..0b4c22d7df9298 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx @@ -6,7 +6,7 @@ import type { ForwardedRef } from 'react'; /** * WordPress dependencies */ -import { useLayoutEffect, useMemo, useState } from '@wordpress/element'; +import { useMemo, useState } from '@wordpress/element'; /** * Internal dependencies @@ -20,104 +20,9 @@ import { VisualLabelWrapper } from './styles'; import * as styles from './styles'; import { ToggleGroupControlAsRadioGroup } from './as-radio-group'; import { ToggleGroupControlAsButtonGroup } from './as-button-group'; -import type { ElementOffsetRect } from '../../utils/element-rect'; import { useTrackElementOffsetRect } from '../../utils/element-rect'; -import { useOnValueUpdate } from '../../utils/hooks/use-on-value-update'; -import { useEvent, useMergeRefs } from '@wordpress/compose'; - -/** - * A utility used to animate something in a container component based on the "offset - * rect" (position relative to the container and size) of a subelement. For example, - * this is useful to render an indicator for the selected option of a component, and - * to animate it when the selected option changes. - * - * Takes in a container element and the up-to-date "offset rect" of the target - * subelement, obtained with `useTrackElementOffsetRect`. Then it does the following: - * - * - Adds CSS variables with rect information to the container, so that the indicator - * can be rendered and animated with them. These are kept up-to-date, enabling CSS - * transitions on change. - * - Sets an attribute (`data-subelement-animated` by default) when the tracked - * element changes, so that the target (e.g. the indicator) can be animated to its - * new size and position. - * - Removes the attribute when the animation is done. - * - * The need for the attribute is due to the fact that the rect might update in - * situations other than when the tracked element changes, e.g. the tracked element - * might be resized. In such cases, there is no need to animate the indicator, and - * the change in size or position of the indicator needs to be reflected immediately. - */ -function useAnimatedOffsetRect( - /** - * The container element. - */ - container: HTMLElement | undefined, - /** - * The rect of the tracked element. - */ - rect: ElementOffsetRect, - { - prefix = 'subelement', - dataAttribute = `${ prefix }-animated`, - transitionEndFilter = () => true, - }: { - /** - * The prefix used for the CSS variables, e.g. if `prefix` is `selected`, the - * CSS variables will be `--selected-top`, `--selected-left`, etc. - * @default 'subelement' - */ - prefix?: string; - /** - * The name of the data attribute used to indicate that the animation is in - * progress. The `data-` prefix is added automatically. - * - * For example, if `dataAttribute` is `indicator-animated`, the attribute will - * be `data-indicator-animated`. - * @default `${ prefix }-animated` - */ - dataAttribute?: string; - /** - * A function that is called with the transition event and returns a boolean - * indicating whether the animation should be stopped. The default is a function - * that always returns `true`. - * - * For example, if the animated element is the `::before` pseudo-element, the - * function can be written as `( event ) => event.pseudoElement === '::before'`. - * @default () => true - */ - transitionEndFilter?: ( event: TransitionEvent ) => boolean; - } = {} -) { - const setProperties = useEvent( () => { - ( Object.keys( rect ) as Array< keyof typeof rect > ).forEach( - ( property ) => - property !== 'element' && - container?.style.setProperty( - `--${ prefix }-${ property }`, - String( rect[ property ] ) - ) - ); - } ); - useLayoutEffect( () => { - setProperties(); - }, [ rect, setProperties ] ); - useOnValueUpdate( rect.element, ( { previousValue } ) => { - // Only enable the animation when moving from one element to another. - if ( rect.element && previousValue ) { - container?.setAttribute( `data-${ dataAttribute }`, '' ); - } - } ); - useLayoutEffect( () => { - function onTransitionEnd( event: TransitionEvent ) { - if ( transitionEndFilter( event ) ) { - container?.removeAttribute( `data-${ dataAttribute }` ); - } - } - container?.addEventListener( 'transitionend', onTransitionEnd ); - return () => - container?.removeEventListener( 'transitionend', onTransitionEnd ); - }, [ dataAttribute, container, transitionEndFilter ] ); -} +import { useMergeRefs } from '@wordpress/compose'; +import { useAnimatedOffsetRect } from '../../utils/hooks/use-animated-offset-rect'; function UnconnectedToggleGroupControl( props: WordPressComponentProps< ToggleGroupControlProps, 'div', false >, diff --git a/packages/components/src/utils/hooks/use-animated-offset-rect.ts b/packages/components/src/utils/hooks/use-animated-offset-rect.ts new file mode 100644 index 00000000000000..4056089738fe99 --- /dev/null +++ b/packages/components/src/utils/hooks/use-animated-offset-rect.ts @@ -0,0 +1,107 @@ +/* eslint-disable jsdoc/require-param */ + +/** + * WordPress dependencies + */ +import { useEvent } from '@wordpress/compose'; +import { useLayoutEffect } from '@wordpress/element'; +/** + * Internal dependencies + */ +import type { ElementOffsetRect } from '../element-rect'; +import { useOnValueUpdate } from './use-on-value-update'; + +/** + * A utility used to animate something in a container component based on the "offset + * rect" (position relative to the container and size) of a subelement. For example, + * this is useful to render an indicator for the selected option of a component, and + * to animate it when the selected option changes. + * + * Takes in a container element and the up-to-date "offset rect" of the target + * subelement, obtained with `useTrackElementOffsetRect`. Then it does the following: + * + * - Adds CSS variables with rect information to the container, so that the indicator + * can be rendered and animated with them. These are kept up-to-date, enabling CSS + * transitions on change. + * - Sets an attribute (`data-subelement-animated` by default) when the tracked + * element changes, so that the target (e.g. the indicator) can be animated to its + * new size and position. + * - Removes the attribute when the animation is done. + * + * The need for the attribute is due to the fact that the rect might update in + * situations other than when the tracked element changes, e.g. the tracked element + * might be resized. In such cases, there is no need to animate the indicator, and + * the change in size or position of the indicator needs to be reflected immediately. + */ +export function useAnimatedOffsetRect( + /** + * The container element. + */ + container: HTMLElement | undefined, + /** + * The rect of the tracked element. + */ + rect: ElementOffsetRect, + { + prefix = 'subelement', + dataAttribute = `${ prefix }-animated`, + transitionEndFilter = () => true, + }: { + /** + * The prefix used for the CSS variables, e.g. if `prefix` is `selected`, the + * CSS variables will be `--selected-top`, `--selected-left`, etc. + * @default 'subelement' + */ + prefix?: string; + /** + * The name of the data attribute used to indicate that the animation is in + * progress. The `data-` prefix is added automatically. + * + * For example, if `dataAttribute` is `indicator-animated`, the attribute will + * be `data-indicator-animated`. + * @default `${ prefix }-animated` + */ + dataAttribute?: string; + /** + * A function that is called with the transition event and returns a boolean + * indicating whether the animation should be stopped. The default is a function + * that always returns `true`. + * + * For example, if the animated element is the `::before` pseudo-element, the + * function can be written as `( event ) => event.pseudoElement === '::before'`. + * @default () => true + */ + transitionEndFilter?: ( event: TransitionEvent ) => boolean; + } = {} +) { + const setProperties = useEvent( () => { + ( Object.keys( rect ) as Array< keyof typeof rect > ).forEach( + ( property ) => + property !== 'element' && + container?.style.setProperty( + `--${ prefix }-${ property }`, + String( rect[ property ] ) + ) + ); + } ); + useLayoutEffect( () => { + setProperties(); + }, [ rect, setProperties ] ); + useOnValueUpdate( rect.element, ( { previousValue } ) => { + // Only enable the animation when moving from one element to another. + if ( rect.element && previousValue ) { + container?.setAttribute( `data-${ dataAttribute }`, '' ); + } + } ); + useLayoutEffect( () => { + function onTransitionEnd( event: TransitionEvent ) { + if ( transitionEndFilter( event ) ) { + container?.removeAttribute( `data-${ dataAttribute }` ); + } + } + container?.addEventListener( 'transitionend', onTransitionEnd ); + return () => + container?.removeEventListener( 'transitionend', onTransitionEnd ); + }, [ dataAttribute, container, transitionEndFilter ] ); +} +/* eslint-enable jsdoc/require-param */ From 597c7d97e5da343eaab9556a30c875cde0a0647f Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Sat, 5 Oct 2024 00:52:26 +1000 Subject: [PATCH 1082/1908] `PaletteEdit`: dedupe palette element slugs (#65772) * First pass at deduping palette element slugs. * Addressing TypeScript errors where PaletteEditListViewProps is using a generic type parameter. The linter was complaining that I wasn't doing the same, even though I was using the same inherited types. Whatever. It could probably be optimized, but it's unrelated to the scope of this PR * Add changelog * Make use of PaletteElement type consistent * Address feedback on deduplicate util * Use count rather than index for new slugs --------- Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/palette-edit/index.tsx | 35 +++++++++++-- .../src/palette-edit/test/index.tsx | 51 ++++++++++++++++++- 3 files changed, 81 insertions(+), 6 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index ffa67b39200282..f70fce00c3983b 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -4,6 +4,7 @@ ### Bug Fixes +- `PaletteEdit`: dedupe palette element slugs ([#65772](https://github.com/WordPress/gutenberg/pull/65772)). - `Tabs`: fix skipping indication animation glitch ([#65878](https://github.com/WordPress/gutenberg/pull/65878)). ## 28.9.0 (2024-10-03) diff --git a/packages/components/src/palette-edit/index.tsx b/packages/components/src/palette-edit/index.tsx index 601ea758b75bba..8bfcb7240b9ea4 100644 --- a/packages/components/src/palette-edit/index.tsx +++ b/packages/components/src/palette-edit/index.tsx @@ -49,7 +49,6 @@ import { kebabCase } from '../utils/strings'; import type { Color, ColorPickerPopoverProps, - Gradient, NameInputProps, OptionProps, PaletteEditListViewProps, @@ -70,6 +69,28 @@ function NameInput( { value, onChange, label }: NameInputProps ) { ); } +/* + * Deduplicates the slugs of the provided elements. + */ +export function deduplicateElementSlugs< T extends PaletteElement >( + elements: T[] +) { + const slugCounts: { [ slug: string ]: number } = {}; + + return elements.map( ( element ) => { + let newSlug: string | undefined; + + const { slug } = element; + slugCounts[ slug ] = ( slugCounts[ slug ] || 0 ) + 1; + + if ( slugCounts[ slug ] > 1 ) { + newSlug = `${ slug }-${ slugCounts[ slug ] - 1 }`; + } + + return { ...element, slug: newSlug ?? slug }; + } ); +} + /** * Returns a name and slug for a palette item. The name takes the format "Color + id". * To ensure there are no duplicate ids, this function checks all slugs. @@ -109,7 +130,7 @@ export function getNameAndSlugForPosition( }; } -function ColorPickerPopover< T extends Color | Gradient >( { +function ColorPickerPopover< T extends PaletteElement >( { isGradient, element, onChange, @@ -167,7 +188,7 @@ function ColorPickerPopover< T extends Color | Gradient >( { ); } -function Option< T extends Color | Gradient >( { +function Option< T extends PaletteElement >( { canOnlyChangeValues, element, onChange, @@ -265,7 +286,7 @@ function Option< T extends Color | Gradient >( { ); } -function PaletteEditListView< T extends Color | Gradient >( { +function PaletteEditListView< T extends PaletteElement >( { elements, onChange, canOnlyChangeValues, @@ -280,7 +301,11 @@ function PaletteEditListView< T extends Color | Gradient >( { elementsReferenceRef.current = elements; }, [ elements ] ); - const debounceOnChange = useDebounce( onChange, 100 ); + const debounceOnChange = useDebounce( + ( updatedElements: T[] ) => + onChange( deduplicateElementSlugs( updatedElements ) ), + 100 + ); return ( <VStack spacing={ 3 }> diff --git a/packages/components/src/palette-edit/test/index.tsx b/packages/components/src/palette-edit/test/index.tsx index 980630633b97f9..7dc00dbba22042 100644 --- a/packages/components/src/palette-edit/test/index.tsx +++ b/packages/components/src/palette-edit/test/index.tsx @@ -7,7 +7,10 @@ import { click, type, press } from '@ariakit/test'; /** * Internal dependencies */ -import PaletteEdit, { getNameAndSlugForPosition } from '..'; +import PaletteEdit, { + getNameAndSlugForPosition, + deduplicateElementSlugs, +} from '..'; import type { PaletteElement } from '../types'; const noop = () => {}; @@ -97,6 +100,52 @@ describe( 'getNameAndSlugForPosition', () => { } ); } ); +describe( 'deduplicateElementSlugs', () => { + it( 'should not change the slugs if they are unique', () => { + const elements: PaletteElement[] = [ + { + slug: 'test-color-1', + color: '#ffffff', + name: 'Test Color 1', + }, + { + slug: 'test-color-2', + color: '#1a4548', + name: 'Test Color 2', + }, + ]; + + expect( deduplicateElementSlugs( elements ) ).toEqual( elements ); + } ); + it( 'should change the slugs if they are not unique', () => { + const elements: PaletteElement[] = [ + { + slug: 'test-color-1', + color: '#ffffff', + name: 'Test Color 1', + }, + { + slug: 'test-color-1', + color: '#1a4548', + name: 'Test Color 2', + }, + ]; + + expect( deduplicateElementSlugs( elements ) ).toEqual( [ + { + slug: 'test-color-1', + color: '#ffffff', + name: 'Test Color 1', + }, + { + slug: 'test-color-1-1', + color: '#1a4548', + name: 'Test Color 2', + }, + ] ); + } ); +} ); + describe( 'PaletteEdit', () => { const defaultProps = { paletteLabel: 'Test label', From 9b1ee5126f742eff77aba3c885afe4ae31e41ab2 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Sat, 5 Oct 2024 00:00:15 +0900 Subject: [PATCH 1083/1908] Query Loop: Fix query type indicator (#65877) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../src/query/edit/inspector-controls/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index 3128c3526926f9..28a6113620fb7c 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -211,7 +211,7 @@ export default function QueryInspectorControls( props ) { label={ __( 'Query type' ) } isBlock onChange={ ( value ) => { - setQuery( { inherit: !! value } ); + setQuery( { inherit: value === 'default' } ); } } help={ inherit @@ -222,14 +222,14 @@ export default function QueryInspectorControls( props ) { 'Display a list of posts or custom post types based on specific criteria.' ) } - value={ !! inherit } + value={ !! inherit ? 'default' : 'custom' } > <ToggleGroupControlOption - value + value="default" label={ __( 'Default' ) } /> <ToggleGroupControlOption - value={ false } + value="custom" label={ __( 'Custom' ) } /> </ToggleGroupControl> From 366cf1f8d6a2169217b82a57ee1af8ba4c1f8b42 Mon Sep 17 00:00:00 2001 From: Michal <mmczaplinski@gmail.com> Date: Fri, 4 Oct 2024 16:30:25 +0100 Subject: [PATCH 1084/1908] Interactivity API: Correctly handle lazily added, deeply nested properties with `deepMerge()` (#65465) * test: Add case for deeply nested undefined properties in context proxy Add a test to ensure the context proxy correctly handles and updates deeply nested properties that are initially undefined. * Update the test case to use `proxifyState()` * Add test for deepMerge with nested undefined properties * Add a failing test in `deep-merge.ts` * Add another failing test * Make all the tests pass * Simplify code * Fix test case name * Add one extra test * Update test in `context-proxy` * Update changelog --------- Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: DAreRodz <darerodz@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- packages/interactivity/CHANGELOG.md | 4 + packages/interactivity/src/proxies/state.ts | 81 ++++++++++--------- .../src/proxies/test/context-proxy.ts | 62 +++++++++++++- .../src/proxies/test/deep-merge.ts | 73 +++++++++++++++++ 4 files changed, 182 insertions(+), 38 deletions(-) diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index d35dfa7c81ae43..f4431d108dc360 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- Correctly handle lazily added, deeply nested properties with `deepMerge()` ([#65465](https://github.com/WordPress/gutenberg/pull/65465)). + ## 6.9.0 (2024-10-03) ## 6.8.0 (2024-09-19) diff --git a/packages/interactivity/src/proxies/state.ts b/packages/interactivity/src/proxies/state.ts index c91d8f6ab90a5b..f63c84738bcb1a 100644 --- a/packages/interactivity/src/proxies/state.ts +++ b/packages/interactivity/src/proxies/state.ts @@ -300,50 +300,57 @@ const deepMergeRecursive = ( source: any, override: boolean = true ) => { - if ( isPlainObject( target ) && isPlainObject( source ) ) { - let hasNewKeys = false; - for ( const key in source ) { - const isNew = ! ( key in target ); - hasNewKeys = hasNewKeys || isNew; + if ( ! ( isPlainObject( target ) && isPlainObject( source ) ) ) { + return; + } - const desc = Object.getOwnPropertyDescriptor( source, key ); - if ( - typeof desc?.get === 'function' || - typeof desc?.set === 'function' - ) { - if ( override || isNew ) { - Object.defineProperty( target, key, { - ...desc, - configurable: true, - enumerable: true, - } ); - - const proxy = getProxyFromObject( target ); - if ( desc?.get && proxy && hasPropSignal( proxy, key ) ) { - const propSignal = getPropSignal( proxy, key ); - propSignal.setGetter( desc.get ); - } - } - } else if ( isPlainObject( source[ key ] ) ) { - if ( isNew ) { - target[ key ] = {}; - } + let hasNewKeys = false; - deepMergeRecursive( target[ key ], source[ key ], override ); - } else if ( override || isNew ) { - Object.defineProperty( target, key, desc! ); + for ( const key in source ) { + const isNew = ! ( key in target ); + hasNewKeys = hasNewKeys || isNew; - const proxy = getProxyFromObject( target ); - if ( desc?.value && proxy && hasPropSignal( proxy, key ) ) { - const propSignal = getPropSignal( proxy, key ); - propSignal.setValue( desc.value ); + const desc = Object.getOwnPropertyDescriptor( source, key )!; + const proxy = getProxyFromObject( target ); + const propSignal = + !! proxy && + hasPropSignal( proxy, key ) && + getPropSignal( proxy, key ); + + if ( + typeof desc.get === 'function' || + typeof desc.set === 'function' + ) { + if ( override || isNew ) { + Object.defineProperty( target, key, { + ...desc, + configurable: true, + enumerable: true, + } ); + if ( desc.get && propSignal ) { + propSignal.setGetter( desc.get ); + } + } + } else if ( isPlainObject( source[ key ] ) ) { + if ( isNew || ( override && ! isPlainObject( target[ key ] ) ) ) { + target[ key ] = {}; + if ( propSignal ) { + propSignal.setValue( target[ key ] ); } } + if ( isPlainObject( target[ key ] ) ) { + deepMergeRecursive( target[ key ], source[ key ], override ); + } + } else if ( override || isNew ) { + Object.defineProperty( target, key, desc ); + if ( propSignal ) { + propSignal.setValue( desc.value ); + } } + } - if ( hasNewKeys && objToIterable.has( target ) ) { - objToIterable.get( target )!.value++; - } + if ( hasNewKeys && objToIterable.has( target ) ) { + objToIterable.get( target )!.value++; } }; diff --git a/packages/interactivity/src/proxies/test/context-proxy.ts b/packages/interactivity/src/proxies/test/context-proxy.ts index 306b3e4a8aa94f..1e4a969d0f9dc6 100644 --- a/packages/interactivity/src/proxies/test/context-proxy.ts +++ b/packages/interactivity/src/proxies/test/context-proxy.ts @@ -6,7 +6,7 @@ import { effect } from '@preact/signals'; /** * Internal dependencies */ -import { proxifyContext, proxifyState } from '../'; +import { proxifyContext, proxifyState, deepMerge } from '../'; describe( 'Interactivity API', () => { describe( 'context proxy', () => { @@ -277,6 +277,66 @@ describe( 'Interactivity API', () => { 'fromFallback', ] ); } ); + + it( 'should handle deeply nested properties that are initially undefined', () => { + const fallback: any = proxifyContext( + proxifyState( 'test', {} ), + {} + ); + const context: any = proxifyContext( + proxifyState( 'test', {} ), + fallback + ); + + let deepValue: any; + const spy = jest.fn( () => { + deepValue = context.a?.b?.c?.d; + } ); + effect( spy ); + + // Initial call, the deep value is undefined + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( deepValue ).toBeUndefined(); + + // Add a deeply nested object to the context + context.a = { b: { c: { d: 'test value' } } }; + + // The effect should be called again + expect( spy ).toHaveBeenCalledTimes( 2 ); + expect( deepValue ).toBe( 'test value' ); + + // Reading the value directly should also work + expect( context.a.b.c.d ).toBe( 'test value' ); + } ); + + it( 'should handle deeply nested properties that are initially undefined and merged with deepMerge', () => { + const fallbackState = proxifyState( 'test', {} ); + const fallback: any = proxifyContext( fallbackState, {} ); + const contextState = proxifyState( 'test', {} ); + const context: any = proxifyContext( contextState, fallback ); + + let deepValue: any; + const spy = jest.fn( () => { + deepValue = context.a?.b?.c?.d; + } ); + effect( spy ); + + // Initial call, the deep value is undefined + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( deepValue ).toBeUndefined(); + + // Use deepMerge to add a deeply nested object to the context + deepMerge( contextState, { + a: { b: { c: { d: 'test value' } } }, + } ); + + // The effect should be called again + expect( spy ).toHaveBeenCalledTimes( 2 ); + expect( deepValue ).toBe( 'test value' ); + + // Reading the value directly should also work + expect( context.a.b.c.d ).toBe( 'test value' ); + } ); } ); describe( 'proxifyContext', () => { diff --git a/packages/interactivity/src/proxies/test/deep-merge.ts b/packages/interactivity/src/proxies/test/deep-merge.ts index bf31c4b552133c..f475385a437876 100644 --- a/packages/interactivity/src/proxies/test/deep-merge.ts +++ b/packages/interactivity/src/proxies/test/deep-merge.ts @@ -389,5 +389,78 @@ describe( 'Interactivity API', () => { expect( spy ).toHaveBeenCalledTimes( 2 ); expect( spy ).toHaveLastReturnedWith( [ 'a', 'b', 'c' ] ); } ); + + it( 'should handle deeply nested properties that are initially undefined', () => { + const target: any = proxifyState( 'test', {} ); + + let deepValue: any; + const spy = jest.fn( () => { + deepValue = target.a?.b?.c?.d; + } ); + effect( spy ); + + // Initial call, the deep value is undefined + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( deepValue ).toBeUndefined(); + + // Use deepMerge to add a deeply nested object to the target + deepMerge( target, { a: { b: { c: { d: 'test value' } } } } ); + + // The effect should be called again + expect( spy ).toHaveBeenCalledTimes( 2 ); + expect( deepValue ).toBe( 'test value' ); + + // Reading the value directly should also work + expect( target.a.b.c.d ).toBe( 'test value' ); + } ); + + it( 'should overwrite values that become objects', () => { + const target: any = proxifyState( 'test', { message: 'hello' } ); + + let message: any; + const spy = jest.fn( () => ( message = target.message ) ); + effect( spy ); + + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( message ).toBe( 'hello' ); + + deepMerge( target, { + message: { content: 'hello', fontStyle: 'italic' }, + } ); + + expect( spy ).toHaveBeenCalledTimes( 2 ); + expect( message ).toEqual( { + content: 'hello', + fontStyle: 'italic', + } ); + + expect( target.message ).toEqual( { + content: 'hello', + fontStyle: 'italic', + } ); + } ); + + it( 'should not overwrite values that become objects if `override` is false', () => { + const target: any = proxifyState( 'test', { message: 'hello' } ); + + let message: any; + const spy = jest.fn( () => ( message = target.message ) ); + effect( spy ); + + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( message ).toBe( 'hello' ); + + deepMerge( + target, + { message: { content: 'hello', fontStyle: 'italic' } }, + false + ); + + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( message ).toBe( 'hello' ); + expect( target.message ).toBe( 'hello' ); + expect( target.message.content ).toBeUndefined(); + expect( target.message.fontStyle ).toBeUndefined(); + } ); } ); } ); From ae8e73bdd0edb03b1cdf027d0a036c88b0c6b625 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Fri, 4 Oct 2024 12:32:36 -0500 Subject: [PATCH 1085/1908] Update/replace edit button with enter on selection (#65760) --- .../use-selected-block-event-handlers.js | 29 ++++++++++++++++--- .../block-tools/zoom-out-toolbar.js | 25 ++-------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-selected-block-event-handlers.js b/packages/block-editor/src/components/block-list/use-block-props/use-selected-block-event-handlers.js index 01cc462e507ecf..19b778ca8fccfc 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-selected-block-event-handlers.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-selected-block-event-handlers.js @@ -10,6 +10,7 @@ import { useRefEffect } from '@wordpress/compose'; * Internal dependencies */ import { store as blockEditorStore } from '../../../store'; +import { unlock } from '../../../lock-unlock'; /** * Adds block behaviour: @@ -20,9 +21,18 @@ import { store as blockEditorStore } from '../../../store'; * @param {string} clientId Block client ID. */ export function useEventHandlers( { clientId, isSelected } ) { - const { getBlockRootClientId, getBlockIndex } = - useSelect( blockEditorStore ); - const { insertAfterBlock, removeBlock } = useDispatch( blockEditorStore ); + const { + getBlockRootClientId, + getBlockIndex, + isZoomOut, + __unstableGetEditorMode, + } = unlock( useSelect( blockEditorStore ) ); + const { + insertAfterBlock, + removeBlock, + __unstableSetEditorMode, + resetZoomLevel, + } = unlock( useDispatch( blockEditorStore ) ); return useRefEffect( ( node ) => { @@ -56,7 +66,14 @@ export function useEventHandlers( { clientId, isSelected } ) { event.preventDefault(); - if ( keyCode === ENTER ) { + if ( + keyCode === ENTER && + __unstableGetEditorMode() === 'zoom-out' && + isZoomOut() + ) { + __unstableSetEditorMode( 'edit' ); + resetZoomLevel(); + } else if ( keyCode === ENTER ) { insertAfterBlock( clientId ); } else { removeBlock( clientId ); @@ -88,6 +105,10 @@ export function useEventHandlers( { clientId, isSelected } ) { getBlockIndex, insertAfterBlock, removeBlock, + __unstableGetEditorMode, + __unstableSetEditorMode, + isZoomOut, + resetZoomLevel, ] ); } diff --git a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js index f2c073117d2ce8..2b5c6a3e3cea6e 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { dragHandle, trash, edit } from '@wordpress/icons'; +import { dragHandle, trash } from '@wordpress/icons'; import { Button, ToolbarButton } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as blocksStore } from '@wordpress/blocks'; @@ -15,7 +15,6 @@ import BlockDraggable from '../block-draggable'; import BlockMover from '../block-mover'; import Shuffle from '../block-toolbar/shuffle'; import NavigableToolbar from '../navigable-toolbar'; -import { unlock } from '../../lock-unlock'; export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { const selected = useSelect( @@ -74,12 +73,9 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { isPrevBlockTemplatePart, canRemove, canMove, - setIsInserterOpened, } = selected; - const { removeBlock, __unstableSetEditorMode, resetZoomLevel } = unlock( - useDispatch( blockEditorStore ) - ); + const { removeBlock } = useDispatch( blockEditorStore ); const showBlockDraggable = canMove && ! isBlockTemplatePart; @@ -123,23 +119,6 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { <Shuffle clientId={ clientId } as={ ToolbarButton } /> ) } - { ! isBlockTemplatePart && ( - <ToolbarButton - className="zoom-out-toolbar-button" - icon={ edit } - label={ __( 'Edit' ) } - onClick={ () => { - // Setting may be undefined. - if ( typeof setIsInserterOpened === 'function' ) { - setIsInserterOpened( false ); - } - __unstableSetEditorMode( 'edit' ); - resetZoomLevel(); - __unstableContentRef.current?.focus(); - } } - /> - ) } - { canRemove && ! isBlockTemplatePart && ( <ToolbarButton className="zoom-out-toolbar-button" From 9d67345a00a0ce3f1ca40b5894e45fc3b9088857 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Oct 2024 17:37:43 +0000 Subject: [PATCH 1086/1908] Bump preactjs/compressed-size-action in the github-actions group (#65792) Bumps the github-actions group with 1 update: [preactjs/compressed-size-action](https://github.com/preactjs/compressed-size-action). Updates `preactjs/compressed-size-action` from 2.6.0 to 2.7.0 - [Release notes](https://github.com/preactjs/compressed-size-action/releases) - [Commits](https://github.com/preactjs/compressed-size-action/compare/f780fd104362cfce9e118f9198df2ee37d12946c...6fa0e7ca017120c754863b31123c5ee2860fd434) --- updated-dependencies: - dependency-name: preactjs/compressed-size-action dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/bundle-size.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bundle-size.yml b/.github/workflows/bundle-size.yml index e24b30eea7ba7c..2de66f77e3918b 100644 --- a/.github/workflows/bundle-size.yml +++ b/.github/workflows/bundle-size.yml @@ -49,7 +49,7 @@ jobs: check-latest: true cache: npm - - uses: preactjs/compressed-size-action@f780fd104362cfce9e118f9198df2ee37d12946c # v2.6.0 + - uses: preactjs/compressed-size-action@6fa0e7ca017120c754863b31123c5ee2860fd434 # v2.7.0 with: repo-token: '${{ secrets.GITHUB_TOKEN }}' pattern: '{build/**/*.min.js,build/**/*.css,build-module/**/*.min.js}' From 06629d25d0c2f4e5d472c6ce7da614b3297aa800 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Sat, 5 Oct 2024 11:54:44 +0900 Subject: [PATCH 1087/1908] Block Visibility: Add e2e test (#65880) * Block Visibility: Add e2e test * Use `toHaveCount` instead of `toBe` Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../editor/various/block-visibility.spec.js | 258 ++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 test/e2e/specs/editor/various/block-visibility.spec.js diff --git a/test/e2e/specs/editor/various/block-visibility.spec.js b/test/e2e/specs/editor/various/block-visibility.spec.js new file mode 100644 index 00000000000000..bed337624275e4 --- /dev/null +++ b/test/e2e/specs/editor/various/block-visibility.spec.js @@ -0,0 +1,258 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.use( { + BlockVisibilityUtils: async ( { page }, use ) => { + await use( new BlockVisibilityUtils( { page } ) ); + }, +} ); + +test.describe( 'Block Visibility', () => { + test.beforeEach( async ( { admin } ) => { + await admin.createNewPost(); + } ); + + test.afterEach( async ( { page } ) => { + // Re-enable all blocks. + await page.evaluate( () => { + const blockTypes = window.wp.data + .select( 'core/blocks' ) + .getBlockTypes(); + window.wp.data + .dispatch( 'core/edit-post' ) + .showBlockTypes( blockTypes ); + } ); + } ); + + test( 'should hide/show the block', async ( { + page, + BlockVisibilityUtils, + } ) => { + // Hide heading block. + await BlockVisibilityUtils.openBlockVisibilityManager(); + await page + .getByRole( 'region', { name: 'Available block types' } ) + .getByRole( 'checkbox', { name: 'Heading' } ) + .uncheck(); + await page + .getByRole( 'dialog', { + name: 'Preferences', + } ) + .getByRole( 'button', { name: 'Close' } ) + .click(); + await page + .getByRole( 'button', { name: 'Toggle block inserter' } ) + .click(); + await page + .getByRole( 'region', { name: 'Block Library' } ) + .getByRole( 'searchbox', { + name: 'Search for blocks and patterns', + } ) + .fill( 'Heading' ); + + await expect( + page + .getByRole( 'tabpanel', { name: 'Blocks' } ) + .getByRole( 'option', { name: 'Heading' } ), + 'Heading block should not be visible' + ).toBeHidden(); + + await page + .getByRole( 'button', { name: 'Toggle block inserter' } ) + .click(); + + // Show heading block again. + await BlockVisibilityUtils.openBlockVisibilityManager(); + + await expect( + page + .getByRole( 'region', { name: 'Available block types' } ) + .getByRole( 'checkbox', { name: 'Heading' } ), + 'Heading block should be unchecked' + ).not.toBeChecked(); + + await page + .getByRole( 'region', { name: 'Available block types' } ) + .getByRole( 'checkbox', { name: 'Heading' } ) + .check(); + await page + .getByRole( 'dialog', { + name: 'Preferences', + } ) + .getByRole( 'button', { name: 'Close' } ) + .click(); + await page + .getByRole( 'button', { name: 'Toggle block inserter' } ) + .click(); + await page + .getByRole( 'region', { name: 'Block Library' } ) + .getByRole( 'searchbox', { + name: 'Search for blocks and patterns', + } ) + .fill( 'Heading' ); + + await expect( + page + .getByRole( 'tabpanel', { name: 'Blocks' } ) + .getByRole( 'option', { name: 'Heading' } ), + 'Heading block should be visible' + ).toBeVisible(); + } ); + + test( 'should hide/show all blocks in a category at once', async ( { + page, + BlockVisibilityUtils, + } ) => { + // Hide Media category blocks. + await BlockVisibilityUtils.openBlockVisibilityManager(); + await page + .getByRole( 'region', { name: 'Available block types' } ) + .getByRole( 'checkbox', { name: 'Media', exact: true } ) + .uncheck(); + await page + .getByRole( 'dialog', { + name: 'Preferences', + } ) + .getByRole( 'button', { name: 'Close' } ) + .click(); + await page + .getByRole( 'button', { name: 'Toggle block inserter' } ) + .click(); + + await expect( + page + .getByRole( 'tabpanel', { name: 'Blocks' } ) + .getByRole( 'heading', { name: 'Media' } ), + 'Media category should not be visible' + ).toBeHidden(); + + await page + .getByRole( 'button', { name: 'Toggle block inserter' } ) + .click(); + + // Show Media category blocks again. + await BlockVisibilityUtils.openBlockVisibilityManager(); + + await expect( + page + .getByRole( 'region', { name: 'Available block types' } ) + .getByRole( 'checkbox', { name: 'Media', exact: true } ), + 'Media category should be unchecked' + ).not.toBeChecked(); + + await page + .getByRole( 'region', { name: 'Available block types' } ) + .getByRole( 'checkbox', { name: 'Media', exact: true } ) + .check(); + await page + .getByRole( 'dialog', { + name: 'Preferences', + } ) + .getByRole( 'button', { name: 'Close' } ) + .click(); + await page + .getByRole( 'button', { name: 'Toggle block inserter' } ) + .click(); + + await expect( + page + .getByRole( 'tabpanel', { name: 'Blocks' } ) + .getByRole( 'heading', { name: 'Media' } ), + 'Media category should be visible' + ).toBeVisible(); + } ); + + test( 'should search for blocks by keyword', async ( { + page, + BlockVisibilityUtils, + } ) => { + await BlockVisibilityUtils.openBlockVisibilityManager(); + await page + .getByRole( 'searchbox', { + name: 'Search for a block', + } ) + .fill( 'verse' ); + const blockCategories = page + .getByRole( 'region', { + name: 'Available block types', + } ) + .getByRole( 'group' ); + + await expect( + blockCategories, + 'Only one category should be visible' + ).toHaveCount( 1 ); + + await expect( + blockCategories.first().getByRole( 'checkbox', { name: 'Text' } ), + 'Text category should be visible' + ).toBeVisible(); + + const textCategoryBlocksList = blockCategories + .first() + .getByRole( 'list' ); + + await expect( + textCategoryBlocksList.getByRole( 'checkbox' ), + 'Only one block should be visible' + ).toHaveCount( 1 ); + + await expect( + textCategoryBlocksList.getByRole( 'checkbox', { name: 'Verse' } ), + 'Verse block should be visible' + ).toBeVisible(); + } ); + + test( 'should reset hidden blocks', async ( { + page, + BlockVisibilityUtils, + } ) => { + await BlockVisibilityUtils.openBlockVisibilityManager(); + + // Hide Heading and List blocks. + await page + .getByRole( 'region', { name: 'Available block types' } ) + .getByRole( 'checkbox', { name: 'Heading' } ) + .uncheck(); + await page + .getByRole( 'region', { name: 'Available block types' } ) + .getByRole( 'checkbox', { name: 'List', exact: true } ) + .uncheck(); + + // Reset hidden blocks. + await page.getByRole( 'button', { name: 'Reset' } ).click(); + + await expect( + page + .getByRole( 'region', { name: 'Available block types' } ) + .getByRole( 'checkbox', { name: 'Heading' } ), + 'Heading block should be checked' + ).toBeChecked(); + await expect( + page + .getByRole( 'region', { name: 'Available block types' } ) + .getByRole( 'checkbox', { name: 'List', exact: true } ), + 'List block should be checked' + ).toBeChecked(); + } ); +} ); + +class BlockVisibilityUtils { + constructor( { page, admin, requestUtils } ) { + this.page = page; + this.admin = admin; + this.requestUtils = requestUtils; + } + async openBlockVisibilityManager() { + await this.page + .getByRole( 'region', { name: 'Editor top bar' } ) + .getByRole( 'button', { name: 'Options' } ) + .click(); + await this.page + .getByRole( 'menuitem', { name: 'Preferences' } ) + .click(); + await this.page.getByRole( 'tab', { name: 'Blocks' } ).click(); + } +} From 90d7c3b1f56ca64d14f2168e30cba257c0e76827 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Sat, 5 Oct 2024 15:34:32 +0200 Subject: [PATCH 1088/1908] Global Styles: fix overflow caused by RangeControl tooltip (#65875) * RangeControl: do not render tooltip in the DOM when hidden * RangeControl: do not apply react props as attributes on wrapper element * Global Styles: add bottom padding to allow for tooltip in font size screen * CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../styles/range-control-styles.ts | 29 ++++++++++++------- .../components/src/range-control/tooltip.tsx | 2 +- .../global-styles/font-sizes/font-size.js | 6 +++- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index f70fce00c3983b..f7f22160c2187b 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Bug Fixes - `PaletteEdit`: dedupe palette element slugs ([#65772](https://github.com/WordPress/gutenberg/pull/65772)). +- `RangeControl`: do not tooltip contents to the DOM when not shown ([#65875](https://github.com/WordPress/gutenberg/pull/65875)). - `Tabs`: fix skipping indication animation glitch ([#65878](https://github.com/WordPress/gutenberg/pull/65878)). ## 28.9.0 (2024-10-03) diff --git a/packages/components/src/range-control/styles/range-control-styles.ts b/packages/components/src/range-control/styles/range-control-styles.ts index dae1d0de3ddb66..6e9c68ace97532 100644 --- a/packages/components/src/range-control/styles/range-control-styles.ts +++ b/packages/components/src/range-control/styles/range-control-styles.ts @@ -57,7 +57,10 @@ const wrapperMargin = ( { marks, __nextHasNoMarginBottom }: WrapperProps ) => { return ''; }; -export const Wrapper = styled.div< WrapperProps >` +export const Wrapper = styled( 'div', { + shouldForwardProp: ( prop: string ) => + ! [ 'color', '__nextHasNoMarginBottom', 'marks' ].includes( prop ), +} )< WrapperProps >` display: block; flex: 1; position: relative; @@ -261,9 +264,20 @@ export const InputRange = styled.input` `; const tooltipShow = ( { show }: TooltipProps ) => { - return css( { - opacity: show ? 1 : 0, - } ); + return css` + display: ${ show ? 'inline-block' : 'none' }; + opacity: ${ show ? 1 : 0 }; + + @media not ( prefers-reduced-motion ) { + transition: + opacity 120ms ease, + display 120ms ease allow-discrete; + } + + @starting-style { + opacity: 0; + } + `; }; const tooltipPosition = ( { position }: TooltipProps ) => { @@ -284,10 +298,8 @@ export const Tooltip = styled.span< TooltipProps >` background: rgba( 0, 0, 0, 0.8 ); border-radius: ${ CONFIG.radiusSmall }; color: white; - display: inline-block; font-size: 12px; min-width: 32px; - opacity: 0; padding: 4px 8px; pointer-events: none; position: absolute; @@ -295,11 +307,8 @@ export const Tooltip = styled.span< TooltipProps >` user-select: none; line-height: 1.4; - @media not ( prefers-reduced-motion ) { - transition: opacity 120ms ease; - } - ${ tooltipShow }; + ${ tooltipPosition }; ${ rtl( { transform: 'translateX(-50%)' }, diff --git a/packages/components/src/range-control/tooltip.tsx b/packages/components/src/range-control/tooltip.tsx index 432415086dcef9..4156c026464347 100644 --- a/packages/components/src/range-control/tooltip.tsx +++ b/packages/components/src/range-control/tooltip.tsx @@ -40,7 +40,7 @@ export default function SimpleTooltip( return ( <Tooltip { ...restProps } - aria-hidden={ show } + aria-hidden="false" className={ classes } position={ position } show={ show } diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js index 63310203ef05b1..b99703d39c8d62 100644 --- a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js @@ -197,7 +197,11 @@ function FontSize() { </HStack> <View> - <Spacer paddingX={ 4 }> + <Spacer + paddingX={ 4 } + marginBottom={ 0 } + paddingBottom={ 6 } + > <VStack spacing={ 4 }> <FlexItem> <FontSizePreview fontSize={ fontSize } /> From 2b7f43a20b71dd6ac9615fe6a294941f13055bb6 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Sun, 6 Oct 2024 14:37:38 -0500 Subject: [PATCH 1089/1908] Remove orphaned select ref code (#65834) --- .../block-editor/src/components/block-tools/index.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index bad331561317f8..cbcb5b8e50b09a 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -25,7 +25,6 @@ import usePopoverScroll from '../block-popover/use-popover-scroll'; import ZoomOutModeInserters from './zoom-out-mode-inserters'; import { useShowBlockTools } from './use-show-block-tools'; import { unlock } from '../../lock-unlock'; -import getEditorRegion from '../../utils/get-editor-region'; function selector( select ) { const { @@ -83,7 +82,6 @@ export default function BlockTools( { } = useShowBlockTools(); const { - clearSelectedBlock, duplicateBlocks, removeBlocks, replaceBlocks, @@ -95,8 +93,6 @@ export default function BlockTools( { expandBlock, } = unlock( useDispatch( blockEditorStore ) ); - const blockSelectionButtonRef = useRef(); - function onKeyDown( event ) { if ( event.defaultPrevented ) { return; @@ -157,13 +153,6 @@ export default function BlockTools( { // block so that focus is directed back to the beginning of the selection. // In effect, to the user this feels like deselecting the multi-selection. selectBlock( clientIds[ 0 ] ); - } else if ( - clientIds.length === 1 && - event.target === blockSelectionButtonRef?.current - ) { - event.preventDefault(); - clearSelectedBlock(); - getEditorRegion( __unstableContentRef.current )?.focus(); } } else if ( isMatch( 'core/block-editor/collapse-list-view', event ) ) { // If focus is currently within a text field, such as a rich text block or other editable field, From 47adb49f6eda1b3288541c94d95ceccf358ebf18 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 7 Oct 2024 08:58:16 +0100 Subject: [PATCH 1090/1908] Testing: Add an e2e test to check the interactions in write mode (#65819) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../src/components/tool-selector/index.js | 2 + .../src/editor/index.ts | 3 + .../src/editor/switch-editor-tool.ts | 34 +++++ .../editor/various/write-design-mode.spec.js | 116 ++++++++++++++++++ 4 files changed, 155 insertions(+) create mode 100644 packages/e2e-test-utils-playwright/src/editor/switch-editor-tool.ts create mode 100644 test/e2e/specs/editor/various/write-design-mode.spec.js diff --git a/packages/block-editor/src/components/tool-selector/index.js b/packages/block-editor/src/components/tool-selector/index.js index fbbf03af7921a7..d328554f384b77 100644 --- a/packages/block-editor/src/components/tool-selector/index.js +++ b/packages/block-editor/src/components/tool-selector/index.js @@ -78,6 +78,7 @@ function ToolSelector( props, ref ) { </> ), info: __( 'Focus on content.' ), + 'aria-label': __( 'Write' ), }, { value: 'edit', @@ -88,6 +89,7 @@ function ToolSelector( props, ref ) { </> ), info: __( 'Edit layout and styles.' ), + 'aria-label': __( 'Design' ), }, ] } /> diff --git a/packages/e2e-test-utils-playwright/src/editor/index.ts b/packages/e2e-test-utils-playwright/src/editor/index.ts index c222f68aecc90a..4ed32134f0979a 100644 --- a/packages/e2e-test-utils-playwright/src/editor/index.ts +++ b/packages/e2e-test-utils-playwright/src/editor/index.ts @@ -28,6 +28,7 @@ import { saveSiteEditorEntities } from './site-editor'; import { setIsFixedToolbar } from './set-is-fixed-toolbar'; import { switchToLegacyCanvas } from './switch-to-legacy-canvas'; import { transformBlockTo } from './transform-block-to'; +import { switchEditorTool } from './switch-editor-tool'; type EditorConstructorProps = { page: Page; @@ -84,6 +85,8 @@ export class Editor { /** @borrows setIsFixedToolbar as this.setIsFixedToolbar */ setIsFixedToolbar: typeof setIsFixedToolbar = setIsFixedToolbar.bind( this ); + /** @borrows switchEditorTool as this.switchEditorTool */ + switchEditorTool: typeof switchEditorTool = switchEditorTool.bind( this ); /** @borrows switchToLegacyCanvas as this.switchToLegacyCanvas */ switchToLegacyCanvas: typeof switchToLegacyCanvas = switchToLegacyCanvas.bind( this ); diff --git a/packages/e2e-test-utils-playwright/src/editor/switch-editor-tool.ts b/packages/e2e-test-utils-playwright/src/editor/switch-editor-tool.ts new file mode 100644 index 00000000000000..67894abe0dcf7f --- /dev/null +++ b/packages/e2e-test-utils-playwright/src/editor/switch-editor-tool.ts @@ -0,0 +1,34 @@ +/** + * Internal dependencies + */ +import type { Editor } from './index'; + +/** + * Switch the editor tool being used. + * + * @param this + * @param label The text string of the button label. + */ +export async function switchEditorTool( this: Editor, label: string ) { + const toolsToolbar = this.page.getByRole( 'toolbar', { + name: 'Document tools', + } ); + await toolsToolbar + .getByRole( 'button', { + name: 'Tools', + } ) + .click(); + const menu = this.page.getByRole( 'menu', { + name: 'Tools', + } ); + await menu + .getByRole( 'menuitemradio', { + name: label, + } ) + .click(); + await toolsToolbar + .getByRole( 'button', { + name: 'Tools', + } ) + .click(); +} diff --git a/test/e2e/specs/editor/various/write-design-mode.spec.js b/test/e2e/specs/editor/various/write-design-mode.spec.js new file mode 100644 index 00000000000000..635ba17f63ee90 --- /dev/null +++ b/test/e2e/specs/editor/various/write-design-mode.spec.js @@ -0,0 +1,116 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.describe( 'Write/Design mode', () => { + test.beforeEach( async ( { admin, editor } ) => { + await admin.createNewPost(); + await expect( + editor.canvas.getByRole( 'textbox', { name: 'Add title' } ) + ).toBeFocused(); + } ); + + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.deleteAllPosts(); + } ); + + test( 'Should prevent selecting intermediary blocks', async ( { + editor, + page, + } ) => { + // Insert a section with a nested block and an editable block. + await editor.insertBlock( { + name: 'core/group', + attributes: { + style: { + spacing: { + padding: '20px', + }, + color: { + background: 'darkgray', + }, + }, + }, + innerBlocks: [ + { + name: 'core/group', + attributes: { + style: { + spacing: { + padding: '20px', + }, + color: { + background: 'lightgray', + }, + }, + }, + innerBlocks: [ + { + name: 'core/paragraph', + attributes: { + content: 'Something', + }, + }, + ], + }, + ], + } ); + + // Switch to write mode. + await editor.switchEditorTool( 'Write' ); + + const sectionBlock = editor.canvas + .getByRole( 'document', { + name: 'Block: Group', + } ) + .nth( 0 ); + const sectionClientId = await sectionBlock.getAttribute( 'data-block' ); + const nestedGroupBlock = sectionBlock.getByRole( 'document', { + name: 'Block: Group', + } ); + const paragraph = nestedGroupBlock.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + const paragraphClientId = await paragraph.getAttribute( 'data-block' ); + + // We should not be able to select the intermediary group block. + // if we try to click on it (the padding area) + // The selection should land on the top level block. + const nestedGroupPosition = await nestedGroupBlock.boundingBox(); + await page.mouse.click( + nestedGroupPosition.x + 5, + nestedGroupPosition.y + 5 + ); + + const getSelectedBlock = async () => + await page.evaluate( () => + window.wp.data + .select( 'core/block-editor' ) + .getSelectedBlockClientId() + ); + + expect( await getSelectedBlock() ).toEqual( sectionClientId ); + + // We should be able to select the paragraph block and write in it. + await paragraph.click(); + await page.keyboard.type( ' something' ); + expect( await getSelectedBlock() ).toEqual( paragraphClientId ); + await expect( paragraph ).toHaveText( 'Something something' ); + + // Check that the inspector still shows the group block with the content panel. + await editor.openDocumentSettingsSidebar(); + const editorSettings = page.getByRole( 'region', { + name: 'Editor settings', + } ); + await expect( + // Ideally we should be using CSS selectors + // but in this case there's no easy role/label + // to retrieve the "selected block title" + editorSettings.locator( '.block-editor-block-card__title' ) + ).toHaveText( 'Group' ); + await expect( + editorSettings.getByRole( 'button', { name: 'Content' } ) + ).toBeVisible(); + } ); +} ); From d89ebd95fa3e45e7d4272a13b0b4d27eabb885de Mon Sep 17 00:00:00 2001 From: Andrei Draganescu <me@andreidraganescu.info> Date: Mon, 7 Oct 2024 11:58:28 +0300 Subject: [PATCH 1091/1908] Try zooming out when selecting the patterns tab in the inserter (#65785) * adds handler for inserter tabs that engages zoom out view and mode * Only moving to blocks should reset zoom out mode * use hook to handle zoom out view, the hook respects the current zoom out setting --------- Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/block-editor/src/components/inserter/menu.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index 4bc26196cb5243..a32251a1a71d05 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -32,6 +32,7 @@ import InserterSearchResults from './search-results'; import useInsertionPoint from './hooks/use-insertion-point'; import { store as blockEditorStore } from '../../store'; import TabbedSidebar from '../tabbed-sidebar'; +import { useZoomOut } from '../../hooks/use-zoom-out'; const NOOP = () => {}; function InserterMenu( @@ -77,6 +78,10 @@ function InserterMenu( } const [ selectedTab, setSelectedTab ] = useState( getInitialTab() ); + const shouldUseZoomOut = + selectedTab === 'patterns' || selectedTab === 'media'; + useZoomOut( shouldUseZoomOut ); + const [ destinationRootClientId, onInsertBlocks, onToggleInsertionPoint ] = useInsertionPoint( { rootClientId, From f5249b4221d3049d32e1c28f4e8edaa5f454d994 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 7 Oct 2024 11:05:28 +0200 Subject: [PATCH 1092/1908] Fix comment in the select mode e2e test --- test/e2e/specs/editor/various/write-design-mode.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/specs/editor/various/write-design-mode.spec.js b/test/e2e/specs/editor/various/write-design-mode.spec.js index 635ba17f63ee90..443a70ea92f680 100644 --- a/test/e2e/specs/editor/various/write-design-mode.spec.js +++ b/test/e2e/specs/editor/various/write-design-mode.spec.js @@ -104,7 +104,7 @@ test.describe( 'Write/Design mode', () => { name: 'Editor settings', } ); await expect( - // Ideally we should be using CSS selectors + // Ideally we should not be using CSS selectors // but in this case there's no easy role/label // to retrieve the "selected block title" editorSettings.locator( '.block-editor-block-card__title' ) From f1f6c0e66f60e1a010c831121af9d477988713ad Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Mon, 7 Oct 2024 19:45:20 +0900 Subject: [PATCH 1093/1908] Post Content Block: Fix conflict between clearFix and focus ring in the editor (#65364) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- packages/block-library/src/post-content/style.scss | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/block-library/src/post-content/style.scss b/packages/block-library/src/post-content/style.scss index 96e27d04679d44..1d3e210e1210d7 100644 --- a/packages/block-library/src/post-content/style.scss +++ b/packages/block-library/src/post-content/style.scss @@ -1,5 +1,3 @@ -.wp-block-post-content::after { - content: ""; - display: table; - clear: both; +.wp-block-post-content { + display: flow-root; } From 3aa19d28dd46433c6c5677fe76a9e0f500678905 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Mon, 7 Oct 2024 12:55:37 +0200 Subject: [PATCH 1094/1908] Private APIs: remove obsolete try/catch block (#65898) Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- packages/private-apis/src/implementation.js | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/packages/private-apis/src/implementation.js b/packages/private-apis/src/implementation.js index 13ee9873e899de..ab0ebfae7ecb05 100644 --- a/packages/private-apis/src/implementation.js +++ b/packages/private-apis/src/implementation.js @@ -59,18 +59,8 @@ const registeredPrivateApis = []; const requiredConsent = 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.'; -/** @type {boolean} */ -let allowReRegistration; -// The safety measure is meant for WordPress core where IS_WORDPRESS_CORE -// is set to true. -// For the general use-case, the re-registration should be allowed by default -// Let's default to true, then. Try/catch will fall back to "true" even if the -// environment variable is not explicitly defined. -try { - allowReRegistration = globalThis.IS_WORDPRESS_CORE ? false : true; -} catch ( error ) { - allowReRegistration = true; -} +// The safety measure is meant for WordPress core where IS_WORDPRESS_CORE is set to true. +const allowReRegistration = globalThis.IS_WORDPRESS_CORE ? false : true; /** * Called by a @wordpress package wishing to opt-in to accessing or exposing From 3ab6ddec663ac0348143d6afc3b0611b8d8aa2aa Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Mon, 7 Oct 2024 15:17:19 +0300 Subject: [PATCH 1095/1908] Block Editor: use shallow memo for prioritized inserter blocks (#65737) * Block Editor: use shallow memo for prioritized inserter blocks * Add single-pass implementation of useShallowMemo --------- Co-authored-by: Jarda Snajdr <jsnajdr@gmail.com> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../use-nested-settings-update.js | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/components/inner-blocks/use-nested-settings-update.js b/packages/block-editor/src/components/inner-blocks/use-nested-settings-update.js index 8417dec1dd48ff..bc07a5a1829e2b 100644 --- a/packages/block-editor/src/components/inner-blocks/use-nested-settings-update.js +++ b/packages/block-editor/src/components/inner-blocks/use-nested-settings-update.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { useLayoutEffect, useMemo, useState } from '@wordpress/element'; +import { useLayoutEffect, useState } from '@wordpress/element'; import { useRegistry } from '@wordpress/data'; import deprecated from '@wordpress/deprecated'; import isShallowEqual from '@wordpress/is-shallow-equal'; @@ -16,12 +16,21 @@ import { getLayoutType } from '../../layouts'; const pendingSettingsUpdates = new WeakMap(); +// Creates a memoizing caching function that remembers the last value and keeps returning it +// as long as the new values are shallowly equal. Helps keep dependencies stable. +function createShallowMemo() { + let value; + return ( newValue ) => { + if ( value === undefined || ! isShallowEqual( value, newValue ) ) { + value = newValue; + } + return value; + }; +} + function useShallowMemo( value ) { - const [ prevValue, setPrevValue ] = useState( value ); - if ( ! isShallowEqual( prevValue, value ) ) { - setPrevValue( value ); - } - return prevValue; + const [ memo ] = useState( createShallowMemo ); + return memo( value ); } /** @@ -77,10 +86,7 @@ export default function useNestedSettingsUpdate( // otherwise if the arrays change length but the first elements are equal the comparison, // does not works as expected. const _allowedBlocks = useShallowMemo( allowedBlocks ); - - const _prioritizedInserterBlocks = useMemo( - () => prioritizedInserterBlocks, - // eslint-disable-next-line react-hooks/exhaustive-deps + const _prioritizedInserterBlocks = useShallowMemo( prioritizedInserterBlocks ); From 119b627d406f1de72203871a6111e9e5d0d095b1 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 7 Oct 2024 15:27:17 +0200 Subject: [PATCH 1096/1908] Dedupe npm packages (#65913) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- package-lock.json | 1055 ++++++++++++++++++++++++--------------------- 1 file changed, 552 insertions(+), 503 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0de59cfd601aa4..c64e3bcac1e2c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -300,10 +300,11 @@ } }, "node_modules/@actions/http-client": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.1.tgz", - "integrity": "sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", + "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", "dev": true, + "license": "MIT", "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" @@ -3837,9 +3838,9 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", - "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", + "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==", "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -5018,15 +5019,15 @@ } }, "node_modules/@floating-ui/dom/node_modules/@floating-ui/utils": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz", - "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", + "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==", "license": "MIT" }, "node_modules/@floating-ui/react-dom": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", - "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", "dev": true, "license": "MIT", "dependencies": { @@ -5127,10 +5128,11 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -6083,10 +6085,11 @@ } }, "node_modules/@ndelangen/get-tarball/node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -7303,10 +7306,11 @@ } }, "node_modules/@puppeteer/browsers/node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -8684,9 +8688,9 @@ } }, "node_modules/@react-native-community/cli-doctor/node_modules/yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -10327,16 +10331,17 @@ } }, "node_modules/@react-navigation/native/node_modules/@react-navigation/core": { - "version": "6.4.16", - "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.16.tgz", - "integrity": "sha512-UDTJBsHxnzgFETR3ZxhctP+RWr4SkyeZpbhpkQoIGOuwSCkt1SE0qjU48/u6r6w6XlX8OqVudn1Ab0QFXTHxuQ==", + "version": "6.4.17", + "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.17.tgz", + "integrity": "sha512-Nd76EpomzChWAosGqWOYE3ItayhDzIEzzZsT7PfGcRFDgW5miHV2t4MZcq9YIK4tzxZjVVpYbIynOOQQd1e0Cg==", + "license": "MIT", "dependencies": { "@react-navigation/routers": "^6.1.9", "escape-string-regexp": "^4.0.0", "nanoid": "^3.1.23", "query-string": "^7.1.3", "react-is": "^16.13.0", - "use-latest-callback": "^0.1.9" + "use-latest-callback": "^0.2.1" }, "peerDependencies": { "react": "*" @@ -12641,10 +12646,11 @@ } }, "node_modules/@storybook/core-server/node_modules/watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "dev": true, + "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -14242,12 +14248,13 @@ } }, "node_modules/@testing-library/jest-dom/node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "dev": true, - "dependencies": { - "dequal": "^2.0.3" + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" } }, "node_modules/@testing-library/jest-dom/node_modules/chalk": { @@ -14861,9 +14868,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "version": "18.19.54", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.54.tgz", + "integrity": "sha512-+BRgt0G5gYjTvdLac9sIeE0iZcJxi4Jc4PV5EUzqi+88jmQLr+fRZdv2tCTV7IHKSGxM6SaLoOXQWWUiLUItMw==", "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -15242,9 +15249,10 @@ } }, "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "license": "MIT", "dependencies": { "@types/yargs-parser": "*" } @@ -16113,9 +16121,9 @@ } }, "node_modules/@wdio/config/node_modules/type-fest": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.21.0.tgz", - "integrity": "sha512-ADn2w7hVPcK6w1I0uWnM//y1rLXZhzB9mr0a3OirzclKF1Wp6VzevUmzz/NRAWunOT6E8HrnpGY7xOfc6K57fA==", + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -16154,10 +16162,11 @@ } }, "node_modules/@wdio/logger/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -16211,15 +16220,22 @@ } }, "node_modules/@wdio/repl/node_modules/@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "20.16.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, + "node_modules/@wdio/repl/node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, "node_modules/@wdio/types": { "version": "8.16.12", "resolved": "https://registry.npmjs.org/@wdio/types/-/types-8.16.12.tgz", @@ -16233,15 +16249,22 @@ } }, "node_modules/@wdio/types/node_modules/@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "20.16.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, + "node_modules/@wdio/types/node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, "node_modules/@wdio/utils": { "version": "8.16.17", "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.16.17.tgz", @@ -16587,10 +16610,11 @@ } }, "node_modules/@wdio/utils/node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -22442,10 +22466,11 @@ } }, "node_modules/core-js-builder/node_modules/terser-webpack-plugin": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", - "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.6.tgz", + "integrity": "sha512-2lBVf/VMVIddjSn3GqbT90GvIJ/eYXJkt8cTzU7NbjKqK8fwv18Ftr4PlbF46b/e88743iZFL5Dtr/rC4hjIeA==", "dev": true, + "license": "MIT", "dependencies": { "cacache": "^12.0.2", "find-cache-dir": "^2.1.0", @@ -22678,6 +22703,37 @@ "node": ">=4.0" } }, + "node_modules/cross-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", + "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/cross-fetch/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -23062,10 +23118,11 @@ "dev": true }, "node_modules/csso/node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -24771,9 +24828,10 @@ } }, "node_modules/envinfo": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", - "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", + "license": "MIT", "bin": { "envinfo": "dist/cli.js" }, @@ -27127,12 +27185,14 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, + "license": "MIT", "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { @@ -27936,10 +27996,11 @@ } }, "node_modules/geckodriver/node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -28106,10 +28167,11 @@ } }, "node_modules/get-stream/node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -31879,10 +31941,11 @@ } }, "node_modules/jest-watch-typeahead/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -33947,15 +34010,6 @@ "node": ">=12" } }, - "node_modules/lighthouse/node_modules/cross-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", - "dev": true, - "dependencies": { - "node-fetch": "^2.6.12" - } - }, "node_modules/lighthouse/node_modules/devtools-protocol": { "version": "0.0.1155343", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1155343.tgz", @@ -33989,26 +34043,6 @@ "node": ">=8" } }, - "node_modules/lighthouse/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/lighthouse/node_modules/open": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", @@ -35706,10 +35740,11 @@ } }, "node_modules/markdown-builder/node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -36767,9 +36802,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -37126,10 +37161,11 @@ } }, "node_modules/mississippi/node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -40888,9 +40924,9 @@ } }, "node_modules/patch-package/node_modules/yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "dev": true, "license": "ISC", "bin": { @@ -41078,9 +41114,10 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", @@ -42016,9 +42053,10 @@ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" }, "node_modules/postcss/node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -42051,10 +42089,11 @@ } }, "node_modules/prebuild-install/node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "end-of-stream": "^1.1.0", @@ -42513,13 +42552,13 @@ } }, "node_modules/puppeteer-core/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -42614,9 +42653,9 @@ "license": "MIT" }, "node_modules/puppeteer-core/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, @@ -42641,9 +42680,9 @@ } }, "node_modules/puppeteer-core/node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "license": "MIT", "dependencies": { @@ -43343,9 +43382,10 @@ } }, "node_modules/react-native-safe-area/node_modules/@types/react": { - "version": "16.14.60", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.60.tgz", - "integrity": "sha512-wIFmnczGsTcgwCBeIYOuy2mdXEiKZ5znU/jNOnMZPQyCcIxauMGWlX0TNG4lZ7NxRKj7YUIZRneJQSSdB2jKgg==", + "version": "16.14.62", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.62.tgz", + "integrity": "sha512-BWf7hqninZav6nerxXj+NeZT/mTpDeG6Lk2zREHAy63CrnXoOGPGtNqTFYFN/sqpSaREDP5otVV88axIXmKfGA==", + "license": "MIT", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "^0.16", @@ -45889,10 +45929,11 @@ "optional": true }, "node_modules/sharp/node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "end-of-stream": "^1.1.0", @@ -47533,12 +47574,13 @@ } }, "node_modules/stylelint/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -47572,10 +47614,11 @@ } }, "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.0.0.tgz", - "integrity": "sha512-6MgEugi8p2tiUhqO7GnPsmbCCzj0YRCwwaTbpGRyKZesjRSzkqkAE9fPp7V2yMs5hwfgbQLgdvSSkGNg1s5Uvw==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", + "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^5.0.0" }, @@ -47666,15 +47709,16 @@ } }, "node_modules/stylelint/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, "node_modules/stylelint/node_modules/postcss": { - "version": "8.4.41", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", - "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, "funding": [ { @@ -47690,10 +47734,11 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -47727,10 +47772,11 @@ } }, "node_modules/stylelint/node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -47777,10 +47823,11 @@ } }, "node_modules/stylelint/node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -47851,10 +47898,11 @@ } }, "node_modules/supports-hyperlinks": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.0.0.tgz", - "integrity": "sha512-bFhn0MQ8qefLyJ3K7PpHiPUTuTVPWw6RXfaMeV6xgJLXtBbszyboz1bvGTVv4R0YpQm2DqlXXn0fFHhxUHVE5w==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" @@ -47960,10 +48008,11 @@ "dev": true }, "node_modules/svgo/node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -48136,10 +48185,11 @@ } }, "node_modules/tar-fs/node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -48968,9 +49018,9 @@ } }, "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "license": "0BSD" }, "node_modules/tsutils": { @@ -49736,13 +49786,17 @@ "deprecated": "Please see https://github.com/lydell/urix#deprecated" }, "node_modules/url": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", - "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", "dev": true, + "license": "MIT", "dependencies": { "punycode": "^1.4.1", - "qs": "^6.11.2" + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/url-loader": { @@ -49819,9 +49873,9 @@ "dev": true }, "node_modules/url/node_modules/qs": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", - "integrity": "sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -49870,9 +49924,10 @@ } }, "node_modules/use-latest-callback": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.9.tgz", - "integrity": "sha512-CL/29uS74AwreI/f2oz2hLTW7ZqVeV5+gxFeGudzQrgkCytrHw33G4KbnQOrRlAEzzAFXi7dDLMC9zhWcVpzmw==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.2.1.tgz", + "integrity": "sha512-QWlq8Is8BGWBf883QOEQP5HWYX/kMI+JTbJ5rdtvJLmXTIh9XoHIO3PQcmQl8BU44VKxow1kbQUHa6mQSMALDQ==", + "license": "MIT", "peerDependencies": { "react": ">=16.8" } @@ -50510,13 +50565,13 @@ } }, "node_modules/webdriver/node_modules/@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "20.16.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "node_modules/webdriver/node_modules/cacheable-lookup": { @@ -50668,6 +50723,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/webdriver/node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, "node_modules/webdriver/node_modules/ws": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", @@ -50734,22 +50796,23 @@ } }, "node_modules/webdriverio/node_modules/@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "20.16.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "node_modules/webdriverio/node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "dev": true, - "dependencies": { - "dequal": "^2.0.3" + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" } }, "node_modules/webdriverio/node_modules/brace-expansion": { @@ -50761,15 +50824,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/webdriverio/node_modules/cross-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", - "dev": true, - "dependencies": { - "node-fetch": "^2.6.12" - } - }, "node_modules/webdriverio/node_modules/devtools-protocol": { "version": "0.0.1203626", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1203626.tgz", @@ -50804,26 +50858,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/webdriverio/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/webdriverio/node_modules/puppeteer-core": { "version": "20.9.0", "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-20.9.0.tgz", @@ -50882,6 +50916,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/webdriverio/node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, "node_modules/webdriverio/node_modules/ws": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", @@ -51000,9 +51041,9 @@ } }, "node_modules/webpack-bundle-analyzer/node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, "license": "MIT", "dependencies": { @@ -51655,9 +51696,9 @@ } }, "node_modules/webpack/node_modules/enhanced-resolve": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", - "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, "license": "MIT", "dependencies": { @@ -51718,10 +51759,11 @@ } }, "node_modules/webpack/node_modules/watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "dev": true, + "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -51950,10 +51992,11 @@ } }, "node_modules/windows-release/node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -53275,9 +53318,10 @@ "integrity": "sha512-XDbrTSBlQV9nxE1GiDL3FaOPy4G/KaJkhDutBX48Kg8CYZMBARyyDFGCWfWJn4pobmInmwud1xxH7VJMAr0CKQ==" }, "packages/components/node_modules/path-to-regexp": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", - "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==" + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "license": "MIT" }, "packages/components/node_modules/uuid": { "version": "8.3.2", @@ -54099,9 +54143,9 @@ "dev": true }, "packages/env/node_modules/yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "dev": true, "license": "ISC", "bin": { @@ -55188,9 +55232,9 @@ } }, "packages/scripts/node_modules/axios": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", - "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dev": true, "license": "MIT", "dependencies": { @@ -55200,13 +55244,14 @@ } }, "packages/scripts/node_modules/babel-loader": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", - "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.4.1.tgz", + "integrity": "sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==", "dev": true, + "license": "MIT", "dependencies": { "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.0", + "loader-utils": "^2.0.4", "make-dir": "^3.1.0", "schema-utils": "^2.6.5" }, @@ -55641,10 +55686,11 @@ "dev": true }, "packages/stylelint-config/node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -55885,9 +55931,9 @@ } }, "@actions/http-client": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.1.tgz", - "integrity": "sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", + "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", "dev": true, "requires": { "tunnel": "^0.0.6", @@ -58372,9 +58418,9 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "@babel/runtime": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", - "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", + "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==", "requires": { "regenerator-runtime": "^0.14.0" }, @@ -59139,16 +59185,16 @@ }, "dependencies": { "@floating-ui/utils": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz", - "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==" + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", + "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==" } } }, "@floating-ui/react-dom": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", - "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", "dev": true, "requires": { "@floating-ui/dom": "^1.0.0" @@ -59216,9 +59262,9 @@ }, "dependencies": { "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true }, "ansi-styles": { @@ -59955,9 +60001,9 @@ }, "dependencies": { "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -60861,9 +60907,9 @@ "dev": true }, "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -61879,9 +61925,9 @@ } }, "yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==" + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==" } } }, @@ -62897,16 +62943,16 @@ }, "dependencies": { "@react-navigation/core": { - "version": "6.4.16", - "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.16.tgz", - "integrity": "sha512-UDTJBsHxnzgFETR3ZxhctP+RWr4SkyeZpbhpkQoIGOuwSCkt1SE0qjU48/u6r6w6XlX8OqVudn1Ab0QFXTHxuQ==", + "version": "6.4.17", + "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.17.tgz", + "integrity": "sha512-Nd76EpomzChWAosGqWOYE3ItayhDzIEzzZsT7PfGcRFDgW5miHV2t4MZcq9YIK4tzxZjVVpYbIynOOQQd1e0Cg==", "requires": { "@react-navigation/routers": "^6.1.9", "escape-string-regexp": "^4.0.0", "nanoid": "^3.1.23", "query-string": "^7.1.3", "react-is": "^16.13.0", - "use-latest-callback": "^0.1.9" + "use-latest-callback": "^0.2.1" } }, "@react-navigation/routers": { @@ -64619,9 +64665,9 @@ } }, "watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "dev": true, "requires": { "glob-to-regexp": "^0.4.1", @@ -65674,13 +65720,10 @@ }, "dependencies": { "aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "requires": { - "dequal": "^2.0.3" - } + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true }, "chalk": { "version": "3.0.0", @@ -66247,9 +66290,9 @@ } }, "@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "version": "18.19.54", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.54.tgz", + "integrity": "sha512-+BRgt0G5gYjTvdLac9sIeE0iZcJxi4Jc4PV5EUzqi+88jmQLr+fRZdv2tCTV7IHKSGxM6SaLoOXQWWUiLUItMw==", "requires": { "undici-types": "~5.26.4" } @@ -66629,9 +66672,9 @@ } }, "@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "requires": { "@types/yargs-parser": "*" } @@ -67176,9 +67219,9 @@ } }, "type-fest": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.21.0.tgz", - "integrity": "sha512-ADn2w7hVPcK6w1I0uWnM//y1rLXZhzB9mr0a3OirzclKF1Wp6VzevUmzz/NRAWunOT6E8HrnpGY7xOfc6K57fA==", + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", "dev": true }, "yocto-queue": { @@ -67202,9 +67245,9 @@ }, "dependencies": { "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true }, "chalk": { @@ -67240,13 +67283,19 @@ }, "dependencies": { "@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "20.16.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "dev": true, "requires": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } + }, + "undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true } } }, @@ -67260,13 +67309,19 @@ }, "dependencies": { "@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "20.16.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "dev": true, "requires": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } + }, + "undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true } } }, @@ -67511,9 +67566,9 @@ } }, "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -68311,9 +68366,9 @@ "integrity": "sha512-XDbrTSBlQV9nxE1GiDL3FaOPy4G/KaJkhDutBX48Kg8CYZMBARyyDFGCWfWJn4pobmInmwud1xxH7VJMAr0CKQ==" }, "path-to-regexp": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", - "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==" + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==" }, "uuid": { "version": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -68886,9 +68941,9 @@ "dev": true }, "yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "dev": true }, "yargs": { @@ -69535,9 +69590,9 @@ } }, "axios": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", - "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dev": true, "requires": { "follow-redirects": "^1.15.6", @@ -69546,13 +69601,13 @@ } }, "babel-loader": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", - "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.4.1.tgz", + "integrity": "sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==", "dev": true, "requires": { "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.0", + "loader-utils": "^2.0.4", "make-dir": "^3.1.0", "schema-utils": "^2.6.5" }, @@ -69855,9 +69910,9 @@ "dev": true }, "source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true }, "stylelint-config-recommended": { @@ -73912,9 +73967,9 @@ } }, "terser-webpack-plugin": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", - "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.6.tgz", + "integrity": "sha512-2lBVf/VMVIddjSn3GqbT90GvIJ/eYXJkt8cTzU7NbjKqK8fwv18Ftr4PlbF46b/e88743iZFL5Dtr/rC4hjIeA==", "dev": true, "requires": { "cacache": "^12.0.2", @@ -74099,6 +74154,26 @@ "is-windows": "^1.0.0" } }, + "cross-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", + "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "dev": true, + "requires": { + "node-fetch": "^2.6.12" + }, + "dependencies": { + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + } + } + }, "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -74387,9 +74462,9 @@ "dev": true }, "source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true } } @@ -75673,9 +75748,9 @@ "dev": true }, "envinfo": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", - "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==" + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==" }, "equivalent-key-map": { "version": "0.2.2", @@ -77479,12 +77554,13 @@ "dev": true }, "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "requires": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" } }, @@ -78068,9 +78144,9 @@ } }, "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -78190,9 +78266,9 @@ }, "dependencies": { "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -80989,9 +81065,9 @@ "dev": true }, "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true }, "chalk": { @@ -82548,15 +82624,6 @@ "wrap-ansi": "^7.0.0" } }, - "cross-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", - "dev": true, - "requires": { - "node-fetch": "^2.6.12" - } - }, "devtools-protocol": { "version": "0.0.1155343", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1155343.tgz", @@ -82584,15 +82651,6 @@ "is-docker": "^2.0.0" } }, - "node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, "open": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", @@ -83940,9 +83998,9 @@ } }, "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -84805,9 +84863,9 @@ } }, "micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "requires": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -85082,9 +85140,9 @@ }, "dependencies": { "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -87898,9 +87956,9 @@ } }, "yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "dev": true } } @@ -88048,9 +88106,9 @@ "integrity": "sha512-SO+NP5argMoJVCWcYiOofPUeEWDIM47FNCBJtp6uJ8PpjtBcudYJTzCbCMit5dzmfSLCoijzEwIXOqPqD45xQg==" }, "picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" }, "picomatch": { "version": "2.3.1", @@ -88181,9 +88239,9 @@ }, "dependencies": { "source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" } } }, @@ -88721,9 +88779,9 @@ }, "dependencies": { "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "optional": true, "requires": { @@ -89087,12 +89145,12 @@ } }, "debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "emoji-regex": { @@ -89152,9 +89210,9 @@ "dev": true }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "proxy-agent": { @@ -89174,9 +89232,9 @@ } }, "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -89811,9 +89869,9 @@ }, "dependencies": { "@types/react": { - "version": "16.14.60", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.60.tgz", - "integrity": "sha512-wIFmnczGsTcgwCBeIYOuy2mdXEiKZ5znU/jNOnMZPQyCcIxauMGWlX0TNG4lZ7NxRKj7YUIZRneJQSSdB2jKgg==", + "version": "16.14.62", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.62.tgz", + "integrity": "sha512-BWf7hqninZav6nerxXj+NeZT/mTpDeG6Lk2zREHAy63CrnXoOGPGtNqTFYFN/sqpSaREDP5otVV88axIXmKfGA==", "requires": { "@types/prop-types": "*", "@types/scheduler": "^0.16", @@ -91646,9 +91704,9 @@ "optional": true }, "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "optional": true, "requires": { @@ -92905,12 +92963,12 @@ } }, "debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "emoji-regex": { @@ -92933,9 +92991,9 @@ } }, "file-entry-cache": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.0.0.tgz", - "integrity": "sha512-6MgEugi8p2tiUhqO7GnPsmbCCzj0YRCwwaTbpGRyKZesjRSzkqkAE9fPp7V2yMs5hwfgbQLgdvSSkGNg1s5Uvw==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", + "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", "dev": true, "requires": { "flat-cache": "^5.0.0" @@ -93000,20 +93058,20 @@ "dev": true }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "postcss": { - "version": "8.4.41", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", - "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, "requires": { "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" } }, "postcss-value-parser": { @@ -93035,9 +93093,9 @@ "dev": true }, "source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true }, "string-width": { @@ -93072,9 +93130,9 @@ }, "dependencies": { "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true } } @@ -93129,9 +93187,9 @@ } }, "supports-hyperlinks": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.0.0.tgz", - "integrity": "sha512-bFhn0MQ8qefLyJ3K7PpHiPUTuTVPWw6RXfaMeV6xgJLXtBbszyboz1bvGTVv4R0YpQm2DqlXXn0fFHhxUHVE5w==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", "dev": true, "requires": { "has-flag": "^4.0.0", @@ -93209,9 +93267,9 @@ "dev": true }, "source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true } } @@ -93369,9 +93427,9 @@ }, "dependencies": { "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -93979,9 +94037,9 @@ } }, "tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, "tsutils": { "version": "3.21.0", @@ -94572,13 +94630,13 @@ "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==" }, "url": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", - "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", "dev": true, "requires": { "punycode": "^1.4.1", - "qs": "^6.11.2" + "qs": "^6.12.3" }, "dependencies": { "punycode": { @@ -94588,9 +94646,9 @@ "dev": true }, "qs": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", - "integrity": "sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, "requires": { "side-channel": "^1.0.6" @@ -94661,9 +94719,9 @@ } }, "use-latest-callback": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.9.tgz", - "integrity": "sha512-CL/29uS74AwreI/f2oz2hLTW7ZqVeV5+gxFeGudzQrgkCytrHw33G4KbnQOrRlAEzzAFXi7dDLMC9zhWcVpzmw==" + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.2.1.tgz", + "integrity": "sha512-QWlq8Is8BGWBf883QOEQP5HWYX/kMI+JTbJ5rdtvJLmXTIh9XoHIO3PQcmQl8BU44VKxow1kbQUHa6mQSMALDQ==" }, "use-memo-one": { "version": "1.1.1", @@ -95163,12 +95221,12 @@ } }, "@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "20.16.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "dev": true, "requires": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "cacheable-lookup": { @@ -95266,6 +95324,12 @@ "lowercase-keys": "^3.0.0" } }, + "undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true + }, "ws": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", @@ -95307,22 +95371,19 @@ }, "dependencies": { "@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "20.16.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "dev": true, "requires": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "requires": { - "dequal": "^2.0.3" - } + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true }, "brace-expansion": { "version": "2.0.1", @@ -95333,15 +95394,6 @@ "balanced-match": "^1.0.0" } }, - "cross-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", - "dev": true, - "requires": { - "node-fetch": "^2.6.12" - } - }, "devtools-protocol": { "version": "0.0.1203626", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1203626.tgz", @@ -95363,15 +95415,6 @@ "brace-expansion": "^2.0.1" } }, - "node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, "puppeteer-core": { "version": "20.9.0", "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-20.9.0.tgz", @@ -95409,6 +95452,12 @@ "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true }, + "undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true + }, "ws": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", @@ -95602,9 +95651,9 @@ } }, "enhanced-resolve": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", - "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, "requires": { "graceful-fs": "^4.2.4", @@ -95645,9 +95694,9 @@ "dev": true }, "watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "dev": true, "requires": { "glob-to-regexp": "^0.4.1", @@ -95688,9 +95737,9 @@ "dev": true }, "acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, "requires": { "acorn": "^8.11.0" @@ -96195,9 +96244,9 @@ } }, "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "requires": { "end-of-stream": "^1.1.0", From 3214be4cc64b10feb2935da43962480cc562b285 Mon Sep 17 00:00:00 2001 From: Alex Lende <alex+github.com@lende.xyz> Date: Mon, 7 Oct 2024 07:46:03 -0700 Subject: [PATCH 1097/1908] Fix DropZone class names on drop (#65798) Co-authored-by: ajlende <ajlende@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/drop-zone/index.tsx | 3 +-- packages/components/src/drop-zone/style.scss | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index f7f22160c2187b..0bf9776d01a5de 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -18,6 +18,7 @@ - `ToggleGroupControl`: indicator doesn't jump around when the layout around it changes ([#65175](https://github.com/WordPress/gutenberg/pull/65175)). - `Composite`: fix legacy support for the store prop ([#65821](https://github.com/WordPress/gutenberg/pull/65821)). - `Composite`: make items tabbable if active element gets removed ([#65720](https://github.com/WordPress/gutenberg/pull/65720)). +- `DropZone`: fix class names on drop ([#65798](https://github.com/WordPress/gutenberg/pull/65798)). ### Deprecations diff --git a/packages/components/src/drop-zone/index.tsx b/packages/components/src/drop-zone/index.tsx index d0aef35b09d4d6..b1bd0199e877d8 100644 --- a/packages/components/src/drop-zone/index.tsx +++ b/packages/components/src/drop-zone/index.tsx @@ -99,6 +99,7 @@ export function DropZoneComponent( { setType( _type ); }, onDragEnd() { + setIsDraggingOverElement( false ); setIsDraggingOverDocument( false ); setType( undefined ); }, @@ -116,8 +117,6 @@ export function DropZoneComponent( { ( ( type === 'file' && onFilesDrop ) || ( type === 'html' && onHTMLDrop ) || ( type === 'default' && onDrop ) ), - 'has-dragged-out': ! isDraggingOverElement, - // Keeping the following classnames for legacy purposes 'is-dragging-over-document': isDraggingOverDocument, 'is-dragging-over-element': isDraggingOverElement, [ `is-dragging-${ type }` ]: !! type, diff --git a/packages/components/src/drop-zone/style.scss b/packages/components/src/drop-zone/style.scss index d3cd18a75b1f8f..d66eaee87b8a1f 100644 --- a/packages/components/src/drop-zone/style.scss +++ b/packages/components/src/drop-zone/style.scss @@ -42,7 +42,7 @@ transform: scale(0.9); } - &.is-active:not(.has-dragged-out) { + &.is-active.is-dragging-over-element { .components-drop-zone__content { opacity: 1; From 43f0d655213673f730c1c0a2b8d0756017b9b448 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Mon, 7 Oct 2024 19:28:46 +0200 Subject: [PATCH 1098/1908] Update npm lockfile to version 3 (#65923) Set the npm lockfile version to 3. > 3: Only the new lockfile information introduced in npm version 7. > Smaller on disk than lockfile version 2, but not interoperable with > older npm versions. Ideal if all users are on npm version 7 and > higher. https://docs.npmjs.com/cli/v8/using-npm/config#lockfile-version Given the engines and engine-strict setting, npm should always be later than version 7. There should be no downsides to this change. --- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- .npmrc | 1 + package-lock.json | 40821 +------------------------------------------- 2 files changed, 2 insertions(+), 40820 deletions(-) diff --git a/.npmrc b/.npmrc index 7a346f877b9319..84662ee5b78b78 100644 --- a/.npmrc +++ b/.npmrc @@ -2,3 +2,4 @@ save-exact = true engine-strict = true legacy-peer-deps = true prefer-dedupe = true +lockfile-version = 3 diff --git a/package-lock.json b/package-lock.json index c64e3bcac1e2c7..4f52b5ca3e465a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,7 @@ { "name": "gutenberg", "version": "19.4.0-rc.1", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -55887,40824 +55887,5 @@ "npm": ">=8.19.2" } } - }, - "dependencies": { - "@actions/core": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", - "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", - "dev": true, - "requires": { - "@actions/http-client": "^2.0.1", - "uuid": "^8.3.2" - }, - "dependencies": { - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - } - } - }, - "@actions/github": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.0.tgz", - "integrity": "sha512-QvE9eAAfEsS+yOOk0cylLBIO/d6WyWIOvsxxzdrPFaud39G6BOkUwScXZn1iBzQzHyu9SBkkLSWlohDWdsasAQ==", - "dev": true, - "requires": { - "@actions/http-client": "^1.0.11", - "@octokit/core": "^3.4.0", - "@octokit/plugin-paginate-rest": "^2.13.3", - "@octokit/plugin-rest-endpoint-methods": "^5.1.1" - }, - "dependencies": { - "@actions/http-client": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz", - "integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==", - "dev": true, - "requires": { - "tunnel": "0.0.6" - } - } - } - }, - "@actions/http-client": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", - "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", - "dev": true, - "requires": { - "tunnel": "^0.0.6", - "undici": "^5.25.4" - } - }, - "@adobe/css-tools": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", - "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", - "dev": true - }, - "@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@apidevtools/json-schema-ref-parser": { - "version": "11.6.4", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.6.4.tgz", - "integrity": "sha512-9K6xOqeevacvweLGik6LnZCb1fBtCOSIWQs8d096XGeqoLKC33UVMGz9+77Gw44KvbH4pKcQPWo4ZpxkXYj05w==", - "dev": true, - "requires": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.15", - "js-yaml": "^4.1.0" - }, - "dependencies": { - "@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - } - } - }, - "@appium/base-driver": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/@appium/base-driver/-/base-driver-9.4.0.tgz", - "integrity": "sha512-R2RdNQ9eMV++VfdrTjnvriaJnrk+btvgol7DE4wZIvwEZ3IPS0NC4yE6twA77RqEhfGixCUmS82pQVWucEnTpA==", - "dev": true, - "requires": { - "@appium/support": "^4.1.7", - "@appium/types": "^0.14.0", - "@colors/colors": "1.6.0", - "@types/async-lock": "1.4.0", - "@types/bluebird": "3.5.40", - "@types/express": "4.17.19", - "@types/lodash": "4.14.199", - "@types/method-override": "0.0.33", - "@types/serve-favicon": "2.5.5", - "async-lock": "1.4.0", - "asyncbox": "2.9.4", - "axios": "1.5.1", - "bluebird": "3.7.2", - "body-parser": "1.20.2", - "es6-error": "4.1.1", - "express": "4.18.2", - "http-status-codes": "2.3.0", - "lodash": "4.17.21", - "lru-cache": "10.0.1", - "method-override": "3.0.0", - "morgan": "1.10.0", - "path-to-regexp": "6.2.1", - "serve-favicon": "2.5.0", - "source-map-support": "0.5.21", - "spdy": "4.0.2", - "type-fest": "3.13.1", - "validate.js": "0.13.1" - }, - "dependencies": { - "@appium/schema": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@appium/schema/-/schema-0.4.2.tgz", - "integrity": "sha512-b2tC2sKAS8wnw8V7W7Rm6pXFt8QY4NTWvibprVYi1g8rZLnlmlIwUW0Gl6FhrWTUyK+u4rbF8vVIIBIU8C+i/g==", - "dev": true, - "requires": { - "@types/json-schema": "7.0.15", - "json-schema": "0.4.0", - "source-map-support": "0.5.21" - } - }, - "@appium/types": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/@appium/types/-/types-0.14.3.tgz", - "integrity": "sha512-zW/fjn6HqvXLQVvWBX0qjYiWpfWKweXQQxUBO6egtiq77PRbDMkpeVAJIF8fvnng7XdaOo4OTdvADaZxpcgKCw==", - "dev": true, - "requires": { - "@appium/schema": "^0.4.2", - "@appium/tsconfig": "^0.x", - "@types/express": "4.17.21", - "@types/npmlog": "4.1.6", - "@types/ws": "8.5.10", - "type-fest": "3.13.1" - }, - "dependencies": { - "@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - } - } - }, - "@colors/colors": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", - "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", - "dev": true - }, - "@types/bluebird": { - "version": "3.5.40", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.40.tgz", - "integrity": "sha512-4dEtF/qcby/FdT6iChii+jFXzVVX0+5HYiDqHKBtHQ3ZV58x5uVJJYRG0N4QllIaj5a2+UDdf/nupae+/M6mdw==", - "dev": true - }, - "@types/express": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.19.tgz", - "integrity": "sha512-UtOfBtzN9OvpZPPbnnYunfjM7XCI4jyk1NvnFhTVz5krYAnW4o5DCoIekvms+8ApqhB4+9wSge1kBijdfTSmfg==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "@types/npmlog": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-4.1.6.tgz", - "integrity": "sha512-0l3z16vnlJGl2Mi/rgJFrdwfLZ4jfNYgE6ZShEpjqhHuGTqdEzNles03NpYHwUMVYZa+Tj46UxKIEpE78lQ3DQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - } - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", - "dev": true - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "path-to-regexp": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", - "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", - "dev": true - }, - "raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true - } - } - }, - "@appium/base-plugin": { - "version": "2.2.21", - "resolved": "https://registry.npmjs.org/@appium/base-plugin/-/base-plugin-2.2.21.tgz", - "integrity": "sha512-MRQyuS3xC0JQwOV+q5gHWSPH6lA/owgsQqGPyVkZH0OB69lx4mmGvO/9Zuz3kTdONN/QdxI6oo6nEvvty9Kt2A==", - "dev": true, - "requires": { - "@appium/base-driver": "^9.4.0", - "@appium/support": "^4.1.7" - } - }, - "@appium/docutils": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/@appium/docutils/-/docutils-0.4.10.tgz", - "integrity": "sha512-8HOVfNkvAE3wmhj4bbZJOo7xXNyoXD6/5pIR42NMey/to/P+a8OI9msXIT5QiZxrItNzWXnnVqhrPW0r2yDtpQ==", - "dev": true, - "requires": { - "@appium/support": "^4.1.7", - "@appium/tsconfig": "^0.3.2", - "@appium/typedoc-plugin-appium": "^0.6.6", - "@sliphua/lilconfig-ts-loader": "3.2.2", - "@types/which": "3.0.0", - "chalk": "4.1.2", - "consola": "2.15.3", - "diff": "5.1.0", - "figures": "3.2.0", - "find-up": "5.0.0", - "json5": "2.2.3", - "lilconfig": "2.1.0", - "lodash": "4.17.21", - "log-symbols": "4.1.0", - "pkg-dir": "5.0.0", - "read-pkg": "5.2.0", - "semver": "7.5.4", - "source-map-support": "0.5.21", - "teen_process": "2.0.50", - "type-fest": "3.13.1", - "typedoc": "0.23.28", - "typedoc-plugin-markdown": "3.14.0", - "typedoc-plugin-resolve-crossmodule-references": "0.3.3", - "typescript": "5.0.4", - "yaml": "2.3.3", - "yargs": "17.7.2", - "yargs-parser": "21.1.1" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "requires": { - "find-up": "^5.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "teen_process": { - "version": "2.0.50", - "resolved": "https://registry.npmjs.org/teen_process/-/teen_process-2.0.50.tgz", - "integrity": "sha512-DDppkV654MHUqIrZe2M4FK4NmTKxHHHlr/2M9yE0VrsY3iDUsZFbCIBzVEZ9fQ47Cem4JLtUp9ml4FGp3vR+Uw==", - "dev": true, - "requires": { - "bluebird": "3.7.2", - "lodash": "4.17.21", - "shell-quote": "1.8.1", - "source-map-support": "0.5.21" - } - }, - "type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true - }, - "typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yaml": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", - "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, - "@appium/schema": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@appium/schema/-/schema-0.3.1.tgz", - "integrity": "sha512-j1/vldw+De2/X+GG5Iy0Vtv9tAiADXjXGycc+nfttrHZNGATxn16xxEFmuoFFPCT77o4adcBrov8Y8l9+oUB2Q==", - "dev": true, - "requires": { - "@types/json-schema": "7.0.12", - "json-schema": "0.4.0", - "source-map-support": "0.5.21" - } - }, - "@appium/support": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@appium/support/-/support-4.1.7.tgz", - "integrity": "sha512-YcEVF9ix+LPoCcuxUj4P0MigQ7wd3f8OfHllR3dTzRauM9QU7nRt0NGxBtbhtV6YPjWg/mGmt/i/m1bJptKsKA==", - "dev": true, - "requires": { - "@appium/tsconfig": "^0.3.2", - "@appium/types": "^0.14.0", - "@colors/colors": "1.6.0", - "@types/archiver": "5.3.3", - "@types/base64-stream": "1.0.3", - "@types/find-root": "1.1.2", - "@types/jsftp": "2.1.3", - "@types/klaw": "3.0.4", - "@types/lockfile": "1.0.2", - "@types/mv": "2.1.2", - "@types/ncp": "2.0.6", - "@types/npmlog": "4.1.4", - "@types/pluralize": "0.0.31", - "@types/semver": "7.5.3", - "@types/shell-quote": "1.7.2", - "@types/supports-color": "8.1.1", - "@types/teen_process": "2.0.1", - "@types/uuid": "9.0.5", - "@types/which": "3.0.0", - "archiver": "6.0.1", - "axios": "1.5.1", - "base64-stream": "1.0.0", - "bluebird": "3.7.2", - "bplist-creator": "0.1.1", - "bplist-parser": "0.3.2", - "form-data": "4.0.0", - "get-stream": "6.0.1", - "glob": "10.3.10", - "jsftp": "2.1.3", - "klaw": "4.1.0", - "lockfile": "1.0.4", - "lodash": "4.17.21", - "log-symbols": "4.1.0", - "moment": "2.29.4", - "mv": "2.1.1", - "ncp": "2.0.0", - "npmlog": "7.0.1", - "opencv-bindings": "4.5.5", - "pkg-dir": "5.0.0", - "plist": "3.1.0", - "pluralize": "8.0.0", - "read-pkg": "5.2.0", - "resolve-from": "5.0.0", - "sanitize-filename": "1.6.3", - "semver": "7.5.4", - "sharp": "0.32.6", - "shell-quote": "1.8.1", - "source-map-support": "0.5.21", - "supports-color": "8.1.1", - "teen_process": "2.0.50", - "type-fest": "3.13.1", - "uuid": "9.0.1", - "which": "4.0.0", - "yauzl": "2.10.0" - }, - "dependencies": { - "@appium/schema": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@appium/schema/-/schema-0.4.2.tgz", - "integrity": "sha512-b2tC2sKAS8wnw8V7W7Rm6pXFt8QY4NTWvibprVYi1g8rZLnlmlIwUW0Gl6FhrWTUyK+u4rbF8vVIIBIU8C+i/g==", - "dev": true, - "requires": { - "@types/json-schema": "7.0.15", - "json-schema": "0.4.0", - "source-map-support": "0.5.21" - } - }, - "@appium/types": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/@appium/types/-/types-0.14.3.tgz", - "integrity": "sha512-zW/fjn6HqvXLQVvWBX0qjYiWpfWKweXQQxUBO6egtiq77PRbDMkpeVAJIF8fvnng7XdaOo4OTdvADaZxpcgKCw==", - "dev": true, - "requires": { - "@appium/schema": "^0.4.2", - "@appium/tsconfig": "^0.x", - "@types/express": "4.17.21", - "@types/npmlog": "4.1.6", - "@types/ws": "8.5.10", - "type-fest": "3.13.1" - }, - "dependencies": { - "@types/npmlog": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-4.1.6.tgz", - "integrity": "sha512-0l3z16vnlJGl2Mi/rgJFrdwfLZ4jfNYgE6ZShEpjqhHuGTqdEzNles03NpYHwUMVYZa+Tj46UxKIEpE78lQ3DQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - } - } - }, - "@colors/colors": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", - "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", - "dev": true - }, - "@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "@types/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", - "dev": true - }, - "@types/teen_process": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/teen_process/-/teen_process-2.0.1.tgz", - "integrity": "sha512-hSLCkcQa9Ok1Mg0c1NbCJh9km6Gynj/7mHF2wQQNiiugMGkbhGfToZwEW78XRBnlw3784B6C8nsYnVeiU9bEwg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/uuid": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.5.tgz", - "integrity": "sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ==", - "dev": true - }, - "@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "are-we-there-yet": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-4.0.2.tgz", - "integrity": "sha512-ncSWAawFhKMJDTdoAeOV+jyW1VCMj5QIAwULIBV0SSR7B/RLPPEQiknKcg/RIIZlUQrxELpsxMiTUoAQ4sIUyg==", - "dev": true - }, - "bplist-parser": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", - "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", - "dev": true, - "requires": { - "big-integer": "1.6.x" - } - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "gauge": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-5.0.2.tgz", - "integrity": "sha512-pMaFftXPtiGIHCJHdcUUx9Rby/rFT/Kkt3fIIGCs+9PMDIljSyRiqraTlxNtBReJRDfUefpa263RQ3vnp5G/LQ==", - "dev": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^4.0.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - }, - "npmlog": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-7.0.1.tgz", - "integrity": "sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg==", - "dev": true, - "requires": { - "are-we-there-yet": "^4.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^5.0.0", - "set-blocking": "^2.0.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "requires": { - "find-up": "^5.0.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "teen_process": { - "version": "2.0.50", - "resolved": "https://registry.npmjs.org/teen_process/-/teen_process-2.0.50.tgz", - "integrity": "sha512-DDppkV654MHUqIrZe2M4FK4NmTKxHHHlr/2M9yE0VrsY3iDUsZFbCIBzVEZ9fQ47Cem4JLtUp9ml4FGp3vR+Uw==", - "dev": true, - "requires": { - "bluebird": "3.7.2", - "lodash": "4.17.21", - "shell-quote": "1.8.1", - "source-map-support": "0.5.21" - } - }, - "type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true - }, - "which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", - "dev": true, - "requires": { - "isexe": "^3.1.1" - } - } - } - }, - "@appium/tsconfig": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@appium/tsconfig/-/tsconfig-0.3.2.tgz", - "integrity": "sha512-GPJKATPBHbOC1lRX3+mq4wPRHzilEsBDh64TFBa156BtBRPhKi2DoLv38I93gNAWPJ+StwqZ5YMndriuu/8jKQ==", - "dev": true, - "requires": { - "@tsconfig/node14": "14.1.0" - } - }, - "@appium/typedoc-plugin-appium": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/@appium/typedoc-plugin-appium/-/typedoc-plugin-appium-0.6.6.tgz", - "integrity": "sha512-sZwhveCtUti2QPAhHWysE8IJVyT9KLUwLxXUBnvDjamEm8cuJmqQDDW9nPgv6iiw1bz9ankv/VLYI8egIpTl6g==", - "dev": true, - "requires": { - "handlebars": "4.7.8", - "lodash": "4.17.21", - "pluralize": "8.0.0", - "type-fest": "3.13.1" - }, - "dependencies": { - "type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true - } - } - }, - "@appium/types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/@appium/types/-/types-0.13.4.tgz", - "integrity": "sha512-Kly8Bf6x6sbP8zt8+WFI9bIh8W+1N8sf2eBrbAoluk8/875sJe9X4JUSvJSxH6ew/C4Yo1e3J/hVywY5AF19ug==", - "dev": true, - "requires": { - "@appium/schema": "^0.3.1", - "@appium/tsconfig": "^0.3.1", - "@types/express": "4.17.17", - "@types/npmlog": "4.1.4", - "@types/ws": "8.5.5", - "type-fest": "3.13.1" - }, - "dependencies": { - "type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true - } - } - }, - "@ariakit/core": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.9.tgz", - "integrity": "sha512-nV0B/OTK/0iB+P9RC7fudznYZ8eR6rR1F912Zc54e3+wSW5RrRvNOiRxyMrgENidd4R7cCMDw77XJLSBLKgEPQ==" - }, - "@ariakit/test": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@ariakit/test/-/test-0.4.2.tgz", - "integrity": "sha512-WXAAiAyTaHV9klntOB81Y+YHyA5iGxy9wXCmjQOfYK5InsuIour+7TVXICUxn2NF0XD6j6OoEJbCVDJ2Y46xEA==", - "dev": true, - "requires": { - "@ariakit/core": "0.4.9", - "@testing-library/dom": "^8.0.0 || ^9.0.0 || ^10.0.0" - } - }, - "@aw-web-design/x-default-browser": { - "version": "1.4.126", - "resolved": "https://registry.npmjs.org/@aw-web-design/x-default-browser/-/x-default-browser-1.4.126.tgz", - "integrity": "sha512-Xk1sIhyNC/esHGGVjL/niHLowM0csl/kFO5uawBy4IrWwy0o1G8LGt3jP6nmWGz+USxeeqbihAmp/oVZju6wug==", - "dev": true, - "requires": { - "default-browser-id": "3.0.0" - } - }, - "@axe-core/puppeteer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@axe-core/puppeteer/-/puppeteer-4.0.0.tgz", - "integrity": "sha512-APFc2iRmrmUfqdBUevjsMxJliDudWPwvCU5Pzw2uKZ0sMVtW3rQuElTcfJCHFq8KOZSSO0BPD+lK+pXOx1ta5Q==", - "dev": true, - "requires": { - "axe-core": "^4.0.1" - } - }, - "@babel/code-frame": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", - "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", - "requires": { - "@babel/highlight": "^7.24.2", - "picocolors": "^1.0.0" - } - }, - "@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==" - }, - "@babel/core": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", - "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.1", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.1", - "@babel/parser": "^7.24.1", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "dependencies": { - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "@babel/eslint-parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.16.0.tgz", - "integrity": "sha512-c+AsYOHjI+FgCa+ifLd8sDXp4U4mjkfFgL9NdQWhuA731kAUJs0WdJIXET4A14EJAR9Jv9FFF/MzPWJfV9Oirw==", - "dev": true, - "requires": { - "eslint-scope": "^5.1.1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.0" - }, - "dependencies": { - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", - "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", - "requires": { - "@babel/types": "^7.24.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", - "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.15" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", - "requires": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "dependencies": { - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "requires": { - "yallist": "^3.0.2" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - } - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.9.tgz", - "integrity": "sha512-B2L9neXTIyPQoXDm+NtovPvG6VOLWnaXu3BIeVDWwdKFgG30oNa6CqVGiJPDWQwIAK49t9gnQI9c6K6RzabiKw==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "semver": "^6.3.1" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", - "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "regexpu-core": "^5.3.1", - "semver": "^6.3.1" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "@babel/helper-define-polyfill-provider": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.4.tgz", - "integrity": "sha512-OrpPZ97s+aPi6h2n1OXzdhVis1SGSsMU2aMHgLcOKfsp4/v1NWpx3CWT3lBj5eeBq9cDkPkh+YCfdF7O12uNDQ==", - "requires": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" - }, - "@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "requires": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", - "requires": { - "@babel/types": "^7.23.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", - "requires": { - "@babel/types": "^7.22.15" - } - }, - "@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", - "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", - "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==" - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", - "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-wrap-function": "^7.22.20" - } - }, - "@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", - "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5" - } - }, - "@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==" - }, - "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" - }, - "@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==" - }, - "@babel/helper-wrap-function": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", - "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", - "requires": { - "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.15", - "@babel/types": "^7.22.19" - } - }, - "@babel/helpers": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", - "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", - "requires": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0" - } - }, - "@babel/highlight": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", - "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", - "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - } - } - }, - "@babel/parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", - "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==" - }, - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", - "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", - "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.23.3" - } - }, - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", - "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", - "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-export-default-from": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.23.3.tgz", - "integrity": "sha512-Q23MpLZfSGZL1kU7fWqV262q65svLSCIP5kZ/JCW/rKTCm/FrLjpvEd2kfUYMVeHh4QhV/xzyoRAHWrAZJrE3Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-export-default-from": "^7.23.3" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", - "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-default-from": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.23.3.tgz", - "integrity": "sha512-KeENO5ck1IeZ/l2lFZNy+mpobV3D2Zy5C1YFnWm+YuY5mQiAWc4yAp13dqgguwsBsFVLh4LPCEqCa5qW13N+hw==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-flow": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.23.3.tgz", - "integrity": "sha512-YZiAIpkJAwQXBJLIQbRFayR5c+gJ35Vcz3bg954k7cd73zqjvhacJuL9RbrzPz8qPmZdgqP6EUKwy0PCNhaaPA==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-syntax-import-assertions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", - "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-syntax-import-attributes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", - "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", - "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", - "requires": { - "@babel/helper-plugin-utils": "^7.24.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", - "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-async-generator-functions": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz", - "integrity": "sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.20", - "@babel/plugin-syntax-async-generators": "^7.8.4" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", - "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", - "requires": { - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.20" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", - "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", - "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-class-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", - "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-class-static-block": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", - "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", - "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-split-export-declaration": "^7.22.6", - "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" - } - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", - "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.15" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", - "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", - "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", - "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-dynamic-import": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", - "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", - "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-export-namespace-from": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", - "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-transform-flow-strip-types": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.23.3.tgz", - "integrity": "sha512-26/pQTf9nQSNVJCrLB1IkHUKyPxR+lMrH2QDPG89+Znu9rAMbtrybdbWeE9bb7gzjmE5iXHEY+e0HUwM6Co93Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-flow": "^7.23.3" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", - "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", - "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", - "requires": { - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-json-strings": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", - "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-json-strings": "^7.8.3" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", - "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-logical-assignment-operators": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", - "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", - "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", - "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", - "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", - "requires": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz", - "integrity": "sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", - "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", - "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", - "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", - "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - } - }, - "@babel/plugin-transform-numeric-separator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", - "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-transform-object-assign": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.23.3.tgz", - "integrity": "sha512-TPJ6O7gVC2rlQH2hvQGRH273G1xdoloCj9Pc07Q7JbIZYDi+Sv5gaE2fu+r5E7qK4zyt6vj0FbZaZTRU5C3OMA==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-object-rest-spread": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", - "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.23.3", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.23.3" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", - "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20" - } - }, - "@babel/plugin-transform-optional-catch-binding": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", - "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - } - }, - "@babel/plugin-transform-optional-chaining": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", - "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", - "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-private-methods": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", - "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", - "requires": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-private-property-in-object": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", - "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", - "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-react-constant-elements": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.22.5.tgz", - "integrity": "sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-react-display-name": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.23.3.tgz", - "integrity": "sha512-GnvhtVfA2OAtzdX58FJxU19rhoGeQzyVndw3GgtdECQvQFXPEZIOVULHVZGAYmOgmqjXpVpfocAbSjh99V/Fqw==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-react-jsx": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", - "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/types": "^7.23.4" - } - }, - "@babel/plugin-transform-react-jsx-development": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", - "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", - "dev": true, - "requires": { - "@babel/plugin-transform-react-jsx": "^7.22.5" - } - }, - "@babel/plugin-transform-react-jsx-self": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz", - "integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-react-jsx-source": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz", - "integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-react-pure-annotations": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.23.3.tgz", - "integrity": "sha512-qMFdSS+TUhB7Q/3HVPnEdYJDQIk57jkntAwSuz9xfSE4n+3I+vHYCli3HoHawN1Z3RfCz/y1zXA/JXjG6cVImQ==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", - "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "regenerator-transform": "^0.15.2" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", - "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-runtime": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.0.tgz", - "integrity": "sha512-zlPf1/XFn5+vWdve3AAhf+Sxl+MVa5VlwTwWgnLx23u4GlatSRQJ3Eoo9vllf0a9il3woQsT4SK+5Z7c06h8ag==", - "requires": { - "@babel/helper-module-imports": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", - "babel-plugin-polyfill-corejs2": "^0.2.3", - "babel-plugin-polyfill-corejs3": "^0.3.0", - "babel-plugin-polyfill-regenerator": "^0.2.3", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", - "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", - "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", - "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", - "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", - "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-typescript": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz", - "integrity": "sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-typescript": "^7.23.3" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", - "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-unicode-property-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", - "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", - "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-unicode-sets-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", - "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/preset-env": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.9.tgz", - "integrity": "sha512-3kBGTNBBk9DQiPoXYS0g0BYlwTQYUTifqgKTjxUwEUkduRT2QOa0FPGBJ+NROQhGyYO5BuTJwGvBnqKDykac6A==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.23.3", - "@babel/plugin-syntax-import-attributes": "^7.23.3", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.23.3", - "@babel/plugin-transform-async-generator-functions": "^7.23.9", - "@babel/plugin-transform-async-to-generator": "^7.23.3", - "@babel/plugin-transform-block-scoped-functions": "^7.23.3", - "@babel/plugin-transform-block-scoping": "^7.23.4", - "@babel/plugin-transform-class-properties": "^7.23.3", - "@babel/plugin-transform-class-static-block": "^7.23.4", - "@babel/plugin-transform-classes": "^7.23.8", - "@babel/plugin-transform-computed-properties": "^7.23.3", - "@babel/plugin-transform-destructuring": "^7.23.3", - "@babel/plugin-transform-dotall-regex": "^7.23.3", - "@babel/plugin-transform-duplicate-keys": "^7.23.3", - "@babel/plugin-transform-dynamic-import": "^7.23.4", - "@babel/plugin-transform-exponentiation-operator": "^7.23.3", - "@babel/plugin-transform-export-namespace-from": "^7.23.4", - "@babel/plugin-transform-for-of": "^7.23.6", - "@babel/plugin-transform-function-name": "^7.23.3", - "@babel/plugin-transform-json-strings": "^7.23.4", - "@babel/plugin-transform-literals": "^7.23.3", - "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", - "@babel/plugin-transform-member-expression-literals": "^7.23.3", - "@babel/plugin-transform-modules-amd": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-modules-systemjs": "^7.23.9", - "@babel/plugin-transform-modules-umd": "^7.23.3", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.23.3", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", - "@babel/plugin-transform-numeric-separator": "^7.23.4", - "@babel/plugin-transform-object-rest-spread": "^7.23.4", - "@babel/plugin-transform-object-super": "^7.23.3", - "@babel/plugin-transform-optional-catch-binding": "^7.23.4", - "@babel/plugin-transform-optional-chaining": "^7.23.4", - "@babel/plugin-transform-parameters": "^7.23.3", - "@babel/plugin-transform-private-methods": "^7.23.3", - "@babel/plugin-transform-private-property-in-object": "^7.23.4", - "@babel/plugin-transform-property-literals": "^7.23.3", - "@babel/plugin-transform-regenerator": "^7.23.3", - "@babel/plugin-transform-reserved-words": "^7.23.3", - "@babel/plugin-transform-shorthand-properties": "^7.23.3", - "@babel/plugin-transform-spread": "^7.23.3", - "@babel/plugin-transform-sticky-regex": "^7.23.3", - "@babel/plugin-transform-template-literals": "^7.23.3", - "@babel/plugin-transform-typeof-symbol": "^7.23.3", - "@babel/plugin-transform-unicode-escapes": "^7.23.3", - "@babel/plugin-transform-unicode-property-regex": "^7.23.3", - "@babel/plugin-transform-unicode-regex": "^7.23.3", - "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.8", - "babel-plugin-polyfill-corejs3": "^0.9.0", - "babel-plugin-polyfill-regenerator": "^0.5.5", - "core-js-compat": "^3.31.0", - "semver": "^6.3.1" - }, - "dependencies": { - "@babel/helper-define-polyfill-provider": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", - "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - } - }, - "@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true - }, - "babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", - "semver": "^6.3.1" - }, - "dependencies": { - "@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - } - } - } - }, - "babel-plugin-polyfill-corejs3": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz", - "integrity": "sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.5.0", - "core-js-compat": "^3.34.0" - } - }, - "babel-plugin-polyfill-regenerator": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", - "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.5.0" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/preset-flow": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.23.3.tgz", - "integrity": "sha512-7yn6hl8RIv+KNk6iIrGZ+D06VhVY35wLVf23Cz/mMu1zOr7u4MMP4j0nZ9tLf8+4ZFpnib8cFYgB/oYg9hfswA==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-transform-flow-strip-types": "^7.23.3" - } - }, - "@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/preset-react": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.23.3.tgz", - "integrity": "sha512-tbkHOS9axH6Ysf2OUEqoSZ6T3Fa2SrNH6WTWSPBboxKzdxNc9qOICeLXkNG0ZEwbQ1HY8liwOce4aN/Ceyuq6w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-transform-react-display-name": "^7.23.3", - "@babel/plugin-transform-react-jsx": "^7.22.15", - "@babel/plugin-transform-react-jsx-development": "^7.22.5", - "@babel/plugin-transform-react-pure-annotations": "^7.23.3" - } - }, - "@babel/preset-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", - "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-typescript": "^7.23.3" - } - }, - "@babel/register": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.23.7.tgz", - "integrity": "sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==", - "requires": { - "clone-deep": "^4.0.1", - "find-cache-dir": "^2.0.0", - "make-dir": "^2.1.0", - "pirates": "^4.0.6", - "source-map-support": "^0.5.16" - }, - "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" - } - } - }, - "@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" - }, - "@babel/runtime": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", - "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==", - "requires": { - "regenerator-runtime": "^0.14.0" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - } - } - }, - "@babel/runtime-corejs3": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.24.1.tgz", - "integrity": "sha512-T9ko/35G+Bkl+win48GduaPlhSlOjjE5s1TeiEcD+QpxlLQnoEfb/nO/T+TQqkm+ipFwORn+rB8w14iJ/uD0bg==", - "dev": true, - "requires": { - "core-js-pure": "^3.30.2", - "regenerator-runtime": "^0.14.0" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - } - } - }, - "@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", - "requires": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" - } - }, - "@babel/traverse": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", - "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", - "requires": { - "@babel/code-frame": "^7.24.1", - "@babel/generator": "^7.24.1", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.1", - "@babel/types": "^7.24.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" - } - } - }, - "@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", - "requires": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - } - }, - "@base2/pretty-print-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz", - "integrity": "sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==", - "dev": true - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "@callstack/reassure-cli": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@callstack/reassure-cli/-/reassure-cli-0.6.1.tgz", - "integrity": "sha512-c5Pihix9anX9hSLsN8Y5cpRUuB5vHSFeaGAHuiRyNLlEOAIEODjQIOCQ7MkxEiWd5rT5t00m9EMfANb1FcnfiA==", - "dev": true, - "requires": { - "@callstack/reassure-compare": "0.3.0", - "simple-git": "^3.16.0", - "yargs": "^17.6.2" - }, - "dependencies": { - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, - "@callstack/reassure-compare": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@callstack/reassure-compare/-/reassure-compare-0.3.0.tgz", - "integrity": "sha512-1TIUhzZELlXkVJE9wH6qm7IkoLChTsKj7rOE9h86yRX4y4vrSru9cdHwktjsuopQ543YbOxehMMx6tGbefsGBA==", - "dev": true, - "requires": { - "markdown-builder": "^0.9.0", - "markdown-table": "^2.0.0", - "zod": "^3.20.2" - }, - "dependencies": { - "markdown-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", - "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", - "dev": true, - "requires": { - "repeat-string": "^1.0.0" - } - } - } - }, - "@callstack/reassure-danger": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@callstack/reassure-danger/-/reassure-danger-0.1.1.tgz", - "integrity": "sha512-lfza+qBdvVYtP7WvMTT+LfjBfuYsXZ4RxuBldsL8wJArGeCl3OZwUg+9bTo8v6kk/nY8memk5HxrCwWDSO24UA==", - "dev": true - }, - "@callstack/reassure-measure": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@callstack/reassure-measure/-/reassure-measure-0.3.1.tgz", - "integrity": "sha512-A7gdyA9nfm6TZt4bQs5bfgy9SOFn8FmMdOjPojSpmpSyECXRK/7aMqqBIuwPt4jgIFFDiEFsd5w88FgsE13CTQ==", - "dev": true, - "requires": { - "mathjs": "^10.1.1" - } - }, - "@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true - }, - "@csstools/css-parser-algorithms": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.1.tgz", - "integrity": "sha512-lSquqZCHxDfuTg/Sk2hiS0mcSFCEBuj49JfzPHJogDBT0mGCyY5A1AQzBWngitrp7i1/HAZpIgzF/VjhOEIJIg==", - "dev": true - }, - "@csstools/css-tokenizer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.1.tgz", - "integrity": "sha512-UBqaiu7kU0lfvaP982/o3khfXccVlHPWp0/vwwiIgDF0GmqqqxoiXC/6FCjlS9u92f7CoEz6nXKQnrn1kIAkOw==", - "dev": true - }, - "@csstools/media-query-list-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-3.0.1.tgz", - "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==", - "dev": true - }, - "@csstools/selector-specificity": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-4.0.0.tgz", - "integrity": "sha512-189nelqtPd8++phaHNwYovKZI0FOzH1vQEE3QhHHkNIGrg5fSs9CbYP3RvfEH5geztnIA9Jwq91wyOIwAW5JIQ==", - "dev": true - }, - "@dabh/diagnostics": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", - "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", - "dev": true, - "requires": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" - } - }, - "@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true - }, - "@dual-bundle/import-meta-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", - "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", - "dev": true - }, - "@egjs/hammerjs": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", - "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", - "requires": { - "@types/hammerjs": "^2.0.36" - } - }, - "@emotion/babel-plugin": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", - "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", - "requires": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/serialize": "^1.1.2", - "babel-plugin-macros": "^3.1.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^4.0.0", - "find-root": "^1.1.0", - "source-map": "^0.5.7", - "stylis": "4.2.0" - }, - "dependencies": { - "@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" - }, - "stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" - } - } - }, - "@emotion/cache": { - "version": "11.7.1", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.7.1.tgz", - "integrity": "sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A==", - "requires": { - "@emotion/memoize": "^0.7.4", - "@emotion/sheet": "^1.1.0", - "@emotion/utils": "^1.0.0", - "@emotion/weak-memoize": "^0.2.5", - "stylis": "4.0.13" - } - }, - "@emotion/css": { - "version": "11.7.1", - "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.7.1.tgz", - "integrity": "sha512-RUUgPlMZunlc7SE5A6Hg+VWRzb2cU6O9xlV78KCFgcnl25s7Qz/20oQg71iKudpLqk7xj0vhbJlwcJJMT0BOZg==", - "requires": { - "@emotion/babel-plugin": "^11.7.1", - "@emotion/cache": "^11.7.1", - "@emotion/serialize": "^1.0.0", - "@emotion/sheet": "^1.0.3", - "@emotion/utils": "^1.0.0" - } - }, - "@emotion/css-prettifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emotion/css-prettifier/-/css-prettifier-1.0.1.tgz", - "integrity": "sha512-cA9Dtol47mtvWKasPC+8tkh2DS0wBkX0MMHKieXGSkGyx079V7yFY85KC0pPalcIy+vi0LbMR9DNyiJBqYgJ1Q==", - "dev": true, - "requires": { - "@emotion/memoize": "^0.7.4", - "stylis": "4.0.13" - } - }, - "@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" - }, - "@emotion/jest": { - "version": "11.7.1", - "resolved": "https://registry.npmjs.org/@emotion/jest/-/jest-11.7.1.tgz", - "integrity": "sha512-IYKyiIm4a7LINESYTa6aAizRj6YTwIvpD9s9yDzkrOEJXKwCqWWOTVNNOJKBygim3fv4lC9KM5jG5qzHvy4ZJg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@emotion/css-prettifier": "^1.0.1", - "chalk": "^4.1.0", - "specificity": "^0.4.1", - "stylis": "4.0.13" - } - }, - "@emotion/memoize": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz", - "integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==" - }, - "@emotion/native": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@emotion/native/-/native-11.0.0.tgz", - "integrity": "sha512-IByi+OfagLtcQsXZMkS06ztcNMZePg6dqwzM4FIkXjN4PhoeJ/jTDRICT3pTIk3ChuurX2oF8fmE+0bfvYi/SA==", - "dev": true, - "requires": { - "@emotion/primitives-core": "^11.0.0" - } - }, - "@emotion/primitives-core": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@emotion/primitives-core/-/primitives-core-11.0.0.tgz", - "integrity": "sha512-4zpfUV7hz9A+j7Hcyiend3LEtRogDXDtMzQy8LOoU39Mw5ntgvTlYQSPbQSzs98BJty/F9Ybyg3pBzFDdMpmDg==", - "dev": true, - "requires": { - "css-to-react-native": "^3.0.0" - }, - "dependencies": { - "css-to-react-native": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", - "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", - "dev": true, - "requires": { - "camelize": "^1.0.0", - "css-color-keywords": "^1.0.0", - "postcss-value-parser": "^4.0.2" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "@emotion/react": { - "version": "11.7.1", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.7.1.tgz", - "integrity": "sha512-DV2Xe3yhkF1yT4uAUoJcYL1AmrnO5SVsdfvu+fBuS7IbByDeTVx9+wFmvx9Idzv7/78+9Mgx2Hcmr7Fex3tIyw==", - "requires": { - "@babel/runtime": "^7.13.10", - "@emotion/cache": "^11.7.1", - "@emotion/serialize": "^1.0.2", - "@emotion/sheet": "^1.1.0", - "@emotion/utils": "^1.0.0", - "@emotion/weak-memoize": "^0.2.5", - "hoist-non-react-statics": "^3.3.1" - } - }, - "@emotion/serialize": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz", - "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==", - "requires": { - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/unitless": "^0.8.1", - "@emotion/utils": "^1.2.1", - "csstype": "^3.0.2" - }, - "dependencies": { - "@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" - } - } - }, - "@emotion/sheet": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.1.0.tgz", - "integrity": "sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g==" - }, - "@emotion/styled": { - "version": "11.6.0", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.6.0.tgz", - "integrity": "sha512-mxVtVyIOTmCAkFbwIp+nCjTXJNgcz4VWkOYQro87jE2QBTydnkiYusMrRGFtzuruiGK4dDaNORk4gH049iiQuw==", - "requires": { - "@babel/runtime": "^7.13.10", - "@emotion/babel-plugin": "^11.3.0", - "@emotion/is-prop-valid": "^1.1.1", - "@emotion/serialize": "^1.0.2", - "@emotion/utils": "^1.0.0" - }, - "dependencies": { - "@emotion/is-prop-valid": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", - "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", - "requires": { - "@emotion/memoize": "^0.8.1" - } - }, - "@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" - } - } - }, - "@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" - }, - "@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", - "dev": true - }, - "@emotion/utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", - "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" - }, - "@emotion/weak-memoize": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", - "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==" - }, - "@es-joy/jsdoccomment": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.40.1.tgz", - "integrity": "sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==", - "dev": true, - "requires": { - "comment-parser": "1.4.0", - "esquery": "^1.5.0", - "jsdoc-type-pratt-parser": "~4.0.0" - } - }, - "@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "dev": true, - "optional": true - }, - "@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "dev": true, - "optional": true - }, - "@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "dev": true, - "optional": true - }, - "@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "dev": true, - "optional": true - }, - "@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "dev": true, - "optional": true - }, - "@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "dev": true, - "optional": true - }, - "@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "dev": true, - "optional": true - }, - "@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "dev": true, - "optional": true - }, - "@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "dev": true, - "optional": true - }, - "@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "dev": true, - "optional": true - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - } - } - }, - "@eslint-community/regexpp": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", - "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz", - "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.0.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - } - } - }, - "@fal-works/esbuild-plugin-global-externals": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@fal-works/esbuild-plugin-global-externals/-/esbuild-plugin-global-externals-2.1.2.tgz", - "integrity": "sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==", - "dev": true - }, - "@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "dev": true - }, - "@floating-ui/core": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.4.1.tgz", - "integrity": "sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==", - "requires": { - "@floating-ui/utils": "^0.1.1" - } - }, - "@floating-ui/dom": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz", - "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==", - "requires": { - "@floating-ui/core": "^1.0.0", - "@floating-ui/utils": "^0.2.0" - }, - "dependencies": { - "@floating-ui/utils": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", - "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==" - } - } - }, - "@floating-ui/react-dom": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", - "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", - "dev": true, - "requires": { - "@floating-ui/dom": "^1.0.0" - } - }, - "@floating-ui/utils": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", - "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==" - }, - "@geometricpanda/storybook-addon-badges": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@geometricpanda/storybook-addon-badges/-/storybook-addon-badges-2.0.1.tgz", - "integrity": "sha512-dCEK/xJewuFe1d+ndF0hQIAJRnUsV9q5kuDmp7zvO7fTd7cDz0X9Bjz0lNRn6n4Z9bL9/iFHKzJESDHFfs4ihQ==", - "dev": true - }, - "@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" - }, - "@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@humanwhocodes/config-array": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", - "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@hutson/parse-repository-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", - "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", - "dev": true - }, - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } - } - }, - "@isaacs/ttlcache": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", - "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==" - }, - "@istanbuljs/load-nyc-config": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", - "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jest/console": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz", - "integrity": "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==", - "dev": true, - "requires": { - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2", - "slash": "^3.0.0" - } - }, - "@jest/core": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz", - "integrity": "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==", - "dev": true, - "requires": { - "@jest/console": "^29.6.2", - "@jest/reporters": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.6.2", - "jest-haste-map": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.2", - "jest-resolve-dependencies": "^29.6.2", - "jest-runner": "^29.6.2", - "jest-runtime": "^29.6.2", - "jest-snapshot": "^29.6.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", - "jest-watcher": "^29.6.2", - "micromatch": "^4.0.4", - "pretty-format": "^29.6.2", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "@jest/create-cache-key-function": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", - "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", - "requires": { - "@jest/types": "^29.6.3" - } - }, - "@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "requires": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - } - }, - "@jest/expect": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz", - "integrity": "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==", - "dev": true, - "requires": { - "expect": "^29.6.2", - "jest-snapshot": "^29.6.2" - } - }, - "@jest/expect-utils": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz", - "integrity": "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==", - "dev": true, - "requires": { - "jest-get-type": "^29.4.3" - } - }, - "@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "requires": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "dependencies": { - "jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - } - } - }, - "@jest/globals": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz", - "integrity": "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==", - "dev": true, - "requires": { - "@jest/environment": "^29.6.2", - "@jest/expect": "^29.6.2", - "@jest/types": "^29.6.1", - "jest-mock": "^29.6.2" - } - }, - "@jest/reporters": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz", - "integrity": "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2", - "jest-worker": "^29.6.2", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/source-map": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", - "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - } - }, - "@jest/test-result": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz", - "integrity": "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==", - "dev": true, - "requires": { - "@jest/console": "^29.6.2", - "@jest/types": "^29.6.1", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz", - "integrity": "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==", - "dev": true, - "requires": { - "@jest/test-result": "^29.6.2", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", - "slash": "^3.0.0" - } - }, - "@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "dependencies": { - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - } - } - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "requires": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" - }, - "@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" - }, - "@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" - }, - "@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "@jsdevtools/ono": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", - "dev": true - }, - "@juggle/resize-observer": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", - "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", - "dev": true - }, - "@kwsites/file-exists": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "dev": true, - "requires": { - "debug": "^4.1.1" - } - }, - "@kwsites/promise-deferred": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", - "dev": true - }, - "@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true - }, - "@lerna/child-process": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@lerna/child-process/-/child-process-7.1.4.tgz", - "integrity": "sha512-cSiMDx9oI9vvVT+V/WHcbqrksNoc9PIPFiks1lPS7zrVWkEbgA6REQyYmRd2H71kihzqhX5TJ20f2dWv6oEPdA==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "execa": "^5.0.0", - "strong-log-transformer": "^2.1.0" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@lerna/create": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@lerna/create/-/create-7.1.4.tgz", - "integrity": "sha512-D5YWXsXIxWb1aGqcbtttczg86zMzkNhcs00/BleFNxdNYlTRdjLIReELOGBGrq3Hij05UN+7Dv9EKnPFJVbqAw==", - "dev": true, - "requires": { - "@lerna/child-process": "7.1.4", - "dedent": "0.7.0", - "fs-extra": "^11.1.1", - "init-package-json": "5.0.0", - "npm-package-arg": "8.1.1", - "p-reduce": "^2.1.0", - "pacote": "^15.2.0", - "pify": "5.0.0", - "semver": "^7.3.4", - "slash": "^3.0.0", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "5.0.0", - "yargs-parser": "20.2.4" - }, - "dependencies": { - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "hosted-git-info": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", - "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "npm-package-arg": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.1.tgz", - "integrity": "sha512-CsP95FhWQDwNqiYS+Q0mZ7FAEDytDZAkNxQqea6IaAFJTAY9Lhhqyl0irU/6PMc7BGfUmnsbHcqxJD7XuVM/rg==", - "dev": true, - "requires": { - "hosted-git-info": "^3.0.6", - "semver": "^7.0.0", - "validate-npm-package-name": "^3.0.0" - }, - "dependencies": { - "validate-npm-package-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", - "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", - "dev": true, - "requires": { - "builtins": "^1.0.3" - } - } - } - }, - "pify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", - "dev": true - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - }, - "validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "dev": true, - "requires": { - "builtins": "^5.0.0" - }, - "dependencies": { - "builtins": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", - "integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==", - "dev": true, - "requires": { - "semver": "^7.0.0" - } - } - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "@mdx-js/react": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.3.0.tgz", - "integrity": "sha512-zQH//gdOmuu7nt2oJR29vFhDv88oGPmVw6BggmrHeMI+xgEkp1B2dX9/bMBSYtK0dyLX/aOmesKS09g222K1/g==", - "dev": true, - "requires": { - "@types/mdx": "^2.0.0", - "@types/react": ">=16" - } - }, - "@ndelangen/get-tarball": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@ndelangen/get-tarball/-/get-tarball-3.0.9.tgz", - "integrity": "sha512-9JKTEik4vq+yGosHYhZ1tiH/3WpUS0Nh0kej4Agndhox8pAdWhEx5knFVRcb/ya9knCRCs1rPxNrSXTDdfVqpA==", - "dev": true, - "requires": { - "gunzip-maybe": "^1.4.2", - "pump": "^3.0.0", - "tar-fs": "^2.1.1" - }, - "dependencies": { - "pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.2.tgz", - "integrity": "sha512-wrIBsjA5pl13f0RN4Zx4FNWmU71lv03meGKnqRUoCyan17s4V3WL92f3w3AIuWbNnpcrQyFBU5qMavJoB8d27w==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.2", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.2.tgz", - "integrity": "sha512-z8+wGWV2dgUhLqrtRYa03yDx4HWMvXKi1z8g3m2JyxAx8F7xk74asqPk5LAETjqDSGLFML/6CDl0+yFunSYicw==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.3.tgz", - "integrity": "sha512-l6t8xEhfK9Sa4YO5mIRdau7XSOADfmh3jCr0evNHdY+HNkW6xuQhgMH7D73VV6WpZOagrW0UludvMTiifiwTfA==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.2", - "fastq": "^1.6.0" - } - }, - "@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", - "dev": true, - "requires": { - "semver": "^7.3.5" - } - }, - "@npmcli/git": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", - "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", - "dev": true, - "requires": { - "@npmcli/promise-spawn": "^6.0.0", - "lru-cache": "^7.4.4", - "npm-pick-manifest": "^8.0.0", - "proc-log": "^3.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^3.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@npmcli/installed-package-contents": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", - "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", - "dev": true, - "requires": { - "npm-bundled": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "dependencies": { - "npm-bundled": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.1.tgz", - "integrity": "sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==", - "dev": true, - "requires": { - "npm-normalize-package-bin": "^3.0.0" - } - }, - "npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", - "dev": true - } - } - }, - "@npmcli/node-gyp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", - "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", - "dev": true - }, - "@npmcli/promise-spawn": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", - "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", - "dev": true, - "requires": { - "which": "^3.0.0" - }, - "dependencies": { - "which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@npmcli/run-script": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz", - "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==", - "dev": true, - "requires": { - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/promise-spawn": "^6.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^3.0.0", - "which": "^3.0.0" - }, - "dependencies": { - "which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@nrwl/devkit": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-16.6.0.tgz", - "integrity": "sha512-xZEN6wfA1uJwv+FVRQFOHsCcpvGvIYGx2zutbzungDodWkfzlJ3tzIGqYjIpPCBVT83erM6Gscnka2W46AuKfA==", - "dev": true, - "requires": { - "@nx/devkit": "16.6.0" - } - }, - "@nrwl/tao": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-16.6.0.tgz", - "integrity": "sha512-NQkDhmzlR1wMuYzzpl4XrKTYgyIzELdJ+dVrNKf4+p4z5WwKGucgRBj60xMQ3kdV25IX95/fmMDB8qVp/pNQ0Q==", - "dev": true, - "requires": { - "nx": "16.6.0", - "tslib": "^2.3.0" - } - }, - "@nx/devkit": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-16.6.0.tgz", - "integrity": "sha512-rhJ0y+MSPHDuoZPxsOYdj/n5ks+gK74TIMgTb8eZgPT/uR86a4oxf62wUQXgECedR5HzLE2HunbnoLhhJXmpJw==", - "dev": true, - "requires": { - "@nrwl/devkit": "16.6.0", - "ejs": "^3.1.7", - "ignore": "^5.0.4", - "semver": "7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "@nx/nx-darwin-arm64": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-16.6.0.tgz", - "integrity": "sha512-8nJuqcWG/Ob39rebgPLpv2h/V46b9Rqqm/AGH+bYV9fNJpxgMXclyincbMIWvfYN2tW+Vb9DusiTxV6RPrLapA==", - "dev": true, - "optional": true - }, - "@nx/nx-darwin-x64": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-16.6.0.tgz", - "integrity": "sha512-T4DV0/2PkPZjzjmsmQEyjPDNBEKc4Rhf7mbIZlsHXj27BPoeNjEcbjtXKuOZHZDIpGFYECGT/sAF6C2NVYgmxw==", - "dev": true, - "optional": true - }, - "@nx/nx-freebsd-x64": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-16.6.0.tgz", - "integrity": "sha512-Ck/yejYgp65dH9pbExKN/X0m22+xS3rWF1DBr2LkP6j1zJaweRc3dT83BWgt5mCjmcmZVk3J8N01AxULAzUAqA==", - "dev": true, - "optional": true - }, - "@nx/nx-linux-arm-gnueabihf": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-16.6.0.tgz", - "integrity": "sha512-eyk/R1mBQ3X0PCSS+Cck3onvr3wmZVmM/+x0x9Ai02Vm6q9Eq6oZ1YtZGQsklNIyw1vk2WV9rJCStfu9mLecEw==", - "dev": true, - "optional": true - }, - "@nx/nx-linux-arm64-gnu": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-16.6.0.tgz", - "integrity": "sha512-S0qFFdQFDmBIEZqBAJl4K47V3YuMvDvthbYE0enXrXApWgDApmhtxINXSOjSus7DNq9kMrgtSDGkBmoBot61iw==", - "dev": true, - "optional": true - }, - "@nx/nx-linux-arm64-musl": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-16.6.0.tgz", - "integrity": "sha512-TXWY5VYtg2wX/LWxyrUkDVpqCyJHF7fWoVMUSlFe+XQnk9wp/yIbq2s0k3h8I4biYb6AgtcVqbR4ID86lSNuMA==", - "dev": true, - "optional": true - }, - "@nx/nx-linux-x64-gnu": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-16.6.0.tgz", - "integrity": "sha512-qQIpSVN8Ij4oOJ5v+U+YztWJ3YQkeCIevr4RdCE9rDilfq9RmBD94L4VDm7NRzYBuQL8uQxqWzGqb7ZW4mfHpw==", - "dev": true, - "optional": true - }, - "@nx/nx-linux-x64-musl": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-16.6.0.tgz", - "integrity": "sha512-EYOHe11lfVfEfZqSAIa1c39mx2Obr4mqd36dBZx+0UKhjrcmWiOdsIVYMQSb3n0TqB33BprjI4p9ZcFSDuoNbA==", - "dev": true, - "optional": true - }, - "@nx/nx-win32-arm64-msvc": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-16.6.0.tgz", - "integrity": "sha512-f1BmuirOrsAGh5+h/utkAWNuqgohvBoekQgMxYcyJxSkFN+pxNG1U68P59Cidn0h9mkyonxGVCBvWwJa3svVFA==", - "dev": true, - "optional": true - }, - "@nx/nx-win32-x64-msvc": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-16.6.0.tgz", - "integrity": "sha512-UmTTjFLpv4poVZE3RdUHianU8/O9zZYBiAnTRq5spwSDwxJHnLTZBUxFFf3ztCxeHOUIfSyW9utpGfCMCptzvQ==", - "dev": true, - "optional": true - }, - "@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3" - } - }, - "@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "dev": true, - "requires": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dev": true, - "requires": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true - }, - "universal-user-agent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", - "dev": true - } - } - }, - "@octokit/endpoint": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-5.5.3.tgz", - "integrity": "sha512-EzKwkwcxeegYYah5ukEeAI/gYRLv2Y9U5PpIsseGSFDk+G3RbipQGBs8GuYS1TLCtQaqoO66+aQGtITPalxsNQ==", - "dev": true, - "requires": { - "@octokit/types": "^2.0.0", - "is-plain-object": "^3.0.0", - "universal-user-agent": "^5.0.0" - }, - "dependencies": { - "@octokit/types": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", - "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", - "dev": true, - "requires": { - "@types/node": ">= 8" - } - }, - "is-plain-object": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", - "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", - "dev": true - }, - "universal-user-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-5.0.0.tgz", - "integrity": "sha512-B5TPtzZleXyPrUMKCpEHFmVhMN6EhmJYjG5PQna9s7mXeSqGTLap4OpqLl5FCEFUI3UBmllkETwKf/db66Y54Q==", - "dev": true, - "requires": { - "os-name": "^3.1.0" - } - } - } - }, - "@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "dev": true, - "requires": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dev": true, - "requires": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "universal-user-agent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", - "dev": true - } - } - }, - "@octokit/openapi-types": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", - "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==", - "dev": true - }, - "@octokit/plugin-enterprise-rest": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz", - "integrity": "sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==", - "dev": true - }, - "@octokit/plugin-paginate-rest": { - "version": "2.21.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", - "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", - "dev": true, - "requires": { - "@octokit/types": "^6.40.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", - "dev": true - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dev": true, - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - } - } - }, - "@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", - "dev": true - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", - "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", - "dev": true, - "requires": { - "@octokit/types": "^6.39.0", - "deprecation": "^2.3.1" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", - "dev": true - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dev": true, - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - } - } - }, - "@octokit/request": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-4.1.1.tgz", - "integrity": "sha512-LOyL0i3oxRo418EXRSJNk/3Q4I0/NKawTn6H/CQp+wnrG1UFLGu080gSsgnWobhPo5BpUNgSQ5BRk5FOOJhD1Q==", - "dev": true, - "requires": { - "@octokit/endpoint": "^5.1.0", - "@octokit/request-error": "^1.0.1", - "deprecation": "^2.0.0", - "is-plain-object": "^3.0.0", - "node-fetch": "^2.3.0", - "once": "^1.4.0", - "universal-user-agent": "^2.1.0" - }, - "dependencies": { - "@octokit/request-error": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.2.1.tgz", - "integrity": "sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA==", - "dev": true, - "requires": { - "@octokit/types": "^2.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/types": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", - "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", - "dev": true, - "requires": { - "@types/node": ">= 8" - } - }, - "is-plain-object": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", - "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", - "dev": true - } - } - }, - "@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/rest": { - "version": "16.26.0", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.26.0.tgz", - "integrity": "sha512-NBpzre44ZAQWZhlH+zUYTgqI0pHN+c9rNj4d+pCydGEiKTGc1HKmoTghEUyr9GxazDyoAvmpx9nL0I7QS1Olvg==", - "dev": true, - "requires": { - "@octokit/request": "^4.0.1", - "@octokit/request-error": "^1.0.2", - "atob-lite": "^2.0.0", - "before-after-hook": "^1.4.0", - "btoa-lite": "^1.0.0", - "deprecation": "^2.0.0", - "lodash.get": "^4.4.2", - "lodash.set": "^4.3.2", - "lodash.uniq": "^4.5.0", - "octokit-pagination-methods": "^1.1.0", - "once": "^1.4.0", - "universal-user-agent": "^2.0.0", - "url-template": "^2.0.8" - }, - "dependencies": { - "@octokit/request-error": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.2.1.tgz", - "integrity": "sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA==", - "dev": true, - "requires": { - "@octokit/types": "^2.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/types": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", - "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", - "dev": true, - "requires": { - "@types/node": ">= 8" - } - } - } - }, - "@octokit/tsconfig": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", - "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", - "dev": true - }, - "@octokit/types": { - "version": "6.34.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", - "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", - "dev": true, - "requires": { - "@octokit/openapi-types": "^11.2.0" - } - }, - "@octokit/webhooks-methods": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-2.0.0.tgz", - "integrity": "sha512-35cfQ4YWlnZnmZKmIxlGPUPLtbkF8lr/A/1Sk1eC0ddLMwQN06dOuLc+dI3YLQS+T+MoNt3DIQ0NynwgKPilig==", - "dev": true - }, - "@octokit/webhooks-types": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-5.8.0.tgz", - "integrity": "sha512-8adktjIb76A7viIdayQSFuBEwOzwhDC+9yxZpKNHjfzrlostHCw0/N7JWpWMObfElwvJMk2fY2l1noENCk9wmw==", - "dev": true - }, - "@parcel/watcher": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.4.tgz", - "integrity": "sha512-cTDi+FUDBIUOBKEtj+nhiJ71AZVlkAsQFuGQTun5tV9mwQBQgZvhCzG+URPQc8myeN32yRVZEfVAPCs1RW+Jvg==", - "dev": true, - "requires": { - "node-addon-api": "^3.2.1", - "node-gyp-build": "^4.3.0" - } - }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true - }, - "@pkgr/utils": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", - "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "fast-glob": "^3.3.0", - "is-glob": "^4.0.3", - "open": "^9.1.0", - "picocolors": "^1.0.0", - "tslib": "^2.6.0" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true - }, - "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "open": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", - "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", - "dev": true, - "requires": { - "default-browser": "^4.0.0", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@playwright/test": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.0.tgz", - "integrity": "sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA==", - "dev": true, - "requires": { - "playwright": "1.47.0" - } - }, - "@pmmmwh/react-refresh-webpack-plugin": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.11.tgz", - "integrity": "sha512-7j/6vdTym0+qZ6u4XbSAxrWBGYSdCfTzySkj7WAFgDLmSyWlOrWvpyzxlFh5jtw9dn0oL/jtW+06XfFiisN3JQ==", - "dev": true, - "requires": { - "ansi-html-community": "^0.0.8", - "common-path-prefix": "^3.0.0", - "core-js-pure": "^3.23.3", - "error-stack-parser": "^2.0.6", - "find-up": "^5.0.0", - "html-entities": "^2.1.0", - "loader-utils": "^2.0.4", - "schema-utils": "^3.0.0", - "source-map": "^0.7.3" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true - } - } - }, - "@polka/url": { - "version": "1.0.0-next.23", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", - "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==", - "dev": true - }, - "@preact/signals-core": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.4.0.tgz", - "integrity": "sha512-5iYoZBhELLIhUQceZI7sDTQWPb+xcVSn2qk8T/aNl/VMh+A4AiPX9YRSh4XO7fZ6pncrVxl1Iln82poVqYVbbw==" - }, - "@puppeteer/browsers": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.4.6.tgz", - "integrity": "sha512-x4BEjr2SjOPowNeiguzjozQbsc6h437ovD/wu+JpaenxVLm3jkgzHY2xOslMTp50HoTvQreMjiexiGQw1sqZlQ==", - "dev": true, - "requires": { - "debug": "4.3.4", - "extract-zip": "2.0.1", - "progress": "2.0.3", - "proxy-agent": "6.3.0", - "tar-fs": "3.0.4", - "unbzip2-stream": "1.4.3", - "yargs": "17.7.1" - }, - "dependencies": { - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "requires": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "tar-fs": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", - "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", - "dev": true, - "requires": { - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - } - }, - "tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, - "requires": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, - "@radix-ui/number": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz", - "integrity": "sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10" - } - }, - "@radix-ui/primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", - "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", - "requires": { - "@babel/runtime": "^7.13.10" - } - }, - "@radix-ui/react-arrow": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", - "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - } - }, - "@radix-ui/react-collection": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", - "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-slot": "1.0.2" - } - }, - "@radix-ui/react-compose-refs": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", - "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", - "requires": { - "@babel/runtime": "^7.13.10" - } - }, - "@radix-ui/react-context": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", - "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", - "requires": { - "@babel/runtime": "^7.13.10" - } - }, - "@radix-ui/react-direction": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz", - "integrity": "sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10" - } - }, - "@radix-ui/react-dismissable-layer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.4.tgz", - "integrity": "sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-escape-keydown": "1.0.3" - } - }, - "@radix-ui/react-focus-guards": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", - "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", - "requires": { - "@babel/runtime": "^7.13.10" - } - }, - "@radix-ui/react-focus-scope": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.3.tgz", - "integrity": "sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1" - } - }, - "@radix-ui/react-id": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", - "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-layout-effect": "1.0.1" - } - }, - "@radix-ui/react-popper": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.2.tgz", - "integrity": "sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1", - "@radix-ui/react-use-rect": "1.0.1", - "@radix-ui/react-use-size": "1.0.1", - "@radix-ui/rect": "1.0.1" - } - }, - "@radix-ui/react-portal": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.3.tgz", - "integrity": "sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - } - }, - "@radix-ui/react-primitive": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", - "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-slot": "1.0.2" - } - }, - "@radix-ui/react-roving-focus": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", - "integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-collection": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-controllable-state": "1.0.1" - } - }, - "@radix-ui/react-select": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-1.2.2.tgz", - "integrity": "sha512-zI7McXr8fNaSrUY9mZe4x/HC0jTLY9fWNhO1oLWYMQGDXuV4UCivIGTxwioSzO0ZCYX9iSLyWmAh/1TOmX3Cnw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/number": "1.0.1", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-collection": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-dismissable-layer": "1.0.4", - "@radix-ui/react-focus-guards": "1.0.1", - "@radix-ui/react-focus-scope": "1.0.3", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-popper": "1.1.2", - "@radix-ui/react-portal": "1.0.3", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-slot": "1.0.2", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-controllable-state": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1", - "@radix-ui/react-use-previous": "1.0.1", - "@radix-ui/react-visually-hidden": "1.0.3", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.5.5" - } - }, - "@radix-ui/react-separator": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.0.3.tgz", - "integrity": "sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - } - }, - "@radix-ui/react-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", - "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1" - } - }, - "@radix-ui/react-toggle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.0.3.tgz", - "integrity": "sha512-Pkqg3+Bc98ftZGsl60CLANXQBBQ4W3mTFS9EJvNxKMZ7magklKV69/id1mlAlOFDDfHvlCms0fx8fA4CMKDJHg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-controllable-state": "1.0.1" - } - }, - "@radix-ui/react-toggle-group": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.0.4.tgz", - "integrity": "sha512-Uaj/M/cMyiyT9Bx6fOZO0SAG4Cls0GptBWiBmBxofmDbNVnYYoyRWj/2M/6VCi/7qcXFWnHhRUfdfZFvvkuu8A==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-roving-focus": "1.0.4", - "@radix-ui/react-toggle": "1.0.3", - "@radix-ui/react-use-controllable-state": "1.0.1" - } - }, - "@radix-ui/react-toolbar": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toolbar/-/react-toolbar-1.0.4.tgz", - "integrity": "sha512-tBgmM/O7a07xbaEkYJWYTXkIdU/1pW4/KZORR43toC/4XWyBCURK0ei9kMUdp+gTPPKBgYLxXmRSH1EVcIDp8Q==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-roving-focus": "1.0.4", - "@radix-ui/react-separator": "1.0.3", - "@radix-ui/react-toggle-group": "1.0.4" - } - }, - "@radix-ui/react-use-callback-ref": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", - "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", - "requires": { - "@babel/runtime": "^7.13.10" - } - }, - "@radix-ui/react-use-controllable-state": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", - "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-callback-ref": "1.0.1" - } - }, - "@radix-ui/react-use-escape-keydown": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", - "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-callback-ref": "1.0.1" - } - }, - "@radix-ui/react-use-layout-effect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", - "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", - "requires": { - "@babel/runtime": "^7.13.10" - } - }, - "@radix-ui/react-use-previous": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.0.1.tgz", - "integrity": "sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10" - } - }, - "@radix-ui/react-use-rect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", - "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/rect": "1.0.1" - } - }, - "@radix-ui/react-use-size": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz", - "integrity": "sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-layout-effect": "1.0.1" - } - }, - "@radix-ui/react-visually-hidden": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz", - "integrity": "sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - } - }, - "@radix-ui/rect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", - "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.13.10" - } - }, - "@react-native-clipboard/clipboard": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@react-native-clipboard/clipboard/-/clipboard-1.11.2.tgz", - "integrity": "sha512-bHyZVW62TuleiZsXNHS1Pv16fWc0fh8O9WvBzl4h2fykqZRW9a+Pv/RGTH56E3X2PqzHP38K5go8zmCZUoIsoQ==" - }, - "@react-native-community/blur": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@react-native-community/blur/-/blur-4.2.0.tgz", - "integrity": "sha512-StgP5zQJOCHqDRjmcKnzVkJ920S6DYBKRJfigSUnlkNQp+HzZtVtyKq0j5a7x84NtHcV7j8Uy5mz1Lx9ZKRKfA==" - }, - "@react-native-community/cli": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-12.3.2.tgz", - "integrity": "sha512-WgoUWwLDcf/G1Su2COUUVs3RzAwnV/vUTdISSpAUGgSc57mPabaAoUctKTnfYEhCnE3j02k3VtaVPwCAFRO3TQ==", - "requires": { - "@react-native-community/cli-clean": "12.3.2", - "@react-native-community/cli-config": "12.3.2", - "@react-native-community/cli-debugger-ui": "12.3.2", - "@react-native-community/cli-doctor": "12.3.2", - "@react-native-community/cli-hermes": "12.3.2", - "@react-native-community/cli-plugin-metro": "12.3.2", - "@react-native-community/cli-server-api": "12.3.2", - "@react-native-community/cli-tools": "12.3.2", - "@react-native-community/cli-types": "12.3.2", - "chalk": "^4.1.2", - "commander": "^9.4.1", - "deepmerge": "^4.3.0", - "execa": "^5.0.0", - "find-up": "^4.1.0", - "fs-extra": "^8.1.0", - "graceful-fs": "^4.1.3", - "prompts": "^2.4.2", - "semver": "^7.5.2" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==" - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "requires": { - "p-locate": "^4.1.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@react-native-community/cli-clean": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-12.3.2.tgz", - "integrity": "sha512-90k2hCX0ddSFPT7EN7h5SZj0XZPXP0+y/++v262hssoey3nhurwF57NGWN0XAR0o9BSW7+mBfeInfabzDraO6A==", - "requires": { - "@react-native-community/cli-tools": "12.3.2", - "chalk": "^4.1.2", - "execa": "^5.0.0" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@react-native-community/cli-config": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-12.3.2.tgz", - "integrity": "sha512-UUCzDjQgvAVL/57rL7eOuFUhd+d+6qfM7V8uOegQFeFEmSmvUUDLYoXpBa5vAK9JgQtSqMBJ1Shmwao+/oElxQ==", - "requires": { - "@react-native-community/cli-tools": "12.3.2", - "chalk": "^4.1.2", - "cosmiconfig": "^5.1.0", - "deepmerge": "^4.3.0", - "glob": "^7.1.3", - "joi": "^17.2.1" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@react-native-community/cli-debugger-ui": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-12.3.2.tgz", - "integrity": "sha512-nSWQUL+51J682DlfcC1bjkUbQbGvHCC25jpqTwHIjmmVjYCX1uHuhPSqQKgPNdvtfOkrkACxczd7kVMmetxY2Q==", - "requires": { - "serve-static": "^1.13.1" - } - }, - "@react-native-community/cli-doctor": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-12.3.2.tgz", - "integrity": "sha512-GrAabdY4qtBX49knHFvEAdLtCjkmndjTeqhYO6BhsbAeKOtspcLT/0WRgdLIaKODRa61ADNB3K5Zm4dU0QrZOg==", - "requires": { - "@react-native-community/cli-config": "12.3.2", - "@react-native-community/cli-platform-android": "12.3.2", - "@react-native-community/cli-platform-ios": "12.3.2", - "@react-native-community/cli-tools": "12.3.2", - "chalk": "^4.1.2", - "command-exists": "^1.2.8", - "deepmerge": "^4.3.0", - "envinfo": "^7.10.0", - "execa": "^5.0.0", - "hermes-profile-transformer": "^0.0.6", - "ip": "^1.1.5", - "node-stream-zip": "^1.9.1", - "ora": "^5.4.1", - "semver": "^7.5.2", - "strip-ansi": "^5.2.0", - "wcwidth": "^1.0.1", - "yaml": "^2.2.1" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "dependencies": { - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==" - } - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - }, - "yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==" - } - } - }, - "@react-native-community/cli-hermes": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-12.3.2.tgz", - "integrity": "sha512-SL6F9O8ghp4ESBFH2YAPLtIN39jdnvGBKnK4FGKpDCjtB3DnUmDsGFlH46S+GGt5M6VzfG2eeKEOKf3pZ6jUzA==", - "requires": { - "@react-native-community/cli-platform-android": "12.3.2", - "@react-native-community/cli-tools": "12.3.2", - "chalk": "^4.1.2", - "hermes-profile-transformer": "^0.0.6", - "ip": "^1.1.5" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@react-native-community/cli-platform-android": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-12.3.2.tgz", - "integrity": "sha512-MZ5nO8yi/N+Fj2i9BJcJ9C/ez+9/Ir7lQt49DWRo9YDmzye66mYLr/P2l/qxsixllbbDi7BXrlLpxaEhMrDopg==", - "requires": { - "@react-native-community/cli-tools": "12.3.2", - "chalk": "^4.1.2", - "execa": "^5.0.0", - "fast-xml-parser": "^4.2.4", - "glob": "^7.1.3", - "logkitty": "^0.7.1" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@react-native-community/cli-platform-ios": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-12.3.2.tgz", - "integrity": "sha512-OcWEAbkev1IL6SUiQnM6DQdsvfsKZhRZtoBNSj9MfdmwotVZSOEZJ+IjZ1FR9ChvMWayO9ns/o8LgoQxr1ZXeg==", - "requires": { - "@react-native-community/cli-tools": "12.3.2", - "chalk": "^4.1.2", - "execa": "^5.0.0", - "fast-xml-parser": "^4.0.12", - "glob": "^7.1.3", - "ora": "^5.4.1" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@react-native-community/cli-plugin-metro": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-12.3.2.tgz", - "integrity": "sha512-FpFBwu+d2E7KRhYPTkKvQsWb2/JKsJv+t1tcqgQkn+oByhp+qGyXBobFB8/R3yYvRRDCSDhS+atWTJzk9TjM8g==" - }, - "@react-native-community/cli-server-api": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-12.3.2.tgz", - "integrity": "sha512-iwa7EO9XFA/OjI5pPLLpI/6mFVqv8L73kNck3CNOJIUCCveGXBKK0VMyOkXaf/BYnihgQrXh+x5cxbDbggr7+Q==", - "requires": { - "@react-native-community/cli-debugger-ui": "12.3.2", - "@react-native-community/cli-tools": "12.3.2", - "compression": "^1.7.1", - "connect": "^3.6.5", - "errorhandler": "^1.5.1", - "nocache": "^3.0.1", - "pretty-format": "^26.6.2", - "serve-static": "^1.13.1", - "ws": "^7.5.1" - }, - "dependencies": { - "@jest/types": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", - "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - } - }, - "@types/yargs": { - "version": "15.0.19", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", - "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", - "requires": { - "@types/yargs-parser": "*" - } - }, - "pretty-format": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", - "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", - "requires": { - "@jest/types": "^26.6.2", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^17.0.1" - } - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - } - } - }, - "@react-native-community/cli-tools": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-12.3.2.tgz", - "integrity": "sha512-nDH7vuEicHI2TI0jac/DjT3fr977iWXRdgVAqPZFFczlbs7A8GQvEdGnZ1G8dqRUmg+kptw0e4hwczAOG89JzQ==", - "requires": { - "appdirsjs": "^1.2.4", - "chalk": "^4.1.2", - "find-up": "^5.0.0", - "mime": "^2.4.1", - "node-fetch": "^2.6.0", - "open": "^6.2.0", - "ora": "^5.4.1", - "semver": "^7.5.2", - "shell-quote": "^1.7.3", - "sudo-prompt": "^9.0.0" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "requires": { - "p-locate": "^5.0.0" - } - }, - "mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==" - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@react-native-community/cli-types": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-12.3.2.tgz", - "integrity": "sha512-9D0UEFqLW8JmS16mjHJxUJWX8E+zJddrHILSH8AJHZ0NNHv4u2DXKdb0wFLMobFxGNxPT+VSOjc60fGvXzWHog==", - "requires": { - "joi": "^17.2.1" - } - }, - "@react-native-community/slider": { - "version": "https://raw.githubusercontent.com/wordpress-mobile/react-native-slider/v3.0.2-wp-5/react-native-community-slider-3.0.2-wp-5.tgz", - "integrity": "sha512-19yl9Em1mFKFLB9o3IO3VpBFw+U7cswjRk6cZ7kkhDCpDD3u0cpzkaIZK6NuFIPCLqOwU0MPtP+gonanN1JQKw==" - }, - "@react-native-masked-view/masked-view": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@react-native-masked-view/masked-view/-/masked-view-0.3.0.tgz", - "integrity": "sha512-qLyoObcjzrkpNcoJjXquUePXfL1dXjHtuv+yX0zZ0Q4kG5yvVqd620+tSh7WbRoHkjpXhFBfLwvGhcWB2I0Lpw==" - }, - "@react-native/assets-registry": { - "version": "0.73.1", - "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.73.1.tgz", - "integrity": "sha512-2FgAbU7uKM5SbbW9QptPPZx8N9Ke2L7bsHb+EhAanZjFZunA9PaYtyjUQ1s7HD+zDVqOQIvjkpXSv7Kejd2tqg==" - }, - "@react-native/babel-plugin-codegen": { - "version": "0.73.3", - "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.73.3.tgz", - "integrity": "sha512-+zQrDDbz6lB48LyzFHxNCgXDCBHH+oTRdXAjikRcBUdeG9St9ABbYFLtb799zSxLOrCqFVyXqhJR2vlgLLEbcg==", - "requires": { - "@react-native/codegen": "0.73.2" - } - }, - "@react-native/babel-preset": { - "version": "0.73.10", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.73.10.tgz", - "integrity": "sha512-LPxR9DZK1EtVSEm2+fpei/AWwzgyHfaY7fuX8wDiy2THRYc/56+v28IihN8g0IAbQH+gdjXVcshJRYfV6bh2gg==", - "dev": true, - "requires": { - "@babel/core": "^7.20.0", - "@babel/plugin-proposal-async-generator-functions": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.18.0", - "@babel/plugin-proposal-export-default-from": "^7.0.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0", - "@babel/plugin-proposal-numeric-separator": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.20.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", - "@babel/plugin-proposal-optional-chaining": "^7.20.0", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", - "@babel/plugin-syntax-export-default-from": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.18.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", - "@babel/plugin-syntax-optional-chaining": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-async-to-generator": "^7.20.0", - "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-classes": "^7.0.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.20.0", - "@babel/plugin-transform-flow-strip-types": "^7.20.0", - "@babel/plugin-transform-function-name": "^7.0.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-modules-commonjs": "^7.0.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.0.0", - "@babel/plugin-transform-parameters": "^7.0.0", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/plugin-transform-react-jsx-self": "^7.0.0", - "@babel/plugin-transform-react-jsx-source": "^7.0.0", - "@babel/plugin-transform-runtime": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-sticky-regex": "^7.0.0", - "@babel/plugin-transform-typescript": "^7.5.0", - "@babel/plugin-transform-unicode-regex": "^7.0.0", - "@babel/template": "^7.0.0", - "babel-plugin-transform-flow-enums": "^0.0.2", - "react-refresh": "^0.4.0" - }, - "dependencies": { - "react-refresh": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz", - "integrity": "sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA==", - "dev": true - } - } - }, - "@react-native/codegen": { - "version": "0.73.2", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.73.2.tgz", - "integrity": "sha512-lfy8S7umhE3QLQG5ViC4wg5N1Z+E6RnaeIw8w1voroQsXXGPB72IBozh8dAHR3+ceTxIU0KX3A8OpJI8e1+HpQ==", - "requires": { - "@babel/parser": "^7.20.0", - "flow-parser": "^0.206.0", - "glob": "^7.1.1", - "invariant": "^2.2.4", - "jscodeshift": "^0.14.0", - "mkdirp": "^0.5.1", - "nullthrows": "^1.1.1" - }, - "dependencies": { - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "requires": { - "minimist": "^1.2.6" - } - } - } - }, - "@react-native/community-cli-plugin": { - "version": "0.73.14", - "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.14.tgz", - "integrity": "sha512-KzIwsTvAJrXPtwhGOSm+OcJH1B8TpY8cS4xxzu/e2qv3a2n4VLePHTPAfco1tmvekV8OHWvvD9JSIX7i2fB1gg==", - "requires": { - "@react-native-community/cli-server-api": "12.3.2", - "@react-native-community/cli-tools": "12.3.2", - "@react-native/dev-middleware": "0.73.7", - "@react-native/metro-babel-transformer": "0.73.14", - "chalk": "^4.0.0", - "execa": "^5.1.1", - "metro": "^0.80.3", - "metro-config": "^0.80.3", - "metro-core": "^0.80.3", - "node-fetch": "^2.2.0", - "readline": "^1.3.0" - }, - "dependencies": { - "@react-native/babel-preset": { - "version": "0.73.20", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.73.20.tgz", - "integrity": "sha512-fU9NqkusbfFq71l4BWQfqqD/lLcLC0MZ++UYgieA3j8lIEppJTLVauv2RwtD2yltBkjebgYEC5Rwvt1l0MUBXw==", - "requires": { - "@babel/core": "^7.20.0", - "@babel/plugin-proposal-async-generator-functions": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.18.0", - "@babel/plugin-proposal-export-default-from": "^7.0.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0", - "@babel/plugin-proposal-numeric-separator": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.20.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", - "@babel/plugin-proposal-optional-chaining": "^7.20.0", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", - "@babel/plugin-syntax-export-default-from": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.18.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", - "@babel/plugin-syntax-optional-chaining": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-async-to-generator": "^7.20.0", - "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-classes": "^7.0.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.20.0", - "@babel/plugin-transform-flow-strip-types": "^7.20.0", - "@babel/plugin-transform-function-name": "^7.0.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-modules-commonjs": "^7.0.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.0.0", - "@babel/plugin-transform-parameters": "^7.0.0", - "@babel/plugin-transform-private-methods": "^7.22.5", - "@babel/plugin-transform-private-property-in-object": "^7.22.11", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/plugin-transform-react-jsx-self": "^7.0.0", - "@babel/plugin-transform-react-jsx-source": "^7.0.0", - "@babel/plugin-transform-runtime": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-sticky-regex": "^7.0.0", - "@babel/plugin-transform-typescript": "^7.5.0", - "@babel/plugin-transform-unicode-regex": "^7.0.0", - "@babel/template": "^7.0.0", - "@react-native/babel-plugin-codegen": "0.73.3", - "babel-plugin-transform-flow-enums": "^0.0.2", - "react-refresh": "^0.14.0" - } - }, - "@react-native/metro-babel-transformer": { - "version": "0.73.14", - "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.14.tgz", - "integrity": "sha512-5wLeYw/lormpSqYfI9H/geZ/EtPmi+x5qLkEit15Q/70hkzYo/M+aWztUtbOITfgTEOP8d6ybROzoGsqgyZLcw==", - "requires": { - "@babel/core": "^7.20.0", - "@react-native/babel-preset": "0.73.20", - "hermes-parser": "0.15.0", - "nullthrows": "^1.1.1" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@react-native/debugger-frontend": { - "version": "0.73.3", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.73.3.tgz", - "integrity": "sha512-RgEKnWuoo54dh7gQhV7kvzKhXZEhpF9LlMdZolyhGxHsBqZ2gXdibfDlfcARFFifPIiaZ3lXuOVVa4ei+uPgTw==" - }, - "@react-native/dev-middleware": { - "version": "0.73.7", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.73.7.tgz", - "integrity": "sha512-BZXpn+qKp/dNdr4+TkZxXDttfx8YobDh8MFHsMk9usouLm22pKgFIPkGBV0X8Do4LBkFNPGtrnsKkWk/yuUXKg==", - "requires": { - "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.73.3", - "chrome-launcher": "^0.15.2", - "chromium-edge-launcher": "^1.0.0", - "connect": "^3.6.5", - "debug": "^2.2.0", - "node-fetch": "^2.2.0", - "open": "^7.0.3", - "serve-static": "^1.13.1", - "temp-dir": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "requires": { - "is-docker": "^2.0.0" - } - }, - "open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "requires": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" - } - }, - "temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==" - } - } - }, - "@react-native/gradle-plugin": { - "version": "0.73.4", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.73.4.tgz", - "integrity": "sha512-PMDnbsZa+tD55Ug+W8CfqXiGoGneSSyrBZCMb5JfiB3AFST3Uj5e6lw8SgI/B6SKZF7lG0BhZ6YHZsRZ5MlXmg==" - }, - "@react-native/js-polyfills": { - "version": "0.73.1", - "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz", - "integrity": "sha512-ewMwGcumrilnF87H4jjrnvGZEaPFCAC4ebraEK+CurDDmwST/bIicI4hrOAv+0Z0F7DEK4O4H7r8q9vH7IbN4g==" - }, - "@react-native/metro-babel-transformer": { - "version": "0.73.10", - "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.10.tgz", - "integrity": "sha512-g0q12s1VcrhI4ab9ZQzFHmvjkDW5PYdJd3LiyhIO3OAWLD7iNLWL5tJe9iA3n8rxbanmf1oauqlNY1UmkxhAvQ==", - "dev": true, - "requires": { - "@babel/core": "^7.20.0", - "@react-native/babel-preset": "*", - "babel-preset-fbjs": "^3.4.0", - "hermes-parser": "0.15.0", - "nullthrows": "^1.1.1" - } - }, - "@react-native/metro-config": { - "version": "0.73.4", - "resolved": "https://registry.npmjs.org/@react-native/metro-config/-/metro-config-0.73.4.tgz", - "integrity": "sha512-4IpWb9InOY23ssua6z/ho2B4uRqF4QaNHGg4aV3D/og5yiVF39GEm/REHU36i+KoHRO3GcB6DrI7N9KrcvgGBw==", - "dev": true, - "requires": { - "@react-native/js-polyfills": "0.73.1", - "@react-native/metro-babel-transformer": "0.73.14", - "metro-config": "^0.80.3", - "metro-runtime": "^0.80.3" - }, - "dependencies": { - "@react-native/babel-preset": { - "version": "0.73.20", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.73.20.tgz", - "integrity": "sha512-fU9NqkusbfFq71l4BWQfqqD/lLcLC0MZ++UYgieA3j8lIEppJTLVauv2RwtD2yltBkjebgYEC5Rwvt1l0MUBXw==", - "dev": true, - "requires": { - "@babel/core": "^7.20.0", - "@babel/plugin-proposal-async-generator-functions": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.18.0", - "@babel/plugin-proposal-export-default-from": "^7.0.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0", - "@babel/plugin-proposal-numeric-separator": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.20.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", - "@babel/plugin-proposal-optional-chaining": "^7.20.0", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", - "@babel/plugin-syntax-export-default-from": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.18.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", - "@babel/plugin-syntax-optional-chaining": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-async-to-generator": "^7.20.0", - "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-classes": "^7.0.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.20.0", - "@babel/plugin-transform-flow-strip-types": "^7.20.0", - "@babel/plugin-transform-function-name": "^7.0.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-modules-commonjs": "^7.0.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.0.0", - "@babel/plugin-transform-parameters": "^7.0.0", - "@babel/plugin-transform-private-methods": "^7.22.5", - "@babel/plugin-transform-private-property-in-object": "^7.22.11", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/plugin-transform-react-jsx-self": "^7.0.0", - "@babel/plugin-transform-react-jsx-source": "^7.0.0", - "@babel/plugin-transform-runtime": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-sticky-regex": "^7.0.0", - "@babel/plugin-transform-typescript": "^7.5.0", - "@babel/plugin-transform-unicode-regex": "^7.0.0", - "@babel/template": "^7.0.0", - "@react-native/babel-plugin-codegen": "0.73.3", - "babel-plugin-transform-flow-enums": "^0.0.2", - "react-refresh": "^0.14.0" - } - }, - "@react-native/metro-babel-transformer": { - "version": "0.73.14", - "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.14.tgz", - "integrity": "sha512-5wLeYw/lormpSqYfI9H/geZ/EtPmi+x5qLkEit15Q/70hkzYo/M+aWztUtbOITfgTEOP8d6ybROzoGsqgyZLcw==", - "dev": true, - "requires": { - "@babel/core": "^7.20.0", - "@react-native/babel-preset": "0.73.20", - "hermes-parser": "0.15.0", - "nullthrows": "^1.1.1" - } - } - } - }, - "@react-native/normalize-color": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@react-native/normalize-color/-/normalize-color-2.1.0.tgz", - "integrity": "sha512-Z1jQI2NpdFJCVgpY+8Dq/Bt3d+YUi1928Q+/CZm/oh66fzM0RUl54vvuXlPJKybH4pdCZey1eDTPaLHkMPNgWA==" - }, - "@react-native/normalize-colors": { - "version": "0.73.2", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.73.2.tgz", - "integrity": "sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w==" - }, - "@react-native/virtualized-lists": { - "version": "0.73.4", - "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.73.4.tgz", - "integrity": "sha512-HpmLg1FrEiDtrtAbXiwCgXFYyloK/dOIPIuWW3fsqukwJEWAiTzm1nXGJ7xPU5XTHiWZ4sKup5Ebaj8z7iyWog==", - "requires": { - "invariant": "^2.2.4", - "nullthrows": "^1.1.1" - } - }, - "@react-navigation/core": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-5.12.0.tgz", - "integrity": "sha512-CTmYrFXCZwInN40CpEzkPxhrpzujj20qvsUgpH05+oO1flwsnaJsyBfYawIcTS62/1/Z6SAM7iW5PbKk+qw9iQ==", - "requires": { - "@react-navigation/routers": "^5.4.9", - "escape-string-regexp": "^4.0.0", - "nanoid": "^3.1.9", - "query-string": "^6.13.1", - "react-is": "^16.13.0", - "use-subscription": "^1.4.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - } - } - }, - "@react-navigation/elements": { - "version": "1.3.18", - "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.18.tgz", - "integrity": "sha512-/0hwnJkrr415yP0Hf4PjUKgGyfshrvNUKFXN85Mrt1gY49hy9IwxZgrrxlh0THXkPeq8q4VWw44eHDfAcQf20Q==" - }, - "@react-navigation/native": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.0.14.tgz", - "integrity": "sha512-Z95bJrRkZerBJq6Qc/xjA/kibPpB+UvPeMWS1CBhRF8FaX1483UdHqPqSbW879tPwjP2R4XfoA4dtoEHswrOjA==", - "requires": { - "@react-navigation/core": "^6.4.1", - "escape-string-regexp": "^4.0.0", - "fast-deep-equal": "^3.1.3", - "nanoid": "^3.1.23" - }, - "dependencies": { - "@react-navigation/core": { - "version": "6.4.17", - "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.17.tgz", - "integrity": "sha512-Nd76EpomzChWAosGqWOYE3ItayhDzIEzzZsT7PfGcRFDgW5miHV2t4MZcq9YIK4tzxZjVVpYbIynOOQQd1e0Cg==", - "requires": { - "@react-navigation/routers": "^6.1.9", - "escape-string-regexp": "^4.0.0", - "nanoid": "^3.1.23", - "query-string": "^7.1.3", - "react-is": "^16.13.0", - "use-latest-callback": "^0.2.1" - } - }, - "@react-navigation/routers": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.9.tgz", - "integrity": "sha512-lTM8gSFHSfkJvQkxacGM6VJtBt61ip2XO54aNfswD+KMw6eeZ4oehl7m0me3CR9hnDE4+60iAZR8sAhvCiI3NA==", - "requires": { - "nanoid": "^3.1.23" - } - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - }, - "query-string": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", - "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", - "requires": { - "decode-uri-component": "^0.2.2", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - } - } - } - }, - "@react-navigation/routers": { - "version": "5.4.9", - "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-5.4.9.tgz", - "integrity": "sha512-dYD5qrIKUmuBEp+O98hB0tDYpEsGQgCQFQgMEoFKBmVVhx2JnJJ1zxRjU7xWcCU4VdBA8IOowgHQHJsVNKYyrg==", - "requires": { - "nanoid": "^3.1.9" - } - }, - "@react-navigation/stack": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-6.3.5.tgz", - "integrity": "sha512-G706Ow+8fhiLT5Cf48566YsjboU5h5ll9nva90xX3br7V6x0JMoGMvXjvbORZyzLuUytQO3mf0T3nVUuO52vZQ==", - "requires": { - "@react-navigation/elements": "^1.3.7", - "color": "^4.2.3", - "warn-once": "^0.1.0" - } - }, - "@react-spring/animated": { - "version": "9.5.5", - "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.5.5.tgz", - "integrity": "sha512-glzViz7syQ3CE6BQOwAyr75cgh0qsihm5lkaf24I0DfU63cMm/3+br299UEYkuaHNmfDfM414uktiPlZCNJbQA==", - "requires": { - "@react-spring/shared": "~9.5.5", - "@react-spring/types": "~9.5.5" - } - }, - "@react-spring/core": { - "version": "9.5.5", - "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.5.5.tgz", - "integrity": "sha512-shaJYb3iX18Au6gkk8ahaF0qx0LpS0Yd+ajb4asBaAQf6WPGuEdJsbsNSgei1/O13JyEATsJl20lkjeslJPMYA==", - "requires": { - "@react-spring/animated": "~9.5.5", - "@react-spring/rafz": "~9.5.5", - "@react-spring/shared": "~9.5.5", - "@react-spring/types": "~9.5.5" - } - }, - "@react-spring/rafz": { - "version": "9.5.5", - "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.5.5.tgz", - "integrity": "sha512-F/CLwB0d10jL6My5vgzRQxCNY2RNyDJZedRBK7FsngdCmzoq3V4OqqNc/9voJb9qRC2wd55oGXUeXv2eIaFmsw==" - }, - "@react-spring/shared": { - "version": "9.5.5", - "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.5.5.tgz", - "integrity": "sha512-YwW70Pa/YXPOwTutExHZmMQSHcNC90kJOnNR4G4mCDNV99hE98jWkIPDOsgqbYx3amIglcFPiYKMaQuGdr8dyQ==", - "requires": { - "@react-spring/rafz": "~9.5.5", - "@react-spring/types": "~9.5.5" - } - }, - "@react-spring/types": { - "version": "9.5.5", - "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.5.5.tgz", - "integrity": "sha512-7I/qY8H7Enwasxr4jU6WmtNK+RZ4Z/XvSlDvjXFVe7ii1x0MoSlkw6pD7xuac8qrHQRm9BTcbZNyeeKApYsvCg==" - }, - "@react-spring/web": { - "version": "9.5.5", - "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.5.5.tgz", - "integrity": "sha512-+moT8aDX/ho/XAhU+HRY9m0LVV9y9CK6NjSRaI+30Re150pB3iEip6QfnF4qnhSCQ5drpMF0XRXHgOTY/xbtFw==", - "requires": { - "@react-spring/animated": "~9.5.5", - "@react-spring/core": "~9.5.5", - "@react-spring/shared": "~9.5.5", - "@react-spring/types": "~9.5.5" - } - }, - "@samverschueren/stream-to-observable": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", - "integrity": "sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==", - "dev": true, - "requires": { - "any-observable": "^0.3.0" - } - }, - "@sentry/core": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.19.7.tgz", - "integrity": "sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw==", - "dev": true, - "requires": { - "@sentry/hub": "6.19.7", - "@sentry/minimal": "6.19.7", - "@sentry/types": "6.19.7", - "@sentry/utils": "6.19.7", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@sentry/hub": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz", - "integrity": "sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA==", - "dev": true, - "requires": { - "@sentry/types": "6.19.7", - "@sentry/utils": "6.19.7", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@sentry/minimal": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.7.tgz", - "integrity": "sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ==", - "dev": true, - "requires": { - "@sentry/hub": "6.19.7", - "@sentry/types": "6.19.7", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@sentry/node": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.19.7.tgz", - "integrity": "sha512-gtmRC4dAXKODMpHXKfrkfvyBL3cI8y64vEi3fDD046uqYcrWdgoQsffuBbxMAizc6Ez1ia+f0Flue6p15Qaltg==", - "dev": true, - "requires": { - "@sentry/core": "6.19.7", - "@sentry/hub": "6.19.7", - "@sentry/types": "6.19.7", - "@sentry/utils": "6.19.7", - "cookie": "^0.4.1", - "https-proxy-agent": "^5.0.0", - "lru_map": "^0.3.3", - "tslib": "^1.9.3" - }, - "dependencies": { - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@sentry/types": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz", - "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==", - "dev": true - }, - "@sentry/utils": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz", - "integrity": "sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==", - "dev": true, - "requires": { - "@sentry/types": "6.19.7", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@sideway/address": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", - "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" - }, - "@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" - }, - "@sidvind/better-ajv-errors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@sidvind/better-ajv-errors/-/better-ajv-errors-2.1.0.tgz", - "integrity": "sha512-JuIb009FhHuL9priFBho2kv7QmZOydj0LgYvj+h1t0mMCmhM/YmQNRlJR5wVtBZya6wrVFK5Hi5TIbv5BKEx7w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.0", - "chalk": "^4.1.0" - } - }, - "@sigstore/bundle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.0.0.tgz", - "integrity": "sha512-yLvrWDOh6uMOUlFCTJIZEnwOT9Xte7NPXUqVexEKGSF5XtBAuSg5du0kn3dRR0p47a4ah10Y0mNt8+uyeQXrBQ==", - "dev": true, - "requires": { - "@sigstore/protobuf-specs": "^0.2.0" - } - }, - "@sigstore/protobuf-specs": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.0.tgz", - "integrity": "sha512-8ZhZKAVfXjIspDWwm3D3Kvj0ddbJ0HqDZ/pOs5cx88HpT8mVsotFrg7H1UMnXOuDHz6Zykwxn4mxG3QLuN+RUg==", - "dev": true - }, - "@sigstore/tuf": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", - "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==", - "dev": true, - "requires": { - "@sigstore/protobuf-specs": "^0.2.0", - "tuf-js": "^1.1.7" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" - }, - "@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true - }, - "@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "requires": { - "@sinonjs/commons": "^3.0.0" - } - }, - "@sliphua/lilconfig-ts-loader": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sliphua/lilconfig-ts-loader/-/lilconfig-ts-loader-3.2.2.tgz", - "integrity": "sha512-nX2aBwAykiG50fSUzK9eyA5UvWcrEKzA0ZzCq9mLwHMwpKxM+U05YH8PHba1LJrbeZ7R1HSjJagWKMqFyq8cxw==", - "dev": true, - "requires": { - "lodash.get": "^4", - "make-error": "^1", - "ts-node": "^9", - "tslib": "^2" - } - }, - "@storybook/addon-a11y": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-7.6.15.tgz", - "integrity": "sha512-8PxRMBJUSxNoceo2IYXFyZp3VU+/ONK/DsD0dj/fVrv7izFrS8aw2GWSsSMK8xAbEUpANXWMKGaSyvrRFVgsVQ==", - "dev": true, - "requires": { - "@storybook/addon-highlight": "7.6.15", - "axe-core": "^4.2.0" - } - }, - "@storybook/addon-actions": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-7.6.15.tgz", - "integrity": "sha512-2Jfvbahe/tmq1iNnNxmcP0JnX0rqCuijjXXai9yMDV3koIMawn6t88MPVrdcso5ch/fxE45522nZqA3SZJbM4g==", - "dev": true, - "requires": { - "@storybook/core-events": "7.6.15", - "@storybook/global": "^5.0.0", - "@types/uuid": "^9.0.1", - "dequal": "^2.0.2", - "polished": "^4.2.2", - "uuid": "^9.0.0" - }, - "dependencies": { - "@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", - "dev": true - } - } - }, - "@storybook/addon-controls": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-7.6.15.tgz", - "integrity": "sha512-HXcG/Lr4ri7WUFz14Y5lEBTA1XmKy0E/DepW88XVy6YNsTpERVWEBcvjKoLAU1smKrfhVto96hK2AVFL3A8EBQ==", - "dev": true, - "requires": { - "@storybook/blocks": "7.6.15", - "lodash": "^4.17.21", - "ts-dedent": "^2.0.0" - } - }, - "@storybook/addon-docs": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-7.6.15.tgz", - "integrity": "sha512-UPODqO+mrYaKyTSAtfRslxOFgSP/v/5vfDx896pbNTC4Sf8xLytoudw4I14hzkHmRdXiOnd21FqXJfmF/Onsvw==", - "dev": true, - "requires": { - "@jest/transform": "^29.3.1", - "@mdx-js/react": "^2.1.5", - "@storybook/blocks": "7.6.15", - "@storybook/client-logger": "7.6.15", - "@storybook/components": "7.6.15", - "@storybook/csf-plugin": "7.6.15", - "@storybook/csf-tools": "7.6.15", - "@storybook/global": "^5.0.0", - "@storybook/mdx2-csf": "^1.0.0", - "@storybook/node-logger": "7.6.15", - "@storybook/postinstall": "7.6.15", - "@storybook/preview-api": "7.6.15", - "@storybook/react-dom-shim": "7.6.15", - "@storybook/theming": "7.6.15", - "@storybook/types": "7.6.15", - "fs-extra": "^11.1.0", - "remark-external-links": "^8.0.0", - "remark-slug": "^6.0.0", - "ts-dedent": "^2.0.0" - }, - "dependencies": { - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - } - } - }, - "@storybook/addon-highlight": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-7.6.15.tgz", - "integrity": "sha512-ptidWZJJcEM83YsxCjf+m1q8Rr9sN8piJ4PJlM2vyc4MLZY4q6htb1JJFeq3ov1Iz6SY9KjKc/zOkWo4L54nxw==", - "dev": true, - "requires": { - "@storybook/global": "^5.0.0" - } - }, - "@storybook/addon-toolbars": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-7.6.15.tgz", - "integrity": "sha512-QougKS2eABB5Jd332i9tBpKgh2lN4aaqXkvmVC5egT5dOuJ9IeuZbGwiALef/uf1f3IuyUP41So9l2dI4u19aw==", - "dev": true - }, - "@storybook/addon-viewport": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-7.6.15.tgz", - "integrity": "sha512-0esg0+onJftU2prD3n/sbxBTrTOIGQnZhbrKPP+/S26dVHuYaR/65XdwpRgXNY5PHK2yjU78HxiJP+Kyu75ntw==", - "dev": true, - "requires": { - "memoizerific": "^1.11.3" - } - }, - "@storybook/blocks": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-7.6.15.tgz", - "integrity": "sha512-ODP7AVh2iIGblI5WKGokWSHbp9YQHc+Uce7JCGcnDbNavoy64Z6R6G+wXzF5jfl7xQlbhQ8yQCuSSL4GNdYTeA==", - "dev": true, - "requires": { - "@storybook/channels": "7.6.15", - "@storybook/client-logger": "7.6.15", - "@storybook/components": "7.6.15", - "@storybook/core-events": "7.6.15", - "@storybook/csf": "^0.1.2", - "@storybook/docs-tools": "7.6.15", - "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.6.15", - "@storybook/preview-api": "7.6.15", - "@storybook/theming": "7.6.15", - "@storybook/types": "7.6.15", - "@types/lodash": "^4.14.167", - "color-convert": "^2.0.1", - "dequal": "^2.0.2", - "lodash": "^4.17.21", - "markdown-to-jsx": "^7.1.8", - "memoizerific": "^1.11.3", - "polished": "^4.2.2", - "react-colorful": "^5.1.2", - "telejson": "^7.2.0", - "tocbot": "^4.20.1", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "dependencies": { - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } - } - }, - "@storybook/builder-manager": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-7.6.15.tgz", - "integrity": "sha512-vfpfCywiasyP7vtbgLJhjssBEwUjZhBsRsubDAzumgOochPiKKPNwsSc5NU/4ZIGaC5zRO26kUaUqFIbJdTEUQ==", - "dev": true, - "requires": { - "@fal-works/esbuild-plugin-global-externals": "^2.1.2", - "@storybook/core-common": "7.6.15", - "@storybook/manager": "7.6.15", - "@storybook/node-logger": "7.6.15", - "@types/ejs": "^3.1.1", - "@types/find-cache-dir": "^3.2.1", - "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.10", - "browser-assert": "^1.2.1", - "ejs": "^3.1.8", - "esbuild": "^0.18.0", - "esbuild-plugin-alias": "^0.2.1", - "express": "^4.17.3", - "find-cache-dir": "^3.0.0", - "fs-extra": "^11.1.0", - "process": "^0.11.10", - "util": "^0.12.4" - }, - "dependencies": { - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - }, - "util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - } - } - }, - "@storybook/builder-webpack5": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-7.6.15.tgz", - "integrity": "sha512-HF+TSK/eU2ld8uQ8VWgcAIzOQ2hjnEkzup363vGZkYUfsHsVbjMpZgf+foDjI4LZNfQ/RjcVEZxqJqIbpM0Sjg==", - "dev": true, - "requires": { - "@babel/core": "^7.23.2", - "@storybook/channels": "7.6.15", - "@storybook/client-logger": "7.6.15", - "@storybook/core-common": "7.6.15", - "@storybook/core-events": "7.6.15", - "@storybook/core-webpack": "7.6.15", - "@storybook/node-logger": "7.6.15", - "@storybook/preview": "7.6.15", - "@storybook/preview-api": "7.6.15", - "@swc/core": "^1.3.82", - "@types/node": "^18.0.0", - "@types/semver": "^7.3.4", - "babel-loader": "^9.0.0", - "browser-assert": "^1.2.1", - "case-sensitive-paths-webpack-plugin": "^2.4.0", - "cjs-module-lexer": "^1.2.3", - "constants-browserify": "^1.0.0", - "css-loader": "^6.7.1", - "es-module-lexer": "^1.4.1", - "express": "^4.17.3", - "fork-ts-checker-webpack-plugin": "^8.0.0", - "fs-extra": "^11.1.0", - "html-webpack-plugin": "^5.5.0", - "magic-string": "^0.30.5", - "path-browserify": "^1.0.1", - "process": "^0.11.10", - "semver": "^7.3.7", - "style-loader": "^3.3.1", - "swc-loader": "^0.2.3", - "terser-webpack-plugin": "^5.3.1", - "ts-dedent": "^2.0.0", - "url": "^0.11.0", - "util": "^0.12.4", - "util-deprecate": "^1.0.2", - "webpack": "5", - "webpack-dev-middleware": "^6.1.1", - "webpack-hot-middleware": "^2.25.1", - "webpack-virtual-modules": "^0.5.0" - }, - "dependencies": { - "css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "dev": true, - "requires": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - } - }, - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "style-loader": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", - "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", - "dev": true - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - }, - "util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - } - } - }, - "@storybook/channels": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.6.15.tgz", - "integrity": "sha512-UPDYRzGkygYFa8QUpEiumWrvZm4u4RKVzgiBt9C4RmHORqkkZzL9LXhaZJp2SmIz1ND5gx6KR5ze8ZnAdwxxoQ==", - "dev": true, - "requires": { - "@storybook/client-logger": "7.6.15", - "@storybook/core-events": "7.6.15", - "@storybook/global": "^5.0.0", - "qs": "^6.10.0", - "telejson": "^7.2.0", - "tiny-invariant": "^1.3.1" - } - }, - "@storybook/cli": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-7.6.15.tgz", - "integrity": "sha512-2QRqCyVGDSkraHxX2JPYkkFccbu5Uo+JYFaFJo4vmMXzDurjWON+Ga2B8FCTd4A8P4C02Ca/79jgQoyBB3xoew==", - "dev": true, - "requires": { - "@babel/core": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/types": "^7.23.0", - "@ndelangen/get-tarball": "^3.0.7", - "@storybook/codemod": "7.6.15", - "@storybook/core-common": "7.6.15", - "@storybook/core-events": "7.6.15", - "@storybook/core-server": "7.6.15", - "@storybook/csf-tools": "7.6.15", - "@storybook/node-logger": "7.6.15", - "@storybook/telemetry": "7.6.15", - "@storybook/types": "7.6.15", - "@types/semver": "^7.3.4", - "@yarnpkg/fslib": "2.10.3", - "@yarnpkg/libzip": "2.3.0", - "chalk": "^4.1.0", - "commander": "^6.2.1", - "cross-spawn": "^7.0.3", - "detect-indent": "^6.1.0", - "envinfo": "^7.7.3", - "execa": "^5.0.0", - "express": "^4.17.3", - "find-up": "^5.0.0", - "fs-extra": "^11.1.0", - "get-npm-tarball-url": "^2.0.3", - "get-port": "^5.1.1", - "giget": "^1.0.0", - "globby": "^11.0.2", - "jscodeshift": "^0.15.1", - "leven": "^3.1.0", - "ora": "^5.4.1", - "prettier": "^2.8.0", - "prompts": "^2.4.0", - "puppeteer-core": "^2.1.1", - "read-pkg-up": "^7.0.1", - "semver": "^7.3.7", - "strip-json-comments": "^3.0.1", - "tempy": "^1.0.1", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "dependencies": { - "agent-base": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", - "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "https-proxy-agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", - "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", - "dev": true, - "requires": { - "agent-base": "5", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "jscodeshift": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz", - "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==", - "dev": true, - "requires": { - "@babel/core": "^7.23.0", - "@babel/parser": "^7.23.0", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-modules-commonjs": "^7.23.0", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", - "@babel/plugin-transform-optional-chaining": "^7.23.0", - "@babel/plugin-transform-private-methods": "^7.22.5", - "@babel/preset-flow": "^7.22.15", - "@babel/preset-typescript": "^7.23.0", - "@babel/register": "^7.22.15", - "babel-core": "^7.0.0-bridge.0", - "chalk": "^4.1.2", - "flow-parser": "0.*", - "graceful-fs": "^4.2.4", - "micromatch": "^4.0.4", - "neo-async": "^2.5.0", - "node-dir": "^0.1.17", - "recast": "^0.23.3", - "temp": "^0.8.4", - "write-file-atomic": "^2.3.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true - }, - "puppeteer-core": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-2.1.1.tgz", - "integrity": "sha512-n13AWriBMPYxnpbb6bnaY5YoY6rGj8vPLrz6CZF3o0qJNEwlcfJVxBzYZ0NJsQ21UbdJoijPCDrM++SUVEz7+w==", - "dev": true, - "requires": { - "@types/mime-types": "^2.1.0", - "debug": "^4.1.0", - "extract-zip": "^1.6.6", - "https-proxy-agent": "^4.0.0", - "mime": "^2.0.3", - "mime-types": "^2.1.25", - "progress": "^2.0.1", - "proxy-from-env": "^1.0.0", - "rimraf": "^2.6.1", - "ws": "^6.1.0" - } - }, - "recast": { - "version": "0.23.9", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", - "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", - "dev": true, - "requires": { - "ast-types": "^0.16.1", - "esprima": "~4.0.0", - "source-map": "~0.6.1", - "tiny-invariant": "^1.3.3", - "tslib": "^2.0.1" - } - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "ws": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", - "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - } - } - }, - "@storybook/client-logger": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.6.15.tgz", - "integrity": "sha512-n+K8IqnombqiQNnywVovS+lK61tvv/XSfgPt0cgvoF/hJZB0VDOMRjWsV+v9qQpj1TQEl1lLWeJwZMthTWupJA==", - "dev": true, - "requires": { - "@storybook/global": "^5.0.0" - } - }, - "@storybook/codemod": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-7.6.15.tgz", - "integrity": "sha512-NiEbTLCdacj6TMxC7G49IImXeMzkG8wpPr8Ayxm9HeG6q5UkiF5/DiZdqbJm2zaosOsOKWwvXg1t6Pq6Nivytg==", - "dev": true, - "requires": { - "@babel/core": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/types": "^7.23.0", - "@storybook/csf": "^0.1.2", - "@storybook/csf-tools": "7.6.15", - "@storybook/node-logger": "7.6.15", - "@storybook/types": "7.6.15", - "@types/cross-spawn": "^6.0.2", - "cross-spawn": "^7.0.3", - "globby": "^11.0.2", - "jscodeshift": "^0.15.1", - "lodash": "^4.17.21", - "prettier": "^2.8.0", - "recast": "^0.23.1" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jscodeshift": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz", - "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==", - "dev": true, - "requires": { - "@babel/core": "^7.23.0", - "@babel/parser": "^7.23.0", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-modules-commonjs": "^7.23.0", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", - "@babel/plugin-transform-optional-chaining": "^7.23.0", - "@babel/plugin-transform-private-methods": "^7.22.5", - "@babel/preset-flow": "^7.22.15", - "@babel/preset-typescript": "^7.23.0", - "@babel/register": "^7.22.15", - "babel-core": "^7.0.0-bridge.0", - "chalk": "^4.1.2", - "flow-parser": "0.*", - "graceful-fs": "^4.2.4", - "micromatch": "^4.0.4", - "neo-async": "^2.5.0", - "node-dir": "^0.1.17", - "recast": "^0.23.3", - "temp": "^0.8.4", - "write-file-atomic": "^2.3.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true - }, - "recast": { - "version": "0.23.9", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", - "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", - "dev": true, - "requires": { - "ast-types": "^0.16.1", - "esprima": "~4.0.0", - "source-map": "~0.6.1", - "tiny-invariant": "^1.3.3", - "tslib": "^2.0.1" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@storybook/components": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-7.6.15.tgz", - "integrity": "sha512-xD+maP7+C9HeZXi2vJ+uK9hXN4S4spP4uDj9pyZ9yViKb+ztEO6WpovUMT8WRQ0mMegWyLXkx3zqu43hZvXM1g==", - "dev": true, - "requires": { - "@radix-ui/react-select": "^1.2.2", - "@radix-ui/react-toolbar": "^1.0.4", - "@storybook/client-logger": "7.6.15", - "@storybook/csf": "^0.1.2", - "@storybook/global": "^5.0.0", - "@storybook/theming": "7.6.15", - "@storybook/types": "7.6.15", - "memoizerific": "^1.11.3", - "use-resize-observer": "^9.1.0", - "util-deprecate": "^1.0.2" - } - }, - "@storybook/core-client": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-7.6.15.tgz", - "integrity": "sha512-jwWol+zo+ItKBzPm9i80bEL6seHMsV0wKSaViVMQ4TqHtEbNeFE8sFEc2NTr18VNBnQOdlQPnEWmdboXBUrGcA==", - "dev": true, - "requires": { - "@storybook/client-logger": "7.6.15", - "@storybook/preview-api": "7.6.15" - } - }, - "@storybook/core-common": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.6.15.tgz", - "integrity": "sha512-VGmcLJ5U1r1s8/YnLbKcyB4GnNL+/sZIPqwlcSKzDXO76HoVFv1kywf7PbASote7P3gdhLSxBdg95LH2bdIbmw==", - "dev": true, - "requires": { - "@storybook/core-events": "7.6.15", - "@storybook/node-logger": "7.6.15", - "@storybook/types": "7.6.15", - "@types/find-cache-dir": "^3.2.1", - "@types/node": "^18.0.0", - "@types/node-fetch": "^2.6.4", - "@types/pretty-hrtime": "^1.0.0", - "chalk": "^4.1.0", - "esbuild": "^0.18.0", - "esbuild-register": "^3.5.0", - "file-system-cache": "2.3.0", - "find-cache-dir": "^3.0.0", - "find-up": "^5.0.0", - "fs-extra": "^11.1.0", - "glob": "^10.0.0", - "handlebars": "^4.7.7", - "lazy-universal-dotenv": "^4.0.0", - "node-fetch": "^2.0.0", - "picomatch": "^2.3.0", - "pkg-dir": "^5.0.0", - "pretty-hrtime": "^1.0.3", - "resolve-from": "^5.0.0", - "ts-dedent": "^2.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - } - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - } - }, - "jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "requires": { - "find-up": "^5.0.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - } - } - }, - "@storybook/core-events": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.6.15.tgz", - "integrity": "sha512-i4YnjGecbpGyrFe0340sPhQ9QjZZEBqvMy6kF4XWt6DYLHxZmsTj1HEdvxVl4Ej7V49Vw0Dm8MepJ1d4Y8MKrQ==", - "dev": true, - "requires": { - "ts-dedent": "^2.0.0" - } - }, - "@storybook/core-server": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-7.6.15.tgz", - "integrity": "sha512-iIlxEAkrmKTSA3iGNqt/4QG7hf5suxBGYIB3DZAOfBo8EdZogMYaEmuCm5dbuaJr0mcVwlqwdhQiWb1VsR/NhA==", - "dev": true, - "requires": { - "@aw-web-design/x-default-browser": "1.4.126", - "@discoveryjs/json-ext": "^0.5.3", - "@storybook/builder-manager": "7.6.15", - "@storybook/channels": "7.6.15", - "@storybook/core-common": "7.6.15", - "@storybook/core-events": "7.6.15", - "@storybook/csf": "^0.1.2", - "@storybook/csf-tools": "7.6.15", - "@storybook/docs-mdx": "^0.1.0", - "@storybook/global": "^5.0.0", - "@storybook/manager": "7.6.15", - "@storybook/node-logger": "7.6.15", - "@storybook/preview-api": "7.6.15", - "@storybook/telemetry": "7.6.15", - "@storybook/types": "7.6.15", - "@types/detect-port": "^1.3.0", - "@types/node": "^18.0.0", - "@types/pretty-hrtime": "^1.0.0", - "@types/semver": "^7.3.4", - "better-opn": "^3.0.2", - "chalk": "^4.1.0", - "cli-table3": "^0.6.1", - "compression": "^1.7.4", - "detect-port": "^1.3.0", - "express": "^4.17.3", - "fs-extra": "^11.1.0", - "globby": "^11.0.2", - "ip": "^2.0.0", - "lodash": "^4.17.21", - "open": "^8.4.0", - "pretty-hrtime": "^1.0.3", - "prompts": "^2.4.0", - "read-pkg-up": "^7.0.1", - "semver": "^7.3.7", - "telejson": "^7.2.0", - "tiny-invariant": "^1.3.1", - "ts-dedent": "^2.0.0", - "util": "^0.12.4", - "util-deprecate": "^1.0.2", - "watchpack": "^2.2.0", - "ws": "^8.2.3" - }, - "dependencies": { - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "ip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", - "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - }, - "util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, - "watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true - } - } - }, - "@storybook/core-webpack": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-7.6.15.tgz", - "integrity": "sha512-6Qk/kc7OKcy4jNowQFz6TFLWM2NYeLoJ73dIbFnN2o8DYS5WwmQLZhZ+MRvr92M+w1nlnc268kaqooYmAj8Mnw==", - "dev": true, - "requires": { - "@storybook/core-common": "7.6.15", - "@storybook/node-logger": "7.6.15", - "@storybook/types": "7.6.15", - "@types/node": "^18.0.0", - "ts-dedent": "^2.0.0" - } - }, - "@storybook/csf": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.11.tgz", - "integrity": "sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg==", - "dev": true, - "requires": { - "type-fest": "^2.19.0" - }, - "dependencies": { - "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true - } - } - }, - "@storybook/csf-plugin": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-7.6.15.tgz", - "integrity": "sha512-5Pm2B8XKNdG3fHyItWKbWnXHSRDFSvetlML+sMWGWYIjwOsnvPqt+gAvLksWhv/uJgDujGxNcPEh+/Y5C8ZAjQ==", - "dev": true, - "requires": { - "@storybook/csf-tools": "7.6.15", - "unplugin": "^1.3.1" - } - }, - "@storybook/csf-tools": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-7.6.15.tgz", - "integrity": "sha512-8iKgg2cmbFTpVhRRJOqouhPcEh0c8ywabG4S8ICZvnJooSXUI9mD9p3tYCS7MYuSiHj0epa1Kkn9DtXJRo9o6g==", - "dev": true, - "requires": { - "@babel/generator": "^7.23.0", - "@babel/parser": "^7.23.0", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0", - "@storybook/csf": "^0.1.2", - "@storybook/types": "7.6.15", - "fs-extra": "^11.1.0", - "recast": "^0.23.1", - "ts-dedent": "^2.0.0" - }, - "dependencies": { - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "recast": { - "version": "0.23.9", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", - "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", - "dev": true, - "requires": { - "ast-types": "^0.16.1", - "esprima": "~4.0.0", - "source-map": "~0.6.1", - "tiny-invariant": "^1.3.3", - "tslib": "^2.0.1" - } - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - } - } - }, - "@storybook/docs-mdx": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@storybook/docs-mdx/-/docs-mdx-0.1.0.tgz", - "integrity": "sha512-JDaBR9lwVY4eSH5W8EGHrhODjygPd6QImRbwjAuJNEnY0Vw4ie3bPkeGfnacB3OBW6u/agqPv2aRlR46JcAQLg==", - "dev": true - }, - "@storybook/docs-tools": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-7.6.15.tgz", - "integrity": "sha512-npZEaI9Wpn9uJcRXFElqyiRw8bSxt95mLywPiEEGMT2kE5FfXM8d5Uj5O64kzoXdRI9IhRPEEZZidOtA/UInfQ==", - "dev": true, - "requires": { - "@storybook/core-common": "7.6.15", - "@storybook/preview-api": "7.6.15", - "@storybook/types": "7.6.15", - "@types/doctrine": "^0.0.3", - "assert": "^2.1.0", - "doctrine": "^3.0.0", - "lodash": "^4.17.21" - }, - "dependencies": { - "assert": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", - "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "is-nan": "^1.3.2", - "object-is": "^1.1.5", - "object.assign": "^4.1.4", - "util": "^0.12.5" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - } - } - }, - "@storybook/global": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", - "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", - "dev": true - }, - "@storybook/manager": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-7.6.15.tgz", - "integrity": "sha512-GGV2ElV5AOIApy/FSDzoSlLUbyd2VhQVD3TdNGRxNauYRjEO8ulXHw2tNbT6ludtpYpDTAILzI6zT/iag8hmPQ==", - "dev": true - }, - "@storybook/manager-api": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-7.6.15.tgz", - "integrity": "sha512-cPBsXcnJiaO3QyaEum2JgdihYea3cI03FeV35JdrBYLIelT4oqbYFnzjznsFg9+Ia9iAbz7aOBNyyRsWnC/UKw==", - "dev": true, - "requires": { - "@storybook/channels": "7.6.15", - "@storybook/client-logger": "7.6.15", - "@storybook/core-events": "7.6.15", - "@storybook/csf": "^0.1.2", - "@storybook/global": "^5.0.0", - "@storybook/router": "7.6.15", - "@storybook/theming": "7.6.15", - "@storybook/types": "7.6.15", - "dequal": "^2.0.2", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "store2": "^2.14.2", - "telejson": "^7.2.0", - "ts-dedent": "^2.0.0" - } - }, - "@storybook/mdx2-csf": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@storybook/mdx2-csf/-/mdx2-csf-1.1.0.tgz", - "integrity": "sha512-TXJJd5RAKakWx4BtpwvSNdgTDkKM6RkXU8GK34S/LhidQ5Pjz3wcnqb0TxEkfhK/ztbP8nKHqXFwLfa2CYkvQw==", - "dev": true - }, - "@storybook/node-logger": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.6.15.tgz", - "integrity": "sha512-C+sCvRjR+5uVU3VTrfyv7/RlPBxesAjIucUAK0keGyIZ7sFQYCPdkm4m/C4s+TcubgAzVvuoUHlRrSppdA7WzQ==", - "dev": true - }, - "@storybook/postinstall": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-7.6.15.tgz", - "integrity": "sha512-DXQQ4kjAbQ7BSd9M4lDI/12vEEciYMP8uYFDlrPFjwD9LezsxtRiORkazjNRRX4730faO5zZsnWhXxCVkxck0g==", - "dev": true - }, - "@storybook/preset-react-webpack": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-7.6.15.tgz", - "integrity": "sha512-Oo3J7RKO/tFUVnRXs16tZGcX6n90gTpHdlT2Z1fZ+y8wEd9o+VvvKFEIIeMcRxf3hHa49R6Kbc4AQaE9FAuDlw==", - "dev": true, - "requires": { - "@babel/preset-flow": "^7.22.15", - "@babel/preset-react": "^7.22.15", - "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", - "@storybook/core-webpack": "7.6.15", - "@storybook/docs-tools": "7.6.15", - "@storybook/node-logger": "7.6.15", - "@storybook/react": "7.6.15", - "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0", - "@types/node": "^18.0.0", - "@types/semver": "^7.3.4", - "babel-plugin-add-react-displayname": "^0.0.5", - "fs-extra": "^11.1.0", - "magic-string": "^0.30.5", - "react-docgen": "^7.0.0", - "react-refresh": "^0.14.0", - "semver": "^7.3.7", - "webpack": "5" - }, - "dependencies": { - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - } - } - }, - "@storybook/preview": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/preview/-/preview-7.6.15.tgz", - "integrity": "sha512-q8d9v0+Bo/DHLV68OyV3Klep4knf2GAbrlHhLW1X4jlPccuEDUojIfqfK7m48ayeIxJzO48fcO0JdKM1XABx7g==", - "dev": true - }, - "@storybook/preview-api": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.15.tgz", - "integrity": "sha512-2KN9vlizF6sFlYsJEGnFqcQaJXs4TTdawC1VazVdtaMSHANDxxDu8F1cP+u7lpPH3DkNZUmTGQDBYfYY9xR0eQ==", - "dev": true, - "requires": { - "@storybook/channels": "7.6.15", - "@storybook/client-logger": "7.6.15", - "@storybook/core-events": "7.6.15", - "@storybook/csf": "^0.1.2", - "@storybook/global": "^5.0.0", - "@storybook/types": "7.6.15", - "@types/qs": "^6.9.5", - "dequal": "^2.0.2", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "synchronous-promise": "^2.0.15", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - } - }, - "@storybook/react": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/react/-/react-7.6.15.tgz", - "integrity": "sha512-oJMSh4iTGu6OqCmj0LhkuPyMkxGMTCoohN4HcDpXd96jCSyWotVebRsg9xm5ddB7f54e6DY4XDoGH0WnVoR23g==", - "dev": true, - "requires": { - "@storybook/client-logger": "7.6.15", - "@storybook/core-client": "7.6.15", - "@storybook/docs-tools": "7.6.15", - "@storybook/global": "^5.0.0", - "@storybook/preview-api": "7.6.15", - "@storybook/react-dom-shim": "7.6.15", - "@storybook/types": "7.6.15", - "@types/escodegen": "^0.0.6", - "@types/estree": "^0.0.51", - "@types/node": "^18.0.0", - "acorn": "^7.4.1", - "acorn-jsx": "^5.3.1", - "acorn-walk": "^7.2.0", - "escodegen": "^2.1.0", - "html-tags": "^3.1.0", - "lodash": "^4.17.21", - "prop-types": "^15.7.2", - "react-element-to-jsx-string": "^15.0.0", - "ts-dedent": "^2.0.0", - "type-fest": "~2.19", - "util-deprecate": "^1.0.2" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true - } - } - }, - "@storybook/react-docgen-typescript-plugin": { - "version": "1.0.6--canary.9.0c3f3b7.0", - "resolved": "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.6--canary.9.0c3f3b7.0.tgz", - "integrity": "sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "endent": "^2.0.1", - "find-cache-dir": "^3.3.1", - "flat-cache": "^3.0.4", - "micromatch": "^4.0.2", - "react-docgen-typescript": "^2.2.2", - "tslib": "^2.0.0" - }, - "dependencies": { - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@storybook/react-dom-shim": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-7.6.15.tgz", - "integrity": "sha512-2+X0HIxIyvjfSKVyGGjSJJLEFJ2ox7Rr8FjlMiRo5QfoOJhohZuWH7p4Lw7JMwm5PotnjrwlfsZI3cCilYJeYA==", - "dev": true - }, - "@storybook/react-webpack5": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/react-webpack5/-/react-webpack5-7.6.15.tgz", - "integrity": "sha512-TyYYSDho+4cQRBCVMKu7XDTCrAsLWaeldCoZm910e4DTXZUV3NDG8hVJIXzweaCu1o7JtDOelxsA6iizR/22GQ==", - "dev": true, - "requires": { - "@storybook/builder-webpack5": "7.6.15", - "@storybook/preset-react-webpack": "7.6.15", - "@storybook/react": "7.6.15", - "@types/node": "^18.0.0" - } - }, - "@storybook/router": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-7.6.15.tgz", - "integrity": "sha512-5yhXXoVZ1iKUgeZoO8PGqBclrLgoJisxIYVK/Y1iJMXZ2ZvwUiTswLALT6lu97tSrcoBVxmqSghg0+U0YEU4Fg==", - "dev": true, - "requires": { - "@storybook/client-logger": "7.6.15", - "memoizerific": "^1.11.3", - "qs": "^6.10.0" - } - }, - "@storybook/source-loader": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-7.6.15.tgz", - "integrity": "sha512-E7LqjfvEUs2dn8ZWc1OfqzXU3vyi2/yP7rPHPRFjDUIpz1QI4IUCUIFY+n3YWkbk8wlmf6dV/2QYzYZPp6RD0g==", - "dev": true, - "requires": { - "@storybook/csf": "^0.1.2", - "@storybook/types": "7.6.15", - "estraverse": "^5.2.0", - "lodash": "^4.17.21", - "prettier": "^2.8.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true - } - } - }, - "@storybook/telemetry": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-7.6.15.tgz", - "integrity": "sha512-klhKXLUS3OXozGEtMbbhKZLDfm+m3nNk2jvGwD6kkBenzFUzb0P2m8awxU7h1pBcKZKH/27U9t3KVzNFzWoWPw==", - "dev": true, - "requires": { - "@storybook/client-logger": "7.6.15", - "@storybook/core-common": "7.6.15", - "@storybook/csf-tools": "7.6.15", - "chalk": "^4.1.0", - "detect-package-manager": "^2.0.1", - "fetch-retry": "^5.0.2", - "fs-extra": "^11.1.0", - "read-pkg-up": "^7.0.1" - }, - "dependencies": { - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - } - } - }, - "@storybook/theming": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-7.6.15.tgz", - "integrity": "sha512-9PpsHAbUf6o0w33/P3mnb7QheTmfGlTYCismj5HMM1O2/zY0kQK9XcG9W+Cyvu56D/lFC19fz9YHQY8W4AbfnQ==", - "dev": true, - "requires": { - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", - "@storybook/client-logger": "7.6.15", - "@storybook/global": "^5.0.0", - "memoizerific": "^1.11.3" - } - }, - "@storybook/types": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.6.15.tgz", - "integrity": "sha512-tLH0lK6SXECSfMpKin9bge+7XiHZII17n6jc9ZI1TfSBZJyq3M6VzWh2r1C2lC97FlkcKXjIwM3n8h1xNjnI+A==", - "dev": true, - "requires": { - "@storybook/channels": "7.6.15", - "@types/babel__core": "^7.0.0", - "@types/express": "^4.7.0", - "file-system-cache": "2.3.0" - } - }, - "@stylistic/stylelint-plugin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-3.0.1.tgz", - "integrity": "sha512-j3mH8HSw2Rob/KJFWZ627w3CQ8gQqVHtzCdPeEffUg5vOgpz4rgrR+Xw2kU0OQCDcdW8Y1nKfdXKKjM5Rn8X0g==", - "dev": true, - "requires": { - "@csstools/css-parser-algorithms": "^3.0.0", - "@csstools/css-tokenizer": "^3.0.0", - "@csstools/media-query-list-parser": "^3.0.0", - "is-plain-object": "^5.0.0", - "postcss-selector-parser": "^6.1.2", - "postcss-value-parser": "^4.2.0", - "style-search": "^0.1.0", - "stylelint": "^16.8.2" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "@svgr/babel-plugin-add-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", - "dev": true - }, - "@svgr/babel-plugin-remove-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", - "dev": true - }, - "@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", - "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", - "dev": true - }, - "@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", - "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", - "dev": true - }, - "@svgr/babel-plugin-svg-dynamic-title": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", - "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", - "dev": true - }, - "@svgr/babel-plugin-svg-em-dimensions": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", - "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", - "dev": true - }, - "@svgr/babel-plugin-transform-react-native-svg": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.0.0.tgz", - "integrity": "sha512-UKrY3860AQICgH7g+6h2zkoxeVEPLYwX/uAjmqo4PIq2FIHppwhIqZstIyTz0ZtlwreKR41O3W3BzsBBiJV2Aw==", - "dev": true - }, - "@svgr/babel-plugin-transform-svg-component": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", - "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", - "dev": true - }, - "@svgr/babel-preset": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.0.0.tgz", - "integrity": "sha512-KLcjiZychInVrhs86OvcYPLTFu9L5XV2vj0XAaE1HwE3J3jLmIzRY8ttdeAg/iFyp8nhavJpafpDZTt+1LIpkQ==", - "dev": true, - "requires": { - "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", - "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", - "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", - "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", - "@svgr/babel-plugin-transform-react-native-svg": "8.0.0", - "@svgr/babel-plugin-transform-svg-component": "8.0.0" - } - }, - "@svgr/core": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.0.0.tgz", - "integrity": "sha512-aJKtc+Pie/rFYsVH/unSkDaZGvEeylNv/s2cP+ta9/rYWxRVvoV/S4Qw65Kmrtah4CBK5PM6ISH9qUH7IJQCng==", - "dev": true, - "requires": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.0.0", - "camelcase": "^6.2.0", - "cosmiconfig": "^8.1.3", - "snake-case": "^3.0.4" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "requires": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - } - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - } - } - }, - "@svgr/hast-util-to-babel-ast": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", - "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", - "dev": true, - "requires": { - "@babel/types": "^7.21.3", - "entities": "^4.4.0" - }, - "dependencies": { - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true - } - } - }, - "@svgr/plugin-jsx": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.0.1.tgz", - "integrity": "sha512-bfCFb+4ZsM3UuKP2t7KmDwn6YV8qVn9HIQJmau6xeQb/iV65Rpi7NBNBWA2hcCd4GKoCqG8hpaaDk5FDR0eH+g==", - "dev": true, - "requires": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.0.0", - "@svgr/hast-util-to-babel-ast": "8.0.0", - "svg-parser": "^2.0.4" - } - }, - "@svgr/plugin-svgo": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.0.1.tgz", - "integrity": "sha512-29OJ1QmJgnohQHDAgAuY2h21xWD6TZiXji+hnx+W635RiXTAlHTbjrZDktfqzkN0bOeQEtNe+xgq73/XeWFfSg==", - "dev": true, - "requires": { - "cosmiconfig": "^8.1.3", - "deepmerge": "^4.3.1", - "svgo": "^3.0.2" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "requires": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - } - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - } - } - }, - "@svgr/webpack": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.0.1.tgz", - "integrity": "sha512-zSoeKcbCmfMXjA11uDuCJb+1LWNb3vy6Qw/VHj0Nfcl3UuqwuoZWknHsBIhCWvi4wU9vPui3aq054qjVyZqY4A==", - "dev": true, - "requires": { - "@babel/core": "^7.21.3", - "@babel/plugin-transform-react-constant-elements": "^7.21.3", - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.21.0", - "@svgr/core": "8.0.0", - "@svgr/plugin-jsx": "8.0.1", - "@svgr/plugin-svgo": "8.0.1" - } - }, - "@swc/core": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.1.tgz", - "integrity": "sha512-3y+Y8js+e7BbM16iND+6Rcs3jdiL28q3iVtYsCviYSSpP2uUVKkp5sJnCY4pg8AaVvyN7CGQHO7gLEZQ5ByozQ==", - "dev": true, - "requires": { - "@swc/core-darwin-arm64": "1.4.1", - "@swc/core-darwin-x64": "1.4.1", - "@swc/core-linux-arm-gnueabihf": "1.4.1", - "@swc/core-linux-arm64-gnu": "1.4.1", - "@swc/core-linux-arm64-musl": "1.4.1", - "@swc/core-linux-x64-gnu": "1.4.1", - "@swc/core-linux-x64-musl": "1.4.1", - "@swc/core-win32-arm64-msvc": "1.4.1", - "@swc/core-win32-ia32-msvc": "1.4.1", - "@swc/core-win32-x64-msvc": "1.4.1", - "@swc/counter": "^0.1.2", - "@swc/types": "^0.1.5" - } - }, - "@swc/core-darwin-arm64": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.1.tgz", - "integrity": "sha512-ePyfx0348UbR4DOAW24TedeJbafnzha8liXFGuQ4bdXtEVXhLfPngprrxKrAddCuv42F9aTxydlF6+adD3FBhA==", - "dev": true, - "optional": true - }, - "@swc/core-darwin-x64": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.1.tgz", - "integrity": "sha512-eLf4JSe6VkCMdDowjM8XNC5rO+BrgfbluEzAVtKR8L2HacNYukieumN7EzpYCi0uF1BYwu1ku6tLyG2r0VcGxA==", - "dev": true, - "optional": true - }, - "@swc/core-linux-arm-gnueabihf": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.1.tgz", - "integrity": "sha512-K8VtTLWMw+rkN/jDC9o/Q9SMmzdiHwYo2CfgkwVT29NsGccwmNhCQx6XoYiPKyKGIFKt4tdQnJHKUFzxUqQVtQ==", - "dev": true, - "optional": true - }, - "@swc/core-linux-arm64-gnu": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.1.tgz", - "integrity": "sha512-0e8p4g0Bfkt8lkiWgcdiENH3RzkcqKtpRXIVNGOmVc0OBkvc2tpm2WTx/eoCnes2HpTT4CTtR3Zljj4knQ4Fvw==", - "dev": true, - "optional": true - }, - "@swc/core-linux-arm64-musl": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.1.tgz", - "integrity": "sha512-b/vWGQo2n7lZVUnSQ7NBq3Qrj85GrAPPiRbpqaIGwOytiFSk8VULFihbEUwDe0rXgY4LDm8z8wkgADZcLnmdUA==", - "dev": true, - "optional": true - }, - "@swc/core-linux-x64-gnu": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.1.tgz", - "integrity": "sha512-AFMQlvkKEdNi1Vk2GFTxxJzbICttBsOQaXa98kFTeWTnFFIyiIj2w7Sk8XRTEJ/AjF8ia8JPKb1zddBWr9+bEQ==", - "dev": true, - "optional": true - }, - "@swc/core-linux-x64-musl": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.1.tgz", - "integrity": "sha512-QX2MxIECX1gfvUVZY+jk528/oFkS9MAl76e3ZRvG2KC/aKlCQL0KSzcTSm13mOxkDKS30EaGRDRQWNukGpMeRg==", - "dev": true, - "optional": true - }, - "@swc/core-win32-arm64-msvc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.1.tgz", - "integrity": "sha512-OklkJYXXI/tntD2zaY8i3iZldpyDw5q+NAP3k9OlQ7wXXf37djRsHLV0NW4+ZNHBjE9xp2RsXJ0jlOJhfgGoFA==", - "dev": true, - "optional": true - }, - "@swc/core-win32-ia32-msvc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.1.tgz", - "integrity": "sha512-MBuc3/QfKX9FnLOU7iGN+6yHRTQaPQ9WskiC8s8JFiKQ+7I2p25tay2RplR9dIEEGgVAu6L7auv96LbNTh+FaA==", - "dev": true, - "optional": true - }, - "@swc/core-win32-x64-msvc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.1.tgz", - "integrity": "sha512-lu4h4wFBb/bOK6N2MuZwg7TrEpwYXgpQf5R7ObNSXL65BwZ9BG8XRzD+dLJmALu8l5N08rP/TrpoKRoGT4WSxw==", - "dev": true, - "optional": true - }, - "@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "dev": true - }, - "@swc/types": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", - "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==", - "dev": true - }, - "@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, - "requires": { - "defer-to-connect": "^2.0.0" - } - }, - "@tannin/compile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@tannin/compile/-/compile-1.1.0.tgz", - "integrity": "sha512-n8m9eNDfoNZoxdvWiTfW/hSPhehzLJ3zW7f8E7oT6mCROoMNWCB4TYtv041+2FMAxweiE0j7i1jubQU4MEC/Gg==", - "requires": { - "@tannin/evaluate": "^1.2.0", - "@tannin/postfix": "^1.1.0" - } - }, - "@tannin/evaluate": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@tannin/evaluate/-/evaluate-1.2.0.tgz", - "integrity": "sha512-3ioXvNowbO/wSrxsDG5DKIMxC81P0QrQTYai8zFNY+umuoHWRPbQ/TuuDEOju9E+jQDXmj6yI5GyejNuh8I+eg==" - }, - "@tannin/plural-forms": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@tannin/plural-forms/-/plural-forms-1.1.0.tgz", - "integrity": "sha512-xl9R2mDZO/qiHam1AgMnAES6IKIg7OBhcXqy6eDsRCdXuxAFPcjrej9HMjyCLE0DJ/8cHf0i5OQTstuBRhpbHw==", - "requires": { - "@tannin/compile": "^1.1.0" - } - }, - "@tannin/postfix": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@tannin/postfix/-/postfix-1.1.0.tgz", - "integrity": "sha512-oocsqY7g0cR+Gur5jRQLSrX2OtpMLMse1I10JQBm8CdGMrDkh1Mg2gjsiquMHRtBs4Qwu5wgEp5GgIYHk4SNPw==" - }, - "@testing-library/dom": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.1.tgz", - "integrity": "sha512-0DGPd9AR3+iDTjGoMpxIkAsUihHZ3Ai6CneU6bRRrffXMgzCdlNk43jTrD2/5LT6CBb3MWTP8v510JzYtahD2w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.1.3", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, - "requires": { - "deep-equal": "^2.0.5" - } - }, - "deep-equal": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", - "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.1", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - } - }, - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - } - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - } - } - }, - "@testing-library/jest-dom": { - "version": "5.16.5", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", - "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", - "dev": true, - "requires": { - "@adobe/css-tools": "^4.0.1", - "@babel/runtime": "^7.9.2", - "@types/testing-library__jest-dom": "^5.9.1", - "aria-query": "^5.0.0", - "chalk": "^3.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", - "redent": "^3.0.0" - }, - "dependencies": { - "aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@testing-library/react": { - "version": "14.3.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.3.0.tgz", - "integrity": "sha512-AYJGvNFMbCa5vt1UtDCa/dcaABrXq8gph6VN+cffIx0UeA0qiGqS+sT60+sb+Gjc8tGXdECWYQgaF0khf8b+Lg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^9.0.0", - "@types/react-dom": "^18.0.0" - } - }, - "@testing-library/react-native": { - "version": "12.4.3", - "resolved": "https://registry.npmjs.org/@testing-library/react-native/-/react-native-12.4.3.tgz", - "integrity": "sha512-WLE7VbbR5jZJQl3vfNK7Wt+IHnzhOxyu95Mr56EHmzH3XhC8DkrPVAnUq9asq/QWj4aGnymbinFx6zZys/WZmA==", - "dev": true, - "requires": { - "jest-matcher-utils": "^29.7.0", - "pretty-format": "^29.7.0", - "redent": "^3.0.0" - } - }, - "@testing-library/user-event": { - "version": "14.4.3", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.4.3.tgz", - "integrity": "sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==", - "dev": true - }, - "@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true - }, - "@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true - }, - "@tsconfig/node14": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-14.1.0.tgz", - "integrity": "sha512-VmsCG04YR58ciHBeJKBDNMWWfYbyP8FekWVuTlpstaUPlat1D0x/tXzkWP7yCMU0eSz9V4OZU0LBWTFJ3xZf6w==", - "dev": true - }, - "@tufjs/canonical-json": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz", - "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==", - "dev": true - }, - "@tufjs/models": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz", - "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==", - "dev": true, - "requires": { - "@tufjs/canonical-json": "1.0.0", - "minimatch": "^9.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "@types/archiver": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-5.3.3.tgz", - "integrity": "sha512-0ABdVcXL6jOwNGY+hjWPqrxUvKelBEwNLcuv/SV2vZ4YCH8w9NttFCt+/QqI5zgMX+iX/XqVy89/r7EmLJmMpQ==", - "dev": true, - "requires": { - "@types/readdir-glob": "*" - } - }, - "@types/argparse": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-2.0.10.tgz", - "integrity": "sha512-C4wahC3gz3vQtvPazrJ5ONwmK1zSDllQboiWvpMM/iOswCYfBREFnjFbq/iWKIVOCl8+m5Pk6eva6/ZSsDuIGA==", - "dev": true - }, - "@types/aria-query": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", - "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==", - "dev": true - }, - "@types/async-lock": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@types/async-lock/-/async-lock-1.4.0.tgz", - "integrity": "sha512-2+rYSaWrpdbQG3SA0LmMT6YxWLrI81AqpMlSkw3QtFc2HGDufkweQSn30Eiev7x9LL0oyFrBqk1PXOnB9IEgKg==", - "dev": true - }, - "@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", - "dev": true, - "requires": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", - "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", - "dev": true, - "requires": { - "@babel/types": "^7.20.7" - } - }, - "@types/base64-stream": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/base64-stream/-/base64-stream-1.0.3.tgz", - "integrity": "sha512-cbLPBuRLRq7l2+syfKT3byML5C/UNK/6hkcDDMxwttE+NtpXvQxhgXj0PNbcLCwUCmfEWMm3eRBpDmpieLegDQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/bluebird": { - "version": "3.5.38", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.38.tgz", - "integrity": "sha512-yR/Kxc0dd4FfwtEoLZMoqJbM/VE/W7hXn/MIjb+axcwag0iFmSPK7OBUZq1YWLynJUoWQkfUrI7T0HDqGApNSg==", - "dev": true - }, - "@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/bonjour": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.11.tgz", - "integrity": "sha512-isGhjmBtLIxdHBDl2xGwUzEM8AOyOvWsADWq7rqirdi/ZQoHnLWErHvsThcEzTX8juDRiZtzp2Qkv5bgNh6mAg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, - "requires": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect-history-api-fallback": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.1.tgz", - "integrity": "sha512-iaQslNbARe8fctL5Lk+DsmgWOM83lM+7FzP0eQUJs1jd3kBE8NWqBTIT2S8SqQOJjxvt2eyIjpOuYeRXq2AdMw==", - "dev": true, - "requires": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "@types/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/detect-port": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/detect-port/-/detect-port-1.3.5.tgz", - "integrity": "sha512-Rf3/lB9WkDfIL9eEKaSYKc+1L/rNVYBjThk22JTqQw0YozXarX8YljFAz+HCoC6h4B4KwCMsBPZHaFezwT4BNA==", - "dev": true - }, - "@types/doctrine": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.3.tgz", - "integrity": "sha512-w5jZ0ee+HaPOaX25X2/2oGR/7rgAQSYII7X7pp0m9KgBfMP7uKfMfTvcpl5Dj+eDBbpxKGiqE+flqDr6XTd2RA==", - "dev": true - }, - "@types/ejs": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz", - "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", - "dev": true - }, - "@types/emscripten": { - "version": "1.39.10", - "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.10.tgz", - "integrity": "sha512-TB/6hBkYQJxsZHSqyeuO1Jt0AB/bW6G7rHt9g7lML7SOF6lbgcHvw/Lr+69iqN0qxgXLhWKScAon73JNnptuDw==", - "dev": true - }, - "@types/escodegen": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@types/escodegen/-/escodegen-0.0.6.tgz", - "integrity": "sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==", - "dev": true - }, - "@types/eslint": { - "version": "8.56.9", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.9.tgz", - "integrity": "sha512-W4W3KcqzjJ0sHg2vAq9vfml6OhsJ53TcUjUqfzzZf/EChUtwspszj/S0pzMxnfRcO55/iGq47dscXw71Fxc4Zg==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", - "dev": true - }, - "@types/express": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", - "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.35", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", - "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "@types/fancy-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/fancy-log/-/fancy-log-2.0.0.tgz", - "integrity": "sha512-g39Vp8ZJ3D0gXhhkhDidVvdy4QajkF7/PV6HGn23FMaMqE/tLC1JNHUeQ7SshKLsBjucakZsXBLkWULbGLdL5g==", - "dev": true - }, - "@types/find-cache-dir": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@types/find-cache-dir/-/find-cache-dir-3.2.1.tgz", - "integrity": "sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==", - "dev": true - }, - "@types/find-root": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/find-root/-/find-root-1.1.2.tgz", - "integrity": "sha512-lGuMq71TL466jtCpvh7orGd+mrdBmo2h8ozvtOOTbq3ByfWpuN+UVxv4sOv3YpsD4NhW2k6ESGhnT/FIg4Ouzw==", - "dev": true - }, - "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", - "dev": true, - "requires": { - "@types/events": "*", - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/graceful-fs": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.3.tgz", - "integrity": "sha512-AiHRaEB50LQg0pZmm659vNBb9f4SJ0qrAnteuzhSeAUcJKxoYgEnprg/83kppCnc2zvtCKbdZry1a5pVY3lOTQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/hammerjs": { - "version": "2.0.45", - "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.45.tgz", - "integrity": "sha512-qkcUlZmX6c4J8q45taBKTL3p+LbITgyx7qhlPYOdOHZB7B31K0mXbP5YA7i7SgDeEGuI9MnumiKPEMrxg8j3KQ==" - }, - "@types/highlight-words-core": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@types/highlight-words-core/-/highlight-words-core-1.2.1.tgz", - "integrity": "sha512-9VZUA5omXBfn+hDxFjUDu1FOJTBM3LmvqfDey+Z6Aa8B8/JmF5SMj6FBrjfgJ/Q3YXOZd3qyTDfJyMZSs/wCUA==" - }, - "@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "@types/http-cache-semantics": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.2.tgz", - "integrity": "sha512-FD+nQWA2zJjh4L9+pFXqWOi0Hs1ryBCfI+985NjluQ1p8EYtoLvjLOKidXBtZ4/IcxDX4o8/E8qDS3540tNliw==", - "dev": true - }, - "@types/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==", - "dev": true - }, - "@types/http-proxy": { - "version": "1.17.12", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.12.tgz", - "integrity": "sha512-kQtujO08dVtQ2wXAuSFfk9ASy3sug4+ogFR8Kd8UgP8PEuc1/G/8yjYRmp//PcDNJEUKOza/MrQu15bouEUCiw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", - "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==" - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "requires": { - "@types/istanbul-lib-report": "*" - } - }, - "@types/jest": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.4.0.tgz", - "integrity": "sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==", - "dev": true, - "requires": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "@types/jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" - } - }, - "@types/jsftp": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@types/jsftp/-/jsftp-2.1.3.tgz", - "integrity": "sha512-R5rP70tkPnH+rhz0s6VuMKqMrkA7ET1AfU3FDGKNhYBgU/XTIbzsYNCgTByo60eitl0mI5OoEA9+MW/t/5iVzA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/klaw": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/klaw/-/klaw-3.0.4.tgz", - "integrity": "sha512-0M5F/WMU9yu2MyRued1VTQvUSwZ3siqYsX6MU7JF7VXRF5RzL0FXWFUrmdrWuGDWmuN6W+SyLhhg1Wp/sXkjtg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/lockfile": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/lockfile/-/lockfile-1.0.2.tgz", - "integrity": "sha512-jD5VbvhfMhaYN4M3qPJuhMVUg3Dfc4tvPvLEAXn6GXbs/ajDFtCQahX37GIE65ipTI3I+hEvNaXS3MYAn9Ce3Q==", - "dev": true - }, - "@types/lodash": { - "version": "4.14.199", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.199.tgz", - "integrity": "sha512-Vrjz5N5Ia4SEzWWgIVwnHNEnb1UE1XMkvY5DGXrAeOGE9imk0hgTHh5GyDjLDJi9OTCn9oo9dXH1uToK1VRfrg==", - "dev": true - }, - "@types/mdx": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.6.tgz", - "integrity": "sha512-sVcwEG10aFU2KcM7cIA0M410UPv/DesOPyG8zMVk0QUDexHA3lYmGucpEpZ2dtWWhi2ip3CG+5g/iH0PwoW4Fw==", - "dev": true - }, - "@types/method-override": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/method-override/-/method-override-0.0.33.tgz", - "integrity": "sha512-H6hK7AZdUOCmboTTUlhfDG3uT0XDljjrk3vIb+GJ3ylkogXu5s/NncGB85r3rtCz6sxZBWF62dlf7I04sIQA5A==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/mime": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", - "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==", - "dev": true - }, - "@types/mime-types": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.4.tgz", - "integrity": "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=", - "dev": true - }, - "@types/mousetrap": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.8.tgz", - "integrity": "sha512-zTqjvgCUT5EoXqbqmd8iJMb4NJqyV/V7pK7AIKq7qcaAsJIpGlTVJS1HQM6YkdHCdnkNSbhcQI7MXYxFfE3iCA==" - }, - "@types/mv": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/mv/-/mv-2.1.2.tgz", - "integrity": "sha512-IvAjPuiQ2exDicnTrMidt1m+tj3gZ60BM0PaoRsU0m9Cn+lrOyemuO9Tf8CvHFmXlxMjr1TVCfadi9sfwbSuKg==", - "dev": true - }, - "@types/ncp": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/ncp/-/ncp-2.0.6.tgz", - "integrity": "sha512-A5CcYVkrcbRD+5ghRzn+LjEYUNT+YpjcPfnpYte6fBNfq3rXJRYA03cATV0XfVbSnOZa2Yp5sXYI1fIkjAF/UA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/node": { - "version": "18.19.54", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.54.tgz", - "integrity": "sha512-+BRgt0G5gYjTvdLac9sIeE0iZcJxi4Jc4PV5EUzqi+88jmQLr+fRZdv2tCTV7IHKSGxM6SaLoOXQWWUiLUItMw==", - "requires": { - "undici-types": "~5.26.4" - } - }, - "@types/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", - "dev": true, - "requires": { - "@types/node": "*", - "form-data": "^4.0.0" - } - }, - "@types/normalize-package-data": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz", - "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==", - "dev": true - }, - "@types/npm-package-arg": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/npm-package-arg/-/npm-package-arg-6.1.1.tgz", - "integrity": "sha512-452/1Kp9IdM/oR10AyqAgZOxUt7eLbm+EMJ194L6oarMYdZNiFIFAOJ7IIr0OrZXTySgfHjJezh2oiyk2kc3ag==", - "dev": true - }, - "@types/npmlog": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-4.1.4.tgz", - "integrity": "sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ==", - "dev": true - }, - "@types/offscreencanvas": { - "version": "2019.7.0", - "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz", - "integrity": "sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==" - }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" - }, - "@types/pluralize": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.31.tgz", - "integrity": "sha512-MQh69PPwFlYAL2qz/Mw5Zc34VTdt7pTck0Xbb6pbPSzdt5oaLB87iyJJxEMS5Dco/s7lXHunEezAvQurZZdrsQ==", - "dev": true - }, - "@types/prettier": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.4.tgz", - "integrity": "sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA==", - "dev": true - }, - "@types/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha512-nj39q0wAIdhwn7DGUyT9irmsKK1tV0bd5WFEhgpqNTMFZ8cE+jieuTphCW0tfdm47S2zVT5mr09B28b1chmQMA==", - "dev": true - }, - "@types/prop-types": { - "version": "15.7.4", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", - "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==" - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true - }, - "@types/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.1.tgz", - "integrity": "sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==", - "requires": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "@types/react-dates": { - "version": "21.8.3", - "resolved": "https://registry.npmjs.org/@types/react-dates/-/react-dates-21.8.3.tgz", - "integrity": "sha512-MSG/A5UCXepPw5a9BtdOXfCCSMcQ5+oQIkm0K2u39sf4EJbsgngUg1zcoY3amxa6Hz0EWZkZOiExK/92J6hxUw==", - "dev": true, - "requires": { - "@types/react": "*", - "@types/react-outside-click-handler": "*", - "moment": "^2.26.0" - } - }, - "@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", - "requires": { - "@types/react": "*" - } - }, - "@types/react-outside-click-handler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/react-outside-click-handler/-/react-outside-click-handler-1.3.1.tgz", - "integrity": "sha512-0BNan5zIIDyO5k9LFSG+60ZxQ/0wf+LTF9BJx3oOUdOaJlZk6RCe52jRB75mlvLLJx2YLa61+NidOwBfptWMKw==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, - "@types/readdir-glob": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.2.tgz", - "integrity": "sha512-vwAYrNN/8yhp/FJRU6HUSD0yk6xfoOS8HrZa8ZL7j+X8hJpaC1hTcAiXX2IxaAkkvrz9mLyoEhYZTE3cEYvA9Q==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/requestidlecallback": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@types/requestidlecallback/-/requestidlecallback-0.3.4.tgz", - "integrity": "sha512-aTSyiZuRemRLTQkJPb25L7A4/eR2Teo5l4yJ1V6P3+MFxEZckTDkNKNtr/V1zEOMzS6H8DgxF22U6jPAPrzQvw==", - "dev": true - }, - "@types/resolve": { - "version": "1.20.6", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", - "integrity": "sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==", - "dev": true - }, - "@types/responselike": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/retry": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", - "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", - "dev": true - }, - "@types/scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" - }, - "@types/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-D/2EJvAlCEtYFEYmmlGwbGXuK886HzyCc3nZX/tkFTQdEU8jZDAgiv08P162yB17y4ZXZoq7yFAnW4GDBb9Now==", - "dev": true - }, - "@types/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", - "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", - "dev": true, - "requires": { - "@types/mime": "^1", - "@types/node": "*" - }, - "dependencies": { - "@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true - } - } - }, - "@types/serve-favicon": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/@types/serve-favicon/-/serve-favicon-2.5.5.tgz", - "integrity": "sha512-E/P1MhsGcalASnOVUPr9QQ4BIXyqQoGtLscG4fcMcEpZ7Z7tl6S4uSJnBJzWj7bj6rRZLIFOv0dR1YcepLNFFA==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/serve-static": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", - "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", - "dev": true, - "requires": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" - } - }, - "@types/shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@types/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-p3SZxGp6LXB6RPdMpJmquKjaxQlN/ijyBLTKGPg9IJK6J2g2sJsMmtXP9kNR+Axxi6MDKN2e/76HCOUmvkIpcw==", - "dev": true - }, - "@types/simple-peer": { - "version": "9.11.6", - "resolved": "https://registry.npmjs.org/@types/simple-peer/-/simple-peer-9.11.6.tgz", - "integrity": "sha512-6kD6yWzHJrVwx+N3RcC+5H9x/rZ7vRTDMrLl40eowvxXEKwvOW2W/ST5GlSQ/6j9yubSzaMj02LdNFTTfscQ3w==", - "requires": { - "@types/node": "*" - } - }, - "@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true - }, - "@types/sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-hkgzYF+qnIl8uTO8rmUSVSfQ8BIfMXC4yJAF4n8BE758YsKBZvFC4NumnAegj7KmylP0liEZNpb9RRGFMbFejA==", - "dev": true - }, - "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" - }, - "@types/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@types/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-dPWnWsf+kzIG140B8z2w3fr5D03TLWbOAFQl45xUpI3vcizeXriNR5VYkWZ+WTMsUHqZ9Xlt3hrxGNANFyNQfw==", - "dev": true - }, - "@types/tapable": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.5.tgz", - "integrity": "sha512-/gG2M/Imw7cQFp8PGvz/SwocNrmKFjFsm5Pb8HdbHkZ1K8pmuPzOX4VeVoiEecFCVf4CsN1r3/BRvx+6sNqwtQ==", - "dev": true - }, - "@types/teen_process": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/teen_process/-/teen_process-2.0.0.tgz", - "integrity": "sha512-Kb0NjBT9cJXg0mjkmYJbA1WM+4EcEpbUfLXxzKhyAihNU0ipuqRyOolTEB2nDU8D8aCI6EcBLaHbSVefED8lGQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/testing-library__jest-dom": { - "version": "5.14.5", - "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz", - "integrity": "sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==", - "dev": true, - "requires": { - "@types/jest": "*" - } - }, - "@types/tough-cookie": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", - "dev": true - }, - "@types/triple-beam": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.3.tgz", - "integrity": "sha512-6tOUG+nVHn0cJbVp25JFayS5UE6+xlbcNF9Lo9mU7U0zk3zeUShZied4YEQZjy1JBF043FSkdXw8YkUJuVtB5g==", - "dev": true - }, - "@types/uglify-js": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.9.2.tgz", - "integrity": "sha512-d6dIfpPbF+8B7WiCi2ELY7m0w1joD8cRW4ms88Emdb2w062NeEpbNCeWwVCgzLRpVG+5e74VFSg4rgJ2xXjEiQ==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - } - }, - "@types/unist": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", - "dev": true - }, - "@types/uuid": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.1.tgz", - "integrity": "sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg==", - "dev": true - }, - "@types/vfile": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz", - "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/unist": "*", - "@types/vfile-message": "*" - } - }, - "@types/vfile-message": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-1.0.1.tgz", - "integrity": "sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/unist": "*" - } - }, - "@types/webpack": { - "version": "4.41.33", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.33.tgz", - "integrity": "sha512-PPajH64Ft2vWevkerISMtnZ8rTs4YmRbs+23c402J0INmxDKCrhZNvwZYtzx96gY2wAtXdrK1BS2fiC8MlLr3g==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/tapable": "^1", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "anymatch": "^3.0.0", - "source-map": "^0.6.0" - } - }, - "@types/webpack-sources": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.7.tgz", - "integrity": "sha512-XyaHrJILjK1VHVC4aVlKsdNN5KBTwufMb43cQs+flGxtPAf/1Qwl8+Q0tp5BwEGaI8D6XT1L+9bSWXckgkjTLw==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.6.1" - } - }, - "@types/which": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/which/-/which-3.0.0.tgz", - "integrity": "sha512-ASCxdbsrwNfSMXALlC3Decif9rwDMu+80KGp5zI2RLRotfMsTv7fHL8W8VDp24wymzDyIFudhUeSCugrgRFfHQ==", - "dev": true - }, - "@types/wrap-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", - "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", - "dev": true - }, - "@types/ws": { - "version": "8.5.5", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", - "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", - "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==" - }, - "@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "dev": true, - "optional": true, - "requires": { - "@types/node": "*" - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.1.tgz", - "integrity": "sha512-3F5PtBzUW0dYlq77Lcqo13fv+58KDwUib3BddilE8ajPJT+faGgxmI9Sw+I8ZS22BYwoir9ZhNXcLi+S+I2bkw==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.4.1", - "@typescript-eslint/type-utils": "6.4.1", - "@typescript-eslint/utils": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "dependencies": { - "@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, - "@typescript-eslint/scope-manager": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", - "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1" - } - }, - "@typescript-eslint/types": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", - "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", - "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/utils": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", - "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.4.1", - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/typescript-estree": "6.4.1", - "semver": "^7.5.4" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", - "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.4.1", - "eslint-visitor-keys": "^3.4.1" - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - } - } - }, - "@typescript-eslint/parser": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.4.1.tgz", - "integrity": "sha512-610G6KHymg9V7EqOaNBMtD1GgpAmGROsmfHJPXNLCU9bfIuLrkdOygltK784F6Crboyd5tBFayPB7Sf0McrQwg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "6.4.1", - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/typescript-estree": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", - "debug": "^4.3.4" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", - "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1" - } - }, - "@typescript-eslint/types": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", - "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", - "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", - "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.4.1", - "eslint-visitor-keys": "^3.4.1" - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - } - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.4.1.tgz", - "integrity": "sha512-7ON8M8NXh73SGZ5XvIqWHjgX2f+vvaOarNliGhjrJnv1vdjG0LVIz+ToYfPirOoBi56jxAKLfsLm40+RvxVVXA==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "6.4.1", - "@typescript-eslint/utils": "6.4.1", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "dependencies": { - "@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, - "@typescript-eslint/scope-manager": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", - "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1" - } - }, - "@typescript-eslint/types": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", - "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", - "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/visitor-keys": "6.4.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/utils": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", - "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.4.1", - "@typescript-eslint/types": "6.4.1", - "@typescript-eslint/typescript-estree": "6.4.1", - "semver": "^7.5.4" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", - "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.4.1", - "eslint-visitor-keys": "^3.4.1" - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - } - } - }, - "@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "dependencies": { - "@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - } - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - } - } - }, - "@use-gesture/core": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz", - "integrity": "sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==" - }, - "@use-gesture/react": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/@use-gesture/react/-/react-10.3.1.tgz", - "integrity": "sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==", - "requires": { - "@use-gesture/core": "10.3.1" - } - }, - "@wdio/config": { - "version": "8.16.20", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.16.20.tgz", - "integrity": "sha512-JFD7aYs3nGF2kNhc0eV03mWFQMJku42NCBl+aedb1jzP3z6tBWV3n1a0ETS4MTLps8lFXBDZWvWEnl+ZvVrHZw==", - "dev": true, - "requires": { - "@wdio/logger": "8.16.17", - "@wdio/types": "8.16.12", - "@wdio/utils": "8.16.17", - "decamelize": "^6.0.0", - "deepmerge-ts": "^5.0.0", - "glob": "^10.2.2", - "import-meta-resolve": "^3.0.0", - "read-pkg-up": "^10.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", - "dev": true - }, - "find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "requires": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - } - }, - "glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - } - }, - "hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", - "dev": true, - "requires": { - "lru-cache": "^10.0.1" - } - }, - "jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "json-parse-even-better-errors": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", - "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", - "dev": true - }, - "lines-and-columns": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", - "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", - "dev": true - }, - "locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "requires": { - "p-locate": "^6.0.0" - } - }, - "lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - }, - "normalize-package-data": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", - "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", - "dev": true, - "requires": { - "hosted-git-info": "^7.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - } - }, - "p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "requires": { - "yocto-queue": "^1.0.0" - } - }, - "p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "requires": { - "p-limit": "^4.0.0" - } - }, - "parse-json": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", - "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.21.4", - "error-ex": "^1.3.2", - "json-parse-even-better-errors": "^3.0.0", - "lines-and-columns": "^2.0.3", - "type-fest": "^3.8.0" - }, - "dependencies": { - "type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true - } - } - }, - "path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true - }, - "read-pkg": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-8.1.0.tgz", - "integrity": "sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.1", - "normalize-package-data": "^6.0.0", - "parse-json": "^7.0.0", - "type-fest": "^4.2.0" - } - }, - "read-pkg-up": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-10.1.0.tgz", - "integrity": "sha512-aNtBq4jR8NawpKJQldrQcSW9y/d+KWH4v24HWkHljOZ7H0av+YTGANBzRh9A5pw7v/bLVsLVPpOhJ7gHNVy8lA==", - "dev": true, - "requires": { - "find-up": "^6.3.0", - "read-pkg": "^8.1.0", - "type-fest": "^4.2.0" - } - }, - "type-fest": { - "version": "4.26.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", - "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", - "dev": true - }, - "yocto-queue": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", - "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", - "dev": true - } - } - }, - "@wdio/logger": { - "version": "8.16.17", - "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-8.16.17.tgz", - "integrity": "sha512-zeQ41z3T+b4IsrriZZipayXxLNDuGsm7TdExaviNGojPVrIsQUCSd/FvlLHM32b7ZrMyInHenu/zx1cjAZO71g==", - "dev": true, - "requires": { - "chalk": "^5.1.2", - "loglevel": "^1.6.0", - "loglevel-plugin-prefix": "^0.8.4", - "strip-ansi": "^7.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true - }, - "chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "@wdio/protocols": { - "version": "8.16.5", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-8.16.5.tgz", - "integrity": "sha512-u9I57hIqmcOgrDH327ZCc2GTXv2YFN5bg6UaA3OUoJU7eJgGYHFB6RrjiNjLXer68iIx07wwVM70V/1xzijd3Q==", - "dev": true - }, - "@wdio/repl": { - "version": "8.10.1", - "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-8.10.1.tgz", - "integrity": "sha512-VZ1WFHTNKjR8Ga97TtV2SZM6fvRjWbYI2i/f4pJB4PtusorKvONAMJf2LQcUBIyzbVobqr7KSrcjmSwRolI+yw==", - "dev": true, - "requires": { - "@types/node": "^20.1.0" - }, - "dependencies": { - "@types/node": { - "version": "20.16.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", - "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", - "dev": true, - "requires": { - "undici-types": "~6.19.2" - } - }, - "undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true - } - } - }, - "@wdio/types": { - "version": "8.16.12", - "resolved": "https://registry.npmjs.org/@wdio/types/-/types-8.16.12.tgz", - "integrity": "sha512-TjCZJ3P9ual21G0dRv0lC9QgHGd3Igv+guEINevBKf/oD4/N84PvQ2eZG1nSbZ3xh8X/dvi+O64A6VEv43gx2w==", - "dev": true, - "requires": { - "@types/node": "^20.1.0" - }, - "dependencies": { - "@types/node": { - "version": "20.16.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", - "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", - "dev": true, - "requires": { - "undici-types": "~6.19.2" - } - }, - "undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true - } - } - }, - "@wdio/utils": { - "version": "8.16.17", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.16.17.tgz", - "integrity": "sha512-jDyOrxbQRDJO0OPt9UBgnwpUIKqtRn4+R0gR5VSDrIG/in5ZZg28yer8urrIVY4yY9ut5r/22VaMHZI9LEXF5w==", - "dev": true, - "requires": { - "@puppeteer/browsers": "^1.6.0", - "@wdio/logger": "8.16.17", - "@wdio/types": "8.16.12", - "decamelize": "^6.0.0", - "deepmerge-ts": "^5.1.0", - "edgedriver": "^5.3.5", - "geckodriver": "^4.2.0", - "get-port": "^7.0.0", - "got": "^13.0.0", - "import-meta-resolve": "^3.0.0", - "locate-app": "^2.1.0", - "safaridriver": "^0.1.0", - "split2": "^4.2.0", - "wait-port": "^1.0.4" - }, - "dependencies": { - "@puppeteer/browsers": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.9.1.tgz", - "integrity": "sha512-PuvK6xZzGhKPvlx3fpfdM2kYY3P/hB1URtK8wA7XUJ6prn6pp22zvJHu48th0SGcHL9SutbPHrFuQgfXTFobWA==", - "dev": true, - "requires": { - "debug": "4.3.4", - "extract-zip": "2.0.1", - "progress": "2.0.3", - "proxy-agent": "6.3.1", - "tar-fs": "3.0.4", - "unbzip2-stream": "1.4.3", - "yargs": "17.7.2" - } - }, - "@sindresorhus/is": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", - "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", - "dev": true - }, - "@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dev": true, - "requires": { - "defer-to-connect": "^2.0.1" - } - }, - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - }, - "cacheable-lookup": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", - "dev": true - }, - "cacheable-request": { - "version": "10.2.14", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", - "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", - "dev": true, - "requires": { - "@types/http-cache-semantics": "^4.0.2", - "get-stream": "^6.0.1", - "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.3", - "mimic-response": "^4.0.0", - "normalize-url": "^8.0.0", - "responselike": "^3.0.0" - }, - "dependencies": { - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - } - } - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "requires": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - } - }, - "get-port": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.1.0.tgz", - "integrity": "sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==", - "dev": true - }, - "got": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", - "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", - "dev": true, - "requires": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - }, - "dependencies": { - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - } - } - }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "http2-wrapper": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", - "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", - "dev": true, - "requires": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" - } - }, - "https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "lowercase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", - "dev": true - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "mimic-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", - "dev": true - }, - "normalize-url": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", - "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", - "dev": true - }, - "p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "dev": true - }, - "proxy-agent": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", - "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.2" - } - }, - "pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true - }, - "responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", - "dev": true, - "requires": { - "lowercase-keys": "^3.0.0" - } - }, - "socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, - "requires": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - } - }, - "split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "tar-fs": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", - "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", - "dev": true, - "requires": { - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - } - }, - "tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, - "requires": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, - "@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", - "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", - "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", - "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", - "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", - "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", - "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0" - } - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - }, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true - } - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", - "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", - "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", - "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", - "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", - "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/helper-wasm-section": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-opt": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", - "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", - "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", - "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", - "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/floating-point-hex-parser": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-code-frame": "1.9.0", - "@webassemblyjs/helper-fsm": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", - "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "@webpack-cli/configtest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", - "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true - }, - "@webpack-cli/info": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", - "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true - }, - "@webpack-cli/serve": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", - "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true - }, - "@wordpress/a11y": { - "version": "file:packages/a11y", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/dom-ready": "file:../dom-ready", - "@wordpress/i18n": "file:../i18n" - } - }, - "@wordpress/annotations": { - "version": "file:packages/annotations", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/data": "file:../data", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/rich-text": "file:../rich-text", - "uuid": "^9.0.1" - }, - "dependencies": { - "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - } - } - }, - "@wordpress/api-fetch": { - "version": "file:packages/api-fetch", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/i18n": "file:../i18n", - "@wordpress/url": "file:../url" - } - }, - "@wordpress/autop": { - "version": "file:packages/autop", - "requires": { - "@babel/runtime": "^7.16.0" - } - }, - "@wordpress/babel-plugin-import-jsx-pragma": { - "version": "file:packages/babel-plugin-import-jsx-pragma" - }, - "@wordpress/babel-plugin-makepot": { - "version": "file:packages/babel-plugin-makepot", - "requires": { - "deepmerge": "^4.3.0", - "gettext-parser": "^1.3.1", - "is-plain-object": "^5.0.0" - } - }, - "@wordpress/babel-preset-default": { - "version": "file:packages/babel-preset-default", - "requires": { - "@babel/core": "^7.16.0", - "@babel/plugin-transform-react-jsx": "^7.16.0", - "@babel/plugin-transform-runtime": "^7.16.0", - "@babel/preset-env": "^7.16.0", - "@babel/preset-typescript": "^7.16.0", - "@babel/runtime": "^7.16.0", - "@wordpress/browserslist-config": "file:../browserslist-config", - "@wordpress/warning": "file:../warning", - "browserslist": "^4.21.10", - "core-js": "^3.31.0", - "react": "^18.3.0" - } - }, - "@wordpress/base-styles": { - "version": "file:packages/base-styles" - }, - "@wordpress/blob": { - "version": "file:packages/blob", - "requires": { - "@babel/runtime": "^7.16.0" - } - }, - "@wordpress/block-directory": { - "version": "file:packages/block-directory", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/a11y": "file:../a11y", - "@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/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/plugins": "file:../plugins", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", - "change-case": "^4.1.2", - "clsx": "^2.1.1" - } - }, - "@wordpress/block-editor": { - "version": "file:packages/block-editor", - "requires": { - "@babel/runtime": "^7.16.0", - "@emotion/react": "^11.7.1", - "@emotion/styled": "^11.6.0", - "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/style-engine": "file:../style-engine", - "@wordpress/token-list": "file:../token-list", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", - "@wordpress/wordcount": "file:../wordcount", - "change-case": "^4.1.2", - "clsx": "^2.1.1", - "colord": "^2.7.0", - "deepmerge": "^4.3.0", - "diff": "^4.0.2", - "fast-deep-equal": "^3.1.3", - "memize": "^2.1.0", - "parsel-js": "^1.1.2", - "postcss": "^8.4.21", - "postcss-prefix-selector": "^1.16.0", - "postcss-urlrebase": "^1.4.0", - "react-autosize-textarea": "^7.1.0", - "react-easy-crop": "^5.0.6", - "remove-accents": "^0.5.0" - }, - "dependencies": { - "postcss-urlrebase": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.4.0.tgz", - "integrity": "sha512-rRaxMmWvXrn8Rk1PqsxmaJwldRHsr0WbbASKKCZYxXwotHkM/5X/6IrwaEe8pdzpbNGCEY86yhYMN0MhgOkADA==", - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" - }, - "react-easy-crop": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/react-easy-crop/-/react-easy-crop-5.0.6.tgz", - "integrity": "sha512-LV8te8NGC72k3l8uAqPAw73D2i9AbRlZqyo1Xz8VetwiMfkSKYgyqE3IFEwf5h+1g7AS1nMxBKk6ZPdhvLw6MQ==", - "requires": { - "normalize-wheel": "^1.0.1", - "tslib": "2.0.1" - } - }, - "tslib": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", - "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==" - } - } - }, - "@wordpress/block-library": { - "version": "file:packages/block-library", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/autop": "file:../autop", - "@wordpress/blob": "file:../blob", - "@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/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interactivity": "file:../interactivity", - "@wordpress/interactivity-router": "file:../interactivity-router", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/server-side-render": "file:../server-side-render", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/wordcount": "file:../wordcount", - "change-case": "^4.1.2", - "clsx": "^2.1.1", - "colord": "^2.7.0", - "escape-html": "^1.0.3", - "fast-average-color": "^9.1.1", - "fast-deep-equal": "^3.1.3", - "memize": "^2.1.0", - "remove-accents": "^0.5.0", - "uuid": "^9.0.1" - }, - "dependencies": { - "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - } - } - }, - "@wordpress/block-serialization-default-parser": { - "version": "file:packages/block-serialization-default-parser", - "requires": { - "@babel/runtime": "^7.16.0" - } - }, - "@wordpress/block-serialization-spec-parser": { - "version": "file:packages/block-serialization-spec-parser", - "requires": { - "pegjs": "^0.10.0", - "phpegjs": "^1.0.0-beta7" - } - }, - "@wordpress/blocks": { - "version": "file:packages/blocks", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/autop": "file:../autop", - "@wordpress/blob": "file:../blob", - "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/shortcode": "file:../shortcode", - "@wordpress/warning": "file:../warning", - "change-case": "^4.1.2", - "colord": "^2.7.0", - "fast-deep-equal": "^3.1.3", - "hpq": "^1.3.0", - "is-plain-object": "^5.0.0", - "memize": "^2.1.0", - "react-is": "^18.3.0", - "remove-accents": "^0.5.0", - "showdown": "^1.9.1", - "simple-html-tokenizer": "^0.5.7", - "uuid": "^9.0.1" - }, - "dependencies": { - "react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, - "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - } - } - }, - "@wordpress/browserslist-config": { - "version": "file:packages/browserslist-config" - }, - "@wordpress/commands": { - "version": "file:packages/commands", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/components": "file:../components", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/private-apis": "file:../private-apis", - "clsx": "^2.1.1", - "cmdk": "^1.0.0" - }, - "dependencies": { - "@radix-ui/react-dialog": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz", - "integrity": "sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==", - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-dismissable-layer": "1.0.5", - "@radix-ui/react-focus-guards": "1.0.1", - "@radix-ui/react-focus-scope": "1.0.4", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-portal": "1.0.4", - "@radix-ui/react-presence": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-slot": "1.0.2", - "@radix-ui/react-use-controllable-state": "1.0.1", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.5.5" - } - }, - "@radix-ui/react-dismissable-layer": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", - "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==", - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-escape-keydown": "1.0.3" - } - }, - "@radix-ui/react-focus-scope": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", - "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==", - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1" - } - }, - "@radix-ui/react-portal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", - "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==", - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - } - }, - "@radix-ui/react-presence": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", - "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==", - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1" - } - }, - "cmdk": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.0.0.tgz", - "integrity": "sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q==", - "requires": { - "@radix-ui/react-dialog": "1.0.5", - "@radix-ui/react-primitive": "1.0.3" - } - } - } - }, - "@wordpress/components": { - "version": "file:packages/components", - "requires": { - "@ariakit/react": "^0.4.10", - "@babel/runtime": "^7.16.0", - "@emotion/cache": "^11.7.1", - "@emotion/css": "^11.7.1", - "@emotion/react": "^11.7.1", - "@emotion/serialize": "^1.0.2", - "@emotion/styled": "^11.6.0", - "@emotion/utils": "^1.0.0", - "@floating-ui/react-dom": "^2.0.8", - "@types/gradient-parser": "0.1.3", - "@types/highlight-words-core": "1.2.1", - "@use-gesture/react": "^10.3.1", - "@wordpress/a11y": "file:../a11y", - "@wordpress/compose": "file:../compose", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/warning": "file:../warning", - "change-case": "^4.1.2", - "clsx": "^2.1.1", - "colord": "^2.7.0", - "date-fns": "^3.6.0", - "deepmerge": "^4.3.0", - "fast-deep-equal": "^3.1.3", - "framer-motion": "^11.1.9", - "gradient-parser": "^0.1.5", - "highlight-words-core": "^1.2.2", - "is-plain-object": "^5.0.0", - "memize": "^2.1.0", - "path-to-regexp": "^6.2.1", - "re-resizable": "^6.4.0", - "react-colorful": "^5.3.1", - "remove-accents": "^0.5.0", - "uuid": "^9.0.1" - }, - "dependencies": { - "@ariakit/react": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.10.tgz", - "integrity": "sha512-c1+6sNLj57aAXrBZMCVGG+OXeFrPAG0TV1jT7oPJcN/KLRs3aCuO3CCJVep/eKepFzzK01kNRGYX3wPT1TXPNw==", - "requires": { - "@ariakit/react-core": "0.4.10" - } - }, - "@ariakit/react-core": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.10.tgz", - "integrity": "sha512-r6DZmtHBmSoOj848+RpBwdZy/55YxPhMhfH14JIO2OLn1F6iSFkQwR7AAGpIrlYycWJFSF7KrQu50O+SSfFJdQ==", - "requires": { - "@ariakit/core": "0.4.9", - "@floating-ui/dom": "^1.0.0", - "use-sync-external-store": "^1.2.0" - } - }, - "@floating-ui/react-dom": { - "version": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.1.tgz", - "integrity": "sha512-rZtAmSht4Lry6gdhAJDrCp/6rKN7++JnL1/Anbr/DdeyYXQPxvg/ivrbYvJulbRf4vL8b212suwMM2lxbv+RQA==", - "requires": { - "@floating-ui/dom": "^1.3.0" - } - }, - "@types/gradient-parser": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@types/gradient-parser/-/gradient-parser-0.1.3.tgz", - "integrity": "sha512-XDbrTSBlQV9nxE1GiDL3FaOPy4G/KaJkhDutBX48Kg8CYZMBARyyDFGCWfWJn4pobmInmwud1xxH7VJMAr0CKQ==" - }, - "path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==" - }, - "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - } - } - }, - "@wordpress/compose": { - "version": "file:packages/compose", - "requires": { - "@babel/runtime": "^7.16.0", - "@types/mousetrap": "^1.6.8", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/undo-manager": "file:../undo-manager", - "change-case": "^4.1.2", - "clipboard": "^2.0.11", - "mousetrap": "^1.6.5", - "use-memo-one": "^1.1.1" - }, - "dependencies": { - "clipboard": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", - "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", - "requires": { - "good-listener": "^1.2.2", - "select": "^1.1.2", - "tiny-emitter": "^2.0.0" - } - } - } - }, - "@wordpress/core-commands": { - "version": "file:packages/core-commands", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/commands": "file:../commands", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/router": "file:../router", - "@wordpress/url": "file:../url" - } - }, - "@wordpress/core-data": { - "version": "file:packages/core-data", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/sync": "file:../sync", - "@wordpress/undo-manager": "file:../undo-manager", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", - "change-case": "^4.1.2", - "equivalent-key-map": "^0.2.2", - "fast-deep-equal": "^3.1.3", - "memize": "^2.1.0", - "uuid": "^9.0.1" - }, - "dependencies": { - "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - } - } - }, - "@wordpress/create-block": { - "version": "file:packages/create-block", - "requires": { - "@wordpress/lazy-import": "file:../lazy-import", - "chalk": "^4.0.0", - "change-case": "^4.1.2", - "check-node-version": "^4.1.0", - "commander": "^9.2.0", - "execa": "^4.0.2", - "fast-glob": "^3.2.7", - "inquirer": "^7.1.0", - "make-dir": "^3.0.0", - "mustache": "^4.0.0", - "npm-package-arg": "^8.1.5", - "rimraf": "^3.0.2", - "write-pkg": "^4.0.0" - } - }, - "@wordpress/create-block-tutorial-template": { - "version": "file:packages/create-block-tutorial-template" - }, - "@wordpress/customize-widgets": { - "version": "file:packages/customize-widgets", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/widgets": "file:../widgets", - "clsx": "^2.1.1", - "fast-deep-equal": "^3.1.3" - } - }, - "@wordpress/data": { - "version": "file:packages/data", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/compose": "file:../compose", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/redux-routine": "file:../redux-routine", - "deepmerge": "^4.3.0", - "equivalent-key-map": "^0.2.2", - "is-plain-object": "^5.0.0", - "is-promise": "^4.0.0", - "redux": "^4.1.2", - "rememo": "^4.0.2", - "use-memo-one": "^1.1.1" - } - }, - "@wordpress/data-controls": { - "version": "file:packages/data-controls", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated" - } - }, - "@wordpress/dataviews": { - "version": "file:packages/dataviews", - "requires": { - "@ariakit/react": "^0.4.10", - "@babel/runtime": "^7.16.0", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/warning": "file:../warning", - "clsx": "^2.1.1", - "remove-accents": "^0.5.0" - }, - "dependencies": { - "@ariakit/react": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.10.tgz", - "integrity": "sha512-c1+6sNLj57aAXrBZMCVGG+OXeFrPAG0TV1jT7oPJcN/KLRs3aCuO3CCJVep/eKepFzzK01kNRGYX3wPT1TXPNw==", - "requires": { - "@ariakit/react-core": "0.4.10" - } - }, - "@ariakit/react-core": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.10.tgz", - "integrity": "sha512-r6DZmtHBmSoOj848+RpBwdZy/55YxPhMhfH14JIO2OLn1F6iSFkQwR7AAGpIrlYycWJFSF7KrQu50O+SSfFJdQ==", - "requires": { - "@ariakit/core": "0.4.9", - "@floating-ui/dom": "^1.0.0", - "use-sync-external-store": "^1.2.0" - } - } - } - }, - "@wordpress/date": { - "version": "file:packages/date", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/deprecated": "file:../deprecated", - "moment": "^2.29.4", - "moment-timezone": "^0.5.40" - } - }, - "@wordpress/dependency-extraction-webpack-plugin": { - "version": "file:packages/dependency-extraction-webpack-plugin", - "requires": { - "json2php": "^0.0.7" - } - }, - "@wordpress/deprecated": { - "version": "file:packages/deprecated", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/hooks": "file:../hooks" - } - }, - "@wordpress/docgen": { - "version": "file:packages/docgen", - "requires": { - "@babel/core": "^7.16.0", - "comment-parser": "^1.1.1", - "mdast-util-inject": "1.1.0", - "optionator": "0.8.2", - "remark": "10.0.1", - "remark-parse": "6.0.3", - "unified": "7.1.0" - } - }, - "@wordpress/dom": { - "version": "file:packages/dom", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/deprecated": "file:../deprecated" - } - }, - "@wordpress/dom-ready": { - "version": "file:packages/dom-ready", - "requires": { - "@babel/runtime": "^7.16.0" - } - }, - "@wordpress/e2e-test-utils": { - "version": "file:packages/e2e-test-utils", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/url": "file:../url", - "change-case": "^4.1.2", - "form-data": "^4.0.0", - "node-fetch": "^2.6.0" - } - }, - "@wordpress/e2e-test-utils-playwright": { - "version": "file:packages/e2e-test-utils-playwright", - "requires": { - "change-case": "^4.1.2", - "form-data": "^4.0.0", - "get-port": "^5.1.1", - "lighthouse": "^10.4.0", - "mime": "^3.0.0", - "web-vitals": "^4.2.1" - }, - "dependencies": { - "web-vitals": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.1.tgz", - "integrity": "sha512-U6bAxeudnhDqcXNl50JC4hLlqox9DZnngxfISZm3DMZnonW35xtJOVUc091L+DOY+6hVZVpKXoiCP0RiT6339Q==", - "dev": true - } - } - }, - "@wordpress/e2e-tests": { - "version": "file:packages/e2e-tests", - "requires": { - "@wordpress/e2e-test-utils": "file:../e2e-test-utils", - "@wordpress/interactivity": "file:../interactivity", - "@wordpress/interactivity-router": "file:../interactivity-router", - "@wordpress/jest-console": "file:../jest-console", - "@wordpress/jest-puppeteer-axe": "file:../jest-puppeteer-axe", - "@wordpress/scripts": "file:../scripts", - "@wordpress/url": "file:../url", - "chalk": "^4.0.0", - "expect-puppeteer": "^4.4.0", - "filenamify": "^4.2.0", - "jest-message-util": "^29.6.2", - "jest-snapshot": "^29.6.2", - "uuid": "^9.0.1" - }, - "dependencies": { - "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - } - } - }, - "@wordpress/edit-post": { - "version": "file:packages/edit-post", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-commands": "file:../core-commands", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/warning": "file:../warning", - "@wordpress/widgets": "file:../widgets", - "clsx": "^2.1.1", - "memize": "^2.1.0" - } - }, - "@wordpress/edit-site": { - "version": "file:packages/edit-site", - "requires": { - "@babel/runtime": "^7.16.0", - "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-commands": "file:../core-commands", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/primitives": "file:../primitives", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/router": "file:../router", - "@wordpress/style-engine": "file:../style-engine", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/widgets": "file:../widgets", - "@wordpress/wordcount": "file:../wordcount", - "change-case": "^4.1.2", - "clsx": "^2.1.1", - "colord": "^2.9.2", - "fast-deep-equal": "^3.1.3", - "memize": "^2.1.0", - "react-autosize-textarea": "^7.1.0" - } - }, - "@wordpress/edit-widgets": { - "version": "file:packages/edit-widgets", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/url": "file:../url", - "@wordpress/widgets": "file:../widgets", - "clsx": "^2.1.1" - } - }, - "@wordpress/editor": { - "version": "file:packages/editor", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/fields": "file:../fields", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/server-side-render": "file:../server-side-render", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", - "@wordpress/wordcount": "file:../wordcount", - "change-case": "^4.1.2", - "client-zip": "^2.4.5", - "clsx": "^2.1.1", - "date-fns": "^3.6.0", - "deepmerge": "^4.3.0", - "fast-deep-equal": "^3.1.3", - "is-plain-object": "^5.0.0", - "memize": "^2.1.0", - "react-autosize-textarea": "^7.1.0", - "remove-accents": "^0.5.0", - "uuid": "^9.0.1" - } - }, - "@wordpress/element": { - "version": "file:packages/element", - "requires": { - "@babel/runtime": "^7.16.0", - "@types/react": "^18.2.79", - "@types/react-dom": "^18.2.25", - "@wordpress/escape-html": "file:../escape-html", - "change-case": "^4.1.2", - "is-plain-object": "^5.0.0", - "react": "^18.3.0", - "react-dom": "^18.3.0" - } - }, - "@wordpress/env": { - "version": "file:packages/env", - "requires": { - "chalk": "^4.0.0", - "copy-dir": "^1.3.0", - "docker-compose": "^0.24.3", - "extract-zip": "^1.6.7", - "got": "^11.8.5", - "inquirer": "^7.1.0", - "js-yaml": "^3.13.1", - "ora": "^4.0.2", - "rimraf": "^3.0.2", - "simple-git": "^3.5.0", - "terminal-link": "^2.0.0", - "yargs": "^17.3.0" - }, - "dependencies": { - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "docker-compose": { - "version": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.24.2.tgz", - "integrity": "sha512-2/WLvA7UZ6A2LDLQrYW0idKipmNBWhtfvrn2yzjC5PnHDzuFVj1zAZN6MJxVMKP0zZH8uzAK6OwVZYHGuyCmTw==", - "dev": true, - "requires": { - "yaml": "^2.2.2" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, - "@wordpress/escape-html": { - "version": "file:packages/escape-html", - "requires": { - "@babel/runtime": "^7.16.0" - } - }, - "@wordpress/eslint-plugin": { - "version": "file:packages/eslint-plugin", - "requires": { - "@babel/eslint-parser": "^7.16.0", - "@typescript-eslint/eslint-plugin": "^6.4.1", - "@typescript-eslint/parser": "^6.4.1", - "@wordpress/babel-preset-default": "file:../babel-preset-default", - "@wordpress/prettier-config": "file:../prettier-config", - "cosmiconfig": "^7.0.0", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-jest": "^27.2.3", - "eslint-plugin-jsdoc": "^46.4.6", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-playwright": "^0.15.3", - "eslint-plugin-prettier": "^5.0.0", - "eslint-plugin-react": "^7.27.0", - "eslint-plugin-react-hooks": "^4.3.0", - "globals": "^13.12.0", - "requireindex": "^1.2.0" - } - }, - "@wordpress/fields": { - "version": "file:packages/fields", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", - "change-case": "4.1.2", - "client-zip": "^2.4.5" - } - }, - "@wordpress/format-library": { - "version": "file:packages/format-library", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/a11y": "file:../a11y", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/url": "file:../url" - } - }, - "@wordpress/hooks": { - "version": "file:packages/hooks", - "requires": { - "@babel/runtime": "^7.16.0" - } - }, - "@wordpress/html-entities": { - "version": "file:packages/html-entities", - "requires": { - "@babel/runtime": "^7.16.0" - } - }, - "@wordpress/i18n": { - "version": "file:packages/i18n", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/hooks": "file:../hooks", - "gettext-parser": "^1.3.1", - "memize": "^2.1.0", - "sprintf-js": "^1.1.1", - "tannin": "^1.2.0" - } - }, - "@wordpress/icons": { - "version": "file:packages/icons", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/element": "file:../element", - "@wordpress/primitives": "file:../primitives" - } - }, - "@wordpress/interactivity": { - "version": "file:packages/interactivity", - "requires": { - "@preact/signals": "^1.2.2", - "preact": "^10.19.3" - }, - "dependencies": { - "@preact/signals": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@preact/signals/-/signals-1.2.2.tgz", - "integrity": "sha512-ColCqdo4cRP18bAuIR4Oik5rDpiyFtPIJIygaYPMEAwTnl4buWkBOflGBSzhYyPyJfKpkwlekrvK+1pzQ2ldWw==", - "requires": { - "@preact/signals-core": "^1.4.0" - } - }, - "preact": { - "version": "10.19.3", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.3.tgz", - "integrity": "sha512-nHHTeFVBTHRGxJXKkKu5hT8C/YWBkPso4/Gad6xuj5dbptt9iF9NZr9pHbPhBrnT2klheu7mHTxTZ/LjwJiEiQ==" - } - } - }, - "@wordpress/interactivity-router": { - "version": "file:packages/interactivity-router", - "requires": { - "@wordpress/a11y": "file:../a11y", - "@wordpress/interactivity": "file:../interactivity" - } - }, - "@wordpress/interface": { - "version": "file:packages/interface", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/a11y": "file:../a11y", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/viewport": "file:../viewport", - "clsx": "^2.1.1" - } - }, - "@wordpress/is-shallow-equal": { - "version": "file:packages/is-shallow-equal", - "requires": { - "@babel/runtime": "^7.16.0" - } - }, - "@wordpress/jest-console": { - "version": "file:packages/jest-console", - "requires": { - "@babel/runtime": "^7.16.0", - "jest-matcher-utils": "^29.6.2" - } - }, - "@wordpress/jest-preset-default": { - "version": "file:packages/jest-preset-default", - "requires": { - "@wordpress/jest-console": "file:../jest-console", - "babel-jest": "^29.6.2" - } - }, - "@wordpress/jest-puppeteer-axe": { - "version": "file:packages/jest-puppeteer-axe", - "requires": { - "@axe-core/puppeteer": "^4.0.0", - "@babel/runtime": "^7.16.0" - } - }, - "@wordpress/keyboard-shortcuts": { - "version": "file:packages/keyboard-shortcuts", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/keycodes": "file:../keycodes" - } - }, - "@wordpress/keycodes": { - "version": "file:packages/keycodes", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/i18n": "file:../i18n" - } - }, - "@wordpress/lazy-import": { - "version": "file:packages/lazy-import", - "requires": { - "execa": "^4.0.2", - "npm-package-arg": "^8.1.5", - "semver": "^7.3.5" - } - }, - "@wordpress/list-reusable-blocks": { - "version": "file:packages/list-reusable-blocks", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "change-case": "^4.1.2" - } - }, - "@wordpress/media-utils": { - "version": "file:packages/media-utils", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n" - } - }, - "@wordpress/notices": { - "version": "file:packages/notices", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/a11y": "file:../a11y", - "@wordpress/data": "file:../data" - } - }, - "@wordpress/npm-package-json-lint-config": { - "version": "file:packages/npm-package-json-lint-config" - }, - "@wordpress/nux": { - "version": "file:packages/nux", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons" - } - }, - "@wordpress/patterns": { - "version": "file:packages/patterns", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/a11y": "file:../a11y", - "@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/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url" - } - }, - "@wordpress/plugins": { - "version": "file:packages/plugins", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "memize": "^2.0.1" - } - }, - "@wordpress/postcss-plugins-preset": { - "version": "file:packages/postcss-plugins-preset", - "requires": { - "@wordpress/base-styles": "file:../base-styles", - "autoprefixer": "^10.2.5" - } - }, - "@wordpress/postcss-themes": { - "version": "file:packages/postcss-themes" - }, - "@wordpress/preferences": { - "version": "file:packages/preferences", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/a11y": "file:../a11y", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/private-apis": "file:../private-apis", - "clsx": "^2.1.1" - } - }, - "@wordpress/preferences-persistence": { - "version": "file:packages/preferences-persistence", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/api-fetch": "file:../api-fetch" - } - }, - "@wordpress/prettier-config": { - "version": "file:packages/prettier-config" - }, - "@wordpress/primitives": { - "version": "file:packages/primitives", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/element": "file:../element", - "clsx": "^2.1.1" - } - }, - "@wordpress/priority-queue": { - "version": "file:packages/priority-queue", - "requires": { - "@babel/runtime": "^7.16.0", - "requestidlecallback": "^0.3.0" - } - }, - "@wordpress/private-apis": { - "version": "file:packages/private-apis", - "requires": { - "@babel/runtime": "^7.16.0" - } - }, - "@wordpress/project-management-automation": { - "version": "file:packages/project-management-automation", - "requires": { - "@actions/core": "1.9.1", - "@actions/github": "^5.0.0", - "@babel/runtime": "^7.16.0", - "@octokit/request-error": "^2.1.0", - "@octokit/webhooks": "^9.26.3" - }, - "dependencies": { - "@octokit/webhooks": { - "version": "9.26.3", - "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.26.3.tgz", - "integrity": "sha512-DLGk+gzeVq5oK89Bo601txYmyrelMQ7Fi5EnjHE0Xs8CWicy2xkmnJMKptKJrBJpstqbd/9oeDFi/Zj2pudBDQ==", - "dev": true, - "requires": { - "@octokit/request-error": "^2.0.2", - "@octokit/webhooks-methods": "^2.0.0", - "@octokit/webhooks-types": "5.8.0", - "aggregate-error": "^3.1.0" - } - } - } - }, - "@wordpress/react-i18n": { - "version": "file:packages/react-i18n", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "utility-types": "^3.10.0" - } - }, - "@wordpress/react-native-aztec": { - "version": "file:packages/react-native-aztec", - "requires": { - "@wordpress/element": "file:../element", - "@wordpress/keycodes": "file:../keycodes" - } - }, - "@wordpress/react-native-bridge": { - "version": "file:packages/react-native-bridge", - "requires": { - "@wordpress/react-native-aztec": "file:../react-native-aztec" - } - }, - "@wordpress/react-native-editor": { - "version": "file:packages/react-native-editor", - "requires": { - "@babel/runtime": "^7.20.0", - "@react-native-clipboard/clipboard": "1.11.2", - "@react-native-community/blur": "4.2.0", - "@react-native-community/slider": "https://raw.githubusercontent.com/wordpress-mobile/react-native-slider/v3.0.2-wp-5/react-native-community-slider-3.0.2-wp-5.tgz", - "@react-native-masked-view/masked-view": "0.3.0", - "@react-navigation/core": "5.12.0", - "@react-navigation/native": "6.0.14", - "@react-navigation/routers": "5.4.9", - "@react-navigation/stack": "6.3.5", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/data": "file:../data", - "@wordpress/edit-post": "file:../edit-post", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/react-native-aztec": "file:../react-native-aztec", - "@wordpress/react-native-bridge": "file:../react-native-bridge", - "core-js": "^3.31.0", - "fast-average-color": "^9.1.1", - "gettext-parser": "^1.3.1", - "jed": "^1.1.1", - "jsdom-jscore-rn": "0.1.8", - "node-fetch": "^2.6.0", - "react-native": "0.73.3", - "react-native-fast-image": "8.5.11", - "react-native-gesture-handler": "2.14.1", - "react-native-get-random-values": "1.4.0", - "react-native-linear-gradient": "2.7.3", - "react-native-modal": "13.0.1", - "react-native-reanimated": "3.6.2", - "react-native-safe-area": "^0.5.0", - "react-native-safe-area-context": "4.8.2", - "react-native-sass-transformer": "^1.1.1", - "react-native-screens": "3.29.0", - "react-native-svg": "14.0.0", - "react-native-url-polyfill": "1.3.0", - "react-native-video": "https://raw.githubusercontent.com/wordpress-mobile/react-native-video/5.2.0-wp-7/react-native-video-5.2.0-wp-7.tgz", - "react-native-webview": "13.6.1" - }, - "dependencies": { - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "react-native-url-polyfill": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/react-native-url-polyfill/-/react-native-url-polyfill-1.3.0.tgz", - "integrity": "sha512-w9JfSkvpqqlix9UjDvJjm1EjSt652zVQ6iwCIj1cVVkwXf4jQhQgTNXY6EVTwuAmUjg6BC6k9RHCBynoLFo3IQ==", - "requires": { - "whatwg-url-without-unicode": "8.0.0-3" - } - }, - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==" - }, - "whatwg-url-without-unicode": { - "version": "8.0.0-3", - "resolved": "https://registry.npmjs.org/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz", - "integrity": "sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==", - "requires": { - "buffer": "^5.4.3", - "punycode": "^2.1.1", - "webidl-conversions": "^5.0.0" - } - } - } - }, - "@wordpress/readable-js-assets-webpack-plugin": { - "version": "file:packages/readable-js-assets-webpack-plugin" - }, - "@wordpress/redux-routine": { - "version": "file:packages/redux-routine", - "requires": { - "@babel/runtime": "^7.16.0", - "is-plain-object": "^5.0.0", - "is-promise": "^4.0.0", - "rungen": "^0.3.2" - } - }, - "@wordpress/report-flaky-tests": { - "version": "file:packages/report-flaky-tests", - "requires": { - "@actions/core": "^1.8.0", - "@actions/github": "^5.0.1", - "jest-message-util": "^29.6.2" - }, - "dependencies": { - "@actions/github": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz", - "integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==", - "dev": true, - "requires": { - "@actions/http-client": "^2.0.1", - "@octokit/core": "^3.6.0", - "@octokit/plugin-paginate-rest": "^2.17.0", - "@octokit/plugin-rest-endpoint-methods": "^5.13.0" - } - } - } - }, - "@wordpress/reusable-blocks": { - "version": "file:packages/reusable-blocks", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url" - } - }, - "@wordpress/rich-text": { - "version": "file:packages/rich-text", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/a11y": "file:../a11y", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/i18n": "file:../i18n", - "@wordpress/keycodes": "file:../keycodes", - "memize": "^2.1.0" - } - }, - "@wordpress/router": { - "version": "file:packages/router", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/element": "file:../element", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", - "history": "^5.3.0" - } - }, - "@wordpress/scripts": { - "version": "file:packages/scripts", - "requires": { - "@babel/core": "^7.16.0", - "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", - "@svgr/webpack": "^8.0.1", - "@wordpress/babel-preset-default": "file:../babel-preset-default", - "@wordpress/browserslist-config": "file:../browserslist-config", - "@wordpress/dependency-extraction-webpack-plugin": "file:../dependency-extraction-webpack-plugin", - "@wordpress/e2e-test-utils-playwright": "file:../e2e-test-utils-playwright", - "@wordpress/eslint-plugin": "file:../eslint-plugin", - "@wordpress/jest-preset-default": "file:../jest-preset-default", - "@wordpress/npm-package-json-lint-config": "file:../npm-package-json-lint-config", - "@wordpress/postcss-plugins-preset": "file:../postcss-plugins-preset", - "@wordpress/prettier-config": "file:../prettier-config", - "@wordpress/stylelint-config": "file:../stylelint-config", - "adm-zip": "^0.5.9", - "babel-jest": "^29.6.2", - "babel-loader": "^8.2.3", - "browserslist": "^4.21.10", - "chalk": "^4.0.0", - "check-node-version": "^4.1.0", - "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^10.2.0", - "cross-spawn": "^5.1.0", - "css-loader": "^6.2.0", - "cssnano": "^6.0.1", - "cwd": "^0.10.0", - "dir-glob": "^3.0.1", - "eslint": "^8.3.0", - "expect-puppeteer": "^4.4.0", - "fast-glob": "^3.2.7", - "filenamify": "^4.2.0", - "jest": "^29.6.2", - "jest-dev-server": "^9.0.1", - "jest-environment-jsdom": "^29.6.2", - "jest-environment-node": "^29.6.2", - "markdownlint-cli": "^0.31.1", - "merge-deep": "^3.0.3", - "mini-css-extract-plugin": "^2.5.1", - "minimist": "^1.2.0", - "npm-package-json-lint": "^6.4.0", - "npm-packlist": "^3.0.0", - "postcss": "^8.4.5", - "postcss-import": "^16.1.0", - "postcss-loader": "^6.2.1", - "prettier": "npm:wp-prettier@3.0.3", - "puppeteer-core": "^23.1.0", - "react-refresh": "^0.14.0", - "read-pkg-up": "^7.0.1", - "resolve-bin": "^0.4.0", - "rtlcss-webpack-plugin": "^4.0.7", - "sass": "^1.35.2", - "sass-loader": "^12.1.0", - "schema-utils": "^4.2.0", - "source-map-loader": "^3.0.0", - "stylelint": "^16.8.2", - "terser-webpack-plugin": "^5.3.9", - "url-loader": "^4.1.1", - "webpack": "^5.88.2", - "webpack-bundle-analyzer": "^4.9.1", - "webpack-cli": "^5.1.4", - "webpack-dev-server": "^4.15.1" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "dev": true, - "requires": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "babel-loader": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.4.1.tgz", - "integrity": "sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==", - "dev": true, - "requires": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.4", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-dev-server": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/jest-dev-server/-/jest-dev-server-9.0.1.tgz", - "integrity": "sha512-eqpJKSvVl4M0ojHZUPNbka8yEzLNbIMiINXDsuMF3lYfIdRO2iPqy+ASR4wBQ6nUyR3OT24oKPWhpsfLhgAVyg==", - "dev": true, - "requires": { - "chalk": "^4.1.2", - "cwd": "^0.10.0", - "find-process": "^1.4.7", - "prompts": "^2.4.2", - "spawnd": "^9.0.1", - "tree-kill": "^1.2.2", - "wait-on": "^7.0.1" - } - }, - "joi": { - "version": "17.11.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", - "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - } - }, - "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "dependencies": { - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - } - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - }, - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - }, - "spawnd": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-9.0.1.tgz", - "integrity": "sha512-vaMk8E9CpbjTYToBxLXowDeArGf1+yI7A6PU6Nr57b2g8BVY8nRi5vTBj3bMF8UkCrMdTMyf/Lh+lrcrW2z7pw==", - "dev": true, - "requires": { - "signal-exit": "^4.1.0", - "tree-kill": "^1.2.2" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "wait-on": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.2.0.tgz", - "integrity": "sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ==", - "dev": true, - "requires": { - "axios": "^1.6.1", - "joi": "^17.11.0", - "lodash": "^4.17.21", - "minimist": "^1.2.8", - "rxjs": "^7.8.1" - } - } - } - }, - "@wordpress/server-side-render": { - "version": "file:packages/server-side-render", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/url": "file:../url", - "fast-deep-equal": "^3.1.3" - } - }, - "@wordpress/shortcode": { - "version": "file:packages/shortcode", - "requires": { - "@babel/runtime": "^7.16.0", - "memize": "^2.0.1" - } - }, - "@wordpress/style-engine": { - "version": "file:packages/style-engine", - "requires": { - "@babel/runtime": "^7.16.0", - "change-case": "^4.1.2" - } - }, - "@wordpress/stylelint-config": { - "version": "file:packages/stylelint-config", - "requires": { - "@stylistic/stylelint-plugin": "^3.0.1", - "stylelint-config-recommended": "^14.0.1", - "stylelint-config-recommended-scss": "^14.1.0" - }, - "dependencies": { - "css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, - "requires": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - } - }, - "mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true - }, - "stylelint-config-recommended": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", - "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", - "dev": true - }, - "stylelint-config-recommended-scss": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.1.0.tgz", - "integrity": "sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg==", - "dev": true, - "requires": { - "postcss-scss": "^4.0.9", - "stylelint-config-recommended": "^14.0.1", - "stylelint-scss": "^6.4.0" - } - }, - "stylelint-scss": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.5.1.tgz", - "integrity": "sha512-ZLqdqihm6uDYkrsOeD6YWb+stZI8Wn92kUNDhE4M+g9g1aCnRv0JlOrttFiAJJwaNzpdQgX3YJb5vDQXVuO9Ww==", - "dev": true, - "requires": { - "css-tree": "2.3.1", - "is-plain-object": "5.0.0", - "known-css-properties": "^0.34.0", - "postcss-media-query-parser": "^0.2.3", - "postcss-resolve-nested-selector": "^0.1.4", - "postcss-selector-parser": "^6.1.1", - "postcss-value-parser": "^4.2.0" - } - } - } - }, - "@wordpress/sync": { - "version": "file:packages/sync", - "requires": { - "@babel/runtime": "^7.16.0", - "@types/simple-peer": "^9.11.5", - "@wordpress/url": "file:../url", - "import-locals": "^2.0.0", - "lib0": "^0.2.42", - "simple-peer": "^9.11.0", - "y-indexeddb": "~9.0.11", - "y-protocols": "^1.0.5", - "y-webrtc": "~10.2.5", - "yjs": "~13.6.6" - } - }, - "@wordpress/token-list": { - "version": "file:packages/token-list", - "requires": { - "@babel/runtime": "^7.16.0" - } - }, - "@wordpress/undo-manager": { - "version": "file:packages/undo-manager", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal" - } - }, - "@wordpress/url": { - "version": "file:packages/url", - "requires": { - "@babel/runtime": "^7.16.0", - "remove-accents": "^0.5.0" - } - }, - "@wordpress/viewport": { - "version": "file:packages/viewport", - "requires": { - "@babel/runtime": "^7.16.0", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element" - } - }, - "@wordpress/warning": { - "version": "file:packages/warning" - }, - "@wordpress/widgets": { - "version": "file:packages/widgets", - "requires": { - "@babel/runtime": "^7.16.0", - "@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/notices": "file:../notices", - "clsx": "^2.1.1" - } - }, - "@wordpress/wordcount": { - "version": "file:packages/wordcount", - "requires": { - "@babel/runtime": "^7.16.0" - } - }, - "@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", - "dev": true - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "@yarnpkg/esbuild-plugin-pnp": { - "version": "3.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@yarnpkg/esbuild-plugin-pnp/-/esbuild-plugin-pnp-3.0.0-rc.15.tgz", - "integrity": "sha512-kYzDJO5CA9sy+on/s2aIW0411AklfCi8Ck/4QDivOqsMKpStZA2SsR+X27VTggGwpStWaLrjJcDcdDMowtG8MA==", - "dev": true, - "requires": { - "tslib": "^2.4.0" - } - }, - "@yarnpkg/fslib": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@yarnpkg/fslib/-/fslib-2.10.3.tgz", - "integrity": "sha512-41H+Ga78xT9sHvWLlFOZLIhtU6mTGZ20pZ29EiZa97vnxdohJD2AF42rCoAoWfqUz486xY6fhjMH+DYEM9r14A==", - "dev": true, - "requires": { - "@yarnpkg/libzip": "^2.3.0", - "tslib": "^1.13.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@yarnpkg/libzip": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/libzip/-/libzip-2.3.0.tgz", - "integrity": "sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==", - "dev": true, - "requires": { - "@types/emscripten": "^1.39.6", - "tslib": "^1.13.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, - "@yarnpkg/parsers": { - "version": "3.0.0-rc.46", - "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", - "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", - "dev": true, - "requires": { - "js-yaml": "^3.10.0", - "tslib": "^2.4.0" - } - }, - "@zkochan/js-yaml": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz", - "integrity": "sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - } - } - }, - "abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true - }, - "acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - }, - "add-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", - "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==", - "dev": true - }, - "address": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", - "dev": true - }, - "adm-zip": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz", - "integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", - "dev": true, - "requires": { - "humanize-ms": "^1.2.1" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "dependencies": { - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - } - } - }, - "ajv": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.7.1.tgz", - "integrity": "sha512-gPpOObTO1QjbnN1sVMjJcp1TF9nggMfO4MBR5uQl6ZVTOaEPq5i4oq/6R9q2alMMPB3eg53wFv1RuJBLuxf3Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "dependencies": { - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } - } - }, - "ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true - }, - "anser": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", - "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==" - }, - "ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - } - } - }, - "ansi-fragments": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz", - "integrity": "sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==", - "requires": { - "colorette": "^1.0.7", - "slice-ansi": "^2.0.0", - "strip-ansi": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-sequence-parser": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", - "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - }, - "dependencies": { - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - } - } - }, - "any-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", - "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", - "dev": true - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "app-root-dir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/app-root-dir/-/app-root-dir-1.0.2.tgz", - "integrity": "sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g==", - "dev": true - }, - "app-root-path": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.2.1.tgz", - "integrity": "sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA==" - }, - "appdirsjs": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.7.tgz", - "integrity": "sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==" - }, - "appium": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/appium/-/appium-2.0.0.tgz", - "integrity": "sha512-SfpaYI35aM2KcShL0gOMDcni9CIev4X+WfEFfncsoM+S3dyPd++FjwoH2pmRDk4yHTDNz8gCTbUizQN8fJgYpw==", - "dev": true, - "requires": { - "@appium/base-driver": "^9.3.15", - "@appium/base-plugin": "^2.2.15", - "@appium/docutils": "^0.4.4", - "@appium/schema": "^0.3.1", - "@appium/support": "^4.1.2", - "@appium/types": "^0.13.2", - "@sidvind/better-ajv-errors": "2.1.0", - "@types/argparse": "2.0.10", - "@types/bluebird": "3.5.38", - "@types/fancy-log": "2.0.0", - "@types/semver": "7.5.0", - "@types/teen_process": "2.0.0", - "@types/wrap-ansi": "3.0.0", - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "argparse": "2.0.1", - "async-lock": "1.4.0", - "asyncbox": "2.9.4", - "axios": "1.4.0", - "bluebird": "3.7.2", - "cross-env": "7.0.3", - "find-up": "5.0.0", - "glob": "8.1.0", - "lilconfig": "2.1.0", - "lodash": "4.17.21", - "npmlog": "7.0.1", - "ora": "5.4.1", - "package-changed": "3.0.0", - "resolve-from": "5.0.0", - "semver": "7.5.3", - "source-map-support": "0.5.21", - "teen_process": "2.0.2", - "type-fest": "3.11.1", - "winston": "3.9.0", - "wrap-ansi": "7.0.0", - "yaml": "2.3.1" - }, - "dependencies": { - "@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, - "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "are-we-there-yet": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-4.0.2.tgz", - "integrity": "sha512-ncSWAawFhKMJDTdoAeOV+jyW1VCMj5QIAwULIBV0SSR7B/RLPPEQiknKcg/RIIZlUQrxELpsxMiTUoAQ4sIUyg==", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", - "dev": true, - "requires": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.1" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "gauge": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-5.0.2.tgz", - "integrity": "sha512-pMaFftXPtiGIHCJHdcUUx9Rby/rFT/Kkt3fIIGCs+9PMDIljSyRiqraTlxNtBReJRDfUefpa263RQ3vnp5G/LQ==", - "dev": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^4.0.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "npmlog": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-7.0.1.tgz", - "integrity": "sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg==", - "dev": true, - "requires": { - "are-we-there-yet": "^4.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^5.0.0", - "set-blocking": "^2.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "dependencies": { - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - } - } - }, - "semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "type-fest": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.11.1.tgz", - "integrity": "sha512-aCuRNRERRVh33lgQaJRlUxZqzfhzwTrsE98Mc3o3VXqmiaQdHacgUtJ0esp+7MvZ92qhtzKPeusaX6vIEcoreA==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", - "dev": true - } - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "archiver": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-6.0.1.tgz", - "integrity": "sha512-CXGy4poOLBKptiZH//VlWdFuUC1RESbdZjGjILwBuZ73P7WkAUN0htfSfBq/7k6FRFlpu7bg4JOkj1vU9G6jcQ==", - "dev": true, - "requires": { - "archiver-utils": "^4.0.1", - "async": "^3.2.4", - "buffer-crc32": "^0.2.1", - "readable-stream": "^3.6.0", - "readdir-glob": "^1.1.2", - "tar-stream": "^3.0.0", - "zip-stream": "^5.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, - "requires": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - } - } - }, - "archiver-utils": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-4.0.1.tgz", - "integrity": "sha512-Q4Q99idbvzmgCTEAAhi32BkOyq8iVI5EwdO0PmBDSGIzzjYNdcFn7Q7k3OzbLy4kLUPXfJtG6fO2RjftXbobBg==", - "dev": true, - "requires": { - "glob": "^8.0.0", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash": "^4.17.15", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "are-docs-informative": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", - "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", - "dev": true - }, - "are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" - }, - "dependencies": { - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - } - } - }, - "aria-hidden": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.3.tgz", - "integrity": "sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==", - "requires": { - "tslib": "^2.0.0" - } - }, - "aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", - "dev": true - }, - "array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - } - }, - "array-differ": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", - "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", - "dev": true - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", - "dev": true - }, - "array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" - } - }, - "array-iterate": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.2.tgz", - "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", - "dev": true - }, - "array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - } - }, - "arraybuffer.prototype.slice": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", - "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" - } - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, - "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - } - } - }, - "assert": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.1.tgz", - "integrity": "sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A==", - "dev": true, - "requires": { - "object.assign": "^4.1.4", - "util": "^0.10.4" - }, - "dependencies": { - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - } - } - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", - "dev": true - }, - "ast-types": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", - "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", - "dev": true, - "requires": { - "tslib": "^2.0.1" - } - }, - "ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", - "dev": true - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" - }, - "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, - "async-each": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.6.tgz", - "integrity": "sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==", - "dev": true, - "optional": true - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" - }, - "async-lock": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.0.tgz", - "integrity": "sha512-coglx5yIWuetakm3/1dsX9hxCNox22h7+V80RQOu2XUUMidtArxKoZoOtHUPuR84SycKTXzgGzAUR5hJxujyJQ==", - "dev": true - }, - "asyncbox": { - "version": "2.9.4", - "resolved": "https://registry.npmjs.org/asyncbox/-/asyncbox-2.9.4.tgz", - "integrity": "sha512-TCuA73K6Gvn+5tFGsWf4jc+PsR9RmYXw/AF0mv+CRB3VhHLjqHh/w9gPvYILnV0RcRFfjADHtzZexpxWlsP3Tg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.0.0", - "@types/bluebird": "^3.5.37", - "bluebird": "^3.5.1", - "lodash": "^4.17.4", - "source-map-support": "^0.5.5" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" - }, - "atob-lite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", - "integrity": "sha512-LEeSAWeh2Gfa2FtlQE1shxQ8zi5F9GHarrGKz08TMdODD5T4eH6BMsvtnhbWZ+XQn+Gb6om/917ucvRu7l7ukw==", - "dev": true - }, - "autoprefixer": { - "version": "10.4.14", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", - "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", - "dev": true, - "requires": { - "browserslist": "^4.21.5", - "caniuse-lite": "^1.0.30001464", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "autosize": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/autosize/-/autosize-4.0.2.tgz", - "integrity": "sha512-jnSyH2d+qdfPGpWlcuhGiHmqBJ6g3X+8T+iRwFrHPLVcdoGJE/x6Qicm6aDHfTsbgZKxyV8UU/YB2p4cjKDRRA==" - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true - }, - "axe-core": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", - "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==", - "dev": true - }, - "axios": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz", - "integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==", - "dev": true, - "requires": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "axobject-query": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", - "dev": true - }, - "b4a": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", - "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==", - "dev": true - }, - "babel-core": { - "version": "7.0.0-bridge.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", - "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==" - }, - "babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "requires": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - } - }, - "babel-loader": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", - "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", - "dev": true, - "requires": { - "find-cache-dir": "^4.0.0", - "schema-utils": "^4.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "find-cache-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", - "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", - "dev": true, - "requires": { - "common-path-prefix": "^3.0.0", - "pkg-dir": "^7.0.0" - } - }, - "find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "requires": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "requires": { - "p-locate": "^6.0.0" - } - }, - "p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "requires": { - "yocto-queue": "^1.0.0" - } - }, - "p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "requires": { - "p-limit": "^4.0.0" - } - }, - "path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true - }, - "pkg-dir": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", - "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", - "dev": true, - "requires": { - "find-up": "^6.3.0" - } - }, - "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - }, - "yocto-queue": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", - "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", - "dev": true - } - } - }, - "babel-plugin-add-react-displayname": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/babel-plugin-add-react-displayname/-/babel-plugin-add-react-displayname-0.0.5.tgz", - "integrity": "sha512-LY3+Y0XVDYcShHHorshrDbt4KFWL4bSeniCtl4SYZbask+Syngk1uMPCeN9+nSiZo6zX5s0RTq/J9Pnaaf/KHw==", - "dev": true - }, - "babel-plugin-inline-json-import": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/babel-plugin-inline-json-import/-/babel-plugin-inline-json-import-0.3.2.tgz", - "integrity": "sha512-QNNJx08KjmMT25Cw7rAPQ6dlREDPiZGDyApHL8KQ9vrQHbrr4PTi7W8g1tMMZPz0jEMd39nx/eH7xjnDNxq5sA==", - "dev": true, - "requires": { - "decache": "^4.5.1" - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "requires": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" - } - }, - "babel-plugin-polyfill-corejs2": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.3.tgz", - "integrity": "sha512-NDZ0auNRzmAfE1oDDPW2JhzIMXUk+FFe2ICejmt5T4ocKgiQx3e0VCRx9NCAidcMtL2RUZaWtXnmjTCkx0tcbA==", - "requires": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.2.4", - "semver": "^6.1.1" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "babel-plugin-polyfill-corejs3": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.3.0.tgz", - "integrity": "sha512-JLwi9vloVdXLjzACL80j24bG6/T1gYxwowG44dg6HN/7aTPdyPbJJidf6ajoA3RPHHtW0j9KMrSOLpIZpAnPpg==", - "requires": { - "@babel/helper-define-polyfill-provider": "^0.2.4", - "core-js-compat": "^3.18.0" - } - }, - "babel-plugin-polyfill-regenerator": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.3.tgz", - "integrity": "sha512-JVE78oRZPKFIeUqFGrSORNzQnrDwZR16oiWeGM8ZyjBn2XAT5OjP+wXx5ESuo33nUsFUEJYjtklnsKbxW5L+7g==", - "requires": { - "@babel/helper-define-polyfill-provider": "^0.2.4" - } - }, - "babel-plugin-react-native-classname-to-style": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/babel-plugin-react-native-classname-to-style/-/babel-plugin-react-native-classname-to-style-1.2.2.tgz", - "integrity": "sha512-kavZRZ56YoYmrwuCRMY0UuCYfMPszoN7v0DLST1D+rTqkl+cFWVW3W8l//AfWsyMNHkY+UTX+RrB5K7GY9mq3w==", - "dev": true - }, - "babel-plugin-react-native-platform-specific-extensions": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-react-native-platform-specific-extensions/-/babel-plugin-react-native-platform-specific-extensions-1.1.1.tgz", - "integrity": "sha512-ZNN2ImlUlcaPMfzaCw9fWmTc/Ht5ARI0n9RUqiyCdK7LalPJ7yKc+F60BcSHvMHcmA2BgVO8TpSot+dpeZPAMQ==", - "dev": true, - "requires": { - "@babel/template": "^7.0.0-beta.49" - } - }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "7.0.0-beta.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz", - "integrity": "sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ==", - "dev": true - }, - "babel-plugin-transform-flow-enums": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", - "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", - "requires": { - "@babel/plugin-syntax-flow": "^7.12.1" - } - }, - "babel-plugin-transform-remove-console": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz", - "integrity": "sha512-88blrUrMX3SPiGkT1GnvVY8E/7A+k6oj3MNvUtTIxJflFzXTw1bHkuJ/y039ouhFMp2prRn5cQGzokViYi1dsg==", - "dev": true - }, - "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - } - }, - "babel-preset-fbjs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz", - "integrity": "sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow==", - "dev": true, - "requires": { - "@babel/plugin-proposal-class-properties": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-syntax-class-properties": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-block-scoped-functions": "^7.0.0", - "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-classes": "^7.0.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-flow-strip-types": "^7.0.0", - "@babel/plugin-transform-for-of": "^7.0.0", - "@babel/plugin-transform-function-name": "^7.0.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-member-expression-literals": "^7.0.0", - "@babel/plugin-transform-modules-commonjs": "^7.0.0", - "@babel/plugin-transform-object-super": "^7.0.0", - "@babel/plugin-transform-parameters": "^7.0.0", - "@babel/plugin-transform-property-literals": "^7.0.0", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-template-literals": "^7.0.0", - "babel-plugin-syntax-trailing-function-commas": "^7.0.0-beta.0" - } - }, - "babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - } - }, - "babel-runtime": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz", - "integrity": "sha512-zeCYxDePWYAT/DfmQWIHsMSFW2vv45UIwIAMjGvQVsTd47RwsiRH0uK1yzyWZ7LDBKdhnGDPM6NYEO5CZyhPrg==", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.10.0" - }, - "dependencies": { - "core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "dev": true - }, - "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==", - "dev": true - } - } - }, - "bail": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", - "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "bare-events": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.2.1.tgz", - "integrity": "sha512-9GYPpsPFvrWBkelIhOhTWtkeZxVxZOdb3VnFTCzlOo3OjvmTvzLoZFUT8kNFACx0vJej6QPney1Cf9BvzCNE/A==", - "dev": true, - "optional": true - }, - "bare-fs": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.2.2.tgz", - "integrity": "sha512-X9IqgvyB0/VA5OZJyb5ZstoN62AzD7YxVGog13kkfYWYqJYcK0kcqLZ6TrmH5qr4/8//ejVcX4x/a0UvaogXmA==", - "dev": true, - "optional": true, - "requires": { - "bare-events": "^2.0.0", - "bare-os": "^2.0.0", - "bare-path": "^2.0.0", - "streamx": "^2.13.0" - } - }, - "bare-os": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.2.1.tgz", - "integrity": "sha512-OwPyHgBBMkhC29Hl3O4/YfxW9n7mdTr2+SsO29XBWKKJsbgj3mnorDB80r5TiCQgQstgE5ga1qNYrpes6NvX2w==", - "dev": true, - "optional": true - }, - "bare-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.0.tgz", - "integrity": "sha512-DIIg7ts8bdRKwJRJrUMy/PICEaQZaPGZ26lsSx9MJSwIhSrcdHn7/C8W+XmnG/rKi6BaRcz+JO00CjZteybDtw==", - "dev": true, - "optional": true, - "requires": { - "bare-os": "^2.1.0" - } - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-descriptor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", - "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - } - } - } - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "base64-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64-stream/-/base64-stream-1.0.0.tgz", - "integrity": "sha512-BQQZftaO48FcE1Kof9CmXMFaAdqkcNorgc8CxesZv9nMbbTF1EFyQe89UOuh//QMmdtfUDXyO8rgUalemL5ODA==", - "dev": true - }, - "basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "basic-ftp": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.3.tgz", - "integrity": "sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==", - "dev": true - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true - }, - "before-after-hook": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-1.4.0.tgz", - "integrity": "sha512-l5r9ir56nda3qu14nAXIlyq1MmUSs0meCIaFAh8HwkFwP1F8eToOuS3ah2VAHHcY04jaYD7FpJC5JTXHYRbkzg==", - "dev": true - }, - "benchmark": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", - "integrity": "sha512-l9MlfN4M1K/H2fbhfMy3B7vJd6AGKJVQn2h6Sg/Yx+KckoUA7ewS5Vv6TjSq18ooE1kS9hhAlQRH3AkXIh/aOQ==", - "dev": true, - "requires": { - "lodash": "^4.17.4", - "platform": "^1.3.3" - } - }, - "better-opn": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz", - "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==", - "dev": true, - "requires": { - "open": "^8.0.4" - }, - "dependencies": { - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - } - } - }, - "big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, - "binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true - }, - "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - } - } - }, - "bonjour-service": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", - "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", - "dev": true, - "requires": { - "array-flatten": "^2.1.2", - "dns-equal": "^1.0.0", - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - }, - "dependencies": { - "array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - } - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "bplist-creator": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.1.tgz", - "integrity": "sha512-Ese7052fdWrxp/vqSJkydgx/1MdBnNOCV2XVfbmdGWD2H6EYza+Q4pyYSuVSnCUD22hfI/BFI4jHaC3NLXLlJQ==", - "dev": true, - "requires": { - "stream-buffers": "2.2.x" - } - }, - "bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, - "requires": { - "big-integer": "^1.6.44" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "requires": { - "fill-range": "^7.1.1" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "dev": true - }, - "browser-assert": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", - "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", - "dev": true - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "dev": true, - "requires": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "browserify-sign": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz", - "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==", - "dev": true, - "requires": { - "bn.js": "^5.2.1", - "browserify-rsa": "^4.1.0", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.4", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.6", - "readable-stream": "^3.6.2", - "safe-buffer": "^5.2.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "~1.0.5" - } - }, - "browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", - "requires": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - } - }, - "bser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", - "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", - "requires": { - "node-int64": "^0.4.0" - } - }, - "btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==", - "dev": true - }, - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", - "dev": true - }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", - "dev": true - }, - "builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", - "dev": true - }, - "builtins": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", - "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==", - "dev": true - }, - "bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dev": true, - "requires": { - "run-applescript": "^5.0.0" - } - }, - "byte-size": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-8.1.1.tgz", - "integrity": "sha512-tUkzZWK0M/qdoLEqikxBWe4kumyuwjl3HO6zHTr4yEI23EojPtLYXdG1+AQY7MN0cGyNDvEaJ8wiYQm6P2bPxg==", - "dev": true - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" - }, - "cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - } - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true - }, - "cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dev": true, - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - } - }, - "call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - } - }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", - "requires": { - "callsites": "^2.0.0" - }, - "dependencies": { - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==" - } - } - }, - "caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", - "requires": { - "caller-callsite": "^2.0.0" - } - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ==", - "dev": true - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" - }, - "camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "requires": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - }, - "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "dependencies": { - "map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true - } - } - }, - "camelize": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", - "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" - }, - "caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "requires": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "caniuse-lite": { - "version": "1.0.30001636", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz", - "integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==" - }, - "capital-case": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", - "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, - "case-sensitive-paths-webpack-plugin": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", - "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", - "dev": true - }, - "ccount": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz", - "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", - "dev": true - }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", - "dev": true, - "requires": { - "traverse": ">=0.3.0 <0.4" - }, - "dependencies": { - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", - "dev": true - } - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "change-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", - "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", - "requires": { - "camel-case": "^4.1.2", - "capital-case": "^1.0.4", - "constant-case": "^3.0.4", - "dot-case": "^3.0.4", - "header-case": "^2.0.4", - "no-case": "^3.0.4", - "param-case": "^3.0.4", - "pascal-case": "^3.1.2", - "path-case": "^3.0.4", - "sentence-case": "^3.0.4", - "snake-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, - "character-entities": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", - "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==", - "dev": true - }, - "character-entities-html4": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz", - "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==", - "dev": true - }, - "character-entities-legacy": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", - "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==", - "dev": true - }, - "character-reference-invalid": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", - "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", - "dev": true - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "check-node-version": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/check-node-version/-/check-node-version-4.1.0.tgz", - "integrity": "sha512-TSXGsyfW5/xY2QseuJn8/hleO2AU7HxVCdkc900jp1vcfzF840GkjvRT7CHl8sRtWn23n3X3k0cwH9RXeRwhfw==", - "dev": true, - "requires": { - "chalk": "^3.0.0", - "map-values": "^1.0.1", - "minimist": "^1.2.0", - "object-filter": "^1.0.2", - "run-parallel": "^1.1.4", - "semver": "^6.3.0" - }, - "dependencies": { - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "chrome-launcher": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", - "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", - "requires": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "requires": { - "is-docker": "^2.0.0" - } - } - } - }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true - }, - "chromium-bidi": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.16.tgz", - "integrity": "sha512-7ZbXdWERxRxSwo3txsBjjmc/NLxqb1Bk30mRb0BMS4YIaiV6zvKZqL/UAH+DdqcDYayDWk2n/y8klkBDODrPvA==", - "dev": true, - "requires": { - "mitt": "3.0.0" - } - }, - "chromium-edge-launcher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz", - "integrity": "sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA==", - "requires": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0", - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "dependencies": { - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "requires": { - "is-docker": "^2.0.0" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - } - } - }, - "ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==" - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "citty": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", - "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", - "dev": true, - "requires": { - "consola": "^3.2.3" - }, - "dependencies": { - "consola": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", - "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", - "dev": true - } - } - }, - "cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "clean-css": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", - "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", - "dev": true, - "requires": { - "source-map": "~0.6.0" - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "clean-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", - "dev": true, - "requires": { - "@types/webpack": "^4.4.31", - "del": "^4.1.1" - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==" - }, - "cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", - "dev": true, - "requires": { - "@colors/colors": "1.5.0", - "string-width": "^4.2.0" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "cli-truncate": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", - "integrity": "sha512-f4r4yJnbT++qUPI9NR4XLDLq41gQ+uqnPItWG0F5ZkehuNiTTa3EY0S4AqTSUOeJ7/zU41oWPQSNkW5BqPL9bg==", - "dev": true, - "requires": { - "slice-ansi": "0.0.4", - "string-width": "^1.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "cli-width": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", - "dev": true - }, - "client-zip": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/client-zip/-/client-zip-2.4.5.tgz", - "integrity": "sha512-4y4d5ZeTH/szIAMQeC8ju67pxtvj+3u20wMGwOFrZk+pegy3aSEA2JkwgC8XVDTXP/Iqn1gyqNQXmkyBp4KLEQ==" - }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, - "clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" - }, - "cmd-shim": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-6.0.1.tgz", - "integrity": "sha512-S9iI9y0nKR4hwEQsVWpyxld/6kRfGepGfzff83FcaiEBpmvlbA2nnGe7Cylgrx2f/p1P5S5wpRm9oL8z1PbS3Q==", - "dev": true - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", - "dev": true - }, - "collapse-white-space": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz", - "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", - "dev": true - }, - "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "requires": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "dependencies": { - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - } - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" - }, - "colorette": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", - "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" - }, - "colorspace": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", - "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", - "dev": true, - "requires": { - "color": "^3.1.3", - "text-hex": "1.0.x" - }, - "dependencies": { - "color": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", - "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", - "dev": true, - "requires": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" - } - } - } - }, - "columnify": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", - "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", - "dev": true, - "requires": { - "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.0" - } - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" - }, - "commander": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz", - "integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==", - "dev": true - }, - "comment-parser": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.0.tgz", - "integrity": "sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==", - "dev": true - }, - "common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" - }, - "compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "requires": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "complex.js": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz", - "integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "compress-commons": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-5.0.1.tgz", - "integrity": "sha512-MPh//1cERdLtqwO3pOFLeXtpuai0Y2WCd5AhtKxznqM7WtaMYaOEMSgn45d9D10sIHSfIKE603HlOp8OPGrvag==", - "dev": true, - "requires": { - "crc-32": "^1.2.0", - "crc32-stream": "^5.0.0", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "computed-style": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/computed-style/-/computed-style-0.1.4.tgz", - "integrity": "sha512-WpAmaKbMNmS3OProfHIdJiNleNJdgUrJfbKArXua28QF7+0CoZjlLn0lp6vlc+dl5r2/X9GQiQRQQU4BzSa69w==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "concurrently": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-3.5.0.tgz", - "integrity": "sha512-Z2iVM5+c0VxKmENTXrG/kp+MUhWEEH+wI5wV/L8CTFJDb/uae1zSVIkNM7o3W4Tdt42pv7RGsOICaskWy9bqSA==", - "dev": true, - "requires": { - "chalk": "0.5.1", - "commander": "2.6.0", - "date-fns": "^1.23.0", - "lodash": "^4.5.1", - "rx": "2.3.24", - "spawn-command": "^0.0.2-1", - "supports-color": "^3.2.3", - "tree-kill": "^1.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "integrity": "sha512-sGwIGMjhYdW26/IhwK2gkWWI8DRCVO6uj3hYgHT+zD+QL1pa37tM3ujhyfcJIYSbsxp7Gxhy7zrRW/1AHm4BmA==", - "dev": true - }, - "ansi-styles": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "integrity": "sha512-f2PKUkN5QngiSemowa6Mrk9MPCdtFiOSmibjZ+j1qhLGHHYsqZwmBMRF3IRMVXo8sybDqx2fJl2d/8OphBoWkA==", - "dev": true - }, - "chalk": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "integrity": "sha512-bIKA54hP8iZhyDT81TOsJiQvR1gW+ZYSXFaZUAvoD4wCHdbHY2actmpTE4x344ZlFqHbvoxKOaESULTZN2gstg==", - "dev": true, - "requires": { - "ansi-styles": "^1.1.0", - "escape-string-regexp": "^1.0.0", - "has-ansi": "^0.1.0", - "strip-ansi": "^0.3.0", - "supports-color": "^0.2.0" - }, - "dependencies": { - "supports-color": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "integrity": "sha512-tdCZ28MnM7k7cJDJc7Eq80A9CsRFAAOZUy41npOZCs++qSjfIy7o5Rh46CBk+Dk5FbKJ33X3Tqg4YrV07N5RaA==", - "dev": true - } - } - }, - "commander": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz", - "integrity": "sha512-PhbTMT+ilDXZKqH8xbvuUY2ZEQNef0Q7DKxgoEKb4ccytsdvVVJmYqR0sGbi96nxU6oGrwEIQnclpK2NBZuQlg==", - "dev": true - }, - "date-fns": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", - "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", - "dev": true - }, - "has-ansi": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "integrity": "sha512-1YsTg1fk2/6JToQhtZkArMkurq8UoWU1Qe0aR3VUHjgij4nOylSWLWAtBXoZ4/dXOmugfLGm1c+QhuD0JyedFA==", - "dev": true, - "requires": { - "ansi-regex": "^0.2.0" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", - "dev": true - }, - "strip-ansi": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "integrity": "sha512-DerhZL7j6i6/nEnVG0qViKXI0OKouvvpsAiaj7c+LfqZZZxdwZtv8+UiA/w4VUJpT8UzX0pR1dcHOii1GbmruQ==", - "dev": true, - "requires": { - "ansi-regex": "^0.2.1" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - }, - "dependencies": { - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - } - } - }, - "connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true - }, - "consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", - "dev": true - }, - "console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true - }, - "constant-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", - "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case": "^2.0.2" - } - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", - "dev": true - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "requires": { - "safe-buffer": "5.2.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true - }, - "conventional-changelog-angular": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz", - "integrity": "sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==", - "dev": true, - "requires": { - "compare-func": "^2.0.0" - } - }, - "conventional-changelog-core": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-5.0.1.tgz", - "integrity": "sha512-Rvi5pH+LvgsqGwZPZ3Cq/tz4ty7mjijhr3qR4m9IBXNbxGGYgTVVO+duXzz9aArmHxFtwZ+LRkrNIMDQzgoY4A==", - "dev": true, - "requires": { - "add-stream": "^1.0.0", - "conventional-changelog-writer": "^6.0.0", - "conventional-commits-parser": "^4.0.0", - "dateformat": "^3.0.3", - "get-pkg-repo": "^4.2.1", - "git-raw-commits": "^3.0.0", - "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^5.0.0", - "normalize-package-data": "^3.0.3", - "read-pkg": "^3.0.0", - "read-pkg-up": "^3.0.0" - }, - "dependencies": { - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "dependencies": { - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - } - } - }, - "conventional-changelog-preset-loader": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-3.0.0.tgz", - "integrity": "sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==", - "dev": true - }, - "conventional-changelog-writer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-6.0.1.tgz", - "integrity": "sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ==", - "dev": true, - "requires": { - "conventional-commits-filter": "^3.0.0", - "dateformat": "^3.0.3", - "handlebars": "^4.7.7", - "json-stringify-safe": "^5.0.1", - "meow": "^8.1.2", - "semver": "^7.0.0", - "split": "^1.0.1" - } - }, - "conventional-commits-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-3.0.0.tgz", - "integrity": "sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==", - "dev": true, - "requires": { - "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.1" - } - }, - "conventional-commits-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz", - "integrity": "sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==", - "dev": true, - "requires": { - "is-text-path": "^1.0.1", - "JSONStream": "^1.3.5", - "meow": "^8.1.2", - "split2": "^3.2.2" - } - }, - "conventional-recommended-bump": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-7.0.1.tgz", - "integrity": "sha512-Ft79FF4SlOFvX4PkwFDRnaNiIVX7YbmqGU0RwccUaiGvgp3S0a8ipR2/Qxk31vclDNM+GSdJOVs2KrsUCjblVA==", - "dev": true, - "requires": { - "concat-stream": "^2.0.0", - "conventional-changelog-preset-loader": "^3.0.0", - "conventional-commits-filter": "^3.0.0", - "conventional-commits-parser": "^4.0.0", - "git-raw-commits": "^3.0.0", - "git-semver-tags": "^5.0.0", - "meow": "^8.1.2" - }, - "dependencies": { - "concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" - }, - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", - "dev": true - }, - "copy-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/copy-dir/-/copy-dir-1.3.0.tgz", - "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==", - "dev": true - }, - "copy-webpack-plugin": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.0.tgz", - "integrity": "sha512-my6iXII95c78w14HzYCNya5TlJYa44lOppAge5GSTMM1SyDxNsVGCJvhP4/ld6snm8lzjn3XOonMZD6s1L86Og==", - "dev": true, - "requires": { - "fast-glob": "^3.2.7", - "glob-parent": "^6.0.1", - "globby": "^12.0.2", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "array-union": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", - "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", - "dev": true - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globby": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", - "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", - "dev": true, - "requires": { - "array-union": "^3.0.1", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.7", - "ignore": "^5.1.9", - "merge2": "^1.4.1", - "slash": "^4.0.0" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - }, - "serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true - } - } - }, - "core-js": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.35.1.tgz", - "integrity": "sha512-IgdsbxNyMskrTFxa9lWHyMwAJU5gXOPP+1yO+K59d50VLVAIDAbs7gIv705KzALModfK3ZrSZTPNpC0PQgIZuw==" - }, - "core-js-builder": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/core-js-builder/-/core-js-builder-3.35.1.tgz", - "integrity": "sha512-CfIvg+khWyS7ElbRXhuQH9QVUQxRDFl8AUwP08BxubJmYtRZuqwjwvc/DVnwRXQ6sqg8ghfNRgnUDWzwNhU/Rw==", - "dev": true, - "requires": { - "core-js": "3.35.1", - "core-js-compat": "3.35.1", - "mkdirp": ">=0.5.5 <1", - "webpack": ">=4.47.0 <5" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "terser": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", - "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", - "dev": true, - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - } - }, - "terser-webpack-plugin": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.6.tgz", - "integrity": "sha512-2lBVf/VMVIddjSn3GqbT90GvIJ/eYXJkt8cTzU7NbjKqK8fwv18Ftr4PlbF46b/e88743iZFL5Dtr/rC4hjIeA==", - "dev": true, - "requires": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^4.0.0", - "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" - } - }, - "webpack": { - "version": "4.47.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.47.0.tgz", - "integrity": "sha512-td7fYwgLSrky3fI1EuU5cneU4+pbH6GgOfuKNS1tNPcfdGinGELAqsb/BP4nnvZyKSG2i/xFGU7+n2PvZA8HJQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/wasm-edit": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "acorn": "^6.4.1", - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^4.5.0", - "eslint-scope": "^4.0.3", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.4.0", - "loader-utils": "^1.2.3", - "memory-fs": "^0.4.1", - "micromatch": "^3.1.10", - "mkdirp": "^0.5.3", - "neo-async": "^2.6.1", - "node-libs-browser": "^2.2.1", - "schema-utils": "^1.0.0", - "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.3", - "watchpack": "^1.7.4", - "webpack-sources": "^1.4.1" - } - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - } - } - }, - "core-js-compat": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.1.tgz", - "integrity": "sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw==", - "requires": { - "browserslist": "^4.22.2" - } - }, - "core-js-pure": { - "version": "3.31.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.31.0.tgz", - "integrity": "sha512-/AnE9Y4OsJZicCzIe97JP5XoPKQJfTuEG43aEVLFJGOJpyqELod+pE6LEl63DfG1Mp8wX97LDaDpy1GmLEUxlg==", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" - }, - "cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "dependencies": { - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" - } - } - }, - "crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "dev": true - }, - "crc32-stream": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-5.0.0.tgz", - "integrity": "sha512-B0EPa1UK+qnpBZpG+7FgPCu0J2ETLpXq09o9BkLkEAhdB6Z61Qo4pJ3JYu0c+Qi+/SAL7QThqnzS06pmSSyZaw==", - "dev": true, - "requires": { - "crc-32": "^1.2.0", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - } - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "cross-env": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-3.2.4.tgz", - "integrity": "sha512-T8AFEAiuJ0w53ou6rnu3Fipaiu1W6ZO9GYfd33uxe1kAIiXM0fD8QnIm7orcJBOt7WQC5Ply63E7WZW/jSM+FA==", - "dev": true, - "requires": { - "cross-spawn": "^5.1.0", - "is-windows": "^1.0.0" - } - }, - "cross-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", - "dev": true, - "requires": { - "node-fetch": "^2.6.12" - }, - "dependencies": { - "node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - } - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true - }, - "csp_evaluator": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/csp_evaluator/-/csp_evaluator-1.1.1.tgz", - "integrity": "sha512-N3ASg0C4kNPUaNxt1XAvzHIVuzdtr8KLgfk1O8WDyimp1GisPAHESupArO2ieHk9QWbrJ/WkQODyh21Ps/xhxw==", - "dev": true - }, - "css": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", - "requires": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - } - }, - "css-color-keywords": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", - "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==" - }, - "css-declaration-sorter": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", - "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", - "dev": true - }, - "css-functions-list": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.2.tgz", - "integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==", - "dev": true - }, - "css-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.2.0.tgz", - "integrity": "sha512-/rvHfYRjIpymZblf49w8jYcRo2y9gj6rV8UroHGmBxKrIyGLokpycyKzp9OkitvqT29ZSpzJ0Ic7SpnJX3sC8g==", - "dev": true, - "requires": { - "icss-utils": "^5.1.0", - "postcss": "^8.2.15", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.1.0", - "semver": "^7.3.5" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "css-mediaquery": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz", - "integrity": "sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q==" - }, - "css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "dependencies": { - "dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" - }, - "domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "requires": { - "domelementtype": "^2.3.0" - } - }, - "domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "requires": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - } - }, - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" - } - } - }, - "css-shorthand-properties": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/css-shorthand-properties/-/css-shorthand-properties-1.1.1.tgz", - "integrity": "sha512-Md+Juc7M3uOdbAFwOYlTrccIZ7oCFuzrhKYQjdeUEW/sE1hv17Jp/Bws+ReOPpGVBTYCBoYo+G17V5Qo8QQ75A==", - "dev": true - }, - "css-to-react-native": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-2.3.2.tgz", - "integrity": "sha512-VOFaeZA053BqvvvqIA8c9n0+9vFppVBAHCp6JgFTtTMU3Mzi+XnelJ9XC9ul3BqFzZyQ5N+H0SnwsWT2Ebchxw==", - "requires": { - "camelize": "^1.0.0", - "css-color-keywords": "^1.0.0", - "postcss-value-parser": "^3.3.0" - } - }, - "css-to-react-native-transform": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/css-to-react-native-transform/-/css-to-react-native-transform-1.9.0.tgz", - "integrity": "sha512-darzotx5xx+Q0bzASkvNBasztLCssNerzf9jpMZx0H4CTY6J/y2Wh50ZtYAJ3FmESEux1bJcGa6T0zfISTuFqw==", - "requires": { - "css": "^2.2.4", - "css-mediaquery": "^0.1.2", - "css-to-react-native": "^2.3.0" - } - }, - "css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "requires": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - } - }, - "css-value": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", - "integrity": "sha512-FUV3xaJ63buRLgHrLQVlVgQnQdR4yqdLGaDu7g8CQcWjInDfM9plBTPI9FRfpahju1UBSaMckeb2/46ApS/V1Q==", - "dev": true - }, - "css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" - }, - "css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", - "dev": true - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "cssnano": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.0.1.tgz", - "integrity": "sha512-fVO1JdJ0LSdIGJq68eIxOqFpIJrZqXUsBt8fkrBcztCQqAjQD51OhZp7tc0ImcbwXD4k7ny84QTV90nZhmqbkg==", - "dev": true, - "requires": { - "cssnano-preset-default": "^6.0.1", - "lilconfig": "^2.1.0" - } - }, - "cssnano-preset-default": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.0.1.tgz", - "integrity": "sha512-7VzyFZ5zEB1+l1nToKyrRkuaJIx0zi/1npjvZfbBwbtNTzhLtlvYraK/7/uqmX2Wb2aQtd983uuGw79jAjLSuQ==", - "dev": true, - "requires": { - "css-declaration-sorter": "^6.3.1", - "cssnano-utils": "^4.0.0", - "postcss-calc": "^9.0.0", - "postcss-colormin": "^6.0.0", - "postcss-convert-values": "^6.0.0", - "postcss-discard-comments": "^6.0.0", - "postcss-discard-duplicates": "^6.0.0", - "postcss-discard-empty": "^6.0.0", - "postcss-discard-overridden": "^6.0.0", - "postcss-merge-longhand": "^6.0.0", - "postcss-merge-rules": "^6.0.1", - "postcss-minify-font-values": "^6.0.0", - "postcss-minify-gradients": "^6.0.0", - "postcss-minify-params": "^6.0.0", - "postcss-minify-selectors": "^6.0.0", - "postcss-normalize-charset": "^6.0.0", - "postcss-normalize-display-values": "^6.0.0", - "postcss-normalize-positions": "^6.0.0", - "postcss-normalize-repeat-style": "^6.0.0", - "postcss-normalize-string": "^6.0.0", - "postcss-normalize-timing-functions": "^6.0.0", - "postcss-normalize-unicode": "^6.0.0", - "postcss-normalize-url": "^6.0.0", - "postcss-normalize-whitespace": "^6.0.0", - "postcss-ordered-values": "^6.0.0", - "postcss-reduce-initial": "^6.0.0", - "postcss-reduce-transforms": "^6.0.0", - "postcss-svgo": "^6.0.0", - "postcss-unique-selectors": "^6.0.0" - } - }, - "cssnano-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.0.tgz", - "integrity": "sha512-Z39TLP+1E0KUcd7LGyF4qMfu8ZufI0rDzhdyAMsa/8UyNUU8wpS0fhdBxbQbv32r64ea00h4878gommRVg2BHw==", - "dev": true - }, - "csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dev": true, - "requires": { - "css-tree": "~2.2.0" - }, - "dependencies": { - "css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dev": true, - "requires": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" - } - }, - "mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "dev": true - }, - "source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true - } - } - }, - "cssstyle": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", - "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", - "dev": true, - "requires": { - "rrweb-cssom": "^0.7.1" - } - }, - "csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" - }, - "cwd": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.10.0.tgz", - "integrity": "sha512-YGZxdTTL9lmLkCUTpg4j0zQ7IhRB5ZmqNBbGCl3Tg6MP/d5/6sY7L5mmTjzbc6JKgVZYiqTQTNhPFsbXNGlRaA==", - "dev": true, - "requires": { - "find-pkg": "^0.1.2", - "fs-exists-sync": "^0.1.0" - } - }, - "cyclist": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.2.tgz", - "integrity": "sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==", - "dev": true - }, - "damerau-levenshtein": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz", - "integrity": "sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==", - "dev": true - }, - "dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", - "dev": true - }, - "data-uri-to-buffer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-5.0.1.tgz", - "integrity": "sha512-a9l6T1qqDogvvnw0nKlfZzqsyikEBZBClF39V3TFoKhDtGBqHu2HkuomJc02j5zft8zrUaXEuoicLeW54RkzPg==", - "dev": true - }, - "data-urls": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", - "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", - "dev": true, - "requires": { - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" - }, - "dependencies": { - "tr46": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", - "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", - "dev": true, - "requires": { - "punycode": "^2.3.1" - } - }, - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true - }, - "whatwg-url": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", - "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", - "dev": true, - "requires": { - "tr46": "^5.0.0", - "webidl-conversions": "^7.0.0" - } - } - } - }, - "date-fns": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", - "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==" - }, - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true - }, - "dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "decache": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/decache/-/decache-4.5.1.tgz", - "integrity": "sha512-5J37nATc6FmOTLbcsr9qx7Nm28qQyg1SK4xyEHqM0IBkNhWFp0Sm+vKoWYHD8wq+OUEb9jLyaKFfzzd1A9hcoA==", - "dev": true, - "requires": { - "callsite": "^1.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" - }, - "decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", - "dev": true, - "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - } - }, - "decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==" - }, - "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "requires": { - "mimic-response": "^3.1.0" - }, - "dependencies": { - "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true - } - } - }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "deep-freeze": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz", - "integrity": "sha512-Z+z8HiAvsGwmjqlphnHW5oz6yWlOwu6EQfFTjmeTWlDeda3FS2yv3jhq35TX/ewmsnqB+RX2IdsIOyjJCQN5tg==", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" - }, - "deepmerge-ts": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-5.1.0.tgz", - "integrity": "sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw==", - "dev": true - }, - "default-browser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", - "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", - "dev": true, - "requires": { - "bundle-name": "^3.0.0", - "default-browser-id": "^3.0.0", - "execa": "^7.1.1", - "titleize": "^3.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true - }, - "is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true - }, - "mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true - }, - "npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "requires": { - "path-key": "^4.0.0" - }, - "dependencies": { - "path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true - } - } - }, - "onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "requires": { - "mimic-fn": "^4.0.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "default-browser-id": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", - "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dev": true, - "requires": { - "bplist-parser": "^0.2.0", - "untildify": "^4.0.0" - } - }, - "default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "requires": { - "execa": "^5.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "requires": { - "clone": "^1.0.2" - } - }, - "defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true - }, - "define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - } - }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true - }, - "define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dev": true, - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-descriptor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", - "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - } - } - } - }, - "defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "dev": true - }, - "degenerator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", - "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, - "requires": { - "ast-types": "^0.13.4", - "escodegen": "^2.1.0", - "esprima": "^4.0.1" - }, - "dependencies": { - "ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, - "requires": { - "tslib": "^2.0.1" - } - } - } - }, - "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true - } - } - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true - }, - "delegate": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true - }, - "denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true - }, - "deprecated-react-native-prop-types": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-2.3.0.tgz", - "integrity": "sha512-pWD0voFtNYxrVqvBMYf5gq3NA2GCpfodS1yNynTPc93AYA/KEMGeWDqqeUB6R2Z9ZofVhks2aeJXiuQqKNpesA==", - "requires": { - "@react-native/normalize-color": "*", - "invariant": "*", - "prop-types": "*" - } - }, - "deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true - }, - "dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true - }, - "des.js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", - "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - }, - "detect-indent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", - "integrity": "sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==", - "dev": true - }, - "detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", - "dev": true, - "optional": true - }, - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true - }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "detect-node-es": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", - "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" - }, - "detect-package-manager": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-package-manager/-/detect-package-manager-2.0.1.tgz", - "integrity": "sha512-j/lJHyoLlWi6G1LDdLgvUtz60Zo5GEj+sVYtTVXnYLDPuzgC3llMxonXym9zIwhhUII8vjdw0LXxavpLqTbl1A==", - "dev": true, - "requires": { - "execa": "^5.1.1" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "detect-port": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", - "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", - "dev": true, - "requires": { - "address": "^1.0.1", - "debug": "4" - } - }, - "devtools-protocol": { - "version": "0.0.1312386", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz", - "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==", - "dev": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" - }, - "diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - } - } - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - }, - "dependencies": { - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - } - } - }, - "dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", - "dev": true - }, - "dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dev": true, - "requires": { - "@leichtgewicht/ip-codec": "^2.0.1" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-accessibility-api": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.14.tgz", - "integrity": "sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==", - "dev": true - }, - "dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "requires": { - "utila": "~0.4" - } - }, - "dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "requires": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - }, - "dependencies": { - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - } - } - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true - }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - }, - "dependencies": { - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - } - } - }, - "dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "dev": true - }, - "dotenv-expand": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", - "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", - "dev": true - }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "duplexify": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", - "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "edge-paths": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/edge-paths/-/edge-paths-3.0.5.tgz", - "integrity": "sha512-sB7vSrDnFa4ezWQk9nZ/n0FdpdUuC6R1EOrlU3DL+bovcNFK28rqu2emmAUjujYEJTWIgQGqgVVWUZXMnc8iWg==", - "dev": true, - "requires": { - "@types/which": "^2.0.1", - "which": "^2.0.2" - }, - "dependencies": { - "@types/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/which/-/which-2.0.2.tgz", - "integrity": "sha512-113D3mDkZDjo+EeUEHCFy0qniNc1ZpecGiAU7WSo7YDoSzolZIQKpYFHrPpjkB2nuyahcKfrmLXeQlh7gqJYdw==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "edgedriver": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/edgedriver/-/edgedriver-5.3.7.tgz", - "integrity": "sha512-E1qNFEA9NbaCPSvGaeZhyd7mEZLar+oFS0NRAe5TehJcQ3cayoUdJE5uOFrbxdv/rM4NEPH7aK9a9kgG09rszA==", - "dev": true, - "requires": { - "@wdio/logger": "^8.11.0", - "decamelize": "^6.0.0", - "edge-paths": "^3.0.5", - "node-fetch": "^3.3.2", - "unzipper": "^0.10.14", - "which": "^4.0.0" - }, - "dependencies": { - "data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "dev": true - }, - "decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", - "dev": true - }, - "isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true - }, - "node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "dev": true, - "requires": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - } - }, - "which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", - "dev": true, - "requires": { - "isexe": "^3.1.1" - } - } - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", - "dev": true, - "requires": { - "jake": "^10.8.5" - } - }, - "electron-to-chromium": { - "version": "1.4.643", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.643.tgz", - "integrity": "sha512-QHscvvS7gt155PtoRC0dR2ilhL8E9LHhfTQEq1uD5AL0524rBLAwpAREFH06f87/e45B9XkR6Ki5dbhbCsVEIg==" - }, - "elegant-spinner": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", - "integrity": "sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==", - "dev": true - }, - "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, - "requires": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - } - } - }, - "emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "enabled": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" - }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "requires": { - "iconv-lite": "^0.6.2" - } - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "endent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", - "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", - "dev": true, - "requires": { - "dedent": "^0.7.0", - "fast-json-parse": "^1.0.3", - "objectorarray": "^1.0.5" - } - }, - "enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - }, - "dependencies": { - "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - } - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true - }, - "envinfo": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", - "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==" - }, - "equivalent-key-map": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/equivalent-key-map/-/equivalent-key-map-0.2.2.tgz", - "integrity": "sha512-xvHeyCDbZzkpN4VHQj/n+j2lOwL0VWszG30X4cOrc9Y7Tuo2qCdZK/0AMod23Z5dCtNUbaju6p0rwOhHUk05ew==" - }, - "err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "error-stack-parser": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz", - "integrity": "sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==", - "requires": { - "stackframe": "^1.1.1" - } - }, - "errorhandler": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", - "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==", - "requires": { - "accepts": "~1.3.7", - "escape-html": "~1.0.3" - } - }, - "es-abstract": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", - "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.1", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.1", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "safe-array-concat": "^1.0.0", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.10" - } - }, - "es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.4" - } - }, - "es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true - }, - "es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - } - } - }, - "es-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", - "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", - "dev": true - }, - "es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - } - }, - "es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true - }, - "esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "requires": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "esbuild-plugin-alias": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/esbuild-plugin-alias/-/esbuild-plugin-alias-0.2.1.tgz", - "integrity": "sha512-jyfL/pwPqaFXyKnj8lP8iLk6Z0m099uXR45aSN8Av1XD4vhvQutxxPzgA2bTcAwQpa1zCXDcWOlhFgyP3GKqhQ==", - "dev": true - }, - "esbuild-register": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.5.0.tgz", - "integrity": "sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "escape-latex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz", - "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - }, - "escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "source-map": "~0.6.1" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "eslint": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz", - "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.0.4", - "@humanwhocodes/config-array": "^0.6.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.1.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.2.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "eslint-config-prettier": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", - "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", - "dev": true - }, - "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "eslint-module-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz", - "integrity": "sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ==", - "dev": true, - "requires": { - "debug": "^3.2.7", - "find-up": "^2.1.0", - "pkg-dir": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, - "eslint-plugin-eslint-comments": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.1.2.tgz", - "integrity": "sha512-QexaqrNeteFfRTad96W+Vi4Zj1KFbkHHNMMaHZEYcovKav6gdomyGzaxSDSL3GoIyUOo078wRAdYlu1caiauIQ==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "ignore": "^5.0.5" - } - }, - "eslint-plugin-import": { - "version": "2.25.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.2.tgz", - "integrity": "sha512-qCwQr9TYfoBHOFcVGKY9C9unq05uOxxdklmBXLVvcwo68y5Hta6/GzCZEMx2zQiu0woKNEER0LE7ZgaOfBU14g==", - "dev": true, - "requires": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.0", - "has": "^1.0.3", - "is-core-module": "^2.7.0", - "is-glob": "^4.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.5", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.11.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "requires": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - } - } - }, - "eslint-plugin-jest": { - "version": "27.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz", - "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==", - "dev": true, - "requires": { - "@typescript-eslint/utils": "^5.10.0" - } - }, - "eslint-plugin-jest-dom": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest-dom/-/eslint-plugin-jest-dom-5.0.2.tgz", - "integrity": "sha512-zfNOwQOrOOGcxb3tcOgB2fEiqmgEbXKcPrNC+NlNSWCi3wg/m+DWVqrrshp4gOjhpP1R/1X7kkHumnf8PLUFhw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.16.3", - "requireindex": "^1.2.0" - } - }, - "eslint-plugin-jsdoc": { - "version": "46.4.6", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.6.tgz", - "integrity": "sha512-z4SWYnJfOqftZI+b3RM9AtWL1vF/sLWE/LlO9yOKDof9yN2+n3zOdOJTGX/pRE/xnPsooOLG2Rq6e4d+XW3lNw==", - "dev": true, - "requires": { - "@es-joy/jsdoccomment": "~0.40.1", - "are-docs-informative": "^0.0.2", - "comment-parser": "1.4.0", - "debug": "^4.3.4", - "escape-string-regexp": "^4.0.0", - "esquery": "^1.5.0", - "is-builtin-module": "^3.2.1", - "semver": "^7.5.4", - "spdx-expression-parse": "^3.0.1" - }, - "dependencies": { - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - } - } - }, - "eslint-plugin-jsx-a11y": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz", - "integrity": "sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==", - "dev": true, - "requires": { - "@babel/runtime": "^7.16.3", - "aria-query": "^4.2.2", - "array-includes": "^3.1.4", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.3.5", - "axobject-query": "^2.2.0", - "damerau-levenshtein": "^1.0.7", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.2.1", - "language-tags": "^1.0.5", - "minimatch": "^3.0.4" - }, - "dependencies": { - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - } - } - }, - "eslint-plugin-playwright": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-0.15.3.tgz", - "integrity": "sha512-LQMW5y0DLK5Fnpya7JR1oAYL2/7Y9wDiYw6VZqlKqcRGSgjbVKNqxraphk7ra1U3Bb5EK444xMgUlQPbMg2M1g==", - "dev": true - }, - "eslint-plugin-prettier": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz", - "integrity": "sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.5" - } - }, - "eslint-plugin-react": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.27.0.tgz", - "integrity": "sha512-0Ut+CkzpppgFtoIhdzi2LpdpxxBvgFf99eFqWxJnUrO7mMe0eOiNpou6rvNYeVVV6lWZvTah0BFne7k5xHjARg==", - "dev": true, - "requires": { - "array-includes": "^3.1.4", - "array.prototype.flatmap": "^1.2.5", - "doctrine": "^2.1.0", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.0.4", - "object.entries": "^1.1.5", - "object.fromentries": "^2.0.5", - "object.hasown": "^1.1.0", - "object.values": "^1.1.5", - "prop-types": "^15.7.2", - "resolve": "^2.0.0-next.3", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.6" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "requires": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "eslint-plugin-react-hooks": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz", - "integrity": "sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==", - "dev": true - }, - "eslint-plugin-ssr-friendly": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/eslint-plugin-ssr-friendly/-/eslint-plugin-ssr-friendly-1.0.6.tgz", - "integrity": "sha512-O1S/0Q8FYTl1c4vwIr0cg59u37mL5qe7sxpMzjdIo2v8l0LjCugU699trmkgOheQINTq7R9yhfCo6YaAb4tYUQ==", - "dev": true, - "requires": { - "globals": "^13.8.0" - } - }, - "eslint-plugin-storybook": { - "version": "0.6.13", - "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.6.13.tgz", - "integrity": "sha512-smd+CS0WH1jBqUEJ3znGS7DU4ayBE9z6lkQAK2yrSUv1+rq8BT/tiI5C/rKE7rmiqiAfojtNYZRhzo5HrulccQ==", - "dev": true, - "requires": { - "@storybook/csf": "^0.0.1", - "@typescript-eslint/utils": "^5.45.0", - "requireindex": "^1.1.0", - "ts-dedent": "^2.2.0" - }, - "dependencies": { - "@storybook/csf": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.1.tgz", - "integrity": "sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw==", - "dev": true, - "requires": { - "lodash": "^4.17.15" - } - } - } - }, - "eslint-plugin-testing-library": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.0.2.tgz", - "integrity": "sha512-3BV6FWtLbpKFb4Y1obSdt8PC9xSqz6T+7EHB/6pSCXqVjKPoS67ck903feKMKQphd5VhrX+N51yHuVaPa7elsw==", - "dev": true, - "requires": { - "@typescript-eslint/utils": "^5.58.0" - } - }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - } - }, - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - }, - "espree": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.1.0.tgz", - "integrity": "sha512-ZgYLvCS1wxOczBYGcQT9DDWgicXwJ4dbocr9uYN+/eresBAUuBu+O4WzB21ufQ/JqQT8gyp7hJ3z8SHii32mTQ==", - "dev": true, - "requires": { - "acorn": "^8.6.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" - }, - "dependencies": { - "acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, - "eventemitter2": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-1.0.5.tgz", - "integrity": "sha512-EUFhWUYzqqBZlzBMI+dPU8rnKXfQZEUnitnccQuEIAnvWFHCpt3+4fts2+4dpxLtlsiseVXCMFg37KjYChSxpg==" - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "execa": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz", - "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "dev": true, - "optional": true - }, - "expand-tilde": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", - "integrity": "sha512-rtmc+cjLZqnu9dSYosX9EWmSJhTwpACgJQTfj4hgg2JjOD/6SIQalZrt4a3aQeh++oNxkazcaxrhPUj6+g5G/Q==", - "dev": true, - "requires": { - "os-homedir": "^1.0.1" - } - }, - "expect": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz", - "integrity": "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==", - "dev": true, - "requires": { - "@jest/expect-utils": "^29.6.2", - "@types/node": "*", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2" - } - }, - "expect-puppeteer": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/expect-puppeteer/-/expect-puppeteer-4.4.0.tgz", - "integrity": "sha512-6Ey4Xy2xvmuQu7z7YQtMsaMV0EHJRpVxIDOd5GRrm04/I3nkTKIutELfECsLp6le+b3SSa3cXhPiw6PgqzxYWA==", - "dev": true - }, - "exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", - "dev": true - }, - "express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dev": true, - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - }, - "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - } - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "external-editor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", - "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-descriptor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", - "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - } - } - } - }, - "extract-zip": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", - "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", - "dev": true, - "requires": { - "concat-stream": "^1.6.2", - "debug": "^2.6.9", - "mkdirp": "^0.5.4", - "yauzl": "^2.10.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - } - } - }, - "fast-average-color": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/fast-average-color/-/fast-average-color-9.1.1.tgz", - "integrity": "sha512-PJizLBcGb/jqUzrH66385te4+GcOK7wcUiCDvBUszdpzc/pvV1kwifvvsFygV3mS+7qwnWmK9/BrZniaOOC9ag==", - "requires": { - "@types/offscreencanvas": "^2019.7.0" - } - }, - "fast-base64-decode": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz", - "integrity": "sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-fifo": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.0.tgz", - "integrity": "sha512-IgfweLvEpwyA4WgiQe9Nx6VV2QkML2NkvZnk1oKnIzXgXdWxuhF7zw4DvLTPZJn6PIUneiAXPF24QmoEqHTjyw==", - "dev": true - }, - "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-parse": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", - "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fast-memoize": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", - "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" - }, - "fast-uri": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", - "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", - "dev": true - }, - "fast-xml-parser": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.4.tgz", - "integrity": "sha512-utnwm92SyozgA3hhH2I8qldf2lBqm6qHOICawRNRFu1qMe3+oqr+GcXjGqTmXTMGE5T4eC03kr/rlh5C1IRdZA==", - "requires": { - "strnum": "^1.0.5" - } - }, - "fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true - }, - "fastq": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz", - "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==", - "dev": true, - "requires": { - "reusify": "^1.0.0" - } - }, - "faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "fb-watchman": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", - "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", - "requires": { - "bser": "^2.0.0" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "fecha": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", - "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", - "dev": true - }, - "fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "dev": true, - "requires": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - } - }, - "fetch-retry": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-5.0.6.tgz", - "integrity": "sha512-3yurQZ2hD9VISAhJJP9bpYFNQrHHBXE2JxxjY5aLEcDi46RmAzJE2OC9FAde0yis5ElW0jTTzs0zfg/Cca4XqQ==", - "dev": true - }, - "figgy-pudding": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", - "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", - "dev": true - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-system-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-2.3.0.tgz", - "integrity": "sha512-l4DMNdsIPsVnKrgEXbJwDJsA5mB8rGwHYERMgqQx/xAUtChPJMre1bXBzDEqqVbWv9AIbFezXMxeEkZDSrXUOQ==", - "dev": true, - "requires": { - "fs-extra": "11.1.1", - "ramda": "0.29.0" - }, - "dependencies": { - "fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - } - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dev": true, - "requires": { - "minimatch": "^5.0.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "filename-reserved-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", - "dev": true - }, - "filenamify": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.2.0.tgz", - "integrity": "sha512-pkgE+4p7N1n7QieOopmn3TqJaefjdWXwEkj2XLZJLKfOgcQKkn11ahvGNgTD8mLggexLiDFQxeTs14xVU22XPA==", - "dev": true, - "requires": { - "filename-reserved-regex": "^2.0.0", - "strip-outer": "^1.0.1", - "trim-repeated": "^1.0.0" - } - }, - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "requires": { - "to-regex-range": "^5.0.1" - }, - "dependencies": { - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "filter-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==" - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "requires": { - "find-up": "^3.0.0" - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" - } - } - }, - "find-file-up": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-0.1.3.tgz", - "integrity": "sha512-mBxmNbVyjg1LQIIpgO8hN+ybWBgDQK8qjht+EbrTCGmmPV/sc7RF1i9stPTD6bpvXZywBdrwRYxhSdJv867L6A==", - "dev": true, - "requires": { - "fs-exists-sync": "^0.1.0", - "resolve-dir": "^0.1.0" - } - }, - "find-parent-dir": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", - "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", - "dev": true - }, - "find-pkg": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-0.1.2.tgz", - "integrity": "sha512-0rnQWcFwZr7eO0513HahrWafsc3CTFioEB7DRiEYCUM/70QXSY8f3mCST17HXLcPvEhzH/Ty/Bxd72ZZsr/yvw==", - "dev": true, - "requires": { - "find-file-up": "^0.1.2" - } - }, - "find-process": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.7.tgz", - "integrity": "sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "commander": "^5.1.0", - "debug": "^4.1.1" - }, - "dependencies": { - "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true - } - } - }, - "find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "find-yarn-workspace-root": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", - "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", - "dev": true, - "requires": { - "micromatch": "^4.0.2" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "requires": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "flow-enums-runtime": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", - "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==" - }, - "flow-parser": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.206.0.tgz", - "integrity": "sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w==" - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "fn.name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", - "dev": true - }, - "follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true - }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "requires": { - "is-callable": "^1.1.3" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", - "dev": true - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "fork-ts-checker-webpack-plugin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz", - "integrity": "sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cosmiconfig": "^7.0.1", - "deepmerge": "^4.2.2", - "fs-extra": "^10.0.0", - "memfs": "^3.4.1", - "minimatch": "^3.0.4", - "node-abort-controller": "^3.0.1", - "schema-utils": "^3.1.1", - "semver": "^7.3.5", - "tapable": "^2.2.1" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - } - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", - "dev": true - }, - "formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dev": true, - "requires": { - "fetch-blob": "^3.1.2" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true - }, - "fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "framer-motion": { - "version": "11.1.9", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.1.9.tgz", - "integrity": "sha512-flECDIPV4QDNcOrDafVFiIazp8X01HFpzc01eDKJsdNH/wrATcYydJSH9JbPWMS8UD5lZlw+J1sK8LG2kICgqw==", - "requires": { - "tslib": "^2.4.0" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "fs-exists-sync": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "integrity": "sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==", - "dev": true - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs-monkey": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", - "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==", - "dev": true - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "optional": true - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "ftp-response-parser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ftp-response-parser/-/ftp-response-parser-1.0.1.tgz", - "integrity": "sha512-++Ahlo2hs/IC7UVQzjcSAfeUpCwTTzs4uvG5XfGnsinIFkWUYF4xWwPd5qZuK8MJrmUIxFMuHcfqaosCDjvIWw==", - "dev": true, - "requires": { - "readable-stream": "^1.0.31" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "dev": true - } - } - }, - "function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" - }, - "function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - } - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true - }, - "gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "geckodriver": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-4.2.1.tgz", - "integrity": "sha512-4m/CRk0OI8MaANRuFIahvOxYTSjlNAO2p9JmE14zxueknq6cdtB5M9UGRQ8R9aMV0bLGNVHHDnDXmoXdOwJfWg==", - "dev": true, - "requires": { - "@wdio/logger": "^8.11.0", - "decamelize": "^6.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "node-fetch": "^3.3.1", - "tar-fs": "^3.0.4", - "unzipper": "^0.10.14", - "which": "^4.0.0" - }, - "dependencies": { - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - }, - "data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "dev": true - }, - "decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", - "dev": true - }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, - "isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true - }, - "node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "dev": true, - "requires": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - } - }, - "pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "tar-fs": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", - "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", - "dev": true, - "requires": { - "bare-fs": "^2.1.1", - "bare-path": "^2.1.0", - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - } - }, - "tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, - "requires": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, - "which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", - "dev": true, - "requires": { - "isexe": "^3.1.1" - } - } - } - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" - }, - "get-browser-rtc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz", - "integrity": "sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ==" - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "requires": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - } - }, - "get-nonce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", - "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==" - }, - "get-npm-tarball-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/get-npm-tarball-url/-/get-npm-tarball-url-2.1.0.tgz", - "integrity": "sha512-ro+DiMu5DXgRBabqXupW38h7WPZ9+Ad8UjwhvsmmN8w1sU7ab0nzAXvVZ4kqYg57OrqomRtJvepX5/xvFKNtjA==", - "dev": true - }, - "get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", - "dev": true - }, - "get-pkg-repo": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", - "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", - "dev": true, - "requires": { - "@hutson/parse-repository-url": "^3.0.0", - "hosted-git-info": "^4.0.0", - "through2": "^2.0.0", - "yargs": "^16.2.0" - } - }, - "get-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", - "dev": true - }, - "get-stdin": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", - "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", - "dev": true - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - }, - "dependencies": { - "pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "get-uri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.1.tgz", - "integrity": "sha512-7ZqONUVqaabogsYNWlYj0t3YZaL6dhuEueZXGF+/YVmf6dHmaFg8/6psJKqhx9QykIDKzpGcy2cn4oV4YC7V/Q==", - "dev": true, - "requires": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^5.0.1", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", - "dev": true - }, - "gettext-parser": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.4.0.tgz", - "integrity": "sha512-sedZYLHlHeBop/gZ1jdg59hlUEcpcZJofLq2JFwJT1zTqAU3l2wFv6IsuwFHGqbiT9DWzMUW4/em2+hspnmMMA==", - "requires": { - "encoding": "^0.1.12", - "safe-buffer": "^5.1.1" - } - }, - "giget": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.1.tgz", - "integrity": "sha512-4VG22mopWtIeHwogGSy1FViXVo0YT+m6BrqZfz0JJFwbSsePsCdOzdLIIli5BtMp7Xe8f/o2OmBpQX2NBOC24g==", - "dev": true, - "requires": { - "citty": "^0.1.5", - "consola": "^3.2.3", - "defu": "^6.1.3", - "node-fetch-native": "^1.6.1", - "nypm": "^0.3.3", - "ohash": "^1.1.3", - "pathe": "^1.1.1", - "tar": "^6.2.0" - }, - "dependencies": { - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "consola": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", - "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", - "dev": true - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "git-raw-commits": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-3.0.0.tgz", - "integrity": "sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==", - "dev": true, - "requires": { - "dargs": "^7.0.0", - "meow": "^8.1.2", - "split2": "^3.2.2" - } - }, - "git-remote-origin-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", - "integrity": "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==", - "dev": true, - "requires": { - "gitconfiglocal": "^1.0.0", - "pify": "^2.3.0" - } - }, - "git-semver-tags": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-5.0.1.tgz", - "integrity": "sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==", - "dev": true, - "requires": { - "meow": "^8.1.2", - "semver": "^7.0.0" - } - }, - "git-up": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", - "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==", - "dev": true, - "requires": { - "is-ssh": "^1.4.0", - "parse-url": "^8.1.0" - } - }, - "git-url-parse": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.0.tgz", - "integrity": "sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==", - "dev": true, - "requires": { - "git-up": "^7.0.0" - } - }, - "gitconfiglocal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", - "integrity": "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==", - "dev": true, - "requires": { - "ini": "^1.3.2" - } - }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "dev": true, - "optional": true - }, - "github-slugger": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz", - "integrity": "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==", - "dev": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", - "dev": true, - "optional": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", - "dev": true, - "optional": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "requires": { - "global-prefix": "^3.0.0" - } - }, - "global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "requires": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - } - }, - "globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - }, - "dependencies": { - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "dependencies": { - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "globjoin": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", - "dev": true - }, - "good-listener": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", - "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", - "requires": { - "delegate": "^3.1.2" - } - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, - "requires": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "gradient-parser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/gradient-parser/-/gradient-parser-0.1.5.tgz", - "integrity": "sha512-+uPlcVbjrKOnTzvz0MjTj7BfACj8OmxIa1moIjJV7btvhUMSJk0D47RfDCgDrZE3dYMz9Cf5xKJwnrKLjUq0KQ==" - }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "gunzip-maybe": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", - "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", - "dev": true, - "requires": { - "browserify-zlib": "^0.1.4", - "is-deflate": "^1.0.0", - "is-gzip": "^1.0.0", - "peek-stream": "^1.1.0", - "pumpify": "^1.3.3", - "through2": "^2.0.3" - }, - "dependencies": { - "browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", - "dev": true, - "requires": { - "pako": "~0.2.0" - } - }, - "pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", - "dev": true - } - } - }, - "handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - } - }, - "hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true - } - } - }, - "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - }, - "has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "requires": { - "es-define-property": "^1.0.0" - } - }, - "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "requires": { - "function-bind": "^1.1.2" - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "header-case": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", - "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", - "requires": { - "capital-case": "^1.0.4", - "tslib": "^2.0.3" - } - }, - "hermes-estree": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.15.0.tgz", - "integrity": "sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ==" - }, - "hermes-parser": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.15.0.tgz", - "integrity": "sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q==", - "requires": { - "hermes-estree": "0.15.0" - } - }, - "hermes-profile-transformer": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz", - "integrity": "sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ==", - "requires": { - "source-map": "^0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" - } - } - }, - "highlight-words-core": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/highlight-words-core/-/highlight-words-core-1.2.2.tgz", - "integrity": "sha512-BXUKIkUuh6cmmxzi5OIbUJxrG8OAk2MqoL1DtO3Wo9D2faJg2ph5ntyuQeLqaHJmzER6H5tllCDA9ZnNe9BVGg==" - }, - "history": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", - "integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==", - "requires": { - "@babel/runtime": "^7.7.6" - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dev": true, - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "requires": { - "react-is": "^16.7.0" - } - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "hpq": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/hpq/-/hpq-1.3.0.tgz", - "integrity": "sha512-fvYTvdCFOWQupGxqkahrkA+ERBuMdzkxwtUdKrxR6rmMd4Pfl+iZ1QiQYoaZ0B/v0y59MOMnz3XFUWbT50/NWA==" - }, - "html-encoding-sniffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", - "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "dev": true, - "requires": { - "whatwg-encoding": "^3.1.1" - } - }, - "html-entities": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", - "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", - "dev": true - }, - "html-escaper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", - "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", - "dev": true - }, - "html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "requires": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "dependencies": { - "commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true - } - } - }, - "html-tags": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", - "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", - "dev": true - }, - "html-webpack-plugin": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", - "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", - "dev": true, - "requires": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "dependencies": { - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - } - } - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - }, - "dependencies": { - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - } - } - }, - "htmlparser2-without-node-native": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/htmlparser2-without-node-native/-/htmlparser2-without-node-native-3.9.2.tgz", - "integrity": "sha512-+FplQXqmY5fRx6vCIp2P5urWaoBCpTNJMXnKP/6mNCcyb+AZWWJzA8D03peXfozlxDL+vpgLK5dJblqEgu8j6A==", - "requires": { - "domelementtype": "^1.3.0", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "eventemitter2": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" - } - }, - "http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - } - } - }, - "http-link-header": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-link-header/-/http-link-header-1.1.1.tgz", - "integrity": "sha512-mW3N/rTYpCn99s1do0zx6nzFZSwLH9HGfUM4ZqLWJ16ylmYaC2v5eYGqrNTQlByx8AzUgGI+V/32gXPugs1+Sw==", - "dev": true - }, - "http-parser-js": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", - "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", - "dev": true - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "dependencies": { - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true - } - } - }, - "http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, - "requires": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - } - }, - "http-status-codes": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", - "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", - "dev": true - }, - "http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, - "requires": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "dependencies": { - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true - } - } - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", - "dev": true - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "requires": { - "ms": "^2.0.0" - } - }, - "husky": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.0.tgz", - "integrity": "sha512-xK7lO0EtSzfFPiw+oQncQVy/XqV7UVVjxBByc+Iv5iK3yhW9boDoWgvZy3OGo48QKg/hUtZkzz0hi2HXa0kn7w==", - "dev": true - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==", - "dev": true - }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "ignore-walk": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-4.0.1.tgz", - "integrity": "sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==", - "dev": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "image-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", - "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", - "requires": { - "queue": "6.0.2" - } - }, - "image-ssim": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/image-ssim/-/image-ssim-0.2.0.tgz", - "integrity": "sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" - } - } - }, - "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - } - } - }, - "import-locals": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-locals/-/import-locals-2.0.0.tgz", - "integrity": "sha512-1/bPE89IZhyf7dr5Pkz7b4UyVXy5pEt7PTEfye15UEn3AK8+2zwcDCfKk9Pwun4ltfhOSszOrReSsFcDKw/yoA==" - }, - "import-meta-resolve": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-3.0.0.tgz", - "integrity": "sha512-4IwhLhNNA8yy445rPjD/lWh++7hMDOml2eHtd58eG7h+qK3EryMuuRbsHGPikCoAgIkkDnckKfWSk2iDla/ejg==", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" - }, - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==", - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "init-package-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-5.0.0.tgz", - "integrity": "sha512-kBhlSheBfYmq3e0L1ii+VKe3zBTLL5lDCDWR+f9dLmEGSB3MqLlMlsolubSsyI88Bg6EA+BIMlomAnQ1SwgQBw==", - "dev": true, - "requires": { - "npm-package-arg": "^10.0.0", - "promzard": "^1.0.0", - "read": "^2.0.0", - "read-package-json": "^6.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^5.0.0" - }, - "dependencies": { - "hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "npm-package-arg": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", - "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", - "dev": true, - "requires": { - "hosted-git-info": "^6.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - } - }, - "validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", - "dev": true - } - } - }, - "inquirer": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", - "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", - "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.15", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.5.3", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true - }, - "intl-messageformat": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-4.4.0.tgz", - "integrity": "sha512-z+Bj2rS3LZSYU4+sNitdHrwnBhr0wO80ZJSW8EzKDBowwUe3Q/UsvgCGjrwa+HPzoGCLEb9HAjfJgo4j2Sac8w==", - "dev": true, - "requires": { - "intl-messageformat-parser": "^1.8.1" - } - }, - "intl-messageformat-parser": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.8.1.tgz", - "integrity": "sha512-IMSCKVf0USrM/959vj3xac7s8f87sc+80Y/ipBzdKy4ifBv5Gsj2tZ41EAaURVg01QU71fYr77uA8Meh6kELbg==", - "dev": true - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "requires": { - "loose-envify": "^1.0.0" - } - }, - "ip": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", - "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==" - }, - "ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dev": true, - "requires": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "dependencies": { - "sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true - } - } - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true - }, - "irregular-plurals": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.2.0.tgz", - "integrity": "sha512-YqTdPLfwP7YFN0SsD3QUVCkm9ZG2VzOXv3DOrw5G5mkMbVwptTwVcFv7/C0vOpBmgTxAeTG19XpUs1E522LW9Q==", - "dev": true - }, - "is-absolute-url": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", - "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", - "dev": true - }, - "is-accessor-descriptor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", - "integrity": "sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==", - "dev": true, - "requires": { - "hasown": "^2.0.0" - } - }, - "is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", - "dev": true - }, - "is-alphanumeric": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", - "integrity": "sha512-ZmRL7++ZkcMOfDuWZuMJyIVLr2keE1o/DeNWh1EmgqGhUcV+9BIVsx0BcSBOHTZqzjs4+dISzr2KAeBEWGgXeA==", - "dev": true - }, - "is-alphanumerical": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", - "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", - "dev": true, - "requires": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - } - }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "requires": { - "builtin-modules": "^3.3.0" - } - }, - "is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - }, - "dependencies": { - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - } - } - }, - "is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "requires": { - "has": "^1.0.3" - } - }, - "is-data-descriptor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz", - "integrity": "sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==", - "dev": true, - "requires": { - "hasown": "^2.0.0" - } - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-decimal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", - "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", - "dev": true - }, - "is-deflate": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", - "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", - "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - } - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==" - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==" - }, - "is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true - }, - "is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-gzip": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", - "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", - "dev": true - }, - "is-hexadecimal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", - "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", - "dev": true - }, - "is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "requires": { - "is-docker": "^3.0.0" - }, - "dependencies": { - "is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true - } - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" - }, - "is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true - }, - "is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true - }, - "is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - } - }, - "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", - "dev": true - }, - "is-observable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", - "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", - "dev": true, - "requires": { - "symbol-observable": "^1.1.0" - } - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "requires": { - "is-path-inside": "^2.1.0" - } - }, - "is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "requires": { - "path-is-inside": "^1.0.2" - } - }, - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true - }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" - }, - "is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", - "dev": true - }, - "is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-ssh": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", - "integrity": "sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==", - "dev": true, - "requires": { - "protocols": "^2.0.1" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", - "dev": true, - "requires": { - "text-extensions": "^1.0.0" - } - }, - "is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dev": true, - "requires": { - "which-typed-array": "^1.1.11" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" - }, - "is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true - }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "is-whitespace-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", - "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-word-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", - "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", - "dev": true - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" - }, - "isomorphic.js": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", - "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==" - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "jake": { - "version": "10.8.7", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", - "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", - "dev": true, - "requires": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" - } - }, - "javascript-natural-sort": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", - "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", - "dev": true - }, - "jed": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/jed/-/jed-1.1.1.tgz", - "integrity": "sha512-z35ZSEcXHxLW4yumw0dF6L464NT36vmx3wxJw8MDpraBcWuNVgUPZgPJKcu1HekNgwlMFNqol7i/IpSbjhqwqA==" - }, - "jest": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz", - "integrity": "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==", - "dev": true, - "requires": { - "@jest/core": "^29.6.2", - "@jest/types": "^29.6.1", - "import-local": "^3.0.2", - "jest-cli": "^29.6.2" - } - }, - "jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", - "dev": true, - "requires": { - "execa": "^5.0.0", - "p-limit": "^3.1.0" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "jest-circus": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz", - "integrity": "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==", - "dev": true, - "requires": { - "@jest/environment": "^29.6.2", - "@jest/expect": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.6.2", - "jest-matcher-utils": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-runtime": "^29.6.2", - "jest-snapshot": "^29.6.2", - "jest-util": "^29.6.2", - "p-limit": "^3.1.0", - "pretty-format": "^29.6.2", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "dependencies": { - "dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", - "dev": true - } - } - }, - "jest-cli": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz", - "integrity": "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==", - "dev": true, - "requires": { - "@jest/core": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/types": "^29.6.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^29.6.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", - "prompts": "^2.0.1", - "yargs": "^17.3.1" - }, - "dependencies": { - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, - "jest-config": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz", - "integrity": "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.6.2", - "@jest/types": "^29.6.1", - "babel-jest": "^29.6.2", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.6.2", - "jest-environment-node": "^29.6.2", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.2", - "jest-runner": "^29.6.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.6.2", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - } - } - }, - "jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", - "dev": true, - "requires": { - "detect-newline": "^3.0.0" - } - }, - "jest-each": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz", - "integrity": "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.1", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.6.2", - "pretty-format": "^29.6.2" - } - }, - "jest-environment-jsdom": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.6.2.tgz", - "integrity": "sha512-7oa/+266AAEgkzae8i1awNEfTfjwawWKLpiw2XesZmaoVVj9u9t8JOYx18cG29rbPNtkUlZ8V4b5Jb36y/VxoQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.6.2", - "@jest/fake-timers": "^29.6.2", - "@jest/types": "^29.6.1", - "@types/jsdom": "^20.0.0", - "@types/node": "*", - "jest-mock": "^29.6.2", - "jest-util": "^29.6.2", - "jsdom": "25.0.1" - } - }, - "jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "requires": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==" - }, - "jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-jasmine2": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-29.6.2.tgz", - "integrity": "sha512-g8IF0MHkDYeDYt9eseYx3nx8cn86zCuP49G72f19oXcuCu8b46rt293RRLErLUTbTubRP7zl/ev5+p4I5XPc9g==", - "dev": true, - "requires": { - "@jest/environment": "^29.6.2", - "@jest/expect": "^29.6.2", - "@jest/source-map": "^29.6.0", - "@jest/test-result": "^29.6.2", - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.6.2", - "jest-matcher-utils": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-runtime": "^29.6.2", - "jest-snapshot": "^29.6.2", - "jest-util": "^29.6.2", - "p-limit": "^3.1.0", - "pretty-format": "^29.6.2" - } - }, - "jest-junit": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-13.0.0.tgz", - "integrity": "sha512-JSHR+Dhb32FGJaiKkqsB7AR3OqWKtldLd6ZH2+FJ8D4tsweb8Id8zEVReU4+OlrRO1ZluqJLQEETm+Q6/KilBg==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "strip-ansi": "^6.0.1", - "uuid": "^8.3.2", - "xml": "^1.0.1" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - } - } - }, - "jest-leak-detector": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz", - "integrity": "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==", - "dev": true, - "requires": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.2" - } - }, - "jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-message-util": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz", - "integrity": "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.6.2", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - } - }, - "jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-resolve": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz", - "integrity": "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - } - }, - "jest-resolve-dependencies": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz", - "integrity": "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==", - "dev": true, - "requires": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.6.2" - } - }, - "jest-runner": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz", - "integrity": "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==", - "dev": true, - "requires": { - "@jest/console": "^29.6.2", - "@jest/environment": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.6.2", - "jest-haste-map": "^29.6.2", - "jest-leak-detector": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-resolve": "^29.6.2", - "jest-runtime": "^29.6.2", - "jest-util": "^29.6.2", - "jest-watcher": "^29.6.2", - "jest-worker": "^29.6.2", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "dependencies": { - "source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - } - } - }, - "jest-runtime": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz", - "integrity": "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==", - "dev": true, - "requires": { - "@jest/environment": "^29.6.2", - "@jest/fake-timers": "^29.6.2", - "@jest/globals": "^29.6.2", - "@jest/source-map": "^29.6.0", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-mock": "^29.6.2", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.2", - "jest-snapshot": "^29.6.2", - "jest-util": "^29.6.2", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "jest-snapshot": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz", - "integrity": "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.6.2", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.6.2", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2", - "natural-compare": "^1.4.0", - "pretty-format": "^29.6.2", - "semver": "^7.5.3" - } - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "requires": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" - } - } - }, - "jest-watch-typeahead": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-2.2.2.tgz", - "integrity": "sha512-+QgOFW4o5Xlgd6jGS5X37i08tuuXNW8X0CV9WNFi+3n8ExCIP+E1melYhvYLjv5fE6D0yyzk74vsSO8I6GqtvQ==", - "dev": true, - "requires": { - "ansi-escapes": "^6.0.0", - "chalk": "^5.2.0", - "jest-regex-util": "^29.0.0", - "jest-watcher": "^29.0.0", - "slash": "^5.0.0", - "string-length": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "dependencies": { - "ansi-escapes": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", - "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", - "dev": true - }, - "ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true - }, - "chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true - }, - "char-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", - "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==", - "dev": true - }, - "slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true - }, - "string-length": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", - "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", - "dev": true, - "requires": { - "char-regex": "^2.0.0", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "jest-watcher": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz", - "integrity": "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==", - "dev": true, - "requires": { - "@jest/test-result": "^29.6.2", - "@jest/types": "^29.6.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.6.2", - "string-length": "^4.0.1" - } - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "joi": { - "version": "17.13.3", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", - "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", - "requires": { - "@hapi/hoek": "^9.3.0", - "@hapi/topo": "^5.1.0", - "@sideway/address": "^4.1.5", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" - } - }, - "jpeg-js": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", - "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", - "dev": true - }, - "js-library-detector": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/js-library-detector/-/js-library-detector-6.7.0.tgz", - "integrity": "sha512-c80Qupofp43y4cJ7+8TTDN/AsDwLi5oOm/plBrWI+iQt485vKXCco+yVmOwEgdo9VOdsYTuV0UlTeetVPTriXA==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true - }, - "jsc-android": { - "version": "250231.0.0", - "resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz", - "integrity": "sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==" - }, - "jsc-safe-url": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", - "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==" - }, - "jscodeshift": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz", - "integrity": "sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==", - "requires": { - "@babel/core": "^7.13.16", - "@babel/parser": "^7.13.16", - "@babel/plugin-proposal-class-properties": "^7.13.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", - "@babel/plugin-proposal-optional-chaining": "^7.13.12", - "@babel/plugin-transform-modules-commonjs": "^7.13.8", - "@babel/preset-flow": "^7.13.13", - "@babel/preset-typescript": "^7.13.0", - "@babel/register": "^7.13.16", - "babel-core": "^7.0.0-bridge.0", - "chalk": "^4.1.2", - "flow-parser": "0.*", - "graceful-fs": "^4.2.4", - "micromatch": "^4.0.4", - "neo-async": "^2.5.0", - "node-dir": "^0.1.17", - "recast": "^0.21.0", - "temp": "^0.8.4", - "write-file-atomic": "^2.3.0" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jsdoc-type-pratt-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", - "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", - "dev": true - }, - "jsdom": { - "version": "25.0.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", - "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", - "dev": true, - "requires": { - "cssstyle": "^4.1.0", - "data-urls": "^5.0.0", - "decimal.js": "^10.4.3", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.5", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.12", - "parse5": "^7.1.2", - "rrweb-cssom": "^0.7.1", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^5.0.0", - "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^3.1.1", - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0", - "ws": "^8.18.0", - "xml-name-validator": "^5.0.0" - }, - "dependencies": { - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, - "tr46": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", - "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", - "dev": true, - "requires": { - "punycode": "^2.3.1" - } - }, - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true - }, - "whatwg-url": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", - "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", - "dev": true, - "requires": { - "tr46": "^5.0.0", - "webidl-conversions": "^7.0.0" - } - }, - "ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true - } - } - }, - "jsdom-jscore-rn": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/jsdom-jscore-rn/-/jsdom-jscore-rn-0.1.8.tgz", - "integrity": "sha512-Sm0BCCQL3RRmJwztZa9B4QIOxgFOiu7vpsJjLsjG55HlRzOgUdmTOHrhV4SZkjXef5sBF+E8qKnrhsBUO7Gxjg==", - "requires": { - "htmlparser2-without-node-native": "^3.9.2", - "querystring": "^0.2.0" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" - }, - "jsftp": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/jsftp/-/jsftp-2.1.3.tgz", - "integrity": "sha512-r79EVB8jaNAZbq8hvanL8e8JGu2ZNr2bXdHC4ZdQhRImpSPpnWwm5DYVzQ5QxJmtGtKhNNuvqGgbNaFl604fEQ==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "ftp-response-parser": "^1.0.1", - "once": "^1.4.0", - "parse-listing": "^1.1.3", - "stream-combiner": "^0.2.2", - "unorm": "^1.4.1" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.0.tgz", - "integrity": "sha512-zfA+5SuwYN2VWqN1/5HZaDzQKLJHaBVMZIIM+wuYjdptkaQsqzDdqjqf+lZZJUuJq1aanHiY8LhH8LmH+qBYJA==", - "dev": true, - "requires": { - "call-bind": "^1.0.5", - "isarray": "^2.0.5", - "jsonify": "^0.0.1", - "object-keys": "^1.1.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - } - } - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true - }, - "json2php": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/json2php/-/json2php-0.0.7.tgz", - "integrity": "sha512-dnSoUiLAoVaMXxFsVi4CrPVYMKOuDBXTghXSmMINX44RZ8WM9cXlY7UqrQnlAcODCVO7FV3+8t/5nDKAjimLfg==", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" - }, - "jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", - "dev": true - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", - "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", - "dev": true - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "requires": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - } - }, - "keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" - }, - "klaw": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-4.1.0.tgz", - "integrity": "sha512-1zGZ9MF9H22UnkpVeuaGKOjfA2t6WrfdrJmGjy16ykcjnKQDmHVX+KI477rpbGevz/5FD4MC3xf1oxylBgcaQw==", - "dev": true - }, - "klaw-sync": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", - "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11" - } - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" - }, - "klona": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "dev": true - }, - "known-css-properties": { - "version": "0.34.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.34.0.tgz", - "integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==", - "dev": true - }, - "kuler": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", - "dev": true - }, - "ky": { - "version": "0.33.3", - "resolved": "https://registry.npmjs.org/ky/-/ky-0.33.3.tgz", - "integrity": "sha512-CasD9OCEQSFIam2U8efFK81Yeg8vNMTBUqtMOHlrcWQHqUX3HeCl9Dr31u4toV7emlH8Mymk5+9p0lL6mKb/Xw==", - "dev": true - }, - "language-subtag-registry": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz", - "integrity": "sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==", - "dev": true - }, - "language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", - "dev": true, - "requires": { - "language-subtag-registry": "~0.3.2" - } - }, - "launch-editor": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", - "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", - "dev": true, - "requires": { - "picocolors": "^1.0.0", - "shell-quote": "^1.7.3" - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==", - "dev": true - }, - "lazy-universal-dotenv": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/lazy-universal-dotenv/-/lazy-universal-dotenv-4.0.0.tgz", - "integrity": "sha512-aXpZJRnTkpK6gQ/z4nk+ZBLd/Qdp118cvPruLSIQzQNRhKwEcdXCOzXuF55VDqIiuAaY3UGZ10DJtvZzDcvsxg==", - "dev": true, - "requires": { - "app-root-dir": "^1.0.2", - "dotenv": "^16.0.0", - "dotenv-expand": "^10.0.0" - } - }, - "lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - } - }, - "lerna": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/lerna/-/lerna-7.1.4.tgz", - "integrity": "sha512-/cabvmTTkmayyALIZx7OpHRex72i8xSOkiJchEkrKxAZHoLNaGSwqwKkj+x6WtmchhWl/gLlqwQXGRuxrJKiBw==", - "dev": true, - "requires": { - "@lerna/child-process": "7.1.4", - "@lerna/create": "7.1.4", - "@npmcli/run-script": "6.0.2", - "@nx/devkit": ">=16.5.1 < 17", - "@octokit/plugin-enterprise-rest": "6.0.1", - "@octokit/rest": "19.0.11", - "byte-size": "8.1.1", - "chalk": "4.1.0", - "clone-deep": "4.0.1", - "cmd-shim": "6.0.1", - "columnify": "1.6.0", - "conventional-changelog-angular": "6.0.0", - "conventional-changelog-core": "5.0.1", - "conventional-recommended-bump": "7.0.1", - "cosmiconfig": "^8.2.0", - "dedent": "0.7.0", - "envinfo": "7.8.1", - "execa": "5.0.0", - "fs-extra": "^11.1.1", - "get-port": "5.1.1", - "get-stream": "6.0.0", - "git-url-parse": "13.1.0", - "glob-parent": "5.1.2", - "globby": "11.1.0", - "graceful-fs": "4.2.11", - "has-unicode": "2.0.1", - "import-local": "3.1.0", - "ini": "^1.3.8", - "init-package-json": "5.0.0", - "inquirer": "^8.2.4", - "is-ci": "3.0.1", - "is-stream": "2.0.0", - "jest-diff": ">=29.4.3 < 30", - "js-yaml": "4.1.0", - "libnpmaccess": "7.0.2", - "libnpmpublish": "7.3.0", - "load-json-file": "6.2.0", - "lodash": "^4.17.21", - "make-dir": "3.1.0", - "minimatch": "3.0.5", - "multimatch": "5.0.0", - "node-fetch": "2.6.7", - "npm-package-arg": "8.1.1", - "npm-packlist": "5.1.1", - "npm-registry-fetch": "^14.0.5", - "npmlog": "^6.0.2", - "nx": ">=16.5.1 < 17", - "p-map": "4.0.0", - "p-map-series": "2.1.0", - "p-pipe": "3.1.0", - "p-queue": "6.6.2", - "p-reduce": "2.1.0", - "p-waterfall": "2.1.1", - "pacote": "^15.2.0", - "pify": "5.0.0", - "read-cmd-shim": "4.0.0", - "read-package-json": "6.0.4", - "resolve-from": "5.0.0", - "rimraf": "^4.4.1", - "semver": "^7.3.8", - "signal-exit": "3.0.7", - "slash": "3.0.0", - "ssri": "^9.0.1", - "strong-log-transformer": "2.1.0", - "tar": "6.1.11", - "temp-dir": "1.0.0", - "typescript": ">=3 < 6", - "upath": "2.0.1", - "uuid": "^9.0.0", - "validate-npm-package-license": "3.0.4", - "validate-npm-package-name": "5.0.0", - "write-file-atomic": "5.0.1", - "write-pkg": "4.0.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4" - }, - "dependencies": { - "@octokit/auth-token": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz", - "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==", - "dev": true - }, - "@octokit/core": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz", - "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==", - "dev": true, - "requires": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/endpoint": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz", - "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==", - "dev": true, - "requires": { - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/graphql": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", - "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", - "dev": true, - "requires": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/openapi-types": { - "version": "18.1.1", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.1.1.tgz", - "integrity": "sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==", - "dev": true - }, - "@octokit/plugin-paginate-rest": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", - "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", - "dev": true, - "requires": { - "@octokit/tsconfig": "^1.0.2", - "@octokit/types": "^9.2.3" - } - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz", - "integrity": "sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==", - "dev": true, - "requires": { - "@octokit/types": "^10.0.0" - }, - "dependencies": { - "@octokit/types": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-10.0.0.tgz", - "integrity": "sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==", - "dev": true, - "requires": { - "@octokit/openapi-types": "^18.0.0" - } - } - } - }, - "@octokit/request": { - "version": "6.2.8", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz", - "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==", - "dev": true, - "requires": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", - "dev": true, - "requires": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/rest": { - "version": "19.0.11", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", - "integrity": "sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==", - "dev": true, - "requires": { - "@octokit/core": "^4.2.1", - "@octokit/plugin-paginate-rest": "^6.1.2", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.1.2" - } - }, - "@octokit/types": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz", - "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", - "dev": true, - "requires": { - "@octokit/openapi-types": "^18.0.0" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true - }, - "cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "requires": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", - "dev": true - }, - "execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", - "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", - "dev": true - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "hosted-git-info": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", - "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "ignore-walk": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", - "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==", - "dev": true, - "requires": { - "minimatch": "^5.0.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "inquirer": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", - "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6", - "wrap-ansi": "^6.0.1" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - } - } - }, - "is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "requires": { - "ci-info": "^3.2.0" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "npm-package-arg": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.1.tgz", - "integrity": "sha512-CsP95FhWQDwNqiYS+Q0mZ7FAEDytDZAkNxQqea6IaAFJTAY9Lhhqyl0irU/6PMc7BGfUmnsbHcqxJD7XuVM/rg==", - "dev": true, - "requires": { - "hosted-git-info": "^3.0.6", - "semver": "^7.0.0", - "validate-npm-package-name": "^3.0.0" - }, - "dependencies": { - "validate-npm-package-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", - "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", - "dev": true, - "requires": { - "builtins": "^1.0.3" - } - } - } - }, - "npm-packlist": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.1.tgz", - "integrity": "sha512-UfpSvQ5YKwctmodvPPkK6Fwk603aoVsf8AEbmVKAEECrfvL8SSe1A2YIwrJ6xmTHAITKPwwZsWo7WwEbNk0kxw==", - "dev": true, - "requires": { - "glob": "^8.0.1", - "ignore-walk": "^5.0.1", - "npm-bundled": "^1.1.2", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", - "dev": true - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "rimraf": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", - "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", - "dev": true, - "requires": { - "glob": "^9.2.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "minimatch": "^8.0.2", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" - } - }, - "minimatch": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", - "dev": true - } - } - }, - "rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "universal-user-agent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", - "dev": true - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - }, - "upath": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", - "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", - "dev": true - }, - "validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "dev": true, - "requires": { - "builtins": "^5.0.0" - }, - "dependencies": { - "builtins": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", - "integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==", - "dev": true, - "requires": { - "semver": "^7.0.0" - } - } - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "dependencies": { - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - } - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "lib0": { - "version": "0.2.79", - "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.79.tgz", - "integrity": "sha512-fIdPbxzMVq10wt3ou1lp3/f9n5ciHZ6t+P1vyGy3XXr018AntTYM4eg24sNFcNq8SYDQwmhhoGdS58IlYBzfBw==", - "requires": { - "isomorphic.js": "^0.2.4" - } - }, - "libnpmaccess": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-7.0.2.tgz", - "integrity": "sha512-vHBVMw1JFMTgEk15zRsJuSAg7QtGGHpUSEfnbcRL1/gTBag9iEfJbyjpDmdJmwMhvpoLoNBtdAUCdGnaP32hhw==", - "dev": true, - "requires": { - "npm-package-arg": "^10.1.0", - "npm-registry-fetch": "^14.0.3" - }, - "dependencies": { - "hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "npm-package-arg": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", - "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", - "dev": true, - "requires": { - "hosted-git-info": "^6.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - } - }, - "validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", - "dev": true - } - } - }, - "libnpmpublish": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-7.3.0.tgz", - "integrity": "sha512-fHUxw5VJhZCNSls0KLNEG0mCD2PN1i14gH5elGOgiVnU3VgTcRahagYP2LKI1m0tFCJ+XrAm0zVYyF5RCbXzcg==", - "dev": true, - "requires": { - "ci-info": "^3.6.1", - "normalize-package-data": "^5.0.0", - "npm-package-arg": "^10.1.0", - "npm-registry-fetch": "^14.0.3", - "proc-log": "^3.0.0", - "semver": "^7.3.7", - "sigstore": "^1.4.0", - "ssri": "^10.0.1" - }, - "dependencies": { - "hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - }, - "normalize-package-data": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", - "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", - "dev": true, - "requires": { - "hosted-git-info": "^6.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - } - }, - "npm-package-arg": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", - "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", - "dev": true, - "requires": { - "hosted-git-info": "^6.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - } - }, - "ssri": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", - "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", - "dev": true, - "requires": { - "minipass": "^7.0.3" - } - }, - "validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", - "dev": true - } - } - }, - "lighthouse": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/lighthouse/-/lighthouse-10.4.0.tgz", - "integrity": "sha512-XQWHEWkJ8YxSPsxttBJORy5+hQrzbvGkYfeP3fJjyYKioWkF2MXfFqNK4ZuV4jL8pBu7Z91qnQP6In0bq1yXww==", - "dev": true, - "requires": { - "@sentry/node": "^6.17.4", - "axe-core": "4.7.2", - "chrome-launcher": "^0.15.2", - "configstore": "^5.0.1", - "csp_evaluator": "1.1.1", - "devtools-protocol": "0.0.1155343", - "enquirer": "^2.3.6", - "http-link-header": "^1.1.1", - "intl-messageformat": "^4.4.0", - "jpeg-js": "^0.4.4", - "js-library-detector": "^6.6.0", - "lighthouse-logger": "^1.4.1", - "lighthouse-stack-packs": "1.11.0", - "lodash": "^4.17.21", - "lookup-closest-locale": "6.2.0", - "metaviewport-parser": "0.3.0", - "open": "^8.4.0", - "parse-cache-control": "1.0.1", - "ps-list": "^8.0.0", - "puppeteer-core": "^20.8.0", - "robots-parser": "^3.0.0", - "semver": "^5.3.0", - "speedline-core": "^1.4.3", - "third-party-web": "^0.23.3", - "ws": "^7.0.0", - "yargs": "^17.3.1", - "yargs-parser": "^21.0.0" - }, - "dependencies": { - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "devtools-protocol": { - "version": "0.0.1155343", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1155343.tgz", - "integrity": "sha512-oD9vGBV2wTc7fAzAM6KC0chSgs234V8+qDEeK+mcbRj2UvcuA7lgBztGi/opj/iahcXD3BSj8Ymvib628yy9FA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "puppeteer-core": { - "version": "20.9.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-20.9.0.tgz", - "integrity": "sha512-H9fYZQzMTRrkboEfPmf7m3CLDN6JvbxXA3qTtS+dFt27tR+CsFHzPsT6pzp6lYL6bJbAPaR0HaPO6uSi+F94Pg==", - "dev": true, - "requires": { - "@puppeteer/browsers": "1.4.6", - "chromium-bidi": "0.4.16", - "cross-fetch": "4.0.0", - "debug": "4.3.4", - "devtools-protocol": "0.0.1147663", - "ws": "8.13.0" - }, - "dependencies": { - "devtools-protocol": { - "version": "0.0.1147663", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1147663.tgz", - "integrity": "sha512-hyWmRrexdhbZ1tcJUGpO95ivbRhWXz++F4Ko+n21AY5PNln2ovoJw+8ZMNDTtip+CNFQfrtLVh/w4009dXO/eQ==", - "dev": true - }, - "ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true - } - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, - "lighthouse-logger": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", - "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", - "requires": { - "debug": "^2.6.9", - "marky": "^1.2.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "lighthouse-stack-packs": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/lighthouse-stack-packs/-/lighthouse-stack-packs-1.11.0.tgz", - "integrity": "sha512-sRr0z1S/I26VffRLq9KJsKtLk856YrJlNGmcJmbLX8dFn3MuzVPUbstuChEhqnSxZb8TZmVfthuXuwhG9vRoSw==", - "dev": true - }, - "lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true - }, - "line-height": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/line-height/-/line-height-0.3.1.tgz", - "integrity": "sha512-YExecgqPwnp5gplD2+Y8e8A5+jKpr25+DzMbFdI1/1UAr0FJrTFv4VkHLf8/6B590i1wUPJWMKKldkd/bdQ//w==", - "requires": { - "computed-style": "~0.1.3" - } - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "lint-staged": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.0.2.tgz", - "integrity": "sha512-ZldhtIfT7bynVa7nmU/1jbK05r9hYQXbIQqZSotqdBCAcGJDEUqaUB7kG3ZCdoe9Qkj6HUM3x2yjCGJRxPUQLA==", - "dev": true, - "requires": { - "chalk": "^3.0.0", - "commander": "^4.0.1", - "cosmiconfig": "^6.0.0", - "debug": "^4.1.1", - "dedent": "^0.7.0", - "execa": "^3.4.0", - "listr": "^0.14.3", - "log-symbols": "^3.0.0", - "micromatch": "^4.0.2", - "normalize-path": "^3.0.0", - "please-upgrade-node": "^3.2.0", - "string-argv": "0.3.1", - "stringify-object": "^3.3.0" - }, - "dependencies": { - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - }, - "cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz", - "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "p-finally": "^2.0.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "p-finally": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", - "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", - "dev": true - }, - "listr": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", - "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", - "dev": true, - "requires": { - "@samverschueren/stream-to-observable": "^0.3.0", - "is-observable": "^1.1.0", - "is-promise": "^2.1.0", - "is-stream": "^1.1.0", - "listr-silent-renderer": "^1.1.1", - "listr-update-renderer": "^0.5.0", - "listr-verbose-renderer": "^0.5.0", - "p-map": "^2.0.0", - "rxjs": "^6.3.3" - }, - "dependencies": { - "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - } - } - }, - "listr-silent-renderer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", - "integrity": "sha512-L26cIFm7/oZeSNVhWB6faeorXhMg4HNlb/dS/7jHhr708jxlXrtrBWo4YUxZQkc6dGoxEAe6J/D3juTRBUzjtA==", - "dev": true - }, - "listr-update-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", - "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "cli-truncate": "^0.2.1", - "elegant-spinner": "^1.0.1", - "figures": "^1.7.0", - "indent-string": "^3.0.0", - "log-symbols": "^1.0.2", - "log-update": "^2.3.0", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha512-mmPrW0Fh2fxOzdBbFv4g1m6pR72haFLPJ2G5SJEELf1y+iaQrDG6cWCPjy54RHYbZAt7X+ls690Kw62AdWXBzQ==", - "dev": true, - "requires": { - "chalk": "^1.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true - } - } - }, - "listr-verbose-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", - "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "cli-cursor": "^2.1.0", - "date-fns": "^1.27.2", - "figures": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "date-fns": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", - "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", - "dev": true - } - } - }, - "load-json-file": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-6.2.0.tgz", - "integrity": "sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "parse-json": "^5.0.0", - "strip-bom": "^4.0.0", - "type-fest": "^0.6.0" - } - }, - "loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", - "dev": true - }, - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "locate-app": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/locate-app/-/locate-app-2.1.0.tgz", - "integrity": "sha512-rcVo/iLUxrd9d0lrmregK/Z5Y5NCpSwf9KlMbPpOHmKmdxdQY1Fj8NDQ5QymJTryCsBLqwmniFv2f3JKbk9Bvg==", - "dev": true, - "requires": { - "n12": "0.4.0", - "type-fest": "2.13.0", - "userhome": "1.0.0" - }, - "dependencies": { - "type-fest": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.13.0.tgz", - "integrity": "sha512-lPfAm42MxE4/456+QyIaaVBAwgpJb6xZ8PRu09utnhPdWwcyj9vgy6Sq0Z5yNbJ21EdxB5dRU/Qg8bsyAMtlcw==", - "dev": true - } - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "lockfile": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz", - "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", - "dev": true, - "requires": { - "signal-exit": "^3.0.2" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "dev": true - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" - }, - "lodash.escape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==", - "dev": true - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true - }, - "lodash.invokemap": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.invokemap/-/lodash.invokemap-4.6.0.tgz", - "integrity": "sha512-CfkycNtMqgUlfjfdh2BhKO/ZXrP8ePOX5lEU/g0R3ItJcnuxWDwokMGKx1hWcfOikmyOVx6X9IwWnDGlgKl61w==", - "dev": true - }, - "lodash.ismatch": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", - "dev": true - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.pullall": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.pullall/-/lodash.pullall-4.2.0.tgz", - "integrity": "sha512-VhqxBKH0ZxPpLhiu68YD1KnHmbhQJQctcipvmFnqIBDYzcIHzf3Zpu0tpeOKtR4x76p9yohc506eGdOjTmyIBg==", - "dev": true - }, - "lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==", - "dev": true - }, - "lodash.throttle": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==" - }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "lodash.uniqby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", - "dev": true - }, - "lodash.zip": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", - "integrity": "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - } - } - } - }, - "logform": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.5.1.tgz", - "integrity": "sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==", - "dev": true, - "requires": { - "@colors/colors": "1.5.0", - "@types/triple-beam": "^1.3.2", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^2.3.1", - "triple-beam": "^1.3.0" - }, - "dependencies": { - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, - "logkitty": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/logkitty/-/logkitty-0.7.1.tgz", - "integrity": "sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==", - "requires": { - "ansi-fragments": "^0.2.1", - "dayjs": "^1.8.15", - "yargs": "^15.1.0" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "loglevel": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz", - "integrity": "sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==", - "dev": true - }, - "loglevel-plugin-prefix": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz", - "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==", - "dev": true - }, - "longest-streak": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", - "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", - "dev": true - }, - "lookup-closest-locale": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/lookup-closest-locale/-/lookup-closest-locale-6.2.0.tgz", - "integrity": "sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==", - "dev": true - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "requires": { - "tslib": "^2.0.3" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - }, - "lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true - }, - "lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "dev": true - }, - "macos-release": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.2.0.tgz", - "integrity": "sha512-iV2IDxZaX8dIcM7fG6cI46uNmHUxHE4yN+Z8tKHAW1TBPMZDIKHf/3L+YnOuj/FK9il14UaVdHmiQ1tsi90ltA==", - "dev": true - }, - "magic-string": { - "version": "0.30.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz", - "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==", - "dev": true, - "requires": { - "@jridgewell/sourcemap-codec": "^1.4.15" - } - }, - "make-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", - "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "cacache": { - "version": "17.1.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", - "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", - "dev": true, - "requires": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^7.7.1", - "minipass": "^7.0.3", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - } - } - }, - "fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "dev": true, - "requires": { - "minipass": "^7.0.3" - }, - "dependencies": { - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - } - } - }, - "glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "dependencies": { - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - } - } - }, - "jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - }, - "ssri": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", - "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", - "dev": true, - "requires": { - "minipass": "^7.0.3" - }, - "dependencies": { - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - } - } - }, - "unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "dev": true, - "requires": { - "unique-slug": "^4.0.0" - } - }, - "unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - } - } - }, - "makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "requires": { - "tmpl": "1.0.5" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", - "dev": true - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true - }, - "map-or-similar": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", - "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", - "dev": true - }, - "map-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-values/-/map-values-1.0.1.tgz", - "integrity": "sha512-BbShUnr5OartXJe1GeccAWtfro11hhgNJg6G9/UtWKjVGvV5U4C09cg5nk8JUevhXODaXY+hQ3xxMUKSs62ONQ==", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "markdown-builder": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/markdown-builder/-/markdown-builder-0.9.0.tgz", - "integrity": "sha512-UovCyEEzMeKE7l88fbOk9SIJkOG7KXkg+TdudN8rvOtCtBO5uu1X27HSnM7LS/xH+vaShJLGpkBcYYcojWNx/g==", - "dev": true, - "requires": { - "husky": "^1.0.0-rc.14" - }, - "dependencies": { - "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "dev": true, - "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "husky": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-1.3.1.tgz", - "integrity": "sha512-86U6sVVVf4b5NYSZ0yvv88dRgBSSXXmHaiq5pP4KDj5JVzdwKgBjEtUPOm8hcoytezFwbU+7gotXNhpHdystlg==", - "dev": true, - "requires": { - "cosmiconfig": "^5.0.7", - "execa": "^1.0.0", - "find-up": "^3.0.0", - "get-stdin": "^6.0.0", - "is-ci": "^2.0.0", - "pkg-dir": "^3.0.0", - "please-upgrade-node": "^3.1.1", - "read-pkg": "^4.0.1", - "run-node": "^1.0.0", - "slash": "^2.0.0" - } - }, - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", - "dev": true, - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "read-pkg": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", - "integrity": "sha512-+UBirHHDm5J+3WDmLBZYSklRYg82nMlz+enn+GMZ22nSR2f4bzxmhso6rzQW/3mT2PVzpzDTiYIZahk8UmZ44w==", - "dev": true, - "requires": { - "normalize-package-data": "^2.3.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0" - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - } - } - }, - "markdown-escapes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz", - "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", - "dev": true - }, - "markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", - "dev": true, - "requires": { - "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "dev": true - } - } - }, - "markdown-table": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", - "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", - "dev": true - }, - "markdown-to-jsx": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.4.1.tgz", - "integrity": "sha512-GbrbkTnHp9u6+HqbPRFJbObi369AgJNXi/sGqq5HRsoZW063xR1XDCaConqq+whfEIAlzB1YPnOgsPc7B7bc/A==", - "dev": true - }, - "markdownlint": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.25.1.tgz", - "integrity": "sha512-AG7UkLzNa1fxiOv5B+owPsPhtM4D6DoODhsJgiaNg1xowXovrYgOnLqAgOOFQpWOlHFVQUzjMY5ypNNTeov92g==", - "dev": true, - "requires": { - "markdown-it": "12.3.2" - } - }, - "markdownlint-cli": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.31.1.tgz", - "integrity": "sha512-keIOMwQn+Ch7MoBwA+TdkyVMuxAeZFEGmIIlvwgV0Z1TGS5MxPnRr29XCLhkNzCHU+uNKGjU+VEjLX+Z9kli6g==", - "dev": true, - "requires": { - "commander": "~9.0.0", - "get-stdin": "~9.0.0", - "glob": "~7.2.0", - "ignore": "~5.2.0", - "js-yaml": "^4.1.0", - "jsonc-parser": "~3.0.0", - "markdownlint": "~0.25.1", - "markdownlint-rule-helpers": "~0.16.0", - "minimatch": "~3.0.5", - "run-con": "~1.2.10" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "commander": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.0.0.tgz", - "integrity": "sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "dependencies": { - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "markdownlint-rule-helpers": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.16.0.tgz", - "integrity": "sha512-oEacRUVeTJ5D5hW1UYd2qExYI0oELdYK72k1TKGvIeYJIbqQWAz476NAc7LNixSySUhcNl++d02DvX0ccDk9/w==", - "dev": true - }, - "marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "dev": true - }, - "marky": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", - "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==" - }, - "mathjs": { - "version": "10.6.4", - "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-10.6.4.tgz", - "integrity": "sha512-omQyvRE1jIy+3k2qsqkWASOcd45aZguXZDckr3HtnTYyXk5+2xpVfC3kATgbO2Srjxlqww3TVdhD0oUdZ/hiFA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.18.6", - "complex.js": "^2.1.1", - "decimal.js": "^10.3.1", - "escape-latex": "^1.2.0", - "fraction.js": "^4.2.0", - "javascript-natural-sort": "^0.7.1", - "seedrandom": "^3.0.5", - "tiny-emitter": "^2.1.0", - "typed-function": "^2.1.0" - } - }, - "mathml-tag-names": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", - "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", - "dev": true - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "mdast-util-compact": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", - "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", - "dev": true, - "requires": { - "unist-util-modify-children": "^1.0.0", - "unist-util-visit": "^1.1.0" - } - }, - "mdast-util-definitions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", - "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", - "dev": true, - "requires": { - "unist-util-visit": "^2.0.0" - }, - "dependencies": { - "unist-util-is": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", - "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", - "dev": true - }, - "unist-util-visit": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", - "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit-parents": "^3.0.0" - } - }, - "unist-util-visit-parents": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", - "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0" - } - } - } - }, - "mdast-util-inject": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", - "integrity": "sha512-CcJ0mHa36QYumDKiZ2OIR+ClhfOM7zIzN+Wfy8tRZ1hpH9DKLCS+Mh4DyK5bCxzE9uxMWcbIpeNFWsg1zrj/2g==", - "dev": true, - "requires": { - "mdast-util-to-string": "^1.0.0" - } - }, - "mdast-util-to-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.5.tgz", - "integrity": "sha512-2qLt/DEOo5F6nc2VFScQiHPzQ0XXcabquRJxKMhKte8nt42o08HUxNDPk7tt0YPxnWjAT11I1SYi0X0iPnfI5A==", - "dev": true - }, - "mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true - }, - "memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dev": true, - "requires": { - "fs-monkey": "^1.0.4" - } - }, - "memize": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/memize/-/memize-2.1.0.tgz", - "integrity": "sha512-yywVJy8ctVlN5lNPxsep5urnZ6TTclwPEyigM9M3Bi8vseJBOfqNrGWN/r8NzuIt3PovM323W04blJfGQfQSVg==" - }, - "memoize-one": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", - "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" - }, - "memoizerific": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", - "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", - "dev": true, - "requires": { - "map-or-similar": "^1.5.0" - } - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", - "dev": true - }, - "meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", - "dev": true, - "requires": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "dependencies": { - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - } - }, - "type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true - } - } - }, - "merge-deep": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz", - "integrity": "sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "clone-deep": "^0.2.4", - "kind-of": "^3.0.2" - }, - "dependencies": { - "clone-deep": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", - "integrity": "sha512-we+NuQo2DHhSl+DP6jlUiAhyAjBQrYnpOk15rN6c6JSPScjiCLh8IbSU+VTcph6YS3o7mASE8a0+gbZ7ChLpgg==", - "dev": true, - "requires": { - "for-own": "^0.1.3", - "is-plain-object": "^2.0.1", - "kind-of": "^3.0.2", - "lazy-cache": "^1.0.3", - "shallow-clone": "^0.1.2" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "shallow-clone": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", - "integrity": "sha512-J1zdXCky5GmNnuauESROVu31MQSnLoYvlyEn6j2Ztk6Q5EHFIhxkMhYcv6vuDzl2XEzoRr856QwzMgWM/TmZgw==", - "dev": true, - "requires": { - "is-extendable": "^0.1.1", - "kind-of": "^2.0.1", - "lazy-cache": "^0.2.3", - "mixin-object": "^2.0.1" - }, - "dependencies": { - "kind-of": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", - "integrity": "sha512-0u8i1NZ/mg0b+W3MGGw5I7+6Eib2nx72S/QvXa0hYjEkjTknYmEYQJwGu3mLC0BrhtJjtQafTkyRUQ75Kx0LVg==", - "dev": true, - "requires": { - "is-buffer": "^1.0.2" - } - }, - "lazy-cache": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", - "integrity": "sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ==", - "dev": true - } - } - } - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "metaviewport-parser": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/metaviewport-parser/-/metaviewport-parser-0.3.0.tgz", - "integrity": "sha512-EoYJ8xfjQ6kpe9VbVHvZTZHiOl4HL1Z18CrZ+qahvLXT7ZO4YTC2JMyt5FaUp9JJp6J4Ybb/z7IsCXZt86/QkQ==", - "dev": true - }, - "method-override": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", - "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==", - "dev": true, - "requires": { - "debug": "3.1.0", - "methods": "~1.1.2", - "parseurl": "~1.3.2", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true - }, - "metro": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/metro/-/metro-0.80.5.tgz", - "integrity": "sha512-OE/CGbOgbi8BlTN1QqJgKOBaC27dS0JBQw473JcivrpgVnqIsluROA7AavEaTVUrB9wPUZvoNVDROn5uiM2jfw==", - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/core": "^7.20.0", - "@babel/generator": "^7.20.0", - "@babel/parser": "^7.20.0", - "@babel/template": "^7.0.0", - "@babel/traverse": "^7.20.0", - "@babel/types": "^7.20.0", - "accepts": "^1.3.7", - "chalk": "^4.0.0", - "ci-info": "^2.0.0", - "connect": "^3.6.5", - "debug": "^2.2.0", - "denodeify": "^1.2.1", - "error-stack-parser": "^2.0.6", - "graceful-fs": "^4.2.4", - "hermes-parser": "0.18.2", - "image-size": "^1.0.2", - "invariant": "^2.2.4", - "jest-worker": "^29.6.3", - "jsc-safe-url": "^0.2.2", - "lodash.throttle": "^4.1.1", - "metro-babel-transformer": "0.80.5", - "metro-cache": "0.80.5", - "metro-cache-key": "0.80.5", - "metro-config": "0.80.5", - "metro-core": "0.80.5", - "metro-file-map": "0.80.5", - "metro-resolver": "0.80.5", - "metro-runtime": "0.80.5", - "metro-source-map": "0.80.5", - "metro-symbolicate": "0.80.5", - "metro-transform-plugins": "0.80.5", - "metro-transform-worker": "0.80.5", - "mime-types": "^2.1.27", - "node-fetch": "^2.2.0", - "nullthrows": "^1.1.1", - "rimraf": "^3.0.2", - "serialize-error": "^2.1.0", - "source-map": "^0.5.6", - "strip-ansi": "^6.0.0", - "throat": "^5.0.0", - "ws": "^7.5.1", - "yargs": "^17.6.2" - }, - "dependencies": { - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "hermes-estree": { - "version": "0.18.2", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.18.2.tgz", - "integrity": "sha512-KoLsoWXJ5o81nit1wSyEZnWUGy9cBna9iYMZBR7skKh7okYAYKqQ9/OczwpMHn/cH0hKDyblulGsJ7FknlfVxQ==" - }, - "hermes-parser": { - "version": "0.18.2", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.18.2.tgz", - "integrity": "sha512-1eQfvib+VPpgBZ2zYKQhpuOjw1tH+Emuib6QmjkJWJMhyjM8xnXMvA+76o9LhF0zOAJDZgPfQhg43cyXEyl5Ew==", - "requires": { - "hermes-estree": "0.18.2" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" - } - } - }, - "metro-babel-transformer": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.80.5.tgz", - "integrity": "sha512-sxH6hcWCorhTbk4kaShCWsadzu99WBL4Nvq4m/sDTbp32//iGuxtAnUK+ZV+6IEygr2u9Z0/4XoZ8Sbcl71MpA==", - "requires": { - "@babel/core": "^7.20.0", - "hermes-parser": "0.18.2", - "nullthrows": "^1.1.1" - }, - "dependencies": { - "hermes-estree": { - "version": "0.18.2", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.18.2.tgz", - "integrity": "sha512-KoLsoWXJ5o81nit1wSyEZnWUGy9cBna9iYMZBR7skKh7okYAYKqQ9/OczwpMHn/cH0hKDyblulGsJ7FknlfVxQ==" - }, - "hermes-parser": { - "version": "0.18.2", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.18.2.tgz", - "integrity": "sha512-1eQfvib+VPpgBZ2zYKQhpuOjw1tH+Emuib6QmjkJWJMhyjM8xnXMvA+76o9LhF0zOAJDZgPfQhg43cyXEyl5Ew==", - "requires": { - "hermes-estree": "0.18.2" - } - } - } - }, - "metro-cache": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.80.5.tgz", - "integrity": "sha512-2u+dQ4PZwmC7eZo9uMBNhQQMig9f+w4QWBZwXCdVy/RYOHM0eObgGdMEOwODo73uxie82T9lWzxr3aZOZ+Nqtw==", - "requires": { - "metro-core": "0.80.5", - "rimraf": "^3.0.2" - } - }, - "metro-cache-key": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.80.5.tgz", - "integrity": "sha512-fr3QLZUarsB3tRbVcmr34kCBsTHk0Sh9JXGvBY/w3b2lbre+Lq5gtgLyFElHPecGF7o4z1eK9r3ubxtScHWcbA==" - }, - "metro-config": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.80.5.tgz", - "integrity": "sha512-elqo/lwvF+VjZ1OPyvmW/9hSiGlmcqu+rQvDKw5F5WMX48ZC+ySTD1WcaD7e97pkgAlJHVYqZ98FCjRAYOAFRQ==", - "requires": { - "connect": "^3.6.5", - "cosmiconfig": "^5.0.5", - "jest-validate": "^29.6.3", - "metro": "0.80.5", - "metro-cache": "0.80.5", - "metro-core": "0.80.5", - "metro-runtime": "0.80.5" - }, - "dependencies": { - "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - } - }, - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - } - } - }, - "metro-core": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.80.5.tgz", - "integrity": "sha512-vkLuaBhnZxTVpaZO8ZJVEHzjaqSXpOdpAiztSZ+NDaYM6jEFgle3/XIbLW91jTSf2+T8Pj5yB1G7KuOX+BcVwg==", - "requires": { - "lodash.throttle": "^4.1.1", - "metro-resolver": "0.80.5" - } - }, - "metro-file-map": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.80.5.tgz", - "integrity": "sha512-bKCvJ05drjq6QhQxnDUt3I8x7bTcHo3IIKVobEr14BK++nmxFGn/BmFLRzVBlghM6an3gqwpNEYxS5qNc+VKcg==", - "requires": { - "anymatch": "^3.0.3", - "debug": "^2.2.0", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.4", - "invariant": "^2.2.4", - "jest-worker": "^29.6.3", - "micromatch": "^4.0.4", - "node-abort-controller": "^3.1.1", - "nullthrows": "^1.1.1", - "walker": "^1.0.7" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "metro-minify-terser": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.80.5.tgz", - "integrity": "sha512-S7oZLLcab6YXUT6jYFX/ZDMN7Fq6xBGGAG8liMFU1UljX6cTcEC2u+UIafYgCLrdVexp/+ClxrIetVPZ5LtL/g==", - "requires": { - "terser": "^5.15.0" - } - }, - "metro-resolver": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.80.5.tgz", - "integrity": "sha512-haJ/Hveio3zv/Fr4eXVdKzjUeHHDogYok7OpRqPSXGhTXisNXB+sLN7CpcUrCddFRUDLnVaqQOYwhYsFndgUwA==" - }, - "metro-runtime": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.80.5.tgz", - "integrity": "sha512-L0syTWJUdWzfUmKgkScr6fSBVTh6QDr8eKEkRtn40OBd8LPagrJGySBboWSgbyn9eIb4ayW3Y347HxgXBSAjmg==", - "requires": { - "@babel/runtime": "^7.0.0" - } - }, - "metro-source-map": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.80.5.tgz", - "integrity": "sha512-DwSF4l03mKPNqCtyQ6K23I43qzU1BViAXnuH81eYWdHglP+sDlPpY+/7rUahXEo6qXEHXfAJgVoo1sirbXbmsQ==", - "requires": { - "@babel/traverse": "^7.20.0", - "@babel/types": "^7.20.0", - "invariant": "^2.2.4", - "metro-symbolicate": "0.80.5", - "nullthrows": "^1.1.1", - "ob1": "0.80.5", - "source-map": "^0.5.6", - "vlq": "^1.0.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" - } - } - }, - "metro-symbolicate": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.80.5.tgz", - "integrity": "sha512-IsM4mTYvmo9JvIqwEkCZ5+YeDVPST78Q17ZgljfLdHLSpIivOHp9oVoiwQ/YGbLx0xRHRIS/tKiXueWBnj3UWA==", - "requires": { - "invariant": "^2.2.4", - "metro-source-map": "0.80.5", - "nullthrows": "^1.1.1", - "source-map": "^0.5.6", - "through2": "^2.0.1", - "vlq": "^1.0.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" - } - } - }, - "metro-transform-plugins": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.80.5.tgz", - "integrity": "sha512-7IdlTqK/k5+qE3RvIU5QdCJUPk4tHWEqgVuYZu8exeW+s6qOJ66hGIJjXY/P7ccucqF+D4nsbAAW5unkoUdS6g==", - "requires": { - "@babel/core": "^7.20.0", - "@babel/generator": "^7.20.0", - "@babel/template": "^7.0.0", - "@babel/traverse": "^7.20.0", - "nullthrows": "^1.1.1" - } - }, - "metro-transform-worker": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.80.5.tgz", - "integrity": "sha512-Q1oM7hfP+RBgAtzRFBDjPhArELUJF8iRCZ8OidqCpYzQJVGuJZ7InSnIf3hn1JyqiUQwv2f1LXBO78i2rAjzyA==", - "requires": { - "@babel/core": "^7.20.0", - "@babel/generator": "^7.20.0", - "@babel/parser": "^7.20.0", - "@babel/types": "^7.20.0", - "metro": "0.80.5", - "metro-babel-transformer": "0.80.5", - "metro-cache": "0.80.5", - "metro-cache-key": "0.80.5", - "metro-minify-terser": "0.80.5", - "metro-source-map": "0.80.5", - "metro-transform-plugins": "0.80.5", - "nullthrows": "^1.1.1" - } - }, - "micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "requires": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - } - } - }, - "mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true - }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, - "mini-css-extract-plugin": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.1.tgz", - "integrity": "sha512-CRC6E2yedNjfOA3nQjpqAkpnranxhxmilhBPYtldnXcPT/QZb3aJFzvt0pp8W1jhuLR/E0zDa+QEHuC/HhhaLQ==", - "dev": true, - "requires": { - "schema-utils": "^4.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - } - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" - }, - "minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "dependencies": { - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true - } - } - }, - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - }, - "dependencies": { - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-fetch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.3.tgz", - "integrity": "sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ==", - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^5.0.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "dependencies": { - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - } - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-json-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", - "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", - "dev": true, - "requires": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "mitt": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", - "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==", - "dev": true - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "mixin-object": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", - "integrity": "sha512-ALGF1Jt9ouehcaXaHhn6t1yGWRqGaHkPFndtFVHfZXOvkIZ/yoGaSi0AHVTafb3ZBGg4dr/bDwnaEKqCXzchMA==", - "dev": true, - "requires": { - "for-in": "^0.1.3", - "is-extendable": "^0.1.1" - }, - "dependencies": { - "for-in": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", - "integrity": "sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g==", - "dev": true - } - } - }, - "mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "dev": true - }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true - }, - "mock-match-media": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/mock-match-media/-/mock-match-media-0.4.2.tgz", - "integrity": "sha512-1Q/Z7cfqWVTZd5Iz0bLxqzl6/8vaPl4KxxciRSRu+TCeGxRlxGDgjwWre0KkHlfS01r1iGCUWuF0n3ftvS/C/A==", - "dev": true, - "requires": { - "css-mediaquery": "^0.1.2" - } - }, - "modify-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", - "dev": true - }, - "moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" - }, - "moment-timezone": { - "version": "0.5.43", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz", - "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==", - "requires": { - "moment": "^2.29.4" - } - }, - "moment-timezone-data-webpack-plugin": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/moment-timezone-data-webpack-plugin/-/moment-timezone-data-webpack-plugin-1.5.1.tgz", - "integrity": "sha512-1le6a35GgYdWMVYFzrfpE/F6Pk4bj0M3QKD6Iv6ba9LqWGoVqHQRHyCTLvLis5E1J98Sz40ET6yhZzMVakwpjg==", - "dev": true, - "requires": { - "find-cache-dir": "^3.0.0", - "make-dir": "^3.0.0" - }, - "dependencies": { - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "morgan": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", - "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", - "dev": true, - "requires": { - "basic-auth": "~2.0.1", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-finished": "~2.3.0", - "on-headers": "~1.0.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - } - } - }, - "mousetrap": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz", - "integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==" - }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "mrmime": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", - "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "requires": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - } - }, - "multimatch": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", - "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", - "dev": true, - "requires": { - "@types/minimatch": "^3.0.3", - "array-differ": "^3.0.0", - "array-union": "^2.1.0", - "arrify": "^2.0.1", - "minimatch": "^3.0.4" - }, - "dependencies": { - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true - } - } - }, - "mustache": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.0.0.tgz", - "integrity": "sha512-FJgjyX/IVkbXBXYUwH+OYwQKqWpFPLaLVESd70yHjSDunwzV2hZOoTBvPf4KLoxesUzzyfTH6F784Uqd7Wm5yA==", - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "mv": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", - "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", - "dev": true, - "requires": { - "mkdirp": "~0.5.1", - "ncp": "~2.0.0", - "rimraf": "~2.4.0" - }, - "dependencies": { - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "rimraf": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", - "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", - "dev": true, - "requires": { - "glob": "^6.0.1" - } - } - } - }, - "n12": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/n12/-/n12-0.4.0.tgz", - "integrity": "sha512-p/hj4zQ8d3pbbFLQuN1K9honUxiDDhueOWyFLw/XgBv+wZCE44bcLH4CIcsolOceJQduh4Jf7m/LfaTxyGmGtQ==", - "dev": true - }, - "nan": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", - "dev": true, - "optional": true - }, - "nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "dev": true, - "optional": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "ncp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", - "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "requires": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "nocache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/nocache/-/nocache-3.0.4.tgz", - "integrity": "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==" - }, - "nock": { - "version": "12.0.3", - "resolved": "https://registry.npmjs.org/nock/-/nock-12.0.3.tgz", - "integrity": "sha512-QNb/j8kbFnKCiyqi9C5DD0jH/FubFGj5rt9NQFONXwQm3IPB0CULECg/eS3AU1KgZb/6SwUa4/DTRKhVxkGABw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.13", - "propagate": "^2.0.0" - } - }, - "node-abi": { - "version": "3.47.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.47.0.tgz", - "integrity": "sha512-2s6B2CWZM//kPgwnuI0KrYwNjfdByE25zvAaEpq9IH4zcNsarH8Ihu/UuX6XMPEogDAxkuUFeZn60pXNHAqn3A==", - "dev": true, - "optional": true, - "requires": { - "semver": "^7.3.5" - } - }, - "node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" - }, - "node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true - }, - "node-dir": { - "version": "0.1.17", - "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", - "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", - "requires": { - "minimatch": "^3.0.2" - } - }, - "node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "dev": true - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-fetch-native": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.2.tgz", - "integrity": "sha512-69mtXOFZ6hSkYiXAVB5SqaRvrbITC/NPyqv7yuu/qw0nmgPyYbIMYYNIDhNtwPrzk0ptrimrLz/hhjvm4w5Z+w==", - "dev": true - }, - "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true - }, - "node-gyp": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz", - "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==", - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^11.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "node-gyp-build": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", - "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", - "dev": true - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" - }, - "node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - } - } - }, - "node-machine-id": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", - "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==", - "dev": true - }, - "node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" - }, - "node-stream-zip": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz", - "integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==" - }, - "node-watch": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.0.tgz", - "integrity": "sha512-OOBiglke5SlRQT5WYfwXTmYqTfXjcTNBHpalyHLtLxDpQYVpVRkJqabcch1kmwJsjV/J4OZuzEafeb4soqtFZA==", - "dev": true - }, - "nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "requires": { - "abbrev": "^1.0.0" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true - }, - "normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true - }, - "normalize-wheel": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz", - "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==" - }, - "npm-bundled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", - "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", - "dev": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-install-checks": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.1.1.tgz", - "integrity": "sha512-dH3GmQL4vsPtld59cOn8uY0iOqRmqKvV+DLGwNXV/Q7MDgD2QfOADWd/mFXcIE5LVhYYGjA3baz6W9JneqnuCw==", - "dev": true, - "requires": { - "semver": "^7.1.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", - "dev": true - }, - "npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" - } - }, - "npm-package-json-lint": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/npm-package-json-lint/-/npm-package-json-lint-6.4.0.tgz", - "integrity": "sha512-cuXAJJB1Rdqz0UO6w524matlBqDBjcNt7Ru+RDIu4y6RI1gVqiWBnylrK8sPRk81gGBA0X8hJbDXolVOoTc+sA==", - "dev": true, - "requires": { - "ajv": "^6.12.6", - "ajv-errors": "^1.0.1", - "chalk": "^4.1.2", - "cosmiconfig": "^8.0.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "ignore": "^5.2.0", - "is-plain-obj": "^3.0.0", - "jsonc-parser": "^3.2.0", - "log-symbols": "^4.1.0", - "meow": "^9.0.0", - "plur": "^4.0.0", - "semver": "^7.3.8", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1", - "type-fest": "^3.2.0", - "validate-npm-package-name": "^5.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "requires": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true - }, - "meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "dev": true, - "requires": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "dependencies": { - "type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true - } - } - }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - } - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true - }, - "validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", - "dev": true - } - } - }, - "npm-packlist": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-3.0.0.tgz", - "integrity": "sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ==", - "dev": true, - "requires": { - "glob": "^7.1.6", - "ignore-walk": "^4.0.1", - "npm-bundled": "^1.1.1", - "npm-normalize-package-bin": "^1.0.1" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "npm-pick-manifest": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.2.tgz", - "integrity": "sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==", - "dev": true, - "requires": { - "npm-install-checks": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^10.0.0", - "semver": "^7.3.5" - }, - "dependencies": { - "hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", - "dev": true - }, - "npm-package-arg": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", - "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", - "dev": true, - "requires": { - "hosted-git-info": "^6.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - } - }, - "validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", - "dev": true - } - } - }, - "npm-registry-fetch": { - "version": "14.0.5", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz", - "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==", - "dev": true, - "requires": { - "make-fetch-happen": "^11.0.0", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^10.0.0", - "proc-log": "^3.0.0" - }, - "dependencies": { - "hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - }, - "npm-package-arg": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", - "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", - "dev": true, - "requires": { - "hosted-git-info": "^6.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - } - }, - "validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", - "dev": true - } - } - }, - "npm-run-all": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", - "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "memorystream": "^0.3.1", - "minimatch": "^3.0.4", - "pidtree": "^0.3.0", - "read-pkg": "^3.0.0", - "shell-quote": "^1.6.1", - "string.prototype.padend": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - } - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, - "requires": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - } - }, - "nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "requires": { - "boolbase": "^1.0.0" - } - }, - "nullthrows": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", - "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==" - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", - "dev": true - }, - "nwsapi": { - "version": "2.2.13", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", - "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", - "dev": true - }, - "nx": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/nx/-/nx-16.6.0.tgz", - "integrity": "sha512-4UaS9nRakpZs45VOossA7hzSQY2dsr035EoPRGOc81yoMFW6Sqn1Rgq4hiLbHZOY8MnWNsLMkgolNMz1jC8YUQ==", - "dev": true, - "requires": { - "@nrwl/tao": "16.6.0", - "@nx/nx-darwin-arm64": "16.6.0", - "@nx/nx-darwin-x64": "16.6.0", - "@nx/nx-freebsd-x64": "16.6.0", - "@nx/nx-linux-arm-gnueabihf": "16.6.0", - "@nx/nx-linux-arm64-gnu": "16.6.0", - "@nx/nx-linux-arm64-musl": "16.6.0", - "@nx/nx-linux-x64-gnu": "16.6.0", - "@nx/nx-linux-x64-musl": "16.6.0", - "@nx/nx-win32-arm64-msvc": "16.6.0", - "@nx/nx-win32-x64-msvc": "16.6.0", - "@parcel/watcher": "2.0.4", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.6", - "axios": "^1.0.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^7.0.2", - "dotenv": "~10.0.0", - "enquirer": "~2.3.6", - "fast-glob": "3.2.7", - "figures": "3.2.0", - "flat": "^5.0.2", - "fs-extra": "^11.1.0", - "glob": "7.1.4", - "ignore": "^5.0.4", - "js-yaml": "4.1.0", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "3.0.5", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "semver": "7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "v8-compile-cache": "2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "lines-and-columns": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", - "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - }, - "tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "dev": true - }, - "tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", - "dev": true, - "requires": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "dependencies": { - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - } - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, - "nypm": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.6.tgz", - "integrity": "sha512-2CATJh3pd6CyNfU5VZM7qSwFu0ieyabkEdnogE30Obn1czrmOYiZ8DOZLe1yBdLKWoyD3Mcy2maUs+0MR3yVjQ==", - "dev": true, - "requires": { - "citty": "^0.1.5", - "execa": "^8.0.1", - "pathe": "^1.1.2", - "ufo": "^1.3.2" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - } - }, - "get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true - }, - "human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true - }, - "is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true - }, - "mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true - }, - "npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "requires": { - "path-key": "^4.0.0" - }, - "dependencies": { - "path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true - } - } - }, - "onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "requires": { - "mimic-fn": "^4.0.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - }, - "strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "ob1": { - "version": "0.80.5", - "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.80.5.tgz", - "integrity": "sha512-zYDMnnNrFi/1Tqh0vo3PE4p97Tpl9/4MP2k2ECvkbLOZzQuAYZJLTUYVLZb7hJhbhjT+JJxAwBGS8iu5hCSd1w==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-filter": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object-filter/-/object-filter-1.0.2.tgz", - "integrity": "sha512-NahvP2vZcy1ZiiYah30CEPw0FpDcSkSePJBMpzl5EQgCmISijiGuJm3SPYp7U+Lf2TljyaIw3E5EgkEx/TNEVA==", - "dev": true - }, - "object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true - }, - "object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "object.hasown": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.0.tgz", - "integrity": "sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "objectorarray": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz", - "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==", - "dev": true - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "octokit-pagination-methods": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz", - "integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==", - "dev": true - }, - "ohash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", - "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==", - "dev": true - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "one-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", - "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "dev": true, - "requires": { - "fn.name": "1.x.x" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "open": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", - "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", - "requires": { - "is-wsl": "^1.1.0" - } - }, - "opencv-bindings": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/opencv-bindings/-/opencv-bindings-4.5.5.tgz", - "integrity": "sha512-FdYE9uqnoPKbAkZFEOpIh6RTtJIz1lz+W27xPCo1Ov6+d0OOgg+Hm9OT2MIGIG8V1Dp3fWlLvi7SIjDOpqO2XA==", - "dev": true - }, - "opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha512-oCOQ8AIC2ciLy/sE2ehafRBleBgDLvzGhBRRev87sP7ovnbvQfqpc3XFI0DhHey2OfVoNV91W+GPC6B3540/5Q==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } - }, - "ora": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-4.1.1.tgz", - "integrity": "sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A==", - "dev": true, - "requires": { - "chalk": "^3.0.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.2.0", - "is-interactive": "^1.0.0", - "log-symbols": "^3.0.0", - "mute-stream": "0.0.8", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "dependencies": { - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", - "dev": true - }, - "os-name": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", - "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", - "dev": true, - "requires": { - "macos-release": "^2.2.0", - "windows-release": "^3.1.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true - }, - "p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - }, - "dependencies": { - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - } - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-map-series": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-2.1.0.tgz", - "integrity": "sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==", - "dev": true - }, - "p-pipe": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-3.1.0.tgz", - "integrity": "sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==", - "dev": true - }, - "p-queue": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", - "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.4", - "p-timeout": "^3.2.0" - } - }, - "p-reduce": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz", - "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==", - "dev": true - }, - "p-retry": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", - "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", - "dev": true, - "requires": { - "@types/retry": "^0.12.0", - "retry": "^0.13.1" - }, - "dependencies": { - "retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true - } - } - }, - "p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "dev": true, - "requires": { - "p-finally": "^1.0.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true - }, - "p-waterfall": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-waterfall/-/p-waterfall-2.1.1.tgz", - "integrity": "sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw==", - "dev": true, - "requires": { - "p-reduce": "^2.0.0" - } - }, - "pac-proxy-agent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", - "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", - "dev": true, - "requires": { - "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", - "pac-resolver": "^7.0.0", - "socks-proxy-agent": "^8.0.2" - }, - "dependencies": { - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, - "socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, - "requires": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - } - } - } - }, - "pac-resolver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", - "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", - "dev": true, - "requires": { - "degenerator": "^5.0.0", - "ip": "^1.1.8", - "netmask": "^2.0.2" - } - }, - "package-changed": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/package-changed/-/package-changed-3.0.0.tgz", - "integrity": "sha512-HSRbrO+Ab5AuqqYGSevtKJ1Yt96jW1VKV7wrp8K4SKj5tyDp/7D96uPCQyCPiNtWTEH/7nA3hZ4z2slbc9yFxg==", - "dev": true, - "requires": { - "commander": "^6.2.0" - }, - "dependencies": { - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - } - } - }, - "package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true - }, - "pacote": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.2.0.tgz", - "integrity": "sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==", - "dev": true, - "requires": { - "@npmcli/git": "^4.0.0", - "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/promise-spawn": "^6.0.1", - "@npmcli/run-script": "^6.0.0", - "cacache": "^17.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^5.0.0", - "npm-package-arg": "^10.0.0", - "npm-packlist": "^7.0.0", - "npm-pick-manifest": "^8.0.0", - "npm-registry-fetch": "^14.0.0", - "proc-log": "^3.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^6.0.0", - "read-package-json-fast": "^3.0.0", - "sigstore": "^1.3.0", - "ssri": "^10.0.0", - "tar": "^6.1.11" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "cacache": { - "version": "17.1.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", - "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", - "dev": true, - "requires": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^7.7.1", - "minipass": "^7.0.3", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - } - } - }, - "fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "dev": true, - "requires": { - "minipass": "^7.0.3" - }, - "dependencies": { - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - } - } - }, - "glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "dependencies": { - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - } - } - }, - "hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - } - }, - "ignore-walk": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.5.tgz", - "integrity": "sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==", - "dev": true, - "requires": { - "minimatch": "^9.0.0" - } - }, - "jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - }, - "npm-package-arg": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", - "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", - "dev": true, - "requires": { - "hosted-git-info": "^6.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - } - }, - "npm-packlist": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", - "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", - "dev": true, - "requires": { - "ignore-walk": "^6.0.0" - } - }, - "ssri": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", - "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", - "dev": true, - "requires": { - "minipass": "^7.0.3" - }, - "dependencies": { - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - } - } - }, - "unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "dev": true, - "requires": { - "unique-slug": "^4.0.0" - } - }, - "unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", - "dev": true - } - } - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "parallel-transform": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", - "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", - "dev": true, - "requires": { - "cyclist": "^1.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, - "param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "parse-cache-control": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", - "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", - "dev": true - }, - "parse-entities": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", - "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", - "dev": true, - "requires": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parse-listing": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/parse-listing/-/parse-listing-1.1.3.tgz", - "integrity": "sha512-a1p1i+9Qyc8pJNwdrSvW1g5TPxRH0sywVi6OzVvYHRo6xwF9bDWBxtH0KkxeOOvhUE8vAMtiSfsYQFOuK901eA==", - "dev": true - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", - "dev": true - }, - "parse-path": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", - "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", - "dev": true, - "requires": { - "protocols": "^2.0.0" - } - }, - "parse-url": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", - "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", - "dev": true, - "requires": { - "parse-path": "^7.0.0" - } - }, - "parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "requires": { - "entities": "^4.4.0" - }, - "dependencies": { - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true - } - } - }, - "parsel-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/parsel-js/-/parsel-js-1.1.2.tgz", - "integrity": "sha512-D66DG2nKx4Yoq66TMEyCUHlR2STGqO7vsBrX7tgyS9cfQyO6XD5JyzOiflwmWN6a4wbUAqpmHqmrxlTQVGZcbA==" - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", - "dev": true - }, - "patch-package": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz", - "integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==", - "dev": true, - "requires": { - "@yarnpkg/lockfile": "^1.1.0", - "chalk": "^4.1.2", - "ci-info": "^3.7.0", - "cross-spawn": "^7.0.3", - "find-yarn-workspace-root": "^2.0.0", - "fs-extra": "^9.0.0", - "json-stable-stringify": "^1.0.2", - "klaw-sync": "^6.0.0", - "minimist": "^1.2.6", - "open": "^7.4.2", - "rimraf": "^2.6.3", - "semver": "^7.5.3", - "slash": "^2.0.0", - "tmp": "^0.0.33", - "yaml": "^2.2.2" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "dev": true, - "requires": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", - "dev": true - } - } - }, - "path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", - "dev": true - }, - "path-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", - "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", - "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", - "dev": true, - "optional": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "requires": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true - }, - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - } - } - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true - } - } - }, - "pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true - }, - "pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "peek-stream": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", - "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "duplexify": "^3.5.0", - "through2": "^2.0.3" - } - }, - "pegjs": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", - "integrity": "sha512-qI5+oFNEGi3L5HAxDwN2LA4Gg7irF70Zs25edhjld9QemOgp0CbvMtbFcMvFtEo1OityPrcCzkQFB8JP/hxgow==" - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, - "phpegjs": { - "version": "1.0.0-beta7", - "resolved": "https://registry.npmjs.org/phpegjs/-/phpegjs-1.0.0-beta7.tgz", - "integrity": "sha512-SO+NP5argMoJVCWcYiOofPUeEWDIM47FNCBJtp6uJ8PpjtBcudYJTzCbCMit5dzmfSLCoijzEwIXOqPqD45xQg==" - }, - "picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "pidtree": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", - "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==" - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha512-ojakdnUgL5pzJYWw2AIDEupaQCX5OPbM688ZevubICjdIX01PRSYKqm33fJoCOJBRseYCTUlQRnBNX+Pchaejw==", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - }, - "platform": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz", - "integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==", - "dev": true - }, - "playwright": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.0.tgz", - "integrity": "sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==", - "dev": true, - "requires": { - "fsevents": "2.3.2", - "playwright-core": "1.47.0" - } - }, - "playwright-core": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0.tgz", - "integrity": "sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==", - "dev": true - }, - "please-upgrade-node": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", - "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", - "dev": true, - "requires": { - "semver-compare": "^1.0.0" - } - }, - "plist": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", - "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", - "dev": true, - "requires": { - "@xmldom/xmldom": "^0.8.8", - "base64-js": "^1.5.1", - "xmlbuilder": "^15.1.1" - } - }, - "plur": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz", - "integrity": "sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==", - "dev": true, - "requires": { - "irregular-plurals": "^3.2.0" - } - }, - "pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "dev": true - }, - "polished": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/polished/-/polished-4.2.2.tgz", - "integrity": "sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.17.8" - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", - "dev": true - }, - "postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", - "requires": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" - }, - "dependencies": { - "source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" - } - } - }, - "postcss-calc": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", - "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.11", - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-colormin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.0.0.tgz", - "integrity": "sha512-EuO+bAUmutWoZYgHn2T1dG1pPqHU6L4TjzPlu4t1wZGXQ/fxV16xg2EJmYi0z+6r+MGV1yvpx1BHkUaRrPa2bw==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-convert-values": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.0.0.tgz", - "integrity": "sha512-U5D8QhVwqT++ecmy8rnTb+RL9n/B806UVaS3m60lqle4YDFcpbS3ae5bTQIh3wOGUSDHSEtMYLs/38dNG7EYFw==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-discard-comments": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.0.tgz", - "integrity": "sha512-p2skSGqzPMZkEQvJsgnkBhCn8gI7NzRH2683EEjrIkoMiwRELx68yoUJ3q3DGSGuQ8Ug9Gsn+OuDr46yfO+eFw==", - "dev": true - }, - "postcss-discard-duplicates": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.0.tgz", - "integrity": "sha512-bU1SXIizMLtDW4oSsi5C/xHKbhLlhek/0/yCnoMQany9k3nPBq+Ctsv/9oMmyqbR96HYHxZcHyK2HR5P/mqoGA==", - "dev": true - }, - "postcss-discard-empty": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.0.tgz", - "integrity": "sha512-b+h1S1VT6dNhpcg+LpyiUrdnEZfICF0my7HAKgJixJLW7BnNmpRH34+uw/etf5AhOlIhIAuXApSzzDzMI9K/gQ==", - "dev": true - }, - "postcss-discard-overridden": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.0.tgz", - "integrity": "sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw==", - "dev": true - }, - "postcss-import": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz", - "integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", - "dev": true, - "requires": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" - } - }, - "postcss-local-keyframes": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/postcss-local-keyframes/-/postcss-local-keyframes-0.0.2.tgz", - "integrity": "sha512-nRN01llvxnqLw1TZu4kBknHwpxPPK3DLLJClQ3eTGhS+jBNyoIAMx0hw+fdiDOy7TXjfnojamPwUm/UxBEZDTw==", - "dev": true - }, - "postcss-media-query-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", - "dev": true - }, - "postcss-merge-longhand": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.0.tgz", - "integrity": "sha512-4VSfd1lvGkLTLYcxFuISDtWUfFS4zXe0FpF149AyziftPFQIWxjvFSKhA4MIxMe4XM3yTDgQMbSNgzIVxChbIg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^6.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-merge-rules": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.0.1.tgz", - "integrity": "sha512-a4tlmJIQo9SCjcfiCcCMg/ZCEe0XTkl/xK0XHBs955GWg9xDX3NwP9pwZ78QUOWB8/0XCjZeJn98Dae0zg6AAw==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^4.0.0", - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-minify-font-values": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.0.0.tgz", - "integrity": "sha512-zNRAVtyh5E8ndZEYXA4WS8ZYsAp798HiIQ1V2UF/C/munLp2r1UGHwf1+6JFu7hdEhJFN+W1WJQKBrtjhFgEnA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-minify-gradients": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.0.tgz", - "integrity": "sha512-wO0F6YfVAR+K1xVxF53ueZJza3L+R3E6cp0VwuXJQejnNUH0DjcAFe3JEBeTY1dLwGa0NlDWueCA1VlEfiKgAA==", - "dev": true, - "requires": { - "colord": "^2.9.1", - "cssnano-utils": "^4.0.0", - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-minify-params": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.0.0.tgz", - "integrity": "sha512-Fz/wMQDveiS0n5JPcvsMeyNXOIMrwF88n7196puSuQSWSa+/Ofc1gDOSY2xi8+A4PqB5dlYCKk/WfqKqsI+ReQ==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "cssnano-utils": "^4.0.0", - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-minify-selectors": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.0.tgz", - "integrity": "sha512-ec/q9JNCOC2CRDNnypipGfOhbYPuUkewGwLnbv6omue/PSASbHSU7s6uSQ0tcFRVv731oMIx8k0SP4ZX6be/0g==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true - }, - "postcss-modules-local-by-default": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", - "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-modules-scope": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", - "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.4" - } - }, - "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0" - } - }, - "postcss-normalize-charset": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.0.tgz", - "integrity": "sha512-cqundwChbu8yO/gSWkuFDmKrCZ2vJzDAocheT2JTd0sFNA4HMGoKMfbk2B+J0OmO0t5GUkiAkSM5yF2rSLUjgQ==", - "dev": true - }, - "postcss-normalize-display-values": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.0.tgz", - "integrity": "sha512-Qyt5kMrvy7dJRO3OjF7zkotGfuYALETZE+4lk66sziWSPzlBEt7FrUshV6VLECkI4EN8Z863O6Nci4NXQGNzYw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-normalize-positions": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.0.tgz", - "integrity": "sha512-mPCzhSV8+30FZyWhxi6UoVRYd3ZBJgTRly4hOkaSifo0H+pjDYcii/aVT4YE6QpOil15a5uiv6ftnY3rm0igPg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-normalize-repeat-style": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.0.tgz", - "integrity": "sha512-50W5JWEBiOOAez2AKBh4kRFm2uhrT3O1Uwdxz7k24aKtbD83vqmcVG7zoIwo6xI2FZ/HDlbrCopXhLeTpQib1A==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-normalize-string": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.0.tgz", - "integrity": "sha512-KWkIB7TrPOiqb8ZZz6homet2KWKJwIlysF5ICPZrXAylGe2hzX/HSf4NTX2rRPJMAtlRsj/yfkrWGavFuB+c0w==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-normalize-timing-functions": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.0.tgz", - "integrity": "sha512-tpIXWciXBp5CiFs8sem90IWlw76FV4oi6QEWfQwyeREVwUy39VSeSqjAT7X0Qw650yAimYW5gkl2Gd871N5SQg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-normalize-unicode": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.0.tgz", - "integrity": "sha512-ui5crYkb5ubEUDugDc786L/Me+DXp2dLg3fVJbqyAl0VPkAeALyAijF2zOsnZyaS1HyfPuMH0DwyY18VMFVNkg==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-normalize-url": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.0.tgz", - "integrity": "sha512-98mvh2QzIPbb02YDIrYvAg4OUzGH7s1ZgHlD3fIdTHLgPLRpv1ZTKJDnSAKr4Rt21ZQFzwhGMXxpXlfrUBKFHw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-normalize-whitespace": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.0.tgz", - "integrity": "sha512-7cfE1AyLiK0+ZBG6FmLziJzqQCpTQY+8XjMhMAz8WSBSCsCNNUKujgIgjCAmDT3cJ+3zjTXFkoD15ZPsckArVw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-ordered-values": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.0.tgz", - "integrity": "sha512-K36XzUDpvfG/nWkjs6d1hRBydeIxGpKS2+n+ywlKPzx1nMYDYpoGbcjhj5AwVYJK1qV2/SDoDEnHzlPD6s3nMg==", - "dev": true, - "requires": { - "cssnano-utils": "^4.0.0", - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-prefix-selector": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/postcss-prefix-selector/-/postcss-prefix-selector-1.16.1.tgz", - "integrity": "sha512-Umxu+FvKMwlY6TyDzGFoSUnzW+NOfMBLyC1tAkIjgX+Z/qGspJeRjVC903D7mx7TuBpJlwti2ibXtWuA7fKMeQ==" - }, - "postcss-reduce-initial": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz", - "integrity": "sha512-s2UOnidpVuXu6JiiI5U+fV2jamAw5YNA9Fdi/GRK0zLDLCfXmSGqQtzpUPtfN66RtCbb9fFHoyZdQaxOB3WxVA==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0" - } - }, - "postcss-reduce-transforms": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.0.tgz", - "integrity": "sha512-FQ9f6xM1homnuy1wLe9lP1wujzxnwt1EwiigtWwuyf8FsqqXUDUp2Ulxf9A5yjlUOTdCJO6lonYjg1mgqIIi2w==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-resolve-nested-selector": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", - "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", - "dev": true - }, - "postcss-safe-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.0.tgz", - "integrity": "sha512-ovehqRNVCpuFzbXoTb4qLtyzK3xn3t/CUBxOs8LsnQjQrShaB4lKiHoVqY8ANaC0hBMHq5QVWk77rwGklFUDrg==", - "dev": true - }, - "postcss-scss": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", - "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", - "dev": true - }, - "postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "postcss-svgo": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.0.tgz", - "integrity": "sha512-r9zvj/wGAoAIodn84dR/kFqwhINp5YsJkLoujybWG59grR/IHx+uQ2Zo+IcOwM0jskfYX3R0mo+1Kip1VSNcvw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0", - "svgo": "^3.0.2" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - } - } - }, - "postcss-unique-selectors": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.0.tgz", - "integrity": "sha512-EPQzpZNxOxP7777t73RQpZE5e9TrnCrkvp7AH7a0l89JmZiPnS82y216JowHXwpBCQitfyxrof9TK3rYbi7/Yw==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" - }, - "prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "dependencies": { - "pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "optional": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true - }, - "prettier": { - "version": "npm:wp-prettier@3.0.3", - "resolved": "https://registry.npmjs.org/wp-prettier/-/wp-prettier-3.0.3.tgz", - "integrity": "sha512-X4UlrxDTH8oom9qXlcjnydsjAOD2BmB6yFmvS4Z2zdTzqqpRWb+fbqrH412+l+OUXmbzJlSXjlMFYPgYG12IAA==", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, - "requires": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" - }, - "react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - } - } - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", - "dev": true - }, - "proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", - "dev": true - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "promise": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", - "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", - "requires": { - "asap": "~2.0.6" - } - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true - }, - "promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "requires": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - } - }, - "prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, - "promzard": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/promzard/-/promzard-1.0.0.tgz", - "integrity": "sha512-KQVDEubSUHGSt5xLakaToDFrSoZhStB8dXLzk2xvwR67gJktrHFvpR63oZgHyK19WKbHFLXJqCPXdVR3aBP8Ig==", - "dev": true, - "requires": { - "read": "^2.0.0" - } - }, - "prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", - "dev": true - }, - "protocols": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", - "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==", - "dev": true - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "proxy-agent": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.0.tgz", - "integrity": "sha512-0LdR757eTj/JfuU7TL2YCuAZnxWXu3tkJbg4Oq3geW/qFNT/32T0sp2HnZ9O0lMR4q3vwAt0+xCA8SR0WAD0og==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.0", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.0", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.1" - }, - "dependencies": { - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, - "requires": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - } - } - } - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true - }, - "ps-list": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/ps-list/-/ps-list-8.1.1.tgz", - "integrity": "sha512-OPS9kEJYVmiO48u/B9qneqhkMvgCxT+Tm28VCEJpheTpl8cJ0ffZRRNgS5mrQRTrX5yRTpaJ+hRDeefXYmmorQ==", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true - }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - } - } - }, - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" - }, - "puppeteer-core": { - "version": "23.1.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.1.0.tgz", - "integrity": "sha512-SvAsu+xnLN2FMXE/59bp3s3WXp8ewqUGzVV4AQtml/2xmsciZnU/bXcCW+eETHPWQ6Agg2vTI7QzWXPpEARK2g==", - "dev": true, - "requires": { - "@puppeteer/browsers": "2.3.1", - "chromium-bidi": "0.6.4", - "debug": "^4.3.6", - "devtools-protocol": "0.0.1312386", - "typed-query-selector": "^2.12.0", - "ws": "^8.18.0" - }, - "dependencies": { - "@puppeteer/browsers": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.1.tgz", - "integrity": "sha512-uK7o3hHkK+naEobMSJ+2ySYyXtQkBxIH8Gn4MK9ciePjNV+Pf+PgY/W7iPzn2MTjl3stcYB5AlcTmPYw7AXDwA==", - "dev": true, - "requires": { - "debug": "^4.3.6", - "extract-zip": "^2.0.1", - "progress": "^2.0.3", - "proxy-agent": "^6.4.0", - "semver": "^7.6.3", - "tar-fs": "^3.0.6", - "unbzip2-stream": "^1.4.3", - "yargs": "^17.7.2" - } - }, - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - }, - "chromium-bidi": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.4.tgz", - "integrity": "sha512-8zoq6ogmhQQkAKZVKO2ObFTl4uOkqoX1PlKQX3hZQ5E9cbUotcAb7h4pTNVAGGv8Z36PF3CtdOriEp/Rz82JqQ==", - "dev": true, - "requires": { - "mitt": "3.0.1", - "urlpattern-polyfill": "10.0.0", - "zod": "3.23.8" - } - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "requires": { - "ms": "^2.1.3" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "requires": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - } - }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "mitt": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", - "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", - "dev": true - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "proxy-agent": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", - "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.3", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.2" - } - }, - "pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - }, - "socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, - "requires": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "tar-fs": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", - "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", - "dev": true, - "requires": { - "bare-fs": "^2.1.1", - "bare-path": "^2.1.0", - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - } - }, - "tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, - "requires": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, - "pure-rand": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", - "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "query-selector-shadow-dom": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.1.tgz", - "integrity": "sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==", - "dev": true - }, - "query-string": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", - "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", - "requires": { - "decode-uri-component": "^0.2.0", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", - "dev": true - }, - "queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "requires": { - "inherits": "~2.0.3" - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" - }, - "queue-tick": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", - "dev": true - }, - "quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true - }, - "ramda": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.0.tgz", - "integrity": "sha512-BBea6L67bYLtdbOqfp8f58fPMqEwx0doL+pAi8TZyp2YWz8R9G8z9x75CZI8W+ftqhFHCpEX2cRnUUXK130iKA==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "optional": true - } - } - }, - "re-resizable": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/re-resizable/-/re-resizable-6.9.0.tgz", - "integrity": "sha512-3cUDG81ylyqI0Pdgle/RHwwRYq0ORZzsUaySOCO8IbEtNyaRtrIHYm/jMQ5pjcNiKCxR3vsSymIQZHwJq4gg2Q==", - "requires": { - "fast-memoize": "^2.5.1" - } - }, - "react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "requires": { - "loose-envify": "^1.1.0" - } - }, - "react-autosize-textarea": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/react-autosize-textarea/-/react-autosize-textarea-7.1.0.tgz", - "integrity": "sha512-BHpjCDkuOlllZn3nLazY2F8oYO1tS2jHnWhcjTWQdcKiiMU6gHLNt/fzmqMSyerR0eTdKtfSIqtSeTtghNwS+g==", - "requires": { - "autosize": "^4.0.2", - "line-height": "^0.3.1", - "prop-types": "^15.5.6" - } - }, - "react-colorful": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.3.1.tgz", - "integrity": "sha512-nkP1w1LGe8PzhtOQO10xSDTsMWAYVj/Wm5c7ORk7CBngjCE7hHsknFRtosT5qMYkwWs8wSiU0sBwZ8dyzRbNEQ==" - }, - "react-devtools-core": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.5.tgz", - "integrity": "sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==", - "requires": { - "shell-quote": "^1.6.1", - "ws": "^7" - } - }, - "react-docgen": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-7.0.3.tgz", - "integrity": "sha512-i8aF1nyKInZnANZ4uZrH49qn1paRgBZ7wZiCNBMnenlPzEv0mRl+ShpTVEI6wZNl8sSc79xZkivtgLKQArcanQ==", - "dev": true, - "requires": { - "@babel/core": "^7.18.9", - "@babel/traverse": "^7.18.9", - "@babel/types": "^7.18.9", - "@types/babel__core": "^7.18.0", - "@types/babel__traverse": "^7.18.0", - "@types/doctrine": "^0.0.9", - "@types/resolve": "^1.20.2", - "doctrine": "^3.0.0", - "resolve": "^1.22.1", - "strip-indent": "^4.0.0" - }, - "dependencies": { - "@types/doctrine": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz", - "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==", - "dev": true - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "strip-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", - "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", - "dev": true, - "requires": { - "min-indent": "^1.0.1" - } - } - } - }, - "react-docgen-typescript": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", - "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", - "dev": true - }, - "react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "requires": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - } - }, - "react-element-to-jsx-string": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-15.0.0.tgz", - "integrity": "sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==", - "dev": true, - "requires": { - "@base2/pretty-print-object": "1.0.1", - "is-plain-object": "5.0.0", - "react-is": "18.1.0" - }, - "dependencies": { - "react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", - "dev": true - } - } - }, - "react-freeze": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.3.tgz", - "integrity": "sha512-ZnXwLQnGzrDpHBHiC56TXFXvmolPeMjTn1UOm610M4EXGzbEDR7oOIyS2ZiItgbs6eZc4oU/a0hpk8PrcKvv5g==" - }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "react-native": { - "version": "0.73.3", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.73.3.tgz", - "integrity": "sha512-RSQDtT2DNUcmB4IgmW9NhRb5wqvXFl6DI2NEJmt0ps2OrVHpoA8Tkq+lkFOA/fvPscJKtFKEHFBDSR5UHR3PUw==", - "requires": { - "@jest/create-cache-key-function": "^29.6.3", - "@react-native-community/cli": "12.3.2", - "@react-native-community/cli-platform-android": "12.3.2", - "@react-native-community/cli-platform-ios": "12.3.2", - "@react-native/assets-registry": "0.73.1", - "@react-native/codegen": "0.73.2", - "@react-native/community-cli-plugin": "0.73.14", - "@react-native/gradle-plugin": "0.73.4", - "@react-native/js-polyfills": "0.73.1", - "@react-native/normalize-colors": "0.73.2", - "@react-native/virtualized-lists": "0.73.4", - "abort-controller": "^3.0.0", - "anser": "^1.4.9", - "ansi-regex": "^5.0.0", - "base64-js": "^1.5.1", - "chalk": "^4.0.0", - "deprecated-react-native-prop-types": "^5.0.0", - "event-target-shim": "^5.0.1", - "flow-enums-runtime": "^0.0.6", - "invariant": "^2.2.4", - "jest-environment-node": "^29.6.3", - "jsc-android": "^250231.0.0", - "memoize-one": "^5.0.0", - "metro-runtime": "^0.80.3", - "metro-source-map": "^0.80.3", - "mkdirp": "^0.5.1", - "nullthrows": "^1.1.1", - "pretty-format": "^26.5.2", - "promise": "^8.3.0", - "react-devtools-core": "^4.27.7", - "react-refresh": "^0.14.0", - "react-shallow-renderer": "^16.15.0", - "regenerator-runtime": "^0.13.2", - "scheduler": "0.24.0-canary-efb381bbf-20230505", - "stacktrace-parser": "^0.1.10", - "whatwg-fetch": "^3.0.0", - "ws": "^6.2.2", - "yargs": "^17.6.2" - }, - "dependencies": { - "@jest/types": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", - "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - } - }, - "@types/yargs": { - "version": "15.0.19", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", - "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", - "requires": { - "@types/yargs-parser": "*" - } - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "deprecated-react-native-prop-types": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-5.0.0.tgz", - "integrity": "sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ==", - "requires": { - "@react-native/normalize-colors": "^0.73.0", - "invariant": "^2.2.4", - "prop-types": "^15.8.1" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "requires": { - "minimist": "^1.2.6" - } - }, - "pretty-format": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", - "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", - "requires": { - "@jest/types": "^26.6.2", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^17.0.1" - } - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "scheduler": { - "version": "0.24.0-canary-efb381bbf-20230505", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", - "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", - "requires": { - "loose-envify": "^1.1.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "ws": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", - "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", - "requires": { - "async-limiter": "~1.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" - } - } - }, - "react-native-animatable": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/react-native-animatable/-/react-native-animatable-1.3.3.tgz", - "integrity": "sha512-2ckIxZQAsvWn25Ho+DK3d1mXIgj7tITkrS4pYDvx96WyOttSvzzFeQnM2od0+FUMzILbdHDsDEqZvnz1DYNQ1w==", - "requires": { - "prop-types": "^15.7.2" - } - }, - "react-native-fast-image": { - "version": "8.5.11", - "resolved": "https://registry.npmjs.org/react-native-fast-image/-/react-native-fast-image-8.5.11.tgz", - "integrity": "sha512-cNW4bIJg3nvKaheG8vGMfqCt5LMWX9MS5+wMudgKIHbGO51spRr4sgnlhVgwHLcZ5aeNOVJ8CPRxDIWKRq/0QA==" - }, - "react-native-gesture-handler": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.14.1.tgz", - "integrity": "sha512-YiM1BApV4aKeuwsM6O4C2ufwewYEKk6VMXOt0YqEZFMwABBFWhXLySFZYjBSNRU2USGppJbfHP1q1DfFQpKhdA==", - "requires": { - "@egjs/hammerjs": "^2.0.17", - "hoist-non-react-statics": "^3.3.0", - "invariant": "^2.2.4", - "lodash": "^4.17.21", - "prop-types": "^15.7.2" - } - }, - "react-native-get-random-values": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/react-native-get-random-values/-/react-native-get-random-values-1.4.0.tgz", - "integrity": "sha512-NnmEZcC5zfz+QEytFPM/fw818Hodw/BNbv7jGxU4pla4K2K9DCzG83IReMJqQ2wo552AYKguqrBG2SSn/U6rbA==", - "requires": { - "fast-base64-decode": "^1.0.0" - } - }, - "react-native-linear-gradient": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/react-native-linear-gradient/-/react-native-linear-gradient-2.7.3.tgz", - "integrity": "sha512-iyJszlZ1Ech2c+2qV+isMvvJKyoctR9ashDkhJg1/cuSF0vQaeLV1FAYTT3qW9doxChJGxVAFfYoxotH0yi3Iw==" - }, - "react-native-modal": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-13.0.1.tgz", - "integrity": "sha512-UB+mjmUtf+miaG/sDhOikRfBOv0gJdBU2ZE1HtFWp6UixW9jCk/bhGdHUgmZljbPpp0RaO/6YiMmQSSK3kkMaw==", - "requires": { - "prop-types": "^15.6.2", - "react-native-animatable": "1.3.3" - } - }, - "react-native-reanimated": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.6.2.tgz", - "integrity": "sha512-IIMREMOrxhtK35drfpzh2UhxNqAOHnuvGgtMofj7yHcMj16tmWZR2zFvMUf6z2MfmXv+aVgFQ6TRZ6yKYf7LNA==", - "requires": { - "@babel/plugin-transform-object-assign": "^7.16.7", - "@babel/preset-typescript": "^7.16.7", - "convert-source-map": "^2.0.0", - "invariant": "^2.2.4" - }, - "dependencies": { - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" - } - } - }, - "react-native-safe-area": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/react-native-safe-area/-/react-native-safe-area-0.5.1.tgz", - "integrity": "sha512-gBLv93P90sM6hk5HzUwTXzFuSDazTpg2ONi5iL9pnUsUfwdw2L9SKgjgVroxX10leGB9+0zz6/ycV+mItqr8OQ==", - "requires": { - "@types/react": "^16.8.8" - }, - "dependencies": { - "@types/react": { - "version": "16.14.62", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.62.tgz", - "integrity": "sha512-BWf7hqninZav6nerxXj+NeZT/mTpDeG6Lk2zREHAy63CrnXoOGPGtNqTFYFN/sqpSaREDP5otVV88axIXmKfGA==", - "requires": { - "@types/prop-types": "*", - "@types/scheduler": "^0.16", - "csstype": "^3.0.2" - } - } - } - }, - "react-native-safe-area-context": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.8.2.tgz", - "integrity": "sha512-ffUOv8BJQ6RqO3nLml5gxJ6ab3EestPiyWekxdzO/1MQ7NF8fW1Mzh1C5QE9yq573Xefnc7FuzGXjtesZGv7cQ==" - }, - "react-native-sass-transformer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/react-native-sass-transformer/-/react-native-sass-transformer-1.4.0.tgz", - "integrity": "sha512-PlRiaJIcDzYpIVDH0OQuabkMGy/zp7N/A14rqhBrFqhADXC0xR2W53Cb7CicL9CsOL4y7Sh2dv4pgMvqgMdwqQ==", - "requires": { - "app-root-path": "^2.1.0", - "css-to-react-native-transform": "^1.8.1", - "semver": "^5.6.0" - }, - "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" - } - } - }, - "react-native-screens": { - "version": "3.29.0", - "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.29.0.tgz", - "integrity": "sha512-yB1GoAMamFAcYf4ku94uBPn0/ani9QG7NdI98beJ5cet2YFESYYzuEIuU+kt+CNRcO8qqKeugxlfgAa3HyTqlg==", - "requires": { - "react-freeze": "^1.0.0", - "warn-once": "^0.1.0" - } - }, - "react-native-svg": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-14.0.0.tgz", - "integrity": "sha512-17W/gWXRUMS7p7PSHu/WyGkZUc1NzRTGxxXc0VqBLjzKSchyb0EmgsiWf9aKmfC6gmY0wcsmKZcGV41bCcNfBA==", - "requires": { - "css-select": "^5.1.0", - "css-tree": "^1.1.3" - } - }, - "react-native-url-polyfill": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/react-native-url-polyfill/-/react-native-url-polyfill-1.1.2.tgz", - "integrity": "sha512-RPYwjW+4udnAf26xUCQP2dn4t2tnRFo3Ii4s/hy7Ivpe7xYtXp7CMVX505CR8X3p0f8NKmOJ4MQEFMMnbd/Y/Q==", - "dev": true, - "requires": { - "buffer": "^5.4.3", - "whatwg-url-without-unicode": "8.0.0-1" - }, - "dependencies": { - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - } - } - }, - "react-native-video": { - "version": "https://raw.githubusercontent.com/wordpress-mobile/react-native-video/5.2.0-wp-7/react-native-video-5.2.0-wp-7.tgz", - "integrity": "sha512-DTwhGwqkc3IyDWsyJe8d+cEwaw7aHBgT7Q9+X+N3zDIC7qP3bZnXuTUeag8oz9XhfxRDRQJmF+t5is3qVNIuUA==", - "requires": { - "deprecated-react-native-prop-types": "^2.2.0", - "prop-types": "^15.7.2" - } - }, - "react-native-webview": { - "version": "13.6.1", - "resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.6.1.tgz", - "integrity": "sha512-m8leQJhouBIER0YFc1nKF7XKYtaF040tvSJJ5VAoD/P0lW7nAXZO4D1jaOEq3HQvEq3SsMl7qh7DW/XO5VhUlg==", - "requires": { - "escape-string-regexp": "2.0.0", - "invariant": "2.2.4" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" - } - } - }, - "react-refresh": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", - "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==" - }, - "react-remove-scroll": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", - "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==", - "requires": { - "react-remove-scroll-bar": "^2.3.3", - "react-style-singleton": "^2.2.1", - "tslib": "^2.1.0", - "use-callback-ref": "^1.3.0", - "use-sidecar": "^1.1.2" - } - }, - "react-remove-scroll-bar": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz", - "integrity": "sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==", - "requires": { - "react-style-singleton": "^2.2.1", - "tslib": "^2.0.0" - } - }, - "react-shallow-renderer": { - "version": "16.15.0", - "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", - "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", - "requires": { - "object-assign": "^4.1.1", - "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" - } - }, - "react-style-singleton": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", - "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", - "requires": { - "get-nonce": "^1.0.0", - "invariant": "^2.2.4", - "tslib": "^2.0.0" - } - }, - "react-test-renderer": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.3.1.tgz", - "integrity": "sha512-KkAgygexHUkQqtvvx/otwxtuFu5cVjfzTCtjXLH9boS19/Nbtg84zS7wIQn39G8IlrhThBpQsMKkq5ZHZIYFXA==", - "dev": true, - "requires": { - "react-is": "^18.3.1", - "react-shallow-renderer": "^16.15.0", - "scheduler": "^0.23.2" - }, - "dependencies": { - "react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - } - } - }, - "read": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/read/-/read-2.1.0.tgz", - "integrity": "sha512-bvxi1QLJHcaywCAEsAk4DG3nVoqiY2Csps3qzWalhj5hFqRn1d/OixkFXtLO1PrgHUcAP0FNaSY/5GYNfENFFQ==", - "dev": true, - "requires": { - "mute-stream": "~1.0.0" - }, - "dependencies": { - "mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", - "dev": true - } - } - }, - "read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "requires": { - "pify": "^2.3.0" - } - }, - "read-cmd-shim": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz", - "integrity": "sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==", - "dev": true - }, - "read-package-json": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", - "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", - "dev": true, - "requires": { - "glob": "^10.2.2", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^5.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - } - }, - "hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - } - }, - "jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "json-parse-even-better-errors": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", - "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", - "dev": true - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - }, - "normalize-package-data": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", - "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", - "dev": true, - "requires": { - "hosted-git-info": "^6.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - } - }, - "npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", - "dev": true - } - } - }, - "read-package-json-fast": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", - "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", - "dev": true, - "requires": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "dependencies": { - "json-parse-even-better-errors": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", - "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", - "dev": true - }, - "npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", - "dev": true - } - } - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdir-glob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", - "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", - "dev": true, - "requires": { - "minimatch": "^5.1.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "readline": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", - "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==" - }, - "reassure": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/reassure/-/reassure-0.7.1.tgz", - "integrity": "sha512-dCDo4AInl48Q66PAbF3JzV5WVGIQu2AiCNAy+zhcZ0ESalb4zsVuAvhLdgXCsWr9DhPju63rEGgoNWl9noDVKg==", - "dev": true, - "requires": { - "@callstack/reassure-cli": "0.6.1", - "@callstack/reassure-danger": "0.1.1", - "@callstack/reassure-measure": "0.3.1" - } - }, - "recast": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz", - "integrity": "sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==", - "requires": { - "ast-types": "0.15.2", - "esprima": "~4.0.0", - "source-map": "~0.6.1", - "tslib": "^2.0.1" - }, - "dependencies": { - "ast-types": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", - "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", - "requires": { - "tslib": "^2.0.1" - } - } - } - }, - "rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, - "requires": { - "resolve": "^1.20.0" - } - }, - "redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "requires": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "dependencies": { - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - } - } - }, - "redux": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", - "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", - "requires": { - "@babel/runtime": "^7.9.2" - } - }, - "regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" - }, - "regenerate-unicode-properties": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", - "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", - "requires": { - "regenerate": "^1.4.2" - } - }, - "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, - "regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" - } - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "requires": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - } - }, - "regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" - } - } - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true - }, - "remark": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/remark/-/remark-10.0.1.tgz", - "integrity": "sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ==", - "dev": true, - "requires": { - "remark-parse": "^6.0.0", - "remark-stringify": "^6.0.0", - "unified": "^7.0.0" - } - }, - "remark-external-links": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/remark-external-links/-/remark-external-links-8.0.0.tgz", - "integrity": "sha512-5vPSX0kHoSsqtdftSHhIYofVINC8qmp0nctkeU9YoJwV3YfiBRiI6cbFRJ0oI/1F9xS+bopXG0m2KS8VFscuKA==", - "dev": true, - "requires": { - "extend": "^3.0.0", - "is-absolute-url": "^3.0.0", - "mdast-util-definitions": "^4.0.0", - "space-separated-tokens": "^1.0.0", - "unist-util-visit": "^2.0.0" - }, - "dependencies": { - "unist-util-is": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", - "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", - "dev": true - }, - "unist-util-visit": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", - "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit-parents": "^3.0.0" - } - }, - "unist-util-visit-parents": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", - "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0" - } - } - } - }, - "remark-parse": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-6.0.3.tgz", - "integrity": "sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^1.1.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^1.0.0", - "vfile-location": "^2.0.0", - "xtend": "^4.0.1" - } - }, - "remark-slug": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-6.1.0.tgz", - "integrity": "sha512-oGCxDF9deA8phWvxFuyr3oSJsdyUAxMFbA0mZ7Y1Sas+emILtO+e5WutF9564gDsEN4IXaQXm5pFo6MLH+YmwQ==", - "dev": true, - "requires": { - "github-slugger": "^1.0.0", - "mdast-util-to-string": "^1.0.0", - "unist-util-visit": "^2.0.0" - }, - "dependencies": { - "unist-util-is": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", - "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", - "dev": true - }, - "unist-util-visit": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", - "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit-parents": "^3.0.0" - } - }, - "unist-util-visit-parents": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", - "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0" - } - } - } - }, - "remark-stringify": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-6.0.4.tgz", - "integrity": "sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg==", - "dev": true, - "requires": { - "ccount": "^1.0.0", - "is-alphanumeric": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "longest-streak": "^2.0.1", - "markdown-escapes": "^1.0.0", - "markdown-table": "^1.1.0", - "mdast-util-compact": "^1.0.0", - "parse-entities": "^1.0.2", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "stringify-entities": "^1.0.1", - "unherit": "^1.0.4", - "xtend": "^4.0.1" - } - }, - "rememo": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/rememo/-/rememo-4.0.2.tgz", - "integrity": "sha512-NVfSP9NstE3QPNs/TnegQY0vnJnstKQSpcrsI2kBTB3dB2PkdfKdTa+abbjMIDqpc63fE5LfjLgfMst0ULMFxQ==" - }, - "remove-accents": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", - "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==" - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", - "dev": true, - "optional": true - }, - "renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dev": true, - "requires": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - } - }, - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - } - } - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha512-vuNYXC7gG7IeVNBC1xUllqCcZKRbJoSPOBhnTEcAIiKCsbuef6zO3F0Rve3isPMMoNoQRWjQwbAgAjHUHniyEA==", - "dev": true - }, - "requestidlecallback": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/requestidlecallback/-/requestidlecallback-0.3.0.tgz", - "integrity": "sha512-TWHFkT7S9p7IxLC5A1hYmAYQx2Eb9w1skrXmQ+dS1URyvR8tenMLl4lHbqEOUnpEYxNKpkVMXUgknVpBZWXXfQ==" - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, - "requireindex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", - "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "resize-observer-polyfill": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", - "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", - "dev": true - }, - "resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "requires": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, - "resolve-bin": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/resolve-bin/-/resolve-bin-0.4.0.tgz", - "integrity": "sha1-RxMiSYkRAa+xmZH+k3ywpfBy5dk=", - "dev": true, - "requires": { - "find-parent-dir": "~0.3.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } - } - }, - "resolve-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", - "integrity": "sha512-QxMPqI6le2u0dCLyiGzgy92kjkkL6zO0XyvHzjdTNH3zM6e5Hz3BwG6+aEyNgiQ5Xz6PwTwgQEj3U50dByPKIA==", - "dev": true, - "requires": { - "expand-tilde": "^1.2.2", - "global-modules": "^0.2.3" - }, - "dependencies": { - "global-modules": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", - "integrity": "sha512-JeXuCbvYzYXcwE6acL9V2bAOeSIGl4dD+iwLY9iUx2VBJJ80R18HCn+JCwHM9Oegdfya3lEkGCdaRkSyc10hDA==", - "dev": true, - "requires": { - "global-prefix": "^0.1.4", - "is-windows": "^0.2.0" - } - }, - "global-prefix": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", - "integrity": "sha512-gOPiyxcD9dJGCEArAhF4Hd0BAqvAe/JzERP7tYumE4yIkmIedPUVXcJFWbV3/p/ovIIvKjkrTk+f1UVkq7vvbw==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.0", - "ini": "^1.3.4", - "is-windows": "^0.2.0", - "which": "^1.2.12" - } - }, - "is-windows": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha512-n67eJYmXbniZB7RF4I/FTjK1s6RPOCTxhYrVYLRaCt3lF0mpWZPKr3T2LSZAqyjQsxR2qMmGYXXzK0YWwcPM1Q==", - "dev": true - } - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==" - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==" - }, - "resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true - }, - "responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, - "requires": { - "lowercase-keys": "^2.0.0" - } - }, - "resq": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/resq/-/resq-1.11.0.tgz", - "integrity": "sha512-G10EBz+zAAy3zUd/CDoBbXRL6ia9kOo3xRHrMDsHljI0GDkhYlyjwoCx5+3eCC4swi1uCoZQhskuJkj7Gp57Bw==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1" - }, - "dependencies": { - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", - "dev": true - } - } - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rgb2hex": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.5.tgz", - "integrity": "sha512-22MOP1Rh7sAo1BZpDG6R5RFYzR2lYEgwq7HEmyW2qcsOqR2lQKmn+O//xV3YG/0rrhMC6KVX2hU+ZXuaw9a5bw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "robots-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/robots-parser/-/robots-parser-3.0.1.tgz", - "integrity": "sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ==", - "dev": true - }, - "rrweb-cssom": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", - "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", - "dev": true - }, - "rtlcss": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.0.0.tgz", - "integrity": "sha512-j6oypPP+mgFwDXL1JkLCtm6U/DQntMUqlv5SOhpgHhdIE+PmBcjrtAHIpXfbIup47kD5Sgja9JDsDF1NNOsBwQ==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0", - "postcss": "^8.4.6", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - } - } - }, - "rtlcss-webpack-plugin": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/rtlcss-webpack-plugin/-/rtlcss-webpack-plugin-4.0.7.tgz", - "integrity": "sha512-ouSbJtgcLBBQIsMgarxsDnfgRqm/AS4BKls/mz/Xb6HSl+PdEzefTR+Wz5uWQx4odoX0g261Z7yb3QBz0MTm0g==", - "dev": true, - "requires": { - "babel-runtime": "~6.25.0", - "rtlcss": "^3.5.0" - }, - "dependencies": { - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "rtlcss": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz", - "integrity": "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==", - "dev": true, - "requires": { - "find-up": "^5.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.3.11", - "strip-json-comments": "^3.1.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - } - } - }, - "run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dev": true, - "requires": { - "execa": "^5.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true - }, - "run-con": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/run-con/-/run-con-1.2.10.tgz", - "integrity": "sha512-n7PZpYmMM26ZO21dd8y3Yw1TRtGABjRtgPSgFS/nhzfvbJMXFtJhJVyEgayMiP+w/23craJjsnfDvx4W4ue/HQ==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~2.0.0", - "minimist": "^1.2.5", - "strip-json-comments": "~3.1.1" - }, - "dependencies": { - "ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - } - } - }, - "run-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz", - "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", - "dev": true - }, - "run-parallel": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", - "dev": true - }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } - }, - "rungen": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/rungen/-/rungen-0.3.2.tgz", - "integrity": "sha512-zWl10xu2D7zoR8zSC2U6bg5bYF6T/Wk7rxwp8IPaJH7f0Ge21G03kNHVgHR7tyVkSSfAOG0Rqf/Cl38JftSmtw==" - }, - "rx": { - "version": "2.3.24", - "resolved": "https://registry.npmjs.org/rx/-/rx-2.3.24.tgz", - "integrity": "sha512-Ue4ZB7Dzbn2I9sIj8ws536nOP2S53uypyCkCz9q0vlYD5Kn6/pu4dE+wt2ZfFzd9m73hiYKnnCb1OyKqc+MRkg==", - "dev": true - }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "safaridriver": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/safaridriver/-/safaridriver-0.1.0.tgz", - "integrity": "sha512-azzzIP3gR1TB9bVPv7QO4Zjw0rR1BWEU/s2aFdUMN48gxDjxEB13grAEuXDmkKPgE74cObymDxmAmZnL3clj4w==", - "dev": true - }, - "safe-array-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", - "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - } - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - } - }, - "safe-stable-stringify": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", - "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sanitize-filename": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", - "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", - "dev": true, - "requires": { - "truncate-utf8-bytes": "^1.0.0" - } - }, - "sass": { - "version": "1.35.2", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.35.2.tgz", - "integrity": "sha512-jhO5KAR+AMxCEwIH3v+4zbB2WB0z67V1X0jbapfVwQQdjHZUGUyukpnoM6+iCMfsIUC016w9OPKQ5jrNOS9uXw==", - "dev": true, - "requires": { - "chokidar": ">=3.0.0 <4.0.0" - } - }, - "sass-loader": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.1.0.tgz", - "integrity": "sha512-FVJZ9kxVRYNZTIe2xhw93n3xJNYZADr+q69/s98l9nTCrWASo+DR2Ot0s5xTKQDDEosUkatsGeHxcH4QBp5bSg==", - "dev": true, - "requires": { - "klona": "^2.0.4", - "neo-async": "^2.6.2" - } - }, - "saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "requires": { - "loose-envify": "^1.1.0" - } - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - } - } - }, - "seedrandom": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", - "dev": true - }, - "select": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", - "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==" - }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true - }, - "selfsigned": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", - "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", - "dev": true, - "requires": { - "node-forge": "^1" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true - }, - "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - } - } - }, - "sentence-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", - "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, - "serialize-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", - "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==" - }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-favicon": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz", - "integrity": "sha512-FMW2RvqNr03x+C0WxTyu6sOv21oOjkq5j8tjquWccwa6ScNyGFOGJVpuS1NmTVGBAHS07xnSKotgf2ehQmf9iA==", - "dev": true, - "requires": { - "etag": "~1.8.1", - "fresh": "0.5.2", - "ms": "2.1.1", - "parseurl": "~1.3.2", - "safe-buffer": "5.1.1" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true - } - } - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - } - } - }, - "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "requires": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - } - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "requires": { - "kind-of": "^6.0.2" - } - }, - "sharp": { - "version": "0.32.6", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", - "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", - "dev": true, - "optional": true, - "requires": { - "color": "^4.2.3", - "detect-libc": "^2.0.2", - "node-addon-api": "^6.1.0", - "prebuild-install": "^7.1.1", - "semver": "^7.5.4", - "simple-get": "^4.0.1", - "tar-fs": "^3.0.4", - "tunnel-agent": "^0.6.0" - }, - "dependencies": { - "node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", - "dev": true, - "optional": true - }, - "pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "optional": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "tar-fs": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", - "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", - "dev": true, - "optional": true, - "requires": { - "bare-fs": "^2.1.1", - "bare-path": "^2.1.0", - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - } - }, - "tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, - "optional": true, - "requires": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - } - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true - }, - "shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==" - }, - "shiki": { - "version": "0.14.4", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.4.tgz", - "integrity": "sha512-IXCRip2IQzKwxArNNq1S+On4KPML3Yyn8Zzs/xRgcgOWIr8ntIK3IKzjFPfjy/7kt9ZMjc+FItfqHRBg8b6tNQ==", - "dev": true, - "requires": { - "ansi-sequence-parser": "^1.1.0", - "jsonc-parser": "^3.2.0", - "vscode-oniguruma": "^1.7.0", - "vscode-textmate": "^8.0.0" - }, - "dependencies": { - "jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true - } - } - }, - "showdown": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/showdown/-/showdown-1.9.1.tgz", - "integrity": "sha512-9cGuS382HcvExtf5AHk7Cb4pAeQQ+h0eTr33V1mu+crYWV4KvWAw6el92bDrqGEk5d46Ai/fhbEUwqJ/mTCNEA==", - "requires": { - "yargs": "^14.2" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", - "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", - "requires": { - "cliui": "^5.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^15.0.1" - } - }, - "yargs-parser": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.3.tgz", - "integrity": "sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "sigstore": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.8.0.tgz", - "integrity": "sha512-ogU8qtQ3VFBawRJ8wjsBEX/vIFeHuGs1fm4jZtjWQwjo8pfAt7T/rh+udlAN4+QUe0IzA8qRSc/YZ7dHP6kh+w==", - "dev": true, - "requires": { - "@sigstore/bundle": "^1.0.0", - "@sigstore/protobuf-specs": "^0.2.0", - "@sigstore/tuf": "^1.0.3", - "make-fetch-happen": "^11.0.1" - } - }, - "simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true, - "optional": true - }, - "simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "dev": true, - "optional": true, - "requires": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "simple-git": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.24.0.tgz", - "integrity": "sha512-QqAKee9Twv+3k8IFOFfPB2hnk6as6Y6ACUpwCtQvRYBAes23Wv3SZlHVobAzqcE8gfsisCvPw3HGW3HYM+VYYw==", - "dev": true, - "requires": { - "@kwsites/file-exists": "^1.1.1", - "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.3.4" - } - }, - "simple-html-tokenizer": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.5.7.tgz", - "integrity": "sha512-APW9iYbkJ5cijjX4Ljhf3VG8SwYPUJT5gZrwci/wieMabQxWFiV5VwsrP5c6GMRvXKEQMGkAB1d9dvW66dTqpg==" - }, - "simple-peer": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-9.11.1.tgz", - "integrity": "sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw==", - "requires": { - "buffer": "^6.0.3", - "debug": "^4.3.2", - "err-code": "^3.0.1", - "get-browser-rtc": "^1.1.0", - "queue-microtask": "^1.2.3", - "randombytes": "^2.1.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "err-code": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", - "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "requires": { - "is-arrayish": "^0.3.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - } - } - }, - "sirv": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", - "integrity": "sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==", - "dev": true, - "requires": { - "@polka/url": "^1.0.0-next.20", - "mrmime": "^1.0.0", - "totalist": "^3.0.0" - } - }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" - }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw==", - "dev": true - }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true - }, - "snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-descriptor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", - "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "snapshot-diff": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/snapshot-diff/-/snapshot-diff-0.10.0.tgz", - "integrity": "sha512-tbThBMguEG4TQNPfYD5VDAYbmxsSnu+VQSLElWfDBdebLKqXZa14hap8LqxAwD9w8CT4dfS+Ga9+7JMmHMU98g==", - "dev": true, - "requires": { - "jest-diff": "^29.0.0", - "jest-snapshot": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "requires": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - }, - "dependencies": { - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - } - } - }, - "socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", - "dev": true, - "requires": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - } - }, - "socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - } - }, - "sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - }, - "dependencies": { - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true - } - } - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "source-map-js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", - "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", - "dev": true - }, - "source-map-loader": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.0.tgz", - "integrity": "sha512-GKGWqWvYr04M7tn8dryIWvb0s8YM41z82iQv01yBtIylgxax0CwvSy6gc2Y02iuXwEfGWRlMicH0nvms9UZphw==", - "dev": true, - "requires": { - "abab": "^2.0.5", - "iconv-lite": "^0.6.2", - "source-map-js": "^0.6.2" - } - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" - }, - "space-separated-tokens": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", - "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", - "dev": true - }, - "spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", - "dev": true - }, - "spdx-correct": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", - "dev": true - }, - "spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "specificity": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz", - "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==", - "dev": true - }, - "speedline-core": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/speedline-core/-/speedline-core-1.4.3.tgz", - "integrity": "sha512-DI7/OuAUD+GMpR6dmu8lliO2Wg5zfeh+/xsdyJZCzd8o5JgFUjCeLsBDuZjIQJdwXS3J0L/uZYrELKYqx+PXog==", - "dev": true, - "requires": { - "@types/node": "*", - "image-ssim": "^0.2.0", - "jpeg-js": "^0.4.1" - } - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "requires": { - "through": "2" - } - }, - "split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "requires": { - "readable-stream": "^3.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "sprintf-js": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", - "integrity": "sha512-h/U+VScR2Ft+aXDjGTLtguUEIrYuOjTj79BAOElUvdahYMaaa7SNLjJpOIn+Uzt0hsgHfYvlbcno3e9yXOSo8Q==" - }, - "ssri": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", - "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "dev": true - }, - "stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", - "requires": { - "escape-string-regexp": "^2.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" - } - } - }, - "stackframe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", - "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==" - }, - "stacktrace-parser": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", - "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", - "requires": { - "type-fest": "^0.7.1" - }, - "dependencies": { - "type-fest": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", - "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==" - } - } - }, - "state-toggle": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", - "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" - }, - "stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "requires": { - "internal-slot": "^1.0.4" - } - }, - "store2": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/store2/-/store2-2.14.2.tgz", - "integrity": "sha512-siT1RiqlfQnGqgT/YzXVUNsom9S0H1OX+dpdGN1xkyYATo4I6sep5NmsRD/40s3IIOvlCq6akxkqG82urIZW1w==", - "dev": true - }, - "storybook": { - "version": "7.6.15", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-7.6.15.tgz", - "integrity": "sha512-Ybezq9JRk5CBhzjgzZ/oT7mnU45UwhyVSGKW+PUKZGGUG9VH2hCrTEES9f/zEF82kj/5COVPyqR/5vlXuuS39A==", - "dev": true, - "requires": { - "@storybook/cli": "7.6.15" - } - }, - "storybook-source-link": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/storybook-source-link/-/storybook-source-link-2.0.9.tgz", - "integrity": "sha512-ysQRQ3e6CtJp9uKPRmb6lfQBDl34DrBftKGU4zycHQYESlqOFYRBQ1GgUwN5kL8un2suDqtMc5IHh50fEAmXqg==", - "dev": true - }, - "stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-buffers": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", - "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", - "dev": true - }, - "stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ==", - "dev": true, - "requires": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "streamx": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.1.tgz", - "integrity": "sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==", - "dev": true, - "requires": { - "fast-fifo": "^1.1.0", - "queue-tick": "^1.0.1" - } - }, - "strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", - "dev": true - }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - } - } - }, - "string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4" - } - }, - "string.prototype.padend": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz", - "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "stringify-entities": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", - "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "dev": true, - "requires": { - "character-entities-html4": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } - }, - "stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dev": true, - "requires": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" - }, - "strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "requires": { - "min-indent": "^1.0.0" - } - }, - "strip-json-comments": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.0.tgz", - "integrity": "sha512-V1LGY4UUo0jgwC+ELQ2BNWfPa17TIuwBLg+j1AA/9RPzKINl1lhxVEu2r+ZTTO8aetIsUzE5Qj6LMSBkoGYKKw==", - "dev": true - }, - "strip-outer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.2" - } - }, - "strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" - }, - "strong-log-transformer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", - "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", - "dev": true, - "requires": { - "duplexer": "^0.1.1", - "minimist": "^1.2.0", - "through": "^2.3.4" - } - }, - "style-loader": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.2.1.tgz", - "integrity": "sha512-1k9ZosJCRFaRbY6hH49JFlRB0fVSbmnyq1iTPjNxUmGVjBNEmwrrHPenhlp+Lgo51BojHSf6pl2FcqYaN3PfVg==", - "dev": true - }, - "style-search": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", - "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", - "dev": true - }, - "stylehacks": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.0.0.tgz", - "integrity": "sha512-+UT589qhHPwz6mTlCLSt/vMNTJx8dopeJlZAlBMJPWA3ORqu6wmQY7FBXf+qD+FsqoBJODyqNxOUP3jdntFRdw==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "postcss-selector-parser": "^6.0.4" - } - }, - "stylelint": { - "version": "16.8.2", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.8.2.tgz", - "integrity": "sha512-fInKATippQhcSm7AB+T32GpI+626yohrg33GkFT/5jzliUw5qhlwZq2UQQwgl3HsHrf09oeARi0ZwgY/UWEv9A==", - "dev": true, - "requires": { - "@csstools/css-parser-algorithms": "^3.0.0", - "@csstools/css-tokenizer": "^3.0.0", - "@csstools/media-query-list-parser": "^3.0.0", - "@csstools/selector-specificity": "^4.0.0", - "@dual-bundle/import-meta-resolve": "^4.1.0", - "balanced-match": "^2.0.0", - "colord": "^2.9.3", - "cosmiconfig": "^9.0.0", - "css-functions-list": "^3.2.2", - "css-tree": "^2.3.1", - "debug": "^4.3.6", - "fast-glob": "^3.3.2", - "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^9.0.0", - "global-modules": "^2.0.0", - "globby": "^11.1.0", - "globjoin": "^0.1.4", - "html-tags": "^3.3.1", - "ignore": "^5.3.2", - "imurmurhash": "^0.1.4", - "is-plain-object": "^5.0.0", - "known-css-properties": "^0.34.0", - "mathml-tag-names": "^2.1.3", - "meow": "^13.2.0", - "micromatch": "^4.0.7", - "normalize-path": "^3.0.0", - "picocolors": "^1.0.1", - "postcss": "^8.4.41", - "postcss-resolve-nested-selector": "^0.1.6", - "postcss-safe-parser": "^7.0.0", - "postcss-selector-parser": "^6.1.2", - "postcss-value-parser": "^4.2.0", - "resolve-from": "^5.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^7.1.0", - "supports-hyperlinks": "^3.0.0", - "svg-tags": "^1.0.0", - "table": "^6.8.2", - "write-file-atomic": "^5.0.1" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "balanced-match": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", - "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", - "dev": true - }, - "cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", - "dev": true, - "requires": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - } - }, - "css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, - "requires": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - } - }, - "debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "requires": { - "ms": "^2.1.3" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "file-entry-cache": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", - "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", - "dev": true, - "requires": { - "flat-cache": "^5.0.0" - } - }, - "flat-cache": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", - "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", - "dev": true, - "requires": { - "flatted": "^3.3.1", - "keyv": "^4.5.4" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true - }, - "meow": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", - "dev": true - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "dev": true, - "requires": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.0", - "source-map-js": "^1.2.1" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - }, - "source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true - } - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-hyperlinks": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz", - "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==", - "dev": true, - "requires": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - } - }, - "write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - } - } - } - }, - "stylis": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz", - "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==" - }, - "sudo-prompt": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz", - "integrity": "sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "dev": true, - "requires": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" - }, - "svg-parser": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", - "dev": true - }, - "svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", - "dev": true - }, - "svgo": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.2.tgz", - "integrity": "sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ==", - "dev": true, - "requires": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^5.1.0", - "css-tree": "^2.2.1", - "csso": "^5.0.5", - "picocolors": "^1.0.0" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, - "requires": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - } - }, - "mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true - }, - "source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true - } - } - }, - "swc-loader": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", - "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", - "dev": true, - "requires": { - "@swc/counter": "^0.1.3" - } - }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", - "dev": true - }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "synchronous-promise": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.17.tgz", - "integrity": "sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==", - "dev": true - }, - "synckit": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", - "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", - "dev": true, - "requires": { - "@pkgr/utils": "^2.3.1", - "tslib": "^2.5.0" - } - }, - "table": { - "version": "6.8.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", - "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "tannin": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tannin/-/tannin-1.2.0.tgz", - "integrity": "sha512-U7GgX/RcSeUETbV7gYgoz8PD7Ni4y95pgIP/Z6ayI3CfhSujwKEBlGFTCRN+Aqnuyf4AN2yHL+L8x+TCGjb9uA==", - "requires": { - "@tannin/plural-forms": "^1.1.0" - } - }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true - }, - "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, - "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - }, - "dependencies": { - "pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "teen_process": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/teen_process/-/teen_process-2.0.2.tgz", - "integrity": "sha512-8Be+s0d3XIs6rosilYTYR8/TY4JfAl8Der8ItWhI/o/MTYGLTcjvNUNk5AU8c1eTpJ98MF0xextE8VJtqhtUcg==", - "dev": true, - "requires": { - "@babel/runtime": "7.19.0", - "bluebird": "3.7.2", - "lodash": "4.17.21", - "shell-quote": "1.7.3", - "source-map-support": "0.5.21", - "which": "2.0.2" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz", - "integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "telejson": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz", - "integrity": "sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==", - "dev": true, - "requires": { - "memoizerific": "^1.11.3" - } - }, - "temp": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", - "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", - "requires": { - "rimraf": "~2.6.2" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==", - "dev": true - }, - "tempy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", - "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", - "dev": true, - "requires": { - "del": "^6.0.0", - "is-stream": "^2.0.0", - "temp-dir": "^2.0.0", - "type-fest": "^0.16.0", - "unique-string": "^2.0.0" - }, - "dependencies": { - "del": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", - "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", - "dev": true, - "requires": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - } - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "dev": true - }, - "type-fest": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", - "dev": true - } - } - }, - "terminal-link": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.0.0.tgz", - "integrity": "sha512-rdBAY35jUvVapqCuhehjenLbYY73cVgRQ6podD6u9EDBomBBHjCOtmq2InPgPpTysOIOsQ5PdBzwSC/sKjv6ew==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - } - }, - "terser": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.32.0.tgz", - "integrity": "sha512-v3Gtw3IzpBJ0ugkxEX8U0W6+TnPKRRCWGh1jC/iM/e3Ki5+qvO1L1EAZ56bZasc64aXHwRHNIQEzm6//i5cemQ==", - "requires": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==" - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - } - } - }, - "terser-webpack-plugin": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "dev": true - }, - "text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", - "dev": true - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "third-party-web": { - "version": "0.23.4", - "resolved": "https://registry.npmjs.org/third-party-web/-/third-party-web-0.23.4.tgz", - "integrity": "sha512-kwYnSZRhEvv0SBW2fp8SBBKRglMoBjV8xz6C31m0ewqOtknB5UL+Ihg+M81hyFY5ldkZuGWPb+e4GVDkzf/gYg==", - "dev": true - }, - "throat": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", - "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==" - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "timers-browserify": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", - "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - }, - "tiny-emitter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" - }, - "tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", - "dev": true - }, - "titleize": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", - "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", - "dev": true - }, - "tldts": { - "version": "6.1.50", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.50.tgz", - "integrity": "sha512-q9GOap6q3KCsLMdOjXhWU5jVZ8/1dIib898JBRLsN+tBhENpBDcAVQbE0epADOjw11FhQQy9AcbqKGBQPUfTQA==", - "dev": true, - "requires": { - "tldts-core": "^6.1.50" - } - }, - "tldts-core": { - "version": "6.1.50", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.50.tgz", - "integrity": "sha512-na2EcZqmdA2iV9zHV7OHQDxxdciEpxrjbkp+aHmZgnZKHzoElLajP59np5/4+sare9fQBfixgvXKx8ev1d7ytw==", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "tocbot": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/tocbot/-/tocbot-4.25.0.tgz", - "integrity": "sha512-kE5wyCQJ40hqUaRVkyQ4z5+4juzYsv/eK+aqD97N62YH0TxFhzJvo22RUQQZdO3YnXAk42ZOfOpjVdy+Z0YokA==", - "dev": true - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true - }, - "tough-cookie": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", - "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", - "dev": true, - "requires": { - "tldts": "^6.1.32" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true - }, - "trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==", - "dev": true - }, - "trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true - }, - "trim-repeated": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.2" - } - }, - "trim-trailing-lines": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", - "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==", - "dev": true - }, - "triple-beam": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", - "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", - "dev": true - }, - "trough": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz", - "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==", - "dev": true - }, - "truncate-utf8-bytes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", - "dev": true, - "requires": { - "utf8-byte-length": "^1.0.1" - } - }, - "ts-api-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.2.tgz", - "integrity": "sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==", - "dev": true - }, - "ts-dedent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", - "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", - "dev": true - }, - "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", - "dev": true, - "requires": { - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - } - }, - "tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - } - } - }, - "tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==", - "dev": true - }, - "tuf-js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", - "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", - "dev": true, - "requires": { - "@tufjs/models": "1.0.4", - "debug": "^4.3.4", - "make-fetch-happen": "^11.1.1" - } - }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" - } - }, - "typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - } - }, - "typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - } - }, - "typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - } - }, - "typed-function": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-2.1.0.tgz", - "integrity": "sha512-bctQIOqx2iVbWGDGPWwIm18QScpu2XRmkC19D8rQGFsjKSgteq/o1hTZvIG/wuDq8fanpBDrLkLq+aEN/6y5XQ==", - "dev": true - }, - "typed-query-selector": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", - "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "typedoc": { - "version": "0.23.28", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.28.tgz", - "integrity": "sha512-9x1+hZWTHEQcGoP7qFmlo4unUoVJLB0H/8vfO/7wqTnZxg4kPuji9y3uRzEu0ZKez63OJAUmiGhUrtukC6Uj3w==", - "dev": true, - "requires": { - "lunr": "^2.3.9", - "marked": "^4.2.12", - "minimatch": "^7.1.3", - "shiki": "^0.14.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", - "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "typedoc-plugin-markdown": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.14.0.tgz", - "integrity": "sha512-UyQLkLRkfTFhLdhSf3RRpA3nNInGn+k6sll2vRXjflaMNwQAAiB61SYbisNZTg16t4K1dt1bPQMMGLrxS0GZ0Q==", - "dev": true, - "requires": { - "handlebars": "^4.7.7" - } - }, - "typedoc-plugin-resolve-crossmodule-references": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/typedoc-plugin-resolve-crossmodule-references/-/typedoc-plugin-resolve-crossmodule-references-0.3.3.tgz", - "integrity": "sha512-ZWWBy2WR8z9a6iXYGlyB3KrpV+JDdZv1mndYU6Eh6mInrfMCrQJi3Y5K9ihMBfuaBGB//le1nEmQLgzU3IO+dw==", - "dev": true - }, - "typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", - "dev": true - }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "ufo": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz", - "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==", - "dev": true - }, - "uglify-js": { - "version": "3.13.7", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.7.tgz", - "integrity": "sha512-1Psi2MmnZJbnEsgJJIlfnd7tFlJfitusmR7zDI8lXlFI0ACD4/Rm/xdrU8bh6zF0i74aiVoBtkRiFulkrmh3AA==", - "dev": true, - "optional": true - }, - "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, - "unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, - "requires": { - "buffer": "^5.2.1", - "through": "^2.3.8" - }, - "dependencies": { - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - } - } - }, - "undici": { - "version": "5.28.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", - "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", - "dev": true, - "requires": { - "@fastify/busboy": "^2.0.0" - } - }, - "undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" - }, - "unherit": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", - "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "xtend": "^4.0.1" - } - }, - "unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" - }, - "unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "requires": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==" - }, - "unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==" - }, - "unified": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-7.1.0.tgz", - "integrity": "sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "@types/vfile": "^3.0.0", - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^1.1.0", - "trough": "^1.0.0", - "vfile": "^3.0.0", - "x-is-string": "^0.1.0" - }, - "dependencies": { - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true - } - } - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "requires": { - "crypto-random-string": "^2.0.0" - } - }, - "unist-util-is": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", - "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", - "dev": true - }, - "unist-util-modify-children": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz", - "integrity": "sha512-GRi04yhng1WqBf5RBzPkOtWAadcZS2gvuOgNn/cyJBYNxtTuyYqTKN0eg4rC1YJwGnzrqfRB3dSKm8cNCjNirg==", - "dev": true, - "requires": { - "array-iterate": "^1.0.0" - } - }, - "unist-util-remove-position": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", - "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } - }, - "unist-util-stringify-position": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", - "dev": true - }, - "unist-util-visit": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", - "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", - "dev": true, - "requires": { - "unist-util-visit-parents": "^2.0.0" - } - }, - "unist-util-visit-parents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", - "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", - "dev": true, - "requires": { - "unist-util-is": "^3.0.0" - } - }, - "universal-user-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-2.1.0.tgz", - "integrity": "sha512-8itiX7G05Tu3mGDTdNY2fB4KJ8MgZLS54RdG6PkkfwMAavrXu1mV/lls/GABx9O3Rw4PnTtasxrvbMQoBYY92Q==", - "dev": true, - "requires": { - "os-name": "^3.0.0" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "unorm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", - "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - }, - "unplugin": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.7.1.tgz", - "integrity": "sha512-JqzORDAPxxs8ErLV4x+LL7bk5pk3YlcWqpSNsIkAZj972KzFZLClc/ekppahKkOczGkwIG6ElFgdOgOlK4tXZw==", - "dev": true, - "requires": { - "acorn": "^8.11.3", - "chokidar": "^3.5.3", - "webpack-sources": "^3.2.3", - "webpack-virtual-modules": "^0.6.1" - }, - "dependencies": { - "acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true - }, - "webpack-virtual-modules": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", - "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", - "dev": true - } - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", - "dev": true - } - } - }, - "untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true - }, - "unzipper": { - "version": "0.10.14", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", - "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", - "dev": true, - "requires": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - }, - "dependencies": { - "bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", - "dev": true - } - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, - "optional": true - }, - "update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "upper-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", - "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", - "requires": { - "tslib": "^2.0.3" - } - }, - "upper-case-first": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", - "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", - "requires": { - "tslib": "^2.0.3" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==" - }, - "url": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", - "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", - "dev": true, - "requires": { - "punycode": "^1.4.1", - "qs": "^6.12.3" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - }, - "qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dev": true, - "requires": { - "side-channel": "^1.0.6" - } - } - } - }, - "url-loader": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", - "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", - "dev": true, - "requires": { - "loader-utils": "^2.0.0", - "mime-types": "^2.1.27", - "schema-utils": "^3.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "url-template": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", - "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==", - "dev": true - }, - "urlpattern-polyfill": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "use-callback-ref": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.0.tgz", - "integrity": "sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==", - "requires": { - "tslib": "^2.0.0" - } - }, - "use-latest-callback": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.2.1.tgz", - "integrity": "sha512-QWlq8Is8BGWBf883QOEQP5HWYX/kMI+JTbJ5rdtvJLmXTIh9XoHIO3PQcmQl8BU44VKxow1kbQUHa6mQSMALDQ==" - }, - "use-memo-one": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.1.tgz", - "integrity": "sha512-oFfsyun+bP7RX8X2AskHNTxu+R3QdE/RC5IefMbqptmACAA/gfol1KDD5KRzPsGMa62sWxGZw+Ui43u6x4ddoQ==" - }, - "use-resize-observer": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-9.1.0.tgz", - "integrity": "sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==", - "dev": true, - "requires": { - "@juggle/resize-observer": "^3.3.1" - } - }, - "use-sidecar": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", - "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", - "requires": { - "detect-node-es": "^1.1.0", - "tslib": "^2.0.0" - } - }, - "use-subscription": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/use-subscription/-/use-subscription-1.5.0.tgz", - "integrity": "sha512-/FVRiB2I7NDjzWoNBYPt6YkkvleMm/lFtxj1hH6nX2TVrJ/5UTbovw9OE1efv2Zl0HoAYuTjM7zHd9OsABn5sg==", - "requires": { - "object-assign": "^4.1.1" - } - }, - "use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==" - }, - "userhome": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/userhome/-/userhome-1.0.0.tgz", - "integrity": "sha512-ayFKY3H+Pwfy4W98yPdtH1VqH4psDeyW8lYYFzfecR9d6hqLpqhecktvYR3SEEXt7vG0S1JEpciI3g94pMErig==", - "dev": true - }, - "utf8-byte-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", - "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==", - "dev": true - }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true - }, - "utility-types": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", - "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" - }, - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "validate-npm-package-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", - "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", - "dev": true, - "requires": { - "builtins": "^1.0.3" - } - }, - "validate.js": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/validate.js/-/validate.js-0.13.1.tgz", - "integrity": "sha512-PnFM3xiZ+kYmLyTiMgTYmU7ZHkjBZz2/+F0DaALc/uUtVzdCt1wAosvYJ5hFQi/hz8O4zb52FQhHZRC+uVkJ+g==", - "dev": true - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" - }, - "vfile": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz", - "integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==", - "dev": true, - "requires": { - "is-buffer": "^2.0.0", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-message": "^1.0.0" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true - } - } - }, - "vfile-location": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", - "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==", - "dev": true - }, - "vfile-message": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", - "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", - "dev": true, - "requires": { - "unist-util-stringify-position": "^1.1.1" - } - }, - "vlq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", - "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==" - }, - "vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", - "dev": true - }, - "vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "dev": true - }, - "vscode-textmate": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", - "dev": true - }, - "w3c-xmlserializer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", - "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "dev": true, - "requires": { - "xml-name-validator": "^5.0.0" - } - }, - "wait-port": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/wait-port/-/wait-port-1.1.0.tgz", - "integrity": "sha512-3e04qkoN3LxTMLakdqeWth8nih8usyg+sf1Bgdf9wwUkp05iuK1eSY/QpLvscT/+F/gA89+LpUmmgBtesbqI2Q==", - "dev": true, - "requires": { - "chalk": "^4.1.2", - "commander": "^9.3.0", - "debug": "^4.3.4" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "requires": { - "makeerror": "1.0.12" - } - }, - "warn-once": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz", - "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==" - }, - "watchpack": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", - "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", - "dev": true, - "requires": { - "chokidar": "^3.4.1", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0", - "watchpack-chokidar2": "^2.0.1" - } - }, - "watchpack-chokidar2": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", - "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", - "dev": true, - "optional": true, - "requires": { - "chokidar": "^2.1.8" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "optional": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, - "optional": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "optional": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "optional": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "optional": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "dev": true, - "optional": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", - "dev": true, - "optional": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "optional": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - } - } - }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "requires": { - "defaults": "^1.0.3" - } - }, - "web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "dev": true - }, - "webdriver": { - "version": "8.16.20", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-8.16.20.tgz", - "integrity": "sha512-3Dynj9pfTqmbDadqmMmD/sQgGFwho92zQPGgpAqLUMebE/qEkraoIfRWdbi2tw1ityiThOJVPTXfwsY/bpvknw==", - "dev": true, - "requires": { - "@types/node": "^20.1.0", - "@types/ws": "^8.5.3", - "@wdio/config": "8.16.20", - "@wdio/logger": "8.16.17", - "@wdio/protocols": "8.16.5", - "@wdio/types": "8.16.12", - "@wdio/utils": "8.16.17", - "deepmerge-ts": "^5.1.0", - "got": "^ 12.6.1", - "ky": "^0.33.0", - "ws": "^8.8.0" - }, - "dependencies": { - "@sindresorhus/is": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", - "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", - "dev": true - }, - "@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dev": true, - "requires": { - "defer-to-connect": "^2.0.1" - } - }, - "@types/node": { - "version": "20.16.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", - "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", - "dev": true, - "requires": { - "undici-types": "~6.19.2" - } - }, - "cacheable-lookup": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", - "dev": true - }, - "cacheable-request": { - "version": "10.2.14", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", - "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", - "dev": true, - "requires": { - "@types/http-cache-semantics": "^4.0.2", - "get-stream": "^6.0.1", - "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.3", - "mimic-response": "^4.0.0", - "normalize-url": "^8.0.0", - "responselike": "^3.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "got": { - "version": "12.6.1", - "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", - "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", - "dev": true, - "requires": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - } - }, - "http2-wrapper": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", - "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", - "dev": true, - "requires": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" - } - }, - "lowercase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", - "dev": true - }, - "mimic-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", - "dev": true - }, - "normalize-url": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", - "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", - "dev": true - }, - "p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "dev": true - }, - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true - }, - "responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", - "dev": true, - "requires": { - "lowercase-keys": "^3.0.0" - } - }, - "undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true - }, - "ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true - } - } - }, - "webdriverio": { - "version": "8.16.20", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.16.20.tgz", - "integrity": "sha512-2xSJDrMxwPF1kucB/r7Wc8yF689GGi7iSKrog7vkkoIiRY25vd3U129iN2mTYgNDyM6SM0kw+GP5W1s73khpYw==", - "dev": true, - "requires": { - "@types/node": "^20.1.0", - "@wdio/config": "8.16.20", - "@wdio/logger": "8.16.17", - "@wdio/protocols": "8.16.5", - "@wdio/repl": "8.10.1", - "@wdio/types": "8.16.12", - "@wdio/utils": "8.16.17", - "archiver": "^6.0.0", - "aria-query": "^5.0.0", - "css-shorthand-properties": "^1.1.1", - "css-value": "^0.0.1", - "devtools-protocol": "^0.0.1203626", - "grapheme-splitter": "^1.0.2", - "import-meta-resolve": "^3.0.0", - "is-plain-obj": "^4.1.0", - "lodash.clonedeep": "^4.5.0", - "lodash.zip": "^4.2.0", - "minimatch": "^9.0.0", - "puppeteer-core": "^20.9.0", - "query-selector-shadow-dom": "^1.0.0", - "resq": "^1.9.1", - "rgb2hex": "0.2.5", - "serialize-error": "^11.0.1", - "webdriver": "8.16.20" - }, - "dependencies": { - "@types/node": { - "version": "20.16.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", - "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", - "dev": true, - "requires": { - "undici-types": "~6.19.2" - } - }, - "aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "devtools-protocol": { - "version": "0.0.1203626", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1203626.tgz", - "integrity": "sha512-nEzHZteIUZfGCZtTiS1fRpC8UZmsfD1SiyPvaUNvS13dvKf666OAm8YTi0+Ca3n1nLEyu49Cy4+dPWpaHFJk9g==", - "dev": true - }, - "is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "dev": true - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "puppeteer-core": { - "version": "20.9.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-20.9.0.tgz", - "integrity": "sha512-H9fYZQzMTRrkboEfPmf7m3CLDN6JvbxXA3qTtS+dFt27tR+CsFHzPsT6pzp6lYL6bJbAPaR0HaPO6uSi+F94Pg==", - "dev": true, - "requires": { - "@puppeteer/browsers": "1.4.6", - "chromium-bidi": "0.4.16", - "cross-fetch": "4.0.0", - "debug": "4.3.4", - "devtools-protocol": "0.0.1147663", - "ws": "8.13.0" - }, - "dependencies": { - "devtools-protocol": { - "version": "0.0.1147663", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1147663.tgz", - "integrity": "sha512-hyWmRrexdhbZ1tcJUGpO95ivbRhWXz++F4Ko+n21AY5PNln2ovoJw+8ZMNDTtip+CNFQfrtLVh/w4009dXO/eQ==", - "dev": true - } - } - }, - "serialize-error": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-11.0.3.tgz", - "integrity": "sha512-2G2y++21dhj2R7iHAdd0FIzjGwuKZld+7Pl/bTU6YIkrC2ZMbVUjm+luj6A6V34Rv9XfKJDKpTWu9W4Gse1D9g==", - "dev": true, - "requires": { - "type-fest": "^2.12.2" - } - }, - "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true - }, - "undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true - }, - "ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true - } - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "webpack": { - "version": "5.88.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", - "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@xtuc/long": "4.2.2" - } - }, - "acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - } - } - }, - "webpack-bundle-analyzer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.9.1.tgz", - "integrity": "sha512-jnd6EoYrf9yMxCyYDPj8eutJvtjQNp8PHmni/e/ulydHBWhT5J3menXt3HEkScsu9YqMAcG4CfFjs3rj5pVU1w==", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "0.5.7", - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "commander": "^7.2.0", - "escape-string-regexp": "^4.0.0", - "gzip-size": "^6.0.0", - "is-plain-object": "^5.0.0", - "lodash.debounce": "^4.0.8", - "lodash.escape": "^4.0.1", - "lodash.flatten": "^4.4.0", - "lodash.invokemap": "^4.6.0", - "lodash.pullall": "^4.2.0", - "lodash.uniqby": "^4.7.0", - "opener": "^1.5.2", - "picocolors": "^1.0.0", - "sirv": "^2.0.3", - "ws": "^7.3.1" - }, - "dependencies": { - "acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true - }, - "acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "requires": { - "acorn": "^8.11.0" - } - }, - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, - "requires": { - "duplexer": "^0.1.2" - } - } - } - }, - "webpack-cli": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", - "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^2.1.1", - "@webpack-cli/info": "^2.0.2", - "@webpack-cli/serve": "^2.0.5", - "colorette": "^2.0.14", - "commander": "^10.0.1", - "cross-spawn": "^7.0.3", - "envinfo": "^7.7.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^3.1.1", - "rechoir": "^0.8.0", - "webpack-merge": "^5.7.3" - }, - "dependencies": { - "colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "webpack-dev-middleware": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz", - "integrity": "sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw==", - "dev": true, - "requires": { - "colorette": "^2.0.10", - "memfs": "^3.4.12", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - } - } - }, - "webpack-dev-server": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", - "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", - "dev": true, - "requires": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.13.0" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - }, - "webpack-dev-middleware": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", - "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", - "dev": true, - "requires": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - } - }, - "ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true - } - } - }, - "webpack-hot-middleware": { - "version": "2.26.1", - "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz", - "integrity": "sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A==", - "dev": true, - "requires": { - "ansi-html-community": "0.0.8", - "html-entities": "^2.1.0", - "strip-ansi": "^6.0.0" - } - }, - "webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - } - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true - }, - "webpack-virtual-modules": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", - "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", - "dev": true - }, - "websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true - }, - "whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "dev": true, - "requires": { - "iconv-lite": "0.6.3" - } - }, - "whatwg-fetch": { - "version": "3.6.20", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", - "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" - }, - "whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "dev": true - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "whatwg-url-without-unicode": { - "version": "8.0.0-1", - "resolved": "https://registry.npmjs.org/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-1.tgz", - "integrity": "sha512-0Uy8mjsG5O8Y53327XL+ZqsrMdxO1CL/6m840SmW5iyRWFvU2zlxS2RzpD3pFFVKYOKCmsKn5JKzWxQ+bImnWA==", - "dev": true, - "requires": { - "webidl-conversions": "^5.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true - } - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - } - }, - "which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" - }, - "which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - } - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "windows-release": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.2.0.tgz", - "integrity": "sha512-QTlz2hKLrdqukrsapKsINzqMgOUpQW268eJ0OaOpJN32h272waxR9fkB9VoWRtK7uKHG5EHJcTXQBD8XZVJkFA==", - "dev": true, - "requires": { - "execa": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "winston": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.9.0.tgz", - "integrity": "sha512-jW51iW/X95BCW6MMtZWr2jKQBP4hV5bIDq9QrIjfDk6Q9QuxvTKEAlpUNAzP+HYHFFCeENhph16s0zEunu4uuQ==", - "dev": true, - "requires": { - "@colors/colors": "1.5.0", - "@dabh/diagnostics": "^2.0.2", - "async": "^3.2.3", - "is-stream": "^2.0.0", - "logform": "^2.4.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "safe-stable-stringify": "^2.3.1", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.5.0" - }, - "dependencies": { - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "winston-transport": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", - "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", - "dev": true, - "requires": { - "logform": "^2.3.2", - "readable-stream": "^3.6.0", - "triple-beam": "^1.3.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true - }, - "worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "write-json-file": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", - "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", - "dev": true, - "requires": { - "detect-indent": "^5.0.0", - "graceful-fs": "^4.1.15", - "make-dir": "^2.1.0", - "pify": "^4.0.1", - "sort-keys": "^2.0.0", - "write-file-atomic": "^2.4.2" - }, - "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "write-pkg": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-4.0.0.tgz", - "integrity": "sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==", - "dev": true, - "requires": { - "sort-keys": "^2.0.0", - "type-fest": "^0.4.1", - "write-json-file": "^3.2.0" - }, - "dependencies": { - "type-fest": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", - "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", - "dev": true - } - } - }, - "ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==" - }, - "x-is-string": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", - "integrity": "sha512-GojqklwG8gpzOVEVki5KudKNoq7MbbjYZCbyWzEz7tyPA7eleiE0+ePwOWQQRb5fm86rD3S8Tc0tSFf3AOv50w==", - "dev": true - }, - "xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true - }, - "xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", - "dev": true - }, - "xml-name-validator": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", - "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", - "dev": true - }, - "xmlbuilder": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", - "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", - "dev": true - }, - "xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y-indexeddb": { - "version": "9.0.11", - "resolved": "https://registry.npmjs.org/y-indexeddb/-/y-indexeddb-9.0.11.tgz", - "integrity": "sha512-HOKQ70qW1h2WJGtOKu9rE8fbX86ExVZedecndMuhwax3yM4DQsQzCTGHt/jvTrFZr/9Ahvd8neD6aZ4dMMjtdg==", - "requires": { - "lib0": "^0.2.74" - } - }, - "y-protocols": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.5.tgz", - "integrity": "sha512-Wil92b7cGk712lRHDqS4T90IczF6RkcvCwAD0A2OPg+adKmOe+nOiT/N2hvpQIWS3zfjmtL4CPaH5sIW1Hkm/A==", - "requires": { - "lib0": "^0.2.42" - } - }, - "y-webrtc": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/y-webrtc/-/y-webrtc-10.2.5.tgz", - "integrity": "sha512-ZyBNvTI5L28sQ2PQI0T/JvyWgvuTq05L21vGkIlcvNLNSJqAaLCBJRe3FHEqXoaogqWmRcEAKGfII4ErNXMnNw==", - "requires": { - "lib0": "^0.2.42", - "simple-peer": "^9.11.0", - "ws": "^7.2.0", - "y-protocols": "^1.0.5" - } - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "dependencies": { - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - } - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "yjs": { - "version": "13.6.7", - "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.7.tgz", - "integrity": "sha512-mCZTh4kjvUS2DnaktsYN6wLH3WZCJBLqrTdkWh1bIDpA/sB/GNFaLA/dyVJj2Hc7KwONuuoC/vWe9bwBBosZLQ==", - "requires": { - "lib0": "^0.2.74" - } - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" - }, - "zip-stream": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-5.0.1.tgz", - "integrity": "sha512-UfZ0oa0C8LI58wJ+moL46BDIMgCQbnsb+2PoiJYtonhBsMh2bq1eRBVkvjfVsqbEHd9/EgKPUuL9saSSsec8OA==", - "dev": true, - "requires": { - "archiver-utils": "^4.0.1", - "compress-commons": "^5.0.1", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", - "dev": true - } } } From dc11a305caa0f9d1593400fe16a84ebce363488a Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Mon, 7 Oct 2024 19:37:47 +0200 Subject: [PATCH 1099/1908] Interactivity API: Allow "default" suffix values (#65815) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix an issue where "default" could not be used as "suffix" values in Interactivity API directives, for example in a directive like: data-wp-class--default="…" --- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- .../directive-class/render.php | 20 +- .../directive-class/view.js | 4 +- .../interactive-blocks/directive-init/view.js | 2 +- .../directive-on-document/view.js | 2 +- .../directive-on-window/view.js | 2 +- .../interactive-blocks/directive-run/view.js | 4 +- .../directive-watch/view.js | 2 +- .../interactive-blocks/tovdom-islands/view.js | 2 +- packages/interactivity/CHANGELOG.md | 1 + packages/interactivity/src/directives.tsx | 247 +++++++++--------- packages/interactivity/src/hooks.tsx | 30 ++- packages/interactivity/src/vdom.ts | 38 +-- .../interactivity/directive-class.spec.ts | 10 + 13 files changed, 202 insertions(+), 162 deletions(-) diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-class/render.php b/packages/e2e-tests/plugins/interactive-blocks/directive-class/render.php index 4e543b0588cfc9..3f03ba210470f0 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-class/render.php +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-class/render.php @@ -59,17 +59,17 @@ class="foo bar baz" data-testid="can toggle class when class attribute is missing" ></div> - <div data-wp-context='{ "falseValue": false }'> + <div data-wp-context='{ "value": false }'> <div class="foo" - data-wp-class--foo="context.falseValue" + data-wp-class--foo="context.value" data-testid="can use context values" ></div> <button - data-wp-on--click="actions.toggleContextFalseValue" + data-wp-on--click="actions.toggleContextValue" data-testid="toggle context false value" > - Toggle context falseValue + Toggle context value </button> </div> @@ -83,4 +83,16 @@ class="foo" data-testid="can use classes with several dashes" ></div> + <div data-wp-context='{ "value": false }'> + <div + data-wp-class--default="context.value" + data-testid="class name default" + ></div> + <button + data-wp-on--click="actions.toggleContextValue" + data-testid="toggle class name default" + > + Toggle context val + </button> + </div> </div> diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-class/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-class/view.js index f008ae910673fd..9ae5207c0e05c5 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-class/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-class/view.js @@ -15,9 +15,9 @@ const { state } = store( 'directive-class', { toggleFalseValue: () => { state.falseValue = ! state.falseValue; }, - toggleContextFalseValue: () => { + toggleContextValue: () => { const context = getContext(); - context.falseValue = ! context.falseValue; + context.value = ! context.value; }, }, } ); diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-init/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-init/view.js index 9990e2743c8799..a8c70a4a907207 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-init/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-init/view.js @@ -12,7 +12,7 @@ const { directive } = privateApis( directive( 'show-mock', ( { directives: { 'show-mock': showMock }, element, evaluate } ) => { - const entry = showMock.find( ( { suffix } ) => suffix === 'default' ); + const entry = showMock.find( ( { suffix } ) => suffix === null ); if ( ! evaluate( entry ) ) { return null; } diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/view.js index 19ffc2a530193b..b9689ac978f85f 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/view.js @@ -12,7 +12,7 @@ const { directive } = privateApis( directive( 'show-mock', ( { directives: { 'show-mock': showMock }, element, evaluate } ) => { - const entry = showMock.find( ( { suffix } ) => suffix === 'default' ); + const entry = showMock.find( ( { suffix } ) => suffix === null ); if ( ! evaluate( entry ) ) { return null; } diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/view.js index e22379ad4d0775..ef72e266e10759 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/view.js @@ -12,7 +12,7 @@ const { directive } = privateApis( directive( 'show-mock', ( { directives: { 'show-mock': showMock }, element, evaluate } ) => { - const entry = showMock.find( ( { suffix } ) => suffix === 'default' ); + const entry = showMock.find( ( { suffix } ) => suffix === null ); if ( ! evaluate( entry ) ) { return null; } diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-run/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-run/view.js index cb9be34b2460a8..125ac392042306 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-run/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-run/view.js @@ -21,9 +21,7 @@ directive( element, evaluate, } ) => { - const entry = showChildren.find( - ( { suffix } ) => suffix === 'default' - ); + const entry = showChildren.find( ( { suffix } ) => suffix === null ); return evaluate( entry ) ? element : cloneElement( element, { children: null } ); diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-watch/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-watch/view.js index af2d452a104319..ad035811a0bcd7 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-watch/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-watch/view.js @@ -12,7 +12,7 @@ const { directive } = privateApis( directive( 'show-mock', ( { directives: { 'show-mock': showMock }, element, evaluate } ) => { - const entry = showMock.find( ( { suffix } ) => suffix === 'default' ); + const entry = showMock.find( ( { suffix } ) => suffix === null ); if ( ! evaluate( entry ) ) { return null; } diff --git a/packages/e2e-tests/plugins/interactive-blocks/tovdom-islands/view.js b/packages/e2e-tests/plugins/interactive-blocks/tovdom-islands/view.js index 2993a273486c2b..8016e931624a16 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/tovdom-islands/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/tovdom-islands/view.js @@ -12,7 +12,7 @@ const { directive, h } = privateApis( directive( 'show-mock', ( { directives: { 'show-mock': showMock }, element, evaluate } ) => { - const entry = showMock.find( ( { suffix } ) => suffix === 'default' ); + const entry = showMock.find( ( { suffix } ) => suffix === null ); if ( ! evaluate( entry ) ) { element.props.children = h( diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index f4431d108dc360..7a510bd89b0f78 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -4,6 +4,7 @@ ### Bug Fixes +- Fix an issue where "default" could not be used as a directive suffix ([#65815](https://github.com/WordPress/gutenberg/pull/65815)). - Correctly handle lazily added, deeply nested properties with `deepMerge()` ([#65465](https://github.com/WordPress/gutenberg/pull/65465)). ## 6.9.0 (2024-10-03) diff --git a/packages/interactivity/src/directives.tsx b/packages/interactivity/src/directives.tsx index 340880954683da..31e07d095e0a4c 100644 --- a/packages/interactivity/src/directives.tsx +++ b/packages/interactivity/src/directives.tsx @@ -18,7 +18,14 @@ import { splitTask, isPlainObject, } from './utils'; -import { directive, getEvaluate, type DirectiveEntry } from './hooks'; +import { + directive, + getEvaluate, + isDefaultDirectiveSuffix, + isNonDefaultDirectiveSuffix, + type DirectiveCallback, + type DirectiveEntry, +} from './hooks'; import { getScope } from './scopes'; import { proxifyState, proxifyContext, deepMerge } from './proxies'; @@ -86,11 +93,13 @@ const cssStringToObject = ( * * @param type 'window' or 'document' */ -const getGlobalEventDirective = ( type: 'window' | 'document' ) => { +const getGlobalEventDirective = ( + type: 'window' | 'document' +): DirectiveCallback => { return ( { directives, evaluate } ) => { directives[ `on-${ type }` ] - .filter( ( { suffix } ) => suffix !== 'default' ) - .forEach( ( entry: DirectiveEntry ) => { + .filter( isNonDefaultDirectiveSuffix ) + .forEach( ( entry ) => { const eventName = entry.suffix.split( '--', 1 )[ 0 ]; useInit( () => { const cb = ( event: Event ) => evaluate( entry, event ); @@ -108,11 +117,13 @@ const getGlobalEventDirective = ( type: 'window' | 'document' ) => { * * @param type 'window' or 'document' */ -const getGlobalAsyncEventDirective = ( type: 'window' | 'document' ) => { +const getGlobalAsyncEventDirective = ( + type: 'window' | 'document' +): DirectiveCallback => { return ( { directives, evaluate } ) => { directives[ `on-async-${ type }` ] - .filter( ( { suffix } ) => suffix !== 'default' ) - .forEach( ( entry: DirectiveEntry ) => { + .filter( isNonDefaultDirectiveSuffix ) + .forEach( ( entry ) => { const eventName = entry.suffix.split( '--', 1 )[ 0 ]; useInit( () => { const cb = async ( event: Event ) => { @@ -139,9 +150,7 @@ export default () => { context: inheritedContext, } ) => { const { Provider } = inheritedContext; - const defaultEntry = context.find( - ( { suffix } ) => suffix === 'default' - ); + const defaultEntry = context.find( isDefaultDirectiveSuffix ); const { client: inheritedClient, server: inheritedServer } = useContext( inheritedContext ); @@ -256,15 +265,13 @@ export default () => { // data-wp-on--[event] directive( 'on', ( { directives: { on }, element, evaluate } ) => { const events = new Map< string, Set< DirectiveEntry > >(); - on.filter( ( { suffix } ) => suffix !== 'default' ).forEach( - ( entry ) => { - const event = entry.suffix.split( '--' )[ 0 ]; - if ( ! events.has( event ) ) { - events.set( event, new Set< DirectiveEntry >() ); - } - events.get( event )!.add( entry ); + on.filter( isNonDefaultDirectiveSuffix ).forEach( ( entry ) => { + const event = entry.suffix.split( '--' )[ 0 ]; + if ( ! events.has( event ) ) { + events.set( event, new Set< DirectiveEntry >() ); } - ); + events.get( event )!.add( entry ); + } ); events.forEach( ( entries, eventType ) => { const existingHandler = element.props[ `on${ eventType }` ]; @@ -308,7 +315,7 @@ export default () => { ( { directives: { 'on-async': onAsync }, element, evaluate } ) => { const events = new Map< string, Set< DirectiveEntry > >(); onAsync - .filter( ( { suffix } ) => suffix !== 'default' ) + .filter( isNonDefaultDirectiveSuffix ) .forEach( ( entry ) => { const event = entry.suffix.split( '--' )[ 0 ]; if ( ! events.has( event ) ) { @@ -350,7 +357,7 @@ export default () => { 'class', ( { directives: { class: classNames }, element, evaluate } ) => { classNames - .filter( ( { suffix } ) => suffix !== 'default' ) + .filter( isNonDefaultDirectiveSuffix ) .forEach( ( entry ) => { const className = entry.suffix; const result = evaluate( entry ); @@ -391,119 +398,112 @@ export default () => { // data-wp-style--[style-prop] directive( 'style', ( { directives: { style }, element, evaluate } ) => { - style - .filter( ( { suffix } ) => suffix !== 'default' ) - .forEach( ( entry ) => { - const styleProp = entry.suffix; - const result = evaluate( entry ); - element.props.style = element.props.style || {}; - if ( typeof element.props.style === 'string' ) { - element.props.style = cssStringToObject( - element.props.style - ); - } + style.filter( isNonDefaultDirectiveSuffix ).forEach( ( entry ) => { + const styleProp = entry.suffix; + const result = evaluate( entry ); + element.props.style = element.props.style || {}; + if ( typeof element.props.style === 'string' ) { + element.props.style = cssStringToObject( element.props.style ); + } + if ( ! result ) { + delete element.props.style[ styleProp ]; + } else { + element.props.style[ styleProp ] = result; + } + + useInit( () => { + /* + * This seems necessary because Preact doesn't change the styles on + * the hydration, so we have to do it manually. It doesn't need deps + * because it only needs to do it the first time. + */ if ( ! result ) { - delete element.props.style[ styleProp ]; + ( + element.ref as RefObject< HTMLElement > + ).current!.style.removeProperty( styleProp ); } else { - element.props.style[ styleProp ] = result; + ( element.ref as RefObject< HTMLElement > ).current!.style[ + styleProp + ] = result; } - - useInit( () => { - /* - * This seems necessary because Preact doesn't change the styles on - * the hydration, so we have to do it manually. It doesn't need deps - * because it only needs to do it the first time. - */ - if ( ! result ) { - ( - element.ref as RefObject< HTMLElement > - ).current!.style.removeProperty( styleProp ); - } else { - ( - element.ref as RefObject< HTMLElement > - ).current!.style[ styleProp ] = result; - } - } ); } ); + } ); } ); // data-wp-bind--[attribute] directive( 'bind', ( { directives: { bind }, element, evaluate } ) => { - bind.filter( ( { suffix } ) => suffix !== 'default' ).forEach( - ( entry ) => { - const attribute = entry.suffix; - const result = evaluate( entry ); - element.props[ attribute ] = result; + bind.filter( isNonDefaultDirectiveSuffix ).forEach( ( entry ) => { + const attribute = entry.suffix; + const result = evaluate( entry ); + element.props[ attribute ] = result; + + /* + * This is necessary because Preact doesn't change the attributes on the + * hydration, so we have to do it manually. It only needs to do it the + * first time. After that, Preact will handle the changes. + */ + useInit( () => { + const el = ( element.ref as RefObject< HTMLElement > ).current!; /* - * This is necessary because Preact doesn't change the attributes on the - * hydration, so we have to do it manually. It only needs to do it the - * first time. After that, Preact will handle the changes. + * We set the value directly to the corresponding HTMLElement instance + * property excluding the following special cases. We follow Preact's + * logic: https://github.com/preactjs/preact/blob/ea49f7a0f9d1ff2c98c0bdd66aa0cbc583055246/src/diff/props.js#L110-L129 */ - useInit( () => { - const el = ( element.ref as RefObject< HTMLElement > ) - .current!; - - /* - * We set the value directly to the corresponding HTMLElement instance - * property excluding the following special cases. We follow Preact's - * logic: https://github.com/preactjs/preact/blob/ea49f7a0f9d1ff2c98c0bdd66aa0cbc583055246/src/diff/props.js#L110-L129 - */ - if ( attribute === 'style' ) { - if ( typeof result === 'string' ) { - el.style.cssText = result; - } - return; - } else if ( - attribute !== 'width' && - attribute !== 'height' && - attribute !== 'href' && - attribute !== 'list' && - attribute !== 'form' && - /* - * The value for `tabindex` follows the parsing rules for an - * integer. If that fails, or if the attribute isn't present, then - * the browsers should "follow platform conventions to determine if - * the element should be considered as a focusable area", - * practically meaning that most elements get a default of `-1` (not - * focusable), but several also get a default of `0` (focusable in - * order after all elements with a positive `tabindex` value). - * - * @see https://html.spec.whatwg.org/#tabindex-value - */ - attribute !== 'tabIndex' && - attribute !== 'download' && - attribute !== 'rowSpan' && - attribute !== 'colSpan' && - attribute !== 'role' && - attribute in el - ) { - try { - el[ attribute ] = - result === null || result === undefined - ? '' - : result; - return; - } catch ( err ) {} + if ( attribute === 'style' ) { + if ( typeof result === 'string' ) { + el.style.cssText = result; } + return; + } else if ( + attribute !== 'width' && + attribute !== 'height' && + attribute !== 'href' && + attribute !== 'list' && + attribute !== 'form' && /* - * aria- and data- attributes have no boolean representation. - * A `false` value is different from the attribute not being - * present, so we can't remove it. - * We follow Preact's logic: https://github.com/preactjs/preact/blob/ea49f7a0f9d1ff2c98c0bdd66aa0cbc583055246/src/diff/props.js#L131C24-L136 + * The value for `tabindex` follows the parsing rules for an + * integer. If that fails, or if the attribute isn't present, then + * the browsers should "follow platform conventions to determine if + * the element should be considered as a focusable area", + * practically meaning that most elements get a default of `-1` (not + * focusable), but several also get a default of `0` (focusable in + * order after all elements with a positive `tabindex` value). + * + * @see https://html.spec.whatwg.org/#tabindex-value */ - if ( - result !== null && - result !== undefined && - ( result !== false || attribute[ 4 ] === '-' ) - ) { - el.setAttribute( attribute, result ); - } else { - el.removeAttribute( attribute ); - } - } ); - } - ); + attribute !== 'tabIndex' && + attribute !== 'download' && + attribute !== 'rowSpan' && + attribute !== 'colSpan' && + attribute !== 'role' && + attribute in el + ) { + try { + el[ attribute ] = + result === null || result === undefined + ? '' + : result; + return; + } catch ( err ) {} + } + /* + * aria- and data- attributes have no boolean representation. + * A `false` value is different from the attribute not being + * present, so we can't remove it. + * We follow Preact's logic: https://github.com/preactjs/preact/blob/ea49f7a0f9d1ff2c98c0bdd66aa0cbc583055246/src/diff/props.js#L131C24-L136 + */ + if ( + result !== null && + result !== undefined && + ( result !== false || attribute[ 4 ] === '-' ) + ) { + el.setAttribute( attribute, result ); + } else { + el.removeAttribute( attribute ); + } + } ); + } ); } ); // data-wp-ignore @@ -528,7 +528,7 @@ export default () => { // data-wp-text directive( 'text', ( { directives: { text }, element, evaluate } ) => { - const entry = text.find( ( { suffix } ) => suffix === 'default' ); + const entry = text.find( isDefaultDirectiveSuffix ); if ( ! entry ) { element.props.children = null; return; @@ -565,12 +565,13 @@ export default () => { const inheritedValue = useContext( inheritedContext ); const [ entry ] = each; - const { namespace, suffix } = entry; + const { namespace } = entry; const list = evaluate( entry ); + const itemProp = isNonDefaultDirectiveSuffix( entry ) + ? kebabToCamelCase( entry.suffix ) + : 'item'; return list.map( ( item ) => { - const itemProp = - suffix === 'default' ? 'item' : kebabToCamelCase( suffix ); const itemContext = proxifyContext( proxifyState( namespace, {} ), inheritedValue.client[ namespace ] diff --git a/packages/interactivity/src/hooks.tsx b/packages/interactivity/src/hooks.tsx index 6b55ec014aa799..e9b9f48ba3518e 100644 --- a/packages/interactivity/src/hooks.tsx +++ b/packages/interactivity/src/hooks.tsx @@ -23,9 +23,29 @@ import { getScope, setScope, resetScope, type Scope } from './scopes'; export interface DirectiveEntry { value: string | object; namespace: string; + suffix: string | null; +} + +export interface NonDefaultSuffixDirectiveEntry extends DirectiveEntry { suffix: string; } +export interface DefaultSuffixDirectiveEntry extends DirectiveEntry { + suffix: null; +} + +export function isNonDefaultDirectiveSuffix( + entry: DirectiveEntry +): entry is NonDefaultSuffixDirectiveEntry { + return entry.suffix !== null; +} + +export function isDefaultDirectiveSuffix( + entry: DirectiveEntry +): entry is DefaultSuffixDirectiveEntry { + return entry.suffix === null; +} + type DirectiveEntries = Record< string, DirectiveEntry[] >; interface DirectiveArgs { @@ -56,7 +76,7 @@ interface DirectiveArgs { evaluate: Evaluate; } -interface DirectiveCallback { +export interface DirectiveCallback { ( args: DirectiveArgs ): VNode< any > | null | void; } @@ -107,7 +127,7 @@ const directivePriorities: Record< string, number > = {}; * directive( * 'alert', // Name without the `data-wp-` prefix. * ( { directives: { alert }, element, evaluate } ) => { - * const defaultEntry = alert.find( entry => entry.suffix === 'default' ); + * const defaultEntry = alert.find( isDefaultDirectiveSuffix ); * element.props.onclick = () => { alert( evaluate( defaultEntry ) ); } * } * ) @@ -126,7 +146,7 @@ const directivePriorities: Record< string, number > = {}; * </div> * ``` * Note that, in the previous example, the directive callback gets the path - * value (`state.alert`) from the directive entry with suffix `default`. A + * value (`state.alert`) from the directive entry with suffix `null`. A * custom suffix can also be specified by appending `--` to the directive * attribute, followed by the suffix, like in the following HTML snippet: * @@ -311,9 +331,7 @@ options.vnode = ( vnode: VNode< any > ) => { const props = vnode.props; const directives = props.__directives; if ( directives.key ) { - vnode.key = directives.key.find( - ( { suffix } ) => suffix === 'default' - ).value; + vnode.key = directives.key.find( isDefaultDirectiveSuffix ).value; } delete props.__directives; const priorityLevels = getPriorityLevels( directives ); diff --git a/packages/interactivity/src/vdom.ts b/packages/interactivity/src/vdom.ts index 98deca656cfa6c..b533a130e4a6f0 100644 --- a/packages/interactivity/src/vdom.ts +++ b/packages/interactivity/src/vdom.ts @@ -7,6 +7,7 @@ import { h, type ComponentChild, type JSX } from 'preact'; */ import { directivePrefix as p } from './constants'; import { warn } from './utils'; +import { type DirectiveEntry } from './hooks'; const ignoreAttr = `data-${ p }-ignore`; const islandAttr = `data-${ p }-interactive`; @@ -139,26 +140,25 @@ export function toVdom( root: Node ): Array< ComponentChild > { } if ( directives.length ) { - props.__directives = directives.reduce( - ( obj, [ name, ns, value ] ) => { - const directiveMatch = directiveParser.exec( name ); - if ( directiveMatch === null ) { - warn( `Found malformed directive name: ${ name }.` ); - return obj; - } - const prefix = directiveMatch[ 1 ] || ''; - const suffix = directiveMatch[ 2 ] || 'default'; - - obj[ prefix ] = obj[ prefix ] || []; - obj[ prefix ].push( { - namespace: ns ?? currentNamespace(), - value, - suffix, - } ); + props.__directives = directives.reduce< + Record< string, Array< DirectiveEntry > > + >( ( obj, [ name, ns, value ] ) => { + const directiveMatch = directiveParser.exec( name ); + if ( directiveMatch === null ) { + warn( `Found malformed directive name: ${ name }.` ); return obj; - }, - {} - ); + } + const prefix = directiveMatch[ 1 ] || ''; + const suffix = directiveMatch[ 2 ] || null; + + obj[ prefix ] = obj[ prefix ] || []; + obj[ prefix ].push( { + namespace: ns ?? currentNamespace()!, + value: value as DirectiveEntry[ 'value' ], + suffix, + } ); + return obj; + }, {} ); } // @ts-expect-error Fixed in upcoming preact release https://github.com/preactjs/preact/pull/4334 diff --git a/test/e2e/specs/interactivity/directive-class.spec.ts b/test/e2e/specs/interactivity/directive-class.spec.ts index b7e085aba15143..96b725568767ae 100644 --- a/test/e2e/specs/interactivity/directive-class.spec.ts +++ b/test/e2e/specs/interactivity/directive-class.spec.ts @@ -108,4 +108,14 @@ test.describe( 'data-wp-class', () => { const el = page.getByTestId( 'can use classes with several dashes' ); await expect( el ).toHaveClass( 'main-bg----color' ); } ); + + test( 'can use "default" as a class name', async ( { page } ) => { + const el = page.getByTestId( 'class name default' ); + const btn = page.getByTestId( 'toggle class name default' ); + await expect( el ).not.toHaveClass( 'default' ); + await btn.click(); + await expect( el ).toHaveClass( 'default' ); + await btn.click(); + await expect( el ).not.toHaveClass( 'default' ); + } ); } ); From e4f1150196da1c88c1fe1e8f1943a3ca2a08e1f0 Mon Sep 17 00:00:00 2001 From: Dani Guardiola <hi@daniguardio.la> Date: Mon, 7 Oct 2024 21:55:47 +0200 Subject: [PATCH 1100/1908] Tabs: unify vertical tabs styles (#65387) * Remove inserter pattern overrides * Make font weights 400 (inactive) and 500 (active) * Apply styles only when vertical. * Make vertical indicator theme accent color at 4% opacity. * Make height 48px. * Add radius. * Also use hover styles in focus-visible. * Fix indicator not visible in inserter > patterns/media. * Adjust padding. * Tweak focus ring. * Wrap long labels. * Add chevron and fix a few minor details. * Fix merge issues. * Fix focus indicator (gets cropped with the new overflow auto setting) * Fix unwanted chevron. * Fix unwanted nested scrollbar in inserter > patterns/media vertical tabs. * Switch to transform for performance. * Adjust border-radius based on scaling factor. Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> * Apply feedback. * Add changelog entry. * Switch to `padding-inline`. * Remove unnecessary styles. * Fix horizontal tabs height. * Remove more unnecessary styles (padding). * Make horizontal padding specific to inline. * Make flex/whitespace styles more explicit. * Make scroll margin specific to vertical tabs. * The "inline" in inline-flex is unnecessary and confusing, removed it. * Remove unnecessary position: relative * Make resets more explicit * Remove unnecessary text-align. * Improve comment * Remove unnecessary margin-left * Clean up TabList styles. * Adjust text-align. * Clean up selector * Fix focus indicator * Clean up position: relative. * Fix typo. * Add position: relative back. * Improve focus indicator when selectOnMove is enabled. * Add fade in effect to chevron when selectOnMove is enabled. * Use [data-focus-visible] consistently. * Styles clean up. * Add comment for clarity. * Move scroll-margin to the right place. * Use CSS variable for accuracy. * Fix overflow. * Skip failing test for Safari :( * Fix flashing issue. * Transition chevron only on selected and not on hover or focus-visible. * Improve chevron opacity transition with suggested value. * fix changelog --- .../inserter/category-tabs/index.js | 12 +- .../src/components/inserter/style.scss | 42 +---- packages/components/CHANGELOG.md | 4 + packages/components/src/tabs/styles.ts | 152 +++++++++++++----- packages/components/src/tabs/tab.tsx | 10 +- packages/components/src/tabs/tablist.tsx | 1 + test/e2e/specs/editor/various/a11y.spec.js | 7 + 7 files changed, 131 insertions(+), 97 deletions(-) diff --git a/packages/block-editor/src/components/inserter/category-tabs/index.js b/packages/block-editor/src/components/inserter/category-tabs/index.js index 6a02cf1a170c45..6d8f5fcbca1334 100644 --- a/packages/block-editor/src/components/inserter/category-tabs/index.js +++ b/packages/block-editor/src/components/inserter/category-tabs/index.js @@ -2,14 +2,10 @@ * WordPress dependencies */ import { usePrevious, useReducedMotion } from '@wordpress/compose'; -import { isRTL } from '@wordpress/i18n'; import { - __experimentalHStack as HStack, - FlexBlock, privateApis as componentsPrivateApis, __unstableMotion as motion, } from '@wordpress/components'; -import { Icon, chevronRight, chevronLeft } from '@wordpress/icons'; /** * Internal dependencies @@ -55,18 +51,12 @@ function CategoryTabs( { <Tabs.Tab key={ category.name } tabId={ category.name } - className="block-editor-inserter__category-tab" aria-label={ category.label } aria-current={ category === selectedCategory ? 'true' : undefined } > - <HStack> - <FlexBlock>{ category.label }</FlexBlock> - <Icon - icon={ isRTL() ? chevronLeft : chevronRight } - /> - </HStack> + { category.label } </Tabs.Tab> ) ) } </Tabs.TabList> diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index f3fa8d1e7df04b..9e727b13795249 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -214,55 +214,15 @@ $block-inserter-tabs-height: 44px; .block-editor-inserter__media-tabs-container, .block-editor-inserter__block-patterns-tabs-container { + flex-grow: 1; padding: $grid-unit-20; - height: 100%; display: flex; flex-direction: column; justify-content: space-between; } .block-editor-inserter__category-tablist { - display: flex; - flex-direction: column; - border: none; margin-bottom: $grid-unit-10; - // Push the listitem wrapping the "explore" button to the bottom of the panel. - div[role="listitem"]:last-child { - margin-top: auto; - } - - // Temporarily disable the component's indicator animation. - // TODO: remove in favor of using the native component's styles and behavior, - // see https://github.com/WordPress/gutenberg/pull/62879#issuecomment-2219720582 - &[aria-orientation="vertical"]::after { - content: none; - } - - .block-editor-inserter__category-tab { - // Account for the icon on the right so that it's visually balanced. - padding: $grid-unit-10 $grid-unit-05 $grid-unit-10 $grid-unit-15; - text-align: left; - font-weight: inherit; - display: block; - position: relative; - height: auto; - - &[aria-selected="true"] { - color: var(--wp-admin-theme-color); - - .components-flex-item { - filter: brightness(0.95); - } - - svg { - fill: var(--wp-admin-theme-color); - } - } - - &::before { - display: none; - } - } } .block-editor-inserter__category-panel { diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 0bf9776d01a5de..4ae124347187e7 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -8,6 +8,10 @@ - `RangeControl`: do not tooltip contents to the DOM when not shown ([#65875](https://github.com/WordPress/gutenberg/pull/65875)). - `Tabs`: fix skipping indication animation glitch ([#65878](https://github.com/WordPress/gutenberg/pull/65878)). +### Enhancements + +- `Tabs`: revamped vertical orientation styles ([#65387](https://github.com/WordPress/gutenberg/pull/65387)). + ## 28.9.0 (2024-10-03) ### Bug Fixes diff --git a/packages/components/src/tabs/styles.ts b/packages/components/src/tabs/styles.ts index 4f6b4a4c7c8dcb..926abc3e34b102 100644 --- a/packages/components/src/tabs/styles.ts +++ b/packages/components/src/tabs/styles.ts @@ -9,18 +9,15 @@ import * as Ariakit from '@ariakit/react'; */ import { COLORS, CONFIG } from '../utils'; import { space } from '../utils/space'; +import Icon from '../icon'; export const TabListWrapper = styled.div` - position: relative; display: flex; align-items: stretch; - flex-direction: row; - text-align: center; overflow-x: auto; &[aria-orientation='vertical'] { flex-direction: column; - text-align: start; } :where( [aria-orientation='horizontal'] ) { @@ -40,11 +37,12 @@ export const TabListWrapper = styled.div` @media not ( prefers-reduced-motion ) { &[data-indicator-animated]::before { - transition-property: transform; + transition-property: transform, border-radius, border-block; transition-duration: 0.2s; transition-timing-function: ease-out; } } + position: relative; &::before { content: ''; position: absolute; @@ -59,7 +57,7 @@ export const TabListWrapper = styled.div` /* Using a large value to avoid antialiasing rounding issues when scaling in the transform, see: https://stackoverflow.com/a/52159123 */ --antialiasing-factor: 100; - &:not( [aria-orientation='vertical'] ) { + &[aria-orientation='horizontal'] { --fade-width: 4rem; --fade-gradient-base: transparent 0%, black var( --fade-width ); --fade-gradient-composed: var( --fade-gradient-base ), black 60%, @@ -104,40 +102,67 @@ export const TabListWrapper = styled.div` ${ COLORS.theme.accent }; } } - &[aria-orientation='vertical']::before { - top: 0; - left: 0; - width: 100%; - height: calc( var( --antialiasing-factor ) * 1px ); - transform: translateY( calc( var( --selected-top, 0 ) * 1px ) ) - scaleY( + &[aria-orientation='vertical'] { + &::before { + /* Adjusting the border radius to match the scaling in the y axis. */ + border-radius: ${ CONFIG.radiusSmall } / calc( - var( --selected-height, 0 ) / var( --antialiasing-factor ) - ) + ${ CONFIG.radiusSmall } / + ( + var( --selected-height, 0 ) / + var( --antialiasing-factor ) + ) + ); + top: 0; + left: 0; + width: 100%; + height: calc( var( --antialiasing-factor ) * 1px ); + transform: translateY( calc( var( --selected-top, 0 ) * 1px ) ) + scaleY( + calc( + var( --selected-height, 0 ) / + var( --antialiasing-factor ) + ) + ); + background-color: color-mix( + in srgb, + ${ COLORS.theme.accent }, + transparent 96% ); - background-color: ${ COLORS.theme.gray[ 100 ] }; + } + &[data-select-on-move='true']:has( + :is( :focus-visible, [data-focus-visible] ) + )::before { + box-sizing: border-box; + border: var( --wp-admin-border-width-focus ) solid + ${ COLORS.theme.accent }; + /* Adjusting the border width to match the scaling in the y axis. */ + border-block-width: calc( + var( --wp-admin-border-width-focus, 1px ) / + ( + var( --selected-height, 0 ) / + var( --antialiasing-factor ) + ) + ); + } } `; export const Tab = styled( Ariakit.Tab )` & { - scroll-margin: 24px; - flex-grow: 1; - flex-shrink: 0; - display: inline-flex; - align-items: center; - position: relative; + /* Resets */ border-radius: 0; - height: ${ space( 12 ) }; background: transparent; border: none; box-shadow: none; + + flex: 1 0 auto; + white-space: nowrap; + display: flex; + align-items: center; cursor: pointer; - line-height: 1.2; // Some languages characters e.g. Japanese may have a native higher line-height. - padding: ${ space( 4 ) }; - margin-left: 0; - font-weight: 500; - text-align: inherit; + line-height: 1.2; // Characters in some languages (e.g. Japanese) may have a native higher line-height. + font-weight: 400; color: ${ COLORS.theme.foreground }; &[aria-disabled='true'] { @@ -145,24 +170,19 @@ export const Tab = styled( Ariakit.Tab )` color: ${ COLORS.ui.textDisabled }; } - &:not( [aria-disabled='true'] ):hover { + &:not( [aria-disabled='true'] ):is( :hover, [data-focus-visible] ) { color: ${ COLORS.theme.accent }; } &:focus:not( :disabled ) { - position: relative; box-shadow: none; outline: none; } - // Focus. + // Focus indicator. + position: relative; &::after { - content: ''; position: absolute; - top: ${ space( 3 ) }; - right: ${ space( 3 ) }; - bottom: ${ space( 3 ) }; - left: ${ space( 3 ) }; pointer-events: none; // Draw the indicator. @@ -175,23 +195,69 @@ export const Tab = styled( Ariakit.Tab )` opacity: 0; @media not ( prefers-reduced-motion ) { - transition: opacity 0.1s linear; + transition: opacity 0.15s 0.15s linear; } } - &:focus-visible::after { + &[data-focus-visible]::after { opacity: 1; } } + [aria-orientation='horizontal'] & { + padding-inline: ${ space( 4 ) }; + height: ${ space( 12 ) }; + text-align: center; + scroll-margin: 24px; + + &::after { + content: ''; + inset: ${ space( 3 ) }; + } + } + [aria-orientation='vertical'] & { - min-height: ${ space( - 10 - ) }; // Avoid fixed height to allow for long strings that go in multiple lines. + padding: ${ space( 2 ) } ${ space( 3 ) }; + min-height: ${ space( 10 ) }; + text-align: start; + + &[aria-selected='true'] { + color: ${ COLORS.theme.accent }; + fill: currentColor; + } + } + [aria-orientation='vertical'][data-select-on-move='false'] &::after { + content: ''; + inset: var( --wp-admin-border-width-focus ); } +`; + +export const TabChildren = styled.span` + flex-grow: 1; +`; +export const TabChevron = styled( Icon )` + flex-shrink: 0; + margin-inline-end: ${ space( -1 ) }; [aria-orientation='horizontal'] & { - justify-content: center; + display: none; + } + opacity: 0; + [role='tab']:is( [aria-selected='true'], [data-focus-visible], :hover ) & { + opacity: 1; + } + // The chevron is transitioned into existence when selectOnMove is enabled, + // because otherwise it looks jarring, as it shows up outside of the focus + // indicator that's being animated at the same time. + @media not ( prefers-reduced-motion ) { + [data-select-on-move='true'] + [role='tab']:is( [aria-selected='true'], ) + & { + transition: opacity 0.3s ease-in; + } + } + &:dir( rtl ) { + rotate: 180deg; } `; @@ -201,7 +267,7 @@ export const TabPanel = styled( Ariakit.TabPanel )` outline: none; } - &:focus-visible { + &[data-focus-visible] { box-shadow: 0 0 0 var( --wp-admin-border-width-focus ) ${ COLORS.theme.accent }; // Windows high contrast mode. diff --git a/packages/components/src/tabs/tab.tsx b/packages/components/src/tabs/tab.tsx index e1aa85c636cdd1..29f6111adc8397 100644 --- a/packages/components/src/tabs/tab.tsx +++ b/packages/components/src/tabs/tab.tsx @@ -10,8 +10,13 @@ import { forwardRef } from '@wordpress/element'; import type { TabProps } from './types'; import warning from '@wordpress/warning'; import { useTabsContext } from './context'; -import { Tab as StyledTab } from './styles'; +import { + Tab as StyledTab, + TabChildren as StyledTabChildren, + TabChevron as StyledTabChevron, +} from './styles'; import type { WordPressComponentProps } from '../context'; +import { chevronRight } from '@wordpress/icons'; export const Tab = forwardRef< HTMLButtonElement, @@ -33,7 +38,8 @@ export const Tab = forwardRef< render={ render } { ...otherProps } > - { children } + <StyledTabChildren>{ children }</StyledTabChildren> + <StyledTabChevron icon={ chevronRight } /> </StyledTab> ); } ); diff --git a/packages/components/src/tabs/tablist.tsx b/packages/components/src/tabs/tablist.tsx index a861d3294aae66..512a3eb6724289 100644 --- a/packages/components/src/tabs/tablist.tsx +++ b/packages/components/src/tabs/tablist.tsx @@ -115,6 +115,7 @@ export const TabList = forwardRef< render={ <TabListWrapper /> } onBlur={ onBlur } tabIndex={ -1 } + data-select-on-move={ selectOnMove ? 'true' : 'false' } { ...otherProps } className={ clsx( overflow.first && 'is-overflowing-first', diff --git a/test/e2e/specs/editor/various/a11y.spec.js b/test/e2e/specs/editor/various/a11y.spec.js index 3ec7318ab89e78..8f63b57fda657f 100644 --- a/test/e2e/specs/editor/various/a11y.spec.js +++ b/test/e2e/specs/editor/various/a11y.spec.js @@ -123,7 +123,14 @@ test.describe( 'a11y (@firefox, @webkit)', () => { test( 'should make the modal content focusable when it is scrollable', async ( { page, pageUtils, + browserName, } ) => { + // eslint-disable-next-line playwright/no-skipped-test + test.skip( + browserName === 'webkit', + 'Known bug with focus order in Safari.' + ); + // Note: this test depends on a particular viewport height to determine whether or not // the modal content is scrollable. If this tests fails and needs to be debugged locally, // double-check the viewport height when running locally versus in CI. Additionally, From 502a2d5bd25cc06af4241ad872c3bcef0d56fed5 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Tue, 8 Oct 2024 00:15:52 +0300 Subject: [PATCH 1101/1908] Simplify logical expression in `InitPatternModal` (#65922) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/edit-post/src/components/init-pattern-modal/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/edit-post/src/components/init-pattern-modal/index.js b/packages/edit-post/src/components/init-pattern-modal/index.js index 4288557ec712d6..1bfeadd73f94a6 100644 --- a/packages/edit-post/src/components/init-pattern-modal/index.js +++ b/packages/edit-post/src/components/init-pattern-modal/index.js @@ -27,8 +27,8 @@ export default function InitPatternModal() { isNewPost: isCleanNewPost(), }; }, [] ); - const [ isModalOpen, setIsModalOpen ] = useState( () => - isNewPost && postType === 'wp_block' ? true : false + const [ isModalOpen, setIsModalOpen ] = useState( + () => isNewPost && postType === 'wp_block' ); if ( postType !== 'wp_block' || ! isNewPost ) { From 622f41e07a0d61a9bb589887d8c40b4768d3efb2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 20:27:25 -0400 Subject: [PATCH 1102/1908] Bump the github-actions group with 2 updates (#65916) Bumps the github-actions group with 2 updates: [actions/cache](https://github.com/actions/cache) and [ruby/setup-ruby](https://github.com/ruby/setup-ruby). Updates `actions/cache` from 4.0.2 to 4.1.0 - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/0c45773b623bea8c8e75f6c82b208c3cf94ea4f9...2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2) Updates `ruby/setup-ruby` from 1.194.0 to 1.195.0 - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb) - [Commits](https://github.com/ruby/setup-ruby/compare/c04af2bb7258bb6a03df1d3c1865998ac9390972...086ffb1a2090c870a3f881cc91ea83aa4243d408) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/pull-request-automation.yml | 2 +- .github/workflows/rnmobile-android-runner.yml | 4 ++-- .github/workflows/rnmobile-ios-runner.yml | 8 ++++---- .github/workflows/unit-test.yml | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pull-request-automation.yml b/.github/workflows/pull-request-automation.yml index 2006eafd81cc7d..f85b8510067569 100644 --- a/.github/workflows/pull-request-automation.yml +++ b/.github/workflows/pull-request-automation.yml @@ -24,7 +24,7 @@ jobs: check-latest: true - name: Cache NPM packages - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 with: # npm cache files are stored in `~/.npm` on Linux/macOS path: ~/.npm diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index 9392ba100af713..729d1d20fd7e7b 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -37,7 +37,7 @@ jobs: uses: ./.github/setup-node - name: Restore tests setup cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 with: path: | ~/.appium @@ -50,7 +50,7 @@ jobs: uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0 - name: AVD cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 id: avd-cache with: path: | diff --git a/.github/workflows/rnmobile-ios-runner.yml b/.github/workflows/rnmobile-ios-runner.yml index cf065ad1cdf7db..475937eb58f5f8 100644 --- a/.github/workflows/rnmobile-ios-runner.yml +++ b/.github/workflows/rnmobile-ios-runner.yml @@ -27,7 +27,7 @@ jobs: with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - uses: ruby/setup-ruby@c04af2bb7258bb6a03df1d3c1865998ac9390972 # v1.194.0 + - uses: ruby/setup-ruby@086ffb1a2090c870a3f881cc91ea83aa4243d408 # v1.195.0 with: # `.ruby-version` file location working-directory: packages/react-native-editor/ios @@ -42,7 +42,7 @@ jobs: uses: ./.github/setup-node - name: Restore tests setup cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 with: path: | ~/.appium @@ -55,7 +55,7 @@ jobs: run: find package-lock.json packages/react-native-editor/ios packages/react-native-aztec/ios packages/react-native-bridge/ios -type f -print0 | sort -z | xargs -0 shasum | tee ios-checksums.txt - name: Restore build cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 with: path: | packages/react-native-editor/ios/build/GutenbergDemo/Build/Products/Release-iphonesimulator/GutenbergDemo.app @@ -63,7 +63,7 @@ jobs: key: ${{ runner.os }}-ios-build-${{ matrix.xcode }}-${{ matrix.device }}-${{ hashFiles('ios-checksums.txt') }} - name: Restore pods cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 with: path: | packages/react-native-editor/ios/Pods diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index bfa35492589a48..47b5e9f76ea7b0 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -296,7 +296,7 @@ jobs: run: echo "date=$(/bin/date -u --date='last Mon' "+%F")" >> $GITHUB_OUTPUT - name: Cache PHPCS scan cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 with: path: .cache/phpcs.json key: ${{ runner.os }}-date-${{ steps.get-date.outputs.date }}-phpcs-cache-${{ hashFiles('**/composer.json', 'phpcs.xml.dist') }} From d82a3b69ac8f11dedbdf0d02633ca9decaa8a4a4 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Tue, 8 Oct 2024 08:48:41 +0200 Subject: [PATCH 1103/1908] Match visible label of search inputs with their actual label. (#65458) * Match visible label of search inputs with their actual label. * Adjust more tests. * Adjust more tests. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../pattern-explorer-sidebar.js | 2 +- .../src/components/inserter/menu.js | 2 +- .../src/components/inserter/quick-inserter.js | 2 +- .../components/link-control/search-input.js | 9 +- .../components/link-control/search-results.js | 15 +- .../src/components/link-control/test/index.js | 130 +++++++++++------- .../media-replace-flow/test/index.js | 2 +- .../src/query/edit/pattern-selection-modal.js | 2 +- .../src/template-part/edit/selection-modal.js | 2 +- .../global-styles/screen-block-list.js | 2 +- .../hierarchical-term-selector.js | 1 + test/e2e/specs/editor/blocks/buttons.spec.js | 8 +- test/e2e/specs/editor/blocks/group.spec.js | 5 +- test/e2e/specs/editor/blocks/links.spec.js | 6 +- .../blocks/navigation-list-view.spec.js | 4 +- .../specs/editor/blocks/navigation.spec.js | 4 +- .../editor/plugins/allowed-blocks.spec.js | 2 +- .../editor/plugins/block-directory.spec.js | 4 +- .../editor/plugins/block-variations.spec.js | 4 +- .../editor/various/adding-patterns.spec.js | 2 +- .../editor/various/allowed-patterns.spec.js | 4 +- .../editor/various/inserting-blocks.spec.js | 14 +- .../editor/various/parsing-patterns.spec.js | 2 +- .../e2e/specs/editor/various/patterns.spec.js | 2 +- .../block-style-variations.spec.js | 5 +- .../site-editor/global-styles-sidebar.spec.js | 2 +- .../site-editor/site-editor-inserter.spec.js | 8 +- .../specs/widgets/customizing-widgets.spec.js | 6 +- .../e2e/specs/widgets/editing-widgets.spec.js | 4 +- 29 files changed, 136 insertions(+), 119 deletions(-) diff --git a/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js b/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js index d258c24da10cfb..89384bc0537143 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js +++ b/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js @@ -40,7 +40,7 @@ function PatternsExplorerSearch( { searchValue, setSearchValue } ) { __nextHasNoMarginBottom onChange={ setSearchValue } value={ searchValue } - label={ __( 'Search for patterns' ) } + label={ __( 'Search' ) } placeholder={ __( 'Search' ) } /> </div> diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index a32251a1a71d05..fa72728f6de20c 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -168,7 +168,7 @@ function InserterMenu( setFilterValue( value ); } } value={ filterValue } - label={ __( 'Search for blocks and patterns' ) } + label={ __( 'Search' ) } placeholder={ __( 'Search' ) } /> { !! delayedFilterValue && ( diff --git a/packages/block-editor/src/components/inserter/quick-inserter.js b/packages/block-editor/src/components/inserter/quick-inserter.js index 7c7f836842b418..9f393a7ce15202 100644 --- a/packages/block-editor/src/components/inserter/quick-inserter.js +++ b/packages/block-editor/src/components/inserter/quick-inserter.js @@ -116,7 +116,7 @@ export default function QuickInserter( { onChange={ ( value ) => { setFilterValue( value ); } } - label={ __( 'Search for blocks and patterns' ) } + label={ __( 'Search' ) } placeholder={ __( 'Search' ) } /> ) } diff --git a/packages/block-editor/src/components/link-control/search-input.js b/packages/block-editor/src/components/link-control/search-input.js index f41884092e4894..3f109b8a371552 100644 --- a/packages/block-editor/src/components/link-control/search-input.js +++ b/packages/block-editor/src/components/link-control/search-input.js @@ -1,7 +1,6 @@ /** * WordPress dependencies */ -import { useInstanceId } from '@wordpress/compose'; import { forwardRef, useState } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; @@ -58,7 +57,6 @@ const LinkControlSearchInput = forwardRef( ? fetchSuggestions || genericSearchHandler : noopSearchHandler; - const instanceId = useInstanceId( LinkControlSearchInput ); const [ focusedSuggestion, setFocusedSuggestion ] = useState(); /** @@ -76,7 +74,6 @@ const LinkControlSearchInput = forwardRef( const handleRenderSuggestions = ( props ) => renderSuggestions( { ...props, - instanceId, withCreateSuggestion, createSuggestionButtonText, suggestionsQuery, @@ -116,16 +113,18 @@ const LinkControlSearchInput = forwardRef( } }; + const inputLabel = placeholder ?? __( 'Search or type URL' ); + return ( <div className="block-editor-link-control__search-input-container"> <URLInput disableSuggestions={ currentLink?.url === value } - label={ __( 'Link' ) } + label={ inputLabel } hideLabelFromVision={ hideLabelFromVision } className={ className } value={ value } onChange={ onInputChange } - placeholder={ placeholder ?? __( 'Search or type URL' ) } + placeholder={ inputLabel } __experimentalRenderSuggestions={ showSuggestions ? handleRenderSuggestions : null } diff --git a/packages/block-editor/src/components/link-control/search-results.js b/packages/block-editor/src/components/link-control/search-results.js index 2186b5d8b62f7f..29558f69291c57 100644 --- a/packages/block-editor/src/components/link-control/search-results.js +++ b/packages/block-editor/src/components/link-control/search-results.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { VisuallyHidden, MenuGroup } from '@wordpress/components'; +import { MenuGroup } from '@wordpress/components'; /** * External dependencies @@ -17,7 +17,6 @@ import LinkControlSearchItem from './search-item'; import { CREATE_TYPE, LINK_ENTRY_TYPES } from './constants'; export default function LinkControlSearchResults( { - instanceId, withCreateSuggestion, currentInputValue, handleSuggestionClick, @@ -47,10 +46,6 @@ export default function LinkControlSearchResults( { // If the query has a specified type, then we can skip showing them in the result. See #24839. const shouldShowSuggestionsTypes = ! suggestionsQuery?.type; - // According to guidelines aria-label should be added if the label - // itself is not visible. - // See: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/listbox_role - const searchResultsLabelId = `block-editor-link-control-search-results-label-${ instanceId }`; const labelText = isInitialSuggestions ? __( 'Suggestions' ) : sprintf( @@ -58,19 +53,13 @@ export default function LinkControlSearchResults( { __( 'Search results for "%s"' ), currentInputValue ); - const searchResultsLabel = ( - <VisuallyHidden id={ searchResultsLabelId }> - { labelText } - </VisuallyHidden> - ); return ( <div className="block-editor-link-control__search-results-wrapper"> - { searchResultsLabel } <div { ...suggestionsListProps } className={ resultsListClasses } - aria-labelledby={ searchResultsLabelId } + aria-label={ labelText } > <MenuGroup> { suggestions.map( ( suggestion, index ) => { diff --git a/packages/block-editor/src/components/link-control/test/index.js b/packages/block-editor/src/components/link-control/test/index.js index fa8c4d86eae5c9..e416b9b522a53c 100644 --- a/packages/block-editor/src/components/link-control/test/index.js +++ b/packages/block-editor/src/components/link-control/test/index.js @@ -138,7 +138,9 @@ describe( 'Basic rendering', () => { render( <LinkControl /> ); // Search Input UI. - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); expect( searchInput ).toBeVisible(); } ); @@ -147,7 +149,9 @@ describe( 'Basic rendering', () => { render( <LinkControl /> ); // Search Input UI. - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); expect( searchInput ).toBeVisible(); // Make sure we use the ARIA 1.0 pattern with aria-owns. @@ -170,7 +174,9 @@ describe( 'Basic rendering', () => { render( <LinkControl /> ); // Search Input UI. - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); // Simulate searching for a term. await user.type( searchInput, 'Hello' ); @@ -283,7 +289,9 @@ describe( 'Basic rendering', () => { render( <LinkControl /> ); // Search Input UI. - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); // Simulate searching for a term. await user.type( searchInput, searchTerm ); @@ -296,7 +304,7 @@ describe( 'Basic rendering', () => { render( <LinkControl value={ { url: 'https://example.com' } } /> ); expect( - screen.queryByRole( 'combobox', { name: 'Link' } ) + screen.queryByRole( 'combobox', { name: 'Search or type URL' } ) ).not.toBeInTheDocument(); } ); @@ -309,7 +317,7 @@ describe( 'Basic rendering', () => { ); expect( - screen.getByRole( 'combobox', { name: 'Link' } ) + screen.getByRole( 'combobox', { name: 'Search or type URL' } ) ).toBeVisible(); } ); @@ -327,7 +335,7 @@ describe( 'Basic rendering', () => { await user.click( editButton ); expect( - screen.getByRole( 'combobox', { name: 'Link' } ) + screen.getByRole( 'combobox', { name: 'Search or type URL' } ) ).toBeVisible(); // If passed `forceIsEditingLink` of `false` while editing, should @@ -340,7 +348,7 @@ describe( 'Basic rendering', () => { ); expect( - screen.queryByRole( 'combobox', { name: 'Link' } ) + screen.queryByRole( 'combobox', { name: 'Search or type URL' } ) ).not.toBeInTheDocument(); } ); @@ -428,7 +436,7 @@ describe( 'Basic rendering', () => { // Should revert back to editing mode. expect( - screen.getByRole( 'combobox', { name: 'Link' } ) + screen.getByRole( 'combobox', { name: 'Search or type URL' } ) ).toBeVisible(); } ); } ); @@ -450,7 +458,9 @@ describe( 'Searching for a link', () => { render( <LinkControl /> ); // Search Input UI. - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); // Simulate searching for a term. await user.type( searchInput, searchTerm ); @@ -475,7 +485,7 @@ describe( 'Searching for a link', () => { // Search Input UI. const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); // Simulate searching for a term. @@ -526,7 +536,7 @@ describe( 'Searching for a link', () => { // Search Input UI. const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); // Simulate searching for a term. @@ -558,7 +568,9 @@ describe( 'Searching for a link', () => { render( <LinkControl /> ); // Search Input UI. - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); // Simulate searching for a term. await user.type( searchInput, searchTerm ); @@ -601,7 +613,9 @@ describe( 'Searching for a link', () => { render( <LinkControl showSuggestions={ false } /> ); // Search Input UI. - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); // Simulate searching for a term. await user.type( searchInput, 'anything' ); @@ -618,7 +632,9 @@ describe( 'Searching for a link', () => { render( <LinkControl /> ); // Search Input UI. - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); // Simulate searching for a term. await user.type( searchInput, searchTerm ); @@ -648,7 +664,9 @@ describe( 'Searching for a link', () => { render( <LinkControl noURLSuggestion /> ); // Search Input UI. - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); // Simulate searching for a term. await user.type( searchInput, 'couldbeurlorentitysearchterm' ); @@ -679,7 +697,7 @@ describe( 'Manual link entry', () => { // Search Input UI. const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); // Simulate searching for a term. @@ -715,7 +733,7 @@ describe( 'Manual link entry', () => { // Search Input UI. const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); if ( searchString.length ) { @@ -749,7 +767,7 @@ describe( 'Manual link entry', () => { // Search Input UI. const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); // Remove the existing link. @@ -830,7 +848,7 @@ describe( 'Manual link entry', () => { await toggleSettingsDrawer( user ); let searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); let textInput = screen.getByRole( 'textbox', { @@ -865,7 +883,7 @@ describe( 'Manual link entry', () => { // Re-query the inputs as they have been replaced. searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); textInput = screen.getByRole( 'textbox', { @@ -913,7 +931,7 @@ describe( 'Manual link entry', () => { // Search Input UI. const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); // Simulate searching for a term. @@ -949,7 +967,7 @@ describe( 'Link submission', () => { render( <LinkControlConsumer /> ); const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); const submitButton = screen.getByRole( 'button', { @@ -988,7 +1006,7 @@ describe( 'Link submission', () => { render( <LinkControlConsumer /> ); const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); const createSubmitButton = screen.queryByRole( 'button', { @@ -1035,9 +1053,9 @@ describe( 'Default search suggestions', () => { // Verify input has no value has default suggestions should only show // when this does not have a value. // Search Input UI. - expect( screen.getByRole( 'combobox', { name: 'Link' } ) ).toHaveValue( - '' - ); + expect( + screen.getByRole( 'combobox', { name: 'Search or type URL' } ) + ).toHaveValue( '' ); // Ensure only called once as a guard against potential infinite // re-render loop within `componentDidUpdate` calling `updateSuggestions` @@ -1064,7 +1082,9 @@ describe( 'Default search suggestions', () => { } ); await user.click( currentLinkBtn ); - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); // Search input is set to the URL value. expect( searchInput ).toHaveValue( initialValue.url ); @@ -1086,7 +1106,9 @@ describe( 'Default search suggestions', () => { render( <LinkControl showInitialSuggestions /> ); // Search Input UI. - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); // Simulate searching for a term. await user.type( searchInput, searchTerm ); @@ -1124,7 +1146,9 @@ describe( 'Default search suggestions', () => { render( <LinkControl showInitialSuggestions /> ); - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); const searchResultsField = screen.queryByRole( 'listbox', { name: 'Suggestions', @@ -1183,7 +1207,7 @@ describe( 'Creating Entities (eg: Posts, Pages)', () => { // Search Input UI. const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); // Simulate searching for a term. @@ -1250,7 +1274,9 @@ describe( 'Creating Entities (eg: Posts, Pages)', () => { render( <LinkControlConsumer /> ); // Search Input UI. - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); // Simulate searching for a term. await user.type( searchInput, 'Some new page to create' ); @@ -1299,7 +1325,9 @@ describe( 'Creating Entities (eg: Posts, Pages)', () => { render( <LinkControlConsumer /> ); // Search Input UI. - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); // Simulate searching for a term. await user.type( searchInput, entityNameText ); @@ -1342,7 +1370,9 @@ describe( 'Creating Entities (eg: Posts, Pages)', () => { render( <LinkControlConsumer /> ); // Search Input UI. - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); // Simulate searching for a term. await user.type( searchInput, entityNameText ); @@ -1366,7 +1396,7 @@ describe( 'Creating Entities (eg: Posts, Pages)', () => { // Search Input UI. const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); const searchResultsField = screen.queryByRole( 'listbox' ); @@ -1387,7 +1417,7 @@ describe( 'Creating Entities (eg: Posts, Pages)', () => { // Search Input UI. const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); const searchResultsField = screen.queryByRole( 'listbox' ); @@ -1411,7 +1441,7 @@ describe( 'Creating Entities (eg: Posts, Pages)', () => { // Search Input UI. const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); // Simulate searching for a term. @@ -1445,7 +1475,9 @@ describe( 'Creating Entities (eg: Posts, Pages)', () => { render( <LinkControl createSuggestion={ createSuggestion } /> ); // Search Input UI. - searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); // Simulate searching for a term. await user.type( searchInput, searchText ); @@ -1460,7 +1492,9 @@ describe( 'Creating Entities (eg: Posts, Pages)', () => { await user.click( createButton ); - searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); const errorNotice = screen.getAllByText( 'API response returned invalid entity.' @@ -1533,7 +1567,9 @@ describe( 'Selecting links', () => { // Simulate searching for a term. await user.click( currentLinkBtn ); - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); currentLinkUI = screen.queryByLabelText( 'Currently selected' ); // We should be back to showing the search input. @@ -1574,7 +1610,7 @@ describe( 'Selecting links', () => { // Search Input UI. const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); // Simulate searching for a term. @@ -1636,7 +1672,7 @@ describe( 'Selecting links', () => { // Search Input UI. const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); // Simulate searching for a term. @@ -1726,7 +1762,7 @@ describe( 'Selecting links', () => { // Search Input UI. const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); // Step down into the search results, highlighting the first result item. @@ -1784,7 +1820,7 @@ describe( 'Selecting links', () => { // focus the search input const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); fireEvent.focus( searchInput ); @@ -2006,7 +2042,9 @@ describe( 'Post types', () => { render( <LinkControl /> ); // Search Input UI. - const searchInput = screen.getByRole( 'combobox', { name: 'Link' } ); + const searchInput = screen.getByRole( 'combobox', { + name: 'Search or type URL', + } ); // Simulate searching for a term. await user.type( searchInput, searchTerm ); @@ -2034,7 +2072,7 @@ describe( 'Post types', () => { // Search Input UI. const searchInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); // Simulate searching for a term. diff --git a/packages/block-editor/src/components/media-replace-flow/test/index.js b/packages/block-editor/src/components/media-replace-flow/test/index.js index 1d326804f0dcca..dace470aa67b0f 100644 --- a/packages/block-editor/src/components/media-replace-flow/test/index.js +++ b/packages/block-editor/src/components/media-replace-flow/test/index.js @@ -110,7 +110,7 @@ describe( 'General media replace flow', () => { ); const mediaURLInput = screen.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', expanded: false, } ); diff --git a/packages/block-library/src/query/edit/pattern-selection-modal.js b/packages/block-library/src/query/edit/pattern-selection-modal.js index 7fa29d0d894f1d..41a339908c5644 100644 --- a/packages/block-library/src/query/edit/pattern-selection-modal.js +++ b/packages/block-library/src/query/edit/pattern-selection-modal.js @@ -70,7 +70,7 @@ export default function PatternSelectionModal( { __nextHasNoMarginBottom onChange={ setSearchValue } value={ searchValue } - label={ __( 'Search for patterns' ) } + label={ __( 'Search' ) } placeholder={ __( 'Search' ) } /> </div> diff --git a/packages/block-library/src/template-part/edit/selection-modal.js b/packages/block-library/src/template-part/edit/selection-modal.js index 1df7314aaca0bb..5fa5d9786d8c96 100644 --- a/packages/block-library/src/template-part/edit/selection-modal.js +++ b/packages/block-library/src/template-part/edit/selection-modal.js @@ -80,7 +80,7 @@ export default function TemplatePartSelectionModal( { __nextHasNoMarginBottom onChange={ setSearchValue } value={ searchValue } - label={ __( 'Search for replacements' ) } + label={ __( 'Search' ) } placeholder={ __( 'Search' ) } /> </div> diff --git a/packages/edit-site/src/components/global-styles/screen-block-list.js b/packages/edit-site/src/components/global-styles/screen-block-list.js index 0f7d2540fb04df..51807ba79aa111 100644 --- a/packages/edit-site/src/components/global-styles/screen-block-list.js +++ b/packages/edit-site/src/components/global-styles/screen-block-list.js @@ -174,7 +174,7 @@ function ScreenBlockList() { className="edit-site-block-types-search" onChange={ setFilterValue } value={ filterValue } - label={ __( 'Search for blocks' ) } + label={ __( 'Search' ) } placeholder={ __( 'Search' ) } /> <MemoizedBlockList filterValue={ deferredFilterValue } /> diff --git a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js index 071453f4f3f626..e019185b8a97cd 100644 --- a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js +++ b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js @@ -411,6 +411,7 @@ export function HierarchicalTermSelector( { slug } ) { __next40pxDefaultSize __nextHasNoMarginBottom label={ filterLabel } + placeholder={ filterLabel } value={ filterValue } onChange={ setFilter } /> diff --git a/test/e2e/specs/editor/blocks/buttons.spec.js b/test/e2e/specs/editor/blocks/buttons.spec.js index f62732470d9747..25bc2d6101024a 100644 --- a/test/e2e/specs/editor/blocks/buttons.spec.js +++ b/test/e2e/specs/editor/blocks/buttons.spec.js @@ -60,7 +60,7 @@ test.describe( 'Buttons', () => { ).toBeFocused(); await pageUtils.pressKeys( 'primary+k' ); await expect( - page.locator( 'role=combobox[name="Link"i]' ) + page.locator( 'role=combobox[name="Search or type URL"i]' ) ).toBeFocused(); await page.keyboard.press( 'Escape' ); await expect( @@ -91,7 +91,7 @@ test.describe( 'Buttons', () => { ).toBeFocused(); await pageUtils.pressKeys( 'primary+k' ); await expect( - page.locator( 'role=combobox[name="Link"i]' ) + page.locator( 'role=combobox[name="Search or type URL"i]' ) ).toBeFocused(); await page.keyboard.type( 'https://example.com' ); await page.keyboard.press( 'Enter' ); @@ -123,7 +123,9 @@ test.describe( 'Buttons', () => { ).toBeFocused(); await pageUtils.pressKeys( 'primary+k' ); - const urlInput = page.locator( 'role=combobox[name="Link"i]' ); + const urlInput = page.locator( + 'role=combobox[name="Search or type URL"i]' + ); await expect( urlInput ).toBeFocused(); await page.keyboard.type( 'example.com' ); diff --git a/test/e2e/specs/editor/blocks/group.spec.js b/test/e2e/specs/editor/blocks/group.spec.js index ccf522d8c4d533..871974c1f44dd4 100644 --- a/test/e2e/specs/editor/blocks/group.spec.js +++ b/test/e2e/specs/editor/blocks/group.spec.js @@ -19,10 +19,7 @@ test.describe( 'Group', () => { await inserterButton.click(); - await page.type( - 'role=searchbox[name="Search for blocks and patterns"i]', - 'Group' - ); + await page.type( 'role=searchbox[name="Search"i]', 'Group' ); await page.click( 'role=listbox[name="Blocks"i] >> role=option[name="Group"i]' diff --git a/test/e2e/specs/editor/blocks/links.spec.js b/test/e2e/specs/editor/blocks/links.spec.js index 02400fe9c9dd8a..5206f5b6689e14 100644 --- a/test/e2e/specs/editor/blocks/links.spec.js +++ b/test/e2e/specs/editor/blocks/links.spec.js @@ -116,7 +116,7 @@ test.describe( 'Links', () => { await expect( page.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ) ).toHaveValue( '' ); } ); @@ -393,7 +393,7 @@ test.describe( 'Links', () => { await pageUtils.pressKeys( 'primary+k' ); const urlInput = page.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); // Expect the "Link" combobox to be visible and focused @@ -498,7 +498,7 @@ test.describe( 'Links', () => { await expect( linkPopover.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ) ).toHaveValue( URL ); diff --git a/test/e2e/specs/editor/blocks/navigation-list-view.spec.js b/test/e2e/specs/editor/blocks/navigation-list-view.spec.js index 2d5189a6bd6529..2f9963169a5230 100644 --- a/test/e2e/specs/editor/blocks/navigation-list-view.spec.js +++ b/test/e2e/specs/editor/blocks/navigation-list-view.spec.js @@ -174,7 +174,7 @@ test.describe( 'Navigation block - List view editing', () => { // Expect to see the block inserter. await expect( page.getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ) ).toBeFocused(); @@ -588,7 +588,7 @@ class LinkControl { getSearchInput() { return this.page.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); } diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index 19da69cd27c4aa..83e95a08c0f6a2 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -615,7 +615,7 @@ class Navigation { getLinkControlSearch() { return this.page.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); } @@ -668,7 +668,7 @@ class Navigation { */ async addPage( label ) { const linkControlSearch = this.page.getByRole( 'combobox', { - name: 'Link', + name: 'Search or type URL', } ); await expect( linkControlSearch ).toBeFocused(); diff --git a/test/e2e/specs/editor/plugins/allowed-blocks.spec.js b/test/e2e/specs/editor/plugins/allowed-blocks.spec.js index 4211e428238218..6c8f4ead41c6f9 100644 --- a/test/e2e/specs/editor/plugins/allowed-blocks.spec.js +++ b/test/e2e/specs/editor/plugins/allowed-blocks.spec.js @@ -27,7 +27,7 @@ test.describe( 'Allowed Blocks Filter', () => { const searchbox = page .getByRole( 'region', { name: 'Block Library' } ) .getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ); await searchbox.fill( 'Paragraph' ); diff --git a/test/e2e/specs/editor/plugins/block-directory.spec.js b/test/e2e/specs/editor/plugins/block-directory.spec.js index 28700e787e8836..f9bf1f85151864 100644 --- a/test/e2e/specs/editor/plugins/block-directory.spec.js +++ b/test/e2e/specs/editor/plugins/block-directory.spec.js @@ -135,7 +135,7 @@ test.describe( 'Block Directory', () => { */ await blockLibrary .getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ) .fill( '@$@@Dsdsdfw2$@' ); @@ -226,7 +226,7 @@ test.describe( 'Block Directory', () => { await blockLibrary .getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ) .fill( MOCK_BLOCK1.title ); diff --git a/test/e2e/specs/editor/plugins/block-variations.spec.js b/test/e2e/specs/editor/plugins/block-variations.spec.js index 4c5488af4443f6..653680b48e1e66 100644 --- a/test/e2e/specs/editor/plugins/block-variations.spec.js +++ b/test/e2e/specs/editor/plugins/block-variations.spec.js @@ -28,7 +28,7 @@ test.describe( 'Block variations', () => { await page .getByRole( 'region', { name: 'Block Library' } ) .getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ) .fill( 'Quote' ); @@ -69,7 +69,7 @@ test.describe( 'Block variations', () => { await page .getByRole( 'region', { name: 'Block Library' } ) .getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ) .fill( 'Paragraph' ); diff --git a/test/e2e/specs/editor/various/adding-patterns.spec.js b/test/e2e/specs/editor/various/adding-patterns.spec.js index 35192dd364dc66..b634798b455403 100644 --- a/test/e2e/specs/editor/various/adding-patterns.spec.js +++ b/test/e2e/specs/editor/various/adding-patterns.spec.js @@ -13,7 +13,7 @@ test.describe( 'adding patterns', () => { await page.getByRole( 'tab', { name: 'Patterns' } ).click(); await page.fill( - 'role=region[name="Block Library"i] >> role=searchbox[name="Search for blocks and patterns"i]', + 'role=region[name="Block Library"i] >> role=searchbox[name="Search"i]', 'Standard' ); diff --git a/test/e2e/specs/editor/various/allowed-patterns.spec.js b/test/e2e/specs/editor/various/allowed-patterns.spec.js index 83d44403d60ee2..a99b1f5c291066 100644 --- a/test/e2e/specs/editor/various/allowed-patterns.spec.js +++ b/test/e2e/specs/editor/various/allowed-patterns.spec.js @@ -26,7 +26,7 @@ test.describe( 'Allowed Patterns', () => { name: 'Block Library', } ) .getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ) .fill( 'Test:' ); @@ -69,7 +69,7 @@ test.describe( 'Allowed Patterns', () => { name: 'Block Library', } ) .getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ) .fill( 'Test:' ); diff --git a/test/e2e/specs/editor/various/inserting-blocks.spec.js b/test/e2e/specs/editor/various/inserting-blocks.spec.js index b4f23c8b8e2bbf..83b919585a695c 100644 --- a/test/e2e/specs/editor/various/inserting-blocks.spec.js +++ b/test/e2e/specs/editor/various/inserting-blocks.spec.js @@ -76,7 +76,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { ); await page.fill( - 'role=region[name="Block Library"i] >> role=searchbox[name="Search for blocks and patterns"i]', + 'role=region[name="Block Library"i] >> role=searchbox[name="Search"i]', 'Heading' ); @@ -139,7 +139,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { ); await page.fill( - 'role=region[name="Block Library"i] >> role=searchbox[name="Search for blocks and patterns"i]', + 'role=region[name="Block Library"i] >> role=searchbox[name="Search"i]', 'Heading' ); @@ -197,7 +197,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { const PATTERN_NAME = 'Standard'; await page.fill( - 'role=region[name="Block Library"i] >> role=searchbox[name="Search for blocks and patterns"i]', + 'role=region[name="Block Library"i] >> role=searchbox[name="Search"i]', PATTERN_NAME ); @@ -286,7 +286,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { 'role=region[name="Editor top bar"i] >> role=button[name="Toggle block inserter"i]' ); await page.fill( - 'role=region[name="Block Library"i] >> role=searchbox[name="Search for blocks and patterns"i]', + 'role=region[name="Block Library"i] >> role=searchbox[name="Search"i]', PATTERN_NAME ); await page.hover( @@ -353,7 +353,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { const PATTERN_NAME = 'Standard'; await page.fill( - 'role=region[name="Block Library"i] >> role=searchbox[name="Search for blocks and patterns"i]', + 'role=region[name="Block Library"i] >> role=searchbox[name="Search"i]', PATTERN_NAME ); @@ -596,7 +596,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { await page .getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ) .first() .fill( 'Verse' ); @@ -606,7 +606,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { page .getByRole( 'region', { name: 'Block Library' } ) .getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ) .first() ).toHaveValue( 'Verse' ); diff --git a/test/e2e/specs/editor/various/parsing-patterns.spec.js b/test/e2e/specs/editor/various/parsing-patterns.spec.js index d8abe7a46fbc1b..62c8ba2de24104 100644 --- a/test/e2e/specs/editor/various/parsing-patterns.spec.js +++ b/test/e2e/specs/editor/various/parsing-patterns.spec.js @@ -37,7 +37,7 @@ test.describe( 'Parsing patterns', () => { } ); } ); await page.fill( - 'role=region[name="Block Library"i] >> role=searchbox[name="Search for blocks and patterns"i]', + 'role=region[name="Block Library"i] >> role=searchbox[name="Search"i]', 'whitespace' ); await page diff --git a/test/e2e/specs/editor/various/patterns.spec.js b/test/e2e/specs/editor/various/patterns.spec.js index 781d4657a20b90..7204f2bace51a5 100644 --- a/test/e2e/specs/editor/various/patterns.spec.js +++ b/test/e2e/specs/editor/various/patterns.spec.js @@ -500,7 +500,7 @@ test.describe( 'Synced pattern', () => { .click(); await page .getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ) .fill( 'Awesome empty' ); diff --git a/test/e2e/specs/site-editor/block-style-variations.spec.js b/test/e2e/specs/site-editor/block-style-variations.spec.js index 122b42a571b078..97ebc74db8308a 100644 --- a/test/e2e/specs/site-editor/block-style-variations.spec.js +++ b/test/e2e/specs/site-editor/block-style-variations.spec.js @@ -321,10 +321,7 @@ async function addPageContent( editor, page ) { 'role=button[name="Toggle block inserter"i]' ); await inserterButton.click(); - await page.type( - 'role=searchbox[name="Search for blocks and patterns"i]', - 'Group' - ); + await page.type( 'role=searchbox[name="Search"i]', 'Group' ); await page.click( 'role=listbox[name="Blocks"i] >> role=option[name="Group"i]' ); diff --git a/test/e2e/specs/site-editor/global-styles-sidebar.spec.js b/test/e2e/specs/site-editor/global-styles-sidebar.spec.js index 257ebc38f3b4dd..0b034def6a3063 100644 --- a/test/e2e/specs/site-editor/global-styles-sidebar.spec.js +++ b/test/e2e/specs/site-editor/global-styles-sidebar.spec.js @@ -32,7 +32,7 @@ test.describe( 'Global styles sidebar', () => { .click(); await page - .getByRole( 'searchbox', { name: 'Search for blocks' } ) + .getByRole( 'searchbox', { name: 'Search' } ) .fill( 'heading' ); // Matches both Heading and Table of Contents blocks. diff --git a/test/e2e/specs/site-editor/site-editor-inserter.spec.js b/test/e2e/specs/site-editor/site-editor-inserter.spec.js index 98cb8e4e74149c..acb0c5409f9b09 100644 --- a/test/e2e/specs/site-editor/site-editor-inserter.spec.js +++ b/test/e2e/specs/site-editor/site-editor-inserter.spec.js @@ -28,16 +28,12 @@ test.describe( 'Site Editor Inserter', () => { // Visibility check await expect( - page.locator( - 'role=searchbox[name="Search for blocks and patterns"i]' - ) + page.locator( 'role=searchbox[name="Search"i]' ) ).toBeVisible(); await page.click( 'role=button[name="Toggle block inserter"i]' ); //Hidden State check await expect( - page.locator( - 'role=searchbox[name="Search for blocks and patterns"i]' - ) + page.locator( 'role=searchbox[name="Search"i]' ) ).toBeHidden(); } ); diff --git a/test/e2e/specs/widgets/customizing-widgets.spec.js b/test/e2e/specs/widgets/customizing-widgets.spec.js index 38e9d3ee2c58ab..04b09da84928e1 100644 --- a/test/e2e/specs/widgets/customizing-widgets.spec.js +++ b/test/e2e/specs/widgets/customizing-widgets.spec.js @@ -79,7 +79,7 @@ test.describe( 'Widgets Customizer', () => { ); const inlineInserterSearchBox = page.locator( - 'role=searchbox[name="Search for blocks and patterns"i]' + 'role=searchbox[name="Search"i]' ); await expect( inlineInserterSearchBox ).toBeFocused(); @@ -651,9 +651,7 @@ class WidgetsCustomizerPage { 'role=toolbar[name="Document tools"i] >> role=button[name="Add block"i]' ); - const searchBox = this.page.locator( - 'role=searchbox[name="Search for blocks and patterns"i]' - ); + const searchBox = this.page.locator( 'role=searchbox[name="Search"i]' ); // Clear the input. await searchBox.evaluate( ( node ) => { diff --git a/test/e2e/specs/widgets/editing-widgets.spec.js b/test/e2e/specs/widgets/editing-widgets.spec.js index 28e9aac437572c..92a264492c018d 100644 --- a/test/e2e/specs/widgets/editing-widgets.spec.js +++ b/test/e2e/specs/widgets/editing-widgets.spec.js @@ -207,7 +207,7 @@ test.describe( 'Widgets screen', () => { await inBetweenInserterButton.click(); const inserterSearchBox = page.getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ); await expect( inserterSearchBox ).toBeFocused(); @@ -704,7 +704,7 @@ class WidgetsScreen { await blockLibrary .getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ) .fill( blockName ); From d6a4c72606d97d4b9e1593cce28f6bf9d5448052 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:37:10 +0530 Subject: [PATCH 1104/1908] Fix: Embed Block: Match HTML in the editor and frontend (#65478) * Add the fix for embed to resemeble exact markup as frontend and backend * Fix e2e test for updated embed block * Add the blockprops className to use the newClassname * Fix the code syntax for the same * Add the missing class on editor for the embed block * Add is-type-<typename> class to the editor embed block Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/block-library/src/embed/edit.js | 21 +++++++++++++++++-- .../block-library/src/embed/embed-preview.js | 20 ++---------------- .../specs/editor/various/embedding.spec.js | 6 +++--- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/packages/block-library/src/embed/edit.js b/packages/block-library/src/embed/edit.js index da3dac3e3d62b5..c0a10a20e31fc4 100644 --- a/packages/block-library/src/embed/edit.js +++ b/packages/block-library/src/embed/edit.js @@ -30,6 +30,7 @@ import { useBlockProps } from '@wordpress/block-editor'; import { store as coreStore } from '@wordpress/core-data'; import { View } from '@wordpress/primitives'; import { getAuthority } from '@wordpress/url'; +import { Caption } from '../utils/caption'; const EmbedEdit = ( props ) => { const { @@ -261,7 +262,15 @@ const EmbedEdit = ( props ) => { toggleResponsive={ toggleResponsive } switchBackToURLInput={ () => setIsEditingURL( true ) } /> - <View { ...blockProps }> + <figure + { ...blockProps } + className={ clsx( blockProps.className, className, { + [ `is-type-${ type }` ]: type, + [ `is-provider-${ providerNameSlug }` ]: providerNameSlug, + [ `wp-block-embed-${ providerNameSlug }` ]: + providerNameSlug, + } ) } + > <EmbedPreview preview={ preview } previewable={ previewable } @@ -279,7 +288,15 @@ const EmbedEdit = ( props ) => { attributes={ attributes } setAttributes={ setAttributes } /> - </View> + <Caption + attributes={ attributes } + setAttributes={ setAttributes } + isSelected={ isSelected } + insertBlocksAfter={ insertBlocksAfter } + label={ __( 'Embed caption text' ) } + showToolbarButton={ isSelected } + /> + </figure> </> ); }; diff --git a/packages/block-library/src/embed/embed-preview.js b/packages/block-library/src/embed/embed-preview.js index 1a230faf0c3d57..c0c7d5942d1d78 100644 --- a/packages/block-library/src/embed/embed-preview.js +++ b/packages/block-library/src/embed/embed-preview.js @@ -21,7 +21,6 @@ import { getAuthority } from '@wordpress/url'; * Internal dependencies */ import WpEmbedPreview from './wp-embed-preview'; -import { Caption } from '../utils/caption'; export default function EmbedPreview( { preview, @@ -32,9 +31,6 @@ export default function EmbedPreview( { className, icon, label, - insertBlocksAfter, - attributes, - setAttributes, } ) { const [ interactive, setInteractive ] = useState( false ); @@ -96,11 +92,7 @@ export default function EmbedPreview( { /* eslint-enable jsx-a11y/no-static-element-interactions */ return ( - <figure - className={ clsx( className, 'wp-block-embed', { - 'is-type-video': 'video' === type, - } ) } - > + <> { previewable ? ( embedWrapper ) : ( @@ -122,14 +114,6 @@ export default function EmbedPreview( { </p> </Placeholder> ) } - <Caption - attributes={ attributes } - setAttributes={ setAttributes } - isSelected={ isSelected } - insertBlocksAfter={ insertBlocksAfter } - label={ __( 'Embed caption text' ) } - showToolbarButton={ isSelected } - /> - </figure> + </> ); } diff --git a/test/e2e/specs/editor/various/embedding.spec.js b/test/e2e/specs/editor/various/embedding.spec.js index fb9746dce52e3c..fe488f91301749 100644 --- a/test/e2e/specs/editor/various/embedding.spec.js +++ b/test/e2e/specs/editor/various/embedding.spec.js @@ -134,15 +134,15 @@ test.describe( 'Embedding content', () => { 'https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/' ); await expect( - currenEmbedBlock.locator( 'figure' ), + currenEmbedBlock, 'WordPress valid content. Should render valid figure element.' - ).toHaveClass( 'wp-block-embed' ); + ).toHaveClass( /wp-block-embed/ ); await embedUtils.insertEmbed( 'https://www.youtube.com/watch?v=lXMskKTw3Bc' ); await expect( - currenEmbedBlock.locator( 'figure' ), + currenEmbedBlock, 'Video content. Should render valid figure element, and include the aspect ratio class.' ).toHaveClass( /wp-embed-aspect-16-9/ ); From ace97353e22183c395fa9abd903fe3a19fe73826 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Tue, 8 Oct 2024 17:45:15 +0800 Subject: [PATCH 1105/1908] Pattern block: Ensure consistent editing of overrides in Write Mode (#65408) * Move pattern block block editing state to store selector Fix broken `getEnabledBlockParents` selector unit tests Update test Fix flash of content when in zoom out mode * Combine into one selector * Add unit tests * Add zoom out pattern block editing mode test ---- Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> --- .../src/store/private-selectors.js | 18 +++ packages/block-editor/src/store/selectors.js | 38 ++++++ .../src/store/test/private-selectors.js | 3 +- .../block-editor/src/store/test/selectors.js | 112 +++++++++++++++++- packages/block-library/src/block/edit.js | 57 +-------- 5 files changed, 175 insertions(+), 53 deletions(-) diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index c3228980310656..eeb987fc00f616 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -684,3 +684,21 @@ export function getClosestAllowedInsertionPointForPattern( export function getInsertionPoint( state ) { return state.insertionPoint; } + +/** + * Retrieves the number of parent pattern blocks. + * + * @param {Object} state Global application state. + * @param {string} clientId The block client ID. + * + * @return {number} The number of parent pattern blocks. + */ +export function getParentPatternCount( state, clientId ) { + const parents = getBlockParents( state, clientId ); + return parents.reduce( ( count, parent ) => { + if ( getBlockName( state, parent ) === 'core/block' ) { + return count + 1; + } + return count; + }, 0 ); +} diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 6cf6aae296141f..812c48c87e7dca 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -40,6 +40,7 @@ import { getSectionRootClientId, isSectionBlock, getParentSectionBlock, + getParentPatternCount, } from './private-selectors'; /** @@ -2972,6 +2973,43 @@ export const getBlockEditingMode = createRegistrySelector( clientId = ''; } + // Handle pattern blocks (core/block) and the content of those blocks. + const parentPatternCount = getParentPatternCount( state, clientId ); + + // Make the outer pattern block content only mode. + if ( + getBlockName( state, clientId ) === 'core/block' && + parentPatternCount === 0 + ) { + return 'contentOnly'; + } + + if ( parentPatternCount > 0 ) { + // Disable nested patterns. + if ( parentPatternCount > 1 ) { + return 'disabled'; + } + + // Disable pattern content editing in zoom-out mode. + const _isZoomOut = + __unstableGetEditorMode( state ) === 'zoom-out'; + if ( _isZoomOut ) { + return 'disabled'; + } + + // If the block has a binding of any kind, allow content only editing. + const attributes = getBlockAttributes( state, clientId ); + if ( + Object.keys( attributes?.metadata?.bindings ?? {} ) + ?.length > 0 + ) { + return 'contentOnly'; + } + + // Otherwise, the block is part of the pattern source and should not be editable. + return 'disabled'; + } + // In zoom-out mode, override the behavior set by // __unstableSetBlockEditingMode to only allow editing the top-level // sections. diff --git a/packages/block-editor/src/store/test/private-selectors.js b/packages/block-editor/src/store/test/private-selectors.js index cbb75daa4baaa0..cca0714f3856d7 100644 --- a/packages/block-editor/src/store/test/private-selectors.js +++ b/packages/block-editor/src/store/test/private-selectors.js @@ -428,7 +428,6 @@ describe( 'private selectors', () => { 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', ], ] ), - order: new Map( [ [ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', @@ -443,6 +442,7 @@ describe( 'private selectors', () => { ], [ '', [ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337' ] ], ] ), + byClientId: new Map( [] ), }, blockEditingModes: new Map( [ [ '', 'disabled' ], @@ -495,6 +495,7 @@ describe( 'private selectors', () => { ], [ '', [ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337' ] ], ] ), + byClientId: new Map( [] ), }, blockEditingModes: new Map( [ [ '', 'disabled' ], diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index a08c2e0dde1508..67af4d1b631162 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -3079,7 +3079,7 @@ describe( 'selectors', () => { byClientId: new Map( Object.entries( { block1: { name: 'core/test-block-ancestor' }, - block2: { name: 'core/block' }, + block2: { name: 'core/group' }, block3: { name: 'core/test-block-parent' }, } ) ), @@ -4668,4 +4668,114 @@ describe( 'getBlockEditingMode', () => { ) ).toBe( 'disabled' ); } ); + + describe( 'pattern blocks', () => { + const patternBlockState = { + settings: {}, + blocks: { + byClientId: new Map( + Object.entries( { + 'pattern-a': { name: 'core/block' }, + 'pattern-b': { name: 'core/block' }, + 'heading-a': { name: 'core/heading' }, + 'paragraph-a': { name: 'core/paragraph' }, + 'paragraph-b': { name: 'core/paragraph' }, + } ) + ), + order: new Map( + Object.entries( { + '': [ 'pattern-a' ], + 'pattern-a': [ + 'heading-a', + 'paragraph-a', + 'pattern-b', + ], + 'pattern-b': [ 'paragraph-b' ], + } ) + ), + parents: new Map( + Object.entries( { + 'paragraph-b': 'pattern-b', + 'pattern-b': 'pattern-a', + 'paragraph-a': 'pattern-a', + 'heading-a': 'pattern-a', + 'pattern-a': '', + } ) + ), + blockListSettings: { + 'pattern-a': {}, + 'pattern-b': {}, + }, + attributes: new Map( + Object.entries( { + 'paragraph-a': { + metadata: { + bindings: { + __default: { + source: 'core/pattern-overrides', + }, + }, + }, + }, + 'paragraph-b': { + metadata: { + bindings: { + __default: { + source: 'core/pattern-overrides', + }, + }, + }, + }, + } ) + ), + }, + }; + + it( 'should return contentOnly for the outer pattern block', () => { + expect( + getBlockEditingMode( patternBlockState, 'pattern-a' ) + ).toBe( 'contentOnly' ); + } ); + + it( 'should return contentOnly for blocks with bindings in the outer pattern', () => { + expect( + getBlockEditingMode( patternBlockState, 'paragraph-a' ) + ).toBe( 'contentOnly' ); + } ); + + it( 'should return disabled for unbound blocks', () => { + expect( + getBlockEditingMode( patternBlockState, 'heading-a' ) + ).toBe( 'disabled' ); + } ); + + it( 'should return disabled for the nested pattern', () => { + expect( + getBlockEditingMode( patternBlockState, 'pattern-a' ) + ).toBe( 'contentOnly' ); + } ); + + it( 'should return disabled for blocks with bindings in the nested pattern', () => { + expect( + getBlockEditingMode( patternBlockState, 'paragraph-b' ) + ).toBe( 'disabled' ); + } ); + + it( 'should disable all inner blocks of the outer pattern in zoom out mode with the outer pattern in content only mode', () => { + const state = { + ...patternBlockState, + editorMode: 'zoom-out', + }; + expect( getBlockEditingMode( state, 'pattern-a' ) ).toBe( + 'contentOnly' + ); + [ 'paragraph-a', 'paragraph-b', 'heading-a', 'pattern-b' ].forEach( + ( block ) => { + expect( getBlockEditingMode( state, block ) ).toBe( + 'disabled' + ); + } + ); + } ); + } ); } ); diff --git a/packages/block-library/src/block/edit.js b/packages/block-library/src/block/edit.js index 104b07157cba74..3d4d07e52b386a 100644 --- a/packages/block-library/src/block/edit.js +++ b/packages/block-library/src/block/edit.js @@ -7,7 +7,7 @@ import clsx from 'clsx'; * WordPress dependencies */ import { useSelect, useDispatch } from '@wordpress/data'; -import { useRef, useMemo, useEffect } from '@wordpress/element'; +import { useRef, useMemo } from '@wordpress/element'; import { useEntityRecord, store as coreStore, @@ -37,12 +37,10 @@ import { getBlockBindingsSource } from '@wordpress/blocks'; /** * Internal dependencies */ -import { name as patternBlockName } from './index'; import { unlock } from '../lock-unlock'; const { useLayoutClasses } = unlock( blockEditorPrivateApis ); -const { isOverridableBlock, hasOverridableBlocks } = - unlock( patternsPrivateApis ); +const { hasOverridableBlocks } = unlock( patternsPrivateApis ); const fullAlignments = [ 'full', 'wide', 'left', 'right' ]; @@ -75,22 +73,6 @@ const useInferredLayout = ( blocks, parentLayout ) => { }, [ blocks, parentLayout ] ); }; -function setBlockEditMode( setEditMode, blocks, mode ) { - blocks.forEach( ( block ) => { - const editMode = - mode || - ( isOverridableBlock( block ) ? 'contentOnly' : 'disabled' ); - setEditMode( block.clientId, editMode ); - - setBlockEditMode( - setEditMode, - block.innerBlocks, - // Disable editing for nested patterns. - block.name === patternBlockName ? 'disabled' : mode - ); - } ); -} - function RecursionWarning() { const blockProps = useBlockProps(); return ( @@ -171,7 +153,6 @@ function ReusableBlockEdit( { name, attributes: { ref, content }, __unstableParentLayout: parentLayout, - clientId: patternClientId, setAttributes, } ) { const { record, hasResolved } = useEntityRecord( @@ -184,49 +165,24 @@ function ReusableBlockEdit( { } ); const isMissing = hasResolved && ! record; - const { setBlockEditingMode, __unstableMarkLastChangeAsPersistent } = + const { __unstableMarkLastChangeAsPersistent } = useDispatch( blockEditorStore ); - const { - innerBlocks, - onNavigateToEntityRecord, - editingMode, - hasPatternOverridesSource, - } = useSelect( + const { onNavigateToEntityRecord, hasPatternOverridesSource } = useSelect( ( select ) => { - const { getBlocks, getSettings, getBlockEditingMode } = - select( blockEditorStore ); + const { getSettings } = select( blockEditorStore ); // For editing link to the site editor if the theme and user permissions support it. return { - innerBlocks: getBlocks( patternClientId ), onNavigateToEntityRecord: getSettings().onNavigateToEntityRecord, - editingMode: getBlockEditingMode( patternClientId ), hasPatternOverridesSource: !! getBlockBindingsSource( 'core/pattern-overrides' ), }; }, - [ patternClientId ] + [] ); - // Sync the editing mode of the pattern block with the inner blocks. - useEffect( () => { - setBlockEditMode( - setBlockEditingMode, - innerBlocks, - // Disable editing if the pattern itself is disabled. - editingMode === 'disabled' || ! hasPatternOverridesSource - ? 'disabled' - : undefined - ); - }, [ - editingMode, - innerBlocks, - setBlockEditingMode, - hasPatternOverridesSource, - ] ); - const canOverrideBlocks = useMemo( () => hasPatternOverridesSource && hasOverridableBlocks( blocks ), [ hasPatternOverridesSource, blocks ] @@ -244,7 +200,6 @@ function ReusableBlockEdit( { } ); const innerBlocksProps = useInnerBlocksProps( blockProps, { - templateLock: 'all', layout, value: blocks, onInput: NOOP, From 6bf18c223b51e72fbf7dd32aa28c848ec7661cee Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 8 Oct 2024 19:21:12 +0900 Subject: [PATCH 1106/1908] e2e: fix Block Visibility test (#65939) Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- test/e2e/specs/editor/various/block-visibility.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e/specs/editor/various/block-visibility.spec.js b/test/e2e/specs/editor/various/block-visibility.spec.js index bed337624275e4..814276af6e25f1 100644 --- a/test/e2e/specs/editor/various/block-visibility.spec.js +++ b/test/e2e/specs/editor/various/block-visibility.spec.js @@ -48,7 +48,7 @@ test.describe( 'Block Visibility', () => { await page .getByRole( 'region', { name: 'Block Library' } ) .getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ) .fill( 'Heading' ); @@ -89,7 +89,7 @@ test.describe( 'Block Visibility', () => { await page .getByRole( 'region', { name: 'Block Library' } ) .getByRole( 'searchbox', { - name: 'Search for blocks and patterns', + name: 'Search', } ) .fill( 'Heading' ); From b6c3f8f3e23ba1679a9e38caed84dd914257f07a Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Tue, 8 Oct 2024 12:34:43 +0200 Subject: [PATCH 1107/1908] Fix navigate regions shortcuts on the back button WP logo slot (#63611) * Avoid to pass unnecessary props to useNavigateRegions. * Remove bubblesVirtually from WP logo slot. * Restore bubblesVirtually. * Move useNavigateRegions to an outermost ancestor. * Remove no longer used enableRegionNavigation prop. * Add changelog entry --------- Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../edit-post/src/components/layout/index.js | 89 ++++++++++--------- .../edit-site/src/components/editor/index.js | 1 - .../edit-site/src/components/layout/index.js | 30 ++----- .../src/components/layout/index.js | 25 ++++-- .../src/components/layout/interface.js | 15 ---- .../src/components/editor-interface/index.js | 15 ---- packages/interface/CHANGELOG.md | 4 + .../components/interface-skeleton/index.js | 14 +-- 8 files changed, 78 insertions(+), 115 deletions(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 66fa9dd5d93b8a..e7411fe8c3ab6e 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -47,6 +47,7 @@ import { SlotFillProvider, Tooltip, VisuallyHidden, + __unstableUseNavigateRegions as useNavigateRegions, } from '@wordpress/components'; import { useMediaQuery, @@ -482,6 +483,8 @@ function Layout( { document.body.classList.remove( 'show-icon-labels' ); } + const navigateRegionsProps = useNavigateRegions(); + const className = clsx( 'edit-post-layout', 'is-mode-' + mode, { 'has-metaboxes': hasActiveMetaboxes, } ); @@ -567,47 +570,53 @@ function Layout( { <ErrorBoundary> <CommandMenu /> <WelcomeGuide postType={ currentPostType } /> - <Editor - settings={ editorSettings } - initialEdits={ initialEdits } - postType={ currentPostType } - postId={ currentPostId } - templateId={ templateId } - className={ className } - styles={ styles } - forceIsDirty={ hasActiveMetaboxes } - contentRef={ paddingAppenderRef } - disableIframe={ ! shouldIframe } - // We should auto-focus the canvas (title) on load. - // eslint-disable-next-line jsx-a11y/no-autofocus - autoFocus={ ! isWelcomeGuideVisible } - onActionPerformed={ onActionPerformed } - extraSidebarPanels={ - showMetaBoxes && <MetaBoxes location="side" /> - } - extraContent={ - ! isDistractionFree && - showMetaBoxes && ( - <MetaBoxesMain isLegacy={ ! shouldIframe } /> - ) - } + <div + className={ navigateRegionsProps.className } + { ...navigateRegionsProps } + ref={ navigateRegionsProps.ref } > - <PostLockedModal /> - <EditorInitialization /> - <FullscreenMode isActive={ isFullscreenActive } /> - <BrowserURL hasHistory={ hasHistory } /> - <UnsavedChangesWarning /> - <AutosaveMonitor /> - <LocalAutosaveMonitor /> - <EditPostKeyboardShortcuts /> - <EditorKeyboardShortcutsRegister /> - <BlockKeyboardShortcuts /> - <InitPatternModal /> - <PluginArea onError={ onPluginAreaError } /> - <PostEditorMoreMenu /> - { backButton } - <EditorSnackbars /> - </Editor> + <Editor + settings={ editorSettings } + initialEdits={ initialEdits } + postType={ currentPostType } + postId={ currentPostId } + templateId={ templateId } + className={ className } + styles={ styles } + forceIsDirty={ hasActiveMetaboxes } + contentRef={ paddingAppenderRef } + disableIframe={ ! shouldIframe } + // We should auto-focus the canvas (title) on load. + // eslint-disable-next-line jsx-a11y/no-autofocus + autoFocus={ ! isWelcomeGuideVisible } + onActionPerformed={ onActionPerformed } + extraSidebarPanels={ + showMetaBoxes && <MetaBoxes location="side" /> + } + extraContent={ + ! isDistractionFree && + showMetaBoxes && ( + <MetaBoxesMain isLegacy={ ! shouldIframe } /> + ) + } + > + <PostLockedModal /> + <EditorInitialization /> + <FullscreenMode isActive={ isFullscreenActive } /> + <BrowserURL hasHistory={ hasHistory } /> + <UnsavedChangesWarning /> + <AutosaveMonitor /> + <LocalAutosaveMonitor /> + <EditPostKeyboardShortcuts /> + <EditorKeyboardShortcutsRegister /> + <BlockKeyboardShortcuts /> + <InitPatternModal /> + <PluginArea onError={ onPluginAreaError } /> + <PostEditorMoreMenu /> + { backButton } + <EditorSnackbars /> + </Editor> + </div> </ErrorBoundary> </SlotFillProvider> ); diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 855225081236c8..ae8749a3677afd 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -230,7 +230,6 @@ export default function EditSiteEditor( { isPostsList = false } ) { 'show-icon-labels': showIconLabels, } ) } styles={ styles } - enableRegionNavigation={ false } customSaveButton={ _isPreviewingTheme && <SaveButton size="compact" /> } diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index c54b7efa382c66..2619f7c96dcf74 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -20,7 +20,6 @@ import { } from '@wordpress/compose'; import { __ } from '@wordpress/i18n'; import { useState, useRef, useEffect } from '@wordpress/element'; -import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts'; import { CommandMenu } from '@wordpress/commands'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { @@ -57,28 +56,13 @@ export default function Layout( { route } ) { useCommands(); const isMobileViewport = useViewportMatch( 'medium', '<' ); const toggleRef = useRef(); - const { canvasMode, previousShortcut, nextShortcut } = useSelect( - ( select ) => { - const { getAllShortcutKeyCombinations } = select( - keyboardShortcutsStore - ); - const { getCanvasMode } = unlock( select( editSiteStore ) ); - return { - canvasMode: getCanvasMode(), - previousShortcut: getAllShortcutKeyCombinations( - 'core/editor/previous-region' - ), - nextShortcut: getAllShortcutKeyCombinations( - 'core/editor/next-region' - ), - }; - }, - [] - ); - const navigateRegionsProps = useNavigateRegions( { - previous: previousShortcut, - next: nextShortcut, - } ); + const { canvasMode } = useSelect( ( select ) => { + const { getCanvasMode } = unlock( select( editSiteStore ) ); + return { + canvasMode: getCanvasMode(), + }; + }, [] ); + const navigateRegionsProps = useNavigateRegions(); const disableMotion = useReducedMotion(); const [ canvasResizer, canvasSize ] = useResizeObserver(); const isEditorLoading = useIsSiteEditorLoading(); diff --git a/packages/edit-widgets/src/components/layout/index.js b/packages/edit-widgets/src/components/layout/index.js index 54338d10fb8503..4fc70a6c0c74eb 100644 --- a/packages/edit-widgets/src/components/layout/index.js +++ b/packages/edit-widgets/src/components/layout/index.js @@ -5,6 +5,7 @@ import { __, sprintf } from '@wordpress/i18n'; import { useDispatch } from '@wordpress/data'; import { PluginArea } from '@wordpress/plugins'; import { store as noticesStore } from '@wordpress/notices'; +import { __unstableUseNavigateRegions as useNavigateRegions } from '@wordpress/components'; /** * Internal dependencies @@ -31,17 +32,25 @@ function Layout( { blockEditorSettings } ) { ); } + const navigateRegionsProps = useNavigateRegions(); + return ( <ErrorBoundary> - <WidgetAreasBlockEditorProvider - blockEditorSettings={ blockEditorSettings } + <div + className={ navigateRegionsProps.className } + { ...navigateRegionsProps } + ref={ navigateRegionsProps.ref } > - <Interface blockEditorSettings={ blockEditorSettings } /> - <Sidebar /> - <PluginArea onError={ onPluginAreaError } /> - <UnsavedChangesWarning /> - <WelcomeGuide /> - </WidgetAreasBlockEditorProvider> + <WidgetAreasBlockEditorProvider + blockEditorSettings={ blockEditorSettings } + > + <Interface blockEditorSettings={ blockEditorSettings } /> + <Sidebar /> + <PluginArea onError={ onPluginAreaError } /> + <UnsavedChangesWarning /> + <WelcomeGuide /> + </WidgetAreasBlockEditorProvider> + </div> </ErrorBoundary> ); } diff --git a/packages/edit-widgets/src/components/layout/interface.js b/packages/edit-widgets/src/components/layout/interface.js index ee46251eca2245..bec40a6e830699 100644 --- a/packages/edit-widgets/src/components/layout/interface.js +++ b/packages/edit-widgets/src/components/layout/interface.js @@ -11,7 +11,6 @@ import { store as interfaceStore, } from '@wordpress/interface'; import { __ } from '@wordpress/i18n'; -import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts'; import { store as preferencesStore } from '@wordpress/preferences'; /** @@ -43,8 +42,6 @@ function Interface( { blockEditorSettings } ) { hasSidebarEnabled, isInserterOpened, isListViewOpened, - previousShortcut, - nextShortcut, } = useSelect( ( select ) => ( { hasSidebarEnabled: !! select( @@ -56,14 +53,6 @@ function Interface( { blockEditorSettings } ) { 'core/edit-widgets', 'showBlockBreadcrumbs' ), - previousShortcut: select( - keyboardShortcutsStore - ).getAllShortcutKeyCombinations( - 'core/edit-widgets/previous-region' - ), - nextShortcut: select( - keyboardShortcutsStore - ).getAllShortcutKeyCombinations( 'core/edit-widgets/next-region' ), } ), [] ); @@ -112,10 +101,6 @@ function Interface( { blockEditorSettings } ) { </div> ) } - shortcuts={ { - previous: previousShortcut, - next: nextShortcut, - } } /> ); } diff --git a/packages/editor/src/components/editor-interface/index.js b/packages/editor/src/components/editor-interface/index.js index 0709b91175712d..6dc4c3fe770608 100644 --- a/packages/editor/src/components/editor-interface/index.js +++ b/packages/editor/src/components/editor-interface/index.js @@ -15,7 +15,6 @@ import { BlockBreadcrumb, BlockToolbar, } from '@wordpress/block-editor'; -import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts'; import { useViewportMatch } from '@wordpress/compose'; import { useState, useCallback } from '@wordpress/element'; @@ -49,7 +48,6 @@ const interfaceLabels = { export default function EditorInterface( { className, - enableRegionNavigation, styles, children, forceIsDirty, @@ -69,8 +67,6 @@ export default function EditorInterface( { isListViewOpened, isDistractionFree, isPreviewMode, - previousShortcut, - nextShortcut, showBlockBreadcrumbs, documentLabel, isZoomOut, @@ -88,12 +84,6 @@ export default function EditorInterface( { isListViewOpened: select( editorStore ).isListViewOpened(), isDistractionFree: get( 'core', 'distractionFree' ), isPreviewMode: editorSettings.__unstableIsPreviewMode, - previousShortcut: select( - keyboardShortcutsStore - ).getAllShortcutKeyCombinations( 'core/editor/previous-region' ), - nextShortcut: select( - keyboardShortcutsStore - ).getAllShortcutKeyCombinations( 'core/editor/next-region' ), showBlockBreadcrumbs: get( 'core', 'showBlockBreadcrumbs' ), // translators: Default label for the Document in the Block Breadcrumb. documentLabel: postTypeLabel || _x( 'Document', 'noun' ), @@ -121,7 +111,6 @@ export default function EditorInterface( { return ( <InterfaceSkeleton - enableRegionNavigation={ enableRegionNavigation } isDistractionFree={ isDistractionFree } className={ clsx( 'editor-editor-interface', className, { 'is-entity-save-view-open': !! entitiesSavedStatesCallback, @@ -231,10 +220,6 @@ export default function EditorInterface( { ) : undefined } - shortcuts={ { - previous: previousShortcut, - next: nextShortcut, - } } /> ); } diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index f590aeed5b6ccc..985fed5a140437 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- `InterfaceSkeleton` no longer supports region navigation and its props `enableRegionNavigation` and `shortcuts` are removed. ([#63611](https://github.com/WordPress/gutenberg/pull/63611)). It’s recommended to add region navigation with the higher-order component `navigateRegions` or the hook `__unstableUseNavigateRegions` from `@wordpress/components`. + ## 6.9.0 (2024-10-03) ## 6.8.0 (2024-09-19) diff --git a/packages/interface/src/components/interface-skeleton/index.js b/packages/interface/src/components/interface-skeleton/index.js index a1fd20b642206f..0a49db4f159d88 100644 --- a/packages/interface/src/components/interface-skeleton/index.js +++ b/packages/interface/src/components/interface-skeleton/index.js @@ -8,13 +8,11 @@ import clsx from 'clsx'; */ import { forwardRef, useEffect } from '@wordpress/element'; import { - __unstableUseNavigateRegions as useNavigateRegions, __unstableMotion as motion, __unstableAnimatePresence as AnimatePresence, } from '@wordpress/components'; import { __, _x } from '@wordpress/i18n'; import { - useMergeRefs, useReducedMotion, useViewportMatch, useResizeObserver, @@ -85,10 +83,6 @@ function InterfaceSkeleton( actions, labels, className, - enableRegionNavigation = true, - // Todo: does this need to be a prop. - // Can we use a dependency to keyboard-shortcuts directly? - shortcuts, }, ref ) { @@ -101,7 +95,6 @@ function InterfaceSkeleton( duration: disableMotion ? 0 : ANIMATION_DURATION, ease: [ 0.6, 0, 0.4, 1 ], }; - const navigateRegionsProps = useNavigateRegions( shortcuts ); useHTMLClass( 'interface-interface-skeleton__html-container' ); const defaultLabels = { @@ -123,15 +116,10 @@ function InterfaceSkeleton( return ( <div - { ...( enableRegionNavigation ? navigateRegionsProps : {} ) } - ref={ useMergeRefs( [ - ref, - enableRegionNavigation ? navigateRegionsProps.ref : undefined, - ] ) } + ref={ ref } className={ clsx( className, 'interface-interface-skeleton', - navigateRegionsProps.className, !! footer && 'has-footer' ) } > From 8ae8cc11df445ae864f4e7ccdfd7fa0a6d256446 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:00:03 +0200 Subject: [PATCH 1108/1908] Update "hidden" icon to be clearer, and invert logic as used in Data Views (#65914) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/dataviews/CHANGELOG.md | 2 ++ .../dataviews/src/components/dataviews-view-config/index.tsx | 2 +- packages/icons/CHANGELOG.md | 4 ++++ packages/icons/src/library/unseen.js | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 7569cfb93ac0b6..ebc35e336d6876 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Invert the logic for which icon to show in `DataViews` when using the filter view. Icons now match the action of the button label. ([#65914](https://github.com/WordPress/gutenberg/pull/65914)). + ## 4.5.0 (2024-10-03) ## 4.4.0 (2024-09-19) diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index 02e81b2b0913d8..ec4a5f9a7f1d0a 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -358,7 +358,7 @@ function FieldItem( { } }, 50 ); } } - icon={ isVisible ? seen : unseen } + icon={ isVisible ? unseen : seen } label={ isVisible ? sprintf( diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index b1b19fdfbc0f2f..c0ee7aab2cf986 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Update `unseen` icon to be a strike-through eye, rather than a closed eye, to match provide consistency. ([#65914](https://github.com/WordPress/gutenberg/pull/65914)). + ## 10.9.0 (2024-10-03) ## 10.8.0 (2024-09-19) diff --git a/packages/icons/src/library/unseen.js b/packages/icons/src/library/unseen.js index 384c67d08ff55f..bb73a2199e1ee4 100644 --- a/packages/icons/src/library/unseen.js +++ b/packages/icons/src/library/unseen.js @@ -5,7 +5,7 @@ import { SVG, Path } from '@wordpress/primitives'; const unseen = ( <SVG viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> - <Path d="M4.67 10.664s-2.09 1.11-2.917 1.582l.494.87 1.608-.914.002.002c.343.502.86 1.17 1.563 1.84.348.33.742.663 1.185.976L5.57 16.744l.858.515 1.02-1.701a9.1 9.1 0 0 0 4.051 1.18V19h1v-2.263a9.1 9.1 0 0 0 4.05-1.18l1.021 1.7.858-.514-1.034-1.723c.442-.313.837-.646 1.184-.977.703-.669 1.22-1.337 1.563-1.839l.002-.003 1.61.914.493-.87c-1.75-.994-2.918-1.58-2.918-1.58l-.003.005a8.29 8.29 0 0 1-.422.689 10.097 10.097 0 0 1-1.36 1.598c-1.218 1.16-3.042 2.293-5.544 2.293-2.503 0-4.327-1.132-5.546-2.293a10.099 10.099 0 0 1-1.359-1.599 8.267 8.267 0 0 1-.422-.689l-.003-.005Z" /> + <Path d="M20.7 12.7s0-.1-.1-.2c0-.2-.2-.4-.4-.6-.3-.5-.9-1.2-1.6-1.8-.7-.6-1.5-1.3-2.6-1.8l-.6 1.4c.9.4 1.6 1 2.1 1.5.6.6 1.1 1.2 1.4 1.6.1.2.3.4.3.5v.1l.7-.3.7-.3Zm-5.2-9.3-1.8 4c-.5-.1-1.1-.2-1.7-.2-3 0-5.2 1.4-6.6 2.7-.7.7-1.2 1.3-1.6 1.8-.2.3-.3.5-.4.6 0 0 0 .1-.1.2s0 0 .7.3l.7.3V13c0-.1.2-.3.3-.5.3-.4.7-1 1.4-1.6 1.2-1.2 3-2.3 5.5-2.3H13v.3c-.4 0-.8-.1-1.1-.1-1.9 0-3.5 1.6-3.5 3.5s.6 2.3 1.6 2.9l-2 4.4.9.4 7.6-16.2-.9-.4Zm-3 12.6c1.7-.2 3-1.7 3-3.5s-.2-1.4-.6-1.9L12.4 16Z" /> </SVG> ); From 4dc8a020171dbf2ef5c84216e09ddbaf96adeded Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:06:15 +0200 Subject: [PATCH 1109/1908] Block Bindings: Register bindings sources in widgets screens (#65937) * Register sources in customize-widgets * Register sources in edit-widgets Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- package-lock.json | 2 ++ packages/customize-widgets/package.json | 1 + packages/customize-widgets/src/index.js | 11 +++++++++++ packages/edit-widgets/package.json | 1 + packages/edit-widgets/src/index.js | 10 +++++++++- 5 files changed, 24 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 4f52b5ca3e465a..5de2d0320139ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53494,6 +53494,7 @@ "@wordpress/core-data": "file:../core-data", "@wordpress/data": "file:../data", "@wordpress/dom": "file:../dom", + "@wordpress/editor": "file:../editor", "@wordpress/element": "file:../element", "@wordpress/hooks": "file:../hooks", "@wordpress/i18n": "file:../i18n", @@ -53929,6 +53930,7 @@ "@wordpress/data": "file:../data", "@wordpress/deprecated": "file:../deprecated", "@wordpress/dom": "file:../dom", + "@wordpress/editor": "file:../editor", "@wordpress/element": "file:../element", "@wordpress/hooks": "file:../hooks", "@wordpress/i18n": "file:../i18n", diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 7231de9ac1b18f..32f79cbd3c3b5d 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -33,6 +33,7 @@ "@wordpress/core-data": "file:../core-data", "@wordpress/data": "file:../data", "@wordpress/dom": "file:../dom", + "@wordpress/editor": "file:../editor", "@wordpress/element": "file:../element", "@wordpress/hooks": "file:../hooks", "@wordpress/i18n": "file:../i18n", diff --git a/packages/customize-widgets/src/index.js b/packages/customize-widgets/src/index.js index 5de010fa8bd37e..35be3c2ee4b14b 100644 --- a/packages/customize-widgets/src/index.js +++ b/packages/customize-widgets/src/index.js @@ -17,6 +17,7 @@ import { store as blocksStore, } from '@wordpress/blocks'; import { dispatch } from '@wordpress/data'; +import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { store as preferencesStore } from '@wordpress/preferences'; /** @@ -26,6 +27,7 @@ import CustomizeWidgets from './components/customize-widgets'; import getSidebarSection from './controls/sidebar-section'; import getSidebarControl from './controls/sidebar-control'; import './filters'; +import { unlock } from './lock-unlock'; const { wp } = window; @@ -37,6 +39,11 @@ const DISABLED_BLOCKS = [ ]; const ENABLE_EXPERIMENTAL_FSE_BLOCKS = false; +const { + registerCoreBlockBindingsSources, + bootstrapBlockBindingsSourcesFromServer, +} = unlock( editorPrivateApis ); + /** * Initializes the widgets block editor in the customizer. * @@ -60,6 +67,10 @@ export function initialize( editorName, blockEditorSettings ) { ); } ); registerCoreBlocks( coreBlocks ); + bootstrapBlockBindingsSourcesFromServer( + blockEditorSettings?.blockBindingsSources + ); + registerCoreBlockBindingsSources(); registerLegacyWidgetBlock(); if ( globalThis.IS_GUTENBERG_PLUGIN ) { __experimentalRegisterExperimentalCoreBlocks( { diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index e9d0f18df460a6..39bdee011a55c1 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -38,6 +38,7 @@ "@wordpress/data": "file:../data", "@wordpress/deprecated": "file:../deprecated", "@wordpress/dom": "file:../dom", + "@wordpress/editor": "file:../editor", "@wordpress/element": "file:../element", "@wordpress/hooks": "file:../hooks", "@wordpress/i18n": "file:../i18n", diff --git a/packages/edit-widgets/src/index.js b/packages/edit-widgets/src/index.js index f8247d733f1a15..fadd488a702cfe 100644 --- a/packages/edit-widgets/src/index.js +++ b/packages/edit-widgets/src/index.js @@ -9,6 +9,7 @@ import { } from '@wordpress/blocks'; import { dispatch } from '@wordpress/data'; import deprecated from '@wordpress/deprecated'; +import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { StrictMode, createRoot } from '@wordpress/element'; import { registerCoreBlocks, @@ -29,7 +30,7 @@ import { store as preferencesStore } from '@wordpress/preferences'; import './store'; import './filters'; import * as widgetArea from './blocks/widget-area'; - +import { unlock } from './lock-unlock'; import Layout from './components/layout'; import { ALLOW_REUSABLE_BLOCKS, @@ -43,6 +44,11 @@ const disabledBlocks = [ ...( ALLOW_REUSABLE_BLOCKS ? [] : [ 'core/block' ] ), ]; +const { + registerCoreBlockBindingsSources, + bootstrapBlockBindingsSourcesFromServer, +} = unlock( editorPrivateApis ); + /** * Initializes the block editor in the widgets screen. * @@ -72,6 +78,8 @@ export function initializeEditor( id, settings ) { dispatch( blocksStore ).reapplyBlockTypeFilters(); registerCoreBlocks( coreBlocks ); + bootstrapBlockBindingsSourcesFromServer( settings?.blockBindingsSources ); + registerCoreBlockBindingsSources(); registerLegacyWidgetBlock(); if ( globalThis.IS_GUTENBERG_PLUGIN ) { __experimentalRegisterExperimentalCoreBlocks( { From d716a253bb3a232aab4349be32f41af70b7985d2 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 8 Oct 2024 14:31:22 +0200 Subject: [PATCH 1110/1908] Global styles: leave screen if current shadow entry gets deleted (#65935) * Global styles: leave screen if current shadow entry gets deleted * Refine approach * Apply feedback --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: nith53 <nithins53@git.wordpress.org> Co-authored-by: benniledl <benniledl@git.wordpress.org> --- .../global-styles/shadows-edit-panel.js | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js index 61bed62cff3d64..af5f3445a51190 100644 --- a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js +++ b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js @@ -35,7 +35,7 @@ import { reset, moreVertical, } from '@wordpress/icons'; -import { useState, useMemo } from '@wordpress/element'; +import { useState, useMemo, useEffect } from '@wordpress/element'; /** * Internal dependencies @@ -73,12 +73,30 @@ const presetShadowMenuItems = [ export default function ShadowsEditPanel() { const { + goBack, params: { category, slug }, - goTo, } = useNavigator(); const [ shadows, setShadows ] = useGlobalSetting( `shadow.presets.${ category }` ); + + useEffect( () => { + const hasCurrentShadow = shadows?.some( + ( shadow ) => shadow.slug === slug + ); + // If the shadow being edited doesn't exist anymore in the global styles setting, navigate back + // to prevent the user from editing a non-existent shadow entry. + // This can happen, for example: + // - when the user deletes the shadow + // - when the user resets the styles while editing a custom shadow + // + // The check on the slug is necessary to prevent a double back navigation when the user triggers + // a backward navigation by interacting with the screen's UI. + if ( !! slug && ! hasCurrentShadow ) { + goBack(); + } + }, [ shadows, slug, goBack ] ); + const [ baseShadows ] = useGlobalSetting( `shadow.presets.${ category }`, undefined, @@ -123,9 +141,7 @@ export default function ShadowsEditPanel() { }; const handleShadowDelete = () => { - const updatedShadows = shadows.filter( ( s ) => s.slug !== slug ); - setShadows( updatedShadows ); - goTo( `/shadows` ); + setShadows( shadows.filter( ( s ) => s.slug !== slug ) ); }; const handleShadowRename = ( newName ) => { From 79940e0ca94cd814631e9a29f2d9178352246c70 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 8 Oct 2024 14:32:02 +0200 Subject: [PATCH 1111/1908] Global styles: improve Navigator usage in typography panel (#65942) * Global styles: remove trailing slack from font sizes screen path * Remove unncessary goTo * Use goBack instead of goTo, add extra slug check to avoid double goBack call --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/global-styles/font-sizes/font-size.js | 9 ++++----- .../global-styles/font-sizes/font-sizes-count.js | 2 +- packages/edit-site/src/components/global-styles/ui.js | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js index b99703d39c8d62..43418f9caf5eb6 100644 --- a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js @@ -36,7 +36,7 @@ function FontSize() { const { params: { origin, slug }, - goTo, + goBack, } = useNavigator(); const [ fontSizes, setFontSizes ] = useGlobalSetting( @@ -53,10 +53,10 @@ function FontSize() { // Navigate to the font sizes list if the font size is not available. useEffect( () => { - if ( ! fontSize ) { - goTo( '/typography/font-sizes/', { isBack: true } ); + if ( !! slug && ! fontSize ) { + goBack(); } - }, [ fontSize, goTo ] ); + }, [ slug, fontSize, goBack ] ); if ( ! origin || ! slug || ! fontSize ) { return null; @@ -158,7 +158,6 @@ function FontSize() { __( 'Manage the font size %s.' ), fontSize.name ) } - onBack={ () => goTo( '/typography/font-sizes/' ) } /> { origin === 'custom' && ( <FlexItem> diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-sizes-count.js b/packages/edit-site/src/components/global-styles/font-sizes/font-sizes-count.js index 8c8c79772ecbf3..c268648a134a74 100644 --- a/packages/edit-site/src/components/global-styles/font-sizes/font-sizes-count.js +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-sizes-count.js @@ -24,7 +24,7 @@ function FontSizes() { </HStack> <ItemGroup isBordered isSeparated> <NavigationButtonAsItem - path="/typography/font-sizes/" + path="/typography/font-sizes" aria-label={ __( 'Edit font size presets' ) } > <HStack direction="row"> diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index fbc3e461e6abb6..d534da901cd2e2 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -302,7 +302,7 @@ function GlobalStylesUI() { <ScreenTypography /> </GlobalStylesNavigationScreen> - <GlobalStylesNavigationScreen path="/typography/font-sizes/"> + <GlobalStylesNavigationScreen path="/typography/font-sizes"> <FontSizes /> </GlobalStylesNavigationScreen> From 4c0f72985a540e20d88374cb67abe289cf36f4fb Mon Sep 17 00:00:00 2001 From: Matias Benedetto <matias.benedetto@gmail.com> Date: Tue, 8 Oct 2024 10:11:07 -0300 Subject: [PATCH 1112/1908] List all active fonts in the typography section (#65806) * list all active fonts * sort active fonts alphabetically also skip unnecessary sorts * abstract font source mapping into function --------- Co-authored-by: Vicente Canales <1157901+vcanales@users.noreply.github.com> --- .../components/global-styles/font-families.js | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-families.js b/packages/edit-site/src/components/global-styles/font-families.js index 5332478823c210..cd1697b7b79bd8 100644 --- a/packages/edit-site/src/components/global-styles/font-families.js +++ b/packages/edit-site/src/components/global-styles/font-families.js @@ -25,6 +25,19 @@ import { unlock } from '../../lock-unlock'; const { useGlobalSetting } = unlock( blockEditorPrivateApis ); +/** + * Maps the fonts with the source, if available. + * + * @param {Array} fonts The fonts to map. + * @param {string} source The source of the fonts. + * @return {Array} The mapped fonts. + */ +function mapFontsWithSource( fonts, source ) { + return fonts + ? fonts.map( ( f ) => setUIValuesNeeded( f, { source } ) ) + : []; +} + function FontFamilies() { const { baseCustomFonts, modalTabOpen, setModalTabOpen } = useContext( FontLibraryContext ); @@ -34,18 +47,12 @@ function FontFamilies() { undefined, 'base' ); - const themeFonts = fontFamilies?.theme - ? fontFamilies.theme - .map( ( f ) => setUIValuesNeeded( f, { source: 'theme' } ) ) - .sort( ( a, b ) => a.name.localeCompare( b.name ) ) - : []; - const customFonts = fontFamilies?.custom - ? fontFamilies.custom - .map( ( f ) => setUIValuesNeeded( f, { source: 'custom' } ) ) - .sort( ( a, b ) => a.name.localeCompare( b.name ) ) - : []; - const hasFonts = 0 < customFonts.length || 0 < themeFonts.length; - + const themeFonts = mapFontsWithSource( fontFamilies?.theme, 'theme' ); + const customFonts = mapFontsWithSource( fontFamilies?.custom, 'custom' ); + const activeFonts = [ ...themeFonts, ...customFonts ].sort( ( a, b ) => + a.name.localeCompare( b.name ) + ); + const hasFonts = 0 < activeFonts.length; const hasInstalledFonts = hasFonts || baseFontFamilies?.theme?.length > 0 || @@ -61,11 +68,11 @@ function FontFamilies() { ) } <VStack spacing={ 4 }> - { [ ...themeFonts, ...customFonts ].length > 0 && ( + { activeFonts.length > 0 && ( <> <Subtitle level={ 3 }>{ __( 'Fonts' ) }</Subtitle> <ItemGroup size="large" isBordered isSeparated> - { themeFonts.map( ( font ) => ( + { activeFonts.map( ( font ) => ( <FontFamilyItem key={ font.slug } font={ font } From 076be0ccab3a7102924b2e14b1896014a36cddb8 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Tue, 8 Oct 2024 14:13:16 +0100 Subject: [PATCH 1113/1908] Use correct label in PHP Backport documentation (#65908) Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- docs/contributors/code/back-merging-to-wp-core.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributors/code/back-merging-to-wp-core.md b/docs/contributors/code/back-merging-to-wp-core.md index d6c283629e1938..2ae1efb1727415 100644 --- a/docs/contributors/code/back-merging-to-wp-core.md +++ b/docs/contributors/code/back-merging-to-wp-core.md @@ -31,7 +31,7 @@ There are however certain exceptions to that rule. PRs with the following criter - Does not contain changes to PHP code. - Has label `Backport from WordPress Core` - this code is already in WP Core and is being synchronized back to Gutenberg. -- Has label `Backport to WordPress Core` - this code has already been synchronized to WP Core. +- Has label `Backported to WordPress Core` - this code has already been synchronized to WP Core. ## Further Reading From 41141266da91fce8c1e4b711cb6ca5e7ff1a2dce Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Tue, 8 Oct 2024 07:15:44 -0700 Subject: [PATCH 1114/1908] Post editor: Fix "typewriter" spacing style application (#65885) * Add parameter to enable/disable hook * Separate concerns of useEditorStyles and usePaddingAppender Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../edit-post/src/components/layout/index.js | 53 ++++++++----------- .../components/layout/use-padding-appender.js | 22 +++----- 2 files changed, 29 insertions(+), 46 deletions(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index e7411fe8c3ab6e..20ef22b5f0eb25 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -85,27 +85,17 @@ const DESIGN_POST_TYPES = [ 'wp_navigation', ]; -function useEditorStyles() { - const { - hasThemeStyleSupport, - editorSettings, - isZoomedOutView, - renderingMode, - postType, - } = useSelect( ( select ) => { - const { __unstableGetEditorMode } = select( blockEditorStore ); - const { getCurrentPostType, getRenderingMode } = select( editorStore ); - const _postType = getCurrentPostType(); +function useEditorStyles( ...additionalStyles ) { + const { hasThemeStyleSupport, editorSettings } = useSelect( ( select ) => { return { hasThemeStyleSupport: select( editPostStore ).isFeatureActive( 'themeStyles' ), editorSettings: select( editorStore ).getEditorSettings(), - isZoomedOutView: __unstableGetEditorMode() === 'zoom-out', - renderingMode: getRenderingMode(), - postType: _postType, }; }, [] ); + const addedStyles = additionalStyles.join( '\n' ); + // Compute the default styles. return useMemo( () => { const presetStyles = @@ -142,19 +132,8 @@ function useEditorStyles() { ? editorSettings.styles ?? [] : defaultEditorStyles; - // Add a space for the typewriter effect. When typing in the last block, - // there needs to be room to scroll up. - if ( - ! isZoomedOutView && - renderingMode === 'post-only' && - ! DESIGN_POST_TYPES.includes( postType ) - ) { - return [ - ...baseStyles, - { - css: ':root :where(.editor-styles-wrapper)::after {content: ""; display: block; height: 40vh;}', - }, - ]; + if ( addedStyles ) { + return [ ...baseStyles, { css: addedStyles } ]; } return baseStyles; @@ -163,7 +142,7 @@ function useEditorStyles() { editorSettings.disableLayoutStyles, editorSettings.styles, hasThemeStyleSupport, - postType, + addedStyles, ] ); } @@ -395,7 +374,6 @@ function Layout( { } ) { useCommands(); useEditPostCommands(); - const paddingAppenderRef = usePaddingAppender(); const shouldIframe = useShouldIframe(); const { createErrorNotice } = useDispatch( noticesStore ); const { @@ -419,6 +397,7 @@ function Layout( { hasHistory, isWelcomeGuideVisible, templateId, + enablePaddingAppender, } = useSelect( ( select ) => { const { get } = select( preferencesStore ); @@ -434,9 +413,12 @@ function Layout( { kind: 'postType', name: 'wp_template', } ); + const { __unstableGetEditorMode } = select( blockEditorStore ); + const { getEditorMode, getRenderingMode } = select( editorStore ); + const isRenderingPostOnly = getRenderingMode() === 'post-only'; return { - mode: select( editorStore ).getEditorMode(), + mode: getEditorMode(), isFullscreenActive: select( editPostStore ).isFeatureActive( 'fullscreenMode' ), hasActiveMetaboxes: select( editPostStore ).hasMetaBoxes(), @@ -446,7 +428,7 @@ function Layout( { isDistractionFree: get( 'core', 'distractionFree' ), showMetaBoxes: ! DESIGN_POST_TYPES.includes( currentPostType ) && - select( editorStore ).getRenderingMode() === 'post-only', + isRenderingPostOnly, isWelcomeGuideVisible: isFeatureActive( 'welcomeGuide' ), templateId: supportsTemplateMode && @@ -455,10 +437,17 @@ function Layout( { ! isEditingTemplate ? getEditedPostTemplateId() : null, + enablePaddingAppender: + __unstableGetEditorMode() !== 'zoom-out' && + isRenderingPostOnly && + ! DESIGN_POST_TYPES.includes( currentPostType ), }; }, [ currentPostType, isEditingTemplate, settings.supportsTemplateMode ] ); + const [ paddingAppenderRef, paddingStyle ] = usePaddingAppender( + enablePaddingAppender + ); // Set the right context for the command palette const commandContext = hasBlockSelected @@ -474,7 +463,7 @@ function Layout( { } ), [ settings, onNavigateToEntityRecord, onNavigateToPreviousEntityRecord ] ); - const styles = useEditorStyles(); + const styles = useEditorStyles( paddingStyle ); // We need to add the show-icon-labels class to the body element so it is applied to modals. if ( showIconLabels ) { diff --git a/packages/edit-post/src/components/layout/use-padding-appender.js b/packages/edit-post/src/components/layout/use-padding-appender.js index efd46a485058ca..edffc6f3dd07c9 100644 --- a/packages/edit-post/src/components/layout/use-padding-appender.js +++ b/packages/edit-post/src/components/layout/use-padding-appender.js @@ -6,27 +6,20 @@ import { useRefEffect } from '@wordpress/compose'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { isUnmodifiedDefaultBlock } from '@wordpress/blocks'; -export function usePaddingAppender() { +// Ruleset to add space for the typewriter effect. When typing in the last +// block, there needs to be room to scroll up. +const CSS = + ':root :where(.editor-styles-wrapper)::after {content: ""; display: block; height: 40vh;}'; + +export function usePaddingAppender( enabled ) { const registry = useRegistry(); - return useRefEffect( + const effect = useRefEffect( ( node ) => { function onMouseDown( event ) { if ( event.target !== node ) { return; } - const { ownerDocument } = node; - const { defaultView } = ownerDocument; - - const pseudoHeight = defaultView.parseInt( - defaultView.getComputedStyle( node, ':after' ).height, - 10 - ); - - if ( ! pseudoHeight ) { - return; - } - // Only handle clicks under the last child. const lastChild = node.lastElementChild; if ( ! lastChild ) { @@ -64,4 +57,5 @@ export function usePaddingAppender() { }, [ registry ] ); + return enabled ? [ effect, CSS ] : []; } From 1b8751be5d9424d551fa30a08bd2fcc092889989 Mon Sep 17 00:00:00 2001 From: Matt West <matt@mattwest.design> Date: Tue, 8 Oct 2024 15:21:04 +0100 Subject: [PATCH 1115/1908] Icons: Update cloud upload and add cloud download icon. (#65906) Co-authored-by: matt-west <mattwest@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../test/__snapshots__/index.js.snap | 2 +- packages/icons/CHANGELOG.md | 5 +++++ packages/icons/src/index.js | 1 + packages/icons/src/library/cloud-download.js | 12 ++++++++++++ packages/icons/src/library/cloud-upload.js | 2 +- 5 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 packages/icons/src/library/cloud-download.js diff --git a/packages/editor/src/components/post-saved-state/test/__snapshots__/index.js.snap b/packages/editor/src/components/post-saved-state/test/__snapshots__/index.js.snap index 95ea3db54b511e..ee8d46d393c487 100644 --- a/packages/editor/src/components/post-saved-state/test/__snapshots__/index.js.snap +++ b/packages/editor/src/components/post-saved-state/test/__snapshots__/index.js.snap @@ -16,7 +16,7 @@ exports[`PostSavedState returns a disabled button if the post is not saveable 1` xmlns="http://www.w3.org/2000/svg" > <path - d="M17.3 10.1c0-2.5-2.1-4.4-4.8-4.4-2.2 0-4.1 1.4-4.6 3.3h-.2C5.7 9 4 10.7 4 12.8c0 2.1 1.7 3.8 3.7 3.8h9c1.8 0 3.2-1.5 3.2-3.3.1-1.6-1.1-2.9-2.6-3.2zm-.5 5.1h-4v-2.4L14 14l1-1-3-3-3 3 1 1 1.2-1.2v2.4H7.7c-1.2 0-2.2-1.1-2.2-2.3s1-2.4 2.2-2.4H9l.3-1.1c.4-1.3 1.7-2.2 3.2-2.2 1.8 0 3.3 1.3 3.3 2.9v1.3l1.3.2c.8.1 1.4.9 1.4 1.8 0 1-.8 1.8-1.7 1.8z" + d="M17.3 10.1C17.3 7.60001 15.2 5.70001 12.5 5.70001C10.3 5.70001 8.4 7.10001 7.9 9.00001H7.7C5.7 9.00001 4 10.7 4 12.8C4 14.9 5.7 16.6 7.7 16.6H9.5V15.2H7.7C6.5 15.2 5.5 14.1 5.5 12.9C5.5 11.7 6.5 10.5 7.7 10.5H9L9.3 9.40001C9.7 8.10001 11 7.20001 12.5 7.20001C14.3 7.20001 15.8 8.50001 15.8 10.1V11.4L17.1 11.6C17.9 11.7 18.5 12.5 18.5 13.4C18.5 14.4 17.7 15.2 16.8 15.2H14.5V16.6H16.7C18.5 16.6 19.9 15.1 19.9 13.3C20 11.7 18.8 10.4 17.3 10.1Z M14.1245 14.2426L15.1852 13.182L12.0032 10L8.82007 13.1831L9.88072 14.2438L11.25 12.8745V18H12.75V12.8681L14.1245 14.2426Z" /> </svg> </button> diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index c0ee7aab2cf986..e33269cd7be390 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -4,6 +4,11 @@ ### Enhancements +- Update `cloudUpload` icon to improve visibility of the up arrow. + +### New Features + +- Add new `cloudDownload` icon. - Update `unseen` icon to be a strike-through eye, rather than a closed eye, to match provide consistency. ([#65914](https://github.com/WordPress/gutenberg/pull/65914)). ## 10.9.0 (2024-10-03) diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index 586911ffc746b2..1601f04ac0c22e 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -50,6 +50,7 @@ export { default as chevronUpDown } from './library/chevron-up-down'; export { default as classic } from './library/classic'; export { default as close } from './library/close'; export { default as closeSmall } from './library/close-small'; +export { default as cloudDownload } from './library/cloud-download'; export { default as cloudUpload } from './library/cloud-upload'; export { default as cloud } from './library/cloud'; export { default as code } from './library/code'; diff --git a/packages/icons/src/library/cloud-download.js b/packages/icons/src/library/cloud-download.js new file mode 100644 index 00000000000000..ad24c7cbcd1436 --- /dev/null +++ b/packages/icons/src/library/cloud-download.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const cloudDownload = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M17.3 10.1002C17.3 7.6002 15.2 5.7002 12.5 5.7002C10.3 5.7002 8.4 7.1002 7.9 9.0002H7.7C5.7 9.0002 4 10.7002 4 12.8002C4 14.9002 5.7 16.6002 7.7 16.6002V15.2002C6.5 15.2002 5.5 14.1002 5.5 12.9002C5.5 11.7002 6.5 10.5002 7.7 10.5002H9L9.3 9.4002C9.7 8.1002 11 7.2002 12.5 7.2002C14.3 7.2002 15.8 8.5002 15.8 10.1002V11.4002L17.1 11.6002C17.9 11.7002 18.5 12.5002 18.5 13.4002C18.5 14.4002 17.7 15.2002 16.8 15.2002H16.5V16.6002H16.7C18.5 16.6002 19.9 15.1002 19.9 13.3002C20 11.7002 18.8 10.4002 17.3 10.1002Z M9.8806 13.7576L8.81995 14.8182L12.0019 18.0002L15.1851 14.8171L14.1244 13.7564L12.7551 15.1257L12.7551 10.0002L11.2551 10.0002V15.1321L9.8806 13.7576Z" /> + </SVG> +); + +export default cloudDownload; diff --git a/packages/icons/src/library/cloud-upload.js b/packages/icons/src/library/cloud-upload.js index 1df5a19d8742de..d7ab407cf615d2 100644 --- a/packages/icons/src/library/cloud-upload.js +++ b/packages/icons/src/library/cloud-upload.js @@ -5,7 +5,7 @@ import { SVG, Path } from '@wordpress/primitives'; const cloudUpload = ( <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> - <Path d="M17.3 10.1c0-2.5-2.1-4.4-4.8-4.4-2.2 0-4.1 1.4-4.6 3.3h-.2C5.7 9 4 10.7 4 12.8c0 2.1 1.7 3.8 3.7 3.8h9c1.8 0 3.2-1.5 3.2-3.3.1-1.6-1.1-2.9-2.6-3.2zm-.5 5.1h-4v-2.4L14 14l1-1-3-3-3 3 1 1 1.2-1.2v2.4H7.7c-1.2 0-2.2-1.1-2.2-2.3s1-2.4 2.2-2.4H9l.3-1.1c.4-1.3 1.7-2.2 3.2-2.2 1.8 0 3.3 1.3 3.3 2.9v1.3l1.3.2c.8.1 1.4.9 1.4 1.8 0 1-.8 1.8-1.7 1.8z" /> + <Path d="M17.3 10.1C17.3 7.60001 15.2 5.70001 12.5 5.70001C10.3 5.70001 8.4 7.10001 7.9 9.00001H7.7C5.7 9.00001 4 10.7 4 12.8C4 14.9 5.7 16.6 7.7 16.6H9.5V15.2H7.7C6.5 15.2 5.5 14.1 5.5 12.9C5.5 11.7 6.5 10.5 7.7 10.5H9L9.3 9.40001C9.7 8.10001 11 7.20001 12.5 7.20001C14.3 7.20001 15.8 8.50001 15.8 10.1V11.4L17.1 11.6C17.9 11.7 18.5 12.5 18.5 13.4C18.5 14.4 17.7 15.2 16.8 15.2H14.5V16.6H16.7C18.5 16.6 19.9 15.1 19.9 13.3C20 11.7 18.8 10.4 17.3 10.1Z M14.1245 14.2426L15.1852 13.182L12.0032 10L8.82007 13.1831L9.88072 14.2438L11.25 12.8745V18H12.75V12.8681L14.1245 14.2426Z" /> </SVG> ); From db22c1b306a1e8c16604ee04ffdd1751aa5978e6 Mon Sep 17 00:00:00 2001 From: Michal <mmczaplinski@gmail.com> Date: Tue, 8 Oct 2024 15:46:17 +0100 Subject: [PATCH 1116/1908] Interactivity API: Improvements to the experimental full-page navigation (#64067) * fix: Add initial data population in interactivity router * chore: Update element.innerText to element.textContent in head.ts file * feat: Exclude src and href attributes when copying head element attributes * chore: Populate initial data in interactivity router * chore: Move Populate initial data in interactivity router * Wait for `load` event of script element before returning from `fetchHeadAssets()` function * feat: Update head tags to improve prefetching of scripts and stylesheets This commit modifies the `updateHead` function in `head.ts` to improve support for lazy loading of scripts and stylesheets. It preloades the script modules using `modulepreload`, imports the necessary scripts using dynamic imports and adds the `preload` link elements for stylesheets. * Do not load interactivity script modules in development mode when full page navigation is enabled * Format interactivity-api.php * Update interactivity script module registration to use version from asset files - Added logic to retrieve version information from `index.min.asset.php` and `router.min.asset.php` files. - Updated `wp_register_script_module` calls to use the retrieved version instead of the default version when full-page navigation is not enabled. * empty commit * Rename populateInitialData to populateServerData * remove populateServerData * try: remove the webpack comment * try: remove the await import() * bring back the async import * Move headElements to head.ts * Revert "try: remove the webpack comment" This reverts commit 62e527e1769162894881eba76fc33bd96e3fa7eb. * default_version => router_version * Remove the changes to interactivity-api.php * Make `renderRegions` async * Update TS type of the stylesheets variable Co-authored-by: Jon Surrell <sirreal@users.noreply.github.com> * Replace Array.from() with direct forEach() on NodeList in head.ts: * Check if href is null * Clarify why we only prefetch script modules * Add changelog --------- Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: DAreRodz <darerodz@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: luisherranz <luisherranz@git.wordpress.org> Co-authored-by: westonruter <westonruter@git.wordpress.org> --- packages/interactivity-router/CHANGELOG.md | 8 ++ packages/interactivity-router/src/head.ts | 114 ++++++++++++--------- packages/interactivity-router/src/index.ts | 56 +++++----- 3 files changed, 106 insertions(+), 72 deletions(-) diff --git a/packages/interactivity-router/CHANGELOG.md b/packages/interactivity-router/CHANGELOG.md index 7878796b9004cc..4f794899096683 100644 --- a/packages/interactivity-router/CHANGELOG.md +++ b/packages/interactivity-router/CHANGELOG.md @@ -2,6 +2,14 @@ ## Unreleased +### Enhancements + +- Improvements to the experimental full-page navigation ([#64067](https://github.com/WordPress/gutenberg/pull/64067)): + - Remove the `src` attributes from prefetched script tags. + - Use `.textContent` instead of `.innerText` to set `<script>` contents. + - Use `populateInitialData()` with state from the server. + - Wait for the `load` event of the script element before evaluating it. + ## 2.9.0 (2024-10-03) ## 2.8.0 (2024-09-19) diff --git a/packages/interactivity-router/src/head.ts b/packages/interactivity-router/src/head.ts index 2bde7cea520404..69139348b582ff 100644 --- a/packages/interactivity-router/src/head.ts +++ b/packages/interactivity-router/src/head.ts @@ -1,3 +1,11 @@ +/** + * The cache of prefetched stylesheets and scripts. + */ +export const headElements = new Map< + string, + { tag: HTMLElement; text?: string } +>(); + /** * Helper to update only the necessary tags in the head. * @@ -29,6 +37,14 @@ export const updateHead = async ( newHead: HTMLHeadElement[] ) => { } } + await Promise.all( + [ ...headElements.entries() ] + .filter( ( [ , { tag } ] ) => tag.nodeName === 'SCRIPT' ) + .map( async ( [ url ] ) => { + await import( /* webpackIgnore: true */ url ); + } ) + ); + // Prepare new assets. const toAppend = [ ...newHeadMap.values() ]; @@ -41,60 +57,66 @@ export const updateHead = async ( newHead: HTMLHeadElement[] ) => { * Fetches and processes head assets (stylesheets and scripts) from a specified document. * * @async - * @param doc The document from which to fetch head assets. It should support standard DOM querying methods. - * @param headElements A map of head elements to modify tracking the URLs of already processed assets to avoid duplicates. - * @param headElements.tag - * @param headElements.text + * @param doc The document from which to fetch head assets. It should support standard DOM querying methods. * * @return Returns an array of HTML elements representing the head assets. */ export const fetchHeadAssets = async ( - doc: Document, - headElements: Map< string, { tag: HTMLElement; text: string } > + doc: Document ): Promise< HTMLElement[] > => { const headTags = []; - const assets = [ - { - tagName: 'style', - selector: 'link[rel=stylesheet]', - attribute: 'href', - }, - { tagName: 'script', selector: 'script[src]', attribute: 'src' }, - ]; - for ( const asset of assets ) { - const { tagName, selector, attribute } = asset; - const tags = doc.querySelectorAll< - HTMLScriptElement | HTMLStyleElement - >( selector ); - - // Use Promise.all to wait for fetch to complete - await Promise.all( - Array.from( tags ).map( async ( tag ) => { - const attributeValue = tag.getAttribute( attribute ); - if ( ! headElements.has( attributeValue ) ) { - try { - const response = await fetch( attributeValue ); - const text = await response.text(); - headElements.set( attributeValue, { - tag, - text, - } ); - } catch ( e ) { - // eslint-disable-next-line no-console - console.error( e ); - } - } - const headElement = headElements.get( attributeValue ); - const element = doc.createElement( tagName ); - element.innerText = headElement.text; - for ( const attr of headElement.tag.attributes ) { - element.setAttribute( attr.name, attr.value ); + // We only want to fetch module scripts because regular scripts (without + // `async` or `defer` attributes) can depend on the execution of other scripts. + // Scripts found in the head are blocking and must be executed in order. + const scripts = doc.querySelectorAll< HTMLScriptElement >( + 'script[type="module"][src]' + ); + + scripts.forEach( ( script ) => { + const src = script.getAttribute( 'src' ); + if ( ! headElements.has( src ) ) { + // add the <link> elements to prefetch the module scripts + const link = doc.createElement( 'link' ); + link.rel = 'modulepreload'; + link.href = src; + document.head.append( link ); + headElements.set( src, { tag: script } ); + } + } ); + + const stylesheets = doc.querySelectorAll< HTMLLinkElement >( + 'link[rel=stylesheet]' + ); + + await Promise.all( + Array.from( stylesheets ).map( async ( tag ) => { + const href = tag.getAttribute( 'href' ); + if ( ! href ) { + return; + } + + if ( ! headElements.has( href ) ) { + try { + const response = await fetch( href ); + const text = await response.text(); + headElements.set( href, { + tag, + text, + } ); + } catch ( e ) { + // eslint-disable-next-line no-console + console.error( e ); } - headTags.push( element ); - } ) - ); - } + } + + const headElement = headElements.get( href ); + const styleElement = doc.createElement( 'style' ); + styleElement.textContent = headElement.text; + + headTags.push( styleElement ); + } ) + ); return [ doc.querySelector( 'title' ), diff --git a/packages/interactivity-router/src/index.ts b/packages/interactivity-router/src/index.ts index b2e8e2d4395dcd..8a46d4ce350113 100644 --- a/packages/interactivity-router/src/index.ts +++ b/packages/interactivity-router/src/index.ts @@ -6,7 +6,7 @@ import { store, privateApis, getConfig } from '@wordpress/interactivity'; /** * Internal dependencies */ -import { fetchHeadAssets, updateHead } from './head'; +import { fetchHeadAssets, updateHead, headElements } from './head'; const { directivePrefix, @@ -54,7 +54,6 @@ const navigationMode: 'regionBased' | 'fullPage' = // The cache of visited and prefetched pages, stylesheets and scripts. const pages = new Map< string, Promise< Page | false > >(); -const headElements = new Map< string, { tag: HTMLElement; text: string } >(); // Helper to remove domain and hash from the URL. We are only interesting in // caching the path and the query. @@ -87,7 +86,7 @@ const regionsToVdom: RegionsToVdom = async ( dom, { vdom } = {} ) => { let head: HTMLElement[]; if ( globalThis.IS_GUTENBERG_PLUGIN ) { if ( navigationMode === 'fullPage' ) { - head = await fetchHeadAssets( dom, headElements ); + head = await fetchHeadAssets( dom ); regions.body = vdom ? vdom.get( document.body ) : toVdom( dom.body ); @@ -108,19 +107,22 @@ const regionsToVdom: RegionsToVdom = async ( dom, { vdom } = {} ) => { }; // Render all interactive regions contained in the given page. -const renderRegions = ( page: Page ) => { - batch( () => { - if ( globalThis.IS_GUTENBERG_PLUGIN ) { - if ( navigationMode === 'fullPage' ) { - // Once this code is tested and more mature, the head should be updated for region based navigation as well. - updateHead( page.head ); - const fragment = getRegionRootFragment( document.body ); +const renderRegions = async ( page: Page ) => { + if ( globalThis.IS_GUTENBERG_PLUGIN ) { + if ( navigationMode === 'fullPage' ) { + // Once this code is tested and more mature, the head should be updated for region based navigation as well. + await updateHead( page.head ); + const fragment = getRegionRootFragment( document.body ); + batch( () => { + populateServerData( page.initialData ); render( page.regions.body, fragment ); - } + } ); } - if ( navigationMode === 'regionBased' ) { + } + if ( navigationMode === 'regionBased' ) { + const attrName = `data-${ directivePrefix }-router-region`; + batch( () => { populateServerData( page.initialData ); - const attrName = `data-${ directivePrefix }-router-region`; document .querySelectorAll( `[${ attrName }]` ) .forEach( ( region ) => { @@ -128,11 +130,11 @@ const renderRegions = ( page: Page ) => { const fragment = getRegionRootFragment( region ); render( page.regions[ id ], fragment ); } ); - } - if ( page.title ) { - document.title = page.title; - } - } ); + } ); + } + if ( page.title ) { + document.title = page.title; + } }; /** @@ -156,7 +158,7 @@ window.addEventListener( 'popstate', async () => { const pagePath = getPagePath( window.location.href ); // Remove hash. const page = pages.has( pagePath ) && ( await pages.get( pagePath ) ); if ( page ) { - renderRegions( page ); + await renderRegions( page ); // Update the URL in the state. state.url = window.location.href; } else { @@ -170,13 +172,15 @@ window.addEventListener( 'popstate', async () => { if ( globalThis.IS_GUTENBERG_PLUGIN ) { if ( navigationMode === 'fullPage' ) { // Cache the scripts. Has to be called before fetching the assets. - [].map.call( document.querySelectorAll( 'script[src]' ), ( script ) => { - headElements.set( script.getAttribute( 'src' ), { - tag: script, - text: script.textContent, - } ); - } ); - await fetchHeadAssets( document, headElements ); + [].map.call( + document.querySelectorAll( 'script[type="module"][src]' ), + ( script ) => { + headElements.set( script.getAttribute( 'src' ), { + tag: script, + } ); + } + ); + await fetchHeadAssets( document ); } } pages.set( From b15b8fd522109ae96a26fb869ed663bcf6b39bf7 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Tue, 8 Oct 2024 09:05:58 -0700 Subject: [PATCH 1117/1908] Post editor: fix meta boxes accessibility (#65466) * Replace details element with custom toggle * Consolidate details of updating height into function * Reduce conditionals for toggle vs. resizable * Fix style in RTL * Remove unneeded overflow style * Maintain focus even with caret browsing on * Use `ResizableBox` again * Add aria-expanded to toggle and remove aria-label * Fix styles for Windows high contrast mode * Add missing "border" in Windows high contrast mode * Move `flex-shrink` rule to toggle only * Fix rule preserved for non-iframe canvas * Make meta boxes container a navigable region * Try hiding meta box region contents when not expanded * Fix hidden conditional * Rename a couple functions Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: joedolson <joedolson@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../edit-post/src/components/layout/index.js | 200 +++++++++--------- .../src/components/layout/style.scss | 126 +++++++---- .../src/components/navigable-region/index.js | 43 ++-- 3 files changed, 206 insertions(+), 163 deletions(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 20ef22b5f0eb25..88d0cd1588f03f 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -31,6 +31,7 @@ import { useRef, useState, } from '@wordpress/element'; +import { chevronDown, chevronUp } from '@wordpress/icons'; import { store as noticesStore } from '@wordpress/notices'; import { store as preferencesStore } from '@wordpress/preferences'; import { @@ -43,6 +44,7 @@ import { addQueryArgs } from '@wordpress/url'; import { decodeEntities } from '@wordpress/html-entities'; import { store as coreStore } from '@wordpress/core-data'; import { + Icon, ResizableBox, SlotFillProvider, Tooltip, @@ -76,7 +78,7 @@ import useNavigateToEntityRecord from '../../hooks/use-navigate-to-entity-record const { getLayoutStyles } = unlock( blockEditorPrivateApis ); const { useCommands } = unlock( coreCommandsPrivateApis ); const { useCommandContext } = unlock( commandsPrivateApis ); -const { Editor, FullscreenMode } = unlock( editorPrivateApis ); +const { Editor, FullscreenMode, NavigableRegion } = unlock( editorPrivateApis ); const { BlockKeyboardShortcuts } = unlock( blockLibraryPrivateApis ); const DESIGN_POST_TYPES = [ 'wp_template', @@ -163,7 +165,7 @@ function MetaBoxesMain( { isLegacy } ) { ]; }, [] ); const { set: setPreference } = useDispatch( preferencesStore ); - const resizableBoxRef = useRef(); + const metaBoxesMainRef = useRef(); const isShort = useMediaQuery( '(max-height: 549px)' ); const [ { min, max }, setHeightConstraints ] = useState( () => ( {} ) ); @@ -178,9 +180,9 @@ function MetaBoxesMain( { isLegacy } ) { ':scope > .components-notice-list' ); const resizeHandle = container.querySelector( - '.edit-post-meta-boxes-main__resize-handle' + '.edit-post-meta-boxes-main__presenter' ); - const actualize = () => { + const deriveConstraints = () => { const fullHeight = container.offsetHeight; let nextMax = fullHeight; for ( const element of noticeLists ) { @@ -189,7 +191,7 @@ function MetaBoxesMain( { isLegacy } ) { const nextMin = resizeHandle.offsetHeight; setHeightConstraints( { min: nextMin, max: nextMax } ); }; - const observer = new window.ResizeObserver( actualize ); + const observer = new window.ResizeObserver( deriveConstraints ); observer.observe( container ); for ( const element of noticeLists ) { observer.observe( element ); @@ -201,12 +203,33 @@ function MetaBoxesMain( { isLegacy } ) { const separatorHelpId = useId(); const [ isUntouched, setIsUntouched ] = useState( true ); + const applyHeight = ( candidateHeight, isPersistent, isInstant ) => { + const nextHeight = Math.min( max, Math.max( min, candidateHeight ) ); + if ( isPersistent ) { + setPreference( + 'core/edit-post', + 'metaBoxesMainOpenHeight', + nextHeight + ); + } else { + separatorRef.current.ariaValueNow = getAriaValueNow( nextHeight ); + } + if ( isInstant ) { + metaBoxesMainRef.current.updateSize( { + height: nextHeight, + // Oddly, when the event that triggered this was not from the mouse (e.g. keydown), + // if `width` is left unspecified a subsequent drag gesture applies a fixed + // width and the pane fails to widen/narrow with parent width changes from + // sidebars opening/closing or window resizes. + width: 'auto', + } ); + } + }; if ( ! hasAnyVisible ) { return; } - const className = 'edit-post-meta-boxes-main'; const contents = ( <div className={ clsx( @@ -214,6 +237,7 @@ function MetaBoxesMain( { isLegacy } ) { 'edit-post-layout__metaboxes', ! isLegacy && 'edit-post-meta-boxes-main__liner' ) } + hidden={ ! isLegacy && isShort && ! isOpen } > <MetaBoxes location="normal" /> <MetaBoxes location="advanced" /> @@ -236,59 +260,39 @@ function MetaBoxesMain( { isLegacy } ) { const usedAriaValueNow = max === undefined || isAutoHeight ? 50 : getAriaValueNow( openHeight ); - if ( isShort ) { - return ( - <details - className={ className } - open={ isOpen } - onToggle={ ( { target } ) => { - setPreference( - 'core/edit-post', - 'metaBoxesMainIsOpen', - target.open - ); - } } - > - <summary>{ __( 'Meta Boxes' ) }</summary> - { contents } - </details> - ); - } + const toggle = () => + setPreference( 'core/edit-post', 'metaBoxesMainIsOpen', ! isOpen ); // TODO: Support more/all keyboard interactions from the window splitter pattern: // https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/ const onSeparatorKeyDown = ( event ) => { const delta = { ArrowUp: 20, ArrowDown: -20 }[ event.key ]; if ( delta ) { - const { resizable } = resizableBoxRef.current; - const fromHeight = isAutoHeight - ? resizable.offsetHeight - : openHeight; - const nextHeight = Math.min( - max, - Math.max( min, delta + fromHeight ) - ); - resizableBoxRef.current.updateSize( { - height: nextHeight, - // Oddly, if left unspecified a subsequent drag gesture applies a fixed - // width and the pane fails to shrink/grow with parent width changes from - // sidebars opening/closing or window resizes. - width: 'auto', - } ); - setPreference( - 'core/edit-post', - 'metaBoxesMainOpenHeight', - nextHeight - ); + const pane = metaBoxesMainRef.current.resizable; + const fromHeight = isAutoHeight ? pane.offsetHeight : openHeight; + const nextHeight = delta + fromHeight; + applyHeight( nextHeight, true, true ); + event.preventDefault(); } }; - - return ( - <ResizableBox - className={ className } - defaultSize={ { height: openHeight } } - ref={ resizableBoxRef } - enable={ { + const className = 'edit-post-meta-boxes-main'; + const paneLabel = __( 'Meta Boxes' ); + let Pane, paneProps; + if ( isShort ) { + Pane = NavigableRegion; + paneProps = { + className: clsx( className, 'is-toggle-only' ), + }; + } else { + Pane = ResizableBox; + paneProps = /** @type {Parameters<typeof ResizableBox>[0]} */ ( { + as: NavigableRegion, + ref: metaBoxesMainRef, + className: clsx( className, 'is-resizable' ), + defaultSize: { height: openHeight }, + minHeight: min, + maxHeight: usedMax, + enable: { top: true, right: false, bottom: false, @@ -297,72 +301,66 @@ function MetaBoxesMain( { isLegacy } ) { topRight: false, bottomRight: false, bottomLeft: false, - } } - minHeight={ min } - maxHeight={ usedMax } - bounds="parent" - boundsByDirection - // Avoids hiccups while dragging over objects like iframes and ensures that - // the event to end the drag is captured by the target (resize handle) - // whether or not it’s under the pointer. - onPointerDown={ ( { pointerId, target } ) => { - target.setPointerCapture( pointerId ); - } } - onResizeStart={ ( event, direction, elementRef ) => { - if ( isAutoHeight ) { - const heightNow = elementRef.offsetHeight; - // Sets the starting height to avoid visual jumps in height and - // aria-valuenow being `NaN` for the first (few) resize events. - resizableBoxRef.current.updateSize( { height: heightNow } ); - // Causes `maxHeight` to update to full `max` value instead of half. - setIsUntouched( false ); - } - } } - onResize={ () => { - const { height } = resizableBoxRef.current.state; - const separator = separatorRef.current; - separator.ariaValueNow = getAriaValueNow( height ); - } } - onResizeStop={ () => { - const nextHeight = resizableBoxRef.current.state.height; - setPreference( - 'core/edit-post', - 'metaBoxesMainOpenHeight', - nextHeight - ); - } } - handleClasses={ { - top: 'edit-post-meta-boxes-main__resize-handle', - } } - handleComponent={ { + }, + handleClasses: { top: 'edit-post-meta-boxes-main__presenter' }, + handleComponent: { top: ( <> <Tooltip text={ __( 'Drag to resize' ) }> - { /* Disable reason: aria-valuenow is supported by separator role. */ } - { /* eslint-disable-next-line jsx-a11y/role-supports-aria-props */ } - <button + <button // eslint-disable-line jsx-a11y/role-supports-aria-props ref={ separatorRef } + role="separator" // eslint-disable-line jsx-a11y/no-interactive-element-to-noninteractive-role + aria-valuenow={ usedAriaValueNow } aria-label={ __( 'Drag to resize' ) } aria-describedby={ separatorHelpId } onKeyDown={ onSeparatorKeyDown } - // Disable reason: buttons are allowed to be separator role. - // eslint-disable-next-line jsx-a11y/no-interactive-element-to-noninteractive-role - role="separator" - aria-valuenow={ usedAriaValueNow } /> </Tooltip> <VisuallyHidden id={ separatorHelpId }> { __( - 'Use up and down arrow keys to resize the metabox panel.' + 'Use up and down arrow keys to resize the metabox pane.' ) } </VisuallyHidden> </> ), - } } - > - <meta ref={ effectSizeConstraints } /> + }, + // Avoids hiccups while dragging over objects like iframes and ensures that + // the event to end the drag is captured by the target (resize handle) + // whether or not it’s under the pointer. + onPointerDown: ( { pointerId, target } ) => { + target.setPointerCapture( pointerId ); + }, + onResizeStart: ( event, direction, elementRef ) => { + if ( isAutoHeight ) { + // Sets the starting height to avoid visual jumps in height and + // aria-valuenow being `NaN` for the first (few) resize events. + applyHeight( elementRef.offsetHeight, false, true ); + setIsUntouched( false ); + } + }, + onResize: () => + applyHeight( metaBoxesMainRef.current.state.height ), + onResizeStop: () => + applyHeight( metaBoxesMainRef.current.state.height, true ), + } ); + } + + return ( + <Pane aria-label={ paneLabel } { ...paneProps }> + { isShort ? ( + <button + aria-expanded={ isOpen } + className="edit-post-meta-boxes-main__presenter" + onClick={ toggle } + > + { paneLabel } + <Icon icon={ isOpen ? chevronUp : chevronDown } /> + </button> + ) : ( + <meta ref={ effectSizeConstraints } /> + ) } { contents } - </ResizableBox> + </Pane> ); } diff --git a/packages/edit-post/src/components/layout/style.scss b/packages/edit-post/src/components/layout/style.scss index 5d0a9a29c329ca..18f12c1dbfbb92 100644 --- a/packages/edit-post/src/components/layout/style.scss +++ b/packages/edit-post/src/components/layout/style.scss @@ -1,71 +1,111 @@ -$resize-handle-height: $grid-unit-30; - .edit-post-meta-boxes-main { filter: drop-shadow(0 -1px rgba($color: #000, $alpha: 0.133)); // 0.133 = $gray-200 but with alpha. + // Windows High Contrast mode will show this outline, but not the shadow. + outline: 1px solid transparent; background-color: $white; - clear: both; // This is seemingly only needed in case the canvas is not iframe’d. - - &:not(details) { - padding-top: $resize-handle-height; - } - - // The component renders as a details element in short viewports. - &:is(details) { - & > summary { - cursor: pointer; - color: $gray-900; - background-color: $white; - height: $button-size-compact; - line-height: $button-size-compact; - font-size: 13px; - padding-left: $grid-unit-30; - box-shadow: 0 $border-width $gray-300; - } + display: flex; + flex-direction: column; + overflow: hidden; - &[open] > summary { - position: sticky; - top: 0; - z-index: 1; - } + &.is-resizable { + padding-block-start: $grid-unit-30; } } -.edit-post-meta-boxes-main__resize-handle { +.edit-post-meta-boxes-main__presenter { display: flex; - // The position is absolute by default inline style of ResizableBox. - inset: 0 0 auto 0; - height: $resize-handle-height; box-shadow: 0 $border-width $gray-300; + // Windows High Contrast mode will show this outline, but not the shadow. + outline: 1px solid transparent; + position: relative; + z-index: 1; - & > button { + // Button style reset for both toggle or resizable. + .is-toggle-only > &, + .is-resizable.edit-post-meta-boxes-main & > button { appearance: none; - cursor: inherit; - margin: auto; padding: 0; border: none; outline: none; - background-color: $gray-300; - width: $grid-unit-80; - height: $grid-unit-05; - border-radius: $radius-small; - transition: width 0.3s ease-out; - @include reduce-motion("transition"); + background-color: transparent; } - &:hover > button, - > button:focus { - background-color: var(--wp-admin-theme-color); - width: $grid-unit-80 + $grid-unit-20; + .is-toggle-only > & { + flex-shrink: 0; + cursor: pointer; + height: $button-size-compact; + justify-content: space-between; + align-items: center; + padding-inline: $grid-unit-30 $grid-unit-15; + + &:is(:hover, :focus-visible) { + color: var(--wp-admin-theme-color); + } + &:focus-visible::after { + content: ""; + position: absolute; + inset: var(--wp-admin-border-width-focus); + @include button-style__focus(); + } + > svg { + fill: currentColor; + } + } + + .is-resizable.edit-post-meta-boxes-main & { + inset: 0 0 auto; + + > button { + cursor: inherit; + width: $grid-unit-80; + height: $grid-unit-30; + margin: auto; + + &::before { + content: ""; + background-color: $gray-300; + // Windows High Contrast mode will show this outline, but not the background-color. + outline: 2px solid transparent; + outline-offset: -2px; + position: absolute; + inset-block: calc(50% - #{$grid-unit-05} / 2) auto; + transform: translateX(-50%); + width: inherit; + height: $grid-unit-05; + border-radius: $radius-small; + transition: width 0.3s ease-out; + @include reduce-motion("transition"); + } + } + + &:is(:hover, :focus-within) > button::before { + background-color: var(--wp-admin-theme-color); + width: $grid-unit-80 + $grid-unit-20; + } + } +} + +@media (pointer: coarse) { + .is-resizable.edit-post-meta-boxes-main { + padding-block-start: $button-size-compact; + + .edit-post-meta-boxes-main__presenter > button { + height: $button-size-compact; + } } } .edit-post-meta-boxes-main__liner { overflow: auto; - max-height: 100%; // Keep the contents behind the resize handle or details summary. isolation: isolate; } +// In case the canvas is not iframe’d. +.edit-post-layout__metaboxes { + clear: both; +} + .has-metaboxes .editor-visual-editor { flex: 1; diff --git a/packages/interface/src/components/navigable-region/index.js b/packages/interface/src/components/navigable-region/index.js index a4c051185b63ab..50b98d49070d43 100644 --- a/packages/interface/src/components/navigable-region/index.js +++ b/packages/interface/src/components/navigable-region/index.js @@ -1,24 +1,29 @@ +/** + * WordPress dependencies + */ +import { forwardRef } from '@wordpress/element'; + /** * External dependencies */ import clsx from 'clsx'; -export default function NavigableRegion( { - children, - className, - ariaLabel, - as: Tag = 'div', - ...props -} ) { - return ( - <Tag - className={ clsx( 'interface-navigable-region', className ) } - aria-label={ ariaLabel } - role="region" - tabIndex="-1" - { ...props } - > - { children } - </Tag> - ); -} +const NavigableRegion = forwardRef( + ( { children, className, ariaLabel, as: Tag = 'div', ...props }, ref ) => { + return ( + <Tag + ref={ ref } + className={ clsx( 'interface-navigable-region', className ) } + aria-label={ ariaLabel } + role="region" + tabIndex="-1" + { ...props } + > + { children } + </Tag> + ); + } +); + +NavigableRegion.displayName = 'NavigableRegion'; +export default NavigableRegion; From 6f77cdf87ffdfda776499de640fc2adbbe02ec28 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Wed, 9 Oct 2024 02:22:05 +0800 Subject: [PATCH 1118/1908] Revert "Pattern block: Ensure consistent editing of overrides in Write Mode (#65408)" (#65953) This reverts commit ace97353e22183c395fa9abd903fe3a19fe73826. ---- Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/store/private-selectors.js | 18 --- packages/block-editor/src/store/selectors.js | 38 ------ .../src/store/test/private-selectors.js | 3 +- .../block-editor/src/store/test/selectors.js | 112 +----------------- packages/block-library/src/block/edit.js | 57 ++++++++- 5 files changed, 53 insertions(+), 175 deletions(-) diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index eeb987fc00f616..c3228980310656 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -684,21 +684,3 @@ export function getClosestAllowedInsertionPointForPattern( export function getInsertionPoint( state ) { return state.insertionPoint; } - -/** - * Retrieves the number of parent pattern blocks. - * - * @param {Object} state Global application state. - * @param {string} clientId The block client ID. - * - * @return {number} The number of parent pattern blocks. - */ -export function getParentPatternCount( state, clientId ) { - const parents = getBlockParents( state, clientId ); - return parents.reduce( ( count, parent ) => { - if ( getBlockName( state, parent ) === 'core/block' ) { - return count + 1; - } - return count; - }, 0 ); -} diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 812c48c87e7dca..6cf6aae296141f 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -40,7 +40,6 @@ import { getSectionRootClientId, isSectionBlock, getParentSectionBlock, - getParentPatternCount, } from './private-selectors'; /** @@ -2973,43 +2972,6 @@ export const getBlockEditingMode = createRegistrySelector( clientId = ''; } - // Handle pattern blocks (core/block) and the content of those blocks. - const parentPatternCount = getParentPatternCount( state, clientId ); - - // Make the outer pattern block content only mode. - if ( - getBlockName( state, clientId ) === 'core/block' && - parentPatternCount === 0 - ) { - return 'contentOnly'; - } - - if ( parentPatternCount > 0 ) { - // Disable nested patterns. - if ( parentPatternCount > 1 ) { - return 'disabled'; - } - - // Disable pattern content editing in zoom-out mode. - const _isZoomOut = - __unstableGetEditorMode( state ) === 'zoom-out'; - if ( _isZoomOut ) { - return 'disabled'; - } - - // If the block has a binding of any kind, allow content only editing. - const attributes = getBlockAttributes( state, clientId ); - if ( - Object.keys( attributes?.metadata?.bindings ?? {} ) - ?.length > 0 - ) { - return 'contentOnly'; - } - - // Otherwise, the block is part of the pattern source and should not be editable. - return 'disabled'; - } - // In zoom-out mode, override the behavior set by // __unstableSetBlockEditingMode to only allow editing the top-level // sections. diff --git a/packages/block-editor/src/store/test/private-selectors.js b/packages/block-editor/src/store/test/private-selectors.js index cca0714f3856d7..cbb75daa4baaa0 100644 --- a/packages/block-editor/src/store/test/private-selectors.js +++ b/packages/block-editor/src/store/test/private-selectors.js @@ -428,6 +428,7 @@ describe( 'private selectors', () => { 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', ], ] ), + order: new Map( [ [ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', @@ -442,7 +443,6 @@ describe( 'private selectors', () => { ], [ '', [ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337' ] ], ] ), - byClientId: new Map( [] ), }, blockEditingModes: new Map( [ [ '', 'disabled' ], @@ -495,7 +495,6 @@ describe( 'private selectors', () => { ], [ '', [ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337' ] ], ] ), - byClientId: new Map( [] ), }, blockEditingModes: new Map( [ [ '', 'disabled' ], diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index 67af4d1b631162..a08c2e0dde1508 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -3079,7 +3079,7 @@ describe( 'selectors', () => { byClientId: new Map( Object.entries( { block1: { name: 'core/test-block-ancestor' }, - block2: { name: 'core/group' }, + block2: { name: 'core/block' }, block3: { name: 'core/test-block-parent' }, } ) ), @@ -4668,114 +4668,4 @@ describe( 'getBlockEditingMode', () => { ) ).toBe( 'disabled' ); } ); - - describe( 'pattern blocks', () => { - const patternBlockState = { - settings: {}, - blocks: { - byClientId: new Map( - Object.entries( { - 'pattern-a': { name: 'core/block' }, - 'pattern-b': { name: 'core/block' }, - 'heading-a': { name: 'core/heading' }, - 'paragraph-a': { name: 'core/paragraph' }, - 'paragraph-b': { name: 'core/paragraph' }, - } ) - ), - order: new Map( - Object.entries( { - '': [ 'pattern-a' ], - 'pattern-a': [ - 'heading-a', - 'paragraph-a', - 'pattern-b', - ], - 'pattern-b': [ 'paragraph-b' ], - } ) - ), - parents: new Map( - Object.entries( { - 'paragraph-b': 'pattern-b', - 'pattern-b': 'pattern-a', - 'paragraph-a': 'pattern-a', - 'heading-a': 'pattern-a', - 'pattern-a': '', - } ) - ), - blockListSettings: { - 'pattern-a': {}, - 'pattern-b': {}, - }, - attributes: new Map( - Object.entries( { - 'paragraph-a': { - metadata: { - bindings: { - __default: { - source: 'core/pattern-overrides', - }, - }, - }, - }, - 'paragraph-b': { - metadata: { - bindings: { - __default: { - source: 'core/pattern-overrides', - }, - }, - }, - }, - } ) - ), - }, - }; - - it( 'should return contentOnly for the outer pattern block', () => { - expect( - getBlockEditingMode( patternBlockState, 'pattern-a' ) - ).toBe( 'contentOnly' ); - } ); - - it( 'should return contentOnly for blocks with bindings in the outer pattern', () => { - expect( - getBlockEditingMode( patternBlockState, 'paragraph-a' ) - ).toBe( 'contentOnly' ); - } ); - - it( 'should return disabled for unbound blocks', () => { - expect( - getBlockEditingMode( patternBlockState, 'heading-a' ) - ).toBe( 'disabled' ); - } ); - - it( 'should return disabled for the nested pattern', () => { - expect( - getBlockEditingMode( patternBlockState, 'pattern-a' ) - ).toBe( 'contentOnly' ); - } ); - - it( 'should return disabled for blocks with bindings in the nested pattern', () => { - expect( - getBlockEditingMode( patternBlockState, 'paragraph-b' ) - ).toBe( 'disabled' ); - } ); - - it( 'should disable all inner blocks of the outer pattern in zoom out mode with the outer pattern in content only mode', () => { - const state = { - ...patternBlockState, - editorMode: 'zoom-out', - }; - expect( getBlockEditingMode( state, 'pattern-a' ) ).toBe( - 'contentOnly' - ); - [ 'paragraph-a', 'paragraph-b', 'heading-a', 'pattern-b' ].forEach( - ( block ) => { - expect( getBlockEditingMode( state, block ) ).toBe( - 'disabled' - ); - } - ); - } ); - } ); } ); diff --git a/packages/block-library/src/block/edit.js b/packages/block-library/src/block/edit.js index 3d4d07e52b386a..104b07157cba74 100644 --- a/packages/block-library/src/block/edit.js +++ b/packages/block-library/src/block/edit.js @@ -7,7 +7,7 @@ import clsx from 'clsx'; * WordPress dependencies */ import { useSelect, useDispatch } from '@wordpress/data'; -import { useRef, useMemo } from '@wordpress/element'; +import { useRef, useMemo, useEffect } from '@wordpress/element'; import { useEntityRecord, store as coreStore, @@ -37,10 +37,12 @@ import { getBlockBindingsSource } from '@wordpress/blocks'; /** * Internal dependencies */ +import { name as patternBlockName } from './index'; import { unlock } from '../lock-unlock'; const { useLayoutClasses } = unlock( blockEditorPrivateApis ); -const { hasOverridableBlocks } = unlock( patternsPrivateApis ); +const { isOverridableBlock, hasOverridableBlocks } = + unlock( patternsPrivateApis ); const fullAlignments = [ 'full', 'wide', 'left', 'right' ]; @@ -73,6 +75,22 @@ const useInferredLayout = ( blocks, parentLayout ) => { }, [ blocks, parentLayout ] ); }; +function setBlockEditMode( setEditMode, blocks, mode ) { + blocks.forEach( ( block ) => { + const editMode = + mode || + ( isOverridableBlock( block ) ? 'contentOnly' : 'disabled' ); + setEditMode( block.clientId, editMode ); + + setBlockEditMode( + setEditMode, + block.innerBlocks, + // Disable editing for nested patterns. + block.name === patternBlockName ? 'disabled' : mode + ); + } ); +} + function RecursionWarning() { const blockProps = useBlockProps(); return ( @@ -153,6 +171,7 @@ function ReusableBlockEdit( { name, attributes: { ref, content }, __unstableParentLayout: parentLayout, + clientId: patternClientId, setAttributes, } ) { const { record, hasResolved } = useEntityRecord( @@ -165,24 +184,49 @@ function ReusableBlockEdit( { } ); const isMissing = hasResolved && ! record; - const { __unstableMarkLastChangeAsPersistent } = + const { setBlockEditingMode, __unstableMarkLastChangeAsPersistent } = useDispatch( blockEditorStore ); - const { onNavigateToEntityRecord, hasPatternOverridesSource } = useSelect( + const { + innerBlocks, + onNavigateToEntityRecord, + editingMode, + hasPatternOverridesSource, + } = useSelect( ( select ) => { - const { getSettings } = select( blockEditorStore ); + const { getBlocks, getSettings, getBlockEditingMode } = + select( blockEditorStore ); // For editing link to the site editor if the theme and user permissions support it. return { + innerBlocks: getBlocks( patternClientId ), onNavigateToEntityRecord: getSettings().onNavigateToEntityRecord, + editingMode: getBlockEditingMode( patternClientId ), hasPatternOverridesSource: !! getBlockBindingsSource( 'core/pattern-overrides' ), }; }, - [] + [ patternClientId ] ); + // Sync the editing mode of the pattern block with the inner blocks. + useEffect( () => { + setBlockEditMode( + setBlockEditingMode, + innerBlocks, + // Disable editing if the pattern itself is disabled. + editingMode === 'disabled' || ! hasPatternOverridesSource + ? 'disabled' + : undefined + ); + }, [ + editingMode, + innerBlocks, + setBlockEditingMode, + hasPatternOverridesSource, + ] ); + const canOverrideBlocks = useMemo( () => hasPatternOverridesSource && hasOverridableBlocks( blocks ), [ hasPatternOverridesSource, blocks ] @@ -200,6 +244,7 @@ function ReusableBlockEdit( { } ); const innerBlocksProps = useInnerBlocksProps( blockProps, { + templateLock: 'all', layout, value: blocks, onInput: NOOP, From 5529e44dbf8b2ae13e9837c2f122458caf6a2c40 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 9 Oct 2024 01:19:20 +0200 Subject: [PATCH 1119/1908] Composite: add legacy unit tests to stable version (#65952) * Composite: add legacy unit tests to stable version * getByText => getByRole --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../components/src/composite/test/index.tsx | 667 +++++++++++++++++- 1 file changed, 629 insertions(+), 38 deletions(-) diff --git a/packages/components/src/composite/test/index.tsx b/packages/components/src/composite/test/index.tsx index 64619aaed01bd6..197302a5f3c9d3 100644 --- a/packages/components/src/composite/test/index.tsx +++ b/packages/components/src/composite/test/index.tsx @@ -15,29 +15,6 @@ import { useState } from '@wordpress/element'; */ import { Composite } from '..'; -// This is necessary because of how Ariakit calculates page up and -// page down. Without this, nothing has a height, and so paging up -// and down doesn't behave as expected in tests. - -let clientHeightSpy: jest.SpiedGetter< - typeof HTMLElement.prototype.clientHeight ->; - -beforeAll( () => { - clientHeightSpy = jest - .spyOn( HTMLElement.prototype, 'clientHeight', 'get' ) - .mockImplementation( function getClientHeight( this: HTMLElement ) { - if ( this.tagName === 'BODY' ) { - return window.outerHeight; - } - return 50; - } ); -} ); - -afterAll( () => { - clientHeightSpy?.mockRestore(); -} ); - async function renderAndValidate( ...args: Parameters< typeof render > ) { const view = render( ...args ); await waitFor( () => { @@ -51,25 +28,148 @@ async function renderAndValidate( ...args: Parameters< typeof render > ) { return view; } -function RemoveItemTest( props: ComponentProps< typeof Composite > ) { - const [ showThirdItem, setShowThirdItem ] = useState( true ); - return ( - <> - <button>Focus trap before composite</button> - <Composite { ...props }> +describe( 'Composite', () => { + let clientHeightSpy: jest.SpiedGetter< + typeof HTMLElement.prototype.clientHeight + >; + + beforeAll( () => { + // This is necessary because of how Ariakit calculates page up and + // page down. Without this, nothing has a height, and so paging up + // and down doesn't behave as expected in tests. + clientHeightSpy = jest + .spyOn( HTMLElement.prototype, 'clientHeight', 'get' ) + .mockImplementation( function getClientHeight( this: HTMLElement ) { + if ( this.tagName === 'BODY' ) { + return window.outerHeight; + } + return 50; + } ); + } ); + + afterAll( () => { + clientHeightSpy?.mockRestore(); + } ); + + test( 'Renders as a single tab stop', async () => { + await renderAndValidate( + <> + <button>Before</button> + <Composite> + <Composite.Item>Item 1</Composite.Item> + <Composite.Item>Item 2</Composite.Item> + <Composite.Item>Item 3</Composite.Item> + </Composite> + <button>After</button> + </> + ); + + await press.Tab(); + expect( + screen.getByRole( 'button', { name: 'Before' } ) + ).toHaveFocus(); + await press.Tab(); + expect( + screen.getByRole( 'button', { name: 'Item 1' } ) + ).toHaveFocus(); + await press.Tab(); + expect( screen.getByRole( 'button', { name: 'After' } ) ).toHaveFocus(); + await press.ShiftTab(); + expect( + screen.getByRole( 'button', { name: 'Item 1' } ) + ).toHaveFocus(); + } ); + + test( 'Excludes disabled items', async () => { + await renderAndValidate( + <Composite> <Composite.Item>Item 1</Composite.Item> - <Composite.Item>Item 2</Composite.Item> - { showThirdItem && <Composite.Item>Item 3</Composite.Item> } + <Composite.Item disabled>Item 2</Composite.Item> + <Composite.Item>Item 3</Composite.Item> </Composite> - <button onClick={ () => setShowThirdItem( ( value ) => ! value ) }> - Toggle third item - </button> - </> - ); -} + ); + + const item1 = screen.getByRole( 'button', { name: 'Item 1' } ); + const item2 = screen.getByRole( 'button', { name: 'Item 2' } ); + const item3 = screen.getByRole( 'button', { name: 'Item 3' } ); + + expect( item2 ).toBeDisabled(); + + await press.Tab(); + expect( item1 ).toHaveFocus(); + await press.ArrowDown(); + expect( item2 ).not.toHaveFocus(); + expect( item3 ).toHaveFocus(); + } ); + + test( 'Includes focusable disabled items', async () => { + await renderAndValidate( + <Composite> + <Composite.Item>Item 1</Composite.Item> + <Composite.Item disabled accessibleWhenDisabled> + Item 2 + </Composite.Item> + <Composite.Item>Item 3</Composite.Item> + </Composite> + ); + + const item1 = screen.getByRole( 'button', { name: 'Item 1' } ); + const item2 = screen.getByRole( 'button', { name: 'Item 2' } ); + const item3 = screen.getByRole( 'button', { name: 'Item 3' } ); + + expect( item2 ).toBeEnabled(); + expect( item2 ).toHaveAttribute( 'aria-disabled', 'true' ); + + await press.Tab(); + expect( item1 ).toHaveFocus(); + await press.ArrowDown(); + expect( item2 ).toHaveFocus(); + expect( item3 ).not.toHaveFocus(); + } ); + + test( 'Supports `activeId`', async () => { + /* eslint-disable no-restricted-syntax */ + await renderAndValidate( + <Composite activeId="item-2"> + <Composite.Item id="item-1">Item 1</Composite.Item> + <Composite.Item id="item-2">Item 2</Composite.Item> + <Composite.Item id="item-3">Item 3</Composite.Item> + </Composite> + ); + /* eslint-enable no-restricted-syntax */ + + const item2 = screen.getByRole( 'button', { name: 'Item 2' } ); + + await press.Tab(); + await waitFor( () => expect( item2 ).toHaveFocus() ); + } ); -describe( 'Composite', () => { it( 'should remain focusable even when there are no elements in the DOM associated with the currently active ID', async () => { + const RemoveItemTest = ( + props: ComponentProps< typeof Composite > + ) => { + const [ showThirdItem, setShowThirdItem ] = useState( true ); + return ( + <> + <button>Focus trap before composite</button> + <Composite { ...props }> + <Composite.Item>Item 1</Composite.Item> + <Composite.Item>Item 2</Composite.Item> + { showThirdItem && ( + <Composite.Item>Item 3</Composite.Item> + ) } + </Composite> + <button + onClick={ () => + setShowThirdItem( ( value ) => ! value ) + } + > + Toggle third item + </button> + </> + ); + }; + await renderAndValidate( <RemoveItemTest /> ); const toggleButton = screen.getByRole( 'button', { @@ -120,4 +220,495 @@ describe( 'Composite', () => { screen.getByRole( 'button', { name: 'Item 3' } ) ).toHaveFocus(); } ); + + describe.each( [ + [ 'When LTR', false ], + [ 'When RTL', true ], + ] )( '%s', ( _when, rtl ) => { + const previousArrowKey = rtl ? 'ArrowRight' : 'ArrowLeft'; + const nextArrowKey = rtl ? 'ArrowLeft' : 'ArrowRight'; + const firstArrowKey = rtl ? 'End' : 'Home'; + const lastArrowKey = rtl ? 'Home' : 'End'; + + describe( 'In one dimension', () => { + test( 'All directions work with no orientation', async () => { + await renderAndValidate( + <Composite rtl={ rtl }> + <Composite.Item>Item 1</Composite.Item> + <Composite.Item>Item 2</Composite.Item> + <Composite.Item>Item 3</Composite.Item> + </Composite> + ); + + const item1 = screen.getByRole( 'button', { name: 'Item 1' } ); + const item2 = screen.getByRole( 'button', { name: 'Item 2' } ); + const item3 = screen.getByRole( 'button', { name: 'Item 3' } ); + + await press.Tab(); + expect( item1 ).toHaveFocus(); + await press.ArrowDown(); + expect( item2 ).toHaveFocus(); + await press.ArrowDown(); + expect( item3 ).toHaveFocus(); + await press.ArrowDown(); + expect( item3 ).toHaveFocus(); + await press.ArrowUp(); + expect( item2 ).toHaveFocus(); + await press.ArrowUp(); + expect( item1 ).toHaveFocus(); + await press.ArrowUp(); + expect( item1 ).toHaveFocus(); + await press( nextArrowKey ); + expect( item2 ).toHaveFocus(); + await press( nextArrowKey ); + expect( item3 ).toHaveFocus(); + await press( previousArrowKey ); + expect( item2 ).toHaveFocus(); + await press( previousArrowKey ); + expect( item1 ).toHaveFocus(); + await press.End(); + expect( item3 ).toHaveFocus(); + await press.Home(); + expect( item1 ).toHaveFocus(); + await press.PageDown(); + expect( item3 ).toHaveFocus(); + await press.PageUp(); + expect( item1 ).toHaveFocus(); + } ); + + test( 'Only left/right work with horizontal orientation', async () => { + await renderAndValidate( + <Composite rtl={ rtl } orientation="horizontal"> + <Composite.Item>Item 1</Composite.Item> + <Composite.Item>Item 2</Composite.Item> + <Composite.Item>Item 3</Composite.Item> + </Composite> + ); + + const item1 = screen.getByRole( 'button', { name: 'Item 1' } ); + const item2 = screen.getByRole( 'button', { name: 'Item 2' } ); + const item3 = screen.getByRole( 'button', { name: 'Item 3' } ); + + await press.Tab(); + expect( item1 ).toHaveFocus(); + await press.ArrowDown(); + expect( item1 ).toHaveFocus(); + await press( nextArrowKey ); + expect( item2 ).toHaveFocus(); + await press( nextArrowKey ); + expect( item3 ).toHaveFocus(); + await press.ArrowUp(); + expect( item3 ).toHaveFocus(); + await press( previousArrowKey ); + expect( item2 ).toHaveFocus(); + await press( previousArrowKey ); + expect( item1 ).toHaveFocus(); + await press.End(); + expect( item3 ).toHaveFocus(); + await press.Home(); + expect( item1 ).toHaveFocus(); + await press.PageDown(); + expect( item3 ).toHaveFocus(); + await press.PageUp(); + expect( item1 ).toHaveFocus(); + } ); + + test( 'Only up/down work with vertical orientation', async () => { + await renderAndValidate( + <Composite rtl={ rtl } orientation="vertical"> + <Composite.Item>Item 1</Composite.Item> + <Composite.Item>Item 2</Composite.Item> + <Composite.Item>Item 3</Composite.Item> + </Composite> + ); + + const item1 = screen.getByRole( 'button', { name: 'Item 1' } ); + const item2 = screen.getByRole( 'button', { name: 'Item 2' } ); + const item3 = screen.getByRole( 'button', { name: 'Item 3' } ); + + await press.Tab(); + expect( item1 ).toHaveFocus(); + await press( nextArrowKey ); + expect( item1 ).toHaveFocus(); + await press.ArrowDown(); + expect( item2 ).toHaveFocus(); + await press.ArrowDown(); + expect( item3 ).toHaveFocus(); + await press( previousArrowKey ); + expect( item3 ).toHaveFocus(); + await press.ArrowUp(); + expect( item2 ).toHaveFocus(); + await press.ArrowUp(); + expect( item1 ).toHaveFocus(); + await press.End(); + expect( item3 ).toHaveFocus(); + await press.Home(); + expect( item1 ).toHaveFocus(); + await press.PageDown(); + expect( item3 ).toHaveFocus(); + await press.PageUp(); + expect( item1 ).toHaveFocus(); + } ); + + test( 'Focus wraps with loop enabled', async () => { + await renderAndValidate( + <Composite rtl={ rtl } focusLoop> + <Composite.Item>Item 1</Composite.Item> + <Composite.Item>Item 2</Composite.Item> + <Composite.Item>Item 3</Composite.Item> + </Composite> + ); + + const item1 = screen.getByRole( 'button', { name: 'Item 1' } ); + const item2 = screen.getByRole( 'button', { name: 'Item 2' } ); + const item3 = screen.getByRole( 'button', { name: 'Item 3' } ); + + await press.Tab(); + expect( item1 ).toHaveFocus(); + await press.ArrowDown(); + expect( item2 ).toHaveFocus(); + await press.ArrowDown(); + expect( item3 ).toHaveFocus(); + await press.ArrowDown(); + expect( item1 ).toHaveFocus(); + await press.ArrowUp(); + expect( item3 ).toHaveFocus(); + await press( nextArrowKey ); + expect( item1 ).toHaveFocus(); + await press( previousArrowKey ); + expect( item3 ).toHaveFocus(); + } ); + } ); + + describe( 'In two dimensions', () => { + test( 'All directions work as standard', async () => { + await renderAndValidate( + <Composite rtl={ rtl }> + <Composite.Row> + <Composite.Item>Item A1</Composite.Item> + <Composite.Item>Item A2</Composite.Item> + <Composite.Item>Item A3</Composite.Item> + </Composite.Row> + <Composite.Row> + <Composite.Item>Item B1</Composite.Item> + <Composite.Item>Item B2</Composite.Item> + <Composite.Item>Item B3</Composite.Item> + </Composite.Row> + <Composite.Row> + <Composite.Item>Item C1</Composite.Item> + <Composite.Item>Item C2</Composite.Item> + <Composite.Item>Item C3</Composite.Item> + </Composite.Row> + </Composite> + ); + + const itemA1 = screen.getByRole( 'button', { + name: 'Item A1', + } ); + const itemA2 = screen.getByRole( 'button', { + name: 'Item A2', + } ); + const itemA3 = screen.getByRole( 'button', { + name: 'Item A3', + } ); + const itemB1 = screen.getByRole( 'button', { + name: 'Item B1', + } ); + const itemB2 = screen.getByRole( 'button', { + name: 'Item B2', + } ); + const itemC1 = screen.getByRole( 'button', { + name: 'Item C1', + } ); + const itemC3 = screen.getByRole( 'button', { + name: 'Item C3', + } ); + + await press.Tab(); + expect( itemA1 ).toHaveFocus(); + await press.ArrowUp(); + expect( itemA1 ).toHaveFocus(); + await press( previousArrowKey ); + expect( itemA1 ).toHaveFocus(); + await press.ArrowDown(); + expect( itemB1 ).toHaveFocus(); + await press( nextArrowKey ); + expect( itemB2 ).toHaveFocus(); + await press.ArrowUp(); + expect( itemA2 ).toHaveFocus(); + await press( previousArrowKey ); + expect( itemA1 ).toHaveFocus(); + await press( lastArrowKey ); + expect( itemA3 ).toHaveFocus(); + await press.PageDown(); + expect( itemC3 ).toHaveFocus(); + await press( nextArrowKey ); + expect( itemC3 ).toHaveFocus(); + await press.ArrowDown(); + expect( itemC3 ).toHaveFocus(); + await press( firstArrowKey ); + expect( itemC1 ).toHaveFocus(); + await press.PageUp(); + expect( itemA1 ).toHaveFocus(); + await press.End( null, { ctrlKey: true } ); + expect( itemC3 ).toHaveFocus(); + await press.Home( null, { ctrlKey: true } ); + expect( itemA1 ).toHaveFocus(); + } ); + + test( 'Focus wraps around rows/columns with loop enabled', async () => { + await renderAndValidate( + <Composite rtl={ rtl } focusLoop> + <Composite.Row> + <Composite.Item>Item A1</Composite.Item> + <Composite.Item>Item A2</Composite.Item> + <Composite.Item>Item A3</Composite.Item> + </Composite.Row> + <Composite.Row> + <Composite.Item>Item B1</Composite.Item> + <Composite.Item>Item B2</Composite.Item> + <Composite.Item>Item B3</Composite.Item> + </Composite.Row> + <Composite.Row> + <Composite.Item>Item C1</Composite.Item> + <Composite.Item>Item C2</Composite.Item> + <Composite.Item>Item C3</Composite.Item> + </Composite.Row> + </Composite> + ); + + const itemA1 = screen.getByRole( 'button', { + name: 'Item A1', + } ); + const itemA2 = screen.getByRole( 'button', { + name: 'Item A2', + } ); + const itemA3 = screen.getByRole( 'button', { + name: 'Item A3', + } ); + const itemB1 = screen.getByRole( 'button', { + name: 'Item B1', + } ); + const itemC1 = screen.getByRole( 'button', { + name: 'Item C1', + } ); + const itemC3 = screen.getByRole( 'button', { + name: 'Item C3', + } ); + + await press.Tab(); + expect( itemA1 ).toHaveFocus(); + await press( nextArrowKey ); + expect( itemA2 ).toHaveFocus(); + await press( nextArrowKey ); + expect( itemA3 ).toHaveFocus(); + await press( nextArrowKey ); + expect( itemA1 ).toHaveFocus(); + await press.ArrowDown(); + expect( itemB1 ).toHaveFocus(); + await press.ArrowDown(); + expect( itemC1 ).toHaveFocus(); + await press.ArrowDown(); + expect( itemA1 ).toHaveFocus(); + await press( previousArrowKey ); + expect( itemA3 ).toHaveFocus(); + await press.ArrowUp(); + expect( itemC3 ).toHaveFocus(); + } ); + + test( 'Focus moves between rows/columns with wrap enabled', async () => { + await renderAndValidate( + <Composite rtl={ rtl } focusWrap> + <Composite.Row> + <Composite.Item>Item A1</Composite.Item> + <Composite.Item>Item A2</Composite.Item> + <Composite.Item>Item A3</Composite.Item> + </Composite.Row> + <Composite.Row> + <Composite.Item>Item B1</Composite.Item> + <Composite.Item>Item B2</Composite.Item> + <Composite.Item>Item B3</Composite.Item> + </Composite.Row> + <Composite.Row> + <Composite.Item>Item C1</Composite.Item> + <Composite.Item>Item C2</Composite.Item> + <Composite.Item>Item C3</Composite.Item> + </Composite.Row> + </Composite> + ); + + const itemA1 = screen.getByRole( 'button', { + name: 'Item A1', + } ); + const itemA2 = screen.getByRole( 'button', { + name: 'Item A2', + } ); + const itemA3 = screen.getByRole( 'button', { + name: 'Item A3', + } ); + const itemB1 = screen.getByRole( 'button', { + name: 'Item B1', + } ); + const itemC1 = screen.getByRole( 'button', { + name: 'Item C1', + } ); + const itemC3 = screen.getByRole( 'button', { + name: 'Item C3', + } ); + await press.Tab(); + expect( itemA1 ).toHaveFocus(); + await press( nextArrowKey ); + expect( itemA2 ).toHaveFocus(); + await press( nextArrowKey ); + expect( itemA3 ).toHaveFocus(); + await press( nextArrowKey ); + expect( itemB1 ).toHaveFocus(); + await press.ArrowDown(); + expect( itemC1 ).toHaveFocus(); + await press.ArrowDown(); + expect( itemA2 ).toHaveFocus(); + await press( previousArrowKey ); + expect( itemA1 ).toHaveFocus(); + await press( previousArrowKey ); + expect( itemA1 ).toHaveFocus(); + await press.ArrowUp(); + expect( itemA1 ).toHaveFocus(); + await press.End( itemA1, { ctrlKey: true } ); + expect( itemC3 ).toHaveFocus(); + await press( nextArrowKey ); + expect( itemC3 ).toHaveFocus(); + await press.ArrowDown(); + expect( itemC3 ).toHaveFocus(); + } ); + + test( 'Focus wraps around start/end with loop and wrap enabled', async () => { + await renderAndValidate( + <Composite rtl={ rtl } focusLoop focusWrap> + <Composite.Row> + <Composite.Item>Item A1</Composite.Item> + <Composite.Item>Item A2</Composite.Item> + <Composite.Item>Item A3</Composite.Item> + </Composite.Row> + <Composite.Row> + <Composite.Item>Item B1</Composite.Item> + <Composite.Item>Item B2</Composite.Item> + <Composite.Item>Item B3</Composite.Item> + </Composite.Row> + <Composite.Row> + <Composite.Item>Item C1</Composite.Item> + <Composite.Item>Item C2</Composite.Item> + <Composite.Item>Item C3</Composite.Item> + </Composite.Row> + </Composite> + ); + + const itemA1 = screen.getByRole( 'button', { + name: 'Item A1', + } ); + const itemC3 = screen.getByRole( 'button', { + name: 'Item C3', + } ); + + await press.Tab(); + expect( itemA1 ).toHaveFocus(); + await press( previousArrowKey ); + expect( itemC3 ).toHaveFocus(); + await press.ArrowDown(); + expect( itemA1 ).toHaveFocus(); + await press.ArrowUp(); + expect( itemC3 ).toHaveFocus(); + await press( nextArrowKey ); + expect( itemA1 ).toHaveFocus(); + } ); + + test( 'Focus shifts if vertical neighbor unavailable when shift enabled', async () => { + await renderAndValidate( + <Composite rtl={ rtl } focusShift> + <Composite.Row> + <Composite.Item>Item A1</Composite.Item> + </Composite.Row> + <Composite.Row> + <Composite.Item>Item B1</Composite.Item> + <Composite.Item>Item B2</Composite.Item> + </Composite.Row> + <Composite.Row> + <Composite.Item>Item C1</Composite.Item> + <Composite.Item disabled>Item C2</Composite.Item> + </Composite.Row> + </Composite> + ); + + const itemA1 = screen.getByRole( 'button', { + name: 'Item A1', + } ); + const itemB1 = screen.getByRole( 'button', { + name: 'Item B1', + } ); + const itemB2 = screen.getByRole( 'button', { + name: 'Item B2', + } ); + const itemC1 = screen.getByRole( 'button', { + name: 'Item C1', + } ); + + await press.Tab(); + expect( itemA1 ).toHaveFocus(); + await press.ArrowDown(); + expect( itemB1 ).toHaveFocus(); + await press( nextArrowKey ); + expect( itemB2 ).toHaveFocus(); + await press.ArrowUp(); + // A2 doesn't exist + expect( itemA1 ).toHaveFocus(); + await press.ArrowDown(); + expect( itemB1 ).toHaveFocus(); + await press( nextArrowKey ); + expect( itemB2 ).toHaveFocus(); + await press.ArrowDown(); + // C2 is disabled + expect( itemC1 ).toHaveFocus(); + } ); + + test( 'Focus does not shift if vertical neighbor unavailable when shift not enabled', async () => { + await renderAndValidate( + <Composite rtl={ rtl }> + <Composite.Row> + <Composite.Item>Item A1</Composite.Item> + </Composite.Row> + <Composite.Row> + <Composite.Item>Item B1</Composite.Item> + <Composite.Item>Item B2</Composite.Item> + </Composite.Row> + <Composite.Row> + <Composite.Item>Item C1</Composite.Item> + <Composite.Item disabled>Item C2</Composite.Item> + </Composite.Row> + </Composite> + ); + + const itemA1 = screen.getByRole( 'button', { + name: 'Item A1', + } ); + const itemB1 = screen.getByRole( 'button', { + name: 'Item B1', + } ); + const itemB2 = screen.getByRole( 'button', { + name: 'Item B2', + } ); + + await press.Tab(); + expect( itemA1 ).toHaveFocus(); + await press.ArrowDown(); + expect( itemB1 ).toHaveFocus(); + await press( nextArrowKey ); + expect( itemB2 ).toHaveFocus(); + await press.ArrowUp(); + // A2 doesn't exist + expect( itemB2 ).toHaveFocus(); + await press.ArrowDown(); + // C2 is disabled + expect( itemB2 ).toHaveFocus(); + } ); + } ); + } ); } ); From 09d6ede98cf32af20c24eb06147c4c7bcdcbb692 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 9 Oct 2024 09:00:21 +0000 Subject: [PATCH 1120/1908] Bump plugin version to 19.4.0 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index c9f4a8fc580200..1a7f0df4814217 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.4.0-rc.1 + * Version: 19.4.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 5de2d0320139ee..efb60e897864d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.4.0-rc.1", + "version": "19.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.4.0-rc.1", + "version": "19.4.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 5b8af1f99e7ad9..b60152ef0fe0cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.4.0-rc.1", + "version": "19.4.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 6be7f8f9ecb8fdc0f1c69803507850a1781407bb Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 9 Oct 2024 09:17:15 +0000 Subject: [PATCH 1121/1908] Update Changelog for 19.4.0 --- changelog.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 06d92230737fc5..b74a541e9cd1ea 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,6 @@ == Changelog == -= 19.4.0-rc.1 = - += 19.4.0 = ## Changelog @@ -43,6 +42,7 @@ - Storybook: Allow for case-agnostic filtering of icons. ([65780](https://github.com/WordPress/gutenberg/pull/65780)) - ToggleGroupControl: Improve animation. ([65175](https://github.com/WordPress/gutenberg/pull/65175)) - Tabs: Tweak sizing and overflow behavior of TabList. ([64371](https://github.com/WordPress/gutenberg/pull/64371)) +- Tabs: Unify vertical tabs styles. ([65387](https://github.com/WordPress/gutenberg/pull/65387)) #### Zoom Out - Add prompt to zoom out separator. ([65392](https://github.com/WordPress/gutenberg/pull/65392)) From 72d2ff4a041d570dd7a6504a8384ebf6e5b91fee Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Wed, 9 Oct 2024 12:55:14 +0200 Subject: [PATCH 1122/1908] Upgrade browserslist and webcompat data packages (#65926) * Upgrade browserslist and webcompat data packages * Limit view scripts to the Form block * Update blocks.js * Upgrade also webpack * Update snapshots --------- Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- package-lock.json | 146 ++++++++---------- package.json | 10 +- .../test/__snapshots__/build.js.snap | 60 +++---- .../test/__snapshots__/build.js.snap | 2 - packages/scripts/package.json | 4 +- tools/webpack/blocks.js | 4 +- 6 files changed, 106 insertions(+), 120 deletions(-) diff --git a/package-lock.json b/package-lock.json index efb60e897864d9..6c126a89593fff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -169,15 +169,15 @@ "babel-plugin-react-native-platform-specific-extensions": "1.1.1", "babel-plugin-transform-remove-console": "6.9.4", "benchmark": "2.1.4", - "browserslist": "4.22.2", - "caniuse-lite": "1.0.30001636", + "browserslist": "4.24.0", + "caniuse-lite": "1.0.30001667", "chalk": "4.1.1", "change-case": "4.1.2", "client-zip": "^2.4.5", "commander": "9.2.0", "concurrently": "3.5.0", "copy-webpack-plugin": "10.2.0", - "core-js-builder": "3.35.1", + "core-js-builder": "3.38.1", "cross-env": "3.2.4", "css-loader": "6.2.0", "cssnano": "6.0.1", @@ -246,11 +246,11 @@ "strip-json-comments": "5.0.0", "style-loader": "3.2.1", "terser": "5.32.0", - "terser-webpack-plugin": "5.3.9", + "terser-webpack-plugin": "5.3.10", "typescript": "5.5.3", "uuid": "9.0.1", "webdriverio": "8.16.20", - "webpack": "5.88.2", + "webpack": "5.95.0", "webpack-bundle-analyzer": "4.9.1", "worker-farm": "1.7.0" }, @@ -14594,16 +14594,6 @@ "@types/json-schema": "*" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -17556,10 +17546,10 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "dev": true, "peerDependencies": { "acorn": "^8" @@ -20075,9 +20065,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", "funding": [ { "type": "opencollective", @@ -20093,10 +20083,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -20483,9 +20473,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001636", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz", - "integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==", + "version": "1.0.30001667", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz", + "integrity": "sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==", "funding": [ { "type": "opencollective", @@ -20499,8 +20489,7 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ], - "license": "CC-BY-4.0" + ] }, "node_modules/capital-case": { "version": "1.0.4", @@ -22276,9 +22265,9 @@ } }, "node_modules/core-js": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.35.1.tgz", - "integrity": "sha512-IgdsbxNyMskrTFxa9lWHyMwAJU5gXOPP+1yO+K59d50VLVAIDAbs7gIv705KzALModfK3ZrSZTPNpC0PQgIZuw==", + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz", + "integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -22286,14 +22275,14 @@ } }, "node_modules/core-js-builder": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/core-js-builder/-/core-js-builder-3.35.1.tgz", - "integrity": "sha512-CfIvg+khWyS7ElbRXhuQH9QVUQxRDFl8AUwP08BxubJmYtRZuqwjwvc/DVnwRXQ6sqg8ghfNRgnUDWzwNhU/Rw==", + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-builder/-/core-js-builder-3.38.1.tgz", + "integrity": "sha512-SxxFz0xLPX+MMCC3QtRavu5rzhFe28QqiaQKko+25DrUEsPYbNasZACUkKDDGfInxJiUk/9/PhmHwIdyN4vSKA==", "dev": true, "dependencies": { - "core-js": "3.35.1", - "core-js-compat": "3.35.1", - "mkdirp": ">=0.5.5 <1", + "core-js": "3.38.1", + "core-js-compat": "3.38.1", + "mkdirp": ">=0.5.6 <1", "webpack": ">=4.47.0 <5" }, "engines": { @@ -22549,11 +22538,11 @@ } }, "node_modules/core-js-compat": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.1.tgz", - "integrity": "sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw==", + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", "dependencies": { - "browserslist": "^4.22.2" + "browserslist": "^4.23.3" }, "funding": { "type": "opencollective", @@ -24666,9 +24655,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.643", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.643.tgz", - "integrity": "sha512-QHscvvS7gt155PtoRC0dR2ilhL8E9LHhfTQEq1uD5AL0524rBLAwpAREFH06f87/e45B9XkR6Ki5dbhbCsVEIg==" + "version": "1.5.33", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.33.tgz", + "integrity": "sha512-+cYTcFB1QqD4j4LegwLfpCNxifb6dDFUAwk6RsLusCwIaZI6or2f+q8rs5tTB2YC53HhOlIbEaqHMAAC8IOIwA==" }, "node_modules/elegant-spinner": { "version": "1.0.1", @@ -25098,9 +25087,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "engines": { "node": ">=6" } @@ -38007,9 +37996,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "node_modules/node-stream-zip": { "version": "1.15.0", @@ -48476,16 +48465,16 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", + "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" + "terser": "^5.26.0" }, "engines": { "node": ">= 10.13.0" @@ -49726,9 +49715,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "funding": [ { "type": "opencollective", @@ -49744,8 +49733,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -50950,34 +50939,33 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/webpack": { - "version": "5.88.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", - "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", + "version": "5.95.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", + "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", "dev": true, "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { @@ -55196,9 +55184,9 @@ "schema-utils": "^4.2.0", "source-map-loader": "^3.0.0", "stylelint": "^16.8.2", - "terser-webpack-plugin": "^5.3.9", + "terser-webpack-plugin": "^5.3.10", "url-loader": "^4.1.1", - "webpack": "^5.88.2", + "webpack": "^5.95.0", "webpack-bundle-analyzer": "^4.9.1", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1" diff --git a/package.json b/package.json index b60152ef0fe0cb..50a0b3720cdc32 100644 --- a/package.json +++ b/package.json @@ -181,15 +181,15 @@ "babel-plugin-react-native-platform-specific-extensions": "1.1.1", "babel-plugin-transform-remove-console": "6.9.4", "benchmark": "2.1.4", - "browserslist": "4.22.2", - "caniuse-lite": "1.0.30001636", + "browserslist": "4.24.0", + "caniuse-lite": "1.0.30001667", "chalk": "4.1.1", "change-case": "4.1.2", "client-zip": "^2.4.5", "commander": "9.2.0", "concurrently": "3.5.0", "copy-webpack-plugin": "10.2.0", - "core-js-builder": "3.35.1", + "core-js-builder": "3.38.1", "cross-env": "3.2.4", "css-loader": "6.2.0", "cssnano": "6.0.1", @@ -258,11 +258,11 @@ "strip-json-comments": "5.0.0", "style-loader": "3.2.1", "terser": "5.32.0", - "terser-webpack-plugin": "5.3.9", + "terser-webpack-plugin": "5.3.10", "typescript": "5.5.3", "uuid": "9.0.1", "webdriverio": "8.16.20", - "webpack": "5.88.2", + "webpack": "5.95.0", "webpack-bundle-analyzer": "4.9.1", "worker-farm": "1.7.0" }, diff --git a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap index f0d418851103ba..8ea40b00d7c2d1 100644 --- a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap +++ b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap @@ -26,7 +26,7 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`combine-assets\` sh `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-dependency-graph\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('@wordpress/interactivity'), 'version' => '58fadee5eca3ad30aff6', 'type' => 'module'); +"<?php return array('dependencies' => array('@wordpress/interactivity'), 'version' => '1e02dcb4017382a2799f', 'type' => 'module'); " `; @@ -41,7 +41,7 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-dependency-g `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-dynamic-dependency-graph\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array(array('id' => '@wordpress/interactivity', 'import' => 'dynamic')), 'version' => '293aebad4ca761cf396f', 'type' => 'module'); +"<?php return array('dependencies' => array(array('id' => '@wordpress/interactivity', 'import' => 'dynamic')), 'version' => '3e43f50123c85675372f', 'type' => 'module'); " `; @@ -56,7 +56,7 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-dynamic-depe `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-external-deps\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array(array('id' => '@wordpress/interactivity', 'import' => 'dynamic')), 'version' => 'e1033c1bd62e8cb8d4c9', 'type' => 'module'); +"<?php return array('dependencies' => array(array('id' => '@wordpress/interactivity', 'import' => 'dynamic')), 'version' => '095eb9129a2ad858900d', 'type' => 'module'); " `; @@ -71,7 +71,7 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-external-dep `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`dynamic-import\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array(array('id' => '@wordpress/blob', 'import' => 'dynamic')), 'version' => '4f59b7847b70a07b2710', 'type' => 'module'); +"<?php return array('dependencies' => array(array('id' => '@wordpress/blob', 'import' => 'dynamic')), 'version' => '1c950858231a54e241b8', 'type' => 'module'); " `; @@ -155,7 +155,7 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`module-renames\` sh `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`no-default\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array(), 'version' => '34504aa793c63cd3d73a', 'type' => 'module'); +"<?php return array('dependencies' => array(), 'version' => 'fcac76462c8a830d8d92', 'type' => 'module'); " `; @@ -265,17 +265,17 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comm exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comment-minified\` should produce expected output: External modules should match snapshot 1`] = `[]`; exports[`DependencyExtractionWebpackPlugin modules Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'a.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('@wordpress/blob'), 'version' => 'a1906cfc819b623c86f8', 'type' => 'module'); +"<?php return array('dependencies' => array('@wordpress/blob'), 'version' => 'ee5ac21a1f0003d732e6', 'type' => 'module'); " `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'b.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('@wordpress/blob', 'lodash'), 'version' => '04771412967314fde455', 'type' => 'module'); +"<?php return array('dependencies' => array('@wordpress/blob', 'lodash'), 'version' => '5b112b32c6db548c2997', 'type' => 'module'); " `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'runtime.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array(), 'version' => 'e7402f5608a888d8fd66', 'type' => 'module'); +"<?php return array('dependencies' => array(), 'version' => 'b1ca4106075e0bd94f9c', 'type' => 'module'); " `; @@ -335,7 +335,7 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`wordpress\` should `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`wordpress-interactivity\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('lodash', array('id' => '@wordpress/interactivity', 'import' => 'dynamic')), 'version' => 'fcc07ce68574cdc2a6a5', 'type' => 'module'); +"<?php return array('dependencies' => array('lodash', array('id' => '@wordpress/interactivity', 'import' => 'dynamic')), 'version' => '363140026eaa9abcaf33', 'type' => 'module'); " `; @@ -355,7 +355,7 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`wordpress-interacti `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`wordpress-require\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('@wordpress/blob', 'lodash'), 'version' => 'f40de15d66b54da440d2', 'type' => 'module'); +"<?php return array('dependencies' => array('@wordpress/blob', 'lodash'), 'version' => 'ee5a6866beeb5643397c', 'type' => 'module'); " `; @@ -375,7 +375,7 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`wordpress-require\` `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`combine-assets\` should produce expected output: Asset file 'assets.php' should match snapshot 1`] = ` -"<?php return array('fileA.js' => array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'cbe985cf6e1a25d848e5'), 'fileB.js' => array('dependencies' => array('wp-token-list'), 'version' => '7f3970305cf0aecb54ab')); +"<?php return array('fileA.js' => array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'e1840d27f0719ffa42d3'), 'fileB.js' => array('dependencies' => array('wp-token-list'), 'version' => '1e60e007d6496c9b46cf')); " `; @@ -406,7 +406,7 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`combine-assets\` sh `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-dependency-graph\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('wp-interactivity'), 'version' => '79a1af3afac581f52492'); +"<?php return array('dependencies' => array('wp-interactivity'), 'version' => '82601013091064d44360'); " `; @@ -424,7 +424,7 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-dependency-g `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-dynamic-dependency-graph\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('wp-interactivity'), 'version' => 'ac0e2f1bcd3a6a0e7aff'); +"<?php return array('dependencies' => array('wp-interactivity'), 'version' => '162f4d352c99e6c37be1'); " `; @@ -442,7 +442,7 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-dynamic-depe `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-external-deps\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('wp-interactivity'), 'version' => '455f3cab924853d41b8b'); +"<?php return array('dependencies' => array('wp-interactivity'), 'version' => '4c336c2cbbbff439b43e'); " `; @@ -460,7 +460,7 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-external-dep `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`dynamic-import\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('wp-blob'), 'version' => 'c0e8a6f22065ea096606'); +"<?php return array('dependencies' => array('wp-blob'), 'version' => '29070464c1c503708675'); " `; @@ -484,7 +484,7 @@ Module not found: Error: Ensure error in script build. `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`function-output-filename\` should produce expected output: Asset file 'chunk--main--main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'fc2d750fc9e08c5749db'); +"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '0633d70f7567175ad0d5'); " `; @@ -507,7 +507,7 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`function-output-fil `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`has-extension-suffix\` should produce expected output: Asset file 'index.min.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'c3f17b34fdd974d57d0f'); +"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '91d6fc79d8288f1bd30f'); " `; @@ -530,7 +530,7 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`has-extension-suffi `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`module-renames\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('renamed--@my/module', 'renamed--other-module'), 'version' => '34854902f36ec8e176d6'); +"<?php return array('dependencies' => array('renamed--@my/module', 'renamed--other-module'), 'version' => '728ec64636a1f078764f'); " `; @@ -563,14 +563,14 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`no-default\` should exports[`DependencyExtractionWebpackPlugin scripts Webpack \`no-default\` should produce expected output: External modules should match snapshot 1`] = `[]`; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`no-deps\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array(), 'version' => '143ed23d4b8be5611fcb'); +"<?php return array('dependencies' => array(), 'version' => 'b922a4320dd8b7a352f4'); " `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`no-deps\` should produce expected output: External modules should match snapshot 1`] = `[]`; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`option-function-output-filename\` should produce expected output: Asset file 'chunk--main--main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'fc2d750fc9e08c5749db'); +"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '0633d70f7567175ad0d5'); " `; @@ -593,7 +593,7 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`option-function-out `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`option-output-filename\` should produce expected output: Asset file 'main-foo.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'fc2d750fc9e08c5749db'); +"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '0633d70f7567175ad0d5'); " `; @@ -615,7 +615,7 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`option-output-filen ] `; -exports[`DependencyExtractionWebpackPlugin scripts Webpack \`output-format-json\` should produce expected output: Asset file 'main.asset.json' should match snapshot 1`] = `"{"dependencies":["lodash"],"version":"7bd48470d799a795bf9a"}"`; +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`output-format-json\` should produce expected output: Asset file 'main.asset.json' should match snapshot 1`] = `"{"dependencies":["lodash"],"version":"b36983b739da7af0ccd4"}"`; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`output-format-json\` should produce expected output: External modules should match snapshot 1`] = ` [ @@ -628,7 +628,7 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`output-format-json\ `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`overrides\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('wp-blob', 'wp-script-handle-for-rxjs', 'wp-url'), 'version' => '708c71445153f1d07e4a'); +"<?php return array('dependencies' => array('wp-blob', 'wp-script-handle-for-rxjs', 'wp-url'), 'version' => '35e570db18559a76b3e6'); " `; @@ -667,7 +667,7 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`overrides\` should `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comment\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('wp-polyfill'), 'version' => '464c785b5c938d4fde3f'); +"<?php return array('dependencies' => array('wp-polyfill'), 'version' => '48f720dd907eea75c1fd'); " `; @@ -681,17 +681,17 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comm exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comment-minified\` should produce expected output: External modules should match snapshot 1`] = `[]`; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'a.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('wp-blob'), 'version' => 'd3cda564b538b44d38ef'); +"<?php return array('dependencies' => array('wp-blob'), 'version' => 'd091f1cbbf7603d6e12c'); " `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'b.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '420d636da562e71648f7'); +"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '845bc6d4ffbdb9419ebd'); " `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'runtime.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array(), 'version' => 'dc673033633cae5c6702'); +"<?php return array('dependencies' => array(), 'version' => '717eb779e609d175a7dd'); " `; @@ -714,7 +714,7 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`runtime-chunk-singl `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`style-imports\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '4c661914a4e4d80b8a0b'); +"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '041fb611b5192ffe83f9'); " `; @@ -737,7 +737,7 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`style-imports\` sho `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`wordpress\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'fc2d750fc9e08c5749db'); +"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '0633d70f7567175ad0d5'); " `; @@ -783,7 +783,7 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`wordpress-interacti `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`wordpress-require\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '40370eb4ce6428562da6'); +"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '7087050d1490e856fec8'); " `; diff --git a/packages/readable-js-assets-webpack-plugin/test/__snapshots__/build.js.snap b/packages/readable-js-assets-webpack-plugin/test/__snapshots__/build.js.snap index c033e572e8e5e4..92670d3d1cb376 100644 --- a/packages/readable-js-assets-webpack-plugin/test/__snapshots__/build.js.snap +++ b/packages/readable-js-assets-webpack-plugin/test/__snapshots__/build.js.snap @@ -2,7 +2,6 @@ exports[`ReadableJsAssetsWebpackPlugin should produce the expected output: Asset file index.js should match snapshot 1`] = ` "/******/ (() => { // webpackBootstrap -var __webpack_exports__ = {}; function notMinified() { // eslint-disable-next-line no-console console.log( 'hello' ); @@ -17,7 +16,6 @@ exports[`ReadableJsAssetsWebpackPlugin should produce the expected output: Asset exports[`ReadableJsAssetsWebpackPlugin should produce the expected output: Asset file view.js should match snapshot 1`] = ` "/******/ (() => { // webpackBootstrap -var __webpack_exports__ = {}; function notMinified() { // eslint-disable-next-line no-console console.log( 'hello' ); diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 29fef4864a991d..19c474e27ffd9f 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -86,9 +86,9 @@ "schema-utils": "^4.2.0", "source-map-loader": "^3.0.0", "stylelint": "^16.8.2", - "terser-webpack-plugin": "^5.3.9", + "terser-webpack-plugin": "^5.3.10", "url-loader": "^4.1.1", - "webpack": "^5.88.2", + "webpack": "^5.95.0", "webpack-bundle-analyzer": "^4.9.1", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1" diff --git a/tools/webpack/blocks.js b/tools/webpack/blocks.js index a7866b61a6a1f4..02a379d3cdae20 100644 --- a/tools/webpack/blocks.js +++ b/tools/webpack/blocks.js @@ -54,12 +54,12 @@ const createEntrypoints = () => { /* * Returns an array of paths to block view files within the `@wordpress/block-library` package. * These paths can be matched by the regex `blockViewRegex` in order to extract - * the block's filename. + * the block's filename. All blocks were migrated to script modules but the Form block. * * Returns an empty array if no files were found. */ const blockViewScriptPaths = fastGlob.sync( - './packages/block-library/build-module/**/view*.js' + './packages/block-library/build-module/form/view.js' ); /* From 6aad856241e57134b6dfc62b4e9e3ea827c0b935 Mon Sep 17 00:00:00 2001 From: Miguel Fonseca <150562+mcsf@users.noreply.github.com> Date: Wed, 9 Oct 2024 13:27:13 +0200 Subject: [PATCH 1123/1908] env: README: Expand examples of path syntax (#65972) --- packages/env/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/env/README.md b/packages/env/README.md index b82f59f734840c..35b00fe83e8f4d 100644 --- a/packages/env/README.md +++ b/packages/env/README.md @@ -499,7 +499,7 @@ Several types of strings can be passed into the `core`, `plugins`, `themes`, and | ----------------- | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | Relative path | `.<path>\|~<path>` | `"./a/directory"`, `"../a/directory"`, `"~/a/directory"` | | Absolute path | `/<path>\|<letter>:\<path>` | `"/a/directory"`, `"C:\\a\\directory"` | -| GitHub repository | `<owner>/<repo>[#<ref>]` | `"WordPress/WordPress"`, `"WordPress/gutenberg#trunk"`, if no branch is provided wp-env will fall back to the repos default branch | +| GitHub repository | `<owner>/<repo>[/<path>][#<ref>]` | `"WordPress/WordPress"`, `"WordPress/gutenberg#trunk"`, `WordPress/themes/my-theme#my-branch`; if no branch is provided wp-env will fall back to the repo's default branch | | SSH repository | `ssh://user@host/<owner>/<repo>.git[#<ref>]` | `"ssh://git@github.com/WordPress/WordPress.git"` | | ZIP File | `http[s]://<host>/<path>.zip` | `"https://wordpress.org/wordpress-5.4-beta2.zip"` | From 7340783694bdeaa8c4c73030b7a05c83cdcffa44 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 9 Oct 2024 15:07:38 +0200 Subject: [PATCH 1124/1908] Update node-fetch to 2.7.0 (#65957) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- package-lock.json | 54 +++++++++++------------ package.json | 2 +- packages/e2e-test-utils/package.json | 2 +- packages/react-native-editor/package.json | 2 +- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6c126a89593fff..4f55f02a79706d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -212,7 +212,7 @@ "mock-match-media": "0.4.2", "moment-timezone-data-webpack-plugin": "1.5.1", "nock": "12.0.3", - "node-fetch": "2.6.7", + "node-fetch": "2.7.0", "node-watch": "0.7.0", "npm-run-all": "4.1.5", "patch-package": "8.0.0", @@ -22702,27 +22702,6 @@ "node-fetch": "^2.6.12" } }, - "node_modules/cross-fetch/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -33348,6 +33327,27 @@ "node": "*" } }, + "node_modules/lerna/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/lerna/node_modules/npm-package-arg": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.1.tgz", @@ -37842,9 +37842,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" @@ -53714,7 +53714,7 @@ "@wordpress/url": "file:../url", "change-case": "^4.1.2", "form-data": "^4.0.0", - "node-fetch": "^2.6.0" + "node-fetch": "2.7.0" }, "engines": { "node": ">=18.12.0", @@ -54919,7 +54919,7 @@ "gettext-parser": "^1.3.1", "jed": "^1.1.1", "jsdom-jscore-rn": "0.1.8", - "node-fetch": "^2.6.0", + "node-fetch": "2.7.0", "react-native": "0.73.3", "react-native-fast-image": "8.5.11", "react-native-gesture-handler": "2.14.1", diff --git a/package.json b/package.json index 50a0b3720cdc32..e0806af385ae6d 100644 --- a/package.json +++ b/package.json @@ -224,7 +224,7 @@ "mock-match-media": "0.4.2", "moment-timezone-data-webpack-plugin": "1.5.1", "nock": "12.0.3", - "node-fetch": "2.6.7", + "node-fetch": "2.7.0", "node-watch": "0.7.0", "npm-run-all": "4.1.5", "patch-package": "8.0.0", diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index a91938f54dd52c..ba0df0cf7532f5 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -36,7 +36,7 @@ "@wordpress/url": "file:../url", "change-case": "^4.1.2", "form-data": "^4.0.0", - "node-fetch": "^2.6.0" + "node-fetch": "2.7.0" }, "peerDependencies": { "jest": ">=29", diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json index 976ef742586c3a..0d2dd66aa2f2fc 100644 --- a/packages/react-native-editor/package.json +++ b/packages/react-native-editor/package.json @@ -55,7 +55,7 @@ "gettext-parser": "^1.3.1", "jed": "^1.1.1", "jsdom-jscore-rn": "0.1.8", - "node-fetch": "^2.6.0", + "node-fetch": "2.7.0", "react-native": "0.73.3", "react-native-fast-image": "8.5.11", "react-native-gesture-handler": "2.14.1", From a24a346fd739c2b779befffcb9de04aa3073c045 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:43:16 +0200 Subject: [PATCH 1125/1908] Block Bindings: Accept client ID as parameter for `useBlockBindingsUtils` (#65818) * Pass `clientId` to `useBlockBindingsUtils` * Add unit tests for `useBlockBindingsUtils` * Use `resetBlocks` instead of `insertBlocks` in unit test Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/block-editor/README.md | 4 + .../block-editor/src/utils/block-bindings.js | 15 +- .../utils/test/use-block-bindings-utils.js | 174 ++++++++++++++++++ 3 files changed, 187 insertions(+), 6 deletions(-) create mode 100644 packages/block-editor/src/utils/test/use-block-bindings-utils.js diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index a6f3b8980cfd7a..36f3dc0ba73fa1 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -877,6 +877,10 @@ updateBlockBindings( { url: undefined } ); removeAllBlockBindings(); ``` +_Parameters_ + +- _clientId_ `?string`: Optional block client ID. If not set, it will use the current block client ID from the context. + _Returns_ - `?WPBlockBindingsUtils`: Object containing the block bindings utils. diff --git a/packages/block-editor/src/utils/block-bindings.js b/packages/block-editor/src/utils/block-bindings.js index 2deeb959371742..dcf80d985473b2 100644 --- a/packages/block-editor/src/utils/block-bindings.js +++ b/packages/block-editor/src/utils/block-bindings.js @@ -32,6 +32,8 @@ function isObjectEmpty( object ) { * * @since 6.7.0 Introduced in WordPress core. * + * @param {?string} clientId Optional block client ID. If not set, it will use the current block client ID from the context. + * * @return {?WPBlockBindingsUtils} Object containing the block bindings utils. * * @example @@ -62,8 +64,9 @@ function isObjectEmpty( object ) { * removeAllBlockBindings(); * ``` */ -export function useBlockBindingsUtils() { - const { clientId } = useBlockEditContext(); +export function useBlockBindingsUtils( clientId ) { + const { clientId: contextClientId } = useBlockEditContext(); + const blockClientId = clientId || contextClientId; const { updateBlockAttributes } = useDispatch( blockEditorStore ); const { getBlockAttributes } = useRegistry().select( blockEditorStore ); @@ -98,7 +101,7 @@ export function useBlockBindingsUtils() { */ const updateBlockBindings = ( bindings ) => { const { metadata: { bindings: currentBindings, ...metadata } = {} } = - getBlockAttributes( clientId ); + getBlockAttributes( blockClientId ); const newBindings = { ...currentBindings }; Object.entries( bindings ).forEach( ( [ attribute, binding ] ) => { @@ -118,7 +121,7 @@ export function useBlockBindingsUtils() { delete newMetadata.bindings; } - updateBlockAttributes( clientId, { + updateBlockAttributes( blockClientId, { metadata: isObjectEmpty( newMetadata ) ? undefined : newMetadata, } ); }; @@ -136,8 +139,8 @@ export function useBlockBindingsUtils() { */ const removeAllBlockBindings = () => { const { metadata: { bindings, ...metadata } = {} } = - getBlockAttributes( clientId ); - updateBlockAttributes( clientId, { + getBlockAttributes( blockClientId ); + updateBlockAttributes( blockClientId, { metadata: isObjectEmpty( metadata ) ? undefined : metadata, } ); }; diff --git a/packages/block-editor/src/utils/test/use-block-bindings-utils.js b/packages/block-editor/src/utils/test/use-block-bindings-utils.js new file mode 100644 index 00000000000000..e5e26bd24c20d1 --- /dev/null +++ b/packages/block-editor/src/utils/test/use-block-bindings-utils.js @@ -0,0 +1,174 @@ +/** + * External dependencies + */ +import { renderHook } from '@testing-library/react'; + +/** + * WordPress dependencies + */ +import { store as blockEditorStore } from '@wordpress/block-editor'; +import { dispatch, select } from '@wordpress/data'; +import { + createBlock, + getBlockTypes, + unregisterBlockType, +} from '@wordpress/blocks'; +import { registerCoreBlocks } from '@wordpress/block-library'; + +/** + * Internal dependencies + */ +import { useBlockBindingsUtils } from '../'; + +describe( 'useBlockBindingsUtils', () => { + beforeAll( () => { + // Register all core blocks + registerCoreBlocks(); + } ); + + let clientId; + beforeEach( async () => { + const block = createBlock( 'core/paragraph', { + metadata: { + name: 'Block name', + bindings: { + prop1: { + source: 'core/post-meta', + args: { + key: 'initial_key', + }, + }, + prop2: { + source: 'core/post-meta', + args: { + key: 'initial_key', + }, + }, + }, + }, + } ); + await dispatch( blockEditorStore ).resetBlocks( [ block ] ); + clientId = block.clientId; + } ); + + afterAll( () => { + // Remove blocks after all tests. + dispatch( blockEditorStore ).resetBlocks( [] ); + + // Clean up registered blocks + getBlockTypes().forEach( ( block ) => { + unregisterBlockType( block.name ); + } ); + } ); + + it( 'should be possible to update just one connection', async () => { + renderHook( () => { + const { updateBlockBindings } = useBlockBindingsUtils( clientId ); + updateBlockBindings( { + prop1: { + source: 'core/post-meta', + args: { + key: 'new_key', + }, + }, + } ); + } ); + const { metadata } = + await select( blockEditorStore ).getBlockAttributes( clientId ); + expect( metadata ).toMatchObject( { + // Other metadata properties shouldn't change. + name: 'Block name', + bindings: { + prop1: { + source: 'core/post-meta', + args: { + key: 'new_key', + }, + }, + prop2: { + source: 'core/post-meta', + args: { + key: 'initial_key', + }, + }, + }, + } ); + } ); + + it( 'should be possible to update multiple connections at once', async () => { + renderHook( () => { + const { updateBlockBindings } = useBlockBindingsUtils( clientId ); + updateBlockBindings( { + prop1: { + source: 'core/post-meta', + args: { + key: 'new_key', + }, + }, + prop2: { + source: 'core/post-meta', + args: { + key: 'new_key', + }, + }, + } ); + } ); + const { metadata } = + await select( blockEditorStore ).getBlockAttributes( clientId ); + expect( metadata ).toMatchObject( { + // Other metadata properties shouldn't change. + name: 'Block name', + bindings: { + prop1: { + source: 'core/post-meta', + args: { + key: 'new_key', + }, + }, + prop2: { + source: 'core/post-meta', + args: { + key: 'new_key', + }, + }, + }, + } ); + } ); + + it( 'should be possible to remove connections', async () => { + renderHook( () => { + const { updateBlockBindings } = useBlockBindingsUtils( clientId ); + updateBlockBindings( { + prop2: undefined, + } ); + } ); + const { metadata } = + await select( blockEditorStore ).getBlockAttributes( clientId ); + expect( metadata ).toMatchObject( { + // Other metadata properties shouldn't change. + name: 'Block name', + bindings: { + prop1: { + source: 'core/post-meta', + args: { + key: 'initial_key', + }, + }, + }, + } ); + } ); + + it( 'should be possible to remove all connections', async () => { + renderHook( () => { + const { removeAllBlockBindings } = + useBlockBindingsUtils( clientId ); + removeAllBlockBindings(); + } ); + const { metadata } = + await select( blockEditorStore ).getBlockAttributes( clientId ); + expect( metadata ).toMatchObject( { + // Other metadata properties shouldn't change. + name: 'Block name', + } ); + } ); +} ); From b3aaefe8edb31474f0680c9f79ea218a4137aae2 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Wed, 9 Oct 2024 17:24:28 +0200 Subject: [PATCH 1126/1908] Update and align babel dependencies version (#65949) * Update @babel/* dependencies to 7.25.7 * Swap old proposal-* plugin to transform-* plugins * Update non-official, babel-* dependencies * Update package-lock.json * Remove `@babel/plugin-transform-async-generator-functions` and `@babel/plugin-transform-export-namespace-from` as they are included with other dependencies * Update platform docs package-lock.json * CHANGELOG -- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- package-lock.json | 2380 +++++++++++++---- package.json | 11 +- packages/README.md | 2 +- packages/a11y/package.json | 2 +- packages/annotations/package.json | 2 +- packages/api-fetch/package.json | 2 +- packages/autop/package.json | 2 +- .../package.json | 2 +- packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/CHANGELOG.md | 9 + packages/babel-preset-default/README.md | 2 +- packages/babel-preset-default/package.json | 12 +- packages/blob/package.json | 2 +- packages/block-directory/package.json | 2 +- packages/block-editor/package.json | 2 +- packages/block-library/package.json | 2 +- .../package.json | 2 +- packages/blocks/package.json | 2 +- packages/commands/package.json | 2 +- packages/components/package.json | 2 +- packages/compose/package.json | 2 +- packages/core-commands/package.json | 2 +- packages/core-data/package.json | 2 +- packages/customize-widgets/package.json | 2 +- packages/data-controls/package.json | 2 +- packages/data/package.json | 2 +- packages/dataviews/package.json | 2 +- packages/date/package.json | 2 +- packages/deprecated/package.json | 2 +- packages/docgen/package.json | 2 +- packages/dom-ready/package.json | 2 +- packages/dom/package.json | 2 +- packages/e2e-test-utils/package.json | 2 +- packages/edit-post/package.json | 2 +- packages/edit-site/package.json | 2 +- packages/edit-widgets/package.json | 2 +- packages/editor/package.json | 2 +- packages/element/package.json | 2 +- packages/escape-html/package.json | 2 +- packages/eslint-plugin/package.json | 2 +- packages/fields/package.json | 2 +- packages/format-library/package.json | 2 +- packages/hooks/package.json | 2 +- packages/html-entities/package.json | 2 +- packages/i18n/package.json | 2 +- packages/icons/package.json | 2 +- packages/interface/package.json | 2 +- packages/is-shallow-equal/package.json | 2 +- packages/jest-console/package.json | 2 +- packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/package.json | 2 +- packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/package.json | 2 +- packages/notices/package.json | 2 +- packages/nux/package.json | 2 +- packages/patterns/package.json | 2 +- packages/plugins/package.json | 2 +- packages/preferences-persistence/package.json | 2 +- packages/preferences/package.json | 2 +- packages/primitives/package.json | 2 +- packages/priority-queue/package.json | 2 +- packages/private-apis/package.json | 2 +- .../package.json | 2 +- packages/react-i18n/package.json | 2 +- packages/react-native-editor/babel.config.js | 2 +- packages/react-native-editor/package.json | 2 +- packages/redux-routine/package.json | 2 +- packages/reusable-blocks/package.json | 2 +- packages/rich-text/package.json | 2 +- packages/router/package.json | 2 +- packages/scripts/package.json | 6 +- packages/server-side-render/package.json | 2 +- packages/shortcode/package.json | 2 +- packages/style-engine/package.json | 2 +- packages/sync/package.json | 2 +- packages/token-list/package.json | 2 +- packages/undo-manager/package.json | 2 +- packages/url/package.json | 2 +- packages/viewport/package.json | 2 +- packages/widgets/package.json | 2 +- packages/wordcount/package.json | 2 +- platform-docs/package-lock.json | 9 +- test/native/babel.config.js | 4 +- 85 files changed, 1954 insertions(+), 633 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4f55f02a79706d..c240bfd1784377 100644 --- a/package-lock.json +++ b/package-lock.json @@ -88,11 +88,10 @@ "@actions/github": "5.0.0", "@apidevtools/json-schema-ref-parser": "11.6.4", "@ariakit/test": "^0.4.2", - "@babel/core": "7.24.3", - "@babel/plugin-proposal-export-namespace-from": "7.18.9", - "@babel/plugin-syntax-jsx": "7.24.1", - "@babel/runtime-corejs3": "7.24.1", - "@babel/traverse": "7.24.1", + "@babel/core": "7.25.7", + "@babel/plugin-syntax-jsx": "7.25.7", + "@babel/runtime-corejs3": "7.25.7", + "@babel/traverse": "7.25.7", "@emotion/babel-plugin": "11.11.0", "@emotion/jest": "11.7.1", "@emotion/native": "11.0.0", @@ -163,7 +162,7 @@ "ajv": "8.7.1", "appium": "2.0.0", "babel-jest": "29.7.0", - "babel-loader": "9.1.3", + "babel-loader": "9.2.1", "babel-plugin-inline-json-import": "0.3.2", "babel-plugin-react-native-classname-to-style": "1.2.2", "babel-plugin-react-native-platform-specific-extensions": "1.1.1", @@ -1590,11 +1589,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", - "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.2", + "@babel/highlight": "^7.25.7", "picocolors": "^1.0.0" }, "engines": { @@ -1602,28 +1602,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.7.tgz", + "integrity": "sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", - "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.7.tgz", + "integrity": "sha512-yJ474Zv3cwiSOO9nXJuqzvwEeM+chDuQ8GJirw+pZ91sCGCyOZ3dJkVE09fTV0VEVzXyLWhh3G/AolYTPX7Mow==", + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.1", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.1", - "@babel/parser": "^7.24.1", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helpers": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -1651,66 +1653,28 @@ "semver": "bin/semver.js" } }, - "node_modules/@babel/eslint-parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.16.0.tgz", - "integrity": "sha512-c+AsYOHjI+FgCa+ifLd8sDXp4U4mjkfFgL9NdQWhuA731kAUJs0WdJIXET4A14EJAR9Jv9FFF/MzPWJfV9Oirw==", - "dev": true, - "dependencies": { - "eslint-scope": "^5.1.1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || >=14.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.11.0", - "eslint": "^7.5.0 || ^8.0.0" - } - }, - "node_modules/@babel/eslint-parser/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@babel/eslint-parser/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/generator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", - "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", + "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.0", + "@babel/types": "^7.25.7", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", + "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1729,13 +1693,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", + "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -1795,12 +1760,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", - "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.7.tgz", + "integrity": "sha512-byHhumTj/X47wJ6C6eLpK7wW/WBEcnUeb7D0FNc/jFQnQVw7DOso3Zz5u9x/zLrFVkHa89ZGDbkAa1D54NdrCQ==", + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "regexpu-core": "^5.3.1", + "@babel/helper-annotate-as-pure": "^7.25.7", + "regexpu-core": "^6.1.1", "semver": "^6.3.1" }, "engines": { @@ -1868,6 +1834,7 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, "dependencies": { "@babel/types": "^7.22.5" }, @@ -1887,26 +1854,28 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", + "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", + "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1927,21 +1896,23 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", - "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", + "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", - "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.7.tgz", + "integrity": "sha512-kRGE89hLnPfcz6fTrlNU+uhgcwv0mBE4Gv3P9Ke9kLVJYpi4AMVVEElXvB5CabrPZW4nCM8P8UyyjrzCM0O2sw==", + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-wrap-function": "^7.22.20" + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-wrap-function": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1967,11 +1938,13 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", + "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2000,61 +1973,66 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", + "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", - "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.7.tgz", + "integrity": "sha512-MA0roW3JF2bD1ptAaJnvcabsVlNQShUaThyJbCDD4bCp8NEgiFvpoqRI2YS22hHlc2thjO/fTg2ShLMC3jygAg==", + "license": "MIT", "dependencies": { - "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.15", - "@babel/types": "^7.22.19" + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", - "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", + "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", + "license": "MIT", "dependencies": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0" + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", - "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-validator-identifier": "^7.25.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -2067,6 +2045,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -2078,6 +2057,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -2088,9 +2068,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", - "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", + "integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.7" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -2098,6 +2082,39 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.7.tgz", + "integrity": "sha512-UV9Lg53zyebzD1DwQoT9mzkEKa922LNUp5YkTJ6Uta0RbyXaQNUgcvSt7qIu1PpPzVb6rd10OVNTzkyBGeVmxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.7.tgz", + "integrity": "sha512-GDDWeVLNxRIkQTnJn2pDOM1pkCgYdSqPeT1a9vh9yIqu2uzzgw1zcqEb+IJOhy+dTBMlNdThrDIksr2o09qrrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", @@ -2195,22 +2212,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", @@ -2295,6 +2296,19 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", @@ -2451,11 +2465,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", - "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.7.tgz", + "integrity": "sha512-ruZOnKO+ajVL/MVx+PwNBPOkrnXTXoWMtte1MBpegfCArhqOe3Bj52avVj1huLLxNKYKXYaSxZ2F+woK1ekXfw==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2605,15 +2620,16 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz", - "integrity": "sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.7.tgz", + "integrity": "sha512-4B6OhTrwYKHYYgcwErvZjbmH9X5TxQBsaBHdzEIB4l71gR5jh/tuHGlb9in47udL2+wVUcOz5XXhhfhVJwEpEg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.20", - "@babel/plugin-syntax-async-generators": "^7.8.4" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-remap-async-to-generator": "^7.25.7", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2789,6 +2805,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.7.tgz", + "integrity": "sha512-HvS6JF66xSS5rNKXLqkk7L9c/jZ/cdIVIcoPVrnl8IsVpLggTjXs8OWekbLHs/VtYDDh5WXnQyeE3PPUGm22MA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-transform-dynamic-import": { "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", @@ -2822,12 +2855,13 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", - "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.7.tgz", + "integrity": "sha512-h3MDAP5l34NQkkNulsTNyjdaR+OiB0Im67VU//sFupouP8Q6m9Spy7l66DcaAQxtmCqGdanPByLsnwFttxKISQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { @@ -3642,18 +3676,6 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", @@ -3832,11 +3854,6 @@ "semver": "bin/semver" } }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" - }, "node_modules/@babel/runtime": { "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", @@ -3850,10 +3867,11 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.24.1.tgz", - "integrity": "sha512-T9ko/35G+Bkl+win48GduaPlhSlOjjE5s1TeiEcD+QpxlLQnoEfb/nO/T+TQqkm+ipFwORn+rB8w14iJ/uD0bg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.25.7.tgz", + "integrity": "sha512-gMmIEhg35sXk9Te5qbGp3W9YKrvLt3HV658/d3odWrHSqT0JeG5OzsJWFHRLiOohRyjRsJc/x03DhJm3i8VJxg==", "dev": true, + "license": "MIT", "dependencies": { "core-js-pure": "^3.30.2", "regenerator-runtime": "^0.14.0" @@ -3874,31 +3892,30 @@ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", + "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" + "@babel/code-frame": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", - "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", + "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.1", - "@babel/generator": "^7.24.1", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -3915,12 +3932,13 @@ } }, "node_modules/@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", + "integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -6095,6 +6113,30 @@ "once": "^1.3.1" } }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.2.tgz", @@ -19056,10 +19098,11 @@ } }, "node_modules/babel-loader": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", - "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", + "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", "dev": true, + "license": "MIT", "dependencies": { "find-cache-dir": "^4.0.0", "schema-utils": "^4.0.0" @@ -32321,14 +32364,15 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/jsftp": { @@ -44239,12 +44283,14 @@ "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "license": "MIT" }, "node_modules/regenerate-unicode-properties": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", - "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "license": "MIT", "dependencies": { "regenerate": "^1.4.2" }, @@ -44309,14 +44355,15 @@ } }, "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", + "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", + "license": "MIT", "dependencies": { - "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.11.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" }, @@ -44324,25 +44371,24 @@ "node": ">=4" } }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "license": "MIT" + }, "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.1.tgz", + "integrity": "sha512-1DHODs4B8p/mQHU9kr+jv8+wIC9mtG4eBHxWxIq5mhjE3D5oORhCc6deRKzTjs9DcfRFmj9BHSDguZklqCGFWQ==", + "license": "BSD-2-Clause", "dependencies": { - "jsesc": "~0.5.0" + "jsesc": "~3.0.2" }, "bin": { "regjsparser": "bin/parser" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "bin": { - "jsesc": "bin/jsesc" - } - }, "node_modules/relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -49399,9 +49445,10 @@ } }, "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "license": "MIT", "engines": { "node": ">=4" } @@ -49410,6 +49457,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "license": "MIT", "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -49419,9 +49467,10 @@ } }, "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "license": "MIT", "engines": { "node": ">=4" } @@ -49430,6 +49479,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "license": "MIT", "engines": { "node": ">=4" } @@ -52596,7 +52646,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/dom-ready": "file:../dom-ready", "@wordpress/i18n": "file:../i18n" }, @@ -52610,7 +52660,7 @@ "version": "3.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/data": "file:../data", "@wordpress/hooks": "file:../hooks", "@wordpress/i18n": "file:../i18n", @@ -52638,7 +52688,7 @@ "version": "7.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/i18n": "file:../i18n", "@wordpress/url": "file:../url" }, @@ -52652,7 +52702,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "engines": { "node": ">=18.12.0", @@ -52669,7 +52719,7 @@ "npm": ">=8.19.2" }, "peerDependencies": { - "@babel/core": "^7.12.9" + "@babel/core": "^7.25.7" } }, "packages/babel-plugin-makepot": { @@ -52687,7 +52737,7 @@ "npm": ">=8.19.2" }, "peerDependencies": { - "@babel/core": "^7.12.9" + "@babel/core": "^7.25.7" } }, "packages/babel-preset-default": { @@ -52696,12 +52746,12 @@ "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@babel/core": "^7.16.0", - "@babel/plugin-transform-react-jsx": "^7.16.0", - "@babel/plugin-transform-runtime": "^7.16.0", - "@babel/preset-env": "^7.16.0", - "@babel/preset-typescript": "^7.16.0", - "@babel/runtime": "^7.16.0", + "@babel/core": "7.25.7", + "@babel/plugin-transform-react-jsx": "7.25.7", + "@babel/plugin-transform-runtime": "7.25.7", + "@babel/preset-env": "7.25.7", + "@babel/preset-typescript": "7.25.7", + "@babel/runtime": "7.25.7", "@wordpress/browserslist-config": "file:../browserslist-config", "@wordpress/warning": "file:../warning", "browserslist": "^4.21.10", @@ -52713,263 +52763,1496 @@ "npm": ">=8.19.2" } }, - "packages/base-styles": { - "name": "@wordpress/base-styles", - "version": "5.9.0", + "packages/babel-preset-default/node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.7.tgz", + "integrity": "sha512-12xfNeKNH7jubQNm7PAkzlLwEmCs1tfuX3UjIw6vP6QXi+leKh6+LyC/+Ed4EIQermwd58wsyh070yjDHFlNGg==", "dev": true, - "license": "GPL-2.0-or-later", - "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" - } - }, - "packages/blob": { - "name": "@wordpress/blob", - "version": "4.9.0", - "license": "GPL-2.0-or-later", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" + "node": ">=6.9.0" } }, - "packages/block-directory": { - "name": "@wordpress/block-directory", - "version": "5.9.0", - "license": "GPL-2.0-or-later", + "packages/babel-preset-default/node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.7.tgz", + "integrity": "sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.16.0", - "@wordpress/a11y": "file:../a11y", - "@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/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/plugins": "file:../plugins", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", - "change-case": "^4.1.2", - "clsx": "^2.1.1" + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/traverse": "^7.25.7", + "semver": "^6.3.1" }, "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" + "node": ">=6.9.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "@babel/core": "^7.0.0" } }, - "packages/block-editor": { - "name": "@wordpress/block-editor", - "version": "14.4.0", - "license": "GPL-2.0-or-later", + "packages/babel-preset-default/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.16.0", - "@emotion/react": "^11.7.1", - "@emotion/styled": "^11.6.0", - "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/style-engine": "file:../style-engine", - "@wordpress/token-list": "file:../token-list", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", - "@wordpress/wordcount": "file:../wordcount", - "change-case": "^4.1.2", - "clsx": "^2.1.1", - "colord": "^2.7.0", - "deepmerge": "^4.3.0", - "diff": "^4.0.2", - "fast-deep-equal": "^3.1.3", - "memize": "^2.1.0", - "parsel-js": "^1.1.2", - "postcss": "^8.4.21", - "postcss-prefix-selector": "^1.16.0", - "postcss-urlrebase": "^1.4.0", - "react-autosize-textarea": "^7.1.0", - "react-easy-crop": "^5.0.6", - "remove-accents": "^0.5.0" - }, - "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "packages/block-editor/node_modules/postcss-urlrebase": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.4.0.tgz", - "integrity": "sha512-rRaxMmWvXrn8Rk1PqsxmaJwldRHsr0WbbASKKCZYxXwotHkM/5X/6IrwaEe8pdzpbNGCEY86yhYMN0MhgOkADA==", + "packages/babel-preset-default/node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.7.tgz", + "integrity": "sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==", + "dev": true, "license": "MIT", "dependencies": { - "postcss-value-parser": "^4.2.0" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, - "peerDependencies": { - "postcss": "^8.3.0" + "engines": { + "node": ">=6.9.0" } }, - "packages/block-editor/node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "license": "MIT" - }, - "packages/block-editor/node_modules/react-easy-crop": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/react-easy-crop/-/react-easy-crop-5.0.6.tgz", - "integrity": "sha512-LV8te8NGC72k3l8uAqPAw73D2i9AbRlZqyo1Xz8VetwiMfkSKYgyqE3IFEwf5h+1g7AS1nMxBKk6ZPdhvLw6MQ==", + "packages/babel-preset-default/node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.7.tgz", + "integrity": "sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==", + "dev": true, + "license": "MIT", "dependencies": { - "normalize-wheel": "^1.0.1", - "tslib": "2.0.1" + "@babel/types": "^7.25.7" }, - "peerDependencies": { - "react": ">=16.4.0", - "react-dom": ">=16.4.0" + "engines": { + "node": ">=6.9.0" } }, - "packages/block-editor/node_modules/tslib": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", - "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==" - }, - "packages/block-library": { - "name": "@wordpress/block-library", - "version": "9.9.0", - "license": "GPL-2.0-or-later", + "packages/babel-preset-default/node_modules/@babel/helper-replace-supers": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.7.tgz", + "integrity": "sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.16.0", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/autop": "file:../autop", - "@wordpress/blob": "file:../blob", - "@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/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interactivity": "file:../interactivity", - "@wordpress/interactivity-router": "file:../interactivity-router", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/server-side-render": "file:../server-side-render", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/wordcount": "file:../wordcount", - "change-case": "^4.1.2", - "clsx": "^2.1.1", - "colord": "^2.7.0", - "escape-html": "^1.0.3", - "fast-average-color": "^9.1.1", - "fast-deep-equal": "^3.1.3", - "memize": "^2.1.0", - "remove-accents": "^0.5.0", - "uuid": "^9.0.1" + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" + "node": ">=6.9.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "@babel/core": "^7.0.0" } }, - "packages/block-library/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "packages/babel-preset-default/node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.7.tgz", + "integrity": "sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "packages/block-serialization-default-parser": { - "name": "@wordpress/block-serialization-default-parser", - "version": "5.9.0", - "license": "GPL-2.0-or-later", + "packages/babel-preset-default/node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.7.tgz", + "integrity": "sha512-wxyWg2RYaSUYgmd9MR0FyRGyeOMQE/Uzr1wzd/g5cf5bwi9A4v6HFdDm7y1MgDtod/fLOSTZY6jDgV0xU9d5bA==", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "packages/block-serialization-spec-parser": { - "name": "@wordpress/block-serialization-spec-parser", - "version": "5.9.0", - "license": "GPL-2.0-or-later", + "packages/babel-preset-default/node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.7.tgz", + "integrity": "sha512-Xwg6tZpLxc4iQjorYsyGMyfJE7nP5MV8t/Ka58BgiA7Jw0fRqQNcANlLfdJ/yvBt9z9LD2We+BEkT7vLqZRWng==", + "dev": true, + "license": "MIT", "dependencies": { - "pegjs": "^0.10.0", - "phpegjs": "^1.0.0-beta7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-transform-optional-chaining": "^7.25.7" }, "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" } }, - "packages/blocks": { - "name": "@wordpress/blocks", - "version": "13.9.0", - "license": "GPL-2.0-or-later", + "packages/babel-preset-default/node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.7.tgz", + "integrity": "sha512-UVATLMidXrnH+GMUIuxq55nejlj02HP7F5ETyBONzP6G87fPBogG4CH6kxrSrdIuAjdwNO9VzyaYsrZPscWUrw==", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.16.0", - "@wordpress/autop": "file:../autop", - "@wordpress/blob": "file:../blob", - "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.7.tgz", + "integrity": "sha512-ZvZQRmME0zfJnDQnVBKYzHxXT7lYBB3Revz1GuS7oLXWMgqUPX4G+DDbT30ICClht9WKV34QVrZhSw6WdklwZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", + "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.7.tgz", + "integrity": "sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.7.tgz", + "integrity": "sha512-EJN2mKxDwfOUCPxMO6MUI58RN3ganiRAG/MS/S3HfB6QFNjroAMelQo/gybyYq97WerCBAZoyrAoW8Tzdq2jWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.7.tgz", + "integrity": "sha512-ZUCjAavsh5CESCmi/xCpX1qcCaAglzs/7tmuvoFnJgA1dM7gQplsguljoTg+Ru8WENpX89cQyAtWoaE0I3X3Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-remap-async-to-generator": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.7.tgz", + "integrity": "sha512-xHttvIM9fvqW+0a3tZlYcZYSBpSWzGBFIt/sYG3tcdSzBB8ZeVgz2gBP7Df+sM0N1850jrviYSSeUuc+135dmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.7.tgz", + "integrity": "sha512-ZEPJSkVZaeTFG/m2PARwLZQ+OG0vFIhPlKHK/JdIMy8DbRJ/htz6LRrTFtdzxi9EHmcwbNPAKDnadpNSIW+Aow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.7.tgz", + "integrity": "sha512-mhyfEW4gufjIqYFo9krXHJ3ElbFLIze5IDp+wQTxoPd+mwFb1NxatNAwmv8Q8Iuxv7Zc+q8EkiMQwc9IhyGf4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.7.tgz", + "integrity": "sha512-rvUUtoVlkDWtDWxGAiiQj0aNktTPn3eFynBcMC2IhsXweehwgdI9ODe+XjWw515kEmv22sSOTp/rxIRuTiB7zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-classes": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.7.tgz", + "integrity": "sha512-9j9rnl+YCQY0IGoeipXvnk3niWicIB6kCsWRGLwX241qSXpbA4MKxtp/EdvFxsc4zI5vqfLxzOd0twIJ7I99zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/traverse": "^7.25.7", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.7.tgz", + "integrity": "sha512-QIv+imtM+EtNxg/XBKL3hiWjgdLjMOmZ+XzQwSgmBfKbfxUjBzGgVPklUuE55eq5/uVoh8gg3dqlrwR/jw3ZeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/template": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-destructuring": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.7.tgz", + "integrity": "sha512-xKcfLTlJYUczdaM1+epcdh1UGewJqr9zATgrNHcLBcV2QmfvPPEixo/sK/syql9cEmbr7ulu5HMFG5vbbt/sEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.7.tgz", + "integrity": "sha512-kXzXMMRzAtJdDEgQBLF4oaiT6ZCU3oWHgpARnTKDAqPkDJ+bs3NrZb310YYevR5QlRo3Kn7dzzIdHbZm1VzJdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.7.tgz", + "integrity": "sha512-by+v2CjoL3aMnWDOyCIg+yxU9KXSRa9tN6MbqggH5xvymmr9p4AMjYkNlQy4brMceBnUyHZ9G8RnpvT8wP7Cfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.7.tgz", + "integrity": "sha512-UvcLuual4h7/GfylKm2IAA3aph9rwvAM2XBA0uPKU3lca+Maai4jBjjEVUS568ld6kJcgbouuumCBhMd/Yz17w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.7.tgz", + "integrity": "sha512-yjqtpstPfZ0h/y40fAXRv2snciYr0OAoMXY/0ClC7tm4C/nG5NJKmIItlaYlLbIVAWNfrYuy9dq1bE0SbX0PEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-for-of": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.7.tgz", + "integrity": "sha512-n/TaiBGJxYFWvpJDfsxSj9lEEE44BFM1EPGz4KEiTipTgkoFVVcCmzAL3qA7fdQU96dpo4gGf5HBx/KnDvqiHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.7.tgz", + "integrity": "sha512-5MCTNcjCMxQ63Tdu9rxyN6cAWurqfrDZ76qvVPrGYdBxIj+EawuuxTu/+dgJlhK5eRz3v1gLwp6XwS8XaX2NiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-json-strings": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.7.tgz", + "integrity": "sha512-Ot43PrL9TEAiCe8C/2erAjXMeVSnE/BLEx6eyrKLNFCCw5jvhTHKyHxdI1pA0kz5njZRYAnMO2KObGqOCRDYSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-literals": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.7.tgz", + "integrity": "sha512-fwzkLrSu2fESR/cm4t6vqd7ebNIopz2QHGtjoU+dswQo/P6lwAG04Q98lliE3jkz/XqnbGFLnUcE0q0CVUf92w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.7.tgz", + "integrity": "sha512-iImzbA55BjiovLyG2bggWS+V+OLkaBorNvc/yJoeeDQGztknRnDdYfp2d/UPmunZYEnZi6Lg8QcTmNMHOB0lGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.7.tgz", + "integrity": "sha512-Std3kXwpXfRV0QtQy5JJcRpkqP8/wG4XL7hSKZmGlxPlDqmpXtEPRmhF7ztnlTCtUN3eXRUJp+sBEZjaIBVYaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.7.tgz", + "integrity": "sha512-CgselSGCGzjQvKzghCvDTxKHP3iooenLpJDO842ehn5D2G5fJB222ptnDwQho0WjEvg7zyoxb9P+wiYxiJX5yA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.7.tgz", + "integrity": "sha512-L9Gcahi0kKFYXvweO6n0wc3ZG1ChpSFdgG+eV1WYZ3/dGbJK7vvk91FgGgak8YwRgrCuihF8tE/Xg07EkL5COg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.7.tgz", + "integrity": "sha512-t9jZIvBmOXJsiuyOwhrIGs8dVcD6jDyg2icw1VL4A/g+FnWyJKwUfSSU2nwJuMV2Zqui856El9u+ElB+j9fV1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.7.tgz", + "integrity": "sha512-p88Jg6QqsaPh+EB7I9GJrIqi1Zt4ZBHUQtjw3z1bzEXcLh6GfPqzZJ6G+G1HBGKUNukT58MnKG7EN7zXQBCODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.7.tgz", + "integrity": "sha512-BtAT9LzCISKG3Dsdw5uso4oV1+v2NlVXIIomKJgQybotJY3OwCwJmkongjHgwGKoZXd0qG5UZ12JUlDQ07W6Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-new-target": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.7.tgz", + "integrity": "sha512-CfCS2jDsbcZaVYxRFo2qtavW8SpdzmBXC2LOI4oO0rP+JSRDxxF3inF4GcPsLgfb5FjkhXG5/yR/lxuRs2pySA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.7.tgz", + "integrity": "sha512-FbuJ63/4LEL32mIxrxwYaqjJxpbzxPVQj5a+Ebrc8JICV6YX8nE53jY+K0RZT3um56GoNWgkS2BQ/uLGTjtwfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.7.tgz", + "integrity": "sha512-8CbutzSSh4hmD+jJHIA8vdTNk15kAzOnFLVVgBSMGr28rt85ouT01/rezMecks9pkU939wDInImwCKv4ahU4IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.7.tgz", + "integrity": "sha512-1JdVKPhD7Y5PvgfFy0Mv2brdrolzpzSoUq2pr6xsR+m+3viGGeHEokFKsCgOkbeFOQxfB1Vt2F0cPJLRpFI4Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-object-super": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.7.tgz", + "integrity": "sha512-pWT6UXCEW3u1t2tcAGtE15ornCBvopHj9Bps9D2DsH15APgNVOTwwczGckX+WkAvBmuoYKRCFa4DK+jM8vh5AA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.7.tgz", + "integrity": "sha512-m9obYBA39mDPN7lJzD5WkGGb0GO54PPLXsbcnj1Hyeu8mSRz7Gb4b1A6zxNX32ZuUySDK4G6it8SDFWD1nCnqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.7.tgz", + "integrity": "sha512-h39agClImgPWg4H8mYVAbD1qP9vClFbEjqoJmt87Zen8pjqK8FTPUwrOXAvqu5soytwxrLMd2fx2KSCp2CHcNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-parameters": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.7.tgz", + "integrity": "sha512-FYiTvku63me9+1Nz7TOx4YMtW3tWXzfANZtrzHhUZrz4d47EEtMQhzFoZWESfXuAMMT5mwzD4+y1N8ONAX6lMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz", + "integrity": "sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.7.tgz", + "integrity": "sha512-LzA5ESzBy7tqj00Yjey9yWfs3FKy4EmJyKOSWld144OxkTji81WWnUT8nkLUn+imN/zHL8ZQlOu/MTUAhHaX3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-property-literals": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.7.tgz", + "integrity": "sha512-lQEeetGKfFi0wHbt8ClQrUSUMfEeI3MMm74Z73T9/kuz990yYVtfofjf3NuA42Jy3auFOpbjDyCSiIkTs1VIYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.7.tgz", + "integrity": "sha512-vILAg5nwGlR9EXE8JIOX4NHXd49lrYbN8hnjffDtoULwpL9hUx/N55nqh2qd0q6FyNDfjl9V79ecKGvFbcSA0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-jsx": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-regenerator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.7.tgz", + "integrity": "sha512-mgDoQCRjrY3XK95UuV60tZlFCQGXEtMg8H+IsW72ldw1ih1jZhzYXbJvghmAEpg5UVhhnCeia1CkGttUvCkiMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.7.tgz", + "integrity": "sha512-3OfyfRRqiGeOvIWSagcwUTVk2hXBsr/ww7bLn6TRTuXnexA+Udov2icFOxFX9abaj4l96ooYkcNN1qi2Zvqwng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-runtime": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.7.tgz", + "integrity": "sha512-Y9p487tyTzB0yDYQOtWnC+9HGOuogtP3/wNpun1xJXEEvI6vip59BSBTsHnekZLqxmPcgsrAKt46HAAb//xGhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.7.tgz", + "integrity": "sha512-uBbxNwimHi5Bv3hUccmOFlUy3ATO6WagTApenHz9KzoIdn0XeACdB12ZJ4cjhuB2WSi80Ez2FWzJnarccriJeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-spread": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.7.tgz", + "integrity": "sha512-Mm6aeymI0PBh44xNIv/qvo8nmbkpZze1KvR8MkEqbIREDxoiWTi18Zr2jryfRMwDfVZF9foKh060fWgni44luw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.7.tgz", + "integrity": "sha512-ZFAeNkpGuLnAQ/NCsXJ6xik7Id+tHuS+NT+ue/2+rn/31zcdnupCdmunOizEaP0JsUmTFSTOPoQY7PkK2pttXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-template-literals": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.7.tgz", + "integrity": "sha512-SI274k0nUsFFmyQupiO7+wKATAmMFf8iFgq2O+vVFXZ0SV9lNfT1NGzBEhjquFmD8I9sqHLguH+gZVN3vww2AA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.7.tgz", + "integrity": "sha512-OmWmQtTHnO8RSUbL0NTdtpbZHeNTnm68Gj5pA4Y2blFNh+V4iZR68V1qL9cI37J21ZN7AaCnkfdHtLExQPf2uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-typescript": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.7.tgz", + "integrity": "sha512-VKlgy2vBzj8AmEzunocMun2fF06bsSWV+FvVXohtL6FGve/+L217qhHxRTVGHEDO/YR8IANcjzgJsd04J8ge5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-syntax-typescript": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.7.tgz", + "integrity": "sha512-BN87D7KpbdiABA+t3HbVqHzKWUDN3dymLaTnPFAMyc8lV+KN3+YzNhVRNdinaCPA4AUqx7ubXbQ9shRjYBl3SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.7.tgz", + "integrity": "sha512-IWfR89zcEPQGB/iB408uGtSPlQd3Jpq11Im86vUgcmSTcoWAiQMCTOa2K2yNNqFJEBVICKhayctee65Ka8OB0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.7.tgz", + "integrity": "sha512-8JKfg/hiuA3qXnlLx8qtv5HWRbgyFx2hMMtpDDuU2rTckpKkGu4ycK5yYHwuEa16/quXfoxHBIApEsNyMWnt0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.7.tgz", + "integrity": "sha512-YRW8o9vzImwmh4Q3Rffd09bH5/hvY0pxg+1H1i0f7APoUeg12G7+HhLj9ZFNIrYkgBXhIijPJ+IXypN0hLTIbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "packages/babel-preset-default/node_modules/@babel/preset-env": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.7.tgz", + "integrity": "sha512-Gibz4OUdyNqqLj+7OAvBZxOD7CklCtMA5/j0JgUEwOnaRULsPDXmic2iKxL2DX2vQduPR5wH2hjZas/Vr/Oc0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.25.7", + "@babel/plugin-syntax-import-attributes": "^7.25.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.25.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.7", + "@babel/plugin-transform-async-to-generator": "^7.25.7", + "@babel/plugin-transform-block-scoped-functions": "^7.25.7", + "@babel/plugin-transform-block-scoping": "^7.25.7", + "@babel/plugin-transform-class-properties": "^7.25.7", + "@babel/plugin-transform-class-static-block": "^7.25.7", + "@babel/plugin-transform-classes": "^7.25.7", + "@babel/plugin-transform-computed-properties": "^7.25.7", + "@babel/plugin-transform-destructuring": "^7.25.7", + "@babel/plugin-transform-dotall-regex": "^7.25.7", + "@babel/plugin-transform-duplicate-keys": "^7.25.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.7", + "@babel/plugin-transform-dynamic-import": "^7.25.7", + "@babel/plugin-transform-exponentiation-operator": "^7.25.7", + "@babel/plugin-transform-export-namespace-from": "^7.25.7", + "@babel/plugin-transform-for-of": "^7.25.7", + "@babel/plugin-transform-function-name": "^7.25.7", + "@babel/plugin-transform-json-strings": "^7.25.7", + "@babel/plugin-transform-literals": "^7.25.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.7", + "@babel/plugin-transform-member-expression-literals": "^7.25.7", + "@babel/plugin-transform-modules-amd": "^7.25.7", + "@babel/plugin-transform-modules-commonjs": "^7.25.7", + "@babel/plugin-transform-modules-systemjs": "^7.25.7", + "@babel/plugin-transform-modules-umd": "^7.25.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.7", + "@babel/plugin-transform-new-target": "^7.25.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.7", + "@babel/plugin-transform-numeric-separator": "^7.25.7", + "@babel/plugin-transform-object-rest-spread": "^7.25.7", + "@babel/plugin-transform-object-super": "^7.25.7", + "@babel/plugin-transform-optional-catch-binding": "^7.25.7", + "@babel/plugin-transform-optional-chaining": "^7.25.7", + "@babel/plugin-transform-parameters": "^7.25.7", + "@babel/plugin-transform-private-methods": "^7.25.7", + "@babel/plugin-transform-private-property-in-object": "^7.25.7", + "@babel/plugin-transform-property-literals": "^7.25.7", + "@babel/plugin-transform-regenerator": "^7.25.7", + "@babel/plugin-transform-reserved-words": "^7.25.7", + "@babel/plugin-transform-shorthand-properties": "^7.25.7", + "@babel/plugin-transform-spread": "^7.25.7", + "@babel/plugin-transform-sticky-regex": "^7.25.7", + "@babel/plugin-transform-template-literals": "^7.25.7", + "@babel/plugin-transform-typeof-symbol": "^7.25.7", + "@babel/plugin-transform-unicode-escapes": "^7.25.7", + "@babel/plugin-transform-unicode-property-regex": "^7.25.7", + "@babel/plugin-transform-unicode-regex": "^7.25.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.38.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/preset-typescript": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.25.7.tgz", + "integrity": "sha512-rkkpaXJZOFN45Fb+Gki0c+KMIglk4+zZXOoMJuyEK8y8Kkc8Jd3BDmP7qPsz0zQMJj+UD7EprF+AqAXcILnexw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "@babel/plugin-syntax-jsx": "^7.25.7", + "@babel/plugin-transform-modules-commonjs": "^7.25.7", + "@babel/plugin-transform-typescript": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "packages/babel-preset-default/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "packages/babel-preset-default/node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "packages/babel-preset-default/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "packages/babel-preset-default/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "packages/base-styles": { + "name": "@wordpress/base-styles", + "version": "5.9.0", + "dev": true, + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "packages/blob": { + "name": "@wordpress/blob", + "version": "4.9.0", + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "7.25.7" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "packages/block-directory": { + "name": "@wordpress/block-directory", + "version": "5.9.0", + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "7.25.7", + "@wordpress/a11y": "file:../a11y", + "@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/editor": "file:../editor", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/plugins": "file:../plugins", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url", + "change-case": "^4.1.2", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "packages/block-editor": { + "name": "@wordpress/block-editor", + "version": "14.4.0", + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "7.25.7", + "@emotion/react": "^11.7.1", + "@emotion/styled": "^11.6.0", + "@react-spring/web": "^9.4.5", + "@wordpress/a11y": "file:../a11y", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blob": "file:../blob", + "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", + "@wordpress/blocks": "file:../blocks", + "@wordpress/commands": "file:../commands", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/date": "file:../date", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/element": "file:../element", + "@wordpress/escape-html": "file:../escape-html", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/notices": "file:../notices", + "@wordpress/preferences": "file:../preferences", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/style-engine": "file:../style-engine", + "@wordpress/token-list": "file:../token-list", + "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", + "@wordpress/wordcount": "file:../wordcount", + "change-case": "^4.1.2", + "clsx": "^2.1.1", + "colord": "^2.7.0", + "deepmerge": "^4.3.0", + "diff": "^4.0.2", + "fast-deep-equal": "^3.1.3", + "memize": "^2.1.0", + "parsel-js": "^1.1.2", + "postcss": "^8.4.21", + "postcss-prefix-selector": "^1.16.0", + "postcss-urlrebase": "^1.4.0", + "react-autosize-textarea": "^7.1.0", + "react-easy-crop": "^5.0.6", + "remove-accents": "^0.5.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "packages/block-editor/node_modules/postcss-urlrebase": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.4.0.tgz", + "integrity": "sha512-rRaxMmWvXrn8Rk1PqsxmaJwldRHsr0WbbASKKCZYxXwotHkM/5X/6IrwaEe8pdzpbNGCEY86yhYMN0MhgOkADA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.3.0" + } + }, + "packages/block-editor/node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "packages/block-editor/node_modules/react-easy-crop": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/react-easy-crop/-/react-easy-crop-5.0.6.tgz", + "integrity": "sha512-LV8te8NGC72k3l8uAqPAw73D2i9AbRlZqyo1Xz8VetwiMfkSKYgyqE3IFEwf5h+1g7AS1nMxBKk6ZPdhvLw6MQ==", + "dependencies": { + "normalize-wheel": "^1.0.1", + "tslib": "2.0.1" + }, + "peerDependencies": { + "react": ">=16.4.0", + "react-dom": ">=16.4.0" + } + }, + "packages/block-editor/node_modules/tslib": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", + "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==" + }, + "packages/block-library": { + "name": "@wordpress/block-library", + "version": "9.9.0", + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "7.25.7", + "@wordpress/a11y": "file:../a11y", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/autop": "file:../autop", + "@wordpress/blob": "file:../blob", + "@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/date": "file:../date", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/element": "file:../element", + "@wordpress/escape-html": "file:../escape-html", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/interactivity": "file:../interactivity", + "@wordpress/interactivity-router": "file:../interactivity-router", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/notices": "file:../notices", + "@wordpress/patterns": "file:../patterns", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/reusable-blocks": "file:../reusable-blocks", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/server-side-render": "file:../server-side-render", + "@wordpress/url": "file:../url", + "@wordpress/viewport": "file:../viewport", + "@wordpress/wordcount": "file:../wordcount", + "change-case": "^4.1.2", + "clsx": "^2.1.1", + "colord": "^2.7.0", + "escape-html": "^1.0.3", + "fast-average-color": "^9.1.1", + "fast-deep-equal": "^3.1.3", + "memize": "^2.1.0", + "remove-accents": "^0.5.0", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "packages/block-library/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "packages/block-serialization-default-parser": { + "name": "@wordpress/block-serialization-default-parser", + "version": "5.9.0", + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "7.25.7" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "packages/block-serialization-spec-parser": { + "name": "@wordpress/block-serialization-spec-parser", + "version": "5.9.0", + "license": "GPL-2.0-or-later", + "dependencies": { + "pegjs": "^0.10.0", + "phpegjs": "^1.0.0-beta7" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "packages/blocks": { + "name": "@wordpress/blocks", + "version": "13.9.0", + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "7.25.7", + "@wordpress/autop": "file:../autop", + "@wordpress/blob": "file:../blob", + "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", "@wordpress/data": "file:../data", "@wordpress/deprecated": "file:../deprecated", "@wordpress/dom": "file:../dom", @@ -53030,7 +54313,7 @@ "version": "1.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/components": "file:../components", "@wordpress/data": "file:../data", "@wordpress/element": "file:../element", @@ -53204,7 +54487,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@emotion/cache": "^11.7.1", "@emotion/css": "^11.7.1", "@emotion/react": "^11.7.1", @@ -53324,7 +54607,7 @@ "version": "7.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@types/mousetrap": "^1.6.8", "@wordpress/deprecated": "file:../deprecated", "@wordpress/dom": "file:../dom", @@ -53361,7 +54644,7 @@ "version": "1.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/block-editor": "file:../block-editor", "@wordpress/commands": "file:../commands", "@wordpress/compose": "file:../compose", @@ -53390,7 +54673,7 @@ "version": "7.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/block-editor": "file:../block-editor", "@wordpress/blocks": "file:../blocks", @@ -53473,7 +54756,7 @@ "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/block-editor": "file:../block-editor", "@wordpress/block-library": "file:../block-library", "@wordpress/blocks": "file:../blocks", @@ -53512,7 +54795,7 @@ "version": "10.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/compose": "file:../compose", "@wordpress/deprecated": "file:../deprecated", "@wordpress/element": "file:../element", @@ -53541,7 +54824,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/data": "file:../data", "@wordpress/deprecated": "file:../deprecated" @@ -53560,7 +54843,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", "@wordpress/data": "file:../data", @@ -53616,7 +54899,7 @@ "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/deprecated": "file:../deprecated", "moment": "^2.29.4", "moment-timezone": "^0.5.40" @@ -53647,7 +54930,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/hooks": "file:../hooks" }, "engines": { @@ -53661,7 +54944,7 @@ "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@babel/core": "^7.16.0", + "@babel/core": "7.25.7", "comment-parser": "^1.1.1", "mdast-util-inject": "1.1.0", "optionator": "0.8.2", @@ -53682,7 +54965,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/deprecated": "file:../deprecated" }, "engines": { @@ -53695,7 +54978,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "engines": { "node": ">=18.12.0", @@ -53708,7 +54991,7 @@ "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/keycodes": "file:../keycodes", "@wordpress/url": "file:../url", @@ -53798,7 +55081,7 @@ "version": "8.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/block-editor": "file:../block-editor", @@ -53845,7 +55128,7 @@ "version": "6.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@react-spring/web": "^9.4.5", "@wordpress/a11y": "file:../a11y", "@wordpress/api-fetch": "file:../api-fetch", @@ -53907,7 +55190,7 @@ "version": "6.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/block-editor": "file:../block-editor", "@wordpress/block-library": "file:../block-library", @@ -53951,7 +55234,7 @@ "version": "14.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", @@ -54013,7 +55296,7 @@ "version": "6.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@types/react": "^18.2.79", "@types/react-dom": "^18.2.25", "@wordpress/escape-html": "file:../escape-html", @@ -54174,7 +55457,7 @@ "version": "3.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "engines": { "node": ">=18.12.0", @@ -54187,7 +55470,7 @@ "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@babel/eslint-parser": "^7.16.0", + "@babel/eslint-parser": "7.25.7", "@typescript-eslint/eslint-plugin": "^6.4.1", "@typescript-eslint/parser": "^6.4.1", "@wordpress/babel-preset-default": "file:../babel-preset-default", @@ -54224,12 +55507,41 @@ } } }, + "packages/eslint-plugin/node_modules/@babel/eslint-parser": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.7.tgz", + "integrity": "sha512-B+BO9x86VYsQHimucBAL1fxTJKF4wyKY6ZVzee9QgzdZOUfs3BaR6AQrgoGrRI+7IFS1wUz/VyQ+SoBcSpdPbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" + } + }, + "packages/eslint-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "packages/fields": { "name": "@wordpress/fields", "version": "0.1.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", "@wordpress/blocks": "file:../blocks", @@ -54265,7 +55577,7 @@ "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/block-editor": "file:../block-editor", "@wordpress/components": "file:../components", @@ -54293,7 +55605,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "engines": { "node": ">=18.12.0", @@ -54305,7 +55617,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "engines": { "node": ">=18.12.0", @@ -54317,7 +55629,7 @@ "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/hooks": "file:../hooks", "gettext-parser": "^1.3.1", "memize": "^2.1.0", @@ -54337,7 +55649,7 @@ "version": "10.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/element": "file:../element", "@wordpress/primitives": "file:../primitives" }, @@ -54401,7 +55713,7 @@ "version": "6.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", @@ -54430,7 +55742,7 @@ "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "engines": { "node": ">=18.12.0", @@ -54443,7 +55755,7 @@ "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "jest-matcher-utils": "^29.6.2" }, "engines": { @@ -54461,7 +55773,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/jest-console": "file:../jest-console", - "babel-jest": "^29.6.2" + "babel-jest": "29.7.0" }, "engines": { "node": ">=18.12.0", @@ -54479,7 +55791,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@axe-core/puppeteer": "^4.0.0", - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "engines": { "node": ">=18.12.0", @@ -54500,7 +55812,7 @@ "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/data": "file:../data", "@wordpress/element": "file:../element", "@wordpress/keycodes": "file:../keycodes" @@ -54518,7 +55830,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/i18n": "file:../i18n" }, "engines": { @@ -54546,7 +55858,7 @@ "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", "@wordpress/components": "file:../components", @@ -54569,7 +55881,7 @@ "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", "@wordpress/element": "file:../element", @@ -54585,7 +55897,7 @@ "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/data": "file:../data" }, @@ -54615,7 +55927,7 @@ "version": "9.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", "@wordpress/data": "file:../data", @@ -54638,7 +55950,7 @@ "version": "2.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/block-editor": "file:../block-editor", "@wordpress/blocks": "file:../blocks", @@ -54668,7 +55980,7 @@ "version": "7.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", "@wordpress/element": "file:../element", @@ -54721,7 +56033,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", @@ -54747,7 +56059,7 @@ "version": "2.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch" }, "engines": { @@ -54773,7 +56085,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/element": "file:../element", "clsx": "^2.1.1" }, @@ -54790,7 +56102,7 @@ "version": "3.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "requestidlecallback": "^0.3.0" }, "engines": { @@ -54803,7 +56115,7 @@ "version": "1.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "engines": { "node": ">=18.12.0", @@ -54818,7 +56130,7 @@ "dependencies": { "@actions/core": "1.9.1", "@actions/github": "^5.0.0", - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@octokit/request-error": "^2.1.0", "@octokit/webhooks": "^9.26.3" }, @@ -54845,7 +56157,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/element": "file:../element", "@wordpress/i18n": "file:../i18n", "utility-types": "^3.10.0" @@ -54893,7 +56205,7 @@ "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.20.0", + "@babel/runtime": "7.25.7", "@react-native-clipboard/clipboard": "1.11.2", "@react-native-community/blur": "4.2.0", "@react-native-community/slider": "https://raw.githubusercontent.com/wordpress-mobile/react-native-slider/v3.0.2-wp-5/react-native-community-slider-3.0.2-wp-5.tgz", @@ -55014,7 +56326,7 @@ "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "is-plain-object": "^5.0.0", "is-promise": "^4.0.0", "rungen": "^0.3.2" @@ -55059,7 +56371,7 @@ "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/block-editor": "file:../block-editor", "@wordpress/blocks": "file:../blocks", "@wordpress/components": "file:../components", @@ -55086,7 +56398,7 @@ "version": "7.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/compose": "file:../compose", "@wordpress/data": "file:../data", @@ -55110,7 +56422,7 @@ "version": "1.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/element": "file:../element", "@wordpress/private-apis": "file:../private-apis", "@wordpress/url": "file:../url", @@ -55130,7 +56442,7 @@ "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@babel/core": "^7.16.0", + "@babel/core": "7.25.7", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", "@svgr/webpack": "^8.0.1", "@wordpress/babel-preset-default": "file:../babel-preset-default", @@ -55144,8 +56456,8 @@ "@wordpress/prettier-config": "file:../prettier-config", "@wordpress/stylelint-config": "file:../stylelint-config", "adm-zip": "^0.5.9", - "babel-jest": "^29.6.2", - "babel-loader": "^8.2.3", + "babel-jest": "29.7.0", + "babel-loader": "9.2.1", "browserslist": "^4.21.10", "chalk": "^4.0.0", "check-node-version": "^4.1.0", @@ -55585,7 +56897,7 @@ "version": "5.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blocks": "file:../blocks", "@wordpress/components": "file:../components", @@ -55611,7 +56923,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "memize": "^2.0.1" }, "engines": { @@ -55624,7 +56936,7 @@ "version": "2.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "change-case": "^4.1.2" }, "engines": { @@ -55756,7 +57068,7 @@ "version": "1.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@types/simple-peer": "^9.11.5", "@wordpress/url": "file:../url", "import-locals": "^2.0.0", @@ -55777,7 +57089,7 @@ "version": "3.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "engines": { "node": ">=18.12.0", @@ -55789,7 +57101,7 @@ "version": "1.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/is-shallow-equal": "file:../is-shallow-equal" }, "engines": { @@ -55802,7 +57114,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "remove-accents": "^0.5.0" }, "engines": { @@ -55815,7 +57127,7 @@ "version": "6.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/compose": "file:../compose", "@wordpress/data": "file:../data", "@wordpress/element": "file:../element" @@ -55842,7 +57154,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/block-editor": "file:../block-editor", "@wordpress/blocks": "file:../blocks", @@ -55870,7 +57182,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "engines": { "node": ">=18.12.0", diff --git a/package.json b/package.json index e0806af385ae6d..4c071bf746c159 100644 --- a/package.json +++ b/package.json @@ -100,11 +100,10 @@ "@actions/github": "5.0.0", "@apidevtools/json-schema-ref-parser": "11.6.4", "@ariakit/test": "^0.4.2", - "@babel/core": "7.24.3", - "@babel/plugin-proposal-export-namespace-from": "7.18.9", - "@babel/plugin-syntax-jsx": "7.24.1", - "@babel/runtime-corejs3": "7.24.1", - "@babel/traverse": "7.24.1", + "@babel/core": "7.25.7", + "@babel/plugin-syntax-jsx": "7.25.7", + "@babel/runtime-corejs3": "7.25.7", + "@babel/traverse": "7.25.7", "@emotion/babel-plugin": "11.11.0", "@emotion/jest": "11.7.1", "@emotion/native": "11.0.0", @@ -175,7 +174,7 @@ "ajv": "8.7.1", "appium": "2.0.0", "babel-jest": "29.7.0", - "babel-loader": "9.1.3", + "babel-loader": "9.2.1", "babel-plugin-inline-json-import": "0.3.2", "babel-plugin-react-native-classname-to-style": "1.2.2", "babel-plugin-react-native-platform-specific-extensions": "1.1.1", diff --git a/packages/README.md b/packages/README.md index b8d2c913a91b9d..0b131f6c404d4e 100644 --- a/packages/README.md +++ b/packages/README.md @@ -28,7 +28,7 @@ When creating a new package, you need to provide at least the following: "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" diff --git a/packages/a11y/package.json b/packages/a11y/package.json index e3868dca8b6baf..761367e0bb6f45 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -30,7 +30,7 @@ "types": "build-types", "wpScriptModuleExports": "./build-module/module/index.js", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/dom-ready": "file:../dom-ready", "@wordpress/i18n": "file:../i18n" }, diff --git a/packages/annotations/package.json b/packages/annotations/package.json index ab482712954252..417d6b22c9fd86 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -26,7 +26,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/data": "file:../data", "@wordpress/hooks": "file:../hooks", "@wordpress/i18n": "file:../i18n", diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 3ad4425db40309..13d23eaf496115 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -28,7 +28,7 @@ "react-native": "src/index", "types": "build-types", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/i18n": "file:../i18n", "@wordpress/url": "file:../url" }, diff --git a/packages/autop/package.json b/packages/autop/package.json index 9320cfc26213aa..7025f39b7b4a4c 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -28,7 +28,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index 47ecbcccd5eb2f..82ced61c51e505 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -32,7 +32,7 @@ ], "main": "index.js", "peerDependencies": { - "@babel/core": "^7.12.9" + "@babel/core": "^7.25.7" }, "publishConfig": { "access": "public" diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index d04a20a7164594..0877bc9bf10bd8 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -34,7 +34,7 @@ "is-plain-object": "^5.0.0" }, "peerDependencies": { - "@babel/core": "^7.12.9" + "@babel/core": "^7.25.7" }, "publishConfig": { "access": "public" diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index c577d6fd038bcf..4237d8266db30c 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -2,6 +2,15 @@ ## Unreleased +### Enhancements + +- The bundled `@babel/core` dependency has been updated from requiring `^7.16.0` to requiring `7.25.7` ([#36244](https://github.com/WordPress/gutenberg/pull/36244)). +- The bundled `@babel/plugin-transform-react-jsx` dependency has been updated from requiring `^7.16.0` to requiring `7.25.7` ([#36244](https://github.com/WordPress/gutenberg/pull/36244)). +- The bundled `@babel/plugin-transform-runtime` dependency has been updated from requiring `^7.16.0` to requiring `7.25.7` ([#36244](https://github.com/WordPress/gutenberg/pull/36244)). +- The bundled `@babel/preset-env` dependency has been updated from requiring `^7.16.0` to requiring `7.25.7` ([#36244](https://github.com/WordPress/gutenberg/pull/36244)). +- The bundled `@babel/preset-typescript` dependency has been updated from requiring `^7.16.0` to requiring `7.25.7` ([#36244](https://github.com/WordPress/gutenberg/pull/36244)). +- The bundled `@babel/runtime` dependency has been updated from requiring `^7.16.0` to requiring `7.25.7` ([#36244](https://github.com/WordPress/gutenberg/pull/36244)). + ## 8.9.0 (2024-10-03) ### Bug Fixes diff --git a/packages/babel-preset-default/README.md b/packages/babel-preset-default/README.md index 301d2583dcf865..de2e417d80e1e7 100644 --- a/packages/babel-preset-default/README.md +++ b/packages/babel-preset-default/README.md @@ -35,7 +35,7 @@ For example, if you'd like to use a new language feature proposal which has not ```json { "presets": [ "@wordpress/babel-preset-default" ], - "plugins": [ "@babel/plugin-proposal-class-properties" ] + "plugins": [ "@babel/plugin-transform-class-properties" ] } ``` diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index f98ac198e22730..a7eb893c75f016 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -32,12 +32,12 @@ ], "main": "index.js", "dependencies": { - "@babel/core": "^7.16.0", - "@babel/plugin-transform-react-jsx": "^7.16.0", - "@babel/plugin-transform-runtime": "^7.16.0", - "@babel/preset-env": "^7.16.0", - "@babel/preset-typescript": "^7.16.0", - "@babel/runtime": "^7.16.0", + "@babel/core": "7.25.7", + "@babel/plugin-transform-react-jsx": "7.25.7", + "@babel/plugin-transform-runtime": "7.25.7", + "@babel/preset-env": "7.25.7", + "@babel/preset-typescript": "7.25.7", + "@babel/runtime": "7.25.7", "@wordpress/browserslist-config": "file:../browserslist-config", "@wordpress/warning": "file:../warning", "browserslist": "^4.21.10", diff --git a/packages/blob/package.json b/packages/blob/package.json index 96d35105fc8246..158eb69e270089 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -28,7 +28,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index b1f0aaf2a599ad..5d0d489fdeedb5 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -26,7 +26,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/block-editor": "file:../block-editor", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 1c6c313345d723..32b8830fe48db0 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -32,7 +32,7 @@ "{src,build,build-module}/{index.js,store/index.js,hooks/**}" ], "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@emotion/react": "^11.7.1", "@emotion/styled": "^11.6.0", "@react-spring/web": "^9.4.5", diff --git a/packages/block-library/package.json b/packages/block-library/package.json index ac25e1cdb815ab..ba5283aee9da84 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -38,7 +38,7 @@ "./search/view": "./build-module/search/view.js" }, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/autop": "file:../autop", diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 5dabca2d129452..c0cf1286835649 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -29,7 +29,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 644e428cb686b4..b66d06e7884c4f 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -29,7 +29,7 @@ "{src,build,build-module}/{index.js,store/index.js}" ], "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/autop": "file:../autop", "@wordpress/blob": "file:../blob", "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", diff --git a/packages/commands/package.json b/packages/commands/package.json index 6fd5fdf9971e46..8c4521da0a34b8 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -27,7 +27,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/components": "file:../components", "@wordpress/data": "file:../data", "@wordpress/element": "file:../element", diff --git a/packages/components/package.json b/packages/components/package.json index 0a2b7b0d0431be..0bc1c865299d2d 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -32,7 +32,7 @@ "types": "build-types", "dependencies": { "@ariakit/react": "^0.4.10", - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@emotion/cache": "^11.7.1", "@emotion/css": "^11.7.1", "@emotion/react": "^11.7.1", diff --git a/packages/compose/package.json b/packages/compose/package.json index 83ffd1d2b364f1..9f8a6287a8f044 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -30,7 +30,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@types/mousetrap": "^1.6.8", "@wordpress/deprecated": "file:../deprecated", "@wordpress/dom": "file:../dom", diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 1eed9f5348145a..3ecc6ca145a71f 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -27,7 +27,7 @@ "react-native": "src/index", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/block-editor": "file:../block-editor", "@wordpress/commands": "file:../commands", "@wordpress/compose": "file:../compose", diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 4037bd577c3233..8eebcd083a83fa 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -31,7 +31,7 @@ "{src,build,build-module}/index.js" ], "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/block-editor": "file:../block-editor", "@wordpress/blocks": "file:../blocks", diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 32f79cbd3c3b5d..4ad8407ef73cbc 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -24,7 +24,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/block-editor": "file:../block-editor", "@wordpress/block-library": "file:../block-library", "@wordpress/blocks": "file:../blocks", diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index cf4aab46c6daee..712e7165348e61 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -28,7 +28,7 @@ "react-native": "src/index", "types": "build-types", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/data": "file:../data", "@wordpress/deprecated": "file:../deprecated" diff --git a/packages/data/package.json b/packages/data/package.json index 7ba4efc4592254..0320f7ffae681b 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -29,7 +29,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/compose": "file:../compose", "@wordpress/deprecated": "file:../deprecated", "@wordpress/element": "file:../element", diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index d5b465a3f7b2de..0dbf07ca52ff98 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -29,7 +29,7 @@ "sideEffects": false, "dependencies": { "@ariakit/react": "^0.4.10", - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", "@wordpress/data": "file:../data", diff --git a/packages/date/package.json b/packages/date/package.json index 3023e0cba30e51..71b1bc46bb147a 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -27,7 +27,7 @@ "react-native": "src/index", "types": "build-types", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/deprecated": "file:../deprecated", "moment": "^2.29.4", "moment-timezone": "^0.5.40" diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 2c7d69a11ea921..541c01b072bb94 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -28,7 +28,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/hooks": "file:../hooks" }, "publishConfig": { diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 2829246f9e4309..0842d451a55a5a 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -31,7 +31,7 @@ "docgen": "./bin/cli.js" }, "dependencies": { - "@babel/core": "^7.16.0", + "@babel/core": "7.25.7", "comment-parser": "^1.1.1", "mdast-util-inject": "1.1.0", "optionator": "0.8.2", diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 56913124da79f3..81fa96ab147826 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -28,7 +28,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" diff --git a/packages/dom/package.json b/packages/dom/package.json index c80beed815ea90..0e9250f0dbef39 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -29,7 +29,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/deprecated": "file:../deprecated" }, "publishConfig": { diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index ba0df0cf7532f5..8ec9f34d8366a2 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -30,7 +30,7 @@ "main": "build/index.js", "module": "build-module/index.js", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/keycodes": "file:../keycodes", "@wordpress/url": "file:../url", diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index dd2eaa5115bafb..babb8a84a65d67 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -27,7 +27,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/block-editor": "file:../block-editor", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index bd86d74c686801..53f0204eae9968 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -27,7 +27,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@react-spring/web": "^9.4.5", "@wordpress/a11y": "file:../a11y", "@wordpress/api-fetch": "file:../api-fetch", diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 39bdee011a55c1..891d140a4f6d1b 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -27,7 +27,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/block-editor": "file:../block-editor", "@wordpress/block-library": "file:../block-library", diff --git a/packages/editor/package.json b/packages/editor/package.json index 8781b0b992d94f..96970acd7fd034 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -31,7 +31,7 @@ "{src,build,build-module}/{index.js,store/index.js,hooks/**,bindings/**}" ], "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", diff --git a/packages/element/package.json b/packages/element/package.json index dc96c5a83b182a..0160f504cdb832 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -29,7 +29,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@types/react": "^18.2.79", "@types/react-dom": "^18.2.25", "@wordpress/escape-html": "file:../escape-html", diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index b45f4c236f41eb..c5c5fdc8c694be 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -28,7 +28,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 6638473b94b184..af30427b6e4a8b 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -31,7 +31,7 @@ ], "main": "index.js", "dependencies": { - "@babel/eslint-parser": "^7.16.0", + "@babel/eslint-parser": "7.25.7", "@typescript-eslint/eslint-plugin": "^6.4.1", "@typescript-eslint/parser": "^6.4.1", "@wordpress/babel-preset-default": "file:../babel-preset-default", diff --git a/packages/fields/package.json b/packages/fields/package.json index d0dd29138c5e5f..3c4edabf873a9a 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -31,7 +31,7 @@ "src/**/*.scss" ], "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", "@wordpress/blocks": "file:../blocks", diff --git a/packages/format-library/package.json b/packages/format-library/package.json index fa2f45682a2b7c..f868bf56fc59cb 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -26,7 +26,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/block-editor": "file:../block-editor", "@wordpress/components": "file:../components", diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 841dcd33afb7fa..47f89922f1a873 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -27,7 +27,7 @@ "react-native": "src/index", "types": "build-types", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index fe0c1314b1a387..935b4735dd3a46 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -28,7 +28,7 @@ "react-native": "src/index", "types": "build-types", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 7dc84901cafea1..fcc47e9b7dca30 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -30,7 +30,7 @@ "pot-to-php": "./tools/pot-to-php.js" }, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/hooks": "file:../hooks", "gettext-parser": "^1.3.1", "memize": "^2.1.0", diff --git a/packages/icons/package.json b/packages/icons/package.json index 39395b2b76cb0b..bd2db0224b8cbe 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -29,7 +29,7 @@ "react-native": "src/index", "types": "build-types", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/element": "file:../element", "@wordpress/primitives": "file:../primitives" }, diff --git a/packages/interface/package.json b/packages/interface/package.json index cb55a37da29b54..7c4d65a0367b06 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -32,7 +32,7 @@ "{src,build,build-module}/{index.js,store/index.js}" ], "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index bd28c31fc750b2..7125e4604c506c 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -37,7 +37,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index a35f92896950fc..514a62b085ee04 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -33,7 +33,7 @@ "module": "build-module/index.js", "types": "types", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "jest-matcher-utils": "^29.6.2" }, "peerDependencies": { diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 1a64cc47294f31..6a8b91f4d41d5e 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -32,7 +32,7 @@ "main": "index.js", "dependencies": { "@wordpress/jest-console": "file:../jest-console", - "babel-jest": "^29.6.2" + "babel-jest": "29.7.0" }, "peerDependencies": { "@babel/core": ">=7", diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 71674e12e0df94..0c82889d48c65b 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -33,7 +33,7 @@ "module": "build-module/index.js", "dependencies": { "@axe-core/puppeteer": "^4.0.0", - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "peerDependencies": { "jest": ">=29", diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index bf71b807329f77..96f86771f49099 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -26,7 +26,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/data": "file:../data", "@wordpress/element": "file:../element", "@wordpress/keycodes": "file:../keycodes" diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index cfff9c69844232..9e34c83952838d 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -28,7 +28,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/i18n": "file:../i18n" }, "publishConfig": { diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 4971c35c947eb2..d50f257805465b 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -26,7 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", "@wordpress/components": "file:../components", diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 25bdb46a352bbb..4d5b3c8ccc0f8f 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -27,7 +27,7 @@ "module": "build-module/index.js", "types": "build-types", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", "@wordpress/element": "file:../element", diff --git a/packages/notices/package.json b/packages/notices/package.json index b6712776778e13..8bac25815d88cf 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -27,7 +27,7 @@ "react-native": "src/index", "types": "build-types", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/data": "file:../data" }, diff --git a/packages/nux/package.json b/packages/nux/package.json index f633695d5490a2..dfc69ba6ccf1ad 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -31,7 +31,7 @@ "{src,build,build-module}/{index.js,store/index.js}" ], "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", "@wordpress/data": "file:../data", diff --git a/packages/patterns/package.json b/packages/patterns/package.json index b9654af383f723..edafe4f1c9fefb 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -31,7 +31,7 @@ "{src,build,build-module}/{index.js,store/index.js,hooks/**}" ], "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/block-editor": "file:../block-editor", "@wordpress/blocks": "file:../blocks", diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 7772c7361cd5bc..6ea881e56931bb 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -27,7 +27,7 @@ "react-native": "src/index", "types": "build-types", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", "@wordpress/element": "file:../element", diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index 1872840d8a8cc9..06e005ba49b079 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -28,7 +28,7 @@ "react-native": "src/index", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch" }, "publishConfig": { diff --git a/packages/preferences/package.json b/packages/preferences/package.json index 722212c3d0d48b..2cf9b0666da390 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -29,7 +29,7 @@ "react-native": "src/index", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 4bf8849c0dba4a..9348dff41e66b7 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -31,7 +31,7 @@ ], "types": "build-types", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/element": "file:../element", "clsx": "^2.1.1" }, diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 991d5a207c780c..3414ce59031797 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -29,7 +29,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "requestidlecallback": "^0.3.0" }, "publishConfig": { diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index ada754f9405259..230d880ac72a6f 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -29,7 +29,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 67ad670628efcd..2da7535df6d111 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -28,7 +28,7 @@ "dependencies": { "@actions/core": "1.9.1", "@actions/github": "^5.0.0", - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@octokit/request-error": "^2.1.0", "@octokit/webhooks": "^9.26.3" }, diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index acf4656d65496b..4870e47ab13ecd 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -28,7 +28,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/element": "file:../element", "@wordpress/i18n": "file:../i18n", "utility-types": "^3.10.0" diff --git a/packages/react-native-editor/babel.config.js b/packages/react-native-editor/babel.config.js index 27a43df36e98b3..7f81d06082b58f 100644 --- a/packages/react-native-editor/babel.config.js +++ b/packages/react-native-editor/babel.config.js @@ -10,7 +10,7 @@ module.exports = function ( api ) { plugins: [ path.resolve( __dirname, - '../../node_modules/@babel/plugin-proposal-async-generator-functions' + '../../node_modules/@babel/plugin-transform-async-generator-functions' ), '@babel/plugin-transform-runtime', '@babel/plugin-transform-named-capturing-groups-regex', diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json index 0d2dd66aa2f2fc..3a345a23e0a5d9 100644 --- a/packages/react-native-editor/package.json +++ b/packages/react-native-editor/package.json @@ -29,7 +29,7 @@ "main": "src/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.20.0", + "@babel/runtime": "7.25.7", "@react-native-clipboard/clipboard": "1.11.2", "@react-native-community/blur": "4.2.0", "@react-native-community/slider": "https://raw.githubusercontent.com/wordpress-mobile/react-native-slider/v3.0.2-wp-5/react-native-community-slider-3.0.2-wp-5.tgz", diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 80857aa15908d0..22fef722bf6152 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -30,7 +30,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "is-plain-object": "^5.0.0", "is-promise": "^4.0.0", "rungen": "^0.3.2" diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 8936c97e247683..dab24659ca176d 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -29,7 +29,7 @@ "{src,build,build-module}/{index.js,store/index.js}" ], "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/block-editor": "file:../block-editor", "@wordpress/blocks": "file:../blocks", "@wordpress/components": "file:../components", diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index f9ecb72cfb6d0e..68ffc5ee35e6f1 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -31,7 +31,7 @@ ], "types": "build-types", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/a11y": "file:../a11y", "@wordpress/compose": "file:../compose", "@wordpress/data": "file:../data", diff --git a/packages/router/package.json b/packages/router/package.json index eadc360d8e0cbf..594970d85378d0 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -27,7 +27,7 @@ "react-native": "src/index", "types": "build-types", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/element": "file:../element", "@wordpress/private-apis": "file:../private-apis", "@wordpress/url": "file:../url", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 19c474e27ffd9f..821097d728ab06 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -32,7 +32,7 @@ "wp-scripts": "./bin/wp-scripts.js" }, "dependencies": { - "@babel/core": "^7.16.0", + "@babel/core": "7.25.7", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", "@svgr/webpack": "^8.0.1", "@wordpress/babel-preset-default": "file:../babel-preset-default", @@ -46,8 +46,8 @@ "@wordpress/prettier-config": "file:../prettier-config", "@wordpress/stylelint-config": "file:../stylelint-config", "adm-zip": "^0.5.9", - "babel-jest": "^29.6.2", - "babel-loader": "^8.2.3", + "babel-jest": "29.7.0", + "babel-loader": "9.2.1", "browserslist": "^4.21.10", "chalk": "^4.0.0", "check-node-version": "^4.1.0", diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index d7dd1311a2f107..c1a5bd731e29a3 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -27,7 +27,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blocks": "file:../blocks", "@wordpress/components": "file:../components", diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index b0e2f5eb34181d..478754a31e1026 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -26,7 +26,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "memize": "^2.0.1" }, "publishConfig": { diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 80babe6bcd4ca5..ed194f57ff3a9f 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -30,7 +30,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "change-case": "^4.1.2" }, "publishConfig": { diff --git a/packages/sync/package.json b/packages/sync/package.json index 27f618f3345584..9d8633558789e8 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -28,7 +28,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@types/simple-peer": "^9.11.5", "@wordpress/url": "file:../url", "import-locals": "^2.0.0", diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 69c59f5ff582fb..4b2ef6fd9d576f 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -27,7 +27,7 @@ "react-native": "src/index", "types": "build-types", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index c08951947ee377..02b72044c01656 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -29,7 +29,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/is-shallow-equal": "file:../is-shallow-equal" }, "publishConfig": { diff --git a/packages/url/package.json b/packages/url/package.json index 9fa2c416619cf2..22deb9b8c81be2 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -28,7 +28,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "remove-accents": "^0.5.0" }, "publishConfig": { diff --git a/packages/viewport/package.json b/packages/viewport/package.json index cc990e6732ba86..3997038bfbd8cc 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -26,7 +26,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/compose": "file:../compose", "@wordpress/data": "file:../data", "@wordpress/element": "file:../element" diff --git a/packages/widgets/package.json b/packages/widgets/package.json index bf73872934da55..ef5e953ffe5f2a 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -24,7 +24,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.16.0", + "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/block-editor": "file:../block-editor", "@wordpress/blocks": "file:../blocks", diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index b813249f1f7d75..5be9c2073df1df 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -27,7 +27,7 @@ "react-native": "src/index", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" diff --git a/platform-docs/package-lock.json b/platform-docs/package-lock.json index 9ebc6258ce71c4..ce0969c3928a48 100644 --- a/platform-docs/package-lock.json +++ b/platform-docs/package-lock.json @@ -2189,7 +2189,7 @@ "@slorber/static-site-generator-webpack-plugin": "^4.0.7", "@svgr/webpack": "^6.5.1", "autoprefixer": "^10.4.14", - "babel-loader": "^9.1.3", + "babel-loader": "9.2.1", "babel-plugin-dynamic-import-node": "^2.3.3", "boxen": "^6.2.1", "chalk": "^4.1.2", @@ -4126,9 +4126,10 @@ } }, "node_modules/babel-loader": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", - "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", + "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", + "license": "MIT", "dependencies": { "find-cache-dir": "^4.0.0", "schema-utils": "^4.0.0" diff --git a/test/native/babel.config.js b/test/native/babel.config.js index d7bf10b1dfbc4b..e43fd420a43157 100644 --- a/test/native/babel.config.js +++ b/test/native/babel.config.js @@ -3,7 +3,7 @@ module.exports = ( api ) => { return { presets: [ 'module:@react-native/babel-preset' ], plugins: [ - '@babel/plugin-proposal-async-generator-functions', + '@babel/plugin-transform-async-generator-functions', '@babel/plugin-transform-runtime', [ 'react-native-platform-specific-extensions', @@ -12,7 +12,7 @@ module.exports = ( api ) => { }, ], 'react-native-reanimated/plugin', - '@babel/plugin-proposal-export-namespace-from', + '@babel/plugin-transform-export-namespace-from', '@babel/plugin-transform-dynamic-import', ], overrides: [ From 080bce9b82b1805d70e323c6dc66a1c398ac5300 Mon Sep 17 00:00:00 2001 From: Lee Pak <159242502+leemyongpakva@users.noreply.github.com> Date: Wed, 9 Oct 2024 22:39:57 +0700 Subject: [PATCH 1127/1908] consistent with block-development-examples data-basics-59c8f8 (#65995) --- docs/how-to-guides/data-basics/1-data-basics-setup.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/how-to-guides/data-basics/1-data-basics-setup.md b/docs/how-to-guides/data-basics/1-data-basics-setup.md index e61db83c4ecbd5..d3208ceb352b4b 100644 --- a/docs/how-to-guides/data-basics/1-data-basics-setup.md +++ b/docs/how-to-guides/data-basics/1-data-basics-setup.md @@ -10,7 +10,7 @@ We'll do all the development inside of a WordPress plugin. Let's start by creati - my-first-gutenberg-app.php – to create a new admin page - src/index.js – for our JavaScript application -- style.css – for the minimal stylesheet +- src/style.css – for the minimal stylesheet - package.json – for the build process Go ahead and create these files using the following snippets: @@ -36,7 +36,7 @@ window.addEventListener( ); ``` -**style.css:** +**src/style.css:** ```css .toplevel_page_my-first-gutenberg-app #wpcontent { @@ -149,7 +149,7 @@ function load_custom_wp_admin_scripts( $hook ) { // Load our style.css. wp_register_style( 'my-first-gutenberg-app', - plugins_url( 'style.css', __FILE__ ), + plugins_url( 'build/style-index.css', __FILE__ ), array(), $asset_file['version'] ); From ec5acbdbe0ccffd734de3f2aa76b42bb974b79b7 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 9 Oct 2024 18:00:11 +0200 Subject: [PATCH 1128/1908] BlockCanvas: Fix the height prop and width of the block editor (#65977) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> --- .../src/components/iframe/content.scss | 19 ------------------- .../src/components/iframe/index.js | 1 + .../src/components/iframe/style.scss | 16 ++++++++++++++++ packages/block-editor/src/style.scss | 1 + storybook/stories/playground/box/index.js | 2 +- 5 files changed, 19 insertions(+), 20 deletions(-) create mode 100644 packages/block-editor/src/components/iframe/style.scss diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss index 90b887993bf6db..52210fb1e241b6 100644 --- a/packages/block-editor/src/components/iframe/content.scss +++ b/packages/block-editor/src/components/iframe/content.scss @@ -2,25 +2,6 @@ position: relative; } -.block-editor-iframe__container { - width: 100%; - height: 100%; - overflow-x: hidden; -} - -.block-editor-iframe__scale-container { - width: 100%; - height: 100%; - display: flex; -} - -.block-editor-iframe__scale-container.is-zoomed-out { - $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw); - $prev-container-width: var(--wp-block-editor-iframe-zoom-out-prev-container-width, 100vw); - width: $prev-container-width; - margin-left: calc(-1 * (#{$prev-container-width} - #{$container-width}) / 2); -} - .block-editor-iframe__html { border: 0 solid $gray-300; transform-origin: top center; diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index 3e022cf95ae556..fa7ce26526f410 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -380,6 +380,7 @@ function Iframe( { style={ { ...props.style, height: props.style?.height, + border: 0, } } ref={ useMergeRefs( [ ref, setRef ] ) } tabIndex={ tabIndex } diff --git a/packages/block-editor/src/components/iframe/style.scss b/packages/block-editor/src/components/iframe/style.scss new file mode 100644 index 00000000000000..e460df3ab3e0a9 --- /dev/null +++ b/packages/block-editor/src/components/iframe/style.scss @@ -0,0 +1,16 @@ +.block-editor-iframe__container { + width: 100%; + height: 100%; + overflow-x: hidden; +} + +.block-editor-iframe__scale-container { + height: 100%; +} + +.block-editor-iframe__scale-container.is-zoomed-out { + $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw); + $prev-container-width: var(--wp-block-editor-iframe-zoom-out-prev-container-width, 100vw); + width: $prev-container-width; + margin-left: calc(-1 * (#{$prev-container-width} - #{$container-width}) / 2); +} diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index e6ec77b55a0ec5..512169351fe1fb 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -30,6 +30,7 @@ @import "./components/global-styles/style.scss"; @import "./components/grid/style.scss"; @import "./components/height-control/style.scss"; +@import "./components/iframe/style.scss"; @import "./components/image-size-control/style.scss"; @import "./components/inserter-list-item/style.scss"; @import "./components/inspector-controls-tabs/style.scss"; diff --git a/storybook/stories/playground/box/index.js b/storybook/stories/playground/box/index.js index 3fb3c3b5862c47..cca522a90c1441 100644 --- a/storybook/stories/playground/box/index.js +++ b/storybook/stories/playground/box/index.js @@ -37,7 +37,7 @@ export default function EditorBox() { } } > <BlockToolbar hideDragHandle /> - <BlockCanvas height="100%" styles={ editorStyles } /> + <BlockCanvas height="500px" styles={ editorStyles } /> </BlockEditorProvider> </div> ); From fc62bf65665c0513ea78e338245829b2f9d9ed79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Juh=C3=A9=20Lluveras?= <contact@albertjuhe.com> Date: Wed, 9 Oct 2024 19:44:24 +0200 Subject: [PATCH 1129/1908] Rename wp_register_block_template() to register_block_template() (#65958) Co-authored-by: Aljullu <aljullu@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- backport-changelog/6.7/7543.md | 3 ++ lib/compat/wordpress-6.7/block-templates.php | 49 +++++++++++++++++-- .../plugins/block-template-registration.php | 12 ++--- phpunit/block-template-test.php | 8 +-- ...tenberg-rest-templates-controller-test.php | 4 +- 5 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 backport-changelog/6.7/7543.md diff --git a/backport-changelog/6.7/7543.md b/backport-changelog/6.7/7543.md new file mode 100644 index 00000000000000..7dcb74354ac813 --- /dev/null +++ b/backport-changelog/6.7/7543.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7543 + +* https://github.com/WordPress/gutenberg/pull/65958 diff --git a/lib/compat/wordpress-6.7/block-templates.php b/lib/compat/wordpress-6.7/block-templates.php index d1f2859070b8b4..65d99ee978efed 100644 --- a/lib/compat/wordpress-6.7/block-templates.php +++ b/lib/compat/wordpress-6.7/block-templates.php @@ -5,7 +5,7 @@ * @package gutenberg */ -if ( ! function_exists( 'wp_register_block_template' ) ) { +if ( ! function_exists( 'register_block_template' ) ) { /** * Register a template. * @@ -22,20 +22,63 @@ * } * @return WP_Block_Template|WP_Error The registered template object on success, WP_Error object on failure. */ - function wp_register_block_template( $template_name, $args = array() ) { + function register_block_template( $template_name, $args = array() ) { return WP_Block_Templates_Registry::get_instance()->register( $template_name, $args ); } } +if ( ! function_exists( 'unregister_block_template' ) ) { + /** + * Unregister a template. + * + * @param string $template_name Template name in the form of `plugin_uri//template_name`. + * @return WP_Block_Template|WP_Error The unregistered template object on success, WP_Error object on failure or if + * the template doesn't exist. + */ + function unregister_block_template( $template_name ) { + return WP_Block_Templates_Registry::get_instance()->unregister( $template_name ); + } +} + +if ( ! function_exists( 'wp_register_block_template' ) ) { + /** + * Register a template. + * + * @deprecated 19.4.0 wp_register_block_template is deprecated. Please use register_block_template instead. + * + * @param string $template_name Template name in the form of `plugin_uri//template_name`. + * @param array|string $args { + * Optional. Array or string of arguments for registering a block template. + * + * @type string $title Optional. Title of the template as it will be shown in the Site Editor + * and other UI elements. + * @type string $description Optional. Description of the template as it will be shown in the Site + * Editor. + * @type string $content Optional. Default content of the template that will be used when the + * template is rendered or edited in the editor. + * @type string[] $post_types Optional. Array of post types to which the template should be available. + * @type string $plugin Uri of the plugin that registers the template. + * } + * @return WP_Block_Template|WP_Error The registered template object on success, WP_Error object on failure. + */ + function wp_register_block_template( $template_name, $args = array() ) { + _deprecated_function( __FUNCTION__, 'Gutenberg 19.4.0', 'register_block_template' ); + register_block_template( $template_name, $args ); + } +} + if ( ! function_exists( 'wp_unregister_block_template' ) ) { /** * Unregister a template. * + * @deprecated 19.4.0 wp_unregister_block_template is deprecated. Please use unregister_block_template instead. + * * @param string $template_name Template name in the form of `plugin_uri//template_name`. * @return WP_Block_Template|WP_Error The unregistered template object on success, WP_Error object on failure or if * the template doesn't exist. */ function wp_unregister_block_template( $template_name ) { - return WP_Block_Templates_Registry::get_instance()->unregister( $template_name ); + _deprecated_function( __FUNCTION__, 'Gutenberg 19.4.0', 'unregister_block_template' ); + return unregister_block_template( $template_name ); } } diff --git a/packages/e2e-tests/plugins/block-template-registration.php b/packages/e2e-tests/plugins/block-template-registration.php index a7c75552849658..f93deb19688c4b 100644 --- a/packages/e2e-tests/plugins/block-template-registration.php +++ b/packages/e2e-tests/plugins/block-template-registration.php @@ -11,7 +11,7 @@ 'init', function () { // Custom template used by most tests. - wp_register_block_template( + register_block_template( 'gutenberg//plugin-template', array( 'title' => 'Plugin Template', @@ -28,7 +28,7 @@ function () { ); // Custom template overridden by the theme. - wp_register_block_template( + register_block_template( 'gutenberg//custom-template', array( 'title' => 'Custom Template (overridden by the theme)', @@ -39,7 +39,7 @@ function () { ); // Custom template used to test unregistration. - wp_register_block_template( + register_block_template( 'gutenberg//plugin-unregistered-template', array( 'title' => 'Plugin Unregistered Template', @@ -47,10 +47,10 @@ function () { 'content' => '<!-- wp:template-part {"slug":"header","tagName":"header"} /--><!-- wp:group {"tagName":"main","layout":{"inherit":true}} --><main class="wp-block-group"><!-- wp:paragraph --><p>This is a plugin-registered template that is also unregistered.</p><!-- /wp:paragraph --></main><!-- /wp:group -->', ) ); - wp_unregister_block_template( 'gutenberg//plugin-unregistered-template' ); + unregister_block_template( 'gutenberg//plugin-unregistered-template' ); // Custom template used to test overriding default WP templates. - wp_register_block_template( + register_block_template( 'gutenberg//page', array( 'title' => 'Plugin Page Template', @@ -60,7 +60,7 @@ function () { ); // Custom template used to test overriding default WP templates which can be created by the user. - wp_register_block_template( + register_block_template( 'gutenberg//author-admin', array( 'title' => 'Plugin Author Template', diff --git a/phpunit/block-template-test.php b/phpunit/block-template-test.php index 6589aad90b8053..d3cfb1fe12f4f5 100644 --- a/phpunit/block-template-test.php +++ b/phpunit/block-template-test.php @@ -11,13 +11,13 @@ public function set_up() { public function test_get_block_templates_from_registry() { $template_name = 'test-plugin//test-template'; - wp_register_block_template( $template_name ); + register_block_template( $template_name ); $templates = get_block_templates(); $this->assertArrayHasKey( $template_name, $templates ); - wp_unregister_block_template( $template_name ); + unregister_block_template( $template_name ); } public function test_get_block_template_from_registry() { @@ -26,12 +26,12 @@ public function test_get_block_template_from_registry() { 'title' => 'Test Template', ); - wp_register_block_template( $template_name, $args ); + register_block_template( $template_name, $args ); $template = get_block_template( 'block-theme//test-template' ); $this->assertEquals( 'Test Template', $template->title ); - wp_unregister_block_template( $template_name ); + unregister_block_template( $template_name ); } } diff --git a/phpunit/class-gutenberg-rest-templates-controller-test.php b/phpunit/class-gutenberg-rest-templates-controller-test.php index 14735246c6fb20..b69416c675305b 100644 --- a/phpunit/class-gutenberg-rest-templates-controller-test.php +++ b/phpunit/class-gutenberg-rest-templates-controller-test.php @@ -32,7 +32,7 @@ public function test_get_item() { 'post_types' => array( 'post', 'page' ), ); - wp_register_block_template( $template_name, $args ); + register_block_template( $template_name, $args ); $request = new WP_REST_Request( 'GET', '/wp/v2/templates/test-plugin//test-template' ); $response = rest_get_server()->dispatch( $request ); @@ -52,7 +52,7 @@ public function test_get_item() { $this->assertSame( 'Test Template', $data['title']['rendered'], 'Template title mismatch.' ); $this->assertSame( 'test-plugin', $data['plugin'], 'Plugin name mismatch.' ); - wp_unregister_block_template( $template_name ); + unregister_block_template( $template_name ); $request = new WP_REST_Request( 'GET', '/wp/v2/templates/test-plugin//test-template' ); $response = rest_get_server()->dispatch( $request ); From e86152bc8b45d5fe213ed688f145e82f73bb2fd4 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 10 Oct 2024 04:27:55 +0900 Subject: [PATCH 1130/1908] ToggleGroupControl: Don't autoselect option on first group focus (#65892) * ToggleGroupControl: Don't autoselect option on first group focus * Fix test * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../test/__snapshots__/index.tsx.snap | 12 ++++----- .../src/toggle-group-control/test/index.tsx | 13 ++++++++++ .../component.tsx | 26 ++++++++----------- .../toggle-group-control/as-radio-group.tsx | 3 +++ .../src/toggle-group-control/types.ts | 1 + 6 files changed, 35 insertions(+), 21 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 4ae124347187e7..a532fda22f972f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -7,6 +7,7 @@ - `PaletteEdit`: dedupe palette element slugs ([#65772](https://github.com/WordPress/gutenberg/pull/65772)). - `RangeControl`: do not tooltip contents to the DOM when not shown ([#65875](https://github.com/WordPress/gutenberg/pull/65875)). - `Tabs`: fix skipping indication animation glitch ([#65878](https://github.com/WordPress/gutenberg/pull/65878)). +- `ToggleGroupControl`: Don't autoselect option on first group focus ([#65892](https://github.com/WordPress/gutenberg/pull/65892)). ### Enhancements diff --git a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap index d2d98eaba85e6f..832c6d7cb7a8c8 100644 --- a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap +++ b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap @@ -283,7 +283,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = class="components-toggle-group-control emotion-8 emotion-9" data-wp-c16t="true" data-wp-component="ToggleGroupControl" - id="toggle-group-control-as-radio-group-11" + id="toggle-group-control-as-radio-group-12" role="radiogroup" > <div @@ -297,7 +297,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = data-value="uppercase" data-wp-c16t="true" data-wp-component="ToggleGroupControlOptionBase" - id="toggle-group-control-as-radio-group-11-30" + id="toggle-group-control-as-radio-group-12-32" role="radio" type="button" value="uppercase" @@ -330,7 +330,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = data-value="lowercase" data-wp-c16t="true" data-wp-component="ToggleGroupControlOptionBase" - id="toggle-group-control-as-radio-group-11-31" + id="toggle-group-control-as-radio-group-12-33" role="radio" type="button" value="lowercase" @@ -575,7 +575,7 @@ exports[`ToggleGroupControl controlled should render correctly with text options class="components-toggle-group-control emotion-8 emotion-9" data-wp-c16t="true" data-wp-component="ToggleGroupControl" - id="toggle-group-control-as-radio-group-10" + id="toggle-group-control-as-radio-group-11" role="radiogroup" > <div @@ -588,7 +588,7 @@ exports[`ToggleGroupControl controlled should render correctly with text options data-value="rigas" data-wp-c16t="true" data-wp-component="ToggleGroupControlOptionBase" - id="toggle-group-control-as-radio-group-10-28" + id="toggle-group-control-as-radio-group-11-30" role="radio" type="button" value="rigas" @@ -610,7 +610,7 @@ exports[`ToggleGroupControl controlled should render correctly with text options data-value="jack" data-wp-c16t="true" data-wp-component="ToggleGroupControlOptionBase" - id="toggle-group-control-as-radio-group-10-29" + id="toggle-group-control-as-radio-group-11-31" role="radio" type="button" value="jack" diff --git a/packages/components/src/toggle-group-control/test/index.tsx b/packages/components/src/toggle-group-control/test/index.tsx index 170db01ae523c2..d7b4824fce4de8 100644 --- a/packages/components/src/toggle-group-control/test/index.tsx +++ b/packages/components/src/toggle-group-control/test/index.tsx @@ -162,6 +162,19 @@ describe.each( [ expect( mockOnChange ).toHaveBeenCalledWith( 'rigas' ); } ); + it( 'should not set a value on focus', async () => { + render( + <Component label="Test Toggle Group Control">{ options }</Component> + ); + + const radio = screen.getByRole( 'radio', { name: 'R' } ); + expect( radio ).not.toBeChecked(); + + await press.Tab(); + expect( radio ).toHaveFocus(); + expect( radio ).not.toBeChecked(); + } ); + it( 'should render tooltip where `showTooltip` === `true`', async () => { render( <Component label="Test Toggle Group Control"> diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx index d8604c59c540f0..b33f53dd706b53 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx @@ -75,7 +75,6 @@ function ToggleGroupControlOptionBase( value, children, showTooltip = false, - onFocus: onFocusProp, disabled, ...otherButtonProps } = buttonProps; @@ -132,7 +131,6 @@ function ToggleGroupControlOptionBase( <button { ...commonProps } disabled={ disabled } - onFocus={ onFocusProp } aria-pressed={ isPressed } type="button" onClick={ buttonOnClick } @@ -142,19 +140,17 @@ function ToggleGroupControlOptionBase( ) : ( <Ariakit.Radio disabled={ disabled } - render={ - <button - type="button" - { ...commonProps } - onFocus={ ( event ) => { - onFocusProp?.( event ); - if ( event.defaultPrevented ) { - return; - } - toggleGroupControlContext.setValue( value ); - } } - /> - } + onFocusVisible={ () => { + // Conditions ensure that the first visible focus to a radio group + // without a selected option will not automatically select the option. + if ( + toggleGroupControlContext.value !== null || + toggleGroupControlContext.activeItemIsNotFirstItem?.() + ) { + toggleGroupControlContext.setValue( value ); + } + } } + render={ <button type="button" { ...commonProps } /> } value={ value } > <ButtonContentView>{ children }</ButtonContentView> diff --git a/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx b/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx index 342f9f128defd9..4481fc9f6138d8 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx @@ -75,6 +75,8 @@ function UnforwardedToggleGroupControlAsRadioGroup( const groupContextValue = useMemo( (): ToggleGroupControlContextProps => ( { + activeItemIsNotFirstItem: () => + radio.getState().activeId !== radio.first(), baseId, isBlock: ! isAdaptiveWidth, size, @@ -87,6 +89,7 @@ function UnforwardedToggleGroupControlAsRadioGroup( [ baseId, isAdaptiveWidth, + radio, selectedValue, setSelectedElement, setValue, diff --git a/packages/components/src/toggle-group-control/types.ts b/packages/components/src/toggle-group-control/types.ts index 2a4af680263dba..463d8d26e64410 100644 --- a/packages/components/src/toggle-group-control/types.ts +++ b/packages/components/src/toggle-group-control/types.ts @@ -131,6 +131,7 @@ export type ToggleGroupControlProps = Pick< }; export type ToggleGroupControlContextProps = { + activeItemIsNotFirstItem?: () => boolean; isDeselectable?: boolean; baseId: string; isBlock: ToggleGroupControlProps[ 'isBlock' ]; From 03cfbff40ef2e5bf9ad369bb0a18642aa70833ef Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 10 Oct 2024 14:37:11 +0900 Subject: [PATCH 1131/1908] Exit zoon out when mode is changed (#65975) --- .../block-editor/src/components/tool-selector/index.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/tool-selector/index.js b/packages/block-editor/src/components/tool-selector/index.js index d328554f384b77..14a7f00593e196 100644 --- a/packages/block-editor/src/components/tool-selector/index.js +++ b/packages/block-editor/src/components/tool-selector/index.js @@ -36,7 +36,7 @@ function ToolSelector( props, ref ) { ( select ) => select( blockEditorStore ).__unstableGetEditorMode(), [] ); - const { __unstableSetEditorMode } = unlock( + const { resetZoomLevel, __unstableSetEditorMode } = unlock( useDispatch( blockEditorStore ) ); @@ -67,7 +67,10 @@ function ToolSelector( props, ref ) { value={ mode === 'navigation' ? 'navigation' : 'edit' } - onSelect={ __unstableSetEditorMode } + onSelect={ ( newMode ) => { + resetZoomLevel(); + __unstableSetEditorMode( newMode ); + } } choices={ [ { value: 'navigation', From 017c8bcf18050f024d4290b5299a324eb3184368 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 10 Oct 2024 10:36:16 +0200 Subject: [PATCH 1132/1908] Global styles: improve navigation logic for revisions screen (#65946) * Global styles: improve navigation logic for revisions screen * Merge style book case into default, add comment * Remove unnecessary goTo calls * Remove useNavigator import * Apply feedback --------- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../components/global-styles-sidebar/index.js | 12 +------- .../global-styles/screen-revisions/index.js | 13 ++------- .../src/components/global-styles/ui.js | 28 +++++++++++-------- 3 files changed, 20 insertions(+), 33 deletions(-) diff --git a/packages/edit-site/src/components/global-styles-sidebar/index.js b/packages/edit-site/src/components/global-styles-sidebar/index.js index 966005907cda4a..90a3331d14c716 100644 --- a/packages/edit-site/src/components/global-styles-sidebar/index.js +++ b/packages/edit-site/src/components/global-styles-sidebar/index.js @@ -1,13 +1,7 @@ /** * WordPress dependencies */ -import { - FlexItem, - FlexBlock, - Flex, - Button, - useNavigator, -} from '@wordpress/components'; +import { FlexItem, FlexBlock, Flex, Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { styles, seen, backup } from '@wordpress/icons'; import { useSelect, useDispatch } from '@wordpress/data'; @@ -86,21 +80,17 @@ export default function GlobalStylesSidebar() { }, [ shouldClearCanvasContainerView ] ); const { setIsListViewOpened } = useDispatch( editorStore ); - const { goTo } = useNavigator(); const toggleRevisions = () => { setIsListViewOpened( false ); if ( isRevisionsStyleBookOpened ) { - goTo( '/' ); setEditorCanvasContainerView( 'style-book' ); return; } if ( isRevisionsOpened ) { - goTo( '/' ); setEditorCanvasContainerView( undefined ); return; } - goTo( '/revisions' ); if ( isStyleBookOpened ) { setEditorCanvasContainerView( diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/index.js b/packages/edit-site/src/components/global-styles/screen-revisions/index.js index b980d199e7be30..a50b8f13d55cc2 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/index.js +++ b/packages/edit-site/src/components/global-styles/screen-revisions/index.js @@ -3,7 +3,6 @@ */ import { __, sprintf } from '@wordpress/i18n'; import { - useNavigator, __experimentalConfirmDialog as ConfirmDialog, Spinner, } from '@wordpress/components'; @@ -33,7 +32,6 @@ const { GlobalStylesContext, areGlobalStyleConfigsEqual } = unlock( const PAGE_SIZE = 10; function ScreenRevisions() { - const { goTo } = useNavigator(); const { user: currentEditorGlobalStyles, setUserConfig } = useContext( GlobalStylesContext ); const { blocks, editorCanvasContainerView } = useSelect( @@ -71,6 +69,8 @@ function ScreenRevisions() { currentEditorGlobalStyles ); + // The actual code that triggers the revisions screen to navigate back + // to the home screen in in `packages/edit-site/src/components/global-styles/ui.js`. const onCloseRevisions = () => { const canvasContainerView = editorCanvasContainerView === 'global-styles-revisions:style-book' @@ -85,15 +85,6 @@ function ScreenRevisions() { onCloseRevisions(); }; - useEffect( () => { - if ( - ! editorCanvasContainerView || - ! editorCanvasContainerView.startsWith( 'global-styles-revisions' ) - ) { - goTo( '/' ); // Return to global styles main panel. - } - }, [ editorCanvasContainerView ] ); - useEffect( () => { if ( ! isLoading && revisions.length ) { setCurrentRevisions( revisions ); diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index d534da901cd2e2..6cd465e237100a 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -70,10 +70,8 @@ function GlobalStylesActionMenu() { const { setEditorCanvasContainerView } = unlock( useDispatch( editSiteStore ) ); - const { goTo } = useNavigator(); const loadCustomCSS = () => { setEditorCanvasContainerView( 'global-styles-css' ); - goTo( '/css' ); }; return ( @@ -253,21 +251,29 @@ function GlobalStylesEditorCanvasContainerLink() { switch ( editorCanvasContainerView ) { case 'global-styles-revisions': case 'global-styles-revisions:style-book': - goTo( '/revisions' ); + if ( ! isRevisionsOpen ) { + goTo( '/revisions' ); + } break; case 'global-styles-css': goTo( '/css' ); break; + // The stand-alone style book is open + // and the revisions panel is open, + // close the revisions panel. + // Otherwise keep the style book open while + // browsing global styles panel. + // + // Falling through as it matches the default scenario. case 'style-book': - /* - * The stand-alone style book is open - * and the revisions panel is open, - * close the revisions panel. - * Otherwise keep the style book open while - * browsing global styles panel. - */ + default: + // In general, if the revision screen is in view but the + // `editorCanvasContainerView` is not a revision view, close it. + // This also includes the scenario when the stand-alone style + // book is open, in which case we want the user to close the + // revisions screen and browse global styles. if ( isRevisionsOpen ) { - goTo( '/' ); + goTo( '/', { isBack: true } ); } break; } From 0d5bcedfd7e4fe3c6cf443536a20dd339b45bc92 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:51:41 +0200 Subject: [PATCH 1133/1908] Check image `src` with falsy value (#66004) Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/block-library/src/image/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index 5d7815a1f2f3fb..1a5fae7ce9cbb7 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -24,7 +24,7 @@ function render_block_core_image( $attributes, $content, $block ) { $p = new WP_HTML_Tag_Processor( $content ); - if ( ! $p->next_tag( 'img' ) || null === $p->get_attribute( 'src' ) ) { + if ( ! $p->next_tag( 'img' ) || ! $p->get_attribute( 'src' ) ) { return ''; } From d809650edace0d7212e7cb0e274637e7e55560c2 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Thu, 10 Oct 2024 11:42:34 +0200 Subject: [PATCH 1134/1908] Storybook: Add stub doc on existing colors. (#65982) * Storybook: Add stub doc on existing colors. * Update 4.6 to 4.5 for contrast. * Update based on feedback. * Use SCSS also for the alerts. * Separate white and black. --- Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: mattrwalker <mattryanwalker@git.wordpress.org> --- storybook/stories/tokens/color.mdx | 61 ++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 storybook/stories/tokens/color.mdx diff --git a/storybook/stories/tokens/color.mdx b/storybook/stories/tokens/color.mdx new file mode 100644 index 00000000000000..17944a47777fc8 --- /dev/null +++ b/storybook/stories/tokens/color.mdx @@ -0,0 +1,61 @@ +import { Meta, ColorPalette, ColorItem } from '@storybook/blocks'; + +<Meta title="Tokens/Color" name="page" /> + +# Color + +This document outlines the default color set of the WordPress component system as it ships. The page is a work in progress. + +## Colors + +<ColorPalette> + <ColorItem + title="Black & White" + subtitle="" + colors={{ + '$black': '#000', + '$white': '#fff', + }} + /> +</ColorPalette> + +<ColorPalette> + <ColorItem + title="Gray Tones" + subtitle="" + colors={{ + '$gray-900': '#1e1e1e', + '$gray-800': '#2f2f2f', + '$gray-700': '#757575', + '$gray-600': '#949494', + '$gray-400': '#ccc', + '$gray-300': '#ddd', + '$gray-200': '#e0e0e0', + '$gray-100': '#f0f0f0', + }} + /> +</ColorPalette> + +<ColorPalette> + <ColorItem + title="Alert colors" + subtitle="" + colors={{ + '$alert-yellow': '#f0b849', + '$alert-red': '#cc1818', + '$alert-green': '#4ab866', + }} + /> +</ColorPalette> + +## Contrast + +Ensure proper contrast is met between text, icons, UI, and backgrounds. Text needs to meet a 4.5:1 ratio to meet AA standards, while large text (16px+) and UI elements (borders, etc.) need to meet a 3:1 ratio. In this section is a list of tokens you can use to meet these criteria. + +Against a white background: + +* **Gray 700**\ +Lightest gray you can use and meet 4.5:1 text contrast. + +* **Gray 600**\ +Lightest gray you can use and meet 3:1 UI contrast. From 8d1dd6c3220f5043d05b780b727107f658dccab0 Mon Sep 17 00:00:00 2001 From: Vrishabh Jasani <71686151+Vrishabhsk@users.noreply.github.com> Date: Thu, 10 Oct 2024 15:24:40 +0400 Subject: [PATCH 1135/1908] SearchControl: Deprecate onClose prop (#65988) * Soft deprecate onClose function prop and execute deprecated * Update README and StoryBook JSDoc * Expect console.warn due to deprecated func call and fix typo * Address PR feedback Remove WithOnClose storybook variation. Refactor deprecation message. Add @ignore for onClose in types.ts. Add deprecations section in CHANGELOG.md * Replace toHaveWarned with toHaveWarnedWith Co-authored-by: Vrishabhsk <vrishabhsk@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/search-control/README.md | 2 ++ packages/components/src/search-control/index.tsx | 7 +++++++ .../src/search-control/stories/index.story.tsx | 15 --------------- .../components/src/search-control/test/index.tsx | 5 ++++- packages/components/src/search-control/types.ts | 3 +++ 6 files changed, 20 insertions(+), 16 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index a532fda22f972f..87fd00dd8c826d 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -9,6 +9,10 @@ - `Tabs`: fix skipping indication animation glitch ([#65878](https://github.com/WordPress/gutenberg/pull/65878)). - `ToggleGroupControl`: Don't autoselect option on first group focus ([#65892](https://github.com/WordPress/gutenberg/pull/65892)). +### Deprecations + +- `SearchControl`: Soft deprecate `onClose` prop ([#65988](https://github.com/WordPress/gutenberg/pull/65988)). + ### Enhancements - `Tabs`: revamped vertical orientation styles ([#65387](https://github.com/WordPress/gutenberg/pull/65387)). diff --git a/packages/components/src/search-control/README.md b/packages/components/src/search-control/README.md index 52513ab47f582e..3945f451d6dcf7 100644 --- a/packages/components/src/search-control/README.md +++ b/packages/components/src/search-control/README.md @@ -76,6 +76,8 @@ A function that receives the value of the input. #### onClose +_Note: this prop is deprecated._ + When an `onClose` callback is provided, the search control will render a close button that will trigger the given callback. Use this if you want the button to trigger your own logic to close the search field entirely, rather than just clearing the input value. diff --git a/packages/components/src/search-control/index.tsx b/packages/components/src/search-control/index.tsx index c41eda9b209b6c..0a1b821a0a079a 100644 --- a/packages/components/src/search-control/index.tsx +++ b/packages/components/src/search-control/index.tsx @@ -10,6 +10,7 @@ import { useInstanceId, useMergeRefs } from '@wordpress/compose'; import { __ } from '@wordpress/i18n'; import { Icon, search, closeSmall } from '@wordpress/icons'; import { forwardRef, useMemo, useRef } from '@wordpress/element'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies @@ -31,6 +32,12 @@ function SuffixItem( { return <Icon icon={ search } />; } + if ( onClose ) { + deprecated( '`onClose` prop in wp.components.SearchControl', { + since: '6.8', + } ); + } + const onReset = () => { onChange( '' ); searchRef.current?.focus(); diff --git a/packages/components/src/search-control/stories/index.story.tsx b/packages/components/src/search-control/stories/index.story.tsx index 215288bb67c9b6..59618dd7e0913b 100644 --- a/packages/components/src/search-control/stories/index.story.tsx +++ b/packages/components/src/search-control/stories/index.story.tsx @@ -50,18 +50,3 @@ Default.args = { help: 'Help text to explain the input.', __nextHasNoMarginBottom: true, }; - -/** - * When an `onClose` callback is provided, the search control will render a close button - * that will trigger the given callback. - * - * Use this if you want the button to trigger your own logic to close the search field entirely, - * rather than just clearing the input value. - */ -export const WithOnClose = Template.bind( {} ); -WithOnClose.args = { - ...Default.args, -}; -WithOnClose.argTypes = { - onClose: { action: 'onClose' }, -}; diff --git a/packages/components/src/search-control/test/index.tsx b/packages/components/src/search-control/test/index.tsx index c6637945adcf63..5250a531f58d09 100644 --- a/packages/components/src/search-control/test/index.tsx +++ b/packages/components/src/search-control/test/index.tsx @@ -72,13 +72,16 @@ describe( 'SearchControl', () => { expect( onChangeSpy ).toHaveBeenLastCalledWith( '' ); } ); - it( 'should should render a Close button (instead of Reset) when onClose function is provided', async () => { + it( 'should render a Close button (instead of Reset) when onClose function is provided', async () => { const onChangeSpy = jest.fn(); const onCloseSpy = jest.fn(); render( <Component onChange={ onChangeSpy } onClose={ onCloseSpy } /> ); + expect( console ).toHaveWarnedWith( + '`onClose` prop in wp.components.SearchControl is deprecated since version 6.8.' + ); expect( screen.queryByRole( 'button', { name: 'Close search' } ) ).toBeVisible(); diff --git a/packages/components/src/search-control/types.ts b/packages/components/src/search-control/types.ts index 1bf38d1c25f6fb..e4117e5ed57ffb 100644 --- a/packages/components/src/search-control/types.ts +++ b/packages/components/src/search-control/types.ts @@ -40,6 +40,9 @@ export type SearchControlProps = Pick< InputControlProps, 'help' | 'value' > & { * * Use this if you want the button to trigger your own logic to close the search field entirely, * rather than just clearing the input value. + * + * @deprecated + * @ignore */ onClose?: () => void; /** @ignore */ From 715844d8a6db56a0f1bb9be9cfd14a6a43c258cd Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Thu, 10 Oct 2024 13:16:54 +0100 Subject: [PATCH 1136/1908] Add type tokens to storybook (#65993) * Add type tokens to storybook * Use tabs for spacing * Apply suggestions from code review Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com> --------- Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- storybook/stories/tokens/typography.mdx | 178 ++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 storybook/stories/tokens/typography.mdx diff --git a/storybook/stories/tokens/typography.mdx b/storybook/stories/tokens/typography.mdx new file mode 100644 index 00000000000000..c3b49b2865f186 --- /dev/null +++ b/storybook/stories/tokens/typography.mdx @@ -0,0 +1,178 @@ +import { Meta, Typeset } from '@storybook/addon-docs/blocks'; + +<Meta title="Tokens/Typography" name="page" /> + +export const typography = { + type: { + primary: '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif', + }, + weight: { + regular: '400', + medium: '500', + }, + size: { + s1: 11, + s2: 12, + s3: 13, + s4: 15, + s5: 20, + s6: 32, + }, +}; + +export const SampleTextHeading = 'Code is Poetry.'; +export const SampleTextParagraph = 'WordPress grows when people like you tell their friends about it, and the thousands of businesses and services that are built on and around WordPress share that fact with their users.' + +# Typography tokens + +This document outlines the various tokens relating to typography in the WordPress components system. + +## Semantic tokens + +Semantic tokens compose primitive tokens to create reusable type styles enhancing consistency across the software. + +They are defined as SASS mixins and can be used like so: + +```css +.my-component { + @include heading-large(); +} +``` + +### Headings + +<Typeset + fontSizes={[ + Number(typography.size.s6), + Number(typography.size.s5), + Number(typography.size.s4), + Number(typography.size.s3), + Number(typography.size.s2), + Number(typography.size.s1), + ]} + fontWeight={typography.weight.medium} + sampleText={SampleTextHeading} + fontFamily={typography.type.primary} +/> + +<table> + <thead> + <tr> + <th>Style</th> + <th>Primitives</th> + </tr> + </thead> + <tbody> + <tr> + <td>heading-2x-large</td> + <td>`$font-family-headings`, `font-weight-medium`, `font-size-2x-large`, `line-height-2x-large`</td> + </tr> + <tr> + <td>heading-x-large</td> + <td>`$font-family-headings`, `font-weight-medium`, `font-size-x-large`, `line-height-medium`</td> + </tr> + <tr> + <td>heading-large</td> + <td>`$font-family-headings`, `font-weight-medium`, `font-size-large`, `line-height-small`</td> + </tr> + <tr> + <td>heading-medium</td> + <td>`$font-family-headings`, `font-weight-medium`, `font-size-medium`, `line-height-small`</td> + </tr> + <tr> + <td>heading-small</td> + <td>`$font-family-headings`, `font-weight-medium`, `font-size-x-small`, `line-height-x-small`</td> + </tr> + </tbody> +</table> + +### Body + +<Typeset + fontSizes={[ + Number(typography.size.s5), + Number(typography.size.s4), + Number(typography.size.s3), + Number(typography.size.s2), + ]} + fontWeight={typography.weight.regular} + sampleText={SampleTextParagraph} + fontFamily={typography.type.primary} +/> + +<table> + <thead> + <tr> + <th>Style</th> + <th>Primitives</th> + </tr> + </thead> + <tbody> + <tr> + <td>body-x-large</td> + <td>`$font-family-body`, `font-weight-regular`, `font-size-x-large`, `line-height-x-large`</td> + </tr> + <tr> + <td>body-large</td> + <td>`$font-family-body`, `font-weight-regular`, `font-size-large`, `line-height-medium`</td> + </tr> + <tr> + <td>body-medium</td> + <td>`$font-family-body`, `font-weight-regular`, `font-size-medium`, `line-height-small`</td> + </tr> + <tr> + <td>body-small</td> + <td>`$font-family-body`, `font-weight-regular`, `font-size-small`, `line-height-x-small`</td> + </tr> + </tbody> +</table> + +## Primitive tokens + +Primitive tokens are organized into 4 sets relating to `size`, `line-height`, `weight`, and `family`, defined as SASS variables. + +### Size +```css +$font-size-x-small: 11px; +$font-size-small: 12px; +$font-size-medium: 13px; +$font-size-large: 15px; +$font-size-x-large: 20px; +$font-size-2x-large: 32px; +``` + +### Line-height + +```css +$font-line-height-x-small: 16px; +$font-line-height-small: 20px; +$font-line-height-medium: 24px; +$font-line-height-large: 28px; +$font-line-height-x-large: 32px; +$font-line-height-2x-large: 40px; +``` + +### Weight + +```css +$font-weight-regular: 400; +$font-weight-medium: 500; +``` + +### Families + +```css +$font-family-headings: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +$font-family-body: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +$font-family-mono: Menlo, Consolas, monaco, monospace; +``` + +Generally use of semantic tokens is encouraged, but it is possible to create ad hoc styles by referencing primitives, for example: + +```css +.my-type-style { + font-family: $font-family-headings; + line-height: $font-line-height-x-small; + font-weight: $font-weight-regular; +} +``` From cff0bf5ab533d00aff2cb88928b95ef94218913b Mon Sep 17 00:00:00 2001 From: Rich Tabor <hi@richtabor.com> Date: Thu, 10 Oct 2024 14:47:05 +0200 Subject: [PATCH 1137/1908] Make zoom transition smoother (#66017) Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/base-styles/_animations.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/base-styles/_animations.scss b/packages/base-styles/_animations.scss index b17478ed24f040..87e5f035f46a6c 100644 --- a/packages/base-styles/_animations.scss +++ b/packages/base-styles/_animations.scss @@ -37,7 +37,7 @@ } @mixin editor-canvas-resize-animation() { - transition: all 0.5s cubic-bezier(0.65, 0, 0.45, 1); + transition: all 0.4s cubic-bezier(0.46, 0.03, 0.52, 0.96); @include reduce-motion("transition"); } From 5bac40d6c48518644fd3a9a4d754736805c48254 Mon Sep 17 00:00:00 2001 From: Rich Tabor <hi@richtabor.com> Date: Thu, 10 Oct 2024 14:51:43 +0200 Subject: [PATCH 1138/1908] Zoom-out and Device preview: use 40px padding consistently (#66018) Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../block-editor/src/components/use-resize-canvas/index.js | 4 +--- packages/editor/src/components/visual-editor/index.js | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/use-resize-canvas/index.js b/packages/block-editor/src/components/use-resize-canvas/index.js index 7243b0f1b0b82f..3b4d97a097964c 100644 --- a/packages/block-editor/src/components/use-resize-canvas/index.js +++ b/packages/block-editor/src/components/use-resize-canvas/index.js @@ -43,11 +43,9 @@ export default function useResizeCanvas( deviceType ) { return deviceWidth < actualWidth ? deviceWidth : actualWidth; }; - const marginValue = () => ( window.innerHeight < 800 ? 36 : 64 ); - const contentInlineStyles = ( device ) => { const height = device === 'Mobile' ? '768px' : '1024px'; - const marginVertical = marginValue() + 'px'; + const marginVertical = '40px'; const marginHorizontal = 'auto'; switch ( device ) { diff --git a/packages/editor/src/components/visual-editor/index.js b/packages/editor/src/components/visual-editor/index.js index 88d2dac8ffd77c..4b41ca0146b5ba 100644 --- a/packages/editor/src/components/visual-editor/index.js +++ b/packages/editor/src/components/visual-editor/index.js @@ -341,7 +341,7 @@ function VisualEditor( { isZoomedOut && ! isTabletViewport ? { scale: 'default', - frameSize: '48px', + frameSize: '40px', } : {}; From b52cf1fca6d29df62a2dbbb62955ae578efa2c8a Mon Sep 17 00:00:00 2001 From: Rich Tabor <hi@richtabor.com> Date: Thu, 10 Oct 2024 14:52:20 +0200 Subject: [PATCH 1139/1908] remove border, use padding top/bottom (#66012) Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- packages/block-editor/src/components/iframe/content.scss | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss index 52210fb1e241b6..9e908da09c84f0 100644 --- a/packages/block-editor/src/components/iframe/content.scss +++ b/packages/block-editor/src/components/iframe/content.scss @@ -19,9 +19,7 @@ background-color: $gray-300; - // Firefox and Safari don't render margin-bottom here and margin-bottom is needed for Chrome - // layout, so we use border matching the background instead of margins. - border: calc(#{$frame-size} / #{$scale}) solid $gray-300; + padding: calc(#{$frame-size} / #{$scale}) 0; // Chrome seems to respect that transform scale shouldn't affect the layout size of the element, // so we need to adjust the height of the content to match the scale by using negative margins. From b06549de7eebf6a1b5f67d8465648d42f9b0a27e Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 10 Oct 2024 15:13:02 +0200 Subject: [PATCH 1140/1908] Tooltip: add aria-describedby to anchor only if not redundant (#65989) * Improve comment * Add unit tests * Add temporary storybook examples * CHANGELOG * Fix lint errors * Remove temporary storybook examples --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/tooltip/index.tsx | 9 ++- .../components/src/tooltip/test/index.tsx | 78 +++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 87fd00dd8c826d..870f96308aa462 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -4,6 +4,7 @@ ### Bug Fixes +- `Tooltip`: add `aria-describedby` to the anchor only if not redundant ([#65989](https://github.com/WordPress/gutenberg/pull/65989)). - `PaletteEdit`: dedupe palette element slugs ([#65772](https://github.com/WordPress/gutenberg/pull/65772)). - `RangeControl`: do not tooltip contents to the DOM when not shown ([#65875](https://github.com/WordPress/gutenberg/pull/65875)). - `Tabs`: fix skipping indication animation glitch ([#65878](https://github.com/WordPress/gutenberg/pull/65878)). diff --git a/packages/components/src/tooltip/index.tsx b/packages/components/src/tooltip/index.tsx index 7ce9311fc942ea..ce94daf67bfaba 100644 --- a/packages/components/src/tooltip/index.tsx +++ b/packages/components/src/tooltip/index.tsx @@ -107,9 +107,16 @@ function UnforwardedTooltip( // TODO: this is a temporary workaround to minimize the effects of the // Ariakit upgrade. Ariakit doesn't pass the `aria-describedby` prop to // the tooltip anchor anymore since 0.4.0, so we need to add it manually. + // The `aria-describedby` attribute is added only if the anchor doesn't have + // one already, and if the tooltip text is not the same as the anchor's + // `aria-label` // See: https://github.com/WordPress/gutenberg/pull/64066 + // See: https://github.com/WordPress/gutenberg/pull/65989 function addDescribedById( element: React.ReactElement ) { - return describedById && mounted + return describedById && + mounted && + element.props[ 'aria-describedby' ] === undefined && + element.props[ 'aria-label' ] !== text ? cloneElement( element, { 'aria-describedby': describedById } ) : element; } diff --git a/packages/components/src/tooltip/test/index.tsx b/packages/components/src/tooltip/test/index.tsx index 67922ab1d5ac41..3679b597b2cb14 100644 --- a/packages/components/src/tooltip/test/index.tsx +++ b/packages/components/src/tooltip/test/index.tsx @@ -516,4 +516,82 @@ describe( 'Tooltip', () => { ).not.toHaveClass( 'components-tooltip' ); } ); } ); + + describe( 'aria-describedby', () => { + it( "should not override the anchor's aria-describedby attribute if specified", async () => { + render( + <> + <Tooltip { ...props }> + <button aria-describedby="tooltip-test-description"> + Tooltip anchor + </button> + </Tooltip> + { /* eslint-disable-next-line no-restricted-syntax */ } + <p id="tooltip-test-description">Tooltip description</p> + <button>focus trap outside</button> + </> + ); + + expect( + screen.getByRole( 'button', { name: 'Tooltip anchor' } ) + ).toHaveAccessibleDescription( 'Tooltip description' ); + + // Focus the anchor, tooltip should show + await press.Tab(); + expect( + screen.getByRole( 'button', { name: 'Tooltip anchor' } ) + ).toHaveFocus(); + await waitExpectTooltipToShow(); + + // The anchors should retain its previous accessible description, + // since the tooltip shouldn't override it. + expect( + screen.getByRole( 'button', { name: 'Tooltip anchor' } ) + ).toHaveAccessibleDescription( 'Tooltip description' ); + + // Focus the other button, tooltip should hide + await press.Tab(); + expect( + screen.getByRole( 'button', { name: 'focus trap outside' } ) + ).toHaveFocus(); + await waitExpectTooltipToHide(); + } ); + + it( "should not add the aria-describedby attribute to the anchor if the tooltip text matches the anchor's aria-label", async () => { + render( + <> + <Tooltip { ...props }> + <button aria-label={ props.text }> + Tooltip anchor + </button> + </Tooltip> + <button>focus trap outside</button> + </> + ); + + expect( + screen.getByRole( 'button', { name: props.text } ) + ).not.toHaveAccessibleDescription(); + + // Focus the anchor, tooltip should show + await press.Tab(); + expect( + screen.getByRole( 'button', { name: props.text } ) + ).toHaveFocus(); + await waitExpectTooltipToShow(); + + // The anchor shouldn't have an aria-describedby prop + // because its aria-label matches the tooltip text. + expect( + screen.getByRole( 'button', { name: props.text } ) + ).not.toHaveAccessibleDescription(); + + // Focus the other button, tooltip should hide + await press.Tab(); + expect( + screen.getByRole( 'button', { name: 'focus trap outside' } ) + ).toHaveFocus(); + await waitExpectTooltipToHide(); + } ); + } ); } ); From c85370d7620bce44995746d1abe08e58344047e1 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Fri, 11 Oct 2024 01:59:37 +1100 Subject: [PATCH 1141/1908] Zoom Out: When double clicking a template while zoomed out , reset zoom level instead of showing dialog (#65963) * Zoom Out: When double clicking a template while zoomed out, reset zoom level instead of showing template editing dialog * Try reusing useZoomOutModeExit hook --- packages/block-editor/src/private-apis.js | 2 ++ .../visual-editor/edit-template-blocks-notification.js | 6 +++++- packages/editor/src/components/visual-editor/index.js | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 7205bef5798ec1..98dd326a3ebb34 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -32,6 +32,7 @@ import { usesContextKey } from './components/rich-text/format-edit'; import { ExperimentalBlockCanvas } from './components/block-canvas'; import { getDuotoneFilter } from './components/duotone/utils'; import { useFlashEditableBlocks } from './components/use-flash-editable-blocks'; +import { useZoomOutModeExit } from './components/block-list/use-block-props/use-zoom-out-mode-exit'; import { selectBlockPatternsKey, reusableBlocksSelectKey, @@ -78,6 +79,7 @@ lock( privateApis, { TextAlignmentControl, usesContextKey, useFlashEditableBlocks, + useZoomOutModeExit, globalStylesDataKey, globalStylesLinksDataKey, selectBlockPatternsKey, diff --git a/packages/editor/src/components/visual-editor/edit-template-blocks-notification.js b/packages/editor/src/components/visual-editor/edit-template-blocks-notification.js index 3ccbe79127c013..bacf1beb1abecd 100644 --- a/packages/editor/src/components/visual-editor/edit-template-blocks-notification.js +++ b/packages/editor/src/components/visual-editor/edit-template-blocks-notification.js @@ -61,7 +61,11 @@ export default function EditTemplateBlocksNotification( { contentRef } ) { ) { return; } - setIsDialogOpen( true ); + + if ( ! event.defaultPrevented ) { + event.preventDefault(); + setIsDialogOpen( true ); + } }; const canvas = contentRef.current; diff --git a/packages/editor/src/components/visual-editor/index.js b/packages/editor/src/components/visual-editor/index.js index 4b41ca0146b5ba..1528538c7ef2bd 100644 --- a/packages/editor/src/components/visual-editor/index.js +++ b/packages/editor/src/components/visual-editor/index.js @@ -48,6 +48,7 @@ const { useLayoutStyles, ExperimentalBlockCanvas: BlockCanvas, useFlashEditableBlocks, + useZoomOutModeExit, } = unlock( blockEditorPrivateApis ); /** @@ -335,6 +336,7 @@ function VisualEditor( { useSelectNearestEditableBlock( { isEnabled: renderingMode === 'template-locked', } ), + useZoomOutModeExit(), ] ); const zoomOutProps = From ced4f8ca1204fb1737faf44f46e1d27aa78d966e Mon Sep 17 00:00:00 2001 From: Maggie <maggie.cabrera@automattic.com> Date: Thu, 10 Oct 2024 17:51:44 +0200 Subject: [PATCH 1142/1908] Zoom out: fix scaling issues (#65998) * changed from using borders to use pseudo elements * added comments * Include frame size in the scaling calculation Instead of adding the frame size as a border (which causes reflow issues), include the frame size in the scaling calculation so there's always a left/right gutter of the frame size. * Account for scaling in the frame height * Calculation in CSS * Revert "Calculation in CSS" This reverts commit 38de9fc24b6ee46ae82b879416026a7f5b59c7f2. * Add comment about why the calculation for scaling needs to happen in the JS * Force px value for frameSize * Restore previous frameSize var setting * Add back line break * Use padding top/bottom instead of before/after for top/bottom frame * Remove more before/after css since we are using padding --------- Co-authored-by: Jerry Jones <jones.jeremydavid@gmail.com> Co-authored-by: Alex Lende <alex+github.com@lende.xyz> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- .../block-editor/src/components/iframe/content.scss | 10 ++++++---- packages/block-editor/src/components/iframe/index.js | 8 +++++++- packages/block-editor/src/components/iframe/style.scss | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss index 9e908da09c84f0..206f1adf329461 100644 --- a/packages/block-editor/src/components/iframe/content.scss +++ b/packages/block-editor/src/components/iframe/content.scss @@ -3,7 +3,6 @@ } .block-editor-iframe__html { - border: 0 solid $gray-300; transform-origin: top center; @include editor-canvas-resize-animation; } @@ -19,14 +18,17 @@ background-color: $gray-300; - padding: calc(#{$frame-size} / #{$scale}) 0; - // Chrome seems to respect that transform scale shouldn't affect the layout size of the element, // so we need to adjust the height of the content to match the scale by using negative margins. $extra-content-height: calc(#{$content-height} * (1 - #{$scale})); - $total-frame-height: calc(2 * #{$frame-size}); + $total-frame-height: calc(2 * #{$frame-size} / #{$scale}); $total-height: calc(#{$extra-content-height} + #{$total-frame-height} + 2px); margin-bottom: calc(-1 * #{$total-height}); + // Add the top/bottom frame size. We use scaling to account for the left/right, as + // the padding left/right causes the contents to reflow, which breaks the 1:1 scaling + // of the content. + padding-top: calc(#{$frame-size} / #{$scale}); + padding-bottom: calc(#{$frame-size} / #{$scale}); body { min-height: calc((#{$inner-height} - #{$total-frame-height}) / #{$scale}); diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index fa7ce26526f410..d234339909a5c1 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -306,13 +306,19 @@ function Iframe( { iframeDocument.documentElement.classList.add( 'is-zoomed-out' ); const maxWidth = 750; + // This scaling calculation has to happen within the JS because CSS calc() can + // only divide and multiply by a unitless value. I.e. calc( 100px / 2 ) is valid + // but calc( 100px / 2px ) is not. iframeDocument.documentElement.style.setProperty( '--wp-block-editor-iframe-zoom-out-scale', scale === 'default' - ? Math.min( containerWidth, maxWidth ) / + ? ( Math.min( containerWidth, maxWidth ) - + parseInt( frameSize ) * 2 ) / prevContainerWidthRef.current : scale ); + + // frameSize has to be a px value for the scaling and frame size to be computed correctly. iframeDocument.documentElement.style.setProperty( '--wp-block-editor-iframe-zoom-out-frame-size', typeof frameSize === 'number' ? `${ frameSize }px` : frameSize diff --git a/packages/block-editor/src/components/iframe/style.scss b/packages/block-editor/src/components/iframe/style.scss index e460df3ab3e0a9..dcddcdf0950a45 100644 --- a/packages/block-editor/src/components/iframe/style.scss +++ b/packages/block-editor/src/components/iframe/style.scss @@ -12,5 +12,6 @@ $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw); $prev-container-width: var(--wp-block-editor-iframe-zoom-out-prev-container-width, 100vw); width: $prev-container-width; + // This is to offset the movement of the iframe when we open sidebars margin-left: calc(-1 * (#{$prev-container-width} - #{$container-width}) / 2); } From 2cd6929a8aa0e904a8bb91685d7df5eb64e9bb7e Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Fri, 11 Oct 2024 10:39:37 +1100 Subject: [PATCH 1143/1908] Backport from WordPress Core: improve performance of WP_Theme_JSON::merge when merging background styles (#66002) Backporting the current state of https://github.com/WordPress/wordpress-develop/pull/7486 and adding tests. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: mukeshpanchal27 <mukesh27@git.wordpress.org> Co-authored-by: felixarntz <flixos90@git.wordpress.org> Co-authored-by: andrewserong < andrewserong@git.wordpress.org> Co-authored-by: joemcgill < joemcgill@git.wordpress.org> --- lib/class-wp-theme-json-gutenberg.php | 106 +++++++++++++++++--------- phpunit/class-wp-theme-json-test.php | 52 +++++++++++++ 2 files changed, 121 insertions(+), 37 deletions(-) diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 756ef06c80aa87..8cd83e007f37c9 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2723,9 +2723,12 @@ private static function update_separator_declarations( $declarations ) { * * @param array $theme_json The theme.json converted to an array. * @param array $selectors Optional list of selectors per block. - * @param array $options An array of options to facilitate filtering node generation - * The options currently supported are: - * - `include_block_style_variations` which includes CSS for block style variations. + * @param array $options { + * Optional. An array of options for now used for internal purposes only (may change without notice). + * + * @type bool $include_block_style_variations Includes nodes for block style variations. Default false. + * @type bool $include_node_paths_only Return only block nodes node paths. Default false. + * } * @return array The block nodes in theme.json. */ private static function get_block_nodes( $theme_json, $selectors = array(), $options = array() ) { @@ -2740,47 +2743,64 @@ private static function get_block_nodes( $theme_json, $selectors = array(), $opt return $nodes; } - foreach ( $theme_json['styles']['blocks'] as $name => $node ) { - $selector = null; - if ( isset( $selectors[ $name ]['selector'] ) ) { - $selector = $selectors[ $name ]['selector']; - } + $include_variations = $options['include_block_style_variations'] ?? false; + $include_node_paths_only = $options['include_node_paths_only'] ?? false; - $duotone_selector = null; - if ( isset( $selectors[ $name ]['duotone'] ) ) { - $duotone_selector = $selectors[ $name ]['duotone']; - } + foreach ( $theme_json['styles']['blocks'] as $name => $node ) { + $node_path = array( 'styles', 'blocks', $name ); + if ( $include_node_paths_only ) { + $nodes[] = array( + 'path' => $node_path, + ); + } else { + $selector = null; + if ( isset( $selectors[ $name ]['selector'] ) ) { + $selector = $selectors[ $name ]['selector']; + } - $feature_selectors = null; - if ( isset( $selectors[ $name ]['selectors'] ) ) { - $feature_selectors = $selectors[ $name ]['selectors']; - } + $duotone_selector = null; + if ( isset( $selectors[ $name ]['duotone'] ) ) { + $duotone_selector = $selectors[ $name ]['duotone']; + } - $variation_selectors = array(); - $include_variations = $options['include_block_style_variations'] ?? false; - if ( $include_variations && isset( $node['variations'] ) ) { - foreach ( $node['variations'] as $variation => $node ) { - $variation_selectors[] = array( - 'path' => array( 'styles', 'blocks', $name, 'variations', $variation ), - 'selector' => $selectors[ $name ]['styleVariations'][ $variation ], - ); + $feature_selectors = null; + if ( isset( $selectors[ $name ]['selectors'] ) ) { + $feature_selectors = $selectors[ $name ]['selectors']; } - } - $nodes[] = array( - 'name' => $name, - 'path' => array( 'styles', 'blocks', $name ), - 'selector' => $selector, - 'selectors' => $feature_selectors, - 'duotone' => $duotone_selector, - 'variations' => $variation_selectors, - 'css' => $selector, - ); + $variation_selectors = array(); + if ( $include_variations && isset( $node['variations'] ) ) { + foreach ( $node['variations'] as $variation => $node ) { + $variation_selectors[] = array( + 'path' => array( 'styles', 'blocks', $name, 'variations', $variation ), + 'selector' => $selectors[ $name ]['styleVariations'][ $variation ], + ); + } + } + + $nodes[] = array( + 'name' => $name, + 'path' => $node_path, + 'selector' => $selector, + 'selectors' => $feature_selectors, + 'duotone' => $duotone_selector, + 'variations' => $variation_selectors, + 'css' => $selector, + ); + } if ( isset( $theme_json['styles']['blocks'][ $name ]['elements'] ) ) { foreach ( $theme_json['styles']['blocks'][ $name ]['elements'] as $element => $node ) { + $node_path = array( 'styles', 'blocks', $name, 'elements', $element ); + if ( $include_node_paths_only ) { + $nodes[] = array( + 'path' => $node_path, + ); + continue; + } + $nodes[] = array( - 'path' => array( 'styles', 'blocks', $name, 'elements', $element ), + 'path' => $node_path, 'selector' => $selectors[ $name ]['elements'][ $element ], ); @@ -2788,8 +2808,16 @@ private static function get_block_nodes( $theme_json, $selectors = array(), $opt if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element ] ) ) { foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element ] as $pseudo_selector ) { if ( isset( $theme_json['styles']['blocks'][ $name ]['elements'][ $element ][ $pseudo_selector ] ) ) { + $node_path = array( 'styles', 'blocks', $name, 'elements', $element ); + if ( $include_node_paths_only ) { + $nodes[] = array( + 'path' => $node_path, + ); + continue; + } + $nodes[] = array( - 'path' => array( 'styles', 'blocks', $name, 'elements', $element ), + 'path' => $node_path, 'selector' => static::append_to_selector( $selectors[ $name ]['elements'][ $element ], $pseudo_selector ), ); } @@ -3264,7 +3292,11 @@ public function merge( $incoming ) { * some values provide exceptions, namely style values that are * objects and represent unique definitions for the style. */ - $style_nodes = static::get_styles_block_nodes(); + $style_nodes = static::get_block_nodes( + $this->theme_json, + array(), + array( 'include_node_paths_only' => true ) + ); foreach ( $style_nodes as $style_node ) { $path = $style_node['path']; /* diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 10bb47b87fba89..29d454f6f4f0b0 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -5726,4 +5726,56 @@ public function test_opt_in_to_block_style_variations() { $this->assertEquals( $expected, $button_variations ); } + + /** + * This test covers `get_block_nodes` with the `$include_node_paths_only` option. + * When `true`, `$include_node_paths_only` should return only the paths of the block nodes. + */ + public function test_return_block_node_paths() { + $theme_json = new ReflectionClass( 'WP_Theme_JSON_Gutenberg' ); + + $func = $theme_json->getMethod( 'get_block_nodes' ); + $func->setAccessible( true ); + + $theme_json = array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'typography' => array( + 'fontSize' => '16px', + ), + 'blocks' => array( + 'core/button' => array( + 'color' => array( + 'background' => 'red', + ), + ), + 'core/group' => array( + 'elements' => array( + 'link' => array( + 'color' => array( + 'background' => 'blue', + ), + ), + ), + ), + ), + ), + ); + + $block_nodes = $func->invoke( null, $theme_json, array(), array( 'include_node_paths_only' => true ) ); + + $expected = array( + array( + 'path' => array( 'styles', 'blocks', 'core/button' ), + ), + array( + 'path' => array( 'styles', 'blocks', 'core/group' ), + ), + array( + 'path' => array( 'styles', 'blocks', 'core/group', 'elements', 'link' ), + ), + ); + + $this->assertEquals( $expected, $block_nodes ); + } } From 5c514368f47dbae9ebb722749cd85f64725c367e Mon Sep 17 00:00:00 2001 From: Renatho De Carli Rosa <renatho@gmail.com> Date: Thu, 10 Oct 2024 21:38:54 -0300 Subject: [PATCH 1144/1908] Update z-index hierarchy (#65626) Co-authored-by: renatho <renathoc@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: allilevine <firewatch@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/base-styles/_z-index.scss | 8 +++----- packages/block-library/src/cover/editor.scss | 1 - packages/block-library/src/cover/style.scss | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index 77238c6f386084..ff61c5793e787f 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -31,12 +31,10 @@ $z-layers: ( ".interface-interface-skeleton__header": 30, ".interface-interface-skeleton__content": 20, ".edit-widgets-header": 30, - ".wp-block-cover__inner-container": 1, // InnerBlocks area inside cover image block. ".wp-block-cover.is-placeholder .components-placeholder.is-large": 1, // Cover block resizer component inside a large placeholder. - ".wp-block-cover.has-background-dim::before": 1, // Overlay area inside block cover need to be higher than the video background. - ".block-library-cover__padding-visualizer": 2, // BoxControl visualizer needs to be +1 higher than .wp-block-cover.has-background-dim::before - ".wp-block-cover__image-background": 0, // Image background inside cover block. - ".wp-block-cover__video-background": 0, // Video background inside cover block. + ".wp-block-cover.has-background-dim::before": 0, // Overlay area inside block cover need to be higher than the video background. + ".wp-block-cover__image-background": -1, // Image background inside cover block. + ".wp-block-cover__video-background": -1, // Video background inside cover block. ".wp-block-template-part__placeholder-preview-filter-input": 1, // Fixed position appender: diff --git a/packages/block-library/src/cover/editor.scss b/packages/block-library/src/cover/editor.scss index b92c401311beee..a72b928b55b970 100644 --- a/packages/block-library/src/cover/editor.scss +++ b/packages/block-library/src/cover/editor.scss @@ -42,7 +42,6 @@ // Shown while media is being uploaded .components-spinner { position: absolute; - z-index: z-index(".wp-block-cover__inner-container"); top: 50%; left: 50%; transform: translate(-50%, -50%); // Account for spinner dimensions diff --git a/packages/block-library/src/cover/style.scss b/packages/block-library/src/cover/style.scss index 41b3acf1833fc0..4b2bee7a665970 100644 --- a/packages/block-library/src/cover/style.scss +++ b/packages/block-library/src/cover/style.scss @@ -95,8 +95,8 @@ } .wp-block-cover__inner-container { + position: relative; width: 100%; - z-index: z-index(".wp-block-cover__inner-container"); color: inherit; // Reset the fixed LTR direction at the root of the block in RTL languages. /*rtl:raw: direction: rtl; */ From f083e298b761cbf608c94e3518c243d4f8d1a95e Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:54:08 +1000 Subject: [PATCH 1145/1908] Post Content: Fix display of block support styles (#66003) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: peterwilsoncc <peterwilsoncc@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> --- .../block-library/src/post-content/edit.js | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/post-content/edit.js b/packages/block-library/src/post-content/edit.js index 041a3b4fa02f61..582165303c0d05 100644 --- a/packages/block-library/src/post-content/edit.js +++ b/packages/block-library/src/post-content/edit.js @@ -8,19 +8,24 @@ import { RecursionProvider, useHasRecursion, Warning, + __experimentalUseBlockPreview as useBlockPreview, } from '@wordpress/block-editor'; +import { parse } from '@wordpress/blocks'; import { useEntityProp, useEntityBlockEditor, store as coreStore, } from '@wordpress/core-data'; import { useSelect } from '@wordpress/data'; +import { useMemo } from '@wordpress/element'; + /** * Internal dependencies */ import { useCanEditEntity } from '../utils/hooks'; function ReadOnlyContent( { + parentLayout, layoutClassNames, userCanEdit, postType, @@ -33,7 +38,28 @@ function ReadOnlyContent( { postId ); const blockProps = useBlockProps( { className: layoutClassNames } ); - return content?.protected && ! userCanEdit ? ( + const blocks = useMemo( () => { + return content?.raw ? parse( content.raw ) : []; + }, [ content?.raw ] ); + const blockPreviewProps = useBlockPreview( { + blocks, + props: blockProps, + layout: parentLayout, + } ); + + if ( userCanEdit ) { + /* + * Rendering the block preview using the raw content blocks allows for + * block support styles to be generated and applied by the editor. + * + * The preview using the raw blocks can only be presented to users with + * edit permissions for the post to prevent potential exposure of private + * block content. + */ + return <div { ...blockPreviewProps }></div>; + } + + return content?.protected ? ( <div { ...blockProps }> <Warning>{ __( 'This content is password protected.' ) }</Warning> </div> @@ -96,6 +122,7 @@ function Content( props ) { <EditableContent { ...props } /> ) : ( <ReadOnlyContent + parentLayout={ props.parentLayout } layoutClassNames={ layoutClassNames } userCanEdit={ userCanEdit } postType={ postType } @@ -141,6 +168,7 @@ function RecursionError() { export default function PostContentEdit( { context, __unstableLayoutClassNames: layoutClassNames, + __unstableParentLayout: parentLayout, } ) { const { postId: contextPostId, postType: contextPostType } = context; const hasAlreadyRendered = useHasRecursion( contextPostId ); @@ -154,6 +182,7 @@ export default function PostContentEdit( { { contextPostId && contextPostType ? ( <Content context={ context } + parentLayout={ parentLayout } layoutClassNames={ layoutClassNames } /> ) : ( From e89e988ba4a65b34357d5ee9ab78a8f6de73c35b Mon Sep 17 00:00:00 2001 From: dhruvang21 <105810308+dhruvang21@users.noreply.github.com> Date: Fri, 11 Oct 2024 09:06:47 +0530 Subject: [PATCH 1146/1908] Fix: pattern rendering issue (#66022) When navigating between the "All Patterns" tab (specifically on page 2) and the "Template Parts" tab, the patterns fail to load correctly, and a "No Results" message is displayed. This commit checks for a previous post type, and, if different, resets the pagination to page 1 to ensure the first page of new post types are shown. --------- Co-authored-by: dhruvang21 <dhruvang21@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- packages/edit-site/src/components/page-patterns/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index be3bb7429c32f9..69ebf66093806a 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -78,6 +78,7 @@ export default function DataviewsPatterns() { const categoryId = categoryIdFromURL || PATTERN_DEFAULT_CATEGORY; const [ view, setView ] = useState( DEFAULT_VIEW ); const previousCategoryId = usePrevious( categoryId ); + const previousPostType = usePrevious( type ); const viewSyncStatus = view.filters?.find( ( { field } ) => field === 'sync-status' )?.value; @@ -121,10 +122,10 @@ export default function DataviewsPatterns() { // Reset the page number when the category changes. useEffect( () => { - if ( previousCategoryId !== categoryId ) { + if ( previousCategoryId !== categoryId || previousPostType !== type ) { setView( ( prevView ) => ( { ...prevView, page: 1 } ) ); } - }, [ categoryId, previousCategoryId ] ); + }, [ categoryId, previousCategoryId, previousPostType, type ] ); const { data, paginationInfo } = useMemo( () => { // Search is managed server-side as well as filters for patterns. // However, the author filter in template parts is done client-side. From e24356a056a5030a8d839dd6540cb76fd454e1a2 Mon Sep 17 00:00:00 2001 From: Maggie <maggie.cabrera@automattic.com> Date: Fri, 11 Oct 2024 11:08:34 +0200 Subject: [PATCH 1147/1908] Zoom out: e2e test - zoomed out mode zooms the canvas (#65943) * removed outdated e2 tests and added a new one * Update test/e2e/specs/site-editor/zoom-out.spec.js Co-authored-by: Daniel Richards <daniel.richards@automattic.com> * fixed canvas selector * check the size of the iframe after scaling * check if the canvas is separated * reformat comments * updated test after rebasing trunk with latest changes * recalculate the position using padding instead of border --------- Co-authored-by: Daniel Richards <daniel.richards@automattic.com> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- test/e2e/specs/site-editor/zoom-out.spec.js | 80 ++++++++------------- 1 file changed, 30 insertions(+), 50 deletions(-) diff --git a/test/e2e/specs/site-editor/zoom-out.spec.js b/test/e2e/specs/site-editor/zoom-out.spec.js index 53b777a2545a34..6ede9014d2a303 100644 --- a/test/e2e/specs/site-editor/zoom-out.spec.js +++ b/test/e2e/specs/site-editor/zoom-out.spec.js @@ -3,65 +3,45 @@ */ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); -// The test is flaky and fails almost consistently. -// See: https://github.com/WordPress/gutenberg/issues/61806. -// eslint-disable-next-line playwright/no-skipped-test -test.describe.skip( 'Zoom Out', () => { +test.describe( 'Zoom Out', () => { test.beforeAll( async ( { requestUtils } ) => { - await requestUtils.activateTheme( 'emptytheme' ); + await requestUtils.activateTheme( 'twentytwentyfour' ); } ); - test.beforeEach( async ( { admin, editor, page } ) => { - await admin.visitAdminPage( 'admin.php', 'page=gutenberg-experiments' ); - - const zoomedOutCheckbox = page.getByLabel( - 'Enable zoomed out view when selecting a pattern category in the main inserter.' - ); - - await zoomedOutCheckbox.setChecked( true ); - await expect( zoomedOutCheckbox ).toBeChecked(); - await page.getByRole( 'button', { name: 'Save Changes' } ).click(); + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentyone' ); + } ); + test.beforeEach( async ( { admin, editor } ) => { await admin.visitSiteEditor(); await editor.canvas.locator( 'body' ).click(); } ); - test.afterEach( async ( { admin, page } ) => { - await admin.visitAdminPage( 'admin.php', 'page=gutenberg-experiments' ); - const zoomedOutCheckbox = page.getByLabel( - 'Enable zoomed out view when selecting a pattern category in the main inserter.' - ); - await zoomedOutCheckbox.setChecked( false ); - await expect( zoomedOutCheckbox ).not.toBeChecked(); - await page.getByRole( 'button', { name: 'Save Changes' } ).click(); - } ); - - test.afterAll( async ( { requestUtils } ) => { - await requestUtils.activateTheme( 'twentytwentyone' ); - } ); - - test( 'Clicking on inserter while on zoom-out should open the patterns tab on the inserter', async ( { + test( 'Entering zoomed out mode zooms the canvas', async ( { page, + editor, } ) => { - // Trigger zoom out on Global Styles because there the inserter is not open. - await page.getByRole( 'button', { name: 'Styles' } ).click(); - await page.getByRole( 'button', { name: 'Browse styles' } ).click(); - - // select the 1st pattern - await page - .frameLocator( 'iframe[name="editor-canvas"]' ) - .locator( 'header' ) - .click(); - - await expect( page.getByLabel( 'Add pattern' ) ).toHaveCount( 3 ); - await page.getByLabel( 'Add pattern' ).first().click(); - await expect( page.getByLabel( 'Add pattern' ) ).toHaveCount( 2 ); - - await expect( - page - .locator( '#tabs-2-allPatterns-view div' ) - .filter( { hasText: 'All' } ) - .nth( 1 ) - ).toBeVisible(); + await page.getByLabel( 'Zoom Out' ).click(); + const iframe = page.locator( 'iframe[name="editor-canvas"]' ); + const html = editor.canvas.locator( 'html' ); + + // Check that the html is scaled. + await expect( html ).toHaveCSS( + 'transform', + 'matrix(0.67, 0, 0, 0.67, 0, 0)' + ); + const iframeRect = await iframe.boundingBox(); + const htmlRect = await html.boundingBox(); + + // Check that the iframe is larger than the html. + expect( iframeRect.width ).toBeGreaterThan( htmlRect.width ); + + // Check that the zoomed out content has a frame around it. + const paddingTop = await html.evaluate( ( element ) => { + const paddingValue = window.getComputedStyle( element ).paddingTop; + return parseFloat( paddingValue ); + } ); + expect( htmlRect.y + paddingTop ).toBeGreaterThan( iframeRect.y ); + expect( htmlRect.x ).toBeGreaterThan( iframeRect.x ); } ); } ); From b6c321fff86f132347dac1abe0a7af525eebfe8e Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Fri, 11 Oct 2024 11:10:11 +0200 Subject: [PATCH 1148/1908] Interactivity: Update preact packages (#66008) * Update preact packages * Update package-lock * Fix some EffectFn types * Remove outdated ts-expect-error * Add changelog Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- package-lock.json | 61 +++++++++++++++-------------- packages/interactivity/CHANGELOG.md | 4 ++ packages/interactivity/package.json | 4 +- packages/interactivity/src/utils.ts | 4 +- packages/interactivity/src/vdom.ts | 1 - 5 files changed, 40 insertions(+), 34 deletions(-) diff --git a/package-lock.json b/package-lock.json index c240bfd1784377..14b24167aa0a7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7260,10 +7260,27 @@ "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==", "dev": true }, + "node_modules/@preact/signals": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@preact/signals/-/signals-1.3.0.tgz", + "integrity": "sha512-EOMeg42SlLS72dhoq6Vjq08havnLseWmPQ8A0YsgIAqMgWgx7V1a39+Pxo6i7SY5NwJtH4849JogFq3M67AzWg==", + "license": "MIT", + "dependencies": { + "@preact/signals-core": "^1.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "preact": "10.x" + } + }, "node_modules/@preact/signals-core": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.4.0.tgz", - "integrity": "sha512-5iYoZBhELLIhUQceZI7sDTQWPb+xcVSn2qk8T/aNl/VMh+A4AiPX9YRSh4XO7fZ6pncrVxl1Iln82poVqYVbbw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.8.0.tgz", + "integrity": "sha512-OBvUsRZqNmjzCZXWLxkZfhcgT+Fk8DDcT/8vD6a1xhDemodyy87UJRJfASMuSD8FaAIeGgGm85ydXhm7lr4fyA==", + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -42094,6 +42111,16 @@ "node": ">=0.10.0" } }, + "node_modules/preact": { + "version": "10.24.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.2.tgz", + "integrity": "sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/prebuild-install": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", @@ -55663,8 +55690,8 @@ "version": "6.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@preact/signals": "^1.2.2", - "preact": "^10.19.3" + "@preact/signals": "^1.3.0", + "preact": "^10.24.2" }, "engines": { "node": ">=18.12.0", @@ -55684,30 +55711,6 @@ "npm": ">=8.19.2" } }, - "packages/interactivity/node_modules/@preact/signals": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@preact/signals/-/signals-1.2.2.tgz", - "integrity": "sha512-ColCqdo4cRP18bAuIR4Oik5rDpiyFtPIJIygaYPMEAwTnl4buWkBOflGBSzhYyPyJfKpkwlekrvK+1pzQ2ldWw==", - "dependencies": { - "@preact/signals-core": "^1.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" - }, - "peerDependencies": { - "preact": "10.x" - } - }, - "packages/interactivity/node_modules/preact": { - "version": "10.19.3", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.3.tgz", - "integrity": "sha512-nHHTeFVBTHRGxJXKkKu5hT8C/YWBkPso4/Gad6xuj5dbptt9iF9NZr9pHbPhBrnT2klheu7mHTxTZ/LjwJiEiQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" - } - }, "packages/interface": { "name": "@wordpress/interface", "version": "6.9.0", diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 7a510bd89b0f78..be6bdeefe81e0d 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Internal + +- Upgrade preact libraries [#66008](https://github.com/WordPress/gutenberg/pull/66008). + ### Bug Fixes - Fix an issue where "default" could not be used as a directive suffix ([#65815](https://github.com/WordPress/gutenberg/pull/65815)). diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 417ec8a2d337ba..2519e983e93446 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -31,8 +31,8 @@ "./debug": "./build-module/debug.js" }, "dependencies": { - "@preact/signals": "^1.2.2", - "preact": "^10.19.3" + "@preact/signals": "^1.3.0", + "preact": "^10.24.2" }, "publishConfig": { "access": "public" diff --git a/packages/interactivity/src/utils.ts b/packages/interactivity/src/utils.ts index c5eb91681294f2..4f10ed517de502 100644 --- a/packages/interactivity/src/utils.ts +++ b/packages/interactivity/src/utils.ts @@ -67,9 +67,9 @@ export const splitTask = () => { * @param notify The function that notifies listeners when the value is flushed. * @return The Flusher object with `flush` and `dispose` properties. */ -function createFlusher( compute: () => unknown, notify: () => void ): Flusher { +function createFlusher( compute: () => void, notify: () => void ): Flusher { let flush: () => void = () => undefined; - const dispose = effect( function ( this: any ) { + const dispose = effect( function ( this: any ): void { flush = this.c.bind( this ); this.x = compute; this.c = notify; diff --git a/packages/interactivity/src/vdom.ts b/packages/interactivity/src/vdom.ts index b533a130e4a6f0..9a1ec7ec5d76f0 100644 --- a/packages/interactivity/src/vdom.ts +++ b/packages/interactivity/src/vdom.ts @@ -161,7 +161,6 @@ export function toVdom( root: Node ): Array< ComponentChild > { }, {} ); } - // @ts-expect-error Fixed in upcoming preact release https://github.com/preactjs/preact/pull/4334 if ( localName === 'template' ) { props.content = [ ...( elementNode as HTMLTemplateElement ).content.childNodes, From 4f3da917d2991b6e2cb08bf9ee72b1c2b07a6bc0 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu <me@andreidraganescu.info> Date: Fri, 11 Oct 2024 14:01:42 +0300 Subject: [PATCH 1149/1908] Always preview style variations using desktop device type (#66023) * always preview style variations using desktop device type * Improve comment --------- Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: juanfra <juanfra@git.wordpress.org> --- .../components/global-styles/screen-style-variations.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/screen-style-variations.js b/packages/edit-site/src/components/global-styles/screen-style-variations.js index 4fefbe39ac55ce..70727ac6698801 100644 --- a/packages/edit-site/src/components/global-styles/screen-style-variations.js +++ b/packages/edit-site/src/components/global-styles/screen-style-variations.js @@ -4,6 +4,8 @@ import { Card, CardBody } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useZoomOut } from '@wordpress/block-editor'; +import { useDispatch } from '@wordpress/data'; +import { store as editorStore } from '@wordpress/editor'; /** * Internal dependencies @@ -12,9 +14,12 @@ import ScreenHeader from './header'; import SidebarNavigationScreenGlobalStylesContent from '../sidebar-navigation-screen-global-styles/content'; function ScreenStyleVariations() { - // Move to zoom out mode when this component is mounted - // and back to the previous mode when unmounted. + // Style Variations should only be previewed in with + // - a "zoomed out" editor + // - "Desktop" device preview + const { setDeviceType } = useDispatch( editorStore ); useZoomOut(); + setDeviceType( 'desktop' ); return ( <> From 26dfcb9db7263ed397a30d499ef1025fc13f1112 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:49:00 +0300 Subject: [PATCH 1150/1908] Block Editor: Cleanup AutoBlockPreview render memoization of BlockList (#66060) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: sgomes <sergiomdgomes@git.wordpress.org> --- packages/block-editor/src/components/block-preview/auto.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/block-preview/auto.js b/packages/block-editor/src/components/block-preview/auto.js index 0f04a68dd61a82..835f379c09b987 100644 --- a/packages/block-editor/src/components/block-preview/auto.js +++ b/packages/block-editor/src/components/block-preview/auto.js @@ -15,7 +15,7 @@ import EditorStyles from '../editor-styles'; import { store } from '../../store'; // This is used to avoid rendering the block list if the sizes change. -let MemoizedBlockList; +const MemoizedBlockList = memo( BlockList ); const MAX_HEIGHT = 2000; const EMPTY_ADDITIONAL_STYLES = []; @@ -55,9 +55,6 @@ function ScaledBlockPreview( { return styles; }, [ styles, additionalStyles ] ); - // Initialize on render instead of module top level, to avoid circular dependency issues. - MemoizedBlockList = MemoizedBlockList || memo( BlockList ); - const scale = containerWidth / viewportWidth; const aspectRatio = contentHeight ? containerWidth / ( contentHeight * scale ) From b6c9a4227155d683dc48b3325ae7a0709e98a5c5 Mon Sep 17 00:00:00 2001 From: Nick Diego <nick.diego@automattic.com> Date: Fri, 11 Oct 2024 14:57:25 -0500 Subject: [PATCH 1151/1908] Add heading level curation documentation (#66076) * Add heading level curation documentation. Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: ryanwelcher <welcher@git.wordpress.org> --- .../disable-editor-functionality.md | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/how-to-guides/curating-the-editor-experience/disable-editor-functionality.md b/docs/how-to-guides/curating-the-editor-experience/disable-editor-functionality.md index ce8478f0241319..a20d2cf9d8b8a7 100644 --- a/docs/how-to-guides/curating-the-editor-experience/disable-editor-functionality.md +++ b/docs/how-to-guides/curating-the-editor-experience/disable-editor-functionality.md @@ -6,6 +6,37 @@ This page is dedicated to the many ways you can disable specific functionality i There might be times when you don’t want access to a block at all to be available for users. To control what’s available in the inserter, you can take two approaches: [an allow list](/docs/reference-guides/filters/block-filters.md#using-an-allow-list) that disables all blocks except those on the list or a [deny list that unregisters specific blocks](/docs/reference-guides/filters/block-filters.md#using-a-deny-list). +## Curate heading levels + +Core WordPress blocks with a heading level dropdown include support for the `levelOptions` attribute. This applies to the Heading, Site Title, Site Tagline, Query Title, Post Title, and Comments Title blocks. The `levelOptions` attribute accepts an array of numbers corresponding to heading levels, where `1` represents H1, `2` represents H2, and so on. + +This attribute allows you to specify which heading levels should appear in the dropdown UI, providing a lightweight curation method that does not require block deprecations. Any existing heading levels are preserved in the markup, while `levelOptions` only affects the UI display. + +You can apply this attribute directly in the block markup, a technique that will be commonly used in block templates, template parts, and patterns. For example, the following markup disables H1, H2, and H6 in the Heading block by setting `"levelOptions":[3,4,5]`. + +```html +<!-- wp:heading {"level":3,"levelOptions":[3,4,5],"className":"wp-block-heading"} --> +<h3 class="wp-block-heading">Markup example</h3> +<!-- /wp:heading --> +``` + +You can also use [block filters](/docs/reference-guides/filters/block-filters.md) to set the default value of this attribute globally or for specific blocks. The example below disables H1, H2, and H6 for all Heading blocks. You can further customize this by restricting certain heading levels based on conditions like user capabilities. + +```php +function example_modify_heading_levels_globally( $args, $block_type ) { + + if ( 'core/heading' !== $block_type ) { + return $args; + } + + // Remove H1, H2, and H6. + $args['attributes']['levelOptions']['default'] = [ 3, 4, 5 ]; + + return $args; +} +add_filter( 'register_block_type_args', 'example_modify_heading_levels_globally', 10, 2 ); +``` + ## Disable the Pattern Directory To fully remove patterns bundled with WordPress core from being accessed in the Inserter, the following can be added to your `functions.php` file: From ad6e1300a579fd9f8efce4c91f97d4c705aca4c1 Mon Sep 17 00:00:00 2001 From: Sarah Norris <1645628+mikachan@users.noreply.github.com> Date: Sat, 12 Oct 2024 07:31:38 +0100 Subject: [PATCH 1152/1908] Query Loop: Fix isControlAllowed and isTemplate combined logic (#65984) * Fix isControlAllowed and isTemplate logic * Remove isTemplate check when inherit is already being checked Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: daviedR <daviedr@git.wordpress.org> --- .../src/query/edit/inspector-controls/index.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index 28a6113620fb7c..b373e0933fe718 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -123,21 +123,18 @@ export default function QueryInspectorControls( props ) { const showInheritControl = isTemplate && isControlAllowed( allowedControls, 'inherit' ); const showPostTypeControl = - ( ! inherit && isControlAllowed( allowedControls, 'postType' ) ) || - ! isTemplate; + ! inherit && isControlAllowed( allowedControls, 'postType' ); const postTypeControlLabel = __( 'Post type' ); const postTypeControlHelp = __( 'Select the type of content to display: posts, pages, or custom post types.' ); const showColumnsControl = false; const showOrderControl = - ( ! inherit && isControlAllowed( allowedControls, 'order' ) ) || - ! isTemplate; + ! inherit && isControlAllowed( allowedControls, 'order' ); const showStickyControl = - ( ! inherit && - showSticky && - isControlAllowed( allowedControls, 'sticky' ) ) || - ( showSticky && ! isTemplate ); + ! inherit && + showSticky && + isControlAllowed( allowedControls, 'sticky' ); const showSettingsPanel = showInheritControl || showPostTypeControl || From fa8b36fb1406dd27528c9f8a0385a5e0d31fcc25 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Sat, 12 Oct 2024 21:43:17 +0200 Subject: [PATCH 1153/1908] Write/Design tool: Persist as a user preference (#65945) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/block-editor/src/store/actions.js | 5 +++-- packages/block-editor/src/store/reducer.js | 17 ----------------- packages/block-editor/src/store/selectors.js | 11 +++++++---- .../src/store/test/private-selectors.js | 8 +++++++- .../block-editor/src/store/test/selectors.js | 15 +++++++++++++-- packages/edit-site/src/store/private-actions.js | 3 --- .../reusable-blocks/src/store/test/actions.js | 2 ++ 7 files changed, 32 insertions(+), 29 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index ee11838395ec5c..d92f8bc08569dc 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -21,6 +21,7 @@ import { __, _n, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; import { create, insert, remove, toHTMLString } from '@wordpress/rich-text'; import deprecated from '@wordpress/deprecated'; +import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies @@ -1668,7 +1669,7 @@ export const setNavigationMode = */ export const __unstableSetEditorMode = ( mode ) => - ( { dispatch, select } ) => { + ( { dispatch, select, registry } ) => { // When switching to zoom-out mode, we need to select the parent section if ( mode === 'zoom-out' ) { const firstSelectedClientId = select.getBlockSelectionStart(); @@ -1708,7 +1709,7 @@ export const __unstableSetEditorMode = } } - dispatch( { type: 'SET_EDITOR_MODE', mode } ); + registry.dispatch( preferencesStore ).set( 'core', 'editorTool', mode ); if ( mode === 'navigation' ) { speak( diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index f6445f8a3681c9..1435e815813c46 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1786,22 +1786,6 @@ export const blockListSettings = ( state = {}, action ) => { return state; }; -/** - * Reducer returning which mode is enabled. - * - * @param {string} state Current state. - * @param {Object} action Dispatched action. - * - * @return {string} Updated state. - */ -export function editorMode( state = 'edit', action ) { - if ( action.type === 'SET_EDITOR_MODE' ) { - return action.mode; - } - - return state; -} - /** * Reducer return an updated state representing the most recent block attribute * update. The state is structured as an object where the keys represent the @@ -2117,7 +2101,6 @@ const combinedReducers = combineReducers( { preferences, lastBlockAttributesChange, lastFocus, - editorMode, expandedBlock, highlightedBlock, lastBlockInserted, diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 6cf6aae296141f..a81d88de33466d 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -16,6 +16,7 @@ import { symbol } from '@wordpress/icons'; import { create, remove, toHTMLString } from '@wordpress/rich-text'; import deprecated from '@wordpress/deprecated'; import { createSelector, createRegistrySelector } from '@wordpress/data'; +import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies @@ -2691,7 +2692,7 @@ export function __experimentalGetLastBlockAttributeChanges( state ) { * @return {boolean} Is navigation mode enabled. */ export function isNavigationMode( state ) { - return state.editorMode === 'navigation'; + return __unstableGetEditorMode( state ) === 'navigation'; } /** @@ -2701,9 +2702,11 @@ export function isNavigationMode( state ) { * * @return {string} the editor mode. */ -export function __unstableGetEditorMode( state ) { - return state.editorMode; -} +export const __unstableGetEditorMode = createRegistrySelector( + ( select ) => () => { + return select( preferencesStore ).get( 'core', 'editorTool' ); + } +); /** * Returns whether block moving mode is enabled. diff --git a/packages/block-editor/src/store/test/private-selectors.js b/packages/block-editor/src/store/test/private-selectors.js index cbb75daa4baaa0..73c14faa6fd065 100644 --- a/packages/block-editor/src/store/test/private-selectors.js +++ b/packages/block-editor/src/store/test/private-selectors.js @@ -11,7 +11,7 @@ import { isDragging, getBlockStyles, } from '../private-selectors'; -import { getBlockEditingMode } from '../selectors'; +import { getBlockEditingMode, __unstableGetEditorMode } from '../selectors'; describe( 'private selectors', () => { describe( 'isBlockInterfaceHidden', () => { @@ -125,11 +125,17 @@ describe( 'private selectors', () => { }; const hasContentRoleAttribute = jest.fn( () => false ); + const get = jest.fn( () => 'edit' ); getBlockEditingMode.registry = { select: jest.fn( () => ( { hasContentRoleAttribute, } ) ), }; + __unstableGetEditorMode.registry = { + select: jest.fn( () => ( { + get, + } ) ), + }; it( 'should return false when top level block is not disabled', () => { const state = { diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index a08c2e0dde1508..00aa085f667093 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -9,6 +9,7 @@ import { import { RawHTML } from '@wordpress/element'; import { symbol } from '@wordpress/icons'; import { select, dispatch } from '@wordpress/data'; +import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies @@ -4470,7 +4471,6 @@ describe( 'getBlockEditingMode', () => { const navigationModeStateWithRootSection = { ...baseState, - editorMode: 'navigation', settings: { [ sectionRootClientIdKey ]: 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', // The group is the "main" container }, @@ -4480,12 +4480,18 @@ describe( 'getBlockEditingMode', () => { const fauxPrivateAPIs = {}; - lock( fauxPrivateAPIs, { hasContentRoleAttribute } ); + lock( fauxPrivateAPIs, { + hasContentRoleAttribute, + } ); getBlockEditingMode.registry = { select: jest.fn( () => fauxPrivateAPIs ), }; + afterEach( () => { + dispatch( preferencesStore ).set( 'core', 'editorTool', undefined ); + } ); + it( 'should return default by default', () => { expect( getBlockEditingMode( @@ -4610,6 +4616,7 @@ describe( 'getBlockEditingMode', () => { } ); it( 'in navigation mode, the root section container is default', () => { + dispatch( preferencesStore ).set( 'core', 'editorTool', 'navigation' ); expect( getBlockEditingMode( navigationModeStateWithRootSection, @@ -4619,6 +4626,7 @@ describe( 'getBlockEditingMode', () => { } ); it( 'in navigation mode, anything outside the section container is disabled', () => { + dispatch( preferencesStore ).set( 'core', 'editorTool', 'navigation' ); expect( getBlockEditingMode( navigationModeStateWithRootSection, @@ -4628,6 +4636,7 @@ describe( 'getBlockEditingMode', () => { } ); it( 'in navigation mode, sections are contentOnly', () => { + dispatch( preferencesStore ).set( 'core', 'editorTool', 'navigation' ); expect( getBlockEditingMode( navigationModeStateWithRootSection, @@ -4643,6 +4652,7 @@ describe( 'getBlockEditingMode', () => { } ); it( 'in navigation mode, blocks with content attributes within sections are contentOnly', () => { + dispatch( preferencesStore ).set( 'core', 'editorTool', 'navigation' ); hasContentRoleAttribute.mockReturnValueOnce( true ); expect( getBlockEditingMode( @@ -4661,6 +4671,7 @@ describe( 'getBlockEditingMode', () => { } ); it( 'in navigation mode, blocks without content attributes within sections are disabled', () => { + dispatch( preferencesStore ).set( 'core', 'editorTool', 'navigation' ); expect( getBlockEditingMode( navigationModeStateWithRootSection, diff --git a/packages/edit-site/src/store/private-actions.js b/packages/edit-site/src/store/private-actions.js index 37164690ed7fca..94bcc490b6fd60 100644 --- a/packages/edit-site/src/store/private-actions.js +++ b/packages/edit-site/src/store/private-actions.js @@ -19,9 +19,6 @@ export const setCanvasMode = registry.batch( () => { registry.dispatch( blockEditorStore ).clearSelectedBlock(); registry.dispatch( editorStore ).setDeviceType( 'Desktop' ); - registry - .dispatch( blockEditorStore ) - .__unstableSetEditorMode( 'edit' ); const isPublishSidebarOpened = registry .select( editorStore ) .isPublishSidebarOpened(); diff --git a/packages/reusable-blocks/src/store/test/actions.js b/packages/reusable-blocks/src/store/test/actions.js index b2feae1195ee1d..debd6568683891 100644 --- a/packages/reusable-blocks/src/store/test/actions.js +++ b/packages/reusable-blocks/src/store/test/actions.js @@ -12,6 +12,7 @@ import { import { store as coreStore } from '@wordpress/core-data'; import apiFetch from '@wordpress/api-fetch'; +import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies @@ -31,6 +32,7 @@ function createRegistryWithStores() { registry.register( blockEditorStore ); registry.register( reusableBlocksStore ); registry.register( blocksStore ); + registry.register( preferencesStore ); // Register entity here instead of mocking API handlers for loadPostTypeEntities() registry.dispatch( coreStore ).addEntities( [ From 0e587d5fdcfe0392161f2c8f25cc9eaf2ff86b2a Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 14 Oct 2024 12:43:45 +1000 Subject: [PATCH 1154/1908] Editor: Prevent wrapping text when showing icon labels in header (#66038) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- packages/editor/src/components/header/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/editor/src/components/header/style.scss b/packages/editor/src/components/header/style.scss index 8712121fff3ea6..4259ef4b8a2084 100644 --- a/packages/editor/src/components/header/style.scss +++ b/packages/editor/src/components/header/style.scss @@ -130,6 +130,7 @@ // ... and display labels. &::after { content: attr(aria-label); + white-space: nowrap; } &[aria-disabled="true"] { background-color: transparent; From 7b29bb31d4aa607d9a789f6371a4e07128cd4834 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Mon, 14 Oct 2024 08:42:17 +0200 Subject: [PATCH 1155/1908] Zoom layout shift: second alternate fix. (#66041) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- packages/block-editor/src/components/iframe/content.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss index 206f1adf329461..069274e66bdfd0 100644 --- a/packages/block-editor/src/components/iframe/content.scss +++ b/packages/block-editor/src/components/iframe/content.scss @@ -1,5 +1,6 @@ .block-editor-iframe__body { position: relative; + border: 0.01px solid transparent; } .block-editor-iframe__html { @@ -32,8 +33,6 @@ body { min-height: calc((#{$inner-height} - #{$total-frame-height}) / #{$scale}); - display: flex; - flex-direction: column; > .is-root-container:not(.wp-block-post-content) { flex: 1; From 25048e3b67c46b1d376f9f018f55576821e301cd Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Mon, 14 Oct 2024 14:54:07 +0800 Subject: [PATCH 1156/1908] Hide grid visualizer when grid is template locked or block editing mode is not default (#66065) Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: bph <bph@git.wordpress.org> * Hide grid visualizer when template locked or block editing mode is not default * Remove unlocks --- .../block-editor/src/hooks/grid-visualizer.js | 32 ++++++++---- .../block-editor/src/hooks/layout-child.js | 51 +++++++++++++++++-- 2 files changed, 71 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/hooks/grid-visualizer.js b/packages/block-editor/src/hooks/grid-visualizer.js index 44102208c4d1d4..26650c85ea5094 100644 --- a/packages/block-editor/src/hooks/grid-visualizer.js +++ b/packages/block-editor/src/hooks/grid-visualizer.js @@ -16,20 +16,34 @@ function GridLayoutSync( props ) { } function GridTools( { clientId, layout } ) { - const { isSelected, isDragging } = useSelect( ( select ) => { - const { isBlockSelected, isDraggingBlocks } = - select( blockEditorStore ); + const isVisible = useSelect( + ( select ) => { + const { + isBlockSelected, + isDraggingBlocks, + getTemplateLock, + getBlockEditingMode, + } = select( blockEditorStore ); - return { - isSelected: isBlockSelected( clientId ), - isDragging: isDraggingBlocks(), - }; - } ); + // These calls are purposely ordered from least expensive to most expensive. + // Hides the visualizer in cases where the user is not or cannot interact with it. + if ( + ( ! isDraggingBlocks() && ! isBlockSelected( clientId ) ) || + getTemplateLock( clientId ) || + getBlockEditingMode( clientId ) !== 'default' + ) { + return false; + } + + return true; + }, + [ clientId ] + ); return ( <> <GridLayoutSync clientId={ clientId } /> - { ( isSelected || isDragging ) && ( + { isVisible && ( <GridVisualizer clientId={ clientId } parentLayout={ layout } /> ) } </> diff --git a/packages/block-editor/src/hooks/layout-child.js b/packages/block-editor/src/hooks/layout-child.js index 558d5e2cc626bf..7a8e039c689690 100644 --- a/packages/block-editor/src/hooks/layout-child.js +++ b/packages/block-editor/src/hooks/layout-child.js @@ -175,9 +175,54 @@ function ChildLayoutControlsPure( { clientId, style, setAttributes } ) { isManualPlacement, } = parentLayout; - const rootClientId = useSelect( + if ( parentLayoutType !== 'grid' ) { + return null; + } + + return ( + <GridTools + clientId={ clientId } + style={ style } + setAttributes={ setAttributes } + allowSizingOnChildren={ allowSizingOnChildren } + isManualPlacement={ isManualPlacement } + parentLayout={ parentLayout } + /> + ); +} + +function GridTools( { + clientId, + style, + setAttributes, + allowSizingOnChildren, + isManualPlacement, + parentLayout, +} ) { + const { rootClientId, isVisible } = useSelect( ( select ) => { - return select( blockEditorStore ).getBlockRootClientId( clientId ); + const { + getBlockRootClientId, + getBlockEditingMode, + getTemplateLock, + } = select( blockEditorStore ); + + const _rootClientId = getBlockRootClientId( clientId ); + + if ( + getTemplateLock( _rootClientId ) || + getBlockEditingMode( _rootClientId ) !== 'default' + ) { + return { + rootClientId: _rootClientId, + isVisible: false, + }; + } + + return { + rootClientId: _rootClientId, + isVisible: true, + }; }, [ clientId ] ); @@ -185,7 +230,7 @@ function ChildLayoutControlsPure( { clientId, style, setAttributes } ) { // Use useState() instead of useRef() so that GridItemResizer updates when ref is set. const [ resizerBounds, setResizerBounds ] = useState(); - if ( parentLayoutType !== 'grid' ) { + if ( ! isVisible ) { return null; } From 27b86b2a447ebc9f1f3541c86cd2cce475744a2d Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 14 Oct 2024 16:42:38 +0900 Subject: [PATCH 1157/1908] Fix e2e Storybook config (#66089) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- test/storybook-playwright/storybook/main.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/storybook-playwright/storybook/main.js b/test/storybook-playwright/storybook/main.js index e3023f844da2db..b80833ca725f96 100644 --- a/test/storybook-playwright/storybook/main.js +++ b/test/storybook-playwright/storybook/main.js @@ -7,6 +7,7 @@ const config = { ...baseConfig, addons: [ '@storybook/addon-toolbars' ], docs: undefined, + staticDirs: undefined, stories: [ '../../../packages/components/src/**/stories/e2e/*.story.@(js|tsx|mdx)', ], From ca9857ec13f97ff75fdc83dba3cb00e5630d45b7 Mon Sep 17 00:00:00 2001 From: Vrishabh Jasani <71686151+Vrishabhsk@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:41:12 +0400 Subject: [PATCH 1158/1908] Fix : Secondary Button Transition (#66045) * Modify box-shadow to allow transition delay * Replace hex with * Replace $black with currentColor * Update changelog --------- Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Co-authored-by: Vrishabhsk <vrishabhsk@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/button/style.scss | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 870f96308aa462..6d3714d9cb5db6 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -9,6 +9,7 @@ - `RangeControl`: do not tooltip contents to the DOM when not shown ([#65875](https://github.com/WordPress/gutenberg/pull/65875)). - `Tabs`: fix skipping indication animation glitch ([#65878](https://github.com/WordPress/gutenberg/pull/65878)). - `ToggleGroupControl`: Don't autoselect option on first group focus ([#65892](https://github.com/WordPress/gutenberg/pull/65892)). +- `Button`: fix `box-shadow` transition for secondary variation ([#66045](https://github.com/WordPress/gutenberg/pull/66045)). ### Deprecations diff --git a/packages/components/src/button/style.scss b/packages/components/src/button/style.scss index 444e4d397b3ef8..61455a54e26f6b 100644 --- a/packages/components/src/button/style.scss +++ b/packages/components/src/button/style.scss @@ -133,7 +133,7 @@ */ &.is-secondary { - box-shadow: inset 0 0 0 $border-width $components-color-accent; + box-shadow: inset 0 0 0 $border-width $components-color-accent, 0 0 0 currentColor; outline: 1px solid transparent; // Shown in high contrast mode. white-space: nowrap; color: $components-color-accent; @@ -148,6 +148,10 @@ &[aria-disabled="true"]:hover:not(:focus) { box-shadow: inset 0 0 0 $border-width $gray-300; } + + &:focus:not(:disabled) { + box-shadow: 0 0 0 currentColor inset, 0 0 0 var(--wp-admin-border-width-focus) $components-color-accent; + } } /** From b6bd15e42f60c76dc1213be59eeb18b7b572d8ca Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Mon, 14 Oct 2024 13:29:04 +0200 Subject: [PATCH 1159/1908] Improve PostURL terminology and accessibility (#63669) * Improve PostURL terminology and accessibility. * Restore createInterpolateElement after rebase. * Remove value truncation after PR 64053. * Replace term URL with Permalink. * Reduce post url intro text top margin. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: joedolson <joedolson@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../editor/src/components/post-url/index.js | 122 ++++++++++-------- .../editor/src/components/post-url/panel.js | 90 ++++++++----- .../editor/src/components/post-url/style.scss | 24 +++- 3 files changed, 145 insertions(+), 91 deletions(-) diff --git a/packages/editor/src/components/post-url/index.js b/packages/editor/src/components/post-url/index.js index 8d072fa2eeb5d2..c7dc5712dcac4a 100644 --- a/packages/editor/src/components/post-url/index.js +++ b/packages/editor/src/components/post-url/index.js @@ -17,7 +17,7 @@ import { import { store as noticesStore } from '@wordpress/notices'; import { copySmall } from '@wordpress/icons'; import { store as coreStore } from '@wordpress/core-data'; -import { useCopyToClipboard } from '@wordpress/compose'; +import { useCopyToClipboard, useInstanceId } from '@wordpress/compose'; /** * Internal dependencies @@ -70,25 +70,29 @@ export default function PostURL( { onClose } ) { const { createNotice } = useDispatch( noticesStore ); const [ forceEmptyField, setForceEmptyField ] = useState( false ); const copyButtonRef = useCopyToClipboard( permalink, () => { - createNotice( 'info', __( 'Copied URL to clipboard.' ), { + createNotice( 'info', __( 'Copied Permalink to clipboard.' ), { isDismissible: true, type: 'snackbar', } ); } ); + const postUrlSlugDescriptionId = + 'editor-post-url__slug-descriotion-' + useInstanceId( PostURL ); + return ( <div className="editor-post-url"> <InspectorPopoverHeader - title={ __( 'Link' ) } + title={ __( 'Slug' ) } onClose={ onClose } /> <VStack spacing={ 3 }> { isEditable && ( - <div> + <p className="editor-post-url__intro"> { createInterpolateElement( __( - 'Customize the last part of the URL. <a>Learn more.</a>' + '<span>Customize the last part of the Permalink.</span> <a>Learn more.</a>' ), { + span: <span id={ postUrlSlugDescriptionId } />, a: ( <ExternalLink href={ __( @@ -98,59 +102,67 @@ export default function PostURL( { onClose } ) { ), } ) } - </div> + </p> ) } <div> { isEditable && ( - <InputControl - __next40pxDefaultSize - prefix={ - <InputControlPrefixWrapper> - / - </InputControlPrefixWrapper> - } - suffix={ - <InputControlSuffixWrapper variant="control"> - <Button - icon={ copySmall } - ref={ copyButtonRef } - size="small" - label="Copy" - /> - </InputControlSuffixWrapper> - } - label={ __( 'Link' ) } - hideLabelFromVision - value={ forceEmptyField ? '' : postSlug } - autoComplete="off" - spellCheck="false" - type="text" - className="editor-post-url__input" - onChange={ ( newValue ) => { - editPost( { slug: newValue } ); - // When we delete the field the permalink gets - // reverted to the original value. - // The forceEmptyField logic allows the user to have - // the field temporarily empty while typing. - if ( ! newValue ) { - if ( ! forceEmptyField ) { - setForceEmptyField( true ); - } - return; + <> + <InputControl + __next40pxDefaultSize + prefix={ + <InputControlPrefixWrapper> + / + </InputControlPrefixWrapper> } - if ( forceEmptyField ) { - setForceEmptyField( false ); + suffix={ + <InputControlSuffixWrapper variant="control"> + <Button + icon={ copySmall } + ref={ copyButtonRef } + size="small" + label="Copy" + /> + </InputControlSuffixWrapper> } - } } - onBlur={ ( event ) => { - editPost( { - slug: cleanForSlug( event.target.value ), - } ); - if ( forceEmptyField ) { - setForceEmptyField( false ); - } - } } - help={ + label={ __( 'Slug' ) } + hideLabelFromVision + value={ forceEmptyField ? '' : postSlug } + autoComplete="off" + spellCheck="false" + type="text" + className="editor-post-url__input" + onChange={ ( newValue ) => { + editPost( { slug: newValue } ); + // When we delete the field the permalink gets + // reverted to the original value. + // The forceEmptyField logic allows the user to have + // the field temporarily empty while typing. + if ( ! newValue ) { + if ( ! forceEmptyField ) { + setForceEmptyField( true ); + } + return; + } + if ( forceEmptyField ) { + setForceEmptyField( false ); + } + } } + onBlur={ ( event ) => { + editPost( { + slug: cleanForSlug( + event.target.value + ), + } ); + if ( forceEmptyField ) { + setForceEmptyField( false ); + } + } } + aria-describedby={ postUrlSlugDescriptionId } + /> + <p className="editor-post-url__permalink"> + <span className="editor-post-url__permalink-visual-label"> + { __( 'Permalink:' ) } + </span> <ExternalLink className="editor-post-url__link" href={ postLink } @@ -166,8 +178,8 @@ export default function PostURL( { onClose } ) { { permalinkSuffix } </span> </ExternalLink> - } - /> + </p> + </> ) } { ! isEditable && ( <ExternalLink diff --git a/packages/editor/src/components/post-url/panel.js b/packages/editor/src/components/post-url/panel.js index aca36566c04727..a5d3ddeb77f846 100644 --- a/packages/editor/src/components/post-url/panel.js +++ b/packages/editor/src/components/post-url/panel.js @@ -3,11 +3,7 @@ */ import { useMemo, useState } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; -import { - Dropdown, - Button, - __experimentalTruncate as Truncate, -} from '@wordpress/components'; +import { Dropdown, Button, ExternalLink } from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; import { safeDecodeURIComponent } from '@wordpress/url'; import { store as coreStore } from '@wordpress/core-data'; @@ -26,6 +22,20 @@ import { store as editorStore } from '../../store'; * @return {JSX.Element} The rendered PostURLPanel component. */ export default function PostURLPanel() { + const { isFrontPage } = useSelect( ( select ) => { + const { getCurrentPostId } = select( editorStore ); + const { getEditedEntityRecord, canUser } = select( coreStore ); + const siteSettings = canUser( 'read', { + kind: 'root', + name: 'site', + } ) + ? getEditedEntityRecord( 'root', 'site' ) + : undefined; + const _id = getCurrentPostId(); + return { + isFrontPage: siteSettings?.page_on_front === _id, + }; + }, [] ); // Use internal state instead of a ref to make sure that the component // re-renders when the popover's anchor updates. const [ popoverAnchor, setPopoverAnchor ] = useState( null ); @@ -42,41 +52,38 @@ export default function PostURLPanel() { [ popoverAnchor ] ); + const label = isFrontPage ? __( 'Link' ) : __( 'Slug' ); + return ( <PostURLCheck> - <PostPanelRow label={ __( 'Link' ) } ref={ setPopoverAnchor }> - <Dropdown - popoverProps={ popoverProps } - className="editor-post-url__panel-dropdown" - contentClassName="editor-post-url__panel-dialog" - focusOnMount - renderToggle={ ( { isOpen, onToggle } ) => ( - <PostURLToggle isOpen={ isOpen } onClick={ onToggle } /> - ) } - renderContent={ ( { onClose } ) => ( - <PostURL onClose={ onClose } /> - ) } - /> + <PostPanelRow label={ label } ref={ setPopoverAnchor }> + { ! isFrontPage && ( + <Dropdown + popoverProps={ popoverProps } + className="editor-post-url__panel-dropdown" + contentClassName="editor-post-url__panel-dialog" + focusOnMount + renderToggle={ ( { isOpen, onToggle } ) => ( + <PostURLToggle + isOpen={ isOpen } + onClick={ onToggle } + /> + ) } + renderContent={ ( { onClose } ) => ( + <PostURL onClose={ onClose } /> + ) } + /> + ) } + { isFrontPage && <FrontPageLink /> } </PostPanelRow> </PostURLCheck> ); } function PostURLToggle( { isOpen, onClick } ) { - const { slug, isFrontPage, postLink } = useSelect( ( select ) => { - const { getCurrentPostId, getCurrentPost } = select( editorStore ); - const { getEditedEntityRecord, canUser } = select( coreStore ); - const siteSettings = canUser( 'read', { - kind: 'root', - name: 'site', - } ) - ? getEditedEntityRecord( 'root', 'site' ) - : undefined; - const _id = getCurrentPostId(); + const { slug } = useSelect( ( select ) => { return { slug: select( editorStore ).getEditedPostSlug(), - isFrontPage: siteSettings?.page_on_front === _id, - postLink: getCurrentPost()?.link, }; }, [] ); const decodedSlug = safeDecodeURIComponent( slug ); @@ -90,9 +97,26 @@ function PostURLToggle( { isOpen, onClick } ) { aria-label={ sprintf( __( 'Change link: %s' ), decodedSlug ) } onClick={ onClick } > - <Truncate numberOfLines={ 1 }> - { isFrontPage ? postLink : `/${ decodedSlug }` } - </Truncate> + <>{ decodedSlug }</> </Button> ); } + +function FrontPageLink() { + const { postLink } = useSelect( ( select ) => { + const { getCurrentPost } = select( editorStore ); + return { + postLink: getCurrentPost()?.link, + }; + }, [] ); + + return ( + <ExternalLink + className="editor-post-url__front-page-link" + href={ postLink } + target="_blank" + > + { postLink } + </ExternalLink> + ); +} diff --git a/packages/editor/src/components/post-url/style.scss b/packages/editor/src/components/post-url/style.scss index c815f89682cb2d..f8a70f5fdf760b 100644 --- a/packages/editor/src/components/post-url/style.scss +++ b/packages/editor/src/components/post-url/style.scss @@ -9,14 +9,19 @@ } /* rtl:begin:ignore */ -.editor-post-url__link { +.editor-post-url__link, +.editor-post-url__front-page-link { direction: ltr; word-break: break-word; - margin-top: $grid-unit-05; - color: $gray-700; } /* rtl:end:ignore */ +.editor-post-url__front-page-link { + // Match padding on tertiary buttons for alignment. + padding: $grid-unit-15 * 0.5 0 $grid-unit-15 * 0.5 $grid-unit-15; +} + + .editor-post-url__link-slug { font-weight: 600; } @@ -30,3 +35,16 @@ .editor-post-url__panel-toggle { word-break: break-word; } + +.editor-post-url__intro { + margin: 0; +} + +.editor-post-url__permalink { + margin-top: $grid-unit-10; + margin-bottom: 0; + + &-visual-label { + display: block; + } +} From 7ca579031287c55ea8d9cb3249563b74f2c0b4a7 Mon Sep 17 00:00:00 2001 From: "Stephen A. Bernhardt" <sabernhardt@yahoo.com> Date: Mon, 14 Oct 2024 07:23:05 -0500 Subject: [PATCH 1160/1908] Code block: set LTR direction for RTL languages (#65891) * style.scss direction and alignment * editor.scss direction and alignment * Revert changes to `editor.scss` * Switch `left` to `initial` and add comment Co-authored-by: sabernhardt <sabernhardt@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ankitpanchal75 <ankitmaru@git.wordpress.org> Co-authored-by: torounit <toro_unit@git.wordpress.org> --- packages/block-library/src/code/style.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/block-library/src/code/style.scss b/packages/block-library/src/code/style.scss index 670a4f7f1ef4c8..ccc950d19b552c 100644 --- a/packages/block-library/src/code/style.scss +++ b/packages/block-library/src/code/style.scss @@ -9,5 +9,10 @@ font-family: inherit; overflow-wrap: break-word; white-space: pre-wrap; + // Set direction and avoid inheriting alignment from a parent element. + /*!rtl:begin:ignore*/ + direction: ltr; + text-align: initial; + /*!rtl:end:ignore*/ } } From 4af4518b0917296091f6d520ce1352f6094cc3eb Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Mon, 14 Oct 2024 07:33:45 -0500 Subject: [PATCH 1161/1908] Restores setting zoom out mode to useZoomOut hook (#65999) * Restores setting zoom out mode to useZoomOut hook * Fix test --------- Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- packages/block-editor/README.md | 4 +- .../block-editor/src/hooks/use-zoom-out.js | 56 ++++++++++++------- .../editor/various/parsing-patterns.spec.js | 10 +++- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 36f3dc0ba73fa1..7fc44c2ead9439 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -1077,11 +1077,11 @@ _Parameters_ ### useZoomOut -A hook used to set the zoomed out view, invoking the hook sets the mode. +A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode. _Parameters_ -- _zoomOut_ `boolean`: If we should zoom out or not. +- _zoomOut_ `boolean`: If we should enter into zoomOut mode or not ### Warning diff --git a/packages/block-editor/src/hooks/use-zoom-out.js b/packages/block-editor/src/hooks/use-zoom-out.js index 2a1b43060c00a9..23511487a54bf7 100644 --- a/packages/block-editor/src/hooks/use-zoom-out.js +++ b/packages/block-editor/src/hooks/use-zoom-out.js @@ -9,39 +9,55 @@ import { useEffect, useRef } from '@wordpress/element'; */ import { store as blockEditorStore } from '../store'; import { unlock } from '../lock-unlock'; - /** - * A hook used to set the zoomed out view, invoking the hook sets the mode. + * A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode. * - * @param {boolean} zoomOut If we should zoom out or not. + * @param {boolean} zoomOut If we should enter into zoomOut mode or not */ export function useZoomOut( zoomOut = true ) { - const { setZoomLevel } = unlock( useDispatch( blockEditorStore ) ); - const { isZoomOut } = unlock( useSelect( blockEditorStore ) ); + const { __unstableSetEditorMode, setZoomLevel } = unlock( + useDispatch( blockEditorStore ) + ); + const { __unstableGetEditorMode } = unlock( useSelect( blockEditorStore ) ); - const originalIsZoomOutRef = useRef( null ); + const originalEditingModeRef = useRef( null ); + const mode = __unstableGetEditorMode(); useEffect( () => { // Only set this on mount so we know what to return to when we unmount. - if ( ! originalIsZoomOutRef.current ) { - originalIsZoomOutRef.current = isZoomOut(); + if ( ! originalEditingModeRef.current ) { + originalEditingModeRef.current = mode; } - // The effect opens the zoom-out view if we want it open and the canvas is not currently zoomed-out. - if ( zoomOut && isZoomOut() === false ) { + return () => { + // We need to use __unstableGetEditorMode() here and not `mode`, as mode may not update on unmount + if ( + __unstableGetEditorMode() === 'zoom-out' && + __unstableGetEditorMode() !== originalEditingModeRef.current + ) { + __unstableSetEditorMode( originalEditingModeRef.current ); + setZoomLevel( 100 ); + } + }; + }, [] ); + + // The effect opens the zoom-out view if we want it open and it's not currently in zoom-out mode. + useEffect( () => { + if ( zoomOut && mode !== 'zoom-out' ) { + __unstableSetEditorMode( 'zoom-out' ); setZoomLevel( 50 ); } else if ( ! zoomOut && - isZoomOut() && - originalIsZoomOutRef.current !== isZoomOut() + __unstableGetEditorMode() === 'zoom-out' && + originalEditingModeRef.current !== mode ) { - setZoomLevel( originalIsZoomOutRef.current ? 50 : 100 ); + __unstableSetEditorMode( originalEditingModeRef.current ); + setZoomLevel( 100 ); } - - return () => { - if ( isZoomOut() && isZoomOut() !== originalIsZoomOutRef.current ) { - setZoomLevel( originalIsZoomOutRef.current ? 50 : 100 ); - } - }; - }, [ isZoomOut, setZoomLevel, zoomOut ] ); + }, [ + __unstableGetEditorMode, + __unstableSetEditorMode, + zoomOut, + setZoomLevel, + ] ); // Mode is deliberately excluded from the dependencies so that the effect does not run when mode changes. } diff --git a/test/e2e/specs/editor/various/parsing-patterns.spec.js b/test/e2e/specs/editor/various/parsing-patterns.spec.js index 62c8ba2de24104..fd9305d0db786f 100644 --- a/test/e2e/specs/editor/various/parsing-patterns.spec.js +++ b/test/e2e/specs/editor/various/parsing-patterns.spec.js @@ -36,6 +36,14 @@ test.describe( 'Parsing patterns', () => { ], } ); } ); + + // Exit zoom out mode and select the inner buttons block to ensure + // the correct insertion point is selected. + await page.getByRole( 'button', { name: 'Zoom Out' } ).click(); + await editor.selectBlocks( + editor.canvas.locator( 'role=document[name="Block: Button"i]' ) + ); + await page.fill( 'role=region[name="Block Library"i] >> role=searchbox[name="Search"i]', 'whitespace' @@ -43,7 +51,7 @@ test.describe( 'Parsing patterns', () => { await page .locator( 'role=option[name="Pattern with top-level whitespace"i]' ) .click(); - expect( await editor.getBlocks() ).toMatchObject( [ + await expect.poll( editor.getBlocks ).toMatchObject( [ { name: 'core/buttons', innerBlocks: [ From ff58388dd4bde0e2a1df0fb65fd7cef7bd4f2882 Mon Sep 17 00:00:00 2001 From: vineet khollam <53342781+vk17-starlord@users.noreply.github.com> Date: Mon, 14 Oct 2024 18:05:04 +0530 Subject: [PATCH 1162/1908] Fixed : Modal dialog: small improvement for elementShouldBeHidden (#65941) * Fixed : Modal dialog: small improvement for elementShouldBeHidden #65829 * Refactor `elementShouldBeHidden` to combine all checks into a single return statement * Added : PR description in changelog.md * Removed comments from function and fixed changelog * Removed modal details from bug fixes and moved to enhancements * Add missing empty line to changelog. * moved : PR details to enhancement section * Add missing empty line to changelog. --------- Co-authored-by: vk17-starlord <vineet2003@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: up1512001 <up1512001@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/modal/aria-helper.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 6d3714d9cb5db6..48113f874af3a2 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -17,6 +17,7 @@ ### Enhancements +- `Modal`: Modal dialog small improvement for elementShouldBeHidden ([#65941](https://github.com/WordPress/gutenberg/pull/65941)). - `Tabs`: revamped vertical orientation styles ([#65387](https://github.com/WordPress/gutenberg/pull/65387)). ## 28.9.0 (2024-10-03) diff --git a/packages/components/src/modal/aria-helper.ts b/packages/components/src/modal/aria-helper.ts index 6a1d39c0a4ed31..bd11fb71253e1e 100644 --- a/packages/components/src/modal/aria-helper.ts +++ b/packages/components/src/modal/aria-helper.ts @@ -47,6 +47,7 @@ export function elementShouldBeHidden( element: Element ) { const role = element.getAttribute( 'role' ); return ! ( element.tagName === 'SCRIPT' || + element.hasAttribute( 'hidden' ) || element.hasAttribute( 'aria-hidden' ) || element.hasAttribute( 'aria-live' ) || ( role && LIVE_REGION_ARIA_ROLES.has( role ) ) From 4b6e08aac313d605dcfbc6ef0666bc75e62b5dbe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 08:37:35 -0400 Subject: [PATCH 1163/1908] Bump the github-actions group across 1 directory with 3 updates (#65992) Bumps the github-actions group with 3 updates in the / directory: [actions/checkout](https://github.com/actions/checkout), [actions/cache](https://github.com/actions/cache) and [ruby/setup-ruby](https://github.com/ruby/setup-ruby). Updates `actions/checkout` from 4.2.0 to 4.2.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/d632683dd7b4114ad314bca15554477dd762a938...eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871) Updates `actions/cache` from 4.1.0 to 4.1.1 - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2...3624ceb22c1c5a301c8db4169662070a689d9ea8) Updates `ruby/setup-ruby` from 1.195.0 to 1.196.0 - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb) - [Commits](https://github.com/ruby/setup-ruby/compare/086ffb1a2090c870a3f881cc91ea83aa4243d408...f26937343756480a8cb3ae1f623b9c8d89ed6984) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/build-plugin-zip.yml | 10 +++++----- .github/workflows/bundle-size.yml | 2 +- .github/workflows/check-backport-changelog.yml | 2 +- .github/workflows/check-components-changelog.yml | 2 +- .github/workflows/cherry-pick-wp-release.yml | 2 +- .github/workflows/create-block.yml | 2 +- .github/workflows/end2end-test.yml | 4 ++-- .github/workflows/gradle-wrapper-validation.yml | 2 +- .github/workflows/performance.yml | 2 +- .github/workflows/publish-npm-packages.yml | 6 +++--- .github/workflows/pull-request-automation.yml | 4 ++-- .github/workflows/rnmobile-android-runner.yml | 6 +++--- .github/workflows/rnmobile-ios-runner.yml | 10 +++++----- .github/workflows/static-checks.yml | 2 +- .github/workflows/storybook-pages.yml | 2 +- .github/workflows/sync-backport-changelog.yml | 2 +- .github/workflows/unit-test.yml | 14 +++++++------- .../workflows/upload-release-to-plugin-repo.yml | 2 +- 18 files changed, 38 insertions(+), 38 deletions(-) diff --git a/.github/workflows/build-plugin-zip.yml b/.github/workflows/build-plugin-zip.yml index 0f813267b586bd..9a3a9abb84963d 100644 --- a/.github/workflows/build-plugin-zip.yml +++ b/.github/workflows/build-plugin-zip.yml @@ -72,7 +72,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: token: ${{ secrets.GUTENBERG_TOKEN }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -168,7 +168,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: ref: ${{ needs.bump-version.outputs.release_branch || github.ref }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -225,7 +225,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: fetch-depth: 2 ref: ${{ needs.bump-version.outputs.release_branch }} @@ -314,14 +314,14 @@ jobs: if: ${{ endsWith( needs.bump-version.outputs.new_version, '-rc.1' ) }} steps: - name: Checkout (for CLI) - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: path: main ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Checkout (for publishing) - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: path: publish # Later, we switch this branch in the script that publishes packages. diff --git a/.github/workflows/bundle-size.yml b/.github/workflows/bundle-size.yml index 2de66f77e3918b..4b0b93ac959ed8 100644 --- a/.github/workflows/bundle-size.yml +++ b/.github/workflows/bundle-size.yml @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: fetch-depth: 1 show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/check-backport-changelog.yml b/.github/workflows/check-backport-changelog.yml index cf07b1a3936b97..889e1cfb477256 100644 --- a/.github/workflows/check-backport-changelog.yml +++ b/.github/workflows/check-backport-changelog.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest if: ${{ !contains(github.event.pull_request.labels.*.name, 'No Core Sync Required') && !contains(github.event.pull_request.labels.*.name, 'Backport from WordPress Core') }} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: ref: ${{ github.event.pull_request.head.ref }} repository: ${{ github.event.pull_request.head.repo.full_name }} diff --git a/.github/workflows/check-components-changelog.yml b/.github/workflows/check-components-changelog.yml index 40fbfe22bea568..2c0d52c77ea4e2 100644 --- a/.github/workflows/check-components-changelog.yml +++ b/.github/workflows/check-components-changelog.yml @@ -22,7 +22,7 @@ jobs: - name: 'Get PR commit count' run: echo "PR_COMMIT_COUNT=$(( ${{ github.event.pull_request.commits }} + 1 ))" >> "${GITHUB_ENV}" - name: Checkout code - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: ref: ${{ github.event.pull_request.head.ref }} repository: ${{ github.event.pull_request.head.repo.full_name }} diff --git a/.github/workflows/cherry-pick-wp-release.yml b/.github/workflows/cherry-pick-wp-release.yml index 11688a7cfba980..5771a21d5b068b 100644 --- a/.github/workflows/cherry-pick-wp-release.yml +++ b/.github/workflows/cherry-pick-wp-release.yml @@ -70,7 +70,7 @@ jobs: - name: Checkout repository if: env.cherry_pick == 'true' - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: token: ${{ secrets.GUTENBERG_TOKEN }} fetch-depth: 0 diff --git a/.github/workflows/create-block.yml b/.github/workflows/create-block.yml index d20b3e353c31e4..4d99d396996c59 100644 --- a/.github/workflows/create-block.yml +++ b/.github/workflows/create-block.yml @@ -24,7 +24,7 @@ jobs: os: ['macos-latest', 'ubuntu-latest', 'windows-latest'] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/end2end-test.yml b/.github/workflows/end2end-test.yml index bbf033222a4b31..2ea5949d20946c 100644 --- a/.github/workflows/end2end-test.yml +++ b/.github/workflows/end2end-test.yml @@ -27,7 +27,7 @@ jobs: totalParts: [8] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -102,7 +102,7 @@ jobs: steps: # Checkout defaults to using the branch which triggered the event, which # isn't necessarily `trunk` (e.g. in the case of a merge). - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 4715e1e09c2b83..f268ac7183ee21 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -6,7 +6,7 @@ jobs: name: 'Validation' runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - uses: gradle/wrapper-validation-action@v3 diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index 9c4bee3af473c8..a79f2eee9315a5 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -33,7 +33,7 @@ jobs: WP_ARTIFACTS_PATH: ${{ github.workspace }}/artifacts steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/publish-npm-packages.yml b/.github/workflows/publish-npm-packages.yml index 66f8130ece2f06..b95a4baaf5075a 100644 --- a/.github/workflows/publish-npm-packages.yml +++ b/.github/workflows/publish-npm-packages.yml @@ -31,7 +31,7 @@ jobs: steps: - name: Checkout (for CLI) if: ${{ github.event.inputs.release_type != 'wp' }} - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: path: cli ref: trunk @@ -39,7 +39,7 @@ jobs: - name: Checkout (for publishing) if: ${{ github.event.inputs.release_type != 'wp' }} - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: path: publish # Later, we switch this branch in the script that publishes packages. @@ -49,7 +49,7 @@ jobs: - name: Checkout (for publishing WP major version) if: ${{ github.event.inputs.release_type == 'wp' && github.event.inputs.wp_version }} - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: path: publish ref: wp/${{ github.event.inputs.wp_version }} diff --git a/.github/workflows/pull-request-automation.yml b/.github/workflows/pull-request-automation.yml index f85b8510067569..9aecafc2009e7f 100644 --- a/.github/workflows/pull-request-automation.yml +++ b/.github/workflows/pull-request-automation.yml @@ -12,7 +12,7 @@ jobs: steps: # Checkout defaults to using the branch which triggered the event, which # isn't necessarily `trunk` (e.g. in the case of a merge). - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -24,7 +24,7 @@ jobs: check-latest: true - name: Cache NPM packages - uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 + uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 with: # npm cache files are stored in `~/.npm` on Linux/macOS path: ~/.npm diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index 729d1d20fd7e7b..a1e332be783030 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -23,7 +23,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -37,7 +37,7 @@ jobs: uses: ./.github/setup-node - name: Restore tests setup cache - uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 + uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 with: path: | ~/.appium @@ -50,7 +50,7 @@ jobs: uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0 - name: AVD cache - uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 + uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 id: avd-cache with: path: | diff --git a/.github/workflows/rnmobile-ios-runner.yml b/.github/workflows/rnmobile-ios-runner.yml index 475937eb58f5f8..a5c5dfd3f96f93 100644 --- a/.github/workflows/rnmobile-ios-runner.yml +++ b/.github/workflows/rnmobile-ios-runner.yml @@ -23,11 +23,11 @@ jobs: native-test-name: [gutenberg-editor-rendering] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - uses: ruby/setup-ruby@086ffb1a2090c870a3f881cc91ea83aa4243d408 # v1.195.0 + - uses: ruby/setup-ruby@f26937343756480a8cb3ae1f623b9c8d89ed6984 # v1.196.0 with: # `.ruby-version` file location working-directory: packages/react-native-editor/ios @@ -42,7 +42,7 @@ jobs: uses: ./.github/setup-node - name: Restore tests setup cache - uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 + uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 with: path: | ~/.appium @@ -55,7 +55,7 @@ jobs: run: find package-lock.json packages/react-native-editor/ios packages/react-native-aztec/ios packages/react-native-bridge/ios -type f -print0 | sort -z | xargs -0 shasum | tee ios-checksums.txt - name: Restore build cache - uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 + uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 with: path: | packages/react-native-editor/ios/build/GutenbergDemo/Build/Products/Release-iphonesimulator/GutenbergDemo.app @@ -63,7 +63,7 @@ jobs: key: ${{ runner.os }}-ios-build-${{ matrix.xcode }}-${{ matrix.device }}-${{ hashFiles('ios-checksums.txt') }} - name: Restore pods cache - uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 + uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 with: path: | packages/react-native-editor/ios/Pods diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml index 1af2bb0ec79275..bf1a70d3adefc2 100644 --- a/.github/workflows/static-checks.yml +++ b/.github/workflows/static-checks.yml @@ -22,7 +22,7 @@ jobs: if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/storybook-pages.yml b/.github/workflows/storybook-pages.yml index 83f7fdb96f9262..a0a7d0f12db1e5 100644 --- a/.github/workflows/storybook-pages.yml +++ b/.github/workflows/storybook-pages.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/sync-backport-changelog.yml b/.github/workflows/sync-backport-changelog.yml index b71d9440c38a1f..31b00459c24c6c 100644 --- a/.github/workflows/sync-backport-changelog.yml +++ b/.github/workflows/sync-backport-changelog.yml @@ -20,7 +20,7 @@ jobs: ) steps: - name: Checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: fetch-depth: 2 # Fetch the last two commits to compare changes - name: Check for changes in backport-changelog diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 47b5e9f76ea7b0..272d7e12d7193a 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -70,7 +70,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -121,7 +121,7 @@ jobs: name: Build JavaScript assets for PHP unit tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -173,7 +173,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -278,7 +278,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -296,7 +296,7 @@ jobs: run: echo "date=$(/bin/date -u --date='last Mon' "+%F")" >> $GITHUB_OUTPUT - name: Cache PHPCS scan cache - uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 + uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 with: path: .cache/phpcs.json key: ${{ runner.os }}-date-${{ steps.get-date.outputs.date }}-phpcs-cache-${{ hashFiles('**/composer.json', 'phpcs.xml.dist') }} @@ -348,7 +348,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/upload-release-to-plugin-repo.yml b/.github/workflows/upload-release-to-plugin-repo.yml index d09e2af3dd2135..e8d3e3e245abd0 100644 --- a/.github/workflows/upload-release-to-plugin-repo.yml +++ b/.github/workflows/upload-release-to-plugin-repo.yml @@ -96,7 +96,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: ref: ${{ matrix.branch }} token: ${{ secrets.GUTENBERG_TOKEN }} From 3d87652b1c5b4e37a3d6db97ae00705d283deccb Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Mon, 14 Oct 2024 07:47:29 -0700 Subject: [PATCH 1164/1908] Data Views list layout: revise for improved text truncation (#65376) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove background-color and box-shadow from actions * Shorten primary field’s text on hover or selected state * Data Views list layout: revise for improved text truncation * Let primary field be full with in resting state * Remove seemingly errant border radius on item wrapper * Unnest actions gridcells * Fix cursor style of list items * Update test selector * Revert "Update test selector" This reverts commit 59e8b7dfab39df3994468920b731b72477760d86. * Put primary field in front if it has interactive elements --------- Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> --- .../src/dataviews-layouts/list/index.tsx | 181 ++++++++---------- .../src/dataviews-layouts/list/style.scss | 75 ++++---- 2 files changed, 113 insertions(+), 143 deletions(-) diff --git a/packages/dataviews/src/dataviews-layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx index fb46521fe217b7..e737b18f5b02a9 100644 --- a/packages/dataviews/src/dataviews-layouts/list/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/list/index.tsx @@ -145,11 +145,9 @@ function ListItem< Item >( { const descriptionId = `${ idPrefix }-description`; const [ isHovered, setIsHovered ] = useState( false ); - const handleMouseEnter = () => { - setIsHovered( true ); - }; - const handleMouseLeave = () => { - setIsHovered( false ); + const handleHover: React.MouseEventHandler = ( { type } ) => { + const isHover = type === 'mouseenter'; + setIsHovered( isHover ); }; useEffect( () => { @@ -187,6 +185,45 @@ function ListItem< Item >( { <primaryField.render item={ item } /> ) : null; + const usedActions = eligibleActions?.length > 0 && ( + <HStack spacing={ 3 } className="dataviews-view-list__item-actions"> + { primaryAction && ( + <PrimaryActionGridCell + idPrefix={ idPrefix } + primaryAction={ primaryAction } + item={ item } + /> + ) } + <div role="gridcell"> + <DropdownMenu + trigger={ + <Composite.Item + id={ generateDropdownTriggerCompositeId( + idPrefix + ) } + render={ + <Button + size="small" + icon={ moreVertical } + label={ __( 'Actions' ) } + accessibleWhenDisabled + disabled={ ! actions.length } + onKeyDown={ onDropdownTriggerKeyDown } + /> + } + /> + } + placement="bottom-end" + > + <ActionsDropdownMenuGroup + actions={ eligibleActions } + item={ item } + /> + </DropdownMenu> + </div> + </HStack> + ); + return ( <Composite.Row ref={ itemRef } @@ -196,116 +233,60 @@ function ListItem< Item >( { 'is-selected': isSelected, 'is-hovered': isHovered, } ) } - onMouseEnter={ handleMouseEnter } - onMouseLeave={ handleMouseLeave } + onMouseEnter={ handleHover } + onMouseLeave={ handleHover } > - <HStack - className="dataviews-view-list__item-wrapper" - alignment="center" - spacing={ 0 } - > + <HStack className="dataviews-view-list__item-wrapper" spacing={ 0 }> <div role="gridcell"> <Composite.Item - render={ <div /> } - role="button" id={ generateItemWrapperCompositeId( idPrefix ) } aria-pressed={ isSelected } aria-labelledby={ labelId } aria-describedby={ descriptionId } className="dataviews-view-list__item" onClick={ () => onSelect( item ) } + /> + </div> + <HStack spacing={ 3 } justify="start" alignment="flex-start"> + <div className="dataviews-view-list__media-wrapper"> + { renderedMediaField } + </div> + <VStack + spacing={ 1 } + className="dataviews-view-list__field-wrapper" > - <HStack - spacing={ 3 } - justify="start" - alignment="flex-start" - > - <div className="dataviews-view-list__media-wrapper"> - { renderedMediaField } - </div> - <VStack - spacing={ 1 } - className="dataviews-view-list__field-wrapper" + <HStack spacing={ 0 }> + <div + className="dataviews-view-list__primary-field" + id={ labelId } > - <span - className="dataviews-view-list__primary-field" - id={ labelId } - > - { renderedPrimaryField } - </span> + { renderedPrimaryField } + </div> + { usedActions } + </HStack> + <div + className="dataviews-view-list__fields" + id={ descriptionId } + > + { visibleFields.map( ( field ) => ( <div - className="dataviews-view-list__fields" - id={ descriptionId } + key={ field.id } + className="dataviews-view-list__field" > - { visibleFields.map( ( field ) => ( - <div - key={ field.id } - className="dataviews-view-list__field" - > - <VisuallyHidden - as="span" - className="dataviews-view-list__field-label" - > - { field.label } - </VisuallyHidden> - <span className="dataviews-view-list__field-value"> - <field.render item={ item } /> - </span> - </div> - ) ) } + <VisuallyHidden + as="span" + className="dataviews-view-list__field-label" + > + { field.label } + </VisuallyHidden> + <span className="dataviews-view-list__field-value"> + <field.render item={ item } /> + </span> </div> - </VStack> - </HStack> - </Composite.Item> - </div> - { eligibleActions?.length > 0 && ( - <HStack - spacing={ 3 } - justify="flex-end" - className="dataviews-view-list__item-actions" - style={ { - flexShrink: '0', - width: 'auto', - } } - > - { primaryAction && ( - <PrimaryActionGridCell - idPrefix={ idPrefix } - primaryAction={ primaryAction } - item={ item } - /> - ) } - <div role="gridcell"> - <DropdownMenu - trigger={ - <Composite.Item - id={ generateDropdownTriggerCompositeId( - idPrefix - ) } - render={ - <Button - size="small" - icon={ moreVertical } - label={ __( 'Actions' ) } - accessibleWhenDisabled - disabled={ ! actions.length } - onKeyDown={ - onDropdownTriggerKeyDown - } - /> - } - /> - } - placement="bottom-end" - > - <ActionsDropdownMenuGroup - actions={ eligibleActions } - item={ item } - /> - </DropdownMenu> + ) ) } </div> - </HStack> - ) } + </VStack> + </HStack> </HStack> </Composite.Row> ); diff --git a/packages/dataviews/src/dataviews-layouts/list/style.scss b/packages/dataviews/src/dataviews-layouts/list/style.scss index ea3236f6d75e1e..9a3128c14b76a7 100644 --- a/packages/dataviews/src/dataviews-layouts/list/style.scss +++ b/packages/dataviews/src/dataviews-layouts/list/style.scss @@ -7,63 +7,40 @@ ul.dataviews-view-list { li { margin: 0; - cursor: pointer; border-top: 1px solid $gray-100; .dataviews-view-list__item-wrapper { position: relative; - border-radius: $grid-unit-05; - - > * { - width: 100%; - } + padding: $grid-unit-20 $grid-unit-30; } .dataviews-view-list__item-actions { - position: absolute; - top: $grid-unit-20; - right: 0; - + flex: 0; + overflow: hidden; > div { height: $button-size-small; } .components-button { + position: relative; + z-index: 1; opacity: 0; } } - &:has(.dataviews-view-list__fields:empty) { - .dataviews-view-list__item-actions { - top: 50%; - transform: translateY(-50%); - } - } - - &.is-selected, - &.is-hovered, - &:focus-within { + &:where(.is-selected, .is-hovered, :focus-within) { .dataviews-view-list__item-actions { - background: #f8f8f8; - padding-left: $grid-unit-10; - margin-right: $grid-unit-30; - box-shadow: -12px 0 8px 0 #f8f8f8; + flex-basis: min-content; + overflow: unset; + margin-inline: $grid-unit-10 0; .components-button { opacity: 1; - position: static; } } } - &.is-selected { - .dataviews-view-list__item-actions { - background-color: rgb(247 248 255); - box-shadow: -12px 0 8px 0 rgb(247 248 255); - } - } - &.is-selected.is-selected { border-top: 1px solid rgba(var(--wp-admin-theme-color--rgb), 0.12); @@ -105,27 +82,38 @@ ul.dataviews-view-list { } .dataviews-view-list__item { - box-sizing: border-box; - padding: $grid-unit-20 $grid-unit-30; - width: 100%; + position: absolute; + z-index: 1; + inset: 0; scroll-margin: $grid-unit-10 0; + appearance: none; + border: none; + background: none; + padding: 0; + cursor: pointer; &:focus-visible { + outline: none; + &::before { position: absolute; content: ""; - top: var(--wp-admin-border-width-focus); - right: var(--wp-admin-border-width-focus); - bottom: var(--wp-admin-border-width-focus); - left: var(--wp-admin-border-width-focus); + inset: var(--wp-admin-border-width-focus); box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); border-radius: $radius-small; + // Windows High Contrast mode will show this outline, but not the box-shadow. + outline: 2px solid transparent; } } - .dataviews-view-list__primary-field { - min-height: $grid-unit-30; - line-height: $grid-unit-30; - overflow: hidden; + } + .dataviews-view-list__primary-field { + flex: 1; + min-height: $grid-unit-30; + line-height: $grid-unit-30; + overflow: hidden; + // The field should be in front of the main button in case it has a link/button. + &:has(a, button) { + z-index: 1; } } @@ -164,6 +152,7 @@ ul.dataviews-view-list { .dataviews-view-list__field-wrapper { min-height: $grid-unit-05 * 13; // Ensures title is centrally aligned when all fields are hidden + flex-grow: 1; } .dataviews-view-list__fields { From a55c62c5c810c84258afcdac7da1a7019a69b332 Mon Sep 17 00:00:00 2001 From: Renatho De Carli Rosa <renatho@gmail.com> Date: Tue, 15 Oct 2024 00:29:07 -0300 Subject: [PATCH 1165/1908] Revert "Update z-index hierarchy (#65626)" (#66074) Co-authored-by: renatho <renathoc@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: juanfra <juanfra@git.wordpress.org> --- packages/base-styles/_z-index.scss | 8 +++++--- packages/block-library/src/cover/editor.scss | 1 + packages/block-library/src/cover/style.scss | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index ff61c5793e787f..77238c6f386084 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -31,10 +31,12 @@ $z-layers: ( ".interface-interface-skeleton__header": 30, ".interface-interface-skeleton__content": 20, ".edit-widgets-header": 30, + ".wp-block-cover__inner-container": 1, // InnerBlocks area inside cover image block. ".wp-block-cover.is-placeholder .components-placeholder.is-large": 1, // Cover block resizer component inside a large placeholder. - ".wp-block-cover.has-background-dim::before": 0, // Overlay area inside block cover need to be higher than the video background. - ".wp-block-cover__image-background": -1, // Image background inside cover block. - ".wp-block-cover__video-background": -1, // Video background inside cover block. + ".wp-block-cover.has-background-dim::before": 1, // Overlay area inside block cover need to be higher than the video background. + ".block-library-cover__padding-visualizer": 2, // BoxControl visualizer needs to be +1 higher than .wp-block-cover.has-background-dim::before + ".wp-block-cover__image-background": 0, // Image background inside cover block. + ".wp-block-cover__video-background": 0, // Video background inside cover block. ".wp-block-template-part__placeholder-preview-filter-input": 1, // Fixed position appender: diff --git a/packages/block-library/src/cover/editor.scss b/packages/block-library/src/cover/editor.scss index a72b928b55b970..b92c401311beee 100644 --- a/packages/block-library/src/cover/editor.scss +++ b/packages/block-library/src/cover/editor.scss @@ -42,6 +42,7 @@ // Shown while media is being uploaded .components-spinner { position: absolute; + z-index: z-index(".wp-block-cover__inner-container"); top: 50%; left: 50%; transform: translate(-50%, -50%); // Account for spinner dimensions diff --git a/packages/block-library/src/cover/style.scss b/packages/block-library/src/cover/style.scss index 4b2bee7a665970..41b3acf1833fc0 100644 --- a/packages/block-library/src/cover/style.scss +++ b/packages/block-library/src/cover/style.scss @@ -95,8 +95,8 @@ } .wp-block-cover__inner-container { - position: relative; width: 100%; + z-index: z-index(".wp-block-cover__inner-container"); color: inherit; // Reset the fixed LTR direction at the root of the block in RTL languages. /*rtl:raw: direction: rtl; */ From d655af640e94a96299c54a588b8b4ba5d0fb3682 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Tue, 15 Oct 2024 08:46:53 +0200 Subject: [PATCH 1166/1908] Remove the verb Toggle from the Block Inserter button. (#65983) * Remove the verb Toggle from the Block Inserter button. * Adjust tests. * Try to fix performance test. * Try to fix perf test --------- Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: kristastevens <kristastevens@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../src/components/inserter/menu.js | 2 +- packages/e2e-test-utils/src/inserter.js | 14 ++++---- .../components/header/document-tools/index.js | 2 +- .../secondary-sidebar/inserter-sidebar.js | 2 +- .../src/components/document-tools/index.js | 2 +- test/e2e/specs/editor/blocks/columns.spec.js | 6 ++-- test/e2e/specs/editor/blocks/group.spec.js | 2 +- test/e2e/specs/editor/blocks/image.spec.js | 3 +- .../editor/plugins/allowed-blocks.spec.js | 2 +- .../editor/plugins/block-directory.spec.js | 4 +-- .../specs/editor/plugins/block-icons.spec.js | 10 +++--- .../editor/plugins/block-variations.spec.js | 4 +-- .../specs/editor/plugins/child-blocks.spec.js | 6 ++-- .../inner-blocks-allowed-blocks.spec.js | 4 +-- .../editor/plugins/pattern-recursion.spec.js | 4 +-- .../editor/plugins/post-type-locking.spec.js | 5 ++- .../plugins/register-block-type-hooks.spec.js | 2 +- test/e2e/specs/editor/various/a11y.spec.js | 4 +-- .../editor/various/adding-patterns.spec.js | 2 +- .../editor/various/allowed-patterns.spec.js | 4 +-- .../editor/various/block-visibility.spec.js | 12 +++---- .../specs/editor/various/editor-modes.spec.js | 2 +- .../editor/various/inserting-blocks.spec.js | 23 ++++++------- .../editor/various/parsing-patterns.spec.js | 2 +- .../e2e/specs/editor/various/patterns.spec.js | 6 ++-- .../various/shortcut-focus-toolbar.spec.js | 4 +-- .../block-style-variations.spec.js | 2 +- test/e2e/specs/site-editor/pages.spec.js | 4 ++- .../site-editor/site-editor-inserter.spec.js | 7 ++-- test/e2e/specs/site-editor/style-book.spec.js | 2 +- .../e2e/specs/widgets/editing-widgets.spec.js | 4 +-- test/performance/specs/post-editor.spec.js | 32 ++++++++++++------- 32 files changed, 99 insertions(+), 85 deletions(-) diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index fa72728f6de20c..bdd4ff11abceee 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -322,7 +322,7 @@ function InserterMenu( onSelect={ handleSetSelectedTab } onClose={ onClose } selectedTab={ selectedTab } - closeButtonLabel={ __( 'Close block inserter' ) } + closeButtonLabel={ __( 'Close Block Inserter' ) } tabs={ [ { name: 'blocks', diff --git a/packages/e2e-test-utils/src/inserter.js b/packages/e2e-test-utils/src/inserter.js index 5beab3c6205b6e..90ea39b49f00d6 100644 --- a/packages/e2e-test-utils/src/inserter.js +++ b/packages/e2e-test-utils/src/inserter.js @@ -49,12 +49,12 @@ async function isGlobalInserterOpen() { return !! document.querySelector( '.edit-post-header [aria-label="Add block"].is-pressed,' + '.edit-site-header-edit-mode [aria-label="Add block"].is-pressed,' + - '.edit-post-header [aria-label="Toggle block inserter"].is-pressed,' + - '.edit-site-header [aria-label="Toggle block inserter"].is-pressed,' + - '.edit-widgets-header [aria-label="Toggle block inserter"].is-pressed,' + + '.edit-post-header [aria-label="Block Inserter"].is-pressed,' + + '.edit-site-header [aria-label="Block Inserter"].is-pressed,' + + '.edit-widgets-header [aria-label="Block Inserter"].is-pressed,' + '.edit-widgets-header [aria-label="Add block"].is-pressed,' + '.edit-site-header-edit-mode__inserter-toggle.is-pressed,' + - '.editor-header [aria-label="Toggle block inserter"].is-pressed' + '.editor-header [aria-label="Block Inserter"].is-pressed' ); } ); } @@ -68,10 +68,10 @@ export async function toggleGlobalBlockInserter() { '.editor-document-tools__inserter-toggle,' + '.edit-post-header [aria-label="Add block"],' + '.edit-site-header [aria-label="Add block"],' + - '.edit-post-header [aria-label="Toggle block inserter"],' + - '.edit-site-header [aria-label="Toggle block inserter"],' + + '.edit-post-header [aria-label="Block Inserter"],' + + '.edit-site-header [aria-label="Block Inserter"],' + '.edit-widgets-header [aria-label="Add block"],' + - '.edit-widgets-header [aria-label="Toggle block inserter"],' + + '.edit-widgets-header [aria-label="Block Inserter"],' + '.edit-site-header-edit-mode__inserter-toggle' ); } diff --git a/packages/edit-widgets/src/components/header/document-tools/index.js b/packages/edit-widgets/src/components/header/document-tools/index.js index a0d69cde376cf7..567a5e1240747e 100644 --- a/packages/edit-widgets/src/components/header/document-tools/index.js +++ b/packages/edit-widgets/src/components/header/document-tools/index.js @@ -72,7 +72,7 @@ function DocumentTools() { /* translators: button label text should, if possible, be under 16 characters. */ label={ _x( - 'Toggle block inserter', + 'Block Inserter', 'Generic label for block inserter button' ) } size="compact" diff --git a/packages/edit-widgets/src/components/secondary-sidebar/inserter-sidebar.js b/packages/edit-widgets/src/components/secondary-sidebar/inserter-sidebar.js index 156a15e2f460ca..4b26dd306ea0a3 100644 --- a/packages/edit-widgets/src/components/secondary-sidebar/inserter-sidebar.js +++ b/packages/edit-widgets/src/components/secondary-sidebar/inserter-sidebar.js @@ -47,7 +47,7 @@ export default function InserterSidebar() { __next40pxDefaultSize icon={ close } onClick={ closeInserter } - label={ __( 'Close block inserter' ) } + label={ __( 'Close Block Inserter' ) } /> </TagName> <div className="edit-widgets-layout__inserter-panel-content"> diff --git a/packages/editor/src/components/document-tools/index.js b/packages/editor/src/components/document-tools/index.js index 6a8c20c8d70551..146945f7343bf2 100644 --- a/packages/editor/src/components/document-tools/index.js +++ b/packages/editor/src/components/document-tools/index.js @@ -96,7 +96,7 @@ function DocumentTools( { className, disableBlockTools = false } ) { /* translators: button label text should, if possible, be under 16 characters. */ const longLabel = _x( - 'Toggle block inserter', + 'Block Inserter', 'Generic label for block inserter button' ); const shortLabel = ! isInserterOpened ? __( 'Add' ) : __( 'Close' ); diff --git a/test/e2e/specs/editor/blocks/columns.spec.js b/test/e2e/specs/editor/blocks/columns.spec.js index e322a52eeba10b..eea6e321aacb11 100644 --- a/test/e2e/specs/editor/blocks/columns.spec.js +++ b/test/e2e/specs/editor/blocks/columns.spec.js @@ -33,10 +33,8 @@ test.describe( 'Columns', () => { .first() .click(); - // Toggle Block inserter - await page - .locator( 'role=button[name="Toggle block inserter"i]' ) - .click(); + // Block Inserter + await page.locator( 'role=button[name="Block Inserter"i]' ).click(); // Verify Column const inserterOptions = page.locator( diff --git a/test/e2e/specs/editor/blocks/group.spec.js b/test/e2e/specs/editor/blocks/group.spec.js index 871974c1f44dd4..0d815872c0bbb2 100644 --- a/test/e2e/specs/editor/blocks/group.spec.js +++ b/test/e2e/specs/editor/blocks/group.spec.js @@ -14,7 +14,7 @@ test.describe( 'Group', () => { } ) => { // Search for the group block and insert it. const inserterButton = page.locator( - 'role=button[name="Toggle block inserter"i]' + 'role=button[name="Block Inserter"i]' ); await inserterButton.click(); diff --git a/test/e2e/specs/editor/blocks/image.spec.js b/test/e2e/specs/editor/blocks/image.spec.js index 43527b48fbf707..6110a125ff6f7e 100644 --- a/test/e2e/specs/editor/blocks/image.spec.js +++ b/test/e2e/specs/editor/blocks/image.spec.js @@ -437,7 +437,8 @@ test.describe( 'Image', () => { async function openMediaTab() { const blockInserter = page.getByRole( 'button', { - name: 'Toggle block inserter', + name: 'Block Inserter', + exact: true, } ); const isClosed = ( await blockInserter.getAttribute( 'aria-pressed' ) ) === diff --git a/test/e2e/specs/editor/plugins/allowed-blocks.spec.js b/test/e2e/specs/editor/plugins/allowed-blocks.spec.js index 6c8f4ead41c6f9..ed7490afe84fe9 100644 --- a/test/e2e/specs/editor/plugins/allowed-blocks.spec.js +++ b/test/e2e/specs/editor/plugins/allowed-blocks.spec.js @@ -21,7 +21,7 @@ test.describe( 'Allowed Blocks Filter', () => { } ) => { // The paragraph block is available. await page - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); const searchbox = page diff --git a/test/e2e/specs/editor/plugins/block-directory.spec.js b/test/e2e/specs/editor/plugins/block-directory.spec.js index f9bf1f85151864..2fa4ee33e6c1ab 100644 --- a/test/e2e/specs/editor/plugins/block-directory.spec.js +++ b/test/e2e/specs/editor/plugins/block-directory.spec.js @@ -122,7 +122,7 @@ test.describe( 'Block Directory', () => { await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); const blockLibrary = page.getByRole( 'region', { @@ -209,7 +209,7 @@ test.describe( 'Block Directory', () => { await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); const blockLibrary = page.getByRole( 'region', { diff --git a/test/e2e/specs/editor/plugins/block-icons.spec.js b/test/e2e/specs/editor/plugins/block-icons.spec.js index 0418f4200afc05..3a00b41b9e71ed 100644 --- a/test/e2e/specs/editor/plugins/block-icons.spec.js +++ b/test/e2e/specs/editor/plugins/block-icons.spec.js @@ -26,7 +26,7 @@ test.describe( 'Block Icons', () => { test( 'Block with svg icon', async ( { editor, page } ) => { await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); const blockLibrary = page.getByRole( 'region', { @@ -60,7 +60,7 @@ test.describe( 'Block Icons', () => { test( 'Block with dash icon', async ( { editor, page } ) => { await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); const blockLibrary = page.getByRole( 'region', { @@ -100,7 +100,7 @@ test.describe( 'Block Icons', () => { test( 'Block with function icon', async ( { editor, page } ) => { await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); const blockLibrary = page.getByRole( 'region', { @@ -137,7 +137,7 @@ test.describe( 'Block Icons', () => { } ) => { await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); const blockLibrary = page.getByRole( 'region', { @@ -185,7 +185,7 @@ test.describe( 'Block Icons', () => { } ) => { await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); const blockLibrary = page.getByRole( 'region', { diff --git a/test/e2e/specs/editor/plugins/block-variations.spec.js b/test/e2e/specs/editor/plugins/block-variations.spec.js index 653680b48e1e66..3f71d2b57d9fd1 100644 --- a/test/e2e/specs/editor/plugins/block-variations.spec.js +++ b/test/e2e/specs/editor/plugins/block-variations.spec.js @@ -22,7 +22,7 @@ test.describe( 'Block variations', () => { page, } ) => { await page - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); await page @@ -63,7 +63,7 @@ test.describe( 'Block variations', () => { page, } ) => { await page - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); await page diff --git a/test/e2e/specs/editor/plugins/child-blocks.spec.js b/test/e2e/specs/editor/plugins/child-blocks.spec.js index 0cd043c6a46105..765b4040a4b976 100644 --- a/test/e2e/specs/editor/plugins/child-blocks.spec.js +++ b/test/e2e/specs/editor/plugins/child-blocks.spec.js @@ -19,7 +19,7 @@ test.describe( 'Child Blocks', () => { test( 'are hidden from the global block inserter', async ( { page } ) => { const blockInserter = page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ); + .getByRole( 'button', { name: 'Block Inserter', exact: true } ); const blockLibrary = page.getByRole( 'region', { name: 'Block Library', } ); @@ -47,7 +47,7 @@ test.describe( 'Child Blocks', () => { const blockInserter = page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ); + .getByRole( 'button', { name: 'Block Inserter', exact: true } ); const blockLibrary = page .getByRole( 'region', { name: 'Block Library', @@ -85,7 +85,7 @@ test.describe( 'Child Blocks', () => { const blockInserter = page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ); + .getByRole( 'button', { name: 'Block Inserter', exact: true } ); const blockLibrary = page .getByRole( 'region', { name: 'Block Library', diff --git a/test/e2e/specs/editor/plugins/inner-blocks-allowed-blocks.spec.js b/test/e2e/specs/editor/plugins/inner-blocks-allowed-blocks.spec.js index d2dc521f0196bd..4ee6d7a0fc4fec 100644 --- a/test/e2e/specs/editor/plugins/inner-blocks-allowed-blocks.spec.js +++ b/test/e2e/specs/editor/plugins/inner-blocks-allowed-blocks.spec.js @@ -45,7 +45,7 @@ test.describe( 'Allowed Blocks Setting on InnerBlocks', () => { const blockInserter = page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ); + .getByRole( 'button', { name: 'Block Inserter', exact: true } ); const blockLibrary = page .getByRole( 'region', { name: 'Block Library', @@ -92,7 +92,7 @@ test.describe( 'Allowed Blocks Setting on InnerBlocks', () => { const blockInserter = page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ); + .getByRole( 'button', { name: 'Block Inserter', exact: true } ); const blockLibrary = page .getByRole( 'region', { name: 'Block Library', diff --git a/test/e2e/specs/editor/plugins/pattern-recursion.spec.js b/test/e2e/specs/editor/plugins/pattern-recursion.spec.js index 9a8292271be8e1..c688f3580c3701 100644 --- a/test/e2e/specs/editor/plugins/pattern-recursion.spec.js +++ b/test/e2e/specs/editor/plugins/pattern-recursion.spec.js @@ -59,9 +59,9 @@ test.describe( 'Preventing Pattern Recursion (server)', () => { page, editor, } ) => { - // Click the Toggle block inserter button + // Click the Block Inserter button await page - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); // Click the Patterns tab await page.getByRole( 'tab', { name: 'Patterns' } ).click(); diff --git a/test/e2e/specs/editor/plugins/post-type-locking.spec.js b/test/e2e/specs/editor/plugins/post-type-locking.spec.js index af6256d05e02eb..ff02d18c51464b 100644 --- a/test/e2e/specs/editor/plugins/post-type-locking.spec.js +++ b/test/e2e/specs/editor/plugins/post-type-locking.spec.js @@ -208,7 +208,10 @@ test.describe( 'Post-type locking', () => { await expect( page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { + name: 'Block Inserter', + exact: true, + } ) ).toBeEnabled(); await editor.insertBlock( { name: 'core/list' } ); diff --git a/test/e2e/specs/editor/plugins/register-block-type-hooks.spec.js b/test/e2e/specs/editor/plugins/register-block-type-hooks.spec.js index 2ec62ffd056d31..a7e6f970179a4a 100644 --- a/test/e2e/specs/editor/plugins/register-block-type-hooks.spec.js +++ b/test/e2e/specs/editor/plugins/register-block-type-hooks.spec.js @@ -18,7 +18,7 @@ test.describe( 'Register block type hooks', () => { } ); test( 'has a custom category for Paragraph block', async ( { page } ) => { - await page.click( 'role=button[name="Toggle block inserter"i]' ); + await page.click( 'role=button[name="Block Inserter"i]' ); expect( page.locator( diff --git a/test/e2e/specs/editor/various/a11y.spec.js b/test/e2e/specs/editor/various/a11y.spec.js index 8f63b57fda657f..f116476989a133 100644 --- a/test/e2e/specs/editor/various/a11y.spec.js +++ b/test/e2e/specs/editor/various/a11y.spec.js @@ -40,10 +40,10 @@ test.describe( 'a11y (@firefox, @webkit)', () => { // This test assumes the Editor is not in Fullscreen mode. Check the // first tabbable element within the 'Editor top bar' region is the - // 'Toggle block inserter' button. + // 'Block Inserter' button. await pageUtils.pressKeys( 'Tab' ); await expect( - page.locator( 'role=button[name=/Toggle block inserter/i]' ) + page.locator( 'role=button[name=/Block Inserter/i]' ) ).toBeFocused(); } ); diff --git a/test/e2e/specs/editor/various/adding-patterns.spec.js b/test/e2e/specs/editor/various/adding-patterns.spec.js index b634798b455403..3226965b18d703 100644 --- a/test/e2e/specs/editor/various/adding-patterns.spec.js +++ b/test/e2e/specs/editor/various/adding-patterns.spec.js @@ -9,7 +9,7 @@ test.describe( 'adding patterns', () => { } ); test( 'should insert a block pattern', async ( { page, editor } ) => { - await page.getByLabel( 'Toggle block inserter' ).click(); + await page.getByLabel( 'Block Inserter' ).click(); await page.getByRole( 'tab', { name: 'Patterns' } ).click(); await page.fill( diff --git a/test/e2e/specs/editor/various/allowed-patterns.spec.js b/test/e2e/specs/editor/various/allowed-patterns.spec.js index a99b1f5c291066..01ca5ba0480c3a 100644 --- a/test/e2e/specs/editor/various/allowed-patterns.spec.js +++ b/test/e2e/specs/editor/various/allowed-patterns.spec.js @@ -18,7 +18,7 @@ test.describe( 'Allowed Patterns', () => { await admin.createNewPost(); await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); await page @@ -61,7 +61,7 @@ test.describe( 'Allowed Patterns', () => { await admin.createNewPost(); await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); await page diff --git a/test/e2e/specs/editor/various/block-visibility.spec.js b/test/e2e/specs/editor/various/block-visibility.spec.js index 814276af6e25f1..6e4163f4ed5839 100644 --- a/test/e2e/specs/editor/various/block-visibility.spec.js +++ b/test/e2e/specs/editor/various/block-visibility.spec.js @@ -43,7 +43,7 @@ test.describe( 'Block Visibility', () => { .getByRole( 'button', { name: 'Close' } ) .click(); await page - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); await page .getByRole( 'region', { name: 'Block Library' } ) @@ -60,7 +60,7 @@ test.describe( 'Block Visibility', () => { ).toBeHidden(); await page - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); // Show heading block again. @@ -84,7 +84,7 @@ test.describe( 'Block Visibility', () => { .getByRole( 'button', { name: 'Close' } ) .click(); await page - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); await page .getByRole( 'region', { name: 'Block Library' } ) @@ -118,7 +118,7 @@ test.describe( 'Block Visibility', () => { .getByRole( 'button', { name: 'Close' } ) .click(); await page - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); await expect( @@ -129,7 +129,7 @@ test.describe( 'Block Visibility', () => { ).toBeHidden(); await page - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); // Show Media category blocks again. @@ -153,7 +153,7 @@ test.describe( 'Block Visibility', () => { .getByRole( 'button', { name: 'Close' } ) .click(); await page - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); await expect( diff --git a/test/e2e/specs/editor/various/editor-modes.spec.js b/test/e2e/specs/editor/various/editor-modes.spec.js index 95c409f0589e31..4e856e6214ca8c 100644 --- a/test/e2e/specs/editor/various/editor-modes.spec.js +++ b/test/e2e/specs/editor/various/editor-modes.spec.js @@ -115,7 +115,7 @@ test.describe( 'Editing modes (visual/HTML)', () => { await expect( page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) ).toBeDisabled(); // Go back to the visual editor. diff --git a/test/e2e/specs/editor/various/inserting-blocks.spec.js b/test/e2e/specs/editor/various/inserting-blocks.spec.js index 83b919585a695c..29b59b727acfef 100644 --- a/test/e2e/specs/editor/various/inserting-blocks.spec.js +++ b/test/e2e/specs/editor/various/inserting-blocks.spec.js @@ -72,7 +72,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { ); await page.click( - 'role=region[name="Editor top bar"i] >> role=button[name="Toggle block inserter"i]' + 'role=region[name="Editor top bar"i] >> role=button[name="Block Inserter"i]' ); await page.fill( @@ -135,7 +135,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { ); await page.click( - 'role=region[name="Editor top bar"i] >> role=button[name="Toggle block inserter"i]' + 'role=region[name="Editor top bar"i] >> role=button[name="Block Inserter"i]' ); await page.fill( @@ -191,7 +191,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { ); await page.click( - 'role=region[name="Editor top bar"i] >> role=button[name="Toggle block inserter"i]' + 'role=region[name="Editor top bar"i] >> role=button[name="Block Inserter"i]' ); const PATTERN_NAME = 'Standard'; @@ -283,7 +283,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { // Insert a synced pattern. await page.click( - 'role=region[name="Editor top bar"i] >> role=button[name="Toggle block inserter"i]' + 'role=region[name="Editor top bar"i] >> role=button[name="Block Inserter"i]' ); await page.fill( 'role=region[name="Block Library"i] >> role=searchbox[name="Search"i]', @@ -347,7 +347,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { ); await page.click( - 'role=region[name="Editor top bar"i] >> role=button[name="Toggle block inserter"i]' + 'role=region[name="Editor top bar"i] >> role=button[name="Block Inserter"i]' ); const PATTERN_NAME = 'Standard'; @@ -389,7 +389,8 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { await admin.createNewPost(); const inserterButton = page.getByRole( 'button', { - name: 'Toggle block inserter', + name: 'Block Inserter', + exact: true, } ); const blockLibrary = page.getByRole( 'region', { name: 'Block Library', @@ -503,7 +504,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { await editor.selectBlocks( paragraphBlock ); await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); await page .getByRole( 'listbox', { name: 'Text' } ) @@ -624,7 +625,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { await admin.createNewPost(); await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); await page.getByRole( 'option', { name: 'More', exact: true } ).click(); @@ -646,7 +647,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { await admin.createNewPost(); await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); await page .getByRole( 'listbox', { name: 'Text' } ) @@ -674,7 +675,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); await page .getByRole( 'listbox', { name: 'Media' } ) @@ -726,7 +727,7 @@ test.describe( 'insert media from inserter', () => { } ) => { await admin.createNewPost(); - await page.getByLabel( 'Toggle block inserter' ).click(); + await page.getByLabel( 'Block Inserter' ).click(); await page.getByRole( 'tab', { name: 'Media' } ).click(); await page.getByRole( 'tab', { name: 'Images' } ).click(); await page.getByLabel( uploadedMedia.title.raw ).click(); diff --git a/test/e2e/specs/editor/various/parsing-patterns.spec.js b/test/e2e/specs/editor/various/parsing-patterns.spec.js index fd9305d0db786f..d8edc544ffa03c 100644 --- a/test/e2e/specs/editor/various/parsing-patterns.spec.js +++ b/test/e2e/specs/editor/various/parsing-patterns.spec.js @@ -15,7 +15,7 @@ test.describe( 'Parsing patterns', () => { innerBlocks: [ { name: 'core/button', attributes: { text: 'a' } } ], } ); await page.keyboard.press( 'ArrowDown' ); - await page.getByLabel( 'Toggle block inserter' ).click(); + await page.getByLabel( 'Block Inserter' ).click(); await page.getByRole( 'tab', { name: 'Patterns' } ).click(); await page.evaluate( () => { diff --git a/test/e2e/specs/editor/various/patterns.spec.js b/test/e2e/specs/editor/various/patterns.spec.js index 7204f2bace51a5..00a68a9f08ea55 100644 --- a/test/e2e/specs/editor/various/patterns.spec.js +++ b/test/e2e/specs/editor/various/patterns.spec.js @@ -63,7 +63,7 @@ test.describe( 'Unsynced pattern', () => { // Check that the new pattern is available in the inserter and that it gets inserted as // a plain paragraph block. - await page.getByLabel( 'Toggle block inserter' ).click(); + await page.getByLabel( 'Block Inserter' ).click(); await page .getByRole( 'tab', { name: 'Patterns', @@ -166,7 +166,7 @@ test.describe( 'Synced pattern', () => { ).toBe( true ); // Check that the new pattern is available in the inserter. - await page.getByLabel( 'Toggle block inserter' ).click(); + await page.getByLabel( 'Block Inserter' ).click(); await page .getByRole( 'tab', { name: 'Patterns', @@ -496,7 +496,7 @@ test.describe( 'Synced pattern', () => { } ); await page - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); await page .getByRole( 'searchbox', { diff --git a/test/e2e/specs/editor/various/shortcut-focus-toolbar.spec.js b/test/e2e/specs/editor/various/shortcut-focus-toolbar.spec.js index cfaf4e0be9188f..fc54a1a71c8daa 100644 --- a/test/e2e/specs/editor/various/shortcut-focus-toolbar.spec.js +++ b/test/e2e/specs/editor/various/shortcut-focus-toolbar.spec.js @@ -201,11 +201,11 @@ class ToolbarUtils { this.pageUtils = pageUtils; this.documentToolbarButton = this.page.getByRole( 'button', { - name: 'Toggle block inserter', + name: 'Block Inserter', exact: true, } ); this.documentToolbarTooltip = this.page.locator( - 'text=Toggle block inserter' + 'text=Block Inserter' ); this.blockToolbarParagraphButton = this.page.getByRole( 'button', { name: 'Paragraph', diff --git a/test/e2e/specs/site-editor/block-style-variations.spec.js b/test/e2e/specs/site-editor/block-style-variations.spec.js index 97ebc74db8308a..3c642ea9d1299e 100644 --- a/test/e2e/specs/site-editor/block-style-variations.spec.js +++ b/test/e2e/specs/site-editor/block-style-variations.spec.js @@ -318,7 +318,7 @@ async function draftNewPage( page ) { // Create a Group block with 2 nested Group blocks. async function addPageContent( editor, page ) { const inserterButton = page.locator( - 'role=button[name="Toggle block inserter"i]' + 'role=button[name="Block Inserter"i]' ); await inserterButton.click(); await page.type( 'role=searchbox[name="Search"i]', 'Group' ); diff --git a/test/e2e/specs/site-editor/pages.spec.js b/test/e2e/specs/site-editor/pages.spec.js index 7a76db40337c2c..4817651bac8f9d 100644 --- a/test/e2e/specs/site-editor/pages.spec.js +++ b/test/e2e/specs/site-editor/pages.spec.js @@ -36,7 +36,9 @@ async function addPageContent( editor, page ) { .fill( 'Lorem ipsum dolor sit amet' ); // Insert into Page Content using global inserter. - await page.getByRole( 'button', { name: 'Toggle block inserter' } ).click(); + await page + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) + .click(); await page.getByRole( 'option', { name: 'Heading', exact: true } ).click(); await editor.canvas .getByRole( 'document', { diff --git a/test/e2e/specs/site-editor/site-editor-inserter.spec.js b/test/e2e/specs/site-editor/site-editor-inserter.spec.js index acb0c5409f9b09..04075cbedab308 100644 --- a/test/e2e/specs/site-editor/site-editor-inserter.spec.js +++ b/test/e2e/specs/site-editor/site-editor-inserter.spec.js @@ -24,13 +24,13 @@ test.describe( 'Site Editor Inserter', () => { test( 'inserter toggle button should toggle global inserter', async ( { page, } ) => { - await page.click( 'role=button[name="Toggle block inserter"i]' ); + await page.click( 'role=button[name="Block Inserter"i]' ); // Visibility check await expect( page.locator( 'role=searchbox[name="Search"i]' ) ).toBeVisible(); - await page.click( 'role=button[name="Toggle block inserter"i]' ); + await page.click( 'role=button[name="Block Inserter"i]' ); //Hidden State check await expect( page.locator( 'role=searchbox[name="Search"i]' ) @@ -43,7 +43,8 @@ test.describe( 'Site Editor Inserter', () => { editor, } ) => { const inserterButton = page.getByRole( 'button', { - name: 'Toggle block inserter', + name: 'Block Inserter', + exact: true, } ); const blockLibrary = page.getByRole( 'region', { name: 'Block Library', diff --git a/test/e2e/specs/site-editor/style-book.spec.js b/test/e2e/specs/site-editor/style-book.spec.js index 3f871d28ef941b..9a34f30f82ff9c 100644 --- a/test/e2e/specs/site-editor/style-book.spec.js +++ b/test/e2e/specs/site-editor/style-book.spec.js @@ -29,7 +29,7 @@ test.describe( 'Style Book', () => { test( 'should disable toolbar buttons when open', async ( { page } ) => { await expect( - page.locator( 'role=button[name="Toggle block inserter"i]' ) + page.locator( 'role=button[name="Block Inserter"i]' ) ).toBeDisabled(); await expect( page.locator( 'role=button[name="Tools"i]' ) diff --git a/test/e2e/specs/widgets/editing-widgets.spec.js b/test/e2e/specs/widgets/editing-widgets.spec.js index 92a264492c018d..019e07fe87daac 100644 --- a/test/e2e/specs/widgets/editing-widgets.spec.js +++ b/test/e2e/specs/widgets/editing-widgets.spec.js @@ -56,7 +56,7 @@ test.describe( 'Widgets screen', () => { await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); const blockLibrary = page.getByRole( 'region', { name: 'Block Library', @@ -698,7 +698,7 @@ class WidgetsScreen { if ( await blockLibrary.isHidden() ) { await this.#page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'Toggle block inserter' } ) + .getByRole( 'button', { name: 'Block Inserter', exact: true } ) .click(); } diff --git a/test/performance/specs/post-editor.spec.js b/test/performance/specs/post-editor.spec.js index 20925ebb36587f..becbf375eff2ac 100644 --- a/test/performance/specs/post-editor.spec.js +++ b/test/performance/specs/post-editor.spec.js @@ -368,9 +368,11 @@ test.describe( 'Post Editor Performance', () => { // Go to the test page. await admin.editPost( draftId ); await perfUtils.disableAutosave(); - const globalInserterToggle = page.getByRole( 'button', { - name: 'Toggle block inserter', - } ); + const globalInserterToggle = page + .getByRole( 'region', { name: 'Editor top bar' } ) + .getByRole( 'button', { + name: 'Block Inserter', + } ); const samples = 10; const throwaway = 1; @@ -424,9 +426,11 @@ test.describe( 'Post Editor Performance', () => { // Go to the test page. await admin.editPost( draftId ); await perfUtils.disableAutosave(); - const globalInserterToggle = page.getByRole( 'button', { - name: 'Toggle block inserter', - } ); + const globalInserterToggle = page + .getByRole( 'region', { name: 'Editor top bar' } ) + .getByRole( 'button', { + name: 'Block Inserter', + } ); // Open Inserter. await globalInserterToggle.click(); @@ -483,9 +487,11 @@ test.describe( 'Post Editor Performance', () => { await admin.editPost( draftId ); await perfUtils.disableAutosave(); - const globalInserterToggle = page.getByRole( 'button', { - name: 'Toggle block inserter', - } ); + const globalInserterToggle = page + .getByRole( 'region', { name: 'Editor top bar' } ) + .getByRole( 'button', { + name: 'Block Inserter', + } ); const paragraphBlockItem = page.locator( '.block-editor-inserter__menu .editor-block-list-item-paragraph' ); @@ -535,9 +541,11 @@ test.describe( 'Post Editor Performance', () => { test( 'Run the test', async ( { page, admin, perfUtils } ) => { await admin.createNewPost(); await perfUtils.disableAutosave(); - const globalInserterToggle = page.getByRole( 'button', { - name: 'Toggle block inserter', - } ); + const globalInserterToggle = page + .getByRole( 'region', { name: 'Editor top bar' } ) + .getByRole( 'button', { + name: 'Block Inserter', + } ); const testPatterns = [ { From 926290659088d5b5515de01577da927b00444418 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:26:59 +0200 Subject: [PATCH 1167/1908] Add initial tests for image rendering (#66010) - Add initial tests for image rendering Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- phpunit/blocks/render-block-image-test.php | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 phpunit/blocks/render-block-image-test.php diff --git a/phpunit/blocks/render-block-image-test.php b/phpunit/blocks/render-block-image-test.php new file mode 100644 index 00000000000000..fe39aee8c50b9d --- /dev/null +++ b/phpunit/blocks/render-block-image-test.php @@ -0,0 +1,62 @@ +<?php +/** + * Image block rendering tests. + * + * @package WordPress + * @subpackage Blocks + */ + +/** + * Tests for the Image block. + * + * @group blocks + */ +class Tests_Blocks_Render_Image extends WP_UnitTestCase { + /** + * @covers ::render_block_core_image + */ + public function test_should_render_block_core_image_when_src_is_defined() { + $attributes = array(); + $content = '<figure class="wp-block-image"><img src="http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/2021/04/canola.jpg" aria-label="test render"/></figure>'; + $parsed_blocks = parse_blocks( + '<!-- wp:image -->' + ); + $parsed_block = $parsed_blocks[0]; + $block = new WP_Block( $parsed_block ); + + $rendered_block = gutenberg_render_block_core_image( $attributes, $content, $block ); + $this->assertStringContainsString( 'aria-label="test render"', $rendered_block ); + } + + /** + * @covers ::render_block_core_image + */ + public function test_should_not_render_block_core_image_when_src_is_not_defined() { + $attributes = array(); + $content = '<figure class="wp-block-image"><img /></figure>'; + $parsed_blocks = parse_blocks( + '<!-- wp:image -->' + ); + $parsed_block = $parsed_blocks[0]; + $block = new WP_Block( $parsed_block ); + + $rendered_block = gutenberg_render_block_core_image( $attributes, $content, $block ); + $this->assertEquals( '', $rendered_block ); + } + + /** + * @covers ::render_block_core_image + */ + public function test_should_not_render_block_core_image_when_src_is_empty_string() { + $attributes = array(); + $content = '<figure class="wp-block-image"><img src=""/></figure>'; + $parsed_blocks = parse_blocks( + '<!-- wp:image -->' + ); + $parsed_block = $parsed_blocks[0]; + $block = new WP_Block( $parsed_block ); + + $rendered_block = gutenberg_render_block_core_image( $attributes, $content, $block ); + $this->assertEquals( '', $rendered_block ); + } +} From 1e8f5e01d7d2f43cd16f00aef03f3d16f543ae2f Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Tue, 15 Oct 2024 11:12:05 +0200 Subject: [PATCH 1168/1908] Block Bindings: Bootstrap server sources earlier (#66058) * Remove bindings bootstrap functions * Remove bootstrap calls * Remove old filter * Adapt unit tests * Add compat filter in Gutenberg * Only run script if not already registered * Remove extra label in test * Remove unit test * Add backport changelog * Return warning if any client-only prop is defined Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: ryanwelcher <welcher@git.wordpress.org> --- backport-changelog/6.7/7552.md | 3 + lib/compat/wordpress-6.7/block-bindings.php | 42 +++++-------- packages/blocks/src/api/registration.js | 15 +++-- packages/blocks/src/api/test/registration.js | 60 +++---------------- packages/blocks/src/store/private-actions.js | 14 ----- packages/blocks/src/store/reducer.js | 16 ----- packages/customize-widgets/src/index.js | 8 +-- .../e2e-tests/plugins/block-bindings/index.js | 1 - packages/edit-post/src/index.js | 2 - packages/edit-site/src/index.js | 6 +- packages/edit-widgets/src/index.js | 6 +- packages/editor/src/bindings/api.js | 33 +--------- packages/editor/src/private-apis.js | 6 +- 13 files changed, 41 insertions(+), 171 deletions(-) create mode 100644 backport-changelog/6.7/7552.md diff --git a/backport-changelog/6.7/7552.md b/backport-changelog/6.7/7552.md new file mode 100644 index 00000000000000..d304162b3cae67 --- /dev/null +++ b/backport-changelog/6.7/7552.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7552 + +* https://github.com/WordPress/gutenberg/pull/66058 diff --git a/lib/compat/wordpress-6.7/block-bindings.php b/lib/compat/wordpress-6.7/block-bindings.php index a8f68c0f0f04ea..70ba523ac966ea 100644 --- a/lib/compat/wordpress-6.7/block-bindings.php +++ b/lib/compat/wordpress-6.7/block-bindings.php @@ -6,38 +6,28 @@ */ /** - * Adds the block bindings sources registered in the server to the editor settings. - * - * This allows them to be bootstrapped in the editor. - * - * @param array $settings The block editor settings from the `block_editor_settings_all` filter. - * @return array The editor settings including the block bindings sources. + * Bootstrap the block bindings sources registered in the server. */ -function gutenberg_add_server_block_bindings_sources_to_editor_settings( $editor_settings ) { - // Check if the sources are already exposed in the editor settings. - if ( isset( $editor_settings['blockBindingsSources'] ) ) { - return $editor_settings; - } - - $registered_block_bindings_sources = get_all_registered_block_bindings_sources(); - if ( ! empty( $registered_block_bindings_sources ) ) { - // Initialize array. - $editor_settings['blockBindingsSources'] = array(); - foreach ( $registered_block_bindings_sources as $source_name => $source_properties ) { - // Add source with the label to editor settings. - $editor_settings['blockBindingsSources'][ $source_name ] = array( - 'label' => $source_properties->label, +function gutenberg_bootstrap_server_block_bindings_sources() { + $registered_sources = get_all_registered_block_bindings_sources(); + if ( ! empty( $registered_sources ) ) { + $filtered_sources = array(); + foreach ( $registered_sources as $source ) { + $filtered_sources[] = array( + 'name' => $source->name, + 'label' => $source->label, + 'usesContext' => $source->uses_context, ); - // Add `usesContext` property if exists. - if ( ! empty( $source_properties->uses_context ) ) { - $editor_settings['blockBindingsSources'][ $source_name ]['usesContext'] = $source_properties->uses_context; - } } + $script = sprintf( 'for ( const source of %s ) { ! wp.blocks.getBlockBindingsSource( source.name ) && wp.blocks.registerBlockBindingsSource( source ); }', wp_json_encode( $filtered_sources ) ); + wp_add_inline_script( + 'wp-blocks', + $script + ); } - return $editor_settings; } -add_filter( 'block_editor_settings_all', 'gutenberg_add_server_block_bindings_sources_to_editor_settings', 10 ); +add_action( 'enqueue_block_editor_assets', 'gutenberg_bootstrap_server_block_bindings_sources', 5 ); /** * Initialize `canUpdateBlockBindings` editor setting if it doesn't exist. By default, it is `true` only for admin users. diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 31be38b861c284..ae12b0cfbcf49d 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -809,13 +809,16 @@ export const registerBlockBindingsSource = ( source ) => { /* * Check if the source has been already registered on the client. - * If the `getValues` property is defined, it could be assumed the source is already registered. + * If any property expected to be "client-only" is defined, return a warning. */ - if ( existingSource?.getValues ) { - warning( - 'Block bindings source "' + name + '" is already registered.' - ); - return; + const serverProps = [ 'label', 'usesContext' ]; + for ( const prop in existingSource ) { + if ( ! serverProps.includes( prop ) && existingSource[ prop ] ) { + warning( + 'Block bindings source "' + name + '" is already registered.' + ); + return; + } } // Check the `name` property is correct. diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index 483949af4fe5f2..99ca6390d2d3b1 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -1513,10 +1513,8 @@ describe( 'blocks', () => { } ); it( 'should not override label from the server', () => { - // Bootstrap source from the server. - unlock( - dispatch( blocksStore ) - ).addBootstrappedBlockBindingsSource( { + // Simulate bootstrap source from the server. + registerBlockBindingsSource( { name: 'core/server', label: 'Server label', } ); @@ -1543,10 +1541,8 @@ describe( 'blocks', () => { } ); it( 'should add usesContext when only defined in the server', () => { - // Bootstrap source from the server. - unlock( - dispatch( blocksStore ) - ).addBootstrappedBlockBindingsSource( { + // Simulate bootstrap source from the server. + registerBlockBindingsSource( { name: 'core/testing', label: 'testing', usesContext: [ 'postId', 'postType' ], @@ -1562,10 +1558,8 @@ describe( 'blocks', () => { } ); it( 'should add usesContext when only defined in the client', () => { - // Bootstrap source from the server. - unlock( - dispatch( blocksStore ) - ).addBootstrappedBlockBindingsSource( { + // Simulate bootstrap source from the server. + registerBlockBindingsSource( { name: 'core/testing', label: 'testing', } ); @@ -1581,10 +1575,8 @@ describe( 'blocks', () => { } ); it( 'should merge usesContext from server and client without duplicates', () => { - // Bootstrap source from the server. - unlock( - dispatch( blocksStore ) - ).addBootstrappedBlockBindingsSource( { + // Simulate bootstrap source from the server. + registerBlockBindingsSource( { name: 'core/testing', label: 'testing', usesContext: [ 'postId', 'postType' ], @@ -1705,42 +1697,6 @@ describe( 'blocks', () => { 'Block bindings source "core/test-source" is already registered.' ); } ); - - it( 'should correctly merge properties when bootstrap happens after registration', () => { - // Register source in the client. - const clientOnlyProperties = { - getValues: () => 'values', - setValues: () => 'new values', - canUserEditValue: () => true, - }; - registerBlockBindingsSource( { - name: 'core/custom-source', - label: 'Client Label', - usesContext: [ 'postId', 'postType' ], - ...clientOnlyProperties, - } ); - - // Bootstrap source from the server. - unlock( - dispatch( blocksStore ) - ).addBootstrappedBlockBindingsSource( { - name: 'core/custom-source', - label: 'Server Label', - usesContext: [ 'postId', 'serverContext' ], - } ); - - // Check that the bootstrap values prevail and the client properties are still there. - expect( getBlockBindingsSource( 'core/custom-source' ) ).toEqual( { - // Should use the server label. - label: 'Server Label', - // Should merge usesContext from server and client. - usesContext: [ 'postId', 'postType', 'serverContext' ], - // Should keep client properties. - ...clientOnlyProperties, - } ); - - unregisterBlockBindingsSource( 'core/custom-source' ); - } ); } ); describe( 'unregisterBlockBindingsSource', () => { diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index 02f8506b3c3bf8..bfefe56773d77a 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -70,17 +70,3 @@ export function removeBlockBindingsSource( name ) { name, }; } - -/** - * Add bootstrapped block bindings sources, usually initialized from the server. - * - * @param {string} source Name of the source to bootstrap. - */ -export function addBootstrappedBlockBindingsSource( source ) { - return { - type: 'ADD_BOOTSTRAPPED_BLOCK_BINDINGS_SOURCE', - name: source.name, - label: source.label, - usesContext: source.usesContext, - }; -} diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 7c7fb4763a1cb6..16594a79271e6c 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -417,22 +417,6 @@ export function blockBindingsSources( state = {}, action ) { getFieldsList, }, }; - case 'ADD_BOOTSTRAPPED_BLOCK_BINDINGS_SOURCE': - return { - ...state, - [ action.name ]: { - /* - * Keep the exisitng properties in case the source has been registered - * in the client before bootstrapping. - */ - ...state[ action.name ], - label: action.label, - usesContext: getMergedUsesContext( - state[ action.name ]?.usesContext, - action.usesContext - ), - }, - }; case 'REMOVE_BLOCK_BINDINGS_SOURCE': return omit( state, action.name ); } diff --git a/packages/customize-widgets/src/index.js b/packages/customize-widgets/src/index.js index 35be3c2ee4b14b..df96d645ee7007 100644 --- a/packages/customize-widgets/src/index.js +++ b/packages/customize-widgets/src/index.js @@ -39,10 +39,7 @@ const DISABLED_BLOCKS = [ ]; const ENABLE_EXPERIMENTAL_FSE_BLOCKS = false; -const { - registerCoreBlockBindingsSources, - bootstrapBlockBindingsSourcesFromServer, -} = unlock( editorPrivateApis ); +const { registerCoreBlockBindingsSources } = unlock( editorPrivateApis ); /** * Initializes the widgets block editor in the customizer. @@ -67,9 +64,6 @@ export function initialize( editorName, blockEditorSettings ) { ); } ); registerCoreBlocks( coreBlocks ); - bootstrapBlockBindingsSourcesFromServer( - blockEditorSettings?.blockBindingsSources - ); registerCoreBlockBindingsSources(); registerLegacyWidgetBlock(); if ( globalThis.IS_GUTENBERG_PLUGIN ) { diff --git a/packages/e2e-tests/plugins/block-bindings/index.js b/packages/e2e-tests/plugins/block-bindings/index.js index c31502631307d0..5c364257caed19 100644 --- a/packages/e2e-tests/plugins/block-bindings/index.js +++ b/packages/e2e-tests/plugins/block-bindings/index.js @@ -19,7 +19,6 @@ const setValues = ( { dispatch, bindings } ) => { registerBlockBindingsSource( { name: 'testing/complete-source', - label: 'Complete Source', getValues, setValues, canUserEditValue: () => true, diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index daf789cb0a2ec9..685ffc56f63a80 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -28,7 +28,6 @@ import { unlock } from './lock-unlock'; const { BackButton: __experimentalMainDashboardButton, registerCoreBlockBindingsSources, - bootstrapBlockBindingsSourcesFromServer, } = unlock( editorPrivateApis ); /** @@ -95,7 +94,6 @@ export function initializeEditor( } registerCoreBlocks(); - bootstrapBlockBindingsSourcesFromServer( settings?.blockBindingsSources ); registerCoreBlockBindingsSources(); registerLegacyWidgetBlock( { inserter: false } ); registerWidgetGroupBlock( { inserter: false } ); diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 1aceecc4d8b1fc..83d25bcd0c03ac 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -28,10 +28,7 @@ import { store as editSiteStore } from './store'; import { unlock } from './lock-unlock'; import App from './components/app'; -const { - registerCoreBlockBindingsSources, - bootstrapBlockBindingsSourcesFromServer, -} = unlock( editorPrivateApis ); +const { registerCoreBlockBindingsSources } = unlock( editorPrivateApis ); /** * Initializes the site editor screen. @@ -48,7 +45,6 @@ export function initializeEditor( id, settings ) { ( { name } ) => name !== 'core/freeform' ); registerCoreBlocks( coreBlocks ); - bootstrapBlockBindingsSourcesFromServer( settings?.blockBindingsSources ); registerCoreBlockBindingsSources(); dispatch( blocksStore ).setFreeformFallbackBlockName( 'core/html' ); registerLegacyWidgetBlock( { inserter: false } ); diff --git a/packages/edit-widgets/src/index.js b/packages/edit-widgets/src/index.js index fadd488a702cfe..8788ee2b99ea1d 100644 --- a/packages/edit-widgets/src/index.js +++ b/packages/edit-widgets/src/index.js @@ -44,10 +44,7 @@ const disabledBlocks = [ ...( ALLOW_REUSABLE_BLOCKS ? [] : [ 'core/block' ] ), ]; -const { - registerCoreBlockBindingsSources, - bootstrapBlockBindingsSourcesFromServer, -} = unlock( editorPrivateApis ); +const { registerCoreBlockBindingsSources } = unlock( editorPrivateApis ); /** * Initializes the block editor in the widgets screen. @@ -78,7 +75,6 @@ export function initializeEditor( id, settings ) { dispatch( blocksStore ).reapplyBlockTypeFilters(); registerCoreBlocks( coreBlocks ); - bootstrapBlockBindingsSourcesFromServer( settings?.blockBindingsSources ); registerCoreBlockBindingsSources(); registerLegacyWidgetBlock(); if ( globalThis.IS_GUTENBERG_PLUGIN ) { diff --git a/packages/editor/src/bindings/api.js b/packages/editor/src/bindings/api.js index 84003fab7eaf7b..2d32d76abbc3bc 100644 --- a/packages/editor/src/bindings/api.js +++ b/packages/editor/src/bindings/api.js @@ -1,18 +1,13 @@ /** * WordPress dependencies */ -import { - store as blocksStore, - registerBlockBindingsSource, -} from '@wordpress/blocks'; -import { dispatch } from '@wordpress/data'; +import { registerBlockBindingsSource } from '@wordpress/blocks'; /** * Internal dependencies */ import patternOverrides from './pattern-overrides'; import postMeta from './post-meta'; -import { unlock } from '../lock-unlock'; /** * Function to register core block bindings sources provided by the editor. @@ -28,29 +23,3 @@ export function registerCoreBlockBindingsSources() { registerBlockBindingsSource( patternOverrides ); registerBlockBindingsSource( postMeta ); } - -/** - * Function to bootstrap core block bindings sources defined in the server. - * - * @param {Object} sources Object containing the sources to bootstrap. - * - * @example - * ```js - * import { bootstrapBlockBindingsSourcesFromServer } from '@wordpress/editor'; - * - * bootstrapBlockBindingsSourcesFromServer( sources ); - * ``` - */ -export function bootstrapBlockBindingsSourcesFromServer( sources ) { - if ( sources ) { - const { addBootstrappedBlockBindingsSource } = unlock( - dispatch( blocksStore ) - ); - for ( const [ name, args ] of Object.entries( sources ) ) { - addBootstrappedBlockBindingsSource( { - name, - ...args, - } ); - } - } -} diff --git a/packages/editor/src/private-apis.js b/packages/editor/src/private-apis.js index d4a5c3eebbb4ce..f9a6d4d17904ee 100644 --- a/packages/editor/src/private-apis.js +++ b/packages/editor/src/private-apis.js @@ -23,10 +23,7 @@ import { mergeBaseAndUserConfigs, GlobalStylesProvider, } from './components/global-styles-provider'; -import { - registerCoreBlockBindingsSources, - bootstrapBlockBindingsSourcesFromServer, -} from './bindings/api'; +import { registerCoreBlockBindingsSources } from './bindings/api'; const { store: interfaceStore, ...remainingInterfaceApis } = interfaceApis; @@ -47,7 +44,6 @@ lock( privateApis, { ViewMoreMenuGroup, ResizableEditor, registerCoreBlockBindingsSources, - bootstrapBlockBindingsSourcesFromServer, // This is a temporary private API while we're updating the site editor to use EditorProvider. interfaceStore, From 9671329c386d2b743f14ef314823fbf915366ebd Mon Sep 17 00:00:00 2001 From: Andrei Draganescu <andrei.draganescu@automattic.com> Date: Tue, 15 Oct 2024 13:31:32 +0300 Subject: [PATCH 1169/1908] Make zoom out vertical toolbar consistent (#65627) * enable vertical toolbar for non full width elements, anchor based on parent * Update packages/block-editor/src/components/block-popover/index.js Co-authored-by: Dave Smith <getdavemail@gmail.com> * Update packages/block-editor/src/components/block-popover/index.js Co-authored-by: Dave Smith <getdavemail@gmail.com> * make zoom out check a dependency of the memoization, improve code readability * comment typos * subscribe to state instead of calculating zoom out view state when calculating the anchor * get the section wrapper for anchoring instead of the parent * use a selector instead of computing on the fly the parent section * check if the block element exists yet before computing the anchor * check if the block element exists yet before computing the anchor * differentiate between section toolbar and block toolbar for correct positioning when both are visible * address some nits * make the select in anchor setting rerun when block selection changes * fix bug with anchor rect when zoom out not engaged * fix typo * Use root container element in post editor as popover anchor * improve comment * improve comment to max improvement possible Co-authored-by: Dave Smith <getdavemail@gmail.com> * mega nit commit Co-authored-by: Dave Smith <getdavemail@gmail.com> * Fix bug with Posts with no full width blocks * give up on section root, always seek canvas element to position vertical toolbar, also fix typo * introduce the concept of canvas via a 1st variable * Use `__unstableContentRef` for zoomed out toolbar positioning instead of dom classname --------- Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- .../src/components/block-popover/index.js | 66 ++++++++++++++++++- .../block-tools/use-show-block-tools.js | 13 +++- .../block-tools/zoom-out-popover.js | 3 +- 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 47022e336e4869..637ab1cb8a53e0 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -8,6 +8,7 @@ import clsx from 'clsx'; */ import { useMergeRefs } from '@wordpress/compose'; import { Popover } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; import { forwardRef, useMemo, @@ -21,6 +22,8 @@ import { import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; import usePopoverScroll from './use-popover-scroll'; import { rectUnion, getVisibleElementBounds } from '../../utils/dom'; +import { store as blockEditorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; const MAX_POPOVER_RECOMPUTE_COUNTER = Number.MAX_SAFE_INTEGER; @@ -74,12 +77,38 @@ function BlockPopover( }; }, [ selectedElement ] ); + const { isZoomOut, parentSectionBlock, isSectionSelected } = useSelect( + ( select ) => { + const { + isZoomOut: isZoomOutSelector, + getSectionRootClientId, + getParentSectionBlock, + getBlockOrder, + } = unlock( select( blockEditorStore ) ); + + return { + isZoomOut: isZoomOutSelector(), + parentSectionBlock: + getParentSectionBlock( clientId ) ?? clientId, + isSectionSelected: getBlockOrder( + getSectionRootClientId() + ).includes( clientId ), + }; + }, + [ clientId ] + ); + + // This element is used to position the zoom out view vertical toolbar + // correctly, relative to the selected section. + const parentSectionElement = useBlockElement( parentSectionBlock ); + const popoverAnchor = useMemo( () => { if ( // popoverDimensionsRecomputeCounter is by definition always equal or greater // than 0. This check is only there to satisfy the correctness of the // exhaustive-deps rule for the `useMemo` hook. popoverDimensionsRecomputeCounter < 0 || + ( isZoomOut && ! parentSectionElement ) || ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) { @@ -88,6 +117,35 @@ function BlockPopover( return { getBoundingClientRect() { + // The zoom out view has a vertical block toolbar that should always + // be on the edge of the canvas, aligned to the top of the currently + // selected section. This condition changes the anchor of the toolbar + // to the section instead of the block to handle blocks that are + // not full width and nested blocks to keep section height. + if ( isZoomOut && isSectionSelected ) { + // Compute the height based on the parent section of the + // selected block, because the selected block may be + // shorter than the section. + const canvasElementRect = getVisibleElementBounds( + __unstableContentRef.current + ); + const parentSectionElementRect = + getVisibleElementBounds( parentSectionElement ); + const anchorHeight = + parentSectionElementRect.bottom - + parentSectionElementRect.top; + + // Always use the width of the section root element to make sure + // the toolbar is always on the edge of the canvas. + const anchorWidth = canvasElementRect.width; + return new window.DOMRectReadOnly( + canvasElementRect.left, + parentSectionElementRect.top, + anchorWidth, + anchorHeight + ); + } + return lastSelectedElement ? rectUnion( getVisibleElementBounds( selectedElement ), @@ -98,10 +156,14 @@ function BlockPopover( contextElement: selectedElement, }; }, [ + popoverDimensionsRecomputeCounter, + isZoomOut, + parentSectionElement, + selectedElement, bottomClientId, lastSelectedElement, - selectedElement, - popoverDimensionsRecomputeCounter, + isSectionSelected, + __unstableContentRef, ] ); if ( ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) { diff --git a/packages/block-editor/src/components/block-tools/use-show-block-tools.js b/packages/block-editor/src/components/block-tools/use-show-block-tools.js index 02a8f0583bcddf..97737b4ec2f5b4 100644 --- a/packages/block-editor/src/components/block-tools/use-show-block-tools.js +++ b/packages/block-editor/src/components/block-tools/use-show-block-tools.js @@ -8,6 +8,7 @@ import { isUnmodifiedDefaultBlock } from '@wordpress/blocks'; * Internal dependencies */ import { store as blockEditorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; /** * Source of truth for which block tools are showing in the block editor. @@ -24,7 +25,9 @@ export function useShowBlockTools() { getSettings, __unstableGetEditorMode, isTyping, - } = select( blockEditorStore ); + getBlockOrder, + getSectionRootClientId, + } = unlock( select( blockEditorStore ) ); const clientId = getSelectedBlockClientId() || getFirstMultiSelectedBlockClientId(); @@ -42,10 +45,14 @@ export function useShowBlockTools() { editorMode === 'edit' && isEmptyDefaultBlock; const isZoomOut = editorMode === 'zoom-out'; + const isSectionSelected = getBlockOrder( + getSectionRootClientId() + ).includes( clientId ); const _showZoomOutToolbar = + clientId && isZoomOut && - block?.attributes?.align === 'full' && - ! _showEmptyBlockSideInserter; + ! _showEmptyBlockSideInserter && + isSectionSelected; const _showBlockToolbarPopover = ! _showZoomOutToolbar && ! getSettings().hasFixedToolbar && diff --git a/packages/block-editor/src/components/block-tools/zoom-out-popover.js b/packages/block-editor/src/components/block-tools/zoom-out-popover.js index a1f2990a5cc1ef..7a5c2243cf0540 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-popover.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-popover.js @@ -5,7 +5,7 @@ import clsx from 'clsx'; /** * Internal dependencies */ -import BlockPopover from '../block-popover'; +import { PrivateBlockPopover as BlockPopover } from '../block-popover'; import useBlockToolbarPopoverProps from './use-block-toolbar-popover-props'; import useSelectedBlockToolProps from './use-selected-block-tool-props'; import ZoomOutToolbar from './zoom-out-toolbar'; @@ -29,6 +29,7 @@ export default function ZoomOutPopover( { clientId, __unstableContentRef } ) { return ( <BlockPopover + __unstableContentRef={ __unstableContentRef } clientId={ capturingClientId || clientId } bottomClientId={ lastClientId } className={ clsx( 'zoom-out-toolbar-popover', { From f55063e9bad7ad33bc547d0b1ee926ada0388c24 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:35:54 +0530 Subject: [PATCH 1170/1908] Refactor setting panel of cover block control (#65432) Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- .../src/cover/edit/inspector-controls.js | 147 ++++++++++++------ packages/block-library/src/cover/test/edit.js | 4 +- 2 files changed, 105 insertions(+), 46 deletions(-) diff --git a/packages/block-library/src/cover/edit/inspector-controls.js b/packages/block-library/src/cover/edit/inspector-controls.js index fd83ba716ddd45..2ed9b055d49f35 100644 --- a/packages/block-library/src/cover/edit/inspector-controls.js +++ b/packages/block-library/src/cover/edit/inspector-controls.js @@ -5,12 +5,12 @@ import { useMemo } from '@wordpress/element'; import { ExternalLink, FocalPointPicker, - PanelBody, RangeControl, TextareaControl, ToggleControl, SelectControl, __experimentalUseCustomUnits as useCustomUnits, + __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, __experimentalUnitControl as UnitControl, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, @@ -31,6 +31,7 @@ import { __ } from '@wordpress/i18n'; */ import { COVER_MIN_HEIGHT, mediaPosition } from '../shared'; import { unlock } from '../../lock-unlock'; +import { useToolsPanelDropdownMenuProps } from '../../utils/hooks'; const { cleanEmptyObject } = unlock( blockEditorPrivateApis ); @@ -160,72 +161,130 @@ export default function CoverInspectorControls( { ), }; + const dropdownMenuProps = useToolsPanelDropdownMenuProps(); + return ( <> <InspectorControls> { !! url && ( - <PanelBody title={ __( 'Settings' ) }> + <ToolsPanel + label={ __( 'Settings' ) } + resetAll={ () => { + setAttributes( { + hasParallax: false, + focalPoint: undefined, + isRepeated: false, + alt: '', + } ); + } } + dropdownMenuProps={ dropdownMenuProps } + > { isImageBackground && ( <> - <ToggleControl - __nextHasNoMarginBottom + <ToolsPanelItem label={ __( 'Fixed background' ) } - checked={ hasParallax } - onChange={ toggleParallax } - /> + isShownByDefault + hasValue={ () => hasParallax } + onDeselect={ () => + setAttributes( { + hasParallax: false, + focalPoint: undefined, + } ) + } + > + <ToggleControl + __nextHasNoMarginBottom + label={ __( 'Fixed background' ) } + checked={ hasParallax } + onChange={ toggleParallax } + /> + </ToolsPanelItem> - <ToggleControl - __nextHasNoMarginBottom + <ToolsPanelItem label={ __( 'Repeated background' ) } - checked={ isRepeated } - onChange={ toggleIsRepeated } - /> + isShownByDefault + hasValue={ () => isRepeated } + onDeselect={ () => + setAttributes( { + isRepeated: false, + } ) + } + > + <ToggleControl + __nextHasNoMarginBottom + label={ __( 'Repeated background' ) } + checked={ isRepeated } + onChange={ toggleIsRepeated } + /> + </ToolsPanelItem> </> ) } { showFocalPointPicker && ( - <FocalPointPicker - __nextHasNoMarginBottom + <ToolsPanelItem label={ __( 'Focal point' ) } - url={ url } - value={ focalPoint } - onDragStart={ imperativeFocalPointPreview } - onDrag={ imperativeFocalPointPreview } - onChange={ ( newFocalPoint ) => + isShownByDefault + hasValue={ () => !! focalPoint } + onDeselect={ () => setAttributes( { - focalPoint: newFocalPoint, + focalPoint: undefined, } ) } - /> + > + <FocalPointPicker + __nextHasNoMarginBottom + label={ __( 'Focal point' ) } + url={ url } + value={ focalPoint } + onDragStart={ imperativeFocalPointPreview } + onDrag={ imperativeFocalPointPreview } + onChange={ ( newFocalPoint ) => + setAttributes( { + focalPoint: newFocalPoint, + } ) + } + /> + </ToolsPanelItem> ) } { ! useFeaturedImage && url && ! isVideoBackground && ( - <TextareaControl - __nextHasNoMarginBottom + <ToolsPanelItem label={ __( 'Alternative text' ) } - value={ alt } - onChange={ ( newAlt ) => - setAttributes( { alt: newAlt } ) + isShownByDefault + hasValue={ () => !! alt } + onDeselect={ () => + setAttributes( { alt: '' } ) } - help={ - <> - <ExternalLink - href={ - // translators: Localized tutorial, if one exists. W3C Web Accessibility Initiative link has list of existing translations. - __( - 'https://www.w3.org/WAI/tutorials/images/decision-tree/' - ) - } - > + > + <TextareaControl + __nextHasNoMarginBottom + label={ __( 'Alternative text' ) } + value={ alt } + onChange={ ( newAlt ) => + setAttributes( { alt: newAlt } ) + } + help={ + <> + <ExternalLink + href={ + // translators: Localized tutorial, if one exists. W3C Web Accessibility Initiative link has list of existing translations. + __( + 'https://www.w3.org/WAI/tutorials/images/decision-tree/' + ) + } + > + { __( + 'Describe the purpose of the image.' + ) } + </ExternalLink> + <br /> { __( - 'Describe the purpose of the image.' + 'Leave empty if decorative.' ) } - </ExternalLink> - <br /> - { __( 'Leave empty if decorative.' ) } - </> - } - /> + </> + } + /> + </ToolsPanelItem> ) } - </PanelBody> + </ToolsPanel> ) } </InspectorControls> { colorGradientSettings.hasColorsOrGradients && ( diff --git a/packages/block-library/src/cover/test/edit.js b/packages/block-library/src/cover/test/edit.js index 97c52a47ec4d72..348cd88edfd962 100644 --- a/packages/block-library/src/cover/test/edit.js +++ b/packages/block-library/src/cover/test/edit.js @@ -190,7 +190,7 @@ describe( 'Cover block', () => { test( 'does not display media settings panel if url is not set', async () => { await setup(); expect( - screen.queryByRole( 'button', { + screen.queryByRole( 'heading', { name: 'Settings', } ) ).not.toBeInTheDocument(); @@ -202,7 +202,7 @@ describe( 'Cover block', () => { await selectBlock( 'Block: Cover' ); expect( - screen.getByRole( 'button', { + screen.getByRole( 'heading', { name: 'Settings', } ) ).toBeInTheDocument(); From 43417f3752dd6f3e5fe723ef54af7dd58123215b Mon Sep 17 00:00:00 2001 From: Ryan McCue <me@ryanmccue.info> Date: Tue, 15 Oct 2024 12:09:45 +0100 Subject: [PATCH 1171/1908] Correct capability for the Experiments page (#66118) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: rmccue <rmccue@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> --- lib/init.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/init.php b/lib/init.php index 88dcba4525f6e2..13ca26d4b9e83c 100644 --- a/lib/init.php +++ b/lib/init.php @@ -51,7 +51,7 @@ function gutenberg_menu() { 'gutenberg', __( 'Experiments Settings', 'gutenberg' ), __( 'Experiments', 'gutenberg' ), - 'edit_posts', + 'manage_options', 'gutenberg-experiments', 'the_gutenberg_experiments' ); From 98f3f6a5b3cccfcc8d94cefa9a4bee9750478132 Mon Sep 17 00:00:00 2001 From: Nick Diego <nick.diego@automattic.com> Date: Tue, 15 Oct 2024 06:43:50 -0500 Subject: [PATCH 1172/1908] Revert the manage fonts button. (#66107) Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../components/global-styles/font-families.js | 51 +++++++++++-------- .../specs/site-editor/font-library.spec.js | 18 +++---- 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-families.js b/packages/edit-site/src/components/global-styles/font-families.js index cd1697b7b79bd8..f3e81efbe597b0 100644 --- a/packages/edit-site/src/components/global-styles/font-families.js +++ b/packages/edit-site/src/components/global-styles/font-families.js @@ -6,9 +6,11 @@ import { __experimentalText as Text, __experimentalItemGroup as ItemGroup, __experimentalVStack as VStack, + __experimentalHStack as HStack, Button, } from '@wordpress/components'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; +import { settings } from '@wordpress/icons'; import { useContext } from '@wordpress/element'; /** @@ -67,10 +69,18 @@ function FontFamilies() { /> ) } - <VStack spacing={ 4 }> + <VStack spacing={ 2 }> + <HStack justify="space-between"> + <Subtitle level={ 3 }>{ __( 'Fonts' ) }</Subtitle> + <Button + onClick={ () => setModalTabOpen( 'installed-fonts' ) } + label={ __( 'Manage fonts' ) } + icon={ settings } + size="small" + /> + </HStack> { activeFonts.length > 0 && ( <> - <Subtitle level={ 3 }>{ __( 'Fonts' ) }</Subtitle> <ItemGroup size="large" isBordered isSeparated> { activeFonts.map( ( font ) => ( <FontFamilyItem @@ -82,31 +92,30 @@ function FontFamilies() { </> ) } { ! hasFonts && ( - <VStack> - <Subtitle level={ 3 }>{ __( 'Fonts' ) }</Subtitle> + <> <Text as="p"> { hasInstalledFonts ? __( 'No fonts activated.' ) : __( 'No fonts installed.' ) } </Text> - </VStack> + <Button + className="edit-site-global-styles-font-families__manage-fonts" + variant="secondary" + __next40pxDefaultSize + onClick={ () => { + setModalTabOpen( + hasInstalledFonts + ? 'installed-fonts' + : 'upload-fonts' + ); + } } + > + { hasInstalledFonts + ? __( 'Manage fonts' ) + : __( 'Add fonts' ) } + </Button> + </> ) } - <Button - className="edit-site-global-styles-font-families__manage-fonts" - variant="secondary" - __next40pxDefaultSize - onClick={ () => { - setModalTabOpen( - hasInstalledFonts - ? 'installed-fonts' - : 'upload-fonts' - ); - } } - > - { hasInstalledFonts - ? __( 'Manage fonts' ) - : __( 'Add fonts' ) } - </Button> </VStack> </> ); diff --git a/test/e2e/specs/site-editor/font-library.spec.js b/test/e2e/specs/site-editor/font-library.spec.js index 6d699f4b02a63e..7271768206d1b6 100644 --- a/test/e2e/specs/site-editor/font-library.spec.js +++ b/test/e2e/specs/site-editor/font-library.spec.js @@ -38,7 +38,7 @@ test.describe( 'Font Library', () => { ).toBeVisible(); } ); - test( 'should display the "Add fonts" button', async ( { page } ) => { + test( 'should display the "Manage fonts" icon', async ( { page } ) => { await page .getByRole( 'region', { name: 'Editor top bar' } ) .getByRole( 'button', { name: 'Styles' } ) @@ -46,10 +46,10 @@ test.describe( 'Font Library', () => { await page .getByRole( 'button', { name: 'Typography Styles' } ) .click(); - const addFontsButton = page.getByRole( 'button', { - name: 'Add fonts', + const manageFontsIcon = page.getByRole( 'button', { + name: 'Manage fonts', } ); - await expect( addFontsButton ).toBeVisible(); + await expect( manageFontsIcon ).toBeVisible(); } ); } ); @@ -66,9 +66,7 @@ test.describe( 'Font Library', () => { } ); } ); - test( 'should display the "Manage fonts" button', async ( { - page, - } ) => { + test( 'should display the "Manage fonts" icon', async ( { page } ) => { await page .getByRole( 'region', { name: 'Editor top bar' } ) .getByRole( 'button', { name: 'Styles' } ) @@ -76,13 +74,13 @@ test.describe( 'Font Library', () => { await page .getByRole( 'button', { name: 'Typography Styles' } ) .click(); - const manageFontsButton = page.getByRole( 'button', { + const manageFontsIcon = page.getByRole( 'button', { name: 'Manage fonts', } ); - await expect( manageFontsButton ).toBeVisible(); + await expect( manageFontsIcon ).toBeVisible(); } ); - test( 'should open the "Manage fonts" modal when clicking the "Manage fonts" button', async ( { + test( 'should open the "Manage fonts" modal when clicking the "Manage fonts" icon', async ( { page, } ) => { await page From d2b654a100cf069b54aac02909d7863f6578636f Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Tue, 15 Oct 2024 09:15:07 -0500 Subject: [PATCH 1173/1908] Position scaled html within available container space (#66034) * Positions the iframed HTML canvas via translateX rather than margin-left on the iframe in order to have the scrollbar for the iframe available instead of hidden off canvas. This also fixes issues with the vertical toolbar and inserters not rerendering to their new positions. * Renames prevContainerWidthRef to initialContainerWidth so it's clearer that this is the point when zoom out was initialized, then renames the CSS vars prev-container-width to outer-container-width, using the larger value of containerWidth or initialContainerWidth so it can be more consistently named. * Force largest available window size to scale from If you started with a sidebar open, then entered zoom out, then closed the sidebar, your scaled canvas would be too large. It should match the same size as if you start with no sidebars open, then enter zoom out. This also fixes an issue where scaling could be larger than 1. * Only animate scaling on entry and exit of zoom out mode to improve animations when opening and closing sidebars. * Known divergence: When starting from a smaller canvas (sidebars open), entering zoom out, then closing sidebars, there will be reflow on the canvas. --------- Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: dhruvang21 <dhruvang21@git.wordpress.org> Co-authored-by: AhmarZaidi <ahmarzaidi@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- packages/base-styles/_animations.scss | 5 -- .../src/components/block-canvas/style.scss | 1 - .../src/components/iframe/content.scss | 25 +++++-- .../src/components/iframe/index.js | 67 +++++++++++++++---- .../src/components/iframe/style.scss | 11 +-- test/e2e/specs/site-editor/zoom-out.spec.js | 4 +- 6 files changed, 83 insertions(+), 30 deletions(-) diff --git a/packages/base-styles/_animations.scss b/packages/base-styles/_animations.scss index 87e5f035f46a6c..e5bbf863757356 100644 --- a/packages/base-styles/_animations.scss +++ b/packages/base-styles/_animations.scss @@ -36,11 +36,6 @@ @include reduce-motion("animation"); } -@mixin editor-canvas-resize-animation() { - transition: all 0.4s cubic-bezier(0.46, 0.03, 0.52, 0.96); - @include reduce-motion("transition"); -} - // Deprecated @mixin edit-post__fade-in-animation($speed: 0.08s, $delay: 0s) { @warn "The `edit-post__fade-in-animation` mixin is deprecated. Use `animation__fade-in` instead."; diff --git a/packages/block-editor/src/components/block-canvas/style.scss b/packages/block-editor/src/components/block-canvas/style.scss index 1395b5c0a437d3..9e924cb79bace1 100644 --- a/packages/block-editor/src/components/block-canvas/style.scss +++ b/packages/block-editor/src/components/block-canvas/style.scss @@ -4,5 +4,4 @@ iframe[name="editor-canvas"] { height: 100%; display: block; background-color: transparent; - @include editor-canvas-resize-animation; } diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss index 069274e66bdfd0..4a0e2d519f914b 100644 --- a/packages/block-editor/src/components/iframe/content.scss +++ b/packages/block-editor/src/components/iframe/content.scss @@ -5,7 +5,21 @@ .block-editor-iframe__html { transform-origin: top center; - @include editor-canvas-resize-animation; + // 400ms should match the animation speed used in iframe/index.js + $zoomOutAnimation: all 400ms cubic-bezier(0.46, 0.03, 0.52, 0.96); + + // We don't want to animate the transform of the translateX because it is used + // to "center" the canvas. Leaving it on causes the canvas to slide around in + // odd ways. + transition: $zoomOutAnimation, transform 0s scale 0s; + @include reduce-motion("transition"); + + &.zoom-out-animation { + // we only want to animate the scaling when entering zoom out. When sidebars + // are toggled, the resizing of the iframe handles scaling the canvas as well, + // and the doubled animations cause very odd animations. + transition: $zoomOutAnimation, transform 0s; + } } .block-editor-iframe__html.is-zoomed-out { @@ -13,10 +27,11 @@ $frame-size: var(--wp-block-editor-iframe-zoom-out-frame-size); $inner-height: var(--wp-block-editor-iframe-zoom-out-inner-height); $content-height: var(--wp-block-editor-iframe-zoom-out-content-height); - $prev-container-width: var(--wp-block-editor-iframe-zoom-out-prev-container-width); - - transform: scale(#{$scale}); - + $outer-container-width: var(--wp-block-editor-iframe-zoom-out-outer-container-width); + $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw); + // Apply an X translation to center the scaled content within the available space. + transform: translateX(calc(( #{$outer-container-width} - #{ $container-width }) / 2 / #{$scale})); + scale: #{$scale}; background-color: $gray-300; // Chrome seems to respect that transform scale shouldn't affect the layout size of the element, diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index d234339909a5c1..b72d86ef8e0f8f 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -122,7 +122,7 @@ function Iframe( { }, [] ); const { styles = '', scripts = '' } = resolvedAssets; const [ iframeDocument, setIframeDocument ] = useState(); - const prevContainerWidthRef = useRef(); + const initialContainerWidth = useRef(); const [ bodyClasses, setBodyClasses ] = useState( [] ); const clearerRef = useBlockSelectionClearer(); const [ before, writingFlowRef, after ] = useWritingFlow(); @@ -243,7 +243,7 @@ function Iframe( { useEffect( () => { if ( ! isZoomedOut ) { - prevContainerWidthRef.current = containerWidth; + initialContainerWidth.current = containerWidth; } }, [ containerWidth, isZoomedOut ] ); @@ -298,14 +298,49 @@ function Iframe( { useEffect( () => cleanup, [ cleanup ] ); + const zoomOutAnimationClassnameRef = useRef( null ); + const handleZoomOutAnimationClassname = () => { + clearTimeout( zoomOutAnimationClassnameRef.current ); + + iframeDocument.documentElement.classList.add( 'zoom-out-animation' ); + + zoomOutAnimationClassnameRef.current = setTimeout( () => { + iframeDocument.documentElement.classList.remove( + 'zoom-out-animation' + ); + }, 400 ); // 400ms should match the animation speed used in components/iframe/content.scss + }; + + // Toggle zoom out CSS Classes only when zoom out mode changes. We could add these into the useEffect + // that controls settings the CSS variables, but then we would need to do more work to ensure we're + // only toggling these when the zoom out mode changes, as that useEffect is also triggered by a large + // number of dependencies. useEffect( () => { if ( ! iframeDocument || ! isZoomedOut ) { return; } + handleZoomOutAnimationClassname(); iframeDocument.documentElement.classList.add( 'is-zoomed-out' ); + return () => { + handleZoomOutAnimationClassname(); + iframeDocument.documentElement.classList.remove( 'is-zoomed-out' ); + }; + }, [ iframeDocument, isZoomedOut ] ); + + // Calculate the scaling and CSS variables for the zoom out canvas + useEffect( () => { + if ( ! iframeDocument || ! isZoomedOut ) { + return; + } + const maxWidth = 750; + // Note: When we initialize the zoom out when the canvas is smaller (sidebars open), + // initialContainerWidth will be smaller than the full page, and reflow will happen + // when the canvas area becomes larger due to sidebars closing. This is a known but + // minor divergence for now. + // This scaling calculation has to happen within the JS because CSS calc() can // only divide and multiply by a unitless value. I.e. calc( 100px / 2 ) is valid // but calc( 100px / 2px ) is not. @@ -314,7 +349,10 @@ function Iframe( { scale === 'default' ? ( Math.min( containerWidth, maxWidth ) - parseInt( frameSize ) * 2 ) / - prevContainerWidthRef.current + Math.max( + initialContainerWidth.current, + containerWidth + ) : scale ); @@ -336,13 +374,16 @@ function Iframe( { `${ containerWidth }px` ); iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-prev-container-width', - `${ prevContainerWidthRef.current }px` + '--wp-block-editor-iframe-zoom-out-outer-container-width', + `${ Math.max( initialContainerWidth.current, containerWidth ) }px` ); - return () => { - iframeDocument.documentElement.classList.remove( 'is-zoomed-out' ); + // iframeDocument.documentElement.style.setProperty( + // '--wp-block-editor-iframe-zoom-out-outer-container-width', + // `${ Math.max( initialContainerWidth.current, containerWidth ) }px` + // ); + return () => { iframeDocument.documentElement.style.removeProperty( '--wp-block-editor-iframe-zoom-out-scale' ); @@ -359,7 +400,7 @@ function Iframe( { '--wp-block-editor-iframe-zoom-out-container-width' ); iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-prev-container-width' + '--wp-block-editor-iframe-zoom-out-outer-container-width' ); }; }, [ @@ -460,10 +501,12 @@ function Iframe( { isZoomedOut && 'is-zoomed-out' ) } style={ { - '--wp-block-editor-iframe-zoom-out-container-width': - isZoomedOut && `${ containerWidth }px`, - '--wp-block-editor-iframe-zoom-out-prev-container-width': - isZoomedOut && `${ prevContainerWidthRef.current }px`, + '--wp-block-editor-iframe-zoom-out-outer-container-width': + isZoomedOut && + `${ Math.max( + initialContainerWidth.current, + containerWidth + ) }px`, } } > { iframe } diff --git a/packages/block-editor/src/components/iframe/style.scss b/packages/block-editor/src/components/iframe/style.scss index dcddcdf0950a45..d05be2f3977b9f 100644 --- a/packages/block-editor/src/components/iframe/style.scss +++ b/packages/block-editor/src/components/iframe/style.scss @@ -9,9 +9,10 @@ } .block-editor-iframe__scale-container.is-zoomed-out { - $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw); - $prev-container-width: var(--wp-block-editor-iframe-zoom-out-prev-container-width, 100vw); - width: $prev-container-width; - // This is to offset the movement of the iframe when we open sidebars - margin-left: calc(-1 * (#{$prev-container-width} - #{$container-width}) / 2); + $outer-container-width: var(--wp-block-editor-iframe-zoom-out-outer-container-width, 100vw); + width: $outer-container-width; + // Position the iframe so that it is always aligned with the right side so that + // the scrollbar is always visible on the right side + position: absolute; + right: 0; } diff --git a/test/e2e/specs/site-editor/zoom-out.spec.js b/test/e2e/specs/site-editor/zoom-out.spec.js index 6ede9014d2a303..2aabee07d18785 100644 --- a/test/e2e/specs/site-editor/zoom-out.spec.js +++ b/test/e2e/specs/site-editor/zoom-out.spec.js @@ -27,8 +27,8 @@ test.describe( 'Zoom Out', () => { // Check that the html is scaled. await expect( html ).toHaveCSS( - 'transform', - 'matrix(0.67, 0, 0, 0.67, 0, 0)' + 'scale', + new RegExp( /0\.[5-8][0-9]*/, 'i' ) ); const iframeRect = await iframe.boundingBox(); const htmlRect = await html.boundingBox(); From 7590b3d0122322368ee7bc1f46a4034fcf2fe297 Mon Sep 17 00:00:00 2001 From: Alex Lende <alex+github.com@lende.xyz> Date: Tue, 15 Oct 2024 07:23:07 -0700 Subject: [PATCH 1174/1908] Fix duotone on parallax/repeated featured image cover blocks (#65929) Co-authored-by: ajlende <ajlende@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: mrfoxtalbot <mrfoxtalbot@git.wordpress.org> Co-authored-by: jordesign <jordesign@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: iamtakashi <iamtakashi@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: henriqueiamarino <iamarinoh@git.wordpress.org> --- packages/block-library/src/cover/index.php | 57 ++++++++++++++-------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/packages/block-library/src/cover/index.php b/packages/block-library/src/cover/index.php index 2fca0b0374dd29..1ffe7ab3f4dbc6 100644 --- a/packages/block-library/src/cover/index.php +++ b/packages/block-library/src/cover/index.php @@ -20,29 +20,22 @@ function render_block_core_cover( $attributes, $content ) { return $content; } + $object_position = isset( $attributes['focalPoint'] ) + ? round( $attributes['focalPoint']['x'] * 100 ) . '% ' . round( $attributes['focalPoint']['y'] * 100 ) . '%' + : null; + if ( ! ( $attributes['hasParallax'] || $attributes['isRepeated'] ) ) { $attr = array( 'class' => 'wp-block-cover__image-background', 'data-object-fit' => 'cover', ); - if ( isset( $attributes['focalPoint'] ) ) { - $object_position = round( $attributes['focalPoint']['x'] * 100 ) . '% ' . round( $attributes['focalPoint']['y'] * 100 ) . '%'; + if ( $object_position ) { $attr['data-object-position'] = $object_position; - $attr['style'] = 'object-position: ' . $object_position; + $attr['style'] = 'object-position:' . $object_position . ';'; } $image = get_the_post_thumbnail( null, 'post-thumbnail', $attr ); - - /* - * Inserts the featured image between the (1st) cover 'background' `span` and 'inner_container' `div`, - * and removes eventual whitespace characters between the two (typically introduced at template level) - */ - $inner_container_start = '/<div\b[^>]+wp-block-cover__inner-container[\s|"][^>]*>/U'; - if ( 1 === preg_match( $inner_container_start, $content, $matches, PREG_OFFSET_CAPTURE ) ) { - $offset = $matches[0][1]; - $content = substr( $content, 0, $offset ) . $image . substr( $content, $offset ); - } } else { if ( in_the_loop() ) { update_post_thumbnail_cache(); @@ -52,15 +45,41 @@ function render_block_core_cover( $attributes, $content ) { return $content; } - $processor = new WP_HTML_Tag_Processor( $content ); + $current_thumbnail_id = get_post_thumbnail_id(); + + $processor = new WP_HTML_Tag_Processor( '<div></div>' ); $processor->next_tag(); - $styles = $processor->get_attribute( 'style' ); - $merged_styles = ! empty( $styles ) ? $styles . ';' : ''; - $merged_styles .= 'background-image:url(' . esc_url( $current_featured_image ) . ');'; + $current_alt = trim( strip_tags( get_post_meta( $current_thumbnail_id, '_wp_attachment_image_alt', true ) ) ); + if ( $current_alt ) { + $processor->set_attribute( 'role', 'img' ); + $processor->set_attribute( 'aria-label', $current_alt ); + } + + $processor->add_class( 'wp-block-cover__image-background' ); + $processor->add_class( 'wp-image-' . $current_thumbnail_id ); + if ( $attributes['hasParallax'] ) { + $processor->add_class( 'has-parallax' ); + } + if ( $attributes['isRepeated'] ) { + $processor->add_class( 'is-repeated' ); + } + + $styles = 'background-position:' . ( $object_position ?? '50% 50%' ) . ';'; + $styles .= 'background-image:url(' . esc_url( $current_featured_image ) . ');'; + $processor->set_attribute( 'style', $styles ); + + $image = $processor->get_updated_html(); + } - $processor->set_attribute( 'style', $merged_styles ); - $content = $processor->get_updated_html(); + /* + * Inserts the featured image between the (1st) cover 'background' `span` and 'inner_container' `div`, + * and removes eventual whitespace characters between the two (typically introduced at template level) + */ + $inner_container_start = '/<div\b[^>]+wp-block-cover__inner-container[\s|"][^>]*>/U'; + if ( 1 === preg_match( $inner_container_start, $content, $matches, PREG_OFFSET_CAPTURE ) ) { + $offset = $matches[0][1]; + $content = substr( $content, 0, $offset ) . $image . substr( $content, $offset ); } return $content; From ec71b324b27f5498f22374f5954aa3ee1e0a3e25 Mon Sep 17 00:00:00 2001 From: Lee Pak <159242502+leemyongpakva@users.noreply.github.com> Date: Tue, 15 Oct 2024 21:28:52 +0700 Subject: [PATCH 1175/1908] data-basics/4-building-a-create-page-form is ready now (#66100) * Update 4-building-a-create-page-form.md consistency: other parts don't have "Part" in Heading * Update 3-building-an-edit-form.md Part 4 is ready now * Update 3-building-an-edit-form.md remove a space * Run docs:build --------- Unlinked contributors: leemyongpakva. Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- docs/how-to-guides/data-basics/3-building-an-edit-form.md | 2 +- docs/how-to-guides/data-basics/4-building-a-create-page-form.md | 2 +- docs/manifest.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/how-to-guides/data-basics/3-building-an-edit-form.md b/docs/how-to-guides/data-basics/3-building-an-edit-form.md index 65c4d0a5486a0d..5f4e30357798d5 100644 --- a/docs/how-to-guides/data-basics/3-building-an-edit-form.md +++ b/docs/how-to-guides/data-basics/3-building-an-edit-form.md @@ -539,5 +539,5 @@ function EditPageForm( { pageId, onCancel, onSaveFinished } ) { ## What's next? * **Previous part:** [Building a list of pages](/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md) -* **Next part:** Building a *New Page* form (coming soon) +* **Next part:** [Building a Create Page form](/docs/how-to-guides/data-basics/4-building-a-create-page-form.md) * (optional) Review the [finished app](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/data-basics-59c8f8) in the block-development-examples repository diff --git a/docs/how-to-guides/data-basics/4-building-a-create-page-form.md b/docs/how-to-guides/data-basics/4-building-a-create-page-form.md index 33c6e9a5ccff5b..9011596e0feddd 100644 --- a/docs/how-to-guides/data-basics/4-building-a-create-page-form.md +++ b/docs/how-to-guides/data-basics/4-building-a-create-page-form.md @@ -1,4 +1,4 @@ -# Part 4: Building a Create page form +# Building a Create page form In the [previous part](/docs/how-to-guides/data-basics/3-building-an-edit-form.md) we created an *Edit page* feature, and in this part we will add a *Create page* feature. Here's a glimpse of what we're going to build: diff --git a/docs/manifest.json b/docs/manifest.json index 8387b9079694c0..5e94c6b83b70d2 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -198,7 +198,7 @@ "parent": "data-basics" }, { - "title": "Part 4: Building a Create page form", + "title": "Building a Create page form", "slug": "4-building-a-create-page-form", "markdown_source": "../docs/how-to-guides/data-basics/4-building-a-create-page-form.md", "parent": "data-basics" From d32b15d972e8f38e6cebfa59fb339135e2b98b61 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Tue, 15 Oct 2024 07:49:40 -0700 Subject: [PATCH 1176/1908] Polish zoom out inserter (#66110) * Hide overflow; add delay to prompt; revise font scale * Tweak prompt text transition --- .../src/components/block-list/content.scss | 5 +++-- .../components/block-list/zoom-out-separator.js | 14 ++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index 6a88813b0c6049..b42ebe349d5997 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -404,14 +404,15 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b display: flex; align-items: center; justify-content: center; + overflow: hidden; font-size: $default-font-size; font-family: $default-font; color: $black; font-weight: normal; .is-zoomed-out & { - // Scale the font size based on the zoom level. - font-size: calc(#{$default-font-size} * ( 2 - var(--wp-block-editor-iframe-zoom-out-scale) )); + // Maintains an absolute font-size by counter-scaling based on the zoom level. + font-size: calc(#{$default-font-size} / var(--wp-block-editor-iframe-zoom-out-scale)); } &.is-dragged-over { diff --git a/packages/block-editor/src/components/block-list/zoom-out-separator.js b/packages/block-editor/src/components/block-list/zoom-out-separator.js index 9e0d087c2267cd..f2e6d050141fb5 100644 --- a/packages/block-editor/src/components/block-list/zoom-out-separator.js +++ b/packages/block-editor/src/components/block-list/zoom-out-separator.js @@ -101,14 +101,15 @@ export function ZoomOutSeparator( { <AnimatePresence> { isVisible && ( <motion.div - as="button" - layout={ ! isReducedMotion } initial={ { height: 0 } } - animate={ { height: '120px' } } + animate={ { + // Use a height equal to that of the zoom out frame size. + height: 'calc(1 * var(--wp-block-editor-iframe-zoom-out-frame-size) / var(--wp-block-editor-iframe-zoom-out-scale)', + } } exit={ { height: 0 } } transition={ { type: 'tween', - duration: 0.2, + duration: isReducedMotion ? 0 : 0.2, ease: [ 0.6, 0, 0.4, 1 ], } } className={ clsx( @@ -124,10 +125,11 @@ export function ZoomOutSeparator( { <motion.div initial={ { opacity: 0 } } animate={ { opacity: 1 } } - exit={ { opacity: 0 } } + exit={ { opacity: 0, transition: { delay: -0.125 } } } transition={ { - type: 'tween', + ease: 'linear', duration: 0.1, + delay: 0.125, } } > { __( 'Drop pattern.' ) } From 26e108deabcb6f58ffdf424f06887efb9f88333c Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Tue, 15 Oct 2024 17:01:14 +0200 Subject: [PATCH 1177/1908] Add missing `post.slug` dependency to `useMemo` (#66125) - Add missing `post.slug` dependency to `useMemo` Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/editor/src/components/provider/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 0c45dbc5e7199c..51b54979cb34aa 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -222,6 +222,7 @@ export const ExperimentalEditorProvider = withRegistryProvider( shouldRenderTemplate, post.id, post.type, + post.slug, rootLevelPost.type, rootLevelPost.slug, postTypes, From cd8d4dc12b874b32695ac0c52e186d8ae6f35054 Mon Sep 17 00:00:00 2001 From: Weston Ruter <westonruter@google.com> Date: Tue, 15 Oct 2024 18:56:51 -0700 Subject: [PATCH 1178/1908] Leverage scheduler.yield in splitTask when available (#66001) * Leverage scheduler.yield in splitTask when available * Eliminate extra Promise when using scheduler.yield() Co-authored-by: swissspidy <swissspidy@git.wordpress.org> * Avoid needlessly re-checking whether scheduler.yield() is defined * Remove needless function wrapper * Ensure that scheduler is context object to yield function * Remove needless async * Reduce verbosity of scheduler.yield() existence check * Fix return type for scheduler.yield() Co-authored-by: Brendan Kenny <bckenny@gmail.com> * Define scheduler and scheduler.yield as optional Co-authored-by: Brendan Kenny <bckenny@gmail.com> --------- Unlinked contributors: brendankenny, LeszekSwirski. Co-authored-by: felixarntz <flixos90@git.wordpress.org> --- packages/interactivity/src/utils.ts | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/interactivity/src/utils.ts b/packages/interactivity/src/utils.ts index 4f10ed517de502..9cd6f8bebb0d1c 100644 --- a/packages/interactivity/src/utils.ts +++ b/packages/interactivity/src/utils.ts @@ -22,6 +22,14 @@ interface Flusher { readonly dispose: () => void; } +declare global { + interface Window { + scheduler?: { + readonly yield?: () => Promise< void >; + }; + } +} + /** * Executes a callback function after the next frame is rendered. * @@ -48,12 +56,14 @@ const afterNextFrame = ( callback: () => void ) => { * * @return Promise */ -export const splitTask = () => { - return new Promise( ( resolve ) => { - // TODO: Use scheduler.yield() when available. - setTimeout( resolve, 0 ); - } ); -}; +export const splitTask = + typeof window.scheduler?.yield === 'function' + ? window.scheduler.yield.bind( window.scheduler ) + : () => { + return new Promise( ( resolve ) => { + setTimeout( resolve, 0 ); + } ); + }; /** * Creates a Flusher object that can be used to flush computed values and notify listeners. From 0ee8ce4536a2fc57ddeef10b9ada4bf9ceb07cdd Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Wed, 16 Oct 2024 07:36:11 +0530 Subject: [PATCH 1179/1908] Updated several typos in client-assets.php file (#66084) * Updated several typos in client-assets.php file * updated in backport changelog * moved changelog file in 6.7 folder --------- Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: mukeshpanchal27 <mukesh27@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- backport-changelog/6.7/7561.md | 3 +++ lib/client-assets.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 backport-changelog/6.7/7561.md diff --git a/backport-changelog/6.7/7561.md b/backport-changelog/6.7/7561.md new file mode 100644 index 00000000000000..43fcffa41c02a5 --- /dev/null +++ b/backport-changelog/6.7/7561.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7561 + +* https://github.com/WordPress/gutenberg/pull/66084 diff --git a/lib/client-assets.php b/lib/client-assets.php index 2343530e5595a7..3e4f79cd3c1f77 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -630,7 +630,7 @@ function gutenberg_default_script_modules() { switch ( $script_module_id ) { /* * Interactivity exposes two entrypoints, "/index" and "/debug". - * "/debug" should replalce "/index" in devlopment. + * "/debug" should replace "/index" in development. */ case '@wordpress/interactivity/debug': if ( ! SCRIPT_DEBUG ) { From f809836298f82fe0303a5da1f7f938af459f7cb8 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Wed, 16 Oct 2024 08:46:17 +0300 Subject: [PATCH 1180/1908] Edit Site: Remove redundant state in StyleVariationsContainer (#66130) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../global-styles/style-variations-container.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/style-variations-container.js b/packages/edit-site/src/components/global-styles/style-variations-container.js index 18fc6f6ad90563..759303bcf5fa7b 100644 --- a/packages/edit-site/src/components/global-styles/style-variations-container.js +++ b/packages/edit-site/src/components/global-styles/style-variations-container.js @@ -3,7 +3,7 @@ */ import { store as coreStore } from '@wordpress/core-data'; import { useSelect } from '@wordpress/data'; -import { useContext, useEffect, useMemo, useState } from '@wordpress/element'; +import { useContext, useMemo } from '@wordpress/element'; import { __experimentalGrid as Grid } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; @@ -20,12 +20,7 @@ const { GlobalStylesContext } = unlock( blockEditorPrivateApis ); export default function StyleVariationsContainer( { gap = 2 } ) { const { user } = useContext( GlobalStylesContext ); - const [ currentUserStyles, setCurrentUserStyles ] = useState( user ); - const userStyles = currentUserStyles?.styles; - - useEffect( () => { - setCurrentUserStyles( user ); - }, [ user ] ); + const userStyles = user?.styles; const variations = useSelect( ( select ) => { return select( From 83ba78aac0f41a9adc2454ac16178967b2163bdc Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Wed, 16 Oct 2024 08:46:26 +0300 Subject: [PATCH 1181/1908] Edit Site: Avoid recomputing variations when no theme variations (#66137) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../use-theme-style-variations-by-property.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/hooks/use-theme-style-variations/use-theme-style-variations-by-property.js b/packages/edit-site/src/hooks/use-theme-style-variations/use-theme-style-variations-by-property.js index e6e3a1ccc3aa6d..adf98b0d89b019 100644 --- a/packages/edit-site/src/hooks/use-theme-style-variations/use-theme-style-variations-by-property.js +++ b/packages/edit-site/src/hooks/use-theme-style-variations/use-theme-style-variations-by-property.js @@ -13,6 +13,7 @@ import { __ } from '@wordpress/i18n'; */ import { unlock } from '../../lock-unlock'; +const EMPTY_ARRAY = []; const { GlobalStylesContext, areGlobalStyleConfigsEqual } = unlock( blockEditorPrivateApis ); @@ -82,7 +83,7 @@ export function useCurrentMergeThemeStyleVariationsWithUserConfig( ).__experimentalGetCurrentThemeGlobalStylesVariations(); return { - variationsFromTheme: _variationsFromTheme || [], + variationsFromTheme: _variationsFromTheme || EMPTY_ARRAY, }; }, [] ); const { user: userVariation } = useContext( GlobalStylesContext ); From 3fd7c8a2cbdb321611c447d64d6fe4b79dfdefd0 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:05:40 +1100 Subject: [PATCH 1182/1908] Theme JSON: remove redundant check and relocate $selectors assignment (#66154) Remove redundant check for `$theme_json['styles']`,` which means `WP_Theme_JSON::get_blocks_metadata()` is only called if necessary. This also has the potential to slightly improve the performance of functions that call WP_Theme_JSON::get_styles_block_nodes(), where no block styles exist Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- backport-changelog/6.8/7575.md | 3 +++ lib/class-wp-theme-json-gutenberg.php | 8 ++------ 2 files changed, 5 insertions(+), 6 deletions(-) create mode 100644 backport-changelog/6.8/7575.md diff --git a/backport-changelog/6.8/7575.md b/backport-changelog/6.8/7575.md new file mode 100644 index 00000000000000..f1c6a84da1368e --- /dev/null +++ b/backport-changelog/6.8/7575.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7575 + +* https://github.com/WordPress/gutenberg/pull/66154 diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 8cd83e007f37c9..98d0719cd24a90 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2732,17 +2732,13 @@ private static function update_separator_declarations( $declarations ) { * @return array The block nodes in theme.json. */ private static function get_block_nodes( $theme_json, $selectors = array(), $options = array() ) { - $selectors = empty( $selectors ) ? static::get_blocks_metadata() : $selectors; - $nodes = array(); - if ( ! isset( $theme_json['styles'] ) ) { - return $nodes; - } + $nodes = array(); - // Blocks. if ( ! isset( $theme_json['styles']['blocks'] ) ) { return $nodes; } + $selectors = empty( $selectors ) ? static::get_blocks_metadata() : $selectors; $include_variations = $options['include_block_style_variations'] ?? false; $include_node_paths_only = $options['include_node_paths_only'] ?? false; From 6d84740fb33ae906469b35f4f8d74c4902f78b1a Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Wed, 16 Oct 2024 10:36:27 +0200 Subject: [PATCH 1183/1908] Memoize pattern objects returned from getAllowedPatterns (#66159) Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: madhusudhand <madhudollu@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- packages/block-editor/src/store/selectors.js | 24 +++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index a81d88de33466d..2bfc52118d7ace 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2385,6 +2385,21 @@ const getAllowedPatternsDependants = ( select ) => ( state, rootClientId ) => [ ...getInsertBlockTypeDependants( state, rootClientId ), ]; +const patternsWithParsedBlocks = new WeakMap(); +function enhancePatternWithParsedBlocks( pattern ) { + let enhancedPattern = patternsWithParsedBlocks.get( pattern ); + if ( ! enhancedPattern ) { + enhancedPattern = { + ...pattern, + get blocks() { + return getParsedPattern( pattern ).blocks; + }, + }; + patternsWithParsedBlocks.set( pattern, enhancedPattern ); + } + return enhancedPattern; +} + /** * Returns the list of allowed patterns for inner blocks children. * @@ -2406,14 +2421,7 @@ export const __experimentalGetAllowedPatterns = createRegistrySelector( const { allowedBlockTypes } = getSettings( state ); const parsedPatterns = patterns .filter( ( { inserter = true } ) => !! inserter ) - .map( ( pattern ) => { - return { - ...pattern, - get blocks() { - return getParsedPattern( pattern ).blocks; - }, - }; - } ); + .map( enhancePatternWithParsedBlocks ); const availableParsedPatterns = parsedPatterns.filter( ( pattern ) => From 5c18dc781c47b4f072b6a26a8eea2b1a4d1c75fa Mon Sep 17 00:00:00 2001 From: Django <mediaformat.ux@gmail.com> Date: Wed, 16 Oct 2024 03:30:30 -0600 Subject: [PATCH 1184/1908] Remove clip for screen-reader-text CSS (#66145) Co-authored-by: mediaformat <mediaformat@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- .../src/components/responsive-block-control/style.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/components/responsive-block-control/style.scss b/packages/block-editor/src/components/responsive-block-control/style.scss index 7f90e12dd87c66..e840a3bfcf436a 100644 --- a/packages/block-editor/src/components/responsive-block-control/style.scss +++ b/packages/block-editor/src/components/responsive-block-control/style.scss @@ -1,6 +1,5 @@ @mixin screen-reader-text() { border: 0; - clip: rect(1px, 1px, 1px, 1px); clip-path: inset(50%); height: 1px; margin: -1px; From 3948575f8940231faa63fe883caa66dd948d83cc Mon Sep 17 00:00:00 2001 From: Michal <mmczaplinski@gmail.com> Date: Wed, 16 Oct 2024 10:37:07 +0100 Subject: [PATCH 1185/1908] Update the changelog (#66120) Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- packages/interactivity-router/CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/interactivity-router/CHANGELOG.md b/packages/interactivity-router/CHANGELOG.md index 4f794899096683..10294b3a7e6204 100644 --- a/packages/interactivity-router/CHANGELOG.md +++ b/packages/interactivity-router/CHANGELOG.md @@ -7,8 +7,10 @@ - Improvements to the experimental full-page navigation ([#64067](https://github.com/WordPress/gutenberg/pull/64067)): - Remove the `src` attributes from prefetched script tags. - Use `.textContent` instead of `.innerText` to set `<script>` contents. - - Use `populateInitialData()` with state from the server. + - Use [`populateServerData()`](https://github.com/WordPress/gutenberg/blob/9671329c386d2b743f14ef314823fbf915366ebd/packages/interactivity/src/store.ts#L269) with state from the server. - Wait for the `load` event of the script element before evaluating it. + - Make `renderRegions()` an async function. + - Only prefetch **module** scripts, never prefetch regular scripts. That's because regular scripts (without `async` or `defer` attributes) found in the head are blocking and must be executed in order. When prefetching there is no guarantee that the scripts will execute in the order they are prefetched. Module scripts can be executed in any order. ## 2.9.0 (2024-10-03) From 1c5934092c1dea9d2b581a094c8e195b31dcb2fc Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:27:26 +0300 Subject: [PATCH 1186/1908] Query Block: Remove redundant sticky state (#66126) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../block-library/src/query/edit/inspector-controls/index.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index b373e0933fe718..06105bef4e0269 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -62,7 +62,7 @@ export default function QueryInspectorControls( props ) { format, } = query; const allowedControls = useAllowedControls( attributes ); - const [ showSticky, setShowSticky ] = useState( postType === 'post' ); + const showSticky = postType === 'post'; const { postTypesTaxonomiesMap, postTypesSelectOptions, @@ -70,9 +70,6 @@ export default function QueryInspectorControls( props ) { } = usePostTypes(); const taxonomies = useTaxonomies( postType ); const isPostTypeHierarchical = useIsPostTypeHierarchical( postType ); - useEffect( () => { - setShowSticky( postType === 'post' ); - }, [ postType ] ); const onPostTypeChange = ( newValue ) => { const updateQuery = { postType: newValue }; // We need to dynamically update the `taxQuery` property, From 1e0f7c19d7675f499db32b97b73dd95ba5a8b6dc Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Wed, 16 Oct 2024 12:39:19 +0200 Subject: [PATCH 1187/1908] Add argument with post ID to the editor.savePost hook (#66165) Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/edit-post/src/store/actions.js | 2 +- packages/editor/src/store/actions.js | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/edit-post/src/store/actions.js b/packages/edit-post/src/store/actions.js index 1dc0401baf21c3..7ab0a965379be2 100644 --- a/packages/edit-post/src/store/actions.js +++ b/packages/edit-post/src/store/actions.js @@ -481,7 +481,7 @@ export const initializeMetaBoxes = addAction( 'editor.savePost', 'core/edit-post/save-metaboxes', - async ( options ) => { + async ( post, options ) => { if ( ! options.isAutosave && select.hasMetaBoxes() ) { await dispatch.requestMetaBoxUpdates(); } diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index f8a18fc86e5376..70be70c6293399 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -278,7 +278,11 @@ export const savePost = if ( ! error ) { try { - await doActionAsync( 'editor.savePost', options ); + await doActionAsync( + 'editor.savePost', + { id: previousRecord.id }, + options + ); } catch ( err ) { error = err; } From 5dc1bdcc12fcd1b1d715cf878b9bba455cc9dd8f Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Wed, 16 Oct 2024 11:54:10 +0100 Subject: [PATCH 1188/1908] Fix rich text toolbar corners (#66163) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> --- packages/block-editor/src/components/rich-text/style.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/block-editor/src/components/rich-text/style.scss b/packages/block-editor/src/components/rich-text/style.scss index ca274d378d4088..ba109648df1428 100644 --- a/packages/block-editor/src/components/rich-text/style.scss +++ b/packages/block-editor/src/components/rich-text/style.scss @@ -9,12 +9,17 @@ margin-bottom: $grid-unit-10; box-shadow: none; outline: none; + border-radius: $radius-small; } .components-toolbar { border-radius: $radius-small; } + .components-toolbar-group { + background: none; + } + .components-toolbar__control, .components-dropdown-menu__toggle { min-width: $block-toolbar-height; From 27aed30dbd7297f44a391f7994fa2e4b7cd2127c Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Wed, 16 Oct 2024 12:09:15 +0100 Subject: [PATCH 1189/1908] Fix site editor back button visual regressions (#66166) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/edit-site/src/components/sidebar-button/index.js | 2 +- packages/edit-site/src/components/sidebar-button/style.scss | 4 ++-- .../src/components/sidebar-navigation-screen/style.scss | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-button/index.js b/packages/edit-site/src/components/sidebar-button/index.js index 64c6efb891f462..f4cea37f01078b 100644 --- a/packages/edit-site/src/components/sidebar-button/index.js +++ b/packages/edit-site/src/components/sidebar-button/index.js @@ -11,7 +11,7 @@ import { Button } from '@wordpress/components'; export default function SidebarButton( props ) { return ( <Button - __next40pxDefaultSize + size="compact" { ...props } className={ clsx( 'edit-site-sidebar-button', props.className ) } /> diff --git a/packages/edit-site/src/components/sidebar-button/style.scss b/packages/edit-site/src/components/sidebar-button/style.scss index 6daa560a114ad0..4507accbd12123 100644 --- a/packages/edit-site/src/components/sidebar-button/style.scss +++ b/packages/edit-site/src/components/sidebar-button/style.scss @@ -14,10 +14,10 @@ outline: 3px solid transparent; } - &:hover, + &:hover:not(:disabled,[aria-disabled="true"]), &:focus-visible, &:focus, - &:not([aria-disabled="true"]):active, + &:not(:disabled,[aria-disabled="true"]):active, &[aria-expanded="true"] { color: $gray-100; } diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss index f0260581a8988f..1d57472f7e9f94 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss @@ -68,7 +68,11 @@ .edit-site-sidebar-navigation-screen__title { flex-grow: 1; overflow-wrap: break-word; - padding: $grid-unit-05 * 0.5 0 0 0; + + &#{&}, + &#{&} .edit-site-sidebar-navigation-screen__title { + line-height: $font-line-height-x-large; + } } .edit-site-sidebar-navigation-screen__actions { From f205b11b09117f3f4ea9cb8ae5f7b818b08c7c27 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 16 Oct 2024 21:03:52 +0900 Subject: [PATCH 1190/1908] Components: Set up README auto-generator (#66035) * Add components readme generator * Move * AlignmentMatrixControl: Add missing `@deprecated` tag * Add docs manifest for AlignmentMatrixControl * Handle case with no subcomponents * Add JSON schema * Commit AlignmentMatrixControl readme changes * Fixup: Handle case with no subcomponents * Add manifest for AnglePickerControl * Simplify * Improve schema descriptions * Handle docgen errors * Convert to async * Move glob further up * Handle unparseable JSON * Handle write file progress * Fixup * Apply feedback in markdown props handling * Simplify * Handle cases when `displayName` in manifest is wrong Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- bin/api-docs/gen-components-docs/index.mjs | 112 ++++++++++++++++++ .../gen-components-docs/markdown/index.mjs | 40 +++++++ .../gen-components-docs/markdown/props.mjs | 51 ++++++++ package-lock.json | 20 ++++ package.json | 5 +- .../components/schemas/docs-manifest.json | 38 ++++++ .../src/alignment-matrix-control/README.md | 82 +++++++------ .../docs-manifest.json | 12 ++ .../src/alignment-matrix-control/types.ts | 2 + .../src/angle-picker-control/README.md | 59 +++++---- .../angle-picker-control/docs-manifest.json | 5 + 11 files changed, 366 insertions(+), 60 deletions(-) create mode 100644 bin/api-docs/gen-components-docs/index.mjs create mode 100644 bin/api-docs/gen-components-docs/markdown/index.mjs create mode 100644 bin/api-docs/gen-components-docs/markdown/props.mjs create mode 100644 packages/components/schemas/docs-manifest.json create mode 100644 packages/components/src/alignment-matrix-control/docs-manifest.json create mode 100644 packages/components/src/angle-picker-control/docs-manifest.json diff --git a/bin/api-docs/gen-components-docs/index.mjs b/bin/api-docs/gen-components-docs/index.mjs new file mode 100644 index 00000000000000..e036995b4c4f74 --- /dev/null +++ b/bin/api-docs/gen-components-docs/index.mjs @@ -0,0 +1,112 @@ +/** + * External dependencies + */ +import docgen from 'react-docgen-typescript'; +import glob from 'glob'; +import fs from 'node:fs/promises'; +import path from 'path'; + +/** + * Internal dependencies + */ +import { generateMarkdownDocs } from './markdown/index.mjs'; + +const MANIFEST_GLOB = 'packages/components/src/**/docs-manifest.json'; + +// For consistency, options should generally match the options used in Storybook. +const OPTIONS = { + shouldExtractLiteralValuesFromEnum: true, + shouldRemoveUndefinedFromOptional: true, + propFilter: ( prop ) => + prop.parent ? ! /node_modules/.test( prop.parent.fileName ) : true, + savePropValueAsString: true, +}; + +function getTypeDocsForComponent( { + manifestPath, + componentFilePath, + displayName, +} ) { + const resolvedPath = path.resolve( + path.dirname( manifestPath ), + componentFilePath + ); + + const typeDocs = docgen.parse( resolvedPath, OPTIONS ); + + if ( typeDocs.length === 0 ) { + throw new Error( + `react-docgen-typescript could not generate any type docs from ${ resolvedPath }` + ); + } + + const matchingTypeDoc = typeDocs.find( + ( obj ) => obj.displayName === displayName + ); + + if ( typeof matchingTypeDoc === 'undefined' ) { + const unmatchedTypeDocs = typeDocs + .map( ( obj ) => `\`${ obj.displayName }\`` ) + .join( ', ' ); + + throw new Error( + `react-docgen-typescript could not find type docs for ${ displayName } in ${ resolvedPath }. (Found ${ unmatchedTypeDocs })` + ); + } + + return matchingTypeDoc; +} + +async function parseManifest( manifestPath ) { + try { + return JSON.parse( await fs.readFile( manifestPath, 'utf8' ) ); + } catch ( e ) { + throw new Error( + `Error parsing docs manifest at ${ manifestPath }: ${ e.message }` + ); + } +} + +const manifests = glob.sync( MANIFEST_GLOB ); + +await Promise.all( + manifests.map( async ( manifestPath ) => { + const manifest = await parseManifest( manifestPath ); + + const typeDocs = getTypeDocsForComponent( { + manifestPath, + componentFilePath: manifest.filePath, + displayName: manifest.displayName, + } ); + + const subcomponentTypeDocs = manifest.subcomponents?.map( + ( subcomponent ) => { + const docs = getTypeDocsForComponent( { + manifestPath, + componentFilePath: subcomponent.filePath, + displayName: subcomponent.displayName, + } ); + + if ( subcomponent.preferredDisplayName ) { + docs.displayName = subcomponent.preferredDisplayName; + } + + return docs; + } + ); + const docs = generateMarkdownDocs( { typeDocs, subcomponentTypeDocs } ); + const outputFile = path.resolve( + path.dirname( manifestPath ), + './README.md' + ); + + try { + console.log( `Writing docs to ${ outputFile }` ); + return fs.writeFile( outputFile, docs ); + } catch ( e ) { + throw new Error( + `Error writing docs to ${ outputFile }: ${ e.message }` + ); + } + } ) +); diff --git a/bin/api-docs/gen-components-docs/markdown/index.mjs b/bin/api-docs/gen-components-docs/markdown/index.mjs new file mode 100644 index 00000000000000..85655b89f08414 --- /dev/null +++ b/bin/api-docs/gen-components-docs/markdown/index.mjs @@ -0,0 +1,40 @@ +/** + * External dependencies + */ +import json2md from 'json2md'; + +/** + * Internal dependencies + */ +import { generateMarkdownPropsJson } from './props.mjs'; + +export function generateMarkdownDocs( { typeDocs, subcomponentTypeDocs } ) { + const mainDocsJson = [ + '<!-- This file is generated automatically and cannot be edited directly. -->\n', + { h1: typeDocs.displayName }, + { + p: `<p class="callout callout-info">See the <a href="https://wordpress.github.io/gutenberg/?path=/docs/components-${ typeDocs.displayName.toLowerCase() }--docs">WordPress Storybook</a> for more detailed, interactive documentation.</p>`, + }, + typeDocs.description, + ...generateMarkdownPropsJson( typeDocs.props ), + ]; + + const subcomponentDocsJson = subcomponentTypeDocs?.length + ? [ + { h2: 'Subcomponents' }, + ...subcomponentTypeDocs.flatMap( ( subcomponentTypeDoc ) => [ + { + h3: subcomponentTypeDoc.displayName, + }, + subcomponentTypeDoc.description, + ...generateMarkdownPropsJson( subcomponentTypeDoc.props, { + headingLevel: 4, + } ), + ] ), + ] + : []; + + return json2md( + [ ...mainDocsJson, ...subcomponentDocsJson ].filter( Boolean ) + ); +} diff --git a/bin/api-docs/gen-components-docs/markdown/props.mjs b/bin/api-docs/gen-components-docs/markdown/props.mjs new file mode 100644 index 00000000000000..9d019c4240f008 --- /dev/null +++ b/bin/api-docs/gen-components-docs/markdown/props.mjs @@ -0,0 +1,51 @@ +function renderPropType( type ) { + const MAX_ENUM_VALUES = 10; + + switch ( type.name ) { + case 'enum': { + const string = type.value + .slice( 0, MAX_ENUM_VALUES ) + .map( ( { value } ) => value ) + .join( ' | ' ); + + if ( type.value.length > MAX_ENUM_VALUES ) { + return `${ string } | ...`; + } + return string; + } + default: + return type.name; + } +} + +export function generateMarkdownPropsJson( props, { headingLevel = 2 } = {} ) { + const sortedKeys = Object.keys( props ).sort( ( [ a ], [ b ] ) => + a.localeCompare( b ) + ); + + const propsJson = sortedKeys + .flatMap( ( key ) => { + const prop = props[ key ]; + + if ( prop.description?.includes( '@ignore' ) ) { + return null; + } + + return [ + { [ `h${ headingLevel + 1 }` ]: `\`${ key }\`` }, + prop.description, + { + ul: [ + `Type: \`${ renderPropType( prop.type ) }\``, + `Required: ${ prop.required ? 'Yes' : 'No' }`, + prop.defaultValue && + `Default: \`${ prop.defaultValue.value }\``, + ].filter( Boolean ), + }, + ]; + } ) + .filter( Boolean ); + + return [ { [ `h${ headingLevel }` ]: 'Props' }, ...propsJson ]; +} + diff --git a/package-lock.json b/package-lock.json index 14b24167aa0a7c..1674dd65b70b7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -204,6 +204,7 @@ "jest-junit": "13.0.0", "jest-message-util": "29.6.2", "jest-watch-typeahead": "2.2.2", + "json2md": "2.0.1", "lerna": "7.1.4", "lint-staged": "10.0.2", "make-dir": "3.0.0", @@ -223,6 +224,7 @@ "progress": "2.0.3", "puppeteer-core": "23.1.0", "react": "18.3.1", + "react-docgen-typescript": "2.2.2", "react-dom": "18.3.1", "react-native": "0.73.3", "react-native-url-polyfill": "1.1.2", @@ -29765,6 +29767,13 @@ "node": ">=4" } }, + "node_modules/indento": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/indento/-/indento-1.1.13.tgz", + "integrity": "sha512-YZWk3mreBEM7sBPddsiQnW9Z8SGg/gNpFfscJq00HCDS7pxcQWWWMSVKJU7YkTRyDu1Zv2s8zaK8gQWKmCXHlg==", + "dev": true, + "license": "MIT" + }, "node_modules/infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", @@ -32488,6 +32497,16 @@ "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true }, + "node_modules/json2md": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/json2md/-/json2md-2.0.1.tgz", + "integrity": "sha512-VbwmZ83qmUfKBS2pUOHlzNKEZFPBeJSbzEok3trMYyboZUgdHNn1XZfc1uT8UZs1GHCrmRUBXCfqw4YmmQuOhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "indento": "^1.1.13" + } + }, "node_modules/json2php": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/json2php/-/json2php-0.0.7.tgz", @@ -43192,6 +43211,7 @@ "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", "dev": true, + "license": "MIT", "peerDependencies": { "typescript": ">= 4.3.x" } diff --git a/package.json b/package.json index 4c071bf746c159..14af2c94f62669 100644 --- a/package.json +++ b/package.json @@ -216,6 +216,7 @@ "jest-junit": "13.0.0", "jest-message-util": "29.6.2", "jest-watch-typeahead": "2.2.2", + "json2md": "2.0.1", "lerna": "7.1.4", "lint-staged": "10.0.2", "make-dir": "3.0.0", @@ -235,6 +236,7 @@ "progress": "2.0.3", "puppeteer-core": "23.1.0", "react": "18.3.1", + "react-docgen-typescript": "2.2.2", "react-dom": "18.3.1", "react-native": "0.73.3", "react-native-url-polyfill": "1.1.2", @@ -282,7 +284,8 @@ "distclean": "git clean --force -d -X", "docs:api-ref": "node ./bin/api-docs/update-api-docs.js", "docs:blocks": "node ./bin/api-docs/gen-block-lib-list.js", - "docs:build": "npm-run-all docs:gen docs:blocks docs:api-ref docs:theme-ref", + "docs:build": "npm-run-all docs:components docs:gen docs:blocks docs:api-ref docs:theme-ref", + "docs:components": "node ./bin/api-docs/gen-components-docs/index.mjs", "docs:gen": "node ./docs/tool/index.js", "docs:theme-ref": "node ./bin/api-docs/gen-theme-reference.mjs", "env": "wp-env", diff --git a/packages/components/schemas/docs-manifest.json b/packages/components/schemas/docs-manifest.json new file mode 100644 index 00000000000000..7d1e40f4f696d7 --- /dev/null +++ b/packages/components/schemas/docs-manifest.json @@ -0,0 +1,38 @@ +{ + "title": "JSON schema for @wordpress/components README manifests", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "displayName": { + "type": "string", + "description": "The `displayName` of the component, as determined in code. Used to identify the component in the specified source file." + }, + "filePath": { + "type": "string", + "description": "The file path where the component is located." + }, + "subcomponents": { + "type": "array", + "description": "List of subcomponents related to the component.", + "items": { + "type": "object", + "properties": { + "displayName": { + "type": "string", + "description": "The `displayName` of the subcomponent, as determined in code. Used to identify the component in the specified source file." + }, + "preferredDisplayName": { + "type": "string", + "description": "The display name to use in the README, if it is different from the `displayName` as determined in code." + }, + "filePath": { + "type": "string", + "description": "The file path where the subcomponent is located." + } + }, + "required": [ "displayName", "filePath" ] + } + } + }, + "required": [ "displayName", "filePath" ] +} diff --git a/packages/components/src/alignment-matrix-control/README.md b/packages/components/src/alignment-matrix-control/README.md index 68ecab6b7adb47..8e6ef324ce8e60 100644 --- a/packages/components/src/alignment-matrix-control/README.md +++ b/packages/components/src/alignment-matrix-control/README.md @@ -1,12 +1,15 @@ +<!-- This file is generated automatically and cannot be edited directly. --> + # AlignmentMatrixControl -AlignmentMatrixControl components enable adjustments to horizontal and vertical alignments for UI. -## Usage +<p class="callout callout-info">See the <a href="https://wordpress.github.io/gutenberg/?path=/docs/components-alignmentmatrixcontrol--docs">WordPress Storybook</a> for more detailed, interactive documentation.</p> + +AlignmentMatrixControl components enable adjustments to horizontal and vertical alignments for UI. ```jsx -import { useState } from 'react'; import { AlignmentMatrixControl } from '@wordpress/components'; +import { useState } from '@wordpress/element'; const Example = () => { const [ alignment, setAlignment ] = useState( 'center center' ); @@ -14,63 +17,70 @@ const Example = () => { return ( <AlignmentMatrixControl value={ alignment } - onChange={ ( newAlignment ) => setAlignment( newAlignment ) } + onChange={ setAlignment } /> ); }; ``` - ## Props -The component accepts the following props: +### `defaultValue` -### className +If provided, sets the default alignment value. -The class that will be added to the classes of the underlying `grid` widget. -- Type: `string` -- Required: No + - Type: `"center" | "top left" | "top center" | "top right" | "center left" | "center center" | "center right" | "bottom left" | "bottom center" | "bottom right"` + - Required: No + - Default: `'center center'` -### id +### `label` -Unique ID for the component. +Accessible label. If provided, sets the `aria-label` attribute of the +underlying `grid` widget. -- Type: `string` -- Required: No + - Type: `string` + - Required: No + - Default: `'Alignment Matrix Control'` -### label +### `onChange` -Accessible label. If provided, sets the `aria-label` attribute of the underlying `grid` widget. +A function that receives the updated alignment value. -- Type: `string` -- Required: No -- Default: `Alignment Matrix Control` + - Type: `(newValue: AlignmentMatrixControlValue) => void` + - Required: No -### defaultValue +### `value` -If provided, sets the default alignment value. +The current alignment value. -- Type: `AlignmentMatrixControlValue` -- Required: No -- Default: `center center` + - Type: `"center" | "top left" | "top center" | "top right" | "center left" | "center center" | "center right" | "bottom left" | "bottom center" | "bottom right"` + - Required: No -### value +### `width` -The current alignment value. +If provided, sets the width of the control. -- Type: `AlignmentMatrixControlValue` -- Required: No + - Type: `number` + - Required: No + - Default: `92` -### onChange +## Subcomponents -A function that receives the updated alignment value. +### AlignmentMatrixControl.Icon -- Type: `( newValue: AlignmentMatrixControlValue ) => void` -- Required: No +#### Props -### width +##### `disablePointerEvents` -If provided, sets the width of the control. +If `true`, disables pointer events on the icon. - - Type: `number` + - Type: `boolean` - Required: No - - Default: `92` + - Default: `true` + +##### `value` + +The current alignment value. + + - Type: `"center" | "top left" | "top center" | "top right" | "center left" | "center center" | "center right" | "bottom left" | "bottom center" | "bottom right"` + - Required: No + - Default: `center` diff --git a/packages/components/src/alignment-matrix-control/docs-manifest.json b/packages/components/src/alignment-matrix-control/docs-manifest.json new file mode 100644 index 00000000000000..82ee28f4840c49 --- /dev/null +++ b/packages/components/src/alignment-matrix-control/docs-manifest.json @@ -0,0 +1,12 @@ +{ + "$schema": "../../schemas/docs-manifest.json", + "displayName": "AlignmentMatrixControl", + "filePath": "./index.tsx", + "subcomponents": [ + { + "displayName": "AlignmentMatrixControlIcon", + "preferredDisplayName": "AlignmentMatrixControl.Icon", + "filePath": "./icon.tsx" + } + ] +} diff --git a/packages/components/src/alignment-matrix-control/types.ts b/packages/components/src/alignment-matrix-control/types.ts index 0f97c2df3b02bb..e93f412c1f4721 100644 --- a/packages/components/src/alignment-matrix-control/types.ts +++ b/packages/components/src/alignment-matrix-control/types.ts @@ -54,6 +54,8 @@ export type AlignmentMatrixControlIconProps = Pick< * component instead_ * * The size of the icon. + * + * @deprecated * @ignore * @default 24 */ diff --git a/packages/components/src/angle-picker-control/README.md b/packages/components/src/angle-picker-control/README.md index deed41089fdc1d..f5f2627409e133 100644 --- a/packages/components/src/angle-picker-control/README.md +++ b/packages/components/src/angle-picker-control/README.md @@ -1,44 +1,57 @@ +<!-- This file is generated automatically and cannot be edited directly. --> + # AnglePickerControl -`AnglePickerControl` is a React component to render a UI that allows users to pick an angle. -Users can choose an angle in a visual UI with the mouse by dragging an angle indicator inside a circle or by directly inserting the desired angle in a text field. -## Usage +<p class="callout callout-info">See the <a href="https://wordpress.github.io/gutenberg/?path=/docs/components-anglepickercontrol--docs">WordPress Storybook</a> for more detailed, interactive documentation.</p> + +`AnglePickerControl` is a React component to render a UI that allows users to +pick an angle. Users can choose an angle in a visual UI with the mouse by +dragging an angle indicator inside a circle or by directly inserting the +desired angle in a text field. ```jsx -import { useState } from 'react'; +import { useState } from '@wordpress/element'; import { AnglePickerControl } from '@wordpress/components'; function Example() { - const [ angle, setAngle ] = useState( 0 ); - return ( - <AnglePickerControl - value={ angle } - onChange={ setAngle } - /> - ); -}; + const [ angle, setAngle ] = useState( 0 ); + return ( + <AnglePickerControl + value={ angle } + onChange={ setAngle } + </> + ); +} ``` - ## Props -The component accepts the following props. +### `as` + +The HTML element or React component to render the component as. -### `label`: `string` + - Type: `"symbol" | "object" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | ...` + - Required: No + +### `label` Label to use for the angle picker. -- Required: No -- Default: `__( 'Angle' )` + - Type: `string` + - Required: No + - Default: `__( 'Angle' )` -### `value`: `number | string` +### `onChange` -The current value of the input. The value represents an angle in degrees and should be a value between 0 and 360. +A function that receives the new value of the input. -- Required: Yes + - Type: `(value: number) => void` + - Required: Yes -### `onChange`: `( value: number ) => void` +### `value` -A function that receives the new value of the input. +The current value of the input. The value represents an angle in degrees +and should be a value between 0 and 360. -- Required: Yes + - Type: `string | number` + - Required: Yes diff --git a/packages/components/src/angle-picker-control/docs-manifest.json b/packages/components/src/angle-picker-control/docs-manifest.json new file mode 100644 index 00000000000000..bcbfb353ac9e32 --- /dev/null +++ b/packages/components/src/angle-picker-control/docs-manifest.json @@ -0,0 +1,5 @@ +{ + "$schema": "../../schemas/docs-manifest.json", + "displayName": "AnglePickerControl", + "filePath": "./index.tsx" +} From 2bdeb49d19a1398604d6b2a02f0dec8a9318c9ea Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 16 Oct 2024 14:27:29 +0200 Subject: [PATCH 1191/1908] Block Bindings: Allow label override when it is defined in client registration (#66160) * Change registration to override label * Change unit test * Compare label values * Keep server value if client is not defined * Add unit test to ensure server label persists Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- packages/blocks/src/api/registration.js | 12 +++------ packages/blocks/src/api/test/registration.js | 26 +++++++++++++++++--- packages/blocks/src/store/reducer.js | 3 +-- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index ae12b0cfbcf49d..2f4bab2b5f2589 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -854,14 +854,6 @@ export const registerBlockBindingsSource = ( source ) => { } // Check the `label` property is correct. - if ( label && existingSource?.label ) { - warning( - 'Block bindings "' + - name + - '" source label is already defined in the server.' - ); - return; - } if ( ! label && ! existingSource?.label ) { warning( 'Block bindings source must contain a label.' ); @@ -873,6 +865,10 @@ export const registerBlockBindingsSource = ( source ) => { return; } + if ( label && existingSource?.label && label !== existingSource?.label ) { + warning( 'Block bindings "' + name + '" source label was overriden.' ); + } + // Check the `usesContext` property is correct. if ( usesContext && ! Array.isArray( usesContext ) ) { warning( 'Block bindings source usesContext must be an array.' ); diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index 99ca6390d2d3b1..73f310bbf04dc7 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -1512,20 +1512,38 @@ describe( 'blocks', () => { expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); } ); - it( 'should not override label from the server', () => { + it( 'should override label from the server', () => { // Simulate bootstrap source from the server. registerBlockBindingsSource( { - name: 'core/server', + name: 'core/testing', label: 'Server label', } ); // Override the source with a different label in the client. registerBlockBindingsSource( { - name: 'core/server', + name: 'core/testing', label: 'Client label', } ); expect( console ).toHaveWarnedWith( - 'Block bindings "core/server" source label is already defined in the server.' + 'Block bindings "core/testing" source label was overriden.' ); + const source = getBlockBindingsSource( 'core/testing' ); + unregisterBlockBindingsSource( 'core/testing' ); + expect( source.label ).toEqual( 'Client label' ); + } ); + + it( 'should keep label from the server when not defined in the client', () => { + // Simulate bootstrap source from the server. + registerBlockBindingsSource( { + name: 'core/testing', + label: 'Server label', + } ); + // Override the source with a different label in the client. + registerBlockBindingsSource( { + name: 'core/testing', + } ); + const source = getBlockBindingsSource( 'core/testing' ); + unregisterBlockBindingsSource( 'core/testing' ); + expect( source.label ).toEqual( 'Server label' ); } ); // Check the `usesContext` array is correct. diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 16594a79271e6c..ac652b91890319 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -403,8 +403,7 @@ export function blockBindingsSources( state = {}, action ) { return { ...state, [ action.name ]: { - // Don't override the label if it's already set. - label: state[ action.name ]?.label || action.label, + label: action.label || state[ action.name ]?.label, usesContext: getMergedUsesContext( state[ action.name ]?.usesContext, action.usesContext From 6544c6f69c858953d74203d081fcc57a20afb839 Mon Sep 17 00:00:00 2001 From: Django <mediaformat.ux@gmail.com> Date: Wed, 16 Oct 2024 06:40:11 -0600 Subject: [PATCH 1192/1908] Remove clip and -webkit-clip for screen-reader-text CSS (#66144) Co-authored-by: mediaformat <mediaformat@git.wordpress.org> --- packages/block-library/src/common.scss | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/block-library/src/common.scss b/packages/block-library/src/common.scss index c6327692ff02a3..15c2cd52b76aad 100644 --- a/packages/block-library/src/common.scss +++ b/packages/block-library/src/common.scss @@ -75,8 +75,6 @@ .screen-reader-text { border: 0; - clip: rect(1px, 1px, 1px, 1px); - -webkit-clip-path: inset(50%); clip-path: inset(50%); height: 1px; margin: -1px; @@ -89,7 +87,6 @@ .screen-reader-text:focus { background-color: $gray-300; - clip: auto !important; clip-path: none; color: #444; display: block; From e015455cf89565bd87b3d69610c7e8dc439ee31d Mon Sep 17 00:00:00 2001 From: Anmol Verma <77019763+AnmolVerma404@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:40:49 +0530 Subject: [PATCH 1193/1908] Return result from register_block_template in wp_register_block_template function (#66102) Co-authored-by: AnmolVerma404 <anmolverma404@git.wordpress.org> Co-authored-by: Aljullu <aljullu@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- lib/compat/wordpress-6.7/block-templates.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compat/wordpress-6.7/block-templates.php b/lib/compat/wordpress-6.7/block-templates.php index 65d99ee978efed..acbd0b4981fe29 100644 --- a/lib/compat/wordpress-6.7/block-templates.php +++ b/lib/compat/wordpress-6.7/block-templates.php @@ -63,7 +63,7 @@ function unregister_block_template( $template_name ) { */ function wp_register_block_template( $template_name, $args = array() ) { _deprecated_function( __FUNCTION__, 'Gutenberg 19.4.0', 'register_block_template' ); - register_block_template( $template_name, $args ); + return register_block_template( $template_name, $args ); } } From 0b67b898f3339e17ecad23bf0828969b2cea959b Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Wed, 16 Oct 2024 07:18:14 -0700 Subject: [PATCH 1194/1908] Fix padding appender hook (#66143) * Fix focus inserted default block * Support clicks below the padding in the iframed editor Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../components/layout/use-padding-appender.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/edit-post/src/components/layout/use-padding-appender.js b/packages/edit-post/src/components/layout/use-padding-appender.js index edffc6f3dd07c9..ee1484f518d7a0 100644 --- a/packages/edit-post/src/components/layout/use-padding-appender.js +++ b/packages/edit-post/src/components/layout/use-padding-appender.js @@ -16,7 +16,13 @@ export function usePaddingAppender( enabled ) { const effect = useRefEffect( ( node ) => { function onMouseDown( event ) { - if ( event.target !== node ) { + if ( + event.target !== node && + // Tests for the parent element because in the iframed editor if the click is + // below the padding the target will be the parent element (html) and should + // still be treated as intent to append. + event.target !== node.parentElement + ) { return; } @@ -31,7 +37,7 @@ export function usePaddingAppender( enabled ) { return; } - event.stopPropagation(); + event.preventDefault(); const blockOrder = registry .select( blockEditorStore ) @@ -50,9 +56,12 @@ export function usePaddingAppender( enabled ) { insertDefaultBlock(); } } - node.addEventListener( 'mousedown', onMouseDown ); + const { ownerDocument } = node; + // Adds the listener on the document so that in the iframed editor clicks below the + // padding can be handled as they too should be treated as intent to append. + ownerDocument.addEventListener( 'mousedown', onMouseDown ); return () => { - node.removeEventListener( 'mousedown', onMouseDown ); + ownerDocument.removeEventListener( 'mousedown', onMouseDown ); }; }, [ registry ] From e2b2058b00661bfb0ec7cfb3deb7cb1837a25b85 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:02:12 +0200 Subject: [PATCH 1195/1908] Contrast notes: Update 4.6:1 note with further context. (#66168) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/base-styles/_colors.scss | 2 +- storybook/stories/tokens/color.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/base-styles/_colors.scss b/packages/base-styles/_colors.scss index e65551e48c783c..bba7fd5c8ec141 100644 --- a/packages/base-styles/_colors.scss +++ b/packages/base-styles/_colors.scss @@ -8,7 +8,7 @@ $black: #000; // Use only when you truly need pure black. For UI, use $gray-900. $gray-900: #1e1e1e; $gray-800: #2f2f2f; -$gray-700: #757575; // Meets 4.6:1 text contrast against white. +$gray-700: #757575; // Meets 4.6:1 (4.5:1 is minimum) text contrast against white. $gray-600: #949494; // Meets 3:1 UI or large text contrast against white. $gray-400: #ccc; $gray-300: #ddd; // Used for most borders. diff --git a/storybook/stories/tokens/color.mdx b/storybook/stories/tokens/color.mdx index 17944a47777fc8..0f99303500ca96 100644 --- a/storybook/stories/tokens/color.mdx +++ b/storybook/stories/tokens/color.mdx @@ -55,7 +55,7 @@ Ensure proper contrast is met between text, icons, UI, and backgrounds. Text nee Against a white background: * **Gray 700**\ -Lightest gray you can use and meet 4.5:1 text contrast. +Meets 4.6:1, lightest gray you can use and meet 4.5:1 text contrast. * **Gray 600**\ Lightest gray you can use and meet 3:1 UI contrast. From b9b633059bb448fa4281c43d8fa8d696ad6881cd Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 17 Oct 2024 01:26:28 +0900 Subject: [PATCH 1196/1908] ToggleGroupControl: Don't set value on focus after a reset (#66151) * Add test * ToggleGroupControl: Don't set value on focus after a reset * Add changelog * Rename to `selectedValueIsEmpty` Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/toggle-group-control/test/index.tsx | 26 +++++++++++++++++++ .../component.tsx | 6 ++++- .../toggle-group-control/as-radio-group.tsx | 9 ++++++- 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 48113f874af3a2..64e5eeb1776523 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -10,6 +10,7 @@ - `Tabs`: fix skipping indication animation glitch ([#65878](https://github.com/WordPress/gutenberg/pull/65878)). - `ToggleGroupControl`: Don't autoselect option on first group focus ([#65892](https://github.com/WordPress/gutenberg/pull/65892)). - `Button`: fix `box-shadow` transition for secondary variation ([#66045](https://github.com/WordPress/gutenberg/pull/66045)). +- `ToggleGroupControl`: Don't set value on focus after a reset ([#66151](https://github.com/WordPress/gutenberg/pull/66151)). ### Deprecations diff --git a/packages/components/src/toggle-group-control/test/index.tsx b/packages/components/src/toggle-group-control/test/index.tsx index d7b4824fce4de8..168e8f498958b5 100644 --- a/packages/components/src/toggle-group-control/test/index.tsx +++ b/packages/components/src/toggle-group-control/test/index.tsx @@ -175,6 +175,32 @@ describe.each( [ expect( radio ).not.toBeChecked(); } ); + if ( mode === 'controlled' ) { + it( 'should not set a value on focus, after the value is reset', async () => { + render( + <Component label="Test Toggle Group Control" value="jack"> + { options } + </Component> + ); + + expect( screen.getByRole( 'radio', { name: 'J' } ) ).toBeChecked(); + + await click( screen.getByRole( 'button', { name: 'Reset' } ) ); + + expect( + screen.getByRole( 'radio', { name: 'J' } ) + ).not.toBeChecked(); + + await press.ShiftTab(); + expect( + screen.getByRole( 'radio', { name: 'R' } ) + ).not.toBeChecked(); + expect( + screen.getByRole( 'radio', { name: 'J' } ) + ).not.toBeChecked(); + } ); + } + it( 'should render tooltip where `showTooltip` === `true`', async () => { render( <Component label="Test Toggle Group Control"> diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx index b33f53dd706b53..041af1adf5e5b5 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx @@ -141,10 +141,14 @@ function ToggleGroupControlOptionBase( <Ariakit.Radio disabled={ disabled } onFocusVisible={ () => { + const selectedValueIsEmpty = + toggleGroupControlContext.value === null || + toggleGroupControlContext.value === ''; + // Conditions ensure that the first visible focus to a radio group // without a selected option will not automatically select the option. if ( - toggleGroupControlContext.value !== null || + ! selectedValueIsEmpty || toggleGroupControlContext.activeItemIsNotFirstItem?.() ) { toggleGroupControlContext.setValue( value ); diff --git a/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx b/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx index 4481fc9f6138d8..0166728dbafba4 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx @@ -9,7 +9,7 @@ import { useStoreState } from '@ariakit/react'; * WordPress dependencies */ import { useInstanceId } from '@wordpress/compose'; -import { forwardRef, useMemo } from '@wordpress/element'; +import { forwardRef, useEffect, useMemo } from '@wordpress/element'; import { isRTL } from '@wordpress/i18n'; /** @@ -73,6 +73,13 @@ function UnforwardedToggleGroupControlAsRadioGroup( const selectedValue = useStoreState( radio, 'value' ); const setValue = radio.setValue; + // Ensures that the active id is also reset after the value is "reset" by the consumer. + useEffect( () => { + if ( selectedValue === '' ) { + radio.setActiveId( undefined ); + } + }, [ radio, selectedValue ] ); + const groupContextValue = useMemo( (): ToggleGroupControlContextProps => ( { activeItemIsNotFirstItem: () => From 3417b42cceb924fc5bae147c19400f88ea92b425 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 16 Oct 2024 16:37:01 +0000 Subject: [PATCH 1197/1908] Bump plugin version to 19.5.0-rc.1 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 1a7f0df4814217..34890e269c8763 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.4.0 + * Version: 19.5.0-rc.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 1674dd65b70b7f..764a441a117a62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.4.0", + "version": "19.5.0-rc.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.4.0", + "version": "19.5.0-rc.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 14af2c94f62669..0d31e446896e65 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.4.0", + "version": "19.5.0-rc.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 93d4e55ffe6d1a504898c8eb643cb3b9f555ea36 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Wed, 16 Oct 2024 09:46:40 -0700 Subject: [PATCH 1198/1908] Fix e2e test for padding appender (#66080) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- test/e2e/specs/editor/various/inserting-blocks.spec.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/e2e/specs/editor/various/inserting-blocks.spec.js b/test/e2e/specs/editor/various/inserting-blocks.spec.js index 29b59b727acfef..3cc369f75f2237 100644 --- a/test/e2e/specs/editor/various/inserting-blocks.spec.js +++ b/test/e2e/specs/editor/various/inserting-blocks.spec.js @@ -45,6 +45,10 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { { name: 'core/image' }, { name: 'core/paragraph' }, ] ); + + await expect( + editor.canvas.locator( '[data-type="core/paragraph"]' ) + ).toBeFocused(); } ); test( 'inserts blocks by dragging and dropping from the global inserter', async ( { From b3d6a96ad40c7f5490f815e1dd7b708837f71b00 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 16 Oct 2024 16:52:44 +0000 Subject: [PATCH 1199/1908] Update Changelog for 19.5.0-rc.1 --- changelog.txt | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) diff --git a/changelog.txt b/changelog.txt index b74a541e9cd1ea..77ee60f980c53a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,239 @@ == Changelog == += 19.5.0-rc.1 = + + +## Changelog + +### Enhancements + +- Remove the verb Toggle from the Block Inserter button. ([65983](https://github.com/WordPress/gutenberg/pull/65983)) +- Update jsdom to 25.0.1. ([65879](https://github.com/WordPress/gutenberg/pull/65879)) +- Write/Design tool: Persist as a user preference. ([65945](https://github.com/WordPress/gutenberg/pull/65945)) + +#### Zoom Out +- Make zoom transition smoother. ([66017](https://github.com/WordPress/gutenberg/pull/66017)) +- Try zooming out when selecting the patterns tab in the inserter. ([65785](https://github.com/WordPress/gutenberg/pull/65785)) +- Update/replace edit button with enter on selection. ([65760](https://github.com/WordPress/gutenberg/pull/65760)) + +#### Block Editor +- Cleanup `AutoBlockPreview` render memoization of `BlockList`. ([66060](https://github.com/WordPress/gutenberg/pull/66060)) +- Use shallow memo for prioritized inserter blocks. ([65737](https://github.com/WordPress/gutenberg/pull/65737)) + +#### Components +- Add type tokens to storybook. ([65993](https://github.com/WordPress/gutenberg/pull/65993)) +- Storybook: Add stub doc on existing colors. ([65982](https://github.com/WordPress/gutenberg/pull/65982)) + +#### Icons +- Update "hidden" icon to be clearer, and invert logic as used in Data Views. ([65914](https://github.com/WordPress/gutenberg/pull/65914)) +- Update cloud upload and add cloud download icon. ([65906](https://github.com/WordPress/gutenberg/pull/65906)) + +#### Global Styles +- Improve navigation logic for revisions screen. ([65946](https://github.com/WordPress/gutenberg/pull/65946)) + +#### Block bindings +- Register bindings sources in widgets screens. ([65937](https://github.com/WordPress/gutenberg/pull/65937)) + +#### Block Library +- Cover Block: Refactor setting panel. ([65432](https://github.com/WordPress/gutenberg/pull/65432)) + + +### Bug Fixes + +- Add argument with post ID to the editor.savePost hook. ([66165](https://github.com/WordPress/gutenberg/pull/66165)) +- Backport from WordPress Core: improve performance of WP_Theme_JSON::Merge when merging background styles. ([66002](https://github.com/WordPress/gutenberg/pull/66002)) +- BlockCanvas: Fix the height prop and width of the block editor. ([65977](https://github.com/WordPress/gutenberg/pull/65977)) +- Correct capability for the Experiments page. ([66118](https://github.com/WordPress/gutenberg/pull/66118)) +- Fix rich text toolbar corners. ([66163](https://github.com/WordPress/gutenberg/pull/66163)) +- Fix: Add missing `post.slug` dependency to `useMemo`. ([66125](https://github.com/WordPress/gutenberg/pull/66125)) +- Fix: Return result from wp_register_block_template function. ([66102](https://github.com/WordPress/gutenberg/pull/66102)) +- List all active fonts in the typography section. ([65806](https://github.com/WordPress/gutenberg/pull/65806)) + +#### Zoom Out +- Exit zoom out when mode is changed. ([65975](https://github.com/WordPress/gutenberg/pull/65975)) +- Fix scaling issues. ([65998](https://github.com/WordPress/gutenberg/pull/65998)) +- Fix zoom reflow by replacing border with padding. ([66012](https://github.com/WordPress/gutenberg/pull/66012)) +- Focus first section root block if no selected block and tabbing to zoom out canvas. ([65843](https://github.com/WordPress/gutenberg/pull/65843)) +- Make zoom out vertical toolbar consistent. ([65627](https://github.com/WordPress/gutenberg/pull/65627)) +- Polish zoom out inserter. ([66110](https://github.com/WordPress/gutenberg/pull/66110)) +- Position scaled html within available container space. ([66034](https://github.com/WordPress/gutenberg/pull/66034)) +- Restores setting zoom out mode to useZoomOut hook. ([65999](https://github.com/WordPress/gutenberg/pull/65999)) +- Use consistent canvas frame spacing on device preview and zoom out. ([66018](https://github.com/WordPress/gutenberg/pull/66018)) +- Zoom layout shift: Second alternate fix. ([66041](https://github.com/WordPress/gutenberg/pull/66041)) + +#### Block Library +- Code block: Set LTR direction for RTL languages. ([65891](https://github.com/WordPress/gutenberg/pull/65891)) +- Fix duotone on parallax/repeated featured image cover blocks. ([65929](https://github.com/WordPress/gutenberg/pull/65929)) +- Fix: Embed Block: Match HTML in the editor and frontend. ([65478](https://github.com/WordPress/gutenberg/pull/65478)) +- Hide grid visualizer when grid is template locked or block editing mode is not default. ([66065](https://github.com/WordPress/gutenberg/pull/66065)) +- Post Content Block: Fix conflict between clearFix and focus ring in the editor. ([65364](https://github.com/WordPress/gutenberg/pull/65364)) +- Post Content: Fix display of block support styles. ([66003](https://github.com/WordPress/gutenberg/pull/66003)) +- Post Terms: Fix fatal error when 'get_the_term_list' returns 'WP_Error'. ([65848](https://github.com/WordPress/gutenberg/pull/65848)) +- Query Loop: Fix isControlAllowed and isTemplate combined logic. ([65984](https://github.com/WordPress/gutenberg/pull/65984)) +- Query Loop: Fix query type indicator. ([65877](https://github.com/WordPress/gutenberg/pull/65877)) +- Revert "Update z-index hierarchy". ([66074](https://github.com/WordPress/gutenberg/pull/66074)) + +#### Block bindings +- Accept client ID as parameter for `useBlockBindingsUtils`. ([65818](https://github.com/WordPress/gutenberg/pull/65818)) +- Allow label override when it is defined in client registration. ([66160](https://github.com/WordPress/gutenberg/pull/66160)) +- Bootstrap server sources earlier. ([66058](https://github.com/WordPress/gutenberg/pull/66058)) +- Fix: Don't render image when `src` attribute is empty. ([66004](https://github.com/WordPress/gutenberg/pull/66004)) + +#### Global Styles +- Always preview style variations using desktop device type. ([66023](https://github.com/WordPress/gutenberg/pull/66023)) +- Improve Navigator usage in typography panel. ([65942](https://github.com/WordPress/gutenberg/pull/65942)) +- Leave screen if current shadow entry gets deleted. ([65935](https://github.com/WordPress/gutenberg/pull/65935)) +- `PaletteEdit`: Dedupe palette element slugs. ([65772](https://github.com/WordPress/gutenberg/pull/65772)) + +#### Block Editor +- Fix DropZone class names on drop. ([65798](https://github.com/WordPress/gutenberg/pull/65798)) +- Fix padding appender hook. ([66143](https://github.com/WordPress/gutenberg/pull/66143)) +- Memoize pattern objects returned from getAllowedPatterns. ([66159](https://github.com/WordPress/gutenberg/pull/66159)) + +#### Components +- Fix : Secondary Button Transition. ([66045](https://github.com/WordPress/gutenberg/pull/66045)) +- Global Styles: Fix overflow caused by RangeControl tooltip. ([65875](https://github.com/WordPress/gutenberg/pull/65875)) +- ToggleGroupControl: Don't set value on focus after a reset. ([66151](https://github.com/WordPress/gutenberg/pull/66151)) + +#### Interactivity API +- Allow "default" suffix values. ([65815](https://github.com/WordPress/gutenberg/pull/65815)) +- Correctly handle lazily added, deeply nested properties with `deepMerge()`. ([65465](https://github.com/WordPress/gutenberg/pull/65465)) +- Improvements to the experimental full-page navigation. ([64067](https://github.com/WordPress/gutenberg/pull/64067)) + +#### Site Editor +- Fix site editor back button visual regressions. ([66166](https://github.com/WordPress/gutenberg/pull/66166)) +- Zoom Out: When double clicking a template while zoomed out , reset zoom level instead of showing dialog. ([65963](https://github.com/WordPress/gutenberg/pull/65963)) + +#### CSS & Styling +- Editor: Prevent wrapping text when showing icon labels in header. ([66038](https://github.com/WordPress/gutenberg/pull/66038)) +- Update z-index hierarchy. ([65626](https://github.com/WordPress/gutenberg/pull/65626)) + +#### Data Views +- Data Views list layout: Revise for improved text truncation. ([65376](https://github.com/WordPress/gutenberg/pull/65376)) +- Fix: Pattern rendering issue. ([66022](https://github.com/WordPress/gutenberg/pull/66022)) + +#### Extensibility +- Rename wp_register_block_template() to register_block_template(). ([65958](https://github.com/WordPress/gutenberg/pull/65958)) + +#### Post Editor +- Fix "typewriter" spacing style application. ([65885](https://github.com/WordPress/gutenberg/pull/65885)) + +#### Synced Patterns +- Pattern block: Ensure consistent editing of overrides in Write Mode. ([65408](https://github.com/WordPress/gutenberg/pull/65408)) + + +### Accessibility + +#### Post Editor +- Fix meta boxes accessibility. ([65466](https://github.com/WordPress/gutenberg/pull/65466)) +- Fix navigate regions shortcuts on the back button WP logo slot. ([63611](https://github.com/WordPress/gutenberg/pull/63611)) +- Improve PostURL terminology and accessibility. ([63669](https://github.com/WordPress/gutenberg/pull/63669)) +- Match visible label of search inputs with their actual label. ([65458](https://github.com/WordPress/gutenberg/pull/65458)) + +#### Components +- Fixed : Modal dialog: Small improvement for elementShouldBeHidden. ([65941](https://github.com/WordPress/gutenberg/pull/65941)) +- ToggleGroupControl: Don't autoselect option on first group focus. ([65892](https://github.com/WordPress/gutenberg/pull/65892)) +- Tooltip: Add aria-describedby to anchor only if not redundant. ([65989](https://github.com/WordPress/gutenberg/pull/65989)) + +#### Typography +- Revert the "Manage fonts" button in Global Styles. ([66107](https://github.com/WordPress/gutenberg/pull/66107)) + + +### Performance + +#### Interactivity API +- Leverage scheduler.yield in splitTask when available. ([66001](https://github.com/WordPress/gutenberg/pull/66001)) + + +### Documentation + +- Add heading level curation documentation. ([66076](https://github.com/WordPress/gutenberg/pull/66076)) +- Components: Set up README auto-generator. ([66035](https://github.com/WordPress/gutenberg/pull/66035)) +- Contrast notes: Update 4.6:1 note with further context. ([66168](https://github.com/WordPress/gutenberg/pull/66168)) +- Data-basics/4-building-a-create-page-form is ready now. ([66100](https://github.com/WordPress/gutenberg/pull/66100)) +- Docs: env: Expand examples of path syntax. ([65972](https://github.com/WordPress/gutenberg/pull/65972)) +- Updated several typos in client-assets.php file. ([66084](https://github.com/WordPress/gutenberg/pull/66084)) +- Use correct label in PHP Backport documentation. ([65908](https://github.com/WordPress/gutenberg/pull/65908)) +- add: Usage examples in core editor documentation. ([63768](https://github.com/WordPress/gutenberg/pull/63768)) + + +### Code Quality + +- .screen-reader-text CSS update for responsive-block-control style.scss. ([66145](https://github.com/WordPress/gutenberg/pull/66145)) +- Add missing CHANGELOG entries for #64067. ([66120](https://github.com/WordPress/gutenberg/pull/66120)) +- Button: Move to stricter lint rule for 40px size adherence. ([65840](https://github.com/WordPress/gutenberg/pull/65840)) +- Private APIs: Remove obsolete try/catch block. ([65898](https://github.com/WordPress/gutenberg/pull/65898)) +- Remove clip and -webkit-clip for block-library common.scss. ([66144](https://github.com/WordPress/gutenberg/pull/66144)) +- Remove unused select toolbar code. ([65834](https://github.com/WordPress/gutenberg/pull/65834)) +- Simplify logical expression in `InitPatternModal`. ([65922](https://github.com/WordPress/gutenberg/pull/65922)) +- Theme JSON: Remove redundant check and relocate $selectors assignment. ([66154](https://github.com/WordPress/gutenberg/pull/66154)) +- Type the router package. ([65854](https://github.com/WordPress/gutenberg/pull/65854)) + +#### Global Styles +- Edit Site: Avoid recomputing variations when no theme variations. ([66137](https://github.com/WordPress/gutenberg/pull/66137)) +- Edit Site: Remove redundant state in `StyleVariationsContainer`. ([66130](https://github.com/WordPress/gutenberg/pull/66130)) + +#### Block Library +- Post Terms: Remove unnecessary 'get_the_terms' call. ([65867](https://github.com/WordPress/gutenberg/pull/65867)) +- Query Loop Block: Remove redundant sticky state. ([66126](https://github.com/WordPress/gutenberg/pull/66126)) + +#### Components +- Clean up Tabs animation logic. ([65878](https://github.com/WordPress/gutenberg/pull/65878)) +- SearchControl: Deprecate onClose prop. ([65988](https://github.com/WordPress/gutenberg/pull/65988)) + +#### Post Editor +- Block Visibility: Add end-to-end test. ([65880](https://github.com/WordPress/gutenberg/pull/65880)) + +#### Zoom Out +- Fix components coding standards in Zoom Out Toolbar. ([65858](https://github.com/WordPress/gutenberg/pull/65858)) + + +### Tools + +#### Testing +- Add an end-to-end test to check the interactions in write mode. ([65819](https://github.com/WordPress/gutenberg/pull/65819)) +- Composite: Add legacy unit tests to stable version. ([65952](https://github.com/WordPress/gutenberg/pull/65952)) +- Fix end-to-end Storybook configuration. ([66089](https://github.com/WordPress/gutenberg/pull/66089)) +- Tests: Add unit tests for image rendering. ([66010](https://github.com/WordPress/gutenberg/pull/66010)) +- Zoom out: End-to-end test - zoomed out mode zooms the canvas. ([65943](https://github.com/WordPress/gutenberg/pull/65943)) +- e2e: Fix Block Visibility test. ([65939](https://github.com/WordPress/gutenberg/pull/65939)) + +#### Build Tooling +- Dedupe npm packages. ([65913](https://github.com/WordPress/gutenberg/pull/65913)) +- Update and align babel dependencies version. ([65949](https://github.com/WordPress/gutenberg/pull/65949)) +- Update node-fetch to 2.7.0. ([65957](https://github.com/WordPress/gutenberg/pull/65957)) +- Update npm lockfile to version 3. ([65923](https://github.com/WordPress/gutenberg/pull/65923)) +- Upgrade browserslist and webcompat data packages. ([65926](https://github.com/WordPress/gutenberg/pull/65926)) + + +### Various + +- Consistent with block-development-examples data-basics-59c8f8. ([65995](https://github.com/WordPress/gutenberg/pull/65995)) +- Interactivity: Update preact packages. ([66008](https://github.com/WordPress/gutenberg/pull/66008)) + +#### Patterns +- Revert "Pattern block: Ensure consistent editing of overrides in Write Mode (#65408)". ([65953](https://github.com/WordPress/gutenberg/pull/65953)) + + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @AnmolVerma404: Fix: Return result from wp_register_block_template function. ([66102](https://github.com/WordPress/gutenberg/pull/66102)) +- @leemyongpakva: Consistent with block-development-examples data-basics-59c8f8. ([65995](https://github.com/WordPress/gutenberg/pull/65995)) +- @matt-west: Icons: Update cloud upload and add cloud download icon. ([65906](https://github.com/WordPress/gutenberg/pull/65906)) +- @mediaformat: .screen-reader-text CSS update for responsive-block-control style.scss. ([66145](https://github.com/WordPress/gutenberg/pull/66145)) +- @vk17-starlord: Fixed : Modal dialog: Small improvement for elementShouldBeHidden. ([65941](https://github.com/WordPress/gutenberg/pull/65941)) +- @Vrishabhsk: SearchControl: Deprecate onClose prop. ([65988](https://github.com/WordPress/gutenberg/pull/65988)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @afercia @ajlende @akasunil @Aljullu @andrewserong @AnmolVerma404 @ciampo @DaniGuardiola @dhruvang21 @draganescu @getdave @hbhalodia @jameskoster @jasmussen @jeryj @jsnajdr @leemyongpakva @MaggieCabrera @Mamaduka @matiasbenedetto @matt-west @mcsf @mediaformat @michalczaplinski @mikachan @mirka @ndiego @ntsekouras @ramonjd @renatho @richtabor @rmccue @sabernhardt @SantosGuillamot @shail-mehta @sirreal @stokesman @t-hamano @talldan @troychaplin @tyxla @up1512001 @vk17-starlord @Vrishabhsk @westonruter @youknowriad + + = 19.4.0 = ## Changelog From 6ca85b832eaed1f9d66b28474511de9d00ccaf75 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 16 Oct 2024 16:48:46 +0000 Subject: [PATCH 1200/1908] Update changelog files --- packages/a11y/CHANGELOG.md | 2 ++ packages/a11y/package.json | 2 +- packages/annotations/CHANGELOG.md | 2 ++ packages/annotations/package.json | 2 +- packages/api-fetch/CHANGELOG.md | 2 ++ packages/api-fetch/package.json | 2 +- packages/autop/CHANGELOG.md | 2 ++ packages/autop/package.json | 2 +- packages/babel-plugin-import-jsx-pragma/CHANGELOG.md | 2 ++ packages/babel-plugin-import-jsx-pragma/package.json | 2 +- packages/babel-plugin-makepot/CHANGELOG.md | 2 ++ packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/CHANGELOG.md | 2 ++ packages/babel-preset-default/package.json | 2 +- packages/base-styles/CHANGELOG.md | 2 ++ packages/base-styles/package.json | 2 +- packages/blob/CHANGELOG.md | 2 ++ packages/blob/package.json | 2 +- packages/block-directory/CHANGELOG.md | 2 ++ packages/block-directory/package.json | 2 +- packages/block-editor/CHANGELOG.md | 2 ++ packages/block-editor/package.json | 2 +- packages/block-library/CHANGELOG.md | 2 ++ packages/block-library/package.json | 2 +- packages/block-serialization-default-parser/CHANGELOG.md | 2 ++ packages/block-serialization-default-parser/package.json | 2 +- packages/block-serialization-spec-parser/CHANGELOG.md | 2 ++ packages/block-serialization-spec-parser/package.json | 2 +- packages/blocks/CHANGELOG.md | 2 ++ packages/blocks/package.json | 2 +- packages/browserslist-config/CHANGELOG.md | 2 ++ packages/browserslist-config/package.json | 2 +- packages/commands/CHANGELOG.md | 2 ++ packages/commands/package.json | 2 +- packages/components/CHANGELOG.md | 2 ++ packages/components/package.json | 2 +- packages/compose/CHANGELOG.md | 2 ++ packages/compose/package.json | 2 +- packages/core-commands/CHANGELOG.md | 2 ++ packages/core-commands/package.json | 2 +- packages/core-data/CHANGELOG.md | 2 ++ packages/core-data/package.json | 2 +- packages/create-block-interactive-template/package.json | 2 +- packages/create-block-tutorial-template/CHANGELOG.md | 2 ++ packages/create-block-tutorial-template/package.json | 2 +- packages/create-block/CHANGELOG.md | 2 ++ packages/create-block/package.json | 2 +- packages/customize-widgets/CHANGELOG.md | 2 ++ packages/customize-widgets/package.json | 2 +- packages/data-controls/CHANGELOG.md | 2 ++ packages/data-controls/package.json | 2 +- packages/data/CHANGELOG.md | 2 ++ packages/data/package.json | 2 +- packages/dataviews/CHANGELOG.md | 2 ++ packages/dataviews/package.json | 2 +- packages/date/CHANGELOG.md | 2 ++ packages/date/package.json | 2 +- packages/dependency-extraction-webpack-plugin/CHANGELOG.md | 2 ++ packages/dependency-extraction-webpack-plugin/package.json | 2 +- packages/deprecated/CHANGELOG.md | 2 ++ packages/deprecated/package.json | 2 +- packages/docgen/CHANGELOG.md | 2 ++ packages/docgen/package.json | 2 +- packages/dom-ready/CHANGELOG.md | 2 ++ packages/dom-ready/package.json | 2 +- packages/dom/CHANGELOG.md | 2 ++ packages/dom/package.json | 2 +- packages/e2e-test-utils-playwright/CHANGELOG.md | 2 ++ packages/e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/CHANGELOG.md | 2 ++ packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/CHANGELOG.md | 2 ++ packages/e2e-tests/package.json | 2 +- packages/edit-post/CHANGELOG.md | 2 ++ packages/edit-post/package.json | 2 +- packages/edit-site/CHANGELOG.md | 2 ++ packages/edit-site/package.json | 2 +- packages/edit-widgets/CHANGELOG.md | 2 ++ packages/edit-widgets/package.json | 2 +- packages/editor/CHANGELOG.md | 2 ++ packages/editor/package.json | 2 +- packages/element/CHANGELOG.md | 2 ++ packages/element/package.json | 2 +- packages/env/CHANGELOG.md | 2 ++ packages/env/package.json | 2 +- packages/escape-html/CHANGELOG.md | 2 ++ packages/escape-html/package.json | 2 +- packages/eslint-plugin/CHANGELOG.md | 2 ++ packages/eslint-plugin/package.json | 2 +- packages/fields/CHANGELOG.md | 2 ++ packages/fields/package.json | 2 +- packages/format-library/CHANGELOG.md | 2 ++ packages/format-library/package.json | 2 +- packages/hooks/CHANGELOG.md | 2 ++ packages/hooks/package.json | 2 +- packages/html-entities/CHANGELOG.md | 2 ++ packages/html-entities/package.json | 2 +- packages/i18n/CHANGELOG.md | 2 ++ packages/i18n/package.json | 2 +- packages/icons/CHANGELOG.md | 2 ++ packages/icons/package.json | 2 +- packages/interactivity-router/CHANGELOG.md | 2 ++ packages/interactivity-router/package.json | 2 +- packages/interactivity/CHANGELOG.md | 2 ++ packages/interactivity/package.json | 2 +- packages/interface/CHANGELOG.md | 2 ++ packages/interface/package.json | 2 +- packages/is-shallow-equal/CHANGELOG.md | 2 ++ packages/is-shallow-equal/package.json | 2 +- packages/jest-console/CHANGELOG.md | 2 ++ packages/jest-console/package.json | 2 +- packages/jest-preset-default/CHANGELOG.md | 2 ++ packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/CHANGELOG.md | 2 ++ packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/CHANGELOG.md | 2 ++ packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/CHANGELOG.md | 2 ++ packages/keycodes/package.json | 2 +- packages/lazy-import/CHANGELOG.md | 2 ++ packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/CHANGELOG.md | 2 ++ packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/CHANGELOG.md | 2 ++ packages/media-utils/package.json | 2 +- packages/notices/CHANGELOG.md | 2 ++ packages/notices/package.json | 2 +- packages/npm-package-json-lint-config/CHANGELOG.md | 2 ++ packages/npm-package-json-lint-config/package.json | 2 +- packages/nux/CHANGELOG.md | 2 ++ packages/nux/package.json | 2 +- packages/patterns/CHANGELOG.md | 2 ++ packages/patterns/package.json | 2 +- packages/plugins/CHANGELOG.md | 2 ++ packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/CHANGELOG.md | 2 ++ packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/CHANGELOG.md | 2 ++ packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/CHANGELOG.md | 2 ++ packages/preferences-persistence/package.json | 2 +- packages/preferences/CHANGELOG.md | 2 ++ packages/preferences/package.json | 2 +- packages/prettier-config/CHANGELOG.md | 2 ++ packages/prettier-config/package.json | 2 +- packages/primitives/CHANGELOG.md | 2 ++ packages/primitives/package.json | 2 +- packages/priority-queue/CHANGELOG.md | 2 ++ packages/priority-queue/package.json | 2 +- packages/private-apis/CHANGELOG.md | 2 ++ packages/private-apis/package.json | 2 +- packages/project-management-automation/CHANGELOG.md | 2 ++ packages/project-management-automation/package.json | 2 +- packages/react-i18n/CHANGELOG.md | 2 ++ packages/react-i18n/package.json | 2 +- packages/readable-js-assets-webpack-plugin/CHANGELOG.md | 2 ++ packages/readable-js-assets-webpack-plugin/package.json | 2 +- packages/redux-routine/CHANGELOG.md | 2 ++ packages/redux-routine/package.json | 2 +- packages/reusable-blocks/CHANGELOG.md | 2 ++ packages/reusable-blocks/package.json | 2 +- packages/rich-text/CHANGELOG.md | 2 ++ packages/rich-text/package.json | 2 +- packages/router/CHANGELOG.md | 2 ++ packages/router/package.json | 2 +- packages/scripts/CHANGELOG.md | 2 ++ packages/scripts/package.json | 2 +- packages/server-side-render/CHANGELOG.md | 2 ++ packages/server-side-render/package.json | 2 +- packages/shortcode/CHANGELOG.md | 2 ++ packages/shortcode/package.json | 2 +- packages/style-engine/CHANGELOG.md | 2 ++ packages/style-engine/package.json | 2 +- packages/stylelint-config/CHANGELOG.md | 2 ++ packages/stylelint-config/package.json | 2 +- packages/sync/CHANGELOG.md | 2 ++ packages/sync/package.json | 2 +- packages/token-list/CHANGELOG.md | 2 ++ packages/token-list/package.json | 2 +- packages/undo-manager/CHANGELOG.md | 2 ++ packages/undo-manager/package.json | 2 +- packages/url/CHANGELOG.md | 2 ++ packages/url/package.json | 2 +- packages/viewport/CHANGELOG.md | 2 ++ packages/viewport/package.json | 2 +- packages/warning/CHANGELOG.md | 2 ++ packages/warning/package.json | 2 +- packages/widgets/CHANGELOG.md | 2 ++ packages/widgets/package.json | 2 +- packages/wordcount/CHANGELOG.md | 2 ++ packages/wordcount/package.json | 2 +- 191 files changed, 286 insertions(+), 96 deletions(-) diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index 7da784818f78c8..08ac31b560ca87 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 761367e0bb6f45..2c0696f5f1c579 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/CHANGELOG.md b/packages/annotations/CHANGELOG.md index caf30a752bb986..0f4795b11f109a 100644 --- a/packages/annotations/CHANGELOG.md +++ b/packages/annotations/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.10.0 (2024-10-16) + ## 3.9.0 (2024-10-03) ## 3.8.0 (2024-09-19) diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 417d6b22c9fd86..d18b5774086c25 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.9.0", + "version": "3.10.0-prerelease", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/CHANGELOG.md b/packages/api-fetch/CHANGELOG.md index 151afa5206c35c..dc654223da9e9f 100644 --- a/packages/api-fetch/CHANGELOG.md +++ b/packages/api-fetch/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.10.0 (2024-10-16) + ## 7.9.0 (2024-10-03) ## 7.8.0 (2024-09-19) diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 13d23eaf496115..184c23484f40c6 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.9.0", + "version": "7.10.0-prerelease", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/CHANGELOG.md b/packages/autop/CHANGELOG.md index b56c0ada46a919..0a4a27cfbed808 100644 --- a/packages/autop/CHANGELOG.md +++ b/packages/autop/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/autop/package.json b/packages/autop/package.json index 7025f39b7b4a4c..a865bc7bb6f495 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md index 8f15b849096f66..6935957675b432 100644 --- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md +++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index 82ced61c51e505..17c59b76f2322a 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/CHANGELOG.md b/packages/babel-plugin-makepot/CHANGELOG.md index d307791a37424a..7fbb829d65a842 100644 --- a/packages/babel-plugin-makepot/CHANGELOG.md +++ b/packages/babel-plugin-makepot/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.10.0 (2024-10-16) + ## 6.9.0 (2024-10-03) ## 6.8.0 (2024-09-19) diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index 0877bc9bf10bd8..8e3601df87b9a2 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.9.0", + "version": "6.10.0-prerelease", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index 4237d8266db30c..c787e176059298 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.10.0 (2024-10-16) + ### Enhancements - The bundled `@babel/core` dependency has been updated from requiring `^7.16.0` to requiring `7.25.7` ([#36244](https://github.com/WordPress/gutenberg/pull/36244)). diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index a7eb893c75f016..349872c0a8f694 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.9.0", + "version": "8.10.0-prerelease", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/CHANGELOG.md b/packages/base-styles/CHANGELOG.md index 8e92ddeece4d20..7535112c5a5c11 100644 --- a/packages/base-styles/CHANGELOG.md +++ b/packages/base-styles/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index b1da65dde47970..06dab95e0117d1 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md index 1631fe7e0618b3..c168f9698e68bd 100644 --- a/packages/blob/CHANGELOG.md +++ b/packages/blob/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/blob/package.json b/packages/blob/package.json index 158eb69e270089..12d2c31bc7ff73 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/CHANGELOG.md b/packages/block-directory/CHANGELOG.md index 2677ce827c1d69..7c2e092139b0ee 100644 --- a/packages/block-directory/CHANGELOG.md +++ b/packages/block-directory/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 5d0d489fdeedb5..5a0b4404d166dd 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 5e3151285966e2..1483fe1da9d5c9 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.5.0 (2024-10-16) + ## 14.4.0 (2024-10-03) ## 14.3.0 (2024-09-19) diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 32b8830fe48db0..f0329208460627 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.4.0", + "version": "14.5.0-prerelease", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index 5ffd428b6dbdcf..b3788917cfbb95 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.10.0 (2024-10-16) + ## 9.9.0 (2024-10-03) ## 9.8.0 (2024-09-19) diff --git a/packages/block-library/package.json b/packages/block-library/package.json index ba5283aee9da84..d75405ab1b2f10 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.9.0", + "version": "9.10.0-prerelease", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/CHANGELOG.md b/packages/block-serialization-default-parser/CHANGELOG.md index 4104f5282ce3fb..9b0457333bd7d5 100644 --- a/packages/block-serialization-default-parser/CHANGELOG.md +++ b/packages/block-serialization-default-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index c0cf1286835649..7219772247e51e 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/CHANGELOG.md b/packages/block-serialization-spec-parser/CHANGELOG.md index 87c683849585e0..40c93063cafbb7 100644 --- a/packages/block-serialization-spec-parser/CHANGELOG.md +++ b/packages/block-serialization-spec-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 38469f4d295298..266eb6ac3d4829 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 7e163fec2ad161..73a700428674b2 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 13.10.0 (2024-10-16) + ## 13.9.0 (2024-10-03) ## 13.8.0 (2024-09-19) diff --git a/packages/blocks/package.json b/packages/blocks/package.json index b66d06e7884c4f..c5053535b754ef 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.9.0", + "version": "13.10.0-prerelease", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/CHANGELOG.md b/packages/browserslist-config/CHANGELOG.md index 9dae2564c1a32e..8a2dc5d0ecc484 100644 --- a/packages/browserslist-config/CHANGELOG.md +++ b/packages/browserslist-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.10.0 (2024-10-16) + ## 6.9.0 (2024-10-03) ## 6.8.0 (2024-09-19) diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 0c4d314203483b..bfc521698e2943 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.9.0", + "version": "6.10.0-prerelease", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/CHANGELOG.md b/packages/commands/CHANGELOG.md index 2b268bd66f404e..c75dbab26739d8 100644 --- a/packages/commands/CHANGELOG.md +++ b/packages/commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.10.0 (2024-10-16) + ## 1.9.0 (2024-10-03) ## 1.8.0 (2024-09-19) diff --git a/packages/commands/package.json b/packages/commands/package.json index 8c4521da0a34b8..1275d5ff029bfa 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.9.0", + "version": "1.10.0-prerelease", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 64e5eeb1776523..d1e75d9e0a3a88 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 28.10.0 (2024-10-16) + ### Bug Fixes - `Tooltip`: add `aria-describedby` to the anchor only if not redundant ([#65989](https://github.com/WordPress/gutenberg/pull/65989)). diff --git a/packages/components/package.json b/packages/components/package.json index 0bc1c865299d2d..0a83b70516552a 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.9.0", + "version": "28.10.0-prerelease", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index e94eed5a08677b..f9d18eed43141d 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.10.0 (2024-10-16) + ## 7.9.0 (2024-10-03) ### Bug Fixes diff --git a/packages/compose/package.json b/packages/compose/package.json index 9f8a6287a8f044..39a502ccf8be9e 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.9.0", + "version": "7.10.0-prerelease", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/CHANGELOG.md b/packages/core-commands/CHANGELOG.md index bd259351a87999..83b809ad526302 100644 --- a/packages/core-commands/CHANGELOG.md +++ b/packages/core-commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.10.0 (2024-10-16) + ## 1.9.0 (2024-10-03) ## 1.8.0 (2024-09-19) diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 3ecc6ca145a71f..6d09c6a4955fe3 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.9.0", + "version": "1.10.0-prerelease", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md index 8a59c811840357..980f552ee0fca7 100644 --- a/packages/core-data/CHANGELOG.md +++ b/packages/core-data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.10.0 (2024-10-16) + ## 7.9.0 (2024-10-03) ## 7.8.0 (2024-09-19) diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 8eebcd083a83fa..533a32f179ccfb 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.9.0", + "version": "7.10.0-prerelease", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index e8b38dab906cca..e9466dc53b4b25 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.9.0", + "version": "2.10.0-prerelease", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/CHANGELOG.md b/packages/create-block-tutorial-template/CHANGELOG.md index 9be4223c70f383..8b4b467a1b4366 100644 --- a/packages/create-block-tutorial-template/CHANGELOG.md +++ b/packages/create-block-tutorial-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index 9eceb95dda83c5..853e4c7f1b71b4 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index db161872fb9828..87e647ec03dc03 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.53.0 (2024-10-16) + ## 4.52.0 (2024-10-03) ## 4.51.0 (2024-09-19) diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 7c31cb57687f00..4aca8901057687 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.52.0", + "version": "4.53.0-prerelease", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/CHANGELOG.md b/packages/customize-widgets/CHANGELOG.md index 46064bac3391ec..4c308aff491268 100644 --- a/packages/customize-widgets/CHANGELOG.md +++ b/packages/customize-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 4ad8407ef73cbc..9784c481faaed6 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/CHANGELOG.md b/packages/data-controls/CHANGELOG.md index 6e70039bc74765..cfbe9d3ea46632 100644 --- a/packages/data-controls/CHANGELOG.md +++ b/packages/data-controls/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 712e7165348e61..3e039eaad25ba6 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index 71db937ed73b48..44d7aa5f954ef2 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.10.0 (2024-10-16) + ## 10.9.0 (2024-10-03) ## 10.8.0 (2024-09-19) diff --git a/packages/data/package.json b/packages/data/package.json index 0320f7ffae681b..efb7974025b199 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.9.0", + "version": "10.10.0-prerelease", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index ebc35e336d6876..d5054b8578d95c 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 (2024-10-16) + - Invert the logic for which icon to show in `DataViews` when using the filter view. Icons now match the action of the button label. ([#65914](https://github.com/WordPress/gutenberg/pull/65914)). ## 4.5.0 (2024-10-03) diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index 0dbf07ca52ff98..9054b9ff1a54a4 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.5.0", + "version": "4.6.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md index 01e9cdc76984c8..4f35e1c2fcd475 100644 --- a/packages/date/CHANGELOG.md +++ b/packages/date/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/date/package.json b/packages/date/package.json index 71b1bc46bb147a..12cfb79059e129 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index c9d127e899fd73..4170d698ca5654 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.10.0 (2024-10-16) + ## 6.9.0 (2024-10-03) ### Enhancements diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index 2eb71b69864232..bdc23a609cd219 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.9.0", + "version": "6.10.0-prerelease", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/CHANGELOG.md b/packages/deprecated/CHANGELOG.md index 0fb389ad15d7e1..8289aedd728b6f 100644 --- a/packages/deprecated/CHANGELOG.md +++ b/packages/deprecated/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 541c01b072bb94..156aa74700d9a4 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/CHANGELOG.md b/packages/docgen/CHANGELOG.md index d01b1f9a9f62d7..139f85f8a62191 100644 --- a/packages/docgen/CHANGELOG.md +++ b/packages/docgen/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.10.0 (2024-10-16) + ## 2.9.0 (2024-10-03) ## 2.8.0 (2024-09-19) diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 0842d451a55a5a..87aec3445c18cd 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.9.0", + "version": "2.10.0-prerelease", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/CHANGELOG.md b/packages/dom-ready/CHANGELOG.md index a14e6185202376..ce17d989eac98d 100644 --- a/packages/dom-ready/CHANGELOG.md +++ b/packages/dom-ready/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 81fa96ab147826..a8a897c6392726 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/CHANGELOG.md b/packages/dom/CHANGELOG.md index e5c95089da8c36..51c8de37b61982 100644 --- a/packages/dom/CHANGELOG.md +++ b/packages/dom/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/dom/package.json b/packages/dom/package.json index 0e9250f0dbef39..c55090419733d3 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/CHANGELOG.md b/packages/e2e-test-utils-playwright/CHANGELOG.md index 0c1833eed08495..5b262e27f5e48b 100644 --- a/packages/e2e-test-utils-playwright/CHANGELOG.md +++ b/packages/e2e-test-utils-playwright/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.10.0 (2024-10-16) + ## 1.9.0 (2024-10-03) ## 1.8.0 (2024-09-19) diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index ebec29be94c89d..6009721ced92f6 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.9.0", + "version": "1.10.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index 8a00b87a34dfd9..84e4d4d564d659 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 11.10.0 (2024-10-16) + ## 11.9.0 (2024-10-03) ## 11.8.0 (2024-09-19) diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index 8ec9f34d8366a2..234510d5827e7b 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.9.0", + "version": "11.10.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md index 9d94db55206f10..9268bec00239f9 100644 --- a/packages/e2e-tests/CHANGELOG.md +++ b/packages/e2e-tests/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.10.0 (2024-10-16) + ## 8.9.0 (2024-10-03) ## 8.8.0 (2024-09-19) diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 714542e115c823..04ba6af0569d20 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.9.0", + "version": "8.10.0-prerelease", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index 41a960ee4e5d27..409af4ead284fd 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.10.0 (2024-10-16) + ## 8.9.0 (2024-10-03) ## 8.8.0 (2024-09-19) diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index babb8a84a65d67..0bf146900b5865 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.9.0", + "version": "8.10.0-prerelease", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/CHANGELOG.md b/packages/edit-site/CHANGELOG.md index e2a728b3fc9ce9..e1c4f09222ae67 100644 --- a/packages/edit-site/CHANGELOG.md +++ b/packages/edit-site/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.10.0 (2024-10-16) + ## 6.9.0 (2024-10-03) ## 6.8.0 (2024-09-19) diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 53f0204eae9968..fabb7ecf1f7053 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.9.0", + "version": "6.10.0-prerelease", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/CHANGELOG.md b/packages/edit-widgets/CHANGELOG.md index 80fde2bfec86e7..5b2fbd4d307416 100644 --- a/packages/edit-widgets/CHANGELOG.md +++ b/packages/edit-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.10.0 (2024-10-16) + ## 6.9.0 (2024-10-03) ## 6.8.0 (2024-09-19) diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 891d140a4f6d1b..a523241c9f7957 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.9.0", + "version": "6.10.0-prerelease", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index dbd2884ab88560..2d72126f377d9d 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.10.0 (2024-10-16) + ## 14.9.0 (2024-10-03) ## 14.8.0 (2024-09-19) diff --git a/packages/editor/package.json b/packages/editor/package.json index 96970acd7fd034..68cfe76a24dabc 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.9.0", + "version": "14.10.0-prerelease", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/CHANGELOG.md b/packages/element/CHANGELOG.md index c480f3a0469b53..1d6adbaef2c684 100644 --- a/packages/element/CHANGELOG.md +++ b/packages/element/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.10.0 (2024-10-16) + ## 6.9.0 (2024-10-03) ## 6.8.0 (2024-09-19) diff --git a/packages/element/package.json b/packages/element/package.json index 0160f504cdb832..f6892e7d6dfffb 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.9.0", + "version": "6.10.0-prerelease", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md index 1adbc578b11e2f..faffee0d5b4d30 100644 --- a/packages/env/CHANGELOG.md +++ b/packages/env/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.10.0 (2024-10-16) + ## 10.9.0 (2024-10-03) ## 10.8.0 (2024-09-19) diff --git a/packages/env/package.json b/packages/env/package.json index ef0a9ca1832013..28d09038cfdf0e 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.9.0", + "version": "10.10.0-prerelease", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/CHANGELOG.md b/packages/escape-html/CHANGELOG.md index 2ba6cc20e2438f..80a4194ec28051 100644 --- a/packages/escape-html/CHANGELOG.md +++ b/packages/escape-html/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.10.0 (2024-10-16) + ## 3.9.0 (2024-10-03) ## 3.8.0 (2024-09-19) diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index c5c5fdc8c694be..5bf91cc101929c 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.9.0", + "version": "3.10.0-prerelease", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 7425062a1cf10e..705312f977e661 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 21.3.0 (2024-10-16) + ## 21.2.0 (2024-10-03) ## 21.1.0 (2024-09-19) diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index af30427b6e4a8b..c79db5771b335e 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "21.2.0", + "version": "21.3.0-prerelease", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/fields/CHANGELOG.md b/packages/fields/CHANGELOG.md index 986cbcdec80568..26f61829fb8018 100644 --- a/packages/fields/CHANGELOG.md +++ b/packages/fields/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.2.0 (2024-10-16) + ## 0.1.0 (2024-10-03) Initial release. diff --git a/packages/fields/package.json b/packages/fields/package.json index 3c4edabf873a9a..b6f534fdf09898 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/fields", - "version": "0.1.0", + "version": "0.2.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/CHANGELOG.md b/packages/format-library/CHANGELOG.md index a2a23524a7a9a5..e2d931b4323745 100644 --- a/packages/format-library/CHANGELOG.md +++ b/packages/format-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/format-library/package.json b/packages/format-library/package.json index f868bf56fc59cb..61a3431db17d90 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/CHANGELOG.md b/packages/hooks/CHANGELOG.md index 962a94056fbbd2..a5caa23d755032 100644 --- a/packages/hooks/CHANGELOG.md +++ b/packages/hooks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ### New Features diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 47f89922f1a873..24020339807958 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/CHANGELOG.md b/packages/html-entities/CHANGELOG.md index 99da545e4e9a93..de6f098713c236 100644 --- a/packages/html-entities/CHANGELOG.md +++ b/packages/html-entities/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 935b4735dd3a46..c4fe9b3874caf2 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index 613da356ace7fb..0fc465873a31ff 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/i18n/package.json b/packages/i18n/package.json index fcc47e9b7dca30..27288530873b7b 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index e33269cd7be390..4082e510708164 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.10.0 (2024-10-16) + ### Enhancements - Update `cloudUpload` icon to improve visibility of the up arrow. diff --git a/packages/icons/package.json b/packages/icons/package.json index bd2db0224b8cbe..61740ce6e9f0f3 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.9.0", + "version": "10.10.0-prerelease", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/CHANGELOG.md b/packages/interactivity-router/CHANGELOG.md index 10294b3a7e6204..8b7db29395a547 100644 --- a/packages/interactivity-router/CHANGELOG.md +++ b/packages/interactivity-router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.10.0 (2024-10-16) + ### Enhancements - Improvements to the experimental full-page navigation ([#64067](https://github.com/WordPress/gutenberg/pull/64067)): diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 529d7a2ad1f32f..ec875f3c4d9996 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.9.0", + "version": "2.10.0-prerelease", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index be6bdeefe81e0d..b5a8fbcb9dde50 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.10.0 (2024-10-16) + ### Internal - Upgrade preact libraries [#66008](https://github.com/WordPress/gutenberg/pull/66008). diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 2519e983e93446..ea0d90516decf7 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.9.0", + "version": "6.10.0-prerelease", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index 985fed5a140437..f9b9181fa75434 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.0.0 (2024-10-16) + ### Breaking Changes - `InterfaceSkeleton` no longer supports region navigation and its props `enableRegionNavigation` and `shortcuts` are removed. ([#63611](https://github.com/WordPress/gutenberg/pull/63611)). It’s recommended to add region navigation with the higher-order component `navigateRegions` or the hook `__unstableUseNavigateRegions` from `@wordpress/components`. diff --git a/packages/interface/package.json b/packages/interface/package.json index 7c4d65a0367b06..22d6b017908604 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "6.9.0", + "version": "7.0.0-prerelease", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/CHANGELOG.md b/packages/is-shallow-equal/CHANGELOG.md index 44bbf38076085a..8dc6be12e1e874 100644 --- a/packages/is-shallow-equal/CHANGELOG.md +++ b/packages/is-shallow-equal/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 7125e4604c506c..5d66f218718737 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/CHANGELOG.md b/packages/jest-console/CHANGELOG.md index 440d41bcc2dc36..693445ed35ef41 100644 --- a/packages/jest-console/CHANGELOG.md +++ b/packages/jest-console/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.10.0 (2024-10-16) + ## 8.9.0 (2024-10-03) ## 8.8.0 (2024-09-19) diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 514a62b085ee04..f4c7d04aa6bc37 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.9.0", + "version": "8.10.0-prerelease", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md index 137c03dce8c7ad..44f121c25e3ee4 100644 --- a/packages/jest-preset-default/CHANGELOG.md +++ b/packages/jest-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 12.10.0 (2024-10-16) + ## 12.9.0 (2024-10-03) ## 12.8.0 (2024-09-19) diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 6a8b91f4d41d5e..bc4a422753cfbe 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.9.0", + "version": "12.10.0-prerelease", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/CHANGELOG.md b/packages/jest-puppeteer-axe/CHANGELOG.md index 7e5503f13eddf1..e3b455827c1971 100644 --- a/packages/jest-puppeteer-axe/CHANGELOG.md +++ b/packages/jest-puppeteer-axe/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.10.0 (2024-10-16) + ## 7.9.0 (2024-10-03) ## 7.8.0 (2024-09-19) diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 0c82889d48c65b..2dde7854bb300e 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.9.0", + "version": "7.10.0-prerelease", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/CHANGELOG.md b/packages/keyboard-shortcuts/CHANGELOG.md index 2c23a099857a33..f549dfcd73b70a 100644 --- a/packages/keyboard-shortcuts/CHANGELOG.md +++ b/packages/keyboard-shortcuts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 96f86771f49099..a10fe0a48a7689 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/CHANGELOG.md b/packages/keycodes/CHANGELOG.md index 1ef044b263e1f3..5b300b79211f38 100644 --- a/packages/keycodes/CHANGELOG.md +++ b/packages/keycodes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 9e34c83952838d..821fbd25c9e492 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/CHANGELOG.md b/packages/lazy-import/CHANGELOG.md index c09059768e81a7..025c2ce1c066da 100644 --- a/packages/lazy-import/CHANGELOG.md +++ b/packages/lazy-import/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.10.0 (2024-10-16) + ## 2.9.0 (2024-10-03) ## 2.8.0 (2024-09-19) diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index 8343dcfeed00be..3d844311b9f8ad 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.9.0", + "version": "2.10.0-prerelease", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/CHANGELOG.md b/packages/list-reusable-blocks/CHANGELOG.md index eb0b3a7cf6b48f..8c2134934192d8 100644 --- a/packages/list-reusable-blocks/CHANGELOG.md +++ b/packages/list-reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index d50f257805465b..768ae065967a57 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/CHANGELOG.md b/packages/media-utils/CHANGELOG.md index 20272be5b7d7be..f47ed34c718d16 100644 --- a/packages/media-utils/CHANGELOG.md +++ b/packages/media-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 4d5b3c8ccc0f8f..5cd6eeb3f5ea80 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/CHANGELOG.md b/packages/notices/CHANGELOG.md index 1c4f629fb2c345..3c55e67bb1b021 100644 --- a/packages/notices/CHANGELOG.md +++ b/packages/notices/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/notices/package.json b/packages/notices/package.json index 8bac25815d88cf..8d472d6c20b329 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/CHANGELOG.md b/packages/npm-package-json-lint-config/CHANGELOG.md index 511f6e8f3b6c4e..e4c7943dc448a3 100644 --- a/packages/npm-package-json-lint-config/CHANGELOG.md +++ b/packages/npm-package-json-lint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index abde4d2490cc9b..435ad98cb6a11a 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/CHANGELOG.md b/packages/nux/CHANGELOG.md index 19ddfd39b2156d..c0af370a933b53 100644 --- a/packages/nux/CHANGELOG.md +++ b/packages/nux/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.10.0 (2024-10-16) + ## 9.9.0 (2024-10-03) ## 9.8.0 (2024-09-19) diff --git a/packages/nux/package.json b/packages/nux/package.json index dfc69ba6ccf1ad..b11370d3e1e64b 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.9.0", + "version": "9.10.0-prerelease", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/CHANGELOG.md b/packages/patterns/CHANGELOG.md index e15ac90000ba4e..31fa83ee8b93bb 100644 --- a/packages/patterns/CHANGELOG.md +++ b/packages/patterns/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.10.0 (2024-10-16) + ## 2.9.0 (2024-10-03) ## 2.8.0 (2024-09-19) diff --git a/packages/patterns/package.json b/packages/patterns/package.json index edafe4f1c9fefb..fd32c4dd50975c 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.9.0", + "version": "2.10.0-prerelease", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/CHANGELOG.md b/packages/plugins/CHANGELOG.md index 9b378eb71f5827..aa54e27a3913da 100644 --- a/packages/plugins/CHANGELOG.md +++ b/packages/plugins/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.10.0 (2024-10-16) + ## 7.9.0 (2024-10-03) ## 7.8.0 (2024-09-19) diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 6ea881e56931bb..d923aed8797884 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.9.0", + "version": "7.10.0-prerelease", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/CHANGELOG.md b/packages/postcss-plugins-preset/CHANGELOG.md index f21d7016240e03..514307874acb12 100644 --- a/packages/postcss-plugins-preset/CHANGELOG.md +++ b/packages/postcss-plugins-preset/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 8e1db61b9668c2..852ff6949a4c44 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/CHANGELOG.md b/packages/postcss-themes/CHANGELOG.md index 19c2acccf0f750..55c0311cc6b95e 100644 --- a/packages/postcss-themes/CHANGELOG.md +++ b/packages/postcss-themes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.10.0 (2024-10-16) + ## 6.9.0 (2024-10-03) ## 6.8.0 (2024-09-19) diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index e7752b3aaa3526..568eeb09e48e61 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.9.0", + "version": "6.10.0-prerelease", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/CHANGELOG.md b/packages/preferences-persistence/CHANGELOG.md index b3f4193fa0c9ee..b9efaa9c69049f 100644 --- a/packages/preferences-persistence/CHANGELOG.md +++ b/packages/preferences-persistence/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.10.0 (2024-10-16) + ## 2.9.0 (2024-10-03) ## 2.8.0 (2024-09-19) diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index 06e005ba49b079..83bf47d5765852 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.9.0", + "version": "2.10.0-prerelease", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/CHANGELOG.md b/packages/preferences/CHANGELOG.md index 114027eed2e228..3b1711b5d87b04 100644 --- a/packages/preferences/CHANGELOG.md +++ b/packages/preferences/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/preferences/package.json b/packages/preferences/package.json index 2cf9b0666da390..e8da2489192ef5 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/CHANGELOG.md b/packages/prettier-config/CHANGELOG.md index 17b3fc88b5ccde..33a0261603fb7c 100644 --- a/packages/prettier-config/CHANGELOG.md +++ b/packages/prettier-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 3f77e6bb125bb5..e27118ca3d3016 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/CHANGELOG.md b/packages/primitives/CHANGELOG.md index 8c646a4dc6c5ca..02b3d9176b2ca8 100644 --- a/packages/primitives/CHANGELOG.md +++ b/packages/primitives/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 9348dff41e66b7..f37b0c986f37ed 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/CHANGELOG.md b/packages/priority-queue/CHANGELOG.md index 7254d4e3f37185..e080b71c08182a 100644 --- a/packages/priority-queue/CHANGELOG.md +++ b/packages/priority-queue/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.10.0 (2024-10-16) + ## 3.9.0 (2024-10-03) ## 3.8.0 (2024-09-19) diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 3414ce59031797..c14217d3100862 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.9.0", + "version": "3.10.0-prerelease", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/CHANGELOG.md b/packages/private-apis/CHANGELOG.md index bd13576ccbcd04..99887b6f4b6152 100644 --- a/packages/private-apis/CHANGELOG.md +++ b/packages/private-apis/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.10.0 (2024-10-16) + ## 1.9.0 (2024-10-03) ## 1.8.0 (2024-09-19) diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index 230d880ac72a6f..927e53ec3e862e 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.9.0", + "version": "1.10.0-prerelease", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/CHANGELOG.md b/packages/project-management-automation/CHANGELOG.md index c48bc76452a5a5..c7b3021d4679c5 100644 --- a/packages/project-management-automation/CHANGELOG.md +++ b/packages/project-management-automation/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.10.0 (2024-10-16) + ## 2.9.0 (2024-10-03) ## 2.8.0 (2024-09-19) diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 2da7535df6d111..d984238dfdd561 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.9.0", + "version": "2.10.0-prerelease", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/CHANGELOG.md b/packages/react-i18n/CHANGELOG.md index fa1b416809ca5c..6efaf980c320bc 100644 --- a/packages/react-i18n/CHANGELOG.md +++ b/packages/react-i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 4870e47ab13ecd..edad4a16e22fe0 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md index c93a667a8faf00..bd5ff8879c2a14 100644 --- a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md +++ b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.10.0 (2024-10-16) + ## 3.9.0 (2024-10-03) ## 3.8.0 (2024-09-19) diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index 8f90b19356c4ee..3562e61cd4db9b 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.9.0", + "version": "3.10.0-prerelease", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/CHANGELOG.md b/packages/redux-routine/CHANGELOG.md index 8154e640d3c98f..0aadde8ca5fa34 100644 --- a/packages/redux-routine/CHANGELOG.md +++ b/packages/redux-routine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 22fef722bf6152..321baa697446e5 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/CHANGELOG.md b/packages/reusable-blocks/CHANGELOG.md index 5e94ec24079144..62e09d8e61dfc6 100644 --- a/packages/reusable-blocks/CHANGELOG.md +++ b/packages/reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index dab24659ca176d..605ea09f46ee29 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/CHANGELOG.md b/packages/rich-text/CHANGELOG.md index 7fe0e351c6f5fe..5717f59a34d285 100644 --- a/packages/rich-text/CHANGELOG.md +++ b/packages/rich-text/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.10.0 (2024-10-16) + ## 7.9.0 (2024-10-03) ## 7.8.0 (2024-09-19) diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 68ffc5ee35e6f1..8b9e32d128c797 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.9.0", + "version": "7.10.0-prerelease", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index 0ce856ea20e88b..23f553b847a404 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.10.0 (2024-10-16) + ### Enhancements - Rewrite the package in typescript ([#65854](https://github.com/WordPress/gutenberg/pull/65854)). diff --git a/packages/router/package.json b/packages/router/package.json index 594970d85378d0..eed2e44e7e65f6 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.9.0", + "version": "1.10.0-prerelease", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index e7b40a3c1f3463..6d72d80d91f0a5 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 30.2.0 (2024-10-16) + ## 30.1.0 (2024-10-03) ## 30.0.0 (2024-09-19) diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 821097d728ab06..0a20c6b006b192 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.1.0", + "version": "30.2.0-prerelease", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/CHANGELOG.md b/packages/server-side-render/CHANGELOG.md index 43de483ed7ae53..3e7fefedfe287b 100644 --- a/packages/server-side-render/CHANGELOG.md +++ b/packages/server-side-render/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.10.0 (2024-10-16) + ## 5.9.0 (2024-10-03) ## 5.8.0 (2024-09-19) diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index c1a5bd731e29a3..f16912063e1f52 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.9.0", + "version": "5.10.0-prerelease", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/CHANGELOG.md b/packages/shortcode/CHANGELOG.md index e3efee9b49779e..ea651b6af87f0d 100644 --- a/packages/shortcode/CHANGELOG.md +++ b/packages/shortcode/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index 478754a31e1026..c69671cc7b20d4 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md index 3435553b63a713..5ad39afec7952c 100644 --- a/packages/style-engine/CHANGELOG.md +++ b/packages/style-engine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.10.0 (2024-10-16) + ## 2.9.0 (2024-10-03) ## 2.8.0 (2024-09-19) diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index ed194f57ff3a9f..9256dc95dd4e24 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.9.0", + "version": "2.10.0-prerelease", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/CHANGELOG.md b/packages/stylelint-config/CHANGELOG.md index ada350fe2fe577..9d263fee2648f7 100644 --- a/packages/stylelint-config/CHANGELOG.md +++ b/packages/stylelint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 23.2.0 (2024-10-16) + ## 23.1.0 (2024-10-03) ## 23.0.0 (2024-09-19) diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 3cb8b481dd4201..3c6031d16db2a1 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "23.1.0", + "version": "23.2.0-prerelease", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/CHANGELOG.md b/packages/sync/CHANGELOG.md index 00141ee08526d7..bbfb3cbb539fd5 100644 --- a/packages/sync/CHANGELOG.md +++ b/packages/sync/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.10.0 (2024-10-16) + ## 1.9.0 (2024-10-03) ## 1.8.0 (2024-09-19) diff --git a/packages/sync/package.json b/packages/sync/package.json index 9d8633558789e8..bd16c61453f1f5 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.9.0", + "version": "1.10.0-prerelease", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/CHANGELOG.md b/packages/token-list/CHANGELOG.md index 77fb52c6ddd2a2..3f46da49645186 100644 --- a/packages/token-list/CHANGELOG.md +++ b/packages/token-list/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.10.0 (2024-10-16) + ## 3.9.0 (2024-10-03) ## 3.8.0 (2024-09-19) diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 4b2ef6fd9d576f..194766faecadc4 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.9.0", + "version": "3.10.0-prerelease", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/CHANGELOG.md b/packages/undo-manager/CHANGELOG.md index 7375a328e01e9d..a3b1f6c6ecdab8 100644 --- a/packages/undo-manager/CHANGELOG.md +++ b/packages/undo-manager/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.10.0 (2024-10-16) + ## 1.9.0 (2024-10-03) ## 1.8.0 (2024-09-19) diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 02b72044c01656..c2e38681c26acc 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.9.0", + "version": "1.10.0-prerelease", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/CHANGELOG.md b/packages/url/CHANGELOG.md index 93be01f8540a2e..fb1175f11adeb7 100644 --- a/packages/url/CHANGELOG.md +++ b/packages/url/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/url/package.json b/packages/url/package.json index 22deb9b8c81be2..50bbe8c2f560e8 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/CHANGELOG.md b/packages/viewport/CHANGELOG.md index c80489b94eac6a..3447e75fd97c6e 100644 --- a/packages/viewport/CHANGELOG.md +++ b/packages/viewport/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.10.0 (2024-10-16) + ## 6.9.0 (2024-10-03) ## 6.8.0 (2024-09-19) diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 3997038bfbd8cc..97e0fef884ad0e 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.9.0", + "version": "6.10.0-prerelease", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/CHANGELOG.md b/packages/warning/CHANGELOG.md index dc56abe7208cb2..bce0ba957230b9 100644 --- a/packages/warning/CHANGELOG.md +++ b/packages/warning/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.10.0 (2024-10-16) + ## 3.9.0 (2024-10-03) ## 3.8.0 (2024-09-19) diff --git a/packages/warning/package.json b/packages/warning/package.json index 7499ced5cb962f..d8ec34abd1bcef 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.9.0", + "version": "3.10.0-prerelease", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/CHANGELOG.md b/packages/widgets/CHANGELOG.md index aaa2e56d0c625c..2436b6b03bed2e 100644 --- a/packages/widgets/CHANGELOG.md +++ b/packages/widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/widgets/package.json b/packages/widgets/package.json index ef5e953ffe5f2a..66dffa6804200b 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/CHANGELOG.md b/packages/wordcount/CHANGELOG.md index 9eeefc104183df..c622c99b324dd7 100644 --- a/packages/wordcount/CHANGELOG.md +++ b/packages/wordcount/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.10.0 (2024-10-16) + ## 4.9.0 (2024-10-03) ## 4.8.0 (2024-09-19) diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index 5be9c2073df1df..311a5320e8f997 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.9.0", + "version": "4.10.0-prerelease", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 2705cd737cef7127e7d9414102970d4f77d24e8d Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 16 Oct 2024 16:50:30 +0000 Subject: [PATCH 1201/1908] chore(release): publish - @wordpress/a11y@4.10.0 - @wordpress/annotations@3.10.0 - @wordpress/api-fetch@7.10.0 - @wordpress/autop@4.10.0 - @wordpress/babel-plugin-import-jsx-pragma@5.10.0 - @wordpress/babel-plugin-makepot@6.10.0 - @wordpress/babel-preset-default@8.10.0 - @wordpress/base-styles@5.10.0 - @wordpress/blob@4.10.0 - @wordpress/block-directory@5.10.0 - @wordpress/block-editor@14.5.0 - @wordpress/block-library@9.10.0 - @wordpress/block-serialization-default-parser@5.10.0 - @wordpress/block-serialization-spec-parser@5.10.0 - @wordpress/blocks@13.10.0 - @wordpress/browserslist-config@6.10.0 - @wordpress/commands@1.10.0 - @wordpress/components@28.10.0 - @wordpress/compose@7.10.0 - @wordpress/core-commands@1.10.0 - @wordpress/core-data@7.10.0 - @wordpress/create-block@4.53.0 - @wordpress/create-block-interactive-template@2.10.0 - @wordpress/create-block-tutorial-template@4.10.0 - @wordpress/customize-widgets@5.10.0 - @wordpress/data@10.10.0 - @wordpress/data-controls@4.10.0 - @wordpress/dataviews@4.6.0 - @wordpress/date@5.10.0 - @wordpress/dependency-extraction-webpack-plugin@6.10.0 - @wordpress/deprecated@4.10.0 - @wordpress/docgen@2.10.0 - @wordpress/dom@4.10.0 - @wordpress/dom-ready@4.10.0 - @wordpress/e2e-test-utils@11.10.0 - @wordpress/e2e-test-utils-playwright@1.10.0 - @wordpress/e2e-tests@8.10.0 - @wordpress/edit-post@8.10.0 - @wordpress/edit-site@6.10.0 - @wordpress/edit-widgets@6.10.0 - @wordpress/editor@14.10.0 - @wordpress/element@6.10.0 - @wordpress/env@10.10.0 - @wordpress/escape-html@3.10.0 - @wordpress/eslint-plugin@21.3.0 - @wordpress/fields@0.2.0 - @wordpress/format-library@5.10.0 - @wordpress/hooks@4.10.0 - @wordpress/html-entities@4.10.0 - @wordpress/i18n@5.10.0 - @wordpress/icons@10.10.0 - @wordpress/interactivity@6.10.0 - @wordpress/interactivity-router@2.10.0 - @wordpress/interface@7.0.0 - @wordpress/is-shallow-equal@5.10.0 - @wordpress/jest-console@8.10.0 - @wordpress/jest-preset-default@12.10.0 - @wordpress/jest-puppeteer-axe@7.10.0 - @wordpress/keyboard-shortcuts@5.10.0 - @wordpress/keycodes@4.10.0 - @wordpress/lazy-import@2.10.0 - @wordpress/list-reusable-blocks@5.10.0 - @wordpress/media-utils@5.10.0 - @wordpress/notices@5.10.0 - @wordpress/npm-package-json-lint-config@5.10.0 - @wordpress/nux@9.10.0 - @wordpress/patterns@2.10.0 - @wordpress/plugins@7.10.0 - @wordpress/postcss-plugins-preset@5.10.0 - @wordpress/postcss-themes@6.10.0 - @wordpress/preferences@4.10.0 - @wordpress/preferences-persistence@2.10.0 - @wordpress/prettier-config@4.10.0 - @wordpress/primitives@4.10.0 - @wordpress/priority-queue@3.10.0 - @wordpress/private-apis@1.10.0 - @wordpress/project-management-automation@2.10.0 - @wordpress/react-i18n@4.10.0 - @wordpress/readable-js-assets-webpack-plugin@3.10.0 - @wordpress/redux-routine@5.10.0 - @wordpress/reusable-blocks@5.10.0 - @wordpress/rich-text@7.10.0 - @wordpress/router@1.10.0 - @wordpress/scripts@30.2.0 - @wordpress/server-side-render@5.10.0 - @wordpress/shortcode@4.10.0 - @wordpress/style-engine@2.10.0 - @wordpress/stylelint-config@23.2.0 - @wordpress/sync@1.10.0 - @wordpress/token-list@3.10.0 - @wordpress/undo-manager@1.10.0 - @wordpress/url@4.10.0 - @wordpress/viewport@6.10.0 - @wordpress/warning@3.10.0 - @wordpress/widgets@4.10.0 - @wordpress/wordcount@4.10.0 --- package-lock.json | 190 +++++++++--------- packages/a11y/package.json | 2 +- packages/annotations/package.json | 2 +- packages/api-fetch/package.json | 2 +- packages/autop/package.json | 2 +- .../package.json | 2 +- packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/package.json | 2 +- packages/base-styles/package.json | 2 +- packages/blob/package.json | 2 +- packages/block-directory/package.json | 2 +- packages/block-editor/package.json | 2 +- packages/block-library/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/blocks/package.json | 2 +- packages/browserslist-config/package.json | 2 +- packages/commands/package.json | 2 +- packages/components/package.json | 2 +- packages/compose/package.json | 2 +- packages/core-commands/package.json | 2 +- packages/core-data/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/create-block/package.json | 2 +- packages/customize-widgets/package.json | 2 +- packages/data-controls/package.json | 2 +- packages/data/package.json | 2 +- packages/dataviews/package.json | 2 +- packages/date/package.json | 2 +- .../package.json | 2 +- packages/deprecated/package.json | 2 +- packages/docgen/package.json | 2 +- packages/dom-ready/package.json | 2 +- packages/dom/package.json | 2 +- .../e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/package.json | 2 +- packages/edit-post/package.json | 2 +- packages/edit-site/package.json | 2 +- packages/edit-widgets/package.json | 2 +- packages/editor/package.json | 2 +- packages/element/package.json | 2 +- packages/env/package.json | 2 +- packages/escape-html/package.json | 2 +- packages/eslint-plugin/package.json | 2 +- packages/fields/package.json | 2 +- packages/format-library/package.json | 2 +- packages/hooks/package.json | 2 +- packages/html-entities/package.json | 2 +- packages/i18n/package.json | 2 +- packages/icons/package.json | 2 +- packages/interactivity-router/package.json | 2 +- packages/interactivity/package.json | 2 +- packages/interface/package.json | 2 +- packages/is-shallow-equal/package.json | 2 +- packages/jest-console/package.json | 2 +- packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/package.json | 2 +- packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/package.json | 2 +- packages/notices/package.json | 2 +- .../npm-package-json-lint-config/package.json | 2 +- packages/nux/package.json | 2 +- packages/patterns/package.json | 2 +- packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/package.json | 2 +- packages/preferences/package.json | 2 +- packages/prettier-config/package.json | 2 +- packages/primitives/package.json | 2 +- packages/priority-queue/package.json | 2 +- packages/private-apis/package.json | 2 +- .../package.json | 2 +- packages/react-i18n/package.json | 2 +- .../package.json | 2 +- packages/redux-routine/package.json | 2 +- packages/reusable-blocks/package.json | 2 +- packages/rich-text/package.json | 2 +- packages/router/package.json | 2 +- packages/scripts/package.json | 2 +- packages/server-side-render/package.json | 2 +- packages/shortcode/package.json | 2 +- packages/style-engine/package.json | 2 +- packages/stylelint-config/package.json | 2 +- packages/sync/package.json | 2 +- packages/token-list/package.json | 2 +- packages/undo-manager/package.json | 2 +- packages/url/package.json | 2 +- packages/viewport/package.json | 2 +- packages/warning/package.json | 2 +- packages/widgets/package.json | 2 +- packages/wordcount/package.json | 2 +- 97 files changed, 191 insertions(+), 191 deletions(-) diff --git a/package-lock.json b/package-lock.json index 764a441a117a62..3201aaf06682d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52690,7 +52690,7 @@ }, "packages/a11y": { "name": "@wordpress/a11y", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -52704,7 +52704,7 @@ }, "packages/annotations": { "name": "@wordpress/annotations", - "version": "3.9.0", + "version": "3.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -52732,7 +52732,7 @@ }, "packages/api-fetch": { "name": "@wordpress/api-fetch", - "version": "7.9.0", + "version": "7.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -52746,7 +52746,7 @@ }, "packages/autop": { "name": "@wordpress/autop", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -52758,7 +52758,7 @@ }, "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.9.0", + "version": "5.10.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -52771,7 +52771,7 @@ }, "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", - "version": "6.9.0", + "version": "6.10.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -52789,7 +52789,7 @@ }, "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", - "version": "8.9.0", + "version": "8.10.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54045,7 +54045,7 @@ }, "packages/base-styles": { "name": "@wordpress/base-styles", - "version": "5.9.0", + "version": "5.10.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54055,7 +54055,7 @@ }, "packages/blob": { "name": "@wordpress/blob", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54067,7 +54067,7 @@ }, "packages/block-directory": { "name": "@wordpress/block-directory", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54103,7 +54103,7 @@ }, "packages/block-editor": { "name": "@wordpress/block-editor", - "version": "14.4.0", + "version": "14.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54202,7 +54202,7 @@ }, "packages/block-library": { "name": "@wordpress/block-library", - "version": "9.9.0", + "version": "9.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54268,7 +54268,7 @@ }, "packages/block-serialization-default-parser": { "name": "@wordpress/block-serialization-default-parser", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54280,7 +54280,7 @@ }, "packages/block-serialization-spec-parser": { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "pegjs": "^0.10.0", @@ -54293,7 +54293,7 @@ }, "packages/blocks": { "name": "@wordpress/blocks", - "version": "13.9.0", + "version": "13.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54347,7 +54347,7 @@ }, "packages/browserslist-config": { "name": "@wordpress/browserslist-config", - "version": "6.9.0", + "version": "6.10.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54357,7 +54357,7 @@ }, "packages/commands": { "name": "@wordpress/commands", - "version": "1.9.0", + "version": "1.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54530,7 +54530,7 @@ }, "packages/components": { "name": "@wordpress/components", - "version": "28.9.0", + "version": "28.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -54651,7 +54651,7 @@ }, "packages/compose": { "name": "@wordpress/compose", - "version": "7.9.0", + "version": "7.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54688,7 +54688,7 @@ }, "packages/core-commands": { "name": "@wordpress/core-commands", - "version": "1.9.0", + "version": "1.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54717,7 +54717,7 @@ }, "packages/core-data": { "name": "@wordpress/core-data", - "version": "7.9.0", + "version": "7.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54762,7 +54762,7 @@ }, "packages/create-block": { "name": "@wordpress/create-block", - "version": "4.52.0", + "version": "4.53.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54790,7 +54790,7 @@ }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", - "version": "4.9.0", + "version": "4.10.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54800,7 +54800,7 @@ }, "packages/customize-widgets": { "name": "@wordpress/customize-widgets", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54839,7 +54839,7 @@ }, "packages/data": { "name": "@wordpress/data", - "version": "10.9.0", + "version": "10.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54868,7 +54868,7 @@ }, "packages/data-controls": { "name": "@wordpress/data-controls", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54886,7 +54886,7 @@ }, "packages/dataviews": { "name": "@wordpress/dataviews", - "version": "4.5.0", + "version": "4.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -54943,7 +54943,7 @@ }, "packages/date": { "name": "@wordpress/date", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54958,7 +54958,7 @@ }, "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.9.0", + "version": "6.10.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54974,7 +54974,7 @@ }, "packages/deprecated": { "name": "@wordpress/deprecated", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54987,7 +54987,7 @@ }, "packages/docgen": { "name": "@wordpress/docgen", - "version": "2.9.0", + "version": "2.10.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55009,7 +55009,7 @@ }, "packages/dom": { "name": "@wordpress/dom", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55022,7 +55022,7 @@ }, "packages/dom-ready": { "name": "@wordpress/dom-ready", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -55034,7 +55034,7 @@ }, "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", - "version": "11.9.0", + "version": "11.10.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55057,7 +55057,7 @@ }, "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.9.0", + "version": "1.10.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55085,7 +55085,7 @@ }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", - "version": "8.9.0", + "version": "8.10.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55125,7 +55125,7 @@ }, "packages/edit-post": { "name": "@wordpress/edit-post", - "version": "8.9.0", + "version": "8.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55172,7 +55172,7 @@ }, "packages/edit-site": { "name": "@wordpress/edit-site", - "version": "6.9.0", + "version": "6.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55234,7 +55234,7 @@ }, "packages/edit-widgets": { "name": "@wordpress/edit-widgets", - "version": "6.9.0", + "version": "6.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55278,7 +55278,7 @@ }, "packages/editor": { "name": "@wordpress/editor", - "version": "14.9.0", + "version": "14.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55340,7 +55340,7 @@ }, "packages/element": { "name": "@wordpress/element", - "version": "6.9.0", + "version": "6.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55359,7 +55359,7 @@ }, "packages/env": { "name": "@wordpress/env", - "version": "10.9.0", + "version": "10.10.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55501,7 +55501,7 @@ }, "packages/escape-html": { "name": "@wordpress/escape-html", - "version": "3.9.0", + "version": "3.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -55513,7 +55513,7 @@ }, "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", - "version": "21.2.0", + "version": "21.3.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55585,7 +55585,7 @@ }, "packages/fields": { "name": "@wordpress/fields", - "version": "0.1.0", + "version": "0.2.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55621,7 +55621,7 @@ }, "packages/format-library": { "name": "@wordpress/format-library", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55649,7 +55649,7 @@ }, "packages/hooks": { "name": "@wordpress/hooks", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -55661,7 +55661,7 @@ }, "packages/html-entities": { "name": "@wordpress/html-entities", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -55673,7 +55673,7 @@ }, "packages/i18n": { "name": "@wordpress/i18n", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55693,7 +55693,7 @@ }, "packages/icons": { "name": "@wordpress/icons", - "version": "10.9.0", + "version": "10.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55707,7 +55707,7 @@ }, "packages/interactivity": { "name": "@wordpress/interactivity", - "version": "6.9.0", + "version": "6.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@preact/signals": "^1.3.0", @@ -55720,7 +55720,7 @@ }, "packages/interactivity-router": { "name": "@wordpress/interactivity-router", - "version": "2.9.0", + "version": "2.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/a11y": "file:../a11y", @@ -55733,7 +55733,7 @@ }, "packages/interface": { "name": "@wordpress/interface", - "version": "6.9.0", + "version": "7.0.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55762,7 +55762,7 @@ }, "packages/is-shallow-equal": { "name": "@wordpress/is-shallow-equal", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -55774,7 +55774,7 @@ }, "packages/jest-console": { "name": "@wordpress/jest-console", - "version": "8.9.0", + "version": "8.10.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55791,7 +55791,7 @@ }, "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", - "version": "12.9.0", + "version": "12.10.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55809,7 +55809,7 @@ }, "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.9.0", + "version": "7.10.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55832,7 +55832,7 @@ }, "packages/keyboard-shortcuts": { "name": "@wordpress/keyboard-shortcuts", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55850,7 +55850,7 @@ }, "packages/keycodes": { "name": "@wordpress/keycodes", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55863,7 +55863,7 @@ }, "packages/lazy-import": { "name": "@wordpress/lazy-import", - "version": "2.9.0", + "version": "2.10.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55878,7 +55878,7 @@ }, "packages/list-reusable-blocks": { "name": "@wordpress/list-reusable-blocks", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55901,7 +55901,7 @@ }, "packages/media-utils": { "name": "@wordpress/media-utils", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55917,7 +55917,7 @@ }, "packages/notices": { "name": "@wordpress/notices", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55934,7 +55934,7 @@ }, "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.9.0", + "version": "5.10.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -55947,7 +55947,7 @@ }, "packages/nux": { "name": "@wordpress/nux", - "version": "9.9.0", + "version": "9.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55970,7 +55970,7 @@ }, "packages/patterns": { "name": "@wordpress/patterns", - "version": "2.9.0", + "version": "2.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56000,7 +56000,7 @@ }, "packages/plugins": { "name": "@wordpress/plugins", - "version": "7.9.0", + "version": "7.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56023,7 +56023,7 @@ }, "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", - "version": "5.9.0", + "version": "5.10.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -56040,7 +56040,7 @@ }, "packages/postcss-themes": { "name": "@wordpress/postcss-themes", - "version": "6.9.0", + "version": "6.10.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -56053,7 +56053,7 @@ }, "packages/preferences": { "name": "@wordpress/preferences", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56079,7 +56079,7 @@ }, "packages/preferences-persistence": { "name": "@wordpress/preferences-persistence", - "version": "2.9.0", + "version": "2.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56092,7 +56092,7 @@ }, "packages/prettier-config": { "name": "@wordpress/prettier-config", - "version": "4.9.0", + "version": "4.10.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -56105,7 +56105,7 @@ }, "packages/primitives": { "name": "@wordpress/primitives", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56122,7 +56122,7 @@ }, "packages/priority-queue": { "name": "@wordpress/priority-queue", - "version": "3.9.0", + "version": "3.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56135,7 +56135,7 @@ }, "packages/private-apis": { "name": "@wordpress/private-apis", - "version": "1.9.0", + "version": "1.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -56147,7 +56147,7 @@ }, "packages/project-management-automation": { "name": "@wordpress/project-management-automation", - "version": "2.9.0", + "version": "2.10.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -56177,7 +56177,7 @@ }, "packages/react-i18n": { "name": "@wordpress/react-i18n", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56333,7 +56333,7 @@ }, "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.9.0", + "version": "3.10.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -56346,7 +56346,7 @@ }, "packages/redux-routine": { "name": "@wordpress/redux-routine", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56391,7 +56391,7 @@ }, "packages/reusable-blocks": { "name": "@wordpress/reusable-blocks", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56418,7 +56418,7 @@ }, "packages/rich-text": { "name": "@wordpress/rich-text", - "version": "7.9.0", + "version": "7.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56442,7 +56442,7 @@ }, "packages/router": { "name": "@wordpress/router", - "version": "1.9.0", + "version": "1.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56461,7 +56461,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "30.1.0", + "version": "30.2.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -56917,7 +56917,7 @@ }, "packages/server-side-render": { "name": "@wordpress/server-side-render", - "version": "5.9.0", + "version": "5.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56943,7 +56943,7 @@ }, "packages/shortcode": { "name": "@wordpress/shortcode", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56956,7 +56956,7 @@ }, "packages/style-engine": { "name": "@wordpress/style-engine", - "version": "2.9.0", + "version": "2.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56969,7 +56969,7 @@ }, "packages/stylelint-config": { "name": "@wordpress/stylelint-config", - "version": "23.1.0", + "version": "23.2.0", "dev": true, "license": "MIT", "dependencies": { @@ -57088,7 +57088,7 @@ }, "packages/sync": { "name": "@wordpress/sync", - "version": "1.9.0", + "version": "1.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -57109,7 +57109,7 @@ }, "packages/token-list": { "name": "@wordpress/token-list", - "version": "3.9.0", + "version": "3.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -57121,7 +57121,7 @@ }, "packages/undo-manager": { "name": "@wordpress/undo-manager", - "version": "1.9.0", + "version": "1.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -57134,7 +57134,7 @@ }, "packages/url": { "name": "@wordpress/url", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -57147,7 +57147,7 @@ }, "packages/viewport": { "name": "@wordpress/viewport", - "version": "6.9.0", + "version": "6.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -57165,7 +57165,7 @@ }, "packages/warning": { "name": "@wordpress/warning", - "version": "3.9.0", + "version": "3.10.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -57174,7 +57174,7 @@ }, "packages/widgets": { "name": "@wordpress/widgets", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -57202,7 +57202,7 @@ }, "packages/wordcount": { "name": "@wordpress/wordcount", - "version": "4.9.0", + "version": "4.10.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 2c0696f5f1c579..230005587619f3 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/package.json b/packages/annotations/package.json index d18b5774086c25..259745c3fd82e2 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.10.0-prerelease", + "version": "3.10.0", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 184c23484f40c6..35fb2da0ec1aad 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.10.0-prerelease", + "version": "7.10.0", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/package.json b/packages/autop/package.json index a865bc7bb6f495..9e2b61ad211cff 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index 17c59b76f2322a..be9dbe0b0fe099 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index 8e3601df87b9a2..f88a5257b24c8f 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.10.0-prerelease", + "version": "6.10.0", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 349872c0a8f694..fb8ae826e55978 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.10.0-prerelease", + "version": "8.10.0", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index 06dab95e0117d1..04d1bb5e2d41ba 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/package.json b/packages/blob/package.json index 12d2c31bc7ff73..087343d1b33a04 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 5a0b4404d166dd..0b72a7ff2099a1 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index f0329208460627..92392b4d9563b2 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.5.0-prerelease", + "version": "14.5.0", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/package.json b/packages/block-library/package.json index d75405ab1b2f10..e9e76b8018e1d3 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.10.0-prerelease", + "version": "9.10.0", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 7219772247e51e..3b159dc3534888 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 266eb6ac3d4829..49c3ed6c872c73 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/package.json b/packages/blocks/package.json index c5053535b754ef..9b7665ae9c87d6 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.10.0-prerelease", + "version": "13.10.0", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index bfc521698e2943..8b19151e950475 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.10.0-prerelease", + "version": "6.10.0", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/package.json b/packages/commands/package.json index 1275d5ff029bfa..e1529416aa7df7 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.10.0-prerelease", + "version": "1.10.0", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/package.json b/packages/components/package.json index 0a83b70516552a..16c7b6c63c0b18 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.10.0-prerelease", + "version": "28.10.0", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/package.json b/packages/compose/package.json index 39a502ccf8be9e..d1eacfd72f0d86 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.10.0-prerelease", + "version": "7.10.0", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 6d09c6a4955fe3..87dc4fb3722f50 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.10.0-prerelease", + "version": "1.10.0", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 533a32f179ccfb..cd568cc60c596b 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.10.0-prerelease", + "version": "7.10.0", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index e9466dc53b4b25..d400d77a49ab67 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.10.0-prerelease", + "version": "2.10.0", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index 853e4c7f1b71b4..42ae74d8eeeb90 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 4aca8901057687..06556dbfaaa342 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.53.0-prerelease", + "version": "4.53.0", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 9784c481faaed6..15cf61c352af8f 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 3e039eaad25ba6..2820445254f0f4 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/package.json b/packages/data/package.json index efb7974025b199..b3adf78a2f3932 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.10.0-prerelease", + "version": "10.10.0", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index 9054b9ff1a54a4..d95e079033c3b6 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.6.0-prerelease", + "version": "4.6.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/package.json b/packages/date/package.json index 12cfb79059e129..2710aeb0437be8 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index bdc23a609cd219..f1b3c0f87bdb9b 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.10.0-prerelease", + "version": "6.10.0", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 156aa74700d9a4..c44b7052c1c545 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 87aec3445c18cd..e7d7447226ce4e 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.10.0-prerelease", + "version": "2.10.0", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index a8a897c6392726..62cbf25ae12e86 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/package.json b/packages/dom/package.json index c55090419733d3..9028598f160785 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 6009721ced92f6..353d19decb8f8a 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.10.0-prerelease", + "version": "1.10.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index 234510d5827e7b..b328245162fef1 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.10.0-prerelease", + "version": "11.10.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 04ba6af0569d20..03f98a8289da4f 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.10.0-prerelease", + "version": "8.10.0", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 0bf146900b5865..e2653a2dab9736 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.10.0-prerelease", + "version": "8.10.0", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index fabb7ecf1f7053..e187acbb1b653f 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.10.0-prerelease", + "version": "6.10.0", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index a523241c9f7957..cc2b97ac809d01 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.10.0-prerelease", + "version": "6.10.0", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/package.json b/packages/editor/package.json index 68cfe76a24dabc..7568d0d6b8470f 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.10.0-prerelease", + "version": "14.10.0", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/package.json b/packages/element/package.json index f6892e7d6dfffb..7efc62530eadb9 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.10.0-prerelease", + "version": "6.10.0", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/package.json b/packages/env/package.json index 28d09038cfdf0e..f35dfa784fcc32 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.10.0-prerelease", + "version": "10.10.0", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 5bf91cc101929c..bc72f326e70b19 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.10.0-prerelease", + "version": "3.10.0", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index c79db5771b335e..5605f343ef5fd9 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "21.3.0-prerelease", + "version": "21.3.0", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/fields/package.json b/packages/fields/package.json index b6f534fdf09898..1f470e6ecba64c 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/fields", - "version": "0.2.0-prerelease", + "version": "0.2.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/package.json b/packages/format-library/package.json index 61a3431db17d90..636552b7408a8c 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 24020339807958..8f8674d0fd4c22 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index c4fe9b3874caf2..4079728d6ae085 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 27288530873b7b..51950104c52e4a 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/package.json b/packages/icons/package.json index 61740ce6e9f0f3..28dedd381de029 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.10.0-prerelease", + "version": "10.10.0", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index ec875f3c4d9996..bb482450699027 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.10.0-prerelease", + "version": "2.10.0", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index ea0d90516decf7..defabf4f76a6ad 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.10.0-prerelease", + "version": "6.10.0", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/package.json b/packages/interface/package.json index 22d6b017908604..964960afc2e1b9 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "7.0.0-prerelease", + "version": "7.0.0", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 5d66f218718737..617f0415935d88 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index f4c7d04aa6bc37..373fc612b598b7 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.10.0-prerelease", + "version": "8.10.0", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index bc4a422753cfbe..953e923dda253b 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.10.0-prerelease", + "version": "12.10.0", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 2dde7854bb300e..0e9b214a175772 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.10.0-prerelease", + "version": "7.10.0", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index a10fe0a48a7689..7ef7599e296566 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 821fbd25c9e492..8ec0c6278595cf 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index 3d844311b9f8ad..1e56c1703cf1c6 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.10.0-prerelease", + "version": "2.10.0", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 768ae065967a57..8ee807dd4404f0 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 5cd6eeb3f5ea80..67adfe9673db28 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/package.json b/packages/notices/package.json index 8d472d6c20b329..798965e93b25ce 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index 435ad98cb6a11a..04fbb5ccc0aea0 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/package.json b/packages/nux/package.json index b11370d3e1e64b..b6b6695b5b1058 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.10.0-prerelease", + "version": "9.10.0", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/package.json b/packages/patterns/package.json index fd32c4dd50975c..6d1dc87554bc36 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.10.0-prerelease", + "version": "2.10.0", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/package.json b/packages/plugins/package.json index d923aed8797884..0fc38303213f25 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.10.0-prerelease", + "version": "7.10.0", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 852ff6949a4c44..e5c1e2ab1629ec 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index 568eeb09e48e61..436c606cf9d1dd 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.10.0-prerelease", + "version": "6.10.0", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index 83bf47d5765852..cd2d86b61264eb 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.10.0-prerelease", + "version": "2.10.0", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/package.json b/packages/preferences/package.json index e8da2489192ef5..8dc6b2f919a20c 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index e27118ca3d3016..f46706b09082bd 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/package.json b/packages/primitives/package.json index f37b0c986f37ed..b81a5049d05b5e 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index c14217d3100862..0e0dde33cc39a0 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.10.0-prerelease", + "version": "3.10.0", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index 927e53ec3e862e..a76fff0de91f5f 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.10.0-prerelease", + "version": "1.10.0", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index d984238dfdd561..6da7e21d76fb0f 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.10.0-prerelease", + "version": "2.10.0", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index edad4a16e22fe0..77dc00b1b8e273 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index 3562e61cd4db9b..4f7a42a8e59ea7 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.10.0-prerelease", + "version": "3.10.0", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 321baa697446e5..46dffc7e069e19 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 605ea09f46ee29..483ecceeb9e252 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 8b9e32d128c797..a4a15743a13ed5 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.10.0-prerelease", + "version": "7.10.0", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/package.json b/packages/router/package.json index eed2e44e7e65f6..a7a181fbde9705 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.10.0-prerelease", + "version": "1.10.0", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 0a20c6b006b192..07cb9799275db5 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.2.0-prerelease", + "version": "30.2.0", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index f16912063e1f52..b91da1f10127b4 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.10.0-prerelease", + "version": "5.10.0", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index c69671cc7b20d4..7b0b965df6d926 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 9256dc95dd4e24..670861a7ca8c97 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.10.0-prerelease", + "version": "2.10.0", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 3c6031d16db2a1..5c213a88519497 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "23.2.0-prerelease", + "version": "23.2.0", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/package.json b/packages/sync/package.json index bd16c61453f1f5..1e79d4673b47dd 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.10.0-prerelease", + "version": "1.10.0", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 194766faecadc4..c4fdfde1af6d01 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.10.0-prerelease", + "version": "3.10.0", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index c2e38681c26acc..3a7c61dc620ec4 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.10.0-prerelease", + "version": "1.10.0", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/package.json b/packages/url/package.json index 50bbe8c2f560e8..9631694dc5e2b1 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 97e0fef884ad0e..c5e46e4700e96b 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.10.0-prerelease", + "version": "6.10.0", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/package.json b/packages/warning/package.json index d8ec34abd1bcef..4191f7f1e38a06 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.10.0-prerelease", + "version": "3.10.0", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 66dffa6804200b..9fdf32172eb723 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index 311a5320e8f997..5ad2fd1908d727 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.10.0-prerelease", + "version": "4.10.0", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 1f528ccbd0102ac3090aaceaf2015c48c13bfcf5 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Wed, 16 Oct 2024 12:39:12 -0500 Subject: [PATCH 1202/1908] Fix scaling animation for device previews (#66132) Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> --- packages/base-styles/_animations.scss | 5 +++++ .../src/components/block-canvas/style.scss | 2 ++ .../block-editor/src/components/iframe/content.scss | 10 +++------- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/base-styles/_animations.scss b/packages/base-styles/_animations.scss index e5bbf863757356..ae5de9a803008c 100644 --- a/packages/base-styles/_animations.scss +++ b/packages/base-styles/_animations.scss @@ -41,3 +41,8 @@ @warn "The `edit-post__fade-in-animation` mixin is deprecated. Use `animation__fade-in` instead."; @include animation__fade-in($speed, $delay); } + +@mixin editor-canvas-resize-animation($additional-transition-rules...) { + transition: all 400ms cubic-bezier(0.46, 0.03, 0.52, 0.96), $additional-transition-rules; + @include reduce-motion("transition"); +} diff --git a/packages/block-editor/src/components/block-canvas/style.scss b/packages/block-editor/src/components/block-canvas/style.scss index 9e924cb79bace1..0b37b4dd1447e2 100644 --- a/packages/block-editor/src/components/block-canvas/style.scss +++ b/packages/block-editor/src/components/block-canvas/style.scss @@ -4,4 +4,6 @@ iframe[name="editor-canvas"] { height: 100%; display: block; background-color: transparent; + // Handles transitions between device previews + @include editor-canvas-resize-animation; } diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss index 4a0e2d519f914b..d33ed7818aa2a8 100644 --- a/packages/block-editor/src/components/iframe/content.scss +++ b/packages/block-editor/src/components/iframe/content.scss @@ -5,20 +5,16 @@ .block-editor-iframe__html { transform-origin: top center; - // 400ms should match the animation speed used in iframe/index.js - $zoomOutAnimation: all 400ms cubic-bezier(0.46, 0.03, 0.52, 0.96); - // We don't want to animate the transform of the translateX because it is used // to "center" the canvas. Leaving it on causes the canvas to slide around in // odd ways. - transition: $zoomOutAnimation, transform 0s scale 0s; - @include reduce-motion("transition"); + @include editor-canvas-resize-animation(transform 0s, scale 0s, padding 0s); &.zoom-out-animation { // we only want to animate the scaling when entering zoom out. When sidebars // are toggled, the resizing of the iframe handles scaling the canvas as well, // and the doubled animations cause very odd animations. - transition: $zoomOutAnimation, transform 0s; + @include editor-canvas-resize-animation(transform 0s); } } @@ -30,7 +26,7 @@ $outer-container-width: var(--wp-block-editor-iframe-zoom-out-outer-container-width); $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw); // Apply an X translation to center the scaled content within the available space. - transform: translateX(calc(( #{$outer-container-width} - #{ $container-width }) / 2 / #{$scale})); + transform: translateX(calc((#{$outer-container-width} - #{$container-width}) / 2 / #{$scale})); scale: #{$scale}; background-color: $gray-300; From 2177aed35b2adfe18ce557f41d4d121752fa5314 Mon Sep 17 00:00:00 2001 From: Shah Shalin <56588503+SH4LIN@users.noreply.github.com> Date: Thu, 17 Oct 2024 00:56:12 +0530 Subject: [PATCH 1203/1908] Fix error when using circlular parent blocks (#66121) Co-authored-by: SH4LIN <sh4lin@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: yuliyan <yuliyan@git.wordpress.org> --- packages/block-editor/src/store/selectors.js | 22 ++++++++++++++++++-- packages/blocks/src/api/registration.js | 9 ++++++++ packages/blocks/src/api/test/registration.js | 11 ++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 2bfc52118d7ace..57e48442b1070b 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -1552,12 +1552,18 @@ export function getTemplateLock( state, rootClientId ) { * @param {string|Object} blockNameOrType The block type object, e.g., the response * from the block directory; or a string name of * an installed block type, e.g.' core/paragraph'. + * @param {Set} checkedBlocks Set of block names that have already been checked. * * @return {boolean} Whether the given block type is allowed to be inserted. */ -const isBlockVisibleInTheInserter = ( state, blockNameOrType ) => { +const isBlockVisibleInTheInserter = ( + state, + blockNameOrType, + checkedBlocks = new Set() +) => { let blockType; let blockName; + if ( blockNameOrType && 'object' === typeof blockNameOrType ) { blockType = blockNameOrType; blockName = blockNameOrType.name; @@ -1565,6 +1571,7 @@ const isBlockVisibleInTheInserter = ( state, blockNameOrType ) => { blockType = getBlockType( blockNameOrType ); blockName = blockNameOrType; } + if ( ! blockType ) { return false; } @@ -1580,11 +1587,22 @@ const isBlockVisibleInTheInserter = ( state, blockNameOrType ) => { return false; } + if ( checkedBlocks.has( blockName ) ) { + return false; + } + + checkedBlocks.add( blockName ); + // If parent blocks are not visible, child blocks should be hidden too. if ( !! blockType.parent?.length ) { return blockType.parent.some( ( name ) => - isBlockVisibleInTheInserter( state, name ) || + ( blockName !== name && + isBlockVisibleInTheInserter( + state, + name, + checkedBlocks + ) ) || // Exception for blocks with post-content parent, // the root level is often consider as "core/post-content". // This exception should only apply to the post editor ideally though. diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 2f4bab2b5f2589..ef1b6bd20a4cdd 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -232,6 +232,15 @@ export function registerBlockType( blockNameOrMetadata, settings ) { return; } + if ( 1 === settings?.parent?.length && name === settings.parent[ 0 ] ) { + warning( + 'Block "' + + name + + '" cannot be a parent of itself. Please remove the block name from the parent list.' + ); + return; + } + if ( ! /^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/.test( name ) ) { warning( 'Block names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-block' diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index 73f310bbf04dc7..656e9471a541b8 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -104,6 +104,17 @@ describe( 'blocks', () => { expect( block ).toBeUndefined(); } ); + it( 'Should reject blocks with the block name itself as the only parent attribute value', () => { + const block = registerBlockType( 'core/test-block', { + ...defaultBlockSettings, + parent: [ 'core/test-block' ], + } ); + expect( console ).toHaveWarnedWith( + 'Block "core/test-block" cannot be a parent of itself. Please remove the block name from the parent list.' + ); + expect( block ).toBeUndefined(); + } ); + it( 'should reject blocks with uppercase characters', () => { const block = registerBlockType( 'Core/Paragraph' ); expect( console ).toHaveWarnedWith( From 346fd4cc8ef5996a8b4434a9cd1f4ade8ed96ff4 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Wed, 16 Oct 2024 16:49:00 -0500 Subject: [PATCH 1204/1908] Fix/html scale code quality (#66181) Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> --- .../src/components/iframe/content.scss | 4 +- .../src/components/iframe/index.js | 57 +++++++++---------- .../src/components/iframe/style.scss | 4 +- 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss index d33ed7818aa2a8..1d01f84b5fd1fd 100644 --- a/packages/block-editor/src/components/iframe/content.scss +++ b/packages/block-editor/src/components/iframe/content.scss @@ -23,10 +23,10 @@ $frame-size: var(--wp-block-editor-iframe-zoom-out-frame-size); $inner-height: var(--wp-block-editor-iframe-zoom-out-inner-height); $content-height: var(--wp-block-editor-iframe-zoom-out-content-height); - $outer-container-width: var(--wp-block-editor-iframe-zoom-out-outer-container-width); + $scale-container-width: var(--wp-block-editor-iframe-zoom-out-scale-container-width); $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw); // Apply an X translation to center the scaled content within the available space. - transform: translateX(calc((#{$outer-container-width} - #{$container-width}) / 2 / #{$scale})); + transform: translateX(calc((#{$scale-container-width} - #{$container-width}) / 2 / #{$scale})); scale: #{$scale}; background-color: $gray-300; diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index b72d86ef8e0f8f..b14514f934fb3e 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -122,7 +122,7 @@ function Iframe( { }, [] ); const { styles = '', scripts = '' } = resolvedAssets; const [ iframeDocument, setIframeDocument ] = useState(); - const initialContainerWidth = useRef(); + const initialContainerWidth = useRef( 0 ); const [ bodyClasses, setBodyClasses ] = useState( [] ); const clearerRef = useBlockSelectionClearer(); const [ before, writingFlowRef, after ] = useWritingFlow(); @@ -247,6 +247,11 @@ function Iframe( { } }, [ containerWidth, isZoomedOut ] ); + const scaleContainerWidth = Math.max( + initialContainerWidth.current, + containerWidth + ); + const disabledRef = useDisabled( { isDisabled: ! readonly } ); const bodyRef = useMergeRefs( [ useBubbleEvents( iframeDocument ), @@ -299,17 +304,6 @@ function Iframe( { useEffect( () => cleanup, [ cleanup ] ); const zoomOutAnimationClassnameRef = useRef( null ); - const handleZoomOutAnimationClassname = () => { - clearTimeout( zoomOutAnimationClassnameRef.current ); - - iframeDocument.documentElement.classList.add( 'zoom-out-animation' ); - - zoomOutAnimationClassnameRef.current = setTimeout( () => { - iframeDocument.documentElement.classList.remove( - 'zoom-out-animation' - ); - }, 400 ); // 400ms should match the animation speed used in components/iframe/content.scss - }; // Toggle zoom out CSS Classes only when zoom out mode changes. We could add these into the useEffect // that controls settings the CSS variables, but then we would need to do more work to ensure we're @@ -320,6 +314,20 @@ function Iframe( { return; } + const handleZoomOutAnimationClassname = () => { + clearTimeout( zoomOutAnimationClassnameRef.current ); + + iframeDocument.documentElement.classList.add( + 'zoom-out-animation' + ); + + zoomOutAnimationClassnameRef.current = setTimeout( () => { + iframeDocument.documentElement.classList.remove( + 'zoom-out-animation' + ); + }, 400 ); // 400ms should match the animation speed used in components/iframe/content.scss + }; + handleZoomOutAnimationClassname(); iframeDocument.documentElement.classList.add( 'is-zoomed-out' ); @@ -349,10 +357,7 @@ function Iframe( { scale === 'default' ? ( Math.min( containerWidth, maxWidth ) - parseInt( frameSize ) * 2 ) / - Math.max( - initialContainerWidth.current, - containerWidth - ) + scaleContainerWidth : scale ); @@ -374,15 +379,10 @@ function Iframe( { `${ containerWidth }px` ); iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-outer-container-width', - `${ Math.max( initialContainerWidth.current, containerWidth ) }px` + '--wp-block-editor-iframe-zoom-out-scale-container-width', + `${ scaleContainerWidth }px` ); - // iframeDocument.documentElement.style.setProperty( - // '--wp-block-editor-iframe-zoom-out-outer-container-width', - // `${ Math.max( initialContainerWidth.current, containerWidth ) }px` - // ); - return () => { iframeDocument.documentElement.style.removeProperty( '--wp-block-editor-iframe-zoom-out-scale' @@ -400,7 +400,7 @@ function Iframe( { '--wp-block-editor-iframe-zoom-out-container-width' ); iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-outer-container-width' + '--wp-block-editor-iframe-zoom-out-scale-container-width' ); }; }, [ @@ -412,6 +412,7 @@ function Iframe( { containerWidth, windowInnerWidth, isZoomedOut, + scaleContainerWidth, ] ); // Make sure to not render the before and after focusable div elements in view @@ -501,12 +502,8 @@ function Iframe( { isZoomedOut && 'is-zoomed-out' ) } style={ { - '--wp-block-editor-iframe-zoom-out-outer-container-width': - isZoomedOut && - `${ Math.max( - initialContainerWidth.current, - containerWidth - ) }px`, + '--wp-block-editor-iframe-zoom-out-scale-container-width': + isZoomedOut && `${ scaleContainerWidth }px`, } } > { iframe } diff --git a/packages/block-editor/src/components/iframe/style.scss b/packages/block-editor/src/components/iframe/style.scss index d05be2f3977b9f..5dd30c338057e2 100644 --- a/packages/block-editor/src/components/iframe/style.scss +++ b/packages/block-editor/src/components/iframe/style.scss @@ -9,8 +9,8 @@ } .block-editor-iframe__scale-container.is-zoomed-out { - $outer-container-width: var(--wp-block-editor-iframe-zoom-out-outer-container-width, 100vw); - width: $outer-container-width; + $scale-container-width: var(--wp-block-editor-iframe-zoom-out-scale-container-width, 100vw); + width: $scale-container-width; // Position the iframe so that it is always aligned with the right side so that // the scrollbar is always visible on the right side position: absolute; From 0decb96f74ca03cddb64f0ccb40f2067f43626bd Mon Sep 17 00:00:00 2001 From: Matt <146485480+mattrwalker@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:55:43 -0400 Subject: [PATCH 1205/1908] Adds categories to Storybooks navigation (#66072) Co-authored-by: mattrwalker <mattryanwalker@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: auareyou <auareyou@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/components/src/button/stories/index.story.tsx | 3 ++- packages/components/src/card/stories/index.story.tsx | 3 ++- .../navigable-container/stories/navigable-menu.story.tsx | 3 ++- .../stories/tabbable-container.story.tsx | 3 ++- packages/components/src/panel/stories/index.story.tsx | 3 ++- packages/components/src/tab-panel/stories/index.story.tsx | 3 ++- packages/components/src/tabs/stories/index.story.tsx | 3 ++- storybook/manager-head.html | 1 + storybook/preview.js | 6 ++++++ 9 files changed, 21 insertions(+), 7 deletions(-) diff --git a/packages/components/src/button/stories/index.story.tsx b/packages/components/src/button/stories/index.story.tsx index 2981319cfb3233..808914893de610 100644 --- a/packages/components/src/button/stories/index.story.tsx +++ b/packages/components/src/button/stories/index.story.tsx @@ -22,7 +22,8 @@ import './style.css'; import Button from '..'; const meta: Meta< typeof Button > = { - title: 'Components/Button', + title: 'Components/Actions/Button', + id: 'components-button', component: Button, argTypes: { // Overrides a limitation of the docgen interpreting our TS types for this as required. diff --git a/packages/components/src/card/stories/index.story.tsx b/packages/components/src/card/stories/index.story.tsx index 1d75c044f1e270..03726abbe754ee 100644 --- a/packages/components/src/card/stories/index.story.tsx +++ b/packages/components/src/card/stories/index.story.tsx @@ -22,7 +22,8 @@ const meta: Meta< typeof Card > = { component: Card, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { CardHeader, CardBody, CardDivider, CardMedia, CardFooter }, - title: 'Components/Card', + title: 'Components/Containers/Card', + id: 'components-card', argTypes: { as: { control: { type: null }, diff --git a/packages/components/src/navigable-container/stories/navigable-menu.story.tsx b/packages/components/src/navigable-container/stories/navigable-menu.story.tsx index 9e5f3eedff5289..2ad7e028d6faf1 100644 --- a/packages/components/src/navigable-container/stories/navigable-menu.story.tsx +++ b/packages/components/src/navigable-container/stories/navigable-menu.story.tsx @@ -9,7 +9,8 @@ import type { Meta, StoryFn } from '@storybook/react'; import { NavigableMenu } from '..'; const meta: Meta< typeof NavigableMenu > = { - title: 'Components/NavigableMenu', + title: 'Components/Containers/NavigableMenu', + id: 'components-navigablemenu', component: NavigableMenu, argTypes: { children: { control: { type: null } }, diff --git a/packages/components/src/navigable-container/stories/tabbable-container.story.tsx b/packages/components/src/navigable-container/stories/tabbable-container.story.tsx index 3dd090f0b05859..07c87a0c20f1bf 100644 --- a/packages/components/src/navigable-container/stories/tabbable-container.story.tsx +++ b/packages/components/src/navigable-container/stories/tabbable-container.story.tsx @@ -9,7 +9,8 @@ import type { Meta, StoryFn } from '@storybook/react'; import { TabbableContainer } from '..'; const meta: Meta< typeof TabbableContainer > = { - title: 'Components/TabbableContainer', + title: 'Components/Containers/TabbableContainer', + id: 'components-tabbablecontainer', component: TabbableContainer, argTypes: { children: { control: { type: null } }, diff --git a/packages/components/src/panel/stories/index.story.tsx b/packages/components/src/panel/stories/index.story.tsx index 7f69f766603ebb..af9cf626f8eecd 100644 --- a/packages/components/src/panel/stories/index.story.tsx +++ b/packages/components/src/panel/stories/index.story.tsx @@ -17,7 +17,8 @@ import InputControl from '../../input-control'; import { wordpress } from '@wordpress/icons'; const meta: Meta< typeof Panel > = { - title: 'Components/Panel', + title: 'Components/Containers/Panel', + id: 'components-panel', component: Panel, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { PanelRow, PanelBody }, diff --git a/packages/components/src/tab-panel/stories/index.story.tsx b/packages/components/src/tab-panel/stories/index.story.tsx index e2f146d55865cb..57a3cc311f863c 100644 --- a/packages/components/src/tab-panel/stories/index.story.tsx +++ b/packages/components/src/tab-panel/stories/index.story.tsx @@ -14,7 +14,8 @@ import { link, more, wordpress } from '@wordpress/icons'; import TabPanel from '..'; const meta: Meta< typeof TabPanel > = { - title: 'Components/TabPanel', + title: 'Components/Containers/TabPanel', + id: 'components-tabpanel', component: TabPanel, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/tabs/stories/index.story.tsx b/packages/components/src/tabs/stories/index.story.tsx index 0f7e0d2c6ac75f..5141a48a899502 100644 --- a/packages/components/src/tabs/stories/index.story.tsx +++ b/packages/components/src/tabs/stories/index.story.tsx @@ -20,7 +20,8 @@ import Tooltip from '../../tooltip'; import Icon from '../../icon'; const meta: Meta< typeof Tabs > = { - title: 'Components (Experimental)/Tabs', + title: 'Components/Containers/Tabs', + id: 'components-tabs', component: Tabs, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 diff --git a/storybook/manager-head.html b/storybook/manager-head.html index dcafe36caefa72..d3f156a6eb788b 100644 --- a/storybook/manager-head.html +++ b/storybook/manager-head.html @@ -10,6 +10,7 @@ 'navigation', 'navigator', 'progressbar', + 'tabs', 'theme', ]; const REDIRECTS = [ diff --git a/storybook/preview.js b/storybook/preview.js index a426faa41c2d71..97be7205349100 100644 --- a/storybook/preview.js +++ b/storybook/preview.js @@ -127,6 +127,12 @@ export const parameters = { 'Playground', 'BlockEditor', 'Components', + [ + 'Introduction', + 'Contributing Guidelines', + 'Actions', + 'Containers', + ], 'Components (Experimental)', 'Icons', ], From 1bb27791da0c61b7528fe7fbf754a828178cf03b Mon Sep 17 00:00:00 2001 From: Renatho De Carli Rosa <renatho@gmail.com> Date: Thu, 17 Oct 2024 00:33:08 -0300 Subject: [PATCH 1206/1908] Fix the navigation issue inside cover blocks (#66093) Co-authored-by: renatho <renathoc@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- packages/block-library/src/cover/style.scss | 6 ++ .../src/navigation/edit/index.js | 33 ++++++++- test/e2e/specs/editor/blocks/cover.spec.js | 71 +++++++++++++++++++ 3 files changed, 107 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/cover/style.scss b/packages/block-library/src/cover/style.scss index 41b3acf1833fc0..b2c1fe88440235 100644 --- a/packages/block-library/src/cover/style.scss +++ b/packages/block-library/src/cover/style.scss @@ -100,6 +100,12 @@ color: inherit; // Reset the fixed LTR direction at the root of the block in RTL languages. /*rtl:raw: direction: rtl; */ + + // Reset the z-index to auto when the body has a modal open. So when the + // modal is inside the cover, it doesn't create a stacking context. + @at-root .has-modal-open & { + z-index: auto; + } } // Position: Top diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js index ae7dd60bd0c5ba..d961f0d8fc93b9 100644 --- a/packages/block-library/src/navigation/edit/index.js +++ b/packages/block-library/src/navigation/edit/index.js @@ -73,6 +73,33 @@ import AccessibleDescription from './accessible-description'; import AccessibleMenuDescription from './accessible-menu-description'; import { unlock } from '../../lock-unlock'; +function useResponsiveMenu( navRef ) { + const [ isResponsiveMenuOpen, setResponsiveMenuVisibility ] = + useState( false ); + + useEffect( () => { + if ( ! navRef.current ) { + return; + } + + const htmlElement = navRef.current.ownerDocument.documentElement; + + // Add a `has-modal-open` class to the <html> when the responsive + // menu is open. This reproduces the same behavior of the frontend. + if ( isResponsiveMenuOpen ) { + htmlElement.classList.add( 'has-modal-open' ); + } else { + htmlElement.classList.remove( 'has-modal-open' ); + } + + return () => { + htmlElement?.classList.remove( 'has-modal-open' ); + }; + }, [ navRef, isResponsiveMenuOpen ] ); + + return [ isResponsiveMenuOpen, setResponsiveMenuVisibility ]; +} + function ColorTools( { textColor, setTextColor, @@ -284,8 +311,10 @@ function Navigation( { __unstableMarkNextChangeAsNotPersistent, } = useDispatch( blockEditorStore ); + const navRef = useRef(); + const [ isResponsiveMenuOpen, setResponsiveMenuVisibility ] = - useState( false ); + useResponsiveMenu( navRef ); const [ overlayMenuPreview, setOverlayMenuPreview ] = useState( false ); @@ -367,8 +396,6 @@ function Navigation( { __unstableMarkNextChangeAsNotPersistent, ] ); - const navRef = useRef(); - // The standard HTML5 tag for the block wrapper. const TagName = 'nav'; diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index cf3005c9eaa18f..a9a93caa4f4341 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -226,6 +226,77 @@ test.describe( 'Cover', () => { await expect( overlay ).toHaveCSS( 'background-color', 'rgb(0, 0, 0)' ); await expect( overlay ).toHaveCSS( 'opacity', '0.5' ); } ); + + test( 'other cover blocks are not over the navigation block when the menu is open', async ( { + editor, + page, + } ) => { + // Insert a Cover block + await editor.insertBlock( { name: 'core/cover' } ); + const coverBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Cover', + } ); + + // Choose a color swatch to transform the placeholder block into + // a functioning block. + await coverBlock + .getByRole( 'option', { + name: 'Color: Black', + } ) + .click(); + + // Insert a Navigation block inside the Cover block + await editor.selectBlocks( coverBlock ); + await coverBlock.getByRole( 'button', { name: 'Add block' } ).click(); + await page.keyboard.type( 'Navigation' ); + const blockResults = page.getByRole( 'listbox', { + name: 'Blocks', + } ); + const blockResultOptions = blockResults.getByRole( 'option' ); + await blockResultOptions.nth( 0 ).click(); + + // Insert a second Cover block. + await editor.insertBlock( { name: 'core/cover' } ); + const secondCoverBlock = editor.canvas + .getByRole( 'document', { + name: 'Block: Cover', + } ) + .last(); + + // Choose a color swatch to transform the placeholder block into + // a functioning block. + await secondCoverBlock + .getByRole( 'option', { + name: 'Color: Black', + } ) + .click(); + + // Set the viewport to a small screen and open menu. + await page.setViewportSize( { width: 375, height: 1000 } ); + const navigationBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Navigation', + } ); + await editor.selectBlocks( navigationBlock ); + await editor.canvas + .getByRole( 'button', { name: 'Open menu' } ) + .click(); + + // Check if inner container of the second cover is clickable. + const secondInnerContainer = secondCoverBlock.locator( + '.wp-block-cover__inner-container' + ); + let isClickable; + try { + isClickable = await secondInnerContainer.click( { + trial: true, + timeout: 1000, // This test will always take 1 second to run. + } ); + } catch ( error ) { + isClickable = false; + } + + expect( isClickable ).toBe( false ); + } ); } ); class CoverBlockUtils { From 0d8bdb78722544da62ef9cfa3d65de5f26ad8c81 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Thu, 17 Oct 2024 09:42:44 +0200 Subject: [PATCH 1207/1908] Block Bindings: Use `getEntityConfig` instead of `getPostTypes` to get available slugs (#66101) * Add slug prop to postType entity config * Use `getEntitiesConfig` instead of `getPostTypes` * Only fetch postTypes in templates * Add `post.type` to `useSelect` dependencies * Use `name` instead of `slug` * Rename variable to `postTypeEntities` Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- .../editor/src/components/provider/index.js | 53 +++++++++++-------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 51b54979cb34aa..87fea30e31cdb9 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -164,40 +164,47 @@ export const ExperimentalEditorProvider = withRegistryProvider( BlockEditorProviderComponent = ExperimentalBlockEditorProvider, __unstableTemplate: template, } ) => { - const { editorSettings, selection, isReady, mode, postTypes } = - useSelect( ( select ) => { - const { - getEditorSettings, - getEditorSelection, - getRenderingMode, - __unstableIsEditorReady, - } = select( editorStore ); - const { getPostTypes } = select( coreStore ); + const { editorSettings, selection, isReady, mode, postTypeEntities } = + useSelect( + ( select ) => { + const { + getEditorSettings, + getEditorSelection, + getRenderingMode, + __unstableIsEditorReady, + } = select( editorStore ); + const { getEntitiesConfig } = select( coreStore ); - return { - editorSettings: getEditorSettings(), - isReady: __unstableIsEditorReady(), - mode: getRenderingMode(), - selection: getEditorSelection(), - postTypes: getPostTypes( { per_page: -1 } ), - }; - }, [] ); + return { + editorSettings: getEditorSettings(), + isReady: __unstableIsEditorReady(), + mode: getRenderingMode(), + selection: getEditorSelection(), + postTypeEntities: + post.type === 'wp_template' + ? getEntitiesConfig( 'postType' ) + : null, + }; + }, + [ post.type ] + ); const shouldRenderTemplate = !! template && mode !== 'post-only'; const rootLevelPost = shouldRenderTemplate ? template : post; const defaultBlockContext = useMemo( () => { const postContext = {}; - // If it is a template, try to inherit the post type from the slug. + // If it is a template, try to inherit the post type from the name. if ( post.type === 'wp_template' ) { if ( post.slug === 'page' ) { postContext.postType = 'page'; } else if ( post.slug === 'single' ) { postContext.postType = 'post'; } else if ( post.slug.split( '-' )[ 0 ] === 'single' ) { - // If the slug is single-{postType}, infer the post type from the slug. - const postTypesSlugs = - postTypes?.map( ( entity ) => entity.slug ) || []; + // If the slug is single-{postType}, infer the post type from the name. + const postTypeNames = + postTypeEntities?.map( ( entity ) => entity.name ) || + []; const match = post.slug.match( - `^single-(${ postTypesSlugs.join( '|' ) })(?:-.+)?$` + `^single-(${ postTypeNames.join( '|' ) })(?:-.+)?$` ); if ( match ) { postContext.postType = match[ 1 ]; @@ -225,7 +232,7 @@ export const ExperimentalEditorProvider = withRegistryProvider( post.slug, rootLevelPost.type, rootLevelPost.slug, - postTypes, + postTypeEntities, ] ); const { id, type } = rootLevelPost; const blockEditorSettings = useBlockEditorSettings( From 6fc539d8f94387f71ed847d2b6bba74c5e1c2ad8 Mon Sep 17 00:00:00 2001 From: Vrishabh Jasani <71686151+Vrishabhsk@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:42:56 +0400 Subject: [PATCH 1208/1908] Fix : "Set featured image" button border flashes on focus (#66092) * Enable smooth transition of box-shadow for feat. img. * Remove fallback style and remove transition Transition is removed to prevent a black border in between transitioning * Update changelog * Remove redundant style Co-authored-by: Vrishabhsk <vrishabhsk@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/editor/CHANGELOG.md | 4 ++++ .../editor/src/components/post-featured-image/style.scss | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index 2d72126f377d9d..2716d965d14343 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- `Post Featured Image`: Fix `Set featured image` button's `box-shadow` transition to prevent border from flashing when focused. + ## 14.10.0 (2024-10-16) ## 14.9.0 (2024-10-03) diff --git a/packages/editor/src/components/post-featured-image/style.scss b/packages/editor/src/components/post-featured-image/style.scss index a14c2ea73a63c1..30d5cb43403cdf 100644 --- a/packages/editor/src/components/post-featured-image/style.scss +++ b/packages/editor/src/components/post-featured-image/style.scss @@ -41,8 +41,6 @@ .editor-post-featured-image__preview { width: 100%; padding: 0; - transition: all 0.1s ease-out; - @include reduce-motion("transition"); box-shadow: 0 0 0 0 var(--wp-admin-theme-color); overflow: hidden; // Ensure the focus style properly encapsulates the image. outline-offset: -#{$border-width}; @@ -66,6 +64,11 @@ .editor-post-featured-image__toggle { box-shadow: inset 0 0 0 $border-width $gray-400; + + &:focus:not(:disabled) { + // Allow smooth transition between focused and unfocused box-shadow states. + box-shadow: 0 0 0 currentColor inset, 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + } } .editor-post-featured-image__actions { From 84976164a80867971e72028783391d17a003de7d Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:26:35 +0900 Subject: [PATCH 1209/1908] Navigation block: fix block appender size (#66153) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/block-library/src/navigation/editor.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/navigation/editor.scss b/packages/block-library/src/navigation/editor.scss index 1d37186e4ae98b..2f61a19be2b799 100644 --- a/packages/block-library/src/navigation/editor.scss +++ b/packages/block-library/src/navigation/editor.scss @@ -203,6 +203,7 @@ $color-control-label-height: 20px; .wp-block-navigation .wp-block + .block-list-appender .block-editor-button-block-appender { background-color: $gray-900; color: $white; + height: $button-size-small; // This needs specificity to override an inherited padding. // That source padding in turn has high specificity to protect From aef74c69cfe57afb5078886b01513d81739e22a7 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:35:49 +0900 Subject: [PATCH 1210/1908] ColorPalette: Prevent overflow of custom color button background (#66152) * ColorPalette: Prevent overflow of custom color button background * Update changelog * Use variable instead of hardcoded value * Update packages/components/src/color-palette/style.scss Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com> * Fix changelog entry --------- Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/color-palette/style.scss | 6 ++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index d1e75d9e0a3a88..f19e7f7eae7baa 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- `ColorPalette`: prevent overflow of custom color button background ([#66152](https://github.com/WordPress/gutenberg/pull/66152)). + ## 28.10.0 (2024-10-16) ### Bug Fixes diff --git a/packages/components/src/color-palette/style.scss b/packages/components/src/color-palette/style.scss index 9d922a8130692a..278aacb22914bb 100644 --- a/packages/components/src/color-palette/style.scss +++ b/packages/components/src/color-palette/style.scss @@ -26,10 +26,7 @@ $border-as-box-shadow: inset 0 0 0 $border-width rgba(0, 0, 0, 0.2); &::after { content: ""; position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; + inset: $border-width; z-index: -1; // The background image creates a checkerboard pattern. Ignore rtlcss to // make it work both in LTR and RTL. @@ -41,6 +38,7 @@ $border-as-box-shadow: inset 0 0 0 $border-width rgba(0, 0, 0, 0.2); background-position: 0 0, 24px 24px; /*rtl:end:ignore*/ background-size: calc(2 * 24px) calc(2 * 24px); + border-radius: $radius-medium - $border-width $radius-medium - $border-width 0 0; } } From f99eb38ad2eb7a7452ecfd2059274be59aaad289 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 17 Oct 2024 11:11:19 +0100 Subject: [PATCH 1211/1908] Zoom Out: Remove zoom-out toolbar (#66039) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../src/components/block-popover/index.js | 62 -------- .../src/components/block-toolbar/index.js | 17 ++- .../src/components/block-tools/index.js | 15 +- .../src/components/block-tools/style.scss | 20 --- .../block-tools/use-show-block-tools.js | 13 -- .../block-tools/zoom-out-mode-inserters.js | 65 ++++----- .../block-tools/zoom-out-popover.js | 47 ------ .../block-tools/zoom-out-toolbar.js | 135 ------------------ .../src/store/private-selectors.js | 3 +- 9 files changed, 44 insertions(+), 333 deletions(-) delete mode 100644 packages/block-editor/src/components/block-tools/zoom-out-popover.js delete mode 100644 packages/block-editor/src/components/block-tools/zoom-out-toolbar.js diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 637ab1cb8a53e0..f01c43ef26a71d 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -8,7 +8,6 @@ import clsx from 'clsx'; */ import { useMergeRefs } from '@wordpress/compose'; import { Popover } from '@wordpress/components'; -import { useSelect } from '@wordpress/data'; import { forwardRef, useMemo, @@ -22,8 +21,6 @@ import { import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; import usePopoverScroll from './use-popover-scroll'; import { rectUnion, getVisibleElementBounds } from '../../utils/dom'; -import { store as blockEditorStore } from '../../store'; -import { unlock } from '../../lock-unlock'; const MAX_POPOVER_RECOMPUTE_COUNTER = Number.MAX_SAFE_INTEGER; @@ -77,38 +74,12 @@ function BlockPopover( }; }, [ selectedElement ] ); - const { isZoomOut, parentSectionBlock, isSectionSelected } = useSelect( - ( select ) => { - const { - isZoomOut: isZoomOutSelector, - getSectionRootClientId, - getParentSectionBlock, - getBlockOrder, - } = unlock( select( blockEditorStore ) ); - - return { - isZoomOut: isZoomOutSelector(), - parentSectionBlock: - getParentSectionBlock( clientId ) ?? clientId, - isSectionSelected: getBlockOrder( - getSectionRootClientId() - ).includes( clientId ), - }; - }, - [ clientId ] - ); - - // This element is used to position the zoom out view vertical toolbar - // correctly, relative to the selected section. - const parentSectionElement = useBlockElement( parentSectionBlock ); - const popoverAnchor = useMemo( () => { if ( // popoverDimensionsRecomputeCounter is by definition always equal or greater // than 0. This check is only there to satisfy the correctness of the // exhaustive-deps rule for the `useMemo` hook. popoverDimensionsRecomputeCounter < 0 || - ( isZoomOut && ! parentSectionElement ) || ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) { @@ -117,35 +88,6 @@ function BlockPopover( return { getBoundingClientRect() { - // The zoom out view has a vertical block toolbar that should always - // be on the edge of the canvas, aligned to the top of the currently - // selected section. This condition changes the anchor of the toolbar - // to the section instead of the block to handle blocks that are - // not full width and nested blocks to keep section height. - if ( isZoomOut && isSectionSelected ) { - // Compute the height based on the parent section of the - // selected block, because the selected block may be - // shorter than the section. - const canvasElementRect = getVisibleElementBounds( - __unstableContentRef.current - ); - const parentSectionElementRect = - getVisibleElementBounds( parentSectionElement ); - const anchorHeight = - parentSectionElementRect.bottom - - parentSectionElementRect.top; - - // Always use the width of the section root element to make sure - // the toolbar is always on the edge of the canvas. - const anchorWidth = canvasElementRect.width; - return new window.DOMRectReadOnly( - canvasElementRect.left, - parentSectionElementRect.top, - anchorWidth, - anchorHeight - ); - } - return lastSelectedElement ? rectUnion( getVisibleElementBounds( selectedElement ), @@ -157,13 +99,9 @@ function BlockPopover( }; }, [ popoverDimensionsRecomputeCounter, - isZoomOut, - parentSectionElement, selectedElement, bottomClientId, lastSelectedElement, - isSectionSelected, - __unstableContentRef, ] ); if ( ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) { diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 2ac2cbb12ff352..d6a0985fef3610 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -16,7 +16,7 @@ import { isReusableBlock, isTemplatePart, } from '@wordpress/blocks'; -import { ToolbarGroup } from '@wordpress/components'; +import { ToolbarGroup, ToolbarButton } from '@wordpress/components'; /** * Internal dependencies @@ -35,6 +35,7 @@ import { store as blockEditorStore } from '../../store'; import __unstableBlockNameContext from './block-name-context'; import NavigableToolbar from '../navigable-toolbar'; import { useHasBlockToolbar } from './use-has-block-toolbar'; +import Shuffle from './shuffle'; import { unlock } from '../../lock-unlock'; /** @@ -67,6 +68,7 @@ export function PrivateBlockToolbar( { isUsingBindings, hasParentPattern, hasContentOnlyLocking, + showShuffleButton, } = useSelect( ( select ) => { const { getBlockName, @@ -79,6 +81,7 @@ export function PrivateBlockToolbar( { getBlockParentsByBlockName, getTemplateLock, getParentSectionBlock, + isZoomOutMode, } = unlock( select( blockEditorStore ) ); const selectedBlockClientIds = getSelectedBlockClientIds(); const selectedBlockClientId = selectedBlockClientIds[ 0 ]; @@ -119,6 +122,7 @@ export function PrivateBlockToolbar( { shouldShowVisualToolbar: isValid && isVisual, toolbarKey: `${ selectedBlockClientId }${ parentClientId }`, showParentSelector: + ! isZoomOutMode() && parentBlockType && getBlockEditingMode( parentClientId ) !== 'disabled' && hasBlockSupport( @@ -130,6 +134,7 @@ export function PrivateBlockToolbar( { isUsingBindings: _isUsingBindings, hasParentPattern: _hasParentPattern, hasContentOnlyLocking: _hasTemplateLock, + showShuffleButton: isZoomOutMode(), }; }, [] ); @@ -179,7 +184,7 @@ export function PrivateBlockToolbar( { key={ toolbarKey } > <div ref={ toolbarWrapperRef } className={ innerClasses }> - { ! isMultiToolbar && isLargeViewport && ( + { showParentSelector && ! isMultiToolbar && isLargeViewport && ( <BlockParentSelector /> ) } { ( shouldShowVisualToolbar || isMultiToolbar ) && @@ -205,6 +210,14 @@ export function PrivateBlockToolbar( { { ! hasContentOnlyLocking && shouldShowVisualToolbar && isMultiToolbar && <BlockGroupToolbar /> } + { showShuffleButton && ( + <ToolbarGroup> + <Shuffle + clientId={ blockClientIds[ 0 ] } + as={ ToolbarButton } + /> + </ToolbarGroup> + ) } { shouldShowVisualToolbar && ( <> <BlockControls.Slot diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index cbcb5b8e50b09a..e07e9b8f4bf5c1 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -19,7 +19,6 @@ import { default as InsertionPoint, } from './insertion-point'; import BlockToolbarPopover from './block-toolbar-popover'; -import ZoomOutPopover from './zoom-out-popover'; import { store as blockEditorStore } from '../../store'; import usePopoverScroll from '../block-popover/use-popover-scroll'; import ZoomOutModeInserters from './zoom-out-mode-inserters'; @@ -75,11 +74,8 @@ export default function BlockTools( { isGroupable, } = useSelect( blockEditorStore ); const { getGroupingBlockName } = useSelect( blocksStore ); - const { - showEmptyBlockSideInserter, - showBlockToolbarPopover, - showZoomOutToolbar, - } = useShowBlockTools(); + const { showEmptyBlockSideInserter, showBlockToolbarPopover } = + useShowBlockTools(); const { duplicateBlocks, @@ -211,13 +207,6 @@ export default function BlockTools( { /> ) } - { showZoomOutToolbar && ( - <ZoomOutPopover - __unstableContentRef={ __unstableContentRef } - clientId={ clientId } - /> - ) } - { /* Used for the inline rich text toolbar. Until this toolbar is combined into BlockToolbar, someone implementing their own BlockToolbar will also need to use this to see the image caption toolbar. */ } { ! isZoomOutMode && ! hasFixedToolbar && ( <Popover.Slot diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index bfb8b958f01ca6..0791dc909d5be4 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -187,23 +187,3 @@ top: 50%; left: 50%; } - -.zoom-out-toolbar { - - .block-editor-block-mover-button.block-editor-block-mover-button:focus-visible::before, - .zoom-out-toolbar-button:focus::before, - .block-editor-block-toolbar-shuffle:focus::before, - .block-selection-button_drag-handle:focus::before { - box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - } - - .block-editor-block-mover { - background: none; - border: none; - } - - // Make the spacing consistent between controls. - .zoom-out-toolbar-button { - height: $button-size-next-default-40px; - } -} diff --git a/packages/block-editor/src/components/block-tools/use-show-block-tools.js b/packages/block-editor/src/components/block-tools/use-show-block-tools.js index 97737b4ec2f5b4..61b5be891fd540 100644 --- a/packages/block-editor/src/components/block-tools/use-show-block-tools.js +++ b/packages/block-editor/src/components/block-tools/use-show-block-tools.js @@ -25,8 +25,6 @@ export function useShowBlockTools() { getSettings, __unstableGetEditorMode, isTyping, - getBlockOrder, - getSectionRootClientId, } = unlock( select( blockEditorStore ) ); const clientId = @@ -44,17 +42,7 @@ export function useShowBlockTools() { ! isTyping() && editorMode === 'edit' && isEmptyDefaultBlock; - const isZoomOut = editorMode === 'zoom-out'; - const isSectionSelected = getBlockOrder( - getSectionRootClientId() - ).includes( clientId ); - const _showZoomOutToolbar = - clientId && - isZoomOut && - ! _showEmptyBlockSideInserter && - isSectionSelected; const _showBlockToolbarPopover = - ! _showZoomOutToolbar && ! getSettings().hasFixedToolbar && ! _showEmptyBlockSideInserter && hasSelectedBlock && @@ -63,7 +51,6 @@ export function useShowBlockTools() { return { showEmptyBlockSideInserter: _showEmptyBlockSideInserter, showBlockToolbarPopover: _showBlockToolbarPopover, - showZoomOutToolbar: _showZoomOutToolbar, }; }, [] ); } diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js index c279cb36782028..17af902bf9baf2 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js @@ -16,30 +16,24 @@ function ZoomOutModeInserters() { const [ isReady, setIsReady ] = useState( false ); const { hasSelection, - insertionPoint, blockOrder, - blockInsertionPointVisible, setInserterIsOpened, sectionRootClientId, selectedBlockClientId, } = useSelect( ( select ) => { const { getSettings, - getInsertionPoint, getBlockOrder, getSelectionStart, getSelectedBlockClientId, getSectionRootClientId, - isBlockInsertionPointVisible, } = unlock( select( blockEditorStore ) ); const root = getSectionRootClientId(); return { hasSelection: !! getSelectionStart().clientId, - insertionPoint: getInsertionPoint(), blockOrder: getBlockOrder( root ), - blockInsertionPointVisible: isBlockInsertionPointVisible(), sectionRootClientId: root, setInserterIsOpened: getSettings().__experimentalSetIsInserterOpened, @@ -64,41 +58,32 @@ function ZoomOutModeInserters() { return null; } - return [ undefined, ...blockOrder ].map( ( clientId, index ) => { - const shouldRenderInsertionPoint = - blockInsertionPointVisible && insertionPoint?.index === index; + const previousClientId = selectedBlockClientId; + const index = blockOrder.findIndex( + ( clientId ) => selectedBlockClientId === clientId + ); + const nextClientId = blockOrder[ index + 1 ]; - const previousClientId = clientId; - const nextClientId = blockOrder[ index ]; - - const isSelected = - selectedBlockClientId === previousClientId || - selectedBlockClientId === nextClientId; - - return ( - <BlockPopoverInbetween - key={ index } - previousClientId={ previousClientId } - nextClientId={ nextClientId } - > - { ! shouldRenderInsertionPoint && isSelected && ( - <ZoomOutModeInserterButton - onClick={ () => { - setInserterIsOpened( { - rootClientId: sectionRootClientId, - insertionIndex: index, - tab: 'patterns', - category: 'all', - } ); - showInsertionPoint( sectionRootClientId, index, { - operation: 'insert', - } ); - } } - /> - ) } - </BlockPopoverInbetween> - ); - } ); + return ( + <BlockPopoverInbetween + previousClientId={ previousClientId } + nextClientId={ nextClientId } + > + <ZoomOutModeInserterButton + onClick={ () => { + setInserterIsOpened( { + rootClientId: sectionRootClientId, + insertionIndex: index + 1, + tab: 'patterns', + category: 'all', + } ); + showInsertionPoint( sectionRootClientId, index + 1, { + operation: 'insert', + } ); + } } + /> + </BlockPopoverInbetween> + ); } export default ZoomOutModeInserters; diff --git a/packages/block-editor/src/components/block-tools/zoom-out-popover.js b/packages/block-editor/src/components/block-tools/zoom-out-popover.js deleted file mode 100644 index 7a5c2243cf0540..00000000000000 --- a/packages/block-editor/src/components/block-tools/zoom-out-popover.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; -/** - * Internal dependencies - */ -import { PrivateBlockPopover as BlockPopover } from '../block-popover'; -import useBlockToolbarPopoverProps from './use-block-toolbar-popover-props'; -import useSelectedBlockToolProps from './use-selected-block-tool-props'; -import ZoomOutToolbar from './zoom-out-toolbar'; - -export default function ZoomOutPopover( { clientId, __unstableContentRef } ) { - const { capturingClientId, isInsertionPointVisible, lastClientId } = - useSelectedBlockToolProps( clientId ); - - const popoverProps = useBlockToolbarPopoverProps( { - contentElement: __unstableContentRef?.current, - clientId, - } ); - - // Override some of the popover props for the zoom-out toolbar. - const props = { - ...popoverProps, - placement: 'left-start', - flip: false, - shift: true, - }; - - return ( - <BlockPopover - __unstableContentRef={ __unstableContentRef } - clientId={ capturingClientId || clientId } - bottomClientId={ lastClientId } - className={ clsx( 'zoom-out-toolbar-popover', { - 'is-insertion-point-visible': isInsertionPointVisible, - } ) } - resize={ false } - { ...props } - > - <ZoomOutToolbar - __unstableContentRef={ __unstableContentRef } - clientId={ clientId } - /> - </BlockPopover> - ); -} diff --git a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js b/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js deleted file mode 100644 index 2b5c6a3e3cea6e..00000000000000 --- a/packages/block-editor/src/components/block-tools/zoom-out-toolbar.js +++ /dev/null @@ -1,135 +0,0 @@ -/** - * WordPress dependencies - */ -import { dragHandle, trash } from '@wordpress/icons'; -import { Button, ToolbarButton } from '@wordpress/components'; -import { useSelect, useDispatch } from '@wordpress/data'; -import { store as blocksStore } from '@wordpress/blocks'; -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import { store as blockEditorStore } from '../../store'; -import BlockDraggable from '../block-draggable'; -import BlockMover from '../block-mover'; -import Shuffle from '../block-toolbar/shuffle'; -import NavigableToolbar from '../navigable-toolbar'; - -export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { - const selected = useSelect( - ( select ) => { - const { - getBlock, - getNextBlockClientId, - getPreviousBlockClientId, - canRemoveBlock, - canMoveBlock, - getSettings, - } = select( blockEditorStore ); - - const { __experimentalSetIsInserterOpened: setIsInserterOpened } = - getSettings(); - - const { getBlockType } = select( blocksStore ); - const { name } = getBlock( clientId ); - const blockType = getBlockType( name ); - const isBlockTemplatePart = - blockType?.name === 'core/template-part'; - - let isNextBlockTemplatePart = false; - const nextClientId = getNextBlockClientId(); - if ( nextClientId ) { - const { name: nextName } = getBlock( nextClientId ); - const nextBlockType = getBlockType( nextName ); - isNextBlockTemplatePart = - nextBlockType?.name === 'core/template-part'; - } - - let isPrevBlockTemplatePart = false; - const prevClientId = getPreviousBlockClientId(); - if ( prevClientId ) { - const { name: prevName } = getBlock( prevClientId ); - const prevBlockType = getBlockType( prevName ); - isPrevBlockTemplatePart = - prevBlockType?.name === 'core/template-part'; - } - - return { - isBlockTemplatePart, - isNextBlockTemplatePart, - isPrevBlockTemplatePart, - canRemove: canRemoveBlock( clientId ), - canMove: canMoveBlock( clientId ), - setIsInserterOpened, - }; - }, - [ clientId ] - ); - - const { - isBlockTemplatePart, - isNextBlockTemplatePart, - isPrevBlockTemplatePart, - canRemove, - canMove, - } = selected; - - const { removeBlock } = useDispatch( blockEditorStore ); - - const showBlockDraggable = canMove && ! isBlockTemplatePart; - - return ( - <NavigableToolbar - className="zoom-out-toolbar" - /* translators: accessibility text for the block toolbar */ - aria-label={ __( 'Block tools' ) } - // The variant is applied as "toolbar" when undefined, which is the black border style of the dropdown from the toolbar popover. - variant="unstyled" - orientation="vertical" - > - { showBlockDraggable && ( - <BlockDraggable clientIds={ [ clientId ] }> - { ( draggableProps ) => ( - <Button - icon={ dragHandle } - className="block-selection-button_drag-handle zoom-out-toolbar-button" - label={ __( 'Drag' ) } - iconSize={ 24 } - size="compact" - // Should not be able to tab to drag handle as this - // button can only be used with a pointer device. - tabIndex="-1" - { ...draggableProps } - /> - ) } - </BlockDraggable> - ) } - { ! isBlockTemplatePart && ( - <BlockMover - clientIds={ [ clientId ] } - hideDragHandle - isBlockMoverUpButtonDisabled={ isPrevBlockTemplatePart } - isBlockMoverDownButtonDisabled={ isNextBlockTemplatePart } - iconSize={ 24 } - size="compact" - /> - ) } - { canMove && canRemove && ( - <Shuffle clientId={ clientId } as={ ToolbarButton } /> - ) } - - { canRemove && ! isBlockTemplatePart && ( - <ToolbarButton - className="zoom-out-toolbar-button" - icon={ trash } - label={ __( 'Delete' ) } - onClick={ () => { - removeBlock( clientId ); - __unstableContentRef.current?.focus(); - } } - /> - ) } - </NavigableToolbar> - ); -} diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index c3228980310656..28e0c2bd47b0ca 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -17,6 +17,7 @@ import { getClientIdsWithDescendants, isNavigationMode, getBlockRootClientId, + __unstableGetEditorMode, } from './selectors'; import { checkAllowListRecursive, @@ -579,7 +580,7 @@ export const getBlockStyles = createSelector( * @return {boolean} Is zoom out mode enabled. */ export function isZoomOutMode( state ) { - return state.editorMode === 'zoom-out'; + return __unstableGetEditorMode( state ) === 'zoom-out'; } /** From c34cf885a41e8375a4f2fad43bf40ec864abe486 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:18:25 +0200 Subject: [PATCH 1212/1908] Scripts: Refactor to extract license logic (#66179) Refactor some of the check-license logic into a reusable module. The check-license script continues to act as the CLI, while another module contains the license checking logic. This is helpful for work migrating to npm workspaces: https://github.com/WordPress/gutenberg/pull/65681 The license checking logic is required, but the implementation will be different to account for npm workspaces in Gutenberg. --- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/scripts/CHANGELOG.md | 5 +- packages/scripts/scripts/check-licenses.js | 346 +--------------- packages/scripts/utils/license.js | 376 ++++++++++++++++++ .../test/license.js} | 5 +- .../test/licenses/apache2-mit.txt | 0 .../test/licenses/apache2.txt | 0 .../test/licenses/bsd3clause.txt | 0 .../{scripts => utils}/test/licenses/mit.txt | 0 .../test/licenses/w3cbsd.txt | 0 9 files changed, 383 insertions(+), 349 deletions(-) create mode 100644 packages/scripts/utils/license.js rename packages/scripts/{scripts/test/check-licenses.js => utils/test/license.js} (96%) rename packages/scripts/{scripts => utils}/test/licenses/apache2-mit.txt (100%) rename packages/scripts/{scripts => utils}/test/licenses/apache2.txt (100%) rename packages/scripts/{scripts => utils}/test/licenses/bsd3clause.txt (100%) rename packages/scripts/{scripts => utils}/test/licenses/mit.txt (100%) rename packages/scripts/{scripts => utils}/test/licenses/w3cbsd.txt (100%) diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 6d72d80d91f0a5..ba644aa11f4a67 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,13 +2,16 @@ ## Unreleased +### Internal + +- Refactor to extract license related logic to a reusable module ([#66179](https://github.com/WordPress/gutenberg/pull/66179)). + ## 30.2.0 (2024-10-16) ## 30.1.0 (2024-10-03) ## 30.0.0 (2024-09-19) - ### Breaking Changes - Updated `stylelint` dependency to `^16.8.2` ([#64828](https://github.com/WordPress/gutenberg/pull/64828)). diff --git a/packages/scripts/scripts/check-licenses.js b/packages/scripts/scripts/check-licenses.js index 6401fd83e3482d..40537cf4880fce 100644 --- a/packages/scripts/scripts/check-licenses.js +++ b/packages/scripts/scripts/check-licenses.js @@ -2,13 +2,12 @@ * External dependencies */ const spawn = require( 'cross-spawn' ); -const { existsSync, readFileSync } = require( 'fs' ); -const chalk = require( 'chalk' ); /** * Internal dependencies */ const { getArgFromCLI, hasArgInCLI } = require( '../utils' ); +const { checkDepsInTree } = require( '../utils/license' ); /* * WARNING: Changes to this file may inadvertently cause us to distribute code that @@ -19,9 +18,6 @@ const { getArgFromCLI, hasArgInCLI } = require( '../utils' ); * reviewed and approved. */ -const ERROR = chalk.reset.inverse.bold.red( ' ERROR ' ); -const WARNING = chalk.reset.inverse.bold.yellow( ' WARNING ' ); - const prod = hasArgInCLI( '--prod' ) || hasArgInCLI( '--production' ); const dev = hasArgInCLI( '--dev' ) || hasArgInCLI( '--development' ); const gpl2 = hasArgInCLI( '--gpl2' ); @@ -33,144 +29,6 @@ const ignored = hasArgInCLI( '--ignore' ) .map( ( moduleName ) => moduleName.trim() ) : []; -/* - * A list of license strings that we've found to be GPL2 compatible. - * - * Note the strings with "AND" in them at the bottom: these should only be added when - * all the licenses in that string are GPL2 compatible. - */ -const gpl2CompatibleLicenses = [ - '0BSD', - 'Apache-2.0 WITH LLVM-exception', - 'Artistic-2.0', - 'BSD-2-Clause', - 'BSD-3-Clause-W3C', - 'BSD-3-Clause', - 'BSD', - 'CC-BY-4.0', - 'CC0-1.0', - 'GPL-2.0-or-later', - 'GPL-2.0', - 'GPL-2.0+', - 'ISC', - 'LGPL-2.1', - 'MIT', - 'MIT/X11', - 'MPL-2.0', - 'ODC-By-1.0', - 'Public Domain', - 'Unlicense', - 'W3C-20150513', - 'WTFPL', - 'Zlib', -]; - -/* - * A list of OSS license strings that aren't GPL2 compatible. - * - * We're cool with using packages that are licensed under any of these if we're not - * distributing them (for example, build tools), but we can't included them in a release. - */ -const otherOssLicenses = [ - 'Apache-2.0', - 'Apache License, Version 2.0', - 'CC-BY-3.0', - 'CC-BY-SA-2.0', - 'LGPL', - 'Python-2.0', -]; - -const licenses = [ - ...gpl2CompatibleLicenses, - ...( gpl2 ? [] : otherOssLicenses ), -]; - -/* - * Some packages don't included a license string in their package.json file, but they - * do have a license listed elsewhere. These files are checked for matching license strings. - * Only the first matching license file with a matching license string is considered. - * - * See: licenseFileStrings. - */ -const licenseFiles = [ - 'LICENCE', - 'license', - 'LICENSE', - 'LICENSE.md', - 'LICENSE.txt', - 'LICENSE-MIT', - 'MIT-LICENSE.txt', - 'Readme.md', - 'README.md', -]; - -/* - * When searching through files for licensing information, these are the strings we look for, - * and their matching license. - */ -const licenseFileStrings = { - 'Apache-2.0': [ 'Licensed under the Apache License, Version 2.0' ], - BSD: [ - 'Redistributions in binary form must reproduce the above copyright notice,', - ], - 'BSD-3-Clause-W3C': [ 'W3C 3-clause BSD License' ], - MIT: [ - 'Permission is hereby granted, free of charge,', - '## License\n\nMIT', - '## License\n\n MIT', - ], -}; - -/** - * Check if a license string matches the given license. - * - * The license string can be a single license, or an SPDX-compatible "OR" license string. - * eg, "(MIT OR Zlib)". - * - * @param {string} allowedLicense The license that's allowed. - * @param {string} licenseType The license string to check. - * - * @return {boolean} true if the licenseType matches the allowedLicense, false if it doesn't. - */ -const checkLicense = ( allowedLicense, licenseType ) => { - if ( ! licenseType ) { - return false; - } - - // Some licenses have unusual capitalisation in them. - const formattedAllowedLicense = allowedLicense.toLowerCase(); - const formattedlicenseType = licenseType.toLowerCase(); - - if ( formattedAllowedLicense === formattedlicenseType ) { - return true; - } - - // We can skip the parsing below if there isn't an 'OR' in the license. - if ( ! formattedlicenseType.includes( ' or ' ) ) { - return false; - } - - /* - * In order to do a basic parse of SPDX-compatible "OR" license strings, we: - * - Remove surrounding brackets: "(mit or zlib)" -> "mit or zlib" - * - Split it into an array: "mit or zlib" -> [ "mit", "zlib" ] - * - Trim any remaining whitespace from each element - */ - const subLicenseTypes = formattedlicenseType - .replace( /^\(*/g, '' ) - .replace( /\)*$/, '' ) - .split( ' or ' ) - .map( ( e ) => e.trim() ); - - // We can then check our array of licenses against the allowedLicense. - return ( - undefined !== - subLicenseTypes.find( ( subLicenseType ) => - checkLicense( allowedLicense, subLicenseType ) - ) - ); -}; - // Use `npm ls` to grab a list of all the packages. const child = spawn.sync( 'npm', @@ -193,204 +51,4 @@ const result = JSON.parse( child.stdout.toString() ); const topLevelDeps = result.dependencies; -function traverseDepTree( deps ) { - for ( const key in deps ) { - const dep = deps[ key ]; - - if ( ignored.includes( dep.name ) ) { - continue; - } - - if ( Object.keys( dep ).length === 0 ) { - continue; - } - - if ( ! dep.hasOwnProperty( 'path' ) && ! dep.missing ) { - if ( dep.hasOwnProperty( 'peerMissing' ) ) { - process.stdout.write( - `${ WARNING } Unable to locate path for missing peer dep ${ dep.name }@${ dep.version }. ` - ); - } else { - process.exitCode = 1; - process.stdout.write( - `${ ERROR } Unable to locate path for ${ dep.name }@${ dep.version }. ` - ); - } - } else if ( dep.missing ) { - for ( const problem of dep.problems ) { - process.stdout.write( `${ WARNING } ${ problem }.\n` ); - } - } else { - checkDepLicense( dep.path ); - } - - if ( dep.hasOwnProperty( 'dependencies' ) ) { - traverseDepTree( dep.dependencies ); - } - } -} - -function detectTypeFromLicenseFiles( path ) { - return licenseFiles.reduce( ( detectedType, licenseFile ) => { - // If another LICENSE file already had licenses in it, use those. - if ( detectedType ) { - return detectedType; - } - - const licensePath = path + '/' + licenseFile; - - if ( existsSync( licensePath ) ) { - const licenseText = readFileSync( licensePath ).toString(); - return detectTypeFromLicenseText( licenseText ); - } - - return detectedType; - }, false ); -} - -function detectTypeFromLicenseText( licenseText ) { - // Check if the file contains any of the strings in licenseFileStrings. - return Object.keys( licenseFileStrings ).reduce( - ( stringDetectedType, licenseStringType ) => { - const licenseFileString = licenseFileStrings[ licenseStringType ]; - - return licenseFileString.reduce( - ( currentDetectedType, fileString ) => { - if ( licenseText.includes( fileString ) ) { - if ( currentDetectedType ) { - return currentDetectedType.concat( - ' AND ', - licenseStringType - ); - } - return licenseStringType; - } - return currentDetectedType; - }, - stringDetectedType - ); - }, - false - ); -} - -const reportedPackages = new Set(); - -function checkDepLicense( path ) { - if ( ! path ) { - return; - } - - const filename = path + '/package.json'; - if ( ! existsSync( filename ) ) { - process.stdout.write( `Unable to locate package.json in ${ path }.` ); - process.exit( 1 ); - } - - /* - * The package.json format can be kind of weird. We allow for the following formats: - * - { license: 'MIT' } - * - { license: { type: 'MIT' } } - * - { licenses: [ 'MIT', 'Zlib' ] } - * - { licenses: [ { type: 'MIT' }, { type: 'Zlib' } ] } - */ - const packageInfo = require( filename ); - const license = - packageInfo.license || - ( packageInfo.licenses && - packageInfo.licenses.map( ( l ) => l.type || l ).join( ' OR ' ) ); - let licenseType = typeof license === 'object' ? license.type : license; - - // Check if the license we've detected is telling us to look in the license file, instead. - if ( - licenseType && - licenseFiles.find( ( licenseFile ) => - licenseType.includes( licenseFile ) - ) - ) { - licenseType = undefined; - } - - if ( licenseType !== undefined ) { - let licenseTypes = [ licenseType ]; - if ( licenseType.includes( ' AND ' ) ) { - licenseTypes = licenseType - .replace( /^\(*/g, '' ) - .replace( /\)*$/, '' ) - .split( ' AND ' ) - .map( ( e ) => e.trim() ); - } - - if ( checkAllCompatible( licenseTypes, licenses ) ) { - return; - } - } - - /* - * If we haven't been able to detect a license in the package.json file, - * or the type was invalid, try reading it from the files defined in - * license files, instead. - */ - const detectedLicenseType = detectTypeFromLicenseFiles( path ); - if ( ! licenseType && ! detectedLicenseType ) { - return; - } - - let detectedLicenseTypes = [ detectedLicenseType ]; - if ( detectedLicenseType && detectedLicenseType.includes( ' AND ' ) ) { - detectedLicenseTypes = detectedLicenseType - .replace( /^\(*/g, '' ) - .replace( /\)*$/, '' ) - .split( ' AND ' ) - .map( ( e ) => e.trim() ); - } - - if ( checkAllCompatible( detectedLicenseTypes, licenses ) ) { - return; - } - - // Do not report same package twice. - if ( reportedPackages.has( packageInfo.name ) ) { - return; - } - - reportedPackages.add( packageInfo.name ); - - process.exitCode = 1; - process.stdout.write( - `${ ERROR } Module ${ packageInfo.name } has an incompatible license '${ licenseType }'.\n` - ); -} - -/** - * Check that all of the licenses for a package are compatible. - * - * This function is invoked when the licenses are a conjunctive ("AND") list of licenses. - * In that case, the software is only compatible if all of the licenses in the list are - * compatible. - * - * @param {Array} packageLicenses The licenses that a package is licensed under. - * @param {Array} compatibleLicenses The list of compatible licenses. - * - * @return {boolean} true if all of the packageLicenses appear in compatibleLicenses. - */ -function checkAllCompatible( packageLicenses, compatibleLicenses ) { - return packageLicenses.reduce( ( compatible, packageLicense ) => { - return ( - compatible && - compatibleLicenses.reduce( - ( found, allowedLicense ) => - found || checkLicense( allowedLicense, packageLicense ), - false - ) - ); - }, true ); -} - -traverseDepTree( topLevelDeps ); - -// Required for unit testing -module.exports = { - detectTypeFromLicenseText, - checkAllCompatible, -}; +checkDepsInTree( topLevelDeps, { ignored, gpl2 } ); diff --git a/packages/scripts/utils/license.js b/packages/scripts/utils/license.js new file mode 100644 index 00000000000000..00043e77ff1412 --- /dev/null +++ b/packages/scripts/utils/license.js @@ -0,0 +1,376 @@ +/** + * External dependencies + */ +const chalk = require( 'chalk' ); +const { existsSync, readFileSync } = require( 'node:fs' ); + +const ERROR_TEXT = chalk.reset.inverse.bold.red( ' ERROR ' ); +const WARNING_TEXT = chalk.reset.inverse.bold.yellow( ' WARNING ' ); + +/** + * @typedef {ReadonlyArray<string>} Licenses + */ + +/** + * Some packages don't included a license string in their package.json file, but they + * do have a license listed elsewhere. These files are checked for matching license strings. + * Only the first matching license file with a matching license string is considered. + * + * See: licenseFileStrings. + * @type {ReadonlyArray<string>} + */ +const licenseFiles = [ + 'LICENCE', + 'license', + 'LICENSE', + 'LICENSE.md', + 'LICENSE.txt', + 'LICENSE-MIT', + 'MIT-LICENSE.txt', + 'Readme.md', + 'README.md', +]; + +/** + * When searching through files for licensing information, these are the strings we look for, + * and their matching license. + */ +const licenseFileStrings = { + 'Apache-2.0': [ 'Licensed under the Apache License, Version 2.0' ], + BSD: [ + 'Redistributions in binary form must reproduce the above copyright notice,', + ], + 'BSD-3-Clause-W3C': [ 'W3C 3-clause BSD License' ], + MIT: [ + 'Permission is hereby granted, free of charge,', + '## License\n\nMIT', + '## License\n\n MIT', + ], +}; + +/* + * A list of license strings that we've found to be GPL2 compatible. + * + * Note the strings with "AND" in them at the bottom: these should only be added when + * all the licenses in that string are GPL2 compatible. + */ +const gpl2CompatibleLicenses = [ + '0BSD', + 'Apache-2.0 WITH LLVM-exception', + 'Artistic-2.0', + 'BSD-2-Clause', + 'BSD-3-Clause-W3C', + 'BSD-3-Clause', + 'BSD', + 'CC-BY-4.0', + 'CC0-1.0', + 'GPL-2.0-or-later', + 'GPL-2.0', + 'GPL-2.0+', + 'ISC', + 'LGPL-2.1', + 'MIT', + 'MIT/X11', + 'MPL-2.0', + 'ODC-By-1.0', + 'Public Domain', + 'Unlicense', + 'W3C-20150513', + 'WTFPL', + 'Zlib', +]; + +/* + * A list of OSS license strings that aren't GPL2 compatible. + * + * We're cool with using packages that are licensed under any of these if we're not + * distributing them (for example, build tools), but we can't included them in a release. + */ +const otherOssLicenses = [ + 'Apache-2.0', + 'Apache License, Version 2.0', + 'CC-BY-3.0', + 'CC-BY-SA-2.0', + 'LGPL', + 'Python-2.0', +]; + +/** + * @param {boolean} gpl2 Only allow GPL2 compatible licenses. + * @return {Licenses} Allowed licenses. + */ +const getLicenses = ( gpl2 ) => { + return [ ...gpl2CompatibleLicenses, ...( gpl2 ? [] : otherOssLicenses ) ]; +}; + +/** + * Check if a license string matches the given license. + * + * The license string can be a single license, or an SPDX-compatible "OR" license string. + * eg, "(MIT OR Zlib)". + * + * @param {string} allowedLicense The license that's allowed. + * @param {string} licenseType The license string to check. + * + * @return {boolean} true if the licenseType matches the allowedLicense, false if it doesn't. + */ +const checkLicense = ( allowedLicense, licenseType ) => { + if ( ! licenseType ) { + return false; + } + + // Some licenses have unusual capitalisation in them. + const formattedAllowedLicense = allowedLicense.toLowerCase(); + const formattedlicenseType = licenseType.toLowerCase(); + + if ( formattedAllowedLicense === formattedlicenseType ) { + return true; + } + + // We can skip the parsing below if there isn't an 'OR' in the license. + if ( ! formattedlicenseType.includes( ' or ' ) ) { + return false; + } + + /* + * In order to do a basic parse of SPDX-compatible "OR" license strings, we: + * - Remove surrounding brackets: "(mit or zlib)" -> "mit or zlib" + * - Split it into an array: "mit or zlib" -> [ "mit", "zlib" ] + * - Trim any remaining whitespace from each element + */ + const subLicenseTypes = formattedlicenseType + .replace( /^\(*/g, '' ) + .replace( /\)*$/, '' ) + .split( ' or ' ) + .map( ( e ) => e.trim() ); + + // We can then check our array of licenses against the allowedLicense. + return ( + undefined !== + subLicenseTypes.find( ( subLicenseType ) => + checkLicense( allowedLicense, subLicenseType ) + ) + ); +}; + +/** + * Check that all of the licenses for a package are compatible. + * + * This function is invoked when the licenses are a conjunctive ("AND") list of licenses. + * In that case, the software is only compatible if all of the licenses in the list are + * compatible. + * + * @param {Licenses} packageLicenses The licenses that a package is licensed under. + * @param {Licenses} compatibleLicenses The list of compatible licenses. + * + * @return {boolean} true if all of the packageLicenses appear in compatibleLicenses. + */ +function checkAllCompatible( packageLicenses, compatibleLicenses ) { + return packageLicenses.reduce( ( compatible, packageLicense ) => { + return ( + compatible && + compatibleLicenses.reduce( + ( found, allowedLicense ) => + found || checkLicense( allowedLicense, packageLicense ), + false + ) + ); + }, true ); +} + +function detectTypeFromLicenseText( licenseText ) { + // Check if the file contains any of the strings in licenseFileStrings. + return Object.keys( licenseFileStrings ).reduce( + ( stringDetectedType, licenseStringType ) => { + const licenseFileString = licenseFileStrings[ licenseStringType ]; + + return licenseFileString.reduce( + ( currentDetectedType, fileString ) => { + if ( licenseText.includes( fileString ) ) { + if ( currentDetectedType ) { + return currentDetectedType.concat( + ' AND ', + licenseStringType + ); + } + return licenseStringType; + } + return currentDetectedType; + }, + stringDetectedType + ); + }, + false + ); +} + +const reportedPackages = new Set(); + +/** + * @param {string} path + * @param {Licenses} licenses + * @return {void} + */ +function checkDepLicense( path, licenses ) { + if ( ! path ) { + return; + } + + const filename = path + '/package.json'; + if ( ! existsSync( filename ) ) { + process.stdout.write( `Unable to locate package.json in ${ path }.` ); + process.exit( 1 ); + } + + /* + * The package.json format can be kind of weird. We allow for the following formats: + * - { license: 'MIT' } + * - { license: { type: 'MIT' } } + * - { licenses: [ 'MIT', 'Zlib' ] } + * - { licenses: [ { type: 'MIT' }, { type: 'Zlib' } ] } + */ + const packageInfo = require( filename ); + const license = + packageInfo.license || + ( packageInfo.licenses && + packageInfo.licenses.map( ( l ) => l.type || l ).join( ' OR ' ) ); + let licenseType = typeof license === 'object' ? license.type : license; + + // Check if the license we've detected is telling us to look in the license file, instead. + if ( + licenseType && + licenseFiles.find( ( licenseFile ) => + licenseType.includes( licenseFile ) + ) + ) { + licenseType = undefined; + } + + if ( licenseType !== undefined ) { + let licenseTypes = [ licenseType ]; + if ( licenseType.includes( ' AND ' ) ) { + licenseTypes = licenseType + .replace( /^\(*/g, '' ) + .replace( /\)*$/, '' ) + .split( ' AND ' ) + .map( ( e ) => e.trim() ); + } + + if ( checkAllCompatible( licenseTypes, licenses ) ) { + return; + } + } + + /* + * If we haven't been able to detect a license in the package.json file, + * or the type was invalid, try reading it from the files defined in + * license files, instead. + */ + const detectedLicenseType = detectTypeFromLicenseFiles( path ); + if ( ! licenseType && ! detectedLicenseType ) { + return; + } + + let detectedLicenseTypes = [ detectedLicenseType ]; + if ( detectedLicenseType && detectedLicenseType.includes( ' AND ' ) ) { + detectedLicenseTypes = detectedLicenseType + .replace( /^\(*/g, '' ) + .replace( /\)*$/, '' ) + .split( ' AND ' ) + .map( ( e ) => e.trim() ); + } + + if ( checkAllCompatible( detectedLicenseTypes, licenses ) ) { + return; + } + + // Do not report same package twice. + if ( reportedPackages.has( packageInfo.name ) ) { + return; + } + + reportedPackages.add( packageInfo.name ); + + process.exitCode = 1; + process.stdout.write( + `${ ERROR_TEXT } Module ${ packageInfo.name } has an incompatible license '${ licenseType }'.\n` + ); +} + +/** + * + * @typedef Options + * @property {boolean} gpl2 Only allow GPL2 compatible licenses. + * @property {Array<string>} [ignored] The list of ignored packages. + */ + +/** + * @param {Object} deps The dependencies tree. + * @param {Options} options + */ +function checkDepsInTree( deps, options ) { + const licenses = getLicenses( options.gpl2 ); + + for ( const key in deps ) { + const dep = deps[ key ]; + + if ( options.ignored?.includes( dep.name ) ) { + continue; + } + + if ( Object.keys( dep ).length === 0 ) { + continue; + } + + if ( ! dep.hasOwnProperty( 'path' ) && ! dep.missing ) { + if ( dep.hasOwnProperty( 'peerMissing' ) ) { + process.stdout.write( + `${ WARNING_TEXT } Unable to locate path for missing peer dep ${ dep.name }@${ dep.version }. ` + ); + } else { + process.exitCode = 1; + process.stdout.write( + `${ ERROR_TEXT } Unable to locate path for ${ dep.name }@${ dep.version }. ` + ); + } + } else if ( dep.missing ) { + for ( const problem of dep.problems ) { + process.stdout.write( `${ WARNING_TEXT } ${ problem }.\n` ); + } + } else { + checkDepLicense( dep.path, licenses ); + } + + if ( dep.hasOwnProperty( 'dependencies' ) ) { + checkDepsInTree( dep.dependencies, options ); + } + } +} + +/** + * @param {string} path The path to the package. + * @return {boolean} true if the package has a license, false if it + */ +function detectTypeFromLicenseFiles( path ) { + return licenseFiles.reduce( ( detectedType, licenseFile ) => { + // If another LICENSE file already had licenses in it, use those. + if ( detectedType ) { + return detectedType; + } + + const licensePath = path + '/' + licenseFile; + + if ( existsSync( licensePath ) ) { + const licenseText = readFileSync( licensePath ).toString(); + return detectTypeFromLicenseText( licenseText ); + } + + return detectedType; + }, false ); +} + +module.exports = { + detectTypeFromLicenseText, + checkAllCompatible, + checkDepsInTree, +}; diff --git a/packages/scripts/scripts/test/check-licenses.js b/packages/scripts/utils/test/license.js similarity index 96% rename from packages/scripts/scripts/test/check-licenses.js rename to packages/scripts/utils/test/license.js index 13116bd9222a06..2c188ba9a347da 100644 --- a/packages/scripts/scripts/test/check-licenses.js +++ b/packages/scripts/utils/test/license.js @@ -7,10 +7,7 @@ const path = require( 'path' ); /** * Internal dependencies */ -import { - detectTypeFromLicenseText, - checkAllCompatible, -} from '../check-licenses'; +import { detectTypeFromLicenseText, checkAllCompatible } from '../license'; describe( 'detectTypeFromLicenseText', () => { let licenseText; diff --git a/packages/scripts/scripts/test/licenses/apache2-mit.txt b/packages/scripts/utils/test/licenses/apache2-mit.txt similarity index 100% rename from packages/scripts/scripts/test/licenses/apache2-mit.txt rename to packages/scripts/utils/test/licenses/apache2-mit.txt diff --git a/packages/scripts/scripts/test/licenses/apache2.txt b/packages/scripts/utils/test/licenses/apache2.txt similarity index 100% rename from packages/scripts/scripts/test/licenses/apache2.txt rename to packages/scripts/utils/test/licenses/apache2.txt diff --git a/packages/scripts/scripts/test/licenses/bsd3clause.txt b/packages/scripts/utils/test/licenses/bsd3clause.txt similarity index 100% rename from packages/scripts/scripts/test/licenses/bsd3clause.txt rename to packages/scripts/utils/test/licenses/bsd3clause.txt diff --git a/packages/scripts/scripts/test/licenses/mit.txt b/packages/scripts/utils/test/licenses/mit.txt similarity index 100% rename from packages/scripts/scripts/test/licenses/mit.txt rename to packages/scripts/utils/test/licenses/mit.txt diff --git a/packages/scripts/scripts/test/licenses/w3cbsd.txt b/packages/scripts/utils/test/licenses/w3cbsd.txt similarity index 100% rename from packages/scripts/scripts/test/licenses/w3cbsd.txt rename to packages/scripts/utils/test/licenses/w3cbsd.txt From b8bfe7174b7a6b499e2f34f34f71c2735ee6c5fb Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 17 Oct 2024 13:25:12 +0300 Subject: [PATCH 1213/1908] PaletteEdit: Use `ItemGroup` and `Item`, and avoid custom styles (#66164) * PaletteEdit: Use Item directly * PaletteEdit: Cleanup legacy PaletteItem styles * CHANGELOG Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++ .../components/src/palette-edit/index.tsx | 9 ++- .../components/src/palette-edit/styles.ts | 68 +------------------ 3 files changed, 9 insertions(+), 72 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index f19e7f7eae7baa..d71f6ba7ce142f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,10 @@ - `ColorPalette`: prevent overflow of custom color button background ([#66152](https://github.com/WordPress/gutenberg/pull/66152)). +### Enhancements + +- `PaletteEdit`: use `Item` internally instead of custom styles ([#66164](https://github.com/WordPress/gutenberg/pull/66164)). + ## 28.10.0 (2024-10-16) ### Bug Fixes diff --git a/packages/components/src/palette-edit/index.tsx b/packages/components/src/palette-edit/index.tsx index 8bfcb7240b9ea4..570613e5378c10 100644 --- a/packages/components/src/palette-edit/index.tsx +++ b/packages/components/src/palette-edit/index.tsx @@ -24,7 +24,7 @@ import Button from '../button'; import { ColorPicker } from '../color-picker'; import { FlexItem } from '../flex'; import { HStack } from '../h-stack'; -import { ItemGroup } from '../item-group'; +import { Item, ItemGroup } from '../item-group'; import { VStack } from '../v-stack'; import GradientPicker from '../gradient-picker'; import ColorPalette from '../color-palette'; @@ -35,7 +35,6 @@ import { PaletteEditStyles, PaletteHeading, IndicatorStyled, - PaletteItem, NameContainer, NameInputControl, DoneButton, @@ -213,7 +212,7 @@ function Option< T extends PaletteElement >( { ); return ( - <PaletteItem ref={ setPopoverAnchor } as="div"> + <Item ref={ setPopoverAnchor } size="small"> <HStack justify="flex-start"> <Button onClick={ () => { @@ -282,7 +281,7 @@ function Option< T extends PaletteElement >( { onClose={ () => setIsEditingColor( false ) } /> ) } - </PaletteItem> + </Item> ); } @@ -309,7 +308,7 @@ function PaletteEditListView< T extends PaletteElement >( { return ( <VStack spacing={ 3 }> - <ItemGroup isRounded> + <ItemGroup isRounded isBordered isSeparated> { elements.map( ( element, index ) => ( <Option isGradient={ isGradient } diff --git a/packages/components/src/palette-edit/styles.ts b/packages/components/src/palette-edit/styles.ts index ad918d8590cf23..0afe38773fc8e2 100644 --- a/packages/components/src/palette-edit/styles.ts +++ b/packages/components/src/palette-edit/styles.ts @@ -2,7 +2,6 @@ * External dependencies */ import styled from '@emotion/styled'; -import { css } from '@emotion/react'; /** * Internal dependencies @@ -10,7 +9,7 @@ import { css } from '@emotion/react'; import Button from '../button'; import { Heading } from '../heading'; import { space } from '../utils/space'; -import { COLORS, CONFIG, font } from '../utils'; +import { COLORS, CONFIG } from '../utils'; import { View } from '../view'; import InputControl from '../input-control'; import { @@ -42,71 +41,6 @@ export const NameInputControl = styled( InputControl )` } `; -const buttonStyleReset = ( { - as, -}: { - as: React.ComponentProps< typeof View >[ 'as' ]; -} ) => { - if ( as === 'button' ) { - return css` - display: flex; - align-items: center; - width: 100%; - appearance: none; - background: transparent; - border: none; - border-radius: 0; - padding: 0; - cursor: pointer; - - &:hover { - color: ${ COLORS.theme.accent }; - } - `; - } - return null; -}; - -export const PaletteItem = styled( View )` - ${ buttonStyleReset } - - padding-block: 3px; - padding-inline-start: ${ space( 3 ) }; - border: 1px solid ${ CONFIG.surfaceBorderColor }; - border-bottom-color: transparent; - font-size: ${ font( 'default.fontSize' ) }; - - &:focus-visible { - border-color: transparent; - box-shadow: 0 0 0 var( --wp-admin-border-width-focus ) - ${ COLORS.theme.accent }; - // Windows high contrast mode. - outline: 2px solid transparent; - outline-offset: 0; - } - - border-top-left-radius: ${ CONFIG.radiusSmall }; - border-top-right-radius: ${ CONFIG.radiusSmall }; - - & + & { - border-top-left-radius: 0; - border-top-right-radius: 0; - } - - &:last-child { - border-bottom-left-radius: ${ CONFIG.radiusSmall }; - border-bottom-right-radius: ${ CONFIG.radiusSmall }; - border-bottom-color: ${ CONFIG.surfaceBorderColor }; - } - - &.is-selected + & { - border-top-color: transparent; - } - &.is-selected { - border-color: ${ COLORS.theme.accent }; - } -`; - export const NameContainer = styled.div` line-height: ${ space( 8 ) }; margin-left: ${ space( 2 ) }; From 6e764be7288185a31cc8ff89fe0d56d2faef7fa0 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 17 Oct 2024 19:31:46 +0900 Subject: [PATCH 1214/1908] Components: Prevent generated readmes duplicating h1 elements when published (#66180) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- bin/api-docs/gen-components-docs/markdown/index.mjs | 2 +- packages/components/src/alignment-matrix-control/README.md | 3 +-- packages/components/src/angle-picker-control/README.md | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/bin/api-docs/gen-components-docs/markdown/index.mjs b/bin/api-docs/gen-components-docs/markdown/index.mjs index 85655b89f08414..126fdf0057b6e5 100644 --- a/bin/api-docs/gen-components-docs/markdown/index.mjs +++ b/bin/api-docs/gen-components-docs/markdown/index.mjs @@ -10,8 +10,8 @@ import { generateMarkdownPropsJson } from './props.mjs'; export function generateMarkdownDocs( { typeDocs, subcomponentTypeDocs } ) { const mainDocsJson = [ - '<!-- This file is generated automatically and cannot be edited directly. -->\n', { h1: typeDocs.displayName }, + '<!-- This file is generated automatically and cannot be edited directly. Make edits via TypeScript types and TSDocs. -->', { p: `<p class="callout callout-info">See the <a href="https://wordpress.github.io/gutenberg/?path=/docs/components-${ typeDocs.displayName.toLowerCase() }--docs">WordPress Storybook</a> for more detailed, interactive documentation.</p>`, }, diff --git a/packages/components/src/alignment-matrix-control/README.md b/packages/components/src/alignment-matrix-control/README.md index 8e6ef324ce8e60..af97e3ae0607cd 100644 --- a/packages/components/src/alignment-matrix-control/README.md +++ b/packages/components/src/alignment-matrix-control/README.md @@ -1,7 +1,6 @@ -<!-- This file is generated automatically and cannot be edited directly. --> - # AlignmentMatrixControl +<!-- This file is generated automatically and cannot be edited directly. Make edits via TypeScript types and TSDocs. --> <p class="callout callout-info">See the <a href="https://wordpress.github.io/gutenberg/?path=/docs/components-alignmentmatrixcontrol--docs">WordPress Storybook</a> for more detailed, interactive documentation.</p> diff --git a/packages/components/src/angle-picker-control/README.md b/packages/components/src/angle-picker-control/README.md index f5f2627409e133..d9389c6564338f 100644 --- a/packages/components/src/angle-picker-control/README.md +++ b/packages/components/src/angle-picker-control/README.md @@ -1,7 +1,6 @@ -<!-- This file is generated automatically and cannot be edited directly. --> - # AnglePickerControl +<!-- This file is generated automatically and cannot be edited directly. Make edits via TypeScript types and TSDocs. --> <p class="callout callout-info">See the <a href="https://wordpress.github.io/gutenberg/?path=/docs/components-anglepickercontrol--docs">WordPress Storybook</a> for more detailed, interactive documentation.</p> From ab467645855eef40b1570e5bd0a8db03aa62dad6 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:51:25 +0200 Subject: [PATCH 1215/1908] Performance tests : - Fix/compare performance with correct branch (#66196) * Target base branch instead of just trunk * Update description Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .github/workflows/performance.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index a79f2eee9315a5..b947f4ff08c602 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -47,9 +47,9 @@ jobs: [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" nvm -v - - name: Compare performance with trunk + - name: Compare performance with base branch if: github.event_name == 'pull_request' - run: ./bin/plugin/cli.js perf $GITHUB_SHA trunk --tests-branch $GITHUB_SHA + run: ./bin/plugin/cli.js perf $GITHUB_SHA ${{ github.base_ref }} --tests-branch $GITHUB_SHA - name: Compare performance with current WordPress Core and previous Gutenberg versions if: github.event_name == 'release' From 0a6cbb6b2495bc5b0296456aeed65c28f7171502 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:01:57 +0300 Subject: [PATCH 1216/1908] ItemGroup: Improve stories to default to bordered and separated (#66191) * ItemGroup: Improve stories to default to bordered * Inherit default story args Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../src/item-group/stories/index.story.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/components/src/item-group/stories/index.story.tsx b/packages/components/src/item-group/stories/index.story.tsx index 473cdfedbf4f12..99309b81ea314f 100644 --- a/packages/components/src/item-group/stories/index.story.tsx +++ b/packages/components/src/item-group/stories/index.story.tsx @@ -37,6 +37,8 @@ const Template: StoryFn< typeof ItemGroup > = ( props ) => ( export const Default: StoryFn< typeof ItemGroup > = Template.bind( {} ); Default.args = { + isBordered: true, + isSeparated: true, children: ( [ { @@ -67,6 +69,7 @@ export const NonClickableItems: StoryFn< typeof ItemGroup > = Template.bind( {} ); NonClickableItems.args = { + ...Default.args, children: ( [ { @@ -83,6 +86,7 @@ NonClickableItems.args = { export const CustomItemSize: StoryFn< typeof ItemGroup > = Template.bind( {} ); CustomItemSize.args = { + ...Default.args, children: ( [ { @@ -98,9 +102,9 @@ CustomItemSize.args = { ).map( mapPropsToItem ), }; -export const WithBorder: StoryFn< typeof ItemGroup > = Template.bind( {} ); -WithBorder.args = { +export const WithoutBorder: StoryFn< typeof ItemGroup > = Template.bind( {} ); +WithoutBorder.args = { ...Default.args, - isBordered: true, - isSeparated: true, + isBordered: false, + isSeparated: false, }; From f58d95823071ed4bf77dd610b62dd0f893907061 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Thu, 17 Oct 2024 13:19:26 +0200 Subject: [PATCH 1217/1908] Scripts: Add BlueOak-1.0.0 license to GPL2 compatible (#66139) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add BlueOak-1.0.0 to GPLv2 compatible licenses recognized by wp-scripts check-licenses. - Remove redundant ignores from Gutenberg's check-licenses script. This license appears on some npm packages. It's intended to be highly permissive. The website states that it should be GPLv2 compatible: > Is the model license compatible with GPL? > > The Council doesn’t see any reason why software licensed under the > Blue Oak Model License 1.0.0 can’t be used, combined, and distributed > with software under GPLv2, LGPLv2.1, GPLv3, LGPLv3, or AGPLv3. https://blueoakcouncil.org/license-faq --- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: aaronjorbin <jorbin@git.wordpress.org> --- package.json | 2 +- packages/scripts/CHANGELOG.md | 4 ++++ packages/scripts/utils/license.js | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 0d31e446896e65..8be1e9cbe3f3a0 100644 --- a/package.json +++ b/package.json @@ -308,7 +308,7 @@ "lint:pkg-json": "wp-scripts lint-pkg-json . 'packages/*/package.json'", "native": "npm run --prefix packages/react-native-editor", "other:changelog": "node ./bin/plugin/cli.js changelog", - "other:check-licenses": "concurrently \"wp-scripts check-licenses --prod --gpl2 --ignore=@react-native-community/cli,@react-native-community/cli-platform-ios,@ampproject/remapping,human-signals,fb-watchman,bser,walker,chrome-launcher,lighthouse-logger,chromium-edge-launcher\" \"wp-scripts check-licenses --dev --ignore=jackspeak,path-scurry,package-json-from-dist\"", + "other:check-licenses": "concurrently \"wp-scripts check-licenses --prod --gpl2 --ignore=@react-native-community/cli,@react-native-community/cli-platform-ios,@ampproject/remapping,human-signals,fb-watchman,walker,chrome-launcher,lighthouse-logger,chromium-edge-launcher\" \"wp-scripts check-licenses --dev\"", "preother:check-local-changes": "npm run docs:build", "other:check-local-changes": "node ./bin/check-local-changes.js", "other:cherry-pick": "node ./bin/cherry-pick.mjs", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index ba644aa11f4a67..4e450974d334fd 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Add BlueOak-1.0.0 the GPLv2-comatible licenses recognized by check-licenses ([#66139](https://github.com/WordPress/gutenberg/pull/66139)). + ### Internal - Refactor to extract license related logic to a reusable module ([#66179](https://github.com/WordPress/gutenberg/pull/66179)). diff --git a/packages/scripts/utils/license.js b/packages/scripts/utils/license.js index 00043e77ff1412..ae18bfb2535985 100644 --- a/packages/scripts/utils/license.js +++ b/packages/scripts/utils/license.js @@ -58,6 +58,7 @@ const gpl2CompatibleLicenses = [ '0BSD', 'Apache-2.0 WITH LLVM-exception', 'Artistic-2.0', + 'BlueOak-1.0.0', 'BSD-2-Clause', 'BSD-3-Clause-W3C', 'BSD-3-Clause', From 8aa998526984a3e9d547cd638840f8314bad9d81 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Thu, 17 Oct 2024 12:24:21 +0100 Subject: [PATCH 1218/1908] Update site icon and title position (#66171) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/edit-site/src/components/layout/style.scss | 4 ++-- packages/edit-site/src/components/site-hub/index.js | 4 ++-- packages/edit-site/src/components/site-hub/style.scss | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/layout/style.scss b/packages/edit-site/src/components/layout/style.scss index 27a3f7b99bf7e2..2c7e6ce1b10c8b 100644 --- a/packages/edit-site/src/components/layout/style.scss +++ b/packages/edit-site/src/components/layout/style.scss @@ -210,8 +210,8 @@ html.canvas-mode-edit-transition::view-transition-group(toggle) { .edit-site-layout__view-mode-toggle-icon { display: flex; - height: $grid-unit-80; - width: $grid-unit-80; + height: $header-height; + width: $header-height; justify-content: center; align-items: center; } diff --git a/packages/edit-site/src/components/site-hub/index.js b/packages/edit-site/src/components/site-hub/index.js index 8cb3502493cff0..3f34b8bd1cccb6 100644 --- a/packages/edit-site/src/components/site-hub/index.js +++ b/packages/edit-site/src/components/site-hub/index.js @@ -68,7 +68,7 @@ const SiteHub = memo( label={ __( 'Go to the Dashboard' ) } className="edit-site-layout__view-mode-toggle" style={ { - transform: 'scale(0.5)', + transform: 'scale(0.5333) translateX(-4px)', // Offset to position the icon 12px from viewport edge borderRadius: 4, } } > @@ -99,7 +99,7 @@ const SiteHub = memo( className="edit-site-site-hub__actions" > <Button - __next40pxDefaultSize + size="compact" className="edit-site-site-hub_toggle-command-center" icon={ search } onClick={ () => openCommandCenter() } diff --git a/packages/edit-site/src/components/site-hub/style.scss b/packages/edit-site/src/components/site-hub/style.scss index 7fae845d4d2030..b1c1a3a41cc532 100644 --- a/packages/edit-site/src/components/site-hub/style.scss +++ b/packages/edit-site/src/components/site-hub/style.scss @@ -4,6 +4,7 @@ justify-content: space-between; gap: $grid-unit-10; margin-right: $grid-unit-15; + height: $grid-unit-70; } .edit-site-site-hub__actions { @@ -29,6 +30,9 @@ overflow: hidden; // Add space for the ↗ to render. padding-right: $grid-unit-20; + + // Create 12px gap between site icon and site title + margin-left: - $grid-unit-05; position: relative; text-decoration: none; text-overflow: ellipsis; From 76cf0756701e48d17147d1bd5fc806eda0cdfa6f Mon Sep 17 00:00:00 2001 From: Matthew Reishus <mreishus@users.noreply.github.com> Date: Thu, 17 Oct 2024 06:53:42 -0500 Subject: [PATCH 1219/1908] scripts: Add build-blocks-manifest command (#65866) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * scripts: Add build-blocks-manifest command * Remove package.json entry * add test * npm install in root to update lockfile * Add changelog entry * error on empty and missing dirs, update tests * Update CHANGELOG.md --------- Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> Co-authored-by: mreishus <mreishus@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: felixarntz <flixos90@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- package-lock.json | 8 ++ packages/scripts/CHANGELOG.md | 4 + packages/scripts/README.md | 35 ++++++ packages/scripts/package.json | 1 + .../scripts/scripts/build-blocks-manifest.js | 72 +++++++++++ .../build-blocks-manifest.js.snap | 113 ++++++++++++++++++ .../scripts/test/build-blocks-manifest.js | 101 ++++++++++++++++ .../build-blocks-manifest/empty-input/.keep | 0 .../input/custom-header/block.json | 33 +++++ .../input/image-gallery/block.json | 50 ++++++++ .../input/simple-button/block.json | 16 +++ 11 files changed, 433 insertions(+) create mode 100644 packages/scripts/scripts/build-blocks-manifest.js create mode 100644 packages/scripts/scripts/test/__snapshots__/build-blocks-manifest.js.snap create mode 100644 packages/scripts/scripts/test/build-blocks-manifest.js create mode 100644 packages/scripts/scripts/test/fixtures/build-blocks-manifest/empty-input/.keep create mode 100644 packages/scripts/scripts/test/fixtures/build-blocks-manifest/input/custom-header/block.json create mode 100644 packages/scripts/scripts/test/fixtures/build-blocks-manifest/input/image-gallery/block.json create mode 100644 packages/scripts/scripts/test/fixtures/build-blocks-manifest/input/simple-button/block.json diff --git a/package-lock.json b/package-lock.json index 3201aaf06682d4..d49fb33f5c7078 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56499,6 +56499,7 @@ "jest-dev-server": "^9.0.1", "jest-environment-jsdom": "^29.6.2", "jest-environment-node": "^29.6.2", + "json2php": "^0.0.9", "markdownlint-cli": "^0.31.1", "merge-deep": "^3.0.3", "mini-css-extract-plugin": "^2.5.1", @@ -56724,6 +56725,13 @@ "dev": true, "license": "MIT" }, + "packages/scripts/node_modules/json2php": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/json2php/-/json2php-0.0.9.tgz", + "integrity": "sha512-fQMYwvPsQt8hxRnCGyg1r2JVi6yL8Um0DIIawiKiMK9yhAAkcRNj5UsBWoaFvFzPpcWbgw9L6wzj+UMYA702Mw==", + "dev": true, + "license": "BSD" + }, "packages/scripts/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 4e450974d334fd..41dcf4d54922f8 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -10,6 +10,10 @@ - Refactor to extract license related logic to a reusable module ([#66179](https://github.com/WordPress/gutenberg/pull/66179)). +### New Features + +- Add new `build-blocks-manifest` command to generate a PHP file containing block metadata from all `block.json` files in a project ([#65866](https://github.com/WordPress/gutenberg/pull/65866)). + ## 30.2.0 (2024-10-16) ## 30.1.0 (2024-10-03) diff --git a/packages/scripts/README.md b/packages/scripts/README.md index 9973090a3e11e4..46e1a1265662cf 100644 --- a/packages/scripts/README.md +++ b/packages/scripts/README.md @@ -117,6 +117,41 @@ and should be registered in WordPress using the Modules API. This script uses [webpack](https://webpack.js.org/) behind the scenes. It’ll look for a webpack config in the top-level directory of your package and will use it if it finds one. If none is found, it’ll use the default config provided by `@wordpress/scripts` packages. Learn more in the [Advanced Usage](#advanced-usage) section. + +### `build-blocks-manifest` + +This script generates a PHP file containing block metadata from all +`block.json` files in the project. This is useful for enhancing performance +when registering multiple block types, as it allows you to use +`wp_register_block_metadata_collection()` in WordPress. + +Usage: `wp-scripts build-blocks-manifest [options]` + +Options: +- `--input`: Specify the input directory (default: 'build') +- `--output`: Specify the output file path (default: 'build/blocks-manifest.php') + +Example: +```bash +wp-scripts build-blocks-manifest --input=src --output=dist/blocks-manifest.php +``` + +This command will scan the specified input directory for `block.json` files, +compile their metadata into a single PHP file, and output it to the specified +location. You can then use this file with +`wp_register_block_metadata_collection()` in your plugin: + +```php +wp_register_block_metadata_collection( + plugin_dir_path( __FILE__ ) . 'dist', + plugin_dir_path( __FILE__ ) . 'dist/blocks-manifest.php' +); +``` + +Using this approach can improve performance when registering multiple block +types, especially for plugins with several custom blocks. Note that this +feature is only available in WordPress 6.7 and later versions. + ### `check-engines` Checks if the current `node`, `npm` (or `yarn`) versions match the given [semantic version](https://semver.org/) ranges. If the given version is not satisfied, information about installing the needed version is printed and the program exits with an error code. diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 07cb9799275db5..c98f341b812655 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -66,6 +66,7 @@ "jest-dev-server": "^9.0.1", "jest-environment-jsdom": "^29.6.2", "jest-environment-node": "^29.6.2", + "json2php": "^0.0.9", "markdownlint-cli": "^0.31.1", "merge-deep": "^3.0.3", "mini-css-extract-plugin": "^2.5.1", diff --git a/packages/scripts/scripts/build-blocks-manifest.js b/packages/scripts/scripts/build-blocks-manifest.js new file mode 100644 index 00000000000000..7138505de59ed6 --- /dev/null +++ b/packages/scripts/scripts/build-blocks-manifest.js @@ -0,0 +1,72 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ); +const path = require( 'path' ); +const { sync: glob } = require( 'fast-glob' ); +const json2php = require( 'json2php' ); +const chalk = require( 'chalk' ); + +/** + * Internal dependencies + */ +const { getArgFromCLI } = require( '../utils' ); + +// Set default paths +const defaultInputDir = 'build'; +const defaultOutputFile = path.join( 'build', 'blocks-manifest.php' ); + +// Parse command line arguments +const inputDir = getArgFromCLI( '--input' ) || defaultInputDir; +const outputFile = getArgFromCLI( '--output' ) || defaultOutputFile; + +const resolvedInputDir = path.resolve( process.cwd(), inputDir ); +if ( ! fs.existsSync( resolvedInputDir ) ) { + const ERROR = chalk.reset.inverse.bold.red( ' ERROR ' ); + process.stdout.write( + `${ ERROR } Input directory "${ inputDir }" does not exist.\n` + ); + process.exit( 1 ); +} + +// Find all block.json files +const blockJsonFiles = glob( './**/block.json', { + cwd: resolvedInputDir, + absolute: true, +} ); + +const blocks = {}; + +blockJsonFiles.forEach( ( file ) => { + const blockJson = JSON.parse( fs.readFileSync( file, 'utf8' ) ); + const directoryName = path.basename( path.dirname( file ) ); + blocks[ directoryName ] = blockJson; +} ); + +if ( Object.keys( blocks ).length === 0 ) { + const ERROR = chalk.reset.inverse.bold.red( ' ERROR ' ); + process.stdout.write( + `${ ERROR } No block.json files were found in path: ${ inputDir }.\n` + ); + process.exit( 1 ); +} + +// Generate PHP content +const printer = json2php.make( { linebreak: '\n', indent: '\t' } ); +const phpContent = `<?php +// This file is generated. Do not modify it manually. +return ${ printer( blocks ) }; +`; + +// Ensure output directory exists +const outputDir = path.dirname( outputFile ); +if ( ! fs.existsSync( outputDir ) ) { + fs.mkdirSync( outputDir, { recursive: true } ); +} + +// Write the file +fs.writeFileSync( outputFile, phpContent ); + +process.stdout.write( + `Block metadata PHP file generated at: ${ outputFile }\n` +); diff --git a/packages/scripts/scripts/test/__snapshots__/build-blocks-manifest.js.snap b/packages/scripts/scripts/test/__snapshots__/build-blocks-manifest.js.snap new file mode 100644 index 00000000000000..aa7cd50e3470ce --- /dev/null +++ b/packages/scripts/scripts/test/__snapshots__/build-blocks-manifest.js.snap @@ -0,0 +1,113 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`build-blocks-manifest script should generate expected blocks manifest 1`] = ` +"<?php +// This file is generated. Do not modify it manually. +return array( + 'custom-header' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 2, + 'name' => 'my-plugin/custom-header', + 'title' => 'Custom Header', + 'category' => 'text', + 'icon' => 'heading', + 'description' => 'A custom header block with color options.', + 'attributes' => array( + 'content' => array( + 'type' => 'string', + 'source' => 'html', + 'selector' => 'h2' + ), + 'textColor' => array( + 'type' => 'string' + ), + 'backgroundColor' => array( + 'type' => 'string' + ) + ), + 'supports' => array( + 'html' => false, + 'color' => array( + 'background' => true, + 'text' => true + ) + ), + 'textdomain' => 'my-plugin', + 'editorScript' => 'file:./index.js', + 'editorStyle' => 'file:./index.css', + 'style' => 'file:./style-index.css' + ), + 'image-gallery' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 2, + 'name' => 'my-plugin/image-gallery', + 'title' => 'Image Gallery', + 'category' => 'media', + 'icon' => 'format-gallery', + 'description' => 'An image gallery block with customizable layout.', + 'attributes' => array( + 'images' => array( + 'type' => 'array', + 'default' => array( + + ), + 'source' => 'query', + 'selector' => 'img', + 'query' => array( + 'url' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'src' + ), + 'alt' => array( + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'alt', + 'default' => '' + ), + 'id' => array( + 'type' => 'number', + 'source' => 'attribute', + 'attribute' => 'data-id' + ) + ) + ), + 'columns' => array( + 'type' => 'number', + 'default' => 3 + ), + 'imageCrop' => array( + 'type' => 'boolean', + 'default' => true + ) + ), + 'supports' => array( + 'align' => array( + 'wide', + 'full' + ) + ), + 'textdomain' => 'my-plugin', + 'editorScript' => 'file:./index.js', + 'editorStyle' => 'file:./index.css', + 'style' => 'file:./style-index.css' + ), + 'simple-button' => array( + '$schema' => 'https://schemas.wp.org/trunk/block.json', + 'apiVersion' => 2, + 'name' => 'my-plugin/simple-button', + 'title' => 'Simple Button', + 'category' => 'design', + 'icon' => 'button', + 'description' => 'A simple button block.', + 'supports' => array( + 'html' => false + ), + 'textdomain' => 'my-plugin', + 'editorScript' => 'file:./index.js', + 'editorStyle' => 'file:./index.css', + 'style' => 'file:./style-index.css' + ) +); +" +`; diff --git a/packages/scripts/scripts/test/build-blocks-manifest.js b/packages/scripts/scripts/test/build-blocks-manifest.js new file mode 100644 index 00000000000000..70009bd6087b56 --- /dev/null +++ b/packages/scripts/scripts/test/build-blocks-manifest.js @@ -0,0 +1,101 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ); +const path = require( 'path' ); +const { execSync } = require( 'child_process' ); +const rimraf = require( 'rimraf' ); + +const fixturesPath = path.join( + __dirname, + 'fixtures', + 'build-blocks-manifest' +); +const outputPath = path.join( __dirname, 'build', 'test-blocks-manifest' ); + +describe( 'build-blocks-manifest script', () => { + beforeAll( () => { + if ( ! fs.existsSync( outputPath ) ) { + fs.mkdirSync( outputPath, { recursive: true } ); + } + rimraf.sync( outputPath ); + } ); + + afterAll( () => { + rimraf.sync( outputPath ); + } ); + + it( 'should generate expected blocks manifest', () => { + const inputDir = path.join( fixturesPath, 'input' ); + const outputFile = path.join( outputPath, 'blocks-manifest.php' ); + + // Run the build-blocks-manifest script + const scriptPath = path.resolve( + __dirname, + '..', + 'build-blocks-manifest.js' + ); + execSync( + `node ${ scriptPath } --input=${ inputDir } --output=${ outputFile }` + ); + + const generatedContent = fs.readFileSync( outputFile, 'utf8' ); + expect( generatedContent ).toMatchSnapshot(); + } ); + + it( 'should error on empty input directory', () => { + const emptyInputDir = path.join( fixturesPath, 'empty-input' ); + const outputFile = path.join( outputPath, 'empty-blocks-manifest.php' ); + + const scriptPath = path.resolve( + __dirname, + '..', + 'build-blocks-manifest.js' + ); + let error; + try { + execSync( + `node ${ scriptPath } --input=${ emptyInputDir } --output=${ outputFile }`, + { encoding: 'utf8' } + ); + } catch ( e ) { + error = e; + } + + // Check that an error was thrown. + expect( error ).toBeDefined(); + expect( error.stdout ).toContain( + `No block.json files were found in path` + ); + + // Ensure that the output file was not created + expect( fs.existsSync( outputFile ) ).toBe( false ); + } ); + + it( 'should error on missing input directory', () => { + const nonExistentInputDir = path.join( fixturesPath, 'missing-input' ); + const outputFile = path.join( outputPath, 'empty-blocks-manifest.php' ); + + const scriptPath = path.resolve( + __dirname, + '..', + 'build-blocks-manifest.js' + ); + let error; + try { + execSync( + `node ${ scriptPath } --input=${ nonExistentInputDir } --output=${ outputFile }`, + { encoding: 'utf8' } + ); + } catch ( e ) { + error = e; + } + + // Check that an error was thrown. + expect( error ).toBeDefined(); + expect( error.stdout ).toContain( `does not exist` ); + + // Ensure that the output file was not created + expect( fs.existsSync( outputFile ) ).toBe( false ); + } ); +} ); diff --git a/packages/scripts/scripts/test/fixtures/build-blocks-manifest/empty-input/.keep b/packages/scripts/scripts/test/fixtures/build-blocks-manifest/empty-input/.keep new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/packages/scripts/scripts/test/fixtures/build-blocks-manifest/input/custom-header/block.json b/packages/scripts/scripts/test/fixtures/build-blocks-manifest/input/custom-header/block.json new file mode 100644 index 00000000000000..056bffbe28b184 --- /dev/null +++ b/packages/scripts/scripts/test/fixtures/build-blocks-manifest/input/custom-header/block.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "my-plugin/custom-header", + "title": "Custom Header", + "category": "text", + "icon": "heading", + "description": "A custom header block with color options.", + "attributes": { + "content": { + "type": "string", + "source": "html", + "selector": "h2" + }, + "textColor": { + "type": "string" + }, + "backgroundColor": { + "type": "string" + } + }, + "supports": { + "html": false, + "color": { + "background": true, + "text": true + } + }, + "textdomain": "my-plugin", + "editorScript": "file:./index.js", + "editorStyle": "file:./index.css", + "style": "file:./style-index.css" +} diff --git a/packages/scripts/scripts/test/fixtures/build-blocks-manifest/input/image-gallery/block.json b/packages/scripts/scripts/test/fixtures/build-blocks-manifest/input/image-gallery/block.json new file mode 100644 index 00000000000000..9c84fff4338704 --- /dev/null +++ b/packages/scripts/scripts/test/fixtures/build-blocks-manifest/input/image-gallery/block.json @@ -0,0 +1,50 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "my-plugin/image-gallery", + "title": "Image Gallery", + "category": "media", + "icon": "format-gallery", + "description": "An image gallery block with customizable layout.", + "attributes": { + "images": { + "type": "array", + "default": [], + "source": "query", + "selector": "img", + "query": { + "url": { + "type": "string", + "source": "attribute", + "attribute": "src" + }, + "alt": { + "type": "string", + "source": "attribute", + "attribute": "alt", + "default": "" + }, + "id": { + "type": "number", + "source": "attribute", + "attribute": "data-id" + } + } + }, + "columns": { + "type": "number", + "default": 3 + }, + "imageCrop": { + "type": "boolean", + "default": true + } + }, + "supports": { + "align": [ "wide", "full" ] + }, + "textdomain": "my-plugin", + "editorScript": "file:./index.js", + "editorStyle": "file:./index.css", + "style": "file:./style-index.css" +} diff --git a/packages/scripts/scripts/test/fixtures/build-blocks-manifest/input/simple-button/block.json b/packages/scripts/scripts/test/fixtures/build-blocks-manifest/input/simple-button/block.json new file mode 100644 index 00000000000000..23e607c411fbdc --- /dev/null +++ b/packages/scripts/scripts/test/fixtures/build-blocks-manifest/input/simple-button/block.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "my-plugin/simple-button", + "title": "Simple Button", + "category": "design", + "icon": "button", + "description": "A simple button block.", + "supports": { + "html": false + }, + "textdomain": "my-plugin", + "editorScript": "file:./index.js", + "editorStyle": "file:./index.css", + "style": "file:./style-index.css" +} From b372527409c9994f583536828218770cc0cc8b29 Mon Sep 17 00:00:00 2001 From: dhruvang21 <105810308+dhruvang21@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:26:47 +0530 Subject: [PATCH 1220/1908] Remove hasArrowIndicator prop (#66204) Co-authored-by: dhruvang21 <dhruvang21@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/block-library/src/table/edit.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-library/src/table/edit.js b/packages/block-library/src/table/edit.js index 95162f4e14c00b..f1cb3fa5d8b8ae 100644 --- a/packages/block-library/src/table/edit.js +++ b/packages/block-library/src/table/edit.js @@ -465,7 +465,6 @@ function TableEdit( { </BlockControls> <BlockControls group="other"> <ToolbarDropdownMenu - hasArrowIndicator icon={ table } label={ __( 'Edit table' ) } controls={ tableControls } From 52d0b99df9cc1e6e0380e11053ea2ed2575492aa Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 17 Oct 2024 13:57:43 +0100 Subject: [PATCH 1221/1908] Site Editor: Prepare route registration by refactoring the site editor router (#66030) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- .../edit-site/src/components/app/index.js | 6 +- .../edit-site/src/components/layout/index.js | 4 +- .../edit-site/src/components/layout/router.js | 151 +++--------------- .../src/components/posts-app/index.js | 4 +- .../src/components/posts-app/router.js | 6 +- .../site-editor-routes/home-edit.js | 17 ++ .../site-editor-routes/home-view.js | 16 ++ .../components/site-editor-routes/index.js | 60 +++++++ .../site-editor-routes/navigation-edit.js | 22 +++ .../navigation-item-edit.js | 26 +++ .../navigation-item-view.js | 25 +++ .../site-editor-routes/navigation-view.js | 21 +++ .../site-editor-routes/pages-edit.js | 35 ++++ .../pages-list-view-quick-edit.js | 56 +++++++ .../site-editor-routes/pages-list-view.js | 44 +++++ .../pages-view-quick-edit.js | 53 ++++++ .../site-editor-routes/pages-view.js | 39 +++++ .../site-editor-routes/patterns-edit.js | 24 +++ .../site-editor-routes/patterns-view.js | 22 +++ .../site-editor-routes/styles-edit.js | 17 ++ .../site-editor-routes/styles-view.js | 16 ++ .../site-editor-routes/templates-edit.js | 22 +++ .../site-editor-routes/templates-list-view.js | 28 ++++ .../site-editor-routes/templates-view.js | 22 +++ .../edit-site/src/store/private-actions.js | 7 + .../edit-site/src/store/private-selectors.js | 4 + packages/edit-site/src/store/reducer.js | 10 ++ 27 files changed, 615 insertions(+), 142 deletions(-) create mode 100644 packages/edit-site/src/components/site-editor-routes/home-edit.js create mode 100644 packages/edit-site/src/components/site-editor-routes/home-view.js create mode 100644 packages/edit-site/src/components/site-editor-routes/index.js create mode 100644 packages/edit-site/src/components/site-editor-routes/navigation-edit.js create mode 100644 packages/edit-site/src/components/site-editor-routes/navigation-item-edit.js create mode 100644 packages/edit-site/src/components/site-editor-routes/navigation-item-view.js create mode 100644 packages/edit-site/src/components/site-editor-routes/navigation-view.js create mode 100644 packages/edit-site/src/components/site-editor-routes/pages-edit.js create mode 100644 packages/edit-site/src/components/site-editor-routes/pages-list-view-quick-edit.js create mode 100644 packages/edit-site/src/components/site-editor-routes/pages-list-view.js create mode 100644 packages/edit-site/src/components/site-editor-routes/pages-view-quick-edit.js create mode 100644 packages/edit-site/src/components/site-editor-routes/pages-view.js create mode 100644 packages/edit-site/src/components/site-editor-routes/patterns-edit.js create mode 100644 packages/edit-site/src/components/site-editor-routes/patterns-view.js create mode 100644 packages/edit-site/src/components/site-editor-routes/styles-edit.js create mode 100644 packages/edit-site/src/components/site-editor-routes/styles-view.js create mode 100644 packages/edit-site/src/components/site-editor-routes/templates-edit.js create mode 100644 packages/edit-site/src/components/site-editor-routes/templates-list-view.js create mode 100644 packages/edit-site/src/components/site-editor-routes/templates-view.js diff --git a/packages/edit-site/src/components/app/index.js b/packages/edit-site/src/components/app/index.js index 452c36014f5db9..133a376c9c246d 100644 --- a/packages/edit-site/src/components/app/index.js +++ b/packages/edit-site/src/components/app/index.js @@ -20,8 +20,9 @@ import { unlock } from '../../lock-unlock'; import { useCommonCommands } from '../../hooks/commands/use-common-commands'; import { useEditModeCommands } from '../../hooks/commands/use-edit-mode-commands'; import useInitEditedEntityFromURL from '../sync-state-with-url/use-init-edited-entity-from-url'; -import useLayoutAreas from '../layout/router'; +import useActiveRoute from '../layout/router'; import useSetCommandContext from '../../hooks/commands/use-set-command-context'; +import { useRegisterSiteEditorRoutes } from '../site-editor-routes'; const { RouterProvider } = unlock( routerPrivateApis ); const { GlobalStylesProvider } = unlock( editorPrivateApis ); @@ -32,7 +33,8 @@ function AppLayout() { useEditModeCommands(); useCommonCommands(); useSetCommandContext(); - const route = useLayoutAreas(); + useRegisterSiteEditorRoutes(); + const route = useActiveRoute(); return <Layout route={ route } />; } diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index 2619f7c96dcf74..d02f2905f24d85 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -68,9 +68,9 @@ export default function Layout( { route } ) { const isEditorLoading = useIsSiteEditorLoading(); const [ isResizableFrameOversized, setIsResizableFrameOversized ] = useState( false ); - const { key: routeKey, areas, widths } = route; + const { name: routeKey, areas, widths } = route; const animationRef = useMovingAnimation( { - triggerAnimationOnChange: canvasMode + '__' + routeKey, + triggerAnimationOnChange: canvasMode, } ); const [ backgroundColor ] = useGlobalStyle( 'color.background' ); diff --git a/packages/edit-site/src/components/layout/router.js b/packages/edit-site/src/components/layout/router.js index 3fd0cc560d9433..912a837555e0d1 100644 --- a/packages/edit-site/src/components/layout/router.js +++ b/packages/edit-site/src/components/layout/router.js @@ -2,31 +2,19 @@ * WordPress dependencies */ import { privateApis as routerPrivateApis } from '@wordpress/router'; -import { __ } from '@wordpress/i18n'; -import { useEffect } from '@wordpress/element'; +import { useEffect, useMemo } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ import { unlock } from '../../lock-unlock'; -import Editor from '../editor'; -import PostList from '../post-list'; -import PagePatterns from '../page-patterns'; -import PageTemplates from '../page-templates'; -import SidebarNavigationScreen from '../sidebar-navigation-screen'; -import SidebarNavigationScreenGlobalStyles from '../sidebar-navigation-screen-global-styles'; -import SidebarNavigationScreenMain from '../sidebar-navigation-screen-main'; -import SidebarNavigationScreenNavigationMenus from '../sidebar-navigation-screen-navigation-menus'; -import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse'; -import SidebarNavigationScreenPatterns from '../sidebar-navigation-screen-patterns'; -import SidebarNavigationScreenNavigationMenu from '../sidebar-navigation-screen-navigation-menu'; -import DataViewsSidebarContent from '../sidebar-dataviews'; import { NAVIGATION_POST_TYPE, PATTERN_TYPES, TEMPLATE_PART_POST_TYPE, TEMPLATE_POST_TYPE, } from '../../utils/constants'; -import { PostEdit } from '../post-edit'; +import { store as editSiteStore } from '../../store'; const { useLocation, useHistory } = unlock( routerPrivateApis ); @@ -73,129 +61,26 @@ function useRedirectOldPaths() { }, [ history, params ] ); } -export default function useLayoutAreas() { +export default function useActiveRoute() { const { params } = useLocation(); - const { postType, postId, path, layout, isCustom, canvas, quickEdit } = - params; - const hasEditCanvasMode = canvas === 'edit'; useRedirectOldPaths(); - - // Page list - if ( postType === 'page' ) { - const isListLayout = layout === 'list' || ! layout; - const showQuickEdit = quickEdit && ! isListLayout; - return { - key: 'pages', - areas: { - sidebar: ( - <SidebarNavigationScreen - title={ __( 'Pages' ) } - backPath={ {} } - content={ <DataViewsSidebarContent /> } - /> - ), - content: <PostList postType={ postType } />, - preview: ! showQuickEdit && - ( isListLayout || hasEditCanvasMode ) && <Editor />, - mobile: hasEditCanvasMode ? ( - <Editor /> - ) : ( - <PostList postType={ postType } /> - ), - edit: showQuickEdit && ( - <PostEdit postType={ postType } postId={ postId } /> - ), - }, - widths: { - content: isListLayout ? 380 : undefined, - edit: showQuickEdit ? 380 : undefined, - }, - }; - } - - // Templates - if ( postType === TEMPLATE_POST_TYPE ) { - const isListLayout = isCustom !== 'true' && layout === 'list'; - return { - key: 'templates', - areas: { - sidebar: ( - <SidebarNavigationScreenTemplatesBrowse backPath={ {} } /> - ), - content: <PageTemplates />, - preview: ( isListLayout || hasEditCanvasMode ) && <Editor />, - mobile: hasEditCanvasMode ? <Editor /> : <PageTemplates />, - }, - widths: { - content: isListLayout ? 380 : undefined, - }, - }; - } - - // Patterns - if ( - [ TEMPLATE_PART_POST_TYPE, PATTERN_TYPES.user ].includes( postType ) - ) { - return { - key: 'patterns', - areas: { - sidebar: <SidebarNavigationScreenPatterns backPath={ {} } />, - content: <PagePatterns />, - mobile: hasEditCanvasMode ? <Editor /> : <PagePatterns />, - preview: hasEditCanvasMode && <Editor />, - }, - }; - } - - // Styles - if ( path === '/wp_global_styles' ) { - return { - key: 'styles', - areas: { - sidebar: ( - <SidebarNavigationScreenGlobalStyles backPath={ {} } /> - ), - preview: <Editor />, - mobile: hasEditCanvasMode && <Editor />, - }, - }; - } - - // Navigation - if ( postType === NAVIGATION_POST_TYPE ) { - if ( postId ) { + const routes = useSelect( ( select ) => { + return unlock( select( editSiteStore ) ).getRoutes(); + }, [] ); + return useMemo( () => { + const matchedRoute = routes.find( ( route ) => route.match( params ) ); + if ( ! matchedRoute ) { return { - key: 'navigation', - areas: { - sidebar: ( - <SidebarNavigationScreenNavigationMenu - backPath={ { postType: NAVIGATION_POST_TYPE } } - /> - ), - preview: <Editor />, - mobile: hasEditCanvasMode && <Editor />, - }, + key: 404, + areas: {}, + widths: {}, }; } + return { - key: 'navigation', - areas: { - sidebar: ( - <SidebarNavigationScreenNavigationMenus backPath={ {} } /> - ), - preview: <Editor />, - mobile: hasEditCanvasMode && <Editor />, - }, + name: matchedRoute.name, + areas: matchedRoute.areas, + widths: matchedRoute.widths, }; - } - - // Fallback shows the home page preview - return { - key: 'default', - areas: { - sidebar: <SidebarNavigationScreenMain />, - preview: <Editor />, - mobile: hasEditCanvasMode && <Editor />, - }, - }; + }, [ routes, params ] ); } diff --git a/packages/edit-site/src/components/posts-app/index.js b/packages/edit-site/src/components/posts-app/index.js index 12bdf33711031c..8b5377bb2e65bd 100644 --- a/packages/edit-site/src/components/posts-app/index.js +++ b/packages/edit-site/src/components/posts-app/index.js @@ -12,7 +12,7 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; */ import useInitEditedEntityFromURL from '../sync-state-with-url/use-init-edited-entity-from-url'; import Layout from '../layout'; -import useLayoutAreas from './router'; +import useActiveRoute from './router'; import { unlock } from '../../lock-unlock'; const { RouterProvider } = unlock( routerPrivateApis ); @@ -21,7 +21,7 @@ const { GlobalStylesProvider } = unlock( editorPrivateApis ); function PostsLayout() { // This ensures the edited entity id and type are initialized properly. useInitEditedEntityFromURL(); - const route = useLayoutAreas(); + const route = useActiveRoute(); return <Layout route={ route } />; } diff --git a/packages/edit-site/src/components/posts-app/router.js b/packages/edit-site/src/components/posts-app/router.js index 5ffbe1831f2a24..de89567b262094 100644 --- a/packages/edit-site/src/components/posts-app/router.js +++ b/packages/edit-site/src/components/posts-app/router.js @@ -17,7 +17,7 @@ import PostList from '../post-list'; const { useLocation } = unlock( routerPrivateApis ); -export default function useLayoutAreas() { +export default function useActiveRoute() { const { params = {} } = useLocation(); const { postType, layout, canvas } = params; const labels = useSelect( @@ -31,7 +31,7 @@ export default function useLayoutAreas() { if ( [ 'post' ].includes( postType ) ) { const isListLayout = layout === 'list' || ! layout; return { - key: 'posts-list', + name: 'posts-list', areas: { sidebar: ( <SidebarNavigationScreen @@ -59,7 +59,7 @@ export default function useLayoutAreas() { // Fallback shows the home page preview return { - key: 'default', + name: 'default', areas: { sidebar: <SidebarNavigationScreenMain />, preview: <Editor isPostsList />, diff --git a/packages/edit-site/src/components/site-editor-routes/home-edit.js b/packages/edit-site/src/components/site-editor-routes/home-edit.js new file mode 100644 index 00000000000000..f6e6499254082f --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/home-edit.js @@ -0,0 +1,17 @@ +/** + * Internal dependencies + */ +import Editor from '../editor'; +import SidebarNavigationScreenMain from '../sidebar-navigation-screen-main'; + +export const homeEditRoute = { + name: 'home-edit', + match: ( params ) => { + return params.canvas === 'edit'; + }, + areas: { + sidebar: <SidebarNavigationScreenMain />, + preview: <Editor />, + mobile: <Editor />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/home-view.js b/packages/edit-site/src/components/site-editor-routes/home-view.js new file mode 100644 index 00000000000000..63d3d021e82083 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/home-view.js @@ -0,0 +1,16 @@ +/** + * Internal dependencies + */ +import Editor from '../editor'; +import SidebarNavigationScreenMain from '../sidebar-navigation-screen-main'; + +export const homeViewRoute = { + name: 'home-view', + match: ( params ) => { + return params.canvas !== 'edit'; + }, + areas: { + sidebar: <SidebarNavigationScreenMain />, + preview: <Editor />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/index.js b/packages/edit-site/src/components/site-editor-routes/index.js new file mode 100644 index 00000000000000..ddc37b353885c1 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/index.js @@ -0,0 +1,60 @@ +/** + * WordPress dependencies + */ +import { useRegistry, useDispatch } from '@wordpress/data'; +import { useEffect } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; +import { store as siteEditorStore } from '../../store'; +import { homeViewRoute } from './home-view'; +import { homeEditRoute } from './home-edit'; +import { navigationViewRoute } from './navigation-view'; +import { navigationEditRoute } from './navigation-edit'; +import { navigationItemEditRoute } from './navigation-item-edit'; +import { navigationItemViewRoute } from './navigation-item-view'; +import { stylesEditRoute } from './styles-edit'; +import { stylesViewRoute } from './styles-view'; +import { patternsEditRoute } from './patterns-edit'; +import { patternsViewRoute } from './patterns-view'; +import { templatesEditRoute } from './templates-edit'; +import { templatesListViewRoute } from './templates-list-view'; +import { templatesViewRoute } from './templates-view'; +import { pagesViewRoute } from './pages-view'; +import { pagesEditRoute } from './pages-edit'; +import { pagesListViewRoute } from './pages-list-view'; +import { pagesListViewQuickEditRoute } from './pages-list-view-quick-edit'; +import { pagesViewQuickEditRoute } from './pages-view-quick-edit'; + +const routes = [ + pagesListViewQuickEditRoute, + pagesListViewRoute, + pagesViewQuickEditRoute, + pagesViewRoute, + pagesEditRoute, + templatesEditRoute, + templatesListViewRoute, + templatesViewRoute, + patternsViewRoute, + patternsEditRoute, + stylesViewRoute, + stylesEditRoute, + navigationItemViewRoute, + navigationItemEditRoute, + navigationViewRoute, + navigationEditRoute, + homeViewRoute, + homeEditRoute, +]; + +export function useRegisterSiteEditorRoutes() { + const registry = useRegistry(); + const { registerRoute } = unlock( useDispatch( siteEditorStore ) ); + useEffect( () => { + registry.batch( () => { + routes.forEach( registerRoute ); + } ); + }, [ registry, registerRoute ] ); +} diff --git a/packages/edit-site/src/components/site-editor-routes/navigation-edit.js b/packages/edit-site/src/components/site-editor-routes/navigation-edit.js new file mode 100644 index 00000000000000..fdba963c41d0cb --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/navigation-edit.js @@ -0,0 +1,22 @@ +/** + * Internal dependencies + */ +import { NAVIGATION_POST_TYPE } from '../../utils/constants'; +import Editor from '../editor'; +import SidebarNavigationScreenNavigationMenus from '../sidebar-navigation-screen-navigation-menus'; + +export const navigationEditRoute = { + name: 'navigation-edit', + match: ( params ) => { + return ( + params.postType === NAVIGATION_POST_TYPE && + ! params.postId && + params.canvas === 'edit' + ); + }, + areas: { + sidebar: <SidebarNavigationScreenNavigationMenus backPath={ {} } />, + preview: <Editor />, + mobile: <Editor />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/navigation-item-edit.js b/packages/edit-site/src/components/site-editor-routes/navigation-item-edit.js new file mode 100644 index 00000000000000..b03cdbd995ac7c --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/navigation-item-edit.js @@ -0,0 +1,26 @@ +/** + * Internal dependencies + */ +import { NAVIGATION_POST_TYPE } from '../../utils/constants'; +import Editor from '../editor'; +import SidebarNavigationScreenNavigationMenu from '../sidebar-navigation-screen-navigation-menu'; + +export const navigationItemEditRoute = { + name: 'navigation-item-edit', + match: ( params ) => { + return ( + params.postType === NAVIGATION_POST_TYPE && + !! params.postId && + params.canvas === 'edit' + ); + }, + areas: { + sidebar: ( + <SidebarNavigationScreenNavigationMenu + backPath={ { postType: NAVIGATION_POST_TYPE } } + /> + ), + preview: <Editor />, + mobile: <Editor />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/navigation-item-view.js b/packages/edit-site/src/components/site-editor-routes/navigation-item-view.js new file mode 100644 index 00000000000000..d04a03a8f9df38 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/navigation-item-view.js @@ -0,0 +1,25 @@ +/** + * Internal dependencies + */ +import { NAVIGATION_POST_TYPE } from '../../utils/constants'; +import Editor from '../editor'; +import SidebarNavigationScreenNavigationMenu from '../sidebar-navigation-screen-navigation-menu'; + +export const navigationItemViewRoute = { + name: 'navigation-item-view', + match: ( params ) => { + return ( + params.postType === NAVIGATION_POST_TYPE && + !! params.postId && + params.canvas !== 'edit' + ); + }, + areas: { + sidebar: ( + <SidebarNavigationScreenNavigationMenu + backPath={ { postType: NAVIGATION_POST_TYPE } } + /> + ), + preview: <Editor />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/navigation-view.js b/packages/edit-site/src/components/site-editor-routes/navigation-view.js new file mode 100644 index 00000000000000..59c38a2f1d099a --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/navigation-view.js @@ -0,0 +1,21 @@ +/** + * Internal dependencies + */ +import { NAVIGATION_POST_TYPE } from '../../utils/constants'; +import Editor from '../editor'; +import SidebarNavigationScreenNavigationMenus from '../sidebar-navigation-screen-navigation-menus'; + +export const navigationViewRoute = { + name: 'navigation-view', + match: ( params ) => { + return ( + params.postType === NAVIGATION_POST_TYPE && + ! params.postId && + params.canvas !== 'edit' + ); + }, + areas: { + sidebar: <SidebarNavigationScreenNavigationMenus backPath={ {} } />, + preview: <Editor />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/pages-edit.js b/packages/edit-site/src/components/site-editor-routes/pages-edit.js new file mode 100644 index 00000000000000..ef4c7efbfb09c2 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/pages-edit.js @@ -0,0 +1,35 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import PostList from '../post-list'; +import DataViewsSidebarContent from '../sidebar-dataviews'; +import SidebarNavigationScreen from '../sidebar-navigation-screen'; +import Editor from '../editor'; + +function PageList() { + return <PostList postType="page" />; +} + +export const pagesEditRoute = { + name: 'pages-edit', + match: ( params ) => { + return params.postType === 'page' && params.canvas === 'edit'; + }, + areas: { + sidebar: ( + <SidebarNavigationScreen + title={ __( 'Pages' ) } + backPath={ {} } + content={ <DataViewsSidebarContent /> } + /> + ), + content: <PageList />, + mobile: <Editor />, + preview: <Editor />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/pages-list-view-quick-edit.js b/packages/edit-site/src/components/site-editor-routes/pages-list-view-quick-edit.js new file mode 100644 index 00000000000000..9eb33e05a99bb0 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/pages-list-view-quick-edit.js @@ -0,0 +1,56 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; + +/** + * Internal dependencies + */ +import PostList from '../post-list'; +import DataViewsSidebarContent from '../sidebar-dataviews'; +import SidebarNavigationScreen from '../sidebar-navigation-screen'; +import { unlock } from '../../lock-unlock'; +import { PostEdit } from '../post-edit'; +import Editor from '../editor'; + +const { useLocation } = unlock( routerPrivateApis ); + +function PageList() { + return <PostList postType="page" />; +} + +function PageQuickEdit() { + const { params } = useLocation(); + return <PostEdit postType="page" postId={ params.postId } />; +} + +export const pagesListViewQuickEditRoute = { + name: 'pages-list-view-quick-edit', + match: ( params ) => { + return ( + params.isCustom !== 'true' && + ( params.layout ?? 'list' ) === 'list' && + !! params.quickEdit && + params.postType === 'page' && + params.canvas !== 'edit' + ); + }, + areas: { + sidebar: ( + <SidebarNavigationScreen + title={ __( 'Pages' ) } + backPath={ {} } + content={ <DataViewsSidebarContent /> } + /> + ), + content: <PageList />, + mobile: <PageList />, + preview: <Editor />, + edit: <PageQuickEdit />, + }, + widths: { + content: 380, + edit: 380, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/pages-list-view.js b/packages/edit-site/src/components/site-editor-routes/pages-list-view.js new file mode 100644 index 00000000000000..74b39848e83f2b --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/pages-list-view.js @@ -0,0 +1,44 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import PostList from '../post-list'; +import DataViewsSidebarContent from '../sidebar-dataviews'; +import SidebarNavigationScreen from '../sidebar-navigation-screen'; +import Editor from '../editor'; + +function PageList() { + return <PostList postType="page" />; +} + +export const pagesListViewRoute = { + name: 'pages-list-view', + match: ( params ) => { + return ( + params.isCustom !== 'true' && + ( params.layout ?? 'list' ) === 'list' && + ! params.quickEdit && + params.postType === 'page' && + params.canvas !== 'edit' + ); + }, + areas: { + sidebar: ( + <SidebarNavigationScreen + title={ __( 'Pages' ) } + backPath={ {} } + content={ <DataViewsSidebarContent /> } + /> + ), + content: <PageList />, + preview: <Editor />, + mobile: <PageList />, + }, + widths: { + content: 380, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/pages-view-quick-edit.js b/packages/edit-site/src/components/site-editor-routes/pages-view-quick-edit.js new file mode 100644 index 00000000000000..907054364c8a93 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/pages-view-quick-edit.js @@ -0,0 +1,53 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; + +/** + * Internal dependencies + */ +import PostList from '../post-list'; +import DataViewsSidebarContent from '../sidebar-dataviews'; +import SidebarNavigationScreen from '../sidebar-navigation-screen'; +import { unlock } from '../../lock-unlock'; +import { PostEdit } from '../post-edit'; + +const { useLocation } = unlock( routerPrivateApis ); + +function PageList() { + return <PostList postType="page" />; +} + +function PageQuickEdit() { + const { params } = useLocation(); + return <PostEdit postType="page" postId={ params.postId } />; +} + +export const pagesViewQuickEditRoute = { + name: 'pages-view-quick-edit', + match: ( params ) => { + return ( + ( params.isCustom === 'true' || + ( params.layout ?? 'list' ) !== 'list' ) && + !! params.quickEdit && + params.postType === 'page' && + params.canvas !== 'edit' + ); + }, + areas: { + sidebar: ( + <SidebarNavigationScreen + title={ __( 'Pages' ) } + backPath={ {} } + content={ <DataViewsSidebarContent /> } + /> + ), + content: <PageList />, + mobile: <PageList />, + edit: <PageQuickEdit />, + }, + widths: { + edit: 380, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/pages-view.js b/packages/edit-site/src/components/site-editor-routes/pages-view.js new file mode 100644 index 00000000000000..df7e211022cacf --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/pages-view.js @@ -0,0 +1,39 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import PostList from '../post-list'; +import DataViewsSidebarContent from '../sidebar-dataviews'; +import SidebarNavigationScreen from '../sidebar-navigation-screen'; + +function PageList() { + return <PostList postType="page" />; +} + +export const pagesViewRoute = { + name: 'pages-view', + match: ( params ) => { + return ( + ( params.isCustom === 'true' || + ( params.layout ?? 'list' ) !== 'list' ) && + ! params.quickEdit && + params.postType === 'page' && + params.canvas !== 'edit' + ); + }, + areas: { + sidebar: ( + <SidebarNavigationScreen + title={ __( 'Pages' ) } + backPath={ {} } + content={ <DataViewsSidebarContent /> } + /> + ), + content: <PageList />, + mobile: <PageList />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/patterns-edit.js b/packages/edit-site/src/components/site-editor-routes/patterns-edit.js new file mode 100644 index 00000000000000..eaf1fd68020181 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/patterns-edit.js @@ -0,0 +1,24 @@ +/** + * Internal dependencies + */ +import Editor from '../editor'; +import SidebarNavigationScreenPatterns from '../sidebar-navigation-screen-patterns'; +import PagePatterns from '../page-patterns'; +import { PATTERN_TYPES, TEMPLATE_PART_POST_TYPE } from '../../utils/constants'; + +export const patternsEditRoute = { + name: 'patterns-edit', + match: ( params ) => { + return ( + [ TEMPLATE_PART_POST_TYPE, PATTERN_TYPES.user ].includes( + params.postType + ) && params.canvas === 'edit' + ); + }, + areas: { + sidebar: <SidebarNavigationScreenPatterns backPath={ {} } />, + content: <PagePatterns />, + mobile: <Editor />, + preview: <Editor />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/patterns-view.js b/packages/edit-site/src/components/site-editor-routes/patterns-view.js new file mode 100644 index 00000000000000..468f7f14abc139 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/patterns-view.js @@ -0,0 +1,22 @@ +/** + * Internal dependencies + */ +import SidebarNavigationScreenPatterns from '../sidebar-navigation-screen-patterns'; +import PagePatterns from '../page-patterns'; +import { PATTERN_TYPES, TEMPLATE_PART_POST_TYPE } from '../../utils/constants'; + +export const patternsViewRoute = { + name: 'patterns-view', + match: ( params ) => { + return ( + [ TEMPLATE_PART_POST_TYPE, PATTERN_TYPES.user ].includes( + params.postType + ) && params.canvas !== 'edit' + ); + }, + areas: { + sidebar: <SidebarNavigationScreenPatterns backPath={ {} } />, + content: <PagePatterns />, + mobile: <PagePatterns />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/styles-edit.js b/packages/edit-site/src/components/site-editor-routes/styles-edit.js new file mode 100644 index 00000000000000..ff52b957bc3609 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/styles-edit.js @@ -0,0 +1,17 @@ +/** + * Internal dependencies + */ +import Editor from '../editor'; +import SidebarNavigationScreenGlobalStyles from '../sidebar-navigation-screen-global-styles'; + +export const stylesEditRoute = { + name: 'styles-edit', + match: ( params ) => { + return params.path === '/wp_global_styles' && params.canvas === 'edit'; + }, + areas: { + sidebar: <SidebarNavigationScreenGlobalStyles backPath={ {} } />, + preview: <Editor />, + mobile: <Editor />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/styles-view.js b/packages/edit-site/src/components/site-editor-routes/styles-view.js new file mode 100644 index 00000000000000..856a610eb23677 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/styles-view.js @@ -0,0 +1,16 @@ +/** + * Internal dependencies + */ +import Editor from '../editor'; +import SidebarNavigationScreenGlobalStyles from '../sidebar-navigation-screen-global-styles'; + +export const stylesViewRoute = { + name: 'styles-view', + match: ( params ) => { + return params.path === '/wp_global_styles' && params.canvas !== 'edit'; + }, + areas: { + sidebar: <SidebarNavigationScreenGlobalStyles backPath={ {} } />, + preview: <Editor />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/templates-edit.js b/packages/edit-site/src/components/site-editor-routes/templates-edit.js new file mode 100644 index 00000000000000..488e9decc1888c --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/templates-edit.js @@ -0,0 +1,22 @@ +/** + * Internal dependencies + */ +import { TEMPLATE_POST_TYPE } from '../../utils/constants'; +import PageTemplates from '../page-templates'; +import Editor from '../editor'; +import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse'; + +export const templatesEditRoute = { + name: 'templates-edit', + match: ( params ) => { + return ( + params.postType === TEMPLATE_POST_TYPE && params.canvas === 'edit' + ); + }, + areas: { + sidebar: <SidebarNavigationScreenTemplatesBrowse backPath={ {} } />, + content: <PageTemplates />, + mobile: <Editor />, + preview: <Editor />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/templates-list-view.js b/packages/edit-site/src/components/site-editor-routes/templates-list-view.js new file mode 100644 index 00000000000000..7cdda1b13c0b47 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/templates-list-view.js @@ -0,0 +1,28 @@ +/** + * Internal dependencies + */ +import { TEMPLATE_POST_TYPE } from '../../utils/constants'; +import PageTemplates from '../page-templates'; +import Editor from '../editor'; +import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse'; + +export const templatesListViewRoute = { + name: 'templates-list-view', + match: ( params ) => { + return ( + params.isCustom !== 'true' && + params.layout === 'list' && + params.postType === TEMPLATE_POST_TYPE && + params.canvas !== 'edit' + ); + }, + areas: { + sidebar: <SidebarNavigationScreenTemplatesBrowse backPath={ {} } />, + content: <PageTemplates />, + mobile: <PageTemplates />, + preview: <Editor />, + }, + widths: { + content: 380, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/templates-view.js b/packages/edit-site/src/components/site-editor-routes/templates-view.js new file mode 100644 index 00000000000000..40fd88c0e60a61 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/templates-view.js @@ -0,0 +1,22 @@ +/** + * Internal dependencies + */ +import { TEMPLATE_POST_TYPE } from '../../utils/constants'; +import PageTemplates from '../page-templates'; +import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse'; + +export const templatesViewRoute = { + name: 'templates-view', + match: ( params ) => { + return ( + ( params.isCustom === 'true' || params.layout !== 'list' ) && + params.postType === TEMPLATE_POST_TYPE && + params.canvas !== 'edit' + ); + }, + areas: { + sidebar: <SidebarNavigationScreenTemplatesBrowse backPath={ {} } />, + content: <PageTemplates />, + mobile: <PageTemplates />, + }, +}; diff --git a/packages/edit-site/src/store/private-actions.js b/packages/edit-site/src/store/private-actions.js index 94bcc490b6fd60..1c5924a292765b 100644 --- a/packages/edit-site/src/store/private-actions.js +++ b/packages/edit-site/src/store/private-actions.js @@ -90,3 +90,10 @@ export const setEditorCanvasContainerView = view, } ); }; + +export function registerRoute( route ) { + return { + type: 'REGISTER_ROUTE', + route, + }; +} diff --git a/packages/edit-site/src/store/private-selectors.js b/packages/edit-site/src/store/private-selectors.js index 1f1f6e999fdb29..d0f1d3f4196008 100644 --- a/packages/edit-site/src/store/private-selectors.js +++ b/packages/edit-site/src/store/private-selectors.js @@ -19,3 +19,7 @@ export function getCanvasMode( state ) { export function getEditorCanvasContainerView( state ) { return state.editorCanvasContainerView; } + +export function getRoutes( state ) { + return state.routes; +} diff --git a/packages/edit-site/src/store/reducer.js b/packages/edit-site/src/store/reducer.js index 1e3d9c43f0eb34..951f004adc9af5 100644 --- a/packages/edit-site/src/store/reducer.js +++ b/packages/edit-site/src/store/reducer.js @@ -98,10 +98,20 @@ function editorCanvasContainerView( state = undefined, action ) { return state; } +function routes( state = [], action ) { + switch ( action.type ) { + case 'REGISTER_ROUTE': + return [ ...state, action.route ]; + } + + return state; +} + export default combineReducers( { settings, editedPost, saveViewPanel, canvasMode, editorCanvasContainerView, + routes, } ); From f83c59253907969de16e172eb5a0fc7bc1f90f9c Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 17 Oct 2024 14:04:32 +0100 Subject: [PATCH 1222/1908] Zoom-out: Rely on zoom-level instead of zoom-out mode (#66141) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> --- .../src/components/block-list/index.js | 6 +-- .../use-focus-first-element.js | 8 +-- .../use-selected-block-event-handlers.js | 27 +++------- .../use-block-props/use-zoom-out-mode-exit.js | 24 ++------- .../block-list/use-in-between-inserter.js | 2 +- .../src/components/block-toolbar/index.js | 6 +-- .../src/components/block-tools/index.js | 6 +-- .../components/block-tools/insertion-point.js | 7 +-- .../src/components/inner-blocks/index.js | 4 +- .../pattern-category-previews.js | 4 +- .../src/components/inserter/menu.js | 4 +- .../src/components/list-view/appender.js | 11 ++-- .../src/components/tool-selector/index.js | 3 +- .../components/use-block-drop-zone/index.js | 8 +-- .../components/writing-flow/use-tab-nav.js | 3 +- .../block-editor/src/hooks/use-zoom-out.js | 46 +++++----------- packages/block-editor/src/store/actions.js | 43 +-------------- .../block-editor/src/store/private-actions.js | 54 +++++++++++++++++-- .../src/store/private-selectors.js | 25 +-------- packages/block-editor/src/store/selectors.js | 9 ++-- .../edit-post/src/components/layout/index.js | 4 +- .../components/layout/use-should-iframe.js | 9 +++- .../src/components/document-tools/index.js | 4 +- .../src/components/inserter-sidebar/index.js | 9 ++-- .../src/components/zoom-out-toggle/index.js | 3 +- packages/editor/src/store/selectors.js | 5 +- 26 files changed, 133 insertions(+), 201 deletions(-) diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index e2e019d4a9bf69..8e8f69f46ae276 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -181,8 +181,8 @@ function Items( { __unstableGetVisibleBlocks, getTemplateLock, getBlockEditingMode, - __unstableGetEditorMode, isSectionBlock, + isZoomOut: _isZoomOut, } = unlock( select( blockEditorStore ) ); const _order = getBlockOrder( rootClientId ); @@ -200,13 +200,13 @@ function Items( { order: _order, selectedBlocks: getSelectedBlockClientIds(), visibleBlocks: __unstableGetVisibleBlocks(), - isZoomOut: __unstableGetEditorMode() === 'zoom-out', + isZoomOut: _isZoomOut(), shouldRenderAppender: ! isSectionBlock( rootClientId ) && getBlockEditingMode( rootClientId ) !== 'disabled' && ! getTemplateLock( rootClientId ) && hasAppender && - __unstableGetEditorMode() !== 'zoom-out' && + ! _isZoomOut() && ( hasCustomAppender || rootClientId === selectedBlockClientId || ( ! rootClientId && diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js b/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js index 27f72d1a100d3e..26f7cca2990d89 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js @@ -15,6 +15,7 @@ import { useSelect } from '@wordpress/data'; */ import { isInsideRootBlock } from '../../../utils/dom'; import { store as blockEditorStore } from '../../../store'; +import { unlock } from '../../../lock-unlock'; /** @typedef {import('@wordpress/element').RefObject} RefObject */ @@ -28,15 +29,16 @@ import { store as blockEditorStore } from '../../../store'; */ export function useFocusFirstElement( { clientId, initialPosition } ) { const ref = useRef(); - const { isBlockSelected, isMultiSelecting, __unstableGetEditorMode } = - useSelect( blockEditorStore ); + const { isBlockSelected, isMultiSelecting, isZoomOut } = unlock( + useSelect( blockEditorStore ) + ); useEffect( () => { // Check if the block is still selected at the time this effect runs. if ( ! isBlockSelected( clientId ) || isMultiSelecting() || - __unstableGetEditorMode() === 'zoom-out' + isZoomOut() ) { return; } diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-selected-block-event-handlers.js b/packages/block-editor/src/components/block-list/use-block-props/use-selected-block-event-handlers.js index 19b778ca8fccfc..68f8a671adbe9a 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-selected-block-event-handlers.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-selected-block-event-handlers.js @@ -21,18 +21,12 @@ import { unlock } from '../../../lock-unlock'; * @param {string} clientId Block client ID. */ export function useEventHandlers( { clientId, isSelected } ) { - const { - getBlockRootClientId, - getBlockIndex, - isZoomOut, - __unstableGetEditorMode, - } = unlock( useSelect( blockEditorStore ) ); - const { - insertAfterBlock, - removeBlock, - __unstableSetEditorMode, - resetZoomLevel, - } = unlock( useDispatch( blockEditorStore ) ); + const { getBlockRootClientId, getBlockIndex, isZoomOut } = unlock( + useSelect( blockEditorStore ) + ); + const { insertAfterBlock, removeBlock, resetZoomLevel } = unlock( + useDispatch( blockEditorStore ) + ); return useRefEffect( ( node ) => { @@ -66,12 +60,7 @@ export function useEventHandlers( { clientId, isSelected } ) { event.preventDefault(); - if ( - keyCode === ENTER && - __unstableGetEditorMode() === 'zoom-out' && - isZoomOut() - ) { - __unstableSetEditorMode( 'edit' ); + if ( keyCode === ENTER && isZoomOut() ) { resetZoomLevel(); } else if ( keyCode === ENTER ) { insertAfterBlock( clientId ); @@ -105,8 +94,6 @@ export function useEventHandlers( { clientId, isSelected } ) { getBlockIndex, insertAfterBlock, removeBlock, - __unstableGetEditorMode, - __unstableSetEditorMode, isZoomOut, resetZoomLevel, ] diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js b/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js index 494694952110bb..d77af3ef89c1ec 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js @@ -14,22 +14,13 @@ import { unlock } from '../../../lock-unlock'; * Allows Zoom Out mode to be exited by double clicking in the selected block. */ export function useZoomOutModeExit() { - const { getSettings, isZoomOut, __unstableGetEditorMode } = unlock( - useSelect( blockEditorStore ) - ); - - const { __unstableSetEditorMode, resetZoomLevel } = unlock( - useDispatch( blockEditorStore ) - ); + const { getSettings, isZoomOut } = unlock( useSelect( blockEditorStore ) ); + const { resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); return useRefEffect( ( node ) => { function onDoubleClick( event ) { - // In "compose" mode. - const composeMode = - __unstableGetEditorMode() === 'zoom-out' && isZoomOut(); - - if ( ! composeMode ) { + if ( ! isZoomOut() ) { return; } @@ -43,7 +34,6 @@ export function useZoomOutModeExit() { ) { __experimentalSetIsInserterOpened( false ); } - __unstableSetEditorMode( 'edit' ); resetZoomLevel(); } } @@ -54,12 +44,6 @@ export function useZoomOutModeExit() { node.removeEventListener( 'dblclick', onDoubleClick ); }; }, - [ - getSettings, - __unstableSetEditorMode, - __unstableGetEditorMode, - isZoomOut, - resetZoomLevel, - ] + [ getSettings, isZoomOut, resetZoomLevel ] ); } 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 2b76804785a576..71eda2558f7930 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 @@ -18,7 +18,7 @@ export function useInBetweenInserter() { const isInBetweenInserterDisabled = useSelect( ( select ) => select( blockEditorStore ).getSettings().isDistractionFree || - select( blockEditorStore ).__unstableGetEditorMode() === 'zoom-out', + unlock( select( blockEditorStore ) ).isZoomOut(), [] ); const { diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index d6a0985fef3610..58a7b2b09bb2cd 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -81,7 +81,7 @@ export function PrivateBlockToolbar( { getBlockParentsByBlockName, getTemplateLock, getParentSectionBlock, - isZoomOutMode, + isZoomOut, } = unlock( select( blockEditorStore ) ); const selectedBlockClientIds = getSelectedBlockClientIds(); const selectedBlockClientId = selectedBlockClientIds[ 0 ]; @@ -122,7 +122,7 @@ export function PrivateBlockToolbar( { shouldShowVisualToolbar: isValid && isVisual, toolbarKey: `${ selectedBlockClientId }${ parentClientId }`, showParentSelector: - ! isZoomOutMode() && + ! isZoomOut() && parentBlockType && getBlockEditingMode( parentClientId ) !== 'disabled' && hasBlockSupport( @@ -134,7 +134,7 @@ export function PrivateBlockToolbar( { isUsingBindings: _isUsingBindings, hasParentPattern: _hasParentPattern, hasContentOnlyLocking: _hasTemplateLock, - showShuffleButton: isZoomOutMode(), + showShuffleButton: isZoomOut(), }; }, [] ); diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index e07e9b8f4bf5c1..700b345be20274 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -30,21 +30,19 @@ function selector( select ) { getSelectedBlockClientId, getFirstMultiSelectedBlockClientId, getSettings, - __unstableGetEditorMode, isTyping, isDragging, + isZoomOut, } = unlock( select( blockEditorStore ) ); const clientId = getSelectedBlockClientId() || getFirstMultiSelectedBlockClientId(); - const editorMode = __unstableGetEditorMode(); - return { clientId, hasFixedToolbar: getSettings().hasFixedToolbar, isTyping: isTyping(), - isZoomOutMode: editorMode === 'zoom-out', + isZoomOutMode: isZoomOut(), isDragging: isDragging(), }; } 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 891a32eaa5dc9c..6c54993b23bcaa 100644 --- a/packages/block-editor/src/components/block-tools/insertion-point.js +++ b/packages/block-editor/src/components/block-tools/insertion-point.js @@ -18,6 +18,7 @@ import Inserter from '../inserter'; import { store as blockEditorStore } from '../../store'; import BlockPopoverInbetween from '../block-popover/inbetween'; import BlockDropZonePopover from '../block-popover/drop-zone'; +import { unlock } from '../../lock-unlock'; export const InsertionPointOpenRef = createContext(); @@ -47,8 +48,8 @@ function InbetweenInsertionPointPopover( { getPreviousBlockClientId, getNextBlockClientId, getSettings, - __unstableGetEditorMode, - } = select( blockEditorStore ); + isZoomOut, + } = unlock( select( blockEditorStore ) ); const insertionPoint = getBlockInsertionPoint(); const order = getBlockOrder( insertionPoint.rootClientId ); @@ -78,7 +79,7 @@ function InbetweenInsertionPointPopover( { rootClientId: insertionPoint.rootClientId, isDistractionFree: settings.isDistractionFree, isInserterShown: insertionPoint?.__unstableWithInserter, - isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', + isZoomOutMode: isZoomOut(), }; }, [] ); const { getBlockEditingMode } = useSelect( blockEditorStore ); diff --git a/packages/block-editor/src/components/inner-blocks/index.js b/packages/block-editor/src/components/inner-blocks/index.js index 1583031a8ea18d..e79c188018cb50 100644 --- a/packages/block-editor/src/components/inner-blocks/index.js +++ b/packages/block-editor/src/components/inner-blocks/index.js @@ -195,7 +195,7 @@ export function useInnerBlocksProps( props = {}, options = {} ) { ( select ) => { const { getBlockName, - __unstableGetEditorMode, + isZoomOut, getTemplateLock, getBlockRootClientId, getBlockEditingMode, @@ -216,7 +216,7 @@ export function useInnerBlocksProps( props = {}, options = {} ) { _isDropZoneDisabled = blockEditingMode === 'disabled'; - if ( __unstableGetEditorMode() === 'zoom-out' ) { + if ( isZoomOut() ) { // In zoom out mode, we want to disable the drop zone for the sections. // The inner blocks belonging to the section drop zone is // already disabled by the blocks themselves being disabled. diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js index 61716f616dafa9..835015704c944b 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js @@ -34,6 +34,7 @@ import { INSERTER_PATTERN_TYPES, } from './utils'; import { store as blockEditorStore } from '../../../store'; +import { unlock } from '../../../lock-unlock'; const noop = () => {}; @@ -45,8 +46,7 @@ export function PatternCategoryPreviews( { showTitlesAsTooltip, } ) { const isZoomOutMode = useSelect( - ( select ) => - select( blockEditorStore ).__unstableGetEditorMode() === 'zoom-out', + ( select ) => unlock( select( blockEditorStore ) ).isZoomOut(), [] ); const [ allPatterns, , onClickPattern ] = usePatternsState( diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index bdd4ff11abceee..915a36d242ba26 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -33,6 +33,7 @@ import useInsertionPoint from './hooks/use-insertion-point'; import { store as blockEditorStore } from '../../store'; import TabbedSidebar from '../tabbed-sidebar'; import { useZoomOut } from '../../hooks/use-zoom-out'; +import { unlock } from '../../lock-unlock'; const NOOP = () => {}; function InserterMenu( @@ -54,8 +55,7 @@ function InserterMenu( ref ) { const isZoomOutMode = useSelect( - ( select ) => - select( blockEditorStore ).__unstableGetEditorMode() === 'zoom-out', + ( select ) => unlock( select( blockEditorStore ) ).isZoomOut(), [] ); const [ filterValue, setFilterValue, delayedFilterValue ] = diff --git a/packages/block-editor/src/components/list-view/appender.js b/packages/block-editor/src/components/list-view/appender.js index ec46a1d211ab65..8cd515499b1a61 100644 --- a/packages/block-editor/src/components/list-view/appender.js +++ b/packages/block-editor/src/components/list-view/appender.js @@ -15,6 +15,7 @@ import useBlockDisplayTitle from '../block-title/use-block-display-title'; import { useListViewContext } from './context'; import Inserter from '../inserter'; import AriaReferencedText from './aria-referenced-text'; +import { unlock } from '../../lock-unlock'; export const Appender = forwardRef( ( { nestingLevel, blockCount, clientId, ...props }, ref ) => { @@ -23,13 +24,11 @@ export const Appender = forwardRef( const instanceId = useInstanceId( Appender ); const hideInserter = useSelect( ( select ) => { - const { getTemplateLock, __unstableGetEditorMode } = - select( blockEditorStore ); - - return ( - !! getTemplateLock( clientId ) || - __unstableGetEditorMode() === 'zoom-out' + const { getTemplateLock, isZoomOut } = unlock( + select( blockEditorStore ) ); + + return !! getTemplateLock( clientId ) || isZoomOut(); }, [ clientId ] ); diff --git a/packages/block-editor/src/components/tool-selector/index.js b/packages/block-editor/src/components/tool-selector/index.js index 14a7f00593e196..d4ba5d58ea61eb 100644 --- a/packages/block-editor/src/components/tool-selector/index.js +++ b/packages/block-editor/src/components/tool-selector/index.js @@ -36,7 +36,7 @@ function ToolSelector( props, ref ) { ( select ) => select( blockEditorStore ).__unstableGetEditorMode(), [] ); - const { resetZoomLevel, __unstableSetEditorMode } = unlock( + const { __unstableSetEditorMode } = unlock( useDispatch( blockEditorStore ) ); @@ -68,7 +68,6 @@ function ToolSelector( props, ref ) { mode === 'navigation' ? 'navigation' : 'edit' } onSelect={ ( newMode ) => { - resetZoomLevel(); __unstableSetEditorMode( newMode ); } } choices={ [ 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 ff4d52aaa493bc..64424178461bcf 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 @@ -330,7 +330,7 @@ export default function useBlockDropZone( { getAllowedBlocks, isDragging, isGroupable, - isZoomOutMode, + isZoomOut, getSectionRootClientId, } = unlock( useSelect( blockEditorStore ) ); const { @@ -383,7 +383,7 @@ export default function useBlockDropZone( { // do not allow dropping as the drop target is not within the root (that which is // treated as "the content" by Zoom Out Mode). if ( - isZoomOutMode() && + isZoomOut() && sectionRootClientId !== targetRootClientId ) { return; @@ -439,7 +439,7 @@ export default function useBlockDropZone( { const [ targetIndex, operation, nearestSide ] = dropTargetPosition; - if ( isZoomOutMode() && operation !== 'insert' ) { + if ( isZoomOut() && operation !== 'insert' ) { return; } @@ -514,7 +514,7 @@ export default function useBlockDropZone( { getDraggedBlockClientIds, getBlockType, getSectionRootClientId, - isZoomOutMode, + isZoomOut, getBlocks, getBlockListSettings, dropZoneElement, diff --git a/packages/block-editor/src/components/writing-flow/use-tab-nav.js b/packages/block-editor/src/components/writing-flow/use-tab-nav.js index 216e7b6e04ad57..16a18358fb2ede 100644 --- a/packages/block-editor/src/components/writing-flow/use-tab-nav.js +++ b/packages/block-editor/src/components/writing-flow/use-tab-nav.js @@ -27,7 +27,6 @@ export default function useTabNav() { getLastFocus, getSectionRootClientId, isZoomOut, - __unstableGetEditorMode, } = unlock( useSelect( blockEditorStore ) ); const { setLastFocus } = unlock( useDispatch( blockEditorStore ) ); @@ -54,7 +53,7 @@ export default function useTabNav() { } } // In "compose" mode without a selected ID, we want to place focus on the section root when tabbing to the canvas. - else if ( __unstableGetEditorMode() === 'zoom-out' && isZoomOut() ) { + else if ( isZoomOut() ) { const sectionRootClientId = getSectionRootClientId(); const sectionBlocks = getBlockOrder( sectionRootClientId ); diff --git a/packages/block-editor/src/hooks/use-zoom-out.js b/packages/block-editor/src/hooks/use-zoom-out.js index 23511487a54bf7..23f7fbc4bd59a1 100644 --- a/packages/block-editor/src/hooks/use-zoom-out.js +++ b/packages/block-editor/src/hooks/use-zoom-out.js @@ -2,62 +2,42 @@ * WordPress dependencies */ import { useSelect, useDispatch } from '@wordpress/data'; -import { useEffect, useRef } from '@wordpress/element'; +import { useEffect } from '@wordpress/element'; /** * Internal dependencies */ import { store as blockEditorStore } from '../store'; import { unlock } from '../lock-unlock'; + /** * A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode. * * @param {boolean} zoomOut If we should enter into zoomOut mode or not */ export function useZoomOut( zoomOut = true ) { - const { __unstableSetEditorMode, setZoomLevel } = unlock( + const { setZoomLevel, resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); - const { __unstableGetEditorMode } = unlock( useSelect( blockEditorStore ) ); - - const originalEditingModeRef = useRef( null ); - const mode = __unstableGetEditorMode(); + const { isZoomOut } = unlock( useSelect( blockEditorStore ) ); useEffect( () => { - // Only set this on mount so we know what to return to when we unmount. - if ( ! originalEditingModeRef.current ) { - originalEditingModeRef.current = mode; - } + const isZoomOutOnMount = isZoomOut(); return () => { - // We need to use __unstableGetEditorMode() here and not `mode`, as mode may not update on unmount - if ( - __unstableGetEditorMode() === 'zoom-out' && - __unstableGetEditorMode() !== originalEditingModeRef.current - ) { - __unstableSetEditorMode( originalEditingModeRef.current ); - setZoomLevel( 100 ); + if ( isZoomOutOnMount ) { + setZoomLevel( 50 ); + } else { + resetZoomLevel(); } }; }, [] ); - // The effect opens the zoom-out view if we want it open and it's not currently in zoom-out mode. useEffect( () => { - if ( zoomOut && mode !== 'zoom-out' ) { - __unstableSetEditorMode( 'zoom-out' ); + if ( zoomOut ) { setZoomLevel( 50 ); - } else if ( - ! zoomOut && - __unstableGetEditorMode() === 'zoom-out' && - originalEditingModeRef.current !== mode - ) { - __unstableSetEditorMode( originalEditingModeRef.current ); - setZoomLevel( 100 ); + } else { + resetZoomLevel(); } - }, [ - __unstableGetEditorMode, - __unstableSetEditorMode, - zoomOut, - setZoomLevel, - ] ); // Mode is deliberately excluded from the dependencies so that the effect does not run when mode changes. + }, [ zoomOut, setZoomLevel, resetZoomLevel ] ); } diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index d92f8bc08569dc..24a08ecb21d6e5 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1669,46 +1669,7 @@ export const setNavigationMode = */ export const __unstableSetEditorMode = ( mode ) => - ( { dispatch, select, registry } ) => { - // When switching to zoom-out mode, we need to select the parent section - if ( mode === 'zoom-out' ) { - const firstSelectedClientId = select.getBlockSelectionStart(); - - const sectionRootClientId = select.getSectionRootClientId(); - - if ( firstSelectedClientId ) { - let sectionClientId; - - if ( sectionRootClientId ) { - const sectionClientIds = - select.getBlockOrder( sectionRootClientId ); - - // If the selected block is a section block, use it. - if ( sectionClientIds?.includes( firstSelectedClientId ) ) { - sectionClientId = firstSelectedClientId; - } else { - // If the selected block is not a section block, find - // the parent section that contains the selected block. - sectionClientId = select - .getBlockParents( firstSelectedClientId ) - .find( ( parent ) => - sectionClientIds.includes( parent ) - ); - } - } else { - sectionClientId = select.getBlockHierarchyRootClientId( - firstSelectedClientId - ); - } - - if ( sectionClientId ) { - dispatch.selectBlock( sectionClientId ); - } else { - dispatch.clearSelectedBlock(); - } - } - } - + ( { registry } ) => { registry.dispatch( preferencesStore ).set( 'core', 'editorTool', mode ); if ( mode === 'navigation' ) { @@ -1723,8 +1684,6 @@ export const __unstableSetEditorMode = 'You are currently in edit mode. To return to the navigation mode, press Escape.' ) ); - } else if ( mode === 'zoom-out' ) { - speak( __( 'You are currently in zoom-out mode.' ) ); } }; diff --git a/packages/block-editor/src/store/private-actions.js b/packages/block-editor/src/store/private-actions.js index 5571db0ce91066..0ca3eb2cf522e6 100644 --- a/packages/block-editor/src/store/private-actions.js +++ b/packages/block-editor/src/store/private-actions.js @@ -2,6 +2,8 @@ * WordPress dependencies */ import { Platform } from '@wordpress/element'; +import { speak } from '@wordpress/a11y'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -404,12 +406,54 @@ export const modifyContentLockBlock = * @param {number} zoom the new zoom level * @return {Object} Action object. */ -export function setZoomLevel( zoom = 100 ) { - return { - type: 'SET_ZOOM_LEVEL', - zoom, +export const setZoomLevel = + ( zoom = 100 ) => + ( { select, dispatch } ) => { + // When switching to zoom-out mode, we need to select the parent section + if ( zoom !== 100 ) { + const firstSelectedClientId = select.getBlockSelectionStart(); + const sectionRootClientId = select.getSectionRootClientId(); + + if ( firstSelectedClientId ) { + let sectionClientId; + + if ( sectionRootClientId ) { + const sectionClientIds = + select.getBlockOrder( sectionRootClientId ); + + // If the selected block is a section block, use it. + if ( sectionClientIds?.includes( firstSelectedClientId ) ) { + sectionClientId = firstSelectedClientId; + } else { + // If the selected block is not a section block, find + // the parent section that contains the selected block. + sectionClientId = select + .getBlockParents( firstSelectedClientId ) + .find( ( parent ) => + sectionClientIds.includes( parent ) + ); + } + } else { + sectionClientId = select.getBlockHierarchyRootClientId( + firstSelectedClientId + ); + } + + if ( sectionClientId ) { + dispatch.selectBlock( sectionClientId ); + } else { + dispatch.clearSelectedBlock(); + } + + speak( __( 'You are currently in zoom-out mode.' ) ); + } + } + + dispatch( { + type: 'SET_ZOOM_LEVEL', + zoom, + } ); }; -} /** * Resets the Zoom state. diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 28e0c2bd47b0ca..dff5dc0184a4d2 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -17,7 +17,6 @@ import { getClientIdsWithDescendants, isNavigationMode, getBlockRootClientId, - __unstableGetEditorMode, } from './selectors'; import { checkAllowListRecursive, @@ -118,6 +117,7 @@ export const getEnabledClientIdsTree = createSelector( state.settings.templateLock, state.blockListSettings, state.editorMode, + state.zoomLevel, getSectionRootClientId( state ), ] ); @@ -572,17 +572,6 @@ export const getBlockStyles = createSelector( ] ); -/** - * Returns whether zoom out mode is enabled. - * - * @param {Object} state Editor state. - * - * @return {boolean} Is zoom out mode enabled. - */ -export function isZoomOutMode( state ) { - return __unstableGetEditorMode( state ) === 'zoom-out'; -} - /** * Retrieves the client ID of the block which contains the blocks * acting as "sections" in the editor. This is typically the "main content" @@ -596,16 +585,6 @@ export function getSectionRootClientId( state ) { return state.settings?.[ sectionRootClientIdKey ]; } -/** - * Returns the zoom out state. - * - * @param {Object} state Global application state. - * @return {boolean} The zoom out state. - */ -export function getZoomLevel( state ) { - return state.zoomLevel; -} - /** * Returns whether the editor is considered zoomed out. * @@ -613,7 +592,7 @@ export function getZoomLevel( state ) { * @return {boolean} Whether the editor is zoomed. */ export function isZoomOut( state ) { - return getZoomLevel( state ) < 100; + return state.zoomLevel < 100; } /** diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 57e48442b1070b..210cd26aeaa954 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -41,6 +41,7 @@ import { getSectionRootClientId, isSectionBlock, getParentSectionBlock, + isZoomOut, } from './private-selectors'; /** @@ -2902,10 +2903,8 @@ export function __unstableHasActiveBlockOverlayActive( state, clientId ) { return true; } - const editorMode = __unstableGetEditorMode( state ); - // In zoom-out mode, the block overlay is always active for section level blocks. - if ( editorMode === 'zoom-out' ) { + if ( isZoomOut( state ) ) { const sectionRootClientId = getSectionRootClientId( state ); if ( sectionRootClientId ) { const sectionClientIds = getBlockOrder( @@ -3004,8 +3003,7 @@ export const getBlockEditingMode = createRegistrySelector( // In zoom-out mode, override the behavior set by // __unstableSetBlockEditingMode to only allow editing the top-level // sections. - const editorMode = __unstableGetEditorMode( state ); - if ( editorMode === 'zoom-out' ) { + if ( isZoomOut( state ) ) { const sectionRootClientId = getSectionRootClientId( state ); if ( clientId === '' /* ROOT_CONTAINER_CLIENT_ID */ ) { @@ -3027,6 +3025,7 @@ export const getBlockEditingMode = createRegistrySelector( return 'disabled'; } + const editorMode = __unstableGetEditorMode( state ); if ( editorMode === 'navigation' ) { const sectionRootClientId = getSectionRootClientId( state ); diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 88d0cd1588f03f..42250054a70873 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -411,7 +411,7 @@ function Layout( { kind: 'postType', name: 'wp_template', } ); - const { __unstableGetEditorMode } = select( blockEditorStore ); + const { isZoomOut } = unlock( select( blockEditorStore ) ); const { getEditorMode, getRenderingMode } = select( editorStore ); const isRenderingPostOnly = getRenderingMode() === 'post-only'; @@ -436,7 +436,7 @@ function Layout( { ? getEditedPostTemplateId() : null, enablePaddingAppender: - __unstableGetEditorMode() !== 'zoom-out' && + ! isZoomOut() && isRenderingPostOnly && ! DESIGN_POST_TYPES.includes( currentPostType ), }; diff --git a/packages/edit-post/src/components/layout/use-should-iframe.js b/packages/edit-post/src/components/layout/use-should-iframe.js index e36a4773c4a1fd..97e746a6a28f6e 100644 --- a/packages/edit-post/src/components/layout/use-should-iframe.js +++ b/packages/edit-post/src/components/layout/use-should-iframe.js @@ -6,6 +6,11 @@ import { useSelect } from '@wordpress/data'; import { store as blocksStore } from '@wordpress/blocks'; import { store as blockEditorStore } from '@wordpress/block-editor'; +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; + const isGutenbergPlugin = globalThis.IS_GUTENBERG_PLUGIN ? true : false; export function useShouldIframe() { @@ -16,7 +21,7 @@ export function useShouldIframe() { isZoomOutMode, } = useSelect( ( select ) => { const { getEditorSettings, getCurrentPostType } = select( editorStore ); - const { __unstableGetEditorMode } = select( blockEditorStore ); + const { isZoomOut } = unlock( select( blockEditorStore ) ); const { getBlockTypes } = select( blocksStore ); const editorSettings = getEditorSettings(); return { @@ -25,7 +30,7 @@ export function useShouldIframe() { return type.apiVersion >= 3; } ), isEditingTemplate: getCurrentPostType() === 'wp_template', - isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', + isZoomOutMode: isZoomOut(), }; }, [] ); diff --git a/packages/editor/src/components/document-tools/index.js b/packages/editor/src/components/document-tools/index.js index 146945f7343bf2..ee261567a9115a 100644 --- a/packages/editor/src/components/document-tools/index.js +++ b/packages/editor/src/components/document-tools/index.js @@ -48,7 +48,7 @@ function DocumentTools( { className, disableBlockTools = false } ) { getListViewToggleRef, } = unlock( select( editorStore ) ); const { getShortcutRepresentation } = select( keyboardShortcutsStore ); - const { __unstableGetEditorMode } = select( blockEditorStore ); + const { isZoomOut } = unlock( select( blockEditorStore ) ); return { isInserterOpened: select( editorStore ).isInserterOpened(), @@ -61,7 +61,7 @@ function DocumentTools( { className, disableBlockTools = false } ) { showIconLabels: get( 'core', 'showIconLabels' ), isDistractionFree: get( 'core', 'distractionFree' ), isVisualMode: getEditorMode() === 'visual', - isZoomedOutView: __unstableGetEditorMode() === 'zoom-out', + isZoomedOutView: isZoomOut(), }; }, [] ); diff --git a/packages/editor/src/components/inserter-sidebar/index.js b/packages/editor/src/components/inserter-sidebar/index.js index 5cace042fae58c..66730b43592b6e 100644 --- a/packages/editor/src/components/inserter-sidebar/index.js +++ b/packages/editor/src/components/inserter-sidebar/index.js @@ -33,15 +33,12 @@ export default function InserterSidebar() { getInserter, isPublishSidebarOpened, } = unlock( select( editorStore ) ); - const { - getBlockRootClientId, - __unstableGetEditorMode, - getSectionRootClientId, - } = unlock( select( blockEditorStore ) ); + const { getBlockRootClientId, isZoomOut, getSectionRootClientId } = + unlock( select( blockEditorStore ) ); const { get } = select( preferencesStore ); const { getActiveComplementaryArea } = select( interfaceStore ); const getBlockSectionRootClientId = () => { - if ( __unstableGetEditorMode() === 'zoom-out' ) { + if ( isZoomOut() ) { const sectionRootClientId = getSectionRootClientId(); if ( sectionRootClientId ) { diff --git a/packages/editor/src/components/zoom-out-toggle/index.js b/packages/editor/src/components/zoom-out-toggle/index.js index b89bf15546f0d8..2cfb2e2da3bc44 100644 --- a/packages/editor/src/components/zoom-out-toggle/index.js +++ b/packages/editor/src/components/zoom-out-toggle/index.js @@ -23,7 +23,7 @@ const ZoomOutToggle = () => { ), } ) ); - const { resetZoomLevel, setZoomLevel, __unstableSetEditorMode } = unlock( + const { resetZoomLevel, setZoomLevel } = unlock( useDispatch( blockEditorStore ) ); @@ -33,7 +33,6 @@ const ZoomOutToggle = () => { } else { setZoomLevel( 50 ); } - __unstableSetEditorMode( isZoomOut ? 'edit' : 'zoom-out' ); }; return ( diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index abb744ee5f2207..2396cb67c73e69 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -28,6 +28,7 @@ import { } from './constants'; import { getPostRawValue } from './reducer'; import { getTemplatePartIcon } from '../utils/get-template-part-icon'; +import { unlock } from '../lock-unlock'; /** * Shared reference to an empty object for cases where it is important to avoid @@ -1299,8 +1300,8 @@ export function getRenderingMode( state ) { */ export const getDeviceType = createRegistrySelector( ( select ) => ( state ) => { - const editorMode = select( blockEditorStore ).__unstableGetEditorMode(); - if ( editorMode === 'zoom-out' ) { + const isZoomOut = unlock( select( blockEditorStore ) ).isZoomOut(); + if ( isZoomOut ) { return 'Desktop'; } return state.deviceType; From ff1d1142d72a5bf79c6138a59c6c66c7d0e1d75d Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 17 Oct 2024 17:16:37 +0200 Subject: [PATCH 1223/1908] Tabs: fix animation timings (#66198) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../src/components/inserter/category-tabs/index.js | 1 - packages/components/CHANGELOG.md | 1 + packages/components/src/tabs/styles.ts | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/inserter/category-tabs/index.js b/packages/block-editor/src/components/inserter/category-tabs/index.js index 6d8f5fcbca1334..2641e2a20c40f6 100644 --- a/packages/block-editor/src/components/inserter/category-tabs/index.js +++ b/packages/block-editor/src/components/inserter/category-tabs/index.js @@ -33,7 +33,6 @@ function CategoryTabs( { return ( <Tabs - className="block-editor-inserter__category-tabs" selectOnMove={ false } selectedTabId={ selectedCategory ? selectedCategory.name : null } orientation="vertical" diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index d71f6ba7ce142f..2064aa9e9e9621 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -4,6 +4,7 @@ ### Bug Fixes +- `Tabs`: fix indicator animation ([#66198](https://github.com/WordPress/gutenberg/pull/66198)). - `ColorPalette`: prevent overflow of custom color button background ([#66152](https://github.com/WordPress/gutenberg/pull/66152)). ### Enhancements diff --git a/packages/components/src/tabs/styles.ts b/packages/components/src/tabs/styles.ts index 926abc3e34b102..da7368c6e19114 100644 --- a/packages/components/src/tabs/styles.ts +++ b/packages/components/src/tabs/styles.ts @@ -195,7 +195,7 @@ export const Tab = styled( Ariakit.Tab )` opacity: 0; @media not ( prefers-reduced-motion ) { - transition: opacity 0.15s 0.15s linear; + transition: opacity 0.1s linear; } } @@ -253,7 +253,7 @@ export const TabChevron = styled( Icon )` [data-select-on-move='true'] [role='tab']:is( [aria-selected='true'], ) & { - transition: opacity 0.3s ease-in; + transition: opacity 0.15s 0.15s linear; } } &:dir( rtl ) { From 2a215b81ae38d95180b25f48b38e4767bfab6fb3 Mon Sep 17 00:00:00 2001 From: Miguel Fonseca <150562+mcsf@users.noreply.github.com> Date: Thu, 17 Oct 2024 16:22:51 +0100 Subject: [PATCH 1224/1908] BlockGroupToolbar: Better i18n context for toolbar labels (#66211) Make it less confusing for translators to translate the actions in BlockGroupToolbar, specifically the buttons to convert a selection of blocks to a Group, a Row, a Stack or a Grid. --- .../src/components/convert-to-group-buttons/toolbar.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/convert-to-group-buttons/toolbar.js b/packages/block-editor/src/components/convert-to-group-buttons/toolbar.js index 21934bfd603f52..b82205d0c46616 100644 --- a/packages/block-editor/src/components/convert-to-group-buttons/toolbar.js +++ b/packages/block-editor/src/components/convert-to-group-buttons/toolbar.js @@ -85,27 +85,27 @@ function BlockGroupToolbar() { <ToolbarGroup> <ToolbarButton icon={ group } - label={ _x( 'Group', 'verb' ) } + label={ _x( 'Group', 'action: convert blocks to group' ) } onClick={ onConvertToGroup } /> { canInsertRow && ( <ToolbarButton icon={ row } - label={ _x( 'Row', 'single horizontal line' ) } + label={ _x( 'Row', 'action: convert blocks to row' ) } onClick={ onConvertToRow } /> ) } { canInsertStack && ( <ToolbarButton icon={ stack } - label={ _x( 'Stack', 'verb' ) } + label={ _x( 'Stack', 'action: convert blocks to stack' ) } onClick={ onConvertToStack } /> ) } { canInsertGrid && ( <ToolbarButton icon={ grid } - label={ _x( 'Grid', 'verb' ) } + label={ _x( 'Grid', 'action: convert blocks to grid' ) } onClick={ onConvertToGrid } /> ) } From 605e9df6f09861c56b7f1c171dc9a7412a52713e Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 17 Oct 2024 17:24:30 +0200 Subject: [PATCH 1225/1908] Tabs and TabPanel: Fix arrow key navigation in RTL (#66201) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/tab-panel/index.tsx | 2 ++ packages/components/src/tabs/index.tsx | 2 ++ 3 files changed, 5 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 2064aa9e9e9621..9c36c6600ac701 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,7 @@ - `Tabs`: fix indicator animation ([#66198](https://github.com/WordPress/gutenberg/pull/66198)). - `ColorPalette`: prevent overflow of custom color button background ([#66152](https://github.com/WordPress/gutenberg/pull/66152)). +- `Tabs` and `TabPanel`: Fix arrow key navigation in RTL ([#66201](https://github.com/WordPress/gutenberg/pull/66201)). ### Enhancements diff --git a/packages/components/src/tab-panel/index.tsx b/packages/components/src/tab-panel/index.tsx index 9e180c30321b93..f9db745b424260 100644 --- a/packages/components/src/tab-panel/index.tsx +++ b/packages/components/src/tab-panel/index.tsx @@ -16,6 +16,7 @@ import { useCallback, } from '@wordpress/element'; import { useInstanceId, usePrevious } from '@wordpress/compose'; +import { isRTL } from '@wordpress/i18n'; /** * Internal dependencies @@ -120,6 +121,7 @@ const UnforwardedTabPanel = ( orientation, selectOnMove, defaultSelectedId: prependInstanceId( initialTabName ), + rtl: isRTL(), } ); const selectedTabName = extractTabName( diff --git a/packages/components/src/tabs/index.tsx b/packages/components/src/tabs/index.tsx index ca8c5b19bcd622..09225c0cce9b8d 100644 --- a/packages/components/src/tabs/index.tsx +++ b/packages/components/src/tabs/index.tsx @@ -14,6 +14,7 @@ import { useMemo, useRef, } from '@wordpress/element'; +import { isRTL } from '@wordpress/i18n'; /** * Internal dependencies @@ -45,6 +46,7 @@ function Tabs( { onSelect?.( strippedDownId ); }, selectedId: selectedTabId && `${ instanceId }-${ selectedTabId }`, + rtl: isRTL(), } ); const isControlled = selectedTabId !== undefined; From 4c15400000023365ea5e414550656bd3be3167ec Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 17 Oct 2024 17:27:49 +0200 Subject: [PATCH 1226/1908] Tabs: simplify styled components code (#66208) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/src/tabs/styles.ts | 2 +- packages/components/src/tabs/tablist.tsx | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/components/src/tabs/styles.ts b/packages/components/src/tabs/styles.ts index da7368c6e19114..36e0ed6f6b0147 100644 --- a/packages/components/src/tabs/styles.ts +++ b/packages/components/src/tabs/styles.ts @@ -11,7 +11,7 @@ import { COLORS, CONFIG } from '../utils'; import { space } from '../utils/space'; import Icon from '../icon'; -export const TabListWrapper = styled.div` +export const StyledTabList = styled( Ariakit.TabList )` display: flex; align-items: stretch; overflow-x: auto; diff --git a/packages/components/src/tabs/tablist.tsx b/packages/components/src/tabs/tablist.tsx index 512a3eb6724289..46cc0488bc67ae 100644 --- a/packages/components/src/tabs/tablist.tsx +++ b/packages/components/src/tabs/tablist.tsx @@ -1,7 +1,6 @@ /** * External dependencies */ -import * as Ariakit from '@ariakit/react'; import { useStoreState } from '@ariakit/react'; /** @@ -16,7 +15,7 @@ import { useMergeRefs } from '@wordpress/compose'; */ import type { TabListProps } from './types'; import { useTabsContext } from './context'; -import { TabListWrapper } from './styles'; +import { StyledTabList } from './styles'; import type { WordPressComponentProps } from '../context'; import clsx from 'clsx'; import type { ElementOffsetRect } from '../utils/element-rect'; @@ -109,10 +108,9 @@ export const TabList = forwardRef< } return ( - <Ariakit.TabList + <StyledTabList ref={ refs } store={ store } - render={ <TabListWrapper /> } onBlur={ onBlur } tabIndex={ -1 } data-select-on-move={ selectOnMove ? 'true' : 'false' } @@ -124,6 +122,6 @@ export const TabList = forwardRef< ) } > { children } - </Ariakit.TabList> + </StyledTabList> ); } ); From 739805c4653a3b0227157bb3ebc2a27c15a22fc1 Mon Sep 17 00:00:00 2001 From: Maggie <maggie.cabrera@automattic.com> Date: Thu, 17 Oct 2024 17:52:16 +0200 Subject: [PATCH 1227/1908] Fix [Flaky Test] Entering zoomed out mode zooms the canvas (#66212) * start each test directly on the template page * remove pause Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- test/e2e/specs/site-editor/zoom-out.spec.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/e2e/specs/site-editor/zoom-out.spec.js b/test/e2e/specs/site-editor/zoom-out.spec.js index 2aabee07d18785..464bd4a4a4efad 100644 --- a/test/e2e/specs/site-editor/zoom-out.spec.js +++ b/test/e2e/specs/site-editor/zoom-out.spec.js @@ -12,9 +12,12 @@ test.describe( 'Zoom Out', () => { await requestUtils.activateTheme( 'twentytwentyone' ); } ); - test.beforeEach( async ( { admin, editor } ) => { - await admin.visitSiteEditor(); - await editor.canvas.locator( 'body' ).click(); + test.beforeEach( async ( { admin } ) => { + await admin.visitSiteEditor( { + postId: 'twentytwentyfour//index', + postType: 'wp_template', + canvas: 'edit', + } ); } ); test( 'Entering zoomed out mode zooms the canvas', async ( { From 51892ff1ca1284ab9672636420775041d2db0c0f Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 17 Oct 2024 13:26:56 +0000 Subject: [PATCH 1228/1908] Update changelog files --- packages/scripts/CHANGELOG.md | 6 ++++-- packages/scripts/package.json | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 41dcf4d54922f8..8a1133a2e7ae22 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -10,9 +10,11 @@ - Refactor to extract license related logic to a reusable module ([#66179](https://github.com/WordPress/gutenberg/pull/66179)). +## 30.3.0 (2024-10-17) + ### New Features -- Add new `build-blocks-manifest` command to generate a PHP file containing block metadata from all `block.json` files in a project ([#65866](https://github.com/WordPress/gutenberg/pull/65866)). +- Add new `build-blocks-manifest` command to generate a PHP file containing block metadata from all `block.json` files in a project ([#65866](https://github.com/WordPress/gutenberg/pull/65866)). ## 30.2.0 (2024-10-16) @@ -33,7 +35,7 @@ ### Enhancements -- Inlines CSS files imported from other CSS files before optimization in the `build` command ([#61121](https://github.com/WordPress/gutenberg/pull/61121)). +- Inlines CSS files imported from other CSS files before optimization in the `build` command ([#61121](https://github.com/WordPress/gutenberg/pull/61121)). ### Bug Fixes diff --git a/packages/scripts/package.json b/packages/scripts/package.json index c98f341b812655..121a9cb09dc8bc 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.2.0", + "version": "30.3.0-prerelease", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 99eae66d2707835ba3e1308ddb5cefa1859a8ef9 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 17 Oct 2024 13:28:40 +0000 Subject: [PATCH 1229/1908] chore(release): publish - @wordpress/e2e-tests@8.10.1 - @wordpress/scripts@30.3.0 --- package-lock.json | 4 ++-- packages/e2e-tests/package.json | 2 +- packages/scripts/package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index d49fb33f5c7078..3c328a047fc588 100644 --- a/package-lock.json +++ b/package-lock.json @@ -55085,7 +55085,7 @@ }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", - "version": "8.10.0", + "version": "8.10.1", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -56461,7 +56461,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "30.2.0", + "version": "30.3.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 03f98a8289da4f..a2192c10049380 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.10.0", + "version": "8.10.1", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 121a9cb09dc8bc..66461f4eb28ec2 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.3.0-prerelease", + "version": "30.3.0", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 4f405ac3a70c555556e623d94cdf35f35f005b07 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 17 Oct 2024 18:01:56 +0200 Subject: [PATCH 1230/1908] RadioGroup: Fix arrow key navigation in RTL (#66202) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/radio-group/index.tsx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 9c36c6600ac701..475bf272cc1bb8 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,7 @@ - `Tabs`: fix indicator animation ([#66198](https://github.com/WordPress/gutenberg/pull/66198)). - `ColorPalette`: prevent overflow of custom color button background ([#66152](https://github.com/WordPress/gutenberg/pull/66152)). +- `RadioGroup`: Fix arrow key navigation in RTL ([#66202](https://github.com/WordPress/gutenberg/pull/66202)). - `Tabs` and `TabPanel`: Fix arrow key navigation in RTL ([#66201](https://github.com/WordPress/gutenberg/pull/66201)). ### Enhancements diff --git a/packages/components/src/radio-group/index.tsx b/packages/components/src/radio-group/index.tsx index ac66c79e904e4b..e59775c00a8023 100644 --- a/packages/components/src/radio-group/index.tsx +++ b/packages/components/src/radio-group/index.tsx @@ -7,6 +7,7 @@ import * as Ariakit from '@ariakit/react'; * WordPress dependencies */ import { useMemo, forwardRef } from '@wordpress/element'; +import { isRTL } from '@wordpress/i18n'; /** * Internal dependencies @@ -34,6 +35,7 @@ function UnforwardedRadioGroup( setValue: ( newValue ) => { onChange?.( newValue ?? undefined ); }, + rtl: isRTL(), } ); const contextValue = useMemo( From b8cd03d2e2713ffe648923712d2599b25808ad67 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 17 Oct 2024 19:05:03 +0200 Subject: [PATCH 1231/1908] Tabs: override tablist's tabindex only when necessary (#66209) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/tabs/tablist.tsx | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 475bf272cc1bb8..53ff933848338c 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -8,6 +8,7 @@ - `ColorPalette`: prevent overflow of custom color button background ([#66152](https://github.com/WordPress/gutenberg/pull/66152)). - `RadioGroup`: Fix arrow key navigation in RTL ([#66202](https://github.com/WordPress/gutenberg/pull/66202)). - `Tabs` and `TabPanel`: Fix arrow key navigation in RTL ([#66201](https://github.com/WordPress/gutenberg/pull/66201)). +- `Tabs`: override tablist's tabindex only when necessary ([#66209](https://github.com/WordPress/gutenberg/pull/66209)). ### Enhancements diff --git a/packages/components/src/tabs/tablist.tsx b/packages/components/src/tabs/tablist.tsx index 46cc0488bc67ae..998da5707aa071 100644 --- a/packages/components/src/tabs/tablist.tsx +++ b/packages/components/src/tabs/tablist.tsx @@ -111,8 +111,15 @@ export const TabList = forwardRef< <StyledTabList ref={ refs } store={ store } + render={ ( props ) => ( + <div + { ...props } + // Fallback to -1 to prevent browsers from making the tablist + // tabbable when it is a scrolling container. + tabIndex={ props.tabIndex ?? -1 } + /> + ) } onBlur={ onBlur } - tabIndex={ -1 } data-select-on-move={ selectOnMove ? 'true' : 'false' } { ...otherProps } className={ clsx( From 86b09fb68036d21a9ff78fc6036093f99ace816d Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Fri, 18 Oct 2024 02:09:33 +0100 Subject: [PATCH 1232/1908] Add elevation tokens to storybook (#66122) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- storybook/stories/tokens/components.tsx | 53 +++++++++++++++ storybook/stories/tokens/elevation.mdx | 88 +++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 storybook/stories/tokens/components.tsx create mode 100644 storybook/stories/tokens/elevation.mdx diff --git a/storybook/stories/tokens/components.tsx b/storybook/stories/tokens/components.tsx new file mode 100644 index 00000000000000..05c2b4bde85a21 --- /dev/null +++ b/storybook/stories/tokens/components.tsx @@ -0,0 +1,53 @@ +/** + * External dependencies + */ +// eslint-disable-next-line @typescript-eslint/no-restricted-imports +import React from 'react'; + +export const ElevationTable = ( { tokens } ) => { + return ( + <table> + <thead> + <tr> + <th>Token</th> + <th>Value</th> + <th>Example</th> + </tr> + </thead> + <tbody> + { tokens.map( ( { name, valueShow, valueCode } ) => ( + <tr key={ name }> + <td style={ { whiteSpace: 'nowrap' } }>{ name }</td> + <td> + <code + style={ { + lineHeight: 1, + margin: '0 2px', + padding: '3px 5px', + borderRadius: '3px', + fontSize: '13px', + border: '1px solid #ECF4F9', + color: 'rgba(46, 52, 56, 0.9)', + backgroundColor: '#F7FAFC', + } } + > + { valueShow } + </code> + </td> + <td style={ { padding: '24px' } }> + <div + aria-label={ `An square showing an example of the '${ name }' elevation styles` } + style={ { + width: '100px', + height: '100px', + boxShadow: valueCode, + background: 'white', + } } + ></div> + </td> + </tr> + ) ) } + </tbody> + </table> + ); +}; diff --git a/storybook/stories/tokens/elevation.mdx b/storybook/stories/tokens/elevation.mdx new file mode 100644 index 00000000000000..d00de6dbde7fab --- /dev/null +++ b/storybook/stories/tokens/elevation.mdx @@ -0,0 +1,88 @@ +import { Meta } from '@storybook/addon-docs/blocks'; +import { ElevationTable } from './components.tsx'; + +<Meta title="Tokens/Elevation" name="page" /> + +# Elevation tokens + +This document outlines the various tokens relating to elevation in the WordPress design system. + +## Values + +Tokens can be used in different ways, but regardless of which method is used, each one is meant to be used as the value of the CSS `box-shadow` property, and references the following values: + +<ElevationTable + tokens={ [ + { + name: 'Extra small', + valueShow: + '0 1px 1px rgba($black, 0.03), 0 1px 2px rgba($black, 0.02), 0 3px 3px rgba($black, 0.02), 0 4px 4px rgba($black, 0.01)', + valueCode: + '0 1px 1px rgba(0, 0, 0, 0.03), 0 1px 2px rgba(0, 0, 0, 0.02), 0 3px 3px rgba(0, 0, 0, 0.02), 0 4px 4px rgba(0, 0, 0, 0.01)', + }, + { + name: 'Small', + valueShow: + '0 1px 2px rgba($black, 0.05), 0 2px 3px rgba($black, 0.04), 0 6px 6px rgba($black, 0.03), 0 8px 8px rgba($black, 0.02)', + valueCode: + '0 1px 2px rgba(0, 0, 0, 0.05), 0 2px 3px rgba(0, 0, 0, 0.04), 0 6px 6px rgba(0, 0, 0, 0.03), 0 8px 8px rgba(0, 0, 0, 0.02)', + }, + { + name: 'Medium', + valueShow: + '0 2px 3px rgba($black, 0.05), 0 4px 5px rgba($black, 0.04), 0 12px 12px rgba($black, 0.03), 0 16px 16px rgba($black, 0.02)', + valueCode: + '0 2px 3px rgba(0, 0, 0, 0.05), 0 4px 5px rgba(0, 0, 0, 0.04), 0 12px 12px rgba(0, 0, 0, 0.03), 0 16px 16px rgba(0, 0, 0, 0.02)', + }, + { + name: 'Large', + valueShow: + '0 5px 15px rgba($black, 0.08), 0 15px 27px rgba($black, 0.07), 0 30px 36px rgba($black, 0.04), 0 50px 43px rgba($black, 0.02)', + valueCode: + '0 5px 15px rgba(0, 0, 0, 0.08), 0 15px 27px rgba(0, 0, 0, 0.07), 0 30px 36px rgba(0, 0, 0, 0.04), 0 50px 43px rgba(0, 0, 0, 0.02)', + }, + ] } +/> + +## CSS tokens + +Elevation tokens are defined as SASS variables: + +- `$elevation-x-small` +- `$elevation-small` +- `$elevation-medium` +- `$elevation-large` + +They can be used like so: + +```css +.elevation-extra-small { + box-shadow: $elevation-x-small; +} +.elevation-small { + box-shadow: $elevation-small; +} +.elevation-medium { + box-shadow: $elevation-medium; +} +.elevation-large { + box-shadow: $elevation-large; +} +``` + +## JS tokens + +When working in the `@wordpress/components` package, the elevation tokens can also be consumed as JavaScript variables via the `CONFIG` object found in the `packages/components/src/utils/index.js` file: + +- `CONFIG.elevationXSmall` +- `CONFIG.elevationSmall` +- `CONFIG.elevationMedium` +- `CONFIG.elevationLarge` + +```js +// Note: the `CONFIG` object is only available within the `@wordpress/components` package. +import { CONFIG } from '../utils'; + +// Later in the code: +box-shadow: ${ CONFIG.elevationXSmall }; +``` From 3e2e434c55347584b25273006a03ce82677c3ee3 Mon Sep 17 00:00:00 2001 From: tellthemachines <tellthemachines@users.noreply.github.com> Date: Fri, 18 Oct 2024 13:51:36 +1100 Subject: [PATCH 1233/1908] Correct docs on display type in flow layouts. (#66224) --- docs/explanations/architecture/styles.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/explanations/architecture/styles.md b/docs/explanations/architecture/styles.md index 952c6c49caad23..68f09f04d21d32 100644 --- a/docs/explanations/architecture/styles.md +++ b/docs/explanations/architecture/styles.md @@ -510,7 +510,7 @@ When a block that opts in to layout support is rendered, two things are processe There are currently four layout types in use: -- Default/Flow: Items are stacked vertically. The parent container block is set to `display: flow` and the spacing between children is handled via vertical margins. +- Default/Flow: Items are stacked vertically. The parent container block's display value isn't specified, so that it may use the default value for that HTML element. For most elements that will usually be `block`. The spacing between children is handled via vertical margins. - Constrained: Items are stacked vertically, using the same spacing logic as the Flow layout. Features constrained widths for child content, outputting widths for standard content size and wide size. Defaults to using global `contentSize` and `wideSize` values set in `settings.layout` in the `theme.json`. - Flex: Items are displayed using a Flexbox layout. Defaults to a horizontal orientation. Spacing between children is handled via the `gap` CSS property. - Grid: Items are displayed using a Grid layout. Defaults to an `auto-fill` approach to column generation but can also be set to a fixed number of columns. Spacing between children is handled via the `gap` CSS property. From 8b4fd4c305a6effa8afbb37f46d76c34e40ddced Mon Sep 17 00:00:00 2001 From: Madhu Dollu <madhusudhan.dollu@gmail.com> Date: Fri, 18 Oct 2024 12:48:23 +0530 Subject: [PATCH 1234/1908] Fix zoom out not persisting while switching between editor and code editor (#65932) * reset zoomLevel on component unmount * conditionally reset zoom level * revert iframe changes and reset zoomLevel in the text-editor Co-authored-by: madhusudhand <madhudollu@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: yani- <yaniiliev@git.wordpress.org> Co-authored-by: ironprogrammer <ironprogrammer@git.wordpress.org> Co-authored-by: simison <simison@git.wordpress.org> Co-authored-by: PARTHVATALIYA <parthvataliya@git.wordpress.org> --- packages/editor/src/components/text-editor/index.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/text-editor/index.js b/packages/editor/src/components/text-editor/index.js index fa0688859b5a69..6997c66826a12d 100644 --- a/packages/editor/src/components/text-editor/index.js +++ b/packages/editor/src/components/text-editor/index.js @@ -6,6 +6,7 @@ import { useDispatch, useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts'; import { useEffect, useRef } from '@wordpress/element'; +import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Internal dependencies @@ -13,6 +14,7 @@ import { useEffect, useRef } from '@wordpress/element'; import { store as editorStore } from '../../store'; import PostTextEditor from '../post-text-editor'; import PostTitleRaw from '../post-title/post-title-raw'; +import { unlock } from '../../lock-unlock'; export default function TextEditor( { autoFocus = false } ) { const { switchEditorMode } = useDispatch( editorStore ); @@ -26,13 +28,20 @@ export default function TextEditor( { autoFocus = false } ) { }; }, [] ); + const { resetZoomLevel, __unstableSetEditorMode } = unlock( + useDispatch( blockEditorStore ) + ); + const titleRef = useRef(); useEffect( () => { + resetZoomLevel(); + __unstableSetEditorMode( 'edit' ); + if ( autoFocus ) { return; } titleRef?.current?.focus(); - }, [ autoFocus ] ); + }, [ autoFocus, resetZoomLevel, __unstableSetEditorMode ] ); return ( <div className="editor-text-editor"> From d330f30a528a252c56ee4adbee2f8ee5f82a0312 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Fri, 18 Oct 2024 09:27:52 +0200 Subject: [PATCH 1235/1908] Global styles menu: Avoid visible labels and accessible names mismatch (#65124) * Simplify global styles root menu labels. * Fix and simplify labels in various global styles submenus. * Adjust failing test. * Fix more tests. * Fix one more test. * Entirely remove palette icons and move color randomizer. * Restore randomize colors position and add visible label. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../components/global-styles/color-panel.js | 12 +----- .../font-sizes/font-sizes-count.js | 5 +-- .../src/components/global-styles/palette.js | 39 ++++++++++--------- .../src/components/global-styles/root-menu.js | 19 ++------- .../global-styles/screen-block-list.js | 7 ---- .../components/global-styles/screen-root.js | 15 ++----- .../components/global-styles/shadows-panel.js | 4 -- .../global-styles/typography-elements.js | 14 ++----- .../variations/variations-panel.js | 1 - test/e2e/specs/editor/blocks/buttons.spec.js | 12 +++--- .../editor/blocks/navigation-colors.spec.js | 6 +-- .../keep-styles-on-block-transforms.spec.js | 2 +- .../specs/site-editor/font-library.spec.js | 34 +++++----------- .../site-editor/global-styles-sidebar.spec.js | 6 +-- .../site-editor/push-to-global-styles.spec.js | 15 +++---- test/e2e/specs/site-editor/style-book.spec.js | 6 +-- .../site-editor/style-variations.spec.js | 22 +++++------ test/e2e/specs/site-editor/styles.spec.js | 4 +- .../user-global-styles-revisions.spec.js | 6 +-- 19 files changed, 81 insertions(+), 148 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/color-panel.js b/packages/block-editor/src/components/global-styles/color-panel.js index a55a7b331bd0dd..7c5257ae93bfaa 100644 --- a/packages/block-editor/src/components/global-styles/color-panel.js +++ b/packages/block-editor/src/components/global-styles/color-panel.js @@ -20,7 +20,7 @@ import { privateApis as componentsPrivateApis, } from '@wordpress/components'; import { useCallback } from '@wordpress/element'; -import { __, sprintf } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -167,10 +167,7 @@ const LabeledColorIndicators = ( { indicators, label } ) => ( </Flex> ) ) } </ZStack> - <FlexItem - className="block-editor-panel-color-gradient-settings__color-name" - title={ label } - > + <FlexItem className="block-editor-panel-color-gradient-settings__color-name"> { label } </FlexItem> </HStack> @@ -231,11 +228,6 @@ function ColorPanelDropdown( { { 'is-open': isOpen } ), 'aria-expanded': isOpen, - 'aria-label': sprintf( - /* translators: %s is the type of color property, e.g., "background" */ - __( 'Color %s styles' ), - label - ), }; return ( diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-sizes-count.js b/packages/edit-site/src/components/global-styles/font-sizes/font-sizes-count.js index c268648a134a74..fb23a38fe43bc2 100644 --- a/packages/edit-site/src/components/global-styles/font-sizes/font-sizes-count.js +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-sizes-count.js @@ -23,10 +23,7 @@ function FontSizes() { <Subtitle level={ 3 }>{ __( 'Font Sizes' ) }</Subtitle> </HStack> <ItemGroup isBordered isSeparated> - <NavigationButtonAsItem - path="/typography/font-sizes" - aria-label={ __( 'Edit font size presets' ) } - > + <NavigationButtonAsItem path="/typography/font-sizes"> <HStack direction="row"> <FlexItem>{ __( 'Font size presets' ) }</FlexItem> <Icon icon={ isRTL() ? chevronLeft : chevronRight } /> diff --git a/packages/edit-site/src/components/global-styles/palette.js b/packages/edit-site/src/components/global-styles/palette.js index 4afb9d88feb3e9..9b8c3f829d2426 100644 --- a/packages/edit-site/src/components/global-styles/palette.js +++ b/packages/edit-site/src/components/global-styles/palette.js @@ -54,32 +54,35 @@ function Palette( { name } ) { const screenPath = ! name ? '/colors/palette' : '/blocks/' + encodeURIComponent( name ) + '/colors/palette'; - const paletteButtonText = - colors.length > 0 ? __( 'Edit palette' ) : __( 'Add colors' ); return ( <VStack spacing={ 3 }> <Subtitle level={ 3 }>{ __( 'Palette' ) }</Subtitle> <ItemGroup isBordered isSeparated> - <NavigationButtonAsItem - path={ screenPath } - aria-label={ paletteButtonText } - > + <NavigationButtonAsItem path={ screenPath }> <HStack direction="row"> - { colors.length <= 0 && ( + { colors.length > 0 ? ( + <> + <ZStack isLayered={ false } offset={ -8 }> + { colors + .slice( 0, 5 ) + .map( ( { color }, index ) => ( + <ColorIndicatorWrapper + key={ `${ color }-${ index }` } + > + <ColorIndicator + colorValue={ color } + /> + </ColorIndicatorWrapper> + ) ) } + </ZStack> + <FlexItem isBlock> + { __( 'Edit palette' ) } + </FlexItem> + </> + ) : ( <FlexItem>{ __( 'Add colors' ) }</FlexItem> ) } - <ZStack isLayered={ false } offset={ -8 }> - { colors - .slice( 0, 5 ) - .map( ( { color }, index ) => ( - <ColorIndicatorWrapper - key={ `${ color }-${ index }` } - > - <ColorIndicator colorValue={ color } /> - </ColorIndicatorWrapper> - ) ) } - </ZStack> <Icon icon={ isRTL() ? chevronLeft : chevronRight } /> </HStack> </NavigationButtonAsItem> diff --git a/packages/edit-site/src/components/global-styles/root-menu.js b/packages/edit-site/src/components/global-styles/root-menu.js index 183686bb52d825..d8e8f5794f9d03 100644 --- a/packages/edit-site/src/components/global-styles/root-menu.js +++ b/packages/edit-site/src/components/global-styles/root-menu.js @@ -48,17 +48,12 @@ function RootMenu() { <NavigationButtonAsItem icon={ typography } path="/typography" - aria-label={ __( 'Typography styles' ) } > { __( 'Typography' ) } </NavigationButtonAsItem> ) } { hasColorPanel && ( - <NavigationButtonAsItem - icon={ color } - path="/colors" - aria-label={ __( 'Colors styles' ) } - > + <NavigationButtonAsItem icon={ color } path="/colors"> { __( 'Colors' ) } </NavigationButtonAsItem> ) } @@ -72,20 +67,12 @@ function RootMenu() { </NavigationButtonAsItem> ) } { hasShadowPanel && ( - <NavigationButtonAsItem - icon={ shadowIcon } - path="/shadows" - aria-label={ __( 'Shadow styles' ) } - > + <NavigationButtonAsItem icon={ shadowIcon } path="/shadows"> { __( 'Shadows' ) } </NavigationButtonAsItem> ) } { hasLayoutPanel && ( - <NavigationButtonAsItem - icon={ layout } - path="/layout" - aria-label={ __( 'Layout styles' ) } - > + <NavigationButtonAsItem icon={ layout } path="/layout"> { __( 'Layout' ) } </NavigationButtonAsItem> ) } diff --git a/packages/edit-site/src/components/global-styles/screen-block-list.js b/packages/edit-site/src/components/global-styles/screen-block-list.js index 51807ba79aa111..441c4168f814aa 100644 --- a/packages/edit-site/src/components/global-styles/screen-block-list.js +++ b/packages/edit-site/src/components/global-styles/screen-block-list.js @@ -86,16 +86,9 @@ function BlockMenuItem( { block } ) { return null; } - const navigationButtonLabel = sprintf( - // translators: %s: is the name of a block e.g., 'Image' or 'Table'. - __( '%s block styles' ), - block.title - ); - return ( <NavigationButtonAsItem path={ '/blocks/' + encodeURIComponent( block.name ) } - aria-label={ navigationButtonLabel } > <HStack justify="flex-start"> <BlockIcon icon={ block.icon } /> diff --git a/packages/edit-site/src/components/global-styles/screen-root.js b/packages/edit-site/src/components/global-styles/screen-root.js index d5b29eca5549c5..ffa85b046ead71 100644 --- a/packages/edit-site/src/components/global-styles/screen-root.js +++ b/packages/edit-site/src/components/global-styles/screen-root.js @@ -67,10 +67,7 @@ function ScreenRoot() { </Card> { hasVariations && ( <ItemGroup> - <NavigationButtonAsItem - path="/variations" - aria-label={ __( 'Browse styles' ) } - > + <NavigationButtonAsItem path="/variations"> <HStack justify="space-between"> <FlexItem> { __( 'Browse styles' ) } @@ -107,10 +104,7 @@ function ScreenRoot() { ) } </Spacer> <ItemGroup> - <NavigationButtonAsItem - path="/blocks" - aria-label={ __( 'Blocks styles' ) } - > + <NavigationButtonAsItem path="/blocks"> <HStack justify="space-between"> <FlexItem>{ __( 'Blocks' ) }</FlexItem> <IconWithCurrentColor @@ -136,10 +130,7 @@ function ScreenRoot() { ) } </Spacer> <ItemGroup> - <NavigationButtonAsItem - path="/css" - aria-label={ __( 'Additional CSS' ) } - > + <NavigationButtonAsItem path="/css"> <HStack justify="space-between"> <FlexItem> { __( 'Additional CSS' ) } diff --git a/packages/edit-site/src/components/global-styles/shadows-panel.js b/packages/edit-site/src/components/global-styles/shadows-panel.js index 18e15ef7dd6f28..43e0c063f492b8 100644 --- a/packages/edit-site/src/components/global-styles/shadows-panel.js +++ b/packages/edit-site/src/components/global-styles/shadows-panel.js @@ -135,10 +135,6 @@ function ShadowItem( { shadow, category } ) { return ( <NavigationButtonAsItem path={ `/shadows/edit/${ category }/${ shadow.slug }` } - aria-label={ - // translators: %s: name of the shadow - sprintf( 'Edit shadow %s', shadow.name ) - } icon={ shadowIcon } > { shadow.name } diff --git a/packages/edit-site/src/components/global-styles/typography-elements.js b/packages/edit-site/src/components/global-styles/typography-elements.js index eaff3de05112b6..d087c8df041521 100644 --- a/packages/edit-site/src/components/global-styles/typography-elements.js +++ b/packages/edit-site/src/components/global-styles/typography-elements.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { __, sprintf } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; import { __experimentalItemGroup as ItemGroup, __experimentalVStack as VStack, @@ -36,17 +36,8 @@ function ElementItem( { parentMenu, element, label } ) { const [ gradientValue ] = useGlobalStyle( prefix + 'color.gradient' ); const [ color ] = useGlobalStyle( prefix + 'color.text' ); - const navigationButtonLabel = sprintf( - // translators: %s: is a subset of Typography, e.g., 'text' or 'links'. - __( 'Typography %s styles' ), - label - ); - return ( - <NavigationButtonAsItem - path={ parentMenu + '/typography/' + element } - aria-label={ navigationButtonLabel } - > + <NavigationButtonAsItem path={ parentMenu + '/typography/' + element }> <HStack justify="flex-start"> <FlexItem className="edit-site-global-styles-screen-typography__indicator" @@ -61,6 +52,7 @@ function ElementItem( { parentMenu, element, label } ) { fontWeight, ...extraStyles, } } + aria-hidden="true" > { __( 'Aa' ) } </FlexItem> diff --git a/packages/edit-site/src/components/global-styles/variations/variations-panel.js b/packages/edit-site/src/components/global-styles/variations/variations-panel.js index f98cc65e5c95b1..22f2f50c58e24f 100644 --- a/packages/edit-site/src/components/global-styles/variations/variations-panel.js +++ b/packages/edit-site/src/components/global-styles/variations/variations-panel.js @@ -55,7 +55,6 @@ export function VariationsPanel( { name } ) { '/variations/' + encodeURIComponent( style.name ) } - aria-label={ style.label } > { style.label } </NavigationButtonAsItem> diff --git a/test/e2e/specs/editor/blocks/buttons.spec.js b/test/e2e/specs/editor/blocks/buttons.spec.js index 25bc2d6101024a..d6b0a0a15c4ea2 100644 --- a/test/e2e/specs/editor/blocks/buttons.spec.js +++ b/test/e2e/specs/editor/blocks/buttons.spec.js @@ -291,11 +291,11 @@ test.describe( 'Buttons', () => { `role=region[name="Editor settings"i] >> role=tab[name="Styles"i]` ); await page.click( - 'role=region[name="Editor settings"i] >> role=button[name="Color Text styles"i]' + 'role=region[name="Editor settings"i] >> role=button[name="Text"i]' ); await page.click( 'role=option[name="Color: Cyan bluish gray"i]' ); await page.click( - 'role=region[name="Editor settings"i] >> role=button[name="Color Background styles"i]' + 'role=region[name="Editor settings"i] >> role=button[name="Background"i]' ); await page.click( 'role=option[name="Color: Vivid red"i]' ); @@ -320,13 +320,13 @@ test.describe( 'Buttons', () => { `role=region[name="Editor settings"i] >> role=tab[name="Styles"i]` ); await page.click( - 'role=region[name="Editor settings"i] >> role=button[name="Color Text styles"i]' + 'role=region[name="Editor settings"i] >> role=button[name="Text"i]' ); await page.click( 'role=button[name="Custom color picker."i]' ); await page.fill( 'role=textbox[name="Hex color"i]', 'ff0000' ); await page.click( - 'role=region[name="Editor settings"i] >> role=button[name="Color Background styles"i]' + 'role=region[name="Editor settings"i] >> role=button[name="Background"i]' ); await page.click( 'role=button[name="Custom color picker."i]' ); await page.fill( 'role=textbox[name="Hex color"i]', '00ff00' ); @@ -355,7 +355,7 @@ test.describe( 'Buttons', () => { `role=region[name="Editor settings"i] >> role=tab[name="Styles"i]` ); await page.click( - 'role=region[name="Editor settings"i] >> role=button[name="Color Background styles"i]' + 'role=region[name="Editor settings"i] >> role=button[name="Background"i]' ); await page.click( 'role=tab[name="Gradient"i]' ); await page.click( 'role=option[name="Gradient: Purple to yellow"i]' ); @@ -384,7 +384,7 @@ test.describe( 'Buttons', () => { `role=region[name="Editor settings"i] >> role=tab[name="Styles"i]` ); await page.click( - 'role=region[name="Editor settings"i] >> role=button[name="Color Background styles"i]' + 'role=region[name="Editor settings"i] >> role=button[name="Background"i]' ); await page.click( 'role=tab[name="Gradient"i]' ); await page.click( diff --git a/test/e2e/specs/editor/blocks/navigation-colors.spec.js b/test/e2e/specs/editor/blocks/navigation-colors.spec.js index 1ddd4af8ab2e13..8692b184fb13f9 100644 --- a/test/e2e/specs/editor/blocks/navigation-colors.spec.js +++ b/test/e2e/specs/editor/blocks/navigation-colors.spec.js @@ -91,13 +91,13 @@ test.describe( 'Navigation colors', () => { // In the sidebar inspector we add a link color and link hover color to the group block. await editor.openDocumentSettingsSidebar(); await page.getByRole( 'tab', { name: 'Styles' } ).click(); - await page.getByRole( 'button', { name: 'Color Text styles' } ).click(); + await page.getByRole( 'button', { name: 'Text' } ).click(); await page .getByRole( 'option', { name: 'Color: White' } ) .click( { force: true } ); await page - .getByRole( 'button', { name: 'Color Background styles' } ) + .getByRole( 'button', { name: 'Background', exact: true } ) .click(); await page .getByRole( 'option', { name: 'Color: Black' } ) @@ -148,7 +148,7 @@ test.describe( 'Navigation colors', () => { .getByRole( 'menuitemcheckbox', { name: 'Show Link' } ) .click(); await page.getByRole( 'tab', { name: 'Styles' } ).click(); - await page.getByRole( 'button', { name: 'Color Link styles' } ).click(); + await page.getByRole( 'button', { name: 'Link', exact: true } ).click(); // rga(207, 46 ,46) is the color of the "vivid red" color preset. await page .getByRole( 'option', { name: 'Color: Vivid red' } ) diff --git a/test/e2e/specs/editor/various/keep-styles-on-block-transforms.spec.js b/test/e2e/specs/editor/various/keep-styles-on-block-transforms.spec.js index 57b958fdfc4b44..32e3def9154ed1 100644 --- a/test/e2e/specs/editor/various/keep-styles-on-block-transforms.spec.js +++ b/test/e2e/specs/editor/various/keep-styles-on-block-transforms.spec.js @@ -17,7 +17,7 @@ test.describe( 'Keep styles on block transforms', () => { .locator( 'role=button[name="Add default block"i]' ) .click(); await page.keyboard.type( '## Heading' ); - await page.click( 'role=button[name="Color Text styles"i]' ); + await page.click( 'role=button[name="Text"i]' ); await page.click( 'role=option[name="Color: Luminous vivid orange"i]' ); await page.click( 'role=button[name="Heading"i]' ); diff --git a/test/e2e/specs/site-editor/font-library.spec.js b/test/e2e/specs/site-editor/font-library.spec.js index 7271768206d1b6..7928ef8f71c534 100644 --- a/test/e2e/specs/site-editor/font-library.spec.js +++ b/test/e2e/specs/site-editor/font-library.spec.js @@ -24,9 +24,7 @@ test.describe( 'Font Library', () => { .getByRole( 'region', { name: 'Editor top bar' } ) .getByRole( 'button', { name: 'Styles' } ) .click(); - await page - .getByRole( 'button', { name: 'Typography Styles' } ) - .click(); + await page.getByRole( 'button', { name: 'Typography' } ).click(); await page .getByRole( 'button', { name: 'Add fonts', @@ -43,9 +41,7 @@ test.describe( 'Font Library', () => { .getByRole( 'region', { name: 'Editor top bar' } ) .getByRole( 'button', { name: 'Styles' } ) .click(); - await page - .getByRole( 'button', { name: 'Typography Styles' } ) - .click(); + await page.getByRole( 'button', { name: 'Typography' } ).click(); const manageFontsIcon = page.getByRole( 'button', { name: 'Manage fonts', } ); @@ -71,9 +67,7 @@ test.describe( 'Font Library', () => { .getByRole( 'region', { name: 'Editor top bar' } ) .getByRole( 'button', { name: 'Styles' } ) .click(); - await page - .getByRole( 'button', { name: 'Typography Styles' } ) - .click(); + await page.getByRole( 'button', { name: 'Typography' } ).click(); const manageFontsIcon = page.getByRole( 'button', { name: 'Manage fonts', } ); @@ -87,9 +81,7 @@ test.describe( 'Font Library', () => { .getByRole( 'region', { name: 'Editor top bar' } ) .getByRole( 'button', { name: 'Styles' } ) .click(); - await page - .getByRole( 'button', { name: 'Typography Styles' } ) - .click(); + await page.getByRole( 'button', { name: 'Typography' } ).click(); await page .getByRole( 'button', { name: 'Manage fonts', @@ -108,9 +100,7 @@ test.describe( 'Font Library', () => { .getByRole( 'region', { name: 'Editor top bar' } ) .getByRole( 'button', { name: 'Styles' } ) .click(); - await page - .getByRole( 'button', { name: 'Typography Styles' } ) - .click(); + await page.getByRole( 'button', { name: 'Typography' } ).click(); await page .getByRole( 'button', { name: 'Manage fonts', @@ -160,9 +150,7 @@ test.describe( 'Font Library', () => { .getByRole( 'region', { name: 'Editor top bar' } ) .getByRole( 'button', { name: 'Styles' } ) .click(); - await page - .getByRole( 'button', { name: 'Typography Styles' } ) - .click(); + await page.getByRole( 'button', { name: 'Typography' } ).click(); await page .getByRole( 'button', { name: 'Add fonts', @@ -196,7 +184,7 @@ test.describe( 'Font Library', () => { // Check CSS preset was created. await page.getByRole( 'button', { name: 'Close' } ).click(); await page - .getByRole( 'button', { name: 'Typography Headings styles' } ) + .getByRole( 'button', { name: 'Headings', exact: true } ) .click(); await page.getByLabel( 'Font' ).selectOption( 'Exo 2' ); await expect( @@ -252,9 +240,7 @@ test.describe( 'Font Library', () => { // Click "Back" button await page.getByRole( 'button', { name: 'Back' } ).click(); - await page - .getByRole( 'button', { name: 'Typography styles' } ) - .click(); + await page.getByRole( 'button', { name: 'Typography' } ).click(); // Click "Jost 2 variants" button await page @@ -286,9 +272,7 @@ test.describe( 'Font Library', () => { // Click "Back" button await page.getByRole( 'button', { name: 'Back' } ).click(); - await page - .getByRole( 'button', { name: 'Typography styles' } ) - .click(); + await page.getByRole( 'button', { name: 'Typography' } ).click(); // Click Cardo font-family. await page diff --git a/test/e2e/specs/site-editor/global-styles-sidebar.spec.js b/test/e2e/specs/site-editor/global-styles-sidebar.spec.js index 0b034def6a3063..7f1b818df4ce0a 100644 --- a/test/e2e/specs/site-editor/global-styles-sidebar.spec.js +++ b/test/e2e/specs/site-editor/global-styles-sidebar.spec.js @@ -28,7 +28,7 @@ test.describe( 'Global styles sidebar', () => { .click(); await page .getByRole( 'region', { name: 'Editor settings' } ) - .getByRole( 'button', { name: 'Blocks styles' } ) + .getByRole( 'button', { name: 'Blocks' } ) .click(); await page @@ -38,11 +38,11 @@ test.describe( 'Global styles sidebar', () => { // Matches both Heading and Table of Contents blocks. // The latter contains "heading" in its description. await expect( - page.getByRole( 'button', { name: 'Heading block styles' } ) + page.getByRole( 'button', { name: 'Heading', exact: true } ) ).toBeVisible(); await expect( page.getByRole( 'button', { - name: 'Table of Contents block styles', + name: 'Table of Contents', } ) ).toBeVisible(); } ); diff --git a/test/e2e/specs/site-editor/push-to-global-styles.spec.js b/test/e2e/specs/site-editor/push-to-global-styles.spec.js index 26224a83e27ebd..3e30f764811b1f 100644 --- a/test/e2e/specs/site-editor/push-to-global-styles.spec.js +++ b/test/e2e/specs/site-editor/push-to-global-styles.spec.js @@ -29,13 +29,14 @@ test.describe( 'Push to Global Styles button', () => { await page.keyboard.type( 'A heading' ); const topBar = page.getByRole( 'region', { name: 'Editor top bar' } ); + const settingsPanel = page.getByRole( 'region', { + name: 'Editor settings', + } ); // Navigate to Styles -> Blocks -> Heading -> Typography await topBar.getByRole( 'button', { name: 'Styles' } ).click(); - await page.getByRole( 'button', { name: 'Blocks styles' } ).click(); - await page - .getByRole( 'button', { name: 'Heading block styles' } ) - .click(); + await settingsPanel.getByRole( 'button', { name: 'Blocks' } ).click(); + await settingsPanel.getByRole( 'button', { name: 'Heading' } ).click(); // Headings should not have uppercase await expect( @@ -95,9 +96,9 @@ test.describe( 'Push to Global Styles button', () => { await page .getByRole( 'button', { name: 'Styles', exact: true } ) .click(); - await page.getByRole( 'button', { name: 'Blocks styles' } ).click(); - await page - .getByRole( 'button', { name: 'Heading block styles' } ) + await page.getByRole( 'button', { name: 'Blocks' } ).click(); + await settingsPanel + .getByRole( 'button', { name: 'Heading', exact: true } ) .click(); // Headings should now have uppercase diff --git a/test/e2e/specs/site-editor/style-book.spec.js b/test/e2e/specs/site-editor/style-book.spec.js index 9a34f30f82ff9c..c94049872edcf6 100644 --- a/test/e2e/specs/site-editor/style-book.spec.js +++ b/test/e2e/specs/site-editor/style-book.spec.js @@ -97,8 +97,8 @@ test.describe( 'Style Book', () => { test( 'should allow to return Global Styles root when example is clicked', async ( { page, } ) => { - await page.click( 'role=button[name="Blocks styles"]' ); - await page.click( 'role=button[name="Heading block styles"]' ); + await page.click( 'role=button[name="Blocks"]' ); + await page.click( 'role=button[name="Heading"]' ); await page .frameLocator( '[name="style-book-canvas"]' ) @@ -111,7 +111,7 @@ test.describe( 'Style Book', () => { await page.click( 'role=button[name="Back"]' ); await expect( - page.locator( 'role=button[name="Blocks styles"]' ) + page.locator( 'role=button[name="Blocks"]' ) ).toBeVisible(); } ); diff --git a/test/e2e/specs/site-editor/style-variations.spec.js b/test/e2e/specs/site-editor/style-variations.spec.js index c4dad7c7d7546c..9c4243b0d171f6 100644 --- a/test/e2e/specs/site-editor/style-variations.spec.js +++ b/test/e2e/specs/site-editor/style-variations.spec.js @@ -78,23 +78,23 @@ test.describe( 'Global styles variations', () => { await siteEditorStyleVariations.browseStyles(); await page.click( 'role=button[name="pink"i]' ); await page.click( 'role=button[name="Back"i]' ); - await page.click( 'role=button[name="Colors styles"i]' ); + await page.click( 'role=button[name="Colors"i]' ); await expect( page.locator( - 'role=button[name="Color Background styles"i] >> .component-color-indicator' + 'role=button[name="Background"i] >> .component-color-indicator' ) ).toHaveCSS( 'background', /rgb\(202, 105, 211\)/ ); await expect( page.locator( - 'role=button[name="Color Text styles"i] >> .component-color-indicator' + 'role=button[name="Text"i] >> .component-color-indicator' ) ).toHaveCSS( 'background', /rgb\(74, 7, 74\)/ ); await page.click( 'role=button[name="Back"i]' ); - await page.click( 'role=button[name="Typography styles"i]' ); - await page.click( 'role=button[name="Typography Text styles"i]' ); + await page.click( 'role=button[name="Typography"i]' ); + await page.click( 'role=button[name="Text"i]' ); await expect( page.locator( 'css=.components-font-size-picker__header__hint' ) @@ -114,23 +114,23 @@ test.describe( 'Global styles variations', () => { await siteEditorStyleVariations.browseStyles(); await page.click( 'role=button[name="yellow"i]' ); await page.click( 'role=button[name="Back"i]' ); - await page.click( 'role=button[name="Colors styles"i]' ); + await page.click( 'role=button[name="Colors"i]' ); await expect( page.locator( - 'role=button[name="Color Background styles"i] >> .component-color-indicator' + 'role=button[name="Background"i] >> .component-color-indicator' ) ).toHaveCSS( 'background', /rgb\(255, 239, 11\)/ ); await expect( page.locator( - 'role=button[name="Color Text styles"i] >> .component-color-indicator' + 'role=button[name="Text"i] >> .component-color-indicator' ) ).toHaveCSS( 'background', /rgb\(25, 25, 17\)/ ); await page.click( 'role=button[name="Back"i]' ); - await page.click( 'role=button[name="Typography styles"i]' ); - await page.click( 'role=button[name="Typography Text styles"i]' ); + await page.click( 'role=button[name="Typography"i]' ); + await page.click( 'role=button[name="Text"i]' ); // TODO: to avoid use classnames to locate these elements, // we could provide accessible attributes to the source code in packages/components/src/font-size-picker/index.js. @@ -156,7 +156,7 @@ test.describe( 'Global styles variations', () => { await siteEditorStyleVariations.browseStyles(); await page.click( 'role=button[name="pink"i]' ); await page.click( 'role=button[name="Back"i]' ); - await page.click( 'role=button[name="Colors styles"i]' ); + await page.click( 'role=button[name="Colors"i]' ); await page.click( 'role=button[name="Edit palette"i]' ); await expect( diff --git a/test/e2e/specs/site-editor/styles.spec.js b/test/e2e/specs/site-editor/styles.spec.js index 8da9aa95c67567..63a051bf6b92d7 100644 --- a/test/e2e/specs/site-editor/styles.spec.js +++ b/test/e2e/specs/site-editor/styles.spec.js @@ -40,9 +40,9 @@ test.describe( 'Styles', () => { const topBar = page.getByRole( 'region', { name: 'Editor top bar' } ); // Navigate to Styles -> Blocks -> Heading -> Typography await topBar.getByRole( 'button', { name: 'Styles' } ).click(); - await page.getByRole( 'button', { name: 'Blocks styles' } ).click(); + await page.getByRole( 'button', { name: 'Blocks' } ).click(); await page - .getByRole( 'button', { name: 'Social Icons block styles' } ) + .getByRole( 'button', { name: 'Social Icons', exact: true } ) .click(); // Find the second padding control and change the padding value diff --git a/test/e2e/specs/site-editor/user-global-styles-revisions.spec.js b/test/e2e/specs/site-editor/user-global-styles-revisions.spec.js index f48c819c3a0891..e0b00fe1e59460 100644 --- a/test/e2e/specs/site-editor/user-global-styles-revisions.spec.js +++ b/test/e2e/specs/site-editor/user-global-styles-revisions.spec.js @@ -75,10 +75,8 @@ test.describe( 'Style Revisions', () => { } ) => { await editor.canvas.locator( 'body' ).click(); await userGlobalStylesRevisions.openStylesPanel(); - await page.getByRole( 'button', { name: 'Colors styles' } ).click(); - await page - .getByRole( 'button', { name: 'Color Background styles' } ) - .click(); + await page.getByRole( 'button', { name: 'Colors' } ).click(); + await page.getByRole( 'button', { name: 'Background' } ).click(); await page .getByRole( 'option', { name: 'Color: Luminous vivid amber' } ) .click( { force: true } ); From 388dd815225f6b880b180c75686ce4ec08bb4139 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Fri, 18 Oct 2024 19:10:53 +1100 Subject: [PATCH 1236/1908] Zoom Out: Disable zoom out toggle button when Style Book is open (#66228) Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: madhusudhand <madhudollu@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> --- packages/editor/src/components/header/index.js | 2 +- packages/editor/src/components/zoom-out-toggle/index.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index 631643f26d4d5f..d3c82a65a5bc6f 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -149,7 +149,7 @@ function Header( { ) } { canBeZoomedOut && isEditorIframed && isWideViewport && ( - <ZoomOutToggle /> + <ZoomOutToggle disabled={ forceDisableBlockTools } /> ) } <PreviewDropdown diff --git a/packages/editor/src/components/zoom-out-toggle/index.js b/packages/editor/src/components/zoom-out-toggle/index.js index 2cfb2e2da3bc44..e07cb6ac92c833 100644 --- a/packages/editor/src/components/zoom-out-toggle/index.js +++ b/packages/editor/src/components/zoom-out-toggle/index.js @@ -14,7 +14,7 @@ import { store as preferencesStore } from '@wordpress/preferences'; */ import { unlock } from '../../lock-unlock'; -const ZoomOutToggle = () => { +const ZoomOutToggle = ( { disabled } ) => { const { isZoomOut, showIconLabels } = useSelect( ( select ) => ( { isZoomOut: unlock( select( blockEditorStore ) ).isZoomOut(), showIconLabels: select( preferencesStore ).get( @@ -37,6 +37,8 @@ const ZoomOutToggle = () => { return ( <Button + accessibleWhenDisabled + disabled={ disabled } onClick={ handleZoomOut } icon={ zoomOutIcon } label={ __( 'Zoom Out' ) } From 9d2b3201cbde7f7a2304fe9e85257db460250bc1 Mon Sep 17 00:00:00 2001 From: Sagar Prajapati <sagarprajapati48@gmail.com> Date: Fri, 18 Oct 2024 15:57:42 +0530 Subject: [PATCH 1237/1908] Add featured image alt text (#66189) * Add featured image alt text * Updated duplicate code to function. * Modify doc * Minor adjustments for the docblock. --------- Co-authored-by: prajapatisagar <sagarprajapati@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../components/post-featured-image/index.js | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/packages/editor/src/components/post-featured-image/index.js b/packages/editor/src/components/post-featured-image/index.js index 9907eb5dd0f22d..cabd791e938bf5 100644 --- a/packages/editor/src/components/post-featured-image/index.js +++ b/packages/editor/src/components/post-featured-image/index.js @@ -121,6 +121,35 @@ function PostFeaturedImage( { } ); } + /** + * Generates the featured image alt text for this editing context. + * + * @param {Object} imageMedia The image media object. + * @param {string} imageMedia.alt_text The alternative text of the image. + * @param {Object} imageMedia.media_details The media details of the image. + * @param {Object} imageMedia.media_details.sizes The sizes of the image. + * @param {Object} imageMedia.media_details.sizes.full The full size details of the image. + * @param {string} imageMedia.media_details.sizes.full.file The file name of the full size image. + * @param {string} imageMedia.slug The slug of the image. + * @return {string} The featured image alt text. + */ + function getImageDescription( imageMedia ) { + if ( imageMedia.alt_text ) { + return sprintf( + // Translators: %s: The selected image alt text. + __( 'Current image: %s' ), + imageMedia.alt_text + ); + } + return sprintf( + // Translators: %s: The selected image filename. + __( + 'The current image has no alternative text. The file name is: %s' + ), + imageMedia.media_details.sizes?.full?.file || imageMedia.slug + ); + } + return ( <PostFeaturedImageCheck> { noticeUI } @@ -130,21 +159,7 @@ function PostFeaturedImage( { id={ `editor-post-featured-image-${ featuredImageId }-describedby` } className="hidden" > - { media.alt_text && - sprintf( - // Translators: %s: The selected image alt text. - __( 'Current image: %s' ), - media.alt_text - ) } - { ! media.alt_text && - sprintf( - // Translators: %s: The selected image filename. - __( - 'The current image has no alternative text. The file name is: %s' - ), - media.media_details.sizes?.full?.file || - media.slug - ) } + { getImageDescription( media ) } </div> ) } <MediaUploadCheck fallback={ instructions }> @@ -188,7 +203,7 @@ function PostFeaturedImage( { <img className="editor-post-featured-image__preview-image" src={ mediaSourceUrl } - alt="" + alt={ getImageDescription( media ) } /> ) } { isLoading && <Spinner /> } From e2097c31041a7b21ddb6e264a4fc15072d462d85 Mon Sep 17 00:00:00 2001 From: Django <mediaformat.ux@gmail.com> Date: Fri, 18 Oct 2024 04:31:19 -0600 Subject: [PATCH 1238/1908] Remove clip & -webkit-clip-path for downloadable-block-list-item style.scss (#66147) * Remove clip for screen-reader-text CSS * item__author display none while is-installing Co-authored-by: mediaformat <mediaformat@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> --- .../downloadable-block-list-item/style.scss | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/block-directory/src/components/downloadable-block-list-item/style.scss b/packages/block-directory/src/components/downloadable-block-list-item/style.scss index 6fce5e1b5b32a7..e13e46ef8d8786 100644 --- a/packages/block-directory/src/components/downloadable-block-list-item/style.scss +++ b/packages/block-directory/src/components/downloadable-block-list-item/style.scss @@ -38,17 +38,7 @@ &.is-installing { .block-directory-downloadable-block-list-item__author { - border: 0; - clip: rect(1px, 1px, 1px, 1px); - -webkit-clip-path: inset(50%); - clip-path: inset(50%); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; - word-wrap: normal !important; + display: none; } } } From 6c0bca194715f0624be38a0df2cde3d5c970a881 Mon Sep 17 00:00:00 2001 From: David Arenas <david.arenas@automattic.com> Date: Fri, 18 Oct 2024 12:54:39 +0200 Subject: [PATCH 1239/1908] Interactivity API: Fix reactivity of undefined objects and arrays added with `deepMerge` (#66183) * Fix types in test * Add failing tests * Fix the bug * Update changelog * Fix changelog * Update tests Co-authored-by: DAreRodz <darerodz@git.wordpress.org> Co-authored-by: michalczaplinski <czapla@git.wordpress.org> --- packages/interactivity/CHANGELOG.md | 4 ++ packages/interactivity/src/proxies/state.ts | 11 ++++- .../src/proxies/test/deep-merge.ts | 42 ++++++++++++++++++- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index b5a8fbcb9dde50..73212578ac109c 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- Fix reactivity of undefined objects and arrays added with `deepMerge()` ([#66183](https://github.com/WordPress/gutenberg/pull/66183)). + ## 6.10.0 (2024-10-16) ### Internal diff --git a/packages/interactivity/src/proxies/state.ts b/packages/interactivity/src/proxies/state.ts index f63c84738bcb1a..d4d573acba8847 100644 --- a/packages/interactivity/src/proxies/state.ts +++ b/packages/interactivity/src/proxies/state.ts @@ -335,7 +335,10 @@ const deepMergeRecursive = ( if ( isNew || ( override && ! isPlainObject( target[ key ] ) ) ) { target[ key ] = {}; if ( propSignal ) { - propSignal.setValue( target[ key ] ); + const ns = getNamespaceFromProxy( proxy ); + propSignal.setValue( + proxifyState( ns, target[ key ] as Object ) + ); } } if ( isPlainObject( target[ key ] ) ) { @@ -344,7 +347,11 @@ const deepMergeRecursive = ( } else if ( override || isNew ) { Object.defineProperty( target, key, desc ); if ( propSignal ) { - propSignal.setValue( desc.value ); + const { value } = desc; + const ns = getNamespaceFromProxy( proxy ); + propSignal.setValue( + shouldProxy( value ) ? proxifyState( ns, value ) : value + ); } } } diff --git a/packages/interactivity/src/proxies/test/deep-merge.ts b/packages/interactivity/src/proxies/test/deep-merge.ts index f475385a437876..267e4850f9af91 100644 --- a/packages/interactivity/src/proxies/test/deep-merge.ts +++ b/packages/interactivity/src/proxies/test/deep-merge.ts @@ -379,7 +379,10 @@ describe( 'Interactivity API', () => { const target = proxifyState< any >( 'test', { a: 1, b: 2 } ); const source = { a: 1, b: 2, c: 3 }; - const spy = jest.fn( () => Object.keys( target ) ); + let keys: any; + const spy = jest.fn( () => { + keys = Object.keys( target ); + } ); effect( spy ); expect( spy ).toHaveBeenCalledTimes( 1 ); @@ -387,7 +390,7 @@ describe( 'Interactivity API', () => { deepMerge( target, source, false ); expect( spy ).toHaveBeenCalledTimes( 2 ); - expect( spy ).toHaveLastReturnedWith( [ 'a', 'b', 'c' ] ); + expect( keys ).toEqual( [ 'a', 'b', 'c' ] ); } ); it( 'should handle deeply nested properties that are initially undefined', () => { @@ -412,6 +415,13 @@ describe( 'Interactivity API', () => { // Reading the value directly should also work expect( target.a.b.c.d ).toBe( 'test value' ); + + // Modify the nested value + target.a.b.c.d = 'new test value'; + + // The effect should be called again + expect( spy ).toHaveBeenCalledTimes( 3 ); + expect( deepValue ).toBe( 'new test value' ); } ); it( 'should overwrite values that become objects', () => { @@ -462,5 +472,33 @@ describe( 'Interactivity API', () => { expect( target.message.content ).toBeUndefined(); expect( target.message.fontStyle ).toBeUndefined(); } ); + + it( 'should keep reactivity of arrays that are initially undefined', () => { + const target: any = proxifyState( 'test', {} ); + + let deepValue: any; + const spy = jest.fn( () => { + deepValue = target.array?.[ 0 ]; + } ); + effect( spy ); + + // Initial call, the deep value is undefined + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( deepValue ).toBeUndefined(); + + // Use deepMerge to add an array to the target + deepMerge( target, { array: [ 'value 1' ] } ); + + // The effect should be called again + expect( spy ).toHaveBeenCalledTimes( 2 ); + expect( deepValue ).toBe( 'value 1' ); + + // Modify the array value + target.array[ 0 ] = 'value 2'; + + // The effect should be called again + expect( spy ).toHaveBeenCalledTimes( 3 ); + expect( deepValue ).toBe( 'value 2' ); + } ); } ); } ); From 5ee948aec84d88e436af0814de3e7e6461ead3c3 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 18 Oct 2024 13:13:13 +0200 Subject: [PATCH 1240/1908] Tabs: restore vertical alignment for tabs content (#66215) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/block-inspector/style.scss | 6 ------ .../src/components/inspector-controls-tabs/index.js | 7 +------ .../src/components/inspector-controls-tabs/utils.js | 3 --- packages/components/CHANGELOG.md | 1 + packages/components/src/tabs/styles.ts | 12 ++++++++++-- 5 files changed, 12 insertions(+), 17 deletions(-) diff --git a/packages/block-editor/src/components/block-inspector/style.scss b/packages/block-editor/src/components/block-inspector/style.scss index 92a9a0dd03ab35..e04dfd8e9a480a 100644 --- a/packages/block-editor/src/components/block-inspector/style.scss +++ b/packages/block-editor/src/components/block-inspector/style.scss @@ -46,9 +46,3 @@ .block-editor-block-inspector__no-block-tools { border-top: $border-width solid $gray-300; } - -.block-editor-block-inspector__tab-item { - flex: 1 1 0px; - display: flex; - justify-content: center; -} diff --git a/packages/block-editor/src/components/inspector-controls-tabs/index.js b/packages/block-editor/src/components/inspector-controls-tabs/index.js index c8d9536aeb9caf..12465df0ca467c 100644 --- a/packages/block-editor/src/components/inspector-controls-tabs/index.js +++ b/packages/block-editor/src/components/inspector-controls-tabs/index.js @@ -46,18 +46,13 @@ export default function InspectorControlsTabs( { <Tabs.TabList> { tabs.map( ( tab ) => showIconLabels ? ( - <Tabs.Tab - key={ tab.name } - tabId={ tab.name } - className={ tab.className } - > + <Tabs.Tab key={ tab.name } tabId={ tab.name }> { tab.title } </Tabs.Tab> ) : ( <Tooltip text={ tab.title } key={ tab.name }> <Tabs.Tab tabId={ tab.name } - className={ tab.className } aria-label={ tab.title } > <Icon icon={ tab.icon } /> diff --git a/packages/block-editor/src/components/inspector-controls-tabs/utils.js b/packages/block-editor/src/components/inspector-controls-tabs/utils.js index b70eb25e274a9b..ff05e79cbd37cc 100644 --- a/packages/block-editor/src/components/inspector-controls-tabs/utils.js +++ b/packages/block-editor/src/components/inspector-controls-tabs/utils.js @@ -9,7 +9,6 @@ export const TAB_SETTINGS = { title: __( 'Settings' ), value: 'settings', icon: cog, - className: 'block-editor-block-inspector__tab-item', }; export const TAB_STYLES = { @@ -17,7 +16,6 @@ export const TAB_STYLES = { title: __( 'Styles' ), value: 'styles', icon: styles, - className: 'block-editor-block-inspector__tab-item', }; export const TAB_LIST_VIEW = { @@ -25,5 +23,4 @@ export const TAB_LIST_VIEW = { title: __( 'List View' ), value: 'list-view', icon: listView, - className: 'block-editor-block-inspector__tab-item', }; diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 53ff933848338c..bd96eed8762b37 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -4,6 +4,7 @@ ### Bug Fixes +- `Tabs`: restore vertical alignent for tabs content ([#66215](https://github.com/WordPress/gutenberg/pull/66215)). - `Tabs`: fix indicator animation ([#66198](https://github.com/WordPress/gutenberg/pull/66198)). - `ColorPalette`: prevent overflow of custom color button background ([#66152](https://github.com/WordPress/gutenberg/pull/66152)). - `RadioGroup`: Fix arrow key navigation in RTL ([#66202](https://github.com/WordPress/gutenberg/pull/66202)). diff --git a/packages/components/src/tabs/styles.ts b/packages/components/src/tabs/styles.ts index 36e0ed6f6b0147..717316227ddb3c 100644 --- a/packages/components/src/tabs/styles.ts +++ b/packages/components/src/tabs/styles.ts @@ -207,7 +207,6 @@ export const Tab = styled( Ariakit.Tab )` [aria-orientation='horizontal'] & { padding-inline: ${ space( 4 ) }; height: ${ space( 12 ) }; - text-align: center; scroll-margin: 24px; &::after { @@ -219,7 +218,6 @@ export const Tab = styled( Ariakit.Tab )` [aria-orientation='vertical'] & { padding: ${ space( 2 ) } ${ space( 3 ) }; min-height: ${ space( 10 ) }; - text-align: start; &[aria-selected='true'] { color: ${ COLORS.theme.accent }; @@ -234,6 +232,16 @@ export const Tab = styled( Ariakit.Tab )` export const TabChildren = styled.span` flex-grow: 1; + + display: flex; + align-items: center; + + [aria-orientation='horizontal'] & { + justify-content: center; + } + [aria-orientation='vertical'] & { + justify-content: start; + } `; export const TabChevron = styled( Icon )` From 240180a808b59f03fd683128e4e7a431a9eaf9f9 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 18 Oct 2024 13:59:12 +0200 Subject: [PATCH 1241/1908] Tabs: align to standard compound components structure (#66225) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/src/private-apis.ts | 2 +- packages/components/src/tabs/index.tsx | 355 +++++++++--------- .../src/tabs/stories/index.story.tsx | 4 +- packages/components/src/tabs/test/index.tsx | 2 +- 4 files changed, 191 insertions(+), 172 deletions(-) diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index b6e033ab24ab74..51f820251b8d7c 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -6,7 +6,7 @@ import { createPrivateSlotFill } from './slot-fill'; import { DropdownMenuV2 } from './dropdown-menu-v2'; import { ComponentsContext } from './context/context-system-provider'; import Theme from './theme'; -import Tabs from './tabs'; +import { Tabs } from './tabs'; import { kebabCase } from './utils/strings'; import { lock } from './lock-unlock'; diff --git a/packages/components/src/tabs/index.tsx b/packages/components/src/tabs/index.tsx index 09225c0cce9b8d..37367e4642e152 100644 --- a/packages/components/src/tabs/index.tsx +++ b/packages/components/src/tabs/index.tsx @@ -25,192 +25,209 @@ import { Tab } from './tab'; import { TabList } from './tablist'; import { TabPanel } from './tabpanel'; -function Tabs( { - selectOnMove = true, - defaultTabId, - orientation = 'horizontal', - onSelect, - children, - selectedTabId, -}: TabsProps ) { - const instanceId = useInstanceId( Tabs, 'tabs' ); - const store = Ariakit.useTabStore( { - selectOnMove, - orientation, - defaultSelectedId: defaultTabId && `${ instanceId }-${ defaultTabId }`, - setSelectedId: ( selectedId ) => { - const strippedDownId = - typeof selectedId === 'string' - ? selectedId.replace( `${ instanceId }-`, '' ) - : selectedId; - onSelect?.( strippedDownId ); - }, - selectedId: selectedTabId && `${ instanceId }-${ selectedTabId }`, - rtl: isRTL(), - } ); - - const isControlled = selectedTabId !== undefined; - - const { items, selectedId, activeId } = useStoreState( store ); - const { setSelectedId, setActiveId } = store; - - // Keep track of whether tabs have been populated. This is used to prevent - // certain effects from firing too early while tab data and relevant - // variables are undefined during the initial render. - const tabsHavePopulatedRef = useRef( false ); - if ( items.length > 0 ) { - tabsHavePopulatedRef.current = true; - } +/** + * Display one panel of content at a time with a tabbed interface, based on the + * WAI-ARIA Tabs Pattern⁠. + * + * @see https://www.w3.org/WAI/ARIA/apg/patterns/tabs/ + * ``` + */ +export const Tabs = Object.assign( + function Tabs( { + selectOnMove = true, + defaultTabId, + orientation = 'horizontal', + onSelect, + children, + selectedTabId, + }: TabsProps ) { + const instanceId = useInstanceId( Tabs, 'tabs' ); + const store = Ariakit.useTabStore( { + selectOnMove, + orientation, + defaultSelectedId: + defaultTabId && `${ instanceId }-${ defaultTabId }`, + setSelectedId: ( selectedId ) => { + const strippedDownId = + typeof selectedId === 'string' + ? selectedId.replace( `${ instanceId }-`, '' ) + : selectedId; + onSelect?.( strippedDownId ); + }, + selectedId: selectedTabId && `${ instanceId }-${ selectedTabId }`, + rtl: isRTL(), + } ); - const selectedTab = items.find( ( item ) => item.id === selectedId ); - const firstEnabledTab = items.find( ( item ) => { - // Ariakit internally refers to disabled tabs as `dimmed`. - return ! item.dimmed; - } ); - const initialTab = items.find( - ( item ) => item.id === `${ instanceId }-${ defaultTabId }` - ); - - // Handle selecting the initial tab. - useLayoutEffect( () => { - if ( isControlled ) { - return; - } + const isControlled = selectedTabId !== undefined; + + const { items, selectedId, activeId } = useStoreState( store ); + const { setSelectedId, setActiveId } = store; - // Wait for the denoted initial tab to be declared before making a - // selection. This ensures that if a tab is declared lazily it can - // still receive initial selection, as well as ensuring no tab is - // selected if an invalid `defaultTabId` is provided. - if ( defaultTabId && ! initialTab ) { - return; + // Keep track of whether tabs have been populated. This is used to prevent + // certain effects from firing too early while tab data and relevant + // variables are undefined during the initial render. + const tabsHavePopulatedRef = useRef( false ); + if ( items.length > 0 ) { + tabsHavePopulatedRef.current = true; } - // If the currently selected tab is missing (i.e. removed from the DOM), - // fall back to the initial tab or the first enabled tab if there is - // one. Otherwise, no tab should be selected. - if ( ! items.find( ( item ) => item.id === selectedId ) ) { - if ( initialTab && ! initialTab.dimmed ) { - setSelectedId( initialTab?.id ); + const selectedTab = items.find( ( item ) => item.id === selectedId ); + const firstEnabledTab = items.find( ( item ) => { + // Ariakit internally refers to disabled tabs as `dimmed`. + return ! item.dimmed; + } ); + const initialTab = items.find( + ( item ) => item.id === `${ instanceId }-${ defaultTabId }` + ); + + // Handle selecting the initial tab. + useLayoutEffect( () => { + if ( isControlled ) { return; } - if ( firstEnabledTab ) { - setSelectedId( firstEnabledTab.id ); - } else if ( tabsHavePopulatedRef.current ) { - setSelectedId( null ); + // Wait for the denoted initial tab to be declared before making a + // selection. This ensures that if a tab is declared lazily it can + // still receive initial selection, as well as ensuring no tab is + // selected if an invalid `defaultTabId` is provided. + if ( defaultTabId && ! initialTab ) { + return; } - } - }, [ - firstEnabledTab, - initialTab, - defaultTabId, - isControlled, - items, - selectedId, - setSelectedId, - ] ); - - // Handle the currently selected tab becoming disabled. - useLayoutEffect( () => { - if ( ! selectedTab?.dimmed ) { - return; - } - - // In controlled mode, we trust that disabling tabs is done - // intentionally, and don't select a new tab automatically. - if ( isControlled ) { - setSelectedId( null ); - return; - } - // If the currently selected tab becomes disabled, fall back to the - // `defaultTabId` if possible. Otherwise select the first - // enabled tab (if there is one). - if ( initialTab && ! initialTab.dimmed ) { - setSelectedId( initialTab.id ); - return; - } - - if ( firstEnabledTab ) { - setSelectedId( firstEnabledTab.id ); - } - }, [ - firstEnabledTab, - initialTab, - isControlled, - selectedTab?.dimmed, - setSelectedId, - ] ); - - // Clear `selectedId` if the active tab is removed from the DOM in controlled mode. - useLayoutEffect( () => { - if ( ! isControlled ) { - return; - } - - // Once the tabs have populated, if the `selectedTabId` still can't be - // found, clear the selection. - if ( - tabsHavePopulatedRef.current && - !! selectedTabId && - ! selectedTab - ) { - setSelectedId( null ); - } - }, [ isControlled, selectedTab, selectedTabId, setSelectedId ] ); + // If the currently selected tab is missing (i.e. removed from the DOM), + // fall back to the initial tab or the first enabled tab if there is + // one. Otherwise, no tab should be selected. + if ( ! items.find( ( item ) => item.id === selectedId ) ) { + if ( initialTab && ! initialTab.dimmed ) { + setSelectedId( initialTab?.id ); + return; + } + + if ( firstEnabledTab ) { + setSelectedId( firstEnabledTab.id ); + } else if ( tabsHavePopulatedRef.current ) { + setSelectedId( null ); + } + } + }, [ + firstEnabledTab, + initialTab, + defaultTabId, + isControlled, + items, + selectedId, + setSelectedId, + ] ); + + // Handle the currently selected tab becoming disabled. + useLayoutEffect( () => { + if ( ! selectedTab?.dimmed ) { + return; + } - useEffect( () => { - // If there is no active tab, fallback to place focus on the first enabled tab - // so there is always an active element - if ( selectedTabId === null && ! activeId && firstEnabledTab?.id ) { - setActiveId( firstEnabledTab.id ); - } - }, [ selectedTabId, activeId, firstEnabledTab?.id, setActiveId ] ); + // In controlled mode, we trust that disabling tabs is done + // intentionally, and don't select a new tab automatically. + if ( isControlled ) { + setSelectedId( null ); + return; + } - useEffect( () => { - if ( ! isControlled ) { - return; - } + // If the currently selected tab becomes disabled, fall back to the + // `defaultTabId` if possible. Otherwise select the first + // enabled tab (if there is one). + if ( initialTab && ! initialTab.dimmed ) { + setSelectedId( initialTab.id ); + return; + } - requestAnimationFrame( () => { - const focusedElement = - items?.[ 0 ]?.element?.ownerDocument.activeElement; + if ( firstEnabledTab ) { + setSelectedId( firstEnabledTab.id ); + } + }, [ + firstEnabledTab, + initialTab, + isControlled, + selectedTab?.dimmed, + setSelectedId, + ] ); + + // Clear `selectedId` if the active tab is removed from the DOM in controlled mode. + useLayoutEffect( () => { + if ( ! isControlled ) { + return; + } + // Once the tabs have populated, if the `selectedTabId` still can't be + // found, clear the selection. if ( - ! focusedElement || - ! items.some( ( item ) => focusedElement === item.element ) + tabsHavePopulatedRef.current && + !! selectedTabId && + ! selectedTab ) { - return; // Return early if no tabs are focused. + setSelectedId( null ); } + }, [ isControlled, selectedTab, selectedTabId, setSelectedId ] ); - // If, after ariakit re-computes the active tab, that tab doesn't match - // the currently focused tab, then we force an update to ariakit to avoid - // any mismatches, especially when navigating to previous/next tab with - // arrow keys. - if ( activeId !== focusedElement.id ) { - setActiveId( focusedElement.id ); + useEffect( () => { + // If there is no active tab, fallback to place focus on the first enabled tab + // so there is always an active element + if ( selectedTabId === null && ! activeId && firstEnabledTab?.id ) { + setActiveId( firstEnabledTab.id ); + } + }, [ selectedTabId, activeId, firstEnabledTab?.id, setActiveId ] ); + + useEffect( () => { + if ( ! isControlled ) { + return; } - } ); - }, [ activeId, isControlled, items, setActiveId ] ); - const contextValue = useMemo( - () => ( { - store, - instanceId, + requestAnimationFrame( () => { + const focusedElement = + items?.[ 0 ]?.element?.ownerDocument.activeElement; + + if ( + ! focusedElement || + ! items.some( ( item ) => focusedElement === item.element ) + ) { + return; // Return early if no tabs are focused. + } + + // If, after ariakit re-computes the active tab, that tab doesn't match + // the currently focused tab, then we force an update to ariakit to avoid + // any mismatches, especially when navigating to previous/next tab with + // arrow keys. + if ( activeId !== focusedElement.id ) { + setActiveId( focusedElement.id ); + } + } ); + }, [ activeId, isControlled, items, setActiveId ] ); + + const contextValue = useMemo( + () => ( { + store, + instanceId, + } ), + [ store, instanceId ] + ); + + return ( + <TabsContext.Provider value={ contextValue }> + { children } + </TabsContext.Provider> + ); + }, + { + Tab: Object.assign( Tab, { + displayName: 'Tabs.Tab', + } ), + TabList: Object.assign( TabList, { + displayName: 'Tabs.TabList', } ), - [ store, instanceId ] - ); - - return ( - <TabsContext.Provider value={ contextValue }> - { children } - </TabsContext.Provider> - ); -} - -Tabs.TabList = TabList; -Tabs.Tab = Tab; -Tabs.TabPanel = TabPanel; -Tabs.Context = TabsContext; - -export default Tabs; + TabPanel: Object.assign( TabPanel, { + displayName: 'Tabs.TabPanel', + } ), + Context: Object.assign( TabsContext, { + displayName: 'Tabs.Context', + } ), + } +); diff --git a/packages/components/src/tabs/stories/index.story.tsx b/packages/components/src/tabs/stories/index.story.tsx index 5141a48a899502..5b2fd621bbb436 100644 --- a/packages/components/src/tabs/stories/index.story.tsx +++ b/packages/components/src/tabs/stories/index.story.tsx @@ -12,7 +12,7 @@ import { useState } from '@wordpress/element'; /** * Internal dependencies */ -import Tabs from '..'; +import { Tabs } from '..'; import { Slot, Fill, Provider as SlotFillProvider } from '../../slot-fill'; import DropdownMenu from '../../dropdown-menu'; import Button from '../../button'; @@ -30,6 +30,8 @@ const meta: Meta< typeof Tabs > = { 'Tabs.Tab': Tabs.Tab, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 'Tabs.TabPanel': Tabs.TabPanel, + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + 'Tabs.Context': Tabs.Context, }, tags: [ 'status-private' ], parameters: { diff --git a/packages/components/src/tabs/test/index.tsx b/packages/components/src/tabs/test/index.tsx index 0563b0227d106e..82c75a3f16b253 100644 --- a/packages/components/src/tabs/test/index.tsx +++ b/packages/components/src/tabs/test/index.tsx @@ -13,7 +13,7 @@ import { useEffect, useState } from '@wordpress/element'; /** * Internal dependencies */ -import Tabs from '..'; +import { Tabs } from '..'; import type { TabsProps } from '../types'; type Tab = { From fa120809525a00ee4cd49c88e15f4520fc9c9d04 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 18 Oct 2024 14:17:06 +0200 Subject: [PATCH 1242/1908] Tabs: update indicator more reactively (#66207) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/tabs/tablist.tsx | 32 ++++++++++++------- packages/components/src/utils/element-rect.ts | 17 ++++++++-- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index bd96eed8762b37..9b3c31814fc59a 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -10,6 +10,7 @@ - `RadioGroup`: Fix arrow key navigation in RTL ([#66202](https://github.com/WordPress/gutenberg/pull/66202)). - `Tabs` and `TabPanel`: Fix arrow key navigation in RTL ([#66201](https://github.com/WordPress/gutenberg/pull/66201)). - `Tabs`: override tablist's tabindex only when necessary ([#66209](https://github.com/WordPress/gutenberg/pull/66209)). +- `Tabs`: update indicator more reactively ([#66207](https://github.com/WordPress/gutenberg/pull/66207)). ### Enhancements diff --git a/packages/components/src/tabs/tablist.tsx b/packages/components/src/tabs/tablist.tsx index 998da5707aa071..181c705e7148cf 100644 --- a/packages/components/src/tabs/tablist.tsx +++ b/packages/components/src/tabs/tablist.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { useStoreState } from '@ariakit/react'; +import * as Ariakit from '@ariakit/react'; +import clsx from 'clsx'; /** * WordPress dependencies @@ -14,11 +15,10 @@ import { useMergeRefs } from '@wordpress/compose'; * Internal dependencies */ import type { TabListProps } from './types'; -import { useTabsContext } from './context'; -import { StyledTabList } from './styles'; import type { WordPressComponentProps } from '../context'; -import clsx from 'clsx'; import type { ElementOffsetRect } from '../utils/element-rect'; +import { useTabsContext } from './context'; +import { StyledTabList } from './styles'; import { useTrackElementOffsetRect } from '../utils/element-rect'; import { useTrackOverflow } from './use-track-overflow'; import { useAnimatedOffsetRect } from '../utils/hooks/use-animated-offset-rect'; @@ -62,15 +62,25 @@ export const TabList = forwardRef< >( function TabList( { children, ...otherProps }, ref ) { const { store } = useTabsContext() ?? {}; - const selectedId = useStoreState( store, 'selectedId' ); - const activeId = useStoreState( store, 'activeId' ); - const selectOnMove = useStoreState( store, 'selectOnMove' ); - const items = useStoreState( store, 'items' ); + const selectedId = Ariakit.useStoreState( store, 'selectedId' ); + const activeId = Ariakit.useStoreState( store, 'activeId' ); + const selectOnMove = Ariakit.useStoreState( store, 'selectOnMove' ); + const items = Ariakit.useStoreState( store, 'items' ); const [ parent, setParent ] = useState< HTMLElement >(); const refs = useMergeRefs( [ ref, setParent ] ); - const selectedRect = useTrackElementOffsetRect( - store?.item( selectedId )?.element - ); + + const selectedItem = store?.item( selectedId ); + const renderedItems = Ariakit.useStoreState( store, 'renderedItems' ); + + const selectedItemIndex = + renderedItems && selectedItem + ? renderedItems.indexOf( selectedItem ) + : -1; + // Use selectedItemIndex as a dependency to force recalculation when the + // selected item index changes (elements are swapped / added / removed). + const selectedRect = useTrackElementOffsetRect( selectedItem?.element, [ + selectedItemIndex, + ] ); // Track overflow to show scroll hints. const overflow = useTrackOverflow( parent, { diff --git a/packages/components/src/utils/element-rect.ts b/packages/components/src/utils/element-rect.ts index 7c83db4428ca0f..7f9693ef9f7df2 100644 --- a/packages/components/src/utils/element-rect.ts +++ b/packages/components/src/utils/element-rect.ts @@ -134,14 +134,17 @@ const POLL_RATE = 100; * milliseconds until it succeeds. */ export function useTrackElementOffsetRect( - targetElement: HTMLElement | undefined | null + targetElement: HTMLElement | undefined | null, + deps: unknown[] = [] ) { const [ indicatorPosition, setIndicatorPosition ] = useState< ElementOffsetRect >( NULL_ELEMENT_OFFSET_RECT ); const intervalRef = useRef< ReturnType< typeof setInterval > >(); const measure = useEvent( () => { - if ( targetElement ) { + // Check that the targetElement is still attached to the DOM, in case + // it was removed since the last `measure` call. + if ( targetElement && targetElement.isConnected ) { const elementOffsetRect = getElementOffsetRect( targetElement ); if ( elementOffsetRect ) { setIndicatorPosition( elementOffsetRect ); @@ -171,6 +174,16 @@ export function useTrackElementOffsetRect( } }, [ setElement, targetElement ] ); + // Escape hatch to force a remeasurement when something else changes rather + // than the target elements' ref or size (for example, the target element + // can change its position within the tablist). + useLayoutEffect( () => { + measure(); + // `measure` is a stable function, so it's safe to omit it from the deps array. + // deps can't be statically analyzed by ESLint + // eslint-disable-next-line react-hooks/exhaustive-deps + }, deps ); + return indicatorPosition; } From 220547e332c1e3d4a4e123b15ddcb40fc3420f8d Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 18 Oct 2024 14:54:12 +0200 Subject: [PATCH 1243/1908] Tabs: expose active tab item props, use ariakit prop types (#66223) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 14 ++- packages/components/src/tabs/README.md | 84 +++++++++++---- packages/components/src/tabs/types.ts | 138 ++++++++++++++++--------- 3 files changed, 161 insertions(+), 75 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 9b3c31814fc59a..165ce7e3748557 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -4,18 +4,22 @@ ### Bug Fixes -- `Tabs`: restore vertical alignent for tabs content ([#66215](https://github.com/WordPress/gutenberg/pull/66215)). -- `Tabs`: fix indicator animation ([#66198](https://github.com/WordPress/gutenberg/pull/66198)). - `ColorPalette`: prevent overflow of custom color button background ([#66152](https://github.com/WordPress/gutenberg/pull/66152)). - `RadioGroup`: Fix arrow key navigation in RTL ([#66202](https://github.com/WordPress/gutenberg/pull/66202)). -- `Tabs` and `TabPanel`: Fix arrow key navigation in RTL ([#66201](https://github.com/WordPress/gutenberg/pull/66201)). -- `Tabs`: override tablist's tabindex only when necessary ([#66209](https://github.com/WordPress/gutenberg/pull/66209)). -- `Tabs`: update indicator more reactively ([#66207](https://github.com/WordPress/gutenberg/pull/66207)). ### Enhancements - `PaletteEdit`: use `Item` internally instead of custom styles ([#66164](https://github.com/WordPress/gutenberg/pull/66164)). +### Experimental + +- `Tabs`: add props to control active tab item ([#66223](https://github.com/WordPress/gutenberg/pull/66223)). +- `Tabs`: restore vertical alignent for tabs content ([#66215](https://github.com/WordPress/gutenberg/pull/66215)). +- `Tabs`: fix indicator animation ([#66198](https://github.com/WordPress/gutenberg/pull/66198)). +- `Tabs`: update indicator more reactively ([#66207](https://github.com/WordPress/gutenberg/pull/66207)). +- `Tabs` and `TabPanel`: Fix arrow key navigation in RTL ([#66201](https://github.com/WordPress/gutenberg/pull/66201)). +- `Tabs`: override tablist's tabindex only when necessary ([#66209](https://github.com/WordPress/gutenberg/pull/66209)). + ## 28.10.0 (2024-10-16) ### Bug Fixes diff --git a/packages/components/src/tabs/README.md b/packages/components/src/tabs/README.md index 6eaadc0ae0b19d..9c7e846046c904 100644 --- a/packages/components/src/tabs/README.md +++ b/packages/components/src/tabs/README.md @@ -109,45 +109,81 @@ Tabs is comprised of four individual components: ###### `children`: `React.ReactNode` -The children elements, which should be at least a `Tabs.Tablist` component and a series of `Tabs.TabPanel` components. +The children elements, which should include one instance of the `Tabs.Tablist` component and as many instances of the `Tabs.TabPanel` components as there are `Tabs.Tab` components. - Required: Yes ###### `selectOnMove`: `boolean` -When `true`, the tab will be selected when receiving focus (automatic tab activation). When `false`, the tab will be selected only when clicked (manual tab activation). See the [official W3C docs](https://www.w3.org/WAI/ARIA/apg/patterns/tabpanel/) for more info. +Determines if the tab should be selected when it receives focus. If set to `false`, the tab will only be selected upon clicking, not when using arrow keys to shift focus (manual tab activation). See the [official W3C docs](https://www.w3.org/WAI/ARIA/apg/patterns/tabpanel/) for more info. - Required: No - Default: `true` -###### `defaultTabId`: `string` +###### `selectedTabId`: `string | null` + +The id of the tab whose panel is currently visible. + +If left `undefined`, it will be automatically set to the first enabled tab, and the component assumes it is being used in "uncontrolled" mode. + +Consequently, any value different than `undefined` will set the component in "controlled" mode. When in "controlled" mode, the `null` value will result in no tabs being selected, and the tablist becoming tabbable. + +- Required: No + +###### `defaultTabId`: `string | null` -The id of the tab to be selected upon mounting of component. If this prop is not set, the first tab will be selected by default. The id provided will be internally prefixed with a unique instance ID to avoid collisions. +The id of the tab whose panel is currently visible. -_Note: this prop will be overridden by the `selectedTabId` prop if it is provided. (Controlled Mode)_ +If left `undefined`, it will be automatically set to the first enabled tab. If set to `null`, no tab will be selected, and the tablist will be tabbable. + +_Note: this prop will be overridden by the `selectedTabId` prop if it is provided (meaning the component will be used in "controlled" mode)._ - Required: No ###### `onSelect`: `( ( selectedId: string | null | undefined ) => void )` -The function called when a tab has been selected. It is passed the selected tab's ID as an argument. +The function called when the `selectedTabId` changes. - Required: No - Default: `noop` -###### `orientation`: `horizontal | vertical` +###### `activeTabId`: `string | null` + +The current active tab `id`. The active tab is the tab element within the tablist widget that has DOM focus. + +- `null` represents the tablist (ie. the base composite element). Users + will be able to navigate out of it using arrow keys; +- If `activeTabId` is initially set to `null`, the base composite element + itself will have focus and users will be able to navigate to it using + arrow keys. + +- Required: No + +###### `defaultActiveTabId`: `string | null` + +The tab id that should be active by default when the composite widget is rendered. If `null`, the tablist element itself will have focus and users will be able to navigate to it using arrow keys. If `undefined`, the first enabled item will be focused. -The orientation of the `tablist` (`vertical` or `horizontal`) +_Note: this prop will be overridden by the `activeTabId` prop if it is provided._ - Required: No -- Default: `horizontal` -###### `selectedTabId`: `string | null` +###### `onActiveTabIdChange`: `( ( activeId: string | null | undefined ) => void )` -The ID of the tab to display. This id is prepended with the `Tabs` instanceId internally. -If left `undefined`, the component assumes it is being used in uncontrolled mode. Consequently, any value different than `undefined` will set the component in `controlled` mode. When in controlled mode, the `null` value will result in no tab being selected. +The function called when the `selectedTabId` changes. -- Required: No +- Required: No +- Default: `noop` + +###### `orientation`: `'horizontal' | 'vertical' | 'both'` + +Defines the orientation of the tablist and determines which arrow keys can be used to move focus: + +- `both`: all arrow keys work; +- `horizontal`: only left and right arrow keys work; +- `vertical`: only up and down arrow keys work. + +- Required: No +- Default: `horizontal` #### TabList @@ -155,7 +191,7 @@ If left `undefined`, the component assumes it is being used in uncontrolled mode ###### `children`: `React.ReactNode` -The children elements, which should be a series of `Tabs.TabPanel` components. +The children elements, which should include one or more instances of the `Tabs.Tab` component. - Required: No @@ -165,26 +201,28 @@ The children elements, which should be a series of `Tabs.TabPanel` components. ###### `tabId`: `string` -A unique identifier for the tab, which is used to generate a unique id for the underlying element. The value of this prop should match with the value of the `tabId` prop on the corresponding `Tabs.TabPanel` component. +The unique ID of the tab. It will be used to register the tab and match it to a corresponding `Tabs.TabPanel` component. If not provided, a unique ID will be automatically generated. - Required: Yes ###### `children`: `React.ReactNode` -The children elements, generally the text to display on the tab. +The contents of the tab. - Required: No ###### `disabled`: `boolean` -Determines if the tab button should be disabled. +Determines if the tab should be disabled. Note that disabled tabs can still be accessed via the keyboard when navigating through the tablist. - Required: No - Default: `false` ###### `render`: `React.ReactNode` -The type of component to render the tab button as. If this prop is not provided, the tab button will be rendered as a `button` element. +Allows the component to be rendered as a different HTML element or React component. The value can be a React element or a function that takes in the original component props and gives back a React element with the props merged. + +By default, the tab will be rendered as a `button` element. - Required: No @@ -194,19 +232,23 @@ The type of component to render the tab button as. If this prop is not provided, ###### `children`: `React.ReactNode` -The children elements, generally the content to display on the tabpanel. +The contents of the tab panel. - Required: No ###### `tabId`: `string` -A unique identifier for the tabpanel, which is used to generate an instanced id for the underlying element. The value of this prop should match with the value of the `tabId` prop on the corresponding `Tabs.Tab` component. +The unique `id` of the `Tabs.Tab` component controlling this panel. This connection is used to assign the `aria-labelledby` attribute to the tab panel and to determine if the tab panel should be visible. + +If not provided, this link is automatically established by matching the order of `Tabs.Tab` and `Tabs.TabPanel` elements in the DOM. - Required: Yes ###### `focusable`: `boolean` -Determines whether or not the tabpanel element should be focusable. If `false`, pressing the tab key will skip over the tabpanel, and instead focus on the first focusable element in the panel (if there is one). +Determines whether or not the tabpanel element should be focusable. + +If `false`, pressing the tab key will skip over the tabpanel, and instead focus on the first focusable element in the panel (if there is one). - Required: No - Default: `true` diff --git a/packages/components/src/tabs/types.ts b/packages/components/src/tabs/types.ts index 29baf25f224f7a..959a82509a05d6 100644 --- a/packages/components/src/tabs/types.ts +++ b/packages/components/src/tabs/types.ts @@ -18,98 +18,138 @@ export type TabsContextProps = export type TabsProps = { /** - * The children elements, which should be at least a - * `Tabs.Tablist` component and a series of `Tabs.TabPanel` - * components. + * The children elements, which should include one instance of the + * `Tabs.Tablist` component and as many instances of the `Tabs.TabPanel` + * components as there are `Tabs.Tab` components. */ - children: React.ReactNode; + children: Ariakit.TabProps[ 'children' ]; /** - * When `true`, the tab will be selected when receiving focus (automatic tab - * activation). When `false`, the tab will be selected only when clicked - * (manual tab activation). See the official W3C docs for more info. + * Determines if the tab should be selected when it receives focus. If set to + * `false`, the tab will only be selected upon clicking, not when using arrow + * keys to shift focus (manual tab activation). See the official W3C docs + * for more info. * * @default true * * @see https://www.w3.org/WAI/ARIA/apg/patterns/tabpanel/ */ - selectOnMove?: boolean; + selectOnMove?: Ariakit.TabStoreProps[ 'selectOnMove' ]; /** - * The id of the tab to be selected upon mounting of component. - * If this prop is not set, the first tab will be selected by default. - * The id provided will be internally prefixed with the - * `TabsContextProps.instanceId`. + * The id of the tab whose panel is currently visible. + * + * If left `undefined`, it will be automatically set to the first enabled + * tab, and the component assumes it is being used in "uncontrolled" mode. + * + * Consequently, any value different than `undefined` will set the component + * in "controlled" mode. When in "controlled" mode, the `null` value will + * result in no tabs being selected, and the tablist becoming tabbable. + */ + selectedTabId?: Ariakit.TabStoreProps[ 'selectedId' ]; + /** + * The id of the tab whose panel is currently visible. + * + * If left `undefined`, it will be automatically set to the first enabled + * tab. If set to `null`, no tab will be selected, and the tablist will be + * tabbable. * * Note: this prop will be overridden by the `selectedTabId` prop if it is - * provided. (Controlled Mode) + * provided (meaning the component will be used in "controlled" mode). */ - defaultTabId?: string; + defaultTabId?: Ariakit.TabStoreProps[ 'defaultSelectedId' ]; /** - * The function called when a tab has been selected. - * It is passed the id of the newly selected tab as an argument. + * The function called when the `selectedTabId` changes. */ - onSelect?: ( selectedId: string | null | undefined ) => void; - + onSelect?: Ariakit.TabStoreProps[ 'setSelectedId' ]; /** - * The orientation of the tablist. + * The current active tab `id`. The active tab is the tab element within the + * tablist widget that has DOM focus. + * - `null` represents the tablist (ie. the base composite element). Users + * will be able to navigate out of it using arrow keys. + * - If `activeTabId` is initially set to `null`, the base composite element + * itself will have focus and users will be able to navigate to it using + * arrow keys.activeTabId + */ + activeTabId?: Ariakit.TabStoreProps[ 'activeId' ]; + /** + * The tab id that should be active by default when the composite widget is + * rendered. If `null`, the tablist element itself will have focus + * and users will be able to navigate to it using arrow keys. If `undefined`, + * the first enabled item will be focused. * - * @default `horizontal` + * Note: this prop will be overridden by the `activeTabId` prop if it is + * provided. + */ + defaultActiveTabId?: Ariakit.TabStoreProps[ 'defaultActiveId' ]; + /** + * A callback that gets called when the `activeTabId` state changes. */ - orientation?: 'horizontal' | 'vertical'; + onActiveTabIdChange?: Ariakit.TabStoreProps[ 'setActiveId' ]; /** - * The Id of the tab to display. This id is prepended with the `Tabs` - * instanceId internally. + * Defines the orientation of the tablist and determines which arrow keys + * can be used to move focus: + * - `both`: all arrow keys work. + * - `horizontal`: only left and right arrow keys work. + * - `vertical`: only up and down arrow keys work. * - * If left `undefined`, the component assumes it is being used in - * uncontrolled mode. Consequently, any value different than `undefined` - * will set the component in `controlled` mode. - * When in controlled mode, the `null` value will result in no tab being selected. + * @default "horizontal" */ - selectedTabId?: string | null; + orientation?: Ariakit.TabStoreProps[ 'orientation' ]; }; export type TabListProps = { /** - * The children elements, which should be a series of `Tabs.TabPanel` components. + * The children elements, which should include one or more instances of the + * `Tabs.Tab` component. */ - children?: React.ReactNode; + children: Ariakit.TabListProps[ 'children' ]; }; +// TODO: consider prop name changes (tabId, selectedTabId) +// switch to auto-generated README +// compound technique + export type TabProps = { /** - * The id of the tab, which is prepended with the `Tabs` instanceId. - * The value of this prop should match with the value of the `tabId` prop on - * the corresponding `Tabs.TabPanel` component. + * The unique ID of the tab. It will be used to register the tab and match + * it to a corresponding `Tabs.TabPanel` component. */ - tabId: string; + tabId: NonNullable< Ariakit.TabProps[ 'id' ] >; /** - * The children elements, generally the text to display on the tab. + * The contents of the tab. */ - children?: React.ReactNode; + children?: Ariakit.TabProps[ 'children' ]; /** - * Determines if the tab button should be disabled. + * Determines if the tab should be disabled. Note that disabled tabs can + * still be accessed via the keyboard when navigating through the tablist. * * @default false */ - disabled?: boolean; + disabled?: Ariakit.TabProps[ 'disabled' ]; /** - * The type of component to render the tab button as. If this prop is not - * provided, the tab button will be rendered as a `button` element. + * Allows the component to be rendered as a different HTML element or React + * component. The value can be a React element or a function that takes in the + * original component props and gives back a React element with the props + * merged. + * + * By default, the tab will be rendered as a `button` element. */ - render?: React.ReactElement; + render?: Ariakit.TabProps[ 'render' ]; }; export type TabPanelProps = { /** - * The children elements, generally the content to display on the tabpanel. + * The contents of the tab panel. */ - children?: React.ReactNode; + children?: Ariakit.TabPanelProps[ 'children' ]; /** - * A unique identifier for the tabpanel, which is used to generate an - * instanced id for the underlying element. - * The value of this prop should match with the value of the `tabId` prop on - * the corresponding `Tabs.Tab` component. + * The unique `id` of the `Tabs.Tab` component controlling this panel. This + * connection is used to assign the `aria-labelledby` attribute to the tab + * panel and to determine if the tab panel should be visible. + * + * If not provided, this link is automatically established by matching the + * order of `Tabs.Tab` and `Tabs.TabPanel` elements in the DOM. */ - tabId: string; + tabId: NonNullable< Ariakit.TabPanelProps[ 'tabId' ] >; /** * Determines whether or not the tabpanel element should be focusable. * If `false`, pressing the tab key will skip over the tabpanel, and instead @@ -117,5 +157,5 @@ export type TabPanelProps = { * * @default true */ - focusable?: boolean; + focusable?: Ariakit.TabPanelProps[ 'focusable' ]; }; From 219696636c990e558a47ace60c15d8e3e05ca1af Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Fri, 18 Oct 2024 15:09:06 +0100 Subject: [PATCH 1244/1908] Add foundations:elevation to storybook (#66124) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../foundations/design-language/elevation.mdx | 87 ++++++++ .../static/elevation-examples.svg | 170 ++++++++++++++ .../design-language/static/elevation.svg | 208 ++++++++++++++++++ .../design-language/static/wp-logo@2x.png | Bin 0 -> 5395 bytes storybook/stories/tokens/elevation.mdx | 2 +- 5 files changed, 466 insertions(+), 1 deletion(-) create mode 100644 storybook/stories/foundations/design-language/elevation.mdx create mode 100644 storybook/stories/foundations/design-language/static/elevation-examples.svg create mode 100644 storybook/stories/foundations/design-language/static/elevation.svg create mode 100644 storybook/stories/foundations/design-language/static/wp-logo@2x.png diff --git a/storybook/stories/foundations/design-language/elevation.mdx b/storybook/stories/foundations/design-language/elevation.mdx new file mode 100644 index 00000000000000..11591568b3600c --- /dev/null +++ b/storybook/stories/foundations/design-language/elevation.mdx @@ -0,0 +1,87 @@ +import { Meta, Typeset } from '@storybook/addon-docs/blocks'; +import elevation from './static/elevation.svg'; +import elevationExamples from './static/elevation-examples.svg'; + +<Meta title="Foundations/Design Language/Elevation" name="page" /> + +# Elevation + +{/* Leaving alt text empty since this image is presentational */} + +<img src={ elevation } alt="" width="100%" /> + +Elevation, through the use of shadows, visually indicates the layers where overlapping UI elements reside. Shadows create the illusion of depth, showing how one UI element is positioned above another on the z-axis. Elevation should be used to organize elements, establish a clear hierarchy, and draw focus to key components. + +In the WordPress Design System there are four levels of elevation correlating to specific uses: + +<table> + <thead> + <tr> + <th>Elevation</th> + <th>Usage</th> + <th>Examples</th> + </tr> + </thead> + <tbody> + <tr> + <td>Extra small</td> + <td> + Applied to large sections and containers that group related content + and controls. These containers may shift or overlap other content + without causing too much visual disruption + </td> + <td>Preview Frame, Content Frame</td> + </tr> + <tr> + <td>Small</td> + <td> + Used for components that provide contextual feedback without being + overly intrusive. Small elevation is ideal for non-interruptive elements + that subtly surface additional information or actions. + </td> + <td>Tooltips, Snackbars</td> + </tr> + <tr> + <td>Medium</td> + <td> + Applied to components that offer additional actions to the user. This + elevation level helps differentiate actionable elements that appear in + context without requiring major focus shifts. + </td> + <td>Menus, Command Palette</td> + </tr> + <tr> + <td>Large</td> + <td> + Reserved for components that confirm actions or require decisions, large + elevation is used for more interruptive elements that demand user attention + to complete important tasks. + </td> + <td>Modals</td> + </tr> + </tbody> +</table> + +## Accessibility considerations + +* Interactive Elements: Elevation can be an important visual cue to indicate which elements are interactive, +particularly for folks with monochromatic color blindness. Elevating buttons, handles, and other interactive +elements makes them stand out, helping users quickly identify where they can take action. +* Focus: Higher levels of elevation can be used to draw attention to components that require user interaction +or confirmation, such as modals, guides, and decision-based tasks, enhancing accessibility by reducing +cognitive load. + +## Examples + +The diagram below visually demonstrates the examples outlined in the table above. + +<img src={ elevationExamples } alt="Diagram illustrating elevation levels" width="100%" /> + +1. Content frame and Preview frame +2. Snackbar +3. Menu +4. Modal + +## Tokens + +Use tokens to apply elevation in your work. Please refer to the [Tokens section](?path=/docs/tokens-elevation--page) to learn more. diff --git a/storybook/stories/foundations/design-language/static/elevation-examples.svg b/storybook/stories/foundations/design-language/static/elevation-examples.svg new file mode 100644 index 00000000000000..516313cbca4df3 --- /dev/null +++ b/storybook/stories/foundations/design-language/static/elevation-examples.svg @@ -0,0 +1,170 @@ +<svg width="1123" height="736" fill="none" xmlns="http://www.w3.org/2000/svg"> + <rect width="1123" height="736" rx="8" fill="#E4E4E4"/> + <g filter="url(#a)"> + <path fill="#F1F1F1" d="M304 12h309v712H304z"/> + <rect x="565" y="20" width="40" height="40" rx="20" fill="#1E1E1E"/> + <path d="M586.923 34.364V46h-2.108v-9.585h-.068l-2.721 1.738v-1.931l2.892-1.858h2.005Z" fill="#fff"/> + </g> + <g filter="url(#b)"> + <path fill="#F1F1F1" d="M625 12h486v712H625z"/> + <rect x="1063" y="20" width="40" height="40" rx="20" fill="#1E1E1E"/> + <path d="M1084.92 34.364V46h-2.1v-9.585h-.07l-2.72 1.738v-1.931l2.89-1.858h2Z" fill="#fff"/> + </g> + <g filter="url(#c)"> + <path fill="#FAFAFA" d="M273 44h149v219H273z"/> + <rect x="374" y="52" width="40" height="40" rx="20" fill="#1E1E1E"/> + <path d="M393.999 78.16c-.818 0-1.545-.141-2.182-.421-.632-.28-1.132-.67-1.5-1.17a3.039 3.039 0 0 1-.585-1.734h2.137c.019.315.123.59.312.824.19.231.441.411.756.54.314.129.666.193 1.057.193.416 0 .786-.072 1.108-.216.322-.148.573-.352.755-.614a1.51 1.51 0 0 0 .267-.903 1.571 1.571 0 0 0-.272-.932c-.186-.269-.455-.479-.807-.63-.349-.152-.769-.228-1.262-.228h-1.028v-1.625h1.028c.406 0 .76-.07 1.063-.21.307-.14.547-.337.721-.59.175-.258.26-.556.256-.893.004-.33-.07-.615-.221-.858a1.497 1.497 0 0 0-.631-.574 2.074 2.074 0 0 0-.949-.204c-.356 0-.686.064-.989.193a1.801 1.801 0 0 0-.733.551 1.398 1.398 0 0 0-.295.841h-2.028c.015-.651.202-1.224.562-1.716a3.634 3.634 0 0 1 1.455-1.159c.606-.28 1.286-.42 2.039-.42.777 0 1.451.145 2.023.437.576.288 1.021.676 1.335 1.165.315.489.472 1.028.472 1.62.004.654-.189 1.204-.58 1.647-.386.443-.894.733-1.522.87v.09c.818.114 1.445.417 1.88.91.44.488.658 1.096.654 1.823a2.92 2.92 0 0 1-.557 1.75c-.367.511-.875.913-1.523 1.205-.644.291-1.382.437-2.216.437Z" fill="#fff"/> + </g> + <g filter="url(#d)"> + <path fill="#F6F6F6" d="M32 643h287v61H32z"/> + <rect x="271" y="651" width="40" height="40" rx="20" fill="#1E1E1E"/> + <path d="M287.065 677v-1.523l4.04-3.96c.386-.39.708-.737.966-1.04.258-.303.451-.596.58-.88.128-.285.193-.588.193-.909 0-.368-.084-.682-.25-.944a1.664 1.664 0 0 0-.688-.613 2.214 2.214 0 0 0-.994-.216c-.383 0-.718.079-1.006.238a1.644 1.644 0 0 0-.67.665c-.156.288-.233.631-.233 1.029h-2.006c0-.739.169-1.381.506-1.927a3.42 3.42 0 0 1 1.392-1.267c.595-.299 1.276-.448 2.045-.448.781 0 1.466.145 2.057.437.591.292 1.049.691 1.375 1.199.33.507.494 1.087.494 1.739 0 .435-.083.863-.25 1.284-.166.42-.46.886-.88 1.397-.417.512-1.002 1.131-1.756 1.858l-2.006 2.04v.08h5.069V677h-7.978Z" fill="#fff"/> + </g> + <g filter="url(#e)"> + <path fill="#fff" d="M349 205h425v327H349z"/> + <rect x="726" y="213" width="40" height="40" rx="20" fill="#1E1E1E"/> + <path d="M741.496 236.841v-1.676l4.937-7.801h1.398v2.386h-.852l-3.324 5.267v.091h6.892v1.733h-9.051Zm5.551 2.159v-2.67l.023-.75v-8.216h1.988V239h-2.011Z" fill="#fff"/> + </g> + <defs> + <filter id="a" x="300" y="11" width="317" height="721" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="4"/> + <feGaussianBlur stdDeviation="2"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0"/> + <feBlend in2="BackgroundImageFix" result="effect1_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="3"/> + <feGaussianBlur stdDeviation="1.5"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.02 0"/> + <feBlend in2="effect1_dropShadow_15809_7029" result="effect2_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="1"/> + <feGaussianBlur stdDeviation="1"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.02 0"/> + <feBlend in2="effect2_dropShadow_15809_7029" result="effect3_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="1"/> + <feGaussianBlur stdDeviation=".5"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"/> + <feBlend in2="effect3_dropShadow_15809_7029" result="effect4_dropShadow_15809_7029"/> + <feBlend in="SourceGraphic" in2="effect4_dropShadow_15809_7029" result="shape"/> + </filter> + <filter id="b" x="621" y="11" width="494" height="721" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="4"/> + <feGaussianBlur stdDeviation="2"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0"/> + <feBlend in2="BackgroundImageFix" result="effect1_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="3"/> + <feGaussianBlur stdDeviation="1.5"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.02 0"/> + <feBlend in2="effect1_dropShadow_15809_7029" result="effect2_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="1"/> + <feGaussianBlur stdDeviation="1"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.02 0"/> + <feBlend in2="effect2_dropShadow_15809_7029" result="effect3_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="1"/> + <feGaussianBlur stdDeviation=".5"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"/> + <feBlend in2="effect3_dropShadow_15809_7029" result="effect4_dropShadow_15809_7029"/> + <feBlend in="SourceGraphic" in2="effect4_dropShadow_15809_7029" result="shape"/> + </filter> + <filter id="c" x="257" y="43" width="181" height="252" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="16"/> + <feGaussianBlur stdDeviation="8"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.02 0"/> + <feBlend in2="BackgroundImageFix" result="effect1_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="4"/> + <feGaussianBlur stdDeviation="2.5"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"/> + <feBlend in2="effect1_dropShadow_15809_7029" result="effect2_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="4"/> + <feGaussianBlur stdDeviation="2.5"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/> + <feBlend in2="effect2_dropShadow_15809_7029" result="effect3_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="2"/> + <feGaussianBlur stdDeviation="1.5"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0"/> + <feBlend in2="effect3_dropShadow_15809_7029" result="effect4_dropShadow_15809_7029"/> + <feBlend in="SourceGraphic" in2="effect4_dropShadow_15809_7029" result="shape"/> + </filter> + <filter id="d" x="24" y="642" width="303" height="78" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="8"/> + <feGaussianBlur stdDeviation="4"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.02 0"/> + <feBlend in2="BackgroundImageFix" result="effect1_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="1"/> + <feGaussianBlur stdDeviation="1"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0"/> + <feBlend in2="effect1_dropShadow_15809_7029" result="effect2_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="1"/> + <feGaussianBlur stdDeviation="1"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0"/> + <feBlend in2="effect2_dropShadow_15809_7029" result="effect3_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="1"/> + <feGaussianBlur stdDeviation="1"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0"/> + <feBlend in2="effect3_dropShadow_15809_7029" result="effect4_dropShadow_15809_7029"/> + <feBlend in="SourceGraphic" in2="effect4_dropShadow_15809_7029" result="shape"/> + </filter> + <filter id="e" x="306" y="193" width="511" height="432" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="50"/> + <feGaussianBlur stdDeviation="21.5"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.02 0"/> + <feBlend in2="BackgroundImageFix" result="effect1_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="30"/> + <feGaussianBlur stdDeviation="18"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/> + <feBlend in2="effect1_dropShadow_15809_7029" result="effect2_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="15"/> + <feGaussianBlur stdDeviation="13.5"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.07 0"/> + <feBlend in2="effect2_dropShadow_15809_7029" result="effect3_dropShadow_15809_7029"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="5"/> + <feGaussianBlur stdDeviation="7.5"/> + <feComposite in2="hardAlpha" operator="out"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0"/> + <feBlend in2="effect3_dropShadow_15809_7029" result="effect4_dropShadow_15809_7029"/> + <feBlend in="SourceGraphic" in2="effect4_dropShadow_15809_7029" result="shape"/> + </filter> + </defs> +</svg> \ No newline at end of file diff --git a/storybook/stories/foundations/design-language/static/elevation.svg b/storybook/stories/foundations/design-language/static/elevation.svg new file mode 100644 index 00000000000000..737e7955ad9df6 --- /dev/null +++ b/storybook/stories/foundations/design-language/static/elevation.svg @@ -0,0 +1,208 @@ +<svg width="1123" height="439" fill="none" xmlns="http://www.w3.org/2000/svg"> + <g clip-path="url(#a)"> + <rect width="1123" height="439" rx="8" fill="#3858E9"/> + <g filter="url(#b)"> + <rect width="705" height="924" rx="12" transform="matrix(.86603 -.5 .86603 .5 184.238 -6.64)" fill="#617CF4"/> + <rect width="705" height="924" rx="12" transform="matrix(.86603 -.5 .86603 .5 184.238 -6.64)" fill="url(#c)" fill-opacity=".4"/> + </g> + <g filter="url(#d)"> + <rect width="705" height="924" rx="12" transform="matrix(.86603 -.5 .86603 .5 -442.398 355.146)" fill="#617CF4"/> + <rect width="705" height="924" rx="12" transform="matrix(.86603 -.5 .86603 .5 -442.398 355.146)" fill="url(#e)" fill-opacity=".4"/> + </g> + <g filter="url(#f)"> + <rect width="397.5" height="88.5" rx="12" transform="matrix(.86603 -.5 .86603 .5 455 608.75)" fill="#A7B8FF" fill-opacity=".9"/> + <rect width="397.5" height="88.5" rx="12" transform="matrix(.86603 -.5 .86603 .5 455 608.75)" fill="url(#g)" fill-opacity=".8"/> + </g> + <g filter="url(#h)"> + <rect width="270.418" height="316.5" rx="24" transform="matrix(.86603 -.5 .86603 .5 102 363.209)" fill="#859BFB" fill-opacity=".9"/> + <rect width="270.418" height="316.5" rx="24" transform="matrix(.86603 -.5 .86603 .5 102 363.209)" fill="url(#i)" fill-opacity=".6"/> + </g> + <g filter="url(#j)"> + <rect width="270.418" height="316.5" rx="24" transform="matrix(.86603 -.5 .86603 .5 439 48.209)" fill="#859BFB" fill-opacity=".9"/> + <rect width="270.418" height="316.5" rx="24" transform="matrix(.86603 -.5 .86603 .5 439 48.209)" fill="url(#k)" fill-opacity=".6"/> + </g> + <g filter="url(#l)"> + <rect width="521.081" height="725.336" rx="36" transform="matrix(.86603 -.5 .86603 .5 20.979 165.499)" fill="#C2CCFF" fill-opacity=".9"/> + <rect width="521.081" height="725.336" rx="36" transform="matrix(.86603 -.5 .86603 .5 20.979 165.499)" fill="url(#m)" fill-opacity=".2"/> + </g> + </g> + <defs> + <linearGradient id="c" x1="352.5" y1="0" x2="352.5" y2="924" gradientUnits="userSpaceOnUse"> + <stop stop-color="#fff" stop-opacity=".25"/> + </linearGradient> + <linearGradient id="e" x1="352.5" y1="0" x2="352.5" y2="924" gradientUnits="userSpaceOnUse"> + <stop stop-color="#fff" stop-opacity=".25"/> + </linearGradient> + <linearGradient id="g" x1="198.75" y1="0" x2="198.75" y2="88.5" gradientUnits="userSpaceOnUse"> + <stop stop-color="#fff" stop-opacity=".25"/> + </linearGradient> + <linearGradient id="i" x1="135.209" y1="0" x2="135.209" y2="316.5" gradientUnits="userSpaceOnUse"> + <stop stop-color="#fff" stop-opacity=".25"/> + </linearGradient> + <linearGradient id="k" x1="135.209" y1="0" x2="135.209" y2="316.5" gradientUnits="userSpaceOnUse"> + <stop stop-color="#fff" stop-opacity=".25"/> + </linearGradient> + <linearGradient id="m" x1="260.541" y1="0" x2="260.541" y2="725.336" gradientUnits="userSpaceOnUse"> + <stop stop-color="#fff" stop-opacity=".25"/> + </linearGradient> + <filter id="b" x="182.326" y="-363.626" width="1414.58" height="831.471" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feGaussianBlur in="BackgroundImageFix" stdDeviation="4"/> + <feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="1"/> + <feGaussianBlur stdDeviation="1"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/> + <feBlend in2="effect1_backgroundBlur_15773_6493" result="effect2_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="3"/> + <feGaussianBlur stdDeviation="1.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"/> + <feBlend in2="effect2_dropShadow_15773_6493" result="effect3_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="6"/> + <feGaussianBlur stdDeviation="2"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.02 0"/> + <feBlend in2="effect3_dropShadow_15773_6493" result="effect4_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="11"/> + <feGaussianBlur stdDeviation="2.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0"/> + <feBlend in2="effect4_dropShadow_15773_6493" result="effect5_dropShadow_15773_6493"/> + <feBlend in="SourceGraphic" in2="effect5_dropShadow_15773_6493" result="shape"/> + </filter> + <filter id="d" x="-444.31" y="-1.839" width="1414.58" height="831.471" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feGaussianBlur in="BackgroundImageFix" stdDeviation="4"/> + <feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="1"/> + <feGaussianBlur stdDeviation="1"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/> + <feBlend in2="effect1_backgroundBlur_15773_6493" result="effect2_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="3"/> + <feGaussianBlur stdDeviation="1.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"/> + <feBlend in2="effect2_dropShadow_15773_6493" result="effect3_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="6"/> + <feGaussianBlur stdDeviation="2"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.02 0"/> + <feBlend in2="effect3_dropShadow_15773_6493" result="effect4_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="11"/> + <feGaussianBlur stdDeviation="2.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0"/> + <feBlend in2="effect4_dropShadow_15773_6493" result="effect5_dropShadow_15773_6493"/> + <feBlend in="SourceGraphic" in2="effect5_dropShadow_15773_6493" result="shape"/> + </filter> + <filter id="f" x="453.088" y="405.515" width="424.713" height="254.971" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feGaussianBlur in="BackgroundImageFix" stdDeviation="4"/> + <feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset/> + <feGaussianBlur stdDeviation=".5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0"/> + <feBlend in2="effect1_backgroundBlur_15773_6493" result="effect2_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="2"/> + <feGaussianBlur stdDeviation="1"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/> + <feBlend in2="effect2_dropShadow_15773_6493" result="effect3_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="4"/> + <feGaussianBlur stdDeviation="1.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"/> + <feBlend in2="effect3_dropShadow_15773_6493" result="effect4_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="8"/> + <feGaussianBlur stdDeviation="1.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0"/> + <feBlend in2="effect4_dropShadow_15773_6493" result="effect5_dropShadow_15773_6493"/> + <feBlend in="SourceGraphic" in2="effect5_dropShadow_15773_6493" result="shape"/> + </filter> + <filter id="h" x="105.175" y="227.029" width="501.936" height="318.4" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feGaussianBlur in="BackgroundImageFix" stdDeviation="4"/> + <feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="1"/> + <feGaussianBlur stdDeviation="1.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/> + <feBlend in2="effect1_backgroundBlur_15773_6493" result="effect2_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="5"/> + <feGaussianBlur stdDeviation="2.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"/> + <feBlend in2="effect2_dropShadow_15773_6493" result="effect3_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="12"/> + <feGaussianBlur stdDeviation="3.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.02 0"/> + <feBlend in2="effect3_dropShadow_15773_6493" result="effect4_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="22"/> + <feGaussianBlur stdDeviation="4.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0"/> + <feBlend in2="effect4_dropShadow_15773_6493" result="effect5_dropShadow_15773_6493"/> + <feBlend in="SourceGraphic" in2="effect5_dropShadow_15773_6493" result="shape"/> + </filter> + <filter id="j" x="442.175" y="-87.971" width="501.936" height="318.4" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feGaussianBlur in="BackgroundImageFix" stdDeviation="4"/> + <feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="1"/> + <feGaussianBlur stdDeviation="1.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/> + <feBlend in2="effect1_backgroundBlur_15773_6493" result="effect2_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="5"/> + <feGaussianBlur stdDeviation="2.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"/> + <feBlend in2="effect2_dropShadow_15773_6493" result="effect3_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="12"/> + <feGaussianBlur stdDeviation="3.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.02 0"/> + <feBlend in2="effect3_dropShadow_15773_6493" result="effect4_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="22"/> + <feGaussianBlur stdDeviation="4.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0"/> + <feBlend in2="effect4_dropShadow_15773_6493" result="effect5_dropShadow_15773_6493"/> + <feBlend in="SourceGraphic" in2="effect5_dropShadow_15773_6493" result="shape"/> + </filter> + <filter id="l" x="15.242" y="-92.498" width="1090.9" height="693.121" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feGaussianBlur in="BackgroundImageFix" stdDeviation="4"/> + <feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="4"/> + <feGaussianBlur stdDeviation="4"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/> + <feBlend in2="effect1_backgroundBlur_15773_6493" result="effect2_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="15"/> + <feGaussianBlur stdDeviation="7.5"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"/> + <feBlend in2="effect2_dropShadow_15773_6493" result="effect3_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="33"/> + <feGaussianBlur stdDeviation="10"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.02 0"/> + <feBlend in2="effect3_dropShadow_15773_6493" result="effect4_dropShadow_15773_6493"/> + <feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> + <feOffset dy="59"/> + <feGaussianBlur stdDeviation="12"/> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0"/> + <feBlend in2="effect4_dropShadow_15773_6493" result="effect5_dropShadow_15773_6493"/> + <feBlend in="SourceGraphic" in2="effect5_dropShadow_15773_6493" result="shape"/> + </filter> + <clipPath id="a"> + <rect width="1123" height="439" rx="8" fill="#fff"/> + </clipPath> + </defs> +</svg> \ No newline at end of file diff --git a/storybook/stories/foundations/design-language/static/wp-logo@2x.png b/storybook/stories/foundations/design-language/static/wp-logo@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a95cd961902b01cbd7635676f703ba9da135642d GIT binary patch literal 5395 zcmV+u73}JXP)<h;3K|Lk000e1NJLTq00LM5004Xl0{{R3f*L;O0001-P)t-s0000e zC@>`}Fe4~1Bq=T=CoUr>FC!=~Bq%N;CNLx@Fd!f>A}22+DJ~-@E+Z)~BPcB+DK8`` zFC-~2Bq=W<C@v%@FC!-|BPcH;C@v!?E+Zx_ASf^*DJ~)@E+Q!|BquN+CNLl{Fd`{0 zBPlK-CoUr?E+Z)|BPlQ?B`_l?Fd`=|BquK-DJ~@_EhH%}BPcK<C@vx>E+i)}9Y%eH z0000qbW%=J03a}6aF3tAfKWgX&+q@QVDHaxuYbRg-`}86Aa9Rwa8MA>kk7DCP%w~> zug_r5UtfUFZyD`x000y6Nkl<ZcmeF#$D)HE5QX7E4C)}0p5X2M{ogRXV0yycalTcG z?tUsgLS;Jd7*i}6Q|1+00*Ik>r*?A86`e{Ezyqu{PA;iUMRx(Pc_Fvx_UKjs98}dG zn4xB6cN;F&<!B%~&SZ2QfE~MCR7NX0jfbPYY!p2LxHYRuspvAEdRc3b7TlCozqE9V z?8zf7xaPT$l?l`B^foO;04KZ@vSJk7hbL!W1bB64>#(ZQdAXEVoSjJv>*0Brt|okZ z_g;8utGgxJ(+lET_&dO}lZAdoA<G>v=hPjhmhy0?1u&MSsigoLCzmxQqrl6mLibJp zE4B!xtKi<@26gXv(i+nOz)K?w6Lo)9M;rFc%YvZ|Kv&bpvI^1)&H%NgB|umC(Y3>) zX_ecu0A2N&wz5JVVHC=O!>)W59uHSyCan*YwSulxxI=nWa5t)Dp`c`eZFj{^Vl=8% zmZ4NZS48?5ZM;gPCTp#RV}gY5+pF+fB>&mk!84@@o@Jq=jW>xjVM}{YBH|P!2^;sI zD<g6GOf6sEB2rU&pb!!NU-Ok$N8LIRd85?8Yna1WB569pDQ>f1HKFML>dMdwKM5{| zV1gW2VlkcY<yV`ylt3?72w$4$YX&-rlRFtg6D)+k(G%7mo%WOB1w1CKIeX`!r8v%f zab&wCjf@tU9>8Wi;Q%whw|U?H-Tt8ig?&pGb<_KuPIb}*IhB5{TPn%oi4rUV&pHle za@Q~$o@dhxbF`{S+3302wjnll&iW6<s|r~68s+W(+0uJomiu7L$y9VT8r3F*eR=Ku zO)GoXsxb9v<SAHEfOi9;i7om^9|TJ|Vai6&)mAx^VXtIIs417IgLE^q2vUgF4A|H= zGm@%JP)V1go?SQkq0cyC{YP$@S^KMbJpqe@waEsnO|~hO1vEvu!dP`()aq@<5m>Qb z!J*IG<d%uG^H(0Q>dD=cCZ!*8Gm{;%^o3tO&38~c>In5Xyp+OWlYy3br2%VSd27cK ziN?<Q3X1BX^jFq3XTZ3-K!tLKnTJh|DfNRT*ILytsU$5?*4$gT{)7vUUZ@4gpLl8< z;CQg81T+~K##)`K6x-|k!>Pr(yVR;4y&S6&qm*uS;>edwmc_25CHN&45x}Mxl7hfm zrO`;s-GTk*NF?}$nD`Cf>wSC;YPgmfR*gXd4Fk>!+q5-+<>YdXhesXrEpQE3zOdr! zZz-@wh4{j~+|*q<Yg%V%;VvVvc}${$Xr564KU$Sg!n76!30N;s3o#S<j=}#08FX~( zv$W7<Xkjz}mKAq;{sLQ~gt``bIqc=w4!{zVvC!`?SP3`x7&)eeVyJ~^4%)<;Yhe&7 zi4y8s=w9MtuLA+A!i@6;zBc}t#fK~{ta1Wd0Qf3_pyn0UkWxay4pXd#{7}ne+{FKD zF`hi9pJwR@SZf?C{r9ZCahP*gRdKvin`-Eqv9tFL*V52R<+Fu{$k#%&7GjE%m+=pt zzI*a^YuHVP2Z`ZkajgwnyMz@cMPf}3$t!yxSYoc{ND~s4y1OFenf`MTV(rx2`q!Ro zXr<vjO^rYl^R%#FTBy?@ajJuK2q<oe5^AroOQi1ge8V>Y5Tm<(IUm^VYSy?(74pGi z4-5__zmSFf#tjaH%{t=z=4>`KTOu~ErQuC4|CHF3sf9erSIZKu#Hkj@0dEB6D4@Sf zOl9K!ONbT)3*Jb4Xl`z5^1xzAmJzVXg)Rh(e5KreRYJj+$Q$k?W%?6GRw?gAriD6w zCnsN}Dg)b0a)YLX6+{$q?(CB<_aT)2(=1hbEU*3YW5yObV(aqSe>y+oH%Z5>mVh<w z=|d>}av}GA{#Duk{{i`n$YH{Fu`J8p(^=MV^${9wkHXeLm?7u~L;|fH=18r)jC-nu z5PmGw{+SZW7i_rob682}#&mjeDrPq(y{Ye~8X7pH8PL{-%fJene9Z7lcG!2_3h!-j z%wEGqcAqU)I#^$Zm+YjW^hvL(Qe|jiZjv8{elkbMmUQI}VA3M7TnW1$xZVNQ6*!EW z4pkzoBC;s9Zj{x9wftxm#JW7NDow6Rl!Kyd$o$V%j|C=_tJ}l=07njLvSp)y)kSO= z`VHf4m&iT1JT0sd35wtL<o#GnUPrVLZsI4DBhpIPwQR8NwVr^-HCiB>Qv`6Yd%8@a z%}(Btd#}CwZJo|h;QjL8HY=wFi0t`>jWm=#mV3_A!X5g7rec3eFO%$Dy49f)mVg~7 zA#f!vbIJNs4Vo*pf1vZo{O4Z}1k0&uL4_`mK!%^1^Bebr({y?Q9RRFOmz5$)!yxC5 zc*jHw^8%Y0)cbzQ<jp8k3#A9@fLe%3h+J{9>f{?@Q19f@I*V9NY8Y8<R)N&2<vg$7 zbV!ENpu%g>DGN1tTFn18WMXY6`oxg|%h5tn@SXIE3=6pyf)YY$KB<I1pu@l>smHB! zv`f-K5*6rjzJh~Ab9dy;t3eYUXUD)A)IA;EjGW!#tZu8OoA&6&0F%5qT3F?1;c_6# zQOGVbwNR8$$4-<Ghr%<Y7rWwHsz;69{wH}Gc-6Pg01KVo=%p{8xP_X{-J=s07<r=- z-&F!*oo*;y9FT^~wa^azR3AHUe@+YQp%V5wi6~(Q&e!aFVjV^Ru*8|f?+6z5`6M5# zd1`-^gvd{!egMu0>fC*+ocjZWT?9+_@A}wq)$44Qynz{_g+qsh{y{rY$+WCgpoFM} zsuFJGU1ugm2M!j^y*OBWU`D_y(1jc<e3=+np=pY{J4dk85seO3gof@EEQm`vT8OxA z30Ss&>L4f(Ed(XhweZhDXHUtpE**!!z{2Jxoe!P4kjn(??+6=>WrMZM0qg#6g@x2f zC2QMv<|<i5sqPy(4J@0bg`14Pwiv#&lFxaP`-m2bGYw*=E1}Z~Amc9gFtCbTu+T9f z2dqM>X0p}r(|{#69QfBAbC%_khPxB6BG41-{BJ6_7B2J*phK{T76v)f8p{#YKnV{( zJ{Tb|2dp|9EQt8a#D8qUy_HvTTfkKstiyw(u+qT_=}G$jLZCHoc<0;}!%~%_g#}yL zg7ZdFf8bzAFF8=cQ|x>~39a6X^ab@7B<}<)bW8-lQX895CRn??<XwCe_^XD*<ToT> zxeP6A6yU+UJRFZ$ObbN`Q43}5C|`PmhOv!<Mam5T7OP3+gEa#erNOcgPYGCci_XCw zWN6Wbm}7~d77`^STDS+tLXJh=hH9vUiWXLbd+Cx7!Alz)EL8J{fYqh6pru&VqinFc zcAyaqtl9$M7+X17v|)Nwh`ru2B_vu{2r6t;NVHIt5VTN~us}^f$wF%Z76c1=t{LTn z#iwToSTh?CD+1P6xakyFb(pvEH?~rPqqU(8p^lZWg$)akeMfgdT97&x?S@*EP{$6H z&_k&s=Y!Ge99WZN&oQttG%j>XX3f2QTv%V?H8@ybP)87~*jtJfa<(cVXsweCCCC^6 z3$EMgO8EJV7B1k-1}pDe3q=W03sDIrqA{?r?UIAl;c68I772}Q_UeXwuxg1{O-*DN zJD8Kj(dss|VReim2fjvAyRm~iqlL>mwGxx7hK$jg6D3r!6D0&#Fxz0#Z3$TB!&OAC zo(ouYm_s%70<fSH$qo{pHJnNbfG%qHniASy4A;UiJn?1_Co{BAln}HKl#qW;4dyvm zXtQecJiyXzQjZ=E7TTdv+JEEG4JxJwNigC=w9wu@q~}^F0Z1H3*JDB1OO#N>PL%NJ zBNp1ijGi%AvyzWU|0zrFm!Cdzuw>~g0)tjAw1zTo4T^=`;t=?Nfo-d#SS>2-p92pQ zEfgixw6GN=1h9Tylw*O-<dcjGz}oy<U@fjCT=8;4=Q&tH3<84|QVrvA2)Lq)+P$KL zcz*$ZQ0Jh069TSGX<@8I2^H)PI6kfNW^@2i4pw7J?6-WdAY?x+ShG*p1vDfD(mer- z5QB%{r$Dk+_RnM3spvw!PEo>v41pFJ2x0~QN(Xz~irW<}T!9jjIu=_}95k@X@LgM@ zcTpW{`D9?NLTE^r(<vQC4*_D(3A|yfd#i*Gd?B9$C4|5>z-Xg?!Yu2dc~&h};++7j zyz<Th38}ox<BaPIzzXoXKFz4Gh-^bi0@jv*MTqhF4P{t}nKx=7Dk0UvB`C{J*oTCB z18b5PS{qVM=N2;N3Z0g7UNBc!JRMkM73?FI&A7%fVnhReYsS1`EwUs@7FmA*N{E3i z4xDH)^oaa&Ed;NFvhan}`KueMBv>+{{`z>ZZ0are<wCF|qPFG|u;kn|9U%tk9zz@M zZ%JsyKU@nz2{Ev32Tp7;^mN>lpoJyD4ntpf+VxmP#8J`X*JIfy25Yq8WbqZG%DDrr zR#oD;J*~wr?`ld0BLS+MSCmjLhW%ne2{+OYRhCL&w}TcogqI?F+p{ECA~%Gr{1v1o z0ap81u%y?=wA|32ob9|f`nkO}_BaA##l=h7@aJ7GRS*g2B3CP#N3<}25>}96G5^tz zIf>o{UCap%e9iloR-ZG#vZ+T|Uk=u&K!u@Tfqk~0<=py>bP>UdbS>RNwggqQFs4F5 z=nd-)Y9Up^QN%dIw6LTpSV8_b)>&O-6I>d&+F$2xmUgY25qBwkI9N;AU)eqiEGO?@ zo2p!R1WRvN30Sh#o&ZO*5R?$&LKr9^gq|JxAYVREmC*_kvdD+2aOD6=Ml2oymc^dW zc*y+MK_co`3YJgR*s9ZWJ4UA$u=Iv&p<aF}0_#UsKfUcU7<Db&>tjMG*mH|4ukHBA z&y!I&-QEG0iVCTOtStlU3$8u5WM^chb2gX-CUah}-AO3J6@b{M62m_b?#sdU*d10- z6^#i4)eNeep)}UWHHZ>IXO(n7SMc$kJHL0s1bbVw1LP(Kx?r#-;d2I*Tdi=)ZLN%X zyM~apOXgtsT}7L$uWQLcG-<HRP%#~y*6{+!Z|VFwNG)`y1gxnX!7Nab@I(o-s!#Le z(m1Q{?u8jV-}wkXJ)Nq(KzcoUFZ@6@^{e<yL??ZZl}Twe5D$mrP~l!0?!}3Lma;lg zLKfKK5hIHM3xC6oYvF?W7YGHi=4ZGvX-b^F#Cx9cTP?V@b2cTAkohOJ&mTrqtY`g3 zXJqOhr%}IEHB<B{2v{0f(y+u|dUJGI$AJ<iwb0z07z5T0VWC=B(i|3*5Mvg0ne;bu z)xjth*0edJc@te-pRVmJ63+mkm0PQGvc=`W_&7MI4L^F1*~;gPT0Uwa)oAsG4eaa& zS(ZlyYLGvt{r=$qzlM)g(E?FIQRSp{8}Kylro5=>WYQ!NUgCV<O|kZN$8}@+Uo<b3 zfb=zIxf9teI~piW;)bWTzr=J})OXOE;&_KbZ351A_!7E=Cw@pW2_b8HP7AHFo)opP zlrY?jJb~i?TDYLtEqTZjKgkW&mBS<|wJH9jFE?WC+yJI&TLcW6!3|qkXaxt&lixUW z5l<zdnVS|4+j%jJyFq>XS_=)Q>SmN{x<c8B5|Si;d#8j-<-&ow5im$wTsz7)%63=2 zEK6_4Co#1DY-Q;s$n=j>KQb6!RsVm&=D}F){goX@tz~r9dmXP(R#y`^sGaz-G+K5X zC%%%$p%!~SoiuVcSKeQ_C^=#etmdSlm4?FAFl6o7w2l`gq*}NUCG17VDF!UAg@$04 zQNM5Uzh5V=N4ep~R}8QC5prLd2mJvN^<mbYg4LMyR%_H0_)COdZ5Wb!0Zz!YPNyj$ z_J6Df_*HW2839XZUr_8o%D}p^;oq<4gC%m4XS0v?I>=T2Ww3Y?&i-%`x?50p$@XfU z<T^?+DFPVq8&}jqQ9|O4Z6WxbX2Ej^Gt5>L!YE2eEv%ZMo0dUqm$oCOA=eBks2l>d z?tup#;a!KvS#b)Mx$_x)3uQf4(Qmjk>L_ar10XDFloE<aU@Q7c*cf@`fd;CDq<^;g zh!*8?@o{$ZCHtpknL6jYwGzGR{c<t8ahO-P@or8VHn*M)b!taWuMB`9w(iLHk91v> z1yHH2eZ^?;AKp=T0TzUSzFb#q2{#+L!x_Fv@OrnmW82dS$PJst`jh^)4&dicbKi3G zZg0mVXaA~fQd1KpBwG0AFqX9<gm2E?#qb->jd`--T+Ai#TgeQ@n-ju!lbk&kK$go; zLJVxxfUCKLwYO&P=1wQ9WfnKULT$||1wYZj&l3CIq`jwELe_evj`+5}{BL`Aw5m7^ zgaLTctVv8vty<ct^kQLea=-8YZi~orl3~IT;avHD574Wh4Cwrc&MT8JG%wkm2|m=G zo1LPd{rb6$9Y)6QGBt}AoCrSE&?c*}n1x~zHiC#Bn>JU5;B(n_gK+oqZyh)G<Tie5 zLayM86)UH|tBo3c5~^=%aBNONSy2HbYro5<1AEr$BdP7FJlA;u$;wl`iRtAeROQs` z!>}QMnB{W6)hD48NlItr3PjiGWcqzRohKn~)rSD~Ke7d)PeLha^}Uq<{tL39CVI7s zB^Y^J$;TW3EUPujy{wCNx&B%bHImaBzySNb`|{HeZ^6yWgLA<aqf{$%rvVILS&x=Z zi4{iz=wA!JP3DbQT>=3ps!C#ZkzNzMUR?yx-|E>8k-m}QA&VPN02HDYySZtgp5d3z zdLtG<w^uFo><>p#c{NA-yldp?Z%732nlg_KK6&q*_nuk57XjcksZ{5dj*%*O%V6hg x@6w*tCIWb0EWs@cU&aUK>+EjD5CFhW`v)S+^3-dh8~p$P002ovPDHLkV1hxt=*R#7 literal 0 HcmV?d00001 diff --git a/storybook/stories/tokens/elevation.mdx b/storybook/stories/tokens/elevation.mdx index d00de6dbde7fab..5bd7dbf79a2622 100644 --- a/storybook/stories/tokens/elevation.mdx +++ b/storybook/stories/tokens/elevation.mdx @@ -5,7 +5,7 @@ import { ElevationTable } from './components.tsx'; # Elevation tokens -This document outlines the various tokens relating to elevation in the WordPress design system. +This document outlines the various tokens relating to [elevation](?path=/docs/foundations-design-language-elevation--page) in the WordPress design system. ## Values From ec9625e7fa24d0112428906917e6615651f5ba89 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Fri, 18 Oct 2024 17:00:12 +0200 Subject: [PATCH 1245/1908] Block bindings: allow only string field types in bindings. (#66174) * Filter fields by type in post meta * Add e2e test * Allow only strings * Update test to expect numbers and integers to be hidden * Update tests to check for label instead of key * Adapt object custom field * Adapt e2e tests * Add `type` prop to `getFieldsList` * Adapt testing source * Reduce diff * Add `attribute` to dependencies --------- Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- .../block-editor/src/hooks/block-bindings.js | 63 +++++++++----- packages/e2e-tests/plugins/block-bindings.php | 86 +++++++++++++++++++ packages/editor/src/bindings/post-meta.js | 1 + .../various/block-bindings/post-meta.spec.js | 49 +++++++++++ 4 files changed, 176 insertions(+), 23 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 5c002613831ce1..694c9c1c0bb3cc 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -5,6 +5,7 @@ import { __ } from '@wordpress/i18n'; import { getBlockBindingsSource, getBlockBindingsSources, + getBlockType, } from '@wordpress/blocks'; import { __experimentalItemGroup as ItemGroup, @@ -29,6 +30,7 @@ import { import { unlock } from '../lock-unlock'; import InspectorControls from '../components/inspector-controls'; import BlockContext from '../components/block-context'; +import { useBlockEditContext } from '../components/block-edit'; import { useBlockBindingsUtils } from '../utils/block-bindings'; import { store as blockEditorStore } from '../store'; @@ -50,9 +52,20 @@ const useToolsPanelDropdownMenuProps = () => { }; function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) { + const { clientId } = useBlockEditContext(); const registeredSources = getBlockBindingsSources(); const { updateBlockBindings } = useBlockBindingsUtils(); const currentKey = binding?.args?.key; + const attributeType = useSelect( + ( select ) => { + const { name: blockName } = + select( blockEditorStore ).getBlock( clientId ); + const _attributeType = + getBlockType( blockName ).attributes?.[ attribute ]?.type; + return _attributeType === 'rich-text' ? 'string' : _attributeType; + }, + [ clientId, attribute ] + ); return ( <> { Object.entries( fieldsList ).map( ( [ name, fields ], i ) => ( @@ -63,29 +76,33 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) { { registeredSources[ name ].label } </DropdownMenuV2.GroupLabel> ) } - { Object.entries( fields ).map( ( [ key, args ] ) => ( - <DropdownMenuV2.RadioItem - key={ key } - onChange={ () => - updateBlockBindings( { - [ attribute ]: { - source: name, - args: { key }, - }, - } ) - } - name={ attribute + '-binding' } - value={ key } - checked={ key === currentKey } - > - <DropdownMenuV2.ItemLabel> - { args?.label } - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> - { args?.value } - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.RadioItem> - ) ) } + { Object.entries( fields ) + .filter( + ( [ , args ] ) => args?.type === attributeType + ) + .map( ( [ key, args ] ) => ( + <DropdownMenuV2.RadioItem + key={ key } + onChange={ () => + updateBlockBindings( { + [ attribute ]: { + source: name, + args: { key }, + }, + } ) + } + name={ attribute + '-binding' } + value={ key } + checked={ key === currentKey } + > + <DropdownMenuV2.ItemLabel> + { args?.label } + </DropdownMenuV2.ItemLabel> + <DropdownMenuV2.ItemHelpText> + { args?.value } + </DropdownMenuV2.ItemHelpText> + </DropdownMenuV2.RadioItem> + ) ) } </DropdownMenuV2.Group> { i !== Object.keys( fieldsList ).length - 1 && ( <DropdownMenuV2.Separator /> diff --git a/packages/e2e-tests/plugins/block-bindings.php b/packages/e2e-tests/plugins/block-bindings.php index ffbe50ab3cc902..b86673c2c523d0 100644 --- a/packages/e2e-tests/plugins/block-bindings.php +++ b/packages/e2e-tests/plugins/block-bindings.php @@ -21,14 +21,17 @@ function gutenberg_test_block_bindings_registration() { 'text_field' => array( 'label' => 'Text Field Label', 'value' => 'Text Field Value', + 'type' => 'string', ), 'url_field' => array( 'label' => 'URL Field Label', 'value' => $testing_url, + 'type' => 'string', ), 'empty_field' => array( 'label' => 'Empty Field Label', 'value' => '', + 'type' => 'string', ), ); @@ -106,6 +109,89 @@ function gutenberg_test_block_bindings_registration() { 'type' => 'string', ) ); + // Register different types of custom fields for testing. + register_meta( + 'post', + 'string_custom_field', + array( + 'label' => 'String custom field', + 'default' => '', + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + ) + ); + register_meta( + 'post', + 'object_custom_field', + array( + 'label' => 'Object custom field', + 'show_in_rest' => array( + 'schema' => array( + 'type' => 'object', + 'properties' => array( + 'foo' => array( + 'type' => 'string', + ), + ), + ), + ), + 'single' => true, + 'type' => 'object', + ) + ); + register_meta( + 'post', + 'array_custom_field', + array( + 'label' => 'Array custom field', + 'show_in_rest' => array( + 'schema' => array( + 'type' => 'array', + 'items' => array( + 'type' => 'string', + ), + ), + ), + 'single' => true, + 'type' => 'array', + 'default' => array(), + ) + ); + register_meta( + 'post', + 'number', + array( + 'label' => 'Number custom field', + 'type' => 'number', + 'show_in_rest' => true, + 'single' => true, + 'default' => 5.5, + ) + ); + register_meta( + 'post', + 'integer', + array( + 'label' => 'Integer custom field', + 'type' => 'integer', + 'show_in_rest' => true, + 'single' => true, + 'default' => 5, + ) + ); + register_meta( + 'post', + 'boolean', + array( + 'label' => 'Boolean custom field', + 'type' => 'boolean', + 'show_in_rest' => true, + 'single' => true, + 'default' => true, + ) + ); + // Register CPT custom fields. register_meta( 'post', diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index 9198ac0fe41e1e..a3602ce7d62076 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -60,6 +60,7 @@ function getPostMetaFields( select, context ) { entityMetaValues?.[ key ] ?? // When using the default, an empty string IS NOT a valid value. ( props.default || undefined ), + type: props.type, }; } } ); diff --git a/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js b/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js index d82def6feb66bf..32334bfc777f2a 100644 --- a/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js +++ b/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js @@ -547,5 +547,54 @@ test.describe( 'Post Meta source', () => { .filter( { hasText: 'Movie field label' } ); await expect( movieField ).toBeVisible(); } ); + test( 'should not be possible to connect non-supported fields through the attributes panel', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + } ); + await page.getByLabel( 'Attributes options' ).click(); + await page + .getByRole( 'menuitemcheckbox', { + name: 'Show content', + } ) + .click(); + await page + .getByRole( 'button', { + name: 'content', + } ) + .click(); + await expect( + page.getByRole( 'menuitemradio', { + name: 'String custom field', + } ) + ).toBeVisible(); + await expect( + page.getByRole( 'menuitemradio', { + name: 'Number custom field', + } ) + ).toBeHidden(); + await expect( + page.getByRole( 'menuitemradio', { + name: 'Integer custom field', + } ) + ).toBeHidden(); + await expect( + page.getByRole( 'menuitemradio', { + name: 'Boolean custom field', + } ) + ).toBeHidden(); + await expect( + page.getByRole( 'menuitemradio', { + name: 'Object custom field', + } ) + ).toBeHidden(); + await expect( + page.getByRole( 'menuitemradio', { + name: 'Array custom field', + } ) + ).toBeHidden(); + } ); } ); } ); From 1bfac715be20febb532007d0ac8a530682a9e8aa Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Fri, 18 Oct 2024 16:21:57 +0100 Subject: [PATCH 1246/1908] Zoom Out: Hide slots and grouping buttons (#66243) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../src/components/block-toolbar/index.js | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 58a7b2b09bb2cd..77b10149aaf226 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -69,6 +69,9 @@ export function PrivateBlockToolbar( { hasParentPattern, hasContentOnlyLocking, showShuffleButton, + showSlots, + showGroupButtons, + showLockButtons, } = useSelect( ( select ) => { const { getBlockName, @@ -135,6 +138,9 @@ export function PrivateBlockToolbar( { hasParentPattern: _hasParentPattern, hasContentOnlyLocking: _hasTemplateLock, showShuffleButton: isZoomOut(), + showSlots: ! isZoomOut(), + showGroupButtons: ! isZoomOut(), + showLockButtons: ! isZoomOut(), }; }, [] ); @@ -195,11 +201,13 @@ export function PrivateBlockToolbar( { > <ToolbarGroup className="block-editor-block-toolbar__block-controls"> <BlockSwitcher clientIds={ blockClientIds } /> - { ! isMultiToolbar && isDefaultEditingMode && ( - <BlockLockToolbar - clientId={ blockClientId } - /> - ) } + { ! isMultiToolbar && + isDefaultEditingMode && + showLockButtons && ( + <BlockLockToolbar + clientId={ blockClientId } + /> + ) } <BlockMover clientIds={ blockClientIds } hideDragHandle={ hideDragHandle } @@ -209,7 +217,8 @@ export function PrivateBlockToolbar( { ) } { ! hasContentOnlyLocking && shouldShowVisualToolbar && - isMultiToolbar && <BlockGroupToolbar /> } + isMultiToolbar && + showGroupButtons && <BlockGroupToolbar /> } { showShuffleButton && ( <ToolbarGroup> <Shuffle @@ -218,7 +227,7 @@ export function PrivateBlockToolbar( { /> </ToolbarGroup> ) } - { shouldShowVisualToolbar && ( + { shouldShowVisualToolbar && showSlots && ( <> <BlockControls.Slot group="parent" From 2725061547cc72251ce7afae62ee6e78bd3c6339 Mon Sep 17 00:00:00 2001 From: Michal <mmczaplinski@gmail.com> Date: Fri, 18 Oct 2024 16:43:20 +0100 Subject: [PATCH 1247/1908] iAPI: Add tests for handling arrays in `deepMerge()` (#66218) * add new tests * updated tests * remove one extra test Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: DAreRodz <darerodz@git.wordpress.org> --- .../src/proxies/test/deep-merge.ts | 83 +++++++++++++++---- 1 file changed, 65 insertions(+), 18 deletions(-) diff --git a/packages/interactivity/src/proxies/test/deep-merge.ts b/packages/interactivity/src/proxies/test/deep-merge.ts index 267e4850f9af91..aaa762cb979f3c 100644 --- a/packages/interactivity/src/proxies/test/deep-merge.ts +++ b/packages/interactivity/src/proxies/test/deep-merge.ts @@ -251,24 +251,6 @@ describe( 'Interactivity API', () => { expect( result ).toEqual( { a: 1 } ); } ); - it( 'should handle arrays', () => { - const target = { a: [ 1, 2 ] }; - const source = { a: [ 3, 4 ] }; - const result = {}; - deepMerge( result, target ); - deepMerge( result, source ); - expect( result ).toEqual( { a: [ 3, 4 ] } ); - } ); - - it( 'should handle arrays when overwrite is false', () => { - const target = { a: [ 1, 2 ] }; - const source = { a: [ 3, 4 ] }; - const result = {}; - deepMerge( result, target, false ); - deepMerge( result, source, false ); - expect( result ).toEqual( { a: [ 1, 2 ] } ); - } ); - it( 'should handle null values', () => { const target = { a: 1, b: null }; const source = { b: 2, c: null }; @@ -500,5 +482,70 @@ describe( 'Interactivity API', () => { expect( spy ).toHaveBeenCalledTimes( 3 ); expect( deepValue ).toBe( 'value 2' ); } ); + + describe( 'arrays', () => { + it( 'should handle arrays', () => { + const target = { a: [ 1, 2 ] }; + const source = { a: [ 3, 4 ] }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { a: [ 3, 4 ] } ); + } ); + + it( 'should handle arrays when overwrite is false', () => { + const target = { a: [ 1, 2 ] }; + const source = { a: [ 3, 4 ] }; + const result = {}; + deepMerge( result, target, false ); + deepMerge( result, source, false ); + expect( result ).toEqual( { a: [ 1, 2 ] } ); + } ); + + it( 'should add new array from source if not present in target', () => { + const target = { a: 1 }; + const source = { arr: [ 1, 2, 3 ] }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { a: 1, arr: [ 1, 2, 3 ] } ); + } ); + + it( 'should handle nested arrays', () => { + const target = { nested: { arr: [ 1, 2 ] } }; + const source = { nested: { arr: [ 3, 4, 5 ] } }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { nested: { arr: [ 3, 4, 5 ] } } ); + } ); + + it( 'should handle object with array as target and object with object as source', () => { + const target = { arr: [ 1, 2, 3 ] }; + const source = { arr: { 1: 'two', 3: 'four' } }; + const result: any = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { arr: { 1: 'two', 3: 'four' } } ); + } ); + + it( 'should handle object with object as target and object with array as source', () => { + const target = { arr: { 0: 'zero', 2: 'two' } }; + const source = { arr: [ 'a', 'b', 'c' ] }; + const result = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { arr: [ 'a', 'b', 'c' ] } ); + } ); + + it( 'should handle objects with arrays containing object elements', () => { + const target = { arr: [ { a: 1 }, { b: 2 } ] }; + const source = { arr: [ { a: 2 }, { c: 3 } ] }; + const result: any = {}; + deepMerge( result, target ); + deepMerge( result, source ); + expect( result ).toEqual( { arr: [ { a: 2 }, { c: 3 } ] } ); + } ); + } ); } ); } ); From 0ae2cb8e520292f2726fa6c63676b91333819168 Mon Sep 17 00:00:00 2001 From: Michal <mmczaplinski@gmail.com> Date: Fri, 18 Oct 2024 16:53:01 +0100 Subject: [PATCH 1248/1908] iAPI: Add comments to the `deepMerge()` function (#66220) * update comment * Add comments Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: DAreRodz <darerodz@git.wordpress.org> --- packages/interactivity/src/proxies/state.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/interactivity/src/proxies/state.ts b/packages/interactivity/src/proxies/state.ts index d4d573acba8847..f9af257bada2ea 100644 --- a/packages/interactivity/src/proxies/state.ts +++ b/packages/interactivity/src/proxies/state.ts @@ -300,6 +300,8 @@ const deepMergeRecursive = ( source: any, override: boolean = true ) => { + // If target is not a plain object and the source is, we don't need to merge + // them because the source will be used as the new value of the target. if ( ! ( isPlainObject( target ) && isPlainObject( source ) ) ) { return; } @@ -317,38 +319,50 @@ const deepMergeRecursive = ( hasPropSignal( proxy, key ) && getPropSignal( proxy, key ); + // Handle getters and setters if ( typeof desc.get === 'function' || typeof desc.set === 'function' ) { if ( override || isNew ) { + // Because we are setting a getter or setter, we need to use + // Object.defineProperty to define the property on the target object. Object.defineProperty( target, key, { ...desc, configurable: true, enumerable: true, } ); + // Update the getter in the property signal if it exists if ( desc.get && propSignal ) { propSignal.setGetter( desc.get ); } } + + // Handle nested objects } else if ( isPlainObject( source[ key ] ) ) { if ( isNew || ( override && ! isPlainObject( target[ key ] ) ) ) { + // Create a new object if the property is new or needs to be overridden target[ key ] = {}; if ( propSignal ) { + // Create a new proxified state for the nested object const ns = getNamespaceFromProxy( proxy ); propSignal.setValue( proxifyState( ns, target[ key ] as Object ) ); } } + // Both target and source are plain objects, merge them recursively if ( isPlainObject( target[ key ] ) ) { deepMergeRecursive( target[ key ], source[ key ], override ); } + + // Handle primitive values and non-plain objects } else if ( override || isNew ) { Object.defineProperty( target, key, desc ); if ( propSignal ) { const { value } = desc; const ns = getNamespaceFromProxy( proxy ); + // Proxify the value if necessary before setting it in the signal propSignal.setValue( shouldProxy( value ) ? proxifyState( ns, value ) : value ); From bcddcb6ad6d2cf7b39fc528037ccabd07b730212 Mon Sep 17 00:00:00 2001 From: Troy Chaplin <15524465+troychaplin@users.noreply.github.com> Date: Fri, 18 Oct 2024 14:09:53 -0400 Subject: [PATCH 1249/1908] docs: example for getSelectedBlock (#66108) * add: example for getSelectedBlock * change: build docs --- .../data/data-core-block-editor.md | 33 +++++++++++++++++++ packages/block-editor/src/store/selectors.js | 33 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index 956e8dd010581a..437f7be20f7705 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -738,6 +738,39 @@ _Returns_ Returns the currently selected block, or null if there is no selected block. +_Usage_ + +```js +import { select } from '@wordpress/data'; +import { store as blockEditorStore } from '@wordpress/block-editor'; + +// Set initial active block client ID +let activeBlockClientId = null; + +const getActiveBlockData = () => { + const activeBlock = select( blockEditorStore ).getSelectedBlock(); + + if ( activeBlock && activeBlock.clientId !== activeBlockClientId ) { + activeBlockClientId = activeBlock.clientId; + + // Get active block name and attributes + const activeBlockName = activeBlock.name; + const activeBlockAttributes = activeBlock.attributes; + + // Log active block name and attributes + console.log( activeBlockName, activeBlockAttributes ); + } +}; + +// Subscribe to changes in the editor +// wp.data.subscribe(() => { +// getActiveBlockData() +// }) + +// Update active block data on click +// onclick="getActiveBlockData()" +``` + _Parameters_ - _state_ `Object`: Global application state. diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 210cd26aeaa954..3fdaadb24fc129 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -542,6 +542,39 @@ export function getSelectedBlockClientId( state ) { * * @param {Object} state Global application state. * + * @example + * + *```js + * import { select } from '@wordpress/data' + * import { store as blockEditorStore } from '@wordpress/block-editor' + * + * // Set initial active block client ID + * let activeBlockClientId = null + * + * const getActiveBlockData = () => { + * const activeBlock = select(blockEditorStore).getSelectedBlock() + * + * if (activeBlock && activeBlock.clientId !== activeBlockClientId) { + * activeBlockClientId = activeBlock.clientId + * + * // Get active block name and attributes + * const activeBlockName = activeBlock.name + * const activeBlockAttributes = activeBlock.attributes + * + * // Log active block name and attributes + * console.log(activeBlockName, activeBlockAttributes) + * } + * } + * + * // Subscribe to changes in the editor + * // wp.data.subscribe(() => { + * // getActiveBlockData() + * // }) + * + * // Update active block data on click + * // onclick="getActiveBlockData()" + *``` + * * @return {?Object} Selected block. */ export function getSelectedBlock( state ) { From 413bf9bf423fba3e130f6f08551f0030d499e76d Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Sat, 19 Oct 2024 16:11:34 +0800 Subject: [PATCH 1250/1908] Fix extra scrollbar appearing when searching in the inserter (#66229) Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> Co-authored-by: dhruvang21 <dhruvang21@git.wordpress.org> --- packages/block-editor/src/components/inserter/style.scss | 6 ++++++ .../block-editor/src/components/tabbed-sidebar/style.scss | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index 9e727b13795249..51228a1c46a248 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -123,6 +123,12 @@ $block-inserter-tabs-height: 44px; } .block-editor-inserter__panel-header { + // Use `position: relative` to ensure any absolute positioned child elements are + // positioned relative to the panel header. + // This makes the overflow rule of the panel work correctly, particularly when the + // `VisuallyHidden` component is used within the inserter UI. + position: relative; + display: inline-flex; align-items: center; padding: $grid-unit-20 $grid-unit-20 0; diff --git a/packages/block-editor/src/components/tabbed-sidebar/style.scss b/packages/block-editor/src/components/tabbed-sidebar/style.scss index f7fba1c0003467..38932f8714ad94 100644 --- a/packages/block-editor/src/components/tabbed-sidebar/style.scss +++ b/packages/block-editor/src/components/tabbed-sidebar/style.scss @@ -32,4 +32,10 @@ flex-direction: column; overflow-y: auto; scrollbar-gutter: auto; + + // Use `position: relative` to ensure any absolute positioned child elements are + // positioned relative to the tab panel. + // This makes the overflow rule of the panel work correctly, particularly when the + // `VisuallyHidden` component is used within the inserter UI. + position: relative; } From d600cee3055e99a747f63e1d82626d522f31f9ad Mon Sep 17 00:00:00 2001 From: tellthemachines <tellthemachines@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:53:22 +1100 Subject: [PATCH 1251/1908] Remove relative position from sidebar tabpanel (#66267) Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- .../block-editor/src/components/tabbed-sidebar/style.scss | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/block-editor/src/components/tabbed-sidebar/style.scss b/packages/block-editor/src/components/tabbed-sidebar/style.scss index 38932f8714ad94..f7fba1c0003467 100644 --- a/packages/block-editor/src/components/tabbed-sidebar/style.scss +++ b/packages/block-editor/src/components/tabbed-sidebar/style.scss @@ -32,10 +32,4 @@ flex-direction: column; overflow-y: auto; scrollbar-gutter: auto; - - // Use `position: relative` to ensure any absolute positioned child elements are - // positioned relative to the tab panel. - // This makes the overflow rule of the panel work correctly, particularly when the - // `VisuallyHidden` component is used within the inserter UI. - position: relative; } From b4443e43b267d9361e1fbd762f602ce490a923ac Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Mon, 21 Oct 2024 03:28:52 +0100 Subject: [PATCH 1252/1908] Resets the Zoom on viewed/edited entity change (#66232) Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> * Resets the Zoom on syncing to new entity * Zoom back out when exiting editor --------- Co-authored-by: Daniel Richards <daniel.richards@automattic.com> --- packages/edit-site/src/components/editor/index.js | 9 +++++++++ .../use-init-edited-entity-from-url.js | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index ae8749a3677afd..c2a7730c0fee56 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -23,6 +23,7 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; import { store as preferencesStore } from '@wordpress/preferences'; import { decodeEntities } from '@wordpress/html-entities'; import { Icon, arrowUpLeft } from '@wordpress/icons'; +import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Internal dependencies @@ -153,6 +154,9 @@ export default function EditSiteEditor( { isPostsList = false } ) { [ settings.styles, canvasMode, currentPostIsTrashed ] ); const { setCanvasMode } = unlock( useDispatch( editSiteStore ) ); + const { __unstableSetEditorMode, resetZoomLevel } = unlock( + useDispatch( blockEditorStore ) + ); const { createSuccessNotice } = useDispatch( noticesStore ); const history = useHistory(); const onActionPerformed = useCallback( @@ -261,6 +265,11 @@ export default function EditSiteEditor( { isPostsList = false } ) { tooltipPosition="middle right" onClick={ () => { setCanvasMode( 'view' ); + __unstableSetEditorMode( + 'edit' + ); + resetZoomLevel(); + // TODO: this is a temporary solution to navigate to the posts list if we are // come here through `posts list` and are in focus mode editing a template, template part etc.. if ( diff --git a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js index ab6ea92bac4413..9f507693c4cfdc 100644 --- a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js +++ b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js @@ -5,6 +5,7 @@ import { useEffect, useMemo } from '@wordpress/element'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as coreDataStore } from '@wordpress/core-data'; import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Internal dependencies @@ -248,9 +249,14 @@ export default function useInitEditedEntityFromURL() { useResolveEditedEntityAndContext( params ); const { setEditedEntity } = useDispatch( editSiteStore ); + const { __unstableSetEditorMode, resetZoomLevel } = unlock( + useDispatch( blockEditorStore ) + ); useEffect( () => { if ( isReady ) { + __unstableSetEditorMode( 'edit' ); + resetZoomLevel(); setEditedEntity( postType, postId, context ); } }, [ isReady, postType, postId, context, setEditedEntity ] ); From 0b972a8db2d75236c7d0310625aaa1cd1ece7e91 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Mon, 21 Oct 2024 15:38:42 +1100 Subject: [PATCH 1253/1908] Theme JSON: get_block_nodes - relocate $selectors assignment (#66265) Backport from https://github.com/WordPress/wordpress-develop/pull/7575 Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: mukeshpanchal27 <mukesh27@git.wordpress.org> --- lib/class-wp-theme-json-gutenberg.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 98d0719cd24a90..5975e4fe9852ff 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2738,10 +2738,14 @@ private static function get_block_nodes( $theme_json, $selectors = array(), $opt return $nodes; } - $selectors = empty( $selectors ) ? static::get_blocks_metadata() : $selectors; $include_variations = $options['include_block_style_variations'] ?? false; $include_node_paths_only = $options['include_node_paths_only'] ?? false; + // If only node paths are to be returned, skip selector assignment. + if ( ! $include_node_paths_only ) { + $selectors = empty( $selectors ) ? static::get_blocks_metadata() : $selectors; + } + foreach ( $theme_json['styles']['blocks'] as $name => $node ) { $node_path = array( 'styles', 'blocks', $name ); if ( $include_node_paths_only ) { From 4693c0f9942f11f48e0912db378b1b9e2fbf4af0 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Mon, 21 Oct 2024 17:14:32 +0900 Subject: [PATCH 1254/1908] Packages: Use npm workspaces (#65681) Update package management to use npm workspaces instead of lerna. Lerna is obsolete for many repository management operations, such as dependency installation or script running. All of these are supported by npm now. Lerna continues to be used for publishing flows to ensure the appropriate dependencies are updated and published with the correct versions. The hope is that this simplfies dependendy management and maintains a more sane dependency tree. Dependency management has become increasingly difficult as Gutenberg has grown. --- Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: yusuke-omae <omaeyusuke@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- bin/check-licenses.mjs | 69 + docs/contributors/code/managing-packages.md | 6 +- package-lock.json | 5682 +++++------------ package.json | 110 +- packages/README.md | 41 +- packages/a11y/.npmrc | 1 - packages/a11y/package.json | 7 +- packages/annotations/.npmrc | 1 - packages/annotations/package.json | 11 +- packages/api-fetch/.npmrc | 1 - packages/api-fetch/package.json | 7 +- packages/autop/.npmrc | 1 - packages/autop/package.json | 3 +- .../babel-plugin-import-jsx-pragma/.npmrc | 1 - packages/babel-plugin-makepot/.npmrc | 1 - packages/babel-preset-default/.npmrc | 1 - packages/babel-preset-default/package.json | 4 +- packages/base-styles/.npmrc | 1 - packages/blob/.npmrc | 1 - packages/blob/package.json | 3 +- packages/block-directory/.npmrc | 1 - packages/block-directory/package.json | 39 +- packages/block-editor/.npmrc | 1 - packages/block-editor/package.json | 63 +- packages/block-library/.npmrc | 1 - packages/block-library/package.json | 69 +- .../block-serialization-default-parser/.npmrc | 1 - .../package.json | 3 +- .../block-serialization-spec-parser/.npmrc | 1 - .../package.json | 3 +- packages/blocks/.npmrc | 1 - packages/blocks/package.json | 33 +- packages/browserslist-config/.npmrc | 1 - packages/commands/.npmrc | 0 packages/commands/package.json | 17 +- packages/components/.npmrc | 1 - packages/components/package.json | 37 +- packages/compose/.npmrc | 1 - packages/compose/package.json | 17 +- packages/core-commands/.npmrc | 1 - packages/core-commands/package.json | 29 +- packages/core-data/.npmrc | 1 - packages/core-data/package.json | 35 +- .../create-block-interactive-template/.npmrc | 1 - .../create-block-tutorial-template/.npmrc | 1 - packages/create-block/.npmrc | 1 - packages/create-block/package.json | 2 +- packages/customize-widgets/.npmrc | 1 - packages/customize-widgets/package.json | 45 +- packages/data-controls/package.json | 9 +- packages/data/.npmrc | 1 - packages/data/package.json | 17 +- packages/dataviews/.npmrc | 1 - packages/dataviews/package.json | 21 +- packages/date/.npmrc | 1 - packages/date/package.json | 5 +- packages/deprecated/.npmrc | 1 - packages/deprecated/package.json | 5 +- packages/docgen/.npmrc | 1 - packages/dom-ready/.npmrc | 1 - packages/dom-ready/package.json | 3 +- packages/dom/.npmrc | 1 - packages/dom/package.json | 5 +- packages/e2e-test-utils-playwright/.npmrc | 1 - packages/e2e-test-utils/.npmrc | 1 - packages/e2e-test-utils/package.json | 6 +- packages/e2e-tests/.npmrc | 1 - packages/e2e-tests/package.json | 14 +- packages/edit-post/.npmrc | 1 - packages/edit-post/package.json | 61 +- packages/edit-site/.npmrc | 1 - packages/edit-site/package.json | 81 +- packages/edit-widgets/.npmrc | 1 - packages/edit-widgets/package.json | 57 +- packages/editor/.npmrc | 1 - packages/editor/package.json | 73 +- packages/element/.npmrc | 1 - packages/element/package.json | 5 +- packages/env/.npmrc | 1 - packages/escape-html/.npmrc | 1 - packages/escape-html/package.json | 3 +- packages/eslint-plugin/.npmrc | 1 - packages/eslint-plugin/package.json | 4 +- packages/fields/.npmrc | 1 - packages/fields/package.json | 41 +- packages/format-library/.npmrc | 1 - packages/format-library/package.json | 27 +- packages/hooks/.npmrc | 1 - packages/hooks/package.json | 3 +- packages/html-entities/.npmrc | 1 - packages/html-entities/package.json | 3 +- packages/i18n/.npmrc | 1 - packages/i18n/package.json | 5 +- packages/icons/.npmrc | 1 - packages/icons/package.json | 7 +- packages/interactivity-router/.npmrc | 1 - packages/interactivity-router/package.json | 4 +- packages/interactivity/.npmrc | 1 - packages/interface/.npmrc | 1 - packages/interface/package.json | 27 +- packages/is-shallow-equal/.npmrc | 1 - packages/is-shallow-equal/package.json | 3 +- packages/jest-console/.npmrc | 1 - packages/jest-preset-default/.npmrc | 1 - packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/.npmrc | 1 - packages/keyboard-shortcuts/.npmrc | 0 packages/keyboard-shortcuts/package.json | 9 +- packages/keycodes/.npmrc | 1 - packages/keycodes/package.json | 5 +- packages/lazy-import/.npmrc | 1 - packages/list-reusable-blocks/.npmrc | 1 - packages/list-reusable-blocks/package.json | 15 +- packages/media-utils/.npmrc | 1 - packages/media-utils/package.json | 11 +- packages/notices/.npmrc | 1 - packages/notices/package.json | 7 +- packages/npm-package-json-lint-config/.npmrc | 1 - packages/nux/.npmrc | 1 - packages/nux/package.json | 17 +- packages/patterns/.npmrc | 1 - packages/patterns/package.json | 31 +- packages/plugins/.npmrc | 1 - packages/plugins/package.json | 15 +- packages/postcss-plugins-preset/.npmrc | 1 - packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/.npmrc | 1 - packages/preferences-persistence/.npmrc | 1 - packages/preferences-persistence/package.json | 5 +- packages/preferences/.npmrc | 1 - packages/preferences/package.json | 21 +- packages/prettier-config/.npmrc | 1 - packages/primitives/.npmrc | 1 - packages/primitives/package.json | 5 +- packages/priority-queue/.npmrc | 1 - packages/priority-queue/package.json | 3 +- packages/private-apis/package.json | 3 +- packages/project-management-automation/.npmrc | 1 - packages/react-i18n/package.json | 7 +- packages/react-native-aztec/.npmrc | 1 - packages/react-native-aztec/package.json | 4 +- packages/react-native-bridge/.npmrc | 1 - packages/react-native-bridge/package.json | 2 +- packages/react-native-editor/.npmrc | 1 - packages/react-native-editor/package.json | 24 +- .../readable-js-assets-webpack-plugin/.npmrc | 1 - packages/redux-routine/.npmrc | 1 - packages/redux-routine/package.json | 3 +- packages/report-flaky-tests/.npmrc | 1 - packages/reusable-blocks/.npmrc | 1 - packages/reusable-blocks/package.json | 25 +- packages/rich-text/.npmrc | 1 - packages/rich-text/package.json | 19 +- packages/router/.npmrc | 0 packages/router/package.json | 9 +- packages/scripts/.npmrc | 1 - packages/scripts/package.json | 20 +- packages/server-side-render/.npmrc | 1 - packages/server-side-render/package.json | 21 +- packages/shortcode/.npmrc | 1 - packages/shortcode/package.json | 3 +- packages/style-engine/.npmrc | 1 - packages/style-engine/package.json | 3 +- packages/stylelint-config/.npmrc | 1 - packages/sync/.npmrc | 1 - packages/sync/package.json | 5 +- packages/token-list/.npmrc | 1 - packages/token-list/package.json | 3 +- packages/undo-manager/.npmrc | 1 - packages/undo-manager/package.json | 5 +- packages/url/.npmrc | 1 - packages/url/package.json | 3 +- packages/viewport/.npmrc | 1 - packages/viewport/package.json | 9 +- packages/warning/.npmrc | 1 - packages/warning/package.json | 3 +- packages/widgets/.npmrc | 1 - packages/widgets/package.json | 25 +- packages/wordcount/.npmrc | 1 - packages/wordcount/package.json | 3 +- tools/webpack/packages.js | 38 +- tools/webpack/script-modules.js | 39 +- 182 files changed, 2329 insertions(+), 5012 deletions(-) create mode 100755 bin/check-licenses.mjs delete mode 100644 packages/a11y/.npmrc delete mode 100644 packages/annotations/.npmrc delete mode 100644 packages/api-fetch/.npmrc delete mode 100644 packages/autop/.npmrc delete mode 100644 packages/babel-plugin-import-jsx-pragma/.npmrc delete mode 100644 packages/babel-plugin-makepot/.npmrc delete mode 100644 packages/babel-preset-default/.npmrc delete mode 100644 packages/base-styles/.npmrc delete mode 100644 packages/blob/.npmrc delete mode 100644 packages/block-directory/.npmrc delete mode 100644 packages/block-editor/.npmrc delete mode 100644 packages/block-library/.npmrc delete mode 100644 packages/block-serialization-default-parser/.npmrc delete mode 100644 packages/block-serialization-spec-parser/.npmrc delete mode 100644 packages/blocks/.npmrc delete mode 100644 packages/browserslist-config/.npmrc delete mode 100644 packages/commands/.npmrc delete mode 100644 packages/components/.npmrc delete mode 100644 packages/compose/.npmrc delete mode 100644 packages/core-commands/.npmrc delete mode 100644 packages/core-data/.npmrc delete mode 100644 packages/create-block-interactive-template/.npmrc delete mode 100644 packages/create-block-tutorial-template/.npmrc delete mode 100644 packages/create-block/.npmrc delete mode 100644 packages/customize-widgets/.npmrc delete mode 100644 packages/data/.npmrc delete mode 100644 packages/dataviews/.npmrc delete mode 100644 packages/date/.npmrc delete mode 100644 packages/deprecated/.npmrc delete mode 100644 packages/docgen/.npmrc delete mode 100644 packages/dom-ready/.npmrc delete mode 100644 packages/dom/.npmrc delete mode 100644 packages/e2e-test-utils-playwright/.npmrc delete mode 100644 packages/e2e-test-utils/.npmrc delete mode 100644 packages/e2e-tests/.npmrc delete mode 100644 packages/edit-post/.npmrc delete mode 100644 packages/edit-site/.npmrc delete mode 100644 packages/edit-widgets/.npmrc delete mode 100644 packages/editor/.npmrc delete mode 100644 packages/element/.npmrc delete mode 100644 packages/env/.npmrc delete mode 100644 packages/escape-html/.npmrc delete mode 100644 packages/eslint-plugin/.npmrc delete mode 100644 packages/fields/.npmrc delete mode 100644 packages/format-library/.npmrc delete mode 100644 packages/hooks/.npmrc delete mode 100644 packages/html-entities/.npmrc delete mode 100644 packages/i18n/.npmrc delete mode 100644 packages/icons/.npmrc delete mode 100644 packages/interactivity-router/.npmrc delete mode 100644 packages/interactivity/.npmrc delete mode 100644 packages/interface/.npmrc delete mode 100644 packages/is-shallow-equal/.npmrc delete mode 100644 packages/jest-console/.npmrc delete mode 100644 packages/jest-preset-default/.npmrc delete mode 100644 packages/jest-puppeteer-axe/.npmrc delete mode 100644 packages/keyboard-shortcuts/.npmrc delete mode 100644 packages/keycodes/.npmrc delete mode 100644 packages/lazy-import/.npmrc delete mode 100644 packages/list-reusable-blocks/.npmrc delete mode 100644 packages/media-utils/.npmrc delete mode 100644 packages/notices/.npmrc delete mode 100644 packages/npm-package-json-lint-config/.npmrc delete mode 100644 packages/nux/.npmrc delete mode 100644 packages/patterns/.npmrc delete mode 100644 packages/plugins/.npmrc delete mode 100644 packages/postcss-plugins-preset/.npmrc delete mode 100644 packages/postcss-themes/.npmrc delete mode 100644 packages/preferences-persistence/.npmrc delete mode 100644 packages/preferences/.npmrc delete mode 100644 packages/prettier-config/.npmrc delete mode 100644 packages/primitives/.npmrc delete mode 100644 packages/priority-queue/.npmrc delete mode 100644 packages/project-management-automation/.npmrc delete mode 100644 packages/react-native-aztec/.npmrc delete mode 100644 packages/react-native-bridge/.npmrc delete mode 100644 packages/react-native-editor/.npmrc delete mode 100644 packages/readable-js-assets-webpack-plugin/.npmrc delete mode 100644 packages/redux-routine/.npmrc delete mode 100644 packages/report-flaky-tests/.npmrc delete mode 100644 packages/reusable-blocks/.npmrc delete mode 100644 packages/rich-text/.npmrc delete mode 100644 packages/router/.npmrc delete mode 100644 packages/scripts/.npmrc delete mode 100644 packages/server-side-render/.npmrc delete mode 100644 packages/shortcode/.npmrc delete mode 100644 packages/style-engine/.npmrc delete mode 100644 packages/stylelint-config/.npmrc delete mode 100644 packages/sync/.npmrc delete mode 100644 packages/token-list/.npmrc delete mode 100644 packages/undo-manager/.npmrc delete mode 100644 packages/url/.npmrc delete mode 100644 packages/viewport/.npmrc delete mode 100644 packages/warning/.npmrc delete mode 100644 packages/widgets/.npmrc delete mode 100644 packages/wordcount/.npmrc diff --git a/bin/check-licenses.mjs b/bin/check-licenses.mjs new file mode 100755 index 00000000000000..458590e696a9fd --- /dev/null +++ b/bin/check-licenses.mjs @@ -0,0 +1,69 @@ +#!/usr/bin/env node + +/** + * External dependencies + */ +import { spawnSync } from 'node:child_process'; + +/** + * Internal dependencies + */ +import { checkDepsInTree } from '../packages/scripts/utils/license.js'; + +const ignored = [ '@ampproject/remapping' ]; + +/* + * `wp-scripts check-licenses` uses prod and dev dependencies of the package to scan for dependencies. With npm workspaces, workspace packages (the @wordpress/* packages) are not listed in the main package json and this approach does not work. + * + * Instead, work from an npm query that uses some custom information in package.json files to declare packages that are shipped with WordPress (and must be GPLv2 compatible) or other files that may use more permissive licenses. + */ + +/** + * @typedef PackageInfo + * @property {string} name Package name. + */ + +/** @type {ReadonlyArray<PackageInfo>} */ +const workspacePackages = JSON.parse( + spawnSync( + 'npm', + [ + 'query', + '.workspace:attr([wpScript]), .workspace:attr([wpScriptModuleExports])', + ], + /* + * Set the max buffer to ~157MB, since the output size for + * prod is ~21 MB and dev is ~110 MB + */ + { maxBuffer: 1024 * 1024 * 150 } + ).stdout +); + +const packageNames = workspacePackages.map( ( { name } ) => name ); + +const dependenciesToProcess = JSON.parse( + spawnSync( + 'npm', + [ + 'ls', + '--json', + '--long', + '--all', + '--lockfile-only', + '--omit=dev', + ...packageNames.map( + ( packageName ) => `--workspace=${ packageName }` + ), + ], + /* + * Set the max buffer to ~157MB, since the output size for + * prod is ~21 MB and dev is ~110 MB + */ + { maxBuffer: 1024 * 1024 * 150 } + ).stdout +).dependencies; + +checkDepsInTree( dependenciesToProcess, { + ignored, + gpl2: true, +} ); diff --git a/docs/contributors/code/managing-packages.md b/docs/contributors/code/managing-packages.md index bfea8fed81242b..8ad0266b1482bf 100644 --- a/docs/contributors/code/managing-packages.md +++ b/docs/contributors/code/managing-packages.md @@ -1,11 +1,7 @@ # Managing Packages -This repository uses [monorepo] to manage WordPress modules and publish them with [lerna] as packages to [npm]. This enforces certain steps in the workflow which are described in details in [packages](https://github.com/WordPress/gutenberg/blob/HEAD/packages/README.md) documentation. +This repository uses [npm workspaces](https://docs.npmjs.com/cli/v10/using-npm/workspaces) to manage WordPress packages and [lerna](https://lerna.js.org/) to publish them to [npm](https://www.npmjs.com/). This enforces certain steps in the workflow which are described in details in [packages](https://github.com/WordPress/gutenberg/blob/HEAD/packages/README.md) documentation. Maintaining dozens of npm packages is difficult—it can be tough to keep track of changes. That's why we use `CHANGELOG.md` files for each package to simplify the release process. As a contributor, you should add an entry to the aforementioned file each time you contribute adding production code as described in [Maintaining Changelogs](https://github.com/WordPress/gutenberg/blob/HEAD/packages/README.md#maintaining-changelogs) section. Publishing WordPress packages to npm is automated by synchronizing it with the bi-weekly Gutenberg plugin RC1 release. You can learn more about this process and other ways to publish new versions of npm packages in the [Gutenberg Release Process document](/docs/contributors/code/release.md#packages-releases-to-npm-and-wordpress-core-updates). - -[lerna]: https://lerna.js.org/ -[monorepo]: https://monorepo.tools -[npm]: https://www.npmjs.com/ diff --git a/package-lock.json b/package-lock.json index 3c328a047fc588..288a2ee5904d7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,80 +9,9 @@ "version": "19.5.0-rc.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", - "dependencies": { - "@wordpress/a11y": "file:packages/a11y", - "@wordpress/annotations": "file:packages/annotations", - "@wordpress/api-fetch": "file:packages/api-fetch", - "@wordpress/autop": "file:packages/autop", - "@wordpress/blob": "file:packages/blob", - "@wordpress/block-directory": "file:packages/block-directory", - "@wordpress/block-editor": "file:packages/block-editor", - "@wordpress/block-library": "file:packages/block-library", - "@wordpress/block-serialization-default-parser": "file:packages/block-serialization-default-parser", - "@wordpress/block-serialization-spec-parser": "file:packages/block-serialization-spec-parser", - "@wordpress/blocks": "file:packages/blocks", - "@wordpress/commands": "file:packages/commands", - "@wordpress/components": "file:packages/components", - "@wordpress/compose": "file:packages/compose", - "@wordpress/core-commands": "file:packages/core-commands", - "@wordpress/core-data": "file:packages/core-data", - "@wordpress/customize-widgets": "file:packages/customize-widgets", - "@wordpress/data": "file:packages/data", - "@wordpress/data-controls": "file:packages/data-controls", - "@wordpress/dataviews": "file:packages/dataviews", - "@wordpress/date": "file:packages/date", - "@wordpress/deprecated": "file:packages/deprecated", - "@wordpress/dom": "file:packages/dom", - "@wordpress/dom-ready": "file:packages/dom-ready", - "@wordpress/edit-post": "file:packages/edit-post", - "@wordpress/edit-site": "file:packages/edit-site", - "@wordpress/edit-widgets": "file:packages/edit-widgets", - "@wordpress/editor": "file:packages/editor", - "@wordpress/element": "file:packages/element", - "@wordpress/escape-html": "file:packages/escape-html", - "@wordpress/fields": "file:packages/fields", - "@wordpress/format-library": "file:packages/format-library", - "@wordpress/hooks": "file:packages/hooks", - "@wordpress/html-entities": "file:packages/html-entities", - "@wordpress/i18n": "file:packages/i18n", - "@wordpress/icons": "file:packages/icons", - "@wordpress/interactivity": "file:packages/interactivity", - "@wordpress/interactivity-router": "file:packages/interactivity-router", - "@wordpress/interface": "file:packages/interface", - "@wordpress/is-shallow-equal": "file:packages/is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts", - "@wordpress/keycodes": "file:packages/keycodes", - "@wordpress/list-reusable-blocks": "file:packages/list-reusable-blocks", - "@wordpress/media-utils": "file:packages/media-utils", - "@wordpress/notices": "file:packages/notices", - "@wordpress/nux": "file:packages/nux", - "@wordpress/patterns": "file:packages/patterns", - "@wordpress/plugins": "file:packages/plugins", - "@wordpress/preferences": "file:packages/preferences", - "@wordpress/preferences-persistence": "file:packages/preferences-persistence", - "@wordpress/primitives": "file:packages/primitives", - "@wordpress/priority-queue": "file:packages/priority-queue", - "@wordpress/private-apis": "file:packages/private-apis", - "@wordpress/react-i18n": "file:packages/react-i18n", - "@wordpress/react-native-aztec": "file:packages/react-native-aztec", - "@wordpress/react-native-bridge": "file:packages/react-native-bridge", - "@wordpress/react-native-editor": "file:packages/react-native-editor", - "@wordpress/redux-routine": "file:packages/redux-routine", - "@wordpress/reusable-blocks": "file:packages/reusable-blocks", - "@wordpress/rich-text": "file:packages/rich-text", - "@wordpress/router": "file:packages/router", - "@wordpress/server-side-render": "file:packages/server-side-render", - "@wordpress/shortcode": "file:packages/shortcode", - "@wordpress/style-engine": "file:packages/style-engine", - "@wordpress/sync": "file:packages/sync", - "@wordpress/token-list": "file:packages/token-list", - "@wordpress/undo-manager": "file:packages/undo-manager", - "@wordpress/url": "file:packages/url", - "@wordpress/viewport": "file:packages/viewport", - "@wordpress/warning": "file:packages/warning", - "@wordpress/widgets": "file:packages/widgets", - "@wordpress/wordcount": "file:packages/wordcount" - }, + "workspaces": [ + "packages/*" + ], "devDependencies": { "@actions/core": "1.9.1", "@actions/github": "5.0.0", @@ -132,33 +61,6 @@ "@types/semver": "7.3.8", "@types/sprintf-js": "1.1.2", "@types/uuid": "8.3.1", - "@wordpress/babel-plugin-import-jsx-pragma": "file:packages/babel-plugin-import-jsx-pragma", - "@wordpress/babel-plugin-makepot": "file:packages/babel-plugin-makepot", - "@wordpress/babel-preset-default": "file:packages/babel-preset-default", - "@wordpress/base-styles": "file:packages/base-styles", - "@wordpress/browserslist-config": "file:packages/browserslist-config", - "@wordpress/create-block": "file:packages/create-block", - "@wordpress/create-block-tutorial-template": "file:packages/create-block-tutorial-template", - "@wordpress/dependency-extraction-webpack-plugin": "file:packages/dependency-extraction-webpack-plugin", - "@wordpress/docgen": "file:packages/docgen", - "@wordpress/e2e-test-utils": "file:packages/e2e-test-utils", - "@wordpress/e2e-test-utils-playwright": "file:packages/e2e-test-utils-playwright", - "@wordpress/e2e-tests": "file:packages/e2e-tests", - "@wordpress/env": "file:packages/env", - "@wordpress/eslint-plugin": "file:packages/eslint-plugin", - "@wordpress/jest-console": "file:packages/jest-console", - "@wordpress/jest-preset-default": "file:packages/jest-preset-default", - "@wordpress/jest-puppeteer-axe": "file:packages/jest-puppeteer-axe", - "@wordpress/lazy-import": "file:packages/lazy-import", - "@wordpress/npm-package-json-lint-config": "file:packages/npm-package-json-lint-config", - "@wordpress/postcss-plugins-preset": "file:packages/postcss-plugins-preset", - "@wordpress/postcss-themes": "file:packages/postcss-themes", - "@wordpress/prettier-config": "file:packages/prettier-config", - "@wordpress/project-management-automation": "file:packages/project-management-automation", - "@wordpress/readable-js-assets-webpack-plugin": "file:packages/readable-js-assets-webpack-plugin", - "@wordpress/report-flaky-tests": "file:packages/report-flaky-tests", - "@wordpress/scripts": "file:packages/scripts", - "@wordpress/stylelint-config": "file:packages/stylelint-config", "ajv": "8.7.1", "appium": "2.0.0", "babel-jest": "29.7.0", @@ -264,7 +166,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", - "dev": true, "dependencies": { "@actions/http-client": "^2.0.1", "uuid": "^8.3.2" @@ -274,7 +175,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -283,7 +183,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.0.tgz", "integrity": "sha512-QvE9eAAfEsS+yOOk0cylLBIO/d6WyWIOvsxxzdrPFaud39G6BOkUwScXZn1iBzQzHyu9SBkkLSWlohDWdsasAQ==", - "dev": true, "dependencies": { "@actions/http-client": "^1.0.11", "@octokit/core": "^3.4.0", @@ -295,7 +194,6 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz", "integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==", - "dev": true, "dependencies": { "tunnel": "0.0.6" } @@ -304,7 +202,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", - "dev": true, "license": "MIT", "dependencies": { "tunnel": "^0.0.6", @@ -1579,7 +1476,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/@axe-core/puppeteer/-/puppeteer-4.0.0.tgz", "integrity": "sha512-APFc2iRmrmUfqdBUevjsMxJliDudWPwvCU5Pzw2uKZ0sMVtW3rQuElTcfJCHFq8KOZSSO0BPD+lK+pXOx1ta5Q==", - "dev": true, "dependencies": { "axe-core": "^4.0.1" }, @@ -1604,9 +1500,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.7.tgz", - "integrity": "sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.8.tgz", + "integrity": "sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1683,12 +1579,13 @@ } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", - "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.7.tgz", + "integrity": "sha512-12xfNeKNH7jubQNm7PAkzlLwEmCs1tfuX3UjIw6vP6QXi+leKh6+LyC/+Ed4EIQermwd58wsyh070yjDHFlNGg==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1732,18 +1629,17 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.9.tgz", - "integrity": "sha512-B2L9neXTIyPQoXDm+NtovPvG6VOLWnaXu3BIeVDWwdKFgG30oNa6CqVGiJPDWQwIAK49t9gnQI9c6K6RzabiKw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.7.tgz", + "integrity": "sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==", + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/traverse": "^7.25.7", "semver": "^6.3.1" }, "engines": { @@ -1787,29 +1683,19 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.4.tgz", - "integrity": "sha512-OrpPZ97s+aPi6h2n1OXzdhVis1SGSsMU2aMHgLcOKfsp4/v1NWpx3CWT3lBj5eeBq9cDkPkh+YCfdF7O12uNDQ==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" + "resolve": "^1.14.2" }, "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/helper-environment-visitor": { @@ -1820,36 +1706,14 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.7.tgz", + "integrity": "sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1887,11 +1751,12 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.7.tgz", + "integrity": "sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1924,13 +1789,14 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.7.tgz", + "integrity": "sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==", + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5" + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1953,22 +1819,13 @@ } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.7.tgz", + "integrity": "sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2088,7 +1945,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.7.tgz", "integrity": "sha512-UV9Lg53zyebzD1DwQoT9mzkEKa922LNUp5YkTJ6Uta0RbyXaQNUgcvSt7qIu1PpPzVb6rd10OVNTzkyBGeVmxQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -2105,7 +1961,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.7.tgz", "integrity": "sha512-GDDWeVLNxRIkQTnJn2pDOM1pkCgYdSqPeT1a9vh9yIqu2uzzgw1zcqEb+IJOhy+dTBMlNdThrDIksr2o09qrrQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -2118,12 +1973,12 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", - "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.7.tgz", + "integrity": "sha512-wxyWg2RYaSUYgmd9MR0FyRGyeOMQE/Uzr1wzd/g5cf5bwi9A4v6HFdDm7y1MgDtod/fLOSTZY6jDgV0xU9d5bA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2133,14 +1988,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", - "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.7.tgz", + "integrity": "sha512-Xwg6tZpLxc4iQjorYsyGMyfJE7nP5MV8t/Ka58BgiA7Jw0fRqQNcANlLfdJ/yvBt9z9LD2We+BEkT7vLqZRWng==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.23.3" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-transform-optional-chaining": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2150,13 +2005,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", - "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.7.tgz", + "integrity": "sha512-UVATLMidXrnH+GMUIuxq55nejlj02HP7F5ETyBONzP6G87fPBogG4CH6kxrSrdIuAjdwNO9VzyaYsrZPscWUrw==", + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2302,7 +2157,6 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -2326,7 +2180,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -2338,7 +2191,6 @@ "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -2350,7 +2202,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -2390,7 +2241,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -2413,12 +2263,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", - "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.7.tgz", + "integrity": "sha512-ZvZQRmME0zfJnDQnVBKYzHxXT7lYBB3Revz1GuS7oLXWMgqUPX4G+DDbT30ICClht9WKV34QVrZhSw6WdklwZQ==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2428,12 +2278,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", - "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", + "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2446,7 +2296,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -2458,7 +2307,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -2485,7 +2333,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -2566,7 +2413,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -2578,11 +2424,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.7.tgz", + "integrity": "sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2595,7 +2442,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -2608,11 +2454,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", - "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.7.tgz", + "integrity": "sha512-EJN2mKxDwfOUCPxMO6MUI58RN3ganiRAG/MS/S3HfB6QFNjroAMelQo/gybyYq97WerCBAZoyrAoW8Tzdq2jWg==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2622,15 +2469,13 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.7.tgz", - "integrity": "sha512-4B6OhTrwYKHYYgcwErvZjbmH9X5TxQBsaBHdzEIB4l71gR5jh/tuHGlb9in47udL2+wVUcOz5XXhhfhVJwEpEg==", - "dev": true, + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.8.tgz", + "integrity": "sha512-9ypqkozyzpG+HxlH4o4gdctalFGIjjdufzo7I2XPda0iBnZ6a+FO0rIEQcdSPXp02CkvGsII1exJhmROPQd5oA==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", "@babel/helper-remap-async-to-generator": "^7.25.7", - "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/traverse": "^7.25.7" }, "engines": { @@ -2641,13 +2486,14 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", - "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.7.tgz", + "integrity": "sha512-ZUCjAavsh5CESCmi/xCpX1qcCaAglzs/7tmuvoFnJgA1dM7gQplsguljoTg+Ru8WENpX89cQyAtWoaE0I3X3Pg==", + "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.20" + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-remap-async-to-generator": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2657,12 +2503,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", - "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.7.tgz", + "integrity": "sha512-xHttvIM9fvqW+0a3tZlYcZYSBpSWzGBFIt/sYG3tcdSzBB8ZeVgz2gBP7Df+sM0N1850jrviYSSeUuc+135dmQ==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2672,11 +2518,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", - "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.7.tgz", + "integrity": "sha512-ZEPJSkVZaeTFG/m2PARwLZQ+OG0vFIhPlKHK/JdIMy8DbRJ/htz6LRrTFtdzxi9EHmcwbNPAKDnadpNSIW+Aow==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2686,13 +2533,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", - "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.7.tgz", + "integrity": "sha512-mhyfEW4gufjIqYFo9krXHJ3ElbFLIze5IDp+wQTxoPd+mwFb1NxatNAwmv8Q8Iuxv7Zc+q8EkiMQwc9IhyGf4g==", + "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2702,14 +2549,13 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", - "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", - "dev": true, + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.8.tgz", + "integrity": "sha512-e82gl3TCorath6YLf9xUwFehVvjvfqFhdOo4+0iVIVju+6XOi5XHkqB3P2AXnSwoeTX0HBoXq5gJFtvotJzFnQ==", + "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-class-static-block": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2719,17 +2565,16 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", - "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.7.tgz", + "integrity": "sha512-9j9rnl+YCQY0IGoeipXvnk3niWicIB6kCsWRGLwX241qSXpbA4MKxtp/EdvFxsc4zI5vqfLxzOd0twIJ7I99zg==", + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/traverse": "^7.25.7", "globals": "^11.1.0" }, "engines": { @@ -2748,12 +2593,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", - "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.7.tgz", + "integrity": "sha512-QIv+imtM+EtNxg/XBKL3hiWjgdLjMOmZ+XzQwSgmBfKbfxUjBzGgVPklUuE55eq5/uVoh8gg3dqlrwR/jw3ZeA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.15" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/template": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2763,11 +2609,12 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", - "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.7.tgz", + "integrity": "sha512-xKcfLTlJYUczdaM1+epcdh1UGewJqr9zATgrNHcLBcV2QmfvPPEixo/sK/syql9cEmbr7ulu5HMFG5vbbt/sEA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2777,13 +2624,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", - "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.7.tgz", + "integrity": "sha512-kXzXMMRzAtJdDEgQBLF4oaiT6ZCU3oWHgpARnTKDAqPkDJ+bs3NrZb310YYevR5QlRo3Kn7dzzIdHbZm1VzJdQ==", + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2793,12 +2640,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", - "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.7.tgz", + "integrity": "sha512-by+v2CjoL3aMnWDOyCIg+yxU9KXSRa9tN6MbqggH5xvymmr9p4AMjYkNlQy4brMceBnUyHZ9G8RnpvT8wP7Cfg==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2811,7 +2658,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.7.tgz", "integrity": "sha512-HvS6JF66xSS5rNKXLqkk7L9c/jZ/cdIVIcoPVrnl8IsVpLggTjXs8OWekbLHs/VtYDDh5WXnQyeE3PPUGm22MA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.7", @@ -2825,13 +2671,12 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", - "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", - "dev": true, + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.8.tgz", + "integrity": "sha512-gznWY+mr4ZQL/EWPcbBQUP3BXS5FwZp8RUOw06BaRn8tQLzN4XLIxXejpHN9Qo8x8jjBmAAKp6FoS51AgkSA/A==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2841,13 +2686,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", - "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.7.tgz", + "integrity": "sha512-yjqtpstPfZ0h/y40fAXRv2snciYr0OAoMXY/0ClC7tm4C/nG5NJKmIItlaYlLbIVAWNfrYuy9dq1bE0SbX0PEg==", + "license": "MIT", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2857,14 +2702,12 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.7.tgz", - "integrity": "sha512-h3MDAP5l34NQkkNulsTNyjdaR+OiB0Im67VU//sFupouP8Q6m9Spy7l66DcaAQxtmCqGdanPByLsnwFttxKISQ==", - "dev": true, + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.8.tgz", + "integrity": "sha512-sPtYrduWINTQTW7FtOy99VCTWp4H23UX7vYcut7S4CIMEXU+54zKX9uCoGkLsWXteyaMXzVHgzWbLfQ1w4GZgw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2889,13 +2732,13 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", - "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.7.tgz", + "integrity": "sha512-n/TaiBGJxYFWvpJDfsxSj9lEEE44BFM1EPGz4KEiTipTgkoFVVcCmzAL3qA7fdQU96dpo4gGf5HBx/KnDvqiHw==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2905,13 +2748,14 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", - "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.7.tgz", + "integrity": "sha512-5MCTNcjCMxQ63Tdu9rxyN6cAWurqfrDZ76qvVPrGYdBxIj+EawuuxTu/+dgJlhK5eRz3v1gLwp6XwS8XaX2NiQ==", + "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2921,13 +2765,12 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", - "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", - "dev": true, + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.8.tgz", + "integrity": "sha512-4OMNv7eHTmJ2YXs3tvxAfa/I43di+VcF+M4Wt66c88EAED1RoGaf1D64cL5FkRpNL+Vx9Hds84lksWvd/wMIdA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-json-strings": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2937,11 +2780,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", - "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.7.tgz", + "integrity": "sha512-fwzkLrSu2fESR/cm4t6vqd7ebNIopz2QHGtjoU+dswQo/P6lwAG04Q98lliE3jkz/XqnbGFLnUcE0q0CVUf92w==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2951,13 +2795,12 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", - "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", - "dev": true, + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.8.tgz", + "integrity": "sha512-f5W0AhSbbI+yY6VakT04jmxdxz+WsID0neG7+kQZbCOjuyJNdL5Nn4WIBm4hRpKnUcO9lP0eipUhFN12JpoH8g==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2967,12 +2810,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", - "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.7.tgz", + "integrity": "sha512-Std3kXwpXfRV0QtQy5JJcRpkqP8/wG4XL7hSKZmGlxPlDqmpXtEPRmhF7ztnlTCtUN3eXRUJp+sBEZjaIBVYaw==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2982,13 +2825,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", - "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.7.tgz", + "integrity": "sha512-CgselSGCGzjQvKzghCvDTxKHP3iooenLpJDO842ehn5D2G5fJB222ptnDwQho0WjEvg7zyoxb9P+wiYxiJX5yA==", + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2998,13 +2841,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", - "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.7.tgz", + "integrity": "sha512-L9Gcahi0kKFYXvweO6n0wc3ZG1ChpSFdgG+eV1WYZ3/dGbJK7vvk91FgGgak8YwRgrCuihF8tE/Xg07EkL5COg==", + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3014,15 +2858,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz", - "integrity": "sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.7.tgz", + "integrity": "sha512-t9jZIvBmOXJsiuyOwhrIGs8dVcD6jDyg2icw1VL4A/g+FnWyJKwUfSSU2nwJuMV2Zqui856El9u+ElB+j9fV1g==", + "license": "MIT", "dependencies": { - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3032,13 +2876,13 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", - "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.7.tgz", + "integrity": "sha512-p88Jg6QqsaPh+EB7I9GJrIqi1Zt4ZBHUQtjw3z1bzEXcLh6GfPqzZJ6G+G1HBGKUNukT58MnKG7EN7zXQBCODw==", + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3048,12 +2892,13 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", - "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.7.tgz", + "integrity": "sha512-BtAT9LzCISKG3Dsdw5uso4oV1+v2NlVXIIomKJgQybotJY3OwCwJmkongjHgwGKoZXd0qG5UZ12JUlDQ07W6Ow==", + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3063,12 +2908,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", - "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.7.tgz", + "integrity": "sha512-CfCS2jDsbcZaVYxRFo2qtavW8SpdzmBXC2LOI4oO0rP+JSRDxxF3inF4GcPsLgfb5FjkhXG5/yR/lxuRs2pySA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3078,13 +2923,12 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", - "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", - "dev": true, + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.8.tgz", + "integrity": "sha512-Z7WJJWdQc8yCWgAmjI3hyC+5PXIubH9yRKzkl9ZEG647O9szl9zvmKLzpbItlijBnVhTUf1cpyWBsZ3+2wjWPQ==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3094,13 +2938,12 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", - "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", - "dev": true, + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.8.tgz", + "integrity": "sha512-rm9a5iEFPS4iMIy+/A/PiS0QN0UyjPIeVvbU5EMZFKJZHt8vQnasbpo3T3EFcxzCeYO0BHfc4RqooCZc51J86Q==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3124,16 +2967,14 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", - "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", - "dev": true, + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.8.tgz", + "integrity": "sha512-LkUu0O2hnUKHKE7/zYOIjByMa4VRaV2CD/cdGz0AxU9we+VA3kDDggKEzI0Oz1IroG+6gUP6UmWEHBMWZU316g==", + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.23.3", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.23.3" + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-transform-parameters": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3143,13 +2984,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", - "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.7.tgz", + "integrity": "sha512-pWT6UXCEW3u1t2tcAGtE15ornCBvopHj9Bps9D2DsH15APgNVOTwwczGckX+WkAvBmuoYKRCFa4DK+jM8vh5AA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3159,13 +3000,12 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", - "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", - "dev": true, + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.8.tgz", + "integrity": "sha512-EbQYweoMAHOn7iJ9GgZo14ghhb9tTjgOc88xFgYngifx7Z9u580cENCV159M4xDh3q/irbhSjZVpuhpC2gKBbg==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3175,14 +3015,13 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", - "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", - "dev": true, + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.8.tgz", + "integrity": "sha512-q05Bk7gXOxpTHoQ8RSzGSh/LHVB9JEIkKnk3myAWwZHnYiTGYtbdrYkIsS8Xyh4ltKf7GNUSgzs/6P2bJtBAQg==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3192,11 +3031,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", - "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.7.tgz", + "integrity": "sha512-FYiTvku63me9+1Nz7TOx4YMtW3tWXzfANZtrzHhUZrz4d47EEtMQhzFoZWESfXuAMMT5mwzD4+y1N8ONAX6lMQ==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3206,12 +3046,13 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", - "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz", + "integrity": "sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==", + "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3221,14 +3062,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", - "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.8.tgz", + "integrity": "sha512-8Uh966svuB4V8RHHg0QJOB32QK287NBksJOByoKmHMp1TAobNniNalIkI2i5IPj5+S9NYCG4VIjbEuiSN8r+ow==", + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3238,12 +3079,12 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", - "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.7.tgz", + "integrity": "sha512-lQEeetGKfFi0wHbt8ClQrUSUMfEeI3MMm74Z73T9/kuz990yYVtfofjf3NuA42Jy3auFOpbjDyCSiIkTs1VIYw==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3256,7 +3097,6 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.22.5.tgz", "integrity": "sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -3282,15 +3122,16 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", - "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.7.tgz", + "integrity": "sha512-vILAg5nwGlR9EXE8JIOX4NHXd49lrYbN8hnjffDtoULwpL9hUx/N55nqh2qd0q6FyNDfjl9V79ecKGvFbcSA0Q==", + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/types": "^7.23.4" + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-jsx": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3303,7 +3144,6 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", - "dev": true, "dependencies": { "@babel/plugin-transform-react-jsx": "^7.22.5" }, @@ -3346,7 +3186,6 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.23.3.tgz", "integrity": "sha512-qMFdSS+TUhB7Q/3HVPnEdYJDQIk57jkntAwSuz9xfSE4n+3I+vHYCli3HoHawN1Z3RfCz/y1zXA/JXjG6cVImQ==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5" @@ -3359,12 +3198,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", - "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.7.tgz", + "integrity": "sha512-mgDoQCRjrY3XK95UuV60tZlFCQGXEtMg8H+IsW72ldw1ih1jZhzYXbJvghmAEpg5UVhhnCeia1CkGttUvCkiMQ==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.25.7", "regenerator-transform": "^0.15.2" }, "engines": { @@ -3375,12 +3214,12 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", - "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.7.tgz", + "integrity": "sha512-3OfyfRRqiGeOvIWSagcwUTVk2hXBsr/ww7bLn6TRTuXnexA+Udov2icFOxFX9abaj4l96ooYkcNN1qi2Zvqwng==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3390,16 +3229,17 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.0.tgz", - "integrity": "sha512-zlPf1/XFn5+vWdve3AAhf+Sxl+MVa5VlwTwWgnLx23u4GlatSRQJ3Eoo9vllf0a9il3woQsT4SK+5Z7c06h8ag==", - "dependencies": { - "@babel/helper-module-imports": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", - "babel-plugin-polyfill-corejs2": "^0.2.3", - "babel-plugin-polyfill-corejs3": "^0.3.0", - "babel-plugin-polyfill-regenerator": "^0.2.3", - "semver": "^6.3.0" + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.7.tgz", + "integrity": "sha512-Y9p487tyTzB0yDYQOtWnC+9HGOuogtP3/wNpun1xJXEEvI6vip59BSBTsHnekZLqxmPcgsrAKt46HAAb//xGhg==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -3417,11 +3257,12 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", - "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.7.tgz", + "integrity": "sha512-uBbxNwimHi5Bv3hUccmOFlUy3ATO6WagTApenHz9KzoIdn0XeACdB12ZJ4cjhuB2WSi80Ez2FWzJnarccriJeA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3431,12 +3272,13 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", - "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.7.tgz", + "integrity": "sha512-Mm6aeymI0PBh44xNIv/qvo8nmbkpZze1KvR8MkEqbIREDxoiWTi18Zr2jryfRMwDfVZF9foKh060fWgni44luw==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3446,11 +3288,12 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", - "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.7.tgz", + "integrity": "sha512-ZFAeNkpGuLnAQ/NCsXJ6xik7Id+tHuS+NT+ue/2+rn/31zcdnupCdmunOizEaP0JsUmTFSTOPoQY7PkK2pttXw==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3460,12 +3303,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", - "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.7.tgz", + "integrity": "sha512-SI274k0nUsFFmyQupiO7+wKATAmMFf8iFgq2O+vVFXZ0SV9lNfT1NGzBEhjquFmD8I9sqHLguH+gZVN3vww2AA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3475,12 +3318,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", - "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.7.tgz", + "integrity": "sha512-OmWmQtTHnO8RSUbL0NTdtpbZHeNTnm68Gj5pA4Y2blFNh+V4iZR68V1qL9cI37J21ZN7AaCnkfdHtLExQPf2uA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3490,14 +3333,16 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz", - "integrity": "sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.7.tgz", + "integrity": "sha512-VKlgy2vBzj8AmEzunocMun2fF06bsSWV+FvVXohtL6FGve/+L217qhHxRTVGHEDO/YR8IANcjzgJsd04J8ge5Q==", + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-typescript": "^7.23.3" + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-syntax-typescript": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3507,12 +3352,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", - "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.7.tgz", + "integrity": "sha512-BN87D7KpbdiABA+t3HbVqHzKWUDN3dymLaTnPFAMyc8lV+KN3+YzNhVRNdinaCPA4AUqx7ubXbQ9shRjYBl3SQ==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3522,13 +3367,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", - "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.7.tgz", + "integrity": "sha512-IWfR89zcEPQGB/iB408uGtSPlQd3Jpq11Im86vUgcmSTcoWAiQMCTOa2K2yNNqFJEBVICKhayctee65Ka8OB0w==", + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3538,12 +3383,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", - "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.7.tgz", + "integrity": "sha512-8JKfg/hiuA3qXnlLx8qtv5HWRbgyFx2hMMtpDDuU2rTckpKkGu4ycK5yYHwuEa16/quXfoxHBIApEsNyMWnt0g==", + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3553,13 +3399,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", - "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", - "dev": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.7.tgz", + "integrity": "sha512-YRW8o9vzImwmh4Q3Rffd09bH5/hvY0pxg+1H1i0f7APoUeg12G7+HhLj9ZFNIrYkgBXhIijPJ+IXypN0hLTIbw==", + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3569,90 +3415,78 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.9.tgz", - "integrity": "sha512-3kBGTNBBk9DQiPoXYS0g0BYlwTQYUTifqgKTjxUwEUkduRT2QOa0FPGBJ+NROQhGyYO5BuTJwGvBnqKDykac6A==", - "dev": true, + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.8.tgz", + "integrity": "sha512-58T2yulDHMN8YMUxiLq5YmWUnlDCyY1FsHM+v12VMx+1/FlrUj5tY50iDCpofFQEM8fMYOaY9YRvym2jcjn1Dg==", + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "@babel/compat-data": "^7.25.8", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.23.3", - "@babel/plugin-syntax-import-attributes": "^7.23.3", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-import-assertions": "^7.25.7", + "@babel/plugin-syntax-import-attributes": "^7.25.7", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.23.3", - "@babel/plugin-transform-async-generator-functions": "^7.23.9", - "@babel/plugin-transform-async-to-generator": "^7.23.3", - "@babel/plugin-transform-block-scoped-functions": "^7.23.3", - "@babel/plugin-transform-block-scoping": "^7.23.4", - "@babel/plugin-transform-class-properties": "^7.23.3", - "@babel/plugin-transform-class-static-block": "^7.23.4", - "@babel/plugin-transform-classes": "^7.23.8", - "@babel/plugin-transform-computed-properties": "^7.23.3", - "@babel/plugin-transform-destructuring": "^7.23.3", - "@babel/plugin-transform-dotall-regex": "^7.23.3", - "@babel/plugin-transform-duplicate-keys": "^7.23.3", - "@babel/plugin-transform-dynamic-import": "^7.23.4", - "@babel/plugin-transform-exponentiation-operator": "^7.23.3", - "@babel/plugin-transform-export-namespace-from": "^7.23.4", - "@babel/plugin-transform-for-of": "^7.23.6", - "@babel/plugin-transform-function-name": "^7.23.3", - "@babel/plugin-transform-json-strings": "^7.23.4", - "@babel/plugin-transform-literals": "^7.23.3", - "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", - "@babel/plugin-transform-member-expression-literals": "^7.23.3", - "@babel/plugin-transform-modules-amd": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-modules-systemjs": "^7.23.9", - "@babel/plugin-transform-modules-umd": "^7.23.3", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.23.3", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", - "@babel/plugin-transform-numeric-separator": "^7.23.4", - "@babel/plugin-transform-object-rest-spread": "^7.23.4", - "@babel/plugin-transform-object-super": "^7.23.3", - "@babel/plugin-transform-optional-catch-binding": "^7.23.4", - "@babel/plugin-transform-optional-chaining": "^7.23.4", - "@babel/plugin-transform-parameters": "^7.23.3", - "@babel/plugin-transform-private-methods": "^7.23.3", - "@babel/plugin-transform-private-property-in-object": "^7.23.4", - "@babel/plugin-transform-property-literals": "^7.23.3", - "@babel/plugin-transform-regenerator": "^7.23.3", - "@babel/plugin-transform-reserved-words": "^7.23.3", - "@babel/plugin-transform-shorthand-properties": "^7.23.3", - "@babel/plugin-transform-spread": "^7.23.3", - "@babel/plugin-transform-sticky-regex": "^7.23.3", - "@babel/plugin-transform-template-literals": "^7.23.3", - "@babel/plugin-transform-typeof-symbol": "^7.23.3", - "@babel/plugin-transform-unicode-escapes": "^7.23.3", - "@babel/plugin-transform-unicode-property-regex": "^7.23.3", - "@babel/plugin-transform-unicode-regex": "^7.23.3", - "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/plugin-transform-arrow-functions": "^7.25.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.8", + "@babel/plugin-transform-async-to-generator": "^7.25.7", + "@babel/plugin-transform-block-scoped-functions": "^7.25.7", + "@babel/plugin-transform-block-scoping": "^7.25.7", + "@babel/plugin-transform-class-properties": "^7.25.7", + "@babel/plugin-transform-class-static-block": "^7.25.8", + "@babel/plugin-transform-classes": "^7.25.7", + "@babel/plugin-transform-computed-properties": "^7.25.7", + "@babel/plugin-transform-destructuring": "^7.25.7", + "@babel/plugin-transform-dotall-regex": "^7.25.7", + "@babel/plugin-transform-duplicate-keys": "^7.25.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.7", + "@babel/plugin-transform-dynamic-import": "^7.25.8", + "@babel/plugin-transform-exponentiation-operator": "^7.25.7", + "@babel/plugin-transform-export-namespace-from": "^7.25.8", + "@babel/plugin-transform-for-of": "^7.25.7", + "@babel/plugin-transform-function-name": "^7.25.7", + "@babel/plugin-transform-json-strings": "^7.25.8", + "@babel/plugin-transform-literals": "^7.25.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.8", + "@babel/plugin-transform-member-expression-literals": "^7.25.7", + "@babel/plugin-transform-modules-amd": "^7.25.7", + "@babel/plugin-transform-modules-commonjs": "^7.25.7", + "@babel/plugin-transform-modules-systemjs": "^7.25.7", + "@babel/plugin-transform-modules-umd": "^7.25.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.7", + "@babel/plugin-transform-new-target": "^7.25.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.8", + "@babel/plugin-transform-numeric-separator": "^7.25.8", + "@babel/plugin-transform-object-rest-spread": "^7.25.8", + "@babel/plugin-transform-object-super": "^7.25.7", + "@babel/plugin-transform-optional-catch-binding": "^7.25.8", + "@babel/plugin-transform-optional-chaining": "^7.25.8", + "@babel/plugin-transform-parameters": "^7.25.7", + "@babel/plugin-transform-private-methods": "^7.25.7", + "@babel/plugin-transform-private-property-in-object": "^7.25.8", + "@babel/plugin-transform-property-literals": "^7.25.7", + "@babel/plugin-transform-regenerator": "^7.25.7", + "@babel/plugin-transform-reserved-words": "^7.25.7", + "@babel/plugin-transform-shorthand-properties": "^7.25.7", + "@babel/plugin-transform-spread": "^7.25.7", + "@babel/plugin-transform-sticky-regex": "^7.25.7", + "@babel/plugin-transform-template-literals": "^7.25.7", + "@babel/plugin-transform-typeof-symbol": "^7.25.7", + "@babel/plugin-transform-unicode-escapes": "^7.25.7", + "@babel/plugin-transform-unicode-property-regex": "^7.25.7", + "@babel/plugin-transform-unicode-regex": "^7.25.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.7", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.8", - "babel-plugin-polyfill-corejs3": "^0.9.0", - "babel-plugin-polyfill-regenerator": "^0.5.5", - "core-js-compat": "^3.31.0", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.38.1", "semver": "^6.3.1" }, "engines": { @@ -3662,82 +3496,10 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", - "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs2/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz", - "integrity": "sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.5.0", - "core-js-compat": "^3.34.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", - "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.5.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -3762,7 +3524,6 @@ "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -3776,7 +3537,6 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.23.3.tgz", "integrity": "sha512-tbkHOS9axH6Ysf2OUEqoSZ6T3Fa2SrNH6WTWSPBboxKzdxNc9qOICeLXkNG0ZEwbQ1HY8liwOce4aN/Ceyuq6w==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-validator-option": "^7.22.15", @@ -3793,15 +3553,16 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", - "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.25.7.tgz", + "integrity": "sha512-rkkpaXJZOFN45Fb+Gki0c+KMIglk4+zZXOoMJuyEK8y8Kkc8Jd3BDmP7qPsz0zQMJj+UD7EprF+AqAXcILnexw==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-typescript": "^7.23.3" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "@babel/plugin-syntax-jsx": "^7.25.7", + "@babel/plugin-transform-modules-commonjs": "^7.25.7", + "@babel/plugin-transform-typescript": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3872,7 +3633,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.25.7.tgz", "integrity": "sha512-gMmIEhg35sXk9Te5qbGp3W9YKrvLt3HV658/d3odWrHSqT0JeG5OzsJWFHRLiOohRyjRsJc/x03DhJm3i8VJxg==", - "dev": true, "license": "MIT", "dependencies": { "core-js-pure": "^3.30.2", @@ -3885,8 +3645,7 @@ "node_modules/@babel/runtime-corejs3/node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/@babel/runtime/node_modules/regenerator-runtime": { "version": "0.14.1", @@ -3956,8 +3715,7 @@ "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, "node_modules/@callstack/reassure-cli": { "version": "0.6.1", @@ -4124,7 +3882,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.1.tgz", "integrity": "sha512-lSquqZCHxDfuTg/Sk2hiS0mcSFCEBuj49JfzPHJogDBT0mGCyY5A1AQzBWngitrp7i1/HAZpIgzF/VjhOEIJIg==", - "dev": true, "funding": [ { "type": "github", @@ -4146,7 +3903,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.1.tgz", "integrity": "sha512-UBqaiu7kU0lfvaP982/o3khfXccVlHPWp0/vwwiIgDF0GmqqqxoiXC/6FCjlS9u92f7CoEz6nXKQnrn1kIAkOw==", - "dev": true, "funding": [ { "type": "github", @@ -4165,7 +3921,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-3.0.1.tgz", "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==", - "dev": true, "funding": [ { "type": "github", @@ -4188,7 +3943,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-4.0.0.tgz", "integrity": "sha512-189nelqtPd8++phaHNwYovKZI0FOzH1vQEE3QhHHkNIGrg5fSs9CbYP3RvfEH5geztnIA9Jwq91wyOIwAW5JIQ==", - "dev": true, "funding": [ { "type": "github", @@ -4221,7 +3975,6 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, "engines": { "node": ">=10.0.0" } @@ -4230,7 +3983,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", - "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -4533,7 +4285,6 @@ "version": "0.40.1", "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.40.1.tgz", "integrity": "sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==", - "dev": true, "dependencies": { "comment-parser": "1.4.0", "esquery": "^1.5.0", @@ -4899,7 +4650,6 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -4914,7 +4664,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -4926,7 +4675,6 @@ "version": "4.8.0", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", - "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -4935,7 +4683,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz", "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==", - "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -4955,7 +4702,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -4970,14 +4716,12 @@ "node_modules/@eslint/eslintrc/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/@eslint/eslintrc/node_modules/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, "engines": { "node": ">= 4" } @@ -4986,7 +4730,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -4998,7 +4741,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -5016,7 +4758,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "dev": true, "engines": { "node": ">=14" } @@ -5105,7 +4846,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", - "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.0", "debug": "^4.1.1", @@ -5118,8 +4858,7 @@ "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", @@ -5239,7 +4978,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", - "dev": true, "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -5254,7 +4992,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -5267,7 +5004,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -5279,7 +5015,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -5294,7 +5029,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -5306,7 +5040,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "engines": { "node": ">=6" } @@ -5315,7 +5048,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -5324,7 +5056,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, "engines": { "node": ">=8" } @@ -5333,7 +5064,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, "engines": { "node": ">=8" } @@ -5342,7 +5072,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz", "integrity": "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==", - "dev": true, "dependencies": { "@jest/types": "^29.6.1", "@types/node": "*", @@ -5359,7 +5088,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz", "integrity": "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==", - "dev": true, "dependencies": { "@jest/console": "^29.6.2", "@jest/reporters": "^29.6.2", @@ -5431,7 +5159,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz", "integrity": "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==", - "dev": true, "dependencies": { "expect": "^29.6.2", "jest-snapshot": "^29.6.2" @@ -5444,7 +5171,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz", "integrity": "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==", - "dev": true, "dependencies": { "jest-get-type": "^29.4.3" }, @@ -5491,7 +5217,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz", "integrity": "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==", - "dev": true, "dependencies": { "@jest/environment": "^29.6.2", "@jest/expect": "^29.6.2", @@ -5506,7 +5231,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz", "integrity": "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==", - "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.6.2", @@ -5549,7 +5273,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5580,7 +5303,6 @@ "version": "29.6.0", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", @@ -5594,7 +5316,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz", "integrity": "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==", - "dev": true, "dependencies": { "@jest/console": "^29.6.2", "@jest/types": "^29.6.1", @@ -5609,7 +5330,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz", "integrity": "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==", - "dev": true, "dependencies": { "@jest/test-result": "^29.6.2", "graceful-fs": "^4.2.9", @@ -5624,7 +5344,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -5649,14 +5368,12 @@ "node_modules/@jest/transform/node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/@jest/transform/node_modules/write-file-atomic": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" @@ -5749,7 +5466,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "dev": true, "dependencies": { "debug": "^4.1.1" } @@ -5757,14 +5473,12 @@ "node_modules/@kwsites/promise-deferred": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", - "dev": true + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, "node_modules/@lerna/child-process": { "version": "7.1.4", @@ -6119,7 +5833,6 @@ "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "dev": true, "license": "MIT", "dependencies": { "eslint-scope": "5.1.1" @@ -6129,7 +5842,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", @@ -6143,7 +5855,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.2.tgz", "integrity": "sha512-wrIBsjA5pl13f0RN4Zx4FNWmU71lv03meGKnqRUoCyan17s4V3WL92f3w3AIuWbNnpcrQyFBU5qMavJoB8d27w==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.2", "run-parallel": "^1.1.9" @@ -6156,7 +5867,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.2.tgz", "integrity": "sha512-z8+wGWV2dgUhLqrtRYa03yDx4HWMvXKi1z8g3m2JyxAx8F7xk74asqPk5LAETjqDSGLFML/6CDl0+yFunSYicw==", - "dev": true, "engines": { "node": ">= 8" } @@ -6165,7 +5875,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.3.tgz", "integrity": "sha512-l6t8xEhfK9Sa4YO5mIRdau7XSOADfmh3jCr0evNHdY+HNkW6xuQhgMH7D73VV6WpZOagrW0UludvMTiifiwTfA==", - "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.2", "fastq": "^1.6.0" @@ -6578,7 +6287,6 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "dev": true, "dependencies": { "@octokit/types": "^6.0.3" } @@ -6587,7 +6295,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "dev": true, "dependencies": { "@octokit/auth-token": "^2.4.4", "@octokit/graphql": "^4.5.8", @@ -6602,7 +6309,6 @@ "version": "6.0.12", "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dev": true, "dependencies": { "@octokit/types": "^6.0.3", "is-plain-object": "^5.0.0", @@ -6613,7 +6319,6 @@ "version": "5.6.3", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dev": true, "dependencies": { "@octokit/endpoint": "^6.0.1", "@octokit/request-error": "^2.1.0", @@ -6626,14 +6331,12 @@ "node_modules/@octokit/core/node_modules/before-after-hook": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" }, "node_modules/@octokit/core/node_modules/universal-user-agent": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", - "dev": true + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" }, "node_modules/@octokit/endpoint": { "version": "5.5.3", @@ -6677,7 +6380,6 @@ "version": "4.8.0", "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "dev": true, "dependencies": { "@octokit/request": "^5.6.0", "@octokit/types": "^6.0.3", @@ -6688,7 +6390,6 @@ "version": "6.0.12", "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dev": true, "dependencies": { "@octokit/types": "^6.0.3", "is-plain-object": "^5.0.0", @@ -6699,7 +6400,6 @@ "version": "5.6.3", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dev": true, "dependencies": { "@octokit/endpoint": "^6.0.1", "@octokit/request-error": "^2.1.0", @@ -6712,14 +6412,12 @@ "node_modules/@octokit/graphql/node_modules/universal-user-agent": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", - "dev": true + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" }, "node_modules/@octokit/openapi-types": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", - "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==", - "dev": true + "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==" }, "node_modules/@octokit/plugin-enterprise-rest": { "version": "6.0.1", @@ -6731,7 +6429,6 @@ "version": "2.21.3", "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", - "dev": true, "dependencies": { "@octokit/types": "^6.40.0" }, @@ -6742,14 +6439,12 @@ "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { "version": "12.11.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", - "dev": true + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" }, "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { "version": "6.41.0", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dev": true, "dependencies": { "@octokit/openapi-types": "^12.11.0" } @@ -6767,7 +6462,6 @@ "version": "5.16.2", "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", - "dev": true, "dependencies": { "@octokit/types": "^6.39.0", "deprecation": "^2.3.1" @@ -6779,14 +6473,12 @@ "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { "version": "12.11.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", - "dev": true + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" }, "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { "version": "6.41.0", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dev": true, "dependencies": { "@octokit/openapi-types": "^12.11.0" } @@ -6810,7 +6502,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "dev": true, "dependencies": { "@octokit/types": "^6.0.3", "deprecation": "^2.0.0", @@ -6897,7 +6588,6 @@ "version": "6.34.0", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", - "dev": true, "dependencies": { "@octokit/openapi-types": "^11.2.0" } @@ -6906,14 +6596,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-2.0.0.tgz", "integrity": "sha512-35cfQ4YWlnZnmZKmIxlGPUPLtbkF8lr/A/1Sk1eC0ddLMwQN06dOuLc+dI3YLQS+T+MoNt3DIQ0NynwgKPilig==", - "dev": true, "license": "MIT" }, "node_modules/@octokit/webhooks-types": { "version": "5.8.0", "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-5.8.0.tgz", "integrity": "sha512-8adktjIb76A7viIdayQSFuBEwOzwhDC+9yxZpKNHjfzrlostHCw0/N7JWpWMObfElwvJMk2fY2l1noENCk9wmw==", - "dev": true, "license": "MIT" }, "node_modules/@parcel/watcher": { @@ -6948,7 +6636,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "fast-glob": "^3.3.0", @@ -6968,7 +6655,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -6982,7 +6668,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, "engines": { "node": ">=12" }, @@ -6994,7 +6679,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -7010,7 +6694,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -7022,7 +6705,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -7034,7 +6716,6 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", - "dev": true, "dependencies": { "default-browser": "^4.0.0", "define-lazy-prop": "^3.0.0", @@ -7052,7 +6733,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -7061,7 +6741,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -7073,7 +6752,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -7082,7 +6760,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -7112,7 +6789,6 @@ "version": "0.5.11", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.11.tgz", "integrity": "sha512-7j/6vdTym0+qZ6u4XbSAxrWBGYSdCfTzySkj7WAFgDLmSyWlOrWvpyzxlFh5jtw9dn0oL/jtW+06XfFiisN3JQ==", - "dev": true, "dependencies": { "ansi-html-community": "^0.0.8", "common-path-prefix": "^3.0.0", @@ -7162,7 +6838,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -7178,7 +6853,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -7194,7 +6868,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -7209,7 +6882,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -7224,7 +6896,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -7233,7 +6904,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -7251,7 +6921,6 @@ "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, "engines": { "node": ">= 8" } @@ -7259,8 +6928,7 @@ "node_modules/@polka/url": { "version": "1.0.0-next.23", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", - "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==", - "dev": true + "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==" }, "node_modules/@preact/signals": { "version": "1.3.0", @@ -7292,7 +6960,6 @@ "version": "1.4.6", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.4.6.tgz", "integrity": "sha512-x4BEjr2SjOPowNeiguzjozQbsc6h437ovD/wu+JpaenxVLm3jkgzHY2xOslMTp50HoTvQreMjiexiGQw1sqZlQ==", - "dev": true, "dependencies": { "debug": "4.3.4", "extract-zip": "2.0.1", @@ -7321,7 +6988,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -7334,14 +7000,12 @@ "node_modules/@puppeteer/browsers/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/@puppeteer/browsers/node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -7361,7 +7025,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -7370,7 +7033,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -7381,7 +7043,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -7395,7 +7056,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", - "dev": true, "dependencies": { "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", @@ -7406,7 +7066,6 @@ "version": "3.1.7", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", @@ -7417,7 +7076,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -7434,7 +7092,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "engines": { "node": ">=10" } @@ -7443,7 +7100,6 @@ "version": "17.7.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", - "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -7461,7 +7117,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "engines": { "node": ">=12" } @@ -8749,9 +8404,9 @@ } }, "node_modules/@react-native-community/cli-doctor/node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -10561,7 +10216,6 @@ "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.19.7.tgz", "integrity": "sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw==", - "dev": true, "dependencies": { "@sentry/hub": "6.19.7", "@sentry/minimal": "6.19.7", @@ -10576,14 +10230,12 @@ "node_modules/@sentry/core/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/hub": { "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz", "integrity": "sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA==", - "dev": true, "dependencies": { "@sentry/types": "6.19.7", "@sentry/utils": "6.19.7", @@ -10596,14 +10248,12 @@ "node_modules/@sentry/hub/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/minimal": { "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.7.tgz", "integrity": "sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ==", - "dev": true, "dependencies": { "@sentry/hub": "6.19.7", "@sentry/types": "6.19.7", @@ -10616,14 +10266,12 @@ "node_modules/@sentry/minimal/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/node": { "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.19.7.tgz", "integrity": "sha512-gtmRC4dAXKODMpHXKfrkfvyBL3cI8y64vEi3fDD046uqYcrWdgoQsffuBbxMAizc6Ez1ia+f0Flue6p15Qaltg==", - "dev": true, "dependencies": { "@sentry/core": "6.19.7", "@sentry/hub": "6.19.7", @@ -10642,7 +10290,6 @@ "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -10650,14 +10297,12 @@ "node_modules/@sentry/node/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/types": { "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz", "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==", - "dev": true, "engines": { "node": ">=6" } @@ -10666,7 +10311,6 @@ "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz", "integrity": "sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==", - "dev": true, "dependencies": { "@sentry/types": "6.19.7", "tslib": "^1.9.3" @@ -10678,8 +10322,7 @@ "node_modules/@sentry/utils/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sideway/address": { "version": "4.1.5", @@ -10758,7 +10401,6 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, "engines": { "node": ">=10" }, @@ -13531,7 +13173,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-3.0.1.tgz", "integrity": "sha512-j3mH8HSw2Rob/KJFWZ627w3CQ8gQqVHtzCdPeEffUg5vOgpz4rgrR+Xw2kU0OQCDcdW8Y1nKfdXKKjM5Rn8X0g==", - "dev": true, "dependencies": { "@csstools/css-parser-algorithms": "^3.0.0", "@csstools/css-tokenizer": "^3.0.0", @@ -13552,14 +13193,12 @@ "node_modules/@stylistic/stylelint-plugin/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", - "dev": true, "engines": { "node": ">=14" }, @@ -13575,7 +13214,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", - "dev": true, "engines": { "node": ">=14" }, @@ -13591,7 +13229,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", - "dev": true, "engines": { "node": ">=14" }, @@ -13607,7 +13244,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", - "dev": true, "engines": { "node": ">=14" }, @@ -13623,7 +13259,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", - "dev": true, "engines": { "node": ">=14" }, @@ -13639,7 +13274,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", - "dev": true, "engines": { "node": ">=14" }, @@ -13655,7 +13289,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.0.0.tgz", "integrity": "sha512-UKrY3860AQICgH7g+6h2zkoxeVEPLYwX/uAjmqo4PIq2FIHppwhIqZstIyTz0ZtlwreKR41O3W3BzsBBiJV2Aw==", - "dev": true, "engines": { "node": ">=14" }, @@ -13671,7 +13304,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", - "dev": true, "engines": { "node": ">=12" }, @@ -13687,7 +13319,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.0.0.tgz", "integrity": "sha512-KLcjiZychInVrhs86OvcYPLTFu9L5XV2vj0XAaE1HwE3J3jLmIzRY8ttdeAg/iFyp8nhavJpafpDZTt+1LIpkQ==", - "dev": true, "dependencies": { "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", @@ -13713,7 +13344,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.0.0.tgz", "integrity": "sha512-aJKtc+Pie/rFYsVH/unSkDaZGvEeylNv/s2cP+ta9/rYWxRVvoV/S4Qw65Kmrtah4CBK5PM6ISH9qUH7IJQCng==", - "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.0.0", @@ -13732,14 +13362,12 @@ "node_modules/@svgr/core/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/@svgr/core/node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, "engines": { "node": ">=10" }, @@ -13751,7 +13379,6 @@ "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -13777,7 +13404,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -13789,7 +13415,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -13798,7 +13423,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", - "dev": true, "dependencies": { "@babel/types": "^7.21.3", "entities": "^4.4.0" @@ -13815,7 +13439,6 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, "engines": { "node": ">=0.12" }, @@ -13827,7 +13450,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.0.1.tgz", "integrity": "sha512-bfCFb+4ZsM3UuKP2t7KmDwn6YV8qVn9HIQJmau6xeQb/iV65Rpi7NBNBWA2hcCd4GKoCqG8hpaaDk5FDR0eH+g==", - "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.0.0", @@ -13849,7 +13471,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.0.1.tgz", "integrity": "sha512-29OJ1QmJgnohQHDAgAuY2h21xWD6TZiXji+hnx+W635RiXTAlHTbjrZDktfqzkN0bOeQEtNe+xgq73/XeWFfSg==", - "dev": true, "dependencies": { "cosmiconfig": "^8.1.3", "deepmerge": "^4.3.1", @@ -13869,14 +13490,12 @@ "node_modules/@svgr/plugin-svgo/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/@svgr/plugin-svgo/node_modules/cosmiconfig": { "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -13902,7 +13521,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -13914,7 +13532,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -13923,7 +13540,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.0.1.tgz", "integrity": "sha512-zSoeKcbCmfMXjA11uDuCJb+1LWNb3vy6Qw/VHj0Nfcl3UuqwuoZWknHsBIhCWvi4wU9vPui3aq054qjVyZqY4A==", - "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@babel/plugin-transform-react-constant-elements": "^7.21.3", @@ -14156,7 +13772,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, "dependencies": { "defer-to-connect": "^2.0.0" }, @@ -14408,14 +14023,12 @@ "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -14504,7 +14117,6 @@ "version": "7.20.0", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", - "dev": true, "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -14517,7 +14129,6 @@ "version": "7.6.4", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, "dependencies": { "@babel/types": "^7.0.0" } @@ -14526,7 +14137,6 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -14536,7 +14146,6 @@ "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", - "dev": true, "dependencies": { "@babel/types": "^7.20.7" } @@ -14560,7 +14169,6 @@ "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -14570,7 +14178,6 @@ "version": "3.5.11", "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.11.tgz", "integrity": "sha512-isGhjmBtLIxdHBDl2xGwUzEM8AOyOvWsADWq7rqirdi/ZQoHnLWErHvsThcEzTX8juDRiZtzp2Qkv5bgNh6mAg==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -14579,7 +14186,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "^3.1.4", @@ -14591,7 +14197,6 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -14600,7 +14205,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.1.tgz", "integrity": "sha512-iaQslNbARe8fctL5Lk+DsmgWOM83lM+7FzP0eQUJs1jd3kBE8NWqBTIT2S8SqQOJjxvt2eyIjpOuYeRXq2AdMw==", - "dev": true, "dependencies": { "@types/express-serve-static-core": "*", "@types/node": "*" @@ -14658,20 +14262,17 @@ "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, "node_modules/@types/events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", - "dev": true + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" }, "node_modules/@types/express": { "version": "4.17.17", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", - "dev": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -14683,7 +14284,6 @@ "version": "4.17.35", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", - "dev": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -14713,7 +14313,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", - "dev": true, "dependencies": { "@types/events": "*", "@types/minimatch": "*", @@ -14724,7 +14323,6 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.3.tgz", "integrity": "sha512-AiHRaEB50LQg0pZmm659vNBb9f4SJ0qrAnteuzhSeAUcJKxoYgEnprg/83kppCnc2zvtCKbdZry1a5pVY3lOTQ==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -14748,20 +14346,17 @@ "node_modules/@types/http-cache-semantics": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.2.tgz", - "integrity": "sha512-FD+nQWA2zJjh4L9+pFXqWOi0Hs1ryBCfI+985NjluQ1p8EYtoLvjLOKidXBtZ4/IcxDX4o8/E8qDS3540tNliw==", - "dev": true + "integrity": "sha512-FD+nQWA2zJjh4L9+pFXqWOi0Hs1ryBCfI+985NjluQ1p8EYtoLvjLOKidXBtZ4/IcxDX4o8/E8qDS3540tNliw==" }, "node_modules/@types/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==", - "dev": true + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" }, "node_modules/@types/http-proxy": { "version": "1.17.12", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.12.tgz", "integrity": "sha512-kQtujO08dVtQ2wXAuSFfk9ASy3sug4+ogFR8Kd8UgP8PEuc1/G/8yjYRmp//PcDNJEUKOza/MrQu15bouEUCiw==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -14801,7 +14396,6 @@ "version": "20.0.1", "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", - "dev": true, "dependencies": { "@types/node": "*", "@types/tough-cookie": "*", @@ -14820,20 +14414,17 @@ "node_modules/@types/json-schema": { "version": "7.0.12", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==" }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, "node_modules/@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -14877,8 +14468,7 @@ "node_modules/@types/mime": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", - "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==", - "dev": true + "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==" }, "node_modules/@types/mime-types": { "version": "2.1.4", @@ -14889,14 +14479,12 @@ "node_modules/@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, "node_modules/@types/minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=", - "dev": true + "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=" }, "node_modules/@types/mousetrap": { "version": "1.6.8", @@ -14919,9 +14507,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.54", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.54.tgz", - "integrity": "sha512-+BRgt0G5gYjTvdLac9sIeE0iZcJxi4Jc4PV5EUzqi+88jmQLr+fRZdv2tCTV7IHKSGxM6SaLoOXQWWUiLUItMw==", + "version": "18.19.56", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.56.tgz", + "integrity": "sha512-4EMJlWwwGnVPflJAtM14p9eVSa6BOv5b92mCsh5zcM1UagNtEtrbbtaE6WE1tw2TabavatnwqXjlIpcAEuJJNg==", "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -14940,8 +14528,7 @@ "node_modules/@types/normalize-package-data": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz", - "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==", - "dev": true + "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==" }, "node_modules/@types/npm-package-arg": { "version": "6.1.1", @@ -14991,14 +14578,12 @@ "node_modules/@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" }, "node_modules/@types/range-parser": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, "node_modules/@types/react": { "version": "18.3.1", @@ -15062,7 +14647,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -15070,8 +14654,7 @@ "node_modules/@types/retry": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", - "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", - "dev": true + "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==" }, "node_modules/@types/scheduler": { "version": "0.16.2", @@ -15088,7 +14671,6 @@ "version": "0.17.1", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", - "dev": true, "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -15097,8 +14679,7 @@ "node_modules/@types/send/node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" }, "node_modules/@types/serve-favicon": { "version": "2.5.5", @@ -15113,7 +14694,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", - "dev": true, "dependencies": { "@types/express": "*" } @@ -15122,7 +14702,6 @@ "version": "1.15.2", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", - "dev": true, "dependencies": { "@types/http-errors": "*", "@types/mime": "*", @@ -15147,7 +14726,6 @@ "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -15155,8 +14733,7 @@ "node_modules/@types/source-list-map": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==" }, "node_modules/@types/sprintf-js": { "version": "1.1.2", @@ -15178,8 +14755,7 @@ "node_modules/@types/tapable": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.5.tgz", - "integrity": "sha512-/gG2M/Imw7cQFp8PGvz/SwocNrmKFjFsm5Pb8HdbHkZ1K8pmuPzOX4VeVoiEecFCVf4CsN1r3/BRvx+6sNqwtQ==", - "dev": true + "integrity": "sha512-/gG2M/Imw7cQFp8PGvz/SwocNrmKFjFsm5Pb8HdbHkZ1K8pmuPzOX4VeVoiEecFCVf4CsN1r3/BRvx+6sNqwtQ==" }, "node_modules/@types/teen_process": { "version": "2.0.0", @@ -15202,8 +14778,7 @@ "node_modules/@types/tough-cookie": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", - "dev": true + "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==" }, "node_modules/@types/triple-beam": { "version": "1.3.3", @@ -15215,7 +14790,6 @@ "version": "3.9.2", "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.9.2.tgz", "integrity": "sha512-d6dIfpPbF+8B7WiCi2ELY7m0w1joD8cRW4ms88Emdb2w062NeEpbNCeWwVCgzLRpVG+5e74VFSg4rgJ2xXjEiQ==", - "dev": true, "dependencies": { "source-map": "^0.6.1" } @@ -15223,8 +14797,7 @@ "node_modules/@types/unist": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", - "dev": true + "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==" }, "node_modules/@types/uuid": { "version": "8.3.1", @@ -15236,7 +14809,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz", "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==", - "dev": true, "dependencies": { "@types/node": "*", "@types/unist": "*", @@ -15247,7 +14819,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-1.0.1.tgz", "integrity": "sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA==", - "dev": true, "dependencies": { "@types/node": "*", "@types/unist": "*" @@ -15257,7 +14828,6 @@ "version": "4.41.33", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.33.tgz", "integrity": "sha512-PPajH64Ft2vWevkerISMtnZ8rTs4YmRbs+23c402J0INmxDKCrhZNvwZYtzx96gY2wAtXdrK1BS2fiC8MlLr3g==", - "dev": true, "dependencies": { "@types/node": "*", "@types/tapable": "^1", @@ -15271,7 +14841,6 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.7.tgz", "integrity": "sha512-XyaHrJILjK1VHVC4aVlKsdNN5KBTwufMb43cQs+flGxtPAf/1Qwl8+Q0tp5BwEGaI8D6XT1L+9bSWXckgkjTLw==", - "dev": true, "dependencies": { "@types/node": "*", "@types/source-list-map": "*", @@ -15294,7 +14863,6 @@ "version": "8.5.5", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -15317,7 +14885,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "dev": true, "optional": true, "dependencies": { "@types/node": "*" @@ -15327,7 +14894,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.1.tgz", "integrity": "sha512-3F5PtBzUW0dYlq77Lcqo13fv+58KDwUib3BddilE8ajPJT+faGgxmI9Sw+I8ZS22BYwoir9ZhNXcLi+S+I2bkw==", - "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", "@typescript-eslint/scope-manager": "6.4.1", @@ -15361,14 +14927,12 @@ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1" @@ -15385,7 +14949,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", - "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -15398,7 +14961,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1", @@ -15425,7 +14987,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", - "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", @@ -15450,7 +15011,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" @@ -15467,7 +15027,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15479,7 +15038,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.4.1.tgz", "integrity": "sha512-610G6KHymg9V7EqOaNBMtD1GgpAmGROsmfHJPXNLCU9bfIuLrkdOygltK784F6Crboyd5tBFayPB7Sf0McrQwg==", - "dev": true, "dependencies": { "@typescript-eslint/scope-manager": "6.4.1", "@typescript-eslint/types": "6.4.1", @@ -15507,7 +15065,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1" @@ -15524,7 +15081,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", - "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -15537,7 +15093,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1", @@ -15564,7 +15119,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" @@ -15581,7 +15135,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15593,7 +15146,6 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0" @@ -15610,7 +15162,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.4.1.tgz", "integrity": "sha512-7ON8M8NXh73SGZ5XvIqWHjgX2f+vvaOarNliGhjrJnv1vdjG0LVIz+ToYfPirOoBi56jxAKLfsLm40+RvxVVXA==", - "dev": true, "dependencies": { "@typescript-eslint/typescript-estree": "6.4.1", "@typescript-eslint/utils": "6.4.1", @@ -15636,14 +15187,12 @@ "node_modules/@typescript-eslint/type-utils/node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1" @@ -15660,7 +15209,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", - "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -15673,7 +15221,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1", @@ -15700,7 +15247,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", - "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", @@ -15725,7 +15271,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" @@ -15742,7 +15287,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15754,7 +15298,6 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15767,7 +15310,6 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0", @@ -15794,7 +15336,6 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", @@ -15819,14 +15360,12 @@ "node_modules/@typescript-eslint/utils/node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" }, "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -15839,7 +15378,6 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" @@ -15856,7 +15394,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -16271,9 +15808,9 @@ } }, "node_modules/@wdio/repl/node_modules/@types/node": { - "version": "20.16.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", - "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", + "version": "20.16.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.12.tgz", + "integrity": "sha512-LfPFB0zOeCeCNQV3i+67rcoVvoN5n0NVuR2vLG0O5ySQMgchuZlC4lgz546ZOJyDtj5KIgOxy+lacOimfqZAIA==", "dev": true, "license": "MIT", "dependencies": { @@ -16300,9 +15837,9 @@ } }, "node_modules/@wdio/types/node_modules/@types/node": { - "version": "20.16.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", - "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", + "version": "20.16.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.12.tgz", + "integrity": "sha512-LfPFB0zOeCeCNQV3i+67rcoVvoN5n0NVuR2vLG0O5ySQMgchuZlC4lgz546ZOJyDtj5KIgOxy+lacOimfqZAIA==", "dev": true, "license": "MIT", "dependencies": { @@ -16868,7 +16405,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -16878,14 +16414,12 @@ "node_modules/@webassemblyjs/helper-numbers/node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, "node_modules/@webassemblyjs/helper-numbers/node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.9.0", @@ -17013,7 +16547,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true, "engines": { "node": ">=14.15.0" }, @@ -17026,7 +16559,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true, "engines": { "node": ">=14.15.0" }, @@ -17039,7 +16571,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true, "engines": { "node": ">=14.15.0" }, @@ -17141,6 +16672,10 @@ "resolved": "packages/create-block", "link": true }, + "node_modules/@wordpress/create-block-interactive-template": { + "resolved": "packages/create-block-interactive-template", + "link": true + }, "node_modules/@wordpress/create-block-tutorial-template": { "resolved": "packages/create-block-tutorial-template", "link": true @@ -17461,14 +16996,12 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "node_modules/@yarnpkg/esbuild-plugin-pnp": { "version": "3.0.0-rc.15", @@ -17563,8 +17096,7 @@ "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" }, "node_modules/abbrev": { "version": "1.1.1", @@ -17611,7 +17143,6 @@ "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "dev": true, "peerDependencies": { "acorn": "^8" } @@ -17620,7 +17151,6 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -17653,7 +17183,6 @@ "version": "0.5.9", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz", "integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==", - "dev": true, "engines": { "node": ">=6.0" } @@ -17662,7 +17191,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, "dependencies": { "debug": "4" }, @@ -17686,7 +17214,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", @@ -17700,7 +17227,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -17710,7 +17236,6 @@ "version": "8.7.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.7.1.tgz", "integrity": "sha512-gPpOObTO1QjbnN1sVMjJcp1TF9nggMfO4MBR5uQl6ZVTOaEPq5i4oq/6R9q2alMMPB3eg53wFv1RuJBLuxf3Hw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -17726,7 +17251,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true, "peerDependencies": { "ajv": ">=5.0.0" } @@ -17735,7 +17259,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, "dependencies": { "ajv": "^8.0.0" }, @@ -17752,7 +17275,6 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -17760,8 +17282,7 @@ "node_modules/ajv/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/anser": { "version": "1.4.10", @@ -17772,7 +17293,6 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, "engines": { "node": ">=6" } @@ -17781,7 +17301,6 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, "dependencies": { "type-fest": "^0.21.3" }, @@ -17796,7 +17315,6 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, "engines": { "node": ">=10" }, @@ -17861,7 +17379,6 @@ "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, "engines": [ "node >= 0.8.0" ], @@ -18588,7 +18105,6 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", - "dev": true, "engines": { "node": ">=14" } @@ -18654,7 +18170,6 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", - "dev": true, "dependencies": { "@babel/runtime": "^7.10.2", "@babel/runtime-corejs3": "^7.10.2" @@ -18685,7 +18200,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -18694,7 +18208,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "is-array-buffer": "^3.0.1" @@ -18715,8 +18228,7 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/array-ify": { "version": "1.0.0", @@ -18728,7 +18240,6 @@ "version": "3.1.6", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -18746,14 +18257,12 @@ "node_modules/array-iterate": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.2.tgz", - "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==", - "dev": true + "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==" }, "node_modules/array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", - "dev": true, "dependencies": { "array-uniq": "^1.0.1" }, @@ -18765,7 +18274,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -18783,7 +18291,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -18801,7 +18308,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -18819,7 +18325,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", - "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.2", @@ -18839,7 +18344,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -18910,8 +18414,7 @@ "node_modules/ast-types-flow": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", - "dev": true + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" }, "node_modules/astral-regex": { "version": "1.0.0", @@ -18970,8 +18473,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/at-least-node": { "version": "1.0.0", @@ -19003,7 +18505,6 @@ "version": "10.4.14", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -19035,8 +18536,7 @@ "node_modules/autoprefixer/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/autosize": { "version": "4.0.2", @@ -19047,7 +18547,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -19059,7 +18558,6 @@ "version": "4.7.2", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==", - "dev": true, "engines": { "node": ">=4" } @@ -19078,14 +18576,12 @@ "node_modules/axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", - "dev": true + "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==" }, "node_modules/b4a": { "version": "1.6.4", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", - "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==", - "dev": true + "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==" }, "node_modules/babel-core": { "version": "7.0.0-bridge.0", @@ -19099,7 +18595,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, "dependencies": { "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", @@ -19321,7 +18816,6 @@ "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -19337,7 +18831,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -19363,47 +18856,51 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.3.tgz", - "integrity": "sha512-NDZ0auNRzmAfE1oDDPW2JhzIMXUk+FFe2ICejmt5T4ocKgiQx3e0VCRx9NCAidcMtL2RUZaWtXnmjTCkx0tcbA==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.2.4", - "semver": "^6.1.1" + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.3.0.tgz", - "integrity": "sha512-JLwi9vloVdXLjzACL80j24bG6/T1gYxwowG44dg6HN/7aTPdyPbJJidf6ajoA3RPHHtW0j9KMrSOLpIZpAnPpg==", + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.2.4", - "core-js-compat": "^3.18.0" + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.3.tgz", - "integrity": "sha512-JVE78oRZPKFIeUqFGrSORNzQnrDwZR16oiWeGM8ZyjBn2XAT5OjP+wXx5ESuo33nUsFUEJYjtklnsKbxW5L+7g==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.2.4" + "@babel/helper-define-polyfill-provider": "^0.6.2" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-react-native-classname-to-style": { @@ -19445,7 +18942,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", @@ -19506,7 +19002,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" @@ -19522,7 +19017,6 @@ "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz", "integrity": "sha512-zeCYxDePWYAT/DfmQWIHsMSFW2vv45UIwIAMjGvQVsTd47RwsiRH0uK1yzyWZ7LDBKdhnGDPM6NYEO5CZyhPrg==", - "dev": true, "dependencies": { "core-js": "^2.4.0", "regenerator-runtime": "^0.10.0" @@ -19533,20 +19027,17 @@ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "dev": true, "hasInstallScript": true }, "node_modules/babel-runtime/node_modules/regenerator-runtime": { "version": "0.10.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==", - "dev": true + "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==" }, "node_modules/bail": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", - "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", - "dev": true + "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==" }, "node_modules/balanced-match": { "version": "1.0.2", @@ -19557,14 +19048,12 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.2.1.tgz", "integrity": "sha512-9GYPpsPFvrWBkelIhOhTWtkeZxVxZOdb3VnFTCzlOo3OjvmTvzLoZFUT8kNFACx0vJej6QPney1Cf9BvzCNE/A==", - "dev": true, "optional": true }, "node_modules/bare-fs": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.2.2.tgz", "integrity": "sha512-X9IqgvyB0/VA5OZJyb5ZstoN62AzD7YxVGog13kkfYWYqJYcK0kcqLZ6TrmH5qr4/8//ejVcX4x/a0UvaogXmA==", - "dev": true, "optional": true, "dependencies": { "bare-events": "^2.0.0", @@ -19577,14 +19066,12 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.2.1.tgz", "integrity": "sha512-OwPyHgBBMkhC29Hl3O4/YfxW9n7mdTr2+SsO29XBWKKJsbgj3mnorDB80r5TiCQgQstgE5ga1qNYrpes6NvX2w==", - "dev": true, "optional": true }, "node_modules/bare-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.0.tgz", "integrity": "sha512-DIIg7ts8bdRKwJRJrUMy/PICEaQZaPGZ26lsSx9MJSwIhSrcdHn7/C8W+XmnG/rKi6BaRcz+JO00CjZteybDtw==", - "dev": true, "optional": true, "dependencies": { "bare-os": "^2.1.0" @@ -19674,7 +19161,6 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.3.tgz", "integrity": "sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==", - "dev": true, "engines": { "node": ">=10.0.0" } @@ -19682,8 +19168,7 @@ "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, "node_modules/before-after-hook": { "version": "1.4.0", @@ -19746,7 +19231,6 @@ "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true, "engines": { "node": ">=0.6" } @@ -19755,7 +19239,6 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, "engines": { "node": "*" } @@ -19777,7 +19260,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, "engines": { "node": ">=8" }, @@ -19862,7 +19344,6 @@ "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dev": true, "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.4", @@ -19886,7 +19367,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -19895,7 +19375,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "dependencies": { "ms": "2.0.0" } @@ -19904,7 +19383,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -19913,7 +19391,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -19925,7 +19402,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, "dependencies": { "ee-first": "1.1.1" }, @@ -19937,7 +19413,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", - "dev": true, "dependencies": { "array-flatten": "^2.1.2", "dns-equal": "^1.0.0", @@ -19948,8 +19423,7 @@ "node_modules/bonjour-service/node_modules/array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" }, "node_modules/boolbase": { "version": "1.0.0", @@ -19969,7 +19443,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, "dependencies": { "big-integer": "^1.6.44" }, @@ -20186,7 +19659,6 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, "engines": { "node": "*" } @@ -20224,7 +19696,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, "engines": { "node": ">=6" }, @@ -20241,14 +19712,12 @@ "node_modules/builtins": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", - "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==", - "dev": true + "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==" }, "node_modules/bundle-name": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dev": true, "dependencies": { "run-applescript": "^5.0.0" }, @@ -20382,7 +19851,6 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, "engines": { "node": ">=10.6.0" } @@ -20391,7 +19859,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dev": true, "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", @@ -20409,7 +19876,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -20492,7 +19958,6 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, "dependencies": { "camelcase": "^5.3.1", "map-obj": "^4.0.0", @@ -20509,7 +19974,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, "engines": { "node": ">=8" }, @@ -20526,7 +19990,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, "dependencies": { "browserslist": "^4.0.0", "caniuse-lite": "^1.0.0", @@ -20575,8 +20038,7 @@ "node_modules/ccount": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz", - "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", - "dev": true + "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==" }, "node_modules/chainsaw": { "version": "0.1.0", @@ -20656,7 +20118,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, "engines": { "node": ">=10" } @@ -20664,38 +20125,32 @@ "node_modules/character-entities": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", - "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==", - "dev": true + "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==" }, "node_modules/character-entities-html4": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz", - "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==", - "dev": true + "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==" }, "node_modules/character-entities-legacy": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", - "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==", - "dev": true + "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==" }, "node_modules/character-reference-invalid": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", - "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", - "dev": true + "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==" }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, "node_modules/check-node-version": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/check-node-version/-/check-node-version-4.1.0.tgz", "integrity": "sha512-TSXGsyfW5/xY2QseuJn8/hleO2AU7HxVCdkc900jp1vcfzF840GkjvRT7CHl8sRtWn23n3X3k0cwH9RXeRwhfw==", - "dev": true, "dependencies": { "chalk": "^3.0.0", "map-values": "^1.0.1", @@ -20715,7 +20170,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -20728,7 +20182,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -20737,7 +20190,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -20746,7 +20198,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -20758,7 +20209,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -20782,7 +20232,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -20839,7 +20288,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, "engines": { "node": ">=6.0" } @@ -20848,7 +20296,6 @@ "version": "0.4.16", "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.16.tgz", "integrity": "sha512-7ZbXdWERxRxSwo3txsBjjmc/NLxqb1Bk30mRb0BMS4YIaiV6zvKZqL/UAH+DdqcDYayDWk2n/y8klkBDODrPvA==", - "dev": true, "dependencies": { "mitt": "3.0.0" }, @@ -20947,8 +20394,7 @@ "node_modules/cjs-module-lexer": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" }, "node_modules/class-utils": { "version": "0.3.6", @@ -20993,7 +20439,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, "engines": { "node": ">=6" } @@ -21002,7 +20447,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", - "dev": true, "dependencies": { "@types/webpack": "^4.4.31", "del": "^4.1.1" @@ -21144,8 +20588,7 @@ "node_modules/cli-width": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", - "dev": true + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==" }, "node_modules/client-zip": { "version": "2.4.5", @@ -21224,7 +20667,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, "dependencies": { "mimic-response": "^1.0.0" }, @@ -21253,7 +20695,6 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" @@ -21271,14 +20712,12 @@ "node_modules/collapse-white-space": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz", - "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", - "dev": true + "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==" }, "node_modules/collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==" }, "node_modules/collection-visit": { "version": "1.0.0", @@ -21399,7 +20838,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -21416,7 +20854,6 @@ "version": "9.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz", "integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==", - "dev": true, "engines": { "node": "^12.20.0 || >=14" } @@ -21425,7 +20862,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.0.tgz", "integrity": "sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==", - "dev": true, "engines": { "node": ">= 12.0.0" } @@ -21433,8 +20869,7 @@ "node_modules/common-path-prefix": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "dev": true + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==" }, "node_modules/commondir": { "version": "1.0.1", @@ -21549,7 +20984,6 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, "engines": [ "node >= 0.8" ], @@ -21699,7 +21133,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, "dependencies": { "dot-prop": "^5.2.0", "graceful-fs": "^4.1.2", @@ -21716,7 +21149,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -21742,7 +21174,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true, "engines": { "node": ">=0.8" } @@ -21793,7 +21224,6 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, "dependencies": { "safe-buffer": "5.2.1" }, @@ -21805,7 +21235,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -21825,7 +21254,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -22099,7 +21527,6 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -22107,8 +21534,7 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/copy-concurrently": { "version": "1.0.5", @@ -22180,14 +21606,12 @@ "node_modules/copy-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/copy-dir/-/copy-dir-1.3.0.tgz", - "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==", - "dev": true + "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==" }, "node_modules/copy-webpack-plugin": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.0.tgz", "integrity": "sha512-my6iXII95c78w14HzYCNya5TlJYa44lOppAge5GSTMM1SyDxNsVGCJvhP4/ld6snm8lzjn3XOonMZD6s1L86Og==", - "dev": true, "dependencies": { "fast-glob": "^3.2.7", "glob-parent": "^6.0.1", @@ -22211,7 +21635,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -22228,7 +21651,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -22240,7 +21662,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", - "dev": true, "engines": { "node": ">=12" }, @@ -22252,7 +21673,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -22264,7 +21684,6 @@ "version": "12.2.0", "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", - "dev": true, "dependencies": { "array-union": "^3.0.1", "dir-glob": "^3.0.1", @@ -22283,14 +21702,12 @@ "node_modules/copy-webpack-plugin/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/copy-webpack-plugin/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -22309,7 +21726,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -22318,7 +21734,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true, "engines": { "node": ">=12" }, @@ -22615,7 +22030,6 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.31.0.tgz", "integrity": "sha512-/AnE9Y4OsJZicCzIe97JP5XoPKQJfTuEG43aEVLFJGOJpyqELod+pE6LEl63DfG1Mp8wX97LDaDpy1GmLEUxlg==", - "dev": true, "hasInstallScript": true, "funding": { "type": "opencollective", @@ -22758,7 +22172,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", - "dev": true, "license": "MIT", "dependencies": { "node-fetch": "^2.6.12" @@ -22768,7 +22181,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", - "dev": true, "dependencies": { "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", @@ -22801,7 +22213,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true, "engines": { "node": ">=8" } @@ -22809,8 +22220,7 @@ "node_modules/csp_evaluator": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/csp_evaluator/-/csp_evaluator-1.1.1.tgz", - "integrity": "sha512-N3ASg0C4kNPUaNxt1XAvzHIVuzdtr8KLgfk1O8WDyimp1GisPAHESupArO2ieHk9QWbrJ/WkQODyh21Ps/xhxw==", - "dev": true + "integrity": "sha512-N3ASg0C4kNPUaNxt1XAvzHIVuzdtr8KLgfk1O8WDyimp1GisPAHESupArO2ieHk9QWbrJ/WkQODyh21Ps/xhxw==" }, "node_modules/css": { "version": "2.2.4", @@ -22835,7 +22245,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", - "dev": true, "engines": { "node": "^10 || ^12 || >=14" }, @@ -22847,7 +22256,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.2.tgz", "integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==", - "dev": true, "engines": { "node": ">=12 || >=16" } @@ -22856,7 +22264,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.2.0.tgz", "integrity": "sha512-/rvHfYRjIpymZblf49w8jYcRo2y9gj6rV8UroHGmBxKrIyGLokpycyKzp9OkitvqT29ZSpzJ0Ic7SpnJX3sC8g==", - "dev": true, "dependencies": { "icss-utils": "^5.1.0", "postcss": "^8.2.15", @@ -22881,8 +22288,7 @@ "node_modules/css-loader/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/css-mediaquery": { "version": "0.1.2", @@ -23031,7 +22437,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, "bin": { "cssesc": "bin/cssesc" }, @@ -23043,7 +22448,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.0.1.tgz", "integrity": "sha512-fVO1JdJ0LSdIGJq68eIxOqFpIJrZqXUsBt8fkrBcztCQqAjQD51OhZp7tc0ImcbwXD4k7ny84QTV90nZhmqbkg==", - "dev": true, "dependencies": { "cssnano-preset-default": "^6.0.1", "lilconfig": "^2.1.0" @@ -23063,7 +22467,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.0.1.tgz", "integrity": "sha512-7VzyFZ5zEB1+l1nToKyrRkuaJIx0zi/1npjvZfbBwbtNTzhLtlvYraK/7/uqmX2Wb2aQtd983uuGw79jAjLSuQ==", - "dev": true, "dependencies": { "css-declaration-sorter": "^6.3.1", "cssnano-utils": "^4.0.0", @@ -23106,7 +22509,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.0.tgz", "integrity": "sha512-Z39TLP+1E0KUcd7LGyF4qMfu8ZufI0rDzhdyAMsa/8UyNUU8wpS0fhdBxbQbv32r64ea00h4878gommRVg2BHw==", - "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -23118,7 +22520,6 @@ "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dev": true, "dependencies": { "css-tree": "~2.2.0" }, @@ -23131,7 +22532,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dev": true, "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" @@ -23144,14 +22544,12 @@ "node_modules/csso/node_modules/mdn-data": { "version": "2.0.28", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "dev": true + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" }, "node_modules/csso/node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -23161,7 +22559,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", - "dev": true, "dependencies": { "rrweb-cssom": "^0.7.1" }, @@ -23178,7 +22575,6 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.10.0.tgz", "integrity": "sha512-YGZxdTTL9lmLkCUTpg4j0zQ7IhRB5ZmqNBbGCl3Tg6MP/d5/6sY7L5mmTjzbc6JKgVZYiqTQTNhPFsbXNGlRaA==", - "dev": true, "dependencies": { "find-pkg": "^0.1.2", "fs-exists-sync": "^0.1.0" @@ -23196,8 +22592,7 @@ "node_modules/damerau-levenshtein": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz", - "integrity": "sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==", - "dev": true + "integrity": "sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==" }, "node_modules/dargs": { "version": "7.0.0", @@ -23212,7 +22607,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-5.0.1.tgz", "integrity": "sha512-a9l6T1qqDogvvnw0nKlfZzqsyikEBZBClF39V3TFoKhDtGBqHu2HkuomJc02j5zft8zrUaXEuoicLeW54RkzPg==", - "dev": true, "engines": { "node": ">= 14" } @@ -23221,7 +22615,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", - "dev": true, "dependencies": { "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0" @@ -23234,7 +22627,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", - "dev": true, "dependencies": { "punycode": "^2.3.1" }, @@ -23246,7 +22638,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, "engines": { "node": ">=12" } @@ -23255,7 +22646,6 @@ "version": "14.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", - "dev": true, "dependencies": { "tr46": "^5.0.0", "webidl-conversions": "^7.0.0" @@ -23329,7 +22719,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", - "dev": true, "dependencies": { "decamelize": "^1.1.0", "map-obj": "^1.0.0" @@ -23341,8 +22730,7 @@ "node_modules/decimal.js": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" }, "node_modules/decode-uri-component": { "version": "0.2.2", @@ -23356,7 +22744,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, "dependencies": { "mimic-response": "^3.1.0" }, @@ -23371,7 +22758,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -23389,7 +22775,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, "engines": { "node": ">=4.0.0" } @@ -23403,8 +22788,7 @@ "node_modules/deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, "node_modules/deepmerge": { "version": "4.3.1", @@ -23427,7 +22811,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", - "dev": true, "dependencies": { "bundle-name": "^3.0.0", "default-browser-id": "^3.0.0", @@ -23445,7 +22828,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dev": true, "dependencies": { "bplist-parser": "^0.2.0", "untildify": "^4.0.0" @@ -23461,7 +22843,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -23475,7 +22856,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.1", @@ -23498,7 +22878,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, "engines": { "node": ">=10" }, @@ -23510,7 +22889,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, "engines": { "node": ">=14.18.0" } @@ -23519,7 +22897,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -23531,7 +22908,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, "engines": { "node": ">=12" }, @@ -23543,7 +22919,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, "dependencies": { "path-key": "^4.0.0" }, @@ -23558,7 +22933,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -23570,7 +22944,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, "dependencies": { "mimic-fn": "^4.0.0" }, @@ -23585,7 +22958,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -23594,7 +22966,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -23606,7 +22977,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -23615,7 +22985,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, "engines": { "node": ">=12" }, @@ -23627,7 +22996,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -23642,7 +23010,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, "dependencies": { "execa": "^5.0.0" }, @@ -23654,7 +23021,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -23668,7 +23034,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -23691,7 +23056,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, "engines": { "node": ">=10" }, @@ -23703,7 +23067,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, "engines": { "node": ">=10.17.0" } @@ -23712,7 +23075,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" }, @@ -23724,7 +23086,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -23733,7 +23094,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -23745,7 +23105,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -23760,7 +23119,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -23769,7 +23127,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -23781,7 +23138,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -23790,7 +23146,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -23813,7 +23168,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, "engines": { "node": ">=10" } @@ -23822,7 +23176,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -23839,7 +23192,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, "engines": { "node": ">=8" } @@ -23848,7 +23200,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dev": true, "dependencies": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" @@ -23896,7 +23247,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, "dependencies": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", @@ -23910,7 +23260,6 @@ "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, "dependencies": { "tslib": "^2.0.1" }, @@ -23922,7 +23271,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, "dependencies": { "@types/glob": "^7.1.1", "globby": "^6.1.0", @@ -23940,7 +23288,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -23960,7 +23307,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", - "dev": true, "dependencies": { "array-union": "^1.0.1", "glob": "^7.0.3", @@ -23976,7 +23322,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -23985,7 +23330,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true, "engines": { "node": ">=6" } @@ -23994,7 +23338,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, "engines": { "node": ">=6" } @@ -24003,7 +23346,6 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -24015,7 +23357,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -24040,7 +23381,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -24058,8 +23398,7 @@ "node_modules/deprecation": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" }, "node_modules/dequal": { "version": "2.0.3", @@ -24093,7 +23432,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", "integrity": "sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==", - "dev": true, "engines": { "node": ">=4" } @@ -24112,7 +23450,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, "engines": { "node": ">=8" } @@ -24120,8 +23457,7 @@ "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" }, "node_modules/detect-node-es": { "version": "1.1.0", @@ -24309,7 +23645,6 @@ "version": "0.0.1312386", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz", "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/diff": { @@ -24324,7 +23659,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -24350,7 +23684,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, "dependencies": { "path-type": "^4.0.0" }, @@ -24362,7 +23695,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -24370,14 +23702,12 @@ "node_modules/dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", - "dev": true + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dev": true, "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" }, @@ -24389,7 +23719,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -24485,7 +23814,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, "dependencies": { "is-obj": "^2.0.0" }, @@ -24497,7 +23825,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, "engines": { "node": ">=8" } @@ -24526,8 +23853,7 @@ "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" }, "node_modules/duplexer2": { "version": "0.1.4", @@ -24740,7 +24066,6 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -24757,7 +24082,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, "engines": { "node": ">= 4" } @@ -24788,7 +24112,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "dependencies": { "once": "^1.4.0" } @@ -24835,7 +24158,6 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, "dependencies": { "ansi-colors": "^4.1.1" }, @@ -24852,7 +24174,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, "engines": { "node": ">=6" } @@ -24924,7 +24245,6 @@ "version": "1.22.1", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", - "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "arraybuffer.prototype.slice": "^1.0.1", @@ -24977,7 +24297,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -24989,7 +24308,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -25023,14 +24341,12 @@ "node_modules/es-module-lexer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", - "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", - "dev": true + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" }, "node_modules/es-set-tostringtag": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dev": true, "dependencies": { "get-intrinsic": "^1.1.3", "has": "^1.0.3", @@ -25044,7 +24360,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, "dependencies": { "has": "^1.0.3" } @@ -25053,7 +24368,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -25158,7 +24472,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -25179,7 +24492,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -25188,7 +24500,6 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz", "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==", - "dev": true, "dependencies": { "@eslint/eslintrc": "^1.0.4", "@humanwhocodes/config-array": "^0.6.0", @@ -25243,7 +24554,6 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", - "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -25274,7 +24584,6 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz", "integrity": "sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ==", - "dev": true, "dependencies": { "debug": "^3.2.7", "find-up": "^2.1.0", @@ -25288,7 +24597,6 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -25296,8 +24604,7 @@ "node_modules/eslint-module-utils/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/eslint-plugin-eslint-comments": { "version": "3.1.2", @@ -25319,7 +24626,6 @@ "version": "2.25.2", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.2.tgz", "integrity": "sha512-qCwQr9TYfoBHOFcVGKY9C9unq05uOxxdklmBXLVvcwo68y5Hta6/GzCZEMx2zQiu0woKNEER0LE7ZgaOfBU14g==", - "dev": true, "dependencies": { "array-includes": "^3.1.4", "array.prototype.flat": "^1.2.5", @@ -25346,7 +24652,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "dependencies": { "ms": "2.0.0" } @@ -25355,7 +24660,6 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -25366,7 +24670,6 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -25374,14 +24677,12 @@ "node_modules/eslint-plugin-import/node_modules/eslint-import-resolver-node/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/eslint-plugin-jest": { "version": "27.2.3", "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz", "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==", - "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" }, @@ -25425,7 +24726,6 @@ "version": "46.4.6", "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.6.tgz", "integrity": "sha512-z4SWYnJfOqftZI+b3RM9AtWL1vF/sLWE/LlO9yOKDof9yN2+n3zOdOJTGX/pRE/xnPsooOLG2Rq6e4d+XW3lNw==", - "dev": true, "dependencies": { "@es-joy/jsdoccomment": "~0.40.1", "are-docs-informative": "^0.0.2", @@ -25448,7 +24748,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -25460,7 +24759,6 @@ "version": "6.5.1", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz", "integrity": "sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==", - "dev": true, "dependencies": { "@babel/runtime": "^7.16.3", "aria-query": "^4.2.2", @@ -25485,14 +24783,12 @@ "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/eslint-plugin-playwright": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-0.15.3.tgz", "integrity": "sha512-LQMW5y0DLK5Fnpya7JR1oAYL2/7Y9wDiYw6VZqlKqcRGSgjbVKNqxraphk7ra1U3Bb5EK444xMgUlQPbMg2M1g==", - "dev": true, "peerDependencies": { "eslint": ">=7", "eslint-plugin-jest": ">=25" @@ -25507,7 +24803,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz", "integrity": "sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==", - "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.8.5" @@ -25536,7 +24831,6 @@ "version": "7.27.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.27.0.tgz", "integrity": "sha512-0Ut+CkzpppgFtoIhdzi2LpdpxxBvgFf99eFqWxJnUrO7mMe0eOiNpou6rvNYeVVV6lWZvTah0BFne7k5xHjARg==", - "dev": true, "dependencies": { "array-includes": "^3.1.4", "array.prototype.flatmap": "^1.2.5", @@ -25564,7 +24858,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz", "integrity": "sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==", - "dev": true, "engines": { "node": ">=10" }, @@ -25576,7 +24869,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -25585,7 +24877,6 @@ "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -25602,7 +24893,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -25679,7 +24969,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, "dependencies": { "eslint-visitor-keys": "^2.0.0" }, @@ -25697,7 +24986,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, "engines": { "node": ">=10" } @@ -25706,7 +24994,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -25721,14 +25008,12 @@ "node_modules/eslint/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/eslint/node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -25742,7 +25027,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -25754,7 +25038,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -25766,7 +25049,6 @@ "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -25782,7 +25064,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -25794,7 +25075,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -25803,7 +25083,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -25815,7 +25094,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, "engines": { "node": ">= 4" } @@ -25824,7 +25102,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -25836,7 +25113,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -25849,7 +25125,6 @@ "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -25866,7 +25141,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -25875,7 +25149,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, "engines": { "node": ">= 0.8.0" } @@ -25884,7 +25157,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -25896,7 +25168,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -25905,7 +25176,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -25917,7 +25187,6 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -25929,7 +25198,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -25944,7 +25212,6 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/espree/-/espree-9.1.0.tgz", "integrity": "sha512-ZgYLvCS1wxOczBYGcQT9DDWgicXwJ4dbocr9uYN+/eresBAUuBu+O4WzB21ufQ/JqQT8gyp7hJ3z8SHii32mTQ==", - "dev": true, "dependencies": { "acorn": "^8.6.0", "acorn-jsx": "^5.3.1", @@ -25955,10 +25222,9 @@ } }, "node_modules/espree/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -25971,7 +25237,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -25995,7 +25260,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -26007,7 +25271,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -26016,7 +25279,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -26028,7 +25290,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -26037,7 +25298,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, "engines": { "node": ">=4.0" } @@ -26046,7 +25306,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -26075,14 +25334,12 @@ "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, "engines": { "node": ">=0.8.x" } @@ -26101,7 +25358,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz", "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", @@ -26124,7 +25380,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -26138,7 +25393,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" }, @@ -26150,7 +25404,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -26159,7 +25412,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -26171,7 +25423,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -26186,7 +25437,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -26195,7 +25445,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -26207,7 +25456,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -26216,7 +25464,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -26231,7 +25478,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, "engines": { "node": ">= 0.8.0" } @@ -26301,7 +25547,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", "integrity": "sha512-rtmc+cjLZqnu9dSYosX9EWmSJhTwpACgJQTfj4hgg2JjOD/6SIQalZrt4a3aQeh++oNxkazcaxrhPUj6+g5G/Q==", - "dev": true, "dependencies": { "os-homedir": "^1.0.1" }, @@ -26313,7 +25558,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz", "integrity": "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==", - "dev": true, "dependencies": { "@jest/expect-utils": "^29.6.2", "@types/node": "*", @@ -26329,8 +25573,7 @@ "node_modules/expect-puppeteer": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/expect-puppeteer/-/expect-puppeteer-4.4.0.tgz", - "integrity": "sha512-6Ey4Xy2xvmuQu7z7YQtMsaMV0EHJRpVxIDOd5GRrm04/I3nkTKIutELfECsLp6le+b3SSa3cXhPiw6PgqzxYWA==", - "dev": true + "integrity": "sha512-6Ey4Xy2xvmuQu7z7YQtMsaMV0EHJRpVxIDOd5GRrm04/I3nkTKIutELfECsLp6le+b3SSa3cXhPiw6PgqzxYWA==" }, "node_modules/exponential-backoff": { "version": "3.1.1", @@ -26342,7 +25585,6 @@ "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -26384,7 +25626,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "dependencies": { "ms": "2.0.0" } @@ -26393,7 +25634,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -26402,7 +25642,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -26420,7 +25659,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, "dependencies": { "ee-first": "1.1.1" }, @@ -26432,7 +25670,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -26452,7 +25689,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -26460,8 +25696,7 @@ "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "node_modules/extend-shallow": { "version": "3.0.2", @@ -26504,7 +25739,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", - "dev": true, "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", @@ -26518,7 +25752,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -26586,7 +25819,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", - "dev": true, "dependencies": { "concat-stream": "^1.6.2", "debug": "^2.6.9", @@ -26601,7 +25833,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "dependencies": { "ms": "2.0.0" } @@ -26610,7 +25841,6 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, "dependencies": { "minimist": "^1.2.6" }, @@ -26642,20 +25872,17 @@ "node_modules/fast-diff": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" }, "node_modules/fast-fifo": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.0.tgz", - "integrity": "sha512-IgfweLvEpwyA4WgiQe9Nx6VV2QkML2NkvZnk1oKnIzXgXdWxuhF7zw4DvLTPZJn6PIUneiAXPF24QmoEqHTjyw==", - "dev": true + "integrity": "sha512-IgfweLvEpwyA4WgiQe9Nx6VV2QkML2NkvZnk1oKnIzXgXdWxuhF7zw4DvLTPZJn6PIUneiAXPF24QmoEqHTjyw==" }, "node_modules/fast-glob": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -26671,7 +25898,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -26688,14 +25914,12 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "node_modules/fast-memoize": { "version": "2.5.2", @@ -26706,7 +25930,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", - "dev": true, "license": "MIT" }, "node_modules/fast-xml-parser": { @@ -26734,7 +25957,6 @@ "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, "engines": { "node": ">= 4.9.1" } @@ -26743,7 +25965,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz", "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==", - "dev": true, "dependencies": { "reusify": "^1.0.0" } @@ -26752,7 +25973,6 @@ "version": "0.11.4", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, "dependencies": { "websocket-driver": ">=0.5.1" }, @@ -26772,7 +25992,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, "dependencies": { "pend": "~1.2.0" } @@ -26835,7 +26054,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -26929,7 +26147,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", - "dev": true, "engines": { "node": ">=4" } @@ -26938,7 +26155,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.2.0.tgz", "integrity": "sha512-pkgE+4p7N1n7QieOopmn3TqJaefjdWXwEkj2XLZJLKfOgcQKkn11ahvGNgTD8mLggexLiDFQxeTs14xVU22XPA==", - "dev": true, "dependencies": { "filename-reserved-regex": "^2.0.0", "strip-outer": "^1.0.1", @@ -27129,7 +26345,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-0.1.3.tgz", "integrity": "sha512-mBxmNbVyjg1LQIIpgO8hN+ybWBgDQK8qjht+EbrTCGmmPV/sc7RF1i9stPTD6bpvXZywBdrwRYxhSdJv867L6A==", - "dev": true, "dependencies": { "fs-exists-sync": "^0.1.0", "resolve-dir": "^0.1.0" @@ -27141,14 +26356,12 @@ "node_modules/find-parent-dir": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", - "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", - "dev": true + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=" }, "node_modules/find-pkg": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-0.1.2.tgz", "integrity": "sha512-0rnQWcFwZr7eO0513HahrWafsc3CTFioEB7DRiEYCUM/70QXSY8f3mCST17HXLcPvEhzH/Ty/Bxd72ZZsr/yvw==", - "dev": true, "dependencies": { "find-file-up": "^0.1.2" }, @@ -27160,7 +26373,6 @@ "version": "1.4.7", "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.7.tgz", "integrity": "sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==", - "dev": true, "dependencies": { "chalk": "^4.0.0", "commander": "^5.1.0", @@ -27174,7 +26386,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true, "engines": { "node": ">= 6" } @@ -27188,7 +26399,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, "dependencies": { "locate-path": "^2.0.0" }, @@ -27218,7 +26428,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", @@ -27232,8 +26441,7 @@ "node_modules/flatted": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" }, "node_modules/flow-enums-runtime": { "version": "0.0.6", @@ -27268,7 +26476,6 @@ "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, "funding": [ { "type": "individual", @@ -27288,7 +26495,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, "dependencies": { "is-callable": "^1.1.3" } @@ -27297,7 +26503,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -27306,7 +26511,6 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==", - "dev": true, "dependencies": { "for-in": "^1.0.1" }, @@ -27548,7 +26752,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -27583,7 +26786,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -27592,7 +26794,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "dev": true, "engines": { "node": "*" }, @@ -27665,7 +26866,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", "integrity": "sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -27698,8 +26898,7 @@ "node_modules/fs-monkey": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", - "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==", - "dev": true + "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==" }, "node_modules/fs-write-stream-atomic": { "version": "1.0.10", @@ -27838,7 +27037,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", @@ -27855,14 +27053,12 @@ "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -28101,7 +27297,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -28161,7 +27356,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", - "dev": true, "engines": { "node": ">=8" }, @@ -28173,7 +27367,6 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", - "dev": true, "engines": { "node": ">=12" }, @@ -28185,7 +27378,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, "dependencies": { "pump": "^3.0.0" }, @@ -28200,7 +27392,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -28211,7 +27402,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.1" @@ -28227,7 +27417,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.1.tgz", "integrity": "sha512-7ZqONUVqaabogsYNWlYj0t3YZaL6dhuEueZXGF+/YVmf6dHmaFg8/6psJKqhx9QykIDKzpGcy2cn4oV4YC7V/Q==", - "dev": true, "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^5.0.1", @@ -28467,14 +27656,12 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "node_modules/global-modules": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, "dependencies": { "global-prefix": "^3.0.0" }, @@ -28486,7 +27673,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, "dependencies": { "ini": "^1.3.5", "kind-of": "^6.0.2", @@ -28500,7 +27686,6 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -28515,7 +27700,6 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -28527,7 +27711,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, "dependencies": { "define-properties": "^1.1.3" }, @@ -28542,7 +27725,6 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -28562,7 +27744,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, "engines": { "node": ">=8" } @@ -28571,7 +27752,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -28587,7 +27767,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -28598,8 +27777,7 @@ "node_modules/globjoin": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", - "dev": true + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==" }, "node_modules/good-listener": { "version": "1.2.2", @@ -28613,7 +27791,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -28625,7 +27802,6 @@ "version": "11.8.6", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, "dependencies": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", @@ -28668,8 +27844,7 @@ "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" }, "node_modules/gunzip-maybe": { "version": "1.4.2", @@ -28706,8 +27881,7 @@ "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" }, "node_modules/handlebars": { "version": "4.7.8", @@ -28734,7 +27908,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, "engines": { "node": ">=6" } @@ -28775,7 +27948,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -28792,7 +27964,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -28804,7 +27975,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -28816,7 +27986,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -28828,7 +27997,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -28952,7 +28120,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -29046,7 +28213,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, "dependencies": { "parse-passwd": "^1.0.0" }, @@ -29058,7 +28224,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -29070,7 +28235,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -29081,14 +28245,12 @@ "node_modules/hosted-git-info/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, "dependencies": { "inherits": "^2.0.1", "obuf": "^1.0.0", @@ -29105,7 +28267,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "dev": true, "dependencies": { "whatwg-encoding": "^3.1.1" }, @@ -29117,7 +28278,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", - "dev": true, "funding": [ { "type": "github", @@ -29132,8 +28292,7 @@ "node_modules/html-escaper": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", - "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", - "dev": true + "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==" }, "node_modules/html-minifier-terser": { "version": "6.1.0", @@ -29169,7 +28328,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", - "dev": true, "engines": { "node": ">=8" }, @@ -29318,14 +28476,12 @@ "node_modules/http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "node_modules/http-deceiver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" }, "node_modules/http-errors": { "version": "2.0.0", @@ -29367,7 +28523,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/http-link-header/-/http-link-header-1.1.1.tgz", "integrity": "sha512-mW3N/rTYpCn99s1do0zx6nzFZSwLH9HGfUM4ZqLWJ16ylmYaC2v5eYGqrNTQlByx8AzUgGI+V/32gXPugs1+Sw==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -29375,14 +28530,12 @@ "node_modules/http-parser-js": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", - "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", - "dev": true + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==" }, "node_modules/http-proxy": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", @@ -29419,7 +28572,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", @@ -29449,7 +28601,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" @@ -29462,7 +28613,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, "engines": { "node": ">=10" }, @@ -29480,7 +28630,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -29493,7 +28642,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, "engines": { "node": ">=8.12.0" } @@ -29537,7 +28685,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, "engines": { "node": "^10 || ^12 || >= 14" }, @@ -29574,7 +28721,6 @@ "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, "engines": { "node": ">= 4" } @@ -29583,7 +28729,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-4.0.1.tgz", "integrity": "sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==", - "dev": true, "dependencies": { "minimatch": "^3.0.4" }, @@ -29608,8 +28753,7 @@ "node_modules/image-ssim": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/image-ssim/-/image-ssim-0.2.0.tgz", - "integrity": "sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==", - "dev": true + "integrity": "sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==" }, "node_modules/import-fresh": { "version": "3.3.0", @@ -29638,7 +28782,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -29657,7 +28800,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -29670,7 +28812,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -29682,7 +28823,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -29697,7 +28837,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -29709,7 +28848,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "engines": { "node": ">=6" } @@ -29718,7 +28856,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -29727,7 +28864,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, "dependencies": { "find-up": "^4.0.0" }, @@ -29797,8 +28933,7 @@ "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "node_modules/init-package-json": { "version": "5.0.0", @@ -29867,7 +29002,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", - "dev": true, "dependencies": { "ansi-escapes": "^4.2.1", "chalk": "^3.0.0", @@ -29891,7 +29025,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -29904,7 +29037,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, "dependencies": { "restore-cursor": "^3.1.0" }, @@ -29915,14 +29047,12 @@ "node_modules/inquirer/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/inquirer/node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -29937,7 +29067,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -29946,7 +29075,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -29955,7 +29083,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -29964,7 +29091,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -29979,7 +29105,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -29992,7 +29117,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -30006,7 +29130,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -30018,7 +29141,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dev": true, "dependencies": { "get-intrinsic": "^1.2.0", "has": "^1.0.3", @@ -30032,7 +29154,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -30041,7 +29162,6 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-4.4.0.tgz", "integrity": "sha512-z+Bj2rS3LZSYU4+sNitdHrwnBhr0wO80ZJSW8EzKDBowwUe3Q/UsvgCGjrwa+HPzoGCLEb9HAjfJgo4j2Sac8w==", - "dev": true, "dependencies": { "intl-messageformat-parser": "^1.8.1" } @@ -30050,8 +29170,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.8.1.tgz", "integrity": "sha512-IMSCKVf0USrM/959vj3xac7s8f87sc+80Y/ipBzdKy4ifBv5Gsj2tZ41EAaURVg01QU71fYr77uA8Meh6kELbg==", - "deprecated": "We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser", - "dev": true + "deprecated": "We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser" }, "node_modules/invariant": { "version": "2.2.4", @@ -30070,7 +29189,6 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dev": true, "license": "MIT", "dependencies": { "jsbn": "1.1.0", @@ -30084,14 +29202,12 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, "engines": { "node": ">= 0.10" } @@ -30100,7 +29216,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.2.0.tgz", "integrity": "sha512-YqTdPLfwP7YFN0SsD3QUVCkm9ZG2VzOXv3DOrw5G5mkMbVwptTwVcFv7/C0vOpBmgTxAeTG19XpUs1E522LW9Q==", - "dev": true, "engines": { "node": ">=8" } @@ -30130,7 +29245,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", - "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -30140,7 +29254,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", "integrity": "sha512-ZmRL7++ZkcMOfDuWZuMJyIVLr2keE1o/DeNWh1EmgqGhUcV+9BIVsx0BcSBOHTZqzjs4+dISzr2KAeBEWGgXeA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -30149,7 +29262,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", - "dev": true, "dependencies": { "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0" @@ -30175,7 +29287,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.0", @@ -30194,7 +29305,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, "dependencies": { "has-bigints": "^1.0.1" }, @@ -30206,7 +29316,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -30218,7 +29327,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -30233,14 +29341,12 @@ "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "node_modules/is-builtin-module": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, "dependencies": { "builtin-modules": "^3.3.0" }, @@ -30255,7 +29361,6 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -30308,7 +29413,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -30322,8 +29426,7 @@ "node_modules/is-decimal": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", - "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", - "dev": true + "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==" }, "node_modules/is-deflate": { "version": "1.0.0", @@ -30370,7 +29473,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -30379,7 +29481,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -30396,7 +29497,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, "engines": { "node": ">=6" } @@ -30420,7 +29520,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -30440,14 +29539,12 @@ "node_modules/is-hexadecimal": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", - "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", - "dev": true + "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==" }, "node_modules/is-inside-container": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, "dependencies": { "is-docker": "^3.0.0" }, @@ -30465,7 +29562,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, "bin": { "is-docker": "cli.js" }, @@ -30519,7 +29615,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -30543,7 +29638,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -30591,7 +29685,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, "engines": { "node": ">=6" } @@ -30600,7 +29693,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, "dependencies": { "is-path-inside": "^2.1.0" }, @@ -30612,7 +29704,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, "dependencies": { "path-is-inside": "^1.0.2" }, @@ -30624,7 +29715,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, "engines": { "node": ">=10" }, @@ -30643,8 +29733,7 @@ "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" }, "node_modules/is-promise": { "version": "4.0.0", @@ -30655,7 +29744,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -30689,7 +29777,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2" }, @@ -30719,7 +29806,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -30734,7 +29820,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -30761,7 +29846,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dev": true, "dependencies": { "which-typed-array": "^1.1.11" }, @@ -30775,8 +29859,7 @@ "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, "node_modules/is-unicode-supported": { "version": "0.1.0", @@ -30802,7 +29885,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2" }, @@ -30827,7 +29909,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", - "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -30846,7 +29927,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", - "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -30891,7 +29971,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, "engines": { "node": ">=8" } @@ -30900,7 +29979,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", @@ -30916,7 +29994,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -30925,7 +30002,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", @@ -30939,7 +30015,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -30948,7 +30023,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -30960,7 +30034,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -30974,7 +30047,6 @@ "version": "3.1.6", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", - "dev": true, "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -31034,7 +30106,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz", "integrity": "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==", - "dev": true, "dependencies": { "@jest/core": "^29.6.2", "@jest/types": "^29.6.1", @@ -31060,7 +30131,6 @@ "version": "29.5.0", "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", - "dev": true, "dependencies": { "execa": "^5.0.0", "p-limit": "^3.1.0" @@ -31073,7 +30143,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -31087,7 +30156,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -31110,7 +30178,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, "engines": { "node": ">=10" }, @@ -31122,7 +30189,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, "engines": { "node": ">=10.17.0" } @@ -31131,7 +30197,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" }, @@ -31143,7 +30208,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -31152,7 +30216,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -31164,7 +30227,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -31179,7 +30241,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -31188,7 +30249,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -31200,7 +30260,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -31209,7 +30268,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -31224,7 +30282,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz", "integrity": "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==", - "dev": true, "dependencies": { "@jest/environment": "^29.6.2", "@jest/expect": "^29.6.2", @@ -31255,7 +30312,6 @@ "version": "1.5.3", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", - "dev": true, "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, @@ -31269,7 +30325,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz", "integrity": "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==", - "dev": true, "dependencies": { "@jest/core": "^29.6.2", "@jest/test-result": "^29.6.2", @@ -31303,7 +30358,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -31316,14 +30370,12 @@ "node_modules/jest-cli/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/jest-cli/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -31332,7 +30384,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -31346,7 +30397,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -31363,7 +30413,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "engines": { "node": ">=10" } @@ -31372,7 +30421,6 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -31390,7 +30438,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "engines": { "node": ">=12" } @@ -31399,7 +30446,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz", "integrity": "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==", - "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.6.2", @@ -31444,7 +30490,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -31464,7 +30509,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -31476,7 +30520,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", @@ -31491,7 +30534,6 @@ "version": "29.4.3", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", - "dev": true, "dependencies": { "detect-newline": "^3.0.0" }, @@ -31503,7 +30545,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz", "integrity": "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==", - "dev": true, "dependencies": { "@jest/types": "^29.6.1", "chalk": "^4.0.0", @@ -31519,7 +30560,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.6.2.tgz", "integrity": "sha512-7oa/+266AAEgkzae8i1awNEfTfjwawWKLpiw2XesZmaoVVj9u9t8JOYx18cG29rbPNtkUlZ8V4b5Jb36y/VxoQ==", - "dev": true, "dependencies": { "@jest/environment": "^29.6.2", "@jest/fake-timers": "^29.6.2", @@ -31570,7 +30610,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -31659,7 +30698,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz", "integrity": "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==", - "dev": true, "dependencies": { "jest-get-type": "^29.4.3", "pretty-format": "^29.6.2" @@ -31672,7 +30710,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.7.0", @@ -31687,7 +30724,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz", "integrity": "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.6.1", @@ -31720,7 +30756,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, "engines": { "node": ">=6" }, @@ -31737,7 +30772,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -31746,7 +30780,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz", "integrity": "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==", - "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", @@ -31766,7 +30799,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz", "integrity": "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==", - "dev": true, "dependencies": { "jest-regex-util": "^29.4.3", "jest-snapshot": "^29.6.2" @@ -31779,7 +30811,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz", "integrity": "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==", - "dev": true, "dependencies": { "@jest/console": "^29.6.2", "@jest/environment": "^29.6.2", @@ -31811,7 +30842,6 @@ "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -31821,7 +30851,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz", "integrity": "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==", - "dev": true, "dependencies": { "@jest/environment": "^29.6.2", "@jest/fake-timers": "^29.6.2", @@ -31854,7 +30883,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -31874,7 +30902,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz", "integrity": "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==", - "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", @@ -32058,7 +31085,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz", "integrity": "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==", - "dev": true, "dependencies": { "@jest/test-result": "^29.6.2", "@jest/types": "^29.6.1", @@ -32125,14 +31151,12 @@ "node_modules/jpeg-js": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", - "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", - "dev": true + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" }, "node_modules/js-library-detector": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/js-library-detector/-/js-library-detector-6.7.0.tgz", "integrity": "sha512-c80Qupofp43y4cJ7+8TTDN/AsDwLi5oOm/plBrWI+iQt485vKXCco+yVmOwEgdo9VOdsYTuV0UlTeetVPTriXA==", - "dev": true, "engines": { "node": ">=12" } @@ -32158,7 +31182,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true, "license": "MIT" }, "node_modules/jsc-android": { @@ -32241,7 +31264,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", - "dev": true, "engines": { "node": ">=12.0.0" } @@ -32250,7 +31272,6 @@ "version": "25.0.1", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", - "dev": true, "dependencies": { "cssstyle": "^4.1.0", "data-urls": "^5.0.0", @@ -32299,7 +31320,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, "dependencies": { "debug": "^4.3.4" }, @@ -32311,7 +31331,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -32324,7 +31343,6 @@ "version": "7.0.5", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -32337,7 +31355,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", - "dev": true, "dependencies": { "punycode": "^2.3.1" }, @@ -32349,7 +31366,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, "engines": { "node": ">=12" } @@ -32358,7 +31374,6 @@ "version": "14.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", - "dev": true, "dependencies": { "tr46": "^5.0.0", "webidl-conversions": "^7.0.0" @@ -32371,7 +31386,6 @@ "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -32436,8 +31450,7 @@ "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, "node_modules/json-parse-better-errors": { "version": "1.0.2", @@ -32458,8 +31471,7 @@ "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/json-stable-stringify": { "version": "1.1.0", @@ -32482,8 +31494,7 @@ "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, "node_modules/json-stable-stringify/node_modules/isarray": { "version": "2.0.5", @@ -32510,8 +31521,7 @@ "node_modules/json2php": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/json2php/-/json2php-0.0.7.tgz", - "integrity": "sha512-dnSoUiLAoVaMXxFsVi4CrPVYMKOuDBXTghXSmMINX44RZ8WM9cXlY7UqrQnlAcODCVO7FV3+8t/5nDKAjimLfg==", - "dev": true + "integrity": "sha512-dnSoUiLAoVaMXxFsVi4CrPVYMKOuDBXTghXSmMINX44RZ8WM9cXlY7UqrQnlAcODCVO7FV3+8t/5nDKAjimLfg==" }, "node_modules/json5": { "version": "2.2.3", @@ -32527,8 +31537,7 @@ "node_modules/jsonc-parser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", - "dev": true + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==" }, "node_modules/jsonfile": { "version": "4.0.0", @@ -32576,7 +31585,6 @@ "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", @@ -32591,7 +31599,6 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, "dependencies": { "json-buffer": "3.0.1" } @@ -32634,7 +31641,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "dev": true, "engines": { "node": ">= 8" } @@ -32642,8 +31648,7 @@ "node_modules/known-css-properties": { "version": "0.34.0", "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.34.0.tgz", - "integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==", - "dev": true + "integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==" }, "node_modules/kuler": { "version": "2.0.0", @@ -32666,14 +31671,12 @@ "node_modules/language-subtag-registry": { "version": "0.3.21", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz", - "integrity": "sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==", - "dev": true + "integrity": "sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==" }, "node_modules/language-tags": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", - "dev": true, "dependencies": { "language-subtag-registry": "~0.3.2" } @@ -32682,7 +31685,6 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", - "dev": true, "dependencies": { "picocolors": "^1.0.0", "shell-quote": "^1.7.3" @@ -32692,7 +31694,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -33812,7 +32813,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -34003,7 +33003,6 @@ "version": "10.4.0", "resolved": "https://registry.npmjs.org/lighthouse/-/lighthouse-10.4.0.tgz", "integrity": "sha512-XQWHEWkJ8YxSPsxttBJORy5+hQrzbvGkYfeP3fJjyYKioWkF2MXfFqNK4ZuV4jL8pBu7Z91qnQP6In0bq1yXww==", - "dev": true, "dependencies": { "@sentry/node": "^6.17.4", "axe-core": "4.7.2", @@ -34062,14 +33061,12 @@ "node_modules/lighthouse-stack-packs": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/lighthouse-stack-packs/-/lighthouse-stack-packs-1.11.0.tgz", - "integrity": "sha512-sRr0z1S/I26VffRLq9KJsKtLk856YrJlNGmcJmbLX8dFn3MuzVPUbstuChEhqnSxZb8TZmVfthuXuwhG9vRoSw==", - "dev": true + "integrity": "sha512-sRr0z1S/I26VffRLq9KJsKtLk856YrJlNGmcJmbLX8dFn3MuzVPUbstuChEhqnSxZb8TZmVfthuXuwhG9vRoSw==" }, "node_modules/lighthouse/node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -34082,20 +33079,17 @@ "node_modules/lighthouse/node_modules/devtools-protocol": { "version": "0.0.1155343", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1155343.tgz", - "integrity": "sha512-oD9vGBV2wTc7fAzAM6KC0chSgs234V8+qDEeK+mcbRj2UvcuA7lgBztGi/opj/iahcXD3BSj8Ymvib628yy9FA==", - "dev": true + "integrity": "sha512-oD9vGBV2wTc7fAzAM6KC0chSgs234V8+qDEeK+mcbRj2UvcuA7lgBztGi/opj/iahcXD3BSj8Ymvib628yy9FA==" }, "node_modules/lighthouse/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/lighthouse/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -34104,7 +33098,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -34116,7 +33109,6 @@ "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -34133,7 +33125,6 @@ "version": "20.9.0", "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-20.9.0.tgz", "integrity": "sha512-H9fYZQzMTRrkboEfPmf7m3CLDN6JvbxXA3qTtS+dFt27tR+CsFHzPsT6pzp6lYL6bJbAPaR0HaPO6uSi+F94Pg==", - "dev": true, "dependencies": { "@puppeteer/browsers": "1.4.6", "chromium-bidi": "0.4.16", @@ -34157,14 +33148,12 @@ "node_modules/lighthouse/node_modules/puppeteer-core/node_modules/devtools-protocol": { "version": "0.0.1147663", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1147663.tgz", - "integrity": "sha512-hyWmRrexdhbZ1tcJUGpO95ivbRhWXz++F4Ko+n21AY5PNln2ovoJw+8ZMNDTtip+CNFQfrtLVh/w4009dXO/eQ==", - "dev": true + "integrity": "sha512-hyWmRrexdhbZ1tcJUGpO95ivbRhWXz++F4Ko+n21AY5PNln2ovoJw+8ZMNDTtip+CNFQfrtLVh/w4009dXO/eQ==" }, "node_modules/lighthouse/node_modules/puppeteer-core/node_modules/ws": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, "engines": { "node": ">=10.0.0" }, @@ -34185,7 +33174,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "bin": { "semver": "bin/semver" } @@ -34194,7 +33182,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -34208,7 +33195,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -34225,7 +33211,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "engines": { "node": ">=10" } @@ -34234,7 +33219,6 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -34252,7 +33236,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "engines": { "node": ">=12" } @@ -34261,7 +33244,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, "engines": { "node": ">=10" } @@ -34286,7 +33268,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", - "dev": true, "dependencies": { "uc.micro": "^1.0.1" } @@ -34809,7 +33790,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -34846,7 +33826,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -34883,14 +33862,12 @@ "node_modules/lodash.escape": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==", - "dev": true + "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==" }, "node_modules/lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "dev": true + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" }, "node_modules/lodash.get": { "version": "4.4.2", @@ -34901,8 +33878,7 @@ "node_modules/lodash.invokemap": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.invokemap/-/lodash.invokemap-4.6.0.tgz", - "integrity": "sha512-CfkycNtMqgUlfjfdh2BhKO/ZXrP8ePOX5lEU/g0R3ItJcnuxWDwokMGKx1hWcfOikmyOVx6X9IwWnDGlgKl61w==", - "dev": true + "integrity": "sha512-CfkycNtMqgUlfjfdh2BhKO/ZXrP8ePOX5lEU/g0R3ItJcnuxWDwokMGKx1hWcfOikmyOVx6X9IwWnDGlgKl61w==" }, "node_modules/lodash.ismatch": { "version": "4.4.0", @@ -34913,20 +33889,17 @@ "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, "node_modules/lodash.pullall": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.pullall/-/lodash.pullall-4.2.0.tgz", - "integrity": "sha512-VhqxBKH0ZxPpLhiu68YD1KnHmbhQJQctcipvmFnqIBDYzcIHzf3Zpu0tpeOKtR4x76p9yohc506eGdOjTmyIBg==", - "dev": true + "integrity": "sha512-VhqxBKH0ZxPpLhiu68YD1KnHmbhQJQctcipvmFnqIBDYzcIHzf3Zpu0tpeOKtR4x76p9yohc506eGdOjTmyIBg==" }, "node_modules/lodash.set": { "version": "4.3.2", @@ -34942,20 +33915,17 @@ "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==" }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" }, "node_modules/lodash.uniqby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", - "dev": true + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==" }, "node_modules/lodash.zip": { "version": "4.2.0", @@ -35213,14 +34183,12 @@ "node_modules/longest-streak": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", - "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", - "dev": true + "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==" }, "node_modules/lookup-closest-locale": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/lookup-closest-locale/-/lookup-closest-locale-6.2.0.tgz", - "integrity": "sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==", - "dev": true + "integrity": "sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==" }, "node_modules/loose-envify": { "version": "1.4.0", @@ -35245,7 +34213,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, "engines": { "node": ">=8" } @@ -35253,14 +34220,12 @@ "node_modules/lru_map": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", - "dev": true + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==" }, "node_modules/lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, "dependencies": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" @@ -35306,7 +34271,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", - "dev": true, "dependencies": { "semver": "^6.0.0" }, @@ -35318,7 +34282,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -35567,7 +34530,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -35581,8 +34543,7 @@ "node_modules/map-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-values/-/map-values-1.0.1.tgz", - "integrity": "sha512-BbShUnr5OartXJe1GeccAWtfro11hhgNJg6G9/UtWKjVGvV5U4C09cg5nk8JUevhXODaXY+hQ3xxMUKSs62ONQ==", - "dev": true + "integrity": "sha512-BbShUnr5OartXJe1GeccAWtfro11hhgNJg6G9/UtWKjVGvV5U4C09cg5nk8JUevhXODaXY+hQ3xxMUKSs62ONQ==" }, "node_modules/map-visit": { "version": "1.0.0", @@ -35854,14 +34815,12 @@ "node_modules/markdown-escapes": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz", - "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", - "dev": true + "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==" }, "node_modules/markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", - "dev": true, "dependencies": { "argparse": "^2.0.1", "entities": "~2.1.0", @@ -35876,14 +34835,12 @@ "node_modules/markdown-it/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/markdown-it/node_modules/entities": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "dev": true, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -35891,8 +34848,7 @@ "node_modules/markdown-table": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", - "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", - "dev": true + "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==" }, "node_modules/markdown-to-jsx": { "version": "7.4.1", @@ -35910,7 +34866,6 @@ "version": "0.25.1", "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.25.1.tgz", "integrity": "sha512-AG7UkLzNa1fxiOv5B+owPsPhtM4D6DoODhsJgiaNg1xowXovrYgOnLqAgOOFQpWOlHFVQUzjMY5ypNNTeov92g==", - "dev": true, "dependencies": { "markdown-it": "12.3.2" }, @@ -35922,7 +34877,6 @@ "version": "0.31.1", "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.31.1.tgz", "integrity": "sha512-keIOMwQn+Ch7MoBwA+TdkyVMuxAeZFEGmIIlvwgV0Z1TGS5MxPnRr29XCLhkNzCHU+uNKGjU+VEjLX+Z9kli6g==", - "dev": true, "dependencies": { "commander": "~9.0.0", "get-stdin": "~9.0.0", @@ -35945,14 +34899,12 @@ "node_modules/markdownlint-cli/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/markdownlint-cli/node_modules/commander": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/commander/-/commander-9.0.0.tgz", "integrity": "sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==", - "dev": true, "engines": { "node": "^12.20.0 || >=14" } @@ -35961,7 +34913,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -35981,7 +34932,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -35993,7 +34943,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -36005,7 +34954,6 @@ "version": "3.0.8", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -36016,8 +34964,7 @@ "node_modules/markdownlint-rule-helpers": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.16.0.tgz", - "integrity": "sha512-oEacRUVeTJ5D5hW1UYd2qExYI0oELdYK72k1TKGvIeYJIbqQWAz476NAc7LNixSySUhcNl++d02DvX0ccDk9/w==", - "dev": true + "integrity": "sha512-oEacRUVeTJ5D5hW1UYd2qExYI0oELdYK72k1TKGvIeYJIbqQWAz476NAc7LNixSySUhcNl++d02DvX0ccDk9/w==" }, "node_modules/marked": { "version": "4.3.0", @@ -36063,7 +35010,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", - "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -36084,7 +35030,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", - "dev": true, "dependencies": { "unist-util-modify-children": "^1.0.0", "unist-util-visit": "^1.1.0" @@ -36146,7 +35091,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", "integrity": "sha512-CcJ0mHa36QYumDKiZ2OIR+ClhfOM7zIzN+Wfy8tRZ1hpH9DKLCS+Mh4DyK5bCxzE9uxMWcbIpeNFWsg1zrj/2g==", - "dev": true, "dependencies": { "mdast-util-to-string": "^1.0.0" } @@ -36154,8 +35098,7 @@ "node_modules/mdast-util-to-string": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.5.tgz", - "integrity": "sha512-2qLt/DEOo5F6nc2VFScQiHPzQ0XXcabquRJxKMhKte8nt42o08HUxNDPk7tt0YPxnWjAT11I1SYi0X0iPnfI5A==", - "dev": true + "integrity": "sha512-2qLt/DEOo5F6nc2VFScQiHPzQ0XXcabquRJxKMhKte8nt42o08HUxNDPk7tt0YPxnWjAT11I1SYi0X0iPnfI5A==" }, "node_modules/mdn-data": { "version": "2.0.14", @@ -36165,14 +35108,12 @@ "node_modules/mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -36181,7 +35122,6 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dev": true, "dependencies": { "fs-monkey": "^1.0.4" }, @@ -36283,7 +35223,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz", "integrity": "sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==", - "dev": true, "dependencies": { "arr-union": "^3.1.0", "clone-deep": "^0.2.4", @@ -36297,7 +35236,6 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", "integrity": "sha512-we+NuQo2DHhSl+DP6jlUiAhyAjBQrYnpOk15rN6c6JSPScjiCLh8IbSU+VTcph6YS3o7mASE8a0+gbZ7ChLpgg==", - "dev": true, "dependencies": { "for-own": "^0.1.3", "is-plain-object": "^2.0.1", @@ -36313,7 +35251,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "dependencies": { "isobject": "^3.0.1" }, @@ -36325,7 +35262,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, "dependencies": { "is-buffer": "^1.1.5" }, @@ -36337,7 +35273,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", "integrity": "sha512-J1zdXCky5GmNnuauESROVu31MQSnLoYvlyEn6j2Ztk6Q5EHFIhxkMhYcv6vuDzl2XEzoRr856QwzMgWM/TmZgw==", - "dev": true, "dependencies": { "is-extendable": "^0.1.1", "kind-of": "^2.0.1", @@ -36352,7 +35287,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", "integrity": "sha512-0u8i1NZ/mg0b+W3MGGw5I7+6Eib2nx72S/QvXa0hYjEkjTknYmEYQJwGu3mLC0BrhtJjtQafTkyRUQ75Kx0LVg==", - "dev": true, "dependencies": { "is-buffer": "^1.0.2" }, @@ -36364,7 +35298,6 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", "integrity": "sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -36372,8 +35305,7 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "node_modules/merge-stream": { "version": "2.0.0", @@ -36384,7 +35316,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "engines": { "node": ">= 8" } @@ -36392,8 +35323,7 @@ "node_modules/metaviewport-parser": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/metaviewport-parser/-/metaviewport-parser-0.3.0.tgz", - "integrity": "sha512-EoYJ8xfjQ6kpe9VbVHvZTZHiOl4HL1Z18CrZ+qahvLXT7ZO4YTC2JMyt5FaUp9JJp6J4Ybb/z7IsCXZt86/QkQ==", - "dev": true + "integrity": "sha512-EoYJ8xfjQ6kpe9VbVHvZTZHiOl4HL1Z18CrZ+qahvLXT7ZO4YTC2JMyt5FaUp9JJp6J4Ybb/z7IsCXZt86/QkQ==" }, "node_modules/method-override": { "version": "3.0.0", @@ -36423,7 +35353,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -36906,7 +35835,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "dev": true, "bin": { "mime": "cli.js" }, @@ -36946,7 +35874,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, "engines": { "node": ">=4" } @@ -36955,7 +35882,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, "engines": { "node": ">=4" } @@ -36964,7 +35890,6 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.1.tgz", "integrity": "sha512-CRC6E2yedNjfOA3nQjpqAkpnranxhxmilhBPYtldnXcPT/QZb3aJFzvt0pp8W1jhuLR/E0zDa+QEHuC/HhhaLQ==", - "dev": true, "dependencies": { "schema-utils": "^4.0.0" }, @@ -36983,7 +35908,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -37000,7 +35924,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -37011,14 +35934,12 @@ "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -37036,8 +35957,7 @@ "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", @@ -37068,7 +35988,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, "dependencies": { "arrify": "^1.0.1", "is-plain-obj": "^1.1.0", @@ -37082,7 +36001,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -37243,8 +36161,7 @@ "node_modules/mitt": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", - "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==", - "dev": true + "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==" }, "node_modules/mixin-deep": { "version": "1.3.2", @@ -37287,7 +36204,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", "integrity": "sha512-ALGF1Jt9ouehcaXaHhn6t1yGWRqGaHkPFndtFVHfZXOvkIZ/yoGaSi0AHVTafb3ZBGg4dr/bDwnaEKqCXzchMA==", - "dev": true, "dependencies": { "for-in": "^0.1.3", "is-extendable": "^0.1.1" @@ -37300,7 +36216,6 @@ "version": "0.1.8", "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", "integrity": "sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -37323,8 +36238,7 @@ "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "node_modules/mock-match-media": { "version": "0.4.2", @@ -37601,7 +36515,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", - "dev": true, "engines": { "node": ">=10" } @@ -37615,7 +36528,6 @@ "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, "dependencies": { "dns-packet": "^5.2.2", "thunky": "^1.0.2" @@ -37665,7 +36577,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.0.0.tgz", "integrity": "sha512-FJgjyX/IVkbXBXYUwH+OYwQKqWpFPLaLVESd70yHjSDunwzV2hZOoTBvPf4KLoxesUzzyfTH6F784Uqd7Wm5yA==", - "dev": true, "bin": { "mustache": "bin/mustache" }, @@ -37676,8 +36587,7 @@ "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, "node_modules/mv": { "version": "2.1.1", @@ -37795,8 +36705,7 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, "node_modules/ncp": { "version": "2.0.0", @@ -37824,7 +36733,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, "engines": { "node": ">= 0.4.0" } @@ -37951,7 +36859,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, "engines": { "node": ">= 6.13.0" } @@ -38120,7 +37027,6 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -38131,14 +37037,12 @@ "node_modules/normalize-package-data/node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" }, "node_modules/normalize-package-data/node_modules/semver": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "bin": { "semver": "bin/semver" } @@ -38155,7 +37059,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -38164,7 +37067,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, "engines": { "node": ">=10" }, @@ -38181,7 +37083,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", - "dev": true, "dependencies": { "npm-normalize-package-bin": "^1.0.1" } @@ -38201,14 +37102,12 @@ "node_modules/npm-normalize-package-bin": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", - "dev": true + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" }, "node_modules/npm-package-arg": { "version": "8.1.5", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", - "dev": true, "dependencies": { "hosted-git-info": "^4.0.1", "semver": "^7.3.4", @@ -38222,7 +37121,6 @@ "version": "6.4.0", "resolved": "https://registry.npmjs.org/npm-package-json-lint/-/npm-package-json-lint-6.4.0.tgz", "integrity": "sha512-cuXAJJB1Rdqz0UO6w524matlBqDBjcNt7Ru+RDIu4y6RI1gVqiWBnylrK8sPRk81gGBA0X8hJbDXolVOoTc+sA==", - "dev": true, "dependencies": { "ajv": "^6.12.6", "ajv-errors": "^1.0.1", @@ -38254,7 +37152,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -38269,14 +37166,12 @@ "node_modules/npm-package-json-lint/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/npm-package-json-lint/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -38292,7 +37187,6 @@ "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -38318,7 +37212,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -38327,7 +37220,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -38339,14 +37231,12 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true, "license": "MIT" }, "node_modules/npm-package-json-lint/node_modules/meow": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "dev": true, "dependencies": { "@types/minimist": "^1.2.0", "camelcase-keys": "^6.2.2", @@ -38372,7 +37262,6 @@ "version": "0.18.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, "engines": { "node": ">=10" }, @@ -38384,7 +37273,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, "dependencies": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", @@ -38399,7 +37287,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -38408,7 +37295,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -38420,7 +37306,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -38432,7 +37317,6 @@ "version": "3.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true, "engines": { "node": ">=14.16" }, @@ -38444,7 +37328,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", - "dev": true, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -38453,7 +37336,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-3.0.0.tgz", "integrity": "sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ==", - "dev": true, "dependencies": { "glob": "^7.1.6", "ignore-walk": "^4.0.1", @@ -38471,7 +37353,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -38819,8 +37700,7 @@ "node_modules/nwsapi": { "version": "2.2.13", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", - "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", - "dev": true + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==" }, "node_modules/nx": { "version": "16.6.0", @@ -39553,14 +38433,12 @@ "node_modules/object-filter": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/object-filter/-/object-filter-1.0.2.tgz", - "integrity": "sha512-NahvP2vZcy1ZiiYah30CEPw0FpDcSkSePJBMpzl5EQgCmISijiGuJm3SPYp7U+Lf2TljyaIw3E5EgkEx/TNEVA==", - "dev": true + "integrity": "sha512-NahvP2vZcy1ZiiYah30CEPw0FpDcSkSePJBMpzl5EQgCmISijiGuJm3SPYp7U+Lf2TljyaIw3E5EgkEx/TNEVA==" }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -39585,7 +38463,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -39606,7 +38483,6 @@ "version": "4.1.4", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -39624,7 +38500,6 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -39638,7 +38513,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -39655,7 +38529,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.0.tgz", "integrity": "sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg==", - "dev": true, "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.19.1" @@ -39680,7 +38553,6 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -39702,8 +38574,7 @@ "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" }, "node_modules/octokit-pagination-methods": { "version": "1.1.0", @@ -39786,7 +38657,6 @@ "version": "1.5.2", "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true, "bin": { "opener": "bin/opener-bin.js" } @@ -39795,7 +38665,6 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha512-oCOQ8AIC2ciLy/sE2ehafRBleBgDLvzGhBRRev87sP7ovnbvQfqpc3XFI0DhHey2OfVoNV91W+GPC6B3540/5Q==", - "dev": true, "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.4", @@ -39812,7 +38681,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/ora/-/ora-4.1.1.tgz", "integrity": "sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A==", - "dev": true, "dependencies": { "chalk": "^3.0.0", "cli-cursor": "^3.1.0", @@ -39834,7 +38702,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -39847,7 +38714,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, "dependencies": { "restore-cursor": "^3.1.0" }, @@ -39859,7 +38725,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -39868,7 +38733,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", - "dev": true, "dependencies": { "chalk": "^2.4.2" }, @@ -39880,7 +38744,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -39892,7 +38755,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -39906,7 +38768,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "engines": { "node": ">=4" } @@ -39915,7 +38776,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -39927,7 +38787,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -39936,7 +38795,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -39951,7 +38809,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -39964,7 +38821,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -39982,7 +38838,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -40004,7 +38859,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -40013,7 +38867,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, "engines": { "node": ">=8" } @@ -40045,7 +38898,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, "dependencies": { "p-limit": "^1.1.0" }, @@ -40057,7 +38909,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, "dependencies": { "p-try": "^1.0.0" }, @@ -40130,7 +38981,6 @@ "version": "4.6.1", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", - "dev": true, "dependencies": { "@types/retry": "^0.12.0", "retry": "^0.13.1" @@ -40143,7 +38993,6 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, "engines": { "node": ">= 4" } @@ -40164,7 +39013,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, "engines": { "node": ">=4" } @@ -40188,7 +39036,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", - "dev": true, "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.0.2", @@ -40207,7 +39054,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, "dependencies": { "debug": "^4.3.4" }, @@ -40219,7 +39065,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -40232,7 +39077,6 @@ "version": "7.0.5", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -40246,7 +39090,6 @@ "version": "8.0.4", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.1", @@ -40261,7 +39104,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", - "dev": true, "dependencies": { "degenerator": "^5.0.0", "ip": "^1.1.8", @@ -40635,14 +39477,12 @@ "node_modules/parse-cache-control": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", - "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", - "dev": true + "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==" }, "node_modules/parse-entities": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", - "dev": true, "dependencies": { "character-entities": "^1.0.0", "character-entities-legacy": "^1.0.0", @@ -40682,7 +39522,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -40709,7 +39548,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, "dependencies": { "entities": "^4.4.0" }, @@ -40721,7 +39559,6 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, "engines": { "node": ">=0.12" }, @@ -40993,9 +39830,9 @@ } }, "node_modules/patch-package/node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", "dev": true, "license": "ISC", "bin": { @@ -41046,8 +39883,7 @@ "node_modules/path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", - "dev": true + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==" }, "node_modules/path-key": { "version": "2.0.1", @@ -41100,8 +39936,7 @@ "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/path-type": { "version": "3.0.0", @@ -41171,8 +40006,7 @@ "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" }, "node_modules/phpegjs": { "version": "1.0.0-beta7", @@ -41215,7 +40049,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -41224,7 +40057,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -41233,7 +40065,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", - "dev": true, "dependencies": { "pinkie": "^2.0.0" }, @@ -41253,7 +40084,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", "integrity": "sha512-ojakdnUgL5pzJYWw2AIDEupaQCX5OPbM688ZevubICjdIX01PRSYKqm33fJoCOJBRseYCTUlQRnBNX+Pchaejw==", - "dev": true, "dependencies": { "find-up": "^2.1.0" }, @@ -41324,7 +40154,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz", "integrity": "sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==", - "dev": true, "dependencies": { "irregular-plurals": "^3.2.0" }, @@ -41397,7 +40226,6 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", - "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.11", "postcss-value-parser": "^4.2.0" @@ -41412,14 +40240,12 @@ "node_modules/postcss-calc/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-colormin": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.0.0.tgz", "integrity": "sha512-EuO+bAUmutWoZYgHn2T1dG1pPqHU6L4TjzPlu4t1wZGXQ/fxV16xg2EJmYi0z+6r+MGV1yvpx1BHkUaRrPa2bw==", - "dev": true, "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0", @@ -41436,14 +40262,12 @@ "node_modules/postcss-colormin/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-convert-values": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.0.0.tgz", "integrity": "sha512-U5D8QhVwqT++ecmy8rnTb+RL9n/B806UVaS3m60lqle4YDFcpbS3ae5bTQIh3wOGUSDHSEtMYLs/38dNG7EYFw==", - "dev": true, "dependencies": { "browserslist": "^4.21.4", "postcss-value-parser": "^4.2.0" @@ -41458,14 +40282,12 @@ "node_modules/postcss-convert-values/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-discard-comments": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.0.tgz", "integrity": "sha512-p2skSGqzPMZkEQvJsgnkBhCn8gI7NzRH2683EEjrIkoMiwRELx68yoUJ3q3DGSGuQ8Ug9Gsn+OuDr46yfO+eFw==", - "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -41477,7 +40299,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.0.tgz", "integrity": "sha512-bU1SXIizMLtDW4oSsi5C/xHKbhLlhek/0/yCnoMQany9k3nPBq+Ctsv/9oMmyqbR96HYHxZcHyK2HR5P/mqoGA==", - "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -41489,7 +40310,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.0.tgz", "integrity": "sha512-b+h1S1VT6dNhpcg+LpyiUrdnEZfICF0my7HAKgJixJLW7BnNmpRH34+uw/etf5AhOlIhIAuXApSzzDzMI9K/gQ==", - "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -41501,7 +40321,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.0.tgz", "integrity": "sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw==", - "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -41513,7 +40332,6 @@ "version": "16.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz", "integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -41529,14 +40347,12 @@ "node_modules/postcss-import/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-loader": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", - "dev": true, "dependencies": { "cosmiconfig": "^7.0.0", "klona": "^2.0.5", @@ -41569,14 +40385,12 @@ "node_modules/postcss-media-query-parser": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", - "dev": true + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==" }, "node_modules/postcss-merge-longhand": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.0.tgz", "integrity": "sha512-4VSfd1lvGkLTLYcxFuISDtWUfFS4zXe0FpF149AyziftPFQIWxjvFSKhA4MIxMe4XM3yTDgQMbSNgzIVxChbIg==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0", "stylehacks": "^6.0.0" @@ -41591,14 +40405,12 @@ "node_modules/postcss-merge-longhand/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-merge-rules": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.0.1.tgz", "integrity": "sha512-a4tlmJIQo9SCjcfiCcCMg/ZCEe0XTkl/xK0XHBs955GWg9xDX3NwP9pwZ78QUOWB8/0XCjZeJn98Dae0zg6AAw==", - "dev": true, "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0", @@ -41616,7 +40428,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.0.0.tgz", "integrity": "sha512-zNRAVtyh5E8ndZEYXA4WS8ZYsAp798HiIQ1V2UF/C/munLp2r1UGHwf1+6JFu7hdEhJFN+W1WJQKBrtjhFgEnA==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41630,14 +40441,12 @@ "node_modules/postcss-minify-font-values/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-minify-gradients": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.0.tgz", "integrity": "sha512-wO0F6YfVAR+K1xVxF53ueZJza3L+R3E6cp0VwuXJQejnNUH0DjcAFe3JEBeTY1dLwGa0NlDWueCA1VlEfiKgAA==", - "dev": true, "dependencies": { "colord": "^2.9.1", "cssnano-utils": "^4.0.0", @@ -41653,14 +40462,12 @@ "node_modules/postcss-minify-gradients/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-minify-params": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.0.0.tgz", "integrity": "sha512-Fz/wMQDveiS0n5JPcvsMeyNXOIMrwF88n7196puSuQSWSa+/Ofc1gDOSY2xi8+A4PqB5dlYCKk/WfqKqsI+ReQ==", - "dev": true, "dependencies": { "browserslist": "^4.21.4", "cssnano-utils": "^4.0.0", @@ -41676,14 +40483,12 @@ "node_modules/postcss-minify-params/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-minify-selectors": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.0.tgz", "integrity": "sha512-ec/q9JNCOC2CRDNnypipGfOhbYPuUkewGwLnbv6omue/PSASbHSU7s6uSQ0tcFRVv731oMIx8k0SP4ZX6be/0g==", - "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.5" }, @@ -41698,7 +40503,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, "engines": { "node": "^10 || ^12 || >= 14" }, @@ -41710,7 +40514,6 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", - "dev": true, "dependencies": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^6.0.2", @@ -41726,14 +40529,12 @@ "node_modules/postcss-modules-local-by-default/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-modules-scope": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", - "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.4" }, @@ -41748,7 +40549,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, "dependencies": { "icss-utils": "^5.0.0" }, @@ -41763,7 +40563,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.0.tgz", "integrity": "sha512-cqundwChbu8yO/gSWkuFDmKrCZ2vJzDAocheT2JTd0sFNA4HMGoKMfbk2B+J0OmO0t5GUkiAkSM5yF2rSLUjgQ==", - "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -41775,7 +40574,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.0.tgz", "integrity": "sha512-Qyt5kMrvy7dJRO3OjF7zkotGfuYALETZE+4lk66sziWSPzlBEt7FrUshV6VLECkI4EN8Z863O6Nci4NXQGNzYw==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41789,14 +40587,12 @@ "node_modules/postcss-normalize-display-values/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-normalize-positions": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.0.tgz", "integrity": "sha512-mPCzhSV8+30FZyWhxi6UoVRYd3ZBJgTRly4hOkaSifo0H+pjDYcii/aVT4YE6QpOil15a5uiv6ftnY3rm0igPg==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41810,14 +40606,12 @@ "node_modules/postcss-normalize-positions/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-normalize-repeat-style": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.0.tgz", "integrity": "sha512-50W5JWEBiOOAez2AKBh4kRFm2uhrT3O1Uwdxz7k24aKtbD83vqmcVG7zoIwo6xI2FZ/HDlbrCopXhLeTpQib1A==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41831,14 +40625,12 @@ "node_modules/postcss-normalize-repeat-style/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-normalize-string": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.0.tgz", "integrity": "sha512-KWkIB7TrPOiqb8ZZz6homet2KWKJwIlysF5ICPZrXAylGe2hzX/HSf4NTX2rRPJMAtlRsj/yfkrWGavFuB+c0w==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41852,14 +40644,12 @@ "node_modules/postcss-normalize-string/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-normalize-timing-functions": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.0.tgz", "integrity": "sha512-tpIXWciXBp5CiFs8sem90IWlw76FV4oi6QEWfQwyeREVwUy39VSeSqjAT7X0Qw650yAimYW5gkl2Gd871N5SQg==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41873,14 +40663,12 @@ "node_modules/postcss-normalize-timing-functions/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-normalize-unicode": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.0.tgz", "integrity": "sha512-ui5crYkb5ubEUDugDc786L/Me+DXp2dLg3fVJbqyAl0VPkAeALyAijF2zOsnZyaS1HyfPuMH0DwyY18VMFVNkg==", - "dev": true, "dependencies": { "browserslist": "^4.21.4", "postcss-value-parser": "^4.2.0" @@ -41895,14 +40683,12 @@ "node_modules/postcss-normalize-unicode/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-normalize-url": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.0.tgz", "integrity": "sha512-98mvh2QzIPbb02YDIrYvAg4OUzGH7s1ZgHlD3fIdTHLgPLRpv1ZTKJDnSAKr4Rt21ZQFzwhGMXxpXlfrUBKFHw==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41916,14 +40702,12 @@ "node_modules/postcss-normalize-url/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-normalize-whitespace": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.0.tgz", "integrity": "sha512-7cfE1AyLiK0+ZBG6FmLziJzqQCpTQY+8XjMhMAz8WSBSCsCNNUKujgIgjCAmDT3cJ+3zjTXFkoD15ZPsckArVw==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41937,14 +40721,12 @@ "node_modules/postcss-normalize-whitespace/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-ordered-values": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.0.tgz", "integrity": "sha512-K36XzUDpvfG/nWkjs6d1hRBydeIxGpKS2+n+ywlKPzx1nMYDYpoGbcjhj5AwVYJK1qV2/SDoDEnHzlPD6s3nMg==", - "dev": true, "dependencies": { "cssnano-utils": "^4.0.0", "postcss-value-parser": "^4.2.0" @@ -41959,8 +40741,7 @@ "node_modules/postcss-ordered-values/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-prefix-selector": { "version": "1.16.1", @@ -41975,7 +40756,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz", "integrity": "sha512-s2UOnidpVuXu6JiiI5U+fV2jamAw5YNA9Fdi/GRK0zLDLCfXmSGqQtzpUPtfN66RtCbb9fFHoyZdQaxOB3WxVA==", - "dev": true, "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0" @@ -41991,7 +40771,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.0.tgz", "integrity": "sha512-FQ9f6xM1homnuy1wLe9lP1wujzxnwt1EwiigtWwuyf8FsqqXUDUp2Ulxf9A5yjlUOTdCJO6lonYjg1mgqIIi2w==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -42005,20 +40784,17 @@ "node_modules/postcss-reduce-transforms/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-resolve-nested-selector": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", - "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", - "dev": true + "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==" }, "node_modules/postcss-safe-parser": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.0.tgz", "integrity": "sha512-ovehqRNVCpuFzbXoTb4qLtyzK3xn3t/CUBxOs8LsnQjQrShaB4lKiHoVqY8ANaC0hBMHq5QVWk77rwGklFUDrg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -42044,7 +40820,6 @@ "version": "4.0.9", "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", - "dev": true, "funding": [ { "type": "opencollective", @@ -42070,7 +40845,6 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -42083,7 +40857,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.0.tgz", "integrity": "sha512-r9zvj/wGAoAIodn84dR/kFqwhINp5YsJkLoujybWG59grR/IHx+uQ2Zo+IcOwM0jskfYX3R0mo+1Kip1VSNcvw==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0", "svgo": "^3.0.2" @@ -42098,14 +40871,12 @@ "node_modules/postcss-svgo/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-unique-selectors": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.0.tgz", "integrity": "sha512-EPQzpZNxOxP7777t73RQpZE5e9TrnCrkvp7AH7a0l89JmZiPnS82y216JowHXwpBCQitfyxrof9TK3rYbi7/Yw==", - "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.5" }, @@ -42183,7 +40954,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, "engines": { "node": ">= 0.8.0" } @@ -42193,7 +40963,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/wp-prettier/-/wp-prettier-3.0.3.tgz", "integrity": "sha512-X4UlrxDTH8oom9qXlcjnydsjAOD2BmB6yFmvS4Z2zdTzqqpRWb+fbqrH412+l+OUXmbzJlSXjlMFYPgYG12IAA==", - "dev": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -42208,7 +40977,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, "dependencies": { "fast-diff": "^1.1.2" }, @@ -42291,7 +41059,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -42376,7 +41143,6 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -42389,7 +41155,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.0.tgz", "integrity": "sha512-0LdR757eTj/JfuU7TL2YCuAZnxWXu3tkJbg4Oq3geW/qFNT/32T0sp2HnZ9O0lMR4q3vwAt0+xCA8SR0WAD0og==", - "dev": true, "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", @@ -42408,7 +41173,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, "dependencies": { "debug": "^4.3.4" }, @@ -42420,7 +41184,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -42433,7 +41196,6 @@ "version": "7.0.5", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -42447,7 +41209,6 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, "engines": { "node": ">=12" } @@ -42456,7 +41217,6 @@ "version": "8.0.4", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.1", @@ -42470,8 +41230,7 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/prr": { "version": "1.0.1", @@ -42483,7 +41242,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/ps-list/-/ps-list-8.1.1.tgz", "integrity": "sha512-OPS9kEJYVmiO48u/B9qneqhkMvgCxT+Tm28VCEJpheTpl8cJ0ffZRRNgS5mrQRTrX5yRTpaJ+hRDeefXYmmorQ==", - "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -42494,8 +41252,7 @@ "node_modules/pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" }, "node_modules/public-encrypt": { "version": "4.0.3", @@ -42550,7 +41307,6 @@ "version": "23.1.0", "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.1.0.tgz", "integrity": "sha512-SvAsu+xnLN2FMXE/59bp3s3WXp8ewqUGzVV4AQtml/2xmsciZnU/bXcCW+eETHPWQ6Agg2vTI7QzWXPpEARK2g==", - "dev": true, "license": "Apache-2.0", "dependencies": { "@puppeteer/browsers": "2.3.1", @@ -42568,7 +41324,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.1.tgz", "integrity": "sha512-uK7o3hHkK+naEobMSJ+2ySYyXtQkBxIH8Gn4MK9ciePjNV+Pf+PgY/W7iPzn2MTjl3stcYB5AlcTmPYw7AXDwA==", - "dev": true, "license": "Apache-2.0", "dependencies": { "debug": "^4.3.6", @@ -42591,7 +41346,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, "license": "MIT", "dependencies": { "debug": "^4.3.4" @@ -42604,7 +41358,6 @@ "version": "0.6.4", "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.4.tgz", "integrity": "sha512-8zoq6ogmhQQkAKZVKO2ObFTl4uOkqoX1PlKQX3hZQ5E9cbUotcAb7h4pTNVAGGv8Z36PF3CtdOriEp/Rz82JqQ==", - "dev": true, "license": "Apache-2.0", "dependencies": { "mitt": "3.0.1", @@ -42619,7 +41372,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -42634,7 +41386,6 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -42652,14 +41403,12 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/puppeteer-core/node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "debug": "^4.1.1", @@ -42680,7 +41429,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.0", @@ -42694,7 +41442,6 @@ "version": "7.0.5", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -42708,7 +41455,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -42718,7 +41464,6 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -42728,21 +41473,18 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", - "dev": true, "license": "MIT" }, "node_modules/puppeteer-core/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/puppeteer-core/node_modules/proxy-agent": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -42762,7 +41504,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -42773,7 +41514,6 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -42786,7 +41526,6 @@ "version": "8.0.4", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.1", @@ -42801,7 +41540,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -42816,7 +41554,6 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", - "dev": true, "license": "MIT", "dependencies": { "pump": "^3.0.0", @@ -42831,7 +41568,6 @@ "version": "3.1.7", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, "license": "MIT", "dependencies": { "b4a": "^1.6.4", @@ -42843,7 +41579,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -42861,7 +41596,6 @@ "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -42883,7 +41617,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -42893,7 +41626,6 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "license": "MIT", "dependencies": { "cliui": "^8.0.1", @@ -42912,7 +41644,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -42922,7 +41653,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", - "dev": true, "funding": [ { "type": "individual", @@ -42938,7 +41668,6 @@ "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, "dependencies": { "side-channel": "^1.0.4" }, @@ -43020,14 +41749,12 @@ "node_modules/queue-tick": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", - "dev": true + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" }, "node_modules/quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, "engines": { "node": ">=8" } @@ -43072,7 +41799,6 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dev": true, "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -43087,7 +41813,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -43096,7 +41821,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -43882,7 +42606,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, "dependencies": { "pify": "^2.3.0" } @@ -44072,7 +42795,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", @@ -44087,7 +42809,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, "dependencies": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", @@ -44104,7 +42825,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -44117,7 +42837,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -44129,7 +42848,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -44144,7 +42862,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -44156,7 +42873,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "engines": { "node": ">=6" } @@ -44165,7 +42881,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -44174,7 +42889,6 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, "engines": { "node": ">=8" } @@ -44236,7 +42950,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -44289,7 +43002,6 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, "dependencies": { "resolve": "^1.20.0" }, @@ -44301,7 +43013,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" @@ -44314,7 +43025,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, "engines": { "node": ">=8" } @@ -44354,7 +43064,6 @@ "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, "dependencies": { "@babel/runtime": "^7.8.4" } @@ -44376,7 +43085,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -44393,7 +43101,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, "engines": { "node": ">=8" }, @@ -44449,7 +43156,6 @@ "version": "10.0.1", "resolved": "https://registry.npmjs.org/remark/-/remark-10.0.1.tgz", "integrity": "sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ==", - "dev": true, "dependencies": { "remark-parse": "^6.0.0", "remark-stringify": "^6.0.0", @@ -44516,7 +43222,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-6.0.3.tgz", "integrity": "sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg==", - "dev": true, "dependencies": { "collapse-white-space": "^1.0.2", "is-alphabetical": "^1.0.0", @@ -44593,7 +43298,6 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-6.0.4.tgz", "integrity": "sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg==", - "dev": true, "dependencies": { "ccount": "^1.0.0", "is-alphanumeric": "^1.0.0", @@ -44734,7 +43438,6 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "dev": true, "engines": { "node": ">=0.10" } @@ -44743,7 +43446,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", "integrity": "sha512-vuNYXC7gG7IeVNBC1xUllqCcZKRbJoSPOBhnTEcAIiKCsbuef6zO3F0Rve3isPMMoNoQRWjQwbAgAjHUHniyEA==", - "dev": true, "engines": { "node": ">= 0.10" } @@ -44765,7 +43467,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -44779,7 +43480,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", - "dev": true, "engines": { "node": ">=0.10.5" } @@ -44787,8 +43487,7 @@ "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "node_modules/resize-observer-polyfill": { "version": "1.5.1", @@ -44815,14 +43514,12 @@ "node_modules/resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" }, "node_modules/resolve-bin": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/resolve-bin/-/resolve-bin-0.4.0.tgz", "integrity": "sha1-RxMiSYkRAa+xmZH+k3ywpfBy5dk=", - "dev": true, "dependencies": { "find-parent-dir": "~0.3.0" } @@ -44831,7 +43528,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, "dependencies": { "resolve-from": "^5.0.0" }, @@ -44843,7 +43539,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, "engines": { "node": ">=8" } @@ -44852,7 +43547,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", "integrity": "sha512-QxMPqI6le2u0dCLyiGzgy92kjkkL6zO0XyvHzjdTNH3zM6e5Hz3BwG6+aEyNgiQ5Xz6PwTwgQEj3U50dByPKIA==", - "dev": true, "dependencies": { "expand-tilde": "^1.2.2", "global-modules": "^0.2.3" @@ -44865,7 +43559,6 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", "integrity": "sha512-JeXuCbvYzYXcwE6acL9V2bAOeSIGl4dD+iwLY9iUx2VBJJ80R18HCn+JCwHM9Oegdfya3lEkGCdaRkSyc10hDA==", - "dev": true, "dependencies": { "global-prefix": "^0.1.4", "is-windows": "^0.2.0" @@ -44878,7 +43571,6 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", "integrity": "sha512-gOPiyxcD9dJGCEArAhF4Hd0BAqvAe/JzERP7tYumE4yIkmIedPUVXcJFWbV3/p/ovIIvKjkrTk+f1UVkq7vvbw==", - "dev": true, "dependencies": { "homedir-polyfill": "^1.0.0", "ini": "^1.3.4", @@ -44893,7 +43585,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", "integrity": "sha512-n67eJYmXbniZB7RF4I/FTjK1s6RPOCTxhYrVYLRaCt3lF0mpWZPKr3T2LSZAqyjQsxR2qMmGYXXzK0YWwcPM1Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -44916,7 +43607,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true, "engines": { "node": ">=10" } @@ -44925,7 +43615,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, "dependencies": { "lowercase-keys": "^2.0.0" }, @@ -44983,7 +43672,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -45042,7 +43730,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/robots-parser/-/robots-parser-3.0.1.tgz", "integrity": "sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ==", - "dev": true, "engines": { "node": ">=10.0.0" } @@ -45050,8 +43737,7 @@ "node_modules/rrweb-cssom": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", - "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", - "dev": true + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==" }, "node_modules/rtlcss": { "version": "4.0.0", @@ -45075,7 +43761,6 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/rtlcss-webpack-plugin/-/rtlcss-webpack-plugin-4.0.7.tgz", "integrity": "sha512-ouSbJtgcLBBQIsMgarxsDnfgRqm/AS4BKls/mz/Xb6HSl+PdEzefTR+Wz5uWQx4odoX0g261Z7yb3QBz0MTm0g==", - "dev": true, "dependencies": { "babel-runtime": "~6.25.0", "rtlcss": "^3.5.0" @@ -45085,7 +43770,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -45101,7 +43785,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -45116,7 +43799,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -45131,7 +43813,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -45140,7 +43821,6 @@ "version": "3.5.0", "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz", "integrity": "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==", - "dev": true, "dependencies": { "find-up": "^5.0.0", "picocolors": "^1.0.0", @@ -45155,7 +43835,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -45179,7 +43858,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dev": true, "dependencies": { "execa": "^5.0.0" }, @@ -45194,7 +43872,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -45208,7 +43885,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -45231,7 +43907,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, "engines": { "node": ">=10" }, @@ -45243,7 +43918,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, "engines": { "node": ">=10.17.0" } @@ -45252,7 +43926,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" }, @@ -45264,7 +43937,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -45273,7 +43945,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -45285,7 +43956,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -45300,7 +43970,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -45309,7 +43978,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -45321,7 +43989,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -45330,7 +43997,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -45345,7 +44011,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -45354,7 +44019,6 @@ "version": "1.2.10", "resolved": "https://registry.npmjs.org/run-con/-/run-con-1.2.10.tgz", "integrity": "sha512-n7PZpYmMM26ZO21dd8y3Yw1TRtGABjRtgPSgFS/nhzfvbJMXFtJhJVyEgayMiP+w/23craJjsnfDvx4W4ue/HQ==", - "dev": true, "dependencies": { "deep-extend": "^0.6.0", "ini": "~2.0.0", @@ -45369,7 +44033,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, "engines": { "node": ">=10" } @@ -45378,7 +44041,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -45401,8 +44063,7 @@ "node_modules/run-parallel": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", - "dev": true + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" }, "node_modules/run-queue": { "version": "1.0.3", @@ -45428,7 +44089,6 @@ "version": "6.6.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, "dependencies": { "tslib": "^1.9.0" }, @@ -45439,8 +44099,7 @@ "node_modules/rxjs/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/safaridriver": { "version": "0.1.0", @@ -45452,7 +44111,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.0", @@ -45469,8 +44127,7 @@ "node_modules/safe-array-concat/node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" }, "node_modules/safe-buffer": { "version": "5.1.2", @@ -45490,7 +44147,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.3", @@ -45527,7 +44183,6 @@ "version": "1.35.2", "resolved": "https://registry.npmjs.org/sass/-/sass-1.35.2.tgz", "integrity": "sha512-jhO5KAR+AMxCEwIH3v+4zbB2WB0z67V1X0jbapfVwQQdjHZUGUyukpnoM6+iCMfsIUC016w9OPKQ5jrNOS9uXw==", - "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0" }, @@ -45542,7 +44197,6 @@ "version": "12.1.0", "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.1.0.tgz", "integrity": "sha512-FVJZ9kxVRYNZTIe2xhw93n3xJNYZADr+q69/s98l9nTCrWASo+DR2Ot0s5xTKQDDEosUkatsGeHxcH4QBp5bSg==", - "dev": true, "dependencies": { "klona": "^2.0.4", "neo-async": "^2.6.2" @@ -45576,7 +44230,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, "dependencies": { "xmlchars": "^2.2.0" }, @@ -45636,14 +44289,12 @@ "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" }, "node_modules/selfsigned": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", - "dev": true, "dependencies": { "node-forge": "^1" }, @@ -45825,7 +44476,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dev": true, "dependencies": { "accepts": "~1.3.4", "batch": "0.6.1", @@ -45843,7 +44493,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "dependencies": { "ms": "2.0.0" } @@ -45852,7 +44501,6 @@ "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -45866,8 +44514,7 @@ "node_modules/serve-index/node_modules/setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, "node_modules/serve-static": { "version": "1.15.0", @@ -45892,7 +44539,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -46053,7 +44699,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, "dependencies": { "shebang-regex": "^1.0.0" }, @@ -46065,7 +44710,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -46261,7 +44905,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -46349,7 +44992,6 @@ "version": "3.24.0", "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.24.0.tgz", "integrity": "sha512-QqAKee9Twv+3k8IFOFfPB2hnk6as6Y6ACUpwCtQvRYBAes23Wv3SZlHVobAzqcE8gfsisCvPw3HGW3HYM+VYYw==", - "dev": true, "dependencies": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", @@ -46451,7 +45093,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", "integrity": "sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==", - "dev": true, "dependencies": { "@polka/url": "^1.0.0-next.20", "mrmime": "^1.0.0", @@ -46487,7 +45128,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -46647,7 +45287,6 @@ "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, "dependencies": { "faye-websocket": "^0.11.3", "uuid": "^8.3.2", @@ -46658,7 +45297,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -46667,7 +45305,6 @@ "version": "2.8.3", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", - "dev": true, "license": "MIT", "dependencies": { "ip-address": "^9.0.5", @@ -46696,7 +45333,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==", - "dev": true, "dependencies": { "is-plain-obj": "^1.0.0" }, @@ -46708,7 +45344,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -46731,7 +45366,6 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -46740,7 +45374,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.0.tgz", "integrity": "sha512-GKGWqWvYr04M7tn8dryIWvb0s8YM41z82iQv01yBtIylgxax0CwvSy6gc2Y02iuXwEfGWRlMicH0nvms9UZphw==", - "dev": true, "dependencies": { "abab": "^2.0.5", "iconv-lite": "^0.6.2", @@ -46805,7 +45438,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -46814,14 +45446,12 @@ "node_modules/spdx-exceptions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", - "dev": true + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -46830,14 +45460,12 @@ "node_modules/spdx-license-ids": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", - "dev": true + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" }, "node_modules/spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, "dependencies": { "debug": "^4.1.0", "handle-thing": "^2.0.0", @@ -46853,7 +45481,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, "dependencies": { "debug": "^4.1.0", "detect-node": "^2.0.4", @@ -46867,7 +45494,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -46890,7 +45516,6 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/speedline-core/-/speedline-core-1.4.3.tgz", "integrity": "sha512-DI7/OuAUD+GMpR6dmu8lliO2Wg5zfeh+/xsdyJZCzd8o5JgFUjCeLsBDuZjIQJdwXS3J0L/uZYrELKYqx+PXog==", - "dev": true, "dependencies": { "@types/node": "*", "image-ssim": "^0.2.0", @@ -47024,8 +45649,7 @@ "node_modules/state-toggle": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", - "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==", - "dev": true + "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==" }, "node_modules/static-extend": { "version": "0.1.2", @@ -47180,7 +45804,6 @@ "version": "2.15.1", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.1.tgz", "integrity": "sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==", - "dev": true, "dependencies": { "fast-fifo": "^1.1.0", "queue-tick": "^1.0.1" @@ -47215,7 +45838,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -47292,7 +45914,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -47328,7 +45949,6 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -47345,7 +45965,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -47359,7 +45978,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -47373,7 +45991,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "dev": true, "dependencies": { "character-entities-html4": "^1.0.0", "character-entities-legacy": "^1.0.0", @@ -47423,7 +46040,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, "engines": { "node": ">=8" } @@ -47449,7 +46065,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, "dependencies": { "min-indent": "^1.0.0" }, @@ -47473,7 +46088,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", - "dev": true, "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -47522,14 +46136,12 @@ "node_modules/style-search": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", - "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", - "dev": true + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==" }, "node_modules/stylehacks": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.0.0.tgz", "integrity": "sha512-+UT589qhHPwz6mTlCLSt/vMNTJx8dopeJlZAlBMJPWA3ORqu6wmQY7FBXf+qD+FsqoBJODyqNxOUP3jdntFRdw==", - "dev": true, "dependencies": { "browserslist": "^4.21.4", "postcss-selector-parser": "^6.0.4" @@ -47545,7 +46157,6 @@ "version": "16.8.2", "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.8.2.tgz", "integrity": "sha512-fInKATippQhcSm7AB+T32GpI+626yohrg33GkFT/5jzliUw5qhlwZq2UQQwgl3HsHrf09oeARi0ZwgY/UWEv9A==", - "dev": true, "funding": [ { "type": "opencollective", @@ -47607,20 +46218,17 @@ "node_modules/stylelint/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/stylelint/node_modules/balanced-match": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", - "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", - "dev": true + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==" }, "node_modules/stylelint/node_modules/cosmiconfig": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", - "dev": true, "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", @@ -47646,7 +46254,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -47659,7 +46266,6 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -47676,14 +46282,12 @@ "node_modules/stylelint/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/stylelint/node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -47699,7 +46303,6 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", - "dev": true, "license": "MIT", "dependencies": { "flat-cache": "^5.0.0" @@ -47712,7 +46315,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", - "dev": true, "dependencies": { "flatted": "^3.3.1", "keyv": "^4.5.4" @@ -47725,7 +46327,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -47737,7 +46338,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -47746,7 +46346,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, "engines": { "node": ">= 4" } @@ -47755,7 +46354,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -47764,7 +46362,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -47775,14 +46372,12 @@ "node_modules/stylelint/node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, "node_modules/stylelint/node_modules/meow": { "version": "13.2.0", "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", - "dev": true, "engines": { "node": ">=18" }, @@ -47794,14 +46389,12 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/stylelint/node_modules/postcss": { "version": "8.4.47", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -47829,14 +46422,12 @@ "node_modules/stylelint/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/stylelint/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, "engines": { "node": ">=8" } @@ -47845,7 +46436,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "engines": { "node": ">=14" }, @@ -47857,7 +46447,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -47867,7 +46456,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -47881,7 +46469,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -47893,7 +46480,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -47908,7 +46494,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -47921,7 +46506,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -47933,7 +46517,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz", "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==", - "dev": true, "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" @@ -47949,7 +46532,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^4.0.1" @@ -47983,7 +46565,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0", @@ -47997,7 +46578,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -48006,7 +46586,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -48028,20 +46607,17 @@ "node_modules/svg-parser": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", - "dev": true + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" }, "node_modules/svg-tags": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", - "dev": true + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==" }, "node_modules/svgo": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.2.tgz", "integrity": "sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ==", - "dev": true, "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", @@ -48065,7 +46641,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, "engines": { "node": ">= 10" } @@ -48074,7 +46649,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -48086,14 +46660,12 @@ "node_modules/svgo/node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, "node_modules/svgo/node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -48124,8 +46696,7 @@ "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "node_modules/synchronous-promise": { "version": "2.0.17", @@ -48137,7 +46708,6 @@ "version": "0.8.5", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", - "dev": true, "dependencies": { "@pkgr/utils": "^2.3.1", "tslib": "^2.5.0" @@ -48153,7 +46723,6 @@ "version": "6.8.2", "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", - "dev": true, "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", @@ -48169,7 +46738,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, "engines": { "node": ">=8" } @@ -48177,14 +46745,12 @@ "node_modules/table/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/table/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -48193,7 +46759,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -48210,7 +46775,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -48531,7 +47095,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.0.0.tgz", "integrity": "sha512-rdBAY35jUvVapqCuhehjenLbYY73cVgRQ6podD6u9EDBomBBHjCOtmq2InPgPpTysOIOsQ5PdBzwSC/sKjv6ew==", - "dev": true, "dependencies": { "ansi-escapes": "^4.2.1", "supports-hyperlinks": "^2.0.0" @@ -48561,7 +47124,6 @@ "version": "5.3.10", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", @@ -48595,7 +47157,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -48611,7 +47172,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -48620,7 +47180,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -48634,7 +47193,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -48652,7 +47210,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -48661,7 +47218,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -48673,9 +47229,9 @@ } }, "node_modules/terser/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -48693,7 +47249,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -48707,7 +47262,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -48741,14 +47295,12 @@ "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" }, "node_modules/third-party-web": { "version": "0.23.4", "resolved": "https://registry.npmjs.org/third-party-web/-/third-party-web-0.23.4.tgz", - "integrity": "sha512-kwYnSZRhEvv0SBW2fp8SBBKRglMoBjV8xz6C31m0ewqOtknB5UL+Ihg+M81hyFY5ldkZuGWPb+e4GVDkzf/gYg==", - "dev": true + "integrity": "sha512-kwYnSZRhEvv0SBW2fp8SBBKRglMoBjV8xz6C31m0ewqOtknB5UL+Ihg+M81hyFY5ldkZuGWPb+e4GVDkzf/gYg==" }, "node_modules/throat": { "version": "5.0.0", @@ -48758,8 +47310,7 @@ "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" }, "node_modules/through2": { "version": "2.0.5", @@ -48773,8 +47324,7 @@ "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" }, "node_modules/timers-browserify": { "version": "2.0.12", @@ -48803,7 +47353,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -48815,7 +47364,6 @@ "version": "6.1.50", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.50.tgz", "integrity": "sha512-q9GOap6q3KCsLMdOjXhWU5jVZ8/1dIib898JBRLsN+tBhENpBDcAVQbE0epADOjw11FhQQy9AcbqKGBQPUfTQA==", - "dev": true, "dependencies": { "tldts-core": "^6.1.50" }, @@ -48826,14 +47374,12 @@ "node_modules/tldts-core": { "version": "6.1.50", "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.50.tgz", - "integrity": "sha512-na2EcZqmdA2iV9zHV7OHQDxxdciEpxrjbkp+aHmZgnZKHzoElLajP59np5/4+sare9fQBfixgvXKx8ev1d7ytw==", - "dev": true + "integrity": "sha512-na2EcZqmdA2iV9zHV7OHQDxxdciEpxrjbkp+aHmZgnZKHzoElLajP59np5/4+sare9fQBfixgvXKx8ev1d7ytw==" }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -48930,7 +47476,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, "engines": { "node": ">=6" } @@ -48939,7 +47484,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", - "dev": true, "dependencies": { "tldts": "^6.1.32" }, @@ -48956,7 +47500,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, "bin": { "tree-kill": "cli.js" } @@ -48965,14 +47508,12 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==", - "deprecated": "Use String.prototype.trim() instead", - "dev": true + "deprecated": "Use String.prototype.trim() instead" }, "node_modules/trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true, "engines": { "node": ">=8" } @@ -48981,7 +47522,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", - "dev": true, "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -48992,8 +47532,7 @@ "node_modules/trim-trailing-lines": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", - "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==", - "dev": true + "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==" }, "node_modules/triple-beam": { "version": "1.4.1", @@ -49007,8 +47546,7 @@ "node_modules/trough": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz", - "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==", - "dev": true + "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==" }, "node_modules/truncate-utf8-bytes": { "version": "1.0.2", @@ -49023,7 +47561,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.2.tgz", "integrity": "sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==", - "dev": true, "engines": { "node": ">=16.13.0" }, @@ -49070,7 +47607,6 @@ "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -49082,7 +47618,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, "dependencies": { "minimist": "^1.2.0" }, @@ -49094,22 +47629,20 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, "engines": { "node": ">=4" } }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "license": "0BSD" }, "node_modules/tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, "dependencies": { "tslib": "^1.8.1" }, @@ -49123,8 +47656,7 @@ "node_modules/tsutils/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/tty-browserify": { "version": "0.0.0", @@ -49150,7 +47682,6 @@ "version": "0.0.6", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, "engines": { "node": ">=0.6.11 <=0.7.0 || >=0.7.3" } @@ -49172,7 +47703,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, "dependencies": { "prelude-ls": "~1.1.2" }, @@ -49192,7 +47722,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, "engines": { "node": ">=8" } @@ -49201,7 +47730,6 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -49214,7 +47742,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1", @@ -49228,7 +47755,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "for-each": "^0.3.3", @@ -49246,7 +47772,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", - "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", @@ -49265,7 +47790,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "for-each": "^0.3.3", @@ -49287,20 +47811,17 @@ "node_modules/typed-query-selector": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", - "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", - "dev": true + "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==" }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, "dependencies": { "is-typedarray": "^1.0.0" } @@ -49392,8 +47913,7 @@ "node_modules/uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" }, "node_modules/ufo": { "version": "1.4.0", @@ -49418,7 +47938,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -49433,7 +47952,6 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" @@ -49443,7 +47961,6 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "funding": [ { "type": "github", @@ -49467,7 +47984,6 @@ "version": "5.28.4", "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", - "dev": true, "license": "MIT", "dependencies": { "@fastify/busboy": "^2.0.0" @@ -49485,7 +48001,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", - "dev": true, "dependencies": { "inherits": "^2.0.1", "xtend": "^4.0.1" @@ -49535,7 +48050,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/unified/-/unified-7.1.0.tgz", "integrity": "sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==", - "dev": true, "dependencies": { "@types/unist": "^2.0.0", "@types/vfile": "^3.0.0", @@ -49551,7 +48065,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -49593,7 +48106,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, "dependencies": { "crypto-random-string": "^2.0.0" }, @@ -49604,14 +48116,12 @@ "node_modules/unist-util-is": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", - "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", - "dev": true + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==" }, "node_modules/unist-util-modify-children": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz", "integrity": "sha512-GRi04yhng1WqBf5RBzPkOtWAadcZS2gvuOgNn/cyJBYNxtTuyYqTKN0eg4rC1YJwGnzrqfRB3dSKm8cNCjNirg==", - "dev": true, "dependencies": { "array-iterate": "^1.0.0" } @@ -49620,7 +48130,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", - "dev": true, "dependencies": { "unist-util-visit": "^1.1.0" }, @@ -49632,14 +48141,12 @@ "node_modules/unist-util-stringify-position": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", - "dev": true + "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==" }, "node_modules/unist-util-visit": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", - "dev": true, "dependencies": { "unist-util-visit-parents": "^2.0.0" } @@ -49648,7 +48155,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", - "dev": true, "dependencies": { "unist-util-is": "^3.0.0" } @@ -49700,9 +48206,9 @@ } }, "node_modules/unplugin/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "dev": true, "license": "MIT", "bin": { @@ -49771,7 +48277,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, "engines": { "node": ">=8" } @@ -49860,7 +48365,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -49889,7 +48393,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", - "dev": true, "dependencies": { "loader-utils": "^2.0.0", "mime-types": "^2.1.27", @@ -49916,7 +48419,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -49932,7 +48434,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -49977,8 +48478,7 @@ "node_modules/urlpattern-polyfill": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", - "dev": true + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==" }, "node_modules/use": { "version": "3.1.1", @@ -50145,14 +48645,12 @@ "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" }, "node_modules/v8-to-istanbul": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", @@ -50166,7 +48664,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -50176,7 +48673,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", - "dev": true, "dependencies": { "builtins": "^1.0.3" } @@ -50199,7 +48695,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz", "integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==", - "dev": true, "dependencies": { "is-buffer": "^2.0.0", "replace-ext": "1.0.0", @@ -50211,7 +48706,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==", - "dev": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" @@ -50221,7 +48715,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", - "dev": true, "dependencies": { "unist-util-stringify-position": "^1.1.1" } @@ -50230,7 +48723,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, "funding": [ { "type": "github", @@ -50276,7 +48768,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "dev": true, "dependencies": { "xml-name-validator": "^5.0.0" }, @@ -50582,7 +49073,6 @@ "version": "1.7.3", "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, "dependencies": { "minimalistic-assert": "^1.0.0" } @@ -50651,9 +49141,9 @@ } }, "node_modules/webdriver/node_modules/@types/node": { - "version": "20.16.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", - "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", + "version": "20.16.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.12.tgz", + "integrity": "sha512-LfPFB0zOeCeCNQV3i+67rcoVvoN5n0NVuR2vLG0O5ySQMgchuZlC4lgz546ZOJyDtj5KIgOxy+lacOimfqZAIA==", "dev": true, "license": "MIT", "dependencies": { @@ -50882,9 +49372,9 @@ } }, "node_modules/webdriverio/node_modules/@types/node": { - "version": "20.16.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", - "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", + "version": "20.16.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.12.tgz", + "integrity": "sha512-LfPFB0zOeCeCNQV3i+67rcoVvoN5n0NVuR2vLG0O5ySQMgchuZlC4lgz546ZOJyDtj5KIgOxy+lacOimfqZAIA==", "dev": true, "license": "MIT", "dependencies": { @@ -51039,7 +49529,6 @@ "version": "5.95.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", - "dev": true, "dependencies": { "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", @@ -51085,7 +49574,6 @@ "version": "4.9.1", "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.9.1.tgz", "integrity": "sha512-jnd6EoYrf9yMxCyYDPj8eutJvtjQNp8PHmni/e/ulydHBWhT5J3menXt3HEkScsu9YqMAcG4CfFjs3rj5pVU1w==", - "dev": true, "dependencies": { "@discoveryjs/json-ext": "0.5.7", "acorn": "^8.0.4", @@ -51113,10 +49601,9 @@ } }, "node_modules/webpack-bundle-analyzer/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -51129,7 +49616,6 @@ "version": "8.3.4", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, "license": "MIT", "dependencies": { "acorn": "^8.11.0" @@ -51142,7 +49628,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, "engines": { "node": ">= 10" } @@ -51151,7 +49636,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -51163,7 +49647,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, "dependencies": { "duplexer": "^0.1.2" }, @@ -51178,7 +49661,6 @@ "version": "5.1.4", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", - "dev": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1", @@ -51222,14 +49704,12 @@ "node_modules/webpack-cli/node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" }, "node_modules/webpack-cli/node_modules/commander": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, "engines": { "node": ">=14" } @@ -51238,7 +49718,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -51252,7 +49731,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -51261,7 +49739,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -51273,7 +49750,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -51282,7 +49758,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -51385,7 +49860,6 @@ "version": "4.15.1", "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", - "dev": true, "dependencies": { "@types/bonjour": "^3.5.9", "@types/connect-history-api-fallback": "^1.3.5", @@ -51444,7 +49918,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -51461,7 +49934,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -51472,14 +49944,12 @@ "node_modules/webpack-dev-server/node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" }, "node_modules/webpack-dev-server/node_modules/ipaddr.js": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", - "dev": true, "engines": { "node": ">= 10" } @@ -51488,7 +49958,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -51499,14 +49968,12 @@ "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/webpack-dev-server/node_modules/open": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -51523,7 +49990,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -51542,7 +50008,6 @@ "version": "5.3.4", "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", - "dev": true, "dependencies": { "colorette": "^2.0.10", "memfs": "^3.4.3", @@ -51565,7 +50030,6 @@ "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -51598,7 +50062,6 @@ "version": "5.8.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", - "dev": true, "dependencies": { "clone-deep": "^4.0.1", "wildcard": "^2.0.0" @@ -51611,7 +50074,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -51626,7 +50088,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -51635,26 +50096,22 @@ "node_modules/webpack/node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/webpack/node_modules/@webassemblyjs/helper-buffer": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" }, "node_modules/webpack/node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "node_modules/webpack/node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -51666,7 +50123,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -51675,7 +50131,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -51683,14 +50138,12 @@ "node_modules/webpack/node_modules/@webassemblyjs/utf8": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "node_modules/webpack/node_modules/@webassemblyjs/wasm-edit": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -51706,7 +50159,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", @@ -51719,7 +50171,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -51731,7 +50182,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-api-error": "1.11.6", @@ -51745,17 +50195,15 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" } }, "node_modules/webpack/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -51768,7 +50216,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -51784,7 +50231,6 @@ "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -51798,7 +50244,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -51811,7 +50256,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, "engines": { "node": ">=6.11.5" } @@ -51820,7 +50264,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -51838,7 +50281,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -51847,7 +50289,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", - "dev": true, "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", @@ -51861,7 +50302,6 @@ "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, "dependencies": { "http-parser-js": ">=0.5.1", "safe-buffer": ">=5.1.0", @@ -51875,7 +50315,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -51884,7 +50323,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "dev": true, "dependencies": { "iconv-lite": "0.6.3" }, @@ -51901,7 +50339,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "dev": true, "engines": { "node": ">=18" } @@ -51940,7 +50377,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -51952,7 +50388,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -51988,7 +50423,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", - "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", @@ -52015,8 +50449,7 @@ "node_modules/wildcard": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" }, "node_modules/windows-release": { "version": "3.2.0", @@ -52176,7 +50609,6 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -52184,8 +50616,7 @@ "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" }, "node_modules/worker-farm": { "version": "1.7.0", @@ -52301,7 +50732,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", - "dev": true, "dependencies": { "detect-indent": "^5.0.0", "graceful-fs": "^4.1.15", @@ -52318,7 +50748,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, "dependencies": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -52331,7 +50760,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, "engines": { "node": ">=6" } @@ -52340,7 +50768,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "bin": { "semver": "bin/semver" } @@ -52349,7 +50776,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-4.0.0.tgz", "integrity": "sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==", - "dev": true, "dependencies": { "sort-keys": "^2.0.0", "type-fest": "^0.4.1", @@ -52363,7 +50789,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", - "dev": true, "engines": { "node": ">=6" } @@ -52392,14 +50817,12 @@ "node_modules/x-is-string": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", - "integrity": "sha512-GojqklwG8gpzOVEVki5KudKNoq7MbbjYZCbyWzEz7tyPA7eleiE0+ePwOWQQRb5fm86rD3S8Tc0tSFf3AOv50w==", - "dev": true + "integrity": "sha512-GojqklwG8gpzOVEVki5KudKNoq7MbbjYZCbyWzEz7tyPA7eleiE0+ePwOWQQRb5fm86rD3S8Tc0tSFf3AOv50w==" }, "node_modules/xdg-basedir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true, "engines": { "node": ">=8" } @@ -52414,7 +50837,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", - "dev": true, "engines": { "node": ">=18" } @@ -52431,8 +50853,7 @@ "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, "node_modules/xtend": { "version": "4.0.2", @@ -52500,8 +50921,7 @@ "node_modules/yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" }, "node_modules/yaml": { "version": "1.10.2", @@ -52533,7 +50953,6 @@ "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, "engines": { "node": ">=10" } @@ -52608,7 +51027,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" @@ -52682,7 +51100,6 @@ "version": "3.23.8", "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" @@ -52694,8 +51111,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/dom-ready": "file:../dom-ready", - "@wordpress/i18n": "file:../i18n" + "@wordpress/dom-ready": "*", + "@wordpress/i18n": "*" }, "engines": { "node": ">=18.12.0", @@ -52708,10 +51125,10 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/data": "file:../data", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/rich-text": "file:../rich-text", + "@wordpress/data": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/rich-text": "*", "uuid": "^9.0.1" }, "engines": { @@ -52736,8 +51153,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/i18n": "file:../i18n", - "@wordpress/url": "file:../url" + "@wordpress/i18n": "*", + "@wordpress/url": "*" }, "engines": { "node": ">=18.12.0", @@ -52759,7 +51176,6 @@ "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", "version": "5.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -52772,7 +51188,6 @@ "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", "version": "6.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "deepmerge": "^4.3.0", @@ -52790,7 +51205,6 @@ "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", "version": "8.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -52799,8 +51213,8 @@ "@babel/preset-env": "7.25.7", "@babel/preset-typescript": "7.25.7", "@babel/runtime": "7.25.7", - "@wordpress/browserslist-config": "file:../browserslist-config", - "@wordpress/warning": "file:../warning", + "@wordpress/browserslist-config": "*", + "@wordpress/warning": "*", "browserslist": "^4.21.10", "core-js": "^3.31.0", "react": "^18.3.0" @@ -52810,177 +51224,113 @@ "npm": ">=8.19.2" } }, - "packages/babel-preset-default/node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.7.tgz", - "integrity": "sha512-12xfNeKNH7jubQNm7PAkzlLwEmCs1tfuX3UjIw6vP6QXi+leKh6+LyC/+Ed4EIQermwd58wsyh070yjDHFlNGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "packages/babel-preset-default/node_modules/@babel/helper-create-class-features-plugin": { + "packages/babel-preset-default/node_modules/@babel/plugin-transform-class-static-block": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.7.tgz", - "integrity": "sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==", - "dev": true, + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.7.tgz", + "integrity": "sha512-rvUUtoVlkDWtDWxGAiiQj0aNktTPn3eFynBcMC2IhsXweehwgdI9ODe+XjWw515kEmv22sSOTp/rxIRuTiB7zg==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-member-expression-to-functions": "^7.25.7", - "@babel/helper-optimise-call-expression": "^7.25.7", - "@babel/helper-replace-supers": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", - "@babel/traverse": "^7.25.7", - "semver": "^6.3.1" + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "packages/babel-preset-default/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "@babel/core": "^7.12.0" } }, - "packages/babel-preset-default/node_modules/@babel/helper-member-expression-to-functions": { + "packages/babel-preset-default/node_modules/@babel/plugin-transform-dynamic-import": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.7.tgz", - "integrity": "sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==", - "dev": true, + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.7.tgz", + "integrity": "sha512-UvcLuual4h7/GfylKm2IAA3aph9rwvAM2XBA0uPKU3lca+Maai4jBjjEVUS568ld6kJcgbouuumCBhMd/Yz17w==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { "node": ">=6.9.0" - } - }, - "packages/babel-preset-default/node_modules/@babel/helper-optimise-call-expression": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.7.tgz", - "integrity": "sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.7" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/@babel/helper-replace-supers": { + "packages/babel-preset-default/node_modules/@babel/plugin-transform-json-strings": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.7.tgz", - "integrity": "sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==", - "dev": true, + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.7.tgz", + "integrity": "sha512-Ot43PrL9TEAiCe8C/2erAjXMeVSnE/BLEx6eyrKLNFCCw5jvhTHKyHxdI1pA0kz5njZRYAnMO2KObGqOCRDYSA==", "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.25.7", - "@babel/helper-optimise-call-expression": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "packages/babel-preset-default/node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.7.tgz", - "integrity": "sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" + "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "packages/babel-preset-default/node_modules/@babel/plugin-transform-logical-assignment-operators": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.7.tgz", - "integrity": "sha512-wxyWg2RYaSUYgmd9MR0FyRGyeOMQE/Uzr1wzd/g5cf5bwi9A4v6HFdDm7y1MgDtod/fLOSTZY6jDgV0xU9d5bA==", - "dev": true, + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.7.tgz", + "integrity": "sha512-iImzbA55BjiovLyG2bggWS+V+OLkaBorNvc/yJoeeDQGztknRnDdYfp2d/UPmunZYEnZi6Lg8QcTmNMHOB0lGA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "packages/babel-preset-default/node_modules/@babel/plugin-transform-nullish-coalescing-operator": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.7.tgz", - "integrity": "sha512-Xwg6tZpLxc4iQjorYsyGMyfJE7nP5MV8t/Ka58BgiA7Jw0fRqQNcANlLfdJ/yvBt9z9LD2We+BEkT7vLqZRWng==", - "dev": true, + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.7.tgz", + "integrity": "sha512-FbuJ63/4LEL32mIxrxwYaqjJxpbzxPVQj5a+Ebrc8JICV6YX8nE53jY+K0RZT3um56GoNWgkS2BQ/uLGTjtwfw==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", - "@babel/plugin-transform-optional-chaining": "^7.25.7" + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.13.0" + "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "packages/babel-preset-default/node_modules/@babel/plugin-transform-numeric-separator": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.7.tgz", - "integrity": "sha512-UVATLMidXrnH+GMUIuxq55nejlj02HP7F5ETyBONzP6G87fPBogG4CH6kxrSrdIuAjdwNO9VzyaYsrZPscWUrw==", - "dev": true, + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.7.tgz", + "integrity": "sha512-8CbutzSSh4hmD+jJHIA8vdTNk15kAzOnFLVVgBSMGr28rt85ouT01/rezMecks9pkU939wDInImwCKv4ahU4IA==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-syntax-import-assertions": { + "packages/babel-preset-default/node_modules/@babel/plugin-transform-object-rest-spread": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.7.tgz", - "integrity": "sha512-ZvZQRmME0zfJnDQnVBKYzHxXT7lYBB3Revz1GuS7oLXWMgqUPX4G+DDbT30ICClht9WKV34QVrZhSw6WdklwZQ==", - "dev": true, + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.7.tgz", + "integrity": "sha512-1JdVKPhD7Y5PvgfFy0Mv2brdrolzpzSoUq2pr6xsR+m+3viGGeHEokFKsCgOkbeFOQxfB1Vt2F0cPJLRpFI4Zg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -52989,14 +51339,14 @@ "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-syntax-import-attributes": { + "packages/babel-preset-default/node_modules/@babel/plugin-transform-optional-catch-binding": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", - "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", - "dev": true, + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.7.tgz", + "integrity": "sha512-m9obYBA39mDPN7lJzD5WkGGb0GO54PPLXsbcnj1Hyeu8mSRz7Gb4b1A6zxNX32ZuUySDK4G6it8SDFWD1nCnqg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -53005,14 +51355,15 @@ "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-syntax-typescript": { + "packages/babel-preset-default/node_modules/@babel/plugin-transform-optional-chaining": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.7.tgz", - "integrity": "sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==", - "dev": true, + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.7.tgz", + "integrity": "sha512-h39agClImgPWg4H8mYVAbD1qP9vClFbEjqoJmt87Zen8pjqK8FTPUwrOXAvqu5soytwxrLMd2fx2KSCp2CHcNg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -53021,14 +51372,16 @@ "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-arrow-functions": { + "packages/babel-preset-default/node_modules/@babel/plugin-transform-private-property-in-object": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.7.tgz", - "integrity": "sha512-EJN2mKxDwfOUCPxMO6MUI58RN3ganiRAG/MS/S3HfB6QFNjroAMelQo/gybyYq97WerCBAZoyrAoW8Tzdq2jWg==", - "dev": true, + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.7.tgz", + "integrity": "sha512-LzA5ESzBy7tqj00Yjey9yWfs3FKy4EmJyKOSWld144OxkTji81WWnUT8nkLUn+imN/zHL8ZQlOu/MTUAhHaX3g==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { "node": ">=6.9.0" @@ -53037,16 +51390,95 @@ "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-async-to-generator": { + "packages/babel-preset-default/node_modules/@babel/preset-env": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.7.tgz", - "integrity": "sha512-ZUCjAavsh5CESCmi/xCpX1qcCaAglzs/7tmuvoFnJgA1dM7gQplsguljoTg+Ru8WENpX89cQyAtWoaE0I3X3Pg==", - "dev": true, + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.7.tgz", + "integrity": "sha512-Gibz4OUdyNqqLj+7OAvBZxOD7CklCtMA5/j0JgUEwOnaRULsPDXmic2iKxL2DX2vQduPR5wH2hjZas/Vr/Oc0g==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.7", + "@babel/compat-data": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-remap-async-to-generator": "^7.25.7" + "@babel/helper-validator-option": "^7.25.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.25.7", + "@babel/plugin-syntax-import-attributes": "^7.25.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.25.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.7", + "@babel/plugin-transform-async-to-generator": "^7.25.7", + "@babel/plugin-transform-block-scoped-functions": "^7.25.7", + "@babel/plugin-transform-block-scoping": "^7.25.7", + "@babel/plugin-transform-class-properties": "^7.25.7", + "@babel/plugin-transform-class-static-block": "^7.25.7", + "@babel/plugin-transform-classes": "^7.25.7", + "@babel/plugin-transform-computed-properties": "^7.25.7", + "@babel/plugin-transform-destructuring": "^7.25.7", + "@babel/plugin-transform-dotall-regex": "^7.25.7", + "@babel/plugin-transform-duplicate-keys": "^7.25.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.7", + "@babel/plugin-transform-dynamic-import": "^7.25.7", + "@babel/plugin-transform-exponentiation-operator": "^7.25.7", + "@babel/plugin-transform-export-namespace-from": "^7.25.7", + "@babel/plugin-transform-for-of": "^7.25.7", + "@babel/plugin-transform-function-name": "^7.25.7", + "@babel/plugin-transform-json-strings": "^7.25.7", + "@babel/plugin-transform-literals": "^7.25.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.7", + "@babel/plugin-transform-member-expression-literals": "^7.25.7", + "@babel/plugin-transform-modules-amd": "^7.25.7", + "@babel/plugin-transform-modules-commonjs": "^7.25.7", + "@babel/plugin-transform-modules-systemjs": "^7.25.7", + "@babel/plugin-transform-modules-umd": "^7.25.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.7", + "@babel/plugin-transform-new-target": "^7.25.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.7", + "@babel/plugin-transform-numeric-separator": "^7.25.7", + "@babel/plugin-transform-object-rest-spread": "^7.25.7", + "@babel/plugin-transform-object-super": "^7.25.7", + "@babel/plugin-transform-optional-catch-binding": "^7.25.7", + "@babel/plugin-transform-optional-chaining": "^7.25.7", + "@babel/plugin-transform-parameters": "^7.25.7", + "@babel/plugin-transform-private-methods": "^7.25.7", + "@babel/plugin-transform-private-property-in-object": "^7.25.7", + "@babel/plugin-transform-property-literals": "^7.25.7", + "@babel/plugin-transform-regenerator": "^7.25.7", + "@babel/plugin-transform-reserved-words": "^7.25.7", + "@babel/plugin-transform-shorthand-properties": "^7.25.7", + "@babel/plugin-transform-spread": "^7.25.7", + "@babel/plugin-transform-sticky-regex": "^7.25.7", + "@babel/plugin-transform-template-literals": "^7.25.7", + "@babel/plugin-transform-typeof-symbol": "^7.25.7", + "@babel/plugin-transform-unicode-escapes": "^7.25.7", + "@babel/plugin-transform-unicode-property-regex": "^7.25.7", + "@babel/plugin-transform-unicode-regex": "^7.25.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.38.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -53055,1125 +51487,145 @@ "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.7.tgz", - "integrity": "sha512-xHttvIM9fvqW+0a3tZlYcZYSBpSWzGBFIt/sYG3tcdSzBB8ZeVgz2gBP7Df+sM0N1850jrviYSSeUuc+135dmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, + "packages/babel-preset-default/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "packages/base-styles": { + "name": "@wordpress/base-styles", + "version": "5.10.0", + "license": "GPL-2.0-or-later", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.12.0", + "npm": ">=8.19.2" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.7.tgz", - "integrity": "sha512-ZEPJSkVZaeTFG/m2PARwLZQ+OG0vFIhPlKHK/JdIMy8DbRJ/htz6LRrTFtdzxi9EHmcwbNPAKDnadpNSIW+Aow==", - "dev": true, - "license": "MIT", + "packages/blob": { + "name": "@wordpress/blob", + "version": "4.10.0", + "license": "GPL-2.0-or-later", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/runtime": "7.25.7" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.12.0", + "npm": ">=8.19.2" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-class-properties": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.7.tgz", - "integrity": "sha512-mhyfEW4gufjIqYFo9krXHJ3ElbFLIze5IDp+wQTxoPd+mwFb1NxatNAwmv8Q8Iuxv7Zc+q8EkiMQwc9IhyGf4g==", - "dev": true, - "license": "MIT", + "packages/block-directory": { + "name": "@wordpress/block-directory", + "version": "5.10.0", + "license": "GPL-2.0-or-later", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/runtime": "7.25.7", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/plugins": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", + "change-case": "^4.1.2", + "clsx": "^2.1.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.12.0", + "npm": ">=8.19.2" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.7.tgz", - "integrity": "sha512-rvUUtoVlkDWtDWxGAiiQj0aNktTPn3eFynBcMC2IhsXweehwgdI9ODe+XjWw515kEmv22sSOTp/rxIRuTiB7zg==", - "dev": true, - "license": "MIT", + "packages/block-editor": { + "name": "@wordpress/block-editor", + "version": "14.5.0", + "license": "GPL-2.0-or-later", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-class-static-block": "^7.14.5" + "@babel/runtime": "7.25.7", + "@emotion/react": "^11.7.1", + "@emotion/styled": "^11.6.0", + "@react-spring/web": "^9.4.5", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/block-serialization-default-parser": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/style-engine": "*", + "@wordpress/token-list": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", + "@wordpress/wordcount": "*", + "change-case": "^4.1.2", + "clsx": "^2.1.1", + "colord": "^2.7.0", + "deepmerge": "^4.3.0", + "diff": "^4.0.2", + "fast-deep-equal": "^3.1.3", + "memize": "^2.1.0", + "parsel-js": "^1.1.2", + "postcss": "^8.4.21", + "postcss-prefix-selector": "^1.16.0", + "postcss-urlrebase": "^1.4.0", + "react-autosize-textarea": "^7.1.0", + "react-easy-crop": "^5.0.6", + "remove-accents": "^0.5.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.12.0", + "npm": ">=8.19.2" }, "peerDependencies": { - "@babel/core": "^7.12.0" + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-classes": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.7.tgz", - "integrity": "sha512-9j9rnl+YCQY0IGoeipXvnk3niWicIB6kCsWRGLwX241qSXpbA4MKxtp/EdvFxsc4zI5vqfLxzOd0twIJ7I99zg==", - "dev": true, + "packages/block-editor/node_modules/postcss-urlrebase": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.4.0.tgz", + "integrity": "sha512-rRaxMmWvXrn8Rk1PqsxmaJwldRHsr0WbbASKKCZYxXwotHkM/5X/6IrwaEe8pdzpbNGCEY86yhYMN0MhgOkADA==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-replace-supers": "^7.25.7", - "@babel/traverse": "^7.25.7", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" + "postcss-value-parser": "^4.2.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.7.tgz", - "integrity": "sha512-QIv+imtM+EtNxg/XBKL3hiWjgdLjMOmZ+XzQwSgmBfKbfxUjBzGgVPklUuE55eq5/uVoh8gg3dqlrwR/jw3ZeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/template": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-destructuring": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.7.tgz", - "integrity": "sha512-xKcfLTlJYUczdaM1+epcdh1UGewJqr9zATgrNHcLBcV2QmfvPPEixo/sK/syql9cEmbr7ulu5HMFG5vbbt/sEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.7.tgz", - "integrity": "sha512-kXzXMMRzAtJdDEgQBLF4oaiT6ZCU3oWHgpARnTKDAqPkDJ+bs3NrZb310YYevR5QlRo3Kn7dzzIdHbZm1VzJdQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.7.tgz", - "integrity": "sha512-by+v2CjoL3aMnWDOyCIg+yxU9KXSRa9tN6MbqggH5xvymmr9p4AMjYkNlQy4brMceBnUyHZ9G8RnpvT8wP7Cfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.7.tgz", - "integrity": "sha512-UvcLuual4h7/GfylKm2IAA3aph9rwvAM2XBA0uPKU3lca+Maai4jBjjEVUS568ld6kJcgbouuumCBhMd/Yz17w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.7.tgz", - "integrity": "sha512-yjqtpstPfZ0h/y40fAXRv2snciYr0OAoMXY/0ClC7tm4C/nG5NJKmIItlaYlLbIVAWNfrYuy9dq1bE0SbX0PEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-for-of": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.7.tgz", - "integrity": "sha512-n/TaiBGJxYFWvpJDfsxSj9lEEE44BFM1EPGz4KEiTipTgkoFVVcCmzAL3qA7fdQU96dpo4gGf5HBx/KnDvqiHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-function-name": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.7.tgz", - "integrity": "sha512-5MCTNcjCMxQ63Tdu9rxyN6cAWurqfrDZ76qvVPrGYdBxIj+EawuuxTu/+dgJlhK5eRz3v1gLwp6XwS8XaX2NiQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/traverse": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-json-strings": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.7.tgz", - "integrity": "sha512-Ot43PrL9TEAiCe8C/2erAjXMeVSnE/BLEx6eyrKLNFCCw5jvhTHKyHxdI1pA0kz5njZRYAnMO2KObGqOCRDYSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-literals": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.7.tgz", - "integrity": "sha512-fwzkLrSu2fESR/cm4t6vqd7ebNIopz2QHGtjoU+dswQo/P6lwAG04Q98lliE3jkz/XqnbGFLnUcE0q0CVUf92w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.7.tgz", - "integrity": "sha512-iImzbA55BjiovLyG2bggWS+V+OLkaBorNvc/yJoeeDQGztknRnDdYfp2d/UPmunZYEnZi6Lg8QcTmNMHOB0lGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.7.tgz", - "integrity": "sha512-Std3kXwpXfRV0QtQy5JJcRpkqP8/wG4XL7hSKZmGlxPlDqmpXtEPRmhF7ztnlTCtUN3eXRUJp+sBEZjaIBVYaw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.7.tgz", - "integrity": "sha512-CgselSGCGzjQvKzghCvDTxKHP3iooenLpJDO842ehn5D2G5fJB222ptnDwQho0WjEvg7zyoxb9P+wiYxiJX5yA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.7.tgz", - "integrity": "sha512-L9Gcahi0kKFYXvweO6n0wc3ZG1ChpSFdgG+eV1WYZ3/dGbJK7vvk91FgGgak8YwRgrCuihF8tE/Xg07EkL5COg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-simple-access": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.7.tgz", - "integrity": "sha512-t9jZIvBmOXJsiuyOwhrIGs8dVcD6jDyg2icw1VL4A/g+FnWyJKwUfSSU2nwJuMV2Zqui856El9u+ElB+j9fV1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "@babel/traverse": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.7.tgz", - "integrity": "sha512-p88Jg6QqsaPh+EB7I9GJrIqi1Zt4ZBHUQtjw3z1bzEXcLh6GfPqzZJ6G+G1HBGKUNukT58MnKG7EN7zXQBCODw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.7.tgz", - "integrity": "sha512-BtAT9LzCISKG3Dsdw5uso4oV1+v2NlVXIIomKJgQybotJY3OwCwJmkongjHgwGKoZXd0qG5UZ12JUlDQ07W6Ow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-new-target": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.7.tgz", - "integrity": "sha512-CfCS2jDsbcZaVYxRFo2qtavW8SpdzmBXC2LOI4oO0rP+JSRDxxF3inF4GcPsLgfb5FjkhXG5/yR/lxuRs2pySA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.7.tgz", - "integrity": "sha512-FbuJ63/4LEL32mIxrxwYaqjJxpbzxPVQj5a+Ebrc8JICV6YX8nE53jY+K0RZT3um56GoNWgkS2BQ/uLGTjtwfw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.7.tgz", - "integrity": "sha512-8CbutzSSh4hmD+jJHIA8vdTNk15kAzOnFLVVgBSMGr28rt85ouT01/rezMecks9pkU939wDInImwCKv4ahU4IA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.7.tgz", - "integrity": "sha512-1JdVKPhD7Y5PvgfFy0Mv2brdrolzpzSoUq2pr6xsR+m+3viGGeHEokFKsCgOkbeFOQxfB1Vt2F0cPJLRpFI4Zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-object-super": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.7.tgz", - "integrity": "sha512-pWT6UXCEW3u1t2tcAGtE15ornCBvopHj9Bps9D2DsH15APgNVOTwwczGckX+WkAvBmuoYKRCFa4DK+jM8vh5AA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-replace-supers": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.7.tgz", - "integrity": "sha512-m9obYBA39mDPN7lJzD5WkGGb0GO54PPLXsbcnj1Hyeu8mSRz7Gb4b1A6zxNX32ZuUySDK4G6it8SDFWD1nCnqg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.7.tgz", - "integrity": "sha512-h39agClImgPWg4H8mYVAbD1qP9vClFbEjqoJmt87Zen8pjqK8FTPUwrOXAvqu5soytwxrLMd2fx2KSCp2CHcNg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-parameters": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.7.tgz", - "integrity": "sha512-FYiTvku63me9+1Nz7TOx4YMtW3tWXzfANZtrzHhUZrz4d47EEtMQhzFoZWESfXuAMMT5mwzD4+y1N8ONAX6lMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz", - "integrity": "sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.7.tgz", - "integrity": "sha512-LzA5ESzBy7tqj00Yjey9yWfs3FKy4EmJyKOSWld144OxkTji81WWnUT8nkLUn+imN/zHL8ZQlOu/MTUAhHaX3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-property-literals": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.7.tgz", - "integrity": "sha512-lQEeetGKfFi0wHbt8ClQrUSUMfEeI3MMm74Z73T9/kuz990yYVtfofjf3NuA42Jy3auFOpbjDyCSiIkTs1VIYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.7.tgz", - "integrity": "sha512-vILAg5nwGlR9EXE8JIOX4NHXd49lrYbN8hnjffDtoULwpL9hUx/N55nqh2qd0q6FyNDfjl9V79ecKGvFbcSA0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-module-imports": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-jsx": "^7.25.7", - "@babel/types": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-regenerator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.7.tgz", - "integrity": "sha512-mgDoQCRjrY3XK95UuV60tZlFCQGXEtMg8H+IsW72ldw1ih1jZhzYXbJvghmAEpg5UVhhnCeia1CkGttUvCkiMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "regenerator-transform": "^0.15.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.7.tgz", - "integrity": "sha512-3OfyfRRqiGeOvIWSagcwUTVk2hXBsr/ww7bLn6TRTuXnexA+Udov2icFOxFX9abaj4l96ooYkcNN1qi2Zvqwng==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-runtime": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.7.tgz", - "integrity": "sha512-Y9p487tyTzB0yDYQOtWnC+9HGOuogtP3/wNpun1xJXEEvI6vip59BSBTsHnekZLqxmPcgsrAKt46HAAb//xGhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.7.tgz", - "integrity": "sha512-uBbxNwimHi5Bv3hUccmOFlUy3ATO6WagTApenHz9KzoIdn0XeACdB12ZJ4cjhuB2WSi80Ez2FWzJnarccriJeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-spread": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.7.tgz", - "integrity": "sha512-Mm6aeymI0PBh44xNIv/qvo8nmbkpZze1KvR8MkEqbIREDxoiWTi18Zr2jryfRMwDfVZF9foKh060fWgni44luw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.7.tgz", - "integrity": "sha512-ZFAeNkpGuLnAQ/NCsXJ6xik7Id+tHuS+NT+ue/2+rn/31zcdnupCdmunOizEaP0JsUmTFSTOPoQY7PkK2pttXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-template-literals": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.7.tgz", - "integrity": "sha512-SI274k0nUsFFmyQupiO7+wKATAmMFf8iFgq2O+vVFXZ0SV9lNfT1NGzBEhjquFmD8I9sqHLguH+gZVN3vww2AA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.7.tgz", - "integrity": "sha512-OmWmQtTHnO8RSUbL0NTdtpbZHeNTnm68Gj5pA4Y2blFNh+V4iZR68V1qL9cI37J21ZN7AaCnkfdHtLExQPf2uA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-typescript": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.7.tgz", - "integrity": "sha512-VKlgy2vBzj8AmEzunocMun2fF06bsSWV+FvVXohtL6FGve/+L217qhHxRTVGHEDO/YR8IANcjzgJsd04J8ge5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", - "@babel/plugin-syntax-typescript": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.7.tgz", - "integrity": "sha512-BN87D7KpbdiABA+t3HbVqHzKWUDN3dymLaTnPFAMyc8lV+KN3+YzNhVRNdinaCPA4AUqx7ubXbQ9shRjYBl3SQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.7.tgz", - "integrity": "sha512-IWfR89zcEPQGB/iB408uGtSPlQd3Jpq11Im86vUgcmSTcoWAiQMCTOa2K2yNNqFJEBVICKhayctee65Ka8OB0w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.7.tgz", - "integrity": "sha512-8JKfg/hiuA3qXnlLx8qtv5HWRbgyFx2hMMtpDDuU2rTckpKkGu4ycK5yYHwuEa16/quXfoxHBIApEsNyMWnt0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.7.tgz", - "integrity": "sha512-YRW8o9vzImwmh4Q3Rffd09bH5/hvY0pxg+1H1i0f7APoUeg12G7+HhLj9ZFNIrYkgBXhIijPJ+IXypN0hLTIbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "packages/babel-preset-default/node_modules/@babel/preset-env": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.7.tgz", - "integrity": "sha512-Gibz4OUdyNqqLj+7OAvBZxOD7CklCtMA5/j0JgUEwOnaRULsPDXmic2iKxL2DX2vQduPR5wH2hjZas/Vr/Oc0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.25.7", - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-validator-option": "^7.25.7", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.7", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.7", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.7", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.7", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.25.7", - "@babel/plugin-syntax-import-attributes": "^7.25.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.25.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.7", - "@babel/plugin-transform-async-to-generator": "^7.25.7", - "@babel/plugin-transform-block-scoped-functions": "^7.25.7", - "@babel/plugin-transform-block-scoping": "^7.25.7", - "@babel/plugin-transform-class-properties": "^7.25.7", - "@babel/plugin-transform-class-static-block": "^7.25.7", - "@babel/plugin-transform-classes": "^7.25.7", - "@babel/plugin-transform-computed-properties": "^7.25.7", - "@babel/plugin-transform-destructuring": "^7.25.7", - "@babel/plugin-transform-dotall-regex": "^7.25.7", - "@babel/plugin-transform-duplicate-keys": "^7.25.7", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.7", - "@babel/plugin-transform-dynamic-import": "^7.25.7", - "@babel/plugin-transform-exponentiation-operator": "^7.25.7", - "@babel/plugin-transform-export-namespace-from": "^7.25.7", - "@babel/plugin-transform-for-of": "^7.25.7", - "@babel/plugin-transform-function-name": "^7.25.7", - "@babel/plugin-transform-json-strings": "^7.25.7", - "@babel/plugin-transform-literals": "^7.25.7", - "@babel/plugin-transform-logical-assignment-operators": "^7.25.7", - "@babel/plugin-transform-member-expression-literals": "^7.25.7", - "@babel/plugin-transform-modules-amd": "^7.25.7", - "@babel/plugin-transform-modules-commonjs": "^7.25.7", - "@babel/plugin-transform-modules-systemjs": "^7.25.7", - "@babel/plugin-transform-modules-umd": "^7.25.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.7", - "@babel/plugin-transform-new-target": "^7.25.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.7", - "@babel/plugin-transform-numeric-separator": "^7.25.7", - "@babel/plugin-transform-object-rest-spread": "^7.25.7", - "@babel/plugin-transform-object-super": "^7.25.7", - "@babel/plugin-transform-optional-catch-binding": "^7.25.7", - "@babel/plugin-transform-optional-chaining": "^7.25.7", - "@babel/plugin-transform-parameters": "^7.25.7", - "@babel/plugin-transform-private-methods": "^7.25.7", - "@babel/plugin-transform-private-property-in-object": "^7.25.7", - "@babel/plugin-transform-property-literals": "^7.25.7", - "@babel/plugin-transform-regenerator": "^7.25.7", - "@babel/plugin-transform-reserved-words": "^7.25.7", - "@babel/plugin-transform-shorthand-properties": "^7.25.7", - "@babel/plugin-transform-spread": "^7.25.7", - "@babel/plugin-transform-sticky-regex": "^7.25.7", - "@babel/plugin-transform-template-literals": "^7.25.7", - "@babel/plugin-transform-typeof-symbol": "^7.25.7", - "@babel/plugin-transform-unicode-escapes": "^7.25.7", - "@babel/plugin-transform-unicode-property-regex": "^7.25.7", - "@babel/plugin-transform-unicode-regex": "^7.25.7", - "@babel/plugin-transform-unicode-sets-regex": "^7.25.7", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.38.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/@babel/preset-typescript": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.25.7.tgz", - "integrity": "sha512-rkkpaXJZOFN45Fb+Gki0c+KMIglk4+zZXOoMJuyEK8y8Kkc8Jd3BDmP7qPsz0zQMJj+UD7EprF+AqAXcILnexw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-validator-option": "^7.25.7", - "@babel/plugin-syntax-jsx": "^7.25.7", - "@babel/plugin-transform-modules-commonjs": "^7.25.7", - "@babel/plugin-transform-typescript": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/babel-preset-default/node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "packages/babel-preset-default/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", - "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2", - "core-js-compat": "^3.38.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "packages/babel-preset-default/node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", - "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "packages/babel-preset-default/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "packages/babel-preset-default/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "packages/base-styles": { - "name": "@wordpress/base-styles", - "version": "5.10.0", - "dev": true, - "license": "GPL-2.0-or-later", - "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" - } - }, - "packages/blob": { - "name": "@wordpress/blob", - "version": "4.10.0", - "license": "GPL-2.0-or-later", - "dependencies": { - "@babel/runtime": "7.25.7" - }, - "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" - } - }, - "packages/block-directory": { - "name": "@wordpress/block-directory", - "version": "5.10.0", - "license": "GPL-2.0-or-later", - "dependencies": { - "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@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/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/plugins": "file:../plugins", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", - "change-case": "^4.1.2", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "packages/block-editor": { - "name": "@wordpress/block-editor", - "version": "14.5.0", - "license": "GPL-2.0-or-later", - "dependencies": { - "@babel/runtime": "7.25.7", - "@emotion/react": "^11.7.1", - "@emotion/styled": "^11.6.0", - "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/style-engine": "file:../style-engine", - "@wordpress/token-list": "file:../token-list", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", - "@wordpress/wordcount": "file:../wordcount", - "change-case": "^4.1.2", - "clsx": "^2.1.1", - "colord": "^2.7.0", - "deepmerge": "^4.3.0", - "diff": "^4.0.2", - "fast-deep-equal": "^3.1.3", - "memize": "^2.1.0", - "parsel-js": "^1.1.2", - "postcss": "^8.4.21", - "postcss-prefix-selector": "^1.16.0", - "postcss-urlrebase": "^1.4.0", - "react-autosize-textarea": "^7.1.0", - "react-easy-crop": "^5.0.6", - "remove-accents": "^0.5.0" - }, - "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "packages/block-editor/node_modules/postcss-urlrebase": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.4.0.tgz", - "integrity": "sha512-rRaxMmWvXrn8Rk1PqsxmaJwldRHsr0WbbASKKCZYxXwotHkM/5X/6IrwaEe8pdzpbNGCEY86yhYMN0MhgOkADA==", - "license": "MIT", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "peerDependencies": { - "postcss": "^8.3.0" + "postcss": "^8.3.0" } }, "packages/block-editor/node_modules/postcss-value-parser": { @@ -54206,39 +51658,39 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/autop": "file:../autop", - "@wordpress/blob": "file:../blob", - "@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/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interactivity": "file:../interactivity", - "@wordpress/interactivity-router": "file:../interactivity-router", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/server-side-render": "file:../server-side-render", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/autop": "*", + "@wordpress/blob": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interactivity": "*", + "@wordpress/interactivity-router": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/rich-text": "*", + "@wordpress/server-side-render": "*", + "@wordpress/url": "*", + "@wordpress/viewport": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -54297,21 +51749,21 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/autop": "file:../autop", - "@wordpress/blob": "file:../blob", - "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/shortcode": "file:../shortcode", - "@wordpress/warning": "file:../warning", + "@wordpress/autop": "*", + "@wordpress/blob": "*", + "@wordpress/block-serialization-default-parser": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/shortcode": "*", + "@wordpress/warning": "*", "change-case": "^4.1.2", "colord": "^2.7.0", "fast-deep-equal": "^3.1.3", @@ -54348,7 +51800,6 @@ "packages/browserslist-config": { "name": "@wordpress/browserslist-config", "version": "6.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -54361,13 +51812,13 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/private-apis": "file:../private-apis", + "@wordpress/components": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/private-apis": "*", "clsx": "^2.1.1", "cmdk": "^1.0.0" }, @@ -54545,23 +51996,23 @@ "@types/gradient-parser": "0.1.3", "@types/highlight-words-core": "1.2.1", "@use-gesture/react": "^10.3.1", - "@wordpress/a11y": "file:../a11y", - "@wordpress/compose": "file:../compose", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/warning": "file:../warning", + "@wordpress/a11y": "*", + "@wordpress/compose": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keycodes": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/warning": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -54656,13 +52107,13 @@ "dependencies": { "@babel/runtime": "7.25.7", "@types/mousetrap": "^1.6.8", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/undo-manager": "file:../undo-manager", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keycodes": "*", + "@wordpress/priority-queue": "*", + "@wordpress/undo-manager": "*", "change-case": "^4.1.2", "clipboard": "^2.0.11", "mousetrap": "^1.6.5", @@ -54692,19 +52143,19 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/commands": "file:../commands", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/router": "file:../router", - "@wordpress/url": "file:../url" + "@wordpress/block-editor": "*", + "@wordpress/commands": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/private-apis": "*", + "@wordpress/router": "*", + "@wordpress/url": "*" }, "engines": { "node": ">=18.12.0", @@ -54721,22 +52172,22 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/sync": "file:../sync", - "@wordpress/undo-manager": "file:../undo-manager", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/sync": "*", + "@wordpress/undo-manager": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", "change-case": "^4.1.2", "equivalent-key-map": "^0.2.2", "fast-deep-equal": "^3.1.3", @@ -54763,10 +52214,9 @@ "packages/create-block": { "name": "@wordpress/create-block", "version": "4.53.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/lazy-import": "file:../lazy-import", + "@wordpress/lazy-import": "*", "chalk": "^4.0.0", "change-case": "^4.1.2", "check-node-version": "^4.1.0", @@ -54788,10 +52238,18 @@ "npm": ">=10.2.3" } }, + "packages/create-block-interactive-template": { + "name": "@wordpress/create-block-interactive-template", + "version": "2.10.0", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", "version": "4.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -54804,27 +52262,27 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/widgets": "file:../widgets", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interface": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/media-utils": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/widgets": "*", "clsx": "^2.1.1", "fast-deep-equal": "^3.1.3" }, @@ -54843,13 +52301,13 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/compose": "file:../compose", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/redux-routine": "file:../redux-routine", + "@wordpress/compose": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/priority-queue": "*", + "@wordpress/private-apis": "*", + "@wordpress/redux-routine": "*", "deepmerge": "^4.3.0", "equivalent-key-map": "^0.2.2", "is-plain-object": "^5.0.0", @@ -54872,9 +52330,9 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated" + "@wordpress/api-fetch": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*" }, "engines": { "node": ">=18.12.0", @@ -54891,15 +52349,15 @@ "dependencies": { "@ariakit/react": "^0.4.10", "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/warning": "file:../warning", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/warning": "*", "clsx": "^2.1.1", "remove-accents": "^0.5.0" }, @@ -54947,7 +52405,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/deprecated": "file:../deprecated", + "@wordpress/deprecated": "*", "moment": "^2.29.4", "moment-timezone": "^0.5.40" }, @@ -54959,7 +52417,6 @@ "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", "version": "6.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "json2php": "^0.0.7" @@ -54978,7 +52435,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/hooks": "file:../hooks" + "@wordpress/hooks": "*" }, "engines": { "node": ">=18.12.0", @@ -54988,7 +52445,6 @@ "packages/docgen": { "name": "@wordpress/docgen", "version": "2.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -55013,7 +52469,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/deprecated": "file:../deprecated" + "@wordpress/deprecated": "*" }, "engines": { "node": ">=18.12.0", @@ -55035,13 +52491,12 @@ "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", "version": "11.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/url": "file:../url", + "@wordpress/api-fetch": "*", + "@wordpress/keycodes": "*", + "@wordpress/url": "*", "change-case": "^4.1.2", "form-data": "^4.0.0", "node-fetch": "2.7.0" @@ -55058,7 +52513,6 @@ "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", "version": "1.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "change-case": "^4.1.2", @@ -55080,22 +52534,20 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.1.tgz", "integrity": "sha512-U6bAxeudnhDqcXNl50JC4hLlqox9DZnngxfISZm3DMZnonW35xtJOVUc091L+DOY+6hVZVpKXoiCP0RiT6339Q==", - "dev": true, "license": "Apache-2.0" }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", "version": "8.10.1", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/e2e-test-utils": "file:../e2e-test-utils", - "@wordpress/interactivity": "file:../interactivity", - "@wordpress/interactivity-router": "file:../interactivity-router", - "@wordpress/jest-console": "file:../jest-console", - "@wordpress/jest-puppeteer-axe": "file:../jest-puppeteer-axe", - "@wordpress/scripts": "file:../scripts", - "@wordpress/url": "file:../url", + "@wordpress/e2e-test-utils": "*", + "@wordpress/interactivity": "*", + "@wordpress/interactivity-router": "*", + "@wordpress/jest-console": "*", + "@wordpress/jest-puppeteer-axe": "*", + "@wordpress/scripts": "*", + "@wordpress/url": "*", "chalk": "^4.0.0", "expect-puppeteer": "^4.4.0", "filenamify": "^4.2.0", @@ -55118,7 +52570,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -55129,35 +52580,35 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-commands": "file:../core-commands", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/warning": "file:../warning", - "@wordpress/widgets": "file:../widgets", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-commands": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", + "@wordpress/viewport": "*", + "@wordpress/warning": "*", + "@wordpress/widgets": "*", "clsx": "^2.1.1", "memize": "^2.1.0" }, @@ -55177,45 +52628,45 @@ "dependencies": { "@babel/runtime": "7.25.7", "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-commands": "file:../core-commands", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/primitives": "file:../primitives", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/router": "file:../router", - "@wordpress/style-engine": "file:../style-engine", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/widgets": "file:../widgets", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-commands": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dataviews": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/primitives": "*", + "@wordpress/priority-queue": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/router": "*", + "@wordpress/style-engine": "*", + "@wordpress/url": "*", + "@wordpress/viewport": "*", + "@wordpress/widgets": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.9.2", @@ -55238,33 +52689,33 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/url": "file:../url", - "@wordpress/widgets": "file:../widgets", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interface": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/media-utils": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/url": "*", + "@wordpress/widgets": "*", "clsx": "^2.1.1" }, "engines": { @@ -55282,41 +52733,41 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/fields": "file:../fields", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/server-side-render": "file:../server-side-render", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dataviews": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/fields": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interface": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/media-utils": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/rich-text": "*", + "@wordpress/server-side-render": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "client-zip": "^2.4.5", "clsx": "^2.1.1", @@ -55346,7 +52797,7 @@ "@babel/runtime": "7.25.7", "@types/react": "^18.2.79", "@types/react-dom": "^18.2.25", - "@wordpress/escape-html": "file:../escape-html", + "@wordpress/escape-html": "*", "change-case": "^4.1.2", "is-plain-object": "^5.0.0", "react": "^18.3.0", @@ -55360,7 +52811,6 @@ "packages/env": { "name": "@wordpress/env", "version": "10.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "chalk": "^4.0.0", @@ -55388,7 +52838,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -55402,7 +52851,6 @@ "version": "0.24.2", "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.24.2.tgz", "integrity": "sha512-2/WLvA7UZ6A2LDLQrYW0idKipmNBWhtfvrn2yzjC5PnHDzuFVj1zAZN6MJxVMKP0zZH8uzAK6OwVZYHGuyCmTw==", - "dev": true, "dependencies": { "yaml": "^2.2.2" }, @@ -55413,14 +52861,12 @@ "packages/env/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "packages/env/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -55429,7 +52875,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -55443,7 +52888,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -55459,14 +52903,12 @@ "packages/env/node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, "packages/env/node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", - "dev": true, + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -55479,7 +52921,6 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -55496,8 +52937,7 @@ "packages/env/node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" }, "packages/escape-html": { "name": "@wordpress/escape-html", @@ -55514,14 +52954,13 @@ "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", "version": "21.3.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/eslint-parser": "7.25.7", "@typescript-eslint/eslint-plugin": "^6.4.1", "@typescript-eslint/parser": "^6.4.1", - "@wordpress/babel-preset-default": "file:../babel-preset-default", - "@wordpress/prettier-config": "file:../prettier-config", + "@wordpress/babel-preset-default": "*", + "@wordpress/prettier-config": "*", "cosmiconfig": "^7.0.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.2", @@ -55558,7 +52997,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.7.tgz", "integrity": "sha512-B+BO9x86VYsQHimucBAL1fxTJKF4wyKY6ZVzee9QgzdZOUfs3BaR6AQrgoGrRI+7IFS1wUz/VyQ+SoBcSpdPbw==", - "dev": true, "license": "MIT", "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", @@ -55577,7 +53015,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -55589,25 +53026,25 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dataviews": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", "change-case": "4.1.2", "client-zip": "^2.4.5" }, @@ -55625,18 +53062,18 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/url": "file:../url" + "@wordpress/a11y": "*", + "@wordpress/block-editor": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/url": "*" }, "engines": { "node": ">=18.12.0", @@ -55677,7 +53114,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/hooks": "file:../hooks", + "@wordpress/hooks": "*", "gettext-parser": "^1.3.1", "memize": "^2.1.0", "sprintf-js": "^1.1.1", @@ -55697,8 +53134,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", - "@wordpress/primitives": "file:../primitives" + "@wordpress/element": "*", + "@wordpress/primitives": "*" }, "engines": { "node": ">=18.12.0", @@ -55723,8 +53160,8 @@ "version": "2.10.0", "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/a11y": "file:../a11y", - "@wordpress/interactivity": "file:../interactivity" + "@wordpress/a11y": "*", + "@wordpress/interactivity": "*" }, "engines": { "node": ">=18.12.0", @@ -55737,18 +53174,18 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/viewport": "file:../viewport", + "@wordpress/a11y": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/viewport": "*", "clsx": "^2.1.1" }, "engines": { @@ -55775,7 +53212,6 @@ "packages/jest-console": { "name": "@wordpress/jest-console", "version": "8.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55792,10 +53228,9 @@ "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", "version": "12.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/jest-console": "file:../jest-console", + "@wordpress/jest-console": "*", "babel-jest": "29.7.0" }, "engines": { @@ -55810,7 +53245,6 @@ "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", "version": "7.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@axe-core/puppeteer": "^4.0.0", @@ -55836,9 +53270,9 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/keycodes": "file:../keycodes" + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/keycodes": "*" }, "engines": { "node": ">=18.12.0", @@ -55854,7 +53288,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/i18n": "file:../i18n" + "@wordpress/i18n": "*" }, "engines": { "node": ">=18.12.0", @@ -55864,7 +53298,6 @@ "packages/lazy-import": { "name": "@wordpress/lazy-import", "version": "2.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "execa": "^4.0.2", @@ -55882,12 +53315,12 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", "change-case": "^4.1.2" }, "engines": { @@ -55905,10 +53338,10 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n" + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*" }, "engines": { "node": ">=18.12.0", @@ -55921,8 +53354,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/data": "file:../data" + "@wordpress/a11y": "*", + "@wordpress/data": "*" }, "engines": { "node": ">=18.12.0", @@ -55935,7 +53368,6 @@ "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", "version": "5.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55951,13 +53383,13 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons" + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*" }, "engines": { "node": ">=18.12.0", @@ -55974,20 +53406,20 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@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/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url" + "@wordpress/a11y": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*" }, "engines": { "node": ">=18.12.0", @@ -56004,12 +53436,12 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/icons": "*", + "@wordpress/is-shallow-equal": "*", "memize": "^2.0.1" }, "engines": { @@ -56024,10 +53456,9 @@ "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", "version": "5.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/base-styles": "file:../base-styles", + "@wordpress/base-styles": "*", "autoprefixer": "^10.2.5" }, "engines": { @@ -56041,7 +53472,6 @@ "packages/postcss-themes": { "name": "@wordpress/postcss-themes", "version": "6.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -56057,15 +53487,15 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/private-apis": "file:../private-apis", + "@wordpress/a11y": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/private-apis": "*", "clsx": "^2.1.1" }, "engines": { @@ -56083,7 +53513,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch" + "@wordpress/api-fetch": "*" }, "engines": { "node": ">=18.12.0", @@ -56093,7 +53523,6 @@ "packages/prettier-config": { "name": "@wordpress/prettier-config", "version": "4.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -56109,7 +53538,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", + "@wordpress/element": "*", "clsx": "^2.1.1" }, "engines": { @@ -56148,7 +53577,6 @@ "packages/project-management-automation": { "name": "@wordpress/project-management-automation", "version": "2.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@actions/core": "1.9.1", @@ -56166,7 +53594,6 @@ "version": "9.26.3", "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.26.3.tgz", "integrity": "sha512-DLGk+gzeVq5oK89Bo601txYmyrelMQ7Fi5EnjHE0Xs8CWicy2xkmnJMKptKJrBJpstqbd/9oeDFi/Zj2pudBDQ==", - "dev": true, "license": "MIT", "dependencies": { "@octokit/request-error": "^2.0.2", @@ -56181,8 +53608,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", + "@wordpress/element": "*", + "@wordpress/i18n": "*", "utility-types": "^3.10.0" }, "engines": { @@ -56195,8 +53622,8 @@ "version": "1.121.0", "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/element": "file:../element", - "@wordpress/keycodes": "file:../keycodes" + "@wordpress/element": "*", + "@wordpress/keycodes": "*" }, "engines": { "node": ">=18.12.0", @@ -56212,7 +53639,7 @@ "version": "1.121.0", "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/react-native-aztec": "file:../react-native-aztec" + "@wordpress/react-native-aztec": "*" }, "engines": { "node": ">=18.12.0", @@ -56237,18 +53664,18 @@ "@react-navigation/native": "6.0.14", "@react-navigation/routers": "5.4.9", "@react-navigation/stack": "6.3.5", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/data": "file:../data", - "@wordpress/edit-post": "file:../edit-post", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/react-native-aztec": "file:../react-native-aztec", - "@wordpress/react-native-bridge": "file:../react-native-bridge", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/data": "*", + "@wordpress/edit-post": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/react-native-aztec": "*", + "@wordpress/react-native-bridge": "*", "core-js": "^3.31.0", "fast-average-color": "^9.1.1", "gettext-parser": "^1.3.1", @@ -56334,7 +53761,6 @@ "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", "version": "3.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -56365,7 +53791,6 @@ "packages/report-flaky-tests": { "name": "@wordpress/report-flaky-tests", "version": "0.0.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@actions/core": "^1.8.0", @@ -56381,7 +53806,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz", "integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==", - "dev": true, "dependencies": { "@actions/http-client": "^2.0.1", "@octokit/core": "^3.6.0", @@ -56395,17 +53819,17 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url" + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*" }, "engines": { "node": ">=18.12.0", @@ -56422,14 +53846,14 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/i18n": "file:../i18n", - "@wordpress/keycodes": "file:../keycodes", + "@wordpress/a11y": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/i18n": "*", + "@wordpress/keycodes": "*", "memize": "^2.1.0" }, "engines": { @@ -56446,9 +53870,9 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", + "@wordpress/element": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", "history": "^5.3.0" }, "engines": { @@ -56462,22 +53886,21 @@ "packages/scripts": { "name": "@wordpress/scripts", "version": "30.3.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", "@svgr/webpack": "^8.0.1", - "@wordpress/babel-preset-default": "file:../babel-preset-default", - "@wordpress/browserslist-config": "file:../browserslist-config", - "@wordpress/dependency-extraction-webpack-plugin": "file:../dependency-extraction-webpack-plugin", - "@wordpress/e2e-test-utils-playwright": "file:../e2e-test-utils-playwright", - "@wordpress/eslint-plugin": "file:../eslint-plugin", - "@wordpress/jest-preset-default": "file:../jest-preset-default", - "@wordpress/npm-package-json-lint-config": "file:../npm-package-json-lint-config", - "@wordpress/postcss-plugins-preset": "file:../postcss-plugins-preset", - "@wordpress/prettier-config": "file:../prettier-config", - "@wordpress/stylelint-config": "file:../stylelint-config", + "@wordpress/babel-preset-default": "*", + "@wordpress/browserslist-config": "*", + "@wordpress/dependency-extraction-webpack-plugin": "*", + "@wordpress/e2e-test-utils-playwright": "*", + "@wordpress/eslint-plugin": "*", + "@wordpress/jest-preset-default": "*", + "@wordpress/npm-package-json-lint-config": "*", + "@wordpress/postcss-plugins-preset": "*", + "@wordpress/prettier-config": "*", + "@wordpress/stylelint-config": "*", "adm-zip": "^0.5.9", "babel-jest": "29.7.0", "babel-loader": "9.2.1", @@ -56544,7 +53967,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -56561,7 +53983,6 @@ "version": "1.7.7", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "dev": true, "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -56573,7 +53994,6 @@ "version": "8.4.1", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.4.1.tgz", "integrity": "sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==", - "dev": true, "license": "MIT", "dependencies": { "find-cache-dir": "^3.3.1", @@ -56593,7 +54013,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -56610,14 +54029,12 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, "license": "MIT" }, "packages/scripts/node_modules/babel-loader/node_modules/schema-utils": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.5", @@ -56636,7 +54053,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -56652,7 +54068,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", @@ -56669,7 +54084,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -56682,7 +54096,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -56691,7 +54104,6 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/jest-dev-server/-/jest-dev-server-9.0.1.tgz", "integrity": "sha512-eqpJKSvVl4M0ojHZUPNbka8yEzLNbIMiINXDsuMF3lYfIdRO2iPqy+ASR4wBQ6nUyR3OT24oKPWhpsfLhgAVyg==", - "dev": true, "dependencies": { "chalk": "^4.1.2", "cwd": "^0.10.0", @@ -56709,7 +54121,6 @@ "version": "17.11.0", "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", - "dev": true, "dependencies": { "@hapi/hoek": "^9.0.0", "@hapi/topo": "^5.0.0", @@ -56722,21 +54133,18 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, "license": "MIT" }, "packages/scripts/node_modules/json2php": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/json2php/-/json2php-0.0.9.tgz", "integrity": "sha512-fQMYwvPsQt8hxRnCGyg1r2JVi6yL8Um0DIIawiKiMK9yhAAkcRNj5UsBWoaFvFzPpcWbgw9L6wzj+UMYA702Mw==", - "dev": true, "license": "BSD" }, "packages/scripts/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -56748,7 +54156,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, "dependencies": { "semver": "^6.0.0" }, @@ -56763,7 +54170,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -56778,7 +54184,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -56790,7 +54195,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "engines": { "node": ">=6" } @@ -56799,7 +54203,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -56808,7 +54211,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, "dependencies": { "find-up": "^4.0.0" }, @@ -56820,7 +54222,6 @@ "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, "dependencies": { "tslib": "^2.1.0" } @@ -56829,7 +54230,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", @@ -56849,7 +54249,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" @@ -56862,7 +54261,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -56871,7 +54269,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "engines": { "node": ">=14" }, @@ -56883,7 +54280,6 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-9.0.1.tgz", "integrity": "sha512-vaMk8E9CpbjTYToBxLXowDeArGf1+yI7A6PU6Nr57b2g8BVY8nRi5vTBj3bMF8UkCrMdTMyf/Lh+lrcrW2z7pw==", - "dev": true, "dependencies": { "signal-exit": "^4.1.0", "tree-kill": "^1.2.2" @@ -56896,7 +54292,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -56908,7 +54303,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.2.0.tgz", "integrity": "sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ==", - "dev": true, "dependencies": { "axios": "^1.6.1", "joi": "^17.11.0", @@ -56929,15 +54323,15 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/url": "file:../url", + "@wordpress/api-fetch": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/url": "*", "fast-deep-equal": "^3.1.3" }, "engines": { @@ -56978,7 +54372,6 @@ "packages/stylelint-config": { "name": "@wordpress/stylelint-config", "version": "23.2.0", - "dev": true, "license": "MIT", "dependencies": { "@stylistic/stylelint-plugin": "^3.0.1", @@ -56997,7 +54390,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -57009,20 +54401,17 @@ "packages/stylelint-config/node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, "packages/stylelint-config/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "packages/stylelint-config/node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -57032,7 +54421,6 @@ "version": "14.0.1", "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -57054,7 +54442,6 @@ "version": "14.1.0", "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.1.0.tgz", "integrity": "sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg==", - "dev": true, "dependencies": { "postcss-scss": "^4.0.9", "stylelint-config-recommended": "^14.0.1", @@ -57077,7 +54464,6 @@ "version": "6.5.1", "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.5.1.tgz", "integrity": "sha512-ZLqdqihm6uDYkrsOeD6YWb+stZI8Wn92kUNDhE4M+g9g1aCnRv0JlOrttFiAJJwaNzpdQgX3YJb5vDQXVuO9Ww==", - "dev": true, "dependencies": { "css-tree": "2.3.1", "is-plain-object": "5.0.0", @@ -57101,7 +54487,7 @@ "dependencies": { "@babel/runtime": "7.25.7", "@types/simple-peer": "^9.11.5", - "@wordpress/url": "file:../url", + "@wordpress/url": "*", "import-locals": "^2.0.0", "lib0": "^0.2.42", "simple-peer": "^9.11.0", @@ -57133,7 +54519,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal" + "@wordpress/is-shallow-equal": "*" }, "engines": { "node": ">=18.12.0", @@ -57159,9 +54545,9 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element" + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/element": "*" }, "engines": { "node": ">=18.12.0", @@ -57186,17 +54572,17 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@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/notices": "file:../notices", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", "clsx": "^2.1.1" }, "engines": { diff --git a/package.json b/package.json index 8be1e9cbe3f3a0..caa3edb410283f 100644 --- a/package.json +++ b/package.json @@ -21,80 +21,6 @@ "config": { "IS_GUTENBERG_PLUGIN": true }, - "dependencies": { - "@wordpress/a11y": "file:packages/a11y", - "@wordpress/annotations": "file:packages/annotations", - "@wordpress/api-fetch": "file:packages/api-fetch", - "@wordpress/autop": "file:packages/autop", - "@wordpress/blob": "file:packages/blob", - "@wordpress/block-directory": "file:packages/block-directory", - "@wordpress/block-editor": "file:packages/block-editor", - "@wordpress/block-library": "file:packages/block-library", - "@wordpress/block-serialization-default-parser": "file:packages/block-serialization-default-parser", - "@wordpress/block-serialization-spec-parser": "file:packages/block-serialization-spec-parser", - "@wordpress/blocks": "file:packages/blocks", - "@wordpress/commands": "file:packages/commands", - "@wordpress/components": "file:packages/components", - "@wordpress/compose": "file:packages/compose", - "@wordpress/core-commands": "file:packages/core-commands", - "@wordpress/core-data": "file:packages/core-data", - "@wordpress/customize-widgets": "file:packages/customize-widgets", - "@wordpress/data": "file:packages/data", - "@wordpress/data-controls": "file:packages/data-controls", - "@wordpress/dataviews": "file:packages/dataviews", - "@wordpress/date": "file:packages/date", - "@wordpress/deprecated": "file:packages/deprecated", - "@wordpress/dom": "file:packages/dom", - "@wordpress/dom-ready": "file:packages/dom-ready", - "@wordpress/edit-post": "file:packages/edit-post", - "@wordpress/edit-site": "file:packages/edit-site", - "@wordpress/edit-widgets": "file:packages/edit-widgets", - "@wordpress/editor": "file:packages/editor", - "@wordpress/element": "file:packages/element", - "@wordpress/escape-html": "file:packages/escape-html", - "@wordpress/fields": "file:packages/fields", - "@wordpress/format-library": "file:packages/format-library", - "@wordpress/hooks": "file:packages/hooks", - "@wordpress/html-entities": "file:packages/html-entities", - "@wordpress/i18n": "file:packages/i18n", - "@wordpress/icons": "file:packages/icons", - "@wordpress/interactivity": "file:packages/interactivity", - "@wordpress/interactivity-router": "file:packages/interactivity-router", - "@wordpress/interface": "file:packages/interface", - "@wordpress/is-shallow-equal": "file:packages/is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts", - "@wordpress/keycodes": "file:packages/keycodes", - "@wordpress/list-reusable-blocks": "file:packages/list-reusable-blocks", - "@wordpress/media-utils": "file:packages/media-utils", - "@wordpress/notices": "file:packages/notices", - "@wordpress/nux": "file:packages/nux", - "@wordpress/patterns": "file:packages/patterns", - "@wordpress/plugins": "file:packages/plugins", - "@wordpress/preferences": "file:packages/preferences", - "@wordpress/preferences-persistence": "file:packages/preferences-persistence", - "@wordpress/primitives": "file:packages/primitives", - "@wordpress/priority-queue": "file:packages/priority-queue", - "@wordpress/private-apis": "file:packages/private-apis", - "@wordpress/react-i18n": "file:packages/react-i18n", - "@wordpress/react-native-aztec": "file:packages/react-native-aztec", - "@wordpress/react-native-bridge": "file:packages/react-native-bridge", - "@wordpress/react-native-editor": "file:packages/react-native-editor", - "@wordpress/redux-routine": "file:packages/redux-routine", - "@wordpress/reusable-blocks": "file:packages/reusable-blocks", - "@wordpress/rich-text": "file:packages/rich-text", - "@wordpress/router": "file:packages/router", - "@wordpress/server-side-render": "file:packages/server-side-render", - "@wordpress/shortcode": "file:packages/shortcode", - "@wordpress/style-engine": "file:packages/style-engine", - "@wordpress/sync": "file:packages/sync", - "@wordpress/token-list": "file:packages/token-list", - "@wordpress/undo-manager": "file:packages/undo-manager", - "@wordpress/url": "file:packages/url", - "@wordpress/viewport": "file:packages/viewport", - "@wordpress/warning": "file:packages/warning", - "@wordpress/widgets": "file:packages/widgets", - "@wordpress/wordcount": "file:packages/wordcount" - }, "devDependencies": { "@actions/core": "1.9.1", "@actions/github": "5.0.0", @@ -144,33 +70,6 @@ "@types/semver": "7.3.8", "@types/sprintf-js": "1.1.2", "@types/uuid": "8.3.1", - "@wordpress/babel-plugin-import-jsx-pragma": "file:packages/babel-plugin-import-jsx-pragma", - "@wordpress/babel-plugin-makepot": "file:packages/babel-plugin-makepot", - "@wordpress/babel-preset-default": "file:packages/babel-preset-default", - "@wordpress/base-styles": "file:packages/base-styles", - "@wordpress/browserslist-config": "file:packages/browserslist-config", - "@wordpress/create-block": "file:packages/create-block", - "@wordpress/create-block-tutorial-template": "file:packages/create-block-tutorial-template", - "@wordpress/dependency-extraction-webpack-plugin": "file:packages/dependency-extraction-webpack-plugin", - "@wordpress/docgen": "file:packages/docgen", - "@wordpress/e2e-test-utils": "file:packages/e2e-test-utils", - "@wordpress/e2e-test-utils-playwright": "file:packages/e2e-test-utils-playwright", - "@wordpress/e2e-tests": "file:packages/e2e-tests", - "@wordpress/env": "file:packages/env", - "@wordpress/eslint-plugin": "file:packages/eslint-plugin", - "@wordpress/jest-console": "file:packages/jest-console", - "@wordpress/jest-preset-default": "file:packages/jest-preset-default", - "@wordpress/jest-puppeteer-axe": "file:packages/jest-puppeteer-axe", - "@wordpress/lazy-import": "file:packages/lazy-import", - "@wordpress/npm-package-json-lint-config": "file:packages/npm-package-json-lint-config", - "@wordpress/postcss-plugins-preset": "file:packages/postcss-plugins-preset", - "@wordpress/postcss-themes": "file:packages/postcss-themes", - "@wordpress/prettier-config": "file:packages/prettier-config", - "@wordpress/project-management-automation": "file:packages/project-management-automation", - "@wordpress/readable-js-assets-webpack-plugin": "file:packages/readable-js-assets-webpack-plugin", - "@wordpress/report-flaky-tests": "file:packages/report-flaky-tests", - "@wordpress/scripts": "file:packages/scripts", - "@wordpress/stylelint-config": "file:packages/stylelint-config", "ajv": "8.7.1", "appium": "2.0.0", "babel-jest": "29.7.0", @@ -274,7 +173,7 @@ "build": "npm run build:packages && wp-scripts build", "build:analyze-bundles": "npm run build -- --webpack-bundle-analyzer", "build:package-types": "node ./bin/packages/validate-typescript-version.js && ( tsc --build || ( echo 'tsc failed. Try cleaning up first: `npm run clean:package-types`'; exit 1 ) ) && node ./bin/packages/check-build-type-declaration-files.js", - "prebuild:packages": "npm run clean:packages && lerna run build", + "prebuild:packages": "npm run clean:packages && npm run --if-present --workspaces build", "build:packages": "npm run --silent build:package-types && node ./bin/packages/build.js", "build:plugin-zip": "bash ./bin/build-plugin-zip.sh", "clean:package-types": "tsc --build --clean && rimraf \"./packages/*/build-types\"", @@ -308,7 +207,7 @@ "lint:pkg-json": "wp-scripts lint-pkg-json . 'packages/*/package.json'", "native": "npm run --prefix packages/react-native-editor", "other:changelog": "node ./bin/plugin/cli.js changelog", - "other:check-licenses": "concurrently \"wp-scripts check-licenses --prod --gpl2 --ignore=@react-native-community/cli,@react-native-community/cli-platform-ios,@ampproject/remapping,human-signals,fb-watchman,walker,chrome-launcher,lighthouse-logger,chromium-edge-launcher\" \"wp-scripts check-licenses --dev\"", + "other:check-licenses": "concurrently \"node ./bin/check-licenses.mjs\" \"wp-scripts check-licenses --dev\"", "preother:check-local-changes": "npm run docs:build", "other:check-local-changes": "node ./bin/check-local-changes.js", "other:cherry-pick": "node ./bin/cherry-pick.mjs", @@ -387,5 +286,8 @@ "**/tsconfig.json": [ "npm run lint:tsconfig" ] - } + }, + "workspaces": [ + "packages/*" + ] } diff --git a/packages/README.md b/packages/README.md index 0b131f6c404d4e..27efdf2d43ad52 100644 --- a/packages/README.md +++ b/packages/README.md @@ -1,6 +1,6 @@ # Managing Packages -This repository uses [monorepo] to manage WordPress modules and publish them with [lerna] as packages to [npm]. +This repository uses [npm workspaces](https://docs.npmjs.com/cli/v10/using-npm/workspaces) to manage WordPress packages and [lerna](https://lerna.js.org/) to publish them with to [npm](https://www.npmjs.com/). ## Creating a New Package @@ -36,11 +36,7 @@ When creating a new package, you need to provide at least the following: } ``` This assumes that your code is located in the `src` folder and will be transpiled with `Babel`. -2. `.npmrc` file which disables creating `package-lock.json` file for the package: - ``` - package-lock=false - ``` -3. `README.md` file containing at least: +1. `README.md` file containing at least: - Package name - Package description - Installation details @@ -48,7 +44,7 @@ When creating a new package, you need to provide at least the following: - API documentation, if applicable ([more info](#maintaining-api-documentation)) - A link to the contributing guidelines ([here's an example](https://github.com/WordPress/gutenberg/tree/HEAD/packages/a11y/README.md#contributing-to-this-package) from the a11y package) - `Code is Poetry` logo (`<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p>`) -4. `CHANGELOG.md` file containing at least: +1. `CHANGELOG.md` file containing at least: ``` <!-- Learn how to maintain this file at https://github.com/WordPress/gutenberg/tree/HEAD/packages#maintaining-changelogs. --> @@ -70,35 +66,32 @@ Production dependencies are stored in the `dependencies` section of the package #### Adding New Dependencies -The simplest way to add a production dependency to one of the packages is to run a very convenient [lerna add](https://github.com/lerna/lerna/tree/HEAD/commands/add#readme) command from the root of the project. +The simplest way to add a production dependency to one of the packages is to run a command like the following from the root of the project. _Example:_ ```bash -lerna add change-case packages/a11y +npm install change-case -w packages/a11y ``` -This command adds the latest version of `change-case` as a dependency to the `@wordpress/a11y` package, which is located in `packages/a11y` folder. +This command adds the `change-case` as a dependency to the `@wordpress/a11y` package, which is located in `packages/a11y` folder. If there was the same dependency installed then the version specified in the `package-lock.json` file is going to be reused. If you want to enforce a different version, you can do so by adding the `@` suffix to the package name. + +_Example:_ + +```bash +npm install change-case@latest -w packages/a11y +``` #### Removing Existing Dependencies -Removing a dependency from one of the WordPress packages requires some manual work. You need to remove the line in the corresponding `dependencies` section of the `package.json` file. +Removing a dependency from one of the WordPress packages is similar to installation. You need to run a command like the following from the root of the project. _Example:_ -```diff -+++ b/packages/scripts/package.json -@@ -43,7 +43,6 @@ - "check-node-version": "^4.1.0", - "cross-spawn": "^5.1.0", - "eslint": "^7.1.0", -- "jest": "^29.6.2", - "minimist": "^1.2.0", - "npm-package-json-lint": "^6.4.0", +```bash +npm uninstall change-case -w packages/a11y ``` -Next, you need to run `npm install` in the root of the project to ensure that `package-lock.json` file gets properly regenerated. - #### Updating Existing Dependencies This is the most confusing part of working with [monorepo] which causes a lot of hassles for contributors. The most successful strategy so far is to do the following: @@ -239,10 +232,6 @@ For consumers to use the published type declarations, we'll set the `types` fiel Ensure that the `build-types` directory will be included in the published package, for example if a `files` field is declared. -[lerna]: https://lerna.js.org/ -[monorepo]: https://monorepo.tools -[npm]: https://www.npmjs.com/ - ## Optimizing for bundlers In order for bundlers to tree-shake packages effectively, they often need to know whether a package includes side effects in its code. This is done through the `sideEffects` field in the package's `package.json`. diff --git a/packages/a11y/.npmrc b/packages/a11y/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/a11y/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 230005587619f3..a506cb940e7765 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -31,10 +31,11 @@ "wpScriptModuleExports": "./build-module/module/index.js", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/dom-ready": "file:../dom-ready", - "@wordpress/i18n": "file:../i18n" + "@wordpress/dom-ready": "*", + "@wordpress/i18n": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/annotations/.npmrc b/packages/annotations/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/annotations/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 259745c3fd82e2..4a1f0fe2b771b5 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -27,10 +27,10 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/data": "file:../data", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/rich-text": "file:../rich-text", + "@wordpress/data": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/rich-text": "*", "uuid": "^9.0.1" }, "peerDependencies": { @@ -38,5 +38,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/api-fetch/.npmrc b/packages/api-fetch/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/api-fetch/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 35fb2da0ec1aad..79968c31d1043a 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -29,10 +29,11 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/i18n": "file:../i18n", - "@wordpress/url": "file:../url" + "@wordpress/i18n": "*", + "@wordpress/url": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/autop/.npmrc b/packages/autop/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/autop/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/autop/package.json b/packages/autop/package.json index 9e2b61ad211cff..aea14b2c666e14 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -32,5 +32,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/babel-plugin-import-jsx-pragma/.npmrc b/packages/babel-plugin-import-jsx-pragma/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/babel-plugin-import-jsx-pragma/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/babel-plugin-makepot/.npmrc b/packages/babel-plugin-makepot/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/babel-plugin-makepot/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/babel-preset-default/.npmrc b/packages/babel-preset-default/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/babel-preset-default/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index fb8ae826e55978..777a40012d67f7 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -38,8 +38,8 @@ "@babel/preset-env": "7.25.7", "@babel/preset-typescript": "7.25.7", "@babel/runtime": "7.25.7", - "@wordpress/browserslist-config": "file:../browserslist-config", - "@wordpress/warning": "file:../warning", + "@wordpress/browserslist-config": "*", + "@wordpress/warning": "*", "browserslist": "^4.21.10", "core-js": "^3.31.0", "react": "^18.3.0" diff --git a/packages/base-styles/.npmrc b/packages/base-styles/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/base-styles/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/blob/.npmrc b/packages/blob/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/blob/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/blob/package.json b/packages/blob/package.json index 087343d1b33a04..183e6aca33dc0c 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -32,5 +32,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/block-directory/.npmrc b/packages/block-directory/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/block-directory/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 0b72a7ff2099a1..6ff9ad7d510861 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -27,24 +27,24 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@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/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/plugins": "file:../plugins", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/plugins": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", "change-case": "^4.1.2", "clsx": "^2.1.1" }, @@ -54,5 +54,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/block-editor/.npmrc b/packages/block-editor/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/block-editor/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 92392b4d9563b2..b798e626c2e90f 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -36,36 +36,36 @@ "@emotion/react": "^11.7.1", "@emotion/styled": "^11.6.0", "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/style-engine": "file:../style-engine", - "@wordpress/token-list": "file:../token-list", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/block-serialization-default-parser": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/style-engine": "*", + "@wordpress/token-list": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -87,5 +87,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/block-library/.npmrc b/packages/block-library/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/block-library/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/block-library/package.json b/packages/block-library/package.json index e9e76b8018e1d3..18ad0e46059c91 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -39,39 +39,39 @@ }, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/autop": "file:../autop", - "@wordpress/blob": "file:../blob", - "@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/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interactivity": "file:../interactivity", - "@wordpress/interactivity-router": "file:../interactivity-router", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/server-side-render": "file:../server-side-render", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/autop": "*", + "@wordpress/blob": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interactivity": "*", + "@wordpress/interactivity-router": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/rich-text": "*", + "@wordpress/server-side-render": "*", + "@wordpress/url": "*", + "@wordpress/viewport": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -88,5 +88,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/block-serialization-default-parser/.npmrc b/packages/block-serialization-default-parser/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/block-serialization-default-parser/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 3b159dc3534888..14d2db0f688688 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -33,5 +33,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/block-serialization-spec-parser/.npmrc b/packages/block-serialization-spec-parser/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/block-serialization-spec-parser/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 49c3ed6c872c73..9a871250162ca0 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -37,5 +37,6 @@ "build": "concurrently \"npm run build:js\" \"npm run build:php\"", "build:js": "pegjs --format commonjs -o ./parser.js ./grammar.pegjs", "build:php": "node bin/create-php-parser.js" - } + }, + "wpScript": true } diff --git a/packages/blocks/.npmrc b/packages/blocks/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/blocks/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 9b7665ae9c87d6..d7207548d173fc 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -30,21 +30,21 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/autop": "file:../autop", - "@wordpress/blob": "file:../blob", - "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/shortcode": "file:../shortcode", - "@wordpress/warning": "file:../warning", + "@wordpress/autop": "*", + "@wordpress/blob": "*", + "@wordpress/block-serialization-default-parser": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/shortcode": "*", + "@wordpress/warning": "*", "change-case": "^4.1.2", "colord": "^2.7.0", "fast-deep-equal": "^3.1.3", @@ -62,5 +62,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/browserslist-config/.npmrc b/packages/browserslist-config/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/browserslist-config/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/commands/.npmrc b/packages/commands/.npmrc deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/packages/commands/package.json b/packages/commands/package.json index e1529416aa7df7..4d35172ce8186d 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -28,13 +28,13 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/private-apis": "file:../private-apis", + "@wordpress/components": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/private-apis": "*", "clsx": "^2.1.1", "cmdk": "^1.0.0" }, @@ -44,5 +44,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/components/.npmrc b/packages/components/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/components/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/components/package.json b/packages/components/package.json index 16c7b6c63c0b18..a44e0afe89152b 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -43,23 +43,23 @@ "@types/gradient-parser": "0.1.3", "@types/highlight-words-core": "1.2.1", "@use-gesture/react": "^10.3.1", - "@wordpress/a11y": "file:../a11y", - "@wordpress/compose": "file:../compose", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/warning": "file:../warning", + "@wordpress/a11y": "*", + "@wordpress/compose": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keycodes": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/warning": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -83,5 +83,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/compose/.npmrc b/packages/compose/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/compose/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/compose/package.json b/packages/compose/package.json index d1eacfd72f0d86..f7aa8a3bf9b3bc 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -32,13 +32,13 @@ "dependencies": { "@babel/runtime": "7.25.7", "@types/mousetrap": "^1.6.8", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/undo-manager": "file:../undo-manager", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keycodes": "*", + "@wordpress/priority-queue": "*", + "@wordpress/undo-manager": "*", "change-case": "^4.1.2", "clipboard": "^2.0.11", "mousetrap": "^1.6.5", @@ -49,5 +49,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/core-commands/.npmrc b/packages/core-commands/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/core-commands/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 87dc4fb3722f50..adad0ee55afc23 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -28,19 +28,19 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/commands": "file:../commands", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/router": "file:../router", - "@wordpress/url": "file:../url" + "@wordpress/block-editor": "*", + "@wordpress/commands": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/private-apis": "*", + "@wordpress/router": "*", + "@wordpress/url": "*" }, "peerDependencies": { "react": "^18.0.0", @@ -48,5 +48,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/core-data/.npmrc b/packages/core-data/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/core-data/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/core-data/package.json b/packages/core-data/package.json index cd568cc60c596b..6b70fb0af3a8f4 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -32,22 +32,22 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/sync": "file:../sync", - "@wordpress/undo-manager": "file:../undo-manager", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/sync": "*", + "@wordpress/undo-manager": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", "change-case": "^4.1.2", "equivalent-key-map": "^0.2.2", "fast-deep-equal": "^3.1.3", @@ -60,5 +60,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/create-block-interactive-template/.npmrc b/packages/create-block-interactive-template/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/create-block-interactive-template/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/create-block-tutorial-template/.npmrc b/packages/create-block-tutorial-template/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/create-block-tutorial-template/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/create-block/.npmrc b/packages/create-block/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/create-block/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 06556dbfaaa342..a9215bb2699d32 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -31,7 +31,7 @@ "wp-create-block": "./index.js" }, "dependencies": { - "@wordpress/lazy-import": "file:../lazy-import", + "@wordpress/lazy-import": "*", "chalk": "^4.0.0", "change-case": "^4.1.2", "check-node-version": "^4.1.0", diff --git a/packages/customize-widgets/.npmrc b/packages/customize-widgets/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/customize-widgets/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 15cf61c352af8f..68e736c566c110 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -25,27 +25,27 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/widgets": "file:../widgets", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interface": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/media-utils": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/widgets": "*", "clsx": "^2.1.1", "fast-deep-equal": "^3.1.3" }, @@ -55,5 +55,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 2820445254f0f4..84462f49e5c0c8 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -29,14 +29,15 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated" + "@wordpress/api-fetch": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*" }, "peerDependencies": { "react": "^18.0.0" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/data/.npmrc b/packages/data/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/data/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/data/package.json b/packages/data/package.json index b3adf78a2f3932..5e1817f0fb6ad8 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -30,13 +30,13 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/compose": "file:../compose", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/redux-routine": "file:../redux-routine", + "@wordpress/compose": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/priority-queue": "*", + "@wordpress/private-apis": "*", + "@wordpress/redux-routine": "*", "deepmerge": "^4.3.0", "equivalent-key-map": "^0.2.2", "is-plain-object": "^5.0.0", @@ -50,5 +50,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/dataviews/.npmrc b/packages/dataviews/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/dataviews/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index d95e079033c3b6..a83fd163517d0a 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -30,15 +30,15 @@ "dependencies": { "@ariakit/react": "^0.4.10", "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/warning": "file:../warning", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/warning": "*", "clsx": "^2.1.1", "remove-accents": "^0.5.0" }, @@ -47,5 +47,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/date/.npmrc b/packages/date/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/date/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/date/package.json b/packages/date/package.json index 2710aeb0437be8..a5925869f2acc0 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -28,11 +28,12 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/deprecated": "file:../deprecated", + "@wordpress/deprecated": "*", "moment": "^2.29.4", "moment-timezone": "^0.5.40" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/deprecated/.npmrc b/packages/deprecated/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/deprecated/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index c44b7052c1c545..4871d5772dbb64 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -29,9 +29,10 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/hooks": "file:../hooks" + "@wordpress/hooks": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/docgen/.npmrc b/packages/docgen/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/docgen/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/dom-ready/.npmrc b/packages/dom-ready/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/dom-ready/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 62cbf25ae12e86..65334a21bd1373 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -32,5 +32,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/dom/.npmrc b/packages/dom/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/dom/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/dom/package.json b/packages/dom/package.json index 9028598f160785..9d738a07b89b99 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -30,9 +30,10 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/deprecated": "file:../deprecated" + "@wordpress/deprecated": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/e2e-test-utils-playwright/.npmrc b/packages/e2e-test-utils-playwright/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/e2e-test-utils-playwright/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/e2e-test-utils/.npmrc b/packages/e2e-test-utils/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/e2e-test-utils/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index b328245162fef1..ca116dd0264a71 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -31,9 +31,9 @@ "module": "build-module/index.js", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/url": "file:../url", + "@wordpress/api-fetch": "*", + "@wordpress/keycodes": "*", + "@wordpress/url": "*", "change-case": "^4.1.2", "form-data": "^4.0.0", "node-fetch": "2.7.0" diff --git a/packages/e2e-tests/.npmrc b/packages/e2e-tests/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/e2e-tests/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index a2192c10049380..5bf2b5c8663ac7 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -24,13 +24,13 @@ "npm": ">=8.19.2" }, "dependencies": { - "@wordpress/e2e-test-utils": "file:../e2e-test-utils", - "@wordpress/interactivity": "file:../interactivity", - "@wordpress/interactivity-router": "file:../interactivity-router", - "@wordpress/jest-console": "file:../jest-console", - "@wordpress/jest-puppeteer-axe": "file:../jest-puppeteer-axe", - "@wordpress/scripts": "file:../scripts", - "@wordpress/url": "file:../url", + "@wordpress/e2e-test-utils": "*", + "@wordpress/interactivity": "*", + "@wordpress/interactivity-router": "*", + "@wordpress/jest-console": "*", + "@wordpress/jest-puppeteer-axe": "*", + "@wordpress/scripts": "*", + "@wordpress/url": "*", "chalk": "^4.0.0", "expect-puppeteer": "^4.4.0", "filenamify": "^4.2.0", diff --git a/packages/edit-post/.npmrc b/packages/edit-post/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/edit-post/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index e2653a2dab9736..028520e79cad7a 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -28,35 +28,35 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-commands": "file:../core-commands", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/warning": "file:../warning", - "@wordpress/widgets": "file:../widgets", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-commands": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", + "@wordpress/viewport": "*", + "@wordpress/warning": "*", + "@wordpress/widgets": "*", "clsx": "^2.1.1", "memize": "^2.1.0" }, @@ -66,5 +66,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/edit-site/.npmrc b/packages/edit-site/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/edit-site/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index e187acbb1b653f..83cae4a7100bc7 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -29,45 +29,45 @@ "dependencies": { "@babel/runtime": "7.25.7", "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-commands": "file:../core-commands", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/primitives": "file:../primitives", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/router": "file:../router", - "@wordpress/style-engine": "file:../style-engine", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/widgets": "file:../widgets", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-commands": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dataviews": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/primitives": "*", + "@wordpress/priority-queue": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/router": "*", + "@wordpress/style-engine": "*", + "@wordpress/url": "*", + "@wordpress/viewport": "*", + "@wordpress/widgets": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.9.2", @@ -81,5 +81,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/edit-widgets/.npmrc b/packages/edit-widgets/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/edit-widgets/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index cc2b97ac809d01..1b412c5adb78c3 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -28,33 +28,33 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/url": "file:../url", - "@wordpress/widgets": "file:../widgets", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interface": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/media-utils": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/url": "*", + "@wordpress/widgets": "*", "clsx": "^2.1.1" }, "peerDependencies": { @@ -63,5 +63,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/editor/.npmrc b/packages/editor/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/editor/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/editor/package.json b/packages/editor/package.json index 7568d0d6b8470f..8c799085875c20 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -32,41 +32,41 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/fields": "file:../fields", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/server-side-render": "file:../server-side-render", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dataviews": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/fields": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interface": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/media-utils": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/rich-text": "*", + "@wordpress/server-side-render": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "client-zip": "^2.4.5", "clsx": "^2.1.1", @@ -85,5 +85,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/element/.npmrc b/packages/element/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/element/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/element/package.json b/packages/element/package.json index 7efc62530eadb9..51e08e534b271e 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -32,7 +32,7 @@ "@babel/runtime": "7.25.7", "@types/react": "^18.2.79", "@types/react-dom": "^18.2.25", - "@wordpress/escape-html": "file:../escape-html", + "@wordpress/escape-html": "*", "change-case": "^4.1.2", "is-plain-object": "^5.0.0", "react": "^18.3.0", @@ -40,5 +40,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/env/.npmrc b/packages/env/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/env/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/escape-html/.npmrc b/packages/escape-html/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/escape-html/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index bc72f326e70b19..cadf7e9eaa174c 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -32,5 +32,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/eslint-plugin/.npmrc b/packages/eslint-plugin/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/eslint-plugin/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 5605f343ef5fd9..4a85de55f671a3 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -34,8 +34,8 @@ "@babel/eslint-parser": "7.25.7", "@typescript-eslint/eslint-plugin": "^6.4.1", "@typescript-eslint/parser": "^6.4.1", - "@wordpress/babel-preset-default": "file:../babel-preset-default", - "@wordpress/prettier-config": "file:../prettier-config", + "@wordpress/babel-preset-default": "*", + "@wordpress/prettier-config": "*", "cosmiconfig": "^7.0.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.2", diff --git a/packages/fields/.npmrc b/packages/fields/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/fields/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/fields/package.json b/packages/fields/package.json index 1f470e6ecba64c..019ec99ed7a8ed 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -32,25 +32,25 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dataviews": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", "change-case": "4.1.2", "client-zip": "^2.4.5" }, @@ -59,5 +59,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/format-library/.npmrc b/packages/format-library/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/format-library/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/format-library/package.json b/packages/format-library/package.json index 636552b7408a8c..e30ca517de794e 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -27,18 +27,18 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/url": "file:../url" + "@wordpress/a11y": "*", + "@wordpress/block-editor": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/url": "*" }, "peerDependencies": { "react": "^18.0.0", @@ -46,5 +46,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/hooks/.npmrc b/packages/hooks/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/hooks/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 8f8674d0fd4c22..04a0865f5c44ae 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -31,5 +31,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/html-entities/.npmrc b/packages/html-entities/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/html-entities/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 4079728d6ae085..7ccf5d52f55fb7 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -32,5 +32,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/i18n/.npmrc b/packages/i18n/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/i18n/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 51950104c52e4a..f2ccf4b0fa2934 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/hooks": "file:../hooks", + "@wordpress/hooks": "*", "gettext-parser": "^1.3.1", "memize": "^2.1.0", "sprintf-js": "^1.1.1", @@ -39,5 +39,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/icons/.npmrc b/packages/icons/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/icons/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/icons/package.json b/packages/icons/package.json index 28dedd381de029..a2e3c97b67b55e 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -30,10 +30,11 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", - "@wordpress/primitives": "file:../primitives" + "@wordpress/element": "*", + "@wordpress/primitives": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/interactivity-router/.npmrc b/packages/interactivity-router/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/interactivity-router/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index bb482450699027..2d33456a5712b0 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -28,8 +28,8 @@ "types": "build-types", "wpScriptModuleExports": "./build-module/index.js", "dependencies": { - "@wordpress/a11y": "file:../a11y", - "@wordpress/interactivity": "file:../interactivity" + "@wordpress/a11y": "*", + "@wordpress/interactivity": "*" }, "publishConfig": { "access": "public" diff --git a/packages/interactivity/.npmrc b/packages/interactivity/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/interactivity/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/interface/.npmrc b/packages/interface/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/interface/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/interface/package.json b/packages/interface/package.json index 964960afc2e1b9..e5870e0dfadfb2 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -33,18 +33,18 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/viewport": "file:../viewport", + "@wordpress/a11y": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/viewport": "*", "clsx": "^2.1.1" }, "peerDependencies": { @@ -53,5 +53,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/is-shallow-equal/.npmrc b/packages/is-shallow-equal/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/is-shallow-equal/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 617f0415935d88..1034ce1e76cda8 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -41,5 +41,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/jest-console/.npmrc b/packages/jest-console/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/jest-console/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/jest-preset-default/.npmrc b/packages/jest-preset-default/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/jest-preset-default/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 953e923dda253b..2db25a45f5b8e7 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -31,7 +31,7 @@ ], "main": "index.js", "dependencies": { - "@wordpress/jest-console": "file:../jest-console", + "@wordpress/jest-console": "*", "babel-jest": "29.7.0" }, "peerDependencies": { diff --git a/packages/jest-puppeteer-axe/.npmrc b/packages/jest-puppeteer-axe/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/jest-puppeteer-axe/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/keyboard-shortcuts/.npmrc b/packages/keyboard-shortcuts/.npmrc deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 7ef7599e296566..4687df000bb3a7 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -27,14 +27,15 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/keycodes": "file:../keycodes" + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/keycodes": "*" }, "peerDependencies": { "react": "^18.0.0" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/keycodes/.npmrc b/packages/keycodes/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/keycodes/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 8ec0c6278595cf..cce62c927fa206 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -29,9 +29,10 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/i18n": "file:../i18n" + "@wordpress/i18n": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/lazy-import/.npmrc b/packages/lazy-import/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/lazy-import/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/list-reusable-blocks/.npmrc b/packages/list-reusable-blocks/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/list-reusable-blocks/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 8ee807dd4404f0..d5a7dace810b48 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -27,12 +27,12 @@ "module": "build-module/index.js", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", "change-case": "^4.1.2" }, "peerDependencies": { @@ -41,5 +41,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/media-utils/.npmrc b/packages/media-utils/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/media-utils/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 67adfe9673db28..0ba56f26706833 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -28,12 +28,13 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n" + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/notices/.npmrc b/packages/notices/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/notices/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/notices/package.json b/packages/notices/package.json index 798965e93b25ce..de04c49a26cd6e 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -28,13 +28,14 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/data": "file:../data" + "@wordpress/a11y": "*", + "@wordpress/data": "*" }, "peerDependencies": { "react": "^18.0.0" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/npm-package-json-lint-config/.npmrc b/packages/npm-package-json-lint-config/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/npm-package-json-lint-config/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/nux/.npmrc b/packages/nux/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/nux/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/nux/package.json b/packages/nux/package.json index b6b6695b5b1058..122bb2758263d6 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -32,13 +32,13 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons" + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*" }, "peerDependencies": { "react": "^18.0.0", @@ -46,5 +46,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/patterns/.npmrc b/packages/patterns/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/patterns/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 6d1dc87554bc36..3da30812d61edd 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -32,20 +32,20 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@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/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url" + "@wordpress/a11y": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*" }, "peerDependencies": { "react": "^18.0.0", @@ -53,5 +53,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/plugins/.npmrc b/packages/plugins/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/plugins/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 0fc38303213f25..a2ce790e0935e5 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -28,12 +28,12 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/icons": "*", + "@wordpress/is-shallow-equal": "*", "memize": "^2.0.1" }, "peerDependencies": { @@ -42,5 +42,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/postcss-plugins-preset/.npmrc b/packages/postcss-plugins-preset/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/postcss-plugins-preset/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index e5c1e2ab1629ec..82753b0ff56d38 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -30,7 +30,7 @@ ], "main": "lib/index.js", "dependencies": { - "@wordpress/base-styles": "file:../base-styles", + "@wordpress/base-styles": "*", "autoprefixer": "^10.2.5" }, "peerDependencies": { diff --git a/packages/postcss-themes/.npmrc b/packages/postcss-themes/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/postcss-themes/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/preferences-persistence/.npmrc b/packages/preferences-persistence/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/preferences-persistence/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index cd2d86b61264eb..e91c8f295d4653 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -29,9 +29,10 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch" + "@wordpress/api-fetch": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/preferences/.npmrc b/packages/preferences/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/preferences/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/preferences/package.json b/packages/preferences/package.json index 8dc6b2f919a20c..ef9f0ef8803dfc 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -30,15 +30,15 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/private-apis": "file:../private-apis", + "@wordpress/a11y": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/private-apis": "*", "clsx": "^2.1.1" }, "peerDependencies": { @@ -47,5 +47,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/prettier-config/.npmrc b/packages/prettier-config/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/prettier-config/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/primitives/.npmrc b/packages/primitives/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/primitives/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/primitives/package.json b/packages/primitives/package.json index b81a5049d05b5e..67117e037002c6 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -32,7 +32,7 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", + "@wordpress/element": "*", "clsx": "^2.1.1" }, "peerDependencies": { @@ -40,5 +40,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/priority-queue/.npmrc b/packages/priority-queue/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/priority-queue/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 0e0dde33cc39a0..0113bb9b1bc62c 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -34,5 +34,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index a76fff0de91f5f..eae83e1fc46d34 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -33,5 +33,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/project-management-automation/.npmrc b/packages/project-management-automation/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/project-management-automation/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 77dc00b1b8e273..6a741d33f997c1 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -29,11 +29,12 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", + "@wordpress/element": "*", + "@wordpress/i18n": "*", "utility-types": "^3.10.0" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/react-native-aztec/.npmrc b/packages/react-native-aztec/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/react-native-aztec/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/react-native-aztec/package.json b/packages/react-native-aztec/package.json index e2f5d5f425d869..b0327b531395e5 100644 --- a/packages/react-native-aztec/package.json +++ b/packages/react-native-aztec/package.json @@ -23,8 +23,8 @@ "npm": ">=8.19.2" }, "dependencies": { - "@wordpress/element": "file:../element", - "@wordpress/keycodes": "file:../keycodes" + "@wordpress/element": "*", + "@wordpress/keycodes": "*" }, "peerDependencies": { "react": "*", diff --git a/packages/react-native-bridge/.npmrc b/packages/react-native-bridge/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/react-native-bridge/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/react-native-bridge/package.json b/packages/react-native-bridge/package.json index 925b83103dca00..b0c0a2485520df 100644 --- a/packages/react-native-bridge/package.json +++ b/packages/react-native-bridge/package.json @@ -24,7 +24,7 @@ "main": "index.js", "react-native": "index", "dependencies": { - "@wordpress/react-native-aztec": "file:../react-native-aztec" + "@wordpress/react-native-aztec": "*" }, "peerDependencies": { "react-native": "*" diff --git a/packages/react-native-editor/.npmrc b/packages/react-native-editor/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/react-native-editor/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json index 3a345a23e0a5d9..e6e53af1190ad7 100644 --- a/packages/react-native-editor/package.json +++ b/packages/react-native-editor/package.json @@ -38,18 +38,18 @@ "@react-navigation/native": "6.0.14", "@react-navigation/routers": "5.4.9", "@react-navigation/stack": "6.3.5", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/data": "file:../data", - "@wordpress/edit-post": "file:../edit-post", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/react-native-aztec": "file:../react-native-aztec", - "@wordpress/react-native-bridge": "file:../react-native-bridge", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/data": "*", + "@wordpress/edit-post": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/react-native-aztec": "*", + "@wordpress/react-native-bridge": "*", "core-js": "^3.31.0", "fast-average-color": "^9.1.1", "gettext-parser": "^1.3.1", diff --git a/packages/readable-js-assets-webpack-plugin/.npmrc b/packages/readable-js-assets-webpack-plugin/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/readable-js-assets-webpack-plugin/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/redux-routine/.npmrc b/packages/redux-routine/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/redux-routine/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 46dffc7e069e19..70d1cae1a8b5fd 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -40,5 +40,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/report-flaky-tests/.npmrc b/packages/report-flaky-tests/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/report-flaky-tests/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/reusable-blocks/.npmrc b/packages/reusable-blocks/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/reusable-blocks/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 483ecceeb9e252..461a17001b0c38 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -30,17 +30,17 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url" + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*" }, "peerDependencies": { "react": "^18.0.0", @@ -48,5 +48,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/rich-text/.npmrc b/packages/rich-text/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/rich-text/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index a4a15743a13ed5..c2b99faaa72d7f 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -32,14 +32,14 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/i18n": "file:../i18n", - "@wordpress/keycodes": "file:../keycodes", + "@wordpress/a11y": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/i18n": "*", + "@wordpress/keycodes": "*", "memize": "^2.1.0" }, "peerDependencies": { @@ -47,5 +47,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/router/.npmrc b/packages/router/.npmrc deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/packages/router/package.json b/packages/router/package.json index a7a181fbde9705..d7a1219e0b95cf 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -28,9 +28,9 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", + "@wordpress/element": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", "history": "^5.3.0" }, "peerDependencies": { @@ -38,5 +38,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/scripts/.npmrc b/packages/scripts/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/scripts/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 66461f4eb28ec2..20da2369c3d64a 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -35,16 +35,16 @@ "@babel/core": "7.25.7", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", "@svgr/webpack": "^8.0.1", - "@wordpress/babel-preset-default": "file:../babel-preset-default", - "@wordpress/browserslist-config": "file:../browserslist-config", - "@wordpress/dependency-extraction-webpack-plugin": "file:../dependency-extraction-webpack-plugin", - "@wordpress/e2e-test-utils-playwright": "file:../e2e-test-utils-playwright", - "@wordpress/eslint-plugin": "file:../eslint-plugin", - "@wordpress/jest-preset-default": "file:../jest-preset-default", - "@wordpress/npm-package-json-lint-config": "file:../npm-package-json-lint-config", - "@wordpress/postcss-plugins-preset": "file:../postcss-plugins-preset", - "@wordpress/prettier-config": "file:../prettier-config", - "@wordpress/stylelint-config": "file:../stylelint-config", + "@wordpress/babel-preset-default": "*", + "@wordpress/browserslist-config": "*", + "@wordpress/dependency-extraction-webpack-plugin": "*", + "@wordpress/e2e-test-utils-playwright": "*", + "@wordpress/eslint-plugin": "*", + "@wordpress/jest-preset-default": "*", + "@wordpress/npm-package-json-lint-config": "*", + "@wordpress/postcss-plugins-preset": "*", + "@wordpress/prettier-config": "*", + "@wordpress/stylelint-config": "*", "adm-zip": "^0.5.9", "babel-jest": "29.7.0", "babel-loader": "9.2.1", diff --git a/packages/server-side-render/.npmrc b/packages/server-side-render/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/server-side-render/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index b91da1f10127b4..a40d4358c35308 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -28,15 +28,15 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/url": "file:../url", + "@wordpress/api-fetch": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/url": "*", "fast-deep-equal": "^3.1.3" }, "peerDependencies": { @@ -45,5 +45,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/shortcode/.npmrc b/packages/shortcode/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/shortcode/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index 7b0b965df6d926..c10007806383d9 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -31,5 +31,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/style-engine/.npmrc b/packages/style-engine/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/style-engine/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 670861a7ca8c97..ed6eebf9483d17 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -35,5 +35,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/stylelint-config/.npmrc b/packages/stylelint-config/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/stylelint-config/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/sync/.npmrc b/packages/sync/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/sync/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/sync/package.json b/packages/sync/package.json index 1e79d4673b47dd..27ed67971b7ca9 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -30,7 +30,7 @@ "dependencies": { "@babel/runtime": "7.25.7", "@types/simple-peer": "^9.11.5", - "@wordpress/url": "file:../url", + "@wordpress/url": "*", "import-locals": "^2.0.0", "lib0": "^0.2.42", "simple-peer": "^9.11.0", @@ -41,5 +41,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/token-list/.npmrc b/packages/token-list/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/token-list/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/token-list/package.json b/packages/token-list/package.json index c4fdfde1af6d01..e73fc1918ec55e 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -31,5 +31,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/undo-manager/.npmrc b/packages/undo-manager/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/undo-manager/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 3a7c61dc620ec4..9e31c9c0d6dd7f 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -30,9 +30,10 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal" + "@wordpress/is-shallow-equal": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/url/.npmrc b/packages/url/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/url/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/url/package.json b/packages/url/package.json index 9631694dc5e2b1..e7228be292bf03 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -33,5 +33,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/viewport/.npmrc b/packages/viewport/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/viewport/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/viewport/package.json b/packages/viewport/package.json index c5e46e4700e96b..916776cdbe98b3 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -27,14 +27,15 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element" + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/element": "*" }, "peerDependencies": { "react": "^18.0.0" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/warning/.npmrc b/packages/warning/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/warning/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/warning/package.json b/packages/warning/package.json index 4191f7f1e38a06..d9d4835a220f0a 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -29,5 +29,6 @@ "sideEffects": false, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/widgets/.npmrc b/packages/widgets/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/widgets/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 9fdf32172eb723..d85e06c399b2d9 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -25,17 +25,17 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@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/notices": "file:../notices", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", "clsx": "^2.1.1" }, "peerDependencies": { @@ -44,5 +44,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/wordcount/.npmrc b/packages/wordcount/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/wordcount/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index 5ad2fd1908d727..f2fa54e449da51 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -31,5 +31,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/tools/webpack/packages.js b/tools/webpack/packages.js index 76d460cafc15d0..371a219be5f3f5 100644 --- a/tools/webpack/packages.js +++ b/tools/webpack/packages.js @@ -4,6 +4,7 @@ const CopyWebpackPlugin = require( 'copy-webpack-plugin' ); const MomentTimezoneDataPlugin = require( 'moment-timezone-data-webpack-plugin' ); const { join } = require( 'path' ); +const { readdirSync } = require( 'node:fs' ); /** * WordPress dependencies @@ -16,7 +17,12 @@ const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extrac /** * Internal dependencies */ -const { dependencies } = require( '../../package' ); +const packageDirs = readdirSync( + new URL( '../packages', `file://${ __dirname }` ), + { + withFileTypes: true, + } +).flatMap( ( dirent ) => ( dirent.isDirectory() ? [ dirent.name ] : [] ) ); const { baseConfig, plugins, stylesTransform } = require( './shared' ); const WORDPRESS_NAMESPACE = '@wordpress/'; @@ -82,15 +88,23 @@ const bundledPackagesPhpConfig = [ }, } ) ); -const gutenbergPackages = Object.keys( dependencies ) - .filter( - ( packageName ) => - ! BUNDLED_PACKAGES.includes( packageName ) && - packageName.startsWith( WORDPRESS_NAMESPACE ) && - ! packageName.startsWith( WORDPRESS_NAMESPACE + 'react-native' ) && - ! packageName.startsWith( WORDPRESS_NAMESPACE + 'interactivity' ) - ) - .map( ( packageName ) => packageName.replace( WORDPRESS_NAMESPACE, '' ) ); +/** @type {Array<string>} */ +const gutenbergScripts = []; +for ( const packageDir of packageDirs ) { + const packageJson = require( + `${ WORDPRESS_NAMESPACE }${ packageDir }/package.json` + ); + + if ( ! packageJson.wpScript ) { + continue; + } + + if ( BUNDLED_PACKAGES.includes( packageJson.name ) ) { + continue; + } + + gutenbergScripts.push( packageDir ); +} const exportDefaultPackages = [ 'api-fetch', @@ -114,7 +128,7 @@ module.exports = { ...baseConfig, name: 'packages', entry: Object.fromEntries( - gutenbergPackages.map( ( packageName ) => [ + gutenbergScripts.map( ( packageName ) => [ packageName, { import: `./packages/${ packageName }`, @@ -148,7 +162,7 @@ module.exports = { ...plugins, new DependencyExtractionWebpackPlugin( { injectPolyfill: false } ), new CopyWebpackPlugin( { - patterns: gutenbergPackages + patterns: gutenbergScripts .map( ( packageName ) => ( { from: '*.css', context: `./packages/${ packageName }/build-style`, diff --git a/tools/webpack/script-modules.js b/tools/webpack/script-modules.js index 021f11f5f5ed95..aac387ee32957a 100644 --- a/tools/webpack/script-modules.js +++ b/tools/webpack/script-modules.js @@ -2,6 +2,7 @@ * External dependencies */ const { join } = require( 'path' ); +const { readdirSync } = require( 'node:fs' ); /** * WordPress dependencies @@ -14,39 +15,25 @@ const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extrac const { baseConfig, plugins } = require( './shared' ); const WORDPRESS_NAMESPACE = '@wordpress/'; -const { createRequire } = require( 'node:module' ); -const rootURL = new URL( '..', `file://${ __dirname }` ); -const fromRootRequire = createRequire( rootURL ); - -/** @type {Iterable<[string, string]>} */ -const iterableDeps = Object.entries( - fromRootRequire( './package.json' ).dependencies -); +const packageDirs = readdirSync( + new URL( '../packages', `file://${ __dirname }` ), + { + withFileTypes: true, + } +).flatMap( ( dirent ) => ( dirent.isDirectory() ? [ dirent.name ] : [] ) ); /** @type {Map<string, string>} */ const gutenbergScriptModules = new Map(); -for ( const [ packageName, versionSpecifier ] of iterableDeps ) { - if ( - ! packageName.startsWith( WORDPRESS_NAMESPACE ) || - ! versionSpecifier.startsWith( 'file:' ) || - packageName.startsWith( WORDPRESS_NAMESPACE + 'react-native' ) - ) { - continue; - } - - const packageRequire = createRequire( - // Remove the leading "file:" specifier to build a package URL. - new URL( `${ versionSpecifier.substring( 5 ) }/`, rootURL ) - ); +for ( const packageDir of packageDirs ) { + const packageJson = require( `@wordpress/${ packageDir }/package.json` ); - const depPackageJson = packageRequire( './package.json' ); - if ( ! Object.hasOwn( depPackageJson, 'wpScriptModuleExports' ) ) { + if ( ! Object.hasOwn( packageJson, 'wpScriptModuleExports' ) ) { continue; } - const moduleName = packageName.substring( WORDPRESS_NAMESPACE.length ); - let { wpScriptModuleExports } = depPackageJson; + const moduleName = packageJson.name.substring( WORDPRESS_NAMESPACE.length ); + let { wpScriptModuleExports } = packageJson; // Special handling for { "wpScriptModuleExports": "./build-module/index.js" }. if ( typeof wpScriptModuleExports === 'string' ) { @@ -75,7 +62,7 @@ for ( const [ packageName, versionSpecifier ] of iterableDeps ) { gutenbergScriptModules.set( `${ moduleName }/${ name }`, - packageRequire.resolve( exportPath ) + require.resolve( `@wordpress/${ packageDir }/${ exportPath }` ) ); } } From 91272a2b4bfca1f75a6754a0f3689c3a42988f0c Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Mon, 21 Oct 2024 10:42:58 +0200 Subject: [PATCH 1255/1908] Revert "Packages: Use npm workspaces (#65681)" (#66270) This reverts commit 4693c0f9942f11f48e0912db378b1b9e2fbf4af0. --- bin/check-licenses.mjs | 69 - docs/contributors/code/managing-packages.md | 6 +- package-lock.json | 5698 ++++++++++++----- package.json | 110 +- packages/README.md | 41 +- packages/a11y/.npmrc | 1 + packages/a11y/package.json | 7 +- packages/annotations/.npmrc | 1 + packages/annotations/package.json | 11 +- packages/api-fetch/.npmrc | 1 + packages/api-fetch/package.json | 7 +- packages/autop/.npmrc | 1 + packages/autop/package.json | 3 +- .../babel-plugin-import-jsx-pragma/.npmrc | 1 + packages/babel-plugin-makepot/.npmrc | 1 + packages/babel-preset-default/.npmrc | 1 + packages/babel-preset-default/package.json | 4 +- packages/base-styles/.npmrc | 1 + packages/blob/.npmrc | 1 + packages/blob/package.json | 3 +- packages/block-directory/.npmrc | 1 + packages/block-directory/package.json | 39 +- packages/block-editor/.npmrc | 1 + packages/block-editor/package.json | 63 +- packages/block-library/.npmrc | 1 + packages/block-library/package.json | 69 +- .../block-serialization-default-parser/.npmrc | 1 + .../package.json | 3 +- .../block-serialization-spec-parser/.npmrc | 1 + .../package.json | 3 +- packages/blocks/.npmrc | 1 + packages/blocks/package.json | 33 +- packages/browserslist-config/.npmrc | 1 + packages/commands/.npmrc | 0 packages/commands/package.json | 17 +- packages/components/.npmrc | 1 + packages/components/package.json | 37 +- packages/compose/.npmrc | 1 + packages/compose/package.json | 17 +- packages/core-commands/.npmrc | 1 + packages/core-commands/package.json | 29 +- packages/core-data/.npmrc | 1 + packages/core-data/package.json | 35 +- .../create-block-interactive-template/.npmrc | 1 + .../create-block-tutorial-template/.npmrc | 1 + packages/create-block/.npmrc | 1 + packages/create-block/package.json | 2 +- packages/customize-widgets/.npmrc | 1 + packages/customize-widgets/package.json | 45 +- packages/data-controls/package.json | 9 +- packages/data/.npmrc | 1 + packages/data/package.json | 17 +- packages/dataviews/.npmrc | 1 + packages/dataviews/package.json | 21 +- packages/date/.npmrc | 1 + packages/date/package.json | 5 +- packages/deprecated/.npmrc | 1 + packages/deprecated/package.json | 5 +- packages/docgen/.npmrc | 1 + packages/dom-ready/.npmrc | 1 + packages/dom-ready/package.json | 3 +- packages/dom/.npmrc | 1 + packages/dom/package.json | 5 +- packages/e2e-test-utils-playwright/.npmrc | 1 + packages/e2e-test-utils/.npmrc | 1 + packages/e2e-test-utils/package.json | 6 +- packages/e2e-tests/.npmrc | 1 + packages/e2e-tests/package.json | 14 +- packages/edit-post/.npmrc | 1 + packages/edit-post/package.json | 61 +- packages/edit-site/.npmrc | 1 + packages/edit-site/package.json | 81 +- packages/edit-widgets/.npmrc | 1 + packages/edit-widgets/package.json | 57 +- packages/editor/.npmrc | 1 + packages/editor/package.json | 73 +- packages/element/.npmrc | 1 + packages/element/package.json | 5 +- packages/env/.npmrc | 1 + packages/escape-html/.npmrc | 1 + packages/escape-html/package.json | 3 +- packages/eslint-plugin/.npmrc | 1 + packages/eslint-plugin/package.json | 4 +- packages/fields/.npmrc | 1 + packages/fields/package.json | 41 +- packages/format-library/.npmrc | 1 + packages/format-library/package.json | 27 +- packages/hooks/.npmrc | 1 + packages/hooks/package.json | 3 +- packages/html-entities/.npmrc | 1 + packages/html-entities/package.json | 3 +- packages/i18n/.npmrc | 1 + packages/i18n/package.json | 5 +- packages/icons/.npmrc | 1 + packages/icons/package.json | 7 +- packages/interactivity-router/.npmrc | 1 + packages/interactivity-router/package.json | 4 +- packages/interactivity/.npmrc | 1 + packages/interface/.npmrc | 1 + packages/interface/package.json | 27 +- packages/is-shallow-equal/.npmrc | 1 + packages/is-shallow-equal/package.json | 3 +- packages/jest-console/.npmrc | 1 + packages/jest-preset-default/.npmrc | 1 + packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/.npmrc | 1 + packages/keyboard-shortcuts/.npmrc | 0 packages/keyboard-shortcuts/package.json | 9 +- packages/keycodes/.npmrc | 1 + packages/keycodes/package.json | 5 +- packages/lazy-import/.npmrc | 1 + packages/list-reusable-blocks/.npmrc | 1 + packages/list-reusable-blocks/package.json | 15 +- packages/media-utils/.npmrc | 1 + packages/media-utils/package.json | 11 +- packages/notices/.npmrc | 1 + packages/notices/package.json | 7 +- packages/npm-package-json-lint-config/.npmrc | 1 + packages/nux/.npmrc | 1 + packages/nux/package.json | 17 +- packages/patterns/.npmrc | 1 + packages/patterns/package.json | 31 +- packages/plugins/.npmrc | 1 + packages/plugins/package.json | 15 +- packages/postcss-plugins-preset/.npmrc | 1 + packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/.npmrc | 1 + packages/preferences-persistence/.npmrc | 1 + packages/preferences-persistence/package.json | 5 +- packages/preferences/.npmrc | 1 + packages/preferences/package.json | 21 +- packages/prettier-config/.npmrc | 1 + packages/primitives/.npmrc | 1 + packages/primitives/package.json | 5 +- packages/priority-queue/.npmrc | 1 + packages/priority-queue/package.json | 3 +- packages/private-apis/package.json | 3 +- packages/project-management-automation/.npmrc | 1 + packages/react-i18n/package.json | 7 +- packages/react-native-aztec/.npmrc | 1 + packages/react-native-aztec/package.json | 4 +- packages/react-native-bridge/.npmrc | 1 + packages/react-native-bridge/package.json | 2 +- packages/react-native-editor/.npmrc | 1 + packages/react-native-editor/package.json | 24 +- .../readable-js-assets-webpack-plugin/.npmrc | 1 + packages/redux-routine/.npmrc | 1 + packages/redux-routine/package.json | 3 +- packages/report-flaky-tests/.npmrc | 1 + packages/reusable-blocks/.npmrc | 1 + packages/reusable-blocks/package.json | 25 +- packages/rich-text/.npmrc | 1 + packages/rich-text/package.json | 19 +- packages/router/.npmrc | 0 packages/router/package.json | 9 +- packages/scripts/.npmrc | 1 + packages/scripts/package.json | 20 +- packages/server-side-render/.npmrc | 1 + packages/server-side-render/package.json | 21 +- packages/shortcode/.npmrc | 1 + packages/shortcode/package.json | 3 +- packages/style-engine/.npmrc | 1 + packages/style-engine/package.json | 3 +- packages/stylelint-config/.npmrc | 1 + packages/sync/.npmrc | 1 + packages/sync/package.json | 5 +- packages/token-list/.npmrc | 1 + packages/token-list/package.json | 3 +- packages/undo-manager/.npmrc | 1 + packages/undo-manager/package.json | 5 +- packages/url/.npmrc | 1 + packages/url/package.json | 3 +- packages/viewport/.npmrc | 1 + packages/viewport/package.json | 9 +- packages/warning/.npmrc | 1 + packages/warning/package.json | 3 +- packages/widgets/.npmrc | 1 + packages/widgets/package.json | 25 +- packages/wordcount/.npmrc | 1 + packages/wordcount/package.json | 3 +- tools/webpack/packages.js | 38 +- tools/webpack/script-modules.js | 39 +- 182 files changed, 5020 insertions(+), 2337 deletions(-) delete mode 100755 bin/check-licenses.mjs create mode 100644 packages/a11y/.npmrc create mode 100644 packages/annotations/.npmrc create mode 100644 packages/api-fetch/.npmrc create mode 100644 packages/autop/.npmrc create mode 100644 packages/babel-plugin-import-jsx-pragma/.npmrc create mode 100644 packages/babel-plugin-makepot/.npmrc create mode 100644 packages/babel-preset-default/.npmrc create mode 100644 packages/base-styles/.npmrc create mode 100644 packages/blob/.npmrc create mode 100644 packages/block-directory/.npmrc create mode 100644 packages/block-editor/.npmrc create mode 100644 packages/block-library/.npmrc create mode 100644 packages/block-serialization-default-parser/.npmrc create mode 100644 packages/block-serialization-spec-parser/.npmrc create mode 100644 packages/blocks/.npmrc create mode 100644 packages/browserslist-config/.npmrc create mode 100644 packages/commands/.npmrc create mode 100644 packages/components/.npmrc create mode 100644 packages/compose/.npmrc create mode 100644 packages/core-commands/.npmrc create mode 100644 packages/core-data/.npmrc create mode 100644 packages/create-block-interactive-template/.npmrc create mode 100644 packages/create-block-tutorial-template/.npmrc create mode 100644 packages/create-block/.npmrc create mode 100644 packages/customize-widgets/.npmrc create mode 100644 packages/data/.npmrc create mode 100644 packages/dataviews/.npmrc create mode 100644 packages/date/.npmrc create mode 100644 packages/deprecated/.npmrc create mode 100644 packages/docgen/.npmrc create mode 100644 packages/dom-ready/.npmrc create mode 100644 packages/dom/.npmrc create mode 100644 packages/e2e-test-utils-playwright/.npmrc create mode 100644 packages/e2e-test-utils/.npmrc create mode 100644 packages/e2e-tests/.npmrc create mode 100644 packages/edit-post/.npmrc create mode 100644 packages/edit-site/.npmrc create mode 100644 packages/edit-widgets/.npmrc create mode 100644 packages/editor/.npmrc create mode 100644 packages/element/.npmrc create mode 100644 packages/env/.npmrc create mode 100644 packages/escape-html/.npmrc create mode 100644 packages/eslint-plugin/.npmrc create mode 100644 packages/fields/.npmrc create mode 100644 packages/format-library/.npmrc create mode 100644 packages/hooks/.npmrc create mode 100644 packages/html-entities/.npmrc create mode 100644 packages/i18n/.npmrc create mode 100644 packages/icons/.npmrc create mode 100644 packages/interactivity-router/.npmrc create mode 100644 packages/interactivity/.npmrc create mode 100644 packages/interface/.npmrc create mode 100644 packages/is-shallow-equal/.npmrc create mode 100644 packages/jest-console/.npmrc create mode 100644 packages/jest-preset-default/.npmrc create mode 100644 packages/jest-puppeteer-axe/.npmrc create mode 100644 packages/keyboard-shortcuts/.npmrc create mode 100644 packages/keycodes/.npmrc create mode 100644 packages/lazy-import/.npmrc create mode 100644 packages/list-reusable-blocks/.npmrc create mode 100644 packages/media-utils/.npmrc create mode 100644 packages/notices/.npmrc create mode 100644 packages/npm-package-json-lint-config/.npmrc create mode 100644 packages/nux/.npmrc create mode 100644 packages/patterns/.npmrc create mode 100644 packages/plugins/.npmrc create mode 100644 packages/postcss-plugins-preset/.npmrc create mode 100644 packages/postcss-themes/.npmrc create mode 100644 packages/preferences-persistence/.npmrc create mode 100644 packages/preferences/.npmrc create mode 100644 packages/prettier-config/.npmrc create mode 100644 packages/primitives/.npmrc create mode 100644 packages/priority-queue/.npmrc create mode 100644 packages/project-management-automation/.npmrc create mode 100644 packages/react-native-aztec/.npmrc create mode 100644 packages/react-native-bridge/.npmrc create mode 100644 packages/react-native-editor/.npmrc create mode 100644 packages/readable-js-assets-webpack-plugin/.npmrc create mode 100644 packages/redux-routine/.npmrc create mode 100644 packages/report-flaky-tests/.npmrc create mode 100644 packages/reusable-blocks/.npmrc create mode 100644 packages/rich-text/.npmrc create mode 100644 packages/router/.npmrc create mode 100644 packages/scripts/.npmrc create mode 100644 packages/server-side-render/.npmrc create mode 100644 packages/shortcode/.npmrc create mode 100644 packages/style-engine/.npmrc create mode 100644 packages/stylelint-config/.npmrc create mode 100644 packages/sync/.npmrc create mode 100644 packages/token-list/.npmrc create mode 100644 packages/undo-manager/.npmrc create mode 100644 packages/url/.npmrc create mode 100644 packages/viewport/.npmrc create mode 100644 packages/warning/.npmrc create mode 100644 packages/widgets/.npmrc create mode 100644 packages/wordcount/.npmrc diff --git a/bin/check-licenses.mjs b/bin/check-licenses.mjs deleted file mode 100755 index 458590e696a9fd..00000000000000 --- a/bin/check-licenses.mjs +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env node - -/** - * External dependencies - */ -import { spawnSync } from 'node:child_process'; - -/** - * Internal dependencies - */ -import { checkDepsInTree } from '../packages/scripts/utils/license.js'; - -const ignored = [ '@ampproject/remapping' ]; - -/* - * `wp-scripts check-licenses` uses prod and dev dependencies of the package to scan for dependencies. With npm workspaces, workspace packages (the @wordpress/* packages) are not listed in the main package json and this approach does not work. - * - * Instead, work from an npm query that uses some custom information in package.json files to declare packages that are shipped with WordPress (and must be GPLv2 compatible) or other files that may use more permissive licenses. - */ - -/** - * @typedef PackageInfo - * @property {string} name Package name. - */ - -/** @type {ReadonlyArray<PackageInfo>} */ -const workspacePackages = JSON.parse( - spawnSync( - 'npm', - [ - 'query', - '.workspace:attr([wpScript]), .workspace:attr([wpScriptModuleExports])', - ], - /* - * Set the max buffer to ~157MB, since the output size for - * prod is ~21 MB and dev is ~110 MB - */ - { maxBuffer: 1024 * 1024 * 150 } - ).stdout -); - -const packageNames = workspacePackages.map( ( { name } ) => name ); - -const dependenciesToProcess = JSON.parse( - spawnSync( - 'npm', - [ - 'ls', - '--json', - '--long', - '--all', - '--lockfile-only', - '--omit=dev', - ...packageNames.map( - ( packageName ) => `--workspace=${ packageName }` - ), - ], - /* - * Set the max buffer to ~157MB, since the output size for - * prod is ~21 MB and dev is ~110 MB - */ - { maxBuffer: 1024 * 1024 * 150 } - ).stdout -).dependencies; - -checkDepsInTree( dependenciesToProcess, { - ignored, - gpl2: true, -} ); diff --git a/docs/contributors/code/managing-packages.md b/docs/contributors/code/managing-packages.md index 8ad0266b1482bf..bfea8fed81242b 100644 --- a/docs/contributors/code/managing-packages.md +++ b/docs/contributors/code/managing-packages.md @@ -1,7 +1,11 @@ # Managing Packages -This repository uses [npm workspaces](https://docs.npmjs.com/cli/v10/using-npm/workspaces) to manage WordPress packages and [lerna](https://lerna.js.org/) to publish them to [npm](https://www.npmjs.com/). This enforces certain steps in the workflow which are described in details in [packages](https://github.com/WordPress/gutenberg/blob/HEAD/packages/README.md) documentation. +This repository uses [monorepo] to manage WordPress modules and publish them with [lerna] as packages to [npm]. This enforces certain steps in the workflow which are described in details in [packages](https://github.com/WordPress/gutenberg/blob/HEAD/packages/README.md) documentation. Maintaining dozens of npm packages is difficult—it can be tough to keep track of changes. That's why we use `CHANGELOG.md` files for each package to simplify the release process. As a contributor, you should add an entry to the aforementioned file each time you contribute adding production code as described in [Maintaining Changelogs](https://github.com/WordPress/gutenberg/blob/HEAD/packages/README.md#maintaining-changelogs) section. Publishing WordPress packages to npm is automated by synchronizing it with the bi-weekly Gutenberg plugin RC1 release. You can learn more about this process and other ways to publish new versions of npm packages in the [Gutenberg Release Process document](/docs/contributors/code/release.md#packages-releases-to-npm-and-wordpress-core-updates). + +[lerna]: https://lerna.js.org/ +[monorepo]: https://monorepo.tools +[npm]: https://www.npmjs.com/ diff --git a/package-lock.json b/package-lock.json index 288a2ee5904d7e..3c328a047fc588 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,80 @@ "version": "19.5.0-rc.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", - "workspaces": [ - "packages/*" - ], + "dependencies": { + "@wordpress/a11y": "file:packages/a11y", + "@wordpress/annotations": "file:packages/annotations", + "@wordpress/api-fetch": "file:packages/api-fetch", + "@wordpress/autop": "file:packages/autop", + "@wordpress/blob": "file:packages/blob", + "@wordpress/block-directory": "file:packages/block-directory", + "@wordpress/block-editor": "file:packages/block-editor", + "@wordpress/block-library": "file:packages/block-library", + "@wordpress/block-serialization-default-parser": "file:packages/block-serialization-default-parser", + "@wordpress/block-serialization-spec-parser": "file:packages/block-serialization-spec-parser", + "@wordpress/blocks": "file:packages/blocks", + "@wordpress/commands": "file:packages/commands", + "@wordpress/components": "file:packages/components", + "@wordpress/compose": "file:packages/compose", + "@wordpress/core-commands": "file:packages/core-commands", + "@wordpress/core-data": "file:packages/core-data", + "@wordpress/customize-widgets": "file:packages/customize-widgets", + "@wordpress/data": "file:packages/data", + "@wordpress/data-controls": "file:packages/data-controls", + "@wordpress/dataviews": "file:packages/dataviews", + "@wordpress/date": "file:packages/date", + "@wordpress/deprecated": "file:packages/deprecated", + "@wordpress/dom": "file:packages/dom", + "@wordpress/dom-ready": "file:packages/dom-ready", + "@wordpress/edit-post": "file:packages/edit-post", + "@wordpress/edit-site": "file:packages/edit-site", + "@wordpress/edit-widgets": "file:packages/edit-widgets", + "@wordpress/editor": "file:packages/editor", + "@wordpress/element": "file:packages/element", + "@wordpress/escape-html": "file:packages/escape-html", + "@wordpress/fields": "file:packages/fields", + "@wordpress/format-library": "file:packages/format-library", + "@wordpress/hooks": "file:packages/hooks", + "@wordpress/html-entities": "file:packages/html-entities", + "@wordpress/i18n": "file:packages/i18n", + "@wordpress/icons": "file:packages/icons", + "@wordpress/interactivity": "file:packages/interactivity", + "@wordpress/interactivity-router": "file:packages/interactivity-router", + "@wordpress/interface": "file:packages/interface", + "@wordpress/is-shallow-equal": "file:packages/is-shallow-equal", + "@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts", + "@wordpress/keycodes": "file:packages/keycodes", + "@wordpress/list-reusable-blocks": "file:packages/list-reusable-blocks", + "@wordpress/media-utils": "file:packages/media-utils", + "@wordpress/notices": "file:packages/notices", + "@wordpress/nux": "file:packages/nux", + "@wordpress/patterns": "file:packages/patterns", + "@wordpress/plugins": "file:packages/plugins", + "@wordpress/preferences": "file:packages/preferences", + "@wordpress/preferences-persistence": "file:packages/preferences-persistence", + "@wordpress/primitives": "file:packages/primitives", + "@wordpress/priority-queue": "file:packages/priority-queue", + "@wordpress/private-apis": "file:packages/private-apis", + "@wordpress/react-i18n": "file:packages/react-i18n", + "@wordpress/react-native-aztec": "file:packages/react-native-aztec", + "@wordpress/react-native-bridge": "file:packages/react-native-bridge", + "@wordpress/react-native-editor": "file:packages/react-native-editor", + "@wordpress/redux-routine": "file:packages/redux-routine", + "@wordpress/reusable-blocks": "file:packages/reusable-blocks", + "@wordpress/rich-text": "file:packages/rich-text", + "@wordpress/router": "file:packages/router", + "@wordpress/server-side-render": "file:packages/server-side-render", + "@wordpress/shortcode": "file:packages/shortcode", + "@wordpress/style-engine": "file:packages/style-engine", + "@wordpress/sync": "file:packages/sync", + "@wordpress/token-list": "file:packages/token-list", + "@wordpress/undo-manager": "file:packages/undo-manager", + "@wordpress/url": "file:packages/url", + "@wordpress/viewport": "file:packages/viewport", + "@wordpress/warning": "file:packages/warning", + "@wordpress/widgets": "file:packages/widgets", + "@wordpress/wordcount": "file:packages/wordcount" + }, "devDependencies": { "@actions/core": "1.9.1", "@actions/github": "5.0.0", @@ -61,6 +132,33 @@ "@types/semver": "7.3.8", "@types/sprintf-js": "1.1.2", "@types/uuid": "8.3.1", + "@wordpress/babel-plugin-import-jsx-pragma": "file:packages/babel-plugin-import-jsx-pragma", + "@wordpress/babel-plugin-makepot": "file:packages/babel-plugin-makepot", + "@wordpress/babel-preset-default": "file:packages/babel-preset-default", + "@wordpress/base-styles": "file:packages/base-styles", + "@wordpress/browserslist-config": "file:packages/browserslist-config", + "@wordpress/create-block": "file:packages/create-block", + "@wordpress/create-block-tutorial-template": "file:packages/create-block-tutorial-template", + "@wordpress/dependency-extraction-webpack-plugin": "file:packages/dependency-extraction-webpack-plugin", + "@wordpress/docgen": "file:packages/docgen", + "@wordpress/e2e-test-utils": "file:packages/e2e-test-utils", + "@wordpress/e2e-test-utils-playwright": "file:packages/e2e-test-utils-playwright", + "@wordpress/e2e-tests": "file:packages/e2e-tests", + "@wordpress/env": "file:packages/env", + "@wordpress/eslint-plugin": "file:packages/eslint-plugin", + "@wordpress/jest-console": "file:packages/jest-console", + "@wordpress/jest-preset-default": "file:packages/jest-preset-default", + "@wordpress/jest-puppeteer-axe": "file:packages/jest-puppeteer-axe", + "@wordpress/lazy-import": "file:packages/lazy-import", + "@wordpress/npm-package-json-lint-config": "file:packages/npm-package-json-lint-config", + "@wordpress/postcss-plugins-preset": "file:packages/postcss-plugins-preset", + "@wordpress/postcss-themes": "file:packages/postcss-themes", + "@wordpress/prettier-config": "file:packages/prettier-config", + "@wordpress/project-management-automation": "file:packages/project-management-automation", + "@wordpress/readable-js-assets-webpack-plugin": "file:packages/readable-js-assets-webpack-plugin", + "@wordpress/report-flaky-tests": "file:packages/report-flaky-tests", + "@wordpress/scripts": "file:packages/scripts", + "@wordpress/stylelint-config": "file:packages/stylelint-config", "ajv": "8.7.1", "appium": "2.0.0", "babel-jest": "29.7.0", @@ -166,6 +264,7 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", + "dev": true, "dependencies": { "@actions/http-client": "^2.0.1", "uuid": "^8.3.2" @@ -175,6 +274,7 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -183,6 +283,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.0.tgz", "integrity": "sha512-QvE9eAAfEsS+yOOk0cylLBIO/d6WyWIOvsxxzdrPFaud39G6BOkUwScXZn1iBzQzHyu9SBkkLSWlohDWdsasAQ==", + "dev": true, "dependencies": { "@actions/http-client": "^1.0.11", "@octokit/core": "^3.4.0", @@ -194,6 +295,7 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz", "integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==", + "dev": true, "dependencies": { "tunnel": "0.0.6" } @@ -202,6 +304,7 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", + "dev": true, "license": "MIT", "dependencies": { "tunnel": "^0.0.6", @@ -1476,6 +1579,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/@axe-core/puppeteer/-/puppeteer-4.0.0.tgz", "integrity": "sha512-APFc2iRmrmUfqdBUevjsMxJliDudWPwvCU5Pzw2uKZ0sMVtW3rQuElTcfJCHFq8KOZSSO0BPD+lK+pXOx1ta5Q==", + "dev": true, "dependencies": { "axe-core": "^4.0.1" }, @@ -1500,9 +1604,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.8.tgz", - "integrity": "sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.7.tgz", + "integrity": "sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1579,13 +1683,12 @@ } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.7.tgz", - "integrity": "sha512-12xfNeKNH7jubQNm7PAkzlLwEmCs1tfuX3UjIw6vP6QXi+leKh6+LyC/+Ed4EIQermwd58wsyh070yjDHFlNGg==", - "license": "MIT", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dev": true, "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -1629,17 +1732,18 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.7.tgz", - "integrity": "sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==", - "license": "MIT", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.9.tgz", + "integrity": "sha512-B2L9neXTIyPQoXDm+NtovPvG6VOLWnaXu3BIeVDWwdKFgG30oNa6CqVGiJPDWQwIAK49t9gnQI9c6K6RzabiKw==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-member-expression-to-functions": "^7.25.7", - "@babel/helper-optimise-call-expression": "^7.25.7", - "@babel/helper-replace-supers": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", - "@babel/traverse": "^7.25.7", + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", "semver": "^6.3.1" }, "engines": { @@ -1683,19 +1787,29 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", - "license": "MIT", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.4.tgz", + "integrity": "sha512-OrpPZ97s+aPi6h2n1OXzdhVis1SGSsMU2aMHgLcOKfsp4/v1NWpx3CWT3lBj5eeBq9cDkPkh+YCfdF7O12uNDQ==", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "resolve": "^1.14.2", + "semver": "^6.1.2" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" } }, "node_modules/@babel/helper-environment-visitor": { @@ -1706,14 +1820,36 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.7.tgz", - "integrity": "sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==", - "license": "MIT", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -1751,12 +1887,11 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.7.tgz", - "integrity": "sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==", - "license": "MIT", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", "dependencies": { - "@babel/types": "^7.25.7" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1789,14 +1924,13 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.7.tgz", - "integrity": "sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==", - "license": "MIT", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.25.7", - "@babel/helper-optimise-call-expression": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1819,13 +1953,22 @@ } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.7.tgz", - "integrity": "sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==", - "license": "MIT", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dependencies": { + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1945,6 +2088,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.7.tgz", "integrity": "sha512-UV9Lg53zyebzD1DwQoT9mzkEKa922LNUp5YkTJ6Uta0RbyXaQNUgcvSt7qIu1PpPzVb6rd10OVNTzkyBGeVmxQ==", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -1961,6 +2105,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.7.tgz", "integrity": "sha512-GDDWeVLNxRIkQTnJn2pDOM1pkCgYdSqPeT1a9vh9yIqu2uzzgw1zcqEb+IJOhy+dTBMlNdThrDIksr2o09qrrQ==", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1973,12 +2118,12 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.7.tgz", - "integrity": "sha512-wxyWg2RYaSUYgmd9MR0FyRGyeOMQE/Uzr1wzd/g5cf5bwi9A4v6HFdDm7y1MgDtod/fLOSTZY6jDgV0xU9d5bA==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1988,14 +2133,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.7.tgz", - "integrity": "sha512-Xwg6tZpLxc4iQjorYsyGMyfJE7nP5MV8t/Ka58BgiA7Jw0fRqQNcANlLfdJ/yvBt9z9LD2We+BEkT7vLqZRWng==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", - "@babel/plugin-transform-optional-chaining": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -2005,13 +2150,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.7.tgz", - "integrity": "sha512-UVATLMidXrnH+GMUIuxq55nejlj02HP7F5ETyBONzP6G87fPBogG4CH6kxrSrdIuAjdwNO9VzyaYsrZPscWUrw==", - "license": "MIT", + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", + "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2157,6 +2302,7 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -2180,6 +2326,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -2191,6 +2338,7 @@ "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -2202,6 +2350,7 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -2241,6 +2390,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -2263,12 +2413,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.7.tgz", - "integrity": "sha512-ZvZQRmME0zfJnDQnVBKYzHxXT7lYBB3Revz1GuS7oLXWMgqUPX4G+DDbT30ICClht9WKV34QVrZhSw6WdklwZQ==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2278,12 +2428,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", - "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2296,6 +2446,7 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -2307,6 +2458,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -2333,6 +2485,7 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -2413,6 +2566,7 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -2424,12 +2578,11 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.7.tgz", - "integrity": "sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2442,6 +2595,7 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -2454,12 +2608,11 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.7.tgz", - "integrity": "sha512-EJN2mKxDwfOUCPxMO6MUI58RN3ganiRAG/MS/S3HfB6QFNjroAMelQo/gybyYq97WerCBAZoyrAoW8Tzdq2jWg==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2469,13 +2622,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.8.tgz", - "integrity": "sha512-9ypqkozyzpG+HxlH4o4gdctalFGIjjdufzo7I2XPda0iBnZ6a+FO0rIEQcdSPXp02CkvGsII1exJhmROPQd5oA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.7.tgz", + "integrity": "sha512-4B6OhTrwYKHYYgcwErvZjbmH9X5TxQBsaBHdzEIB4l71gR5jh/tuHGlb9in47udL2+wVUcOz5XXhhfhVJwEpEg==", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", "@babel/helper-remap-async-to-generator": "^7.25.7", + "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/traverse": "^7.25.7" }, "engines": { @@ -2486,14 +2641,13 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.7.tgz", - "integrity": "sha512-ZUCjAavsh5CESCmi/xCpX1qcCaAglzs/7tmuvoFnJgA1dM7gQplsguljoTg+Ru8WENpX89cQyAtWoaE0I3X3Pg==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", + "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", "dependencies": { - "@babel/helper-module-imports": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-remap-async-to-generator": "^7.25.7" + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -2503,12 +2657,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.7.tgz", - "integrity": "sha512-xHttvIM9fvqW+0a3tZlYcZYSBpSWzGBFIt/sYG3tcdSzBB8ZeVgz2gBP7Df+sM0N1850jrviYSSeUuc+135dmQ==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2518,12 +2672,11 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.7.tgz", - "integrity": "sha512-ZEPJSkVZaeTFG/m2PARwLZQ+OG0vFIhPlKHK/JdIMy8DbRJ/htz6LRrTFtdzxi9EHmcwbNPAKDnadpNSIW+Aow==", - "license": "MIT", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", + "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2533,13 +2686,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.7.tgz", - "integrity": "sha512-mhyfEW4gufjIqYFo9krXHJ3ElbFLIze5IDp+wQTxoPd+mwFb1NxatNAwmv8Q8Iuxv7Zc+q8EkiMQwc9IhyGf4g==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2549,13 +2702,14 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.8.tgz", - "integrity": "sha512-e82gl3TCorath6YLf9xUwFehVvjvfqFhdOo4+0iVIVju+6XOi5XHkqB3P2AXnSwoeTX0HBoXq5gJFtvotJzFnQ==", - "license": "MIT", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", + "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { "node": ">=6.9.0" @@ -2565,16 +2719,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.7.tgz", - "integrity": "sha512-9j9rnl+YCQY0IGoeipXvnk3niWicIB6kCsWRGLwX241qSXpbA4MKxtp/EdvFxsc4zI5vqfLxzOd0twIJ7I99zg==", - "license": "MIT", + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", + "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-replace-supers": "^7.25.7", - "@babel/traverse": "^7.25.7", + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-split-export-declaration": "^7.22.6", "globals": "^11.1.0" }, "engines": { @@ -2593,13 +2748,12 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.7.tgz", - "integrity": "sha512-QIv+imtM+EtNxg/XBKL3hiWjgdLjMOmZ+XzQwSgmBfKbfxUjBzGgVPklUuE55eq5/uVoh8gg3dqlrwR/jw3ZeA==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/template": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -2609,12 +2763,11 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.7.tgz", - "integrity": "sha512-xKcfLTlJYUczdaM1+epcdh1UGewJqr9zATgrNHcLBcV2QmfvPPEixo/sK/syql9cEmbr7ulu5HMFG5vbbt/sEA==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2624,13 +2777,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.7.tgz", - "integrity": "sha512-kXzXMMRzAtJdDEgQBLF4oaiT6ZCU3oWHgpARnTKDAqPkDJ+bs3NrZb310YYevR5QlRo3Kn7dzzIdHbZm1VzJdQ==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2640,12 +2793,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.7.tgz", - "integrity": "sha512-by+v2CjoL3aMnWDOyCIg+yxU9KXSRa9tN6MbqggH5xvymmr9p4AMjYkNlQy4brMceBnUyHZ9G8RnpvT8wP7Cfg==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2658,6 +2811,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.7.tgz", "integrity": "sha512-HvS6JF66xSS5rNKXLqkk7L9c/jZ/cdIVIcoPVrnl8IsVpLggTjXs8OWekbLHs/VtYDDh5WXnQyeE3PPUGm22MA==", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.7", @@ -2671,12 +2825,13 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.8.tgz", - "integrity": "sha512-gznWY+mr4ZQL/EWPcbBQUP3BXS5FwZp8RUOw06BaRn8tQLzN4XLIxXejpHN9Qo8x8jjBmAAKp6FoS51AgkSA/A==", - "license": "MIT", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", + "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -2686,13 +2841,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.7.tgz", - "integrity": "sha512-yjqtpstPfZ0h/y40fAXRv2snciYr0OAoMXY/0ClC7tm4C/nG5NJKmIItlaYlLbIVAWNfrYuy9dq1bE0SbX0PEg==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "dev": true, "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2702,12 +2857,14 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.8.tgz", - "integrity": "sha512-sPtYrduWINTQTW7FtOy99VCTWp4H23UX7vYcut7S4CIMEXU+54zKX9uCoGkLsWXteyaMXzVHgzWbLfQ1w4GZgw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.7.tgz", + "integrity": "sha512-h3MDAP5l34NQkkNulsTNyjdaR+OiB0Im67VU//sFupouP8Q6m9Spy7l66DcaAQxtmCqGdanPByLsnwFttxKISQ==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -2732,13 +2889,13 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.7.tgz", - "integrity": "sha512-n/TaiBGJxYFWvpJDfsxSj9lEEE44BFM1EPGz4KEiTipTgkoFVVcCmzAL3qA7fdQU96dpo4gGf5HBx/KnDvqiHw==", - "license": "MIT", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", + "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2748,14 +2905,13 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.7.tgz", - "integrity": "sha512-5MCTNcjCMxQ63Tdu9rxyN6cAWurqfrDZ76qvVPrGYdBxIj+EawuuxTu/+dgJlhK5eRz3v1gLwp6XwS8XaX2NiQ==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", "dependencies": { - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2765,12 +2921,13 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.8.tgz", - "integrity": "sha512-4OMNv7eHTmJ2YXs3tvxAfa/I43di+VcF+M4Wt66c88EAED1RoGaf1D64cL5FkRpNL+Vx9Hds84lksWvd/wMIdA==", - "license": "MIT", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", + "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -2780,12 +2937,11 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.7.tgz", - "integrity": "sha512-fwzkLrSu2fESR/cm4t6vqd7ebNIopz2QHGtjoU+dswQo/P6lwAG04Q98lliE3jkz/XqnbGFLnUcE0q0CVUf92w==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2795,12 +2951,13 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.8.tgz", - "integrity": "sha512-f5W0AhSbbI+yY6VakT04jmxdxz+WsID0neG7+kQZbCOjuyJNdL5Nn4WIBm4hRpKnUcO9lP0eipUhFN12JpoH8g==", - "license": "MIT", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", + "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { "node": ">=6.9.0" @@ -2810,12 +2967,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.7.tgz", - "integrity": "sha512-Std3kXwpXfRV0QtQy5JJcRpkqP8/wG4XL7hSKZmGlxPlDqmpXtEPRmhF7ztnlTCtUN3eXRUJp+sBEZjaIBVYaw==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2825,13 +2982,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.7.tgz", - "integrity": "sha512-CgselSGCGzjQvKzghCvDTxKHP3iooenLpJDO842ehn5D2G5fJB222ptnDwQho0WjEvg7zyoxb9P+wiYxiJX5yA==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2841,14 +2998,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.7.tgz", - "integrity": "sha512-L9Gcahi0kKFYXvweO6n0wc3ZG1ChpSFdgG+eV1WYZ3/dGbJK7vvk91FgGgak8YwRgrCuihF8tE/Xg07EkL5COg==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", "dependencies": { - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-simple-access": "^7.25.7" + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2858,15 +3014,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.7.tgz", - "integrity": "sha512-t9jZIvBmOXJsiuyOwhrIGs8dVcD6jDyg2icw1VL4A/g+FnWyJKwUfSSU2nwJuMV2Zqui856El9u+ElB+j9fV1g==", - "license": "MIT", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz", + "integrity": "sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==", + "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -2876,13 +3032,13 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.7.tgz", - "integrity": "sha512-p88Jg6QqsaPh+EB7I9GJrIqi1Zt4ZBHUQtjw3z1bzEXcLh6GfPqzZJ6G+G1HBGKUNukT58MnKG7EN7zXQBCODw==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2892,13 +3048,12 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.7.tgz", - "integrity": "sha512-BtAT9LzCISKG3Dsdw5uso4oV1+v2NlVXIIomKJgQybotJY3OwCwJmkongjHgwGKoZXd0qG5UZ12JUlDQ07W6Ow==", - "license": "MIT", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2908,12 +3063,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.7.tgz", - "integrity": "sha512-CfCS2jDsbcZaVYxRFo2qtavW8SpdzmBXC2LOI4oO0rP+JSRDxxF3inF4GcPsLgfb5FjkhXG5/yR/lxuRs2pySA==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2923,12 +3078,13 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.8.tgz", - "integrity": "sha512-Z7WJJWdQc8yCWgAmjI3hyC+5PXIubH9yRKzkl9ZEG647O9szl9zvmKLzpbItlijBnVhTUf1cpyWBsZ3+2wjWPQ==", - "license": "MIT", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", + "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -2938,12 +3094,13 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.8.tgz", - "integrity": "sha512-rm9a5iEFPS4iMIy+/A/PiS0QN0UyjPIeVvbU5EMZFKJZHt8vQnasbpo3T3EFcxzCeYO0BHfc4RqooCZc51J86Q==", - "license": "MIT", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", + "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { "node": ">=6.9.0" @@ -2967,14 +3124,16 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.8.tgz", - "integrity": "sha512-LkUu0O2hnUKHKE7/zYOIjByMa4VRaV2CD/cdGz0AxU9we+VA3kDDggKEzI0Oz1IroG+6gUP6UmWEHBMWZU316g==", - "license": "MIT", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", + "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-transform-parameters": "^7.25.7" + "@babel/compat-data": "^7.23.3", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -2984,13 +3143,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.7.tgz", - "integrity": "sha512-pWT6UXCEW3u1t2tcAGtE15ornCBvopHj9Bps9D2DsH15APgNVOTwwczGckX+WkAvBmuoYKRCFa4DK+jM8vh5AA==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-replace-supers": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -3000,12 +3159,13 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.8.tgz", - "integrity": "sha512-EbQYweoMAHOn7iJ9GgZo14ghhb9tTjgOc88xFgYngifx7Z9u580cENCV159M4xDh3q/irbhSjZVpuhpC2gKBbg==", - "license": "MIT", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", + "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -3015,13 +3175,14 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.8.tgz", - "integrity": "sha512-q05Bk7gXOxpTHoQ8RSzGSh/LHVB9JEIkKnk3myAWwZHnYiTGYtbdrYkIsS8Xyh4ltKf7GNUSgzs/6P2bJtBAQg==", - "license": "MIT", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", + "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -3031,12 +3192,11 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.7.tgz", - "integrity": "sha512-FYiTvku63me9+1Nz7TOx4YMtW3tWXzfANZtrzHhUZrz4d47EEtMQhzFoZWESfXuAMMT5mwzD4+y1N8ONAX6lMQ==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -3046,13 +3206,12 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz", - "integrity": "sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -3062,14 +3221,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.8.tgz", - "integrity": "sha512-8Uh966svuB4V8RHHg0QJOB32QK287NBksJOByoKmHMp1TAobNniNalIkI2i5IPj5+S9NYCG4VIjbEuiSN8r+ow==", - "license": "MIT", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", + "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { "node": ">=6.9.0" @@ -3079,12 +3238,12 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.7.tgz", - "integrity": "sha512-lQEeetGKfFi0wHbt8ClQrUSUMfEeI3MMm74Z73T9/kuz990yYVtfofjf3NuA42Jy3auFOpbjDyCSiIkTs1VIYw==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -3097,6 +3256,7 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.22.5.tgz", "integrity": "sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -3122,16 +3282,15 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.7.tgz", - "integrity": "sha512-vILAg5nwGlR9EXE8JIOX4NHXd49lrYbN8hnjffDtoULwpL9hUx/N55nqh2qd0q6FyNDfjl9V79ecKGvFbcSA0Q==", - "license": "MIT", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", + "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-module-imports": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-jsx": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.23.3", + "@babel/types": "^7.23.4" }, "engines": { "node": ">=6.9.0" @@ -3144,6 +3303,7 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "dev": true, "dependencies": { "@babel/plugin-transform-react-jsx": "^7.22.5" }, @@ -3186,6 +3346,7 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.23.3.tgz", "integrity": "sha512-qMFdSS+TUhB7Q/3HVPnEdYJDQIk57jkntAwSuz9xfSE4n+3I+vHYCli3HoHawN1Z3RfCz/y1zXA/JXjG6cVImQ==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5" @@ -3198,12 +3359,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.7.tgz", - "integrity": "sha512-mgDoQCRjrY3XK95UuV60tZlFCQGXEtMg8H+IsW72ldw1ih1jZhzYXbJvghmAEpg5UVhhnCeia1CkGttUvCkiMQ==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-plugin-utils": "^7.22.5", "regenerator-transform": "^0.15.2" }, "engines": { @@ -3214,12 +3375,12 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.7.tgz", - "integrity": "sha512-3OfyfRRqiGeOvIWSagcwUTVk2hXBsr/ww7bLn6TRTuXnexA+Udov2icFOxFX9abaj4l96ooYkcNN1qi2Zvqwng==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -3229,17 +3390,16 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.7.tgz", - "integrity": "sha512-Y9p487tyTzB0yDYQOtWnC+9HGOuogtP3/wNpun1xJXEEvI6vip59BSBTsHnekZLqxmPcgsrAKt46HAAb//xGhg==", - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "semver": "^6.3.1" + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.0.tgz", + "integrity": "sha512-zlPf1/XFn5+vWdve3AAhf+Sxl+MVa5VlwTwWgnLx23u4GlatSRQJ3Eoo9vllf0a9il3woQsT4SK+5Z7c06h8ag==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.0", + "@babel/helper-plugin-utils": "^7.14.5", + "babel-plugin-polyfill-corejs2": "^0.2.3", + "babel-plugin-polyfill-corejs3": "^0.3.0", + "babel-plugin-polyfill-regenerator": "^0.2.3", + "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" @@ -3257,12 +3417,11 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.7.tgz", - "integrity": "sha512-uBbxNwimHi5Bv3hUccmOFlUy3ATO6WagTApenHz9KzoIdn0XeACdB12ZJ4cjhuB2WSi80Ez2FWzJnarccriJeA==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -3272,13 +3431,12 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.7.tgz", - "integrity": "sha512-Mm6aeymI0PBh44xNIv/qvo8nmbkpZze1KvR8MkEqbIREDxoiWTi18Zr2jryfRMwDfVZF9foKh060fWgni44luw==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -3288,12 +3446,11 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.7.tgz", - "integrity": "sha512-ZFAeNkpGuLnAQ/NCsXJ6xik7Id+tHuS+NT+ue/2+rn/31zcdnupCdmunOizEaP0JsUmTFSTOPoQY7PkK2pttXw==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -3303,12 +3460,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.7.tgz", - "integrity": "sha512-SI274k0nUsFFmyQupiO7+wKATAmMFf8iFgq2O+vVFXZ0SV9lNfT1NGzBEhjquFmD8I9sqHLguH+gZVN3vww2AA==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -3318,12 +3475,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.7.tgz", - "integrity": "sha512-OmWmQtTHnO8RSUbL0NTdtpbZHeNTnm68Gj5pA4Y2blFNh+V4iZR68V1qL9cI37J21ZN7AaCnkfdHtLExQPf2uA==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -3333,16 +3490,14 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.7.tgz", - "integrity": "sha512-VKlgy2vBzj8AmEzunocMun2fF06bsSWV+FvVXohtL6FGve/+L217qhHxRTVGHEDO/YR8IANcjzgJsd04J8ge5Q==", - "license": "MIT", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz", + "integrity": "sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", - "@babel/plugin-syntax-typescript": "^7.25.7" + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.23.6", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-typescript": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -3352,12 +3507,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.7.tgz", - "integrity": "sha512-BN87D7KpbdiABA+t3HbVqHzKWUDN3dymLaTnPFAMyc8lV+KN3+YzNhVRNdinaCPA4AUqx7ubXbQ9shRjYBl3SQ==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -3367,13 +3522,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.7.tgz", - "integrity": "sha512-IWfR89zcEPQGB/iB408uGtSPlQd3Jpq11Im86vUgcmSTcoWAiQMCTOa2K2yNNqFJEBVICKhayctee65Ka8OB0w==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -3383,13 +3538,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.7.tgz", - "integrity": "sha512-8JKfg/hiuA3qXnlLx8qtv5HWRbgyFx2hMMtpDDuU2rTckpKkGu4ycK5yYHwuEa16/quXfoxHBIApEsNyMWnt0g==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -3399,13 +3553,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.7.tgz", - "integrity": "sha512-YRW8o9vzImwmh4Q3Rffd09bH5/hvY0pxg+1H1i0f7APoUeg12G7+HhLj9ZFNIrYkgBXhIijPJ+IXypN0hLTIbw==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -3415,78 +3569,90 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.8.tgz", - "integrity": "sha512-58T2yulDHMN8YMUxiLq5YmWUnlDCyY1FsHM+v12VMx+1/FlrUj5tY50iDCpofFQEM8fMYOaY9YRvym2jcjn1Dg==", - "license": "MIT", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.9.tgz", + "integrity": "sha512-3kBGTNBBk9DQiPoXYS0g0BYlwTQYUTifqgKTjxUwEUkduRT2QOa0FPGBJ+NROQhGyYO5BuTJwGvBnqKDykac6A==", + "dev": true, "dependencies": { - "@babel/compat-data": "^7.25.8", - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-validator-option": "^7.25.7", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.7", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.7", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.7", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.7", + "@babel/compat-data": "^7.23.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.25.7", - "@babel/plugin-syntax-import-attributes": "^7.25.7", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.23.3", + "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.25.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.8", - "@babel/plugin-transform-async-to-generator": "^7.25.7", - "@babel/plugin-transform-block-scoped-functions": "^7.25.7", - "@babel/plugin-transform-block-scoping": "^7.25.7", - "@babel/plugin-transform-class-properties": "^7.25.7", - "@babel/plugin-transform-class-static-block": "^7.25.8", - "@babel/plugin-transform-classes": "^7.25.7", - "@babel/plugin-transform-computed-properties": "^7.25.7", - "@babel/plugin-transform-destructuring": "^7.25.7", - "@babel/plugin-transform-dotall-regex": "^7.25.7", - "@babel/plugin-transform-duplicate-keys": "^7.25.7", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.7", - "@babel/plugin-transform-dynamic-import": "^7.25.8", - "@babel/plugin-transform-exponentiation-operator": "^7.25.7", - "@babel/plugin-transform-export-namespace-from": "^7.25.8", - "@babel/plugin-transform-for-of": "^7.25.7", - "@babel/plugin-transform-function-name": "^7.25.7", - "@babel/plugin-transform-json-strings": "^7.25.8", - "@babel/plugin-transform-literals": "^7.25.7", - "@babel/plugin-transform-logical-assignment-operators": "^7.25.8", - "@babel/plugin-transform-member-expression-literals": "^7.25.7", - "@babel/plugin-transform-modules-amd": "^7.25.7", - "@babel/plugin-transform-modules-commonjs": "^7.25.7", - "@babel/plugin-transform-modules-systemjs": "^7.25.7", - "@babel/plugin-transform-modules-umd": "^7.25.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.7", - "@babel/plugin-transform-new-target": "^7.25.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.8", - "@babel/plugin-transform-numeric-separator": "^7.25.8", - "@babel/plugin-transform-object-rest-spread": "^7.25.8", - "@babel/plugin-transform-object-super": "^7.25.7", - "@babel/plugin-transform-optional-catch-binding": "^7.25.8", - "@babel/plugin-transform-optional-chaining": "^7.25.8", - "@babel/plugin-transform-parameters": "^7.25.7", - "@babel/plugin-transform-private-methods": "^7.25.7", - "@babel/plugin-transform-private-property-in-object": "^7.25.8", - "@babel/plugin-transform-property-literals": "^7.25.7", - "@babel/plugin-transform-regenerator": "^7.25.7", - "@babel/plugin-transform-reserved-words": "^7.25.7", - "@babel/plugin-transform-shorthand-properties": "^7.25.7", - "@babel/plugin-transform-spread": "^7.25.7", - "@babel/plugin-transform-sticky-regex": "^7.25.7", - "@babel/plugin-transform-template-literals": "^7.25.7", - "@babel/plugin-transform-typeof-symbol": "^7.25.7", - "@babel/plugin-transform-unicode-escapes": "^7.25.7", - "@babel/plugin-transform-unicode-property-regex": "^7.25.7", - "@babel/plugin-transform-unicode-regex": "^7.25.7", - "@babel/plugin-transform-unicode-sets-regex": "^7.25.7", + "@babel/plugin-transform-arrow-functions": "^7.23.3", + "@babel/plugin-transform-async-generator-functions": "^7.23.9", + "@babel/plugin-transform-async-to-generator": "^7.23.3", + "@babel/plugin-transform-block-scoped-functions": "^7.23.3", + "@babel/plugin-transform-block-scoping": "^7.23.4", + "@babel/plugin-transform-class-properties": "^7.23.3", + "@babel/plugin-transform-class-static-block": "^7.23.4", + "@babel/plugin-transform-classes": "^7.23.8", + "@babel/plugin-transform-computed-properties": "^7.23.3", + "@babel/plugin-transform-destructuring": "^7.23.3", + "@babel/plugin-transform-dotall-regex": "^7.23.3", + "@babel/plugin-transform-duplicate-keys": "^7.23.3", + "@babel/plugin-transform-dynamic-import": "^7.23.4", + "@babel/plugin-transform-exponentiation-operator": "^7.23.3", + "@babel/plugin-transform-export-namespace-from": "^7.23.4", + "@babel/plugin-transform-for-of": "^7.23.6", + "@babel/plugin-transform-function-name": "^7.23.3", + "@babel/plugin-transform-json-strings": "^7.23.4", + "@babel/plugin-transform-literals": "^7.23.3", + "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", + "@babel/plugin-transform-member-expression-literals": "^7.23.3", + "@babel/plugin-transform-modules-amd": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-modules-systemjs": "^7.23.9", + "@babel/plugin-transform-modules-umd": "^7.23.3", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.23.3", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", + "@babel/plugin-transform-numeric-separator": "^7.23.4", + "@babel/plugin-transform-object-rest-spread": "^7.23.4", + "@babel/plugin-transform-object-super": "^7.23.3", + "@babel/plugin-transform-optional-catch-binding": "^7.23.4", + "@babel/plugin-transform-optional-chaining": "^7.23.4", + "@babel/plugin-transform-parameters": "^7.23.3", + "@babel/plugin-transform-private-methods": "^7.23.3", + "@babel/plugin-transform-private-property-in-object": "^7.23.4", + "@babel/plugin-transform-property-literals": "^7.23.3", + "@babel/plugin-transform-regenerator": "^7.23.3", + "@babel/plugin-transform-reserved-words": "^7.23.3", + "@babel/plugin-transform-shorthand-properties": "^7.23.3", + "@babel/plugin-transform-spread": "^7.23.3", + "@babel/plugin-transform-sticky-regex": "^7.23.3", + "@babel/plugin-transform-template-literals": "^7.23.3", + "@babel/plugin-transform-typeof-symbol": "^7.23.3", + "@babel/plugin-transform-unicode-escapes": "^7.23.3", + "@babel/plugin-transform-unicode-property-regex": "^7.23.3", + "@babel/plugin-transform-unicode-regex": "^7.23.3", + "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.38.1", + "babel-plugin-polyfill-corejs2": "^0.4.8", + "babel-plugin-polyfill-corejs3": "^0.9.0", + "babel-plugin-polyfill-regenerator": "^0.5.5", + "core-js-compat": "^3.31.0", "semver": "^6.3.1" }, "engines": { @@ -3496,10 +3662,82 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs2/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz", + "integrity": "sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.5.0", + "core-js-compat": "^3.34.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", + "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.5.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -3524,6 +3762,7 @@ "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -3537,6 +3776,7 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.23.3.tgz", "integrity": "sha512-tbkHOS9axH6Ysf2OUEqoSZ6T3Fa2SrNH6WTWSPBboxKzdxNc9qOICeLXkNG0ZEwbQ1HY8liwOce4aN/Ceyuq6w==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-validator-option": "^7.22.15", @@ -3553,16 +3793,15 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.25.7.tgz", - "integrity": "sha512-rkkpaXJZOFN45Fb+Gki0c+KMIglk4+zZXOoMJuyEK8y8Kkc8Jd3BDmP7qPsz0zQMJj+UD7EprF+AqAXcILnexw==", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", + "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-validator-option": "^7.25.7", - "@babel/plugin-syntax-jsx": "^7.25.7", - "@babel/plugin-transform-modules-commonjs": "^7.25.7", - "@babel/plugin-transform-typescript": "^7.25.7" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-syntax-jsx": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-typescript": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -3633,6 +3872,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.25.7.tgz", "integrity": "sha512-gMmIEhg35sXk9Te5qbGp3W9YKrvLt3HV658/d3odWrHSqT0JeG5OzsJWFHRLiOohRyjRsJc/x03DhJm3i8VJxg==", + "dev": true, "license": "MIT", "dependencies": { "core-js-pure": "^3.30.2", @@ -3645,7 +3885,8 @@ "node_modules/@babel/runtime-corejs3/node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true }, "node_modules/@babel/runtime/node_modules/regenerator-runtime": { "version": "0.14.1", @@ -3715,7 +3956,8 @@ "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true }, "node_modules/@callstack/reassure-cli": { "version": "0.6.1", @@ -3882,6 +4124,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.1.tgz", "integrity": "sha512-lSquqZCHxDfuTg/Sk2hiS0mcSFCEBuj49JfzPHJogDBT0mGCyY5A1AQzBWngitrp7i1/HAZpIgzF/VjhOEIJIg==", + "dev": true, "funding": [ { "type": "github", @@ -3903,6 +4146,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.1.tgz", "integrity": "sha512-UBqaiu7kU0lfvaP982/o3khfXccVlHPWp0/vwwiIgDF0GmqqqxoiXC/6FCjlS9u92f7CoEz6nXKQnrn1kIAkOw==", + "dev": true, "funding": [ { "type": "github", @@ -3921,6 +4165,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-3.0.1.tgz", "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==", + "dev": true, "funding": [ { "type": "github", @@ -3943,6 +4188,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-4.0.0.tgz", "integrity": "sha512-189nelqtPd8++phaHNwYovKZI0FOzH1vQEE3QhHHkNIGrg5fSs9CbYP3RvfEH5geztnIA9Jwq91wyOIwAW5JIQ==", + "dev": true, "funding": [ { "type": "github", @@ -3975,6 +4221,7 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, "engines": { "node": ">=10.0.0" } @@ -3983,6 +4230,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", + "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -4285,6 +4533,7 @@ "version": "0.40.1", "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.40.1.tgz", "integrity": "sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==", + "dev": true, "dependencies": { "comment-parser": "1.4.0", "esquery": "^1.5.0", @@ -4650,6 +4899,7 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -4664,6 +4914,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -4675,6 +4926,7 @@ "version": "4.8.0", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", + "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -4683,6 +4935,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz", "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==", + "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -4702,6 +4955,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -4716,12 +4970,14 @@ "node_modules/@eslint/eslintrc/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/@eslint/eslintrc/node_modules/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, "engines": { "node": ">= 4" } @@ -4730,6 +4986,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -4741,6 +4998,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, "engines": { "node": ">=8" }, @@ -4758,6 +5016,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, "engines": { "node": ">=14" } @@ -4846,6 +5105,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", + "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.0", "debug": "^4.1.1", @@ -4858,7 +5118,8 @@ "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", @@ -4978,6 +5239,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", + "dev": true, "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -4992,6 +5254,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -5004,6 +5267,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -5015,6 +5279,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -5029,6 +5294,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -5040,6 +5306,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, "engines": { "node": ">=6" } @@ -5048,6 +5315,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "engines": { "node": ">=8" } @@ -5056,6 +5324,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, "engines": { "node": ">=8" } @@ -5064,6 +5333,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, "engines": { "node": ">=8" } @@ -5072,6 +5342,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz", "integrity": "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==", + "dev": true, "dependencies": { "@jest/types": "^29.6.1", "@types/node": "*", @@ -5088,6 +5359,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz", "integrity": "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==", + "dev": true, "dependencies": { "@jest/console": "^29.6.2", "@jest/reporters": "^29.6.2", @@ -5159,6 +5431,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz", "integrity": "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==", + "dev": true, "dependencies": { "expect": "^29.6.2", "jest-snapshot": "^29.6.2" @@ -5171,6 +5444,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz", "integrity": "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==", + "dev": true, "dependencies": { "jest-get-type": "^29.4.3" }, @@ -5217,6 +5491,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz", "integrity": "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==", + "dev": true, "dependencies": { "@jest/environment": "^29.6.2", "@jest/expect": "^29.6.2", @@ -5231,6 +5506,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz", "integrity": "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==", + "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.6.2", @@ -5273,6 +5549,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5303,6 +5580,7 @@ "version": "29.6.0", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", + "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", @@ -5316,6 +5594,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz", "integrity": "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==", + "dev": true, "dependencies": { "@jest/console": "^29.6.2", "@jest/types": "^29.6.1", @@ -5330,6 +5609,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz", "integrity": "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==", + "dev": true, "dependencies": { "@jest/test-result": "^29.6.2", "graceful-fs": "^4.2.9", @@ -5344,6 +5624,7 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -5368,12 +5649,14 @@ "node_modules/@jest/transform/node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true }, "node_modules/@jest/transform/node_modules/write-file-atomic": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" @@ -5466,6 +5749,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "dev": true, "dependencies": { "debug": "^4.1.1" } @@ -5473,12 +5757,14 @@ "node_modules/@kwsites/promise-deferred": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", + "dev": true }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", + "dev": true }, "node_modules/@lerna/child-process": { "version": "7.1.4", @@ -5833,6 +6119,7 @@ "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, "license": "MIT", "dependencies": { "eslint-scope": "5.1.1" @@ -5842,6 +6129,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", @@ -5855,6 +6143,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.2.tgz", "integrity": "sha512-wrIBsjA5pl13f0RN4Zx4FNWmU71lv03meGKnqRUoCyan17s4V3WL92f3w3AIuWbNnpcrQyFBU5qMavJoB8d27w==", + "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.2", "run-parallel": "^1.1.9" @@ -5867,6 +6156,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.2.tgz", "integrity": "sha512-z8+wGWV2dgUhLqrtRYa03yDx4HWMvXKi1z8g3m2JyxAx8F7xk74asqPk5LAETjqDSGLFML/6CDl0+yFunSYicw==", + "dev": true, "engines": { "node": ">= 8" } @@ -5875,6 +6165,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.3.tgz", "integrity": "sha512-l6t8xEhfK9Sa4YO5mIRdau7XSOADfmh3jCr0evNHdY+HNkW6xuQhgMH7D73VV6WpZOagrW0UludvMTiifiwTfA==", + "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.2", "fastq": "^1.6.0" @@ -6287,6 +6578,7 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "dev": true, "dependencies": { "@octokit/types": "^6.0.3" } @@ -6295,6 +6587,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "dev": true, "dependencies": { "@octokit/auth-token": "^2.4.4", "@octokit/graphql": "^4.5.8", @@ -6309,6 +6602,7 @@ "version": "6.0.12", "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "dev": true, "dependencies": { "@octokit/types": "^6.0.3", "is-plain-object": "^5.0.0", @@ -6319,6 +6613,7 @@ "version": "5.6.3", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "dev": true, "dependencies": { "@octokit/endpoint": "^6.0.1", "@octokit/request-error": "^2.1.0", @@ -6331,12 +6626,14 @@ "node_modules/@octokit/core/node_modules/before-after-hook": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true }, "node_modules/@octokit/core/node_modules/universal-user-agent": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "dev": true }, "node_modules/@octokit/endpoint": { "version": "5.5.3", @@ -6380,6 +6677,7 @@ "version": "4.8.0", "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "dev": true, "dependencies": { "@octokit/request": "^5.6.0", "@octokit/types": "^6.0.3", @@ -6390,6 +6688,7 @@ "version": "6.0.12", "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "dev": true, "dependencies": { "@octokit/types": "^6.0.3", "is-plain-object": "^5.0.0", @@ -6400,6 +6699,7 @@ "version": "5.6.3", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "dev": true, "dependencies": { "@octokit/endpoint": "^6.0.1", "@octokit/request-error": "^2.1.0", @@ -6412,12 +6712,14 @@ "node_modules/@octokit/graphql/node_modules/universal-user-agent": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "dev": true }, "node_modules/@octokit/openapi-types": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", - "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==" + "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==", + "dev": true }, "node_modules/@octokit/plugin-enterprise-rest": { "version": "6.0.1", @@ -6429,6 +6731,7 @@ "version": "2.21.3", "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", + "dev": true, "dependencies": { "@octokit/types": "^6.40.0" }, @@ -6439,12 +6742,14 @@ "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { "version": "12.11.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", + "dev": true }, "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { "version": "6.41.0", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "dev": true, "dependencies": { "@octokit/openapi-types": "^12.11.0" } @@ -6462,6 +6767,7 @@ "version": "5.16.2", "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", + "dev": true, "dependencies": { "@octokit/types": "^6.39.0", "deprecation": "^2.3.1" @@ -6473,12 +6779,14 @@ "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { "version": "12.11.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", + "dev": true }, "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { "version": "6.41.0", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "dev": true, "dependencies": { "@octokit/openapi-types": "^12.11.0" } @@ -6502,6 +6810,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "dev": true, "dependencies": { "@octokit/types": "^6.0.3", "deprecation": "^2.0.0", @@ -6588,6 +6897,7 @@ "version": "6.34.0", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", + "dev": true, "dependencies": { "@octokit/openapi-types": "^11.2.0" } @@ -6596,12 +6906,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-2.0.0.tgz", "integrity": "sha512-35cfQ4YWlnZnmZKmIxlGPUPLtbkF8lr/A/1Sk1eC0ddLMwQN06dOuLc+dI3YLQS+T+MoNt3DIQ0NynwgKPilig==", + "dev": true, "license": "MIT" }, "node_modules/@octokit/webhooks-types": { "version": "5.8.0", "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-5.8.0.tgz", "integrity": "sha512-8adktjIb76A7viIdayQSFuBEwOzwhDC+9yxZpKNHjfzrlostHCw0/N7JWpWMObfElwvJMk2fY2l1noENCk9wmw==", + "dev": true, "license": "MIT" }, "node_modules/@parcel/watcher": { @@ -6636,6 +6948,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", + "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "fast-glob": "^3.3.0", @@ -6655,6 +6968,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -6668,6 +6982,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, "engines": { "node": ">=12" }, @@ -6679,6 +6994,7 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -6694,6 +7010,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -6705,6 +7022,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -6716,6 +7034,7 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "dev": true, "dependencies": { "default-browser": "^4.0.0", "define-lazy-prop": "^3.0.0", @@ -6733,6 +7052,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -6741,6 +7061,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -6752,6 +7073,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } @@ -6760,6 +7082,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -6789,6 +7112,7 @@ "version": "0.5.11", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.11.tgz", "integrity": "sha512-7j/6vdTym0+qZ6u4XbSAxrWBGYSdCfTzySkj7WAFgDLmSyWlOrWvpyzxlFh5jtw9dn0oL/jtW+06XfFiisN3JQ==", + "dev": true, "dependencies": { "ansi-html-community": "^0.0.8", "common-path-prefix": "^3.0.0", @@ -6838,6 +7162,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6853,6 +7178,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -6868,6 +7194,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -6882,6 +7209,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -6896,6 +7224,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "engines": { "node": ">=8" } @@ -6904,6 +7233,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -6921,6 +7251,7 @@ "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, "engines": { "node": ">= 8" } @@ -6928,7 +7259,8 @@ "node_modules/@polka/url": { "version": "1.0.0-next.23", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", - "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==" + "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==", + "dev": true }, "node_modules/@preact/signals": { "version": "1.3.0", @@ -6960,6 +7292,7 @@ "version": "1.4.6", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.4.6.tgz", "integrity": "sha512-x4BEjr2SjOPowNeiguzjozQbsc6h437ovD/wu+JpaenxVLm3jkgzHY2xOslMTp50HoTvQreMjiexiGQw1sqZlQ==", + "dev": true, "dependencies": { "debug": "4.3.4", "extract-zip": "2.0.1", @@ -6988,6 +7321,7 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -7000,12 +7334,14 @@ "node_modules/@puppeteer/browsers/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/@puppeteer/browsers/node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -7025,6 +7361,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -7033,6 +7370,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -7043,6 +7381,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -7056,6 +7395,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", + "dev": true, "dependencies": { "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", @@ -7066,6 +7406,7 @@ "version": "3.1.7", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", @@ -7076,6 +7417,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -7092,6 +7434,7 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, "engines": { "node": ">=10" } @@ -7100,6 +7443,7 @@ "version": "17.7.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -7117,6 +7461,7 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, "engines": { "node": ">=12" } @@ -8404,9 +8749,9 @@ } }, "node_modules/@react-native-community/cli-doctor/node_modules/yaml": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", - "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -10216,6 +10561,7 @@ "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.19.7.tgz", "integrity": "sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw==", + "dev": true, "dependencies": { "@sentry/hub": "6.19.7", "@sentry/minimal": "6.19.7", @@ -10230,12 +10576,14 @@ "node_modules/@sentry/core/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, "node_modules/@sentry/hub": { "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz", "integrity": "sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA==", + "dev": true, "dependencies": { "@sentry/types": "6.19.7", "@sentry/utils": "6.19.7", @@ -10248,12 +10596,14 @@ "node_modules/@sentry/hub/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, "node_modules/@sentry/minimal": { "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.7.tgz", "integrity": "sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ==", + "dev": true, "dependencies": { "@sentry/hub": "6.19.7", "@sentry/types": "6.19.7", @@ -10266,12 +10616,14 @@ "node_modules/@sentry/minimal/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, "node_modules/@sentry/node": { "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.19.7.tgz", "integrity": "sha512-gtmRC4dAXKODMpHXKfrkfvyBL3cI8y64vEi3fDD046uqYcrWdgoQsffuBbxMAizc6Ez1ia+f0Flue6p15Qaltg==", + "dev": true, "dependencies": { "@sentry/core": "6.19.7", "@sentry/hub": "6.19.7", @@ -10290,6 +10642,7 @@ "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -10297,12 +10650,14 @@ "node_modules/@sentry/node/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, "node_modules/@sentry/types": { "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz", "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==", + "dev": true, "engines": { "node": ">=6" } @@ -10311,6 +10666,7 @@ "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz", "integrity": "sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==", + "dev": true, "dependencies": { "@sentry/types": "6.19.7", "tslib": "^1.9.3" @@ -10322,7 +10678,8 @@ "node_modules/@sentry/utils/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, "node_modules/@sideway/address": { "version": "4.1.5", @@ -10401,6 +10758,7 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, "engines": { "node": ">=10" }, @@ -13173,6 +13531,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-3.0.1.tgz", "integrity": "sha512-j3mH8HSw2Rob/KJFWZ627w3CQ8gQqVHtzCdPeEffUg5vOgpz4rgrR+Xw2kU0OQCDcdW8Y1nKfdXKKjM5Rn8X0g==", + "dev": true, "dependencies": { "@csstools/css-parser-algorithms": "^3.0.0", "@csstools/css-tokenizer": "^3.0.0", @@ -13193,12 +13552,14 @@ "node_modules/@stylistic/stylelint-plugin/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, "engines": { "node": ">=14" }, @@ -13214,6 +13575,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, "engines": { "node": ">=14" }, @@ -13229,6 +13591,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, "engines": { "node": ">=14" }, @@ -13244,6 +13607,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, "engines": { "node": ">=14" }, @@ -13259,6 +13623,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, "engines": { "node": ">=14" }, @@ -13274,6 +13639,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, "engines": { "node": ">=14" }, @@ -13289,6 +13655,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.0.0.tgz", "integrity": "sha512-UKrY3860AQICgH7g+6h2zkoxeVEPLYwX/uAjmqo4PIq2FIHppwhIqZstIyTz0ZtlwreKR41O3W3BzsBBiJV2Aw==", + "dev": true, "engines": { "node": ">=14" }, @@ -13304,6 +13671,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, "engines": { "node": ">=12" }, @@ -13319,6 +13687,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.0.0.tgz", "integrity": "sha512-KLcjiZychInVrhs86OvcYPLTFu9L5XV2vj0XAaE1HwE3J3jLmIzRY8ttdeAg/iFyp8nhavJpafpDZTt+1LIpkQ==", + "dev": true, "dependencies": { "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", @@ -13344,6 +13713,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.0.0.tgz", "integrity": "sha512-aJKtc+Pie/rFYsVH/unSkDaZGvEeylNv/s2cP+ta9/rYWxRVvoV/S4Qw65Kmrtah4CBK5PM6ISH9qUH7IJQCng==", + "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.0.0", @@ -13362,12 +13732,14 @@ "node_modules/@svgr/core/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/@svgr/core/node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, "engines": { "node": ">=10" }, @@ -13379,6 +13751,7 @@ "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -13404,6 +13777,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -13415,6 +13789,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "engines": { "node": ">=8" } @@ -13423,6 +13798,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, "dependencies": { "@babel/types": "^7.21.3", "entities": "^4.4.0" @@ -13439,6 +13815,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, "engines": { "node": ">=0.12" }, @@ -13450,6 +13827,7 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.0.1.tgz", "integrity": "sha512-bfCFb+4ZsM3UuKP2t7KmDwn6YV8qVn9HIQJmau6xeQb/iV65Rpi7NBNBWA2hcCd4GKoCqG8hpaaDk5FDR0eH+g==", + "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.0.0", @@ -13471,6 +13849,7 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.0.1.tgz", "integrity": "sha512-29OJ1QmJgnohQHDAgAuY2h21xWD6TZiXji+hnx+W635RiXTAlHTbjrZDktfqzkN0bOeQEtNe+xgq73/XeWFfSg==", + "dev": true, "dependencies": { "cosmiconfig": "^8.1.3", "deepmerge": "^4.3.1", @@ -13490,12 +13869,14 @@ "node_modules/@svgr/plugin-svgo/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/@svgr/plugin-svgo/node_modules/cosmiconfig": { "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -13521,6 +13902,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -13532,6 +13914,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "engines": { "node": ">=8" } @@ -13540,6 +13923,7 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.0.1.tgz", "integrity": "sha512-zSoeKcbCmfMXjA11uDuCJb+1LWNb3vy6Qw/VHj0Nfcl3UuqwuoZWknHsBIhCWvi4wU9vPui3aq054qjVyZqY4A==", + "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@babel/plugin-transform-react-constant-elements": "^7.21.3", @@ -13772,6 +14156,7 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, "dependencies": { "defer-to-connect": "^2.0.0" }, @@ -14023,12 +14408,14 @@ "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "dev": true }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, "engines": { "node": ">=10.13.0" } @@ -14117,6 +14504,7 @@ "version": "7.20.0", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", + "dev": true, "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -14129,6 +14517,7 @@ "version": "7.6.4", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, "dependencies": { "@babel/types": "^7.0.0" } @@ -14137,6 +14526,7 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -14146,6 +14536,7 @@ "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dev": true, "dependencies": { "@babel/types": "^7.20.7" } @@ -14169,6 +14560,7 @@ "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dev": true, "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -14178,6 +14570,7 @@ "version": "3.5.11", "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.11.tgz", "integrity": "sha512-isGhjmBtLIxdHBDl2xGwUzEM8AOyOvWsADWq7rqirdi/ZQoHnLWErHvsThcEzTX8juDRiZtzp2Qkv5bgNh6mAg==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -14186,6 +14579,7 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "^3.1.4", @@ -14197,6 +14591,7 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -14205,6 +14600,7 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.1.tgz", "integrity": "sha512-iaQslNbARe8fctL5Lk+DsmgWOM83lM+7FzP0eQUJs1jd3kBE8NWqBTIT2S8SqQOJjxvt2eyIjpOuYeRXq2AdMw==", + "dev": true, "dependencies": { "@types/express-serve-static-core": "*", "@types/node": "*" @@ -14262,17 +14658,20 @@ "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true }, "node_modules/@types/events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", + "dev": true }, "node_modules/@types/express": { "version": "4.17.17", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "dev": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -14284,6 +14683,7 @@ "version": "4.17.35", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "dev": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -14313,6 +14713,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, "dependencies": { "@types/events": "*", "@types/minimatch": "*", @@ -14323,6 +14724,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.3.tgz", "integrity": "sha512-AiHRaEB50LQg0pZmm659vNBb9f4SJ0qrAnteuzhSeAUcJKxoYgEnprg/83kppCnc2zvtCKbdZry1a5pVY3lOTQ==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -14346,17 +14748,20 @@ "node_modules/@types/http-cache-semantics": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.2.tgz", - "integrity": "sha512-FD+nQWA2zJjh4L9+pFXqWOi0Hs1ryBCfI+985NjluQ1p8EYtoLvjLOKidXBtZ4/IcxDX4o8/E8qDS3540tNliw==" + "integrity": "sha512-FD+nQWA2zJjh4L9+pFXqWOi0Hs1ryBCfI+985NjluQ1p8EYtoLvjLOKidXBtZ4/IcxDX4o8/E8qDS3540tNliw==", + "dev": true }, "node_modules/@types/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==", + "dev": true }, "node_modules/@types/http-proxy": { "version": "1.17.12", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.12.tgz", "integrity": "sha512-kQtujO08dVtQ2wXAuSFfk9ASy3sug4+ogFR8Kd8UgP8PEuc1/G/8yjYRmp//PcDNJEUKOza/MrQu15bouEUCiw==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -14396,6 +14801,7 @@ "version": "20.0.1", "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "dev": true, "dependencies": { "@types/node": "*", "@types/tough-cookie": "*", @@ -14414,17 +14820,20 @@ "node_modules/@types/json-schema": { "version": "7.0.12", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==" + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true }, "node_modules/@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -14468,7 +14877,8 @@ "node_modules/@types/mime": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", - "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==" + "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==", + "dev": true }, "node_modules/@types/mime-types": { "version": "2.1.4", @@ -14479,12 +14889,14 @@ "node_modules/@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true }, "node_modules/@types/minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=" + "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=", + "dev": true }, "node_modules/@types/mousetrap": { "version": "1.6.8", @@ -14507,9 +14919,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.56", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.56.tgz", - "integrity": "sha512-4EMJlWwwGnVPflJAtM14p9eVSa6BOv5b92mCsh5zcM1UagNtEtrbbtaE6WE1tw2TabavatnwqXjlIpcAEuJJNg==", + "version": "18.19.54", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.54.tgz", + "integrity": "sha512-+BRgt0G5gYjTvdLac9sIeE0iZcJxi4Jc4PV5EUzqi+88jmQLr+fRZdv2tCTV7IHKSGxM6SaLoOXQWWUiLUItMw==", "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -14528,7 +14940,8 @@ "node_modules/@types/normalize-package-data": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz", - "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==" + "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==", + "dev": true }, "node_modules/@types/npm-package-arg": { "version": "6.1.1", @@ -14578,12 +14991,14 @@ "node_modules/@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true }, "node_modules/@types/range-parser": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true }, "node_modules/@types/react": { "version": "18.3.1", @@ -14647,6 +15062,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -14654,7 +15070,8 @@ "node_modules/@types/retry": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", - "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==" + "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", + "dev": true }, "node_modules/@types/scheduler": { "version": "0.16.2", @@ -14671,6 +15088,7 @@ "version": "0.17.1", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dev": true, "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -14679,7 +15097,8 @@ "node_modules/@types/send/node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true }, "node_modules/@types/serve-favicon": { "version": "2.5.5", @@ -14694,6 +15113,7 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "dev": true, "dependencies": { "@types/express": "*" } @@ -14702,6 +15122,7 @@ "version": "1.15.2", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "dev": true, "dependencies": { "@types/http-errors": "*", "@types/mime": "*", @@ -14726,6 +15147,7 @@ "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -14733,7 +15155,8 @@ "node_modules/@types/source-list-map": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==" + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", + "dev": true }, "node_modules/@types/sprintf-js": { "version": "1.1.2", @@ -14755,7 +15178,8 @@ "node_modules/@types/tapable": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.5.tgz", - "integrity": "sha512-/gG2M/Imw7cQFp8PGvz/SwocNrmKFjFsm5Pb8HdbHkZ1K8pmuPzOX4VeVoiEecFCVf4CsN1r3/BRvx+6sNqwtQ==" + "integrity": "sha512-/gG2M/Imw7cQFp8PGvz/SwocNrmKFjFsm5Pb8HdbHkZ1K8pmuPzOX4VeVoiEecFCVf4CsN1r3/BRvx+6sNqwtQ==", + "dev": true }, "node_modules/@types/teen_process": { "version": "2.0.0", @@ -14778,7 +15202,8 @@ "node_modules/@types/tough-cookie": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==" + "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", + "dev": true }, "node_modules/@types/triple-beam": { "version": "1.3.3", @@ -14790,6 +15215,7 @@ "version": "3.9.2", "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.9.2.tgz", "integrity": "sha512-d6dIfpPbF+8B7WiCi2ELY7m0w1joD8cRW4ms88Emdb2w062NeEpbNCeWwVCgzLRpVG+5e74VFSg4rgJ2xXjEiQ==", + "dev": true, "dependencies": { "source-map": "^0.6.1" } @@ -14797,7 +15223,8 @@ "node_modules/@types/unist": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==" + "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", + "dev": true }, "node_modules/@types/uuid": { "version": "8.3.1", @@ -14809,6 +15236,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz", "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==", + "dev": true, "dependencies": { "@types/node": "*", "@types/unist": "*", @@ -14819,6 +15247,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-1.0.1.tgz", "integrity": "sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA==", + "dev": true, "dependencies": { "@types/node": "*", "@types/unist": "*" @@ -14828,6 +15257,7 @@ "version": "4.41.33", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.33.tgz", "integrity": "sha512-PPajH64Ft2vWevkerISMtnZ8rTs4YmRbs+23c402J0INmxDKCrhZNvwZYtzx96gY2wAtXdrK1BS2fiC8MlLr3g==", + "dev": true, "dependencies": { "@types/node": "*", "@types/tapable": "^1", @@ -14841,6 +15271,7 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.7.tgz", "integrity": "sha512-XyaHrJILjK1VHVC4aVlKsdNN5KBTwufMb43cQs+flGxtPAf/1Qwl8+Q0tp5BwEGaI8D6XT1L+9bSWXckgkjTLw==", + "dev": true, "dependencies": { "@types/node": "*", "@types/source-list-map": "*", @@ -14863,6 +15294,7 @@ "version": "8.5.5", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -14885,6 +15317,7 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "dev": true, "optional": true, "dependencies": { "@types/node": "*" @@ -14894,6 +15327,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.1.tgz", "integrity": "sha512-3F5PtBzUW0dYlq77Lcqo13fv+58KDwUib3BddilE8ajPJT+faGgxmI9Sw+I8ZS22BYwoir9ZhNXcLi+S+I2bkw==", + "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", "@typescript-eslint/scope-manager": "6.4.1", @@ -14927,12 +15361,14 @@ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", + "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1" @@ -14949,6 +15385,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", + "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -14961,6 +15398,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", + "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1", @@ -14987,6 +15425,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", + "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", @@ -15011,6 +15450,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", + "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" @@ -15027,6 +15467,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15038,6 +15479,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.4.1.tgz", "integrity": "sha512-610G6KHymg9V7EqOaNBMtD1GgpAmGROsmfHJPXNLCU9bfIuLrkdOygltK784F6Crboyd5tBFayPB7Sf0McrQwg==", + "dev": true, "dependencies": { "@typescript-eslint/scope-manager": "6.4.1", "@typescript-eslint/types": "6.4.1", @@ -15065,6 +15507,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", + "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1" @@ -15081,6 +15524,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", + "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -15093,6 +15537,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", + "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1", @@ -15119,6 +15564,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", + "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" @@ -15135,6 +15581,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15146,6 +15593,7 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0" @@ -15162,6 +15610,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.4.1.tgz", "integrity": "sha512-7ON8M8NXh73SGZ5XvIqWHjgX2f+vvaOarNliGhjrJnv1vdjG0LVIz+ToYfPirOoBi56jxAKLfsLm40+RvxVVXA==", + "dev": true, "dependencies": { "@typescript-eslint/typescript-estree": "6.4.1", "@typescript-eslint/utils": "6.4.1", @@ -15187,12 +15636,14 @@ "node_modules/@typescript-eslint/type-utils/node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", + "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1" @@ -15209,6 +15660,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", + "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -15221,6 +15673,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", + "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1", @@ -15247,6 +15700,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", + "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", @@ -15271,6 +15725,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", + "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" @@ -15287,6 +15742,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15298,6 +15754,7 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15310,6 +15767,7 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0", @@ -15336,6 +15794,7 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", @@ -15360,12 +15819,14 @@ "node_modules/@typescript-eslint/utils/node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true }, "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -15378,6 +15839,7 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" @@ -15394,6 +15856,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15808,9 +16271,9 @@ } }, "node_modules/@wdio/repl/node_modules/@types/node": { - "version": "20.16.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.12.tgz", - "integrity": "sha512-LfPFB0zOeCeCNQV3i+67rcoVvoN5n0NVuR2vLG0O5ySQMgchuZlC4lgz546ZOJyDtj5KIgOxy+lacOimfqZAIA==", + "version": "20.16.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "dev": true, "license": "MIT", "dependencies": { @@ -15837,9 +16300,9 @@ } }, "node_modules/@wdio/types/node_modules/@types/node": { - "version": "20.16.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.12.tgz", - "integrity": "sha512-LfPFB0zOeCeCNQV3i+67rcoVvoN5n0NVuR2vLG0O5ySQMgchuZlC4lgz546ZOJyDtj5KIgOxy+lacOimfqZAIA==", + "version": "20.16.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "dev": true, "license": "MIT", "dependencies": { @@ -16405,6 +16868,7 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -16414,12 +16878,14 @@ "node_modules/@webassemblyjs/helper-numbers/node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true }, "node_modules/@webassemblyjs/helper-numbers/node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.9.0", @@ -16547,6 +17013,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, "engines": { "node": ">=14.15.0" }, @@ -16559,6 +17026,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, "engines": { "node": ">=14.15.0" }, @@ -16571,6 +17039,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, "engines": { "node": ">=14.15.0" }, @@ -16672,10 +17141,6 @@ "resolved": "packages/create-block", "link": true }, - "node_modules/@wordpress/create-block-interactive-template": { - "resolved": "packages/create-block-interactive-template", - "link": true - }, "node_modules/@wordpress/create-block-tutorial-template": { "resolved": "packages/create-block-tutorial-template", "link": true @@ -16996,12 +17461,14 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true }, "node_modules/@yarnpkg/esbuild-plugin-pnp": { "version": "3.0.0-rc.15", @@ -17096,7 +17563,8 @@ "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true }, "node_modules/abbrev": { "version": "1.1.1", @@ -17143,6 +17611,7 @@ "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, "peerDependencies": { "acorn": "^8" } @@ -17151,6 +17620,7 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -17183,6 +17653,7 @@ "version": "0.5.9", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz", "integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==", + "dev": true, "engines": { "node": ">=6.0" } @@ -17191,6 +17662,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, "dependencies": { "debug": "4" }, @@ -17214,6 +17686,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", @@ -17227,6 +17700,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -17236,6 +17710,7 @@ "version": "8.7.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.7.1.tgz", "integrity": "sha512-gPpOObTO1QjbnN1sVMjJcp1TF9nggMfO4MBR5uQl6ZVTOaEPq5i4oq/6R9q2alMMPB3eg53wFv1RuJBLuxf3Hw==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -17251,6 +17726,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true, "peerDependencies": { "ajv": ">=5.0.0" } @@ -17259,6 +17735,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, "dependencies": { "ajv": "^8.0.0" }, @@ -17275,6 +17752,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -17282,7 +17760,8 @@ "node_modules/ajv/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, "node_modules/anser": { "version": "1.4.10", @@ -17293,6 +17772,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, "engines": { "node": ">=6" } @@ -17301,6 +17781,7 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, "dependencies": { "type-fest": "^0.21.3" }, @@ -17315,6 +17796,7 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, "engines": { "node": ">=10" }, @@ -17379,6 +17861,7 @@ "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, "engines": [ "node >= 0.8.0" ], @@ -18105,6 +18588,7 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true, "engines": { "node": ">=14" } @@ -18170,6 +18654,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "dev": true, "dependencies": { "@babel/runtime": "^7.10.2", "@babel/runtime-corejs3": "^7.10.2" @@ -18200,6 +18685,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -18208,6 +18694,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "is-array-buffer": "^3.0.1" @@ -18228,7 +18715,8 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true }, "node_modules/array-ify": { "version": "1.0.0", @@ -18240,6 +18728,7 @@ "version": "3.1.6", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -18257,12 +18746,14 @@ "node_modules/array-iterate": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.2.tgz", - "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==" + "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==", + "dev": true }, "node_modules/array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, "dependencies": { "array-uniq": "^1.0.1" }, @@ -18274,6 +18765,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -18291,6 +18783,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -18308,6 +18801,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -18325,6 +18819,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", + "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.2", @@ -18344,6 +18839,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -18414,7 +18910,8 @@ "node_modules/ast-types-flow": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", + "dev": true }, "node_modules/astral-regex": { "version": "1.0.0", @@ -18473,7 +18970,8 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true }, "node_modules/at-least-node": { "version": "1.0.0", @@ -18505,6 +19003,7 @@ "version": "10.4.14", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -18536,7 +19035,8 @@ "node_modules/autoprefixer/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/autosize": { "version": "4.0.2", @@ -18547,6 +19047,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -18558,6 +19059,7 @@ "version": "4.7.2", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==", + "dev": true, "engines": { "node": ">=4" } @@ -18576,12 +19078,14 @@ "node_modules/axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==" + "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", + "dev": true }, "node_modules/b4a": { "version": "1.6.4", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", - "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==" + "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==", + "dev": true }, "node_modules/babel-core": { "version": "7.0.0-bridge.0", @@ -18595,6 +19099,7 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, "dependencies": { "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", @@ -18816,6 +19321,7 @@ "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -18831,6 +19337,7 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -18856,51 +19363,47 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "license": "MIT", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.3.tgz", + "integrity": "sha512-NDZ0auNRzmAfE1oDDPW2JhzIMXUk+FFe2ICejmt5T4ocKgiQx3e0VCRx9NCAidcMtL2RUZaWtXnmjTCkx0tcbA==", "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", - "semver": "^6.3.1" + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.2.4", + "semver": "^6.1.1" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "@babel/core": "^7.0.0-0" } }, "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", - "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", - "license": "MIT", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.3.0.tgz", + "integrity": "sha512-JLwi9vloVdXLjzACL80j24bG6/T1gYxwowG44dg6HN/7aTPdyPbJJidf6ajoA3RPHHtW0j9KMrSOLpIZpAnPpg==", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2", - "core-js-compat": "^3.38.0" + "@babel/helper-define-polyfill-provider": "^0.2.4", + "core-js-compat": "^3.18.0" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "@babel/core": "^7.0.0-0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", - "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", - "license": "MIT", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.3.tgz", + "integrity": "sha512-JVE78oRZPKFIeUqFGrSORNzQnrDwZR16oiWeGM8ZyjBn2XAT5OjP+wXx5ESuo33nUsFUEJYjtklnsKbxW5L+7g==", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2" + "@babel/helper-define-polyfill-provider": "^0.2.4" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "@babel/core": "^7.0.0-0" } }, "node_modules/babel-plugin-react-native-classname-to-style": { @@ -18942,6 +19445,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", @@ -19002,6 +19506,7 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" @@ -19017,6 +19522,7 @@ "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz", "integrity": "sha512-zeCYxDePWYAT/DfmQWIHsMSFW2vv45UIwIAMjGvQVsTd47RwsiRH0uK1yzyWZ7LDBKdhnGDPM6NYEO5CZyhPrg==", + "dev": true, "dependencies": { "core-js": "^2.4.0", "regenerator-runtime": "^0.10.0" @@ -19027,17 +19533,20 @@ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "dev": true, "hasInstallScript": true }, "node_modules/babel-runtime/node_modules/regenerator-runtime": { "version": "0.10.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==" + "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==", + "dev": true }, "node_modules/bail": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", - "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==" + "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", + "dev": true }, "node_modules/balanced-match": { "version": "1.0.2", @@ -19048,12 +19557,14 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.2.1.tgz", "integrity": "sha512-9GYPpsPFvrWBkelIhOhTWtkeZxVxZOdb3VnFTCzlOo3OjvmTvzLoZFUT8kNFACx0vJej6QPney1Cf9BvzCNE/A==", + "dev": true, "optional": true }, "node_modules/bare-fs": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.2.2.tgz", "integrity": "sha512-X9IqgvyB0/VA5OZJyb5ZstoN62AzD7YxVGog13kkfYWYqJYcK0kcqLZ6TrmH5qr4/8//ejVcX4x/a0UvaogXmA==", + "dev": true, "optional": true, "dependencies": { "bare-events": "^2.0.0", @@ -19066,12 +19577,14 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.2.1.tgz", "integrity": "sha512-OwPyHgBBMkhC29Hl3O4/YfxW9n7mdTr2+SsO29XBWKKJsbgj3mnorDB80r5TiCQgQstgE5ga1qNYrpes6NvX2w==", + "dev": true, "optional": true }, "node_modules/bare-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.0.tgz", "integrity": "sha512-DIIg7ts8bdRKwJRJrUMy/PICEaQZaPGZ26lsSx9MJSwIhSrcdHn7/C8W+XmnG/rKi6BaRcz+JO00CjZteybDtw==", + "dev": true, "optional": true, "dependencies": { "bare-os": "^2.1.0" @@ -19161,6 +19674,7 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.3.tgz", "integrity": "sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==", + "dev": true, "engines": { "node": ">=10.0.0" } @@ -19168,7 +19682,8 @@ "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true }, "node_modules/before-after-hook": { "version": "1.4.0", @@ -19231,6 +19746,7 @@ "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, "engines": { "node": ">=0.6" } @@ -19239,6 +19755,7 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, "engines": { "node": "*" } @@ -19260,6 +19777,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, "engines": { "node": ">=8" }, @@ -19344,6 +19862,7 @@ "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dev": true, "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.4", @@ -19367,6 +19886,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -19375,6 +19895,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { "ms": "2.0.0" } @@ -19383,6 +19904,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -19391,6 +19913,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -19402,6 +19925,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, "dependencies": { "ee-first": "1.1.1" }, @@ -19413,6 +19937,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", + "dev": true, "dependencies": { "array-flatten": "^2.1.2", "dns-equal": "^1.0.0", @@ -19423,7 +19948,8 @@ "node_modules/bonjour-service/node_modules/array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true }, "node_modules/boolbase": { "version": "1.0.0", @@ -19443,6 +19969,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, "dependencies": { "big-integer": "^1.6.44" }, @@ -19659,6 +20186,7 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, "engines": { "node": "*" } @@ -19696,6 +20224,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, "engines": { "node": ">=6" }, @@ -19712,12 +20241,14 @@ "node_modules/builtins": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", - "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==" + "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==", + "dev": true }, "node_modules/bundle-name": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, "dependencies": { "run-applescript": "^5.0.0" }, @@ -19851,6 +20382,7 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, "engines": { "node": ">=10.6.0" } @@ -19859,6 +20391,7 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", @@ -19876,6 +20409,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -19958,6 +20492,7 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, "dependencies": { "camelcase": "^5.3.1", "map-obj": "^4.0.0", @@ -19974,6 +20509,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, "engines": { "node": ">=8" }, @@ -19990,6 +20526,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, "dependencies": { "browserslist": "^4.0.0", "caniuse-lite": "^1.0.0", @@ -20038,7 +20575,8 @@ "node_modules/ccount": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz", - "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==" + "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", + "dev": true }, "node_modules/chainsaw": { "version": "0.1.0", @@ -20118,6 +20656,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, "engines": { "node": ">=10" } @@ -20125,32 +20664,38 @@ "node_modules/character-entities": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", - "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==" + "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==", + "dev": true }, "node_modules/character-entities-html4": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz", - "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==" + "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==", + "dev": true }, "node_modules/character-entities-legacy": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", - "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==" + "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==", + "dev": true }, "node_modules/character-reference-invalid": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", - "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==" + "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", + "dev": true }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true }, "node_modules/check-node-version": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/check-node-version/-/check-node-version-4.1.0.tgz", "integrity": "sha512-TSXGsyfW5/xY2QseuJn8/hleO2AU7HxVCdkc900jp1vcfzF840GkjvRT7CHl8sRtWn23n3X3k0cwH9RXeRwhfw==", + "dev": true, "dependencies": { "chalk": "^3.0.0", "map-values": "^1.0.1", @@ -20170,6 +20715,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -20182,6 +20728,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -20190,6 +20737,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -20198,6 +20746,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -20209,6 +20758,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -20232,6 +20782,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -20288,6 +20839,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, "engines": { "node": ">=6.0" } @@ -20296,6 +20848,7 @@ "version": "0.4.16", "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.16.tgz", "integrity": "sha512-7ZbXdWERxRxSwo3txsBjjmc/NLxqb1Bk30mRb0BMS4YIaiV6zvKZqL/UAH+DdqcDYayDWk2n/y8klkBDODrPvA==", + "dev": true, "dependencies": { "mitt": "3.0.0" }, @@ -20394,7 +20947,8 @@ "node_modules/cjs-module-lexer": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true }, "node_modules/class-utils": { "version": "0.3.6", @@ -20439,6 +20993,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, "engines": { "node": ">=6" } @@ -20447,6 +21002,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", + "dev": true, "dependencies": { "@types/webpack": "^4.4.31", "del": "^4.1.1" @@ -20588,7 +21144,8 @@ "node_modules/cli-width": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==" + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true }, "node_modules/client-zip": { "version": "2.4.5", @@ -20667,6 +21224,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, "dependencies": { "mimic-response": "^1.0.0" }, @@ -20695,6 +21253,7 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" @@ -20712,12 +21271,14 @@ "node_modules/collapse-white-space": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz", - "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==" + "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", + "dev": true }, "node_modules/collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==" + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true }, "node_modules/collection-visit": { "version": "1.0.0", @@ -20838,6 +21399,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -20854,6 +21416,7 @@ "version": "9.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz", "integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==", + "dev": true, "engines": { "node": "^12.20.0 || >=14" } @@ -20862,6 +21425,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.0.tgz", "integrity": "sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==", + "dev": true, "engines": { "node": ">= 12.0.0" } @@ -20869,7 +21433,8 @@ "node_modules/common-path-prefix": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==" + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true }, "node_modules/commondir": { "version": "1.0.1", @@ -20984,6 +21549,7 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, "engines": [ "node >= 0.8" ], @@ -21133,6 +21699,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, "dependencies": { "dot-prop": "^5.2.0", "graceful-fs": "^4.1.2", @@ -21149,6 +21716,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -21174,6 +21742,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, "engines": { "node": ">=0.8" } @@ -21224,6 +21793,7 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, "dependencies": { "safe-buffer": "5.2.1" }, @@ -21235,6 +21805,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, "funding": [ { "type": "github", @@ -21254,6 +21825,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -21527,6 +22099,7 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -21534,7 +22107,8 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true }, "node_modules/copy-concurrently": { "version": "1.0.5", @@ -21606,12 +22180,14 @@ "node_modules/copy-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/copy-dir/-/copy-dir-1.3.0.tgz", - "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==" + "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==", + "dev": true }, "node_modules/copy-webpack-plugin": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.0.tgz", "integrity": "sha512-my6iXII95c78w14HzYCNya5TlJYa44lOppAge5GSTMM1SyDxNsVGCJvhP4/ld6snm8lzjn3XOonMZD6s1L86Og==", + "dev": true, "dependencies": { "fast-glob": "^3.2.7", "glob-parent": "^6.0.1", @@ -21635,6 +22211,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -21651,6 +22228,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -21662,6 +22240,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "dev": true, "engines": { "node": ">=12" }, @@ -21673,6 +22252,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -21684,6 +22264,7 @@ "version": "12.2.0", "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", + "dev": true, "dependencies": { "array-union": "^3.0.1", "dir-glob": "^3.0.1", @@ -21702,12 +22283,14 @@ "node_modules/copy-webpack-plugin/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, "node_modules/copy-webpack-plugin/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -21726,6 +22309,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -21734,6 +22318,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, "engines": { "node": ">=12" }, @@ -22030,6 +22615,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.31.0.tgz", "integrity": "sha512-/AnE9Y4OsJZicCzIe97JP5XoPKQJfTuEG43aEVLFJGOJpyqELod+pE6LEl63DfG1Mp8wX97LDaDpy1GmLEUxlg==", + "dev": true, "hasInstallScript": true, "funding": { "type": "opencollective", @@ -22172,6 +22758,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "dev": true, "license": "MIT", "dependencies": { "node-fetch": "^2.6.12" @@ -22181,6 +22768,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "dev": true, "dependencies": { "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", @@ -22213,6 +22801,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, "engines": { "node": ">=8" } @@ -22220,7 +22809,8 @@ "node_modules/csp_evaluator": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/csp_evaluator/-/csp_evaluator-1.1.1.tgz", - "integrity": "sha512-N3ASg0C4kNPUaNxt1XAvzHIVuzdtr8KLgfk1O8WDyimp1GisPAHESupArO2ieHk9QWbrJ/WkQODyh21Ps/xhxw==" + "integrity": "sha512-N3ASg0C4kNPUaNxt1XAvzHIVuzdtr8KLgfk1O8WDyimp1GisPAHESupArO2ieHk9QWbrJ/WkQODyh21Ps/xhxw==", + "dev": true }, "node_modules/css": { "version": "2.2.4", @@ -22245,6 +22835,7 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "dev": true, "engines": { "node": "^10 || ^12 || >=14" }, @@ -22256,6 +22847,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.2.tgz", "integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==", + "dev": true, "engines": { "node": ">=12 || >=16" } @@ -22264,6 +22856,7 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.2.0.tgz", "integrity": "sha512-/rvHfYRjIpymZblf49w8jYcRo2y9gj6rV8UroHGmBxKrIyGLokpycyKzp9OkitvqT29ZSpzJ0Ic7SpnJX3sC8g==", + "dev": true, "dependencies": { "icss-utils": "^5.1.0", "postcss": "^8.2.15", @@ -22288,7 +22881,8 @@ "node_modules/css-loader/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/css-mediaquery": { "version": "0.1.2", @@ -22437,6 +23031,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, "bin": { "cssesc": "bin/cssesc" }, @@ -22448,6 +23043,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.0.1.tgz", "integrity": "sha512-fVO1JdJ0LSdIGJq68eIxOqFpIJrZqXUsBt8fkrBcztCQqAjQD51OhZp7tc0ImcbwXD4k7ny84QTV90nZhmqbkg==", + "dev": true, "dependencies": { "cssnano-preset-default": "^6.0.1", "lilconfig": "^2.1.0" @@ -22467,6 +23063,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.0.1.tgz", "integrity": "sha512-7VzyFZ5zEB1+l1nToKyrRkuaJIx0zi/1npjvZfbBwbtNTzhLtlvYraK/7/uqmX2Wb2aQtd983uuGw79jAjLSuQ==", + "dev": true, "dependencies": { "css-declaration-sorter": "^6.3.1", "cssnano-utils": "^4.0.0", @@ -22509,6 +23106,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.0.tgz", "integrity": "sha512-Z39TLP+1E0KUcd7LGyF4qMfu8ZufI0rDzhdyAMsa/8UyNUU8wpS0fhdBxbQbv32r64ea00h4878gommRVg2BHw==", + "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -22520,6 +23118,7 @@ "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, "dependencies": { "css-tree": "~2.2.0" }, @@ -22532,6 +23131,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" @@ -22544,12 +23144,14 @@ "node_modules/csso/node_modules/mdn-data": { "version": "2.0.28", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true }, "node_modules/csso/node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -22559,6 +23161,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", + "dev": true, "dependencies": { "rrweb-cssom": "^0.7.1" }, @@ -22575,6 +23178,7 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.10.0.tgz", "integrity": "sha512-YGZxdTTL9lmLkCUTpg4j0zQ7IhRB5ZmqNBbGCl3Tg6MP/d5/6sY7L5mmTjzbc6JKgVZYiqTQTNhPFsbXNGlRaA==", + "dev": true, "dependencies": { "find-pkg": "^0.1.2", "fs-exists-sync": "^0.1.0" @@ -22592,7 +23196,8 @@ "node_modules/damerau-levenshtein": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz", - "integrity": "sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==" + "integrity": "sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==", + "dev": true }, "node_modules/dargs": { "version": "7.0.0", @@ -22607,6 +23212,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-5.0.1.tgz", "integrity": "sha512-a9l6T1qqDogvvnw0nKlfZzqsyikEBZBClF39V3TFoKhDtGBqHu2HkuomJc02j5zft8zrUaXEuoicLeW54RkzPg==", + "dev": true, "engines": { "node": ">= 14" } @@ -22615,6 +23221,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, "dependencies": { "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0" @@ -22627,6 +23234,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, "dependencies": { "punycode": "^2.3.1" }, @@ -22638,6 +23246,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, "engines": { "node": ">=12" } @@ -22646,6 +23255,7 @@ "version": "14.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, "dependencies": { "tr46": "^5.0.0", "webidl-conversions": "^7.0.0" @@ -22719,6 +23329,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, "dependencies": { "decamelize": "^1.1.0", "map-obj": "^1.0.0" @@ -22730,7 +23341,8 @@ "node_modules/decimal.js": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true }, "node_modules/decode-uri-component": { "version": "0.2.2", @@ -22744,6 +23356,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, "dependencies": { "mimic-response": "^3.1.0" }, @@ -22758,6 +23371,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, "engines": { "node": ">=10" }, @@ -22775,6 +23389,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, "engines": { "node": ">=4.0.0" } @@ -22788,7 +23403,8 @@ "node_modules/deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true }, "node_modules/deepmerge": { "version": "4.3.1", @@ -22811,6 +23427,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "dev": true, "dependencies": { "bundle-name": "^3.0.0", "default-browser-id": "^3.0.0", @@ -22828,6 +23445,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, "dependencies": { "bplist-parser": "^0.2.0", "untildify": "^4.0.0" @@ -22843,6 +23461,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -22856,6 +23475,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.1", @@ -22878,6 +23498,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, "engines": { "node": ">=10" }, @@ -22889,6 +23510,7 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, "engines": { "node": ">=14.18.0" } @@ -22897,6 +23519,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -22908,6 +23531,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, "engines": { "node": ">=12" }, @@ -22919,6 +23543,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, "dependencies": { "path-key": "^4.0.0" }, @@ -22933,6 +23558,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, "engines": { "node": ">=12" }, @@ -22944,6 +23570,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, "dependencies": { "mimic-fn": "^4.0.0" }, @@ -22958,6 +23585,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -22966,6 +23594,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -22977,6 +23606,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } @@ -22985,6 +23615,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, "engines": { "node": ">=12" }, @@ -22996,6 +23627,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -23010,6 +23642,7 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, "dependencies": { "execa": "^5.0.0" }, @@ -23021,6 +23654,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -23034,6 +23668,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -23056,6 +23691,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, "engines": { "node": ">=10" }, @@ -23067,6 +23703,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, "engines": { "node": ">=10.17.0" } @@ -23075,6 +23712,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, "engines": { "node": ">=8" }, @@ -23086,6 +23724,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, "engines": { "node": ">=6" } @@ -23094,6 +23733,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -23105,6 +23745,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -23119,6 +23760,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -23127,6 +23769,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -23138,6 +23781,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } @@ -23146,6 +23790,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -23168,6 +23813,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, "engines": { "node": ">=10" } @@ -23176,6 +23822,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -23192,6 +23839,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, "engines": { "node": ">=8" } @@ -23200,6 +23848,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, "dependencies": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" @@ -23247,6 +23896,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dev": true, "dependencies": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", @@ -23260,6 +23910,7 @@ "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dev": true, "dependencies": { "tslib": "^2.0.1" }, @@ -23271,6 +23922,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, "dependencies": { "@types/glob": "^7.1.1", "globby": "^6.1.0", @@ -23288,6 +23940,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -23307,6 +23960,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "dev": true, "dependencies": { "array-union": "^1.0.1", "glob": "^7.0.3", @@ -23322,6 +23976,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -23330,6 +23985,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true, "engines": { "node": ">=6" } @@ -23338,6 +23994,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, "engines": { "node": ">=6" } @@ -23346,6 +24003,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -23357,6 +24015,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "engines": { "node": ">=0.4.0" } @@ -23381,6 +24040,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -23398,7 +24058,8 @@ "node_modules/deprecation": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true }, "node_modules/dequal": { "version": "2.0.3", @@ -23432,6 +24093,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", "integrity": "sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==", + "dev": true, "engines": { "node": ">=4" } @@ -23450,6 +24112,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, "engines": { "node": ">=8" } @@ -23457,7 +24120,8 @@ "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true }, "node_modules/detect-node-es": { "version": "1.1.0", @@ -23645,6 +24309,7 @@ "version": "0.0.1312386", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz", "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/diff": { @@ -23659,6 +24324,7 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -23684,6 +24350,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, "dependencies": { "path-type": "^4.0.0" }, @@ -23695,6 +24362,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "engines": { "node": ">=8" } @@ -23702,12 +24370,14 @@ "node_modules/dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", + "dev": true }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" }, @@ -23719,6 +24389,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -23814,6 +24485,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, "dependencies": { "is-obj": "^2.0.0" }, @@ -23825,6 +24497,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, "engines": { "node": ">=8" } @@ -23853,7 +24526,8 @@ "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true }, "node_modules/duplexer2": { "version": "0.1.4", @@ -24066,6 +24740,7 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, "engines": { "node": ">=12" }, @@ -24082,6 +24757,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, "engines": { "node": ">= 4" } @@ -24112,6 +24788,7 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, "dependencies": { "once": "^1.4.0" } @@ -24158,6 +24835,7 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, "dependencies": { "ansi-colors": "^4.1.1" }, @@ -24174,6 +24852,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, "engines": { "node": ">=6" } @@ -24245,6 +24924,7 @@ "version": "1.22.1", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", + "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "arraybuffer.prototype.slice": "^1.0.1", @@ -24297,6 +24977,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -24308,6 +24989,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, "engines": { "node": ">= 0.4" } @@ -24341,12 +25023,14 @@ "node_modules/es-module-lexer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", - "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", + "dev": true }, "node_modules/es-set-tostringtag": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, "dependencies": { "get-intrinsic": "^1.1.3", "has": "^1.0.3", @@ -24360,6 +25044,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, "dependencies": { "has": "^1.0.3" } @@ -24368,6 +25053,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -24472,6 +25158,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -24492,6 +25179,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { "node": ">=4.0" } @@ -24500,6 +25188,7 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz", "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==", + "dev": true, "dependencies": { "@eslint/eslintrc": "^1.0.4", "@humanwhocodes/config-array": "^0.6.0", @@ -24554,6 +25243,7 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -24584,6 +25274,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz", "integrity": "sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ==", + "dev": true, "dependencies": { "debug": "^3.2.7", "find-up": "^2.1.0", @@ -24597,6 +25288,7 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -24604,7 +25296,8 @@ "node_modules/eslint-module-utils/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true }, "node_modules/eslint-plugin-eslint-comments": { "version": "3.1.2", @@ -24626,6 +25319,7 @@ "version": "2.25.2", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.2.tgz", "integrity": "sha512-qCwQr9TYfoBHOFcVGKY9C9unq05uOxxdklmBXLVvcwo68y5Hta6/GzCZEMx2zQiu0woKNEER0LE7ZgaOfBU14g==", + "dev": true, "dependencies": { "array-includes": "^3.1.4", "array.prototype.flat": "^1.2.5", @@ -24652,6 +25346,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { "ms": "2.0.0" } @@ -24660,6 +25355,7 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -24670,6 +25366,7 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -24677,12 +25374,14 @@ "node_modules/eslint-plugin-import/node_modules/eslint-import-resolver-node/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true }, "node_modules/eslint-plugin-jest": { "version": "27.2.3", "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz", "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==", + "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" }, @@ -24726,6 +25425,7 @@ "version": "46.4.6", "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.6.tgz", "integrity": "sha512-z4SWYnJfOqftZI+b3RM9AtWL1vF/sLWE/LlO9yOKDof9yN2+n3zOdOJTGX/pRE/xnPsooOLG2Rq6e4d+XW3lNw==", + "dev": true, "dependencies": { "@es-joy/jsdoccomment": "~0.40.1", "are-docs-informative": "^0.0.2", @@ -24748,6 +25448,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "engines": { "node": ">=10" }, @@ -24759,6 +25460,7 @@ "version": "6.5.1", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz", "integrity": "sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==", + "dev": true, "dependencies": { "@babel/runtime": "^7.16.3", "aria-query": "^4.2.2", @@ -24783,12 +25485,14 @@ "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true }, "node_modules/eslint-plugin-playwright": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-0.15.3.tgz", "integrity": "sha512-LQMW5y0DLK5Fnpya7JR1oAYL2/7Y9wDiYw6VZqlKqcRGSgjbVKNqxraphk7ra1U3Bb5EK444xMgUlQPbMg2M1g==", + "dev": true, "peerDependencies": { "eslint": ">=7", "eslint-plugin-jest": ">=25" @@ -24803,6 +25507,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz", "integrity": "sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==", + "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.8.5" @@ -24831,6 +25536,7 @@ "version": "7.27.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.27.0.tgz", "integrity": "sha512-0Ut+CkzpppgFtoIhdzi2LpdpxxBvgFf99eFqWxJnUrO7mMe0eOiNpou6rvNYeVVV6lWZvTah0BFne7k5xHjARg==", + "dev": true, "dependencies": { "array-includes": "^3.1.4", "array.prototype.flatmap": "^1.2.5", @@ -24858,6 +25564,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz", "integrity": "sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==", + "dev": true, "engines": { "node": ">=10" }, @@ -24869,6 +25576,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { "node": ">=4.0" } @@ -24877,6 +25585,7 @@ "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -24893,6 +25602,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -24969,6 +25679,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, "dependencies": { "eslint-visitor-keys": "^2.0.0" }, @@ -24986,6 +25697,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, "engines": { "node": ">=10" } @@ -24994,6 +25706,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -25008,12 +25721,14 @@ "node_modules/eslint/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/eslint/node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -25027,6 +25742,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -25038,6 +25754,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "engines": { "node": ">=10" }, @@ -25049,6 +25766,7 @@ "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -25064,6 +25782,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -25075,6 +25794,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { "node": ">=4.0" } @@ -25083,6 +25803,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -25094,6 +25815,7 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, "engines": { "node": ">= 4" } @@ -25102,6 +25824,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -25113,6 +25836,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -25125,6 +25849,7 @@ "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -25141,6 +25866,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -25149,6 +25875,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, "engines": { "node": ">= 0.8.0" } @@ -25157,6 +25884,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -25168,6 +25896,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } @@ -25176,6 +25905,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, "engines": { "node": ">=8" }, @@ -25187,6 +25917,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -25198,6 +25929,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -25212,6 +25944,7 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/espree/-/espree-9.1.0.tgz", "integrity": "sha512-ZgYLvCS1wxOczBYGcQT9DDWgicXwJ4dbocr9uYN+/eresBAUuBu+O4WzB21ufQ/JqQT8gyp7hJ3z8SHii32mTQ==", + "dev": true, "dependencies": { "acorn": "^8.6.0", "acorn-jsx": "^5.3.1", @@ -25222,9 +25955,10 @@ } }, "node_modules/espree/node_modules/acorn": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", - "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -25237,6 +25971,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -25260,6 +25995,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -25271,6 +26007,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { "node": ">=4.0" } @@ -25279,6 +26016,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -25290,6 +26028,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { "node": ">=4.0" } @@ -25298,6 +26037,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, "engines": { "node": ">=4.0" } @@ -25306,6 +26046,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -25334,12 +26075,14 @@ "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, "engines": { "node": ">=0.8.x" } @@ -25358,6 +26101,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz", "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==", + "dev": true, "dependencies": { "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", @@ -25380,6 +26124,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -25393,6 +26138,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, "engines": { "node": ">=8" }, @@ -25404,6 +26150,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, "engines": { "node": ">=6" } @@ -25412,6 +26159,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -25423,6 +26171,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -25437,6 +26186,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -25445,6 +26195,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -25456,6 +26207,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } @@ -25464,6 +26216,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -25478,6 +26231,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, "engines": { "node": ">= 0.8.0" } @@ -25547,6 +26301,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", "integrity": "sha512-rtmc+cjLZqnu9dSYosX9EWmSJhTwpACgJQTfj4hgg2JjOD/6SIQalZrt4a3aQeh++oNxkazcaxrhPUj6+g5G/Q==", + "dev": true, "dependencies": { "os-homedir": "^1.0.1" }, @@ -25558,6 +26313,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz", "integrity": "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==", + "dev": true, "dependencies": { "@jest/expect-utils": "^29.6.2", "@types/node": "*", @@ -25573,7 +26329,8 @@ "node_modules/expect-puppeteer": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/expect-puppeteer/-/expect-puppeteer-4.4.0.tgz", - "integrity": "sha512-6Ey4Xy2xvmuQu7z7YQtMsaMV0EHJRpVxIDOd5GRrm04/I3nkTKIutELfECsLp6le+b3SSa3cXhPiw6PgqzxYWA==" + "integrity": "sha512-6Ey4Xy2xvmuQu7z7YQtMsaMV0EHJRpVxIDOd5GRrm04/I3nkTKIutELfECsLp6le+b3SSa3cXhPiw6PgqzxYWA==", + "dev": true }, "node_modules/exponential-backoff": { "version": "3.1.1", @@ -25585,6 +26342,7 @@ "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -25626,6 +26384,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { "ms": "2.0.0" } @@ -25634,6 +26393,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -25642,6 +26402,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -25659,6 +26420,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, "dependencies": { "ee-first": "1.1.1" }, @@ -25670,6 +26432,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, "funding": [ { "type": "github", @@ -25689,6 +26452,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -25696,7 +26460,8 @@ "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, "node_modules/extend-shallow": { "version": "3.0.2", @@ -25739,6 +26504,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "dev": true, "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", @@ -25752,6 +26518,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -25819,6 +26586,7 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "dev": true, "dependencies": { "concat-stream": "^1.6.2", "debug": "^2.6.9", @@ -25833,6 +26601,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { "ms": "2.0.0" } @@ -25841,6 +26610,7 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, "dependencies": { "minimist": "^1.2.6" }, @@ -25872,17 +26642,20 @@ "node_modules/fast-diff": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true }, "node_modules/fast-fifo": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.0.tgz", - "integrity": "sha512-IgfweLvEpwyA4WgiQe9Nx6VV2QkML2NkvZnk1oKnIzXgXdWxuhF7zw4DvLTPZJn6PIUneiAXPF24QmoEqHTjyw==" + "integrity": "sha512-IgfweLvEpwyA4WgiQe9Nx6VV2QkML2NkvZnk1oKnIzXgXdWxuhF7zw4DvLTPZJn6PIUneiAXPF24QmoEqHTjyw==", + "dev": true }, "node_modules/fast-glob": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -25898,6 +26671,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -25914,12 +26688,14 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true }, "node_modules/fast-memoize": { "version": "2.5.2", @@ -25930,6 +26706,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "dev": true, "license": "MIT" }, "node_modules/fast-xml-parser": { @@ -25957,6 +26734,7 @@ "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, "engines": { "node": ">= 4.9.1" } @@ -25965,6 +26743,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz", "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==", + "dev": true, "dependencies": { "reusify": "^1.0.0" } @@ -25973,6 +26752,7 @@ "version": "0.11.4", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, "dependencies": { "websocket-driver": ">=0.5.1" }, @@ -25992,6 +26772,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, "dependencies": { "pend": "~1.2.0" } @@ -26054,6 +26835,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -26147,6 +26929,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "dev": true, "engines": { "node": ">=4" } @@ -26155,6 +26938,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.2.0.tgz", "integrity": "sha512-pkgE+4p7N1n7QieOopmn3TqJaefjdWXwEkj2XLZJLKfOgcQKkn11ahvGNgTD8mLggexLiDFQxeTs14xVU22XPA==", + "dev": true, "dependencies": { "filename-reserved-regex": "^2.0.0", "strip-outer": "^1.0.1", @@ -26345,6 +27129,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-0.1.3.tgz", "integrity": "sha512-mBxmNbVyjg1LQIIpgO8hN+ybWBgDQK8qjht+EbrTCGmmPV/sc7RF1i9stPTD6bpvXZywBdrwRYxhSdJv867L6A==", + "dev": true, "dependencies": { "fs-exists-sync": "^0.1.0", "resolve-dir": "^0.1.0" @@ -26356,12 +27141,14 @@ "node_modules/find-parent-dir": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", - "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=" + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true }, "node_modules/find-pkg": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-0.1.2.tgz", "integrity": "sha512-0rnQWcFwZr7eO0513HahrWafsc3CTFioEB7DRiEYCUM/70QXSY8f3mCST17HXLcPvEhzH/Ty/Bxd72ZZsr/yvw==", + "dev": true, "dependencies": { "find-file-up": "^0.1.2" }, @@ -26373,6 +27160,7 @@ "version": "1.4.7", "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.7.tgz", "integrity": "sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==", + "dev": true, "dependencies": { "chalk": "^4.0.0", "commander": "^5.1.0", @@ -26386,6 +27174,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, "engines": { "node": ">= 6" } @@ -26399,6 +27188,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, "dependencies": { "locate-path": "^2.0.0" }, @@ -26428,6 +27218,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", @@ -26441,7 +27232,8 @@ "node_modules/flatted": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true }, "node_modules/flow-enums-runtime": { "version": "0.0.6", @@ -26476,6 +27268,7 @@ "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, "funding": [ { "type": "individual", @@ -26495,6 +27288,7 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, "dependencies": { "is-callable": "^1.1.3" } @@ -26503,6 +27297,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -26511,6 +27306,7 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==", + "dev": true, "dependencies": { "for-in": "^1.0.1" }, @@ -26752,6 +27548,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -26786,6 +27583,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -26794,6 +27592,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true, "engines": { "node": "*" }, @@ -26866,6 +27665,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", "integrity": "sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -26898,7 +27698,8 @@ "node_modules/fs-monkey": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", - "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==" + "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==", + "dev": true }, "node_modules/fs-write-stream-atomic": { "version": "1.0.10", @@ -27037,6 +27838,7 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", @@ -27053,12 +27855,14 @@ "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -27297,6 +28101,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -27356,6 +28161,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "dev": true, "engines": { "node": ">=8" }, @@ -27367,6 +28173,7 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true, "engines": { "node": ">=12" }, @@ -27378,6 +28185,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, "dependencies": { "pump": "^3.0.0" }, @@ -27392,6 +28200,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -27402,6 +28211,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.1" @@ -27417,6 +28227,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.1.tgz", "integrity": "sha512-7ZqONUVqaabogsYNWlYj0t3YZaL6dhuEueZXGF+/YVmf6dHmaFg8/6psJKqhx9QykIDKzpGcy2cn4oV4YC7V/Q==", + "dev": true, "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^5.0.1", @@ -27656,12 +28467,14 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true }, "node_modules/global-modules": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, "dependencies": { "global-prefix": "^3.0.0" }, @@ -27673,6 +28486,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, "dependencies": { "ini": "^1.3.5", "kind-of": "^6.0.2", @@ -27686,6 +28500,7 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -27700,6 +28515,7 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, "engines": { "node": ">=10" }, @@ -27711,6 +28527,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, "dependencies": { "define-properties": "^1.1.3" }, @@ -27725,6 +28542,7 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -27744,6 +28562,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, "engines": { "node": ">=8" } @@ -27752,6 +28571,7 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -27767,6 +28587,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -27777,7 +28598,8 @@ "node_modules/globjoin": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==" + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true }, "node_modules/good-listener": { "version": "1.2.2", @@ -27791,6 +28613,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -27802,6 +28625,7 @@ "version": "11.8.6", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, "dependencies": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", @@ -27844,7 +28668,8 @@ "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true }, "node_modules/gunzip-maybe": { "version": "1.4.2", @@ -27881,7 +28706,8 @@ "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true }, "node_modules/handlebars": { "version": "4.7.8", @@ -27908,6 +28734,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, "engines": { "node": ">=6" } @@ -27948,6 +28775,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -27964,6 +28792,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -27975,6 +28804,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -27986,6 +28816,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -27997,6 +28828,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -28120,6 +28952,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -28213,6 +29046,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, "dependencies": { "parse-passwd": "^1.0.0" }, @@ -28224,6 +29058,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -28235,6 +29070,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -28245,12 +29081,14 @@ "node_modules/hosted-git-info/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, "dependencies": { "inherits": "^2.0.1", "obuf": "^1.0.0", @@ -28267,6 +29105,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, "dependencies": { "whatwg-encoding": "^3.1.1" }, @@ -28278,6 +29117,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "dev": true, "funding": [ { "type": "github", @@ -28292,7 +29132,8 @@ "node_modules/html-escaper": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", - "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==" + "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", + "dev": true }, "node_modules/html-minifier-terser": { "version": "6.1.0", @@ -28328,6 +29169,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, "engines": { "node": ">=8" }, @@ -28476,12 +29318,14 @@ "node_modules/http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true }, "node_modules/http-deceiver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true }, "node_modules/http-errors": { "version": "2.0.0", @@ -28523,6 +29367,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/http-link-header/-/http-link-header-1.1.1.tgz", "integrity": "sha512-mW3N/rTYpCn99s1do0zx6nzFZSwLH9HGfUM4ZqLWJ16ylmYaC2v5eYGqrNTQlByx8AzUgGI+V/32gXPugs1+Sw==", + "dev": true, "engines": { "node": ">=6.0.0" } @@ -28530,12 +29375,14 @@ "node_modules/http-parser-js": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", - "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==" + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", + "dev": true }, "node_modules/http-proxy": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", @@ -28572,6 +29419,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", @@ -28601,6 +29449,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" @@ -28613,6 +29462,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, "engines": { "node": ">=10" }, @@ -28630,6 +29480,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -28642,6 +29493,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, "engines": { "node": ">=8.12.0" } @@ -28685,6 +29537,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, "engines": { "node": "^10 || ^12 || >= 14" }, @@ -28721,6 +29574,7 @@ "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, "engines": { "node": ">= 4" } @@ -28729,6 +29583,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-4.0.1.tgz", "integrity": "sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==", + "dev": true, "dependencies": { "minimatch": "^3.0.4" }, @@ -28753,7 +29608,8 @@ "node_modules/image-ssim": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/image-ssim/-/image-ssim-0.2.0.tgz", - "integrity": "sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==" + "integrity": "sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==", + "dev": true }, "node_modules/import-fresh": { "version": "3.3.0", @@ -28782,6 +29638,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -28800,6 +29657,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -28812,6 +29670,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -28823,6 +29682,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -28837,6 +29697,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -28848,6 +29709,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, "engines": { "node": ">=6" } @@ -28856,6 +29718,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "engines": { "node": ">=8" } @@ -28864,6 +29727,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, "dependencies": { "find-up": "^4.0.0" }, @@ -28933,7 +29797,8 @@ "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true }, "node_modules/init-package-json": { "version": "5.0.0", @@ -29002,6 +29867,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", + "dev": true, "dependencies": { "ansi-escapes": "^4.2.1", "chalk": "^3.0.0", @@ -29025,6 +29891,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -29037,6 +29904,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, "dependencies": { "restore-cursor": "^3.1.0" }, @@ -29047,12 +29915,14 @@ "node_modules/inquirer/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/inquirer/node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -29067,6 +29937,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -29075,6 +29946,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -29083,6 +29955,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, "engines": { "node": ">=6" } @@ -29091,6 +29964,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -29105,6 +29979,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -29117,6 +29992,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -29130,6 +30006,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -29141,6 +30018,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, "dependencies": { "get-intrinsic": "^1.2.0", "has": "^1.0.3", @@ -29154,6 +30032,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, "engines": { "node": ">=10.13.0" } @@ -29162,6 +30041,7 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-4.4.0.tgz", "integrity": "sha512-z+Bj2rS3LZSYU4+sNitdHrwnBhr0wO80ZJSW8EzKDBowwUe3Q/UsvgCGjrwa+HPzoGCLEb9HAjfJgo4j2Sac8w==", + "dev": true, "dependencies": { "intl-messageformat-parser": "^1.8.1" } @@ -29170,7 +30050,8 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.8.1.tgz", "integrity": "sha512-IMSCKVf0USrM/959vj3xac7s8f87sc+80Y/ipBzdKy4ifBv5Gsj2tZ41EAaURVg01QU71fYr77uA8Meh6kELbg==", - "deprecated": "We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser" + "deprecated": "We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser", + "dev": true }, "node_modules/invariant": { "version": "2.2.4", @@ -29189,6 +30070,7 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, "license": "MIT", "dependencies": { "jsbn": "1.1.0", @@ -29202,12 +30084,14 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, "engines": { "node": ">= 0.10" } @@ -29216,6 +30100,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.2.0.tgz", "integrity": "sha512-YqTdPLfwP7YFN0SsD3QUVCkm9ZG2VzOXv3DOrw5G5mkMbVwptTwVcFv7/C0vOpBmgTxAeTG19XpUs1E522LW9Q==", + "dev": true, "engines": { "node": ">=8" } @@ -29245,6 +30130,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -29254,6 +30140,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", "integrity": "sha512-ZmRL7++ZkcMOfDuWZuMJyIVLr2keE1o/DeNWh1EmgqGhUcV+9BIVsx0BcSBOHTZqzjs4+dISzr2KAeBEWGgXeA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -29262,6 +30149,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", + "dev": true, "dependencies": { "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0" @@ -29287,6 +30175,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.0", @@ -29305,6 +30194,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, "dependencies": { "has-bigints": "^1.0.1" }, @@ -29316,6 +30206,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -29327,6 +30218,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -29341,12 +30233,14 @@ "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true }, "node_modules/is-builtin-module": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, "dependencies": { "builtin-modules": "^3.3.0" }, @@ -29361,6 +30255,7 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -29413,6 +30308,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -29426,7 +30322,8 @@ "node_modules/is-decimal": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", - "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==" + "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", + "dev": true }, "node_modules/is-deflate": { "version": "1.0.0", @@ -29473,6 +30370,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -29481,6 +30379,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -29497,6 +30396,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, "engines": { "node": ">=6" } @@ -29520,6 +30420,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -29539,12 +30440,14 @@ "node_modules/is-hexadecimal": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", - "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==" + "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", + "dev": true }, "node_modules/is-inside-container": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, "dependencies": { "is-docker": "^3.0.0" }, @@ -29562,6 +30465,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, "bin": { "is-docker": "cli.js" }, @@ -29615,6 +30519,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -29638,6 +30543,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -29685,6 +30591,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true, "engines": { "node": ">=6" } @@ -29693,6 +30600,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, "dependencies": { "is-path-inside": "^2.1.0" }, @@ -29704,6 +30612,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, "dependencies": { "path-is-inside": "^1.0.2" }, @@ -29715,6 +30624,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, "engines": { "node": ">=10" }, @@ -29733,7 +30643,8 @@ "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true }, "node_modules/is-promise": { "version": "4.0.0", @@ -29744,6 +30655,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -29777,6 +30689,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, "dependencies": { "call-bind": "^1.0.2" }, @@ -29806,6 +30719,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -29820,6 +30734,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -29846,6 +30761,7 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, "dependencies": { "which-typed-array": "^1.1.11" }, @@ -29859,7 +30775,8 @@ "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true }, "node_modules/is-unicode-supported": { "version": "0.1.0", @@ -29885,6 +30802,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.2" }, @@ -29909,6 +30827,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", + "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -29927,6 +30846,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", + "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -29971,6 +30891,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, "engines": { "node": ">=8" } @@ -29979,6 +30900,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", @@ -29994,6 +30916,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -30002,6 +30925,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", @@ -30015,6 +30939,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -30023,6 +30948,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -30034,6 +30960,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -30047,6 +30974,7 @@ "version": "3.1.6", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -30106,6 +31034,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz", "integrity": "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==", + "dev": true, "dependencies": { "@jest/core": "^29.6.2", "@jest/types": "^29.6.1", @@ -30131,6 +31060,7 @@ "version": "29.5.0", "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", + "dev": true, "dependencies": { "execa": "^5.0.0", "p-limit": "^3.1.0" @@ -30143,6 +31073,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -30156,6 +31087,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -30178,6 +31110,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, "engines": { "node": ">=10" }, @@ -30189,6 +31122,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, "engines": { "node": ">=10.17.0" } @@ -30197,6 +31131,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, "engines": { "node": ">=8" }, @@ -30208,6 +31143,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, "engines": { "node": ">=6" } @@ -30216,6 +31152,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -30227,6 +31164,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -30241,6 +31179,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -30249,6 +31188,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -30260,6 +31200,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } @@ -30268,6 +31209,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -30282,6 +31224,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz", "integrity": "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==", + "dev": true, "dependencies": { "@jest/environment": "^29.6.2", "@jest/expect": "^29.6.2", @@ -30312,6 +31255,7 @@ "version": "1.5.3", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, @@ -30325,6 +31269,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz", "integrity": "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==", + "dev": true, "dependencies": { "@jest/core": "^29.6.2", "@jest/test-result": "^29.6.2", @@ -30358,6 +31303,7 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -30370,12 +31316,14 @@ "node_modules/jest-cli/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/jest-cli/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -30384,6 +31332,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -30397,6 +31346,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -30413,6 +31363,7 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, "engines": { "node": ">=10" } @@ -30421,6 +31372,7 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -30438,6 +31390,7 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, "engines": { "node": ">=12" } @@ -30446,6 +31399,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz", "integrity": "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==", + "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.6.2", @@ -30490,6 +31444,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -30509,6 +31464,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, "engines": { "node": ">=8" }, @@ -30520,6 +31476,7 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", @@ -30534,6 +31491,7 @@ "version": "29.4.3", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", + "dev": true, "dependencies": { "detect-newline": "^3.0.0" }, @@ -30545,6 +31503,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz", "integrity": "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==", + "dev": true, "dependencies": { "@jest/types": "^29.6.1", "chalk": "^4.0.0", @@ -30560,6 +31519,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.6.2.tgz", "integrity": "sha512-7oa/+266AAEgkzae8i1awNEfTfjwawWKLpiw2XesZmaoVVj9u9t8JOYx18cG29rbPNtkUlZ8V4b5Jb36y/VxoQ==", + "dev": true, "dependencies": { "@jest/environment": "^29.6.2", "@jest/fake-timers": "^29.6.2", @@ -30610,6 +31570,7 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -30698,6 +31659,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz", "integrity": "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==", + "dev": true, "dependencies": { "jest-get-type": "^29.4.3", "pretty-format": "^29.6.2" @@ -30710,6 +31672,7 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.7.0", @@ -30724,6 +31687,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz", "integrity": "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==", + "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.6.1", @@ -30756,6 +31720,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, "engines": { "node": ">=6" }, @@ -30772,6 +31737,7 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -30780,6 +31746,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz", "integrity": "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==", + "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", @@ -30799,6 +31766,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz", "integrity": "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==", + "dev": true, "dependencies": { "jest-regex-util": "^29.4.3", "jest-snapshot": "^29.6.2" @@ -30811,6 +31779,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz", "integrity": "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==", + "dev": true, "dependencies": { "@jest/console": "^29.6.2", "@jest/environment": "^29.6.2", @@ -30842,6 +31811,7 @@ "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -30851,6 +31821,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz", "integrity": "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==", + "dev": true, "dependencies": { "@jest/environment": "^29.6.2", "@jest/fake-timers": "^29.6.2", @@ -30883,6 +31854,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -30902,6 +31874,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz", "integrity": "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==", + "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", @@ -31085,6 +32058,7 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz", "integrity": "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==", + "dev": true, "dependencies": { "@jest/test-result": "^29.6.2", "@jest/types": "^29.6.1", @@ -31151,12 +32125,14 @@ "node_modules/jpeg-js": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", - "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", + "dev": true }, "node_modules/js-library-detector": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/js-library-detector/-/js-library-detector-6.7.0.tgz", "integrity": "sha512-c80Qupofp43y4cJ7+8TTDN/AsDwLi5oOm/plBrWI+iQt485vKXCco+yVmOwEgdo9VOdsYTuV0UlTeetVPTriXA==", + "dev": true, "engines": { "node": ">=12" } @@ -31182,6 +32158,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true, "license": "MIT" }, "node_modules/jsc-android": { @@ -31264,6 +32241,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "dev": true, "engines": { "node": ">=12.0.0" } @@ -31272,6 +32250,7 @@ "version": "25.0.1", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", + "dev": true, "dependencies": { "cssstyle": "^4.1.0", "data-urls": "^5.0.0", @@ -31320,6 +32299,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, "dependencies": { "debug": "^4.3.4" }, @@ -31331,6 +32311,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -31343,6 +32324,7 @@ "version": "7.0.5", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -31355,6 +32337,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, "dependencies": { "punycode": "^2.3.1" }, @@ -31366,6 +32349,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, "engines": { "node": ">=12" } @@ -31374,6 +32358,7 @@ "version": "14.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, "dependencies": { "tr46": "^5.0.0", "webidl-conversions": "^7.0.0" @@ -31386,6 +32371,7 @@ "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -31450,7 +32436,8 @@ "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true }, "node_modules/json-parse-better-errors": { "version": "1.0.2", @@ -31471,7 +32458,8 @@ "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/json-stable-stringify": { "version": "1.1.0", @@ -31494,7 +32482,8 @@ "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true }, "node_modules/json-stable-stringify/node_modules/isarray": { "version": "2.0.5", @@ -31521,7 +32510,8 @@ "node_modules/json2php": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/json2php/-/json2php-0.0.7.tgz", - "integrity": "sha512-dnSoUiLAoVaMXxFsVi4CrPVYMKOuDBXTghXSmMINX44RZ8WM9cXlY7UqrQnlAcODCVO7FV3+8t/5nDKAjimLfg==" + "integrity": "sha512-dnSoUiLAoVaMXxFsVi4CrPVYMKOuDBXTghXSmMINX44RZ8WM9cXlY7UqrQnlAcODCVO7FV3+8t/5nDKAjimLfg==", + "dev": true }, "node_modules/json5": { "version": "2.2.3", @@ -31537,7 +32527,8 @@ "node_modules/jsonc-parser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==" + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "dev": true }, "node_modules/jsonfile": { "version": "4.0.0", @@ -31585,6 +32576,7 @@ "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", @@ -31599,6 +32591,7 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, "dependencies": { "json-buffer": "3.0.1" } @@ -31641,6 +32634,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "dev": true, "engines": { "node": ">= 8" } @@ -31648,7 +32642,8 @@ "node_modules/known-css-properties": { "version": "0.34.0", "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.34.0.tgz", - "integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==" + "integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==", + "dev": true }, "node_modules/kuler": { "version": "2.0.0", @@ -31671,12 +32666,14 @@ "node_modules/language-subtag-registry": { "version": "0.3.21", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz", - "integrity": "sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==" + "integrity": "sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==", + "dev": true }, "node_modules/language-tags": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "dev": true, "dependencies": { "language-subtag-registry": "~0.3.2" } @@ -31685,6 +32682,7 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", + "dev": true, "dependencies": { "picocolors": "^1.0.0", "shell-quote": "^1.7.3" @@ -31694,6 +32692,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -32813,6 +33812,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -33003,6 +34003,7 @@ "version": "10.4.0", "resolved": "https://registry.npmjs.org/lighthouse/-/lighthouse-10.4.0.tgz", "integrity": "sha512-XQWHEWkJ8YxSPsxttBJORy5+hQrzbvGkYfeP3fJjyYKioWkF2MXfFqNK4ZuV4jL8pBu7Z91qnQP6In0bq1yXww==", + "dev": true, "dependencies": { "@sentry/node": "^6.17.4", "axe-core": "4.7.2", @@ -33061,12 +34062,14 @@ "node_modules/lighthouse-stack-packs": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/lighthouse-stack-packs/-/lighthouse-stack-packs-1.11.0.tgz", - "integrity": "sha512-sRr0z1S/I26VffRLq9KJsKtLk856YrJlNGmcJmbLX8dFn3MuzVPUbstuChEhqnSxZb8TZmVfthuXuwhG9vRoSw==" + "integrity": "sha512-sRr0z1S/I26VffRLq9KJsKtLk856YrJlNGmcJmbLX8dFn3MuzVPUbstuChEhqnSxZb8TZmVfthuXuwhG9vRoSw==", + "dev": true }, "node_modules/lighthouse/node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -33079,17 +34082,20 @@ "node_modules/lighthouse/node_modules/devtools-protocol": { "version": "0.0.1155343", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1155343.tgz", - "integrity": "sha512-oD9vGBV2wTc7fAzAM6KC0chSgs234V8+qDEeK+mcbRj2UvcuA7lgBztGi/opj/iahcXD3BSj8Ymvib628yy9FA==" + "integrity": "sha512-oD9vGBV2wTc7fAzAM6KC0chSgs234V8+qDEeK+mcbRj2UvcuA7lgBztGi/opj/iahcXD3BSj8Ymvib628yy9FA==", + "dev": true }, "node_modules/lighthouse/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/lighthouse/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -33098,6 +34104,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -33109,6 +34116,7 @@ "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -33125,6 +34133,7 @@ "version": "20.9.0", "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-20.9.0.tgz", "integrity": "sha512-H9fYZQzMTRrkboEfPmf7m3CLDN6JvbxXA3qTtS+dFt27tR+CsFHzPsT6pzp6lYL6bJbAPaR0HaPO6uSi+F94Pg==", + "dev": true, "dependencies": { "@puppeteer/browsers": "1.4.6", "chromium-bidi": "0.4.16", @@ -33148,12 +34157,14 @@ "node_modules/lighthouse/node_modules/puppeteer-core/node_modules/devtools-protocol": { "version": "0.0.1147663", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1147663.tgz", - "integrity": "sha512-hyWmRrexdhbZ1tcJUGpO95ivbRhWXz++F4Ko+n21AY5PNln2ovoJw+8ZMNDTtip+CNFQfrtLVh/w4009dXO/eQ==" + "integrity": "sha512-hyWmRrexdhbZ1tcJUGpO95ivbRhWXz++F4Ko+n21AY5PNln2ovoJw+8ZMNDTtip+CNFQfrtLVh/w4009dXO/eQ==", + "dev": true }, "node_modules/lighthouse/node_modules/puppeteer-core/node_modules/ws": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "dev": true, "engines": { "node": ">=10.0.0" }, @@ -33174,6 +34185,7 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, "bin": { "semver": "bin/semver" } @@ -33182,6 +34194,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -33195,6 +34208,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -33211,6 +34225,7 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, "engines": { "node": ">=10" } @@ -33219,6 +34234,7 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -33236,6 +34252,7 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, "engines": { "node": ">=12" } @@ -33244,6 +34261,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, "engines": { "node": ">=10" } @@ -33268,6 +34286,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dev": true, "dependencies": { "uc.micro": "^1.0.1" } @@ -33790,6 +34809,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -33826,6 +34846,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -33862,12 +34883,14 @@ "node_modules/lodash.escape": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==" + "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==", + "dev": true }, "node_modules/lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dev": true }, "node_modules/lodash.get": { "version": "4.4.2", @@ -33878,7 +34901,8 @@ "node_modules/lodash.invokemap": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.invokemap/-/lodash.invokemap-4.6.0.tgz", - "integrity": "sha512-CfkycNtMqgUlfjfdh2BhKO/ZXrP8ePOX5lEU/g0R3ItJcnuxWDwokMGKx1hWcfOikmyOVx6X9IwWnDGlgKl61w==" + "integrity": "sha512-CfkycNtMqgUlfjfdh2BhKO/ZXrP8ePOX5lEU/g0R3ItJcnuxWDwokMGKx1hWcfOikmyOVx6X9IwWnDGlgKl61w==", + "dev": true }, "node_modules/lodash.ismatch": { "version": "4.4.0", @@ -33889,17 +34913,20 @@ "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true }, "node_modules/lodash.pullall": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.pullall/-/lodash.pullall-4.2.0.tgz", - "integrity": "sha512-VhqxBKH0ZxPpLhiu68YD1KnHmbhQJQctcipvmFnqIBDYzcIHzf3Zpu0tpeOKtR4x76p9yohc506eGdOjTmyIBg==" + "integrity": "sha512-VhqxBKH0ZxPpLhiu68YD1KnHmbhQJQctcipvmFnqIBDYzcIHzf3Zpu0tpeOKtR4x76p9yohc506eGdOjTmyIBg==", + "dev": true }, "node_modules/lodash.set": { "version": "4.3.2", @@ -33915,17 +34942,20 @@ "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==" + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true }, "node_modules/lodash.uniqby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==" + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", + "dev": true }, "node_modules/lodash.zip": { "version": "4.2.0", @@ -34183,12 +35213,14 @@ "node_modules/longest-streak": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", - "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==" + "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", + "dev": true }, "node_modules/lookup-closest-locale": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/lookup-closest-locale/-/lookup-closest-locale-6.2.0.tgz", - "integrity": "sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==" + "integrity": "sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==", + "dev": true }, "node_modules/loose-envify": { "version": "1.4.0", @@ -34213,6 +35245,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, "engines": { "node": ">=8" } @@ -34220,12 +35253,14 @@ "node_modules/lru_map": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==" + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", + "dev": true }, "node_modules/lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, "dependencies": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" @@ -34271,6 +35306,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "dev": true, "dependencies": { "semver": "^6.0.0" }, @@ -34282,6 +35318,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -34530,6 +35567,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -34543,7 +35581,8 @@ "node_modules/map-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-values/-/map-values-1.0.1.tgz", - "integrity": "sha512-BbShUnr5OartXJe1GeccAWtfro11hhgNJg6G9/UtWKjVGvV5U4C09cg5nk8JUevhXODaXY+hQ3xxMUKSs62ONQ==" + "integrity": "sha512-BbShUnr5OartXJe1GeccAWtfro11hhgNJg6G9/UtWKjVGvV5U4C09cg5nk8JUevhXODaXY+hQ3xxMUKSs62ONQ==", + "dev": true }, "node_modules/map-visit": { "version": "1.0.0", @@ -34815,12 +35854,14 @@ "node_modules/markdown-escapes": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz", - "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==" + "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", + "dev": true }, "node_modules/markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dev": true, "dependencies": { "argparse": "^2.0.1", "entities": "~2.1.0", @@ -34835,12 +35876,14 @@ "node_modules/markdown-it/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/markdown-it/node_modules/entities": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -34848,7 +35891,8 @@ "node_modules/markdown-table": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", - "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==" + "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", + "dev": true }, "node_modules/markdown-to-jsx": { "version": "7.4.1", @@ -34866,6 +35910,7 @@ "version": "0.25.1", "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.25.1.tgz", "integrity": "sha512-AG7UkLzNa1fxiOv5B+owPsPhtM4D6DoODhsJgiaNg1xowXovrYgOnLqAgOOFQpWOlHFVQUzjMY5ypNNTeov92g==", + "dev": true, "dependencies": { "markdown-it": "12.3.2" }, @@ -34877,6 +35922,7 @@ "version": "0.31.1", "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.31.1.tgz", "integrity": "sha512-keIOMwQn+Ch7MoBwA+TdkyVMuxAeZFEGmIIlvwgV0Z1TGS5MxPnRr29XCLhkNzCHU+uNKGjU+VEjLX+Z9kli6g==", + "dev": true, "dependencies": { "commander": "~9.0.0", "get-stdin": "~9.0.0", @@ -34899,12 +35945,14 @@ "node_modules/markdownlint-cli/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/markdownlint-cli/node_modules/commander": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/commander/-/commander-9.0.0.tgz", "integrity": "sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==", + "dev": true, "engines": { "node": "^12.20.0 || >=14" } @@ -34913,6 +35961,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -34932,6 +35981,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -34943,6 +35993,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -34954,6 +36005,7 @@ "version": "3.0.8", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -34964,7 +36016,8 @@ "node_modules/markdownlint-rule-helpers": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.16.0.tgz", - "integrity": "sha512-oEacRUVeTJ5D5hW1UYd2qExYI0oELdYK72k1TKGvIeYJIbqQWAz476NAc7LNixSySUhcNl++d02DvX0ccDk9/w==" + "integrity": "sha512-oEacRUVeTJ5D5hW1UYd2qExYI0oELdYK72k1TKGvIeYJIbqQWAz476NAc7LNixSySUhcNl++d02DvX0ccDk9/w==", + "dev": true }, "node_modules/marked": { "version": "4.3.0", @@ -35010,6 +36063,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -35030,6 +36084,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", + "dev": true, "dependencies": { "unist-util-modify-children": "^1.0.0", "unist-util-visit": "^1.1.0" @@ -35091,6 +36146,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", "integrity": "sha512-CcJ0mHa36QYumDKiZ2OIR+ClhfOM7zIzN+Wfy8tRZ1hpH9DKLCS+Mh4DyK5bCxzE9uxMWcbIpeNFWsg1zrj/2g==", + "dev": true, "dependencies": { "mdast-util-to-string": "^1.0.0" } @@ -35098,7 +36154,8 @@ "node_modules/mdast-util-to-string": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.5.tgz", - "integrity": "sha512-2qLt/DEOo5F6nc2VFScQiHPzQ0XXcabquRJxKMhKte8nt42o08HUxNDPk7tt0YPxnWjAT11I1SYi0X0iPnfI5A==" + "integrity": "sha512-2qLt/DEOo5F6nc2VFScQiHPzQ0XXcabquRJxKMhKte8nt42o08HUxNDPk7tt0YPxnWjAT11I1SYi0X0iPnfI5A==", + "dev": true }, "node_modules/mdn-data": { "version": "2.0.14", @@ -35108,12 +36165,14 @@ "node_modules/mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -35122,6 +36181,7 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, "dependencies": { "fs-monkey": "^1.0.4" }, @@ -35223,6 +36283,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz", "integrity": "sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==", + "dev": true, "dependencies": { "arr-union": "^3.1.0", "clone-deep": "^0.2.4", @@ -35236,6 +36297,7 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", "integrity": "sha512-we+NuQo2DHhSl+DP6jlUiAhyAjBQrYnpOk15rN6c6JSPScjiCLh8IbSU+VTcph6YS3o7mASE8a0+gbZ7ChLpgg==", + "dev": true, "dependencies": { "for-own": "^0.1.3", "is-plain-object": "^2.0.1", @@ -35251,6 +36313,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, "dependencies": { "isobject": "^3.0.1" }, @@ -35262,6 +36325,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, "dependencies": { "is-buffer": "^1.1.5" }, @@ -35273,6 +36337,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", "integrity": "sha512-J1zdXCky5GmNnuauESROVu31MQSnLoYvlyEn6j2Ztk6Q5EHFIhxkMhYcv6vuDzl2XEzoRr856QwzMgWM/TmZgw==", + "dev": true, "dependencies": { "is-extendable": "^0.1.1", "kind-of": "^2.0.1", @@ -35287,6 +36352,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", "integrity": "sha512-0u8i1NZ/mg0b+W3MGGw5I7+6Eib2nx72S/QvXa0hYjEkjTknYmEYQJwGu3mLC0BrhtJjtQafTkyRUQ75Kx0LVg==", + "dev": true, "dependencies": { "is-buffer": "^1.0.2" }, @@ -35298,6 +36364,7 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", "integrity": "sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -35305,7 +36372,8 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true }, "node_modules/merge-stream": { "version": "2.0.0", @@ -35316,6 +36384,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, "engines": { "node": ">= 8" } @@ -35323,7 +36392,8 @@ "node_modules/metaviewport-parser": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/metaviewport-parser/-/metaviewport-parser-0.3.0.tgz", - "integrity": "sha512-EoYJ8xfjQ6kpe9VbVHvZTZHiOl4HL1Z18CrZ+qahvLXT7ZO4YTC2JMyt5FaUp9JJp6J4Ybb/z7IsCXZt86/QkQ==" + "integrity": "sha512-EoYJ8xfjQ6kpe9VbVHvZTZHiOl4HL1Z18CrZ+qahvLXT7ZO4YTC2JMyt5FaUp9JJp6J4Ybb/z7IsCXZt86/QkQ==", + "dev": true }, "node_modules/method-override": { "version": "3.0.0", @@ -35353,6 +36423,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -35835,6 +36906,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, "bin": { "mime": "cli.js" }, @@ -35874,6 +36946,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, "engines": { "node": ">=4" } @@ -35882,6 +36955,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, "engines": { "node": ">=4" } @@ -35890,6 +36964,7 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.1.tgz", "integrity": "sha512-CRC6E2yedNjfOA3nQjpqAkpnranxhxmilhBPYtldnXcPT/QZb3aJFzvt0pp8W1jhuLR/E0zDa+QEHuC/HhhaLQ==", + "dev": true, "dependencies": { "schema-utils": "^4.0.0" }, @@ -35908,6 +36983,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -35924,6 +37000,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -35934,12 +37011,14 @@ "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -35957,7 +37036,8 @@ "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true }, "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", @@ -35988,6 +37068,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, "dependencies": { "arrify": "^1.0.1", "is-plain-obj": "^1.1.0", @@ -36001,6 +37082,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -36161,7 +37243,8 @@ "node_modules/mitt": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", - "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==" + "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==", + "dev": true }, "node_modules/mixin-deep": { "version": "1.3.2", @@ -36204,6 +37287,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", "integrity": "sha512-ALGF1Jt9ouehcaXaHhn6t1yGWRqGaHkPFndtFVHfZXOvkIZ/yoGaSi0AHVTafb3ZBGg4dr/bDwnaEKqCXzchMA==", + "dev": true, "dependencies": { "for-in": "^0.1.3", "is-extendable": "^0.1.1" @@ -36216,6 +37300,7 @@ "version": "0.1.8", "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", "integrity": "sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -36238,7 +37323,8 @@ "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true }, "node_modules/mock-match-media": { "version": "0.4.2", @@ -36515,6 +37601,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", + "dev": true, "engines": { "node": ">=10" } @@ -36528,6 +37615,7 @@ "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, "dependencies": { "dns-packet": "^5.2.2", "thunky": "^1.0.2" @@ -36577,6 +37665,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.0.0.tgz", "integrity": "sha512-FJgjyX/IVkbXBXYUwH+OYwQKqWpFPLaLVESd70yHjSDunwzV2hZOoTBvPf4KLoxesUzzyfTH6F784Uqd7Wm5yA==", + "dev": true, "bin": { "mustache": "bin/mustache" }, @@ -36587,7 +37676,8 @@ "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true }, "node_modules/mv": { "version": "2.1.1", @@ -36705,7 +37795,8 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true }, "node_modules/ncp": { "version": "2.0.0", @@ -36733,6 +37824,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "dev": true, "engines": { "node": ">= 0.4.0" } @@ -36859,6 +37951,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, "engines": { "node": ">= 6.13.0" } @@ -37027,6 +38120,7 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -37037,12 +38131,14 @@ "node_modules/normalize-package-data/node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true }, "node_modules/normalize-package-data/node_modules/semver": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, "bin": { "semver": "bin/semver" } @@ -37059,6 +38155,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -37067,6 +38164,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, "engines": { "node": ">=10" }, @@ -37083,6 +38181,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "dev": true, "dependencies": { "npm-normalize-package-bin": "^1.0.1" } @@ -37102,12 +38201,14 @@ "node_modules/npm-normalize-package-bin": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true }, "node_modules/npm-package-arg": { "version": "8.1.5", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "dev": true, "dependencies": { "hosted-git-info": "^4.0.1", "semver": "^7.3.4", @@ -37121,6 +38222,7 @@ "version": "6.4.0", "resolved": "https://registry.npmjs.org/npm-package-json-lint/-/npm-package-json-lint-6.4.0.tgz", "integrity": "sha512-cuXAJJB1Rdqz0UO6w524matlBqDBjcNt7Ru+RDIu4y6RI1gVqiWBnylrK8sPRk81gGBA0X8hJbDXolVOoTc+sA==", + "dev": true, "dependencies": { "ajv": "^6.12.6", "ajv-errors": "^1.0.1", @@ -37152,6 +38254,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -37166,12 +38269,14 @@ "node_modules/npm-package-json-lint/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/npm-package-json-lint/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -37187,6 +38292,7 @@ "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -37212,6 +38318,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -37220,6 +38327,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -37231,12 +38339,14 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, "license": "MIT" }, "node_modules/npm-package-json-lint/node_modules/meow": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "dev": true, "dependencies": { "@types/minimist": "^1.2.0", "camelcase-keys": "^6.2.2", @@ -37262,6 +38372,7 @@ "version": "0.18.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, "engines": { "node": ">=10" }, @@ -37273,6 +38384,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, "dependencies": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", @@ -37287,6 +38399,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "engines": { "node": ">=8" } @@ -37295,6 +38408,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, "engines": { "node": ">=8" }, @@ -37306,6 +38420,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -37317,6 +38432,7 @@ "version": "3.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "dev": true, "engines": { "node": ">=14.16" }, @@ -37328,6 +38444,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "dev": true, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -37336,6 +38453,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-3.0.0.tgz", "integrity": "sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ==", + "dev": true, "dependencies": { "glob": "^7.1.6", "ignore-walk": "^4.0.1", @@ -37353,6 +38471,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -37700,7 +38819,8 @@ "node_modules/nwsapi": { "version": "2.2.13", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", - "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==" + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", + "dev": true }, "node_modules/nx": { "version": "16.6.0", @@ -38433,12 +39553,14 @@ "node_modules/object-filter": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/object-filter/-/object-filter-1.0.2.tgz", - "integrity": "sha512-NahvP2vZcy1ZiiYah30CEPw0FpDcSkSePJBMpzl5EQgCmISijiGuJm3SPYp7U+Lf2TljyaIw3E5EgkEx/TNEVA==" + "integrity": "sha512-NahvP2vZcy1ZiiYah30CEPw0FpDcSkSePJBMpzl5EQgCmISijiGuJm3SPYp7U+Lf2TljyaIw3E5EgkEx/TNEVA==", + "dev": true }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -38463,6 +39585,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, "engines": { "node": ">= 0.4" } @@ -38483,6 +39606,7 @@ "version": "4.1.4", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -38500,6 +39624,7 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -38513,6 +39638,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -38529,6 +39655,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.0.tgz", "integrity": "sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg==", + "dev": true, "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.19.1" @@ -38553,6 +39680,7 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -38574,7 +39702,8 @@ "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true }, "node_modules/octokit-pagination-methods": { "version": "1.1.0", @@ -38657,6 +39786,7 @@ "version": "1.5.2", "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, "bin": { "opener": "bin/opener-bin.js" } @@ -38665,6 +39795,7 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha512-oCOQ8AIC2ciLy/sE2ehafRBleBgDLvzGhBRRev87sP7ovnbvQfqpc3XFI0DhHey2OfVoNV91W+GPC6B3540/5Q==", + "dev": true, "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.4", @@ -38681,6 +39812,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/ora/-/ora-4.1.1.tgz", "integrity": "sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A==", + "dev": true, "dependencies": { "chalk": "^3.0.0", "cli-cursor": "^3.1.0", @@ -38702,6 +39834,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -38714,6 +39847,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, "dependencies": { "restore-cursor": "^3.1.0" }, @@ -38725,6 +39859,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -38733,6 +39868,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, "dependencies": { "chalk": "^2.4.2" }, @@ -38744,6 +39880,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -38755,6 +39892,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -38768,6 +39906,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, "engines": { "node": ">=4" } @@ -38776,6 +39915,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -38787,6 +39927,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, "engines": { "node": ">=6" } @@ -38795,6 +39936,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -38809,6 +39951,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -38821,6 +39964,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -38838,6 +39982,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -38859,6 +40004,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -38867,6 +40013,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, "engines": { "node": ">=8" } @@ -38898,6 +40045,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, "dependencies": { "p-limit": "^1.1.0" }, @@ -38909,6 +40057,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, "dependencies": { "p-try": "^1.0.0" }, @@ -38981,6 +40130,7 @@ "version": "4.6.1", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", + "dev": true, "dependencies": { "@types/retry": "^0.12.0", "retry": "^0.13.1" @@ -38993,6 +40143,7 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, "engines": { "node": ">= 4" } @@ -39013,6 +40164,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, "engines": { "node": ">=4" } @@ -39036,6 +40188,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", + "dev": true, "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.0.2", @@ -39054,6 +40207,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, "dependencies": { "debug": "^4.3.4" }, @@ -39065,6 +40219,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -39077,6 +40232,7 @@ "version": "7.0.5", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -39090,6 +40246,7 @@ "version": "8.0.4", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.1", @@ -39104,6 +40261,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", + "dev": true, "dependencies": { "degenerator": "^5.0.0", "ip": "^1.1.8", @@ -39477,12 +40635,14 @@ "node_modules/parse-cache-control": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", - "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==" + "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", + "dev": true }, "node_modules/parse-entities": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", + "dev": true, "dependencies": { "character-entities": "^1.0.0", "character-entities-legacy": "^1.0.0", @@ -39522,6 +40682,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -39548,6 +40709,7 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, "dependencies": { "entities": "^4.4.0" }, @@ -39559,6 +40721,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, "engines": { "node": ">=0.12" }, @@ -39830,9 +40993,9 @@ } }, "node_modules/patch-package/node_modules/yaml": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", - "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "dev": true, "license": "ISC", "bin": { @@ -39883,7 +41046,8 @@ "node_modules/path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==" + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "dev": true }, "node_modules/path-key": { "version": "2.0.1", @@ -39936,7 +41100,8 @@ "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true }, "node_modules/path-type": { "version": "3.0.0", @@ -40006,7 +41171,8 @@ "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true }, "node_modules/phpegjs": { "version": "1.0.0-beta7", @@ -40049,6 +41215,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -40057,6 +41224,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -40065,6 +41233,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, "dependencies": { "pinkie": "^2.0.0" }, @@ -40084,6 +41253,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", "integrity": "sha512-ojakdnUgL5pzJYWw2AIDEupaQCX5OPbM688ZevubICjdIX01PRSYKqm33fJoCOJBRseYCTUlQRnBNX+Pchaejw==", + "dev": true, "dependencies": { "find-up": "^2.1.0" }, @@ -40154,6 +41324,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz", "integrity": "sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==", + "dev": true, "dependencies": { "irregular-plurals": "^3.2.0" }, @@ -40226,6 +41397,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", + "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.11", "postcss-value-parser": "^4.2.0" @@ -40240,12 +41412,14 @@ "node_modules/postcss-calc/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-colormin": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.0.0.tgz", "integrity": "sha512-EuO+bAUmutWoZYgHn2T1dG1pPqHU6L4TjzPlu4t1wZGXQ/fxV16xg2EJmYi0z+6r+MGV1yvpx1BHkUaRrPa2bw==", + "dev": true, "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0", @@ -40262,12 +41436,14 @@ "node_modules/postcss-colormin/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-convert-values": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.0.0.tgz", "integrity": "sha512-U5D8QhVwqT++ecmy8rnTb+RL9n/B806UVaS3m60lqle4YDFcpbS3ae5bTQIh3wOGUSDHSEtMYLs/38dNG7EYFw==", + "dev": true, "dependencies": { "browserslist": "^4.21.4", "postcss-value-parser": "^4.2.0" @@ -40282,12 +41458,14 @@ "node_modules/postcss-convert-values/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-discard-comments": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.0.tgz", "integrity": "sha512-p2skSGqzPMZkEQvJsgnkBhCn8gI7NzRH2683EEjrIkoMiwRELx68yoUJ3q3DGSGuQ8Ug9Gsn+OuDr46yfO+eFw==", + "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -40299,6 +41477,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.0.tgz", "integrity": "sha512-bU1SXIizMLtDW4oSsi5C/xHKbhLlhek/0/yCnoMQany9k3nPBq+Ctsv/9oMmyqbR96HYHxZcHyK2HR5P/mqoGA==", + "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -40310,6 +41489,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.0.tgz", "integrity": "sha512-b+h1S1VT6dNhpcg+LpyiUrdnEZfICF0my7HAKgJixJLW7BnNmpRH34+uw/etf5AhOlIhIAuXApSzzDzMI9K/gQ==", + "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -40321,6 +41501,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.0.tgz", "integrity": "sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw==", + "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -40332,6 +41513,7 @@ "version": "16.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz", "integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==", + "dev": true, "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -40347,12 +41529,14 @@ "node_modules/postcss-import/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-loader": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "dev": true, "dependencies": { "cosmiconfig": "^7.0.0", "klona": "^2.0.5", @@ -40385,12 +41569,14 @@ "node_modules/postcss-media-query-parser": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==" + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true }, "node_modules/postcss-merge-longhand": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.0.tgz", "integrity": "sha512-4VSfd1lvGkLTLYcxFuISDtWUfFS4zXe0FpF149AyziftPFQIWxjvFSKhA4MIxMe4XM3yTDgQMbSNgzIVxChbIg==", + "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0", "stylehacks": "^6.0.0" @@ -40405,12 +41591,14 @@ "node_modules/postcss-merge-longhand/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-merge-rules": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.0.1.tgz", "integrity": "sha512-a4tlmJIQo9SCjcfiCcCMg/ZCEe0XTkl/xK0XHBs955GWg9xDX3NwP9pwZ78QUOWB8/0XCjZeJn98Dae0zg6AAw==", + "dev": true, "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0", @@ -40428,6 +41616,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.0.0.tgz", "integrity": "sha512-zNRAVtyh5E8ndZEYXA4WS8ZYsAp798HiIQ1V2UF/C/munLp2r1UGHwf1+6JFu7hdEhJFN+W1WJQKBrtjhFgEnA==", + "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -40441,12 +41630,14 @@ "node_modules/postcss-minify-font-values/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-minify-gradients": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.0.tgz", "integrity": "sha512-wO0F6YfVAR+K1xVxF53ueZJza3L+R3E6cp0VwuXJQejnNUH0DjcAFe3JEBeTY1dLwGa0NlDWueCA1VlEfiKgAA==", + "dev": true, "dependencies": { "colord": "^2.9.1", "cssnano-utils": "^4.0.0", @@ -40462,12 +41653,14 @@ "node_modules/postcss-minify-gradients/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-minify-params": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.0.0.tgz", "integrity": "sha512-Fz/wMQDveiS0n5JPcvsMeyNXOIMrwF88n7196puSuQSWSa+/Ofc1gDOSY2xi8+A4PqB5dlYCKk/WfqKqsI+ReQ==", + "dev": true, "dependencies": { "browserslist": "^4.21.4", "cssnano-utils": "^4.0.0", @@ -40483,12 +41676,14 @@ "node_modules/postcss-minify-params/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-minify-selectors": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.0.tgz", "integrity": "sha512-ec/q9JNCOC2CRDNnypipGfOhbYPuUkewGwLnbv6omue/PSASbHSU7s6uSQ0tcFRVv731oMIx8k0SP4ZX6be/0g==", + "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.5" }, @@ -40503,6 +41698,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, "engines": { "node": "^10 || ^12 || >= 14" }, @@ -40514,6 +41710,7 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "dev": true, "dependencies": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^6.0.2", @@ -40529,12 +41726,14 @@ "node_modules/postcss-modules-local-by-default/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-modules-scope": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.4" }, @@ -40549,6 +41748,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, "dependencies": { "icss-utils": "^5.0.0" }, @@ -40563,6 +41763,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.0.tgz", "integrity": "sha512-cqundwChbu8yO/gSWkuFDmKrCZ2vJzDAocheT2JTd0sFNA4HMGoKMfbk2B+J0OmO0t5GUkiAkSM5yF2rSLUjgQ==", + "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -40574,6 +41775,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.0.tgz", "integrity": "sha512-Qyt5kMrvy7dJRO3OjF7zkotGfuYALETZE+4lk66sziWSPzlBEt7FrUshV6VLECkI4EN8Z863O6Nci4NXQGNzYw==", + "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -40587,12 +41789,14 @@ "node_modules/postcss-normalize-display-values/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-normalize-positions": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.0.tgz", "integrity": "sha512-mPCzhSV8+30FZyWhxi6UoVRYd3ZBJgTRly4hOkaSifo0H+pjDYcii/aVT4YE6QpOil15a5uiv6ftnY3rm0igPg==", + "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -40606,12 +41810,14 @@ "node_modules/postcss-normalize-positions/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-normalize-repeat-style": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.0.tgz", "integrity": "sha512-50W5JWEBiOOAez2AKBh4kRFm2uhrT3O1Uwdxz7k24aKtbD83vqmcVG7zoIwo6xI2FZ/HDlbrCopXhLeTpQib1A==", + "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -40625,12 +41831,14 @@ "node_modules/postcss-normalize-repeat-style/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-normalize-string": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.0.tgz", "integrity": "sha512-KWkIB7TrPOiqb8ZZz6homet2KWKJwIlysF5ICPZrXAylGe2hzX/HSf4NTX2rRPJMAtlRsj/yfkrWGavFuB+c0w==", + "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -40644,12 +41852,14 @@ "node_modules/postcss-normalize-string/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-normalize-timing-functions": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.0.tgz", "integrity": "sha512-tpIXWciXBp5CiFs8sem90IWlw76FV4oi6QEWfQwyeREVwUy39VSeSqjAT7X0Qw650yAimYW5gkl2Gd871N5SQg==", + "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -40663,12 +41873,14 @@ "node_modules/postcss-normalize-timing-functions/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-normalize-unicode": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.0.tgz", "integrity": "sha512-ui5crYkb5ubEUDugDc786L/Me+DXp2dLg3fVJbqyAl0VPkAeALyAijF2zOsnZyaS1HyfPuMH0DwyY18VMFVNkg==", + "dev": true, "dependencies": { "browserslist": "^4.21.4", "postcss-value-parser": "^4.2.0" @@ -40683,12 +41895,14 @@ "node_modules/postcss-normalize-unicode/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-normalize-url": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.0.tgz", "integrity": "sha512-98mvh2QzIPbb02YDIrYvAg4OUzGH7s1ZgHlD3fIdTHLgPLRpv1ZTKJDnSAKr4Rt21ZQFzwhGMXxpXlfrUBKFHw==", + "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -40702,12 +41916,14 @@ "node_modules/postcss-normalize-url/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-normalize-whitespace": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.0.tgz", "integrity": "sha512-7cfE1AyLiK0+ZBG6FmLziJzqQCpTQY+8XjMhMAz8WSBSCsCNNUKujgIgjCAmDT3cJ+3zjTXFkoD15ZPsckArVw==", + "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -40721,12 +41937,14 @@ "node_modules/postcss-normalize-whitespace/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-ordered-values": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.0.tgz", "integrity": "sha512-K36XzUDpvfG/nWkjs6d1hRBydeIxGpKS2+n+ywlKPzx1nMYDYpoGbcjhj5AwVYJK1qV2/SDoDEnHzlPD6s3nMg==", + "dev": true, "dependencies": { "cssnano-utils": "^4.0.0", "postcss-value-parser": "^4.2.0" @@ -40741,7 +41959,8 @@ "node_modules/postcss-ordered-values/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-prefix-selector": { "version": "1.16.1", @@ -40756,6 +41975,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz", "integrity": "sha512-s2UOnidpVuXu6JiiI5U+fV2jamAw5YNA9Fdi/GRK0zLDLCfXmSGqQtzpUPtfN66RtCbb9fFHoyZdQaxOB3WxVA==", + "dev": true, "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0" @@ -40771,6 +41991,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.0.tgz", "integrity": "sha512-FQ9f6xM1homnuy1wLe9lP1wujzxnwt1EwiigtWwuyf8FsqqXUDUp2Ulxf9A5yjlUOTdCJO6lonYjg1mgqIIi2w==", + "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -40784,17 +42005,20 @@ "node_modules/postcss-reduce-transforms/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-resolve-nested-selector": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", - "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==" + "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", + "dev": true }, "node_modules/postcss-safe-parser": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.0.tgz", "integrity": "sha512-ovehqRNVCpuFzbXoTb4qLtyzK3xn3t/CUBxOs8LsnQjQrShaB4lKiHoVqY8ANaC0hBMHq5QVWk77rwGklFUDrg==", + "dev": true, "funding": [ { "type": "opencollective", @@ -40820,6 +42044,7 @@ "version": "4.0.9", "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", + "dev": true, "funding": [ { "type": "opencollective", @@ -40845,6 +42070,7 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -40857,6 +42083,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.0.tgz", "integrity": "sha512-r9zvj/wGAoAIodn84dR/kFqwhINp5YsJkLoujybWG59grR/IHx+uQ2Zo+IcOwM0jskfYX3R0mo+1Kip1VSNcvw==", + "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0", "svgo": "^3.0.2" @@ -40871,12 +42098,14 @@ "node_modules/postcss-svgo/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/postcss-unique-selectors": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.0.tgz", "integrity": "sha512-EPQzpZNxOxP7777t73RQpZE5e9TrnCrkvp7AH7a0l89JmZiPnS82y216JowHXwpBCQitfyxrof9TK3rYbi7/Yw==", + "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.5" }, @@ -40954,6 +42183,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, "engines": { "node": ">= 0.8.0" } @@ -40963,6 +42193,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/wp-prettier/-/wp-prettier-3.0.3.tgz", "integrity": "sha512-X4UlrxDTH8oom9qXlcjnydsjAOD2BmB6yFmvS4Z2zdTzqqpRWb+fbqrH412+l+OUXmbzJlSXjlMFYPgYG12IAA==", + "dev": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -40977,6 +42208,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, "dependencies": { "fast-diff": "^1.1.2" }, @@ -41059,6 +42291,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, "engines": { "node": ">=0.4.0" } @@ -41143,6 +42376,7 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -41155,6 +42389,7 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.0.tgz", "integrity": "sha512-0LdR757eTj/JfuU7TL2YCuAZnxWXu3tkJbg4Oq3geW/qFNT/32T0sp2HnZ9O0lMR4q3vwAt0+xCA8SR0WAD0og==", + "dev": true, "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", @@ -41173,6 +42408,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, "dependencies": { "debug": "^4.3.4" }, @@ -41184,6 +42420,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -41196,6 +42433,7 @@ "version": "7.0.5", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -41209,6 +42447,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -41217,6 +42456,7 @@ "version": "8.0.4", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.1", @@ -41230,7 +42470,8 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true }, "node_modules/prr": { "version": "1.0.1", @@ -41242,6 +42483,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/ps-list/-/ps-list-8.1.1.tgz", "integrity": "sha512-OPS9kEJYVmiO48u/B9qneqhkMvgCxT+Tm28VCEJpheTpl8cJ0ffZRRNgS5mrQRTrX5yRTpaJ+hRDeefXYmmorQ==", + "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -41252,7 +42494,8 @@ "node_modules/pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true }, "node_modules/public-encrypt": { "version": "4.0.3", @@ -41307,6 +42550,7 @@ "version": "23.1.0", "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.1.0.tgz", "integrity": "sha512-SvAsu+xnLN2FMXE/59bp3s3WXp8ewqUGzVV4AQtml/2xmsciZnU/bXcCW+eETHPWQ6Agg2vTI7QzWXPpEARK2g==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@puppeteer/browsers": "2.3.1", @@ -41324,6 +42568,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.1.tgz", "integrity": "sha512-uK7o3hHkK+naEobMSJ+2ySYyXtQkBxIH8Gn4MK9ciePjNV+Pf+PgY/W7iPzn2MTjl3stcYB5AlcTmPYw7AXDwA==", + "dev": true, "license": "Apache-2.0", "dependencies": { "debug": "^4.3.6", @@ -41346,6 +42591,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, "license": "MIT", "dependencies": { "debug": "^4.3.4" @@ -41358,6 +42604,7 @@ "version": "0.6.4", "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.4.tgz", "integrity": "sha512-8zoq6ogmhQQkAKZVKO2ObFTl4uOkqoX1PlKQX3hZQ5E9cbUotcAb7h4pTNVAGGv8Z36PF3CtdOriEp/Rz82JqQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { "mitt": "3.0.1", @@ -41372,6 +42619,7 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -41386,6 +42634,7 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -41403,12 +42652,14 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, "license": "MIT" }, "node_modules/puppeteer-core/node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "debug": "^4.1.1", @@ -41429,6 +42680,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.0", @@ -41442,6 +42694,7 @@ "version": "7.0.5", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -41455,6 +42708,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -41464,6 +42718,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -41473,18 +42728,21 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true, "license": "MIT" }, "node_modules/puppeteer-core/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, "node_modules/puppeteer-core/node_modules/proxy-agent": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", + "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -41504,6 +42762,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -41514,6 +42773,7 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -41526,6 +42786,7 @@ "version": "8.0.4", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.1", @@ -41540,6 +42801,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -41554,6 +42816,7 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", + "dev": true, "license": "MIT", "dependencies": { "pump": "^3.0.0", @@ -41568,6 +42831,7 @@ "version": "3.1.7", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, "license": "MIT", "dependencies": { "b4a": "^1.6.4", @@ -41579,6 +42843,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -41596,6 +42861,7 @@ "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -41617,6 +42883,7 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -41626,6 +42893,7 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, "license": "MIT", "dependencies": { "cliui": "^8.0.1", @@ -41644,6 +42912,7 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -41653,6 +42922,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", + "dev": true, "funding": [ { "type": "individual", @@ -41668,6 +42938,7 @@ "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, "dependencies": { "side-channel": "^1.0.4" }, @@ -41749,12 +43020,14 @@ "node_modules/queue-tick": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", + "dev": true }, "node_modules/quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, "engines": { "node": ">=8" } @@ -41799,6 +43072,7 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dev": true, "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -41813,6 +43087,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -41821,6 +43096,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -42606,6 +43882,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, "dependencies": { "pify": "^2.3.0" } @@ -42795,6 +44072,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", @@ -42809,6 +44087,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, "dependencies": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", @@ -42825,6 +44104,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -42837,6 +44117,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -42848,6 +44129,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -42862,6 +44144,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -42873,6 +44156,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, "engines": { "node": ">=6" } @@ -42881,6 +44165,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "engines": { "node": ">=8" } @@ -42889,6 +44174,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, "engines": { "node": ">=8" } @@ -42950,6 +44236,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -43002,6 +44289,7 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, "dependencies": { "resolve": "^1.20.0" }, @@ -43013,6 +44301,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" @@ -43025,6 +44314,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, "engines": { "node": ">=8" } @@ -43064,6 +44354,7 @@ "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, "dependencies": { "@babel/runtime": "^7.8.4" } @@ -43085,6 +44376,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -43101,6 +44393,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, "engines": { "node": ">=8" }, @@ -43156,6 +44449,7 @@ "version": "10.0.1", "resolved": "https://registry.npmjs.org/remark/-/remark-10.0.1.tgz", "integrity": "sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ==", + "dev": true, "dependencies": { "remark-parse": "^6.0.0", "remark-stringify": "^6.0.0", @@ -43222,6 +44516,7 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-6.0.3.tgz", "integrity": "sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg==", + "dev": true, "dependencies": { "collapse-white-space": "^1.0.2", "is-alphabetical": "^1.0.0", @@ -43298,6 +44593,7 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-6.0.4.tgz", "integrity": "sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg==", + "dev": true, "dependencies": { "ccount": "^1.0.0", "is-alphanumeric": "^1.0.0", @@ -43438,6 +44734,7 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true, "engines": { "node": ">=0.10" } @@ -43446,6 +44743,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", "integrity": "sha512-vuNYXC7gG7IeVNBC1xUllqCcZKRbJoSPOBhnTEcAIiKCsbuef6zO3F0Rve3isPMMoNoQRWjQwbAgAjHUHniyEA==", + "dev": true, "engines": { "node": ">= 0.10" } @@ -43467,6 +44765,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -43480,6 +44779,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true, "engines": { "node": ">=0.10.5" } @@ -43487,7 +44787,8 @@ "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true }, "node_modules/resize-observer-polyfill": { "version": "1.5.1", @@ -43514,12 +44815,14 @@ "node_modules/resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true }, "node_modules/resolve-bin": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/resolve-bin/-/resolve-bin-0.4.0.tgz", "integrity": "sha1-RxMiSYkRAa+xmZH+k3ywpfBy5dk=", + "dev": true, "dependencies": { "find-parent-dir": "~0.3.0" } @@ -43528,6 +44831,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, "dependencies": { "resolve-from": "^5.0.0" }, @@ -43539,6 +44843,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, "engines": { "node": ">=8" } @@ -43547,6 +44852,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", "integrity": "sha512-QxMPqI6le2u0dCLyiGzgy92kjkkL6zO0XyvHzjdTNH3zM6e5Hz3BwG6+aEyNgiQ5Xz6PwTwgQEj3U50dByPKIA==", + "dev": true, "dependencies": { "expand-tilde": "^1.2.2", "global-modules": "^0.2.3" @@ -43559,6 +44865,7 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", "integrity": "sha512-JeXuCbvYzYXcwE6acL9V2bAOeSIGl4dD+iwLY9iUx2VBJJ80R18HCn+JCwHM9Oegdfya3lEkGCdaRkSyc10hDA==", + "dev": true, "dependencies": { "global-prefix": "^0.1.4", "is-windows": "^0.2.0" @@ -43571,6 +44878,7 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", "integrity": "sha512-gOPiyxcD9dJGCEArAhF4Hd0BAqvAe/JzERP7tYumE4yIkmIedPUVXcJFWbV3/p/ovIIvKjkrTk+f1UVkq7vvbw==", + "dev": true, "dependencies": { "homedir-polyfill": "^1.0.0", "ini": "^1.3.4", @@ -43585,6 +44893,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", "integrity": "sha512-n67eJYmXbniZB7RF4I/FTjK1s6RPOCTxhYrVYLRaCt3lF0mpWZPKr3T2LSZAqyjQsxR2qMmGYXXzK0YWwcPM1Q==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -43607,6 +44916,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, "engines": { "node": ">=10" } @@ -43615,6 +44925,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, "dependencies": { "lowercase-keys": "^2.0.0" }, @@ -43672,6 +44983,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -43730,6 +45042,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/robots-parser/-/robots-parser-3.0.1.tgz", "integrity": "sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ==", + "dev": true, "engines": { "node": ">=10.0.0" } @@ -43737,7 +45050,8 @@ "node_modules/rrweb-cssom": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", - "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==" + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true }, "node_modules/rtlcss": { "version": "4.0.0", @@ -43761,6 +45075,7 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/rtlcss-webpack-plugin/-/rtlcss-webpack-plugin-4.0.7.tgz", "integrity": "sha512-ouSbJtgcLBBQIsMgarxsDnfgRqm/AS4BKls/mz/Xb6HSl+PdEzefTR+Wz5uWQx4odoX0g261Z7yb3QBz0MTm0g==", + "dev": true, "dependencies": { "babel-runtime": "~6.25.0", "rtlcss": "^3.5.0" @@ -43770,6 +45085,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -43785,6 +45101,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -43799,6 +45116,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -43813,6 +45131,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "engines": { "node": ">=8" } @@ -43821,6 +45140,7 @@ "version": "3.5.0", "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz", "integrity": "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==", + "dev": true, "dependencies": { "find-up": "^5.0.0", "picocolors": "^1.0.0", @@ -43835,6 +45155,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, "engines": { "node": ">=8" }, @@ -43858,6 +45179,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, "dependencies": { "execa": "^5.0.0" }, @@ -43872,6 +45194,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -43885,6 +45208,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -43907,6 +45231,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, "engines": { "node": ">=10" }, @@ -43918,6 +45243,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, "engines": { "node": ">=10.17.0" } @@ -43926,6 +45252,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, "engines": { "node": ">=8" }, @@ -43937,6 +45264,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, "engines": { "node": ">=6" } @@ -43945,6 +45273,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -43956,6 +45285,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -43970,6 +45300,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -43978,6 +45309,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -43989,6 +45321,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } @@ -43997,6 +45330,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -44011,6 +45345,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, "engines": { "node": ">=0.12.0" } @@ -44019,6 +45354,7 @@ "version": "1.2.10", "resolved": "https://registry.npmjs.org/run-con/-/run-con-1.2.10.tgz", "integrity": "sha512-n7PZpYmMM26ZO21dd8y3Yw1TRtGABjRtgPSgFS/nhzfvbJMXFtJhJVyEgayMiP+w/23craJjsnfDvx4W4ue/HQ==", + "dev": true, "dependencies": { "deep-extend": "^0.6.0", "ini": "~2.0.0", @@ -44033,6 +45369,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, "engines": { "node": ">=10" } @@ -44041,6 +45378,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, "engines": { "node": ">=8" }, @@ -44063,7 +45401,8 @@ "node_modules/run-parallel": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", + "dev": true }, "node_modules/run-queue": { "version": "1.0.3", @@ -44089,6 +45428,7 @@ "version": "6.6.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, "dependencies": { "tslib": "^1.9.0" }, @@ -44099,7 +45439,8 @@ "node_modules/rxjs/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, "node_modules/safaridriver": { "version": "0.1.0", @@ -44111,6 +45452,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.0", @@ -44127,7 +45469,8 @@ "node_modules/safe-array-concat/node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true }, "node_modules/safe-buffer": { "version": "5.1.2", @@ -44147,6 +45490,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.3", @@ -44183,6 +45527,7 @@ "version": "1.35.2", "resolved": "https://registry.npmjs.org/sass/-/sass-1.35.2.tgz", "integrity": "sha512-jhO5KAR+AMxCEwIH3v+4zbB2WB0z67V1X0jbapfVwQQdjHZUGUyukpnoM6+iCMfsIUC016w9OPKQ5jrNOS9uXw==", + "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0" }, @@ -44197,6 +45542,7 @@ "version": "12.1.0", "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.1.0.tgz", "integrity": "sha512-FVJZ9kxVRYNZTIe2xhw93n3xJNYZADr+q69/s98l9nTCrWASo+DR2Ot0s5xTKQDDEosUkatsGeHxcH4QBp5bSg==", + "dev": true, "dependencies": { "klona": "^2.0.4", "neo-async": "^2.6.2" @@ -44230,6 +45576,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, "dependencies": { "xmlchars": "^2.2.0" }, @@ -44289,12 +45636,14 @@ "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true }, "node_modules/selfsigned": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "dev": true, "dependencies": { "node-forge": "^1" }, @@ -44476,6 +45825,7 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, "dependencies": { "accepts": "~1.3.4", "batch": "0.6.1", @@ -44493,6 +45843,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { "ms": "2.0.0" } @@ -44501,6 +45852,7 @@ "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -44514,7 +45866,8 @@ "node_modules/serve-index/node_modules/setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true }, "node_modules/serve-static": { "version": "1.15.0", @@ -44539,6 +45892,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -44699,6 +46053,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, "dependencies": { "shebang-regex": "^1.0.0" }, @@ -44710,6 +46065,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -44905,6 +46261,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -44992,6 +46349,7 @@ "version": "3.24.0", "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.24.0.tgz", "integrity": "sha512-QqAKee9Twv+3k8IFOFfPB2hnk6as6Y6ACUpwCtQvRYBAes23Wv3SZlHVobAzqcE8gfsisCvPw3HGW3HYM+VYYw==", + "dev": true, "dependencies": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", @@ -45093,6 +46451,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", "integrity": "sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==", + "dev": true, "dependencies": { "@polka/url": "^1.0.0-next.20", "mrmime": "^1.0.0", @@ -45128,6 +46487,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -45287,6 +46647,7 @@ "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, "dependencies": { "faye-websocket": "^0.11.3", "uuid": "^8.3.2", @@ -45297,6 +46658,7 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -45305,6 +46667,7 @@ "version": "2.8.3", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dev": true, "license": "MIT", "dependencies": { "ip-address": "^9.0.5", @@ -45333,6 +46696,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==", + "dev": true, "dependencies": { "is-plain-obj": "^1.0.0" }, @@ -45344,6 +46708,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -45366,6 +46731,7 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -45374,6 +46740,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.0.tgz", "integrity": "sha512-GKGWqWvYr04M7tn8dryIWvb0s8YM41z82iQv01yBtIylgxax0CwvSy6gc2Y02iuXwEfGWRlMicH0nvms9UZphw==", + "dev": true, "dependencies": { "abab": "^2.0.5", "iconv-lite": "^0.6.2", @@ -45438,6 +46805,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -45446,12 +46814,14 @@ "node_modules/spdx-exceptions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -45460,12 +46830,14 @@ "node_modules/spdx-license-ids": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "dev": true }, "node_modules/spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, "dependencies": { "debug": "^4.1.0", "handle-thing": "^2.0.0", @@ -45481,6 +46853,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, "dependencies": { "debug": "^4.1.0", "detect-node": "^2.0.4", @@ -45494,6 +46867,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -45516,6 +46890,7 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/speedline-core/-/speedline-core-1.4.3.tgz", "integrity": "sha512-DI7/OuAUD+GMpR6dmu8lliO2Wg5zfeh+/xsdyJZCzd8o5JgFUjCeLsBDuZjIQJdwXS3J0L/uZYrELKYqx+PXog==", + "dev": true, "dependencies": { "@types/node": "*", "image-ssim": "^0.2.0", @@ -45649,7 +47024,8 @@ "node_modules/state-toggle": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", - "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==" + "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==", + "dev": true }, "node_modules/static-extend": { "version": "0.1.2", @@ -45804,6 +47180,7 @@ "version": "2.15.1", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.1.tgz", "integrity": "sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==", + "dev": true, "dependencies": { "fast-fifo": "^1.1.0", "queue-tick": "^1.0.1" @@ -45838,6 +47215,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -45914,6 +47292,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -45949,6 +47328,7 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -45965,6 +47345,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -45978,6 +47359,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -45991,6 +47373,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", + "dev": true, "dependencies": { "character-entities-html4": "^1.0.0", "character-entities-legacy": "^1.0.0", @@ -46040,6 +47423,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, "engines": { "node": ">=8" } @@ -46065,6 +47449,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, "dependencies": { "min-indent": "^1.0.0" }, @@ -46088,6 +47473,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -46136,12 +47522,14 @@ "node_modules/style-search": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", - "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==" + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", + "dev": true }, "node_modules/stylehacks": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.0.0.tgz", "integrity": "sha512-+UT589qhHPwz6mTlCLSt/vMNTJx8dopeJlZAlBMJPWA3ORqu6wmQY7FBXf+qD+FsqoBJODyqNxOUP3jdntFRdw==", + "dev": true, "dependencies": { "browserslist": "^4.21.4", "postcss-selector-parser": "^6.0.4" @@ -46157,6 +47545,7 @@ "version": "16.8.2", "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.8.2.tgz", "integrity": "sha512-fInKATippQhcSm7AB+T32GpI+626yohrg33GkFT/5jzliUw5qhlwZq2UQQwgl3HsHrf09oeARi0ZwgY/UWEv9A==", + "dev": true, "funding": [ { "type": "opencollective", @@ -46218,17 +47607,20 @@ "node_modules/stylelint/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/stylelint/node_modules/balanced-match": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", - "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==" + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true }, "node_modules/stylelint/node_modules/cosmiconfig": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", @@ -46254,6 +47646,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -46266,6 +47659,7 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -46282,12 +47676,14 @@ "node_modules/stylelint/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/stylelint/node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -46303,6 +47699,7 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", + "dev": true, "license": "MIT", "dependencies": { "flat-cache": "^5.0.0" @@ -46315,6 +47712,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", + "dev": true, "dependencies": { "flatted": "^3.3.1", "keyv": "^4.5.4" @@ -46327,6 +47725,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -46338,6 +47737,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -46346,6 +47746,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, "engines": { "node": ">= 4" } @@ -46354,6 +47755,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -46362,6 +47764,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -46372,12 +47775,14 @@ "node_modules/stylelint/node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true }, "node_modules/stylelint/node_modules/meow": { "version": "13.2.0", "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "dev": true, "engines": { "node": ">=18" }, @@ -46389,12 +47794,14 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, "node_modules/stylelint/node_modules/postcss": { "version": "8.4.47", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -46422,12 +47829,14 @@ "node_modules/stylelint/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/stylelint/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, "engines": { "node": ">=8" } @@ -46436,6 +47845,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, "engines": { "node": ">=14" }, @@ -46447,6 +47857,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -46456,6 +47867,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -46469,6 +47881,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -46480,6 +47893,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -46494,6 +47908,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -46506,6 +47921,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -46517,6 +47933,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz", "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==", + "dev": true, "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" @@ -46532,6 +47949,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^4.0.1" @@ -46565,6 +47983,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0", @@ -46578,6 +47997,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -46586,6 +48006,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -46607,17 +48028,20 @@ "node_modules/svg-parser": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true }, "node_modules/svg-tags": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==" + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true }, "node_modules/svgo": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.2.tgz", "integrity": "sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ==", + "dev": true, "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", @@ -46641,6 +48065,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, "engines": { "node": ">= 10" } @@ -46649,6 +48074,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -46660,12 +48086,14 @@ "node_modules/svgo/node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true }, "node_modules/svgo/node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -46696,7 +48124,8 @@ "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true }, "node_modules/synchronous-promise": { "version": "2.0.17", @@ -46708,6 +48137,7 @@ "version": "0.8.5", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "dev": true, "dependencies": { "@pkgr/utils": "^2.3.1", "tslib": "^2.5.0" @@ -46723,6 +48153,7 @@ "version": "6.8.2", "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", + "dev": true, "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", @@ -46738,6 +48169,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, "engines": { "node": ">=8" } @@ -46745,12 +48177,14 @@ "node_modules/table/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/table/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -46759,6 +48193,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -46775,6 +48210,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -47095,6 +48531,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.0.0.tgz", "integrity": "sha512-rdBAY35jUvVapqCuhehjenLbYY73cVgRQ6podD6u9EDBomBBHjCOtmq2InPgPpTysOIOsQ5PdBzwSC/sKjv6ew==", + "dev": true, "dependencies": { "ansi-escapes": "^4.2.1", "supports-hyperlinks": "^2.0.0" @@ -47124,6 +48561,7 @@ "version": "5.3.10", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", @@ -47157,6 +48595,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -47172,6 +48611,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -47180,6 +48620,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -47193,6 +48634,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -47210,6 +48652,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -47218,6 +48661,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -47229,9 +48673,9 @@ } }, "node_modules/terser/node_modules/acorn": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", - "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -47249,6 +48693,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -47262,6 +48707,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -47295,12 +48741,14 @@ "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true }, "node_modules/third-party-web": { "version": "0.23.4", "resolved": "https://registry.npmjs.org/third-party-web/-/third-party-web-0.23.4.tgz", - "integrity": "sha512-kwYnSZRhEvv0SBW2fp8SBBKRglMoBjV8xz6C31m0ewqOtknB5UL+Ihg+M81hyFY5ldkZuGWPb+e4GVDkzf/gYg==" + "integrity": "sha512-kwYnSZRhEvv0SBW2fp8SBBKRglMoBjV8xz6C31m0ewqOtknB5UL+Ihg+M81hyFY5ldkZuGWPb+e4GVDkzf/gYg==", + "dev": true }, "node_modules/throat": { "version": "5.0.0", @@ -47310,7 +48758,8 @@ "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true }, "node_modules/through2": { "version": "2.0.5", @@ -47324,7 +48773,8 @@ "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true }, "node_modules/timers-browserify": { "version": "2.0.12", @@ -47353,6 +48803,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "dev": true, "engines": { "node": ">=12" }, @@ -47364,6 +48815,7 @@ "version": "6.1.50", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.50.tgz", "integrity": "sha512-q9GOap6q3KCsLMdOjXhWU5jVZ8/1dIib898JBRLsN+tBhENpBDcAVQbE0epADOjw11FhQQy9AcbqKGBQPUfTQA==", + "dev": true, "dependencies": { "tldts-core": "^6.1.50" }, @@ -47374,12 +48826,14 @@ "node_modules/tldts-core": { "version": "6.1.50", "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.50.tgz", - "integrity": "sha512-na2EcZqmdA2iV9zHV7OHQDxxdciEpxrjbkp+aHmZgnZKHzoElLajP59np5/4+sare9fQBfixgvXKx8ev1d7ytw==" + "integrity": "sha512-na2EcZqmdA2iV9zHV7OHQDxxdciEpxrjbkp+aHmZgnZKHzoElLajP59np5/4+sare9fQBfixgvXKx8ev1d7ytw==", + "dev": true }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -47476,6 +48930,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, "engines": { "node": ">=6" } @@ -47484,6 +48939,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "dev": true, "dependencies": { "tldts": "^6.1.32" }, @@ -47500,6 +48956,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, "bin": { "tree-kill": "cli.js" } @@ -47508,12 +48965,14 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==", - "deprecated": "Use String.prototype.trim() instead" + "deprecated": "Use String.prototype.trim() instead", + "dev": true }, "node_modules/trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, "engines": { "node": ">=8" } @@ -47522,6 +48981,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "dev": true, "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -47532,7 +48992,8 @@ "node_modules/trim-trailing-lines": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", - "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==" + "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==", + "dev": true }, "node_modules/triple-beam": { "version": "1.4.1", @@ -47546,7 +49007,8 @@ "node_modules/trough": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz", - "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==" + "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==", + "dev": true }, "node_modules/truncate-utf8-bytes": { "version": "1.0.2", @@ -47561,6 +49023,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.2.tgz", "integrity": "sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==", + "dev": true, "engines": { "node": ">=16.13.0" }, @@ -47607,6 +49070,7 @@ "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -47618,6 +49082,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, "dependencies": { "minimist": "^1.2.0" }, @@ -47629,20 +49094,22 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, "engines": { "node": ">=4" } }, "node_modules/tslib": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", - "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "license": "0BSD" }, "node_modules/tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, "dependencies": { "tslib": "^1.8.1" }, @@ -47656,7 +49123,8 @@ "node_modules/tsutils/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, "node_modules/tty-browserify": { "version": "0.0.0", @@ -47682,6 +49150,7 @@ "version": "0.0.6", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, "engines": { "node": ">=0.6.11 <=0.7.0 || >=0.7.3" } @@ -47703,6 +49172,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, "dependencies": { "prelude-ls": "~1.1.2" }, @@ -47722,6 +49192,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, "engines": { "node": ">=8" } @@ -47730,6 +49201,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -47742,6 +49214,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1", @@ -47755,6 +49228,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "for-each": "^0.3.3", @@ -47772,6 +49246,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", @@ -47790,6 +49265,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "for-each": "^0.3.3", @@ -47811,17 +49287,20 @@ "node_modules/typed-query-selector": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", - "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==" + "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", + "dev": true }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, "dependencies": { "is-typedarray": "^1.0.0" } @@ -47913,7 +49392,8 @@ "node_modules/uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true }, "node_modules/ufo": { "version": "1.4.0", @@ -47938,6 +49418,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -47952,6 +49433,7 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" @@ -47961,6 +49443,7 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, "funding": [ { "type": "github", @@ -47984,6 +49467,7 @@ "version": "5.28.4", "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, "license": "MIT", "dependencies": { "@fastify/busboy": "^2.0.0" @@ -48001,6 +49485,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", + "dev": true, "dependencies": { "inherits": "^2.0.1", "xtend": "^4.0.1" @@ -48050,6 +49535,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/unified/-/unified-7.1.0.tgz", "integrity": "sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==", + "dev": true, "dependencies": { "@types/unist": "^2.0.0", "@types/vfile": "^3.0.0", @@ -48065,6 +49551,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -48106,6 +49593,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, "dependencies": { "crypto-random-string": "^2.0.0" }, @@ -48116,12 +49604,14 @@ "node_modules/unist-util-is": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", - "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==" + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", + "dev": true }, "node_modules/unist-util-modify-children": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz", "integrity": "sha512-GRi04yhng1WqBf5RBzPkOtWAadcZS2gvuOgNn/cyJBYNxtTuyYqTKN0eg4rC1YJwGnzrqfRB3dSKm8cNCjNirg==", + "dev": true, "dependencies": { "array-iterate": "^1.0.0" } @@ -48130,6 +49620,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", + "dev": true, "dependencies": { "unist-util-visit": "^1.1.0" }, @@ -48141,12 +49632,14 @@ "node_modules/unist-util-stringify-position": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==" + "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", + "dev": true }, "node_modules/unist-util-visit": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "dev": true, "dependencies": { "unist-util-visit-parents": "^2.0.0" } @@ -48155,6 +49648,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "dev": true, "dependencies": { "unist-util-is": "^3.0.0" } @@ -48206,9 +49700,9 @@ } }, "node_modules/unplugin/node_modules/acorn": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", - "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, "license": "MIT", "bin": { @@ -48277,6 +49771,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, "engines": { "node": ">=8" } @@ -48365,6 +49860,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -48393,6 +49889,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "dev": true, "dependencies": { "loader-utils": "^2.0.0", "mime-types": "^2.1.27", @@ -48419,6 +49916,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -48434,6 +49932,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -48478,7 +49977,8 @@ "node_modules/urlpattern-polyfill": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==" + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", + "dev": true }, "node_modules/use": { "version": "3.1.1", @@ -48645,12 +50145,14 @@ "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true }, "node_modules/v8-to-istanbul": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", @@ -48664,6 +50166,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -48673,6 +50176,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", + "dev": true, "dependencies": { "builtins": "^1.0.3" } @@ -48695,6 +50199,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz", "integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==", + "dev": true, "dependencies": { "is-buffer": "^2.0.0", "replace-ext": "1.0.0", @@ -48706,6 +50211,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==", + "dev": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" @@ -48715,6 +50221,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", + "dev": true, "dependencies": { "unist-util-stringify-position": "^1.1.1" } @@ -48723,6 +50230,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, "funding": [ { "type": "github", @@ -48768,6 +50276,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, "dependencies": { "xml-name-validator": "^5.0.0" }, @@ -49073,6 +50582,7 @@ "version": "1.7.3", "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, "dependencies": { "minimalistic-assert": "^1.0.0" } @@ -49141,9 +50651,9 @@ } }, "node_modules/webdriver/node_modules/@types/node": { - "version": "20.16.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.12.tgz", - "integrity": "sha512-LfPFB0zOeCeCNQV3i+67rcoVvoN5n0NVuR2vLG0O5ySQMgchuZlC4lgz546ZOJyDtj5KIgOxy+lacOimfqZAIA==", + "version": "20.16.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "dev": true, "license": "MIT", "dependencies": { @@ -49372,9 +50882,9 @@ } }, "node_modules/webdriverio/node_modules/@types/node": { - "version": "20.16.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.12.tgz", - "integrity": "sha512-LfPFB0zOeCeCNQV3i+67rcoVvoN5n0NVuR2vLG0O5ySQMgchuZlC4lgz546ZOJyDtj5KIgOxy+lacOimfqZAIA==", + "version": "20.16.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "dev": true, "license": "MIT", "dependencies": { @@ -49529,6 +51039,7 @@ "version": "5.95.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", + "dev": true, "dependencies": { "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", @@ -49574,6 +51085,7 @@ "version": "4.9.1", "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.9.1.tgz", "integrity": "sha512-jnd6EoYrf9yMxCyYDPj8eutJvtjQNp8PHmni/e/ulydHBWhT5J3menXt3HEkScsu9YqMAcG4CfFjs3rj5pVU1w==", + "dev": true, "dependencies": { "@discoveryjs/json-ext": "0.5.7", "acorn": "^8.0.4", @@ -49601,9 +51113,10 @@ } }, "node_modules/webpack-bundle-analyzer/node_modules/acorn": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", - "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -49616,6 +51129,7 @@ "version": "8.3.4", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, "license": "MIT", "dependencies": { "acorn": "^8.11.0" @@ -49628,6 +51142,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, "engines": { "node": ">= 10" } @@ -49636,6 +51151,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "engines": { "node": ">=10" }, @@ -49647,6 +51163,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dev": true, "dependencies": { "duplexer": "^0.1.2" }, @@ -49661,6 +51178,7 @@ "version": "5.1.4", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1", @@ -49704,12 +51222,14 @@ "node_modules/webpack-cli/node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true }, "node_modules/webpack-cli/node_modules/commander": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, "engines": { "node": ">=14" } @@ -49718,6 +51238,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -49731,6 +51252,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -49739,6 +51261,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -49750,6 +51273,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } @@ -49758,6 +51282,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -49860,6 +51385,7 @@ "version": "4.15.1", "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "dev": true, "dependencies": { "@types/bonjour": "^3.5.9", "@types/connect-history-api-fallback": "^1.3.5", @@ -49918,6 +51444,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -49934,6 +51461,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -49944,12 +51472,14 @@ "node_modules/webpack-dev-server/node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true }, "node_modules/webpack-dev-server/node_modules/ipaddr.js": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, "engines": { "node": ">= 10" } @@ -49958,6 +51488,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -49968,12 +51499,14 @@ "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, "node_modules/webpack-dev-server/node_modules/open": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -49990,6 +51523,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -50008,6 +51542,7 @@ "version": "5.3.4", "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "dev": true, "dependencies": { "colorette": "^2.0.10", "memfs": "^3.4.3", @@ -50030,6 +51565,7 @@ "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -50062,6 +51598,7 @@ "version": "5.8.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, "dependencies": { "clone-deep": "^4.0.1", "wildcard": "^2.0.0" @@ -50074,6 +51611,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, "engines": { "node": ">=10.13.0" } @@ -50088,6 +51626,7 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -50096,22 +51635,26 @@ "node_modules/webpack/node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true }, "node_modules/webpack/node_modules/@webassemblyjs/helper-buffer": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true }, "node_modules/webpack/node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true }, "node_modules/webpack/node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -50123,6 +51666,7 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -50131,6 +51675,7 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -50138,12 +51683,14 @@ "node_modules/webpack/node_modules/@webassemblyjs/utf8": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true }, "node_modules/webpack/node_modules/@webassemblyjs/wasm-edit": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -50159,6 +51706,7 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", @@ -50171,6 +51719,7 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -50182,6 +51731,7 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-api-error": "1.11.6", @@ -50195,15 +51745,17 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" } }, "node_modules/webpack/node_modules/acorn": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", - "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -50216,6 +51768,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -50231,6 +51784,7 @@ "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -50244,6 +51798,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -50256,6 +51811,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, "engines": { "node": ">=6.11.5" } @@ -50264,6 +51820,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -50281,6 +51838,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, "engines": { "node": ">=6" } @@ -50289,6 +51847,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "dev": true, "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", @@ -50302,6 +51861,7 @@ "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, "dependencies": { "http-parser-js": ">=0.5.1", "safe-buffer": ">=5.1.0", @@ -50315,6 +51875,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, "engines": { "node": ">=0.8.0" } @@ -50323,6 +51884,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, "dependencies": { "iconv-lite": "0.6.3" }, @@ -50339,6 +51901,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, "engines": { "node": ">=18" } @@ -50377,6 +51940,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -50388,6 +51952,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -50423,6 +51988,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", @@ -50449,7 +52015,8 @@ "node_modules/wildcard": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true }, "node_modules/windows-release": { "version": "3.2.0", @@ -50609,6 +52176,7 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -50616,7 +52184,8 @@ "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true }, "node_modules/worker-farm": { "version": "1.7.0", @@ -50732,6 +52301,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", + "dev": true, "dependencies": { "detect-indent": "^5.0.0", "graceful-fs": "^4.1.15", @@ -50748,6 +52318,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, "dependencies": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -50760,6 +52331,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, "engines": { "node": ">=6" } @@ -50768,6 +52340,7 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, "bin": { "semver": "bin/semver" } @@ -50776,6 +52349,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-4.0.0.tgz", "integrity": "sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==", + "dev": true, "dependencies": { "sort-keys": "^2.0.0", "type-fest": "^0.4.1", @@ -50789,6 +52363,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", + "dev": true, "engines": { "node": ">=6" } @@ -50817,12 +52392,14 @@ "node_modules/x-is-string": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", - "integrity": "sha512-GojqklwG8gpzOVEVki5KudKNoq7MbbjYZCbyWzEz7tyPA7eleiE0+ePwOWQQRb5fm86rD3S8Tc0tSFf3AOv50w==" + "integrity": "sha512-GojqklwG8gpzOVEVki5KudKNoq7MbbjYZCbyWzEz7tyPA7eleiE0+ePwOWQQRb5fm86rD3S8Tc0tSFf3AOv50w==", + "dev": true }, "node_modules/xdg-basedir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true, "engines": { "node": ">=8" } @@ -50837,6 +52414,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, "engines": { "node": ">=18" } @@ -50853,7 +52431,8 @@ "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true }, "node_modules/xtend": { "version": "4.0.2", @@ -50921,7 +52500,8 @@ "node_modules/yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true }, "node_modules/yaml": { "version": "1.10.2", @@ -50953,6 +52533,7 @@ "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, "engines": { "node": ">=10" } @@ -51027,6 +52608,7 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" @@ -51100,6 +52682,7 @@ "version": "3.23.8", "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" @@ -51111,8 +52694,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/dom-ready": "*", - "@wordpress/i18n": "*" + "@wordpress/dom-ready": "file:../dom-ready", + "@wordpress/i18n": "file:../i18n" }, "engines": { "node": ">=18.12.0", @@ -51125,10 +52708,10 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/data": "*", - "@wordpress/hooks": "*", - "@wordpress/i18n": "*", - "@wordpress/rich-text": "*", + "@wordpress/data": "file:../data", + "@wordpress/hooks": "file:../hooks", + "@wordpress/i18n": "file:../i18n", + "@wordpress/rich-text": "file:../rich-text", "uuid": "^9.0.1" }, "engines": { @@ -51153,8 +52736,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/i18n": "*", - "@wordpress/url": "*" + "@wordpress/i18n": "file:../i18n", + "@wordpress/url": "file:../url" }, "engines": { "node": ">=18.12.0", @@ -51176,6 +52759,7 @@ "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", "version": "5.10.0", + "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -51188,6 +52772,7 @@ "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", "version": "6.10.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "deepmerge": "^4.3.0", @@ -51205,6 +52790,7 @@ "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", "version": "8.10.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -51213,8 +52799,8 @@ "@babel/preset-env": "7.25.7", "@babel/preset-typescript": "7.25.7", "@babel/runtime": "7.25.7", - "@wordpress/browserslist-config": "*", - "@wordpress/warning": "*", + "@wordpress/browserslist-config": "file:../browserslist-config", + "@wordpress/warning": "file:../warning", "browserslist": "^4.21.10", "core-js": "^3.31.0", "react": "^18.3.0" @@ -51224,113 +52810,177 @@ "npm": ">=8.19.2" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-class-static-block": { + "packages/babel-preset-default/node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.7.tgz", - "integrity": "sha512-rvUUtoVlkDWtDWxGAiiQj0aNktTPn3eFynBcMC2IhsXweehwgdI9ODe+XjWw515kEmv22sSOTp/rxIRuTiB7zg==", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.7.tgz", + "integrity": "sha512-12xfNeKNH7jubQNm7PAkzlLwEmCs1tfuX3UjIw6vP6QXi+leKh6+LyC/+Ed4EIQermwd58wsyh070yjDHFlNGg==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-class-static-block": "^7.14.5" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "packages/babel-preset-default/node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.7.tgz", + "integrity": "sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/traverse": "^7.25.7", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.12.0" + "@babel/core": "^7.0.0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-dynamic-import": { + "packages/babel-preset-default/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "packages/babel-preset-default/node_modules/@babel/helper-member-expression-to-functions": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.7.tgz", - "integrity": "sha512-UvcLuual4h7/GfylKm2IAA3aph9rwvAM2XBA0uPKU3lca+Maai4jBjjEVUS568ld6kJcgbouuumCBhMd/Yz17w==", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.7.tgz", + "integrity": "sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" + } + }, + "packages/babel-preset-default/node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.7.tgz", + "integrity": "sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.7" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=6.9.0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-json-strings": { + "packages/babel-preset-default/node_modules/@babel/helper-replace-supers": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.7.tgz", - "integrity": "sha512-Ot43PrL9TEAiCe8C/2erAjXMeVSnE/BLEx6eyrKLNFCCw5jvhTHKyHxdI1pA0kz5njZRYAnMO2KObGqOCRDYSA==", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.7.tgz", + "integrity": "sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-json-strings": "^7.8.3" + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-logical-assignment-operators": { + "packages/babel-preset-default/node_modules/@babel/helper-skip-transparent-expression-wrappers": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.7.tgz", - "integrity": "sha512-iImzbA55BjiovLyG2bggWS+V+OLkaBorNvc/yJoeeDQGztknRnDdYfp2d/UPmunZYEnZi6Lg8QcTmNMHOB0lGA==", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.7.tgz", + "integrity": "sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.7.tgz", + "integrity": "sha512-wxyWg2RYaSUYgmd9MR0FyRGyeOMQE/Uzr1wzd/g5cf5bwi9A4v6HFdDm7y1MgDtod/fLOSTZY6jDgV0xU9d5bA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "packages/babel-preset-default/node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.7.tgz", - "integrity": "sha512-FbuJ63/4LEL32mIxrxwYaqjJxpbzxPVQj5a+Ebrc8JICV6YX8nE53jY+K0RZT3um56GoNWgkS2BQ/uLGTjtwfw==", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.7.tgz", + "integrity": "sha512-Xwg6tZpLxc4iQjorYsyGMyfJE7nP5MV8t/Ka58BgiA7Jw0fRqQNcANlLfdJ/yvBt9z9LD2We+BEkT7vLqZRWng==", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-transform-optional-chaining": "^7.25.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.13.0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-numeric-separator": { + "packages/babel-preset-default/node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.7.tgz", - "integrity": "sha512-8CbutzSSh4hmD+jJHIA8vdTNk15kAzOnFLVVgBSMGr28rt85ouT01/rezMecks9pkU939wDInImwCKv4ahU4IA==", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.7.tgz", + "integrity": "sha512-UVATLMidXrnH+GMUIuxq55nejlj02HP7F5ETyBONzP6G87fPBogG4CH6kxrSrdIuAjdwNO9VzyaYsrZPscWUrw==", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-object-rest-spread": { + "packages/babel-preset-default/node_modules/@babel/plugin-syntax-import-assertions": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.7.tgz", - "integrity": "sha512-1JdVKPhD7Y5PvgfFy0Mv2brdrolzpzSoUq2pr6xsR+m+3viGGeHEokFKsCgOkbeFOQxfB1Vt2F0cPJLRpFI4Zg==", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.7.tgz", + "integrity": "sha512-ZvZQRmME0zfJnDQnVBKYzHxXT7lYBB3Revz1GuS7oLXWMgqUPX4G+DDbT30ICClht9WKV34QVrZhSw6WdklwZQ==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -51339,14 +52989,14 @@ "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-optional-catch-binding": { + "packages/babel-preset-default/node_modules/@babel/plugin-syntax-import-attributes": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.7.tgz", - "integrity": "sha512-m9obYBA39mDPN7lJzD5WkGGb0GO54PPLXsbcnj1Hyeu8mSRz7Gb4b1A6zxNX32ZuUySDK4G6it8SDFWD1nCnqg==", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", + "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -51355,15 +53005,14 @@ "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-optional-chaining": { + "packages/babel-preset-default/node_modules/@babel/plugin-syntax-typescript": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.7.tgz", - "integrity": "sha512-h39agClImgPWg4H8mYVAbD1qP9vClFbEjqoJmt87Zen8pjqK8FTPUwrOXAvqu5soytwxrLMd2fx2KSCp2CHcNg==", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.7.tgz", + "integrity": "sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -51372,16 +53021,14 @@ "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/@babel/plugin-transform-private-property-in-object": { + "packages/babel-preset-default/node_modules/@babel/plugin-transform-arrow-functions": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.7.tgz", - "integrity": "sha512-LzA5ESzBy7tqj00Yjey9yWfs3FKy4EmJyKOSWld144OxkTji81WWnUT8nkLUn+imN/zHL8ZQlOu/MTUAhHaX3g==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.7.tgz", + "integrity": "sha512-EJN2mKxDwfOUCPxMO6MUI58RN3ganiRAG/MS/S3HfB6QFNjroAMelQo/gybyYq97WerCBAZoyrAoW8Tzdq2jWg==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-create-class-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -51390,95 +53037,16 @@ "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/@babel/preset-env": { + "packages/babel-preset-default/node_modules/@babel/plugin-transform-async-to-generator": { "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.7.tgz", - "integrity": "sha512-Gibz4OUdyNqqLj+7OAvBZxOD7CklCtMA5/j0JgUEwOnaRULsPDXmic2iKxL2DX2vQduPR5wH2hjZas/Vr/Oc0g==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.7.tgz", + "integrity": "sha512-ZUCjAavsh5CESCmi/xCpX1qcCaAglzs/7tmuvoFnJgA1dM7gQplsguljoTg+Ru8WENpX89cQyAtWoaE0I3X3Pg==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.7", - "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-module-imports": "^7.25.7", "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-validator-option": "^7.25.7", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.7", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.7", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.7", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.7", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.25.7", - "@babel/plugin-syntax-import-attributes": "^7.25.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.25.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.7", - "@babel/plugin-transform-async-to-generator": "^7.25.7", - "@babel/plugin-transform-block-scoped-functions": "^7.25.7", - "@babel/plugin-transform-block-scoping": "^7.25.7", - "@babel/plugin-transform-class-properties": "^7.25.7", - "@babel/plugin-transform-class-static-block": "^7.25.7", - "@babel/plugin-transform-classes": "^7.25.7", - "@babel/plugin-transform-computed-properties": "^7.25.7", - "@babel/plugin-transform-destructuring": "^7.25.7", - "@babel/plugin-transform-dotall-regex": "^7.25.7", - "@babel/plugin-transform-duplicate-keys": "^7.25.7", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.7", - "@babel/plugin-transform-dynamic-import": "^7.25.7", - "@babel/plugin-transform-exponentiation-operator": "^7.25.7", - "@babel/plugin-transform-export-namespace-from": "^7.25.7", - "@babel/plugin-transform-for-of": "^7.25.7", - "@babel/plugin-transform-function-name": "^7.25.7", - "@babel/plugin-transform-json-strings": "^7.25.7", - "@babel/plugin-transform-literals": "^7.25.7", - "@babel/plugin-transform-logical-assignment-operators": "^7.25.7", - "@babel/plugin-transform-member-expression-literals": "^7.25.7", - "@babel/plugin-transform-modules-amd": "^7.25.7", - "@babel/plugin-transform-modules-commonjs": "^7.25.7", - "@babel/plugin-transform-modules-systemjs": "^7.25.7", - "@babel/plugin-transform-modules-umd": "^7.25.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.7", - "@babel/plugin-transform-new-target": "^7.25.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.7", - "@babel/plugin-transform-numeric-separator": "^7.25.7", - "@babel/plugin-transform-object-rest-spread": "^7.25.7", - "@babel/plugin-transform-object-super": "^7.25.7", - "@babel/plugin-transform-optional-catch-binding": "^7.25.7", - "@babel/plugin-transform-optional-chaining": "^7.25.7", - "@babel/plugin-transform-parameters": "^7.25.7", - "@babel/plugin-transform-private-methods": "^7.25.7", - "@babel/plugin-transform-private-property-in-object": "^7.25.7", - "@babel/plugin-transform-property-literals": "^7.25.7", - "@babel/plugin-transform-regenerator": "^7.25.7", - "@babel/plugin-transform-reserved-words": "^7.25.7", - "@babel/plugin-transform-shorthand-properties": "^7.25.7", - "@babel/plugin-transform-spread": "^7.25.7", - "@babel/plugin-transform-sticky-regex": "^7.25.7", - "@babel/plugin-transform-template-literals": "^7.25.7", - "@babel/plugin-transform-typeof-symbol": "^7.25.7", - "@babel/plugin-transform-unicode-escapes": "^7.25.7", - "@babel/plugin-transform-unicode-property-regex": "^7.25.7", - "@babel/plugin-transform-unicode-regex": "^7.25.7", - "@babel/plugin-transform-unicode-sets-regex": "^7.25.7", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.38.1", - "semver": "^6.3.1" + "@babel/helper-remap-async-to-generator": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -51487,155 +53055,1135 @@ "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "packages/base-styles": { - "name": "@wordpress/base-styles", - "version": "5.10.0", - "license": "GPL-2.0-or-later", + "packages/babel-preset-default/node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.7.tgz", + "integrity": "sha512-xHttvIM9fvqW+0a3tZlYcZYSBpSWzGBFIt/sYG3tcdSzBB8ZeVgz2gBP7Df+sM0N1850jrviYSSeUuc+135dmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "packages/blob": { - "name": "@wordpress/blob", - "version": "4.10.0", - "license": "GPL-2.0-or-later", + "packages/babel-preset-default/node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.7.tgz", + "integrity": "sha512-ZEPJSkVZaeTFG/m2PARwLZQ+OG0vFIhPlKHK/JdIMy8DbRJ/htz6LRrTFtdzxi9EHmcwbNPAKDnadpNSIW+Aow==", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "7.25.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "packages/block-directory": { - "name": "@wordpress/block-directory", - "version": "5.10.0", - "license": "GPL-2.0-or-later", + "packages/babel-preset-default/node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.7.tgz", + "integrity": "sha512-mhyfEW4gufjIqYFo9krXHJ3ElbFLIze5IDp+wQTxoPd+mwFb1NxatNAwmv8Q8Iuxv7Zc+q8EkiMQwc9IhyGf4g==", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/api-fetch": "*", - "@wordpress/block-editor": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/editor": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/notices": "*", - "@wordpress/plugins": "*", - "@wordpress/private-apis": "*", - "@wordpress/url": "*", - "change-case": "^4.1.2", - "clsx": "^2.1.1" + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" + "node": ">=6.9.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "@babel/core": "^7.0.0-0" } }, - "packages/block-editor": { - "name": "@wordpress/block-editor", - "version": "14.5.0", - "license": "GPL-2.0-or-later", + "packages/babel-preset-default/node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.7.tgz", + "integrity": "sha512-rvUUtoVlkDWtDWxGAiiQj0aNktTPn3eFynBcMC2IhsXweehwgdI9ODe+XjWw515kEmv22sSOTp/rxIRuTiB7zg==", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "7.25.7", - "@emotion/react": "^11.7.1", - "@emotion/styled": "^11.6.0", - "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "*", - "@wordpress/api-fetch": "*", - "@wordpress/blob": "*", - "@wordpress/block-serialization-default-parser": "*", - "@wordpress/blocks": "*", - "@wordpress/commands": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/date": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/element": "*", - "@wordpress/escape-html": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/is-shallow-equal": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/keycodes": "*", - "@wordpress/notices": "*", - "@wordpress/preferences": "*", - "@wordpress/private-apis": "*", - "@wordpress/rich-text": "*", - "@wordpress/style-engine": "*", - "@wordpress/token-list": "*", - "@wordpress/url": "*", - "@wordpress/warning": "*", - "@wordpress/wordcount": "*", - "change-case": "^4.1.2", - "clsx": "^2.1.1", - "colord": "^2.7.0", - "deepmerge": "^4.3.0", - "diff": "^4.0.2", - "fast-deep-equal": "^3.1.3", - "memize": "^2.1.0", - "parsel-js": "^1.1.2", - "postcss": "^8.4.21", - "postcss-prefix-selector": "^1.16.0", - "postcss-urlrebase": "^1.4.0", - "react-autosize-textarea": "^7.1.0", - "react-easy-crop": "^5.0.6", - "remove-accents": "^0.5.0" + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" + "node": ">=6.9.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "@babel/core": "^7.12.0" } }, - "packages/block-editor/node_modules/postcss-urlrebase": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.4.0.tgz", - "integrity": "sha512-rRaxMmWvXrn8Rk1PqsxmaJwldRHsr0WbbASKKCZYxXwotHkM/5X/6IrwaEe8pdzpbNGCEY86yhYMN0MhgOkADA==", + "packages/babel-preset-default/node_modules/@babel/plugin-transform-classes": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.7.tgz", + "integrity": "sha512-9j9rnl+YCQY0IGoeipXvnk3niWicIB6kCsWRGLwX241qSXpbA4MKxtp/EdvFxsc4zI5vqfLxzOd0twIJ7I99zg==", + "dev": true, "license": "MIT", "dependencies": { - "postcss-value-parser": "^4.2.0" + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/traverse": "^7.25.7", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "postcss": "^8.3.0" + "@babel/core": "^7.0.0-0" } }, - "packages/block-editor/node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "license": "MIT" - }, - "packages/block-editor/node_modules/react-easy-crop": { - "version": "5.0.6", + "packages/babel-preset-default/node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.7.tgz", + "integrity": "sha512-QIv+imtM+EtNxg/XBKL3hiWjgdLjMOmZ+XzQwSgmBfKbfxUjBzGgVPklUuE55eq5/uVoh8gg3dqlrwR/jw3ZeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/template": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-destructuring": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.7.tgz", + "integrity": "sha512-xKcfLTlJYUczdaM1+epcdh1UGewJqr9zATgrNHcLBcV2QmfvPPEixo/sK/syql9cEmbr7ulu5HMFG5vbbt/sEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.7.tgz", + "integrity": "sha512-kXzXMMRzAtJdDEgQBLF4oaiT6ZCU3oWHgpARnTKDAqPkDJ+bs3NrZb310YYevR5QlRo3Kn7dzzIdHbZm1VzJdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.7.tgz", + "integrity": "sha512-by+v2CjoL3aMnWDOyCIg+yxU9KXSRa9tN6MbqggH5xvymmr9p4AMjYkNlQy4brMceBnUyHZ9G8RnpvT8wP7Cfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.7.tgz", + "integrity": "sha512-UvcLuual4h7/GfylKm2IAA3aph9rwvAM2XBA0uPKU3lca+Maai4jBjjEVUS568ld6kJcgbouuumCBhMd/Yz17w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.7.tgz", + "integrity": "sha512-yjqtpstPfZ0h/y40fAXRv2snciYr0OAoMXY/0ClC7tm4C/nG5NJKmIItlaYlLbIVAWNfrYuy9dq1bE0SbX0PEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-for-of": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.7.tgz", + "integrity": "sha512-n/TaiBGJxYFWvpJDfsxSj9lEEE44BFM1EPGz4KEiTipTgkoFVVcCmzAL3qA7fdQU96dpo4gGf5HBx/KnDvqiHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.7.tgz", + "integrity": "sha512-5MCTNcjCMxQ63Tdu9rxyN6cAWurqfrDZ76qvVPrGYdBxIj+EawuuxTu/+dgJlhK5eRz3v1gLwp6XwS8XaX2NiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-json-strings": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.7.tgz", + "integrity": "sha512-Ot43PrL9TEAiCe8C/2erAjXMeVSnE/BLEx6eyrKLNFCCw5jvhTHKyHxdI1pA0kz5njZRYAnMO2KObGqOCRDYSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-literals": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.7.tgz", + "integrity": "sha512-fwzkLrSu2fESR/cm4t6vqd7ebNIopz2QHGtjoU+dswQo/P6lwAG04Q98lliE3jkz/XqnbGFLnUcE0q0CVUf92w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.7.tgz", + "integrity": "sha512-iImzbA55BjiovLyG2bggWS+V+OLkaBorNvc/yJoeeDQGztknRnDdYfp2d/UPmunZYEnZi6Lg8QcTmNMHOB0lGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.7.tgz", + "integrity": "sha512-Std3kXwpXfRV0QtQy5JJcRpkqP8/wG4XL7hSKZmGlxPlDqmpXtEPRmhF7ztnlTCtUN3eXRUJp+sBEZjaIBVYaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.7.tgz", + "integrity": "sha512-CgselSGCGzjQvKzghCvDTxKHP3iooenLpJDO842ehn5D2G5fJB222ptnDwQho0WjEvg7zyoxb9P+wiYxiJX5yA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.7.tgz", + "integrity": "sha512-L9Gcahi0kKFYXvweO6n0wc3ZG1ChpSFdgG+eV1WYZ3/dGbJK7vvk91FgGgak8YwRgrCuihF8tE/Xg07EkL5COg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.7.tgz", + "integrity": "sha512-t9jZIvBmOXJsiuyOwhrIGs8dVcD6jDyg2icw1VL4A/g+FnWyJKwUfSSU2nwJuMV2Zqui856El9u+ElB+j9fV1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.7.tgz", + "integrity": "sha512-p88Jg6QqsaPh+EB7I9GJrIqi1Zt4ZBHUQtjw3z1bzEXcLh6GfPqzZJ6G+G1HBGKUNukT58MnKG7EN7zXQBCODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.7.tgz", + "integrity": "sha512-BtAT9LzCISKG3Dsdw5uso4oV1+v2NlVXIIomKJgQybotJY3OwCwJmkongjHgwGKoZXd0qG5UZ12JUlDQ07W6Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-new-target": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.7.tgz", + "integrity": "sha512-CfCS2jDsbcZaVYxRFo2qtavW8SpdzmBXC2LOI4oO0rP+JSRDxxF3inF4GcPsLgfb5FjkhXG5/yR/lxuRs2pySA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.7.tgz", + "integrity": "sha512-FbuJ63/4LEL32mIxrxwYaqjJxpbzxPVQj5a+Ebrc8JICV6YX8nE53jY+K0RZT3um56GoNWgkS2BQ/uLGTjtwfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.7.tgz", + "integrity": "sha512-8CbutzSSh4hmD+jJHIA8vdTNk15kAzOnFLVVgBSMGr28rt85ouT01/rezMecks9pkU939wDInImwCKv4ahU4IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.7.tgz", + "integrity": "sha512-1JdVKPhD7Y5PvgfFy0Mv2brdrolzpzSoUq2pr6xsR+m+3viGGeHEokFKsCgOkbeFOQxfB1Vt2F0cPJLRpFI4Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-object-super": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.7.tgz", + "integrity": "sha512-pWT6UXCEW3u1t2tcAGtE15ornCBvopHj9Bps9D2DsH15APgNVOTwwczGckX+WkAvBmuoYKRCFa4DK+jM8vh5AA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.7.tgz", + "integrity": "sha512-m9obYBA39mDPN7lJzD5WkGGb0GO54PPLXsbcnj1Hyeu8mSRz7Gb4b1A6zxNX32ZuUySDK4G6it8SDFWD1nCnqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.7.tgz", + "integrity": "sha512-h39agClImgPWg4H8mYVAbD1qP9vClFbEjqoJmt87Zen8pjqK8FTPUwrOXAvqu5soytwxrLMd2fx2KSCp2CHcNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-parameters": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.7.tgz", + "integrity": "sha512-FYiTvku63me9+1Nz7TOx4YMtW3tWXzfANZtrzHhUZrz4d47EEtMQhzFoZWESfXuAMMT5mwzD4+y1N8ONAX6lMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz", + "integrity": "sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.7.tgz", + "integrity": "sha512-LzA5ESzBy7tqj00Yjey9yWfs3FKy4EmJyKOSWld144OxkTji81WWnUT8nkLUn+imN/zHL8ZQlOu/MTUAhHaX3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-property-literals": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.7.tgz", + "integrity": "sha512-lQEeetGKfFi0wHbt8ClQrUSUMfEeI3MMm74Z73T9/kuz990yYVtfofjf3NuA42Jy3auFOpbjDyCSiIkTs1VIYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.7.tgz", + "integrity": "sha512-vILAg5nwGlR9EXE8JIOX4NHXd49lrYbN8hnjffDtoULwpL9hUx/N55nqh2qd0q6FyNDfjl9V79ecKGvFbcSA0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-jsx": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-regenerator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.7.tgz", + "integrity": "sha512-mgDoQCRjrY3XK95UuV60tZlFCQGXEtMg8H+IsW72ldw1ih1jZhzYXbJvghmAEpg5UVhhnCeia1CkGttUvCkiMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.7.tgz", + "integrity": "sha512-3OfyfRRqiGeOvIWSagcwUTVk2hXBsr/ww7bLn6TRTuXnexA+Udov2icFOxFX9abaj4l96ooYkcNN1qi2Zvqwng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-runtime": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.7.tgz", + "integrity": "sha512-Y9p487tyTzB0yDYQOtWnC+9HGOuogtP3/wNpun1xJXEEvI6vip59BSBTsHnekZLqxmPcgsrAKt46HAAb//xGhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.7.tgz", + "integrity": "sha512-uBbxNwimHi5Bv3hUccmOFlUy3ATO6WagTApenHz9KzoIdn0XeACdB12ZJ4cjhuB2WSi80Ez2FWzJnarccriJeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-spread": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.7.tgz", + "integrity": "sha512-Mm6aeymI0PBh44xNIv/qvo8nmbkpZze1KvR8MkEqbIREDxoiWTi18Zr2jryfRMwDfVZF9foKh060fWgni44luw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.7.tgz", + "integrity": "sha512-ZFAeNkpGuLnAQ/NCsXJ6xik7Id+tHuS+NT+ue/2+rn/31zcdnupCdmunOizEaP0JsUmTFSTOPoQY7PkK2pttXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-template-literals": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.7.tgz", + "integrity": "sha512-SI274k0nUsFFmyQupiO7+wKATAmMFf8iFgq2O+vVFXZ0SV9lNfT1NGzBEhjquFmD8I9sqHLguH+gZVN3vww2AA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.7.tgz", + "integrity": "sha512-OmWmQtTHnO8RSUbL0NTdtpbZHeNTnm68Gj5pA4Y2blFNh+V4iZR68V1qL9cI37J21ZN7AaCnkfdHtLExQPf2uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-typescript": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.7.tgz", + "integrity": "sha512-VKlgy2vBzj8AmEzunocMun2fF06bsSWV+FvVXohtL6FGve/+L217qhHxRTVGHEDO/YR8IANcjzgJsd04J8ge5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-syntax-typescript": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.7.tgz", + "integrity": "sha512-BN87D7KpbdiABA+t3HbVqHzKWUDN3dymLaTnPFAMyc8lV+KN3+YzNhVRNdinaCPA4AUqx7ubXbQ9shRjYBl3SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.7.tgz", + "integrity": "sha512-IWfR89zcEPQGB/iB408uGtSPlQd3Jpq11Im86vUgcmSTcoWAiQMCTOa2K2yNNqFJEBVICKhayctee65Ka8OB0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.7.tgz", + "integrity": "sha512-8JKfg/hiuA3qXnlLx8qtv5HWRbgyFx2hMMtpDDuU2rTckpKkGu4ycK5yYHwuEa16/quXfoxHBIApEsNyMWnt0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.7.tgz", + "integrity": "sha512-YRW8o9vzImwmh4Q3Rffd09bH5/hvY0pxg+1H1i0f7APoUeg12G7+HhLj9ZFNIrYkgBXhIijPJ+IXypN0hLTIbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "packages/babel-preset-default/node_modules/@babel/preset-env": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.7.tgz", + "integrity": "sha512-Gibz4OUdyNqqLj+7OAvBZxOD7CklCtMA5/j0JgUEwOnaRULsPDXmic2iKxL2DX2vQduPR5wH2hjZas/Vr/Oc0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.25.7", + "@babel/plugin-syntax-import-attributes": "^7.25.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.25.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.7", + "@babel/plugin-transform-async-to-generator": "^7.25.7", + "@babel/plugin-transform-block-scoped-functions": "^7.25.7", + "@babel/plugin-transform-block-scoping": "^7.25.7", + "@babel/plugin-transform-class-properties": "^7.25.7", + "@babel/plugin-transform-class-static-block": "^7.25.7", + "@babel/plugin-transform-classes": "^7.25.7", + "@babel/plugin-transform-computed-properties": "^7.25.7", + "@babel/plugin-transform-destructuring": "^7.25.7", + "@babel/plugin-transform-dotall-regex": "^7.25.7", + "@babel/plugin-transform-duplicate-keys": "^7.25.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.7", + "@babel/plugin-transform-dynamic-import": "^7.25.7", + "@babel/plugin-transform-exponentiation-operator": "^7.25.7", + "@babel/plugin-transform-export-namespace-from": "^7.25.7", + "@babel/plugin-transform-for-of": "^7.25.7", + "@babel/plugin-transform-function-name": "^7.25.7", + "@babel/plugin-transform-json-strings": "^7.25.7", + "@babel/plugin-transform-literals": "^7.25.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.7", + "@babel/plugin-transform-member-expression-literals": "^7.25.7", + "@babel/plugin-transform-modules-amd": "^7.25.7", + "@babel/plugin-transform-modules-commonjs": "^7.25.7", + "@babel/plugin-transform-modules-systemjs": "^7.25.7", + "@babel/plugin-transform-modules-umd": "^7.25.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.7", + "@babel/plugin-transform-new-target": "^7.25.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.7", + "@babel/plugin-transform-numeric-separator": "^7.25.7", + "@babel/plugin-transform-object-rest-spread": "^7.25.7", + "@babel/plugin-transform-object-super": "^7.25.7", + "@babel/plugin-transform-optional-catch-binding": "^7.25.7", + "@babel/plugin-transform-optional-chaining": "^7.25.7", + "@babel/plugin-transform-parameters": "^7.25.7", + "@babel/plugin-transform-private-methods": "^7.25.7", + "@babel/plugin-transform-private-property-in-object": "^7.25.7", + "@babel/plugin-transform-property-literals": "^7.25.7", + "@babel/plugin-transform-regenerator": "^7.25.7", + "@babel/plugin-transform-reserved-words": "^7.25.7", + "@babel/plugin-transform-shorthand-properties": "^7.25.7", + "@babel/plugin-transform-spread": "^7.25.7", + "@babel/plugin-transform-sticky-regex": "^7.25.7", + "@babel/plugin-transform-template-literals": "^7.25.7", + "@babel/plugin-transform-typeof-symbol": "^7.25.7", + "@babel/plugin-transform-unicode-escapes": "^7.25.7", + "@babel/plugin-transform-unicode-property-regex": "^7.25.7", + "@babel/plugin-transform-unicode-regex": "^7.25.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.38.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/@babel/preset-typescript": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.25.7.tgz", + "integrity": "sha512-rkkpaXJZOFN45Fb+Gki0c+KMIglk4+zZXOoMJuyEK8y8Kkc8Jd3BDmP7qPsz0zQMJj+UD7EprF+AqAXcILnexw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "@babel/plugin-syntax-jsx": "^7.25.7", + "@babel/plugin-transform-modules-commonjs": "^7.25.7", + "@babel/plugin-transform-typescript": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "packages/babel-preset-default/node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "packages/babel-preset-default/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "packages/babel-preset-default/node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "packages/babel-preset-default/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "packages/babel-preset-default/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "packages/base-styles": { + "name": "@wordpress/base-styles", + "version": "5.10.0", + "dev": true, + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "packages/blob": { + "name": "@wordpress/blob", + "version": "4.10.0", + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "7.25.7" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "packages/block-directory": { + "name": "@wordpress/block-directory", + "version": "5.10.0", + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "7.25.7", + "@wordpress/a11y": "file:../a11y", + "@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/editor": "file:../editor", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/plugins": "file:../plugins", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url", + "change-case": "^4.1.2", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "packages/block-editor": { + "name": "@wordpress/block-editor", + "version": "14.5.0", + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "7.25.7", + "@emotion/react": "^11.7.1", + "@emotion/styled": "^11.6.0", + "@react-spring/web": "^9.4.5", + "@wordpress/a11y": "file:../a11y", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blob": "file:../blob", + "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", + "@wordpress/blocks": "file:../blocks", + "@wordpress/commands": "file:../commands", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/date": "file:../date", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/element": "file:../element", + "@wordpress/escape-html": "file:../escape-html", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/notices": "file:../notices", + "@wordpress/preferences": "file:../preferences", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/style-engine": "file:../style-engine", + "@wordpress/token-list": "file:../token-list", + "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", + "@wordpress/wordcount": "file:../wordcount", + "change-case": "^4.1.2", + "clsx": "^2.1.1", + "colord": "^2.7.0", + "deepmerge": "^4.3.0", + "diff": "^4.0.2", + "fast-deep-equal": "^3.1.3", + "memize": "^2.1.0", + "parsel-js": "^1.1.2", + "postcss": "^8.4.21", + "postcss-prefix-selector": "^1.16.0", + "postcss-urlrebase": "^1.4.0", + "react-autosize-textarea": "^7.1.0", + "react-easy-crop": "^5.0.6", + "remove-accents": "^0.5.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "packages/block-editor/node_modules/postcss-urlrebase": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.4.0.tgz", + "integrity": "sha512-rRaxMmWvXrn8Rk1PqsxmaJwldRHsr0WbbASKKCZYxXwotHkM/5X/6IrwaEe8pdzpbNGCEY86yhYMN0MhgOkADA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.3.0" + } + }, + "packages/block-editor/node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "packages/block-editor/node_modules/react-easy-crop": { + "version": "5.0.6", "resolved": "https://registry.npmjs.org/react-easy-crop/-/react-easy-crop-5.0.6.tgz", "integrity": "sha512-LV8te8NGC72k3l8uAqPAw73D2i9AbRlZqyo1Xz8VetwiMfkSKYgyqE3IFEwf5h+1g7AS1nMxBKk6ZPdhvLw6MQ==", "dependencies": { @@ -51658,39 +54206,39 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/api-fetch": "*", - "@wordpress/autop": "*", - "@wordpress/blob": "*", - "@wordpress/block-editor": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/date": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/element": "*", - "@wordpress/escape-html": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/interactivity": "*", - "@wordpress/interactivity-router": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/keycodes": "*", - "@wordpress/notices": "*", - "@wordpress/patterns": "*", - "@wordpress/primitives": "*", - "@wordpress/private-apis": "*", - "@wordpress/reusable-blocks": "*", - "@wordpress/rich-text": "*", - "@wordpress/server-side-render": "*", - "@wordpress/url": "*", - "@wordpress/viewport": "*", - "@wordpress/wordcount": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/autop": "file:../autop", + "@wordpress/blob": "file:../blob", + "@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/date": "file:../date", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/element": "file:../element", + "@wordpress/escape-html": "file:../escape-html", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/interactivity": "file:../interactivity", + "@wordpress/interactivity-router": "file:../interactivity-router", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/notices": "file:../notices", + "@wordpress/patterns": "file:../patterns", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/reusable-blocks": "file:../reusable-blocks", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/server-side-render": "file:../server-side-render", + "@wordpress/url": "file:../url", + "@wordpress/viewport": "file:../viewport", + "@wordpress/wordcount": "file:../wordcount", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -51749,21 +54297,21 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/autop": "*", - "@wordpress/blob": "*", - "@wordpress/block-serialization-default-parser": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/is-shallow-equal": "*", - "@wordpress/private-apis": "*", - "@wordpress/rich-text": "*", - "@wordpress/shortcode": "*", - "@wordpress/warning": "*", + "@wordpress/autop": "file:../autop", + "@wordpress/blob": "file:../blob", + "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/shortcode": "file:../shortcode", + "@wordpress/warning": "file:../warning", "change-case": "^4.1.2", "colord": "^2.7.0", "fast-deep-equal": "^3.1.3", @@ -51800,6 +54348,7 @@ "packages/browserslist-config": { "name": "@wordpress/browserslist-config", "version": "6.10.0", + "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -51812,13 +54361,13 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "*", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/private-apis": "*", + "@wordpress/components": "file:../components", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/private-apis": "file:../private-apis", "clsx": "^2.1.1", "cmdk": "^1.0.0" }, @@ -51996,23 +54545,23 @@ "@types/gradient-parser": "0.1.3", "@types/highlight-words-core": "1.2.1", "@use-gesture/react": "^10.3.1", - "@wordpress/a11y": "*", - "@wordpress/compose": "*", - "@wordpress/date": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/element": "*", - "@wordpress/escape-html": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/is-shallow-equal": "*", - "@wordpress/keycodes": "*", - "@wordpress/primitives": "*", - "@wordpress/private-apis": "*", - "@wordpress/rich-text": "*", - "@wordpress/warning": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/compose": "file:../compose", + "@wordpress/date": "file:../date", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/element": "file:../element", + "@wordpress/escape-html": "file:../escape-html", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/warning": "file:../warning", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -52107,13 +54656,13 @@ "dependencies": { "@babel/runtime": "7.25.7", "@types/mousetrap": "^1.6.8", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/element": "*", - "@wordpress/is-shallow-equal": "*", - "@wordpress/keycodes": "*", - "@wordpress/priority-queue": "*", - "@wordpress/undo-manager": "*", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/element": "file:../element", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/priority-queue": "file:../priority-queue", + "@wordpress/undo-manager": "file:../undo-manager", "change-case": "^4.1.2", "clipboard": "^2.0.11", "mousetrap": "^1.6.5", @@ -52143,19 +54692,19 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "*", - "@wordpress/commands": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/notices": "*", - "@wordpress/private-apis": "*", - "@wordpress/router": "*", - "@wordpress/url": "*" + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/commands": "file:../commands", + "@wordpress/compose": "file:../compose", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/router": "file:../router", + "@wordpress/url": "file:../url" }, "engines": { "node": ">=18.12.0", @@ -52172,22 +54721,22 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/block-editor": "*", - "@wordpress/blocks": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/element": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/is-shallow-equal": "*", - "@wordpress/private-apis": "*", - "@wordpress/rich-text": "*", - "@wordpress/sync": "*", - "@wordpress/undo-manager": "*", - "@wordpress/url": "*", - "@wordpress/warning": "*", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/blocks": "file:../blocks", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/element": "file:../element", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/sync": "file:../sync", + "@wordpress/undo-manager": "file:../undo-manager", + "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", "change-case": "^4.1.2", "equivalent-key-map": "^0.2.2", "fast-deep-equal": "^3.1.3", @@ -52214,9 +54763,10 @@ "packages/create-block": { "name": "@wordpress/create-block", "version": "4.53.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/lazy-import": "*", + "@wordpress/lazy-import": "file:../lazy-import", "chalk": "^4.0.0", "change-case": "^4.1.2", "check-node-version": "^4.1.0", @@ -52238,18 +54788,10 @@ "npm": ">=10.2.3" } }, - "packages/create-block-interactive-template": { - "name": "@wordpress/create-block-interactive-template", - "version": "2.10.0", - "license": "GPL-2.0-or-later", - "engines": { - "node": ">=18.12.0", - "npm": ">=8.19.2" - } - }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", "version": "4.10.0", + "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -52262,27 +54804,27 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "*", - "@wordpress/block-library": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/dom": "*", - "@wordpress/editor": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/interface": "*", - "@wordpress/is-shallow-equal": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/keycodes": "*", - "@wordpress/media-utils": "*", - "@wordpress/preferences": "*", - "@wordpress/private-apis": "*", - "@wordpress/widgets": "*", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/block-library": "file:../block-library", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/dom": "file:../dom", + "@wordpress/editor": "file:../editor", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/interface": "file:../interface", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/media-utils": "file:../media-utils", + "@wordpress/preferences": "file:../preferences", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/widgets": "file:../widgets", "clsx": "^2.1.1", "fast-deep-equal": "^3.1.3" }, @@ -52301,13 +54843,13 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/compose": "*", - "@wordpress/deprecated": "*", - "@wordpress/element": "*", - "@wordpress/is-shallow-equal": "*", - "@wordpress/priority-queue": "*", - "@wordpress/private-apis": "*", - "@wordpress/redux-routine": "*", + "@wordpress/compose": "file:../compose", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/element": "file:../element", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/priority-queue": "file:../priority-queue", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/redux-routine": "file:../redux-routine", "deepmerge": "^4.3.0", "equivalent-key-map": "^0.2.2", "is-plain-object": "^5.0.0", @@ -52330,9 +54872,9 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*" + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated" }, "engines": { "node": ">=18.12.0", @@ -52349,15 +54891,15 @@ "dependencies": { "@ariakit/react": "^0.4.10", "@babel/runtime": "7.25.7", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/primitives": "*", - "@wordpress/private-apis": "*", - "@wordpress/warning": "*", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/warning": "file:../warning", "clsx": "^2.1.1", "remove-accents": "^0.5.0" }, @@ -52405,7 +54947,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/deprecated": "*", + "@wordpress/deprecated": "file:../deprecated", "moment": "^2.29.4", "moment-timezone": "^0.5.40" }, @@ -52417,6 +54959,7 @@ "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", "version": "6.10.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "json2php": "^0.0.7" @@ -52435,7 +54978,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/hooks": "*" + "@wordpress/hooks": "file:../hooks" }, "engines": { "node": ">=18.12.0", @@ -52445,6 +54988,7 @@ "packages/docgen": { "name": "@wordpress/docgen", "version": "2.10.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -52469,7 +55013,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/deprecated": "*" + "@wordpress/deprecated": "file:../deprecated" }, "engines": { "node": ">=18.12.0", @@ -52491,12 +55035,13 @@ "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", "version": "11.10.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/keycodes": "*", - "@wordpress/url": "*", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/url": "file:../url", "change-case": "^4.1.2", "form-data": "^4.0.0", "node-fetch": "2.7.0" @@ -52513,6 +55058,7 @@ "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", "version": "1.10.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "change-case": "^4.1.2", @@ -52534,20 +55080,22 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.1.tgz", "integrity": "sha512-U6bAxeudnhDqcXNl50JC4hLlqox9DZnngxfISZm3DMZnonW35xtJOVUc091L+DOY+6hVZVpKXoiCP0RiT6339Q==", + "dev": true, "license": "Apache-2.0" }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", "version": "8.10.1", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/e2e-test-utils": "*", - "@wordpress/interactivity": "*", - "@wordpress/interactivity-router": "*", - "@wordpress/jest-console": "*", - "@wordpress/jest-puppeteer-axe": "*", - "@wordpress/scripts": "*", - "@wordpress/url": "*", + "@wordpress/e2e-test-utils": "file:../e2e-test-utils", + "@wordpress/interactivity": "file:../interactivity", + "@wordpress/interactivity-router": "file:../interactivity-router", + "@wordpress/jest-console": "file:../jest-console", + "@wordpress/jest-puppeteer-axe": "file:../jest-puppeteer-axe", + "@wordpress/scripts": "file:../scripts", + "@wordpress/url": "file:../url", "chalk": "^4.0.0", "expect-puppeteer": "^4.4.0", "filenamify": "^4.2.0", @@ -52570,6 +55118,7 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -52580,35 +55129,35 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/api-fetch": "*", - "@wordpress/block-editor": "*", - "@wordpress/block-library": "*", - "@wordpress/blocks": "*", - "@wordpress/commands": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-commands": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/editor": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/keycodes": "*", - "@wordpress/notices": "*", - "@wordpress/plugins": "*", - "@wordpress/preferences": "*", - "@wordpress/private-apis": "*", - "@wordpress/url": "*", - "@wordpress/viewport": "*", - "@wordpress/warning": "*", - "@wordpress/widgets": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/block-library": "file:../block-library", + "@wordpress/blocks": "file:../blocks", + "@wordpress/commands": "file:../commands", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-commands": "file:../core-commands", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/editor": "file:../editor", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/notices": "file:../notices", + "@wordpress/plugins": "file:../plugins", + "@wordpress/preferences": "file:../preferences", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url", + "@wordpress/viewport": "file:../viewport", + "@wordpress/warning": "file:../warning", + "@wordpress/widgets": "file:../widgets", "clsx": "^2.1.1", "memize": "^2.1.0" }, @@ -52628,45 +55177,45 @@ "dependencies": { "@babel/runtime": "7.25.7", "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "*", - "@wordpress/api-fetch": "*", - "@wordpress/blob": "*", - "@wordpress/block-editor": "*", - "@wordpress/block-library": "*", - "@wordpress/blocks": "*", - "@wordpress/commands": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-commands": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/dataviews": "*", - "@wordpress/date": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/editor": "*", - "@wordpress/element": "*", - "@wordpress/escape-html": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/keycodes": "*", - "@wordpress/notices": "*", - "@wordpress/patterns": "*", - "@wordpress/plugins": "*", - "@wordpress/preferences": "*", - "@wordpress/primitives": "*", - "@wordpress/priority-queue": "*", - "@wordpress/private-apis": "*", - "@wordpress/reusable-blocks": "*", - "@wordpress/router": "*", - "@wordpress/style-engine": "*", - "@wordpress/url": "*", - "@wordpress/viewport": "*", - "@wordpress/widgets": "*", - "@wordpress/wordcount": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blob": "file:../blob", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/block-library": "file:../block-library", + "@wordpress/blocks": "file:../blocks", + "@wordpress/commands": "file:../commands", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-commands": "file:../core-commands", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/dataviews": "file:../dataviews", + "@wordpress/date": "file:../date", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/editor": "file:../editor", + "@wordpress/element": "file:../element", + "@wordpress/escape-html": "file:../escape-html", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/notices": "file:../notices", + "@wordpress/patterns": "file:../patterns", + "@wordpress/plugins": "file:../plugins", + "@wordpress/preferences": "file:../preferences", + "@wordpress/primitives": "file:../primitives", + "@wordpress/priority-queue": "file:../priority-queue", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/reusable-blocks": "file:../reusable-blocks", + "@wordpress/router": "file:../router", + "@wordpress/style-engine": "file:../style-engine", + "@wordpress/url": "file:../url", + "@wordpress/viewport": "file:../viewport", + "@wordpress/widgets": "file:../widgets", + "@wordpress/wordcount": "file:../wordcount", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.9.2", @@ -52689,33 +55238,33 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/block-editor": "*", - "@wordpress/block-library": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/editor": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/interface": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/keycodes": "*", - "@wordpress/media-utils": "*", - "@wordpress/notices": "*", - "@wordpress/patterns": "*", - "@wordpress/plugins": "*", - "@wordpress/preferences": "*", - "@wordpress/private-apis": "*", - "@wordpress/reusable-blocks": "*", - "@wordpress/url": "*", - "@wordpress/widgets": "*", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/block-library": "file:../block-library", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/editor": "file:../editor", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/interface": "file:../interface", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/media-utils": "file:../media-utils", + "@wordpress/notices": "file:../notices", + "@wordpress/patterns": "file:../patterns", + "@wordpress/plugins": "file:../plugins", + "@wordpress/preferences": "file:../preferences", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/reusable-blocks": "file:../reusable-blocks", + "@wordpress/url": "file:../url", + "@wordpress/widgets": "file:../widgets", "clsx": "^2.1.1" }, "engines": { @@ -52733,41 +55282,41 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/api-fetch": "*", - "@wordpress/blob": "*", - "@wordpress/block-editor": "*", - "@wordpress/blocks": "*", - "@wordpress/commands": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/dataviews": "*", - "@wordpress/date": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/element": "*", - "@wordpress/fields": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/interface": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/keycodes": "*", - "@wordpress/media-utils": "*", - "@wordpress/notices": "*", - "@wordpress/patterns": "*", - "@wordpress/plugins": "*", - "@wordpress/preferences": "*", - "@wordpress/private-apis": "*", - "@wordpress/reusable-blocks": "*", - "@wordpress/rich-text": "*", - "@wordpress/server-side-render": "*", - "@wordpress/url": "*", - "@wordpress/warning": "*", - "@wordpress/wordcount": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blob": "file:../blob", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/blocks": "file:../blocks", + "@wordpress/commands": "file:../commands", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/dataviews": "file:../dataviews", + "@wordpress/date": "file:../date", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/element": "file:../element", + "@wordpress/fields": "file:../fields", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/interface": "file:../interface", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/media-utils": "file:../media-utils", + "@wordpress/notices": "file:../notices", + "@wordpress/patterns": "file:../patterns", + "@wordpress/plugins": "file:../plugins", + "@wordpress/preferences": "file:../preferences", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/reusable-blocks": "file:../reusable-blocks", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/server-side-render": "file:../server-side-render", + "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", + "@wordpress/wordcount": "file:../wordcount", "change-case": "^4.1.2", "client-zip": "^2.4.5", "clsx": "^2.1.1", @@ -52797,7 +55346,7 @@ "@babel/runtime": "7.25.7", "@types/react": "^18.2.79", "@types/react-dom": "^18.2.25", - "@wordpress/escape-html": "*", + "@wordpress/escape-html": "file:../escape-html", "change-case": "^4.1.2", "is-plain-object": "^5.0.0", "react": "^18.3.0", @@ -52811,6 +55360,7 @@ "packages/env": { "name": "@wordpress/env", "version": "10.10.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "chalk": "^4.0.0", @@ -52838,6 +55388,7 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -52851,6 +55402,7 @@ "version": "0.24.2", "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.24.2.tgz", "integrity": "sha512-2/WLvA7UZ6A2LDLQrYW0idKipmNBWhtfvrn2yzjC5PnHDzuFVj1zAZN6MJxVMKP0zZH8uzAK6OwVZYHGuyCmTw==", + "dev": true, "dependencies": { "yaml": "^2.2.2" }, @@ -52861,12 +55413,14 @@ "packages/env/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "packages/env/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -52875,6 +55429,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -52888,6 +55443,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -52903,12 +55459,14 @@ "packages/env/node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true }, "packages/env/node_modules/yaml": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", - "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "dev": true, "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -52921,6 +55479,7 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -52937,7 +55496,8 @@ "packages/env/node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true }, "packages/escape-html": { "name": "@wordpress/escape-html", @@ -52954,13 +55514,14 @@ "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", "version": "21.3.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/eslint-parser": "7.25.7", "@typescript-eslint/eslint-plugin": "^6.4.1", "@typescript-eslint/parser": "^6.4.1", - "@wordpress/babel-preset-default": "*", - "@wordpress/prettier-config": "*", + "@wordpress/babel-preset-default": "file:../babel-preset-default", + "@wordpress/prettier-config": "file:../prettier-config", "cosmiconfig": "^7.0.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.2", @@ -52997,6 +55558,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.7.tgz", "integrity": "sha512-B+BO9x86VYsQHimucBAL1fxTJKF4wyKY6ZVzee9QgzdZOUfs3BaR6AQrgoGrRI+7IFS1wUz/VyQ+SoBcSpdPbw==", + "dev": true, "license": "MIT", "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", @@ -53015,6 +55577,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -53026,25 +55589,25 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/blob": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/dataviews": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/notices": "*", - "@wordpress/patterns": "*", - "@wordpress/primitives": "*", - "@wordpress/private-apis": "*", - "@wordpress/url": "*", - "@wordpress/warning": "*", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blob": "file:../blob", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/dataviews": "file:../dataviews", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/patterns": "file:../patterns", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", "change-case": "4.1.2", "client-zip": "^2.4.5" }, @@ -53062,18 +55625,18 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/block-editor": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/private-apis": "*", - "@wordpress/rich-text": "*", - "@wordpress/url": "*" + "@wordpress/a11y": "file:../a11y", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/url": "file:../url" }, "engines": { "node": ">=18.12.0", @@ -53114,7 +55677,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/hooks": "*", + "@wordpress/hooks": "file:../hooks", "gettext-parser": "^1.3.1", "memize": "^2.1.0", "sprintf-js": "^1.1.1", @@ -53134,8 +55697,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "*", - "@wordpress/primitives": "*" + "@wordpress/element": "file:../element", + "@wordpress/primitives": "file:../primitives" }, "engines": { "node": ">=18.12.0", @@ -53160,8 +55723,8 @@ "version": "2.10.0", "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/a11y": "*", - "@wordpress/interactivity": "*" + "@wordpress/a11y": "file:../a11y", + "@wordpress/interactivity": "file:../interactivity" }, "engines": { "node": ">=18.12.0", @@ -53174,18 +55737,18 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/plugins": "*", - "@wordpress/preferences": "*", - "@wordpress/private-apis": "*", - "@wordpress/viewport": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/plugins": "file:../plugins", + "@wordpress/preferences": "file:../preferences", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/viewport": "file:../viewport", "clsx": "^2.1.1" }, "engines": { @@ -53212,6 +55775,7 @@ "packages/jest-console": { "name": "@wordpress/jest-console", "version": "8.10.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53228,9 +55792,10 @@ "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", "version": "12.10.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/jest-console": "*", + "@wordpress/jest-console": "file:../jest-console", "babel-jest": "29.7.0" }, "engines": { @@ -53245,6 +55810,7 @@ "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", "version": "7.10.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@axe-core/puppeteer": "^4.0.0", @@ -53270,9 +55836,9 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/keycodes": "*" + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/keycodes": "file:../keycodes" }, "engines": { "node": ">=18.12.0", @@ -53288,7 +55854,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/i18n": "*" + "@wordpress/i18n": "file:../i18n" }, "engines": { "node": ">=18.12.0", @@ -53298,6 +55864,7 @@ "packages/lazy-import": { "name": "@wordpress/lazy-import", "version": "2.10.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "execa": "^4.0.2", @@ -53315,12 +55882,12 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/blob": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blob": "file:../blob", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", "change-case": "^4.1.2" }, "engines": { @@ -53338,10 +55905,10 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/blob": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*" + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blob": "file:../blob", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n" }, "engines": { "node": ">=18.12.0", @@ -53354,8 +55921,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/data": "*" + "@wordpress/a11y": "file:../a11y", + "@wordpress/data": "file:../data" }, "engines": { "node": ">=18.12.0", @@ -53368,6 +55935,7 @@ "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", "version": "5.10.0", + "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53383,13 +55951,13 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*" + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons" }, "engines": { "node": ">=18.12.0", @@ -53406,20 +55974,20 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/block-editor": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/notices": "*", - "@wordpress/private-apis": "*", - "@wordpress/url": "*" + "@wordpress/a11y": "file:../a11y", + "@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/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url" }, "engines": { "node": ">=18.12.0", @@ -53436,12 +56004,12 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/icons": "*", - "@wordpress/is-shallow-equal": "*", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/icons": "file:../icons", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", "memize": "^2.0.1" }, "engines": { @@ -53456,9 +56024,10 @@ "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", "version": "5.10.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/base-styles": "*", + "@wordpress/base-styles": "file:../base-styles", "autoprefixer": "^10.2.5" }, "engines": { @@ -53472,6 +56041,7 @@ "packages/postcss-themes": { "name": "@wordpress/postcss-themes", "version": "6.10.0", + "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53487,15 +56057,15 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/private-apis": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/private-apis": "file:../private-apis", "clsx": "^2.1.1" }, "engines": { @@ -53513,7 +56083,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*" + "@wordpress/api-fetch": "file:../api-fetch" }, "engines": { "node": ">=18.12.0", @@ -53523,6 +56093,7 @@ "packages/prettier-config": { "name": "@wordpress/prettier-config", "version": "4.10.0", + "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53538,7 +56109,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "*", + "@wordpress/element": "file:../element", "clsx": "^2.1.1" }, "engines": { @@ -53577,6 +56148,7 @@ "packages/project-management-automation": { "name": "@wordpress/project-management-automation", "version": "2.10.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@actions/core": "1.9.1", @@ -53594,6 +56166,7 @@ "version": "9.26.3", "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.26.3.tgz", "integrity": "sha512-DLGk+gzeVq5oK89Bo601txYmyrelMQ7Fi5EnjHE0Xs8CWicy2xkmnJMKptKJrBJpstqbd/9oeDFi/Zj2pudBDQ==", + "dev": true, "license": "MIT", "dependencies": { "@octokit/request-error": "^2.0.2", @@ -53608,8 +56181,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "*", - "@wordpress/i18n": "*", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", "utility-types": "^3.10.0" }, "engines": { @@ -53622,8 +56195,8 @@ "version": "1.121.0", "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/element": "*", - "@wordpress/keycodes": "*" + "@wordpress/element": "file:../element", + "@wordpress/keycodes": "file:../keycodes" }, "engines": { "node": ">=18.12.0", @@ -53639,7 +56212,7 @@ "version": "1.121.0", "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/react-native-aztec": "*" + "@wordpress/react-native-aztec": "file:../react-native-aztec" }, "engines": { "node": ">=18.12.0", @@ -53664,18 +56237,18 @@ "@react-navigation/native": "6.0.14", "@react-navigation/routers": "5.4.9", "@react-navigation/stack": "6.3.5", - "@wordpress/api-fetch": "*", - "@wordpress/block-editor": "*", - "@wordpress/block-library": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/data": "*", - "@wordpress/edit-post": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/i18n": "*", - "@wordpress/react-native-aztec": "*", - "@wordpress/react-native-bridge": "*", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/block-library": "file:../block-library", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/data": "file:../data", + "@wordpress/edit-post": "file:../edit-post", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/i18n": "file:../i18n", + "@wordpress/react-native-aztec": "file:../react-native-aztec", + "@wordpress/react-native-bridge": "file:../react-native-bridge", "core-js": "^3.31.0", "fast-average-color": "^9.1.1", "gettext-parser": "^1.3.1", @@ -53761,6 +56334,7 @@ "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", "version": "3.10.0", + "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53791,6 +56365,7 @@ "packages/report-flaky-tests": { "name": "@wordpress/report-flaky-tests", "version": "0.0.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@actions/core": "^1.8.0", @@ -53806,6 +56381,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz", "integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==", + "dev": true, "dependencies": { "@actions/http-client": "^2.0.1", "@octokit/core": "^3.6.0", @@ -53819,17 +56395,17 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/notices": "*", - "@wordpress/private-apis": "*", - "@wordpress/url": "*" + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url" }, "engines": { "node": ">=18.12.0", @@ -53846,14 +56422,14 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/element": "*", - "@wordpress/escape-html": "*", - "@wordpress/i18n": "*", - "@wordpress/keycodes": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/element": "file:../element", + "@wordpress/escape-html": "file:../escape-html", + "@wordpress/i18n": "file:../i18n", + "@wordpress/keycodes": "file:../keycodes", "memize": "^2.1.0" }, "engines": { @@ -53870,9 +56446,9 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "*", - "@wordpress/private-apis": "*", - "@wordpress/url": "*", + "@wordpress/element": "file:../element", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url", "history": "^5.3.0" }, "engines": { @@ -53886,21 +56462,22 @@ "packages/scripts": { "name": "@wordpress/scripts", "version": "30.3.0", + "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", "@svgr/webpack": "^8.0.1", - "@wordpress/babel-preset-default": "*", - "@wordpress/browserslist-config": "*", - "@wordpress/dependency-extraction-webpack-plugin": "*", - "@wordpress/e2e-test-utils-playwright": "*", - "@wordpress/eslint-plugin": "*", - "@wordpress/jest-preset-default": "*", - "@wordpress/npm-package-json-lint-config": "*", - "@wordpress/postcss-plugins-preset": "*", - "@wordpress/prettier-config": "*", - "@wordpress/stylelint-config": "*", + "@wordpress/babel-preset-default": "file:../babel-preset-default", + "@wordpress/browserslist-config": "file:../browserslist-config", + "@wordpress/dependency-extraction-webpack-plugin": "file:../dependency-extraction-webpack-plugin", + "@wordpress/e2e-test-utils-playwright": "file:../e2e-test-utils-playwright", + "@wordpress/eslint-plugin": "file:../eslint-plugin", + "@wordpress/jest-preset-default": "file:../jest-preset-default", + "@wordpress/npm-package-json-lint-config": "file:../npm-package-json-lint-config", + "@wordpress/postcss-plugins-preset": "file:../postcss-plugins-preset", + "@wordpress/prettier-config": "file:../prettier-config", + "@wordpress/stylelint-config": "file:../stylelint-config", "adm-zip": "^0.5.9", "babel-jest": "29.7.0", "babel-loader": "9.2.1", @@ -53967,6 +56544,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -53983,6 +56561,7 @@ "version": "1.7.7", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "dev": true, "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -53994,6 +56573,7 @@ "version": "8.4.1", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.4.1.tgz", "integrity": "sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==", + "dev": true, "license": "MIT", "dependencies": { "find-cache-dir": "^3.3.1", @@ -54013,6 +56593,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -54029,12 +56610,14 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, "license": "MIT" }, "packages/scripts/node_modules/babel-loader/node_modules/schema-utils": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.5", @@ -54053,6 +56636,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -54068,6 +56652,7 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", @@ -54084,6 +56669,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -54096,6 +56682,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -54104,6 +56691,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/jest-dev-server/-/jest-dev-server-9.0.1.tgz", "integrity": "sha512-eqpJKSvVl4M0ojHZUPNbka8yEzLNbIMiINXDsuMF3lYfIdRO2iPqy+ASR4wBQ6nUyR3OT24oKPWhpsfLhgAVyg==", + "dev": true, "dependencies": { "chalk": "^4.1.2", "cwd": "^0.10.0", @@ -54121,6 +56709,7 @@ "version": "17.11.0", "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", + "dev": true, "dependencies": { "@hapi/hoek": "^9.0.0", "@hapi/topo": "^5.0.0", @@ -54133,18 +56722,21 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, "license": "MIT" }, "packages/scripts/node_modules/json2php": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/json2php/-/json2php-0.0.9.tgz", "integrity": "sha512-fQMYwvPsQt8hxRnCGyg1r2JVi6yL8Um0DIIawiKiMK9yhAAkcRNj5UsBWoaFvFzPpcWbgw9L6wzj+UMYA702Mw==", + "dev": true, "license": "BSD" }, "packages/scripts/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -54156,6 +56748,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, "dependencies": { "semver": "^6.0.0" }, @@ -54170,6 +56763,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -54184,6 +56778,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -54195,6 +56790,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, "engines": { "node": ">=6" } @@ -54203,6 +56799,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "engines": { "node": ">=8" } @@ -54211,6 +56808,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, "dependencies": { "find-up": "^4.0.0" }, @@ -54222,6 +56820,7 @@ "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, "dependencies": { "tslib": "^2.1.0" } @@ -54230,6 +56829,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", @@ -54249,6 +56849,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" @@ -54261,6 +56862,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -54269,6 +56871,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, "engines": { "node": ">=14" }, @@ -54280,6 +56883,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-9.0.1.tgz", "integrity": "sha512-vaMk8E9CpbjTYToBxLXowDeArGf1+yI7A6PU6Nr57b2g8BVY8nRi5vTBj3bMF8UkCrMdTMyf/Lh+lrcrW2z7pw==", + "dev": true, "dependencies": { "signal-exit": "^4.1.0", "tree-kill": "^1.2.2" @@ -54292,6 +56896,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -54303,6 +56908,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.2.0.tgz", "integrity": "sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ==", + "dev": true, "dependencies": { "axios": "^1.6.1", "joi": "^17.11.0", @@ -54323,15 +56929,15 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/url": "*", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/url": "file:../url", "fast-deep-equal": "^3.1.3" }, "engines": { @@ -54372,6 +56978,7 @@ "packages/stylelint-config": { "name": "@wordpress/stylelint-config", "version": "23.2.0", + "dev": true, "license": "MIT", "dependencies": { "@stylistic/stylelint-plugin": "^3.0.1", @@ -54390,6 +56997,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -54401,17 +57009,20 @@ "packages/stylelint-config/node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true }, "packages/stylelint-config/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "packages/stylelint-config/node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -54421,6 +57032,7 @@ "version": "14.0.1", "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", + "dev": true, "funding": [ { "type": "opencollective", @@ -54442,6 +57054,7 @@ "version": "14.1.0", "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.1.0.tgz", "integrity": "sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg==", + "dev": true, "dependencies": { "postcss-scss": "^4.0.9", "stylelint-config-recommended": "^14.0.1", @@ -54464,6 +57077,7 @@ "version": "6.5.1", "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.5.1.tgz", "integrity": "sha512-ZLqdqihm6uDYkrsOeD6YWb+stZI8Wn92kUNDhE4M+g9g1aCnRv0JlOrttFiAJJwaNzpdQgX3YJb5vDQXVuO9Ww==", + "dev": true, "dependencies": { "css-tree": "2.3.1", "is-plain-object": "5.0.0", @@ -54487,7 +57101,7 @@ "dependencies": { "@babel/runtime": "7.25.7", "@types/simple-peer": "^9.11.5", - "@wordpress/url": "*", + "@wordpress/url": "file:../url", "import-locals": "^2.0.0", "lib0": "^0.2.42", "simple-peer": "^9.11.0", @@ -54519,7 +57133,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/is-shallow-equal": "*" + "@wordpress/is-shallow-equal": "file:../is-shallow-equal" }, "engines": { "node": ">=18.12.0", @@ -54545,9 +57159,9 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/element": "*" + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element" }, "engines": { "node": ">=18.12.0", @@ -54572,17 +57186,17 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/block-editor": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/notices": "*", + "@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/notices": "file:../notices", "clsx": "^2.1.1" }, "engines": { diff --git a/package.json b/package.json index caa3edb410283f..8be1e9cbe3f3a0 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,80 @@ "config": { "IS_GUTENBERG_PLUGIN": true }, + "dependencies": { + "@wordpress/a11y": "file:packages/a11y", + "@wordpress/annotations": "file:packages/annotations", + "@wordpress/api-fetch": "file:packages/api-fetch", + "@wordpress/autop": "file:packages/autop", + "@wordpress/blob": "file:packages/blob", + "@wordpress/block-directory": "file:packages/block-directory", + "@wordpress/block-editor": "file:packages/block-editor", + "@wordpress/block-library": "file:packages/block-library", + "@wordpress/block-serialization-default-parser": "file:packages/block-serialization-default-parser", + "@wordpress/block-serialization-spec-parser": "file:packages/block-serialization-spec-parser", + "@wordpress/blocks": "file:packages/blocks", + "@wordpress/commands": "file:packages/commands", + "@wordpress/components": "file:packages/components", + "@wordpress/compose": "file:packages/compose", + "@wordpress/core-commands": "file:packages/core-commands", + "@wordpress/core-data": "file:packages/core-data", + "@wordpress/customize-widgets": "file:packages/customize-widgets", + "@wordpress/data": "file:packages/data", + "@wordpress/data-controls": "file:packages/data-controls", + "@wordpress/dataviews": "file:packages/dataviews", + "@wordpress/date": "file:packages/date", + "@wordpress/deprecated": "file:packages/deprecated", + "@wordpress/dom": "file:packages/dom", + "@wordpress/dom-ready": "file:packages/dom-ready", + "@wordpress/edit-post": "file:packages/edit-post", + "@wordpress/edit-site": "file:packages/edit-site", + "@wordpress/edit-widgets": "file:packages/edit-widgets", + "@wordpress/editor": "file:packages/editor", + "@wordpress/element": "file:packages/element", + "@wordpress/escape-html": "file:packages/escape-html", + "@wordpress/fields": "file:packages/fields", + "@wordpress/format-library": "file:packages/format-library", + "@wordpress/hooks": "file:packages/hooks", + "@wordpress/html-entities": "file:packages/html-entities", + "@wordpress/i18n": "file:packages/i18n", + "@wordpress/icons": "file:packages/icons", + "@wordpress/interactivity": "file:packages/interactivity", + "@wordpress/interactivity-router": "file:packages/interactivity-router", + "@wordpress/interface": "file:packages/interface", + "@wordpress/is-shallow-equal": "file:packages/is-shallow-equal", + "@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts", + "@wordpress/keycodes": "file:packages/keycodes", + "@wordpress/list-reusable-blocks": "file:packages/list-reusable-blocks", + "@wordpress/media-utils": "file:packages/media-utils", + "@wordpress/notices": "file:packages/notices", + "@wordpress/nux": "file:packages/nux", + "@wordpress/patterns": "file:packages/patterns", + "@wordpress/plugins": "file:packages/plugins", + "@wordpress/preferences": "file:packages/preferences", + "@wordpress/preferences-persistence": "file:packages/preferences-persistence", + "@wordpress/primitives": "file:packages/primitives", + "@wordpress/priority-queue": "file:packages/priority-queue", + "@wordpress/private-apis": "file:packages/private-apis", + "@wordpress/react-i18n": "file:packages/react-i18n", + "@wordpress/react-native-aztec": "file:packages/react-native-aztec", + "@wordpress/react-native-bridge": "file:packages/react-native-bridge", + "@wordpress/react-native-editor": "file:packages/react-native-editor", + "@wordpress/redux-routine": "file:packages/redux-routine", + "@wordpress/reusable-blocks": "file:packages/reusable-blocks", + "@wordpress/rich-text": "file:packages/rich-text", + "@wordpress/router": "file:packages/router", + "@wordpress/server-side-render": "file:packages/server-side-render", + "@wordpress/shortcode": "file:packages/shortcode", + "@wordpress/style-engine": "file:packages/style-engine", + "@wordpress/sync": "file:packages/sync", + "@wordpress/token-list": "file:packages/token-list", + "@wordpress/undo-manager": "file:packages/undo-manager", + "@wordpress/url": "file:packages/url", + "@wordpress/viewport": "file:packages/viewport", + "@wordpress/warning": "file:packages/warning", + "@wordpress/widgets": "file:packages/widgets", + "@wordpress/wordcount": "file:packages/wordcount" + }, "devDependencies": { "@actions/core": "1.9.1", "@actions/github": "5.0.0", @@ -70,6 +144,33 @@ "@types/semver": "7.3.8", "@types/sprintf-js": "1.1.2", "@types/uuid": "8.3.1", + "@wordpress/babel-plugin-import-jsx-pragma": "file:packages/babel-plugin-import-jsx-pragma", + "@wordpress/babel-plugin-makepot": "file:packages/babel-plugin-makepot", + "@wordpress/babel-preset-default": "file:packages/babel-preset-default", + "@wordpress/base-styles": "file:packages/base-styles", + "@wordpress/browserslist-config": "file:packages/browserslist-config", + "@wordpress/create-block": "file:packages/create-block", + "@wordpress/create-block-tutorial-template": "file:packages/create-block-tutorial-template", + "@wordpress/dependency-extraction-webpack-plugin": "file:packages/dependency-extraction-webpack-plugin", + "@wordpress/docgen": "file:packages/docgen", + "@wordpress/e2e-test-utils": "file:packages/e2e-test-utils", + "@wordpress/e2e-test-utils-playwright": "file:packages/e2e-test-utils-playwright", + "@wordpress/e2e-tests": "file:packages/e2e-tests", + "@wordpress/env": "file:packages/env", + "@wordpress/eslint-plugin": "file:packages/eslint-plugin", + "@wordpress/jest-console": "file:packages/jest-console", + "@wordpress/jest-preset-default": "file:packages/jest-preset-default", + "@wordpress/jest-puppeteer-axe": "file:packages/jest-puppeteer-axe", + "@wordpress/lazy-import": "file:packages/lazy-import", + "@wordpress/npm-package-json-lint-config": "file:packages/npm-package-json-lint-config", + "@wordpress/postcss-plugins-preset": "file:packages/postcss-plugins-preset", + "@wordpress/postcss-themes": "file:packages/postcss-themes", + "@wordpress/prettier-config": "file:packages/prettier-config", + "@wordpress/project-management-automation": "file:packages/project-management-automation", + "@wordpress/readable-js-assets-webpack-plugin": "file:packages/readable-js-assets-webpack-plugin", + "@wordpress/report-flaky-tests": "file:packages/report-flaky-tests", + "@wordpress/scripts": "file:packages/scripts", + "@wordpress/stylelint-config": "file:packages/stylelint-config", "ajv": "8.7.1", "appium": "2.0.0", "babel-jest": "29.7.0", @@ -173,7 +274,7 @@ "build": "npm run build:packages && wp-scripts build", "build:analyze-bundles": "npm run build -- --webpack-bundle-analyzer", "build:package-types": "node ./bin/packages/validate-typescript-version.js && ( tsc --build || ( echo 'tsc failed. Try cleaning up first: `npm run clean:package-types`'; exit 1 ) ) && node ./bin/packages/check-build-type-declaration-files.js", - "prebuild:packages": "npm run clean:packages && npm run --if-present --workspaces build", + "prebuild:packages": "npm run clean:packages && lerna run build", "build:packages": "npm run --silent build:package-types && node ./bin/packages/build.js", "build:plugin-zip": "bash ./bin/build-plugin-zip.sh", "clean:package-types": "tsc --build --clean && rimraf \"./packages/*/build-types\"", @@ -207,7 +308,7 @@ "lint:pkg-json": "wp-scripts lint-pkg-json . 'packages/*/package.json'", "native": "npm run --prefix packages/react-native-editor", "other:changelog": "node ./bin/plugin/cli.js changelog", - "other:check-licenses": "concurrently \"node ./bin/check-licenses.mjs\" \"wp-scripts check-licenses --dev\"", + "other:check-licenses": "concurrently \"wp-scripts check-licenses --prod --gpl2 --ignore=@react-native-community/cli,@react-native-community/cli-platform-ios,@ampproject/remapping,human-signals,fb-watchman,walker,chrome-launcher,lighthouse-logger,chromium-edge-launcher\" \"wp-scripts check-licenses --dev\"", "preother:check-local-changes": "npm run docs:build", "other:check-local-changes": "node ./bin/check-local-changes.js", "other:cherry-pick": "node ./bin/cherry-pick.mjs", @@ -286,8 +387,5 @@ "**/tsconfig.json": [ "npm run lint:tsconfig" ] - }, - "workspaces": [ - "packages/*" - ] + } } diff --git a/packages/README.md b/packages/README.md index 27efdf2d43ad52..0b131f6c404d4e 100644 --- a/packages/README.md +++ b/packages/README.md @@ -1,6 +1,6 @@ # Managing Packages -This repository uses [npm workspaces](https://docs.npmjs.com/cli/v10/using-npm/workspaces) to manage WordPress packages and [lerna](https://lerna.js.org/) to publish them with to [npm](https://www.npmjs.com/). +This repository uses [monorepo] to manage WordPress modules and publish them with [lerna] as packages to [npm]. ## Creating a New Package @@ -36,7 +36,11 @@ When creating a new package, you need to provide at least the following: } ``` This assumes that your code is located in the `src` folder and will be transpiled with `Babel`. -1. `README.md` file containing at least: +2. `.npmrc` file which disables creating `package-lock.json` file for the package: + ``` + package-lock=false + ``` +3. `README.md` file containing at least: - Package name - Package description - Installation details @@ -44,7 +48,7 @@ When creating a new package, you need to provide at least the following: - API documentation, if applicable ([more info](#maintaining-api-documentation)) - A link to the contributing guidelines ([here's an example](https://github.com/WordPress/gutenberg/tree/HEAD/packages/a11y/README.md#contributing-to-this-package) from the a11y package) - `Code is Poetry` logo (`<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p>`) -1. `CHANGELOG.md` file containing at least: +4. `CHANGELOG.md` file containing at least: ``` <!-- Learn how to maintain this file at https://github.com/WordPress/gutenberg/tree/HEAD/packages#maintaining-changelogs. --> @@ -66,32 +70,35 @@ Production dependencies are stored in the `dependencies` section of the package #### Adding New Dependencies -The simplest way to add a production dependency to one of the packages is to run a command like the following from the root of the project. +The simplest way to add a production dependency to one of the packages is to run a very convenient [lerna add](https://github.com/lerna/lerna/tree/HEAD/commands/add#readme) command from the root of the project. _Example:_ ```bash -npm install change-case -w packages/a11y +lerna add change-case packages/a11y ``` -This command adds the `change-case` as a dependency to the `@wordpress/a11y` package, which is located in `packages/a11y` folder. If there was the same dependency installed then the version specified in the `package-lock.json` file is going to be reused. If you want to enforce a different version, you can do so by adding the `@` suffix to the package name. - -_Example:_ - -```bash -npm install change-case@latest -w packages/a11y -``` +This command adds the latest version of `change-case` as a dependency to the `@wordpress/a11y` package, which is located in `packages/a11y` folder. #### Removing Existing Dependencies -Removing a dependency from one of the WordPress packages is similar to installation. You need to run a command like the following from the root of the project. +Removing a dependency from one of the WordPress packages requires some manual work. You need to remove the line in the corresponding `dependencies` section of the `package.json` file. _Example:_ -```bash -npm uninstall change-case -w packages/a11y +```diff ++++ b/packages/scripts/package.json +@@ -43,7 +43,6 @@ + "check-node-version": "^4.1.0", + "cross-spawn": "^5.1.0", + "eslint": "^7.1.0", +- "jest": "^29.6.2", + "minimist": "^1.2.0", + "npm-package-json-lint": "^6.4.0", ``` +Next, you need to run `npm install` in the root of the project to ensure that `package-lock.json` file gets properly regenerated. + #### Updating Existing Dependencies This is the most confusing part of working with [monorepo] which causes a lot of hassles for contributors. The most successful strategy so far is to do the following: @@ -232,6 +239,10 @@ For consumers to use the published type declarations, we'll set the `types` fiel Ensure that the `build-types` directory will be included in the published package, for example if a `files` field is declared. +[lerna]: https://lerna.js.org/ +[monorepo]: https://monorepo.tools +[npm]: https://www.npmjs.com/ + ## Optimizing for bundlers In order for bundlers to tree-shake packages effectively, they often need to know whether a package includes side effects in its code. This is done through the `sideEffects` field in the package's `package.json`. diff --git a/packages/a11y/.npmrc b/packages/a11y/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/a11y/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/a11y/package.json b/packages/a11y/package.json index a506cb940e7765..230005587619f3 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -31,11 +31,10 @@ "wpScriptModuleExports": "./build-module/module/index.js", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/dom-ready": "*", - "@wordpress/i18n": "*" + "@wordpress/dom-ready": "file:../dom-ready", + "@wordpress/i18n": "file:../i18n" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/annotations/.npmrc b/packages/annotations/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/annotations/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 4a1f0fe2b771b5..259745c3fd82e2 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -27,10 +27,10 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/data": "*", - "@wordpress/hooks": "*", - "@wordpress/i18n": "*", - "@wordpress/rich-text": "*", + "@wordpress/data": "file:../data", + "@wordpress/hooks": "file:../hooks", + "@wordpress/i18n": "file:../i18n", + "@wordpress/rich-text": "file:../rich-text", "uuid": "^9.0.1" }, "peerDependencies": { @@ -38,6 +38,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/api-fetch/.npmrc b/packages/api-fetch/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/api-fetch/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 79968c31d1043a..35fb2da0ec1aad 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -29,11 +29,10 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/i18n": "*", - "@wordpress/url": "*" + "@wordpress/i18n": "file:../i18n", + "@wordpress/url": "file:../url" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/autop/.npmrc b/packages/autop/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/autop/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/autop/package.json b/packages/autop/package.json index aea14b2c666e14..9e2b61ad211cff 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -32,6 +32,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/babel-plugin-import-jsx-pragma/.npmrc b/packages/babel-plugin-import-jsx-pragma/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/babel-plugin-import-jsx-pragma/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/babel-plugin-makepot/.npmrc b/packages/babel-plugin-makepot/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/babel-plugin-makepot/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/babel-preset-default/.npmrc b/packages/babel-preset-default/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/babel-preset-default/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 777a40012d67f7..fb8ae826e55978 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -38,8 +38,8 @@ "@babel/preset-env": "7.25.7", "@babel/preset-typescript": "7.25.7", "@babel/runtime": "7.25.7", - "@wordpress/browserslist-config": "*", - "@wordpress/warning": "*", + "@wordpress/browserslist-config": "file:../browserslist-config", + "@wordpress/warning": "file:../warning", "browserslist": "^4.21.10", "core-js": "^3.31.0", "react": "^18.3.0" diff --git a/packages/base-styles/.npmrc b/packages/base-styles/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/base-styles/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/blob/.npmrc b/packages/blob/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/blob/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/blob/package.json b/packages/blob/package.json index 183e6aca33dc0c..087343d1b33a04 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -32,6 +32,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/block-directory/.npmrc b/packages/block-directory/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/block-directory/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 6ff9ad7d510861..0b72a7ff2099a1 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -27,24 +27,24 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/api-fetch": "*", - "@wordpress/block-editor": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/editor": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/notices": "*", - "@wordpress/plugins": "*", - "@wordpress/private-apis": "*", - "@wordpress/url": "*", + "@wordpress/a11y": "file:../a11y", + "@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/editor": "file:../editor", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/plugins": "file:../plugins", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url", "change-case": "^4.1.2", "clsx": "^2.1.1" }, @@ -54,6 +54,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/block-editor/.npmrc b/packages/block-editor/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/block-editor/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index b798e626c2e90f..92392b4d9563b2 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -36,36 +36,36 @@ "@emotion/react": "^11.7.1", "@emotion/styled": "^11.6.0", "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "*", - "@wordpress/api-fetch": "*", - "@wordpress/blob": "*", - "@wordpress/block-serialization-default-parser": "*", - "@wordpress/blocks": "*", - "@wordpress/commands": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/date": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/element": "*", - "@wordpress/escape-html": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/is-shallow-equal": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/keycodes": "*", - "@wordpress/notices": "*", - "@wordpress/preferences": "*", - "@wordpress/private-apis": "*", - "@wordpress/rich-text": "*", - "@wordpress/style-engine": "*", - "@wordpress/token-list": "*", - "@wordpress/url": "*", - "@wordpress/warning": "*", - "@wordpress/wordcount": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blob": "file:../blob", + "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", + "@wordpress/blocks": "file:../blocks", + "@wordpress/commands": "file:../commands", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/date": "file:../date", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/element": "file:../element", + "@wordpress/escape-html": "file:../escape-html", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/notices": "file:../notices", + "@wordpress/preferences": "file:../preferences", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/style-engine": "file:../style-engine", + "@wordpress/token-list": "file:../token-list", + "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", + "@wordpress/wordcount": "file:../wordcount", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -87,6 +87,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/block-library/.npmrc b/packages/block-library/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/block-library/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 18ad0e46059c91..e9e76b8018e1d3 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -39,39 +39,39 @@ }, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/api-fetch": "*", - "@wordpress/autop": "*", - "@wordpress/blob": "*", - "@wordpress/block-editor": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/date": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/element": "*", - "@wordpress/escape-html": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/interactivity": "*", - "@wordpress/interactivity-router": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/keycodes": "*", - "@wordpress/notices": "*", - "@wordpress/patterns": "*", - "@wordpress/primitives": "*", - "@wordpress/private-apis": "*", - "@wordpress/reusable-blocks": "*", - "@wordpress/rich-text": "*", - "@wordpress/server-side-render": "*", - "@wordpress/url": "*", - "@wordpress/viewport": "*", - "@wordpress/wordcount": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/autop": "file:../autop", + "@wordpress/blob": "file:../blob", + "@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/date": "file:../date", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/element": "file:../element", + "@wordpress/escape-html": "file:../escape-html", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/interactivity": "file:../interactivity", + "@wordpress/interactivity-router": "file:../interactivity-router", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/notices": "file:../notices", + "@wordpress/patterns": "file:../patterns", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/reusable-blocks": "file:../reusable-blocks", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/server-side-render": "file:../server-side-render", + "@wordpress/url": "file:../url", + "@wordpress/viewport": "file:../viewport", + "@wordpress/wordcount": "file:../wordcount", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -88,6 +88,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/block-serialization-default-parser/.npmrc b/packages/block-serialization-default-parser/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/block-serialization-default-parser/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 14d2db0f688688..3b159dc3534888 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -33,6 +33,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/block-serialization-spec-parser/.npmrc b/packages/block-serialization-spec-parser/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/block-serialization-spec-parser/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 9a871250162ca0..49c3ed6c872c73 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -37,6 +37,5 @@ "build": "concurrently \"npm run build:js\" \"npm run build:php\"", "build:js": "pegjs --format commonjs -o ./parser.js ./grammar.pegjs", "build:php": "node bin/create-php-parser.js" - }, - "wpScript": true + } } diff --git a/packages/blocks/.npmrc b/packages/blocks/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/blocks/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/blocks/package.json b/packages/blocks/package.json index d7207548d173fc..9b7665ae9c87d6 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -30,21 +30,21 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/autop": "*", - "@wordpress/blob": "*", - "@wordpress/block-serialization-default-parser": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/is-shallow-equal": "*", - "@wordpress/private-apis": "*", - "@wordpress/rich-text": "*", - "@wordpress/shortcode": "*", - "@wordpress/warning": "*", + "@wordpress/autop": "file:../autop", + "@wordpress/blob": "file:../blob", + "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/shortcode": "file:../shortcode", + "@wordpress/warning": "file:../warning", "change-case": "^4.1.2", "colord": "^2.7.0", "fast-deep-equal": "^3.1.3", @@ -62,6 +62,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/browserslist-config/.npmrc b/packages/browserslist-config/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/browserslist-config/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/commands/.npmrc b/packages/commands/.npmrc new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/packages/commands/package.json b/packages/commands/package.json index 4d35172ce8186d..e1529416aa7df7 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -28,13 +28,13 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "*", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/private-apis": "*", + "@wordpress/components": "file:../components", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/private-apis": "file:../private-apis", "clsx": "^2.1.1", "cmdk": "^1.0.0" }, @@ -44,6 +44,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/components/.npmrc b/packages/components/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/components/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/components/package.json b/packages/components/package.json index a44e0afe89152b..16c7b6c63c0b18 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -43,23 +43,23 @@ "@types/gradient-parser": "0.1.3", "@types/highlight-words-core": "1.2.1", "@use-gesture/react": "^10.3.1", - "@wordpress/a11y": "*", - "@wordpress/compose": "*", - "@wordpress/date": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/element": "*", - "@wordpress/escape-html": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/is-shallow-equal": "*", - "@wordpress/keycodes": "*", - "@wordpress/primitives": "*", - "@wordpress/private-apis": "*", - "@wordpress/rich-text": "*", - "@wordpress/warning": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/compose": "file:../compose", + "@wordpress/date": "file:../date", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/element": "file:../element", + "@wordpress/escape-html": "file:../escape-html", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/warning": "file:../warning", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -83,6 +83,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/compose/.npmrc b/packages/compose/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/compose/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/compose/package.json b/packages/compose/package.json index f7aa8a3bf9b3bc..d1eacfd72f0d86 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -32,13 +32,13 @@ "dependencies": { "@babel/runtime": "7.25.7", "@types/mousetrap": "^1.6.8", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/element": "*", - "@wordpress/is-shallow-equal": "*", - "@wordpress/keycodes": "*", - "@wordpress/priority-queue": "*", - "@wordpress/undo-manager": "*", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/element": "file:../element", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/priority-queue": "file:../priority-queue", + "@wordpress/undo-manager": "file:../undo-manager", "change-case": "^4.1.2", "clipboard": "^2.0.11", "mousetrap": "^1.6.5", @@ -49,6 +49,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/core-commands/.npmrc b/packages/core-commands/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/core-commands/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index adad0ee55afc23..87dc4fb3722f50 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -28,19 +28,19 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "*", - "@wordpress/commands": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/notices": "*", - "@wordpress/private-apis": "*", - "@wordpress/router": "*", - "@wordpress/url": "*" + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/commands": "file:../commands", + "@wordpress/compose": "file:../compose", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/router": "file:../router", + "@wordpress/url": "file:../url" }, "peerDependencies": { "react": "^18.0.0", @@ -48,6 +48,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/core-data/.npmrc b/packages/core-data/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/core-data/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 6b70fb0af3a8f4..cd568cc60c596b 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -32,22 +32,22 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/block-editor": "*", - "@wordpress/blocks": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/element": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/is-shallow-equal": "*", - "@wordpress/private-apis": "*", - "@wordpress/rich-text": "*", - "@wordpress/sync": "*", - "@wordpress/undo-manager": "*", - "@wordpress/url": "*", - "@wordpress/warning": "*", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/blocks": "file:../blocks", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/element": "file:../element", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/sync": "file:../sync", + "@wordpress/undo-manager": "file:../undo-manager", + "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", "change-case": "^4.1.2", "equivalent-key-map": "^0.2.2", "fast-deep-equal": "^3.1.3", @@ -60,6 +60,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/create-block-interactive-template/.npmrc b/packages/create-block-interactive-template/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/create-block-interactive-template/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/create-block-tutorial-template/.npmrc b/packages/create-block-tutorial-template/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/create-block-tutorial-template/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/create-block/.npmrc b/packages/create-block/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/create-block/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/create-block/package.json b/packages/create-block/package.json index a9215bb2699d32..06556dbfaaa342 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -31,7 +31,7 @@ "wp-create-block": "./index.js" }, "dependencies": { - "@wordpress/lazy-import": "*", + "@wordpress/lazy-import": "file:../lazy-import", "chalk": "^4.0.0", "change-case": "^4.1.2", "check-node-version": "^4.1.0", diff --git a/packages/customize-widgets/.npmrc b/packages/customize-widgets/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/customize-widgets/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 68e736c566c110..15cf61c352af8f 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -25,27 +25,27 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "*", - "@wordpress/block-library": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/dom": "*", - "@wordpress/editor": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/interface": "*", - "@wordpress/is-shallow-equal": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/keycodes": "*", - "@wordpress/media-utils": "*", - "@wordpress/preferences": "*", - "@wordpress/private-apis": "*", - "@wordpress/widgets": "*", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/block-library": "file:../block-library", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/dom": "file:../dom", + "@wordpress/editor": "file:../editor", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/interface": "file:../interface", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/media-utils": "file:../media-utils", + "@wordpress/preferences": "file:../preferences", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/widgets": "file:../widgets", "clsx": "^2.1.1", "fast-deep-equal": "^3.1.3" }, @@ -55,6 +55,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 84462f49e5c0c8..2820445254f0f4 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -29,15 +29,14 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*" + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated" }, "peerDependencies": { "react": "^18.0.0" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/data/.npmrc b/packages/data/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/data/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/data/package.json b/packages/data/package.json index 5e1817f0fb6ad8..b3adf78a2f3932 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -30,13 +30,13 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/compose": "*", - "@wordpress/deprecated": "*", - "@wordpress/element": "*", - "@wordpress/is-shallow-equal": "*", - "@wordpress/priority-queue": "*", - "@wordpress/private-apis": "*", - "@wordpress/redux-routine": "*", + "@wordpress/compose": "file:../compose", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/element": "file:../element", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/priority-queue": "file:../priority-queue", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/redux-routine": "file:../redux-routine", "deepmerge": "^4.3.0", "equivalent-key-map": "^0.2.2", "is-plain-object": "^5.0.0", @@ -50,6 +50,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/dataviews/.npmrc b/packages/dataviews/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/dataviews/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index a83fd163517d0a..d95e079033c3b6 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -30,15 +30,15 @@ "dependencies": { "@ariakit/react": "^0.4.10", "@babel/runtime": "7.25.7", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/primitives": "*", - "@wordpress/private-apis": "*", - "@wordpress/warning": "*", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/warning": "file:../warning", "clsx": "^2.1.1", "remove-accents": "^0.5.0" }, @@ -47,6 +47,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/date/.npmrc b/packages/date/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/date/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/date/package.json b/packages/date/package.json index a5925869f2acc0..2710aeb0437be8 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -28,12 +28,11 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/deprecated": "*", + "@wordpress/deprecated": "file:../deprecated", "moment": "^2.29.4", "moment-timezone": "^0.5.40" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/deprecated/.npmrc b/packages/deprecated/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/deprecated/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 4871d5772dbb64..c44b7052c1c545 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -29,10 +29,9 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/hooks": "*" + "@wordpress/hooks": "file:../hooks" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/docgen/.npmrc b/packages/docgen/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/docgen/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/dom-ready/.npmrc b/packages/dom-ready/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/dom-ready/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 65334a21bd1373..62cbf25ae12e86 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -32,6 +32,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/dom/.npmrc b/packages/dom/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/dom/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/dom/package.json b/packages/dom/package.json index 9d738a07b89b99..9028598f160785 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -30,10 +30,9 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/deprecated": "*" + "@wordpress/deprecated": "file:../deprecated" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/e2e-test-utils-playwright/.npmrc b/packages/e2e-test-utils-playwright/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/e2e-test-utils-playwright/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/e2e-test-utils/.npmrc b/packages/e2e-test-utils/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/e2e-test-utils/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index ca116dd0264a71..b328245162fef1 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -31,9 +31,9 @@ "module": "build-module/index.js", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/keycodes": "*", - "@wordpress/url": "*", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/url": "file:../url", "change-case": "^4.1.2", "form-data": "^4.0.0", "node-fetch": "2.7.0" diff --git a/packages/e2e-tests/.npmrc b/packages/e2e-tests/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/e2e-tests/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 5bf2b5c8663ac7..a2192c10049380 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -24,13 +24,13 @@ "npm": ">=8.19.2" }, "dependencies": { - "@wordpress/e2e-test-utils": "*", - "@wordpress/interactivity": "*", - "@wordpress/interactivity-router": "*", - "@wordpress/jest-console": "*", - "@wordpress/jest-puppeteer-axe": "*", - "@wordpress/scripts": "*", - "@wordpress/url": "*", + "@wordpress/e2e-test-utils": "file:../e2e-test-utils", + "@wordpress/interactivity": "file:../interactivity", + "@wordpress/interactivity-router": "file:../interactivity-router", + "@wordpress/jest-console": "file:../jest-console", + "@wordpress/jest-puppeteer-axe": "file:../jest-puppeteer-axe", + "@wordpress/scripts": "file:../scripts", + "@wordpress/url": "file:../url", "chalk": "^4.0.0", "expect-puppeteer": "^4.4.0", "filenamify": "^4.2.0", diff --git a/packages/edit-post/.npmrc b/packages/edit-post/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/edit-post/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 028520e79cad7a..e2653a2dab9736 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -28,35 +28,35 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/api-fetch": "*", - "@wordpress/block-editor": "*", - "@wordpress/block-library": "*", - "@wordpress/blocks": "*", - "@wordpress/commands": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-commands": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/editor": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/keycodes": "*", - "@wordpress/notices": "*", - "@wordpress/plugins": "*", - "@wordpress/preferences": "*", - "@wordpress/private-apis": "*", - "@wordpress/url": "*", - "@wordpress/viewport": "*", - "@wordpress/warning": "*", - "@wordpress/widgets": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/block-library": "file:../block-library", + "@wordpress/blocks": "file:../blocks", + "@wordpress/commands": "file:../commands", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-commands": "file:../core-commands", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/editor": "file:../editor", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/notices": "file:../notices", + "@wordpress/plugins": "file:../plugins", + "@wordpress/preferences": "file:../preferences", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url", + "@wordpress/viewport": "file:../viewport", + "@wordpress/warning": "file:../warning", + "@wordpress/widgets": "file:../widgets", "clsx": "^2.1.1", "memize": "^2.1.0" }, @@ -66,6 +66,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/edit-site/.npmrc b/packages/edit-site/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/edit-site/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 83cae4a7100bc7..e187acbb1b653f 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -29,45 +29,45 @@ "dependencies": { "@babel/runtime": "7.25.7", "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "*", - "@wordpress/api-fetch": "*", - "@wordpress/blob": "*", - "@wordpress/block-editor": "*", - "@wordpress/block-library": "*", - "@wordpress/blocks": "*", - "@wordpress/commands": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-commands": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/dataviews": "*", - "@wordpress/date": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/editor": "*", - "@wordpress/element": "*", - "@wordpress/escape-html": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/keycodes": "*", - "@wordpress/notices": "*", - "@wordpress/patterns": "*", - "@wordpress/plugins": "*", - "@wordpress/preferences": "*", - "@wordpress/primitives": "*", - "@wordpress/priority-queue": "*", - "@wordpress/private-apis": "*", - "@wordpress/reusable-blocks": "*", - "@wordpress/router": "*", - "@wordpress/style-engine": "*", - "@wordpress/url": "*", - "@wordpress/viewport": "*", - "@wordpress/widgets": "*", - "@wordpress/wordcount": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blob": "file:../blob", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/block-library": "file:../block-library", + "@wordpress/blocks": "file:../blocks", + "@wordpress/commands": "file:../commands", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-commands": "file:../core-commands", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/dataviews": "file:../dataviews", + "@wordpress/date": "file:../date", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/editor": "file:../editor", + "@wordpress/element": "file:../element", + "@wordpress/escape-html": "file:../escape-html", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/notices": "file:../notices", + "@wordpress/patterns": "file:../patterns", + "@wordpress/plugins": "file:../plugins", + "@wordpress/preferences": "file:../preferences", + "@wordpress/primitives": "file:../primitives", + "@wordpress/priority-queue": "file:../priority-queue", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/reusable-blocks": "file:../reusable-blocks", + "@wordpress/router": "file:../router", + "@wordpress/style-engine": "file:../style-engine", + "@wordpress/url": "file:../url", + "@wordpress/viewport": "file:../viewport", + "@wordpress/widgets": "file:../widgets", + "@wordpress/wordcount": "file:../wordcount", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.9.2", @@ -81,6 +81,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/edit-widgets/.npmrc b/packages/edit-widgets/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/edit-widgets/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 1b412c5adb78c3..cc2b97ac809d01 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -28,33 +28,33 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/block-editor": "*", - "@wordpress/block-library": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/editor": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/interface": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/keycodes": "*", - "@wordpress/media-utils": "*", - "@wordpress/notices": "*", - "@wordpress/patterns": "*", - "@wordpress/plugins": "*", - "@wordpress/preferences": "*", - "@wordpress/private-apis": "*", - "@wordpress/reusable-blocks": "*", - "@wordpress/url": "*", - "@wordpress/widgets": "*", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/block-library": "file:../block-library", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/editor": "file:../editor", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/interface": "file:../interface", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/media-utils": "file:../media-utils", + "@wordpress/notices": "file:../notices", + "@wordpress/patterns": "file:../patterns", + "@wordpress/plugins": "file:../plugins", + "@wordpress/preferences": "file:../preferences", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/reusable-blocks": "file:../reusable-blocks", + "@wordpress/url": "file:../url", + "@wordpress/widgets": "file:../widgets", "clsx": "^2.1.1" }, "peerDependencies": { @@ -63,6 +63,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/editor/.npmrc b/packages/editor/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/editor/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/editor/package.json b/packages/editor/package.json index 8c799085875c20..7568d0d6b8470f 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -32,41 +32,41 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/api-fetch": "*", - "@wordpress/blob": "*", - "@wordpress/block-editor": "*", - "@wordpress/blocks": "*", - "@wordpress/commands": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/dataviews": "*", - "@wordpress/date": "*", - "@wordpress/deprecated": "*", - "@wordpress/dom": "*", - "@wordpress/element": "*", - "@wordpress/fields": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/interface": "*", - "@wordpress/keyboard-shortcuts": "*", - "@wordpress/keycodes": "*", - "@wordpress/media-utils": "*", - "@wordpress/notices": "*", - "@wordpress/patterns": "*", - "@wordpress/plugins": "*", - "@wordpress/preferences": "*", - "@wordpress/private-apis": "*", - "@wordpress/reusable-blocks": "*", - "@wordpress/rich-text": "*", - "@wordpress/server-side-render": "*", - "@wordpress/url": "*", - "@wordpress/warning": "*", - "@wordpress/wordcount": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blob": "file:../blob", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/blocks": "file:../blocks", + "@wordpress/commands": "file:../commands", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/dataviews": "file:../dataviews", + "@wordpress/date": "file:../date", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/dom": "file:../dom", + "@wordpress/element": "file:../element", + "@wordpress/fields": "file:../fields", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/interface": "file:../interface", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/keycodes": "file:../keycodes", + "@wordpress/media-utils": "file:../media-utils", + "@wordpress/notices": "file:../notices", + "@wordpress/patterns": "file:../patterns", + "@wordpress/plugins": "file:../plugins", + "@wordpress/preferences": "file:../preferences", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/reusable-blocks": "file:../reusable-blocks", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/server-side-render": "file:../server-side-render", + "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", + "@wordpress/wordcount": "file:../wordcount", "change-case": "^4.1.2", "client-zip": "^2.4.5", "clsx": "^2.1.1", @@ -85,6 +85,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/element/.npmrc b/packages/element/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/element/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/element/package.json b/packages/element/package.json index 51e08e534b271e..7efc62530eadb9 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -32,7 +32,7 @@ "@babel/runtime": "7.25.7", "@types/react": "^18.2.79", "@types/react-dom": "^18.2.25", - "@wordpress/escape-html": "*", + "@wordpress/escape-html": "file:../escape-html", "change-case": "^4.1.2", "is-plain-object": "^5.0.0", "react": "^18.3.0", @@ -40,6 +40,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/env/.npmrc b/packages/env/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/env/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/escape-html/.npmrc b/packages/escape-html/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/escape-html/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index cadf7e9eaa174c..bc72f326e70b19 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -32,6 +32,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/eslint-plugin/.npmrc b/packages/eslint-plugin/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/eslint-plugin/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 4a85de55f671a3..5605f343ef5fd9 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -34,8 +34,8 @@ "@babel/eslint-parser": "7.25.7", "@typescript-eslint/eslint-plugin": "^6.4.1", "@typescript-eslint/parser": "^6.4.1", - "@wordpress/babel-preset-default": "*", - "@wordpress/prettier-config": "*", + "@wordpress/babel-preset-default": "file:../babel-preset-default", + "@wordpress/prettier-config": "file:../prettier-config", "cosmiconfig": "^7.0.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.2", diff --git a/packages/fields/.npmrc b/packages/fields/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/fields/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/fields/package.json b/packages/fields/package.json index 019ec99ed7a8ed..1f470e6ecba64c 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -32,25 +32,25 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/blob": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/dataviews": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/notices": "*", - "@wordpress/patterns": "*", - "@wordpress/primitives": "*", - "@wordpress/private-apis": "*", - "@wordpress/url": "*", - "@wordpress/warning": "*", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blob": "file:../blob", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/dataviews": "file:../dataviews", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/patterns": "file:../patterns", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", "change-case": "4.1.2", "client-zip": "^2.4.5" }, @@ -59,6 +59,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/format-library/.npmrc b/packages/format-library/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/format-library/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/format-library/package.json b/packages/format-library/package.json index e30ca517de794e..636552b7408a8c 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -27,18 +27,18 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/block-editor": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/private-apis": "*", - "@wordpress/rich-text": "*", - "@wordpress/url": "*" + "@wordpress/a11y": "file:../a11y", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/rich-text": "file:../rich-text", + "@wordpress/url": "file:../url" }, "peerDependencies": { "react": "^18.0.0", @@ -46,6 +46,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/hooks/.npmrc b/packages/hooks/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/hooks/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 04a0865f5c44ae..8f8674d0fd4c22 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -31,6 +31,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/html-entities/.npmrc b/packages/html-entities/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/html-entities/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 7ccf5d52f55fb7..4079728d6ae085 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -32,6 +32,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/i18n/.npmrc b/packages/i18n/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/i18n/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/i18n/package.json b/packages/i18n/package.json index f2ccf4b0fa2934..51950104c52e4a 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/hooks": "*", + "@wordpress/hooks": "file:../hooks", "gettext-parser": "^1.3.1", "memize": "^2.1.0", "sprintf-js": "^1.1.1", @@ -39,6 +39,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/icons/.npmrc b/packages/icons/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/icons/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/icons/package.json b/packages/icons/package.json index a2e3c97b67b55e..28dedd381de029 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -30,11 +30,10 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "*", - "@wordpress/primitives": "*" + "@wordpress/element": "file:../element", + "@wordpress/primitives": "file:../primitives" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/interactivity-router/.npmrc b/packages/interactivity-router/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/interactivity-router/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 2d33456a5712b0..bb482450699027 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -28,8 +28,8 @@ "types": "build-types", "wpScriptModuleExports": "./build-module/index.js", "dependencies": { - "@wordpress/a11y": "*", - "@wordpress/interactivity": "*" + "@wordpress/a11y": "file:../a11y", + "@wordpress/interactivity": "file:../interactivity" }, "publishConfig": { "access": "public" diff --git a/packages/interactivity/.npmrc b/packages/interactivity/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/interactivity/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/interface/.npmrc b/packages/interface/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/interface/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/interface/package.json b/packages/interface/package.json index e5870e0dfadfb2..964960afc2e1b9 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -33,18 +33,18 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/plugins": "*", - "@wordpress/preferences": "*", - "@wordpress/private-apis": "*", - "@wordpress/viewport": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/plugins": "file:../plugins", + "@wordpress/preferences": "file:../preferences", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/viewport": "file:../viewport", "clsx": "^2.1.1" }, "peerDependencies": { @@ -53,6 +53,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/is-shallow-equal/.npmrc b/packages/is-shallow-equal/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/is-shallow-equal/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 1034ce1e76cda8..617f0415935d88 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -41,6 +41,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/jest-console/.npmrc b/packages/jest-console/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/jest-console/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/jest-preset-default/.npmrc b/packages/jest-preset-default/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/jest-preset-default/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 2db25a45f5b8e7..953e923dda253b 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -31,7 +31,7 @@ ], "main": "index.js", "dependencies": { - "@wordpress/jest-console": "*", + "@wordpress/jest-console": "file:../jest-console", "babel-jest": "29.7.0" }, "peerDependencies": { diff --git a/packages/jest-puppeteer-axe/.npmrc b/packages/jest-puppeteer-axe/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/jest-puppeteer-axe/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/keyboard-shortcuts/.npmrc b/packages/keyboard-shortcuts/.npmrc new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 4687df000bb3a7..7ef7599e296566 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -27,15 +27,14 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/keycodes": "*" + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/keycodes": "file:../keycodes" }, "peerDependencies": { "react": "^18.0.0" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/keycodes/.npmrc b/packages/keycodes/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/keycodes/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index cce62c927fa206..8ec0c6278595cf 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -29,10 +29,9 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/i18n": "*" + "@wordpress/i18n": "file:../i18n" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/lazy-import/.npmrc b/packages/lazy-import/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/lazy-import/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/list-reusable-blocks/.npmrc b/packages/list-reusable-blocks/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/list-reusable-blocks/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index d5a7dace810b48..8ee807dd4404f0 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -27,12 +27,12 @@ "module": "build-module/index.js", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/blob": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blob": "file:../blob", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", "change-case": "^4.1.2" }, "peerDependencies": { @@ -41,6 +41,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/media-utils/.npmrc b/packages/media-utils/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/media-utils/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 0ba56f26706833..67adfe9673db28 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -28,13 +28,12 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/blob": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*" + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blob": "file:../blob", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/notices/.npmrc b/packages/notices/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/notices/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/notices/package.json b/packages/notices/package.json index de04c49a26cd6e..798965e93b25ce 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -28,14 +28,13 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/data": "*" + "@wordpress/a11y": "file:../a11y", + "@wordpress/data": "file:../data" }, "peerDependencies": { "react": "^18.0.0" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/npm-package-json-lint-config/.npmrc b/packages/npm-package-json-lint-config/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/npm-package-json-lint-config/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/nux/.npmrc b/packages/nux/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/nux/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/nux/package.json b/packages/nux/package.json index 122bb2758263d6..b6b6695b5b1058 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -32,13 +32,13 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*" + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons" }, "peerDependencies": { "react": "^18.0.0", @@ -46,6 +46,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/patterns/.npmrc b/packages/patterns/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/patterns/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 3da30812d61edd..6d1dc87554bc36 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -32,20 +32,20 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/block-editor": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/html-entities": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/notices": "*", - "@wordpress/private-apis": "*", - "@wordpress/url": "*" + "@wordpress/a11y": "file:../a11y", + "@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/html-entities": "file:../html-entities", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url" }, "peerDependencies": { "react": "^18.0.0", @@ -53,6 +53,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/plugins/.npmrc b/packages/plugins/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/plugins/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/plugins/package.json b/packages/plugins/package.json index a2ce790e0935e5..0fc38303213f25 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -28,12 +28,12 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/icons": "*", - "@wordpress/is-shallow-equal": "*", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/icons": "file:../icons", + "@wordpress/is-shallow-equal": "file:../is-shallow-equal", "memize": "^2.0.1" }, "peerDependencies": { @@ -42,6 +42,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/postcss-plugins-preset/.npmrc b/packages/postcss-plugins-preset/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/postcss-plugins-preset/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 82753b0ff56d38..e5c1e2ab1629ec 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -30,7 +30,7 @@ ], "main": "lib/index.js", "dependencies": { - "@wordpress/base-styles": "*", + "@wordpress/base-styles": "file:../base-styles", "autoprefixer": "^10.2.5" }, "peerDependencies": { diff --git a/packages/postcss-themes/.npmrc b/packages/postcss-themes/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/postcss-themes/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/preferences-persistence/.npmrc b/packages/preferences-persistence/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/preferences-persistence/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index e91c8f295d4653..cd2d86b61264eb 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -29,10 +29,9 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*" + "@wordpress/api-fetch": "file:../api-fetch" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/preferences/.npmrc b/packages/preferences/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/preferences/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/preferences/package.json b/packages/preferences/package.json index ef9f0ef8803dfc..8dc6b2f919a20c 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -30,15 +30,15 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/private-apis": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/private-apis": "file:../private-apis", "clsx": "^2.1.1" }, "peerDependencies": { @@ -47,6 +47,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/prettier-config/.npmrc b/packages/prettier-config/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/prettier-config/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/primitives/.npmrc b/packages/primitives/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/primitives/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 67117e037002c6..b81a5049d05b5e 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -32,7 +32,7 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "*", + "@wordpress/element": "file:../element", "clsx": "^2.1.1" }, "peerDependencies": { @@ -40,6 +40,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/priority-queue/.npmrc b/packages/priority-queue/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/priority-queue/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 0113bb9b1bc62c..0e0dde33cc39a0 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -34,6 +34,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index eae83e1fc46d34..a76fff0de91f5f 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -33,6 +33,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/project-management-automation/.npmrc b/packages/project-management-automation/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/project-management-automation/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 6a741d33f997c1..77dc00b1b8e273 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -29,12 +29,11 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "*", - "@wordpress/i18n": "*", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", "utility-types": "^3.10.0" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/react-native-aztec/.npmrc b/packages/react-native-aztec/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/react-native-aztec/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/react-native-aztec/package.json b/packages/react-native-aztec/package.json index b0327b531395e5..e2f5d5f425d869 100644 --- a/packages/react-native-aztec/package.json +++ b/packages/react-native-aztec/package.json @@ -23,8 +23,8 @@ "npm": ">=8.19.2" }, "dependencies": { - "@wordpress/element": "*", - "@wordpress/keycodes": "*" + "@wordpress/element": "file:../element", + "@wordpress/keycodes": "file:../keycodes" }, "peerDependencies": { "react": "*", diff --git a/packages/react-native-bridge/.npmrc b/packages/react-native-bridge/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/react-native-bridge/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/react-native-bridge/package.json b/packages/react-native-bridge/package.json index b0c0a2485520df..925b83103dca00 100644 --- a/packages/react-native-bridge/package.json +++ b/packages/react-native-bridge/package.json @@ -24,7 +24,7 @@ "main": "index.js", "react-native": "index", "dependencies": { - "@wordpress/react-native-aztec": "*" + "@wordpress/react-native-aztec": "file:../react-native-aztec" }, "peerDependencies": { "react-native": "*" diff --git a/packages/react-native-editor/.npmrc b/packages/react-native-editor/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/react-native-editor/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json index e6e53af1190ad7..3a345a23e0a5d9 100644 --- a/packages/react-native-editor/package.json +++ b/packages/react-native-editor/package.json @@ -38,18 +38,18 @@ "@react-navigation/native": "6.0.14", "@react-navigation/routers": "5.4.9", "@react-navigation/stack": "6.3.5", - "@wordpress/api-fetch": "*", - "@wordpress/block-editor": "*", - "@wordpress/block-library": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/data": "*", - "@wordpress/edit-post": "*", - "@wordpress/element": "*", - "@wordpress/hooks": "*", - "@wordpress/i18n": "*", - "@wordpress/react-native-aztec": "*", - "@wordpress/react-native-bridge": "*", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/block-library": "file:../block-library", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/data": "file:../data", + "@wordpress/edit-post": "file:../edit-post", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/i18n": "file:../i18n", + "@wordpress/react-native-aztec": "file:../react-native-aztec", + "@wordpress/react-native-bridge": "file:../react-native-bridge", "core-js": "^3.31.0", "fast-average-color": "^9.1.1", "gettext-parser": "^1.3.1", diff --git a/packages/readable-js-assets-webpack-plugin/.npmrc b/packages/readable-js-assets-webpack-plugin/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/readable-js-assets-webpack-plugin/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/redux-routine/.npmrc b/packages/redux-routine/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/redux-routine/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 70d1cae1a8b5fd..46dffc7e069e19 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -40,6 +40,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/report-flaky-tests/.npmrc b/packages/report-flaky-tests/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/report-flaky-tests/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/reusable-blocks/.npmrc b/packages/reusable-blocks/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/reusable-blocks/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 461a17001b0c38..483ecceeb9e252 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -30,17 +30,17 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/notices": "*", - "@wordpress/private-apis": "*", - "@wordpress/url": "*" + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/core-data": "file:../core-data", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url" }, "peerDependencies": { "react": "^18.0.0", @@ -48,6 +48,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/rich-text/.npmrc b/packages/rich-text/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/rich-text/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index c2b99faaa72d7f..a4a15743a13ed5 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -32,14 +32,14 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/element": "*", - "@wordpress/escape-html": "*", - "@wordpress/i18n": "*", - "@wordpress/keycodes": "*", + "@wordpress/a11y": "file:../a11y", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/element": "file:../element", + "@wordpress/escape-html": "file:../escape-html", + "@wordpress/i18n": "file:../i18n", + "@wordpress/keycodes": "file:../keycodes", "memize": "^2.1.0" }, "peerDependencies": { @@ -47,6 +47,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/router/.npmrc b/packages/router/.npmrc new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/packages/router/package.json b/packages/router/package.json index d7a1219e0b95cf..a7a181fbde9705 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -28,9 +28,9 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "*", - "@wordpress/private-apis": "*", - "@wordpress/url": "*", + "@wordpress/element": "file:../element", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url", "history": "^5.3.0" }, "peerDependencies": { @@ -38,6 +38,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/scripts/.npmrc b/packages/scripts/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/scripts/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 20da2369c3d64a..66461f4eb28ec2 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -35,16 +35,16 @@ "@babel/core": "7.25.7", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", "@svgr/webpack": "^8.0.1", - "@wordpress/babel-preset-default": "*", - "@wordpress/browserslist-config": "*", - "@wordpress/dependency-extraction-webpack-plugin": "*", - "@wordpress/e2e-test-utils-playwright": "*", - "@wordpress/eslint-plugin": "*", - "@wordpress/jest-preset-default": "*", - "@wordpress/npm-package-json-lint-config": "*", - "@wordpress/postcss-plugins-preset": "*", - "@wordpress/prettier-config": "*", - "@wordpress/stylelint-config": "*", + "@wordpress/babel-preset-default": "file:../babel-preset-default", + "@wordpress/browserslist-config": "file:../browserslist-config", + "@wordpress/dependency-extraction-webpack-plugin": "file:../dependency-extraction-webpack-plugin", + "@wordpress/e2e-test-utils-playwright": "file:../e2e-test-utils-playwright", + "@wordpress/eslint-plugin": "file:../eslint-plugin", + "@wordpress/jest-preset-default": "file:../jest-preset-default", + "@wordpress/npm-package-json-lint-config": "file:../npm-package-json-lint-config", + "@wordpress/postcss-plugins-preset": "file:../postcss-plugins-preset", + "@wordpress/prettier-config": "file:../prettier-config", + "@wordpress/stylelint-config": "file:../stylelint-config", "adm-zip": "^0.5.9", "babel-jest": "29.7.0", "babel-loader": "9.2.1", diff --git a/packages/server-side-render/.npmrc b/packages/server-side-render/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/server-side-render/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index a40d4358c35308..b91da1f10127b4 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -28,15 +28,15 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/deprecated": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/url": "*", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/deprecated": "file:../deprecated", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/url": "file:../url", "fast-deep-equal": "^3.1.3" }, "peerDependencies": { @@ -45,6 +45,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/shortcode/.npmrc b/packages/shortcode/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/shortcode/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index c10007806383d9..7b0b965df6d926 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -31,6 +31,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/style-engine/.npmrc b/packages/style-engine/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/style-engine/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index ed6eebf9483d17..670861a7ca8c97 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -35,6 +35,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/stylelint-config/.npmrc b/packages/stylelint-config/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/stylelint-config/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/sync/.npmrc b/packages/sync/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/sync/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/sync/package.json b/packages/sync/package.json index 27ed67971b7ca9..1e79d4673b47dd 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -30,7 +30,7 @@ "dependencies": { "@babel/runtime": "7.25.7", "@types/simple-peer": "^9.11.5", - "@wordpress/url": "*", + "@wordpress/url": "file:../url", "import-locals": "^2.0.0", "lib0": "^0.2.42", "simple-peer": "^9.11.0", @@ -41,6 +41,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/token-list/.npmrc b/packages/token-list/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/token-list/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/token-list/package.json b/packages/token-list/package.json index e73fc1918ec55e..c4fdfde1af6d01 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -31,6 +31,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/undo-manager/.npmrc b/packages/undo-manager/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/undo-manager/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 9e31c9c0d6dd7f..3a7c61dc620ec4 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -30,10 +30,9 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/is-shallow-equal": "*" + "@wordpress/is-shallow-equal": "file:../is-shallow-equal" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/url/.npmrc b/packages/url/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/url/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/url/package.json b/packages/url/package.json index e7228be292bf03..9631694dc5e2b1 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -33,6 +33,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/viewport/.npmrc b/packages/viewport/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/viewport/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 916776cdbe98b3..c5e46e4700e96b 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -27,15 +27,14 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/compose": "*", - "@wordpress/data": "*", - "@wordpress/element": "*" + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element" }, "peerDependencies": { "react": "^18.0.0" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/warning/.npmrc b/packages/warning/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/warning/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/warning/package.json b/packages/warning/package.json index d9d4835a220f0a..4191f7f1e38a06 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -29,6 +29,5 @@ "sideEffects": false, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/widgets/.npmrc b/packages/widgets/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/widgets/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/widgets/package.json b/packages/widgets/package.json index d85e06c399b2d9..9fdf32172eb723 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -25,17 +25,17 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "*", - "@wordpress/block-editor": "*", - "@wordpress/blocks": "*", - "@wordpress/components": "*", - "@wordpress/compose": "*", - "@wordpress/core-data": "*", - "@wordpress/data": "*", - "@wordpress/element": "*", - "@wordpress/i18n": "*", - "@wordpress/icons": "*", - "@wordpress/notices": "*", + "@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/notices": "file:../notices", "clsx": "^2.1.1" }, "peerDependencies": { @@ -44,6 +44,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/wordcount/.npmrc b/packages/wordcount/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/wordcount/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index f2fa54e449da51..5ad2fd1908d727 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -31,6 +31,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/tools/webpack/packages.js b/tools/webpack/packages.js index 371a219be5f3f5..76d460cafc15d0 100644 --- a/tools/webpack/packages.js +++ b/tools/webpack/packages.js @@ -4,7 +4,6 @@ const CopyWebpackPlugin = require( 'copy-webpack-plugin' ); const MomentTimezoneDataPlugin = require( 'moment-timezone-data-webpack-plugin' ); const { join } = require( 'path' ); -const { readdirSync } = require( 'node:fs' ); /** * WordPress dependencies @@ -17,12 +16,7 @@ const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extrac /** * Internal dependencies */ -const packageDirs = readdirSync( - new URL( '../packages', `file://${ __dirname }` ), - { - withFileTypes: true, - } -).flatMap( ( dirent ) => ( dirent.isDirectory() ? [ dirent.name ] : [] ) ); +const { dependencies } = require( '../../package' ); const { baseConfig, plugins, stylesTransform } = require( './shared' ); const WORDPRESS_NAMESPACE = '@wordpress/'; @@ -88,23 +82,15 @@ const bundledPackagesPhpConfig = [ }, } ) ); -/** @type {Array<string>} */ -const gutenbergScripts = []; -for ( const packageDir of packageDirs ) { - const packageJson = require( - `${ WORDPRESS_NAMESPACE }${ packageDir }/package.json` - ); - - if ( ! packageJson.wpScript ) { - continue; - } - - if ( BUNDLED_PACKAGES.includes( packageJson.name ) ) { - continue; - } - - gutenbergScripts.push( packageDir ); -} +const gutenbergPackages = Object.keys( dependencies ) + .filter( + ( packageName ) => + ! BUNDLED_PACKAGES.includes( packageName ) && + packageName.startsWith( WORDPRESS_NAMESPACE ) && + ! packageName.startsWith( WORDPRESS_NAMESPACE + 'react-native' ) && + ! packageName.startsWith( WORDPRESS_NAMESPACE + 'interactivity' ) + ) + .map( ( packageName ) => packageName.replace( WORDPRESS_NAMESPACE, '' ) ); const exportDefaultPackages = [ 'api-fetch', @@ -128,7 +114,7 @@ module.exports = { ...baseConfig, name: 'packages', entry: Object.fromEntries( - gutenbergScripts.map( ( packageName ) => [ + gutenbergPackages.map( ( packageName ) => [ packageName, { import: `./packages/${ packageName }`, @@ -162,7 +148,7 @@ module.exports = { ...plugins, new DependencyExtractionWebpackPlugin( { injectPolyfill: false } ), new CopyWebpackPlugin( { - patterns: gutenbergScripts + patterns: gutenbergPackages .map( ( packageName ) => ( { from: '*.css', context: `./packages/${ packageName }/build-style`, diff --git a/tools/webpack/script-modules.js b/tools/webpack/script-modules.js index aac387ee32957a..021f11f5f5ed95 100644 --- a/tools/webpack/script-modules.js +++ b/tools/webpack/script-modules.js @@ -2,7 +2,6 @@ * External dependencies */ const { join } = require( 'path' ); -const { readdirSync } = require( 'node:fs' ); /** * WordPress dependencies @@ -15,25 +14,39 @@ const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extrac const { baseConfig, plugins } = require( './shared' ); const WORDPRESS_NAMESPACE = '@wordpress/'; +const { createRequire } = require( 'node:module' ); -const packageDirs = readdirSync( - new URL( '../packages', `file://${ __dirname }` ), - { - withFileTypes: true, - } -).flatMap( ( dirent ) => ( dirent.isDirectory() ? [ dirent.name ] : [] ) ); +const rootURL = new URL( '..', `file://${ __dirname }` ); +const fromRootRequire = createRequire( rootURL ); + +/** @type {Iterable<[string, string]>} */ +const iterableDeps = Object.entries( + fromRootRequire( './package.json' ).dependencies +); /** @type {Map<string, string>} */ const gutenbergScriptModules = new Map(); -for ( const packageDir of packageDirs ) { - const packageJson = require( `@wordpress/${ packageDir }/package.json` ); +for ( const [ packageName, versionSpecifier ] of iterableDeps ) { + if ( + ! packageName.startsWith( WORDPRESS_NAMESPACE ) || + ! versionSpecifier.startsWith( 'file:' ) || + packageName.startsWith( WORDPRESS_NAMESPACE + 'react-native' ) + ) { + continue; + } + + const packageRequire = createRequire( + // Remove the leading "file:" specifier to build a package URL. + new URL( `${ versionSpecifier.substring( 5 ) }/`, rootURL ) + ); - if ( ! Object.hasOwn( packageJson, 'wpScriptModuleExports' ) ) { + const depPackageJson = packageRequire( './package.json' ); + if ( ! Object.hasOwn( depPackageJson, 'wpScriptModuleExports' ) ) { continue; } - const moduleName = packageJson.name.substring( WORDPRESS_NAMESPACE.length ); - let { wpScriptModuleExports } = packageJson; + const moduleName = packageName.substring( WORDPRESS_NAMESPACE.length ); + let { wpScriptModuleExports } = depPackageJson; // Special handling for { "wpScriptModuleExports": "./build-module/index.js" }. if ( typeof wpScriptModuleExports === 'string' ) { @@ -62,7 +75,7 @@ for ( const packageDir of packageDirs ) { gutenbergScriptModules.set( `${ moduleName }/${ name }`, - require.resolve( `@wordpress/${ packageDir }/${ exportPath }` ) + packageRequire.resolve( exportPath ) ); } } From 9b0f6aa0eba137530c594c442cfa8dca2748c499 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 21 Oct 2024 09:57:22 +0100 Subject: [PATCH 1256/1908] Zoom Out: Bundle behavior in block-editor and add story (#66240) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- package-lock.json | 58 ++++++++++++++++ package.json | 1 + .../src/components/block-canvas/index.js | 18 ++++- .../src/components/document-tools/index.js | 8 +-- .../src/components/visual-editor/index.js | 10 --- storybook/stories/playground/index.story.js | 9 +++ .../stories/playground/zoom-out/index.js | 68 +++++++++++++++++++ .../stories/playground/zoom-out/pattern.js | 39 +++++++++++ 8 files changed, 193 insertions(+), 18 deletions(-) create mode 100644 storybook/stories/playground/zoom-out/index.js create mode 100644 storybook/stories/playground/zoom-out/pattern.js diff --git a/package-lock.json b/package-lock.json index 3c328a047fc588..22c37a17c7c28d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -223,6 +223,7 @@ "prettier": "npm:wp-prettier@3.0.3", "progress": "2.0.3", "puppeteer-core": "23.1.0", + "raw-loader": "4.0.2", "react": "18.3.1", "react-docgen-typescript": "2.2.2", "react-dom": "18.3.1", @@ -43104,6 +43105,63 @@ "node": ">=0.10.0" } }, + "node_modules/raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/raw-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/raw-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", diff --git a/package.json b/package.json index 8be1e9cbe3f3a0..ae86dc0d1577c4 100644 --- a/package.json +++ b/package.json @@ -235,6 +235,7 @@ "prettier": "npm:wp-prettier@3.0.3", "progress": "2.0.3", "puppeteer-core": "23.1.0", + "raw-loader": "4.0.2", "react": "18.3.1", "react-docgen-typescript": "2.2.2", "react-dom": "18.3.1", diff --git a/packages/block-editor/src/components/block-canvas/index.js b/packages/block-editor/src/components/block-canvas/index.js index 9bad3ca22e95f7..cce3223acd9695 100644 --- a/packages/block-editor/src/components/block-canvas/index.js +++ b/packages/block-editor/src/components/block-canvas/index.js @@ -1,8 +1,9 @@ /** * WordPress dependencies */ -import { useMergeRefs } from '@wordpress/compose'; +import { useMergeRefs, useViewportMatch } from '@wordpress/compose'; import { useRef } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -15,6 +16,8 @@ import WritingFlow from '../writing-flow'; import { useMouseMoveTypingReset } from '../observe-typing'; import { useBlockSelectionClearer } from '../block-selection-clearer'; import { useBlockCommands } from '../use-block-commands'; +import { store as blockEditorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; // EditorStyles is a memoized component, so avoid passing a new // object reference on each render. @@ -32,10 +35,22 @@ export function ExperimentalBlockCanvas( { iframeProps, } ) { useBlockCommands(); + const isTabletViewport = useViewportMatch( 'medium', '<' ); const resetTypingRef = useMouseMoveTypingReset(); const clearerRef = useBlockSelectionClearer(); const localRef = useRef(); const contentRef = useMergeRefs( [ contentRefProp, clearerRef, localRef ] ); + const isZoomedOut = useSelect( + ( select ) => unlock( select( blockEditorStore ) ).isZoomOut(), + [] + ); + const zoomOutIframeProps = + isZoomedOut && ! isTabletViewport + ? { + scale: 'default', + frameSize: '40px', + } + : {}; if ( ! shouldIframe ) { return ( @@ -70,6 +85,7 @@ export function ExperimentalBlockCanvas( { > <Iframe { ...iframeProps } + { ...zoomOutIframeProps } ref={ resetTypingRef } contentRef={ contentRef } style={ { diff --git a/packages/editor/src/components/document-tools/index.js b/packages/editor/src/components/document-tools/index.js index ee261567a9115a..b2295b555ce080 100644 --- a/packages/editor/src/components/document-tools/index.js +++ b/packages/editor/src/components/document-tools/index.js @@ -9,11 +9,7 @@ import clsx from 'clsx'; import { useViewportMatch } from '@wordpress/compose'; import { useSelect, useDispatch } from '@wordpress/data'; import { __, _x } from '@wordpress/i18n'; -import { - NavigableToolbar, - ToolSelector, - store as blockEditorStore, -} from '@wordpress/block-editor'; +import { NavigableToolbar, ToolSelector } from '@wordpress/block-editor'; import { Button, ToolbarItem } from '@wordpress/components'; import { listView, plus } from '@wordpress/icons'; import { useCallback } from '@wordpress/element'; @@ -48,7 +44,6 @@ function DocumentTools( { className, disableBlockTools = false } ) { getListViewToggleRef, } = unlock( select( editorStore ) ); const { getShortcutRepresentation } = select( keyboardShortcutsStore ); - const { isZoomOut } = unlock( select( blockEditorStore ) ); return { isInserterOpened: select( editorStore ).isInserterOpened(), @@ -61,7 +56,6 @@ function DocumentTools( { className, disableBlockTools = false } ) { showIconLabels: get( 'core', 'showIconLabels' ), isDistractionFree: get( 'core', 'distractionFree' ), isVisualMode: getEditorMode() === 'visual', - isZoomedOutView: isZoomOut(), }; }, [] ); diff --git a/packages/editor/src/components/visual-editor/index.js b/packages/editor/src/components/visual-editor/index.js index 1528538c7ef2bd..8ad9ce7fc974ac 100644 --- a/packages/editor/src/components/visual-editor/index.js +++ b/packages/editor/src/components/visual-editor/index.js @@ -108,7 +108,6 @@ function VisualEditor( { } ) { const [ resizeObserver, sizes ] = useResizeObserver(); const isMobileViewport = useViewportMatch( 'small', '<' ); - const isTabletViewport = useViewportMatch( 'medium', '<' ); const { renderingMode, postContentAttributes, @@ -339,14 +338,6 @@ function VisualEditor( { useZoomOutModeExit(), ] ); - const zoomOutProps = - isZoomedOut && ! isTabletViewport - ? { - scale: 'default', - frameSize: '40px', - } - : {}; - const forceFullHeight = postType === NAVIGATION_POST_TYPE; const enableResizing = [ @@ -403,7 +394,6 @@ function VisualEditor( { height="100%" iframeProps={ { ...iframeProps, - ...zoomOutProps, style: { ...iframeProps?.style, ...deviceStyles, diff --git a/storybook/stories/playground/index.story.js b/storybook/stories/playground/index.story.js index 55c19774643329..699f3a295e9df8 100644 --- a/storybook/stories/playground/index.story.js +++ b/storybook/stories/playground/index.story.js @@ -4,6 +4,7 @@ import EditorFullPage from './fullpage'; import EditorBox from './box'; import EditorWithUndoRedo from './with-undo-redo'; +import EditorZoomOut from './zoom-out'; export default { title: 'Playground/Block Editor', @@ -35,3 +36,11 @@ export const UndoRedo = () => { UndoRedo.parameters = { sourceLink: 'storybook/stories/playground/with-undo-redo/index.js', }; + +export const ZoomOut = () => { + return <EditorZoomOut />; +}; + +ZoomOut.parameters = { + sourceLink: 'storybook/stories/playground/zoom-out/index.js', +}; diff --git a/storybook/stories/playground/zoom-out/index.js b/storybook/stories/playground/zoom-out/index.js new file mode 100644 index 00000000000000..fae405c6b0ff30 --- /dev/null +++ b/storybook/stories/playground/zoom-out/index.js @@ -0,0 +1,68 @@ +/** + * WordPress dependencies + */ +import { useEffect, useState } from '@wordpress/element'; +import { registerCoreBlocks } from '@wordpress/block-library'; +import { useDispatch } from '@wordpress/data'; +import { + BlockEditorProvider, + BlockCanvas, + store as blockEditorStore, + BlockList, +} from '@wordpress/block-editor'; +import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; +import { parse } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import editorStyles from '../editor-styles'; +// eslint-disable-next-line @wordpress/dependency-group +import contentCss from '!!raw-loader!../../../../packages/block-editor/build-style/content.css'; +import { pattern } from './pattern'; + +// Temporary hack to access private APIs before stabilizing zoom level. +const { unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( + 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', + '@wordpress/edit-site' +); + +function EnableZoomOut() { + const { setZoomLevel } = unlock( useDispatch( blockEditorStore ) ); + + useEffect( () => { + setZoomLevel( 50 ); + }, [ setZoomLevel ] ); + + return null; +} + +export default function EditorZoomOut() { + const [ blocks, updateBlocks ] = useState( [] ); + + useEffect( () => { + registerCoreBlocks(); + updateBlocks( parse( pattern ) ); + }, [] ); + + return ( + // eslint-disable-next-line jsx-a11y/no-static-element-interactions + <div + className="editor-zoom-out" + onKeyDown={ ( event ) => event.stopPropagation() } + style={ { background: '#ddd', border: '1px solid gray' } } + > + <BlockEditorProvider + value={ blocks } + onInput={ updateBlocks } + onChange={ updateBlocks } + > + <EnableZoomOut /> + <BlockCanvas height="500px" styles={ editorStyles }> + <style>{ contentCss }</style> + <BlockList /> + </BlockCanvas> + </BlockEditorProvider> + </div> + ); +} diff --git a/storybook/stories/playground/zoom-out/pattern.js b/storybook/stories/playground/zoom-out/pattern.js new file mode 100644 index 00000000000000..7c58486de55235 --- /dev/null +++ b/storybook/stories/playground/zoom-out/pattern.js @@ -0,0 +1,39 @@ +export const pattern = `<!-- wp:cover {"customOverlayColor":"#eb4c77","contentPosition":"center center","isDark":false,"align":"full","style":{"spacing":{"padding":{"top":"6vw","right":"6vw","bottom":"6vw","left":"6vw"},"margin":{"top":"0"}}}} --> +<div class="wp-block-cover alignfull is-light" style="margin-top:0;padding-top:6vw;padding-right:6vw;padding-bottom:6vw;padding-left:6vw"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-100 has-background-dim" style="background-color:#eb4c77"></span><div class="wp-block-cover__inner-container"><!-- wp:group {"style":{"spacing":{"blockGap":"0vw"}},"layout":{"type":"flex","flexWrap":"wrap","justifyContent":"center","verticalAlignment":"top"}} --> +<div class="wp-block-group"><!-- wp:group {"align":"wide","style":{"spacing":{"blockGap":"0px"},"layout":{"selfStretch":"fill"}},"layout":{"type":"constrained","justifyContent":"left","contentSize":"600px"}} --> +<div class="wp-block-group alignwide"><!-- wp:heading {"textAlign":"left","align":"wide","style":{"typography":{"fontSize":"100px","textTransform":"none","fontStyle":"normal","fontWeight":"500","lineHeight":"0.9"}},"textColor":"contrast"} --> +<h2 class="wp-block-heading alignwide has-text-align-left has-contrast-color has-text-color" style="font-size:100px;font-style:normal;font-weight:500;line-height:0.9;text-transform:none">Time for an adventure</h2> +<!-- /wp:heading --> + +<!-- wp:spacer {"height":"24px"} --> +<div style="height:24px" aria-hidden="true" class="wp-block-spacer"></div> +<!-- /wp:spacer --> + +<!-- wp:paragraph {"align":"left","textColor":"contrast"} --> +<p class="has-text-align-left has-contrast-color has-text-color">Explore our network of trails that lead through a variety of woodland habitats and observe the diverse flora that call this area home. </p> +<!-- /wp:paragraph --> + +<!-- wp:spacer {"height":"60px"} --> +<div style="height:60px" aria-hidden="true" class="wp-block-spacer"></div> +<!-- /wp:spacer --> + +<!-- wp:buttons {"layout":{"type":"flex","justifyContent":"left","flexWrap":"nowrap"}} --> +<div class="wp-block-buttons"><!-- wp:button {"backgroundColor":"contrast","textColor":"base","style":{"spacing":{"padding":{"top":"24px","right":"48px","bottom":"24px","left":"48px"}},"typography":{"fontSize":"16px","fontStyle":"normal","fontWeight":"500","textTransform":"uppercase","letterSpacing":"0px"},"border":{"radius":"0px"}},"className":"is-style-fill"} --> +<div class="wp-block-button has-custom-font-size is-style-fill" style="font-size:16px;font-style:normal;font-weight:500;letter-spacing:0px;text-transform:uppercase"><a class="wp-block-button__link has-base-color has-contrast-background-color has-text-color has-background wp-element-button" style="border-radius:0px;padding-top:24px;padding-right:48px;padding-bottom:24px;padding-left:48px">Sign up</a></div> +<!-- /wp:button --></div> +<!-- /wp:buttons --></div> +<!-- /wp:group --> + +<!-- wp:group {"style":{"layout":{"selfStretch":"fit","flexSize":null},"spacing":{"blockGap":"24px"}},"layout":{"type":"flex","flexWrap":"nowrap","verticalAlignment":"top","justifyContent":"right"}} --> +<div class="wp-block-group"><!-- wp:group {"style":{"layout":{"selfStretch":"fixed","flexSize":"50%"}},"layout":{"type":"default"}} --> +<div class="wp-block-group"><!-- wp:spacer {"height":"8vw"} --> +<div style="height:8vw" aria-hidden="true" class="wp-block-spacer"></div> +<!-- /wp:spacer --> + +</div> +<!-- /wp:group --> + +</div> +<!-- /wp:group --></div> +<!-- /wp:group --></div></div> +<!-- /wp:cover -->`; From 2fe909bbb60a07cb4d9c026d5d63f2ea8098e1c0 Mon Sep 17 00:00:00 2001 From: Matt <146485480+mattrwalker@users.noreply.github.com> Date: Mon, 21 Oct 2024 05:31:24 -0400 Subject: [PATCH 1257/1908] Storybook: Organizes components under 'Utilities' (#66210) Co-authored-by: mattrwalker <mattryanwalker@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/components/src/animate/stories/index.story.tsx | 3 ++- packages/components/src/composite/stories/index.story.tsx | 3 ++- packages/components/src/disabled/stories/index.story.tsx | 3 ++- packages/components/src/draggable/stories/index.story.tsx | 3 ++- .../components/src/keyboard-shortcuts/stories/index.story.tsx | 3 ++- packages/components/src/resizable-box/stories/index.story.tsx | 3 ++- packages/components/src/sandbox/stories/index.story.tsx | 3 ++- packages/components/src/scroll-lock/stories/index.story.tsx | 3 ++- packages/components/src/shortcut/stories/index.story.tsx | 3 ++- packages/components/src/slot-fill/stories/index.story.tsx | 3 ++- packages/components/src/theme/stories/index.story.tsx | 3 ++- .../components/src/visually-hidden/stories/index.story.tsx | 3 ++- storybook/preview.js | 1 + 13 files changed, 25 insertions(+), 12 deletions(-) diff --git a/packages/components/src/animate/stories/index.story.tsx b/packages/components/src/animate/stories/index.story.tsx index de28495a97fc57..c1798b503faa83 100644 --- a/packages/components/src/animate/stories/index.story.tsx +++ b/packages/components/src/animate/stories/index.story.tsx @@ -10,7 +10,8 @@ import { Animate } from '..'; import Notice from '../../notice'; const meta: Meta< typeof Animate > = { - title: 'Components/Animate', + title: 'Components/Utilities/Animate', + id: 'components-animate', component: Animate, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx index c5518375df8a6f..eefcd599134757 100644 --- a/packages/components/src/composite/stories/index.story.tsx +++ b/packages/components/src/composite/stories/index.story.tsx @@ -16,7 +16,8 @@ import { Composite } from '..'; import { Tooltip } from '../../tooltip'; const meta: Meta< typeof Composite > = { - title: 'Components/Composite', + title: 'Components/Utilities/Composite', + id: 'components-composite', component: Composite, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 diff --git a/packages/components/src/disabled/stories/index.story.tsx b/packages/components/src/disabled/stories/index.story.tsx index b5da6ccedddc07..59ff84dec43fca 100644 --- a/packages/components/src/disabled/stories/index.story.tsx +++ b/packages/components/src/disabled/stories/index.story.tsx @@ -18,7 +18,8 @@ import TextareaControl from '../../textarea-control/'; import { VStack } from '../../v-stack/'; const meta: Meta< typeof Disabled > = { - title: 'Components/Disabled', + title: 'Components/Utilities/Disabled', + id: 'components-disabled', component: Disabled, argTypes: { as: { control: { type: null } }, diff --git a/packages/components/src/draggable/stories/index.story.tsx b/packages/components/src/draggable/stories/index.story.tsx index fc48618b1083a3..6ecb54a07a3fb2 100644 --- a/packages/components/src/draggable/stories/index.story.tsx +++ b/packages/components/src/draggable/stories/index.story.tsx @@ -18,7 +18,8 @@ import Draggable from '..'; const meta: Meta< typeof Draggable > = { component: Draggable, - title: 'Components/Draggable', + title: 'Components/Utilities/Draggable', + id: 'components-draggable', argTypes: { elementId: { control: { type: null } }, __experimentalDragComponent: { control: { type: null } }, diff --git a/packages/components/src/keyboard-shortcuts/stories/index.story.tsx b/packages/components/src/keyboard-shortcuts/stories/index.story.tsx index 9e3a1e207451bb..0c8e0f451929a0 100644 --- a/packages/components/src/keyboard-shortcuts/stories/index.story.tsx +++ b/packages/components/src/keyboard-shortcuts/stories/index.story.tsx @@ -10,7 +10,8 @@ import KeyboardShortcuts from '..'; const meta: Meta< typeof KeyboardShortcuts > = { component: KeyboardShortcuts, - title: 'Components/KeyboardShortcuts', + title: 'Components/Utilities/KeyboardShortcuts', + id: 'components-keyboardshortcuts', parameters: { controls: { expanded: true }, docs: { canvas: { sourceState: 'shown' } }, diff --git a/packages/components/src/resizable-box/stories/index.story.tsx b/packages/components/src/resizable-box/stories/index.story.tsx index 81852f9cb4ea43..489a094c33f119 100644 --- a/packages/components/src/resizable-box/stories/index.story.tsx +++ b/packages/components/src/resizable-box/stories/index.story.tsx @@ -14,7 +14,8 @@ import ResizableBox from '..'; import { useState } from '@wordpress/element'; const meta: Meta< typeof ResizableBox > = { - title: 'Components/ResizableBox', + title: 'Components/Utilities/ResizableBox', + id: 'components-resizablebox', component: ResizableBox, argTypes: { children: { control: { type: null } }, diff --git a/packages/components/src/sandbox/stories/index.story.tsx b/packages/components/src/sandbox/stories/index.story.tsx index efa8db621a4a63..0d083eac3e9026 100644 --- a/packages/components/src/sandbox/stories/index.story.tsx +++ b/packages/components/src/sandbox/stories/index.story.tsx @@ -10,7 +10,8 @@ import SandBox from '..'; const meta: Meta< typeof SandBox > = { component: SandBox, - title: 'Components/SandBox', + title: 'Components/Utilities/SandBox', + id: 'components-sandbox', argTypes: { onFocus: { control: { type: null } }, }, diff --git a/packages/components/src/scroll-lock/stories/index.story.tsx b/packages/components/src/scroll-lock/stories/index.story.tsx index 8518c0c520a486..b251018f00b38e 100644 --- a/packages/components/src/scroll-lock/stories/index.story.tsx +++ b/packages/components/src/scroll-lock/stories/index.story.tsx @@ -17,7 +17,8 @@ import ScrollLock from '..'; const meta: Meta< typeof ScrollLock > = { component: ScrollLock, - title: 'Components/ScrollLock', + title: 'Components/Utilities/ScrollLock', + id: 'components-scrolllock', parameters: { controls: { hideNoControlsWarning: true }, docs: { canvas: { sourceState: 'shown' } }, diff --git a/packages/components/src/shortcut/stories/index.story.tsx b/packages/components/src/shortcut/stories/index.story.tsx index 27e96e3f6d1984..b0bd31ac51cf4b 100644 --- a/packages/components/src/shortcut/stories/index.story.tsx +++ b/packages/components/src/shortcut/stories/index.story.tsx @@ -10,7 +10,8 @@ import Shortcut from '../'; const meta: Meta< typeof Shortcut > = { component: Shortcut, - title: 'Components/Shortcut', + title: 'Components/Utilities/Shortcut', + id: 'components-shortcut', parameters: { controls: { expanded: true, diff --git a/packages/components/src/slot-fill/stories/index.story.tsx b/packages/components/src/slot-fill/stories/index.story.tsx index ee00a12d698954..bc6c4f57ad9ce1 100644 --- a/packages/components/src/slot-fill/stories/index.story.tsx +++ b/packages/components/src/slot-fill/stories/index.story.tsx @@ -15,7 +15,8 @@ import { Slot, Fill, Provider as SlotFillProvider } from '../'; const meta: Meta< typeof Slot > = { component: Slot, - title: 'Components/SlotFill', + title: 'Components/Utilities/SlotFill', + id: 'components-slotfill', // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { Fill, SlotFillProvider }, argTypes: { diff --git a/packages/components/src/theme/stories/index.story.tsx b/packages/components/src/theme/stories/index.story.tsx index d0af0a9b974fe3..67eec72533ff3f 100644 --- a/packages/components/src/theme/stories/index.story.tsx +++ b/packages/components/src/theme/stories/index.story.tsx @@ -13,7 +13,8 @@ import { HStack } from '../../h-stack'; const meta: Meta< typeof Theme > = { component: Theme, - title: 'Components/Theme', + title: 'Components/Utilities/Theme', + id: 'components-theme', argTypes: { accent: { control: { type: 'color' } }, background: { control: { type: 'color' } }, diff --git a/packages/components/src/visually-hidden/stories/index.story.tsx b/packages/components/src/visually-hidden/stories/index.story.tsx index 149b2da6b5c891..8abe45a94aab4f 100644 --- a/packages/components/src/visually-hidden/stories/index.story.tsx +++ b/packages/components/src/visually-hidden/stories/index.story.tsx @@ -10,7 +10,8 @@ import { VisuallyHidden } from '..'; const meta: Meta< typeof VisuallyHidden > = { component: VisuallyHidden, - title: 'Components/VisuallyHidden', + title: 'Components/Utilities/VisuallyHidden', + id: 'components-visuallyhidden', argTypes: { children: { control: { type: null } }, as: { control: { type: 'text' } }, diff --git a/storybook/preview.js b/storybook/preview.js index 97be7205349100..21f2eab912059a 100644 --- a/storybook/preview.js +++ b/storybook/preview.js @@ -132,6 +132,7 @@ export const parameters = { 'Contributing Guidelines', 'Actions', 'Containers', + 'Utilities', ], 'Components (Experimental)', 'Icons', From 88de21bac0c2652beb2b835fbce0ea3e2a1bdf89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:50:54 +0200 Subject: [PATCH 1258/1908] Block inserter: prevent editor from crashing if `blockType.parent` is a string (#66234) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/block-editor/src/store/selectors.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 3fdaadb24fc129..787225f18a0a57 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -1628,8 +1628,18 @@ const isBlockVisibleInTheInserter = ( checkedBlocks.add( blockName ); // If parent blocks are not visible, child blocks should be hidden too. - if ( !! blockType.parent?.length ) { - return blockType.parent.some( + // + // In some scenarios, blockType.parent may be a string. + // A better approach would be sanitize parent in all the places that can be modified: + // block registration, processBlockType, filters, etc. + // In the meantime, this is a hotfix to prevent the editor from crashing. + const parent = + typeof blockType.parent === 'string' || + blockType.parent instanceof String + ? [ blockType.parent ] + : blockType.parent; + if ( Array.isArray( parent ) ) { + return parent.some( ( name ) => ( blockName !== name && isBlockVisibleInTheInserter( @@ -1643,6 +1653,7 @@ const isBlockVisibleInTheInserter = ( name === 'core/post-content' ); } + return true; }; From a41659632a1bd90a767cfe214db3eb94858a12bb Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 21 Oct 2024 19:25:00 +0900 Subject: [PATCH 1259/1908] Editor: Handle zoom out state via the 'switchEditorMode' action (#66262) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/editor/src/components/text-editor/index.js | 11 +---------- packages/editor/src/store/actions.js | 4 +++- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/editor/src/components/text-editor/index.js b/packages/editor/src/components/text-editor/index.js index 6997c66826a12d..fa0688859b5a69 100644 --- a/packages/editor/src/components/text-editor/index.js +++ b/packages/editor/src/components/text-editor/index.js @@ -6,7 +6,6 @@ import { useDispatch, useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts'; import { useEffect, useRef } from '@wordpress/element'; -import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Internal dependencies @@ -14,7 +13,6 @@ import { store as blockEditorStore } from '@wordpress/block-editor'; import { store as editorStore } from '../../store'; import PostTextEditor from '../post-text-editor'; import PostTitleRaw from '../post-title/post-title-raw'; -import { unlock } from '../../lock-unlock'; export default function TextEditor( { autoFocus = false } ) { const { switchEditorMode } = useDispatch( editorStore ); @@ -28,20 +26,13 @@ export default function TextEditor( { autoFocus = false } ) { }; }, [] ); - const { resetZoomLevel, __unstableSetEditorMode } = unlock( - useDispatch( blockEditorStore ) - ); - const titleRef = useRef(); useEffect( () => { - resetZoomLevel(); - __unstableSetEditorMode( 'edit' ); - if ( autoFocus ) { return; } titleRef?.current?.focus(); - }, [ autoFocus, resetZoomLevel, __unstableSetEditorMode ] ); + }, [ autoFocus ] ); return ( <div className="editor-text-editor"> diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index 70be70c6293399..f28f5feeead179 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -883,9 +883,11 @@ export const switchEditorMode = ( { dispatch, registry } ) => { registry.dispatch( preferencesStore ).set( 'core', 'editorMode', mode ); - // Unselect blocks when we switch to a non visual mode. if ( mode !== 'visual' ) { + // Unselect blocks when we switch to a non visual mode. registry.dispatch( blockEditorStore ).clearSelectedBlock(); + // Exit zoom out state when switching to a non visual mode. + unlock( registry.dispatch( blockEditorStore ) ).resetZoomLevel(); } if ( mode === 'visual' ) { From 3b2b2ed288dc691bfc86ba28c2df8bfb47ca428a Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 21 Oct 2024 19:25:19 +0900 Subject: [PATCH 1260/1908] Editor: No need to reset mode when changing device preview types (#66261) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> --- packages/editor/src/components/preview-dropdown/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js index 0fbb2beb62665e..e7a19f92548f5f 100644 --- a/packages/editor/src/components/preview-dropdown/index.js +++ b/packages/editor/src/components/preview-dropdown/index.js @@ -46,12 +46,10 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { }; }, [] ); const { setDeviceType } = useDispatch( editorStore ); - const { __unstableSetEditorMode } = useDispatch( blockEditorStore ); const { resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); const handleDevicePreviewChange = ( newDeviceType ) => { setDeviceType( newDeviceType ); - __unstableSetEditorMode( 'edit' ); resetZoomLevel(); }; From 55a701641146dc4c5c2cb2162ce581e59f176716 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 21 Oct 2024 19:26:08 +0900 Subject: [PATCH 1261/1908] Block Editor: No need to unlock public actions (#66260) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/block-editor/src/components/tool-selector/index.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/tool-selector/index.js b/packages/block-editor/src/components/tool-selector/index.js index d4ba5d58ea61eb..8c4b5c86c40828 100644 --- a/packages/block-editor/src/components/tool-selector/index.js +++ b/packages/block-editor/src/components/tool-selector/index.js @@ -18,7 +18,6 @@ import { Icon, edit as editIcon } from '@wordpress/icons'; * Internal dependencies */ import { store as blockEditorStore } from '../../store'; -import { unlock } from '../../lock-unlock'; const selectIcon = ( <SVG @@ -36,9 +35,7 @@ function ToolSelector( props, ref ) { ( select ) => select( blockEditorStore ).__unstableGetEditorMode(), [] ); - const { __unstableSetEditorMode } = unlock( - useDispatch( blockEditorStore ) - ); + const { __unstableSetEditorMode } = useDispatch( blockEditorStore ); return ( <Dropdown From 75e336606c8edcc8e557760b8407935c59eb4d44 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 21 Oct 2024 12:42:00 +0200 Subject: [PATCH 1262/1908] Style Book: clean up layout (#66255) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/components/style-book/index.js | 65 +++++++++---------- .../src/components/style-book/style.scss | 26 ++++---- 2 files changed, 44 insertions(+), 47 deletions(-) diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 7b85c320e20c99..42b6e3f4fc99b6 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -120,39 +120,38 @@ function StyleBook( { > { resizeObserver } { showTabs ? ( - <div className="edit-site-style-book__tabs"> - <Tabs> - <div className="edit-site-style-book__tablist-container"> - <Tabs.TabList> - { tabs.map( ( tab ) => ( - <Tabs.Tab - tabId={ tab.slug } - key={ tab.slug } - > - { tab.title } - </Tabs.Tab> - ) ) } - </Tabs.TabList> - </div> - { tabs.map( ( tab ) => ( - <Tabs.TabPanel - key={ tab.slug } - tabId={ tab.slug } - focusable={ false } - > - <StyleBookBody - category={ tab.slug } - examples={ examples } - isSelected={ isSelected } - onSelect={ onSelect } - settings={ settings } - sizes={ sizes } - title={ tab.title } - /> - </Tabs.TabPanel> - ) ) } - </Tabs> - </div> + <Tabs> + <div className="edit-site-style-book__tablist-container"> + <Tabs.TabList> + { tabs.map( ( tab ) => ( + <Tabs.Tab + tabId={ tab.slug } + key={ tab.slug } + > + { tab.title } + </Tabs.Tab> + ) ) } + </Tabs.TabList> + </div> + { tabs.map( ( tab ) => ( + <Tabs.TabPanel + key={ tab.slug } + tabId={ tab.slug } + focusable={ false } + className="edit-site-style-book__tabpanel" + > + <StyleBookBody + category={ tab.slug } + examples={ examples } + isSelected={ isSelected } + onSelect={ onSelect } + settings={ settings } + sizes={ sizes } + title={ tab.title } + /> + </Tabs.TabPanel> + ) ) } + </Tabs> ) : ( <StyleBookBody examples={ examples } diff --git a/packages/edit-site/src/components/style-book/style.scss b/packages/edit-site/src/components/style-book/style.scss index 3e0c6466438a22..773b4f10f581bb 100644 --- a/packages/edit-site/src/components/style-book/style.scss +++ b/packages/edit-site/src/components/style-book/style.scss @@ -5,6 +5,10 @@ &.is-button { border-radius: $radius-large; } + + display: flex; + flex-direction: column; + align-items: stretch; } .edit-site-style-book__iframe { @@ -18,22 +22,16 @@ } .edit-site-style-book__tablist-container { - background: $white; + flex: none; + + display: flex; width: 100%; padding-right: 56px; - display: flex; - position: absolute; - z-index: 1; + background: $white; } -.edit-site-style-book__tabs { - [role="tabpanel"] { - bottom: 0; - left: 0; - overflow: auto; - padding: 0; - position: absolute; - right: 0; - top: $grid-unit-60; // Height of tabs. - } +.edit-site-style-book__tabpanel { + flex: 1 0 auto; + + overflow: auto; } From 12c8ca7f2b2706abb96688a9f1515c462abd4366 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 21 Oct 2024 13:10:49 +0200 Subject: [PATCH 1263/1908] Group: fix padding select (#65857) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../src/components/block-list/content.scss | 2 +- .../src/components/writing-flow/index.js | 8 +++++--- packages/block-library/src/group/editor.scss | 12 ++++++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index b42ebe349d5997..3d3b8517ca09c3 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -24,7 +24,7 @@ // hack a progressive enhancement. /* stylelint-disable -- Stylelint is disabled to allow the hack to work. */ _::-webkit-full-page-media, _:future, :root .block-editor-block-list__layout::selection, -_::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-block-list__layout::selection { +_::-webkit-full-page-media, _:future, :root [data-has-multi-selection="true"] .block-editor-block-list__layout::selection { background-color: transparent; } /* stylelint-enable */ diff --git a/packages/block-editor/src/components/writing-flow/index.js b/packages/block-editor/src/components/writing-flow/index.js index 7e6b36b0e22143..cb789bdd7035b4 100644 --- a/packages/block-editor/src/components/writing-flow/index.js +++ b/packages/block-editor/src/components/writing-flow/index.js @@ -47,19 +47,21 @@ export function useWritingFlow() { useRefEffect( ( node ) => { node.tabIndex = 0; + node.dataset.hasMultiSelection = hasMultiSelection; if ( ! hasMultiSelection ) { - return; + return () => { + delete node.dataset.hasMultiSelection; + }; } - node.classList.add( 'has-multi-selection' ); node.setAttribute( 'aria-label', __( 'Multiple selected blocks' ) ); return () => { - node.classList.remove( 'has-multi-selection' ); + delete node.dataset.hasMultiSelection; node.removeAttribute( 'aria-label' ); }; }, diff --git a/packages/block-library/src/group/editor.scss b/packages/block-library/src/group/editor.scss index 739a9cd0cf852e..12f5028b96ec3d 100644 --- a/packages/block-library/src/group/editor.scss +++ b/packages/block-library/src/group/editor.scss @@ -10,6 +10,18 @@ } } +// Reset user select, but the next rule should take precedence for nested +// groups. +:where([data-has-multi-selection]:not([contenteditable="true"]) .wp-block-group > *) { + user-select: initial; +} + +// When we are not multi-selecting, prevent children from capturing the +// selection, which happens when the group is flex and children inlined. +:where([data-has-multi-selection]:not([contenteditable="true"]) .wp-block-group) { + user-select: none; +} + // Place block list appender in the same place content will appear. [data-type="core/group"].is-selected { .block-list-appender { From 5d7ecbe3487dfdad7e39fd0df9fac4c5f798f7a2 Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Mon, 21 Oct 2024 14:41:05 +0200 Subject: [PATCH 1264/1908] Add new private `vips` package (#64845) --- package-lock.json | 26 ++ package.json | 1 + packages/vips/.npmrc | 1 + packages/vips/CHANGELOG.md | 7 + packages/vips/README.md | 98 +++++++ packages/vips/package.json | 35 +++ packages/vips/src/index.ts | 366 +++++++++++++++++++++++++ packages/vips/src/test/resize-image.ts | 223 +++++++++++++++ packages/vips/src/types.ts | 170 ++++++++++++ packages/vips/src/utils.ts | 43 +++ packages/vips/tsconfig.json | 9 + patches/wasm-vips+0.0.10.patch | 15 + test/unit/config/global-mocks.js | 5 + test/unit/config/wasm-stub.js | 1 + test/unit/jest.config.js | 1 + tools/webpack/packages.js | 14 + tsconfig.json | 1 + 17 files changed, 1016 insertions(+) create mode 100644 packages/vips/.npmrc create mode 100644 packages/vips/CHANGELOG.md create mode 100644 packages/vips/README.md create mode 100644 packages/vips/package.json create mode 100644 packages/vips/src/index.ts create mode 100644 packages/vips/src/test/resize-image.ts create mode 100644 packages/vips/src/types.ts create mode 100644 packages/vips/src/utils.ts create mode 100644 packages/vips/tsconfig.json create mode 100644 patches/wasm-vips+0.0.10.patch create mode 100644 test/unit/config/wasm-stub.js diff --git a/package-lock.json b/package-lock.json index 22c37a17c7c28d..82cf77db40c57d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -79,6 +79,7 @@ "@wordpress/undo-manager": "file:packages/undo-manager", "@wordpress/url": "file:packages/url", "@wordpress/viewport": "file:packages/viewport", + "@wordpress/vips": "file:packages/vips", "@wordpress/warning": "file:packages/warning", "@wordpress/widgets": "file:packages/widgets", "@wordpress/wordcount": "file:packages/wordcount" @@ -17438,6 +17439,10 @@ "resolved": "packages/viewport", "link": true }, + "node_modules/@wordpress/vips": { + "resolved": "packages/vips", + "link": true + }, "node_modules/@wordpress/warning": { "resolved": "packages/warning", "link": true @@ -50418,6 +50423,15 @@ "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz", "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==" }, + "node_modules/wasm-vips": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/wasm-vips/-/wasm-vips-0.0.10.tgz", + "integrity": "sha512-ZDIRjxTm03iRRXM9WwvVh8MH+mKHUBedJTC/MYd/cVGZxShnYcEd0BB7gSGDpxgkzcPSYUnN1HQJipDBhxVHTg==", + "license": "MIT", + "engines": { + "node": ">=16.4.0" + } + }, "node_modules/watchpack": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", @@ -57229,6 +57243,18 @@ "react": "^18.0.0" } }, + "packages/vips": { + "name": "@wordpress/vips", + "version": "1.0.0-prerelease", + "license": "GPL-2.0-or-later", + "dependencies": { + "wasm-vips": "^0.0.10" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, "packages/warning": { "name": "@wordpress/warning", "version": "3.10.0", diff --git a/package.json b/package.json index ae86dc0d1577c4..c280e1b728c3df 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,7 @@ "@wordpress/undo-manager": "file:packages/undo-manager", "@wordpress/url": "file:packages/url", "@wordpress/viewport": "file:packages/viewport", + "@wordpress/vips": "file:packages/vips", "@wordpress/warning": "file:packages/warning", "@wordpress/widgets": "file:packages/widgets", "@wordpress/wordcount": "file:packages/wordcount" diff --git a/packages/vips/.npmrc b/packages/vips/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/vips/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/vips/CHANGELOG.md b/packages/vips/CHANGELOG.md new file mode 100644 index 00000000000000..691cb6760320f4 --- /dev/null +++ b/packages/vips/CHANGELOG.md @@ -0,0 +1,7 @@ +<!-- Learn how to maintain this file at https://github.com/WordPress/gutenberg/tree/HEAD/packages#maintaining-changelogs. --> + +## Unreleased + +### New Features + +- Initial public release. diff --git a/packages/vips/README.md b/packages/vips/README.md new file mode 100644 index 00000000000000..d7bf6001b51027 --- /dev/null +++ b/packages/vips/README.md @@ -0,0 +1,98 @@ +# `@wordpress/vips` + +Helper package to interact with [`wasm-vips`](https://github.com/kleisauke/wasm-vips). + +## Installation + +Install the module + +```bash +npm install @wordpress/vips --save +``` + +## API Reference + +<!-- START TOKEN(Autogenerated API docs) --> + +### cancelOperations + +Cancels all ongoing image operations for a given item ID. + +The onProgress callbacks check for an IDs existence in this list, killing the process if it's absent. + +_Parameters_ + +- _id_ `ItemId`: Item ID. + +_Returns_ + +- boolean Whether any operation was cancelled. + +### compressImage + +Compresses an existing image using vips. + +_Parameters_ + +- _id_ `ItemId`: Item ID. +- _buffer_ `ArrayBuffer`: Original file buffer. +- _type_ `string`: Mime type. +- _quality_ Desired quality. +- _interlaced_ Whether to use interlaced/progressive mode. Only used if the outputType supports it. + +_Returns_ + +- `Promise< ArrayBuffer >`: Compressed file data. + +### convertImageFormat + +Converts an image to a different format using vips. + +_Parameters_ + +- _id_ `ItemId`: Item ID. +- _buffer_ `ArrayBuffer`: Original file buffer. +- _inputType_ `string`: Input mime type. +- _outputType_ `string`: Output mime type. +- _quality_ Desired quality. +- _interlaced_ Whether to use interlaced/progressive mode. Only used if the outputType supports it. + +### hasTransparency + +Determines whether an image has an alpha channel. + +_Parameters_ + +- _buffer_ `ArrayBuffer`: Original file object. + +_Returns_ + +- `Promise< boolean >`: Whether the image has an alpha channel. + +### resizeImage + +Resizes an image using vips. + +_Parameters_ + +- _id_ `ItemId`: Item ID. +- _buffer_ `ArrayBuffer`: Original file buffer. +- _type_ `string`: Mime type. +- _resize_ `ImageSizeCrop`: Resize options. +- _smartCrop_ Whether to use smart cropping (i.e. saliency-aware). + +_Returns_ + +- `Promise< { buffer: ArrayBuffer; width: number; height: number; originalWidth: number; originalHeight: number; } >`: Processed file data plus the old and new dimensions. + +### setLocation + +Dynamically sets the location / public path to use for loading the WASM files. + +This is required when loading this module in an inline worker, where globals such as **webpack_public_path** are not available. + +_Parameters_ + +- _newLocation_ `string`: Location, typically a base URL such as "<https://example.com/path/to/js/...">. + +<!-- END TOKEN(Autogenerated API docs) --> diff --git a/packages/vips/package.json b/packages/vips/package.json new file mode 100644 index 00000000000000..34d5e3fff3fb18 --- /dev/null +++ b/packages/vips/package.json @@ -0,0 +1,35 @@ +{ + "name": "@wordpress/vips", + "version": "1.0.0-prerelease", + "private": true, + "description": "Utils for working with libvips.", + "author": "The WordPress Contributors", + "license": "GPL-2.0-or-later", + "keywords": [ + "wordpress", + "media", + "libvips" + ], + "homepage": "https://github.com/WordPress/gutenberg/tree/HEAD/packages/vips/README.md", + "repository": { + "type": "git", + "url": "https://github.com/WordPress/gutenberg.git", + "directory": "packages/vips" + }, + "bugs": { + "url": "https://github.com/WordPress/gutenberg/issues" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "main": "build/index.js", + "module": "build-module/index.js", + "types": "build-types", + "dependencies": { + "wasm-vips": "^0.0.10" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/vips/src/index.ts b/packages/vips/src/index.ts new file mode 100644 index 00000000000000..5dffe1f0808f28 --- /dev/null +++ b/packages/vips/src/index.ts @@ -0,0 +1,366 @@ +/** + * External dependencies + */ +import Vips from 'wasm-vips'; + +// @ts-expect-error +// eslint-disable-next-line import/no-unresolved +import VipsModule from 'wasm-vips/vips.wasm'; + +// @ts-expect-error +// eslint-disable-next-line import/no-unresolved +import VipsHeifModule from 'wasm-vips/vips-heif.wasm'; + +// @ts-expect-error +// eslint-disable-next-line import/no-unresolved +import VipsJxlModule from 'wasm-vips/vips-jxl.wasm'; + +/** + * Internal dependencies + */ +import type { + ItemId, + ImageSizeCrop, + LoadOptions, + SaveOptions, + ThumbnailOptions, +} from './types'; +import { supportsAnimation, supportsInterlace, supportsQuality } from './utils'; + +interface EmscriptenModule { + setAutoDeleteLater: ( autoDelete: boolean ) => void; + setDelayFunction: ( fn: ( fn: () => void ) => void ) => void; +} + +let location = ''; + +/** + * Dynamically sets the location / public path to use for loading the WASM files. + * + * This is required when loading this module in an inline worker, + * where globals such as __webpack_public_path__ are not available. + * + * @param newLocation Location, typically a base URL such as "https://example.com/path/to/js/...". + */ +export function setLocation( newLocation: string ) { + location = newLocation; +} + +let cleanup: () => void; + +let vipsInstance: typeof Vips; + +/** + * Instantiates and returns a new vips instance. + * + * Reuses any existing instance. + */ +async function getVips(): Promise< typeof Vips > { + if ( vipsInstance ) { + return vipsInstance; + } + + vipsInstance = await Vips( { + locateFile: ( fileName: string ) => { + if ( fileName.endsWith( 'vips.wasm' ) ) { + fileName = VipsModule; + } else if ( fileName.endsWith( 'vips-heif.wasm' ) ) { + fileName = VipsHeifModule; + } else if ( fileName.endsWith( 'vips-jxl.wasm' ) ) { + fileName = VipsJxlModule; + } + + return location + fileName; + }, + preRun: ( module: EmscriptenModule ) => { + // https://github.com/kleisauke/wasm-vips/issues/13#issuecomment-1073246828 + module.setAutoDeleteLater( true ); + module.setDelayFunction( ( fn: () => void ) => { + cleanup = fn; + } ); + }, + } ); + + return vipsInstance; +} + +/** + * Holds a list of ongoing operations for a given ID. + * + * This way, operations can be cancelled mid-progress. + */ +const inProgressOperations = new Set< ItemId >(); + +/** + * Cancels all ongoing image operations for a given item ID. + * + * The onProgress callbacks check for an IDs existence in this list, + * killing the process if it's absent. + * + * @param id Item ID. + * @return boolean Whether any operation was cancelled. + */ +export async function cancelOperations( id: ItemId ) { + return inProgressOperations.delete( id ); +} + +/** + * Converts an image to a different format using vips. + * + * @param id Item ID. + * @param buffer Original file buffer. + * @param inputType Input mime type. + * @param outputType Output mime type. + * @param quality Desired quality. + * @param interlaced Whether to use interlaced/progressive mode. + * Only used if the outputType supports it. + */ +export async function convertImageFormat( + id: ItemId, + buffer: ArrayBuffer, + inputType: string, + outputType: string, + quality = 0.82, + interlaced = false +): Promise< ArrayBuffer > { + const ext = outputType.split( '/' )[ 1 ]; + + inProgressOperations.add( id ); + + let strOptions = ''; + const loadOptions: LoadOptions< typeof inputType > = {}; + + // To ensure all frames are loaded in case the image is animated. + if ( supportsAnimation( inputType ) ) { + strOptions = '[n=-1]'; + ( loadOptions as LoadOptions< typeof inputType > ).n = -1; + } + + const vips = await getVips(); + const image = vips.Image.newFromBuffer( buffer, strOptions, loadOptions ); + + // TODO: Report progress, see https://github.com/swissspidy/media-experiments/issues/327. + image.onProgress = () => { + if ( ! inProgressOperations.has( id ) ) { + image.kill = true; + } + }; + + const saveOptions: SaveOptions< typeof outputType > = {}; + + if ( supportsQuality( outputType ) ) { + saveOptions.Q = quality * 100; + } + + if ( interlaced && supportsInterlace( outputType ) ) { + saveOptions.interlace = interlaced; + } + + // See https://github.com/swissspidy/media-experiments/issues/324. + if ( 'image/avif' === outputType ) { + saveOptions.effort = 2; + } + + const outBuffer = image.writeToBuffer( `.${ ext }`, saveOptions ); + const result = outBuffer.buffer; + + cleanup?.(); + + return result; +} + +/** + * Compresses an existing image using vips. + * + * @param id Item ID. + * @param buffer Original file buffer. + * @param type Mime type. + * @param quality Desired quality. + * @param interlaced Whether to use interlaced/progressive mode. + * Only used if the outputType supports it. + * @return Compressed file data. + */ +export async function compressImage( + id: ItemId, + buffer: ArrayBuffer, + type: string, + quality = 0.82, + interlaced = false +): Promise< ArrayBuffer > { + return convertImageFormat( id, buffer, type, type, quality, interlaced ); +} + +/** + * Resizes an image using vips. + * + * @param id Item ID. + * @param buffer Original file buffer. + * @param type Mime type. + * @param resize Resize options. + * @param smartCrop Whether to use smart cropping (i.e. saliency-aware). + * @return Processed file data plus the old and new dimensions. + */ +export async function resizeImage( + id: ItemId, + buffer: ArrayBuffer, + type: string, + resize: ImageSizeCrop, + smartCrop = false +): Promise< { + buffer: ArrayBuffer; + width: number; + height: number; + originalWidth: number; + originalHeight: number; +} > { + const ext = type.split( '/' )[ 1 ]; + + inProgressOperations.add( id ); + + const vips = await getVips(); + const thumbnailOptions: ThumbnailOptions = { + size: 'down', + }; + + let strOptions = ''; + const loadOptions: LoadOptions< typeof type > = {}; + + // To ensure all frames are loaded in case the image is animated. + // But only if we're not cropping. + if ( supportsAnimation( type ) && ! resize.crop ) { + strOptions = '[n=-1]'; + thumbnailOptions.option_string = strOptions; + ( loadOptions as LoadOptions< typeof type > ).n = -1; + } + + // TODO: Report progress, see https://github.com/swissspidy/media-experiments/issues/327. + const onProgress = () => { + if ( ! inProgressOperations.has( id ) ) { + image.kill = true; + } + }; + + let image = vips.Image.newFromBuffer( buffer, strOptions, loadOptions ); + + image.onProgress = onProgress; + + const { width, pageHeight } = image; + + // If resize.height is zero. + resize.height = resize.height || ( pageHeight / width ) * resize.width; + + let resizeWidth = resize.width; + thumbnailOptions.height = resize.height; + + if ( ! resize.crop ) { + image = vips.Image.thumbnailBuffer( + buffer, + resizeWidth, + thumbnailOptions + ); + + image.onProgress = onProgress; + } else if ( true === resize.crop ) { + thumbnailOptions.crop = smartCrop ? 'attention' : 'centre'; + + image = vips.Image.thumbnailBuffer( + buffer, + resizeWidth, + thumbnailOptions + ); + + image.onProgress = onProgress; + } else { + // First resize, then do the cropping. + // This allows operating on the second bitmap with the correct dimensions. + + if ( width < pageHeight ) { + resizeWidth = + resize.width >= resize.height + ? resize.width + : ( width / pageHeight ) * resize.height; + thumbnailOptions.height = + resize.width >= resize.height + ? ( pageHeight / width ) * resizeWidth + : resize.height; + } else { + resizeWidth = + resize.width >= resize.height + ? ( width / pageHeight ) * resize.height + : resize.width; + thumbnailOptions.height = + resize.width >= resize.height + ? resize.height + : ( pageHeight / width ) * resizeWidth; + } + + image = vips.Image.thumbnailBuffer( + buffer, + resizeWidth, + thumbnailOptions + ); + + image.onProgress = onProgress; + + let left = 0; + if ( 'center' === resize.crop[ 0 ] ) { + left = ( image.width - resize.width ) / 2; + } else if ( 'right' === resize.crop[ 0 ] ) { + left = image.width - resize.width; + } + + let top = 0; + if ( 'center' === resize.crop[ 1 ] ) { + top = ( image.height - resize.height ) / 2; + } else if ( 'bottom' === resize.crop[ 1 ] ) { + top = image.height - resize.height; + } + + // Address rounding errors where `left` or `top` become negative integers + // and `resize.width` / `resize.height` are bigger than the actual dimensions. + // Downside: one side could be 1px smaller than the requested size. + left = Math.max( 0, left ); + top = Math.max( 0, top ); + resize.width = Math.min( image.width, resize.width ); + resize.height = Math.min( image.height, resize.height ); + + image = image.crop( left, top, resize.width, resize.height ); + + image.onProgress = onProgress; + } + + // TODO: Allow passing quality? + const saveOptions: SaveOptions< typeof type > = {}; + const outBuffer = image.writeToBuffer( `.${ ext }`, saveOptions ); + + const result = { + buffer: outBuffer.buffer, + width: image.width, + height: image.pageHeight, + originalWidth: width, + originalHeight: pageHeight, + }; + + // Only call after `image` is no longer being used. + cleanup?.(); + + return result; +} + +/** + * Determines whether an image has an alpha channel. + * + * @param buffer Original file object. + * @return Whether the image has an alpha channel. + */ +export async function hasTransparency( + buffer: ArrayBuffer +): Promise< boolean > { + const vips = await getVips(); + const image = vips.Image.newFromBuffer( buffer ); + const hasAlpha = image.hasAlpha(); + + cleanup?.(); + + return hasAlpha; +} diff --git a/packages/vips/src/test/resize-image.ts b/packages/vips/src/test/resize-image.ts new file mode 100644 index 00000000000000..1f1155d388d42c --- /dev/null +++ b/packages/vips/src/test/resize-image.ts @@ -0,0 +1,223 @@ +/** + * Internal dependencies + */ +import { resizeImage } from '../'; +import type { ImageSizeCrop } from '../types'; + +const mockThumbnailBuffer = jest.fn( () => new MockImage() ); +const mockCrop = jest.fn( () => new MockImage() ); +const mockNewFromBuffer = jest.fn( () => new MockImage() ); + +class MockImage { + width = 100; + height = 100; + pageHeight = 100; + crop = mockCrop; + writeToBuffer = jest.fn( () => ( { + buffer: '', + } ) ); +} + +class MockVipsImage { + static thumbnailBuffer = mockThumbnailBuffer; + static newFromBuffer = mockNewFromBuffer; +} + +jest.mock( 'wasm-vips', () => + jest.fn( () => ( { + Image: MockVipsImage, + } ) ) +); + +describe( 'resizeImage', () => { + afterEach( () => { + jest.clearAllMocks(); + } ); + + it( 'resizes without crop', async () => { + const jpegFile = new File( [ '<BLOB>' ], 'example.jpg', { + lastModified: 1234567891, + type: 'image/jpeg', + } ); + const buffer = await jpegFile.arrayBuffer(); + + await resizeImage( 'itemId', buffer, 'image/jpeg', { + width: 100, + height: 100, + } ); + + expect( mockThumbnailBuffer ).toHaveBeenCalledWith( buffer, 100, { + height: 100, + size: 'down', + } ); + expect( mockCrop ).not.toHaveBeenCalled(); + } ); + + it( 'resizes without crop and zero height', async () => { + const jpegFile = new File( [], 'example.jpg', { + lastModified: 1234567891, + type: 'image/jpeg', + } ); + const buffer = await jpegFile.arrayBuffer(); + + await resizeImage( 'itemId', buffer, 'image/jpeg', { + width: 100, + height: 0, + } ); + + expect( mockThumbnailBuffer ).toHaveBeenCalledWith( buffer, 100, { + size: 'down', + height: 100, + } ); + expect( mockCrop ).not.toHaveBeenCalled(); + } ); + + it( 'resizes with center crop', async () => { + const jpegFile = new File( [ '<BLOB>' ], 'example.jpg', { + lastModified: 1234567891, + type: 'image/jpeg', + } ); + const buffer = await jpegFile.arrayBuffer(); + + await resizeImage( 'itemId', buffer, 'image/jpeg', { + width: 100, + height: 100, + crop: true, + } ); + + expect( mockThumbnailBuffer ).toHaveBeenCalledWith( buffer, 100, { + height: 100, + crop: 'centre', + size: 'down', + } ); + expect( mockCrop ).not.toHaveBeenCalled(); + } ); + + it( 'resizes with center crop and zero height', async () => { + const jpegFile = new File( [ '<BLOB>' ], 'example.jpg', { + lastModified: 1234567891, + type: 'image/jpeg', + } ); + const buffer = await jpegFile.arrayBuffer(); + + await resizeImage( 'itemId', buffer, 'image/jpeg', { + width: 100, + height: 0, + crop: true, + } ); + + expect( mockThumbnailBuffer ).toHaveBeenCalledWith( buffer, 100, { + crop: 'centre', + height: 100, + size: 'down', + } ); + expect( mockCrop ).not.toHaveBeenCalled(); + } ); + + it( 'resizes without crop and attention strategy', async () => { + const jpegFile = new File( [ '<BLOB>' ], 'example.jpg', { + lastModified: 1234567891, + type: 'image/jpeg', + } ); + const buffer = await jpegFile.arrayBuffer(); + + await resizeImage( + 'itemId', + buffer, + 'image/jpeg', + { + width: 100, + height: 100, + }, + true + ); + + expect( mockThumbnailBuffer ).toHaveBeenCalledWith( buffer, 100, { + height: 100, + size: 'down', + } ); + expect( mockCrop ).not.toHaveBeenCalled(); + } ); + + it( 'resizes with center crop and attention strategy', async () => { + const jpegFile = new File( [ '<BLOB>' ], 'example.jpg', { + lastModified: 1234567891, + type: 'image/jpeg', + } ); + const buffer = await jpegFile.arrayBuffer(); + + await resizeImage( + 'itemId', + buffer, + 'image/jpeg', + { + width: 100, + height: 100, + crop: true, + }, + true + ); + + expect( mockThumbnailBuffer ).toHaveBeenCalledWith( buffer, 100, { + height: 100, + crop: 'attention', + size: 'down', + } ); + expect( mockCrop ).not.toHaveBeenCalled(); + } ); + + it.each< [ ImageSizeCrop[ 'crop' ], [ number, number, number, number ] ] >( + [ + [ + [ 'left', 'top' ], + [ 0, 0, 25, 25 ], + ], + [ + [ 'center', 'top' ], + [ 37.5, 0, 25, 25 ], + ], + [ + [ 'right', 'top' ], + [ 75, 0, 25, 25 ], + ], + [ + [ 'left', 'center' ], + [ 0, 37.5, 25, 25 ], + ], + [ + [ 'center', 'center' ], + [ 37.5, 37.5, 25, 25 ], + ], + [ + [ 'right', 'center' ], + [ 75, 37.5, 25, 25 ], + ], + [ + [ 'left', 'bottom' ], + [ 0, 75, 25, 25 ], + ], + [ + [ 'center', 'bottom' ], + [ 37.5, 75, 25, 25 ], + ], + [ + [ 'right', 'bottom' ], + [ 75, 75, 25, 25 ], + ], + ] + )( 'resizes with %s param and crops %s', async ( crop, expected ) => { + const jpegFile = new File( [ '<BLOB>' ], 'example.jpg', { + lastModified: 1234567891, + type: 'image/jpeg', + } ); + const buffer = await jpegFile.arrayBuffer(); + + await resizeImage( 'itemId', buffer, 'image/jpeg', { + width: 25, + height: 25, + crop, + } ); + + expect( mockCrop ).toHaveBeenCalledWith( ...expected ); + } ); +} ); diff --git a/packages/vips/src/types.ts b/packages/vips/src/types.ts new file mode 100644 index 00000000000000..d0978ff7979634 --- /dev/null +++ b/packages/vips/src/types.ts @@ -0,0 +1,170 @@ +export type ItemId = string; + +export interface ImageSizeCrop { + width: number; + height: number; + crop?: + | boolean + | [ 'left' | 'center' | 'right', 'top' | 'center' | 'bottom' ]; +} + +/** + * none: Do nothing. Same as low. + * centre: Just take the centre. + * entropy: Use an entropy measure + * attention: Look for features likely to draw human attention. + * low: Position the crop towards the low coordinate. Same as none. + * high: Position the crop towards the high coordinate. + * all: Everything is interesting. + */ +type Interesting = + | 'none' + | 'centre' + | 'entropy' + | 'attention' + | 'low' + | 'high' + | 'all'; + +/** + * none: Don't attach metadata. + * exif: Keep Exif metadata. + * xmp: Keep XMP metadata. + * iptc: Keep IPTC metadata. + * icc: Keep ICC metadata. + * other: Keep other metadata (e.g. PNG comments and some TIFF tags). + * all: Keep all metadata. + */ +type ForeignKeep = 'none' | 'exif' | 'xmp' | 'iptc' | 'icc' | 'other' | 'all'; + +/** + * The rendering intent.'absolute' is best for + * scientific work, 'relative' is usually best for + * accurate communication with other imaging libraries. + * + * perceptual: Perceptual rendering intent. + * relative: Relative colorimetric rendering intent. + * saturation: Saturation rendering intent. + * absolute: Absolute colorimetric rendering intent. + */ +type Intent = 'perceptual' | 'relative' | 'saturation' | 'absolute'; + +/** + * How sensitive loaders are to errors, from never stop (very insensitive), to + * stop on the smallest warning (very sensitive). + * + * Each one implies the ones before it, so 'error' implies + * 'truncated'. + * + * none: Never stop. + * truncated: Stop on image truncated, nothing else. + * error: Stop on serious error or truncation. + * warning: Stop on anything, even warnings. + */ +type FailOn = 'none' | 'truncated' | 'error' | 'warning'; + +/** + * The type of access an operation has to supply. See vips_tilecache() + * and #VipsForeign. + * + * random: means requests can come in any order. + * + * sequential: means requests will be top-to-bottom, but with some + * amount of buffering behind the read point for small non-local accesses. + */ +type Access = 'random' | 'sequential' | 'sequential-unbuffered'; + +export interface LoadOptions< T extends string > { + /** + * Number of pages to load, -1 for all. + */ + n?: T extends 'image/gif' + ? number + : T extends 'image/webp' + ? number + : never; + /** + * Required access pattern for this file. + */ + access?: Access; + /** + * Error level to fail on. + */ + fail_on?: FailOn; + /** + * Don't use a cached result for this operation. + */ + revalidate?: boolean; +} + +export interface SaveOptions< T extends string > { + /** + * Quality factor. + */ + Q?: T extends 'image/gif' ? never : number; + /** + * Which metadata to retain. + */ + keep?: ForeignKeep; + /** + * Generate an interlaced (progressive) JPEG/PNG/GIF. + * Do not provide for any other type! + */ + interlace?: boolean; + /** + * Enable lossless compression (for WebP). + * Do not provide for any other type! + */ + lossless?: T extends 'image/gif' ? never : boolean; + /** + * CPU effort / encoding speed. + * + * While supported by other encoders as well, + * it is most relevant for AVIF, as it is slow by default. + */ + effort?: number; +} + +export interface ThumbnailOptions { + /** + * Options that are passed on to the underlying loader. + */ + option_string?: string; + /** + * Size to this height. + */ + height?: number; + /** + * Whether to upsize, downsize, both up and + * downsize, or force a size (breaks aspect ratio). + */ + size?: 'both' | 'up' | 'down' | 'force'; + /** + * Don't use orientation tags to rotate image upright. + */ + no_rotate?: boolean; + /** + * Reduce to fill target rectangle, then crop. + */ + crop?: Interesting; + /** + * Reduce in linear light. + */ + linear?: boolean; + /** + * Fallback import profile. + */ + import_profile?: string; + /** + * Fallback export profile. + */ + export_profile?: string; + /** + * Rendering intent. + */ + intent?: Intent; + /** + * Error level to fail on. + */ + fail_on?: FailOn; +} diff --git a/packages/vips/src/utils.ts b/packages/vips/src/utils.ts new file mode 100644 index 00000000000000..924d28110b597e --- /dev/null +++ b/packages/vips/src/utils.ts @@ -0,0 +1,43 @@ +/** + * Determines whether a given file type supports a quality setting, + * + * @todo Make this smarter. + * + * @param type Mime type. + * @return Whether the file supports a quality setting. + */ +export function supportsQuality( + type: string +): type is 'image/jpeg' | 'image/png' | 'image/webp' | 'image/avif' { + return [ 'image/jpeg', 'image/png', 'image/webp', 'image/avif' ].includes( + type + ); +} + +/** + * Determines whether a given file type supports animation, + * + * @todo Make this smarter. + * + * @param type Mime type. + * @return Whether the file supports animation. + */ +export function supportsAnimation( + type: string +): type is 'image/webp' | 'image/gif' { + return [ 'image/webp', 'image/gif' ].includes( type ); +} + +/** + * Determines whether a given file type supports interlaced/progressive output. + * + * @todo Make this smarter. + * + * @param type Mime type. + * @return Whether the file supports interlaced/progressive output. + */ +export function supportsInterlace( + type: string +): type is 'image/jpeg' | 'image/gif' | 'image/png' { + return [ 'image/jpeg', 'image/gif', 'image/png' ].includes( type ); +} diff --git a/packages/vips/tsconfig.json b/packages/vips/tsconfig.json new file mode 100644 index 00000000000000..6e33d8ff82d47e --- /dev/null +++ b/packages/vips/tsconfig.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types" + }, + "include": [ "src/**/*" ] +} diff --git a/patches/wasm-vips+0.0.10.patch b/patches/wasm-vips+0.0.10.patch new file mode 100644 index 00000000000000..3310b706e5a46b --- /dev/null +++ b/patches/wasm-vips+0.0.10.patch @@ -0,0 +1,15 @@ +diff --git a/node_modules/wasm-vips/package.json b/node_modules/wasm-vips/package.json +index c20f052..b26a38a 100644 +--- a/node_modules/wasm-vips/package.json ++++ b/node_modules/wasm-vips/package.json +@@ -15,10 +15,6 @@ + "type": "commonjs", + "exports": { + ".": { +- "browser": { +- "import": "./lib/vips-es6.js", +- "require": "./lib/vips.js" +- }, + "node": { + "import": "./lib/vips-node.mjs", + "require": "./lib/vips-node.js" diff --git a/test/unit/config/global-mocks.js b/test/unit/config/global-mocks.js index 4c5e5f8f8cd117..ce64f03b514be8 100644 --- a/test/unit/config/global-mocks.js +++ b/test/unit/config/global-mocks.js @@ -2,6 +2,7 @@ * External dependencies */ import { TextDecoder, TextEncoder } from 'node:util'; +import { Blob as BlobPolyfill, File as FilePolyfill } from 'node:buffer'; jest.mock( '@wordpress/compose', () => { return { @@ -44,3 +45,7 @@ if ( ! global.TextDecoder ) { if ( ! global.TextEncoder ) { global.TextEncoder = TextEncoder; } + +// Override jsdom built-ins with native node implementation. +global.Blob = BlobPolyfill; +global.File = FilePolyfill; diff --git a/test/unit/config/wasm-stub.js b/test/unit/config/wasm-stub.js new file mode 100644 index 00000000000000..0a77fdcfdd6914 --- /dev/null +++ b/test/unit/config/wasm-stub.js @@ -0,0 +1 @@ +// Stub file for Jest. diff --git a/test/unit/jest.config.js b/test/unit/jest.config.js index 8564d4116691fd..8d363cc46e9157 100644 --- a/test/unit/jest.config.js +++ b/test/unit/jest.config.js @@ -13,6 +13,7 @@ module.exports = { moduleNameMapper: { [ `@wordpress\\/(${ transpiledPackageNames.join( '|' ) })$` ]: 'packages/$1/src', + '.+\\.wasm$': '<rootDir>/test/unit/config/wasm-stub.js', }, preset: '@wordpress/jest-preset-default', setupFiles: [ diff --git a/tools/webpack/packages.js b/tools/webpack/packages.js index 76d460cafc15d0..340d677e358333 100644 --- a/tools/webpack/packages.js +++ b/tools/webpack/packages.js @@ -141,6 +141,20 @@ module.exports = { return `webpack://${ info.namespace }/${ info.resourcePath }`; }, }, + module: { + rules: [ + ...baseConfig.module.rules, + { + test: /\.wasm$/, + type: 'asset/resource', + generator: { + // FIXME: Do not hardcode path. + filename: './build/vips/[name].wasm', + publicPath: '', + }, + }, + ], + }, performance: { hints: false, // disable warnings about package sizes }, diff --git a/tsconfig.json b/tsconfig.json index 4dafc0acc958c6..51bb7f2d68924a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -55,6 +55,7 @@ { "path": "packages/token-list" }, { "path": "packages/undo-manager" }, { "path": "packages/url" }, + { "path": "packages/vips" }, { "path": "packages/warning" }, { "path": "packages/wordcount" } ], From 76f58cf5c380cff90cf876c6446c46354926b560 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Mon, 21 Oct 2024 16:45:14 +0300 Subject: [PATCH 1265/1908] Update the speak messages when switching editor modes (#66278) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: PARTHVATALIYA <parthvataliya@git.wordpress.org> --- packages/block-editor/src/store/actions.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 24a08ecb21d6e5..6edc5cb4da0393 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1673,17 +1673,9 @@ export const __unstableSetEditorMode = registry.dispatch( preferencesStore ).set( 'core', 'editorTool', mode ); if ( mode === 'navigation' ) { - speak( - __( - 'You are currently in navigation mode. Navigate blocks using the Tab key and Arrow keys. Use Left and Right Arrow keys to move between nesting levels. To exit navigation mode and edit the selected block, press Enter.' - ) - ); + speak( __( 'You are currently in Write mode.' ) ); } else if ( mode === 'edit' ) { - speak( - __( - 'You are currently in edit mode. To return to the navigation mode, press Escape.' - ) - ); + speak( __( 'You are currently in Design mode.' ) ); } }; From 013b4905179cd641bef3ed5d3a4669f1a8f283ba Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Mon, 21 Oct 2024 19:26:46 +0530 Subject: [PATCH 1266/1908] Cover Block: Add Image Resolution options (#62926) * Add attribute for resolution of image in cover block * Add resolutionTool into cover block for background images * Relocate the resolution control in inspector control * Add image size class to image on save * Retain previous value of sizeSlug attribute on image change * Update url based on selected image size * Update setting panel using ToolsPanel component * Remove clear media button from setting panel * Remove Resolution Tool component from dimension panel * Update role of setting panel in unit test * Remove unneccessory code * Remove typecasting for boolean variable and update default value * Set default value to full size for media size slug attribute * clear whitespace and typos * Set default value for image resolution * Fix empty image sizes condition Unlinked contributors: Bladed3d. Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: codebymikey <codebymikey@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- packages/block-library/src/cover/block.json | 3 ++ packages/block-library/src/cover/constants.js | 1 + .../block-library/src/cover/edit/index.js | 19 ++++++++ .../src/cover/edit/inspector-controls.js | 47 ++++++++++++++++++- packages/block-library/src/cover/save.js | 2 + 6 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 packages/block-library/src/cover/constants.js diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 66f713b3aa40fc..dd49d156857249 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -246,7 +246,7 @@ Add an image or video with a text overlay. ([Source](https://github.com/WordPres - **Name:** core/cover - **Category:** media - **Supports:** align, anchor, color (heading, text, ~~background~~, ~~enableContrastChecker~~), dimensions (aspectRatio), interactivity (clientNavigation), layout (~~allowJustification~~), shadow, spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~ -- **Attributes:** allowedBlocks, alt, backgroundType, contentPosition, customGradient, customOverlayColor, dimRatio, focalPoint, gradient, hasParallax, id, isDark, isRepeated, isUserOverlayColor, minHeight, minHeightUnit, overlayColor, tagName, templateLock, url, useFeaturedImage +- **Attributes:** allowedBlocks, alt, backgroundType, contentPosition, customGradient, customOverlayColor, dimRatio, focalPoint, gradient, hasParallax, id, isDark, isRepeated, isUserOverlayColor, minHeight, minHeightUnit, overlayColor, sizeSlug, tagName, templateLock, url, useFeaturedImage ## Details diff --git a/packages/block-library/src/cover/block.json b/packages/block-library/src/cover/block.json index 0ce80ca8d424f4..733dfc12fc9bca 100644 --- a/packages/block-library/src/cover/block.json +++ b/packages/block-library/src/cover/block.json @@ -78,6 +78,9 @@ "tagName": { "type": "string", "default": "div" + }, + "sizeSlug": { + "type": "string" } }, "usesContext": [ "postId", "postType" ], diff --git a/packages/block-library/src/cover/constants.js b/packages/block-library/src/cover/constants.js new file mode 100644 index 00000000000000..984193dbfb376a --- /dev/null +++ b/packages/block-library/src/cover/constants.js @@ -0,0 +1 @@ +export const DEFAULT_MEDIA_SIZE_SLUG = 'full'; diff --git a/packages/block-library/src/cover/edit/index.js b/packages/block-library/src/cover/edit/index.js index 804027708881b6..88a47f566987c6 100644 --- a/packages/block-library/src/cover/edit/index.js +++ b/packages/block-library/src/cover/edit/index.js @@ -47,6 +47,7 @@ import { DEFAULT_BACKGROUND_COLOR, DEFAULT_OVERLAY_COLOR, } from './color-utils'; +import { DEFAULT_MEDIA_SIZE_SLUG } from '../constants'; function getInnerBlocksTemplate( attributes ) { return [ @@ -100,6 +101,7 @@ function CoverEdit( { templateLock, tagName: TagName = 'div', isUserOverlayColor, + sizeSlug, } = attributes; const [ featuredImage ] = useEntityProp( @@ -108,6 +110,7 @@ function CoverEdit( { 'featured_media', postId ); + const { getSettings } = useSelect( blockEditorStore ); const { __unstableMarkNextChangeAsNotPersistent } = useDispatch( blockEditorStore ); @@ -199,6 +202,22 @@ function CoverEdit( { averageBackgroundColor ); + if ( backgroundType === IMAGE_BACKGROUND_TYPE && mediaAttributes.id ) { + const { imageDefaultSize } = getSettings(); + + // Try to use the previous selected image size if it's available + // otherwise try the default image size or fallback to full size. + if ( sizeSlug && newMedia?.sizes?.[ sizeSlug ] ) { + mediaAttributes.sizeSlug = sizeSlug; + mediaAttributes.url = newMedia?.sizes?.[ sizeSlug ]?.url; + } else if ( newMedia?.sizes?.[ imageDefaultSize ] ) { + mediaAttributes.sizeSlug = imageDefaultSize; + mediaAttributes.url = newMedia?.sizes?.[ sizeSlug ]?.url; + } else { + mediaAttributes.sizeSlug = DEFAULT_MEDIA_SIZE_SLUG; + } + } + setAttributes( { ...mediaAttributes, focalPoint: undefined, diff --git a/packages/block-library/src/cover/edit/inspector-controls.js b/packages/block-library/src/cover/edit/inspector-controls.js index 2ed9b055d49f35..c0807869ee1a5c 100644 --- a/packages/block-library/src/cover/edit/inspector-controls.js +++ b/packages/block-library/src/cover/edit/inspector-controls.js @@ -19,12 +19,15 @@ import { useInstanceId } from '@wordpress/compose'; import { InspectorControls, useSettings, + store as blockEditorStore, __experimentalColorGradientSettingsDropdown as ColorGradientSettingsDropdown, __experimentalUseGradient, __experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients, privateApis as blockEditorPrivateApis, } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies @@ -32,8 +35,9 @@ import { __ } from '@wordpress/i18n'; import { COVER_MIN_HEIGHT, mediaPosition } from '../shared'; import { unlock } from '../../lock-unlock'; import { useToolsPanelDropdownMenuProps } from '../../utils/hooks'; +import { DEFAULT_MEDIA_SIZE_SLUG } from '../constants'; -const { cleanEmptyObject } = unlock( blockEditorPrivateApis ); +const { cleanEmptyObject, ResolutionTool } = unlock( blockEditorPrivateApis ); function CoverHeightInput( { onChange, @@ -95,6 +99,7 @@ export default function CoverInspectorControls( { } ) { const { useFeaturedImage, + id, dimRatio, focalPoint, hasParallax, @@ -112,7 +117,38 @@ export default function CoverInspectorControls( { overlayColor, } = currentSettings; + const sizeSlug = attributes.sizeSlug || DEFAULT_MEDIA_SIZE_SLUG; + const { gradientValue, setGradient } = __experimentalUseGradient(); + const { getSettings } = useSelect( blockEditorStore ); + + const imageSizes = getSettings()?.imageSizes; + + const image = useSelect( + ( select ) => + id && isImageBackground + ? select( coreStore ).getMedia( id, { context: 'view' } ) + : null, + [ id, isImageBackground ] + ); + + function updateImage( newSizeSlug ) { + const newUrl = image?.media_details?.sizes?.[ newSizeSlug ]?.source_url; + if ( ! newUrl ) { + return null; + } + + setAttributes( { + url: newUrl, + sizeSlug: newSizeSlug, + } ); + } + + const imageSizeOptions = imageSizes + ?.filter( + ( { slug } ) => image?.media_details?.sizes?.[ slug ]?.source_url + ) + ?.map( ( { name, slug } ) => ( { value: slug, label: name } ) ); const toggleParallax = () => { setAttributes( { @@ -175,6 +211,7 @@ export default function CoverInspectorControls( { focalPoint: undefined, isRepeated: false, alt: '', + sizeSlug: undefined, } ); } } dropdownMenuProps={ dropdownMenuProps } @@ -284,6 +321,14 @@ export default function CoverInspectorControls( { /> </ToolsPanelItem> ) } + { ! useFeaturedImage && !! imageSizeOptions?.length && ( + <ResolutionTool + value={ sizeSlug } + onChange={ updateImage } + options={ imageSizeOptions } + defaultValue={ DEFAULT_MEDIA_SIZE_SLUG } + /> + ) } </ToolsPanel> ) } </InspectorControls> diff --git a/packages/block-library/src/cover/save.js b/packages/block-library/src/cover/save.js index f4ee486fb99a7c..325ddf2b741f98 100644 --- a/packages/block-library/src/cover/save.js +++ b/packages/block-library/src/cover/save.js @@ -45,6 +45,7 @@ export default function save( { attributes } ) { minHeight: minHeightProp, minHeightUnit, tagName: Tag, + sizeSlug, } = attributes; const overlayColorClass = getColorClassName( 'background-color', @@ -95,6 +96,7 @@ export default function save( { attributes } ) { 'wp-block-cover__image-background', id ? `wp-image-${ id }` : null, { + [ `size-${ sizeSlug }` ]: sizeSlug, 'has-parallax': hasParallax, 'is-repeated': isRepeated, } From f99347e27927c73b07601116d4f22d3c7611dc97 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Mon, 21 Oct 2024 17:23:03 +0200 Subject: [PATCH 1267/1908] Remove unnecessary Tooltip component from radius control linked button (#66274) Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../border-radius-control/linked-button.js | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/block-editor/src/components/border-radius-control/linked-button.js b/packages/block-editor/src/components/border-radius-control/linked-button.js index 82752c91de6470..58afe350b72126 100644 --- a/packages/block-editor/src/components/border-radius-control/linked-button.js +++ b/packages/block-editor/src/components/border-radius-control/linked-button.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { Button, Tooltip } from '@wordpress/components'; +import { Button } from '@wordpress/components'; import { link, linkOff } from '@wordpress/icons'; import { __ } from '@wordpress/i18n'; @@ -9,15 +9,13 @@ export default function LinkedButton( { isLinked, ...props } ) { const label = isLinked ? __( 'Unlink radii' ) : __( 'Link radii' ); return ( - <Tooltip text={ label }> - <Button - { ...props } - className="component-border-radius-control__linked-button" - size="small" - icon={ isLinked ? link : linkOff } - iconSize={ 24 } - aria-label={ label } - /> - </Tooltip> + <Button + { ...props } + className="component-border-radius-control__linked-button" + size="small" + icon={ isLinked ? link : linkOff } + iconSize={ 24 } + label={ label } + /> ); } From 6fbca55ee5d379ca148bfe43437a1e387b04af7c Mon Sep 17 00:00:00 2001 From: vykes-mac <47489215+vykes-mac@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:42:31 -0400 Subject: [PATCH 1268/1908] Combobox, FormTokenField: show message when no matches found (#66142) Co-authored-by: vykes-mac <vykesmac@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: matt-west <mattwest@git.wordpress.org> --- packages/components/CHANGELOG.md | 2 ++ packages/components/src/form-token-field/style.scss | 5 ++++- .../components/src/form-token-field/suggestions-list.tsx | 6 ++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 165ce7e3748557..b149172bd10376 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -40,6 +40,8 @@ - `Modal`: Modal dialog small improvement for elementShouldBeHidden ([#65941](https://github.com/WordPress/gutenberg/pull/65941)). - `Tabs`: revamped vertical orientation styles ([#65387](https://github.com/WordPress/gutenberg/pull/65387)). +- `ComboboxControl`: display `No items found` when there are no matches found ([#66142](https://github.com/WordPress/gutenberg/pull/66142)) +- `FormTokenField`: display `No items found` when there are no matches found. This occurs when the `__experimentalExpandOnFocus` prop is enabled ([#66142](https://github.com/WordPress/gutenberg/pull/66142)) ## 28.9.0 (2024-10-03) diff --git a/packages/components/src/form-token-field/style.scss b/packages/components/src/form-token-field/style.scss index cf5cc5b63e2227..51f9e24ea0d4f2 100644 --- a/packages/components/src/form-token-field/style.scss +++ b/packages/components/src/form-token-field/style.scss @@ -173,7 +173,6 @@ padding: $grid-unit-10 $grid-unit-15; min-height: $button-size-compact; margin: 0; - cursor: pointer; box-sizing: border-box; &.is-selected { @@ -189,4 +188,8 @@ background-color: $components-color-accent-transparent-40; } } + + &:not(.is-empty) { + cursor: pointer; + } } diff --git a/packages/components/src/form-token-field/suggestions-list.tsx b/packages/components/src/form-token-field/suggestions-list.tsx index 43a9b87c2030b3..1339e0cc189e38 100644 --- a/packages/components/src/form-token-field/suggestions-list.tsx +++ b/packages/components/src/form-token-field/suggestions-list.tsx @@ -8,6 +8,7 @@ import type { MouseEventHandler, ReactNode } from 'react'; * WordPress dependencies */ import { useRefEffect } from '@wordpress/compose'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -156,6 +157,11 @@ export function SuggestionsList< ); /* eslint-enable jsx-a11y/click-events-have-key-events */ } ) } + { suggestions.length === 0 && ( + <li className="components-form-token-field__suggestion is-empty"> + { __( 'No items found' ) } + </li> + ) } </ul> ); } From 119caccd9130cecbd24fe62df55221af33415afb Mon Sep 17 00:00:00 2001 From: Michal <mmczaplinski@gmail.com> Date: Mon, 21 Oct 2024 17:10:33 +0100 Subject: [PATCH 1269/1908] Docs: Interactivity API - Add documentation for `getServerState()` and `getServerContext()` (#66104) * Add documentation on `getServerState()` and `getServerContext()` * update heading level * Undelete the "Conclusion" * Fix link to the documentation * update link to router docs * clarify about context * add reference to @wordpress/router Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: DAreRodz <darerodz@git.wordpress.org> --- .../interactivity-api/api-reference.md | 935 ++++++++++-------- ...l-state-local-context-and-derived-state.md | 106 +- 2 files changed, 623 insertions(+), 418 deletions(-) diff --git a/docs/reference-guides/interactivity-api/api-reference.md b/docs/reference-guides/interactivity-api/api-reference.md index 25498d10bde2ef..bbbb565684c578 100644 --- a/docs/reference-guides/interactivity-api/api-reference.md +++ b/docs/reference-guides/interactivity-api/api-reference.md @@ -6,8 +6,8 @@ Interactivity API is only available for WordPress 6.5 and above. To add interactions to blocks using the Interactivity API, developers can use: -- **Directives:** Added to the markup to add specific behavior to the DOM elements of the block -- **Store:** Contains the logic and data (state, actions, side effects, etc.) needed for the behavior +- **Directives:** Added to the markup to add specific behavior to the DOM elements of the block +- **Store:** Contains the logic and data (state, actions, side effects, etc.) needed for the behavior DOM elements are connected to data stored in the state and context through directives. If data in the state or context change directives will react to those changes, updating the DOM accordingly (see [diagram](https://excalidraw.com/#json=T4meh6lltJh6TCX51NTIu,DmIhxYSGFTL_ywZFbsmuSw)). @@ -21,21 +21,21 @@ Interactivity API directives use the `data-` prefix. Here's an example of direct ```html <div - data-wp-interactive="myPlugin" - data-wp-context='{ "isOpen": false }' - data-wp-watch="callbacks.logIsOpen" + data-wp-interactive="myPlugin" + data-wp-context='{ "isOpen": false }' + data-wp-watch="callbacks.logIsOpen" > - <button - data-wp-on--click="actions.toggle" - data-wp-bind--aria-expanded="context.isOpen" - aria-controls="p-1" - > - Toggle - </button> - - <p id="p-1" data-wp-bind--hidden="!context.isOpen"> - This element is now visible! - </p> + <button + data-wp-on--click="actions.toggle" + data-wp-bind--aria-expanded="context.isOpen" + aria-controls="p-1" + > + Toggle + </button> + + <p id="p-1" data-wp-bind--hidden="!context.isOpen"> + This element is now visible! + </p> </div> ``` @@ -52,24 +52,44 @@ The `wp-interactive` directive "activates" the interactivity for the DOM element ```html <!-- Let's make this element and its children interactive and set the namespace --> <div - data-wp-interactive="myPlugin" - data-wp-context='{ "myColor" : "red", "myBgColor": "yellow" }' + data-wp-interactive="myPlugin" + data-wp-context='{ "myColor" : "red", "myBgColor": "yellow" }' > - <p>I'm interactive now, <span data-wp-style--background-color="context.myBgColor">and I can use directives!</span></p> - <div> - <p>I'm also interactive, <span data-wp-style--color="context.myColor">and I can also use directives!</span></p> - </div> + <p> + I'm interactive now, + <span data-wp-style--background-color="context.myBgColor" + >and I can use directives!</span + > + </p> + <div> + <p> + I'm also interactive, + <span data-wp-style--color="context.myColor" + >and I can also use directives!</span + > + </p> + </div> </div> <!-- This is also valid --> <div - data-wp-interactive='{ "namespace": "myPlugin" }' - data-wp-context='{ "myColor" : "red", "myBgColor": "yellow" }' + data-wp-interactive='{ "namespace": "myPlugin" }' + data-wp-context='{ "myColor" : "red", "myBgColor": "yellow" }' > - <p>I'm interactive now, <span data-wp-style--background-color="context.myBgColor">and I can use directives!</span></p> - <div> - <p>I'm also interactive, <span data-wp-style--color="context.myColor">and I can also use directives!</span></p> - </div> + <p> + I'm interactive now, + <span data-wp-style--background-color="context.myBgColor" + >and I can use directives!</span + > + </p> + <div> + <p> + I'm also interactive, + <span data-wp-style--color="context.myColor" + >and I can also use directives!</span + > + </p> + </div> </div> ``` @@ -96,31 +116,31 @@ The `wp-context` directive accepts a stringified JSON as a value. <summary><em>See store used with the directive above</em></summary> ```js -store( "myPlugin", { - actions: { - logId: () => { - const { post } = getContext(); - console.log( post.id ); - }, - }, +store( 'myPlugin', { + actions: { + logId: () => { + const { post } = getContext(); + console.log( post.id ); + }, + }, } ); ``` + </details> Different contexts can be defined at different levels, and deeper levels will merge their own context with any parent one: ```html <div data-wp-context='{ "foo": "bar" }'> - <span data-wp-text="context.foo"><!-- Will output: "bar" --></span> + <span data-wp-text="context.foo"><!-- Will output: "bar" --></span> - <div data-wp-context='{ "bar": "baz" }'> - <span data-wp-text="context.foo"><!-- Will output: "bar" --></span> + <div data-wp-context='{ "bar": "baz" }'> + <span data-wp-text="context.foo"><!-- Will output: "bar" --></span> - <div data-wp-context='{ "foo": "bob" }'> - <span data-wp-text="context.foo"><!-- Will output: "bob" --></span> - </div> - - </div> + <div data-wp-context='{ "foo": "bob" }'> + <span data-wp-text="context.foo"><!-- Will output: "bob" --></span> + </div> + </div> </div> ``` @@ -130,18 +150,18 @@ This directive allows setting HTML attributes on elements based on a boolean or ```html <li data-wp-context='{ "isMenuOpen": false }'> - <button - data-wp-on--click="actions.toggleMenu" - data-wp-bind--aria-expanded="context.isMenuOpen" - > - Toggle - </button> - <div data-wp-bind--hidden="!context.isMenuOpen"> - <span>Title</span> - <ul> - SUBMENU ITEMS - </ul> - </div> + <button + data-wp-on--click="actions.toggleMenu" + data-wp-bind--aria-expanded="context.isMenuOpen" + > + Toggle + </button> + <div data-wp-bind--hidden="!context.isMenuOpen"> + <span>Title</span> + <ul> + SUBMENU ITEMS + </ul> + </div> </li> ``` @@ -149,33 +169,34 @@ This directive allows setting HTML attributes on elements based on a boolean or <summary><em>See store used with the directive above</em></summary> ```js -store( "myPlugin", { - actions: { - toggleMenu: () => { - const context = getContext(); - context.isMenuOpen = !context.isMenuOpen; - }, - }, +store( 'myPlugin', { + actions: { + toggleMenu: () => { + const context = getContext(); + context.isMenuOpen = ! context.isMenuOpen; + }, + }, } ); ``` + </details> The `wp-bind` directive is executed: -- When the element is created -- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference) +- When the element is created +- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference) When `wp-bind` directive references a callback to get its final value: -- The `wp-bind` directive will be executed each time there's a change on any of the properties of the `state` or `context` used inside this callback. -- The returned value in the callback function is used to change the value of the associated attribute. +- The `wp-bind` directive will be executed each time there's a change on any of the properties of the `state` or `context` used inside this callback. +- The returned value in the callback function is used to change the value of the associated attribute. The `wp-bind` will do different things when the DOM element is applied, depending on its value: - - If the value is `true`, the attribute is added: `<div attribute>` - - If the value is `false`, the attribute is removed: `<div>` - - If the value is a string, the attribute is added with its value assigned: `<div attribute="value"` - - If the attribute name starts with `aria-` or `data-` and the value is boolean (either `true` or `false`), the attribute is added to the DOM with the boolean value assigned as a string: `<div aria-attribute="true">` +- If the value is `true`, the attribute is added: `<div attribute>` +- If the value is `false`, the attribute is removed: `<div>` +- If the value is a string, the attribute is added with its value assigned: `<div attribute="value"` +- If the attribute name starts with `aria-` or `data-` and the value is boolean (either `true` or `false`), the attribute is added to the DOM with the boolean value assigned as a string: `<div aria-attribute="true">` ### `wp-class` @@ -183,20 +204,20 @@ This directive adds or removes a class to an HTML element, depending on a boolea ```html <div> - <li - data-wp-context='{ "isSelected": false }' - data-wp-on--click="actions.toggleSelection" - data-wp-class--selected="context.isSelected" - > - Option 1 - </li> - <li - data-wp-context='{ "isSelected": false }' - data-wp-on--click="actions.toggleSelection" - data-wp-class--selected="context.isSelected" - > - Option 2 - </li> + <li + data-wp-context='{ "isSelected": false }' + data-wp-on--click="actions.toggleSelection" + data-wp-class--selected="context.isSelected" + > + Option 1 + </li> + <li + data-wp-context='{ "isSelected": false }' + data-wp-on--click="actions.toggleSelection" + data-wp-class--selected="context.isSelected" + > + Option 2 + </li> </div> ``` @@ -204,21 +225,22 @@ This directive adds or removes a class to an HTML element, depending on a boolea <summary><em>See store used with the directive above</em></summary> ```js -store( "myPlugin", { - actions: { - toggleSelection: () => { - const context = getContext(); - context.isSelected = !context.isSelected - } - } +store( 'myPlugin', { + actions: { + toggleSelection: () => { + const context = getContext(); + context.isSelected = ! context.isSelected; + }, + }, } ); ``` + </details> The `wp-class` directive is executed: -- When the element is created -- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference) +- When the element is created +- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference) The boolean value received by the directive is used to toggle (add when `true` or remove when `false`) the associated class name from the `class` attribute. @@ -229,24 +251,24 @@ So, for example, use the class name `is-dark` instead of `isDark` and `data-wp-c ```html <!-- Recommended --> <div data-wp-class--is-dark="context.isDarkMode"> - <!-- ... --> + <!-- ... --> </div> <!-- Not recommended --> <div data-wp-class--isDark="context.isDarkMode"> - <!-- ... --> + <!-- ... --> </div> ``` ```css /* Recommended */ .is-dark { - /* ... */ + /* ... */ } /* Not recommended */ .isDark { - /* ... */ + /* ... */ } ``` @@ -255,9 +277,11 @@ So, for example, use the class name `is-dark` instead of `isDark` and `data-wp-c This directive adds or removes inline style to an HTML element, depending on its value. It follows the syntax `data-wp-style--css-property`. ```html -<div data-wp-context='{ "color": "red" }' > - <button data-wp-on--click="actions.toggleContextColor">Toggle Color Text</button> - <p data-wp-style--color="context.color">Hello World!</p> +<div data-wp-context='{ "color": "red" }'> + <button data-wp-on--click="actions.toggleContextColor"> + Toggle Color Text + </button> + <p data-wp-style--color="context.color">Hello World!</p> </div> > ``` @@ -266,26 +290,27 @@ This directive adds or removes inline style to an HTML element, depending on its <summary><em>See store used with the directive above</em></summary> ```js -store( "myPlugin", { - actions: { - toggleContextColor: () => { - const context = getContext(); - context.color = context.color === 'red' ? 'blue' : 'red'; - }, - }, +store( 'myPlugin', { + actions: { + toggleContextColor: () => { + const context = getContext(); + context.color = context.color === 'red' ? 'blue' : 'red'; + }, + }, } ); ``` + </details> The `wp-style` directive is executed: -- When the element is created -- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference) +- When the element is created +- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference) The value received by the directive is used to add or remove the style attribute with the associated CSS property: -- If the value is `false`, the style attribute is removed: `<div>` -- If the value is a string, the attribute is added with its value assigned: `<div style="css-property: value;">` +- If the value is `false`, the style attribute is removed: `<div>` +- If the value is a string, the attribute is added with its value assigned: `<div style="css-property: value;">` ### `wp-text` @@ -293,10 +318,10 @@ It sets the inner text of an HTML element. ```html <div data-wp-context='{ "text": "Text 1" }'> - <span data-wp-text="context.text"></span> - <button data-wp-on--click="actions.toggleContextText"> - Toggle Context Text - </button> + <span data-wp-text="context.text"></span> + <button data-wp-on--click="actions.toggleContextText"> + Toggle Context Text + </button> </div> ``` @@ -304,21 +329,22 @@ It sets the inner text of an HTML element. <summary><em>See store used with the directive above</em></summary> ```js -store( "myPlugin", { - actions: { - toggleContextText: () => { - const context = getContext(); - context.text = context.text === 'Text 1' ? 'Text 2' : 'Text 1'; - }, - }, +store( 'myPlugin', { + actions: { + toggleContextText: () => { + const context = getContext(); + context.text = context.text === 'Text 1' ? 'Text 2' : 'Text 1'; + }, + }, } ); ``` + </details> The `wp-text` directive is executed: -- When the element is created -- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference) +- When the element is created +- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference) The returned value is used to change the inner content of the element: `<div>value</div>`. @@ -340,14 +366,15 @@ This directive runs code on dispatched DOM events like `click` or `keyup`. The s <summary><em>See store used with the directive above</em></summary> ```js -store( "myPlugin", { - actions: { - logTime: ( event ) => { - console.log( new Date() ) - }, - }, +store( 'myPlugin', { + actions: { + logTime: ( event ) => { + console.log( new Date() ); + }, + }, } ); ``` + </details> The `wp-on` directive is executed each time the associated event is triggered. @@ -378,7 +405,7 @@ The syntax of this directive is `data-wp-on-window--[window-event]` (like `data- <summary><em>See store used with the directive above</em></summary> ```js -store( "myPlugin", { +store( 'myPlugin', { callbacks: { logWidth() { console.log( 'Window width: ', window.innerWidth ); @@ -386,6 +413,7 @@ store( "myPlugin", { }, } ); ``` + </details> The callback passed as the reference receives [the event](https://developer.mozilla.org/en-US/docs/Web/API/Event) (`event`), and the returned value by this callback is ignored. When the element is removed from the DOM, the event listener is also removed. @@ -414,14 +442,15 @@ The syntax of this directive is `data-wp-on-document--[document-event]` (like `d <summary><em>See store used with the directive above</em></summary> ```js -store( "myPlugin", { +store( 'myPlugin', { callbacks: { - logKeydown(event) { + logKeydown( event ) { console.log( 'Key pressed: ', event.key ); }, - }, + }, } ); ``` + </details> The callback passed as the reference receives [the event](https://developer.mozilla.org/en-US/docs/Web/API/Event) (`event`), and the returned value by this callback is ignored. When the element is removed from the DOM, the event listener is also removed. @@ -439,13 +468,10 @@ You can attach several side effects to the same DOM element by using the syntax The `unique-id` doesn't need to be unique globally. It just needs to be different from the other unique IDs of the `wp-watch` directives of that DOM element. ```html -<div - data-wp-context='{ "counter": 0 }' - data-wp-watch="callbacks.logCounter" -> - <p>Counter: <span data-wp-text="context.counter"></span></p> - <button data-wp-on--click="actions.increaseCounter">+</button> - <button data-wp-on--click="actions.decreaseCounter">-</button> +<div data-wp-context='{ "counter": 0 }' data-wp-watch="callbacks.logCounter"> + <p>Counter: <span data-wp-text="context.counter"></span></p> + <button data-wp-on--click="actions.increaseCounter">+</button> + <button data-wp-on--click="actions.decreaseCounter">-</button> </div> ``` @@ -453,40 +479,41 @@ The `unique-id` doesn't need to be unique globally. It just needs to be differen <summary><em>See store used with the directive above</em></summary> ```js -store( "myPlugin", { - actions: { - increaseCounter: () => { - const context = getContext(); - context.counter++; - }, - decreaseCounter: () => { - const context = getContext(); - context.counter--; - }, - }, - callbacks: { - logCounter: () => { - const { counter } = getContext(); - console.log("Counter is " + counter + " at " + new Date() ); - }, - }, +store( 'myPlugin', { + actions: { + increaseCounter: () => { + const context = getContext(); + context.counter++; + }, + decreaseCounter: () => { + const context = getContext(); + context.counter--; + }, + }, + callbacks: { + logCounter: () => { + const { counter } = getContext(); + console.log( 'Counter is ' + counter + ' at ' + new Date() ); + }, + }, } ); ``` + </details> The `wp-watch` directive is executed: -- When the element is created -- Each time that any of the properties of the `state` or `context` used inside the callback changes +- When the element is created +- Each time that any of the properties of the `state` or `context` used inside the callback changes The `wp-watch` directive can return a function. If it does, the returned function is used as cleanup logic, i.e., it will run just before the callback runs again, and it will run again when the element is removed from the DOM. As a reference, some use cases for this directive may be: -- Logging -- Changing the title of the page -- Setting the focus on an element with `.focus()`. -- Changing the state or context when certain conditions are met +- Logging +- Changing the title of the page +- Setting the focus on an element with `.focus()`. +- Changing the state or context when certain conditions are met ### `wp-init` @@ -498,7 +525,7 @@ The `unique-id` doesn't need to be unique globally. It just needs to be differen ```html <div data-wp-init="callbacks.logTimeInit"> - <p>Hi!</p> + <p>Hi!</p> </div> ``` @@ -506,10 +533,10 @@ Here's another example with several `wp-init` directives on the same DOM element ```html <form - data-wp-init--log="callbacks.logTimeInit" - data-wp-init--focus="callbacks.focusFirstElement" + data-wp-init--log="callbacks.logTimeInit" + data-wp-init--focus="callbacks.focusFirstElement" > - <input type="text"> + <input type="text" /> </form> ``` @@ -546,7 +573,7 @@ The `unique-id` doesn't need to be unique globally. It just needs to be differen ```html <div data-wp-run="callbacks.logInView"> - <p>Hi!</p> + <p>Hi!</p> </div> ``` @@ -554,38 +581,44 @@ The `unique-id` doesn't need to be unique globally. It just needs to be differen <summary><em>See store used with the directive above</em></summary> ```js -import { getElement, store, useState, useEffect } from '@wordpress/interactivity'; +import { + getElement, + store, + useState, + useEffect, +} from '@wordpress/interactivity'; // Unlike `data-wp-init` and `data-wp-watch`, you can use any hooks inside // `data-wp-run` callbacks. const useInView = () => { - const [ inView, setInView ] = useState( false ); - useEffect( () => { - const { ref } = getElement(); - const observer = new IntersectionObserver( ( [ entry ] ) => { - setInView( entry.isIntersecting ); - } ); - observer.observe( ref ); - return () => ref && observer.unobserve( ref ); - }, []); - return inView; + const [ inView, setInView ] = useState( false ); + useEffect( () => { + const { ref } = getElement(); + const observer = new IntersectionObserver( ( [ entry ] ) => { + setInView( entry.isIntersecting ); + } ); + observer.observe( ref ); + return () => ref && observer.unobserve( ref ); + }, [] ); + return inView; }; store( 'myPlugin', { - callbacks: { - logInView: () => { - const isInView = useInView(); - useEffect( () => { - if ( isInView ) { - console.log( 'Inside' ); - } else { - console.log( 'Outside' ); - } - }); - } - }, + callbacks: { + logInView: () => { + const isInView = useInView(); + useEffect( () => { + if ( isInView ) { + console.log( 'Inside' ); + } else { + console.log( 'Outside' ); + } + } ); + }, + }, } ); ``` + </details> It's important to note that, similar to (P)React components, the `ref` from `getElement()` is `null` during the first render. To properly access the DOM element reference, you typically need to use an effect-like hook such as `useEffect`, `useInit`, or `useWatch`. This ensures that the `getElement()` runs after the component has been mounted and the `ref` is available. @@ -598,8 +631,8 @@ The key should be a string that uniquely identifies the element among its siblin ```html <ul> - <li data-wp-key="unique-id-1">Item 1</li> - <li data-wp-key="unique-id-2">Item 2</li> + <li data-wp-key="unique-id-1">Item 1</li> + <li data-wp-key="unique-id-2">Item 2</li> </ul> ``` @@ -607,8 +640,8 @@ But it can also be used on other elements: ```html <div> - <a data-wp-key="previous-page" ...>Previous page</a> - <a data-wp-key="next-page" ...>Next page</a> + <a data-wp-key="previous-page" ...>Previous page</a> + <a data-wp-key="next-page" ...>Next page</a> </div> ``` @@ -624,9 +657,9 @@ For example, let's consider the following HTML. ```html <ul data-wp-context='{ "list": [ "hello", "hola", "olá" ] }'> - <template data-wp-each="context.list" > - <li data-wp-text="context.item"></li> - </template> + <template data-wp-each="context.list"> + <li data-wp-text="context.item"></li> + </template> </ul> ``` @@ -634,9 +667,9 @@ It would generate the following output: ```html <ul data-wp-context='{ "list": [ "hello", "hola", "olá" ] }'> - <li data-wp-text="context.item">hello</li> - <li data-wp-text="context.item">hola</li> - <li data-wp-text="context.item">olá</li> + <li data-wp-text="context.item">hello</li> + <li data-wp-text="context.item">hola</li> + <li data-wp-text="context.item">olá</li> </ul> ``` @@ -644,9 +677,9 @@ The prop that holds the item in the context can be changed by passing a suffix t ```html <ul data-wp-context='{ "list": [ "hello", "hola", "olá" ] }'> - <template data-wp-each--greeting="context.list" > - <li data-wp-text="context.greeting"></li> - </template> + <template data-wp-each--greeting="context.list"> + <li data-wp-text="context.greeting"></li> + </template> </ul> ``` @@ -655,19 +688,21 @@ By default, it uses each element as the key for the rendered nodes, but you can For that, you must use `data-wp-each-key` in the `<template>` tag and not `data-wp-key` inside the template content. This is because `data-wp-each` creates a context provider wrapper around each rendered item, and those wrappers are the ones that need the `key` property. ```html -<ul data-wp-context='{ +<ul + data-wp-context='{ "list": [ { "id": "en", "value": "hello" }, { "id": "es", "value": "hola" }, { "id": "pt", "value": "olá" } ] -}'> - <template - data-wp-each--greeting="context.list" - data-wp-each-key="context.greeting.id" - > - <li data-wp-text="context.greeting.value"></li> - </template> +}' +> + <template + data-wp-each--greeting="context.list" + data-wp-each-key="context.greeting.id" + > + <li data-wp-text="context.greeting.value"></li> + </template> </ul> ``` @@ -677,12 +712,12 @@ For server-side rendered lists, another directive called `data-wp-each-child` en ```html <ul data-wp-context='{ "list": [ "hello", "hola", "olá" ] }'> - <template data-wp-each--greeting="context.list" > - <li data-wp-text="context.greeting"></li> - </template> - <li data-wp-each-child>hello</li> - <li data-wp-each-child>hola</li> - <li data-wp-each-child>olá</li> + <template data-wp-each--greeting="context.list"> + <li data-wp-text="context.greeting"></li> + </template> + <li data-wp-each-child>hello</li> + <li data-wp-each-child>hola</li> + <li data-wp-each-child>olá</li> </ul> ``` @@ -693,21 +728,21 @@ The value assigned to a directive is a string pointing to a specific state, acti In the following example, a getter is used to define the `state.isPlaying` derived value. ```js -const { state } = store( "myPlugin", { - state: { - currentVideo: '', - get isPlaying() { - return state.currentVideo !== ''; - } - }, +const { state } = store( 'myPlugin', { + state: { + currentVideo: '', + get isPlaying() { + return state.currentVideo !== ''; + }, + }, } ); ``` And then, the string value `"state.isPlaying"` is used to assign the result of this selector to `data-wp-bind--hidden`. ```html -<div data-wp-bind--hidden="!state.isPlaying" ... > - <iframe ...></iframe> +<div data-wp-bind--hidden="!state.isPlaying" ...> + <iframe ...></iframe> </div> ``` @@ -719,7 +754,7 @@ The example below is getting `state.isPlaying` from `otherPlugin` instead of `my ```html <div data-wp-interactive="myPlugin"> - <div data-wp-bind--hidden="otherPlugin::!state.isPlaying" ... > + <div data-wp-bind--hidden="otherPlugin::!state.isPlaying" ...> <iframe ...></iframe> </div> </div> @@ -737,35 +772,33 @@ The store is used to create the logic (actions, side effects, etc.) linked to th It defines data available to the HTML nodes of the page. It is important to differentiate between two ways to define the data: -- **Global state**: It is defined using the `store()` function with the `state` property, and the data is available to all the HTML nodes of the page. -- **Context/Local State**: It is defined using the `data-wp-context` directive in an HTML node, and the data is available to that HTML node and its children. It can be accessed using the `getContext` function inside of an action, derived state or side effect. +- **Global state**: It is defined using the `store()` function with the `state` property, and the data is available to all the HTML nodes of the page. +- **Context/Local State**: It is defined using the `data-wp-context` directive in an HTML node, and the data is available to that HTML node and its children. It can be accessed using the `getContext` function inside of an action, derived state or side effect. ```html <div data-wp-context='{ "someText": "Hello World!" }'> + <!-- Access global state --> + <span data-wp-text="state.someText"></span> - <!-- Access global state --> - <span data-wp-text="state.someText"></span> - - <!-- Access local state (context) --> - <span data-wp-text="context.someText"></span> - + <!-- Access local state (context) --> + <span data-wp-text="context.someText"></span> </div> ``` ```js -const { state } = store( "myPlugin", { - state: { - someText: "Hello Universe!" - }, - actions: { - someAction: () => { - state.someText // Access or modify global state - "Hello Universe!" +const { state } = store( 'myPlugin', { + state: { + someText: 'Hello Universe!', + }, + actions: { + someAction: () => { + state.someText; // Access or modify global state - "Hello Universe!" - const context = getContext(); - context.someText // Access or modify local state (context) - "Hello World!" - }, - }, -} ) + const context = getContext(); + context.someText; // Access or modify local state (context) - "Hello World!" + }, + }, +} ); ``` #### Actions @@ -773,19 +806,19 @@ const { state } = store( "myPlugin", { Actions are just regular JavaScript functions. Usually triggered by the `data-wp-on` directive (using event listeners) or other actions. ```ts -const { state, actions } = store("myPlugin", { - actions: { - selectItem: ( id ) => { - const context = getContext(); - // `id` is optional here, so this action can be used in a directive. - state.selected = id || context.id; - }, - otherAction: () => { - // but it can also be called from other actions. - actions.selectItem(123); // it works and type is correct - } - } -}); +const { state, actions } = store( 'myPlugin', { + actions: { + selectItem: ( id ) => { + const context = getContext(); + // `id` is optional here, so this action can be used in a directive. + state.selected = id || context.id; + }, + otherAction: () => { + // but it can also be called from other actions. + actions.selectItem( 123 ); // it works and type is correct + }, + }, +} ); ``` <h5 id="async-actions">Async actions</h5> @@ -798,45 +831,46 @@ Imagine a block that has two buttons. One lives inside a context that has `isOpe ```html <div data-wp-context='{ "isOpen": true }'> - <button data-wp-on--click="actions.someAction">Click</button> + <button data-wp-on--click="actions.someAction">Click</button> </div> <div data-wp-context='{ "isOpen": false }'> - <button data-wp-on--click="actions.someAction">Click</button> + <button data-wp-on--click="actions.someAction">Click</button> </div> ``` If the action is async and needs to await a long delay. -- The user clicks the first button. -- The scope points to the first context, where `isOpen: true`. -- The first access to `state.isOpen` is correct because `getContext` returns the current scope. -- The action starts awaiting a long delay. -- Before the action resumes, the user clicks the second button. -- The scope is changed to the second context, where `isOpen: false`. -- The first access to `state.isOpen` is correct because `getContext` returns the current scope. -- The second action starts awaiting a long delay. -- The first action finishes awaiting and resumes its execution. -- The second access to `state.isOpen` of the first action is incorrect, because `getContext` now returns the wrong scope. +- The user clicks the first button. +- The scope points to the first context, where `isOpen: true`. +- The first access to `state.isOpen` is correct because `getContext` returns the current scope. +- The action starts awaiting a long delay. +- Before the action resumes, the user clicks the second button. +- The scope is changed to the second context, where `isOpen: false`. +- The first access to `state.isOpen` is correct because `getContext` returns the current scope. +- The second action starts awaiting a long delay. +- The first action finishes awaiting and resumes its execution. +- The second access to `state.isOpen` of the first action is incorrect, because `getContext` now returns the wrong scope. We need to be able to know when async actions start awaiting and resume operations, so we can restore the proper scope, and that's what generators do. The store will work fine if it is written like this: + ```js -const { state } = store("myPlugin", { - state: { - get isOpen() { - return getContext().isOpen; - }, - }, - actions: { - someAction: function* () { - state.isOpen; // This context is correct because it's synchronous. - yield longDelay(); // With generators, the caller controls when to resume this function. - state.isOpen; // This context is correct because we restored the proper scope before we resumed the function. - }, - }, -}); +const { state } = store( 'myPlugin', { + state: { + get isOpen() { + return getContext().isOpen; + }, + }, + actions: { + someAction: function* () { + state.isOpen; // This context is correct because it's synchronous. + yield longDelay(); // With generators, the caller controls when to resume this function. + state.isOpen; // This context is correct because we restored the proper scope before we resumed the function. + }, + }, +} ); ``` As mentioned above with [`wp-on`](#wp-on), [`wp-on-window`](#wp-on-window), and [`wp-on-document`](#wp-on-document), an async action should be used whenever the `async` versions of the aforementioned directives cannot be used due to the action requiring synchronous access to the `event` object. Synchronous access is required whenever the action needs to call `event.preventDefault()`, `event.stopPropagation()`, or `event.stopImmediatePropagation()`. To ensure that the action code does not contribute to a long task, you may manually yield to the main thread after calling the synchronous event API. For example: @@ -844,20 +878,20 @@ As mentioned above with [`wp-on`](#wp-on), [`wp-on-window`](#wp-on-window), and ```js // Note: In WordPress 6.6 this splitTask function is exported by @wordpress/interactivity. function splitTask() { - return new Promise(resolve => { - setTimeout(resolve, 0); - }); + return new Promise( ( resolve ) => { + setTimeout( resolve, 0 ); + } ); } -store("myPlugin", { - actions: { - handleClick: function* (event) { - event.preventDefault(); - yield splitTask(); - doTheWork(); - }, - }, -}); +store( 'myPlugin', { + actions: { + handleClick: function* ( event ) { + event.preventDefault(); + yield splitTask(); + doTheWork(); + }, + }, +} ); ``` You may want to add multiple such `yield` points in your action if it is doing a lot of work. @@ -872,97 +906,97 @@ They return a computed version of the state. They can access both `state` and `c ```js // view.js -const { state } = store( "myPlugin", { - state: { - amount: 34, - defaultCurrency: 'EUR', - currencyExchange: { - USD: 1.1, - GBP: 0.85, - }, - get amountInUSD() { - return state.currencyExchange[ 'USD' ] * state.amount; - }, - get amountInGBP() { - return state.currencyExchange[ 'GBP' ] * state.amount; - }, - }, +const { state } = store( 'myPlugin', { + state: { + amount: 34, + defaultCurrency: 'EUR', + currencyExchange: { + USD: 1.1, + GBP: 0.85, + }, + get amountInUSD() { + return state.currencyExchange[ 'USD' ] * state.amount; + }, + get amountInGBP() { + return state.currencyExchange[ 'GBP' ] * state.amount; + }, + }, } ); ``` ### Accessing data in callbacks - The **`store`** contains all the store properties, like `state`, `actions` or `callbacks`. They are returned by the `store()` call, so you can access them by destructuring it: ```js -const { state, actions } = store( "myPlugin", { - // ... +const { state, actions } = store( 'myPlugin', { + // ... } ); ``` The `store()` function can be called multiple times and all the store parts will be merged together: ```js -store( "myPlugin", { - state: { - someValue: 1, - } +store( 'myPlugin', { + state: { + someValue: 1, + }, } ); -const { state } = store( "myPlugin", { - actions: { - someAction() { - state.someValue // = 1 - } - } +const { state } = store( 'myPlugin', { + actions: { + someAction() { + state.someValue; // = 1 + }, + }, } ); ``` + <div class="callout callout-info"> All <code>store()</code> calls with the same namespace return the same references, i.e., the same <code>state</code>, <code>actions</code>, etc., containing the result of merging all the store parts passed. </div> -- To access the context inside an action, derived state, or side effect, you can use the `getContext` function. -- To access the reference, you can use the `getElement` function. +- To access the context inside an action, derived state, or side effect, you can use the `getContext` function. +- To access the reference, you can use the `getElement` function. ```js -const { state } = store( "myPlugin", { - state: { - get someDerivedValue() { - const context = getContext(); - const { ref } = getElement(); - // ... - } - }, - actions: { - someAction() { - const context = getContext(); - const { ref } = getElement(); - // ... - } - }, - callbacks: { - someEffect() { - const context = getContext(); - const { ref } = getElement(); - // ... - } - } +const { state } = store( 'myPlugin', { + state: { + get someDerivedValue() { + const context = getContext(); + const { ref } = getElement(); + // ... + }, + }, + actions: { + someAction() { + const context = getContext(); + const { ref } = getElement(); + // ... + }, + }, + callbacks: { + someEffect() { + const context = getContext(); + const { ref } = getElement(); + // ... + }, + }, } ); ``` This approach enables some functionalities that make directives flexible and powerful: -- Actions and side effects can read and modify the state and the context. -- Actions and state in blocks can be accessed by other blocks. -- Actions and side effects can do anything a regular JavaScript function can do, like access the DOM or make API requests. -- Side effects automatically react to state changes. +- Actions and side effects can read and modify the state and the context. +- Actions and state in blocks can be accessed by other blocks. +- Actions and side effects can do anything a regular JavaScript function can do, like access the DOM or make API requests. +- Side effects automatically react to state changes. ### Setting the store #### On the client side -*In the `view.js` file of each block* the developer can define both the state and the elements of the store referencing functions like actions, side effects or derived state. +_In the `view.js` file of each block_ the developer can define both the state and the elements of the store referencing functions like actions, side effects or derived state. The `store` method used to set the store in JavaScript can be imported from `@wordpress/interactivity`. @@ -970,21 +1004,21 @@ The `store` method used to set the store in JavaScript can be imported from `@wo // store import { store, getContext } from '@wordpress/interactivity'; -store( "myPlugin", { - actions: { - toggle: () => { - const context = getContext(); - context.isOpen = !context.isOpen; - }, - }, - callbacks: { - logIsOpen: () => { - const { isOpen } = getContext(); - // Log the value of `isOpen` each time it changes. - console.log( `Is open: ${ isOpen }` ); - } - }, -}); +store( 'myPlugin', { + actions: { + toggle: () => { + const context = getContext(); + context.isOpen = ! context.isOpen; + }, + }, + callbacks: { + logIsOpen: () => { + const { isOpen } = getContext(); + // Log the value of `isOpen` each time it changes. + console.log( `Is open: ${ isOpen }` ); + }, + }, +} ); ``` #### On the server side @@ -1022,43 +1056,54 @@ A given store namespace can be marked as private, thus preventing its content to ```js const { state } = store( - "myPlugin/private", - { state: { messages: [ "private message" ] } }, + 'myPlugin/private', + { state: { messages: [ 'private message' ] } }, { lock: true } ); // The following call throws an Error! -store( "myPlugin/private", { /* store part */ } ); +store( 'myPlugin/private', { + /* store part */ +} ); ``` There is also a way to unlock private stores: instead of passing a boolean, you can use a string as the `lock` value. Such a string can then be used in subsequent `store()` calls to the same namespace to unlock its content. Only the code knowing the string lock will be able to unlock the protected store namespaced. This is useful for complex stores defined in multiple JS modules. ```js const { state } = store( - "myPlugin/private", - { state: { messages: [ "private message" ] } }, + 'myPlugin/private', + { state: { messages: [ 'private message' ] } }, { lock: PRIVATE_LOCK } ); // The following call works as expected. -store( "myPlugin/private", { /* store part */ }, { lock: PRIVATE_LOCK } ); +store( + 'myPlugin/private', + { + /* store part */ + }, + { lock: PRIVATE_LOCK } +); ``` ### Store client methods Apart from the store function, there are also some methods that allows the developer to access data on their store functions. - - getContext() - - getElement() +- getContext() + - getServerContext() + - getServerState() +- getElement() #### getContext() Retrieves the context inherited by the element evaluating a function from the store. The returned value depends on the element and the namespace where the function calling `getContext()` exists. It can also take an optional namespace argument to retrieve the context of a specific interactive region. ```js -const context = getContext('namespace'); +const context = getContext( 'namespace' ); ``` -- `namespace` (optional): A string that matches the namespace of an interactive region. If not provided, it retrieves the context of the current interactive region. + +- `namespace` (optional): A string that matches the namespace of an interactive region. If not provided, it retrieves the context of the current interactive region. ```php // render.php @@ -1071,20 +1116,78 @@ const context = getContext('namespace'); // store import { store, getContext } from '@wordpress/interactivity'; -store( "myPlugin", { - actions: { - log: () => { - const context = getContext(); - // Logs "false" - console.log('context => ', context.isOpen) - - // With namespace argument. - const myPluginContext = getContext("myPlugin"); - // Logs "false" - console.log('myPlugin isOpen => ', myPluginContext.isOpen); - }, - }, -}); +store( 'myPlugin', { + actions: { + log: () => { + const context = getContext(); + // Logs "false" + console.log( 'context => ', context.isOpen ); + + // With namespace argument. + const myPluginContext = getContext( 'myPlugin' ); + // Logs "false" + console.log( 'myPlugin isOpen => ', myPluginContext.isOpen ); + }, + }, +} ); +``` + +#### getServerContext() + +This function is analogous to `getContext()`, but with 2 key differences: + +1. Whenever [`actions.navigate()`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity-router/#actions) from [`@wordpress/interactivity-router`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity-router/) is called, the object returned by `getServerContext()` is updated. This is useful when you want to update the context of a block based on **new** context coming from the page loaded via `actions.navigate()`. This new context is embedded in the HTML of the page loaded via `actions.navigate()`. +2. The object returned by `getServerContext()` is read-only. + +The server context cannot be directly used in directives, but you can use callbacks to subscribe to its changes. + +```js +const serverContext = getServerContext( 'namespace' ); +``` + +- `namespace` (optional): A string that matches the namespace of an interactive region. If not provided, it retrieves the server context of the current interactive region. + +Example usage: + +```js +store( 'myPlugin', { + callbacks: { + updateServerContext() { + const context = getContext(); + const serverContext = getServerContext(); + // Override some property with the new value that came from the server. + context.overridableProp = serverContext.overridableProp; + }, + }, +} ); +``` + +#### getServerState() + +Retrieves the server state an interactive region. + +This function is serves the same purpose as `getServerContext()`, but it returns the **state** instead of the **context**. + +The object returned is read-only, and includes the state defined in PHP with `wp_interactivity_state()`. When using [`actions.navigate()`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity-router/#actions) from [`@wordpress/interactivity-router`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity-router/), the object returned by `getServerState()` is updated to reflect the changes in its properties, without affecting the state returned by `store()`. Directives can subscribe to those changes to update the state if needed. + +```js +const serverState = getServerState( 'namespace' ); +``` + +- `namespace` (optional): A string that matches the namespace of an interactive region. If not provided, it retrieves the server state of the current interactive region. + +Example usage: + +```js +const { state } = store( 'myStore', { + callbacks: { + updateServerState() { + const serverState = getServerState(); + // Override some property with the new value that came from the server. + state.overridableProp = serverState.overridableProp; + }, + }, +} ); ``` #### getElement() @@ -1106,15 +1209,15 @@ Those attributes will contain the directives of that element. In the button exam // store import { store, getElement } from '@wordpress/interactivity'; -store( "myPlugin", { - actions: { - log: () => { - const element = getElement(); - // Logs attributes - console.log('element attributes => ', element.attributes) - }, - }, -}); +store( 'myPlugin', { + actions: { + log: () => { + const element = getElement(); + // Logs attributes + console.log( 'element attributes => ', element.attributes ); + }, + }, +} ); ``` The code will log: @@ -1136,7 +1239,7 @@ When the Interactivity API runtime execute callbacks, the scope is set automatic An example, where `actions.nextImage` would trigger an undefined error without the wrapper: ```js -store('mySliderPlugin', { +store( 'mySliderPlugin', { callbacks: { initSlideShow: () => { setInterval( @@ -1146,8 +1249,8 @@ store('mySliderPlugin', { 3_000 ); }, - }, -}) + }, +} ); ``` ## Server functions @@ -1218,14 +1321,13 @@ const { state } = store( 'myPlugin', { method: 'POST', body: formData, } ).then( ( response ) => response.json() ); - console.log( 'Server data!', data ); - } catch ( e ) { - // Something went wrong! - } - }, + console.log( 'Server data!', data ); + } catch ( e ) { + // Something went wrong! + } }, - } -); + }, +} ); ``` ### wp_interactivity_process_directives @@ -1244,6 +1346,7 @@ echo $processed_html; ``` will output: + ```html <div data-wp-text="myPlugin::state.greeting">Hello, World!</div> ``` @@ -1269,5 +1372,5 @@ $my_context = array( will output: ```html -<div data-wp-context='{"counter":0,"isOpen":true}'> +<div data-wp-context='{"counter":0,"isOpen":true}'></div> ``` diff --git a/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md b/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md index a2b39fc4c77fb2..f4fcbdf576c1cf 100644 --- a/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md +++ b/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md @@ -692,7 +692,7 @@ In this example, the derived state `state.double` reads from the local context p ### Example: Using derived state with both local context and global state -Let's now consider a scenario where there are a global tax rate and local product prices and calculate the final price, including tax. +Let's now consider a scenario where there is a global tax rate and local product prices and calculate the final price, including tax. ```html <div @@ -735,6 +735,108 @@ In this example, `priceWithTax` is derived from both the global `taxRate` and th By using derived state, you create a more maintainable and less error-prone codebase. It ensures that related state values are always in sync, reduces the complexity of your actions, and makes your code more declarative and easier to reason about. +## Subscribing to Server State and Context + +Interactivity API offers a region-based navigation feature that dynamically replaces a part of the page without a full page reload. The [Query block](/docs/reference-guides/core-blocks.md#query-loop) natively supports this feature when the `Force page reload` toggle is disabled. Developers can use the same functionality in custom blocks by calling [`actions.navigate()`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity-router/#actions) from the [`@wordpress/interactivity-router`](https://github.com/WordPress/gutenberg/tree/trunk/packages/interactivity-router) script module. + +When using region-based navigation, it's crucial to ensure that your interactive blocks stay in sync with the server-provided global state and local context. By default, the Interactivity API will never overwrite the global state or local context with the server-provided values. The Interactivity API provides two functions to help manage this synchronization: [`getServerState()`](/docs/reference-guides/interactivity-api/api-reference.md#getserverstate) and [`getServerContext()`](/docs/reference-guides/interactivity-api/api-reference.md#getservercontext). + +### `getServerState()` + +`getServerState()` allows you to subscribe to changes in the **global state** that occur during client-side navigation. This function is analogous to `getServerContext()`, but it works with the global state instead of the local context. + +Let's consider a quiz that has multiple questions. Each question is a separate page. When the user navigates to a new question, the server provides the new question and the time left to answer all the questions. + +```php +<?php +wp_interactivity_state( 'myPlugin', array( + 'question' => get_question_for_page( get_the_ID() ), + 'timeLeft' => 5 * 60, // Time to answer all the questions. +) ); +?> +``` + +```javascript +import { store, getServerState } from '@wordpress/interactivity'; + +store( 'myPlugin', { + actions: { + // This action would be triggered by a directive, like: + // <button data-wp-on-click="actions.nextQuestion">Next Question</button> + *nextQuestion() { + event.preventDefault( event ); + const { actions } = yield import( + '@wordpress/interactivity-router' + ); + actions.navigate( '/question-2' ); + }, + }, + callbacks: { + // This callback would be triggered by a directive, like: + // <div data-wp-watch="callbacks.updateQuestion"></div> + updateQuestion() { + const serverState = getServerState(); + + // Update with the new value coming from the server. + // We DON'T want to update `timeLeft` because it represents the time left to answer ALL the questions. + state.question = serverState.question; + }, + }, +} ); +``` + +### `getServerContext()` + +`getServerContext()` allows you to subscribe to changes in the **local context** that occur during client-side navigation. This function is analogous to `getServerState()`, but it works with the local context instead of the global state. + +Consider a quiz that has multiple questions. Each question is a separate page. When the user navigates to a new question, the server provides the new question and the time left to answer all the questions. + +```php +<?php +wp_interactivity_context( 'myPlugin', array( + 'currentQuestion' => get_question_for_page( get_the_ID() ), +) ); +?> +``` + +```javascript +import { store, getServerContext } from '@wordpress/interactivity'; + +store( 'myPlugin', { + actions: { + // This action would be triggered by a directive, like: + // <button data-wp-on-click="actions.nextQuestion">Next Question</button> + *nextQuestion() { + event.preventDefault( event ); + const { actions } = yield import( + '@wordpress/interactivity-router' + ); + actions.navigate( '/question-2' ); + }, + }, + callbacks: { + // This callback would be triggered by a directive, like: + // <div data-wp-watch="callbacks.updateQuestion"></div> + updateQuestion() { + const serverContext = getServerContext(); + const context = getContext(); + + // Update with the new value coming from the server. + context.currentQuestion = serverContext.currentQuestion; + }, + }, +} ); +``` + +### When to Use + +Whenever you have interactive blocks that rely on global state that may change due to navigation events, ensuring consistency across different parts of your application. + +### Best Practices for using `getServerState()` and `getServerContext()` + +- **Read-Only References:** Both `getServerState()` and `getServerContext()` return read-only objects. You can use those objects to update the global state or local context. +- **Callback Integration:** Incorporate these functions within your store [callbacks](/docs/reference-guides/interactivity-api/api-reference.md#accessing-data-in-callbacks) to react to state and context changes. + ## Conclusion -Remember, the key to effective state management is to keep your state minimal and avoid redundancy. Use derived state to compute values dynamically, and choose between global state and local context based on the scope and requirements of your data. This will lead to a cleaner, more robust architecture that is easier to debug and maintain. +Remember, the key to effective state management is to keep your state minimal and avoid redundancy. Use derived state to compute values dynamically, and choose between global state and local context based on the scope and requirements of your data. This will lead to a cleaner, more robust architecture that is easier to debug and maintain. Finally, if you need to synchronize the state or context with the server, you can use `getServerState()` and `getServerContext()` to achieve this. From 484c96035f521ff519afe7986c2199536a1e1485 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Tue, 22 Oct 2024 09:24:49 +1100 Subject: [PATCH 1270/1908] Block toolbar: account for scrollable blocks that affect the position of the block toolbar (#66188) The rect bounds of blocvk child elements, specifically the x and y values, change when the element is scrolled. This change attempts to correct the overflow so the scrollable children do not influence the x,y values of the block toolbar popover. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- packages/block-editor/src/utils/dom.js | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/utils/dom.js b/packages/block-editor/src/utils/dom.js index 9c2e813ef742b6..0603e9bbb1db96 100644 --- a/packages/block-editor/src/utils/dom.js +++ b/packages/block-editor/src/utils/dom.js @@ -118,6 +118,22 @@ function isElementVisible( element ) { return true; } +/** + * Checks if the element is scrollable. + * + * @param {Element} element Element. + * @return {boolean} True if the element is scrollable. + */ +function isScrollable( element ) { + const style = window.getComputedStyle( element ); + return ( + style.overflowX === 'auto' || + style.overflowX === 'scroll' || + style.overflowY === 'auto' || + style.overflowY === 'scroll' + ); +} + /** * Returns the rect of the element including all visible nested elements. * @@ -136,19 +152,23 @@ function isElementVisible( element ) { */ export function getVisibleElementBounds( element ) { const viewport = element.ownerDocument.defaultView; + if ( ! viewport ) { return new window.DOMRectReadOnly(); } let bounds = element.getBoundingClientRect(); - const stack = [ element ]; let currentElement; while ( ( currentElement = stack.pop() ) ) { for ( const child of currentElement.children ) { if ( isElementVisible( child ) ) { - const childBounds = child.getBoundingClientRect(); + let childBounds = child.getBoundingClientRect(); + // If the parent is scrollable, use parent's scrollable bounds. + if ( isScrollable( currentElement ) ) { + childBounds = currentElement.getBoundingClientRect(); + } bounds = rectUnion( bounds, childBounds ); stack.push( child ); } From e36a382fac75293db3d603ba679d1b96fc46b627 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 22 Oct 2024 14:02:18 +0900 Subject: [PATCH 1271/1908] Post Editor: Always force iframe in pattern editor (#65887) * Post Editor: Always force iframe in pattern editor * Aggregate conditions into useShouldIframe hook * Revert "Aggregate conditions into useShouldIframe hook" This reverts commit 5da84337c5d2845489f0a0e8ebc3d728898deee3. * Aggregate conditions into useShouldIframe hook * Add device type check to useShouldIframe check Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> --- .../src/components/layout/use-should-iframe.js | 16 +++++++++++----- .../editor/src/components/visual-editor/index.js | 6 ++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/edit-post/src/components/layout/use-should-iframe.js b/packages/edit-post/src/components/layout/use-should-iframe.js index 97e746a6a28f6e..6da344c138f64b 100644 --- a/packages/edit-post/src/components/layout/use-should-iframe.js +++ b/packages/edit-post/src/components/layout/use-should-iframe.js @@ -17,10 +17,12 @@ export function useShouldIframe() { const { isBlockBasedTheme, hasV3BlocksOnly, - isEditingTemplate, + isEditingTemplateOrPattern, isZoomOutMode, + deviceType, } = useSelect( ( select ) => { - const { getEditorSettings, getCurrentPostType } = select( editorStore ); + const { getEditorSettings, getCurrentPostType, getDeviceType } = + select( editorStore ); const { isZoomOut } = unlock( select( blockEditorStore ) ); const { getBlockTypes } = select( blocksStore ); const editorSettings = getEditorSettings(); @@ -29,15 +31,19 @@ export function useShouldIframe() { hasV3BlocksOnly: getBlockTypes().every( ( type ) => { return type.apiVersion >= 3; } ), - isEditingTemplate: getCurrentPostType() === 'wp_template', + isEditingTemplateOrPattern: [ 'wp_template', 'wp_block' ].includes( + getCurrentPostType() + ), isZoomOutMode: isZoomOut(), + deviceType: getDeviceType(), }; }, [] ); return ( hasV3BlocksOnly || ( isGutenbergPlugin && isBlockBasedTheme ) || - isEditingTemplate || - isZoomOutMode + isEditingTemplateOrPattern || + isZoomOutMode || + [ 'Tablet', 'Mobile' ].includes( deviceType ) ); } diff --git a/packages/editor/src/components/visual-editor/index.js b/packages/editor/src/components/visual-editor/index.js index 8ad9ce7fc974ac..0f772075f5d4ae 100644 --- a/packages/editor/src/components/visual-editor/index.js +++ b/packages/editor/src/components/visual-editor/index.js @@ -351,8 +351,6 @@ function VisualEditor( { ! isMobileViewport && // Dsiable resizing in zoomed-out mode. ! isZoomedOut; - const shouldIframe = - ! disableIframe || [ 'Tablet', 'Mobile' ].includes( deviceType ); const iframeStyles = useMemo( () => { return [ @@ -377,7 +375,7 @@ function VisualEditor( { { 'has-padding': isFocusedEntity || enableResizing, 'is-resizable': enableResizing, - 'is-iframed': shouldIframe, + 'is-iframed': ! disableIframe, } ) } > @@ -388,7 +386,7 @@ function VisualEditor( { } > <BlockCanvas - shouldIframe={ shouldIframe } + shouldIframe={ ! disableIframe } contentRef={ contentRef } styles={ iframeStyles } height="100%" From 3705cf89292d979ab9247a8eabfcc862fe3dd223 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Tue, 22 Oct 2024 07:57:29 +0200 Subject: [PATCH 1272/1908] Block editor: remove reusable blocks stylesheet from iframe (#66285) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- backport-changelog/6.8/7604.md | 3 +++ lib/client-assets.php | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 backport-changelog/6.8/7604.md diff --git a/backport-changelog/6.8/7604.md b/backport-changelog/6.8/7604.md new file mode 100644 index 00000000000000..fc6902859caa49 --- /dev/null +++ b/backport-changelog/6.8/7604.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7604 + +* https://github.com/WordPress/gutenberg/pull/66285 diff --git a/lib/client-assets.php b/lib/client-assets.php index 3e4f79cd3c1f77..092ae2d3679424 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -327,7 +327,6 @@ function gutenberg_register_packages_styles( $styles ) { 'wp-reset-editor-styles', 'wp-block-library', 'wp-patterns', - 'wp-reusable-blocks', // Until #37466, we can't specifically add them as editor styles yet, // so we must hard-code it here as a dependency. 'wp-block-editor-content', From 0711717b8a6586212e5a2da03cc34ba92dba0e91 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Tue, 22 Oct 2024 08:52:13 +0200 Subject: [PATCH 1273/1908] Fix Global styles panel header buttons text overlap for 'Show button text labels' (#63243) * Use compact variant for close butotn in complementary area. * Fix global styles header buttons when they show text. * Improve flexbox layout. * Adjust gap. * Set button size to small. * Remove no longer necessary margins. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- .../components/global-styles-sidebar/index.js | 66 +++++++++++-------- .../global-styles-sidebar/style.scss | 6 ++ .../complementary-area-header/style.scss | 5 -- 3 files changed, 43 insertions(+), 34 deletions(-) diff --git a/packages/edit-site/src/components/global-styles-sidebar/index.js b/packages/edit-site/src/components/global-styles-sidebar/index.js index 90a3331d14c716..2194f2edbc0f29 100644 --- a/packages/edit-site/src/components/global-styles-sidebar/index.js +++ b/packages/edit-site/src/components/global-styles-sidebar/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { FlexItem, FlexBlock, Flex, Button } from '@wordpress/components'; +import { FlexItem, Flex, Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { styles, seen, backup } from '@wordpress/icons'; import { useSelect, useDispatch } from '@wordpress/data'; @@ -130,38 +130,46 @@ export default function GlobalStylesSidebar() { className="edit-site-global-styles-sidebar__header" gap={ 1 } > - <FlexBlock style={ { minWidth: 'min-content' } }> + <FlexItem> <h2 className="edit-site-global-styles-sidebar__header-title"> { __( 'Styles' ) } </h2> - </FlexBlock> - <FlexItem> - <Button - icon={ seen } - label={ __( 'Style Book' ) } - isPressed={ - isStyleBookOpened || isRevisionsStyleBookOpened - } - accessibleWhenDisabled - disabled={ shouldClearCanvasContainerView } - onClick={ toggleStyleBook } - size="compact" - /> - </FlexItem> - <FlexItem> - <Button - label={ __( 'Revisions' ) } - icon={ backup } - onClick={ toggleRevisions } - accessibleWhenDisabled - disabled={ ! hasRevisions } - isPressed={ - isRevisionsOpened || isRevisionsStyleBookOpened - } - size="compact" - /> </FlexItem> - <GlobalStylesMenuSlot /> + <Flex + justify="flex-end" + gap={ 1 } + className="edit-site-global-styles-sidebar__header-actions" + > + <FlexItem> + <Button + icon={ seen } + label={ __( 'Style Book' ) } + isPressed={ + isStyleBookOpened || + isRevisionsStyleBookOpened + } + accessibleWhenDisabled + disabled={ shouldClearCanvasContainerView } + onClick={ toggleStyleBook } + size="compact" + /> + </FlexItem> + <FlexItem> + <Button + label={ __( 'Revisions' ) } + icon={ backup } + onClick={ toggleRevisions } + accessibleWhenDisabled + disabled={ ! hasRevisions } + isPressed={ + isRevisionsOpened || + isRevisionsStyleBookOpened + } + size="compact" + /> + </FlexItem> + <GlobalStylesMenuSlot /> + </Flex> </Flex> } > diff --git a/packages/edit-site/src/components/global-styles-sidebar/style.scss b/packages/edit-site/src/components/global-styles-sidebar/style.scss index 4ca87bf200f178..30b1fc597ad707 100644 --- a/packages/edit-site/src/components/global-styles-sidebar/style.scss +++ b/packages/edit-site/src/components/global-styles-sidebar/style.scss @@ -31,6 +31,10 @@ margin: 0; } +.edit-site-global-styles-sidebar .edit-site-global-styles-sidebar__header-actions { + flex: 1; +} + .edit-site-global-styles-sidebar .components-navigation__menu-title-heading { font-size: $default-font-size * 1.2; font-weight: 500; @@ -75,6 +79,8 @@ .show-icon-labels { .edit-site-global-styles-sidebar__header { .components-button.has-icon { + width: auto; + // Hide the button icons when labels are set to display... svg { display: none; diff --git a/packages/interface/src/components/complementary-area-header/style.scss b/packages/interface/src/components/complementary-area-header/style.scss index a6b9b532069602..2984c78c776a70 100644 --- a/packages/interface/src/components/complementary-area-header/style.scss +++ b/packages/interface/src/components/complementary-area-header/style.scss @@ -26,11 +26,6 @@ .components-button.has-icon { display: none; - margin-left: auto; - - ~ .components-button { - margin-left: 0; - } @include break-medium() { display: flex; From 48d201833e258b57bf0171276f8bcd8294f09d6a Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:28:35 +0530 Subject: [PATCH 1274/1908] Add lightbox option in gallery block link control (#64014) * Add link control as toolbar option in gallery * Add link option constant for lightbox * Add expand on lick option in link control * Add class into menugroup component for info text style * Add styles for info text in link control of popover of gallery block * Add info text for lightbox option in link control for gallery block * Add action for lightbox option in gallery block link control * Show lightbox option only when lightbox UI is enabled * Disable lightbox when other link option is selected in gallery block * Remove unneccessory constant * Conditionally apply the lightbox attribute based on defatult setting * Fix lightbox default option issue for gallery block on page load * Highlight link to option in gallery block when selected * update condition to Highlight link to option * Fix lightbox attribute issue for default state of linkTo option * fix: Set empty default `block` settings value (#64448) Currently, `__experimentalFeatures` is only partially implemented for the native mobile editor. Recent changes to the shared Gallery block component included a reference to this missing key via the `useSettings` Hook. Setting a default, empty value ensure exceptions are not thrown. Co-authored-by: dcalhoun <dpcalhoun@git.wordpress.org> Co-authored-by: akasunil <sunil25393@git.wordpress.org> * Change lightbox option lable and address other feedback * Move lightbox logic to getHrefAndDestination function * Remove highlight of LinkTo option in gallery block * Remove css for info text of lightbox option * Refactor getHrefAndDestination function to for lightbox additional attributes --------- Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: dcalhoun <dpcalhoun@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: madhusudhand <madhudollu@git.wordpress.org> --- .../test/use-global-styles-context.native.js | 1 + .../use-global-styles-context.native.js | 6 +++++ .../block-library/src/gallery/constants.js | 1 + packages/block-library/src/gallery/edit.js | 27 +++++++++++++++++-- packages/block-library/src/gallery/utils.js | 25 +++++++++++++++-- 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/test/use-global-styles-context.native.js b/packages/block-editor/src/components/global-styles/test/use-global-styles-context.native.js index a247b4132b1ff7..a8b1e9e1bdf1b9 100644 --- a/packages/block-editor/src/components/global-styles/test/use-global-styles-context.native.js +++ b/packages/block-editor/src/components/global-styles/test/use-global-styles-context.native.js @@ -414,6 +414,7 @@ describe( 'getGlobalStyles', () => { expect( globalStyles ).toEqual( expect.objectContaining( { __experimentalFeatures: { + blocks: {}, color: { palette: RAW_FEATURES.color.palette, gradients, diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-context.native.js b/packages/block-editor/src/components/global-styles/use-global-styles-context.native.js index 31bcd899fda7a9..f4aedc378e1a73 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-context.native.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-context.native.js @@ -410,6 +410,9 @@ export function getColorsAndGradients( return { __experimentalGlobalStylesBaseStyles: null, __experimentalFeatures: { + // Set an empty object to avoid errors from shared web components relying + // upon block settings. E.g., the Gallery block. + blocks: {}, color: { ...( ! features?.color ? { @@ -455,6 +458,9 @@ export function getGlobalStyles( rawStyles, rawFeatures ) { return { __experimentalFeatures: { + // Set an empty object to avoid errors from shared web components relying + // upon block settings. E.g., the Gallery block. + blocks: {}, color: { palette: colors?.palette, gradients, diff --git a/packages/block-library/src/gallery/constants.js b/packages/block-library/src/gallery/constants.js index f4a06914393132..19fc61cac84583 100644 --- a/packages/block-library/src/gallery/constants.js +++ b/packages/block-library/src/gallery/constants.js @@ -1,5 +1,6 @@ export const LINK_DESTINATION_NONE = 'none'; export const LINK_DESTINATION_MEDIA = 'media'; +export const LINK_DESTINATION_LIGHTBOX = 'lightbox'; export const LINK_DESTINATION_ATTACHMENT = 'attachment'; export const LINK_DESTINATION_MEDIA_WP_CORE = 'file'; export const LINK_DESTINATION_ATTACHMENT_WP_CORE = 'post'; diff --git a/packages/block-library/src/gallery/edit.js b/packages/block-library/src/gallery/edit.js index c73fe1977ce4cc..7a0cc1de53c387 100644 --- a/packages/block-library/src/gallery/edit.js +++ b/packages/block-library/src/gallery/edit.js @@ -25,6 +25,7 @@ import { useInnerBlocksProps, BlockControls, MediaReplaceFlow, + useSettings, } from '@wordpress/block-editor'; import { Platform, useEffect, useMemo } from '@wordpress/element'; import { __, _x, sprintf } from '@wordpress/i18n'; @@ -38,6 +39,7 @@ import { customLink, image as imageIcon, linkOff, + fullscreen, } from '@wordpress/icons'; /** @@ -55,6 +57,7 @@ import { LINK_DESTINATION_ATTACHMENT, LINK_DESTINATION_MEDIA, LINK_DESTINATION_NONE, + LINK_DESTINATION_LIGHTBOX, } from './constants'; import useImageSizes from './use-image-sizes'; import useGetNewImages from './use-get-new-images'; @@ -62,7 +65,7 @@ import useGetMedia from './use-get-media'; import GapStyles from './gap-styles'; const MAX_COLUMNS = 8; -const linkOptions = [ +let linkOptions = [ { icon: customLink, label: __( 'Link images to attachment pages' ), @@ -75,6 +78,13 @@ const linkOptions = [ value: LINK_DESTINATION_MEDIA, noticeText: __( 'Media Files' ), }, + { + icon: fullscreen, + label: __( 'Expand on click' ), + value: LINK_DESTINATION_LIGHTBOX, + noticeText: __( 'Lightbox effect' ), + infoText: __( 'Scale images with a lightbox effect' ), + }, { icon: linkOff, label: _x( 'None', 'Media item link option' ), @@ -107,6 +117,14 @@ export default function GalleryEdit( props ) { onFocus, } = props; + const lightboxSetting = useSettings( 'blocks.core/image.lightbox' )[ 0 ]; + + if ( ! lightboxSetting?.allowEditing ) { + linkOptions = linkOptions.filter( + ( option ) => option.value !== LINK_DESTINATION_LIGHTBOX + ); + } + const { columns, imageCrop, randomOrder, linkTarget, linkTo, sizeSlug } = attributes; @@ -363,9 +381,13 @@ export default function GalleryEdit( props ) { const image = block.attributes.id ? imageData.find( ( { id } ) => id === block.attributes.id ) : null; + changedAttributes[ block.clientId ] = getHrefAndDestination( image, - value + value, + false, + block.attributes, + lightboxSetting ); } ); updateBlockAttributes( blocks, changedAttributes, true ); @@ -646,6 +668,7 @@ export default function GalleryEdit( props ) { onClose(); } } role="menuitemradio" + info={ linkItem.infoText } > { linkItem.label } </MenuItem> diff --git a/packages/block-library/src/gallery/utils.js b/packages/block-library/src/gallery/utils.js index 15f2062ea943da..4b2aca81f6ffb3 100644 --- a/packages/block-library/src/gallery/utils.js +++ b/packages/block-library/src/gallery/utils.js @@ -7,6 +7,7 @@ import { LINK_DESTINATION_NONE, LINK_DESTINATION_MEDIA_WP_CORE, LINK_DESTINATION_ATTACHMENT_WP_CORE, + LINK_DESTINATION_LIGHTBOX, } from './constants'; import { LINK_DESTINATION_ATTACHMENT as IMAGE_LINK_DESTINATION_ATTACHMENT, @@ -20,13 +21,18 @@ import { * * @param {Object} image Gallery image. * @param {string} galleryDestination Gallery's selected link destination. - * @param {Object} imageDestination Image blocks attributes. + * @param {Object} imageDestination Image block link destination attribute. + * @param {Object} attributes Block attributes. + * @param {Object} lightboxSetting Lightbox setting. + * * @return {Object} New attributes to assign to image block. */ export function getHrefAndDestination( image, galleryDestination, - imageDestination + imageDestination, + attributes, + lightboxSetting ) { // Gutenberg and WordPress use different constants so if image_default_link_type // option is set we need to map from the WP Core values. @@ -36,17 +42,32 @@ export function getHrefAndDestination( return { href: image?.source_url || image?.url, // eslint-disable-line camelcase linkDestination: IMAGE_LINK_DESTINATION_MEDIA, + lightbox: lightboxSetting?.enabled + ? { ...attributes?.lightbox, enabled: false } + : undefined, }; case LINK_DESTINATION_ATTACHMENT_WP_CORE: case LINK_DESTINATION_ATTACHMENT: return { href: image?.link, linkDestination: IMAGE_LINK_DESTINATION_ATTACHMENT, + lightbox: lightboxSetting?.enabled + ? { ...attributes?.lightbox, enabled: false } + : undefined, + }; + case LINK_DESTINATION_LIGHTBOX: + return { + href: undefined, + lightbox: ! lightboxSetting?.enabled + ? { ...attributes?.lightbox, enabled: true } + : undefined, + linkDestination: IMAGE_LINK_DESTINATION_NONE, }; case LINK_DESTINATION_NONE: return { href: undefined, linkDestination: IMAGE_LINK_DESTINATION_NONE, + lightbox: undefined, }; } From f9055e28ee7896d335204e74a5005ecec1c53472 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 22 Oct 2024 16:12:36 +0900 Subject: [PATCH 1275/1908] Upgrade Playwright to v1.48 (#66296) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> --- package-lock.json | 26 +++++++++++++------------- package.json | 2 +- packages/scripts/package.json | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 82cf77db40c57d..524584ed63e31a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -100,7 +100,7 @@ "@octokit/rest": "16.26.0", "@octokit/types": "6.34.0", "@octokit/webhooks-types": "5.8.0", - "@playwright/test": "1.47.0", + "@playwright/test": "1.48.1", "@pmmmwh/react-refresh-webpack-plugin": "0.5.11", "@react-native/babel-preset": "0.73.10", "@react-native/metro-babel-transformer": "0.73.10", @@ -7096,12 +7096,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.0.tgz", - "integrity": "sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA==", + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.1.tgz", + "integrity": "sha512-s9RtWoxkOLmRJdw3oFvhFbs9OJS0BzrLUc8Hf6l2UdCNd1rqeEyD4BhCJkvzeEoD1FsK4mirsWwGerhVmYKtZg==", "dev": true, "dependencies": { - "playwright": "1.47.0" + "playwright": "1.48.1" }, "bin": { "playwright": "cli.js" @@ -41274,12 +41274,12 @@ "dev": true }, "node_modules/playwright": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.0.tgz", - "integrity": "sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==", + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.1.tgz", + "integrity": "sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w==", "dev": true, "dependencies": { - "playwright-core": "1.47.0" + "playwright-core": "1.48.1" }, "bin": { "playwright": "cli.js" @@ -41292,9 +41292,9 @@ } }, "node_modules/playwright-core": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0.tgz", - "integrity": "sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==", + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.1.tgz", + "integrity": "sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -56607,7 +56607,7 @@ "npm": ">=8.19.2" }, "peerDependencies": { - "@playwright/test": "^1.47.0", + "@playwright/test": "^1.48.1", "react": "^18.0.0", "react-dom": "^18.0.0" } diff --git a/package.json b/package.json index c280e1b728c3df..67bfb7cf5df37b 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "@octokit/rest": "16.26.0", "@octokit/types": "6.34.0", "@octokit/webhooks-types": "5.8.0", - "@playwright/test": "1.47.0", + "@playwright/test": "1.48.1", "@pmmmwh/react-refresh-webpack-plugin": "0.5.11", "@react-native/babel-preset": "0.73.10", "@react-native/metro-babel-transformer": "0.73.10", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 66461f4eb28ec2..9bc4fcd915b204 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -95,7 +95,7 @@ "webpack-dev-server": "^4.15.1" }, "peerDependencies": { - "@playwright/test": "^1.47.0", + "@playwright/test": "^1.48.1", "react": "^18.0.0", "react-dom": "^18.0.0" }, From fe56004bafc42cdfe1fde897f05ff1d64a60b661 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Tue, 22 Oct 2024 09:33:00 +0200 Subject: [PATCH 1276/1908] Clean up: adjust reusable-blocks dependencies (#66302) --- backport-changelog/6.8/7604.md | 1 + lib/client-assets.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backport-changelog/6.8/7604.md b/backport-changelog/6.8/7604.md index fc6902859caa49..8c7d80994ae605 100644 --- a/backport-changelog/6.8/7604.md +++ b/backport-changelog/6.8/7604.md @@ -1,3 +1,4 @@ https://github.com/WordPress/wordpress-develop/pull/7604 * https://github.com/WordPress/gutenberg/pull/66285 +* https://github.com/WordPress/gutenberg/pull/66302 diff --git a/lib/client-assets.php b/lib/client-assets.php index 092ae2d3679424..275c48dfc8e2d1 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -419,7 +419,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-editor', 'wp-edit-blocks', 'wp-patterns', 'wp-reusable-blocks', 'wp-widgets', 'wp-preferences' ), + array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks', 'wp-patterns', 'wp-widgets', 'wp-preferences' ), $version ); $styles->add_data( 'wp-edit-widgets', 'rtl', 'replace' ); From 0e65adcbe187797a536aa99f56b063a61cafdc3d Mon Sep 17 00:00:00 2001 From: Juan Aldasoro <juanfraa@gmail.com> Date: Tue, 22 Oct 2024 11:03:26 +0200 Subject: [PATCH 1277/1908] Set image width to `fit-content` to solve aspect ratio problems in Firefox. (#66217) --- packages/block-library/src/image/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/image/style.scss b/packages/block-library/src/image/style.scss index 1bb19bf29da691..da4ccc50dac7f1 100644 --- a/packages/block-library/src/image/style.scss +++ b/packages/block-library/src/image/style.scss @@ -9,6 +9,7 @@ max-width: 100%; vertical-align: bottom; box-sizing: border-box; + width: fit-content; @media (prefers-reduced-motion: no-preference) { &.hide { From a4aeb1a03e91848fed09e6036ead2c54ad8db02e Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Tue, 22 Oct 2024 12:26:42 +0300 Subject: [PATCH 1278/1908] Storybook: Add BlockPatternsList story (#66227) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../block-patterns-list/stories/fixtures.js | 834 ++++++++++++++++++ .../stories/index.story.js | 81 ++ .../components/block-patterns-list/style.scss | 2 + 3 files changed, 917 insertions(+) create mode 100644 packages/block-editor/src/components/block-patterns-list/stories/fixtures.js create mode 100644 packages/block-editor/src/components/block-patterns-list/stories/index.story.js diff --git a/packages/block-editor/src/components/block-patterns-list/stories/fixtures.js b/packages/block-editor/src/components/block-patterns-list/stories/fixtures.js new file mode 100644 index 00000000000000..0fd895bbe1716d --- /dev/null +++ b/packages/block-editor/src/components/block-patterns-list/stories/fixtures.js @@ -0,0 +1,834 @@ +export default [ + { + name: 'test/1', + title: 'Centered image with two-tone background color', + blocks: [ + { + clientId: '035ea9e6-cf5a-4631-a11e-29f3f696f836', + name: 'core/cover', + isValid: true, + attributes: { + useFeaturedImage: false, + alt: '', + hasParallax: false, + isRepeated: false, + dimRatio: 100, + backgroundType: 'image', + minHeight: 66, + minHeightUnit: 'vh', + customGradient: + 'linear-gradient(90deg,rgb(35,74,20) 50%,rgb(225,137,116) 50%)', + isDark: false, + tagName: 'div', + align: 'full', + style: { + spacing: { + padding: { + top: '5vw', + right: '5vw', + bottom: '5vw', + left: '5vw', + }, + margin: { + top: '0', + }, + }, + }, + }, + innerBlocks: [ + { + clientId: '57c3e044-137d-456d-8426-20768e07f09f', + name: 'core/group', + isValid: true, + attributes: { + tagName: 'div', + style: { + spacing: { + blockGap: '0px', + }, + layout: { + selfStretch: 'fill', + flexSize: null, + }, + }, + layout: { + type: 'constrained', + contentSize: '600px', + wideSize: '1200px', + }, + }, + innerBlocks: [ + { + clientId: + '9e251315-0ea5-4849-9e1a-974de0981f51', + name: 'core/spacer', + isValid: true, + attributes: { + height: '100px', + }, + innerBlocks: [], + originalContent: + '<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>', + validationIssues: [], + }, + { + clientId: + 'd83373a3-bdc3-44d6-9f6f-5a36ef8d637c', + name: 'core/image', + isValid: true, + attributes: { + url: 'https://pd.w.org/2022/03/3866241b433db4ee2.96648572.jpeg', + alt: '', + caption: '', + sizeSlug: 'large', + className: 'is-style-default', + style: { + color: { + duotone: [ '#000000', '#ffffff' ], + }, + }, + }, + innerBlocks: [], + originalContent: + '<figure class="wp-block-image size-large is-style-default"><img src="https://pd.w.org/2022/03/3866241b433db4ee2.96648572.jpeg" alt="" /></figure>', + validationIssues: [], + }, + { + clientId: + '56e72331-1213-466f-bd14-1131a56b2c95', + name: 'core/spacer', + isValid: true, + attributes: { + height: '48px', + }, + innerBlocks: [], + originalContent: + '<div style="height:48px" aria-hidden="true" class="wp-block-spacer"></div>', + validationIssues: [], + }, + { + clientId: + '851c15bc-f5cf-4780-838e-6bfea2b09b30', + name: 'core/heading', + isValid: true, + attributes: { + textAlign: 'center', + content: 'Etcetera', + level: 2, + align: 'wide', + style: { + typography: { + fontSize: '50px', + fontStyle: 'normal', + fontWeight: '400', + textTransform: 'uppercase', + letterSpacing: '32px', + lineHeight: '1', + }, + spacing: { + padding: { + left: '32px', + }, + }, + }, + textColor: 'white', + }, + innerBlocks: [], + originalContent: + '<h2 class="wp-block-heading alignwide has-text-align-center has-white-color has-text-color" style="padding-left:32px;font-size:50px;font-style:normal;font-weight:400;letter-spacing:32px;line-height:1;text-transform:uppercase">Etcetera</h2>', + validationIssues: [], + }, + { + clientId: + 'a734e600-5b98-47c4-982d-c98e8c8b78a2', + name: 'core/spacer', + isValid: true, + attributes: { + height: '100px', + }, + innerBlocks: [], + originalContent: + '<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-group">\n\n\n\n\n\n\n\n</div>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-cover alignfull is-light" style="margin-top:0;padding-top:5vw;padding-right:5vw;padding-bottom:5vw;padding-left:5vw;min-height:66vh"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-100 has-background-dim has-background-gradient" style="background:linear-gradient(90deg,rgb(35,74,20) 50%,rgb(225,137,116) 50%)"></span><div class="wp-block-cover__inner-container"></div></div>', + validationIssues: [], + }, + ], + }, + { + name: 'test/2', + title: 'Fullwidth, vertically aligned headline on right with description on left', + blocks: [ + { + clientId: 'efa29ce0-cf43-421b-b9e6-46f52f17d943', + name: 'core/cover', + isValid: true, + attributes: { + alt: '', + hasParallax: false, + isRepeated: false, + dimRatio: 100, + customOverlayColor: '#e68b14', + backgroundType: 'image', + isDark: false, + useFeaturedImage: false, + tagName: 'div', + align: 'full', + style: { + spacing: { + padding: { + top: '5vw', + right: '5vw', + bottom: '5vw', + left: '5vw', + }, + margin: { + top: '0', + }, + }, + }, + isUserOverlayColor: true, + }, + innerBlocks: [ + { + clientId: '4e50914f-9c9c-471a-84ad-4a22b514a393', + name: 'core/group', + isValid: true, + attributes: { + tagName: 'div', + layout: { + type: 'flex', + flexWrap: 'wrap', + verticalAlignment: 'top', + }, + }, + innerBlocks: [ + { + clientId: + '72b5d32d-35df-4530-8c81-ce67baaf34d1', + name: 'core/group', + isValid: true, + attributes: { + tagName: 'div', + style: { + layout: { + selfStretch: 'fixed', + flexSize: '320px', + }, + spacing: { + blockGap: '24px', + }, + }, + layout: { + type: 'default', + }, + }, + innerBlocks: [ + { + clientId: + '86b7c5b3-2de6-42ff-9d41-d38dd267a122', + name: 'core/paragraph', + isValid: true, + attributes: { + content: + "Let 'em Roll is an album by American organist Big John Patton recorded in 1965 and released on the Blue Note label.", + dropCap: false, + style: { + layout: { + selfStretch: 'fixed', + flexSize: '330px', + }, + typography: { + fontSize: '17px', + fontStyle: 'normal', + fontWeight: '300', + lineHeight: '1.4', + textTransform: 'none', + textDecoration: 'none', + letterSpacing: '0px', + }, + }, + }, + innerBlocks: [], + originalContent: + '<p style="font-size:17px;font-style:normal;font-weight:300;letter-spacing:0px;line-height:1.4;text-decoration:none;text-transform:none">Let \'em Roll is an album by American organist Big John Patton recorded in 1965 and released on the Blue Note label.</p>', + validationIssues: [], + }, + { + clientId: + '50d8d1c7-05dd-41d4-af67-29449e818ef7', + name: 'core/buttons', + isValid: true, + attributes: {}, + innerBlocks: [ + { + clientId: + '3e26f576-a29a-4947-85f2-1454ea85db60', + name: 'core/button', + isValid: true, + attributes: { + tagName: 'a', + type: 'button', + text: 'Shop Now', + backgroundColor: 'black', + textColor: 'white', + style: { + typography: { + fontSize: '17px', + fontStyle: 'normal', + fontWeight: '700', + textDecoration: + 'none', + textTransform: + 'uppercase', + letterSpacing: + '0px', + }, + spacing: { + padding: { + top: '14px', + bottom: '14px', + left: '36px', + right: '36px', + }, + }, + border: { + radius: '0px', + top: { + radius: '0px', + width: '0px', + style: 'none', + }, + right: { + radius: '0px', + width: '0px', + style: 'none', + }, + bottom: { + radius: '0px', + width: '0px', + style: 'none', + }, + left: { + radius: '0px', + width: '0px', + style: 'none', + }, + }, + }, + }, + innerBlocks: [], + originalContent: + '<div class="wp-block-button has-custom-font-size" style="font-size:17px;font-style:normal;font-weight:700;letter-spacing:0px;text-decoration:none;text-transform:uppercase"><a class="wp-block-button__link has-white-color has-black-background-color has-text-color has-background wp-element-button" style="border-radius:0px;border-top-style:none;border-top-width:0px;border-right-style:none;border-right-width:0px;border-bottom-style:none;border-bottom-width:0px;border-left-style:none;border-left-width:0px;padding-top:14px;padding-right:36px;padding-bottom:14px;padding-left:36px">Shop Now</a></div>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-buttons"></div>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-group">\n\n</div>', + validationIssues: [], + }, + { + clientId: + 'e8176dce-481f-4454-8e01-13bc5382e0fd', + name: 'core/group', + isValid: true, + attributes: { + tagName: 'div', + style: { + spacing: { + blockGap: '0px', + }, + layout: { + selfStretch: 'fill', + flexSize: null, + }, + }, + layout: { + type: 'default', + }, + }, + innerBlocks: [ + { + clientId: + '738291ae-b0d1-4867-90b5-f35b999ca407', + name: 'core/paragraph', + isValid: true, + attributes: { + align: 'right', + content: "Let<br>'EM<br>Roll", + dropCap: false, + style: { + typography: { + fontSize: '148px', + textTransform: 'uppercase', + fontStyle: 'normal', + fontWeight: '700', + lineHeight: '0.8', + letterSpacing: '-4px', + }, + }, + textColor: 'black', + }, + innerBlocks: [], + originalContent: + '<p class="has-text-align-right has-black-color has-text-color" style="font-size:148px;font-style:normal;font-weight:700;letter-spacing:-4px;line-height:0.8;text-transform:uppercase">Let<br>\'EM<br>Roll</p>', + validationIssues: [], + }, + { + clientId: + '331df46f-7623-49a1-8031-7c421bddc15a', + name: 'core/paragraph', + isValid: true, + attributes: { + align: 'right', + content: 'Big<br>John<br>Patton', + dropCap: false, + style: { + typography: { + fontSize: '148px', + textTransform: 'uppercase', + fontStyle: 'normal', + fontWeight: '700', + lineHeight: '0.8', + letterSpacing: '-4px', + }, + }, + textColor: 'white', + }, + innerBlocks: [], + originalContent: + '<p class="has-text-align-right has-white-color has-text-color" style="font-size:148px;font-style:normal;font-weight:700;letter-spacing:-4px;line-height:0.8;text-transform:uppercase">Big<br>John<br>Patton</p>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-group">\n\n</div>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-group">\n\n</div>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-cover alignfull is-light" style="margin-top:0;padding-top:5vw;padding-right:5vw;padding-bottom:5vw;padding-left:5vw"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-100 has-background-dim" style="background-color:#e68b14"></span><div class="wp-block-cover__inner-container"></div></div>', + validationIssues: [], + }, + ], + }, + { + name: 'test/3', + title: 'Two columns of text with offset heading', + blocks: [ + { + clientId: 'da715d18-2126-4be0-bf13-3328419f220a', + name: 'core/group', + isValid: true, + attributes: { + tagName: 'div', + align: 'full', + style: { + color: { + background: '#f2f0e9', + }, + }, + }, + innerBlocks: [ + { + clientId: '8a89e4af-1f70-4545-9d1e-887ff50a141d', + name: 'core/spacer', + isValid: true, + attributes: { + height: '70px', + }, + innerBlocks: [], + originalContent: + '<div style="height:70px" aria-hidden="true" class="wp-block-spacer"></div>', + validationIssues: [], + }, + { + clientId: '4ab42169-0fcd-416a-bd34-487f6a4e33ad', + name: 'core/columns', + isValid: true, + attributes: { + verticalAlignment: 'center', + isStackedOnMobile: true, + align: 'wide', + }, + innerBlocks: [ + { + clientId: + '88b53c37-16dc-4396-b9bc-6cc115411d9a', + name: 'core/column', + isValid: true, + attributes: { + width: '50%', + }, + innerBlocks: [ + { + clientId: + '1b5a12e4-06cf-4f78-b665-7440771d0025', + name: 'core/paragraph', + isValid: true, + attributes: { + content: + '<strong>Oceanic Inspiration</strong>', + dropCap: false, + style: { + typography: { + lineHeight: '1.1', + fontSize: '30px', + }, + color: { + text: '#000000', + }, + }, + }, + innerBlocks: [], + originalContent: + '<p class="has-text-color" style="color:#000000;font-size:30px;line-height:1.1"><strong>Oceanic Inspiration</strong></p>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-column" style="flex-basis:50%"></div>', + validationIssues: [], + }, + { + clientId: + '82b7e2aa-dcd8-4b34-a2a9-d239192fed71', + name: 'core/column', + isValid: true, + attributes: { + width: '50%', + }, + innerBlocks: [ + { + clientId: + 'b0fbba51-f3ec-40d5-91d6-64a24ae223f4', + name: 'core/separator', + isValid: true, + attributes: { + className: 'is-style-wide', + opacity: 'css', + style: { + color: { + background: '#000000', + }, + }, + }, + innerBlocks: [], + originalContent: + '<hr class="wp-block-separator has-text-color has-background is-style-wide" style="background-color:#000000;color:#000000" />', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-column" style="flex-basis:50%"></div>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-columns alignwide are-vertically-aligned-center">\n\n</div>', + validationIssues: [], + }, + { + clientId: '72d3dc7f-bbbe-4088-b556-a32c07191068', + name: 'core/columns', + isValid: true, + attributes: { + isStackedOnMobile: true, + align: 'wide', + }, + innerBlocks: [ + { + clientId: + 'cf3abb5c-eee8-4314-af70-022b4f7e5bc4', + name: 'core/column', + isValid: true, + attributes: {}, + innerBlocks: [], + originalContent: + '<div class="wp-block-column"></div>', + validationIssues: [], + }, + { + clientId: + '6978a278-bcf8-4244-9e99-bf5b56fe0f5e', + name: 'core/column', + isValid: true, + attributes: {}, + innerBlocks: [ + { + clientId: + '26a6b210-07b6-49b1-8c0b-41d0760562a5', + name: 'core/paragraph', + isValid: true, + attributes: { + content: + 'Winding veils round their heads, the women walked on deck. They were now moving steadily down the river, passing the dark shapes of ships at anchor, and London was a swarm of lights with a pale yellow canopy drooping above it. There were the lights of the great theatres, the lights of the long streets, lights that indicated huge squares of domestic comfort, lights that hung high in air.', + dropCap: false, + style: { + color: { + text: '#000000', + }, + }, + fontSize: 'extra-small', + }, + innerBlocks: [], + originalContent: + '<p class="has-text-color has-extra-small-font-size" style="color:#000000">Winding veils round their heads, the women walked on deck. They were now moving steadily down the river, passing the dark shapes of ships at anchor, and London was a swarm of lights with a pale yellow canopy drooping above it. There were the lights of the great theatres, the lights of the long streets, lights that indicated huge squares of domestic comfort, lights that hung high in air.</p>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-column"></div>', + validationIssues: [], + }, + { + clientId: + '53ac5018-2b60-429e-b893-fce01f8bad24', + name: 'core/column', + isValid: true, + attributes: {}, + innerBlocks: [ + { + clientId: + '10a12c7d-77b5-46c7-8215-ff2f94ed4e27', + name: 'core/paragraph', + isValid: true, + attributes: { + content: + 'No darkness would ever settle upon those lamps, as no darkness had settled upon them for hundreds of years. It seemed dreadful that the town should blaze for ever in the same spot; dreadful at least to people going away to adventure upon the sea, and beholding it as a circumscribed mound, eternally burnt, eternally scarred. From the deck of the ship the great city appeared a crouched and cowardly figure, a sedentary miser.', + dropCap: false, + style: { + color: { + text: '#000000', + }, + }, + fontSize: 'extra-small', + }, + innerBlocks: [], + originalContent: + '<p class="has-text-color has-extra-small-font-size" style="color:#000000">No darkness would ever settle upon those lamps, as no darkness had settled upon them for hundreds of years. It seemed dreadful that the town should blaze for ever in the same spot; dreadful at least to people going away to adventure upon the sea, and beholding it as a circumscribed mound, eternally burnt, eternally scarred. From the deck of the ship the great city appeared a crouched and cowardly figure, a sedentary miser.</p>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-column"></div>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-columns alignwide">\n\n\n\n</div>', + validationIssues: [], + }, + { + clientId: 'f401521c-d5d4-486a-b069-47350b032dc9', + name: 'core/spacer', + isValid: true, + attributes: { + height: '40px', + }, + innerBlocks: [], + originalContent: + '<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-group alignfull has-background" style="background-color:#f2f0e9">\n\n\n\n\n\n</div>', + validationIssues: [], + }, + ], + }, + { + name: 'test/4', + title: 'Offset text with a brutalist design vibe', + blocks: [ + { + clientId: 'ac947e62-0568-4fa2-85a0-927b86c8ae42', + name: 'core/cover', + isValid: true, + attributes: { + alt: '', + hasParallax: false, + isRepeated: false, + dimRatio: 100, + customOverlayColor: '#ffb43c', + backgroundType: 'image', + minHeight: 66, + minHeightUnit: 'vh', + isDark: false, + useFeaturedImage: false, + tagName: 'div', + align: 'full', + textColor: 'black', + style: { + spacing: { + padding: { + top: '48px', + right: '48px', + bottom: '48px', + left: '48px', + }, + margin: { + top: '0', + }, + }, + }, + isUserOverlayColor: true, + }, + innerBlocks: [ + { + clientId: 'a23ab6aa-b6dc-4148-a7fc-a4ad04deb738', + name: 'core/group', + isValid: true, + attributes: { + tagName: 'div', + style: { + spacing: { + blockGap: '0px', + }, + }, + layout: { + type: 'constrained', + wideSize: '1200px', + contentSize: '800px', + }, + }, + innerBlocks: [ + { + clientId: + '2cd000fa-8e5b-4edc-8238-5912c5e397d2', + name: 'core/paragraph', + isValid: true, + attributes: { + align: 'left', + content: + '<mark style="color:#a65a00" class="has-inline-color">✴︎</mark> Walk', + dropCap: false, + style: { + typography: { + fontSize: '148px', + textTransform: 'uppercase', + fontStyle: 'normal', + fontWeight: '700', + lineHeight: '0.9', + letterSpacing: '-2px', + }, + }, + textColor: 'black', + }, + innerBlocks: [], + originalContent: + '<p class="has-text-align-left has-black-color has-text-color" style="font-size:148px;font-style:normal;font-weight:700;letter-spacing:-2px;line-height:0.9;text-transform:uppercase"><mark style="color:#a65a00" class="has-inline-color">✴︎</mark> Walk</p>', + validationIssues: [], + }, + { + clientId: + '2d747e99-c672-4d7f-91d4-f8f03d295f2b', + name: 'core/paragraph', + isValid: true, + attributes: { + align: 'right', + content: 'In the', + dropCap: false, + style: { + typography: { + fontSize: '148px', + textTransform: 'uppercase', + fontStyle: 'normal', + fontWeight: '700', + lineHeight: '0.9', + letterSpacing: '-2px', + }, + }, + textColor: 'black', + }, + innerBlocks: [], + originalContent: + '<p class="has-text-align-right has-black-color has-text-color" style="font-size:148px;font-style:normal;font-weight:700;letter-spacing:-2px;line-height:0.9;text-transform:uppercase">In the</p>', + validationIssues: [], + }, + { + clientId: + 'd63e34e7-8943-49ff-bc05-8749809f4117', + name: 'core/paragraph', + isValid: true, + attributes: { + align: 'left', + content: 'Park', + dropCap: false, + style: { + typography: { + fontSize: '148px', + textTransform: 'uppercase', + fontStyle: 'normal', + fontWeight: '700', + lineHeight: '0.9', + letterSpacing: '-2px', + }, + }, + textColor: 'black', + }, + innerBlocks: [], + originalContent: + '<p class="has-text-align-left has-black-color has-text-color" style="font-size:148px;font-style:normal;font-weight:700;letter-spacing:-2px;line-height:0.9;text-transform:uppercase">Park</p>', + validationIssues: [], + }, + { + clientId: + 'e996575b-4ada-43b1-8ae1-a6dbb2ec0ecc', + name: 'core/paragraph', + isValid: true, + attributes: { + align: 'center', + content: '—01.03', + dropCap: false, + style: { + typography: { + fontSize: '140px', + textTransform: 'uppercase', + fontStyle: 'italic', + fontWeight: '200', + letterSpacing: '0px', + lineHeight: '0.9', + }, + color: { + text: '#a65a00', + }, + }, + }, + innerBlocks: [], + originalContent: + '<p class="has-text-align-center has-text-color" style="color:#a65a00;font-size:140px;font-style:italic;font-weight:200;letter-spacing:0px;line-height:0.9;text-transform:uppercase">—01.03</p>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-group">\n\n\n\n\n\n</div>', + validationIssues: [], + }, + ], + originalContent: + '<div class="wp-block-cover alignfull is-light has-black-color has-text-color" style="margin-top:0;padding-top:48px;padding-right:48px;padding-bottom:48px;padding-left:48px;min-height:66vh"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-100 has-background-dim" style="background-color:#ffb43c"></span><div class="wp-block-cover__inner-container"></div></div>', + validationIssues: [], + }, + ], + }, +]; diff --git a/packages/block-editor/src/components/block-patterns-list/stories/index.story.js b/packages/block-editor/src/components/block-patterns-list/stories/index.story.js new file mode 100644 index 00000000000000..9eb393ea13e762 --- /dev/null +++ b/packages/block-editor/src/components/block-patterns-list/stories/index.story.js @@ -0,0 +1,81 @@ +/** + * External dependencies + */ +import blockLibraryStyles from '!!raw-loader!../../../../../block-library/build-style/style.css'; + +/** + * WordPress dependencies + */ +import { useAsyncList } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import BlockPatternsList from '../'; +import { ExperimentalBlockEditorProvider } from '../../provider'; +import patterns from './fixtures'; + +const blockEditorSettings = { + styles: [ { css: blockLibraryStyles } ], +}; + +export default { + component: BlockPatternsList, + title: 'BlockEditor/BlockPatternsList', +}; + +export const Default = { + render: function Template( props ) { + const shownPatterns = useAsyncList( props.blockPatterns ); + return ( + <ExperimentalBlockEditorProvider settings={ blockEditorSettings }> + <BlockPatternsList + shownPatterns={ shownPatterns } + { ...props } + /> + </ExperimentalBlockEditorProvider> + ); + }, + args: { + blockPatterns: patterns, + isDraggable: false, + label: 'Block patterns story', + showTitle: true, + showTitlesAsTooltip: false, + }, + argTypes: { + blockPatterns: { description: 'The patterns to render.' }, + shownPatterns: { + description: + 'Usually this component is used with `useAsyncList` for performance reasons and you should provide the returned list from that hook. Alternatively it should have the same value with `blockPatterns`.', + }, + showTitle: { + description: 'Whether to render the title of each pattern.', + table: { + defaultValue: { summary: true }, + type: { summary: 'boolean' }, + }, + }, + onClickPattern: { type: 'function' }, + onHover: { type: 'function' }, + showTitlesAsTooltip: { + description: + 'Whether to render the title of each pattern as a tooltip. If enabled, it takes precedence over `showTitle` prop.', + }, + orientation: { + description: 'Orientation for the underlying composite widget.', + table: { + defaultValue: { summary: 'both' }, + type: { summary: 'string' }, + }, + }, + category: { description: 'The currently selected pattern category.' }, + isDraggable: { + description: 'Whether the pattern list item should be draggable.', + }, + }, + parameters: { + actions: { argTypesRegex: '^on.*' }, + controls: { expanded: true }, + }, +}; diff --git a/packages/block-editor/src/components/block-patterns-list/style.scss b/packages/block-editor/src/components/block-patterns-list/style.scss index 84e95563737c3c..c46bb49b9a9016 100644 --- a/packages/block-editor/src/components/block-patterns-list/style.scss +++ b/packages/block-editor/src/components/block-patterns-list/style.scss @@ -26,6 +26,8 @@ // the bottom margin set on `...__list-item` above scroll-margin-bottom: ($grid-unit-40 + $grid-unit-30); + outline: 0; + .block-editor-block-patterns-list__item-title { flex-grow: 1; font-size: $helptext-font-size; From 0b76a258213bde016726e16949d76fed12c5a34d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 22 Oct 2024 11:40:45 +0200 Subject: [PATCH 1279/1908] Site editor routes: add docs for areas and prevent `edit` area from rendering when canvas is `edit` (#66309) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../edit-site/src/components/layout/index.js | 22 ++++++++++--------- .../components/site-editor-routes/README.md | 20 +++++++++++++++++ 2 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 packages/edit-site/src/components/site-editor-routes/README.md diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index d02f2905f24d85..8c150039c6df81 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -183,16 +183,18 @@ export default function Layout( { route } ) { </div> ) } - { ! isMobileViewport && areas.edit && ( - <div - className="edit-site-layout__area" - style={ { - maxWidth: widths?.edit, - } } - > - { areas.edit } - </div> - ) } + { ! isMobileViewport && + areas.edit && + canvasMode !== 'edit' && ( + <div + className="edit-site-layout__area" + style={ { + maxWidth: widths?.edit, + } } + > + { areas.edit } + </div> + ) } { ! isMobileViewport && areas.preview && ( <div className="edit-site-layout__canvas-container"> diff --git a/packages/edit-site/src/components/site-editor-routes/README.md b/packages/edit-site/src/components/site-editor-routes/README.md new file mode 100644 index 00000000000000..64121c8bd9a6b5 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/README.md @@ -0,0 +1,20 @@ +# Site Editor Routes + +## Areas + +When `canvasMode` is not `edit`, the areas avaliable to use are: + +| Area | Non-mobile viewport | Mobile viewport | +| --- | --- | --- | +| `sidebar` | Always rendered. | Only if `mobile` is not provided. | +| `content` | Rendered if provided. | Not rendered. | +| `preview` | Rendered if provided. | Not rendered. | +| `edit` | Rendered if provided. | Not rendered. | +| `mobile` | Not rendered | Rendered as full-screen, if provided. | + +When `canvasMode` is `edit`, the areas avaliable to use are: + +| Area | Non-mobile viewport | Mobile viewport | +| --- | --- | --- | +| `preview` | Rendered as full-screen, if provided. Otherwise, it'll display an empty blank sidebar. | Not rendered. | +| `mobile` | Not rendered | Rendered as full-screen, if provided. Otherwise, it'll display an empty blank sidebar. | From 58362df3d20b4ad3b2c7c9e7eae7e7999702c85f Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 22 Oct 2024 11:39:11 +0100 Subject: [PATCH 1280/1908] Site Editor: Remove synchronization of canvas mode into store (#66213) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../block-editor/use-editor-iframe-props.js | 40 +++---- .../block-editor/use-site-editor-settings.js | 19 ++-- .../edit-site/src/components/editor/index.js | 41 ++++--- .../editor/use-adapt-editor-to-canvas.js | 53 ++++++++++ .../components/global-styles-sidebar/index.js | 81 +++++++------- .../components/keyboard-shortcuts/global.js | 8 +- .../edit-site/src/components/layout/index.js | 39 +++---- .../src/components/resizable-frame/index.js | 29 +++-- .../src/components/save-panel/index.js | 60 +++++------ .../index.js | 76 ++++++++----- .../use-sync-canvas-mode-with-url.js | 73 ------------- .../src/hooks/commands/use-common-commands.js | 100 +++++++++++------- .../hooks/commands/use-edit-mode-commands.js | 32 +++--- .../hooks/commands/use-set-command-context.js | 16 ++- .../edit-site/src/store/private-actions.js | 79 -------------- .../edit-site/src/store/private-selectors.js | 11 -- packages/edit-site/src/store/reducer.js | 18 ---- packages/router/src/history.ts | 36 ++++++- 18 files changed, 387 insertions(+), 424 deletions(-) create mode 100644 packages/edit-site/src/components/editor/use-adapt-editor-to-canvas.js delete mode 100644 packages/edit-site/src/components/sync-state-with-url/use-sync-canvas-mode-with-url.js diff --git a/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js b/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js index 3b5c9f7fe65726..46719a00c16aad 100644 --- a/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js +++ b/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js @@ -6,37 +6,37 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { useSelect, useDispatch } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; import { ENTER, SPACE } from '@wordpress/keycodes'; import { useState, useEffect } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { store as editorStore } from '@wordpress/editor'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies */ import { unlock } from '../../lock-unlock'; -import { store as editSiteStore } from '../../store'; -export default function useEditorIframeProps() { - const { canvasMode, currentPostIsTrashed } = useSelect( ( select ) => { - const { getCanvasMode } = unlock( select( editSiteStore ) ); +const { useLocation, useHistory } = unlock( routerPrivateApis ); - return { - canvasMode: getCanvasMode(), - currentPostIsTrashed: - select( editorStore ).getCurrentPostAttribute( 'status' ) === - 'trash', - }; +export default function useEditorIframeProps() { + const { params } = useLocation(); + const history = useHistory(); + const { canvas = 'view' } = params; + const currentPostIsTrashed = useSelect( ( select ) => { + return ( + select( editorStore ).getCurrentPostAttribute( 'status' ) === + 'trash' + ); }, [] ); - const { setCanvasMode } = unlock( useDispatch( editSiteStore ) ); const [ isFocused, setIsFocused ] = useState( false ); useEffect( () => { - if ( canvasMode === 'edit' ) { + if ( canvas === 'edit' ) { setIsFocused( false ); } - }, [ canvasMode ] ); + }, [ canvas ] ); // In view mode, make the canvas iframe be perceived and behave as a button // to switch to edit mode, with a meaningful label and no title attribute. @@ -55,11 +55,15 @@ export default function useEditorIframeProps() { ! currentPostIsTrashed ) { event.preventDefault(); - setCanvasMode( 'edit' ); + history.push( { ...params, canvas: 'edit' }, undefined, { + transition: 'canvas-mode-edit-transition', + } ); } }, onClick: () => { - setCanvasMode( 'edit' ); + history.push( { ...params, canvas: 'edit' }, undefined, { + transition: 'canvas-mode-edit-transition', + } ); }, onClickCapture: ( event ) => { if ( currentPostIsTrashed ) { @@ -72,8 +76,8 @@ export default function useEditorIframeProps() { return { className: clsx( 'edit-site-visual-editor__editor-canvas', { - 'is-focused': isFocused && canvasMode === 'view', + 'is-focused': isFocused && canvas === 'view', } ), - ...( canvasMode === 'view' ? viewModeIframeProps : {} ), + ...( canvas === 'view' ? viewModeIframeProps : {} ), }; } diff --git a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js index e4d70402efa8be..dcdfb157b235b6 100644 --- a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js +++ b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js @@ -38,22 +38,25 @@ function useNavigateToPreviousEntityRecord() { } export function useSpecificEditorSettings() { + const { params } = useLocation(); + const { canvas = 'view' } = params; const onNavigateToEntityRecord = useNavigateToEntityRecord(); - const { canvasMode, settings, shouldUseTemplateAsDefaultRenderingMode } = - useSelect( ( select ) => { - const { getEditedPostContext, getCanvasMode, getSettings } = unlock( + const { settings, shouldUseTemplateAsDefaultRenderingMode } = useSelect( + ( select ) => { + const { getEditedPostContext, getSettings } = unlock( select( editSiteStore ) ); const _context = getEditedPostContext(); return { - canvasMode: getCanvasMode(), settings: getSettings(), // TODO: The `postType` check should be removed when the default rendering mode per post type is merged. // @see https://github.com/WordPress/gutenberg/pull/62304/ shouldUseTemplateAsDefaultRenderingMode: _context?.postId && _context?.postType !== 'post', }; - }, [] ); + }, + [] + ); const defaultRenderingMode = shouldUseTemplateAsDefaultRenderingMode ? 'template-locked' : 'post-only'; @@ -65,15 +68,15 @@ export function useSpecificEditorSettings() { richEditingEnabled: true, supportsTemplateMode: true, - focusMode: canvasMode !== 'view', + focusMode: canvas !== 'view', defaultRenderingMode, onNavigateToEntityRecord, onNavigateToPreviousEntityRecord, - __unstableIsPreviewMode: canvasMode === 'view', + __unstableIsPreviewMode: canvas === 'view', }; }, [ settings, - canvasMode, + canvas, defaultRenderingMode, onNavigateToEntityRecord, onNavigateToPreviousEntityRecord, diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index c2a7730c0fee56..9058a163707997 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -48,6 +48,7 @@ import SiteIcon from '../site-icon'; import useEditorIframeProps from '../block-editor/use-editor-iframe-props'; import useEditorTitle from './use-editor-title'; import { useIsSiteEditorLoading } from '../layout/hooks'; +import { useAdaptEditorToCanvas } from './use-adapt-editor-to-canvas'; const { Editor, BackButton } = unlock( editorPrivateApis ); const { useHistory, useLocation } = unlock( routerPrivateApis ); @@ -80,13 +81,14 @@ const siteIconVariants = { export default function EditSiteEditor( { isPostsList = false } ) { const disableMotion = useReducedMotion(); const { params } = useLocation(); + const { canvas = 'view' } = params; const isLoading = useIsSiteEditorLoading(); + useAdaptEditorToCanvas( canvas ); const { editedPostType, editedPostId, contextPostType, contextPostId, - canvasMode, isEditingPage, supportsGlobalStyles, showIconLabels, @@ -97,7 +99,6 @@ export default function EditSiteEditor( { isPostsList = false } ) { const { getEditorCanvasContainerView, getEditedPostContext, - getCanvasMode, isPage, getEditedPostType, getEditedPostId, @@ -114,7 +115,6 @@ export default function EditSiteEditor( { isPostsList = false } ) { editedPostId: getEditedPostId(), contextPostType: _context?.postId ? _context.postType : undefined, contextPostId: _context?.postId ? _context.postId : undefined, - canvasMode: getCanvasMode(), isEditingPage: isPage(), supportsGlobalStyles: getCurrentTheme()?.is_block_theme, showIconLabels: get( 'core', 'showIconLabels' ), @@ -129,7 +129,7 @@ export default function EditSiteEditor( { isPostsList = false } ) { const _isPreviewingTheme = isPreviewingTheme(); const hasDefaultEditorCanvasView = ! useHasEditorCanvasContainer(); const iframeProps = useEditorIframeProps(); - const isEditMode = canvasMode === 'edit'; + const isEditMode = canvas === 'edit'; const postWithTemplate = !! contextPostId; const loadingProgressId = useInstanceId( CanvasLoader, @@ -144,16 +144,15 @@ export default function EditSiteEditor( { isPostsList = false } ) { // Forming a "block formatting context" to prevent margin collapsing. // @see https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context css: - canvasMode === 'view' + canvas === 'view' ? `body{min-height: 100vh; ${ currentPostIsTrashed ? '' : 'cursor: pointer;' }}` : undefined, }, ], - [ settings.styles, canvasMode, currentPostIsTrashed ] + [ settings.styles, canvas, currentPostIsTrashed ] ); - const { setCanvasMode } = unlock( useDispatch( editSiteStore ) ); const { __unstableSetEditorMode, resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); @@ -264,7 +263,6 @@ export default function EditSiteEditor( { isPostsList = false } ) { showTooltip tooltipPosition="middle right" onClick={ () => { - setCanvasMode( 'view' ); __unstableSetEditorMode( 'edit' ); @@ -276,10 +274,29 @@ export default function EditSiteEditor( { isPostsList = false } ) { isPostsList && params?.focusMode ) { - history.push( { - page: 'gutenberg-posts-dashboard', - postType: 'post', - } ); + history.push( + { + page: 'gutenberg-posts-dashboard', + postType: 'post', + }, + undefined, + { + transition: + 'canvas-mode-view-transition', + } + ); + } else { + history.push( + { + ...params, + canvas: undefined, + }, + undefined, + { + transition: + 'canvas-mode-view-transition', + } + ); } } } > diff --git a/packages/edit-site/src/components/editor/use-adapt-editor-to-canvas.js b/packages/edit-site/src/components/editor/use-adapt-editor-to-canvas.js new file mode 100644 index 00000000000000..a09adfb7a49d53 --- /dev/null +++ b/packages/edit-site/src/components/editor/use-adapt-editor-to-canvas.js @@ -0,0 +1,53 @@ +/** + * WordPress dependencies + */ +import { useDispatch, useSelect, useRegistry } from '@wordpress/data'; +import { store as blockEditorStore } from '@wordpress/block-editor'; +import { store as editorStore } from '@wordpress/editor'; +import { useLayoutEffect } from '@wordpress/element'; +import { store as preferencesStore } from '@wordpress/preferences'; + +export function useAdaptEditorToCanvas( canvas ) { + const { clearSelectedBlock } = useDispatch( blockEditorStore ); + const { + setDeviceType, + closePublishSidebar, + setIsListViewOpened, + setIsInserterOpened, + } = useDispatch( editorStore ); + const { get: getPreference } = useSelect( preferencesStore ); + const registry = useRegistry(); + useLayoutEffect( () => { + const isMediumOrBigger = + window.matchMedia( '(min-width: 782px)' ).matches; + registry.batch( () => { + clearSelectedBlock(); + setDeviceType( 'Desktop' ); + closePublishSidebar(); + setIsInserterOpened( false ); + + // Check if the block list view should be open by default. + // If `distractionFree` mode is enabled, the block list view should not be open. + // This behavior is disabled for small viewports. + if ( + isMediumOrBigger && + canvas === 'edit' && + getPreference( 'core', 'showListViewByDefault' ) && + ! getPreference( 'core', 'distractionFree' ) + ) { + setIsListViewOpened( true ); + } else { + setIsListViewOpened( false ); + } + } ); + }, [ + canvas, + registry, + clearSelectedBlock, + setDeviceType, + closePublishSidebar, + setIsInserterOpened, + setIsListViewOpened, + getPreference, + ] ); +} diff --git a/packages/edit-site/src/components/global-styles-sidebar/index.js b/packages/edit-site/src/components/global-styles-sidebar/index.js index 2194f2edbc0f29..2b9a2669a96fe6 100644 --- a/packages/edit-site/src/components/global-styles-sidebar/index.js +++ b/packages/edit-site/src/components/global-styles-sidebar/index.js @@ -11,6 +11,7 @@ import { store as editorStore, privateApis as editorPrivateApis, } from '@wordpress/editor'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies @@ -23,8 +24,11 @@ import { store as coreStore } from '@wordpress/core-data'; import DefaultSidebar from './default-sidebar'; const { interfaceStore } = unlock( editorPrivateApis ); +const { useLocation } = unlock( routerPrivateApis ); export default function GlobalStylesSidebar() { + const { params } = useLocation(); + const { canvas = 'view' } = params; const { shouldClearCanvasContainerView, isStyleBookOpened, @@ -32,43 +36,48 @@ export default function GlobalStylesSidebar() { hasRevisions, isRevisionsOpened, isRevisionsStyleBookOpened, - } = useSelect( ( select ) => { - const { getActiveComplementaryArea } = select( interfaceStore ); - const { getEditorCanvasContainerView, getCanvasMode } = unlock( - select( editSiteStore ) - ); - const canvasContainerView = getEditorCanvasContainerView(); - const _isVisualEditorMode = - 'visual' === select( editorStore ).getEditorMode(); - const _isEditCanvasMode = 'edit' === getCanvasMode(); - const _showListViewByDefault = select( preferencesStore ).get( - 'core', - 'showListViewByDefault' - ); - const { getEntityRecord, __experimentalGetCurrentGlobalStylesId } = - select( coreStore ); + } = useSelect( + ( select ) => { + const { getActiveComplementaryArea } = select( interfaceStore ); + const { getEditorCanvasContainerView } = unlock( + select( editSiteStore ) + ); + const canvasContainerView = getEditorCanvasContainerView(); + const _isVisualEditorMode = + 'visual' === select( editorStore ).getEditorMode(); + const _isEditCanvasMode = 'edit' === canvas; + const _showListViewByDefault = select( preferencesStore ).get( + 'core', + 'showListViewByDefault' + ); + const { getEntityRecord, __experimentalGetCurrentGlobalStylesId } = + select( coreStore ); - const globalStylesId = __experimentalGetCurrentGlobalStylesId(); - const globalStyles = globalStylesId - ? getEntityRecord( 'root', 'globalStyles', globalStylesId ) - : undefined; + const globalStylesId = __experimentalGetCurrentGlobalStylesId(); + const globalStyles = globalStylesId + ? getEntityRecord( 'root', 'globalStyles', globalStylesId ) + : undefined; - return { - isStyleBookOpened: 'style-book' === canvasContainerView, - shouldClearCanvasContainerView: - 'edit-site/global-styles' !== - getActiveComplementaryArea( 'core' ) || - ! _isVisualEditorMode || - ! _isEditCanvasMode, - showListViewByDefault: _showListViewByDefault, - hasRevisions: - !! globalStyles?._links?.[ 'version-history' ]?.[ 0 ]?.count, - isRevisionsStyleBookOpened: - 'global-styles-revisions:style-book' === canvasContainerView, - isRevisionsOpened: - 'global-styles-revisions' === canvasContainerView, - }; - }, [] ); + return { + isStyleBookOpened: 'style-book' === canvasContainerView, + shouldClearCanvasContainerView: + 'edit-site/global-styles' !== + getActiveComplementaryArea( 'core' ) || + ! _isVisualEditorMode || + ! _isEditCanvasMode, + showListViewByDefault: _showListViewByDefault, + hasRevisions: + !! globalStyles?._links?.[ 'version-history' ]?.[ 0 ] + ?.count, + isRevisionsStyleBookOpened: + 'global-styles-revisions:style-book' === + canvasContainerView, + isRevisionsOpened: + 'global-styles-revisions' === canvasContainerView, + }; + }, + [ canvas ] + ); const { setEditorCanvasContainerView } = unlock( useDispatch( editSiteStore ) ); @@ -77,7 +86,7 @@ export default function GlobalStylesSidebar() { if ( shouldClearCanvasContainerView ) { setEditorCanvasContainerView( undefined ); } - }, [ shouldClearCanvasContainerView ] ); + }, [ shouldClearCanvasContainerView, setEditorCanvasContainerView ] ); const { setIsListViewOpened } = useDispatch( editorStore ); diff --git a/packages/edit-site/src/components/keyboard-shortcuts/global.js b/packages/edit-site/src/components/keyboard-shortcuts/global.js index 2e71cf88202069..8ab9723e42ea65 100644 --- a/packages/edit-site/src/components/keyboard-shortcuts/global.js +++ b/packages/edit-site/src/components/keyboard-shortcuts/global.js @@ -5,6 +5,7 @@ import { useShortcut } from '@wordpress/keyboard-shortcuts'; import { useDispatch, useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { store as editorStore } from '@wordpress/editor'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies @@ -12,12 +13,14 @@ import { store as editorStore } from '@wordpress/editor'; import { store as editSiteStore } from '../../store'; import { unlock } from '../../lock-unlock'; +const { useHistory } = unlock( routerPrivateApis ); + function KeyboardShortcutsGlobal() { const { __experimentalGetDirtyEntityRecords, isSavingEntityRecord } = useSelect( coreStore ); const { hasNonPostEntityChanges } = useSelect( editorStore ); - const { getCanvasMode } = unlock( useSelect( editSiteStore ) ); const { setIsSaveViewOpened } = useDispatch( editSiteStore ); + const history = useHistory(); useShortcut( 'core/edit-site/save', ( event ) => { event.preventDefault(); @@ -28,7 +31,8 @@ function KeyboardShortcutsGlobal() { isSavingEntityRecord( record.kind, record.name, record.key ) ); const _hasNonPostEntityChanges = hasNonPostEntityChanges(); - const isViewMode = getCanvasMode() === 'view'; + const isViewMode = + history.getLocationWithParams().params.canvas === 'view'; if ( ( ! hasDirtyEntities || ! _hasNonPostEntityChanges || isSaving ) && ! isViewMode diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index 8c150039c6df81..3b9769d470f518 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -6,7 +6,6 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { useSelect } from '@wordpress/data'; import { __unstableMotion as motion, __unstableAnimatePresence as AnimatePresence, @@ -27,12 +26,12 @@ import { privateApis as editorPrivateApis, } from '@wordpress/editor'; import { privateApis as coreCommandsPrivateApis } from '@wordpress/core-commands'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies */ import ErrorBoundary from '../error-boundary'; -import { store as editSiteStore } from '../../store'; import { default as SiteHub, SiteHubMobile } from '../site-hub'; import ResizableFrame from '../resizable-frame'; import { unlock } from '../../lock-unlock'; @@ -43,25 +42,20 @@ import useMovingAnimation from './animation'; import SidebarContent from '../sidebar'; import SaveHub from '../save-hub'; import SavePanel from '../save-panel'; -import useSyncCanvasModeWithURL from '../sync-state-with-url/use-sync-canvas-mode-with-url'; const { useCommands } = unlock( coreCommandsPrivateApis ); const { useGlobalStyle } = unlock( blockEditorPrivateApis ); const { NavigableRegion } = unlock( editorPrivateApis ); +const { useLocation } = unlock( routerPrivateApis ); const ANIMATION_DURATION = 0.3; export default function Layout( { route } ) { - useSyncCanvasModeWithURL(); + const { params } = useLocation(); + const { canvas = 'view' } = params; useCommands(); const isMobileViewport = useViewportMatch( 'medium', '<' ); const toggleRef = useRef(); - const { canvasMode } = useSelect( ( select ) => { - const { getCanvasMode } = unlock( select( editSiteStore ) ); - return { - canvasMode: getCanvasMode(), - }; - }, [] ); const navigateRegionsProps = useNavigateRegions(); const disableMotion = useReducedMotion(); const [ canvasResizer, canvasSize ] = useResizeObserver(); @@ -70,26 +64,19 @@ export default function Layout( { route } ) { useState( false ); const { name: routeKey, areas, widths } = route; const animationRef = useMovingAnimation( { - triggerAnimationOnChange: canvasMode, + triggerAnimationOnChange: routeKey + '-' + canvas, } ); const [ backgroundColor ] = useGlobalStyle( 'color.background' ); const [ gradientValue ] = useGlobalStyle( 'color.gradient' ); - const previousCanvaMode = usePrevious( canvasMode ); + const previousCanvaMode = usePrevious( canvas ); useEffect( () => { if ( previousCanvaMode === 'edit' ) { toggleRef.current?.focus(); } // Should not depend on the previous canvas mode value but the next. // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ canvasMode ] ); - - // Synchronizing the URL with the store value of canvasMode happens in an effect - // This condition ensures the component is only rendered after the synchronization happens - // which prevents any animations due to potential canvasMode value change. - if ( canvasMode === 'init' ) { - return null; - } + }, [ canvas ] ); return ( <> @@ -103,7 +90,7 @@ export default function Layout( { route } ) { 'edit-site-layout', navigateRegionsProps.className, { - 'is-full-canvas': canvasMode === 'edit', + 'is-full-canvas': canvas === 'edit', } ) } > @@ -118,7 +105,7 @@ export default function Layout( { route } ) { className="edit-site-layout__sidebar-region" > <AnimatePresence> - { canvasMode === 'view' && ( + { canvas === 'view' && ( <motion.div initial={ { opacity: 0 } } animate={ { opacity: 1 } } @@ -156,7 +143,7 @@ export default function Layout( { route } ) { { isMobileViewport && areas.mobile && ( <div className="edit-site-layout__mobile"> - { canvasMode !== 'edit' && ( + { canvas !== 'edit' && ( <SidebarContent routeKey={ routeKey }> <SiteHubMobile ref={ toggleRef } @@ -172,7 +159,7 @@ export default function Layout( { route } ) { { ! isMobileViewport && areas.content && - canvasMode !== 'edit' && ( + canvas !== 'edit' && ( <div className="edit-site-layout__area" style={ { @@ -213,9 +200,7 @@ export default function Layout( { route } ) { <ErrorBoundary> <ResizableFrame isReady={ ! isEditorLoading } - isFullWidth={ - canvasMode === 'edit' - } + isFullWidth={ canvas === 'edit' } defaultSize={ { width: canvasSize.width - diff --git a/packages/edit-site/src/components/resizable-frame/index.js b/packages/edit-site/src/components/resizable-frame/index.js index b5aae01918e691..95ccfe4fdd966f 100644 --- a/packages/edit-site/src/components/resizable-frame/index.js +++ b/packages/edit-site/src/components/resizable-frame/index.js @@ -13,14 +13,15 @@ import { __unstableMotion as motion, } from '@wordpress/components'; import { useInstanceId, useReducedMotion } from '@wordpress/compose'; -import { useDispatch, useSelect } from '@wordpress/data'; import { __, isRTL } from '@wordpress/i18n'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies */ import { unlock } from '../../lock-unlock'; -import { store as editSiteStore } from '../../store'; + +const { useLocation, useHistory } = unlock( routerPrivateApis ); // Removes the inline styles in the drag handles. const HANDLE_STYLES_OVERRIDE = { @@ -86,6 +87,9 @@ function ResizableFrame( { defaultSize, innerContentStyle, } ) { + const history = useHistory(); + const { params } = useLocation(); + const { canvas = 'view' } = params; const disableMotion = useReducedMotion(); const [ frameSize, setFrameSize ] = useState( INITIAL_FRAME_SIZE ); // The width of the resizable frame when a new resize gesture starts. @@ -93,11 +97,7 @@ function ResizableFrame( { const [ isResizing, setIsResizing ] = useState( false ); const [ shouldShowHandle, setShouldShowHandle ] = useState( false ); const [ resizeRatio, setResizeRatio ] = useState( 1 ); - const canvasMode = useSelect( - ( select ) => unlock( select( editSiteStore ) ).getCanvasMode(), - [] - ); - const { setCanvasMode } = unlock( useDispatch( editSiteStore ) ); + const FRAME_TRANSITION = { type: 'tween', duration: isResizing ? 0 : 0.5 }; const frameRef = useRef( null ); const resizableHandleHelpId = useInstanceId( @@ -158,7 +158,16 @@ function ResizableFrame( { setFrameSize( INITIAL_FRAME_SIZE ); } else { // Trigger full screen if the frame is resized far enough to the left. - setCanvasMode( 'edit' ); + history.push( + { + ...params, + canvas: 'edit', + }, + undefined, + { + transition: 'canvas-mode-edit-transition', + } + ); } }; @@ -237,7 +246,7 @@ function ResizableFrame( { } } } whileHover={ - canvasMode === 'view' + canvas === 'view' ? { scale: 1.005, transition: { @@ -275,7 +284,7 @@ function ResizableFrame( { onMouseOver={ () => setShouldShowHandle( true ) } onMouseOut={ () => setShouldShowHandle( false ) } handleComponent={ { - [ isRTL() ? 'right' : 'left' ]: canvasMode === 'view' && ( + [ isRTL() ? 'right' : 'left' ]: canvas === 'view' && ( <> <Tooltip text={ __( 'Drag to resize' ) }> { /* Disable reason: role="separator" does in fact support aria-valuenow */ } diff --git a/packages/edit-site/src/components/save-panel/index.js b/packages/edit-site/src/components/save-panel/index.js index 9b00a39fd78948..d7817d5b3c1bb2 100644 --- a/packages/edit-site/src/components/save-panel/index.js +++ b/packages/edit-site/src/components/save-panel/index.js @@ -15,6 +15,8 @@ import { import { useDispatch, useSelect } from '@wordpress/data'; import { __, sprintf } from '@wordpress/i18n'; import { store as coreStore } from '@wordpress/core-data'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { useEffect } from '@wordpress/element'; /** * Internal dependencies @@ -27,6 +29,7 @@ import { isPreviewingTheme } from '../../utils/is-previewing-theme'; const { EntitiesSavedStatesExtensible, NavigableRegion } = unlock( privateApis ); +const { useLocation } = unlock( routerPrivateApis ); const EntitiesSavedStatesForPreview = ( { onClose } ) => { const isDirtyProps = useEntitiesSavedStatesIsDirty(); @@ -87,41 +90,36 @@ const _EntitiesSavedStates = ( { onClose, renderDialog = undefined } ) => { }; export default function SavePanel() { - const { isSaveViewOpen, canvasMode, isDirty, isSaving } = useSelect( - ( select ) => { - const { - __experimentalGetDirtyEntityRecords, - isSavingEntityRecord, - isResolving, - } = select( coreStore ); - const dirtyEntityRecords = __experimentalGetDirtyEntityRecords(); - const isActivatingTheme = isResolving( 'activateTheme' ); - const { isSaveViewOpened, getCanvasMode } = unlock( - select( editSiteStore ) - ); + const { params } = useLocation(); + const { canvas = 'view' } = params; + const { isSaveViewOpen, isDirty, isSaving } = useSelect( ( select ) => { + const { + __experimentalGetDirtyEntityRecords, + isSavingEntityRecord, + isResolving, + } = select( coreStore ); + const dirtyEntityRecords = __experimentalGetDirtyEntityRecords(); + const isActivatingTheme = isResolving( 'activateTheme' ); + const { isSaveViewOpened } = unlock( select( editSiteStore ) ); - // The currently selected entity to display. - // Typically template or template part in the site editor. - return { - isSaveViewOpen: isSaveViewOpened(), - canvasMode: getCanvasMode(), - isDirty: dirtyEntityRecords.length > 0, - isSaving: - dirtyEntityRecords.some( ( record ) => - isSavingEntityRecord( - record.kind, - record.name, - record.key - ) - ) || isActivatingTheme, - }; - }, - [] - ); + // The currently selected entity to display. + // Typically template or template part in the site editor. + return { + isSaveViewOpen: isSaveViewOpened(), + isDirty: dirtyEntityRecords.length > 0, + isSaving: + dirtyEntityRecords.some( ( record ) => + isSavingEntityRecord( record.kind, record.name, record.key ) + ) || isActivatingTheme, + }; + }, [] ); const { setIsSaveViewOpened } = useDispatch( editSiteStore ); const onClose = () => setIsSaveViewOpened( false ); + useEffect( () => { + setIsSaveViewOpened( false ); + }, [ canvas, setIsSaveViewOpened ] ); - if ( canvasMode === 'view' ) { + if ( canvas === 'view' ) { return isSaveViewOpen ? ( <Modal className="edit-site-save-panel__modal" diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js index 76cdcc61fbfe9c..6579107a60e55f 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js @@ -9,6 +9,7 @@ import { useViewportMatch } from '@wordpress/compose'; import { useCallback } from '@wordpress/element'; import { store as editorStore } from '@wordpress/editor'; import { store as preferencesStore } from '@wordpress/preferences'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies @@ -23,10 +24,12 @@ import useGlobalStylesRevisions from '../global-styles/screen-revisions/use-glob import SidebarNavigationScreenDetailsFooter from '../sidebar-navigation-screen-details-footer'; import SidebarNavigationScreenGlobalStylesContent from './content'; +const { useLocation, useHistory } = unlock( routerPrivateApis ); + export function SidebarNavigationItemGlobalStyles( props ) { const { openGeneralSidebar } = useDispatch( editSiteStore ); - const { setCanvasMode } = unlock( useDispatch( editSiteStore ) ); - + const history = useHistory(); + const { params } = useLocation(); const hasGlobalStyleVariations = useSelect( ( select ) => !! select( @@ -48,7 +51,16 @@ export function SidebarNavigationItemGlobalStyles( props ) { { ...props } onClick={ () => { // Switch to edit mode. - setCanvasMode( 'edit' ); + history.push( + { + ...params, + canvas: 'edit', + }, + undefined, + { + transition: 'canvas-mode-edit-transition', + } + ); // Open global styles sidebar. openGeneralSidebar( 'edit-site/global-styles' ); } } @@ -57,45 +69,51 @@ export function SidebarNavigationItemGlobalStyles( props ) { } export default function SidebarNavigationScreenGlobalStyles( { backPath } ) { + const history = useHistory(); + const { params } = useLocation(); + const { canvas = 'view' } = params; const { revisions, isLoading: isLoadingRevisions } = useGlobalStylesRevisions(); const { openGeneralSidebar } = useDispatch( editSiteStore ); const { setIsListViewOpened } = useDispatch( editorStore ); const isMobileViewport = useViewportMatch( 'medium', '<' ); - const { setCanvasMode, setEditorCanvasContainerView } = unlock( + const { setEditorCanvasContainerView } = unlock( useDispatch( editSiteStore ) ); - const { isViewMode, isStyleBookOpened, revisionsCount } = useSelect( - ( select ) => { - const { getCanvasMode, getEditorCanvasContainerView } = unlock( - select( editSiteStore ) - ); - const { getEntityRecord, __experimentalGetCurrentGlobalStylesId } = - select( coreStore ); - const globalStylesId = __experimentalGetCurrentGlobalStylesId(); - const globalStyles = globalStylesId - ? getEntityRecord( 'root', 'globalStyles', globalStylesId ) - : undefined; - return { - isViewMode: 'view' === getCanvasMode(), - isStyleBookOpened: - 'style-book' === getEditorCanvasContainerView(), - revisionsCount: - globalStyles?._links?.[ 'version-history' ]?.[ 0 ]?.count ?? - 0, - }; - }, - [] - ); + const { isStyleBookOpened, revisionsCount } = useSelect( ( select ) => { + const { getEditorCanvasContainerView } = unlock( + select( editSiteStore ) + ); + const { getEntityRecord, __experimentalGetCurrentGlobalStylesId } = + select( coreStore ); + const globalStylesId = __experimentalGetCurrentGlobalStylesId(); + const globalStyles = globalStylesId + ? getEntityRecord( 'root', 'globalStyles', globalStylesId ) + : undefined; + return { + isStyleBookOpened: 'style-book' === getEditorCanvasContainerView(), + revisionsCount: + globalStyles?._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0, + }; + }, [] ); const { set: setPreference } = useDispatch( preferencesStore ); const openGlobalStyles = useCallback( async () => { + history.push( + { + ...params, + canvas: 'edit', + }, + undefined, + { + transition: 'canvas-mode-edit-transition', + } + ); return Promise.all( [ setPreference( 'core', 'distractionFree', false ), - setCanvasMode( 'edit' ), openGeneralSidebar( 'edit-site/global-styles' ), ] ); - }, [ setCanvasMode, openGeneralSidebar, setPreference ] ); + }, [ history, params, openGeneralSidebar, setPreference ] ); const openStyleBook = useCallback( async () => { await openGlobalStyles(); @@ -166,7 +184,7 @@ export default function SidebarNavigationScreenGlobalStyles( { backPath } ) { </> } /> - { isStyleBookOpened && ! isMobileViewport && isViewMode && ( + { isStyleBookOpened && ! isMobileViewport && canvas === 'view' && ( <StyleBook enableResizing={ false } isSelected={ () => false } diff --git a/packages/edit-site/src/components/sync-state-with-url/use-sync-canvas-mode-with-url.js b/packages/edit-site/src/components/sync-state-with-url/use-sync-canvas-mode-with-url.js deleted file mode 100644 index d9295f83ee2452..00000000000000 --- a/packages/edit-site/src/components/sync-state-with-url/use-sync-canvas-mode-with-url.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - * WordPress dependencies - */ -import { useEffect, useRef } from '@wordpress/element'; -import { useSelect, useDispatch } from '@wordpress/data'; -import { privateApis as routerPrivateApis } from '@wordpress/router'; - -/** - * Internal dependencies - */ -import { store as editSiteStore } from '../../store'; -import { unlock } from '../../lock-unlock'; - -const { useLocation, useHistory } = unlock( routerPrivateApis ); - -export default function useSyncCanvasModeWithURL() { - const history = useHistory(); - const { params } = useLocation(); - const canvasMode = useSelect( - ( select ) => unlock( select( editSiteStore ) ).getCanvasMode(), - [] - ); - const { setCanvasMode } = unlock( useDispatch( editSiteStore ) ); - const currentCanvasModeRef = useRef( canvasMode ); - const { canvas: canvasInUrl } = params; - const currentCanvasInUrlRef = useRef( canvasInUrl ); - const currentUrlParamsRef = useRef( params ); - useEffect( () => { - currentUrlParamsRef.current = params; - }, [ params ] ); - - useEffect( () => { - currentCanvasModeRef.current = canvasMode; - if ( canvasMode === 'init' ) { - return; - } - - if ( - canvasMode === 'edit' && - currentCanvasInUrlRef.current !== canvasMode - ) { - history.push( { - ...currentUrlParamsRef.current, - canvas: 'edit', - } ); - } - - if ( - canvasMode === 'view' && - currentCanvasInUrlRef.current !== undefined - ) { - history.push( { - ...currentUrlParamsRef.current, - canvas: undefined, - } ); - } - }, [ canvasMode, history ] ); - - useEffect( () => { - currentCanvasInUrlRef.current = canvasInUrl; - if ( - canvasInUrl !== 'edit' && - currentCanvasModeRef.current !== 'view' - ) { - setCanvasMode( 'view' ); - } else if ( - canvasInUrl === 'edit' && - currentCanvasModeRef.current !== 'edit' - ) { - setCanvasMode( 'edit' ); - } - }, [ canvasInUrl, setCanvasMode ] ); -} diff --git a/packages/edit-site/src/hooks/commands/use-common-commands.js b/packages/edit-site/src/hooks/commands/use-common-commands.js index ca6e2d1c6b45dd..536817e88d3a47 100644 --- a/packages/edit-site/src/hooks/commands/use-common-commands.js +++ b/packages/edit-site/src/hooks/commands/use-common-commands.js @@ -29,13 +29,10 @@ const { useGlobalStylesReset } = unlock( blockEditorPrivateApis ); const { useHistory, useLocation } = unlock( routerPrivateApis ); function useGlobalStylesOpenStylesCommands() { - const { openGeneralSidebar, setCanvasMode } = unlock( - useDispatch( editSiteStore ) - ); + const { openGeneralSidebar } = unlock( useDispatch( editSiteStore ) ); const { params } = useLocation(); - const { getCanvasMode } = unlock( useSelect( editSiteStore ) ); + const { canvas = 'view' } = params; const history = useHistory(); - const isBlockBasedTheme = useSelect( ( select ) => { return select( coreStore ).getCurrentTheme().is_block_theme; }, [] ); @@ -57,22 +54,21 @@ function useGlobalStylesOpenStylesCommands() { canvas: 'edit', } ); } - if ( params.postId && getCanvasMode() !== 'edit' ) { - setCanvasMode( 'edit' ); + if ( params.postId && canvas !== 'edit' ) { + history.push( + { ...params, canvas: 'edit' }, + undefined, + { + transition: 'canvas-mode-edit-transition', + } + ); } openGeneralSidebar( 'edit-site/global-styles' ); }, icon: styles, }, ]; - }, [ - history, - openGeneralSidebar, - setCanvasMode, - getCanvasMode, - isBlockBasedTheme, - params.postId, - ] ); + }, [ history, openGeneralSidebar, params, canvas, isBlockBasedTheme ] ); return { isLoading: false, @@ -81,11 +77,9 @@ function useGlobalStylesOpenStylesCommands() { } function useGlobalStylesToggleWelcomeGuideCommands() { - const { openGeneralSidebar, setCanvasMode } = unlock( - useDispatch( editSiteStore ) - ); + const { openGeneralSidebar } = unlock( useDispatch( editSiteStore ) ); const { params } = useLocation(); - const { getCanvasMode } = unlock( useSelect( editSiteStore ) ); + const { canvas = 'view' } = params; const { set } = useDispatch( preferencesStore ); const history = useHistory(); @@ -110,8 +104,17 @@ function useGlobalStylesToggleWelcomeGuideCommands() { canvas: 'edit', } ); } - if ( params.postId && getCanvasMode() !== 'edit' ) { - setCanvasMode( 'edit' ); + if ( params.postId && canvas !== 'edit' ) { + history.push( + { + ...params, + canvas: 'edit', + }, + undefined, + { + transition: 'canvas-mode-edit-transition', + } + ); } openGeneralSidebar( 'edit-site/global-styles' ); set( 'core/edit-site', 'welcomeGuideStyles', true ); @@ -127,11 +130,10 @@ function useGlobalStylesToggleWelcomeGuideCommands() { }, [ history, openGeneralSidebar, - setCanvasMode, - getCanvasMode, + canvas, isBlockBasedTheme, set, - params.postId, + params, ] ); return { @@ -167,9 +169,11 @@ function useGlobalStylesResetCommands() { } function useGlobalStylesOpenCssCommands() { - const { openGeneralSidebar, setEditorCanvasContainerView, setCanvasMode } = - unlock( useDispatch( editSiteStore ) ); + const { openGeneralSidebar, setEditorCanvasContainerView } = unlock( + useDispatch( editSiteStore ) + ); const { params } = useLocation(); + const { canvas = 'view' } = params; const history = useHistory(); const { canEditCSS } = useSelect( ( select ) => { const { getEntityRecord, __experimentalGetCurrentGlobalStylesId } = @@ -184,7 +188,6 @@ function useGlobalStylesOpenCssCommands() { canEditCSS: !! globalStyles?._links?.[ 'wp:action-edit-css' ], }; }, [] ); - const { getCanvasMode } = unlock( useSelect( editSiteStore ) ); const commands = useMemo( () => { if ( ! canEditCSS ) { @@ -204,8 +207,17 @@ function useGlobalStylesOpenCssCommands() { canvas: 'edit', } ); } - if ( params.postId && getCanvasMode() !== 'edit' ) { - setCanvasMode( 'edit' ); + if ( params.postId && canvas !== 'edit' ) { + history.push( + { + ...params, + canvas: 'edit', + }, + undefined, + { + transition: 'canvas-mode-edit-transition', + } + ); } openGeneralSidebar( 'edit-site/global-styles' ); setEditorCanvasContainerView( 'global-styles-css' ); @@ -217,9 +229,8 @@ function useGlobalStylesOpenCssCommands() { openGeneralSidebar, setEditorCanvasContainerView, canEditCSS, - getCanvasMode, - setCanvasMode, - params.postId, + canvas, + params, ] ); return { isLoading: false, @@ -228,10 +239,11 @@ function useGlobalStylesOpenCssCommands() { } function useGlobalStylesOpenRevisionsCommands() { - const { openGeneralSidebar, setEditorCanvasContainerView, setCanvasMode } = - unlock( useDispatch( editSiteStore ) ); - const { getCanvasMode } = unlock( useSelect( editSiteStore ) ); + const { openGeneralSidebar, setEditorCanvasContainerView } = unlock( + useDispatch( editSiteStore ) + ); const { params } = useLocation(); + const { canvas = 'view' } = params; const history = useHistory(); const hasRevisions = useSelect( ( select ) => { const { getEntityRecord, __experimentalGetCurrentGlobalStylesId } = @@ -261,8 +273,17 @@ function useGlobalStylesOpenRevisionsCommands() { canvas: 'edit', } ); } - if ( params.postId && getCanvasMode() !== 'edit' ) { - setCanvasMode( 'edit' ); + if ( params.postId && canvas !== 'edit' ) { + history.push( + { + ...params, + canvas: 'edit', + }, + undefined, + { + transition: 'canvas-mode-edit-transition', + } + ); } openGeneralSidebar( 'edit-site/global-styles' ); setEditorCanvasContainerView( 'global-styles-revisions' ); @@ -274,9 +295,8 @@ function useGlobalStylesOpenRevisionsCommands() { history, openGeneralSidebar, setEditorCanvasContainerView, - getCanvasMode, - setCanvasMode, - params.postId, + canvas, + params, ] ); return { diff --git a/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js b/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js index d0064a947001a2..97283044193892 100644 --- a/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js +++ b/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js @@ -20,26 +20,22 @@ import { unlock } from '../../lock-unlock'; import { TEMPLATE_POST_TYPE } from '../../utils/constants'; import { useLink } from '../../components/routes/link'; -const { useHistory } = unlock( routerPrivateApis ); +const { useHistory, useLocation } = unlock( routerPrivateApis ); function usePageContentFocusCommands() { const { record: template } = useEditedEntityRecord(); - const { isPage, canvasMode, templateId, currentPostType } = useSelect( - ( select ) => { - const { isPage: _isPage, getCanvasMode } = unlock( - select( editSiteStore ) - ); - const { getCurrentPostType, getCurrentTemplateId } = - select( editorStore ); - return { - isPage: _isPage(), - canvasMode: getCanvasMode(), - templateId: getCurrentTemplateId(), - currentPostType: getCurrentPostType(), - }; - }, - [] - ); + const { params } = useLocation(); + const { canvas = 'view' } = params; + const { isPage, templateId, currentPostType } = useSelect( ( select ) => { + const { isPage: _isPage } = unlock( select( editSiteStore ) ); + const { getCurrentPostType, getCurrentTemplateId } = + select( editorStore ); + return { + isPage: _isPage(), + templateId: getCurrentTemplateId(), + currentPostType: getCurrentPostType(), + }; + }, [] ); const { onClick: editTemplate } = useLink( { postType: 'wp_template', @@ -48,7 +44,7 @@ function usePageContentFocusCommands() { const { setRenderingMode } = useDispatch( editorStore ); - if ( ! isPage || canvasMode !== 'edit' ) { + if ( ! isPage || canvas !== 'edit' ) { return { isLoading: false, commands: [] }; } diff --git a/packages/edit-site/src/hooks/commands/use-set-command-context.js b/packages/edit-site/src/hooks/commands/use-set-command-context.js index 30f7f7ce258c61..e27c4ca91582fd 100644 --- a/packages/edit-site/src/hooks/commands/use-set-command-context.js +++ b/packages/edit-site/src/hooks/commands/use-set-command-context.js @@ -4,34 +4,32 @@ import { useSelect } from '@wordpress/data'; import { privateApis as commandsPrivateApis } from '@wordpress/commands'; import { store as blockEditorStore } from '@wordpress/block-editor'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies */ -import { store as editSiteStore } from '../../store'; import { unlock } from '../../lock-unlock'; import { useHasEditorCanvasContainer } from '../../components/editor-canvas-container'; const { useCommandContext } = unlock( commandsPrivateApis ); +const { useLocation } = unlock( routerPrivateApis ); /** * React hook used to set the correct command context based on the current state. */ export default function useSetCommandContext() { - const { hasBlockSelected, canvasMode } = useSelect( ( select ) => { - const { getCanvasMode } = unlock( select( editSiteStore ) ); - const { getBlockSelectionStart } = select( blockEditorStore ); - return { - canvasMode: getCanvasMode(), - hasBlockSelected: getBlockSelectionStart(), - }; + const { params } = useLocation(); + const { canvas = 'view' } = params; + const hasBlockSelected = useSelect( ( select ) => { + return select( blockEditorStore ).getBlockSelectionStart(); }, [] ); const hasEditorCanvasContainer = useHasEditorCanvasContainer(); // Sets the right context for the command palette let commandContext = 'site-editor'; - if ( canvasMode === 'edit' ) { + if ( canvas === 'edit' ) { commandContext = 'entity-edit'; } if ( hasBlockSelected ) { diff --git a/packages/edit-site/src/store/private-actions.js b/packages/edit-site/src/store/private-actions.js index 1c5924a292765b..1db3873acedda2 100644 --- a/packages/edit-site/src/store/private-actions.js +++ b/packages/edit-site/src/store/private-actions.js @@ -1,82 +1,3 @@ -/** - * WordPress dependencies - */ -import { store as blockEditorStore } from '@wordpress/block-editor'; -import { store as preferencesStore } from '@wordpress/preferences'; -import { store as editorStore } from '@wordpress/editor'; - -/** - * Action that switches the canvas mode. - * - * @param {?string} mode Canvas mode. - */ -export const setCanvasMode = - ( mode ) => - ( { registry, dispatch } ) => { - const isMediumOrBigger = - window.matchMedia( '(min-width: 782px)' ).matches; - const switchCanvasMode = () => { - registry.batch( () => { - registry.dispatch( blockEditorStore ).clearSelectedBlock(); - registry.dispatch( editorStore ).setDeviceType( 'Desktop' ); - const isPublishSidebarOpened = registry - .select( editorStore ) - .isPublishSidebarOpened(); - dispatch( { - type: 'SET_CANVAS_MODE', - mode, - } ); - const isEditMode = mode === 'edit'; - if ( isPublishSidebarOpened && ! isEditMode ) { - registry.dispatch( editorStore ).closePublishSidebar(); - } - - // Check if the block list view should be open by default. - // If `distractionFree` mode is enabled, the block list view should not be open. - // This behavior is disabled for small viewports. - if ( - isMediumOrBigger && - isEditMode && - registry - .select( preferencesStore ) - .get( 'core', 'showListViewByDefault' ) && - ! registry - .select( preferencesStore ) - .get( 'core', 'distractionFree' ) - ) { - registry - .dispatch( editorStore ) - .setIsListViewOpened( true ); - } else { - registry - .dispatch( editorStore ) - .setIsListViewOpened( false ); - } - registry.dispatch( editorStore ).setIsInserterOpened( false ); - } ); - }; - - /* - * Skip transition in mobile, otherwise it crashes the browser. - * See: https://github.com/WordPress/gutenberg/pull/63002. - */ - if ( ! isMediumOrBigger || ! document.startViewTransition ) { - switchCanvasMode(); - } else { - document.documentElement.classList.add( - `canvas-mode-${ mode }-transition` - ); - const transition = document.startViewTransition( () => - switchCanvasMode() - ); - transition.finished.finally( () => { - document.documentElement.classList.remove( - `canvas-mode-${ mode }-transition` - ); - } ); - } - }; - /** * Action that switches the editor canvas container view. * diff --git a/packages/edit-site/src/store/private-selectors.js b/packages/edit-site/src/store/private-selectors.js index d0f1d3f4196008..b7c14534419582 100644 --- a/packages/edit-site/src/store/private-selectors.js +++ b/packages/edit-site/src/store/private-selectors.js @@ -1,14 +1,3 @@ -/** - * Returns the current canvas mode. - * - * @param {Object} state Global application state. - * - * @return {string} Canvas mode. - */ -export function getCanvasMode( state ) { - return state.canvasMode; -} - /** * Returns the editor canvas container view. * diff --git a/packages/edit-site/src/store/reducer.js b/packages/edit-site/src/store/reducer.js index 951f004adc9af5..3ce067c25c1954 100644 --- a/packages/edit-site/src/store/reducer.js +++ b/packages/edit-site/src/store/reducer.js @@ -60,27 +60,10 @@ export function saveViewPanel( state = false, action ) { switch ( action.type ) { case 'SET_IS_SAVE_VIEW_OPENED': return action.isOpen; - case 'SET_CANVAS_MODE': - return false; } return state; } -/** - * Reducer used to track the site editor canvas mode (edit or view). - * - * @param {Object} state Current state. - * @param {Object} action Dispatched action. - */ -function canvasMode( state = 'init', action ) { - switch ( action.type ) { - case 'SET_CANVAS_MODE': - return action.mode; - } - - return state; -} - /** * Reducer used to track the site editor canvas container view. * Default is `undefined`, denoting the default, visual block editor. @@ -111,7 +94,6 @@ export default combineReducers( { settings, editedPost, saveViewPanel, - canvasMode, editorCanvasContainerView, routes, } ); diff --git a/packages/router/src/history.ts b/packages/router/src/history.ts index e046522a751894..6cbef108eec206 100644 --- a/packages/router/src/history.ts +++ b/packages/router/src/history.ts @@ -12,6 +12,10 @@ export interface EnhancedHistory extends BrowserHistory { getLocationWithParams: () => Location; } +interface PushOptions { + transition?: string; +} + const history = createBrowserHistory(); const originalHistoryPush = history.push; @@ -32,9 +36,35 @@ function preserveThemePreview( params: Record< string, any > ) { return { ...params, wp_theme_preview: currentThemePreview }; } -function push( params: Record< string, any >, state: Record< string, any > ) { - const search = buildQueryString( preserveThemePreview( params ) ); - return originalHistoryPush.call( history, { search }, state ); +function push( + params: Record< string, any >, + state: Record< string, any >, + options: PushOptions = {} +) { + const performPush = () => { + const search = buildQueryString( preserveThemePreview( params ) ); + return originalHistoryPush.call( history, { search }, state ); + }; + + /* + * Skip transition in mobile, otherwise it crashes the browser. + * See: https://github.com/WordPress/gutenberg/pull/63002. + */ + const isMediumOrBigger = window.matchMedia( '(min-width: 782px)' ).matches; + if ( + ! isMediumOrBigger || + // @ts-expect-error + ! document.startViewTransition || + ! options.transition + ) { + return performPush(); + } + document.documentElement.classList.add( options.transition ); + // @ts-expect-error + const transition = document.startViewTransition( () => performPush() ); + transition.finished.finally( () => { + document.documentElement.classList.remove( options.transition ?? '' ); + } ); } function replace( From c0317dd12cccf08ef7eda737e7276b5f7e548cac Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Tue, 22 Oct 2024 11:40:59 +0100 Subject: [PATCH 1281/1908] Data views: Fix alignment of action items in list layout (#66273) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> --- packages/dataviews/src/dataviews-layouts/list/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataviews/src/dataviews-layouts/list/style.scss b/packages/dataviews/src/dataviews-layouts/list/style.scss index 9a3128c14b76a7..429f2397c96019 100644 --- a/packages/dataviews/src/dataviews-layouts/list/style.scss +++ b/packages/dataviews/src/dataviews-layouts/list/style.scss @@ -33,7 +33,7 @@ ul.dataviews-view-list { .dataviews-view-list__item-actions { flex-basis: min-content; overflow: unset; - margin-inline: $grid-unit-10 0; + padding-inline-end: $grid-unit-05; .components-button { opacity: 1; From e43a1c574959eb835f34b92479b7b6b4ff5ff8ea Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Tue, 22 Oct 2024 13:17:50 +0200 Subject: [PATCH 1282/1908] Pull request automation: use full npm install (#66314) Remove single-package installation from this workflow that creates problems when migrating to npm workspaces. The regular npm install workflow is frequently available in cache. --- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- .github/workflows/pull-request-automation.yml | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/.github/workflows/pull-request-automation.yml b/.github/workflows/pull-request-automation.yml index 9aecafc2009e7f..cf37fa00c060bf 100644 --- a/.github/workflows/pull-request-automation.yml +++ b/.github/workflows/pull-request-automation.yml @@ -17,24 +17,8 @@ jobs: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - name: Use desired version of Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 - with: - node-version-file: '.nvmrc' - check-latest: true - - - name: Cache NPM packages - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 - with: - # npm cache files are stored in `~/.npm` on Linux/macOS - path: ~/.npm - key: ${{ runner.os }}-node-${{ matrix.node }}-npm-pr-automation-cache-${{ hashFiles('**/package-lock.json') }} - - # Changing into the action's directory and running `npm install` is much - # faster than a full project-wide `npm ci`. - - name: Install NPM dependencies - run: npm install - working-directory: packages/project-management-automation + - name: Setup Node.js and install dependencies + uses: ./.github/setup-node - uses: ./packages/project-management-automation with: From d0771cda1bdc8d4d78c956f4fffda04182572967 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Tue, 22 Oct 2024 14:34:25 +0300 Subject: [PATCH 1283/1908] Edit Site: Fix canvasMode var (#66316) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- .../edit-site/src/components/layout/index.js | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index 3b9769d470f518..12799f46fbe348 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -170,18 +170,16 @@ export default function Layout( { route } ) { </div> ) } - { ! isMobileViewport && - areas.edit && - canvasMode !== 'edit' && ( - <div - className="edit-site-layout__area" - style={ { - maxWidth: widths?.edit, - } } - > - { areas.edit } - </div> - ) } + { ! isMobileViewport && areas.edit && canvas !== 'edit' && ( + <div + className="edit-site-layout__area" + style={ { + maxWidth: widths?.edit, + } } + > + { areas.edit } + </div> + ) } { ! isMobileViewport && areas.preview && ( <div className="edit-site-layout__canvas-container"> From 9fcb43b679d957abe4c051fbcdf17a70bdb84e0f Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Tue, 22 Oct 2024 15:13:52 +0300 Subject: [PATCH 1284/1908] Update a few function definitions (#66315) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/src/spacer/hook.ts | 5 +++-- packages/data-controls/src/index.ts | 4 +++- packages/fields/src/mutation/index.ts | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/components/src/spacer/hook.ts b/packages/components/src/spacer/hook.ts index 82d36baa5e202f..3ef4b21e104c74 100644 --- a/packages/components/src/spacer/hook.ts +++ b/packages/components/src/spacer/hook.ts @@ -12,8 +12,9 @@ import { space } from '../utils/space'; import { rtl, useCx } from '../utils'; import type { SpacerProps } from './types'; -const isDefined = < T >( o: T ): o is Exclude< T, null | undefined > => - typeof o !== 'undefined' && o !== null; +function isDefined< T >( o: T ): o is Exclude< T, null | undefined > { + return typeof o !== 'undefined' && o !== null; +} export function useSpacer( props: WordPressComponentProps< SpacerProps, 'div' > diff --git a/packages/data-controls/src/index.ts b/packages/data-controls/src/index.ts index 9edc6502ef881f..c0898d214224f5 100644 --- a/packages/data-controls/src/index.ts +++ b/packages/data-controls/src/index.ts @@ -154,7 +154,9 @@ export const __unstableAwaitPromise = function < T >( promise: Promise< T > ) { * store. */ export const controls = { - AWAIT_PROMISE: < T >( { promise }: { promise: Promise< T > } ) => promise, + AWAIT_PROMISE< T >( { promise }: { promise: Promise< T > } ) { + return promise; + }, API_FETCH( { request }: { request: APIFetchOptions } ) { return triggerFetch( request ); }, diff --git a/packages/fields/src/mutation/index.ts b/packages/fields/src/mutation/index.ts index 80e399d74e9479..89df0f769f70ed 100644 --- a/packages/fields/src/mutation/index.ts +++ b/packages/fields/src/mutation/index.ts @@ -10,9 +10,9 @@ import { dispatch } from '@wordpress/data'; */ import type { CoreDataError, Post } from '../types'; -const getErrorMessagesFromPromises = < T >( +function getErrorMessagesFromPromises< T >( allSettledResults: PromiseSettledResult< T >[] -) => { +) { const errorMessages = new Set< string >(); // If there was at lease one failure. if ( allSettledResults.length === 1 ) { @@ -36,7 +36,7 @@ const getErrorMessagesFromPromises = < T >( } } return errorMessages; -}; +} export type NoticeSettings< T extends Post > = { success: { From ba2d08e434df9955543966d4fdd83a557ee1eb0c Mon Sep 17 00:00:00 2001 From: Carolina Nymark <myazalea@hotmail.com> Date: Tue, 22 Oct 2024 14:19:16 +0200 Subject: [PATCH 1285/1908] Archives: Add border block support (#63400) Archives: Add border block support Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/block-library/src/archives/block.json | 6 ++++++ packages/block-library/src/archives/editor.scss | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/packages/block-library/src/archives/block.json b/packages/block-library/src/archives/block.json index e36691f3143c22..7fe956a994ed5a 100644 --- a/packages/block-library/src/archives/block.json +++ b/packages/block-library/src/archives/block.json @@ -26,6 +26,12 @@ }, "supports": { "align": true, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + }, "html": false, "spacing": { "margin": true, diff --git a/packages/block-library/src/archives/editor.scss b/packages/block-library/src/archives/editor.scss index 6bb1d96431acf7..eb657b595f7141 100644 --- a/packages/block-library/src/archives/editor.scss +++ b/packages/block-library/src/archives/editor.scss @@ -1,3 +1,11 @@ ul.wp-block-archives { padding-left: 2.5em; } + +// The following styles are to prevent duplicate spacing and borders for the archives +// block in the editor given it uses server side rendering. +// See https://github.com/WordPress/gutenberg/pull/63400 +.wp-block-archives .wp-block-archives { + margin: 0; + border: 0; +} From 1461ef1c57639605c3233e72252f4b80b736896c Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 22 Oct 2024 21:21:03 +0900 Subject: [PATCH 1286/1908] SpacingSizesControl: Use generic label for linked button (#66304) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: madhusudhand <madhudollu@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> --- .../spacing-sizes-control/linked-button.js | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/components/spacing-sizes-control/linked-button.js b/packages/block-editor/src/components/spacing-sizes-control/linked-button.js index e9ca68aaa2b31d..f6d56be66072ad 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/linked-button.js +++ b/packages/block-editor/src/components/spacing-sizes-control/linked-button.js @@ -3,20 +3,10 @@ */ import { Button, Tooltip } from '@wordpress/components'; import { link, linkOff } from '@wordpress/icons'; -import { __, sprintf } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; export default function LinkedButton( { isLinked, ...props } ) { - const label = isLinked - ? sprintf( - // translators: 1. Type of spacing being modified (padding, margin, etc). - __( 'Unlink %1$s' ), - props.label.toLowerCase() - ).trim() - : sprintf( - // translators: 1. Type of spacing being modified (padding, margin, etc). - __( 'Link %1$s' ), - props.label.toLowerCase() - ).trim(); + const label = isLinked ? __( 'Unlink sides' ) : __( 'Link sides' ); return ( <Tooltip text={ label }> From d1c3508487735e8266f8ea7a6a3238ee8ca6b81b Mon Sep 17 00:00:00 2001 From: Carolina Nymark <myazalea@hotmail.com> Date: Tue, 22 Oct 2024 14:49:28 +0200 Subject: [PATCH 1287/1908] Add theme type to the bug report issue template (#63851) * Add theme type to the bug report issue template * Add "Not sure" option to the theme type checkboxes --------- Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/ISSUE_TEMPLATE/Bug_report.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.yml b/.github/ISSUE_TEMPLATE/Bug_report.yml index 5d7c876ccefca7..41bb6f1c9ba108 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.yml +++ b/.github/ISSUE_TEMPLATE/Bug_report.yml @@ -65,3 +65,13 @@ body: options: - label: 'Yes' required: true + + - type: checkboxes + id: themes + attributes: + label: Please confirm which theme type you used for testing. + options: + - label: 'Block' + - label: 'Classic' + - label: 'Hybrid (e.g. classic with theme.json)' + - label: 'Not sure' From ca8c191b419a8335c94f9e1c9526793ecc1c35cb Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 22 Oct 2024 22:36:13 +0900 Subject: [PATCH 1288/1908] Editor Interface: Remove small header from global styles/plugin sidebar (#64474) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../global-styles-sidebar/default-sidebar.js | 1 - .../components/global-styles-sidebar/index.js | 32 ++++++++++-------- .../components/global-styles/screen-css.js | 1 + .../src/components/plugin-sidebar/index.js | 13 -------- packages/interface/CHANGELOG.md | 4 +++ .../complementary-area-header/index.js | 33 +++++++------------ .../complementary-area-header/style.scss | 25 -------------- .../components/complementary-area/README.md | 8 ----- .../components/complementary-area/index.js | 7 ++-- .../components/complementary-area/style.scss | 6 +--- 10 files changed, 39 insertions(+), 91 deletions(-) diff --git a/packages/edit-site/src/components/global-styles-sidebar/default-sidebar.js b/packages/edit-site/src/components/global-styles-sidebar/default-sidebar.js index 5817c6d97ddddf..1f24bb49aa9f80 100644 --- a/packages/edit-site/src/components/global-styles-sidebar/default-sidebar.js +++ b/packages/edit-site/src/components/global-styles-sidebar/default-sidebar.js @@ -30,7 +30,6 @@ export default function DefaultSidebar( { scope="core" identifier={ identifier } title={ title } - smallScreenTitle={ title } icon={ icon } closeLabel={ closeLabel } header={ header } diff --git a/packages/edit-site/src/components/global-styles-sidebar/index.js b/packages/edit-site/src/components/global-styles-sidebar/index.js index 2b9a2669a96fe6..c0ad313d5d477c 100644 --- a/packages/edit-site/src/components/global-styles-sidebar/index.js +++ b/packages/edit-site/src/components/global-styles-sidebar/index.js @@ -11,6 +11,7 @@ import { store as editorStore, privateApis as editorPrivateApis, } from '@wordpress/editor'; +import { useViewportMatch } from '@wordpress/compose'; import { privateApis as routerPrivateApis } from '@wordpress/router'; /** @@ -81,6 +82,7 @@ export default function GlobalStylesSidebar() { const { setEditorCanvasContainerView } = unlock( useDispatch( editSiteStore ) ); + const isMobileViewport = useViewportMatch( 'medium', '<' ); useEffect( () => { if ( shouldClearCanvasContainerView ) { @@ -149,20 +151,22 @@ export default function GlobalStylesSidebar() { gap={ 1 } className="edit-site-global-styles-sidebar__header-actions" > - <FlexItem> - <Button - icon={ seen } - label={ __( 'Style Book' ) } - isPressed={ - isStyleBookOpened || - isRevisionsStyleBookOpened - } - accessibleWhenDisabled - disabled={ shouldClearCanvasContainerView } - onClick={ toggleStyleBook } - size="compact" - /> - </FlexItem> + { ! isMobileViewport && ( + <FlexItem> + <Button + icon={ seen } + label={ __( 'Style Book' ) } + isPressed={ + isStyleBookOpened || + isRevisionsStyleBookOpened + } + accessibleWhenDisabled + disabled={ shouldClearCanvasContainerView } + onClick={ toggleStyleBook } + size="compact" + /> + </FlexItem> + ) } <FlexItem> <Button label={ __( 'Revisions' ) } diff --git a/packages/edit-site/src/components/global-styles/screen-css.js b/packages/edit-site/src/components/global-styles/screen-css.js index b6d8cb7fd7086e..7d67bac28824fe 100644 --- a/packages/edit-site/src/components/global-styles/screen-css.js +++ b/packages/edit-site/src/components/global-styles/screen-css.js @@ -33,6 +33,7 @@ function ScreenCSS() { description={ <> { description } + <br /> <ExternalLink href={ __( 'https://developer.wordpress.org/advanced-administration/wordpress/css/' diff --git a/packages/editor/src/components/plugin-sidebar/index.js b/packages/editor/src/components/plugin-sidebar/index.js index 56a954cadffb69..5cd61a3747e6c1 100644 --- a/packages/editor/src/components/plugin-sidebar/index.js +++ b/packages/editor/src/components/plugin-sidebar/index.js @@ -1,15 +1,8 @@ /** * WordPress dependencies */ -import { useSelect } from '@wordpress/data'; -import { __ } from '@wordpress/i18n'; import { ComplementaryArea } from '@wordpress/interface'; -/** - * Internal dependencies - */ -import { store as editorStore } from '../../store'; - /** * Renders a sidebar when activated. The contents within the `PluginSidebar` will appear as content within the sidebar. * It also automatically renders a corresponding `PluginSidebarMenuItem` component when `isPinnable` flag is set to `true`. @@ -76,16 +69,10 @@ import { store as editorStore } from '../../store'; * ``` */ export default function PluginSidebar( { className, ...props } ) { - const { postTitle } = useSelect( ( select ) => { - return { - postTitle: select( editorStore ).getEditedPostAttribute( 'title' ), - }; - }, [] ); return ( <ComplementaryArea panelClassName={ className } className="editor-sidebar" - smallScreenTitle={ postTitle || __( '(no title)' ) } scope="core" { ...props } /> diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index f9b9181fa75434..ea748e80a9eb6a 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Removed `smallScreenTitle` prop from the `ComplementaryArea` component ([#64474](https://github.com/WordPress/gutenberg/pull/64474)). + ## 7.0.0 (2024-10-16) ### Breaking Changes diff --git a/packages/interface/src/components/complementary-area-header/index.js b/packages/interface/src/components/complementary-area-header/index.js index f1ed44e123676f..85670155086003 100644 --- a/packages/interface/src/components/complementary-area-header/index.js +++ b/packages/interface/src/components/complementary-area-header/index.js @@ -14,7 +14,6 @@ import { closeSmall } from '@wordpress/icons'; import ComplementaryAreaToggle from '../complementary-area-toggle'; const ComplementaryAreaHeader = ( { - smallScreenTitle, children, className, toggleButtonProps, @@ -23,27 +22,17 @@ const ComplementaryAreaHeader = ( { <ComplementaryAreaToggle icon={ closeSmall } { ...toggleButtonProps } /> ); return ( - <> - <div className="components-panel__header interface-complementary-area-header__small"> - { smallScreenTitle && ( - <h2 className="interface-complementary-area-header__small-title"> - { smallScreenTitle } - </h2> - ) } - { toggleButton } - </div> - <div - className={ clsx( - 'components-panel__header', - 'interface-complementary-area-header', - className - ) } - tabIndex={ -1 } - > - { children } - { toggleButton } - </div> - </> + <div + className={ clsx( + 'components-panel__header', + 'interface-complementary-area-header', + className + ) } + tabIndex={ -1 } + > + { children } + { toggleButton } + </div> ); }; diff --git a/packages/interface/src/components/complementary-area-header/style.scss b/packages/interface/src/components/complementary-area-header/style.scss index 2984c78c776a70..ce602f369d2aed 100644 --- a/packages/interface/src/components/complementary-area-header/style.scss +++ b/packages/interface/src/components/complementary-area-header/style.scss @@ -1,20 +1,3 @@ -.components-panel__header.interface-complementary-area-header__small { - background: $white; - padding-right: $grid-unit-05; - - .interface-complementary-area-header__small-title { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - width: 100%; - margin: 0; - } - - @include break-medium() { - display: none; - } -} - .interface-complementary-area-header { background: $white; padding-right: $grid-unit-15; // Reduced padding to account for close buttons. @@ -23,12 +6,4 @@ .interface-complementary-area-header__title { margin: 0; } - - .components-button.has-icon { - display: none; - - @include break-medium() { - display: flex; - } - } } diff --git a/packages/interface/src/components/complementary-area/README.md b/packages/interface/src/components/complementary-area/README.md index b96406043415fe..b270da23931a22 100644 --- a/packages/interface/src/components/complementary-area/README.md +++ b/packages/interface/src/components/complementary-area/README.md @@ -84,14 +84,6 @@ The scope of the complementary area e.g: "core", "myplugin/custom-screen-a", - Type: `String` - Required: Yes -### smallScreenTitle - -In small screens, the complementary area may take up the entire screen. -`smallScreenTitle` allows displaying a title above the complementary area, so the user is more aware of what the area refers to. - -- Type: `String` -- Required: No - ### title Human friendly title of the complementary area. diff --git a/packages/interface/src/components/complementary-area/index.js b/packages/interface/src/components/complementary-area/index.js index d9fa8e71acb23a..84334f6b2659b4 100644 --- a/packages/interface/src/components/complementary-area/index.js +++ b/packages/interface/src/components/complementary-area/index.js @@ -179,7 +179,6 @@ function ComplementaryArea( { panelClassName, scope, name, - smallScreenTitle, title, toggleShortcut, isActiveByDefault, @@ -220,6 +219,9 @@ function ComplementaryArea( { }, [ identifier, scope ] ); + + const isMobileViewport = useViewportMatch( 'medium', '<' ); + useAdjustComplementaryListener( scope, identifier, @@ -300,7 +302,6 @@ function ComplementaryArea( { className={ headerClassName } closeLabel={ closeLabel } onClose={ () => disableComplementaryArea( scope ) } - smallScreenTitle={ smallScreenTitle } toggleButtonProps={ { label: closeLabel, size: 'small', @@ -314,7 +315,7 @@ function ComplementaryArea( { <h2 className="interface-complementary-area-header__title"> { title } </h2> - { isPinnable && ( + { isPinnable && ! isMobileViewport && ( <Button className="interface-complementary-area__pin-unpin-item" icon={ isPinned ? starFilled : starEmpty } diff --git a/packages/interface/src/components/complementary-area/style.scss b/packages/interface/src/components/complementary-area/style.scss index f45273516f53b5..1f769acb69f74d 100644 --- a/packages/interface/src/components/complementary-area/style.scss +++ b/packages/interface/src/components/complementary-area/style.scss @@ -25,11 +25,7 @@ z-index: z-index(".interface-complementary-area .components-panel__header"); &.editor-sidebar__panel-tabs { - top: $panel-header-height; - - @include break-medium() { - top: 0; - } + top: 0; } } From c926d6974269229b7f3bab0dd3e366db854b9051 Mon Sep 17 00:00:00 2001 From: VATALIYA PARTH <88878890+PARTHVATALIYA@users.noreply.github.com> Date: Tue, 22 Oct 2024 19:11:03 +0530 Subject: [PATCH 1289/1908] Fix: Activate zoom out on large viewport (#66308) * Activate zoom out on large viewport * Reset zoom out when view-port change to medium --------- Co-authored-by: PARTHVATALIYA <parthvataliya@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- packages/block-editor/src/hooks/use-zoom-out.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/hooks/use-zoom-out.js b/packages/block-editor/src/hooks/use-zoom-out.js index 23f7fbc4bd59a1..914886497bbb38 100644 --- a/packages/block-editor/src/hooks/use-zoom-out.js +++ b/packages/block-editor/src/hooks/use-zoom-out.js @@ -9,6 +9,7 @@ import { useEffect } from '@wordpress/element'; */ import { store as blockEditorStore } from '../store'; import { unlock } from '../lock-unlock'; +import { useViewportMatch } from '@wordpress/compose'; /** * A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode. @@ -20,12 +21,13 @@ export function useZoomOut( zoomOut = true ) { useDispatch( blockEditorStore ) ); const { isZoomOut } = unlock( useSelect( blockEditorStore ) ); + const isWideViewport = useViewportMatch( 'large' ); useEffect( () => { const isZoomOutOnMount = isZoomOut(); return () => { - if ( isZoomOutOnMount ) { + if ( isZoomOutOnMount && isWideViewport ) { setZoomLevel( 50 ); } else { resetZoomLevel(); @@ -34,10 +36,10 @@ export function useZoomOut( zoomOut = true ) { }, [] ); useEffect( () => { - if ( zoomOut ) { + if ( zoomOut && isWideViewport ) { setZoomLevel( 50 ); } else { resetZoomLevel(); } - }, [ zoomOut, setZoomLevel, resetZoomLevel ] ); + }, [ zoomOut, setZoomLevel, resetZoomLevel, isWideViewport ] ); } From 80fcf02a844454a812ce7f4070c2a4cac80d54f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Oct 2024 14:04:44 +0000 Subject: [PATCH 1290/1908] Bump the github-actions group across 1 directory with 2 updates (#66325) Bumps the github-actions group with 2 updates in the / directory: [actions/cache](https://github.com/actions/cache) and [ruby/setup-ruby](https://github.com/ruby/setup-ruby). Updates `actions/cache` from 4.1.1 to 4.1.2 - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/3624ceb22c1c5a301c8db4169662070a689d9ea8...6849a6489940f00c2f30c0fb92c6274307ccb58a) Updates `ruby/setup-ruby` from 1.196.0 to 1.197.0 - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb) - [Commits](https://github.com/ruby/setup-ruby/compare/f26937343756480a8cb3ae1f623b9c8d89ed6984...7bae1d00b5db9166f4f0fc47985a3a5702cb58f0) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/rnmobile-android-runner.yml | 4 ++-- .github/workflows/rnmobile-ios-runner.yml | 8 ++++---- .github/workflows/unit-test.yml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index a1e332be783030..e9477dcf7c9bfb 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -37,7 +37,7 @@ jobs: uses: ./.github/setup-node - name: Restore tests setup cache - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 + uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: | ~/.appium @@ -50,7 +50,7 @@ jobs: uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0 - name: AVD cache - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 + uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 id: avd-cache with: path: | diff --git a/.github/workflows/rnmobile-ios-runner.yml b/.github/workflows/rnmobile-ios-runner.yml index a5c5dfd3f96f93..90fb7e15fe4d1f 100644 --- a/.github/workflows/rnmobile-ios-runner.yml +++ b/.github/workflows/rnmobile-ios-runner.yml @@ -27,7 +27,7 @@ jobs: with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - uses: ruby/setup-ruby@f26937343756480a8cb3ae1f623b9c8d89ed6984 # v1.196.0 + - uses: ruby/setup-ruby@7bae1d00b5db9166f4f0fc47985a3a5702cb58f0 # v1.197.0 with: # `.ruby-version` file location working-directory: packages/react-native-editor/ios @@ -42,7 +42,7 @@ jobs: uses: ./.github/setup-node - name: Restore tests setup cache - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 + uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: | ~/.appium @@ -55,7 +55,7 @@ jobs: run: find package-lock.json packages/react-native-editor/ios packages/react-native-aztec/ios packages/react-native-bridge/ios -type f -print0 | sort -z | xargs -0 shasum | tee ios-checksums.txt - name: Restore build cache - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 + uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: | packages/react-native-editor/ios/build/GutenbergDemo/Build/Products/Release-iphonesimulator/GutenbergDemo.app @@ -63,7 +63,7 @@ jobs: key: ${{ runner.os }}-ios-build-${{ matrix.xcode }}-${{ matrix.device }}-${{ hashFiles('ios-checksums.txt') }} - name: Restore pods cache - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 + uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: | packages/react-native-editor/ios/Pods diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 272d7e12d7193a..cb3ac1cc1b154f 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -296,7 +296,7 @@ jobs: run: echo "date=$(/bin/date -u --date='last Mon' "+%F")" >> $GITHUB_OUTPUT - name: Cache PHPCS scan cache - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 + uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: .cache/phpcs.json key: ${{ runner.os }}-date-${{ steps.get-date.outputs.date }}-phpcs-cache-${{ hashFiles('**/composer.json', 'phpcs.xml.dist') }} From d9e7ee7156d6d41375899dc0f3867f6941faf6a5 Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini <26530524+zaguiini@users.noreply.github.com> Date: Tue, 22 Oct 2024 11:34:09 -0300 Subject: [PATCH 1291/1908] Stabilize isPreviewMode flag (#66149) * Introduce stable isPreviewMode key and deprecate __unstableIsPreviewMode * Expose stable isPreviewMode as registry values * Use isPreviewMode instead of __unstableIsPreviewMode when accessing the setting * Access isPreviewMode directly from getSettings instead of through private symbol within RichText block * Revert private isPreviewMode changes * Add __unstableIsPreviewMode getter within settings reducer * Remove all other __unstableIsPreviewMode definitions * Define deprecation setter with Object.defineProperty to avoid eager getting when spreading the settings object * Use WP version within deprecation note * Add deprecation notice when trying to set __unstableIsPreviewMode in updateSettings * Add test to assert deprecated getters are passed to sub registry when defining a nested provider * Move deprecated setter logic to __experimentalUpdateSettings --- .../src/components/block-list/block.js | 3 +- .../src/components/block-list/index.js | 2 +- .../src/components/block-preview/index.js | 4 +- .../src/components/iframe/index.js | 2 +- .../src/components/provider/index.js | 4 +- .../provider/test/experimental-provider.js | 44 ++++++++++++++++++- packages/block-editor/src/store/defaults.js | 3 +- .../block-editor/src/store/private-actions.js | 25 +++++++++-- packages/block-editor/src/store/reducer.js | 36 ++++++++++----- .../block-editor/src/store/test/actions.js | 41 +++++++++++++++++ .../block-editor/src/store/test/reducer.js | 23 ++++++++++ .../block-editor/use-site-editor-settings.js | 2 +- .../page-patterns/use-pattern-settings.js | 2 +- .../src/components/revisions/index.js | 5 ++- .../src/components/style-book/index.js | 7 ++- .../editor/src/components/commands/index.js | 2 +- .../src/components/editor-interface/index.js | 2 +- .../editor/src/components/provider/index.js | 2 +- .../provider/use-block-editor-settings.js | 2 +- .../src/components/visual-editor/index.js | 2 +- 20 files changed, 178 insertions(+), 35 deletions(-) diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 783b45da932a3d..2215625596dc5c 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -629,8 +629,7 @@ function BlockListBlockProvider( props ) { const attributes = getBlockAttributes( clientId ); const { name: blockName, isValid } = blockWithoutAttributes; const blockType = getBlockType( blockName ); - const { supportsLayout, __unstableIsPreviewMode: isPreviewMode } = - getSettings(); + const { supportsLayout, isPreviewMode } = getSettings(); const hasLightBlockWrapper = blockType?.apiVersion > 1; const previewContext = { isPreviewMode, diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index 8e8f69f46ae276..2d91108ccb4123 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -187,7 +187,7 @@ function Items( { const _order = getBlockOrder( rootClientId ); - if ( getSettings().__unstableIsPreviewMode ) { + if ( getSettings().isPreviewMode ) { return { order: _order, selectedBlocks: EMPTY_ARRAY, diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 1c9bbe571db320..9eef0f1dc2abd5 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -59,7 +59,7 @@ export function BlockPreview( { () => ( { ...originalSettings, focusMode: false, // Disable "Spotlight mode". - __unstableIsPreviewMode: true, + isPreviewMode: true, } ), [ originalSettings ] ); @@ -124,7 +124,7 @@ export function useBlockPreview( { blocks, props = {}, layout } ) { ...originalSettings, styles: undefined, // Clear styles included by the parent settings, as they are already output by the parent's EditorStyles. focusMode: false, // Disable "Spotlight mode". - __unstableIsPreviewMode: true, + isPreviewMode: true, } ), [ originalSettings ] ); diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index b14514f934fb3e..a69d8db29e07df 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -117,7 +117,7 @@ function Iframe( { const settings = getSettings(); return { resolvedAssets: settings.__unstableResolvedAssets, - isPreviewMode: settings.__unstableIsPreviewMode, + isPreviewMode: settings.isPreviewMode, }; }, [] ); const { styles = '', scripts = '' } = resolvedAssets; diff --git a/packages/block-editor/src/components/provider/index.js b/packages/block-editor/src/components/provider/index.js index 8c24b797efeac8..abbb122ae3a0e0 100644 --- a/packages/block-editor/src/components/provider/index.js +++ b/packages/block-editor/src/components/provider/index.js @@ -46,9 +46,7 @@ export const ExperimentalBlockEditorProvider = withRegistryProvider( return ( <SlotFillProvider passthrough> - { ! settings?.__unstableIsPreviewMode && ( - <KeyboardShortcuts.Register /> - ) } + { ! settings?.isPreviewMode && <KeyboardShortcuts.Register /> } <BlockRefsProvider>{ children }</BlockRefsProvider> </SlotFillProvider> ); diff --git a/packages/block-editor/src/components/provider/test/experimental-provider.js b/packages/block-editor/src/components/provider/test/experimental-provider.js index 2bb2aaadce95cc..8bb94698fffc81 100644 --- a/packages/block-editor/src/components/provider/test/experimental-provider.js +++ b/packages/block-editor/src/components/provider/test/experimental-provider.js @@ -5,7 +5,7 @@ import { render } from '@testing-library/react'; /** * WordPress dependencies */ -import { useRegistry } from '@wordpress/data'; +import { useRegistry, useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -21,6 +21,20 @@ const HasEditorSetting = ( props ) => { return <p>Test.</p>; }; +const PreviewModeGetter = () => { + const previewModeKeys = useSelect( ( select ) => { + const { getSettings } = select( blockEditorStore ); + const settings = getSettings(); + return { + // This property will be removed in the future. There is a test that asserts we're throwing a deprecation warning. + __unstableIsPreviewMode: settings.__unstableIsPreviewMode, + isPreviewMode: settings.isPreviewMode, + }; + }, [] ); + + return <>{ JSON.stringify( previewModeKeys ) }</>; +}; + describe( 'BlockEditorProvider', () => { let registry; const setRegistry = ( reg ) => { @@ -58,6 +72,34 @@ describe( 'BlockEditorProvider', () => { const settings = registry.select( blockEditorStore ).getSettings(); expect( settings ).toHaveProperty( 'stableSetting' ); } ); + it( 'preserves deprecated getters incoming from the settings reducer', async () => { + const consoleWarn = jest + .spyOn( global.console, 'warn' ) + .mockImplementation(); + + const { container } = render( + <BlockEditorProvider + settings={ { + isPreviewMode: true, + } } + > + <PreviewModeGetter /> + </BlockEditorProvider> + ); + + expect( container ).toHaveTextContent( + JSON.stringify( { + __unstableIsPreviewMode: true, + isPreviewMode: true, + } ) + ); + + expect( consoleWarn ).toHaveBeenCalledWith( + '__unstableIsPreviewMode is deprecated since version 6.8. Please use isPreviewMode instead.' + ); + + consoleWarn.mockRestore(); + } ); } ); describe( 'ExperimentalBlockEditorProvider', () => { diff --git a/packages/block-editor/src/store/defaults.js b/packages/block-editor/src/store/defaults.js index 54877eafc36901..8314ad872468b2 100644 --- a/packages/block-editor/src/store/defaults.js +++ b/packages/block-editor/src/store/defaults.js @@ -167,7 +167,8 @@ export const SETTINGS_DEFAULTS = { __mobileEnablePageTemplates: false, __experimentalBlockPatterns: [], __experimentalBlockPatternCategories: [], - __unstableIsPreviewMode: false, + + isPreviewMode: false, // These settings will be completely revamped in the future. // The goal is to evolve this into an API which will instruct diff --git a/packages/block-editor/src/store/private-actions.js b/packages/block-editor/src/store/private-actions.js index 0ca3eb2cf522e6..e79833e0a73da7 100644 --- a/packages/block-editor/src/store/private-actions.js +++ b/packages/block-editor/src/store/private-actions.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { Platform } from '@wordpress/element'; +import deprecated from '@wordpress/deprecated'; import { speak } from '@wordpress/a11y'; import { __ } from '@wordpress/i18n'; @@ -41,14 +42,32 @@ export function __experimentalUpdateSettings( settings, { stripExperimentalSettings = false, reset = false } = {} ) { - let cleanSettings = settings; + let incomingSettings = settings; + + if ( Object.hasOwn( incomingSettings, '__unstableIsPreviewMode' ) ) { + deprecated( + "__unstableIsPreviewMode argument in wp.data.dispatch('core/block-editor').updateSettings", + { + since: '6.8', + alternative: 'isPreviewMode', + } + ); + + incomingSettings = { ...incomingSettings }; + incomingSettings.isPreviewMode = + incomingSettings.__unstableIsPreviewMode; + delete incomingSettings.__unstableIsPreviewMode; + } + + let cleanSettings = incomingSettings; + // There are no plugins in the mobile apps, so there is no // need to strip the experimental settings: if ( stripExperimentalSettings && Platform.OS === 'web' ) { cleanSettings = {}; - for ( const key in settings ) { + for ( const key in incomingSettings ) { if ( ! privateSettings.includes( key ) ) { - cleanSettings[ key ] = settings[ key ]; + cleanSettings[ key ] = incomingSettings[ key ]; } } } diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 1435e815813c46..2f0fa70d616fd9 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -8,6 +8,7 @@ import fastDeepEqual from 'fast-deep-equal/es6'; */ import { pipe } from '@wordpress/compose'; import { combineReducers, select } from '@wordpress/data'; +import deprecated from '@wordpress/deprecated'; import { store as blocksStore } from '@wordpress/blocks'; /** * Internal dependencies @@ -1660,17 +1661,30 @@ export function template( state = { isValid: true }, action ) { */ export function settings( state = SETTINGS_DEFAULTS, action ) { switch ( action.type ) { - case 'UPDATE_SETTINGS': - if ( action.reset ) { - return { - ...SETTINGS_DEFAULTS, - ...action.settings, - }; - } - return { - ...state, - ...action.settings, - }; + case 'UPDATE_SETTINGS': { + const updatedSettings = action.reset + ? { + ...SETTINGS_DEFAULTS, + ...action.settings, + } + : { + ...state, + ...action.settings, + }; + + Object.defineProperty( updatedSettings, '__unstableIsPreviewMode', { + get() { + deprecated( '__unstableIsPreviewMode', { + since: '6.8', + alternative: 'isPreviewMode', + } ); + + return this.isPreviewMode; + }, + } ); + + return updatedSettings; + } } return state; diff --git a/packages/block-editor/src/store/test/actions.js b/packages/block-editor/src/store/test/actions.js index f960363cdb0ddb..ce973e44f4523b 100644 --- a/packages/block-editor/src/store/test/actions.js +++ b/packages/block-editor/src/store/test/actions.js @@ -1125,6 +1125,47 @@ describe( 'actions', () => { } ); } ); + describe( 'updateSettings', () => { + it( 'warns when setting the deprecated __unstableIsPreviewMode property and sets the stable property instead', () => { + const consoleWarn = jest + .spyOn( global.console, 'warn' ) + .mockImplementation(); + + const store = createRegistry().registerStore( + blockEditorStoreName, + { + actions, + selectors, + reducer, + } + ); + + store.dispatch( + updateSettings( { + __unstableIsPreviewMode: true, + } ) + ); + + expect( consoleWarn ).toHaveBeenCalledWith( + "__unstableIsPreviewMode argument in wp.data.dispatch('core/block-editor').updateSettings is deprecated since version 6.8. Please use isPreviewMode instead." + ); + + consoleWarn.mockClear(); + + expect( store.getState().settings.__unstableIsPreviewMode ).toBe( + true + ); + + expect( store.getState().settings.isPreviewMode ).toBe( true ); + + expect( consoleWarn ).toHaveBeenCalledWith( + '__unstableIsPreviewMode is deprecated since version 6.8. Please use isPreviewMode instead.' + ); + + consoleWarn.mockRestore(); + } ); + } ); + describe( 'registerInserterMediaCategory', () => { describe( 'should log errors when invalid', () => { it( 'valid object', () => { diff --git a/packages/block-editor/src/store/test/reducer.js b/packages/block-editor/src/store/test/reducer.js index 1f1b9a9143d981..c99d639ba8a09e 100644 --- a/packages/block-editor/src/store/test/reducer.js +++ b/packages/block-editor/src/store/test/reducer.js @@ -32,6 +32,7 @@ import { insertionPoint, template, blockListSettings, + settings, lastBlockAttributesChange, lastBlockInserted, blockEditingModes, @@ -3070,6 +3071,28 @@ describe( 'state', () => { } ); } ); + describe( 'settings', () => { + it( 'should warn about __unstableIsPreviewMode deprecation', () => { + const consoleWarn = jest + .spyOn( global.console, 'warn' ) + .mockImplementation(); + + const settingsObject = settings( undefined, { + type: 'UPDATE_SETTINGS', + reset: true, + } ); + + expect( settingsObject.__unstableIsPreviewMode ).toBeDefined(); + expect( settingsObject.isPreviewMode ).toBeDefined(); + + expect( consoleWarn ).toHaveBeenCalledWith( + '__unstableIsPreviewMode is deprecated since version 6.8. Please use isPreviewMode instead.' + ); + + consoleWarn.mockRestore(); + } ); + } ); + describe( 'blockListSettings', () => { it( 'should add new settings', () => { const original = deepFreeze( {} ); diff --git a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js index dcdfb157b235b6..e6dd0368249627 100644 --- a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js +++ b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js @@ -72,7 +72,7 @@ export function useSpecificEditorSettings() { defaultRenderingMode, onNavigateToEntityRecord, onNavigateToPreviousEntityRecord, - __unstableIsPreviewMode: canvas === 'view', + isPreviewMode: canvas === 'view', }; }, [ settings, diff --git a/packages/edit-site/src/components/page-patterns/use-pattern-settings.js b/packages/edit-site/src/components/page-patterns/use-pattern-settings.js index 28a16b1d7ed7db..274604395baac5 100644 --- a/packages/edit-site/src/components/page-patterns/use-pattern-settings.js +++ b/packages/edit-site/src/components/page-patterns/use-pattern-settings.js @@ -43,7 +43,7 @@ export default function usePatternSettings() { return { ...restStoredSettings, __experimentalBlockPatterns: blockPatterns, - __unstableIsPreviewMode: true, + isPreviewMode: true, }; }, [ storedSettings, blockPatterns ] ); diff --git a/packages/edit-site/src/components/revisions/index.js b/packages/edit-site/src/components/revisions/index.js index d43b5e8d2ac025..5ce95872e0c9ae 100644 --- a/packages/edit-site/src/components/revisions/index.js +++ b/packages/edit-site/src/components/revisions/index.js @@ -53,7 +53,10 @@ function Revisions( { userConfig, blocks } ) { [] ); const settings = useMemo( - () => ( { ...originalSettings, __unstableIsPreviewMode: true } ), + () => ( { + ...originalSettings, + isPreviewMode: true, + } ), [ originalSettings ] ); diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 42b6e3f4fc99b6..0d8c49d76af507 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -91,7 +91,10 @@ function StyleBook( { ); const settings = useMemo( - () => ( { ...originalSettings, __unstableIsPreviewMode: true } ), + () => ( { + ...originalSettings, + isPreviewMode: true, + } ), [ originalSettings ] ); @@ -328,7 +331,7 @@ const Example = ( { id, title, blocks, isSelected, onClick } ) => { () => ( { ...originalSettings, focusMode: false, // Disable "Spotlight mode". - __unstableIsPreviewMode: true, + isPreviewMode: true, } ), [ originalSettings ] ); diff --git a/packages/editor/src/components/commands/index.js b/packages/editor/src/components/commands/index.js index b1471e25583415..a9c726f660b22e 100644 --- a/packages/editor/src/components/commands/index.js +++ b/packages/editor/src/components/commands/index.js @@ -57,7 +57,7 @@ function useEditorCommandLoader() { isDistractionFree: get( 'core', 'distractionFree' ), isFocusMode: get( 'core', 'focusMode' ), isTopToolbar: get( 'core', 'fixedToolbar' ), - isPreviewMode: getSettings().__unstableIsPreviewMode, + isPreviewMode: getSettings().isPreviewMode, isViewable: getPostType( getCurrentPostType() )?.viewable ?? false, isCodeEditingEnabled: getEditorSettings().codeEditingEnabled, isRichEditingEnabled: getEditorSettings().richEditingEnabled, diff --git a/packages/editor/src/components/editor-interface/index.js b/packages/editor/src/components/editor-interface/index.js index 6dc4c3fe770608..4c3fcc30e23d82 100644 --- a/packages/editor/src/components/editor-interface/index.js +++ b/packages/editor/src/components/editor-interface/index.js @@ -83,7 +83,7 @@ export default function EditorInterface( { isInserterOpened: select( editorStore ).isInserterOpened(), isListViewOpened: select( editorStore ).isListViewOpened(), isDistractionFree: get( 'core', 'distractionFree' ), - isPreviewMode: editorSettings.__unstableIsPreviewMode, + isPreviewMode: editorSettings.isPreviewMode, showBlockBreadcrumbs: get( 'core', 'showBlockBreadcrumbs' ), // translators: Default label for the Document in the Block Breadcrumb. documentLabel: postTypeLabel || _x( 'Document', 'noun' ), diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 87fea30e31cdb9..50d02610062c00 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -330,7 +330,7 @@ export const ExperimentalEditorProvider = withRegistryProvider( useSubRegistry={ false } > { children } - { ! settings.__unstableIsPreviewMode && ( + { ! settings.isPreviewMode && ( <> <PatternsMenuItems /> <TemplatePartMenuItems /> diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 12a67e44262b21..170ec96c107288 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -74,6 +74,7 @@ const BLOCK_EDITOR_SETTINGS = [ 'imageDimensions', 'imageEditing', 'imageSizes', + 'isPreviewMode', 'isRTL', 'locale', 'maxWidth', @@ -85,7 +86,6 @@ const BLOCK_EDITOR_SETTINGS = [ 'supportsLayout', 'widgetTypesToHideFromLegacyWidgetBlock', '__unstableHasCustomAppender', - '__unstableIsPreviewMode', '__unstableResolvedAssets', '__unstableIsBlockBasedTheme', ]; diff --git a/packages/editor/src/components/visual-editor/index.js b/packages/editor/src/components/visual-editor/index.js index 0f772075f5d4ae..6462c4a3f83682 100644 --- a/packages/editor/src/components/visual-editor/index.js +++ b/packages/editor/src/components/visual-editor/index.js @@ -166,7 +166,7 @@ function VisualEditor( { deviceType: getDeviceType(), isFocusedEntity: !! editorSettings.onNavigateToPreviousEntityRecord, postType: postTypeSlug, - isPreview: editorSettings.__unstableIsPreviewMode, + isPreview: editorSettings.isPreviewMode, }; }, [] ); const { isCleanNewPost } = useSelect( editorStore ); From 81704424da4a17d22e9fcee2a5fe2fc93c8382a1 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:46:06 +0300 Subject: [PATCH 1292/1908] ESLint: Remove various React Compiler mutation violations (#66327) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-editor/src/components/iframe/index.js | 8 ++++---- packages/components/src/composite/legacy/index.tsx | 7 +++++-- .../src/components/dataviews-bulk-actions/index.tsx | 12 ++++++------ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index a69d8db29e07df..9fc9fd4be64bdd 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -122,7 +122,7 @@ function Iframe( { }, [] ); const { styles = '', scripts = '' } = resolvedAssets; const [ iframeDocument, setIframeDocument ] = useState(); - const initialContainerWidth = useRef( 0 ); + const initialContainerWidthRef = useRef( 0 ); const [ bodyClasses, setBodyClasses ] = useState( [] ); const clearerRef = useBlockSelectionClearer(); const [ before, writingFlowRef, after ] = useWritingFlow(); @@ -243,12 +243,12 @@ function Iframe( { useEffect( () => { if ( ! isZoomedOut ) { - initialContainerWidth.current = containerWidth; + initialContainerWidthRef.current = containerWidth; } }, [ containerWidth, isZoomedOut ] ); const scaleContainerWidth = Math.max( - initialContainerWidth.current, + initialContainerWidthRef.current, containerWidth ); @@ -345,7 +345,7 @@ function Iframe( { const maxWidth = 750; // Note: When we initialize the zoom out when the canvas is smaller (sidebars open), - // initialContainerWidth will be smaller than the full page, and reflow will happen + // initialContainerWidthRef will be smaller than the full page, and reflow will happen // when the canvas area becomes larger due to sidebars closing. This is a known but // minor divergence for now. diff --git a/packages/components/src/composite/legacy/index.tsx b/packages/components/src/composite/legacy/index.tsx index 22ddff6572dd01..c6e6616e96c044 100644 --- a/packages/components/src/composite/legacy/index.tsx +++ b/packages/components/src/composite/legacy/index.tsx @@ -151,8 +151,11 @@ function proxyComposite< C extends Component >( const { store, ...rest } = mapLegacyStatePropsToComponentProps( legacyProps ); - const props = rest as ComponentProps< C >; - props.id = useInstanceId( store, props.baseId, props.id ); + let props = rest as ComponentProps< C >; + props = { + ...props, + id: useInstanceId( store, props.baseId, props.id ), + }; Object.entries( propMap ).forEach( ( [ from, to ] ) => { if ( props.hasOwnProperty( from ) ) { diff --git a/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx b/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx index 5eb9c5e1b6a4d0..92a3fe85f67e74 100644 --- a/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx +++ b/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx @@ -269,7 +269,7 @@ function FooterContent< Item >( { const [ actionInProgress, setActionInProgress ] = useState< string | null >( null ); - const footerContent = useRef< JSX.Element | null >( null ); + const footerContentRef = useRef< JSX.Element | null >( null ); const bulkActions = useMemo( () => actions.filter( ( action ) => action.supportsBulk ), @@ -306,8 +306,8 @@ function FooterContent< Item >( { [ actions, selectedItems ] ); if ( ! actionInProgress ) { - if ( footerContent.current ) { - footerContent.current = null; + if ( footerContentRef.current ) { + footerContentRef.current = null; } return renderFooterContent( data, @@ -320,8 +320,8 @@ function FooterContent< Item >( { setActionInProgress, onChangeSelection ); - } else if ( ! footerContent.current ) { - footerContent.current = renderFooterContent( + } else if ( ! footerContentRef.current ) { + footerContentRef.current = renderFooterContent( data, actions, getItemId, @@ -333,7 +333,7 @@ function FooterContent< Item >( { onChangeSelection ); } - return footerContent.current; + return footerContentRef.current; } export function BulkActionsFooter() { From bed7639ad6a0baeca9e03b3f1781e6b2e8a8fed6 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 23 Oct 2024 01:47:36 +0900 Subject: [PATCH 1293/1908] Icons: Add align-item related icons (#66242) * Icons: Add align-item related icons * Use `justify` prefix Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../block-vertical-alignment-control/icons.js | 34 ------------------- .../block-vertical-alignment-control/ui.js | 26 ++++++-------- packages/icons/src/index.js | 5 +++ packages/icons/src/library/justify-bottom.js | 12 +++++++ .../src/library/justify-center-vertical.js | 12 +++++++ .../library/justify-space-between-vertical.js | 12 +++++++ .../src/library/justify-stretch-vertical.js | 12 +++++++ packages/icons/src/library/justify-top.js | 12 +++++++ 8 files changed, 76 insertions(+), 49 deletions(-) delete mode 100644 packages/block-editor/src/components/block-vertical-alignment-control/icons.js create mode 100644 packages/icons/src/library/justify-bottom.js create mode 100644 packages/icons/src/library/justify-center-vertical.js create mode 100644 packages/icons/src/library/justify-space-between-vertical.js create mode 100644 packages/icons/src/library/justify-stretch-vertical.js create mode 100644 packages/icons/src/library/justify-top.js diff --git a/packages/block-editor/src/components/block-vertical-alignment-control/icons.js b/packages/block-editor/src/components/block-vertical-alignment-control/icons.js deleted file mode 100644 index b5c283ffef37db..00000000000000 --- a/packages/block-editor/src/components/block-vertical-alignment-control/icons.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * WordPress dependencies - */ -import { Path, SVG } from '@wordpress/components'; - -export const alignBottom = ( - <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> - <Path d="M15 4H9v11h6V4zM4 18.5V20h16v-1.5H4z" /> - </SVG> -); - -export const alignCenter = ( - <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> - <Path d="M20 11h-5V4H9v7H4v1.5h5V20h6v-7.5h5z" /> - </SVG> -); - -export const alignTop = ( - <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> - <Path d="M9 20h6V9H9v11zM4 4v1.5h16V4H4z" /> - </SVG> -); - -export const alignStretch = ( - <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> - <Path d="M4 4L20 4L20 5.5L4 5.5L4 4ZM10 7L14 7L14 17L10 17L10 7ZM20 18.5L4 18.5L4 20L20 20L20 18.5Z" /> - </SVG> -); - -export const spaceBetween = ( - <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> - <Path d="M7 4H17V8L7 8V4ZM7 16L17 16V20L7 20V16ZM20 11.25H4V12.75H20V11.25Z" /> - </SVG> -); diff --git a/packages/block-editor/src/components/block-vertical-alignment-control/ui.js b/packages/block-editor/src/components/block-vertical-alignment-control/ui.js index d1cacadf0cc49c..26340aa9179d82 100644 --- a/packages/block-editor/src/components/block-vertical-alignment-control/ui.js +++ b/packages/block-editor/src/components/block-vertical-alignment-control/ui.js @@ -3,37 +3,33 @@ */ import { _x } from '@wordpress/i18n'; import { ToolbarGroup, ToolbarDropdownMenu } from '@wordpress/components'; - -/** - * Internal dependencies - */ import { - alignTop, - alignCenter, - alignBottom, - alignStretch, - spaceBetween, -} from './icons'; + justifyTop, + justifyCenterVertical, + justifyBottom, + justifyStretchVertical, + justifySpaceBetweenVertical, +} from '@wordpress/icons'; const BLOCK_ALIGNMENTS_CONTROLS = { top: { - icon: alignTop, + icon: justifyTop, title: _x( 'Align top', 'Block vertical alignment setting' ), }, center: { - icon: alignCenter, + icon: justifyCenterVertical, title: _x( 'Align middle', 'Block vertical alignment setting' ), }, bottom: { - icon: alignBottom, + icon: justifyBottom, title: _x( 'Align bottom', 'Block vertical alignment setting' ), }, stretch: { - icon: alignStretch, + icon: justifyStretchVertical, title: _x( 'Stretch to fill', 'Block vertical alignment setting' ), }, 'space-between': { - icon: spaceBetween, + icon: justifySpaceBetweenVertical, title: _x( 'Space between', 'Block vertical alignment setting' ), }, }; diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index 1601f04ac0c22e..14eaec92b78c4d 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -130,11 +130,16 @@ export { default as image } from './library/image'; export { default as info } from './library/info'; export { default as insertAfter } from './library/insert-after'; export { default as insertBefore } from './library/insert-before'; +export { default as justifyBottom } from './library/justify-bottom'; export { default as justifyLeft } from './library/justify-left'; export { default as justifyCenter } from './library/justify-center'; +export { default as justifyCenterVertical } from './library/justify-center-vertical'; export { default as justifyRight } from './library/justify-right'; export { default as justifySpaceBetween } from './library/justify-space-between'; +export { default as justifySpaceBetweenVertical } from './library/justify-space-between-vertical'; export { default as justifyStretch } from './library/justify-stretch'; +export { default as justifyStretchVertical } from './library/justify-stretch-vertical'; +export { default as justifyTop } from './library/justify-top'; export { default as key } from './library/key'; export { default as keyboard } from './library/keyboard'; export { default as keyboardClose } from './library/keyboard-close'; diff --git a/packages/icons/src/library/justify-bottom.js b/packages/icons/src/library/justify-bottom.js new file mode 100644 index 00000000000000..25923e39dcc862 --- /dev/null +++ b/packages/icons/src/library/justify-bottom.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const justifyBottom = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M15 4H9v11h6V4zM4 18.5V20h16v-1.5H4z" /> + </SVG> +); + +export default justifyBottom; diff --git a/packages/icons/src/library/justify-center-vertical.js b/packages/icons/src/library/justify-center-vertical.js new file mode 100644 index 00000000000000..e3ab16fdc5d619 --- /dev/null +++ b/packages/icons/src/library/justify-center-vertical.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const justifyCenterVertical = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M20 11h-5V4H9v7H4v1.5h5V20h6v-7.5h5z" /> + </SVG> +); + +export default justifyCenterVertical; diff --git a/packages/icons/src/library/justify-space-between-vertical.js b/packages/icons/src/library/justify-space-between-vertical.js new file mode 100644 index 00000000000000..21a03134a4eb83 --- /dev/null +++ b/packages/icons/src/library/justify-space-between-vertical.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const justifySpaceBetweenVertical = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M7 4H17V8L7 8V4ZM7 16L17 16V20L7 20V16ZM20 11.25H4V12.75H20V11.25Z" /> + </SVG> +); + +export default justifySpaceBetweenVertical; diff --git a/packages/icons/src/library/justify-stretch-vertical.js b/packages/icons/src/library/justify-stretch-vertical.js new file mode 100644 index 00000000000000..29f976f4e717d3 --- /dev/null +++ b/packages/icons/src/library/justify-stretch-vertical.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const justifyStretchVertical = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M4 4L20 4L20 5.5L4 5.5L4 4ZM10 7L14 7L14 17L10 17L10 7ZM20 18.5L4 18.5L4 20L20 20L20 18.5Z" /> + </SVG> +); + +export default justifyStretchVertical; diff --git a/packages/icons/src/library/justify-top.js b/packages/icons/src/library/justify-top.js new file mode 100644 index 00000000000000..03c90a242546e3 --- /dev/null +++ b/packages/icons/src/library/justify-top.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const justifyTop = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M9 20h6V9H9v11zM4 4v1.5h16V4H4z" /> + </SVG> +); + +export default justifyTop; From acf661ce436d3e04d164dfb858853b4b796d2340 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:20:04 +0000 Subject: [PATCH 1294/1908] Bump reactivecircus/android-emulator-runner in the react-native group (#66095) Bumps the react-native group with 1 update: [reactivecircus/android-emulator-runner](https://github.com/reactivecircus/android-emulator-runner). Updates `reactivecircus/android-emulator-runner` from 2.32.0 to 2.33.0 - [Release notes](https://github.com/reactivecircus/android-emulator-runner/releases) - [Changelog](https://github.com/ReactiveCircus/android-emulator-runner/blob/main/CHANGELOG.md) - [Commits](https://github.com/reactivecircus/android-emulator-runner/compare/f0d1ed2dcad93c7479e8b2f2226c83af54494915...62dbb605bba737720e10b196cb4220d374026a6d) --- updated-dependencies: - dependency-name: reactivecircus/android-emulator-runner dependency-type: direct:production update-type: version-update:semver-minor dependency-group: react-native ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/rnmobile-android-runner.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index e9477dcf7c9bfb..df302926f20cef 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -60,7 +60,7 @@ jobs: - name: Create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@f0d1ed2dcad93c7479e8b2f2226c83af54494915 # v2.32.0 + uses: reactivecircus/android-emulator-runner@62dbb605bba737720e10b196cb4220d374026a6d # v2.33.0 with: api-level: ${{ matrix.api-level }} force-avd-creation: false @@ -71,7 +71,7 @@ jobs: script: echo "Generated AVD snapshot for caching." - name: Run tests - uses: reactivecircus/android-emulator-runner@f0d1ed2dcad93c7479e8b2f2226c83af54494915 # v2.32.0 + uses: reactivecircus/android-emulator-runner@62dbb605bba737720e10b196cb4220d374026a6d # v2.33.0 with: api-level: ${{ matrix.api-level }} force-avd-creation: false From b152b2190412a6b33bd5afee981f7e5e4ed44a15 Mon Sep 17 00:00:00 2001 From: Vipul Gupta <55375170+vipul0425@users.noreply.github.com> Date: Wed, 23 Oct 2024 11:54:49 +0530 Subject: [PATCH 1295/1908] Buttons: Fix the initial white space in nofollow rel (#66303) * fix: the initial white space in noFollow rel. * Added unit test to cover nofollow attribute without spacing --------- Co-authored-by: vipul0425 <vipulgupta003@git.wordpress.org> Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: franzaurus <franz00@git.wordpress.org> --- .../src/button/get-updated-link-attributes.js | 2 +- .../button/test/get-updated-link-attributes.js | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/button/get-updated-link-attributes.js b/packages/block-library/src/button/get-updated-link-attributes.js index 97b837a8be20bd..0e39a1815a3188 100644 --- a/packages/block-library/src/button/get-updated-link-attributes.js +++ b/packages/block-library/src/button/get-updated-link-attributes.js @@ -40,7 +40,7 @@ export function getUpdatedLinkAttributes( { if ( nofollow ) { updatedRel = updatedRel?.includes( NOFOLLOW_REL ) ? updatedRel - : updatedRel + ` ${ NOFOLLOW_REL }`; + : ( updatedRel + ` ${ NOFOLLOW_REL }` ).trim(); } else { const relRegex = new RegExp( `\\b${ NOFOLLOW_REL }\\s*`, 'g' ); updatedRel = updatedRel?.replace( relRegex, '' ).trim(); diff --git a/packages/block-library/src/button/test/get-updated-link-attributes.js b/packages/block-library/src/button/test/get-updated-link-attributes.js index af0c3da332110c..7349303d178b41 100644 --- a/packages/block-library/src/button/test/get-updated-link-attributes.js +++ b/packages/block-library/src/button/test/get-updated-link-attributes.js @@ -79,6 +79,21 @@ describe( 'getUpdatedLinkAttributes method', () => { expect( result.rel ).toEqual( 'rel_value nofollow' ); } ); + it( 'should correctly update link attributes with nofollow without spacing', () => { + const options = { + url: 'example.com', + opensInNewTab: false, + nofollow: true, + rel: '', + }; + + const result = getUpdatedLinkAttributes( options ); + + expect( result.url ).toEqual( 'http://example.com' ); + expect( result.linkTarget ).toEqual( undefined ); + expect( result.rel ).toEqual( 'nofollow' ); + } ); + it( 'should correctly handle rel with existing nofollow values and remove duplicates', () => { const options = { url: 'example.com', From 8d1f22268f9c40427e6404531bb3b065b836d05f Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 23 Oct 2024 08:20:36 +0100 Subject: [PATCH 1296/1908] Link Shortcut: Only trigger the link shortcut if there's a text selection (#66056) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- packages/format-library/src/link/index.js | 10 ++++- test/e2e/specs/editor/blocks/links.spec.js | 48 ++++------------------ 2 files changed, 16 insertions(+), 42 deletions(-) diff --git a/packages/format-library/src/link/index.js b/packages/format-library/src/link/index.js index ef7008451698ae..508ed4655a6695 100644 --- a/packages/format-library/src/link/index.js +++ b/packages/format-library/src/link/index.js @@ -170,9 +170,17 @@ function Edit( { openedBy?.el?.tagName === 'A' && openedBy?.action === 'click' ); + const hasSelection = ! isCollapsed( value ); + return ( <> - <RichTextShortcut type="primary" character="k" onUse={ addLink } /> + { hasSelection && ( + <RichTextShortcut + type="primary" + character="k" + onUse={ addLink } + /> + ) } <RichTextShortcut type="primaryShift" character="k" diff --git a/test/e2e/specs/editor/blocks/links.spec.js b/test/e2e/specs/editor/blocks/links.spec.js index 5206f5b6689e14..95e9c65b6ec190 100644 --- a/test/e2e/specs/editor/blocks/links.spec.js +++ b/test/e2e/specs/editor/blocks/links.spec.js @@ -121,38 +121,6 @@ test.describe( 'Links', () => { ).toHaveValue( '' ); } ); - test( `can be created without any text selected`, async ( { - page, - editor, - pageUtils, - } ) => { - // Create a block with some text. - await editor.insertBlock( { - name: 'core/paragraph', - } ); - await page.keyboard.type( 'This is Gutenberg: ' ); - - // Press Cmd+K to insert a link. - await pageUtils.pressKeys( 'primary+K' ); - - // Type a URL. - await page.keyboard.type( 'https://wordpress.org/gutenberg' ); - - // Press Enter to apply the link. - await pageUtils.pressKeys( 'Enter' ); - - // A link with the URL as its text should have been inserted. - await expect.poll( editor.getBlocks ).toMatchObject( [ - { - name: 'core/paragraph', - attributes: { - content: - 'This is Gutenberg: <a href="https://wordpress.org/gutenberg">https://wordpress.org/gutenberg</a>', - }, - }, - ] ); - } ); - test( `will automatically create a link if selected text is a valid HTTP based URL`, async ( { page, editor, @@ -341,7 +309,7 @@ test.describe( 'Links', () => { // Make a collapsed selection inside the link. await pageUtils.pressKeys( 'ArrowLeft' ); await pageUtils.pressKeys( 'ArrowRight' ); - await pageUtils.pressKeys( 'primary+k' ); + await editor.clickBlockToolbarButton( 'Link' ); const linkPopover = LinkUtils.getLinkPopover(); await linkPopover.getByRole( 'button', { name: 'Edit' } ).click(); @@ -485,9 +453,8 @@ test.describe( 'Links', () => { await pageUtils.pressKeys( 'End' ); await expect( linkPopover ).toBeHidden(); - // Move the caret back into the link text and the link popover - // should not be displayed. - await pageUtils.pressKeys( 'ArrowLeft' ); + // Move the caret back into and selects the link text. + await pageUtils.pressKeys( 'shiftAlt+ArrowLeft' ); await expect( linkPopover ).toBeHidden(); // Switch the Link UI into "Edit" mode via keyboard shortcut @@ -1015,7 +982,6 @@ test.describe( 'Links', () => { test( 'should not display text input when initially creating the link', async ( { page, editor, - pageUtils, LinkUtils, } ) => { // Create a block with some text. @@ -1024,8 +990,8 @@ test.describe( 'Links', () => { } ); await page.keyboard.type( 'This is Gutenberg: ' ); - // Press Cmd+K to insert a link. - await pageUtils.pressKeys( 'primary+k' ); + // Insert a link + await editor.clickBlockToolbarButton( 'Link' ); const linkPopover = LinkUtils.getLinkPopover(); @@ -1048,8 +1014,8 @@ test.describe( 'Links', () => { // Make a collapsed selection inside the link. This is used // as a stress test to ensure we can find the link text from a // collapsed RichTextValue that contains a link format. - await pageUtils.pressKeys( 'ArrowLeft' ); - await pageUtils.pressKeys( 'ArrowRight' ); + await pageUtils.pressKeys( 'End' ); + await pageUtils.pressKeys( 'shiftAlt+ArrowLeft' ); await pageUtils.pressKeys( 'primary+k' ); const linkPopover = LinkUtils.getLinkPopover(); From 6184562abe1cf362164cd15e9853b45e7955a488 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 23 Oct 2024 16:22:56 +0900 Subject: [PATCH 1297/1908] Interface: Remove duplicate 'withComplementaryAreaContext' file (#66348) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../interface/complementary-area-context/index.js | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 packages/interface/complementary-area-context/index.js diff --git a/packages/interface/complementary-area-context/index.js b/packages/interface/complementary-area-context/index.js deleted file mode 100644 index bdfc6869e1e51d..00000000000000 --- a/packages/interface/complementary-area-context/index.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * WordPress dependencies - */ -import { withPluginContext } from '@wordpress/plugins'; - -export default withPluginContext( ( context, ownProps ) => { - return { - icon: ownProps.icon || context.icon, - identifier: - ownProps.identifier || `${ context.name }/${ ownProps.name }`, - }; -} ); From 9421bc9fd54d7765c3d785cda8f4a555f597f17d Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 23 Oct 2024 16:24:23 +0900 Subject: [PATCH 1298/1908] Editor: Use plugin context hook in 'PluginPreviewMenuItem' (#66350) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/editor/README.md | 4 +-- .../plugin-preview-menu-item/index.js | 27 ++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/packages/editor/README.md b/packages/editor/README.md index 2acb98ef13642c..bcd1727e046d07 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -878,9 +878,9 @@ function onPreviewClick() { } const ExternalPreviewMenuItem = () => ( - <PreviewDropdownMenuItem icon={ external } onClick={ onPreviewClick }> + <PluginPreviewMenuItem icon={ external } onClick={ onPreviewClick }> { __( 'Preview in new tab' ) } - </PreviewDropdownMenuItem> + </PluginPreviewMenuItem> ); registerPlugin( 'external-preview-menu-item', { render: ExternalPreviewMenuItem, diff --git a/packages/editor/src/components/plugin-preview-menu-item/index.js b/packages/editor/src/components/plugin-preview-menu-item/index.js index 422248e17b88e1..8038da04595aae 100644 --- a/packages/editor/src/components/plugin-preview-menu-item/index.js +++ b/packages/editor/src/components/plugin-preview-menu-item/index.js @@ -1,9 +1,8 @@ /** * WordPress dependencies */ -import { compose } from '@wordpress/compose'; import { MenuItem } from '@wordpress/components'; -import { withPluginContext } from '@wordpress/plugins'; +import { usePluginContext } from '@wordpress/plugins'; import { ActionItem } from '@wordpress/interface'; /** @@ -27,12 +26,12 @@ import { ActionItem } from '@wordpress/interface'; * } * * const ExternalPreviewMenuItem = () => ( - * <PreviewDropdownMenuItem + * <PluginPreviewMenuItem * icon={ external } * onClick={ onPreviewClick } * > * { __( 'Preview in new tab' ) } - * </PreviewDropdownMenuItem> + * </PluginPreviewMenuItem> * ); * registerPlugin( 'external-preview-menu-item', { * render: ExternalPreviewMenuItem, @@ -41,12 +40,14 @@ import { ActionItem } from '@wordpress/interface'; * * @return {Component} The rendered menu item component. */ -export default compose( - withPluginContext( ( context, ownProps ) => { - return { - as: ownProps.as ?? MenuItem, - icon: ownProps.icon || context.icon, - name: 'core/plugin-preview-menu', - }; - } ) -)( ActionItem ); +export default function PluginPreviewMenuItem( props ) { + const context = usePluginContext(); + return ( + <ActionItem + name="core/plugin-preview-menu" + as={ props.as ?? MenuItem } + icon={ props.icon || context.icon } + { ...props } + /> + ); +} From f57081eb7a73044f06dc5d784da5951c276d18d9 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 23 Oct 2024 16:26:59 +0900 Subject: [PATCH 1299/1908] Editor: Use plugin context hook in 'PluginMoreMenuItem' (#66351) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../components/plugin-more-menu-item/index.js | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/editor/src/components/plugin-more-menu-item/index.js b/packages/editor/src/components/plugin-more-menu-item/index.js index 1382aad29c433c..28173c24ebcefa 100644 --- a/packages/editor/src/components/plugin-more-menu-item/index.js +++ b/packages/editor/src/components/plugin-more-menu-item/index.js @@ -1,9 +1,8 @@ /** * WordPress dependencies */ -import { compose } from '@wordpress/compose'; import { MenuItem } from '@wordpress/components'; -import { withPluginContext } from '@wordpress/plugins'; +import { usePluginContext } from '@wordpress/plugins'; import { ActionItem } from '@wordpress/interface'; /** @@ -62,12 +61,14 @@ import { ActionItem } from '@wordpress/interface'; * * @return {Component} The component to be rendered. */ -export default compose( - withPluginContext( ( context, ownProps ) => { - return { - as: ownProps.as ?? MenuItem, - icon: ownProps.icon || context.icon, - name: 'core/plugin-more-menu', - }; - } ) -)( ActionItem ); +export default function PluginMoreMenuItem( props ) { + const context = usePluginContext(); + return ( + <ActionItem + name="core/plugin-more-menu" + as={ props.as ?? MenuItem } + icon={ props.icon || context.icon } + { ...props } + /> + ); +} From 8a7a381d8a6de41cd4a1af5ad4f47ad0ea53f1d3 Mon Sep 17 00:00:00 2001 From: Ahmar Zaidi <71930390+AhmarZaidi@users.noreply.github.com> Date: Wed, 23 Oct 2024 13:31:06 +0530 Subject: [PATCH 1300/1908] Remove toggle verb from post list data views (#66334) Co-authored-by: AhmarZaidi <ahmarzaidi@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- packages/edit-site/src/components/post-list/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 6738310ff6021b..3efe3361f3c51e 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -412,7 +412,7 @@ export default function PostList( { postType } ) { size="compact" isPressed={ quickEdit } icon={ drawerRight } - label={ __( 'Toggle details panel' ) } + label={ __( 'Details panel' ) } onClick={ () => { history.push( { ...location.params, From a02ce46b34fd34dfdd8bd86ddcc86d2df39c2383 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 23 Oct 2024 09:35:46 +0100 Subject: [PATCH 1301/1908] Zoom Out: Use the zoom-level value to scale the iframe (#66280) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- .../src/components/block-canvas/index.js | 8 ++++---- packages/block-editor/src/components/iframe/index.js | 2 +- packages/block-editor/src/hooks/use-zoom-out.js | 4 ++-- packages/block-editor/src/store/private-selectors.js | 12 +++++++++++- .../editor/src/components/zoom-out-toggle/index.js | 2 +- storybook/stories/playground/index.story.js | 7 +++++-- storybook/stories/playground/zoom-out/index.js | 10 +++++----- 7 files changed, 29 insertions(+), 16 deletions(-) diff --git a/packages/block-editor/src/components/block-canvas/index.js b/packages/block-editor/src/components/block-canvas/index.js index cce3223acd9695..c399f38054ed4d 100644 --- a/packages/block-editor/src/components/block-canvas/index.js +++ b/packages/block-editor/src/components/block-canvas/index.js @@ -40,14 +40,14 @@ export function ExperimentalBlockCanvas( { const clearerRef = useBlockSelectionClearer(); const localRef = useRef(); const contentRef = useMergeRefs( [ contentRefProp, clearerRef, localRef ] ); - const isZoomedOut = useSelect( - ( select ) => unlock( select( blockEditorStore ) ).isZoomOut(), + const zoomLevel = useSelect( + ( select ) => unlock( select( blockEditorStore ) ).getZoomLevel(), [] ); const zoomOutIframeProps = - isZoomedOut && ! isTabletViewport + zoomLevel !== 100 && ! isTabletViewport ? { - scale: 'default', + scale: zoomLevel, frameSize: '40px', } : {}; diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index 9fc9fd4be64bdd..85e1f12a7c0d63 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -354,7 +354,7 @@ function Iframe( { // but calc( 100px / 2px ) is not. iframeDocument.documentElement.style.setProperty( '--wp-block-editor-iframe-zoom-out-scale', - scale === 'default' + scale === 'auto-scaled' ? ( Math.min( containerWidth, maxWidth ) - parseInt( frameSize ) * 2 ) / scaleContainerWidth diff --git a/packages/block-editor/src/hooks/use-zoom-out.js b/packages/block-editor/src/hooks/use-zoom-out.js index 914886497bbb38..bc2d325e81d61a 100644 --- a/packages/block-editor/src/hooks/use-zoom-out.js +++ b/packages/block-editor/src/hooks/use-zoom-out.js @@ -28,7 +28,7 @@ export function useZoomOut( zoomOut = true ) { return () => { if ( isZoomOutOnMount && isWideViewport ) { - setZoomLevel( 50 ); + setZoomLevel( 'auto-scaled' ); } else { resetZoomLevel(); } @@ -37,7 +37,7 @@ export function useZoomOut( zoomOut = true ) { useEffect( () => { if ( zoomOut && isWideViewport ) { - setZoomLevel( 50 ); + setZoomLevel( 'auto-scaled' ); } else { resetZoomLevel(); } diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index dff5dc0184a4d2..525aca4c236cbc 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -592,7 +592,17 @@ export function getSectionRootClientId( state ) { * @return {boolean} Whether the editor is zoomed. */ export function isZoomOut( state ) { - return state.zoomLevel < 100; + return state.zoomLevel === 'auto-scaled' || state.zoomLevel < 100; +} + +/** + * Returns whether the zoom level. + * + * @param {Object} state Global application state. + * @return {number|"auto-scaled"} Zoom level. + */ +export function getZoomLevel( state ) { + return state.zoomLevel; } /** diff --git a/packages/editor/src/components/zoom-out-toggle/index.js b/packages/editor/src/components/zoom-out-toggle/index.js index e07cb6ac92c833..619cc06c689c0b 100644 --- a/packages/editor/src/components/zoom-out-toggle/index.js +++ b/packages/editor/src/components/zoom-out-toggle/index.js @@ -31,7 +31,7 @@ const ZoomOutToggle = ( { disabled } ) => { if ( isZoomOut ) { resetZoomLevel(); } else { - setZoomLevel( 50 ); + setZoomLevel( 'auto-scaled' ); } }; diff --git a/storybook/stories/playground/index.story.js b/storybook/stories/playground/index.story.js index 699f3a295e9df8..eab17455c2954e 100644 --- a/storybook/stories/playground/index.story.js +++ b/storybook/stories/playground/index.story.js @@ -37,10 +37,13 @@ UndoRedo.parameters = { sourceLink: 'storybook/stories/playground/with-undo-redo/index.js', }; -export const ZoomOut = () => { - return <EditorZoomOut />; +export const ZoomOut = ( props ) => { + return <EditorZoomOut { ...props } />; }; ZoomOut.parameters = { sourceLink: 'storybook/stories/playground/zoom-out/index.js', }; +ZoomOut.argTypes = { + zoomLevel: { control: { type: 'range', min: 10, max: 100, step: 5 } }, +}; diff --git a/storybook/stories/playground/zoom-out/index.js b/storybook/stories/playground/zoom-out/index.js index fae405c6b0ff30..4f2efcf48523e8 100644 --- a/storybook/stories/playground/zoom-out/index.js +++ b/storybook/stories/playground/zoom-out/index.js @@ -27,17 +27,17 @@ const { unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( '@wordpress/edit-site' ); -function EnableZoomOut() { +function EnableZoomOut( { zoomLevel } ) { const { setZoomLevel } = unlock( useDispatch( blockEditorStore ) ); useEffect( () => { - setZoomLevel( 50 ); - }, [ setZoomLevel ] ); + setZoomLevel( zoomLevel ? zoomLevel / 100 : 'auto-scaled' ); + }, [ setZoomLevel, zoomLevel ] ); return null; } -export default function EditorZoomOut() { +export default function EditorZoomOut( { zoomLevel } ) { const [ blocks, updateBlocks ] = useState( [] ); useEffect( () => { @@ -57,7 +57,7 @@ export default function EditorZoomOut() { onInput={ updateBlocks } onChange={ updateBlocks } > - <EnableZoomOut /> + <EnableZoomOut zoomLevel={ zoomLevel } /> <BlockCanvas height="500px" styles={ editorStyles }> <style>{ contentCss }</style> <BlockList /> From 4440247e97db0c3ad220d1cad07fb98156a5418b Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 23 Oct 2024 09:52:55 +0100 Subject: [PATCH 1302/1908] Quick Edit: Fix JS error when bulk editing pages (#66358) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- packages/edit-site/src/components/post-edit/index.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 0ec63589d97673..8d7e09c702047e 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -65,13 +65,18 @@ function PostEditForm( { postType, postId } ) { const onChange = ( edits ) => { for ( const id of ids ) { if ( + edits.status && edits.status !== 'future' && record.status === 'future' && new Date( record.date ) > new Date() ) { edits.date = null; } - if ( edits.status === 'private' && record.password ) { + if ( + edits.status && + edits.status === 'private' && + record.password + ) { edits.password = ''; } editEntityRecord( 'postType', postType, id, edits ); From abe37675d4e25f35828e780c49588e01d26f4e31 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 23 Oct 2024 09:54:55 +0100 Subject: [PATCH 1303/1908] Zoom Out: Remove double click to exit hook from the block-editor package (#66335) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- .../src/components/block-list/use-block-props/index.js | 2 -- packages/block-editor/src/private-apis.js | 2 -- packages/editor/src/components/visual-editor/index.js | 2 +- .../src/components/visual-editor}/use-zoom-out-mode-exit.js | 4 ++-- 4 files changed, 3 insertions(+), 7 deletions(-) rename packages/{block-editor/src/components/block-list/use-block-props => editor/src/components/visual-editor}/use-zoom-out-mode-exit.js (90%) diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index 45fc1d9eb5ea12..25b9a21f0d2867 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -25,7 +25,6 @@ import { } from '../../block-edit/context'; import { useFocusHandler } from './use-focus-handler'; import { useEventHandlers } from './use-selected-block-event-handlers'; -import { useZoomOutModeExit } from './use-zoom-out-mode-exit'; import { useBlockRefProvider } from './use-block-refs'; import { useIntersectionObserver } from './use-intersection-observer'; import { useScrollIntoView } from './use-scroll-into-view'; @@ -112,7 +111,6 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { useBlockRefProvider( clientId ), useFocusHandler( clientId ), useEventHandlers( { clientId, isSelected } ), - useZoomOutModeExit(), useIsHovered( { clientId } ), useIntersectionObserver(), useMovingAnimation( { triggerAnimationOnChange: index, clientId } ), diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 98dd326a3ebb34..7205bef5798ec1 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -32,7 +32,6 @@ import { usesContextKey } from './components/rich-text/format-edit'; import { ExperimentalBlockCanvas } from './components/block-canvas'; import { getDuotoneFilter } from './components/duotone/utils'; import { useFlashEditableBlocks } from './components/use-flash-editable-blocks'; -import { useZoomOutModeExit } from './components/block-list/use-block-props/use-zoom-out-mode-exit'; import { selectBlockPatternsKey, reusableBlocksSelectKey, @@ -79,7 +78,6 @@ lock( privateApis, { TextAlignmentControl, usesContextKey, useFlashEditableBlocks, - useZoomOutModeExit, globalStylesDataKey, globalStylesLinksDataKey, selectBlockPatternsKey, diff --git a/packages/editor/src/components/visual-editor/index.js b/packages/editor/src/components/visual-editor/index.js index 6462c4a3f83682..133057d9f388f1 100644 --- a/packages/editor/src/components/visual-editor/index.js +++ b/packages/editor/src/components/visual-editor/index.js @@ -41,6 +41,7 @@ import { TEMPLATE_PART_POST_TYPE, TEMPLATE_POST_TYPE, } from '../../store/constants'; +import { useZoomOutModeExit } from './use-zoom-out-mode-exit'; const { LayoutStyle, @@ -48,7 +49,6 @@ const { useLayoutStyles, ExperimentalBlockCanvas: BlockCanvas, useFlashEditableBlocks, - useZoomOutModeExit, } = unlock( blockEditorPrivateApis ); /** diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js b/packages/editor/src/components/visual-editor/use-zoom-out-mode-exit.js similarity index 90% rename from packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js rename to packages/editor/src/components/visual-editor/use-zoom-out-mode-exit.js index d77af3ef89c1ec..5a2bb49dbb832e 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js +++ b/packages/editor/src/components/visual-editor/use-zoom-out-mode-exit.js @@ -3,12 +3,12 @@ */ import { useSelect, useDispatch } from '@wordpress/data'; import { useRefEffect } from '@wordpress/compose'; +import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Internal dependencies */ -import { store as blockEditorStore } from '../../../store'; -import { unlock } from '../../../lock-unlock'; +import { unlock } from '../../lock-unlock'; /** * Allows Zoom Out mode to be exited by double clicking in the selected block. From 0433d90352e17f164ed417d21a3c802231d3bf97 Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Wed, 23 Oct 2024 12:43:44 +0200 Subject: [PATCH 1304/1908] Use npm workspaces for packages (second attempt) (#66272) Update package management to use npm workspaces instead of lerna. Lerna is obsolete for many repository management operations, such as dependency installation or script running. All of these are supported by npm now. Lerna continues to be used for publishing flows to ensure the appropriate dependencies are updated and published with the correct versions. The hope is that this simplfies dependendy management and maintains a more sane dependency tree. Dependency management has become increasingly difficult as Gutenberg has grown. --- This was originally merged in 4693c0f9942f11f48e0912db378b1b9e2fbf4af0. It was reverted in order to merge it at a more time. --- Co-authored-by: t-hamano wildworks@git.wordpress.org Co-authored-by: sirreal jonsurrell@git.wordpress.org Co-authored-by: gziolo gziolo@git.wordpress.org Co-authored-by: ciampo mciampini@git.wordpress.org Co-authored-by: jsnajdr jsnajdr@git.wordpress.org Co-authored-by: yusuke-omae omaeyusuke@git.wordpress.org Co-authored-by: kevin940726 kevin940726@git.wordpress.org --- bin/check-licenses.mjs | 69 + docs/contributors/code/managing-packages.md | 6 +- package-lock.json | 5116 +++++++---------- package.json | 111 +- packages/README.md | 41 +- packages/a11y/.npmrc | 1 - packages/a11y/package.json | 7 +- packages/annotations/.npmrc | 1 - packages/annotations/package.json | 11 +- packages/api-fetch/.npmrc | 1 - packages/api-fetch/package.json | 7 +- packages/autop/.npmrc | 1 - packages/autop/package.json | 3 +- .../babel-plugin-import-jsx-pragma/.npmrc | 1 - packages/babel-plugin-makepot/.npmrc | 1 - packages/babel-preset-default/.npmrc | 1 - packages/babel-preset-default/package.json | 4 +- packages/base-styles/.npmrc | 1 - packages/blob/.npmrc | 1 - packages/blob/package.json | 3 +- packages/block-directory/.npmrc | 1 - packages/block-directory/package.json | 39 +- packages/block-editor/.npmrc | 1 - packages/block-editor/package.json | 63 +- packages/block-library/.npmrc | 1 - packages/block-library/package.json | 69 +- .../block-serialization-default-parser/.npmrc | 1 - .../package.json | 3 +- .../block-serialization-spec-parser/.npmrc | 1 - .../package.json | 3 +- packages/blocks/.npmrc | 1 - packages/blocks/package.json | 33 +- packages/browserslist-config/.npmrc | 1 - packages/commands/.npmrc | 0 packages/commands/package.json | 17 +- packages/components/.npmrc | 1 - packages/components/package.json | 37 +- packages/compose/.npmrc | 1 - packages/compose/package.json | 17 +- packages/core-commands/.npmrc | 1 - packages/core-commands/package.json | 29 +- packages/core-data/.npmrc | 1 - packages/core-data/package.json | 35 +- .../create-block-interactive-template/.npmrc | 1 - .../create-block-tutorial-template/.npmrc | 1 - packages/create-block/.npmrc | 1 - packages/create-block/package.json | 2 +- packages/customize-widgets/.npmrc | 1 - packages/customize-widgets/package.json | 45 +- packages/data-controls/package.json | 9 +- packages/data/.npmrc | 1 - packages/data/package.json | 17 +- packages/dataviews/.npmrc | 1 - packages/dataviews/package.json | 21 +- packages/date/.npmrc | 1 - packages/date/package.json | 5 +- packages/deprecated/.npmrc | 1 - packages/deprecated/package.json | 5 +- packages/docgen/.npmrc | 1 - packages/dom-ready/.npmrc | 1 - packages/dom-ready/package.json | 3 +- packages/dom/.npmrc | 1 - packages/dom/package.json | 5 +- packages/e2e-test-utils-playwright/.npmrc | 1 - packages/e2e-test-utils/.npmrc | 1 - packages/e2e-test-utils/package.json | 6 +- packages/e2e-tests/.npmrc | 1 - packages/e2e-tests/package.json | 14 +- packages/edit-post/.npmrc | 1 - packages/edit-post/package.json | 61 +- packages/edit-site/.npmrc | 1 - packages/edit-site/package.json | 81 +- packages/edit-widgets/.npmrc | 1 - packages/edit-widgets/package.json | 57 +- packages/editor/.npmrc | 1 - packages/editor/package.json | 73 +- packages/element/.npmrc | 1 - packages/element/package.json | 5 +- packages/env/.npmrc | 1 - packages/escape-html/.npmrc | 1 - packages/escape-html/package.json | 3 +- packages/eslint-plugin/.npmrc | 1 - packages/eslint-plugin/package.json | 4 +- packages/fields/.npmrc | 1 - packages/fields/package.json | 41 +- packages/format-library/.npmrc | 1 - packages/format-library/package.json | 27 +- packages/hooks/.npmrc | 1 - packages/hooks/package.json | 3 +- packages/html-entities/.npmrc | 1 - packages/html-entities/package.json | 3 +- packages/i18n/.npmrc | 1 - packages/i18n/package.json | 5 +- packages/icons/.npmrc | 1 - packages/icons/package.json | 7 +- packages/interactivity-router/.npmrc | 1 - packages/interactivity-router/package.json | 4 +- packages/interactivity/.npmrc | 1 - packages/interface/.npmrc | 1 - packages/interface/package.json | 27 +- packages/is-shallow-equal/.npmrc | 1 - packages/is-shallow-equal/package.json | 3 +- packages/jest-console/.npmrc | 1 - packages/jest-preset-default/.npmrc | 1 - packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/.npmrc | 1 - packages/keyboard-shortcuts/.npmrc | 0 packages/keyboard-shortcuts/package.json | 9 +- packages/keycodes/.npmrc | 1 - packages/keycodes/package.json | 5 +- packages/lazy-import/.npmrc | 1 - packages/list-reusable-blocks/.npmrc | 1 - packages/list-reusable-blocks/package.json | 15 +- packages/media-utils/.npmrc | 1 - packages/media-utils/package.json | 11 +- packages/notices/.npmrc | 1 - packages/notices/package.json | 7 +- packages/npm-package-json-lint-config/.npmrc | 1 - packages/nux/.npmrc | 1 - packages/nux/package.json | 17 +- packages/patterns/.npmrc | 1 - packages/patterns/package.json | 31 +- packages/plugins/.npmrc | 1 - packages/plugins/package.json | 15 +- packages/postcss-plugins-preset/.npmrc | 1 - packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/.npmrc | 1 - packages/preferences-persistence/.npmrc | 1 - packages/preferences-persistence/package.json | 5 +- packages/preferences/.npmrc | 1 - packages/preferences/package.json | 21 +- packages/prettier-config/.npmrc | 1 - packages/primitives/.npmrc | 1 - packages/primitives/package.json | 5 +- packages/priority-queue/.npmrc | 1 - packages/priority-queue/package.json | 3 +- packages/private-apis/package.json | 3 +- packages/project-management-automation/.npmrc | 1 - packages/react-i18n/package.json | 7 +- packages/react-native-aztec/.npmrc | 1 - packages/react-native-aztec/package.json | 4 +- packages/react-native-bridge/.npmrc | 1 - packages/react-native-bridge/package.json | 2 +- packages/react-native-editor/.npmrc | 1 - packages/react-native-editor/package.json | 24 +- .../readable-js-assets-webpack-plugin/.npmrc | 1 - packages/redux-routine/.npmrc | 1 - packages/redux-routine/package.json | 3 +- packages/report-flaky-tests/.npmrc | 1 - packages/reusable-blocks/.npmrc | 1 - packages/reusable-blocks/package.json | 25 +- packages/rich-text/.npmrc | 1 - packages/rich-text/package.json | 19 +- packages/router/.npmrc | 0 packages/router/package.json | 9 +- packages/scripts/.npmrc | 1 - packages/scripts/package.json | 20 +- packages/server-side-render/.npmrc | 1 - packages/server-side-render/package.json | 21 +- packages/shortcode/.npmrc | 1 - packages/shortcode/package.json | 3 +- packages/style-engine/.npmrc | 1 - packages/style-engine/package.json | 3 +- packages/stylelint-config/.npmrc | 1 - packages/sync/.npmrc | 1 - packages/sync/package.json | 5 +- packages/token-list/.npmrc | 1 - packages/token-list/package.json | 3 +- packages/undo-manager/.npmrc | 1 - packages/undo-manager/package.json | 5 +- packages/url/.npmrc | 1 - packages/url/package.json | 3 +- packages/viewport/.npmrc | 1 - packages/viewport/package.json | 9 +- packages/vips/package.json | 3 +- packages/warning/.npmrc | 1 - packages/warning/package.json | 3 +- packages/widgets/.npmrc | 1 - packages/widgets/package.json | 25 +- packages/wordcount/.npmrc | 1 - packages/wordcount/package.json | 3 +- tools/webpack/packages.js | 38 +- tools/webpack/script-modules.js | 39 +- 183 files changed, 2721 insertions(+), 4058 deletions(-) create mode 100755 bin/check-licenses.mjs delete mode 100644 packages/a11y/.npmrc delete mode 100644 packages/annotations/.npmrc delete mode 100644 packages/api-fetch/.npmrc delete mode 100644 packages/autop/.npmrc delete mode 100644 packages/babel-plugin-import-jsx-pragma/.npmrc delete mode 100644 packages/babel-plugin-makepot/.npmrc delete mode 100644 packages/babel-preset-default/.npmrc delete mode 100644 packages/base-styles/.npmrc delete mode 100644 packages/blob/.npmrc delete mode 100644 packages/block-directory/.npmrc delete mode 100644 packages/block-editor/.npmrc delete mode 100644 packages/block-library/.npmrc delete mode 100644 packages/block-serialization-default-parser/.npmrc delete mode 100644 packages/block-serialization-spec-parser/.npmrc delete mode 100644 packages/blocks/.npmrc delete mode 100644 packages/browserslist-config/.npmrc delete mode 100644 packages/commands/.npmrc delete mode 100644 packages/components/.npmrc delete mode 100644 packages/compose/.npmrc delete mode 100644 packages/core-commands/.npmrc delete mode 100644 packages/core-data/.npmrc delete mode 100644 packages/create-block-interactive-template/.npmrc delete mode 100644 packages/create-block-tutorial-template/.npmrc delete mode 100644 packages/create-block/.npmrc delete mode 100644 packages/customize-widgets/.npmrc delete mode 100644 packages/data/.npmrc delete mode 100644 packages/dataviews/.npmrc delete mode 100644 packages/date/.npmrc delete mode 100644 packages/deprecated/.npmrc delete mode 100644 packages/docgen/.npmrc delete mode 100644 packages/dom-ready/.npmrc delete mode 100644 packages/dom/.npmrc delete mode 100644 packages/e2e-test-utils-playwright/.npmrc delete mode 100644 packages/e2e-test-utils/.npmrc delete mode 100644 packages/e2e-tests/.npmrc delete mode 100644 packages/edit-post/.npmrc delete mode 100644 packages/edit-site/.npmrc delete mode 100644 packages/edit-widgets/.npmrc delete mode 100644 packages/editor/.npmrc delete mode 100644 packages/element/.npmrc delete mode 100644 packages/env/.npmrc delete mode 100644 packages/escape-html/.npmrc delete mode 100644 packages/eslint-plugin/.npmrc delete mode 100644 packages/fields/.npmrc delete mode 100644 packages/format-library/.npmrc delete mode 100644 packages/hooks/.npmrc delete mode 100644 packages/html-entities/.npmrc delete mode 100644 packages/i18n/.npmrc delete mode 100644 packages/icons/.npmrc delete mode 100644 packages/interactivity-router/.npmrc delete mode 100644 packages/interactivity/.npmrc delete mode 100644 packages/interface/.npmrc delete mode 100644 packages/is-shallow-equal/.npmrc delete mode 100644 packages/jest-console/.npmrc delete mode 100644 packages/jest-preset-default/.npmrc delete mode 100644 packages/jest-puppeteer-axe/.npmrc delete mode 100644 packages/keyboard-shortcuts/.npmrc delete mode 100644 packages/keycodes/.npmrc delete mode 100644 packages/lazy-import/.npmrc delete mode 100644 packages/list-reusable-blocks/.npmrc delete mode 100644 packages/media-utils/.npmrc delete mode 100644 packages/notices/.npmrc delete mode 100644 packages/npm-package-json-lint-config/.npmrc delete mode 100644 packages/nux/.npmrc delete mode 100644 packages/patterns/.npmrc delete mode 100644 packages/plugins/.npmrc delete mode 100644 packages/postcss-plugins-preset/.npmrc delete mode 100644 packages/postcss-themes/.npmrc delete mode 100644 packages/preferences-persistence/.npmrc delete mode 100644 packages/preferences/.npmrc delete mode 100644 packages/prettier-config/.npmrc delete mode 100644 packages/primitives/.npmrc delete mode 100644 packages/priority-queue/.npmrc delete mode 100644 packages/project-management-automation/.npmrc delete mode 100644 packages/react-native-aztec/.npmrc delete mode 100644 packages/react-native-bridge/.npmrc delete mode 100644 packages/react-native-editor/.npmrc delete mode 100644 packages/readable-js-assets-webpack-plugin/.npmrc delete mode 100644 packages/redux-routine/.npmrc delete mode 100644 packages/report-flaky-tests/.npmrc delete mode 100644 packages/reusable-blocks/.npmrc delete mode 100644 packages/rich-text/.npmrc delete mode 100644 packages/router/.npmrc delete mode 100644 packages/scripts/.npmrc delete mode 100644 packages/server-side-render/.npmrc delete mode 100644 packages/shortcode/.npmrc delete mode 100644 packages/style-engine/.npmrc delete mode 100644 packages/stylelint-config/.npmrc delete mode 100644 packages/sync/.npmrc delete mode 100644 packages/token-list/.npmrc delete mode 100644 packages/undo-manager/.npmrc delete mode 100644 packages/url/.npmrc delete mode 100644 packages/viewport/.npmrc delete mode 100644 packages/warning/.npmrc delete mode 100644 packages/widgets/.npmrc delete mode 100644 packages/wordcount/.npmrc diff --git a/bin/check-licenses.mjs b/bin/check-licenses.mjs new file mode 100755 index 00000000000000..458590e696a9fd --- /dev/null +++ b/bin/check-licenses.mjs @@ -0,0 +1,69 @@ +#!/usr/bin/env node + +/** + * External dependencies + */ +import { spawnSync } from 'node:child_process'; + +/** + * Internal dependencies + */ +import { checkDepsInTree } from '../packages/scripts/utils/license.js'; + +const ignored = [ '@ampproject/remapping' ]; + +/* + * `wp-scripts check-licenses` uses prod and dev dependencies of the package to scan for dependencies. With npm workspaces, workspace packages (the @wordpress/* packages) are not listed in the main package json and this approach does not work. + * + * Instead, work from an npm query that uses some custom information in package.json files to declare packages that are shipped with WordPress (and must be GPLv2 compatible) or other files that may use more permissive licenses. + */ + +/** + * @typedef PackageInfo + * @property {string} name Package name. + */ + +/** @type {ReadonlyArray<PackageInfo>} */ +const workspacePackages = JSON.parse( + spawnSync( + 'npm', + [ + 'query', + '.workspace:attr([wpScript]), .workspace:attr([wpScriptModuleExports])', + ], + /* + * Set the max buffer to ~157MB, since the output size for + * prod is ~21 MB and dev is ~110 MB + */ + { maxBuffer: 1024 * 1024 * 150 } + ).stdout +); + +const packageNames = workspacePackages.map( ( { name } ) => name ); + +const dependenciesToProcess = JSON.parse( + spawnSync( + 'npm', + [ + 'ls', + '--json', + '--long', + '--all', + '--lockfile-only', + '--omit=dev', + ...packageNames.map( + ( packageName ) => `--workspace=${ packageName }` + ), + ], + /* + * Set the max buffer to ~157MB, since the output size for + * prod is ~21 MB and dev is ~110 MB + */ + { maxBuffer: 1024 * 1024 * 150 } + ).stdout +).dependencies; + +checkDepsInTree( dependenciesToProcess, { + ignored, + gpl2: true, +} ); diff --git a/docs/contributors/code/managing-packages.md b/docs/contributors/code/managing-packages.md index bfea8fed81242b..8ad0266b1482bf 100644 --- a/docs/contributors/code/managing-packages.md +++ b/docs/contributors/code/managing-packages.md @@ -1,11 +1,7 @@ # Managing Packages -This repository uses [monorepo] to manage WordPress modules and publish them with [lerna] as packages to [npm]. This enforces certain steps in the workflow which are described in details in [packages](https://github.com/WordPress/gutenberg/blob/HEAD/packages/README.md) documentation. +This repository uses [npm workspaces](https://docs.npmjs.com/cli/v10/using-npm/workspaces) to manage WordPress packages and [lerna](https://lerna.js.org/) to publish them to [npm](https://www.npmjs.com/). This enforces certain steps in the workflow which are described in details in [packages](https://github.com/WordPress/gutenberg/blob/HEAD/packages/README.md) documentation. Maintaining dozens of npm packages is difficult—it can be tough to keep track of changes. That's why we use `CHANGELOG.md` files for each package to simplify the release process. As a contributor, you should add an entry to the aforementioned file each time you contribute adding production code as described in [Maintaining Changelogs](https://github.com/WordPress/gutenberg/blob/HEAD/packages/README.md#maintaining-changelogs) section. Publishing WordPress packages to npm is automated by synchronizing it with the bi-weekly Gutenberg plugin RC1 release. You can learn more about this process and other ways to publish new versions of npm packages in the [Gutenberg Release Process document](/docs/contributors/code/release.md#packages-releases-to-npm-and-wordpress-core-updates). - -[lerna]: https://lerna.js.org/ -[monorepo]: https://monorepo.tools -[npm]: https://www.npmjs.com/ diff --git a/package-lock.json b/package-lock.json index 524584ed63e31a..76bc76d72f33a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,81 +9,9 @@ "version": "19.5.0-rc.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", - "dependencies": { - "@wordpress/a11y": "file:packages/a11y", - "@wordpress/annotations": "file:packages/annotations", - "@wordpress/api-fetch": "file:packages/api-fetch", - "@wordpress/autop": "file:packages/autop", - "@wordpress/blob": "file:packages/blob", - "@wordpress/block-directory": "file:packages/block-directory", - "@wordpress/block-editor": "file:packages/block-editor", - "@wordpress/block-library": "file:packages/block-library", - "@wordpress/block-serialization-default-parser": "file:packages/block-serialization-default-parser", - "@wordpress/block-serialization-spec-parser": "file:packages/block-serialization-spec-parser", - "@wordpress/blocks": "file:packages/blocks", - "@wordpress/commands": "file:packages/commands", - "@wordpress/components": "file:packages/components", - "@wordpress/compose": "file:packages/compose", - "@wordpress/core-commands": "file:packages/core-commands", - "@wordpress/core-data": "file:packages/core-data", - "@wordpress/customize-widgets": "file:packages/customize-widgets", - "@wordpress/data": "file:packages/data", - "@wordpress/data-controls": "file:packages/data-controls", - "@wordpress/dataviews": "file:packages/dataviews", - "@wordpress/date": "file:packages/date", - "@wordpress/deprecated": "file:packages/deprecated", - "@wordpress/dom": "file:packages/dom", - "@wordpress/dom-ready": "file:packages/dom-ready", - "@wordpress/edit-post": "file:packages/edit-post", - "@wordpress/edit-site": "file:packages/edit-site", - "@wordpress/edit-widgets": "file:packages/edit-widgets", - "@wordpress/editor": "file:packages/editor", - "@wordpress/element": "file:packages/element", - "@wordpress/escape-html": "file:packages/escape-html", - "@wordpress/fields": "file:packages/fields", - "@wordpress/format-library": "file:packages/format-library", - "@wordpress/hooks": "file:packages/hooks", - "@wordpress/html-entities": "file:packages/html-entities", - "@wordpress/i18n": "file:packages/i18n", - "@wordpress/icons": "file:packages/icons", - "@wordpress/interactivity": "file:packages/interactivity", - "@wordpress/interactivity-router": "file:packages/interactivity-router", - "@wordpress/interface": "file:packages/interface", - "@wordpress/is-shallow-equal": "file:packages/is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts", - "@wordpress/keycodes": "file:packages/keycodes", - "@wordpress/list-reusable-blocks": "file:packages/list-reusable-blocks", - "@wordpress/media-utils": "file:packages/media-utils", - "@wordpress/notices": "file:packages/notices", - "@wordpress/nux": "file:packages/nux", - "@wordpress/patterns": "file:packages/patterns", - "@wordpress/plugins": "file:packages/plugins", - "@wordpress/preferences": "file:packages/preferences", - "@wordpress/preferences-persistence": "file:packages/preferences-persistence", - "@wordpress/primitives": "file:packages/primitives", - "@wordpress/priority-queue": "file:packages/priority-queue", - "@wordpress/private-apis": "file:packages/private-apis", - "@wordpress/react-i18n": "file:packages/react-i18n", - "@wordpress/react-native-aztec": "file:packages/react-native-aztec", - "@wordpress/react-native-bridge": "file:packages/react-native-bridge", - "@wordpress/react-native-editor": "file:packages/react-native-editor", - "@wordpress/redux-routine": "file:packages/redux-routine", - "@wordpress/reusable-blocks": "file:packages/reusable-blocks", - "@wordpress/rich-text": "file:packages/rich-text", - "@wordpress/router": "file:packages/router", - "@wordpress/server-side-render": "file:packages/server-side-render", - "@wordpress/shortcode": "file:packages/shortcode", - "@wordpress/style-engine": "file:packages/style-engine", - "@wordpress/sync": "file:packages/sync", - "@wordpress/token-list": "file:packages/token-list", - "@wordpress/undo-manager": "file:packages/undo-manager", - "@wordpress/url": "file:packages/url", - "@wordpress/viewport": "file:packages/viewport", - "@wordpress/vips": "file:packages/vips", - "@wordpress/warning": "file:packages/warning", - "@wordpress/widgets": "file:packages/widgets", - "@wordpress/wordcount": "file:packages/wordcount" - }, + "workspaces": [ + "packages/*" + ], "devDependencies": { "@actions/core": "1.9.1", "@actions/github": "5.0.0", @@ -133,33 +61,6 @@ "@types/semver": "7.3.8", "@types/sprintf-js": "1.1.2", "@types/uuid": "8.3.1", - "@wordpress/babel-plugin-import-jsx-pragma": "file:packages/babel-plugin-import-jsx-pragma", - "@wordpress/babel-plugin-makepot": "file:packages/babel-plugin-makepot", - "@wordpress/babel-preset-default": "file:packages/babel-preset-default", - "@wordpress/base-styles": "file:packages/base-styles", - "@wordpress/browserslist-config": "file:packages/browserslist-config", - "@wordpress/create-block": "file:packages/create-block", - "@wordpress/create-block-tutorial-template": "file:packages/create-block-tutorial-template", - "@wordpress/dependency-extraction-webpack-plugin": "file:packages/dependency-extraction-webpack-plugin", - "@wordpress/docgen": "file:packages/docgen", - "@wordpress/e2e-test-utils": "file:packages/e2e-test-utils", - "@wordpress/e2e-test-utils-playwright": "file:packages/e2e-test-utils-playwright", - "@wordpress/e2e-tests": "file:packages/e2e-tests", - "@wordpress/env": "file:packages/env", - "@wordpress/eslint-plugin": "file:packages/eslint-plugin", - "@wordpress/jest-console": "file:packages/jest-console", - "@wordpress/jest-preset-default": "file:packages/jest-preset-default", - "@wordpress/jest-puppeteer-axe": "file:packages/jest-puppeteer-axe", - "@wordpress/lazy-import": "file:packages/lazy-import", - "@wordpress/npm-package-json-lint-config": "file:packages/npm-package-json-lint-config", - "@wordpress/postcss-plugins-preset": "file:packages/postcss-plugins-preset", - "@wordpress/postcss-themes": "file:packages/postcss-themes", - "@wordpress/prettier-config": "file:packages/prettier-config", - "@wordpress/project-management-automation": "file:packages/project-management-automation", - "@wordpress/readable-js-assets-webpack-plugin": "file:packages/readable-js-assets-webpack-plugin", - "@wordpress/report-flaky-tests": "file:packages/report-flaky-tests", - "@wordpress/scripts": "file:packages/scripts", - "@wordpress/stylelint-config": "file:packages/stylelint-config", "ajv": "8.7.1", "appium": "2.0.0", "babel-jest": "29.7.0", @@ -266,7 +167,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", - "dev": true, "dependencies": { "@actions/http-client": "^2.0.1", "uuid": "^8.3.2" @@ -276,7 +176,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -285,7 +184,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.0.tgz", "integrity": "sha512-QvE9eAAfEsS+yOOk0cylLBIO/d6WyWIOvsxxzdrPFaud39G6BOkUwScXZn1iBzQzHyu9SBkkLSWlohDWdsasAQ==", - "dev": true, "dependencies": { "@actions/http-client": "^1.0.11", "@octokit/core": "^3.4.0", @@ -297,7 +195,6 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz", "integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==", - "dev": true, "dependencies": { "tunnel": "0.0.6" } @@ -306,7 +203,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", - "dev": true, "license": "MIT", "dependencies": { "tunnel": "^0.0.6", @@ -1581,7 +1477,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/@axe-core/puppeteer/-/puppeteer-4.0.0.tgz", "integrity": "sha512-APFc2iRmrmUfqdBUevjsMxJliDudWPwvCU5Pzw2uKZ0sMVtW3rQuElTcfJCHFq8KOZSSO0BPD+lK+pXOx1ta5Q==", - "dev": true, "dependencies": { "axe-core": "^4.0.1" }, @@ -1593,12 +1488,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", - "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.9.tgz", + "integrity": "sha512-z88xeGxnzehn2sqZ8UdGQEvYErF1odv2CftxInpSYJt6uHuPe9YjahKZITGs3l5LeI9d2ROG+obuDAoSlqbNfQ==", "license": "MIT", "dependencies": { - "@babel/highlight": "^7.25.7", + "@babel/highlight": "^7.25.9", "picocolors": "^1.0.0" }, "engines": { @@ -1606,9 +1501,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.7.tgz", - "integrity": "sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.9.tgz", + "integrity": "sha512-yD+hEuJ/+wAJ4Ox2/rpNv5HIuPG82x3ZlQvYVn8iYCprdxzE7P1udpGF1jyjQVBU4dgznN+k2h103vxZ7NdPyw==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1658,12 +1553,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", - "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.9.tgz", + "integrity": "sha512-omlUGkr5EaoIJrhLf9CJ0TvjBRpd9+AXRG//0GEQ9THSo8wPiTlbpy1/Ow8ZTrbXpjd9FHXfbFQx32I04ht0FA==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.7", + "@babel/types": "^7.25.9", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -1673,37 +1568,65 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", - "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", - "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz", + "integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", - "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.7", - "@babel/helper-validator-option": "^7.25.7", + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -1734,18 +1657,17 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.9.tgz", - "integrity": "sha512-B2L9neXTIyPQoXDm+NtovPvG6VOLWnaXu3BIeVDWwdKFgG30oNa6CqVGiJPDWQwIAK49t9gnQI9c6K6RzabiKw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", + "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.25.9", "semver": "^6.3.1" }, "engines": { @@ -1755,6 +1677,33 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -1764,12 +1713,12 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.7.tgz", - "integrity": "sha512-byHhumTj/X47wJ6C6eLpK7wW/WBEcnUeb7D0FNc/jFQnQVw7DOso3Zz5u9x/zLrFVkHa89ZGDbkAa1D54NdrCQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz", + "integrity": "sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-annotate-as-pure": "^7.25.9", "regexpu-core": "^6.1.1", "semver": "^6.3.1" }, @@ -1789,29 +1738,19 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.4.tgz", - "integrity": "sha512-OrpPZ97s+aPi6h2n1OXzdhVis1SGSsMU2aMHgLcOKfsp4/v1NWpx3CWT3lBj5eeBq9cDkPkh+YCfdF7O12uNDQ==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" + "resolve": "^1.14.2" }, "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/helper-environment-visitor": { @@ -1822,64 +1761,96 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "license": "MIT", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, + "node_modules/@babel/helper-member-expression-to-functions/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "node_modules/@babel/helper-member-expression-to-functions/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", - "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", + "node_modules/@babel/helper-module-imports/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helper-module-imports/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", - "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.9.tgz", + "integrity": "sha512-TvLZY/F3+GvdRYFZFyxMvnsKi+4oJdgZzU3BoGN9Uc2d9C6zfNwJcKKhjqLAhK8i46mv93jsO74fDh3ih6rpHA==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.7", - "@babel/helper-simple-access": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-simple-access": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1888,35 +1859,63 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-module-transforms/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", - "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.7.tgz", - "integrity": "sha512-kRGE89hLnPfcz6fTrlNU+uhgcwv0mBE4Gv3P9Ke9kLVJYpi4AMVVEElXvB5CabrPZW4nCM8P8UyyjrzCM0O2sw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", + "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-wrap-function": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1925,14 +1924,42 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz", + "integrity": "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==", + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5" + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1941,82 +1968,181 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-replace-supers/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-simple-access": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", - "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", + "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helper-simple-access/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "node_modules/@babel/helper-skip-transparent-expression-wrappers/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", - "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", - "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", - "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.7.tgz", - "integrity": "sha512-MA0roW3JF2bD1ptAaJnvcabsVlNQShUaThyJbCDD4bCp8NEgiFvpoqRI2YS22hHlc2thjO/fTg2ShLMC3jygAg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", + "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", "license": "MIT", "dependencies": { - "@babel/template": "^7.25.7", - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helper-wrap-function/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helpers": { "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", @@ -2031,12 +2157,12 @@ } }, "node_modules/@babel/highlight": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", - "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz", + "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.9", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -2072,12 +2198,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", - "integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz", + "integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.7" + "@babel/types": "^7.25.9" }, "bin": { "parser": "bin/babel-parser.js" @@ -2087,14 +2213,13 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.7.tgz", - "integrity": "sha512-UV9Lg53zyebzD1DwQoT9mzkEKa922LNUp5YkTJ6Uta0RbyXaQNUgcvSt7qIu1PpPzVb6rd10OVNTzkyBGeVmxQ==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", + "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2103,14 +2228,40 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.7.tgz", - "integrity": "sha512-GDDWeVLNxRIkQTnJn2pDOM1pkCgYdSqPeT1a9vh9yIqu2uzzgw1zcqEb+IJOhy+dTBMlNdThrDIksr2o09qrrQ==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", + "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2120,12 +2271,12 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", - "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", + "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2135,14 +2286,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", - "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.23.3" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2152,13 +2303,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", - "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", + "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2167,6 +2318,33 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-proposal-async-generator-functions": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", @@ -2304,7 +2482,6 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -2328,7 +2505,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -2340,7 +2516,6 @@ "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -2352,7 +2527,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -2392,7 +2566,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -2415,12 +2588,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", - "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.9.tgz", + "integrity": "sha512-4GHX5uzr5QMOOuzV0an9MFju4hKlm0OyePl/lHhcsTVae5t/IKVHnb8W67Vr6FuLlk5lPqLB7n7O+K5R46emYg==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2430,12 +2603,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", - "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.9.tgz", + "integrity": "sha512-u3EN9ub8LyYvgTnrgp8gboElouayiwPdnM7x5tcnW3iSt09/lQYPwMNK40I9IUxo7QOZhAsPHCmmuO7EPdruqg==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2448,7 +2621,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -2460,7 +2632,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -2487,7 +2658,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -2568,7 +2738,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -2580,11 +2749,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2597,7 +2767,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -2610,11 +2779,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", - "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", + "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2624,16 +2794,14 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.7.tgz", - "integrity": "sha512-4B6OhTrwYKHYYgcwErvZjbmH9X5TxQBsaBHdzEIB4l71gR5jh/tuHGlb9in47udL2+wVUcOz5XXhhfhVJwEpEg==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz", + "integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-remap-async-to-generator": "^7.25.7", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/traverse": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2642,14 +2810,42 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-async-generator-functions/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", - "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", + "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.20" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2659,12 +2855,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", - "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz", + "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2674,11 +2870,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", - "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", + "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2688,13 +2885,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", - "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", + "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", + "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2704,14 +2901,13 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", - "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.9.tgz", + "integrity": "sha512-UIf+72C7YJ+PJ685/PpATbCz00XqiFEzHX5iysRwfvNT0Ko+FaXSvRgLytFSp8xUItrG9pFM/KoBBZDrY/cYyg==", + "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-class-static-block": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2721,17 +2917,16 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", - "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", + "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/traverse": "^7.25.9", "globals": "^11.1.0" }, "engines": { @@ -2741,6 +2936,24 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-classes/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/plugin-transform-classes/node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -2750,12 +2963,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", - "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", + "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.15" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/template": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2765,11 +2979,12 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", - "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", + "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2779,13 +2994,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", - "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", + "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2795,12 +3010,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", - "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", + "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2810,14 +3025,13 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.7.tgz", - "integrity": "sha512-HvS6JF66xSS5rNKXLqkk7L9c/jZ/cdIVIcoPVrnl8IsVpLggTjXs8OWekbLHs/VtYDDh5WXnQyeE3PPUGm22MA==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2827,13 +3041,12 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", - "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", + "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2843,13 +3056,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", - "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz", + "integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==", + "license": "MIT", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2859,14 +3072,12 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.7.tgz", - "integrity": "sha512-h3MDAP5l34NQkkNulsTNyjdaR+OiB0Im67VU//sFupouP8Q6m9Spy7l66DcaAQxtmCqGdanPByLsnwFttxKISQ==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", + "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2891,13 +3102,13 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", - "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz", + "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2907,13 +3118,14 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", - "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", + "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", + "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2922,14 +3134,40 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-function-name/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/plugin-transform-function-name/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", - "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", + "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-json-strings": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2939,11 +3177,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", - "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", + "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2953,13 +3192,12 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", - "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", + "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2969,12 +3207,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", - "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", + "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2984,13 +3222,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", - "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", + "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3000,13 +3238,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", - "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz", + "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==", + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-simple-access": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3016,15 +3255,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz", - "integrity": "sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", + "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", + "license": "MIT", "dependencies": { - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3033,14 +3272,41 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-modules-systemjs/node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", - "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", + "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3050,12 +3316,13 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", - "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3065,12 +3332,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", - "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", + "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3080,13 +3347,12 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", - "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz", + "integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3096,13 +3362,12 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", - "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", + "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3126,16 +3391,14 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", - "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", + "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.23.3", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.23.3" + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3145,13 +3408,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", - "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", + "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3161,13 +3424,12 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", - "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", + "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3177,14 +3439,13 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", - "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3194,11 +3455,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", - "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", + "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3208,12 +3470,13 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", - "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", + "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", + "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3223,14 +3486,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", - "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", + "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3240,12 +3503,12 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", - "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", + "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3258,7 +3521,6 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.22.5.tgz", "integrity": "sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -3284,15 +3546,16 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", - "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", + "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/types": "^7.23.4" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3305,7 +3568,6 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", - "dev": true, "dependencies": { "@babel/plugin-transform-react-jsx": "^7.22.5" }, @@ -3344,11 +3606,25 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-react-jsx/node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-react-pure-annotations": { "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.23.3.tgz", "integrity": "sha512-qMFdSS+TUhB7Q/3HVPnEdYJDQIk57jkntAwSuz9xfSE4n+3I+vHYCli3HoHawN1Z3RfCz/y1zXA/JXjG6cVImQ==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5" @@ -3361,12 +3637,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", - "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", + "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.25.9", "regenerator-transform": "^0.15.2" }, "engines": { @@ -3377,12 +3653,12 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", - "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", + "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3392,16 +3668,17 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.0.tgz", - "integrity": "sha512-zlPf1/XFn5+vWdve3AAhf+Sxl+MVa5VlwTwWgnLx23u4GlatSRQJ3Eoo9vllf0a9il3woQsT4SK+5Z7c06h8ag==", - "dependencies": { - "@babel/helper-module-imports": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", - "babel-plugin-polyfill-corejs2": "^0.2.3", - "babel-plugin-polyfill-corejs3": "^0.3.0", - "babel-plugin-polyfill-regenerator": "^0.2.3", - "semver": "^6.3.0" + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz", + "integrity": "sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -3419,11 +3696,12 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", - "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", + "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3433,12 +3711,13 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", - "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", + "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3448,11 +3727,12 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", - "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", + "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3462,12 +3742,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", - "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz", + "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3477,12 +3757,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", - "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz", + "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3492,14 +3772,16 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz", - "integrity": "sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.9.tgz", + "integrity": "sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==", + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-typescript": "^7.23.3" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3509,12 +3791,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", - "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", + "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3524,13 +3806,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", - "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", + "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3540,12 +3822,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", - "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", + "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3555,13 +3838,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", - "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", + "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3571,90 +3854,78 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.9.tgz", - "integrity": "sha512-3kBGTNBBk9DQiPoXYS0g0BYlwTQYUTifqgKTjxUwEUkduRT2QOa0FPGBJ+NROQhGyYO5BuTJwGvBnqKDykac6A==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.9.tgz", + "integrity": "sha512-XqDEt+hfsQukahSX9JOBDHhpUHDhj2zGSxoqWQFCMajOSBnbhBdgON/bU/5PkBA1yX5tqW6tTzuIPVsZTQ7h5Q==", + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "@babel/compat-data": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.23.3", - "@babel/plugin-syntax-import-attributes": "^7.23.3", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-import-assertions": "^7.25.9", + "@babel/plugin-syntax-import-attributes": "^7.25.9", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.23.3", - "@babel/plugin-transform-async-generator-functions": "^7.23.9", - "@babel/plugin-transform-async-to-generator": "^7.23.3", - "@babel/plugin-transform-block-scoped-functions": "^7.23.3", - "@babel/plugin-transform-block-scoping": "^7.23.4", - "@babel/plugin-transform-class-properties": "^7.23.3", - "@babel/plugin-transform-class-static-block": "^7.23.4", - "@babel/plugin-transform-classes": "^7.23.8", - "@babel/plugin-transform-computed-properties": "^7.23.3", - "@babel/plugin-transform-destructuring": "^7.23.3", - "@babel/plugin-transform-dotall-regex": "^7.23.3", - "@babel/plugin-transform-duplicate-keys": "^7.23.3", - "@babel/plugin-transform-dynamic-import": "^7.23.4", - "@babel/plugin-transform-exponentiation-operator": "^7.23.3", - "@babel/plugin-transform-export-namespace-from": "^7.23.4", - "@babel/plugin-transform-for-of": "^7.23.6", - "@babel/plugin-transform-function-name": "^7.23.3", - "@babel/plugin-transform-json-strings": "^7.23.4", - "@babel/plugin-transform-literals": "^7.23.3", - "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", - "@babel/plugin-transform-member-expression-literals": "^7.23.3", - "@babel/plugin-transform-modules-amd": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-modules-systemjs": "^7.23.9", - "@babel/plugin-transform-modules-umd": "^7.23.3", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.23.3", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", - "@babel/plugin-transform-numeric-separator": "^7.23.4", - "@babel/plugin-transform-object-rest-spread": "^7.23.4", - "@babel/plugin-transform-object-super": "^7.23.3", - "@babel/plugin-transform-optional-catch-binding": "^7.23.4", - "@babel/plugin-transform-optional-chaining": "^7.23.4", - "@babel/plugin-transform-parameters": "^7.23.3", - "@babel/plugin-transform-private-methods": "^7.23.3", - "@babel/plugin-transform-private-property-in-object": "^7.23.4", - "@babel/plugin-transform-property-literals": "^7.23.3", - "@babel/plugin-transform-regenerator": "^7.23.3", - "@babel/plugin-transform-reserved-words": "^7.23.3", - "@babel/plugin-transform-shorthand-properties": "^7.23.3", - "@babel/plugin-transform-spread": "^7.23.3", - "@babel/plugin-transform-sticky-regex": "^7.23.3", - "@babel/plugin-transform-template-literals": "^7.23.3", - "@babel/plugin-transform-typeof-symbol": "^7.23.3", - "@babel/plugin-transform-unicode-escapes": "^7.23.3", - "@babel/plugin-transform-unicode-property-regex": "^7.23.3", - "@babel/plugin-transform-unicode-regex": "^7.23.3", - "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.25.9", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.25.9", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.25.9", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.25.9", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.25.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.25.9", + "@babel/plugin-transform-typeof-symbol": "^7.25.9", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.8", - "babel-plugin-polyfill-corejs3": "^0.9.0", - "babel-plugin-polyfill-regenerator": "^0.5.5", - "core-js-compat": "^3.31.0", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.38.1", "semver": "^6.3.1" }, "engines": { @@ -3664,82 +3935,10 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", - "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs2/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz", - "integrity": "sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.5.0", - "core-js-compat": "^3.34.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", - "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.5.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -3764,7 +3963,6 @@ "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -3778,7 +3976,6 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.23.3.tgz", "integrity": "sha512-tbkHOS9axH6Ysf2OUEqoSZ6T3Fa2SrNH6WTWSPBboxKzdxNc9qOICeLXkNG0ZEwbQ1HY8liwOce4aN/Ceyuq6w==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-validator-option": "^7.22.15", @@ -3795,15 +3992,31 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", - "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.25.9.tgz", + "integrity": "sha512-XWxw1AcKk36kgxf4C//fl0ikjLeqGUWn062/Fd8GtpTfDJOX6Ud95FK+4JlDA36BX4bNGndXi3a6Vr4Jo5/61A==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-typescript": "^7.23.3" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript/node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3874,7 +4087,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.25.7.tgz", "integrity": "sha512-gMmIEhg35sXk9Te5qbGp3W9YKrvLt3HV658/d3odWrHSqT0JeG5OzsJWFHRLiOohRyjRsJc/x03DhJm3i8VJxg==", - "dev": true, "license": "MIT", "dependencies": { "core-js-pure": "^3.30.2", @@ -3887,8 +4099,7 @@ "node_modules/@babel/runtime-corejs3/node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/@babel/runtime/node_modules/regenerator-runtime": { "version": "0.14.1", @@ -3896,14 +4107,14 @@ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/@babel/template": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", - "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3936,14 +4147,13 @@ } }, "node_modules/@babel/types": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", - "integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz", + "integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3958,8 +4168,7 @@ "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, "node_modules/@callstack/reassure-cli": { "version": "0.6.1", @@ -4126,7 +4335,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.1.tgz", "integrity": "sha512-lSquqZCHxDfuTg/Sk2hiS0mcSFCEBuj49JfzPHJogDBT0mGCyY5A1AQzBWngitrp7i1/HAZpIgzF/VjhOEIJIg==", - "dev": true, "funding": [ { "type": "github", @@ -4148,7 +4356,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.1.tgz", "integrity": "sha512-UBqaiu7kU0lfvaP982/o3khfXccVlHPWp0/vwwiIgDF0GmqqqxoiXC/6FCjlS9u92f7CoEz6nXKQnrn1kIAkOw==", - "dev": true, "funding": [ { "type": "github", @@ -4167,7 +4374,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-3.0.1.tgz", "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==", - "dev": true, "funding": [ { "type": "github", @@ -4190,7 +4396,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-4.0.0.tgz", "integrity": "sha512-189nelqtPd8++phaHNwYovKZI0FOzH1vQEE3QhHHkNIGrg5fSs9CbYP3RvfEH5geztnIA9Jwq91wyOIwAW5JIQ==", - "dev": true, "funding": [ { "type": "github", @@ -4223,7 +4428,6 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, "engines": { "node": ">=10.0.0" } @@ -4232,7 +4436,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", - "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -4535,7 +4738,6 @@ "version": "0.40.1", "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.40.1.tgz", "integrity": "sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==", - "dev": true, "dependencies": { "comment-parser": "1.4.0", "esquery": "^1.5.0", @@ -4901,7 +5103,6 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -4916,7 +5117,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -4928,7 +5128,6 @@ "version": "4.8.0", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", - "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -4937,7 +5136,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz", "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==", - "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -4957,7 +5155,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -4972,14 +5169,12 @@ "node_modules/@eslint/eslintrc/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/@eslint/eslintrc/node_modules/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, "engines": { "node": ">= 4" } @@ -4988,7 +5183,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -5000,7 +5194,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -5018,7 +5211,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "dev": true, "engines": { "node": ">=14" } @@ -5107,7 +5299,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", - "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.0", "debug": "^4.1.1", @@ -5120,8 +5311,7 @@ "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", @@ -5241,7 +5431,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", - "dev": true, "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -5256,7 +5445,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -5269,7 +5457,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -5281,7 +5468,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -5296,7 +5482,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -5308,7 +5493,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "engines": { "node": ">=6" } @@ -5317,7 +5501,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -5326,7 +5509,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, "engines": { "node": ">=8" } @@ -5335,7 +5517,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, "engines": { "node": ">=8" } @@ -5344,7 +5525,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz", "integrity": "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==", - "dev": true, "dependencies": { "@jest/types": "^29.6.1", "@types/node": "*", @@ -5361,7 +5541,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz", "integrity": "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==", - "dev": true, "dependencies": { "@jest/console": "^29.6.2", "@jest/reporters": "^29.6.2", @@ -5433,7 +5612,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz", "integrity": "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==", - "dev": true, "dependencies": { "expect": "^29.6.2", "jest-snapshot": "^29.6.2" @@ -5446,7 +5624,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz", "integrity": "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==", - "dev": true, "dependencies": { "jest-get-type": "^29.4.3" }, @@ -5493,7 +5670,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz", "integrity": "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==", - "dev": true, "dependencies": { "@jest/environment": "^29.6.2", "@jest/expect": "^29.6.2", @@ -5508,7 +5684,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz", "integrity": "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==", - "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.6.2", @@ -5551,7 +5726,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5582,7 +5756,6 @@ "version": "29.6.0", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", @@ -5596,7 +5769,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz", "integrity": "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==", - "dev": true, "dependencies": { "@jest/console": "^29.6.2", "@jest/types": "^29.6.1", @@ -5611,7 +5783,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz", "integrity": "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==", - "dev": true, "dependencies": { "@jest/test-result": "^29.6.2", "graceful-fs": "^4.2.9", @@ -5626,7 +5797,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -5651,14 +5821,12 @@ "node_modules/@jest/transform/node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/@jest/transform/node_modules/write-file-atomic": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" @@ -5751,7 +5919,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "dev": true, "dependencies": { "debug": "^4.1.1" } @@ -5759,14 +5926,12 @@ "node_modules/@kwsites/promise-deferred": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", - "dev": true + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, "node_modules/@lerna/child-process": { "version": "7.1.4", @@ -6121,7 +6286,6 @@ "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "dev": true, "license": "MIT", "dependencies": { "eslint-scope": "5.1.1" @@ -6131,7 +6295,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", @@ -6145,7 +6308,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.2.tgz", "integrity": "sha512-wrIBsjA5pl13f0RN4Zx4FNWmU71lv03meGKnqRUoCyan17s4V3WL92f3w3AIuWbNnpcrQyFBU5qMavJoB8d27w==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.2", "run-parallel": "^1.1.9" @@ -6158,7 +6320,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.2.tgz", "integrity": "sha512-z8+wGWV2dgUhLqrtRYa03yDx4HWMvXKi1z8g3m2JyxAx8F7xk74asqPk5LAETjqDSGLFML/6CDl0+yFunSYicw==", - "dev": true, "engines": { "node": ">= 8" } @@ -6167,7 +6328,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.3.tgz", "integrity": "sha512-l6t8xEhfK9Sa4YO5mIRdau7XSOADfmh3jCr0evNHdY+HNkW6xuQhgMH7D73VV6WpZOagrW0UludvMTiifiwTfA==", - "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.2", "fastq": "^1.6.0" @@ -6580,7 +6740,6 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "dev": true, "dependencies": { "@octokit/types": "^6.0.3" } @@ -6589,7 +6748,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "dev": true, "dependencies": { "@octokit/auth-token": "^2.4.4", "@octokit/graphql": "^4.5.8", @@ -6604,7 +6762,6 @@ "version": "6.0.12", "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dev": true, "dependencies": { "@octokit/types": "^6.0.3", "is-plain-object": "^5.0.0", @@ -6615,7 +6772,6 @@ "version": "5.6.3", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dev": true, "dependencies": { "@octokit/endpoint": "^6.0.1", "@octokit/request-error": "^2.1.0", @@ -6628,14 +6784,12 @@ "node_modules/@octokit/core/node_modules/before-after-hook": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" }, "node_modules/@octokit/core/node_modules/universal-user-agent": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", - "dev": true + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" }, "node_modules/@octokit/endpoint": { "version": "5.5.3", @@ -6679,7 +6833,6 @@ "version": "4.8.0", "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "dev": true, "dependencies": { "@octokit/request": "^5.6.0", "@octokit/types": "^6.0.3", @@ -6690,7 +6843,6 @@ "version": "6.0.12", "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dev": true, "dependencies": { "@octokit/types": "^6.0.3", "is-plain-object": "^5.0.0", @@ -6701,7 +6853,6 @@ "version": "5.6.3", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dev": true, "dependencies": { "@octokit/endpoint": "^6.0.1", "@octokit/request-error": "^2.1.0", @@ -6714,14 +6865,12 @@ "node_modules/@octokit/graphql/node_modules/universal-user-agent": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", - "dev": true + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" }, "node_modules/@octokit/openapi-types": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", - "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==", - "dev": true + "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==" }, "node_modules/@octokit/plugin-enterprise-rest": { "version": "6.0.1", @@ -6733,7 +6882,6 @@ "version": "2.21.3", "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", - "dev": true, "dependencies": { "@octokit/types": "^6.40.0" }, @@ -6744,14 +6892,12 @@ "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { "version": "12.11.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", - "dev": true + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" }, "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { "version": "6.41.0", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dev": true, "dependencies": { "@octokit/openapi-types": "^12.11.0" } @@ -6769,7 +6915,6 @@ "version": "5.16.2", "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", - "dev": true, "dependencies": { "@octokit/types": "^6.39.0", "deprecation": "^2.3.1" @@ -6781,14 +6926,12 @@ "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { "version": "12.11.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", - "dev": true + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" }, "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { "version": "6.41.0", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dev": true, "dependencies": { "@octokit/openapi-types": "^12.11.0" } @@ -6812,7 +6955,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "dev": true, "dependencies": { "@octokit/types": "^6.0.3", "deprecation": "^2.0.0", @@ -6899,7 +7041,6 @@ "version": "6.34.0", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", - "dev": true, "dependencies": { "@octokit/openapi-types": "^11.2.0" } @@ -6908,14 +7049,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-2.0.0.tgz", "integrity": "sha512-35cfQ4YWlnZnmZKmIxlGPUPLtbkF8lr/A/1Sk1eC0ddLMwQN06dOuLc+dI3YLQS+T+MoNt3DIQ0NynwgKPilig==", - "dev": true, "license": "MIT" }, "node_modules/@octokit/webhooks-types": { "version": "5.8.0", "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-5.8.0.tgz", "integrity": "sha512-8adktjIb76A7viIdayQSFuBEwOzwhDC+9yxZpKNHjfzrlostHCw0/N7JWpWMObfElwvJMk2fY2l1noENCk9wmw==", - "dev": true, "license": "MIT" }, "node_modules/@parcel/watcher": { @@ -6950,7 +7089,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "fast-glob": "^3.3.0", @@ -6970,7 +7108,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -6984,7 +7121,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, "engines": { "node": ">=12" }, @@ -6996,7 +7132,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -7012,7 +7147,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -7024,7 +7158,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -7036,7 +7169,6 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", - "dev": true, "dependencies": { "default-browser": "^4.0.0", "define-lazy-prop": "^3.0.0", @@ -7054,7 +7186,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -7063,7 +7194,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -7075,7 +7205,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -7084,7 +7213,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -7114,7 +7242,6 @@ "version": "0.5.11", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.11.tgz", "integrity": "sha512-7j/6vdTym0+qZ6u4XbSAxrWBGYSdCfTzySkj7WAFgDLmSyWlOrWvpyzxlFh5jtw9dn0oL/jtW+06XfFiisN3JQ==", - "dev": true, "dependencies": { "ansi-html-community": "^0.0.8", "common-path-prefix": "^3.0.0", @@ -7164,7 +7291,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -7180,7 +7306,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -7196,7 +7321,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -7211,7 +7335,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -7226,7 +7349,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -7235,7 +7357,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -7253,7 +7374,6 @@ "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, "engines": { "node": ">= 8" } @@ -7261,8 +7381,7 @@ "node_modules/@polka/url": { "version": "1.0.0-next.23", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", - "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==", - "dev": true + "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==" }, "node_modules/@preact/signals": { "version": "1.3.0", @@ -7294,7 +7413,6 @@ "version": "1.4.6", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.4.6.tgz", "integrity": "sha512-x4BEjr2SjOPowNeiguzjozQbsc6h437ovD/wu+JpaenxVLm3jkgzHY2xOslMTp50HoTvQreMjiexiGQw1sqZlQ==", - "dev": true, "dependencies": { "debug": "4.3.4", "extract-zip": "2.0.1", @@ -7323,7 +7441,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -7336,14 +7453,12 @@ "node_modules/@puppeteer/browsers/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/@puppeteer/browsers/node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -7363,7 +7478,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -7372,7 +7486,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -7383,7 +7496,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -7397,7 +7509,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", - "dev": true, "dependencies": { "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", @@ -7408,7 +7519,6 @@ "version": "3.1.7", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", @@ -7419,7 +7529,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -7436,7 +7545,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "engines": { "node": ">=10" } @@ -7445,7 +7553,6 @@ "version": "17.7.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", - "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -7463,7 +7570,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "engines": { "node": ">=12" } @@ -8751,9 +8857,9 @@ } }, "node_modules/@react-native-community/cli-doctor/node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -10563,7 +10669,6 @@ "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.19.7.tgz", "integrity": "sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw==", - "dev": true, "dependencies": { "@sentry/hub": "6.19.7", "@sentry/minimal": "6.19.7", @@ -10578,14 +10683,12 @@ "node_modules/@sentry/core/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/hub": { "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz", "integrity": "sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA==", - "dev": true, "dependencies": { "@sentry/types": "6.19.7", "@sentry/utils": "6.19.7", @@ -10598,14 +10701,12 @@ "node_modules/@sentry/hub/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/minimal": { "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.7.tgz", "integrity": "sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ==", - "dev": true, "dependencies": { "@sentry/hub": "6.19.7", "@sentry/types": "6.19.7", @@ -10618,14 +10719,12 @@ "node_modules/@sentry/minimal/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/node": { "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.19.7.tgz", "integrity": "sha512-gtmRC4dAXKODMpHXKfrkfvyBL3cI8y64vEi3fDD046uqYcrWdgoQsffuBbxMAizc6Ez1ia+f0Flue6p15Qaltg==", - "dev": true, "dependencies": { "@sentry/core": "6.19.7", "@sentry/hub": "6.19.7", @@ -10644,7 +10743,6 @@ "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -10652,14 +10750,12 @@ "node_modules/@sentry/node/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/types": { "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz", "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==", - "dev": true, "engines": { "node": ">=6" } @@ -10668,7 +10764,6 @@ "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz", "integrity": "sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==", - "dev": true, "dependencies": { "@sentry/types": "6.19.7", "tslib": "^1.9.3" @@ -10680,8 +10775,7 @@ "node_modules/@sentry/utils/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sideway/address": { "version": "4.1.5", @@ -10760,7 +10854,6 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, "engines": { "node": ">=10" }, @@ -13533,7 +13626,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-3.0.1.tgz", "integrity": "sha512-j3mH8HSw2Rob/KJFWZ627w3CQ8gQqVHtzCdPeEffUg5vOgpz4rgrR+Xw2kU0OQCDcdW8Y1nKfdXKKjM5Rn8X0g==", - "dev": true, "dependencies": { "@csstools/css-parser-algorithms": "^3.0.0", "@csstools/css-tokenizer": "^3.0.0", @@ -13554,14 +13646,12 @@ "node_modules/@stylistic/stylelint-plugin/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", - "dev": true, "engines": { "node": ">=14" }, @@ -13577,7 +13667,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", - "dev": true, "engines": { "node": ">=14" }, @@ -13593,7 +13682,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", - "dev": true, "engines": { "node": ">=14" }, @@ -13609,7 +13697,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", - "dev": true, "engines": { "node": ">=14" }, @@ -13625,7 +13712,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", - "dev": true, "engines": { "node": ">=14" }, @@ -13641,7 +13727,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", - "dev": true, "engines": { "node": ">=14" }, @@ -13657,7 +13742,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.0.0.tgz", "integrity": "sha512-UKrY3860AQICgH7g+6h2zkoxeVEPLYwX/uAjmqo4PIq2FIHppwhIqZstIyTz0ZtlwreKR41O3W3BzsBBiJV2Aw==", - "dev": true, "engines": { "node": ">=14" }, @@ -13673,7 +13757,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", - "dev": true, "engines": { "node": ">=12" }, @@ -13689,7 +13772,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.0.0.tgz", "integrity": "sha512-KLcjiZychInVrhs86OvcYPLTFu9L5XV2vj0XAaE1HwE3J3jLmIzRY8ttdeAg/iFyp8nhavJpafpDZTt+1LIpkQ==", - "dev": true, "dependencies": { "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", @@ -13715,7 +13797,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.0.0.tgz", "integrity": "sha512-aJKtc+Pie/rFYsVH/unSkDaZGvEeylNv/s2cP+ta9/rYWxRVvoV/S4Qw65Kmrtah4CBK5PM6ISH9qUH7IJQCng==", - "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.0.0", @@ -13734,14 +13815,12 @@ "node_modules/@svgr/core/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/@svgr/core/node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, "engines": { "node": ">=10" }, @@ -13753,7 +13832,6 @@ "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -13779,7 +13857,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -13791,7 +13868,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -13800,7 +13876,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", - "dev": true, "dependencies": { "@babel/types": "^7.21.3", "entities": "^4.4.0" @@ -13817,7 +13892,6 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, "engines": { "node": ">=0.12" }, @@ -13829,7 +13903,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.0.1.tgz", "integrity": "sha512-bfCFb+4ZsM3UuKP2t7KmDwn6YV8qVn9HIQJmau6xeQb/iV65Rpi7NBNBWA2hcCd4GKoCqG8hpaaDk5FDR0eH+g==", - "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.0.0", @@ -13851,7 +13924,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.0.1.tgz", "integrity": "sha512-29OJ1QmJgnohQHDAgAuY2h21xWD6TZiXji+hnx+W635RiXTAlHTbjrZDktfqzkN0bOeQEtNe+xgq73/XeWFfSg==", - "dev": true, "dependencies": { "cosmiconfig": "^8.1.3", "deepmerge": "^4.3.1", @@ -13871,14 +13943,12 @@ "node_modules/@svgr/plugin-svgo/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/@svgr/plugin-svgo/node_modules/cosmiconfig": { "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -13904,7 +13974,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -13916,7 +13985,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -13925,7 +13993,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.0.1.tgz", "integrity": "sha512-zSoeKcbCmfMXjA11uDuCJb+1LWNb3vy6Qw/VHj0Nfcl3UuqwuoZWknHsBIhCWvi4wU9vPui3aq054qjVyZqY4A==", - "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@babel/plugin-transform-react-constant-elements": "^7.21.3", @@ -14158,7 +14225,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, "dependencies": { "defer-to-connect": "^2.0.0" }, @@ -14410,14 +14476,12 @@ "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -14506,7 +14570,6 @@ "version": "7.20.0", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", - "dev": true, "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -14519,7 +14582,6 @@ "version": "7.6.4", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, "dependencies": { "@babel/types": "^7.0.0" } @@ -14528,7 +14590,6 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -14538,7 +14599,6 @@ "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", - "dev": true, "dependencies": { "@babel/types": "^7.20.7" } @@ -14562,7 +14622,6 @@ "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -14572,7 +14631,6 @@ "version": "3.5.11", "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.11.tgz", "integrity": "sha512-isGhjmBtLIxdHBDl2xGwUzEM8AOyOvWsADWq7rqirdi/ZQoHnLWErHvsThcEzTX8juDRiZtzp2Qkv5bgNh6mAg==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -14581,7 +14639,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "^3.1.4", @@ -14593,7 +14650,6 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -14602,7 +14658,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.1.tgz", "integrity": "sha512-iaQslNbARe8fctL5Lk+DsmgWOM83lM+7FzP0eQUJs1jd3kBE8NWqBTIT2S8SqQOJjxvt2eyIjpOuYeRXq2AdMw==", - "dev": true, "dependencies": { "@types/express-serve-static-core": "*", "@types/node": "*" @@ -14660,20 +14715,17 @@ "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, "node_modules/@types/events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", - "dev": true + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" }, "node_modules/@types/express": { "version": "4.17.17", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", - "dev": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -14685,7 +14737,6 @@ "version": "4.17.35", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", - "dev": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -14715,7 +14766,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", - "dev": true, "dependencies": { "@types/events": "*", "@types/minimatch": "*", @@ -14726,7 +14776,6 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.3.tgz", "integrity": "sha512-AiHRaEB50LQg0pZmm659vNBb9f4SJ0qrAnteuzhSeAUcJKxoYgEnprg/83kppCnc2zvtCKbdZry1a5pVY3lOTQ==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -14750,20 +14799,17 @@ "node_modules/@types/http-cache-semantics": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.2.tgz", - "integrity": "sha512-FD+nQWA2zJjh4L9+pFXqWOi0Hs1ryBCfI+985NjluQ1p8EYtoLvjLOKidXBtZ4/IcxDX4o8/E8qDS3540tNliw==", - "dev": true + "integrity": "sha512-FD+nQWA2zJjh4L9+pFXqWOi0Hs1ryBCfI+985NjluQ1p8EYtoLvjLOKidXBtZ4/IcxDX4o8/E8qDS3540tNliw==" }, "node_modules/@types/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==", - "dev": true + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" }, "node_modules/@types/http-proxy": { "version": "1.17.12", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.12.tgz", "integrity": "sha512-kQtujO08dVtQ2wXAuSFfk9ASy3sug4+ogFR8Kd8UgP8PEuc1/G/8yjYRmp//PcDNJEUKOza/MrQu15bouEUCiw==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -14803,7 +14849,6 @@ "version": "20.0.1", "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", - "dev": true, "dependencies": { "@types/node": "*", "@types/tough-cookie": "*", @@ -14822,20 +14867,17 @@ "node_modules/@types/json-schema": { "version": "7.0.12", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==" }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, "node_modules/@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -14879,8 +14921,7 @@ "node_modules/@types/mime": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", - "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==", - "dev": true + "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==" }, "node_modules/@types/mime-types": { "version": "2.1.4", @@ -14891,14 +14932,12 @@ "node_modules/@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, "node_modules/@types/minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=", - "dev": true + "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=" }, "node_modules/@types/mousetrap": { "version": "1.6.8", @@ -14921,9 +14960,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.54", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.54.tgz", - "integrity": "sha512-+BRgt0G5gYjTvdLac9sIeE0iZcJxi4Jc4PV5EUzqi+88jmQLr+fRZdv2tCTV7IHKSGxM6SaLoOXQWWUiLUItMw==", + "version": "18.19.59", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.59.tgz", + "integrity": "sha512-vizm2EqwV/7Zay+A6J3tGl9Lhr7CjZe2HmWS988sefiEmsyP9CeXEleho6i4hJk/8UtZAo0bWN4QPZZr83RxvQ==", "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -14942,8 +14981,7 @@ "node_modules/@types/normalize-package-data": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz", - "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==", - "dev": true + "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==" }, "node_modules/@types/npm-package-arg": { "version": "6.1.1", @@ -14993,14 +15031,12 @@ "node_modules/@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" }, "node_modules/@types/range-parser": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, "node_modules/@types/react": { "version": "18.3.1", @@ -15064,7 +15100,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -15072,8 +15107,7 @@ "node_modules/@types/retry": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", - "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", - "dev": true + "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==" }, "node_modules/@types/scheduler": { "version": "0.16.2", @@ -15090,7 +15124,6 @@ "version": "0.17.1", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", - "dev": true, "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -15099,8 +15132,7 @@ "node_modules/@types/send/node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" }, "node_modules/@types/serve-favicon": { "version": "2.5.5", @@ -15115,7 +15147,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", - "dev": true, "dependencies": { "@types/express": "*" } @@ -15124,7 +15155,6 @@ "version": "1.15.2", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", - "dev": true, "dependencies": { "@types/http-errors": "*", "@types/mime": "*", @@ -15149,7 +15179,6 @@ "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -15157,8 +15186,7 @@ "node_modules/@types/source-list-map": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==" }, "node_modules/@types/sprintf-js": { "version": "1.1.2", @@ -15180,8 +15208,7 @@ "node_modules/@types/tapable": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.5.tgz", - "integrity": "sha512-/gG2M/Imw7cQFp8PGvz/SwocNrmKFjFsm5Pb8HdbHkZ1K8pmuPzOX4VeVoiEecFCVf4CsN1r3/BRvx+6sNqwtQ==", - "dev": true + "integrity": "sha512-/gG2M/Imw7cQFp8PGvz/SwocNrmKFjFsm5Pb8HdbHkZ1K8pmuPzOX4VeVoiEecFCVf4CsN1r3/BRvx+6sNqwtQ==" }, "node_modules/@types/teen_process": { "version": "2.0.0", @@ -15204,8 +15231,7 @@ "node_modules/@types/tough-cookie": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", - "dev": true + "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==" }, "node_modules/@types/triple-beam": { "version": "1.3.3", @@ -15217,7 +15243,6 @@ "version": "3.9.2", "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.9.2.tgz", "integrity": "sha512-d6dIfpPbF+8B7WiCi2ELY7m0w1joD8cRW4ms88Emdb2w062NeEpbNCeWwVCgzLRpVG+5e74VFSg4rgJ2xXjEiQ==", - "dev": true, "dependencies": { "source-map": "^0.6.1" } @@ -15225,8 +15250,7 @@ "node_modules/@types/unist": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", - "dev": true + "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==" }, "node_modules/@types/uuid": { "version": "8.3.1", @@ -15238,7 +15262,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz", "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==", - "dev": true, "dependencies": { "@types/node": "*", "@types/unist": "*", @@ -15249,7 +15272,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-1.0.1.tgz", "integrity": "sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA==", - "dev": true, "dependencies": { "@types/node": "*", "@types/unist": "*" @@ -15259,7 +15281,6 @@ "version": "4.41.33", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.33.tgz", "integrity": "sha512-PPajH64Ft2vWevkerISMtnZ8rTs4YmRbs+23c402J0INmxDKCrhZNvwZYtzx96gY2wAtXdrK1BS2fiC8MlLr3g==", - "dev": true, "dependencies": { "@types/node": "*", "@types/tapable": "^1", @@ -15273,7 +15294,6 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.7.tgz", "integrity": "sha512-XyaHrJILjK1VHVC4aVlKsdNN5KBTwufMb43cQs+flGxtPAf/1Qwl8+Q0tp5BwEGaI8D6XT1L+9bSWXckgkjTLw==", - "dev": true, "dependencies": { "@types/node": "*", "@types/source-list-map": "*", @@ -15296,7 +15316,6 @@ "version": "8.5.5", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -15319,7 +15338,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "dev": true, "optional": true, "dependencies": { "@types/node": "*" @@ -15329,7 +15347,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.1.tgz", "integrity": "sha512-3F5PtBzUW0dYlq77Lcqo13fv+58KDwUib3BddilE8ajPJT+faGgxmI9Sw+I8ZS22BYwoir9ZhNXcLi+S+I2bkw==", - "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", "@typescript-eslint/scope-manager": "6.4.1", @@ -15363,14 +15380,12 @@ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1" @@ -15387,7 +15402,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", - "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -15400,7 +15414,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1", @@ -15427,7 +15440,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", - "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", @@ -15452,7 +15464,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" @@ -15469,7 +15480,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15481,7 +15491,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.4.1.tgz", "integrity": "sha512-610G6KHymg9V7EqOaNBMtD1GgpAmGROsmfHJPXNLCU9bfIuLrkdOygltK784F6Crboyd5tBFayPB7Sf0McrQwg==", - "dev": true, "dependencies": { "@typescript-eslint/scope-manager": "6.4.1", "@typescript-eslint/types": "6.4.1", @@ -15509,7 +15518,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1" @@ -15526,7 +15534,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", - "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -15539,7 +15546,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1", @@ -15566,7 +15572,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" @@ -15583,7 +15588,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15595,7 +15599,6 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0" @@ -15612,7 +15615,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.4.1.tgz", "integrity": "sha512-7ON8M8NXh73SGZ5XvIqWHjgX2f+vvaOarNliGhjrJnv1vdjG0LVIz+ToYfPirOoBi56jxAKLfsLm40+RvxVVXA==", - "dev": true, "dependencies": { "@typescript-eslint/typescript-estree": "6.4.1", "@typescript-eslint/utils": "6.4.1", @@ -15638,14 +15640,12 @@ "node_modules/@typescript-eslint/type-utils/node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz", "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1" @@ -15662,7 +15662,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz", "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==", - "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -15675,7 +15674,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz", "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "@typescript-eslint/visitor-keys": "6.4.1", @@ -15702,7 +15700,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==", - "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", @@ -15727,7 +15724,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz", "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==", - "dev": true, "dependencies": { "@typescript-eslint/types": "6.4.1", "eslint-visitor-keys": "^3.4.1" @@ -15744,7 +15740,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15756,7 +15751,6 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15769,7 +15763,6 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0", @@ -15796,7 +15789,6 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", @@ -15821,14 +15813,12 @@ "node_modules/@typescript-eslint/utils/node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" }, "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -15841,7 +15831,6 @@ "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" @@ -15858,7 +15847,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -16273,9 +16261,9 @@ } }, "node_modules/@wdio/repl/node_modules/@types/node": { - "version": "20.16.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", - "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", + "version": "20.16.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.15.tgz", + "integrity": "sha512-DV58qQz9dBMqVVn+qnKwGa51QzCD4YM/tQM16qLKxdf5tqz5W4QwtrMzjSTbabN1cFTSuyxVYBy+QWHjWW8X/g==", "dev": true, "license": "MIT", "dependencies": { @@ -16302,9 +16290,9 @@ } }, "node_modules/@wdio/types/node_modules/@types/node": { - "version": "20.16.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", - "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", + "version": "20.16.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.15.tgz", + "integrity": "sha512-DV58qQz9dBMqVVn+qnKwGa51QzCD4YM/tQM16qLKxdf5tqz5W4QwtrMzjSTbabN1cFTSuyxVYBy+QWHjWW8X/g==", "dev": true, "license": "MIT", "dependencies": { @@ -16870,7 +16858,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -16880,14 +16867,12 @@ "node_modules/@webassemblyjs/helper-numbers/node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, "node_modules/@webassemblyjs/helper-numbers/node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.9.0", @@ -17015,7 +17000,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true, "engines": { "node": ">=14.15.0" }, @@ -17028,7 +17012,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true, "engines": { "node": ">=14.15.0" }, @@ -17041,7 +17024,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true, "engines": { "node": ">=14.15.0" }, @@ -17143,6 +17125,10 @@ "resolved": "packages/create-block", "link": true }, + "node_modules/@wordpress/create-block-interactive-template": { + "resolved": "packages/create-block-interactive-template", + "link": true + }, "node_modules/@wordpress/create-block-tutorial-template": { "resolved": "packages/create-block-tutorial-template", "link": true @@ -17467,14 +17453,12 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "node_modules/@yarnpkg/esbuild-plugin-pnp": { "version": "3.0.0-rc.15", @@ -17569,8 +17553,7 @@ "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" }, "node_modules/abbrev": { "version": "1.1.1", @@ -17617,7 +17600,6 @@ "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "dev": true, "peerDependencies": { "acorn": "^8" } @@ -17626,7 +17608,6 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -17659,7 +17640,6 @@ "version": "0.5.9", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz", "integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==", - "dev": true, "engines": { "node": ">=6.0" } @@ -17668,7 +17648,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, "dependencies": { "debug": "4" }, @@ -17692,7 +17671,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", @@ -17706,7 +17684,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -17716,7 +17693,6 @@ "version": "8.7.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.7.1.tgz", "integrity": "sha512-gPpOObTO1QjbnN1sVMjJcp1TF9nggMfO4MBR5uQl6ZVTOaEPq5i4oq/6R9q2alMMPB3eg53wFv1RuJBLuxf3Hw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -17732,7 +17708,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true, "peerDependencies": { "ajv": ">=5.0.0" } @@ -17741,7 +17716,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, "dependencies": { "ajv": "^8.0.0" }, @@ -17758,7 +17732,6 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -17766,8 +17739,7 @@ "node_modules/ajv/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/anser": { "version": "1.4.10", @@ -17778,7 +17750,6 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, "engines": { "node": ">=6" } @@ -17787,7 +17758,6 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, "dependencies": { "type-fest": "^0.21.3" }, @@ -17802,7 +17772,6 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, "engines": { "node": ">=10" }, @@ -17867,7 +17836,6 @@ "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, "engines": [ "node >= 0.8.0" ], @@ -18594,7 +18562,6 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", - "dev": true, "engines": { "node": ">=14" } @@ -18660,7 +18627,6 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", - "dev": true, "dependencies": { "@babel/runtime": "^7.10.2", "@babel/runtime-corejs3": "^7.10.2" @@ -18691,7 +18657,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -18700,7 +18665,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "is-array-buffer": "^3.0.1" @@ -18721,8 +18685,7 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/array-ify": { "version": "1.0.0", @@ -18734,7 +18697,6 @@ "version": "3.1.6", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -18752,14 +18714,12 @@ "node_modules/array-iterate": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.2.tgz", - "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==", - "dev": true + "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==" }, "node_modules/array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", - "dev": true, "dependencies": { "array-uniq": "^1.0.1" }, @@ -18771,7 +18731,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -18789,7 +18748,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -18807,7 +18765,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -18825,7 +18782,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", - "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.2", @@ -18845,7 +18801,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -18916,8 +18871,7 @@ "node_modules/ast-types-flow": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", - "dev": true + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" }, "node_modules/astral-regex": { "version": "1.0.0", @@ -18976,8 +18930,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/at-least-node": { "version": "1.0.0", @@ -19009,7 +18962,6 @@ "version": "10.4.14", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -19041,8 +18993,7 @@ "node_modules/autoprefixer/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/autosize": { "version": "4.0.2", @@ -19053,7 +19004,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -19065,7 +19015,6 @@ "version": "4.7.2", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==", - "dev": true, "engines": { "node": ">=4" } @@ -19084,14 +19033,12 @@ "node_modules/axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", - "dev": true + "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==" }, "node_modules/b4a": { "version": "1.6.4", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", - "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==", - "dev": true + "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==" }, "node_modules/babel-core": { "version": "7.0.0-bridge.0", @@ -19105,7 +19052,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, "dependencies": { "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", @@ -19327,7 +19273,6 @@ "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -19343,7 +19288,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -19369,47 +19313,51 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.3.tgz", - "integrity": "sha512-NDZ0auNRzmAfE1oDDPW2JhzIMXUk+FFe2ICejmt5T4ocKgiQx3e0VCRx9NCAidcMtL2RUZaWtXnmjTCkx0tcbA==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.2.4", - "semver": "^6.1.1" + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.3.0.tgz", - "integrity": "sha512-JLwi9vloVdXLjzACL80j24bG6/T1gYxwowG44dg6HN/7aTPdyPbJJidf6ajoA3RPHHtW0j9KMrSOLpIZpAnPpg==", + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.2.4", - "core-js-compat": "^3.18.0" + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.3.tgz", - "integrity": "sha512-JVE78oRZPKFIeUqFGrSORNzQnrDwZR16oiWeGM8ZyjBn2XAT5OjP+wXx5ESuo33nUsFUEJYjtklnsKbxW5L+7g==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.2.4" + "@babel/helper-define-polyfill-provider": "^0.6.2" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-react-native-classname-to-style": { @@ -19451,7 +19399,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", @@ -19512,7 +19459,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" @@ -19528,7 +19474,6 @@ "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz", "integrity": "sha512-zeCYxDePWYAT/DfmQWIHsMSFW2vv45UIwIAMjGvQVsTd47RwsiRH0uK1yzyWZ7LDBKdhnGDPM6NYEO5CZyhPrg==", - "dev": true, "dependencies": { "core-js": "^2.4.0", "regenerator-runtime": "^0.10.0" @@ -19539,20 +19484,17 @@ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "dev": true, "hasInstallScript": true }, "node_modules/babel-runtime/node_modules/regenerator-runtime": { "version": "0.10.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==", - "dev": true + "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==" }, "node_modules/bail": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", - "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", - "dev": true + "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==" }, "node_modules/balanced-match": { "version": "1.0.2", @@ -19563,14 +19505,12 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.2.1.tgz", "integrity": "sha512-9GYPpsPFvrWBkelIhOhTWtkeZxVxZOdb3VnFTCzlOo3OjvmTvzLoZFUT8kNFACx0vJej6QPney1Cf9BvzCNE/A==", - "dev": true, "optional": true }, "node_modules/bare-fs": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.2.2.tgz", "integrity": "sha512-X9IqgvyB0/VA5OZJyb5ZstoN62AzD7YxVGog13kkfYWYqJYcK0kcqLZ6TrmH5qr4/8//ejVcX4x/a0UvaogXmA==", - "dev": true, "optional": true, "dependencies": { "bare-events": "^2.0.0", @@ -19583,14 +19523,12 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.2.1.tgz", "integrity": "sha512-OwPyHgBBMkhC29Hl3O4/YfxW9n7mdTr2+SsO29XBWKKJsbgj3mnorDB80r5TiCQgQstgE5ga1qNYrpes6NvX2w==", - "dev": true, "optional": true }, "node_modules/bare-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.0.tgz", "integrity": "sha512-DIIg7ts8bdRKwJRJrUMy/PICEaQZaPGZ26lsSx9MJSwIhSrcdHn7/C8W+XmnG/rKi6BaRcz+JO00CjZteybDtw==", - "dev": true, "optional": true, "dependencies": { "bare-os": "^2.1.0" @@ -19680,7 +19618,6 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.3.tgz", "integrity": "sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==", - "dev": true, "engines": { "node": ">=10.0.0" } @@ -19688,8 +19625,7 @@ "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, "node_modules/before-after-hook": { "version": "1.4.0", @@ -19752,7 +19688,6 @@ "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true, "engines": { "node": ">=0.6" } @@ -19761,7 +19696,6 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, "engines": { "node": "*" } @@ -19783,7 +19717,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, "engines": { "node": ">=8" }, @@ -19868,7 +19801,6 @@ "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dev": true, "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.4", @@ -19892,7 +19824,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -19901,7 +19832,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "dependencies": { "ms": "2.0.0" } @@ -19910,7 +19840,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -19919,7 +19848,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -19931,7 +19859,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, "dependencies": { "ee-first": "1.1.1" }, @@ -19943,7 +19870,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", - "dev": true, "dependencies": { "array-flatten": "^2.1.2", "dns-equal": "^1.0.0", @@ -19954,8 +19880,7 @@ "node_modules/bonjour-service/node_modules/array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" }, "node_modules/boolbase": { "version": "1.0.0", @@ -19975,7 +19900,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, "dependencies": { "big-integer": "^1.6.44" }, @@ -20192,7 +20116,6 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, "engines": { "node": "*" } @@ -20230,7 +20153,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, "engines": { "node": ">=6" }, @@ -20247,14 +20169,12 @@ "node_modules/builtins": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", - "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==", - "dev": true + "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==" }, "node_modules/bundle-name": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dev": true, "dependencies": { "run-applescript": "^5.0.0" }, @@ -20388,7 +20308,6 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, "engines": { "node": ">=10.6.0" } @@ -20397,7 +20316,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dev": true, "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", @@ -20415,7 +20333,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -20498,7 +20415,6 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, "dependencies": { "camelcase": "^5.3.1", "map-obj": "^4.0.0", @@ -20515,7 +20431,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, "engines": { "node": ">=8" }, @@ -20532,7 +20447,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, "dependencies": { "browserslist": "^4.0.0", "caniuse-lite": "^1.0.0", @@ -20581,8 +20495,7 @@ "node_modules/ccount": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz", - "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", - "dev": true + "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==" }, "node_modules/chainsaw": { "version": "0.1.0", @@ -20662,7 +20575,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, "engines": { "node": ">=10" } @@ -20670,38 +20582,32 @@ "node_modules/character-entities": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", - "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==", - "dev": true + "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==" }, "node_modules/character-entities-html4": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz", - "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==", - "dev": true + "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==" }, "node_modules/character-entities-legacy": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", - "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==", - "dev": true + "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==" }, "node_modules/character-reference-invalid": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", - "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", - "dev": true + "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==" }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, "node_modules/check-node-version": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/check-node-version/-/check-node-version-4.1.0.tgz", "integrity": "sha512-TSXGsyfW5/xY2QseuJn8/hleO2AU7HxVCdkc900jp1vcfzF840GkjvRT7CHl8sRtWn23n3X3k0cwH9RXeRwhfw==", - "dev": true, "dependencies": { "chalk": "^3.0.0", "map-values": "^1.0.1", @@ -20721,7 +20627,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -20734,7 +20639,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -20743,7 +20647,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -20752,7 +20655,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -20764,7 +20666,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -20788,7 +20689,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -20845,7 +20745,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, "engines": { "node": ">=6.0" } @@ -20854,7 +20753,6 @@ "version": "0.4.16", "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.16.tgz", "integrity": "sha512-7ZbXdWERxRxSwo3txsBjjmc/NLxqb1Bk30mRb0BMS4YIaiV6zvKZqL/UAH+DdqcDYayDWk2n/y8klkBDODrPvA==", - "dev": true, "dependencies": { "mitt": "3.0.0" }, @@ -20953,8 +20851,7 @@ "node_modules/cjs-module-lexer": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" }, "node_modules/class-utils": { "version": "0.3.6", @@ -20999,7 +20896,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, "engines": { "node": ">=6" } @@ -21008,7 +20904,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", - "dev": true, "dependencies": { "@types/webpack": "^4.4.31", "del": "^4.1.1" @@ -21150,8 +21045,7 @@ "node_modules/cli-width": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", - "dev": true + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==" }, "node_modules/client-zip": { "version": "2.4.5", @@ -21230,7 +21124,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, "dependencies": { "mimic-response": "^1.0.0" }, @@ -21259,7 +21152,6 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" @@ -21277,14 +21169,12 @@ "node_modules/collapse-white-space": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz", - "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", - "dev": true + "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==" }, "node_modules/collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==" }, "node_modules/collection-visit": { "version": "1.0.0", @@ -21405,7 +21295,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -21422,7 +21311,6 @@ "version": "9.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz", "integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==", - "dev": true, "engines": { "node": "^12.20.0 || >=14" } @@ -21431,7 +21319,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.0.tgz", "integrity": "sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==", - "dev": true, "engines": { "node": ">= 12.0.0" } @@ -21439,8 +21326,7 @@ "node_modules/common-path-prefix": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "dev": true + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==" }, "node_modules/commondir": { "version": "1.0.1", @@ -21555,7 +21441,6 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, "engines": [ "node >= 0.8" ], @@ -21705,7 +21590,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, "dependencies": { "dot-prop": "^5.2.0", "graceful-fs": "^4.1.2", @@ -21722,7 +21606,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -21748,7 +21631,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true, "engines": { "node": ">=0.8" } @@ -21799,7 +21681,6 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, "dependencies": { "safe-buffer": "5.2.1" }, @@ -21811,7 +21692,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -21831,7 +21711,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -22105,7 +21984,6 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -22113,8 +21991,7 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/copy-concurrently": { "version": "1.0.5", @@ -22186,14 +22063,12 @@ "node_modules/copy-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/copy-dir/-/copy-dir-1.3.0.tgz", - "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==", - "dev": true + "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==" }, "node_modules/copy-webpack-plugin": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.0.tgz", "integrity": "sha512-my6iXII95c78w14HzYCNya5TlJYa44lOppAge5GSTMM1SyDxNsVGCJvhP4/ld6snm8lzjn3XOonMZD6s1L86Og==", - "dev": true, "dependencies": { "fast-glob": "^3.2.7", "glob-parent": "^6.0.1", @@ -22217,7 +22092,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -22234,7 +22108,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -22246,7 +22119,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", - "dev": true, "engines": { "node": ">=12" }, @@ -22258,7 +22130,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -22270,7 +22141,6 @@ "version": "12.2.0", "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", - "dev": true, "dependencies": { "array-union": "^3.0.1", "dir-glob": "^3.0.1", @@ -22289,14 +22159,12 @@ "node_modules/copy-webpack-plugin/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/copy-webpack-plugin/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -22315,7 +22183,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -22324,7 +22191,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true, "engines": { "node": ">=12" }, @@ -22621,7 +22487,6 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.31.0.tgz", "integrity": "sha512-/AnE9Y4OsJZicCzIe97JP5XoPKQJfTuEG43aEVLFJGOJpyqELod+pE6LEl63DfG1Mp8wX97LDaDpy1GmLEUxlg==", - "dev": true, "hasInstallScript": true, "funding": { "type": "opencollective", @@ -22764,7 +22629,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", - "dev": true, "license": "MIT", "dependencies": { "node-fetch": "^2.6.12" @@ -22774,7 +22638,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", - "dev": true, "dependencies": { "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", @@ -22807,7 +22670,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true, "engines": { "node": ">=8" } @@ -22815,8 +22677,7 @@ "node_modules/csp_evaluator": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/csp_evaluator/-/csp_evaluator-1.1.1.tgz", - "integrity": "sha512-N3ASg0C4kNPUaNxt1XAvzHIVuzdtr8KLgfk1O8WDyimp1GisPAHESupArO2ieHk9QWbrJ/WkQODyh21Ps/xhxw==", - "dev": true + "integrity": "sha512-N3ASg0C4kNPUaNxt1XAvzHIVuzdtr8KLgfk1O8WDyimp1GisPAHESupArO2ieHk9QWbrJ/WkQODyh21Ps/xhxw==" }, "node_modules/css": { "version": "2.2.4", @@ -22841,7 +22702,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", - "dev": true, "engines": { "node": "^10 || ^12 || >=14" }, @@ -22853,7 +22713,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.2.tgz", "integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==", - "dev": true, "engines": { "node": ">=12 || >=16" } @@ -22862,7 +22721,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.2.0.tgz", "integrity": "sha512-/rvHfYRjIpymZblf49w8jYcRo2y9gj6rV8UroHGmBxKrIyGLokpycyKzp9OkitvqT29ZSpzJ0Ic7SpnJX3sC8g==", - "dev": true, "dependencies": { "icss-utils": "^5.1.0", "postcss": "^8.2.15", @@ -22887,8 +22745,7 @@ "node_modules/css-loader/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/css-mediaquery": { "version": "0.1.2", @@ -23037,7 +22894,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, "bin": { "cssesc": "bin/cssesc" }, @@ -23049,7 +22905,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.0.1.tgz", "integrity": "sha512-fVO1JdJ0LSdIGJq68eIxOqFpIJrZqXUsBt8fkrBcztCQqAjQD51OhZp7tc0ImcbwXD4k7ny84QTV90nZhmqbkg==", - "dev": true, "dependencies": { "cssnano-preset-default": "^6.0.1", "lilconfig": "^2.1.0" @@ -23069,7 +22924,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.0.1.tgz", "integrity": "sha512-7VzyFZ5zEB1+l1nToKyrRkuaJIx0zi/1npjvZfbBwbtNTzhLtlvYraK/7/uqmX2Wb2aQtd983uuGw79jAjLSuQ==", - "dev": true, "dependencies": { "css-declaration-sorter": "^6.3.1", "cssnano-utils": "^4.0.0", @@ -23112,7 +22966,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.0.tgz", "integrity": "sha512-Z39TLP+1E0KUcd7LGyF4qMfu8ZufI0rDzhdyAMsa/8UyNUU8wpS0fhdBxbQbv32r64ea00h4878gommRVg2BHw==", - "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -23124,7 +22977,6 @@ "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dev": true, "dependencies": { "css-tree": "~2.2.0" }, @@ -23137,7 +22989,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dev": true, "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" @@ -23150,14 +23001,12 @@ "node_modules/csso/node_modules/mdn-data": { "version": "2.0.28", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "dev": true + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" }, "node_modules/csso/node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -23167,7 +23016,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", - "dev": true, "dependencies": { "rrweb-cssom": "^0.7.1" }, @@ -23184,7 +23032,6 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.10.0.tgz", "integrity": "sha512-YGZxdTTL9lmLkCUTpg4j0zQ7IhRB5ZmqNBbGCl3Tg6MP/d5/6sY7L5mmTjzbc6JKgVZYiqTQTNhPFsbXNGlRaA==", - "dev": true, "dependencies": { "find-pkg": "^0.1.2", "fs-exists-sync": "^0.1.0" @@ -23202,8 +23049,7 @@ "node_modules/damerau-levenshtein": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz", - "integrity": "sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==", - "dev": true + "integrity": "sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==" }, "node_modules/dargs": { "version": "7.0.0", @@ -23218,7 +23064,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-5.0.1.tgz", "integrity": "sha512-a9l6T1qqDogvvnw0nKlfZzqsyikEBZBClF39V3TFoKhDtGBqHu2HkuomJc02j5zft8zrUaXEuoicLeW54RkzPg==", - "dev": true, "engines": { "node": ">= 14" } @@ -23227,7 +23072,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", - "dev": true, "dependencies": { "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0" @@ -23240,7 +23084,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", - "dev": true, "dependencies": { "punycode": "^2.3.1" }, @@ -23252,7 +23095,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, "engines": { "node": ">=12" } @@ -23261,7 +23103,6 @@ "version": "14.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", - "dev": true, "dependencies": { "tr46": "^5.0.0", "webidl-conversions": "^7.0.0" @@ -23335,7 +23176,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", - "dev": true, "dependencies": { "decamelize": "^1.1.0", "map-obj": "^1.0.0" @@ -23347,8 +23187,7 @@ "node_modules/decimal.js": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" }, "node_modules/decode-uri-component": { "version": "0.2.2", @@ -23362,7 +23201,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, "dependencies": { "mimic-response": "^3.1.0" }, @@ -23377,7 +23215,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -23395,7 +23232,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, "engines": { "node": ">=4.0.0" } @@ -23409,8 +23245,7 @@ "node_modules/deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, "node_modules/deepmerge": { "version": "4.3.1", @@ -23433,7 +23268,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", - "dev": true, "dependencies": { "bundle-name": "^3.0.0", "default-browser-id": "^3.0.0", @@ -23451,7 +23285,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dev": true, "dependencies": { "bplist-parser": "^0.2.0", "untildify": "^4.0.0" @@ -23467,7 +23300,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -23481,7 +23313,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.1", @@ -23504,7 +23335,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, "engines": { "node": ">=10" }, @@ -23516,7 +23346,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, "engines": { "node": ">=14.18.0" } @@ -23525,7 +23354,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -23537,7 +23365,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, "engines": { "node": ">=12" }, @@ -23549,7 +23376,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, "dependencies": { "path-key": "^4.0.0" }, @@ -23564,7 +23390,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -23576,7 +23401,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, "dependencies": { "mimic-fn": "^4.0.0" }, @@ -23591,7 +23415,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -23600,7 +23423,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -23612,7 +23434,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -23621,7 +23442,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, "engines": { "node": ">=12" }, @@ -23633,7 +23453,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -23648,7 +23467,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, "dependencies": { "execa": "^5.0.0" }, @@ -23660,7 +23478,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -23674,7 +23491,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -23697,7 +23513,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, "engines": { "node": ">=10" }, @@ -23709,7 +23524,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, "engines": { "node": ">=10.17.0" } @@ -23718,7 +23532,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" }, @@ -23730,7 +23543,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -23739,7 +23551,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -23751,7 +23562,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -23766,7 +23576,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -23775,7 +23584,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -23787,7 +23595,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -23796,7 +23603,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -23819,7 +23625,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, "engines": { "node": ">=10" } @@ -23828,7 +23633,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -23845,7 +23649,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, "engines": { "node": ">=8" } @@ -23854,7 +23657,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dev": true, "dependencies": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" @@ -23902,7 +23704,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, "dependencies": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", @@ -23916,7 +23717,6 @@ "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, "dependencies": { "tslib": "^2.0.1" }, @@ -23928,7 +23728,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, "dependencies": { "@types/glob": "^7.1.1", "globby": "^6.1.0", @@ -23946,7 +23745,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -23966,7 +23764,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", - "dev": true, "dependencies": { "array-union": "^1.0.1", "glob": "^7.0.3", @@ -23982,7 +23779,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -23991,7 +23787,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true, "engines": { "node": ">=6" } @@ -24000,7 +23795,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, "engines": { "node": ">=6" } @@ -24009,7 +23803,6 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -24021,7 +23814,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -24046,7 +23838,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -24064,8 +23855,7 @@ "node_modules/deprecation": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" }, "node_modules/dequal": { "version": "2.0.3", @@ -24099,7 +23889,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", "integrity": "sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==", - "dev": true, "engines": { "node": ">=4" } @@ -24118,7 +23907,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, "engines": { "node": ">=8" } @@ -24126,8 +23914,7 @@ "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" }, "node_modules/detect-node-es": { "version": "1.1.0", @@ -24315,7 +24102,6 @@ "version": "0.0.1312386", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz", "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/diff": { @@ -24330,7 +24116,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -24356,7 +24141,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, "dependencies": { "path-type": "^4.0.0" }, @@ -24368,7 +24152,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -24376,14 +24159,12 @@ "node_modules/dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", - "dev": true + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dev": true, "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" }, @@ -24395,7 +24176,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -24491,7 +24271,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, "dependencies": { "is-obj": "^2.0.0" }, @@ -24503,7 +24282,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, "engines": { "node": ">=8" } @@ -24532,8 +24310,7 @@ "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" }, "node_modules/duplexer2": { "version": "0.1.4", @@ -24746,7 +24523,6 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -24763,7 +24539,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, "engines": { "node": ">= 4" } @@ -24794,7 +24569,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "dependencies": { "once": "^1.4.0" } @@ -24841,7 +24615,6 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, "dependencies": { "ansi-colors": "^4.1.1" }, @@ -24858,7 +24631,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, "engines": { "node": ">=6" } @@ -24930,7 +24702,6 @@ "version": "1.22.1", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", - "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "arraybuffer.prototype.slice": "^1.0.1", @@ -24983,7 +24754,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -24995,7 +24765,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -25029,14 +24798,12 @@ "node_modules/es-module-lexer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", - "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", - "dev": true + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" }, "node_modules/es-set-tostringtag": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dev": true, "dependencies": { "get-intrinsic": "^1.1.3", "has": "^1.0.3", @@ -25050,7 +24817,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, "dependencies": { "has": "^1.0.3" } @@ -25059,7 +24825,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -25164,7 +24929,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -25185,7 +24949,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -25194,7 +24957,6 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz", "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==", - "dev": true, "dependencies": { "@eslint/eslintrc": "^1.0.4", "@humanwhocodes/config-array": "^0.6.0", @@ -25249,7 +25011,6 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", - "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -25280,7 +25041,6 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz", "integrity": "sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ==", - "dev": true, "dependencies": { "debug": "^3.2.7", "find-up": "^2.1.0", @@ -25294,7 +25054,6 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -25302,8 +25061,7 @@ "node_modules/eslint-module-utils/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/eslint-plugin-eslint-comments": { "version": "3.1.2", @@ -25325,7 +25083,6 @@ "version": "2.25.2", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.2.tgz", "integrity": "sha512-qCwQr9TYfoBHOFcVGKY9C9unq05uOxxdklmBXLVvcwo68y5Hta6/GzCZEMx2zQiu0woKNEER0LE7ZgaOfBU14g==", - "dev": true, "dependencies": { "array-includes": "^3.1.4", "array.prototype.flat": "^1.2.5", @@ -25352,7 +25109,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "dependencies": { "ms": "2.0.0" } @@ -25361,7 +25117,6 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -25372,7 +25127,6 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -25380,14 +25134,12 @@ "node_modules/eslint-plugin-import/node_modules/eslint-import-resolver-node/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/eslint-plugin-jest": { "version": "27.2.3", "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz", "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==", - "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" }, @@ -25431,7 +25183,6 @@ "version": "46.4.6", "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.6.tgz", "integrity": "sha512-z4SWYnJfOqftZI+b3RM9AtWL1vF/sLWE/LlO9yOKDof9yN2+n3zOdOJTGX/pRE/xnPsooOLG2Rq6e4d+XW3lNw==", - "dev": true, "dependencies": { "@es-joy/jsdoccomment": "~0.40.1", "are-docs-informative": "^0.0.2", @@ -25454,7 +25205,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -25466,7 +25216,6 @@ "version": "6.5.1", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz", "integrity": "sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==", - "dev": true, "dependencies": { "@babel/runtime": "^7.16.3", "aria-query": "^4.2.2", @@ -25491,14 +25240,12 @@ "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/eslint-plugin-playwright": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-0.15.3.tgz", "integrity": "sha512-LQMW5y0DLK5Fnpya7JR1oAYL2/7Y9wDiYw6VZqlKqcRGSgjbVKNqxraphk7ra1U3Bb5EK444xMgUlQPbMg2M1g==", - "dev": true, "peerDependencies": { "eslint": ">=7", "eslint-plugin-jest": ">=25" @@ -25513,7 +25260,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz", "integrity": "sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==", - "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.8.5" @@ -25542,7 +25288,6 @@ "version": "7.27.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.27.0.tgz", "integrity": "sha512-0Ut+CkzpppgFtoIhdzi2LpdpxxBvgFf99eFqWxJnUrO7mMe0eOiNpou6rvNYeVVV6lWZvTah0BFne7k5xHjARg==", - "dev": true, "dependencies": { "array-includes": "^3.1.4", "array.prototype.flatmap": "^1.2.5", @@ -25570,7 +25315,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz", "integrity": "sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==", - "dev": true, "engines": { "node": ">=10" }, @@ -25582,7 +25326,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -25591,7 +25334,6 @@ "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -25608,7 +25350,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -25685,7 +25426,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, "dependencies": { "eslint-visitor-keys": "^2.0.0" }, @@ -25703,7 +25443,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, "engines": { "node": ">=10" } @@ -25712,7 +25451,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -25727,14 +25465,12 @@ "node_modules/eslint/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/eslint/node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -25748,7 +25484,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -25760,7 +25495,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -25772,7 +25506,6 @@ "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -25788,7 +25521,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -25800,7 +25532,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -25809,7 +25540,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -25821,7 +25551,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, "engines": { "node": ">= 4" } @@ -25830,7 +25559,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -25842,7 +25570,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -25855,7 +25582,6 @@ "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -25872,7 +25598,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -25881,7 +25606,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, "engines": { "node": ">= 0.8.0" } @@ -25890,7 +25614,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -25902,7 +25625,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -25911,7 +25633,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -25923,7 +25644,6 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -25935,7 +25655,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -25950,7 +25669,6 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/espree/-/espree-9.1.0.tgz", "integrity": "sha512-ZgYLvCS1wxOczBYGcQT9DDWgicXwJ4dbocr9uYN+/eresBAUuBu+O4WzB21ufQ/JqQT8gyp7hJ3z8SHii32mTQ==", - "dev": true, "dependencies": { "acorn": "^8.6.0", "acorn-jsx": "^5.3.1", @@ -25961,10 +25679,9 @@ } }, "node_modules/espree/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -25977,7 +25694,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -26001,7 +25717,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -26013,7 +25728,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -26022,7 +25736,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -26034,7 +25747,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -26043,7 +25755,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, "engines": { "node": ">=4.0" } @@ -26052,7 +25763,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -26081,14 +25791,12 @@ "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, "engines": { "node": ">=0.8.x" } @@ -26107,7 +25815,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz", "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", @@ -26130,7 +25837,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -26144,7 +25850,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" }, @@ -26156,7 +25861,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -26165,7 +25869,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -26177,7 +25880,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -26192,7 +25894,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -26201,7 +25902,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -26213,7 +25913,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -26222,7 +25921,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -26237,7 +25935,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, "engines": { "node": ">= 0.8.0" } @@ -26307,7 +26004,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", "integrity": "sha512-rtmc+cjLZqnu9dSYosX9EWmSJhTwpACgJQTfj4hgg2JjOD/6SIQalZrt4a3aQeh++oNxkazcaxrhPUj6+g5G/Q==", - "dev": true, "dependencies": { "os-homedir": "^1.0.1" }, @@ -26319,7 +26015,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz", "integrity": "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==", - "dev": true, "dependencies": { "@jest/expect-utils": "^29.6.2", "@types/node": "*", @@ -26335,8 +26030,7 @@ "node_modules/expect-puppeteer": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/expect-puppeteer/-/expect-puppeteer-4.4.0.tgz", - "integrity": "sha512-6Ey4Xy2xvmuQu7z7YQtMsaMV0EHJRpVxIDOd5GRrm04/I3nkTKIutELfECsLp6le+b3SSa3cXhPiw6PgqzxYWA==", - "dev": true + "integrity": "sha512-6Ey4Xy2xvmuQu7z7YQtMsaMV0EHJRpVxIDOd5GRrm04/I3nkTKIutELfECsLp6le+b3SSa3cXhPiw6PgqzxYWA==" }, "node_modules/exponential-backoff": { "version": "3.1.1", @@ -26348,7 +26042,6 @@ "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -26390,7 +26083,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "dependencies": { "ms": "2.0.0" } @@ -26399,7 +26091,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -26408,7 +26099,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -26426,7 +26116,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, "dependencies": { "ee-first": "1.1.1" }, @@ -26438,7 +26127,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -26458,7 +26146,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -26466,8 +26153,7 @@ "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "node_modules/extend-shallow": { "version": "3.0.2", @@ -26510,7 +26196,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", - "dev": true, "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", @@ -26524,7 +26209,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -26592,7 +26276,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", - "dev": true, "dependencies": { "concat-stream": "^1.6.2", "debug": "^2.6.9", @@ -26607,7 +26290,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "dependencies": { "ms": "2.0.0" } @@ -26616,7 +26298,6 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, "dependencies": { "minimist": "^1.2.6" }, @@ -26648,20 +26329,17 @@ "node_modules/fast-diff": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" }, "node_modules/fast-fifo": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.0.tgz", - "integrity": "sha512-IgfweLvEpwyA4WgiQe9Nx6VV2QkML2NkvZnk1oKnIzXgXdWxuhF7zw4DvLTPZJn6PIUneiAXPF24QmoEqHTjyw==", - "dev": true + "integrity": "sha512-IgfweLvEpwyA4WgiQe9Nx6VV2QkML2NkvZnk1oKnIzXgXdWxuhF7zw4DvLTPZJn6PIUneiAXPF24QmoEqHTjyw==" }, "node_modules/fast-glob": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -26677,7 +26355,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -26694,14 +26371,12 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "node_modules/fast-memoize": { "version": "2.5.2", @@ -26712,7 +26387,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", - "dev": true, "license": "MIT" }, "node_modules/fast-xml-parser": { @@ -26740,7 +26414,6 @@ "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, "engines": { "node": ">= 4.9.1" } @@ -26749,7 +26422,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz", "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==", - "dev": true, "dependencies": { "reusify": "^1.0.0" } @@ -26758,7 +26430,6 @@ "version": "0.11.4", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, "dependencies": { "websocket-driver": ">=0.5.1" }, @@ -26778,7 +26449,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, "dependencies": { "pend": "~1.2.0" } @@ -26841,7 +26511,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -26935,7 +26604,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", - "dev": true, "engines": { "node": ">=4" } @@ -26944,7 +26612,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.2.0.tgz", "integrity": "sha512-pkgE+4p7N1n7QieOopmn3TqJaefjdWXwEkj2XLZJLKfOgcQKkn11ahvGNgTD8mLggexLiDFQxeTs14xVU22XPA==", - "dev": true, "dependencies": { "filename-reserved-regex": "^2.0.0", "strip-outer": "^1.0.1", @@ -27135,7 +26802,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-0.1.3.tgz", "integrity": "sha512-mBxmNbVyjg1LQIIpgO8hN+ybWBgDQK8qjht+EbrTCGmmPV/sc7RF1i9stPTD6bpvXZywBdrwRYxhSdJv867L6A==", - "dev": true, "dependencies": { "fs-exists-sync": "^0.1.0", "resolve-dir": "^0.1.0" @@ -27147,14 +26813,12 @@ "node_modules/find-parent-dir": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", - "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", - "dev": true + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=" }, "node_modules/find-pkg": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-0.1.2.tgz", "integrity": "sha512-0rnQWcFwZr7eO0513HahrWafsc3CTFioEB7DRiEYCUM/70QXSY8f3mCST17HXLcPvEhzH/Ty/Bxd72ZZsr/yvw==", - "dev": true, "dependencies": { "find-file-up": "^0.1.2" }, @@ -27166,7 +26830,6 @@ "version": "1.4.7", "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.7.tgz", "integrity": "sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==", - "dev": true, "dependencies": { "chalk": "^4.0.0", "commander": "^5.1.0", @@ -27180,7 +26843,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true, "engines": { "node": ">= 6" } @@ -27194,7 +26856,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, "dependencies": { "locate-path": "^2.0.0" }, @@ -27224,7 +26885,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", @@ -27238,8 +26898,7 @@ "node_modules/flatted": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" }, "node_modules/flow-enums-runtime": { "version": "0.0.6", @@ -27274,7 +26933,6 @@ "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, "funding": [ { "type": "individual", @@ -27294,7 +26952,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, "dependencies": { "is-callable": "^1.1.3" } @@ -27303,7 +26960,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -27312,7 +26968,6 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==", - "dev": true, "dependencies": { "for-in": "^1.0.1" }, @@ -27554,7 +27209,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -27589,7 +27243,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -27598,7 +27251,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "dev": true, "engines": { "node": "*" }, @@ -27671,7 +27323,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", "integrity": "sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -27704,8 +27355,7 @@ "node_modules/fs-monkey": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", - "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==", - "dev": true + "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==" }, "node_modules/fs-write-stream-atomic": { "version": "1.0.10", @@ -27844,7 +27494,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", @@ -27861,14 +27510,12 @@ "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -28107,7 +27754,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -28167,7 +27813,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", - "dev": true, "engines": { "node": ">=8" }, @@ -28179,7 +27824,6 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", - "dev": true, "engines": { "node": ">=12" }, @@ -28191,7 +27835,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, "dependencies": { "pump": "^3.0.0" }, @@ -28206,7 +27849,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -28217,7 +27859,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.1" @@ -28233,7 +27874,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.1.tgz", "integrity": "sha512-7ZqONUVqaabogsYNWlYj0t3YZaL6dhuEueZXGF+/YVmf6dHmaFg8/6psJKqhx9QykIDKzpGcy2cn4oV4YC7V/Q==", - "dev": true, "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^5.0.1", @@ -28473,14 +28113,12 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "node_modules/global-modules": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, "dependencies": { "global-prefix": "^3.0.0" }, @@ -28492,7 +28130,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, "dependencies": { "ini": "^1.3.5", "kind-of": "^6.0.2", @@ -28506,7 +28143,6 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -28521,7 +28157,6 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -28533,7 +28168,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, "dependencies": { "define-properties": "^1.1.3" }, @@ -28548,7 +28182,6 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -28568,7 +28201,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, "engines": { "node": ">=8" } @@ -28577,7 +28209,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -28593,7 +28224,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -28604,8 +28234,7 @@ "node_modules/globjoin": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", - "dev": true + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==" }, "node_modules/good-listener": { "version": "1.2.2", @@ -28619,7 +28248,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -28631,7 +28259,6 @@ "version": "11.8.6", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, "dependencies": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", @@ -28674,8 +28301,7 @@ "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" }, "node_modules/gunzip-maybe": { "version": "1.4.2", @@ -28712,8 +28338,7 @@ "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" }, "node_modules/handlebars": { "version": "4.7.8", @@ -28740,7 +28365,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, "engines": { "node": ">=6" } @@ -28781,7 +28405,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -28798,7 +28421,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -28810,7 +28432,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -28822,7 +28443,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -28834,7 +28454,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -28958,7 +28577,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -29052,7 +28670,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, "dependencies": { "parse-passwd": "^1.0.0" }, @@ -29064,7 +28681,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -29076,7 +28692,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -29087,14 +28702,12 @@ "node_modules/hosted-git-info/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, "dependencies": { "inherits": "^2.0.1", "obuf": "^1.0.0", @@ -29111,7 +28724,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "dev": true, "dependencies": { "whatwg-encoding": "^3.1.1" }, @@ -29123,7 +28735,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", - "dev": true, "funding": [ { "type": "github", @@ -29138,8 +28749,7 @@ "node_modules/html-escaper": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", - "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", - "dev": true + "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==" }, "node_modules/html-minifier-terser": { "version": "6.1.0", @@ -29175,7 +28785,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", - "dev": true, "engines": { "node": ">=8" }, @@ -29324,14 +28933,12 @@ "node_modules/http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "node_modules/http-deceiver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" }, "node_modules/http-errors": { "version": "2.0.0", @@ -29373,7 +28980,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/http-link-header/-/http-link-header-1.1.1.tgz", "integrity": "sha512-mW3N/rTYpCn99s1do0zx6nzFZSwLH9HGfUM4ZqLWJ16ylmYaC2v5eYGqrNTQlByx8AzUgGI+V/32gXPugs1+Sw==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -29381,14 +28987,12 @@ "node_modules/http-parser-js": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", - "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", - "dev": true + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==" }, "node_modules/http-proxy": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", @@ -29425,7 +29029,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", @@ -29455,7 +29058,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" @@ -29468,7 +29070,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, "engines": { "node": ">=10" }, @@ -29486,7 +29087,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -29499,7 +29099,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, "engines": { "node": ">=8.12.0" } @@ -29543,7 +29142,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, "engines": { "node": "^10 || ^12 || >= 14" }, @@ -29580,7 +29178,6 @@ "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, "engines": { "node": ">= 4" } @@ -29589,7 +29186,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-4.0.1.tgz", "integrity": "sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==", - "dev": true, "dependencies": { "minimatch": "^3.0.4" }, @@ -29614,8 +29210,7 @@ "node_modules/image-ssim": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/image-ssim/-/image-ssim-0.2.0.tgz", - "integrity": "sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==", - "dev": true + "integrity": "sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==" }, "node_modules/import-fresh": { "version": "3.3.0", @@ -29644,7 +29239,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -29663,7 +29257,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -29676,7 +29269,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -29688,7 +29280,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -29703,7 +29294,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -29715,7 +29305,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "engines": { "node": ">=6" } @@ -29724,7 +29313,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -29733,7 +29321,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, "dependencies": { "find-up": "^4.0.0" }, @@ -29803,8 +29390,7 @@ "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "node_modules/init-package-json": { "version": "5.0.0", @@ -29873,7 +29459,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", - "dev": true, "dependencies": { "ansi-escapes": "^4.2.1", "chalk": "^3.0.0", @@ -29897,7 +29482,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -29910,7 +29494,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, "dependencies": { "restore-cursor": "^3.1.0" }, @@ -29921,14 +29504,12 @@ "node_modules/inquirer/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/inquirer/node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -29943,7 +29524,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -29952,7 +29532,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -29961,7 +29540,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -29970,7 +29548,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -29985,7 +29562,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -29998,7 +29574,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -30012,7 +29587,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -30024,7 +29598,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dev": true, "dependencies": { "get-intrinsic": "^1.2.0", "has": "^1.0.3", @@ -30038,7 +29611,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -30047,7 +29619,6 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-4.4.0.tgz", "integrity": "sha512-z+Bj2rS3LZSYU4+sNitdHrwnBhr0wO80ZJSW8EzKDBowwUe3Q/UsvgCGjrwa+HPzoGCLEb9HAjfJgo4j2Sac8w==", - "dev": true, "dependencies": { "intl-messageformat-parser": "^1.8.1" } @@ -30056,8 +29627,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.8.1.tgz", "integrity": "sha512-IMSCKVf0USrM/959vj3xac7s8f87sc+80Y/ipBzdKy4ifBv5Gsj2tZ41EAaURVg01QU71fYr77uA8Meh6kELbg==", - "deprecated": "We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser", - "dev": true + "deprecated": "We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser" }, "node_modules/invariant": { "version": "2.2.4", @@ -30076,7 +29646,6 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dev": true, "license": "MIT", "dependencies": { "jsbn": "1.1.0", @@ -30090,14 +29659,12 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, "engines": { "node": ">= 0.10" } @@ -30106,7 +29673,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.2.0.tgz", "integrity": "sha512-YqTdPLfwP7YFN0SsD3QUVCkm9ZG2VzOXv3DOrw5G5mkMbVwptTwVcFv7/C0vOpBmgTxAeTG19XpUs1E522LW9Q==", - "dev": true, "engines": { "node": ">=8" } @@ -30136,7 +29702,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", - "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -30146,7 +29711,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", "integrity": "sha512-ZmRL7++ZkcMOfDuWZuMJyIVLr2keE1o/DeNWh1EmgqGhUcV+9BIVsx0BcSBOHTZqzjs4+dISzr2KAeBEWGgXeA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -30155,7 +29719,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", - "dev": true, "dependencies": { "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0" @@ -30181,7 +29744,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.0", @@ -30200,7 +29762,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, "dependencies": { "has-bigints": "^1.0.1" }, @@ -30212,7 +29773,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -30224,7 +29784,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -30239,14 +29798,12 @@ "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "node_modules/is-builtin-module": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, "dependencies": { "builtin-modules": "^3.3.0" }, @@ -30261,7 +29818,6 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -30314,7 +29870,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -30328,8 +29883,7 @@ "node_modules/is-decimal": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", - "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", - "dev": true + "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==" }, "node_modules/is-deflate": { "version": "1.0.0", @@ -30376,7 +29930,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -30385,7 +29938,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -30402,7 +29954,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, "engines": { "node": ">=6" } @@ -30426,7 +29977,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -30446,14 +29996,12 @@ "node_modules/is-hexadecimal": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", - "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", - "dev": true + "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==" }, "node_modules/is-inside-container": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, "dependencies": { "is-docker": "^3.0.0" }, @@ -30471,7 +30019,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, "bin": { "is-docker": "cli.js" }, @@ -30525,7 +30072,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -30549,7 +30095,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -30597,7 +30142,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, "engines": { "node": ">=6" } @@ -30606,7 +30150,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, "dependencies": { "is-path-inside": "^2.1.0" }, @@ -30618,7 +30161,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, "dependencies": { "path-is-inside": "^1.0.2" }, @@ -30630,7 +30172,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, "engines": { "node": ">=10" }, @@ -30649,8 +30190,7 @@ "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" }, "node_modules/is-promise": { "version": "4.0.0", @@ -30661,7 +30201,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -30695,7 +30234,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2" }, @@ -30725,7 +30263,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -30740,7 +30277,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -30767,7 +30303,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dev": true, "dependencies": { "which-typed-array": "^1.1.11" }, @@ -30781,8 +30316,7 @@ "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, "node_modules/is-unicode-supported": { "version": "0.1.0", @@ -30808,7 +30342,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2" }, @@ -30833,7 +30366,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", - "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -30852,7 +30384,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", - "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -30897,7 +30428,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, "engines": { "node": ">=8" } @@ -30906,7 +30436,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", @@ -30922,7 +30451,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -30931,7 +30459,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", @@ -30945,7 +30472,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -30954,7 +30480,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -30966,7 +30491,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -30980,7 +30504,6 @@ "version": "3.1.6", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", - "dev": true, "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -31040,7 +30563,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz", "integrity": "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==", - "dev": true, "dependencies": { "@jest/core": "^29.6.2", "@jest/types": "^29.6.1", @@ -31066,7 +30588,6 @@ "version": "29.5.0", "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", - "dev": true, "dependencies": { "execa": "^5.0.0", "p-limit": "^3.1.0" @@ -31079,7 +30600,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -31093,7 +30613,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -31116,7 +30635,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, "engines": { "node": ">=10" }, @@ -31128,7 +30646,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, "engines": { "node": ">=10.17.0" } @@ -31137,7 +30654,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" }, @@ -31149,7 +30665,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -31158,7 +30673,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -31170,7 +30684,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -31185,7 +30698,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -31194,7 +30706,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -31206,7 +30717,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -31215,7 +30725,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -31230,7 +30739,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz", "integrity": "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==", - "dev": true, "dependencies": { "@jest/environment": "^29.6.2", "@jest/expect": "^29.6.2", @@ -31261,7 +30769,6 @@ "version": "1.5.3", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", - "dev": true, "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, @@ -31275,7 +30782,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz", "integrity": "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==", - "dev": true, "dependencies": { "@jest/core": "^29.6.2", "@jest/test-result": "^29.6.2", @@ -31309,7 +30815,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -31322,14 +30827,12 @@ "node_modules/jest-cli/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/jest-cli/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -31338,7 +30841,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -31352,7 +30854,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -31369,7 +30870,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "engines": { "node": ">=10" } @@ -31378,7 +30878,6 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -31396,7 +30895,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "engines": { "node": ">=12" } @@ -31405,7 +30903,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz", "integrity": "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==", - "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.6.2", @@ -31450,7 +30947,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -31470,7 +30966,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -31482,7 +30977,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", @@ -31497,7 +30991,6 @@ "version": "29.4.3", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", - "dev": true, "dependencies": { "detect-newline": "^3.0.0" }, @@ -31509,7 +31002,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz", "integrity": "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==", - "dev": true, "dependencies": { "@jest/types": "^29.6.1", "chalk": "^4.0.0", @@ -31525,7 +31017,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.6.2.tgz", "integrity": "sha512-7oa/+266AAEgkzae8i1awNEfTfjwawWKLpiw2XesZmaoVVj9u9t8JOYx18cG29rbPNtkUlZ8V4b5Jb36y/VxoQ==", - "dev": true, "dependencies": { "@jest/environment": "^29.6.2", "@jest/fake-timers": "^29.6.2", @@ -31576,7 +31067,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -31665,7 +31155,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz", "integrity": "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==", - "dev": true, "dependencies": { "jest-get-type": "^29.4.3", "pretty-format": "^29.6.2" @@ -31678,7 +31167,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.7.0", @@ -31693,7 +31181,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz", "integrity": "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.6.1", @@ -31726,7 +31213,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, "engines": { "node": ">=6" }, @@ -31743,7 +31229,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -31752,7 +31237,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz", "integrity": "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==", - "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", @@ -31772,7 +31256,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz", "integrity": "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==", - "dev": true, "dependencies": { "jest-regex-util": "^29.4.3", "jest-snapshot": "^29.6.2" @@ -31785,7 +31268,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz", "integrity": "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==", - "dev": true, "dependencies": { "@jest/console": "^29.6.2", "@jest/environment": "^29.6.2", @@ -31817,7 +31299,6 @@ "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -31827,7 +31308,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz", "integrity": "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==", - "dev": true, "dependencies": { "@jest/environment": "^29.6.2", "@jest/fake-timers": "^29.6.2", @@ -31860,7 +31340,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -31880,7 +31359,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz", "integrity": "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==", - "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", @@ -32064,7 +31542,6 @@ "version": "29.6.2", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz", "integrity": "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==", - "dev": true, "dependencies": { "@jest/test-result": "^29.6.2", "@jest/types": "^29.6.1", @@ -32131,14 +31608,12 @@ "node_modules/jpeg-js": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", - "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", - "dev": true + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" }, "node_modules/js-library-detector": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/js-library-detector/-/js-library-detector-6.7.0.tgz", "integrity": "sha512-c80Qupofp43y4cJ7+8TTDN/AsDwLi5oOm/plBrWI+iQt485vKXCco+yVmOwEgdo9VOdsYTuV0UlTeetVPTriXA==", - "dev": true, "engines": { "node": ">=12" } @@ -32164,7 +31639,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true, "license": "MIT" }, "node_modules/jsc-android": { @@ -32247,7 +31721,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", - "dev": true, "engines": { "node": ">=12.0.0" } @@ -32256,7 +31729,6 @@ "version": "25.0.1", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", - "dev": true, "dependencies": { "cssstyle": "^4.1.0", "data-urls": "^5.0.0", @@ -32305,7 +31777,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, "dependencies": { "debug": "^4.3.4" }, @@ -32317,7 +31788,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -32330,7 +31800,6 @@ "version": "7.0.5", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -32343,7 +31812,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", - "dev": true, "dependencies": { "punycode": "^2.3.1" }, @@ -32355,7 +31823,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, "engines": { "node": ">=12" } @@ -32364,7 +31831,6 @@ "version": "14.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", - "dev": true, "dependencies": { "tr46": "^5.0.0", "webidl-conversions": "^7.0.0" @@ -32377,7 +31843,6 @@ "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -32442,8 +31907,7 @@ "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, "node_modules/json-parse-better-errors": { "version": "1.0.2", @@ -32464,8 +31928,7 @@ "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/json-stable-stringify": { "version": "1.1.0", @@ -32488,8 +31951,7 @@ "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, "node_modules/json-stable-stringify/node_modules/isarray": { "version": "2.0.5", @@ -32516,8 +31978,7 @@ "node_modules/json2php": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/json2php/-/json2php-0.0.7.tgz", - "integrity": "sha512-dnSoUiLAoVaMXxFsVi4CrPVYMKOuDBXTghXSmMINX44RZ8WM9cXlY7UqrQnlAcODCVO7FV3+8t/5nDKAjimLfg==", - "dev": true + "integrity": "sha512-dnSoUiLAoVaMXxFsVi4CrPVYMKOuDBXTghXSmMINX44RZ8WM9cXlY7UqrQnlAcODCVO7FV3+8t/5nDKAjimLfg==" }, "node_modules/json5": { "version": "2.2.3", @@ -32533,8 +31994,7 @@ "node_modules/jsonc-parser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", - "dev": true + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==" }, "node_modules/jsonfile": { "version": "4.0.0", @@ -32582,7 +32042,6 @@ "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", @@ -32597,7 +32056,6 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, "dependencies": { "json-buffer": "3.0.1" } @@ -32640,7 +32098,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "dev": true, "engines": { "node": ">= 8" } @@ -32648,8 +32105,7 @@ "node_modules/known-css-properties": { "version": "0.34.0", "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.34.0.tgz", - "integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==", - "dev": true + "integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==" }, "node_modules/kuler": { "version": "2.0.0", @@ -32672,14 +32128,12 @@ "node_modules/language-subtag-registry": { "version": "0.3.21", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz", - "integrity": "sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==", - "dev": true + "integrity": "sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==" }, "node_modules/language-tags": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", - "dev": true, "dependencies": { "language-subtag-registry": "~0.3.2" } @@ -32688,7 +32142,6 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", - "dev": true, "dependencies": { "picocolors": "^1.0.0", "shell-quote": "^1.7.3" @@ -32698,7 +32151,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -33818,7 +33270,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -34009,7 +33460,6 @@ "version": "10.4.0", "resolved": "https://registry.npmjs.org/lighthouse/-/lighthouse-10.4.0.tgz", "integrity": "sha512-XQWHEWkJ8YxSPsxttBJORy5+hQrzbvGkYfeP3fJjyYKioWkF2MXfFqNK4ZuV4jL8pBu7Z91qnQP6In0bq1yXww==", - "dev": true, "dependencies": { "@sentry/node": "^6.17.4", "axe-core": "4.7.2", @@ -34068,14 +33518,12 @@ "node_modules/lighthouse-stack-packs": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/lighthouse-stack-packs/-/lighthouse-stack-packs-1.11.0.tgz", - "integrity": "sha512-sRr0z1S/I26VffRLq9KJsKtLk856YrJlNGmcJmbLX8dFn3MuzVPUbstuChEhqnSxZb8TZmVfthuXuwhG9vRoSw==", - "dev": true + "integrity": "sha512-sRr0z1S/I26VffRLq9KJsKtLk856YrJlNGmcJmbLX8dFn3MuzVPUbstuChEhqnSxZb8TZmVfthuXuwhG9vRoSw==" }, "node_modules/lighthouse/node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -34088,20 +33536,17 @@ "node_modules/lighthouse/node_modules/devtools-protocol": { "version": "0.0.1155343", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1155343.tgz", - "integrity": "sha512-oD9vGBV2wTc7fAzAM6KC0chSgs234V8+qDEeK+mcbRj2UvcuA7lgBztGi/opj/iahcXD3BSj8Ymvib628yy9FA==", - "dev": true + "integrity": "sha512-oD9vGBV2wTc7fAzAM6KC0chSgs234V8+qDEeK+mcbRj2UvcuA7lgBztGi/opj/iahcXD3BSj8Ymvib628yy9FA==" }, "node_modules/lighthouse/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/lighthouse/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -34110,7 +33555,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -34122,7 +33566,6 @@ "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -34139,7 +33582,6 @@ "version": "20.9.0", "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-20.9.0.tgz", "integrity": "sha512-H9fYZQzMTRrkboEfPmf7m3CLDN6JvbxXA3qTtS+dFt27tR+CsFHzPsT6pzp6lYL6bJbAPaR0HaPO6uSi+F94Pg==", - "dev": true, "dependencies": { "@puppeteer/browsers": "1.4.6", "chromium-bidi": "0.4.16", @@ -34163,14 +33605,12 @@ "node_modules/lighthouse/node_modules/puppeteer-core/node_modules/devtools-protocol": { "version": "0.0.1147663", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1147663.tgz", - "integrity": "sha512-hyWmRrexdhbZ1tcJUGpO95ivbRhWXz++F4Ko+n21AY5PNln2ovoJw+8ZMNDTtip+CNFQfrtLVh/w4009dXO/eQ==", - "dev": true + "integrity": "sha512-hyWmRrexdhbZ1tcJUGpO95ivbRhWXz++F4Ko+n21AY5PNln2ovoJw+8ZMNDTtip+CNFQfrtLVh/w4009dXO/eQ==" }, "node_modules/lighthouse/node_modules/puppeteer-core/node_modules/ws": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, "engines": { "node": ">=10.0.0" }, @@ -34191,7 +33631,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "bin": { "semver": "bin/semver" } @@ -34200,7 +33639,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -34214,7 +33652,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -34231,7 +33668,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "engines": { "node": ">=10" } @@ -34240,7 +33676,6 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -34258,7 +33693,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "engines": { "node": ">=12" } @@ -34267,7 +33701,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, "engines": { "node": ">=10" } @@ -34292,7 +33725,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", - "dev": true, "dependencies": { "uc.micro": "^1.0.1" } @@ -34815,7 +34247,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -34852,7 +34283,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -34889,14 +34319,12 @@ "node_modules/lodash.escape": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==", - "dev": true + "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==" }, "node_modules/lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "dev": true + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" }, "node_modules/lodash.get": { "version": "4.4.2", @@ -34907,8 +34335,7 @@ "node_modules/lodash.invokemap": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.invokemap/-/lodash.invokemap-4.6.0.tgz", - "integrity": "sha512-CfkycNtMqgUlfjfdh2BhKO/ZXrP8ePOX5lEU/g0R3ItJcnuxWDwokMGKx1hWcfOikmyOVx6X9IwWnDGlgKl61w==", - "dev": true + "integrity": "sha512-CfkycNtMqgUlfjfdh2BhKO/ZXrP8ePOX5lEU/g0R3ItJcnuxWDwokMGKx1hWcfOikmyOVx6X9IwWnDGlgKl61w==" }, "node_modules/lodash.ismatch": { "version": "4.4.0", @@ -34919,20 +34346,17 @@ "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, "node_modules/lodash.pullall": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.pullall/-/lodash.pullall-4.2.0.tgz", - "integrity": "sha512-VhqxBKH0ZxPpLhiu68YD1KnHmbhQJQctcipvmFnqIBDYzcIHzf3Zpu0tpeOKtR4x76p9yohc506eGdOjTmyIBg==", - "dev": true + "integrity": "sha512-VhqxBKH0ZxPpLhiu68YD1KnHmbhQJQctcipvmFnqIBDYzcIHzf3Zpu0tpeOKtR4x76p9yohc506eGdOjTmyIBg==" }, "node_modules/lodash.set": { "version": "4.3.2", @@ -34948,20 +34372,17 @@ "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==" }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" }, "node_modules/lodash.uniqby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", - "dev": true + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==" }, "node_modules/lodash.zip": { "version": "4.2.0", @@ -35219,14 +34640,12 @@ "node_modules/longest-streak": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", - "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", - "dev": true + "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==" }, "node_modules/lookup-closest-locale": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/lookup-closest-locale/-/lookup-closest-locale-6.2.0.tgz", - "integrity": "sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==", - "dev": true + "integrity": "sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==" }, "node_modules/loose-envify": { "version": "1.4.0", @@ -35251,7 +34670,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, "engines": { "node": ">=8" } @@ -35259,14 +34677,12 @@ "node_modules/lru_map": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", - "dev": true + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==" }, "node_modules/lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, "dependencies": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" @@ -35312,7 +34728,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", - "dev": true, "dependencies": { "semver": "^6.0.0" }, @@ -35324,7 +34739,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -35573,7 +34987,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -35587,8 +35000,7 @@ "node_modules/map-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-values/-/map-values-1.0.1.tgz", - "integrity": "sha512-BbShUnr5OartXJe1GeccAWtfro11hhgNJg6G9/UtWKjVGvV5U4C09cg5nk8JUevhXODaXY+hQ3xxMUKSs62ONQ==", - "dev": true + "integrity": "sha512-BbShUnr5OartXJe1GeccAWtfro11hhgNJg6G9/UtWKjVGvV5U4C09cg5nk8JUevhXODaXY+hQ3xxMUKSs62ONQ==" }, "node_modules/map-visit": { "version": "1.0.0", @@ -35860,14 +35272,12 @@ "node_modules/markdown-escapes": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz", - "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", - "dev": true + "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==" }, "node_modules/markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", - "dev": true, "dependencies": { "argparse": "^2.0.1", "entities": "~2.1.0", @@ -35882,14 +35292,12 @@ "node_modules/markdown-it/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/markdown-it/node_modules/entities": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "dev": true, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -35897,8 +35305,7 @@ "node_modules/markdown-table": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", - "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", - "dev": true + "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==" }, "node_modules/markdown-to-jsx": { "version": "7.4.1", @@ -35916,7 +35323,6 @@ "version": "0.25.1", "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.25.1.tgz", "integrity": "sha512-AG7UkLzNa1fxiOv5B+owPsPhtM4D6DoODhsJgiaNg1xowXovrYgOnLqAgOOFQpWOlHFVQUzjMY5ypNNTeov92g==", - "dev": true, "dependencies": { "markdown-it": "12.3.2" }, @@ -35928,7 +35334,6 @@ "version": "0.31.1", "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.31.1.tgz", "integrity": "sha512-keIOMwQn+Ch7MoBwA+TdkyVMuxAeZFEGmIIlvwgV0Z1TGS5MxPnRr29XCLhkNzCHU+uNKGjU+VEjLX+Z9kli6g==", - "dev": true, "dependencies": { "commander": "~9.0.0", "get-stdin": "~9.0.0", @@ -35951,14 +35356,12 @@ "node_modules/markdownlint-cli/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/markdownlint-cli/node_modules/commander": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/commander/-/commander-9.0.0.tgz", "integrity": "sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==", - "dev": true, "engines": { "node": "^12.20.0 || >=14" } @@ -35967,7 +35370,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -35987,7 +35389,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -35999,7 +35400,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -36011,7 +35411,6 @@ "version": "3.0.8", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -36022,8 +35421,7 @@ "node_modules/markdownlint-rule-helpers": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.16.0.tgz", - "integrity": "sha512-oEacRUVeTJ5D5hW1UYd2qExYI0oELdYK72k1TKGvIeYJIbqQWAz476NAc7LNixSySUhcNl++d02DvX0ccDk9/w==", - "dev": true + "integrity": "sha512-oEacRUVeTJ5D5hW1UYd2qExYI0oELdYK72k1TKGvIeYJIbqQWAz476NAc7LNixSySUhcNl++d02DvX0ccDk9/w==" }, "node_modules/marked": { "version": "4.3.0", @@ -36069,7 +35467,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", - "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -36090,7 +35487,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", - "dev": true, "dependencies": { "unist-util-modify-children": "^1.0.0", "unist-util-visit": "^1.1.0" @@ -36152,7 +35548,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", "integrity": "sha512-CcJ0mHa36QYumDKiZ2OIR+ClhfOM7zIzN+Wfy8tRZ1hpH9DKLCS+Mh4DyK5bCxzE9uxMWcbIpeNFWsg1zrj/2g==", - "dev": true, "dependencies": { "mdast-util-to-string": "^1.0.0" } @@ -36160,8 +35555,7 @@ "node_modules/mdast-util-to-string": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.5.tgz", - "integrity": "sha512-2qLt/DEOo5F6nc2VFScQiHPzQ0XXcabquRJxKMhKte8nt42o08HUxNDPk7tt0YPxnWjAT11I1SYi0X0iPnfI5A==", - "dev": true + "integrity": "sha512-2qLt/DEOo5F6nc2VFScQiHPzQ0XXcabquRJxKMhKte8nt42o08HUxNDPk7tt0YPxnWjAT11I1SYi0X0iPnfI5A==" }, "node_modules/mdn-data": { "version": "2.0.14", @@ -36171,14 +35565,12 @@ "node_modules/mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -36187,7 +35579,6 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dev": true, "dependencies": { "fs-monkey": "^1.0.4" }, @@ -36289,7 +35680,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz", "integrity": "sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==", - "dev": true, "dependencies": { "arr-union": "^3.1.0", "clone-deep": "^0.2.4", @@ -36303,7 +35693,6 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", "integrity": "sha512-we+NuQo2DHhSl+DP6jlUiAhyAjBQrYnpOk15rN6c6JSPScjiCLh8IbSU+VTcph6YS3o7mASE8a0+gbZ7ChLpgg==", - "dev": true, "dependencies": { "for-own": "^0.1.3", "is-plain-object": "^2.0.1", @@ -36319,7 +35708,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "dependencies": { "isobject": "^3.0.1" }, @@ -36331,7 +35719,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, "dependencies": { "is-buffer": "^1.1.5" }, @@ -36343,7 +35730,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", "integrity": "sha512-J1zdXCky5GmNnuauESROVu31MQSnLoYvlyEn6j2Ztk6Q5EHFIhxkMhYcv6vuDzl2XEzoRr856QwzMgWM/TmZgw==", - "dev": true, "dependencies": { "is-extendable": "^0.1.1", "kind-of": "^2.0.1", @@ -36358,7 +35744,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", "integrity": "sha512-0u8i1NZ/mg0b+W3MGGw5I7+6Eib2nx72S/QvXa0hYjEkjTknYmEYQJwGu3mLC0BrhtJjtQafTkyRUQ75Kx0LVg==", - "dev": true, "dependencies": { "is-buffer": "^1.0.2" }, @@ -36370,7 +35755,6 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", "integrity": "sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -36378,8 +35762,7 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "node_modules/merge-stream": { "version": "2.0.0", @@ -36390,7 +35773,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "engines": { "node": ">= 8" } @@ -36398,8 +35780,7 @@ "node_modules/metaviewport-parser": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/metaviewport-parser/-/metaviewport-parser-0.3.0.tgz", - "integrity": "sha512-EoYJ8xfjQ6kpe9VbVHvZTZHiOl4HL1Z18CrZ+qahvLXT7ZO4YTC2JMyt5FaUp9JJp6J4Ybb/z7IsCXZt86/QkQ==", - "dev": true + "integrity": "sha512-EoYJ8xfjQ6kpe9VbVHvZTZHiOl4HL1Z18CrZ+qahvLXT7ZO4YTC2JMyt5FaUp9JJp6J4Ybb/z7IsCXZt86/QkQ==" }, "node_modules/method-override": { "version": "3.0.0", @@ -36429,7 +35810,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -36912,7 +36292,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "dev": true, "bin": { "mime": "cli.js" }, @@ -36952,7 +36331,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, "engines": { "node": ">=4" } @@ -36961,7 +36339,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, "engines": { "node": ">=4" } @@ -36970,7 +36347,6 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.1.tgz", "integrity": "sha512-CRC6E2yedNjfOA3nQjpqAkpnranxhxmilhBPYtldnXcPT/QZb3aJFzvt0pp8W1jhuLR/E0zDa+QEHuC/HhhaLQ==", - "dev": true, "dependencies": { "schema-utils": "^4.0.0" }, @@ -36989,7 +36365,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -37006,7 +36381,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -37017,14 +36391,12 @@ "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -37042,8 +36414,7 @@ "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", @@ -37074,7 +36445,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, "dependencies": { "arrify": "^1.0.1", "is-plain-obj": "^1.1.0", @@ -37088,7 +36458,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -37249,8 +36618,7 @@ "node_modules/mitt": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", - "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==", - "dev": true + "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==" }, "node_modules/mixin-deep": { "version": "1.3.2", @@ -37293,7 +36661,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", "integrity": "sha512-ALGF1Jt9ouehcaXaHhn6t1yGWRqGaHkPFndtFVHfZXOvkIZ/yoGaSi0AHVTafb3ZBGg4dr/bDwnaEKqCXzchMA==", - "dev": true, "dependencies": { "for-in": "^0.1.3", "is-extendable": "^0.1.1" @@ -37306,7 +36673,6 @@ "version": "0.1.8", "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", "integrity": "sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -37329,8 +36695,7 @@ "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "node_modules/mock-match-media": { "version": "0.4.2", @@ -37607,7 +36972,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", - "dev": true, "engines": { "node": ">=10" } @@ -37621,7 +36985,6 @@ "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, "dependencies": { "dns-packet": "^5.2.2", "thunky": "^1.0.2" @@ -37671,7 +37034,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.0.0.tgz", "integrity": "sha512-FJgjyX/IVkbXBXYUwH+OYwQKqWpFPLaLVESd70yHjSDunwzV2hZOoTBvPf4KLoxesUzzyfTH6F784Uqd7Wm5yA==", - "dev": true, "bin": { "mustache": "bin/mustache" }, @@ -37682,8 +37044,7 @@ "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, "node_modules/mv": { "version": "2.1.1", @@ -37801,8 +37162,7 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, "node_modules/ncp": { "version": "2.0.0", @@ -37830,7 +37190,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, "engines": { "node": ">= 0.4.0" } @@ -37957,7 +37316,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, "engines": { "node": ">= 6.13.0" } @@ -38126,7 +37484,6 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -38137,14 +37494,12 @@ "node_modules/normalize-package-data/node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" }, "node_modules/normalize-package-data/node_modules/semver": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "bin": { "semver": "bin/semver" } @@ -38161,7 +37516,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -38170,7 +37524,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, "engines": { "node": ">=10" }, @@ -38187,7 +37540,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", - "dev": true, "dependencies": { "npm-normalize-package-bin": "^1.0.1" } @@ -38207,14 +37559,12 @@ "node_modules/npm-normalize-package-bin": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", - "dev": true + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" }, "node_modules/npm-package-arg": { "version": "8.1.5", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", - "dev": true, "dependencies": { "hosted-git-info": "^4.0.1", "semver": "^7.3.4", @@ -38228,7 +37578,6 @@ "version": "6.4.0", "resolved": "https://registry.npmjs.org/npm-package-json-lint/-/npm-package-json-lint-6.4.0.tgz", "integrity": "sha512-cuXAJJB1Rdqz0UO6w524matlBqDBjcNt7Ru+RDIu4y6RI1gVqiWBnylrK8sPRk81gGBA0X8hJbDXolVOoTc+sA==", - "dev": true, "dependencies": { "ajv": "^6.12.6", "ajv-errors": "^1.0.1", @@ -38260,7 +37609,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -38275,14 +37623,12 @@ "node_modules/npm-package-json-lint/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/npm-package-json-lint/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -38298,7 +37644,6 @@ "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -38324,7 +37669,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -38333,7 +37677,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -38345,14 +37688,12 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true, "license": "MIT" }, "node_modules/npm-package-json-lint/node_modules/meow": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "dev": true, "dependencies": { "@types/minimist": "^1.2.0", "camelcase-keys": "^6.2.2", @@ -38378,7 +37719,6 @@ "version": "0.18.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, "engines": { "node": ">=10" }, @@ -38390,7 +37730,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, "dependencies": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", @@ -38405,7 +37744,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -38414,7 +37752,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -38426,7 +37763,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -38438,7 +37774,6 @@ "version": "3.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true, "engines": { "node": ">=14.16" }, @@ -38450,7 +37785,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", - "dev": true, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -38459,7 +37793,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-3.0.0.tgz", "integrity": "sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ==", - "dev": true, "dependencies": { "glob": "^7.1.6", "ignore-walk": "^4.0.1", @@ -38477,7 +37810,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -38825,8 +38157,7 @@ "node_modules/nwsapi": { "version": "2.2.13", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", - "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", - "dev": true + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==" }, "node_modules/nx": { "version": "16.6.0", @@ -39559,14 +38890,12 @@ "node_modules/object-filter": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/object-filter/-/object-filter-1.0.2.tgz", - "integrity": "sha512-NahvP2vZcy1ZiiYah30CEPw0FpDcSkSePJBMpzl5EQgCmISijiGuJm3SPYp7U+Lf2TljyaIw3E5EgkEx/TNEVA==", - "dev": true + "integrity": "sha512-NahvP2vZcy1ZiiYah30CEPw0FpDcSkSePJBMpzl5EQgCmISijiGuJm3SPYp7U+Lf2TljyaIw3E5EgkEx/TNEVA==" }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -39591,7 +38920,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -39612,7 +38940,6 @@ "version": "4.1.4", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -39630,7 +38957,6 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -39644,7 +38970,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -39661,7 +38986,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.0.tgz", "integrity": "sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg==", - "dev": true, "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.19.1" @@ -39686,7 +39010,6 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -39708,8 +39031,7 @@ "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" }, "node_modules/octokit-pagination-methods": { "version": "1.1.0", @@ -39792,7 +39114,6 @@ "version": "1.5.2", "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true, "bin": { "opener": "bin/opener-bin.js" } @@ -39801,7 +39122,6 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha512-oCOQ8AIC2ciLy/sE2ehafRBleBgDLvzGhBRRev87sP7ovnbvQfqpc3XFI0DhHey2OfVoNV91W+GPC6B3540/5Q==", - "dev": true, "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.4", @@ -39818,7 +39138,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/ora/-/ora-4.1.1.tgz", "integrity": "sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A==", - "dev": true, "dependencies": { "chalk": "^3.0.0", "cli-cursor": "^3.1.0", @@ -39840,7 +39159,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -39853,7 +39171,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, "dependencies": { "restore-cursor": "^3.1.0" }, @@ -39865,7 +39182,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -39874,7 +39190,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", - "dev": true, "dependencies": { "chalk": "^2.4.2" }, @@ -39886,7 +39201,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -39898,7 +39212,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -39912,7 +39225,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "engines": { "node": ">=4" } @@ -39921,7 +39233,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -39933,7 +39244,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -39942,7 +39252,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -39957,7 +39266,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -39970,7 +39278,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -39988,7 +39295,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -40010,7 +39316,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -40019,7 +39324,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, "engines": { "node": ">=8" } @@ -40051,7 +39355,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, "dependencies": { "p-limit": "^1.1.0" }, @@ -40063,7 +39366,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, "dependencies": { "p-try": "^1.0.0" }, @@ -40136,7 +39438,6 @@ "version": "4.6.1", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", - "dev": true, "dependencies": { "@types/retry": "^0.12.0", "retry": "^0.13.1" @@ -40149,7 +39450,6 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, "engines": { "node": ">= 4" } @@ -40170,7 +39470,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, "engines": { "node": ">=4" } @@ -40194,7 +39493,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", - "dev": true, "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.0.2", @@ -40213,7 +39511,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, "dependencies": { "debug": "^4.3.4" }, @@ -40225,7 +39522,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -40238,7 +39534,6 @@ "version": "7.0.5", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -40252,7 +39547,6 @@ "version": "8.0.4", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.1", @@ -40267,7 +39561,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", - "dev": true, "dependencies": { "degenerator": "^5.0.0", "ip": "^1.1.8", @@ -40641,14 +39934,12 @@ "node_modules/parse-cache-control": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", - "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", - "dev": true + "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==" }, "node_modules/parse-entities": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", - "dev": true, "dependencies": { "character-entities": "^1.0.0", "character-entities-legacy": "^1.0.0", @@ -40688,7 +39979,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -40715,7 +40005,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, "dependencies": { "entities": "^4.4.0" }, @@ -40727,7 +40016,6 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, "engines": { "node": ">=0.12" }, @@ -40999,9 +40287,9 @@ } }, "node_modules/patch-package/node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", "dev": true, "license": "ISC", "bin": { @@ -41052,8 +40340,7 @@ "node_modules/path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", - "dev": true + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==" }, "node_modules/path-key": { "version": "2.0.1", @@ -41106,8 +40393,7 @@ "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/path-type": { "version": "3.0.0", @@ -41177,8 +40463,7 @@ "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" }, "node_modules/phpegjs": { "version": "1.0.0-beta7", @@ -41221,7 +40506,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -41230,7 +40514,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -41239,7 +40522,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", - "dev": true, "dependencies": { "pinkie": "^2.0.0" }, @@ -41259,7 +40541,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", "integrity": "sha512-ojakdnUgL5pzJYWw2AIDEupaQCX5OPbM688ZevubICjdIX01PRSYKqm33fJoCOJBRseYCTUlQRnBNX+Pchaejw==", - "dev": true, "dependencies": { "find-up": "^2.1.0" }, @@ -41330,7 +40611,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz", "integrity": "sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==", - "dev": true, "dependencies": { "irregular-plurals": "^3.2.0" }, @@ -41403,7 +40683,6 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", - "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.11", "postcss-value-parser": "^4.2.0" @@ -41418,14 +40697,12 @@ "node_modules/postcss-calc/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-colormin": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.0.0.tgz", "integrity": "sha512-EuO+bAUmutWoZYgHn2T1dG1pPqHU6L4TjzPlu4t1wZGXQ/fxV16xg2EJmYi0z+6r+MGV1yvpx1BHkUaRrPa2bw==", - "dev": true, "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0", @@ -41442,14 +40719,12 @@ "node_modules/postcss-colormin/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-convert-values": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.0.0.tgz", "integrity": "sha512-U5D8QhVwqT++ecmy8rnTb+RL9n/B806UVaS3m60lqle4YDFcpbS3ae5bTQIh3wOGUSDHSEtMYLs/38dNG7EYFw==", - "dev": true, "dependencies": { "browserslist": "^4.21.4", "postcss-value-parser": "^4.2.0" @@ -41464,14 +40739,12 @@ "node_modules/postcss-convert-values/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-discard-comments": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.0.tgz", "integrity": "sha512-p2skSGqzPMZkEQvJsgnkBhCn8gI7NzRH2683EEjrIkoMiwRELx68yoUJ3q3DGSGuQ8Ug9Gsn+OuDr46yfO+eFw==", - "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -41483,7 +40756,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.0.tgz", "integrity": "sha512-bU1SXIizMLtDW4oSsi5C/xHKbhLlhek/0/yCnoMQany9k3nPBq+Ctsv/9oMmyqbR96HYHxZcHyK2HR5P/mqoGA==", - "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -41495,7 +40767,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.0.tgz", "integrity": "sha512-b+h1S1VT6dNhpcg+LpyiUrdnEZfICF0my7HAKgJixJLW7BnNmpRH34+uw/etf5AhOlIhIAuXApSzzDzMI9K/gQ==", - "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -41507,7 +40778,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.0.tgz", "integrity": "sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw==", - "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -41519,7 +40789,6 @@ "version": "16.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz", "integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -41535,14 +40804,12 @@ "node_modules/postcss-import/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-loader": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", - "dev": true, "dependencies": { "cosmiconfig": "^7.0.0", "klona": "^2.0.5", @@ -41575,14 +40842,12 @@ "node_modules/postcss-media-query-parser": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", - "dev": true + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==" }, "node_modules/postcss-merge-longhand": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.0.tgz", "integrity": "sha512-4VSfd1lvGkLTLYcxFuISDtWUfFS4zXe0FpF149AyziftPFQIWxjvFSKhA4MIxMe4XM3yTDgQMbSNgzIVxChbIg==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0", "stylehacks": "^6.0.0" @@ -41597,14 +40862,12 @@ "node_modules/postcss-merge-longhand/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-merge-rules": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.0.1.tgz", "integrity": "sha512-a4tlmJIQo9SCjcfiCcCMg/ZCEe0XTkl/xK0XHBs955GWg9xDX3NwP9pwZ78QUOWB8/0XCjZeJn98Dae0zg6AAw==", - "dev": true, "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0", @@ -41622,7 +40885,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.0.0.tgz", "integrity": "sha512-zNRAVtyh5E8ndZEYXA4WS8ZYsAp798HiIQ1V2UF/C/munLp2r1UGHwf1+6JFu7hdEhJFN+W1WJQKBrtjhFgEnA==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41636,14 +40898,12 @@ "node_modules/postcss-minify-font-values/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-minify-gradients": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.0.tgz", "integrity": "sha512-wO0F6YfVAR+K1xVxF53ueZJza3L+R3E6cp0VwuXJQejnNUH0DjcAFe3JEBeTY1dLwGa0NlDWueCA1VlEfiKgAA==", - "dev": true, "dependencies": { "colord": "^2.9.1", "cssnano-utils": "^4.0.0", @@ -41659,14 +40919,12 @@ "node_modules/postcss-minify-gradients/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-minify-params": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.0.0.tgz", "integrity": "sha512-Fz/wMQDveiS0n5JPcvsMeyNXOIMrwF88n7196puSuQSWSa+/Ofc1gDOSY2xi8+A4PqB5dlYCKk/WfqKqsI+ReQ==", - "dev": true, "dependencies": { "browserslist": "^4.21.4", "cssnano-utils": "^4.0.0", @@ -41682,14 +40940,12 @@ "node_modules/postcss-minify-params/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-minify-selectors": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.0.tgz", "integrity": "sha512-ec/q9JNCOC2CRDNnypipGfOhbYPuUkewGwLnbv6omue/PSASbHSU7s6uSQ0tcFRVv731oMIx8k0SP4ZX6be/0g==", - "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.5" }, @@ -41704,7 +40960,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, "engines": { "node": "^10 || ^12 || >= 14" }, @@ -41716,7 +40971,6 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", - "dev": true, "dependencies": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^6.0.2", @@ -41732,14 +40986,12 @@ "node_modules/postcss-modules-local-by-default/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-modules-scope": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", - "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.4" }, @@ -41754,7 +41006,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, "dependencies": { "icss-utils": "^5.0.0" }, @@ -41769,7 +41020,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.0.tgz", "integrity": "sha512-cqundwChbu8yO/gSWkuFDmKrCZ2vJzDAocheT2JTd0sFNA4HMGoKMfbk2B+J0OmO0t5GUkiAkSM5yF2rSLUjgQ==", - "dev": true, "engines": { "node": "^14 || ^16 || >=18.0" }, @@ -41781,7 +41031,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.0.tgz", "integrity": "sha512-Qyt5kMrvy7dJRO3OjF7zkotGfuYALETZE+4lk66sziWSPzlBEt7FrUshV6VLECkI4EN8Z863O6Nci4NXQGNzYw==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41795,14 +41044,12 @@ "node_modules/postcss-normalize-display-values/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-normalize-positions": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.0.tgz", "integrity": "sha512-mPCzhSV8+30FZyWhxi6UoVRYd3ZBJgTRly4hOkaSifo0H+pjDYcii/aVT4YE6QpOil15a5uiv6ftnY3rm0igPg==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41816,14 +41063,12 @@ "node_modules/postcss-normalize-positions/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-normalize-repeat-style": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.0.tgz", "integrity": "sha512-50W5JWEBiOOAez2AKBh4kRFm2uhrT3O1Uwdxz7k24aKtbD83vqmcVG7zoIwo6xI2FZ/HDlbrCopXhLeTpQib1A==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41837,14 +41082,12 @@ "node_modules/postcss-normalize-repeat-style/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-normalize-string": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.0.tgz", "integrity": "sha512-KWkIB7TrPOiqb8ZZz6homet2KWKJwIlysF5ICPZrXAylGe2hzX/HSf4NTX2rRPJMAtlRsj/yfkrWGavFuB+c0w==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41858,14 +41101,12 @@ "node_modules/postcss-normalize-string/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-normalize-timing-functions": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.0.tgz", "integrity": "sha512-tpIXWciXBp5CiFs8sem90IWlw76FV4oi6QEWfQwyeREVwUy39VSeSqjAT7X0Qw650yAimYW5gkl2Gd871N5SQg==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41879,14 +41120,12 @@ "node_modules/postcss-normalize-timing-functions/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-normalize-unicode": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.0.tgz", "integrity": "sha512-ui5crYkb5ubEUDugDc786L/Me+DXp2dLg3fVJbqyAl0VPkAeALyAijF2zOsnZyaS1HyfPuMH0DwyY18VMFVNkg==", - "dev": true, "dependencies": { "browserslist": "^4.21.4", "postcss-value-parser": "^4.2.0" @@ -41901,14 +41140,12 @@ "node_modules/postcss-normalize-unicode/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-normalize-url": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.0.tgz", "integrity": "sha512-98mvh2QzIPbb02YDIrYvAg4OUzGH7s1ZgHlD3fIdTHLgPLRpv1ZTKJDnSAKr4Rt21ZQFzwhGMXxpXlfrUBKFHw==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41922,14 +41159,12 @@ "node_modules/postcss-normalize-url/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-normalize-whitespace": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.0.tgz", "integrity": "sha512-7cfE1AyLiK0+ZBG6FmLziJzqQCpTQY+8XjMhMAz8WSBSCsCNNUKujgIgjCAmDT3cJ+3zjTXFkoD15ZPsckArVw==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -41943,14 +41178,12 @@ "node_modules/postcss-normalize-whitespace/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-ordered-values": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.0.tgz", "integrity": "sha512-K36XzUDpvfG/nWkjs6d1hRBydeIxGpKS2+n+ywlKPzx1nMYDYpoGbcjhj5AwVYJK1qV2/SDoDEnHzlPD6s3nMg==", - "dev": true, "dependencies": { "cssnano-utils": "^4.0.0", "postcss-value-parser": "^4.2.0" @@ -41965,8 +41198,7 @@ "node_modules/postcss-ordered-values/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-prefix-selector": { "version": "1.16.1", @@ -41981,7 +41213,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz", "integrity": "sha512-s2UOnidpVuXu6JiiI5U+fV2jamAw5YNA9Fdi/GRK0zLDLCfXmSGqQtzpUPtfN66RtCbb9fFHoyZdQaxOB3WxVA==", - "dev": true, "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0" @@ -41997,7 +41228,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.0.tgz", "integrity": "sha512-FQ9f6xM1homnuy1wLe9lP1wujzxnwt1EwiigtWwuyf8FsqqXUDUp2Ulxf9A5yjlUOTdCJO6lonYjg1mgqIIi2w==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -42011,20 +41241,17 @@ "node_modules/postcss-reduce-transforms/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-resolve-nested-selector": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", - "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", - "dev": true + "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==" }, "node_modules/postcss-safe-parser": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.0.tgz", "integrity": "sha512-ovehqRNVCpuFzbXoTb4qLtyzK3xn3t/CUBxOs8LsnQjQrShaB4lKiHoVqY8ANaC0hBMHq5QVWk77rwGklFUDrg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -42050,7 +41277,6 @@ "version": "4.0.9", "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", - "dev": true, "funding": [ { "type": "opencollective", @@ -42076,7 +41302,6 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -42089,7 +41314,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.0.tgz", "integrity": "sha512-r9zvj/wGAoAIodn84dR/kFqwhINp5YsJkLoujybWG59grR/IHx+uQ2Zo+IcOwM0jskfYX3R0mo+1Kip1VSNcvw==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0", "svgo": "^3.0.2" @@ -42104,14 +41328,12 @@ "node_modules/postcss-svgo/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-unique-selectors": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.0.tgz", "integrity": "sha512-EPQzpZNxOxP7777t73RQpZE5e9TrnCrkvp7AH7a0l89JmZiPnS82y216JowHXwpBCQitfyxrof9TK3rYbi7/Yw==", - "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.5" }, @@ -42189,7 +41411,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, "engines": { "node": ">= 0.8.0" } @@ -42199,7 +41420,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/wp-prettier/-/wp-prettier-3.0.3.tgz", "integrity": "sha512-X4UlrxDTH8oom9qXlcjnydsjAOD2BmB6yFmvS4Z2zdTzqqpRWb+fbqrH412+l+OUXmbzJlSXjlMFYPgYG12IAA==", - "dev": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -42214,7 +41434,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, "dependencies": { "fast-diff": "^1.1.2" }, @@ -42297,7 +41516,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -42382,7 +41600,6 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -42395,7 +41612,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.0.tgz", "integrity": "sha512-0LdR757eTj/JfuU7TL2YCuAZnxWXu3tkJbg4Oq3geW/qFNT/32T0sp2HnZ9O0lMR4q3vwAt0+xCA8SR0WAD0og==", - "dev": true, "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", @@ -42414,7 +41630,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, "dependencies": { "debug": "^4.3.4" }, @@ -42426,7 +41641,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -42439,7 +41653,6 @@ "version": "7.0.5", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -42453,7 +41666,6 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, "engines": { "node": ">=12" } @@ -42462,7 +41674,6 @@ "version": "8.0.4", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.1", @@ -42476,8 +41687,7 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/prr": { "version": "1.0.1", @@ -42489,7 +41699,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/ps-list/-/ps-list-8.1.1.tgz", "integrity": "sha512-OPS9kEJYVmiO48u/B9qneqhkMvgCxT+Tm28VCEJpheTpl8cJ0ffZRRNgS5mrQRTrX5yRTpaJ+hRDeefXYmmorQ==", - "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -42500,8 +41709,7 @@ "node_modules/pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" }, "node_modules/public-encrypt": { "version": "4.0.3", @@ -42556,7 +41764,6 @@ "version": "23.1.0", "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.1.0.tgz", "integrity": "sha512-SvAsu+xnLN2FMXE/59bp3s3WXp8ewqUGzVV4AQtml/2xmsciZnU/bXcCW+eETHPWQ6Agg2vTI7QzWXPpEARK2g==", - "dev": true, "license": "Apache-2.0", "dependencies": { "@puppeteer/browsers": "2.3.1", @@ -42574,7 +41781,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.1.tgz", "integrity": "sha512-uK7o3hHkK+naEobMSJ+2ySYyXtQkBxIH8Gn4MK9ciePjNV+Pf+PgY/W7iPzn2MTjl3stcYB5AlcTmPYw7AXDwA==", - "dev": true, "license": "Apache-2.0", "dependencies": { "debug": "^4.3.6", @@ -42597,7 +41803,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, "license": "MIT", "dependencies": { "debug": "^4.3.4" @@ -42610,7 +41815,6 @@ "version": "0.6.4", "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.4.tgz", "integrity": "sha512-8zoq6ogmhQQkAKZVKO2ObFTl4uOkqoX1PlKQX3hZQ5E9cbUotcAb7h4pTNVAGGv8Z36PF3CtdOriEp/Rz82JqQ==", - "dev": true, "license": "Apache-2.0", "dependencies": { "mitt": "3.0.1", @@ -42625,7 +41829,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -42640,7 +41843,6 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -42658,14 +41860,12 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/puppeteer-core/node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "debug": "^4.1.1", @@ -42686,7 +41886,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.0", @@ -42700,7 +41899,6 @@ "version": "7.0.5", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -42714,7 +41912,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -42724,7 +41921,6 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -42734,21 +41930,18 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", - "dev": true, "license": "MIT" }, "node_modules/puppeteer-core/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/puppeteer-core/node_modules/proxy-agent": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -42768,7 +41961,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -42779,7 +41971,6 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -42792,7 +41983,6 @@ "version": "8.0.4", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.1", @@ -42807,7 +41997,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -42822,7 +42011,6 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", - "dev": true, "license": "MIT", "dependencies": { "pump": "^3.0.0", @@ -42837,7 +42025,6 @@ "version": "3.1.7", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, "license": "MIT", "dependencies": { "b4a": "^1.6.4", @@ -42849,7 +42036,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -42867,7 +42053,6 @@ "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -42889,7 +42074,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -42899,7 +42083,6 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "license": "MIT", "dependencies": { "cliui": "^8.0.1", @@ -42918,7 +42101,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -42928,7 +42110,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", - "dev": true, "funding": [ { "type": "individual", @@ -42944,7 +42125,6 @@ "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, "dependencies": { "side-channel": "^1.0.4" }, @@ -43026,14 +42206,12 @@ "node_modules/queue-tick": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", - "dev": true + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" }, "node_modules/quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, "engines": { "node": ">=8" } @@ -43078,7 +42256,6 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dev": true, "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -43093,7 +42270,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -43102,7 +42278,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -43945,7 +43120,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, "dependencies": { "pify": "^2.3.0" } @@ -44135,7 +43309,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", @@ -44150,7 +43323,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, "dependencies": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", @@ -44167,7 +43339,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -44180,7 +43351,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -44192,7 +43362,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -44207,7 +43376,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -44219,7 +43387,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "engines": { "node": ">=6" } @@ -44228,7 +43395,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -44237,7 +43403,6 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, "engines": { "node": ">=8" } @@ -44299,7 +43464,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -44352,7 +43516,6 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, "dependencies": { "resolve": "^1.20.0" }, @@ -44364,7 +43527,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" @@ -44377,7 +43539,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, "engines": { "node": ">=8" } @@ -44417,7 +43578,6 @@ "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, "dependencies": { "@babel/runtime": "^7.8.4" } @@ -44439,7 +43599,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -44456,7 +43615,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, "engines": { "node": ">=8" }, @@ -44512,7 +43670,6 @@ "version": "10.0.1", "resolved": "https://registry.npmjs.org/remark/-/remark-10.0.1.tgz", "integrity": "sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ==", - "dev": true, "dependencies": { "remark-parse": "^6.0.0", "remark-stringify": "^6.0.0", @@ -44579,7 +43736,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-6.0.3.tgz", "integrity": "sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg==", - "dev": true, "dependencies": { "collapse-white-space": "^1.0.2", "is-alphabetical": "^1.0.0", @@ -44656,7 +43812,6 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-6.0.4.tgz", "integrity": "sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg==", - "dev": true, "dependencies": { "ccount": "^1.0.0", "is-alphanumeric": "^1.0.0", @@ -44797,7 +43952,6 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "dev": true, "engines": { "node": ">=0.10" } @@ -44806,7 +43960,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", "integrity": "sha512-vuNYXC7gG7IeVNBC1xUllqCcZKRbJoSPOBhnTEcAIiKCsbuef6zO3F0Rve3isPMMoNoQRWjQwbAgAjHUHniyEA==", - "dev": true, "engines": { "node": ">= 0.10" } @@ -44828,7 +43981,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -44842,7 +43994,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", - "dev": true, "engines": { "node": ">=0.10.5" } @@ -44850,8 +44001,7 @@ "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "node_modules/resize-observer-polyfill": { "version": "1.5.1", @@ -44878,14 +44028,12 @@ "node_modules/resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" }, "node_modules/resolve-bin": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/resolve-bin/-/resolve-bin-0.4.0.tgz", "integrity": "sha1-RxMiSYkRAa+xmZH+k3ywpfBy5dk=", - "dev": true, "dependencies": { "find-parent-dir": "~0.3.0" } @@ -44894,7 +44042,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, "dependencies": { "resolve-from": "^5.0.0" }, @@ -44906,7 +44053,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, "engines": { "node": ">=8" } @@ -44915,7 +44061,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", "integrity": "sha512-QxMPqI6le2u0dCLyiGzgy92kjkkL6zO0XyvHzjdTNH3zM6e5Hz3BwG6+aEyNgiQ5Xz6PwTwgQEj3U50dByPKIA==", - "dev": true, "dependencies": { "expand-tilde": "^1.2.2", "global-modules": "^0.2.3" @@ -44928,7 +44073,6 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", "integrity": "sha512-JeXuCbvYzYXcwE6acL9V2bAOeSIGl4dD+iwLY9iUx2VBJJ80R18HCn+JCwHM9Oegdfya3lEkGCdaRkSyc10hDA==", - "dev": true, "dependencies": { "global-prefix": "^0.1.4", "is-windows": "^0.2.0" @@ -44941,7 +44085,6 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", "integrity": "sha512-gOPiyxcD9dJGCEArAhF4Hd0BAqvAe/JzERP7tYumE4yIkmIedPUVXcJFWbV3/p/ovIIvKjkrTk+f1UVkq7vvbw==", - "dev": true, "dependencies": { "homedir-polyfill": "^1.0.0", "ini": "^1.3.4", @@ -44956,7 +44099,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", "integrity": "sha512-n67eJYmXbniZB7RF4I/FTjK1s6RPOCTxhYrVYLRaCt3lF0mpWZPKr3T2LSZAqyjQsxR2qMmGYXXzK0YWwcPM1Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -44979,7 +44121,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true, "engines": { "node": ">=10" } @@ -44988,7 +44129,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, "dependencies": { "lowercase-keys": "^2.0.0" }, @@ -45046,7 +44186,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -45105,7 +44244,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/robots-parser/-/robots-parser-3.0.1.tgz", "integrity": "sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ==", - "dev": true, "engines": { "node": ">=10.0.0" } @@ -45113,8 +44251,7 @@ "node_modules/rrweb-cssom": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", - "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", - "dev": true + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==" }, "node_modules/rtlcss": { "version": "4.0.0", @@ -45138,7 +44275,6 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/rtlcss-webpack-plugin/-/rtlcss-webpack-plugin-4.0.7.tgz", "integrity": "sha512-ouSbJtgcLBBQIsMgarxsDnfgRqm/AS4BKls/mz/Xb6HSl+PdEzefTR+Wz5uWQx4odoX0g261Z7yb3QBz0MTm0g==", - "dev": true, "dependencies": { "babel-runtime": "~6.25.0", "rtlcss": "^3.5.0" @@ -45148,7 +44284,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -45164,7 +44299,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -45179,7 +44313,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -45194,7 +44327,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -45203,7 +44335,6 @@ "version": "3.5.0", "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz", "integrity": "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==", - "dev": true, "dependencies": { "find-up": "^5.0.0", "picocolors": "^1.0.0", @@ -45218,7 +44349,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -45242,7 +44372,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dev": true, "dependencies": { "execa": "^5.0.0" }, @@ -45257,7 +44386,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -45271,7 +44399,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -45294,7 +44421,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, "engines": { "node": ">=10" }, @@ -45306,7 +44432,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, "engines": { "node": ">=10.17.0" } @@ -45315,7 +44440,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" }, @@ -45327,7 +44451,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -45336,7 +44459,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -45348,7 +44470,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -45363,7 +44484,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -45372,7 +44492,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -45384,7 +44503,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -45393,7 +44511,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -45408,7 +44525,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -45417,7 +44533,6 @@ "version": "1.2.10", "resolved": "https://registry.npmjs.org/run-con/-/run-con-1.2.10.tgz", "integrity": "sha512-n7PZpYmMM26ZO21dd8y3Yw1TRtGABjRtgPSgFS/nhzfvbJMXFtJhJVyEgayMiP+w/23craJjsnfDvx4W4ue/HQ==", - "dev": true, "dependencies": { "deep-extend": "^0.6.0", "ini": "~2.0.0", @@ -45432,7 +44547,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, "engines": { "node": ">=10" } @@ -45441,7 +44555,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -45464,8 +44577,7 @@ "node_modules/run-parallel": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", - "dev": true + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" }, "node_modules/run-queue": { "version": "1.0.3", @@ -45491,7 +44603,6 @@ "version": "6.6.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, "dependencies": { "tslib": "^1.9.0" }, @@ -45502,8 +44613,7 @@ "node_modules/rxjs/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/safaridriver": { "version": "0.1.0", @@ -45515,7 +44625,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.0", @@ -45532,8 +44641,7 @@ "node_modules/safe-array-concat/node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" }, "node_modules/safe-buffer": { "version": "5.1.2", @@ -45553,7 +44661,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.3", @@ -45590,7 +44697,6 @@ "version": "1.35.2", "resolved": "https://registry.npmjs.org/sass/-/sass-1.35.2.tgz", "integrity": "sha512-jhO5KAR+AMxCEwIH3v+4zbB2WB0z67V1X0jbapfVwQQdjHZUGUyukpnoM6+iCMfsIUC016w9OPKQ5jrNOS9uXw==", - "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0" }, @@ -45605,7 +44711,6 @@ "version": "12.1.0", "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.1.0.tgz", "integrity": "sha512-FVJZ9kxVRYNZTIe2xhw93n3xJNYZADr+q69/s98l9nTCrWASo+DR2Ot0s5xTKQDDEosUkatsGeHxcH4QBp5bSg==", - "dev": true, "dependencies": { "klona": "^2.0.4", "neo-async": "^2.6.2" @@ -45639,7 +44744,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, "dependencies": { "xmlchars": "^2.2.0" }, @@ -45699,14 +44803,12 @@ "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" }, "node_modules/selfsigned": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", - "dev": true, "dependencies": { "node-forge": "^1" }, @@ -45888,7 +44990,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dev": true, "dependencies": { "accepts": "~1.3.4", "batch": "0.6.1", @@ -45906,7 +45007,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "dependencies": { "ms": "2.0.0" } @@ -45915,7 +45015,6 @@ "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -45929,8 +45028,7 @@ "node_modules/serve-index/node_modules/setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, "node_modules/serve-static": { "version": "1.15.0", @@ -45955,7 +45053,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -46116,7 +45213,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, "dependencies": { "shebang-regex": "^1.0.0" }, @@ -46128,7 +45224,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -46324,7 +45419,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -46412,7 +45506,6 @@ "version": "3.24.0", "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.24.0.tgz", "integrity": "sha512-QqAKee9Twv+3k8IFOFfPB2hnk6as6Y6ACUpwCtQvRYBAes23Wv3SZlHVobAzqcE8gfsisCvPw3HGW3HYM+VYYw==", - "dev": true, "dependencies": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", @@ -46514,7 +45607,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", "integrity": "sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==", - "dev": true, "dependencies": { "@polka/url": "^1.0.0-next.20", "mrmime": "^1.0.0", @@ -46550,7 +45642,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -46710,7 +45801,6 @@ "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, "dependencies": { "faye-websocket": "^0.11.3", "uuid": "^8.3.2", @@ -46721,7 +45811,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -46730,7 +45819,6 @@ "version": "2.8.3", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", - "dev": true, "license": "MIT", "dependencies": { "ip-address": "^9.0.5", @@ -46759,7 +45847,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==", - "dev": true, "dependencies": { "is-plain-obj": "^1.0.0" }, @@ -46771,7 +45858,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -46794,7 +45880,6 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -46803,7 +45888,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.0.tgz", "integrity": "sha512-GKGWqWvYr04M7tn8dryIWvb0s8YM41z82iQv01yBtIylgxax0CwvSy6gc2Y02iuXwEfGWRlMicH0nvms9UZphw==", - "dev": true, "dependencies": { "abab": "^2.0.5", "iconv-lite": "^0.6.2", @@ -46868,7 +45952,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -46877,14 +45960,12 @@ "node_modules/spdx-exceptions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", - "dev": true + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -46893,14 +45974,12 @@ "node_modules/spdx-license-ids": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", - "dev": true + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" }, "node_modules/spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, "dependencies": { "debug": "^4.1.0", "handle-thing": "^2.0.0", @@ -46916,7 +45995,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, "dependencies": { "debug": "^4.1.0", "detect-node": "^2.0.4", @@ -46930,7 +46008,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -46953,7 +46030,6 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/speedline-core/-/speedline-core-1.4.3.tgz", "integrity": "sha512-DI7/OuAUD+GMpR6dmu8lliO2Wg5zfeh+/xsdyJZCzd8o5JgFUjCeLsBDuZjIQJdwXS3J0L/uZYrELKYqx+PXog==", - "dev": true, "dependencies": { "@types/node": "*", "image-ssim": "^0.2.0", @@ -47087,8 +46163,7 @@ "node_modules/state-toggle": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", - "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==", - "dev": true + "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==" }, "node_modules/static-extend": { "version": "0.1.2", @@ -47243,7 +46318,6 @@ "version": "2.15.1", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.1.tgz", "integrity": "sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==", - "dev": true, "dependencies": { "fast-fifo": "^1.1.0", "queue-tick": "^1.0.1" @@ -47278,7 +46352,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -47355,7 +46428,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -47391,7 +46463,6 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -47408,7 +46479,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -47422,7 +46492,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -47436,7 +46505,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "dev": true, "dependencies": { "character-entities-html4": "^1.0.0", "character-entities-legacy": "^1.0.0", @@ -47486,7 +46554,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, "engines": { "node": ">=8" } @@ -47512,7 +46579,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, "dependencies": { "min-indent": "^1.0.0" }, @@ -47536,7 +46602,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", - "dev": true, "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -47585,14 +46650,12 @@ "node_modules/style-search": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", - "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", - "dev": true + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==" }, "node_modules/stylehacks": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.0.0.tgz", "integrity": "sha512-+UT589qhHPwz6mTlCLSt/vMNTJx8dopeJlZAlBMJPWA3ORqu6wmQY7FBXf+qD+FsqoBJODyqNxOUP3jdntFRdw==", - "dev": true, "dependencies": { "browserslist": "^4.21.4", "postcss-selector-parser": "^6.0.4" @@ -47608,7 +46671,6 @@ "version": "16.8.2", "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.8.2.tgz", "integrity": "sha512-fInKATippQhcSm7AB+T32GpI+626yohrg33GkFT/5jzliUw5qhlwZq2UQQwgl3HsHrf09oeARi0ZwgY/UWEv9A==", - "dev": true, "funding": [ { "type": "opencollective", @@ -47670,20 +46732,17 @@ "node_modules/stylelint/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/stylelint/node_modules/balanced-match": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", - "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", - "dev": true + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==" }, "node_modules/stylelint/node_modules/cosmiconfig": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", - "dev": true, "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", @@ -47709,7 +46768,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -47722,7 +46780,6 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -47739,14 +46796,12 @@ "node_modules/stylelint/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/stylelint/node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -47762,7 +46817,6 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", - "dev": true, "license": "MIT", "dependencies": { "flat-cache": "^5.0.0" @@ -47775,7 +46829,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", - "dev": true, "dependencies": { "flatted": "^3.3.1", "keyv": "^4.5.4" @@ -47788,7 +46841,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -47800,7 +46852,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -47809,7 +46860,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, "engines": { "node": ">= 4" } @@ -47818,7 +46868,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -47827,7 +46876,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -47838,14 +46886,12 @@ "node_modules/stylelint/node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, "node_modules/stylelint/node_modules/meow": { "version": "13.2.0", "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", - "dev": true, "engines": { "node": ">=18" }, @@ -47857,14 +46903,12 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/stylelint/node_modules/postcss": { "version": "8.4.47", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -47892,14 +46936,12 @@ "node_modules/stylelint/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/stylelint/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, "engines": { "node": ">=8" } @@ -47908,7 +46950,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "engines": { "node": ">=14" }, @@ -47920,7 +46961,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -47930,7 +46970,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -47944,7 +46983,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -47956,7 +46994,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -47971,7 +47008,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -47984,7 +47020,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -47996,7 +47031,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz", "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==", - "dev": true, "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" @@ -48012,7 +47046,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^4.0.1" @@ -48046,7 +47079,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0", @@ -48060,7 +47092,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -48069,7 +47100,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -48091,20 +47121,17 @@ "node_modules/svg-parser": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", - "dev": true + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" }, "node_modules/svg-tags": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", - "dev": true + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==" }, "node_modules/svgo": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.2.tgz", "integrity": "sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ==", - "dev": true, "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", @@ -48128,7 +47155,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, "engines": { "node": ">= 10" } @@ -48137,7 +47163,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -48149,14 +47174,12 @@ "node_modules/svgo/node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, "node_modules/svgo/node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -48187,8 +47210,7 @@ "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "node_modules/synchronous-promise": { "version": "2.0.17", @@ -48200,7 +47222,6 @@ "version": "0.8.5", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", - "dev": true, "dependencies": { "@pkgr/utils": "^2.3.1", "tslib": "^2.5.0" @@ -48216,7 +47237,6 @@ "version": "6.8.2", "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", - "dev": true, "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", @@ -48232,7 +47252,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, "engines": { "node": ">=8" } @@ -48240,14 +47259,12 @@ "node_modules/table/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/table/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -48256,7 +47273,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -48273,7 +47289,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -48594,7 +47609,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.0.0.tgz", "integrity": "sha512-rdBAY35jUvVapqCuhehjenLbYY73cVgRQ6podD6u9EDBomBBHjCOtmq2InPgPpTysOIOsQ5PdBzwSC/sKjv6ew==", - "dev": true, "dependencies": { "ansi-escapes": "^4.2.1", "supports-hyperlinks": "^2.0.0" @@ -48624,7 +47638,6 @@ "version": "5.3.10", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", @@ -48658,7 +47671,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -48674,7 +47686,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -48683,7 +47694,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -48697,7 +47707,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -48715,7 +47724,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -48724,7 +47732,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -48736,9 +47743,9 @@ } }, "node_modules/terser/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -48756,7 +47763,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -48770,7 +47776,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -48804,14 +47809,12 @@ "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" }, "node_modules/third-party-web": { "version": "0.23.4", "resolved": "https://registry.npmjs.org/third-party-web/-/third-party-web-0.23.4.tgz", - "integrity": "sha512-kwYnSZRhEvv0SBW2fp8SBBKRglMoBjV8xz6C31m0ewqOtknB5UL+Ihg+M81hyFY5ldkZuGWPb+e4GVDkzf/gYg==", - "dev": true + "integrity": "sha512-kwYnSZRhEvv0SBW2fp8SBBKRglMoBjV8xz6C31m0ewqOtknB5UL+Ihg+M81hyFY5ldkZuGWPb+e4GVDkzf/gYg==" }, "node_modules/throat": { "version": "5.0.0", @@ -48821,8 +47824,7 @@ "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" }, "node_modules/through2": { "version": "2.0.5", @@ -48836,8 +47838,7 @@ "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" }, "node_modules/timers-browserify": { "version": "2.0.12", @@ -48866,7 +47867,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -48878,7 +47878,6 @@ "version": "6.1.50", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.50.tgz", "integrity": "sha512-q9GOap6q3KCsLMdOjXhWU5jVZ8/1dIib898JBRLsN+tBhENpBDcAVQbE0epADOjw11FhQQy9AcbqKGBQPUfTQA==", - "dev": true, "dependencies": { "tldts-core": "^6.1.50" }, @@ -48889,14 +47888,12 @@ "node_modules/tldts-core": { "version": "6.1.50", "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.50.tgz", - "integrity": "sha512-na2EcZqmdA2iV9zHV7OHQDxxdciEpxrjbkp+aHmZgnZKHzoElLajP59np5/4+sare9fQBfixgvXKx8ev1d7ytw==", - "dev": true + "integrity": "sha512-na2EcZqmdA2iV9zHV7OHQDxxdciEpxrjbkp+aHmZgnZKHzoElLajP59np5/4+sare9fQBfixgvXKx8ev1d7ytw==" }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -48915,14 +47912,6 @@ "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==", "dev": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } - }, "node_modules/to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -48993,7 +47982,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, "engines": { "node": ">=6" } @@ -49002,7 +47990,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", - "dev": true, "dependencies": { "tldts": "^6.1.32" }, @@ -49019,7 +48006,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, "bin": { "tree-kill": "cli.js" } @@ -49028,14 +48014,12 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==", - "deprecated": "Use String.prototype.trim() instead", - "dev": true + "deprecated": "Use String.prototype.trim() instead" }, "node_modules/trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true, "engines": { "node": ">=8" } @@ -49044,7 +48028,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", - "dev": true, "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -49055,8 +48038,7 @@ "node_modules/trim-trailing-lines": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", - "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==", - "dev": true + "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==" }, "node_modules/triple-beam": { "version": "1.4.1", @@ -49070,8 +48052,7 @@ "node_modules/trough": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz", - "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==", - "dev": true + "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==" }, "node_modules/truncate-utf8-bytes": { "version": "1.0.2", @@ -49086,7 +48067,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.2.tgz", "integrity": "sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==", - "dev": true, "engines": { "node": ">=16.13.0" }, @@ -49133,7 +48113,6 @@ "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -49145,7 +48124,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, "dependencies": { "minimist": "^1.2.0" }, @@ -49157,22 +48135,20 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, "engines": { "node": ">=4" } }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "license": "0BSD" }, "node_modules/tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, "dependencies": { "tslib": "^1.8.1" }, @@ -49186,8 +48162,7 @@ "node_modules/tsutils/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/tty-browserify": { "version": "0.0.0", @@ -49213,7 +48188,6 @@ "version": "0.0.6", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, "engines": { "node": ">=0.6.11 <=0.7.0 || >=0.7.3" } @@ -49235,7 +48209,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, "dependencies": { "prelude-ls": "~1.1.2" }, @@ -49255,7 +48228,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, "engines": { "node": ">=8" } @@ -49264,7 +48236,6 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -49277,7 +48248,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1", @@ -49291,7 +48261,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "for-each": "^0.3.3", @@ -49309,7 +48278,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", - "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", @@ -49328,7 +48296,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "for-each": "^0.3.3", @@ -49350,20 +48317,17 @@ "node_modules/typed-query-selector": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", - "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", - "dev": true + "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==" }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, "dependencies": { "is-typedarray": "^1.0.0" } @@ -49455,8 +48419,7 @@ "node_modules/uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" }, "node_modules/ufo": { "version": "1.4.0", @@ -49481,7 +48444,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -49496,7 +48458,6 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" @@ -49506,7 +48467,6 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "funding": [ { "type": "github", @@ -49530,7 +48490,6 @@ "version": "5.28.4", "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", - "dev": true, "license": "MIT", "dependencies": { "@fastify/busboy": "^2.0.0" @@ -49548,7 +48507,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", - "dev": true, "dependencies": { "inherits": "^2.0.1", "xtend": "^4.0.1" @@ -49598,7 +48556,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/unified/-/unified-7.1.0.tgz", "integrity": "sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==", - "dev": true, "dependencies": { "@types/unist": "^2.0.0", "@types/vfile": "^3.0.0", @@ -49614,7 +48571,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -49656,7 +48612,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, "dependencies": { "crypto-random-string": "^2.0.0" }, @@ -49667,14 +48622,12 @@ "node_modules/unist-util-is": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", - "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", - "dev": true + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==" }, "node_modules/unist-util-modify-children": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz", "integrity": "sha512-GRi04yhng1WqBf5RBzPkOtWAadcZS2gvuOgNn/cyJBYNxtTuyYqTKN0eg4rC1YJwGnzrqfRB3dSKm8cNCjNirg==", - "dev": true, "dependencies": { "array-iterate": "^1.0.0" } @@ -49683,7 +48636,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", - "dev": true, "dependencies": { "unist-util-visit": "^1.1.0" }, @@ -49695,14 +48647,12 @@ "node_modules/unist-util-stringify-position": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", - "dev": true + "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==" }, "node_modules/unist-util-visit": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", - "dev": true, "dependencies": { "unist-util-visit-parents": "^2.0.0" } @@ -49711,7 +48661,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", - "dev": true, "dependencies": { "unist-util-is": "^3.0.0" } @@ -49763,9 +48712,9 @@ } }, "node_modules/unplugin/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "dev": true, "license": "MIT", "bin": { @@ -49834,7 +48783,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, "engines": { "node": ">=8" } @@ -49923,7 +48871,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -49952,7 +48899,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", - "dev": true, "dependencies": { "loader-utils": "^2.0.0", "mime-types": "^2.1.27", @@ -49979,7 +48925,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -49995,7 +48940,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -50040,8 +48984,7 @@ "node_modules/urlpattern-polyfill": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", - "dev": true + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==" }, "node_modules/use": { "version": "3.1.1", @@ -50208,14 +49151,12 @@ "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" }, "node_modules/v8-to-istanbul": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", @@ -50229,7 +49170,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -50239,7 +49179,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", - "dev": true, "dependencies": { "builtins": "^1.0.3" } @@ -50262,7 +49201,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz", "integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==", - "dev": true, "dependencies": { "is-buffer": "^2.0.0", "replace-ext": "1.0.0", @@ -50274,7 +49212,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==", - "dev": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" @@ -50284,7 +49221,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", - "dev": true, "dependencies": { "unist-util-stringify-position": "^1.1.1" } @@ -50293,7 +49229,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, "funding": [ { "type": "github", @@ -50339,7 +49274,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "dev": true, "dependencies": { "xml-name-validator": "^5.0.0" }, @@ -50654,7 +49588,6 @@ "version": "1.7.3", "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, "dependencies": { "minimalistic-assert": "^1.0.0" } @@ -50723,9 +49656,9 @@ } }, "node_modules/webdriver/node_modules/@types/node": { - "version": "20.16.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", - "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", + "version": "20.16.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.15.tgz", + "integrity": "sha512-DV58qQz9dBMqVVn+qnKwGa51QzCD4YM/tQM16qLKxdf5tqz5W4QwtrMzjSTbabN1cFTSuyxVYBy+QWHjWW8X/g==", "dev": true, "license": "MIT", "dependencies": { @@ -50954,9 +49887,9 @@ } }, "node_modules/webdriverio/node_modules/@types/node": { - "version": "20.16.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", - "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", + "version": "20.16.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.15.tgz", + "integrity": "sha512-DV58qQz9dBMqVVn+qnKwGa51QzCD4YM/tQM16qLKxdf5tqz5W4QwtrMzjSTbabN1cFTSuyxVYBy+QWHjWW8X/g==", "dev": true, "license": "MIT", "dependencies": { @@ -51111,7 +50044,6 @@ "version": "5.95.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", - "dev": true, "dependencies": { "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", @@ -51157,7 +50089,6 @@ "version": "4.9.1", "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.9.1.tgz", "integrity": "sha512-jnd6EoYrf9yMxCyYDPj8eutJvtjQNp8PHmni/e/ulydHBWhT5J3menXt3HEkScsu9YqMAcG4CfFjs3rj5pVU1w==", - "dev": true, "dependencies": { "@discoveryjs/json-ext": "0.5.7", "acorn": "^8.0.4", @@ -51185,10 +50116,9 @@ } }, "node_modules/webpack-bundle-analyzer/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -51201,7 +50131,6 @@ "version": "8.3.4", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, "license": "MIT", "dependencies": { "acorn": "^8.11.0" @@ -51214,7 +50143,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, "engines": { "node": ">= 10" } @@ -51223,7 +50151,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -51235,7 +50162,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, "dependencies": { "duplexer": "^0.1.2" }, @@ -51250,7 +50176,6 @@ "version": "5.1.4", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", - "dev": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1", @@ -51294,14 +50219,12 @@ "node_modules/webpack-cli/node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" }, "node_modules/webpack-cli/node_modules/commander": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, "engines": { "node": ">=14" } @@ -51310,7 +50233,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -51324,7 +50246,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -51333,7 +50254,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -51345,7 +50265,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -51354,7 +50273,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -51457,7 +50375,6 @@ "version": "4.15.1", "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", - "dev": true, "dependencies": { "@types/bonjour": "^3.5.9", "@types/connect-history-api-fallback": "^1.3.5", @@ -51516,7 +50433,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -51533,7 +50449,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -51544,14 +50459,12 @@ "node_modules/webpack-dev-server/node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" }, "node_modules/webpack-dev-server/node_modules/ipaddr.js": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", - "dev": true, "engines": { "node": ">= 10" } @@ -51560,7 +50473,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -51571,14 +50483,12 @@ "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/webpack-dev-server/node_modules/open": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -51595,7 +50505,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -51614,7 +50523,6 @@ "version": "5.3.4", "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", - "dev": true, "dependencies": { "colorette": "^2.0.10", "memfs": "^3.4.3", @@ -51637,7 +50545,6 @@ "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -51670,7 +50577,6 @@ "version": "5.8.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", - "dev": true, "dependencies": { "clone-deep": "^4.0.1", "wildcard": "^2.0.0" @@ -51683,7 +50589,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -51698,7 +50603,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -51707,26 +50611,22 @@ "node_modules/webpack/node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/webpack/node_modules/@webassemblyjs/helper-buffer": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" }, "node_modules/webpack/node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "node_modules/webpack/node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -51738,7 +50638,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -51747,7 +50646,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -51755,14 +50653,12 @@ "node_modules/webpack/node_modules/@webassemblyjs/utf8": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "node_modules/webpack/node_modules/@webassemblyjs/wasm-edit": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -51778,7 +50674,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", @@ -51791,7 +50686,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -51803,7 +50697,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-api-error": "1.11.6", @@ -51817,17 +50710,15 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" } }, "node_modules/webpack/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -51840,7 +50731,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -51856,7 +50746,6 @@ "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -51870,7 +50759,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -51883,7 +50771,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, "engines": { "node": ">=6.11.5" } @@ -51892,7 +50779,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -51910,7 +50796,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -51919,7 +50804,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", - "dev": true, "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", @@ -51933,7 +50817,6 @@ "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, "dependencies": { "http-parser-js": ">=0.5.1", "safe-buffer": ">=5.1.0", @@ -51947,7 +50830,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -51956,7 +50838,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "dev": true, "dependencies": { "iconv-lite": "0.6.3" }, @@ -51973,7 +50854,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "dev": true, "engines": { "node": ">=18" } @@ -52012,7 +50892,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -52024,7 +50903,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -52060,7 +50938,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", - "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", @@ -52087,8 +50964,7 @@ "node_modules/wildcard": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" }, "node_modules/windows-release": { "version": "3.2.0", @@ -52248,7 +51124,6 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -52256,8 +51131,7 @@ "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" }, "node_modules/worker-farm": { "version": "1.7.0", @@ -52373,7 +51247,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", - "dev": true, "dependencies": { "detect-indent": "^5.0.0", "graceful-fs": "^4.1.15", @@ -52390,7 +51263,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, "dependencies": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -52403,7 +51275,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, "engines": { "node": ">=6" } @@ -52412,7 +51283,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "bin": { "semver": "bin/semver" } @@ -52421,7 +51291,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-4.0.0.tgz", "integrity": "sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==", - "dev": true, "dependencies": { "sort-keys": "^2.0.0", "type-fest": "^0.4.1", @@ -52435,7 +51304,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", - "dev": true, "engines": { "node": ">=6" } @@ -52464,14 +51332,12 @@ "node_modules/x-is-string": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", - "integrity": "sha512-GojqklwG8gpzOVEVki5KudKNoq7MbbjYZCbyWzEz7tyPA7eleiE0+ePwOWQQRb5fm86rD3S8Tc0tSFf3AOv50w==", - "dev": true + "integrity": "sha512-GojqklwG8gpzOVEVki5KudKNoq7MbbjYZCbyWzEz7tyPA7eleiE0+ePwOWQQRb5fm86rD3S8Tc0tSFf3AOv50w==" }, "node_modules/xdg-basedir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true, "engines": { "node": ">=8" } @@ -52486,7 +51352,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", - "dev": true, "engines": { "node": ">=18" } @@ -52503,8 +51368,7 @@ "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, "node_modules/xtend": { "version": "4.0.2", @@ -52572,8 +51436,7 @@ "node_modules/yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" }, "node_modules/yaml": { "version": "1.10.2", @@ -52605,7 +51468,6 @@ "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, "engines": { "node": ">=10" } @@ -52680,7 +51542,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" @@ -52754,7 +51615,6 @@ "version": "3.23.8", "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" @@ -52766,8 +51626,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/dom-ready": "file:../dom-ready", - "@wordpress/i18n": "file:../i18n" + "@wordpress/dom-ready": "*", + "@wordpress/i18n": "*" }, "engines": { "node": ">=18.12.0", @@ -52780,10 +51640,10 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/data": "file:../data", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/rich-text": "file:../rich-text", + "@wordpress/data": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/rich-text": "*", "uuid": "^9.0.1" }, "engines": { @@ -52808,8 +51668,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/i18n": "file:../i18n", - "@wordpress/url": "file:../url" + "@wordpress/i18n": "*", + "@wordpress/url": "*" }, "engines": { "node": ">=18.12.0", @@ -52831,7 +51691,6 @@ "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", "version": "5.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -52844,7 +51703,6 @@ "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", "version": "6.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "deepmerge": "^4.3.0", @@ -52862,7 +51720,6 @@ "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", "version": "8.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -52871,8 +51728,8 @@ "@babel/preset-env": "7.25.7", "@babel/preset-typescript": "7.25.7", "@babel/runtime": "7.25.7", - "@wordpress/browserslist-config": "file:../browserslist-config", - "@wordpress/warning": "file:../warning", + "@wordpress/browserslist-config": "*", + "@wordpress/warning": "*", "browserslist": "^4.21.10", "core-js": "^3.31.0", "react": "^18.3.0" @@ -52886,7 +51743,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.7.tgz", "integrity": "sha512-12xfNeKNH7jubQNm7PAkzlLwEmCs1tfuX3UjIw6vP6QXi+leKh6+LyC/+Ed4EIQermwd58wsyh070yjDHFlNGg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.25.7", @@ -52900,7 +51756,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.7.tgz", "integrity": "sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.7", @@ -52918,28 +51773,10 @@ "@babel/core": "^7.0.0" } }, - "packages/babel-preset-default/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, "packages/babel-preset-default/node_modules/@babel/helper-member-expression-to-functions": { "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.7.tgz", "integrity": "sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.25.7", @@ -52953,7 +51790,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.7.tgz", "integrity": "sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.25.7" @@ -52966,7 +51802,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.7.tgz", "integrity": "sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-member-expression-to-functions": "^7.25.7", @@ -52984,7 +51819,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.7.tgz", "integrity": "sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.25.7", @@ -52998,7 +51832,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.7.tgz", "integrity": "sha512-wxyWg2RYaSUYgmd9MR0FyRGyeOMQE/Uzr1wzd/g5cf5bwi9A4v6HFdDm7y1MgDtod/fLOSTZY6jDgV0xU9d5bA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53014,7 +51847,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.7.tgz", "integrity": "sha512-Xwg6tZpLxc4iQjorYsyGMyfJE7nP5MV8t/Ka58BgiA7Jw0fRqQNcANlLfdJ/yvBt9z9LD2We+BEkT7vLqZRWng==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -53032,7 +51864,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.7.tgz", "integrity": "sha512-UVATLMidXrnH+GMUIuxq55nejlj02HP7F5ETyBONzP6G87fPBogG4CH6kxrSrdIuAjdwNO9VzyaYsrZPscWUrw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -53049,7 +51880,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.7.tgz", "integrity": "sha512-ZvZQRmME0zfJnDQnVBKYzHxXT7lYBB3Revz1GuS7oLXWMgqUPX4G+DDbT30ICClht9WKV34QVrZhSw6WdklwZQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53065,7 +51895,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53081,7 +51910,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.7.tgz", "integrity": "sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53097,7 +51925,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.7.tgz", "integrity": "sha512-EJN2mKxDwfOUCPxMO6MUI58RN3ganiRAG/MS/S3HfB6QFNjroAMelQo/gybyYq97WerCBAZoyrAoW8Tzdq2jWg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53113,7 +51940,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.7.tgz", "integrity": "sha512-ZUCjAavsh5CESCmi/xCpX1qcCaAglzs/7tmuvoFnJgA1dM7gQplsguljoTg+Ru8WENpX89cQyAtWoaE0I3X3Pg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.25.7", @@ -53131,7 +51957,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.7.tgz", "integrity": "sha512-xHttvIM9fvqW+0a3tZlYcZYSBpSWzGBFIt/sYG3tcdSzBB8ZeVgz2gBP7Df+sM0N1850jrviYSSeUuc+135dmQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53147,7 +51972,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.7.tgz", "integrity": "sha512-ZEPJSkVZaeTFG/m2PARwLZQ+OG0vFIhPlKHK/JdIMy8DbRJ/htz6LRrTFtdzxi9EHmcwbNPAKDnadpNSIW+Aow==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53163,7 +51987,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.7.tgz", "integrity": "sha512-mhyfEW4gufjIqYFo9krXHJ3ElbFLIze5IDp+wQTxoPd+mwFb1NxatNAwmv8Q8Iuxv7Zc+q8EkiMQwc9IhyGf4g==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.7", @@ -53180,7 +52003,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.7.tgz", "integrity": "sha512-rvUUtoVlkDWtDWxGAiiQj0aNktTPn3eFynBcMC2IhsXweehwgdI9ODe+XjWw515kEmv22sSOTp/rxIRuTiB7zg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.7", @@ -53198,7 +52020,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.7.tgz", "integrity": "sha512-9j9rnl+YCQY0IGoeipXvnk3niWicIB6kCsWRGLwX241qSXpbA4MKxtp/EdvFxsc4zI5vqfLxzOd0twIJ7I99zg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.7", @@ -53219,7 +52040,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.7.tgz", "integrity": "sha512-QIv+imtM+EtNxg/XBKL3hiWjgdLjMOmZ+XzQwSgmBfKbfxUjBzGgVPklUuE55eq5/uVoh8gg3dqlrwR/jw3ZeA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -53236,7 +52056,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.7.tgz", "integrity": "sha512-xKcfLTlJYUczdaM1+epcdh1UGewJqr9zATgrNHcLBcV2QmfvPPEixo/sK/syql9cEmbr7ulu5HMFG5vbbt/sEA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53252,7 +52071,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.7.tgz", "integrity": "sha512-kXzXMMRzAtJdDEgQBLF4oaiT6ZCU3oWHgpARnTKDAqPkDJ+bs3NrZb310YYevR5QlRo3Kn7dzzIdHbZm1VzJdQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.7", @@ -53269,7 +52087,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.7.tgz", "integrity": "sha512-by+v2CjoL3aMnWDOyCIg+yxU9KXSRa9tN6MbqggH5xvymmr9p4AMjYkNlQy4brMceBnUyHZ9G8RnpvT8wP7Cfg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53285,7 +52102,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.7.tgz", "integrity": "sha512-UvcLuual4h7/GfylKm2IAA3aph9rwvAM2XBA0uPKU3lca+Maai4jBjjEVUS568ld6kJcgbouuumCBhMd/Yz17w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -53302,7 +52118,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.7.tgz", "integrity": "sha512-yjqtpstPfZ0h/y40fAXRv2snciYr0OAoMXY/0ClC7tm4C/nG5NJKmIItlaYlLbIVAWNfrYuy9dq1bE0SbX0PEg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.7", @@ -53319,7 +52134,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.7.tgz", "integrity": "sha512-n/TaiBGJxYFWvpJDfsxSj9lEEE44BFM1EPGz4KEiTipTgkoFVVcCmzAL3qA7fdQU96dpo4gGf5HBx/KnDvqiHw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -53336,7 +52150,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.7.tgz", "integrity": "sha512-5MCTNcjCMxQ63Tdu9rxyN6cAWurqfrDZ76qvVPrGYdBxIj+EawuuxTu/+dgJlhK5eRz3v1gLwp6XwS8XaX2NiQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.25.7", @@ -53354,7 +52167,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.7.tgz", "integrity": "sha512-Ot43PrL9TEAiCe8C/2erAjXMeVSnE/BLEx6eyrKLNFCCw5jvhTHKyHxdI1pA0kz5njZRYAnMO2KObGqOCRDYSA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -53371,7 +52183,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.7.tgz", "integrity": "sha512-fwzkLrSu2fESR/cm4t6vqd7ebNIopz2QHGtjoU+dswQo/P6lwAG04Q98lliE3jkz/XqnbGFLnUcE0q0CVUf92w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53387,7 +52198,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.7.tgz", "integrity": "sha512-iImzbA55BjiovLyG2bggWS+V+OLkaBorNvc/yJoeeDQGztknRnDdYfp2d/UPmunZYEnZi6Lg8QcTmNMHOB0lGA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -53404,7 +52214,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.7.tgz", "integrity": "sha512-Std3kXwpXfRV0QtQy5JJcRpkqP8/wG4XL7hSKZmGlxPlDqmpXtEPRmhF7ztnlTCtUN3eXRUJp+sBEZjaIBVYaw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53420,7 +52229,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.7.tgz", "integrity": "sha512-CgselSGCGzjQvKzghCvDTxKHP3iooenLpJDO842ehn5D2G5fJB222ptnDwQho0WjEvg7zyoxb9P+wiYxiJX5yA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.25.7", @@ -53437,7 +52245,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.7.tgz", "integrity": "sha512-L9Gcahi0kKFYXvweO6n0wc3ZG1ChpSFdgG+eV1WYZ3/dGbJK7vvk91FgGgak8YwRgrCuihF8tE/Xg07EkL5COg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.25.7", @@ -53455,7 +52262,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.7.tgz", "integrity": "sha512-t9jZIvBmOXJsiuyOwhrIGs8dVcD6jDyg2icw1VL4A/g+FnWyJKwUfSSU2nwJuMV2Zqui856El9u+ElB+j9fV1g==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.25.7", @@ -53474,7 +52280,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.7.tgz", "integrity": "sha512-p88Jg6QqsaPh+EB7I9GJrIqi1Zt4ZBHUQtjw3z1bzEXcLh6GfPqzZJ6G+G1HBGKUNukT58MnKG7EN7zXQBCODw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.25.7", @@ -53491,7 +52296,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.7.tgz", "integrity": "sha512-BtAT9LzCISKG3Dsdw5uso4oV1+v2NlVXIIomKJgQybotJY3OwCwJmkongjHgwGKoZXd0qG5UZ12JUlDQ07W6Ow==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.7", @@ -53508,7 +52312,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.7.tgz", "integrity": "sha512-CfCS2jDsbcZaVYxRFo2qtavW8SpdzmBXC2LOI4oO0rP+JSRDxxF3inF4GcPsLgfb5FjkhXG5/yR/lxuRs2pySA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53524,7 +52327,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.7.tgz", "integrity": "sha512-FbuJ63/4LEL32mIxrxwYaqjJxpbzxPVQj5a+Ebrc8JICV6YX8nE53jY+K0RZT3um56GoNWgkS2BQ/uLGTjtwfw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -53541,7 +52343,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.7.tgz", "integrity": "sha512-8CbutzSSh4hmD+jJHIA8vdTNk15kAzOnFLVVgBSMGr28rt85ouT01/rezMecks9pkU939wDInImwCKv4ahU4IA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -53558,7 +52359,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.7.tgz", "integrity": "sha512-1JdVKPhD7Y5PvgfFy0Mv2brdrolzpzSoUq2pr6xsR+m+3viGGeHEokFKsCgOkbeFOQxfB1Vt2F0cPJLRpFI4Zg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.25.7", @@ -53577,7 +52377,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.7.tgz", "integrity": "sha512-pWT6UXCEW3u1t2tcAGtE15ornCBvopHj9Bps9D2DsH15APgNVOTwwczGckX+WkAvBmuoYKRCFa4DK+jM8vh5AA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -53594,7 +52393,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.7.tgz", "integrity": "sha512-m9obYBA39mDPN7lJzD5WkGGb0GO54PPLXsbcnj1Hyeu8mSRz7Gb4b1A6zxNX32ZuUySDK4G6it8SDFWD1nCnqg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -53611,7 +52409,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.7.tgz", "integrity": "sha512-h39agClImgPWg4H8mYVAbD1qP9vClFbEjqoJmt87Zen8pjqK8FTPUwrOXAvqu5soytwxrLMd2fx2KSCp2CHcNg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -53629,7 +52426,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.7.tgz", "integrity": "sha512-FYiTvku63me9+1Nz7TOx4YMtW3tWXzfANZtrzHhUZrz4d47EEtMQhzFoZWESfXuAMMT5mwzD4+y1N8ONAX6lMQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53645,7 +52441,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz", "integrity": "sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.7", @@ -53662,7 +52457,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.7.tgz", "integrity": "sha512-LzA5ESzBy7tqj00Yjey9yWfs3FKy4EmJyKOSWld144OxkTji81WWnUT8nkLUn+imN/zHL8ZQlOu/MTUAhHaX3g==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.7", @@ -53681,7 +52475,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.7.tgz", "integrity": "sha512-lQEeetGKfFi0wHbt8ClQrUSUMfEeI3MMm74Z73T9/kuz990yYVtfofjf3NuA42Jy3auFOpbjDyCSiIkTs1VIYw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53697,7 +52490,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.7.tgz", "integrity": "sha512-vILAg5nwGlR9EXE8JIOX4NHXd49lrYbN8hnjffDtoULwpL9hUx/N55nqh2qd0q6FyNDfjl9V79ecKGvFbcSA0Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.7", @@ -53717,7 +52509,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.7.tgz", "integrity": "sha512-mgDoQCRjrY3XK95UuV60tZlFCQGXEtMg8H+IsW72ldw1ih1jZhzYXbJvghmAEpg5UVhhnCeia1CkGttUvCkiMQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -53734,7 +52525,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.7.tgz", "integrity": "sha512-3OfyfRRqiGeOvIWSagcwUTVk2hXBsr/ww7bLn6TRTuXnexA+Udov2icFOxFX9abaj4l96ooYkcNN1qi2Zvqwng==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53750,7 +52540,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.7.tgz", "integrity": "sha512-Y9p487tyTzB0yDYQOtWnC+9HGOuogtP3/wNpun1xJXEEvI6vip59BSBTsHnekZLqxmPcgsrAKt46HAAb//xGhg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.25.7", @@ -53771,7 +52560,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.7.tgz", "integrity": "sha512-uBbxNwimHi5Bv3hUccmOFlUy3ATO6WagTApenHz9KzoIdn0XeACdB12ZJ4cjhuB2WSi80Ez2FWzJnarccriJeA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53787,7 +52575,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.7.tgz", "integrity": "sha512-Mm6aeymI0PBh44xNIv/qvo8nmbkpZze1KvR8MkEqbIREDxoiWTi18Zr2jryfRMwDfVZF9foKh060fWgni44luw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -53804,7 +52591,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.7.tgz", "integrity": "sha512-ZFAeNkpGuLnAQ/NCsXJ6xik7Id+tHuS+NT+ue/2+rn/31zcdnupCdmunOizEaP0JsUmTFSTOPoQY7PkK2pttXw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53820,7 +52606,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.7.tgz", "integrity": "sha512-SI274k0nUsFFmyQupiO7+wKATAmMFf8iFgq2O+vVFXZ0SV9lNfT1NGzBEhjquFmD8I9sqHLguH+gZVN3vww2AA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53836,7 +52621,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.7.tgz", "integrity": "sha512-OmWmQtTHnO8RSUbL0NTdtpbZHeNTnm68Gj5pA4Y2blFNh+V4iZR68V1qL9cI37J21ZN7AaCnkfdHtLExQPf2uA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53852,7 +52636,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.7.tgz", "integrity": "sha512-VKlgy2vBzj8AmEzunocMun2fF06bsSWV+FvVXohtL6FGve/+L217qhHxRTVGHEDO/YR8IANcjzgJsd04J8ge5Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.7", @@ -53872,7 +52655,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.7.tgz", "integrity": "sha512-BN87D7KpbdiABA+t3HbVqHzKWUDN3dymLaTnPFAMyc8lV+KN3+YzNhVRNdinaCPA4AUqx7ubXbQ9shRjYBl3SQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -53888,7 +52670,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.7.tgz", "integrity": "sha512-IWfR89zcEPQGB/iB408uGtSPlQd3Jpq11Im86vUgcmSTcoWAiQMCTOa2K2yNNqFJEBVICKhayctee65Ka8OB0w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.7", @@ -53905,7 +52686,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.7.tgz", "integrity": "sha512-8JKfg/hiuA3qXnlLx8qtv5HWRbgyFx2hMMtpDDuU2rTckpKkGu4ycK5yYHwuEa16/quXfoxHBIApEsNyMWnt0g==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.7", @@ -53922,7 +52702,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.7.tgz", "integrity": "sha512-YRW8o9vzImwmh4Q3Rffd09bH5/hvY0pxg+1H1i0f7APoUeg12G7+HhLj9ZFNIrYkgBXhIijPJ+IXypN0hLTIbw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.7", @@ -53939,7 +52718,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.7.tgz", "integrity": "sha512-Gibz4OUdyNqqLj+7OAvBZxOD7CklCtMA5/j0JgUEwOnaRULsPDXmic2iKxL2DX2vQduPR5wH2hjZas/Vr/Oc0g==", - "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.25.7", @@ -54037,7 +52815,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.25.7.tgz", "integrity": "sha512-rkkpaXJZOFN45Fb+Gki0c+KMIglk4+zZXOoMJuyEK8y8Kkc8Jd3BDmP7qPsz0zQMJj+UD7EprF+AqAXcILnexw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -54053,53 +52830,10 @@ "@babel/core": "^7.0.0-0" } }, - "packages/babel-preset-default/node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "packages/babel-preset-default/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", - "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2", - "core-js-compat": "^3.38.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "packages/babel-preset-default/node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", - "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, "packages/babel-preset-default/node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -54109,7 +52843,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -54118,7 +52851,6 @@ "packages/base-styles": { "name": "@wordpress/base-styles", "version": "5.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -54143,24 +52875,24 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@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/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/plugins": "file:../plugins", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/plugins": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", "change-case": "^4.1.2", "clsx": "^2.1.1" }, @@ -54182,36 +52914,36 @@ "@emotion/react": "^11.7.1", "@emotion/styled": "^11.6.0", "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/style-engine": "file:../style-engine", - "@wordpress/token-list": "file:../token-list", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/block-serialization-default-parser": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/style-engine": "*", + "@wordpress/token-list": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -54278,39 +53010,39 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/autop": "file:../autop", - "@wordpress/blob": "file:../blob", - "@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/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interactivity": "file:../interactivity", - "@wordpress/interactivity-router": "file:../interactivity-router", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/server-side-render": "file:../server-side-render", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/autop": "*", + "@wordpress/blob": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interactivity": "*", + "@wordpress/interactivity-router": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/rich-text": "*", + "@wordpress/server-side-render": "*", + "@wordpress/url": "*", + "@wordpress/viewport": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -54369,21 +53101,21 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/autop": "file:../autop", - "@wordpress/blob": "file:../blob", - "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/shortcode": "file:../shortcode", - "@wordpress/warning": "file:../warning", + "@wordpress/autop": "*", + "@wordpress/blob": "*", + "@wordpress/block-serialization-default-parser": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/shortcode": "*", + "@wordpress/warning": "*", "change-case": "^4.1.2", "colord": "^2.7.0", "fast-deep-equal": "^3.1.3", @@ -54420,7 +53152,6 @@ "packages/browserslist-config": { "name": "@wordpress/browserslist-config", "version": "6.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -54433,13 +53164,13 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/private-apis": "file:../private-apis", + "@wordpress/components": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/private-apis": "*", "clsx": "^2.1.1", "cmdk": "^1.0.0" }, @@ -54488,6 +53219,18 @@ } } }, + "packages/commands/node_modules/@radix-ui/react-dialog/node_modules/@babel/runtime": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.9.tgz", + "integrity": "sha512-4zpTHZ9Cm6L9L+uIqghQX8ZXg8HKFcjYO3qHoO8zTmRm6HQUJ8SSJ+KRvbMBZn0EGVlT4DRYeQ/6hjlyXBh+Kg==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "packages/commands/node_modules/@radix-ui/react-dismissable-layer": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", @@ -54515,6 +53258,18 @@ } } }, + "packages/commands/node_modules/@radix-ui/react-dismissable-layer/node_modules/@babel/runtime": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.9.tgz", + "integrity": "sha512-4zpTHZ9Cm6L9L+uIqghQX8ZXg8HKFcjYO3qHoO8zTmRm6HQUJ8SSJ+KRvbMBZn0EGVlT4DRYeQ/6hjlyXBh+Kg==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "packages/commands/node_modules/@radix-ui/react-focus-scope": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", @@ -54540,6 +53295,18 @@ } } }, + "packages/commands/node_modules/@radix-ui/react-focus-scope/node_modules/@babel/runtime": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.9.tgz", + "integrity": "sha512-4zpTHZ9Cm6L9L+uIqghQX8ZXg8HKFcjYO3qHoO8zTmRm6HQUJ8SSJ+KRvbMBZn0EGVlT4DRYeQ/6hjlyXBh+Kg==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "packages/commands/node_modules/@radix-ui/react-portal": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", @@ -54563,6 +53330,18 @@ } } }, + "packages/commands/node_modules/@radix-ui/react-portal/node_modules/@babel/runtime": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.9.tgz", + "integrity": "sha512-4zpTHZ9Cm6L9L+uIqghQX8ZXg8HKFcjYO3qHoO8zTmRm6HQUJ8SSJ+KRvbMBZn0EGVlT4DRYeQ/6hjlyXBh+Kg==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "packages/commands/node_modules/@radix-ui/react-presence": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", @@ -54587,6 +53366,18 @@ } } }, + "packages/commands/node_modules/@radix-ui/react-presence/node_modules/@babel/runtime": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.9.tgz", + "integrity": "sha512-4zpTHZ9Cm6L9L+uIqghQX8ZXg8HKFcjYO3qHoO8zTmRm6HQUJ8SSJ+KRvbMBZn0EGVlT4DRYeQ/6hjlyXBh+Kg==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "packages/commands/node_modules/cmdk": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.0.0.tgz", @@ -54600,6 +53391,12 @@ "react-dom": "^18.0.0" } }, + "packages/commands/node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, "packages/components": { "name": "@wordpress/components", "version": "28.10.0", @@ -54617,23 +53414,23 @@ "@types/gradient-parser": "0.1.3", "@types/highlight-words-core": "1.2.1", "@use-gesture/react": "^10.3.1", - "@wordpress/a11y": "file:../a11y", - "@wordpress/compose": "file:../compose", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/warning": "file:../warning", + "@wordpress/a11y": "*", + "@wordpress/compose": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keycodes": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/warning": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -54728,13 +53525,13 @@ "dependencies": { "@babel/runtime": "7.25.7", "@types/mousetrap": "^1.6.8", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/undo-manager": "file:../undo-manager", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keycodes": "*", + "@wordpress/priority-queue": "*", + "@wordpress/undo-manager": "*", "change-case": "^4.1.2", "clipboard": "^2.0.11", "mousetrap": "^1.6.5", @@ -54764,19 +53561,19 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/commands": "file:../commands", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/router": "file:../router", - "@wordpress/url": "file:../url" + "@wordpress/block-editor": "*", + "@wordpress/commands": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/private-apis": "*", + "@wordpress/router": "*", + "@wordpress/url": "*" }, "engines": { "node": ">=18.12.0", @@ -54793,22 +53590,22 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/sync": "file:../sync", - "@wordpress/undo-manager": "file:../undo-manager", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/sync": "*", + "@wordpress/undo-manager": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", "change-case": "^4.1.2", "equivalent-key-map": "^0.2.2", "fast-deep-equal": "^3.1.3", @@ -54835,10 +53632,9 @@ "packages/create-block": { "name": "@wordpress/create-block", "version": "4.53.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/lazy-import": "file:../lazy-import", + "@wordpress/lazy-import": "*", "chalk": "^4.0.0", "change-case": "^4.1.2", "check-node-version": "^4.1.0", @@ -54860,10 +53656,18 @@ "npm": ">=10.2.3" } }, + "packages/create-block-interactive-template": { + "name": "@wordpress/create-block-interactive-template", + "version": "2.10.0", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", "version": "4.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -54876,27 +53680,27 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/widgets": "file:../widgets", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interface": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/media-utils": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/widgets": "*", "clsx": "^2.1.1", "fast-deep-equal": "^3.1.3" }, @@ -54915,13 +53719,13 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/compose": "file:../compose", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/redux-routine": "file:../redux-routine", + "@wordpress/compose": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/priority-queue": "*", + "@wordpress/private-apis": "*", + "@wordpress/redux-routine": "*", "deepmerge": "^4.3.0", "equivalent-key-map": "^0.2.2", "is-plain-object": "^5.0.0", @@ -54944,9 +53748,9 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated" + "@wordpress/api-fetch": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*" }, "engines": { "node": ">=18.12.0", @@ -54963,15 +53767,15 @@ "dependencies": { "@ariakit/react": "^0.4.10", "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/warning": "file:../warning", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/warning": "*", "clsx": "^2.1.1", "remove-accents": "^0.5.0" }, @@ -55019,7 +53823,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/deprecated": "file:../deprecated", + "@wordpress/deprecated": "*", "moment": "^2.29.4", "moment-timezone": "^0.5.40" }, @@ -55031,7 +53835,6 @@ "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", "version": "6.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "json2php": "^0.0.7" @@ -55050,7 +53853,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/hooks": "file:../hooks" + "@wordpress/hooks": "*" }, "engines": { "node": ">=18.12.0", @@ -55060,7 +53863,6 @@ "packages/docgen": { "name": "@wordpress/docgen", "version": "2.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -55085,7 +53887,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/deprecated": "file:../deprecated" + "@wordpress/deprecated": "*" }, "engines": { "node": ">=18.12.0", @@ -55107,13 +53909,12 @@ "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", "version": "11.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/url": "file:../url", + "@wordpress/api-fetch": "*", + "@wordpress/keycodes": "*", + "@wordpress/url": "*", "change-case": "^4.1.2", "form-data": "^4.0.0", "node-fetch": "2.7.0" @@ -55130,7 +53931,6 @@ "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", "version": "1.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "change-case": "^4.1.2", @@ -55152,22 +53952,20 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.1.tgz", "integrity": "sha512-U6bAxeudnhDqcXNl50JC4hLlqox9DZnngxfISZm3DMZnonW35xtJOVUc091L+DOY+6hVZVpKXoiCP0RiT6339Q==", - "dev": true, "license": "Apache-2.0" }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", "version": "8.10.1", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/e2e-test-utils": "file:../e2e-test-utils", - "@wordpress/interactivity": "file:../interactivity", - "@wordpress/interactivity-router": "file:../interactivity-router", - "@wordpress/jest-console": "file:../jest-console", - "@wordpress/jest-puppeteer-axe": "file:../jest-puppeteer-axe", - "@wordpress/scripts": "file:../scripts", - "@wordpress/url": "file:../url", + "@wordpress/e2e-test-utils": "*", + "@wordpress/interactivity": "*", + "@wordpress/interactivity-router": "*", + "@wordpress/jest-console": "*", + "@wordpress/jest-puppeteer-axe": "*", + "@wordpress/scripts": "*", + "@wordpress/url": "*", "chalk": "^4.0.0", "expect-puppeteer": "^4.4.0", "filenamify": "^4.2.0", @@ -55190,7 +53988,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -55201,35 +53998,35 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-commands": "file:../core-commands", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/warning": "file:../warning", - "@wordpress/widgets": "file:../widgets", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-commands": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", + "@wordpress/viewport": "*", + "@wordpress/warning": "*", + "@wordpress/widgets": "*", "clsx": "^2.1.1", "memize": "^2.1.0" }, @@ -55249,45 +54046,45 @@ "dependencies": { "@babel/runtime": "7.25.7", "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-commands": "file:../core-commands", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/primitives": "file:../primitives", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/router": "file:../router", - "@wordpress/style-engine": "file:../style-engine", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/widgets": "file:../widgets", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-commands": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dataviews": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/primitives": "*", + "@wordpress/priority-queue": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/router": "*", + "@wordpress/style-engine": "*", + "@wordpress/url": "*", + "@wordpress/viewport": "*", + "@wordpress/widgets": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.9.2", @@ -55310,33 +54107,33 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/url": "file:../url", - "@wordpress/widgets": "file:../widgets", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interface": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/media-utils": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/url": "*", + "@wordpress/widgets": "*", "clsx": "^2.1.1" }, "engines": { @@ -55354,41 +54151,41 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/fields": "file:../fields", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/server-side-render": "file:../server-side-render", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dataviews": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/fields": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interface": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/media-utils": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/rich-text": "*", + "@wordpress/server-side-render": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "client-zip": "^2.4.5", "clsx": "^2.1.1", @@ -55418,7 +54215,7 @@ "@babel/runtime": "7.25.7", "@types/react": "^18.2.79", "@types/react-dom": "^18.2.25", - "@wordpress/escape-html": "file:../escape-html", + "@wordpress/escape-html": "*", "change-case": "^4.1.2", "is-plain-object": "^5.0.0", "react": "^18.3.0", @@ -55432,7 +54229,6 @@ "packages/env": { "name": "@wordpress/env", "version": "10.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "chalk": "^4.0.0", @@ -55460,7 +54256,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -55474,7 +54269,6 @@ "version": "0.24.2", "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.24.2.tgz", "integrity": "sha512-2/WLvA7UZ6A2LDLQrYW0idKipmNBWhtfvrn2yzjC5PnHDzuFVj1zAZN6MJxVMKP0zZH8uzAK6OwVZYHGuyCmTw==", - "dev": true, "dependencies": { "yaml": "^2.2.2" }, @@ -55485,14 +54279,12 @@ "packages/env/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "packages/env/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -55501,7 +54293,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -55515,7 +54306,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -55531,14 +54321,12 @@ "packages/env/node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, "packages/env/node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", - "dev": true, + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -55551,7 +54339,6 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -55568,8 +54355,7 @@ "packages/env/node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" }, "packages/escape-html": { "name": "@wordpress/escape-html", @@ -55586,14 +54372,13 @@ "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", "version": "21.3.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/eslint-parser": "7.25.7", "@typescript-eslint/eslint-plugin": "^6.4.1", "@typescript-eslint/parser": "^6.4.1", - "@wordpress/babel-preset-default": "file:../babel-preset-default", - "@wordpress/prettier-config": "file:../prettier-config", + "@wordpress/babel-preset-default": "*", + "@wordpress/prettier-config": "*", "cosmiconfig": "^7.0.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.2", @@ -55630,7 +54415,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.7.tgz", "integrity": "sha512-B+BO9x86VYsQHimucBAL1fxTJKF4wyKY6ZVzee9QgzdZOUfs3BaR6AQrgoGrRI+7IFS1wUz/VyQ+SoBcSpdPbw==", - "dev": true, "license": "MIT", "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", @@ -55649,7 +54433,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -55661,25 +54444,25 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dataviews": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", "change-case": "4.1.2", "client-zip": "^2.4.5" }, @@ -55697,18 +54480,18 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/url": "file:../url" + "@wordpress/a11y": "*", + "@wordpress/block-editor": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/url": "*" }, "engines": { "node": ">=18.12.0", @@ -55749,7 +54532,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/hooks": "file:../hooks", + "@wordpress/hooks": "*", "gettext-parser": "^1.3.1", "memize": "^2.1.0", "sprintf-js": "^1.1.1", @@ -55769,8 +54552,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", - "@wordpress/primitives": "file:../primitives" + "@wordpress/element": "*", + "@wordpress/primitives": "*" }, "engines": { "node": ">=18.12.0", @@ -55795,8 +54578,8 @@ "version": "2.10.0", "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/a11y": "file:../a11y", - "@wordpress/interactivity": "file:../interactivity" + "@wordpress/a11y": "*", + "@wordpress/interactivity": "*" }, "engines": { "node": ">=18.12.0", @@ -55809,18 +54592,18 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/viewport": "file:../viewport", + "@wordpress/a11y": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/viewport": "*", "clsx": "^2.1.1" }, "engines": { @@ -55847,7 +54630,6 @@ "packages/jest-console": { "name": "@wordpress/jest-console", "version": "8.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55864,10 +54646,9 @@ "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", "version": "12.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/jest-console": "file:../jest-console", + "@wordpress/jest-console": "*", "babel-jest": "29.7.0" }, "engines": { @@ -55882,7 +54663,6 @@ "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", "version": "7.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@axe-core/puppeteer": "^4.0.0", @@ -55908,9 +54688,9 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/keycodes": "file:../keycodes" + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/keycodes": "*" }, "engines": { "node": ">=18.12.0", @@ -55926,7 +54706,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/i18n": "file:../i18n" + "@wordpress/i18n": "*" }, "engines": { "node": ">=18.12.0", @@ -55936,7 +54716,6 @@ "packages/lazy-import": { "name": "@wordpress/lazy-import", "version": "2.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "execa": "^4.0.2", @@ -55954,12 +54733,12 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", "change-case": "^4.1.2" }, "engines": { @@ -55977,10 +54756,10 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n" + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*" }, "engines": { "node": ">=18.12.0", @@ -55993,8 +54772,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/data": "file:../data" + "@wordpress/a11y": "*", + "@wordpress/data": "*" }, "engines": { "node": ">=18.12.0", @@ -56007,7 +54786,6 @@ "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", "version": "5.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -56023,13 +54801,13 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons" + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*" }, "engines": { "node": ">=18.12.0", @@ -56046,20 +54824,20 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@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/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url" + "@wordpress/a11y": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*" }, "engines": { "node": ">=18.12.0", @@ -56076,12 +54854,12 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/icons": "*", + "@wordpress/is-shallow-equal": "*", "memize": "^2.0.1" }, "engines": { @@ -56096,10 +54874,9 @@ "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", "version": "5.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/base-styles": "file:../base-styles", + "@wordpress/base-styles": "*", "autoprefixer": "^10.2.5" }, "engines": { @@ -56113,7 +54890,6 @@ "packages/postcss-themes": { "name": "@wordpress/postcss-themes", "version": "6.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -56129,15 +54905,15 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/private-apis": "file:../private-apis", + "@wordpress/a11y": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/private-apis": "*", "clsx": "^2.1.1" }, "engines": { @@ -56155,7 +54931,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch" + "@wordpress/api-fetch": "*" }, "engines": { "node": ">=18.12.0", @@ -56165,7 +54941,6 @@ "packages/prettier-config": { "name": "@wordpress/prettier-config", "version": "4.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -56181,7 +54956,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", + "@wordpress/element": "*", "clsx": "^2.1.1" }, "engines": { @@ -56220,7 +54995,6 @@ "packages/project-management-automation": { "name": "@wordpress/project-management-automation", "version": "2.10.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@actions/core": "1.9.1", @@ -56238,7 +55012,6 @@ "version": "9.26.3", "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.26.3.tgz", "integrity": "sha512-DLGk+gzeVq5oK89Bo601txYmyrelMQ7Fi5EnjHE0Xs8CWicy2xkmnJMKptKJrBJpstqbd/9oeDFi/Zj2pudBDQ==", - "dev": true, "license": "MIT", "dependencies": { "@octokit/request-error": "^2.0.2", @@ -56253,8 +55026,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", + "@wordpress/element": "*", + "@wordpress/i18n": "*", "utility-types": "^3.10.0" }, "engines": { @@ -56267,8 +55040,8 @@ "version": "1.121.0", "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/element": "file:../element", - "@wordpress/keycodes": "file:../keycodes" + "@wordpress/element": "*", + "@wordpress/keycodes": "*" }, "engines": { "node": ">=18.12.0", @@ -56284,7 +55057,7 @@ "version": "1.121.0", "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/react-native-aztec": "file:../react-native-aztec" + "@wordpress/react-native-aztec": "*" }, "engines": { "node": ">=18.12.0", @@ -56309,18 +55082,18 @@ "@react-navigation/native": "6.0.14", "@react-navigation/routers": "5.4.9", "@react-navigation/stack": "6.3.5", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/data": "file:../data", - "@wordpress/edit-post": "file:../edit-post", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/react-native-aztec": "file:../react-native-aztec", - "@wordpress/react-native-bridge": "file:../react-native-bridge", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/data": "*", + "@wordpress/edit-post": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/react-native-aztec": "*", + "@wordpress/react-native-bridge": "*", "core-js": "^3.31.0", "fast-average-color": "^9.1.1", "gettext-parser": "^1.3.1", @@ -56406,7 +55179,6 @@ "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", "version": "3.10.0", - "dev": true, "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -56437,7 +55209,6 @@ "packages/report-flaky-tests": { "name": "@wordpress/report-flaky-tests", "version": "0.0.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@actions/core": "^1.8.0", @@ -56453,7 +55224,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz", "integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==", - "dev": true, "dependencies": { "@actions/http-client": "^2.0.1", "@octokit/core": "^3.6.0", @@ -56467,17 +55237,17 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url" + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*" }, "engines": { "node": ">=18.12.0", @@ -56494,14 +55264,14 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/i18n": "file:../i18n", - "@wordpress/keycodes": "file:../keycodes", + "@wordpress/a11y": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/i18n": "*", + "@wordpress/keycodes": "*", "memize": "^2.1.0" }, "engines": { @@ -56518,9 +55288,9 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", + "@wordpress/element": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", "history": "^5.3.0" }, "engines": { @@ -56534,22 +55304,21 @@ "packages/scripts": { "name": "@wordpress/scripts", "version": "30.3.0", - "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", "@svgr/webpack": "^8.0.1", - "@wordpress/babel-preset-default": "file:../babel-preset-default", - "@wordpress/browserslist-config": "file:../browserslist-config", - "@wordpress/dependency-extraction-webpack-plugin": "file:../dependency-extraction-webpack-plugin", - "@wordpress/e2e-test-utils-playwright": "file:../e2e-test-utils-playwright", - "@wordpress/eslint-plugin": "file:../eslint-plugin", - "@wordpress/jest-preset-default": "file:../jest-preset-default", - "@wordpress/npm-package-json-lint-config": "file:../npm-package-json-lint-config", - "@wordpress/postcss-plugins-preset": "file:../postcss-plugins-preset", - "@wordpress/prettier-config": "file:../prettier-config", - "@wordpress/stylelint-config": "file:../stylelint-config", + "@wordpress/babel-preset-default": "*", + "@wordpress/browserslist-config": "*", + "@wordpress/dependency-extraction-webpack-plugin": "*", + "@wordpress/e2e-test-utils-playwright": "*", + "@wordpress/eslint-plugin": "*", + "@wordpress/jest-preset-default": "*", + "@wordpress/npm-package-json-lint-config": "*", + "@wordpress/postcss-plugins-preset": "*", + "@wordpress/prettier-config": "*", + "@wordpress/stylelint-config": "*", "adm-zip": "^0.5.9", "babel-jest": "29.7.0", "babel-loader": "9.2.1", @@ -56616,7 +55385,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -56633,7 +55401,6 @@ "version": "1.7.7", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "dev": true, "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -56645,7 +55412,6 @@ "version": "8.4.1", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.4.1.tgz", "integrity": "sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==", - "dev": true, "license": "MIT", "dependencies": { "find-cache-dir": "^3.3.1", @@ -56665,7 +55431,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -56682,14 +55447,12 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, "license": "MIT" }, "packages/scripts/node_modules/babel-loader/node_modules/schema-utils": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.5", @@ -56708,7 +55471,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -56724,7 +55486,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", @@ -56741,7 +55502,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -56754,7 +55514,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -56763,7 +55522,6 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/jest-dev-server/-/jest-dev-server-9.0.1.tgz", "integrity": "sha512-eqpJKSvVl4M0ojHZUPNbka8yEzLNbIMiINXDsuMF3lYfIdRO2iPqy+ASR4wBQ6nUyR3OT24oKPWhpsfLhgAVyg==", - "dev": true, "dependencies": { "chalk": "^4.1.2", "cwd": "^0.10.0", @@ -56781,7 +55539,6 @@ "version": "17.11.0", "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", - "dev": true, "dependencies": { "@hapi/hoek": "^9.0.0", "@hapi/topo": "^5.0.0", @@ -56794,21 +55551,18 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, "license": "MIT" }, "packages/scripts/node_modules/json2php": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/json2php/-/json2php-0.0.9.tgz", "integrity": "sha512-fQMYwvPsQt8hxRnCGyg1r2JVi6yL8Um0DIIawiKiMK9yhAAkcRNj5UsBWoaFvFzPpcWbgw9L6wzj+UMYA702Mw==", - "dev": true, "license": "BSD" }, "packages/scripts/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -56820,7 +55574,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, "dependencies": { "semver": "^6.0.0" }, @@ -56835,7 +55588,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -56850,7 +55602,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -56862,7 +55613,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "engines": { "node": ">=6" } @@ -56871,7 +55621,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -56880,7 +55629,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, "dependencies": { "find-up": "^4.0.0" }, @@ -56892,7 +55640,6 @@ "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, "dependencies": { "tslib": "^2.1.0" } @@ -56901,7 +55648,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", @@ -56921,7 +55667,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" @@ -56934,7 +55679,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -56943,7 +55687,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "engines": { "node": ">=14" }, @@ -56955,7 +55698,6 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-9.0.1.tgz", "integrity": "sha512-vaMk8E9CpbjTYToBxLXowDeArGf1+yI7A6PU6Nr57b2g8BVY8nRi5vTBj3bMF8UkCrMdTMyf/Lh+lrcrW2z7pw==", - "dev": true, "dependencies": { "signal-exit": "^4.1.0", "tree-kill": "^1.2.2" @@ -56968,7 +55710,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -56980,7 +55721,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.2.0.tgz", "integrity": "sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ==", - "dev": true, "dependencies": { "axios": "^1.6.1", "joi": "^17.11.0", @@ -57001,15 +55741,15 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/url": "file:../url", + "@wordpress/api-fetch": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/url": "*", "fast-deep-equal": "^3.1.3" }, "engines": { @@ -57050,7 +55790,6 @@ "packages/stylelint-config": { "name": "@wordpress/stylelint-config", "version": "23.2.0", - "dev": true, "license": "MIT", "dependencies": { "@stylistic/stylelint-plugin": "^3.0.1", @@ -57069,7 +55808,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -57081,20 +55819,17 @@ "packages/stylelint-config/node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, "packages/stylelint-config/node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "packages/stylelint-config/node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -57104,7 +55839,6 @@ "version": "14.0.1", "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -57126,7 +55860,6 @@ "version": "14.1.0", "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.1.0.tgz", "integrity": "sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg==", - "dev": true, "dependencies": { "postcss-scss": "^4.0.9", "stylelint-config-recommended": "^14.0.1", @@ -57149,7 +55882,6 @@ "version": "6.5.1", "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.5.1.tgz", "integrity": "sha512-ZLqdqihm6uDYkrsOeD6YWb+stZI8Wn92kUNDhE4M+g9g1aCnRv0JlOrttFiAJJwaNzpdQgX3YJb5vDQXVuO9Ww==", - "dev": true, "dependencies": { "css-tree": "2.3.1", "is-plain-object": "5.0.0", @@ -57173,7 +55905,7 @@ "dependencies": { "@babel/runtime": "7.25.7", "@types/simple-peer": "^9.11.5", - "@wordpress/url": "file:../url", + "@wordpress/url": "*", "import-locals": "^2.0.0", "lib0": "^0.2.42", "simple-peer": "^9.11.0", @@ -57205,7 +55937,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal" + "@wordpress/is-shallow-equal": "*" }, "engines": { "node": ">=18.12.0", @@ -57231,9 +55963,9 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element" + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/element": "*" }, "engines": { "node": ">=18.12.0", @@ -57270,17 +56002,17 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@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/notices": "file:../notices", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", "clsx": "^2.1.1" }, "engines": { diff --git a/package.json b/package.json index 67bfb7cf5df37b..b5f9b1fb0f09e2 100644 --- a/package.json +++ b/package.json @@ -21,81 +21,6 @@ "config": { "IS_GUTENBERG_PLUGIN": true }, - "dependencies": { - "@wordpress/a11y": "file:packages/a11y", - "@wordpress/annotations": "file:packages/annotations", - "@wordpress/api-fetch": "file:packages/api-fetch", - "@wordpress/autop": "file:packages/autop", - "@wordpress/blob": "file:packages/blob", - "@wordpress/block-directory": "file:packages/block-directory", - "@wordpress/block-editor": "file:packages/block-editor", - "@wordpress/block-library": "file:packages/block-library", - "@wordpress/block-serialization-default-parser": "file:packages/block-serialization-default-parser", - "@wordpress/block-serialization-spec-parser": "file:packages/block-serialization-spec-parser", - "@wordpress/blocks": "file:packages/blocks", - "@wordpress/commands": "file:packages/commands", - "@wordpress/components": "file:packages/components", - "@wordpress/compose": "file:packages/compose", - "@wordpress/core-commands": "file:packages/core-commands", - "@wordpress/core-data": "file:packages/core-data", - "@wordpress/customize-widgets": "file:packages/customize-widgets", - "@wordpress/data": "file:packages/data", - "@wordpress/data-controls": "file:packages/data-controls", - "@wordpress/dataviews": "file:packages/dataviews", - "@wordpress/date": "file:packages/date", - "@wordpress/deprecated": "file:packages/deprecated", - "@wordpress/dom": "file:packages/dom", - "@wordpress/dom-ready": "file:packages/dom-ready", - "@wordpress/edit-post": "file:packages/edit-post", - "@wordpress/edit-site": "file:packages/edit-site", - "@wordpress/edit-widgets": "file:packages/edit-widgets", - "@wordpress/editor": "file:packages/editor", - "@wordpress/element": "file:packages/element", - "@wordpress/escape-html": "file:packages/escape-html", - "@wordpress/fields": "file:packages/fields", - "@wordpress/format-library": "file:packages/format-library", - "@wordpress/hooks": "file:packages/hooks", - "@wordpress/html-entities": "file:packages/html-entities", - "@wordpress/i18n": "file:packages/i18n", - "@wordpress/icons": "file:packages/icons", - "@wordpress/interactivity": "file:packages/interactivity", - "@wordpress/interactivity-router": "file:packages/interactivity-router", - "@wordpress/interface": "file:packages/interface", - "@wordpress/is-shallow-equal": "file:packages/is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts", - "@wordpress/keycodes": "file:packages/keycodes", - "@wordpress/list-reusable-blocks": "file:packages/list-reusable-blocks", - "@wordpress/media-utils": "file:packages/media-utils", - "@wordpress/notices": "file:packages/notices", - "@wordpress/nux": "file:packages/nux", - "@wordpress/patterns": "file:packages/patterns", - "@wordpress/plugins": "file:packages/plugins", - "@wordpress/preferences": "file:packages/preferences", - "@wordpress/preferences-persistence": "file:packages/preferences-persistence", - "@wordpress/primitives": "file:packages/primitives", - "@wordpress/priority-queue": "file:packages/priority-queue", - "@wordpress/private-apis": "file:packages/private-apis", - "@wordpress/react-i18n": "file:packages/react-i18n", - "@wordpress/react-native-aztec": "file:packages/react-native-aztec", - "@wordpress/react-native-bridge": "file:packages/react-native-bridge", - "@wordpress/react-native-editor": "file:packages/react-native-editor", - "@wordpress/redux-routine": "file:packages/redux-routine", - "@wordpress/reusable-blocks": "file:packages/reusable-blocks", - "@wordpress/rich-text": "file:packages/rich-text", - "@wordpress/router": "file:packages/router", - "@wordpress/server-side-render": "file:packages/server-side-render", - "@wordpress/shortcode": "file:packages/shortcode", - "@wordpress/style-engine": "file:packages/style-engine", - "@wordpress/sync": "file:packages/sync", - "@wordpress/token-list": "file:packages/token-list", - "@wordpress/undo-manager": "file:packages/undo-manager", - "@wordpress/url": "file:packages/url", - "@wordpress/viewport": "file:packages/viewport", - "@wordpress/vips": "file:packages/vips", - "@wordpress/warning": "file:packages/warning", - "@wordpress/widgets": "file:packages/widgets", - "@wordpress/wordcount": "file:packages/wordcount" - }, "devDependencies": { "@actions/core": "1.9.1", "@actions/github": "5.0.0", @@ -145,33 +70,6 @@ "@types/semver": "7.3.8", "@types/sprintf-js": "1.1.2", "@types/uuid": "8.3.1", - "@wordpress/babel-plugin-import-jsx-pragma": "file:packages/babel-plugin-import-jsx-pragma", - "@wordpress/babel-plugin-makepot": "file:packages/babel-plugin-makepot", - "@wordpress/babel-preset-default": "file:packages/babel-preset-default", - "@wordpress/base-styles": "file:packages/base-styles", - "@wordpress/browserslist-config": "file:packages/browserslist-config", - "@wordpress/create-block": "file:packages/create-block", - "@wordpress/create-block-tutorial-template": "file:packages/create-block-tutorial-template", - "@wordpress/dependency-extraction-webpack-plugin": "file:packages/dependency-extraction-webpack-plugin", - "@wordpress/docgen": "file:packages/docgen", - "@wordpress/e2e-test-utils": "file:packages/e2e-test-utils", - "@wordpress/e2e-test-utils-playwright": "file:packages/e2e-test-utils-playwright", - "@wordpress/e2e-tests": "file:packages/e2e-tests", - "@wordpress/env": "file:packages/env", - "@wordpress/eslint-plugin": "file:packages/eslint-plugin", - "@wordpress/jest-console": "file:packages/jest-console", - "@wordpress/jest-preset-default": "file:packages/jest-preset-default", - "@wordpress/jest-puppeteer-axe": "file:packages/jest-puppeteer-axe", - "@wordpress/lazy-import": "file:packages/lazy-import", - "@wordpress/npm-package-json-lint-config": "file:packages/npm-package-json-lint-config", - "@wordpress/postcss-plugins-preset": "file:packages/postcss-plugins-preset", - "@wordpress/postcss-themes": "file:packages/postcss-themes", - "@wordpress/prettier-config": "file:packages/prettier-config", - "@wordpress/project-management-automation": "file:packages/project-management-automation", - "@wordpress/readable-js-assets-webpack-plugin": "file:packages/readable-js-assets-webpack-plugin", - "@wordpress/report-flaky-tests": "file:packages/report-flaky-tests", - "@wordpress/scripts": "file:packages/scripts", - "@wordpress/stylelint-config": "file:packages/stylelint-config", "ajv": "8.7.1", "appium": "2.0.0", "babel-jest": "29.7.0", @@ -276,7 +174,7 @@ "build": "npm run build:packages && wp-scripts build", "build:analyze-bundles": "npm run build -- --webpack-bundle-analyzer", "build:package-types": "node ./bin/packages/validate-typescript-version.js && ( tsc --build || ( echo 'tsc failed. Try cleaning up first: `npm run clean:package-types`'; exit 1 ) ) && node ./bin/packages/check-build-type-declaration-files.js", - "prebuild:packages": "npm run clean:packages && lerna run build", + "prebuild:packages": "npm run clean:packages && npm run --if-present --workspaces build", "build:packages": "npm run --silent build:package-types && node ./bin/packages/build.js", "build:plugin-zip": "bash ./bin/build-plugin-zip.sh", "clean:package-types": "tsc --build --clean && rimraf \"./packages/*/build-types\"", @@ -310,7 +208,7 @@ "lint:pkg-json": "wp-scripts lint-pkg-json . 'packages/*/package.json'", "native": "npm run --prefix packages/react-native-editor", "other:changelog": "node ./bin/plugin/cli.js changelog", - "other:check-licenses": "concurrently \"wp-scripts check-licenses --prod --gpl2 --ignore=@react-native-community/cli,@react-native-community/cli-platform-ios,@ampproject/remapping,human-signals,fb-watchman,walker,chrome-launcher,lighthouse-logger,chromium-edge-launcher\" \"wp-scripts check-licenses --dev\"", + "other:check-licenses": "concurrently \"node ./bin/check-licenses.mjs\" \"wp-scripts check-licenses --dev\"", "preother:check-local-changes": "npm run docs:build", "other:check-local-changes": "node ./bin/check-local-changes.js", "other:cherry-pick": "node ./bin/cherry-pick.mjs", @@ -389,5 +287,8 @@ "**/tsconfig.json": [ "npm run lint:tsconfig" ] - } + }, + "workspaces": [ + "packages/*" + ] } diff --git a/packages/README.md b/packages/README.md index 0b131f6c404d4e..27efdf2d43ad52 100644 --- a/packages/README.md +++ b/packages/README.md @@ -1,6 +1,6 @@ # Managing Packages -This repository uses [monorepo] to manage WordPress modules and publish them with [lerna] as packages to [npm]. +This repository uses [npm workspaces](https://docs.npmjs.com/cli/v10/using-npm/workspaces) to manage WordPress packages and [lerna](https://lerna.js.org/) to publish them with to [npm](https://www.npmjs.com/). ## Creating a New Package @@ -36,11 +36,7 @@ When creating a new package, you need to provide at least the following: } ``` This assumes that your code is located in the `src` folder and will be transpiled with `Babel`. -2. `.npmrc` file which disables creating `package-lock.json` file for the package: - ``` - package-lock=false - ``` -3. `README.md` file containing at least: +1. `README.md` file containing at least: - Package name - Package description - Installation details @@ -48,7 +44,7 @@ When creating a new package, you need to provide at least the following: - API documentation, if applicable ([more info](#maintaining-api-documentation)) - A link to the contributing guidelines ([here's an example](https://github.com/WordPress/gutenberg/tree/HEAD/packages/a11y/README.md#contributing-to-this-package) from the a11y package) - `Code is Poetry` logo (`<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p>`) -4. `CHANGELOG.md` file containing at least: +1. `CHANGELOG.md` file containing at least: ``` <!-- Learn how to maintain this file at https://github.com/WordPress/gutenberg/tree/HEAD/packages#maintaining-changelogs. --> @@ -70,35 +66,32 @@ Production dependencies are stored in the `dependencies` section of the package #### Adding New Dependencies -The simplest way to add a production dependency to one of the packages is to run a very convenient [lerna add](https://github.com/lerna/lerna/tree/HEAD/commands/add#readme) command from the root of the project. +The simplest way to add a production dependency to one of the packages is to run a command like the following from the root of the project. _Example:_ ```bash -lerna add change-case packages/a11y +npm install change-case -w packages/a11y ``` -This command adds the latest version of `change-case` as a dependency to the `@wordpress/a11y` package, which is located in `packages/a11y` folder. +This command adds the `change-case` as a dependency to the `@wordpress/a11y` package, which is located in `packages/a11y` folder. If there was the same dependency installed then the version specified in the `package-lock.json` file is going to be reused. If you want to enforce a different version, you can do so by adding the `@` suffix to the package name. + +_Example:_ + +```bash +npm install change-case@latest -w packages/a11y +``` #### Removing Existing Dependencies -Removing a dependency from one of the WordPress packages requires some manual work. You need to remove the line in the corresponding `dependencies` section of the `package.json` file. +Removing a dependency from one of the WordPress packages is similar to installation. You need to run a command like the following from the root of the project. _Example:_ -```diff -+++ b/packages/scripts/package.json -@@ -43,7 +43,6 @@ - "check-node-version": "^4.1.0", - "cross-spawn": "^5.1.0", - "eslint": "^7.1.0", -- "jest": "^29.6.2", - "minimist": "^1.2.0", - "npm-package-json-lint": "^6.4.0", +```bash +npm uninstall change-case -w packages/a11y ``` -Next, you need to run `npm install` in the root of the project to ensure that `package-lock.json` file gets properly regenerated. - #### Updating Existing Dependencies This is the most confusing part of working with [monorepo] which causes a lot of hassles for contributors. The most successful strategy so far is to do the following: @@ -239,10 +232,6 @@ For consumers to use the published type declarations, we'll set the `types` fiel Ensure that the `build-types` directory will be included in the published package, for example if a `files` field is declared. -[lerna]: https://lerna.js.org/ -[monorepo]: https://monorepo.tools -[npm]: https://www.npmjs.com/ - ## Optimizing for bundlers In order for bundlers to tree-shake packages effectively, they often need to know whether a package includes side effects in its code. This is done through the `sideEffects` field in the package's `package.json`. diff --git a/packages/a11y/.npmrc b/packages/a11y/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/a11y/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 230005587619f3..a506cb940e7765 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -31,10 +31,11 @@ "wpScriptModuleExports": "./build-module/module/index.js", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/dom-ready": "file:../dom-ready", - "@wordpress/i18n": "file:../i18n" + "@wordpress/dom-ready": "*", + "@wordpress/i18n": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/annotations/.npmrc b/packages/annotations/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/annotations/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 259745c3fd82e2..4a1f0fe2b771b5 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -27,10 +27,10 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/data": "file:../data", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/rich-text": "file:../rich-text", + "@wordpress/data": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/rich-text": "*", "uuid": "^9.0.1" }, "peerDependencies": { @@ -38,5 +38,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/api-fetch/.npmrc b/packages/api-fetch/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/api-fetch/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 35fb2da0ec1aad..79968c31d1043a 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -29,10 +29,11 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/i18n": "file:../i18n", - "@wordpress/url": "file:../url" + "@wordpress/i18n": "*", + "@wordpress/url": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/autop/.npmrc b/packages/autop/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/autop/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/autop/package.json b/packages/autop/package.json index 9e2b61ad211cff..aea14b2c666e14 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -32,5 +32,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/babel-plugin-import-jsx-pragma/.npmrc b/packages/babel-plugin-import-jsx-pragma/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/babel-plugin-import-jsx-pragma/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/babel-plugin-makepot/.npmrc b/packages/babel-plugin-makepot/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/babel-plugin-makepot/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/babel-preset-default/.npmrc b/packages/babel-preset-default/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/babel-preset-default/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index fb8ae826e55978..777a40012d67f7 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -38,8 +38,8 @@ "@babel/preset-env": "7.25.7", "@babel/preset-typescript": "7.25.7", "@babel/runtime": "7.25.7", - "@wordpress/browserslist-config": "file:../browserslist-config", - "@wordpress/warning": "file:../warning", + "@wordpress/browserslist-config": "*", + "@wordpress/warning": "*", "browserslist": "^4.21.10", "core-js": "^3.31.0", "react": "^18.3.0" diff --git a/packages/base-styles/.npmrc b/packages/base-styles/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/base-styles/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/blob/.npmrc b/packages/blob/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/blob/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/blob/package.json b/packages/blob/package.json index 087343d1b33a04..183e6aca33dc0c 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -32,5 +32,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/block-directory/.npmrc b/packages/block-directory/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/block-directory/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 0b72a7ff2099a1..6ff9ad7d510861 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -27,24 +27,24 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@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/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/plugins": "file:../plugins", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/plugins": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", "change-case": "^4.1.2", "clsx": "^2.1.1" }, @@ -54,5 +54,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/block-editor/.npmrc b/packages/block-editor/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/block-editor/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 92392b4d9563b2..b798e626c2e90f 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -36,36 +36,36 @@ "@emotion/react": "^11.7.1", "@emotion/styled": "^11.6.0", "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/style-engine": "file:../style-engine", - "@wordpress/token-list": "file:../token-list", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/block-serialization-default-parser": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/style-engine": "*", + "@wordpress/token-list": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -87,5 +87,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/block-library/.npmrc b/packages/block-library/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/block-library/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/block-library/package.json b/packages/block-library/package.json index e9e76b8018e1d3..18ad0e46059c91 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -39,39 +39,39 @@ }, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/autop": "file:../autop", - "@wordpress/blob": "file:../blob", - "@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/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interactivity": "file:../interactivity", - "@wordpress/interactivity-router": "file:../interactivity-router", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/server-side-render": "file:../server-side-render", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/autop": "*", + "@wordpress/blob": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interactivity": "*", + "@wordpress/interactivity-router": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/rich-text": "*", + "@wordpress/server-side-render": "*", + "@wordpress/url": "*", + "@wordpress/viewport": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -88,5 +88,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/block-serialization-default-parser/.npmrc b/packages/block-serialization-default-parser/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/block-serialization-default-parser/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 3b159dc3534888..14d2db0f688688 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -33,5 +33,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/block-serialization-spec-parser/.npmrc b/packages/block-serialization-spec-parser/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/block-serialization-spec-parser/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 49c3ed6c872c73..9a871250162ca0 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -37,5 +37,6 @@ "build": "concurrently \"npm run build:js\" \"npm run build:php\"", "build:js": "pegjs --format commonjs -o ./parser.js ./grammar.pegjs", "build:php": "node bin/create-php-parser.js" - } + }, + "wpScript": true } diff --git a/packages/blocks/.npmrc b/packages/blocks/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/blocks/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 9b7665ae9c87d6..d7207548d173fc 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -30,21 +30,21 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/autop": "file:../autop", - "@wordpress/blob": "file:../blob", - "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/shortcode": "file:../shortcode", - "@wordpress/warning": "file:../warning", + "@wordpress/autop": "*", + "@wordpress/blob": "*", + "@wordpress/block-serialization-default-parser": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/shortcode": "*", + "@wordpress/warning": "*", "change-case": "^4.1.2", "colord": "^2.7.0", "fast-deep-equal": "^3.1.3", @@ -62,5 +62,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/browserslist-config/.npmrc b/packages/browserslist-config/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/browserslist-config/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/commands/.npmrc b/packages/commands/.npmrc deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/packages/commands/package.json b/packages/commands/package.json index e1529416aa7df7..4d35172ce8186d 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -28,13 +28,13 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/private-apis": "file:../private-apis", + "@wordpress/components": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/private-apis": "*", "clsx": "^2.1.1", "cmdk": "^1.0.0" }, @@ -44,5 +44,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/components/.npmrc b/packages/components/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/components/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/components/package.json b/packages/components/package.json index 16c7b6c63c0b18..a44e0afe89152b 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -43,23 +43,23 @@ "@types/gradient-parser": "0.1.3", "@types/highlight-words-core": "1.2.1", "@use-gesture/react": "^10.3.1", - "@wordpress/a11y": "file:../a11y", - "@wordpress/compose": "file:../compose", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/warning": "file:../warning", + "@wordpress/a11y": "*", + "@wordpress/compose": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keycodes": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/warning": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -83,5 +83,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/compose/.npmrc b/packages/compose/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/compose/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/compose/package.json b/packages/compose/package.json index d1eacfd72f0d86..f7aa8a3bf9b3bc 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -32,13 +32,13 @@ "dependencies": { "@babel/runtime": "7.25.7", "@types/mousetrap": "^1.6.8", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/undo-manager": "file:../undo-manager", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keycodes": "*", + "@wordpress/priority-queue": "*", + "@wordpress/undo-manager": "*", "change-case": "^4.1.2", "clipboard": "^2.0.11", "mousetrap": "^1.6.5", @@ -49,5 +49,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/core-commands/.npmrc b/packages/core-commands/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/core-commands/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 87dc4fb3722f50..adad0ee55afc23 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -28,19 +28,19 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/commands": "file:../commands", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/router": "file:../router", - "@wordpress/url": "file:../url" + "@wordpress/block-editor": "*", + "@wordpress/commands": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/private-apis": "*", + "@wordpress/router": "*", + "@wordpress/url": "*" }, "peerDependencies": { "react": "^18.0.0", @@ -48,5 +48,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/core-data/.npmrc b/packages/core-data/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/core-data/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/core-data/package.json b/packages/core-data/package.json index cd568cc60c596b..6b70fb0af3a8f4 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -32,22 +32,22 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/sync": "file:../sync", - "@wordpress/undo-manager": "file:../undo-manager", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/sync": "*", + "@wordpress/undo-manager": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", "change-case": "^4.1.2", "equivalent-key-map": "^0.2.2", "fast-deep-equal": "^3.1.3", @@ -60,5 +60,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/create-block-interactive-template/.npmrc b/packages/create-block-interactive-template/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/create-block-interactive-template/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/create-block-tutorial-template/.npmrc b/packages/create-block-tutorial-template/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/create-block-tutorial-template/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/create-block/.npmrc b/packages/create-block/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/create-block/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 06556dbfaaa342..a9215bb2699d32 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -31,7 +31,7 @@ "wp-create-block": "./index.js" }, "dependencies": { - "@wordpress/lazy-import": "file:../lazy-import", + "@wordpress/lazy-import": "*", "chalk": "^4.0.0", "change-case": "^4.1.2", "check-node-version": "^4.1.0", diff --git a/packages/customize-widgets/.npmrc b/packages/customize-widgets/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/customize-widgets/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 15cf61c352af8f..68e736c566c110 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -25,27 +25,27 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/widgets": "file:../widgets", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interface": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/media-utils": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/widgets": "*", "clsx": "^2.1.1", "fast-deep-equal": "^3.1.3" }, @@ -55,5 +55,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 2820445254f0f4..84462f49e5c0c8 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -29,14 +29,15 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated" + "@wordpress/api-fetch": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*" }, "peerDependencies": { "react": "^18.0.0" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/data/.npmrc b/packages/data/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/data/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/data/package.json b/packages/data/package.json index b3adf78a2f3932..5e1817f0fb6ad8 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -30,13 +30,13 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/compose": "file:../compose", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/redux-routine": "file:../redux-routine", + "@wordpress/compose": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/is-shallow-equal": "*", + "@wordpress/priority-queue": "*", + "@wordpress/private-apis": "*", + "@wordpress/redux-routine": "*", "deepmerge": "^4.3.0", "equivalent-key-map": "^0.2.2", "is-plain-object": "^5.0.0", @@ -50,5 +50,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/dataviews/.npmrc b/packages/dataviews/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/dataviews/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index d95e079033c3b6..a83fd163517d0a 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -30,15 +30,15 @@ "dependencies": { "@ariakit/react": "^0.4.10", "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/warning": "file:../warning", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/warning": "*", "clsx": "^2.1.1", "remove-accents": "^0.5.0" }, @@ -47,5 +47,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/date/.npmrc b/packages/date/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/date/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/date/package.json b/packages/date/package.json index 2710aeb0437be8..a5925869f2acc0 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -28,11 +28,12 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/deprecated": "file:../deprecated", + "@wordpress/deprecated": "*", "moment": "^2.29.4", "moment-timezone": "^0.5.40" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/deprecated/.npmrc b/packages/deprecated/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/deprecated/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index c44b7052c1c545..4871d5772dbb64 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -29,9 +29,10 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/hooks": "file:../hooks" + "@wordpress/hooks": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/docgen/.npmrc b/packages/docgen/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/docgen/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/dom-ready/.npmrc b/packages/dom-ready/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/dom-ready/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 62cbf25ae12e86..65334a21bd1373 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -32,5 +32,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/dom/.npmrc b/packages/dom/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/dom/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/dom/package.json b/packages/dom/package.json index 9028598f160785..9d738a07b89b99 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -30,9 +30,10 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/deprecated": "file:../deprecated" + "@wordpress/deprecated": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/e2e-test-utils-playwright/.npmrc b/packages/e2e-test-utils-playwright/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/e2e-test-utils-playwright/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/e2e-test-utils/.npmrc b/packages/e2e-test-utils/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/e2e-test-utils/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index b328245162fef1..ca116dd0264a71 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -31,9 +31,9 @@ "module": "build-module/index.js", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/url": "file:../url", + "@wordpress/api-fetch": "*", + "@wordpress/keycodes": "*", + "@wordpress/url": "*", "change-case": "^4.1.2", "form-data": "^4.0.0", "node-fetch": "2.7.0" diff --git a/packages/e2e-tests/.npmrc b/packages/e2e-tests/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/e2e-tests/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index a2192c10049380..5bf2b5c8663ac7 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -24,13 +24,13 @@ "npm": ">=8.19.2" }, "dependencies": { - "@wordpress/e2e-test-utils": "file:../e2e-test-utils", - "@wordpress/interactivity": "file:../interactivity", - "@wordpress/interactivity-router": "file:../interactivity-router", - "@wordpress/jest-console": "file:../jest-console", - "@wordpress/jest-puppeteer-axe": "file:../jest-puppeteer-axe", - "@wordpress/scripts": "file:../scripts", - "@wordpress/url": "file:../url", + "@wordpress/e2e-test-utils": "*", + "@wordpress/interactivity": "*", + "@wordpress/interactivity-router": "*", + "@wordpress/jest-console": "*", + "@wordpress/jest-puppeteer-axe": "*", + "@wordpress/scripts": "*", + "@wordpress/url": "*", "chalk": "^4.0.0", "expect-puppeteer": "^4.4.0", "filenamify": "^4.2.0", diff --git a/packages/edit-post/.npmrc b/packages/edit-post/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/edit-post/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index e2653a2dab9736..028520e79cad7a 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -28,35 +28,35 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-commands": "file:../core-commands", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/warning": "file:../warning", - "@wordpress/widgets": "file:../widgets", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-commands": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", + "@wordpress/viewport": "*", + "@wordpress/warning": "*", + "@wordpress/widgets": "*", "clsx": "^2.1.1", "memize": "^2.1.0" }, @@ -66,5 +66,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/edit-site/.npmrc b/packages/edit-site/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/edit-site/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index e187acbb1b653f..83cae4a7100bc7 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -29,45 +29,45 @@ "dependencies": { "@babel/runtime": "7.25.7", "@react-spring/web": "^9.4.5", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-commands": "file:../core-commands", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/primitives": "file:../primitives", - "@wordpress/priority-queue": "file:../priority-queue", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/router": "file:../router", - "@wordpress/style-engine": "file:../style-engine", - "@wordpress/url": "file:../url", - "@wordpress/viewport": "file:../viewport", - "@wordpress/widgets": "file:../widgets", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-commands": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dataviews": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/primitives": "*", + "@wordpress/priority-queue": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/router": "*", + "@wordpress/style-engine": "*", + "@wordpress/url": "*", + "@wordpress/viewport": "*", + "@wordpress/widgets": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.9.2", @@ -81,5 +81,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/edit-widgets/.npmrc b/packages/edit-widgets/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/edit-widgets/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index cc2b97ac809d01..1b412c5adb78c3 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -28,33 +28,33 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/editor": "file:../editor", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/url": "file:../url", - "@wordpress/widgets": "file:../widgets", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/editor": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interface": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/media-utils": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/url": "*", + "@wordpress/widgets": "*", "clsx": "^2.1.1" }, "peerDependencies": { @@ -63,5 +63,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/editor/.npmrc b/packages/editor/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/editor/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/editor/package.json b/packages/editor/package.json index 7568d0d6b8470f..8c799085875c20 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -32,41 +32,41 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/commands": "file:../commands", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/date": "file:../date", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/dom": "file:../dom", - "@wordpress/element": "file:../element", - "@wordpress/fields": "file:../fields", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/interface": "file:../interface", - "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", - "@wordpress/keycodes": "file:../keycodes", - "@wordpress/media-utils": "file:../media-utils", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/reusable-blocks": "file:../reusable-blocks", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/server-side-render": "file:../server-side-render", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", - "@wordpress/wordcount": "file:../wordcount", + "@wordpress/a11y": "*", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/commands": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dataviews": "*", + "@wordpress/date": "*", + "@wordpress/deprecated": "*", + "@wordpress/dom": "*", + "@wordpress/element": "*", + "@wordpress/fields": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/interface": "*", + "@wordpress/keyboard-shortcuts": "*", + "@wordpress/keycodes": "*", + "@wordpress/media-utils": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/reusable-blocks": "*", + "@wordpress/rich-text": "*", + "@wordpress/server-side-render": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", + "@wordpress/wordcount": "*", "change-case": "^4.1.2", "client-zip": "^2.4.5", "clsx": "^2.1.1", @@ -85,5 +85,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/element/.npmrc b/packages/element/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/element/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/element/package.json b/packages/element/package.json index 7efc62530eadb9..51e08e534b271e 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -32,7 +32,7 @@ "@babel/runtime": "7.25.7", "@types/react": "^18.2.79", "@types/react-dom": "^18.2.25", - "@wordpress/escape-html": "file:../escape-html", + "@wordpress/escape-html": "*", "change-case": "^4.1.2", "is-plain-object": "^5.0.0", "react": "^18.3.0", @@ -40,5 +40,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/env/.npmrc b/packages/env/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/env/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/escape-html/.npmrc b/packages/escape-html/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/escape-html/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index bc72f326e70b19..cadf7e9eaa174c 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -32,5 +32,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/eslint-plugin/.npmrc b/packages/eslint-plugin/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/eslint-plugin/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 5605f343ef5fd9..4a85de55f671a3 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -34,8 +34,8 @@ "@babel/eslint-parser": "7.25.7", "@typescript-eslint/eslint-plugin": "^6.4.1", "@typescript-eslint/parser": "^6.4.1", - "@wordpress/babel-preset-default": "file:../babel-preset-default", - "@wordpress/prettier-config": "file:../prettier-config", + "@wordpress/babel-preset-default": "*", + "@wordpress/prettier-config": "*", "cosmiconfig": "^7.0.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.2", diff --git a/packages/fields/.npmrc b/packages/fields/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/fields/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/fields/package.json b/packages/fields/package.json index 1f470e6ecba64c..019ec99ed7a8ed 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -32,25 +32,25 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/dataviews": "file:../dataviews", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/patterns": "file:../patterns", - "@wordpress/primitives": "file:../primitives", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", - "@wordpress/warning": "file:../warning", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/dataviews": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/patterns": "*", + "@wordpress/primitives": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", + "@wordpress/warning": "*", "change-case": "4.1.2", "client-zip": "^2.4.5" }, @@ -59,5 +59,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/format-library/.npmrc b/packages/format-library/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/format-library/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/format-library/package.json b/packages/format-library/package.json index 636552b7408a8c..e30ca517de794e 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -27,18 +27,18 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/rich-text": "file:../rich-text", - "@wordpress/url": "file:../url" + "@wordpress/a11y": "*", + "@wordpress/block-editor": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/private-apis": "*", + "@wordpress/rich-text": "*", + "@wordpress/url": "*" }, "peerDependencies": { "react": "^18.0.0", @@ -46,5 +46,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/hooks/.npmrc b/packages/hooks/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/hooks/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 8f8674d0fd4c22..04a0865f5c44ae 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -31,5 +31,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/html-entities/.npmrc b/packages/html-entities/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/html-entities/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 4079728d6ae085..7ccf5d52f55fb7 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -32,5 +32,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/i18n/.npmrc b/packages/i18n/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/i18n/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 51950104c52e4a..f2ccf4b0fa2934 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/hooks": "file:../hooks", + "@wordpress/hooks": "*", "gettext-parser": "^1.3.1", "memize": "^2.1.0", "sprintf-js": "^1.1.1", @@ -39,5 +39,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/icons/.npmrc b/packages/icons/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/icons/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/icons/package.json b/packages/icons/package.json index 28dedd381de029..a2e3c97b67b55e 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -30,10 +30,11 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", - "@wordpress/primitives": "file:../primitives" + "@wordpress/element": "*", + "@wordpress/primitives": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/interactivity-router/.npmrc b/packages/interactivity-router/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/interactivity-router/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index bb482450699027..2d33456a5712b0 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -28,8 +28,8 @@ "types": "build-types", "wpScriptModuleExports": "./build-module/index.js", "dependencies": { - "@wordpress/a11y": "file:../a11y", - "@wordpress/interactivity": "file:../interactivity" + "@wordpress/a11y": "*", + "@wordpress/interactivity": "*" }, "publishConfig": { "access": "public" diff --git a/packages/interactivity/.npmrc b/packages/interactivity/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/interactivity/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/interface/.npmrc b/packages/interface/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/interface/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/interface/package.json b/packages/interface/package.json index 964960afc2e1b9..e5870e0dfadfb2 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -33,18 +33,18 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/plugins": "file:../plugins", - "@wordpress/preferences": "file:../preferences", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/viewport": "file:../viewport", + "@wordpress/a11y": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/plugins": "*", + "@wordpress/preferences": "*", + "@wordpress/private-apis": "*", + "@wordpress/viewport": "*", "clsx": "^2.1.1" }, "peerDependencies": { @@ -53,5 +53,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/is-shallow-equal/.npmrc b/packages/is-shallow-equal/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/is-shallow-equal/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 617f0415935d88..1034ce1e76cda8 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -41,5 +41,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/jest-console/.npmrc b/packages/jest-console/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/jest-console/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/jest-preset-default/.npmrc b/packages/jest-preset-default/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/jest-preset-default/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 953e923dda253b..2db25a45f5b8e7 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -31,7 +31,7 @@ ], "main": "index.js", "dependencies": { - "@wordpress/jest-console": "file:../jest-console", + "@wordpress/jest-console": "*", "babel-jest": "29.7.0" }, "peerDependencies": { diff --git a/packages/jest-puppeteer-axe/.npmrc b/packages/jest-puppeteer-axe/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/jest-puppeteer-axe/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/keyboard-shortcuts/.npmrc b/packages/keyboard-shortcuts/.npmrc deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 7ef7599e296566..4687df000bb3a7 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -27,14 +27,15 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/keycodes": "file:../keycodes" + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/keycodes": "*" }, "peerDependencies": { "react": "^18.0.0" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/keycodes/.npmrc b/packages/keycodes/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/keycodes/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 8ec0c6278595cf..cce62c927fa206 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -29,9 +29,10 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/i18n": "file:../i18n" + "@wordpress/i18n": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/lazy-import/.npmrc b/packages/lazy-import/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/lazy-import/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/list-reusable-blocks/.npmrc b/packages/list-reusable-blocks/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/list-reusable-blocks/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 8ee807dd4404f0..d5a7dace810b48 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -27,12 +27,12 @@ "module": "build-module/index.js", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", "change-case": "^4.1.2" }, "peerDependencies": { @@ -41,5 +41,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/media-utils/.npmrc b/packages/media-utils/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/media-utils/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 67adfe9673db28..0ba56f26706833 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -28,12 +28,13 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blob": "file:../blob", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n" + "@wordpress/api-fetch": "*", + "@wordpress/blob": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/notices/.npmrc b/packages/notices/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/notices/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/notices/package.json b/packages/notices/package.json index 798965e93b25ce..de04c49a26cd6e 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -28,13 +28,14 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/data": "file:../data" + "@wordpress/a11y": "*", + "@wordpress/data": "*" }, "peerDependencies": { "react": "^18.0.0" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/npm-package-json-lint-config/.npmrc b/packages/npm-package-json-lint-config/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/npm-package-json-lint-config/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/nux/.npmrc b/packages/nux/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/nux/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/nux/package.json b/packages/nux/package.json index b6b6695b5b1058..122bb2758263d6 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -32,13 +32,13 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons" + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*" }, "peerDependencies": { "react": "^18.0.0", @@ -46,5 +46,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/patterns/.npmrc b/packages/patterns/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/patterns/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 6d1dc87554bc36..3da30812d61edd 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -32,20 +32,20 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@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/html-entities": "file:../html-entities", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url" + "@wordpress/a11y": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/html-entities": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*" }, "peerDependencies": { "react": "^18.0.0", @@ -53,5 +53,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/plugins/.npmrc b/packages/plugins/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/plugins/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 0fc38303213f25..a2ce790e0935e5 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -28,12 +28,12 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/icons": "file:../icons", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/icons": "*", + "@wordpress/is-shallow-equal": "*", "memize": "^2.0.1" }, "peerDependencies": { @@ -42,5 +42,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/postcss-plugins-preset/.npmrc b/packages/postcss-plugins-preset/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/postcss-plugins-preset/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index e5c1e2ab1629ec..82753b0ff56d38 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -30,7 +30,7 @@ ], "main": "lib/index.js", "dependencies": { - "@wordpress/base-styles": "file:../base-styles", + "@wordpress/base-styles": "*", "autoprefixer": "^10.2.5" }, "peerDependencies": { diff --git a/packages/postcss-themes/.npmrc b/packages/postcss-themes/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/postcss-themes/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/preferences-persistence/.npmrc b/packages/preferences-persistence/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/preferences-persistence/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index cd2d86b61264eb..e91c8f295d4653 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -29,9 +29,10 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch" + "@wordpress/api-fetch": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/preferences/.npmrc b/packages/preferences/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/preferences/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/preferences/package.json b/packages/preferences/package.json index 8dc6b2f919a20c..ef9f0ef8803dfc 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -30,15 +30,15 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/private-apis": "file:../private-apis", + "@wordpress/a11y": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/private-apis": "*", "clsx": "^2.1.1" }, "peerDependencies": { @@ -47,5 +47,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/prettier-config/.npmrc b/packages/prettier-config/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/prettier-config/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/primitives/.npmrc b/packages/primitives/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/primitives/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/primitives/package.json b/packages/primitives/package.json index b81a5049d05b5e..67117e037002c6 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -32,7 +32,7 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", + "@wordpress/element": "*", "clsx": "^2.1.1" }, "peerDependencies": { @@ -40,5 +40,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/priority-queue/.npmrc b/packages/priority-queue/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/priority-queue/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 0e0dde33cc39a0..0113bb9b1bc62c 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -34,5 +34,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index a76fff0de91f5f..eae83e1fc46d34 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -33,5 +33,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/project-management-automation/.npmrc b/packages/project-management-automation/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/project-management-automation/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 77dc00b1b8e273..6a741d33f997c1 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -29,11 +29,12 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", + "@wordpress/element": "*", + "@wordpress/i18n": "*", "utility-types": "^3.10.0" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/react-native-aztec/.npmrc b/packages/react-native-aztec/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/react-native-aztec/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/react-native-aztec/package.json b/packages/react-native-aztec/package.json index e2f5d5f425d869..b0327b531395e5 100644 --- a/packages/react-native-aztec/package.json +++ b/packages/react-native-aztec/package.json @@ -23,8 +23,8 @@ "npm": ">=8.19.2" }, "dependencies": { - "@wordpress/element": "file:../element", - "@wordpress/keycodes": "file:../keycodes" + "@wordpress/element": "*", + "@wordpress/keycodes": "*" }, "peerDependencies": { "react": "*", diff --git a/packages/react-native-bridge/.npmrc b/packages/react-native-bridge/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/react-native-bridge/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/react-native-bridge/package.json b/packages/react-native-bridge/package.json index 925b83103dca00..b0c0a2485520df 100644 --- a/packages/react-native-bridge/package.json +++ b/packages/react-native-bridge/package.json @@ -24,7 +24,7 @@ "main": "index.js", "react-native": "index", "dependencies": { - "@wordpress/react-native-aztec": "file:../react-native-aztec" + "@wordpress/react-native-aztec": "*" }, "peerDependencies": { "react-native": "*" diff --git a/packages/react-native-editor/.npmrc b/packages/react-native-editor/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/react-native-editor/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json index 3a345a23e0a5d9..e6e53af1190ad7 100644 --- a/packages/react-native-editor/package.json +++ b/packages/react-native-editor/package.json @@ -38,18 +38,18 @@ "@react-navigation/native": "6.0.14", "@react-navigation/routers": "5.4.9", "@react-navigation/stack": "6.3.5", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/block-library": "file:../block-library", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/data": "file:../data", - "@wordpress/edit-post": "file:../edit-post", - "@wordpress/element": "file:../element", - "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/react-native-aztec": "file:../react-native-aztec", - "@wordpress/react-native-bridge": "file:../react-native-bridge", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/block-library": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/data": "*", + "@wordpress/edit-post": "*", + "@wordpress/element": "*", + "@wordpress/hooks": "*", + "@wordpress/i18n": "*", + "@wordpress/react-native-aztec": "*", + "@wordpress/react-native-bridge": "*", "core-js": "^3.31.0", "fast-average-color": "^9.1.1", "gettext-parser": "^1.3.1", diff --git a/packages/readable-js-assets-webpack-plugin/.npmrc b/packages/readable-js-assets-webpack-plugin/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/readable-js-assets-webpack-plugin/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/redux-routine/.npmrc b/packages/redux-routine/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/redux-routine/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 46dffc7e069e19..70d1cae1a8b5fd 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -40,5 +40,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/report-flaky-tests/.npmrc b/packages/report-flaky-tests/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/report-flaky-tests/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/reusable-blocks/.npmrc b/packages/reusable-blocks/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/reusable-blocks/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 483ecceeb9e252..461a17001b0c38 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -30,17 +30,17 @@ ], "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/block-editor": "file:../block-editor", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/core-data": "file:../core-data", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons", - "@wordpress/notices": "file:../notices", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url" + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*" }, "peerDependencies": { "react": "^18.0.0", @@ -48,5 +48,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/rich-text/.npmrc b/packages/rich-text/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/rich-text/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index a4a15743a13ed5..c2b99faaa72d7f 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -32,14 +32,14 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/a11y": "file:../a11y", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/escape-html": "file:../escape-html", - "@wordpress/i18n": "file:../i18n", - "@wordpress/keycodes": "file:../keycodes", + "@wordpress/a11y": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/escape-html": "*", + "@wordpress/i18n": "*", + "@wordpress/keycodes": "*", "memize": "^2.1.0" }, "peerDependencies": { @@ -47,5 +47,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/router/.npmrc b/packages/router/.npmrc deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/packages/router/package.json b/packages/router/package.json index a7a181fbde9705..d7a1219e0b95cf 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -28,9 +28,9 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "file:../element", - "@wordpress/private-apis": "file:../private-apis", - "@wordpress/url": "file:../url", + "@wordpress/element": "*", + "@wordpress/private-apis": "*", + "@wordpress/url": "*", "history": "^5.3.0" }, "peerDependencies": { @@ -38,5 +38,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/scripts/.npmrc b/packages/scripts/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/scripts/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 9bc4fcd915b204..ef1ff601152429 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -35,16 +35,16 @@ "@babel/core": "7.25.7", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", "@svgr/webpack": "^8.0.1", - "@wordpress/babel-preset-default": "file:../babel-preset-default", - "@wordpress/browserslist-config": "file:../browserslist-config", - "@wordpress/dependency-extraction-webpack-plugin": "file:../dependency-extraction-webpack-plugin", - "@wordpress/e2e-test-utils-playwright": "file:../e2e-test-utils-playwright", - "@wordpress/eslint-plugin": "file:../eslint-plugin", - "@wordpress/jest-preset-default": "file:../jest-preset-default", - "@wordpress/npm-package-json-lint-config": "file:../npm-package-json-lint-config", - "@wordpress/postcss-plugins-preset": "file:../postcss-plugins-preset", - "@wordpress/prettier-config": "file:../prettier-config", - "@wordpress/stylelint-config": "file:../stylelint-config", + "@wordpress/babel-preset-default": "*", + "@wordpress/browserslist-config": "*", + "@wordpress/dependency-extraction-webpack-plugin": "*", + "@wordpress/e2e-test-utils-playwright": "*", + "@wordpress/eslint-plugin": "*", + "@wordpress/jest-preset-default": "*", + "@wordpress/npm-package-json-lint-config": "*", + "@wordpress/postcss-plugins-preset": "*", + "@wordpress/prettier-config": "*", + "@wordpress/stylelint-config": "*", "adm-zip": "^0.5.9", "babel-jest": "29.7.0", "babel-loader": "9.2.1", diff --git a/packages/server-side-render/.npmrc b/packages/server-side-render/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/server-side-render/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index b91da1f10127b4..a40d4358c35308 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -28,15 +28,15 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/api-fetch": "file:../api-fetch", - "@wordpress/blocks": "file:../blocks", - "@wordpress/components": "file:../components", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/deprecated": "file:../deprecated", - "@wordpress/element": "file:../element", - "@wordpress/i18n": "file:../i18n", - "@wordpress/url": "file:../url", + "@wordpress/api-fetch": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/deprecated": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/url": "*", "fast-deep-equal": "^3.1.3" }, "peerDependencies": { @@ -45,5 +45,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/shortcode/.npmrc b/packages/shortcode/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/shortcode/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index 7b0b965df6d926..c10007806383d9 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -31,5 +31,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/style-engine/.npmrc b/packages/style-engine/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/style-engine/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 670861a7ca8c97..ed6eebf9483d17 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -35,5 +35,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/stylelint-config/.npmrc b/packages/stylelint-config/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/stylelint-config/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/sync/.npmrc b/packages/sync/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/sync/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/sync/package.json b/packages/sync/package.json index 1e79d4673b47dd..27ed67971b7ca9 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -30,7 +30,7 @@ "dependencies": { "@babel/runtime": "7.25.7", "@types/simple-peer": "^9.11.5", - "@wordpress/url": "file:../url", + "@wordpress/url": "*", "import-locals": "^2.0.0", "lib0": "^0.2.42", "simple-peer": "^9.11.0", @@ -41,5 +41,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/token-list/.npmrc b/packages/token-list/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/token-list/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/token-list/package.json b/packages/token-list/package.json index c4fdfde1af6d01..e73fc1918ec55e 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -31,5 +31,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/undo-manager/.npmrc b/packages/undo-manager/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/undo-manager/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 3a7c61dc620ec4..9e31c9c0d6dd7f 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -30,9 +30,10 @@ "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/is-shallow-equal": "file:../is-shallow-equal" + "@wordpress/is-shallow-equal": "*" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/url/.npmrc b/packages/url/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/url/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/url/package.json b/packages/url/package.json index 9631694dc5e2b1..e7228be292bf03 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -33,5 +33,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/viewport/.npmrc b/packages/viewport/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/viewport/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/viewport/package.json b/packages/viewport/package.json index c5e46e4700e96b..916776cdbe98b3 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -27,14 +27,15 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/compose": "file:../compose", - "@wordpress/data": "file:../data", - "@wordpress/element": "file:../element" + "@wordpress/compose": "*", + "@wordpress/data": "*", + "@wordpress/element": "*" }, "peerDependencies": { "react": "^18.0.0" }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/vips/package.json b/packages/vips/package.json index 34d5e3fff3fb18..810b8d2b5c9fc4 100644 --- a/packages/vips/package.json +++ b/packages/vips/package.json @@ -31,5 +31,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/warning/.npmrc b/packages/warning/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/warning/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/warning/package.json b/packages/warning/package.json index 4191f7f1e38a06..d9d4835a220f0a 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -29,5 +29,6 @@ "sideEffects": false, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/widgets/.npmrc b/packages/widgets/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/widgets/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 9fdf32172eb723..d85e06c399b2d9 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -25,17 +25,17 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.25.7", - "@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/notices": "file:../notices", + "@wordpress/api-fetch": "*", + "@wordpress/block-editor": "*", + "@wordpress/blocks": "*", + "@wordpress/components": "*", + "@wordpress/compose": "*", + "@wordpress/core-data": "*", + "@wordpress/data": "*", + "@wordpress/element": "*", + "@wordpress/i18n": "*", + "@wordpress/icons": "*", + "@wordpress/notices": "*", "clsx": "^2.1.1" }, "peerDependencies": { @@ -44,5 +44,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/packages/wordcount/.npmrc b/packages/wordcount/.npmrc deleted file mode 100644 index 43c97e719a5a82..00000000000000 --- a/packages/wordcount/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index 5ad2fd1908d727..f2fa54e449da51 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -31,5 +31,6 @@ }, "publishConfig": { "access": "public" - } + }, + "wpScript": true } diff --git a/tools/webpack/packages.js b/tools/webpack/packages.js index 340d677e358333..1dc396a4d75a15 100644 --- a/tools/webpack/packages.js +++ b/tools/webpack/packages.js @@ -4,6 +4,7 @@ const CopyWebpackPlugin = require( 'copy-webpack-plugin' ); const MomentTimezoneDataPlugin = require( 'moment-timezone-data-webpack-plugin' ); const { join } = require( 'path' ); +const { readdirSync } = require( 'node:fs' ); /** * WordPress dependencies @@ -16,7 +17,12 @@ const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extrac /** * Internal dependencies */ -const { dependencies } = require( '../../package' ); +const packageDirs = readdirSync( + new URL( '../packages', `file://${ __dirname }` ), + { + withFileTypes: true, + } +).flatMap( ( dirent ) => ( dirent.isDirectory() ? [ dirent.name ] : [] ) ); const { baseConfig, plugins, stylesTransform } = require( './shared' ); const WORDPRESS_NAMESPACE = '@wordpress/'; @@ -82,15 +88,23 @@ const bundledPackagesPhpConfig = [ }, } ) ); -const gutenbergPackages = Object.keys( dependencies ) - .filter( - ( packageName ) => - ! BUNDLED_PACKAGES.includes( packageName ) && - packageName.startsWith( WORDPRESS_NAMESPACE ) && - ! packageName.startsWith( WORDPRESS_NAMESPACE + 'react-native' ) && - ! packageName.startsWith( WORDPRESS_NAMESPACE + 'interactivity' ) - ) - .map( ( packageName ) => packageName.replace( WORDPRESS_NAMESPACE, '' ) ); +/** @type {Array<string>} */ +const gutenbergScripts = []; +for ( const packageDir of packageDirs ) { + const packageJson = require( + `${ WORDPRESS_NAMESPACE }${ packageDir }/package.json` + ); + + if ( ! packageJson.wpScript ) { + continue; + } + + if ( BUNDLED_PACKAGES.includes( packageJson.name ) ) { + continue; + } + + gutenbergScripts.push( packageDir ); +} const exportDefaultPackages = [ 'api-fetch', @@ -114,7 +128,7 @@ module.exports = { ...baseConfig, name: 'packages', entry: Object.fromEntries( - gutenbergPackages.map( ( packageName ) => [ + gutenbergScripts.map( ( packageName ) => [ packageName, { import: `./packages/${ packageName }`, @@ -162,7 +176,7 @@ module.exports = { ...plugins, new DependencyExtractionWebpackPlugin( { injectPolyfill: false } ), new CopyWebpackPlugin( { - patterns: gutenbergPackages + patterns: gutenbergScripts .map( ( packageName ) => ( { from: '*.css', context: `./packages/${ packageName }/build-style`, diff --git a/tools/webpack/script-modules.js b/tools/webpack/script-modules.js index 021f11f5f5ed95..aac387ee32957a 100644 --- a/tools/webpack/script-modules.js +++ b/tools/webpack/script-modules.js @@ -2,6 +2,7 @@ * External dependencies */ const { join } = require( 'path' ); +const { readdirSync } = require( 'node:fs' ); /** * WordPress dependencies @@ -14,39 +15,25 @@ const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extrac const { baseConfig, plugins } = require( './shared' ); const WORDPRESS_NAMESPACE = '@wordpress/'; -const { createRequire } = require( 'node:module' ); -const rootURL = new URL( '..', `file://${ __dirname }` ); -const fromRootRequire = createRequire( rootURL ); - -/** @type {Iterable<[string, string]>} */ -const iterableDeps = Object.entries( - fromRootRequire( './package.json' ).dependencies -); +const packageDirs = readdirSync( + new URL( '../packages', `file://${ __dirname }` ), + { + withFileTypes: true, + } +).flatMap( ( dirent ) => ( dirent.isDirectory() ? [ dirent.name ] : [] ) ); /** @type {Map<string, string>} */ const gutenbergScriptModules = new Map(); -for ( const [ packageName, versionSpecifier ] of iterableDeps ) { - if ( - ! packageName.startsWith( WORDPRESS_NAMESPACE ) || - ! versionSpecifier.startsWith( 'file:' ) || - packageName.startsWith( WORDPRESS_NAMESPACE + 'react-native' ) - ) { - continue; - } - - const packageRequire = createRequire( - // Remove the leading "file:" specifier to build a package URL. - new URL( `${ versionSpecifier.substring( 5 ) }/`, rootURL ) - ); +for ( const packageDir of packageDirs ) { + const packageJson = require( `@wordpress/${ packageDir }/package.json` ); - const depPackageJson = packageRequire( './package.json' ); - if ( ! Object.hasOwn( depPackageJson, 'wpScriptModuleExports' ) ) { + if ( ! Object.hasOwn( packageJson, 'wpScriptModuleExports' ) ) { continue; } - const moduleName = packageName.substring( WORDPRESS_NAMESPACE.length ); - let { wpScriptModuleExports } = depPackageJson; + const moduleName = packageJson.name.substring( WORDPRESS_NAMESPACE.length ); + let { wpScriptModuleExports } = packageJson; // Special handling for { "wpScriptModuleExports": "./build-module/index.js" }. if ( typeof wpScriptModuleExports === 'string' ) { @@ -75,7 +62,7 @@ for ( const [ packageName, versionSpecifier ] of iterableDeps ) { gutenbergScriptModules.set( `${ moduleName }/${ name }`, - packageRequire.resolve( exportPath ) + require.resolve( `@wordpress/${ packageDir }/${ exportPath }` ) ); } } From 2dbd0a69be56fb8d11b350d8acf7173607901ef4 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 23 Oct 2024 20:09:52 +0900 Subject: [PATCH 1305/1908] Interface: Use plugin context hook instead of HoC (#66362) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../complementary-area-context/index.js | 12 ------------ .../complementary-area-toggle/index.js | 13 +++++++------ .../src/components/complementary-area/index.js | 17 +++++++++-------- 3 files changed, 16 insertions(+), 26 deletions(-) delete mode 100644 packages/interface/src/components/complementary-area-context/index.js diff --git a/packages/interface/src/components/complementary-area-context/index.js b/packages/interface/src/components/complementary-area-context/index.js deleted file mode 100644 index bdfc6869e1e51d..00000000000000 --- a/packages/interface/src/components/complementary-area-context/index.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * WordPress dependencies - */ -import { withPluginContext } from '@wordpress/plugins'; - -export default withPluginContext( ( context, ownProps ) => { - return { - icon: ownProps.icon || context.icon, - identifier: - ownProps.identifier || `${ context.name }/${ ownProps.name }`, - }; -} ); diff --git a/packages/interface/src/components/complementary-area-toggle/index.js b/packages/interface/src/components/complementary-area-toggle/index.js index 2f8d8dd413674b..40b4dd99be7432 100644 --- a/packages/interface/src/components/complementary-area-toggle/index.js +++ b/packages/interface/src/components/complementary-area-toggle/index.js @@ -3,12 +3,12 @@ */ import { Button } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; +import { usePluginContext } from '@wordpress/plugins'; /** * Internal dependencies */ import { store as interfaceStore } from '../../store'; -import complementaryAreaContext from '../complementary-area-context'; /** * Whether the role supports checked state. @@ -29,17 +29,20 @@ function roleSupportsCheckedState( role ) { ].includes( role ); } -function ComplementaryAreaToggle( { +export default function ComplementaryAreaToggle( { as = Button, scope, - identifier, - icon, + identifier: identifierProp, + icon: iconProp, selectedIcon, name, shortcut, ...props } ) { const ComponentToUse = as; + const context = usePluginContext(); + const icon = iconProp || context.icon; + const identifier = identifierProp || `${ context.name }/${ name }`; const isSelected = useSelect( ( select ) => select( interfaceStore ).getActiveComplementaryArea( scope ) === @@ -70,5 +73,3 @@ function ComplementaryAreaToggle( { /> ); } - -export default complementaryAreaContext( ComplementaryAreaToggle ); diff --git a/packages/interface/src/components/complementary-area/index.js b/packages/interface/src/components/complementary-area/index.js index 84334f6b2659b4..ff4c3eb1469789 100644 --- a/packages/interface/src/components/complementary-area/index.js +++ b/packages/interface/src/components/complementary-area/index.js @@ -25,6 +25,7 @@ import { useViewportMatch, usePrevious, } from '@wordpress/compose'; +import { usePluginContext } from '@wordpress/plugins'; /** * Internal dependencies @@ -32,7 +33,6 @@ import { import ComplementaryAreaHeader from '../complementary-area-header'; import ComplementaryAreaMoreMenuItem from '../complementary-area-more-menu-item'; import ComplementaryAreaToggle from '../complementary-area-toggle'; -import withComplementaryAreaContext from '../complementary-area-context'; import PinnedItems from '../pinned-items'; import { store as interfaceStore } from '../../store'; @@ -171,10 +171,10 @@ function ComplementaryArea( { children, className, closeLabel = __( 'Close plugin' ), - identifier, + identifier: identifierProp, header, headerClassName, - icon, + icon: iconProp, isPinnable = true, panelClassName, scope, @@ -183,6 +183,10 @@ function ComplementaryArea( { toggleShortcut, isActiveByDefault, } ) { + const context = usePluginContext(); + const icon = iconProp || context.icon; + const identifier = identifierProp || `${ context.name }/${ name }`; + // This state is used to delay the rendering of the Fill // until the initial effect runs. // This prevents the animation from running on mount if @@ -344,9 +348,6 @@ function ComplementaryArea( { ); } -const ComplementaryAreaWrapped = - withComplementaryAreaContext( ComplementaryArea ); - -ComplementaryAreaWrapped.Slot = ComplementaryAreaSlot; +ComplementaryArea.Slot = ComplementaryAreaSlot; -export default ComplementaryAreaWrapped; +export default ComplementaryArea; From adcd7d07bbeca0550208d3eb3fae656113a87a3f Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 23 Oct 2024 12:01:56 +0000 Subject: [PATCH 1306/1908] Bump plugin version to 19.5.0 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 34890e269c8763..c1ee01c8415522 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.5.0-rc.1 + * Version: 19.5.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 76bc76d72f33a2..54e428d00e518c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.5.0-rc.1", + "version": "19.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.5.0-rc.1", + "version": "19.5.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "workspaces": [ diff --git a/package.json b/package.json index b5f9b1fb0f09e2..06a73c51cc940d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.5.0-rc.1", + "version": "19.5.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From d9f03d2629445978ebebcb5507d8deb8b3f5b68c Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 23 Oct 2024 12:11:33 +0000 Subject: [PATCH 1307/1908] Update Changelog for 19.5.0 --- changelog.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 77ee60f980c53a..2b10884ae10885 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,6 @@ == Changelog == -= 19.5.0-rc.1 = - += 19.5.0 = ## Changelog @@ -78,6 +77,7 @@ - Allow label override when it is defined in client registration. ([66160](https://github.com/WordPress/gutenberg/pull/66160)) - Bootstrap server sources earlier. ([66058](https://github.com/WordPress/gutenberg/pull/66058)) - Fix: Don't render image when `src` attribute is empty. ([66004](https://github.com/WordPress/gutenberg/pull/66004)) +- Allow the field types matching attribute types in bindings. ([66174](https://github.com/WordPress/gutenberg/pull/66174)) #### Global Styles - Always preview style variations using desktop device type. ([66023](https://github.com/WordPress/gutenberg/pull/66023)) @@ -234,6 +234,8 @@ The following contributors merged PRs in this release: @aaronrobertshaw @afercia @ajlende @akasunil @Aljullu @andrewserong @AnmolVerma404 @ciampo @DaniGuardiola @dhruvang21 @draganescu @getdave @hbhalodia @jameskoster @jasmussen @jeryj @jsnajdr @leemyongpakva @MaggieCabrera @Mamaduka @matiasbenedetto @matt-west @mcsf @mediaformat @michalczaplinski @mikachan @mirka @ndiego @ntsekouras @ramonjd @renatho @richtabor @rmccue @sabernhardt @SantosGuillamot @shail-mehta @sirreal @stokesman @t-hamano @talldan @troychaplin @tyxla @up1512001 @vk17-starlord @Vrishabhsk @westonruter @youknowriad + + = 19.4.0 = ## Changelog From 78b65c50345ac6e2477739c0a835c5c18fee3015 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Wed, 23 Oct 2024 14:34:47 +0200 Subject: [PATCH 1308/1908] Block editor: remove patterns UI stylesheet from iframe (#66306) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- backport-changelog/6.8/7604.md | 1 + lib/client-assets.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backport-changelog/6.8/7604.md b/backport-changelog/6.8/7604.md index 8c7d80994ae605..0ab47698103409 100644 --- a/backport-changelog/6.8/7604.md +++ b/backport-changelog/6.8/7604.md @@ -2,3 +2,4 @@ https://github.com/WordPress/wordpress-develop/pull/7604 * https://github.com/WordPress/gutenberg/pull/66285 * https://github.com/WordPress/gutenberg/pull/66302 +* https://github.com/WordPress/gutenberg/pull/66306 diff --git a/lib/client-assets.php b/lib/client-assets.php index 275c48dfc8e2d1..9cdee4753f43b7 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -320,13 +320,13 @@ function gutenberg_register_packages_styles( $styles ) { ); $styles->add_data( 'wp-format-library', 'rtl', 'replace' ); + // Only add CONTENT styles here that should be enqueued in the iframe! $wp_edit_blocks_dependencies = array( 'wp-components', // This need to be added before the block library styles, // The block library styles override the "reset" styles. 'wp-reset-editor-styles', 'wp-block-library', - 'wp-patterns', // Until #37466, we can't specifically add them as editor styles yet, // so we must hard-code it here as a dependency. 'wp-block-editor-content', From 71bb8b82227757728514f3f64941f52ec53d453c Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 23 Oct 2024 21:41:22 +0900 Subject: [PATCH 1309/1908] Plugins: Deprecate 'withPluginContext' HOC (#66363) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- package-lock.json | 1 + packages/plugins/README.md | 2 ++ packages/plugins/package.json | 1 + packages/plugins/src/components/plugin-context/index.tsx | 7 +++++++ packages/plugins/tsconfig.json | 1 + 5 files changed, 12 insertions(+) diff --git a/package-lock.json b/package-lock.json index 54e428d00e518c..05d08172448664 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54856,6 +54856,7 @@ "@babel/runtime": "7.25.7", "@wordpress/components": "*", "@wordpress/compose": "*", + "@wordpress/deprecated": "*", "@wordpress/element": "*", "@wordpress/hooks": "*", "@wordpress/icons": "*", diff --git a/packages/plugins/README.md b/packages/plugins/README.md index bbf70fed553d32..ac2434e51442f4 100644 --- a/packages/plugins/README.md +++ b/packages/plugins/README.md @@ -192,6 +192,8 @@ _Returns_ #### withPluginContext +> **Deprecated** 6.8.0 Use `usePluginContext` hook instead. + A Higher Order Component used to inject Plugin context to the wrapped component. _Parameters_ diff --git a/packages/plugins/package.json b/packages/plugins/package.json index a2ce790e0935e5..75f0bc554b868c 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -30,6 +30,7 @@ "@babel/runtime": "7.25.7", "@wordpress/components": "*", "@wordpress/compose": "*", + "@wordpress/deprecated": "*", "@wordpress/element": "*", "@wordpress/hooks": "*", "@wordpress/icons": "*", diff --git a/packages/plugins/src/components/plugin-context/index.tsx b/packages/plugins/src/components/plugin-context/index.tsx index c2e6f8eaa232d8..3e2d687229011c 100644 --- a/packages/plugins/src/components/plugin-context/index.tsx +++ b/packages/plugins/src/components/plugin-context/index.tsx @@ -3,6 +3,7 @@ */ import { createContext, useContext } from '@wordpress/element'; import { createHigherOrderComponent } from '@wordpress/compose'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies @@ -34,6 +35,8 @@ export function usePluginContext() { * A Higher Order Component used to inject Plugin context to the * wrapped component. * + * @deprecated 6.8.0 Use `usePluginContext` hook instead. + * * @param mapContextToProps Function called on every context change, * expected to return object of props to * merge with the component's own props. @@ -47,6 +50,10 @@ export const withPluginContext = ( ) => T & PluginContext ) => createHigherOrderComponent( ( OriginalComponent ) => { + deprecated( 'wp.plugins.withPluginContext', { + since: '6.8.0', + alternative: 'wp.plugins.usePluginContext', + } ); return ( props ) => ( <Context.Consumer> { ( context ) => ( diff --git a/packages/plugins/tsconfig.json b/packages/plugins/tsconfig.json index 9a0da807348b21..47c626f9ddedc8 100644 --- a/packages/plugins/tsconfig.json +++ b/packages/plugins/tsconfig.json @@ -9,6 +9,7 @@ "references": [ { "path": "../components" }, { "path": "../compose" }, + { "path": "../deprecated" }, { "path": "../element" }, { "path": "../hooks" }, { "path": "../icons" }, From 77f62e01590d7ee235b61631a5502bff07237305 Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Wed, 23 Oct 2024 15:46:06 +0200 Subject: [PATCH 1310/1908] QuickEdit: Add Featured Image Control (#64496) Co-authored-by: gigitux <gigitux@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- package-lock.json | 3 + packages/base-styles/_z-index.scss | 3 + .../core-data/src/entity-types/attachment.ts | 36 +++++- packages/dataviews/src/types.ts | 8 +- packages/edit-site/package.json | 1 + .../src/components/post-edit/index.js | 10 +- .../src/components/post-fields/index.js | 55 +------- .../src/components/post-fields/style.scss | 3 + .../sidebar-dataviews/default-views.js | 7 +- packages/edit-site/src/style.scss | 2 + packages/fields/README.md | 4 + packages/fields/package.json | 2 + .../featured-image/featured-image-edit.tsx | 122 ++++++++++++++++++ .../featured-image/featured-image-view.tsx | 38 ++++++ .../fields/src/fields/featured-image/index.ts | 24 ++++ .../src/fields/featured-image/style.scss | 95 ++++++++++++++ packages/fields/src/fields/index.ts | 1 + packages/fields/tsconfig.json | 4 +- 18 files changed, 355 insertions(+), 63 deletions(-) create mode 100644 packages/edit-site/src/components/post-fields/style.scss create mode 100644 packages/fields/src/fields/featured-image/featured-image-edit.tsx create mode 100644 packages/fields/src/fields/featured-image/featured-image-view.tsx create mode 100644 packages/fields/src/fields/featured-image/index.ts create mode 100644 packages/fields/src/fields/featured-image/style.scss diff --git a/package-lock.json b/package-lock.json index 05d08172448664..a1060b1267af50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54065,6 +54065,7 @@ "@wordpress/editor": "*", "@wordpress/element": "*", "@wordpress/escape-html": "*", + "@wordpress/fields": "*", "@wordpress/hooks": "*", "@wordpress/html-entities": "*", "@wordpress/i18n": "*", @@ -54457,10 +54458,12 @@ "@wordpress/html-entities": "*", "@wordpress/i18n": "*", "@wordpress/icons": "*", + "@wordpress/media-utils": "*", "@wordpress/notices": "*", "@wordpress/patterns": "*", "@wordpress/primitives": "*", "@wordpress/private-apis": "*", + "@wordpress/router": "*", "@wordpress/url": "*", "@wordpress/warning": "*", "change-case": "4.1.2", diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index 77238c6f386084..7bb71732546053 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -206,6 +206,9 @@ $z-layers: ( // Ensure footer stays above the preview field. ".dataviews-footer": 2, + + // Needs to be below media library (.media-model) that has a z-index of 160000. + ".components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown": 160000 - 10, ); @function z-index( $key ) { diff --git a/packages/core-data/src/entity-types/attachment.ts b/packages/core-data/src/entity-types/attachment.ts index 703a08611c0e2b..3d4e6814e29cf6 100644 --- a/packages/core-data/src/entity-types/attachment.ts +++ b/packages/core-data/src/entity-types/attachment.ts @@ -14,6 +14,40 @@ import type { import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records'; +interface MediaDetails { + width: number; + height: number; + file: string; + filesize: number; + sizes: { [ key: string ]: Size }; + image_meta: ImageMeta; + original_image?: string; +} +interface ImageMeta { + aperture: string; + credit: string; + camera: string; + caption: string; + created_timestamp: string; + copyright: string; + focal_length: string; + iso: string; + shutter_speed: string; + title: string; + orientation: string; + keywords: any[]; +} + +interface Size { + file: string; + width: number; + height: number; + filesize?: number; + mime_type: string; + source_url: string; + uncropped?: boolean; +} + declare module './base-entity-records' { export namespace BaseEntityRecords { export interface Attachment< C extends Context > { @@ -124,7 +158,7 @@ declare module './base-entity-records' { /** * Details about the media file, specific to its type. */ - media_details: Record< string, string >; + media_details: MediaDetails; /** * The ID for the associated post of the attachment. */ diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index bc44b57eaaecc6..2a335dce3af32b 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -106,7 +106,7 @@ export type Field< Item > = { /** * Callback used to render the field. Defaults to `field.getValue`. */ - render?: ComponentType< { item: Item } >; + render?: ComponentType< DataViewRenderFieldProps< Item > >; /** * Callback used to render an edit control for the field. @@ -159,7 +159,7 @@ export type NormalizedField< Item > = Field< Item > & { label: string; header: string | ReactElement; getValue: ( args: { item: Item } ) => any; - render: ComponentType< { item: Item } >; + render: ComponentType< DataViewRenderFieldProps< Item > >; Edit: ComponentType< DataFormControlProps< Item > >; sort: ( a: Item, b: Item, direction: SortDirection ) => number; isValid: ( item: Item, context?: ValidationContext ) => boolean; @@ -181,6 +181,10 @@ export type DataFormControlProps< Item > = { hideLabelFromVision?: boolean; }; +export type DataViewRenderFieldProps< Item > = { + item: Item; +}; + /** * The filters applied to the dataset. */ diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 83cae4a7100bc7..f85a9e26a9d689 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -48,6 +48,7 @@ "@wordpress/editor": "*", "@wordpress/element": "*", "@wordpress/escape-html": "*", + "@wordpress/fields": "*", "@wordpress/hooks": "*", "@wordpress/html-entities": "*", "@wordpress/i18n": "*", diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 8d7e09c702047e..a1523142fb6691 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -60,14 +60,20 @@ function PostEditForm( { postType, postId } ) { ); const form = { type: 'panel', - fields: [ 'title', 'status', 'date', 'author', 'comment_status' ], + fields: [ + 'featured_media', + 'title', + 'author', + 'date', + 'comment_status', + ], }; const onChange = ( edits ) => { for ( const id of ids ) { if ( edits.status && edits.status !== 'future' && - record.status === 'future' && + record?.status === 'future' && new Date( record.date ) > new Date() ) { edits.date = null; diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 9e59b23d61922d..c40b86c8026536 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -8,6 +8,7 @@ import clsx from 'clsx'; */ import { __, sprintf } from '@wordpress/i18n'; import { decodeEntities } from '@wordpress/html-entities'; +import { featuredImageField } from '@wordpress/fields'; import { createInterpolateElement, useMemo, @@ -33,11 +34,9 @@ import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; import { LAYOUT_GRID, LAYOUT_TABLE, - LAYOUT_LIST, OPERATOR_IS_ANY, } from '../../utils/constants'; -import { default as Link, useLink } from '../routes/link'; -import Media from '../media'; +import { default as Link } from '../routes/link'; // See https://github.com/WordPress/gutenberg/issues/55886 // We do not support custom statutes at the moment. @@ -81,46 +80,6 @@ const getFormattedDate = ( dateToDisplay ) => getDate( dateToDisplay ) ); -function FeaturedImage( { item, viewType } ) { - const isDisabled = item.status === 'trash'; - const { onClick } = useLink( { - postId: item.id, - postType: item.type, - canvas: 'edit', - } ); - const hasMedia = !! item.featured_media; - const size = - viewType === LAYOUT_GRID - ? [ 'large', 'full', 'medium', 'thumbnail' ] - : [ 'thumbnail', 'medium', 'large', 'full' ]; - const media = hasMedia ? ( - <Media - className="edit-site-post-list__featured-image" - id={ item.featured_media } - size={ size } - /> - ) : null; - const renderButton = viewType !== LAYOUT_LIST && ! isDisabled; - return ( - <div - className={ `edit-site-post-list__featured-image-wrapper is-layout-${ viewType }` } - > - { renderButton ? ( - <button - className="edit-site-post-list__featured-image-button" - type="button" - onClick={ onClick } - aria-label={ item.title?.rendered || __( '(no title)' ) } - > - { media } - </button> - ) : ( - media - ) } - </div> - ); -} - function PostStatusField( { item } ) { const status = STATUSES.find( ( { value } ) => value === item.status ); const label = status?.label || item.status; @@ -190,15 +149,7 @@ function usePostFields( viewType ) { const fields = useMemo( () => [ - { - id: 'featured-image', - label: __( 'Featured Image' ), - getValue: ( { item } ) => item.featured_media, - render: ( { item } ) => ( - <FeaturedImage item={ item } viewType={ viewType } /> - ), - enableSorting: false, - }, + featuredImageField, { label: __( 'Title' ), id: 'title', diff --git a/packages/edit-site/src/components/post-fields/style.scss b/packages/edit-site/src/components/post-fields/style.scss new file mode 100644 index 00000000000000..adeaf9a2678253 --- /dev/null +++ b/packages/edit-site/src/components/post-fields/style.scss @@ -0,0 +1,3 @@ +.components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown { + z-index: z-index(".components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown"); +} diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 658fa319e9c667..72f4c94fe6bcdd 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -31,9 +31,6 @@ export const defaultLayouts = { layout: { primaryField: 'title', styles: { - 'featured-image': { - width: '1%', - }, title: { maxWidth: 300, }, @@ -42,14 +39,14 @@ export const defaultLayouts = { }, [ LAYOUT_GRID ]: { layout: { - mediaField: 'featured-image', + mediaField: 'featured_media', primaryField: 'title', }, }, [ LAYOUT_LIST ]: { layout: { primaryField: 'title', - mediaField: 'featured-image', + mediaField: 'featured_media', }, }, }; diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 4e9e1071e3a77a..1668a940fb28fa 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -1,4 +1,5 @@ @import "../../dataviews/src/style.scss"; +@import "../../fields/src/fields/featured-image/style.scss"; @import "./components/add-new-template/style.scss"; @import "./components/block-editor/style.scss"; @@ -30,6 +31,7 @@ @import "./components/editor-canvas-container/style.scss"; @import "./components/post-edit/style.scss"; @import "./components/post-list/style.scss"; +@import "./components/post-fields/style.scss"; @import "./components/resizable-frame/style.scss"; @import "./hooks/push-changes-to-global-styles/style.scss"; @import "./components/global-styles/font-library-modal/style.scss"; diff --git a/packages/fields/README.md b/packages/fields/README.md index b4e45103600da6..fdcedac3032dbd 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -38,6 +38,10 @@ Undocumented declaration. Undocumented declaration. +### featuredImageField + +Undocumented declaration. + ### orderField Undocumented declaration. diff --git a/packages/fields/package.json b/packages/fields/package.json index 019ec99ed7a8ed..43772cb41981a5 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -45,10 +45,12 @@ "@wordpress/html-entities": "*", "@wordpress/i18n": "*", "@wordpress/icons": "*", + "@wordpress/media-utils": "*", "@wordpress/notices": "*", "@wordpress/patterns": "*", "@wordpress/primitives": "*", "@wordpress/private-apis": "*", + "@wordpress/router": "*", "@wordpress/url": "*", "@wordpress/warning": "*", "change-case": "4.1.2", diff --git a/packages/fields/src/fields/featured-image/featured-image-edit.tsx b/packages/fields/src/fields/featured-image/featured-image-edit.tsx new file mode 100644 index 00000000000000..b0dc612cdcfa50 --- /dev/null +++ b/packages/fields/src/fields/featured-image/featured-image-edit.tsx @@ -0,0 +1,122 @@ +/** + * WordPress dependencies + */ +import { Button, __experimentalGrid as Grid } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; +import { useCallback, useRef } from '@wordpress/element'; +// @ts-ignore +import { MediaUpload } from '@wordpress/media-utils'; +import { lineSolid } from '@wordpress/icons'; +import { store as coreStore } from '@wordpress/core-data'; +import type { DataFormControlProps } from '@wordpress/dataviews'; +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import { __ } from '@wordpress/i18n'; + +export const FeaturedImageEdit = ( { + data, + field, + onChange, +}: DataFormControlProps< BasePost > ) => { + const { id } = field; + + const value = field.getValue( { item: data } ); + + const media = useSelect( + ( select ) => { + const { getEntityRecord } = select( coreStore ); + return getEntityRecord( 'root', 'media', value ); + }, + [ value ] + ); + + const onChangeControl = useCallback( + ( newValue: number ) => + onChange( { + [ id ]: newValue, + } ), + [ id, onChange ] + ); + + const url = media?.source_url; + const title = media?.title?.rendered; + const ref = useRef( null ); + + return ( + <fieldset className="fields-controls__featured-image"> + <div className="fields-controls__featured-image-container"> + <MediaUpload + onSelect={ ( selectedMedia: { id: number } ) => { + onChangeControl( selectedMedia.id ); + } } + allowedTypes={ [ 'image' ] } + render={ ( { open }: { open: () => void } ) => { + return ( + <div + ref={ ref } + role="button" + tabIndex={ -1 } + onClick={ () => { + open(); + } } + onKeyDown={ open } + > + <Grid + rowGap={ 0 } + columnGap={ 8 } + templateColumns="24px 1fr 24px" + > + { url && ( + <> + <img + className="fields-controls__featured-image-image" + alt="" + width={ 24 } + height={ 24 } + src={ url } + /> + <span className="fields-controls__featured-image-title"> + { title } + </span> + </> + ) } + { ! url && ( + <> + <span + className="fields-controls__featured-image-placeholder" + style={ { + width: '24px', + height: '24px', + } } + /> + <span className="fields-controls__featured-image-title"> + { __( 'Choose an image…' ) } + </span> + </> + ) } + { url && ( + <> + <Button + size="small" + className="fields-controls__featured-image-remove-button" + icon={ lineSolid } + onClick={ ( + event: React.MouseEvent< HTMLButtonElement > + ) => { + event.stopPropagation(); + onChangeControl( 0 ); + } } + /> + </> + ) } + </Grid> + </div> + ); + } } + /> + </div> + </fieldset> + ); +}; diff --git a/packages/fields/src/fields/featured-image/featured-image-view.tsx b/packages/fields/src/fields/featured-image/featured-image-view.tsx new file mode 100644 index 00000000000000..36793e6f2ff9ab --- /dev/null +++ b/packages/fields/src/fields/featured-image/featured-image-view.tsx @@ -0,0 +1,38 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import type { DataViewRenderFieldProps } from '@wordpress/dataviews'; + +export const FeaturedImageView = ( { + item, +}: DataViewRenderFieldProps< BasePost > ) => { + const mediaId = item.featured_media; + + const media = useSelect( + ( select ) => { + const { getEntityRecord } = select( coreStore ); + return mediaId ? getEntityRecord( 'root', 'media', mediaId ) : null; + }, + [ mediaId ] + ); + const url = media?.source_url; + + if ( url ) { + return ( + <img + className="fields-controls__featured-image-image" + src={ url } + alt="" + /> + ); + } + + return <span className="fields-controls__featured-image-placeholder" />; +}; diff --git a/packages/fields/src/fields/featured-image/index.ts b/packages/fields/src/fields/featured-image/index.ts new file mode 100644 index 00000000000000..44f9a1b4064648 --- /dev/null +++ b/packages/fields/src/fields/featured-image/index.ts @@ -0,0 +1,24 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import { __ } from '@wordpress/i18n'; +import { FeaturedImageEdit } from './featured-image-edit'; +import { FeaturedImageView } from './featured-image-view'; + +const featuredImageField: Field< BasePost > = { + id: 'featured_media', + type: 'text', + label: __( 'Featured Image' ), + getValue: ( { item } ) => item.featured_media, + Edit: FeaturedImageEdit, + render: FeaturedImageView, + enableSorting: false, +}; + +export default featuredImageField; diff --git a/packages/fields/src/fields/featured-image/style.scss b/packages/fields/src/fields/featured-image/style.scss new file mode 100644 index 00000000000000..46d37960199ead --- /dev/null +++ b/packages/fields/src/fields/featured-image/style.scss @@ -0,0 +1,95 @@ +.fields-controls__featured-image-placeholder { + border-radius: $radius-small; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); + display: inline-block; + padding: 0; + background: + $white + linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%); +} + +.fields-controls__featured-image-title { + width: 100%; + color: $gray-900; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +.fields-controls__featured-image-image { + width: 100%; + height: 100%; + border-radius: $radius-small; + align-self: center; +} + +.fields-controls__featured-image-container { + .fields-controls__featured-image-placeholder { + margin: 0; + } + + span { + margin-right: auto; + } +} + +fieldset.fields-controls__featured-image { + .fields-controls__featured-image-container { + border: $border-width solid $gray-300; + border-radius: $radius-small; + padding: 8px 12px; + cursor: pointer; + &:hover { + background-color: $gray-100; + } + } + + .fields-controls__featured-image-placeholder { + width: 24px; + height: 24px; + } + + span { + align-self: center; + text-align: start; + white-space: nowrap; + } + + .fields-controls__featured-image-upload-button { + padding: 0; + height: fit-content; + &:hover, + &:focus { + border: 0; + color: unset; + } + } + + .fields-controls__featured-image-remove-button { + place-self: end; + } +} + +.dataforms-layouts-panel__field-control { + .fields-controls__featured-image-image { + width: 16px; + height: 16px; + } + + .fields-controls__featured-image-placeholder { + width: 16px; + height: 16px; + } +} + +.dataviews-view-table__cell-content-wrapper { + .fields-controls__featured-image-image { + width: 32px; + height: 32px; + } + + .fields-controls__featured-image-placeholder { + width: 32px; + height: 32px; + } +} diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts index 63ff87842fa4c9..62a1e1485e75e8 100644 --- a/packages/fields/src/fields/index.ts +++ b/packages/fields/src/fields/index.ts @@ -1,2 +1,3 @@ export { default as titleField } from './title'; export { default as orderField } from './order'; +export { default as featuredImageField } from './featured-image'; diff --git a/packages/fields/tsconfig.json b/packages/fields/tsconfig.json index 69dbd076d05747..c553ee023993d0 100644 --- a/packages/fields/tsconfig.json +++ b/packages/fields/tsconfig.json @@ -23,7 +23,9 @@ { "path": "../blob" }, { "path": "../core-data" }, { "path": "../hooks" }, - { "path": "../html-entities" } + { "path": "../html-entities" }, + { "path": "../media-utils" }, + { "path": "../router" } ], "include": [ "src" ] } From 609d573625be035953f3782efdc0589f617b4b78 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Wed, 23 Oct 2024 16:57:54 +0300 Subject: [PATCH 1311/1908] Footnotes: Remove extra callback when parsing content (#66370) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> --- .../core-data/src/hooks/use-entity-block-editor.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/packages/core-data/src/hooks/use-entity-block-editor.js b/packages/core-data/src/hooks/use-entity-block-editor.js index 56238097618e1f..df213898659e7d 100644 --- a/packages/core-data/src/hooks/use-entity-block-editor.js +++ b/packages/core-data/src/hooks/use-entity-block-editor.js @@ -91,11 +91,6 @@ export default function useEntityBlockEditor( kind, name, { id: _id } = {} ) { getEntityRecordEdits, ] ); - const updateFootnotes = useCallback( - ( _blocks ) => updateFootnotesFromMeta( _blocks, meta ), - [ meta ] - ); - const onChange = useCallback( ( newBlocks, options ) => { const noChange = blocks === newBlocks; @@ -111,7 +106,7 @@ export default function useEntityBlockEditor( kind, name, { id: _id } = {} ) { selection, content: ( { blocks: blocksForSerialization = [] } ) => __unstableSerializeAndClean( blocksForSerialization ), - ...updateFootnotes( newBlocks ), + ...updateFootnotesFromMeta( newBlocks, meta ), }; editEntityRecord( kind, name, id, edits, { @@ -124,7 +119,7 @@ export default function useEntityBlockEditor( kind, name, { id: _id } = {} ) { name, id, blocks, - updateFootnotes, + meta, __unstableCreateUndoLevel, editEntityRecord, ] @@ -133,7 +128,7 @@ export default function useEntityBlockEditor( kind, name, { id: _id } = {} ) { const onInput = useCallback( ( newBlocks, options ) => { const { selection, ...rest } = options; - const footnotesChanges = updateFootnotes( newBlocks ); + const footnotesChanges = updateFootnotesFromMeta( newBlocks, meta ); const edits = { selection, ...footnotesChanges }; editEntityRecord( kind, name, id, edits, { @@ -141,7 +136,7 @@ export default function useEntityBlockEditor( kind, name, { id: _id } = {} ) { ...rest, } ); }, - [ kind, name, id, updateFootnotes, editEntityRecord ] + [ kind, name, id, meta, editEntityRecord ] ); return [ blocks, onInput, onChange ]; From 1ca8001abebb048c221e4c48ccef1bc681d3b77f Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Wed, 23 Oct 2024 18:26:20 +0200 Subject: [PATCH 1312/1908] QuickEdit: Add slug field control (#65196) Co-authored-by: gigitux <gigitux@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../src/components/post-edit/index.js | 21 ++- .../src/components/post-fields/index.js | 3 +- packages/edit-site/src/style.scss | 1 + packages/fields/README.md | 4 + packages/fields/src/fields/index.ts | 1 + packages/fields/src/fields/slug/index.ts | 23 +++ packages/fields/src/fields/slug/slug-edit.tsx | 156 ++++++++++++++++++ packages/fields/src/fields/slug/slug-view.tsx | 26 +++ packages/fields/src/fields/slug/style.scss | 22 +++ packages/fields/src/styles.scss | 1 + packages/fields/src/types.ts | 2 + 11 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 packages/fields/src/fields/slug/index.ts create mode 100644 packages/fields/src/fields/slug/slug-edit.tsx create mode 100644 packages/fields/src/fields/slug/slug-view.tsx create mode 100644 packages/fields/src/fields/slug/style.scss create mode 100644 packages/fields/src/styles.scss diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index a1523142fb6691..b9d3f60ef5da2b 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -65,9 +65,19 @@ function PostEditForm( { postType, postId } ) { 'title', 'author', 'date', + 'slug', 'comment_status', ], }; + + const fieldsWithBulkEditSupport = [ + 'title', + 'status', + 'date', + 'author', + 'comment_status', + ]; + const onChange = ( edits ) => { for ( const id of ids ) { if ( @@ -106,7 +116,16 @@ function PostEditForm( { postType, postId } ) { <DataForm data={ ids.length === 1 ? record : multiEdits } fields={ fields } - form={ form } + form={ + ids.length === 1 + ? form + : { + ...form, + fields: form.fields.filter( ( field ) => + fieldsWithBulkEditSupport.includes( field ) + ), + } + } onChange={ onChange } /> </VStack> diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index c40b86c8026536..b5748684e8a19e 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -8,7 +8,7 @@ import clsx from 'clsx'; */ import { __, sprintf } from '@wordpress/i18n'; import { decodeEntities } from '@wordpress/html-entities'; -import { featuredImageField } from '@wordpress/fields'; +import { featuredImageField, slugField } from '@wordpress/fields'; import { createInterpolateElement, useMemo, @@ -320,6 +320,7 @@ function usePostFields( viewType ) { return <time>{ getFormattedDate( item.date ) }</time>; }, }, + slugField, { id: 'comment_status', label: __( 'Discussion' ), diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 1668a940fb28fa..b2f5c826046b79 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -1,4 +1,5 @@ @import "../../dataviews/src/style.scss"; +@import "../../fields/src/styles.scss"; @import "../../fields/src/fields/featured-image/style.scss"; @import "./components/add-new-template/style.scss"; diff --git a/packages/fields/README.md b/packages/fields/README.md index fdcedac3032dbd..0a891f9b07420c 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -70,6 +70,10 @@ Undocumented declaration. Undocumented declaration. +### slugField + +Undocumented declaration. + ### titleField Undocumented declaration. diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts index 62a1e1485e75e8..24655a3d866cfd 100644 --- a/packages/fields/src/fields/index.ts +++ b/packages/fields/src/fields/index.ts @@ -1,3 +1,4 @@ +export { default as slugField } from './slug'; export { default as titleField } from './title'; export { default as orderField } from './order'; export { default as featuredImageField } from './featured-image'; diff --git a/packages/fields/src/fields/slug/index.ts b/packages/fields/src/fields/slug/index.ts new file mode 100644 index 00000000000000..4e81996ceaa6e8 --- /dev/null +++ b/packages/fields/src/fields/slug/index.ts @@ -0,0 +1,23 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import { __ } from '@wordpress/i18n'; +import SlugEdit from './slug-edit'; +import SlugView from './slug-view'; + +const slugField: Field< BasePost > = { + id: 'slug', + type: 'text', + label: __( 'Slug' ), + getValue: ( { item } ) => item.slug, + Edit: SlugEdit, + render: SlugView, +}; + +export default slugField; diff --git a/packages/fields/src/fields/slug/slug-edit.tsx b/packages/fields/src/fields/slug/slug-edit.tsx new file mode 100644 index 00000000000000..760e67c9cff3bf --- /dev/null +++ b/packages/fields/src/fields/slug/slug-edit.tsx @@ -0,0 +1,156 @@ +/** + * WordPress dependencies + */ +import { + Button, + ExternalLink, + __experimentalInputControl as InputControl, + __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper, + __experimentalVStack as VStack, +} from '@wordpress/components'; +import { copySmall } from '@wordpress/icons'; +import { useCopyToClipboard, useInstanceId } from '@wordpress/compose'; +import { useDispatch } from '@wordpress/data'; +import { useCallback, useEffect, useRef } from '@wordpress/element'; +import { store as noticesStore } from '@wordpress/notices'; +import { safeDecodeURIComponent } from '@wordpress/url'; +import type { DataFormControlProps } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; + +const SlugEdit = ( { + field, + onChange, + data, +}: DataFormControlProps< BasePost > ) => { + const { id } = field; + + const slug = field.getValue( { item: data } ) ?? ''; + const permalinkTemplate = data.permalink_template || ''; + const PERMALINK_POSTNAME_REGEX = /%(?:postname|pagename)%/; + const [ prefix, suffix ] = permalinkTemplate.split( + PERMALINK_POSTNAME_REGEX + ); + const permalinkPrefix = prefix; + const permalinkSuffix = suffix; + const isEditable = PERMALINK_POSTNAME_REGEX.test( permalinkTemplate ); + const originalSlug = useRef( slug ); + const slugToDisplay = slug || originalSlug.current; + const permalink = isEditable + ? `${ permalinkPrefix }${ slugToDisplay }${ permalinkSuffix }` + : safeDecodeURIComponent( data.link || '' ); + + useEffect( () => { + if ( slug && originalSlug.current === undefined ) { + originalSlug.current = slug; + } + }, [ slug ] ); + + const onChangeControl = useCallback( + ( newValue?: string ) => + onChange( { + [ id ]: newValue, + } ), + [ id, onChange ] + ); + + const { createNotice } = useDispatch( noticesStore ); + + const copyButtonRef = useCopyToClipboard( permalink, () => { + createNotice( 'info', __( 'Copied Permalink to clipboard.' ), { + isDismissible: true, + type: 'snackbar', + } ); + } ); + + const postUrlSlugDescriptionId = + 'editor-post-url__slug-description-' + useInstanceId( SlugEdit ); + + return ( + <fieldset className="fields-controls__slug"> + { isEditable && ( + <VStack> + <VStack spacing="0px"> + <span> + { __( + 'Customize the last part of the Permalink.' + ) } + </span> + <ExternalLink href="https://wordpress.org/documentation/article/page-post-settings-sidebar/#permalink"> + { __( 'Learn more' ) } + </ExternalLink> + </VStack> + <InputControl + __next40pxDefaultSize + prefix={ + <InputControlPrefixWrapper> + / + </InputControlPrefixWrapper> + } + suffix={ + <Button + __next40pxDefaultSize + icon={ copySmall } + ref={ copyButtonRef } + label={ __( 'Copy' ) } + /> + } + label={ __( 'Link' ) } + hideLabelFromVision + value={ slug } + autoComplete="off" + spellCheck="false" + type="text" + className="fields-controls__slug-input" + onChange={ ( newValue?: string ) => { + onChangeControl( newValue ); + } } + onBlur={ () => { + if ( slug === '' ) { + onChangeControl( originalSlug.current ); + } + } } + aria-describedby={ postUrlSlugDescriptionId } + help={ + <> + <p className="fields-controls__slug-help"> + <span className="fields-controls__slug-help-visual-label"> + { __( 'Permalink:' ) } + </span> + <ExternalLink + className="fields-controls__slug-help-link" + href={ permalink } + > + <span className="fields-controls__slug-help-prefix"> + { permalinkPrefix } + </span> + <span className="fields-controls__slug-help-slug"> + { slugToDisplay } + </span> + <span className="fields-controls__slug-help-suffix"> + { permalinkSuffix } + </span> + </ExternalLink> + </p> + </> + } + /> + </VStack> + ) } + { ! isEditable && ( + <ExternalLink + className="fields-controls__slug-help" + href={ permalink } + > + { permalink } + </ExternalLink> + ) } + </fieldset> + ); +}; + +export default SlugEdit; diff --git a/packages/fields/src/fields/slug/slug-view.tsx b/packages/fields/src/fields/slug/slug-view.tsx new file mode 100644 index 00000000000000..7448673c6a8464 --- /dev/null +++ b/packages/fields/src/fields/slug/slug-view.tsx @@ -0,0 +1,26 @@ +/** + * WordPress dependencies + */ +import { useEffect, useRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; + +const SlugView = ( { item }: { item: BasePost } ) => { + const slug = item.slug; + const originalSlug = useRef( slug ); + + useEffect( () => { + if ( slug && originalSlug.current === undefined ) { + originalSlug.current = slug; + } + }, [ slug ] ); + + const slugToDisplay = slug || originalSlug.current; + + return `/${ slugToDisplay ?? '' }`; +}; + +export default SlugView; diff --git a/packages/fields/src/fields/slug/style.scss b/packages/fields/src/fields/slug/style.scss new file mode 100644 index 00000000000000..aad99b3731e9eb --- /dev/null +++ b/packages/fields/src/fields/slug/style.scss @@ -0,0 +1,22 @@ +.fields-controls__slug { + .fields-controls__slug-external-icon { + margin-left: 5ch; + } + + .fields-controls__slug-input input.components-input-control__input { + padding-inline-start: 0 !important; + } + + .fields-controls__slug-help-link { + word-break: break-word; + } + + .fields-controls__slug-help { + display: flex; + flex-direction: column; + + .fields-controls__slug-help-slug { + font-weight: 600; + } + } +} diff --git a/packages/fields/src/styles.scss b/packages/fields/src/styles.scss new file mode 100644 index 00000000000000..cdb130337f1cd9 --- /dev/null +++ b/packages/fields/src/styles.scss @@ -0,0 +1 @@ +@import "./fields/slug/style.scss"; diff --git a/packages/fields/src/types.ts b/packages/fields/src/types.ts index a5ed9596b07dfd..d895195cb40af7 100644 --- a/packages/fields/src/types.ts +++ b/packages/fields/src/types.ts @@ -35,6 +35,8 @@ export interface BasePost extends CommonPost { menu_order?: number; ping_status?: 'open' | 'closed'; link?: string; + slug?: string; + permalink_template?: string; } export interface Template extends CommonPost { From a775b7cbc23efae79965c612ad4b8cc0c2dc472d Mon Sep 17 00:00:00 2001 From: Pooja Bhimani <82029773+poojabhimani12@users.noreply.github.com> Date: Wed, 23 Oct 2024 12:31:16 -0400 Subject: [PATCH 1313/1908] Add Inline comment experimental flag (#60622) Co-authored-by: MD-sunilprajapati <spmultidots@git.wordpress.org> Co-authored-by: poojabhimani12 <poojabhimani@git.wordpress.org> Co-authored-by: rishishah-multidots <rishishah@git.wordpress.org> Co-authored-by: ingeniumed <ingeniumed@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- backport-changelog/6.8/7488.md | 3 + backport-changelog/6.8/7498.md | 3 + lib/compat/wordpress-6.8/block-comments.php | 70 +++ ...-gutenberg-rest-comment-controller-6-8.php | 135 ++++++ lib/experimental/editor-settings.php | 3 + lib/experiments-page.php | 12 + lib/load.php | 4 + .../block-settings-dropdown.js | 4 + .../components/block-settings-menu/index.js | 3 + .../collab/block-comment-icon-slot.js | 12 + .../collab/block-comment-icon-toolbar-slot.js | 12 + packages/block-editor/src/private-apis.js | 5 +- .../components/collab-sidebar/add-comment.js | 124 ++++++ .../collab-sidebar/comment-button-toolbar.js | 29 ++ .../collab-sidebar/comment-button.js | 31 ++ .../src/components/collab-sidebar/comments.js | 404 ++++++++++++++++++ .../components/collab-sidebar/constants.js | 1 + .../src/components/collab-sidebar/index.js | 299 +++++++++++++ .../src/components/collab-sidebar/style.scss | 111 +++++ .../src/components/collab-sidebar/utils.js | 9 + .../editor/src/components/header/index.js | 2 + packages/editor/src/style.scss | 1 + 22 files changed, 1276 insertions(+), 1 deletion(-) create mode 100644 backport-changelog/6.8/7488.md create mode 100644 backport-changelog/6.8/7498.md create mode 100644 lib/compat/wordpress-6.8/block-comments.php create mode 100644 lib/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php create mode 100644 packages/block-editor/src/components/collab/block-comment-icon-slot.js create mode 100644 packages/block-editor/src/components/collab/block-comment-icon-toolbar-slot.js create mode 100644 packages/editor/src/components/collab-sidebar/add-comment.js create mode 100644 packages/editor/src/components/collab-sidebar/comment-button-toolbar.js create mode 100644 packages/editor/src/components/collab-sidebar/comment-button.js create mode 100644 packages/editor/src/components/collab-sidebar/comments.js create mode 100644 packages/editor/src/components/collab-sidebar/constants.js create mode 100644 packages/editor/src/components/collab-sidebar/index.js create mode 100644 packages/editor/src/components/collab-sidebar/style.scss create mode 100644 packages/editor/src/components/collab-sidebar/utils.js diff --git a/backport-changelog/6.8/7488.md b/backport-changelog/6.8/7488.md new file mode 100644 index 00000000000000..a588bef0e01796 --- /dev/null +++ b/backport-changelog/6.8/7488.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7488 + +* https://github.com/WordPress/gutenberg/pull/60622 \ No newline at end of file diff --git a/backport-changelog/6.8/7498.md b/backport-changelog/6.8/7498.md new file mode 100644 index 00000000000000..6c903246166b64 --- /dev/null +++ b/backport-changelog/6.8/7498.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7498 + +* https://github.com/WordPress/gutenberg/pull/60622 \ No newline at end of file diff --git a/lib/compat/wordpress-6.8/block-comments.php b/lib/compat/wordpress-6.8/block-comments.php new file mode 100644 index 00000000000000..ff9f03b69aa1c3 --- /dev/null +++ b/lib/compat/wordpress-6.8/block-comments.php @@ -0,0 +1,70 @@ +<?php +/** + * Updates the comment type in the REST API for WordPress version 6.7. + * + * This function is used as a filter callback for the 'rest_pre_insert_comment' hook. + * It checks if the 'comment_type' parameter is set to 'block_comment' in the REST API request, + * and if so, updates the 'comment_type' and 'comment_approved' properties of the prepared comment. + * + * @param array $prepared_comment The prepared comment data. + * @param WP_REST_Request $request The REST API request object. + * @return array The updated prepared comment data. + */ +if ( ! function_exists( 'update_comment_type_in_rest_api_6_8' ) && gutenberg_is_experiment_enabled( 'gutenberg-block-comment' ) ) { + function update_comment_type_in_rest_api_6_8( $prepared_comment, $request ) { + if ( ! empty( $request['comment_type'] ) && 'block_comment' === $request['comment_type'] ) { + $prepared_comment['comment_type'] = $request['comment_type']; + $prepared_comment['comment_approved'] = $request['comment_approved']; + } + + return $prepared_comment; + } + add_filter( 'rest_pre_insert_comment', 'update_comment_type_in_rest_api_6_8', 10, 2 ); +} + +/** + * Updates the comment type for avatars in the WordPress REST API. + * + * This function adds the 'block_comment' type to the list of comment types + * for which avatars should be retrieved in the WordPress REST API. + * + * @param array $comment_type The array of comment types. + * @return array The updated array of comment types. + */ +if ( ! function_exists( 'update_get_avatar_comment_type' ) && gutenberg_is_experiment_enabled( 'gutenberg-block-comment' ) ) { + function update_get_avatar_comment_type( $comment_type ) { + $comment_type[] = 'block_comment'; + return $comment_type; + } + add_filter( 'get_avatar_comment_types', 'update_get_avatar_comment_type' ); +} + +/** + * Excludes block comments from the admin comments query. + * + * This function modifies the comments query to exclude comments of type 'block_comment' + * when the query is for comments in the WordPress admin. + * + * @param WP_Comment_Query $query The current comments query. + * + * @return void + */ +if ( ! function_exists( 'exclude_block_comments_from_admin' ) && gutenberg_is_experiment_enabled( 'gutenberg-block-comment' ) ) { + function exclude_block_comments_from_admin( $query ) { + // Only modify the query if it's for comments + if ( isset( $query->query_vars['type'] ) && '' === $query->query_vars['type'] ) { + $query->set( 'type', '' ); + + add_filter( + 'comments_clauses', + function ( $clauses ) { + global $wpdb; + // Exclude comments of type 'block_comment' + $clauses['where'] .= " AND {$wpdb->comments}.comment_type != 'block_comment'"; + return $clauses; + } + ); + } + } + add_action( 'pre_get_comments', 'exclude_block_comments_from_admin' ); +} diff --git a/lib/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php b/lib/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php new file mode 100644 index 00000000000000..981b9dbd840319 --- /dev/null +++ b/lib/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php @@ -0,0 +1,135 @@ +<?php +/** + * A custom REST server for Gutenberg. + * + * @package gutenberg + * @since 6.8.0 + */ + +// Create a new class that extends WP_REST_Comments_Controller +class Gutenberg_REST_Comment_Controller_6_8 extends WP_REST_Comments_Controller { + + public function create_item_permissions_check( $request ) { + if ( ! is_user_logged_in() ) { + if ( get_option( 'comment_registration' ) ) { + return new WP_Error( + 'rest_comment_login_required', + __( 'Sorry, you must be logged in to comment.' ), + array( 'status' => 401 ) + ); + } + + /** + * Filters whether comments can be created via the REST API without authentication. + * + * Enables creating comments for anonymous users. + * + * @since 4.7.0 + * + * @param bool $allow_anonymous Whether to allow anonymous comments to + * be created. Default `false`. + * @param WP_REST_Request $request Request used to generate the + * response. + */ + $allow_anonymous = apply_filters( 'rest_allow_anonymous_comments', false, $request ); + + if ( ! $allow_anonymous ) { + return new WP_Error( + 'rest_comment_login_required', + __( 'Sorry, you must be logged in to comment.' ), + array( 'status' => 401 ) + ); + } + } + + // Limit who can set comment `author`, `author_ip` or `status` to anything other than the default. + if ( isset( $request['author'] ) && get_current_user_id() !== $request['author'] && ! current_user_can( 'moderate_comments' ) ) { + return new WP_Error( + 'rest_comment_invalid_author', + /* translators: %s: Request parameter. */ + sprintf( __( "Sorry, you are not allowed to edit '%s' for comments." ), 'author' ), + array( 'status' => rest_authorization_required_code() ) + ); + } + + if ( isset( $request['author_ip'] ) && ! current_user_can( 'moderate_comments' ) ) { + if ( empty( $_SERVER['REMOTE_ADDR'] ) || $request['author_ip'] !== $_SERVER['REMOTE_ADDR'] ) { + return new WP_Error( + 'rest_comment_invalid_author_ip', + /* translators: %s: Request parameter. */ + sprintf( __( "Sorry, you are not allowed to edit '%s' for comments." ), 'author_ip' ), + array( 'status' => rest_authorization_required_code() ) + ); + } + } + + if ( isset( $request['status'] ) && ! current_user_can( 'moderate_comments' ) ) { + return new WP_Error( + 'rest_comment_invalid_status', + /* translators: %s: Request parameter. */ + sprintf( __( "Sorry, you are not allowed to edit '%s' for comments." ), 'status' ), + array( 'status' => rest_authorization_required_code() ) + ); + } + + if ( empty( $request['post'] ) ) { + return new WP_Error( + 'rest_comment_invalid_post_id', + __( 'Sorry, you are not allowed to create this comment without a post.' ), + array( 'status' => 403 ) + ); + } + + $post = get_post( (int) $request['post'] ); + + if ( ! $post ) { + return new WP_Error( + 'rest_comment_invalid_post_id', + __( 'Sorry, you are not allowed to create this comment without a post.' ), + array( 'status' => 403 ) + ); + } + + if ( 'draft' === $post->post_status && 'comment' === $request['comment_type'] ) { + return new WP_Error( + 'rest_comment_draft_post', + __( 'Sorry, you are not allowed to create a comment on this post.' ), + array( 'status' => 403 ) + ); + } + + if ( 'trash' === $post->post_status ) { + return new WP_Error( + 'rest_comment_trash_post', + __( 'Sorry, you are not allowed to create a comment on this post.' ), + array( 'status' => 403 ) + ); + } + + if ( ! $this->check_read_post_permission( $post, $request ) ) { + return new WP_Error( + 'rest_cannot_read_post', + __( 'Sorry, you are not allowed to read the post for this comment.' ), + array( 'status' => rest_authorization_required_code() ) + ); + } + + if ( ! comments_open( $post->ID ) && 'comment' === $request['comment_type'] ) { + return new WP_Error( + 'rest_comment_closed', + __( 'Sorry, comments are closed for this item.' ), + array( 'status' => 403 ) + ); + } + + return true; + } +} + +add_action( + 'rest_api_init', + function () { + $controller = new Gutenberg_REST_Comment_Controller_6_8(); + $controller->register_routes(); + } +); diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index 126382f85a513e..afc6d7e220f676 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -28,6 +28,9 @@ function gutenberg_enable_experiments() { if ( gutenberg_is_experiment_enabled( 'gutenberg-full-page-client-side-navigation' ) ) { wp_add_inline_script( 'wp-block-library', 'window.__experimentalFullPageClientSideNavigation = true', 'before' ); } + if ( $gutenberg_experiments && array_key_exists( 'gutenberg-block-comment', $gutenberg_experiments ) ) { + wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableBlockComment = true', 'before' ); + } if ( $gutenberg_experiments && array_key_exists( 'gutenberg-quick-edit-dataviews', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalQuickEditDataViews = true', 'before' ); } diff --git a/lib/experiments-page.php b/lib/experiments-page.php index 27a54b920f4d52..946b68283a3e0b 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -163,6 +163,18 @@ function gutenberg_initialize_experiments_settings() { ) ); + add_settings_field( + 'gutenberg-block-comment', + __( 'Block Comments', 'gutenberg' ), + 'gutenberg_display_experiment_field', + 'gutenberg-experiments', + 'gutenberg_experiments_section', + array( + 'label' => __( 'Enable multi-user commenting on blocks', 'gutenberg' ), + 'id' => 'gutenberg-block-comment', + ) + ); + add_settings_field( 'gutenberg-media-processing', __( 'Client-side media processing', 'gutenberg' ), diff --git a/lib/load.php b/lib/load.php index c26160eba2b67d..2c8a0fd0347c92 100644 --- a/lib/load.php +++ b/lib/load.php @@ -46,6 +46,10 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.7/class-gutenberg-rest-server.php'; require __DIR__ . '/compat/wordpress-6.7/rest-api.php'; + // WordPress 6.8 compat. + require __DIR__ . '/compat/wordpress-6.8/block-comments.php'; + require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php'; + // Plugin specific code. require_once __DIR__ . '/class-wp-rest-global-styles-controller-gutenberg.php'; require_once __DIR__ . '/class-wp-rest-edit-site-export-controller-gutenberg.php'; diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index ac2b99ac2bb620..5b5360cc48a8fe 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -19,6 +19,7 @@ import { pipe, useCopyToClipboard } from '@wordpress/compose'; * Internal dependencies */ import BlockActions from '../block-actions'; +import __unstableCommentIconFill from '../../components/collab/block-comment-icon-slot'; import BlockHTMLConvertButton from './block-html-convert-button'; import __unstableBlockSettingsMenuFirstItem from './block-settings-menu-first-item'; import BlockSettingsMenuControls from '../block-settings-menu-controls'; @@ -294,6 +295,9 @@ export function BlockSettingsDropdown( { </MenuItem> </> ) } + <__unstableCommentIconFill.Slot + fillProps={ { onClose } } + /> </MenuGroup> { canCopyStyles && ! isContentOnly && ( <MenuGroup> diff --git a/packages/block-editor/src/components/block-settings-menu/index.js b/packages/block-editor/src/components/block-settings-menu/index.js index 0b0b1a775e736f..50e8abe09d018b 100644 --- a/packages/block-editor/src/components/block-settings-menu/index.js +++ b/packages/block-editor/src/components/block-settings-menu/index.js @@ -7,10 +7,13 @@ import { ToolbarGroup, ToolbarItem } from '@wordpress/components'; * Internal dependencies */ import BlockSettingsDropdown from './block-settings-dropdown'; +import __unstableCommentIconToolbarFill from '../../components/collab/block-comment-icon-toolbar-slot'; export function BlockSettingsMenu( { clientIds, ...props } ) { return ( <ToolbarGroup> + <__unstableCommentIconToolbarFill.Slot /> + <ToolbarItem> { ( toggleProps ) => ( <BlockSettingsDropdown diff --git a/packages/block-editor/src/components/collab/block-comment-icon-slot.js b/packages/block-editor/src/components/collab/block-comment-icon-slot.js new file mode 100644 index 00000000000000..600db904b28741 --- /dev/null +++ b/packages/block-editor/src/components/collab/block-comment-icon-slot.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { createSlotFill } from '@wordpress/components'; + +const { Fill: __unstableCommentIconFill, Slot } = createSlotFill( + '__unstableCommentIconFill' +); + +__unstableCommentIconFill.Slot = Slot; + +export default __unstableCommentIconFill; diff --git a/packages/block-editor/src/components/collab/block-comment-icon-toolbar-slot.js b/packages/block-editor/src/components/collab/block-comment-icon-toolbar-slot.js new file mode 100644 index 00000000000000..dd84b284f082ae --- /dev/null +++ b/packages/block-editor/src/components/collab/block-comment-icon-toolbar-slot.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { createSlotFill } from '@wordpress/components'; + +const { Fill: __unstableCommentIconToolbarFill, Slot } = createSlotFill( + '__unstableCommentIconToolbarFill' +); + +__unstableCommentIconToolbarFill.Slot = Slot; + +export default __unstableCommentIconToolbarFill; diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 7205bef5798ec1..386d5fad49bc62 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -47,7 +47,8 @@ import { PrivatePublishDateTimePicker } from './components/publish-date-time-pic import useSpacingSizes from './components/spacing-sizes-control/hooks/use-spacing-sizes'; import useBlockDisplayTitle from './components/block-title/use-block-display-title'; import TabbedSidebar from './components/tabbed-sidebar'; - +import __unstableCommentIconFill from './components/collab/block-comment-icon-slot'; +import __unstableCommentIconToolbarFill from './components/collab/block-comment-icon-toolbar-slot'; /** * Private @wordpress/block-editor APIs. */ @@ -92,4 +93,6 @@ lock( privateApis, { __unstableBlockStyleVariationOverridesWithConfig, setBackgroundStyleDefaults, sectionRootClientIdKey, + __unstableCommentIconFill, + __unstableCommentIconToolbarFill, } ); diff --git a/packages/editor/src/components/collab-sidebar/add-comment.js b/packages/editor/src/components/collab-sidebar/add-comment.js new file mode 100644 index 00000000000000..191bb23477f7bd --- /dev/null +++ b/packages/editor/src/components/collab-sidebar/add-comment.js @@ -0,0 +1,124 @@ +/** + * WordPress dependencies + */ +import { __, _x } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { useState, useEffect } from '@wordpress/element'; +import { + __experimentalHStack as HStack, + __experimentalVStack as VStack, + Button, + TextControl, +} from '@wordpress/components'; +import { store as blockEditorStore } from '@wordpress/block-editor'; +import { store as coreStore } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ +import { sanitizeCommentString } from './utils'; + +/** + * Renders the UI for adding a comment in the Gutenberg editor's collaboration sidebar. + * + * @param {Object} props - The component props. + * @param {Function} props.onSubmit - A callback function to be called when the user submits a comment. + * @param {boolean} props.showCommentBoard - The function to edit the comment. + * @param {Function} props.setShowCommentBoard - The function to delete the comment. + * @return {JSX.Element} The rendered comment input UI. + */ +export function AddComment( { + onSubmit, + showCommentBoard, + setShowCommentBoard, +} ) { + // State to manage the comment thread. + const [ inputComment, setInputComment ] = useState( '' ); + + const { + defaultAvatar, + clientId, + blockCommentId, + showAddCommentBoard, + currentUser, + } = useSelect( ( select ) => { + const { getSettings } = select( blockEditorStore ); + const { __experimentalDiscussionSettings } = getSettings(); + const selectedBlock = select( blockEditorStore ).getSelectedBlock(); + const userData = select( coreStore ).getCurrentUser(); + return { + defaultAvatar: __experimentalDiscussionSettings?.avatarURL, + clientId: selectedBlock?.clientId, + blockCommentId: selectedBlock?.attributes?.blockCommentId, + showAddCommentBoard: showCommentBoard, + currentUser: userData, + }; + } ); + + const userAvatar = + currentUser && currentUser.avatar_urls && currentUser.avatar_urls[ 48 ] + ? currentUser.avatar_urls[ 48 ] + : defaultAvatar; + + useEffect( () => { + setInputComment( '' ); + }, [ clientId ] ); + + const handleCancel = () => { + setShowCommentBoard( false ); + setInputComment( '' ); + }; + + if ( ! showAddCommentBoard || ! clientId || undefined !== blockCommentId ) { + return null; + } + + return ( + <VStack + spacing="3" + className="editor-collab-sidebar-panel__thread editor-collab-sidebar-panel__active-thread" + > + <HStack alignment="left" spacing="3"> + <img + src={ userAvatar } + // translators: alt text for user avatar image + alt={ __( 'User Avatar' ) } + className="editor-collab-sidebar-panel__user-avatar" + width={ 32 } + height={ 32 } + /> + <span className="editor-collab-sidebar-panel__user-name"> + { currentUser?.name ?? '' } + </span> + </HStack> + <TextControl + __next40pxDefaultSize + __nextHasNoMarginBottom + value={ inputComment } + onChange={ setInputComment } + placeholder={ _x( 'Comment', 'noun' ) } + /> + <HStack alignment="right" spacing="3"> + <Button + __next40pxDefaultSize + variant="tertiary" + text={ _x( 'Cancel', 'Cancel comment button' ) } + onClick={ handleCancel } + /> + <Button + __next40pxDefaultSize + accessibleWhenDisabled + variant="primary" + text={ _x( 'Comment', 'Add comment button' ) } + disabled={ + 0 === sanitizeCommentString( inputComment ).length + } + onClick={ () => { + onSubmit( inputComment ); + setInputComment( '' ); + } } + /> + </HStack> + </VStack> + ); +} diff --git a/packages/editor/src/components/collab-sidebar/comment-button-toolbar.js b/packages/editor/src/components/collab-sidebar/comment-button-toolbar.js new file mode 100644 index 00000000000000..2e378a7eaabab0 --- /dev/null +++ b/packages/editor/src/components/collab-sidebar/comment-button-toolbar.js @@ -0,0 +1,29 @@ +/** + * WordPress dependencies + */ +import { ToolbarButton } from '@wordpress/components'; +import { _x } from '@wordpress/i18n'; +import { comment as commentIcon } from '@wordpress/icons'; +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; + +const { __unstableCommentIconToolbarFill } = unlock( blockEditorPrivateApis ); + +const AddCommentToolbarButton = ( { onClick } ) => { + return ( + <__unstableCommentIconToolbarFill> + <ToolbarButton + accessibleWhenDisabled + icon={ commentIcon } + label={ _x( 'Comment', 'View comment' ) } + onClick={ onClick } + /> + </__unstableCommentIconToolbarFill> + ); +}; + +export default AddCommentToolbarButton; diff --git a/packages/editor/src/components/collab-sidebar/comment-button.js b/packages/editor/src/components/collab-sidebar/comment-button.js new file mode 100644 index 00000000000000..3b020661816660 --- /dev/null +++ b/packages/editor/src/components/collab-sidebar/comment-button.js @@ -0,0 +1,31 @@ +/** + * WordPress dependencies + */ +import { MenuItem } from '@wordpress/components'; +import { _x } from '@wordpress/i18n'; +import { comment as commentIcon } from '@wordpress/icons'; + +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; + +const { __unstableCommentIconFill } = unlock( blockEditorPrivateApis ); + +const AddCommentButton = ( { onClick } ) => { + return ( + <__unstableCommentIconFill> + <MenuItem + icon={ commentIcon } + onClick={ onClick } + aria-haspopup="dialog" + > + { _x( 'Comment', 'Add comment button' ) } + </MenuItem> + </__unstableCommentIconFill> + ); +}; + +export default AddCommentButton; diff --git a/packages/editor/src/components/collab-sidebar/comments.js b/packages/editor/src/components/collab-sidebar/comments.js new file mode 100644 index 00000000000000..c0b4bd3d4dc38a --- /dev/null +++ b/packages/editor/src/components/collab-sidebar/comments.js @@ -0,0 +1,404 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ +import { useState, RawHTML } from '@wordpress/element'; +import { + __experimentalHStack as HStack, + __experimentalVStack as VStack, + __experimentalConfirmDialog as ConfirmDialog, + Button, + DropdownMenu, + TextareaControl, + Tooltip, +} from '@wordpress/components'; +import { + dateI18n, + format, + getSettings as getDateSettings, +} from '@wordpress/date'; +import { Icon, check, published, moreVertical } from '@wordpress/icons'; +import { __, _x } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { useEntityProp } from '@wordpress/core-data'; +import { store as blockEditorStore } from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ +import { sanitizeCommentString } from './utils'; + +/** + * Renders the Comments component. + * + * @param {Object} props - The component props. + * @param {Array} props.threads - The array of comment threads. + * @param {Function} props.onEditComment - The function to handle comment editing. + * @param {Function} props.onAddReply - The function to add a reply to a comment. + * @param {Function} props.onCommentDelete - The function to delete a comment. + * @param {Function} props.onCommentResolve - The function to mark a comment as resolved. + * @return {JSX.Element} The rendered Comments component. + */ +export function Comments( { + threads, + onEditComment, + onAddReply, + onCommentDelete, + onCommentResolve, +} ) { + const [ actionState, setActionState ] = useState( false ); + const [ isConfirmDialogOpen, setIsConfirmDialogOpen ] = useState( false ); + + const handleConfirmDelete = () => { + onCommentDelete( actionState.id ); + setActionState( false ); + setIsConfirmDialogOpen( false ); + }; + + const handleConfirmResolve = () => { + onCommentResolve( actionState.id ); + setActionState( false ); + setIsConfirmDialogOpen( false ); + }; + + const handleCancelDelete = () => { + setActionState( false ); + setIsConfirmDialogOpen( false ); + }; + + const blockCommentId = useSelect( ( select ) => { + const clientID = select( blockEditorStore ).getSelectedBlockClientId(); + return ( + select( blockEditorStore ).getBlock( clientID )?.attributes + ?.blockCommentId ?? false + ); + }, [] ); + + const CommentBoard = ( { thread, parentThread } ) => { + return ( + <> + <CommentHeader + thread={ thread } + onResolve={ () => { + setActionState( { + action: 'resolve', + id: parentThread?.id ?? thread.id, + } ); + setIsConfirmDialogOpen( true ); + } } + onEdit={ () => + setActionState( { action: 'edit', id: thread.id } ) + } + onDelete={ () => { + setActionState( { action: 'delete', id: thread.id } ); + setIsConfirmDialogOpen( true ); + } } + onReply={ + ! parentThread + ? () => + setActionState( { + action: 'reply', + id: thread.id, + } ) + : undefined + } + status={ parentThread?.status ?? thread.status } + /> + <HStack + alignment="left" + spacing="3" + justify="flex-start" + className="editor-collab-sidebar-panel__user-comment" + > + <VStack + spacing="3" + className="editor-collab-sidebar-panel__comment-field" + > + { 'edit' === actionState?.action && + thread.id === actionState?.id && ( + <CommentForm + onSubmit={ ( value ) => { + onEditComment( thread.id, value ); + setActionState( false ); + } } + onCancel={ () => setActionState( false ) } + thread={ thread } + /> + ) } + { ( ! actionState || + 'edit' !== actionState?.action ) && ( + <RawHTML>{ thread?.content?.raw }</RawHTML> + ) } + </VStack> + </HStack> + { 'resolve' === actionState?.action && + thread.id === actionState?.id && ( + <ConfirmDialog + isOpen={ isConfirmDialogOpen } + onConfirm={ handleConfirmResolve } + onCancel={ handleCancelDelete } + confirmButtonText="Yes" + cancelButtonText="No" + > + { + // translators: message displayed when confirming an action + __( + 'Are you sure you want to mark this comment as resolved?' + ) + } + </ConfirmDialog> + ) } + { 'delete' === actionState?.action && + thread.id === actionState?.id && ( + <ConfirmDialog + isOpen={ isConfirmDialogOpen } + onConfirm={ handleConfirmDelete } + onCancel={ handleCancelDelete } + confirmButtonText="Yes" + cancelButtonText="No" + > + { + // translators: message displayed when confirming an action + __( + 'Are you sure you want to delete this comment?' + ) + } + </ConfirmDialog> + ) } + </> + ); + }; + + return ( + <> + { + // If there are no comments, show a message indicating no comments are available. + ( ! Array.isArray( threads ) || threads.length === 0 ) && ( + <VStack + alignment="left" + className="editor-collab-sidebar-panel__thread" + justify="flex-start" + spacing="3" + > + { + // translators: message displayed when there are no comments available + __( 'No comments available' ) + } + </VStack> + ) + } + + { Array.isArray( threads ) && + threads.length > 0 && + threads.map( ( thread ) => ( + <VStack + key={ thread.id } + className={ clsx( + 'editor-collab-sidebar-panel__thread', + { + 'editor-collab-sidebar-panel__active-thread': + blockCommentId && + blockCommentId === thread.id, + } + ) } + id={ thread.id } + spacing="3" + > + <CommentBoard thread={ thread } /> + { 'reply' === actionState?.action && + thread.id === actionState?.id && ( + <HStack + alignment="left" + spacing="3" + justify="flex-start" + className="editor-collab-sidebar-panel__user-comment" + > + <VStack + spacing="3" + className="editor-collab-sidebar-panel__comment-field" + > + <CommentForm + onSubmit={ ( inputComment ) => { + onAddReply( + inputComment, + thread.id + ); + setActionState( false ); + } } + onCancel={ () => + setActionState( false ) + } + /> + </VStack> + </HStack> + ) } + { 0 < thread?.reply?.length && + thread.reply.map( ( reply ) => ( + <VStack + key={ reply.id } + className="editor-collab-sidebar-panel__child-thread" + id={ reply.id } + spacing="2" + > + <CommentBoard + thread={ reply } + parentThread={ thread } + /> + </VStack> + ) ) } + </VStack> + ) ) } + </> + ); +} + +/** + * EditComment component. + * + * @param {Object} props - The component props. + * @param {Function} props.onSubmit - The function to call when updating the comment. + * @param {Function} props.onCancel - The function to call when canceling the comment update. + * @param {Object} props.thread - The comment thread object. + * @return {JSX.Element} The CommentForm component. + */ +function CommentForm( { onSubmit, onCancel, thread } ) { + const [ inputComment, setInputComment ] = useState( + thread?.content?.raw ?? '' + ); + + return ( + <> + <TextareaControl + __nextHasNoMarginBottom + value={ inputComment ?? '' } + onChange={ setInputComment } + /> + <VStack alignment="left" spacing="3" justify="flex-start"> + <HStack alignment="left" spacing="3" justify="flex-start"> + <Button + __next40pxDefaultSize + accessibleWhenDisabled + variant="primary" + onClick={ () => onSubmit( inputComment ) } + disabled={ + 0 === sanitizeCommentString( inputComment ).length + } + > + { thread + ? _x( 'Update', 'verb' ) + : _x( 'Reply', 'Add reply comment' ) } + </Button> + <Button __next40pxDefaultSize onClick={ onCancel }> + { _x( 'Cancel', 'Cancel comment edit' ) } + </Button> + </HStack> + </VStack> + </> + ); +} + +/** + * Renders the header of a comment in the collaboration sidebar. + * + * @param {Object} props - The component props. + * @param {Object} props.thread - The comment thread object. + * @param {Function} props.onResolve - The function to resolve the comment. + * @param {Function} props.onEdit - The function to edit the comment. + * @param {Function} props.onDelete - The function to delete the comment. + * @param {Function} props.onReply - The function to reply to the comment. + * @param {string} props.status - The status of the comment. + * @return {JSX.Element} The rendered comment header. + */ +function CommentHeader( { + thread, + onResolve, + onEdit, + onDelete, + onReply, + status, +} ) { + const dateSettings = getDateSettings(); + const [ dateTimeFormat = dateSettings.formats.time ] = useEntityProp( + 'root', + 'site', + 'time_format' + ); + + const actions = [ + { + title: _x( 'Edit', 'Edit comment' ), + onClick: onEdit, + }, + { + title: _x( 'Delete', 'Delete comment' ), + onClick: onDelete, + }, + { + title: _x( 'Reply', 'Reply on a comment' ), + onClick: onReply, + }, + ]; + + const moreActions = actions.filter( ( item ) => item.onClick ); + + return ( + <HStack alignment="left" spacing="3" justify="flex-start"> + <img + src={ thread?.author_avatar_urls?.[ 48 ] } + className="editor-collab-sidebar-panel__user-avatar" + // translators: alt text for user avatar image + alt={ __( 'User avatar' ) } + width={ 32 } + height={ 32 } + /> + <VStack spacing="0"> + <span className="editor-collab-sidebar-panel__user-name"> + { thread.author_name } + </span> + <time + dateTime={ format( 'h:i A', thread.date ) } + className="editor-collab-sidebar-panel__user-time" + > + { dateI18n( dateTimeFormat, thread.date ) } + </time> + </VStack> + <span className="editor-collab-sidebar-panel__comment-status"> + { status !== 'approved' && ( + <HStack alignment="right" justify="flex-end" spacing="0"> + { 0 === thread.parent && onResolve && ( + <Button + label={ _x( + 'Resolve', + 'Mark comment as resolved' + ) } + __next40pxDefaultSize + icon={ published } + onClick={ onResolve } + showTooltip + /> + ) } + <DropdownMenu + icon={ moreVertical } + label={ _x( + 'Select an action', + 'Select comment action' + ) } + className="editor-collab-sidebar-panel__comment-dropdown-menu" + controls={ moreActions } + /> + </HStack> + ) } + { status === 'approved' && ( + // translators: tooltip for resolved comment + <Tooltip text={ __( 'Resolved' ) }> + <Icon icon={ check } /> + </Tooltip> + ) } + </span> + </HStack> + ); +} diff --git a/packages/editor/src/components/collab-sidebar/constants.js b/packages/editor/src/components/collab-sidebar/constants.js new file mode 100644 index 00000000000000..748c2afc26374d --- /dev/null +++ b/packages/editor/src/components/collab-sidebar/constants.js @@ -0,0 +1 @@ +export const collabSidebarName = 'edit-post/collab-sidebar'; diff --git a/packages/editor/src/components/collab-sidebar/index.js b/packages/editor/src/components/collab-sidebar/index.js new file mode 100644 index 00000000000000..482bf3d4081ed1 --- /dev/null +++ b/packages/editor/src/components/collab-sidebar/index.js @@ -0,0 +1,299 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { useSelect, useDispatch, resolveSelect } from '@wordpress/data'; +import { useState, useEffect, useMemo } from '@wordpress/element'; +import { comment as commentIcon } from '@wordpress/icons'; +import { addFilter } from '@wordpress/hooks'; +import { store as noticesStore } from '@wordpress/notices'; +import { store as coreStore } from '@wordpress/core-data'; +import { store as blockEditorStore } from '@wordpress/block-editor'; +import { store as interfaceStore } from '@wordpress/interface'; + +/** + * Internal dependencies + */ +import PluginSidebar from '../plugin-sidebar'; +import { collabSidebarName } from './constants'; +import { Comments } from './comments'; +import { AddComment } from './add-comment'; +import { store as editorStore } from '../../store'; +import AddCommentButton from './comment-button'; +import AddCommentToolbarButton from './comment-button-toolbar'; + +const threadsEmptyArray = []; + +const isBlockCommentExperimentEnabled = + window?.__experimentalEnableBlockComment; +const modifyBlockCommentAttributes = ( settings ) => { + if ( ! settings.attributes.blockCommentId ) { + settings.attributes = { + ...settings.attributes, + blockCommentId: { + type: 'number', + }, + }; + } + + return settings; +}; + +// Apply the filter to all core blocks +addFilter( + 'blocks.registerBlockType', + 'block-comment/modify-core-block-attributes', + modifyBlockCommentAttributes +); + +/** + * Renders the Collab sidebar. + */ +export default function CollabSidebar() { + const { createNotice } = useDispatch( noticesStore ); + const { saveEntityRecord, deleteEntityRecord } = useDispatch( coreStore ); + const { getEntityRecord } = resolveSelect( coreStore ); + const { enableComplementaryArea } = useDispatch( interfaceStore ); + const [ blockCommentID, setBlockCommentID ] = useState( null ); + const [ showCommentBoard, setShowCommentBoard ] = useState( false ); + const { postId } = useSelect( ( select ) => { + return { + postId: select( editorStore ).getCurrentPostId(), + }; + }, [] ); + + const threads = useSelect( + ( select ) => { + if ( ! postId ) { + return threadsEmptyArray; + } + const { getEntityRecords } = select( coreStore ); + const data = getEntityRecords( 'root', 'comment', { + post: postId, + type: 'block_comment', + status: 'any', + per_page: 100, + } ); + return data || threadsEmptyArray; + }, + [ postId ] + ); + + const clientId = useSelect( ( select ) => { + const { getSelectedBlockClientId } = select( blockEditorStore ); + return getSelectedBlockClientId(); + }, [] ); + + const blockDetails = useSelect( + ( select ) => { + return clientId + ? select( blockEditorStore ).getBlock( clientId ) + : null; + }, + [ clientId ] + ); + + // Get the dispatch functions to save the comment and update the block attributes. + const { updateBlockAttributes } = useDispatch( blockEditorStore ); + + // Process comments to build the tree structure + const resultComments = useMemo( () => { + // Create a compare to store the references to all objects by id + const compare = {}; + const result = []; + + const filteredComments = threads.filter( + ( comment ) => comment.status !== 'trash' + ); + + // Initialize each object with an empty `reply` array + filteredComments.forEach( ( item ) => { + compare[ item.id ] = { ...item, reply: [] }; + } ); + + // Iterate over the data to build the tree structure + filteredComments.forEach( ( item ) => { + if ( item.parent === 0 ) { + // If parent is 0, it's a root item, push it to the result array + result.push( compare[ item.id ] ); + } else if ( compare[ item.parent ] ) { + // Otherwise, find its parent and push it to the parent's `reply` array + compare[ item.parent ].reply.push( compare[ item.id ] ); + } + } ); + + return result; + }, [ threads ] ); + + const openCollabBoard = () => { + setShowCommentBoard( true ); + enableComplementaryArea( 'core', 'edit-post/collab-sidebar' ); + }; + + // Function to save the comment. + const addNewComment = async ( comment, parentCommentId ) => { + const args = { + post: postId, + content: comment, + comment_type: 'block_comment', + comment_approved: 0, + }; + + // Create a new object, conditionally including the parent property + const updatedArgs = { + ...args, + ...( parentCommentId ? { parent: parentCommentId } : {} ), + }; + + const savedRecord = await saveEntityRecord( + 'root', + 'comment', + updatedArgs + ); + + if ( savedRecord ) { + // If it's a main comment, update the block attributes with the comment id. + if ( ! parentCommentId ) { + updateBlockAttributes( clientId, { + blockCommentId: savedRecord?.id, + } ); + } + + createNotice( + 'snackbar', + parentCommentId + ? // translators: Reply added successfully + __( 'Reply added successfully.' ) + : // translators: Comment added successfully + __( 'Comment added successfully.' ), + { + type: 'snackbar', + isDismissible: true, + } + ); + } else { + onError(); + } + }; + + const onCommentResolve = async ( commentId ) => { + const savedRecord = await saveEntityRecord( 'root', 'comment', { + id: commentId, + status: 'approved', + } ); + + if ( savedRecord ) { + // translators: Comment resolved successfully + createNotice( 'snackbar', __( 'Comment marked as resolved.' ), { + type: 'snackbar', + isDismissible: true, + } ); + } else { + onError(); + } + }; + + const onEditComment = async ( commentId, comment ) => { + const savedRecord = await saveEntityRecord( 'root', 'comment', { + id: commentId, + content: comment, + } ); + + if ( savedRecord ) { + createNotice( + 'snackbar', + // translators: Comment edited successfully + __( 'Comment edited successfully.' ), + { + type: 'snackbar', + isDismissible: true, + } + ); + } else { + onError(); + } + }; + + const onError = () => { + createNotice( + 'error', + // translators: Error message when comment submission fails + __( + 'Something went wrong. Please try publishing the post, or you may have already submitted your comment earlier.' + ), + { + isDismissible: true, + } + ); + }; + + const onCommentDelete = async ( commentId ) => { + const childComment = await getEntityRecord( + 'root', + 'comment', + commentId + ); + await deleteEntityRecord( 'root', 'comment', commentId ); + + if ( childComment && ! childComment.parent ) { + updateBlockAttributes( clientId, { + blockCommentId: undefined, + } ); + } + + createNotice( + 'snackbar', + // translators: Comment deleted successfully + __( 'Comment deleted successfully.' ), + { + type: 'snackbar', + isDismissible: true, + } + ); + }; + + useEffect( () => { + if ( blockDetails ) { + setBlockCommentID( blockDetails?.attributes.blockCommentId ); + } + }, [ postId, clientId ] ); + + // Check if the experimental flag is enabled. + if ( ! isBlockCommentExperimentEnabled ) { + return null; // or maybe return some message indicating no threads are available. + } + + return ( + <> + { ! blockCommentID && ( + <AddCommentButton onClick={ openCollabBoard } /> + ) } + + { blockCommentID > 0 && ( + <AddCommentToolbarButton onClick={ openCollabBoard } /> + ) } + <PluginSidebar + identifier={ collabSidebarName } + // translators: Comments sidebar title + title={ __( 'Comments' ) } + icon={ commentIcon } + > + <div className="editor-collab-sidebar-panel"> + <AddComment + threads={ resultComments } + onSubmit={ addNewComment } + showCommentBoard={ showCommentBoard } + setShowCommentBoard={ setShowCommentBoard } + /> + <Comments + threads={ resultComments } + onEditComment={ onEditComment } + onAddReply={ addNewComment } + onCommentDelete={ onCommentDelete } + onCommentResolve={ onCommentResolve } + /> + </div> + </PluginSidebar> + </> + ); +} diff --git a/packages/editor/src/components/collab-sidebar/style.scss b/packages/editor/src/components/collab-sidebar/style.scss new file mode 100644 index 00000000000000..2f937e3df9a25b --- /dev/null +++ b/packages/editor/src/components/collab-sidebar/style.scss @@ -0,0 +1,111 @@ +.editor-collab-sidebar-panel { + padding: $grid-unit-20; + + &__thread { + position: relative; + padding: $grid-unit-20; + border-radius: $radius-large; + border: 1px solid $gray-300; + background-color: $gray-100; + margin-bottom: $grid-unit-20; + } + + &__active-thread { + border: 1.5px solid #3858e9; + background-color: $white; + box-shadow: 0 5.5px 7.8px -0.3px rgba(0, 0, 0, 0.102); + } + + &__comment-field { + flex: 1; + } + + &__child-thread { + margin-top: 15px; + } + + &__user-name { + font-size: 12px; + font-weight: 400; + line-height: 16px; + text-align: left; + color: $gray-700; + text-transform: capitalize; + } + + &__user-time { + font-size: 12px; + font-weight: 400; + line-height: 16px; + text-align: left; + color: $gray-700; + } + + &__user-comment { + font-size: 13px; + font-weight: 400; + line-height: 20px; + text-align: left; + color: $gray-900; + + p { + margin-bottom: 0; + } + } + + &__user-avatar { + border-radius: $radius-round; + flex-shrink: 0; + } + + &__thread-overlay { + background-color: rgba(0, 0, 0, 0.7); + width: 100%; + height: 100%; + text-align: center; + position: absolute; + top: 0; + left: 0; + z-index: 1; + padding: 15px; + border-radius: $radius-large; + color: $white; + + p { + margin-bottom: 15px; + } + + button { + padding: 4px 10px; + color: $white; + } + } + + &__comment-status { + margin-left: auto; + + button { + &.has-icon:not(.has-text) { + min-width: 24px; + padding: 0; + width: 24px; + height: 24px; + flex-shrink: 0; + } + } + } + + &__comment-dropdown-menu { + flex-shrink: 0; + + button { + &.has-icon { + min-width: 24px; + padding: 0; + width: 24px; + height: 24px; + } + } + } + +} diff --git a/packages/editor/src/components/collab-sidebar/utils.js b/packages/editor/src/components/collab-sidebar/utils.js new file mode 100644 index 00000000000000..7e73344c5dc0e1 --- /dev/null +++ b/packages/editor/src/components/collab-sidebar/utils.js @@ -0,0 +1,9 @@ +/** + * Sanitizes a comment string by removing non-printable ASCII characters. + * + * @param {string} str - The comment string to sanitize. + * @return {string} - The sanitized comment string. + */ +export function sanitizeCommentString( str ) { + return str.trim(); +} diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index d3c82a65a5bc6f..1bd1114852fd6c 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -12,6 +12,7 @@ import { PinnedItems } from '@wordpress/interface'; /** * Internal dependencies */ +import CollabSidebar from '../collab-sidebar'; import BackButton, { useHasBackButton } from './back-button'; import CollapsibleBlockToolbar from '../collapsible-block-toolbar'; import DocumentBar from '../document-bar'; @@ -174,6 +175,7 @@ function Header( { } /> ) } + <CollabSidebar /> { customSaveButton } <MoreMenu /> diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss index d1af3095230f34..b62ccd2c8ac71d 100644 --- a/packages/editor/src/style.scss +++ b/packages/editor/src/style.scss @@ -2,6 +2,7 @@ @import "./components/autocompleters/style.scss"; @import "./components/block-manager/style.scss"; +@import "./components/collab-sidebar/style.scss"; @import "./components/collapsible-block-toolbar/style.scss"; @import "./components/create-template-part-modal/style.scss"; @import "./components/block-settings-menu/style.scss"; From b0db4f812923997ab6e68c4c3191c43f48186ae2 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Wed, 23 Oct 2024 13:14:08 -0500 Subject: [PATCH 1314/1908] Make useZoomOut hook private (#66374) Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-editor/README.md | 8 -------- packages/block-editor/src/index.js | 1 - packages/block-editor/src/private-apis.js | 2 ++ .../components/global-styles/screen-style-variations.js | 5 ++++- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 7fc44c2ead9439..a0f75683914408 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -1075,14 +1075,6 @@ _Parameters_ - _override.id_ `?string`: Id of the style override, leave blank to create a new style. - _override.css_ `string`: CSS to apply. -### useZoomOut - -A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode. - -_Parameters_ - -- _zoomOut_ `boolean`: If we should enter into zoomOut mode or not - ### Warning _Related_ diff --git a/packages/block-editor/src/index.js b/packages/block-editor/src/index.js index db1bc0a06ec6d1..d81f23a702b04e 100644 --- a/packages/block-editor/src/index.js +++ b/packages/block-editor/src/index.js @@ -13,7 +13,6 @@ export { getGapCSSValue as __experimentalGetGapCSSValue, getShadowClassesAndStyles as __experimentalGetShadowClassesAndStyles, useCachedTruthy, - useZoomOut, useStyleOverride, } from './hooks'; export * from './components'; diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 386d5fad49bc62..5067317e3f2465 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -24,6 +24,7 @@ import { useLayoutClasses, useLayoutStyles, __unstableBlockStyleVariationOverridesWithConfig, + useZoomOut, } from './hooks'; import DimensionsTool from './components/dimensions-tool'; import ResolutionTool from './components/resolution-tool'; @@ -79,6 +80,7 @@ lock( privateApis, { TextAlignmentControl, usesContextKey, useFlashEditableBlocks, + useZoomOut, globalStylesDataKey, globalStylesLinksDataKey, selectBlockPatternsKey, diff --git a/packages/edit-site/src/components/global-styles/screen-style-variations.js b/packages/edit-site/src/components/global-styles/screen-style-variations.js index 70727ac6698801..12690966ba3c4f 100644 --- a/packages/edit-site/src/components/global-styles/screen-style-variations.js +++ b/packages/edit-site/src/components/global-styles/screen-style-variations.js @@ -3,7 +3,7 @@ */ import { Card, CardBody } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { useZoomOut } from '@wordpress/block-editor'; +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { useDispatch } from '@wordpress/data'; import { store as editorStore } from '@wordpress/editor'; @@ -12,6 +12,9 @@ import { store as editorStore } from '@wordpress/editor'; */ import ScreenHeader from './header'; import SidebarNavigationScreenGlobalStylesContent from '../sidebar-navigation-screen-global-styles/content'; +import { unlock } from '../../lock-unlock'; + +const { useZoomOut } = unlock( blockEditorPrivateApis ); function ScreenStyleVariations() { // Style Variations should only be previewed in with From 54371146e6515a15118c6feceb34ade061b44a1b Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 24 Oct 2024 09:26:19 +1000 Subject: [PATCH 1315/1908] Style Book: Add color tab (#65692) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- ...se-multiple-origin-colors-and-gradients.js | 8 +- .../src/components/global-styles/ui.js | 11 ++ .../components/style-book/color-examples.tsx | 44 ++++++ .../src/components/style-book/constants.ts | 80 ++++++++++- .../style-book/duotone-examples.tsx | 53 ++++++++ .../src/components/style-book/examples.ts | 63 --------- .../src/components/style-book/examples.tsx | 113 ++++++++++++++++ .../src/components/style-book/index.js | 128 ++++++++++++++++-- .../components/style-book/test/categories.js | 5 - .../src/components/style-book/types.ts | 35 ++++- 10 files changed, 455 insertions(+), 85 deletions(-) create mode 100644 packages/edit-site/src/components/style-book/color-examples.tsx create mode 100644 packages/edit-site/src/components/style-book/duotone-examples.tsx delete mode 100644 packages/edit-site/src/components/style-book/examples.ts create mode 100644 packages/edit-site/src/components/style-book/examples.tsx diff --git a/packages/block-editor/src/components/colors-gradients/use-multiple-origin-colors-and-gradients.js b/packages/block-editor/src/components/colors-gradients/use-multiple-origin-colors-and-gradients.js index ee27960529ede3..cfa5930ba7034c 100644 --- a/packages/block-editor/src/components/colors-gradients/use-multiple-origin-colors-and-gradients.js +++ b/packages/block-editor/src/components/colors-gradients/use-multiple-origin-colors-and-gradients.js @@ -55,6 +55,7 @@ export default function useMultipleOriginColorsAndGradients() { 'Theme', 'Indicates this palette comes from the theme.' ), + slug: 'theme', colors: themeColors, } ); } @@ -68,6 +69,7 @@ export default function useMultipleOriginColorsAndGradients() { 'Default', 'Indicates this palette comes from WordPress.' ), + slug: 'default', colors: defaultColors, } ); } @@ -75,8 +77,9 @@ export default function useMultipleOriginColorsAndGradients() { result.push( { name: _x( 'Custom', - 'Indicates this palette comes from the theme.' + 'Indicates this palette is created by the user.' ), + slug: 'custom', colors: customColors, } ); } @@ -96,6 +99,7 @@ export default function useMultipleOriginColorsAndGradients() { 'Theme', 'Indicates this palette comes from the theme.' ), + slug: 'theme', gradients: themeGradients, } ); } @@ -109,6 +113,7 @@ export default function useMultipleOriginColorsAndGradients() { 'Default', 'Indicates this palette comes from WordPress.' ), + slug: 'default', gradients: defaultGradients, } ); } @@ -118,6 +123,7 @@ export default function useMultipleOriginColorsAndGradients() { 'Custom', 'Indicates this palette is created by the user.' ), + slug: 'custom', gradients: customGradients, } ); } diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index 6cd465e237100a..9ca88f40f1f001 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -45,6 +45,7 @@ import ScreenCSS from './screen-css'; import ScreenRevisions from './screen-revisions'; import { unlock } from '../../lock-unlock'; import { store as editSiteStore } from '../../store'; +import { STYLE_BOOK_COLOR_GROUPS } from '../style-book/constants'; const SLOT_FILL_NAME = 'GlobalStylesMenu'; const { useGlobalStylesReset } = unlock( blockEditorPrivateApis ); @@ -191,6 +192,16 @@ function GlobalStylesStyleBook() { ) } onSelect={ ( blockName ) => { + if ( + STYLE_BOOK_COLOR_GROUPS.find( + ( group ) => group.slug === blockName + ) + ) { + // Go to color palettes Global Styles. + navigator.goTo( '/colors/palette' ); + return; + } + // Now go to the selected block. navigator.goTo( '/blocks/' + encodeURIComponent( blockName ) ); } } diff --git a/packages/edit-site/src/components/style-book/color-examples.tsx b/packages/edit-site/src/components/style-book/color-examples.tsx new file mode 100644 index 00000000000000..97bdeecee32d3d --- /dev/null +++ b/packages/edit-site/src/components/style-book/color-examples.tsx @@ -0,0 +1,44 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ +import { __experimentalGrid as Grid } from '@wordpress/components'; +import { View } from '@wordpress/primitives'; +import { + getColorClassName, + __experimentalGetGradientClass, +} from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ +import type { Color, Gradient } from './types'; + +const ColorExamples = ( { colors, type } ): JSX.Element | null => { + if ( ! colors ) { + return null; + } + + return ( + <Grid columns={ 2 } rowGap={ 8 } columnGap={ 16 }> + { colors.map( ( color: Color | Gradient ) => { + const className = + type === 'gradients' + ? __experimentalGetGradientClass( color.slug ) + : getColorClassName( 'background-color', color.slug ); + const classes = clsx( + 'edit-site-style-book__color-example', + className + ); + + return <View key={ color.slug } className={ classes } />; + } ) } + </Grid> + ); +}; + +export default ColorExamples; diff --git a/packages/edit-site/src/components/style-book/constants.ts b/packages/edit-site/src/components/style-book/constants.ts index fc06d8f1409f0d..1ba1bf5e3dffa9 100644 --- a/packages/edit-site/src/components/style-book/constants.ts +++ b/packages/edit-site/src/components/style-book/constants.ts @@ -6,7 +6,52 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import type { StyleBookCategory } from './types'; +import type { StyleBookCategory, StyleBookColorGroup } from './types'; + +export const STYLE_BOOK_COLOR_GROUPS: StyleBookColorGroup[] = [ + { + slug: 'theme-colors', + title: __( 'Theme Colors' ), + origin: 'theme', + type: 'colors', + }, + { + slug: 'theme-gradients', + title: __( 'Theme Gradients' ), + origin: 'theme', + type: 'gradients', + }, + { + slug: 'custom-colors', + title: __( 'Custom Colors' ), + origin: 'custom', + type: 'colors', + }, + { + slug: 'custom-gradients', + title: __( 'Custom Gradients' ), + origin: 'custom', // User. + type: 'gradients', + }, + { + slug: 'duotones', + title: __( 'Duotones' ), + origin: 'theme', + type: 'duotones', + }, + { + slug: 'default-colors', + title: __( 'Default Colors' ), + origin: 'default', + type: 'colors', + }, + { + slug: 'default-gradients', + title: __( 'Default Gradients' ), + origin: 'default', + type: 'gradients', + }, +]; export const STYLE_BOOK_THEME_SUBCATEGORIES: Omit< StyleBookCategory, @@ -74,7 +119,7 @@ export const STYLE_BOOK_CATEGORIES: StyleBookCategory[] = [ { slug: 'colors', title: __( 'Colors' ), - blocks: [ 'custom/colors' ], + blocks: [], }, { slug: 'theme', @@ -111,7 +156,7 @@ export const STYLE_BOOK_IFRAME_STYLES = ` .is-root-container { display: flow-root; } - + body { position: relative; padding: 32px !important; @@ -141,15 +186,40 @@ export const STYLE_BOOK_IFRAME_STYLES = ` box-shadow: 0 0 0 1px var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba)); } + .edit-site-style-book__example.is-disabled-example { + pointer-events: none; + } + .edit-site-style-book__example:focus:not(:disabled) { box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba)); outline: 3px solid transparent; } + .edit-site-style-book__duotone-example > div:first-child { + display: flex; + aspect-ratio: 16 / 9; + grid-row: span 1; + grid-column: span 2; + } + .edit-site-style-book__duotone-example img { + width: 100%; + height: 100%; + object-fit: cover; + } + .edit-site-style-book__duotone-example > div:not(:first-child) { + height: 20px; + border: 1px solid #ddd; + } + + .edit-site-style-book__color-example { + height: 52px; + border: 1px solid #ddd; + } + .edit-site-style-book__examples.is-wide .edit-site-style-book__example { flex-direction: row; } - + .edit-site-style-book__subcategory-title, .edit-site-style-book__example-title { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; @@ -160,7 +230,7 @@ export const STYLE_BOOK_IFRAME_STYLES = ` text-align: left; text-transform: uppercase; } - + .edit-site-style-book__subcategory-title { font-size: 16px; margin-bottom: 40px; diff --git a/packages/edit-site/src/components/style-book/duotone-examples.tsx b/packages/edit-site/src/components/style-book/duotone-examples.tsx new file mode 100644 index 00000000000000..7ee90e61f1c6aa --- /dev/null +++ b/packages/edit-site/src/components/style-book/duotone-examples.tsx @@ -0,0 +1,53 @@ +/** + * WordPress dependencies + */ +import { __experimentalGrid as Grid } from '@wordpress/components'; +import { View } from '@wordpress/primitives'; + +/** + * Internal dependencies + */ +import type { Duotone } from './types'; + +const DuotoneExamples = ( { duotones } ): JSX.Element | null => { + if ( ! duotones ) { + return null; + } + + return ( + <Grid columns={ 2 } rowGap={ 16 } columnGap={ 16 }> + { duotones.map( ( duotone: Duotone ) => { + return ( + <Grid + key={ duotone.slug } + className="edit-site-style-book__duotone-example" + columns={ 2 } + rowGap={ 8 } + columnGap={ 8 } + > + <View> + <img + alt={ `Duotone example: ${ duotone.slug }` } + src="https://s.w.org/images/core/5.3/MtBlanc1.jpg" + style={ { + filter: `url(#wp-duotone-${ duotone.slug })`, + } } + /> + </View> + { duotone.colors.map( ( color ) => { + return ( + <View + key={ color } + className="edit-site-style-book__color-example" + style={ { backgroundColor: color } } + /> + ); + } ) } + </Grid> + ); + } ) } + </Grid> + ); +}; + +export default DuotoneExamples; diff --git a/packages/edit-site/src/components/style-book/examples.ts b/packages/edit-site/src/components/style-book/examples.ts deleted file mode 100644 index 80807b10374c68..00000000000000 --- a/packages/edit-site/src/components/style-book/examples.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * WordPress dependencies - */ -import { __, sprintf } from '@wordpress/i18n'; -import { - getBlockType, - getBlockTypes, - getBlockFromExample, - createBlock, -} from '@wordpress/blocks'; - -/** - * Internal dependencies - */ -import type { BlockExample } from './types'; - -/** - * Returns a list of examples for registered block types. - * - * @return {BlockExample[]} An array of block examples. - */ -export function getExamples(): BlockExample[] { - const nonHeadingBlockExamples = getBlockTypes() - .filter( ( blockType ) => { - const { name, example, supports } = blockType; - return ( - name !== 'core/heading' && - !! example && - supports.inserter !== false - ); - } ) - .map( ( blockType ) => ( { - name: blockType.name, - title: blockType.title, - category: blockType.category, - blocks: getBlockFromExample( blockType.name, blockType.example ), - } ) ); - const isHeadingBlockRegistered = !! getBlockType( 'core/heading' ); - - if ( ! isHeadingBlockRegistered ) { - return nonHeadingBlockExamples; - } - - // Use our own example for the Heading block so that we can show multiple - // heading levels. - const headingsExample = { - name: 'core/heading', - title: __( 'Headings' ), - category: 'text', - blocks: [ 1, 2, 3, 4, 5, 6 ].map( ( level ) => { - return createBlock( 'core/heading', { - content: sprintf( - // translators: %d: heading level e.g: "1", "2", "3" - __( 'Heading %d' ), - level - ), - level, - } ); - } ), - }; - - return [ headingsExample, ...nonHeadingBlockExamples ]; -} diff --git a/packages/edit-site/src/components/style-book/examples.tsx b/packages/edit-site/src/components/style-book/examples.tsx new file mode 100644 index 00000000000000..9f4badd99a6582 --- /dev/null +++ b/packages/edit-site/src/components/style-book/examples.tsx @@ -0,0 +1,113 @@ +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; +import { + getBlockType, + getBlockTypes, + getBlockFromExample, + createBlock, +} from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import type { BlockExample, ColorOrigin, MultiOriginPalettes } from './types'; +import ColorExamples from './color-examples'; +import DuotoneExamples from './duotone-examples'; +import { STYLE_BOOK_COLOR_GROUPS } from './constants'; + +/** + * Returns examples color examples for each origin + * e.g. Core (Default), Theme, and User. + * + * @param {MultiOriginPalettes} colors Global Styles color palettes per origin. + * @return {BlockExample[]} An array of color block examples. + */ +function getColorExamples( colors: MultiOriginPalettes ): BlockExample[] { + if ( ! colors ) { + return []; + } + + const examples: BlockExample[] = []; + + STYLE_BOOK_COLOR_GROUPS.forEach( ( group ) => { + const palette = colors[ group.type ].find( + ( origin: ColorOrigin ) => origin.slug === group.origin + ); + + if ( palette?.[ group.type ] ) { + const example: BlockExample = { + name: group.slug, + title: group.title, + category: 'colors', + }; + if ( group.type === 'duotones' ) { + example.content = ( + <DuotoneExamples duotones={ palette[ group.type ] } /> + ); + examples.push( example ); + } else { + example.content = ( + <ColorExamples + colors={ palette[ group.type ] } + type={ group.type } + /> + ); + examples.push( example ); + } + } + } ); + + return examples; +} + +/** + * Returns a list of examples for registered block types. + * + * @param {MultiOriginPalettes} colors Global styles colors grouped by origin e.g. Core, Theme, and User. + * @return {BlockExample[]} An array of block examples. + */ +export function getExamples( colors: MultiOriginPalettes ): BlockExample[] { + const nonHeadingBlockExamples = getBlockTypes() + .filter( ( blockType ) => { + const { name, example, supports } = blockType; + return ( + name !== 'core/heading' && + !! example && + supports?.inserter !== false + ); + } ) + .map( ( blockType ) => ( { + name: blockType.name, + title: blockType.title, + category: blockType.category, + blocks: getBlockFromExample( blockType.name, blockType.example ), + } ) ); + const isHeadingBlockRegistered = !! getBlockType( 'core/heading' ); + + if ( ! isHeadingBlockRegistered ) { + return nonHeadingBlockExamples; + } + + // Use our own example for the Heading block so that we can show multiple + // heading levels. + const headingsExample = { + name: 'core/heading', + title: __( 'Headings' ), + category: 'text', + blocks: [ 1, 2, 3, 4, 5, 6 ].map( ( level ) => { + return createBlock( 'core/heading', { + content: sprintf( + // translators: %d: heading level e.g: "1", "2", "3" + __( 'Heading %d' ), + level + ), + level, + } ); + } ), + }; + const colorExamples = getColorExamples( colors ); + + return [ headingsExample, ...colorExamples, ...nonHeadingBlockExamples ]; +} diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 0d8c49d76af507..93bbc6311c6865 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -11,18 +11,26 @@ import { Composite, privateApis as componentsPrivateApis, } from '@wordpress/components'; -import { __, sprintf } from '@wordpress/i18n'; +import { __, _x, sprintf } from '@wordpress/i18n'; import { BlockList, privateApis as blockEditorPrivateApis, store as blockEditorStore, + useSettings, __unstableEditorStyles as EditorStyles, __unstableIframe as Iframe, + __experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients, } from '@wordpress/block-editor'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { useSelect } from '@wordpress/data'; import { useResizeObserver } from '@wordpress/compose'; -import { useMemo, useState, memo, useContext } from '@wordpress/element'; +import { + useMemo, + useState, + memo, + useContext, + useEffect, +} from '@wordpress/element'; import { ENTER, SPACE } from '@wordpress/keycodes'; /** @@ -51,6 +59,81 @@ function isObjectEmpty( object ) { return ! object || Object.keys( object ).length === 0; } +/** + * Retrieves colors, gradients, and duotone filters from Global Styles. + * The inclusion of default (Core) palettes is controlled by the relevant + * theme.json property e.g. defaultPalette, defaultGradients, defaultDuotone. + * + * @return {Object} Object containing properties for each type of palette. + */ +function useMultiOriginPalettes() { + const { colors, gradients } = useMultipleOriginColorsAndGradients(); + + // Add duotone filters to the palettes data. + const [ + shouldDisplayDefaultDuotones, + customDuotones, + themeDuotones, + defaultDuotones, + ] = useSettings( + 'color.defaultDuotone', + 'color.duotone.custom', + 'color.duotone.theme', + 'color.duotone.default' + ); + + const palettes = useMemo( () => { + const result = { colors, gradients, duotones: [] }; + + if ( themeDuotones && themeDuotones.length ) { + result.duotones.push( { + name: _x( + 'Theme', + 'Indicates these duotone filters come from the theme.' + ), + slug: 'theme', + duotones: themeDuotones, + } ); + } + + if ( + shouldDisplayDefaultDuotones && + defaultDuotones && + defaultDuotones.length + ) { + result.duotones.push( { + name: _x( + 'Default', + 'Indicates these duotone filters come from WordPress.' + ), + slug: 'default', + duotones: defaultDuotones, + } ); + } + if ( customDuotones && customDuotones.length ) { + result.duotones.push( { + name: _x( + 'Custom', + 'Indicates these doutone filters are created by the user.' + ), + slug: 'custom', + duotones: customDuotones, + } ); + } + + return result; + }, [ + colors, + gradients, + customDuotones, + themeDuotones, + defaultDuotones, + shouldDisplayDefaultDuotones, + ] ); + + return palettes; +} + function StyleBook( { enableResizing = true, isSelected, @@ -64,7 +147,8 @@ function StyleBook( { const [ resizeObserver, sizes ] = useResizeObserver(); const [ textColor ] = useGlobalStyle( 'color.text' ); const [ backgroundColor ] = useGlobalStyle( 'color.background' ); - const [ examples ] = useState( getExamples ); + const colors = useMultiOriginPalettes(); + const [ examples, setExamples ] = useState( () => getExamples( colors ) ); const tabs = useMemo( () => getTopLevelStyleBookCategories().filter( ( category ) => @@ -74,6 +158,12 @@ function StyleBook( { ), [ examples ] ); + + // Ensure color examples are kept in sync with Global Styles palette changes. + useEffect( () => { + setExamples( getExamples( colors ) ); + }, [ colors ] ); + const { base: baseConfig } = useContext( GlobalStylesContext ); const mergedConfig = useMemo( () => { @@ -274,6 +364,7 @@ const Examples = memo( key={ example.name } id={ `example-${ example.name }` } title={ example.title } + content={ example.content } blocks={ example.blocks } isSelected={ isSelected( example.name ) } onClick={ () => { @@ -312,6 +403,7 @@ const Subcategory = ( { examples, isSelected, onSelect } ) => { key={ example.name } id={ `example-${ example.name }` } title={ example.title } + content={ example.content } blocks={ example.blocks } isSelected={ isSelected( example.name ) } onClick={ () => { @@ -322,7 +414,9 @@ const Subcategory = ( { examples, isSelected, onSelect } ) => { ); }; -const Example = ( { id, title, blocks, isSelected, onClick } ) => { +const disabledExamples = [ 'example-duotones' ]; + +const Example = ( { id, title, blocks, isSelected, onClick, content } ) => { const originalSettings = useSelect( ( select ) => select( blockEditorStore ).getSettings(), [] @@ -342,12 +436,20 @@ const Example = ( { id, title, blocks, isSelected, onClick } ) => { [ blocks ] ); + const disabledProps = disabledExamples.includes( id ) + ? { + disabled: true, + accessibleWhenDisabled: true, + } + : {}; + return ( <div role="row"> <div role="gridcell"> <Composite.Item className={ clsx( 'edit-site-style-book__example', { 'is-selected': isSelected, + 'is-disabled-example': !! disabledProps?.disabled, } ) } id={ id } aria-label={ sprintf( @@ -358,6 +460,7 @@ const Example = ( { id, title, blocks, isSelected, onClick } ) => { render={ <div /> } role="button" onClick={ onClick } + { ...disabledProps } > <span className="edit-site-style-book__example-title"> { title } @@ -367,12 +470,17 @@ const Example = ( { id, title, blocks, isSelected, onClick } ) => { aria-hidden > <Disabled className="edit-site-style-book__example-preview__content"> - <ExperimentalBlockEditorProvider - value={ renderedBlocks } - settings={ settings } - > - <BlockList renderAppender={ false } /> - </ExperimentalBlockEditorProvider> + { content ? ( + content + ) : ( + <ExperimentalBlockEditorProvider + value={ renderedBlocks } + settings={ settings } + > + <EditorStyles /> + <BlockList renderAppender={ false } /> + </ExperimentalBlockEditorProvider> + ) } </Disabled> </div> </Composite.Item> diff --git a/packages/edit-site/src/components/style-book/test/categories.js b/packages/edit-site/src/components/style-book/test/categories.js index 5629689e260f89..128eaf282a9c5d 100644 --- a/packages/edit-site/src/components/style-book/test/categories.js +++ b/packages/edit-site/src/components/style-book/test/categories.js @@ -48,11 +48,6 @@ const exampleThemeBlocks = [ title: 'Home Link', category: 'design', }, - { - name: 'custom/colors', - title: 'Colors', - category: 'colors', - }, { name: 'core/site-logo', title: 'Site Logo', diff --git a/packages/edit-site/src/components/style-book/types.ts b/packages/edit-site/src/components/style-book/types.ts index 4729b38b1b2bb1..e7be17b17dd4df 100644 --- a/packages/edit-site/src/components/style-book/types.ts +++ b/packages/edit-site/src/components/style-book/types.ts @@ -9,6 +9,7 @@ export type StyleBookCategory = { slug: string; blocks?: string[]; exclude?: string[]; + include?: string[]; subcategories?: StyleBookCategory[]; }; @@ -16,7 +17,8 @@ export type BlockExample = { name: string; title: string; category: string; - blocks: Block | Block[]; + content?: JSX.Element; + blocks?: Block | Block[]; }; export type CategoryExamples = { @@ -25,3 +27,34 @@ export type CategoryExamples = { examples?: BlockExample[]; subcategories?: CategoryExamples[]; }; + +export type StyleBookColorGroup = { + origin: string; + slug: string; + title: string; + type: string; +}; + +export type Color = { slug: string }; +export type Gradient = { slug: string }; +export type Duotone = { + colors: string[]; + slug: string; +}; + +export type ColorOrigin = { + name: string; + slug: string; + colors?: Color[]; + gradients?: Gradient[]; + duotones?: Duotone[]; +}; + +export type MultiOriginPalettes = { + disableCustomColors: boolean; + disableCustomGradients: boolean; + hasColorsOrGradients: boolean; + colors: Omit< ColorOrigin, 'gradients' | 'duotones' >; + duotones: Omit< ColorOrigin, 'colors' | 'gradients' >; + gradients: Omit< ColorOrigin, 'colors' | 'duotones' >; +}; From 67fca2ebcc9f0caafccbcaef15021d23cb0bf3dd Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 24 Oct 2024 13:53:45 +1000 Subject: [PATCH 1316/1908] Backport: Caching of global styles for blocks from core (#66349) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- lib/global-styles-and-settings.php | 45 +++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/global-styles-and-settings.php b/lib/global-styles-and-settings.php index e62d160d84aa78..c4446cf29cf011 100644 --- a/lib/global-styles-and-settings.php +++ b/lib/global-styles-and-settings.php @@ -73,6 +73,7 @@ function gutenberg_get_global_stylesheet( $types = array() ) { * @see wp_add_global_styles_for_blocks */ $origins = array( 'default', 'theme', 'custom' ); + /* * If the theme doesn't have theme.json but supports both appearance tools and color palette, * the 'theme' origin should be included so color palette presets are also output. @@ -260,8 +261,45 @@ function gutenberg_add_global_styles_for_blocks() { $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); $tree = WP_Theme_JSON_Resolver_Gutenberg::resolve_theme_file_uris( $tree ); $block_nodes = $tree->get_styles_block_nodes(); + + $can_use_cached = ! wp_is_development_mode( 'theme' ); + $update_cache = false; + + if ( $can_use_cached ) { + // Hash the merged WP_Theme_JSON data to bust cache on settings or styles change. + $cache_hash = md5( wp_json_encode( $tree->get_raw_data() ) ); + $cache_key = 'wp_styles_for_blocks'; + $cached = get_transient( $cache_key ); + + // Reset the cached data if there is no value or if the hash has changed. + if ( ! is_array( $cached ) || $cached['hash'] !== $cache_hash ) { + $cached = array( + 'hash' => $cache_hash, + 'blocks' => array(), + ); + + // Update the cache if the hash has changed. + $update_cache = true; + } + } + foreach ( $block_nodes as $metadata ) { - $block_css = $tree->get_styles_for_block( $metadata ); + if ( $can_use_cached ) { + // Use the block name as the key for cached CSS data. Otherwise, use a hash of the metadata. + $cache_node_key = isset( $metadata['name'] ) ? $metadata['name'] : md5( wp_json_encode( $metadata ) ); + + if ( isset( $cached['blocks'][ $cache_node_key ] ) ) { + $block_css = $cached['blocks'][ $cache_node_key ]; + } else { + $block_css = $tree->get_styles_for_block( $metadata ); + $cached['blocks'][ $cache_node_key ] = $block_css; + + // Update the cache if the cache contents have changed. + $update_cache = true; + } + } else { + $block_css = $tree->get_styles_for_block( $metadata ); + } if ( ! wp_should_load_separate_core_block_assets() ) { wp_add_inline_style( 'global-styles', $block_css ); @@ -269,6 +307,7 @@ function gutenberg_add_global_styles_for_blocks() { } $stylesheet_handle = 'global-styles'; + /* * When `wp_should_load_separate_core_block_assets()` is true, block styles are * enqueued for each block on the page in class WP_Block's render function. @@ -306,6 +345,10 @@ function gutenberg_add_global_styles_for_blocks() { } } } + + if ( $update_cache ) { + set_transient( $cache_key, $cached ); + } } /** From e9fb5105040c9d1d4d582543dcd878eb5f21b2a3 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Thu, 24 Oct 2024 09:53:56 +0200 Subject: [PATCH 1317/1908] Fix typo after #63669. (#66396) Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: gigitux <gigitux@git.wordpress.org> --- packages/editor/src/components/post-url/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-url/index.js b/packages/editor/src/components/post-url/index.js index c7dc5712dcac4a..f03bdd59752a83 100644 --- a/packages/editor/src/components/post-url/index.js +++ b/packages/editor/src/components/post-url/index.js @@ -76,7 +76,7 @@ export default function PostURL( { onClose } ) { } ); } ); const postUrlSlugDescriptionId = - 'editor-post-url__slug-descriotion-' + useInstanceId( PostURL ); + 'editor-post-url__slug-description-' + useInstanceId( PostURL ); return ( <div className="editor-post-url"> From 02b1ec46eab511a781d62d26e31746486fb4ef39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:29:07 +0200 Subject: [PATCH 1318/1908] Block registration: normalize blockType.parent to `array` (#66250) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> --- packages/block-editor/src/store/selectors.js | 14 ++------ packages/blocks/CHANGELOG.md | 4 +++ packages/blocks/src/api/registration.js | 9 ----- packages/blocks/src/api/test/registration.js | 33 +++++++++++++++++ .../blocks/src/store/process-block-type.js | 36 +++++++++++++++++++ 5 files changed, 75 insertions(+), 21 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 787225f18a0a57..b5afb2891ef1cf 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -1628,18 +1628,8 @@ const isBlockVisibleInTheInserter = ( checkedBlocks.add( blockName ); // If parent blocks are not visible, child blocks should be hidden too. - // - // In some scenarios, blockType.parent may be a string. - // A better approach would be sanitize parent in all the places that can be modified: - // block registration, processBlockType, filters, etc. - // In the meantime, this is a hotfix to prevent the editor from crashing. - const parent = - typeof blockType.parent === 'string' || - blockType.parent instanceof String - ? [ blockType.parent ] - : blockType.parent; - if ( Array.isArray( parent ) ) { - return parent.some( + if ( Array.isArray( blockType.parent ) ) { + return blockType.parent.some( ( name ) => ( blockName !== name && isBlockVisibleInTheInserter( diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 73a700428674b2..eebbe7148e8055 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking changes + +- Normalize `blockType.parent` to be an array. While string values were never supported, they appeared to work with some unintended side-effects that have been fixed by [#66250](https://github.com/WordPress/gutenberg/pull/66250). For that reason, we've added some code that automatically migrates strings to arrays — though it still raises a warning. + ## 13.10.0 (2024-10-16) ## 13.9.0 (2024-10-03) diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index ef1b6bd20a4cdd..2f4bab2b5f2589 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -232,15 +232,6 @@ export function registerBlockType( blockNameOrMetadata, settings ) { return; } - if ( 1 === settings?.parent?.length && name === settings.parent[ 0 ] ) { - warning( - 'Block "' + - name + - '" cannot be a parent of itself. Please remove the block name from the parent list.' - ); - return; - } - if ( ! /^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/.test( name ) ) { warning( 'Block names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-block' diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index 656e9471a541b8..5941415e61fe55 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -742,6 +742,39 @@ describe( 'blocks', () => { } ); } ); + it( 'should transform parent string to array', () => { + const blockType = { + save: noop, + category: 'text', + title: 'block title', + parent: 'core/paragraph', + }; + const block = registerBlockType( + 'core/test-block-parent-string', + blockType + ); + expect( console ).toHaveWarnedWith( + 'Parent must be undefined or an array of strings (block types), but it is a string.' + ); + expect( block ).toEqual( { + name: 'core/test-block-parent-string', + save: noop, + category: 'text', + title: 'block title', + icon: { src: BLOCK_ICON_DEFAULT }, + attributes: {}, + providesContext: {}, + usesContext: [], + keywords: [], + selectors: {}, + supports: {}, + styles: [], + variations: [], + blockHooks: {}, + parent: [ 'core/paragraph' ], + } ); + } ); + describe( 'applyFilters', () => { afterEach( () => { removeAllFilters( 'blocks.registerBlockType' ); diff --git a/packages/blocks/src/store/process-block-type.js b/packages/blocks/src/store/process-block-type.js index ae8f92f84cfabb..bc7b1a0e10e774 100644 --- a/packages/blocks/src/store/process-block-type.js +++ b/packages/blocks/src/store/process-block-type.js @@ -197,5 +197,41 @@ export const processBlockType = return; } + if ( + typeof settings?.parent === 'string' || + settings?.parent instanceof String + ) { + settings.parent = [ settings.parent ]; + warning( + 'Parent must be undefined or an array of strings (block types), but it is a string.' + ); + // Intentionally continue: + // + // While string values were never supported, they appeared to work with some unintended side-effects + // that have been fixed by [#66250](https://github.com/WordPress/gutenberg/pull/66250). + // + // To be backwards-compatible, this code that automatically migrates strings to arrays. + } + + if ( + ! Array.isArray( settings?.parent ) && + settings?.parent !== undefined + ) { + warning( + 'Parent must be undefined or an array of block types, but it is ', + settings.parent + ); + return; + } + + if ( 1 === settings?.parent?.length && name === settings.parent[ 0 ] ) { + warning( + 'Block "' + + name + + '" cannot be a parent of itself. Please remove the block name from the parent list.' + ); + return; + } + return settings; }; From 0d91946dca83f9eaea37fd82a53143d1c4acdd64 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Thu, 24 Oct 2024 10:37:57 +0100 Subject: [PATCH 1319/1908] Add radius foundation and tokens to storybook (#66219) Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../foundations/design-language/radius.mdx | 55 +++++++++ .../design-language/static/radius-do.svg | 58 ++++++++++ .../design-language/static/radius-dont.svg | 58 ++++++++++ .../design-language/static/radius.svg | 62 +++++++++++ storybook/stories/tokens/components.tsx | 8 +- storybook/stories/tokens/elevation.mdx | 6 +- storybook/stories/tokens/radius.mdx | 105 ++++++++++++++++++ 7 files changed, 346 insertions(+), 6 deletions(-) create mode 100644 storybook/stories/foundations/design-language/radius.mdx create mode 100644 storybook/stories/foundations/design-language/static/radius-do.svg create mode 100644 storybook/stories/foundations/design-language/static/radius-dont.svg create mode 100644 storybook/stories/foundations/design-language/static/radius.svg create mode 100644 storybook/stories/tokens/radius.mdx diff --git a/storybook/stories/foundations/design-language/radius.mdx b/storybook/stories/foundations/design-language/radius.mdx new file mode 100644 index 00000000000000..9117bf940d45a2 --- /dev/null +++ b/storybook/stories/foundations/design-language/radius.mdx @@ -0,0 +1,55 @@ +import { Meta, Typeset } from '@storybook/addon-docs/blocks'; +import radius from './static/radius.svg'; +import radiusDo from './static/radius-do.svg'; +import radiusDont from './static/radius-dont.svg'; + +<Meta title="Foundations/Design Language/Radius" name="page" /> + +# Radius + +<img src={ radius } alt="Radius" width="100%" /> + +The radius scale is designed to provide a consistent, elegant appearance across nested elements. The defined values help maintain visual harmony between smaller primitives and larger containers, ensuring a cohesive user experience. + +## Scale + +The scale includes the following steps: + +- `radius-x-small`: Applied to the smallest elements, such as buttons inside inputs or similar small primitives. This ensures subtle rounding without distracting from the core design. +- `radius-small`: The most commonly used radius value, applied to many primitives like buttons, inputs, and other standalone controls. It provides a moderate rounding that feels balanced and polished. +- `radius-medium`: Used for medium-sized containers like dropdown menus, popovers, and other mid-level components. This value is slightly more pronounced, giving these elements a soft but noticeable edge. +- `radius-large`: Reserved for larger containers such as cards and modals. The larger radius ensures that these elements have a smooth, elegant appearance that enhances their prominence on the page. +- `radius-full`: Applies a `border-radius` of `9999px`, this value creates a highly rounded appearance, often used on pill-shaped buttons or other components where extreme rounding is desired but full circularity is not necessary. +- `radius-round`: This value applies a `border-radius` of `100%`, making elements fully circular. It's typically used for circular avatars or buttons where complete rounding is required. + +These steps are defined as tokens. To view the values and understand how to use them please view the [Tokens section](?path=/docs/tokens-radius--page). + +## Usage Guidelines + +- Consistency: To maintain visual cohesion, adhere to the radius scale when styling elements. Avoid custom radius values unless there is a specific need. +- Nested Elements: When combining elements of different sizes (e.g., buttons within inputs or cards within modals), ensure that smaller nested elements use the appropriate radius value for their size. +- Accessibility: Larger radius values can create a more approachable and friendly appearance, especially for larger components like cards and modals that demand more attention from users. + +<table> + <tr> + <th width="50%">✅ Do</th> + <th width="50%">🚫 Don't</th> + </tr> + <tr> + <td width="50%" valign="top"> + <img src={ radiusDo } alt="Radius do" width="100%" /> + + - Scale application of radius with element or container size. + + - Use `radius-round` for circles and `radius-full` for pills. + </td> + <td width="50%" valign="top"> + <img src={ radiusDont } alt="Radius don't" width="100%" /> + + - Don't nest larger radii inside smaller radii. + + - Don't apply the same + radius value to container and immediate descendent. + </td> + </tr> +</table> diff --git a/storybook/stories/foundations/design-language/static/radius-do.svg b/storybook/stories/foundations/design-language/static/radius-do.svg new file mode 100644 index 00000000000000..baec81e98456a4 --- /dev/null +++ b/storybook/stories/foundations/design-language/static/radius-do.svg @@ -0,0 +1,58 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="821" height="400" fill="none"> + <g clip-path="url(#a)"> + <rect width="821" height="400" fill="#3858E9" rx="8"/> + <rect width="835" height="662" x="-211" y="60" fill="#607AEE" rx="48"/> + <rect width="834" height="661" x="-210.5" y="60.5" stroke="#fff" stroke-opacity=".2" rx="47.5"/> + <rect width="111" height="40" x="-34" y="107" fill="#7D92F1" rx="20"/> + <rect width="110" height="39" x="-33.5" y="107.5" stroke="#fff" stroke-opacity=".2" rx="19.5"/> + <rect width="111" height="40" x="93" y="107" fill="#7D92F1" rx="20"/> + <rect width="110" height="39" x="93.5" y="107.5" stroke="#fff" stroke-opacity=".2" rx="19.5"/> + <rect width="111" height="40" x="220" y="107" fill="#7D92F1" rx="20"/> + <rect width="110" height="39" x="220.5" y="107.5" stroke="#fff" stroke-opacity=".2" rx="19.5"/> + <rect width="40" height="40" x="537" y="107" fill="#7D92F1" rx="12"/> + <rect width="39" height="39" x="537.5" y="107.5" stroke="#fff" stroke-opacity=".2" rx="11.5"/> + <g filter="url(#b)"> + <rect width="335" height="502" x="242" y="163" fill="#93A4F4" rx="24"/> + <rect width="334" height="501" x="242.5" y="163.5" stroke="#fff" stroke-opacity=".2" rx="23.5"/> + </g> + <rect width="287" height="62" x="266" y="187" fill="#ADBBFB" rx="12"/> + <rect width="286" height="61" x="266.5" y="187.5" stroke="#fff" stroke-opacity=".2" rx="11.5"/> + <rect width="40" height="40" x="266" y="281" fill="#ADBBFB" rx="20"/> + <rect width="39" height="39" x="266.5" y="281.5" stroke="#fff" stroke-opacity=".2" rx="19.5"/> + <rect width="40" height="40" x="266" y="337" fill="#ADBBFB" rx="20"/> + <rect width="39" height="39" x="266.5" y="337.5" stroke="#fff" stroke-opacity=".2" rx="19.5"/> + <rect width="40" height="40" x="266" y="393" fill="#ADBBFB" rx="20"/> + <rect width="39" height="39" x="266.5" y="393.5" stroke="#fff" stroke-opacity=".2" rx="19.5"/> + <rect width="40" height="40" x="502" y="198" fill="#CCD4FF" rx="6"/> + <rect width="39" height="39" x="502.5" y="198.5" stroke="#fff" stroke-opacity=".2" rx="5.5"/> + </g> + <defs> + <clipPath id="a"> + <rect width="821" height="400" fill="#fff" rx="8"/> + </clipPath> + <filter id="b" width="533" height="867" x="143" y="144" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> + <feOffset dy="15"/> + <feGaussianBlur stdDeviation="17"/> + <feColorMatrix values="0 0 0 0 0.0117647 0 0 0 0 0.0627451 0 0 0 0 0.329412 0 0 0 0.1 0"/> + <feBlend in2="BackgroundImageFix" result="effect1_dropShadow_15778_6552"/> + <feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> + <feOffset dy="62"/> + <feGaussianBlur stdDeviation="31"/> + <feColorMatrix values="0 0 0 0 0.0117647 0 0 0 0 0.0627451 0 0 0 0 0.329412 0 0 0 0.09 0"/> + <feBlend in2="effect1_dropShadow_15778_6552" result="effect2_dropShadow_15778_6552"/> + <feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> + <feOffset dy="139"/> + <feGaussianBlur stdDeviation="41.5"/> + <feColorMatrix values="0 0 0 0 0.0117647 0 0 0 0 0.0627451 0 0 0 0 0.329412 0 0 0 0.05 0"/> + <feBlend in2="effect2_dropShadow_15778_6552" result="effect3_dropShadow_15778_6552"/> + <feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> + <feOffset dy="247"/> + <feGaussianBlur stdDeviation="49.5"/> + <feColorMatrix values="0 0 0 0 0.0117647 0 0 0 0 0.0627451 0 0 0 0 0.329412 0 0 0 0.01 0"/> + <feBlend in2="effect3_dropShadow_15778_6552" result="effect4_dropShadow_15778_6552"/> + <feBlend in="SourceGraphic" in2="effect4_dropShadow_15778_6552" result="shape"/> + </filter> + </defs> +</svg> diff --git a/storybook/stories/foundations/design-language/static/radius-dont.svg b/storybook/stories/foundations/design-language/static/radius-dont.svg new file mode 100644 index 00000000000000..b4426b2fdd9199 --- /dev/null +++ b/storybook/stories/foundations/design-language/static/radius-dont.svg @@ -0,0 +1,58 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="821" height="400" fill="none"> + <g clip-path="url(#a)"> + <rect width="821" height="400" fill="#3858E9" rx="8"/> + <rect width="835" height="662" x="-211" y="60" fill="#607AEE" rx="6"/> + <rect width="834" height="661" x="-210.5" y="60.5" stroke="#fff" stroke-opacity=".2" rx="5.5"/> + <rect width="111" height="40" x="-34" y="107" fill="#7D92F1" rx="12"/> + <rect width="110" height="39" x="-33.5" y="107.5" stroke="#fff" stroke-opacity=".2" rx="11.5"/> + <rect width="111" height="40" x="93" y="107" fill="#7D92F1" rx="12"/> + <rect width="110" height="39" x="93.5" y="107.5" stroke="#fff" stroke-opacity=".2" rx="11.5"/> + <rect width="111" height="40" x="220" y="107" fill="#7D92F1" rx="12"/> + <rect width="110" height="39" x="220.5" y="107.5" stroke="#fff" stroke-opacity=".2" rx="11.5"/> + <rect width="40" height="40" x="537" y="107" fill="#7D92F1" rx="12"/> + <rect width="39" height="39" x="537.5" y="107.5" stroke="#fff" stroke-opacity=".2" rx="11.5"/> + <g filter="url(#b)"> + <rect width="335" height="502" x="242" y="163" fill="#93A4F4" rx="6"/> + <rect width="334" height="501" x="242.5" y="163.5" stroke="#fff" stroke-opacity=".2" rx="5.5"/> + </g> + <rect width="40" height="40" x="266" y="281" fill="#ADBBFB" rx="16"/> + <rect width="39" height="39" x="266.5" y="281.5" stroke="#fff" stroke-opacity=".2" rx="15.5"/> + <rect width="40" height="40" x="266" y="337" fill="#ADBBFB" rx="16"/> + <rect width="39" height="39" x="266.5" y="337.5" stroke="#fff" stroke-opacity=".2" rx="15.5"/> + <rect width="40" height="40" x="266" y="393" fill="#ADBBFB" rx="16"/> + <rect width="39" height="39" x="266.5" y="393.5" stroke="#fff" stroke-opacity=".2" rx="15.5"/> + <rect width="287" height="62" x="266" y="187" fill="#ADBBFB" rx="6"/> + <rect width="286" height="61" x="266.5" y="187.5" stroke="#fff" stroke-opacity=".2" rx="5.5"/> + <rect width="40" height="40" x="502" y="198" fill="#CCD4FF" rx="9"/> + <rect width="39" height="39" x="502.5" y="198.5" stroke="#fff" stroke-opacity=".2" rx="8.5"/> + </g> + <defs> + <clipPath id="a"> + <rect width="821" height="400" fill="#fff" rx="8"/> + </clipPath> + <filter id="b" width="533" height="867" x="143" y="144" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> + <feOffset dy="15"/> + <feGaussianBlur stdDeviation="17"/> + <feColorMatrix values="0 0 0 0 0.0117647 0 0 0 0 0.0627451 0 0 0 0 0.329412 0 0 0 0.1 0"/> + <feBlend in2="BackgroundImageFix" result="effect1_dropShadow_15779_6567"/> + <feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> + <feOffset dy="62"/> + <feGaussianBlur stdDeviation="31"/> + <feColorMatrix values="0 0 0 0 0.0117647 0 0 0 0 0.0627451 0 0 0 0 0.329412 0 0 0 0.09 0"/> + <feBlend in2="effect1_dropShadow_15779_6567" result="effect2_dropShadow_15779_6567"/> + <feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> + <feOffset dy="139"/> + <feGaussianBlur stdDeviation="41.5"/> + <feColorMatrix values="0 0 0 0 0.0117647 0 0 0 0 0.0627451 0 0 0 0 0.329412 0 0 0 0.05 0"/> + <feBlend in2="effect2_dropShadow_15779_6567" result="effect3_dropShadow_15779_6567"/> + <feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> + <feOffset dy="247"/> + <feGaussianBlur stdDeviation="49.5"/> + <feColorMatrix values="0 0 0 0 0.0117647 0 0 0 0 0.0627451 0 0 0 0 0.329412 0 0 0 0.01 0"/> + <feBlend in2="effect3_dropShadow_15779_6567" result="effect4_dropShadow_15779_6567"/> + <feBlend in="SourceGraphic" in2="effect4_dropShadow_15779_6567" result="shape"/> + </filter> + </defs> +</svg> diff --git a/storybook/stories/foundations/design-language/static/radius.svg b/storybook/stories/foundations/design-language/static/radius.svg new file mode 100644 index 00000000000000..a5d81ef7ca0535 --- /dev/null +++ b/storybook/stories/foundations/design-language/static/radius.svg @@ -0,0 +1,62 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="1091" height="395" fill="none"> + <g clip-path="url(#a)"> + <rect width="1091" height="395" fill="#3858E9" rx="8"/> + <g filter="url(#b)"> + <path fill="url(#c)" fill-opacity=".8" d="M73.06 344.57c-31.45-117.36 38.2-238 155.56-269.44L1091.2-156l166.69 622.08L182.8 754.14 73.07 344.57Z"/> + </g> + <g filter="url(#d)"> + <path fill="url(#e)" fill-opacity=".8" d="M130.76 328.07c-22.73-84.82 27.6-172 112.43-194.73l863.53-231.38 145.37 542.51L234.97 717.02 130.76 328.07Z"/> + </g> + <g filter="url(#f)"> + <path fill="url(#g)" fill-opacity=".8" d="M188.71 312.55c-14.15-52.82 17.2-107.1 70-121.25l863.55-231.4 127.94 477.48-959.16 257-102.32-381.84Z"/> + </g> + <g filter="url(#h)"> + <path fill="url(#i)" fill-opacity=".8" d="M246.93 297.98A40 40 0 0 1 275.2 249l862.57-231.12 103.79 387.33-901.2 241.48-93.44-348.7Z"/> + </g> + </g> + <defs> + <linearGradient id="c" x1="553.66" x2="720.34" y1="-11.97" y2="610.11" gradientUnits="userSpaceOnUse"> + <stop stop-color="#fff" stop-opacity=".25"/> + <stop offset="1" stop-color="#fff" stop-opacity=".1"/> + </linearGradient> + <linearGradient id="e" x1="598.16" x2="743.53" y1="38.22" y2="580.74" gradientUnits="userSpaceOnUse"> + <stop stop-color="#fff" stop-opacity=".25"/> + <stop offset="1" stop-color="#fff" stop-opacity=".1"/> + </linearGradient> + <linearGradient id="g" x1="642.67" x2="770.61" y1="88.42" y2="565.89" gradientUnits="userSpaceOnUse"> + <stop stop-color="#fff" stop-opacity=".25"/> + <stop offset="1" stop-color="#fff" stop-opacity=".1"/> + </linearGradient> + <linearGradient id="i" x1="687.18" x2="790.97" y1="138.61" y2="525.94" gradientUnits="userSpaceOnUse"> + <stop stop-color="#fff" stop-opacity=".25"/> + <stop offset="1" stop-color="#fff" stop-opacity=".1"/> + </linearGradient> + <filter id="b" width="1208.37" height="926.14" x="57.51" y="-164" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feGaussianBlur in="BackgroundImageFix" stdDeviation="4"/> + <feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_15773_6502"/> + <feBlend in="SourceGraphic" in2="effect1_backgroundBlur_15773_6502" result="shape"/> + </filter> + <filter id="d" width="1142.79" height="831.06" x="117.3" y="-106.05" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feGaussianBlur in="BackgroundImageFix" stdDeviation="4"/> + <feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_15773_6502"/> + <feBlend in="SourceGraphic" in2="effect1_backgroundBlur_15773_6502" result="shape"/> + </filter> + <filter id="f" width="1080.88" height="750.49" x="177.31" y="-48.09" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feGaussianBlur in="BackgroundImageFix" stdDeviation="4"/> + <feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_15773_6502"/> + <feBlend in="SourceGraphic" in2="effect1_backgroundBlur_15773_6502" result="shape"/> + </filter> + <filter id="h" width="1012.02" height="644.81" x="237.55" y="9.87" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"> + <feFlood flood-opacity="0" result="BackgroundImageFix"/> + <feGaussianBlur in="BackgroundImageFix" stdDeviation="4"/> + <feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_15773_6502"/> + <feBlend in="SourceGraphic" in2="effect1_backgroundBlur_15773_6502" result="shape"/> + </filter> + <clipPath id="a"> + <rect width="1091" height="395" fill="#fff" rx="8"/> + </clipPath> + </defs> +</svg> diff --git a/storybook/stories/tokens/components.tsx b/storybook/stories/tokens/components.tsx index 05c2b4bde85a21..1144bc10d625d3 100644 --- a/storybook/stories/tokens/components.tsx +++ b/storybook/stories/tokens/components.tsx @@ -4,9 +4,9 @@ // eslint-disable-next-line @typescript-eslint/no-restricted-imports import React from 'react'; -export const ElevationTable = ( { tokens } ) => { +export const TokensTable = ( { tokenCategory, tokens, applyTokenStyle } ) => { return ( - <table> + <table style={ { width: '100%' } }> <thead> <tr> <th>Token</th> @@ -36,12 +36,12 @@ export const ElevationTable = ( { tokens } ) => { </td> <td style={ { padding: '24px' } }> <div - aria-label={ `An square showing an example of the '${ name }' elevation styles` } + aria-label={ `A shape showing an example of the '${ name }' ${ tokenCategory } token` } style={ { width: '100px', height: '100px', - boxShadow: valueCode, background: 'white', + ...applyTokenStyle( valueCode ), } } ></div> </td> diff --git a/storybook/stories/tokens/elevation.mdx b/storybook/stories/tokens/elevation.mdx index 5bd7dbf79a2622..5afb7e75266c4a 100644 --- a/storybook/stories/tokens/elevation.mdx +++ b/storybook/stories/tokens/elevation.mdx @@ -1,5 +1,5 @@ import { Meta } from '@storybook/addon-docs/blocks'; -import { ElevationTable } from './components.tsx'; +import { TokensTable } from './components.tsx'; <Meta title="Tokens/Elevation" name="page" /> @@ -11,7 +11,8 @@ This document outlines the various tokens relating to [elevation](?path=/docs/fo Tokens can be used in different ways, but regardless of which method is used, each one is meant to be used as the value of the CSS `box-shadow` property, and references the following values: -<ElevationTable +<TokensTable + tokenCategory="elevation" tokens={ [ { name: 'Extra small', @@ -42,6 +43,7 @@ Tokens can be used in different ways, but regardless of which method is used, ea '0 5px 15px rgba(0, 0, 0, 0.08), 0 15px 27px rgba(0, 0, 0, 0.07), 0 30px 36px rgba(0, 0, 0, 0.04), 0 50px 43px rgba(0, 0, 0, 0.02)', }, ] } + applyTokenStyle={ ( valueCode ) => ( { boxShadow: valueCode } ) } /> ## CSS tokens diff --git a/storybook/stories/tokens/radius.mdx b/storybook/stories/tokens/radius.mdx new file mode 100644 index 00000000000000..49eeb4a3c312b9 --- /dev/null +++ b/storybook/stories/tokens/radius.mdx @@ -0,0 +1,105 @@ +import { Meta } from '@storybook/blocks'; +import { TokensTable } from './components.tsx'; + +<Meta title="Tokens/Radius" name="page" /> + +# Radius + +This document outlines the various tokens relating to radius in the WordPress design system. + +## Values + +Tokens can be used in different ways, but regardless of which method is used, each one is meant to be used as the value of the CSS `border-radius` property, and references the following values: + +<TokensTable + tokenCategory="radius" + tokens={ [ + { + name: 'Extra small', + valueShow: '1px', + valueCode: '1px', + }, + { + name: 'Small', + valueShow: '2px', + valueCode: '2px', + }, + { + name: 'Medium', + valueShow: '4px', + valueCode: '4px', + }, + { + name: 'Large', + valueShow: '8px', + valueCode: '8px', + }, + { + name: 'Full', + valueShow: '9999px', + valueCode: '9999px', + }, + { + name: 'Round', + valueShow: '100%', + valueCode: '100%', + }, + ] } + applyTokenStyle={ ( valueCode ) => ( { + borderRadius: valueCode, + border: '1px solid #1e1e1e', + } ) } +/> + +## CSS tokens + +Radius tokens are defined as SASS variables: + +- `$radius-x-small` +- `$radius-small` +- `$radius-medium` +- `$radius-large` +- `$radius-full` +- `$radius-round` + +They can be used like so: + +```css +.radius-extra-small { + border-radius: $radius-x-small; +} +.radius-small { + border-radius: $radius-small; +} +.radius-medium { + border-radius: $radius-medium; +} +.radius-large { + border-radius: $radius-large; +} +.radius-full { + border-radius: $radius-full; +} +.radius-round { + border-radius: $radius-round; +} +``` + +## JS tokens + +When working in the `@wordpress/components` package, the radius tokens can also be consumed as JavaScript variables via the `CONFIG` object found in the `packages/components/src/utils/index.js` file: + +- `CONFIG.radiusXSmall` +- `CONFIG.radiusSmall` +- `CONFIG.radiusMedium` +- `CONFIG.radiusLarge` +- `CONFIG.radiusFull` +- `CONFIG.radiusRound` + +```js +// Note: the `CONFIG` object is only available within the `@wordpress/components` package. +import { CONFIG } from '../utils'; + +// Later in the code: +border-radius: ${ CONFIG.radiusXSmall }; +``` From 5b7ac9ec2d57b9bdb28ea735d1be05484719ec92 Mon Sep 17 00:00:00 2001 From: Rudrakshi Gupta <109859631+rudrakshi-gupta@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:16:15 +0530 Subject: [PATCH 1320/1908] Add Transformation from Separator to Spacer (#66230) * Add a transform from the Separator block to the Spacer block * Add a transform from the Separator block to the Spacer block Feat #65492 * Add transformation from spacer to separator - Remove the default height of 50px after transformation to default 100px that of Spacer - Update the transform of blocks so that it retains anchor attribute * Add new transformation block titles in Test * Add new transformation block titles in Test * Add new transformation block titles in Test and resolve linting problem * Add new transformation block titles in Test and resolve linting problem * Update test suite snapshot for test [mobile] to pass successfully --------- Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: rudrakshi-gupta <rudrakshigupta@git.wordpress.org> --- .../__snapshots__/transforms.native.js.snap | 6 ++++++ .../src/separator/test/transforms.native.js | 2 +- .../block-library/src/separator/transforms.js | 11 ++++++++++ packages/block-library/src/spacer/index.js | 2 ++ .../__snapshots__/transforms.native.js.snap | 6 ++++++ .../src/spacer/test/transforms.native.js | 2 +- .../block-library/src/spacer/transforms.js | 20 +++++++++++++++++++ 7 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 packages/block-library/src/spacer/transforms.js diff --git a/packages/block-library/src/separator/test/__snapshots__/transforms.native.js.snap b/packages/block-library/src/separator/test/__snapshots__/transforms.native.js.snap index 8aa4a99b7a0381..6ffb73467852d9 100644 --- a/packages/block-library/src/separator/test/__snapshots__/transforms.native.js.snap +++ b/packages/block-library/src/separator/test/__snapshots__/transforms.native.js.snap @@ -17,3 +17,9 @@ exports[`Separator block transforms to Group block 1`] = ` <!-- /wp:separator --></div> <!-- /wp:group -->" `; + +exports[`Separator block transforms to Spacer block 1`] = ` +"<!-- wp:spacer --> +<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div> +<!-- /wp:spacer -->" +`; diff --git a/packages/block-library/src/separator/test/transforms.native.js b/packages/block-library/src/separator/test/transforms.native.js index f0873c7cd59e42..a5250025398d0e 100644 --- a/packages/block-library/src/separator/test/transforms.native.js +++ b/packages/block-library/src/separator/test/transforms.native.js @@ -16,7 +16,7 @@ const initialHtml = ` <!-- /wp:separator -->`; const transformsWithInnerBlocks = [ 'Columns', 'Group' ]; -const blockTransforms = [ ...transformsWithInnerBlocks ]; +const blockTransforms = [ 'Spacer', ...transformsWithInnerBlocks ]; setupCoreBlocks(); diff --git a/packages/block-library/src/separator/transforms.js b/packages/block-library/src/separator/transforms.js index 06d9d667caf63d..1f40cb5dba8b5e 100644 --- a/packages/block-library/src/separator/transforms.js +++ b/packages/block-library/src/separator/transforms.js @@ -18,6 +18,17 @@ const transforms = { }, }, ], + to: [ + { + type: 'block', + blocks: [ 'core/spacer' ], // Transform to Spacer. + transform: ( { anchor } ) => { + return createBlock( 'core/spacer', { + anchor: anchor || '', + } ); + }, + }, + ], }; export default transforms; diff --git a/packages/block-library/src/spacer/index.js b/packages/block-library/src/spacer/index.js index d77c51bc96cea2..d2a60e0cdc1602 100644 --- a/packages/block-library/src/spacer/index.js +++ b/packages/block-library/src/spacer/index.js @@ -10,6 +10,7 @@ import initBlock from '../utils/init-block'; import deprecated from './deprecated'; import edit from './edit'; import metadata from './block.json'; +import transforms from './transforms'; import save from './save'; const { name } = metadata; @@ -18,6 +19,7 @@ export { metadata, name }; export const settings = { icon, + transforms, edit, save, deprecated, diff --git a/packages/block-library/src/spacer/test/__snapshots__/transforms.native.js.snap b/packages/block-library/src/spacer/test/__snapshots__/transforms.native.js.snap index ce53012ff17e71..2427b0fb0f8559 100644 --- a/packages/block-library/src/spacer/test/__snapshots__/transforms.native.js.snap +++ b/packages/block-library/src/spacer/test/__snapshots__/transforms.native.js.snap @@ -17,3 +17,9 @@ exports[`Spacer block transforms to Group block 1`] = ` <!-- /wp:spacer --></div> <!-- /wp:group -->" `; + +exports[`Spacer block transforms to Separator block 1`] = ` +"<!-- wp:separator --> +<hr class="wp-block-separator has-alpha-channel-opacity"/> +<!-- /wp:separator -->" +`; diff --git a/packages/block-library/src/spacer/test/transforms.native.js b/packages/block-library/src/spacer/test/transforms.native.js index fc84004166775c..df8ff3bf237245 100644 --- a/packages/block-library/src/spacer/test/transforms.native.js +++ b/packages/block-library/src/spacer/test/transforms.native.js @@ -16,7 +16,7 @@ const initialHtml = ` <!-- /wp:spacer -->`; const transformsWithInnerBlocks = [ 'Columns', 'Group' ]; -const blockTransforms = [ ...transformsWithInnerBlocks ]; +const blockTransforms = [ 'Separator', ...transformsWithInnerBlocks ]; setupCoreBlocks(); diff --git a/packages/block-library/src/spacer/transforms.js b/packages/block-library/src/spacer/transforms.js new file mode 100644 index 00000000000000..ddd8afb2ef98d9 --- /dev/null +++ b/packages/block-library/src/spacer/transforms.js @@ -0,0 +1,20 @@ +/** + * WordPress dependencies + */ +import { createBlock } from '@wordpress/blocks'; + +const transforms = { + to: [ + { + type: 'block', + blocks: [ 'core/separator' ], // Transform to Separator. + transform: ( { anchor } ) => { + return createBlock( 'core/separator', { + anchor: anchor || '', + } ); + }, + }, + ], +}; + +export default transforms; From 335201b12f4f27262f65f81573ada27921ec3e27 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 24 Oct 2024 18:48:52 +0900 Subject: [PATCH 1321/1908] Search: Replace ButtonGroup usage with ToggleGroupControl (#65340) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/block-library/src/search/edit.js | 51 ++++++++++++----------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/packages/block-library/src/search/edit.js b/packages/block-library/src/search/edit.js index d4ed5b7e3a4055..b68914893c0e84 100644 --- a/packages/block-library/src/search/edit.js +++ b/packages/block-library/src/search/edit.js @@ -23,14 +23,14 @@ import { useEffect, useRef } from '@wordpress/element'; import { ToolbarDropdownMenu, ToolbarGroup, - Button, - ButtonGroup, ToolbarButton, ResizableBox, PanelBody, __experimentalVStack as VStack, __experimentalUseCustomUnits as useCustomUnits, __experimentalUnitControl as UnitControl, + __experimentalToggleGroupControl as ToggleGroupControl, + __experimentalToggleGroupControlOption as ToggleGroupControlOption, } from '@wordpress/components'; import { useInstanceId } from '@wordpress/compose'; import { Icon, search } from '@wordpress/icons'; @@ -58,6 +58,7 @@ import { // Used to calculate border radius adjustment to avoid "fat" corners when // button is placed inside wrapper. const DEFAULT_INNER_PADDING = '4px'; +const PERCENTAGE_WIDTHS = [ 25, 50, 75, 100 ]; export default function SearchEdit( { className, @@ -445,33 +446,35 @@ export default function SearchEdit( { value={ `${ width }${ widthUnit }` } units={ units } /> - <ButtonGroup - className="wp-block-search__components-button-group" // unused, kept for backwards compatibility - aria-label={ __( 'Percentage Width' ) } + <ToggleGroupControl + label={ __( 'Percentage Width' ) } + value={ + PERCENTAGE_WIDTHS.includes( width ) && + widthUnit === '%' + ? width + : undefined + } + hideLabelFromVision + onChange={ ( newWidth ) => { + setAttributes( { + width: newWidth, + widthUnit: '%', + } ); + } } + isBlock + __next40pxDefaultSize + __nextHasNoMarginBottom > - { [ 25, 50, 75, 100 ].map( ( widthValue ) => { + { PERCENTAGE_WIDTHS.map( ( widthValue ) => { return ( - <Button + <ToggleGroupControlOption key={ widthValue } - size="small" - variant={ - widthValue === width && - widthUnit === '%' - ? 'primary' - : undefined - } - onClick={ () => - setAttributes( { - width: widthValue, - widthUnit: '%', - } ) - } - > - { widthValue }% - </Button> + value={ widthValue } + label={ `${ widthValue }%` } + /> ); } ) } - </ButtonGroup> + </ToggleGroupControl> </VStack> </PanelBody> </InspectorControls> From a7e59f97fe8666739dbe521e29483364d4caed37 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 24 Oct 2024 13:08:47 +0300 Subject: [PATCH 1322/1908] ESLint: Fix a couple of React Compiler reassignment errors (#66331) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- .../src/components/list-view/branch.js | 14 ++++++++------ .../block-library/src/table-of-contents/edit.js | 10 +++++----- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/block-editor/src/components/list-view/branch.js b/packages/block-editor/src/components/list-view/branch.js index ebd1d5a36f5700..5df7134e125cdb 100644 --- a/packages/block-editor/src/components/list-view/branch.js +++ b/packages/block-editor/src/components/list-view/branch.js @@ -5,7 +5,7 @@ import { __experimentalTreeGridRow as TreeGridRow, __experimentalTreeGridCell as TreeGridCell, } from '@wordpress/components'; -import { memo } from '@wordpress/element'; +import { memo, useRef } from '@wordpress/element'; import { AsyncModeProvider, useSelect } from '@wordpress/data'; /** @@ -123,6 +123,8 @@ function ListViewBranch( props ) { draggedClientIds, } = useListViewContext(); + const nextPositionRef = useRef(); + if ( ! canParentExpand ) { return null; } @@ -133,7 +135,7 @@ function ListViewBranch( props ) { const blockCount = filteredBlocks.length; // The appender means an extra row in List View, so add 1 to the row count. const rowCount = showAppender ? blockCount + 1 : blockCount; - let nextPosition = listPosition; + nextPositionRef.current = listPosition; return ( <> @@ -141,7 +143,7 @@ function ListViewBranch( props ) { const { clientId, innerBlocks } = block; if ( index > 0 ) { - nextPosition += countBlocks( + nextPositionRef.current += countBlocks( filteredBlocks[ index - 1 ], expandedState, draggedClientIds, @@ -165,7 +167,7 @@ function ListViewBranch( props ) { } ); const { itemInView } = fixedListWindow; - const blockInView = itemInView( nextPosition ); + const blockInView = itemInView( nextPositionRef.current ); const position = index + 1; const updatedPath = @@ -218,7 +220,7 @@ function ListViewBranch( props ) { showBlockMovers={ showBlockMovers } path={ updatedPath } isExpanded={ isDragged ? false : shouldExpand } - listPosition={ nextPosition } + listPosition={ nextPositionRef.current } selectedClientIds={ selectedClientIds } isSyncedBranch={ syncedBranch } displacement={ displacement } @@ -239,7 +241,7 @@ function ListViewBranch( props ) { showBlockMovers={ showBlockMovers } level={ level + 1 } path={ updatedPath } - listPosition={ nextPosition + 1 } + listPosition={ nextPositionRef.current + 1 } fixedListWindow={ fixedListWindow } isBranchSelected={ isSelectedBranch } selectedClientIds={ selectedClientIds } diff --git a/packages/block-library/src/table-of-contents/edit.js b/packages/block-library/src/table-of-contents/edit.js index 121a8d7c8fc315..33d6e6896fb201 100644 --- a/packages/block-library/src/table-of-contents/edit.js +++ b/packages/block-library/src/table-of-contents/edit.js @@ -17,7 +17,7 @@ import { ToolbarGroup, } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; -import { renderToString } from '@wordpress/element'; +import { renderToString, useRef } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { useInstanceId } from '@wordpress/compose'; import { store as noticeStore } from '@wordpress/notices'; @@ -59,14 +59,14 @@ export default function TableOfContentsEdit( { // If a user clicks to a link prevent redirection and show a warning. const { createWarningNotice, removeNotice } = useDispatch( noticeStore ); - let noticeId; + const noticeIdRef = useRef(); const showRedirectionPreventedNotice = ( event ) => { event.preventDefault(); // Remove previous warning if any, to show one at a time per block. - removeNotice( noticeId ); - noticeId = `block-library/core/table-of-contents/redirection-prevented/${ instanceId }`; + removeNotice( noticeIdRef.current ); + noticeIdRef.current = `block-library/core/table-of-contents/redirection-prevented/${ instanceId }`; createWarningNotice( __( 'Links are disabled in the editor.' ), { - id: noticeId, + id: noticeIdRef.current, type: 'snackbar', } ); }; From 20e10fef8b80e5c96aeb7ff338f28a67b372413e Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 24 Oct 2024 20:25:28 +0900 Subject: [PATCH 1323/1908] Block Editor: Fix 'useInstanceId' hook reference (#66406) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/block-editor/src/hooks/style.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index 2dcc19f424b2cf..998d13cfd22247 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -376,10 +376,14 @@ const elementTypes = [ }, ]; +// Used for generating the instance ID +const STYLE_BLOCK_PROPS_REFERENCE = {}; + function useBlockProps( { name, style } ) { - const blockElementsContainerIdentifier = `wp-elements-${ useInstanceId( - useBlockProps - ) }`; + const blockElementsContainerIdentifier = useInstanceId( + STYLE_BLOCK_PROPS_REFERENCE, + 'wp-elements' + ); const baseElementSelector = `.${ blockElementsContainerIdentifier }`; const blockElementStyles = style?.elements; From 9c7847d7cf09df88c7c3118997bda8e8dba1785b Mon Sep 17 00:00:00 2001 From: Vrishabh Jasani <71686151+Vrishabhsk@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:58:06 +0400 Subject: [PATCH 1324/1908] Change text color to gray-800 to improve color contrast (#66360) Co-authored-by: Vrishabhsk <vrishabhsk@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- packages/edit-site/src/components/post-list/style.scss | 2 +- packages/editor/src/components/post-card-panel/style.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/post-list/style.scss b/packages/edit-site/src/components/post-list/style.scss index 895a02b3106725..db6a32408c7921 100644 --- a/packages/edit-site/src/components/post-list/style.scss +++ b/packages/edit-site/src/components/post-list/style.scss @@ -66,7 +66,7 @@ .edit-site-post-list__title-badge { background: $gray-100; - color: $gray-700; + color: $gray-800; padding: 0 $grid-unit-05; border-radius: $radius-small; font-size: 12px; diff --git a/packages/editor/src/components/post-card-panel/style.scss b/packages/editor/src/components/post-card-panel/style.scss index 73b638673f3e91..f69fe5aa00ad5f 100644 --- a/packages/editor/src/components/post-card-panel/style.scss +++ b/packages/editor/src/components/post-card-panel/style.scss @@ -44,7 +44,7 @@ .editor-post-card-panel__title-badge { background: $gray-100; - color: $gray-700; + color: $gray-800; padding: 0 $grid-unit-05; border-radius: $radius-small; font-size: 12px; From 87ab311b055fb28e34d872f715a85d017727d7bb Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 24 Oct 2024 21:01:36 +0900 Subject: [PATCH 1325/1908] Gallery: Fix React Comiler reassignment error (#66408) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/block-library/src/gallery/edit.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/block-library/src/gallery/edit.js b/packages/block-library/src/gallery/edit.js index 7a0cc1de53c387..d3ec2ce007e6a9 100644 --- a/packages/block-library/src/gallery/edit.js +++ b/packages/block-library/src/gallery/edit.js @@ -65,7 +65,7 @@ import useGetMedia from './use-get-media'; import GapStyles from './gap-styles'; const MAX_COLUMNS = 8; -let linkOptions = [ +const LINK_OPTIONS = [ { icon: customLink, label: __( 'Link images to attachment pages' ), @@ -117,13 +117,13 @@ export default function GalleryEdit( props ) { onFocus, } = props; - const lightboxSetting = useSettings( 'blocks.core/image.lightbox' )[ 0 ]; + const [ lightboxSetting ] = useSettings( 'blocks.core/image.lightbox' ); - if ( ! lightboxSetting?.allowEditing ) { - linkOptions = linkOptions.filter( - ( option ) => option.value !== LINK_DESTINATION_LIGHTBOX - ); - } + const linkOptions = ! lightboxSetting?.allowEditing + ? LINK_OPTIONS.filter( + ( option ) => option.value !== LINK_DESTINATION_LIGHTBOX + ) + : LINK_OPTIONS; const { columns, imageCrop, randomOrder, linkTarget, linkTo, sizeSlug } = attributes; From 0faf4c5753726db970c8ff6edf7e6a07ddc4baa0 Mon Sep 17 00:00:00 2001 From: Rinkal Pagdar <92097119+rinkalpagdar@users.noreply.github.com> Date: Thu, 24 Oct 2024 18:02:35 +0530 Subject: [PATCH 1326/1908] Border support added to comments (#66354) * Border support added to comments * css lint fix Co-authored-by: rinkalpagdar <rinkalpagdar@git.wordpress.org> --- .../block-library/src/comments/block.json | 24 ++++++++++++++++--- .../block-library/src/comments/style.scss | 5 +++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/packages/block-library/src/comments/block.json b/packages/block-library/src/comments/block.json index b35ea3505c816f..cbdf5b3725b84b 100644 --- a/packages/block-library/src/comments/block.json +++ b/packages/block-library/src/comments/block.json @@ -17,7 +17,10 @@ } }, "supports": { - "align": [ "wide", "full" ], + "align": [ + "wide", + "full" + ], "html": false, "color": { "gradients": true, @@ -45,8 +48,23 @@ "__experimentalDefaultControls": { "fontSize": true } + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } }, "editorStyle": "wp-block-comments-editor", - "usesContext": [ "postId", "postType" ] -} + "usesContext": [ + "postId", + "postType" + ] +} \ No newline at end of file diff --git a/packages/block-library/src/comments/style.scss b/packages/block-library/src/comments/style.scss index be8cf1e597f49f..081783db098ab1 100644 --- a/packages/block-library/src/comments/style.scss +++ b/packages/block-library/src/comments/style.scss @@ -13,7 +13,6 @@ } /* end utility classes */ - .navigation { &::after { content: ""; @@ -146,3 +145,7 @@ :where(.wp-block-post-comments input[type="submit"]) { border: none; } + +.wp-block-comments { + box-sizing: border-box; +} From 62e0e6f24d81cc1d73e06a0366f20a1dc3903f5b Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:38:32 +0300 Subject: [PATCH 1327/1908] Block Library: Cleanup unnecessary notice removal (#66409) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- packages/block-library/src/latest-posts/edit.js | 8 ++------ packages/block-library/src/table-of-contents/edit.js | 10 +++------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/packages/block-library/src/latest-posts/edit.js b/packages/block-library/src/latest-posts/edit.js index ab792ae0e353db..7914f10be6bde8 100644 --- a/packages/block-library/src/latest-posts/edit.js +++ b/packages/block-library/src/latest-posts/edit.js @@ -155,15 +155,11 @@ export default function LatestPostsEdit( { attributes, setAttributes } ) { ); // If a user clicks to a link prevent redirection and show a warning. - const { createWarningNotice, removeNotice } = useDispatch( noticeStore ); - let noticeId; + const { createWarningNotice } = useDispatch( noticeStore ); const showRedirectionPreventedNotice = ( event ) => { event.preventDefault(); - // Remove previous warning if any, to show one at a time per block. - removeNotice( noticeId ); - noticeId = `block-library/core/latest-posts/redirection-prevented/${ instanceId }`; createWarningNotice( __( 'Links are disabled in the editor.' ), { - id: noticeId, + id: `block-library/core/latest-posts/redirection-prevented/${ instanceId }`, type: 'snackbar', } ); }; diff --git a/packages/block-library/src/table-of-contents/edit.js b/packages/block-library/src/table-of-contents/edit.js index 33d6e6896fb201..c95b89200cb88c 100644 --- a/packages/block-library/src/table-of-contents/edit.js +++ b/packages/block-library/src/table-of-contents/edit.js @@ -17,7 +17,7 @@ import { ToolbarGroup, } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; -import { renderToString, useRef } from '@wordpress/element'; +import { renderToString } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { useInstanceId } from '@wordpress/compose'; import { store as noticeStore } from '@wordpress/notices'; @@ -58,15 +58,11 @@ export default function TableOfContentsEdit( { ); // If a user clicks to a link prevent redirection and show a warning. - const { createWarningNotice, removeNotice } = useDispatch( noticeStore ); - const noticeIdRef = useRef(); + const { createWarningNotice } = useDispatch( noticeStore ); const showRedirectionPreventedNotice = ( event ) => { event.preventDefault(); - // Remove previous warning if any, to show one at a time per block. - removeNotice( noticeIdRef.current ); - noticeIdRef.current = `block-library/core/table-of-contents/redirection-prevented/${ instanceId }`; createWarningNotice( __( 'Links are disabled in the editor.' ), { - id: noticeIdRef.current, + id: `block-library/core/table-of-contents/redirection-prevented/${ instanceId }`, type: 'snackbar', } ); }; From ae9db95750145767ef662e82a591992b5b1b5169 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 24 Oct 2024 22:34:56 +0900 Subject: [PATCH 1328/1908] Global Styles: Fix React Compiler variable mutation error (#66410) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../components/global-styles/shadows-edit-panel.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js index af5f3445a51190..7321e927fbbae3 100644 --- a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js +++ b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js @@ -301,18 +301,17 @@ function ShadowEditor( { shadow, onChange } ) { const shadowParts = useMemo( () => getShadowParts( shadow ), [ shadow ] ); const onChangeShadowPart = ( index, part ) => { - shadowParts[ index ] = part; - onChange( shadowParts.join( ', ' ) ); + const newShadowParts = [ ...shadowParts ]; + newShadowParts[ index ] = part; + onChange( newShadowParts.join( ', ' ) ); }; const onAddShadowPart = () => { - shadowParts.push( defaultShadow ); - onChange( shadowParts.join( ', ' ) ); + onChange( [ ...shadowParts, defaultShadow ].join( ', ' ) ); }; const onRemoveShadowPart = ( index ) => { - shadowParts.splice( index, 1 ); - onChange( shadowParts.join( ', ' ) ); + onChange( shadowParts.filter( ( p, i ) => i !== index ).join( ', ' ) ); }; return ( From 27b1d9d3a94ace5fe0a3fe4184feb490c788e899 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Thu, 24 Oct 2024 22:36:49 +0800 Subject: [PATCH 1329/1908] Zoom Out: Fix bouncy drop zones (#66399) * Also consider child elements of insertion point in `isInsertionPoint` function * Also disable the root block list when in zoom out mode * Consider situations where the sectionRoot is also the root * Update comment Co-authored-by: Dave Smith <getdavemail@gmail.com> * Fix lint --------- Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> --- .../src/components/inner-blocks/index.js | 14 ++++++++++---- .../src/components/use-block-drop-zone/index.js | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/inner-blocks/index.js b/packages/block-editor/src/components/inner-blocks/index.js index e79c188018cb50..ae587720278200 100644 --- a/packages/block-editor/src/components/inner-blocks/index.js +++ b/packages/block-editor/src/components/inner-blocks/index.js @@ -202,10 +202,17 @@ export function useInnerBlocksProps( props = {}, options = {} ) { getBlockSettings, getSectionRootClientId, } = unlock( select( blockEditorStore ) ); - let _isDropZoneDisabled; if ( ! clientId ) { - return { isDropZoneDisabled: _isDropZoneDisabled }; + const sectionRootClientId = getSectionRootClientId(); + // Disable the root drop zone when zoomed out and the section root client id + // is not the root block list (represented by an empty string). + // This avoids drag handling bugs caused by having two block lists acting as + // drop zones - the actual 'root' block list and the section root. + return { + isDropZoneDisabled: + isZoomOut() && sectionRootClientId !== '', + }; } const { hasBlockSupport, getBlockType } = select( blocksStore ); @@ -214,14 +221,13 @@ export function useInnerBlocksProps( props = {}, options = {} ) { const parentClientId = getBlockRootClientId( clientId ); const [ defaultLayout ] = getBlockSettings( clientId, 'layout' ); - _isDropZoneDisabled = blockEditingMode === 'disabled'; + let _isDropZoneDisabled = blockEditingMode === 'disabled'; if ( isZoomOut() ) { // In zoom out mode, we want to disable the drop zone for the sections. // The inner blocks belonging to the section drop zone is // already disabled by the blocks themselves being disabled. const sectionRootClientId = getSectionRootClientId(); - _isDropZoneDisabled = clientId !== sectionRootClientId; } 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 64424178461bcf..2a3e4948d40b3b 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 @@ -287,7 +287,7 @@ function isInsertionPoint( targetToCheck, ownerDocument ) { return !! ( defaultView && targetToCheck instanceof defaultView.HTMLElement && - targetToCheck.dataset.isInsertionPoint + targetToCheck.closest( '[data-is-insertion-point]' ) ); } From a712932fe11e885cb392365ca623a9e337e8e4da Mon Sep 17 00:00:00 2001 From: Nick Diego <nick.diego@automattic.com> Date: Thu, 24 Oct 2024 10:31:31 -0500 Subject: [PATCH 1330/1908] Remove meetings (#66421) Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> --- docs/contributors/code/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/contributors/code/README.md b/docs/contributors/code/README.md index 848aa8bc26bbd1..4c965e69dbcefa 100644 --- a/docs/contributors/code/README.md +++ b/docs/contributors/code/README.md @@ -4,13 +4,13 @@ A guide on how to get started contributing code to the Gutenberg project. ## Discussions -The [Make WordPress Core blog](https://make.wordpress.org/core/) is the primary spot for the latest information around WordPress development: including announcements, product goals, meeting notes, meeting agendas, and more. +The [Make WordPress Core blog](https://make.wordpress.org/core/) is the primary spot for the latest information around WordPress development, including announcements, product goals, meeting notes, meeting agendas, and more. -Real-time discussions for development take place in `#core-editor` and `#core-js` channels in [Make WordPress Slack](https://make.wordpress.org/chat) (registration required). Weekly meetings for the editor component are on Wednesdays at 14:00UTC, and for the JavaScript component on Tuesday at 15:00UTC, in their respective Slack channels. +Development discussions take place in real-time in the `#core-editor` and `#core-js` channels in [Make WordPress Slack](https://make.wordpress.org/chat) (registration required). ## Development Hub -The Gutenberg project uses GitHub for managing code and tracking issues. The main repository is at: [https://github.com/WordPress/gutenberg](https://github.com/WordPress/gutenberg). +The Gutenberg project uses GitHub to manage code and track issues. The main repository is at: [https://github.com/WordPress/gutenberg](https://github.com/WordPress/gutenberg). Browse [the issues list](https://github.com/wordpress/gutenberg/issues) to find issues to work on. The [good first issue](https://github.com/wordpress/gutenberg/issues?q=is%3Aopen+is%3Aissue+label%3A%22Good+First+Issue%22) and [good first review](https://github.com/WordPress/gutenberg/pulls?q=is%3Aopen+is%3Apr+label%3A%22Good+First+Review%22) labels are good starting points. From d2ba0dc79c9c3f9daf0a087a9425202a3d0d1420 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 24 Oct 2024 20:44:26 +0200 Subject: [PATCH 1331/1908] Site editor: remove "default" admin CSS (#66431) --- backport-changelog/6.8/7642.md | 3 +++ lib/compat/wordpress-6.8/remove-default-css.php | 11 +++++++++++ lib/load.php | 1 + 3 files changed, 15 insertions(+) create mode 100644 backport-changelog/6.8/7642.md create mode 100644 lib/compat/wordpress-6.8/remove-default-css.php diff --git a/backport-changelog/6.8/7642.md b/backport-changelog/6.8/7642.md new file mode 100644 index 00000000000000..f00d4a5473aac8 --- /dev/null +++ b/backport-changelog/6.8/7642.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7642 + +* https://github.com/WordPress/gutenberg/pull/66431 \ No newline at end of file diff --git a/lib/compat/wordpress-6.8/remove-default-css.php b/lib/compat/wordpress-6.8/remove-default-css.php new file mode 100644 index 00000000000000..1076d84f299214 --- /dev/null +++ b/lib/compat/wordpress-6.8/remove-default-css.php @@ -0,0 +1,11 @@ +<?php + +function gutenberg_remove_default_css( $hook ) { + // Maybe also remove on post.php when Gutenberg is enabled for posts. + if ( 'site-editor.php' !== $hook ) { + return; + } + wp_dequeue_style( 'colors' ); +} + +add_action( 'admin_enqueue_scripts', 'gutenberg_remove_default_css' ); diff --git a/lib/load.php b/lib/load.php index 2c8a0fd0347c92..b91118cbced985 100644 --- a/lib/load.php +++ b/lib/load.php @@ -47,6 +47,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.7/rest-api.php'; // WordPress 6.8 compat. + require __DIR__ . '/compat/wordpress-6.8/remove-default-css.php'; require __DIR__ . '/compat/wordpress-6.8/block-comments.php'; require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php'; From 187ef636d7b98882223ba8aaeb768a1d0d355c56 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 25 Oct 2024 11:26:29 +0900 Subject: [PATCH 1332/1908] Fix: JSON Schema Docgen doesn't work on Windows OS (#66414) * Fix: JSON Schema Docgen doesn't work on Windows OS * Update bin/api-docs/gen-theme-reference.mjs Co-authored-by: Jon Surrell <sirreal@users.noreply.github.com> * Lint --------- Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- bin/api-docs/gen-theme-reference.mjs | 29 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/bin/api-docs/gen-theme-reference.mjs b/bin/api-docs/gen-theme-reference.mjs index 6dc7791e288b9e..f50d194c17ee79 100644 --- a/bin/api-docs/gen-theme-reference.mjs +++ b/bin/api-docs/gen-theme-reference.mjs @@ -9,6 +9,7 @@ */ import fs from 'node:fs/promises'; import $RefParser from '@apidevtools/json-schema-ref-parser'; +import { fileURLToPath } from 'node:url'; /** * @typedef {import('@apidevtools/json-schema-ref-parser').JSONSchema} JSONSchema @@ -19,9 +20,8 @@ import $RefParser from '@apidevtools/json-schema-ref-parser'; * * @type {URL} */ -const THEME_JSON_SCHEMA_URL = new URL( - '../../schemas/json/theme.json', - import.meta.url +const THEME_JSON_SCHEMA_PATH = fileURLToPath( + new URL( '../../schemas/json/theme.json', import.meta.url ) ); /** @@ -29,9 +29,11 @@ const THEME_JSON_SCHEMA_URL = new URL( * * @type {URL} */ -const REFERENCE_DOC_URL = new URL( - '../../docs/reference-guides/theme-json-reference/theme-json-living.md', - import.meta.url +const REFERENCE_DOC_PATH = fileURLToPath( + new URL( + '../../docs/reference-guides/theme-json-reference/theme-json-living.md', + import.meta.url + ) ); /** @@ -265,15 +267,12 @@ function generateDocs( themeJson ) { * Main function. */ async function main() { - const themeJson = await $RefParser.dereference( - THEME_JSON_SCHEMA_URL.pathname, - { - parse: { binary: false, text: false, yaml: false }, - resolve: { external: false }, - } - ); + const themeJson = await $RefParser.dereference( THEME_JSON_SCHEMA_PATH, { + parse: { binary: false, text: false, yaml: false }, + resolve: { external: false }, + } ); - const themeJsonReference = await fs.readFile( REFERENCE_DOC_URL, { + const themeJsonReference = await fs.readFile( REFERENCE_DOC_PATH, { encoding: 'utf8', flag: 'r', } ); @@ -285,7 +284,7 @@ async function main() { `${ START_TOKEN }\n${ generatedDocs }\n${ END_TOKEN }` ); - await fs.writeFile( REFERENCE_DOC_URL, updatedThemeJsonReference, { + await fs.writeFile( REFERENCE_DOC_PATH, updatedThemeJsonReference, { encoding: 'utf8', } ); } From 268b0fe815bc8ad6861a9e3579e4bebf56fddc56 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Thu, 24 Oct 2024 19:33:52 -0700 Subject: [PATCH 1333/1908] Revise zoom layout shift fix (#66390) * Contain margins with BFC instead of border * Move to block canvas styles in the visual editor --------- Co-authored-by: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/block-editor/src/components/iframe/content.scss | 1 - packages/editor/src/components/visual-editor/index.js | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss index 1d01f84b5fd1fd..596c177eab2f32 100644 --- a/packages/block-editor/src/components/iframe/content.scss +++ b/packages/block-editor/src/components/iframe/content.scss @@ -1,6 +1,5 @@ .block-editor-iframe__body { position: relative; - border: 0.01px solid transparent; } .block-editor-iframe__html { diff --git a/packages/editor/src/components/visual-editor/index.js b/packages/editor/src/components/visual-editor/index.js index 133057d9f388f1..1c8eb5c3b77640 100644 --- a/packages/editor/src/components/visual-editor/index.js +++ b/packages/editor/src/components/visual-editor/index.js @@ -356,7 +356,10 @@ function VisualEditor( { return [ ...( styles ?? [] ), { - css: `.is-root-container{display:flow-root;${ + // Ensures margins of children are contained so that the body background paints behind them. + // Otherwise, the background of html (when zoomed out) would show there and appear broken. It’s + // important mostly for post-only views yet conceivably an issue in templated views too. + css: `:where(.block-editor-iframe__body){display:flow-root;}.is-root-container{display:flow-root;${ // Some themes will have `min-height: 100vh` for the root container, // which isn't a requirement in auto resize mode. enableResizing ? 'min-height:0!important;' : '' From 5b303212752f1419851b09cdf6bbb02efa47e5eb Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Fri, 25 Oct 2024 09:34:20 +0300 Subject: [PATCH 1334/1908] Zoom out: Add keyboard shortcut in editor (#66400) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> --- .../src/components/zoom-out-toggle/index.js | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/zoom-out-toggle/index.js b/packages/editor/src/components/zoom-out-toggle/index.js index 619cc06c689c0b..81506add699c97 100644 --- a/packages/editor/src/components/zoom-out-toggle/index.js +++ b/packages/editor/src/components/zoom-out-toggle/index.js @@ -3,11 +3,15 @@ */ import { Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; - +import { useEffect } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { square as zoomOutIcon } from '@wordpress/icons'; import { store as preferencesStore } from '@wordpress/preferences'; +import { + useShortcut, + store as keyboardShortcutsStore, +} from '@wordpress/keyboard-shortcuts'; /** * Internal dependencies @@ -26,6 +30,32 @@ const ZoomOutToggle = ( { disabled } ) => { const { resetZoomLevel, setZoomLevel } = unlock( useDispatch( blockEditorStore ) ); + const { registerShortcut, unregisterShortcut } = useDispatch( + keyboardShortcutsStore + ); + + useEffect( () => { + registerShortcut( { + name: 'core/editor/zoom', + category: 'global', + description: __( 'Enter or exit zoom out.' ), + keyCombination: { + modifier: 'primaryShift', + character: '0', + }, + } ); + return () => { + unregisterShortcut( 'core/editor/zoom' ); + }; + }, [ registerShortcut, unregisterShortcut ] ); + + useShortcut( 'core/editor/zoom', () => { + if ( isZoomOut ) { + resetZoomLevel(); + } else { + setZoomLevel( 'auto-scaled' ); + } + } ); const handleZoomOut = () => { if ( isZoomOut ) { From 8fab6ddfec7a7e5b5c051e5e23d94a71a6fcad2e Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 25 Oct 2024 12:07:01 +0400 Subject: [PATCH 1335/1908] Compose: Fix React Complier error for 'useCopyToClipboard' (#66444) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/compose/src/hooks/use-copy-to-clipboard/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/compose/src/hooks/use-copy-to-clipboard/index.js b/packages/compose/src/hooks/use-copy-to-clipboard/index.js index 94ab6048a4b467..fbd7b77fecc4ce 100644 --- a/packages/compose/src/hooks/use-copy-to-clipboard/index.js +++ b/packages/compose/src/hooks/use-copy-to-clipboard/index.js @@ -6,7 +6,7 @@ import Clipboard from 'clipboard'; /** * WordPress dependencies */ -import { useRef } from '@wordpress/element'; +import { useRef, useLayoutEffect } from '@wordpress/element'; /** * Internal dependencies @@ -20,7 +20,9 @@ import useRefEffect from '../use-ref-effect'; */ function useUpdatedRef( value ) { const ref = useRef( value ); - ref.current = value; + useLayoutEffect( () => { + ref.current = value; + }, [ value ] ); return ref; } From 351e0926138454cc97cba89e6ff68b8856169c8b Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 25 Oct 2024 12:27:15 +0400 Subject: [PATCH 1336/1908] Style Book: Fix React Compiler error (#66445) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../edit-site/src/components/style-book/index.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 93bbc6311c6865..8f4023777868ca 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -179,22 +179,20 @@ function StyleBook( { ( select ) => select( blockEditorStore ).getSettings(), [] ); + const [ globalStyles ] = useGlobalStylesOutputWithConfig( mergedConfig ); const settings = useMemo( () => ( { ...originalSettings, + styles: + ! isObjectEmpty( globalStyles ) && ! isObjectEmpty( userConfig ) + ? globalStyles + : originalSettings.styles, isPreviewMode: true, } ), - [ originalSettings ] + [ globalStyles, originalSettings, userConfig ] ); - const [ globalStyles ] = useGlobalStylesOutputWithConfig( mergedConfig ); - - settings.styles = - ! isObjectEmpty( globalStyles ) && ! isObjectEmpty( userConfig ) - ? globalStyles - : settings.styles; - return ( <EditorCanvasContainer onClose={ onClose } From 7dbe0be523a0a1e5e3bc52ccfcbb18c91d085f1f Mon Sep 17 00:00:00 2001 From: Jon Surrell <sirreal@users.noreply.github.com> Date: Fri, 25 Oct 2024 11:12:13 +0200 Subject: [PATCH 1337/1908] Documenation: Update documentation about build process changes (#66428) Document recent changes to the build system that change are requirements for publishing WordPress scripts and script modules. #65064 updated the way that script modules from packages are bundled for Gutenberg and WordPress. #66272 updated the way that scripts from packages are bundled for Gutenberg and WordPress. --------- Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: justintadlock <greenshady@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/README.md | 36 +++++++++++++++++++++++++++++--- packages/block-library/README.md | 15 ++++++++----- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/packages/README.md b/packages/README.md index 27efdf2d43ad52..cc2f34e38ac055 100644 --- a/packages/README.md +++ b/packages/README.md @@ -4,10 +4,11 @@ This repository uses [npm workspaces](https://docs.npmjs.com/cli/v10/using-npm/w ## Creating a New Package -When creating a new package, you need to provide at least the following: +When creating a new package, you need to provide at least the following. Packages bundled in Gutenberg or WordPress must include a `wpScript` and or `wpScriptModuleExports` field in their `package.json` file. See the details below. 1. `package.json` based on the template: - ```json + + ```jsonc { "name": "@wordpress/package-name", "version": "1.0.0-prerelease", @@ -32,10 +33,39 @@ When creating a new package, you need to provide at least the following: }, "publishConfig": { "access": "public" - } + }, + // Include this line to include the package as a WordPress script. + "wpScript": true, + // Include this line to include the package as a WordPress script module. + "wpScriptModuleExports": "./build-module/index.js" } ``` + This assumes that your code is located in the `src` folder and will be transpiled with `Babel`. + + For packages that should ship as a WordPress script, include `wpScript: true` in the `package.json` file. This tells the build system to bundle the package for use as a WordPress script. + + For packages that should ship as a WordPress script module, include a `wpScriptModuleExports` field the `package.json` file. The value of this field can be a string to expose a single script module, or an object with a [shape like the standard `exports` object](https://nodejs.org/docs/latest-v20.x/api/packages.html#subpath-exports) to expose multiple script modules from a single package: + + ```jsonc + { + "name": "@wordpress/example", + + // The string form exposes the `@wordpress/example` script module. + "wpScriptModuleExports": "./build-module/index.js", + + // Multiple sub-modules can be exposed by providing an object: + "wpScriptModuleExports": { + // Exposed as `@wordpress/example` script module. + ".": "./build-module/index.js", + // Exposed as `@wordpress/example/demo-block/view` script module. + "./demo-block/view": "./build-module/index.js" + } + } + ``` + + Both `wpScript` and `wpScriptModuleExports` may be included if the package exposes both a script and a script module. + 1. `README.md` file containing at least: - Package name - Package description diff --git a/packages/block-library/README.md b/packages/block-library/README.md index 28cf7471ed1f14..a6d1984cda98cc 100644 --- a/packages/block-library/README.md +++ b/packages/block-library/README.md @@ -98,21 +98,26 @@ To find out more about contributing to this package or Gutenberg as a whole, ple This file is used when using the option to register individual block from the `@wordpress/block-library` package. -4. If a `view.js` file (or a file prefixed with `view`, e.g. `view-example.js`) is present in the block's directory, this file will be built along other assets, making it available to load from the browser. You only need to reference a `view.min.js` (notice the different file extension) file in the `block.json` file as follows: +4. If the block exposes a script module on the front end, it must be included in the package's `package.json` file in the `wpScriptModules` object. This will include the script module when it's bundled for use in WordPress. See [the packages README for more details.](../README.md): ```json { - "viewScript": "file:./view.min.js" + "name": "@wordpress/block-library", + "wpScriptModuleExports": { + "./blinking-paragraph/view": "./build-module/blinking-paragraph/view.js", + "./image/view": "./build-module/image/view.js" + // Add any new script modules here. + } } ``` - This file will get automatically loaded when the static block is present on the front end. For dynamic block, you need to manually enqueue the view script in `render_callback` of the block, example: + For every dynamic block, you need to manually enqueue the view script module in `render_callback` of the block, example: ```php function render_block_core_blinking_paragraph( $attributes, $content ) { - $should_load_view_script = ! empty( $attributes['isInteractive'] ) && ! wp_script_is( 'wp-block-blinking-paragraph-view' ); + $should_load_view_script = ! empty( $attributes['isInteractive'] ); if ( $should_load_view_script ) { - wp_enqueue_script( 'wp-block-blinking-paragraph-view' ); + wp_enqueue_script_module( '@wordpress/block-library/blinking-paragraph' ); } return $content; From 2036d7ed957b1b83436a673824a7511cfc9ee5ba Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 25 Oct 2024 18:21:19 +0900 Subject: [PATCH 1338/1908] Button Block: Apply Stretch Styles Correctly (#64770) Unlinked contributors: joecsmalley. Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: ethanclevenger91 <eclev91@git.wordpress.org> Co-authored-by: jordesign <jordesign@git.wordpress.org> Co-authored-by: jennydupuy <jdy68@git.wordpress.org> --- packages/block-library/src/button/style.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/block-library/src/button/style.scss b/packages/block-library/src/button/style.scss index 42306cba0c984d..a8f625b95c3923 100644 --- a/packages/block-library/src/button/style.scss +++ b/packages/block-library/src/button/style.scss @@ -9,6 +9,9 @@ $blocks-block__margin: 0.5em; text-align: center; word-break: break-word; // overflow-wrap doesn't work well if a link is wrapped in the div, so use word-break here. box-sizing: border-box; + height: 100%; + width: 100%; + align-content: center; &.aligncenter { text-align: center; From 22a3bf5d32452850aabcc21da327f077cd3c5bfe Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 25 Oct 2024 13:28:22 +0400 Subject: [PATCH 1339/1908] Style Book: Avoid state/effect combo when generating values (#66446) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../edit-site/src/components/style-book/index.js | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 8f4023777868ca..e9660323b83734 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -24,13 +24,7 @@ import { import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { useSelect } from '@wordpress/data'; import { useResizeObserver } from '@wordpress/compose'; -import { - useMemo, - useState, - memo, - useContext, - useEffect, -} from '@wordpress/element'; +import { useMemo, useState, memo, useContext } from '@wordpress/element'; import { ENTER, SPACE } from '@wordpress/keycodes'; /** @@ -148,7 +142,7 @@ function StyleBook( { const [ textColor ] = useGlobalStyle( 'color.text' ); const [ backgroundColor ] = useGlobalStyle( 'color.background' ); const colors = useMultiOriginPalettes(); - const [ examples, setExamples ] = useState( () => getExamples( colors ) ); + const examples = useMemo( () => getExamples( colors ), [ colors ] ); const tabs = useMemo( () => getTopLevelStyleBookCategories().filter( ( category ) => @@ -159,11 +153,6 @@ function StyleBook( { [ examples ] ); - // Ensure color examples are kept in sync with Global Styles palette changes. - useEffect( () => { - setExamples( getExamples( colors ) ); - }, [ colors ] ); - const { base: baseConfig } = useContext( GlobalStylesContext ); const mergedConfig = useMemo( () => { From 808195d9331e18d6973ec268fa9111194e14bdf6 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 25 Oct 2024 11:54:55 +0200 Subject: [PATCH 1340/1908] Tabs and ToggleGroupControl: round indicator size (#66426) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> --- packages/components/CHANGELOG.md | 5 +++-- packages/components/src/tabs/tablist.tsx | 1 + .../toggle-group-control/component.tsx | 1 + .../src/utils/hooks/use-animated-offset-rect.ts | 14 +++++++++++++- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index b149172bd10376..a3f7831e2af781 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,7 @@ - `ColorPalette`: prevent overflow of custom color button background ([#66152](https://github.com/WordPress/gutenberg/pull/66152)). - `RadioGroup`: Fix arrow key navigation in RTL ([#66202](https://github.com/WordPress/gutenberg/pull/66202)). +- `Tabs` and `ToggleGroupControl`: round indicator size ([#66426](https://github.com/WordPress/gutenberg/pull/66426)). ### Enhancements @@ -40,8 +41,8 @@ - `Modal`: Modal dialog small improvement for elementShouldBeHidden ([#65941](https://github.com/WordPress/gutenberg/pull/65941)). - `Tabs`: revamped vertical orientation styles ([#65387](https://github.com/WordPress/gutenberg/pull/65387)). -- `ComboboxControl`: display `No items found` when there are no matches found ([#66142](https://github.com/WordPress/gutenberg/pull/66142)) -- `FormTokenField`: display `No items found` when there are no matches found. This occurs when the `__experimentalExpandOnFocus` prop is enabled ([#66142](https://github.com/WordPress/gutenberg/pull/66142)) +- `ComboboxControl`: display `No items found` when there are no matches found ([#66142](https://github.com/WordPress/gutenberg/pull/66142)) +- `FormTokenField`: display `No items found` when there are no matches found. This occurs when the `__experimentalExpandOnFocus` prop is enabled ([#66142](https://github.com/WordPress/gutenberg/pull/66142)) ## 28.9.0 (2024-10-03) diff --git a/packages/components/src/tabs/tablist.tsx b/packages/components/src/tabs/tablist.tsx index 181c705e7148cf..2f736d6b95441c 100644 --- a/packages/components/src/tabs/tablist.tsx +++ b/packages/components/src/tabs/tablist.tsx @@ -93,6 +93,7 @@ export const TabList = forwardRef< prefix: 'selected', dataAttribute: 'indicator-animated', transitionEndFilter: ( event ) => event.pseudoElement === '::before', + roundRect: true, } ); // Make sure selected tab is scrolled into view. diff --git a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx index 0b4c22d7df9298..7f384f70ae1dc5 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx @@ -58,6 +58,7 @@ function UnconnectedToggleGroupControl( prefix: 'selected', dataAttribute: 'indicator-animated', transitionEndFilter: ( event ) => event.pseudoElement === '::before', + roundRect: true, } ); const cx = useCx(); diff --git a/packages/components/src/utils/hooks/use-animated-offset-rect.ts b/packages/components/src/utils/hooks/use-animated-offset-rect.ts index 4056089738fe99..35e2a54aa02f2f 100644 --- a/packages/components/src/utils/hooks/use-animated-offset-rect.ts +++ b/packages/components/src/utils/hooks/use-animated-offset-rect.ts @@ -46,6 +46,7 @@ export function useAnimatedOffsetRect( prefix = 'subelement', dataAttribute = `${ prefix }-animated`, transitionEndFilter = () => true, + roundRect = false, }: { /** * The prefix used for the CSS variables, e.g. if `prefix` is `selected`, the @@ -72,6 +73,13 @@ export function useAnimatedOffsetRect( * @default () => true */ transitionEndFilter?: ( event: TransitionEvent ) => boolean; + /** + * Whether the `rect` measurements should be rounded down when applied + * to the CSS variables. This can be useful to avoid blurry animations or + * to avoid subpixel rendering issues. + * @default false + */ + roundRect?: boolean; } = {} ) { const setProperties = useEvent( () => { @@ -80,7 +88,11 @@ export function useAnimatedOffsetRect( property !== 'element' && container?.style.setProperty( `--${ prefix }-${ property }`, - String( rect[ property ] ) + String( + roundRect + ? Math.floor( rect[ property ] ) + : rect[ property ] + ) ) ); } ); From 51437a90ad2b4cc715c6ff5806e88176965dfe46 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 25 Oct 2024 19:11:46 +0900 Subject: [PATCH 1341/1908] HTML Block: Force HTML preview in view mode (#66440) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- packages/block-library/src/html/edit.js | 8 +++++++- packages/block-library/src/html/preview.js | 5 +++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/html/edit.js b/packages/block-library/src/html/edit.js index 5c57d73ae40f6c..9a1972d54b7e65 100644 --- a/packages/block-library/src/html/edit.js +++ b/packages/block-library/src/html/edit.js @@ -7,6 +7,7 @@ import { BlockControls, PlainText, useBlockProps, + store as blockEditorStore, } from '@wordpress/block-editor'; import { ToolbarButton, @@ -14,6 +15,7 @@ import { ToolbarGroup, VisuallyHidden, } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; import { useInstanceId } from '@wordpress/compose'; /** @@ -27,6 +29,10 @@ export default function HTMLEdit( { attributes, setAttributes, isSelected } ) { const instanceId = useInstanceId( HTMLEdit, 'html-edit-desc' ); + const isPreviewMode = useSelect( ( select ) => { + return select( blockEditorStore ).getSettings().isPreviewMode; + }, [] ); + function switchToPreview() { setIsPreview( true ); } @@ -58,7 +64,7 @@ export default function HTMLEdit( { attributes, setAttributes, isSelected } ) { </ToolbarButton> </ToolbarGroup> </BlockControls> - { isPreview || isDisabled ? ( + { isPreview || isPreviewMode || isDisabled ? ( <> <Preview content={ attributes.content } diff --git a/packages/block-library/src/html/preview.js b/packages/block-library/src/html/preview.js index d515c0119aa8db..eb24b00bc2352b 100644 --- a/packages/block-library/src/html/preview.js +++ b/packages/block-library/src/html/preview.js @@ -23,14 +23,15 @@ const DEFAULT_STYLES = ` export default function HTMLEditPreview( { content, isSelected } ) { const settingStyles = useSelect( - ( select ) => select( blockEditorStore ).getSettings().styles + ( select ) => select( blockEditorStore ).getSettings().styles, + [] ); const styles = useMemo( () => [ DEFAULT_STYLES, ...transformStyles( - settingStyles.filter( ( style ) => style.css ) + ( settingStyles ?? [] ).filter( ( style ) => style.css ) ), ], [ settingStyles ] From 56e011b31ff2e44b5a2df36a3fadfda4a5f7f19f Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 25 Oct 2024 13:13:31 +0300 Subject: [PATCH 1342/1908] ESLint: Stop disabling `react-hooks/exhaustive-deps` rule (#66324) * ESLint: Stop disabling react-hooks/exhaustive-deps rule * CHANGELOG * Add ref to dependencies * Retain some context in comments Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .eslintrc.js | 12 ---------- packages/components/CHANGELOG.md | 4 ++++ .../autocomplete/autocompleter-ui.native.js | 6 ++--- .../src/autocomplete/autocompleter-ui.tsx | 8 ++----- .../components/src/autocomplete/index.tsx | 3 +-- .../src/color-palette/index.native.js | 3 +-- .../src/color-picker/index.native.js | 1 - .../components/src/date-time/date/index.tsx | 1 - .../components/src/form-token-field/index.tsx | 3 --- .../navigation-screen.native.js | 8 +++---- .../bottom-sheet/sub-sheet/index.native.js | 4 +--- .../src/mobile/color-settings/index.native.js | 4 +--- .../color-settings/picker-screen.native.js | 4 +--- .../src/mobile/image/index.native.js | 4 +--- .../keyboard-avoiding-view/index.ios.js | 4 +--- .../link-picker/link-picker-results.native.js | 7 ++---- .../link-picker/link-picker-screen.native.js | 4 +--- .../src/mobile/link-settings/index.native.js | 24 +++++-------------- .../link-settings-screen.native.js | 4 +--- .../mobile/segmented-control/index.native.js | 8 ++----- .../use-unit-converter-to-mobile.native.js | 8 ++----- packages/components/src/navigation/index.tsx | 3 +-- .../item/use-navigation-tree-item.tsx | 4 ++-- .../src/navigation/menu/menu-title-search.tsx | 4 ++-- .../menu/use-navigation-tree-menu.tsx | 4 ++-- .../components/src/sandbox/index.native.js | 4 +--- packages/components/src/sandbox/index.tsx | 9 +++---- .../src/search-control/index.native.js | 4 +--- .../src/slot-fill/bubbles-virtually/slot.tsx | 3 +-- packages/components/src/slot-fill/fill.ts | 9 +++---- .../src/tools-panel/tools-panel-item/hook.ts | 2 -- .../components/src/tooltip/index.native.js | 20 ++++------------ .../src/unit-control/index.native.js | 8 ++----- packages/components/src/utils/element-rect.ts | 1 - .../src/utils/hooks/use-update-effect.js | 2 -- 35 files changed, 55 insertions(+), 146 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 211ddd9bc35860..dfe779b4683523 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -356,18 +356,6 @@ module.exports = { ], }, }, - { - files: [ - // Components package. - 'packages/components/src/**/*.[tj]s?(x)', - // Navigation block. - 'packages/block-library/src/navigation/**/*.[tj]s?(x)', - ], - excludedFiles: [ ...developmentFiles ], - rules: { - 'react-hooks/exhaustive-deps': 'error', - }, - }, { files: [ 'packages/jest*/**/*.js', '**/test/**/*.js' ], excludedFiles: [ 'test/e2e/**/*.js', 'test/performance/**/*.js' ], diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index a3f7831e2af781..2025a550d55e0f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -21,6 +21,10 @@ - `Tabs` and `TabPanel`: Fix arrow key navigation in RTL ([#66201](https://github.com/WordPress/gutenberg/pull/66201)). - `Tabs`: override tablist's tabindex only when necessary ([#66209](https://github.com/WordPress/gutenberg/pull/66209)). +### Internal + +- ESLint: Stop disabling `react-hooks/exhaustive-deps` rule ([#66324](https://github.com/WordPress/gutenberg/pull/66324)). + ## 28.10.0 (2024-10-16) ### Bug Fixes diff --git a/packages/components/src/autocomplete/autocompleter-ui.native.js b/packages/components/src/autocomplete/autocompleter-ui.native.js index 1400c78e518d75..daf4fe301abf77 100644 --- a/packages/components/src/autocomplete/autocompleter-ui.native.js +++ b/packages/components/src/autocomplete/autocompleter-ui.native.js @@ -69,9 +69,8 @@ export function getAutoCompleterUI( autocompleter ) { } else if ( isVisible && text.length === 0 ) { startAnimation( false ); } - // Temporarily disabling exhaustive-deps to avoid introducing unexpected side effecst. + // We want to avoid introducing unexpected side effects. // See https://github.com/WordPress/gutenberg/pull/41820 - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ items, isVisible, text ] ); const activeItemStyles = usePreferredColorSchemeStyle( @@ -112,9 +111,8 @@ export function getAutoCompleterUI( autocompleter ) { } } ); }, - // Temporarily disabling exhaustive-deps to avoid introducing unexpected side effecst. + // We want to avoid introducing unexpected side effects. // See https://github.com/WordPress/gutenberg/pull/41820 - // eslint-disable-next-line react-hooks/exhaustive-deps [ isVisible ] ); diff --git a/packages/components/src/autocomplete/autocompleter-ui.tsx b/packages/components/src/autocomplete/autocompleter-ui.tsx index c6c1b94deb577e..69105f6c9d3b44 100644 --- a/packages/components/src/autocomplete/autocompleter-ui.tsx +++ b/packages/components/src/autocomplete/autocompleter-ui.tsx @@ -165,9 +165,8 @@ export function getAutoCompleterUI( autocompleter: WPCompleter ) { useLayoutEffect( () => { onChangeOptions( items ); announce( items ); - // Temporarily disabling exhaustive-deps to avoid introducing unexpected side effecst. + // We want to avoid introducing unexpected side effects. // See https://github.com/WordPress/gutenberg/pull/41820 - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ items ] ); if ( items.length === 0 ) { @@ -235,8 +234,5 @@ function useOnClickOutside( document.removeEventListener( 'mousedown', listener ); document.removeEventListener( 'touchstart', listener ); }; - // Disable reason: `ref` is a ref object and should not be included in a - // hook's dependency list. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ handler ] ); + }, [ handler, ref ] ); } diff --git a/packages/components/src/autocomplete/index.tsx b/packages/components/src/autocomplete/index.tsx index ad930d3affdd14..f3278a46015c3c 100644 --- a/packages/components/src/autocomplete/index.tsx +++ b/packages/components/src/autocomplete/index.tsx @@ -380,9 +380,8 @@ export function useAutocomplete( { : AutocompleterUI ); setFilterValue( query === null ? '' : query ); - // Temporarily disabling exhaustive-deps to avoid introducing unexpected side effecst. + // We want to avoid introducing unexpected side effects. // See https://github.com/WordPress/gutenberg/pull/41820 - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ textContent ] ); const { key: selectedKey = '' } = filteredOptions[ selectedIndex ] || {}; diff --git a/packages/components/src/color-palette/index.native.js b/packages/components/src/color-palette/index.native.js index bb45de6d66e884..ab86cd6f05f127 100644 --- a/packages/components/src/color-palette/index.native.js +++ b/packages/components/src/color-palette/index.native.js @@ -115,9 +115,8 @@ function ColorPalette( { scrollViewRef.current.scrollTo( { x: 0, y: 0 } ); } } - // Temporarily disabling exhuastive-deps until the component can be refactored and updated safely. + // Not adding additional dependencies until the component can be refactored and updated safely. // Please see https://github.com/WordPress/gutenberg/pull/41253 for discussion and details. - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ currentSegment ] ); function isSelectedCustom() { diff --git a/packages/components/src/color-picker/index.native.js b/packages/components/src/color-picker/index.native.js index 46059a58520ba9..302de6b7d79b89 100644 --- a/packages/components/src/color-picker/index.native.js +++ b/packages/components/src/color-picker/index.native.js @@ -111,7 +111,6 @@ function ColorPicker( { // the hook’s dependencies and running it a single time. Ideally there // may be a way to refactor and obviate the disabled lint rule. If not, // this comment should be replaced by one that explains the reasoning. - // eslint-disable-next-line react-hooks/exhaustive-deps }, [] ); function onButtonPress( action ) { diff --git a/packages/components/src/date-time/date/index.tsx b/packages/components/src/date-time/date/index.tsx index 5a565ee38cec59..ca093f9d70847b 100644 --- a/packages/components/src/date-time/date/index.tsx +++ b/packages/components/src/date-time/date/index.tsx @@ -302,7 +302,6 @@ function Day( { } // isFocusAllowed is not a dep as there is no point calling focus() on // an already focused element. - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ isFocusable ] ); return ( diff --git a/packages/components/src/form-token-field/index.tsx b/packages/components/src/form-token-field/index.tsx index 9f05dfee008da0..4f2f325e409a76 100644 --- a/packages/components/src/form-token-field/index.tsx +++ b/packages/components/src/form-token-field/index.tsx @@ -124,17 +124,14 @@ export function FormTokenField( props: FormTokenFieldProps ) { } // TODO: updateSuggestions() should first be refactored so its actual deps are clearer. - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ suggestions, prevSuggestions, value, prevValue ] ); useEffect( () => { updateSuggestions(); - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ incompleteTokenValue ] ); useEffect( () => { updateSuggestions(); - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ __experimentalAutoSelectFirstMatch ] ); if ( disabled && isActive ) { diff --git a/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js index d5defc14dd475d..8c43bc85612762 100644 --- a/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js +++ b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js @@ -71,9 +71,9 @@ const BottomSheetNavigationScreen = ( { * callbacks triggered based upon which screen is currently active. * * Related: https://github.com/WordPress/gutenberg/pull/36328#discussion_r768897546 + * + * Also see https://github.com/WordPress/gutenberg/pull/41166. */ - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps }, [] ) ); @@ -130,9 +130,7 @@ const BottomSheetNavigationScreen = ( { </TouchableHighlight> </ScrollView> ); - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ children, isFocused, diff --git a/packages/components/src/mobile/bottom-sheet/sub-sheet/index.native.js b/packages/components/src/mobile/bottom-sheet/sub-sheet/index.native.js index d46b10cfb560f1..14040be0cc239e 100644 --- a/packages/components/src/mobile/bottom-sheet/sub-sheet/index.native.js +++ b/packages/components/src/mobile/bottom-sheet/sub-sheet/index.native.js @@ -28,9 +28,7 @@ const BottomSheetSubSheet = ( { if ( showSheet ) { setIsFullScreen( isFullScreen ); } - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ showSheet, isFullScreen ] ); return ( diff --git a/packages/components/src/mobile/color-settings/index.native.js b/packages/components/src/mobile/color-settings/index.native.js index 10cf776ed808c2..c7956df0e935dd 100644 --- a/packages/components/src/mobile/color-settings/index.native.js +++ b/packages/components/src/mobile/color-settings/index.native.js @@ -35,9 +35,7 @@ const ColorSettingsMemo = memo( useEffect( () => { shouldEnableBottomSheetMaxHeight( true ); onHandleClosingBottomSheet( null ); - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [] ); return ( <BottomSheet.NavigationContainer> diff --git a/packages/components/src/mobile/color-settings/picker-screen.native.js b/packages/components/src/mobile/color-settings/picker-screen.native.js index 2d505621f6eda1..e924580d939794 100644 --- a/packages/components/src/mobile/color-settings/picker-screen.native.js +++ b/packages/components/src/mobile/color-settings/picker-screen.native.js @@ -43,9 +43,7 @@ const PickerScreen = () => { onHandleHardwareButtonPress={ onHandleHardwareButtonPress } /> ); - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ setColor, currentValue, diff --git a/packages/components/src/mobile/image/index.native.js b/packages/components/src/mobile/image/index.native.js index 9f8673b7bdcdff..3c7e4ddc19c006 100644 --- a/packages/components/src/mobile/image/index.native.js +++ b/packages/components/src/mobile/image/index.native.js @@ -112,9 +112,7 @@ const ImageComponent = ( { } } return () => ( isCurrent = false ); - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ url ] ); const onContainerLayout = ( event ) => { diff --git a/packages/components/src/mobile/keyboard-avoiding-view/index.ios.js b/packages/components/src/mobile/keyboard-avoiding-view/index.ios.js index f13e7d329874fd..7630fd21fbc429 100644 --- a/packages/components/src/mobile/keyboard-avoiding-view/index.ios.js +++ b/packages/components/src/mobile/keyboard-avoiding-view/index.ios.js @@ -69,9 +69,7 @@ export const KeyboardAvoidingView = ( { keyboardShowSubscription.remove(); keyboardHideSubscription.remove(); }; - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [] ); function onSafeAreaInsetsUpdate( { safeAreaInsets } ) { diff --git a/packages/components/src/mobile/link-picker/link-picker-results.native.js b/packages/components/src/mobile/link-picker/link-picker-results.native.js index 1d411b97ff0667..4751ebc1ee2111 100644 --- a/packages/components/src/mobile/link-picker/link-picker-results.native.js +++ b/packages/components/src/mobile/link-picker/link-picker-results.native.js @@ -75,9 +75,8 @@ export default function LinkPickerResults( { return { fetchMoreSuggestions: debounce( fetchMore, REQUEST_DEBOUNCE_DELAY ), }; - // Disable eslint rule for now, to avoid introducing a regression + // Not adding dependencies for now, to avoid introducing a regression // (see https://github.com/WordPress/gutenberg/pull/23922#discussion_r1170634879). - // eslint-disable-next-line react-hooks/exhaustive-deps }, [] ); // Prevent setting state when unmounted. @@ -90,9 +89,7 @@ export default function LinkPickerResults( { setHasAllSuggestions( false ); setLinks( [ directEntry ] ); fetchMoreSuggestions( { query, links: [ directEntry ] } ); - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ query ] ); const onEndReached = () => fetchMoreSuggestions( { query, links } ); diff --git a/packages/components/src/mobile/link-picker/link-picker-screen.native.js b/packages/components/src/mobile/link-picker/link-picker-screen.native.js index 7bc1dbd7009b62..999c9053c59862 100644 --- a/packages/components/src/mobile/link-picker/link-picker-screen.native.js +++ b/packages/components/src/mobile/link-picker/link-picker-screen.native.js @@ -53,9 +53,7 @@ const LinkPickerScreen = ( { returnScreenName } ) => { onCancel={ onCancel } /> ); - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ inputValue ] ); }; diff --git a/packages/components/src/mobile/link-settings/index.native.js b/packages/components/src/mobile/link-settings/index.native.js index e80672a3103fa6..a01e33b410a5c0 100644 --- a/packages/components/src/mobile/link-settings/index.native.js +++ b/packages/components/src/mobile/link-settings/index.native.js @@ -101,9 +101,7 @@ function LinkSettings( { if ( onHandleClosingBottomSheet ) { onHandleClosingBottomSheet( onCloseSettingsSheet ); } - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ urlInputValue, labelInputValue, linkRelInputValue ] ); useEffect( () => { @@ -115,9 +113,7 @@ function LinkSettings( { if ( url !== urlInputValue ) { setUrlInputValue( url || '' ); } - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ url ] ); useEffect( () => { @@ -141,9 +137,7 @@ function LinkSettings( { if ( prevEditorSidebarOpened && ! editorSidebarOpened ) { onSetAttributes(); } - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ editorSidebarOpened, isVisible ] ); useEffect( () => { @@ -156,9 +150,7 @@ function LinkSettings( { url: prependHTTP( urlValue ), } ); } - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ urlValue ] ); const onChangeURL = useCallback( @@ -188,9 +180,7 @@ function LinkSettings( { rel: linkRelInputValue, } ); } - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ urlInputValue, labelInputValue, linkRelInputValue, setAttributes ] ); const onCloseSettingsSheet = useCallback( () => { @@ -223,9 +213,7 @@ function LinkSettings( { rel: updatedRel, } ); }, - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 [ linkRelInputValue ] ); diff --git a/packages/components/src/mobile/link-settings/link-settings-screen.native.js b/packages/components/src/mobile/link-settings/link-settings-screen.native.js index d04bd0699b7a54..7147becd67b22d 100644 --- a/packages/components/src/mobile/link-settings/link-settings-screen.native.js +++ b/packages/components/src/mobile/link-settings/link-settings-screen.native.js @@ -37,9 +37,7 @@ const LinkSettingsScreen = ( props ) => { urlValue={ inputValue } /> ); - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ props, inputValue, navigation, route ] ); }; diff --git a/packages/components/src/mobile/segmented-control/index.native.js b/packages/components/src/mobile/segmented-control/index.native.js index 49d46b8cd08beb..36b92bb0d4ea32 100644 --- a/packages/components/src/mobile/segmented-control/index.native.js +++ b/packages/components/src/mobile/segmented-control/index.native.js @@ -74,18 +74,14 @@ const SegmentedControls = ( { useEffect( () => { setActiveSegmentIndex( selectedSegmentIndex ); segmentHandler( segments[ selectedSegmentIndex ] ); - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [] ); useEffect( () => { positionAnimationValue.setValue( calculateEndValue( activeSegmentIndex ) ); - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ segmentsDimensions ] ); const containerStyle = usePreferredColorSchemeStyle( diff --git a/packages/components/src/mobile/utils/use-unit-converter-to-mobile.native.js b/packages/components/src/mobile/utils/use-unit-converter-to-mobile.native.js index 891f11f502ebfe..0b1dfd31147dee 100644 --- a/packages/components/src/mobile/utils/use-unit-converter-to-mobile.native.js +++ b/packages/components/src/mobile/utils/use-unit-converter-to-mobile.native.js @@ -66,9 +66,7 @@ const useConvertUnitToMobile = ( value, unit, styles ) => { return () => { dimensionsChangeSubscription.remove(); }; - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [] ); const onDimensionsChange = useCallback( ( { window } ) => { @@ -85,9 +83,7 @@ const useConvertUnitToMobile = ( value, unit, styles ) => { valueToConvert, valueUnit ); - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ windowSizes, value, unit ] ); }; diff --git a/packages/components/src/navigation/index.tsx b/packages/components/src/navigation/index.tsx index 0069369f3e00cb..92f431dfb22fc7 100644 --- a/packages/components/src/navigation/index.tsx +++ b/packages/components/src/navigation/index.tsx @@ -104,9 +104,8 @@ export function Navigation( { if ( activeMenu !== menu ) { setActiveMenu( activeMenu ); } - // Ignore exhaustive-deps here, as it would require either a larger refactor or some questionable workarounds. + // Not adding deps for now, as it would require either a larger refactor or some questionable workarounds. // See https://github.com/WordPress/gutenberg/pull/41612 for context. - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ activeMenu ] ); const context = { diff --git a/packages/components/src/navigation/item/use-navigation-tree-item.tsx b/packages/components/src/navigation/item/use-navigation-tree-item.tsx index e294af4169517e..335e55f2401bf4 100644 --- a/packages/components/src/navigation/item/use-navigation-tree-item.tsx +++ b/packages/components/src/navigation/item/use-navigation-tree-item.tsx @@ -41,7 +41,7 @@ export const useNavigationTreeItem = ( return () => { removeItem( itemId ); }; - // Ignore exhaustive-deps rule for now. See https://github.com/WordPress/gutenberg/pull/41639 - // eslint-disable-next-line react-hooks/exhaustive-deps + // Not adding deps for now, as it would require either a larger refactor. + // See https://github.com/WordPress/gutenberg/pull/41639 }, [ activeMenu, search ] ); }; diff --git a/packages/components/src/navigation/menu/menu-title-search.tsx b/packages/components/src/navigation/menu/menu-title-search.tsx index c1dbda5af88fb0..f0014fa4768046 100644 --- a/packages/components/src/navigation/menu/menu-title-search.tsx +++ b/packages/components/src/navigation/menu/menu-title-search.tsx @@ -55,8 +55,8 @@ function MenuTitleSearch( { count ); debouncedSpeak( resultsFoundMessage ); - // Ignore exhaustive-deps rule for now. See https://github.com/WordPress/gutenberg/pull/44090 - // eslint-disable-next-line react-hooks/exhaustive-deps + // Not adding deps for now, as it would require either a larger refactor. + // See https://github.com/WordPress/gutenberg/pull/44090 }, [ items, search ] ); const onClose = () => { diff --git a/packages/components/src/navigation/menu/use-navigation-tree-menu.tsx b/packages/components/src/navigation/menu/use-navigation-tree-menu.tsx index 1db2ee87fa7847..8631812445cd7d 100644 --- a/packages/components/src/navigation/menu/use-navigation-tree-menu.tsx +++ b/packages/components/src/navigation/menu/use-navigation-tree-menu.tsx @@ -23,7 +23,7 @@ export const useNavigationTreeMenu = ( props: NavigationMenuProps ) => { return () => { removeMenu( key ); }; - // Ignore exhaustive-deps rule for now. See https://github.com/WordPress/gutenberg/pull/44090 - // eslint-disable-next-line react-hooks/exhaustive-deps + // Not adding deps for now, as it would require either a larger refactor + // See https://github.com/WordPress/gutenberg/pull/44090 }, [] ); }; diff --git a/packages/components/src/sandbox/index.native.js b/packages/components/src/sandbox/index.native.js index b9bbc9a4e3281f..72070bf6efcd08 100644 --- a/packages/components/src/sandbox/index.native.js +++ b/packages/components/src/sandbox/index.native.js @@ -336,9 +336,7 @@ const Sandbox = forwardRef( function Sandbox( useEffect( () => { updateContentHtml(); - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ html, title, type, styles, scripts ] ); useEffect( () => { diff --git a/packages/components/src/sandbox/index.tsx b/packages/components/src/sandbox/index.tsx index 4ad971cb63ca90..5288fea3f7e43e 100644 --- a/packages/components/src/sandbox/index.tsx +++ b/packages/components/src/sandbox/index.tsx @@ -262,23 +262,20 @@ function SandBox( { checkMessageForResize ); }; - // Ignore reason: passing `exhaustive-deps` will likely involve a more detailed refactor. + // Passing `exhaustive-deps` will likely involve a more detailed refactor. // See https://github.com/WordPress/gutenberg/pull/44378 - // eslint-disable-next-line react-hooks/exhaustive-deps }, [] ); useEffect( () => { trySandBox(); - // Ignore reason: passing `exhaustive-deps` will likely involve a more detailed refactor. + // Passing `exhaustive-deps` will likely involve a more detailed refactor. // See https://github.com/WordPress/gutenberg/pull/44378 - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ title, styles, scripts ] ); useEffect( () => { trySandBox( true ); - // Ignore reason: passing `exhaustive-deps` will likely involve a more detailed refactor. + // Passing `exhaustive-deps` will likely involve a more detailed refactor. // See https://github.com/WordPress/gutenberg/pull/44378 - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ html, type ] ); return ( diff --git a/packages/components/src/search-control/index.native.js b/packages/components/src/search-control/index.native.js index 8bff86049b0182..5bb03196d1de14 100644 --- a/packages/components/src/search-control/index.native.js +++ b/packages/components/src/search-control/index.native.js @@ -122,9 +122,7 @@ function SearchControl( { mergeFutureStyles( activeDarkStyles, [ isActive, isDark ] ); setCurrentStyles( futureStyles ); - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ isActive, isDark ] ); const clearInput = useCallback( () => { diff --git a/packages/components/src/slot-fill/bubbles-virtually/slot.tsx b/packages/components/src/slot-fill/bubbles-virtually/slot.tsx index e836782c906154..6ac2d51e1f857f 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/slot.tsx +++ b/packages/components/src/slot-fill/bubbles-virtually/slot.tsx @@ -49,11 +49,10 @@ function Slot( return () => { unregisterSlot( name, ref ); }; - // Ignore reason: We don't want to unregister and register the slot whenever + // We don't want to unregister and register the slot whenever // `fillProps` change, which would cause the fill to be re-mounted. Instead, // we can just update the slot (see hook below). // For more context, see https://github.com/WordPress/gutenberg/pull/44403#discussion_r994415973 - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ registerSlot, unregisterSlot, name ] ); // fillProps may be an update that interacts with the layout, so we // useLayoutEffect. diff --git a/packages/components/src/slot-fill/fill.ts b/packages/components/src/slot-fill/fill.ts index 6aefacc4ff6f18..4134af25684b07 100644 --- a/packages/components/src/slot-fill/fill.ts +++ b/packages/components/src/slot-fill/fill.ts @@ -23,9 +23,8 @@ export default function Fill( { name, children }: FillComponentProps ) { const refValue = ref.current; registerFill( name, refValue ); return () => unregisterFill( name, refValue ); - // Ignore reason: the useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior. + // The useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior. // We'll leave them as-is until a more detailed investigation/refactor can be performed. - // eslint-disable-next-line react-hooks/exhaustive-deps }, [] ); useLayoutEffect( () => { @@ -33,9 +32,8 @@ export default function Fill( { name, children }: FillComponentProps ) { if ( slot ) { slot.forceUpdate(); } - // Ignore reason: the useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior. + // The useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior. // We'll leave them as-is until a more detailed investigation/refactor can be performed. - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ children ] ); useLayoutEffect( () => { @@ -46,9 +44,8 @@ export default function Fill( { name, children }: FillComponentProps ) { unregisterFill( ref.current.name, ref.current ); ref.current.name = name; registerFill( name, ref.current ); - // Ignore reason: the useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior. + // The useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior. // We'll leave them as-is until a more detailed investigation/refactor can be performed. - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ name ] ); return null; diff --git a/packages/components/src/tools-panel/tools-panel-item/hook.ts b/packages/components/src/tools-panel/tools-panel-item/hook.ts index 1e33e7c6740ded..e0a1f0139dcace 100644 --- a/packages/components/src/tools-panel/tools-panel-item/hook.ts +++ b/packages/components/src/tools-panel/tools-panel-item/hook.ts @@ -54,11 +54,9 @@ export function useToolsPanelItem( // hasValue is a new function on every render, so do not add it as a // dependency to the useCallback hook! If needed, we should use a ref. - // eslint-disable-next-line react-hooks/exhaustive-deps const hasValueCallback = useCallback( hasValue, [ panelId ] ); // resetAllFilter is a new function on every render, so do not add it as a // dependency to the useCallback hook! If needed, we should use a ref. - // eslint-disable-next-line react-hooks/exhaustive-deps const resetAllFilterCallback = useCallback( resetAllFilter, [ panelId ] ); const previousPanelId = usePrevious( currentPanelId ); diff --git a/packages/components/src/tooltip/index.native.js b/packages/components/src/tooltip/index.native.js index 61b08c052dfacc..ff880d38e19822 100644 --- a/packages/components/src/tooltip/index.native.js +++ b/packages/components/src/tooltip/index.native.js @@ -62,9 +62,7 @@ const useKeyboardVisibility = () => { showListener.remove(); hideListener.remove(); }; - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [] ); return keyboardVisible; @@ -105,9 +103,7 @@ const Tooltip = ( { } ); } return () => onHandleScreenTouch( null ); - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ visible ] ); // Manage visibility animation. @@ -121,9 +117,7 @@ const Tooltip = ( { setAnimating( true ); startAnimation(); } - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ visible ] ); // Manage tooltip visibility and position in relation to keyboard. @@ -142,9 +136,7 @@ const Tooltip = ( { setAnimating( true ); setVisible( false ); } - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 }, [ visible, keyboardVisible ] ); // Manage tooltip position during keyboard frame changes. @@ -273,9 +265,7 @@ const TooltipSlot = ( { children, ...rest } ) => { setHandleScreenTouch( null ); }; // Memoize context value to avoid unnecessary rerenders of the Provider's children - // Disable reason: deferring this refactor to the native team. - // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps + // See https://github.com/WordPress/gutenberg/pull/41166 const value = useMemo( () => ( { onHandleScreenTouch } ) ); return ( diff --git a/packages/components/src/unit-control/index.native.js b/packages/components/src/unit-control/index.native.js index a4c0b913f53432..4aae14de65779e 100644 --- a/packages/components/src/unit-control/index.native.js +++ b/packages/components/src/unit-control/index.native.js @@ -47,10 +47,8 @@ function UnitControl( { if ( pickerRef?.current ) { pickerRef.current.presentPicker(); } - // Disable reason: this should be fixed by the native team. - // It would be great if this could be done in the context of + // It would be great if the deps could be addressed in the context of // https://github.com/WordPress/gutenberg/pull/39218 - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ pickerRef?.current ] ); const currentInputValue = currentInput === null ? value : currentInput; @@ -106,10 +104,8 @@ function UnitControl( { anchorNodeRef?.current ? findNodeHandle( anchorNodeRef?.current ) : undefined, - // Disable reason: this should be fixed by the native team. - // It would be great if this could be done in the context of + // It would be great if the deps could be addressed in the context of // https://github.com/WordPress/gutenberg/pull/39218 - // eslint-disable-next-line react-hooks/exhaustive-deps [ anchorNodeRef?.current ] ); diff --git a/packages/components/src/utils/element-rect.ts b/packages/components/src/utils/element-rect.ts index 7f9693ef9f7df2..0f58ea6d7caf54 100644 --- a/packages/components/src/utils/element-rect.ts +++ b/packages/components/src/utils/element-rect.ts @@ -181,7 +181,6 @@ export function useTrackElementOffsetRect( measure(); // `measure` is a stable function, so it's safe to omit it from the deps array. // deps can't be statically analyzed by ESLint - // eslint-disable-next-line react-hooks/exhaustive-deps }, deps ); return indicatorPosition; diff --git a/packages/components/src/utils/hooks/use-update-effect.js b/packages/components/src/utils/hooks/use-update-effect.js index ed2c3ca4363579..e371647f033de6 100644 --- a/packages/components/src/utils/hooks/use-update-effect.js +++ b/packages/components/src/utils/hooks/use-update-effect.js @@ -19,11 +19,9 @@ function useUpdateEffect( effect, deps ) { } mountedRef.current = true; return undefined; - // Disable reasons: // 1. This hook needs to pass a dep list that isn't an array literal // 2. `effect` is missing from the array, and will need to be added carefully to avoid additional warnings // see https://github.com/WordPress/gutenberg/pull/41166 - // eslint-disable-next-line react-hooks/exhaustive-deps }, deps ); useEffect( From 7cda6744d81cefc46976d72a5bd45cbd91988ad3 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Fri, 25 Oct 2024 11:15:24 +0100 Subject: [PATCH 1343/1908] Don't switch editor mode when changing entities (#66452) * Only reset zoom level * Avoid set editor mode on sidebar toggle Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Ella <4710635+ellatrix@users.noreply.github.com> --- packages/edit-site/src/components/editor/index.js | 7 +------ .../use-init-edited-entity-from-url.js | 14 +++++++++----- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 9058a163707997..c7481a1d12bd79 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -153,9 +153,7 @@ export default function EditSiteEditor( { isPostsList = false } ) { ], [ settings.styles, canvas, currentPostIsTrashed ] ); - const { __unstableSetEditorMode, resetZoomLevel } = unlock( - useDispatch( blockEditorStore ) - ); + const { resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); const { createSuccessNotice } = useDispatch( noticesStore ); const history = useHistory(); const onActionPerformed = useCallback( @@ -263,9 +261,6 @@ export default function EditSiteEditor( { isPostsList = false } ) { showTooltip tooltipPosition="middle right" onClick={ () => { - __unstableSetEditorMode( - 'edit' - ); resetZoomLevel(); // TODO: this is a temporary solution to navigate to the posts list if we are diff --git a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js index 9f507693c4cfdc..35eeb5963fb546 100644 --- a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js +++ b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js @@ -249,15 +249,19 @@ export default function useInitEditedEntityFromURL() { useResolveEditedEntityAndContext( params ); const { setEditedEntity } = useDispatch( editSiteStore ); - const { __unstableSetEditorMode, resetZoomLevel } = unlock( - useDispatch( blockEditorStore ) - ); + const { resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); useEffect( () => { if ( isReady ) { - __unstableSetEditorMode( 'edit' ); resetZoomLevel(); setEditedEntity( postType, postId, context ); } - }, [ isReady, postType, postId, context, setEditedEntity ] ); + }, [ + isReady, + postType, + postId, + context, + setEditedEntity, + resetZoomLevel, + ] ); } From f1b307ab30ad0b61b1105939d2ad5722a662de2d Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Fri, 25 Oct 2024 14:07:52 +0300 Subject: [PATCH 1344/1908] Remove purple coloring from DocumentBar and PostCard (#66451) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: creativecoder <grantmkin@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/editor/src/components/document-bar/style.scss | 4 ---- packages/editor/src/components/post-card-panel/style.scss | 8 -------- 2 files changed, 12 deletions(-) diff --git a/packages/editor/src/components/document-bar/style.scss b/packages/editor/src/components/document-bar/style.scss index 3e5fbf5f4b1ae1..6a7e7930f5bfb7 100644 --- a/packages/editor/src/components/document-bar/style.scss +++ b/packages/editor/src/components/document-bar/style.scss @@ -67,10 +67,6 @@ flex: 1; overflow: hidden; text-overflow: ellipsis; - - .editor-document-bar.is-global & { - color: var(--wp-block-synced-color); - } } .editor-document-bar__post-type-label { diff --git a/packages/editor/src/components/post-card-panel/style.scss b/packages/editor/src/components/post-card-panel/style.scss index f69fe5aa00ad5f..d8a2a4628e6f9c 100644 --- a/packages/editor/src/components/post-card-panel/style.scss +++ b/packages/editor/src/components/post-card-panel/style.scss @@ -34,14 +34,6 @@ } } -.editor-post-card-panel__icon.is-sync { - fill: var(--wp-block-synced-color); - - & + .editor-post-card-panel__title { - color: var(--wp-block-synced-color); - } -} - .editor-post-card-panel__title-badge { background: $gray-100; color: $gray-800; From 399d585a01561fccabc281bdc2e93d21bf33ecc1 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 25 Oct 2024 14:29:41 +0300 Subject: [PATCH 1345/1908] ESLint: Remove explicit react-hooks/exhaustive-deps disabling (#66461) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../block-editor/src/components/block-list/block.native.js | 4 ---- .../inserter/block-patterns-tab/pattern-category-previews.js | 1 - packages/block-editor/src/components/list-view/index.js | 3 +-- .../block-editor/src/components/rich-text/index.native.js | 2 -- .../src/components/use-block-drop-zone/index.native.js | 1 - .../block-editor/src/components/use-moving-animation/index.js | 1 - packages/block-editor/src/components/use-settings/index.js | 1 - packages/block-editor/src/hooks/contrast-checker.js | 1 - packages/block-library/src/cover/edit/index.js | 3 +-- packages/block-library/src/file/edit.js | 3 +-- packages/block-library/src/social-links/edit.js | 1 - packages/data/src/components/use-select/index.js | 1 - .../src/components/block-editor/use-site-editor-settings.js | 3 +-- packages/edit-site/src/components/layout/animation.js | 1 - packages/edit-site/src/components/layout/index.js | 1 - packages/edit-widgets/src/components/sidebar/index.js | 1 - 16 files changed, 4 insertions(+), 24 deletions(-) diff --git a/packages/block-editor/src/components/block-list/block.native.js b/packages/block-editor/src/components/block-list/block.native.js index 4112d614da35fc..9f34195e50e040 100644 --- a/packages/block-editor/src/components/block-list/block.native.js +++ b/packages/block-editor/src/components/block-list/block.native.js @@ -320,7 +320,6 @@ function BlockListBlock( { name, fontSizes || EMPTY_ARRAY ); - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ // It is crucial to keep the dependencies array minimal to prevent unnecessary calls that could negatively impact performance. // JSON.stringify is used for the following purposes: @@ -329,11 +328,8 @@ function BlockListBlock( { // 2. To filter the attributes object, ensuring that only the relevant attributes (included in // GlobalStylesContext.BLOCK_STYLE_ATTRIBUTES) are considered as dependencies. This reduces the likelihood of // unnecessary useMemo calls when other, unrelated attributes change. - // eslint-disable-next-line react-hooks/exhaustive-deps JSON.stringify( globalStyle ), - // eslint-disable-next-line react-hooks/exhaustive-deps JSON.stringify( wrapperProps?.style ), - // eslint-disable-next-line react-hooks/exhaustive-deps JSON.stringify( Object.fromEntries( Object.entries( attributes ?? {} ).filter( ( [ key ] ) => diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js index 835015704c944b..fcb6c7601fcf7f 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js @@ -117,7 +117,6 @@ export function PatternCategoryPreviews( { const { changePage } = pagingProps; // Hide block pattern preview on unmount. - // eslint-disable-next-line react-hooks/exhaustive-deps useEffect( () => () => onHover( null ), [] ); const onSetPatternSyncFilter = useCallback( diff --git a/packages/block-editor/src/components/list-view/index.js b/packages/block-editor/src/components/list-view/index.js index 87599ea870913b..d7961bd6c02f3d 100644 --- a/packages/block-editor/src/components/list-view/index.js +++ b/packages/block-editor/src/components/list-view/index.js @@ -185,8 +185,7 @@ function ListViewComponent( if ( selectedClientIds?.length ) { focusListItem( selectedClientIds[ 0 ], elementRef?.current ); } - // Disable reason: Only focus on the selected item when the list view is mounted. - // eslint-disable-next-line react-hooks/exhaustive-deps + // Only focus on the selected item when the list view is mounted. }, [] ); const expand = useCallback( diff --git a/packages/block-editor/src/components/rich-text/index.native.js b/packages/block-editor/src/components/rich-text/index.native.js index 4899d49b8c8eb0..687c2759c05de2 100644 --- a/packages/block-editor/src/components/rich-text/index.native.js +++ b/packages/block-editor/src/components/rich-text/index.native.js @@ -212,7 +212,6 @@ export function RichTextWrapper( selectionChangeEnd ); }, - // eslint-disable-next-line react-hooks/exhaustive-deps [ clientId, identifier ] ); @@ -368,7 +367,6 @@ export function RichTextWrapper( onChange( insert( value, '\n' ) ); } }, - // eslint-disable-next-line react-hooks/exhaustive-deps [ onReplace, onSplit, diff --git a/packages/block-editor/src/components/use-block-drop-zone/index.native.js b/packages/block-editor/src/components/use-block-drop-zone/index.native.js index 4f00880873c2fa..f40900ec7db970 100644 --- a/packages/block-editor/src/components/use-block-drop-zone/index.native.js +++ b/packages/block-editor/src/components/use-block-drop-zone/index.native.js @@ -132,7 +132,6 @@ export default function useBlockDropZone( { const getSortedBlocksLayouts = useCallback( () => { return getBlockLayoutsOrderedByYCoord( blocksLayouts.current ); // We use the value of `blocksLayouts` as the dependency. - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ blocksLayouts.current ] ); const isRTL = getSettings().isRTL; diff --git a/packages/block-editor/src/components/use-moving-animation/index.js b/packages/block-editor/src/components/use-moving-animation/index.js index a6ac0968ca16fc..602b683150d0cc 100644 --- a/packages/block-editor/src/components/use-moving-animation/index.js +++ b/packages/block-editor/src/components/use-moving-animation/index.js @@ -61,7 +61,6 @@ function useMovingAnimation( { triggerAnimationOnChange, clientId } ) { previous: ref.current && getAbsolutePosition( ref.current ), prevRect: ref.current && ref.current.getBoundingClientRect(), } ), - // eslint-disable-next-line react-hooks/exhaustive-deps [ triggerAnimationOnChange ] ); diff --git a/packages/block-editor/src/components/use-settings/index.js b/packages/block-editor/src/components/use-settings/index.js index e356260c2d6b38..072653b913c304 100644 --- a/packages/block-editor/src/components/use-settings/index.js +++ b/packages/block-editor/src/components/use-settings/index.js @@ -32,7 +32,6 @@ export function useSettings( ...paths ) { clientId, ...paths ), - // eslint-disable-next-line react-hooks/exhaustive-deps [ clientId, ...paths ] ); } diff --git a/packages/block-editor/src/hooks/contrast-checker.js b/packages/block-editor/src/hooks/contrast-checker.js index 6e503ae8f3319d..368e2e75264858 100644 --- a/packages/block-editor/src/hooks/contrast-checker.js +++ b/packages/block-editor/src/hooks/contrast-checker.js @@ -21,7 +21,6 @@ export default function BlockColorContrastChecker( { clientId } ) { // There are so many things that can change the color of a block // So we perform this check on every render. - // eslint-disable-next-line react-hooks/exhaustive-deps useEffect( () => { if ( ! blockEl ) { return; diff --git a/packages/block-library/src/cover/edit/index.js b/packages/block-library/src/cover/edit/index.js index 88a47f566987c6..77ce9e62d9eb09 100644 --- a/packages/block-library/src/cover/edit/index.js +++ b/packages/block-library/src/cover/edit/index.js @@ -152,8 +152,7 @@ function CoverEdit( { isUserOverlayColor: isUserOverlayColor || false, } ); } )(); - // Disable reason: Update the block only when the featured image changes. - // eslint-disable-next-line react-hooks/exhaustive-deps + // Update the block only when the featured image changes. }, [ mediaUrl ] ); // instead of destructuring the attributes diff --git a/packages/block-library/src/file/edit.js b/packages/block-library/src/file/edit.js index be061d357bffd1..59e660dd3211f1 100644 --- a/packages/block-library/src/file/edit.js +++ b/packages/block-library/src/file/edit.js @@ -103,8 +103,7 @@ function FileEdit( { attributes, isSelected, setAttributes, clientId } ) { downloadButtonText: _x( 'Download', 'button label' ), } ); } - // Reason: This effect should only run on mount. - // eslint-disable-next-line react-hooks/exhaustive-deps + // This effect should only run on mount. }, [] ); function onSelectFile( newMedia ) { diff --git a/packages/block-library/src/social-links/edit.js b/packages/block-library/src/social-links/edit.js index d4dfae70aac5ae..068b34a3a70a4e 100644 --- a/packages/block-library/src/social-links/edit.js +++ b/packages/block-library/src/social-links/edit.js @@ -86,7 +86,6 @@ export function SocialLinksEdit( props ) { } else { setAttributes( { ...backgroundBackupRef.current } ); } - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ logosOnly ] ); const SocialPlaceholder = ( diff --git a/packages/data/src/components/use-select/index.js b/packages/data/src/components/use-select/index.js index a0073d7e847fc2..3e28e9489e977e 100644 --- a/packages/data/src/components/use-select/index.js +++ b/packages/data/src/components/use-select/index.js @@ -223,7 +223,6 @@ function useMappingSelect( suspense, mapSelect, deps ) { // These are "pass-through" dependencies from the parent hook, // and the parent should catch any hook rule violations. - // eslint-disable-next-line react-hooks/exhaustive-deps const selector = useCallback( mapSelect, deps ); const { subscribe, getValue } = store( selector, isAsync ); const result = useSyncExternalStore( subscribe, getValue, getValue ); diff --git a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js index e6dd0368249627..37fa0a2eaf30c2 100644 --- a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js +++ b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js @@ -29,10 +29,9 @@ function useNavigateToPreviousEntityRecord() { previousLocation?.params.canvas === 'edit'; const showBackButton = isFocusMode && didComeFromEditorCanvas; return showBackButton ? () => history.back() : undefined; - // Disable reason: previousLocation changes when the component updates for any reason, not + // `previousLocation` changes when the component updates for any reason, not // just when location changes. Until this is fixed we can't add it to deps. See // https://github.com/WordPress/gutenberg/pull/58710#discussion_r1479219465. - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ location, history ] ); return goBack; } diff --git a/packages/edit-site/src/components/layout/animation.js b/packages/edit-site/src/components/layout/animation.js index 0dc6c61b165aad..00f6eb01a6f1a0 100644 --- a/packages/edit-site/src/components/layout/animation.js +++ b/packages/edit-site/src/components/layout/animation.js @@ -41,7 +41,6 @@ function useMovingAnimation( { triggerAnimationOnChange } ) { previous: ref.current && getAbsolutePosition( ref.current ), prevRect: ref.current && ref.current.getBoundingClientRect(), } ), - // eslint-disable-next-line react-hooks/exhaustive-deps [ triggerAnimationOnChange ] ); diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index 12799f46fbe348..713b1f179b7adb 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -75,7 +75,6 @@ export default function Layout( { route } ) { toggleRef.current?.focus(); } // Should not depend on the previous canvas mode value but the next. - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ canvas ] ); return ( diff --git a/packages/edit-widgets/src/components/sidebar/index.js b/packages/edit-widgets/src/components/sidebar/index.js index 79a47b18c7bf12..a42a6d7c4be7a4 100644 --- a/packages/edit-widgets/src/components/sidebar/index.js +++ b/packages/edit-widgets/src/components/sidebar/index.js @@ -88,7 +88,6 @@ function SidebarContent( { // We're intentionally leaving `currentArea` and `isGeneralSidebarOpen` // out of the dep array because we want this effect to run based on // block selection changes, not sidebar state changes. - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ hasSelectedNonAreaBlock, enableComplementaryArea ] ); const tabsContextValue = useContext( Tabs.Context ); From b2d692c11504da5727261540909ecd1b0814aeab Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 25 Oct 2024 14:41:54 +0300 Subject: [PATCH 1346/1908] Fields: Fix React Compiler mutation errors (#66464) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/fields/src/fields/slug/slug-edit.tsx | 10 +++++----- packages/fields/src/fields/slug/slug-view.tsx | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/fields/src/fields/slug/slug-edit.tsx b/packages/fields/src/fields/slug/slug-edit.tsx index 760e67c9cff3bf..aeb02ba42873b9 100644 --- a/packages/fields/src/fields/slug/slug-edit.tsx +++ b/packages/fields/src/fields/slug/slug-edit.tsx @@ -38,15 +38,15 @@ const SlugEdit = ( { const permalinkPrefix = prefix; const permalinkSuffix = suffix; const isEditable = PERMALINK_POSTNAME_REGEX.test( permalinkTemplate ); - const originalSlug = useRef( slug ); - const slugToDisplay = slug || originalSlug.current; + const originalSlugRef = useRef( slug ); + const slugToDisplay = slug || originalSlugRef.current; const permalink = isEditable ? `${ permalinkPrefix }${ slugToDisplay }${ permalinkSuffix }` : safeDecodeURIComponent( data.link || '' ); useEffect( () => { - if ( slug && originalSlug.current === undefined ) { - originalSlug.current = slug; + if ( slug && originalSlugRef.current === undefined ) { + originalSlugRef.current = slug; } }, [ slug ] ); @@ -111,7 +111,7 @@ const SlugEdit = ( { } } onBlur={ () => { if ( slug === '' ) { - onChangeControl( originalSlug.current ); + onChangeControl( originalSlugRef.current ); } } } aria-describedby={ postUrlSlugDescriptionId } diff --git a/packages/fields/src/fields/slug/slug-view.tsx b/packages/fields/src/fields/slug/slug-view.tsx index 7448673c6a8464..dc17eae128d68a 100644 --- a/packages/fields/src/fields/slug/slug-view.tsx +++ b/packages/fields/src/fields/slug/slug-view.tsx @@ -10,15 +10,15 @@ import type { BasePost } from '../../types'; const SlugView = ( { item }: { item: BasePost } ) => { const slug = item.slug; - const originalSlug = useRef( slug ); + const originalSlugRef = useRef( slug ); useEffect( () => { - if ( slug && originalSlug.current === undefined ) { - originalSlug.current = slug; + if ( slug && originalSlugRef.current === undefined ) { + originalSlugRef.current = slug; } }, [ slug ] ); - const slugToDisplay = slug || originalSlug.current; + const slugToDisplay = slug || originalSlugRef.current; return `/${ slugToDisplay ?? '' }`; }; From e7f2d01e449b105fdc8dbe6799370070573201d7 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Fri, 25 Oct 2024 07:10:27 -0500 Subject: [PATCH 1347/1908] Remove viewport check from useZoomOut hook (#66341) The useZoomOut hook should not be responsible for checking viewport width. It should respect the desired zoom out level passed by the condition. We should decide if we want to enter zoom out or not where we implement the useZoomOut hook (the inserter menu). --------- Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: PARTHVATALIYA <parthvataliya@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- packages/block-editor/src/components/inserter/menu.js | 6 ++++-- packages/block-editor/src/hooks/use-zoom-out.js | 8 +++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index 915a36d242ba26..8dc2f64063c8e3 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -16,7 +16,7 @@ import { } from '@wordpress/element'; import { VisuallyHidden, SearchControl, Popover } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { useDebouncedInput } from '@wordpress/compose'; +import { useDebouncedInput, useViewportMatch } from '@wordpress/compose'; import { useSelect } from '@wordpress/data'; /** @@ -67,6 +67,8 @@ function InserterMenu( const [ patternFilter, setPatternFilter ] = useState( 'all' ); const [ selectedMediaCategory, setSelectedMediaCategory ] = useState( null ); + const isLargeViewport = useViewportMatch( 'large' ); + function getInitialTab() { if ( __experimentalInitialTab ) { return __experimentalInitialTab; @@ -80,7 +82,7 @@ function InserterMenu( const shouldUseZoomOut = selectedTab === 'patterns' || selectedTab === 'media'; - useZoomOut( shouldUseZoomOut ); + useZoomOut( shouldUseZoomOut && isLargeViewport ); const [ destinationRootClientId, onInsertBlocks, onToggleInsertionPoint ] = useInsertionPoint( { diff --git a/packages/block-editor/src/hooks/use-zoom-out.js b/packages/block-editor/src/hooks/use-zoom-out.js index bc2d325e81d61a..bcf5d9ff882f7b 100644 --- a/packages/block-editor/src/hooks/use-zoom-out.js +++ b/packages/block-editor/src/hooks/use-zoom-out.js @@ -9,7 +9,6 @@ import { useEffect } from '@wordpress/element'; */ import { store as blockEditorStore } from '../store'; import { unlock } from '../lock-unlock'; -import { useViewportMatch } from '@wordpress/compose'; /** * A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode. @@ -21,13 +20,12 @@ export function useZoomOut( zoomOut = true ) { useDispatch( blockEditorStore ) ); const { isZoomOut } = unlock( useSelect( blockEditorStore ) ); - const isWideViewport = useViewportMatch( 'large' ); useEffect( () => { const isZoomOutOnMount = isZoomOut(); return () => { - if ( isZoomOutOnMount && isWideViewport ) { + if ( isZoomOutOnMount ) { setZoomLevel( 'auto-scaled' ); } else { resetZoomLevel(); @@ -36,10 +34,10 @@ export function useZoomOut( zoomOut = true ) { }, [] ); useEffect( () => { - if ( zoomOut && isWideViewport ) { + if ( zoomOut ) { setZoomLevel( 'auto-scaled' ); } else { resetZoomLevel(); } - }, [ zoomOut, setZoomLevel, resetZoomLevel, isWideViewport ] ); + }, [ zoomOut, setZoomLevel, resetZoomLevel ] ); } From 029716e11c2d5e9a824aa26c9e7f6f30e9ee62c1 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 25 Oct 2024 16:14:32 +0400 Subject: [PATCH 1348/1908] Rich Text: Fix React Complier error for 'useEventListeners' (#66460) * Rich Text: Fix React Complier error for 'useEventListeners' * Try 'useInsertionEffect' hook Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/rich-text/src/component/event-listeners/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/rich-text/src/component/event-listeners/index.js b/packages/rich-text/src/component/event-listeners/index.js index a6327fe6637c37..4f69db36db06a0 100644 --- a/packages/rich-text/src/component/event-listeners/index.js +++ b/packages/rich-text/src/component/event-listeners/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { useMemo, useRef } from '@wordpress/element'; +import { useMemo, useRef, useInsertionEffect } from '@wordpress/element'; import { useRefEffect } from '@wordpress/compose'; /** @@ -25,7 +25,9 @@ const allEventListeners = [ export function useEventListeners( props ) { const propsRef = useRef( props ); - propsRef.current = props; + useInsertionEffect( () => { + propsRef.current = props; + } ); const refEffects = useMemo( () => allEventListeners.map( ( refEffect ) => refEffect( propsRef ) ), [ propsRef ] From 7941d47a582ea621c4a1f782eddab1f273d15884 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Fri, 25 Oct 2024 15:15:27 +0300 Subject: [PATCH 1349/1908] Iterate zoom out shuffle into a more visual control (#66194) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../components/block-toolbar/change-design.js | 133 ++++++++++++++++++ .../src/components/block-toolbar/index.js | 11 +- .../src/components/block-toolbar/shuffle.js | 111 --------------- .../src/components/block-toolbar/style.scss | 16 +++ 4 files changed, 152 insertions(+), 119 deletions(-) create mode 100644 packages/block-editor/src/components/block-toolbar/change-design.js delete mode 100644 packages/block-editor/src/components/block-toolbar/shuffle.js diff --git a/packages/block-editor/src/components/block-toolbar/change-design.js b/packages/block-editor/src/components/block-toolbar/change-design.js new file mode 100644 index 00000000000000..ecfeff6cb1ed3e --- /dev/null +++ b/packages/block-editor/src/components/block-toolbar/change-design.js @@ -0,0 +1,133 @@ +/** + * WordPress dependencies + */ +import { + ToolbarButton, + ToolbarGroup, + Dropdown, + __experimentalDropdownContentWrapper as DropdownContentWrapper, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { cloneBlock } from '@wordpress/blocks'; +import { useMemo } from '@wordpress/element'; +import { useAsyncList } from '@wordpress/compose'; +import { useSelect, useDispatch } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../../store'; +import BlockPatternsList from '../block-patterns-list'; + +const EMPTY_ARRAY = []; +const MAX_PATTERNS_TO_SHOW = 6; +const POPOVER_PROPS = { + placement: 'bottom-start', +}; + +export default function ChangeDesign( { clientId } ) { + const { categories, currentPatternName, patterns } = useSelect( + ( select ) => { + const { + getBlockAttributes, + getBlockRootClientId, + __experimentalGetAllowedPatterns, + } = select( blockEditorStore ); + const attributes = getBlockAttributes( clientId ); + const _categories = attributes?.metadata?.categories || EMPTY_ARRAY; + const rootBlock = getBlockRootClientId( clientId ); + + // Calling `__experimentalGetAllowedPatterns` is expensive. + // Checking if the block can be changed prevents unnecessary selector calls. + // See: https://github.com/WordPress/gutenberg/pull/64736. + const _patterns = + _categories.length > 0 + ? __experimentalGetAllowedPatterns( rootBlock ) + : EMPTY_ARRAY; + return { + categories: _categories, + currentPatternName: attributes?.metadata?.patternName, + patterns: _patterns, + }; + }, + [ clientId ] + ); + const { replaceBlocks } = useDispatch( blockEditorStore ); + const sameCategoryPatternsWithSingleWrapper = useMemo( () => { + if ( categories.length === 0 || ! patterns || patterns.length === 0 ) { + return EMPTY_ARRAY; + } + return patterns + .filter( ( pattern ) => { + const isCorePattern = + pattern.source === 'core' || + ( pattern.source?.startsWith( 'pattern-directory' ) && + pattern.source !== 'pattern-directory/theme' ); + return ( + // Check if the pattern has only one top level block, + // otherwise we may switch to a pattern that doesn't have replacement suggestions. + pattern.blocks.length === 1 && + // We exclude the core patterns and pattern directory patterns that are not theme patterns. + ! isCorePattern && + // Exclude current pattern. + currentPatternName !== pattern.name && + pattern.categories?.some( ( category ) => { + return categories.includes( category ); + } ) && + // Check if the pattern is not a synced pattern. + ( pattern.syncStatus === 'unsynced' || ! pattern.id ) + ); + } ) + .slice( 0, MAX_PATTERNS_TO_SHOW ); + }, [ categories, currentPatternName, patterns ] ); + + const currentShownPatterns = useAsyncList( + sameCategoryPatternsWithSingleWrapper + ); + + if ( sameCategoryPatternsWithSingleWrapper.length < 2 ) { + return null; + } + + const onClickPattern = ( pattern ) => { + const newBlocks = ( pattern.blocks ?? [] ).map( ( block ) => { + return cloneBlock( block ); + } ); + newBlocks[ 0 ].attributes.metadata = { + ...newBlocks[ 0 ].attributes.metadata, + categories, + }; + replaceBlocks( clientId, newBlocks ); + }; + + return ( + <Dropdown + popoverProps={ POPOVER_PROPS } + renderToggle={ ( { onToggle, isOpen } ) => { + return ( + <ToolbarGroup> + <ToolbarButton + onClick={ () => onToggle( ! isOpen ) } + aria-expanded={ isOpen } + > + { __( 'Change design' ) } + </ToolbarButton> + </ToolbarGroup> + ); + } } + renderContent={ () => ( + <DropdownContentWrapper + className="block-editor-block-toolbar-change-design-content-wrapper" + paddingSize="none" + > + <BlockPatternsList + shownPatterns={ currentShownPatterns } + blockPatterns={ sameCategoryPatternsWithSingleWrapper } + onClickPattern={ onClickPattern } + showTitle={ false } + /> + </DropdownContentWrapper> + ) } + /> + ); +} diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 77b10149aaf226..b3bf7e94accb08 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -16,7 +16,7 @@ import { isReusableBlock, isTemplatePart, } from '@wordpress/blocks'; -import { ToolbarGroup, ToolbarButton } from '@wordpress/components'; +import { ToolbarGroup } from '@wordpress/components'; /** * Internal dependencies @@ -35,7 +35,7 @@ import { store as blockEditorStore } from '../../store'; import __unstableBlockNameContext from './block-name-context'; import NavigableToolbar from '../navigable-toolbar'; import { useHasBlockToolbar } from './use-has-block-toolbar'; -import Shuffle from './shuffle'; +import ChangeDesign from './change-design'; import { unlock } from '../../lock-unlock'; /** @@ -220,12 +220,7 @@ export function PrivateBlockToolbar( { isMultiToolbar && showGroupButtons && <BlockGroupToolbar /> } { showShuffleButton && ( - <ToolbarGroup> - <Shuffle - clientId={ blockClientIds[ 0 ] } - as={ ToolbarButton } - /> - </ToolbarGroup> + <ChangeDesign clientId={ blockClientIds[ 0 ] } /> ) } { shouldShowVisualToolbar && showSlots && ( <> diff --git a/packages/block-editor/src/components/block-toolbar/shuffle.js b/packages/block-editor/src/components/block-toolbar/shuffle.js deleted file mode 100644 index 954c7ff22d68ce..00000000000000 --- a/packages/block-editor/src/components/block-toolbar/shuffle.js +++ /dev/null @@ -1,111 +0,0 @@ -/** - * WordPress dependencies - */ -import { shuffle } from '@wordpress/icons'; -import { ToolbarButton, ToolbarGroup } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import { useMemo } from '@wordpress/element'; -import { useSelect, useDispatch } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import { store as blockEditorStore } from '../../store'; - -const EMPTY_ARRAY = []; - -function Container( props ) { - return ( - <ToolbarGroup> - <ToolbarButton { ...props } /> - </ToolbarGroup> - ); -} - -export default function Shuffle( { clientId, as = Container } ) { - const { categories, patterns, patternName } = useSelect( - ( select ) => { - const { - getBlockAttributes, - getBlockRootClientId, - __experimentalGetAllowedPatterns, - } = select( blockEditorStore ); - const attributes = getBlockAttributes( clientId ); - const _categories = attributes?.metadata?.categories || EMPTY_ARRAY; - const _patternName = attributes?.metadata?.patternName; - const rootBlock = getBlockRootClientId( clientId ); - - // Calling `__experimentalGetAllowedPatterns` is expensive. - // Checking if the block can be shuffled prevents unnecessary selector calls. - // See: https://github.com/WordPress/gutenberg/pull/64736. - const _patterns = - _categories.length > 0 - ? __experimentalGetAllowedPatterns( rootBlock ) - : EMPTY_ARRAY; - return { - categories: _categories, - patterns: _patterns, - patternName: _patternName, - }; - }, - [ clientId ] - ); - const { replaceBlocks } = useDispatch( blockEditorStore ); - const sameCategoryPatternsWithSingleWrapper = useMemo( () => { - if ( categories.length === 0 || ! patterns || patterns.length === 0 ) { - return EMPTY_ARRAY; - } - return patterns.filter( ( pattern ) => { - const isCorePattern = - pattern.source === 'core' || - ( pattern.source?.startsWith( 'pattern-directory' ) && - pattern.source !== 'pattern-directory/theme' ); - return ( - // Check if the pattern has only one top level block, - // otherwise we may shuffle to pattern that will not allow to continue shuffling. - pattern.blocks.length === 1 && - // We exclude the core patterns and pattern directory patterns that are not theme patterns. - ! isCorePattern && - pattern.categories?.some( ( category ) => { - return categories.includes( category ); - } ) && - // Check if the pattern is not a synced pattern. - ( pattern.syncStatus === 'unsynced' || ! pattern.id ) - ); - } ); - }, [ categories, patterns ] ); - - if ( sameCategoryPatternsWithSingleWrapper.length < 2 ) { - return null; - } - - function getNextPattern() { - const numberOfPatterns = sameCategoryPatternsWithSingleWrapper.length; - const patternIndex = sameCategoryPatternsWithSingleWrapper.findIndex( - ( { name } ) => name === patternName - ); - const nextPatternIndex = - patternIndex + 1 < numberOfPatterns ? patternIndex + 1 : 0; - return sameCategoryPatternsWithSingleWrapper[ nextPatternIndex ]; - } - - const ComponentToUse = as; - return ( - <ComponentToUse - label={ __( 'Shuffle' ) } - icon={ shuffle } - className="block-editor-block-toolbar-shuffle" - onClick={ () => { - const nextPattern = getNextPattern(); - nextPattern.blocks[ 0 ].attributes = { - ...nextPattern.blocks[ 0 ].attributes, - metadata: { - ...nextPattern.blocks[ 0 ].attributes.metadata, - categories, - }, - }; - replaceBlocks( clientId, nextPattern.blocks ); - } } - /> - ); -} diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index ae03eeed1a817c..26bf71356925e9 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -285,3 +285,19 @@ } } } + +.block-editor-block-toolbar-change-design-content-wrapper { + padding: $grid-unit-15; + width: 320px; + .block-editor-block-patterns-list { + display: grid; + grid-template-columns: 1fr 1fr; + grid-gap: $grid-unit-15; + .block-editor-block-patterns-list__list-item { + margin-bottom: 0; + } + .block-editor-inserter__media-list__list-item { + min-height: 100px; + } + } +} From 8a2480a88e0bac2685b279ea377ae18d2523022f Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Fri, 25 Oct 2024 14:23:36 +0200 Subject: [PATCH 1350/1908] Site Editor: remove content styles outside canvas (#66432) --- backport-changelog/6.8/7643.md | 3 +++ lib/client-assets.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 backport-changelog/6.8/7643.md diff --git a/backport-changelog/6.8/7643.md b/backport-changelog/6.8/7643.md new file mode 100644 index 00000000000000..e3c923a487be06 --- /dev/null +++ b/backport-changelog/6.8/7643.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7643 + +* https://github.com/WordPress/gutenberg/pull/66432 diff --git a/lib/client-assets.php b/lib/client-assets.php index 9cdee4753f43b7..f6b17ffcce68be 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -410,7 +410,7 @@ function gutenberg_register_packages_styles( $styles ) { $styles, 'wp-edit-site', gutenberg_url( 'build/edit-site/style.css' ), - array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks', 'wp-commands', 'wp-preferences' ), + array( 'wp-components', 'wp-block-editor', 'wp-editor', 'common', 'forms', 'wp-commands', 'wp-preferences' ), $version ); $styles->add_data( 'wp-edit-site', 'rtl', 'replace' ); From 6347583a290531b9c7ae8ffde62f51368843f998 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Fri, 25 Oct 2024 16:21:18 +0300 Subject: [PATCH 1351/1908] Follow up of 66451 - leftovers from removed styles (#66472) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/document-bar/index.js | 6 +--- .../src/components/post-card-panel/index.js | 29 ++----------------- 2 files changed, 3 insertions(+), 32 deletions(-) diff --git a/packages/editor/src/components/document-bar/index.js b/packages/editor/src/components/document-bar/index.js index 904a877734cef9..3c522189a2632f 100644 --- a/packages/editor/src/components/document-bar/index.js +++ b/packages/editor/src/components/document-bar/index.js @@ -26,7 +26,7 @@ import { decodeEntities } from '@wordpress/html-entities'; /** * Internal dependencies */ -import { TEMPLATE_POST_TYPES, GLOBAL_POST_TYPES } from '../../store/constants'; +import { TEMPLATE_POST_TYPES } from '../../store/constants'; import { store as editorStore } from '../../store'; /** @typedef {import("@wordpress/components").IconType} IconType */ @@ -56,7 +56,6 @@ export default function DocumentBar( props ) { postTypeLabel, documentTitle, isNotFound, - isUnsyncedPattern, templateTitle, onNavigateToPreviousEntityRecord, } = useSelect( ( select ) => { @@ -93,7 +92,6 @@ export default function DocumentBar( props ) { _postType, _postId ), - isUnsyncedPattern: _document?.wp_pattern_sync_status === 'unsynced', templateTitle: _templateInfo.title, onNavigateToPreviousEntityRecord: getEditorSettings().onNavigateToPreviousEntityRecord, @@ -104,7 +102,6 @@ export default function DocumentBar( props ) { const isReducedMotion = useReducedMotion(); const isTemplate = TEMPLATE_POST_TYPES.includes( postType ); - const isGlobalEntity = GLOBAL_POST_TYPES.includes( postType ); const hasBackButton = !! onNavigateToPreviousEntityRecord; const entityTitle = isTemplate ? templateTitle : documentTitle; const title = props.title || entityTitle; @@ -119,7 +116,6 @@ export default function DocumentBar( props ) { <div className={ clsx( 'editor-document-bar', { 'has-back-button': hasBackButton, - 'is-global': isGlobalEntity && ! isUnsyncedPattern, } ) } > <AnimatePresence> diff --git a/packages/editor/src/components/post-card-panel/index.js b/packages/editor/src/components/post-card-panel/index.js index ed13af9b55a4aa..1365659f708147 100644 --- a/packages/editor/src/components/post-card-panel/index.js +++ b/packages/editor/src/components/post-card-panel/index.js @@ -1,7 +1,3 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; /** * WordPress dependencies */ @@ -22,8 +18,6 @@ import { store as editorStore } from '../../store'; import { TEMPLATE_POST_TYPE, TEMPLATE_PART_POST_TYPE, - PATTERN_POST_TYPE, - GLOBAL_POST_TYPES, } from '../../store/constants'; import { unlock } from '../../lock-unlock'; import PostActions from '../post-actions'; @@ -33,7 +27,7 @@ export default function PostCardPanel( { postId, onActionPerformed, } ) { - const { isFrontPage, isPostsPage, title, icon, isSync } = useSelect( + const { isFrontPage, isPostsPage, title, icon } = useSelect( ( select ) => { const { __experimentalGetTemplateInfo } = select( editorStore ); const { canUser, getEditedEntityRecord } = select( coreStore ); @@ -52,25 +46,11 @@ export default function PostCardPanel( { [ TEMPLATE_POST_TYPE, TEMPLATE_PART_POST_TYPE ].includes( postType ) && __experimentalGetTemplateInfo( _record ); - let _isSync = false; - if ( GLOBAL_POST_TYPES.includes( postType ) ) { - if ( PATTERN_POST_TYPE === postType ) { - // When the post is first created, the top level wp_pattern_sync_status is not set so get meta value instead. - const currentSyncStatus = - _record?.meta?.wp_pattern_sync_status === 'unsynced' - ? 'unsynced' - : _record?.wp_pattern_sync_status; - _isSync = currentSyncStatus !== 'unsynced'; - } else { - _isSync = true; - } - } return { title: _templateInfo?.title || _record?.title, icon: unlock( select( editorStore ) ).getPostIcon( postType, { area: _record?.area, } ), - isSync: _isSync, isFrontPage: siteSettings?.page_on_front === postId, isPostsPage: siteSettings?.page_for_posts === postId, }; @@ -84,12 +64,7 @@ export default function PostCardPanel( { className="editor-post-card-panel__header" align="flex-start" > - <Icon - className={ clsx( 'editor-post-card-panel__icon', { - 'is-sync': isSync, - } ) } - icon={ icon } - /> + <Icon className="editor-post-card-panel__icon" icon={ icon } /> <Text numberOfLines={ 2 } truncate From cf4aa6f40c5bc680bd68bd422f7c27d1cef4f47c Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Fri, 25 Oct 2024 07:51:01 -0700 Subject: [PATCH 1352/1908] Style Book: fix comment output in styles (#66439) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/components/style-book/constants.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/edit-site/src/components/style-book/constants.ts b/packages/edit-site/src/components/style-book/constants.ts index 1ba1bf5e3dffa9..6aa280c937d42d 100644 --- a/packages/edit-site/src/components/style-book/constants.ts +++ b/packages/edit-site/src/components/style-book/constants.ts @@ -143,6 +143,13 @@ export const STYLE_BOOK_CATEGORIES: StyleBookCategory[] = [ }, ]; +// Forming a "block formatting context" to prevent margin collapsing. +// @see https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context +const ROOT_CONTAINER = ` + .is-root-container { + display: flow-root; + } +`; // The content area of the Style Book is rendered within an iframe so that global styles // are applied to elements within the entire content area. To support elements that are // not part of the block previews, such as headings and layout for the block previews, @@ -151,17 +158,13 @@ export const STYLE_BOOK_CATEGORIES: StyleBookCategory[] = [ // applied to the `button` element, targeted via `.edit-site-style-book__example`. // This is to ensure that browser default styles for buttons are not applied to the previews. export const STYLE_BOOK_IFRAME_STYLES = ` - // Forming a "block formatting context" to prevent margin collapsing. - // @see https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context - .is-root-container { - display: flow-root; - } - body { position: relative; padding: 32px !important; } + ${ ROOT_CONTAINER } + .edit-site-style-book__examples { max-width: 1200px; margin: 0 auto; From 506342b23bff06f4407f2df4950d62198df48fe6 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Fri, 25 Oct 2024 07:58:11 -0700 Subject: [PATCH 1353/1908] Set `ResizableEditor` height based on border-box (#66342) Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../src/components/visual-editor/index.js | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/packages/editor/src/components/visual-editor/index.js b/packages/editor/src/components/visual-editor/index.js index 1c8eb5c3b77640..6a5466a265c3eb 100644 --- a/packages/editor/src/components/visual-editor/index.js +++ b/packages/editor/src/components/visual-editor/index.js @@ -16,7 +16,7 @@ import { privateApis as blockEditorPrivateApis, __experimentalUseResizeCanvas as useResizeCanvas, } from '@wordpress/block-editor'; -import { useEffect, useRef, useMemo } from '@wordpress/element'; +import { useEffect, useRef, useMemo, useState } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; import { parse } from '@wordpress/blocks'; import { store as coreStore } from '@wordpress/core-data'; @@ -106,7 +106,10 @@ function VisualEditor( { contentRef, className, } ) { - const [ resizeObserver, sizes ] = useResizeObserver(); + const [ contentHeight, setContentHeight ] = useState( '' ); + const effectContentHeight = useResizeObserver( ( [ entry ] ) => { + setContentHeight( entry.borderBoxSize[ 0 ].blockSize ); + } ); const isMobileViewport = useViewportMatch( 'small', '<' ); const { renderingMode, @@ -323,21 +326,6 @@ function VisualEditor( { .is-root-container.alignfull { max-width: none; margin-left: auto; margin-right: auto;} .is-root-container.alignfull:where(.is-layout-flow) > :not(.alignleft):not(.alignright) { max-width: none;}`; - const localRef = useRef(); - const typewriterRef = useTypewriter(); - contentRef = useMergeRefs( [ - localRef, - contentRef, - renderingMode === 'post-only' ? typewriterRef : null, - useFlashEditableBlocks( { - isEnabled: renderingMode === 'template-locked', - } ), - useSelectNearestEditableBlock( { - isEnabled: renderingMode === 'template-locked', - } ), - useZoomOutModeExit(), - ] ); - const forceFullHeight = postType === NAVIGATION_POST_TYPE; const enableResizing = [ @@ -368,6 +356,24 @@ function VisualEditor( { ]; }, [ styles, enableResizing ] ); + const localRef = useRef(); + const typewriterRef = useTypewriter(); + contentRef = useMergeRefs( [ + localRef, + contentRef, + renderingMode === 'post-only' ? typewriterRef : null, + useFlashEditableBlocks( { + isEnabled: renderingMode === 'template-locked', + } ), + useSelectNearestEditableBlock( { + isEnabled: renderingMode === 'template-locked', + } ), + useZoomOutModeExit(), + // Avoid resize listeners when not needed, these will trigger + // unnecessary re-renders when animating the iframe width. + enableResizing ? effectContentHeight : null, + ] ); + return ( <div className={ clsx( @@ -385,7 +391,7 @@ function VisualEditor( { <ResizableEditor enableResizing={ enableResizing } height={ - sizes.height && ! forceFullHeight ? sizes.height : '100%' + contentHeight && ! forceFullHeight ? contentHeight : '100%' } > <BlockCanvas @@ -479,12 +485,6 @@ function VisualEditor( { /> ) } </RecursionProvider> - { - // Avoid resize listeners when not needed, - // these will trigger unnecessary re-renders - // when animating the iframe width. - enableResizing && resizeObserver - } </BlockCanvas> </ResizableEditor> </div> From 0466f7d510ef5185d054b3d30b19f21ed9ad986b Mon Sep 17 00:00:00 2001 From: Miguel Fonseca <150562+mcsf@users.noreply.github.com> Date: Fri, 25 Oct 2024 18:16:13 +0100 Subject: [PATCH 1354/1908] Editor: Multi-entity saving: Show correct count of entities to be saved (#66482) The modal was incorrectly displaying the number of different *types* of entities to be saved. This result was inconsistent with the actual list of entities rendered underneath and with the "Review _n_ changes" label on the left-hand sidebar. --- packages/editor/src/components/entities-saved-states/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/entities-saved-states/index.js b/packages/editor/src/components/entities-saved-states/index.js index ba84ef2b392f5b..849bd2d0d71c8c 100644 --- a/packages/editor/src/components/entities-saved-states/index.js +++ b/packages/editor/src/components/entities-saved-states/index.js @@ -177,9 +177,9 @@ export function EntitiesSavedStatesExtensible( { _n( 'There is <strong>%d site change</strong> waiting to be saved.', 'There are <strong>%d site changes</strong> waiting to be saved.', - sortedPartitionedSavables.length + dirtyEntityRecords.length ), - sortedPartitionedSavables.length + dirtyEntityRecords.length ), { strong: <strong /> } ) From 76a5ba19f87a8391e8a1365dcd9e1318d73e1458 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Sat, 26 Oct 2024 21:11:16 +0900 Subject: [PATCH 1355/1908] BorderBoxControl: Deprecate 36px default size (#65752) * Add utility function * BorderBoxControl: Deprecate 36px default size * Fix naming * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ .../border-box-control/README.md | 1 + .../border-box-control/component.tsx | 1 + .../border-box-control/hook.ts | 7 ++++++ .../stories/index.story.tsx | 1 + .../src/border-box-control/test/index.tsx | 1 + .../src/utils/deprecated-36px-size.ts | 24 +++++++++++++++++++ 7 files changed, 39 insertions(+) create mode 100644 packages/components/src/utils/deprecated-36px-size.ts diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 2025a550d55e0f..71e51bc9741b50 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Deprecations + +- `BorderBoxControl`: Deprecate 36px default size ([#65752](https://github.com/WordPress/gutenberg/pull/65752)). + ### Bug Fixes - `ColorPalette`: prevent overflow of custom color button background ([#66152](https://github.com/WordPress/gutenberg/pull/66152)). diff --git a/packages/components/src/border-box-control/border-box-control/README.md b/packages/components/src/border-box-control/border-box-control/README.md index e67a1386103c1a..9d51be2901a2a3 100644 --- a/packages/components/src/border-box-control/border-box-control/README.md +++ b/packages/components/src/border-box-control/border-box-control/README.md @@ -47,6 +47,7 @@ const MyBorderBoxControl = () => { return ( <BorderBoxControl + __next40pxDefaultSize colors={ colors } label={ __( 'Borders' ) } onChange={ onChange } diff --git a/packages/components/src/border-box-control/border-box-control/component.tsx b/packages/components/src/border-box-control/border-box-control/component.tsx index 1dd3437aa50de4..d2d77adc69eb89 100644 --- a/packages/components/src/border-box-control/border-box-control/component.tsx +++ b/packages/components/src/border-box-control/border-box-control/component.tsx @@ -175,6 +175,7 @@ const UnconnectedBorderBoxControl = ( * * return ( * <BorderBoxControl + * __next40pxDefaultSize * colors={ colors } * label={ __( 'Borders' ) } * onChange={ onChange } diff --git a/packages/components/src/border-box-control/border-box-control/hook.ts b/packages/components/src/border-box-control/border-box-control/hook.ts index 6756bd51188fb4..6ab30056665433 100644 --- a/packages/components/src/border-box-control/border-box-control/hook.ts +++ b/packages/components/src/border-box-control/border-box-control/hook.ts @@ -19,6 +19,7 @@ import { import type { WordPressComponentProps } from '../../context'; import { useContextSystem } from '../../context'; import { useCx } from '../../utils/hooks/use-cx'; +import { maybeWarnDeprecated36pxSize } from '../../utils/deprecated-36px-size'; import type { Border } from '../../border-control/types'; import type { Borders, BorderSide, BorderBoxControlProps } from '../types'; @@ -39,6 +40,12 @@ export function useBorderBoxControl( ...otherProps } = useContextSystem( props, 'BorderBoxControl' ); + maybeWarnDeprecated36pxSize( { + componentName: 'BorderBoxControl', + __next40pxDefaultSize, + size, + } ); + const computedSize = size === 'default' && __next40pxDefaultSize ? '__unstable-large' : size; diff --git a/packages/components/src/border-box-control/stories/index.story.tsx b/packages/components/src/border-box-control/stories/index.story.tsx index 5341dacab646eb..0a961d34fb93d3 100644 --- a/packages/components/src/border-box-control/stories/index.story.tsx +++ b/packages/components/src/border-box-control/stories/index.story.tsx @@ -84,4 +84,5 @@ Default.args = { colors, label: 'Borders', enableStyle: true, + __next40pxDefaultSize: true, }; diff --git a/packages/components/src/border-box-control/test/index.tsx b/packages/components/src/border-box-control/test/index.tsx index fe5f7e7a4f1fff..fb536656453f4d 100644 --- a/packages/components/src/border-box-control/test/index.tsx +++ b/packages/components/src/border-box-control/test/index.tsx @@ -44,6 +44,7 @@ const props = { props.value = newValue; } ), value: undefined, + __next40pxDefaultSize: true, }; const toggleLabelRegex = /Border color( and style)* picker/; diff --git a/packages/components/src/utils/deprecated-36px-size.ts b/packages/components/src/utils/deprecated-36px-size.ts new file mode 100644 index 00000000000000..92b2cd8ddce274 --- /dev/null +++ b/packages/components/src/utils/deprecated-36px-size.ts @@ -0,0 +1,24 @@ +/** + * WordPress dependencies + */ +import deprecated from '@wordpress/deprecated'; + +export function maybeWarnDeprecated36pxSize( { + componentName, + __next40pxDefaultSize, + size, +}: { + componentName: string; + __next40pxDefaultSize: boolean | undefined; + size: string; +} ) { + if ( __next40pxDefaultSize || size !== 'default' ) { + return; + } + + deprecated( `36px default size for wp.components.${ componentName }`, { + since: '6.7', + version: '7.0', + hint: 'Set the `__next40pxDefaultSize` prop to true to start opting into the new default size, which will become the default in a future version.', + } ); +} From bf84ac6cf918591c394d09dbb53caa7e16be34bb Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Sat, 26 Oct 2024 21:58:48 +0900 Subject: [PATCH 1356/1908] BorderControl: Deprecate 36px default size (#65755) * Add utility function * BorderBoxControl: Deprecate 36px default size * Fix naming * Add changelog * BorderControl: Deprecate 36px default size * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/border-control/border-control/README.md | 1 + .../src/border-control/border-control/component.tsx | 1 + .../components/src/border-control/border-control/hook.ts | 8 +++++++- .../components/src/border-control/stories/index.story.tsx | 1 + packages/components/src/border-control/test/index.js | 1 + packages/components/src/utils/deprecated-36px-size.ts | 4 ++-- 7 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 71e51bc9741b50..a9f1286bdc4167 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Deprecations - `BorderBoxControl`: Deprecate 36px default size ([#65752](https://github.com/WordPress/gutenberg/pull/65752)). +- `BorderControl`: Deprecate 36px default size ([#65755](https://github.com/WordPress/gutenberg/pull/65755)). ### Bug Fixes diff --git a/packages/components/src/border-control/border-control/README.md b/packages/components/src/border-control/border-control/README.md index fbd0c10e418d5a..0afda1ee31ae81 100644 --- a/packages/components/src/border-control/border-control/README.md +++ b/packages/components/src/border-control/border-control/README.md @@ -30,6 +30,7 @@ const MyBorderControl = () => { return ( <BorderControl + __next40pxDefaultSize colors={ colors } label={ __( 'Border' ) } onChange={ setBorder } diff --git a/packages/components/src/border-control/border-control/component.tsx b/packages/components/src/border-control/border-control/component.tsx index 21be22c9dd55d8..31eeb166a2d60f 100644 --- a/packages/components/src/border-control/border-control/component.tsx +++ b/packages/components/src/border-control/border-control/component.tsx @@ -154,6 +154,7 @@ const UnconnectedBorderControl = ( * * return ( * <BorderControl + * __next40pxDefaultSize * colors={ colors } * label={ __( 'Border' ) } * onChange={ onChange } diff --git a/packages/components/src/border-control/border-control/hook.ts b/packages/components/src/border-control/border-control/hook.ts index 676ff9ea2cc6ed..67af7ce42416c3 100644 --- a/packages/components/src/border-control/border-control/hook.ts +++ b/packages/components/src/border-control/border-control/hook.ts @@ -11,8 +11,8 @@ import { parseQuantityAndUnitFromRawValue } from '../../unit-control/utils'; import type { WordPressComponentProps } from '../../context'; import { useContextSystem } from '../../context'; import { useCx } from '../../utils/hooks/use-cx'; - import type { Border, BorderControlProps } from '../types'; +import { maybeWarnDeprecated36pxSize } from '../../utils/deprecated-36px-size'; // If either width or color are defined, the border is considered valid // and a border style can be set as well. @@ -41,6 +41,12 @@ export function useBorderControl( ...otherProps } = useContextSystem( props, 'BorderControl' ); + maybeWarnDeprecated36pxSize( { + componentName: 'BorderControl', + __next40pxDefaultSize, + size, + } ); + const computedSize = size === 'default' && __next40pxDefaultSize ? '__unstable-large' : size; diff --git a/packages/components/src/border-control/stories/index.story.tsx b/packages/components/src/border-control/stories/index.story.tsx index 0756a18ac5c0e5..3b5fa740d092d6 100644 --- a/packages/components/src/border-control/stories/index.story.tsx +++ b/packages/components/src/border-control/stories/index.story.tsx @@ -93,6 +93,7 @@ export const Default = Template.bind( {} ); Default.args = { colors, label: 'Border', + __next40pxDefaultSize: true, enableAlpha: true, enableStyle: true, shouldSanitizeBorder: true, diff --git a/packages/components/src/border-control/test/index.js b/packages/components/src/border-control/test/index.js index 000a89e14a40b3..ec7fb18837f97d 100644 --- a/packages/components/src/border-control/test/index.js +++ b/packages/components/src/border-control/test/index.js @@ -31,6 +31,7 @@ function createProps( customProps ) { props.value = newValue; } ), value: defaultBorder, + __next40pxDefaultSize: true, ...customProps, }; return props; diff --git a/packages/components/src/utils/deprecated-36px-size.ts b/packages/components/src/utils/deprecated-36px-size.ts index 92b2cd8ddce274..e28e9eebb31a99 100644 --- a/packages/components/src/utils/deprecated-36px-size.ts +++ b/packages/components/src/utils/deprecated-36px-size.ts @@ -17,8 +17,8 @@ export function maybeWarnDeprecated36pxSize( { } deprecated( `36px default size for wp.components.${ componentName }`, { - since: '6.7', - version: '7.0', + since: '6.8', + version: '7.1', hint: 'Set the `__next40pxDefaultSize` prop to true to start opting into the new default size, which will become the default in a future version.', } ); } From c40eb72df45c86166dff6d21fb42b2bbdbad9ce1 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Sun, 27 Oct 2024 14:02:57 +0100 Subject: [PATCH 1357/1908] DrodownMenuV2: Rename folder to `menu` (#66473) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- docs/tool/manifest.js | 2 +- packages/components/src/{dropdown-menu-v2 => menu}/README.md | 0 .../components/src/{dropdown-menu-v2 => menu}/checkbox-item.tsx | 0 packages/components/src/{dropdown-menu-v2 => menu}/context.tsx | 0 .../components/src/{dropdown-menu-v2 => menu}/group-label.tsx | 0 packages/components/src/{dropdown-menu-v2 => menu}/group.tsx | 0 packages/components/src/{dropdown-menu-v2 => menu}/index.tsx | 0 .../src/{dropdown-menu-v2 => menu}/item-help-text.tsx | 0 .../components/src/{dropdown-menu-v2 => menu}/item-label.tsx | 0 packages/components/src/{dropdown-menu-v2 => menu}/item.tsx | 0 .../components/src/{dropdown-menu-v2 => menu}/radio-item.tsx | 0 .../components/src/{dropdown-menu-v2 => menu}/separator.tsx | 0 .../src/{dropdown-menu-v2 => menu}/stories/index.story.tsx | 0 packages/components/src/{dropdown-menu-v2 => menu}/styles.ts | 0 .../components/src/{dropdown-menu-v2 => menu}/test/index.tsx | 0 packages/components/src/{dropdown-menu-v2 => menu}/types.ts | 0 .../use-temporary-focus-visible-fix.ts | 0 packages/components/src/private-apis.ts | 2 +- 18 files changed, 2 insertions(+), 2 deletions(-) rename packages/components/src/{dropdown-menu-v2 => menu}/README.md (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/checkbox-item.tsx (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/context.tsx (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/group-label.tsx (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/group.tsx (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/index.tsx (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/item-help-text.tsx (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/item-label.tsx (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/item.tsx (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/radio-item.tsx (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/separator.tsx (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/stories/index.story.tsx (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/styles.ts (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/test/index.tsx (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/types.ts (100%) rename packages/components/src/{dropdown-menu-v2 => menu}/use-temporary-focus-visible-fix.ts (100%) diff --git a/docs/tool/manifest.js b/docs/tool/manifest.js index 3c1f0fee2090ff..2004fae84f7ccc 100644 --- a/docs/tool/manifest.js +++ b/docs/tool/manifest.js @@ -15,7 +15,7 @@ const componentPaths = glob( 'packages/components/src/*/**/README.md', { '**/src/mobile/**/README.md', 'packages/components/src/theme/README.md', 'packages/components/src/view/README.md', - 'packages/components/src/dropdown-menu-v2/README.md', + 'packages/components/src/menu/README.md', 'packages/components/src/tabs/README.md', 'packages/components/src/custom-select-control-v2/README.md', ], diff --git a/packages/components/src/dropdown-menu-v2/README.md b/packages/components/src/menu/README.md similarity index 100% rename from packages/components/src/dropdown-menu-v2/README.md rename to packages/components/src/menu/README.md diff --git a/packages/components/src/dropdown-menu-v2/checkbox-item.tsx b/packages/components/src/menu/checkbox-item.tsx similarity index 100% rename from packages/components/src/dropdown-menu-v2/checkbox-item.tsx rename to packages/components/src/menu/checkbox-item.tsx diff --git a/packages/components/src/dropdown-menu-v2/context.tsx b/packages/components/src/menu/context.tsx similarity index 100% rename from packages/components/src/dropdown-menu-v2/context.tsx rename to packages/components/src/menu/context.tsx diff --git a/packages/components/src/dropdown-menu-v2/group-label.tsx b/packages/components/src/menu/group-label.tsx similarity index 100% rename from packages/components/src/dropdown-menu-v2/group-label.tsx rename to packages/components/src/menu/group-label.tsx diff --git a/packages/components/src/dropdown-menu-v2/group.tsx b/packages/components/src/menu/group.tsx similarity index 100% rename from packages/components/src/dropdown-menu-v2/group.tsx rename to packages/components/src/menu/group.tsx diff --git a/packages/components/src/dropdown-menu-v2/index.tsx b/packages/components/src/menu/index.tsx similarity index 100% rename from packages/components/src/dropdown-menu-v2/index.tsx rename to packages/components/src/menu/index.tsx diff --git a/packages/components/src/dropdown-menu-v2/item-help-text.tsx b/packages/components/src/menu/item-help-text.tsx similarity index 100% rename from packages/components/src/dropdown-menu-v2/item-help-text.tsx rename to packages/components/src/menu/item-help-text.tsx diff --git a/packages/components/src/dropdown-menu-v2/item-label.tsx b/packages/components/src/menu/item-label.tsx similarity index 100% rename from packages/components/src/dropdown-menu-v2/item-label.tsx rename to packages/components/src/menu/item-label.tsx diff --git a/packages/components/src/dropdown-menu-v2/item.tsx b/packages/components/src/menu/item.tsx similarity index 100% rename from packages/components/src/dropdown-menu-v2/item.tsx rename to packages/components/src/menu/item.tsx diff --git a/packages/components/src/dropdown-menu-v2/radio-item.tsx b/packages/components/src/menu/radio-item.tsx similarity index 100% rename from packages/components/src/dropdown-menu-v2/radio-item.tsx rename to packages/components/src/menu/radio-item.tsx diff --git a/packages/components/src/dropdown-menu-v2/separator.tsx b/packages/components/src/menu/separator.tsx similarity index 100% rename from packages/components/src/dropdown-menu-v2/separator.tsx rename to packages/components/src/menu/separator.tsx diff --git a/packages/components/src/dropdown-menu-v2/stories/index.story.tsx b/packages/components/src/menu/stories/index.story.tsx similarity index 100% rename from packages/components/src/dropdown-menu-v2/stories/index.story.tsx rename to packages/components/src/menu/stories/index.story.tsx diff --git a/packages/components/src/dropdown-menu-v2/styles.ts b/packages/components/src/menu/styles.ts similarity index 100% rename from packages/components/src/dropdown-menu-v2/styles.ts rename to packages/components/src/menu/styles.ts diff --git a/packages/components/src/dropdown-menu-v2/test/index.tsx b/packages/components/src/menu/test/index.tsx similarity index 100% rename from packages/components/src/dropdown-menu-v2/test/index.tsx rename to packages/components/src/menu/test/index.tsx diff --git a/packages/components/src/dropdown-menu-v2/types.ts b/packages/components/src/menu/types.ts similarity index 100% rename from packages/components/src/dropdown-menu-v2/types.ts rename to packages/components/src/menu/types.ts diff --git a/packages/components/src/dropdown-menu-v2/use-temporary-focus-visible-fix.ts b/packages/components/src/menu/use-temporary-focus-visible-fix.ts similarity index 100% rename from packages/components/src/dropdown-menu-v2/use-temporary-focus-visible-fix.ts rename to packages/components/src/menu/use-temporary-focus-visible-fix.ts diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index 51f820251b8d7c..6d28765c2f685e 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -3,7 +3,7 @@ */ import { positionToPlacement as __experimentalPopoverLegacyPositionToPlacement } from './popover/utils'; import { createPrivateSlotFill } from './slot-fill'; -import { DropdownMenuV2 } from './dropdown-menu-v2'; +import { DropdownMenuV2 } from './menu'; import { ComponentsContext } from './context/context-system-provider'; import Theme from './theme'; import { Tabs } from './tabs'; From 7751045b48e425bb9e34926ee6986b2f231e5bef Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Mon, 28 Oct 2024 08:07:40 +1100 Subject: [PATCH 1358/1908] Meta boxes: Fix typo "metabox pane" to "meta box panel". (#66502) Co-authored-by: peterwilsoncc <peterwilsoncc@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: isaeedam <isaeedam@git.wordpress.org> --- packages/edit-post/src/components/layout/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 42250054a70873..ae56a394971a53 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -318,7 +318,7 @@ function MetaBoxesMain( { isLegacy } ) { </Tooltip> <VisuallyHidden id={ separatorHelpId }> { __( - 'Use up and down arrow keys to resize the metabox pane.' + 'Use up and down arrow keys to resize the meta box panel.' ) } </VisuallyHidden> </> From 86a3bc9bb3995928b940f20a934d50a1f6f80ed3 Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Mon, 28 Oct 2024 01:05:35 +0100 Subject: [PATCH 1359/1908] Misc i18n fixes (#66510) Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: peterwilsoncc <peterwilsoncc@git.wordpress.org> --- .../downloadable-block-list-item/index.js | 12 +++---- .../src/components/block-card/index.js | 6 ++-- .../components/block-patterns-paging/index.js | 2 +- .../block-variation-transforms/index.js | 4 +-- .../inserter-button/index.native.js | 2 +- .../components/spacing-sizes-control/index.js | 6 ++-- .../input-controls/spacing-input-control.js | 8 ++--- .../src/components/url-input/index.js | 2 +- .../components/use-block-commands/index.js | 2 +- .../src/utils/get-font-styles-and-weights.js | 4 +-- packages/block-library/src/avatar/hooks.js | 5 ++- packages/block-library/src/avatar/index.php | 9 +++-- .../src/comment-author-avatar/index.php | 2 +- .../block-library/src/latest-posts/edit.js | 2 +- .../block-library/src/latest-posts/index.php | 2 +- .../edit/menu-inspector-controls.js | 4 +-- .../edit/navigation-menu-selector.js | 4 +-- .../src/post-featured-image/edit.js | 2 +- .../src/post-time-to-read/edit.js | 4 +-- .../src/post-time-to-read/index.php | 2 +- .../block-library/src/query-title/edit.js | 4 +-- .../edit/inspector-controls/order-control.js | 4 +-- packages/block-library/src/rss/index.php | 2 +- .../src/template-part/edit/index.js | 2 +- .../block-library/src/video/tracks-editor.js | 4 +-- .../border-control-dropdown/component.tsx | 36 ++++++++++++------- .../components/src/color-palette/index.tsx | 2 +- .../gradient-bar/control-points.tsx | 2 +- .../src/font-size-picker/index.native.js | 14 ++++---- .../index.native.js | 4 +-- .../mobile/bottom-sheet/range-cell.native.js | 2 +- .../bottom-sheet/stepper-cell/index.native.js | 2 +- .../tools-panel-header/component.tsx | 2 +- .../dataviews-selection-checkbox/index.tsx | 5 +-- .../dataviews-view-config/index.tsx | 4 +-- .../src/dataforms-layouts/panel/index.tsx | 4 +-- .../edit-post/src/components/layout/index.js | 2 +- .../src/components/add-new-post/index.js | 2 +- .../src/components/add-new-template/index.js | 2 +- .../src/components/add-new-template/utils.js | 21 ++++++----- .../edit-site/src/components/editor/index.js | 2 +- .../src/components/editor/use-editor-title.js | 6 ++-- .../screen-revisions/revisions-buttons.js | 4 +-- .../global-styles/variations/variation.js | 6 ++-- .../delete-category-menu-item.js | 8 ++--- .../src/components/pagination/index.js | 2 +- .../src/components/post-fields/index.js | 4 +-- .../src/components/save-panel/index.js | 2 +- .../use-navigation-menu-handlers.js | 4 +-- .../build-navigation-label.js | 8 ++--- .../index.js | 8 ++--- .../sidebar-navigation-screen/index.js | 3 +- .../src/components/editor-interface/index.js | 5 +-- .../src/components/page-attributes/parent.js | 10 +++--- .../src/components/post-author/panel.js | 6 ++-- .../post-content-information/index.js | 2 +- .../components/post-last-revision/index.js | 2 +- .../src/components/post-schedule/label.js | 2 +- .../hierarchical-term-selector.js | 4 +-- .../editor/src/components/post-url/panel.js | 6 ++-- .../editor/src/components/sidebar/header.js | 5 +-- .../editor/src/components/sidebar/index.js | 8 +++-- .../src/components/time-to-read/index.js | 6 ++-- .../actions/duplicate-template-part.tsx | 6 ++-- packages/editor/src/store/private-actions.js | 6 ++-- packages/fields/src/actions/delete-post.tsx | 13 ++++--- .../fields/src/actions/duplicate-post.tsx | 4 +-- .../src/actions/view-post-revisions.tsx | 2 +- .../components/interface-skeleton/index.js | 2 +- .../src/components/duplicate-pattern-modal.js | 6 ++-- .../pattern-overrides-block-controls.js | 2 +- 71 files changed, 193 insertions(+), 165 deletions(-) diff --git a/packages/block-directory/src/components/downloadable-block-list-item/index.js b/packages/block-directory/src/components/downloadable-block-list-item/index.js index 7a5f479174ab25..c04ea8ea1767bd 100644 --- a/packages/block-directory/src/components/downloadable-block-list-item/index.js +++ b/packages/block-directory/src/components/downloadable-block-list-item/index.js @@ -34,28 +34,28 @@ function getDownloadableBlockLabel( const stars = Math.round( rating / 0.5 ) * 0.5; if ( ! isInstalled && hasNotice ) { - /* translators: %1$s: block title */ + /* translators: %s: block title */ return sprintf( 'Retry installing %s.', decodeEntities( title ) ); } if ( isInstalled ) { - /* translators: %1$s: block title */ + /* translators: %s: block title */ return sprintf( 'Add %s.', decodeEntities( title ) ); } if ( isInstalling ) { - /* translators: %1$s: block title */ + /* translators: %s: block title */ return sprintf( 'Installing %s.', decodeEntities( title ) ); } // No ratings yet, just use the title. if ( ratingCount < 1 ) { - /* translators: %1$s: block title */ + /* translators: %s: block title */ return sprintf( 'Install %s.', decodeEntities( title ) ); } return sprintf( - /* translators: %1$s: block title, %2$s: average rating, %3$s: total ratings count. */ + /* translators: 1: block title, 2: average rating, 3: total ratings count. */ _n( 'Install %1$s. %2$s stars with %3$s review.', 'Install %1$s. %2$s stars with %3$s reviews.', @@ -131,7 +131,7 @@ function DownloadableBlockListItem( { item, onClick } ) { <span className="block-directory-downloadable-block-list-item__title"> { createInterpolateElement( sprintf( - /* translators: %1$s: block title, %2$s: author name. */ + /* translators: 1: block title. 2: author name. */ __( '%1$s <span>by %2$s</span>' ), decodeEntities( title ), author diff --git a/packages/block-editor/src/components/block-card/index.js b/packages/block-editor/src/components/block-card/index.js index 4d40fe07d55471..c8a12a3be5ef6a 100644 --- a/packages/block-editor/src/components/block-card/index.js +++ b/packages/block-editor/src/components/block-card/index.js @@ -13,7 +13,7 @@ import { __experimentalVStack as VStack, } from '@wordpress/components'; import { chevronLeft, chevronRight } from '@wordpress/icons'; -import { __, isRTL, sprintf } from '@wordpress/i18n'; +import { __, _x, isRTL, sprintf } from '@wordpress/i18n'; import { useSelect, useDispatch } from '@wordpress/data'; /** @@ -68,8 +68,8 @@ function BlockCard( { title, icon, description, blockType, className, name } ) { <h2 className="block-editor-block-card__title"> { name?.length ? sprintf( - // translators: %1$s: Custom block name. %2$s: Block title. - __( '%1$s (%2$s)' ), + // translators: 1: Custom block name. 2: Block title. + _x( '%1$s (%2$s)', 'block label' ), name, title ) diff --git a/packages/block-editor/src/components/block-patterns-paging/index.js b/packages/block-editor/src/components/block-patterns-paging/index.js index e4d7ce49b90f3e..d4d513902ca705 100644 --- a/packages/block-editor/src/components/block-patterns-paging/index.js +++ b/packages/block-editor/src/components/block-patterns-paging/index.js @@ -62,7 +62,7 @@ export default function Pagination( { </HStack> <Text variant="muted"> { sprintf( - // translators: %1$s: Current page number, %2$s: Total number of pages. + // translators: 1: Current page number. 2: Total number of pages. _x( '%1$s of %2$s', 'paging' ), currentPage, numPages diff --git a/packages/block-editor/src/components/block-variation-transforms/index.js b/packages/block-editor/src/components/block-variation-transforms/index.js index 5850fc52b37b68..f03e72843d4731 100644 --- a/packages/block-editor/src/components/block-variation-transforms/index.js +++ b/packages/block-editor/src/components/block-variation-transforms/index.js @@ -45,7 +45,7 @@ function VariationsButtons( { selectedValue === variation.name ? variation.title : sprintf( - /* translators: %s: Name of the block variation */ + /* translators: %s: Block or block variation name. */ __( 'Transform to %s' ), variation.title ) @@ -127,7 +127,7 @@ function VariationsToggleGroupControl( { selectedValue === variation.name ? variation.title : sprintf( - /* translators: %s: Name of the block variation */ + /* translators: %s: Block or block variation name. */ __( 'Transform to %s' ), variation.title ) diff --git a/packages/block-editor/src/components/inserter-button/index.native.js b/packages/block-editor/src/components/inserter-button/index.native.js index 7df5d450d1e629..d9147b2f4d95bd 100644 --- a/packages/block-editor/src/components/inserter-button/index.native.js +++ b/packages/block-editor/src/components/inserter-button/index.native.js @@ -54,7 +54,7 @@ class MenuItem extends Component { const accessibilityLabelFormat = blockIsNew ? // translators: Newly available block name. %s: The localized block name __( '%s block, newly available' ) - : // translators: Block name. %s: The localized block name + : // translators: %s: Block name e.g. "Image block" __( '%s block' ); const accessibilityLabel = sprintf( accessibilityLabelFormat, diff --git a/packages/block-editor/src/components/spacing-sizes-control/index.js b/packages/block-editor/src/components/spacing-sizes-control/index.js index 6ca143d14706ac..458b0abee60f2e 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/index.js +++ b/packages/block-editor/src/components/spacing-sizes-control/index.js @@ -7,7 +7,7 @@ import { __experimentalVStack as VStack, } from '@wordpress/components'; import { useState } from '@wordpress/element'; -import { __, sprintf } from '@wordpress/i18n'; +import { _x, sprintf } from '@wordpress/i18n'; /** * Internal dependencies @@ -89,8 +89,8 @@ export default function SpacingSizesControl( { ALL_SIDES.includes( view ) && showSideInLabel ? LABELS[ view ] : ''; const label = sprintf( - // translators: 2. Type of spacing being modified (Padding, margin, etc). 1: The side of the block being modified (top, bottom, left etc.). - __( '%1$s %2$s' ), + // translators: 1: The side of the block being modified (top, bottom, left etc.). 2. Type of spacing being modified (padding, margin, etc). + _x( '%1$s %2$s', 'spacing' ), labelProp, sideLabel ).trim(); diff --git a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js index d00feed704d17a..f03af41bfbc00d 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js +++ b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js @@ -14,7 +14,7 @@ import { import { useSelect } from '@wordpress/data'; import { useState, useMemo } from '@wordpress/element'; import { usePrevious } from '@wordpress/compose'; -import { __, sprintf } from '@wordpress/i18n'; +import { __, _x, sprintf } from '@wordpress/i18n'; import { settings } from '@wordpress/icons'; /** @@ -124,7 +124,7 @@ export default function SpacingInputControl( { ...spacingSizes, { name: ! isMixed - ? // translators: A custom measurement, eg. a number followed by a unit like 12px. + ? // translators: %s: A custom measurement, e.g. a number followed by a unit like 12px. sprintf( __( 'Custom (%s)' ), value ) : __( 'Mixed' ), slug: 'custom', @@ -200,8 +200,8 @@ export default function SpacingInputControl( { const typeLabel = showSideInLabel ? type?.toLowerCase() : type; const ariaLabel = sprintf( - // translators: 1: The side of the block being modified (top, bottom, left, All sides etc.). 2. Type of spacing being modified (Padding, margin, etc) - __( '%1$s %2$s' ), + // translators: 1: The side of the block being modified (top, bottom, left etc.). 2. Type of spacing being modified (padding, margin, etc). + _x( '%1$s %2$s', 'spacing' ), sideLabel, typeLabel ).trim(); diff --git a/packages/block-editor/src/components/url-input/index.js b/packages/block-editor/src/components/url-input/index.js index cb058be5c932f6..4e7ac61e783661 100644 --- a/packages/block-editor/src/components/url-input/index.js +++ b/packages/block-editor/src/components/url-input/index.js @@ -196,7 +196,7 @@ class URLInput extends Component { if ( !! suggestions.length ) { this.props.debouncedSpeak( sprintf( - /* translators: %s: number of results. */ + /* translators: %d: number of results. */ _n( '%d result found, use up and down arrow keys to navigate.', '%d results found, use up and down arrow keys to navigate.', diff --git a/packages/block-editor/src/components/use-block-commands/index.js b/packages/block-editor/src/components/use-block-commands/index.js index c88ec4e5378926..e739729c8f9e84 100644 --- a/packages/block-editor/src/components/use-block-commands/index.js +++ b/packages/block-editor/src/components/use-block-commands/index.js @@ -113,7 +113,7 @@ export const useTransformCommands = () => { const { name, title, icon } = transformation; return { name: 'core/block-editor/transform-to-' + name.replace( '/', '-' ), - // translators: %s: block title/name. + /* translators: %s: Block or block variation name. */ label: sprintf( __( 'Transform to %s' ), title ), icon: <BlockIcon icon={ icon } />, callback: ( { close } ) => { diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js index dcb56fc86b2673..c832582fa524d5 100644 --- a/packages/block-editor/src/utils/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { _x, __, sprintf } from '@wordpress/i18n'; +import { _x, sprintf } from '@wordpress/i18n'; /** * Internal dependencies @@ -173,7 +173,7 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { ? weightName : sprintf( /* translators: 1: Font weight name. 2: Font style name. */ - __( '%1$s %2$s' ), + _x( '%1$s %2$s', 'font' ), weightName, styleName ); diff --git a/packages/block-library/src/avatar/hooks.js b/packages/block-library/src/avatar/hooks.js index 1f84b5c107682b..d73b604bdef22e 100644 --- a/packages/block-library/src/avatar/hooks.js +++ b/packages/block-library/src/avatar/hooks.js @@ -47,9 +47,8 @@ export function useCommentAvatar( { commentId } ) { src: avatarUrls ? avatarUrls[ avatarUrls.length - 1 ] : defaultAvatar, minSize, maxSize, - // translators: %s is the Author name. alt: authorName - ? // translators: %s is the Author name. + ? // translators: %s: Author name. sprintf( __( '%s Avatar' ), authorName ) : __( 'Default Avatar' ), }; @@ -89,7 +88,7 @@ export function useUserAvatar( { userId, postId, postType } ) { minSize, maxSize, alt: authorDetails - ? // translators: %s is the Author name. + ? // translators: %s: Author name. sprintf( __( '%s Avatar' ), authorDetails?.name ) : __( 'Default Avatar' ), }; diff --git a/packages/block-library/src/avatar/index.php b/packages/block-library/src/avatar/index.php index cc86052af4abe2..d4a01c1c3a1e77 100644 --- a/packages/block-library/src/avatar/index.php +++ b/packages/block-library/src/avatar/index.php @@ -46,7 +46,7 @@ function render_block_core_avatar( $attributes, $content, $block ) { } $author_name = get_the_author_meta( 'display_name', $author_id ); - // translators: %s is the Author name. + // translators: %s: Author name. $alt = sprintf( __( '%s Avatar' ), $author_name ); $avatar_block = get_avatar( $author_id, @@ -64,7 +64,7 @@ function render_block_core_avatar( $attributes, $content, $block ) { // translators: %s is the Author name. $label = 'aria-label="' . esc_attr( sprintf( __( '(%s author archive, opens in a new tab)' ), $author_name ) ) . '"'; } - // translators: %1$s: Author archive link. %2$s: Link target. %3$s Aria label. %4$s Avatar image. + // translators: 1: Author archive link. 2: Link target. %3$s Aria label. %4$s Avatar image. $avatar_block = sprintf( '<a href="%1$s" target="%2$s" %3$s class="wp-block-avatar__link">%4$s</a>', esc_url( get_author_posts_url( $author_id ) ), esc_attr( $attributes['linkTarget'] ), $label, $avatar_block ); } return sprintf( '<div %1s>%2s</div>', $wrapper_attributes, $avatar_block ); @@ -73,7 +73,7 @@ function render_block_core_avatar( $attributes, $content, $block ) { if ( ! $comment ) { return ''; } - /* translators: %s is the Comment Author name */ + /* translators: %s: Author name. */ $alt = sprintf( __( '%s Avatar' ), $comment->comment_author ); $avatar_block = get_avatar( $comment, @@ -88,10 +88,9 @@ function render_block_core_avatar( $attributes, $content, $block ) { if ( isset( $attributes['isLink'] ) && $attributes['isLink'] && isset( $comment->comment_author_url ) && '' !== $comment->comment_author_url ) { $label = ''; if ( '_blank' === $attributes['linkTarget'] ) { - // translators: %s is the Comment Author name. + // translators: %s: Comment author name. $label = 'aria-label="' . esc_attr( sprintf( __( '(%s website link, opens in a new tab)' ), $comment->comment_author ) ) . '"'; } - // translators: %1$s: Comment Author website link. %2$s: Link target. %3$s Aria label. %4$s Avatar image. $avatar_block = sprintf( '<a href="%1$s" target="%2$s" %3$s class="wp-block-avatar__link">%4$s</a>', esc_url( $comment->comment_author_url ), esc_attr( $attributes['linkTarget'] ), $label, $avatar_block ); } return sprintf( '<div %1s>%2s</div>', $wrapper_attributes, $avatar_block ); diff --git a/packages/block-library/src/comment-author-avatar/index.php b/packages/block-library/src/comment-author-avatar/index.php index 7c568fc3ded5e4..1568b6606669c4 100644 --- a/packages/block-library/src/comment-author-avatar/index.php +++ b/packages/block-library/src/comment-author-avatar/index.php @@ -46,7 +46,7 @@ function render_block_core_comment_author_avatar( $attributes, $content, $block $styles = isset( $wrapper_attributes['style'] ) ? $wrapper_attributes['style'] : ''; $classes = isset( $wrapper_attributes['class'] ) ? $wrapper_attributes['class'] : ''; - /* translators: %s is the Comment Author name */ + /* translators: %s: Author name. */ $alt = sprintf( __( '%s Avatar' ), $comment->comment_author ); $avatar_block = get_avatar( diff --git a/packages/block-library/src/latest-posts/edit.js b/packages/block-library/src/latest-posts/edit.js index 7914f10be6bde8..8116b5eecaebf0 100644 --- a/packages/block-library/src/latest-posts/edit.js +++ b/packages/block-library/src/latest-posts/edit.js @@ -589,7 +589,7 @@ export default function LatestPostsEdit( { attributes, setAttributes } ) { { displayAuthor && currentAuthor && ( <div className="wp-block-latest-posts__post-author"> { sprintf( - /* translators: byline. %s: current author. */ + /* translators: byline. %s: author. */ __( 'by %s' ), currentAuthor.name ) } diff --git a/packages/block-library/src/latest-posts/index.php b/packages/block-library/src/latest-posts/index.php index 85c7b58737a1cf..f8fd8ea27bc453 100644 --- a/packages/block-library/src/latest-posts/index.php +++ b/packages/block-library/src/latest-posts/index.php @@ -123,7 +123,7 @@ function render_block_core_latest_posts( $attributes ) { if ( isset( $attributes['displayAuthor'] ) && $attributes['displayAuthor'] ) { $author_display_name = get_the_author_meta( 'display_name', $post->post_author ); - /* translators: byline. %s: current author. */ + /* translators: byline. %s: author. */ $byline = sprintf( __( 'by %s' ), $author_display_name ); if ( ! empty( $author_display_name ) ) { diff --git a/packages/block-library/src/navigation/edit/menu-inspector-controls.js b/packages/block-library/src/navigation/edit/menu-inspector-controls.js index 8f6c2e47fe7759..a2c6078d9fabe2 100644 --- a/packages/block-library/src/navigation/edit/menu-inspector-controls.js +++ b/packages/block-library/src/navigation/edit/menu-inspector-controls.js @@ -26,8 +26,8 @@ import LeafMoreMenu from './leaf-more-menu'; import { updateAttributes } from '../../navigation-link/update-attributes'; import { LinkUI } from '../../navigation-link/link-ui'; -/* translators: %s: The name of a menu. */ -const actionLabel = __( "Switch to '%s'" ); +const actionLabel = + /* translators: %s: The name of a menu. */ __( "Switch to '%s'" ); const BLOCKS_WITH_LINK_UI_SUPPORT = [ 'core/navigation-link', 'core/navigation-submenu', diff --git a/packages/block-library/src/navigation/edit/navigation-menu-selector.js b/packages/block-library/src/navigation/edit/navigation-menu-selector.js index 007220b1789131..dceabf063b26e8 100644 --- a/packages/block-library/src/navigation/edit/navigation-menu-selector.js +++ b/packages/block-library/src/navigation/edit/navigation-menu-selector.js @@ -21,7 +21,7 @@ import useNavigationEntities from '../use-navigation-entities'; function buildMenuLabel( title, id, status ) { if ( ! title ) { - /* translators: %s is the index of the menu in the list of menus. */ + /* translators: %s: the index of the menu in the list of menus. */ return sprintf( __( '(no title %s)' ), id ); } @@ -30,7 +30,7 @@ function buildMenuLabel( title, id, status ) { } return sprintf( - // translators: %1s: title of the menu; %2s: status of the menu (draft, pending, etc.). + // translators: 1: title of the menu. 2: status of the menu (draft, pending, etc.). __( '%1$s (%2$s)' ), decodeEntities( title ), status diff --git a/packages/block-library/src/post-featured-image/edit.js b/packages/block-library/src/post-featured-image/edit.js index dff34379e4f3b4..95441a5a55cfd0 100644 --- a/packages/block-library/src/post-featured-image/edit.js +++ b/packages/block-library/src/post-featured-image/edit.js @@ -207,7 +207,7 @@ export default function PostFeaturedImageEdit( { label={ postType?.labels.singular_name ? sprintf( - // translators: %s: Name of the post type e.g: "Page". + // translators: %s: Name of the post type e.g: "post". __( 'Link to %s' ), postType.labels.singular_name ) diff --git a/packages/block-library/src/post-time-to-read/edit.js b/packages/block-library/src/post-time-to-read/edit.js index abfdce6630a67d..0533b99d3fd9d7 100644 --- a/packages/block-library/src/post-time-to-read/edit.js +++ b/packages/block-library/src/post-time-to-read/edit.js @@ -71,8 +71,8 @@ function PostTimeToReadEdit( { attributes, setAttributes, context } ) { ); return sprintf( - /* translators: %d is the number of minutes the post will take to read. */ - _n( '%d minute', '%d minutes', minutesToRead ), + /* translators: %s: the number of minutes to read the post. */ + _n( '%s minute', '%s minutes', minutesToRead ), minutesToRead ); }, [ contentStructure, blocks ] ); diff --git a/packages/block-library/src/post-time-to-read/index.php b/packages/block-library/src/post-time-to-read/index.php index f7abb1903f04df..eac79d11450b7d 100644 --- a/packages/block-library/src/post-time-to-read/index.php +++ b/packages/block-library/src/post-time-to-read/index.php @@ -32,7 +32,7 @@ function render_block_core_post_time_to_read( $attributes, $content, $block ) { $minutes_to_read = max( 1, (int) round( wp_word_count( $content, $word_count_type ) / $average_reading_rate ) ); $minutes_to_read_string = sprintf( - /* translators: %s is the number of minutes the post will take to read. */ + /* translators: %s: the number of minutes to read the post. */ _n( '%s minute', '%s minutes', $minutes_to_read ), $minutes_to_read ); diff --git a/packages/block-library/src/query-title/edit.js b/packages/block-library/src/query-title/edit.js index 845809a9300137..21d23081837cdf 100644 --- a/packages/block-library/src/query-title/edit.js +++ b/packages/block-library/src/query-title/edit.js @@ -15,7 +15,7 @@ import { HeadingLevelDropdown, } from '@wordpress/block-editor'; import { ToggleControl, PanelBody } from '@wordpress/components'; -import { __, sprintf } from '@wordpress/i18n'; +import { __, _x, sprintf } from '@wordpress/i18n'; /** * Internal dependencies @@ -60,7 +60,7 @@ export default function QueryTitleEdit( { if ( archiveNameLabel ) { title = sprintf( /* translators: 1: Archive type title e.g: "Category", 2: Label of the archive e.g: "Shoes" */ - __( '%1$s: %2$s' ), + _x( '%1$s: %2$s', 'archive label' ), archiveTypeLabel, archiveNameLabel ); diff --git a/packages/block-library/src/query/edit/inspector-controls/order-control.js b/packages/block-library/src/query/edit/inspector-controls/order-control.js index 2f6fa0e589d473..23802f844359d7 100644 --- a/packages/block-library/src/query/edit/inspector-controls/order-control.js +++ b/packages/block-library/src/query/edit/inspector-controls/order-control.js @@ -14,12 +14,12 @@ const orderOptions = [ value: 'date/asc', }, { - /* translators: label for ordering posts by title in ascending order */ + /* translators: Label for ordering posts by title in ascending order. */ label: __( 'A → Z' ), value: 'title/asc', }, { - /* translators: label for ordering posts by title in descending order */ + /* translators: Label for ordering posts by title in descending order. */ label: __( 'Z → A' ), value: 'title/desc', }, diff --git a/packages/block-library/src/rss/index.php b/packages/block-library/src/rss/index.php index 3e8231d259e700..32885863402d5e 100644 --- a/packages/block-library/src/rss/index.php +++ b/packages/block-library/src/rss/index.php @@ -62,7 +62,7 @@ function render_block_core_rss( $attributes ) { if ( is_object( $author ) ) { $author = $author->get_name(); $author = '<span class="wp-block-rss__item-author">' . sprintf( - /* translators: %s: the author. */ + /* translators: byline. %s: author. */ __( 'by %s' ), esc_html( strip_tags( $author ) ) ) . '</span>'; diff --git a/packages/block-library/src/template-part/edit/index.js b/packages/block-library/src/template-part/edit/index.js index 951f875143b0f9..ae941c977e14fd 100644 --- a/packages/block-library/src/template-part/edit/index.js +++ b/packages/block-library/src/template-part/edit/index.js @@ -214,7 +214,7 @@ export default function TemplatePartEdit( { <TagName { ...blockProps }> <Warning> { sprintf( - /* translators: %s: Template part slug */ + /* translators: %s: Template part slug. */ __( 'Template part has been deleted or is unavailable: %s' ), diff --git a/packages/block-library/src/video/tracks-editor.js b/packages/block-library/src/video/tracks-editor.js index d01e365985bc96..10fb241a9ecb30 100644 --- a/packages/block-library/src/video/tracks-editor.js +++ b/packages/block-library/src/video/tracks-editor.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { __, sprintf } from '@wordpress/i18n'; +import { __, _x, sprintf } from '@wordpress/i18n'; import { NavigableMenu, MenuItem, @@ -63,7 +63,7 @@ function TrackList( { tracks, onEditPress } ) { onClick={ () => onEditPress( index ) } aria-label={ sprintf( /* translators: %s: Label of the video text track e.g: "French subtitles" */ - __( 'Edit %s' ), + _x( 'Edit %s', 'text tracks' ), track.label ) } > diff --git a/packages/components/src/border-control/border-control-dropdown/component.tsx b/packages/components/src/border-control/border-control-dropdown/component.tsx index 0223de66a4c78b..827e7973a90432 100644 --- a/packages/components/src/border-control/border-control-dropdown/component.tsx +++ b/packages/components/src/border-control/border-control-dropdown/component.tsx @@ -73,15 +73,19 @@ const getToggleAriaLabel = ( const ariaLabelValue = getAriaLabelColorValue( colorObject.color ); return style ? sprintf( - // translators: %1$s: The name of the color e.g. "vivid red". %2$s: The color's hex code e.g.: "#f00:". %3$s: The current border style selection e.g. "solid". - 'Border color and style picker. The currently selected color is called "%1$s" and has a value of "%2$s". The currently selected style is "%3$s".', + // translators: 1: The name of the color e.g. "vivid red". 2: The color's hex code e.g.: "#f00:". 3: The current border style selection e.g. "solid". + __( + 'Border color and style picker. The currently selected color is called "%1$s" and has a value of "%2$s". The currently selected style is "%3$s".' + ), colorObject.name, ariaLabelValue, style ) : sprintf( - // translators: %1$s: The name of the color e.g. "vivid red". %2$s: The color's hex code e.g.: "#f00:". - 'Border color and style picker. The currently selected color is called "%1$s" and has a value of "%2$s".', + // translators: 1: The name of the color e.g. "vivid red". 2: The color's hex code e.g.: "#f00:". + __( + 'Border color and style picker. The currently selected color is called "%1$s" and has a value of "%2$s".' + ), colorObject.name, ariaLabelValue ); @@ -91,14 +95,18 @@ const getToggleAriaLabel = ( const ariaLabelValue = getAriaLabelColorValue( colorValue ); return style ? sprintf( - // translators: %1$s: The color's hex code e.g.: "#f00:". %2$s: The current border style selection e.g. "solid". - 'Border color and style picker. The currently selected color has a value of "%1$s". The currently selected style is "%2$s".', + // translators: 1: The color's hex code e.g.: "#f00:". 2: The current border style selection e.g. "solid". + __( + 'Border color and style picker. The currently selected color has a value of "%1$s". The currently selected style is "%2$s".' + ), ariaLabelValue, style ) : sprintf( - // translators: %1$s: The color's hex code e.g: "#f00". - 'Border color and style picker. The currently selected color has a value of "%1$s".', + // translators: %s: The color's hex code e.g: "#f00". + __( + 'Border color and style picker. The currently selected color has a value of "%s".' + ), ariaLabelValue ); } @@ -108,8 +116,10 @@ const getToggleAriaLabel = ( if ( colorObject ) { return sprintf( - // translators: %1$s: The name of the color e.g. "vivid red". %2$s: The color's hex code e.g: "#f00". - 'Border color picker. The currently selected color is called "%1$s" and has a value of "%2$s".', + // translators: 1: The name of the color e.g. "vivid red". 2: The color's hex code e.g: "#f00". + __( + 'Border color picker. The currently selected color is called "%1$s" and has a value of "%2$s".' + ), colorObject.name, getAriaLabelColorValue( colorObject.color ) ); @@ -117,8 +127,10 @@ const getToggleAriaLabel = ( if ( colorValue ) { return sprintf( - // translators: %1$s: The color's hex code e.g: "#f00". - 'Border color picker. The currently selected color has a value of "%1$s".', + // translators: %s: The color's hex code e.g: "#f00". + __( + 'Border color picker. The currently selected color has a value of "%s".' + ), getAriaLabelColorValue( colorValue ) ); } diff --git a/packages/components/src/color-palette/index.tsx b/packages/components/src/color-palette/index.tsx index c744faee9b0c3f..a65508d8278c5f 100644 --- a/packages/components/src/color-palette/index.tsx +++ b/packages/components/src/color-palette/index.tsx @@ -233,7 +233,7 @@ function UnforwardedColorPalette( const displayValue = value?.replace( /^var\((.+)\)$/, '$1' ); const customColorAccessibleLabel = !! displayValue ? sprintf( - // translators: %1$s: The name of the color e.g: "vivid red". %2$s: The color's hex code e.g: "#f00". + // translators: 1: The name of the color e.g: "vivid red". 2: The color's hex code e.g: "#f00". __( 'Custom color picker. The currently selected color is called "%1$s" and has a value of "%2$s".' ), diff --git a/packages/components/src/custom-gradient-picker/gradient-bar/control-points.tsx b/packages/components/src/custom-gradient-picker/gradient-bar/control-points.tsx index a92e973d88c5a8..3911e21e0f9348 100644 --- a/packages/components/src/custom-gradient-picker/gradient-bar/control-points.tsx +++ b/packages/components/src/custom-gradient-picker/gradient-bar/control-points.tsx @@ -56,7 +56,7 @@ function ControlPointButton( { <> <Button aria-label={ sprintf( - // translators: %1$s: gradient position e.g: 70, %2$s: gradient color code e.g: rgb(52,121,151). + // translators: 1: gradient position e.g: 70. 2: gradient color code e.g: rgb(52,121,151). __( 'Gradient control point at position %1$s%% with color code %2$s.' ), diff --git a/packages/components/src/font-size-picker/index.native.js b/packages/components/src/font-size-picker/index.native.js index b12a27296ca297..5c22cb86175dbd 100644 --- a/packages/components/src/font-size-picker/index.native.js +++ b/packages/components/src/font-size-picker/index.native.js @@ -9,7 +9,7 @@ import { View, useWindowDimensions } from 'react-native'; import { useNavigation } from '@react-navigation/native'; import { useState } from '@wordpress/element'; import { Icon, chevronRight, check } from '@wordpress/icons'; -import { __, sprintf } from '@wordpress/i18n'; +import { __, _x, sprintf } from '@wordpress/i18n'; /** * Internal dependencies @@ -63,8 +63,8 @@ function FontSizePicker( { } ); const accessibilityLabel = sprintf( - // translators: %1$s: Font size name e.g. Small - __( 'Font Size, %1$s' ), + // translators: %s: Font size name e.g. Small + __( 'Font Size, %s' ), selectedOption.name ); @@ -77,8 +77,8 @@ function FontSizePicker( { value={ selectedValue ? sprintf( - // translators: %1$s: Select control font size name e.g. Small, %2$s: Select control font size e.g. 12px - __( '%1$s (%2$s)' ), + // translators: 1: Select control font size name e.g. Small. 2: Select control font size e.g. 12px + _x( '%1$s (%2$s)', 'font size' ), selectedOption.name, selectedPxValue ) @@ -88,7 +88,7 @@ function FontSizePicker( { accessibilityRole="button" accessibilityLabel={ accessibilityLabel } accessibilityHint={ sprintf( - // translators: %s: Select control button label e.g. Small + // translators: %s: Select control button label e.g. "Button width" __( 'Navigates to select %s' ), selectedOption.name ) } @@ -143,7 +143,7 @@ function FontSizePicker( { accessibilityLabel={ item.sizePx === selectedValue ? sprintf( - // translators: %s: Select font size option value e.g: "Selected: Large". + // translators: %s: The selected option. __( 'Selected: %s' ), item.name ) diff --git a/packages/components/src/mobile/bottom-sheet-select-control/index.native.js b/packages/components/src/mobile/bottom-sheet-select-control/index.native.js index 89c157d85b9b2d..0e0a19c12aed44 100644 --- a/packages/components/src/mobile/bottom-sheet-select-control/index.native.js +++ b/packages/components/src/mobile/bottom-sheet-select-control/index.native.js @@ -64,7 +64,7 @@ const BottomSheetSelectControl = ( { onPress={ openSubSheet } accessibilityRole="button" accessibilityLabel={ sprintf( - // translators: %1$s: Select control button label e.g. "Button width". %2$s: Select control option value e.g: "Auto, 25%". + // translators: 1: Select control button label e.g. "Button width". 2: Select control option value e.g: "Auto, 25%". __( '%1$s. Currently selected: %2$s' ), label, selectedOption.label @@ -102,7 +102,7 @@ const BottomSheetSelectControl = ( { accessibilityLabel={ item.value === selectedValue ? sprintf( - // translators: %s: Select control option value e.g: "Auto, 25%". + // translators: %s: The selected option. __( 'Selected: %s' ), item.label ) diff --git a/packages/components/src/mobile/bottom-sheet/range-cell.native.js b/packages/components/src/mobile/bottom-sheet/range-cell.native.js index f0d82cb96908ac..afa25683e4e3e8 100644 --- a/packages/components/src/mobile/bottom-sheet/range-cell.native.js +++ b/packages/components/src/mobile/bottom-sheet/range-cell.native.js @@ -165,7 +165,7 @@ class BottomSheetRangeCell extends Component { const getAccessibilityLabel = () => { return sprintf( - /* translators: accessibility text. Inform about current value. %1$s: Control label %2$s: setting label (example: width), %3$s: Current value. %4$s: value measurement unit (example: pixels) */ + /* translators: accessibility text. Inform about current value. 1: Control label. 2: setting label (example: width). 3: Current value. 4: value measurement unit (example: pixels) */ __( '%1$s. %2$s is %3$s %4$s.' ), cellProps.label, settingLabel, diff --git a/packages/components/src/mobile/bottom-sheet/stepper-cell/index.native.js b/packages/components/src/mobile/bottom-sheet/stepper-cell/index.native.js index aad78cd12665b6..6e5239687c5aa4 100644 --- a/packages/components/src/mobile/bottom-sheet/stepper-cell/index.native.js +++ b/packages/components/src/mobile/bottom-sheet/stepper-cell/index.native.js @@ -159,7 +159,7 @@ class BottomSheetStepperCell extends Component { }; const accessibilityLabel = sprintf( - /* translators: accessibility text. Inform about current value. %1$s: Control label %2$s: setting label (example: width), %3$s: Current value. %4$s: value measurement unit (example: pixels) */ + /* translators: accessibility text. Inform about current value. 1: Control label. 2: setting label (example: width). 3: Current value. 4: value measurement unit (example: pixels) */ __( '%1$s. %2$s is %3$s %4$s.' ), label, settingLabel, diff --git a/packages/components/src/tools-panel/tools-panel-header/component.tsx b/packages/components/src/tools-panel/tools-panel-header/component.tsx index 5caf9ce82d64f2..1f35258bd50ee1 100644 --- a/packages/components/src/tools-panel/tools-panel-header/component.tsx +++ b/packages/components/src/tools-panel/tools-panel-header/component.tsx @@ -106,7 +106,7 @@ const OptionalControlsGroup = ( { ) : sprintf( // translators: %s: The name of the control to display e.g. "Padding". - __( 'Show %s' ), + _x( 'Show %s', 'input control' ), label ); diff --git a/packages/dataviews/src/components/dataviews-selection-checkbox/index.tsx b/packages/dataviews/src/components/dataviews-selection-checkbox/index.tsx index b81bdad9a54614..c71636618716ba 100644 --- a/packages/dataviews/src/components/dataviews-selection-checkbox/index.tsx +++ b/packages/dataviews/src/components/dataviews-selection-checkbox/index.tsx @@ -33,8 +33,9 @@ export default function DataViewsSelectionCheckbox< Item >( { if ( primaryField?.getValue && item ) { // eslint-disable-next-line @wordpress/valid-sprintf selectionLabel = sprintf( - /* translators: %s: item title. */ - checked ? __( 'Deselect item: %s' ) : __( 'Select item: %s' ), + checked + ? /* translators: %s: item title. */ __( 'Deselect item: %s' ) + : /* translators: %s: item title. */ __( 'Select item: %s' ), primaryField.getValue( { item } ) ); } else { diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index ec4a5f9a7f1d0a..9824f9c8e8c6f6 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -363,12 +363,12 @@ function FieldItem( { isVisible ? sprintf( /* translators: %s: field label */ - __( 'Hide %s' ), + _x( 'Hide %s', 'field' ), label ) : sprintf( /* translators: %s: field label */ - __( 'Show %s' ), + _x( 'Show %s', 'field' ), label ) } diff --git a/packages/dataviews/src/dataforms-layouts/panel/index.tsx b/packages/dataviews/src/dataforms-layouts/panel/index.tsx index 5d3bbc532ad457..4a43d25436fe74 100644 --- a/packages/dataviews/src/dataforms-layouts/panel/index.tsx +++ b/packages/dataviews/src/dataforms-layouts/panel/index.tsx @@ -10,7 +10,7 @@ import { Button, } from '@wordpress/components'; import { useState, useMemo } from '@wordpress/element'; -import { sprintf, __ } from '@wordpress/i18n'; +import { sprintf, __, _x } from '@wordpress/i18n'; import { closeSmall } from '@wordpress/icons'; /** @@ -105,7 +105,7 @@ function FormField< Item >( { aria-expanded={ isOpen } aria-label={ sprintf( // translators: %s: Field name. - __( 'Edit %s' ), + _x( 'Edit %s', 'field' ), field.label ) } onClick={ onToggle } diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index ae56a394971a53..7812280795aad6 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -511,7 +511,7 @@ function Layout( { : newItem.title?.rendered; createSuccessNotice( sprintf( - // translators: %s: Title of the created post e.g: "Post 1". + // translators: %s: Title of the created post or template, e.g: "Hello world". __( '"%s" successfully created.' ), decodeEntities( title ) ), diff --git a/packages/edit-site/src/components/add-new-post/index.js b/packages/edit-site/src/components/add-new-post/index.js index 044e3c703b9948..04e286e3967a44 100644 --- a/packages/edit-site/src/components/add-new-post/index.js +++ b/packages/edit-site/src/components/add-new-post/index.js @@ -64,7 +64,7 @@ export default function AddNewPostModal( { postType, onSave, onClose } ) { createSuccessNotice( sprintf( - // translators: %s: Title of the created post e.g: "Hello world". + // translators: %s: Title of the created post or template, e.g: "Hello world". __( '"%s" successfully created.' ), decodeEntities( newPage.title?.rendered || title ) ), diff --git a/packages/edit-site/src/components/add-new-template/index.js b/packages/edit-site/src/components/add-new-template/index.js index bb0acbe62cd659..1a2d9ea727fa85 100644 --- a/packages/edit-site/src/components/add-new-template/index.js +++ b/packages/edit-site/src/components/add-new-template/index.js @@ -211,7 +211,7 @@ function NewTemplateModal( { onClose } ) { createSuccessNotice( sprintf( - // translators: %s: Title of the created template e.g: "Category". + // translators: %s: Title of the created post or template, e.g: "Hello world". __( '"%s" successfully created.' ), decodeEntities( newTemplate.title?.rendered || title ) ), diff --git a/packages/edit-site/src/components/add-new-template/utils.js b/packages/edit-site/src/components/add-new-template/utils.js index a2644ec4ad4da9..e3e2faf9457926 100644 --- a/packages/edit-site/src/components/add-new-template/utils.js +++ b/packages/edit-site/src/components/add-new-template/utils.js @@ -6,7 +6,7 @@ import { store as coreStore } from '@wordpress/core-data'; import { store as editorStore } from '@wordpress/editor'; import { decodeEntities } from '@wordpress/html-entities'; import { useMemo, useCallback } from '@wordpress/element'; -import { __, sprintf } from '@wordpress/i18n'; +import { __, _x, sprintf } from '@wordpress/i18n'; import { blockMeta, post, archive } from '@wordpress/icons'; /** @@ -246,14 +246,17 @@ export const usePostTypeMenuItems = ( onClickMenuItem ) => { if ( _needsUniqueIdentifier ) { menuItemTitle = labels.template_name ? sprintf( - // translators: %1s: Name of the template e.g: "Single Item: Post"; %2s: Slug of the post type e.g: "book". - __( '%1$s (%2$s)' ), + // translators: 1: Name of the template e.g: "Single Item: Post". 2: Slug of the post type e.g: "book". + _x( '%1$s (%2$s)', 'post type menu label' ), labels.template_name, slug ) : sprintf( - // translators: %1s: Name of the post type e.g: "Post"; %2s: Slug of the post type e.g: "book". - __( 'Single item: %1$s (%2$s)' ), + // translators: 1: Name of the post type e.g: "Post". 2: Slug of the post type e.g: "book". + _x( + 'Single item: %1$s (%2$s)', + 'post type menu label' + ), labels.singular_name, slug ); @@ -410,14 +413,14 @@ export const useTaxonomiesMenuItems = ( onClickMenuItem ) => { if ( _needsUniqueIdentifier ) { menuItemTitle = labels.template_name ? sprintf( - // translators: %1s: Name of the template e.g: "Products by Category"; %2s: Slug of the taxonomy e.g: "product_cat". - __( '%1$s (%2$s)' ), + // translators: 1: Name of the template e.g: "Products by Category". 2s: Slug of the taxonomy e.g: "product_cat". + _x( '%1$s (%2$s)', 'taxonomy template menu label' ), labels.template_name, slug ) : sprintf( - // translators: %1s: Name of the taxonomy e.g: "Category"; %2s: Slug of the taxonomy e.g: "product_cat". - __( '%1$s (%2$s)' ), + // translators: 1: Name of the taxonomy e.g: "Category". 2: Slug of the taxonomy e.g: "product_cat". + _x( '%1$s (%2$s)', 'taxonomy menu label' ), labels.singular_name, slug ); diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index c7481a1d12bd79..8f0ca0c5b29718 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -176,7 +176,7 @@ export default function EditSiteEditor( { isPostsList = false } ) { : newItem.title?.rendered; createSuccessNotice( sprintf( - // translators: %s: Title of the created post e.g: "Post 1". + // translators: %s: Title of the created post or template, e.g: "Hello world". __( '"%s" successfully created.' ), decodeEntities( _title ) ), diff --git a/packages/edit-site/src/components/editor/use-editor-title.js b/packages/edit-site/src/components/editor/use-editor-title.js index 01e258a5db1073..0645c2031a3af0 100644 --- a/packages/edit-site/src/components/editor/use-editor-title.js +++ b/packages/edit-site/src/components/editor/use-editor-title.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { __, sprintf } from '@wordpress/i18n'; +import { _x, sprintf } from '@wordpress/i18n'; /** * Internal dependencies @@ -19,8 +19,8 @@ function useEditorTitle() { let title; if ( hasLoadedPost ) { title = sprintf( - // translators: A breadcrumb trail for the Admin document title. %1$s: title of template being edited, %2$s: type of template (Template or Template Part). - __( '%1$s ‹ %2$s' ), + // translators: A breadcrumb trail for the Admin document title. 1: title of template being edited, 2: type of template (Template or Template Part). + _x( '%1$s ‹ %2$s', 'breadcrumb trail' ), getTitle(), POST_TYPE_LABELS[ editedPost.type ] ?? POST_TYPE_LABELS[ TEMPLATE_POST_TYPE ] diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js b/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js index 5d7c3f6cbded0a..b7ce38857c9461 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js +++ b/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js @@ -71,7 +71,7 @@ function getRevisionLabel( return areStylesEqual ? sprintf( - // translators: %1$s: author display name, %2$s: revision creation date. + // translators: 1: author display name. 2: revision creation date. __( 'Changes saved by %1$s on %2$s. This revision matches current editor styles.' ), @@ -79,7 +79,7 @@ function getRevisionLabel( formattedModifiedDate ) : sprintf( - // translators: %1$s: author display name, %2$s: revision creation date. + // translators: 1: author display name. 2: revision creation date. __( 'Changes saved by %1$s on %2$s' ), authorDisplayName, formattedModifiedDate diff --git a/packages/edit-site/src/components/global-styles/variations/variation.js b/packages/edit-site/src/components/global-styles/variations/variation.js index 48cbe0f19e7ab0..aa936314652885 100644 --- a/packages/edit-site/src/components/global-styles/variations/variation.js +++ b/packages/edit-site/src/components/global-styles/variations/variation.js @@ -9,7 +9,7 @@ import clsx from 'clsx'; import { Tooltip } from '@wordpress/components'; import { useMemo, useContext, useState } from '@wordpress/element'; import { ENTER } from '@wordpress/keycodes'; -import { __, sprintf } from '@wordpress/i18n'; +import { _x, sprintf } from '@wordpress/i18n'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; @@ -64,8 +64,8 @@ export default function Variation( { let label = variation?.title; if ( variation?.description ) { label = sprintf( - /* translators: %1$s: variation title. %2$s variation description. */ - __( '%1$s (%2$s)' ), + /* translators: 1: variation title. 2: variation description. */ + _x( '%1$s (%2$s)', 'variation label' ), variation?.title, variation?.description ); diff --git a/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js b/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js index d366ed6fb3a0e5..d87737c55326c6 100644 --- a/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js +++ b/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js @@ -9,7 +9,7 @@ import { store as coreStore } from '@wordpress/core-data'; import { useDispatch } from '@wordpress/data'; import { useState } from '@wordpress/element'; import { decodeEntities } from '@wordpress/html-entities'; -import { __, sprintf } from '@wordpress/i18n'; +import { __, _x, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; import { privateApis as routerPrivateApis } from '@wordpress/router'; @@ -51,8 +51,8 @@ export default function DeleteCategoryMenuItem( { category, onClose } ) { createSuccessNotice( sprintf( - /* translators: The pattern category's name */ - __( '"%s" deleted.' ), + /* translators: %s: The pattern category's name */ + _x( '"%s" deleted.', 'pattern category' ), category.label ), { type: 'snackbar', id: 'pattern-category-delete' } @@ -91,7 +91,7 @@ export default function DeleteCategoryMenuItem( { category, onClose } ) { className="edit-site-patterns__delete-modal" title={ sprintf( // translators: %s: The pattern category's name. - __( 'Delete "%s"?' ), + _x( 'Delete "%s"?', 'pattern category' ), decodeEntities( category.label ) ) } size="medium" diff --git a/packages/edit-site/src/components/pagination/index.js b/packages/edit-site/src/components/pagination/index.js index 8ef45883eb4524..5d6ce852d5a4c4 100644 --- a/packages/edit-site/src/components/pagination/index.js +++ b/packages/edit-site/src/components/pagination/index.js @@ -65,7 +65,7 @@ export default function Pagination( { </HStack> <Text variant="muted"> { sprintf( - // translators: %1$s: Current page number, %2$s: Total number of pages. + // translators: 1: Current page number. 2: Total number of pages. _x( '%1$s of %2$s', 'paging' ), currentPage, numPages diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index b5748684e8a19e..a921799aabbea2 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -254,7 +254,7 @@ function usePostFields( viewType ) { if ( isDraftOrPrivate ) { return createInterpolateElement( sprintf( - /* translators: %s: page creation date */ + /* translators: %s: page creation or modification date. */ __( '<span>Modified: <time>%s</time></span>' ), getFormattedDate( item.date ) ), @@ -305,7 +305,7 @@ function usePostFields( viewType ) { if ( isPending ) { return createInterpolateElement( sprintf( - /* translators: %s: the newest of created or modified date for the page */ + /* translators: %s: page creation or modification date. */ __( '<span>Modified: <time>%s</time></span>' ), getFormattedDate( dateToDisplay ) ), diff --git a/packages/edit-site/src/components/save-panel/index.js b/packages/edit-site/src/components/save-panel/index.js index d7817d5b3c1bb2..b77e5a9a1a10ba 100644 --- a/packages/edit-site/src/components/save-panel/index.js +++ b/packages/edit-site/src/components/save-panel/index.js @@ -50,7 +50,7 @@ const EntitiesSavedStatesForPreview = ( { onClose } ) => { const additionalPrompt = ( <p> { sprintf( - /* translators: %1$s: The name of active theme, %2$s: The name of theme to be activated. */ + /* translators: 1: The name of active theme, 2: The name of theme to be activated. */ __( 'Saving your changes will change your active theme from %1$s to %2$s.' ), diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/use-navigation-menu-handlers.js b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/use-navigation-menu-handlers.js index 7009ddc6fc9278..4a7e1deddc6d93 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/use-navigation-menu-handlers.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/use-navigation-menu-handlers.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { store as coreStore } from '@wordpress/core-data'; -import { __, sprintf } from '@wordpress/i18n'; +import { __, _x, sprintf } from '@wordpress/i18n'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as noticesStore } from '@wordpress/notices'; import { privateApis as routerPrivateApis } from '@wordpress/router'; @@ -150,7 +150,7 @@ function useDuplicateNavigationMenu() { { title: sprintf( /* translators: %s: Navigation menu title */ - __( '%s (Copy)' ), + _x( '%s (Copy)', 'navigation menu' ), menuTitle ), content: navigationMenu?.content?.raw, diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/build-navigation-label.js b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/build-navigation-label.js index d5e5ff02c63bfd..3e995eb8cdccfb 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/build-navigation-label.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/build-navigation-label.js @@ -1,13 +1,13 @@ /** * WordPress dependencies */ -import { __, sprintf } from '@wordpress/i18n'; +import { __, _x, sprintf } from '@wordpress/i18n'; import { decodeEntities } from '@wordpress/html-entities'; // Copied from packages/block-library/src/navigation/edit/navigation-menu-selector.js. export default function buildNavigationLabel( title, id, status ) { if ( ! title?.rendered ) { - /* translators: %s is the index of the menu in the list of menus. */ + /* translators: %s: the index of the menu in the list of menus. */ return sprintf( __( '(no title %s)' ), id ); } @@ -16,8 +16,8 @@ export default function buildNavigationLabel( title, id, status ) { } return sprintf( - // translators: %1s: title of the menu; %2s: status of the menu (draft, pending, etc.). - __( '%1$s (%2$s)' ), + // translators: 1: title of the menu. 2: status of the menu (draft, pending, etc.). + _x( '%1$s (%2$s)', 'menu label' ), decodeEntities( title?.rendered ), status ); diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js index bc32b0a9061c1e..18e6a4210ee1b2 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { __, sprintf } from '@wordpress/i18n'; +import { __, _x, sprintf } from '@wordpress/i18n'; import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; import { useSelect } from '@wordpress/data'; @@ -27,7 +27,7 @@ import { NAVIGATION_POST_TYPE } from '../../utils/constants'; // Copied from packages/block-library/src/navigation/edit/navigation-menu-selector.js. function buildMenuLabel( title, id, status ) { if ( ! title ) { - /* translators: %s is the index of the menu in the list of menus. */ + /* translators: %s: the index of the menu in the list of menus. */ return sprintf( __( '(no title %s)' ), id ); } @@ -36,8 +36,8 @@ function buildMenuLabel( title, id, status ) { } return sprintf( - // translators: %1s: title of the menu; %2s: status of the menu (draft, pending, etc.). - __( '%1$s (%2$s)' ), + // translators: 1: title of the menu. 2: status of the menu (draft, pending, etc.). + _x( '%1$s (%2$s)', 'menu label' ), decodeEntities( title ), status ); diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/index.js b/packages/edit-site/src/components/sidebar-navigation-screen/index.js index 417e643bb8b04d..0080964310525b 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen/index.js @@ -109,7 +109,8 @@ export default function SidebarNavigationScreen( { { ! isPreviewingTheme() ? title : sprintf( - 'Previewing %1$s: %2$s', + /* translators: 1: theme name. 2: title */ + __( 'Previewing %1$s: %2$s' ), previewingThemeName, title ) } diff --git a/packages/editor/src/components/editor-interface/index.js b/packages/editor/src/components/editor-interface/index.js index 4c3fcc30e23d82..aee75695b3fda4 100644 --- a/packages/editor/src/components/editor-interface/index.js +++ b/packages/editor/src/components/editor-interface/index.js @@ -85,8 +85,9 @@ export default function EditorInterface( { isDistractionFree: get( 'core', 'distractionFree' ), isPreviewMode: editorSettings.isPreviewMode, showBlockBreadcrumbs: get( 'core', 'showBlockBreadcrumbs' ), - // translators: Default label for the Document in the Block Breadcrumb. - documentLabel: postTypeLabel || _x( 'Document', 'noun' ), + documentLabel: + // translators: Default label for the Document in the Block Breadcrumb. + postTypeLabel || _x( 'Document', 'noun, breadcrumb' ), isZoomOut: _isZoomOut(), }; }, [] ); diff --git a/packages/editor/src/components/page-attributes/parent.js b/packages/editor/src/components/page-attributes/parent.js index 0f19ffcdd5daa4..17395589cd313b 100644 --- a/packages/editor/src/components/page-attributes/parent.js +++ b/packages/editor/src/components/page-attributes/parent.js @@ -212,8 +212,10 @@ function PostParentToggle( { isOpen, onClick } ) { className="editor-post-parent__panel-toggle" variant="tertiary" aria-expanded={ isOpen } - // translators: %s: Current post parent. - aria-label={ sprintf( __( 'Change parent: %s' ), parentTitle ) } + aria-label={ + // translators: %s: Current post parent. + sprintf( __( 'Change parent: %s' ), parentTitle ) + } onClick={ onClick } > { parentTitle } @@ -261,9 +263,9 @@ export function ParentRow() { <div> { createInterpolateElement( sprintf( - /* translators: %1$s The home URL of the WordPress installation without the scheme. */ + /* translators: %s: The home URL of the WordPress installation without the scheme. */ __( - 'Child pages inherit characteristics from their parent, such as URL structure. For instance, if "Pricing" is a child of "Services", its URL would be %1$s<wbr />/services<wbr />/pricing.' + 'Child pages inherit characteristics from their parent, such as URL structure. For instance, if "Pricing" is a child of "Services", its URL would be %s<wbr />/services<wbr />/pricing.' ), filterURLForDisplay( homeUrl ).replace( /([/.])/g, diff --git a/packages/editor/src/components/post-author/panel.js b/packages/editor/src/components/post-author/panel.js index a3c53aa417163e..6c6a51918902dc 100644 --- a/packages/editor/src/components/post-author/panel.js +++ b/packages/editor/src/components/post-author/panel.js @@ -25,8 +25,10 @@ function PostAuthorToggle( { isOpen, onClick } ) { className="editor-post-author__panel-toggle" variant="tertiary" aria-expanded={ isOpen } - // translators: %s: Current post link. - aria-label={ sprintf( __( 'Change author: %s' ), authorName ) } + aria-label={ + // translators: %s: Author name. + sprintf( __( 'Change author: %s' ), authorName ) + } onClick={ onClick } > { authorName } diff --git a/packages/editor/src/components/post-content-information/index.js b/packages/editor/src/components/post-content-information/index.js index 569339ef40c8b9..17a43b1ba12962 100644 --- a/packages/editor/src/components/post-content-information/index.js +++ b/packages/editor/src/components/post-content-information/index.js @@ -70,7 +70,7 @@ export default function PostContentInformation() { readingTime <= 1 ? __( '1 minute' ) : sprintf( - // translators: %s: the number of minutes to read the post. + /* translators: %s: the number of minutes to read the post. */ _n( '%s minute', '%s minutes', readingTime ), readingTime.toLocaleString() ); diff --git a/packages/editor/src/components/post-last-revision/index.js b/packages/editor/src/components/post-last-revision/index.js index c0ce37198c951d..fd68f9703cb4e2 100644 --- a/packages/editor/src/components/post-last-revision/index.js +++ b/packages/editor/src/components/post-last-revision/index.js @@ -44,7 +44,7 @@ function PostLastRevision() { icon={ backup } iconPosition="right" text={ sprintf( - /* translators: %s: number of revisions */ + /* translators: %s: number of revisions. */ __( 'Revisions (%s)' ), revisionsCount ) } diff --git a/packages/editor/src/components/post-schedule/label.js b/packages/editor/src/components/post-schedule/label.js index 89e7d02d69ce7f..f6cf3811db7916 100644 --- a/packages/editor/src/components/post-schedule/label.js +++ b/packages/editor/src/components/post-schedule/label.js @@ -48,7 +48,7 @@ export function getFullPostScheduleLabel( dateAttribute ) { const timezoneAbbreviation = getTimezoneAbbreviation(); const formattedDate = dateI18n( - // translators: If using a space between 'g:i' and 'a', use a non-breaking space. + // translators: Use a non-breaking space between 'g:i' and 'a' if appropriate. _x( 'F j, Y g:i\xa0a', 'post schedule full date format' ), date ); diff --git a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js index e019185b8a97cd..ef2019ac3f0f44 100644 --- a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js +++ b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js @@ -310,7 +310,7 @@ export function HierarchicalTermSelector( { slug } ) { const defaultName = slug === 'category' ? __( 'Category' ) : __( 'Term' ); const termAddedMessage = sprintf( - /* translators: %s: taxonomy name */ + /* translators: %s: term name. */ _x( '%s added', 'term' ), taxonomy?.labels?.singular_name ?? defaultName ); @@ -341,7 +341,7 @@ export function HierarchicalTermSelector( { slug } ) { const resultCount = getResultCount( newFilteredTermsTree ); const resultsFoundMessage = sprintf( - /* translators: %d: number of results */ + /* translators: %d: number of results. */ _n( '%d result found.', '%d results found.', resultCount ), resultCount ); diff --git a/packages/editor/src/components/post-url/panel.js b/packages/editor/src/components/post-url/panel.js index a5d3ddeb77f846..786a12cb8e6b54 100644 --- a/packages/editor/src/components/post-url/panel.js +++ b/packages/editor/src/components/post-url/panel.js @@ -93,8 +93,10 @@ function PostURLToggle( { isOpen, onClick } ) { className="editor-post-url__panel-toggle" variant="tertiary" aria-expanded={ isOpen } - // translators: %s: Current post link. - aria-label={ sprintf( __( 'Change link: %s' ), decodedSlug ) } + aria-label={ + // translators: %s: Current post link. + sprintf( __( 'Change link: %s' ), decodedSlug ) + } onClick={ onClick } > <>{ decodedSlug }</> diff --git a/packages/editor/src/components/sidebar/header.js b/packages/editor/src/components/sidebar/header.js index fc4d44ba9e2958..ed2f7f89fe6e7a 100644 --- a/packages/editor/src/components/sidebar/header.js +++ b/packages/editor/src/components/sidebar/header.js @@ -20,8 +20,9 @@ const SidebarHeader = ( _, ref ) => { const { getPostTypeLabel } = select( editorStore ); return { - // translators: Default label for the Document sidebar tab, not selected. - documentLabel: getPostTypeLabel() || _x( 'Document', 'noun' ), + documentLabel: + // translators: Default label for the Document sidebar tab, not selected. + getPostTypeLabel() || _x( 'Document', 'noun, sidebar' ), }; }, [] ); diff --git a/packages/editor/src/components/sidebar/index.js b/packages/editor/src/components/sidebar/index.js index efca709e0eec75..601bcd8f311bb8 100644 --- a/packages/editor/src/components/sidebar/index.js +++ b/packages/editor/src/components/sidebar/index.js @@ -13,7 +13,7 @@ import { useEffect, useRef, } from '@wordpress/element'; -import { isRTL, __ } from '@wordpress/i18n'; +import { isRTL, __, _x } from '@wordpress/i18n'; import { drawerLeft, drawerRight } from '@wordpress/icons'; import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts'; import { privateApis as componentsPrivateApis } from '@wordpress/components'; @@ -101,8 +101,10 @@ const SidebarContent = ( { // see https://github.com/WordPress/gutenberg/pull/55360#pullrequestreview-1737671049 className="editor-sidebar__panel" headerClassName="editor-sidebar__panel-tabs" - /* translators: button label text should, if possible, be under 16 characters. */ - title={ __( 'Settings' ) } + title={ + /* translators: button label text should, if possible, be under 16 characters. */ + _x( 'Settings', 'sidebar button label' ) + } toggleShortcut={ keyboardShortcut } icon={ isRTL() ? drawerLeft : drawerRight } isActiveByDefault={ SIDEBAR_ACTIVE_BY_DEFAULT } diff --git a/packages/editor/src/components/time-to-read/index.js b/packages/editor/src/components/time-to-read/index.js index a71a4b1dac8388..5d748abc3049cb 100644 --- a/packages/editor/src/components/time-to-read/index.js +++ b/packages/editor/src/components/time-to-read/index.js @@ -47,10 +47,10 @@ export default function TimeToRead() { } ) : createInterpolateElement( sprintf( - /* translators: %s is the number of minutes the post will take to read. */ + /* translators: %s: the number of minutes to read the post. */ _n( - '<span>%d</span> minute', - '<span>%d</span> minutes', + '<span>%s</span> minute', + '<span>%s</span> minutes', minutesToRead ), minutesToRead diff --git a/packages/editor/src/dataviews/actions/duplicate-template-part.tsx b/packages/editor/src/dataviews/actions/duplicate-template-part.tsx index fa3cf39ba76268..95e7e6bb672fcc 100644 --- a/packages/editor/src/dataviews/actions/duplicate-template-part.tsx +++ b/packages/editor/src/dataviews/actions/duplicate-template-part.tsx @@ -2,7 +2,7 @@ * WordPress dependencies */ import { useDispatch } from '@wordpress/data'; -import { __, sprintf, _x } from '@wordpress/i18n'; +import { _x, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; import { useMemo } from '@wordpress/element'; // @ts-ignore @@ -42,7 +42,7 @@ const duplicateTemplatePart: Action< TemplatePart > = { createSuccessNotice( sprintf( // translators: %s: The new template part's title e.g. 'Call to action (copy)'. - __( '"%s" duplicated.' ), + _x( '"%s" duplicated.', 'template part' ), getItemTitle( item ) ), { type: 'snackbar', id: 'edit-site-patterns-success' } @@ -55,7 +55,7 @@ const duplicateTemplatePart: Action< TemplatePart > = { defaultArea={ item.area } defaultTitle={ sprintf( /* translators: %s: Existing template part title */ - __( '%s (Copy)' ), + _x( '%s (Copy)', 'template part' ), getItemTitle( item ) ) } onCreate={ onTemplatePartSuccess } diff --git a/packages/editor/src/store/private-actions.js b/packages/editor/src/store/private-actions.js index 358d00af396bbb..74c1f1ea100b37 100644 --- a/packages/editor/src/store/private-actions.js +++ b/packages/editor/src/store/private-actions.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { store as coreStore } from '@wordpress/core-data'; -import { __, sprintf } from '@wordpress/i18n'; +import { __, _x, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { store as preferencesStore } from '@wordpress/preferences'; @@ -410,8 +410,8 @@ export const removeTemplates = decodeEntities( title ) ) : sprintf( - /* translators: The template/part's name. */ - __( '"%s" deleted.' ), + /* translators: %s: The template/part's name. */ + _x( '"%s" deleted.', 'template part' ), decodeEntities( title ) ); } else { diff --git a/packages/fields/src/actions/delete-post.tsx b/packages/fields/src/actions/delete-post.tsx index c5ab866e12479e..d3a469d7f83ab4 100644 --- a/packages/fields/src/actions/delete-post.tsx +++ b/packages/fields/src/actions/delete-post.tsx @@ -2,7 +2,7 @@ * WordPress dependencies */ import { trash } from '@wordpress/icons'; -import { __, _n, sprintf } from '@wordpress/i18n'; +import { __, _x, _n, sprintf } from '@wordpress/i18n'; import { useState } from '@wordpress/element'; import { Button, @@ -66,8 +66,8 @@ const deletePostAction: Action< Template | TemplatePart | Pattern > = { items.length ) : sprintf( - // translators: %s: The template or template part's titles - __( 'Delete "%s"?' ), + // translators: %s: The template or template part's title + _x( 'Delete "%s"?', 'template part' ), getItemTitle( items[ 0 ] ) ) } </Text> @@ -100,8 +100,11 @@ const deletePostAction: Action< Template | TemplatePart | Pattern > = { ) ) : sprintf( - /* translators: The template/part's name. */ - __( '"%s" deleted.' ), + /* translators: %s: The template/part's name. */ + _x( + '"%s" deleted.', + 'template part' + ), decodeEntities( getItemTitle( item ) ) diff --git a/packages/fields/src/actions/duplicate-post.tsx b/packages/fields/src/actions/duplicate-post.tsx index d153073f4b6c12..fd7e0ae9de4ad1 100644 --- a/packages/fields/src/actions/duplicate-post.tsx +++ b/packages/fields/src/actions/duplicate-post.tsx @@ -38,7 +38,7 @@ const duplicatePost: Action< BasePost > = { ...items[ 0 ], title: sprintf( /* translators: %s: Existing template title */ - __( '%s (Copy)' ), + _x( '%s (Copy)', 'template' ), getItemTitle( items[ 0 ] ) ), } ); @@ -104,7 +104,7 @@ const duplicatePost: Action< BasePost > = { createSuccessNotice( sprintf( - // translators: %s: Title of the created template e.g: "Category". + // translators: %s: Title of the created post or template, e.g: "Hello world". __( '"%s" successfully created.' ), decodeEntities( newItem.title?.rendered || item.title ) ), diff --git a/packages/fields/src/actions/view-post-revisions.tsx b/packages/fields/src/actions/view-post-revisions.tsx index 875b925b94f070..75d4edfd73e18d 100644 --- a/packages/fields/src/actions/view-post-revisions.tsx +++ b/packages/fields/src/actions/view-post-revisions.tsx @@ -17,7 +17,7 @@ const viewPostRevisions: Action< Post > = { const revisionsCount = items[ 0 ]._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0; return sprintf( - /* translators: %s: number of revisions */ + /* translators: %s: number of revisions. */ __( 'View revisions (%s)' ), revisionsCount ); diff --git a/packages/interface/src/components/interface-skeleton/index.js b/packages/interface/src/components/interface-skeleton/index.js index 0a49db4f159d88..2417cc909d1698 100644 --- a/packages/interface/src/components/interface-skeleton/index.js +++ b/packages/interface/src/components/interface-skeleton/index.js @@ -105,7 +105,7 @@ function InterfaceSkeleton( /* translators: accessibility text for the secondary sidebar landmark region. */ secondarySidebar: __( 'Block Library' ), /* translators: accessibility text for the settings landmark region. */ - sidebar: __( 'Settings' ), + sidebar: _x( 'Settings', 'settings landmark area' ), /* translators: accessibility text for the publish landmark region. */ actions: __( 'Publish' ), /* translators: accessibility text for the footer landmark region. */ diff --git a/packages/patterns/src/components/duplicate-pattern-modal.js b/packages/patterns/src/components/duplicate-pattern-modal.js index 6fa25a16f8594c..2b51e82f22da4e 100644 --- a/packages/patterns/src/components/duplicate-pattern-modal.js +++ b/packages/patterns/src/components/duplicate-pattern-modal.js @@ -3,7 +3,7 @@ */ import { store as coreStore } from '@wordpress/core-data'; import { useDispatch, useSelect } from '@wordpress/data'; -import { __, sprintf } from '@wordpress/i18n'; +import { __, _x, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; /** @@ -52,7 +52,7 @@ export function useDuplicatePatternProps( { pattern, onSuccess } ) { : pattern.wp_pattern_sync_status || PATTERN_SYNC_TYPES.full, defaultTitle: sprintf( /* translators: %s: Existing pattern title */ - __( '%s (Copy)' ), + _x( '%s (Copy)', 'pattern' ), typeof pattern.title === 'string' ? pattern.title : pattern.title.raw @@ -61,7 +61,7 @@ export function useDuplicatePatternProps( { pattern, onSuccess } ) { createSuccessNotice( sprintf( // translators: %s: The new pattern's title e.g. 'Call to action (copy)'. - __( '"%s" duplicated.' ), + _x( '"%s" duplicated.', 'pattern' ), newPattern.title.raw ), { diff --git a/packages/patterns/src/components/pattern-overrides-block-controls.js b/packages/patterns/src/components/pattern-overrides-block-controls.js index 5a62a5b1993f75..8942b3a09e2e35 100644 --- a/packages/patterns/src/components/pattern-overrides-block-controls.js +++ b/packages/patterns/src/components/pattern-overrides-block-controls.js @@ -68,7 +68,7 @@ function PatternOverridesToolbarIndicator( { clientIds } ) { const blockDescription = isSingleBlockSelected ? sprintf( - /* translators: %1s: The block type's name; %2s: The block's user-provided name (the same as the override name). */ + /* translators: 1: The block type's name. 2: The block's user-provided name (the same as the override name). */ __( 'This %1$s is editable using the "%2$s" override.' ), firstBlockTitle.toLowerCase(), firstBlockName From 76e4dc75571820f74cbec2e854c2a6b31b239e12 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Mon, 28 Oct 2024 15:04:09 +0100 Subject: [PATCH 1360/1908] Improve the link preview accessibility and labels. (#60908) * Improve the link preview accessibility and labels. * Adjust test. * Update test by using ByRole queries. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../components/link-control/link-preview.js | 23 +++-- .../src/components/link-control/test/index.js | 87 ++++++++++++++----- 2 files changed, 78 insertions(+), 32 deletions(-) diff --git a/packages/block-editor/src/components/link-control/link-preview.js b/packages/block-editor/src/components/link-control/link-preview.js index e5de47f0153a82..962228583f43e5 100644 --- a/packages/block-editor/src/components/link-control/link-preview.js +++ b/packages/block-editor/src/components/link-control/link-preview.js @@ -6,7 +6,7 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { __, sprintf } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; import { Button, ExternalLink, @@ -96,7 +96,8 @@ export default function LinkPreview( { return ( <div - aria-label={ __( 'Currently selected' ) } + role="group" + aria-label={ __( 'Manage link' ) } className={ clsx( 'block-editor-link-control__search-item', { 'is-current': true, 'is-rich': hasRichData, @@ -107,7 +108,14 @@ export default function LinkPreview( { } ) } > <div className="block-editor-link-control__search-item-top"> - <span className="block-editor-link-control__search-item-header"> + <span + className="block-editor-link-control__search-item-header" + role="figure" + aria-label={ + /* translators: Accessibility text for the link preview when editing a link. */ + __( 'Link information' ) + } + > <span className={ clsx( 'block-editor-link-control__search-item-icon', @@ -149,6 +157,7 @@ export default function LinkPreview( { label={ __( 'Edit link' ) } onClick={ onEditClick } size="compact" + showTooltip={ ! showIconLabels } /> { hasUnlinkControl && ( <Button @@ -156,19 +165,17 @@ export default function LinkPreview( { label={ __( 'Remove link' ) } onClick={ onRemove } size="compact" + showTooltip={ ! showIconLabels } /> ) } <Button icon={ copySmall } - label={ sprintf( - // Translators: %s is a placeholder for the link URL and an optional colon, (if a Link URL is present). - __( 'Copy link%s' ), // Ends up looking like "Copy link: https://example.com". - isEmptyURL || showIconLabels ? '' : ': ' + value.url - ) } + label={ __( 'Copy link' ) } ref={ ref } accessibleWhenDisabled disabled={ isEmptyURL } size="compact" + showTooltip={ ! showIconLabels } /> <ViewerSlot fillProps={ value } /> </div> diff --git a/packages/block-editor/src/components/link-control/test/index.js b/packages/block-editor/src/components/link-control/test/index.js index e416b9b522a53c..bd97fec4ba0073 100644 --- a/packages/block-editor/src/components/link-control/test/index.js +++ b/packages/block-editor/src/components/link-control/test/index.js @@ -373,7 +373,9 @@ describe( 'Basic rendering', () => { /> ); - const linkPreview = screen.getByLabelText( 'Currently selected' ); + const linkPreview = screen.getByRole( 'group', { + name: 'Manage link', + } ); const isPreviewError = linkPreview.classList.contains( 'is-error' ); expect( isPreviewError ).toBe( true ); @@ -834,7 +836,9 @@ describe( 'Manual link entry', () => { render( <LinkControlConsumer /> ); - let linkPreview = screen.getByLabelText( 'Currently selected' ); + let linkPreview = screen.getByRole( 'group', { + name: 'Manage link', + } ); expect( linkPreview ).toBeInTheDocument(); @@ -868,7 +872,9 @@ describe( 'Manual link entry', () => { // Cancel the editing process. await user.click( cancelButton ); - linkPreview = screen.getByLabelText( 'Currently selected' ); + linkPreview = screen.getByRole( 'group', { + name: 'Manage link', + } ); expect( linkPreview ).toBeInTheDocument(); @@ -1076,7 +1082,9 @@ describe( 'Default search suggestions', () => { // Click the "Edit/Change" button and check initial suggestions are not // shown. - const currentLinkUI = screen.getByLabelText( 'Currently selected' ); + const currentLinkUI = screen.getByRole( 'group', { + name: 'Manage link', + } ); const currentLinkBtn = within( currentLinkUI ).getByRole( 'button', { name: 'Edit link', } ); @@ -1230,8 +1238,9 @@ describe( 'Creating Entities (eg: Posts, Pages)', () => { // Check for loading indicator. const loadingIndicator = screen.getByText( 'Creating…' ); - const currentLinkLabel = - screen.queryByLabelText( 'Currently selected' ); + const currentLinkLabel = screen.queryByRole( 'group', { + name: 'Manage link', + } ); expect( currentLinkLabel ).not.toBeInTheDocument(); expect( loadingIndicator ).toBeVisible(); @@ -1242,8 +1251,9 @@ describe( 'Creating Entities (eg: Posts, Pages)', () => { // Resolve the `createSuggestion` promise. resolver(); - const currentLink = - await screen.findByLabelText( 'Currently selected' ); + const currentLink = await screen.findByRole( 'group', { + name: 'Manage link', + } ); expect( currentLink ).toHaveTextContent( entityNameText ); expect( currentLink ).toHaveTextContent( '/?p=123' ); @@ -1291,7 +1301,9 @@ describe( 'Creating Entities (eg: Posts, Pages)', () => { await user.click( createButton ); - const currentLink = screen.getByLabelText( 'Currently selected' ); + const currentLink = screen.getByRole( 'group', { + name: 'Manage link', + } ); expect( currentLink ).toHaveTextContent( 'Some new page to create' ); expect( currentLink ).toHaveTextContent( '/?p=123' ); @@ -1350,7 +1362,9 @@ describe( 'Creating Entities (eg: Posts, Pages)', () => { triggerEnter( searchInput ); expect( - await screen.findByLabelText( 'Currently selected' ) + await screen.findByRole( 'group', { + name: 'Manage link', + } ) ).toHaveTextContent( entityNameText ); } ); @@ -1529,7 +1543,9 @@ describe( 'Selecting links', () => { render( <LinkControlConsumer /> ); - const currentLink = screen.getByLabelText( 'Currently selected' ); + const currentLink = screen.getByRole( 'group', { + name: 'Manage link', + } ); const currentLinkAnchor = screen.getByRole( 'link', { name: `${ selectedLink.title } (opens in a new tab)`, } ); @@ -1559,7 +1575,9 @@ describe( 'Selecting links', () => { render( <LinkControlConsumer /> ); // Required in order to select the button below. - let currentLinkUI = screen.getByLabelText( 'Currently selected' ); + let currentLinkUI = screen.getByRole( 'group', { + name: 'Manage link', + } ); const currentLinkBtn = within( currentLinkUI ).getByRole( 'button', { name: 'Edit link', } ); @@ -1570,7 +1588,9 @@ describe( 'Selecting links', () => { const searchInput = screen.getByRole( 'combobox', { name: 'Search or type URL', } ); - currentLinkUI = screen.queryByLabelText( 'Currently selected' ); + currentLinkUI = screen.queryByRole( 'group', { + name: 'Manage link', + } ); // We should be back to showing the search input. expect( searchInput ).toBeVisible(); @@ -1733,8 +1753,9 @@ describe( 'Selecting links', () => { triggerEnter( searchInput ); // Check that the suggestion selected via is now shown as selected. - const currentLink = - screen.getByLabelText( 'Currently selected' ); + const currentLink = screen.getByRole( 'group', { + name: 'Manage link', + } ); const currentLinkAnchor = screen.getByRole( 'link', { name: `${ selectedLink.title } (opens in a new tab)`, } ); @@ -2127,7 +2148,9 @@ describe( 'Rich link previews', () => { render( <LinkControl value={ selectedLink } /> ); - const linkPreview = screen.getByLabelText( 'Currently selected' ); + const linkPreview = screen.getByRole( 'group', { + name: 'Manage link', + } ); const isRichLinkPreview = linkPreview.classList.contains( 'is-rich' ); @@ -2148,7 +2171,9 @@ describe( 'Rich link previews', () => { render( <LinkControl value={ selectedLink } hasRichPreviews /> ); - const linkPreview = screen.getByLabelText( 'Currently selected' ); + const linkPreview = screen.getByRole( 'group', { + name: 'Manage link', + } ); await waitFor( () => expect( linkPreview ).toHaveClass( 'is-rich' ) ); } ); @@ -2165,7 +2190,9 @@ describe( 'Rich link previews', () => { render( <LinkControl value={ selectedLink } hasRichPreviews /> ); - const linkPreview = screen.getByLabelText( 'Currently selected' ); + const linkPreview = screen.getByRole( 'group', { + name: 'Manage link', + } ); await waitFor( () => expect( linkPreview ).toHaveClass( 'is-rich' ) ); @@ -2197,7 +2224,9 @@ describe( 'Rich link previews', () => { render( <LinkControl value={ selectedLink } hasRichPreviews /> ); - const linkPreview = screen.getByLabelText( 'Currently selected' ); + const linkPreview = screen.getByRole( 'group', { + name: 'Manage link', + } ); await waitFor( () => expect( linkPreview ).toHaveClass( 'is-rich' ) ); @@ -2221,7 +2250,9 @@ describe( 'Rich link previews', () => { render( <LinkControl value={ selectedLink } hasRichPreviews /> ); - const linkPreview = screen.getByLabelText( 'Currently selected' ); + const linkPreview = screen.getByRole( 'group', { + name: 'Manage link', + } ); await waitFor( () => expect( linkPreview ).toHaveClass( 'is-rich' ) ); @@ -2256,7 +2287,9 @@ describe( 'Rich link previews', () => { render( <LinkControl value={ selectedLink } hasRichPreviews /> ); - const linkPreview = screen.getByLabelText( 'Currently selected' ); + const linkPreview = screen.getByRole( 'group', { + name: 'Manage link', + } ); await waitFor( () => expect( linkPreview ).toHaveClass( 'is-rich' ) @@ -2281,7 +2314,9 @@ describe( 'Rich link previews', () => { render( <LinkControl value={ selectedLink } hasRichPreviews /> ); - const linkPreview = screen.getByLabelText( 'Currently selected' ); + const linkPreview = screen.getByRole( 'group', { + name: 'Manage link', + } ); expect( linkPreview ).toHaveClass( 'is-fetching' ); @@ -2300,7 +2335,9 @@ describe( 'Rich link previews', () => { render( <LinkControl value={ selectedLink } hasRichPreviews /> ); - const linkPreview = screen.getByLabelText( 'Currently selected' ); + const linkPreview = screen.getByRole( 'group', { + name: 'Manage link', + } ); expect( linkPreview ).toHaveClass( 'is-fetching' ); expect( linkPreview ).not.toHaveClass( 'is-rich' ); @@ -2313,7 +2350,9 @@ describe( 'Rich link previews', () => { render( <LinkControl value={ selectedLink } hasRichPreviews /> ); - const linkPreview = screen.getByLabelText( 'Currently selected' ); + const linkPreview = screen.getByRole( 'group', { + name: 'Manage link', + } ); expect( linkPreview ).toHaveClass( 'is-fetching' ); From d36959d9599483f8c7e442dc3d2b5dfff2d3f1f0 Mon Sep 17 00:00:00 2001 From: Ryan Welcher <me@ryanwelcher.com> Date: Mon, 28 Oct 2024 10:05:58 -0400 Subject: [PATCH 1361/1908] Create Block: Adds `--target-dir` flag to allow the tool to target where to scaffold (#53781) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add --targetDir flag to allow targeting a directory where to scaffold the plugin/files. * Not using the targetDir when in --no-plugin mode * Change the name of the flag to match others and update changelog. * WIP commit. * Add logic to generate the paths for the root and block files in one place. * Add a new parameter to allow passing the path once rather than generating it in the function. * Modify the other functions to use the generated paths. * Update the command description. * Update packages/create-block/CHANGELOG.md * Refactor the handling for the root directory * Improve the documentation for target dir * Reorder CLI options in the docs --------- Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> Unlinked contributors: afmarchetti. Co-authored-by: ryanwelcher <welcher@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: bacoords <bacoords@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> Co-authored-by: brettsmason <brettsmason@git.wordpress.org> Co-authored-by: iamleese <leeseoftbc@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> --- packages/create-block/CHANGELOG.md | 4 +++ packages/create-block/README.md | 31 +++++++++---------- packages/create-block/lib/index.js | 10 ++++-- packages/create-block/lib/init-block.js | 23 +++++++------- .../create-block/lib/init-package-json.js | 10 +++--- packages/create-block/lib/init-wp-env.js | 8 ++--- packages/create-block/lib/init-wp-scripts.js | 11 +++---- packages/create-block/lib/output.js | 8 ++--- packages/create-block/lib/scaffold.js | 14 ++++----- 9 files changed, 60 insertions(+), 59 deletions(-) diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index 87e647ec03dc03..9b9504faa1eeab 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancement + +- Add `--target-dir` flag to allow indicating where resulting files will be scaffolded ([#53781](https://github.com/WordPress/gutenberg/pull/53781)) + ## 4.53.0 (2024-10-16) ## 4.52.0 (2024-10-03) diff --git a/packages/create-block/README.md b/packages/create-block/README.md index 55cea45c9afe71..907121d3d466a7 100644 --- a/packages/create-block/README.md +++ b/packages/create-block/README.md @@ -18,10 +18,8 @@ $ npm start The `slug` provided (`todo-list` in the example) defines the folder name for the scaffolded plugin and the internal block name. The WordPress plugin generated must [be installed manually](https://wordpress.org/documentation/article/manage-plugins/#manual-plugin-installation-1). - _(requires `node` version `20.10.0` or above, and `npm` version `10.2.3` or above)_ - > [Watch a video introduction to create-block on Learn.wordpress.org](https://learn.wordpress.org/tutorial/using-the-create-block-tool/) ## Usage @@ -42,25 +40,26 @@ $ npx @wordpress/create-block@latest [options] [slug] When no `slug` is provided, the script will run in interactive mode and will start prompting for the input required (`slug`, title, namespace...) to scaffold the project. - ### `slug` The use of `slug` is optional. When provided it triggers the _quick mode_, where this `slug` is used: -- as the block slug (required for its identification) -- as the output location (folder name) for scaffolded files -- as the name of the WordPress plugin. + +- as the block slug (required for its identification) +- as the output location (folder name) for scaffolded files +- as the name of the WordPress plugin. The rest of the configuration is set to all default values unless overridden with some options listed below. ### `options` - ```bash -V, --version output the version number -t, --template <name> project template type name; allowed values: "static" (default), "es5", the name of an external npm package, or the path to a local directory +--variant choose a block variant as defined by the template --no-plugin scaffold block files only +--target-dir <directory> the directory where the files will be scaffolded, defaults to the slug --namespace <value> internal namespace for the block name --title <value> display title for the block and the WordPress plugin --short-description <value> short description for the block and the WordPress plugin @@ -69,7 +68,6 @@ The rest of the configuration is set to all default values unless overridden wit --no-wp-scripts disable integration with `@wordpress/scripts` package --wp-env enable integration with `@wordpress/env` package -h, --help output usage information ---variant choose a block variant as defined by the template ``` #### `--template` @@ -94,14 +92,6 @@ With this argument, `create-block` will generate a [dynamic block](https://devel $ npx @wordpress/create-block@latest --variant dynamic ``` -#### `--help` - -With this argument, the `create-block` package outputs usage information. - -```bash -$ npx @wordpress/create-block@latest --help -``` - #### `--no-plugin` With this argument, the `create-block` package runs in _No plugin mode_ which only scaffolds block files into the current directory. @@ -109,6 +99,7 @@ With this argument, the `create-block` package runs in _No plugin mode_ which on ```bash $ npx @wordpress/create-block@latest --no-plugin ``` + #### `--wp-env` With this argument, the `create-block` package will add to the generated plugin the configuration and the script to run [`wp-env` package](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/) within the plugin. This will allow you to easily set up a local WordPress environment (via Docker) for building and testing the generated plugin. @@ -117,6 +108,14 @@ With this argument, the `create-block` package will add to the generated plugin $ npx @wordpress/create-block@latest --wp-env ``` +#### `--help` + +With this argument, the `create-block` package outputs usage information. + +```bash +$ npx @wordpress/create-block@latest --help +``` + ## Available commands in the scaffolded project The plugin folder created when executing this command, is a node package with a modern build setup that requires no configuration. diff --git a/packages/create-block/lib/index.js b/packages/create-block/lib/index.js index 8e3d43c140460a..da08bcd4ab1dc7 100644 --- a/packages/create-block/lib/index.js +++ b/packages/create-block/lib/index.js @@ -37,6 +37,12 @@ program 'project template type name; allowed values: "standard", "es5", the name of an external npm package, or the path to a local directory', 'standard' ) + .option( '--variant <variant>', 'the variant of the template to use' ) + .option( '--no-plugin', 'scaffold only block files' ) + .option( + '--target-dir <directory>', + 'the directory where the files will be scaffolded, defaults to the slug' + ) .option( '--namespace <value>', 'internal namespace for the block name' ) .option( '--title <value>', @@ -57,8 +63,6 @@ program 'disable integration with `@wordpress/scripts` package' ) .option( '--wp-env', 'enable integration with `@wordpress/env` package' ) - .option( '--no-plugin', 'scaffold only block files' ) - .option( '--variant <variant>', 'the variant of the template to use' ) .action( async ( slug, @@ -72,6 +76,7 @@ program wpScripts, wpEnv, variant, + targetDir, } ) => { await checkSystemRequirements( engines ); @@ -102,6 +107,7 @@ program title, wpScripts, wpEnv, + targetDir, } ).filter( ( [ , value ] ) => value !== undefined ) ); diff --git a/packages/create-block/lib/init-block.js b/packages/create-block/lib/init-block.js index 0882bdd3404631..8074ef1c8d953d 100644 --- a/packages/create-block/lib/init-block.js +++ b/packages/create-block/lib/init-block.js @@ -1,7 +1,7 @@ /** * External dependencies */ -const { dirname, join } = require( 'path' ); +const { join } = require( 'path' ); const makeDir = require( 'make-dir' ); const { writeFile } = require( 'fs' ).promises; @@ -35,16 +35,18 @@ async function initBlockJSON( { viewScript, customBlockJSON, example, + rootDirectory, } ) { info( '' ); info( 'Creating a "block.json" file.' ); - const outputFile = plugin - ? join( process.cwd(), slug, folderName, 'block.json' ) - : join( process.cwd(), slug, 'block.json' ); - await makeDir( dirname( outputFile ) ); + const blockFolderName = plugin + ? join( rootDirectory, folderName ) + : rootDirectory; + await makeDir( blockFolderName ); + await writeFile( - outputFile, + join( blockFolderName, 'block.json' ), JSON.stringify( Object.fromEntries( Object.entries( { @@ -79,13 +81,12 @@ async function initBlockJSON( { module.exports = async function ( outputTemplates, view ) { await Promise.all( Object.keys( outputTemplates ).map( async ( outputFile ) => { - const pathName = view.plugin - ? join( view.folderName, outputFile ) - : join( process.cwd(), view.slug, outputFile ); - await writeOutputTemplate( outputTemplates[ outputFile ], - pathName, + join( + view.plugin ? view.folderName : '', + outputFile.replace( /\$slug/g, view.slug ) + ), view ); } ) diff --git a/packages/create-block/lib/init-package-json.js b/packages/create-block/lib/init-package-json.js index bbc4436ac1d0e5..7a3765139e39d3 100644 --- a/packages/create-block/lib/init-package-json.js +++ b/packages/create-block/lib/init-package-json.js @@ -3,7 +3,6 @@ */ const { command } = require( 'execa' ); const npmPackageArg = require( 'npm-package-arg' ); -const { join } = require( 'path' ); const writePkg = require( 'write-pkg' ); /** @@ -25,14 +24,13 @@ module.exports = async ( { customScripts, isDynamicVariant, customPackageJSON, + rootDirectory, } ) => { - const cwd = join( process.cwd(), slug ); - info( '' ); info( 'Creating a "package.json" file.' ); await writePkg( - cwd, + rootDirectory, Object.fromEntries( Object.entries( { name: slug, @@ -92,7 +90,7 @@ module.exports = async ( { info( '' ); info( `Installing "${ packageArg }".` ); await command( `npm install ${ packageArg }`, { - cwd, + cwd: rootDirectory, } ); } catch ( { message } ) { info( '' ); @@ -115,7 +113,7 @@ module.exports = async ( { info( '' ); info( `Installing "${ packageArg }".` ); await command( `npm install ${ packageArg } --save-dev`, { - cwd, + cwd: rootDirectory, } ); } catch ( { message } ) { info( '' ); diff --git a/packages/create-block/lib/init-wp-env.js b/packages/create-block/lib/init-wp-env.js index 19fd01646cf041..419e8c0991d44c 100644 --- a/packages/create-block/lib/init-wp-env.js +++ b/packages/create-block/lib/init-wp-env.js @@ -10,21 +10,19 @@ const { writeFile } = require( 'fs' ).promises; */ const { info } = require( './log' ); -module.exports = async ( { slug } ) => { - const cwd = join( process.cwd(), slug ); - +module.exports = async ( { rootDirectory } ) => { info( '' ); info( 'Installing `@wordpress/env` package. It might take a couple of minutes...' ); await command( 'npm install @wordpress/env --save-dev', { - cwd, + cwd: rootDirectory, } ); info( '' ); info( 'Configuring `@wordpress/env`...' ); await writeFile( - join( cwd, '.wp-env.json' ), + join( rootDirectory, '.wp-env.json' ), JSON.stringify( { core: 'WordPress/WordPress', diff --git a/packages/create-block/lib/init-wp-scripts.js b/packages/create-block/lib/init-wp-scripts.js index ca0101957f47f1..dbd33ba45187c8 100644 --- a/packages/create-block/lib/init-wp-scripts.js +++ b/packages/create-block/lib/init-wp-scripts.js @@ -2,33 +2,30 @@ * External dependencies */ const { command } = require( 'execa' ); -const { join } = require( 'path' ); /** * Internal dependencies */ const { info } = require( './log' ); -module.exports = async ( { slug } ) => { - const cwd = join( process.cwd(), slug ); - +module.exports = async ( { rootDirectory } ) => { info( '' ); info( 'Installing `@wordpress/scripts` package. It might take a couple of minutes...' ); await command( 'npm install @wordpress/scripts --save-dev', { - cwd, + cwd: rootDirectory, } ); info( '' ); info( 'Formatting JavaScript files.' ); await command( 'npm run format', { - cwd, + cwd: rootDirectory, } ); info( '' ); info( 'Compiling block.' ); await command( 'npm run build', { - cwd, + cwd: rootDirectory, } ); }; diff --git a/packages/create-block/lib/output.js b/packages/create-block/lib/output.js index dd442b17ae0511..71d2e9ebe86e54 100644 --- a/packages/create-block/lib/output.js +++ b/packages/create-block/lib/output.js @@ -7,19 +7,17 @@ const { render } = require( 'mustache' ); const { writeFile } = require( 'fs' ).promises; const writeOutputAsset = async ( inputFile, outputFile, view ) => { - const outputFilePath = join( view.slug, 'assets', outputFile ); + const outputFilePath = join( view.rootDirectory, 'assets', outputFile ); await makeDir( dirname( outputFilePath ) ); writeFile( outputFilePath, inputFile ); }; const writeOutputTemplate = async ( inputFile, outputFile, view ) => { - const outputFilePath = view.plugin - ? join( view.slug, outputFile.replace( /\$slug/g, view.slug ) ) - : outputFile; - await makeDir( dirname( outputFilePath ) ); // If the rendered template is empty, don't write it. This is how we can conditionally add template files. const renderedFile = render( inputFile, view ); if ( renderedFile.trim().length ) { + const outputFilePath = join( view.rootDirectory, outputFile ); + await makeDir( dirname( outputFilePath ) ); writeFile( outputFilePath, renderedFile ); } }; diff --git a/packages/create-block/lib/scaffold.js b/packages/create-block/lib/scaffold.js index b7d4addde6a82c..73b9f549908867 100644 --- a/packages/create-block/lib/scaffold.js +++ b/packages/create-block/lib/scaffold.js @@ -2,6 +2,7 @@ * External dependencies */ const { pascalCase, snakeCase } = require( 'change-case' ); +const { join } = require( 'path' ); /** * Internal dependencies @@ -40,6 +41,7 @@ module.exports = async ( npmDevDependencies, customScripts, folderName, + targetDir, editorScript, editorStyle, style, @@ -56,7 +58,7 @@ module.exports = async ( ) => { slug = slug.toLowerCase(); namespace = namespace.toLowerCase(); - + const rootDirectory = join( process.cwd(), targetDir || slug ); const transformedValues = transformer( { $schema, apiVersion, @@ -94,6 +96,7 @@ module.exports = async ( customBlockJSON, example, textdomain: slug, + rootDirectory, } ); const view = { @@ -117,11 +120,10 @@ module.exports = async ( return; } + const projectType = plugin ? 'plugin' : 'block'; info( '' ); info( - plugin - ? `Creating a new WordPress plugin in the ${ view.slug } directory.` - : `Creating a new block in the ${ view.slug } directory.` + `Creating a new WordPress ${ projectType } in the ${ rootDirectory } directory.` ); if ( plugin ) { @@ -164,9 +166,7 @@ module.exports = async ( info( '' ); success( - plugin - ? `Done: WordPress plugin ${ title } bootstrapped in the ${ slug } directory.` - : `Done: Block "${ title }" bootstrapped in the ${ slug } directory.` + `Done: WordPress ${ projectType } ${ title } bootstrapped in the ${ rootDirectory } directory.` ); if ( plugin && wpScripts ) { From 1f9f17c028aa7656f1914c731602e16242e5db05 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Mon, 28 Oct 2024 23:09:42 +0900 Subject: [PATCH 1362/1908] Fix: Text overflow in Patterns filter (#66504) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../inserter/block-patterns-tab/patterns-filter.js | 2 +- packages/block-editor/src/components/inserter/style.scss | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/patterns-filter.js b/packages/block-editor/src/components/inserter/block-patterns-tab/patterns-filter.js index fd7458a52bf331..766082bd7690d9 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/patterns-filter.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/patterns-filter.js @@ -158,7 +158,7 @@ export function PatternsFilter( { value={ patternSyncFilter } /> </MenuGroup> - <div className="block-editor-tool-selector__help"> + <div className="block-editor-inserter__patterns-filter-help"> { createInterpolateElement( __( 'Patterns are available from the <Link>WordPress.org Pattern Directory</Link>, bundled in the active theme, or created by users on this site. Only patterns created on this site can be synced.' diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index 51228a1c46a248..c6522671f938d7 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -266,6 +266,13 @@ $block-inserter-tabs-height: 44px; margin-top: $grid-unit-30; } +.block-editor-inserter__patterns-filter-help { + padding: $grid-unit-20; + border-top: $border-width solid $gray-300; + color: $gray-700; + min-width: 280px; +} + .block-editor-inserter__media-list, .block-editor-block-patterns-list { overflow-y: auto; From 13be4401a88ad2e7827f6cc207a518636a7eb351 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Mon, 28 Oct 2024 23:12:02 +0900 Subject: [PATCH 1363/1908] Site Editor: Fix button hover style in sidebar navigation screen (#66505) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../sidebar-navigation-screen-navigation-menus/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss index 3667db2d9331d2..334e90e93c42ce 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss @@ -19,7 +19,7 @@ padding-right: 0; } - .components-button { + .block-editor-list-view-block-select-button { color: $gray-600; &:hover, &:focus, From 6372ef77e99d4a2c962f031f434e1f0565618776 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:17:53 +0100 Subject: [PATCH 1364/1908] Show paragraph block variations in rich text inserter (#66318) Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- .../block-editor/src/autocompleters/block.js | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/autocompleters/block.js b/packages/block-editor/src/autocompleters/block.js index 859ae11036c82a..5fc107c4d3d69e 100644 --- a/packages/block-editor/src/autocompleters/block.js +++ b/packages/block-editor/src/autocompleters/block.js @@ -6,6 +6,7 @@ import { createBlock, createBlocksFromInnerBlocksTemplate, parse, + store as blocksStore, } from '@wordpress/blocks'; import { useMemo } from '@wordpress/element'; @@ -36,22 +37,30 @@ function createBlockCompleter() { triggerPrefix: '/', useItems( filterValue ) { - const { rootClientId, selectedBlockName, prioritizedBlocks } = + const { rootClientId, selectedBlockId, prioritizedBlocks } = useSelect( ( select ) => { const { getSelectedBlockClientId, - getBlockName, + getBlock, getBlockListSettings, getBlockRootClientId, } = select( blockEditorStore ); + const { getActiveBlockVariation } = select( blocksStore ); const selectedBlockClientId = getSelectedBlockClientId(); + const { name: blockName, attributes } = getBlock( + selectedBlockClientId + ); + const activeBlockVariation = getActiveBlockVariation( + blockName, + attributes + ); const _rootClientId = getBlockRootClientId( selectedBlockClientId ); return { - selectedBlockName: selectedBlockClientId - ? getBlockName( selectedBlockClientId ) - : null, + selectedBlockId: activeBlockVariation + ? `${ blockName }/${ activeBlockVariation.name }` + : blockName, rootClientId: _rootClientId, prioritizedBlocks: getBlockListSettings( _rootClientId ) @@ -78,11 +87,11 @@ function createBlockCompleter() { ); return initialFilteredItems - .filter( ( item ) => item.name !== selectedBlockName ) + .filter( ( item ) => item.id !== selectedBlockId ) .slice( 0, SHOWN_BLOCK_TYPES ); }, [ filterValue, - selectedBlockName, + selectedBlockId, items, categories, collections, From dd7451ff41acae3c2e9fa56b6ed7a1f14db04a55 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 29 Oct 2024 01:06:10 +0900 Subject: [PATCH 1365/1908] BaseControl: Auto-generate readme (#66500) * Get subcomponent descriptions * Add BaseControl.VisualLabel as Storybook subcomponent * Display `children` as required prop * BaseControl: Auto-generate readme * Fixup * Fixup Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../get-subcomponent-descriptions.mjs | 46 ++++++++ bin/api-docs/gen-components-docs/index.mjs | 30 ++++- .../components/src/base-control/README.md | 105 ++++++++++-------- .../src/base-control/docs-manifest.json | 12 ++ .../src/base-control/stories/index.story.tsx | 4 + packages/components/src/base-control/types.ts | 3 + 6 files changed, 149 insertions(+), 51 deletions(-) create mode 100644 bin/api-docs/gen-components-docs/get-subcomponent-descriptions.mjs create mode 100644 packages/components/src/base-control/docs-manifest.json diff --git a/bin/api-docs/gen-components-docs/get-subcomponent-descriptions.mjs b/bin/api-docs/gen-components-docs/get-subcomponent-descriptions.mjs new file mode 100644 index 00000000000000..4bb82652f1737a --- /dev/null +++ b/bin/api-docs/gen-components-docs/get-subcomponent-descriptions.mjs @@ -0,0 +1,46 @@ +/** + * External dependencies + */ +import fs from 'node:fs/promises'; +import babel from '@babel/core'; +import { parse as commentParser } from 'comment-parser'; + +/** + * Try to get subcomponent descriptions from the main component Object.assign() call. + */ +export async function getDescriptionsForSubcomponents( + filePath, + mainComponentName +) { + const fileContent = await fs.readFile( filePath, 'utf8' ); + const parsedFile = babel.parse( fileContent, { + filename: filePath, + } ); + const mainComponent = parsedFile.program.body + .filter( ( node ) => node.type === 'ExportNamedDeclaration' ) + .flatMap( ( node ) => node.declaration?.declarations ) + .find( ( node ) => node?.id.name === mainComponentName ); + + if ( + ! ( + // If the main component export has `Object.assign( ... )` + ( + mainComponent?.init?.type === 'CallExpression' && + mainComponent?.init?.callee?.object?.name === 'Object' && + mainComponent?.init?.callee?.property?.name === 'assign' + ) + ) + ) { + return; + } + + const properties = mainComponent?.init?.arguments[ 1 ]?.properties.map( + ( node ) => [ + node.key.name, + commentParser( `/*${ node.leadingComments?.[ 0 ].value }*/`, { + spacing: 'preserve', + } )?.[ 0 ]?.description, + ] + ); + return Object.fromEntries( properties ); +} diff --git a/bin/api-docs/gen-components-docs/index.mjs b/bin/api-docs/gen-components-docs/index.mjs index e036995b4c4f74..c7109dc4982c36 100644 --- a/bin/api-docs/gen-components-docs/index.mjs +++ b/bin/api-docs/gen-components-docs/index.mjs @@ -10,6 +10,7 @@ import path from 'path'; * Internal dependencies */ import { generateMarkdownDocs } from './markdown/index.mjs'; +import { getDescriptionsForSubcomponents } from './get-subcomponent-descriptions.mjs'; const MANIFEST_GLOB = 'packages/components/src/**/docs-manifest.json'; @@ -79,8 +80,10 @@ await Promise.all( displayName: manifest.displayName, } ); - const subcomponentTypeDocs = manifest.subcomponents?.map( - ( subcomponent ) => { + let subcomponentDescriptions; + + const subcomponentTypeDocs = await Promise.all( + manifest.subcomponents?.map( async ( subcomponent ) => { const docs = getTypeDocsForComponent( { manifestPath, componentFilePath: subcomponent.filePath, @@ -91,10 +94,29 @@ await Promise.all( docs.displayName = subcomponent.preferredDisplayName; } + if ( ! subcomponent.description ) { + subcomponentDescriptions ??= + getDescriptionsForSubcomponents( + path.resolve( + path.dirname( manifestPath ), + manifest.filePath + ), + manifest.displayName + ); + + docs.description = ( await subcomponentDescriptions )?.[ + subcomponent.displayName + ]; + } + return docs; - } + } ) ?? [] ); - const docs = generateMarkdownDocs( { typeDocs, subcomponentTypeDocs } ); + + const docs = generateMarkdownDocs( { + typeDocs, + subcomponentTypeDocs, + } ); const outputFile = path.resolve( path.dirname( manifestPath ), './README.md' diff --git a/packages/components/src/base-control/README.md b/packages/components/src/base-control/README.md index d51629de6f7253..839464b41260b5 100644 --- a/packages/components/src/base-control/README.md +++ b/packages/components/src/base-control/README.md @@ -1,8 +1,10 @@ # BaseControl -`BaseControl` is a component used to generate labels and help text for components handling user inputs. +<!-- This file is generated automatically and cannot be edited directly. Make edits via TypeScript types and TSDocs. --> + +<p class="callout callout-info">See the <a href="https://wordpress.github.io/gutenberg/?path=/docs/components-basecontrol--docs">WordPress Storybook</a> for more detailed, interactive documentation.</p> -## Usage +`BaseControl` is a component used to generate labels and help text for components handling user inputs. ```jsx import { BaseControl, useBaseControlProps } from '@wordpress/components'; @@ -23,70 +25,80 @@ const MyCustomTextareaControl = ({ children, ...baseProps }) => ( ); ); ``` - ## Props -The component accepts the following props: +### `__nextHasNoMarginBottom` -### id +Start opting into the new margin-free styles that will become the default in a future version. -The HTML `id` of the control element (passed in as a child to `BaseControl`) to which labels and help text are being generated. This is necessary to accessibly associate the label with that element. + - Type: `boolean` + - Required: No + - Default: `false` -The recommended way is to use the `useBaseControlProps` hook, which takes care of generating a unique `id` for you. Otherwise, if you choose to pass an explicit `id` to this prop, you are responsible for ensuring the uniqueness of the `id`. +### `as` -- Type: `String` -- Required: No +The HTML element or React component to render the component as. -### label + - Type: `"symbol" | "object" | "label" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | ... 516 more ... | ("view" & FunctionComponent<...>)` + - Required: No -If this property is added, a label will be generated using label property as the content. +### `className` -- Type: `String` -- Required: No -### hideLabelFromVision + - Type: `string` + - Required: No -If true, the label will only be visible to screen readers. +### `children` + +The content to be displayed within the `BaseControl`. -- Type: `Boolean` -- Required: No + - Type: `ReactNode` + - Required: Yes -### help +### `help` -Additional description for the control. Only use for meaningful description or instructions for the control. An element containing the description will be programmatically associated to the BaseControl by the means of an `aria-describedby` attribute. +Additional description for the control. -- Type: `ReactNode` -- Required: No +Only use for meaningful description or instructions for the control. An element containing the description will be programmatically associated to the BaseControl by the means of an `aria-describedby` attribute. -### className + - Type: `ReactNode` + - Required: No -Any other classes to add to the wrapper div. +### `hideLabelFromVision` -- Type: `String` -- Required: No +If true, the label will only be visible to screen readers. -### children + - Type: `boolean` + - Required: No + - Default: `false` -The content to be displayed within the BaseControl. +### `id` -- Type: `Element` -- Required: Yes +The HTML `id` of the control element (passed in as a child to `BaseControl`) to which labels and help text are being generated. +This is necessary to accessibly associate the label with that element. -### __nextHasNoMarginBottom +The recommended way is to use the `useBaseControlProps` hook, which takes care of generating a unique `id` for you. +Otherwise, if you choose to pass an explicit `id` to this prop, you are responsible for ensuring the uniqueness of the `id`. -Start opting into the new margin-free styles that will become the default in a future version. + - Type: `string` + - Required: No -- Type: `Boolean` -- Required: No -- Default: `false` +### `label` -## BaseControl.VisualLabel +If this property is added, a label will be generated using label property as the content. -`BaseControl.VisualLabel` is used to render a purely visual label inside a `BaseControl` component. + - Type: `ReactNode` + - Required: No -It should only be used in cases where the children being rendered inside BaseControl are already accessibly labeled, e.g., a button, but we want an additional visual label for that section equivalent to the labels `BaseControl` would otherwise use if the `label` prop was passed. +## Subcomponents -## Usage +### BaseControl.VisualLabel + +`BaseControl.VisualLabel` is used to render a purely visual label inside a `BaseControl` component. + +It should only be used in cases where the children being rendered inside `BaseControl` are already accessibly labeled, +e.g., a button, but we want an additional visual label for that section equivalent to the labels `BaseControl` would +otherwise use if the `label` prop was passed. ```jsx import { BaseControl } from '@wordpress/components'; @@ -101,19 +113,18 @@ const MyBaseControl = () => ( </BaseControl> ); ``` +#### Props -### Props - -#### className +##### `as` -Any other classes to add to the wrapper div. +The HTML element or React component to render the component as. -- Type: `String` -- Required: No + - Type: `"symbol" | "object" | "label" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | ...` + - Required: No -#### children +##### `children` The content to be displayed within the `BaseControl.VisualLabel`. -- Type: `Element` -- Required: Yes + - Type: `ReactNode` + - Required: Yes diff --git a/packages/components/src/base-control/docs-manifest.json b/packages/components/src/base-control/docs-manifest.json new file mode 100644 index 00000000000000..fe4cad660a6dc1 --- /dev/null +++ b/packages/components/src/base-control/docs-manifest.json @@ -0,0 +1,12 @@ +{ + "$schema": "../../schemas/docs-manifest.json", + "displayName": "BaseControl", + "filePath": "./index.tsx", + "subcomponents": [ + { + "displayName": "VisualLabel", + "preferredDisplayName": "BaseControl.VisualLabel", + "filePath": "./index.tsx" + } + ] +} diff --git a/packages/components/src/base-control/stories/index.story.tsx b/packages/components/src/base-control/stories/index.story.tsx index 62191f906a4ce3..ca35b793621577 100644 --- a/packages/components/src/base-control/stories/index.story.tsx +++ b/packages/components/src/base-control/stories/index.story.tsx @@ -12,6 +12,10 @@ import Button from '../../button'; const meta: Meta< typeof BaseControl > = { title: 'Components/BaseControl', component: BaseControl, + subcomponents: { + // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 + 'BaseControl.VisualLabel': BaseControl.VisualLabel, + }, argTypes: { children: { control: { type: null } }, help: { control: { type: 'text' } }, diff --git a/packages/components/src/base-control/types.ts b/packages/components/src/base-control/types.ts index e4c838459209c4..9ca2b7bdd4c6ed 100644 --- a/packages/components/src/base-control/types.ts +++ b/packages/components/src/base-control/types.ts @@ -49,5 +49,8 @@ export type BaseControlProps = { }; export type BaseControlVisualLabelProps = { + /** + * The content to be displayed within the `BaseControl.VisualLabel`. + */ children: ReactNode; }; From 60528475cf5a21785475a5e9c05c72ebf8ce4c2b Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 28 Oct 2024 17:38:05 +0100 Subject: [PATCH 1366/1908] Preload: fix multiple regressions around global styles (#66468) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- backport-changelog/6.8/7661.md | 3 ++ lib/compat/wordpress-6.8/preload.php | 29 +++++++++++++++++++ lib/load.php | 1 + packages/core-data/src/resolvers.js | 2 ++ .../global-styles-provider/index.js | 26 +++++++++++++---- 5 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 backport-changelog/6.8/7661.md create mode 100644 lib/compat/wordpress-6.8/preload.php diff --git a/backport-changelog/6.8/7661.md b/backport-changelog/6.8/7661.md new file mode 100644 index 00000000000000..2170f50c2a4e86 --- /dev/null +++ b/backport-changelog/6.8/7661.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7661 + +* https://github.com/WordPress/gutenberg/pull/66468 diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php new file mode 100644 index 00000000000000..057cdc0965757b --- /dev/null +++ b/lib/compat/wordpress-6.8/preload.php @@ -0,0 +1,29 @@ +<?php + +/** + * Preload theme and global styles paths to avoid flash of variation styles in + * post editor. + * + * @param array $paths REST API paths to preload. + * @param WP_Block_Editor_Context $context Current block editor context. + * @return array Filtered preload paths. + */ +function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { + $excluded_paths = array(); + if ( 'core/edit-site' === $context->name || 'core/edit-post' === $context->name ) { + $stylesheet = get_stylesheet(); + $global_styles_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id(); + $paths[] = '/wp/v2/global-styles/themes/' . $stylesheet . '?context=view'; + $paths[] = '/wp/v2/global-styles/themes/' . $stylesheet . '/variations?context=view'; + $paths[] = array( '/wp/v2/global-styles/' . $global_styles_id, 'OPTIONS' ); + $excluded_paths[] = '/wp/v2/global-styles/themes/' . $stylesheet; + $excluded_paths[] = '/wp/v2/global-styles/' . $global_styles_id; + } + foreach ( $paths as $key => $path ) { + if ( in_array( $path, $excluded_paths, true ) ) { + unset( $paths[ $key ] ); + } + } + return $paths; +} +add_filter( 'block_editor_rest_api_preload_paths', 'gutenberg_block_editor_preload_paths_6_8', 10, 2 ); diff --git a/lib/load.php b/lib/load.php index b91118cbced985..d2229a973142f1 100644 --- a/lib/load.php +++ b/lib/load.php @@ -47,6 +47,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.7/rest-api.php'; // WordPress 6.8 compat. + require __DIR__ . '/compat/wordpress-6.8/preload.php'; require __DIR__ . '/compat/wordpress-6.8/remove-default-css.php'; require __DIR__ . '/compat/wordpress-6.8/block-comments.php'; require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php'; diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 91a73a0b3511c2..a5c33e18efbc60 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -644,6 +644,7 @@ export const __experimentalGetCurrentThemeBaseGlobalStyles = () => async ( { resolveSelect, dispatch } ) => { const currentTheme = await resolveSelect.getCurrentTheme(); + // Please adjust the preloaded requests if this changes! const themeGlobalStyles = await apiFetch( { path: `/wp/v2/global-styles/themes/${ currentTheme.stylesheet }?context=view`, } ); @@ -657,6 +658,7 @@ export const __experimentalGetCurrentThemeGlobalStylesVariations = () => async ( { resolveSelect, dispatch } ) => { const currentTheme = await resolveSelect.getCurrentTheme(); + // Please adjust the preloaded requests if this changes! const variations = await apiFetch( { path: `/wp/v2/global-styles/themes/${ currentTheme.stylesheet }/variations?context=view`, } ); diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js index 6f2d8177056cb1..3f3a3389801eb6 100644 --- a/packages/editor/src/components/global-styles-provider/index.js +++ b/packages/editor/src/components/global-styles-provider/index.js @@ -56,13 +56,27 @@ function useGlobalStylesUserConfig() { select( coreStore ).__experimentalGetCurrentGlobalStylesId(); let record; - const userCanEditGlobalStyles = canUser( 'update', { - kind: 'root', - name: 'globalStyles', - id: _globalStylesId, - } ); - if ( _globalStylesId ) { + // We want the global styles ID request to finish before triggering + // the OPTIONS request for user capabilities, otherwise it will + // fetch `/wp/v2/global-styles` instead of + // `/wp/v2/global-styles/{id}`! + // Please adjust the preloaded requests if this changes! + const userCanEditGlobalStyles = _globalStylesId + ? canUser( 'update', { + kind: 'root', + name: 'globalStyles', + id: _globalStylesId, + } ) + : null; + + if ( + _globalStylesId && + // We want the OPTIONS request for user capabilities to finish + // before getting the records, otherwise we'll fetch both! + typeof userCanEditGlobalStyles === 'boolean' + ) { + // Please adjust the preloaded requests if this changes! if ( userCanEditGlobalStyles ) { record = getEditedEntityRecord( 'root', From bff0fcb324fe0befd58912380d92b2a1fd346e3f Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Mon, 28 Oct 2024 17:41:34 +0100 Subject: [PATCH 1367/1908] Tabs: remove custom logic (#66097) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../inserter/category-tabs/index.js | 17 +- packages/components/CHANGELOG.md | 1 + packages/components/src/tabs/index.tsx | 180 +++---------- packages/components/src/tabs/tab.tsx | 26 +- packages/components/src/tabs/test/index.tsx | 247 +++++++++--------- 5 files changed, 212 insertions(+), 259 deletions(-) diff --git a/packages/block-editor/src/components/inserter/category-tabs/index.js b/packages/block-editor/src/components/inserter/category-tabs/index.js index 2641e2a20c40f6..7b6baaab398f82 100644 --- a/packages/block-editor/src/components/inserter/category-tabs/index.js +++ b/packages/block-editor/src/components/inserter/category-tabs/index.js @@ -6,6 +6,7 @@ import { privateApis as componentsPrivateApis, __unstableMotion as motion, } from '@wordpress/components'; +import { useState, useEffect } from '@wordpress/element'; /** * Internal dependencies @@ -31,10 +32,22 @@ function CategoryTabs( { const previousSelectedCategory = usePrevious( selectedCategory ); + const selectedTabId = selectedCategory ? selectedCategory.name : null; + const [ activeTabId, setActiveId ] = useState(); + const firstTabId = categories?.[ 0 ]?.name; + useEffect( () => { + // If there is no active tab, make the first tab the active tab, so that + // when focus is moved to the tablist, the first tab will be focused + // despite not being selected + if ( selectedTabId === null && ! activeTabId && firstTabId ) { + setActiveId( firstTabId ); + } + }, [ selectedTabId, activeTabId, firstTabId, setActiveId ] ); + return ( <Tabs selectOnMove={ false } - selectedTabId={ selectedCategory ? selectedCategory.name : null } + selectedTabId={ selectedTabId } orientation="vertical" onSelect={ ( categoryId ) => { // Pass the full category object @@ -44,6 +57,8 @@ function CategoryTabs( { ) ); } } + activeTabId={ activeTabId } + onActiveTabIdChange={ setActiveId } > <Tabs.TabList className="block-editor-inserter__category-tablist"> { categories.map( ( category ) => ( diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index a9f1286bdc4167..ba0d68d5c12c09 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -19,6 +19,7 @@ ### Experimental +- `Tabs`: remove internal custom logic ([#66097](https://github.com/WordPress/gutenberg/pull/66097)). - `Tabs`: add props to control active tab item ([#66223](https://github.com/WordPress/gutenberg/pull/66223)). - `Tabs`: restore vertical alignent for tabs content ([#66215](https://github.com/WordPress/gutenberg/pull/66215)). - `Tabs`: fix indicator animation ([#66198](https://github.com/WordPress/gutenberg/pull/66198)). diff --git a/packages/components/src/tabs/index.tsx b/packages/components/src/tabs/index.tsx index 37367e4642e152..819d259395daf8 100644 --- a/packages/components/src/tabs/index.tsx +++ b/packages/components/src/tabs/index.tsx @@ -2,18 +2,12 @@ * External dependencies */ import * as Ariakit from '@ariakit/react'; -import { useStoreState } from '@ariakit/react'; /** * WordPress dependencies */ import { useInstanceId } from '@wordpress/compose'; -import { - useEffect, - useLayoutEffect, - useMemo, - useRef, -} from '@wordpress/element'; +import { useEffect, useMemo } from '@wordpress/element'; import { isRTL } from '@wordpress/i18n'; /** @@ -25,6 +19,22 @@ import { Tab } from './tab'; import { TabList } from './tablist'; import { TabPanel } from './tabpanel'; +function externalToInternalTabId( + externalId: string | undefined | null, + instanceId: string +) { + return externalId && `${ instanceId }-${ externalId }`; +} + +function internalToExternalTabId( + internalId: string | undefined | null, + instanceId: string +) { + return typeof internalId === 'string' + ? internalId.replace( `${ instanceId }-`, '' ) + : internalId; +} + /** * Display one panel of content at a time with a tabbed interface, based on the * WAI-ARIA Tabs Pattern⁠. @@ -40,147 +50,41 @@ export const Tabs = Object.assign( onSelect, children, selectedTabId, + activeTabId, + defaultActiveTabId, + onActiveTabIdChange, }: TabsProps ) { const instanceId = useInstanceId( Tabs, 'tabs' ); const store = Ariakit.useTabStore( { selectOnMove, orientation, - defaultSelectedId: - defaultTabId && `${ instanceId }-${ defaultTabId }`, - setSelectedId: ( selectedId ) => { - const strippedDownId = - typeof selectedId === 'string' - ? selectedId.replace( `${ instanceId }-`, '' ) - : selectedId; - onSelect?.( strippedDownId ); + defaultSelectedId: externalToInternalTabId( + defaultTabId, + instanceId + ), + setSelectedId: ( newSelectedId ) => { + onSelect?.( + internalToExternalTabId( newSelectedId, instanceId ) + ); + }, + selectedId: externalToInternalTabId( selectedTabId, instanceId ), + defaultActiveId: externalToInternalTabId( + defaultActiveTabId, + instanceId + ), + setActiveId: ( newActiveId ) => { + onActiveTabIdChange?.( + internalToExternalTabId( newActiveId, instanceId ) + ); }, - selectedId: selectedTabId && `${ instanceId }-${ selectedTabId }`, + activeId: externalToInternalTabId( activeTabId, instanceId ), rtl: isRTL(), } ); - const isControlled = selectedTabId !== undefined; - - const { items, selectedId, activeId } = useStoreState( store ); - const { setSelectedId, setActiveId } = store; - - // Keep track of whether tabs have been populated. This is used to prevent - // certain effects from firing too early while tab data and relevant - // variables are undefined during the initial render. - const tabsHavePopulatedRef = useRef( false ); - if ( items.length > 0 ) { - tabsHavePopulatedRef.current = true; - } - - const selectedTab = items.find( ( item ) => item.id === selectedId ); - const firstEnabledTab = items.find( ( item ) => { - // Ariakit internally refers to disabled tabs as `dimmed`. - return ! item.dimmed; - } ); - const initialTab = items.find( - ( item ) => item.id === `${ instanceId }-${ defaultTabId }` - ); - - // Handle selecting the initial tab. - useLayoutEffect( () => { - if ( isControlled ) { - return; - } - - // Wait for the denoted initial tab to be declared before making a - // selection. This ensures that if a tab is declared lazily it can - // still receive initial selection, as well as ensuring no tab is - // selected if an invalid `defaultTabId` is provided. - if ( defaultTabId && ! initialTab ) { - return; - } - - // If the currently selected tab is missing (i.e. removed from the DOM), - // fall back to the initial tab or the first enabled tab if there is - // one. Otherwise, no tab should be selected. - if ( ! items.find( ( item ) => item.id === selectedId ) ) { - if ( initialTab && ! initialTab.dimmed ) { - setSelectedId( initialTab?.id ); - return; - } - - if ( firstEnabledTab ) { - setSelectedId( firstEnabledTab.id ); - } else if ( tabsHavePopulatedRef.current ) { - setSelectedId( null ); - } - } - }, [ - firstEnabledTab, - initialTab, - defaultTabId, - isControlled, - items, - selectedId, - setSelectedId, - ] ); - - // Handle the currently selected tab becoming disabled. - useLayoutEffect( () => { - if ( ! selectedTab?.dimmed ) { - return; - } - - // In controlled mode, we trust that disabling tabs is done - // intentionally, and don't select a new tab automatically. - if ( isControlled ) { - setSelectedId( null ); - return; - } - - // If the currently selected tab becomes disabled, fall back to the - // `defaultTabId` if possible. Otherwise select the first - // enabled tab (if there is one). - if ( initialTab && ! initialTab.dimmed ) { - setSelectedId( initialTab.id ); - return; - } - - if ( firstEnabledTab ) { - setSelectedId( firstEnabledTab.id ); - } - }, [ - firstEnabledTab, - initialTab, - isControlled, - selectedTab?.dimmed, - setSelectedId, - ] ); - - // Clear `selectedId` if the active tab is removed from the DOM in controlled mode. - useLayoutEffect( () => { - if ( ! isControlled ) { - return; - } - - // Once the tabs have populated, if the `selectedTabId` still can't be - // found, clear the selection. - if ( - tabsHavePopulatedRef.current && - !! selectedTabId && - ! selectedTab - ) { - setSelectedId( null ); - } - }, [ isControlled, selectedTab, selectedTabId, setSelectedId ] ); + const { items, activeId } = Ariakit.useStoreState( store ); + const { setActiveId } = store; useEffect( () => { - // If there is no active tab, fallback to place focus on the first enabled tab - // so there is always an active element - if ( selectedTabId === null && ! activeId && firstEnabledTab?.id ) { - setActiveId( firstEnabledTab.id ); - } - }, [ selectedTabId, activeId, firstEnabledTab?.id, setActiveId ] ); - - useEffect( () => { - if ( ! isControlled ) { - return; - } - requestAnimationFrame( () => { const focusedElement = items?.[ 0 ]?.element?.ownerDocument.activeElement; @@ -200,7 +104,7 @@ export const Tabs = Object.assign( setActiveId( focusedElement.id ); } } ); - }, [ activeId, isControlled, items, setActiveId ] ); + }, [ activeId, items, setActiveId ] ); const contextValue = useMemo( () => ( { diff --git a/packages/components/src/tabs/tab.tsx b/packages/components/src/tabs/tab.tsx index 29f6111adc8397..70f56e52ad2627 100644 --- a/packages/components/src/tabs/tab.tsx +++ b/packages/components/src/tabs/tab.tsx @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import * as Ariakit from '@ariakit/react'; + /** * WordPress dependencies */ @@ -22,13 +27,27 @@ export const Tab = forwardRef< HTMLButtonElement, Omit< WordPressComponentProps< TabProps, 'button', false >, 'id' > >( function Tab( { children, tabId, disabled, render, ...otherProps }, ref ) { - const context = useTabsContext(); - if ( ! context ) { + const { store, instanceId } = useTabsContext() ?? {}; + + // If the active item is not connected, the tablist may end up in a state + // where none of the tabs are tabbable. In this case, we force all tabs to + // be tabbable, so that as soon as an item received focus, it becomes active + // and Tablist goes back to working as expected. + // eslint-disable-next-line @wordpress/no-unused-vars-before-return + const tabbable = Ariakit.useStoreState( store, ( state ) => { + return ( + state?.activeId !== null && + ! store?.item( state?.activeId )?.element?.isConnected + ); + } ); + + if ( ! store ) { warning( '`Tabs.Tab` must be wrapped in a `Tabs` component.' ); return null; } - const { store, instanceId } = context; + const instancedTabId = `${ instanceId }-${ tabId }`; + return ( <StyledTab ref={ ref } @@ -36,6 +55,7 @@ export const Tab = forwardRef< id={ instancedTabId } disabled={ disabled } render={ render } + tabbable={ tabbable } { ...otherProps } > <StyledTabChildren>{ children }</StyledTabChildren> diff --git a/packages/components/src/tabs/test/index.tsx b/packages/components/src/tabs/test/index.tsx index 82c75a3f16b253..dcf64102c9fa67 100644 --- a/packages/components/src/tabs/test/index.tsx +++ b/packages/components/src/tabs/test/index.tsx @@ -129,7 +129,11 @@ const ControlledTabs = ( { ) ) } </Tabs.TabList> { tabs.map( ( tabObj ) => ( - <Tabs.TabPanel key={ tabObj.tabId } tabId={ tabObj.tabId }> + <Tabs.TabPanel + key={ tabObj.tabId } + tabId={ tabObj.tabId } + focusable={ tabObj.tabpanel?.focusable } + > { tabObj.content } </Tabs.TabPanel> ) ) } @@ -191,6 +195,8 @@ describe( 'Tabs', () => { it( 'should focus on the related TabPanel when pressing the Tab key', async () => { await render( <UncontrolledTabs tabs={ TABS } /> ); + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + const selectedTabPanel = await screen.findByRole( 'tabpanel' ); // Tab should initially focus the first tab in the tablist, which @@ -224,6 +230,8 @@ describe( 'Tabs', () => { <UncontrolledTabs tabs={ TABS_WITH_ALPHA_FOCUSABLE_FALSE } /> ); + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + const alphaButton = await screen.findByRole( 'button', { name: /alpha button/i, } ); @@ -240,7 +248,7 @@ describe( 'Tabs', () => { expect( alphaButton ).toHaveFocus(); } ); - it( 'should focus on the first enabled tab when pressing the Tab key if no tab is selected', async () => { + it( "should focus the first tab, even if disabled, when the current selected tab id doesn't match an existing one", async () => { const TABS_WITH_ALPHA_DISABLED = TABS.map( ( tabObj ) => tabObj.tabId === 'alpha' ? { @@ -256,11 +264,26 @@ describe( 'Tabs', () => { await render( <ControlledTabs tabs={ TABS_WITH_ALPHA_DISABLED } - selectedTabId={ null } + selectedTabId="non-existing-tab" /> ); + // No tab should be selected i.e. it doesn't fall back to first tab. + await waitFor( () => + expect( + screen.queryByRole( 'tab', { selected: true } ) + ).not.toBeInTheDocument() + ); + + // No tabpanel should be rendered either + expect( screen.queryByRole( 'tabpanel' ) ).not.toBeInTheDocument(); + await press.Tab(); + expect( + await screen.findByRole( 'tab', { name: 'Alpha' } ) + ).toHaveFocus(); + + await press.ArrowRight(); expect( await screen.findByRole( 'tab', { name: 'Beta' } ) ).toHaveFocus(); @@ -335,6 +358,8 @@ describe( 'Tabs', () => { <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> ); + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + // onSelect gets called on the initial render. It should be called // with the first enabled tab, which is alpha. expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); @@ -370,12 +395,14 @@ describe( 'Tabs', () => { <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> ); + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + expect( await getSelectedTab() ).not.toHaveFocus(); + // onSelect gets called on the initial render. expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); // Tab to focus the tablist. Make sure Alpha is focused. - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).not.toHaveFocus(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -403,14 +430,14 @@ describe( 'Tabs', () => { <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> ); - // onSelect gets called on the initial render. It should be called - // with the first enabled tab, which is alpha. + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + expect( await getSelectedTab() ).not.toHaveFocus(); + + // onSelect gets called on the initial render. expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); - // Tab to focus the tablist. Make sure alpha is focused. - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).not.toHaveFocus(); + // Tab to focus the tablist. Make sure Alpha is focused. await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -502,16 +529,17 @@ describe( 'Tabs', () => { /> ); - // onSelect gets called on the initial render. It should be called - // with the first enabled tab, which is alpha. + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + expect( await getSelectedTab() ).not.toHaveFocus(); + + // onSelect gets called on the initial render. expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); // Tab to focus the tablist. Make sure Alpha is focused. - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).not.toHaveFocus(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); + // Confirm onSelect has not been re-called expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); @@ -550,6 +578,9 @@ describe( 'Tabs', () => { it( 'should not focus the next tab when the Tab key is pressed', async () => { await render( <UncontrolledTabs tabs={ TABS } /> ); + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + expect( await getSelectedTab() ).not.toHaveFocus(); + // Tab should initially focus the first tab in the tablist, which // is Alpha. await press.Tab(); @@ -579,8 +610,10 @@ describe( 'Tabs', () => { /> ); - // onSelect gets called on the initial render. It should be called - // with the first enabled tab, which is alpha. + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + expect( await getSelectedTab() ).not.toHaveFocus(); + + // onSelect gets called on the initial render. expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); @@ -635,39 +668,20 @@ describe( 'Tabs', () => { await screen.findByRole( 'tabpanel', { name: 'Alpha' } ) ).toBeInTheDocument(); } ); - it( 'should fall back to first enabled tab if the active tab is removed', async () => { + it( 'should not have a selected tab if the currently selected tab is removed', async () => { const { rerender } = await render( <UncontrolledTabs tabs={ TABS } /> ); - // Remove first item from `TABS` array - await rerender( <UncontrolledTabs tabs={ TABS.slice( 1 ) } /> ); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); - } ); - it( 'should not load any tab if the active tab is removed and there are no enabled tabs', async () => { - const TABS_WITH_BETA_GAMMA_DISABLED = TABS.map( ( tabObj ) => - tabObj.tabId !== 'alpha' - ? { - ...tabObj, - tab: { - ...tabObj.tab, - disabled: true, - }, - } - : tabObj - ); - - const { rerender } = await render( - <UncontrolledTabs tabs={ TABS_WITH_BETA_GAMMA_DISABLED } /> - ); expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + expect( await getSelectedTab() ).not.toHaveFocus(); - // Remove alpha - await rerender( - <UncontrolledTabs - tabs={ TABS_WITH_BETA_GAMMA_DISABLED.slice( 1 ) } - /> - ); + // Tab to focus the tablist. Make sure Alpha is focused. + await press.Tab(); + expect( await getSelectedTab() ).toHaveFocus(); + + // Remove first item from `TABS` array + await rerender( <UncontrolledTabs tabs={ TABS.slice( 1 ) } /> ); // No tab should be selected i.e. it doesn't fall back to first tab. await waitFor( () => @@ -715,6 +729,8 @@ describe( 'Tabs', () => { <UncontrolledTabs tabs={ TABS } defaultTabId="beta" /> ); + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + await rerender( <UncontrolledTabs tabs={ TABS } defaultTabId="alpha" /> ); @@ -722,7 +738,7 @@ describe( 'Tabs', () => { expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); } ); - it( 'should fall back to the tab associated to `defaultTabId` if the currently active tab is removed', async () => { + it( 'should not have any selected tabs if the currently selected tab is removed, even if a tab is matching the defaultTabId', async () => { const mockOnSelect = jest.fn(); const { rerender } = await render( @@ -747,10 +763,20 @@ describe( 'Tabs', () => { /> ); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + // No tab should be selected i.e. it doesn't fall back to first tab. + await waitFor( () => + expect( + screen.queryByRole( 'tab', { selected: true } ) + ).not.toBeInTheDocument() + ); + + // No tabpanel should be rendered either + expect( + screen.queryByRole( 'tabpanel' ) + ).not.toBeInTheDocument(); } ); - it( 'should fall back to the tab associated to `defaultTabId` if the currently active tab becomes disabled', async () => { + it( 'should keep the currently selected tab even if it becomes disabled', async () => { const mockOnSelect = jest.fn(); const { rerender } = await render( @@ -765,6 +791,8 @@ describe( 'Tabs', () => { await click( screen.getByRole( 'tab', { name: 'Alpha' } ) ); expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); const TABS_WITH_ALPHA_DISABLED = TABS.map( ( tabObj ) => @@ -787,7 +815,8 @@ describe( 'Tabs', () => { /> ); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); } ); it( 'should have no active tabs when the tab associated to `defaultTabId` is removed while being the active tab', async () => { @@ -821,9 +850,16 @@ describe( 'Tabs', () => { <UncontrolledTabs tabs={ TABS } defaultTabId="delta" /> ); - // There should be no selected tab yet. + // No tab should be selected i.e. it doesn't fall back to first tab. + await waitFor( () => + expect( + screen.queryByRole( 'tab', { selected: true } ) + ).not.toBeInTheDocument() + ); + + // No tabpanel should be rendered either expect( - screen.queryByRole( 'tab', { selected: true } ) + screen.queryByRole( 'tabpanel' ) ).not.toBeInTheDocument(); await rerender( @@ -861,6 +897,8 @@ describe( 'Tabs', () => { /> ); + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + expect( screen.getByRole( 'tab', { name: 'Delta' } ) ).toHaveAttribute( 'aria-disabled', 'true' ); @@ -918,7 +956,7 @@ describe( 'Tabs', () => { expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); } ); - it( 'should select first enabled tab when the tab associated to `defaultTabId` is disabled', async () => { + it( 'should select the tab associated to `defaultTabId` even if the tab is disabled', async () => { const TABS_ONLY_GAMMA_ENABLED = TABS.map( ( tabObj ) => tabObj.tabId !== 'gamma' ? { @@ -939,7 +977,7 @@ describe( 'Tabs', () => { // As alpha (first tab), and beta (the initial tab), are both // disabled the first enabled tab should be gamma. - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); // Re-enable all tabs await rerender( @@ -948,10 +986,10 @@ describe( 'Tabs', () => { // Even if the initial tab becomes enabled again, the selected tab doesn't // change. - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); } ); - it( 'should select the first enabled tab when the selected tab becomes disabled', async () => { + it( 'should keep the currently tab as selected even when it becomes disabled', async () => { const mockOnSelect = jest.fn(); const { rerender } = await render( <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> @@ -981,21 +1019,19 @@ describe( 'Tabs', () => { /> ); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); - expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); // Re-enable all tabs await rerender( <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> ); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); - expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); } ); - it( 'should select the first enabled tab when the tab associated to `defaultTabId` becomes disabled while being the active tab', async () => { + it( 'should select the tab associated to `defaultTabId` even when disabled', async () => { const mockOnSelect = jest.fn(); const { rerender } = await render( @@ -1029,9 +1065,7 @@ describe( 'Tabs', () => { /> ); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); // Re-enable all tabs await rerender( @@ -1044,8 +1078,8 @@ describe( 'Tabs', () => { // Confirm that alpha is still selected, and that onSelect has // not been called again. - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); + expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + expect( mockOnSelect ).not.toHaveBeenCalled(); } ); } ); } ); @@ -1072,7 +1106,7 @@ describe( 'Tabs', () => { expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); } ); - it( 'should not render any tab if `selectedTabId` does not match any known tab', async () => { + it( 'should not have a selected tab if `selectedTabId` does not match any known tab', async () => { await render( <ControlledTabs tabs={ TABS_WITH_DELTA } @@ -1087,11 +1121,13 @@ describe( 'Tabs', () => { // No tabpanel should be rendered either expect( screen.queryByRole( 'tabpanel' ) ).not.toBeInTheDocument(); } ); - it( 'should not render any tab if the active tab is removed', async () => { + it( 'should not have a selected tab if the active tab is removed, but should select a tab that gets added if it matches the selectedTabId', async () => { const { rerender } = await render( <ControlledTabs tabs={ TABS } selectedTabId="beta" /> ); + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + // Remove beta await rerender( <ControlledTabs @@ -1110,6 +1146,7 @@ describe( 'Tabs', () => { screen.queryByRole( 'tab', { selected: true } ) ).not.toBeInTheDocument() ); + // No tabpanel should be rendered either expect( screen.queryByRole( 'tabpanel' ) ).not.toBeInTheDocument(); @@ -1118,17 +1155,11 @@ describe( 'Tabs', () => { <ControlledTabs tabs={ TABS } selectedTabId="beta" /> ); - // No tab should be selected i.e. it doesn't reselect the previously - // removed tab. - expect( - screen.queryByRole( 'tab', { selected: true } ) - ).not.toBeInTheDocument(); - // No tabpanel should be rendered either - expect( screen.queryByRole( 'tabpanel' ) ).not.toBeInTheDocument(); + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); } ); describe( 'Disabled tab', () => { - it( 'should not render any tab if `selectedTabId` refers to a disabled tab', async () => { + it( 'should `selectedTabId` refers to a disabled tab', async () => { const TABS_WITH_DELTA_WITH_BETA_DISABLED = TABS_WITH_DELTA.map( ( tabObj ) => tabObj.tabId === 'beta' @@ -1149,18 +1180,9 @@ describe( 'Tabs', () => { /> ); - // No tab should be selected i.e. it doesn't fall back to first tab. - await waitFor( () => { - expect( - screen.queryByRole( 'tab', { selected: true } ) - ).not.toBeInTheDocument(); - } ); - // No tabpanel should be rendered either - expect( - screen.queryByRole( 'tabpanel' ) - ).not.toBeInTheDocument(); + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); } ); - it( 'should not render any tab when the selected tab becomes disabled', async () => { + it( 'should keep the currently selected tab as selected even when it becomes disabled', async () => { const { rerender } = await render( <ControlledTabs tabs={ TABS } selectedTabId="beta" /> ); @@ -1185,33 +1207,15 @@ describe( 'Tabs', () => { selectedTabId="beta" /> ); - // No tab should be selected i.e. it doesn't fall back to first tab. - // `waitFor` is needed here to prevent testing library from - // throwing a 'not wrapped in `act()`' error. - await waitFor( () => { - expect( - screen.queryByRole( 'tab', { selected: true } ) - ).not.toBeInTheDocument(); - } ); - // No tabpanel should be rendered either - expect( - screen.queryByRole( 'tabpanel' ) - ).not.toBeInTheDocument(); + + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); // re-enable all tabs await rerender( <ControlledTabs tabs={ TABS } selectedTabId="beta" /> ); - // If the previously selected tab is reenabled, it should not - // be reselected. - expect( - screen.queryByRole( 'tab', { selected: true } ) - ).not.toBeInTheDocument(); - // No tabpanel should be rendered either - expect( - screen.queryByRole( 'tabpanel' ) - ).not.toBeInTheDocument(); + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); } ); } ); describe( 'When `selectedId` is changed by the controlling component', () => { @@ -1227,14 +1231,18 @@ describe( 'Tabs', () => { /> ); + expect( await getSelectedTab() ).toHaveTextContent( + 'Beta' + ); + // Tab key should focus the currently selected tab, which is Beta. await press.Tab(); - await waitFor( async () => - expect( await getSelectedTab() ).toHaveTextContent( - 'Beta' - ) + expect( await getSelectedTab() ).toHaveTextContent( + 'Beta' ); - expect( await getSelectedTab() ).toHaveFocus(); + expect( + screen.getByRole( 'tab', { name: 'Beta' } ) + ).toHaveFocus(); await rerender( <ControlledTabs @@ -1244,12 +1252,10 @@ describe( 'Tabs', () => { /> ); - // When the selected tab is changed, it should not automatically receive focus. - + // When the selected tab is changed, focus should not be changed. expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); - expect( screen.getByRole( 'tab', { name: 'Beta' } ) ).toHaveFocus(); @@ -1273,13 +1279,19 @@ describe( 'Tabs', () => { </> ); + expect( await getSelectedTab() ).toHaveTextContent( + 'Beta' + ); + // Tab key should focus the currently selected tab, which is Beta. await press.Tab(); await press.Tab(); expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); - expect( await getSelectedTab() ).toHaveFocus(); + expect( + screen.getByRole( 'tab', { name: 'Beta' } ) + ).toHaveFocus(); await rerender( <> @@ -1293,7 +1305,6 @@ describe( 'Tabs', () => { ); // When the selected tab is changed, it should not automatically receive focus. - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); @@ -1332,6 +1343,8 @@ describe( 'Tabs', () => { <ControlledTabs tabs={ TABS } selectedTabId="beta" /> ); + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + await press.Tab(); // Tab key should focus the currently selected tab, which is Beta. From b7f143fb7da0602feec377899f6c18a18c5178bd Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:53:52 +0200 Subject: [PATCH 1368/1908] Navigation: Improve trigger for fallback navigation (#66478) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> --- .../index.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js index 18e6a4210ee1b2..ece549f57378b2 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js @@ -43,9 +43,6 @@ function buildMenuLabel( title, id, status ) { ); } -// Save a boolean to prevent us creating a fallback more than once per session. -let hasCreatedFallback = false; - export default function SidebarNavigationScreenNavigationMenus( { backPath } ) { const { records: navigationMenus, @@ -61,21 +58,22 @@ export default function SidebarNavigationScreenNavigationMenus( { backPath } ) { isResolvingNavigationMenus && ! hasResolvedNavigationMenus; const { getNavigationFallbackId } = unlock( useSelect( coreStore ) ); + const isCreatingNavigationFallback = useSelect( + ( select ) => + select( coreStore ).isResolving( 'getNavigationFallbackId' ), + [] + ); const firstNavigationMenu = navigationMenus?.[ 0 ]; - // Save a boolean to prevent us creating a fallback more than once per session. - if ( firstNavigationMenu ) { - hasCreatedFallback = true; - } - // If there is no navigation menu found // then trigger fallback algorithm to create one. if ( ! firstNavigationMenu && ! isResolvingNavigationMenus && hasResolvedNavigationMenus && - ! hasCreatedFallback + // Ensure a fallback navigation is created only once + ! isCreatingNavigationFallback ) { getNavigationFallbackId(); } From 624501c6231cbe1ed06f50e435afbe6a4e3286eb Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Mon, 28 Oct 2024 19:27:44 +0200 Subject: [PATCH 1369/1908] README: Add Storybook badge (#66529) * README: Add Storybook badge * Add alt tag Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9c920337ef5941..87db481b5b6b4f 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ [![React Native E2E Tests (iOS)](<https://github.com/WordPress/gutenberg/workflows/React%20Native%20E2E%20Tests%20(iOS)/badge.svg>)](https://github.com/WordPress/gutenberg/actions?query=workflow%3A%22React+Native+E2E+Tests+%28iOS%29%22+branch%3Atrunk) [![React Native E2E Tests (Android)](<https://github.com/WordPress/gutenberg/workflows/React%20Native%20E2E%20Tests%20(Android)/badge.svg>)](https://github.com/WordPress/gutenberg/actions?query=workflow%3A%22React+Native+E2E+Tests+%28Android%29%22+branch%3Atrunk) +<a href="https://wordpress.github.io/gutenberg/" target="_blank"><img src="https://raw.githubusercontent.com/storybooks/brand/master/badge/badge-storybook.svg" alt="Storybook Badge" /></a> + [![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lerna.js.org) ![Screenshot of the Gutenberg Editor, editing a post in WordPress](https://user-images.githubusercontent.com/1204802/100067796-fc3e8700-2e36-11eb-993b-6b80b4310b87.png) From c4b8e510351c5922ed23eb9d9eaf04ef233d3df9 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Tue, 29 Oct 2024 10:21:49 +1100 Subject: [PATCH 1370/1908] Revert 66431 (Site editor: remove "default" admin CSS) (#66540) Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> --- backport-changelog/6.8/7642.md | 3 --- lib/compat/wordpress-6.8/remove-default-css.php | 11 ----------- lib/load.php | 1 - 3 files changed, 15 deletions(-) delete mode 100644 backport-changelog/6.8/7642.md delete mode 100644 lib/compat/wordpress-6.8/remove-default-css.php diff --git a/backport-changelog/6.8/7642.md b/backport-changelog/6.8/7642.md deleted file mode 100644 index f00d4a5473aac8..00000000000000 --- a/backport-changelog/6.8/7642.md +++ /dev/null @@ -1,3 +0,0 @@ -https://github.com/WordPress/wordpress-develop/pull/7642 - -* https://github.com/WordPress/gutenberg/pull/66431 \ No newline at end of file diff --git a/lib/compat/wordpress-6.8/remove-default-css.php b/lib/compat/wordpress-6.8/remove-default-css.php deleted file mode 100644 index 1076d84f299214..00000000000000 --- a/lib/compat/wordpress-6.8/remove-default-css.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -function gutenberg_remove_default_css( $hook ) { - // Maybe also remove on post.php when Gutenberg is enabled for posts. - if ( 'site-editor.php' !== $hook ) { - return; - } - wp_dequeue_style( 'colors' ); -} - -add_action( 'admin_enqueue_scripts', 'gutenberg_remove_default_css' ); diff --git a/lib/load.php b/lib/load.php index d2229a973142f1..574d901e72a69c 100644 --- a/lib/load.php +++ b/lib/load.php @@ -48,7 +48,6 @@ function gutenberg_is_experiment_enabled( $name ) { // WordPress 6.8 compat. require __DIR__ . '/compat/wordpress-6.8/preload.php'; - require __DIR__ . '/compat/wordpress-6.8/remove-default-css.php'; require __DIR__ . '/compat/wordpress-6.8/block-comments.php'; require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php'; From 02da2910ff349fc013417472d1570315a3e89537 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Mon, 28 Oct 2024 17:27:59 -0700 Subject: [PATCH 1371/1908] Fix extraneous scrollbar in device previews (#66494) Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> Co-authored-by: dhruvang21 <dhruvang21@git.wordpress.org> --- packages/block-editor/src/components/iframe/style.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/components/iframe/style.scss b/packages/block-editor/src/components/iframe/style.scss index 5dd30c338057e2..b7374304b38e04 100644 --- a/packages/block-editor/src/components/iframe/style.scss +++ b/packages/block-editor/src/components/iframe/style.scss @@ -1,7 +1,6 @@ .block-editor-iframe__container { width: 100%; height: 100%; - overflow-x: hidden; } .block-editor-iframe__scale-container { From dc4bd0502d9ef354a3f9556d1a36aa1a60d526b8 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Tue, 29 Oct 2024 13:45:27 +1100 Subject: [PATCH 1372/1908] Global styles: move preload paths filter to 6.7 (previously 6.8) (#66543) * Given that this fixes a 6.7 regression move the code into 6.7 compat. * Move for loop into context block * Move backport log to 6.7 Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- backport-changelog/{6.8 => 6.7}/7661.md | 1 + lib/compat/wordpress-6.7/rest-api.php | 19 ++++++++++++++++ lib/compat/wordpress-6.8/preload.php | 29 ------------------------- lib/load.php | 1 - 4 files changed, 20 insertions(+), 30 deletions(-) rename backport-changelog/{6.8 => 6.7}/7661.md (67%) delete mode 100644 lib/compat/wordpress-6.8/preload.php diff --git a/backport-changelog/6.8/7661.md b/backport-changelog/6.7/7661.md similarity index 67% rename from backport-changelog/6.8/7661.md rename to backport-changelog/6.7/7661.md index 2170f50c2a4e86..711d03595162ca 100644 --- a/backport-changelog/6.8/7661.md +++ b/backport-changelog/6.7/7661.md @@ -1,3 +1,4 @@ https://github.com/WordPress/wordpress-develop/pull/7661 * https://github.com/WordPress/gutenberg/pull/66468 +* https://github.com/WordPress/gutenberg/pull/66543 diff --git a/lib/compat/wordpress-6.7/rest-api.php b/lib/compat/wordpress-6.7/rest-api.php index 313367594caae0..89efdc4c4219d2 100644 --- a/lib/compat/wordpress-6.7/rest-api.php +++ b/lib/compat/wordpress-6.7/rest-api.php @@ -50,6 +50,25 @@ function gutenberg_block_editor_preload_paths_6_7( $paths, $context ) { } } + // Preload theme and global styles paths. + $excluded_paths = array(); + if ( 'core/edit-site' === $context->name || 'core/edit-post' === $context->name ) { + $active_theme = get_stylesheet(); + $global_styles_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id(); + $paths[] = '/wp/v2/global-styles/themes/' . $active_theme . '?context=view'; + $paths[] = '/wp/v2/global-styles/themes/' . $active_theme . '/variations?context=view'; + $paths[] = array( '/wp/v2/global-styles/' . $global_styles_id, 'OPTIONS' ); + + // Remove duplicate or unnecessary global styles paths. + $excluded_paths[] = '/wp/v2/global-styles/themes/' . $active_theme; + $excluded_paths[] = '/wp/v2/global-styles/' . $global_styles_id; + foreach ( $paths as $key => $path ) { + if ( in_array( $path, $excluded_paths, true ) ) { + unset( $paths[ $key ] ); + } + } + } + return $paths; } add_filter( 'block_editor_rest_api_preload_paths', 'gutenberg_block_editor_preload_paths_6_7', 10, 2 ); diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php deleted file mode 100644 index 057cdc0965757b..00000000000000 --- a/lib/compat/wordpress-6.8/preload.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/** - * Preload theme and global styles paths to avoid flash of variation styles in - * post editor. - * - * @param array $paths REST API paths to preload. - * @param WP_Block_Editor_Context $context Current block editor context. - * @return array Filtered preload paths. - */ -function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { - $excluded_paths = array(); - if ( 'core/edit-site' === $context->name || 'core/edit-post' === $context->name ) { - $stylesheet = get_stylesheet(); - $global_styles_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id(); - $paths[] = '/wp/v2/global-styles/themes/' . $stylesheet . '?context=view'; - $paths[] = '/wp/v2/global-styles/themes/' . $stylesheet . '/variations?context=view'; - $paths[] = array( '/wp/v2/global-styles/' . $global_styles_id, 'OPTIONS' ); - $excluded_paths[] = '/wp/v2/global-styles/themes/' . $stylesheet; - $excluded_paths[] = '/wp/v2/global-styles/' . $global_styles_id; - } - foreach ( $paths as $key => $path ) { - if ( in_array( $path, $excluded_paths, true ) ) { - unset( $paths[ $key ] ); - } - } - return $paths; -} -add_filter( 'block_editor_rest_api_preload_paths', 'gutenberg_block_editor_preload_paths_6_8', 10, 2 ); diff --git a/lib/load.php b/lib/load.php index 574d901e72a69c..2c8a0fd0347c92 100644 --- a/lib/load.php +++ b/lib/load.php @@ -47,7 +47,6 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.7/rest-api.php'; // WordPress 6.8 compat. - require __DIR__ . '/compat/wordpress-6.8/preload.php'; require __DIR__ . '/compat/wordpress-6.8/block-comments.php'; require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php'; From d4db1b44cee43c4564b461643522dd7589e22570 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 29 Oct 2024 07:33:15 +0400 Subject: [PATCH 1373/1908] Composer: Fix React Compiler errors for 'useDropZone' (#66469) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../compose/src/hooks/use-drop-zone/index.js | 68 ++++++------------- 1 file changed, 21 insertions(+), 47 deletions(-) diff --git a/packages/compose/src/hooks/use-drop-zone/index.js b/packages/compose/src/hooks/use-drop-zone/index.js index c570c034415923..1bf1b822228273 100644 --- a/packages/compose/src/hooks/use-drop-zone/index.js +++ b/packages/compose/src/hooks/use-drop-zone/index.js @@ -1,34 +1,8 @@ -/** - * WordPress dependencies - */ -import { useRef } from '@wordpress/element'; - /** * Internal dependencies */ import useRefEffect from '../use-ref-effect'; - -/* eslint-disable jsdoc/valid-types */ -/** - * @template T - * @param {T} value - * @return {import('react').MutableRefObject<T|null>} A ref with the value. - */ -function useFreshRef( value ) { - /* eslint-enable jsdoc/valid-types */ - /* eslint-disable jsdoc/no-undefined-types */ - /** @type {import('react').MutableRefObject<T>} */ - /* eslint-enable jsdoc/no-undefined-types */ - // Disable reason: We're doing something pretty JavaScript-y here where the - // ref will always have a current value that is not null or undefined but it - // needs to start as undefined. We don't want to change the return type so - // it's easier to just ts-ignore this specific line that's complaining about - // undefined not being part of T. - // @ts-ignore - const ref = useRef(); - ref.current = value; - return ref; -} +import useEvent from '../use-event'; /** * A hook to facilitate drag and drop handling. @@ -55,12 +29,12 @@ export default function useDropZone( { onDragEnd: _onDragEnd, onDragOver: _onDragOver, } ) { - const onDropRef = useFreshRef( _onDrop ); - const onDragStartRef = useFreshRef( _onDragStart ); - const onDragEnterRef = useFreshRef( _onDragEnter ); - const onDragLeaveRef = useFreshRef( _onDragLeave ); - const onDragEndRef = useFreshRef( _onDragEnd ); - const onDragOverRef = useFreshRef( _onDragOver ); + const onDropEvent = useEvent( _onDrop ); + const onDragStartEvent = useEvent( _onDragStart ); + const onDragEnterEvent = useEvent( _onDragEnter ); + const onDragLeaveEvent = useEvent( _onDragLeave ); + const onDragEndEvent = useEvent( _onDragEnd ); + const onDragOverEvent = useEvent( _onDragOver ); return useRefEffect( ( elem ) => { @@ -122,8 +96,8 @@ export default function useDropZone( { ownerDocument.addEventListener( 'dragend', maybeDragEnd ); ownerDocument.addEventListener( 'mousemove', maybeDragEnd ); - if ( onDragStartRef.current ) { - onDragStartRef.current( event ); + if ( _onDragStart ) { + onDragStartEvent( event ); } } @@ -142,15 +116,15 @@ export default function useDropZone( { return; } - if ( onDragEnterRef.current ) { - onDragEnterRef.current( event ); + if ( _onDragEnter ) { + onDragEnterEvent( event ); } } function onDragOver( /** @type {DragEvent} */ event ) { // Only call onDragOver for the innermost hovered drop zones. - if ( ! event.defaultPrevented && onDragOverRef.current ) { - onDragOverRef.current( event ); + if ( ! event.defaultPrevented && _onDragOver ) { + onDragOverEvent( event ); } // Prevent the browser default while also signalling to parent @@ -171,8 +145,8 @@ export default function useDropZone( { return; } - if ( onDragLeaveRef.current ) { - onDragLeaveRef.current( event ); + if ( _onDragLeave ) { + onDragLeaveEvent( event ); } } @@ -192,8 +166,8 @@ export default function useDropZone( { // eslint-disable-next-line no-unused-expressions event.dataTransfer && event.dataTransfer.files.length; - if ( onDropRef.current ) { - onDropRef.current( event ); + if ( _onDrop ) { + onDropEvent( event ); } maybeDragEnd( event ); @@ -209,12 +183,12 @@ export default function useDropZone( { ownerDocument.removeEventListener( 'dragend', maybeDragEnd ); ownerDocument.removeEventListener( 'mousemove', maybeDragEnd ); - if ( onDragEndRef.current ) { - onDragEndRef.current( event ); + if ( _onDragEnd ) { + onDragEndEvent( event ); } } - element.dataset.isDropZone = 'true'; + element.setAttribute( 'data-is-drop-zone', 'true' ); element.addEventListener( 'drop', onDrop ); element.addEventListener( 'dragenter', onDragEnter ); element.addEventListener( 'dragover', onDragOver ); @@ -224,7 +198,7 @@ export default function useDropZone( { ownerDocument.addEventListener( 'dragenter', maybeDragStart ); return () => { - delete element.dataset.isDropZone; + element.removeAttribute( 'data-is-drop-zone' ); element.removeEventListener( 'drop', onDrop ); element.removeEventListener( 'dragenter', onDragEnter ); element.removeEventListener( 'dragover', onDragOver ); From b5cd6e99939c0b3512a8d694a5c91b3393b14809 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 29 Oct 2024 07:33:49 +0400 Subject: [PATCH 1374/1908] Block Editor: Fix React Complier error for Duotone (#66492) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/block-editor/src/hooks/duotone.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index dbd47831c42668..246e4fde7d8ba8 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -302,12 +302,12 @@ function useDuotoneStyles( { // `inline-block` is used instead of `none` to ensure that scroll // position is not affected, as `none` results in the editor // scrolling to the top of the block. - blockElement.style.display = 'inline-block'; + blockElement.style.setProperty( 'display', 'inline-block' ); // Simply accessing el.offsetHeight flushes layout and style changes // in WebKit without having to wait for setTimeout. // eslint-disable-next-line no-unused-expressions blockElement.offsetHeight; - blockElement.style.display = display; + blockElement.style.setProperty( 'display', display ); } // `colors` must be a dependency so this effect runs when the colors // change in Safari. From ffba007d6fbda637f374d678b550de03879d593f Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 29 Oct 2024 07:34:10 +0400 Subject: [PATCH 1375/1908] Block Editor: Fix React Complier error for 'useEventListeners' (#66495) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/rich-text/event-listeners/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/rich-text/event-listeners/index.js b/packages/block-editor/src/components/rich-text/event-listeners/index.js index 46e721dfe5cf7c..4ec67d8f30af97 100644 --- a/packages/block-editor/src/components/rich-text/event-listeners/index.js +++ b/packages/block-editor/src/components/rich-text/event-listeners/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { useMemo, useRef } from '@wordpress/element'; +import { useMemo, useRef, useInsertionEffect } from '@wordpress/element'; import { useRefEffect } from '@wordpress/compose'; /** @@ -35,7 +35,9 @@ const allEventListeners = [ export function useEventListeners( props ) { const propsRef = useRef( props ); - propsRef.current = props; + useInsertionEffect( () => { + propsRef.current = props; + } ); const refEffects = useMemo( () => allEventListeners.map( ( refEffect ) => refEffect( propsRef ) ), [ propsRef ] From ba17e5960231c179d8241842a487ca3835c7101f Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 29 Oct 2024 07:34:31 +0400 Subject: [PATCH 1376/1908] Components: Fix React Compiler error for 'useAutocomplete' (#66496) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/src/autocomplete/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/components/src/autocomplete/index.tsx b/packages/components/src/autocomplete/index.tsx index f3278a46015c3c..7a75be8eca5c84 100644 --- a/packages/components/src/autocomplete/index.tsx +++ b/packages/components/src/autocomplete/index.tsx @@ -97,7 +97,7 @@ export function useAutocomplete( { ( ( props: AutocompleterUIProps ) => JSX.Element | null ) | null >( null ); - const backspacing = useRef( false ); + const backspacingRef = useRef( false ); function insertCompletion( replacement: React.ReactNode ) { if ( autocompleter === null ) { @@ -177,7 +177,7 @@ export function useAutocomplete( { } function handleKeyDown( event: KeyboardEvent ) { - backspacing.current = event.key === 'Backspace'; + backspacingRef.current = event.key === 'Backspace'; if ( ! autocompleter ) { return; @@ -323,7 +323,7 @@ export function useAutocomplete( { // Ex: "Some text @marcelo sekkkk" <--- "kkkk" caused a mismatch, but // if the user presses backspace here, it will show the completion popup again. const matchingWhileBackspacing = - backspacing.current && wordsFromTrigger.length <= 3; + backspacingRef.current && wordsFromTrigger.length <= 3; if ( mismatch && ! ( matchingWhileBackspacing || hasOneTriggerWord ) ) { if ( autocompleter ) { From f760da018679eb891b3544a4f520ea87093e3458 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Tue, 29 Oct 2024 08:08:28 +0200 Subject: [PATCH 1377/1908] Site editor: Fix save shortcut (#66423) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../components/keyboard-shortcuts/global.js | 51 -------------- .../components/keyboard-shortcuts/register.js | 27 -------- .../edit-site/src/components/layout/index.js | 6 +- .../save-keyboard-shortcut/index.js | 69 +++++++++++++++++++ 4 files changed, 71 insertions(+), 82 deletions(-) delete mode 100644 packages/edit-site/src/components/keyboard-shortcuts/global.js delete mode 100644 packages/edit-site/src/components/keyboard-shortcuts/register.js create mode 100644 packages/edit-site/src/components/save-keyboard-shortcut/index.js diff --git a/packages/edit-site/src/components/keyboard-shortcuts/global.js b/packages/edit-site/src/components/keyboard-shortcuts/global.js deleted file mode 100644 index 8ab9723e42ea65..00000000000000 --- a/packages/edit-site/src/components/keyboard-shortcuts/global.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * WordPress dependencies - */ -import { useShortcut } from '@wordpress/keyboard-shortcuts'; -import { useDispatch, useSelect } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; -import { store as editorStore } from '@wordpress/editor'; -import { privateApis as routerPrivateApis } from '@wordpress/router'; - -/** - * Internal dependencies - */ -import { store as editSiteStore } from '../../store'; -import { unlock } from '../../lock-unlock'; - -const { useHistory } = unlock( routerPrivateApis ); - -function KeyboardShortcutsGlobal() { - const { __experimentalGetDirtyEntityRecords, isSavingEntityRecord } = - useSelect( coreStore ); - const { hasNonPostEntityChanges } = useSelect( editorStore ); - const { setIsSaveViewOpened } = useDispatch( editSiteStore ); - const history = useHistory(); - - useShortcut( 'core/edit-site/save', ( event ) => { - event.preventDefault(); - - const dirtyEntityRecords = __experimentalGetDirtyEntityRecords(); - const hasDirtyEntities = !! dirtyEntityRecords.length; - const isSaving = dirtyEntityRecords.some( ( record ) => - isSavingEntityRecord( record.kind, record.name, record.key ) - ); - const _hasNonPostEntityChanges = hasNonPostEntityChanges(); - const isViewMode = - history.getLocationWithParams().params.canvas === 'view'; - if ( - ( ! hasDirtyEntities || ! _hasNonPostEntityChanges || isSaving ) && - ! isViewMode - ) { - return; - } - // At this point, we know that there are dirty entities, other than - // the edited post, and we're not in the process of saving, so open - // save view. - setIsSaveViewOpened( true ); - } ); - - return null; -} - -export default KeyboardShortcutsGlobal; diff --git a/packages/edit-site/src/components/keyboard-shortcuts/register.js b/packages/edit-site/src/components/keyboard-shortcuts/register.js deleted file mode 100644 index 8e491ab61c36f7..00000000000000 --- a/packages/edit-site/src/components/keyboard-shortcuts/register.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * WordPress dependencies - */ -import { useEffect } from '@wordpress/element'; -import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts'; -import { useDispatch } from '@wordpress/data'; -import { __ } from '@wordpress/i18n'; - -function KeyboardShortcutsRegister() { - // Registering the shortcuts. - const { registerShortcut } = useDispatch( keyboardShortcutsStore ); - useEffect( () => { - registerShortcut( { - name: 'core/edit-site/save', - category: 'global', - description: __( 'Save your changes.' ), - keyCombination: { - modifier: 'primary', - character: 's', - }, - } ); - }, [ registerShortcut ] ); - - return null; -} - -export default KeyboardShortcutsRegister; diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index 713b1f179b7adb..551d1448fde5c9 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -35,8 +35,7 @@ import ErrorBoundary from '../error-boundary'; import { default as SiteHub, SiteHubMobile } from '../site-hub'; import ResizableFrame from '../resizable-frame'; import { unlock } from '../../lock-unlock'; -import KeyboardShortcutsRegister from '../keyboard-shortcuts/register'; -import KeyboardShortcutsGlobal from '../keyboard-shortcuts/global'; +import SaveKeyboardShortcut from '../save-keyboard-shortcut'; import { useIsSiteEditorLoading } from './hooks'; import useMovingAnimation from './animation'; import SidebarContent from '../sidebar'; @@ -80,8 +79,7 @@ export default function Layout( { route } ) { return ( <> <CommandMenu /> - <KeyboardShortcutsRegister /> - <KeyboardShortcutsGlobal /> + { canvas === 'view' && <SaveKeyboardShortcut /> } <div { ...navigateRegionsProps } ref={ navigateRegionsProps.ref } diff --git a/packages/edit-site/src/components/save-keyboard-shortcut/index.js b/packages/edit-site/src/components/save-keyboard-shortcut/index.js new file mode 100644 index 00000000000000..a1dccbd2a6b483 --- /dev/null +++ b/packages/edit-site/src/components/save-keyboard-shortcut/index.js @@ -0,0 +1,69 @@ +/** + * WordPress dependencies + */ +import { useEffect } from '@wordpress/element'; +import { + useShortcut, + store as keyboardShortcutsStore, +} from '@wordpress/keyboard-shortcuts'; +import { __ } from '@wordpress/i18n'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { store as editorStore } from '@wordpress/editor'; + +/** + * Internal dependencies + */ +import { store as editSiteStore } from '../../store'; + +const shortcutName = 'core/edit-site/save'; + +/** + * Register the save keyboard shortcut in view mode. + * + * @return {null} Returns null. + */ +export default function SaveKeyboardShortcut() { + const { __experimentalGetDirtyEntityRecords, isSavingEntityRecord } = + useSelect( coreStore ); + const { hasNonPostEntityChanges, isPostSavingLocked } = + useSelect( editorStore ); + const { savePost } = useDispatch( editorStore ); + const { setIsSaveViewOpened } = useDispatch( editSiteStore ); + const { registerShortcut, unregisterShortcut } = useDispatch( + keyboardShortcutsStore + ); + useEffect( () => { + registerShortcut( { + name: shortcutName, + category: 'global', + description: __( 'Save your changes.' ), + keyCombination: { + modifier: 'primary', + character: 's', + }, + } ); + return () => { + unregisterShortcut( shortcutName ); + }; + }, [ registerShortcut, unregisterShortcut ] ); + + useShortcut( 'core/edit-site/save', ( event ) => { + event.preventDefault(); + const dirtyEntityRecords = __experimentalGetDirtyEntityRecords(); + const hasDirtyEntities = !! dirtyEntityRecords.length; + const isSaving = dirtyEntityRecords.some( ( record ) => + isSavingEntityRecord( record.kind, record.name, record.key ) + ); + if ( ! hasDirtyEntities || isSaving ) { + return; + } + if ( hasNonPostEntityChanges() ) { + setIsSaveViewOpened( true ); + } else if ( ! isPostSavingLocked() ) { + savePost(); + } + } ); + + return null; +} From 90fbc53e22925d7bec441b9eb4e61b96e2ebc451 Mon Sep 17 00:00:00 2001 From: Ryan Welcher <me@ryanwelcher.com> Date: Tue, 29 Oct 2024 04:30:30 -0400 Subject: [PATCH 1378/1908] Create block: Ensure $slug is replaced with passed slug (#66528) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add --targetDir flag to allow targeting a directory where to scaffold the plugin/files. * Not using the targetDir when in --no-plugin mode * Change the name of the flag to match others and update changelog. * WIP commit. * Add logic to generate the paths for the root and block files in one place. * Add a new parameter to allow passing the path once rather than generating it in the function. * Modify the other functions to use the generated paths. * Update the command description. * Update packages/create-block/CHANGELOG.md * Refactor the handling for the root directory * Improve the documentation for target dir * Reorder CLI options in the docs * Ensure that $slug is replaced. --------- Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> Co-authored-by: ryanwelcher <welcher@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/create-block/lib/output.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/create-block/lib/output.js b/packages/create-block/lib/output.js index 71d2e9ebe86e54..609a028aa8034e 100644 --- a/packages/create-block/lib/output.js +++ b/packages/create-block/lib/output.js @@ -18,7 +18,10 @@ const writeOutputTemplate = async ( inputFile, outputFile, view ) => { if ( renderedFile.trim().length ) { const outputFilePath = join( view.rootDirectory, outputFile ); await makeDir( dirname( outputFilePath ) ); - writeFile( outputFilePath, renderedFile ); + writeFile( + outputFilePath.replace( /\$slug/g, view.slug ), + renderedFile + ); } }; From 0da9f62e734e4d37fb4b4be25b3b8964c44a3487 Mon Sep 17 00:00:00 2001 From: Nick Galvez <nicholas.galvez@gmail.com> Date: Tue, 29 Oct 2024 02:02:20 -0700 Subject: [PATCH 1379/1908] WP Scripts: Add a `--root-folder` argument to the `plugin-zip` command (#61375) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Scripts: Add a --zip-root-folder argument to the plugin-zip command (#60481) * Scripts: Change the plugin-zip command to add a folder in the plugin zip file by default 1. The plugin-zip command will now create a root folder in the zip file matching the name of the plugin. This aligns with the documentation stating that "By default, it uses Plugin Handbook best practices to discover files." 2. `--zip-root-folder` argument from my previous commit is now named `--root-folder` 3. The --root-folder argument will allow specifying a custom folder, or no folder for backwards compatibility. Example usage: {{{ npm run plugin-zip --root-folder='foo' }}} Follow-up to [61375], [60481]. Props justlevine, gziolo. * Add CHANGELOG entry * Update CHANGELOG.md * Scripts: Modify plugin-zip to add no-root-folder and root-folder options Require an argument for root-folder. Add option no-root-folder to zip files without a root folder for backwards compatibility. Update documentation, and changelog. (#60481) * Scripts: adjust message for plugin-zip command Apply suggestions from code review. props: @gziolo Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> * Update packages/scripts/README.md Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> --------- Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl> Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Co-authored-by: nicolasgalvez <nickgalvez@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: justlevine <justlevine@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/scripts/CHANGELOG.md | 3 ++- packages/scripts/README.md | 8 +++++++ packages/scripts/scripts/plugin-zip.js | 29 +++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 8a1133a2e7ae22..e2279dbbd5b8aa 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -4,7 +4,8 @@ ### Enhancements -- Add BlueOak-1.0.0 the GPLv2-comatible licenses recognized by check-licenses ([#66139](https://github.com/WordPress/gutenberg/pull/66139)). +- Add BlueOak-1.0.0 the GPLv2-compatible licenses recognized by check-licenses ([#66139](https://github.com/WordPress/gutenberg/pull/66139)). +- Add an optional `--root-folder` argument to the `plugin-zip` command ([#61375](https://github.com/WordPress/gutenberg/pull/61375)). By default, the command will use the plugin's name as the root folder of the zip. If the change in the behavior impacted your workflow, you could pass `--no-root-folder` to remove the root folder. ### Internal diff --git a/packages/scripts/README.md b/packages/scripts/README.md index 46e1a1265662cf..f86a4c6091c408 100644 --- a/packages/scripts/README.md +++ b/packages/scripts/README.md @@ -378,6 +378,14 @@ In the case where the plugin author wants to customize the files included in the It reuses the same logic as `npm pack` command to create an npm package tarball. +This is how you create a custom root folder inside the zip file. + +- When updating a plugin, WordPress expects a folder in the root of the zip file which matches the plugin name. So be aware that this may affect the plugin update process. +- `--root-folder` - Add a custom root folder to the zip file. +- `npm run plugin-zip` - By default, unzipping your plugin's zip file will result in a folder with the same name as your plugin. +- `npm run plugin-zip --root-folder='custom-directory'` - Your plugin's zip file will be unzipped into a folder named `custom-directory`. +- `npm run plugin-zip --no-root-folder` - This will create a zip file that has no folder inside, your plugin files will be unzipped directly into the target directory. + ### `start` Transforms your code according the configuration provided so it’s ready for development. The script will automatically rebuild if you make changes to the code, and you will see the build errors in the console. diff --git a/packages/scripts/scripts/plugin-zip.js b/packages/scripts/scripts/plugin-zip.js index b7c2a4df485c27..75ef36a4edeadc 100644 --- a/packages/scripts/scripts/plugin-zip.js +++ b/packages/scripts/scripts/plugin-zip.js @@ -10,13 +10,16 @@ const { stdout } = require( 'process' ); /** * Internal dependencies */ -const { hasPackageProp, getPackageProp } = require( '../utils' ); +const { hasPackageProp, getPackageProp, getArgFromCLI } = require( '../utils' ); const name = getPackageProp( 'name' ); stdout.write( `Creating archive for \`${ name }\` plugin... 🎁\n\n` ); const zip = new AdmZip(); - +const zipRootFolderArg = getArgFromCLI( '--root-folder' ); +const noRootFolderArg = getArgFromCLI( '--no-root-folder' ); +let zipRootFolder = `${ name }/`; let files = []; + if ( hasPackageProp( 'files' ) ) { stdout.write( 'Using the `files` field from `package.json` to detect files:\n\n' @@ -47,10 +50,30 @@ if ( hasPackageProp( 'files' ) ) { ); } +if ( noRootFolderArg !== undefined ) { + zipRootFolder = ''; + stdout.write( ' Plugin files will be zipped without a root folder.\n\n' ); +} else if ( zipRootFolderArg !== undefined ) { + const trimmedZipRootFolderArg = + typeof zipRootFolderArg === 'string' ? zipRootFolderArg.trim() : null; + if ( trimmedZipRootFolderArg === null ) { + stdout.write( + 'Unable to create zip package: please provide a `--root-folder` name or use `--no-root-folder.`\n\n' + ); + process.exit( 1 ); + } + zipRootFolder = `${ trimmedZipRootFolderArg }/`; + stdout.write( + ` Adding the provided folder \`${ zipRootFolder }\` to the root of the package.\n\n` + ); +} files.forEach( ( file ) => { stdout.write( ` Adding \`${ file }\`.\n` ); const zipDirectory = dirname( file ); - zip.addLocalFile( file, zipDirectory !== '.' ? zipDirectory : '' ); + zip.addLocalFile( + file, + zipRootFolder + ( zipDirectory !== '.' ? zipDirectory : '' ) + ); } ); zip.writeZip( `./${ name }.zip` ); From f73c3ad19609074adcf1eb4f53c67c90754b22db Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:41:47 +0530 Subject: [PATCH 1380/1908] ImageSizeControls: Replace ButtonGroup with ToggleGroupControl (#65386) Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- .../components/image-size-control/index.js | 117 +++++++++++------- .../image-size-control/test/index.js | 68 +--------- 2 files changed, 79 insertions(+), 106 deletions(-) diff --git a/packages/block-editor/src/components/image-size-control/index.js b/packages/block-editor/src/components/image-size-control/index.js index 7a333e98f795a1..b5bb705ab101c1 100644 --- a/packages/block-editor/src/components/image-size-control/index.js +++ b/packages/block-editor/src/components/image-size-control/index.js @@ -2,11 +2,11 @@ * WordPress dependencies */ import { - Button, - ButtonGroup, SelectControl, __experimentalNumberControl as NumberControl, __experimentalHStack as HStack, + __experimentalToggleGroupControl as ToggleGroupControl, + __experimentalToggleGroupControlOption as ToggleGroupControlOption, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; @@ -18,6 +18,25 @@ import useDimensionHandler from './use-dimension-handler'; const IMAGE_SIZE_PRESETS = [ 25, 50, 75, 100 ]; const noop = () => {}; +/** + * Get scaled width and height for the given scale. + * + * @param {number} scale The scale to get the scaled width and height for. + * @param {number} imageWidth The image width. + * @param {number} imageHeight The image height. + * + * @return {Object} The scaled width and height. + */ +function getScaledWidthAndHeight( scale, imageWidth, imageHeight ) { + const scaledWidth = Math.round( imageWidth * ( scale / 100 ) ); + const scaledHeight = Math.round( imageHeight * ( scale / 100 ) ); + + return { + scaledWidth, + scaledHeight, + }; +} + export default function ImageSizeControl( { imageSizeHelp, imageWidth, @@ -33,6 +52,40 @@ export default function ImageSizeControl( { const { currentHeight, currentWidth, updateDimension, updateDimensions } = useDimensionHandler( height, width, imageHeight, imageWidth, onChange ); + /** + * Updates the dimensions for the given scale. + * Handler for toggle group control change. + * + * @param {number} scale The scale to update the dimensions for. + */ + const handleUpdateDimensions = ( scale ) => { + if ( undefined === scale ) { + updateDimensions(); + return; + } + + const { scaledWidth, scaledHeight } = getScaledWidthAndHeight( + scale, + imageWidth, + imageHeight + ); + + updateDimensions( scaledHeight, scaledWidth ); + }; + + /** + * Add the stored image preset value to toggle group control. + */ + const selectedValue = IMAGE_SIZE_PRESETS.find( ( scale ) => { + const { scaledWidth, scaledHeight } = getScaledWidthAndHeight( + scale, + imageWidth, + imageHeight + ); + + return currentWidth === scaledWidth && currentHeight === scaledHeight; + } ); + return ( <> { imageSizeOptions && imageSizeOptions.length > 0 && ( @@ -70,47 +123,25 @@ export default function ImageSizeControl( { size="__unstable-large" /> </HStack> - <HStack> - <ButtonGroup aria-label={ __( 'Image size presets' ) }> - { IMAGE_SIZE_PRESETS.map( ( scale ) => { - const scaledWidth = Math.round( - imageWidth * ( scale / 100 ) - ); - const scaledHeight = Math.round( - imageHeight * ( scale / 100 ) - ); - - const isCurrent = - currentWidth === scaledWidth && - currentHeight === scaledHeight; - - return ( - <Button - key={ scale } - size="small" - variant={ - isCurrent ? 'primary' : undefined - } - isPressed={ isCurrent } - onClick={ () => - updateDimensions( - scaledHeight, - scaledWidth - ) - } - > - { scale }% - </Button> - ); - } ) } - </ButtonGroup> - <Button - size="small" - onClick={ () => updateDimensions() } - > - { __( 'Reset' ) } - </Button> - </HStack> + <ToggleGroupControl + label={ __( 'Image size presets' ) } + hideLabelFromVision + onChange={ handleUpdateDimensions } + value={ selectedValue } + isBlock + __next40pxDefaultSize + __nextHasNoMarginBottom + > + { IMAGE_SIZE_PRESETS.map( ( scale ) => { + return ( + <ToggleGroupControlOption + key={ scale } + value={ scale } + label={ `${ scale }%` } + /> + ); + } ) } + </ToggleGroupControl> </div> ) } </> diff --git a/packages/block-editor/src/components/image-size-control/test/index.js b/packages/block-editor/src/components/image-size-control/test/index.js index c36be27971e694..70d94e78e70c2e 100644 --- a/packages/block-editor/src/components/image-size-control/test/index.js +++ b/packages/block-editor/src/components/image-size-control/test/index.js @@ -221,47 +221,8 @@ describe( 'ImageSizeControl', () => { } ); } ); - describe( 'reset button', () => { - it( 'resets both height and width to default values', async () => { - const user = userEvent.setup(); - - render( - <ImageSizeControl - imageHeight="100" - imageWidth="200" - height="300" - width="400" - onChange={ mockOnChange } - /> - ); - - const heightInput = screen.getByRole( 'spinbutton', { - name: 'Height', - } ); - const widthInput = screen.getByRole( 'spinbutton', { - name: 'Width', - } ); - - // The initial dimension values display first. - expect( heightInput ).toHaveValue( 300 ); - expect( widthInput ).toHaveValue( 400 ); - - await user.click( screen.getByRole( 'button', { name: 'Reset' } ) ); - - // Both attributes are set to undefined to clear custom values. - expect( mockOnChange ).toHaveBeenLastCalledWith( { - height: undefined, - width: undefined, - } ); - - // The inputs display the default values once more. - expect( heightInput ).toHaveValue( 100 ); - expect( widthInput ).toHaveValue( 200 ); - } ); - } ); - describe( 'image size percentage presets', () => { - it( 'updates height and width attributes on selection', async () => { + it( 'updates height and width on selection', async () => { const user = userEvent.setup(); render( @@ -272,44 +233,25 @@ describe( 'ImageSizeControl', () => { /> ); - const button = screen.getByRole( 'button', { + const button = screen.getByRole( 'radio', { name: '50%', - pressed: false, + checked: false, } ); await user.click( button ); - expect( button ).toHaveClass( 'is-pressed' ); + expect( button ).toBeChecked(); // Both attributes are set to the rounded scaled value. expect( mockOnChange ).toHaveBeenLastCalledWith( { height: 50, width: 101, } ); - } ); - - it( 'updates height and width inputs on selection', async () => { - const user = userEvent.setup(); - - render( - <ImageSizeControl - imageHeight="100" - imageWidth="201" - onChange={ mockOnChange } - /> - ); - - const button = screen.getByRole( 'button', { - name: '50%', - pressed: false, - } ); - - await user.click( button ); - // Both attributes are set to the rounded scaled value. expect( screen.getByRole( 'spinbutton', { name: 'Height' } ) ).toHaveValue( 50 ); + expect( screen.getByRole( 'spinbutton', { name: 'Width' } ) ).toHaveValue( 101 ); From 471900bb0e626f381d71b06bc03c210873a7d218 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 29 Oct 2024 18:28:05 +0900 Subject: [PATCH 1381/1908] Fix undo/redo Button size in Storybook playground (#66538) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- storybook/stories/playground/with-undo-redo/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/storybook/stories/playground/with-undo-redo/index.js b/storybook/stories/playground/with-undo-redo/index.js index 77e059247a0515..b5a6067cad24b7 100644 --- a/storybook/stories/playground/with-undo-redo/index.js +++ b/storybook/stories/playground/with-undo-redo/index.js @@ -52,6 +52,7 @@ export default function EditorWithUndoRedo() { accessibleWhenDisabled icon={ undoIcon } label="Undo" + size="compact" /> <Button onClick={ redo } @@ -59,6 +60,7 @@ export default function EditorWithUndoRedo() { accessibleWhenDisabled icon={ redoIcon } label="Redo" + size="compact" /> <BlockToolbar hideDragHandle /> </div> From 648c458ac16188ca505bf9b04a2388b941fe9c62 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Tue, 29 Oct 2024 10:34:01 +0100 Subject: [PATCH 1382/1908] Import only the actually used PostCSS exports (#66379) --- packages/block-editor/src/utils/transform-styles/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/utils/transform-styles/index.js b/packages/block-editor/src/utils/transform-styles/index.js index 936ebb016fa1b3..170f770d63d5d4 100644 --- a/packages/block-editor/src/utils/transform-styles/index.js +++ b/packages/block-editor/src/utils/transform-styles/index.js @@ -2,7 +2,8 @@ * External dependencies */ import * as parsel from 'parsel-js'; -import postcss, { CssSyntaxError } from 'postcss'; +import Processor from 'postcss/lib/processor'; +import CssSyntaxError from 'postcss/lib/css-syntax-error'; import prefixSelector from 'postcss-prefix-selector'; import rebaseUrl from 'postcss-urlrebase'; @@ -100,7 +101,7 @@ function transformStyle( wrapperSelector, ]; - return postcss( + return new Processor( [ wrapperSelector && prefixSelector( { From 7ca9567e85350789e47ed41e71a6fc8af3fc1da8 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Tue, 29 Oct 2024 16:42:03 +0530 Subject: [PATCH 1383/1908] Fix: Improve the DocumentBar post type label for the Homepage and Posts Page cases (#66355) * Add the correct consistent label on document bar * Add the utililty custom hook to get the page badge based on current view * Change the variable name to be more precise * Update the document bar label display logic * Address the PR feedbacks Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: Vrishabhsk <vrishabhsk@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../src/components/document-bar/index.js | 16 +++++++- .../src/components/post-card-panel/index.js | 25 ++++------- packages/editor/src/utils/pageTypeBadge.js | 41 +++++++++++++++++++ 3 files changed, 63 insertions(+), 19 deletions(-) create mode 100644 packages/editor/src/utils/pageTypeBadge.js diff --git a/packages/editor/src/components/document-bar/index.js b/packages/editor/src/components/document-bar/index.js index 3c522189a2632f..031262f52f7268 100644 --- a/packages/editor/src/components/document-bar/index.js +++ b/packages/editor/src/components/document-bar/index.js @@ -28,6 +28,7 @@ import { decodeEntities } from '@wordpress/html-entities'; */ import { TEMPLATE_POST_TYPES } from '../../store/constants'; import { store as editorStore } from '../../store'; +import usePageTypeBadge from '../../utils/pageTypeBadge'; /** @typedef {import("@wordpress/components").IconType} IconType */ @@ -107,6 +108,8 @@ export default function DocumentBar( props ) { const title = props.title || entityTitle; const icon = props.icon; + const pageTypeBadge = usePageTypeBadge(); + const mountedRef = useRef( false ); useEffect( () => { mountedRef.current = true; @@ -180,11 +183,20 @@ export default function DocumentBar( props ) { ? decodeEntities( title ) : __( 'No title' ) } </span> - { postTypeLabel && ! props.title && ( + { pageTypeBadge && ( <span className="editor-document-bar__post-type-label"> - { '· ' + decodeEntities( postTypeLabel ) } + { `· ${ pageTypeBadge }` } </span> ) } + { postTypeLabel && + ! props.title && + ! pageTypeBadge && ( + <span className="editor-document-bar__post-type-label"> + { `· ${ decodeEntities( + postTypeLabel + ) }` } + </span> + ) } </Text> </motion.div> <span className="editor-document-bar__shortcut"> diff --git a/packages/editor/src/components/post-card-panel/index.js b/packages/editor/src/components/post-card-panel/index.js index 1365659f708147..410b8cfd4447d9 100644 --- a/packages/editor/src/components/post-card-panel/index.js +++ b/packages/editor/src/components/post-card-panel/index.js @@ -21,22 +21,17 @@ import { } from '../../store/constants'; import { unlock } from '../../lock-unlock'; import PostActions from '../post-actions'; +import usePageTypeBadge from '../../utils/pageTypeBadge'; export default function PostCardPanel( { postType, postId, onActionPerformed, } ) { - const { isFrontPage, isPostsPage, title, icon } = useSelect( + const { title, icon } = useSelect( ( select ) => { const { __experimentalGetTemplateInfo } = select( editorStore ); - const { canUser, getEditedEntityRecord } = select( coreStore ); - const siteSettings = canUser( 'read', { - kind: 'root', - name: 'site', - } ) - ? getEditedEntityRecord( 'root', 'site' ) - : undefined; + const { getEditedEntityRecord } = select( coreStore ); const _record = getEditedEntityRecord( 'postType', postType, @@ -51,12 +46,13 @@ export default function PostCardPanel( { icon: unlock( select( editorStore ) ).getPostIcon( postType, { area: _record?.area, } ), - isFrontPage: siteSettings?.page_on_front === postId, - isPostsPage: siteSettings?.page_for_posts === postId, }; }, [ postId, postType ] ); + + const pageTypeBadge = usePageTypeBadge(); + return ( <div className="editor-post-card-panel"> <HStack @@ -74,14 +70,9 @@ export default function PostCardPanel( { lineHeight="20px" > { title ? decodeEntities( title ) : __( 'No title' ) } - { isFrontPage && ( - <span className="editor-post-card-panel__title-badge"> - { __( 'Homepage' ) } - </span> - ) } - { isPostsPage && ( + { pageTypeBadge && ( <span className="editor-post-card-panel__title-badge"> - { __( 'Posts Page' ) } + { pageTypeBadge } </span> ) } </Text> diff --git a/packages/editor/src/utils/pageTypeBadge.js b/packages/editor/src/utils/pageTypeBadge.js new file mode 100644 index 00000000000000..321b9caa17769e --- /dev/null +++ b/packages/editor/src/utils/pageTypeBadge.js @@ -0,0 +1,41 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ +import { store as editorStore } from '../store'; + +/** + * Custom hook to get the page type badge for the current post on edit site view. + */ +export default function usePageTypeBadge() { + const { isFrontPage, isPostsPage } = useSelect( ( select ) => { + const { getCurrentPostId } = select( editorStore ); + const { canUser, getEditedEntityRecord } = select( coreStore ); + const postId = getCurrentPostId(); + const siteSettings = canUser( 'read', { + kind: 'root', + name: 'site', + } ) + ? getEditedEntityRecord( 'root', 'site' ) + : undefined; + + return { + isFrontPage: siteSettings?.page_on_front === postId, + isPostsPage: siteSettings?.page_for_posts === postId, + }; + } ); + + if ( isFrontPage ) { + return __( 'Homepage' ); + } else if ( isPostsPage ) { + return __( 'Posts Page' ); + } + + return false; +} From 7c64d0ae2899e4ced722fe660bf40b492e3163bd Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Tue, 29 Oct 2024 12:24:55 +0100 Subject: [PATCH 1384/1908] Remove most of the occurrences of the verb toggle. (#66371) * Remove most of the occurrences of the verb toggle. * Remove term panel. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> --- .../block-full-height-alignment-control/index.js | 2 +- packages/block-library/src/cover/test/edit.js | 4 +--- packages/block-library/src/paragraph/edit.js | 2 +- packages/block-library/src/search/edit.js | 2 +- .../data/src/components/use-select/test/index.js | 4 ++-- .../src/components/dataviews-filters/index.tsx | 4 ++-- .../src/components/keyboard-shortcuts/index.js | 2 +- .../edit-site/src/components/post-list/index.js | 2 +- packages/editor/src/components/commands/index.js | 14 ++++++++------ .../register-shortcuts.js | 6 +++--- .../src/components/post-sticky/test/index.js | 12 ++++++------ packages/editor/src/store/actions.js | 4 ++-- 12 files changed, 29 insertions(+), 29 deletions(-) diff --git a/packages/block-editor/src/components/block-full-height-alignment-control/index.js b/packages/block-editor/src/components/block-full-height-alignment-control/index.js index 98384414ae4ba4..00d908ce8b7e79 100644 --- a/packages/block-editor/src/components/block-full-height-alignment-control/index.js +++ b/packages/block-editor/src/components/block-full-height-alignment-control/index.js @@ -7,7 +7,7 @@ import { fullscreen } from '@wordpress/icons'; function BlockFullHeightAlignmentControl( { isActive, - label = __( 'Toggle full height' ), + label = __( 'Full height' ), onToggle, isDisabled, } ) { diff --git a/packages/block-library/src/cover/test/edit.js b/packages/block-library/src/cover/test/edit.js index 348cd88edfd962..5c1a5b5e13e67d 100644 --- a/packages/block-library/src/cover/test/edit.js +++ b/packages/block-library/src/cover/test/edit.js @@ -119,9 +119,7 @@ describe( 'Cover block', () => { 'min-height: 100vh;' ); - await userEvent.click( - screen.getByLabelText( 'Toggle full height' ) - ); + await userEvent.click( screen.getByLabelText( 'Full height' ) ); expect( screen.getByLabelText( 'Block: Cover' ) ).toHaveStyle( 'min-height: 100vh;' diff --git a/packages/block-library/src/paragraph/edit.js b/packages/block-library/src/paragraph/edit.js index 7edfbbc6252ae6..b7f4283d4ec671 100644 --- a/packages/block-library/src/paragraph/edit.js +++ b/packages/block-library/src/paragraph/edit.js @@ -66,7 +66,7 @@ function DropCapControl( { clientId, attributes, setAttributes } ) { } else if ( dropCap ) { helpText = __( 'Showing large initial letter.' ); } else { - helpText = __( 'Toggle to show a large initial letter.' ); + helpText = __( 'Show a large initial letter.' ); } return ( diff --git a/packages/block-library/src/search/edit.js b/packages/block-library/src/search/edit.js index b68914893c0e84..f193c04e2493aa 100644 --- a/packages/block-library/src/search/edit.js +++ b/packages/block-library/src/search/edit.js @@ -376,7 +376,7 @@ export default function SearchEdit( { <BlockControls> <ToolbarGroup> <ToolbarButton - title={ __( 'Toggle search label' ) } + title={ __( 'Show search label' ) } icon={ toggleLabel } onClick={ () => { setAttributes( { diff --git a/packages/data/src/components/use-select/test/index.js b/packages/data/src/components/use-select/test/index.js index 6cd4b1bf70f690..3320f7d4638a59 100644 --- a/packages/data/src/components/use-select/test/index.js +++ b/packages/data/src/components/use-select/test/index.js @@ -676,7 +676,7 @@ describe( 'useSelect', () => { return ( <> <div role="status">{ state }</div> - <button onClick={ toggle }>Toggle</button> + <button onClick={ toggle }>Open</button> </> ); } ); @@ -693,7 +693,7 @@ describe( 'useSelect', () => { 'count2:0' ); - act( () => screen.getByText( 'Toggle' ).click() ); + act( () => screen.getByText( 'Open' ).click() ); expect( selectCount1 ).toHaveBeenCalledTimes( 1 ); expect( selectCount2 ).toHaveBeenCalledTimes( 1 ); diff --git a/packages/dataviews/src/components/dataviews-filters/index.tsx b/packages/dataviews/src/components/dataviews-filters/index.tsx index 96e7f5b5d7b9d9..6a8545a021350e 100644 --- a/packages/dataviews/src/components/dataviews-filters/index.tsx +++ b/packages/dataviews/src/components/dataviews-filters/index.tsx @@ -10,7 +10,7 @@ import { } from '@wordpress/element'; import { __experimentalHStack as HStack, Button } from '@wordpress/components'; import { funnel } from '@wordpress/icons'; -import { __ } from '@wordpress/i18n'; +import { __, _x } from '@wordpress/i18n'; /** * Internal dependencies @@ -124,7 +124,7 @@ export function FilterVisibilityToggle( { className="dataviews-filters__visibility-toggle" size="compact" icon={ funnel } - label={ __( 'Toggle filter display' ) } + label={ _x( 'Filter', 'verb' ) } onClick={ () => { if ( ! isShowingFilter ) { setOpenedFilter( null ); diff --git a/packages/edit-post/src/components/keyboard-shortcuts/index.js b/packages/edit-post/src/components/keyboard-shortcuts/index.js index 108671a8f66321..3d1bc9d3350da3 100644 --- a/packages/edit-post/src/components/keyboard-shortcuts/index.js +++ b/packages/edit-post/src/components/keyboard-shortcuts/index.js @@ -22,7 +22,7 @@ function KeyboardShortcuts() { registerShortcut( { name: 'core/edit-post/toggle-fullscreen', category: 'global', - description: __( 'Toggle fullscreen mode.' ), + description: __( 'Enable or disable fullscreen mode.' ), keyCombination: { modifier: 'secondary', character: 'f', diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 3efe3361f3c51e..4985af3050bd8d 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -412,7 +412,7 @@ export default function PostList( { postType } ) { size="compact" isPressed={ quickEdit } icon={ drawerRight } - label={ __( 'Details panel' ) } + label={ __( 'Details' ) } onClick={ () => { history.push( { ...location.params, diff --git a/packages/editor/src/components/commands/index.js b/packages/editor/src/components/commands/index.js index a9c726f660b22e..8eb88567bd0a3f 100644 --- a/packages/editor/src/components/commands/index.js +++ b/packages/editor/src/components/commands/index.js @@ -98,8 +98,8 @@ function useEditorCommandLoader() { commands.push( { name: 'core/toggle-distraction-free', label: isDistractionFree - ? __( 'Exit Distraction Free' ) - : __( 'Enter Distraction Free' ), + ? __( 'Exit Distraction free' ) + : __( 'Enter Distraction free' ), callback: ( { close } ) => { toggleDistractionFree(); close(); @@ -117,7 +117,9 @@ function useEditorCommandLoader() { commands.push( { name: 'core/toggle-spotlight-mode', - label: __( 'Toggle spotlight' ), + label: isFocusMode + ? __( 'Exit Spotlight mode' ) + : __( 'Enter Spotlight mode' ), callback: ( { close } ) => { toggle( 'core', 'focusMode' ); close(); @@ -160,7 +162,7 @@ function useEditorCommandLoader() { commands.push( { name: 'core/toggle-top-toolbar', - label: __( 'Toggle top toolbar' ), + label: __( 'Top toolbar' ), callback: ( { close } ) => { toggle( 'core', 'fixedToolbar' ); if ( isDistractionFree ) { @@ -224,7 +226,7 @@ function useEditorCommandLoader() { commands.push( { name: 'core/open-settings-sidebar', - label: __( 'Toggle settings sidebar' ), + label: __( 'Show or hide the Settings panel.' ), icon: isRTL() ? drawerLeft : drawerRight, callback: ( { close } ) => { const activeSidebar = getActiveComplementaryArea( 'core' ); @@ -239,7 +241,7 @@ function useEditorCommandLoader() { commands.push( { name: 'core/open-block-inspector', - label: __( 'Toggle block inspector' ), + label: __( 'Show or hide the Block settings panel' ), icon: blockDefault, callback: ( { close } ) => { const activeSidebar = getActiveComplementaryArea( 'core' ); diff --git a/packages/editor/src/components/global-keyboard-shortcuts/register-shortcuts.js b/packages/editor/src/components/global-keyboard-shortcuts/register-shortcuts.js index 26a07166c106c4..9c371ad8f643a3 100644 --- a/packages/editor/src/components/global-keyboard-shortcuts/register-shortcuts.js +++ b/packages/editor/src/components/global-keyboard-shortcuts/register-shortcuts.js @@ -72,7 +72,7 @@ function EditorKeyboardShortcutsRegister() { registerShortcut( { name: 'core/editor/toggle-list-view', category: 'global', - description: __( 'Open the List View.' ), + description: __( 'Show or hide the List View.' ), keyCombination: { modifier: 'access', character: 'o', @@ -82,7 +82,7 @@ function EditorKeyboardShortcutsRegister() { registerShortcut( { name: 'core/editor/toggle-distraction-free', category: 'global', - description: __( 'Toggle distraction free mode.' ), + description: __( 'Enter or exit distraction free mode.' ), keyCombination: { modifier: 'primaryShift', character: '\\', @@ -92,7 +92,7 @@ function EditorKeyboardShortcutsRegister() { registerShortcut( { name: 'core/editor/toggle-sidebar', category: 'global', - description: __( 'Show or hide the Settings sidebar.' ), + description: __( 'Show or hide the Settings panel.' ), keyCombination: { modifier: 'primaryShift', character: ',', diff --git a/packages/editor/src/components/post-sticky/test/index.js b/packages/editor/src/components/post-sticky/test/index.js index ff567cfe2598eb..b6dfd18a0ef828 100644 --- a/packages/editor/src/components/post-sticky/test/index.js +++ b/packages/editor/src/components/post-sticky/test/index.js @@ -35,23 +35,23 @@ function setupUseSelectMock( { hasStickyAction, postType } ) { describe( 'PostSticky', () => { it( 'should not render anything if the post type is not "post"', () => { setupUseSelectMock( { hasStickyAction: true, postType: 'page' } ); - render( <PostStickyCheck>Can Toggle Sticky</PostStickyCheck> ); + render( <PostStickyCheck>Can Show Sticky</PostStickyCheck> ); expect( - screen.queryByText( 'Can Toggle Sticky' ) + screen.queryByText( 'Can Show Sticky' ) ).not.toBeInTheDocument(); } ); it( "should not render anything if post doesn't support stickying", () => { setupUseSelectMock( { hasStickyAction: false, postType: 'post' } ); - render( <PostStickyCheck>Can Toggle Sticky</PostStickyCheck> ); + render( <PostStickyCheck>Can Show Sticky</PostStickyCheck> ); expect( - screen.queryByText( 'Can Toggle Sticky' ) + screen.queryByText( 'Can Show Sticky' ) ).not.toBeInTheDocument(); } ); it( 'should render if the post supports stickying', () => { setupUseSelectMock( { hasStickyAction: true, postType: 'post' } ); - render( <PostStickyCheck>Can Toggle Sticky</PostStickyCheck> ); - expect( screen.getByText( 'Can Toggle Sticky' ) ).toBeVisible(); + render( <PostStickyCheck>Can Show Sticky</PostStickyCheck> ); + expect( screen.getByText( 'Can Show Sticky' ) ).toBeVisible(); } ); } ); diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index f28f5feeead179..cc2c23bcffcf7e 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -841,8 +841,8 @@ export const toggleDistractionFree = .dispatch( noticesStore ) .createInfoNotice( isDistractionFree - ? __( 'Distraction free off.' ) - : __( 'Distraction free on.' ), + ? __( 'Distraction free mode deactivated.' ) + : __( 'Distraction free mode activated.' ), { id: 'core/editor/distraction-free-mode/notice', type: 'snackbar', From 26123cd51f16a77c961a38052fb13535ceecf8b7 Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Tue, 29 Oct 2024 13:14:51 +0100 Subject: [PATCH 1385/1908] Rich text: remove empty file (#66553) --- packages/rich-text/src/remove-unregistered-formatting.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 packages/rich-text/src/remove-unregistered-formatting.js diff --git a/packages/rich-text/src/remove-unregistered-formatting.js b/packages/rich-text/src/remove-unregistered-formatting.js deleted file mode 100644 index e69de29bb2d1d6..00000000000000 From 7714bce8d9356707a020b5d7df84797832c423f8 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 29 Oct 2024 23:18:06 +0900 Subject: [PATCH 1386/1908] TabPanel: Add 40px size prop to tab Button (#66557) * TabPanel: Add 40px size prop to tab Button * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/tab-panel/index.tsx | 1 + packages/components/src/tab-panel/style.scss | 4 +--- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index ba0d68d5c12c09..45f99c71af58ac 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -30,6 +30,7 @@ ### Internal - ESLint: Stop disabling `react-hooks/exhaustive-deps` rule ([#66324](https://github.com/WordPress/gutenberg/pull/66324)). +- `TabPanel`: Add 40px size prop to tab Button ([#66557](https://github.com/WordPress/gutenberg/pull/66557)). ## 28.10.0 (2024-10-16) diff --git a/packages/components/src/tab-panel/index.tsx b/packages/components/src/tab-panel/index.tsx index f9db745b424260..be06b42fcd013f 100644 --- a/packages/components/src/tab-panel/index.tsx +++ b/packages/components/src/tab-panel/index.tsx @@ -220,6 +220,7 @@ const UnforwardedTabPanel = ( ) }-view` } render={ <Button + __next40pxDefaultSize icon={ tab.icon } label={ tab.icon && tab.title } showTooltip={ !! tab.icon } diff --git a/packages/components/src/tab-panel/style.scss b/packages/components/src/tab-panel/style.scss index 229b32c7477e87..b54f7af1bf4ded 100644 --- a/packages/components/src/tab-panel/style.scss +++ b/packages/components/src/tab-panel/style.scss @@ -7,12 +7,10 @@ } } -// This tab style CSS is duplicated verbatim in -// /packages/edit-post/src/components/sidebar/settings-header/style.scss .components-tab-panel__tabs-item { position: relative; border-radius: 0; - height: $grid-unit-60; + height: $grid-unit-60 !important; // https://github.com/WordPress/gutenberg/pull/65075#discussion_r1746282734 background: transparent; border: none; box-shadow: none; From 3a4cc107ac5c1eeb1c863f0e048cd92ef559bdd2 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Tue, 29 Oct 2024 17:05:48 +0100 Subject: [PATCH 1387/1908] `DropdownMenuV2`: rename to `Menu` (#66289) Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../block-editor/src/hooks/block-bindings.js | 28 +- packages/components/CHANGELOG.md | 1 + packages/components/src/menu/README.md | 68 +-- .../components/src/menu/checkbox-item.tsx | 28 +- packages/components/src/menu/context.tsx | 8 +- packages/components/src/menu/group-label.tsx | 16 +- packages/components/src/menu/group.tsx | 16 +- packages/components/src/menu/index.tsx | 135 +++-- .../components/src/menu/item-help-text.tsx | 10 +- packages/components/src/menu/item-label.tsx | 10 +- packages/components/src/menu/item.tsx | 26 +- packages/components/src/menu/radio-item.tsx | 28 +- packages/components/src/menu/separator.tsx | 18 +- .../src/menu/stories/index.story.tsx | 543 +++++++----------- packages/components/src/menu/styles.ts | 34 +- packages/components/src/menu/test/index.tsx | 370 +++++------- packages/components/src/menu/types.ts | 47 +- packages/components/src/private-apis.ts | 4 +- .../components/src/toolbar/toolbar/index.tsx | 3 + .../dataviews-filters/add-filter.tsx | 18 +- .../components/dataviews-filters/index.tsx | 4 +- .../dataviews-item-actions/index.tsx | 30 +- .../dataviews-view-config/index.tsx | 14 +- .../src/dataviews-layouts/list/index.tsx | 10 +- .../table/column-header-menu.tsx | 66 +-- .../global-styles/font-sizes/font-size.js | 26 +- .../global-styles/font-sizes/font-sizes.js | 16 +- .../global-styles/shadows-edit-panel.js | 14 +- .../src/components/post-actions/index.js | 19 +- 29 files changed, 704 insertions(+), 906 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 694c9c1c0bb3cc..615804a311c0fb 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -34,7 +34,7 @@ import { useBlockEditContext } from '../components/block-edit'; import { useBlockBindingsUtils } from '../utils/block-bindings'; import { store as blockEditorStore } from '../store'; -const { DropdownMenuV2 } = unlock( componentsPrivateApis ); +const { Menu } = unlock( componentsPrivateApis ); const EMPTY_OBJECT = {}; @@ -70,18 +70,18 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) { <> { Object.entries( fieldsList ).map( ( [ name, fields ], i ) => ( <Fragment key={ name }> - <DropdownMenuV2.Group> + <Menu.Group> { Object.keys( fieldsList ).length > 1 && ( - <DropdownMenuV2.GroupLabel> + <Menu.GroupLabel> { registeredSources[ name ].label } - </DropdownMenuV2.GroupLabel> + </Menu.GroupLabel> ) } { Object.entries( fields ) .filter( ( [ , args ] ) => args?.type === attributeType ) .map( ( [ key, args ] ) => ( - <DropdownMenuV2.RadioItem + <Menu.RadioItem key={ key } onChange={ () => updateBlockBindings( { @@ -95,17 +95,17 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) { value={ key } checked={ key === currentKey } > - <DropdownMenuV2.ItemLabel> + <Menu.ItemLabel> { args?.label } - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> + </Menu.ItemLabel> + <Menu.ItemHelpText> { args?.value } - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.RadioItem> + </Menu.ItemHelpText> + </Menu.RadioItem> ) ) } - </DropdownMenuV2.Group> + </Menu.Group> { i !== Object.keys( fieldsList ).length - 1 && ( - <DropdownMenuV2.Separator /> + <Menu.Separator /> ) } </Fragment> ) ) } @@ -175,7 +175,7 @@ function EditableBlockBindingsPanelItems( { } ); } } > - <DropdownMenuV2 + <Menu placement={ isMobile ? 'bottom-start' : 'left-start' } @@ -195,7 +195,7 @@ function EditableBlockBindingsPanelItems( { attribute={ attribute } binding={ binding } /> - </DropdownMenuV2> + </Menu> </ToolsPanelItem> ); } ) } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 45f99c71af58ac..9603d9656d5069 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -26,6 +26,7 @@ - `Tabs`: update indicator more reactively ([#66207](https://github.com/WordPress/gutenberg/pull/66207)). - `Tabs` and `TabPanel`: Fix arrow key navigation in RTL ([#66201](https://github.com/WordPress/gutenberg/pull/66201)). - `Tabs`: override tablist's tabindex only when necessary ([#66209](https://github.com/WordPress/gutenberg/pull/66209)). +- `DropdownMenuV2`: rename to `Menu` ([#66289](https://github.com/WordPress/gutenberg/pull/66289)). ### Internal diff --git a/packages/components/src/menu/README.md b/packages/components/src/menu/README.md index 771b5b74b24bf7..6732610c0c6cae 100644 --- a/packages/components/src/menu/README.md +++ b/packages/components/src/menu/README.md @@ -1,51 +1,51 @@ -# `DropdownMenuV2` +# `Menu` <div class="callout callout-alert"> This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. </div> -`DropdownMenuV2` displays a menu to the user (such as a set of actions or functions) triggered by a button. +`Menu` displays a menu to the user (such as a set of actions or functions). The menu is rendered in a popover (this pattern is also known as a "Dropdown menu"), which is triggered by a button. ## Design guidelines ### Usage -#### When to use a DropdownMenu +#### When to use a `Menu` -Use a DropdownMenu when you want users to: +Use a `Menu` when you want users to: - Choose an action or change a setting from a list, AND - Only see the available choices contextually. -`DropdownMenu` is a React component to render an expandable menu of buttons. It is similar in purpose to a `<select>` element, with the distinction that it does not maintain a value. Instead, each option behaves as an action button. +`Menu` is a React component to render an expandable menu of buttons. It is similar in purpose to a `<select>` element, with the distinction that it does not maintain a value. Instead, each option behaves as an action button. -If you need to display all the available options at all times, consider using a Toolbar instead. Use a `DropdownMenu` to display a list of actions after the user interacts with a button. +If you need to display all the available options at all times, consider using a Toolbar instead. Use a `Menu` to display a list of actions after the user interacts with a button. **Do** -Use a `DropdownMenu` to display a list of actions after the user interacts with an icon. +Use a `Menu` to display a list of actions after the user interacts with an icon. -**Don’t** use a `DropdownMenu` for important actions that should always be visible. Use a `Toolbar` instead. +**Don’t** use a `Menu` for important actions that should always be visible. Use a `Toolbar` instead. **Don’t** -Don’t use a `DropdownMenu` for frequently used actions. Use a `Toolbar` instead. +Don’t use a `Menu` for frequently used actions. Use a `Toolbar` instead. #### Behavior -Generally, the parent button should indicate that interacting with it will show a `DropdownMenu`. +Generally, the parent button should indicate that interacting with it will show a `Menu`. -The parent button should retain the same visual styling regardless of whether the `DropdownMenu` is displayed or not. +The parent button should retain the same visual styling regardless of whether the `Menu` is displayed or not. #### Placement -The `DropdownMenu` should typically appear directly below, or below and to the left of, the parent button. If there isn’t enough space below to display the full `DropdownMenu`, it can be displayed instead above the parent button. +The `Menu` should typically appear directly below, or below and to the left of, the parent button. If there isn’t enough space below to display the full `Menu`, it can be displayed instead above the parent button. ## Development guidelines This component is still highly experimental, and it's not normally accessible to consumers of the `@wordpress/components` package. -The component exposes a set of components that are meant to be used in combination with each other in order to implement a `DropdownMenu` correctly. +The component exposes a set of components that are meant to be used in combination with each other in order to implement a `Menu` correctly. -### `DropdownMenuV2` +### `Menu` The root component, used to specify the menu's trigger and its contents. @@ -55,45 +55,45 @@ The component accepts the following props: ##### `trigger`: `React.ReactNode` -The trigger button +The button triggering the menu popover. - Required: yes ##### `children`: `React.ReactNode` -The contents of the dropdown +The contents of the menu (ie. one or more menu items). - Required: yes ##### `defaultOpen`: `boolean` -The open state of the dropdown menu when it is initially rendered. Use when not wanting to control its open state. +The open state of the menu popover when it is initially rendered. Use when not wanting to control its open state. - Required: no - Default: `false` ##### `open`: `boolean` -The controlled open state of the dropdown menu. Must be used in conjunction with `onOpenChange`. +The controlled open state of the menu popover. Must be used in conjunction with `onOpenChange`. - Required: no ##### `onOpenChange`: `(open: boolean) => void` -Event handler called when the open state of the dropdown menu changes. +Event handler called when the open state of the menu popover changes. - Required: no ##### `modal`: `boolean` -The modality of the dropdown menu. When set to true, interaction with outside elements will be disabled and only menu content will be visible to screen readers. +The modality of the menu popover. When set to true, interaction with outside elements will be disabled and only menu content will be visible to screen readers. - Required: no - Default: `true` ##### `placement`: ``'top' | 'top-start' | 'top-end' | 'right' | 'right-start' | 'right-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end'` -The placement of the dropdown menu popover. +The placement of the menu popover. - Required: no - Default: `'bottom-start'` for root-level menus, `'right-start'` for nested menus @@ -112,7 +112,7 @@ The skidding of the popover along the anchor element. Can be set to negative val - Required: no - Default: `0` for root-level menus, `-8` for nested menus -### `DropdownMenuV2.Item` +### `Menu.Item` Used to render a menu item. @@ -140,7 +140,7 @@ The contents of the item's suffix. ##### `hideOnClick`: `boolean` -Whether to hide the dropdown menu when the menu item is clicked. +Whether to hide the menu popover when the menu item is clicked. - Required: no - Default: `true` @@ -152,7 +152,7 @@ Determines if the element is disabled. - Required: no - Default: `false` -### `DropdownMenuV2.CheckboxItem` +### `Menu.CheckboxItem` Used to render a checkbox item. @@ -174,7 +174,7 @@ The contents of the item's suffix. ##### `hideOnClick`: `boolean` -Whether to hide the dropdown menu when the menu item is clicked. +Whether to hide the menu popover when the menu item is clicked. - Required: no - Default: `false` @@ -218,7 +218,7 @@ Event handler called when the checked state of the checkbox menu item changes. - Required: no -### `DropdownMenuV2.RadioItem` +### `Menu.RadioItem` Used to render a radio item. @@ -240,7 +240,7 @@ The contents of the item's suffix. ##### `hideOnClick`: `boolean` -Whether to hide the dropdown menu when the menu item is clicked. +Whether to hide the menu popover when the menu item is clicked. - Required: no - Default: `false` @@ -283,7 +283,7 @@ Event handler called when the checked radio menu item changes. - Required: no -### `DropdownMenuV2.ItemLabel` +### `Menu.ItemLabel` Used to render the menu item's label. @@ -297,7 +297,7 @@ The label contents. - Required: yes -### `DropdownMenuV2.ItemHelpText` +### `Menu.ItemHelpText` Used to render the menu item's help text. @@ -311,7 +311,7 @@ The help text contents. - Required: yes -### `DropdownMenuV2.Group` +### `Menu.Group` Used to group menu items. @@ -321,11 +321,11 @@ The component accepts the following props: ##### `children`: `React.ReactNode` -The contents of the group. +The contents of the menu group (ie. an optional menu group label and one or more menu items). - Required: yes -### `DropdownMenuV2.GroupLabel` +### `Menu.GroupLabel` Used to render a group label. The label text should be kept as short as possible. @@ -335,10 +335,10 @@ The component accepts the following props: ##### `children`: `React.ReactNode` -The contents of the group label. +The contents of the menu group label. - Required: yes -### `DropdownMenuV2.Separator` +### `Menu.Separator` Used to render a visual separator. diff --git a/packages/components/src/menu/checkbox-item.tsx b/packages/components/src/menu/checkbox-item.tsx index bcbc920cbb7205..b9a9b8105e517e 100644 --- a/packages/components/src/menu/checkbox-item.tsx +++ b/packages/components/src/menu/checkbox-item.tsx @@ -13,33 +13,33 @@ import { Icon, check } from '@wordpress/icons'; * Internal dependencies */ import type { WordPressComponentProps } from '../context'; -import { DropdownMenuContext } from './context'; -import type { DropdownMenuCheckboxItemProps } from './types'; +import { MenuContext } from './context'; +import type { MenuCheckboxItemProps } from './types'; import * as Styled from './styles'; import { useTemporaryFocusVisibleFix } from './use-temporary-focus-visible-fix'; -export const DropdownMenuCheckboxItem = forwardRef< +export const MenuCheckboxItem = forwardRef< HTMLDivElement, - WordPressComponentProps< DropdownMenuCheckboxItemProps, 'div', false > ->( function DropdownMenuCheckboxItem( + WordPressComponentProps< MenuCheckboxItemProps, 'div', false > +>( function MenuCheckboxItem( { suffix, children, onBlur, hideOnClick = false, ...props }, ref ) { // TODO: Remove when https://github.com/ariakit/ariakit/issues/4083 is fixed const focusVisibleFixProps = useTemporaryFocusVisibleFix( { onBlur } ); - const dropdownMenuContext = useContext( DropdownMenuContext ); + const menuContext = useContext( MenuContext ); return ( - <Styled.DropdownMenuCheckboxItem + <Styled.MenuCheckboxItem ref={ ref } { ...props } { ...focusVisibleFixProps } accessibleWhenDisabled hideOnClick={ hideOnClick } - store={ dropdownMenuContext?.store } + store={ menuContext?.store } > <Ariakit.MenuItemCheck - store={ dropdownMenuContext?.store } + store={ menuContext?.store } render={ <Styled.ItemPrefixWrapper /> } // Override some ariakit inline styles style={ { width: 'auto', height: 'auto' } } @@ -47,17 +47,17 @@ export const DropdownMenuCheckboxItem = forwardRef< <Icon icon={ check } size={ 24 } /> </Ariakit.MenuItemCheck> - <Styled.DropdownMenuItemContentWrapper> - <Styled.DropdownMenuItemChildrenWrapper> + <Styled.MenuItemContentWrapper> + <Styled.MenuItemChildrenWrapper> { children } - </Styled.DropdownMenuItemChildrenWrapper> + </Styled.MenuItemChildrenWrapper> { suffix && ( <Styled.ItemSuffixWrapper> { suffix } </Styled.ItemSuffixWrapper> ) } - </Styled.DropdownMenuItemContentWrapper> - </Styled.DropdownMenuCheckboxItem> + </Styled.MenuItemContentWrapper> + </Styled.MenuCheckboxItem> ); } ); diff --git a/packages/components/src/menu/context.tsx b/packages/components/src/menu/context.tsx index b285843327267f..1205015c57cbee 100644 --- a/packages/components/src/menu/context.tsx +++ b/packages/components/src/menu/context.tsx @@ -6,8 +6,8 @@ import { createContext } from '@wordpress/element'; /** * Internal dependencies */ -import type { DropdownMenuContext as DropdownMenuContextType } from './types'; +import type { MenuContext as MenuContextType } from './types'; -export const DropdownMenuContext = createContext< - DropdownMenuContextType | undefined ->( undefined ); +export const MenuContext = createContext< MenuContextType | undefined >( + undefined +); diff --git a/packages/components/src/menu/group-label.tsx b/packages/components/src/menu/group-label.tsx index 7d838ef9fa620a..71c5c7de69941e 100644 --- a/packages/components/src/menu/group-label.tsx +++ b/packages/components/src/menu/group-label.tsx @@ -7,18 +7,18 @@ import { forwardRef, useContext } from '@wordpress/element'; * Internal dependencies */ import type { WordPressComponentProps } from '../context'; -import { DropdownMenuContext } from './context'; +import { MenuContext } from './context'; import { Text } from '../text'; -import type { DropdownMenuGroupLabelProps } from './types'; +import type { MenuGroupLabelProps } from './types'; import * as Styled from './styles'; -export const DropdownMenuGroupLabel = forwardRef< +export const MenuGroupLabel = forwardRef< HTMLDivElement, - WordPressComponentProps< DropdownMenuGroupLabelProps, 'div', false > ->( function DropdownMenuGroup( props, ref ) { - const dropdownMenuContext = useContext( DropdownMenuContext ); + WordPressComponentProps< MenuGroupLabelProps, 'div', false > +>( function MenuGroup( props, ref ) { + const menuContext = useContext( MenuContext ); return ( - <Styled.DropdownMenuGroupLabel + <Styled.MenuGroupLabel ref={ ref } render={ // @ts-expect-error The `children` prop is passed @@ -31,7 +31,7 @@ export const DropdownMenuGroupLabel = forwardRef< /> } { ...props } - store={ dropdownMenuContext?.store } + store={ menuContext?.store } /> ); } ); diff --git a/packages/components/src/menu/group.tsx b/packages/components/src/menu/group.tsx index f2bf79015bc691..f9a4138fe43580 100644 --- a/packages/components/src/menu/group.tsx +++ b/packages/components/src/menu/group.tsx @@ -7,20 +7,20 @@ import { forwardRef, useContext } from '@wordpress/element'; * Internal dependencies */ import type { WordPressComponentProps } from '../context'; -import { DropdownMenuContext } from './context'; -import type { DropdownMenuGroupProps } from './types'; +import { MenuContext } from './context'; +import type { MenuGroupProps } from './types'; import * as Styled from './styles'; -export const DropdownMenuGroup = forwardRef< +export const MenuGroup = forwardRef< HTMLDivElement, - WordPressComponentProps< DropdownMenuGroupProps, 'div', false > ->( function DropdownMenuGroup( props, ref ) { - const dropdownMenuContext = useContext( DropdownMenuContext ); + WordPressComponentProps< MenuGroupProps, 'div', false > +>( function MenuGroup( props, ref ) { + const menuContext = useContext( MenuContext ); return ( - <Styled.DropdownMenuGroup + <Styled.MenuGroup ref={ ref } { ...props } - store={ dropdownMenuContext?.store } + store={ menuContext?.store } /> ); } ); diff --git a/packages/components/src/menu/index.tsx b/packages/components/src/menu/index.tsx index 50c4f3069d51b5..6f6e89b0a1c72b 100644 --- a/packages/components/src/menu/index.tsx +++ b/packages/components/src/menu/index.tsx @@ -22,23 +22,20 @@ import { chevronRightSmall } from '@wordpress/icons'; */ import { useContextSystem, contextConnect } from '../context'; import type { WordPressComponentProps } from '../context'; -import type { - DropdownMenuContext as DropdownMenuContextType, - DropdownMenuProps, -} from './types'; +import type { MenuContext as MenuContextType, MenuProps } from './types'; import * as Styled from './styles'; -import { DropdownMenuContext } from './context'; -import { DropdownMenuItem } from './item'; -import { DropdownMenuCheckboxItem } from './checkbox-item'; -import { DropdownMenuRadioItem } from './radio-item'; -import { DropdownMenuGroup } from './group'; -import { DropdownMenuGroupLabel } from './group-label'; -import { DropdownMenuSeparator } from './separator'; -import { DropdownMenuItemLabel } from './item-label'; -import { DropdownMenuItemHelpText } from './item-help-text'; - -const UnconnectedDropdownMenu = ( - props: WordPressComponentProps< DropdownMenuProps, 'div', false >, +import { MenuContext } from './context'; +import { MenuItem } from './item'; +import { MenuCheckboxItem } from './checkbox-item'; +import { MenuRadioItem } from './radio-item'; +import { MenuGroup } from './group'; +import { MenuGroupLabel } from './group-label'; +import { MenuSeparator } from './separator'; +import { MenuItemLabel } from './item-label'; +import { MenuItemHelpText } from './item-help-text'; + +const UnconnectedMenu = ( + props: WordPressComponentProps< MenuProps, 'div', false >, ref: React.ForwardedRef< HTMLDivElement > ) => { const { @@ -62,17 +59,18 @@ const UnconnectedDropdownMenu = ( // Rest ...otherProps - } = useContextSystem< - typeof props & Pick< DropdownMenuContextType, 'variant' > - >( props, 'DropdownMenu' ); + } = useContextSystem< typeof props & Pick< MenuContextType, 'variant' > >( + props, + 'Menu' + ); - const parentContext = useContext( DropdownMenuContext ); + const parentContext = useContext( MenuContext ); const computedDirection = isRTL() ? 'rtl' : 'ltr'; // If an explicit value for the `placement` prop is not passed, - // apply a default placement of `bottom-start` for the root dropdown, - // and of `right-start` for nested dropdowns. + // apply a default placement of `bottom-start` for the root menu popover, + // and of `right-start` for nested menu popovers. let computedPlacement = props.placement ?? ( parentContext?.store ? 'right-start' : 'bottom-start' ); @@ -91,7 +89,7 @@ const UnconnectedDropdownMenu = ( } } - const dropdownMenuStore = Ariakit.useMenuStore( { + const menuStore = Ariakit.useMenuStore( { parent: parentContext?.store, open, defaultOpen, @@ -104,25 +102,25 @@ const UnconnectedDropdownMenu = ( } ); const contextValue = useMemo( - () => ( { store: dropdownMenuStore, variant } ), - [ dropdownMenuStore, variant ] + () => ( { store: menuStore, variant } ), + [ menuStore, variant ] ); // Extract the side from the applied placement — useful for animations. // Using `currentPlacement` instead of `placement` to make sure that we // use the final computed placement (including "flips" etc). const appliedPlacementSide = useStoreState( - dropdownMenuStore, + menuStore, 'currentPlacement' ).split( '-' )[ 0 ]; if ( - dropdownMenuStore.parent && - ! ( isValidElement( trigger ) && DropdownMenuItem === trigger.type ) + menuStore.parent && + ! ( isValidElement( trigger ) && MenuItem === trigger.type ) ) { // eslint-disable-next-line no-console console.warn( - 'For nested DropdownMenus, the `trigger` should always be a `DropdownMenuItem`.' + 'For nested Menus, the `trigger` should always be a `MenuItem`.' ); } @@ -153,9 +151,9 @@ const UnconnectedDropdownMenu = ( { /* Menu trigger */ } <Ariakit.MenuButton ref={ ref } - store={ dropdownMenuStore } + store={ menuStore } render={ - dropdownMenuStore.parent + menuStore.parent ? cloneElement( trigger, { // Add submenu arrow, unless a `suffix` is explicitly specified suffix: ( @@ -178,13 +176,13 @@ const UnconnectedDropdownMenu = ( <Ariakit.Menu { ...otherProps } modal={ modal } - store={ dropdownMenuStore } + store={ menuStore } // Root menu has an 8px distance from its trigger, // otherwise 0 (which causes the submenu to slightly overlap) - gutter={ gutter ?? ( dropdownMenuStore.parent ? 0 : 8 ) } + gutter={ gutter ?? ( menuStore.parent ? 0 : 8 ) } // Align nested menu by the same (but opposite) amount // as the menu container's padding. - shift={ shift ?? ( dropdownMenuStore.parent ? -4 : 0 ) } + shift={ shift ?? ( menuStore.parent ? -4 : 0 ) } hideOnHoverOutside={ false } data-side={ appliedPlacementSide } wrapperProps={ wrapperProps } @@ -200,45 +198,42 @@ const UnconnectedDropdownMenu = ( </Styled.MenuPopoverOuterWrapper> ) } > - <DropdownMenuContext.Provider value={ contextValue }> + <MenuContext.Provider value={ contextValue }> { children } - </DropdownMenuContext.Provider> + </MenuContext.Provider> </Ariakit.Menu> </> ); }; -export const DropdownMenuV2 = Object.assign( - contextConnect( UnconnectedDropdownMenu, 'DropdownMenu' ), - { - Context: Object.assign( DropdownMenuContext, { - displayName: 'DropdownMenuV2.Context', - } ), - Item: Object.assign( DropdownMenuItem, { - displayName: 'DropdownMenuV2.Item', - } ), - RadioItem: Object.assign( DropdownMenuRadioItem, { - displayName: 'DropdownMenuV2.RadioItem', - } ), - CheckboxItem: Object.assign( DropdownMenuCheckboxItem, { - displayName: 'DropdownMenuV2.CheckboxItem', - } ), - Group: Object.assign( DropdownMenuGroup, { - displayName: 'DropdownMenuV2.Group', - } ), - GroupLabel: Object.assign( DropdownMenuGroupLabel, { - displayName: 'DropdownMenuV2.GroupLabel', - } ), - Separator: Object.assign( DropdownMenuSeparator, { - displayName: 'DropdownMenuV2.Separator', - } ), - ItemLabel: Object.assign( DropdownMenuItemLabel, { - displayName: 'DropdownMenuV2.ItemLabel', - } ), - ItemHelpText: Object.assign( DropdownMenuItemHelpText, { - displayName: 'DropdownMenuV2.ItemHelpText', - } ), - } -); - -export default DropdownMenuV2; +export const Menu = Object.assign( contextConnect( UnconnectedMenu, 'Menu' ), { + Context: Object.assign( MenuContext, { + displayName: 'Menu.Context', + } ), + Item: Object.assign( MenuItem, { + displayName: 'Menu.Item', + } ), + RadioItem: Object.assign( MenuRadioItem, { + displayName: 'Menu.RadioItem', + } ), + CheckboxItem: Object.assign( MenuCheckboxItem, { + displayName: 'Menu.CheckboxItem', + } ), + Group: Object.assign( MenuGroup, { + displayName: 'Menu.Group', + } ), + GroupLabel: Object.assign( MenuGroupLabel, { + displayName: 'Menu.GroupLabel', + } ), + Separator: Object.assign( MenuSeparator, { + displayName: 'Menu.Separator', + } ), + ItemLabel: Object.assign( MenuItemLabel, { + displayName: 'Menu.ItemLabel', + } ), + ItemHelpText: Object.assign( MenuItemHelpText, { + displayName: 'Menu.ItemHelpText', + } ), +} ); + +export default Menu; diff --git a/packages/components/src/menu/item-help-text.tsx b/packages/components/src/menu/item-help-text.tsx index 0408d20dfbd40d..0ccc8f7461a8ff 100644 --- a/packages/components/src/menu/item-help-text.tsx +++ b/packages/components/src/menu/item-help-text.tsx @@ -9,15 +9,11 @@ import { forwardRef } from '@wordpress/element'; import type { WordPressComponentProps } from '../context'; import * as Styled from './styles'; -export const DropdownMenuItemHelpText = forwardRef< +export const MenuItemHelpText = forwardRef< HTMLSpanElement, WordPressComponentProps< { children: React.ReactNode }, 'span', true > ->( function DropdownMenuItemHelpText( props, ref ) { +>( function MenuItemHelpText( props, ref ) { return ( - <Styled.DropdownMenuItemHelpText - numberOfLines={ 2 } - ref={ ref } - { ...props } - /> + <Styled.MenuItemHelpText numberOfLines={ 2 } ref={ ref } { ...props } /> ); } ); diff --git a/packages/components/src/menu/item-label.tsx b/packages/components/src/menu/item-label.tsx index a1f9391af2f92d..458f69558eafbc 100644 --- a/packages/components/src/menu/item-label.tsx +++ b/packages/components/src/menu/item-label.tsx @@ -9,15 +9,11 @@ import { forwardRef } from '@wordpress/element'; import type { WordPressComponentProps } from '../context'; import * as Styled from './styles'; -export const DropdownMenuItemLabel = forwardRef< +export const MenuItemLabel = forwardRef< HTMLSpanElement, WordPressComponentProps< { children: React.ReactNode }, 'span', true > ->( function DropdownMenuItemLabel( props, ref ) { +>( function MenuItemLabel( props, ref ) { return ( - <Styled.DropdownMenuItemLabel - numberOfLines={ 1 } - ref={ ref } - { ...props } - /> + <Styled.MenuItemLabel numberOfLines={ 1 } ref={ ref } { ...props } /> ); } ); diff --git a/packages/components/src/menu/item.tsx b/packages/components/src/menu/item.tsx index 2680603db22aa7..f8ae670846f55f 100644 --- a/packages/components/src/menu/item.tsx +++ b/packages/components/src/menu/item.tsx @@ -7,44 +7,44 @@ import { forwardRef, useContext } from '@wordpress/element'; * Internal dependencies */ import type { WordPressComponentProps } from '../context'; -import type { DropdownMenuItemProps } from './types'; +import type { MenuItemProps } from './types'; import * as Styled from './styles'; -import { DropdownMenuContext } from './context'; +import { MenuContext } from './context'; import { useTemporaryFocusVisibleFix } from './use-temporary-focus-visible-fix'; -export const DropdownMenuItem = forwardRef< +export const MenuItem = forwardRef< HTMLDivElement, - WordPressComponentProps< DropdownMenuItemProps, 'div', false > ->( function DropdownMenuItem( + WordPressComponentProps< MenuItemProps, 'div', false > +>( function MenuItem( { prefix, suffix, children, onBlur, hideOnClick = true, ...props }, ref ) { // TODO: Remove when https://github.com/ariakit/ariakit/issues/4083 is fixed const focusVisibleFixProps = useTemporaryFocusVisibleFix( { onBlur } ); - const dropdownMenuContext = useContext( DropdownMenuContext ); + const menuContext = useContext( MenuContext ); return ( - <Styled.DropdownMenuItem + <Styled.MenuItem ref={ ref } { ...props } { ...focusVisibleFixProps } accessibleWhenDisabled hideOnClick={ hideOnClick } - store={ dropdownMenuContext?.store } + store={ menuContext?.store } > <Styled.ItemPrefixWrapper>{ prefix }</Styled.ItemPrefixWrapper> - <Styled.DropdownMenuItemContentWrapper> - <Styled.DropdownMenuItemChildrenWrapper> + <Styled.MenuItemContentWrapper> + <Styled.MenuItemChildrenWrapper> { children } - </Styled.DropdownMenuItemChildrenWrapper> + </Styled.MenuItemChildrenWrapper> { suffix && ( <Styled.ItemSuffixWrapper> { suffix } </Styled.ItemSuffixWrapper> ) } - </Styled.DropdownMenuItemContentWrapper> - </Styled.DropdownMenuItem> + </Styled.MenuItemContentWrapper> + </Styled.MenuItem> ); } ); diff --git a/packages/components/src/menu/radio-item.tsx b/packages/components/src/menu/radio-item.tsx index 547d8f257cdf4b..3848d2062c0c25 100644 --- a/packages/components/src/menu/radio-item.tsx +++ b/packages/components/src/menu/radio-item.tsx @@ -13,8 +13,8 @@ import { Icon } from '@wordpress/icons'; * Internal dependencies */ import type { WordPressComponentProps } from '../context'; -import { DropdownMenuContext } from './context'; -import type { DropdownMenuRadioItemProps } from './types'; +import { MenuContext } from './context'; +import type { MenuRadioItemProps } from './types'; import * as Styled from './styles'; import { SVG, Circle } from '@wordpress/primitives'; import { useTemporaryFocusVisibleFix } from './use-temporary-focus-visible-fix'; @@ -25,28 +25,28 @@ const radioCheck = ( </SVG> ); -export const DropdownMenuRadioItem = forwardRef< +export const MenuRadioItem = forwardRef< HTMLDivElement, - WordPressComponentProps< DropdownMenuRadioItemProps, 'div', false > ->( function DropdownMenuRadioItem( + WordPressComponentProps< MenuRadioItemProps, 'div', false > +>( function MenuRadioItem( { suffix, children, onBlur, hideOnClick = false, ...props }, ref ) { // TODO: Remove when https://github.com/ariakit/ariakit/issues/4083 is fixed const focusVisibleFixProps = useTemporaryFocusVisibleFix( { onBlur } ); - const dropdownMenuContext = useContext( DropdownMenuContext ); + const menuContext = useContext( MenuContext ); return ( - <Styled.DropdownMenuRadioItem + <Styled.MenuRadioItem ref={ ref } { ...props } { ...focusVisibleFixProps } accessibleWhenDisabled hideOnClick={ hideOnClick } - store={ dropdownMenuContext?.store } + store={ menuContext?.store } > <Ariakit.MenuItemCheck - store={ dropdownMenuContext?.store } + store={ menuContext?.store } render={ <Styled.ItemPrefixWrapper /> } // Override some ariakit inline styles style={ { width: 'auto', height: 'auto' } } @@ -54,17 +54,17 @@ export const DropdownMenuRadioItem = forwardRef< <Icon icon={ radioCheck } size={ 24 } /> </Ariakit.MenuItemCheck> - <Styled.DropdownMenuItemContentWrapper> - <Styled.DropdownMenuItemChildrenWrapper> + <Styled.MenuItemContentWrapper> + <Styled.MenuItemChildrenWrapper> { children } - </Styled.DropdownMenuItemChildrenWrapper> + </Styled.MenuItemChildrenWrapper> { suffix && ( <Styled.ItemSuffixWrapper> { suffix } </Styled.ItemSuffixWrapper> ) } - </Styled.DropdownMenuItemContentWrapper> - </Styled.DropdownMenuRadioItem> + </Styled.MenuItemContentWrapper> + </Styled.MenuRadioItem> ); } ); diff --git a/packages/components/src/menu/separator.tsx b/packages/components/src/menu/separator.tsx index bc5aff7ae26118..5d0110016d9c4a 100644 --- a/packages/components/src/menu/separator.tsx +++ b/packages/components/src/menu/separator.tsx @@ -7,21 +7,21 @@ import { forwardRef, useContext } from '@wordpress/element'; * Internal dependencies */ import type { WordPressComponentProps } from '../context'; -import { DropdownMenuContext } from './context'; -import type { DropdownMenuSeparatorProps } from './types'; +import { MenuContext } from './context'; +import type { MenuSeparatorProps } from './types'; import * as Styled from './styles'; -export const DropdownMenuSeparator = forwardRef< +export const MenuSeparator = forwardRef< HTMLHRElement, - WordPressComponentProps< DropdownMenuSeparatorProps, 'hr', false > ->( function DropdownMenuSeparator( props, ref ) { - const dropdownMenuContext = useContext( DropdownMenuContext ); + WordPressComponentProps< MenuSeparatorProps, 'hr', false > +>( function MenuSeparator( props, ref ) { + const menuContext = useContext( MenuContext ); return ( - <Styled.DropdownMenuSeparator + <Styled.MenuSeparator ref={ ref } { ...props } - store={ dropdownMenuContext?.store } - variant={ dropdownMenuContext?.variant } + store={ menuContext?.store } + variant={ menuContext?.variant } /> ); } ); diff --git a/packages/components/src/menu/stories/index.story.tsx b/packages/components/src/menu/stories/index.story.tsx index 90d15ca2ea6c18..ecb4cc3c7593f8 100644 --- a/packages/components/src/menu/stories/index.story.tsx +++ b/packages/components/src/menu/stories/index.story.tsx @@ -14,35 +14,35 @@ import { useState, useMemo, useContext } from '@wordpress/element'; * Internal dependencies */ import { useCx } from '../../utils'; -import DropdownMenuV2 from '..'; +import { Menu } from '..'; import Icon from '../../icon'; import Button from '../../button'; import Modal from '../../modal'; import { createSlotFill, Provider as SlotFillProvider } from '../../slot-fill'; import { ContextSystemProvider } from '../../context'; -const meta: Meta< typeof DropdownMenuV2 > = { - title: 'Components (Experimental)/DropdownMenu V2', - component: DropdownMenuV2, +const meta: Meta< typeof Menu > = { + title: 'Components (Experimental)/Menu', + component: Menu, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - Item: DropdownMenuV2.Item, + Item: Menu.Item, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - CheckboxItem: DropdownMenuV2.CheckboxItem, + CheckboxItem: Menu.CheckboxItem, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - Group: DropdownMenuV2.Group, + Group: Menu.Group, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - GroupLabel: DropdownMenuV2.GroupLabel, + GroupLabel: Menu.GroupLabel, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - Separator: DropdownMenuV2.Separator, + Separator: Menu.Separator, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - Context: DropdownMenuV2.Context, + Context: Menu.Context, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - RadioItem: DropdownMenuV2.RadioItem, + RadioItem: Menu.RadioItem, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - ItemLabel: DropdownMenuV2.ItemLabel, + ItemLabel: Menu.ItemLabel, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 - ItemHelpText: DropdownMenuV2.ItemHelpText, + ItemHelpText: Menu.ItemHelpText, }, argTypes: { children: { control: { type: null } }, @@ -60,52 +60,46 @@ const meta: Meta< typeof DropdownMenuV2 > = { }; export default meta; -export const Default: StoryFn< typeof DropdownMenuV2 > = ( props ) => ( - <DropdownMenuV2 { ...props }> - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel>Label</DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel>Label</DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText>Help text</DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.Item> - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel>Label</DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> +export const Default: StoryFn< typeof Menu > = ( props ) => ( + <Menu { ...props }> + <Menu.Item> + <Menu.ItemLabel>Label</Menu.ItemLabel> + </Menu.Item> + <Menu.Item> + <Menu.ItemLabel>Label</Menu.ItemLabel> + <Menu.ItemHelpText>Help text</Menu.ItemHelpText> + </Menu.Item> + <Menu.Item> + <Menu.ItemLabel>Label</Menu.ItemLabel> + <Menu.ItemHelpText> The menu item help text is automatically truncated when there are more than two lines of text - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.Item> - <DropdownMenuV2.Item hideOnClick={ false }> - <DropdownMenuV2.ItemLabel>Label</DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> + </Menu.ItemHelpText> + </Menu.Item> + <Menu.Item hideOnClick={ false }> + <Menu.ItemLabel>Label</Menu.ItemLabel> + <Menu.ItemHelpText> This item doesn't close the menu on click - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.Item> - <DropdownMenuV2.Item disabled>Disabled item</DropdownMenuV2.Item> - <DropdownMenuV2.Separator /> - <DropdownMenuV2.Group> - <DropdownMenuV2.GroupLabel>Group label</DropdownMenuV2.GroupLabel> - <DropdownMenuV2.Item - prefix={ <Icon icon={ customLink } size={ 24 } /> } - > - <DropdownMenuV2.ItemLabel>With prefix</DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - <DropdownMenuV2.Item suffix="⌘S">With suffix</DropdownMenuV2.Item> - <DropdownMenuV2.Item + </Menu.ItemHelpText> + </Menu.Item> + <Menu.Item disabled>Disabled item</Menu.Item> + <Menu.Separator /> + <Menu.Group> + <Menu.GroupLabel>Group label</Menu.GroupLabel> + <Menu.Item prefix={ <Icon icon={ customLink } size={ 24 } /> }> + <Menu.ItemLabel>With prefix</Menu.ItemLabel> + </Menu.Item> + <Menu.Item suffix="⌘S">With suffix</Menu.Item> + <Menu.Item disabled prefix={ <Icon icon={ formatCapitalize } size={ 24 } /> } suffix="⌥⌘T" > - <DropdownMenuV2.ItemLabel> - Disabled with prefix and suffix - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> - And help text - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.Item> - </DropdownMenuV2.Group> - </DropdownMenuV2> + <Menu.ItemLabel>Disabled with prefix and suffix</Menu.ItemLabel> + <Menu.ItemHelpText>And help text</Menu.ItemHelpText> + </Menu.Item> + </Menu.Group> + </Menu> ); Default.args = { trigger: ( @@ -115,56 +109,46 @@ Default.args = { ), }; -export const WithSubmenu: StoryFn< typeof DropdownMenuV2 > = ( props ) => ( - <DropdownMenuV2 { ...props }> - <DropdownMenuV2.Item>Level 1 item</DropdownMenuV2.Item> - <DropdownMenuV2 +export const WithSubmenu: StoryFn< typeof Menu > = ( props ) => ( + <Menu { ...props }> + <Menu.Item>Level 1 item</Menu.Item> + <Menu trigger={ - <DropdownMenuV2.Item suffix="Suffix"> - <DropdownMenuV2.ItemLabel> + <Menu.Item suffix="Suffix"> + <Menu.ItemLabel> Submenu trigger item with a long label - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> + </Menu.ItemLabel> + </Menu.Item> } > - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Level 2 item - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Level 2 item - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - <DropdownMenuV2 + <Menu.Item> + <Menu.ItemLabel>Level 2 item</Menu.ItemLabel> + </Menu.Item> + <Menu.Item> + <Menu.ItemLabel>Level 2 item</Menu.ItemLabel> + </Menu.Item> + <Menu trigger={ - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Submenu trigger - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> + <Menu.Item> + <Menu.ItemLabel>Submenu trigger</Menu.ItemLabel> + </Menu.Item> } > - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Level 3 item - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Level 3 item - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - </DropdownMenuV2> - </DropdownMenuV2> - </DropdownMenuV2> + <Menu.Item> + <Menu.ItemLabel>Level 3 item</Menu.ItemLabel> + </Menu.Item> + <Menu.Item> + <Menu.ItemLabel>Level 3 item</Menu.ItemLabel> + </Menu.Item> + </Menu> + </Menu> + </Menu> ); WithSubmenu.args = { ...Default.args, }; -export const WithCheckboxes: StoryFn< typeof DropdownMenuV2 > = ( props ) => { +export const WithCheckboxes: StoryFn< typeof Menu > = ( props ) => { const [ isAChecked, setAChecked ] = useState( false ); const [ isBChecked, setBChecked ] = useState( true ); const [ multipleCheckboxesValue, setMultipleCheckboxesValue ] = useState< @@ -172,7 +156,7 @@ export const WithCheckboxes: StoryFn< typeof DropdownMenuV2 > = ( props ) => { >( [ 'b' ] ); const onMultipleCheckboxesCheckedChange: React.ComponentProps< - typeof DropdownMenuV2.CheckboxItem + typeof Menu.CheckboxItem >[ 'onChange' ] = ( e ) => { setMultipleCheckboxesValue( ( prevValues ) => { if ( prevValues.includes( e.target.value ) ) { @@ -183,241 +167,183 @@ export const WithCheckboxes: StoryFn< typeof DropdownMenuV2 > = ( props ) => { }; return ( - <DropdownMenuV2 { ...props }> - <DropdownMenuV2.Group> - <DropdownMenuV2.GroupLabel> + <Menu { ...props }> + <Menu.Group> + <Menu.GroupLabel> Single selection, uncontrolled - </DropdownMenuV2.GroupLabel> - <DropdownMenuV2.CheckboxItem + </Menu.GroupLabel> + <Menu.CheckboxItem name="checkbox-individual-uncontrolled-a" value="a" suffix="⌥⌘T" > - <DropdownMenuV2.ItemLabel> - Checkbox item A - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> - Initially unchecked - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.CheckboxItem> - <DropdownMenuV2.CheckboxItem + <Menu.ItemLabel>Checkbox item A</Menu.ItemLabel> + <Menu.ItemHelpText>Initially unchecked</Menu.ItemHelpText> + </Menu.CheckboxItem> + <Menu.CheckboxItem name="checkbox-individual-uncontrolled-b" value="b" defaultChecked > - <DropdownMenuV2.ItemLabel> - Checkbox item B - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> - Initially checked - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.CheckboxItem> - </DropdownMenuV2.Group> - <DropdownMenuV2.Separator /> - <DropdownMenuV2.Group> - <DropdownMenuV2.GroupLabel> - Single selection, controlled - </DropdownMenuV2.GroupLabel> - <DropdownMenuV2.CheckboxItem + <Menu.ItemLabel>Checkbox item B</Menu.ItemLabel> + <Menu.ItemHelpText>Initially checked</Menu.ItemHelpText> + </Menu.CheckboxItem> + </Menu.Group> + <Menu.Separator /> + <Menu.Group> + <Menu.GroupLabel>Single selection, controlled</Menu.GroupLabel> + <Menu.CheckboxItem name="checkbox-individual-controlled-a" value="a" checked={ isAChecked } onChange={ ( e ) => setAChecked( e.target.checked ) } > - <DropdownMenuV2.ItemLabel> - Checkbox item A - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> - Initially unchecked - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.CheckboxItem> - <DropdownMenuV2.CheckboxItem + <Menu.ItemLabel>Checkbox item A</Menu.ItemLabel> + <Menu.ItemHelpText>Initially unchecked</Menu.ItemHelpText> + </Menu.CheckboxItem> + <Menu.CheckboxItem name="checkbox-individual-controlled-b" value="b" checked={ isBChecked } onChange={ ( e ) => setBChecked( e.target.checked ) } > - <DropdownMenuV2.ItemLabel> - Checkbox item B - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> - Initially checked - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.CheckboxItem> - </DropdownMenuV2.Group> - <DropdownMenuV2.Separator /> - <DropdownMenuV2.Group> - <DropdownMenuV2.GroupLabel> + <Menu.ItemLabel>Checkbox item B</Menu.ItemLabel> + <Menu.ItemHelpText>Initially checked</Menu.ItemHelpText> + </Menu.CheckboxItem> + </Menu.Group> + <Menu.Separator /> + <Menu.Group> + <Menu.GroupLabel> Multiple selection, uncontrolled - </DropdownMenuV2.GroupLabel> - <DropdownMenuV2.CheckboxItem + </Menu.GroupLabel> + <Menu.CheckboxItem name="checkbox-multiple-uncontrolled" value="a" > - <DropdownMenuV2.ItemLabel> - Checkbox item A - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> - Initially unchecked - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.CheckboxItem> - <DropdownMenuV2.CheckboxItem + <Menu.ItemLabel>Checkbox item A</Menu.ItemLabel> + <Menu.ItemHelpText>Initially unchecked</Menu.ItemHelpText> + </Menu.CheckboxItem> + <Menu.CheckboxItem name="checkbox-multiple-uncontrolled" value="b" defaultChecked > - <DropdownMenuV2.ItemLabel> - Checkbox item B - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> - Initially checked - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.CheckboxItem> - </DropdownMenuV2.Group> - <DropdownMenuV2.Separator /> - <DropdownMenuV2.Group> - <DropdownMenuV2.GroupLabel> + <Menu.ItemLabel>Checkbox item B</Menu.ItemLabel> + <Menu.ItemHelpText>Initially checked</Menu.ItemHelpText> + </Menu.CheckboxItem> + </Menu.Group> + <Menu.Separator /> + <Menu.Group> + <Menu.GroupLabel> Multiple selection, controlled - </DropdownMenuV2.GroupLabel> - <DropdownMenuV2.CheckboxItem + </Menu.GroupLabel> + <Menu.CheckboxItem name="checkbox-multiple-controlled" value="a" checked={ multipleCheckboxesValue.includes( 'a' ) } onChange={ onMultipleCheckboxesCheckedChange } > - <DropdownMenuV2.ItemLabel> - Checkbox item A - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> - Initially unchecked - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.CheckboxItem> - <DropdownMenuV2.CheckboxItem + <Menu.ItemLabel>Checkbox item A</Menu.ItemLabel> + <Menu.ItemHelpText>Initially unchecked</Menu.ItemHelpText> + </Menu.CheckboxItem> + <Menu.CheckboxItem name="checkbox-multiple-controlled" value="b" checked={ multipleCheckboxesValue.includes( 'b' ) } onChange={ onMultipleCheckboxesCheckedChange } > - <DropdownMenuV2.ItemLabel> - Checkbox item B - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> - Initially checked - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.CheckboxItem> - </DropdownMenuV2.Group> - </DropdownMenuV2> + <Menu.ItemLabel>Checkbox item B</Menu.ItemLabel> + <Menu.ItemHelpText>Initially checked</Menu.ItemHelpText> + </Menu.CheckboxItem> + </Menu.Group> + </Menu> ); }; WithCheckboxes.args = { ...Default.args, }; -export const WithRadios: StoryFn< typeof DropdownMenuV2 > = ( props ) => { +export const WithRadios: StoryFn< typeof Menu > = ( props ) => { const [ radioValue, setRadioValue ] = useState( 'two' ); const onRadioChange: React.ComponentProps< - typeof DropdownMenuV2.RadioItem + typeof Menu.RadioItem >[ 'onChange' ] = ( e ) => setRadioValue( e.target.value ); return ( - <DropdownMenuV2 { ...props }> - <DropdownMenuV2.Group> - <DropdownMenuV2.GroupLabel> - Uncontrolled - </DropdownMenuV2.GroupLabel> - <DropdownMenuV2.RadioItem name="radio-uncontrolled" value="one"> - <DropdownMenuV2.ItemLabel> - Radio item 1 - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> - Initially unchecked - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.RadioItem> - <DropdownMenuV2.RadioItem + <Menu { ...props }> + <Menu.Group> + <Menu.GroupLabel>Uncontrolled</Menu.GroupLabel> + <Menu.RadioItem name="radio-uncontrolled" value="one"> + <Menu.ItemLabel>Radio item 1</Menu.ItemLabel> + <Menu.ItemHelpText>Initially unchecked</Menu.ItemHelpText> + </Menu.RadioItem> + <Menu.RadioItem name="radio-uncontrolled" value="two" defaultChecked > - <DropdownMenuV2.ItemLabel> - Radio item 2 - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> - Initially checked - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.RadioItem> - </DropdownMenuV2.Group> - <DropdownMenuV2.Separator /> - <DropdownMenuV2.Group> - <DropdownMenuV2.GroupLabel> - Controlled - </DropdownMenuV2.GroupLabel> - <DropdownMenuV2.RadioItem + <Menu.ItemLabel>Radio item 2</Menu.ItemLabel> + <Menu.ItemHelpText>Initially checked</Menu.ItemHelpText> + </Menu.RadioItem> + </Menu.Group> + <Menu.Separator /> + <Menu.Group> + <Menu.GroupLabel>Controlled</Menu.GroupLabel> + <Menu.RadioItem name="radio-controlled" value="one" checked={ radioValue === 'one' } onChange={ onRadioChange } > - <DropdownMenuV2.ItemLabel> - Radio item 1 - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> - Initially unchecked - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.RadioItem> - <DropdownMenuV2.RadioItem + <Menu.ItemLabel>Radio item 1</Menu.ItemLabel> + <Menu.ItemHelpText>Initially unchecked</Menu.ItemHelpText> + </Menu.RadioItem> + <Menu.RadioItem name="radio-controlled" value="two" checked={ radioValue === 'two' } onChange={ onRadioChange } > - <DropdownMenuV2.ItemLabel> - Radio item 2 - </DropdownMenuV2.ItemLabel> - <DropdownMenuV2.ItemHelpText> - Initially checked - </DropdownMenuV2.ItemHelpText> - </DropdownMenuV2.RadioItem> - </DropdownMenuV2.Group> - </DropdownMenuV2> + <Menu.ItemLabel>Radio item 2</Menu.ItemLabel> + <Menu.ItemHelpText>Initially checked</Menu.ItemHelpText> + </Menu.RadioItem> + </Menu.Group> + </Menu> ); }; WithRadios.args = { ...Default.args, }; -const modalOnTopOfDropdown = css` +const modalOnTopOfMenuPopover = css` && { z-index: 1000000; } `; // For more examples with `Modal`, check https://ariakit.org/examples/menu-wordpress-modal -export const WithModals: StoryFn< typeof DropdownMenuV2 > = ( props ) => { +export const WithModals: StoryFn< typeof Menu > = ( props ) => { const [ isOuterModalOpen, setOuterModalOpen ] = useState( false ); const [ isInnerModalOpen, setInnerModalOpen ] = useState( false ); const cx = useCx(); - const modalOverlayClassName = cx( modalOnTopOfDropdown ); + const modalOverlayClassName = cx( modalOnTopOfMenuPopover ); return ( <> - <DropdownMenuV2 { ...props }> - <DropdownMenuV2.Item + <Menu { ...props }> + <Menu.Item onClick={ () => setOuterModalOpen( true ) } hideOnClick={ false } > - <DropdownMenuV2.ItemLabel> - Open outer modal - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - <DropdownMenuV2.Item + <Menu.ItemLabel>Open outer modal</Menu.ItemLabel> + </Menu.Item> + <Menu.Item onClick={ () => setInnerModalOpen( true ) } hideOnClick={ false } > - <DropdownMenuV2.ItemLabel> - Open inner modal - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> + <Menu.ItemLabel>Open inner modal</Menu.ItemLabel> + </Menu.Item> { isInnerModalOpen && ( <Modal onRequestClose={ () => setInnerModalOpen( false ) } @@ -429,7 +355,7 @@ export const WithModals: StoryFn< typeof DropdownMenuV2 > = ( props ) => { </button> </Modal> ) } - </DropdownMenuV2> + </Menu> { isOuterModalOpen && ( <Modal onRequestClose={ () => setOuterModalOpen( false ) } @@ -451,19 +377,16 @@ WithModals.args = { const ExampleSlotFill = createSlotFill( 'Example' ); const Slot = () => { - const dropdownMenuContext = useContext( DropdownMenuV2.Context ); + const menuContext = useContext( Menu.Context ); // Forwarding the content of the slot so that it can be used by the fill const fillProps = useMemo( () => ( { forwardedContext: [ - [ - DropdownMenuV2.Context.Provider, - { value: dropdownMenuContext }, - ], + [ Menu.Context.Provider, { value: menuContext } ], ], } ), - [ dropdownMenuContext ] + [ menuContext ] ); return ( @@ -499,37 +422,31 @@ const Fill = ( { children }: { children: React.ReactNode } ) => { ); }; -export const WithSlotFill: StoryFn< typeof DropdownMenuV2 > = ( props ) => { +export const WithSlotFill: StoryFn< typeof Menu > = ( props ) => { return ( <SlotFillProvider> - <DropdownMenuV2 { ...props }> - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel>Item</DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> + <Menu { ...props }> + <Menu.Item> + <Menu.ItemLabel>Item</Menu.ItemLabel> + </Menu.Item> <Slot /> - </DropdownMenuV2> + </Menu> <Fill> - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Item from fill - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - <DropdownMenuV2 + <Menu.Item> + <Menu.ItemLabel>Item from fill</Menu.ItemLabel> + </Menu.Item> + <Menu trigger={ - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Submenu from fill - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> + <Menu.Item> + <Menu.ItemLabel>Submenu from fill</Menu.ItemLabel> + </Menu.Item> } > - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Submenu item from fill - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu.Item> + <Menu.ItemLabel>Submenu item from fill</Menu.ItemLabel> + </Menu.Item> + </Menu> </Fill> </SlotFillProvider> ); @@ -539,48 +456,40 @@ WithSlotFill.args = { }; const toolbarVariantContextValue = { - DropdownMenuV2: { + Menu: { variant: 'toolbar', }, }; -export const ToolbarVariant: StoryFn< typeof DropdownMenuV2 > = ( props ) => ( +export const ToolbarVariant: StoryFn< typeof Menu > = ( props ) => ( // TODO: add toolbar <ContextSystemProvider value={ toolbarVariantContextValue }> - <DropdownMenuV2 { ...props }> - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Level 1 item - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Level 1 item - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - <DropdownMenuV2.Separator /> - <DropdownMenuV2 + <Menu { ...props }> + <Menu.Item> + <Menu.ItemLabel>Level 1 item</Menu.ItemLabel> + </Menu.Item> + <Menu.Item> + <Menu.ItemLabel>Level 1 item</Menu.ItemLabel> + </Menu.Item> + <Menu.Separator /> + <Menu trigger={ - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Submenu trigger - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> + <Menu.Item> + <Menu.ItemLabel>Submenu trigger</Menu.ItemLabel> + </Menu.Item> } > - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Level 2 item - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - </DropdownMenuV2> - </DropdownMenuV2> + <Menu.Item> + <Menu.ItemLabel>Level 2 item</Menu.ItemLabel> + </Menu.Item> + </Menu> + </Menu> </ContextSystemProvider> ); ToolbarVariant.args = { ...Default.args, }; -export const InsideModal: StoryFn< typeof DropdownMenuV2 > = ( props ) => { +export const InsideModal: StoryFn< typeof Menu > = ( props ) => { const [ isModalOpen, setModalOpen ] = useState( false ); return ( <> @@ -593,34 +502,28 @@ export const InsideModal: StoryFn< typeof DropdownMenuV2 > = ( props ) => { </Button> { isModalOpen && ( <Modal onRequestClose={ () => setModalOpen( false ) }> - <DropdownMenuV2 { ...props }> - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Level 1 item - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Level 1 item - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - <DropdownMenuV2.Separator /> - <DropdownMenuV2 + <Menu { ...props }> + <Menu.Item> + <Menu.ItemLabel>Level 1 item</Menu.ItemLabel> + </Menu.Item> + <Menu.Item> + <Menu.ItemLabel>Level 1 item</Menu.ItemLabel> + </Menu.Item> + <Menu.Separator /> + <Menu trigger={ - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> + <Menu.Item> + <Menu.ItemLabel> Submenu trigger - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> + </Menu.ItemLabel> + </Menu.Item> } > - <DropdownMenuV2.Item> - <DropdownMenuV2.ItemLabel> - Level 2 item - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - </DropdownMenuV2> - </DropdownMenuV2> + <Menu.Item> + <Menu.ItemLabel>Level 2 item</Menu.ItemLabel> + </Menu.Item> + </Menu> + </Menu> <Button onClick={ () => setModalOpen( false ) }> Close modal </Button> diff --git a/packages/components/src/menu/styles.ts b/packages/components/src/menu/styles.ts index b25613e9feb52b..3312c8cb2de161 100644 --- a/packages/components/src/menu/styles.ts +++ b/packages/components/src/menu/styles.ts @@ -12,7 +12,7 @@ import { COLORS, font, rtl, CONFIG } from '../utils'; import { space } from '../utils/space'; import Icon from '../icon'; import { Truncate } from '../truncate'; -import type { DropdownMenuContext } from './types'; +import type { MenuContext } from './types'; const ANIMATION_PARAMS = { SCALE_AMOUNT_OUTER: 0.82, @@ -43,7 +43,7 @@ const TOOLBAR_VARIANT_BOX_SHADOW = `0 0 0 ${ CONFIG.borderWidth } ${ TOOLBAR_VAR const GRID_TEMPLATE_COLS = 'minmax( 0, max-content ) 1fr'; export const MenuPopoverOuterWrapper = styled.div< - Pick< DropdownMenuContext, 'variant' > + Pick< MenuContext, 'variant' > >` position: relative; @@ -229,15 +229,15 @@ const baseItem = css` } `; -export const DropdownMenuItem = styled( Ariakit.MenuItem )` +export const MenuItem = styled( Ariakit.MenuItem )` ${ baseItem }; `; -export const DropdownMenuCheckboxItem = styled( Ariakit.MenuItemCheckbox )` +export const MenuCheckboxItem = styled( Ariakit.MenuItemCheckbox )` ${ baseItem }; `; -export const DropdownMenuRadioItem = styled( Ariakit.MenuItemRadio )` +export const MenuRadioItem = styled( Ariakit.MenuItemRadio )` ${ baseItem }; `; @@ -249,14 +249,14 @@ export const ItemPrefixWrapper = styled.span` * Even when the item is not checked, occupy the same screen space to avoid * the space collapside when no items are checked. */ - ${ DropdownMenuCheckboxItem } > &, - ${ DropdownMenuRadioItem } > & { + ${ MenuCheckboxItem } > &, + ${ MenuRadioItem } > & { /* Same width as the check icons */ min-width: ${ space( 6 ) }; } - ${ DropdownMenuCheckboxItem } > &, - ${ DropdownMenuRadioItem } > &, + ${ MenuCheckboxItem } > &, + ${ MenuRadioItem } > &, &:not( :empty ) { margin-inline-end: ${ space( 2 ) }; } @@ -278,7 +278,7 @@ export const ItemPrefixWrapper = styled.span` } `; -export const DropdownMenuItemContentWrapper = styled.div` +export const MenuItemContentWrapper = styled.div` /* * Always occupy the second column, since the first column * is taken by the prefix wrapper (when displayed). @@ -293,7 +293,7 @@ export const DropdownMenuItemContentWrapper = styled.div` pointer-events: none; `; -export const DropdownMenuItemChildrenWrapper = styled.div` +export const MenuItemChildrenWrapper = styled.div` flex: 1; display: inline-flex; @@ -324,12 +324,12 @@ export const ItemSuffixWrapper = styled.span` } `; -export const DropdownMenuGroup = styled( Ariakit.MenuGroup )` +export const MenuGroup = styled( Ariakit.MenuGroup )` /* Ignore this element when calculating the layout. Useful for subgrid */ display: contents; `; -export const DropdownMenuGroupLabel = styled( Ariakit.MenuGroupLabel )` +export const MenuGroupLabel = styled( Ariakit.MenuGroupLabel )` /* Occupy the width of all grid columns (ie. full width) */ grid-column: 1 / -1; @@ -338,8 +338,8 @@ export const DropdownMenuGroupLabel = styled( Ariakit.MenuGroupLabel )` padding-inline: ${ ITEM_PADDING_INLINE }; `; -export const DropdownMenuSeparator = styled( Ariakit.MenuSeparator )< - Pick< DropdownMenuContext, 'variant' > +export const MenuSeparator = styled( Ariakit.MenuSeparator )< + Pick< MenuContext, 'variant' > >` /* Occupy the width of all grid columns (ie. full width) */ grid-column: 1 / -1; @@ -370,13 +370,13 @@ export const SubmenuChevronIcon = styled( Icon )` ) }; `; -export const DropdownMenuItemLabel = styled( Truncate )` +export const MenuItemLabel = styled( Truncate )` font-size: ${ font( 'default.fontSize' ) }; line-height: 20px; color: inherit; `; -export const DropdownMenuItemHelpText = styled( Truncate )` +export const MenuItemHelpText = styled( Truncate )` font-size: ${ font( 'helpText.fontSize' ) }; line-height: 16px; color: ${ LIGHTER_TEXT_COLOR }; diff --git a/packages/components/src/menu/test/index.tsx b/packages/components/src/menu/test/index.tsx index cb674f27edaacf..60276cdb2379a0 100644 --- a/packages/components/src/menu/test/index.tsx +++ b/packages/components/src/menu/test/index.tsx @@ -12,34 +12,24 @@ import { useState } from '@wordpress/element'; /** * Internal dependencies */ -import { DropdownMenuV2 } from '..'; +import { Menu } from '..'; const delay = ( delayInMs: number ) => { return new Promise( ( resolve ) => setTimeout( resolve, delayInMs ) ); }; -describe( 'DropdownMenu', () => { +describe( 'Menu', () => { // See https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/ it( 'should follow the WAI-ARIA spec', async () => { render( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.Item>Dropdown menu item</DropdownMenuV2.Item> - <DropdownMenuV2.Separator /> - <DropdownMenuV2 - trigger={ - <DropdownMenuV2.Item> - Dropdown submenu - </DropdownMenuV2.Item> - } - > - <DropdownMenuV2.Item> - Dropdown submenu item 1 - </DropdownMenuV2.Item> - <DropdownMenuV2.Item> - Dropdown submenu item 2 - </DropdownMenuV2.Item> - </DropdownMenuV2> - </DropdownMenuV2> + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.Item>Menu item</Menu.Item> + <Menu.Separator /> + <Menu trigger={ <Menu.Item>Submenu trigger item</Menu.Item> }> + <Menu.Item>Submenu item 1</Menu.Item> + <Menu.Item>Submenu item 2</Menu.Item> + </Menu> + </Menu> ); const toggleButton = screen.getByRole( 'button', { @@ -68,7 +58,7 @@ describe( 'DropdownMenu', () => { expect( screen.getAllByRole( 'menuitem' ) ).toHaveLength( 2 ); const submenuTrigger = screen.getByRole( 'menuitem', { - name: 'Dropdown submenu', + name: 'Submenu trigger item', } ); expect( submenuTrigger ).toHaveAttribute( 'aria-haspopup', 'menu' ); expect( submenuTrigger ).toHaveAttribute( 'aria-expanded', 'false' ); @@ -94,36 +84,32 @@ describe( 'DropdownMenu', () => { describe( 'pointer and keyboard interactions', () => { it( 'should open and focus the menu when clicking the trigger', async () => { render( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.Item> - Dropdown menu item - </DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.Item>Menu item</Menu.Item> + </Menu> ); const toggleButton = screen.getByRole( 'button', { name: 'Open dropdown', } ); - // DropdownMenu closed + // Menu closed expect( screen.queryByRole( 'menu' ) ).not.toBeInTheDocument(); // Click to open the menu await click( toggleButton ); - // DropdownMenu open, focus is on the menu wrapper + // Menu open, focus is on the menu wrapper expect( screen.getByRole( 'menu' ) ).toHaveFocus(); } ); it( 'should open and focus the first item when pressing the arrow down key on the trigger', async () => { render( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.Item disabled> - First item - </DropdownMenuV2.Item> - <DropdownMenuV2.Item>Second item</DropdownMenuV2.Item> - <DropdownMenuV2.Item>Third item</DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.Item disabled>First item</Menu.Item> + <Menu.Item>Second item</Menu.Item> + <Menu.Item>Third item</Menu.Item> + </Menu> ); const toggleButton = screen.getByRole( 'button', { @@ -135,12 +121,12 @@ describe( 'DropdownMenu', () => { expect( toggleButton ).toHaveFocus(); - // DropdownMenu closed + // Menu closed expect( screen.queryByRole( 'menuitem' ) ).not.toBeInTheDocument(); await press.ArrowDown(); - // DropdownMenu open, focus is on the first focusable item + // Menu open, focus is on the first focusable item // (disabled items are still focusable and accessible) expect( screen.getByRole( 'menuitem', { name: 'First item' } ) @@ -149,13 +135,11 @@ describe( 'DropdownMenu', () => { it( 'should open and focus the first item when pressing the space key on the trigger', async () => { render( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.Item disabled> - First item - </DropdownMenuV2.Item> - <DropdownMenuV2.Item>Second item</DropdownMenuV2.Item> - <DropdownMenuV2.Item>Third item</DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.Item disabled>First item</Menu.Item> + <Menu.Item>Second item</Menu.Item> + <Menu.Item>Third item</Menu.Item> + </Menu> ); const toggleButton = screen.getByRole( 'button', { @@ -167,12 +151,12 @@ describe( 'DropdownMenu', () => { expect( toggleButton ).toHaveFocus(); - // DropdownMenu closed + // Menu closed expect( screen.queryByRole( 'menuitem' ) ).not.toBeInTheDocument(); await press.Space(); - // DropdownMenu open, focus is on the first focusable item + // Menu open, focus is on the first focusable item // (disabled items are still focusable and accessible expect( screen.getByRole( 'menuitem', { name: 'First item' } ) @@ -181,11 +165,9 @@ describe( 'DropdownMenu', () => { it( 'should close when pressing the escape key', async () => { render( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.Item> - Dropdown menu item - </DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.Item>Menu item</Menu.Item> + </Menu> ); const trigger = screen.getByRole( 'button', { @@ -212,14 +194,9 @@ describe( 'DropdownMenu', () => { it( 'should close when clicking outside of the content', async () => { render( - <DropdownMenuV2 - defaultOpen - trigger={ <button>Open dropdown</button> } - > - <DropdownMenuV2.Item> - Dropdown menu item - </DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu defaultOpen trigger={ <button>Open dropdown</button> }> + <Menu.Item>Menu item</Menu.Item> + </Menu> ); expect( screen.getByRole( 'menu' ) ).toBeInTheDocument(); @@ -232,14 +209,9 @@ describe( 'DropdownMenu', () => { it( 'should close when clicking on a menu item', async () => { render( - <DropdownMenuV2 - defaultOpen - trigger={ <button>Open dropdown</button> } - > - <DropdownMenuV2.Item> - Dropdown menu item - </DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu defaultOpen trigger={ <button>Open dropdown</button> }> + <Menu.Item>Menu item</Menu.Item> + </Menu> ); expect( screen.getByRole( 'menu' ) ).toBeInTheDocument(); @@ -252,14 +224,9 @@ describe( 'DropdownMenu', () => { it( 'should not close when clicking on a menu item when the `hideOnClick` prop is set to `false`', async () => { render( - <DropdownMenuV2 - defaultOpen - trigger={ <button>Open dropdown</button> } - > - <DropdownMenuV2.Item hideOnClick={ false }> - Dropdown menu item - </DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu defaultOpen trigger={ <button>Open dropdown</button> }> + <Menu.Item hideOnClick={ false }>Menu item</Menu.Item> + </Menu> ); expect( screen.getByRole( 'menu' ) ).toBeVisible(); @@ -272,14 +239,9 @@ describe( 'DropdownMenu', () => { it( 'should not close when clicking on a disabled menu item', async () => { render( - <DropdownMenuV2 - defaultOpen - trigger={ <button>Open dropdown</button> } - > - <DropdownMenuV2.Item disabled> - Dropdown menu item - </DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu defaultOpen trigger={ <button>Open dropdown</button> }> + <Menu.Item disabled>Menu item</Menu.Item> + </Menu> ); expect( screen.getByRole( 'menu' ) ).toBeInTheDocument(); @@ -292,85 +254,51 @@ describe( 'DropdownMenu', () => { it( 'should reveal submenu content when hovering over the submenu trigger', async () => { render( - <DropdownMenuV2 - defaultOpen - trigger={ <button>Open dropdown</button> } - > - <DropdownMenuV2.Item> - Dropdown menu item 1 - </DropdownMenuV2.Item> - <DropdownMenuV2.Item> - Dropdown menu item 2 - </DropdownMenuV2.Item> - <DropdownMenuV2 - trigger={ - <DropdownMenuV2.Item> - Dropdown submenu - </DropdownMenuV2.Item> - } + <Menu defaultOpen trigger={ <button>Open dropdown</button> }> + <Menu.Item>Menu item 1</Menu.Item> + <Menu.Item>Menu item 2</Menu.Item> + <Menu + trigger={ <Menu.Item>Submenu trigger item</Menu.Item> } > - <DropdownMenuV2.Item> - Dropdown submenu item 1 - </DropdownMenuV2.Item> - <DropdownMenuV2.Item> - Dropdown submenu item 2 - </DropdownMenuV2.Item> - </DropdownMenuV2> - <DropdownMenuV2.Item> - Dropdown menu item 3 - </DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu.Item>Submenu item 1</Menu.Item> + <Menu.Item>Submenu item 2</Menu.Item> + </Menu> + <Menu.Item>Menu item 3</Menu.Item> + </Menu> ); // Before hover, submenu items are not rendered expect( screen.queryByRole( 'menuitem', { - name: 'Dropdown submenu item 1', + name: 'Submenu item 1', } ) ).not.toBeInTheDocument(); await hover( - screen.getByRole( 'menuitem', { name: 'Dropdown submenu' } ) + screen.getByRole( 'menuitem', { name: 'Submenu trigger item' } ) ); // After hover, submenu items are rendered // Reason for `findByRole`: due to the animation, we've got to wait // a short amount of time for the submenu to appear await screen.findByRole( 'menuitem', { - name: 'Dropdown submenu item 1', + name: 'Submenu item 1', } ); } ); it( 'should navigate menu items and subitems using the arrow, spacebar and enter keys', async () => { render( - <DropdownMenuV2 - defaultOpen - trigger={ <button>Open dropdown</button> } - > - <DropdownMenuV2.Item> - Dropdown menu item 1 - </DropdownMenuV2.Item> - <DropdownMenuV2.Item> - Dropdown menu item 2 - </DropdownMenuV2.Item> - <DropdownMenuV2 - trigger={ - <DropdownMenuV2.Item> - Dropdown submenu - </DropdownMenuV2.Item> - } + <Menu defaultOpen trigger={ <button>Open dropdown</button> }> + <Menu.Item>Menu item 1</Menu.Item> + <Menu.Item>Menu item 2</Menu.Item> + <Menu + trigger={ <Menu.Item>Submenu trigger item</Menu.Item> } > - <DropdownMenuV2.Item> - Dropdown submenu item 1 - </DropdownMenuV2.Item> - <DropdownMenuV2.Item> - Dropdown submenu item 2 - </DropdownMenuV2.Item> - </DropdownMenuV2> - <DropdownMenuV2.Item> - Dropdown menu item 3 - </DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu.Item>Submenu item 1</Menu.Item> + <Menu.Item>Submenu item 2</Menu.Item> + </Menu> + <Menu.Item>Menu item 3</Menu.Item> + </Menu> ); // The menu is focused automatically when `defaultOpen` is set. @@ -382,58 +310,58 @@ describe( 'DropdownMenu', () => { // The selection wraps around from last to first and viceversa await press.ArrowDown(); expect( - screen.getByRole( 'menuitem', { name: 'Dropdown menu item 1' } ) + screen.getByRole( 'menuitem', { name: 'Menu item 1' } ) ).toHaveFocus(); await press.ArrowDown(); expect( - screen.getByRole( 'menuitem', { name: 'Dropdown menu item 2' } ) + screen.getByRole( 'menuitem', { name: 'Menu item 2' } ) ).toHaveFocus(); await press.ArrowDown(); expect( - screen.getByRole( 'menuitem', { name: 'Dropdown submenu' } ) + screen.getByRole( 'menuitem', { name: 'Submenu trigger item' } ) ).toHaveFocus(); await press.ArrowDown(); expect( - screen.getByRole( 'menuitem', { name: 'Dropdown menu item 3' } ) + screen.getByRole( 'menuitem', { name: 'Menu item 3' } ) ).toHaveFocus(); await press.ArrowDown(); expect( - screen.getByRole( 'menuitem', { name: 'Dropdown menu item 1' } ) + screen.getByRole( 'menuitem', { name: 'Menu item 1' } ) ).toHaveFocus(); await press.ArrowUp(); expect( - screen.getByRole( 'menuitem', { name: 'Dropdown menu item 3' } ) + screen.getByRole( 'menuitem', { name: 'Menu item 3' } ) ).toHaveFocus(); await press.ArrowUp(); expect( - screen.getByRole( 'menuitem', { name: 'Dropdown submenu' } ) + screen.getByRole( 'menuitem', { name: 'Submenu trigger item' } ) ).toHaveFocus(); // Arrow right/left can be used to enter/leave submenus await press.ArrowRight(); expect( screen.getByRole( 'menuitem', { - name: 'Dropdown submenu item 1', + name: 'Submenu item 1', } ) ).toHaveFocus(); await press.ArrowDown(); expect( screen.getByRole( 'menuitem', { - name: 'Dropdown submenu item 2', + name: 'Submenu item 2', } ) ).toHaveFocus(); await press.ArrowLeft(); expect( screen.getByRole( 'menuitem', { - name: 'Dropdown submenu', + name: 'Submenu trigger item', } ) ).toHaveFocus(); @@ -441,28 +369,28 @@ describe( 'DropdownMenu', () => { await press.Enter(); expect( screen.getByRole( 'menuitem', { - name: 'Dropdown submenu item 1', + name: 'Submenu item 1', } ) ).toHaveFocus(); await press.ArrowLeft(); expect( screen.getByRole( 'menuitem', { - name: 'Dropdown submenu', + name: 'Submenu trigger item', } ) ).toHaveFocus(); await press.Space(); expect( screen.getByRole( 'menuitem', { - name: 'Dropdown submenu item 1', + name: 'Submenu item 1', } ) ).toHaveFocus(); await press.ArrowLeft(); expect( screen.getByRole( 'menuitem', { - name: 'Dropdown submenu', + name: 'Submenu trigger item', } ) ).toHaveFocus(); } ); @@ -473,32 +401,32 @@ describe( 'DropdownMenu', () => { const ControlledRadioGroup = () => { const [ radioValue, setRadioValue ] = useState( 'two' ); const onRadioChange: React.ComponentProps< - typeof DropdownMenuV2.RadioItem + typeof Menu.RadioItem >[ 'onChange' ] = ( e ) => { onRadioValueChangeSpy( e.target.value ); setRadioValue( e.target.value ); }; return ( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.Group> - <DropdownMenuV2.RadioItem + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.Group> + <Menu.RadioItem name="radio-test" value="radio-one" checked={ radioValue === 'radio-one' } onChange={ onRadioChange } > Radio item one - </DropdownMenuV2.RadioItem> - <DropdownMenuV2.RadioItem + </Menu.RadioItem> + <Menu.RadioItem name="radio-test" value="radio-two" checked={ radioValue === 'radio-two' } onChange={ onRadioChange } > Radio item two - </DropdownMenuV2.RadioItem> - </DropdownMenuV2.Group> - </DropdownMenuV2> + </Menu.RadioItem> + </Menu.Group> + </Menu> ); }; @@ -556,9 +484,9 @@ describe( 'DropdownMenu', () => { it( 'should check radio items and keep the menu open when clicking (uncontrolled)', async () => { const onRadioValueChangeSpy = jest.fn(); render( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.Group> - <DropdownMenuV2.RadioItem + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.Group> + <Menu.RadioItem name="radio-test" value="radio-one" onChange={ ( e ) => @@ -566,8 +494,8 @@ describe( 'DropdownMenu', () => { } > Radio item one - </DropdownMenuV2.RadioItem> - <DropdownMenuV2.RadioItem + </Menu.RadioItem> + <Menu.RadioItem name="radio-test" value="radio-two" defaultChecked @@ -576,9 +504,9 @@ describe( 'DropdownMenu', () => { } > Radio item two - </DropdownMenuV2.RadioItem> - </DropdownMenuV2.Group> - </DropdownMenuV2> + </Menu.RadioItem> + </Menu.Group> + </Menu> ); // Open dropdown @@ -640,8 +568,8 @@ describe( 'DropdownMenu', () => { useState< boolean >(); return ( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.CheckboxItem + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.CheckboxItem name="item-one" value="item-one-value" checked={ itemOneChecked } @@ -655,9 +583,9 @@ describe( 'DropdownMenu', () => { } } > Checkbox item one - </DropdownMenuV2.CheckboxItem> + </Menu.CheckboxItem> - <DropdownMenuV2.CheckboxItem + <Menu.CheckboxItem name="item-two" value="item-two-value" checked={ itemTwoChecked } @@ -671,8 +599,8 @@ describe( 'DropdownMenu', () => { } } > Checkbox item two - </DropdownMenuV2.CheckboxItem> - </DropdownMenuV2> + </Menu.CheckboxItem> + </Menu> ); }; @@ -763,8 +691,8 @@ describe( 'DropdownMenu', () => { const onCheckboxValueChangeSpy = jest.fn(); render( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.CheckboxItem + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.CheckboxItem name="item-one" value="item-one-value" onChange={ ( e ) => { @@ -776,9 +704,9 @@ describe( 'DropdownMenu', () => { } } > Checkbox item one - </DropdownMenuV2.CheckboxItem> + </Menu.CheckboxItem> - <DropdownMenuV2.CheckboxItem + <Menu.CheckboxItem name="item-two" value="item-two-value" defaultChecked @@ -791,8 +719,8 @@ describe( 'DropdownMenu', () => { } } > Checkbox item two - </DropdownMenuV2.CheckboxItem> - </DropdownMenuV2> + </Menu.CheckboxItem> + </Menu> ); // Open dropdown @@ -881,11 +809,9 @@ describe( 'DropdownMenu', () => { it( 'should be modal by default', async () => { render( <> - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.Item> - Dropdown menu item - </DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.Item>Menu item</Menu.Item> + </Menu> <button>Button outside of dropdown</button> </> ); @@ -897,7 +823,7 @@ describe( 'DropdownMenu', () => { } ) ); - // DropdownMenu open, focus is on the menu wrapper + // Menu open, focus is on the menu wrapper expect( screen.getByRole( 'menu' ) ).toHaveFocus(); expect( @@ -910,14 +836,12 @@ describe( 'DropdownMenu', () => { it( 'should not be modal when the `modal` prop is set to `false`', async () => { render( <> - <DropdownMenuV2 + <Menu trigger={ <button>Open dropdown</button> } modal={ false } > - <DropdownMenuV2.Item> - Dropdown menu item - </DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu.Item>Menu item</Menu.Item> + </Menu> <button>Button outside of dropdown</button> </> ); @@ -929,17 +853,17 @@ describe( 'DropdownMenu', () => { } ) ); - // DropdownMenu open, focus is on the menu wrapper + // Menu open, focus is on the menu wrapper expect( screen.getByRole( 'menu' ) ).toHaveFocus(); - // DropdownMenu is not modal, therefore the outer button is part of the + // Menu is not modal, therefore the outer button is part of the // accessibility tree and can be found. const outerButton = screen.getByRole( 'button', { name: 'Button outside of dropdown', } ); // The outer button can be focused by pressing tab. Doing so will cause - // the DropdownMenu to close. + // the Menu to close. await press.Tab(); expect( outerButton ).toBeInTheDocument(); expect( screen.queryByRole( 'menu' ) ).not.toBeInTheDocument(); @@ -949,11 +873,9 @@ describe( 'DropdownMenu', () => { describe( 'items prefix and suffix', () => { it( 'should display a prefix on regular items', async () => { render( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.Item prefix={ <>Item prefix</> }> - Dropdown menu item - </DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.Item prefix={ <>Item prefix</> }>Menu item</Menu.Item> + </Menu> ); // Click to open the menu @@ -966,18 +888,16 @@ describe( 'DropdownMenu', () => { // The contents of the prefix are rendered before the item's children expect( screen.getByRole( 'menuitem', { - name: 'Item prefix Dropdown menu item', + name: 'Item prefix Menu item', } ) ).toBeInTheDocument(); } ); it( 'should display a suffix on regular items', async () => { render( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.Item suffix={ <>Item suffix</> }> - Dropdown menu item - </DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.Item suffix={ <>Item suffix</> }>Menu item</Menu.Item> + </Menu> ); // Click to open the menu @@ -990,22 +910,22 @@ describe( 'DropdownMenu', () => { // The contents of the suffix are rendered after the item's children expect( screen.getByRole( 'menuitem', { - name: 'Dropdown menu item Item suffix', + name: 'Menu item Item suffix', } ) ).toBeInTheDocument(); } ); it( 'should display a suffix on radio items', async () => { render( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.RadioItem + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.RadioItem name="radio-test" value="radio-one" suffix="Radio suffix" > Radio item one - </DropdownMenuV2.RadioItem> - </DropdownMenuV2> + </Menu.RadioItem> + </Menu> ); // Click to open the menu @@ -1025,15 +945,15 @@ describe( 'DropdownMenu', () => { it( 'should display a suffix on checkbox items', async () => { render( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.CheckboxItem + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.CheckboxItem name="checkbox-test" value="checkbox-one" suffix="Checkbox suffix" > Checkbox item one - </DropdownMenuV2.CheckboxItem> - </DropdownMenuV2> + </Menu.CheckboxItem> + </Menu> ); // Click to open the menu @@ -1055,10 +975,10 @@ describe( 'DropdownMenu', () => { describe( 'typeahead', () => { it( 'should highlight matching item', async () => { render( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.Item>One</DropdownMenuV2.Item> - <DropdownMenuV2.Item>Two</DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.Item>One</Menu.Item> + <Menu.Item>Two</Menu.Item> + </Menu> ); // Click to open the menu @@ -1088,10 +1008,10 @@ describe( 'DropdownMenu', () => { it( 'should keep previous focus when no matches are found', async () => { render( - <DropdownMenuV2 trigger={ <button>Open dropdown</button> }> - <DropdownMenuV2.Item>One</DropdownMenuV2.Item> - <DropdownMenuV2.Item>Two</DropdownMenuV2.Item> - </DropdownMenuV2> + <Menu trigger={ <button>Open dropdown</button> }> + <Menu.Item>One</Menu.Item> + <Menu.Item>Two</Menu.Item> + </Menu> ); // Click to open the menu diff --git a/packages/components/src/menu/types.ts b/packages/components/src/menu/types.ts index 795cd9ac76ff58..7b58cef241743e 100644 --- a/packages/components/src/menu/types.ts +++ b/packages/components/src/menu/types.ts @@ -4,9 +4,9 @@ import type * as Ariakit from '@ariakit/react'; import type { Placement } from '@floating-ui/react-dom'; -export interface DropdownMenuContext { +export interface MenuContext { /** - * The ariakit store shared across all DropdownMenu subcomponents. + * The ariakit store shared across all Menu subcomponents. */ store: Ariakit.MenuStore; /** @@ -15,33 +15,33 @@ export interface DropdownMenuContext { variant?: 'toolbar'; } -export interface DropdownMenuProps { +export interface MenuProps { /** - * The trigger button. + * The button triggering the menu popover. */ trigger: React.ReactElement; /** - * The contents of the dropdown. + * The contents of the menu (ie. one or more menu items). */ children?: React.ReactNode; /** - * The open state of the dropdown menu when it is initially rendered. Use when + * The open state of the menu popover when it is initially rendered. Use when * not wanting to control its open state. * * @default false */ defaultOpen?: boolean; /** - * The controlled open state of the dropdown menu. Must be used in conjunction + * The controlled open state of the menu popover. Must be used in conjunction * with `onOpenChange`. */ open?: boolean; /** - * Event handler called when the open state of the dropdown menu changes. + * Event handler called when the open state of the menu popover changes. */ onOpenChange?: ( open: boolean ) => void; /** - * The modality of the dropdown menu. When set to true, interaction with + * The modality of the menu popover. When set to true, interaction with * outside elements will be disabled and only menu content will be visible to * screen readers. * @@ -49,7 +49,7 @@ export interface DropdownMenuProps { */ modal?: boolean; /** - * The placement of the dropdown menu popover. + * The placement of the menu popover. * * @default 'bottom-start' for root-level menus, 'right-start' for nested menus */ @@ -80,21 +80,22 @@ export interface DropdownMenuProps { ) => boolean ); } -export interface DropdownMenuGroupProps { +export interface MenuGroupProps { /** - * The contents of the dropdown menu group. + * The contents of the menu group (ie. an optional menu group label and one + * or more menu items). */ children: React.ReactNode; } -export interface DropdownMenuGroupLabelProps { +export interface MenuGroupLabelProps { /** - * The contents of the dropdown menu group. + * The contents of the menu group label. */ children: React.ReactNode; } -export interface DropdownMenuItemProps { +export interface MenuItemProps { /** * The contents of the menu item. */ @@ -108,7 +109,7 @@ export interface DropdownMenuItemProps { */ suffix?: React.ReactNode; /** - * Whether to hide the parent menu when the item is clicked. + * Whether to hide the menu popover when the menu item is clicked. * * @default true */ @@ -119,10 +120,10 @@ export interface DropdownMenuItemProps { disabled?: boolean; } -export interface DropdownMenuCheckboxItemProps - extends Omit< DropdownMenuItemProps, 'prefix' | 'hideOnClick' > { +export interface MenuCheckboxItemProps + extends Omit< MenuItemProps, 'prefix' | 'hideOnClick' > { /** - * Whether to hide the dropdown menu when the item is clicked. + * Whether to hide the menu popover when the menu item is clicked. * * @default false */ @@ -151,10 +152,10 @@ export interface DropdownMenuCheckboxItemProps onChange?: ( event: React.ChangeEvent< HTMLInputElement > ) => void; } -export interface DropdownMenuRadioItemProps - extends Omit< DropdownMenuItemProps, 'prefix' | 'hideOnClick' > { +export interface MenuRadioItemProps + extends Omit< MenuItemProps, 'prefix' | 'hideOnClick' > { /** - * Whether to hide the dropdown menu when the item is clicked. + * Whether to hide the menu popover when the menu item is clicked. * * @default false */ @@ -182,4 +183,4 @@ export interface DropdownMenuRadioItemProps onChange?: ( event: React.ChangeEvent< HTMLInputElement > ) => void; } -export interface DropdownMenuSeparatorProps {} +export interface MenuSeparatorProps {} diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index 6d28765c2f685e..bea16b719a463d 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -3,7 +3,7 @@ */ import { positionToPlacement as __experimentalPopoverLegacyPositionToPlacement } from './popover/utils'; import { createPrivateSlotFill } from './slot-fill'; -import { DropdownMenuV2 } from './menu'; +import { Menu } from './menu'; import { ComponentsContext } from './context/context-system-provider'; import Theme from './theme'; import { Tabs } from './tabs'; @@ -17,6 +17,6 @@ lock( privateApis, { ComponentsContext, Tabs, Theme, - DropdownMenuV2, + Menu, kebabCase, } ); diff --git a/packages/components/src/toolbar/toolbar/index.tsx b/packages/components/src/toolbar/toolbar/index.tsx index ba2e8062aed85d..6b7f4843560fe7 100644 --- a/packages/components/src/toolbar/toolbar/index.tsx +++ b/packages/components/src/toolbar/toolbar/index.tsx @@ -40,6 +40,9 @@ function UnforwardedToolbar( Dropdown: { variant: 'toolbar', }, + Menu: { + variant: 'toolbar', + }, }; }, [ isVariantDefined ] ); diff --git a/packages/dataviews/src/components/dataviews-filters/add-filter.tsx b/packages/dataviews/src/components/dataviews-filters/add-filter.tsx index c8b6b5fda38fcc..94aebb71ea5874 100644 --- a/packages/dataviews/src/components/dataviews-filters/add-filter.tsx +++ b/packages/dataviews/src/components/dataviews-filters/add-filter.tsx @@ -19,7 +19,7 @@ import { forwardRef } from '@wordpress/element'; import { unlock } from '../../lock-unlock'; import type { NormalizedFilter, View } from '../../types'; -const { DropdownMenuV2 } = unlock( componentsPrivateApis ); +const { Menu } = unlock( componentsPrivateApis ); interface AddFilterProps { filters: NormalizedFilter[]; @@ -28,7 +28,7 @@ interface AddFilterProps { setOpenedFilter: ( filter: string | null ) => void; } -export function AddFilterDropdownMenu( { +export function AddFilterMenu( { filters, view, onChangeView, @@ -39,10 +39,10 @@ export function AddFilterDropdownMenu( { } ) { const inactiveFilters = filters.filter( ( filter ) => ! filter.isVisible ); return ( - <DropdownMenuV2 trigger={ trigger }> + <Menu trigger={ trigger }> { inactiveFilters.map( ( filter ) => { return ( - <DropdownMenuV2.Item + <Menu.Item key={ filter.field } onClick={ () => { setOpenedFilter( filter.field ); @@ -60,13 +60,11 @@ export function AddFilterDropdownMenu( { } ); } } > - <DropdownMenuV2.ItemLabel> - { filter.name } - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> + <Menu.ItemLabel>{ filter.name }</Menu.ItemLabel> + </Menu.Item> ); } ) } - </DropdownMenuV2> + </Menu> ); } @@ -79,7 +77,7 @@ function AddFilter( } const inactiveFilters = filters.filter( ( filter ) => ! filter.isVisible ); return ( - <AddFilterDropdownMenu + <AddFilterMenu trigger={ <Button accessibleWhenDisabled diff --git a/packages/dataviews/src/components/dataviews-filters/index.tsx b/packages/dataviews/src/components/dataviews-filters/index.tsx index 6a8545a021350e..9722844cf4a141 100644 --- a/packages/dataviews/src/components/dataviews-filters/index.tsx +++ b/packages/dataviews/src/components/dataviews-filters/index.tsx @@ -16,7 +16,7 @@ import { __, _x } from '@wordpress/i18n'; * Internal dependencies */ import FilterSummary from './filter-summary'; -import { default as AddFilter, AddFilterDropdownMenu } from './add-filter'; +import { default as AddFilter, AddFilterMenu } from './add-filter'; import ResetFilters from './reset-filters'; import DataViewsContext from '../dataviews-context'; import { sanitizeOperators } from '../../utils'; @@ -100,7 +100,7 @@ export function FilterVisibilityToggle( { } if ( ! hasVisibleFilters ) { return ( - <AddFilterDropdownMenu + <AddFilterMenu filters={ filters } view={ view } onChangeView={ onChangeViewWithFilterVisibility } diff --git a/packages/dataviews/src/components/dataviews-item-actions/index.tsx b/packages/dataviews/src/components/dataviews-item-actions/index.tsx index e33cb0fe56d0ed..20e58a2c6bb1fb 100644 --- a/packages/dataviews/src/components/dataviews-item-actions/index.tsx +++ b/packages/dataviews/src/components/dataviews-item-actions/index.tsx @@ -23,7 +23,7 @@ import { useRegistry } from '@wordpress/data'; import { unlock } from '../../lock-unlock'; import type { Action, ActionModal as ActionModalType } from '../../types'; -const { DropdownMenuV2, kebabCase } = unlock( componentsPrivateApis ); +const { Menu, kebabCase } = unlock( componentsPrivateApis ); export interface ActionTriggerProps< Item > { action: Action< Item >; @@ -43,7 +43,7 @@ interface ActionWithModalProps< Item > extends ActionModalProps< Item > { isBusy?: boolean; } -interface ActionsDropdownMenuGroupProps< Item > { +interface ActionsMenuGroupProps< Item > { actions: Action< Item >[]; item: Item; } @@ -77,7 +77,7 @@ function ButtonTrigger< Item >( { ); } -function DropdownMenuItemTrigger< Item >( { +function MenuItemTrigger< Item >( { action, onClick, items, @@ -85,12 +85,12 @@ function DropdownMenuItemTrigger< Item >( { const label = typeof action.label === 'string' ? action.label : action.label( items ); return ( - <DropdownMenuV2.Item + <Menu.Item onClick={ onClick } hideOnClick={ ! ( 'RenderModal' in action ) } > - <DropdownMenuV2.ItemLabel>{ label }</DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> + <Menu.ItemLabel>{ label }</Menu.ItemLabel> + </Menu.Item> ); } @@ -146,13 +146,13 @@ export function ActionWithModal< Item >( { ); } -export function ActionsDropdownMenuGroup< Item >( { +export function ActionsMenuGroup< Item >( { actions, item, -}: ActionsDropdownMenuGroupProps< Item > ) { +}: ActionsMenuGroupProps< Item > ) { const registry = useRegistry(); return ( - <DropdownMenuV2.Group> + <Menu.Group> { actions.map( ( action ) => { if ( 'RenderModal' in action ) { return ( @@ -160,12 +160,12 @@ export function ActionsDropdownMenuGroup< Item >( { key={ action.id } action={ action } items={ [ item ] } - ActionTrigger={ DropdownMenuItemTrigger } + ActionTrigger={ MenuItemTrigger } /> ); } return ( - <DropdownMenuItemTrigger + <MenuItemTrigger key={ action.id } action={ action } onClick={ () => { @@ -175,7 +175,7 @@ export function ActionsDropdownMenuGroup< Item >( { /> ); } ) } - </DropdownMenuV2.Group> + </Menu.Group> ); } @@ -245,7 +245,7 @@ function CompactItemActions< Item >( { actions, }: CompactItemActionsProps< Item > ) { return ( - <DropdownMenuV2 + <Menu trigger={ <Button size="compact" @@ -258,7 +258,7 @@ function CompactItemActions< Item >( { } placement="bottom-end" > - <ActionsDropdownMenuGroup actions={ actions } item={ item } /> - </DropdownMenuV2> + <ActionsMenuGroup actions={ actions } item={ item } /> + </Menu> ); } diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index 9824f9c8e8c6f6..c8b26c51275891 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -51,7 +51,7 @@ import DataViewsContext from '../dataviews-context'; import { unlock } from '../../lock-unlock'; import DensityPicker from '../../dataviews-layouts/grid/density-picker'; -const { DropdownMenuV2 } = unlock( componentsPrivateApis ); +const { Menu } = unlock( componentsPrivateApis ); interface ViewTypeMenuProps { defaultLayouts?: SupportedLayouts; @@ -69,7 +69,7 @@ function ViewTypeMenu( { } const activeView = VIEW_LAYOUTS.find( ( v ) => view.type === v.type ); return ( - <DropdownMenuV2 + <Menu trigger={ <Button size="compact" @@ -84,7 +84,7 @@ function ViewTypeMenu( { return null; } return ( - <DropdownMenuV2.RadioItem + <Menu.RadioItem key={ layout } value={ layout } name="view-actions-available-view" @@ -104,13 +104,11 @@ function ViewTypeMenu( { warning( 'Invalid dataview' ); } } > - <DropdownMenuV2.ItemLabel> - { config.label } - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.RadioItem> + <Menu.ItemLabel>{ config.label }</Menu.ItemLabel> + </Menu.RadioItem> ); } ) } - </DropdownMenuV2> + </Menu> ); } diff --git a/packages/dataviews/src/dataviews-layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx index e737b18f5b02a9..82f9b5ea4d4fc5 100644 --- a/packages/dataviews/src/dataviews-layouts/list/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/list/index.tsx @@ -32,7 +32,7 @@ import { useRegistry } from '@wordpress/data'; */ import { unlock } from '../../lock-unlock'; import { - ActionsDropdownMenuGroup, + ActionsMenuGroup, ActionModal, } from '../../components/dataviews-item-actions'; import type { Action, NormalizedField, ViewListProps } from '../../types'; @@ -49,7 +49,7 @@ interface ListViewItemProps< Item > { onDropdownTriggerKeyDown: React.KeyboardEventHandler< HTMLButtonElement >; } -const { DropdownMenuV2: DropdownMenu } = unlock( componentsPrivateApis ); +const { Menu } = unlock( componentsPrivateApis ); function generateItemWrapperCompositeId( idPrefix: string ) { return `${ idPrefix }-item-wrapper`; @@ -195,7 +195,7 @@ function ListItem< Item >( { /> ) } <div role="gridcell"> - <DropdownMenu + <Menu trigger={ <Composite.Item id={ generateDropdownTriggerCompositeId( @@ -215,11 +215,11 @@ function ListItem< Item >( { } placement="bottom-end" > - <ActionsDropdownMenuGroup + <ActionsMenuGroup actions={ eligibleActions } item={ item } /> - </DropdownMenu> + </Menu> </div> </HStack> ); diff --git a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx index aff211fb613dcf..7071e54620f369 100644 --- a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx @@ -29,7 +29,7 @@ import type { } from '../../types'; import { getVisibleFieldIds } from '../index'; -const { DropdownMenuV2 } = unlock( componentsPrivateApis ); +const { Menu } = unlock( componentsPrivateApis ); interface HeaderMenuProps< Item > { fieldId: string; @@ -40,12 +40,12 @@ interface HeaderMenuProps< Item > { setOpenedFilter: ( fieldId: string ) => void; } -function WithDropDownMenuSeparators( { children }: { children: ReactNode } ) { +function WithMenuSeparators( { children }: { children: ReactNode } ) { return Children.toArray( children ) .filter( Boolean ) .map( ( child, i ) => ( <Fragment key={ i }> - { i > 0 && <DropdownMenuV2.Separator /> } + { i > 0 && <Menu.Separator /> } { child } </Fragment> ) ); @@ -101,7 +101,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( } return ( - <DropdownMenuV2 + <Menu align="start" trigger={ <Button @@ -120,9 +120,9 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( } style={ { minWidth: '240px' } } > - <WithDropDownMenuSeparators> + <WithMenuSeparators> { isSortable && ( - <DropdownMenuV2.Group> + <Menu.Group> { SORTING_DIRECTIONS.map( ( direction: SortDirection ) => { const isChecked = @@ -133,7 +133,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( const value = `${ fieldId }-${ direction }`; return ( - <DropdownMenuV2.RadioItem + <Menu.RadioItem key={ value } // All sorting radio items share the same name, so that // selecting a sorting option automatically deselects the @@ -153,18 +153,18 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( } ); } } > - <DropdownMenuV2.ItemLabel> + <Menu.ItemLabel> { sortLabels[ direction ] } - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.RadioItem> + </Menu.ItemLabel> + </Menu.RadioItem> ); } ) } - </DropdownMenuV2.Group> + </Menu.Group> ) } { canAddFilter && ( - <DropdownMenuV2.Group> - <DropdownMenuV2.Item + <Menu.Group> + <Menu.Item prefix={ <Icon icon={ funnel } /> } onClick={ () => { setOpenedFilter( fieldId ); @@ -182,14 +182,14 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( } ); } } > - <DropdownMenuV2.ItemLabel> + <Menu.ItemLabel> { __( 'Add filter' ) } - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - </DropdownMenuV2.Group> + </Menu.ItemLabel> + </Menu.Item> + </Menu.Group> ) } - <DropdownMenuV2.Group> - <DropdownMenuV2.Item + <Menu.Group> + <Menu.Item prefix={ <Icon icon={ arrowLeft } /> } disabled={ index < 1 } onClick={ () => { @@ -207,11 +207,9 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( } ); } } > - <DropdownMenuV2.ItemLabel> - { __( 'Move left' ) } - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - <DropdownMenuV2.Item + <Menu.ItemLabel>{ __( 'Move left' ) }</Menu.ItemLabel> + </Menu.Item> + <Menu.Item prefix={ <Icon icon={ arrowRight } /> } disabled={ index >= visibleFieldIds.length - 1 } onClick={ () => { @@ -227,12 +225,10 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( } ); } } > - <DropdownMenuV2.ItemLabel> - { __( 'Move right' ) } - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> + <Menu.ItemLabel>{ __( 'Move right' ) }</Menu.ItemLabel> + </Menu.Item> { isHidable && field && ( - <DropdownMenuV2.Item + <Menu.Item prefix={ <Icon icon={ unseen } /> } onClick={ () => { onHide( field ); @@ -244,14 +240,14 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( } ); } } > - <DropdownMenuV2.ItemLabel> + <Menu.ItemLabel> { __( 'Hide column' ) } - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> + </Menu.ItemLabel> + </Menu.Item> ) } - </DropdownMenuV2.Group> - </WithDropDownMenuSeparators> - </DropdownMenuV2> + </Menu.Group> + </WithMenuSeparators> + </Menu> ); } ); diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js index 43418f9caf5eb6..25dcc69185cae6 100644 --- a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js @@ -27,7 +27,7 @@ import ConfirmDeleteFontSizeDialog from './confirm-delete-font-size-dialog'; import RenameFontSizeDialog from './rename-font-size-dialog'; import SizeControl from '../size-control'; -const { DropdownMenuV2 } = unlock( componentsPrivateApis ); +const { Menu } = unlock( componentsPrivateApis ); const { useGlobalSetting } = unlock( blockEditorPrivateApis ); function FontSize() { @@ -166,7 +166,7 @@ function FontSize() { marginBottom={ 0 } paddingX={ 4 } > - <DropdownMenuV2 + <Menu trigger={ <Button size="small" @@ -175,21 +175,17 @@ function FontSize() { /> } > - <DropdownMenuV2.Item - onClick={ toggleRenameDialog } - > - <DropdownMenuV2.ItemLabel> + <Menu.Item onClick={ toggleRenameDialog }> + <Menu.ItemLabel> { __( 'Rename' ) } - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - <DropdownMenuV2.Item - onClick={ toggleDeleteConfirm } - > - <DropdownMenuV2.ItemLabel> + </Menu.ItemLabel> + </Menu.Item> + <Menu.Item onClick={ toggleDeleteConfirm }> + <Menu.ItemLabel> { __( 'Delete' ) } - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - </DropdownMenuV2> + </Menu.ItemLabel> + </Menu.Item> + </Menu> </Spacer> </FlexItem> ) } diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-sizes.js b/packages/edit-site/src/components/global-styles/font-sizes/font-sizes.js index e09dda1a82fe81..4bda7a7b3266b5 100644 --- a/packages/edit-site/src/components/global-styles/font-sizes/font-sizes.js +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-sizes.js @@ -27,7 +27,7 @@ import { useState } from '@wordpress/element'; * Internal dependencies */ import { unlock } from '../../../lock-unlock'; -const { DropdownMenuV2 } = unlock( componentsPrivateApis ); +const { Menu } = unlock( componentsPrivateApis ); const { useGlobalSetting } = unlock( blockEditorPrivateApis ); import Subtitle from '../subtitle'; import { NavigationButtonAsItem } from '../navigation-button'; @@ -81,7 +81,7 @@ function FontSizeGroup( { /> ) } { !! handleResetFontSizes && ( - <DropdownMenuV2 + <Menu trigger={ <Button size="small" @@ -92,16 +92,14 @@ function FontSizeGroup( { /> } > - <DropdownMenuV2.Item - onClick={ toggleResetDialog } - > - <DropdownMenuV2.ItemLabel> + <Menu.Item onClick={ toggleResetDialog }> + <Menu.ItemLabel> { origin === 'custom' ? __( 'Remove font size presets' ) : __( 'Reset font size presets' ) } - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> - </DropdownMenuV2> + </Menu.ItemLabel> + </Menu.Item> + </Menu> ) } </FlexItem> </HStack> diff --git a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js index 7321e927fbbae3..127480ee5af497 100644 --- a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js +++ b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js @@ -51,7 +51,7 @@ import { } from './shadow-utils'; const { useGlobalSetting } = unlock( blockEditorPrivateApis ); -const { DropdownMenuV2 } = unlock( componentsPrivateApis ); +const { Menu } = unlock( componentsPrivateApis ); const customShadowMenuItems = [ { @@ -163,7 +163,7 @@ export default function ShadowsEditPanel() { <ScreenHeader title={ selectedShadow.name } /> <FlexItem> <Spacer marginTop={ 2 } marginBottom={ 0 } paddingX={ 4 }> - <DropdownMenuV2 + <Menu trigger={ <Button size="small" @@ -176,7 +176,7 @@ export default function ShadowsEditPanel() { ? customShadowMenuItems : presetShadowMenuItems ).map( ( item ) => ( - <DropdownMenuV2.Item + <Menu.Item key={ item.action } onClick={ () => onMenuClick( item.action ) } disabled={ @@ -185,12 +185,12 @@ export default function ShadowsEditPanel() { baseSelectedShadow.shadow } > - <DropdownMenuV2.ItemLabel> + <Menu.ItemLabel> { item.label } - </DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> + </Menu.ItemLabel> + </Menu.Item> ) ) } - </DropdownMenuV2> + </Menu> </Spacer> </FlexItem> </HStack> diff --git a/packages/editor/src/components/post-actions/index.js b/packages/editor/src/components/post-actions/index.js index 8a3850e8f547c1..9f39b1f3305aeb 100644 --- a/packages/editor/src/components/post-actions/index.js +++ b/packages/editor/src/components/post-actions/index.js @@ -18,7 +18,7 @@ import { store as coreStore } from '@wordpress/core-data'; import { unlock } from '../../lock-unlock'; import { usePostActions } from './actions'; -const { DropdownMenuV2, kebabCase } = unlock( componentsPrivateApis ); +const { Menu, kebabCase } = unlock( componentsPrivateApis ); export default function PostActions( { postType, postId, onActionPerformed } ) { const [ isActionsMenuOpen, setIsActionsMenuOpen ] = useState( false ); @@ -54,7 +54,7 @@ export default function PostActions( { postType, postId, onActionPerformed } ) { }, [ allActions, itemWithPermissions ] ); return ( - <DropdownMenuV2 + <Menu open={ isActionsMenuOpen } trigger={ <Button @@ -79,7 +79,7 @@ export default function PostActions( { postType, postId, onActionPerformed } ) { setIsActionsMenuOpen( false ); } } /> - </DropdownMenuV2> + </Menu> ); } @@ -93,12 +93,9 @@ function DropdownMenuItemTrigger( { action, onClick, items } ) { const label = typeof action.label === 'string' ? action.label : action.label( items ); return ( - <DropdownMenuV2.Item - onClick={ onClick } - hideOnClick={ ! action.RenderModal } - > - <DropdownMenuV2.ItemLabel>{ label }</DropdownMenuV2.ItemLabel> - </DropdownMenuV2.Item> + <Menu.Item onClick={ onClick } hideOnClick={ ! action.RenderModal }> + <Menu.ItemLabel>{ label }</Menu.ItemLabel> + </Menu.Item> ); } @@ -145,7 +142,7 @@ function ActionWithModal( { action, item, ActionTrigger, onClose } ) { // With an added onClose prop. function ActionsDropdownMenuGroup( { actions, item, onClose } ) { return ( - <DropdownMenuV2.Group> + <Menu.Group> { actions.map( ( action ) => { if ( action.RenderModal ) { return ( @@ -167,6 +164,6 @@ function ActionsDropdownMenuGroup( { actions, item, onClose } ) { /> ); } ) } - </DropdownMenuV2.Group> + </Menu.Group> ); } From bcdba599018c2b210ab1af789b21326bd53211b7 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 30 Oct 2024 01:27:34 +0900 Subject: [PATCH 1388/1908] PostTaxonomiesFlatTermSelector: Restore space between tag list and most used tags (#66566) * PostTaxonomiesFlatTermSelector: Restore space between tag list and most used tags * Update packages/editor/src/components/post-taxonomies/flat-term-selector.js Co-authored-by: Lena Morita <lena@jaguchi.com> --------- Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../post-taxonomies/flat-term-selector.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/components/post-taxonomies/flat-term-selector.js b/packages/editor/src/components/post-taxonomies/flat-term-selector.js index 5f581e898c953e..21a62c9819026d 100644 --- a/packages/editor/src/components/post-taxonomies/flat-term-selector.js +++ b/packages/editor/src/components/post-taxonomies/flat-term-selector.js @@ -2,8 +2,12 @@ * WordPress dependencies */ import { __, _x, sprintf } from '@wordpress/i18n'; -import { useEffect, useMemo, useState } from '@wordpress/element'; -import { FormTokenField, withFilters } from '@wordpress/components'; +import { Fragment, useEffect, useMemo, useState } from '@wordpress/element'; +import { + FormTokenField, + withFilters, + __experimentalVStack as VStack, +} from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import deprecated from '@wordpress/deprecated'; import { store as coreStore } from '@wordpress/core-data'; @@ -288,8 +292,15 @@ export function FlatTermSelector( { slug, __nextHasNoMarginBottom } ) { singularName ); + const Wrapper = ( { children } ) => + __nextHasNoMarginBottom ? ( + <VStack spacing={ 4 }>{ children }</VStack> + ) : ( + <Fragment>{ children }</Fragment> + ); + return ( - <> + <Wrapper> <FormTokenField __next40pxDefaultSize value={ values } @@ -306,7 +317,7 @@ export function FlatTermSelector( { slug, __nextHasNoMarginBottom } ) { __nextHasNoMarginBottom={ __nextHasNoMarginBottom } /> <MostUsedTerms taxonomy={ taxonomy } onSelect={ appendTerm } /> - </> + </Wrapper> ); } From aa7bb5aab3ba601afe4a3f887fb18150021bd437 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 30 Oct 2024 01:28:24 +0900 Subject: [PATCH 1389/1908] Fix zoom out shortcut on Windows (#66506) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: torounit <toro_unit@git.wordpress.org> --- packages/editor/src/components/zoom-out-toggle/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/zoom-out-toggle/index.js b/packages/editor/src/components/zoom-out-toggle/index.js index 81506add699c97..080a4c58578069 100644 --- a/packages/editor/src/components/zoom-out-toggle/index.js +++ b/packages/editor/src/components/zoom-out-toggle/index.js @@ -12,6 +12,7 @@ import { useShortcut, store as keyboardShortcutsStore, } from '@wordpress/keyboard-shortcuts'; +import { isAppleOS } from '@wordpress/keycodes'; /** * Internal dependencies @@ -40,7 +41,9 @@ const ZoomOutToggle = ( { disabled } ) => { category: 'global', description: __( 'Enter or exit zoom out.' ), keyCombination: { - modifier: 'primaryShift', + // `primaryShift+0` (`ctrl+shift+0`) is the shortcut for switching + // to input mode in Windows, so apply a different key combination. + modifier: isAppleOS() ? 'primaryShift' : 'secondary', character: '0', }, } ); From 6ffb6720e1edbfa7ccf8603ea31c66a1e7521423 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Tue, 29 Oct 2024 20:41:54 +0100 Subject: [PATCH 1390/1908] Interface: remove unused private API support (#66565) Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- package-lock.json | 1 - packages/interface/lock-unlock.js | 10 ---------- packages/interface/package.json | 1 - packages/private-apis/src/implementation.js | 1 - 4 files changed, 13 deletions(-) delete mode 100644 packages/interface/lock-unlock.js diff --git a/package-lock.json b/package-lock.json index a1060b1267af50..c3ffa28d21f3bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54605,7 +54605,6 @@ "@wordpress/icons": "*", "@wordpress/plugins": "*", "@wordpress/preferences": "*", - "@wordpress/private-apis": "*", "@wordpress/viewport": "*", "clsx": "^2.1.1" }, diff --git a/packages/interface/lock-unlock.js b/packages/interface/lock-unlock.js deleted file mode 100644 index 1e5bb39ed18c6d..00000000000000 --- a/packages/interface/lock-unlock.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * WordPress dependencies - */ -import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; - -export const { lock, unlock } = - __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', - '@wordpress/interface' - ); diff --git a/packages/interface/package.json b/packages/interface/package.json index e5870e0dfadfb2..ed9e0debf96d7c 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -43,7 +43,6 @@ "@wordpress/icons": "*", "@wordpress/plugins": "*", "@wordpress/preferences": "*", - "@wordpress/private-apis": "*", "@wordpress/viewport": "*", "clsx": "^2.1.1" }, diff --git a/packages/private-apis/src/implementation.js b/packages/private-apis/src/implementation.js index ab0ebfae7ecb05..b32a95986d32c9 100644 --- a/packages/private-apis/src/implementation.js +++ b/packages/private-apis/src/implementation.js @@ -25,7 +25,6 @@ const CORE_MODULES_USING_PRIVATE_APIS = [ '@wordpress/edit-widgets', '@wordpress/editor', '@wordpress/format-library', - '@wordpress/interface', '@wordpress/patterns', '@wordpress/preferences', '@wordpress/reusable-blocks', From 828868d680a4f052c35854d0ed0fb217179664b8 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 30 Oct 2024 07:24:47 +1100 Subject: [PATCH 1391/1908] Backport from Core: Reuse block metadata in WP_Theme_JSON::get_valid_block_style_variations() for better performance (#66539) * Backporting theme json performance optimizations from https://github.com/WordPress/wordpress-develop/pull/7586 * Tentatively backport using `get_blocks_metadata` instead of `WP_Block_Type_Registry` to get block names. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: mukeshpanchal27 <mukesh27@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- lib/class-wp-theme-json-gutenberg.php | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 5975e4fe9852ff..09f388e7d3b93f 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -745,10 +745,10 @@ public function __construct( $theme_json = array( 'version' => WP_Theme_JSON_Gut } $this->theme_json = WP_Theme_JSON_Schema_Gutenberg::migrate( $theme_json, $origin ); - $registry = WP_Block_Type_Registry::get_instance(); - $valid_block_names = array_keys( $registry->get_all_registered() ); + $blocks_metadata = static::get_blocks_metadata(); + $valid_block_names = array_keys( $blocks_metadata ); $valid_element_names = array_keys( static::ELEMENTS ); - $valid_variations = static::get_valid_block_style_variations(); + $valid_variations = static::get_valid_block_style_variations( $blocks_metadata ); $this->theme_json = static::unwrap_shared_block_style_variations( $this->theme_json, $valid_variations ); $this->theme_json = static::sanitize( $this->theme_json, $valid_block_names, $valid_element_names, $valid_variations ); $this->theme_json = static::maybe_opt_in_into_settings( $this->theme_json ); @@ -3506,9 +3506,10 @@ public static function remove_insecure_properties( $theme_json, $origin = 'theme $theme_json = WP_Theme_JSON_Schema_Gutenberg::migrate( $theme_json, $origin ); - $valid_block_names = array_keys( static::get_blocks_metadata() ); + $blocks_metadata = static::get_blocks_metadata(); + $valid_block_names = array_keys( $blocks_metadata ); $valid_element_names = array_keys( static::ELEMENTS ); - $valid_variations = static::get_valid_block_style_variations(); + $valid_variations = static::get_valid_block_style_variations( $blocks_metadata ); $theme_json = static::sanitize( $theme_json, $valid_block_names, $valid_element_names, $valid_variations ); @@ -4511,11 +4512,16 @@ function ( $matches ) use ( $variation_class ) { /** * Collects valid block style variations keyed by block type. * + * @since 6.6.0 + * @since 6.8.0 Added the `$blocks_metadata` parameter. + * + * @param array $blocks_metadata Optional. List of metadata per block. Default is the metadata for all blocks. * @return array Valid block style variations by block type. */ - protected static function get_valid_block_style_variations() { + protected static function get_valid_block_style_variations( $blocks_metadata = array() ) { $valid_variations = array(); - foreach ( self::get_blocks_metadata() as $block_name => $block_meta ) { + $blocks_metadata = empty( $blocks_metadata ) ? static::get_blocks_metadata() : $blocks_metadata; + foreach ( $blocks_metadata as $block_name => $block_meta ) { if ( ! isset( $block_meta['styleVariations'] ) ) { continue; } From 246258c765e8d44623e72fbb629a8c21b6e25650 Mon Sep 17 00:00:00 2001 From: Hiroshi Urabe <mail@torounit.com> Date: Wed, 30 Oct 2024 16:52:51 +0900 Subject: [PATCH 1392/1908] Fix Parent Check Condition in `buildTermsTree` (#66006) * Use undefined instead of null in `buildTermsTree` * allow null * use undefined * remove null checking --- packages/editor/src/utils/terms.js | 6 ++++-- packages/editor/src/utils/test/terms.js | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/editor/src/utils/terms.js b/packages/editor/src/utils/terms.js index 2d34879548a56c..e3154a6480a0fa 100644 --- a/packages/editor/src/utils/terms.js +++ b/packages/editor/src/utils/terms.js @@ -14,14 +14,16 @@ export function buildTermsTree( flatTerms ) { const flatTermsWithParentAndChildren = flatTerms.map( ( term ) => { return { children: [], - parent: null, + parent: undefined, ...term, }; } ); // All terms should have a `parent` because we're about to index them by it. if ( - flatTermsWithParentAndChildren.some( ( { parent } ) => parent === null ) + flatTermsWithParentAndChildren.some( + ( { parent } ) => parent === undefined + ) ) { return flatTermsWithParentAndChildren; } diff --git a/packages/editor/src/utils/test/terms.js b/packages/editor/src/utils/test/terms.js index 68a1a7f10fb190..fa7d1622370c7a 100644 --- a/packages/editor/src/utils/test/terms.js +++ b/packages/editor/src/utils/test/terms.js @@ -4,14 +4,14 @@ import { buildTermsTree } from '../terms'; describe( 'buildTermsTree()', () => { - it( 'Should return same array as input with null parent and empty children added if parent is never specified.', () => { + it( 'Should return same array as input with undefined parent and empty children added if parent is never specified.', () => { const input = Object.freeze( [ { id: 2232, dummy: true }, { id: 2245, dummy: true }, ] ); const output = Object.freeze( [ - { id: 2232, parent: null, children: [], dummy: true }, - { id: 2245, parent: null, children: [], dummy: true }, + { id: 2232, parent: undefined, children: [], dummy: true }, + { id: 2245, parent: undefined, children: [], dummy: true }, ] ); const termsTreem = buildTermsTree( input ); expect( termsTreem ).toEqual( output ); From 49a931897ac2a5d438f05dbaaa59ceedab71a0f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 30 Oct 2024 09:45:30 +0100 Subject: [PATCH 1393/1908] Templates: hide mediaField in list view if not provided (#66573) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../dataviews/src/dataviews-layouts/list/index.tsx | 12 +++++------- .../dataviews/src/dataviews-layouts/list/style.scss | 6 ------ .../edit-site/src/components/page-templates/index.js | 1 - 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/packages/dataviews/src/dataviews-layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx index 82f9b5ea4d4fc5..a4f94e482c69b3 100644 --- a/packages/dataviews/src/dataviews-layouts/list/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/list/index.tsx @@ -176,10 +176,10 @@ function ListItem< Item >( { }, [ actions, item ] ); const renderedMediaField = mediaField?.render ? ( - <mediaField.render item={ item } /> - ) : ( - <div className="dataviews-view-list__media-placeholder"></div> - ); + <div className="dataviews-view-list__media-wrapper"> + <mediaField.render item={ item } /> + </div> + ) : null; const renderedPrimaryField = primaryField?.render ? ( <primaryField.render item={ item } /> @@ -248,9 +248,7 @@ function ListItem< Item >( { /> </div> <HStack spacing={ 3 } justify="start" alignment="flex-start"> - <div className="dataviews-view-list__media-wrapper"> - { renderedMediaField } - </div> + { renderedMediaField } <VStack spacing={ 1 } className="dataviews-view-list__field-wrapper" diff --git a/packages/dataviews/src/dataviews-layouts/list/style.scss b/packages/dataviews/src/dataviews-layouts/list/style.scss index 429f2397c96019..8fe048cab77b51 100644 --- a/packages/dataviews/src/dataviews-layouts/list/style.scss +++ b/packages/dataviews/src/dataviews-layouts/list/style.scss @@ -144,12 +144,6 @@ ul.dataviews-view-list { } } - .dataviews-view-list__media-placeholder { - width: $grid-unit-05 * 13; - height: $grid-unit-05 * 13; - background-color: $gray-200; - } - .dataviews-view-list__field-wrapper { min-height: $grid-unit-05 * 13; // Ensures title is centrally aligned when all fields are hidden flex-grow: 1; diff --git a/packages/edit-site/src/components/page-templates/index.js b/packages/edit-site/src/components/page-templates/index.js index 5ffc2477337935..ea026ca53566e8 100644 --- a/packages/edit-site/src/components/page-templates/index.js +++ b/packages/edit-site/src/components/page-templates/index.js @@ -74,7 +74,6 @@ const defaultLayouts = { fields: [ 'title', 'description', 'author' ], layout: { primaryField: 'title', - mediaField: 'preview', }, }, }; From e6bdfd5fbaf0604ea837a6463154ce88b9f15859 Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Wed, 30 Oct 2024 11:22:32 +0100 Subject: [PATCH 1394/1908] QuickEdit: Add Parent field (#66527) * Data Views: Add Parent field * add comment * improve documentation * fix preview * use number type * enable sorting * move logic in the useMemo function * consolidate data.parent in one variable Co-authored-by: gigitux <gigitux@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- package-lock.json | 3 +- .../src/components/post-edit/index.js | 1 + .../src/components/post-fields/index.js | 3 +- packages/fields/README.md | 4 + packages/fields/package.json | 3 +- packages/fields/src/fields/index.ts | 1 + packages/fields/src/fields/parent/index.ts | 27 ++ .../fields/src/fields/parent/parent-edit.tsx | 348 ++++++++++++++++++ .../fields/src/fields/parent/parent-view.tsx | 33 ++ packages/fields/src/fields/parent/utils.ts | 18 + 10 files changed, 438 insertions(+), 3 deletions(-) create mode 100644 packages/fields/src/fields/parent/index.ts create mode 100644 packages/fields/src/fields/parent/parent-edit.tsx create mode 100644 packages/fields/src/fields/parent/parent-view.tsx create mode 100644 packages/fields/src/fields/parent/utils.ts diff --git a/package-lock.json b/package-lock.json index c3ffa28d21f3bf..99cbae41c6fac8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54467,7 +54467,8 @@ "@wordpress/url": "*", "@wordpress/warning": "*", "change-case": "4.1.2", - "client-zip": "^2.4.5" + "client-zip": "^2.4.5", + "remove-accents": "^0.5.0" }, "engines": { "node": ">=18.12.0", diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index b9d3f60ef5da2b..a2b3007757e42b 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -66,6 +66,7 @@ function PostEditForm( { postType, postId } ) { 'author', 'date', 'slug', + 'parent', 'comment_status', ], }; diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index a921799aabbea2..7a52b05321794b 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -8,7 +8,7 @@ import clsx from 'clsx'; */ import { __, sprintf } from '@wordpress/i18n'; import { decodeEntities } from '@wordpress/html-entities'; -import { featuredImageField, slugField } from '@wordpress/fields'; +import { featuredImageField, slugField, parentField } from '@wordpress/fields'; import { createInterpolateElement, useMemo, @@ -321,6 +321,7 @@ function usePostFields( viewType ) { }, }, slugField, + parentField, { id: 'comment_status', label: __( 'Discussion' ), diff --git a/packages/fields/README.md b/packages/fields/README.md index 0a891f9b07420c..5fd1031b50fe23 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -46,6 +46,10 @@ Undocumented declaration. Undocumented declaration. +### parentField + +This field is used to display the post parent. + ### permanentlyDeletePost Undocumented declaration. diff --git a/packages/fields/package.json b/packages/fields/package.json index 43772cb41981a5..acb01dd1882eba 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -54,7 +54,8 @@ "@wordpress/url": "*", "@wordpress/warning": "*", "change-case": "4.1.2", - "client-zip": "^2.4.5" + "client-zip": "^2.4.5", + "remove-accents": "^0.5.0" }, "peerDependencies": { "react": "^18.0.0" diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts index 24655a3d866cfd..9f1abef0417f42 100644 --- a/packages/fields/src/fields/index.ts +++ b/packages/fields/src/fields/index.ts @@ -2,3 +2,4 @@ export { default as slugField } from './slug'; export { default as titleField } from './title'; export { default as orderField } from './order'; export { default as featuredImageField } from './featured-image'; +export { default as parentField } from './parent'; diff --git a/packages/fields/src/fields/parent/index.ts b/packages/fields/src/fields/parent/index.ts new file mode 100644 index 00000000000000..2476d071b81652 --- /dev/null +++ b/packages/fields/src/fields/parent/index.ts @@ -0,0 +1,27 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import { __ } from '@wordpress/i18n'; +import { ParentEdit } from './parent-edit'; +import { ParentView } from './parent-view'; + +const parentField: Field< BasePost > = { + id: 'parent', + type: 'text', + label: __( 'Parent' ), + getValue: ( { item } ) => item.parent, + Edit: ParentEdit, + render: ParentView, + enableSorting: true, +}; + +/** + * This field is used to display the post parent. + */ +export default parentField; diff --git a/packages/fields/src/fields/parent/parent-edit.tsx b/packages/fields/src/fields/parent/parent-edit.tsx new file mode 100644 index 00000000000000..030287b8f8fc55 --- /dev/null +++ b/packages/fields/src/fields/parent/parent-edit.tsx @@ -0,0 +1,348 @@ +/** + * WordPress dependencies + */ +import { ComboboxControl, ExternalLink } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; +import { + createInterpolateElement, + useCallback, + useMemo, + useState, +} from '@wordpress/element'; +// @ts-ignore +import { store as coreStore } from '@wordpress/core-data'; +import type { DataFormControlProps } from '@wordpress/dataviews'; + +/** + * External dependencies + */ +import removeAccents from 'remove-accents'; + +/** + * Internal dependencies + */ +import { debounce } from '@wordpress/compose'; +import { decodeEntities } from '@wordpress/html-entities'; +import { __, sprintf } from '@wordpress/i18n'; +import type { BasePost } from '../../types'; +import { getTitleWithFallbackName } from './utils'; +import { filterURLForDisplay } from '@wordpress/url'; + +type TreeBase = { + id: number; + name: string; + [ key: string ]: any; +}; + +type TreeWithParent = TreeBase & { + parent: number; +}; + +type TreeWithoutParent = TreeBase & { + parent: null; +}; + +type Tree = TreeWithParent | TreeWithoutParent; + +function buildTermsTree( flatTerms: Tree[] ) { + const flatTermsWithParentAndChildren = flatTerms.map( ( term ) => { + return { + children: [], + ...term, + }; + } ); + + // All terms should have a `parent` because we're about to index them by it. + if ( + flatTermsWithParentAndChildren.some( + ( { parent } ) => parent === null || parent === undefined + ) + ) { + return flatTermsWithParentAndChildren as TreeWithParent[]; + } + + const termsByParent = ( + flatTermsWithParentAndChildren as TreeWithParent[] + ).reduce( + ( acc, term ) => { + const { parent } = term; + if ( ! acc[ parent ] ) { + acc[ parent ] = []; + } + acc[ parent ].push( term ); + return acc; + }, + {} as Record< string, Array< TreeWithParent > > + ); + + const fillWithChildren = ( + terms: Array< TreeWithParent > + ): Array< TreeWithParent > => { + return terms.map( ( term ) => { + const children = termsByParent[ term.id ]; + return { + ...term, + children: + children && children.length + ? fillWithChildren( children ) + : [], + }; + } ); + }; + + return fillWithChildren( termsByParent[ '0' ] || [] ); +} + +export const getItemPriority = ( name: string, searchValue: string ) => { + const normalizedName = removeAccents( name || '' ).toLowerCase(); + const normalizedSearch = removeAccents( searchValue || '' ).toLowerCase(); + if ( normalizedName === normalizedSearch ) { + return 0; + } + + if ( normalizedName.startsWith( normalizedSearch ) ) { + return normalizedName.length; + } + + return Infinity; +}; + +export function PageAttributesParent( { + data, + onChangeControl, +}: { + data: BasePost; + onChangeControl: ( newValue: number ) => void; +} ) { + const [ fieldValue, setFieldValue ] = useState< null | string >( null ); + + const pageId = data.parent; + const postId = data.id; + const postTypeSlug = data.type; + + const { parentPostTitle, pageItems, isHierarchical } = useSelect( + ( select ) => { + // @ts-expect-error getPostType is not typed + const { getEntityRecord, getEntityRecords, getPostType } = + select( coreStore ); + + const postTypeInfo = getPostType( postTypeSlug ); + + const postIsHierarchical = + postTypeInfo?.hierarchical && postTypeInfo.viewable; + + const parentPost = pageId + ? getEntityRecord< BasePost >( + 'postType', + postTypeSlug, + pageId + ) + : null; + + const query = { + per_page: 100, + exclude: postId, + parent_exclude: postId, + orderby: 'menu_order', + order: 'asc', + _fields: 'id,title,parent', + ...( fieldValue !== null && { + search: fieldValue, + } ), + }; + + return { + isHierarchical: postIsHierarchical, + parentPostTitle: parentPost + ? getTitleWithFallbackName( parentPost ) + : '', + pageItems: postIsHierarchical + ? getEntityRecords< BasePost >( + 'postType', + postTypeSlug, + query + ) + : null, + }; + }, + [ fieldValue, pageId, postId, postTypeSlug ] + ); + + /** + * This logic has been copied from https://github.com/WordPress/gutenberg/blob/0249771b519d5646171fb9fae422006c8ab773f2/packages/editor/src/components/page-attributes/parent.js#L106. + */ + const parentOptions = useMemo( () => { + const getOptionsFromTree = ( + tree: Array< Tree >, + level = 0 + ): Array< { + value: number; + label: string; + rawName: string; + } > => { + const mappedNodes = tree.map( ( treeNode ) => [ + { + value: treeNode.id, + label: + '— '.repeat( level ) + decodeEntities( treeNode.name ), + rawName: treeNode.name, + }, + ...getOptionsFromTree( treeNode.children || [], level + 1 ), + ] ); + + const sortedNodes = mappedNodes.sort( ( [ a ], [ b ] ) => { + const priorityA = getItemPriority( + a.rawName, + fieldValue ?? '' + ); + const priorityB = getItemPriority( + b.rawName, + fieldValue ?? '' + ); + return priorityA >= priorityB ? 1 : -1; + } ); + + return sortedNodes.flat(); + }; + + if ( ! pageItems ) { + return []; + } + + let tree = pageItems.map( ( item ) => ( { + id: item.id as number, + parent: item.parent ?? null, + name: getTitleWithFallbackName( item ), + } ) ); + + // Only build a hierarchical tree when not searching. + if ( ! fieldValue ) { + tree = buildTermsTree( tree ); + } + + const opts = getOptionsFromTree( tree ); + + // Ensure the current parent is in the options list. + const optsHasParent = opts.find( ( item ) => item.value === pageId ); + if ( pageId && parentPostTitle && ! optsHasParent ) { + opts.unshift( { + value: pageId, + label: parentPostTitle, + rawName: '', + } ); + } + return opts.map( ( option ) => ( { + ...option, + value: option.value.toString(), + } ) ); + }, [ pageItems, fieldValue, parentPostTitle, pageId ] ); + + if ( ! isHierarchical ) { + return null; + } + + /** + * Handle user input. + * + * @param {string} inputValue The current value of the input field. + */ + const handleKeydown = ( inputValue: string ) => { + setFieldValue( inputValue ); + }; + + /** + * Handle author selection. + * + * @param {Object} selectedPostId The selected Author. + */ + const handleChange = ( selectedPostId: string | null | undefined ) => { + if ( selectedPostId ) { + return onChangeControl( parseInt( selectedPostId, 10 ) ?? 0 ); + } + + onChangeControl( 0 ); + }; + + return ( + <ComboboxControl + __nextHasNoMarginBottom + __next40pxDefaultSize + label={ __( 'Parent' ) } + help={ __( 'Choose a parent page.' ) } + value={ pageId?.toString() } + options={ parentOptions } + onFilterValueChange={ debounce( + ( value: unknown ) => handleKeydown( value as string ), + 300 + ) } + onChange={ handleChange } + hideLabelFromVision + /> + ); +} + +export const ParentEdit = ( { + data, + field, + onChange, +}: DataFormControlProps< BasePost > ) => { + const { id } = field; + + const homeUrl = useSelect( ( select ) => { + // @ts-expect-error getEntityRecord is not typed with unstableBase as argument. + return select( coreStore ).getEntityRecord< { + home: string; + } >( 'root', '__unstableBase' )?.home as string; + }, [] ); + + const onChangeControl = useCallback( + ( newValue?: number ) => + onChange( { + [ id ]: newValue, + } ), + [ id, onChange ] + ); + + return ( + <fieldset className="fields-controls__parent"> + <div> + { createInterpolateElement( + sprintf( + /* translators: %1$s The home URL of the WordPress installation without the scheme. */ + __( + 'Child pages inherit characteristics from their parent, such as URL structure. For instance, if "Pricing" is a child of "Services", its URL would be %1$s<wbr />/services<wbr />/pricing.' + ), + filterURLForDisplay( homeUrl ).replace( + /([/.])/g, + '<wbr />$1' + ) + ), + { + wbr: <wbr />, + } + ) } + <p> + { createInterpolateElement( + __( + 'They also show up as sub-items in the default navigation menu. <a>Learn more.</a>' + ), + { + a: ( + <ExternalLink + href={ __( + 'https://wordpress.org/documentation/article/page-post-settings-sidebar/#page-attributes' + ) } + children={ undefined } + /> + ), + } + ) } + </p> + <PageAttributesParent + data={ data } + onChangeControl={ onChangeControl } + /> + </div> + </fieldset> + ); +}; diff --git a/packages/fields/src/fields/parent/parent-view.tsx b/packages/fields/src/fields/parent/parent-view.tsx new file mode 100644 index 00000000000000..f0d449db726c32 --- /dev/null +++ b/packages/fields/src/fields/parent/parent-view.tsx @@ -0,0 +1,33 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import type { DataViewRenderFieldProps } from '@wordpress/dataviews'; +import { getTitleWithFallbackName } from './utils'; +import { __ } from '@wordpress/i18n'; + +export const ParentView = ( { + item, +}: DataViewRenderFieldProps< BasePost > ) => { + const parent = useSelect( + ( select ) => { + const { getEntityRecord } = select( coreStore ); + return item?.parent + ? getEntityRecord( 'postType', item.type, item.parent ) + : null; + }, + [ item.parent, item.type ] + ); + + if ( parent ) { + return <>{ getTitleWithFallbackName( parent ) }</>; + } + + return <>{ __( 'None' ) }</>; +}; diff --git a/packages/fields/src/fields/parent/utils.ts b/packages/fields/src/fields/parent/utils.ts new file mode 100644 index 00000000000000..e69fd981305bd5 --- /dev/null +++ b/packages/fields/src/fields/parent/utils.ts @@ -0,0 +1,18 @@ +/** + * WordPress dependencies + */ +import { decodeEntities } from '@wordpress/html-entities'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; + +export function getTitleWithFallbackName( post: BasePost ) { + return typeof post.title === 'object' && + 'rendered' in post.title && + post.title.rendered + ? decodeEntities( post.title.rendered ) + : `#${ post?.id } (${ __( 'no title' ) })`; +} From b95553fa799847f91833ed8603cebf894b54e251 Mon Sep 17 00:00:00 2001 From: Carolina Nymark <myazalea@hotmail.com> Date: Wed, 30 Oct 2024 12:00:50 +0100 Subject: [PATCH 1395/1908] Backport from WordPres core: Improvements for the post format query loop filter (#66037) This pull request copies changes that were made in WordPress core in https://github.com/WordPress/wordpress-develop/pull/7314/: The pull request that added the PHP changes related to https://github.com/WordPress/gutenberg/pull/64167. - Improved logic for the use of the `AND` `relation` key when a user queries for both a format and a taxonomy. - Improved inline documentation, for clarity and readability. - Improved validation of the queried formats against the registered formats. - Misc: renaming of variables for better readability. Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- lib/compat/wordpress-6.7/blocks.php | 62 +++++++++++++------ ...ss-gutenberg-rest-posts-controller-6-7.php | 38 +++++++----- 2 files changed, 65 insertions(+), 35 deletions(-) diff --git a/lib/compat/wordpress-6.7/blocks.php b/lib/compat/wordpress-6.7/blocks.php index 6b9526f8056fd3..1a8e7f5741c0a1 100644 --- a/lib/compat/wordpress-6.7/blocks.php +++ b/lib/compat/wordpress-6.7/blocks.php @@ -59,34 +59,46 @@ function gutenberg_add_format_query_vars_to_query_loop_block( $query, $block ) { return $query; } - $formats = $block->context['query']['format']; - $tax_query = array( 'relation' => 'OR' ); + $formats = $block->context['query']['format']; + /* + * Validate that the format is either `standard` or a supported post format. + * - First, add `standard` to the array of valid formats. + * - Then, remove any invalid formats. + */ + $valid_formats = array_merge( array( 'standard' ), get_post_format_slugs() ); + $formats = array_intersect( $formats, $valid_formats ); - // The default post format, 'standard', is not stored in the database. - // If 'standard' is part of the request, the query needs to exclude all post items that - // have a format assigned. + /* + * The relation needs to be set to `OR` since the request can contain + * two separate conditions. The user may be querying for items that have + * either the `standard` format or a specific format. + */ + $formats_query = array( 'relation' => 'OR' ); + + /* + * The default post format, `standard`, is not stored in the database. + * If `standard` is part of the request, the query needs to exclude all post items that + * have a format assigned. + */ if ( in_array( 'standard', $formats, true ) ) { - $tax_query[] = array( + $formats_query[] = array( 'taxonomy' => 'post_format', 'field' => 'slug', - 'terms' => array(), 'operator' => 'NOT EXISTS', ); - // Remove the standard format, since it cannot be queried. + // Remove the `standard` format, since it cannot be queried. unset( $formats[ array_search( 'standard', $formats, true ) ] ); } - - // Add any remaining formats to the tax query. + // Add any remaining formats to the formats query. if ( ! empty( $formats ) ) { - // Add the post-format- prefix. - $terms = array_map( + // Add the `post-format-` prefix. + $terms = array_map( static function ( $format ) { - return 'post-format-' . $format; + return "post-format-$format"; }, $formats ); - - $tax_query[] = array( + $formats_query[] = array( 'taxonomy' => 'post_format', 'field' => 'slug', 'terms' => $terms, @@ -94,10 +106,22 @@ static function ( $format ) { ); } - // This condition is intended to prevent $tax_query from being added to $query - // if it only contains the relation. - if ( count( $tax_query ) > 1 ) { - $query['tax_query'][] = $tax_query; + /* + * Add `$formats_query` to `$query`, as long as it contains more than one key: + * If `$formats_query` only contains the initial `relation` key, there are no valid formats to query, + * and the query should not be modified. + */ + if ( count( $formats_query ) > 1 ) { + // Enable filtering by both post formats and other taxonomies by combining them with `AND`. + if ( empty( $query['tax_query'] ) ) { + $query['tax_query'] = $formats_query; + } else { + $query['tax_query'] = array( + 'relation' => 'AND', + $query['tax_query'], + $formats_query, + ); + } } return $query; diff --git a/lib/compat/wordpress-6.7/class-gutenberg-rest-posts-controller-6-7.php b/lib/compat/wordpress-6.7/class-gutenberg-rest-posts-controller-6-7.php index c7de4371c94f56..5d3795cf68db76 100644 --- a/lib/compat/wordpress-6.7/class-gutenberg-rest-posts-controller-6-7.php +++ b/lib/compat/wordpress-6.7/class-gutenberg-rest-posts-controller-6-7.php @@ -157,34 +157,40 @@ public function get_items( $request ) { $args = $this->prepare_tax_query( $args, $request ); if ( ! empty( $request['format'] ) ) { - $formats = $request['format']; - $tax_query = array( 'relation' => 'OR' ); - - // The default post format, 'standard', is not stored in the database. - // If 'standard' is part of the request, the query needs to exclude all post items that - // have a format assigned. + $formats = $request['format']; + /* + * The relation needs to be set to `OR` since the request can contain + * two separate conditions. The user may be querying for items that have + * either the `standard` format or a specific format. + */ + $formats_query = array( 'relation' => 'OR' ); + + /* + * The default post format, `standard`, is not stored in the database. + * If `standard` is part of the request, the query needs to exclude all post items that + * have a format assigned. + */ if ( in_array( 'standard', $formats, true ) ) { - $tax_query[] = array( + $formats_query[] = array( 'taxonomy' => 'post_format', 'field' => 'slug', - 'terms' => array(), 'operator' => 'NOT EXISTS', ); - // Remove the standard format, since it cannot be queried. + // Remove the `standard` format, since it cannot be queried. unset( $formats[ array_search( 'standard', $formats, true ) ] ); } - // Add any remaining formats to the tax query. + // Add any remaining formats to the formats query. if ( ! empty( $formats ) ) { - // Add the post-format- prefix. + // Add the `post-format-` prefix. $terms = array_map( static function ( $format ) { - return 'post-format-' . $format; + return "post-format-$format"; }, $formats ); - $tax_query[] = array( + $formats_query[] = array( 'taxonomy' => 'post_format', 'field' => 'slug', 'terms' => $terms, @@ -192,14 +198,14 @@ static function ( $format ) { ); } - // Enable filtering by both post formats and other taxonomies by combining them with AND. + // Enable filtering by both post formats and other taxonomies by combining them with `AND`. if ( isset( $args['tax_query'] ) ) { $args['tax_query'][] = array( 'relation' => 'AND', - $tax_query, + $formats_query, ); } else { - $args['tax_query'] = $tax_query; + $args['tax_query'] = $formats_query; } } From f0ef1acc9326647b2f1b04231cfcdcd3055066cb Mon Sep 17 00:00:00 2001 From: Rinkal Pagdar <92097119+rinkalpagdar@users.noreply.github.com> Date: Wed, 30 Oct 2024 17:19:58 +0530 Subject: [PATCH 1396/1908] Inline Commenting: Disable comments on published posts for now (#66583) Co-authored-by: rinkalpagdar <rinkalpagdar@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/editor/src/components/collab-sidebar/index.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/collab-sidebar/index.js b/packages/editor/src/components/collab-sidebar/index.js index 482bf3d4081ed1..8c7a710bce308a 100644 --- a/packages/editor/src/components/collab-sidebar/index.js +++ b/packages/editor/src/components/collab-sidebar/index.js @@ -62,6 +62,11 @@ export default function CollabSidebar() { }; }, [] ); + const postStatus = useSelect( ( select ) => { + const post = select( editorStore ).getCurrentPost(); + return { postStatus: post?.status }; + }, [] ); + const threads = useSelect( ( select ) => { if ( ! postId ) { @@ -259,7 +264,10 @@ export default function CollabSidebar() { }, [ postId, clientId ] ); // Check if the experimental flag is enabled. - if ( ! isBlockCommentExperimentEnabled ) { + if ( + ! isBlockCommentExperimentEnabled || + postStatus.postStatus === 'publish' + ) { return null; // or maybe return some message indicating no threads are available. } From 5432049fcaacd4a626ea8ff981520515e29a5fae Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 30 Oct 2024 15:58:37 +0400 Subject: [PATCH 1397/1908] Core Data: Add the 'getEntitiesConfig' resolver (#65871) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/core-data/src/actions.js | 20 +-- packages/core-data/src/entities.js | 64 --------- .../src/hooks/test/use-entity-record.js | 11 +- packages/core-data/src/resolvers.js | 86 ++++++++---- packages/core-data/src/test/actions.js | 63 ++++----- packages/core-data/src/test/entities.js | 80 ----------- packages/core-data/src/test/resolvers.js | 124 +++++++++++++----- 7 files changed, 189 insertions(+), 259 deletions(-) diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index e83ad02828cfe7..13cbba39e11765 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -16,7 +16,7 @@ import deprecated from '@wordpress/deprecated'; */ import { getNestedValue, setNestedValue } from './utils'; import { receiveItems, removeItems, receiveQueriedItems } from './queried-data'; -import { getOrLoadEntitiesConfig, DEFAULT_ENTITY_KEY } from './entities'; +import { DEFAULT_ENTITY_KEY } from './entities'; import { createBatch } from './batch'; import { STORE_NAME } from './name'; import { getSyncProvider } from './sync'; @@ -285,8 +285,8 @@ export const deleteEntityRecord = query, { __unstableFetch = apiFetch, throwOnError = false } = {} ) => - async ( { dispatch } ) => { - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + async ( { dispatch, resolveSelect } ) => { + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.kind === kind && config.name === name ); @@ -503,7 +503,7 @@ export const saveEntityRecord = } = {} ) => async ( { select, resolveSelect, dispatch } ) => { - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.kind === kind && config.name === name ); @@ -780,11 +780,11 @@ export const __experimentalBatch = */ export const saveEditedEntityRecord = ( kind, name, recordId, options ) => - async ( { select, dispatch } ) => { + async ( { select, dispatch, resolveSelect } ) => { if ( ! select.hasEditsForEntityRecord( kind, name, recordId ) ) { return; } - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.kind === kind && config.name === name ); @@ -813,7 +813,7 @@ export const saveEditedEntityRecord = */ export const __experimentalSaveSpecifiedEntityEdits = ( kind, name, recordId, itemsToSave, options ) => - async ( { select, dispatch } ) => { + async ( { select, dispatch, resolveSelect } ) => { if ( ! select.hasEditsForEntityRecord( kind, name, recordId ) ) { return; } @@ -828,7 +828,7 @@ export const __experimentalSaveSpecifiedEntityEdits = setNestedValue( editsToSave, item, getNestedValue( edits, item ) ); } - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.kind === kind && config.name === name ); @@ -973,8 +973,8 @@ export function receiveDefaultTemplateId( query, templateId ) { */ export const receiveRevisions = ( kind, name, recordKey, records, query, invalidateCache = false, meta ) => - async ( { dispatch } ) => { - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + async ( { dispatch, resolveSelect } ) => { + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.kind === kind && config.name === name ); diff --git a/packages/core-data/src/entities.js b/packages/core-data/src/entities.js index 8d09402087cf90..f73239e9afbbe5 100644 --- a/packages/core-data/src/entities.js +++ b/packages/core-data/src/entities.js @@ -10,14 +10,7 @@ import apiFetch from '@wordpress/api-fetch'; import { __ } from '@wordpress/i18n'; import { RichTextData } from '@wordpress/rich-text'; -/** - * Internal dependencies - */ -import { addEntities } from './actions'; -import { getSyncProvider } from './sync'; - export const DEFAULT_ENTITY_KEY = 'id'; - const POST_RAW_ATTRIBUTES = [ 'title', 'excerpt', 'content' ]; export const rootEntitiesConfig = [ @@ -458,60 +451,3 @@ export const getMethodName = ( kind, name, prefix = 'get' ) => { const suffix = pascalCase( name ); return `${ prefix }${ kindPrefix }${ suffix }`; }; - -function registerSyncConfigs( configs ) { - configs.forEach( ( { syncObjectType, syncConfig } ) => { - getSyncProvider().register( syncObjectType, syncConfig ); - const editSyncConfig = { ...syncConfig }; - delete editSyncConfig.fetch; - getSyncProvider().register( syncObjectType + '--edit', editSyncConfig ); - } ); -} - -/** - * Loads the entities into the store. - * - * Note: The `name` argument is used for `root` entities requiring additional server data. - * - * @param {string} kind Kind - * @param {string} name Name - * @return {(thunkArgs: object) => Promise<Array>} Entities - */ -export const getOrLoadEntitiesConfig = - ( kind, name ) => - async ( { select, dispatch } ) => { - let configs = select.getEntitiesConfig( kind ); - const hasConfig = !! select.getEntityConfig( kind, name ); - - if ( configs?.length > 0 && hasConfig ) { - if ( window.__experimentalEnableSync ) { - if ( globalThis.IS_GUTENBERG_PLUGIN ) { - registerSyncConfigs( configs ); - } - } - - return configs; - } - - const loader = additionalEntityConfigLoaders.find( ( l ) => { - if ( ! name || ! l.name ) { - return l.kind === kind; - } - - return l.kind === kind && l.name === name; - } ); - if ( ! loader ) { - return []; - } - - configs = await loader.loadEntities(); - if ( window.__experimentalEnableSync ) { - if ( globalThis.IS_GUTENBERG_PLUGIN ) { - registerSyncConfigs( configs ); - } - } - - dispatch( addEntities( configs ) ); - - return configs; - }; diff --git a/packages/core-data/src/hooks/test/use-entity-record.js b/packages/core-data/src/hooks/test/use-entity-record.js index d83957abe06a1b..ac2b547cd9c61a 100644 --- a/packages/core-data/src/hooks/test/use-entity-record.js +++ b/packages/core-data/src/hooks/test/use-entity-record.js @@ -140,7 +140,14 @@ describe( 'useEntityRecord', () => { await act( () => new Promise( ( resolve ) => setTimeout( resolve, 0 ) ) ); - expect( triggerFetch ).toHaveBeenCalledTimes( 1 ); + await waitFor( () => + expect( triggerFetch ).toHaveBeenCalledWith( { + path: '/wp/v2/widgets/1?context=edit', + parse: false, + } ) + ); + // Clear the fetch call history. + triggerFetch.mockReset(); rerender( <UI enabled={ false } /> ); @@ -157,6 +164,6 @@ describe( 'useEntityRecord', () => { await act( () => new Promise( ( resolve ) => setTimeout( resolve, 0 ) ) ); - expect( triggerFetch ).toHaveBeenCalledTimes( 1 ); + expect( triggerFetch ).toHaveBeenCalledTimes( 0 ); } ); } ); diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index a5c33e18efbc60..d3980b89e8fc5b 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -14,7 +14,7 @@ import apiFetch from '@wordpress/api-fetch'; * Internal dependencies */ import { STORE_NAME } from './name'; -import { getOrLoadEntitiesConfig, DEFAULT_ENTITY_KEY } from './entities'; +import { additionalEntityConfigLoaders, DEFAULT_ENTITY_KEY } from './entities'; import { forwardResolver, getNormalizedCommaSeparable, @@ -64,8 +64,8 @@ export const getCurrentUser = */ export const getEntityRecord = ( kind, name, key = '', query ) => - async ( { select, dispatch, registry } ) => { - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + async ( { select, dispatch, registry, resolveSelect } ) => { + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.name === name && config.kind === kind ); @@ -230,8 +230,8 @@ export const getEditedEntityRecord = forwardResolver( 'getEntityRecord' ); */ export const getEntityRecords = ( kind, name, query = {} ) => - async ( { dispatch, registry } ) => { - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + async ( { dispatch, registry, resolveSelect } ) => { + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.name === name && config.kind === kind ); @@ -431,19 +431,36 @@ export const getEmbedPreview = */ export const canUser = ( requestedAction, resource, id ) => - async ( { dispatch, registry } ) => { + async ( { dispatch, registry, resolveSelect } ) => { if ( ! ALLOWED_RESOURCE_ACTIONS.includes( requestedAction ) ) { throw new Error( `'${ requestedAction }' is not a valid action.` ); } + const { hasStartedResolution } = registry.select( STORE_NAME ); + + // Prevent resolving the same resource twice. + for ( const relatedAction of ALLOWED_RESOURCE_ACTIONS ) { + if ( relatedAction === requestedAction ) { + continue; + } + const isAlreadyResolving = hasStartedResolution( 'canUser', [ + relatedAction, + resource, + id, + ] ); + if ( isAlreadyResolving ) { + return; + } + } + let resourcePath = null; if ( typeof resource === 'object' ) { if ( ! resource.kind || ! resource.name ) { throw new Error( 'The entity resource object is not valid.' ); } - const configs = await dispatch( - getOrLoadEntitiesConfig( resource.kind, resource.name ) + const configs = await resolveSelect.getEntitiesConfig( + resource.kind ); const entityConfig = configs.find( ( config ) => @@ -460,23 +477,6 @@ export const canUser = resourcePath = `/wp/v2/${ resource }` + ( id ? '/' + id : '' ); } - const { hasStartedResolution } = registry.select( STORE_NAME ); - - // Prevent resolving the same resource twice. - for ( const relatedAction of ALLOWED_RESOURCE_ACTIONS ) { - if ( relatedAction === requestedAction ) { - continue; - } - const isAlreadyResolving = hasStartedResolution( 'canUser', [ - relatedAction, - resource, - id, - ] ); - if ( isAlreadyResolving ) { - return; - } - } - let response; try { response = await apiFetch( { @@ -823,8 +823,8 @@ export const getDefaultTemplateId = */ export const getRevisions = ( kind, name, recordKey, query = {} ) => - async ( { dispatch, registry } ) => { - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + async ( { dispatch, registry, resolveSelect } ) => { + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.name === name && config.kind === kind ); @@ -944,8 +944,8 @@ getRevisions.shouldInvalidate = ( action, kind, name, recordKey ) => */ export const getRevision = ( kind, name, recordKey, revisionKey, query ) => - async ( { dispatch } ) => { - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + async ( { dispatch, resolveSelect } ) => { + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.name === name && config.kind === kind ); @@ -1017,3 +1017,31 @@ export const getRegisteredPostMeta = ); } }; + +/** + * Requests entity configs for the given kind from the REST API. + * + * @param {string} kind Entity kind. + */ +export const getEntitiesConfig = + ( kind ) => + async ( { dispatch } ) => { + const loader = additionalEntityConfigLoaders.find( + ( l ) => l.kind === kind + ); + + if ( ! loader ) { + return; + } + + try { + const configs = await loader.loadEntities(); + if ( ! configs.length ) { + return; + } + + dispatch.addEntities( configs ); + } catch { + // Do nothing if the request comes back with an API error. + } + }; diff --git a/packages/core-data/src/test/actions.js b/packages/core-data/src/test/actions.js index c00c01fbb77a17..8438d03293c164 100644 --- a/packages/core-data/src/test/actions.js +++ b/packages/core-data/src/test/actions.js @@ -68,8 +68,7 @@ describe( 'deleteEntityRecord', () => { __unstableAcquireStoreLock: jest.fn(), __unstableReleaseStoreLock: jest.fn(), } ); - // Provide entities - dispatch.mockReturnValueOnce( configs ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) }; // Provide response apiFetch.mockImplementation( () => deletedRecord ); @@ -78,7 +77,7 @@ describe( 'deleteEntityRecord', () => { 'postType', 'post', deletedRecord.id - )( { dispatch } ); + )( { dispatch, resolveSelect } ); expect( apiFetch ).toHaveBeenCalledTimes( 1 ); expect( apiFetch ).toHaveBeenCalledWith( { @@ -86,7 +85,7 @@ describe( 'deleteEntityRecord', () => { method: 'DELETE', } ); - expect( dispatch ).toHaveBeenCalledTimes( 4 ); + expect( dispatch ).toHaveBeenCalledTimes( 3 ); expect( dispatch ).toHaveBeenCalledWith( { type: 'DELETE_ENTITY_RECORD_START', kind: 'postType', @@ -120,8 +119,7 @@ describe( 'deleteEntityRecord', () => { __unstableAcquireStoreLock: jest.fn(), __unstableReleaseStoreLock: jest.fn(), } ); - // Provide entities - dispatch.mockReturnValueOnce( entities ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => entities ) }; // Provide response apiFetch.mockImplementation( () => { @@ -137,7 +135,7 @@ describe( 'deleteEntityRecord', () => { { throwOnError: true, } - )( { dispatch } ) + )( { dispatch, resolveSelect } ) ).rejects.toEqual( new Error( 'API error' ) ); } ); @@ -151,8 +149,7 @@ describe( 'deleteEntityRecord', () => { __unstableAcquireStoreLock: jest.fn(), __unstableReleaseStoreLock: jest.fn(), } ); - // Provide entities - dispatch.mockReturnValueOnce( entities ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => entities ) }; // Provide response apiFetch.mockImplementation( () => { @@ -168,7 +165,7 @@ describe( 'deleteEntityRecord', () => { { throwOnError: false, } - )( { dispatch } ) + )( { dispatch, resolveSelect } ) ).resolves.toBe( false ); } ); } ); @@ -195,8 +192,7 @@ describe( 'saveEditedEntityRecord', () => { const dispatch = Object.assign( jest.fn(), { saveEntityRecord: jest.fn(), } ); - // Provide entities - dispatch.mockReturnValueOnce( configs ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) }; // Provide response const updatedRecord = { ...item, menu: 10 }; @@ -208,7 +204,7 @@ describe( 'saveEditedEntityRecord', () => { 'root', 'menuItem', 1 - )( { dispatch, select } ); + )( { dispatch, select, resolveSelect } ); expect( dispatch.saveEntityRecord ).toHaveBeenCalledWith( 'root', @@ -236,8 +232,7 @@ describe( 'saveEditedEntityRecord', () => { const dispatch = Object.assign( jest.fn(), { saveEntityRecord: jest.fn(), } ); - // Provide entities - dispatch.mockReturnValueOnce( configs ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) }; // Provide response const updatedRecord = { ...item, menu: 10 }; @@ -249,7 +244,7 @@ describe( 'saveEditedEntityRecord', () => { 'root', 'menuLocation', 'primary' - )( { dispatch, select } ); + )( { dispatch, select, resolveSelect } ); expect( dispatch.saveEntityRecord ).toHaveBeenCalledWith( 'root', @@ -280,9 +275,7 @@ describe( 'saveEntityRecord', () => { const select = { getRawEntityRecord: () => post, }; - - // Provide entities - dispatch.mockReturnValueOnce( configs ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) }; // Provide response const updatedRecord = { ...post, id: 10 }; @@ -294,7 +287,7 @@ describe( 'saveEntityRecord', () => { 'postType', 'post', post - )( { select, dispatch } ); + )( { select, dispatch, resolveSelect } ); expect( apiFetch ).toHaveBeenCalledTimes( 1 ); expect( apiFetch ).toHaveBeenCalledWith( { @@ -303,7 +296,7 @@ describe( 'saveEntityRecord', () => { data: post, } ); - expect( dispatch ).toHaveBeenCalledTimes( 3 ); + expect( dispatch ).toHaveBeenCalledTimes( 2 ); expect( dispatch ).toHaveBeenCalledWith( { type: 'SAVE_ENTITY_RECORD_START', kind: 'postType', @@ -347,9 +340,7 @@ describe( 'saveEntityRecord', () => { const select = { getRawEntityRecord: () => post, }; - - // Provide entities - dispatch.mockReturnValueOnce( entities ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => entities ) }; // Provide response apiFetch.mockImplementation( () => { @@ -359,7 +350,7 @@ describe( 'saveEntityRecord', () => { await expect( saveEntityRecord( 'postType', 'post', post, { throwOnError: true, - } )( { select, dispatch } ) + } )( { select, dispatch, resolveSelect } ) ).rejects.toEqual( new Error( 'API error' ) ); } ); @@ -371,9 +362,7 @@ describe( 'saveEntityRecord', () => { const select = { getRawEntityRecord: () => post, }; - - // Provide entities - dispatch.mockReturnValueOnce( entities ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => entities ) }; // Provide response apiFetch.mockImplementation( () => { @@ -383,7 +372,7 @@ describe( 'saveEntityRecord', () => { await expect( saveEntityRecord( 'postType', 'post', post, { throwOnError: false, - } )( { select, dispatch } ) + } )( { select, dispatch, resolveSelect } ) ).resolves.toEqual( undefined ); } ); @@ -395,9 +384,7 @@ describe( 'saveEntityRecord', () => { const select = { getRawEntityRecord: () => post, }; - - // Provide entities - dispatch.mockReturnValueOnce( configs ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) }; // Provide response const updatedRecord = { ...post, id: 10 }; @@ -409,7 +396,7 @@ describe( 'saveEntityRecord', () => { 'postType', 'post', post - )( { select, dispatch } ); + )( { select, dispatch, resolveSelect } ); expect( apiFetch ).toHaveBeenCalledTimes( 1 ); expect( apiFetch ).toHaveBeenCalledWith( { @@ -418,7 +405,7 @@ describe( 'saveEntityRecord', () => { data: post, } ); - expect( dispatch ).toHaveBeenCalledTimes( 3 ); + expect( dispatch ).toHaveBeenCalledTimes( 2 ); expect( dispatch ).toHaveBeenCalledWith( { type: 'SAVE_ENTITY_RECORD_START', kind: 'postType', @@ -467,9 +454,7 @@ describe( 'saveEntityRecord', () => { const select = { getRawEntityRecord: () => ( {} ), }; - - // Provide entities - dispatch.mockReturnValueOnce( configs ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) }; // Provide response apiFetch.mockImplementation( () => postType ); @@ -478,7 +463,7 @@ describe( 'saveEntityRecord', () => { 'root', 'postType', postType - )( { select, dispatch } ); + )( { select, dispatch, resolveSelect } ); expect( apiFetch ).toHaveBeenCalledTimes( 1 ); expect( apiFetch ).toHaveBeenCalledWith( { @@ -487,7 +472,7 @@ describe( 'saveEntityRecord', () => { data: postType, } ); - expect( dispatch ).toHaveBeenCalledTimes( 3 ); + expect( dispatch ).toHaveBeenCalledTimes( 2 ); expect( dispatch ).toHaveBeenCalledWith( { type: 'SAVE_ENTITY_RECORD_START', kind: 'root', diff --git a/packages/core-data/src/test/entities.js b/packages/core-data/src/test/entities.js index 27b3d56e76865d..294c843fae117e 100644 --- a/packages/core-data/src/test/entities.js +++ b/packages/core-data/src/test/entities.js @@ -1,16 +1,9 @@ -/** - * WordPress dependencies - */ -import triggerFetch from '@wordpress/api-fetch'; -jest.mock( '@wordpress/api-fetch' ); - /** * Internal dependencies */ import { getMethodName, rootEntitiesConfig, - getOrLoadEntitiesConfig, prePersistPostType, } from '../entities'; @@ -43,79 +36,6 @@ describe( 'getMethodName', () => { } ); } ); -describe( 'getKindEntities', () => { - beforeEach( async () => { - triggerFetch.mockReset(); - } ); - - it( 'shouldn’t do anything if the entities have already been resolved', async () => { - const dispatch = jest.fn(); - const select = { - getEntitiesConfig: jest.fn( () => entities ), - getEntityConfig: jest.fn( () => ( { - kind: 'postType', - name: 'post', - } ) ), - }; - const entities = [ { kind: 'postType' } ]; - await getOrLoadEntitiesConfig( - 'postType', - 'post' - )( { dispatch, select } ); - expect( dispatch ).not.toHaveBeenCalled(); - } ); - - it( 'shouldn’t do anything if there no defined kind config', async () => { - const dispatch = jest.fn(); - const select = { - getEntitiesConfig: jest.fn( () => [] ), - getEntityConfig: jest.fn( () => undefined ), - }; - await getOrLoadEntitiesConfig( - 'unknownKind', - undefined - )( { dispatch, select } ); - expect( dispatch ).not.toHaveBeenCalled(); - } ); - - it( 'should fetch and add the entities', async () => { - const fetchedEntities = [ - { - rest_base: 'posts', - labels: { - singular_name: 'post', - }, - supports: { - revisions: true, - }, - }, - ]; - const dispatch = jest.fn(); - const select = { - getEntitiesConfig: jest.fn( () => [] ), - getEntityConfig: jest.fn( () => undefined ), - }; - triggerFetch.mockImplementation( () => fetchedEntities ); - - await getOrLoadEntitiesConfig( - 'postType', - 'post' - )( { dispatch, select } ); - expect( dispatch ).toHaveBeenCalledTimes( 1 ); - expect( dispatch.mock.calls[ 0 ][ 0 ].type ).toBe( 'ADD_ENTITIES' ); - expect( dispatch.mock.calls[ 0 ][ 0 ].entities.length ).toBe( 1 ); - expect( dispatch.mock.calls[ 0 ][ 0 ].entities[ 0 ].baseURL ).toBe( - '/wp/v2/posts' - ); - expect( - dispatch.mock.calls[ 0 ][ 0 ].entities[ 0 ].getRevisionsUrl( 1 ) - ).toBe( '/wp/v2/posts/1/revisions' ); - expect( - dispatch.mock.calls[ 0 ][ 0 ].entities[ 0 ].getRevisionsUrl( 1, 2 ) - ).toBe( '/wp/v2/posts/1/revisions/2' ); - } ); -} ); - describe( 'prePersistPostType', () => { it( 'set the status to draft and empty the title when saving auto-draft posts', () => { let record = { diff --git a/packages/core-data/src/test/resolvers.js b/packages/core-data/src/test/resolvers.js index f15bee3b3c2b9b..472056a4dfdc9b 100644 --- a/packages/core-data/src/test/resolvers.js +++ b/packages/core-data/src/test/resolvers.js @@ -29,6 +29,7 @@ describe( 'getEntityRecord', () => { }, ]; const registry = { batch: ( callback ) => callback() }; + const resolveSelect = { getEntitiesConfig: jest.fn( () => ENTITIES ) }; let dispatch; beforeEach( async () => { @@ -43,9 +44,6 @@ describe( 'getEntityRecord', () => { } ); it( 'yields with requested post type', async () => { - // Provide entities - dispatch.mockReturnValueOnce( ENTITIES ); - // Provide response triggerFetch.mockImplementation( () => POST_TYPE_RESPONSE ); @@ -53,7 +51,7 @@ describe( 'getEntityRecord', () => { 'root', 'postType', 'post' - )( { dispatch, registry } ); + )( { dispatch, registry, resolveSelect } ); // Fetch request should have been issued. expect( triggerFetch ).toHaveBeenCalledWith( { @@ -84,8 +82,6 @@ describe( 'getEntityRecord', () => { const select = { hasEntityRecords: jest.fn( () => {} ), }; - // Provide entities - dispatch.mockReturnValueOnce( ENTITIES ); // Provide response triggerFetch.mockImplementation( () => POST_TYPE_RESPONSE ); @@ -95,7 +91,7 @@ describe( 'getEntityRecord', () => { 'postType', 'post', query - )( { dispatch, select, registry } ); + )( { dispatch, select, registry, resolveSelect } ); // Trigger apiFetch, test that the query is present in the url. expect( triggerFetch ).toHaveBeenCalledWith( { @@ -141,6 +137,7 @@ describe( 'getEntityRecords', () => { }, ]; const registry = { batch: ( callback ) => callback() }; + const resolveSelect = { getEntitiesConfig: jest.fn( () => ENTITIES ) }; beforeEach( async () => { triggerFetch.mockReset(); @@ -152,13 +149,14 @@ describe( 'getEntityRecords', () => { __unstableAcquireStoreLock: jest.fn(), __unstableReleaseStoreLock: jest.fn(), } ); - // Provide entities - dispatch.mockReturnValueOnce( ENTITIES ); // Provide response triggerFetch.mockImplementation( () => POST_TYPES ); - await getEntityRecords( 'root', 'postType' )( { dispatch, registry } ); + await getEntityRecords( + 'root', + 'postType' + )( { dispatch, registry, resolveSelect } ); // Fetch request should have been issued. expect( triggerFetch ).toHaveBeenCalledWith( { @@ -183,13 +181,14 @@ describe( 'getEntityRecords', () => { __unstableAcquireStoreLock: jest.fn(), __unstableReleaseStoreLock: jest.fn(), } ); - // Provide entities - dispatch.mockReturnValueOnce( ENTITIES ); // Provide response triggerFetch.mockImplementation( () => POST_TYPES ); - await getEntityRecords( 'root', 'postType' )( { dispatch, registry } ); + await getEntityRecords( + 'root', + 'postType' + )( { dispatch, registry, resolveSelect } ); // Fetch request should have been issued. expect( triggerFetch ).toHaveBeenCalledWith( { @@ -216,13 +215,14 @@ describe( 'getEntityRecords', () => { __unstableReleaseStoreLock: jest.fn(), finishResolutions, } ); - // Provide entities - dispatch.mockReturnValueOnce( ENTITIES ); // Provide response triggerFetch.mockImplementation( () => POST_TYPES ); - await getEntityRecords( 'root', 'postType' )( { dispatch, registry } ); + await getEntityRecords( + 'root', + 'postType' + )( { dispatch, registry, resolveSelect } ); // Fetch request should have been issued. expect( triggerFetch ).toHaveBeenCalledWith( { @@ -290,6 +290,7 @@ describe( 'canUser', () => { baseURLParams: { context: 'edit' }, }, ]; + const resolveSelect = { getEntitiesConfig: jest.fn( () => ENTITIES ) }; let dispatch, registry; beforeEach( async () => { @@ -303,7 +304,6 @@ describe( 'canUser', () => { receiveUserPermission: jest.fn(), finishResolution: jest.fn(), } ); - dispatch.mockReturnValue( ENTITIES ); triggerFetch.mockReset(); } ); @@ -312,10 +312,14 @@ describe( 'canUser', () => { Promise.reject( { status: 404 } ) ); - await canUser( 'create', 'media' )( { dispatch, registry } ); + await canUser( + 'create', + 'media' + )( { dispatch, registry, resolveSelect } ); await canUser( 'create', { kind: 'root', name: 'media' } )( { dispatch, registry, + resolveSelect, } ); expect( triggerFetch ).toHaveBeenCalledWith( { @@ -332,6 +336,7 @@ describe( 'canUser', () => { canUser( 'create', { name: 'wp_block' } )( { dispatch, registry, + resolveSelect, } ) ).rejects.toThrow( 'The entity resource object is not valid.' ); } ); @@ -341,7 +346,10 @@ describe( 'canUser', () => { headers: new Map( [ [ 'allow', 'GET' ] ] ), } ) ); - await canUser( 'create', 'media' )( { dispatch, registry } ); + await canUser( + 'create', + 'media' + )( { dispatch, registry, resolveSelect } ); expect( triggerFetch ).toHaveBeenCalledWith( { path: '/wp/v2/media', @@ -363,6 +371,7 @@ describe( 'canUser', () => { await canUser( 'create', { kind: 'root', name: 'media' } )( { dispatch, registry, + resolveSelect, } ); expect( triggerFetch ).toHaveBeenCalledWith( { @@ -382,7 +391,10 @@ describe( 'canUser', () => { headers: new Map( [ [ 'allow', 'POST, GET, PUT, DELETE' ] ] ), } ) ); - await canUser( 'create', 'media' )( { dispatch, registry } ); + await canUser( + 'create', + 'media' + )( { dispatch, registry, resolveSelect } ); expect( triggerFetch ).toHaveBeenCalledWith( { path: '/wp/v2/media', @@ -404,6 +416,7 @@ describe( 'canUser', () => { await canUser( 'create', { kind: 'root', name: 'media' } )( { dispatch, registry, + resolveSelect, } ); expect( triggerFetch ).toHaveBeenCalledWith( { @@ -423,7 +436,11 @@ describe( 'canUser', () => { headers: new Map( [ [ 'allow', 'POST, GET, PUT, DELETE' ] ] ), } ) ); - await canUser( 'create', 'blocks', 123 )( { dispatch, registry } ); + await canUser( + 'create', + 'blocks', + 123 + )( { dispatch, registry, resolveSelect } ); expect( triggerFetch ).toHaveBeenCalledWith( { path: '/wp/v2/blocks/123', @@ -449,6 +466,7 @@ describe( 'canUser', () => { } )( { dispatch, registry, + resolveSelect, } ); expect( triggerFetch ).toHaveBeenCalledWith( { @@ -475,8 +493,14 @@ describe( 'canUser', () => { headers: new Map( [ [ 'allow', 'POST, GET' ] ] ), } ) ); - await canUser( 'create', 'blocks' )( { dispatch, registry } ); - await canUser( 'read', 'blocks' )( { dispatch, registry } ); + await canUser( + 'create', + 'blocks' + )( { dispatch, registry, resolveSelect } ); + await canUser( + 'read', + 'blocks' + )( { dispatch, registry, resolveSelect } ); expect( triggerFetch ).toHaveBeenCalledTimes( 1 ); @@ -508,6 +532,7 @@ describe( 'canUser', () => { } )( { dispatch, registry, + resolveSelect, } ); await canUser( 'read', { kind: 'postType', @@ -515,6 +540,7 @@ describe( 'canUser', () => { } )( { dispatch, registry, + resolveSelect, } ); expect( triggerFetch ).toHaveBeenCalledTimes( 1 ); @@ -541,10 +567,22 @@ describe( 'canUser', () => { headers: new Map( [ [ 'allow', 'POST, GET' ] ] ), } ) ); - await canUser( 'create', 'blocks' )( { dispatch, registry } ); - await canUser( 'read', 'blocks' )( { dispatch, registry } ); - await canUser( 'update', 'blocks' )( { dispatch, registry } ); - await canUser( 'delete', 'blocks' )( { dispatch, registry } ); + await canUser( + 'create', + 'blocks' + )( { dispatch, registry, resolveSelect } ); + await canUser( + 'read', + 'blocks' + )( { dispatch, registry, resolveSelect } ); + await canUser( + 'update', + 'blocks' + )( { dispatch, registry, resolveSelect } ); + await canUser( + 'delete', + 'blocks' + )( { dispatch, registry, resolveSelect } ); expect( dispatch.receiveUserPermission ).toHaveBeenCalledWith( 'create/blocks', @@ -576,10 +614,26 @@ describe( 'canUser', () => { headers: new Map( [ [ 'allow', 'POST, GET, PUT, DELETE' ] ] ), } ) ); - await canUser( 'create', 'blocks', 123 )( { dispatch, registry } ); - await canUser( 'read', 'blocks', 123 )( { dispatch, registry } ); - await canUser( 'update', 'blocks', 123 )( { dispatch, registry } ); - await canUser( 'delete', 'blocks', 123 )( { dispatch, registry } ); + await canUser( + 'create', + 'blocks', + 123 + )( { dispatch, registry, resolveSelect } ); + await canUser( + 'read', + 'blocks', + 123 + )( { dispatch, registry, resolveSelect } ); + await canUser( + 'update', + 'blocks', + 123 + )( { dispatch, registry, resolveSelect } ); + await canUser( + 'delete', + 'blocks', + 123 + )( { dispatch, registry, resolveSelect } ); expect( triggerFetch ).toHaveBeenCalledTimes( 1 ); @@ -617,22 +671,22 @@ describe( 'canUser', () => { kind: 'postType', name: 'wp_block', id: 123, - } )( { dispatch, registry } ); + } )( { dispatch, registry, resolveSelect } ); await canUser( 'read', { kind: 'postType', name: 'wp_block', id: 123, - } )( { dispatch, registry } ); + } )( { dispatch, registry, resolveSelect } ); await canUser( 'update', { kind: 'postType', name: 'wp_block', id: 123, - } )( { dispatch, registry } ); + } )( { dispatch, registry, resolveSelect } ); await canUser( 'delete', { kind: 'postType', name: 'wp_block', id: 123, - } )( { dispatch, registry } ); + } )( { dispatch, registry, resolveSelect } ); expect( triggerFetch ).toHaveBeenCalledTimes( 1 ); From 986fc5519b9455c2683f519abe4d6446111d5e38 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 30 Oct 2024 13:07:52 +0000 Subject: [PATCH 1398/1908] Bump plugin version to 19.6.0-rc.1 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index c1ee01c8415522..6723ae3d58fc0c 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.5.0 + * Version: 19.6.0-rc.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 99cbae41c6fac8..6cbdae9e88d062 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.5.0", + "version": "19.6.0-rc.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.5.0", + "version": "19.6.0-rc.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", "workspaces": [ diff --git a/package.json b/package.json index 06a73c51cc940d..32c6f01b80c4ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.5.0", + "version": "19.6.0-rc.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From e320ecd8ce3f360737fd05b65ed80ab16b6eddf4 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 30 Oct 2024 17:24:26 +0400 Subject: [PATCH 1399/1908] Inline Commenting: Optimize store selector and misc changes (#66592) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/collab-sidebar/index.js | 82 ++++++++----------- 1 file changed, 32 insertions(+), 50 deletions(-) diff --git a/packages/editor/src/components/collab-sidebar/index.js b/packages/editor/src/components/collab-sidebar/index.js index 8c7a710bce308a..39303620dd6222 100644 --- a/packages/editor/src/components/collab-sidebar/index.js +++ b/packages/editor/src/components/collab-sidebar/index.js @@ -3,7 +3,7 @@ */ import { __ } from '@wordpress/i18n'; import { useSelect, useDispatch, resolveSelect } from '@wordpress/data'; -import { useState, useEffect, useMemo } from '@wordpress/element'; +import { useState, useMemo } from '@wordpress/element'; import { comment as commentIcon } from '@wordpress/icons'; import { addFilter } from '@wordpress/hooks'; import { store as noticesStore } from '@wordpress/notices'; @@ -22,7 +22,7 @@ import { store as editorStore } from '../../store'; import AddCommentButton from './comment-button'; import AddCommentToolbarButton from './comment-button-toolbar'; -const threadsEmptyArray = []; +const EMPTY_ARRAY = []; const isBlockCommentExperimentEnabled = window?.__experimentalEnableBlockComment; @@ -54,50 +54,41 @@ export default function CollabSidebar() { const { saveEntityRecord, deleteEntityRecord } = useDispatch( coreStore ); const { getEntityRecord } = resolveSelect( coreStore ); const { enableComplementaryArea } = useDispatch( interfaceStore ); - const [ blockCommentID, setBlockCommentID ] = useState( null ); const [ showCommentBoard, setShowCommentBoard ] = useState( false ); - const { postId } = useSelect( ( select ) => { + + const { postId, postStatus, threads } = useSelect( ( select ) => { + const { getCurrentPostId, getEditedPostAttribute } = + select( editorStore ); + const _postId = getCurrentPostId(); + const data = !! _postId + ? select( coreStore ).getEntityRecords( 'root', 'comment', { + post: _postId, + type: 'block_comment', + status: 'any', + per_page: 100, + } ) + : null; + return { - postId: select( editorStore ).getCurrentPostId(), + postId: _postId, + postStatus: getEditedPostAttribute( 'status' ), + threads: data ?? EMPTY_ARRAY, }; }, [] ); - const postStatus = useSelect( ( select ) => { - const post = select( editorStore ).getCurrentPost(); - return { postStatus: post?.status }; - }, [] ); - - const threads = useSelect( - ( select ) => { - if ( ! postId ) { - return threadsEmptyArray; - } - const { getEntityRecords } = select( coreStore ); - const data = getEntityRecords( 'root', 'comment', { - post: postId, - type: 'block_comment', - status: 'any', - per_page: 100, - } ); - return data || threadsEmptyArray; - }, - [ postId ] - ); + const { clientId, blockCommentId } = useSelect( ( select ) => { + const { getBlockAttributes, getSelectedBlockClientId } = + select( blockEditorStore ); + const _clientId = getSelectedBlockClientId(); - const clientId = useSelect( ( select ) => { - const { getSelectedBlockClientId } = select( blockEditorStore ); - return getSelectedBlockClientId(); + return { + clientId: _clientId, + blockCommentId: _clientId + ? getBlockAttributes( _clientId )?.blockCommentId + : null, + }; }, [] ); - const blockDetails = useSelect( - ( select ) => { - return clientId - ? select( blockEditorStore ).getBlock( clientId ) - : null; - }, - [ clientId ] - ); - // Get the dispatch functions to save the comment and update the block attributes. const { updateBlockAttributes } = useDispatch( blockEditorStore ); @@ -257,27 +248,18 @@ export default function CollabSidebar() { ); }; - useEffect( () => { - if ( blockDetails ) { - setBlockCommentID( blockDetails?.attributes.blockCommentId ); - } - }, [ postId, clientId ] ); - // Check if the experimental flag is enabled. - if ( - ! isBlockCommentExperimentEnabled || - postStatus.postStatus === 'publish' - ) { + if ( ! isBlockCommentExperimentEnabled || postStatus === 'publish' ) { return null; // or maybe return some message indicating no threads are available. } return ( <> - { ! blockCommentID && ( + { ! blockCommentId && ( <AddCommentButton onClick={ openCollabBoard } /> ) } - { blockCommentID > 0 && ( + { blockCommentId > 0 && ( <AddCommentToolbarButton onClick={ openCollabBoard } /> ) } <PluginSidebar From df0fef183221b5e0b46f9e38534bd7148e6cba49 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 30 Oct 2024 13:16:50 +0000 Subject: [PATCH 1400/1908] Update changelog files --- packages/a11y/CHANGELOG.md | 2 ++ packages/a11y/package.json | 2 +- packages/annotations/CHANGELOG.md | 2 ++ packages/annotations/package.json | 2 +- packages/api-fetch/CHANGELOG.md | 2 ++ packages/api-fetch/package.json | 2 +- packages/autop/CHANGELOG.md | 2 ++ packages/autop/package.json | 2 +- packages/babel-plugin-import-jsx-pragma/CHANGELOG.md | 2 ++ packages/babel-plugin-import-jsx-pragma/package.json | 2 +- packages/babel-plugin-makepot/CHANGELOG.md | 2 ++ packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/CHANGELOG.md | 2 ++ packages/babel-preset-default/package.json | 2 +- packages/base-styles/CHANGELOG.md | 2 ++ packages/base-styles/package.json | 2 +- packages/blob/CHANGELOG.md | 2 ++ packages/blob/package.json | 2 +- packages/block-directory/CHANGELOG.md | 2 ++ packages/block-directory/package.json | 2 +- packages/block-editor/CHANGELOG.md | 2 ++ packages/block-editor/package.json | 2 +- packages/block-library/CHANGELOG.md | 2 ++ packages/block-library/package.json | 2 +- packages/block-serialization-default-parser/CHANGELOG.md | 2 ++ packages/block-serialization-default-parser/package.json | 2 +- packages/block-serialization-spec-parser/CHANGELOG.md | 2 ++ packages/block-serialization-spec-parser/package.json | 2 +- packages/blocks/CHANGELOG.md | 2 ++ packages/blocks/package.json | 2 +- packages/browserslist-config/CHANGELOG.md | 2 ++ packages/browserslist-config/package.json | 2 +- packages/commands/CHANGELOG.md | 2 ++ packages/commands/package.json | 2 +- packages/components/CHANGELOG.md | 2 ++ packages/components/package.json | 2 +- packages/compose/CHANGELOG.md | 2 ++ packages/compose/package.json | 2 +- packages/core-commands/CHANGELOG.md | 2 ++ packages/core-commands/package.json | 2 +- packages/core-data/CHANGELOG.md | 2 ++ packages/core-data/package.json | 2 +- packages/create-block-interactive-template/package.json | 2 +- packages/create-block-tutorial-template/CHANGELOG.md | 2 ++ packages/create-block-tutorial-template/package.json | 2 +- packages/create-block/CHANGELOG.md | 2 ++ packages/create-block/package.json | 2 +- packages/customize-widgets/CHANGELOG.md | 2 ++ packages/customize-widgets/package.json | 2 +- packages/data-controls/CHANGELOG.md | 2 ++ packages/data-controls/package.json | 2 +- packages/data/CHANGELOG.md | 2 ++ packages/data/package.json | 2 +- packages/dataviews/CHANGELOG.md | 2 ++ packages/dataviews/package.json | 2 +- packages/date/CHANGELOG.md | 2 ++ packages/date/package.json | 2 +- packages/dependency-extraction-webpack-plugin/CHANGELOG.md | 2 ++ packages/dependency-extraction-webpack-plugin/package.json | 2 +- packages/deprecated/CHANGELOG.md | 2 ++ packages/deprecated/package.json | 2 +- packages/docgen/CHANGELOG.md | 2 ++ packages/docgen/package.json | 2 +- packages/dom-ready/CHANGELOG.md | 2 ++ packages/dom-ready/package.json | 2 +- packages/dom/CHANGELOG.md | 2 ++ packages/dom/package.json | 2 +- packages/e2e-test-utils-playwright/CHANGELOG.md | 2 ++ packages/e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/CHANGELOG.md | 2 ++ packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/CHANGELOG.md | 2 ++ packages/e2e-tests/package.json | 2 +- packages/edit-post/CHANGELOG.md | 2 ++ packages/edit-post/package.json | 2 +- packages/edit-site/CHANGELOG.md | 2 ++ packages/edit-site/package.json | 2 +- packages/edit-widgets/CHANGELOG.md | 2 ++ packages/edit-widgets/package.json | 2 +- packages/editor/CHANGELOG.md | 2 ++ packages/editor/package.json | 2 +- packages/element/CHANGELOG.md | 2 ++ packages/element/package.json | 2 +- packages/env/CHANGELOG.md | 2 ++ packages/env/package.json | 2 +- packages/escape-html/CHANGELOG.md | 2 ++ packages/escape-html/package.json | 2 +- packages/eslint-plugin/CHANGELOG.md | 2 ++ packages/eslint-plugin/package.json | 2 +- packages/fields/CHANGELOG.md | 2 ++ packages/fields/package.json | 2 +- packages/format-library/CHANGELOG.md | 2 ++ packages/format-library/package.json | 2 +- packages/hooks/CHANGELOG.md | 2 ++ packages/hooks/package.json | 2 +- packages/html-entities/CHANGELOG.md | 2 ++ packages/html-entities/package.json | 2 +- packages/i18n/CHANGELOG.md | 2 ++ packages/i18n/package.json | 2 +- packages/icons/CHANGELOG.md | 2 ++ packages/icons/package.json | 2 +- packages/interactivity-router/CHANGELOG.md | 2 ++ packages/interactivity-router/package.json | 2 +- packages/interactivity/CHANGELOG.md | 2 ++ packages/interactivity/package.json | 2 +- packages/interface/CHANGELOG.md | 2 ++ packages/interface/package.json | 2 +- packages/is-shallow-equal/CHANGELOG.md | 2 ++ packages/is-shallow-equal/package.json | 2 +- packages/jest-console/CHANGELOG.md | 2 ++ packages/jest-console/package.json | 2 +- packages/jest-preset-default/CHANGELOG.md | 2 ++ packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/CHANGELOG.md | 2 ++ packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/CHANGELOG.md | 2 ++ packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/CHANGELOG.md | 2 ++ packages/keycodes/package.json | 2 +- packages/lazy-import/CHANGELOG.md | 2 ++ packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/CHANGELOG.md | 2 ++ packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/CHANGELOG.md | 2 ++ packages/media-utils/package.json | 2 +- packages/notices/CHANGELOG.md | 2 ++ packages/notices/package.json | 2 +- packages/npm-package-json-lint-config/CHANGELOG.md | 2 ++ packages/npm-package-json-lint-config/package.json | 2 +- packages/nux/CHANGELOG.md | 2 ++ packages/nux/package.json | 2 +- packages/patterns/CHANGELOG.md | 2 ++ packages/patterns/package.json | 2 +- packages/plugins/CHANGELOG.md | 2 ++ packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/CHANGELOG.md | 2 ++ packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/CHANGELOG.md | 2 ++ packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/CHANGELOG.md | 2 ++ packages/preferences-persistence/package.json | 2 +- packages/preferences/CHANGELOG.md | 2 ++ packages/preferences/package.json | 2 +- packages/prettier-config/CHANGELOG.md | 2 ++ packages/prettier-config/package.json | 2 +- packages/primitives/CHANGELOG.md | 2 ++ packages/primitives/package.json | 2 +- packages/priority-queue/CHANGELOG.md | 2 ++ packages/priority-queue/package.json | 2 +- packages/private-apis/CHANGELOG.md | 2 ++ packages/private-apis/package.json | 2 +- packages/project-management-automation/CHANGELOG.md | 2 ++ packages/project-management-automation/package.json | 2 +- packages/react-i18n/CHANGELOG.md | 2 ++ packages/react-i18n/package.json | 2 +- packages/readable-js-assets-webpack-plugin/CHANGELOG.md | 2 ++ packages/readable-js-assets-webpack-plugin/package.json | 2 +- packages/redux-routine/CHANGELOG.md | 2 ++ packages/redux-routine/package.json | 2 +- packages/reusable-blocks/CHANGELOG.md | 2 ++ packages/reusable-blocks/package.json | 2 +- packages/rich-text/CHANGELOG.md | 2 ++ packages/rich-text/package.json | 2 +- packages/router/CHANGELOG.md | 2 ++ packages/router/package.json | 2 +- packages/scripts/CHANGELOG.md | 2 ++ packages/scripts/package.json | 2 +- packages/server-side-render/CHANGELOG.md | 2 ++ packages/server-side-render/package.json | 2 +- packages/shortcode/CHANGELOG.md | 2 ++ packages/shortcode/package.json | 2 +- packages/style-engine/CHANGELOG.md | 2 ++ packages/style-engine/package.json | 2 +- packages/stylelint-config/CHANGELOG.md | 2 ++ packages/stylelint-config/package.json | 2 +- packages/sync/CHANGELOG.md | 2 ++ packages/sync/package.json | 2 +- packages/token-list/CHANGELOG.md | 2 ++ packages/token-list/package.json | 2 +- packages/undo-manager/CHANGELOG.md | 2 ++ packages/undo-manager/package.json | 2 +- packages/url/CHANGELOG.md | 2 ++ packages/url/package.json | 2 +- packages/viewport/CHANGELOG.md | 2 ++ packages/viewport/package.json | 2 +- packages/warning/CHANGELOG.md | 2 ++ packages/warning/package.json | 2 +- packages/widgets/CHANGELOG.md | 2 ++ packages/widgets/package.json | 2 +- packages/wordcount/CHANGELOG.md | 2 ++ packages/wordcount/package.json | 2 +- 191 files changed, 286 insertions(+), 96 deletions(-) diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index 08ac31b560ca87..5e90577e9155ab 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/a11y/package.json b/packages/a11y/package.json index a506cb940e7765..217a3086225923 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/CHANGELOG.md b/packages/annotations/CHANGELOG.md index 0f4795b11f109a..0618f4962f5eb5 100644 --- a/packages/annotations/CHANGELOG.md +++ b/packages/annotations/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.11.0 (2024-10-30) + ## 3.10.0 (2024-10-16) ## 3.9.0 (2024-10-03) diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 4a1f0fe2b771b5..f3f7f741aca408 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.10.0", + "version": "3.11.0-prerelease", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/CHANGELOG.md b/packages/api-fetch/CHANGELOG.md index dc654223da9e9f..8d3faea535faf3 100644 --- a/packages/api-fetch/CHANGELOG.md +++ b/packages/api-fetch/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.11.0 (2024-10-30) + ## 7.10.0 (2024-10-16) ## 7.9.0 (2024-10-03) diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 79968c31d1043a..25c95723445174 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.10.0", + "version": "7.11.0-prerelease", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/CHANGELOG.md b/packages/autop/CHANGELOG.md index 0a4a27cfbed808..9534b183d6ebb1 100644 --- a/packages/autop/CHANGELOG.md +++ b/packages/autop/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/autop/package.json b/packages/autop/package.json index aea14b2c666e14..3d21dfd5ca7d1a 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md index 6935957675b432..87bc412fd90eb3 100644 --- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md +++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index be9dbe0b0fe099..cc60e407de6918 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/CHANGELOG.md b/packages/babel-plugin-makepot/CHANGELOG.md index 7fbb829d65a842..f643a9304c68ab 100644 --- a/packages/babel-plugin-makepot/CHANGELOG.md +++ b/packages/babel-plugin-makepot/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.11.0 (2024-10-30) + ## 6.10.0 (2024-10-16) ## 6.9.0 (2024-10-03) diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index f88a5257b24c8f..d952ab50de0d0d 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.10.0", + "version": "6.11.0-prerelease", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index c787e176059298..d6eef13b90d456 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.11.0 (2024-10-30) + ## 8.10.0 (2024-10-16) ### Enhancements diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 777a40012d67f7..62e9d8888a9b91 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.10.0", + "version": "8.11.0-prerelease", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/CHANGELOG.md b/packages/base-styles/CHANGELOG.md index 7535112c5a5c11..61ff1100ac6453 100644 --- a/packages/base-styles/CHANGELOG.md +++ b/packages/base-styles/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index 04d1bb5e2d41ba..1135af7b99ccd4 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md index c168f9698e68bd..660c60776c7bd1 100644 --- a/packages/blob/CHANGELOG.md +++ b/packages/blob/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/blob/package.json b/packages/blob/package.json index 183e6aca33dc0c..de1b394f5a618c 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/CHANGELOG.md b/packages/block-directory/CHANGELOG.md index 7c2e092139b0ee..53636f34dad586 100644 --- a/packages/block-directory/CHANGELOG.md +++ b/packages/block-directory/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 6ff9ad7d510861..9fa529b364a649 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 1483fe1da9d5c9..6755c4ec83f215 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.6.0 (2024-10-30) + ## 14.5.0 (2024-10-16) ## 14.4.0 (2024-10-03) diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index b798e626c2e90f..0fb08d702fac21 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.5.0", + "version": "14.6.0-prerelease", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index b3788917cfbb95..4b5cf59f81910d 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.11.0 (2024-10-30) + ## 9.10.0 (2024-10-16) ## 9.9.0 (2024-10-03) diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 18ad0e46059c91..1c078354c12474 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.10.0", + "version": "9.11.0-prerelease", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/CHANGELOG.md b/packages/block-serialization-default-parser/CHANGELOG.md index 9b0457333bd7d5..5911f22795d463 100644 --- a/packages/block-serialization-default-parser/CHANGELOG.md +++ b/packages/block-serialization-default-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 14d2db0f688688..00a498bc9b1fa5 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/CHANGELOG.md b/packages/block-serialization-spec-parser/CHANGELOG.md index 40c93063cafbb7..1833dff1e52c83 100644 --- a/packages/block-serialization-spec-parser/CHANGELOG.md +++ b/packages/block-serialization-spec-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 9a871250162ca0..94325ad9129457 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index eebbe7148e8055..54fc6f77a7427d 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.0.0 (2024-10-30) + ### Breaking changes - Normalize `blockType.parent` to be an array. While string values were never supported, they appeared to work with some unintended side-effects that have been fixed by [#66250](https://github.com/WordPress/gutenberg/pull/66250). For that reason, we've added some code that automatically migrates strings to arrays — though it still raises a warning. diff --git a/packages/blocks/package.json b/packages/blocks/package.json index d7207548d173fc..5fd6d24bb0c9e9 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "13.10.0", + "version": "14.0.0-prerelease", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/CHANGELOG.md b/packages/browserslist-config/CHANGELOG.md index 8a2dc5d0ecc484..1ef626d40ef832 100644 --- a/packages/browserslist-config/CHANGELOG.md +++ b/packages/browserslist-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.11.0 (2024-10-30) + ## 6.10.0 (2024-10-16) ## 6.9.0 (2024-10-03) diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 8b19151e950475..645e72e423008c 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.10.0", + "version": "6.11.0-prerelease", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/CHANGELOG.md b/packages/commands/CHANGELOG.md index c75dbab26739d8..2ec9f745b774fd 100644 --- a/packages/commands/CHANGELOG.md +++ b/packages/commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.11.0 (2024-10-30) + ## 1.10.0 (2024-10-16) ## 1.9.0 (2024-10-03) diff --git a/packages/commands/package.json b/packages/commands/package.json index 4d35172ce8186d..20cdce012c7a58 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.10.0", + "version": "1.11.0-prerelease", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 9603d9656d5069..9c085abdae98c9 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 28.11.0 (2024-10-30) + ### Deprecations - `BorderBoxControl`: Deprecate 36px default size ([#65752](https://github.com/WordPress/gutenberg/pull/65752)). diff --git a/packages/components/package.json b/packages/components/package.json index a44e0afe89152b..abb1ade4c23fcc 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.10.0", + "version": "28.11.0-prerelease", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index f9d18eed43141d..8f8bedfde15d4a 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.11.0 (2024-10-30) + ## 7.10.0 (2024-10-16) ## 7.9.0 (2024-10-03) diff --git a/packages/compose/package.json b/packages/compose/package.json index f7aa8a3bf9b3bc..6123737dcf71bd 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.10.0", + "version": "7.11.0-prerelease", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/CHANGELOG.md b/packages/core-commands/CHANGELOG.md index 83b809ad526302..b98e0c55e24ff5 100644 --- a/packages/core-commands/CHANGELOG.md +++ b/packages/core-commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.11.0 (2024-10-30) + ## 1.10.0 (2024-10-16) ## 1.9.0 (2024-10-03) diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index adad0ee55afc23..30fff81216e91b 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.10.0", + "version": "1.11.0-prerelease", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md index 980f552ee0fca7..31b44fa32dd0a4 100644 --- a/packages/core-data/CHANGELOG.md +++ b/packages/core-data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.11.0 (2024-10-30) + ## 7.10.0 (2024-10-16) ## 7.9.0 (2024-10-03) diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 6b70fb0af3a8f4..aca278be9e2614 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.10.0", + "version": "7.11.0-prerelease", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index d400d77a49ab67..7ea6f1321a7974 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.10.0", + "version": "2.11.0-prerelease", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/CHANGELOG.md b/packages/create-block-tutorial-template/CHANGELOG.md index 8b4b467a1b4366..dd043522c27a6b 100644 --- a/packages/create-block-tutorial-template/CHANGELOG.md +++ b/packages/create-block-tutorial-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index 42ae74d8eeeb90..65ef110fa5151b 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index 9b9504faa1eeab..c961882082541c 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.54.0 (2024-10-30) + ### Enhancement - Add `--target-dir` flag to allow indicating where resulting files will be scaffolded ([#53781](https://github.com/WordPress/gutenberg/pull/53781)) diff --git a/packages/create-block/package.json b/packages/create-block/package.json index a9215bb2699d32..fb956151412230 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.53.0", + "version": "4.54.0-prerelease", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/CHANGELOG.md b/packages/customize-widgets/CHANGELOG.md index 4c308aff491268..b36ed481749ea9 100644 --- a/packages/customize-widgets/CHANGELOG.md +++ b/packages/customize-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 68e736c566c110..31de3890b7c756 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/CHANGELOG.md b/packages/data-controls/CHANGELOG.md index cfbe9d3ea46632..c536d850f8c733 100644 --- a/packages/data-controls/CHANGELOG.md +++ b/packages/data-controls/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 84462f49e5c0c8..8910574746a571 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index 44d7aa5f954ef2..98c553b08b67b9 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.11.0 (2024-10-30) + ## 10.10.0 (2024-10-16) ## 10.9.0 (2024-10-03) diff --git a/packages/data/package.json b/packages/data/package.json index 5e1817f0fb6ad8..7bd62c4dcc6f80 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.10.0", + "version": "10.11.0-prerelease", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index d5054b8578d95c..60cdad73b32efe 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 (2024-10-30) + ## 4.6.0 (2024-10-16) - Invert the logic for which icon to show in `DataViews` when using the filter view. Icons now match the action of the button label. ([#65914](https://github.com/WordPress/gutenberg/pull/65914)). diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index a83fd163517d0a..0e215caf4e9397 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.6.0", + "version": "4.7.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md index 4f35e1c2fcd475..1d0508bd5325ad 100644 --- a/packages/date/CHANGELOG.md +++ b/packages/date/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/date/package.json b/packages/date/package.json index a5925869f2acc0..31b0de0bb9f432 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index 4170d698ca5654..080234c319e477 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.11.0 (2024-10-30) + ## 6.10.0 (2024-10-16) ## 6.9.0 (2024-10-03) diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index f1b3c0f87bdb9b..aac150751d8686 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.10.0", + "version": "6.11.0-prerelease", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/CHANGELOG.md b/packages/deprecated/CHANGELOG.md index 8289aedd728b6f..5ba83861f7cd3d 100644 --- a/packages/deprecated/CHANGELOG.md +++ b/packages/deprecated/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 4871d5772dbb64..17142259d08a67 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/CHANGELOG.md b/packages/docgen/CHANGELOG.md index 139f85f8a62191..b7374d6f921cb4 100644 --- a/packages/docgen/CHANGELOG.md +++ b/packages/docgen/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.11.0 (2024-10-30) + ## 2.10.0 (2024-10-16) ## 2.9.0 (2024-10-03) diff --git a/packages/docgen/package.json b/packages/docgen/package.json index e7d7447226ce4e..2853999ff1cd39 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.10.0", + "version": "2.11.0-prerelease", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/CHANGELOG.md b/packages/dom-ready/CHANGELOG.md index ce17d989eac98d..ffdaeff6e892cf 100644 --- a/packages/dom-ready/CHANGELOG.md +++ b/packages/dom-ready/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 65334a21bd1373..7ce289b6875908 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/CHANGELOG.md b/packages/dom/CHANGELOG.md index 51c8de37b61982..b868abb474e62f 100644 --- a/packages/dom/CHANGELOG.md +++ b/packages/dom/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/dom/package.json b/packages/dom/package.json index 9d738a07b89b99..fa7213d761c934 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/CHANGELOG.md b/packages/e2e-test-utils-playwright/CHANGELOG.md index 5b262e27f5e48b..cbe574c55790a0 100644 --- a/packages/e2e-test-utils-playwright/CHANGELOG.md +++ b/packages/e2e-test-utils-playwright/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.11.0 (2024-10-30) + ## 1.10.0 (2024-10-16) ## 1.9.0 (2024-10-03) diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 353d19decb8f8a..d0088dfa47a9ed 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.10.0", + "version": "1.11.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index 84e4d4d564d659..137b1ba872dc54 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 11.11.0 (2024-10-30) + ## 11.10.0 (2024-10-16) ## 11.9.0 (2024-10-03) diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index ca116dd0264a71..21366e6535475e 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.10.0", + "version": "11.11.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md index 9268bec00239f9..610a2bb9697452 100644 --- a/packages/e2e-tests/CHANGELOG.md +++ b/packages/e2e-tests/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.11.0 (2024-10-30) + ## 8.10.0 (2024-10-16) ## 8.9.0 (2024-10-03) diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 5bf2b5c8663ac7..77bd6c7e31c424 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.10.1", + "version": "8.11.0-prerelease", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index 409af4ead284fd..48a101b543821e 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.11.0 (2024-10-30) + ## 8.10.0 (2024-10-16) ## 8.9.0 (2024-10-03) diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 028520e79cad7a..01d45078c44fee 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.10.0", + "version": "8.11.0-prerelease", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/CHANGELOG.md b/packages/edit-site/CHANGELOG.md index e1c4f09222ae67..7efa4f6c5b9d45 100644 --- a/packages/edit-site/CHANGELOG.md +++ b/packages/edit-site/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.11.0 (2024-10-30) + ## 6.10.0 (2024-10-16) ## 6.9.0 (2024-10-03) diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index f85a9e26a9d689..3f44b9a984d2d9 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.10.0", + "version": "6.11.0-prerelease", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/CHANGELOG.md b/packages/edit-widgets/CHANGELOG.md index 5b2fbd4d307416..316648bf952585 100644 --- a/packages/edit-widgets/CHANGELOG.md +++ b/packages/edit-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.11.0 (2024-10-30) + ## 6.10.0 (2024-10-16) ## 6.9.0 (2024-10-03) diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 1b412c5adb78c3..52461a7ef53ca7 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.10.0", + "version": "6.11.0-prerelease", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index 2716d965d14343..a3980bf4aead7a 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.11.0 (2024-10-30) + ### Bug Fixes - `Post Featured Image`: Fix `Set featured image` button's `box-shadow` transition to prevent border from flashing when focused. diff --git a/packages/editor/package.json b/packages/editor/package.json index 8c799085875c20..97a7a70bfe82ea 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.10.0", + "version": "14.11.0-prerelease", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/CHANGELOG.md b/packages/element/CHANGELOG.md index 1d6adbaef2c684..cf73e03c74f6a8 100644 --- a/packages/element/CHANGELOG.md +++ b/packages/element/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.11.0 (2024-10-30) + ## 6.10.0 (2024-10-16) ## 6.9.0 (2024-10-03) diff --git a/packages/element/package.json b/packages/element/package.json index 51e08e534b271e..7767010efc92e8 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.10.0", + "version": "6.11.0-prerelease", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md index faffee0d5b4d30..c8b49abebfaaa9 100644 --- a/packages/env/CHANGELOG.md +++ b/packages/env/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.11.0 (2024-10-30) + ## 10.10.0 (2024-10-16) ## 10.9.0 (2024-10-03) diff --git a/packages/env/package.json b/packages/env/package.json index f35dfa784fcc32..35032c79741045 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.10.0", + "version": "10.11.0-prerelease", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/CHANGELOG.md b/packages/escape-html/CHANGELOG.md index 80a4194ec28051..f92f40cce1a8cf 100644 --- a/packages/escape-html/CHANGELOG.md +++ b/packages/escape-html/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.11.0 (2024-10-30) + ## 3.10.0 (2024-10-16) ## 3.9.0 (2024-10-03) diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index cadf7e9eaa174c..8b334925719dbc 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.10.0", + "version": "3.11.0-prerelease", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 705312f977e661..3f753fb9b6b8b0 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 21.4.0 (2024-10-30) + ## 21.3.0 (2024-10-16) ## 21.2.0 (2024-10-03) diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 4a85de55f671a3..f6e8683fdd4c95 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "21.3.0", + "version": "21.4.0-prerelease", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/fields/CHANGELOG.md b/packages/fields/CHANGELOG.md index 26f61829fb8018..6f2bf69b653585 100644 --- a/packages/fields/CHANGELOG.md +++ b/packages/fields/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.3.0 (2024-10-30) + ## 0.2.0 (2024-10-16) ## 0.1.0 (2024-10-03) diff --git a/packages/fields/package.json b/packages/fields/package.json index acb01dd1882eba..1494770badb5f8 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/fields", - "version": "0.2.0", + "version": "0.3.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/CHANGELOG.md b/packages/format-library/CHANGELOG.md index e2d931b4323745..f44865c4325e23 100644 --- a/packages/format-library/CHANGELOG.md +++ b/packages/format-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/format-library/package.json b/packages/format-library/package.json index e30ca517de794e..bea85d21f9bf15 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/CHANGELOG.md b/packages/hooks/CHANGELOG.md index a5caa23d755032..284fa3c5098904 100644 --- a/packages/hooks/CHANGELOG.md +++ b/packages/hooks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 04a0865f5c44ae..c9a459eeb6a956 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/CHANGELOG.md b/packages/html-entities/CHANGELOG.md index de6f098713c236..e2d20a85313008 100644 --- a/packages/html-entities/CHANGELOG.md +++ b/packages/html-entities/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 7ccf5d52f55fb7..d9a6d78b079e89 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index 0fc465873a31ff..045589f3d7a3c4 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/i18n/package.json b/packages/i18n/package.json index f2ccf4b0fa2934..08ed3aee5da1f2 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index 4082e510708164..0649fe97ca5a46 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.11.0 (2024-10-30) + ## 10.10.0 (2024-10-16) ### Enhancements diff --git a/packages/icons/package.json b/packages/icons/package.json index a2e3c97b67b55e..5793ca9064bd6b 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.10.0", + "version": "10.11.0-prerelease", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/CHANGELOG.md b/packages/interactivity-router/CHANGELOG.md index 8b7db29395a547..fee7d90751ad5b 100644 --- a/packages/interactivity-router/CHANGELOG.md +++ b/packages/interactivity-router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.11.0 (2024-10-30) + ## 2.10.0 (2024-10-16) ### Enhancements diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 2d33456a5712b0..870418bac4d0af 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.10.0", + "version": "2.11.0-prerelease", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 73212578ac109c..488fcc77d7541d 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.11.0 (2024-10-30) + ### Bug Fixes - Fix reactivity of undefined objects and arrays added with `deepMerge()` ([#66183](https://github.com/WordPress/gutenberg/pull/66183)). diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index defabf4f76a6ad..c485de7e34eae8 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.10.0", + "version": "6.11.0-prerelease", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index ea748e80a9eb6a..67cb692f877098 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.0.0 (2024-10-30) + ### Breaking Changes - Removed `smallScreenTitle` prop from the `ComplementaryArea` component ([#64474](https://github.com/WordPress/gutenberg/pull/64474)). diff --git a/packages/interface/package.json b/packages/interface/package.json index ed9e0debf96d7c..69fe4cad7f5d93 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "7.0.0", + "version": "8.0.0-prerelease", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/CHANGELOG.md b/packages/is-shallow-equal/CHANGELOG.md index 8dc6be12e1e874..5dee7a281357a2 100644 --- a/packages/is-shallow-equal/CHANGELOG.md +++ b/packages/is-shallow-equal/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 1034ce1e76cda8..e55c591c68e9de 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/CHANGELOG.md b/packages/jest-console/CHANGELOG.md index 693445ed35ef41..00cc44f548a858 100644 --- a/packages/jest-console/CHANGELOG.md +++ b/packages/jest-console/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.11.0 (2024-10-30) + ## 8.10.0 (2024-10-16) ## 8.9.0 (2024-10-03) diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 373fc612b598b7..af334bd3562b99 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.10.0", + "version": "8.11.0-prerelease", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md index 44f121c25e3ee4..28e0f4e2bb420d 100644 --- a/packages/jest-preset-default/CHANGELOG.md +++ b/packages/jest-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 12.11.0 (2024-10-30) + ## 12.10.0 (2024-10-16) ## 12.9.0 (2024-10-03) diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 2db25a45f5b8e7..41db85e5b250bc 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.10.0", + "version": "12.11.0-prerelease", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/CHANGELOG.md b/packages/jest-puppeteer-axe/CHANGELOG.md index e3b455827c1971..a6557def1f0f27 100644 --- a/packages/jest-puppeteer-axe/CHANGELOG.md +++ b/packages/jest-puppeteer-axe/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.11.0 (2024-10-30) + ## 7.10.0 (2024-10-16) ## 7.9.0 (2024-10-03) diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 0e9b214a175772..4a125f4d9c17c5 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.10.0", + "version": "7.11.0-prerelease", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/CHANGELOG.md b/packages/keyboard-shortcuts/CHANGELOG.md index f549dfcd73b70a..386e6b95c1258a 100644 --- a/packages/keyboard-shortcuts/CHANGELOG.md +++ b/packages/keyboard-shortcuts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 4687df000bb3a7..ba17110a370a60 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/CHANGELOG.md b/packages/keycodes/CHANGELOG.md index 5b300b79211f38..894501981ab1b5 100644 --- a/packages/keycodes/CHANGELOG.md +++ b/packages/keycodes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index cce62c927fa206..51f1338bf3fbb8 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/CHANGELOG.md b/packages/lazy-import/CHANGELOG.md index 025c2ce1c066da..1f9d1b15304e14 100644 --- a/packages/lazy-import/CHANGELOG.md +++ b/packages/lazy-import/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.11.0 (2024-10-30) + ## 2.10.0 (2024-10-16) ## 2.9.0 (2024-10-03) diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index 1e56c1703cf1c6..e3a327dcff8731 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.10.0", + "version": "2.11.0-prerelease", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/CHANGELOG.md b/packages/list-reusable-blocks/CHANGELOG.md index 8c2134934192d8..958057ffb976de 100644 --- a/packages/list-reusable-blocks/CHANGELOG.md +++ b/packages/list-reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index d5a7dace810b48..ca3db667889062 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/CHANGELOG.md b/packages/media-utils/CHANGELOG.md index f47ed34c718d16..047ff84855f29d 100644 --- a/packages/media-utils/CHANGELOG.md +++ b/packages/media-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 0ba56f26706833..dd30c636e514b2 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/CHANGELOG.md b/packages/notices/CHANGELOG.md index 3c55e67bb1b021..d70c37f4fe721b 100644 --- a/packages/notices/CHANGELOG.md +++ b/packages/notices/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/notices/package.json b/packages/notices/package.json index de04c49a26cd6e..955fa43b652d39 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/CHANGELOG.md b/packages/npm-package-json-lint-config/CHANGELOG.md index e4c7943dc448a3..9c0aafedcead1a 100644 --- a/packages/npm-package-json-lint-config/CHANGELOG.md +++ b/packages/npm-package-json-lint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index 04fbb5ccc0aea0..284a6522b00b72 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/CHANGELOG.md b/packages/nux/CHANGELOG.md index c0af370a933b53..7446f00f381ac4 100644 --- a/packages/nux/CHANGELOG.md +++ b/packages/nux/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.11.0 (2024-10-30) + ## 9.10.0 (2024-10-16) ## 9.9.0 (2024-10-03) diff --git a/packages/nux/package.json b/packages/nux/package.json index 122bb2758263d6..4fd9cba3b3ca72 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.10.0", + "version": "9.11.0-prerelease", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/CHANGELOG.md b/packages/patterns/CHANGELOG.md index 31fa83ee8b93bb..ac4c4e09056129 100644 --- a/packages/patterns/CHANGELOG.md +++ b/packages/patterns/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.11.0 (2024-10-30) + ## 2.10.0 (2024-10-16) ## 2.9.0 (2024-10-03) diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 3da30812d61edd..5575ff39ce2572 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.10.0", + "version": "2.11.0-prerelease", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/CHANGELOG.md b/packages/plugins/CHANGELOG.md index aa54e27a3913da..2696ce8b2bf0b4 100644 --- a/packages/plugins/CHANGELOG.md +++ b/packages/plugins/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.11.0 (2024-10-30) + ## 7.10.0 (2024-10-16) ## 7.9.0 (2024-10-03) diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 75f0bc554b868c..ffd8bde2f53247 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.10.0", + "version": "7.11.0-prerelease", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/CHANGELOG.md b/packages/postcss-plugins-preset/CHANGELOG.md index 514307874acb12..939a997a5eb577 100644 --- a/packages/postcss-plugins-preset/CHANGELOG.md +++ b/packages/postcss-plugins-preset/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 82753b0ff56d38..71258db246e2d7 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/CHANGELOG.md b/packages/postcss-themes/CHANGELOG.md index 55c0311cc6b95e..05cebfe533c6cf 100644 --- a/packages/postcss-themes/CHANGELOG.md +++ b/packages/postcss-themes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.11.0 (2024-10-30) + ## 6.10.0 (2024-10-16) ## 6.9.0 (2024-10-03) diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index 436c606cf9d1dd..3cd813014db8b7 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.10.0", + "version": "6.11.0-prerelease", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/CHANGELOG.md b/packages/preferences-persistence/CHANGELOG.md index b9efaa9c69049f..67bde4ee87c98d 100644 --- a/packages/preferences-persistence/CHANGELOG.md +++ b/packages/preferences-persistence/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.11.0 (2024-10-30) + ## 2.10.0 (2024-10-16) ## 2.9.0 (2024-10-03) diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index e91c8f295d4653..20f20a56c5c314 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.10.0", + "version": "2.11.0-prerelease", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/CHANGELOG.md b/packages/preferences/CHANGELOG.md index 3b1711b5d87b04..2850950d6df7f5 100644 --- a/packages/preferences/CHANGELOG.md +++ b/packages/preferences/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/preferences/package.json b/packages/preferences/package.json index ef9f0ef8803dfc..bfb66311b1aadb 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/CHANGELOG.md b/packages/prettier-config/CHANGELOG.md index 33a0261603fb7c..a942a98605ab56 100644 --- a/packages/prettier-config/CHANGELOG.md +++ b/packages/prettier-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index f46706b09082bd..1b19dc7a3be291 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/CHANGELOG.md b/packages/primitives/CHANGELOG.md index 02b3d9176b2ca8..ac8c402ea9e757 100644 --- a/packages/primitives/CHANGELOG.md +++ b/packages/primitives/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 67117e037002c6..ca999e8f9b792b 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/CHANGELOG.md b/packages/priority-queue/CHANGELOG.md index e080b71c08182a..042e4ae3e97c12 100644 --- a/packages/priority-queue/CHANGELOG.md +++ b/packages/priority-queue/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.11.0 (2024-10-30) + ## 3.10.0 (2024-10-16) ## 3.9.0 (2024-10-03) diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 0113bb9b1bc62c..ef5103f5f79334 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.10.0", + "version": "3.11.0-prerelease", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/CHANGELOG.md b/packages/private-apis/CHANGELOG.md index 99887b6f4b6152..db68d750432bc5 100644 --- a/packages/private-apis/CHANGELOG.md +++ b/packages/private-apis/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.11.0 (2024-10-30) + ## 1.10.0 (2024-10-16) ## 1.9.0 (2024-10-03) diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index eae83e1fc46d34..a750c6f2abcd17 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.10.0", + "version": "1.11.0-prerelease", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/CHANGELOG.md b/packages/project-management-automation/CHANGELOG.md index c7b3021d4679c5..da01acd92c8f3b 100644 --- a/packages/project-management-automation/CHANGELOG.md +++ b/packages/project-management-automation/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.11.0 (2024-10-30) + ## 2.10.0 (2024-10-16) ## 2.9.0 (2024-10-03) diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 6da7e21d76fb0f..d286c2be59048b 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.10.0", + "version": "2.11.0-prerelease", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/CHANGELOG.md b/packages/react-i18n/CHANGELOG.md index 6efaf980c320bc..165c1f0bc95549 100644 --- a/packages/react-i18n/CHANGELOG.md +++ b/packages/react-i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 6a741d33f997c1..64c03f757998d1 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md index bd5ff8879c2a14..63a3192e7aa95f 100644 --- a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md +++ b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.11.0 (2024-10-30) + ## 3.10.0 (2024-10-16) ## 3.9.0 (2024-10-03) diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index 4f7a42a8e59ea7..cffe3669586a33 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.10.0", + "version": "3.11.0-prerelease", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/CHANGELOG.md b/packages/redux-routine/CHANGELOG.md index 0aadde8ca5fa34..54df85dfd5717f 100644 --- a/packages/redux-routine/CHANGELOG.md +++ b/packages/redux-routine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 70d1cae1a8b5fd..8fd54ddf2ed340 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/CHANGELOG.md b/packages/reusable-blocks/CHANGELOG.md index 62e09d8e61dfc6..e4ba1b052ae218 100644 --- a/packages/reusable-blocks/CHANGELOG.md +++ b/packages/reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 461a17001b0c38..b212e297aeee2c 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/CHANGELOG.md b/packages/rich-text/CHANGELOG.md index 5717f59a34d285..138d963020deb5 100644 --- a/packages/rich-text/CHANGELOG.md +++ b/packages/rich-text/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.11.0 (2024-10-30) + ## 7.10.0 (2024-10-16) ## 7.9.0 (2024-10-03) diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index c2b99faaa72d7f..797489ea4601c6 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.10.0", + "version": "7.11.0-prerelease", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index 23f553b847a404..cd0a91605c6f58 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.11.0 (2024-10-30) + ## 1.10.0 (2024-10-16) ### Enhancements diff --git a/packages/router/package.json b/packages/router/package.json index d7a1219e0b95cf..8cb1c6bdd6c5fd 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.10.0", + "version": "1.11.0-prerelease", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index e2279dbbd5b8aa..ca5a44bca62b52 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 30.4.0 (2024-10-30) + ### Enhancements - Add BlueOak-1.0.0 the GPLv2-compatible licenses recognized by check-licenses ([#66139](https://github.com/WordPress/gutenberg/pull/66139)). diff --git a/packages/scripts/package.json b/packages/scripts/package.json index ef1ff601152429..0e1a0f4a3be87b 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.3.0", + "version": "30.4.0-prerelease", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/CHANGELOG.md b/packages/server-side-render/CHANGELOG.md index 3e7fefedfe287b..479fbf835e74d5 100644 --- a/packages/server-side-render/CHANGELOG.md +++ b/packages/server-side-render/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.11.0 (2024-10-30) + ## 5.10.0 (2024-10-16) ## 5.9.0 (2024-10-03) diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index a40d4358c35308..c351ec53f7b3f9 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.10.0", + "version": "5.11.0-prerelease", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/CHANGELOG.md b/packages/shortcode/CHANGELOG.md index ea651b6af87f0d..f869446602cb16 100644 --- a/packages/shortcode/CHANGELOG.md +++ b/packages/shortcode/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index c10007806383d9..7922786d04eb50 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md index 5ad39afec7952c..f9e50558d83664 100644 --- a/packages/style-engine/CHANGELOG.md +++ b/packages/style-engine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.11.0 (2024-10-30) + ## 2.10.0 (2024-10-16) ## 2.9.0 (2024-10-03) diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index ed6eebf9483d17..1ae658745a0973 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.10.0", + "version": "2.11.0-prerelease", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/CHANGELOG.md b/packages/stylelint-config/CHANGELOG.md index 9d263fee2648f7..ac778801a0160d 100644 --- a/packages/stylelint-config/CHANGELOG.md +++ b/packages/stylelint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 23.3.0 (2024-10-30) + ## 23.2.0 (2024-10-16) ## 23.1.0 (2024-10-03) diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 5c213a88519497..aecc448f28d0e2 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "23.2.0", + "version": "23.3.0-prerelease", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/CHANGELOG.md b/packages/sync/CHANGELOG.md index bbfb3cbb539fd5..d9e04f700b8d78 100644 --- a/packages/sync/CHANGELOG.md +++ b/packages/sync/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.11.0 (2024-10-30) + ## 1.10.0 (2024-10-16) ## 1.9.0 (2024-10-03) diff --git a/packages/sync/package.json b/packages/sync/package.json index 27ed67971b7ca9..a11264ec838c9c 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.10.0", + "version": "1.11.0-prerelease", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/CHANGELOG.md b/packages/token-list/CHANGELOG.md index 3f46da49645186..304d67cefdd026 100644 --- a/packages/token-list/CHANGELOG.md +++ b/packages/token-list/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.11.0 (2024-10-30) + ## 3.10.0 (2024-10-16) ## 3.9.0 (2024-10-03) diff --git a/packages/token-list/package.json b/packages/token-list/package.json index e73fc1918ec55e..7998b48e6730bc 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.10.0", + "version": "3.11.0-prerelease", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/CHANGELOG.md b/packages/undo-manager/CHANGELOG.md index a3b1f6c6ecdab8..0f779e36f51687 100644 --- a/packages/undo-manager/CHANGELOG.md +++ b/packages/undo-manager/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.11.0 (2024-10-30) + ## 1.10.0 (2024-10-16) ## 1.9.0 (2024-10-03) diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 9e31c9c0d6dd7f..d7087e7d7084ef 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.10.0", + "version": "1.11.0-prerelease", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/CHANGELOG.md b/packages/url/CHANGELOG.md index fb1175f11adeb7..0e0ac497785e46 100644 --- a/packages/url/CHANGELOG.md +++ b/packages/url/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/url/package.json b/packages/url/package.json index e7228be292bf03..5370e545054f84 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/CHANGELOG.md b/packages/viewport/CHANGELOG.md index 3447e75fd97c6e..ce3f20a6d8e2b7 100644 --- a/packages/viewport/CHANGELOG.md +++ b/packages/viewport/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.11.0 (2024-10-30) + ## 6.10.0 (2024-10-16) ## 6.9.0 (2024-10-03) diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 916776cdbe98b3..9064976528afba 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.10.0", + "version": "6.11.0-prerelease", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/CHANGELOG.md b/packages/warning/CHANGELOG.md index bce0ba957230b9..e6ae7b4a229850 100644 --- a/packages/warning/CHANGELOG.md +++ b/packages/warning/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.11.0 (2024-10-30) + ## 3.10.0 (2024-10-16) ## 3.9.0 (2024-10-03) diff --git a/packages/warning/package.json b/packages/warning/package.json index d9d4835a220f0a..67c33a001cc245 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.10.0", + "version": "3.11.0-prerelease", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/CHANGELOG.md b/packages/widgets/CHANGELOG.md index 2436b6b03bed2e..367add006f8895 100644 --- a/packages/widgets/CHANGELOG.md +++ b/packages/widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/widgets/package.json b/packages/widgets/package.json index d85e06c399b2d9..4efa23343f8c01 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/CHANGELOG.md b/packages/wordcount/CHANGELOG.md index c622c99b324dd7..62b4b2efe1506e 100644 --- a/packages/wordcount/CHANGELOG.md +++ b/packages/wordcount/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.11.0 (2024-10-30) + ## 4.10.0 (2024-10-16) ## 4.9.0 (2024-10-03) diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index f2fa54e449da51..bb898184019cb0 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.10.0", + "version": "4.11.0-prerelease", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From ceeb8ab458523ed2ad2121fe540d789556a12b81 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 30 Oct 2024 13:18:33 +0000 Subject: [PATCH 1401/1908] chore(release): publish - @wordpress/a11y@4.11.0 - @wordpress/annotations@3.11.0 - @wordpress/api-fetch@7.11.0 - @wordpress/autop@4.11.0 - @wordpress/babel-plugin-import-jsx-pragma@5.11.0 - @wordpress/babel-plugin-makepot@6.11.0 - @wordpress/babel-preset-default@8.11.0 - @wordpress/base-styles@5.11.0 - @wordpress/blob@4.11.0 - @wordpress/block-directory@5.11.0 - @wordpress/block-editor@14.6.0 - @wordpress/block-library@9.11.0 - @wordpress/block-serialization-default-parser@5.11.0 - @wordpress/block-serialization-spec-parser@5.11.0 - @wordpress/blocks@14.0.0 - @wordpress/browserslist-config@6.11.0 - @wordpress/commands@1.11.0 - @wordpress/components@28.11.0 - @wordpress/compose@7.11.0 - @wordpress/core-commands@1.11.0 - @wordpress/core-data@7.11.0 - @wordpress/create-block@4.54.0 - @wordpress/create-block-interactive-template@2.11.0 - @wordpress/create-block-tutorial-template@4.11.0 - @wordpress/customize-widgets@5.11.0 - @wordpress/data@10.11.0 - @wordpress/data-controls@4.11.0 - @wordpress/dataviews@4.7.0 - @wordpress/date@5.11.0 - @wordpress/dependency-extraction-webpack-plugin@6.11.0 - @wordpress/deprecated@4.11.0 - @wordpress/docgen@2.11.0 - @wordpress/dom@4.11.0 - @wordpress/dom-ready@4.11.0 - @wordpress/e2e-test-utils@11.11.0 - @wordpress/e2e-test-utils-playwright@1.11.0 - @wordpress/e2e-tests@8.11.0 - @wordpress/edit-post@8.11.0 - @wordpress/edit-site@6.11.0 - @wordpress/edit-widgets@6.11.0 - @wordpress/editor@14.11.0 - @wordpress/element@6.11.0 - @wordpress/env@10.11.0 - @wordpress/escape-html@3.11.0 - @wordpress/eslint-plugin@21.4.0 - @wordpress/fields@0.3.0 - @wordpress/format-library@5.11.0 - @wordpress/hooks@4.11.0 - @wordpress/html-entities@4.11.0 - @wordpress/i18n@5.11.0 - @wordpress/icons@10.11.0 - @wordpress/interactivity@6.11.0 - @wordpress/interactivity-router@2.11.0 - @wordpress/interface@8.0.0 - @wordpress/is-shallow-equal@5.11.0 - @wordpress/jest-console@8.11.0 - @wordpress/jest-preset-default@12.11.0 - @wordpress/jest-puppeteer-axe@7.11.0 - @wordpress/keyboard-shortcuts@5.11.0 - @wordpress/keycodes@4.11.0 - @wordpress/lazy-import@2.11.0 - @wordpress/list-reusable-blocks@5.11.0 - @wordpress/media-utils@5.11.0 - @wordpress/notices@5.11.0 - @wordpress/npm-package-json-lint-config@5.11.0 - @wordpress/nux@9.11.0 - @wordpress/patterns@2.11.0 - @wordpress/plugins@7.11.0 - @wordpress/postcss-plugins-preset@5.11.0 - @wordpress/postcss-themes@6.11.0 - @wordpress/preferences@4.11.0 - @wordpress/preferences-persistence@2.11.0 - @wordpress/prettier-config@4.11.0 - @wordpress/primitives@4.11.0 - @wordpress/priority-queue@3.11.0 - @wordpress/private-apis@1.11.0 - @wordpress/project-management-automation@2.11.0 - @wordpress/react-i18n@4.11.0 - @wordpress/readable-js-assets-webpack-plugin@3.11.0 - @wordpress/redux-routine@5.11.0 - @wordpress/reusable-blocks@5.11.0 - @wordpress/rich-text@7.11.0 - @wordpress/router@1.11.0 - @wordpress/scripts@30.4.0 - @wordpress/server-side-render@5.11.0 - @wordpress/shortcode@4.11.0 - @wordpress/style-engine@2.11.0 - @wordpress/stylelint-config@23.3.0 - @wordpress/sync@1.11.0 - @wordpress/token-list@3.11.0 - @wordpress/undo-manager@1.11.0 - @wordpress/url@4.11.0 - @wordpress/viewport@6.11.0 - @wordpress/warning@3.11.0 - @wordpress/widgets@4.11.0 - @wordpress/wordcount@4.11.0 --- package-lock.json | 192 +++++++++--------- packages/a11y/package.json | 2 +- packages/annotations/package.json | 2 +- packages/api-fetch/package.json | 2 +- packages/autop/package.json | 2 +- .../package.json | 2 +- packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/package.json | 2 +- packages/base-styles/package.json | 2 +- packages/blob/package.json | 2 +- packages/block-directory/package.json | 2 +- packages/block-editor/package.json | 2 +- packages/block-library/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/blocks/package.json | 2 +- packages/browserslist-config/package.json | 2 +- packages/commands/package.json | 2 +- packages/components/package.json | 2 +- packages/compose/package.json | 2 +- packages/core-commands/package.json | 2 +- packages/core-data/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/create-block/package.json | 2 +- packages/customize-widgets/package.json | 2 +- packages/data-controls/package.json | 2 +- packages/data/package.json | 2 +- packages/dataviews/package.json | 2 +- packages/date/package.json | 2 +- .../package.json | 2 +- packages/deprecated/package.json | 2 +- packages/docgen/package.json | 2 +- packages/dom-ready/package.json | 2 +- packages/dom/package.json | 2 +- .../e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/package.json | 2 +- packages/edit-post/package.json | 2 +- packages/edit-site/package.json | 2 +- packages/edit-widgets/package.json | 2 +- packages/editor/package.json | 2 +- packages/element/package.json | 2 +- packages/env/package.json | 2 +- packages/escape-html/package.json | 2 +- packages/eslint-plugin/package.json | 2 +- packages/fields/package.json | 2 +- packages/format-library/package.json | 2 +- packages/hooks/package.json | 2 +- packages/html-entities/package.json | 2 +- packages/i18n/package.json | 2 +- packages/icons/package.json | 2 +- packages/interactivity-router/package.json | 2 +- packages/interactivity/package.json | 2 +- packages/interface/package.json | 2 +- packages/is-shallow-equal/package.json | 2 +- packages/jest-console/package.json | 2 +- packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/package.json | 2 +- packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/package.json | 2 +- packages/notices/package.json | 2 +- .../npm-package-json-lint-config/package.json | 2 +- packages/nux/package.json | 2 +- packages/patterns/package.json | 2 +- packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/package.json | 2 +- packages/preferences/package.json | 2 +- packages/prettier-config/package.json | 2 +- packages/primitives/package.json | 2 +- packages/priority-queue/package.json | 2 +- packages/private-apis/package.json | 2 +- .../package.json | 2 +- packages/react-i18n/package.json | 2 +- .../package.json | 2 +- packages/redux-routine/package.json | 2 +- packages/reusable-blocks/package.json | 2 +- packages/rich-text/package.json | 2 +- packages/router/package.json | 2 +- packages/scripts/package.json | 2 +- packages/server-side-render/package.json | 2 +- packages/shortcode/package.json | 2 +- packages/style-engine/package.json | 2 +- packages/stylelint-config/package.json | 2 +- packages/sync/package.json | 2 +- packages/token-list/package.json | 2 +- packages/undo-manager/package.json | 2 +- packages/url/package.json | 2 +- packages/viewport/package.json | 2 +- packages/warning/package.json | 2 +- packages/widgets/package.json | 2 +- packages/wordcount/package.json | 2 +- 97 files changed, 192 insertions(+), 192 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6cbdae9e88d062..06a46df8855d94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51622,7 +51622,7 @@ }, "packages/a11y": { "name": "@wordpress/a11y", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -51636,7 +51636,7 @@ }, "packages/annotations": { "name": "@wordpress/annotations", - "version": "3.10.0", + "version": "3.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -51664,7 +51664,7 @@ }, "packages/api-fetch": { "name": "@wordpress/api-fetch", - "version": "7.10.0", + "version": "7.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -51678,7 +51678,7 @@ }, "packages/autop": { "name": "@wordpress/autop", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -51690,7 +51690,7 @@ }, "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -51702,7 +51702,7 @@ }, "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", - "version": "6.10.0", + "version": "6.11.0", "license": "GPL-2.0-or-later", "dependencies": { "deepmerge": "^4.3.0", @@ -51719,7 +51719,7 @@ }, "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", - "version": "8.10.0", + "version": "8.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -52850,7 +52850,7 @@ }, "packages/base-styles": { "name": "@wordpress/base-styles", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -52859,7 +52859,7 @@ }, "packages/blob": { "name": "@wordpress/blob", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -52871,7 +52871,7 @@ }, "packages/block-directory": { "name": "@wordpress/block-directory", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -52907,7 +52907,7 @@ }, "packages/block-editor": { "name": "@wordpress/block-editor", - "version": "14.5.0", + "version": "14.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53006,7 +53006,7 @@ }, "packages/block-library": { "name": "@wordpress/block-library", - "version": "9.10.0", + "version": "9.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53072,7 +53072,7 @@ }, "packages/block-serialization-default-parser": { "name": "@wordpress/block-serialization-default-parser", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -53084,7 +53084,7 @@ }, "packages/block-serialization-spec-parser": { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "pegjs": "^0.10.0", @@ -53097,7 +53097,7 @@ }, "packages/blocks": { "name": "@wordpress/blocks", - "version": "13.10.0", + "version": "14.0.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53151,7 +53151,7 @@ }, "packages/browserslist-config": { "name": "@wordpress/browserslist-config", - "version": "6.10.0", + "version": "6.11.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53160,7 +53160,7 @@ }, "packages/commands": { "name": "@wordpress/commands", - "version": "1.10.0", + "version": "1.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53399,7 +53399,7 @@ }, "packages/components": { "name": "@wordpress/components", - "version": "28.10.0", + "version": "28.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -53520,7 +53520,7 @@ }, "packages/compose": { "name": "@wordpress/compose", - "version": "7.10.0", + "version": "7.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53557,7 +53557,7 @@ }, "packages/core-commands": { "name": "@wordpress/core-commands", - "version": "1.10.0", + "version": "1.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53586,7 +53586,7 @@ }, "packages/core-data": { "name": "@wordpress/core-data", - "version": "7.10.0", + "version": "7.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53631,7 +53631,7 @@ }, "packages/create-block": { "name": "@wordpress/create-block", - "version": "4.53.0", + "version": "4.54.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/lazy-import": "*", @@ -53658,7 +53658,7 @@ }, "packages/create-block-interactive-template": { "name": "@wordpress/create-block-interactive-template", - "version": "2.10.0", + "version": "2.11.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53667,7 +53667,7 @@ }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53676,7 +53676,7 @@ }, "packages/customize-widgets": { "name": "@wordpress/customize-widgets", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53715,7 +53715,7 @@ }, "packages/data": { "name": "@wordpress/data", - "version": "10.10.0", + "version": "10.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53744,7 +53744,7 @@ }, "packages/data-controls": { "name": "@wordpress/data-controls", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53762,7 +53762,7 @@ }, "packages/dataviews": { "name": "@wordpress/dataviews", - "version": "4.6.0", + "version": "4.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -53819,7 +53819,7 @@ }, "packages/date": { "name": "@wordpress/date", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53834,7 +53834,7 @@ }, "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.10.0", + "version": "6.11.0", "license": "GPL-2.0-or-later", "dependencies": { "json2php": "^0.0.7" @@ -53849,7 +53849,7 @@ }, "packages/deprecated": { "name": "@wordpress/deprecated", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53862,7 +53862,7 @@ }, "packages/docgen": { "name": "@wordpress/docgen", - "version": "2.10.0", + "version": "2.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -53883,7 +53883,7 @@ }, "packages/dom": { "name": "@wordpress/dom", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53896,7 +53896,7 @@ }, "packages/dom-ready": { "name": "@wordpress/dom-ready", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -53908,7 +53908,7 @@ }, "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", - "version": "11.10.0", + "version": "11.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53930,7 +53930,7 @@ }, "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.10.0", + "version": "1.11.0", "license": "GPL-2.0-or-later", "dependencies": { "change-case": "^4.1.2", @@ -53956,7 +53956,7 @@ }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", - "version": "8.10.1", + "version": "8.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/e2e-test-utils": "*", @@ -53994,7 +53994,7 @@ }, "packages/edit-post": { "name": "@wordpress/edit-post", - "version": "8.10.0", + "version": "8.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54041,7 +54041,7 @@ }, "packages/edit-site": { "name": "@wordpress/edit-site", - "version": "6.10.0", + "version": "6.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54104,7 +54104,7 @@ }, "packages/edit-widgets": { "name": "@wordpress/edit-widgets", - "version": "6.10.0", + "version": "6.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54148,7 +54148,7 @@ }, "packages/editor": { "name": "@wordpress/editor", - "version": "14.10.0", + "version": "14.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54210,7 +54210,7 @@ }, "packages/element": { "name": "@wordpress/element", - "version": "6.10.0", + "version": "6.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54229,7 +54229,7 @@ }, "packages/env": { "name": "@wordpress/env", - "version": "10.10.0", + "version": "10.11.0", "license": "GPL-2.0-or-later", "dependencies": { "chalk": "^4.0.0", @@ -54360,7 +54360,7 @@ }, "packages/escape-html": { "name": "@wordpress/escape-html", - "version": "3.10.0", + "version": "3.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54372,7 +54372,7 @@ }, "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", - "version": "21.3.0", + "version": "21.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/eslint-parser": "7.25.7", @@ -54441,7 +54441,7 @@ }, "packages/fields": { "name": "@wordpress/fields", - "version": "0.2.0", + "version": "0.3.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54480,7 +54480,7 @@ }, "packages/format-library": { "name": "@wordpress/format-library", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54508,7 +54508,7 @@ }, "packages/hooks": { "name": "@wordpress/hooks", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54520,7 +54520,7 @@ }, "packages/html-entities": { "name": "@wordpress/html-entities", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54532,7 +54532,7 @@ }, "packages/i18n": { "name": "@wordpress/i18n", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54552,7 +54552,7 @@ }, "packages/icons": { "name": "@wordpress/icons", - "version": "10.10.0", + "version": "10.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54566,7 +54566,7 @@ }, "packages/interactivity": { "name": "@wordpress/interactivity", - "version": "6.10.0", + "version": "6.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@preact/signals": "^1.3.0", @@ -54579,7 +54579,7 @@ }, "packages/interactivity-router": { "name": "@wordpress/interactivity-router", - "version": "2.10.0", + "version": "2.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/a11y": "*", @@ -54592,7 +54592,7 @@ }, "packages/interface": { "name": "@wordpress/interface", - "version": "7.0.0", + "version": "8.0.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54620,7 +54620,7 @@ }, "packages/is-shallow-equal": { "name": "@wordpress/is-shallow-equal", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54632,7 +54632,7 @@ }, "packages/jest-console": { "name": "@wordpress/jest-console", - "version": "8.10.0", + "version": "8.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54648,7 +54648,7 @@ }, "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", - "version": "12.10.0", + "version": "12.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/jest-console": "*", @@ -54665,7 +54665,7 @@ }, "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.10.0", + "version": "7.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@axe-core/puppeteer": "^4.0.0", @@ -54687,7 +54687,7 @@ }, "packages/keyboard-shortcuts": { "name": "@wordpress/keyboard-shortcuts", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54705,7 +54705,7 @@ }, "packages/keycodes": { "name": "@wordpress/keycodes", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54718,7 +54718,7 @@ }, "packages/lazy-import": { "name": "@wordpress/lazy-import", - "version": "2.10.0", + "version": "2.11.0", "license": "GPL-2.0-or-later", "dependencies": { "execa": "^4.0.2", @@ -54732,7 +54732,7 @@ }, "packages/list-reusable-blocks": { "name": "@wordpress/list-reusable-blocks", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54755,7 +54755,7 @@ }, "packages/media-utils": { "name": "@wordpress/media-utils", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54771,7 +54771,7 @@ }, "packages/notices": { "name": "@wordpress/notices", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54788,7 +54788,7 @@ }, "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -54800,7 +54800,7 @@ }, "packages/nux": { "name": "@wordpress/nux", - "version": "9.10.0", + "version": "9.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54823,7 +54823,7 @@ }, "packages/patterns": { "name": "@wordpress/patterns", - "version": "2.10.0", + "version": "2.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54853,7 +54853,7 @@ }, "packages/plugins": { "name": "@wordpress/plugins", - "version": "7.10.0", + "version": "7.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54877,7 +54877,7 @@ }, "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/base-styles": "*", @@ -54893,7 +54893,7 @@ }, "packages/postcss-themes": { "name": "@wordpress/postcss-themes", - "version": "6.10.0", + "version": "6.11.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -54905,7 +54905,7 @@ }, "packages/preferences": { "name": "@wordpress/preferences", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54931,7 +54931,7 @@ }, "packages/preferences-persistence": { "name": "@wordpress/preferences-persistence", - "version": "2.10.0", + "version": "2.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54944,7 +54944,7 @@ }, "packages/prettier-config": { "name": "@wordpress/prettier-config", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -54956,7 +54956,7 @@ }, "packages/primitives": { "name": "@wordpress/primitives", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54973,7 +54973,7 @@ }, "packages/priority-queue": { "name": "@wordpress/priority-queue", - "version": "3.10.0", + "version": "3.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54986,7 +54986,7 @@ }, "packages/private-apis": { "name": "@wordpress/private-apis", - "version": "1.10.0", + "version": "1.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54998,7 +54998,7 @@ }, "packages/project-management-automation": { "name": "@wordpress/project-management-automation", - "version": "2.10.0", + "version": "2.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@actions/core": "1.9.1", @@ -55026,7 +55026,7 @@ }, "packages/react-i18n": { "name": "@wordpress/react-i18n", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55182,7 +55182,7 @@ }, "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.10.0", + "version": "3.11.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55194,7 +55194,7 @@ }, "packages/redux-routine": { "name": "@wordpress/redux-routine", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55237,7 +55237,7 @@ }, "packages/reusable-blocks": { "name": "@wordpress/reusable-blocks", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55264,7 +55264,7 @@ }, "packages/rich-text": { "name": "@wordpress/rich-text", - "version": "7.10.0", + "version": "7.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55288,7 +55288,7 @@ }, "packages/router": { "name": "@wordpress/router", - "version": "1.10.0", + "version": "1.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55307,7 +55307,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "30.3.0", + "version": "30.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -55741,7 +55741,7 @@ }, "packages/server-side-render": { "name": "@wordpress/server-side-render", - "version": "5.10.0", + "version": "5.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55767,7 +55767,7 @@ }, "packages/shortcode": { "name": "@wordpress/shortcode", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55780,7 +55780,7 @@ }, "packages/style-engine": { "name": "@wordpress/style-engine", - "version": "2.10.0", + "version": "2.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55793,7 +55793,7 @@ }, "packages/stylelint-config": { "name": "@wordpress/stylelint-config", - "version": "23.2.0", + "version": "23.3.0", "license": "MIT", "dependencies": { "@stylistic/stylelint-plugin": "^3.0.1", @@ -55904,7 +55904,7 @@ }, "packages/sync": { "name": "@wordpress/sync", - "version": "1.10.0", + "version": "1.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55925,7 +55925,7 @@ }, "packages/token-list": { "name": "@wordpress/token-list", - "version": "3.10.0", + "version": "3.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -55937,7 +55937,7 @@ }, "packages/undo-manager": { "name": "@wordpress/undo-manager", - "version": "1.10.0", + "version": "1.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55950,7 +55950,7 @@ }, "packages/url": { "name": "@wordpress/url", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55963,7 +55963,7 @@ }, "packages/viewport": { "name": "@wordpress/viewport", - "version": "6.10.0", + "version": "6.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55993,7 +55993,7 @@ }, "packages/warning": { "name": "@wordpress/warning", - "version": "3.10.0", + "version": "3.11.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -56002,7 +56002,7 @@ }, "packages/widgets": { "name": "@wordpress/widgets", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56030,7 +56030,7 @@ }, "packages/wordcount": { "name": "@wordpress/wordcount", - "version": "4.10.0", + "version": "4.11.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 217a3086225923..09fa62a9d082b7 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/package.json b/packages/annotations/package.json index f3f7f741aca408..8a94b326a78194 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.11.0-prerelease", + "version": "3.11.0", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 25c95723445174..26f156a0aa7d77 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.11.0-prerelease", + "version": "7.11.0", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/package.json b/packages/autop/package.json index 3d21dfd5ca7d1a..2169ff828da47a 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index cc60e407de6918..d9b565b4e27ec0 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index d952ab50de0d0d..cf04d3dc72e409 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.11.0-prerelease", + "version": "6.11.0", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 62e9d8888a9b91..2f727d1886425d 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.11.0-prerelease", + "version": "8.11.0", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index 1135af7b99ccd4..7246dc83eaf4c6 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/package.json b/packages/blob/package.json index de1b394f5a618c..4b04d2ea2ddebd 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 9fa529b364a649..59025e1ad45c7a 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 0fb08d702fac21..2b5cc8d6275e89 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.6.0-prerelease", + "version": "14.6.0", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 1c078354c12474..2c880301c8355d 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.11.0-prerelease", + "version": "9.11.0", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 00a498bc9b1fa5..d31ab188c0b6d6 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 94325ad9129457..7cca4a7ca1a68b 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 5fd6d24bb0c9e9..2d944fe656363b 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "14.0.0-prerelease", + "version": "14.0.0", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 645e72e423008c..65bc5231f0651b 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.11.0-prerelease", + "version": "6.11.0", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/package.json b/packages/commands/package.json index 20cdce012c7a58..98eadca595ca86 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.11.0-prerelease", + "version": "1.11.0", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/package.json b/packages/components/package.json index abb1ade4c23fcc..faf923ad426bf6 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.11.0-prerelease", + "version": "28.11.0", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/package.json b/packages/compose/package.json index 6123737dcf71bd..adff24f6663006 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.11.0-prerelease", + "version": "7.11.0", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 30fff81216e91b..ac15b3578cf6ff 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.11.0-prerelease", + "version": "1.11.0", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/package.json b/packages/core-data/package.json index aca278be9e2614..44ed3aaad5dd3a 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.11.0-prerelease", + "version": "7.11.0", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index 7ea6f1321a7974..bd34bed4d2e256 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.11.0-prerelease", + "version": "2.11.0", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index 65ef110fa5151b..c2ea39fad8ba74 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/package.json b/packages/create-block/package.json index fb956151412230..dbb8e56ea72151 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.54.0-prerelease", + "version": "4.54.0", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 31de3890b7c756..ef6748f34205e8 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 8910574746a571..948efe7fb64022 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/package.json b/packages/data/package.json index 7bd62c4dcc6f80..0e46b1a366918e 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.11.0-prerelease", + "version": "10.11.0", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index 0e215caf4e9397..5599a84b92d34c 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.7.0-prerelease", + "version": "4.7.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/package.json b/packages/date/package.json index 31b0de0bb9f432..f53c6314912271 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index aac150751d8686..cb7a4e60bf015d 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.11.0-prerelease", + "version": "6.11.0", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 17142259d08a67..69d2414b0c11a2 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 2853999ff1cd39..be73d0625b63ed 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.11.0-prerelease", + "version": "2.11.0", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 7ce289b6875908..0202229b202842 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/package.json b/packages/dom/package.json index fa7213d761c934..58c572545cc526 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index d0088dfa47a9ed..8a2703bfdec54d 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.11.0-prerelease", + "version": "1.11.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index 21366e6535475e..2ff76b73ed2fbf 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.11.0-prerelease", + "version": "11.11.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 77bd6c7e31c424..cceaa6210a2dd9 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.11.0-prerelease", + "version": "8.11.0", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 01d45078c44fee..c594722d180e4f 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.11.0-prerelease", + "version": "8.11.0", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 3f44b9a984d2d9..95f9cd5f05742a 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.11.0-prerelease", + "version": "6.11.0", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 52461a7ef53ca7..0629dca5ec1052 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.11.0-prerelease", + "version": "6.11.0", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/package.json b/packages/editor/package.json index 97a7a70bfe82ea..61cce478cf08fe 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.11.0-prerelease", + "version": "14.11.0", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/package.json b/packages/element/package.json index 7767010efc92e8..3004dadb7ea605 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.11.0-prerelease", + "version": "6.11.0", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/package.json b/packages/env/package.json index 35032c79741045..a03004abb83283 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.11.0-prerelease", + "version": "10.11.0", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 8b334925719dbc..72863ce15fd8b8 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.11.0-prerelease", + "version": "3.11.0", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index f6e8683fdd4c95..8e2d3e2c97e2bf 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "21.4.0-prerelease", + "version": "21.4.0", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/fields/package.json b/packages/fields/package.json index 1494770badb5f8..e0b7125cf3e4eb 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/fields", - "version": "0.3.0-prerelease", + "version": "0.3.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/package.json b/packages/format-library/package.json index bea85d21f9bf15..f07ba0f4b61b35 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/package.json b/packages/hooks/package.json index c9a459eeb6a956..d0f2fd381b83ca 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index d9a6d78b079e89..d717a89bf049b8 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 08ed3aee5da1f2..33de2873f75a6a 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/package.json b/packages/icons/package.json index 5793ca9064bd6b..125b6f19beaa02 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.11.0-prerelease", + "version": "10.11.0", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 870418bac4d0af..ce9b268af556ac 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.11.0-prerelease", + "version": "2.11.0", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index c485de7e34eae8..106ed44bf44d39 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.11.0-prerelease", + "version": "6.11.0", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/package.json b/packages/interface/package.json index 69fe4cad7f5d93..807135ae0160a6 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "8.0.0-prerelease", + "version": "8.0.0", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index e55c591c68e9de..8da2643a58b840 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index af334bd3562b99..78213b83e7ee54 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.11.0-prerelease", + "version": "8.11.0", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 41db85e5b250bc..7a16a2bdd46d49 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.11.0-prerelease", + "version": "12.11.0", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 4a125f4d9c17c5..4ea7c641be0e1d 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.11.0-prerelease", + "version": "7.11.0", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index ba17110a370a60..50ee79d554a89f 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 51f1338bf3fbb8..3e820ef68cf97e 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index e3a327dcff8731..af18373147c986 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.11.0-prerelease", + "version": "2.11.0", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index ca3db667889062..129909a948ef1d 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index dd30c636e514b2..050e1ab96f2929 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/package.json b/packages/notices/package.json index 955fa43b652d39..34d2253870128b 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index 284a6522b00b72..c02560393b9a9f 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/package.json b/packages/nux/package.json index 4fd9cba3b3ca72..ccf1cb774c2424 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.11.0-prerelease", + "version": "9.11.0", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 5575ff39ce2572..92ef655dc3c9c7 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.11.0-prerelease", + "version": "2.11.0", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/package.json b/packages/plugins/package.json index ffd8bde2f53247..b741c0359b32b1 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.11.0-prerelease", + "version": "7.11.0", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 71258db246e2d7..cda39c4a0bf0bf 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index 3cd813014db8b7..613b00789e78eb 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.11.0-prerelease", + "version": "6.11.0", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index 20f20a56c5c314..e2623eac1a021c 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.11.0-prerelease", + "version": "2.11.0", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/package.json b/packages/preferences/package.json index bfb66311b1aadb..ef231f359ba143 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 1b19dc7a3be291..367a782acffc4d 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/package.json b/packages/primitives/package.json index ca999e8f9b792b..04c3cc86dddec3 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index ef5103f5f79334..91020c0f81db24 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.11.0-prerelease", + "version": "3.11.0", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index a750c6f2abcd17..9364a596c39af0 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.11.0-prerelease", + "version": "1.11.0", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index d286c2be59048b..a3f6e3f0a44230 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.11.0-prerelease", + "version": "2.11.0", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 64c03f757998d1..d98a4d7711f89c 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index cffe3669586a33..3e7d14813968ee 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.11.0-prerelease", + "version": "3.11.0", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 8fd54ddf2ed340..489bc14632ded2 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index b212e297aeee2c..82a812163a0ccc 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 797489ea4601c6..4a5fe0f8e9d5ca 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.11.0-prerelease", + "version": "7.11.0", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/package.json b/packages/router/package.json index 8cb1c6bdd6c5fd..1822e79a317102 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.11.0-prerelease", + "version": "1.11.0", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 0e1a0f4a3be87b..3a50d921145e19 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.4.0-prerelease", + "version": "30.4.0", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index c351ec53f7b3f9..0bb27f17ad62d0 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.11.0-prerelease", + "version": "5.11.0", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index 7922786d04eb50..f85efeb91e1803 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 1ae658745a0973..76ce2ccbb1445d 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.11.0-prerelease", + "version": "2.11.0", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index aecc448f28d0e2..0043e0a62be412 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "23.3.0-prerelease", + "version": "23.3.0", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/package.json b/packages/sync/package.json index a11264ec838c9c..95be09803a75f1 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.11.0-prerelease", + "version": "1.11.0", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 7998b48e6730bc..0d966edeb9ee7d 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.11.0-prerelease", + "version": "3.11.0", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index d7087e7d7084ef..f0464d7fd2f9e2 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.11.0-prerelease", + "version": "1.11.0", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/package.json b/packages/url/package.json index 5370e545054f84..885efe28f8e8b4 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 9064976528afba..05e098f65e1aeb 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.11.0-prerelease", + "version": "6.11.0", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/package.json b/packages/warning/package.json index 67c33a001cc245..cae2aefa421ffe 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.11.0-prerelease", + "version": "3.11.0", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 4efa23343f8c01..b7fa362d615856 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index bb898184019cb0..a9f8304f79d8ff 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.11.0-prerelease", + "version": "4.11.0", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 2b67cd9a4f37170c1e6c87b14788933c1ffb03c5 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 30 Oct 2024 14:02:25 +0000 Subject: [PATCH 1402/1908] Update Changelog for 19.6.0-rc.1 --- changelog.txt | 331 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 331 insertions(+) diff --git a/changelog.txt b/changelog.txt index 2b10884ae10885..ca5175bc74eb46 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,336 @@ == Changelog == += 19.6.0-rc.1 = + +## Changelog + +### Enhancements + +- BlockGroupToolbar: Better i18n context for toolbar labels. ([66211](https://github.com/WordPress/gutenberg/pull/66211)) +- Core Data: Add the 'getEntitiesConfig' resolver. ([65871](https://github.com/WordPress/gutenberg/pull/65871)) +- Create Block: Adds `--target-dir` flag to allow the tool to target where to scaffold. ([53781](https://github.com/WordPress/gutenberg/pull/53781)) +- Editor Interface: Remove small header from global styles/plugin sidebar. ([64474](https://github.com/WordPress/gutenberg/pull/64474)) +- Remove purple coloring from DocumentBar and PostCard. ([66451](https://github.com/WordPress/gutenberg/pull/66451)) +- Scripts: Add BlueOak-1.0.0 license to GPL2 compatible. ([66139](https://github.com/WordPress/gutenberg/pull/66139)) +- WP Scripts: Add a `--root-folder` argument to the `plugin-zip` command. ([61375](https://github.com/WordPress/gutenberg/pull/61375)) + +#### Components +- Add elevation tokens to storybook. ([66122](https://github.com/WordPress/gutenberg/pull/66122)) +- Add foundations:Elevation to storybook. ([66124](https://github.com/WordPress/gutenberg/pull/66124)) +- Add radius foundation and tokens to storybook. ([66219](https://github.com/WordPress/gutenberg/pull/66219)) +- Combobox, FormTokenField: Show message when no matches found. ([66142](https://github.com/WordPress/gutenberg/pull/66142)) +- Storybook: Organizes components under 'Utilities'. ([66210](https://github.com/WordPress/gutenberg/pull/66210)) +- Tabs: Expose active tab item props, use ariakit prop types. ([66223](https://github.com/WordPress/gutenberg/pull/66223)) +- Tabs: Remove custom logic. ([66097](https://github.com/WordPress/gutenberg/pull/66097)) +- `DropdownMenuV2`: Rename to `Menu`. ([66289](https://github.com/WordPress/gutenberg/pull/66289)) + +#### Block Library +- Add Transformation from Separator to Spacer. ([66230](https://github.com/WordPress/gutenberg/pull/66230)) +- Add lightbox option in gallery block link control. ([64014](https://github.com/WordPress/gutenberg/pull/64014)) +- Archives: Add border block support. ([63400](https://github.com/WordPress/gutenberg/pull/63400)) +- Border support added to comments. ([66354](https://github.com/WordPress/gutenberg/pull/66354)) +- Cover Block: Add Image Resolution options. ([62926](https://github.com/WordPress/gutenberg/pull/62926)) +- HTML Block: Force HTML preview in view mode. ([66440](https://github.com/WordPress/gutenberg/pull/66440)) + +#### Zoom Out +- Add keyboard shortcut in editor. ([66400](https://github.com/WordPress/gutenberg/pull/66400)) +- Iterate zoom out shuffle into a more visual control. ([66194](https://github.com/WordPress/gutenberg/pull/66194)) +- Use the zoom-level value to scale the iframe. ([66280](https://github.com/WordPress/gutenberg/pull/66280)) + +#### Site Editor +- Remove synchronization of canvas mode into store. ([66213](https://github.com/WordPress/gutenberg/pull/66213)) +- Style Book: Clean up layout. ([66255](https://github.com/WordPress/gutenberg/pull/66255)) +- Update site icon and title position. ([66171](https://github.com/WordPress/gutenberg/pull/66171)) + +#### Data Views +- Fix alignment of action items in list layout. ([66273](https://github.com/WordPress/gutenberg/pull/66273)) +- Templates: Hide media field in list view. ([66573](https://github.com/WordPress/gutenberg/pull/66573)) + +#### Global Styles +- Backport: Caching of global styles for blocks from core. ([66349](https://github.com/WordPress/gutenberg/pull/66349)) +- Style Book: Add color tab. ([65692](https://github.com/WordPress/gutenberg/pull/65692)) + +#### Real-time Collaboration +- Inline Commenting: Disable comments on published posts for now. ([66583](https://github.com/WordPress/gutenberg/pull/66583)) + +#### Post Editor +- Set `ResizableEditor` height based on border-box. ([66342](https://github.com/WordPress/gutenberg/pull/66342)) + +#### Icons +- Add align-item related icons. ([66242](https://github.com/WordPress/gutenberg/pull/66242)) + +#### REST API +- Backport from WordPress core: Improvements for the post format query loop filter. ([66037](https://github.com/WordPress/gutenberg/pull/66037)) + + +### New APIs + +- Stabilize isPreviewMode flag. ([66149](https://github.com/WordPress/gutenberg/pull/66149)) +- scripts: Add build-blocks-manifest command. ([65866](https://github.com/WordPress/gutenberg/pull/65866)) + + +### Bug Fixes + +- Create block: Ensure $slug is replaced with passed slug. ([66528](https://github.com/WordPress/gutenberg/pull/66528)) +- Fix extraneous scrollbar in device previews. ([66494](https://github.com/WordPress/gutenberg/pull/66494)) +- GH-66090: Self nesting and circular nesting block fix. ([66121](https://github.com/WordPress/gutenberg/pull/66121)) +- Global styles: Move preload paths filter to 6.7 (previously 6.8). ([66543](https://github.com/WordPress/gutenberg/pull/66543)) +- Miscellaneous i18n fixes. ([66510](https://github.com/WordPress/gutenberg/pull/66510)) +- Remove most of the occurrences of the verb toggle. ([66371](https://github.com/WordPress/gutenberg/pull/66371)) +- SpacingSizesControl: Use generic label for linked button. ([66304](https://github.com/WordPress/gutenberg/pull/66304)) + +#### Zoom Out +- Disable zoom out toggle button when Style Book is open. ([66228](https://github.com/WordPress/gutenberg/pull/66228)) +- Don't switch editor mode when changing entities. ([66452](https://github.com/WordPress/gutenberg/pull/66452)) +- Fix scaling animation for device previews. ([66132](https://github.com/WordPress/gutenberg/pull/66132)) +- Fix zoom out not persisting while switching between editor and code editor. ([65932](https://github.com/WordPress/gutenberg/pull/65932)) +- Fix zoom out shortcut on Windows. ([66506](https://github.com/WordPress/gutenberg/pull/66506)) +- Fix: Activate zoom out on large viewport. ([66308](https://github.com/WordPress/gutenberg/pull/66308)) +- Hide slots and grouping buttons. ([66243](https://github.com/WordPress/gutenberg/pull/66243)) +- Remove zoom-out toolbar. ([66039](https://github.com/WordPress/gutenberg/pull/66039)) +- Resets the Zoom on viewed/edited entity change. ([66232](https://github.com/WordPress/gutenberg/pull/66232)) +- Revise zoom layout shift fix. ([66390](https://github.com/WordPress/gutenberg/pull/66390)) +- Zoom-out: Rely on zoom-level instead of zoom-out mode. ([66141](https://github.com/WordPress/gutenberg/pull/66141)) + +#### Block Editor +- Block inserter: Prevent editor from crashing if `blockType.parent` is a string. ([66234](https://github.com/WordPress/gutenberg/pull/66234)) +- Block toolbar: Account for scrollable blocks that affect the position of the block toolbar. ([66188](https://github.com/WordPress/gutenberg/pull/66188)) +- Fix extra scrollbar appearing when searching in the inserter. ([66229](https://github.com/WordPress/gutenberg/pull/66229)) +- Fix: Show paragraph block variations in rich text inserter. ([66318](https://github.com/WordPress/gutenberg/pull/66318)) +- Group: Fix padding select. ([65857](https://github.com/WordPress/gutenberg/pull/65857)) +- Link Shortcut: Only trigger the link shortcut if there's a text selection. ([66056](https://github.com/WordPress/gutenberg/pull/66056)) +- Remove relative position from sidebar tabpanel. ([66267](https://github.com/WordPress/gutenberg/pull/66267)) +- Rich text: Remove empty file. ([66553](https://github.com/WordPress/gutenberg/pull/66553)) +- Zoom Out: Fix bouncy drop zones. ([66399](https://github.com/WordPress/gutenberg/pull/66399)) + +#### Components +- ColorPalette: Prevent overflow of custom color button background. ([66152](https://github.com/WordPress/gutenberg/pull/66152)) +- Fix: Text overflow in Patterns filter. ([66504](https://github.com/WordPress/gutenberg/pull/66504)) +- RadioGroup: Fix arrow key navigation in RTL. ([66202](https://github.com/WordPress/gutenberg/pull/66202)) +- Tabs and TabPanel: Fix arrow key navigation in RTL. ([66201](https://github.com/WordPress/gutenberg/pull/66201)) +- Tabs and ToggleGroupControl: Round indicator size. ([66426](https://github.com/WordPress/gutenberg/pull/66426)) +- Tabs: Fix animation timings. ([66198](https://github.com/WordPress/gutenberg/pull/66198)) +- Tabs: Override tablist's tabindex only when necessary. ([66209](https://github.com/WordPress/gutenberg/pull/66209)) +- Tabs: Restore vertical alignment for tabs content. ([66215](https://github.com/WordPress/gutenberg/pull/66215)) +- Tabs: Update indicator more reactively. ([66207](https://github.com/WordPress/gutenberg/pull/66207)) + +#### Post Editor +- Always force iframe in pattern editor. ([65887](https://github.com/WordPress/gutenberg/pull/65887)) +- Editor: Multi-entity saving: Show correct count of entities to be saved. ([66482](https://github.com/WordPress/gutenberg/pull/66482)) +- Fix : "Set featured image" button border flashes on focus. ([66092](https://github.com/WordPress/gutenberg/pull/66092)) +- Fix Parent Check Condition in `buildTermsTree`. ([66006](https://github.com/WordPress/gutenberg/pull/66006)) +- Fix: Improve the DocumentBar post type label for the Homepage and Posts Page cases. ([66355](https://github.com/WordPress/gutenberg/pull/66355)) +- PostTaxonomiesFlatTermSelector: Restore space between tag list and most used tags. ([66566](https://github.com/WordPress/gutenberg/pull/66566)) + +#### Block Library +- Block registration: Normalize blockType.parent to `array`. ([66250](https://github.com/WordPress/gutenberg/pull/66250)) +- Button Block: Apply Stretch Styles Correctly. ([64770](https://github.com/WordPress/gutenberg/pull/64770)) +- Buttons: Fix the initial white space in nofollow rel. ([66303](https://github.com/WordPress/gutenberg/pull/66303)) +- Fix - Image block: Aspect ratio not responding when dimensions are not set. ([66217](https://github.com/WordPress/gutenberg/pull/66217)) +- Navigation block: Fix block appender size. ([66153](https://github.com/WordPress/gutenberg/pull/66153)) + +#### Site Editor +- Edit Site: Fix canvasMode var. ([66316](https://github.com/WordPress/gutenberg/pull/66316)) +- Fix button hover style in sidebar navigation screen. ([66505](https://github.com/WordPress/gutenberg/pull/66505)) +- Remove toggle verb from post list data views 'Toggle details panel'. ([66334](https://github.com/WordPress/gutenberg/pull/66334)) +- Revert 66431 (Site editor: Remove "default" admin CSS). ([66540](https://github.com/WordPress/gutenberg/pull/66540)) + +#### Meta Boxes +- Typo metabox pane is a meta box panel. ([66502](https://github.com/WordPress/gutenberg/pull/66502)) + +#### REST API +- Preload: Fix multiple regressions around global styles. ([66468](https://github.com/WordPress/gutenberg/pull/66468)) + +#### Style Book +- Fix comment output in styles. ([66439](https://github.com/WordPress/gutenberg/pull/66439)) + +#### Saving +- Site editor: Fix save shortcut. ([66423](https://github.com/WordPress/gutenberg/pull/66423)) + +#### CSS & Styling +- Fix the navigation issue inside cover blocks. ([66093](https://github.com/WordPress/gutenberg/pull/66093)) + + +### Accessibility + +- Update the speak messages when switching editor modes. ([66278](https://github.com/WordPress/gutenberg/pull/66278)) + +#### Post Editor +- Add featured image alt text. ([66189](https://github.com/WordPress/gutenberg/pull/66189)) +- Fix : Badge Color contrast. ([66360](https://github.com/WordPress/gutenberg/pull/66360)) + +#### Block Editor +- ImageSizeControls: Replace ButtonGroup with ToggleGroupControl. ([65386](https://github.com/WordPress/gutenberg/pull/65386)) +- Improve the link preview accessibility and labels. ([60908](https://github.com/WordPress/gutenberg/pull/60908)) + +#### Block Library +- Search: Replace ButtonGroup usage with ToggleGroupControl. ([65340](https://github.com/WordPress/gutenberg/pull/65340)) + +#### Global Styles +- Global styles menu: Avoid visible labels and accessible names mismatch. ([65124](https://github.com/WordPress/gutenberg/pull/65124)) + +#### Site Editor +- Fix Global styles panel header buttons text overlap for 'Show button text labels'. ([63243](https://github.com/WordPress/gutenberg/pull/63243)) + + +### Performance + +- Backport from Core: Reuse block metadata in WP_Theme_JSON::Get_valid_block_style_variations() for better performance. ([66539](https://github.com/WordPress/gutenberg/pull/66539)) +- tests : - Fix/compare performance with correct branch. ([66196](https://github.com/WordPress/gutenberg/pull/66196)) + +#### Site Editor +- Remove "default" admin CSS. ([66431](https://github.com/WordPress/gutenberg/pull/66431)) +- Remove content styles outside canvas. ([66432](https://github.com/WordPress/gutenberg/pull/66432)) + +#### Block bindings +- Use `getEntityConfig` instead of `getPostTypes` to get available slugs. ([66101](https://github.com/WordPress/gutenberg/pull/66101)) + + +### Experiments + +- Add Inline comment experimental flag. ([60622](https://github.com/WordPress/gutenberg/pull/60622)) +- QuickEdit: Add slug field control. ([65196](https://github.com/WordPress/gutenberg/pull/65196)) + +#### Data Views +- Quick Edit: Fix JS error when bulk editing pages. ([66358](https://github.com/WordPress/gutenberg/pull/66358)) +- QuickEdit: Add Featured Image Control. ([64496](https://github.com/WordPress/gutenberg/pull/64496)) +- QuickEdit: Add Parent field. ([66527](https://github.com/WordPress/gutenberg/pull/66527)) + + +### Documentation + +- BaseControl: Auto-generate readme. ([66500](https://github.com/WordPress/gutenberg/pull/66500)) +- Components: Prevent generated readmes duplicating h1 elements when published. ([66180](https://github.com/WordPress/gutenberg/pull/66180)) +- Correct documentation on display type in flow layouts. ([66224](https://github.com/WordPress/gutenberg/pull/66224)) +- Docs: Interactivity API - Add documentation for `getServerState()` and `getServerContext()`. ([66104](https://github.com/WordPress/gutenberg/pull/66104)) +- Fix undo/redo Button size in Storybook playground. ([66538](https://github.com/WordPress/gutenberg/pull/66538)) +- Fix: JSON Schema Docgen doesn't work on Windows OS. ([66414](https://github.com/WordPress/gutenberg/pull/66414)) +- ItemGroup: Improve stories to default to bordered and separated. ([66191](https://github.com/WordPress/gutenberg/pull/66191)) +- README: Add Storybook badge. ([66529](https://github.com/WordPress/gutenberg/pull/66529)) +- Remove meetings that no longer occur from Contributor Guide. ([66421](https://github.com/WordPress/gutenberg/pull/66421)) +- Site editor routes: Add documentation for areas and prevent `edit` area from rendering when canvas is `edit`. ([66309](https://github.com/WordPress/gutenberg/pull/66309)) +- Update documentation about build process changes. ([66428](https://github.com/WordPress/gutenberg/pull/66428)) +- docs: Example for getSelectedBlock. ([66108](https://github.com/WordPress/gutenberg/pull/66108)) + + +### Code Quality + +- Block editor: Remove reusable blocks stylesheet from iframe. ([66285](https://github.com/WordPress/gutenberg/pull/66285)) +- Compose: Fix React Complier error for 'useCopyToClipboard'. ([66444](https://github.com/WordPress/gutenberg/pull/66444)) +- Composer: Fix React Compiler errors for 'useDropZone'. ([66469](https://github.com/WordPress/gutenberg/pull/66469)) +- Fields: Fix React Compiler mutation errors. ([66464](https://github.com/WordPress/gutenberg/pull/66464)) +- Interface: Remove duplicate 'withComplementaryAreaContext' file. ([66348](https://github.com/WordPress/gutenberg/pull/66348)) +- Interface: Remove unused private API support. ([66565](https://github.com/WordPress/gutenberg/pull/66565)) +- Interface: Use plugin context hook instead of HoC. ([66362](https://github.com/WordPress/gutenberg/pull/66362)) +- Remove clip & -webkit-clip-path for downloadable-block-list-item style.scss. ([66147](https://github.com/WordPress/gutenberg/pull/66147)) +- Scripts: Refactor to extract license logic. ([66179](https://github.com/WordPress/gutenberg/pull/66179)) +- Theme JSON: Get_block_nodes - relocate $selectors assignment. ([66265](https://github.com/WordPress/gutenberg/pull/66265)) +- Update a few function definitions. ([66315](https://github.com/WordPress/gutenberg/pull/66315)) + +#### Block Editor +- ESLint: Remove explicit `react-hooks/exhaustive-deps` disabling. ([66461](https://github.com/WordPress/gutenberg/pull/66461)) +- ESLint: Remove various React Compiler mutation violations. ([66327](https://github.com/WordPress/gutenberg/pull/66327)) +- Fix 'useInstanceId' hook reference. ([66406](https://github.com/WordPress/gutenberg/pull/66406)) +- Fix React Compiler error for Duotone. ([66492](https://github.com/WordPress/gutenberg/pull/66492)) +- Fix React Complier error for 'useEventListeners'. ([66495](https://github.com/WordPress/gutenberg/pull/66495)) +- Import only the actually used PostCSS exports. ([66379](https://github.com/WordPress/gutenberg/pull/66379)) +- No need to unlock public actions. ([66260](https://github.com/WordPress/gutenberg/pull/66260)) +- Remove patterns UI stylesheet from iframe. ([66306](https://github.com/WordPress/gutenberg/pull/66306)) +- Remove unnecessary Tooltip component from radius control linked button. ([66274](https://github.com/WordPress/gutenberg/pull/66274)) +- Rich Text: Fix React Complier error for 'useEventListeners'. ([66460](https://github.com/WordPress/gutenberg/pull/66460)) +- Storybook: Add BlockPatternsList story. ([66227](https://github.com/WordPress/gutenberg/pull/66227)) + +#### Components +- BorderBoxControl: Deprecate 36px default size. ([65752](https://github.com/WordPress/gutenberg/pull/65752)) +- BorderControl: Deprecate 36px default size. ([65755](https://github.com/WordPress/gutenberg/pull/65755)) +- DrodownMenuV2: Rename folder to `menu`. ([66473](https://github.com/WordPress/gutenberg/pull/66473)) +- ESLint: Stop disabling `react-hooks/exhaustive-deps` rule. ([66324](https://github.com/WordPress/gutenberg/pull/66324)) +- Fix React Compiler error for 'useAutocomplete'. ([66496](https://github.com/WordPress/gutenberg/pull/66496)) +- PaletteEdit: Use `ItemGroup` and `Item`, and avoid custom styles. ([66164](https://github.com/WordPress/gutenberg/pull/66164)) +- TabPanel: Add 40px size prop to tab Button. ([66557](https://github.com/WordPress/gutenberg/pull/66557)) +- Tabs: Align to standard compound components structure. ([66225](https://github.com/WordPress/gutenberg/pull/66225)) +- Tabs: Simplify styled components code. ([66208](https://github.com/WordPress/gutenberg/pull/66208)) + +#### Zoom Out +- Bundle behavior in block-editor and add story. ([66240](https://github.com/WordPress/gutenberg/pull/66240)) +- Editor: Handle zoom out state via the 'switchEditorMode' action. ([66262](https://github.com/WordPress/gutenberg/pull/66262)) +- Fix/html scale code quality. ([66181](https://github.com/WordPress/gutenberg/pull/66181)) +- Make useZoomOut hook private. ([66374](https://github.com/WordPress/gutenberg/pull/66374)) +- Remove double click to exit hook from the block-editor package. ([66335](https://github.com/WordPress/gutenberg/pull/66335)) +- Remove viewport check from useZoomOut hook. ([66341](https://github.com/WordPress/gutenberg/pull/66341)) + +#### Post Editor +- Editor: No need to reset mode when changing device preview types. ([66261](https://github.com/WordPress/gutenberg/pull/66261)) +- Editor: Use plugin context hook in 'PluginMoreMenuItem'. ([66351](https://github.com/WordPress/gutenberg/pull/66351)) +- Editor: Use plugin context hook in 'PluginPreviewMenuItem'. ([66350](https://github.com/WordPress/gutenberg/pull/66350)) +- Fix typo after #63669. ([66396](https://github.com/WordPress/gutenberg/pull/66396)) +- Remove leftover JS code from 66451. ([66472](https://github.com/WordPress/gutenberg/pull/66472)) + +#### Block Library +- Cleanup unnecessary notice removal. ([66409](https://github.com/WordPress/gutenberg/pull/66409)) +- ESLint: Fix a couple of React Compiler reassignment errors. ([66331](https://github.com/WordPress/gutenberg/pull/66331)) +- Footnotes: Remove extra callback when parsing content. ([66370](https://github.com/WordPress/gutenberg/pull/66370)) +- Gallery: Fix React Compiler reassignment error. ([66408](https://github.com/WordPress/gutenberg/pull/66408)) +- Table Block: Remove hasArrowIndicator prop. ([66204](https://github.com/WordPress/gutenberg/pull/66204)) + +#### Style Book +- Avoid state/effect combo when generating values. ([66446](https://github.com/WordPress/gutenberg/pull/66446)) +- Fix React Compiler error. ([66445](https://github.com/WordPress/gutenberg/pull/66445)) + +#### Global Styles +- Clean up: Adjust reusable-blocks dependencies. ([66302](https://github.com/WordPress/gutenberg/pull/66302)) +- Fix React Compiler variable mutation error. ([66410](https://github.com/WordPress/gutenberg/pull/66410)) + +#### Interactivity API +- iAPI: Add comments to the `deepMerge()` function. ([66220](https://github.com/WordPress/gutenberg/pull/66220)) +- iAPI: Add tests for handling arrays in `deepMerge()`. ([66218](https://github.com/WordPress/gutenberg/pull/66218)) + +#### Navigation in Site View +- Navigation: Improve trigger for fallback navigation. ([66478](https://github.com/WordPress/gutenberg/pull/66478)) + +#### Plugins API +- Plugins: Deprecate 'withPluginContext' HOC. ([66363](https://github.com/WordPress/gutenberg/pull/66363)) + +#### Site Editor +- Prepare route registration by refactoring the site editor router. ([66030](https://github.com/WordPress/gutenberg/pull/66030)) + + +### Tools + +- Add theme type to the bug report issue template. ([63851](https://github.com/WordPress/gutenberg/pull/63851)) +- Pull request automation: Use full npm install. ([66314](https://github.com/WordPress/gutenberg/pull/66314)) +- Use npm workspaces for packages (second attempt). ([66272](https://github.com/WordPress/gutenberg/pull/66272)) + +#### Testing +- Fix [Flaky Test] Entering zoomed out mode zooms the canvas. ([66212](https://github.com/WordPress/gutenberg/pull/66212)) +- Fix end-to-end test for padding appender. ([66080](https://github.com/WordPress/gutenberg/pull/66080)) +- Upgrade Playwright to v1.48. ([66296](https://github.com/WordPress/gutenberg/pull/66296)) + +#### Build Tooling +- Add new private `vips` package. ([64845](https://github.com/WordPress/gutenberg/pull/64845)) +- Revert "Use npm workspaces for packages". ([66270](https://github.com/WordPress/gutenberg/pull/66270)) + + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @AhmarZaidi: Remove toggle verb from post list data views 'Toggle details panel'. ([66334](https://github.com/WordPress/gutenberg/pull/66334)) +- @mediaformat: Remove clip & -webkit-clip-path for downloadable-block-list-item style.scss. ([66147](https://github.com/WordPress/gutenberg/pull/66147)) +- @nicolasgalvez: WP Scripts: Add a `--root-folder` argument to the `plugin-zip` command. ([61375](https://github.com/WordPress/gutenberg/pull/61375)) +- @poojabhimani12: Add Inline comment experimental flag. ([60622](https://github.com/WordPress/gutenberg/pull/60622)) +- @rinkalpagdar: Border support added to comments. ([66354](https://github.com/WordPress/gutenberg/pull/66354)) +- @rudrakshi-gupta: Add Transformation from Separator to Spacer. ([66230](https://github.com/WordPress/gutenberg/pull/66230)) +- @SH4LIN: GH-66090: Self nesting and circular nesting block fix. ([66121](https://github.com/WordPress/gutenberg/pull/66121)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @afercia @AhmarZaidi @akasunil @andrewserong @carolinan @cbravobernal @ciampo @dhruvang21 @ellatrix @getdave @gigitux @hbhalodia @jameskoster @jeryj @jsnajdr @juanfra @madhusudhand @MaggieCabrera @Mamaduka @mattrwalker @mcsf @mediaformat @michalczaplinski @mirka @mreishus @ndiego @nicolasgalvez @ntsekouras @oandregal @PARTHVATALIYA @peterwilsoncc @poojabhimani12 @prajapatisagar @ramonjd @renatho @rinkalpagdar @rudrakshi-gupta @ryanwelcher @SantosGuillamot @SH4LIN @sirreal @stokesman @swissspidy @t-hamano @talldan @tellthemachines @torounit @troychaplin @tyxla @vipul0425 @Vrishabhsk @vykes-mac @youknowriad @zaguiini + + = 19.5.0 = ## Changelog From 09def4228b8f87966f26d9851dd6cbd4e98fa9e5 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:22:40 +0200 Subject: [PATCH 1403/1908] Introduce React Scanner for component usage stats (#65463) * Try: React Scanner for componenent usage stats * Fix globs and exclude dirs * Update glob to avoid native files * Filter out non-component elements * Add comments and exclude more dirs * Merge experimental and unstable components with canonical names * Specify processors explicitly * Count component usage only * Add back omitted comment * Bump react-scanner to v1.2.0 * Only count wp/components imports from outside the package * Default to components and props processor * Default to raw-report * Specify output directory, gitignore it * Fix globs to properly exclude native files * Do not merge unstable and experimental stats with canonical ones * Exclude a few more dirs Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .gitignore | 1 + package-lock.json | 240 +++++++++++++++++++++++++++++++++++++++- package.json | 2 + react-scanner.config.js | 31 ++++++ 4 files changed, 270 insertions(+), 4 deletions(-) create mode 100644 react-scanner.config.js diff --git a/.gitignore b/.gitignore index f699ecfcd4b9ba..4cd1d9706b7370 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ coverage # Directories/files that may appear in your environment *.log yarn.lock +results /artifacts /test/e2e/artifacts /perf-envs diff --git a/package-lock.json b/package-lock.json index 06a46df8855d94..e2093a8759fb83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -132,6 +132,7 @@ "react-native": "0.73.3", "react-native-url-polyfill": "1.1.2", "react-refresh": "0.14.0", + "react-scanner": "1.2.0", "react-test-renderer": "18.3.1", "reassure": "0.7.1", "redux": "4.1.2", @@ -18881,6 +18882,25 @@ "node": ">=4" } }, + "node_modules/astray": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/astray/-/astray-1.1.1.tgz", + "integrity": "sha512-LizvbENqdc8tdvrms/YyYoTtlr43INJni4YZSFr8nNdfOgafi82Hcrfhjm0MdwLhRFBrDhRwtH/0fnntlESxsQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "@types/estree": "^0.0.45" + } + }, + "node_modules/astray/node_modules/@types/estree": { + "version": "0.0.45", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.45.tgz", + "integrity": "sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==", + "dev": true, + "optional": true + }, "node_modules/async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", @@ -24156,6 +24176,12 @@ "node": ">=8" } }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, "node_modules/dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", @@ -24307,6 +24333,15 @@ "node": ">=12" } }, + "node_modules/dset": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -26453,6 +26488,12 @@ "pend": "~1.2.0" } }, + "node_modules/fdir": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-5.2.0.tgz", + "integrity": "sha512-skyI2Laxtj9GYzmktPgY6DT8uswXq+VoxH26SskykvEhTSbi7tRM/787uZt/p8maxrQCJdzC90zX1btbxiJ6lw==", + "dev": true + }, "node_modules/fecha": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", @@ -36968,6 +37009,15 @@ "rimraf": "bin.js" } }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/mrmime": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", @@ -43050,6 +43100,176 @@ } } }, + "node_modules/react-scanner": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/react-scanner/-/react-scanner-1.2.0.tgz", + "integrity": "sha512-gxdliEPTHpT5pQi23Efx+cvCEAzrRx9LeZXuptNRojBpQhOsPk+nQ3o/U8pfqFFc/BWwGipV1TqbG1I7zBgVZQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "8.8.0", + "astray": "1.1.1", + "dlv": "1.1.3", + "dset": "3.1.4", + "fdir": "5.2.0", + "is-plain-object": "5.0.0", + "picomatch": "2.3.1", + "sade": "1.8.1", + "typescript": "5.6.2" + }, + "bin": { + "react-scanner": "bin/react-scanner" + }, + "engines": { + "node": ">=14.x" + } + }, + "node_modules/react-scanner/node_modules/@typescript-eslint/types": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", + "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/react-scanner/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", + "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/react-scanner/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", + "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.8.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/react-scanner/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/react-scanner/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/react-scanner/node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/react-scanner/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/react-scanner/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/react-scanner/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/react-scanner/node_modules/typescript": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/react-shallow-renderer": { "version": "16.15.0", "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", @@ -44615,6 +44835,18 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, + "node_modules/sade": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "dev": true, + "dependencies": { + "mri": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/safaridriver": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/safaridriver/-/safaridriver-0.1.0.tgz", @@ -48064,11 +48296,11 @@ } }, "node_modules/ts-api-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.2.tgz", - "integrity": "sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" diff --git a/package.json b/package.json index 32c6f01b80c4ad..eb38bedd023914 100644 --- a/package.json +++ b/package.json @@ -141,6 +141,7 @@ "react-native": "0.73.3", "react-native-url-polyfill": "1.1.2", "react-refresh": "0.14.0", + "react-scanner": "1.2.0", "react-test-renderer": "18.3.1", "reassure": "0.7.1", "redux": "4.1.2", @@ -179,6 +180,7 @@ "build:plugin-zip": "bash ./bin/build-plugin-zip.sh", "clean:package-types": "tsc --build --clean && rimraf \"./packages/*/build-types\"", "clean:packages": "rimraf \"./packages/*/@(build|build-module|build-style)\"", + "component-usage-stats": "node ./node_modules/react-scanner/bin/react-scanner -c ./react-scanner.config.js", "dev": "cross-env NODE_ENV=development npm run build:packages && concurrently \"wp-scripts start\" \"npm run dev:packages\"", "dev:packages": "cross-env NODE_ENV=development concurrently \"node ./bin/packages/watch.js\" \"tsc --build --watch\"", "distclean": "git clean --force -d -X", diff --git a/react-scanner.config.js b/react-scanner.config.js new file mode 100644 index 00000000000000..7501e7e8fc3ab0 --- /dev/null +++ b/react-scanner.config.js @@ -0,0 +1,31 @@ +module.exports = { + // Crawl the entire repo + crawlFrom: './', + // Needed for properly reporting components with dot notation + includeSubComponents: true, + // Exclude usage in tests, stories, and React Native files. + globs: [ '**/!(test|stories)/!(*native).@(js|ts)?(x)' ], + // Exclude any vendor or docs directories + exclude: [ + 'bin', + 'build', + 'build-module', + 'docs', + 'node_modules', + 'patches', + 'platform-docs', + 'results', + 'schemas', + 'storybook', + 'test', + 'tools', + 'typings', + 'vendor', + ], + /* + * Filter out any non-component React elements and consider only imports of + * `@wordpress/components` outside of the package. + */ + importedFrom: '@wordpress/components', + processors: [ [ 'raw-report', { outputTo: './results/gutenberg.json' } ] ], +}; From 355dfd522f3f74c578fb813d95463943274074a2 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 30 Oct 2024 23:32:21 +0900 Subject: [PATCH 1404/1908] Storybook: Log `warning()` when in dev mode (#66568) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- storybook/main.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/storybook/main.js b/storybook/main.js index f111e9f5d8cd38..e482ee23c2e5fc 100644 --- a/storybook/main.js +++ b/storybook/main.js @@ -2,6 +2,7 @@ * External dependencies */ const path = require( 'path' ); +const DefinePlugin = require( 'webpack' ).DefinePlugin; /** * WordPress dependencies @@ -107,6 +108,15 @@ module.exports = { }, ], }, + plugins: [ + ...config.plugins, + new DefinePlugin( { + // Ensures that `@wordpress/warning` can properly detect dev mode. + 'globalThis.SCRIPT_DEBUG': JSON.stringify( + process.env.NODE_ENV === 'development' + ), + } ), + ], }; }, }; From d4c153a79a58fc1d2d7026273e5d4ffcc48edc7c Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 30 Oct 2024 23:33:48 +0900 Subject: [PATCH 1405/1908] Panel: Add 40px size prop to Button (#66589) * Panel: Add 40px size prop to Button * Add changelog * Update snapshot Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/panel/body.tsx | 1 + .../plugin-post-publish-panel/test/__snapshots__/index.js.snap | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 9c085abdae98c9..79b6acdd2e573e 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -34,6 +34,7 @@ - ESLint: Stop disabling `react-hooks/exhaustive-deps` rule ([#66324](https://github.com/WordPress/gutenberg/pull/66324)). - `TabPanel`: Add 40px size prop to tab Button ([#66557](https://github.com/WordPress/gutenberg/pull/66557)). +- `Panel`: Add 40px size prop to Button ([#66589](https://github.com/WordPress/gutenberg/pull/66589)). ## 28.10.0 (2024-10-16) diff --git a/packages/components/src/panel/body.tsx b/packages/components/src/panel/body.tsx index bf6b867dccbf45..ee1121ef04f4cb 100644 --- a/packages/components/src/panel/body.tsx +++ b/packages/components/src/panel/body.tsx @@ -116,6 +116,7 @@ const PanelBodyTitle = forwardRef( return ( <h2 className="components-panel__body-title"> <Button + __next40pxDefaultSize className="components-panel__body-toggle" aria-expanded={ isOpened } ref={ ref } diff --git a/packages/editor/src/components/plugin-post-publish-panel/test/__snapshots__/index.js.snap b/packages/editor/src/components/plugin-post-publish-panel/test/__snapshots__/index.js.snap index 5a057456d06aca..b144d525374c96 100644 --- a/packages/editor/src/components/plugin-post-publish-panel/test/__snapshots__/index.js.snap +++ b/packages/editor/src/components/plugin-post-publish-panel/test/__snapshots__/index.js.snap @@ -10,7 +10,7 @@ exports[`PluginPostPublishPanel renders fill properly 1`] = ` > <button aria-expanded="true" - class="components-button components-panel__body-toggle" + class="components-button components-panel__body-toggle is-next-40px-default-size" type="button" > <span From 6db97824093b485359962264ac7fedc60099938c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 14:35:43 +0000 Subject: [PATCH 1406/1908] Bump the github-actions group across 1 directory with 2 updates (#66475) Bumps the github-actions group with 2 updates in the / directory: [actions/checkout](https://github.com/actions/checkout) and [actions/setup-node](https://github.com/actions/setup-node). Updates `actions/checkout` from 4.2.1 to 4.2.2 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871...11bd71901bbe5b1630ceea73d27597364c9af683) Updates `actions/setup-node` from 4.0.4 to 4.1.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/0a44ba7841725637a19e28fa30b79a866c81b0a6...39370e3970a6d050c480ffad4ff0ed4d3fdee5af) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/build-plugin-zip.yml | 14 +++++++------- .github/workflows/bundle-size.yml | 4 ++-- .github/workflows/check-backport-changelog.yml | 2 +- .github/workflows/check-components-changelog.yml | 2 +- .github/workflows/cherry-pick-wp-release.yml | 2 +- .github/workflows/create-block.yml | 2 +- .github/workflows/end2end-test.yml | 4 ++-- .github/workflows/gradle-wrapper-validation.yml | 2 +- .github/workflows/performance.yml | 2 +- .github/workflows/publish-npm-packages.yml | 10 +++++----- .github/workflows/pull-request-automation.yml | 2 +- .github/workflows/rnmobile-android-runner.yml | 2 +- .github/workflows/rnmobile-ios-runner.yml | 2 +- .github/workflows/static-checks.yml | 4 ++-- .github/workflows/storybook-pages.yml | 2 +- .github/workflows/sync-backport-changelog.yml | 2 +- .github/workflows/unit-test.yml | 12 ++++++------ .../workflows/upload-release-to-plugin-repo.yml | 2 +- 18 files changed, 36 insertions(+), 36 deletions(-) diff --git a/.github/workflows/build-plugin-zip.yml b/.github/workflows/build-plugin-zip.yml index 9a3a9abb84963d..7ed57c5c5865ac 100644 --- a/.github/workflows/build-plugin-zip.yml +++ b/.github/workflows/build-plugin-zip.yml @@ -72,7 +72,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: token: ${{ secrets.GUTENBERG_TOKEN }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -168,13 +168,13 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ needs.bump-version.outputs.release_branch || github.ref }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 with: node-version-file: '.nvmrc' check-latest: true @@ -225,7 +225,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 ref: ${{ needs.bump-version.outputs.release_branch }} @@ -314,14 +314,14 @@ jobs: if: ${{ endsWith( needs.bump-version.outputs.new_version, '-rc.1' ) }} steps: - name: Checkout (for CLI) - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: path: main ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Checkout (for publishing) - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: path: publish # Later, we switch this branch in the script that publishes packages. @@ -336,7 +336,7 @@ jobs: git config user.email gutenberg@wordpress.org - name: Setup Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 with: node-version-file: 'main/.nvmrc' registry-url: 'https://registry.npmjs.org' diff --git a/.github/workflows/bundle-size.yml b/.github/workflows/bundle-size.yml index 4b0b93ac959ed8..3d95e7aa92bc16 100644 --- a/.github/workflows/bundle-size.yml +++ b/.github/workflows/bundle-size.yml @@ -37,13 +37,13 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 with: node-version-file: '.nvmrc' check-latest: true diff --git a/.github/workflows/check-backport-changelog.yml b/.github/workflows/check-backport-changelog.yml index 889e1cfb477256..48fb56b425be39 100644 --- a/.github/workflows/check-backport-changelog.yml +++ b/.github/workflows/check-backport-changelog.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest if: ${{ !contains(github.event.pull_request.labels.*.name, 'No Core Sync Required') && !contains(github.event.pull_request.labels.*.name, 'Backport from WordPress Core') }} steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.pull_request.head.ref }} repository: ${{ github.event.pull_request.head.repo.full_name }} diff --git a/.github/workflows/check-components-changelog.yml b/.github/workflows/check-components-changelog.yml index 2c0d52c77ea4e2..373a782d5d6ddf 100644 --- a/.github/workflows/check-components-changelog.yml +++ b/.github/workflows/check-components-changelog.yml @@ -22,7 +22,7 @@ jobs: - name: 'Get PR commit count' run: echo "PR_COMMIT_COUNT=$(( ${{ github.event.pull_request.commits }} + 1 ))" >> "${GITHUB_ENV}" - name: Checkout code - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.pull_request.head.ref }} repository: ${{ github.event.pull_request.head.repo.full_name }} diff --git a/.github/workflows/cherry-pick-wp-release.yml b/.github/workflows/cherry-pick-wp-release.yml index 5771a21d5b068b..14bee71c90c909 100644 --- a/.github/workflows/cherry-pick-wp-release.yml +++ b/.github/workflows/cherry-pick-wp-release.yml @@ -70,7 +70,7 @@ jobs: - name: Checkout repository if: env.cherry_pick == 'true' - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: token: ${{ secrets.GUTENBERG_TOKEN }} fetch-depth: 0 diff --git a/.github/workflows/create-block.yml b/.github/workflows/create-block.yml index 4d99d396996c59..1cb40466abe1ef 100644 --- a/.github/workflows/create-block.yml +++ b/.github/workflows/create-block.yml @@ -24,7 +24,7 @@ jobs: os: ['macos-latest', 'ubuntu-latest', 'windows-latest'] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/end2end-test.yml b/.github/workflows/end2end-test.yml index 2ea5949d20946c..ea85a8949573f3 100644 --- a/.github/workflows/end2end-test.yml +++ b/.github/workflows/end2end-test.yml @@ -27,7 +27,7 @@ jobs: totalParts: [8] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -102,7 +102,7 @@ jobs: steps: # Checkout defaults to using the branch which triggered the event, which # isn't necessarily `trunk` (e.g. in the case of a merge). - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index f268ac7183ee21..54378765bd26ff 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -6,7 +6,7 @@ jobs: name: 'Validation' runs-on: ubuntu-latest steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - uses: gradle/wrapper-validation-action@v3 diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index b947f4ff08c602..6c8c984602edcb 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -33,7 +33,7 @@ jobs: WP_ARTIFACTS_PATH: ${{ github.workspace }}/artifacts steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/publish-npm-packages.yml b/.github/workflows/publish-npm-packages.yml index b95a4baaf5075a..11cff85f4717a7 100644 --- a/.github/workflows/publish-npm-packages.yml +++ b/.github/workflows/publish-npm-packages.yml @@ -31,7 +31,7 @@ jobs: steps: - name: Checkout (for CLI) if: ${{ github.event.inputs.release_type != 'wp' }} - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: path: cli ref: trunk @@ -39,7 +39,7 @@ jobs: - name: Checkout (for publishing) if: ${{ github.event.inputs.release_type != 'wp' }} - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: path: publish # Later, we switch this branch in the script that publishes packages. @@ -49,7 +49,7 @@ jobs: - name: Checkout (for publishing WP major version) if: ${{ github.event.inputs.release_type == 'wp' && github.event.inputs.wp_version }} - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: path: publish ref: wp/${{ github.event.inputs.wp_version }} @@ -67,7 +67,7 @@ jobs: - name: Setup Node.js if: ${{ github.event.inputs.release_type != 'wp' }} - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 with: node-version-file: 'cli/.nvmrc' registry-url: 'https://registry.npmjs.org' @@ -75,7 +75,7 @@ jobs: - name: Setup Node.js (for WP major version) if: ${{ github.event.inputs.release_type == 'wp' && github.event.inputs.wp_version }} - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 with: node-version-file: 'publish/.nvmrc' registry-url: 'https://registry.npmjs.org' diff --git a/.github/workflows/pull-request-automation.yml b/.github/workflows/pull-request-automation.yml index cf37fa00c060bf..e1a3defc641aa3 100644 --- a/.github/workflows/pull-request-automation.yml +++ b/.github/workflows/pull-request-automation.yml @@ -12,7 +12,7 @@ jobs: steps: # Checkout defaults to using the branch which triggered the event, which # isn't necessarily `trunk` (e.g. in the case of a merge). - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index df302926f20cef..a57b857aac6234 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -23,7 +23,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/rnmobile-ios-runner.yml b/.github/workflows/rnmobile-ios-runner.yml index 90fb7e15fe4d1f..8851c7c12c4a4a 100644 --- a/.github/workflows/rnmobile-ios-runner.yml +++ b/.github/workflows/rnmobile-ios-runner.yml @@ -23,7 +23,7 @@ jobs: native-test-name: [gutenberg-editor-rendering] steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml index bf1a70d3adefc2..baf97e8d390e91 100644 --- a/.github/workflows/static-checks.yml +++ b/.github/workflows/static-checks.yml @@ -22,12 +22,12 @@ jobs: if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 with: node-version-file: '.nvmrc' check-latest: true diff --git a/.github/workflows/storybook-pages.yml b/.github/workflows/storybook-pages.yml index a0a7d0f12db1e5..4af4934cf0325b 100644 --- a/.github/workflows/storybook-pages.yml +++ b/.github/workflows/storybook-pages.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/sync-backport-changelog.yml b/.github/workflows/sync-backport-changelog.yml index 31b00459c24c6c..e530ca667de3d7 100644 --- a/.github/workflows/sync-backport-changelog.yml +++ b/.github/workflows/sync-backport-changelog.yml @@ -20,7 +20,7 @@ jobs: ) steps: - name: Checkout - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 # Fetch the last two commits to compare changes - name: Check for changes in backport-changelog diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index cb3ac1cc1b154f..46aa109c23e658 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -70,7 +70,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -121,7 +121,7 @@ jobs: name: Build JavaScript assets for PHP unit tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -173,7 +173,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -278,7 +278,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -348,7 +348,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/upload-release-to-plugin-repo.yml b/.github/workflows/upload-release-to-plugin-repo.yml index e8d3e3e245abd0..e866964e69b2d1 100644 --- a/.github/workflows/upload-release-to-plugin-repo.yml +++ b/.github/workflows/upload-release-to-plugin-repo.yml @@ -96,7 +96,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ matrix.branch }} token: ${{ secrets.GUTENBERG_TOKEN }} From 1f09e91d3cacc1a834804cd771861c79ff713cb6 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 30 Oct 2024 23:36:54 +0900 Subject: [PATCH 1407/1908] Popover: Add small size prop to close button (#66587) * Popover: Add small size prop to close button * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/popover/index.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 79b6acdd2e573e..ccafd5b79f0c0d 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -18,6 +18,7 @@ ### Enhancements - `PaletteEdit`: use `Item` internally instead of custom styles ([#66164](https://github.com/WordPress/gutenberg/pull/66164)). +- `Popover`: Use small size variant for close button when `expandOnMobile` prop is enabled ([#66587](https://github.com/WordPress/gutenberg/pull/66587)). ### Experimental diff --git a/packages/components/src/popover/index.tsx b/packages/components/src/popover/index.tsx index 3005f13c952ec0..1b7fb31539c6d0 100644 --- a/packages/components/src/popover/index.tsx +++ b/packages/components/src/popover/index.tsx @@ -419,6 +419,7 @@ const UnforwardedPopover = ( </span> <Button className="components-popover__close" + size="small" icon={ close } onClick={ onClose } /> From cd476fdaf151d527031c53a6d2359e0f40b2c643 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 30 Oct 2024 18:46:44 +0400 Subject: [PATCH 1408/1908] DataViews: Fix 'aria-label' for pattern preview element (#66601) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: kmanijak <karolmanijak@git.wordpress.org> --- packages/edit-site/src/components/page-patterns/fields.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/page-patterns/fields.js b/packages/edit-site/src/components/page-patterns/fields.js index 88de0c1fa39b01..74433b3de72f0e 100644 --- a/packages/edit-site/src/components/page-patterns/fields.js +++ b/packages/edit-site/src/components/page-patterns/fields.js @@ -45,7 +45,7 @@ function PreviewWrapper( { item, onClick, ariaDescribedBy, children } ) { className="page-patterns-preview-field__button" type="button" onClick={ item.type !== PATTERN_TYPES.theme ? onClick : undefined } - aria-label={ item.title } + aria-label={ defaultGetTitle( item ) } aria-describedby={ ariaDescribedBy } aria-disabled={ item.type === PATTERN_TYPES.theme } > From e62588a450d38aee9f25c7cd08f1ecb4c795238a Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 31 Oct 2024 00:16:32 +0900 Subject: [PATCH 1409/1908] Snackbar: Use `link` variant for action Button (#66560) * Snackbar: Use `link` variant for action button * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/snackbar/index.tsx | 3 ++- packages/components/src/snackbar/style.scss | 23 +++++++-------------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index ccafd5b79f0c0d..1f612bfae6597e 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Internal + +- `Snackbar`: Use link variant for action Button ([#66560](https://github.com/WordPress/gutenberg/pull/66560)). + ## 28.11.0 (2024-10-30) ### Deprecations diff --git a/packages/components/src/snackbar/index.tsx b/packages/components/src/snackbar/index.tsx index 0f2b74caca7d4a..dfcb0a6d8f2a84 100644 --- a/packages/components/src/snackbar/index.tsx +++ b/packages/components/src/snackbar/index.tsx @@ -150,9 +150,10 @@ function UnforwardedSnackbar( { actions.map( ( { label, onClick, url }, index ) => { return ( <Button + __next40pxDefaultSize key={ index } href={ url } - variant="tertiary" + variant="link" onClick={ ( event: MouseEvent< HTMLButtonElement > ) => onActionClick( event, onClick ) } diff --git a/packages/components/src/snackbar/style.scss b/packages/components/src/snackbar/style.scss index 1e76a1666411e7..d1afd9b9f01e99 100644 --- a/packages/components/src/snackbar/style.scss +++ b/packages/components/src/snackbar/style.scss @@ -48,25 +48,16 @@ .components-snackbar__action.components-button { margin-left: $grid-unit-40; color: $white; - height: auto; flex-shrink: 0; - line-height: $default-line-height; - padding: 0; - - &:not(:disabled):not([aria-disabled="true"]):not(.is-secondary) { - text-decoration: underline; - background-color: transparent; - &:focus { - color: $white; - box-shadow: none; - outline: 1px dotted $white; - } + &:focus { + box-shadow: none; + outline: 1px dotted $white; + } - &:hover { - text-decoration: none; - color: $white; - } + &:hover { + text-decoration: none; + color: currentColor; } } From 3e151e2e45fd766abf63d4640681de930d29eb77 Mon Sep 17 00:00:00 2001 From: louwie17 <lourensschep@gmail.com> Date: Wed, 30 Oct 2024 12:51:42 -0300 Subject: [PATCH 1410/1908] Add `isVisible` option to fields within DataForm (#65826) Co-authored-by: louwie17 <louwie17@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../dataform-combined-edit/index.tsx | 17 ++++++---- .../dataform/stories/index.story.tsx | 22 +++++++++++-- .../form-field-visibility/index.tsx | 32 +++++++++++++++++++ .../src/dataforms-layouts/panel/index.tsx | 12 +++++-- .../src/dataforms-layouts/regular/index.tsx | 12 +++++-- packages/dataviews/src/types.ts | 5 +++ 6 files changed, 84 insertions(+), 16 deletions(-) create mode 100644 packages/dataviews/src/components/form-field-visibility/index.tsx diff --git a/packages/dataviews/src/components/dataform-combined-edit/index.tsx b/packages/dataviews/src/components/dataform-combined-edit/index.tsx index 6b2a752fa8de52..90a92ac861bdd1 100644 --- a/packages/dataviews/src/components/dataform-combined-edit/index.tsx +++ b/packages/dataviews/src/components/dataform-combined-edit/index.tsx @@ -12,6 +12,7 @@ import { * Internal dependencies */ import type { DataFormCombinedEditProps, NormalizedField } from '../../types'; +import FormFieldVisibility from '../form-field-visibility'; function Header( { title }: { title: string } ) { return ( @@ -41,13 +42,15 @@ function DataFormCombinedEdit< Item >( { ); const children = visibleChildren.map( ( child ) => { return ( - <div className="dataforms-combined-edit__field" key={ child.id }> - <child.Edit - data={ data } - field={ child } - onChange={ onChange } - /> - </div> + <FormFieldVisibility key={ child.id } data={ data } field={ child }> + <div className="dataforms-combined-edit__field"> + <child.Edit + data={ data } + field={ child } + onChange={ onChange } + /> + </div> + </FormFieldVisibility> ); } ); diff --git a/packages/dataviews/src/components/dataform/stories/index.story.tsx b/packages/dataviews/src/components/dataform/stories/index.story.tsx index c929c21f1c21a9..b59d79063200bf 100644 --- a/packages/dataviews/src/components/dataform/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataform/stories/index.story.tsx @@ -7,7 +7,18 @@ import { useState } from '@wordpress/element'; * Internal dependencies */ import DataForm from '../index'; -import type { CombinedFormField } from '../../../types'; +import type { CombinedFormField, Field } from '../../../types'; + +type SamplePost = { + title: string; + order: number; + author: number; + status: string; + reviewer: string; + date: string; + birthdate: string; + password?: string; +}; const meta = { title: 'DataViews/DataForm', @@ -75,14 +86,18 @@ const fields = [ elements: [ { value: 'draft', label: 'Draft' }, { value: 'published', label: 'Published' }, + { value: 'private', label: 'Private' }, ], }, { id: 'password', label: 'Password', type: 'text' as const, + isVisible: ( item: SamplePost ) => { + return item.status !== 'private'; + }, }, -]; +] as Field< SamplePost >[]; export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { const [ post, setPost ] = useState( { @@ -102,13 +117,14 @@ export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { 'author', 'reviewer', 'status', + 'password', 'date', 'birthdate', ], }; return ( - <DataForm + <DataForm< SamplePost > data={ post } fields={ fields } form={ { diff --git a/packages/dataviews/src/components/form-field-visibility/index.tsx b/packages/dataviews/src/components/form-field-visibility/index.tsx new file mode 100644 index 00000000000000..8cea59f11b7aea --- /dev/null +++ b/packages/dataviews/src/components/form-field-visibility/index.tsx @@ -0,0 +1,32 @@ +/** + * WordPress dependencies + */ +import { useMemo } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { NormalizedField } from '../../types'; + +type FormFieldVisibilityProps< Item > = React.PropsWithChildren< { + field: NormalizedField< Item >; + data: Item; +} >; + +export default function FormFieldVisibility< Item >( { + data, + field, + children, +}: FormFieldVisibilityProps< Item > ) { + const isVisible = useMemo( () => { + if ( field.isVisible ) { + return field.isVisible( data ); + } + return true; + }, [ field.isVisible, data ] ); + + if ( ! isVisible ) { + return null; + } + return children; +} diff --git a/packages/dataviews/src/dataforms-layouts/panel/index.tsx b/packages/dataviews/src/dataforms-layouts/panel/index.tsx index 4a43d25436fe74..b74e5e4667d4b1 100644 --- a/packages/dataviews/src/dataforms-layouts/panel/index.tsx +++ b/packages/dataviews/src/dataforms-layouts/panel/index.tsx @@ -19,6 +19,7 @@ import { closeSmall } from '@wordpress/icons'; import { normalizeFields } from '../../normalize-fields'; import { getVisibleFields } from '../get-visible-fields'; import type { DataFormProps, NormalizedField } from '../../types'; +import FormFieldVisibility from '../../components/form-field-visibility'; interface FormFieldProps< Item > { data: Item; @@ -156,12 +157,17 @@ export default function FormPanel< Item >( { <VStack spacing={ 2 }> { visibleFields.map( ( field ) => { return ( - <FormField + <FormFieldVisibility key={ field.id } data={ data } field={ field } - onChange={ onChange } - /> + > + <FormField + data={ data } + field={ field } + onChange={ onChange } + /> + </FormFieldVisibility> ); } ) } </VStack> diff --git a/packages/dataviews/src/dataforms-layouts/regular/index.tsx b/packages/dataviews/src/dataforms-layouts/regular/index.tsx index 57aa163b890e5f..6a340a50584df4 100644 --- a/packages/dataviews/src/dataforms-layouts/regular/index.tsx +++ b/packages/dataviews/src/dataforms-layouts/regular/index.tsx @@ -10,6 +10,7 @@ import { useMemo } from '@wordpress/element'; import { normalizeFields } from '../../normalize-fields'; import { getVisibleFields } from '../get-visible-fields'; import type { DataFormProps } from '../../types'; +import FormFieldVisibility from '../../components/form-field-visibility'; export default function FormRegular< Item >( { data, @@ -33,12 +34,17 @@ export default function FormRegular< Item >( { <VStack spacing={ 4 }> { visibleFields.map( ( field ) => { return ( - <field.Edit + <FormFieldVisibility key={ field.id } data={ data } field={ field } - onChange={ onChange } - /> + > + <field.Edit + data={ data } + field={ field } + onChange={ onChange } + /> + </FormFieldVisibility> ); } ) } </VStack> diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 2a335dce3af32b..0ea0965704d18c 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -123,6 +123,11 @@ export type Field< Item > = { */ isValid?: ( item: Item, context?: ValidationContext ) => boolean; + /** + * Callback used to decide if a field should be displayed. + */ + isVisible?: ( item: Item ) => boolean; + /** * Whether the field is sortable. */ From 422987b9552537ef183b1aa9abf5b0099e3a40f6 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 31 Oct 2024 01:17:38 +0900 Subject: [PATCH 1411/1908] PaletteEdit: Add appropriate size props to Buttons (#66590) * PaletteEdit: Add appropriate size props to Buttons * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/palette-edit/index.tsx | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 1f612bfae6597e..c4dc5e3a57b930 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- `PaletteEdit`: Add appropriate size props to Buttons ([#66590](https://github.com/WordPress/gutenberg/pull/66590)). + ### Internal - `Snackbar`: Use link variant for action Button ([#66560](https://github.com/WordPress/gutenberg/pull/66560)). diff --git a/packages/components/src/palette-edit/index.tsx b/packages/components/src/palette-edit/index.tsx index 570613e5378c10..a58ecbb685e514 100644 --- a/packages/components/src/palette-edit/index.tsx +++ b/packages/components/src/palette-edit/index.tsx @@ -215,6 +215,7 @@ function Option< T extends PaletteElement >( { <Item ref={ setPopoverAnchor } size="small"> <HStack justify="flex-start"> <Button + size="small" onClick={ () => { setIsEditingColor( true ); } } @@ -501,6 +502,7 @@ export function PaletteEdit( { <NavigableMenu role="menu"> { ! isEditing && ( <Button + __next40pxDefaultSize variant="tertiary" onClick={ () => { setIsEditing( true ); @@ -513,6 +515,7 @@ export function PaletteEdit( { ) } { ! canOnlyChangeValues && ( <Button + __next40pxDefaultSize variant="tertiary" onClick={ () => { setEditingElement( @@ -535,6 +538,8 @@ export function PaletteEdit( { ) } { canReset && ( <Button + __next40pxDefaultSize + className="components-palette-edit__menu-button" variant="tertiary" onClick={ () => { setEditingElement( From 9d46c692bb63b6a22d055bd36c82efbad1034340 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Wed, 30 Oct 2024 17:34:58 +0100 Subject: [PATCH 1412/1908] Site Editor: restore block-library editor.css outside canvas (#66556) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- backport-changelog/6.8/7643.md | 1 + lib/client-assets.php | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/backport-changelog/6.8/7643.md b/backport-changelog/6.8/7643.md index e3c923a487be06..f83aa411f9fff3 100644 --- a/backport-changelog/6.8/7643.md +++ b/backport-changelog/6.8/7643.md @@ -1,3 +1,4 @@ https://github.com/WordPress/wordpress-develop/pull/7643 * https://github.com/WordPress/gutenberg/pull/66432 +* https://github.com/WordPress/gutenberg/pull/66556 diff --git a/lib/client-assets.php b/lib/client-assets.php index f6b17ffcce68be..f95ac27f81d010 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -361,6 +361,15 @@ function gutenberg_register_packages_styles( $styles ) { ); $styles->add_data( 'wp-editor-classic-layout-styles', 'rtl', 'replace' ); + gutenberg_override_style( + $styles, + 'wp-block-library-editor', + gutenberg_url( 'build/block-library/editor.css' ), + array(), + $version + ); + $styles->add_data( 'wp-block-library-editor', 'rtl', 'replace' ); + gutenberg_override_style( $styles, 'wp-edit-blocks', @@ -410,7 +419,7 @@ function gutenberg_register_packages_styles( $styles ) { $styles, 'wp-edit-site', gutenberg_url( 'build/edit-site/style.css' ), - array( 'wp-components', 'wp-block-editor', 'wp-editor', 'common', 'forms', 'wp-commands', 'wp-preferences' ), + array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-block-library-editor', 'common', 'forms', 'wp-commands', 'wp-preferences' ), $version ); $styles->add_data( 'wp-edit-site', 'rtl', 'replace' ); From aa2279b390af42228109b73f2baeab67dc062ae1 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Wed, 30 Oct 2024 17:42:05 +0100 Subject: [PATCH 1413/1908] Block Bindings: Docs API reference. (#66251) * Initial commit * Second commit, still not complete * More docs * More fixes * First draft written, still needs grammar check * Applied AI corrections * Changes requested * Address more reviews * Update getFieldsList expanation * Fix wrong function * Fix misspeel * Recover Artemio's commits * Edit references * Update docs * Fix typos, formatting, omissions * Add colons to editor registration definition * Add missing import * Add code markdown for type * Tighten language and format types * Remove extraneous 'a', fix typo * Address Mario's feedback * Add comments * Add manifest * Fix word usage * I edited the wrong file * Add versions, fix label --------- Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> Co-authored-by: justintadlock <greenshady@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> --- docs/manifest.json | 6 + docs/reference-guides/block-api/README.md | 1 + .../block-api/block-bindings.md | 330 ++++++++++++++++++ docs/toc.json | 3 + 4 files changed, 340 insertions(+) create mode 100644 docs/reference-guides/block-api/block-bindings.md diff --git a/docs/manifest.json b/docs/manifest.json index 5e94c6b83b70d2..8f267e79ef4feb 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -371,6 +371,12 @@ "markdown_source": "../docs/reference-guides/block-api/block-attributes.md", "parent": "block-api" }, + { + "title": "Bindings", + "slug": "block-bindings", + "markdown_source": "../docs/reference-guides/block-api/block-bindings.md", + "parent": "block-api" + }, { "title": "Context", "slug": "block-context", diff --git a/docs/reference-guides/block-api/README.md b/docs/reference-guides/block-api/README.md index 128b9abf0f0d7d..1b89b9246d8292 100644 --- a/docs/reference-guides/block-api/README.md +++ b/docs/reference-guides/block-api/README.md @@ -7,6 +7,7 @@ The following sections will walk you through the existing block APIs: - [Annotations](/docs/reference-guides/block-api/block-annotations.md) - [API Versions](/docs/reference-guides/block-api/block-api-versions.md) - [Attributes](/docs/reference-guides/block-api/block-attributes.md) +- [Bindings](/docs/reference-guides/block-api/block-bindings.md) - [Context](/docs/reference-guides/block-api/block-context.md) - [Deprecation](/docs/reference-guides/block-api/block-deprecation.md) - [Edit and Save](/docs/reference-guides/block-api/block-edit-save.md) diff --git a/docs/reference-guides/block-api/block-bindings.md b/docs/reference-guides/block-api/block-bindings.md new file mode 100644 index 00000000000000..479396abc13c9c --- /dev/null +++ b/docs/reference-guides/block-api/block-bindings.md @@ -0,0 +1,330 @@ +# Bindings + +<div class="callout callout-alert"> +Block Bindings API is only available for WordPress 6.5 and above. +</div> + +The Block Bindings API lets you “bind” dynamic data to the block’s attributes, which are then reflected in the final HTML markup that is output to the browser on the front end. + +An example could be connecting an Image block `url` attribute to a function that returns random images from an external API. + +```html +<!-- wp:image { + "metadata":{ + "bindings":{ + "url":{ + "source":"my-plugin/get-random-images" + } + } + } +} --> +``` + + +## Compatible blocks and their attributes + +Right now, not all block attributes are compatible with block bindings. There is some ongoing effort to increase this compatibility, but for now, this is the list: + +| Supported Blocks | Supported Attributes | +| ---------------- | -------------------- | +| Paragraph | content | +| Heading | content | +| Image | id, url, title, alt | +| Button | text, url, linkTarget, rel | + +## Registering a custom source + +Registering a source requires defining at least `name`, a `label` and a `callback` function that gets a value from the source and passes it back to a block attribute. + +Once a source is registered, any supporting block's `metadata.bindings` attribute can be configured to read a value from that source. + +Registration can be done on the server via PHP or in the editor via JavaScript, and both can coexist. + +The label defined in server registration will be overridden by the label defined in the editor. + +### Server registration + +Server registration allows applying a callback that will be executed on the frontend for the bound attribute. + +The function to register a custom source is `register_block_bindings_source($name, $args)`: + +- `name`: `string` that sets the unique ID for the custom source. +- `args`: `array` that contains: + - `label`: `string` with the human-readable name of the custom source. + - `uses_context`: `array` with the block context that is passed to the callback (optional). + - `get_value_callback`: `function` that will run on the bound block's render function. It accepts three arguments: `source_args`, `block_instance` and `attribute_name`. This value can be overridden with the filter `block_bindings_source_value`. + +Note that `register_block_bindings_source()` should be called from a handler attached to the `init` hook. + +Here is an example: + +```php +add_action( + 'init', + function () { + register_block_bindings_source( + 'wpmovies/visualization-date', + array( + 'label' => __( 'Visualization Date', 'custom-bindings' ), + 'get_value_callback' => function ( array $source_args, $block_instance ) { + $post_id = $block_instance->context['postId']; + if ( isset( $source_args['key'] ) ) { + return get_post_meta( $post_id, $source_args['key'], true ); + } + }, + 'uses_context' => array( 'postId' ), + ) + ); + } +); +``` + +This example needs a `post_meta` registered, and, also, a filter can be used to return a default `$visualization_date` value, which will be shown in the next heading. + +```php +add_action( + 'init', + function () { + register_meta( + 'post', + 'wp_movies_visualization_date', + array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + 'label' => __( 'Movie visualization date', 'custom-bindings' ), + ) + ); + } +); +``` + +#### Block bindings source value filter + +_**Note:** Since WordPress 6.7._ + +The value returned by `get_value_callback` can be modified with the `block_bindings_source_value` filter. +The filter has the following parameters: + +- `value`: The value to be filtered. +- `name`: The name of the source. +- `source_args`: `array` containing source arguments. +- `block_instance`: The block instance object. +- `attribute_name`: The name of the attribute. + +Example: + +```php +function wpmovies_format_visualization_date( $value, $name ) { + // Prevent the filter to be applied to other sources. + if ( $name !== 'wpmovies/visualization-date' ) { + return $value; + } + if ( ! $value ) { + return date( 'm/d/Y' ); + } + return date( 'm/d/Y', strtotime( $value ) ); +} + +add_filter( 'block_bindings_source_value', 'wpmovies_format_visualization_date', 10, 2 ); +``` + +#### Server registration Core examples + +There are a few examples in Core that can be used as reference. + +- Post Meta. [Source code](https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/block-bindings/post-meta.php) +- Pattern overrides. [Source code](https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/block-bindings/pattern-overrides.php) +- Twenty Twenty-Five theme. [Source code](https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-content/themes/twentytwentyfive/functions.php) + + +### Editor registration + +_**Note:** Since WordPress 6.7._ + +Editor registration on the client allows defining what the bound block will do when the value is retrieved or when the value is edited. + +The function to register a custom source is `registerBlockBindingsSource( args )`: + +- `args`: `object` with the following structure: + - `name`: `string` with the unique and machine-readable name. + - `label`: `string` with the human readable name of the custom source. In case it was defined already on the server, the server label will be overriden by this one, in that case, it is not recommended to be defined here. (optional) + - `usesContext`: `array` with the block context that the custom source may need. In case it was defined already on the server, it should not be defined here. (optional) + - `getValues`: `function` that retrieves the values from the source. (optional) + - `setValues`: `function` that allows updating the values connected to the source. (optional) + - `canUserEditValue`: `function` to determine if the user can edit the value. The user won't be able to edit by default. (optional) + + +This example will show a custom post meta date in the editor and, if it doesn't exist, it will show today's date. The user can edit the value of the date. (Caution: This example does not format the user input as a date—it's only for educational purposes.) + +```js +import { + registerBlockBindingsSource, +} from '@wordpress/blocks'; +import { __ } from '@wordpress/i18n'; +import { store as coreDataStore } from '@wordpress/core-data'; + +registerBlockBindingsSource( { + name: 'wpmovies/visualization-date', + label: __( 'Visualization Date', 'custom-bindings' ), // We can skip the label, as it was already defined in the server in the previous example. + usesContext: [ 'postType' ], // We can skip postId, as it was already defined in the server in the previous example. + getValues( { select, context } ) { + let wpMoviesVisualizationDate; + const { getEditedEntityRecord } = select( coreDataStore ); + if ( context?.postType && context?.postId ) { + wpMoviesVisualizationDate = getEditedEntityRecord( + 'postType', + context?.postType, + context?.postId + ).meta?.wp_movies_visualization_date; + } + if ( wpMoviesVisualizationDate ) { + return { + content: wpMoviesVisualizationDate, + }; + } + + return { + content: new Date().toLocaleDateString( 'en-US' ), + }; + }, + setValues( { select, dispatch, context, bindings } ) { + dispatch( coreDataStore ).editEntityRecord( + 'postType', + context?.postType, + context?.postId, + { + meta: { + wp_movies_visualization_date: bindings?.content?.newValue, + }, + } + ); + }, + canUserEditValue( { select, context } ) { + return true; + }, +} ); +``` + +#### getValues + +The `getValues` function retrieves the value from the source on block loading. It receives an `object` as an argument with the following properties: + +- `bindings` returns the bindings object of the specific source. It must have the attributes as a key, and the value can be a `string` or an `object` with arguments. +- `clientId` returns a `string` with the current block client ID. +- `context` returns an `object` of the current block context, defined in the `usesContext` property. [More about block context.](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/). +- `select` returns an `object` of a given store's selectors. [More info in their docs.](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#select). + +The function must return an `object` with this structure: +`{ 'block attribute' : value }` + +#### setValues + +The `setValues` function updates all the values of the source of the block bound. It receives an `object` as an argument with the following properties: + +- `bindings` returns the bindings object of the specific source. It must have the attributes as a key, and the value can be a `string` or an `object` with arguments. This object contains a `newValue` property with the user's input. +- `clientId` returns a `string` with the current block client ID. +- `context` returns an `object` of the current block context, defined in the `usesContext` property. [More about block context.](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/). +- `dispatch` returns an `object` of the store's action creators. [More about dispatch](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#dispatch). +- `select` returns an `object` of a given store's selectors. [More info in their docs.](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#select). + + +#### Editor registration Core examples + +There are a few examples in Core that can be used as reference. + +- Post Meta. [Source code](https://github.com/WordPress/gutenberg/blob/5afd6c27bfba2be2e06b502257753fbfff1ae9f0/packages/editor/src/bindings/post-meta.js#L74-L146) +- Pattern overrides. [Source code](https://github.com/WordPress/gutenberg/blob/5afd6c27bfba2be2e06b502257753fbfff1ae9f0/packages/editor/src/bindings/pattern-overrides.js#L8-L100) + +## Unregistering a source + +_**Note:** Since WordPress 6.7._ + +`unregisterBlockBindingsSource` unregisters a block bindings source by providing its name. + +```js +import { unregisterBlockBindingsSource } from '@wordpress/blocks'; + +unregisterBlockBindingsSource( 'plugin/my-custom-source' ); +``` + +## Getting all sources + +_**Note:** Since WordPress 6.7._ + +`getBlockBindingsSources` returns all registered block bindings sources. + +```js +import { getBlockBindingsSources } from '@wordpress/blocks'; + +const registeredSources = getBlockBindingsSources(); +``` + +## Getting one specific source + +_**Note:** Since WordPress 6.7._ + +`getBlockBindingsSource` return a specific block bindings source by its name. + +```js +import { getBlockBindingsSource } from '@wordpress/blocks'; + +const blockBindingsSource = getBlockBindingsSource( 'plugin/my-custom-source' ); +``` + +## Block Bindings Utils + +_**Note:** Since WordPress 6.7._ + +UseBlockBindingUtils is a hook with two helpers that allows developers to edit the `metadata.bindings` attribute easily. + +It accepts a `clientId` string as a parameter, if it is not set, the function will use the current block client ID from the context. + +Example: + +```js +import { useBlockBindingsUtils } from '@wordpress/block-editor'; + +const { updateBlockBindings } = useBlockBindingsUtils('my-block-client-id-12345'); +... +``` + +### updateBlockBindings + +`updateBlockBindings` works similarly to `updateBlockAttributes`, and can be used to create, update, or remove specific connections. + +```js +import { useBlockBindingsUtils } from '@wordpress/block-editor'; + +const { updateBlockBindings } = useBlockBindingsUtils(); + +function updateBlockBindingsURLSource( url ) { + updateBlockBindings({ + url: { + source: 'myplugin/new-source', + } + }) +} + +// Remove binding from url attribute. +function removeBlockBindingsURLSource() { + updateBlockBindings( { url: undefined } ); +} +``` + +### removeAllBlockBindings + +`removeAllBlockBindings` will remove all existing connections in a block by removing the `metadata.bindings` attribute. + +```js +import { useBlockBindingsUtils } from '@wordpress/block-editor'; + +const { removeAllBlockBindings } = useBlockBindingsUtils(); + +function clearBlockBindings() { + removeAllBlockBindings(); +} +``` + + + diff --git a/docs/toc.json b/docs/toc.json index 0d4689811b26ec..69fe86a08256b6 100644 --- a/docs/toc.json +++ b/docs/toc.json @@ -159,6 +159,9 @@ { "docs/reference-guides/block-api/block-attributes.md": [] }, + { + "docs/reference-guides/block-api/block-bindings.md": [] + }, { "docs/reference-guides/block-api/block-context.md": [] }, { "docs/reference-guides/block-api/block-deprecation.md": [] From 9a40ea033698ad2971c0f0a9167e61d2354e1dcd Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Wed, 30 Oct 2024 18:05:40 +0100 Subject: [PATCH 1414/1908] Site Editor: preload settings requests (#66488) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- backport-changelog/6.8/7687.md | 3 +++ lib/compat/wordpress-6.8/preload.php | 34 ++++++++++++++++++++++++++++ lib/load.php | 3 +++ packages/core-data/src/entities.js | 2 ++ 4 files changed, 42 insertions(+) create mode 100644 backport-changelog/6.8/7687.md create mode 100644 lib/compat/wordpress-6.8/preload.php diff --git a/backport-changelog/6.8/7687.md b/backport-changelog/6.8/7687.md new file mode 100644 index 00000000000000..f1505645df20c6 --- /dev/null +++ b/backport-changelog/6.8/7687.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7687 + +* https://github.com/WordPress/gutenberg/pull/66488 diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php new file mode 100644 index 00000000000000..5ba613e22033d4 --- /dev/null +++ b/lib/compat/wordpress-6.8/preload.php @@ -0,0 +1,34 @@ +<?php + +/** + * Preload necessary resources for the editors. + * + * @param array $paths REST API paths to preload. + * @param WP_Block_Editor_Context $context Current block editor context + * + * @return array Filtered preload paths. + */ +function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { + if ( 'core/edit-site' === $context->name ) { + // Core already preloads both of these for `core/edit-post`. + $paths[] = '/wp/v2/settings'; + $paths[] = array( '/wp/v2/settings', 'OPTIONS' ); + $paths[] = '/?_fields=' . implode( + ',', + // @see packages/core-data/src/entities.js + array( + 'description', + 'gmt_offset', + 'home', + 'name', + 'site_icon', + 'site_icon_url', + 'site_logo', + 'timezone_string', + 'url', + ) + ); + } + return $paths; +} +add_filter( 'block_editor_rest_api_preload_paths', 'gutenberg_block_editor_preload_paths_6_8', 10, 2 ); diff --git a/lib/load.php b/lib/load.php index 2c8a0fd0347c92..0540d4cd9efac7 100644 --- a/lib/load.php +++ b/lib/load.php @@ -116,6 +116,9 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.7/compat.php'; require __DIR__ . '/compat/wordpress-6.7/post-formats.php'; +// WordPress 6.8 compat. +require __DIR__ . '/compat/wordpress-6.8/preload.php'; + // Experimental features. require __DIR__ . '/experimental/block-editor-settings-mobile.php'; require __DIR__ . '/experimental/blocks.php'; diff --git a/packages/core-data/src/entities.js b/packages/core-data/src/entities.js index f73239e9afbbe5..3c10676750a2ab 100644 --- a/packages/core-data/src/entities.js +++ b/packages/core-data/src/entities.js @@ -20,6 +20,8 @@ export const rootEntitiesConfig = [ name: '__unstableBase', baseURL: '/', baseURLParams: { + // Please also change the preload path when changing this. + // @see lib/compat/wordpress-6.8/preload.php _fields: [ 'description', 'gmt_offset', From 3e2b03b7e65a7f980e6dd3b33f7beb6eab9937d5 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 31 Oct 2024 02:20:12 +0900 Subject: [PATCH 1415/1908] Guide: Use small size button for page controls (#66607) * Guide: Use small size button for page controls * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/guide/page-control.tsx | 1 + packages/components/src/guide/style.scss | 10 ++++------ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index c4dc5e3a57b930..e0b6a6d071e130 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -4,6 +4,7 @@ ### Enhancements +- `Guide`: Use small size button for page controls ([#66607](https://github.com/WordPress/gutenberg/pull/66607)). - `PaletteEdit`: Add appropriate size props to Buttons ([#66590](https://github.com/WordPress/gutenberg/pull/66590)). ### Internal diff --git a/packages/components/src/guide/page-control.tsx b/packages/components/src/guide/page-control.tsx index 468670c6ad9b9b..80b0a641c2a430 100644 --- a/packages/components/src/guide/page-control.tsx +++ b/packages/components/src/guide/page-control.tsx @@ -27,6 +27,7 @@ export default function PageControl( { aria-current={ page === currentPage ? 'step' : undefined } > <Button + size="small" key={ page } icon={ <PageControlIcon /> } aria-label={ sprintf( diff --git a/packages/components/src/guide/style.scss b/packages/components/src/guide/style.scss index 073bfc06843075..df52d5325f3fbf 100644 --- a/packages/components/src/guide/style.scss +++ b/packages/components/src/guide/style.scss @@ -34,7 +34,7 @@ } } - &__container { + .components-guide__container { display: flex; flex-direction: column; justify-content: space-between; @@ -42,7 +42,7 @@ min-height: 100%; } - &__page { + .components-guide__page { display: flex; flex-direction: column; justify-content: center; @@ -53,7 +53,7 @@ } } - &__footer { + .components-guide__footer { align-content: center; display: flex; height: $button-size; @@ -64,7 +64,7 @@ width: 100%; } - &__page-control { + .components-guide__page-control { margin: 0; text-align: center; @@ -74,8 +74,6 @@ } .components-button { - height: 30px; - min-width: 20px; margin: -6px 0; color: $gray-200; } From ad72cba2a0a159896f75dbe7a0b0dfb57a459350 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 30 Oct 2024 17:37:49 +0000 Subject: [PATCH 1416/1908] Bump plugin version to 19.6.0-rc.2 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 6723ae3d58fc0c..60b7614beefee4 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.6.0-rc.1 + * Version: 19.6.0-rc.2 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index e2093a8759fb83..24812eff02ef8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.6.0-rc.1", + "version": "19.6.0-rc.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.6.0-rc.1", + "version": "19.6.0-rc.2", "hasInstallScript": true, "license": "GPL-2.0-or-later", "workspaces": [ diff --git a/package.json b/package.json index eb38bedd023914..2218fd6171aa30 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.6.0-rc.1", + "version": "19.6.0-rc.2", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 2ca4aa0448229e715daa553d305db54f0a8d09e0 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 30 Oct 2024 17:50:38 +0000 Subject: [PATCH 1417/1908] Update Changelog for 19.6.0-rc.2 --- changelog.txt | 332 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) diff --git a/changelog.txt b/changelog.txt index ca5175bc74eb46..420a6392415b36 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,337 @@ == Changelog == += 19.6.0-rc.2 = + +## Changelog + +### Enhancements + +- BlockGroupToolbar: Better i18n context for toolbar labels. ([66211](https://github.com/WordPress/gutenberg/pull/66211)) +- Core Data: Add the 'getEntitiesConfig' resolver. ([65871](https://github.com/WordPress/gutenberg/pull/65871)) +- Create Block: Adds `--target-dir` flag to allow the tool to target where to scaffold. ([53781](https://github.com/WordPress/gutenberg/pull/53781)) +- Editor Interface: Remove small header from global styles/plugin sidebar. ([64474](https://github.com/WordPress/gutenberg/pull/64474)) +- Remove purple coloring from DocumentBar and PostCard. ([66451](https://github.com/WordPress/gutenberg/pull/66451)) +- Scripts: Add BlueOak-1.0.0 license to GPL2 compatible. ([66139](https://github.com/WordPress/gutenberg/pull/66139)) +- WP Scripts: Add a `--root-folder` argument to the `plugin-zip` command. ([61375](https://github.com/WordPress/gutenberg/pull/61375)) + +#### Components +- Add elevation tokens to storybook. ([66122](https://github.com/WordPress/gutenberg/pull/66122)) +- Add foundations:Elevation to storybook. ([66124](https://github.com/WordPress/gutenberg/pull/66124)) +- Add radius foundation and tokens to storybook. ([66219](https://github.com/WordPress/gutenberg/pull/66219)) +- Combobox, FormTokenField: Show message when no matches found. ([66142](https://github.com/WordPress/gutenberg/pull/66142)) +- Storybook: Organizes components under 'Utilities'. ([66210](https://github.com/WordPress/gutenberg/pull/66210)) +- Tabs: Expose active tab item props, use ariakit prop types. ([66223](https://github.com/WordPress/gutenberg/pull/66223)) +- Tabs: Remove custom logic. ([66097](https://github.com/WordPress/gutenberg/pull/66097)) +- `DropdownMenuV2`: Rename to `Menu`. ([66289](https://github.com/WordPress/gutenberg/pull/66289)) + +#### Block Library +- Add Transformation from Separator to Spacer. ([66230](https://github.com/WordPress/gutenberg/pull/66230)) +- Add lightbox option in gallery block link control. ([64014](https://github.com/WordPress/gutenberg/pull/64014)) +- Archives: Add border block support. ([63400](https://github.com/WordPress/gutenberg/pull/63400)) +- Border support added to comments. ([66354](https://github.com/WordPress/gutenberg/pull/66354)) +- Cover Block: Add Image Resolution options. ([62926](https://github.com/WordPress/gutenberg/pull/62926)) +- HTML Block: Force HTML preview in view mode. ([66440](https://github.com/WordPress/gutenberg/pull/66440)) + +#### Zoom Out +- Add keyboard shortcut in editor. ([66400](https://github.com/WordPress/gutenberg/pull/66400)) +- Iterate zoom out shuffle into a more visual control. ([66194](https://github.com/WordPress/gutenberg/pull/66194)) +- Use the zoom-level value to scale the iframe. ([66280](https://github.com/WordPress/gutenberg/pull/66280)) + +#### Site Editor +- Remove synchronization of canvas mode into store. ([66213](https://github.com/WordPress/gutenberg/pull/66213)) +- Style Book: Clean up layout. ([66255](https://github.com/WordPress/gutenberg/pull/66255)) +- Update site icon and title position. ([66171](https://github.com/WordPress/gutenberg/pull/66171)) + +#### Data Views +- Fix alignment of action items in list layout. ([66273](https://github.com/WordPress/gutenberg/pull/66273)) +- Templates: Hide media field in list view. ([66573](https://github.com/WordPress/gutenberg/pull/66573)) + +#### Global Styles +- Backport: Caching of global styles for blocks from core. ([66349](https://github.com/WordPress/gutenberg/pull/66349)) +- Style Book: Add color tab. ([65692](https://github.com/WordPress/gutenberg/pull/65692)) + +#### Real-time Collaboration +- Inline Commenting: Disable comments on published posts for now. ([66583](https://github.com/WordPress/gutenberg/pull/66583)) + +#### Post Editor +- Set `ResizableEditor` height based on border-box. ([66342](https://github.com/WordPress/gutenberg/pull/66342)) + +#### Icons +- Add align-item related icons. ([66242](https://github.com/WordPress/gutenberg/pull/66242)) + +#### REST API +- Backport from WordPress core: Improvements for the post format query loop filter. ([66037](https://github.com/WordPress/gutenberg/pull/66037)) + + +### New APIs + +- Stabilize isPreviewMode flag. ([66149](https://github.com/WordPress/gutenberg/pull/66149)) +- scripts: Add build-blocks-manifest command. ([65866](https://github.com/WordPress/gutenberg/pull/65866)) + + +### Bug Fixes + +- Create block: Ensure $slug is replaced with passed slug. ([66528](https://github.com/WordPress/gutenberg/pull/66528)) +- Fix extraneous scrollbar in device previews. ([66494](https://github.com/WordPress/gutenberg/pull/66494)) +- GH-66090: Self nesting and circular nesting block fix. ([66121](https://github.com/WordPress/gutenberg/pull/66121)) +- Global styles: Move preload paths filter to 6.7 (previously 6.8). ([66543](https://github.com/WordPress/gutenberg/pull/66543)) +- Miscellaneous i18n fixes. ([66510](https://github.com/WordPress/gutenberg/pull/66510)) +- Remove most of the occurrences of the verb toggle. ([66371](https://github.com/WordPress/gutenberg/pull/66371)) +- SpacingSizesControl: Use generic label for linked button. ([66304](https://github.com/WordPress/gutenberg/pull/66304)) + +#### Zoom Out +- Disable zoom out toggle button when Style Book is open. ([66228](https://github.com/WordPress/gutenberg/pull/66228)) +- Don't switch editor mode when changing entities. ([66452](https://github.com/WordPress/gutenberg/pull/66452)) +- Fix scaling animation for device previews. ([66132](https://github.com/WordPress/gutenberg/pull/66132)) +- Fix zoom out not persisting while switching between editor and code editor. ([65932](https://github.com/WordPress/gutenberg/pull/65932)) +- Fix zoom out shortcut on Windows. ([66506](https://github.com/WordPress/gutenberg/pull/66506)) +- Fix: Activate zoom out on large viewport. ([66308](https://github.com/WordPress/gutenberg/pull/66308)) +- Hide slots and grouping buttons. ([66243](https://github.com/WordPress/gutenberg/pull/66243)) +- Remove zoom-out toolbar. ([66039](https://github.com/WordPress/gutenberg/pull/66039)) +- Resets the Zoom on viewed/edited entity change. ([66232](https://github.com/WordPress/gutenberg/pull/66232)) +- Revise zoom layout shift fix. ([66390](https://github.com/WordPress/gutenberg/pull/66390)) +- Zoom-out: Rely on zoom-level instead of zoom-out mode. ([66141](https://github.com/WordPress/gutenberg/pull/66141)) + +#### Block Editor +- Block inserter: Prevent editor from crashing if `blockType.parent` is a string. ([66234](https://github.com/WordPress/gutenberg/pull/66234)) +- Block toolbar: Account for scrollable blocks that affect the position of the block toolbar. ([66188](https://github.com/WordPress/gutenberg/pull/66188)) +- Fix extra scrollbar appearing when searching in the inserter. ([66229](https://github.com/WordPress/gutenberg/pull/66229)) +- Fix: Show paragraph block variations in rich text inserter. ([66318](https://github.com/WordPress/gutenberg/pull/66318)) +- Group: Fix padding select. ([65857](https://github.com/WordPress/gutenberg/pull/65857)) +- Link Shortcut: Only trigger the link shortcut if there's a text selection. ([66056](https://github.com/WordPress/gutenberg/pull/66056)) +- Remove relative position from sidebar tabpanel. ([66267](https://github.com/WordPress/gutenberg/pull/66267)) +- Rich text: Remove empty file. ([66553](https://github.com/WordPress/gutenberg/pull/66553)) +- Zoom Out: Fix bouncy drop zones. ([66399](https://github.com/WordPress/gutenberg/pull/66399)) + +#### Components +- ColorPalette: Prevent overflow of custom color button background. ([66152](https://github.com/WordPress/gutenberg/pull/66152)) +- Fix: Text overflow in Patterns filter. ([66504](https://github.com/WordPress/gutenberg/pull/66504)) +- RadioGroup: Fix arrow key navigation in RTL. ([66202](https://github.com/WordPress/gutenberg/pull/66202)) +- Tabs and TabPanel: Fix arrow key navigation in RTL. ([66201](https://github.com/WordPress/gutenberg/pull/66201)) +- Tabs and ToggleGroupControl: Round indicator size. ([66426](https://github.com/WordPress/gutenberg/pull/66426)) +- Tabs: Fix animation timings. ([66198](https://github.com/WordPress/gutenberg/pull/66198)) +- Tabs: Override tablist's tabindex only when necessary. ([66209](https://github.com/WordPress/gutenberg/pull/66209)) +- Tabs: Restore vertical alignment for tabs content. ([66215](https://github.com/WordPress/gutenberg/pull/66215)) +- Tabs: Update indicator more reactively. ([66207](https://github.com/WordPress/gutenberg/pull/66207)) + +#### Post Editor +- Always force iframe in pattern editor. ([65887](https://github.com/WordPress/gutenberg/pull/65887)) +- Editor: Multi-entity saving: Show correct count of entities to be saved. ([66482](https://github.com/WordPress/gutenberg/pull/66482)) +- Fix : "Set featured image" button border flashes on focus. ([66092](https://github.com/WordPress/gutenberg/pull/66092)) +- Fix Parent Check Condition in `buildTermsTree`. ([66006](https://github.com/WordPress/gutenberg/pull/66006)) +- Fix: Improve the DocumentBar post type label for the Homepage and Posts Page cases. ([66355](https://github.com/WordPress/gutenberg/pull/66355)) +- PostTaxonomiesFlatTermSelector: Restore space between tag list and most used tags. ([66566](https://github.com/WordPress/gutenberg/pull/66566)) + +#### Block Library +- Block registration: Normalize blockType.parent to `array`. ([66250](https://github.com/WordPress/gutenberg/pull/66250)) +- Button Block: Apply Stretch Styles Correctly. ([64770](https://github.com/WordPress/gutenberg/pull/64770)) +- Buttons: Fix the initial white space in nofollow rel. ([66303](https://github.com/WordPress/gutenberg/pull/66303)) +- Fix - Image block: Aspect ratio not responding when dimensions are not set. ([66217](https://github.com/WordPress/gutenberg/pull/66217)) +- Navigation block: Fix block appender size. ([66153](https://github.com/WordPress/gutenberg/pull/66153)) + +#### Site Editor +- Edit Site: Fix canvasMode var. ([66316](https://github.com/WordPress/gutenberg/pull/66316)) +- Fix button hover style in sidebar navigation screen. ([66505](https://github.com/WordPress/gutenberg/pull/66505)) +- Remove toggle verb from post list data views 'Toggle details panel'. ([66334](https://github.com/WordPress/gutenberg/pull/66334)) +- Revert 66431 (Site editor: Remove "default" admin CSS). ([66540](https://github.com/WordPress/gutenberg/pull/66540)) +- Restore block-library editor.css outside canvas. ([66556](https://github.com/WordPress/gutenberg/pull/66556)) + +#### Meta Boxes +- Typo metabox pane is a meta box panel. ([66502](https://github.com/WordPress/gutenberg/pull/66502)) + +#### REST API +- Preload: Fix multiple regressions around global styles. ([66468](https://github.com/WordPress/gutenberg/pull/66468)) + +#### Style Book +- Fix comment output in styles. ([66439](https://github.com/WordPress/gutenberg/pull/66439)) + +#### Saving +- Site editor: Fix save shortcut. ([66423](https://github.com/WordPress/gutenberg/pull/66423)) + +#### CSS & Styling +- Fix the navigation issue inside cover blocks. ([66093](https://github.com/WordPress/gutenberg/pull/66093)) + + +### Accessibility + +- Update the speak messages when switching editor modes. ([66278](https://github.com/WordPress/gutenberg/pull/66278)) + +#### Post Editor +- Add featured image alt text. ([66189](https://github.com/WordPress/gutenberg/pull/66189)) +- Fix : Badge Color contrast. ([66360](https://github.com/WordPress/gutenberg/pull/66360)) + +#### Block Editor +- ImageSizeControls: Replace ButtonGroup with ToggleGroupControl. ([65386](https://github.com/WordPress/gutenberg/pull/65386)) +- Improve the link preview accessibility and labels. ([60908](https://github.com/WordPress/gutenberg/pull/60908)) + +#### Block Library +- Search: Replace ButtonGroup usage with ToggleGroupControl. ([65340](https://github.com/WordPress/gutenberg/pull/65340)) + +#### Global Styles +- Global styles menu: Avoid visible labels and accessible names mismatch. ([65124](https://github.com/WordPress/gutenberg/pull/65124)) + +#### Site Editor +- Fix Global styles panel header buttons text overlap for 'Show button text labels'. ([63243](https://github.com/WordPress/gutenberg/pull/63243)) + + +### Performance + +- Backport from Core: Reuse block metadata in WP_Theme_JSON::Get_valid_block_style_variations() for better performance. ([66539](https://github.com/WordPress/gutenberg/pull/66539)) +- tests : - Fix/compare performance with correct branch. ([66196](https://github.com/WordPress/gutenberg/pull/66196)) + +#### Site Editor +- Remove "default" admin CSS. ([66431](https://github.com/WordPress/gutenberg/pull/66431)) +- Remove content styles outside canvas. ([66432](https://github.com/WordPress/gutenberg/pull/66432)) + +#### Block bindings +- Use `getEntityConfig` instead of `getPostTypes` to get available slugs. ([66101](https://github.com/WordPress/gutenberg/pull/66101)) + + +### Experiments + +- Add Inline comment experimental flag. ([60622](https://github.com/WordPress/gutenberg/pull/60622)) +- QuickEdit: Add slug field control. ([65196](https://github.com/WordPress/gutenberg/pull/65196)) + +#### Data Views +- Quick Edit: Fix JS error when bulk editing pages. ([66358](https://github.com/WordPress/gutenberg/pull/66358)) +- QuickEdit: Add Featured Image Control. ([64496](https://github.com/WordPress/gutenberg/pull/64496)) +- QuickEdit: Add Parent field. ([66527](https://github.com/WordPress/gutenberg/pull/66527)) + + +### Documentation + +- BaseControl: Auto-generate readme. ([66500](https://github.com/WordPress/gutenberg/pull/66500)) +- Components: Prevent generated readmes duplicating h1 elements when published. ([66180](https://github.com/WordPress/gutenberg/pull/66180)) +- Correct documentation on display type in flow layouts. ([66224](https://github.com/WordPress/gutenberg/pull/66224)) +- Docs: Interactivity API - Add documentation for `getServerState()` and `getServerContext()`. ([66104](https://github.com/WordPress/gutenberg/pull/66104)) +- Fix undo/redo Button size in Storybook playground. ([66538](https://github.com/WordPress/gutenberg/pull/66538)) +- Fix: JSON Schema Docgen doesn't work on Windows OS. ([66414](https://github.com/WordPress/gutenberg/pull/66414)) +- ItemGroup: Improve stories to default to bordered and separated. ([66191](https://github.com/WordPress/gutenberg/pull/66191)) +- README: Add Storybook badge. ([66529](https://github.com/WordPress/gutenberg/pull/66529)) +- Remove meetings that no longer occur from Contributor Guide. ([66421](https://github.com/WordPress/gutenberg/pull/66421)) +- Site editor routes: Add documentation for areas and prevent `edit` area from rendering when canvas is `edit`. ([66309](https://github.com/WordPress/gutenberg/pull/66309)) +- Update documentation about build process changes. ([66428](https://github.com/WordPress/gutenberg/pull/66428)) +- docs: Example for getSelectedBlock. ([66108](https://github.com/WordPress/gutenberg/pull/66108)) + + +### Code Quality + +- Block editor: Remove reusable blocks stylesheet from iframe. ([66285](https://github.com/WordPress/gutenberg/pull/66285)) +- Compose: Fix React Complier error for 'useCopyToClipboard'. ([66444](https://github.com/WordPress/gutenberg/pull/66444)) +- Composer: Fix React Compiler errors for 'useDropZone'. ([66469](https://github.com/WordPress/gutenberg/pull/66469)) +- Fields: Fix React Compiler mutation errors. ([66464](https://github.com/WordPress/gutenberg/pull/66464)) +- Interface: Remove duplicate 'withComplementaryAreaContext' file. ([66348](https://github.com/WordPress/gutenberg/pull/66348)) +- Interface: Remove unused private API support. ([66565](https://github.com/WordPress/gutenberg/pull/66565)) +- Interface: Use plugin context hook instead of HoC. ([66362](https://github.com/WordPress/gutenberg/pull/66362)) +- Remove clip & -webkit-clip-path for downloadable-block-list-item style.scss. ([66147](https://github.com/WordPress/gutenberg/pull/66147)) +- Scripts: Refactor to extract license logic. ([66179](https://github.com/WordPress/gutenberg/pull/66179)) +- Theme JSON: Get_block_nodes - relocate $selectors assignment. ([66265](https://github.com/WordPress/gutenberg/pull/66265)) +- Update a few function definitions. ([66315](https://github.com/WordPress/gutenberg/pull/66315)) + +#### Block Editor +- ESLint: Remove explicit `react-hooks/exhaustive-deps` disabling. ([66461](https://github.com/WordPress/gutenberg/pull/66461)) +- ESLint: Remove various React Compiler mutation violations. ([66327](https://github.com/WordPress/gutenberg/pull/66327)) +- Fix 'useInstanceId' hook reference. ([66406](https://github.com/WordPress/gutenberg/pull/66406)) +- Fix React Compiler error for Duotone. ([66492](https://github.com/WordPress/gutenberg/pull/66492)) +- Fix React Complier error for 'useEventListeners'. ([66495](https://github.com/WordPress/gutenberg/pull/66495)) +- Import only the actually used PostCSS exports. ([66379](https://github.com/WordPress/gutenberg/pull/66379)) +- No need to unlock public actions. ([66260](https://github.com/WordPress/gutenberg/pull/66260)) +- Remove patterns UI stylesheet from iframe. ([66306](https://github.com/WordPress/gutenberg/pull/66306)) +- Remove unnecessary Tooltip component from radius control linked button. ([66274](https://github.com/WordPress/gutenberg/pull/66274)) +- Rich Text: Fix React Complier error for 'useEventListeners'. ([66460](https://github.com/WordPress/gutenberg/pull/66460)) +- Storybook: Add BlockPatternsList story. ([66227](https://github.com/WordPress/gutenberg/pull/66227)) + +#### Components +- BorderBoxControl: Deprecate 36px default size. ([65752](https://github.com/WordPress/gutenberg/pull/65752)) +- BorderControl: Deprecate 36px default size. ([65755](https://github.com/WordPress/gutenberg/pull/65755)) +- DrodownMenuV2: Rename folder to `menu`. ([66473](https://github.com/WordPress/gutenberg/pull/66473)) +- ESLint: Stop disabling `react-hooks/exhaustive-deps` rule. ([66324](https://github.com/WordPress/gutenberg/pull/66324)) +- Fix React Compiler error for 'useAutocomplete'. ([66496](https://github.com/WordPress/gutenberg/pull/66496)) +- PaletteEdit: Use `ItemGroup` and `Item`, and avoid custom styles. ([66164](https://github.com/WordPress/gutenberg/pull/66164)) +- TabPanel: Add 40px size prop to tab Button. ([66557](https://github.com/WordPress/gutenberg/pull/66557)) +- Tabs: Align to standard compound components structure. ([66225](https://github.com/WordPress/gutenberg/pull/66225)) +- Tabs: Simplify styled components code. ([66208](https://github.com/WordPress/gutenberg/pull/66208)) + +#### Zoom Out +- Bundle behavior in block-editor and add story. ([66240](https://github.com/WordPress/gutenberg/pull/66240)) +- Editor: Handle zoom out state via the 'switchEditorMode' action. ([66262](https://github.com/WordPress/gutenberg/pull/66262)) +- Fix/html scale code quality. ([66181](https://github.com/WordPress/gutenberg/pull/66181)) +- Make useZoomOut hook private. ([66374](https://github.com/WordPress/gutenberg/pull/66374)) +- Remove double click to exit hook from the block-editor package. ([66335](https://github.com/WordPress/gutenberg/pull/66335)) +- Remove viewport check from useZoomOut hook. ([66341](https://github.com/WordPress/gutenberg/pull/66341)) + +#### Post Editor +- Editor: No need to reset mode when changing device preview types. ([66261](https://github.com/WordPress/gutenberg/pull/66261)) +- Editor: Use plugin context hook in 'PluginMoreMenuItem'. ([66351](https://github.com/WordPress/gutenberg/pull/66351)) +- Editor: Use plugin context hook in 'PluginPreviewMenuItem'. ([66350](https://github.com/WordPress/gutenberg/pull/66350)) +- Fix typo after #63669. ([66396](https://github.com/WordPress/gutenberg/pull/66396)) +- Remove leftover JS code from 66451. ([66472](https://github.com/WordPress/gutenberg/pull/66472)) + +#### Block Library +- Cleanup unnecessary notice removal. ([66409](https://github.com/WordPress/gutenberg/pull/66409)) +- ESLint: Fix a couple of React Compiler reassignment errors. ([66331](https://github.com/WordPress/gutenberg/pull/66331)) +- Footnotes: Remove extra callback when parsing content. ([66370](https://github.com/WordPress/gutenberg/pull/66370)) +- Gallery: Fix React Compiler reassignment error. ([66408](https://github.com/WordPress/gutenberg/pull/66408)) +- Table Block: Remove hasArrowIndicator prop. ([66204](https://github.com/WordPress/gutenberg/pull/66204)) + +#### Style Book +- Avoid state/effect combo when generating values. ([66446](https://github.com/WordPress/gutenberg/pull/66446)) +- Fix React Compiler error. ([66445](https://github.com/WordPress/gutenberg/pull/66445)) + +#### Global Styles +- Clean up: Adjust reusable-blocks dependencies. ([66302](https://github.com/WordPress/gutenberg/pull/66302)) +- Fix React Compiler variable mutation error. ([66410](https://github.com/WordPress/gutenberg/pull/66410)) + +#### Interactivity API +- iAPI: Add comments to the `deepMerge()` function. ([66220](https://github.com/WordPress/gutenberg/pull/66220)) +- iAPI: Add tests for handling arrays in `deepMerge()`. ([66218](https://github.com/WordPress/gutenberg/pull/66218)) + +#### Navigation in Site View +- Navigation: Improve trigger for fallback navigation. ([66478](https://github.com/WordPress/gutenberg/pull/66478)) + +#### Plugins API +- Plugins: Deprecate 'withPluginContext' HOC. ([66363](https://github.com/WordPress/gutenberg/pull/66363)) + +#### Site Editor +- Prepare route registration by refactoring the site editor router. ([66030](https://github.com/WordPress/gutenberg/pull/66030)) + + +### Tools + +- Add theme type to the bug report issue template. ([63851](https://github.com/WordPress/gutenberg/pull/63851)) +- Pull request automation: Use full npm install. ([66314](https://github.com/WordPress/gutenberg/pull/66314)) +- Use npm workspaces for packages (second attempt). ([66272](https://github.com/WordPress/gutenberg/pull/66272)) + +#### Testing +- Fix [Flaky Test] Entering zoomed out mode zooms the canvas. ([66212](https://github.com/WordPress/gutenberg/pull/66212)) +- Fix end-to-end test for padding appender. ([66080](https://github.com/WordPress/gutenberg/pull/66080)) +- Upgrade Playwright to v1.48. ([66296](https://github.com/WordPress/gutenberg/pull/66296)) + +#### Build Tooling +- Add new private `vips` package. ([64845](https://github.com/WordPress/gutenberg/pull/64845)) +- Revert "Use npm workspaces for packages". ([66270](https://github.com/WordPress/gutenberg/pull/66270)) + + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @AhmarZaidi: Remove toggle verb from post list data views 'Toggle details panel'. ([66334](https://github.com/WordPress/gutenberg/pull/66334)) +- @mediaformat: Remove clip & -webkit-clip-path for downloadable-block-list-item style.scss. ([66147](https://github.com/WordPress/gutenberg/pull/66147)) +- @nicolasgalvez: WP Scripts: Add a `--root-folder` argument to the `plugin-zip` command. ([61375](https://github.com/WordPress/gutenberg/pull/61375)) +- @poojabhimani12: Add Inline comment experimental flag. ([60622](https://github.com/WordPress/gutenberg/pull/60622)) +- @rinkalpagdar: Border support added to comments. ([66354](https://github.com/WordPress/gutenberg/pull/66354)) +- @rudrakshi-gupta: Add Transformation from Separator to Spacer. ([66230](https://github.com/WordPress/gutenberg/pull/66230)) +- @SH4LIN: GH-66090: Self nesting and circular nesting block fix. ([66121](https://github.com/WordPress/gutenberg/pull/66121)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @afercia @AhmarZaidi @akasunil @andrewserong @carolinan @cbravobernal @ciampo @dhruvang21 @ellatrix @getdave @gigitux @hbhalodia @jameskoster @jeryj @jsnajdr @juanfra @madhusudhand @MaggieCabrera @Mamaduka @mattrwalker @mcsf @mediaformat @michalczaplinski @mirka @mreishus @ndiego @nicolasgalvez @ntsekouras @oandregal @PARTHVATALIYA @peterwilsoncc @poojabhimani12 @prajapatisagar @ramonjd @renatho @rinkalpagdar @rudrakshi-gupta @ryanwelcher @SantosGuillamot @SH4LIN @sirreal @stokesman @swissspidy @t-hamano @talldan @tellthemachines @torounit @troychaplin @tyxla @vipul0425 @Vrishabhsk @vykes-mac @youknowriad @zaguiini + + = 19.6.0-rc.1 = ## Changelog From 8a11ce41fc7f237d22d316dcf128516a427c6086 Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Wed, 30 Oct 2024 19:18:49 +0100 Subject: [PATCH 1418/1908] Quick Edit - Slug Field: improve slug preview (#66559) * Quick Edit - Slug Field: improve slug preview * improve type Co-authored-by: gigitux <gigitux@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- packages/fields/src/fields/slug/slug-edit.tsx | 45 +++++++++---------- packages/fields/src/fields/slug/slug-view.tsx | 5 ++- packages/fields/src/fields/slug/utils.ts | 15 +++++++ 3 files changed, 39 insertions(+), 26 deletions(-) create mode 100644 packages/fields/src/fields/slug/utils.ts diff --git a/packages/fields/src/fields/slug/slug-edit.tsx b/packages/fields/src/fields/slug/slug-edit.tsx index aeb02ba42873b9..aad6610550069c 100644 --- a/packages/fields/src/fields/slug/slug-edit.tsx +++ b/packages/fields/src/fields/slug/slug-edit.tsx @@ -21,6 +21,7 @@ import { __ } from '@wordpress/i18n'; * Internal dependencies */ import type { BasePost } from '../../types'; +import { getSlug } from './utils'; const SlugEdit = ( { field, @@ -29,7 +30,7 @@ const SlugEdit = ( { }: DataFormControlProps< BasePost > ) => { const { id } = field; - const slug = field.getValue( { item: data } ) ?? ''; + const slug = field.getValue( { item: data } ) || getSlug( data ); const permalinkTemplate = data.permalink_template || ''; const PERMALINK_POSTNAME_REGEX = /%(?:postname|pagename)%/; const [ prefix, suffix ] = permalinkTemplate.split( @@ -115,30 +116,26 @@ const SlugEdit = ( { } } } aria-describedby={ postUrlSlugDescriptionId } - help={ - <> - <p className="fields-controls__slug-help"> - <span className="fields-controls__slug-help-visual-label"> - { __( 'Permalink:' ) } - </span> - <ExternalLink - className="fields-controls__slug-help-link" - href={ permalink } - > - <span className="fields-controls__slug-help-prefix"> - { permalinkPrefix } - </span> - <span className="fields-controls__slug-help-slug"> - { slugToDisplay } - </span> - <span className="fields-controls__slug-help-suffix"> - { permalinkSuffix } - </span> - </ExternalLink> - </p> - </> - } /> + <div className="fields-controls__slug-help"> + <span className="fields-controls__slug-help-visual-label"> + { __( 'Permalink:' ) } + </span> + <ExternalLink + className="fields-controls__slug-help-link" + href={ permalink } + > + <span className="fields-controls__slug-help-prefix"> + { permalinkPrefix } + </span> + <span className="fields-controls__slug-help-slug"> + { slugToDisplay } + </span> + <span className="fields-controls__slug-help-suffix"> + { permalinkSuffix } + </span> + </ExternalLink> + </div> </VStack> ) } { ! isEditable && ( diff --git a/packages/fields/src/fields/slug/slug-view.tsx b/packages/fields/src/fields/slug/slug-view.tsx index dc17eae128d68a..c418fafd1a9af9 100644 --- a/packages/fields/src/fields/slug/slug-view.tsx +++ b/packages/fields/src/fields/slug/slug-view.tsx @@ -7,9 +7,10 @@ import { useEffect, useRef } from '@wordpress/element'; * Internal dependencies */ import type { BasePost } from '../../types'; +import { getSlug } from './utils'; const SlugView = ( { item }: { item: BasePost } ) => { - const slug = item.slug; + const slug = typeof item === 'object' ? getSlug( item ) : ''; const originalSlugRef = useRef( slug ); useEffect( () => { @@ -20,7 +21,7 @@ const SlugView = ( { item }: { item: BasePost } ) => { const slugToDisplay = slug || originalSlugRef.current; - return `/${ slugToDisplay ?? '' }`; + return `${ slugToDisplay }`; }; export default SlugView; diff --git a/packages/fields/src/fields/slug/utils.ts b/packages/fields/src/fields/slug/utils.ts new file mode 100644 index 00000000000000..a422afaf898f96 --- /dev/null +++ b/packages/fields/src/fields/slug/utils.ts @@ -0,0 +1,15 @@ +/** + * WordPress dependencies + */ +import { cleanForSlug } from '@wordpress/url'; +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import { getItemTitle } from '../../actions/utils'; + +export const getSlug = ( item: BasePost ): string => { + return ( + item.slug || cleanForSlug( getItemTitle( item ) ) || item.id.toString() + ); +}; From d2b3c1fd71484347bccfa1d923fd04303656565d Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 31 Oct 2024 03:27:17 +0900 Subject: [PATCH 1419/1908] Notice: Add appropriate size props to Buttons (#66593) * Notice: Add appropriate size props to Buttons * Add size prop to reset Button in story * Add changelog * Update snapshot Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/notice/index.tsx | 2 ++ packages/components/src/notice/stories/index.story.tsx | 6 +++++- .../src/notice/test/__snapshots__/index.tsx.snap | 8 ++++---- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index e0b6a6d071e130..630b26bad2f797 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,7 @@ - `Guide`: Use small size button for page controls ([#66607](https://github.com/WordPress/gutenberg/pull/66607)). - `PaletteEdit`: Add appropriate size props to Buttons ([#66590](https://github.com/WordPress/gutenberg/pull/66590)). +- `Notice`: Add appropriate size props to Buttons ([#66593](https://github.com/WordPress/gutenberg/pull/66593)). ### Internal diff --git a/packages/components/src/notice/index.tsx b/packages/components/src/notice/index.tsx index 868576ecc9aa3f..6f3ca94d4f734a 100644 --- a/packages/components/src/notice/index.tsx +++ b/packages/components/src/notice/index.tsx @@ -142,6 +142,7 @@ function Notice( { return ( <Button + __next40pxDefaultSize key={ index } href={ url } variant={ computedVariant } @@ -160,6 +161,7 @@ function Notice( { </div> { isDismissible && ( <Button + size="small" className="components-notice__dismiss" icon={ close } label={ __( 'Close' ) } diff --git a/packages/components/src/notice/stories/index.story.tsx b/packages/components/src/notice/stories/index.story.tsx index 3314fc722af969..95bf82016c2b04 100644 --- a/packages/components/src/notice/stories/index.story.tsx +++ b/packages/components/src/notice/stories/index.story.tsx @@ -109,7 +109,11 @@ export const NoticeListSubcomponent: StoryFn< typeof NoticeList > = () => { return ( <> <NoticeList notices={ notices } onRemove={ removeNotice } /> - <Button variant="primary" onClick={ resetNotices }> + <Button + __next40pxDefaultSize + variant="primary" + onClick={ resetNotices } + > Reset Notices </Button> </> diff --git a/packages/components/src/notice/test/__snapshots__/index.tsx.snap b/packages/components/src/notice/test/__snapshots__/index.tsx.snap index c74d6fdd0a6fc9..77abecf14264be 100644 --- a/packages/components/src/notice/test/__snapshots__/index.tsx.snap +++ b/packages/components/src/notice/test/__snapshots__/index.tsx.snap @@ -21,19 +21,19 @@ exports[`Notice should match snapshot 1`] = ` class="components-notice__actions" > <a - class="components-button components-notice__action is-link" + class="components-button components-notice__action is-next-40px-default-size is-link" href="https://example.com" > More information </a> <button - class="components-button components-notice__action is-secondary" + class="components-button components-notice__action is-next-40px-default-size is-secondary" type="button" > Cancel </button> <button - class="components-button components-notice__action is-primary" + class="components-button components-notice__action is-next-40px-default-size is-primary" type="button" > Submit @@ -42,7 +42,7 @@ exports[`Notice should match snapshot 1`] = ` </div> <button aria-label="Close" - class="components-button components-notice__dismiss has-icon" + class="components-button components-notice__dismiss is-small has-icon" type="button" > <svg From fb7b17a0995a4e0c8e9e12035f9047d260bcffa3 Mon Sep 17 00:00:00 2001 From: Renatho De Carli Rosa <renatho@gmail.com> Date: Wed, 30 Oct 2024 20:28:50 -0300 Subject: [PATCH 1420/1908] Improve cover block z-index solution (#66249) * Remove not used variable * Change the order of the elements to the expected layers order So we don't need to set z-index in all the elements, creating the stacking context for the inner blocks, for example. * Update z-index styles to be applied only for backward compatibility * Add position relative to keep inner content on the top * Fix spinner position to be over the overlay * Add new fixture * Update cover fixtures * Update deprecation to match last update from trunk * Add class to the editor * Remove class in favor of a new approach checking the children * Use styles only on frontend for backward compatibility * Fix loading state * Revert "Update cover fixtures" This reverts commit 0ae62731398295ede211eb9d199b4853ddcfea0c. * Fix deprecations and fixtures * Revert "Add the has-modal-open to the editor reproducing the same behavior of the frontend" This reverts commit 64c14d3d4ff081a07bbb8583812650992b9138e0. * Improve documentation comments in the code * Fix native tests * Update snapshots * Fix order of the properties on the generated fixtures * Add alt attribute as part of the attributes changed in the previous version --------- Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Co-authored-by: renatho <renathoc@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- packages/base-styles/_z-index.scss | 6 +- .../block-library/src/cover/deprecated.js | 186 +++++++++++++++++- .../block-library/src/cover/edit/index.js | 45 +++-- packages/block-library/src/cover/editor.scss | 5 +- packages/block-library/src/cover/save.js | 47 +++-- packages/block-library/src/cover/style.scss | 56 ++++-- .../test/__snapshots__/edit.native.js.snap | 18 +- .../__snapshots__/transforms.native.js.snap | 8 +- .../src/cover/test/edit.native.js | 8 +- .../src/cover/test/transforms.native.js | 8 +- .../__snapshots__/transforms.native.js.snap | 2 +- .../__snapshots__/transforms.native.js.snap | 4 +- .../src/navigation/edit/index.js | 33 +--- .../__snapshots__/transforms.native.js.snap | 2 +- .../fixtures/blocks/core__cover.html | 2 +- .../fixtures/blocks/core__cover.parsed.json | 4 +- .../blocks/core__cover.serialized.html | 2 +- .../core__cover__alt-fixed-background.html | 4 +- ...e__cover__alt-fixed-background.parsed.json | 4 +- ...over__alt-fixed-background.serialized.html | 2 +- .../core__cover__deprecated-1.serialized.html | 2 +- .../blocks/core__cover__deprecated-10.json | 2 +- ...core__cover__deprecated-10.serialized.html | 2 +- .../blocks/core__cover__deprecated-14.html | 5 + .../blocks/core__cover__deprecated-14.json | 37 ++++ .../core__cover__deprecated-14.parsed.json | 37 ++++ ...core__cover__deprecated-14.serialized.html | 5 + .../core__cover__deprecated-2.serialized.html | 2 +- .../core__cover__deprecated-3.serialized.html | 2 +- .../core__cover__deprecated-4.serialized.html | 2 +- .../core__cover__deprecated-5.serialized.html | 2 +- .../core__cover__deprecated-6.serialized.html | 6 +- .../core__cover__deprecated-7.serialized.html | 2 +- .../core__cover__deprecated-8.serialized.html | 2 +- ...core__cover__duotone-fixed-background.html | 4 +- ...over__duotone-fixed-background.parsed.json | 4 +- ...__duotone-fixed-background.serialized.html | 2 +- .../blocks/core__cover__gradient-image.html | 2 +- .../core__cover__gradient-image.parsed.json | 4 +- ...ore__cover__gradient-image.serialized.html | 2 +- .../blocks/core__cover__gradient-video.html | 2 +- .../core__cover__gradient-video.parsed.json | 4 +- ...ore__cover__gradient-video.serialized.html | 2 +- .../blocks/core__cover__video-overlay.html | 4 +- .../blocks/core__cover__video-overlay.json | 6 +- .../core__cover__video-overlay.parsed.json | 7 +- ...core__cover__video-overlay.serialized.html | 2 +- .../fixtures/blocks/core__cover__video.html | 2 +- .../blocks/core__cover__video.parsed.json | 4 +- .../blocks/core__cover__video.serialized.html | 2 +- 50 files changed, 441 insertions(+), 166 deletions(-) create mode 100644 test/integration/fixtures/blocks/core__cover__deprecated-14.html create mode 100644 test/integration/fixtures/blocks/core__cover__deprecated-14.json create mode 100644 test/integration/fixtures/blocks/core__cover__deprecated-14.parsed.json create mode 100644 test/integration/fixtures/blocks/core__cover__deprecated-14.serialized.html diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index 7bb71732546053..e4d6ce4ce1b1c9 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -31,12 +31,14 @@ $z-layers: ( ".interface-interface-skeleton__header": 30, ".interface-interface-skeleton__content": 20, ".edit-widgets-header": 30, - ".wp-block-cover__inner-container": 1, // InnerBlocks area inside cover image block. + ".wp-block-cover.is-placeholder .components-placeholder.is-large": 1, // Cover block resizer component inside a large placeholder. + // These z-index are now used only for a deprecated version of the cover block. + ".wp-block-cover__inner-container": 1, // InnerBlocks area inside cover image block. ".wp-block-cover.has-background-dim::before": 1, // Overlay area inside block cover need to be higher than the video background. - ".block-library-cover__padding-visualizer": 2, // BoxControl visualizer needs to be +1 higher than .wp-block-cover.has-background-dim::before ".wp-block-cover__image-background": 0, // Image background inside cover block. ".wp-block-cover__video-background": 0, // Video background inside cover block. + ".wp-block-template-part__placeholder-preview-filter-input": 1, // Fixed position appender: diff --git a/packages/block-library/src/cover/deprecated.js b/packages/block-library/src/cover/deprecated.js index 5e5fc64d12c16f..6dfad9735457f6 100644 --- a/packages/block-library/src/cover/deprecated.js +++ b/packages/block-library/src/cover/deprecated.js @@ -164,7 +164,7 @@ const v8ToV11BlockAttributes = { }, }; -const v12BlockAttributes = { +const v12toV13BlockAttributes = { ...v8ToV11BlockAttributes, useFeaturedImage: { type: 'boolean', @@ -176,6 +176,20 @@ const v12BlockAttributes = { }, }; +const v14BlockAttributes = { + ...v12toV13BlockAttributes, + isUserOverlayColor: { + type: 'boolean', + }, + sizeSlug: { + type: 'string', + }, + alt: { + type: 'string', + default: '', + }, +}; + const v7toV11BlockSupports = { anchor: true, align: true, @@ -244,9 +258,173 @@ const v12BlockSupports = { }, }; +const v14BlockSupports = { + ...v12BlockSupports, + shadow: true, + dimensions: { + aspectRatio: true, + }, + interactivity: { + clientNavigation: true, + }, +}; + +// Deprecation for blocks that have z-index. +const v14 = { + attributes: v14BlockAttributes, + supports: v14BlockSupports, + save( { attributes } ) { + const { + backgroundType, + gradient, + contentPosition, + customGradient, + customOverlayColor, + dimRatio, + focalPoint, + useFeaturedImage, + hasParallax, + isDark, + isRepeated, + overlayColor, + url, + alt, + id, + minHeight: minHeightProp, + minHeightUnit, + tagName: Tag, + sizeSlug, + } = attributes; + const overlayColorClass = getColorClassName( + 'background-color', + overlayColor + ); + const gradientClass = __experimentalGetGradientClass( gradient ); + const minHeight = + minHeightProp && minHeightUnit + ? `${ minHeightProp }${ minHeightUnit }` + : minHeightProp; + + const isImageBackground = IMAGE_BACKGROUND_TYPE === backgroundType; + const isVideoBackground = VIDEO_BACKGROUND_TYPE === backgroundType; + + const isImgElement = ! ( hasParallax || isRepeated ); + + const style = { + minHeight: minHeight || undefined, + }; + + const bgStyle = { + backgroundColor: ! overlayColorClass + ? customOverlayColor + : undefined, + background: customGradient ? customGradient : undefined, + }; + + const objectPosition = + // prettier-ignore + focalPoint && isImgElement + ? mediaPosition(focalPoint) + : undefined; + + const backgroundImage = url ? `url(${ url })` : undefined; + + const backgroundPosition = mediaPosition( focalPoint ); + + const classes = clsx( + { + 'is-light': ! isDark, + 'has-parallax': hasParallax, + 'is-repeated': isRepeated, + 'has-custom-content-position': + ! isContentPositionCenter( contentPosition ), + }, + getPositionClassName( contentPosition ) + ); + + const imgClasses = clsx( + 'wp-block-cover__image-background', + id ? `wp-image-${ id }` : null, + { + [ `size-${ sizeSlug }` ]: sizeSlug, + 'has-parallax': hasParallax, + 'is-repeated': isRepeated, + } + ); + + const gradientValue = gradient || customGradient; + + return ( + <Tag { ...useBlockProps.save( { className: classes, style } ) }> + <span + aria-hidden="true" + className={ clsx( + 'wp-block-cover__background', + overlayColorClass, + dimRatioToClass( dimRatio ), + { + 'has-background-dim': dimRatio !== undefined, + // For backwards compatibility. Former versions of the Cover Block applied + // `.wp-block-cover__gradient-background` in the presence of + // media, a gradient and a dim. + 'wp-block-cover__gradient-background': + url && gradientValue && dimRatio !== 0, + 'has-background-gradient': gradientValue, + [ gradientClass ]: gradientClass, + } + ) } + style={ bgStyle } + /> + + { ! useFeaturedImage && + isImageBackground && + url && + ( isImgElement ? ( + <img + className={ imgClasses } + alt={ alt } + src={ url } + style={ { objectPosition } } + data-object-fit="cover" + data-object-position={ objectPosition } + /> + ) : ( + <div + role={ alt ? 'img' : undefined } + aria-label={ alt ? alt : undefined } + className={ imgClasses } + style={ { backgroundPosition, backgroundImage } } + /> + ) ) } + { isVideoBackground && url && ( + <video + className={ clsx( + 'wp-block-cover__video-background', + 'intrinsic-ignore' + ) } + autoPlay + muted + loop + playsInline + src={ url } + style={ { objectPosition } } + data-object-fit="cover" + data-object-position={ objectPosition } + /> + ) } + <div + { ...useInnerBlocksProps.save( { + className: 'wp-block-cover__inner-container', + } ) } + /> + </Tag> + ); + }, +}; + // Deprecation for blocks that does not have the aria-label when the image background is fixed or repeated. const v13 = { - attributes: v12BlockAttributes, + attributes: v12toV13BlockAttributes, supports: v12BlockSupports, save( { attributes } ) { const { @@ -396,7 +574,7 @@ const v13 = { // Deprecation for blocks to prevent auto overlay color from overriding previously set values. const v12 = { - attributes: v12BlockAttributes, + attributes: v12toV13BlockAttributes, supports: v12BlockSupports, isEligible( attributes ) { return ( @@ -1824,4 +2002,4 @@ const v1 = { }, }; -export default [ v13, v12, v11, v10, v9, v8, v7, v6, v5, v4, v3, v2, v1 ]; +export default [ v14, v13, v12, v11, v10, v9, v8, v7, v6, v5, v4, v3, v2, v1 ]; diff --git a/packages/block-library/src/cover/edit/index.js b/packages/block-library/src/cover/edit/index.js index 77ce9e62d9eb09..0ad87601bfba8b 100644 --- a/packages/block-library/src/cover/edit/index.js +++ b/packages/block-library/src/cover/edit/index.js @@ -527,27 +527,6 @@ function CoverEdit( { data-url={ url } > { resizeListener } - { showOverlay && ( - <span - aria-hidden="true" - className={ clsx( - 'wp-block-cover__background', - dimRatioToClass( dimRatio ), - { - [ overlayColor.class ]: overlayColor.class, - 'has-background-dim': dimRatio !== undefined, - // For backwards compatibility. Former versions of the Cover Block applied - // `.wp-block-cover__gradient-background` in the presence of - // media, a gradient and a dim. - 'wp-block-cover__gradient-background': - url && gradientValue && dimRatio !== 0, - 'has-background-gradient': gradientValue, - [ gradientClass ]: gradientClass, - } - ) } - style={ { backgroundImage: gradientValue, ...bgStyle } } - /> - ) } { ! url && useFeaturedImage && ( <Placeholder @@ -589,7 +568,31 @@ function CoverEdit( { style={ mediaStyle } /> ) } + + { showOverlay && ( + <span + aria-hidden="true" + className={ clsx( + 'wp-block-cover__background', + dimRatioToClass( dimRatio ), + { + [ overlayColor.class ]: overlayColor.class, + 'has-background-dim': dimRatio !== undefined, + // For backwards compatibility. Former versions of the Cover Block applied + // `.wp-block-cover__gradient-background` in the presence of + // media, a gradient and a dim. + 'wp-block-cover__gradient-background': + url && gradientValue && dimRatio !== 0, + 'has-background-gradient': gradientValue, + [ gradientClass ]: gradientClass, + } + ) } + style={ { backgroundImage: gradientValue, ...bgStyle } } + /> + ) } + { isUploadingMedia && <Spinner /> } + <CoverPlaceholder disableMediaButtons onSelectMedia={ onSelectMedia } diff --git a/packages/block-library/src/cover/editor.scss b/packages/block-library/src/cover/editor.scss index b92c401311beee..da5d4be26ac962 100644 --- a/packages/block-library/src/cover/editor.scss +++ b/packages/block-library/src/cover/editor.scss @@ -37,12 +37,15 @@ width: 100%; z-index: 1; } + + .wp-block-cover__inner-container { + z-index: 2; + } } // Shown while media is being uploaded .components-spinner { position: absolute; - z-index: z-index(".wp-block-cover__inner-container"); top: 50%; left: 50%; transform: translate(-50%, -50%); // Account for spinner dimensions diff --git a/packages/block-library/src/cover/save.js b/packages/block-library/src/cover/save.js index 325ddf2b741f98..47fa8010384402 100644 --- a/packages/block-library/src/cover/save.js +++ b/packages/block-library/src/cover/save.js @@ -106,26 +106,6 @@ export default function save( { attributes } ) { return ( <Tag { ...useBlockProps.save( { className: classes, style } ) }> - <span - aria-hidden="true" - className={ clsx( - 'wp-block-cover__background', - overlayColorClass, - dimRatioToClass( dimRatio ), - { - 'has-background-dim': dimRatio !== undefined, - // For backwards compatibility. Former versions of the Cover Block applied - // `.wp-block-cover__gradient-background` in the presence of - // media, a gradient and a dim. - 'wp-block-cover__gradient-background': - url && gradientValue && dimRatio !== 0, - 'has-background-gradient': gradientValue, - [ gradientClass ]: gradientClass, - } - ) } - style={ bgStyle } - /> - { ! useFeaturedImage && isImageBackground && url && @@ -162,6 +142,33 @@ export default function save( { attributes } ) { data-object-position={ objectPosition } /> ) } + + { /* The `wp-block-cover__background` needs to be immediately before + the `wp-block-cover__inner-container`, so the exclusion CSS selector + `.wp-block-cover__background + .wp-block-cover__inner-container` + works properly. If it needs to be changed in the future, the + selector for the backward compatibility for v14 deprecation also + needs change. */ } + <span + aria-hidden="true" + className={ clsx( + 'wp-block-cover__background', + overlayColorClass, + dimRatioToClass( dimRatio ), + { + 'has-background-dim': dimRatio !== undefined, + // For backwards compatibility. Former versions of the Cover Block applied + // `.wp-block-cover__gradient-background` in the presence of + // media, a gradient and a dim. + 'wp-block-cover__gradient-background': + url && gradientValue && dimRatio !== 0, + 'has-background-gradient': gradientValue, + [ gradientClass ]: gradientClass, + } + ) } + style={ bgStyle } + /> + <div { ...useInnerBlocksProps.save( { className: 'wp-block-cover__inner-container', diff --git a/packages/block-library/src/cover/style.scss b/packages/block-library/src/cover/style.scss index b2c1fe88440235..dd2dfa0578c66d 100644 --- a/packages/block-library/src/cover/style.scss +++ b/packages/block-library/src/cover/style.scss @@ -54,7 +54,6 @@ left: 0; bottom: 0; right: 0; - z-index: z-index(".wp-block-cover.has-background-dim::before"); opacity: 0.5; } @@ -95,17 +94,11 @@ } .wp-block-cover__inner-container { + position: relative; // Needed for the inner container to be positioned above other elements with absolute positioning. width: 100%; - z-index: z-index(".wp-block-cover__inner-container"); color: inherit; // Reset the fixed LTR direction at the root of the block in RTL languages. /*rtl:raw: direction: rtl; */ - - // Reset the z-index to auto when the body has a modal open. So when the - // modal is inside the cover, it doesn't create a stacking context. - @at-root .has-modal-open & { - z-index: auto; - } } // Position: Top @@ -215,14 +208,6 @@ video.wp-block-cover__video-background { } } -.wp-block-cover__video-background { - z-index: z-index(".wp-block-cover__video-background"); -} - -.wp-block-cover__image-background { - z-index: z-index(".wp-block-cover__image-background"); -} - // Styles below only exist to support older versions of the block. // Versions that not had inner blocks and used an h2 heading had a section (and not a div) with a class wp-block-cover-image (and not a wp-block-cover). // We are using the previous referred differences to target old versions. @@ -302,3 +287,42 @@ section.wp-block-cover-image > h2, color: inherit; } } + +// Backward compatibility for v14 deprecation. Only applied to the frontend. +// Regarding the `.wp-block-cover__background + .wp-block-cover__inner-container` +// selector: When the `.wp-block-cover__inner-container` comes right after the +// `.wp-block-cover__background` , it means that it's using the new HTML +// structure or that it's using the color background or gradient (even in +// the deprecated version). In the color background or gradient option we don't +// need the z-index because the elements are in the expected order. +body:not(.editor-styles-wrapper) .wp-block-cover:not( +.wp-block-cover:has( + .wp-block-cover__background + .wp-block-cover__inner-container +) +) { + .wp-block-cover__video-background { + z-index: z-index(".wp-block-cover__video-background"); + } + + .wp-block-cover__image-background { + z-index: z-index(".wp-block-cover__image-background"); + } + + // The first selector is required for old Cover markup/ + // Keep .wp-block-cover__gradient-background for v8 deprecation. + &.has-background-dim:not(.has-background-gradient)::before, + .wp-block-cover__background, + .wp-block-cover__gradient-background { + z-index: z-index(".wp-block-cover.has-background-dim::before"); + } + + .wp-block-cover__inner-container { + z-index: z-index(".wp-block-cover__inner-container"); + + // Reset the z-index to auto when the body has a modal open. So when the + // modal is inside the cover, it doesn't create a stacking context. + @at-root .has-modal-open & { + z-index: auto; + } + } +} diff --git a/packages/block-library/src/cover/test/__snapshots__/edit.native.js.snap b/packages/block-library/src/cover/test/__snapshots__/edit.native.js.snap index 25bd83daf06caf..6abcd0458752b0 100644 --- a/packages/block-library/src/cover/test/__snapshots__/edit.native.js.snap +++ b/packages/block-library/src/cover/test/__snapshots__/edit.native.js.snap @@ -34,7 +34,7 @@ exports[`color settings toggles between solid colors and gradients 1`] = ` exports[`minimum height settings changes the height value between units 1`] = ` "<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":10710,"dimRatio":50,"overlayColor":"foreground","isUserOverlayColor":true,"minHeight":50,"minHeightUnit":"px","isDark":false} --> -<div class="wp-block-cover is-light" style="min-height:50px"><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light" style="min-height:50px"><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->" @@ -42,7 +42,7 @@ exports[`minimum height settings changes the height value between units 1`] = ` exports[`minimum height settings changes the height value to 20(vw) 1`] = ` "<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":10710,"dimRatio":50,"overlayColor":"foreground","isUserOverlayColor":true,"minHeight":20,"minHeightUnit":"vw","isDark":false} --> -<div class="wp-block-cover is-light" style="min-height:20vw"><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light" style="min-height:20vw"><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->" @@ -50,7 +50,7 @@ exports[`minimum height settings changes the height value to 20(vw) 1`] = ` exports[`minimum height settings disables the decrease button when reaching the minimum value for Pixels (px) 1`] = ` "<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":10710,"dimRatio":50,"overlayColor":"foreground","isUserOverlayColor":true,"minHeight":50,"minHeightUnit":"px","isDark":false} --> -<div class="wp-block-cover is-light" style="min-height:50px"><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light" style="min-height:50px"><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->" @@ -58,7 +58,7 @@ exports[`minimum height settings disables the decrease button when reaching the exports[`minimum height settings disables the decrease button when reaching the minimum value for Relative to parent font size (em) 1`] = ` "<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":10710,"dimRatio":50,"overlayColor":"foreground","isUserOverlayColor":true,"minHeight":1,"minHeightUnit":"em","isDark":false} --> -<div class="wp-block-cover is-light" style="min-height:1em"><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light" style="min-height:1em"><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->" @@ -66,7 +66,7 @@ exports[`minimum height settings disables the decrease button when reaching the exports[`minimum height settings disables the decrease button when reaching the minimum value for Relative to root font size (rem) 1`] = ` "<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":10710,"dimRatio":50,"overlayColor":"foreground","isUserOverlayColor":true,"minHeight":1,"minHeightUnit":"rem","isDark":false} --> -<div class="wp-block-cover is-light" style="min-height:1rem"><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light" style="min-height:1rem"><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->" @@ -74,7 +74,7 @@ exports[`minimum height settings disables the decrease button when reaching the exports[`minimum height settings disables the decrease button when reaching the minimum value for Viewport height (vh) 1`] = ` "<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":10710,"dimRatio":50,"overlayColor":"foreground","isUserOverlayColor":true,"minHeight":1,"minHeightUnit":"vh","isDark":false} --> -<div class="wp-block-cover is-light" style="min-height:1vh"><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light" style="min-height:1vh"><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->" @@ -82,7 +82,7 @@ exports[`minimum height settings disables the decrease button when reaching the exports[`minimum height settings disables the decrease button when reaching the minimum value for Viewport width (vw) 1`] = ` "<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":10710,"dimRatio":50,"overlayColor":"foreground","isUserOverlayColor":true,"minHeight":1,"minHeightUnit":"vw","isDark":false} --> -<div class="wp-block-cover is-light" style="min-height:1vw"><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light" style="min-height:1vw"><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->" @@ -90,7 +90,7 @@ exports[`minimum height settings disables the decrease button when reaching the exports[`when an image is attached updates background opacity 1`] = ` "<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":10710,"dimRatio":15,"overlayColor":"foreground","isUserOverlayColor":true,"isDark":false} --> -<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim-20 has-background-dim"></span><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light"><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim-20 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->" @@ -98,7 +98,7 @@ exports[`when an image is attached updates background opacity 1`] = ` exports[`when no media is attached and overlay color is set adds image 1`] = ` "<!-- wp:cover {"url":"https://test.files.wordpress.com/local-image-1.mp4","id":2000,"dimRatio":50,"overlayColor":"cyan-bluish-gray","isUserOverlayColor":true} --> -<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-cyan-bluish-gray-background-color has-background-dim"></span><img class="wp-block-cover__image-background wp-image-2000" src="https://test.files.wordpress.com/local-image-1.mp4" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…"} --> +<div class="wp-block-cover is-light"><img class="wp-block-cover__image-background wp-image-2000" src="https://test.files.wordpress.com/local-image-1.mp4" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-cyan-bluish-gray-background-color has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…"} --> <p class="has-text-align-center"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->" diff --git a/packages/block-library/src/cover/test/__snapshots__/transforms.native.js.snap b/packages/block-library/src/cover/test/__snapshots__/transforms.native.js.snap index 1995da7a75876e..680c863d6a52a7 100644 --- a/packages/block-library/src/cover/test/__snapshots__/transforms.native.js.snap +++ b/packages/block-library/src/cover/test/__snapshots__/transforms.native.js.snap @@ -4,7 +4,7 @@ exports[`Cover block transformations with Image to Columns block 1`] = ` "<!-- wp:columns --> <div class="wp-block-columns"><!-- wp:column {"width":"100%"} --> <div class="wp-block-column" style="flex-basis:100%"><!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":890,"dimRatio":20,"overlayColor":"luminous-vivid-orange","isUserOverlayColor":true,"focalPoint":{"x":"0.63","y":"0.83"},"minHeight":219} --> -<div class="wp-block-cover" style="min-height:219px"><span aria-hidden="true" class="wp-block-cover__background has-luminous-vivid-orange-background-color has-background-dim-20 has-background-dim"></span><img class="wp-block-cover__image-background wp-image-890" alt="" src="https://cldup.com/cXyG__fTLN.jpg" style="object-position:63% 83%" data-object-fit="cover" data-object-position="63% 83%"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","className":"has-text-color has-very-light-gray-color","fontSize":"large"} --> +<div class="wp-block-cover" style="min-height:219px"><img class="wp-block-cover__image-background wp-image-890" alt="" src="https://cldup.com/cXyG__fTLN.jpg" style="object-position:63% 83%" data-object-fit="cover" data-object-position="63% 83%"/><span aria-hidden="true" class="wp-block-cover__background has-luminous-vivid-orange-background-color has-background-dim-20 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","className":"has-text-color has-very-light-gray-color","fontSize":"large"} --> <p class="has-text-align-center has-text-color has-very-light-gray-color has-large-font-size">Cool cover</p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --></div> @@ -15,7 +15,7 @@ exports[`Cover block transformations with Image to Columns block 1`] = ` exports[`Cover block transformations with Image to Group block 1`] = ` "<!-- wp:group {"layout":{"type":"constrained"}} --> <div class="wp-block-group"><!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":890,"dimRatio":20,"overlayColor":"luminous-vivid-orange","isUserOverlayColor":true,"focalPoint":{"x":"0.63","y":"0.83"},"minHeight":219} --> -<div class="wp-block-cover" style="min-height:219px"><span aria-hidden="true" class="wp-block-cover__background has-luminous-vivid-orange-background-color has-background-dim-20 has-background-dim"></span><img class="wp-block-cover__image-background wp-image-890" alt="" src="https://cldup.com/cXyG__fTLN.jpg" style="object-position:63% 83%" data-object-fit="cover" data-object-position="63% 83%"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","className":"has-text-color has-very-light-gray-color","fontSize":"large"} --> +<div class="wp-block-cover" style="min-height:219px"><img class="wp-block-cover__image-background wp-image-890" alt="" src="https://cldup.com/cXyG__fTLN.jpg" style="object-position:63% 83%" data-object-fit="cover" data-object-position="63% 83%"/><span aria-hidden="true" class="wp-block-cover__background has-luminous-vivid-orange-background-color has-background-dim-20 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","className":"has-text-color has-very-light-gray-color","fontSize":"large"} --> <p class="has-text-align-center has-text-color has-very-light-gray-color has-large-font-size">Cool cover</p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --></div> @@ -40,7 +40,7 @@ exports[`Cover block transformations with Video to Columns block 1`] = ` "<!-- wp:columns --> <div class="wp-block-columns"><!-- wp:column {"width":"100%"} --> <div class="wp-block-column" style="flex-basis:100%"><!-- wp:cover {"url":"https://i.cloudup.com/YtZFJbuQCE.mov","id":891,"dimRatio":20,"overlayColor":"luminous-vivid-orange","isUserOverlayColor":true,"backgroundType":"video","focalPoint":{"x":"0.63","y":"0.83"},"minHeight":219,"isDark":false} --> -<div class="wp-block-cover is-light" style="min-height:219px"><span aria-hidden="true" class="wp-block-cover__background has-luminous-vivid-orange-background-color has-background-dim-20 has-background-dim"></span><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="https://i.cloudup.com/YtZFJbuQCE.mov" style="object-position:63% 83%" data-object-fit="cover" data-object-position="63% 83%"></video><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","className":"has-text-color has-very-light-gray-color","fontSize":"large"} --> +<div class="wp-block-cover is-light" style="min-height:219px"><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="https://i.cloudup.com/YtZFJbuQCE.mov" style="object-position:63% 83%" data-object-fit="cover" data-object-position="63% 83%"></video><span aria-hidden="true" class="wp-block-cover__background has-luminous-vivid-orange-background-color has-background-dim-20 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","className":"has-text-color has-very-light-gray-color","fontSize":"large"} --> <p class="has-text-align-center has-text-color has-very-light-gray-color has-large-font-size">Cool cover</p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --></div> @@ -51,7 +51,7 @@ exports[`Cover block transformations with Video to Columns block 1`] = ` exports[`Cover block transformations with Video to Group block 1`] = ` "<!-- wp:group {"layout":{"type":"constrained"}} --> <div class="wp-block-group"><!-- wp:cover {"url":"https://i.cloudup.com/YtZFJbuQCE.mov","id":891,"dimRatio":20,"overlayColor":"luminous-vivid-orange","isUserOverlayColor":true,"backgroundType":"video","focalPoint":{"x":"0.63","y":"0.83"},"minHeight":219,"isDark":false} --> -<div class="wp-block-cover is-light" style="min-height:219px"><span aria-hidden="true" class="wp-block-cover__background has-luminous-vivid-orange-background-color has-background-dim-20 has-background-dim"></span><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="https://i.cloudup.com/YtZFJbuQCE.mov" style="object-position:63% 83%" data-object-fit="cover" data-object-position="63% 83%"></video><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","className":"has-text-color has-very-light-gray-color","fontSize":"large"} --> +<div class="wp-block-cover is-light" style="min-height:219px"><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="https://i.cloudup.com/YtZFJbuQCE.mov" style="object-position:63% 83%" data-object-fit="cover" data-object-position="63% 83%"></video><span aria-hidden="true" class="wp-block-cover__background has-luminous-vivid-orange-background-color has-background-dim-20 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","className":"has-text-color has-very-light-gray-color","fontSize":"large"} --> <p class="has-text-align-center has-text-color has-very-light-gray-color has-large-font-size">Cool cover</p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --></div> diff --git a/packages/block-library/src/cover/test/edit.native.js b/packages/block-library/src/cover/test/edit.native.js index 6925cfe3f62214..1b8a7133926d9d 100644 --- a/packages/block-library/src/cover/test/edit.native.js +++ b/packages/block-library/src/cover/test/edit.native.js @@ -53,13 +53,13 @@ const COVER_BLOCK_SOLID_COLOR_HTML = `<!-- wp:cover {"overlayColor":"cyan-bluish <p class="has-text-align-center"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->`; -const COVER_BLOCK_IMAGE_HTML = `<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":10710,"dimRatio":50,"overlayColor":"foreground","isDark":false} --> -<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +const COVER_BLOCK_IMAGE_HTML = `<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":10710,"dimRatio":50,"overlayColor":"foreground","isUserOverlayColor":true,"isDark":false} --> +<div class="wp-block-cover is-light"><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->`; -const COVER_BLOCK_CUSTOM_HEIGHT_HTML = `<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":10710,"dimRatio":50,"overlayColor":"foreground","minHeight":20,"minHeightUnit":"vw","isDark":false} --> -<div class="wp-block-cover is-light" style="min-height:20vw"><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +const COVER_BLOCK_CUSTOM_HEIGHT_HTML = `<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":10710,"dimRatio":50,"overlayColor":"foreground","isUserOverlayColor":true,"minHeight":20,"minHeightUnit":"vw","isDark":false} --> +<div class="wp-block-cover is-light" style="min-height:20vw"><img class="wp-block-cover__image-background wp-image-10710" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-foreground-background-color has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->`; diff --git a/packages/block-library/src/cover/test/transforms.native.js b/packages/block-library/src/cover/test/transforms.native.js index ad3a951a7e9f6d..4232570eb0779f 100644 --- a/packages/block-library/src/cover/test/transforms.native.js +++ b/packages/block-library/src/cover/test/transforms.native.js @@ -11,14 +11,14 @@ import { const block = 'Cover'; const initialHtmlWithImage = ` -<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":890,"dimRatio":20,"overlayColor":"luminous-vivid-orange","focalPoint":{"x":"0.63","y":"0.83"},"minHeight":219} --> -<div class="wp-block-cover" style="min-height:219px"><span aria-hidden="true" class="wp-block-cover__background has-luminous-vivid-orange-background-color has-background-dim-20 has-background-dim"></span><img class="wp-block-cover__image-background wp-image-890" alt="" src="https://cldup.com/cXyG__fTLN.jpg" style="object-position:63% 83%" data-object-fit="cover" data-object-position="63% 83%"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","className":"has-text-color has-very-light-gray-color","fontSize":"large"} --> +<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":890,"dimRatio":20,"overlayColor":"luminous-vivid-orange","isUserOverlayColor":true,"focalPoint":{"x":"0.63","y":"0.83"},"minHeight":219} --> +<div class="wp-block-cover" style="min-height:219px"><img class="wp-block-cover__image-background wp-image-890" alt="" src="https://cldup.com/cXyG__fTLN.jpg" style="object-position:63% 83%" data-object-fit="cover" data-object-position="63% 83%"/><span aria-hidden="true" class="wp-block-cover__background has-luminous-vivid-orange-background-color has-background-dim-20 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","className":"has-text-color has-very-light-gray-color","fontSize":"large"} --> <p class="has-text-align-center has-text-color has-very-light-gray-color has-large-font-size">Cool cover</p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->`; const initialHtmlWithVideo = ` -<!-- wp:cover {"url":"https://i.cloudup.com/YtZFJbuQCE.mov","id":891,"dimRatio":20,"overlayColor":"luminous-vivid-orange","backgroundType":"video","focalPoint":{"x":"0.63","y":"0.83"},"minHeight":219,"isDark":false} --> -<div class="wp-block-cover is-light" style="min-height:219px"><span aria-hidden="true" class="wp-block-cover__background has-luminous-vivid-orange-background-color has-background-dim-20 has-background-dim"></span><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="https://i.cloudup.com/YtZFJbuQCE.mov" style="object-position:63% 83%" data-object-fit="cover" data-object-position="63% 83%"></video><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","className":"has-text-color has-very-light-gray-color","fontSize":"large"} --> +<!-- wp:cover {"url":"https://i.cloudup.com/YtZFJbuQCE.mov","id":891,"dimRatio":20,"overlayColor":"luminous-vivid-orange","isUserOverlayColor":true,"backgroundType":"video","focalPoint":{"x":"0.63","y":"0.83"},"minHeight":219,"isDark":false} --> +<div class="wp-block-cover is-light" style="min-height:219px"><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="https://i.cloudup.com/YtZFJbuQCE.mov" style="object-position:63% 83%" data-object-fit="cover" data-object-position="63% 83%"></video><span aria-hidden="true" class="wp-block-cover__background has-luminous-vivid-orange-background-color has-background-dim-20 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","className":"has-text-color has-very-light-gray-color","fontSize":"large"} --> <p class="has-text-align-center has-text-color has-very-light-gray-color has-large-font-size">Cool cover</p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->`; diff --git a/packages/block-library/src/image/test/__snapshots__/transforms.native.js.snap b/packages/block-library/src/image/test/__snapshots__/transforms.native.js.snap index 56a5fe3c259120..338848fcae1c68 100644 --- a/packages/block-library/src/image/test/__snapshots__/transforms.native.js.snap +++ b/packages/block-library/src/image/test/__snapshots__/transforms.native.js.snap @@ -12,7 +12,7 @@ exports[`Image block transformations to Columns block 1`] = ` exports[`Image block transformations to Cover block 1`] = ` "<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":1,"dimRatio":50,"style":{"color":{}}} --> -<div class="wp-block-cover"><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><img class="wp-block-cover__image-background wp-image-1" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","fontSize":"large"} --> +<div class="wp-block-cover"><img class="wp-block-cover__image-background wp-image-1" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size">Mountain</p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->" diff --git a/packages/block-library/src/media-text/test/__snapshots__/transforms.native.js.snap b/packages/block-library/src/media-text/test/__snapshots__/transforms.native.js.snap index 07e18768ec9c2c..b479b281be720f 100644 --- a/packages/block-library/src/media-text/test/__snapshots__/transforms.native.js.snap +++ b/packages/block-library/src/media-text/test/__snapshots__/transforms.native.js.snap @@ -14,7 +14,7 @@ exports[`Media & Text block transformations with Image to Columns block 1`] = ` exports[`Media & Text block transformations with Image to Cover block 1`] = ` "<!-- wp:cover {"url":"https://cldup.com/cXyG__fTLN.jpg","id":4674,"dimRatio":50,"align":"wide"} --> -<div class="wp-block-cover alignwide"><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><img class="wp-block-cover__image-background wp-image-4674" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"className":"has-large-font-size"} --> +<div class="wp-block-cover alignwide"><img class="wp-block-cover__image-background wp-image-4674" alt="" src="https://cldup.com/cXyG__fTLN.jpg" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"className":"has-large-font-size"} --> <p class="has-large-font-size">Mountain</p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->" @@ -50,7 +50,7 @@ exports[`Media & Text block transformations with Video to Columns block 1`] = ` exports[`Media & Text block transformations with Video to Cover block 1`] = ` "<!-- wp:cover {"url":"https://i.cloudup.com/YtZFJbuQCE.mov","id":4675,"dimRatio":50,"backgroundType":"video","align":"wide"} --> -<div class="wp-block-cover alignwide"><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="https://i.cloudup.com/YtZFJbuQCE.mov" data-object-fit="cover"></video><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"className":"has-large-font-size"} --> +<div class="wp-block-cover alignwide"><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="https://i.cloudup.com/YtZFJbuQCE.mov" data-object-fit="cover"></video><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"className":"has-large-font-size"} --> <p class="has-large-font-size">Cloudup</p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->" diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js index d961f0d8fc93b9..ae7dd60bd0c5ba 100644 --- a/packages/block-library/src/navigation/edit/index.js +++ b/packages/block-library/src/navigation/edit/index.js @@ -73,33 +73,6 @@ import AccessibleDescription from './accessible-description'; import AccessibleMenuDescription from './accessible-menu-description'; import { unlock } from '../../lock-unlock'; -function useResponsiveMenu( navRef ) { - const [ isResponsiveMenuOpen, setResponsiveMenuVisibility ] = - useState( false ); - - useEffect( () => { - if ( ! navRef.current ) { - return; - } - - const htmlElement = navRef.current.ownerDocument.documentElement; - - // Add a `has-modal-open` class to the <html> when the responsive - // menu is open. This reproduces the same behavior of the frontend. - if ( isResponsiveMenuOpen ) { - htmlElement.classList.add( 'has-modal-open' ); - } else { - htmlElement.classList.remove( 'has-modal-open' ); - } - - return () => { - htmlElement?.classList.remove( 'has-modal-open' ); - }; - }, [ navRef, isResponsiveMenuOpen ] ); - - return [ isResponsiveMenuOpen, setResponsiveMenuVisibility ]; -} - function ColorTools( { textColor, setTextColor, @@ -311,10 +284,8 @@ function Navigation( { __unstableMarkNextChangeAsNotPersistent, } = useDispatch( blockEditorStore ); - const navRef = useRef(); - const [ isResponsiveMenuOpen, setResponsiveMenuVisibility ] = - useResponsiveMenu( navRef ); + useState( false ); const [ overlayMenuPreview, setOverlayMenuPreview ] = useState( false ); @@ -396,6 +367,8 @@ function Navigation( { __unstableMarkNextChangeAsNotPersistent, ] ); + const navRef = useRef(); + // The standard HTML5 tag for the block wrapper. const TagName = 'nav'; diff --git a/packages/block-library/src/video/test/__snapshots__/transforms.native.js.snap b/packages/block-library/src/video/test/__snapshots__/transforms.native.js.snap index c0ea73eadc4754..999f5083226f8c 100644 --- a/packages/block-library/src/video/test/__snapshots__/transforms.native.js.snap +++ b/packages/block-library/src/video/test/__snapshots__/transforms.native.js.snap @@ -12,7 +12,7 @@ exports[`Video block transforms to Columns block 1`] = ` exports[`Video block transforms to Cover block 1`] = ` "<!-- wp:cover {"url":"https://i.cloudup.com/YtZFJbuQCE.mov","dimRatio":50,"backgroundType":"video"} --> -<div class="wp-block-cover"><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="https://i.cloudup.com/YtZFJbuQCE.mov" data-object-fit="cover"></video><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","fontSize":"large"} --> +<div class="wp-block-cover"><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="https://i.cloudup.com/YtZFJbuQCE.mov" data-object-fit="cover"></video><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size">Cloudup video</p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover -->" diff --git a/test/integration/fixtures/blocks/core__cover.html b/test/integration/fixtures/blocks/core__cover.html index 5c69931dd22691..889a2393424c13 100644 --- a/test/integration/fixtures/blocks/core__cover.html +++ b/test/integration/fixtures/blocks/core__cover.html @@ -1,7 +1,7 @@ <!-- wp:cover {"url":"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=","dimRatio":40} --> <div class="wp-block-cover"> - <span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span> <img class="wp-block-cover__image-background" alt="" src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" data-object-fit="cover" /> + <span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span> <div class="wp-block-cover__inner-container"> <!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"> diff --git a/test/integration/fixtures/blocks/core__cover.parsed.json b/test/integration/fixtures/blocks/core__cover.parsed.json index 4df6d84c29cef2..8b340629ad19b6 100644 --- a/test/integration/fixtures/blocks/core__cover.parsed.json +++ b/test/integration/fixtures/blocks/core__cover.parsed.json @@ -20,9 +20,9 @@ ] } ], - "innerHTML": "\n<div class=\"wp-block-cover\">\n <span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-40 has-background-dim\"></span>\n <img class=\"wp-block-cover__image-background\" alt=\"\" src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\" data-object-fit=\"cover\" />\n <div class=\"wp-block-cover__inner-container\">\n\t\t\n\t</div>\n</div>\n", + "innerHTML": "\n<div class=\"wp-block-cover\">\n <img class=\"wp-block-cover__image-background\" alt=\"\" src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\" data-object-fit=\"cover\" />\n <span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-40 has-background-dim\"></span>\n <div class=\"wp-block-cover__inner-container\">\n\t\t\n\t</div>\n</div>\n", "innerContent": [ - "\n<div class=\"wp-block-cover\">\n <span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-40 has-background-dim\"></span>\n <img class=\"wp-block-cover__image-background\" alt=\"\" src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\" data-object-fit=\"cover\" />\n <div class=\"wp-block-cover__inner-container\">\n\t\t", + "\n<div class=\"wp-block-cover\">\n <img class=\"wp-block-cover__image-background\" alt=\"\" src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\" data-object-fit=\"cover\" />\n <span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-40 has-background-dim\"></span>\n <div class=\"wp-block-cover__inner-container\">\n\t\t", null, "\n\t</div>\n</div>\n" ] diff --git a/test/integration/fixtures/blocks/core__cover.serialized.html b/test/integration/fixtures/blocks/core__cover.serialized.html index b7eeb8cf4b85d8..78b88ede59d38b 100644 --- a/test/integration/fixtures/blocks/core__cover.serialized.html +++ b/test/integration/fixtures/blocks/core__cover.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=","dimRatio":40} --> -<div class="wp-block-cover"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span><img class="wp-block-cover__image-background" alt="" src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover"><img class="wp-block-cover__image-background" alt="" src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"> Guten Berg! </p> diff --git a/test/integration/fixtures/blocks/core__cover__alt-fixed-background.html b/test/integration/fixtures/blocks/core__cover__alt-fixed-background.html index 7c8aaa5a7ccbc6..0b45adb59f1f40 100644 --- a/test/integration/fixtures/blocks/core__cover__alt-fixed-background.html +++ b/test/integration/fixtures/blocks/core__cover__alt-fixed-background.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"https://w.wiki/59So","id":612,"alt":"Custom alt text","hasParallax":true,"dimRatio":50,"isDark":false,"layout":{"type":"constrained"}} --> -<div class="wp-block-cover is-light has-parallax"><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div role="img" aria-label="Custom alt text" class="wp-block-cover__image-background wp-image-612 has-parallax" style="background-position:50% 50%;background-image:url(https://w.wiki/59So)"></div><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light has-parallax"><div role="img" aria-label="Custom alt text" class="wp-block-cover__image-background wp-image-612 has-parallax" style="background-position:50% 50%;background-image:url(https://w.wiki/59So)"></div><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> -<!-- /wp:cover --> \ No newline at end of file +<!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__alt-fixed-background.parsed.json b/test/integration/fixtures/blocks/core__cover__alt-fixed-background.parsed.json index 9de6f5b24fe0d0..76e0f603020621 100644 --- a/test/integration/fixtures/blocks/core__cover__alt-fixed-background.parsed.json +++ b/test/integration/fixtures/blocks/core__cover__alt-fixed-background.parsed.json @@ -27,9 +27,9 @@ ] } ], - "innerHTML": "\n<div class=\"wp-block-cover is-light has-parallax\"><span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim\"></span><div role=\"img\" aria-label=\"Custom alt text\" class=\"wp-block-cover__image-background wp-image-612 has-parallax\" style=\"background-position:50% 50%;background-image:url(https://w.wiki/59So)\"></div><div class=\"wp-block-cover__inner-container\"></div></div>\n", + "innerHTML": "\n<div class=\"wp-block-cover is-light has-parallax\"><div role=\"img\" aria-label=\"Custom alt text\" class=\"wp-block-cover__image-background wp-image-612 has-parallax\" style=\"background-position:50% 50%;background-image:url(https://w.wiki/59So)\"></div><span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim\"></span><div class=\"wp-block-cover__inner-container\"></div></div>\n", "innerContent": [ - "\n<div class=\"wp-block-cover is-light has-parallax\"><span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim\"></span><div role=\"img\" aria-label=\"Custom alt text\" class=\"wp-block-cover__image-background wp-image-612 has-parallax\" style=\"background-position:50% 50%;background-image:url(https://w.wiki/59So)\"></div><div class=\"wp-block-cover__inner-container\">", + "\n<div class=\"wp-block-cover is-light has-parallax\"><div role=\"img\" aria-label=\"Custom alt text\" class=\"wp-block-cover__image-background wp-image-612 has-parallax\" style=\"background-position:50% 50%;background-image:url(https://w.wiki/59So)\"></div><span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim\"></span><div class=\"wp-block-cover__inner-container\">", null, "</div></div>\n" ] diff --git a/test/integration/fixtures/blocks/core__cover__alt-fixed-background.serialized.html b/test/integration/fixtures/blocks/core__cover__alt-fixed-background.serialized.html index 438eba81614c4a..0b45adb59f1f40 100644 --- a/test/integration/fixtures/blocks/core__cover__alt-fixed-background.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__alt-fixed-background.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"https://w.wiki/59So","id":612,"alt":"Custom alt text","hasParallax":true,"dimRatio":50,"isDark":false,"layout":{"type":"constrained"}} --> -<div class="wp-block-cover is-light has-parallax"><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div role="img" aria-label="Custom alt text" class="wp-block-cover__image-background wp-image-612 has-parallax" style="background-position:50% 50%;background-image:url(https://w.wiki/59So)"></div><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light has-parallax"><div role="img" aria-label="Custom alt text" class="wp-block-cover__image-background wp-image-612 has-parallax" style="background-position:50% 50%;background-image:url(https://w.wiki/59So)"></div><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__deprecated-1.serialized.html b/test/integration/fixtures/blocks/core__cover__deprecated-1.serialized.html index 0a535e66bff5b4..09ed14e47707f2 100644 --- a/test/integration/fixtures/blocks/core__cover__deprecated-1.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__deprecated-1.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==","id":34,"dimRatio":50} --> -<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><img class="wp-block-cover__image-background wp-image-34" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light"><img class="wp-block-cover__image-background wp-image-34" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"><strong>Cover Image</strong></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__deprecated-10.json b/test/integration/fixtures/blocks/core__cover__deprecated-10.json index 6286a4b12eb92e..ce3dc9eb1d553e 100644 --- a/test/integration/fixtures/blocks/core__cover__deprecated-10.json +++ b/test/integration/fixtures/blocks/core__cover__deprecated-10.json @@ -4,7 +4,6 @@ "isValid": true, "attributes": { "url": "https://w.wiki/59Sd", - "useFeaturedImage": false, "id": 609, "alt": "", "hasParallax": false, @@ -12,6 +11,7 @@ "dimRatio": 50, "backgroundType": "image", "isDark": true, + "useFeaturedImage": false, "tagName": "div" }, "innerBlocks": [ diff --git a/test/integration/fixtures/blocks/core__cover__deprecated-10.serialized.html b/test/integration/fixtures/blocks/core__cover__deprecated-10.serialized.html index d48a8b8e983945..88edf18b50c19e 100644 --- a/test/integration/fixtures/blocks/core__cover__deprecated-10.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__deprecated-10.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"https://w.wiki/59Sd","id":609,"dimRatio":50} --> -<div class="wp-block-cover"><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><img class="wp-block-cover__image-background wp-image-609" alt="" src="https://w.wiki/59Sd" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover"><img class="wp-block-cover__image-background wp-image-609" alt="" src="https://w.wiki/59Sd" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__deprecated-14.html b/test/integration/fixtures/blocks/core__cover__deprecated-14.html new file mode 100644 index 00000000000000..184d74cf12a6f0 --- /dev/null +++ b/test/integration/fixtures/blocks/core__cover__deprecated-14.html @@ -0,0 +1,5 @@ + <!-- wp:cover {"url":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==","id":36,"dimRatio":50,"overlayColor":"base","isUserOverlayColor":true,"isDark":false,"layout":{"type":"constrained"}} --> +<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-base-background-color has-background-dim"></span><img class="wp-block-cover__image-background wp-image-36" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> + <p class="has-text-align-center has-large-font-size"></p> + <!-- /wp:paragraph --></div></div> + <!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__deprecated-14.json b/test/integration/fixtures/blocks/core__cover__deprecated-14.json new file mode 100644 index 00000000000000..206e3e4c0d7e14 --- /dev/null +++ b/test/integration/fixtures/blocks/core__cover__deprecated-14.json @@ -0,0 +1,37 @@ +[ + { + "name": "core/cover", + "isValid": true, + "attributes": { + "url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==", + "id": 36, + "alt": "", + "hasParallax": false, + "isRepeated": false, + "dimRatio": 50, + "overlayColor": "base", + "backgroundType": "image", + "isDark": false, + "useFeaturedImage": false, + "tagName": "div", + "isUserOverlayColor": true, + "layout": { + "type": "constrained" + } + }, + "innerBlocks": [ + { + "name": "core/paragraph", + "isValid": true, + "attributes": { + "align": "center", + "content": "", + "dropCap": false, + "placeholder": "Write title…", + "fontSize": "large" + }, + "innerBlocks": [] + } + ] + } +] diff --git a/test/integration/fixtures/blocks/core__cover__deprecated-14.parsed.json b/test/integration/fixtures/blocks/core__cover__deprecated-14.parsed.json new file mode 100644 index 00000000000000..3a9d21e938c643 --- /dev/null +++ b/test/integration/fixtures/blocks/core__cover__deprecated-14.parsed.json @@ -0,0 +1,37 @@ +[ + { + "blockName": "core/cover", + "attrs": { + "url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==", + "id": 36, + "dimRatio": 50, + "overlayColor": "base", + "isUserOverlayColor": true, + "isDark": false, + "layout": { + "type": "constrained" + } + }, + "innerBlocks": [ + { + "blockName": "core/paragraph", + "attrs": { + "align": "center", + "placeholder": "Write title…", + "fontSize": "large" + }, + "innerBlocks": [], + "innerHTML": "\n\t<p class=\"has-text-align-center has-large-font-size\"></p>\n\t", + "innerContent": [ + "\n\t<p class=\"has-text-align-center has-large-font-size\"></p>\n\t" + ] + } + ], + "innerHTML": "\n<div class=\"wp-block-cover is-light\"><span aria-hidden=\"true\" class=\"wp-block-cover__background has-base-background-color has-background-dim\"></span><img class=\"wp-block-cover__image-background wp-image-36\" alt=\"\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==\" data-object-fit=\"cover\"/><div class=\"wp-block-cover__inner-container\"></div></div>\n\t", + "innerContent": [ + "\n<div class=\"wp-block-cover is-light\"><span aria-hidden=\"true\" class=\"wp-block-cover__background has-base-background-color has-background-dim\"></span><img class=\"wp-block-cover__image-background wp-image-36\" alt=\"\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==\" data-object-fit=\"cover\"/><div class=\"wp-block-cover__inner-container\">", + null, + "</div></div>\n\t" + ] + } +] diff --git a/test/integration/fixtures/blocks/core__cover__deprecated-14.serialized.html b/test/integration/fixtures/blocks/core__cover__deprecated-14.serialized.html new file mode 100644 index 00000000000000..1d9b7d596d962f --- /dev/null +++ b/test/integration/fixtures/blocks/core__cover__deprecated-14.serialized.html @@ -0,0 +1,5 @@ +<!-- wp:cover {"url":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==","id":36,"dimRatio":50,"overlayColor":"base","isUserOverlayColor":true,"isDark":false,"layout":{"type":"constrained"}} --> +<div class="wp-block-cover is-light"><img class="wp-block-cover__image-background wp-image-36" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-base-background-color has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<p class="has-text-align-center has-large-font-size"></p> +<!-- /wp:paragraph --></div></div> +<!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__deprecated-2.serialized.html b/test/integration/fixtures/blocks/core__cover__deprecated-2.serialized.html index 361eb663bf1f62..078084707fc164 100644 --- a/test/integration/fixtures/blocks/core__cover__deprecated-2.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__deprecated-2.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==","id":34,"dimRatio":50} --> -<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><img class="wp-block-cover__image-background wp-image-34" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light"><img class="wp-block-cover__image-background wp-image-34" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"><strong>Cover Block</strong></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__deprecated-3.serialized.html b/test/integration/fixtures/blocks/core__cover__deprecated-3.serialized.html index c1cd5a78fbee56..345054f081abeb 100644 --- a/test/integration/fixtures/blocks/core__cover__deprecated-3.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__deprecated-3.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==","id":35,"dimRatio":50} --> -<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><img class="wp-block-cover__image-background wp-image-35" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light"><img class="wp-block-cover__image-background wp-image-35" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"><strong>Cover Block</strong></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__deprecated-4.serialized.html b/test/integration/fixtures/blocks/core__cover__deprecated-4.serialized.html index be37f15331a564..e4fec9b98e228a 100644 --- a/test/integration/fixtures/blocks/core__cover__deprecated-4.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__deprecated-4.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==","id":35,"dimRatio":50,"focalPoint":{"x":"0.07","y":"0.07"}} --> -<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><img class="wp-block-cover__image-background wp-image-35" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" style="object-position:7% 7%" data-object-fit="cover" data-object-position="7% 7%"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light"><img class="wp-block-cover__image-background wp-image-35" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" style="object-position:7% 7%" data-object-fit="cover" data-object-position="7% 7%"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"><strong>Cover Block</strong></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__deprecated-5.serialized.html b/test/integration/fixtures/blocks/core__cover__deprecated-5.serialized.html index 2d9a20ba12791e..35f8479c58169f 100644 --- a/test/integration/fixtures/blocks/core__cover__deprecated-5.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__deprecated-5.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=","dimRatio":50,"gradient":"midnight"} --> -<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-background-dim wp-block-cover__gradient-background has-background-gradient has-midnight-gradient-background"></span><img class="wp-block-cover__image-background" src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light"><img class="wp-block-cover__image-background" src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim wp-block-cover__gradient-background has-background-gradient has-midnight-gradient-background"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size">Cover</p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__deprecated-6.serialized.html b/test/integration/fixtures/blocks/core__cover__deprecated-6.serialized.html index 657c10cc928964..e6f3628a1401f3 100644 --- a/test/integration/fixtures/blocks/core__cover__deprecated-6.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__deprecated-6.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=","dimRatio":40} --> -<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span><img class="wp-block-cover__image-background" src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light"><img class="wp-block-cover__image-background" src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"> Guten Berg! </p> @@ -7,13 +7,13 @@ <!-- /wp:cover --> <!-- wp:cover {"url":"https://example.com/some-background-image.png","id":1933,"dimRatio":0,"focalPoint":{"x":"0.50","y":"0.40"},"minHeight":48,"minHeightUnit":"vw","align":"full"} --> -<div class="wp-block-cover alignfull is-light" style="min-height:48vw"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-0 has-background-dim"></span><img class="wp-block-cover__image-background wp-image-1933" src="https://example.com/some-background-image.png" style="object-position:50% 40%" data-object-fit="cover" data-object-position="50% 40%"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph --> +<div class="wp-block-cover alignfull is-light" style="min-height:48vw"><img class="wp-block-cover__image-background wp-image-1933" src="https://example.com/some-background-image.png" style="object-position:50% 40%" data-object-fit="cover" data-object-position="50% 40%"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim-0 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph --> <p></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --> <!-- wp:cover {"url":"http://localhost:8888/wp-content/uploads/2021/02/percy.jpg","id":134,"dimRatio":50,"contentPosition":"bottom right"} --> -<div class="wp-block-cover is-light has-custom-content-position is-position-bottom-right"><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><img class="wp-block-cover__image-background wp-image-134" alt="" src="http://localhost:8888/wp-content/uploads/2021/02/percy.jpg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light has-custom-content-position is-position-bottom-right"><img class="wp-block-cover__image-background wp-image-134" alt="" src="http://localhost:8888/wp-content/uploads/2021/02/percy.jpg" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size">test</p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__deprecated-7.serialized.html b/test/integration/fixtures/blocks/core__cover__deprecated-7.serialized.html index baa8e32e7e8238..758219f8b0e440 100644 --- a/test/integration/fixtures/blocks/core__cover__deprecated-7.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__deprecated-7.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=","dimRatio":40} --> -<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span><img class="wp-block-cover__image-background" alt="" src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light"><img class="wp-block-cover__image-background" alt="" src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"> Guten Berg! </p> diff --git a/test/integration/fixtures/blocks/core__cover__deprecated-8.serialized.html b/test/integration/fixtures/blocks/core__cover__deprecated-8.serialized.html index fd99791a8e5247..7edbc1f1552679 100644 --- a/test/integration/fixtures/blocks/core__cover__deprecated-8.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__deprecated-8.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=","dimRatio":40} --> -<div class="wp-block-cover"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span><img class="wp-block-cover__image-background" alt="" src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover"><img class="wp-block-cover__image-background" alt="" src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"> Guten Berg! </p> diff --git a/test/integration/fixtures/blocks/core__cover__duotone-fixed-background.html b/test/integration/fixtures/blocks/core__cover__duotone-fixed-background.html index 8c77b25cf33fc5..d94cec5a8e21c7 100644 --- a/test/integration/fixtures/blocks/core__cover__duotone-fixed-background.html +++ b/test/integration/fixtures/blocks/core__cover__duotone-fixed-background.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"https://w.wiki/59So","id":612,"hasParallax":true,"isRepeated":true,"dimRatio":10,"isDark":false,"style":{"color":{"duotone":["#8c00b7","#fcff41"]}}} --> -<div class="wp-block-cover is-light has-parallax is-repeated"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-10 has-background-dim"></span><div class="wp-block-cover__image-background wp-image-612 has-parallax is-repeated" style="background-position:50% 50%;background-image:url(https://w.wiki/59So)"></div><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light has-parallax is-repeated"><div class="wp-block-cover__image-background wp-image-612 has-parallax is-repeated" style="background-position:50% 50%;background-image:url(https://w.wiki/59So)"></div><span aria-hidden="true" class="wp-block-cover__background has-background-dim-10 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> - <!-- /wp:cover --> \ No newline at end of file + <!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__duotone-fixed-background.parsed.json b/test/integration/fixtures/blocks/core__cover__duotone-fixed-background.parsed.json index 22ae61f6258ef7..da2ecc1b779706 100644 --- a/test/integration/fixtures/blocks/core__cover__duotone-fixed-background.parsed.json +++ b/test/integration/fixtures/blocks/core__cover__duotone-fixed-background.parsed.json @@ -29,9 +29,9 @@ ] } ], - "innerHTML": "\n<div class=\"wp-block-cover is-light has-parallax is-repeated\"><span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-10 has-background-dim\"></span><div class=\"wp-block-cover__image-background wp-image-612 has-parallax is-repeated\" style=\"background-position:50% 50%;background-image:url(https://w.wiki/59So)\"></div><div class=\"wp-block-cover__inner-container\"></div></div>\n ", + "innerHTML": "\n<div class=\"wp-block-cover is-light has-parallax is-repeated\"><div class=\"wp-block-cover__image-background wp-image-612 has-parallax is-repeated\" style=\"background-position:50% 50%;background-image:url(https://w.wiki/59So)\"></div><span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-10 has-background-dim\"></span><div class=\"wp-block-cover__inner-container\"></div></div>\n ", "innerContent": [ - "\n<div class=\"wp-block-cover is-light has-parallax is-repeated\"><span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-10 has-background-dim\"></span><div class=\"wp-block-cover__image-background wp-image-612 has-parallax is-repeated\" style=\"background-position:50% 50%;background-image:url(https://w.wiki/59So)\"></div><div class=\"wp-block-cover__inner-container\">", + "\n<div class=\"wp-block-cover is-light has-parallax is-repeated\"><div class=\"wp-block-cover__image-background wp-image-612 has-parallax is-repeated\" style=\"background-position:50% 50%;background-image:url(https://w.wiki/59So)\"></div><span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-10 has-background-dim\"></span><div class=\"wp-block-cover__inner-container\">", null, "</div></div>\n " ] diff --git a/test/integration/fixtures/blocks/core__cover__duotone-fixed-background.serialized.html b/test/integration/fixtures/blocks/core__cover__duotone-fixed-background.serialized.html index e52c3e993dd109..cd838bdc2b49df 100644 --- a/test/integration/fixtures/blocks/core__cover__duotone-fixed-background.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__duotone-fixed-background.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"https://w.wiki/59So","id":612,"hasParallax":true,"isRepeated":true,"dimRatio":10,"isDark":false,"style":{"color":{"duotone":["#8c00b7","#fcff41"]}}} --> -<div class="wp-block-cover is-light has-parallax is-repeated"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-10 has-background-dim"></span><div class="wp-block-cover__image-background wp-image-612 has-parallax is-repeated" style="background-position:50% 50%;background-image:url(https://w.wiki/59So)"></div><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover is-light has-parallax is-repeated"><div class="wp-block-cover__image-background wp-image-612 has-parallax is-repeated" style="background-position:50% 50%;background-image:url(https://w.wiki/59So)"></div><span aria-hidden="true" class="wp-block-cover__background has-background-dim-10 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"></p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__gradient-image.html b/test/integration/fixtures/blocks/core__cover__gradient-image.html index dba861ef5bf3f3..b10e6d215be80e 100644 --- a/test/integration/fixtures/blocks/core__cover__gradient-image.html +++ b/test/integration/fixtures/blocks/core__cover__gradient-image.html @@ -1,7 +1,7 @@ <!-- wp:cover {"url":"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=","dimRatio":30,"customGradient":"linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)"} --> <div class="wp-block-cover"> - <span aria-hidden="true" class="wp-block-cover__background has-background-dim-30 has-background-dim wp-block-cover__gradient-background has-background-gradient" style="background:linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)"></span> <img class="wp-block-cover__image-background" alt="" src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" data-object-fit="cover"/> + <span aria-hidden="true" class="wp-block-cover__background has-background-dim-30 has-background-dim wp-block-cover__gradient-background has-background-gradient" style="background:linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)"></span> <div class="wp-block-cover__inner-container"> <!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"> Cover! </p> diff --git a/test/integration/fixtures/blocks/core__cover__gradient-image.parsed.json b/test/integration/fixtures/blocks/core__cover__gradient-image.parsed.json index e5e97653e27459..38a5afd8aa1dad 100644 --- a/test/integration/fixtures/blocks/core__cover__gradient-image.parsed.json +++ b/test/integration/fixtures/blocks/core__cover__gradient-image.parsed.json @@ -21,9 +21,9 @@ ] } ], - "innerHTML": "\n<div class=\"wp-block-cover\">\n <span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-30 has-background-dim wp-block-cover__gradient-background has-background-gradient\" style=\"background:linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)\"></span>\n <img class=\"wp-block-cover__image-background\" alt=\"\" src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\" data-object-fit=\"cover\"/>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t\n\t</div>\n</div>\n", + "innerHTML": "\n<div class=\"wp-block-cover\">\n <img class=\"wp-block-cover__image-background\" alt=\"\" src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\" data-object-fit=\"cover\"/>\n <span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-30 has-background-dim wp-block-cover__gradient-background has-background-gradient\" style=\"background:linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)\"></span>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t\n\t</div>\n</div>\n", "innerContent": [ - "\n<div class=\"wp-block-cover\">\n <span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-30 has-background-dim wp-block-cover__gradient-background has-background-gradient\" style=\"background:linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)\"></span>\n <img class=\"wp-block-cover__image-background\" alt=\"\" src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\" data-object-fit=\"cover\"/>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t", + "\n<div class=\"wp-block-cover\">\n <img class=\"wp-block-cover__image-background\" alt=\"\" src=\"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=\" data-object-fit=\"cover\"/>\n <span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-30 has-background-dim wp-block-cover__gradient-background has-background-gradient\" style=\"background:linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)\"></span>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t", null, "\n\t</div>\n</div>\n" ] diff --git a/test/integration/fixtures/blocks/core__cover__gradient-image.serialized.html b/test/integration/fixtures/blocks/core__cover__gradient-image.serialized.html index 135949383f712c..22fbae8ff0ec36 100644 --- a/test/integration/fixtures/blocks/core__cover__gradient-image.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__gradient-image.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=","dimRatio":30,"customGradient":"linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)"} --> -<div class="wp-block-cover"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-30 has-background-dim wp-block-cover__gradient-background has-background-gradient" style="background:linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)"></span><img class="wp-block-cover__image-background" alt="" src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover"><img class="wp-block-cover__image-background" alt="" src="data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-background-dim-30 has-background-dim wp-block-cover__gradient-background has-background-gradient" style="background:linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"> Cover! </p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__gradient-video.html b/test/integration/fixtures/blocks/core__cover__gradient-video.html index 1081afe2518b3a..b2450400dd6853 100644 --- a/test/integration/fixtures/blocks/core__cover__gradient-video.html +++ b/test/integration/fixtures/blocks/core__cover__gradient-video.html @@ -1,7 +1,7 @@ <!-- wp:cover {"url":"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=","dimRatio":70,"backgroundType":"video","customGradient":"linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)"} --> <div class="wp-block-cover"> - <span aria-hidden="true" class="wp-block-cover__background has-background-dim-70 has-background-dim wp-block-cover__gradient-background has-background-gradient" style="background:linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)"></span> <video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=" data-object-fit="cover"></video> + <span aria-hidden="true" class="wp-block-cover__background has-background-dim-70 has-background-dim wp-block-cover__gradient-background has-background-gradient" style="background:linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)"></span> <div class="wp-block-cover__inner-container"> <!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size">Cover!</p> diff --git a/test/integration/fixtures/blocks/core__cover__gradient-video.parsed.json b/test/integration/fixtures/blocks/core__cover__gradient-video.parsed.json index 8ad72c9c549b24..95e30ce99f9d7b 100644 --- a/test/integration/fixtures/blocks/core__cover__gradient-video.parsed.json +++ b/test/integration/fixtures/blocks/core__cover__gradient-video.parsed.json @@ -22,9 +22,9 @@ ] } ], - "innerHTML": "\n<div class=\"wp-block-cover\">\n\t<span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-70 has-background-dim wp-block-cover__gradient-background has-background-gradient\" style=\"background:linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)\"></span>\n\t<video class=\"wp-block-cover__video-background intrinsic-ignore\" autoplay muted loop playsinline src=\"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=\" data-object-fit=\"cover\"></video>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t\n\t</div>\n</div>\n", + "innerHTML": "\n<div class=\"wp-block-cover\">\n\t<video class=\"wp-block-cover__video-background intrinsic-ignore\" autoplay muted loop playsinline src=\"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=\" data-object-fit=\"cover\"></video>\n\t<span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-70 has-background-dim wp-block-cover__gradient-background has-background-gradient\" style=\"background:linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)\"></span>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t\n\t</div>\n</div>\n", "innerContent": [ - "\n<div class=\"wp-block-cover\">\n\t<span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-70 has-background-dim wp-block-cover__gradient-background has-background-gradient\" style=\"background:linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)\"></span>\n\t<video class=\"wp-block-cover__video-background intrinsic-ignore\" autoplay muted loop playsinline src=\"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=\" data-object-fit=\"cover\"></video>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t", + "\n<div class=\"wp-block-cover\">\n\t<video class=\"wp-block-cover__video-background intrinsic-ignore\" autoplay muted loop playsinline src=\"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=\" data-object-fit=\"cover\"></video>\n\t<span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-70 has-background-dim wp-block-cover__gradient-background has-background-gradient\" style=\"background:linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)\"></span>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t", null, "\n\t</div>\n</div>\n" ] diff --git a/test/integration/fixtures/blocks/core__cover__gradient-video.serialized.html b/test/integration/fixtures/blocks/core__cover__gradient-video.serialized.html index 417d8666481dcd..ab6f8bdd2a4ddf 100644 --- a/test/integration/fixtures/blocks/core__cover__gradient-video.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__gradient-video.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=","dimRatio":70,"backgroundType":"video","customGradient":"linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)"} --> -<div class="wp-block-cover"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-70 has-background-dim wp-block-cover__gradient-background has-background-gradient" style="background:linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)"></span><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=" data-object-fit="cover"></video><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover"><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=" data-object-fit="cover"></video><span aria-hidden="true" class="wp-block-cover__background has-background-dim-70 has-background-dim wp-block-cover__gradient-background has-background-gradient" style="background:linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size">Cover!</p> <!-- /wp:paragraph --></div></div> <!-- /wp:cover --> diff --git a/test/integration/fixtures/blocks/core__cover__video-overlay.html b/test/integration/fixtures/blocks/core__cover__video-overlay.html index 3d78269821c152..ee45ce3355ebf2 100644 --- a/test/integration/fixtures/blocks/core__cover__video-overlay.html +++ b/test/integration/fixtures/blocks/core__cover__video-overlay.html @@ -1,7 +1,7 @@ -<!-- wp:cover {"url":"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=","dimRatio":10,"customOverlayColor":"#3615d9","backgroundType":"video"} --> +<!-- wp:cover {"url":"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=","dimRatio":10,"customOverlayColor":"#3615d9","backgroundType":"video","isUserOverlayColor":true} --> <div class="wp-block-cover"> - <span aria-hidden="true" class="wp-block-cover__background has-background-dim-10 has-background-dim" style="background-color:#3615d9"></span> <video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=" data-object-fit="cover"></video> + <span aria-hidden="true" class="wp-block-cover__background has-background-dim-10 has-background-dim" style="background-color:#3615d9"></span> <div class="wp-block-cover__inner-container"> <!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"> diff --git a/test/integration/fixtures/blocks/core__cover__video-overlay.json b/test/integration/fixtures/blocks/core__cover__video-overlay.json index 7916e3f7a20b6e..a4171b22c98423 100644 --- a/test/integration/fixtures/blocks/core__cover__video-overlay.json +++ b/test/integration/fixtures/blocks/core__cover__video-overlay.json @@ -4,16 +4,16 @@ "isValid": true, "attributes": { "url": "data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=", + "useFeaturedImage": false, "alt": "", "hasParallax": false, "isRepeated": false, "dimRatio": 10, "customOverlayColor": "#3615d9", + "isUserOverlayColor": true, "backgroundType": "video", "isDark": true, - "useFeaturedImage": false, - "tagName": "div", - "isUserOverlayColor": true + "tagName": "div" }, "innerBlocks": [ { diff --git a/test/integration/fixtures/blocks/core__cover__video-overlay.parsed.json b/test/integration/fixtures/blocks/core__cover__video-overlay.parsed.json index c766000af56727..25bc07b02d873e 100644 --- a/test/integration/fixtures/blocks/core__cover__video-overlay.parsed.json +++ b/test/integration/fixtures/blocks/core__cover__video-overlay.parsed.json @@ -5,7 +5,8 @@ "url": "data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=", "dimRatio": 10, "customOverlayColor": "#3615d9", - "backgroundType": "video" + "backgroundType": "video", + "isUserOverlayColor": true }, "innerBlocks": [ { @@ -22,9 +23,9 @@ ] } ], - "innerHTML": "\n<div class=\"wp-block-cover\">\n\t<span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-10 has-background-dim\" style=\"background-color:#3615d9\"></span>\n\t<video class=\"wp-block-cover__video-background intrinsic-ignore\" autoplay muted loop playsinline src=\"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=\" data-object-fit=\"cover\"></video>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t\n\t</div>\n</div>\n", + "innerHTML": "\n<div class=\"wp-block-cover\">\n\t<video class=\"wp-block-cover__video-background intrinsic-ignore\" autoplay muted loop playsinline src=\"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=\" data-object-fit=\"cover\"></video>\n\t<span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-10 has-background-dim\" style=\"background-color:#3615d9\"></span>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t\n\t</div>\n</div>\n", "innerContent": [ - "\n<div class=\"wp-block-cover\">\n\t<span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-10 has-background-dim\" style=\"background-color:#3615d9\"></span>\n\t<video class=\"wp-block-cover__video-background intrinsic-ignore\" autoplay muted loop playsinline src=\"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=\" data-object-fit=\"cover\"></video>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t", + "\n<div class=\"wp-block-cover\">\n\t<video class=\"wp-block-cover__video-background intrinsic-ignore\" autoplay muted loop playsinline src=\"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=\" data-object-fit=\"cover\"></video>\n\t<span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-10 has-background-dim\" style=\"background-color:#3615d9\"></span>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t", null, "\n\t</div>\n</div>\n" ] diff --git a/test/integration/fixtures/blocks/core__cover__video-overlay.serialized.html b/test/integration/fixtures/blocks/core__cover__video-overlay.serialized.html index 3cbf472fe84c4a..f46a2b18c7044c 100644 --- a/test/integration/fixtures/blocks/core__cover__video-overlay.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__video-overlay.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=","dimRatio":10,"customOverlayColor":"#3615d9","isUserOverlayColor":true,"backgroundType":"video"} --> -<div class="wp-block-cover"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-10 has-background-dim" style="background-color:#3615d9"></span><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=" data-object-fit="cover"></video><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover"><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=" data-object-fit="cover"></video><span aria-hidden="true" class="wp-block-cover__background has-background-dim-10 has-background-dim" style="background-color:#3615d9"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"> Guten Berg! </p> diff --git a/test/integration/fixtures/blocks/core__cover__video.html b/test/integration/fixtures/blocks/core__cover__video.html index 6dc5bfae8a15e4..84402f3079748d 100644 --- a/test/integration/fixtures/blocks/core__cover__video.html +++ b/test/integration/fixtures/blocks/core__cover__video.html @@ -1,7 +1,7 @@ <!-- wp:cover {"url":"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=","dimRatio":40,"backgroundType":"video"} --> <div class="wp-block-cover"> - <span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span> <video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=" data-object-fit="cover"></video> + <span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span> <div class="wp-block-cover__inner-container"> <!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"> diff --git a/test/integration/fixtures/blocks/core__cover__video.parsed.json b/test/integration/fixtures/blocks/core__cover__video.parsed.json index 0ac0886db52f1f..652886567348f8 100644 --- a/test/integration/fixtures/blocks/core__cover__video.parsed.json +++ b/test/integration/fixtures/blocks/core__cover__video.parsed.json @@ -21,9 +21,9 @@ ] } ], - "innerHTML": "\n<div class=\"wp-block-cover\">\n\t<span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-40 has-background-dim\"></span>\n\t<video class=\"wp-block-cover__video-background intrinsic-ignore\" autoplay muted loop playsinline src=\"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=\" data-object-fit=\"cover\"></video>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t\n\t</div>\n</div>\n", + "innerHTML": "\n<div class=\"wp-block-cover\">\n\t<video class=\"wp-block-cover__video-background intrinsic-ignore\" autoplay muted loop playsinline src=\"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=\" data-object-fit=\"cover\"></video>\n\t<span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-40 has-background-dim\"></span>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t\n\t</div>\n</div>\n", "innerContent": [ - "\n<div class=\"wp-block-cover\">\n\t<span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-40 has-background-dim\"></span>\n\t<video class=\"wp-block-cover__video-background intrinsic-ignore\" autoplay muted loop playsinline src=\"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=\" data-object-fit=\"cover\"></video>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t", + "\n<div class=\"wp-block-cover\">\n\t<video class=\"wp-block-cover__video-background intrinsic-ignore\" autoplay muted loop playsinline src=\"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=\" data-object-fit=\"cover\"></video>\n\t<span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-40 has-background-dim\"></span>\n\t<div class=\"wp-block-cover__inner-container\">\n\t\t", null, "\n\t</div>\n</div>\n" ] diff --git a/test/integration/fixtures/blocks/core__cover__video.serialized.html b/test/integration/fixtures/blocks/core__cover__video.serialized.html index 0fb6cbf9e1266e..9670adfd6c3cbd 100644 --- a/test/integration/fixtures/blocks/core__cover__video.serialized.html +++ b/test/integration/fixtures/blocks/core__cover__video.serialized.html @@ -1,5 +1,5 @@ <!-- wp:cover {"url":"data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=","dimRatio":40,"backgroundType":"video"} --> -<div class="wp-block-cover"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=" data-object-fit="cover"></video><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> +<div class="wp-block-cover"><video class="wp-block-cover__video-background intrinsic-ignore" autoplay muted loop playsinline src="data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAC721kYXQhEAUgpBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBSCkG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAsJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAALwABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAB7HRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAIAAAAAAAAALwAAAAAAAAAAAAAAAQEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAC8AAAAAAAEAAAAAAWRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAKxEAAAIAFXEAAAAAAAtaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAFNvdW5kSGFuZGxlcgAAAAEPbWluZgAAABBzbWhkAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAADTc3RibAAAAGdzdHNkAAAAAAAAAAEAAABXbXA0YQAAAAAAAAABAAAAAAAAAAAAAgAQAAAAAKxEAAAAAAAzZXNkcwAAAAADgICAIgACAASAgIAUQBUAAAAAAfQAAAHz+QWAgIACEhAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAIAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAFzAAABdAAAABRzdGNvAAAAAAAAAAEAAAAsAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1Ni40MC4xMDE=" data-object-fit="cover"></video><span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} --> <p class="has-text-align-center has-large-font-size"> Guten Berg! </p> From ed178c3313beaafaf9a1c28774676cc9636a3790 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:44:44 +0100 Subject: [PATCH 1421/1908] Perf: avoid fetching all reusable blocks on load in patterns preference modal (#66621) Avoid fetching block patterns when the site editor loads. Move useStartPatterns() hook to a wrapper and return early if the preferences modal is not active. Fix JS unit tests --------- Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- .../src/components/preferences-modal/index.js | 45 +++++++++++-------- .../preferences-modal/test/index.js | 2 +- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/packages/editor/src/components/preferences-modal/index.js b/packages/editor/src/components/preferences-modal/index.js index a8cfd8245522cd..7ea7ea456ce28e 100644 --- a/packages/editor/src/components/preferences-modal/index.js +++ b/packages/editor/src/components/preferences-modal/index.js @@ -36,25 +36,40 @@ const { } = unlock( preferencesPrivateApis ); export default function EditorPreferencesModal( { extraSections = {} } ) { + const isActive = useSelect( ( select ) => { + return select( interfaceStore ).isModalActive( 'editor/preferences' ); + }, [] ); + const { closeModal } = useDispatch( interfaceStore ); + + if ( ! isActive ) { + return null; + } + + // Please wrap all contents inside PreferencesModalContents to prevent all + // hooks from executing when the modal is not open. + return ( + <PreferencesModal closeModal={ closeModal }> + <PreferencesModalContents extraSections={ extraSections } /> + </PreferencesModal> + ); +} + +function PreferencesModalContents( { extraSections = {} } ) { const isLargeViewport = useViewportMatch( 'medium' ); - const { isActive, showBlockBreadcrumbsOption } = useSelect( + const showBlockBreadcrumbsOption = useSelect( ( select ) => { const { getEditorSettings } = select( editorStore ); const { get } = select( preferencesStore ); - const { isModalActive } = select( interfaceStore ); const isRichEditingEnabled = getEditorSettings().richEditingEnabled; const isDistractionFreeEnabled = get( 'core', 'distractionFree' ); - return { - showBlockBreadcrumbsOption: - ! isDistractionFreeEnabled && - isLargeViewport && - isRichEditingEnabled, - isActive: isModalActive( 'editor/preferences' ), - }; + return ( + ! isDistractionFreeEnabled && + isLargeViewport && + isRichEditingEnabled + ); }, [ isLargeViewport ] ); - const { closeModal } = useDispatch( interfaceStore ); const { setIsListViewOpened, setIsInserterOpened } = useDispatch( editorStore ); const { set: setPreference } = useDispatch( preferencesStore ); @@ -330,13 +345,5 @@ export default function EditorPreferencesModal( { extraSections = {} } ) { ] ); - if ( ! isActive ) { - return null; - } - - return ( - <PreferencesModal closeModal={ closeModal }> - <PreferencesModalTabs sections={ sections } /> - </PreferencesModal> - ); + return <PreferencesModalTabs sections={ sections } />; } diff --git a/packages/editor/src/components/preferences-modal/test/index.js b/packages/editor/src/components/preferences-modal/test/index.js index 01ac1a88fbe7d8..70102eea40f2ee 100644 --- a/packages/editor/src/components/preferences-modal/test/index.js +++ b/packages/editor/src/components/preferences-modal/test/index.js @@ -19,7 +19,7 @@ jest.mock( '@wordpress/compose/src/hooks/use-viewport-match', () => jest.fn() ); describe( 'EditPostPreferencesModal', () => { it( 'should not render when the modal is not active', () => { - useSelect.mockImplementation( () => [ false, false, false ] ); + useSelect.mockImplementation( () => false ); render( <EditPostPreferencesModal /> ); expect( screen.queryByRole( 'dialog', { name: 'Preferences' } ) From beae8ad4601ea9c1d39d00f5bfab512d2163e990 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:48:17 +1100 Subject: [PATCH 1422/1908] Global styles: preload user global styles based on user caps (#66541) This commit preloads '/wp/v2/global-styles/' . $global_styles_id with a context corresponding to user caps, that is, edit for users that can edit global styles, and view for everyone else. Preloading the global styles endpoint according to role context means that admins and non admins, e.g., editors, avoid clientside requests. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- backport-changelog/6.8/7681.md | 3 ++ lib/compat/wordpress-6.7/rest-api.php | 2 +- lib/compat/wordpress-6.8/preload.php | 32 +++++++++++++++++++ .../global-styles-provider/index.js | 28 +++++++++++----- 4 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 backport-changelog/6.8/7681.md diff --git a/backport-changelog/6.8/7681.md b/backport-changelog/6.8/7681.md new file mode 100644 index 00000000000000..b8cffc70c68561 --- /dev/null +++ b/backport-changelog/6.8/7681.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7681 + +* https://github.com/WordPress/gutenberg/pull/66541 diff --git a/lib/compat/wordpress-6.7/rest-api.php b/lib/compat/wordpress-6.7/rest-api.php index 89efdc4c4219d2..741d0ad1805e07 100644 --- a/lib/compat/wordpress-6.7/rest-api.php +++ b/lib/compat/wordpress-6.7/rest-api.php @@ -51,7 +51,6 @@ function gutenberg_block_editor_preload_paths_6_7( $paths, $context ) { } // Preload theme and global styles paths. - $excluded_paths = array(); if ( 'core/edit-site' === $context->name || 'core/edit-post' === $context->name ) { $active_theme = get_stylesheet(); $global_styles_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id(); @@ -60,6 +59,7 @@ function gutenberg_block_editor_preload_paths_6_7( $paths, $context ) { $paths[] = array( '/wp/v2/global-styles/' . $global_styles_id, 'OPTIONS' ); // Remove duplicate or unnecessary global styles paths. + $excluded_paths = array(); $excluded_paths[] = '/wp/v2/global-styles/themes/' . $active_theme; $excluded_paths[] = '/wp/v2/global-styles/' . $global_styles_id; foreach ( $paths as $key => $path ) { diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php index 5ba613e22033d4..0805ace4233d59 100644 --- a/lib/compat/wordpress-6.8/preload.php +++ b/lib/compat/wordpress-6.8/preload.php @@ -29,6 +29,38 @@ function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { ) ); } + + // Preload theme and global styles paths. + if ( 'core/edit-site' === $context->name || 'core/edit-post' === $context->name ) { + $global_styles_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id(); + $excluded_paths = array(); + /* + * Removes any edit or view context paths originating from Core, + * or elsewhere, e.g., gutenberg_block_editor_preload_paths_6_6(). + * Aside from not preloading unnecessary contexts, it also ensures there no duplicates, + * leading to a small optimization: block_editor_rest_api_preload() does not dedupe, + * and will fire off a WP_REST_Request for every path. In the case of + * `/wp/v2/global-styles/*` this will create a new WP_Theme_JSON() instance. + */ + $excluded_paths[] = '/wp/v2/global-styles/' . $global_styles_id . '?context=view'; + // Removes any edit context path originating from gutenberg_block_editor_preload_paths_6_6(). + $excluded_paths[] = '/wp/v2/global-styles/' . $global_styles_id . '?context=edit'; + foreach ( $paths as $key => $path ) { + if ( in_array( $path, $excluded_paths, true ) ) { + unset( $paths[ $key ] ); + } + } + + /* + * Preload the global styles path with the correct context based on user caps. + * NOTE: There is an equivalent conditional check in the client-side code to fetch + * the global styles entity using the appropriate context value. + * See the call to `canUser()`, under `useGlobalStylesUserConfig()` in `packages/edit-site/src/components/use-global-styles-user-config/index.js`. + * Please ensure that the equivalent check is kept in sync with this preload path. + */ + $context = current_user_can( 'edit_theme_options' ) ? 'edit' : 'view'; + $paths[] = "/wp/v2/global-styles/$global_styles_id?context=$context"; + } return $paths; } add_filter( 'block_editor_rest_api_preload_paths', 'gutenberg_block_editor_preload_paths_6_8', 10, 2 ); diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js index 3f3a3389801eb6..74fbed5f000624 100644 --- a/packages/editor/src/components/global-styles-provider/index.js +++ b/packages/editor/src/components/global-styles-provider/index.js @@ -57,11 +57,13 @@ function useGlobalStylesUserConfig() { let record; - // We want the global styles ID request to finish before triggering - // the OPTIONS request for user capabilities, otherwise it will - // fetch `/wp/v2/global-styles` instead of - // `/wp/v2/global-styles/{id}`! - // Please adjust the preloaded requests if this changes! + /* + * Ensure that the global styles ID request is complete by testing `_globalStylesId`, + * before firing off the `canUser` OPTIONS request for user capabilities, otherwise it will + * fetch `/wp/v2/global-styles` instead of `/wp/v2/global-styles/{id}`. + * NOTE: Please keep in sync any preload paths sent to `block_editor_rest_api_preload()`, + * or set using the `block_editor_rest_api_preload_paths` filter, if this changes. + */ const userCanEditGlobalStyles = _globalStylesId ? canUser( 'update', { kind: 'root', @@ -72,11 +74,21 @@ function useGlobalStylesUserConfig() { if ( _globalStylesId && - // We want the OPTIONS request for user capabilities to finish - // before getting the records, otherwise we'll fetch both! + /* + * Test that the OPTIONS request for user capabilities is complete + * before fetching the global styles entity record. + * This is to avoid fetching the global styles entity unnecessarily. + */ typeof userCanEditGlobalStyles === 'boolean' ) { - // Please adjust the preloaded requests if this changes! + /* + * Fetch the global styles entity record based on the user's capabilities. + * The default context is `edit` for users who can edit global styles. + * Otherwise, the context is `view`. + * NOTE: There is an equivalent conditional check using `current_user_can()` in the backend + * to preload the global styles entity. Please keep in sync any preload paths sent to `block_editor_rest_api_preload()`, + * or set using `block_editor_rest_api_preload_paths` filter, if this changes. + */ if ( userCanEditGlobalStyles ) { record = getEditedEntityRecord( 'root', From bf08f064ee6ff01d6042db5e61c02ddbff728ddc Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 31 Oct 2024 13:48:06 +1100 Subject: [PATCH 1423/1908] PostTaxonomiesFlatTermSelector: abstract wrapper component (#66625) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> --- .../post-taxonomies/flat-term-selector.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/editor/src/components/post-taxonomies/flat-term-selector.js b/packages/editor/src/components/post-taxonomies/flat-term-selector.js index 21a62c9819026d..cd9377766af503 100644 --- a/packages/editor/src/components/post-taxonomies/flat-term-selector.js +++ b/packages/editor/src/components/post-taxonomies/flat-term-selector.js @@ -57,6 +57,13 @@ const termNamesToIds = ( names, terms ) => { .filter( ( id ) => id !== undefined ); }; +const Wrapper = ( { children, __nextHasNoMarginBottom } ) => + __nextHasNoMarginBottom ? ( + <VStack spacing={ 4 }>{ children }</VStack> + ) : ( + <Fragment>{ children }</Fragment> + ); + /** * Renders a flat term selector component. * @@ -292,15 +299,8 @@ export function FlatTermSelector( { slug, __nextHasNoMarginBottom } ) { singularName ); - const Wrapper = ( { children } ) => - __nextHasNoMarginBottom ? ( - <VStack spacing={ 4 }>{ children }</VStack> - ) : ( - <Fragment>{ children }</Fragment> - ); - return ( - <Wrapper> + <Wrapper __nextHasNoMarginBottom={ __nextHasNoMarginBottom }> <FormTokenField __next40pxDefaultSize value={ values } From 37e8b9c623a833809a14eaf5ab448565acea0350 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 31 Oct 2024 14:38:48 +0900 Subject: [PATCH 1424/1908] MenuItem: Add 40px size prop on Button (#66596) * MenuItem: Add 40px size prop on Button * Add changelog * Update snapshots Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/menu-item/index.tsx | 1 + .../src/menu-item/test/__snapshots__/index.js.snap | 8 ++++---- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 630b26bad2f797..5fd48336f956c1 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -4,6 +4,7 @@ ### Enhancements +- `MenuItem`: Add 40px size prop on Button ([#66596](https://github.com/WordPress/gutenberg/pull/66596)). - `Guide`: Use small size button for page controls ([#66607](https://github.com/WordPress/gutenberg/pull/66607)). - `PaletteEdit`: Add appropriate size props to Buttons ([#66590](https://github.com/WordPress/gutenberg/pull/66590)). - `Notice`: Add appropriate size props to Buttons ([#66593](https://github.com/WordPress/gutenberg/pull/66593)). diff --git a/packages/components/src/menu-item/index.tsx b/packages/components/src/menu-item/index.tsx index cb746becdbb1ba..cc57d23e585a10 100644 --- a/packages/components/src/menu-item/index.tsx +++ b/packages/components/src/menu-item/index.tsx @@ -56,6 +56,7 @@ function UnforwardedMenuItem( return ( <Button + __next40pxDefaultSize ref={ ref } // Make sure aria-checked matches spec https://www.w3.org/TR/wai-aria-1.1/#aria-checked aria-checked={ diff --git a/packages/components/src/menu-item/test/__snapshots__/index.js.snap b/packages/components/src/menu-item/test/__snapshots__/index.js.snap index 06aaf4b620dfe0..07dc49b034e5ee 100644 --- a/packages/components/src/menu-item/test/__snapshots__/index.js.snap +++ b/packages/components/src/menu-item/test/__snapshots__/index.js.snap @@ -3,7 +3,7 @@ exports[`MenuItem should match snapshot when all props provided 1`] = ` <button aria-checked="true" - class="components-button components-menu-item__button my-class" + class="components-button components-menu-item__button my-class is-next-40px-default-size" role="menuitemcheckbox" type="button" > @@ -35,7 +35,7 @@ exports[`MenuItem should match snapshot when all props provided 1`] = ` exports[`MenuItem should match snapshot when info is provided 1`] = ` <button - class="components-button components-menu-item__button" + class="components-button components-menu-item__button is-next-40px-default-size" role="menuitem" type="button" > @@ -62,7 +62,7 @@ exports[`MenuItem should match snapshot when info is provided 1`] = ` exports[`MenuItem should match snapshot when isSelected and role are optionally provided 1`] = ` <button - class="components-button components-menu-item__button my-class" + class="components-button components-menu-item__button my-class is-next-40px-default-size" role="menuitem" type="button" > @@ -94,7 +94,7 @@ exports[`MenuItem should match snapshot when isSelected and role are optionally exports[`MenuItem should match snapshot when only label provided 1`] = ` <button - class="components-button components-menu-item__button" + class="components-button components-menu-item__button is-next-40px-default-size" role="menuitem" type="button" > From fb511a648a75bac4607f5fb9ba1f72ca5519e097 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:03:16 +0900 Subject: [PATCH 1425/1908] Disable device preview in pattern/template part/navitation editor (#65970) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> --- packages/editor/src/components/header/index.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index 1bd1114852fd6c..07a5e9ddee5911 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -25,6 +25,11 @@ import PostViewLink from '../post-view-link'; import PreviewDropdown from '../preview-dropdown'; import ZoomOutToggle from '../zoom-out-toggle'; import { store as editorStore } from '../../store'; +import { + TEMPLATE_PART_POST_TYPE, + PATTERN_POST_TYPE, + NAVIGATION_POST_TYPE, +} from '../../store/constants'; const toolbarVariations = { distractionFreeDisabled: { y: '-50px' }, @@ -60,12 +65,10 @@ function Header( { showIconLabels, hasFixedToolbar, hasBlockSelection, - isNestedEntity, } = useSelect( ( select ) => { const { get: getPreference } = select( preferencesStore ); const { getEditorMode, - getEditorSettings, getCurrentPostType, isPublishSidebarOpened: _isPublishSidebarOpened, } = select( editorStore ); @@ -78,8 +81,6 @@ function Header( { hasFixedToolbar: getPreference( 'core', 'fixedToolbar' ), hasBlockSelection: !! select( blockEditorStore ).getBlockSelectionStart(), - isNestedEntity: - !! getEditorSettings().onNavigateToPreviousEntityRecord, }; }, [] ); @@ -87,6 +88,12 @@ function Header( { postType ); + const disablePreviewOption = [ + NAVIGATION_POST_TYPE, + TEMPLATE_PART_POST_TYPE, + PATTERN_POST_TYPE, + ].includes( postType ); + const [ isBlockToolsCollapsed, setIsBlockToolsCollapsed ] = useState( true ); @@ -155,7 +162,7 @@ function Header( { <PreviewDropdown forceIsAutosaveable={ forceIsDirty } - disabled={ isNestedEntity } + disabled={ disablePreviewOption } /> <PostPreviewButton className="editor-header__post-preview-button" From 7d4ee569844adf697ff4deb57019e2f01200e7dd Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:05:02 +0100 Subject: [PATCH 1426/1908] Block editor: exclude wp- styles from iframe compat styles (#66628) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../components/iframe/get-compatibility-styles.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/components/iframe/get-compatibility-styles.js b/packages/block-editor/src/components/iframe/get-compatibility-styles.js index 0eae82b11e01f8..fd14e02a219bf6 100644 --- a/packages/block-editor/src/components/iframe/get-compatibility-styles.js +++ b/packages/block-editor/src/components/iframe/get-compatibility-styles.js @@ -37,15 +37,10 @@ export function getCompatibilityStyles() { return accumulator; } - // Don't try to add the reset styles, which were removed as a dependency - // from `edit-blocks` for the iframe since we don't need to reset admin - // styles. - if ( - [ - 'wp-reset-editor-styles-css', - 'wp-reset-editor-styles-rtl-css', - ].includes( ownerNode.id ) - ) { + // Don't try to add core WP styles. We are responsible for adding + // them. This compatibility layer is only meant to add styles added + // by plugins or themes. + if ( ownerNode.id.startsWith( 'wp-' ) ) { return accumulator; } From 7725c949e988b0b917175a13f0f6270112596ad3 Mon Sep 17 00:00:00 2001 From: Vrishabh Jasani <71686151+Vrishabhsk@users.noreply.github.com> Date: Thu, 31 Oct 2024 13:36:29 +0400 Subject: [PATCH 1427/1908] Fix : Snackbar Notice Inconsistency (#66405) Co-authored-by: Vrishabhsk <vrishabhsk@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../data/data-core-edit-post.md | 4 + .../reference-guides/data/data-core-editor.md | 13 ++ .../block-library/src/comments/block.json | 12 +- .../components/keyboard-shortcuts/index.js | 4 +- .../src/components/more-menu/index.js | 6 +- packages/edit-post/src/store/actions.js | 43 ++++++ .../editor/src/components/commands/index.js | 43 +----- .../editor/src/components/more-menu/index.js | 19 ++- packages/editor/src/store/actions.js | 143 ++++++++++++++---- 9 files changed, 194 insertions(+), 93 deletions(-) diff --git a/docs/reference-guides/data/data-core-edit-post.md b/docs/reference-guides/data/data-core-edit-post.md index e3fb22a1a7afe0..06fe5fc30420ae 100644 --- a/docs/reference-guides/data/data-core-edit-post.md +++ b/docs/reference-guides/data/data-core-edit-post.md @@ -528,6 +528,10 @@ _Parameters_ - _feature_ `string`: Feature name. +### toggleFullscreenMode + +Action that toggles the Fullscreen Mode view option. + ### togglePinnedPluginItem Triggers an action object used to toggle a plugin name flag. diff --git a/docs/reference-guides/data/data-core-editor.md b/docs/reference-guides/data/data-core-editor.md index ac3413e694877b..713a247d88be29 100644 --- a/docs/reference-guides/data/data-core-editor.md +++ b/docs/reference-guides/data/data-core-editor.md @@ -1585,6 +1585,11 @@ _Related_ Action that toggles Distraction free mode. Distraction free mode expects there are no sidebars, as due to the z-index values set, you can't close sidebars. +_Parameters_ + +- _options_ `[Object]`: Optional configuration object +- _options.createNotice_ `[boolean]`: Whether to create a notice + ### toggleEditorPanelEnabled Returns an action object used to enable or disable a panel in the editor. @@ -1619,6 +1624,14 @@ _Related_ - toggleSelection in core/block-editor store. +### toggleSpotlightMode + +Action that toggles the Spotlight Mode view option. + +### toggleTopToolbar + +Action that toggles the Top Toolbar view option. + ### trashPost Action for trashing the current post in the editor. diff --git a/packages/block-library/src/comments/block.json b/packages/block-library/src/comments/block.json index cbdf5b3725b84b..ceb8f750c3472d 100644 --- a/packages/block-library/src/comments/block.json +++ b/packages/block-library/src/comments/block.json @@ -17,10 +17,7 @@ } }, "supports": { - "align": [ - "wide", - "full" - ], + "align": [ "wide", "full" ], "html": false, "color": { "gradients": true, @@ -63,8 +60,5 @@ } }, "editorStyle": "wp-block-comments-editor", - "usesContext": [ - "postId", - "postType" - ] -} \ No newline at end of file + "usesContext": [ "postId", "postType" ] +} diff --git a/packages/edit-post/src/components/keyboard-shortcuts/index.js b/packages/edit-post/src/components/keyboard-shortcuts/index.js index 3d1bc9d3350da3..8567b541d03ab6 100644 --- a/packages/edit-post/src/components/keyboard-shortcuts/index.js +++ b/packages/edit-post/src/components/keyboard-shortcuts/index.js @@ -15,7 +15,7 @@ import { __ } from '@wordpress/i18n'; import { store as editPostStore } from '../../store'; function KeyboardShortcuts() { - const { toggleFeature } = useDispatch( editPostStore ); + const { toggleFullscreenMode } = useDispatch( editPostStore ); const { registerShortcut } = useDispatch( keyboardShortcutsStore ); useEffect( () => { @@ -31,7 +31,7 @@ function KeyboardShortcuts() { }, [] ); useShortcut( 'core/edit-post/toggle-fullscreen', () => { - toggleFeature( 'fullscreenMode' ); + toggleFullscreenMode(); } ); return null; diff --git a/packages/edit-post/src/components/more-menu/index.js b/packages/edit-post/src/components/more-menu/index.js index 136742a19dddd4..026354e6813494 100644 --- a/packages/edit-post/src/components/more-menu/index.js +++ b/packages/edit-post/src/components/more-menu/index.js @@ -4,8 +4,8 @@ import { __ } from '@wordpress/i18n'; import { useViewportMatch } from '@wordpress/compose'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; -import { PreferenceToggleMenuItem } from '@wordpress/preferences'; import { displayShortcut } from '@wordpress/keycodes'; +import { PreferenceToggleMenuItem } from '@wordpress/preferences'; /** * Internal dependencies @@ -29,9 +29,9 @@ const MoreMenu = () => { name="fullscreenMode" label={ __( 'Fullscreen mode' ) } info={ __( 'Show and hide the admin user interface' ) } - messageActivated={ __( 'Fullscreen mode activated' ) } + messageActivated={ __( 'Fullscreen mode activated.' ) } messageDeactivated={ __( - 'Fullscreen mode deactivated' + 'Fullscreen mode deactivated.' ) } shortcut={ displayShortcut.secondary( 'f' ) } /> diff --git a/packages/edit-post/src/store/actions.js b/packages/edit-post/src/store/actions.js index 7ab0a965379be2..85702ae1622851 100644 --- a/packages/edit-post/src/store/actions.js +++ b/packages/edit-post/src/store/actions.js @@ -10,6 +10,8 @@ import { import deprecated from '@wordpress/deprecated'; import { addAction } from '@wordpress/hooks'; import { store as coreStore } from '@wordpress/core-data'; +import { store as noticesStore } from '@wordpress/notices'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -509,3 +511,44 @@ export const toggleDistractionFree = } ); registry.dispatch( editorStore ).toggleDistractionFree(); }; + +/** + * Action that toggles the Fullscreen Mode view option. + */ +export const toggleFullscreenMode = + () => + ( { registry } ) => { + const isFullscreen = registry + .select( preferencesStore ) + .get( 'core/edit-post', 'fullscreenMode' ); + + registry + .dispatch( preferencesStore ) + .toggle( 'core/edit-post', 'fullscreenMode' ); + + registry + .dispatch( noticesStore ) + .createInfoNotice( + isFullscreen + ? __( 'Fullscreen mode activated.' ) + : __( 'Fullscreen mode deactivated.' ), + { + id: 'core/edit-post/toggle-fullscreen-mode/notice', + type: 'snackbar', + actions: [ + { + label: __( 'Undo' ), + + onClick: () => { + registry + .dispatch( preferencesStore ) + .toggle( + 'core/edit-post', + 'fullscreenMode' + ); + }, + }, + ], + } + ); + }; diff --git a/packages/editor/src/components/commands/index.js b/packages/editor/src/components/commands/index.js index 8eb88567bd0a3f..b4b9c05db256d7 100644 --- a/packages/editor/src/components/commands/index.js +++ b/packages/editor/src/components/commands/index.js @@ -36,7 +36,6 @@ function useEditorCommandLoader() { isListViewOpen, showBlockBreadcrumbs, isDistractionFree, - isTopToolbar, isFocusMode, isPreviewMode, isViewable, @@ -56,7 +55,6 @@ function useEditorCommandLoader() { showBlockBreadcrumbs: get( 'core', 'showBlockBreadcrumbs' ), isDistractionFree: get( 'core', 'distractionFree' ), isFocusMode: get( 'core', 'focusMode' ), - isTopToolbar: get( 'core', 'fixedToolbar' ), isPreviewMode: getSettings().isPreviewMode, isViewable: getPostType( getCurrentPostType() )?.viewable ?? false, isCodeEditingEnabled: getEditorSettings().codeEditingEnabled, @@ -73,6 +71,8 @@ function useEditorCommandLoader() { setIsListViewOpened, switchEditorMode, toggleDistractionFree, + toggleSpotlightMode, + toggleTopToolbar, } = useDispatch( editorStore ); const { openModal, enableComplementaryArea, disableComplementaryArea } = useDispatch( interfaceStore ); @@ -121,23 +121,8 @@ function useEditorCommandLoader() { ? __( 'Exit Spotlight mode' ) : __( 'Enter Spotlight mode' ), callback: ( { close } ) => { - toggle( 'core', 'focusMode' ); + toggleSpotlightMode(); close(); - createInfoNotice( - isFocusMode ? __( 'Spotlight off.' ) : __( 'Spotlight on.' ), - { - id: 'core/editor/toggle-spotlight-mode/notice', - type: 'snackbar', - actions: [ - { - label: __( 'Undo' ), - onClick: () => { - toggle( 'core', 'focusMode' ); - }, - }, - ], - } - ); }, } ); @@ -164,28 +149,8 @@ function useEditorCommandLoader() { name: 'core/toggle-top-toolbar', label: __( 'Top toolbar' ), callback: ( { close } ) => { - toggle( 'core', 'fixedToolbar' ); - if ( isDistractionFree ) { - toggleDistractionFree(); - } + toggleTopToolbar(); close(); - createInfoNotice( - isTopToolbar - ? __( 'Top toolbar off.' ) - : __( 'Top toolbar on.' ), - { - id: 'core/editor/toggle-top-toolbar/notice', - type: 'snackbar', - actions: [ - { - label: __( 'Undo' ), - onClick: () => { - toggle( 'core', 'fixedToolbar' ); - }, - }, - ], - } - ); }, } ); diff --git a/packages/editor/src/components/more-menu/index.js b/packages/editor/src/components/more-menu/index.js index 6ccc01c6ac049c..9e062e5e5adc50 100644 --- a/packages/editor/src/components/more-menu/index.js +++ b/packages/editor/src/components/more-menu/index.js @@ -35,6 +35,7 @@ export default function MoreMenu() { select( preferencesStore ).get( 'core', 'showIconLabels' ), [] ); + const turnOffDistractionFree = () => { setPreference( 'core', 'distractionFree', false ); }; @@ -67,10 +68,10 @@ export default function MoreMenu() { 'Access all block and document tools in a single place' ) } messageActivated={ __( - 'Top toolbar activated' + 'Top toolbar activated.' ) } messageDeactivated={ __( - 'Top toolbar deactivated' + 'Top toolbar deactivated.' ) } /> <PreferenceToggleMenuItem @@ -79,12 +80,16 @@ export default function MoreMenu() { label={ __( 'Distraction free' ) } info={ __( 'Write with calmness' ) } handleToggling={ false } - onToggle={ toggleDistractionFree } + onToggle={ () => + toggleDistractionFree( { + createNotice: false, + } ) + } messageActivated={ __( - 'Distraction free mode activated' + 'Distraction free mode activated.' ) } messageDeactivated={ __( - 'Distraction free mode deactivated' + 'Distraction free mode deactivated.' ) } shortcut={ displayShortcut.primaryShift( '\\' @@ -96,10 +101,10 @@ export default function MoreMenu() { label={ __( 'Spotlight mode' ) } info={ __( 'Focus on one block at a time' ) } messageActivated={ __( - 'Spotlight mode activated' + 'Spotlight mode activated.' ) } messageDeactivated={ __( - 'Spotlight mode deactivated' + 'Spotlight mode deactivated.' ) } /> <ViewMoreMenuGroup.Slot fillProps={ { onClose } } /> diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index cc2c23bcffcf7e..7ff23cb49f4983 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -812,9 +812,12 @@ export function setIsListViewOpened( isOpen ) { * Action that toggles Distraction free mode. * Distraction free mode expects there are no sidebars, as due to the * z-index values set, you can't close sidebars. + * + * @param {Object} [options={}] Optional configuration object + * @param {boolean} [options.createNotice=true] Whether to create a notice */ export const toggleDistractionFree = - () => + ( { createNotice = true } = {} ) => ( { dispatch, registry } ) => { const isDistractionFree = registry .select( preferencesStore ) @@ -837,42 +840,116 @@ export const toggleDistractionFree = registry .dispatch( preferencesStore ) .set( 'core', 'distractionFree', ! isDistractionFree ); - registry - .dispatch( noticesStore ) - .createInfoNotice( - isDistractionFree - ? __( 'Distraction free mode deactivated.' ) - : __( 'Distraction free mode activated.' ), - { - id: 'core/editor/distraction-free-mode/notice', - type: 'snackbar', - actions: [ - { - label: __( 'Undo' ), - onClick: () => { - registry.batch( () => { - registry - .dispatch( preferencesStore ) - .set( - 'core', - 'fixedToolbar', - isDistractionFree ? true : false - ); - registry - .dispatch( preferencesStore ) - .toggle( - 'core', - 'distractionFree' - ); - } ); + + if ( createNotice ) { + registry + .dispatch( noticesStore ) + .createInfoNotice( + isDistractionFree + ? __( 'Distraction free mode deactivated.' ) + : __( 'Distraction free mode activated.' ), + { + id: 'core/editor/distraction-free-mode/notice', + type: 'snackbar', + actions: [ + { + label: __( 'Undo' ), + onClick: () => { + registry.batch( () => { + registry + .dispatch( preferencesStore ) + .set( + 'core', + 'fixedToolbar', + isDistractionFree + ); + registry + .dispatch( preferencesStore ) + .toggle( + 'core', + 'distractionFree' + ); + } ); + }, }, - }, - ], - } - ); + ], + } + ); + } } ); }; +/** + * Action that toggles the Spotlight Mode view option. + */ +export const toggleSpotlightMode = + () => + ( { registry } ) => { + registry.dispatch( preferencesStore ).toggle( 'core', 'focusMode' ); + + const isFocusMode = registry + .select( preferencesStore ) + .get( 'core', 'focusMode' ); + + registry + .dispatch( noticesStore ) + .createInfoNotice( + isFocusMode + ? __( 'Spotlight mode activated.' ) + : __( 'Spotlight mode deactivated.' ), + { + id: 'core/editor/toggle-spotlight-mode/notice', + type: 'snackbar', + actions: [ + { + label: __( 'Undo' ), + onClick: () => { + registry + .dispatch( preferencesStore ) + .toggle( 'core', 'focusMode' ); + }, + }, + ], + } + ); + }; + +/** + * Action that toggles the Top Toolbar view option. + */ +export const toggleTopToolbar = + () => + ( { registry } ) => { + registry.dispatch( preferencesStore ).toggle( 'core', 'fixedToolbar' ); + + const isTopToolbar = registry + .select( preferencesStore ) + .get( 'core', 'fixedToolbar' ); + + registry + .dispatch( noticesStore ) + .createInfoNotice( + isTopToolbar + ? __( 'Top toolbar activated.' ) + : __( 'Top toolbar deactivated.' ), + { + id: 'core/editor/toggle-top-toolbar/notice', + type: 'snackbar', + actions: [ + { + label: __( 'Undo' ), + + onClick: () => { + registry + .dispatch( preferencesStore ) + .toggle( 'core', 'fixedToolbar' ); + }, + }, + ], + } + ); + }; + /** * Triggers an action used to switch editor mode. * From 3ed56acb9472eebc82d2ebad2d9b9e291f577298 Mon Sep 17 00:00:00 2001 From: Sarah Norris <1645628+mikachan@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:41:33 +0000 Subject: [PATCH 1428/1908] Query Loop: Use templateSlug and postType for more context (#65820) * Use templateSlug for additional context in the editor * Rename isTemplate to isSingularTemplate * Move singular logic to getQueryContext utils function * Simplify function by removing postType logic * Get postType from context * Fix for Post Editor --------- Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- .../src/post-template/block.json | 3 +- .../block-library/src/post-template/edit.js | 6 +- packages/block-library/src/query/block.json | 2 +- .../query/edit/inspector-controls/index.js | 22 ++++++- .../src/query/edit/query-content.js | 27 ++++----- .../block-library/src/query/test/utils.js | 60 ++++++++++++++++++- packages/block-library/src/query/utils.js | 29 +++++++++ 7 files changed, 125 insertions(+), 24 deletions(-) diff --git a/packages/block-library/src/post-template/block.json b/packages/block-library/src/post-template/block.json index 6a575855583527..da576a83312a45 100644 --- a/packages/block-library/src/post-template/block.json +++ b/packages/block-library/src/post-template/block.json @@ -13,7 +13,8 @@ "displayLayout", "templateSlug", "previewPostType", - "enhancedPagination" + "enhancedPagination", + "postType" ], "supports": { "reusable": false, diff --git a/packages/block-library/src/post-template/edit.js b/packages/block-library/src/post-template/edit.js index a9e279ee2c3052..4e7e514ed82b12 100644 --- a/packages/block-library/src/post-template/edit.js +++ b/packages/block-library/src/post-template/edit.js @@ -100,6 +100,7 @@ export default function PostTemplateEdit( { } = {}, templateSlug, previewPostType, + postType: postTypeFromContext, }, attributes: { layout }, __unstableLayoutClassNames, @@ -186,7 +187,10 @@ export default function PostTemplateEdit( { } // When we preview Query Loop blocks we should prefer the current // block's postType, which is passed through block context. - const usedPostType = previewPostType || postType; + const usedPostType = + postTypeFromContext !== 'page' + ? postTypeFromContext + : previewPostType || postType; return { posts: getEntityRecords( 'postType', usedPostType, { ...query, diff --git a/packages/block-library/src/query/block.json b/packages/block-library/src/query/block.json index b2225192c6b218..2379a1d1da53cf 100644 --- a/packages/block-library/src/query/block.json +++ b/packages/block-library/src/query/block.json @@ -42,7 +42,7 @@ "default": false } }, - "usesContext": [ "postType" ], + "usesContext": [ "postType", "templateSlug" ], "providesContext": { "queryId": "queryId", "query": "query", diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index 06105bef4e0269..bc900c073f648d 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -45,9 +45,15 @@ import { useToolsPanelDropdownMenuProps } from '../../../utils/hooks'; const { BlockInfo } = unlock( blockEditorPrivateApis ); export default function QueryInspectorControls( props ) { - const { attributes, setQuery, setDisplayLayout, isTemplate } = props; - const { query, displayLayout } = attributes; const { + attributes, + setQuery, + setDisplayLayout, + postTypeFromContext, + isSingular, + } = props; + const { query, displayLayout } = attributes; + let { order, orderBy, author: authorIds, @@ -61,6 +67,16 @@ export default function QueryInspectorControls( props ) { parents, format, } = query; + // If a post type is set in context, update `postType` to match it, + // unless the post type is `page`, as it usually doesn't make sense to loop + // through pages. + if ( + postTypeFromContext && + postTypeFromContext !== 'page' && + postTypeFromContext !== postType + ) { + postType = postTypeFromContext; + } const allowedControls = useAllowedControls( attributes ); const showSticky = postType === 'post'; const { @@ -118,7 +134,7 @@ export default function QueryInspectorControls( props ) { }, [ querySearch, onChangeDebounced ] ); const showInheritControl = - isTemplate && isControlAllowed( allowedControls, 'inherit' ); + ! isSingular && isControlAllowed( allowedControls, 'inherit' ); const showPostTypeControl = ! inherit && isControlAllowed( allowedControls, 'postType' ); const postTypeControlLabel = __( 'Post type' ); diff --git a/packages/block-library/src/query/edit/query-content.js b/packages/block-library/src/query/edit/query-content.js index 8b3ff09b17934b..bdfcbe0498ec4a 100644 --- a/packages/block-library/src/query/edit/query-content.js +++ b/packages/block-library/src/query/edit/query-content.js @@ -22,6 +22,7 @@ import EnhancedPaginationControl from './inspector-controls/enhanced-pagination- import QueryToolbar from './query-toolbar'; import QueryInspectorControls from './inspector-controls'; import EnhancedPaginationModal from './enhanced-pagination-modal'; +import { getQueryContextFromTemplate } from '../utils'; const DEFAULTS_POSTS_PER_PAGE = 3; @@ -42,7 +43,8 @@ export default function QueryContent( { tagName: TagName = 'div', query: { inherit } = {}, } = attributes; - const { postType } = context; + const { templateSlug, postType } = context; + const { isSingular } = getQueryContextFromTemplate( templateSlug ); const { __unstableMarkNextChangeAsNotPersistent } = useDispatch( blockEditorStore ); const instanceId = useInstanceId( QueryContent ); @@ -50,16 +52,6 @@ export default function QueryContent( { const innerBlocksProps = useInnerBlocksProps( blockProps, { template: TEMPLATE, } ); - const isTemplate = useSelect( - ( select ) => { - const currentTemplate = - select( coreStore ).__experimentalGetTemplateForLink()?.type; - const isInTemplate = 'wp_template' === currentTemplate; - const isInSingularContent = postType !== undefined; - return isInTemplate && ! isInSingularContent; - }, - [ postType ] - ); const { postsPerPage } = useSelect( ( select ) => { const { getSettings } = select( blockEditorStore ); const { getEntityRecord, getEntityRecordEdits, canUser } = @@ -106,9 +98,9 @@ export default function QueryContent( { } else if ( ! query.perPage && postsPerPage ) { newQuery.perPage = postsPerPage; } - // We need to reset the `inherit` value if not in a template, as queries - // are not inherited when outside a template (e.g. when in singular content). - if ( ! isTemplate && query.inherit ) { + // We need to reset the `inherit` value if in a singular template, as queries + // are not inherited when in singular content (e.g. post, page, 404, blank). + if ( isSingular && query.inherit ) { newQuery.inherit = false; } if ( !! Object.keys( newQuery ).length ) { @@ -117,10 +109,10 @@ export default function QueryContent( { } }, [ query.perPage, + query.inherit, postsPerPage, inherit, - isTemplate, - query.inherit, + isSingular, __unstableMarkNextChangeAsNotPersistent, updateQuery, ] ); @@ -167,7 +159,8 @@ export default function QueryContent( { setDisplayLayout={ updateDisplayLayout } setAttributes={ setAttributes } clientId={ clientId } - isTemplate={ isTemplate } + postTypeFromContext={ postType } + isSingular={ isSingular } /> </InspectorControls> <BlockControls> diff --git a/packages/block-library/src/query/test/utils.js b/packages/block-library/src/query/test/utils.js index 1b711850086774..8c2d88ade80518 100644 --- a/packages/block-library/src/query/test/utils.js +++ b/packages/block-library/src/query/test/utils.js @@ -2,7 +2,11 @@ * Internal dependencies */ import { terms } from './fixtures'; -import { getEntitiesInfo, getValueFromObjectPath } from '../utils'; +import { + getEntitiesInfo, + getValueFromObjectPath, + getQueryContextFromTemplate, +} from '../utils'; describe( 'Query block utils', () => { describe( 'getEntitiesInfo', () => { @@ -61,4 +65,58 @@ describe( 'Query block utils', () => { expect( result ).toBe( 'test' ); } ); } ); + + describe( 'getQueryContextFromTemplate', () => { + it( 'should return the correct query context based on template slug', () => { + expect( getQueryContextFromTemplate() ).toStrictEqual( { + isSingular: true, + } ); + expect( getQueryContextFromTemplate( '404' ) ).toStrictEqual( { + isSingular: true, + templateType: '404', + } ); + expect( getQueryContextFromTemplate( 'blank' ) ).toStrictEqual( { + isSingular: true, + templateType: 'blank', + } ); + expect( getQueryContextFromTemplate( 'single' ) ).toStrictEqual( { + isSingular: true, + templateType: 'single', + } ); + expect( + getQueryContextFromTemplate( 'single-film' ) + ).toStrictEqual( { + isSingular: true, + templateType: 'single', + } ); + expect( getQueryContextFromTemplate( 'page' ) ).toStrictEqual( { + isSingular: true, + templateType: 'page', + } ); + expect( getQueryContextFromTemplate( 'wp' ) ).toStrictEqual( { + isSingular: true, + templateType: 'custom', + } ); + expect( getQueryContextFromTemplate( 'category' ) ).toStrictEqual( { + isSingular: false, + templateType: 'category', + } ); + expect( + getQueryContextFromTemplate( 'category-dog' ) + ).toStrictEqual( { + isSingular: false, + templateType: 'category', + } ); + expect( getQueryContextFromTemplate( 'archive' ) ).toStrictEqual( { + isSingular: false, + templateType: 'archive', + } ); + expect( + getQueryContextFromTemplate( 'archive-film' ) + ).toStrictEqual( { + isSingular: false, + templateType: 'archive', + } ); + } ); + } ); } ); diff --git a/packages/block-library/src/query/utils.js b/packages/block-library/src/query/utils.js index 68da2573bab0f6..fc22ca46d471c0 100644 --- a/packages/block-library/src/query/utils.js +++ b/packages/block-library/src/query/utils.js @@ -435,3 +435,32 @@ export const useUnsupportedBlocks = ( clientId ) => { [ clientId ] ); }; + +/** + * Helper function that returns the query context from the editor based on the + * available template slug. + * + * @param {string} templateSlug Current template slug based on context. + * @return {Object} An object with isSingular and templateType properties. + */ +export function getQueryContextFromTemplate( templateSlug ) { + // In the Post Editor, the template slug is not available. + if ( ! templateSlug ) { + return { isSingular: true }; + } + let isSingular = false; + let templateType = templateSlug === 'wp' ? 'custom' : templateSlug; + const singularTemplates = [ '404', 'blank', 'single', 'page', 'custom' ]; + const templateTypeFromSlug = templateSlug.includes( '-' ) + ? templateSlug.split( '-', 1 )[ 0 ] + : templateSlug; + const queryFromTemplateSlug = templateSlug.includes( '-' ) + ? templateSlug.split( '-' ).slice( 1 ).join( '-' ) + : ''; + if ( queryFromTemplateSlug ) { + templateType = templateTypeFromSlug; + } + isSingular = singularTemplates.includes( templateType ); + + return { isSingular, templateType }; +} From fc2bf3a0c5369d5ee4f94ee73aed1feb32c357ad Mon Sep 17 00:00:00 2001 From: louwie17 <lourensschep@gmail.com> Date: Thu, 31 Oct 2024 07:50:06 -0300 Subject: [PATCH 1429/1908] QuickEdit: Add password field to the pages quick edit (#66567) Co-authored-by: louwie17 <louwie17@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- .../dataform-combined-edit/style.scss | 4 ++ .../src/components/post-edit/index.js | 68 +++++++++++-------- .../src/components/post-edit/style.scss | 7 ++ .../src/components/post-fields/index.js | 8 ++- packages/fields/README.md | 4 ++ packages/fields/src/fields/index.ts | 1 + packages/fields/src/fields/password/edit.tsx | 68 +++++++++++++++++++ packages/fields/src/fields/password/index.tsx | 25 +++++++ 8 files changed, 154 insertions(+), 31 deletions(-) create mode 100644 packages/fields/src/fields/password/edit.tsx create mode 100644 packages/fields/src/fields/password/index.tsx diff --git a/packages/dataviews/src/components/dataform-combined-edit/style.scss b/packages/dataviews/src/components/dataform-combined-edit/style.scss index 0b59cbc9a47768..97e052ed897989 100644 --- a/packages/dataviews/src/components/dataform-combined-edit/style.scss +++ b/packages/dataviews/src/components/dataform-combined-edit/style.scss @@ -9,4 +9,8 @@ &__field { flex: 1 1 auto; } + + p.components-base-control__help:has(.components-checkbox-control__help) { + margin-top: $grid-unit-05; + } } diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index a2b3007757e42b..fbff29ed67afa1 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -23,6 +23,14 @@ import { unlock } from '../../lock-unlock'; const { PostCardPanel } = unlock( editorPrivateApis ); +const fieldsWithBulkEditSupport = [ + 'title', + 'status', + 'date', + 'author', + 'comment_status', +]; + function PostEditForm( { postType, postId } ) { const ids = useMemo( () => postId.split( ',' ), [ postId ] ); const { record } = useSelect( @@ -58,27 +66,36 @@ function PostEditForm( { postType, postId } ) { } ), [ _fields ] ); - const form = { - type: 'panel', - fields: [ - 'featured_media', - 'title', - 'author', - 'date', - 'slug', - 'parent', - 'comment_status', - ], - }; - - const fieldsWithBulkEditSupport = [ - 'title', - 'status', - 'date', - 'author', - 'comment_status', - ]; + const form = useMemo( + () => ( { + type: 'panel', + fields: [ + 'featured_media', + 'title', + 'status_and_visibility', + 'author', + 'date', + 'slug', + 'parent', + 'comment_status', + ].filter( + ( field ) => + ids.length === 1 || + fieldsWithBulkEditSupport.includes( field ) + ), + combinedFields: [ + { + id: 'status_and_visibility', + label: __( 'Status & Visibility' ), + children: [ 'status', 'password' ], + direction: 'vertical', + render: ( { item } ) => item.status, + }, + ], + } ), + [ ids ] + ); const onChange = ( edits ) => { for ( const id of ids ) { if ( @@ -117,16 +134,7 @@ function PostEditForm( { postType, postId } ) { <DataForm data={ ids.length === 1 ? record : multiEdits } fields={ fields } - form={ - ids.length === 1 - ? form - : { - ...form, - fields: form.fields.filter( ( field ) => - fieldsWithBulkEditSupport.includes( field ) - ), - } - } + form={ form } onChange={ onChange } /> </VStack> diff --git a/packages/edit-site/src/components/post-edit/style.scss b/packages/edit-site/src/components/post-edit/style.scss index 4eaa41b2e8ed70..5688d83df00c5f 100644 --- a/packages/edit-site/src/components/post-edit/style.scss +++ b/packages/edit-site/src/components/post-edit/style.scss @@ -7,3 +7,10 @@ justify-content: center; } } + +.dataforms-layouts-panel__field-dropdown { + .fields-controls__password { + border-top: $border-width solid $gray-200; + padding-top: $grid-unit-20; + } +} diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 7a52b05321794b..e659a4f96f23f6 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -8,7 +8,12 @@ import clsx from 'clsx'; */ import { __, sprintf } from '@wordpress/i18n'; import { decodeEntities } from '@wordpress/html-entities'; -import { featuredImageField, slugField, parentField } from '@wordpress/fields'; +import { + featuredImageField, + slugField, + parentField, + passwordField, +} from '@wordpress/fields'; import { createInterpolateElement, useMemo, @@ -348,6 +353,7 @@ function usePostFields( viewType ) { }, ], }, + passwordField, ], [ authors, viewType, frontPageId, postsPageId ] ); diff --git a/packages/fields/README.md b/packages/fields/README.md index 5fd1031b50fe23..214f3d6ee3a50a 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -50,6 +50,10 @@ Undocumented declaration. This field is used to display the post parent. +### passwordField + +This field is used to display the post password. + ### permanentlyDeletePost Undocumented declaration. diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts index 9f1abef0417f42..29cbdeb2a4ba6b 100644 --- a/packages/fields/src/fields/index.ts +++ b/packages/fields/src/fields/index.ts @@ -3,3 +3,4 @@ export { default as titleField } from './title'; export { default as orderField } from './order'; export { default as featuredImageField } from './featured-image'; export { default as parentField } from './parent'; +export { default as passwordField } from './password'; diff --git a/packages/fields/src/fields/password/edit.tsx b/packages/fields/src/fields/password/edit.tsx new file mode 100644 index 00000000000000..75226c1f93f15b --- /dev/null +++ b/packages/fields/src/fields/password/edit.tsx @@ -0,0 +1,68 @@ +/** + * WordPress dependencies + */ +import { + CheckboxControl, + __experimentalVStack as VStack, + TextControl, +} from '@wordpress/components'; +import type { DataFormControlProps } from '@wordpress/dataviews'; +import { useState } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; + +function PasswordEdit( { + data, + onChange, + field, +}: DataFormControlProps< BasePost > ) { + const [ showPassword, setShowPassword ] = useState( + !! field.getValue( { item: data } ) + ); + + const handleTogglePassword = ( value: boolean ) => { + setShowPassword( value ); + if ( ! value ) { + onChange( { password: '' } ); + } + }; + + return ( + <VStack + as="fieldset" + spacing={ 4 } + className="fields-controls__password" + > + <CheckboxControl + __nextHasNoMarginBottom + label={ __( 'Password protected' ) } + help={ __( 'Only visible to those who know the password' ) } + checked={ showPassword } + onChange={ handleTogglePassword } + /> + { showPassword && ( + <div className="fields-controls__password-input"> + <TextControl + label={ __( 'Password' ) } + onChange={ ( value ) => + onChange( { + password: value, + } ) + } + value={ field.getValue( { item: data } ) || '' } + placeholder={ __( 'Use a secure password' ) } + type="text" + __next40pxDefaultSize + __nextHasNoMarginBottom + maxLength={ 255 } + /> + </div> + ) } + </VStack> + ); +} +export default PasswordEdit; diff --git a/packages/fields/src/fields/password/index.tsx b/packages/fields/src/fields/password/index.tsx new file mode 100644 index 00000000000000..aa7bc57e3f7cae --- /dev/null +++ b/packages/fields/src/fields/password/index.tsx @@ -0,0 +1,25 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import PasswordEdit from './edit'; + +const passwordField: Field< BasePost > = { + id: 'password', + type: 'text', + getValue: ( { item } ) => item.password, + Edit: PasswordEdit, + enableSorting: false, + enableHiding: false, + isVisible: ( item ) => item.status !== 'private', +}; + +/** + * This field is used to display the post password. + */ +export default passwordField; From f73888a5be8f7c042f49a9080cb853f5c13a0630 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 31 Oct 2024 23:23:53 +0900 Subject: [PATCH 1430/1908] Radio: Deprecate 36px default size (#66572) * Radio: Deprecate 36px default size * Add changelog * Fix changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/radio-group/README.md | 16 +++++++-------- packages/components/src/radio-group/radio.tsx | 7 +++++++ .../src/radio-group/stories/index.story.tsx | 20 +++++++++++++++---- packages/components/src/radio-group/types.ts | 7 ++++++- .../src/utils/deprecated-36px-size.ts | 7 +++++-- .../create-template-part-modal/index.js | 1 + 7 files changed, 47 insertions(+), 15 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 5fd48336f956c1..4b0da1d669ece2 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Deprecations + +- `Radio`: Deprecate 36px default size ([#66572](https://github.com/WordPress/gutenberg/pull/66572)). + ### Enhancements - `MenuItem`: Add 40px size prop on Button ([#66596](https://github.com/WordPress/gutenberg/pull/66596)). diff --git a/packages/components/src/radio-group/README.md b/packages/components/src/radio-group/README.md index 1c24d49f1169d5..78cff485597279 100644 --- a/packages/components/src/radio-group/README.md +++ b/packages/components/src/radio-group/README.md @@ -57,10 +57,10 @@ const MyControlledRadioRadioGroup = () => { const [ checked, setChecked ] = useState( '25' ); return ( <RadioGroup label="Width" onChange={ setChecked } checked={ checked }> - <Radio value="25">25%</Radio> - <Radio value="50">50%</Radio> - <Radio value="75">75%</Radio> - <Radio value="100">100%</Radio> + <Radio __next40pxDefaultSize value="25">25%</Radio> + <Radio __next40pxDefaultSize value="50">50%</Radio> + <Radio __next40pxDefaultSize value="75">75%</Radio> + <Radio __next40pxDefaultSize value="100">100%</Radio> </RadioGroup> ); }; @@ -80,10 +80,10 @@ import { const MyUncontrolledRadioRadioGroup = () => { return ( <RadioGroup label="Width" defaultChecked="25"> - <Radio value="25">25%</Radio> - <Radio value="50">50%</Radio> - <Radio value="75">75%</Radio> - <Radio value="100">100%</Radio> + <Radio __next40pxDefaultSize value="25">25%</Radio> + <Radio __next40pxDefaultSize value="50">50%</Radio> + <Radio __next40pxDefaultSize value="75">75%</Radio> + <Radio __next40pxDefaultSize value="100">100%</Radio> </RadioGroup> ); }; diff --git a/packages/components/src/radio-group/radio.tsx b/packages/components/src/radio-group/radio.tsx index 50a5a2647b39d5..782a737b6ba28a 100644 --- a/packages/components/src/radio-group/radio.tsx +++ b/packages/components/src/radio-group/radio.tsx @@ -16,6 +16,7 @@ import Button from '../button'; import { RadioGroupContext } from './context'; import type { WordPressComponentProps } from '../context'; import type { RadioProps } from './types'; +import { maybeWarnDeprecated36pxSize } from '../utils/deprecated-36px-size'; function UnforwardedRadio( { @@ -30,6 +31,12 @@ function UnforwardedRadio( const selectedValue = useStoreState( store, 'value' ); const isChecked = selectedValue !== undefined && selectedValue === value; + maybeWarnDeprecated36pxSize( { + componentName: 'Radio', + size: undefined, + __next40pxDefaultSize: props.__next40pxDefaultSize, + } ); + return ( <Ariakit.Radio disabled={ disabled } diff --git a/packages/components/src/radio-group/stories/index.story.tsx b/packages/components/src/radio-group/stories/index.story.tsx index d9cf34c93b2ed1..a19fb077e7ec46 100644 --- a/packages/components/src/radio-group/stories/index.story.tsx +++ b/packages/components/src/radio-group/stories/index.story.tsx @@ -28,7 +28,13 @@ const meta: Meta< typeof RadioGroup > = { parameters: { actions: { argTypesRegex: '^on.*' }, controls: { expanded: true }, - docs: { canvas: { sourceState: 'shown' } }, + docs: { + canvas: { sourceState: 'shown' }, + description: { + component: + 'This component is deprecated. Use `RadioControl` or `ToggleGroupControl` instead.', + }, + }, }, }; export default meta; @@ -44,9 +50,15 @@ Default.args = { defaultChecked: 'option2', children: ( <> - <Radio value="option1">Option 1</Radio> - <Radio value="option2">Option 2</Radio> - <Radio value="option3">Option 3</Radio> + <Radio __next40pxDefaultSize value="option1"> + Option 1 + </Radio> + <Radio __next40pxDefaultSize value="option2"> + Option 2 + </Radio> + <Radio __next40pxDefaultSize value="option3"> + Option 3 + </Radio> </> ), }; diff --git a/packages/components/src/radio-group/types.ts b/packages/components/src/radio-group/types.ts index 6422cf4b275f00..c72917a33faa4c 100644 --- a/packages/components/src/radio-group/types.ts +++ b/packages/components/src/radio-group/types.ts @@ -1,3 +1,8 @@ +/** + * Internal dependencies + */ +import type { ButtonProps } from '../button/types'; + export type RadioGroupProps = { /** * Accessible label for the radio group @@ -27,7 +32,7 @@ export type RadioGroupProps = { children: React.ReactNode; }; -export type RadioProps = { +export type RadioProps = Pick< ButtonProps, '__next40pxDefaultSize' > & { /** * The actual value of the radio element. */ diff --git a/packages/components/src/utils/deprecated-36px-size.ts b/packages/components/src/utils/deprecated-36px-size.ts index e28e9eebb31a99..be5baa2515637c 100644 --- a/packages/components/src/utils/deprecated-36px-size.ts +++ b/packages/components/src/utils/deprecated-36px-size.ts @@ -10,9 +10,12 @@ export function maybeWarnDeprecated36pxSize( { }: { componentName: string; __next40pxDefaultSize: boolean | undefined; - size: string; + size: string | undefined; } ) { - if ( __next40pxDefaultSize || size !== 'default' ) { + if ( + __next40pxDefaultSize || + ( size !== undefined && size !== 'default' ) + ) { return; } diff --git a/packages/editor/src/components/create-template-part-modal/index.js b/packages/editor/src/components/create-template-part-modal/index.js index 63e3830295c379..5d594cd646cc10 100644 --- a/packages/editor/src/components/create-template-part-modal/index.js +++ b/packages/editor/src/components/create-template-part-modal/index.js @@ -158,6 +158,7 @@ export function CreateTemplatePartModalContents( { { templatePartAreas.map( ( { icon, label, area: value, description } ) => ( <Radio + __next40pxDefaultSize key={ label } value={ value } className="editor-create-template-part-modal__area-radio" From d8cc9a894e1571c27ae3170bb2b38c02d223b005 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 31 Oct 2024 16:07:38 +0100 Subject: [PATCH 1431/1908] Appender: fix outside-canvas styles (#66630) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> --- .../src/components/block-tools/style.scss | 13 ++++++++++ .../default-block-appender/content.scss | 24 +++++++------------ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index 0791dc909d5be4..66a711454eb798 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -57,6 +57,19 @@ } } +// The black plus that shows up on the right side of an empty paragraph block, +// or the initial appender that exists only on empty documents. +.block-editor-block-list__empty-block-inserter.block-editor-block-list__empty-block-inserter { + position: absolute; + top: 0; + right: 0; + line-height: 0; + + &:disabled { + display: none; + } +} + // Sibling inserter / "inbetweenserter". .block-editor-block-list__empty-block-inserter, .block-editor-block-list__insertion-point-inserter { diff --git a/packages/block-editor/src/components/default-block-appender/content.scss b/packages/block-editor/src/components/default-block-appender/content.scss index 51e0b4381a15d5..3a1bf9889d7481 100644 --- a/packages/block-editor/src/components/default-block-appender/content.scss +++ b/packages/block-editor/src/components/default-block-appender/content.scss @@ -62,24 +62,12 @@ } } -// The black plus that shows up on the right side of an empty paragraph block, or the initial appender -// that exists only on empty documents. -.block-editor-block-list__empty-block-inserter.block-editor-block-list__empty-block-inserter, -.block-editor-default-block-appender .block-editor-inserter { - position: absolute; - top: 0; - right: 0; - line-height: 0; - - &:disabled { - display: none; - } -} - /** - * Fixed position appender. - * These styles apply to all in-canvas inserters that exist inside nesting containers. + * Fixed position appender (right bottom corner). + * + * These styles apply to all in-canvas inserters. All in-canvas inserters always + * exist within a block. */ .block-editor-block-list__block .block-list-appender { @@ -96,6 +84,10 @@ line-height: 0; } + .block-editor-inserter:disabled { + display: none; + } + .block-editor-default-block-appender { height: $button-size-small; } From 51fc0862ca804e7681d4b95fd9d5d58ab401ced1 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:28:07 +0100 Subject: [PATCH 1432/1908] Site Editor: speed up load by preloading home and front-page templates (#66579) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- lib/compat/wordpress-6.8/preload.php | 2 + packages/core-data/src/resolvers.js | 71 +++----------- packages/core-data/src/selectors.ts | 32 ------ .../use-init-edited-entity-from-url.js | 97 ++++++------------- 4 files changed, 49 insertions(+), 153 deletions(-) diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php index 0805ace4233d59..b9e03802a58e95 100644 --- a/lib/compat/wordpress-6.8/preload.php +++ b/lib/compat/wordpress-6.8/preload.php @@ -28,6 +28,8 @@ function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { 'url', ) ); + $paths[] = '/wp/v2/templates/lookup?slug=front-page'; + $paths[] = '/wp/v2/templates/lookup?slug=home'; } // Preload theme and global styles paths. diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index d3980b89e8fc5b..a3bbd37f2d7c20 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -563,58 +563,6 @@ export const getAutosave = await resolveSelect.getAutosaves( postType, postId ); }; -/** - * Retrieve the frontend template used for a given link. - * - * @param {string} link Link. - */ -export const __experimentalGetTemplateForLink = - ( link ) => - async ( { dispatch, resolveSelect } ) => { - let template; - try { - // This is NOT calling a REST endpoint but rather ends up with a response from - // an Ajax function which has a different shape from a WP_REST_Response. - template = await apiFetch( { - url: addQueryArgs( link, { - '_wp-find-template': true, - } ), - } ).then( ( { data } ) => data ); - } catch ( e ) { - // For non-FSE themes, it is possible that this request returns an error. - } - - if ( ! template ) { - return; - } - - const record = await resolveSelect.getEntityRecord( - 'postType', - 'wp_template', - template.id - ); - - if ( record ) { - dispatch.receiveEntityRecords( - 'postType', - 'wp_template', - [ record ], - { - 'find-template': link, - } - ); - } - }; - -__experimentalGetTemplateForLink.shouldInvalidate = ( action ) => { - return ( - ( action.type === 'RECEIVE_ITEMS' || action.type === 'REMOVE_ITEMS' ) && - action.invalidateCache && - action.kind === 'postType' && - action.name === 'wp_template' - ); -}; - export const __experimentalGetCurrentGlobalStylesId = () => async ( { dispatch, resolveSelect } ) => { @@ -801,13 +749,26 @@ export const getNavigationFallbackId = export const getDefaultTemplateId = ( query ) => - async ( { dispatch } ) => { - const template = await apiFetch( { + async ( { dispatch, registry } ) => { + const response = await apiFetch( { path: addQueryArgs( '/wp/v2/templates/lookup', query ), + parse: false, } ); + const template = await response.json(); // Endpoint may return an empty object if no template is found. if ( template?.id ) { - dispatch.receiveDefaultTemplateId( query, template.id ); + registry.batch( () => { + dispatch.receiveDefaultTemplateId( query, template.id ); + dispatch.receiveEntityRecords( 'postType', 'wp_template', [ + template, + ] ); + // Avoid further network requests. + dispatch.finishResolution( 'getEntityRecord', [ + 'postType', + 'wp_template', + template.id, + ] ); + } ); } }; diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index 9acadd5c0c0e70..7ea8c2f7f26d53 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -1284,38 +1284,6 @@ export function getReferenceByDistinctEdits( state ) { return state.editsReference; } -/** - * Retrieve the frontend template used for a given link. - * - * @param state Editor state. - * @param link Link. - * - * @return The template record. - */ -export function __experimentalGetTemplateForLink( - state: State, - link: string -): Optional< ET.Updatable< ET.WpTemplate > > | null | false { - const records = getEntityRecords< ET.WpTemplate >( - state, - 'postType', - 'wp_template', - { - 'find-template': link, - } - ); - - if ( records?.length ) { - return getEditedEntityRecord< ET.WpTemplate >( - state, - 'postType', - 'wp_template', - records[ 0 ].id - ); - } - return null; -} - /** * Retrieve the current theme's base global styles * diff --git a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js index 35eeb5963fb546..3498bed4c99a56 100644 --- a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js +++ b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js @@ -31,47 +31,33 @@ const postTypesWithoutParentTemplate = [ const authorizedPostTypes = [ 'page', 'post' ]; function useResolveEditedEntityAndContext( { postId, postType } ) { - const { - hasLoadedAllDependencies, - homepageId, - postsPageId, - url, - frontPageTemplateId, - } = useSelect( ( select ) => { - const { getEntityRecord, getEntityRecords } = select( coreDataStore ); - const siteData = getEntityRecord( 'root', 'site' ); - const base = getEntityRecord( 'root', '__unstableBase' ); - const templates = getEntityRecords( 'postType', TEMPLATE_POST_TYPE, { - per_page: -1, - } ); - const _homepageId = - siteData?.show_on_front === 'page' && - [ 'number', 'string' ].includes( typeof siteData.page_on_front ) && - !! +siteData.page_on_front // We also need to check if it's not zero(`0`). - ? siteData.page_on_front.toString() - : null; - const _postsPageId = - siteData?.show_on_front === 'page' && - [ 'number', 'string' ].includes( typeof siteData.page_for_posts ) - ? siteData.page_for_posts.toString() - : null; - let _frontPageTemplateId; - if ( templates ) { - const frontPageTemplate = templates.find( - ( t ) => t.slug === 'front-page' - ); - _frontPageTemplateId = frontPageTemplate - ? frontPageTemplate.id - : false; - } - return { - hasLoadedAllDependencies: !! base && !! siteData, - homepageId: _homepageId, - postsPageId: _postsPageId, - url: base?.home, - frontPageTemplateId: _frontPageTemplateId, - }; - }, [] ); + const { hasLoadedAllDependencies, homepageId, postsPageId } = useSelect( + ( select ) => { + const { getEntityRecord } = select( coreDataStore ); + const siteData = getEntityRecord( 'root', 'site' ); + const _homepageId = + siteData?.show_on_front === 'page' && + [ 'number', 'string' ].includes( + typeof siteData.page_on_front + ) && + !! +siteData.page_on_front // We also need to check if it's not zero(`0`). + ? siteData.page_on_front.toString() + : null; + const _postsPageId = + siteData?.show_on_front === 'page' && + [ 'number', 'string' ].includes( + typeof siteData.page_for_posts + ) + ? siteData.page_for_posts.toString() + : null; + return { + hasLoadedAllDependencies: !! siteData, + homepageId: _homepageId, + postsPageId: _postsPageId, + }; + }, + [] + ); /** * This is a hook that recreates the logic to resolve a template for a given WordPress postID postTypeId @@ -99,7 +85,6 @@ function useResolveEditedEntityAndContext( { postId, postType } ) { getEditedEntityRecord, getEntityRecords, getDefaultTemplateId, - __experimentalGetTemplateForLink, } = select( coreDataStore ); function resolveTemplateForPostTypeAndId( @@ -111,15 +96,7 @@ function useResolveEditedEntityAndContext( { postId, postType } ) { postTypeToResolve === 'page' && homepageId === postIdToResolve ) { - // We're still checking whether the front page template exists. - // Don't resolve the template yet. - if ( frontPageTemplateId === undefined ) { - return undefined; - } - - if ( !! frontPageTemplateId ) { - return frontPageTemplateId; - } + return getDefaultTemplateId( { slug: 'front-page' } ); } const editedEntity = getEditedEntityRecord( @@ -135,8 +112,7 @@ function useResolveEditedEntityAndContext( { postId, postType } ) { postTypeToResolve === 'page' && postsPageId === postIdToResolve ) { - return __experimentalGetTemplateForLink( editedEntity.link ) - ?.id; + return getDefaultTemplateId( { slug: 'home' } ); } // First see if the post/page has an assigned template and fetch it. const currentTemplateSlug = editedEntity.template; @@ -194,20 +170,9 @@ function useResolveEditedEntityAndContext( { postId, postType } ) { } // If we're not rendering a specific page, use the front page template. - if ( url ) { - const template = __experimentalGetTemplateForLink( url ); - return template?.id; - } + return getDefaultTemplateId( { slug: 'front-page' } ); }, - [ - homepageId, - postsPageId, - hasLoadedAllDependencies, - url, - postId, - postType, - frontPageTemplateId, - ] + [ homepageId, postsPageId, hasLoadedAllDependencies, postId, postType ] ); const context = useMemo( () => { From 7387fd0f068a6d448116d7d424eb25b7ff1aba67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20K=C3=A4gy?= <mail@fabian-kaegy.de> Date: Thu, 31 Oct 2024 17:33:01 +0100 Subject: [PATCH 1433/1908] Fix: Show Meta Boxes at the bottom of the screen regardless of the current rendering mode (#66508) Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> --- packages/edit-post/src/components/layout/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 7812280795aad6..b50e17054fd3ef 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -424,9 +424,7 @@ function Layout( { !! select( blockEditorStore ).getBlockSelectionStart(), showIconLabels: get( 'core', 'showIconLabels' ), isDistractionFree: get( 'core', 'distractionFree' ), - showMetaBoxes: - ! DESIGN_POST_TYPES.includes( currentPostType ) && - isRenderingPostOnly, + showMetaBoxes: ! DESIGN_POST_TYPES.includes( currentPostType ), isWelcomeGuideVisible: isFeatureActive( 'welcomeGuide' ), templateId: supportsTemplateMode && From 3b9bb77cec975fa2491927e8c640405c791d5415 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:55:57 +0100 Subject: [PATCH 1434/1908] Site editor: preload post if needed (#66631) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- backport-changelog/6.8/7695.md | 3 +++ lib/compat/wordpress-6.8/preload.php | 7 +++++++ 2 files changed, 10 insertions(+) create mode 100644 backport-changelog/6.8/7695.md diff --git a/backport-changelog/6.8/7695.md b/backport-changelog/6.8/7695.md new file mode 100644 index 00000000000000..095c058e6fd10b --- /dev/null +++ b/backport-changelog/6.8/7695.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7695 + +* https://github.com/WordPress/gutenberg/pull/66631 diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php index b9e03802a58e95..2b2994b6f9be85 100644 --- a/lib/compat/wordpress-6.8/preload.php +++ b/lib/compat/wordpress-6.8/preload.php @@ -10,6 +10,13 @@ */ function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { if ( 'core/edit-site' === $context->name ) { + if ( ! empty( $_GET['postId'] ) ) { + $route_for_post = rest_get_route_for_post( $_GET['postId'] ); + if ( $route_for_post ) { + $paths[] = add_query_arg( 'context', 'edit', $route_for_post ); + } + } + // Core already preloads both of these for `core/edit-post`. $paths[] = '/wp/v2/settings'; $paths[] = array( '/wp/v2/settings', 'OPTIONS' ); From 489f6067c623926bce7151a76755bb68d8e22ea7 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 31 Oct 2024 18:53:32 +0100 Subject: [PATCH 1435/1908] Safari: fix site editor template error (#66647) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> --- lib/compat/wordpress-6.8/preload.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php index 2b2994b6f9be85..16aeb4a50619f3 100644 --- a/lib/compat/wordpress-6.8/preload.php +++ b/lib/compat/wordpress-6.8/preload.php @@ -18,7 +18,9 @@ function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { } // Core already preloads both of these for `core/edit-post`. - $paths[] = '/wp/v2/settings'; + // To do: investigate why adding this preload path breaks the site + // editor in Safari ("template not found"). Perhaps a race condition? + // $paths[] = '/wp/v2/settings'; $paths[] = array( '/wp/v2/settings', 'OPTIONS' ); $paths[] = '/?_fields=' . implode( ',', From 2f088e403b47f2380e05ec2448a5902af0cca289 Mon Sep 17 00:00:00 2001 From: Sarah Norris <1645628+mikachan@users.noreply.github.com> Date: Thu, 31 Oct 2024 20:10:18 +0000 Subject: [PATCH 1436/1908] Query Loop: Check for postTypeFromContext before using it (#66655) Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- packages/block-library/src/post-template/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/post-template/edit.js b/packages/block-library/src/post-template/edit.js index 4e7e514ed82b12..b28c726acfc77e 100644 --- a/packages/block-library/src/post-template/edit.js +++ b/packages/block-library/src/post-template/edit.js @@ -188,7 +188,7 @@ export default function PostTemplateEdit( { // When we preview Query Loop blocks we should prefer the current // block's postType, which is passed through block context. const usedPostType = - postTypeFromContext !== 'page' + postTypeFromContext && postTypeFromContext !== 'page' ? postTypeFromContext : previewPostType || postType; return { From fbdc0f97dc463f2a2860de10b8d08cda3d8f69da Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Fri, 1 Nov 2024 11:15:11 +1100 Subject: [PATCH 1437/1908] VisualEditor: Always output has-global-padding classname when in post only mode and the site supports root padding aware alignments (#66626) Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/editor/src/components/visual-editor/index.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/visual-editor/index.js b/packages/editor/src/components/visual-editor/index.js index 6a5466a265c3eb..795a4f983f1536 100644 --- a/packages/editor/src/components/visual-editor/index.js +++ b/packages/editor/src/components/visual-editor/index.js @@ -462,7 +462,13 @@ function VisualEditor( { renderingMode !== 'post-only' || isDesignPostType ? 'wp-site-blocks' - : `${ blockListLayoutClass } wp-block-post-content` // Ensure root level blocks receive default/flow blockGap styling rules. + : `${ blockListLayoutClass } wp-block-post-content`, // Ensure root level blocks receive default/flow blockGap styling rules. + { + 'has-global-padding': + renderingMode === 'post-only' && + ! isDesignPostType && + hasRootPaddingAwareAlignments, + } ) } layout={ blockListLayout } dropZoneElement={ From 99d22755b4e92b5bc09856b2c14a9564fb6797fc Mon Sep 17 00:00:00 2001 From: Carolina Nymark <myazalea@hotmail.com> Date: Fri, 1 Nov 2024 05:42:47 +0100 Subject: [PATCH 1438/1908] Prevent duplicate post format taxonomy queries (#66627) Add an early return to gutenberg_add_format_query_vars_to_query_loop_block if the taxonomy query already includes post formats. Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: david-binda <davidbinda@git.wordpress.org> --- lib/compat/wordpress-6.7/blocks.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/compat/wordpress-6.7/blocks.php b/lib/compat/wordpress-6.7/blocks.php index 1a8e7f5741c0a1..e739808000c5f3 100644 --- a/lib/compat/wordpress-6.7/blocks.php +++ b/lib/compat/wordpress-6.7/blocks.php @@ -59,6 +59,16 @@ function gutenberg_add_format_query_vars_to_query_loop_block( $query, $block ) { return $query; } + // Return early if the query already contains a post format. This is to avoid duplication if the + // WordPress core filter is already applied. + if ( ! empty( $query['tax_query'] ) ) { + foreach ( $query['tax_query'] as $taxquery ) { + if ( isset( $taxquery['taxonomy'] ) && 'post_format' === $taxquery['taxonomy'] ) { + return $query; + } + } + } + $formats = $block->context['query']['format']; /* * Validate that the format is either `standard` or a supported post format. From 11e2d06d86349b3cf4db40ec88988d66647f543a Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Fri, 1 Nov 2024 15:47:31 +1100 Subject: [PATCH 1439/1908] Theme JSON: replace top-level background style objects on merge (#66656) This commit fixes an omission in the theme json merge logic where top-level background image objects are not replaced, rather they are merged, which was the state of affairs before https://github.com/WordPress/gutenberg/pull/64128 Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- backport-changelog/6.8/7697.md | 3 +++ lib/class-wp-theme-json-gutenberg.php | 4 ++++ phpunit/class-wp-theme-json-test.php | 11 ++++++++--- 3 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 backport-changelog/6.8/7697.md diff --git a/backport-changelog/6.8/7697.md b/backport-changelog/6.8/7697.md new file mode 100644 index 00000000000000..e53fbf4bdb8ae5 --- /dev/null +++ b/backport-changelog/6.8/7697.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7697 + +* https://github.com/WordPress/gutenberg/pull/66656 diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 09f388e7d3b93f..dafa8b25f278fc 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -3297,6 +3297,10 @@ public function merge( $incoming ) { array(), array( 'include_node_paths_only' => true ) ); + + // Add top-level styles. + $style_nodes[] = array( 'path' => array( 'styles' ) ); + foreach ( $style_nodes as $style_node ) { $path = $style_node['path']; /* diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 29d454f6f4f0b0..50a0af4f9b3ff3 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -2301,7 +2301,9 @@ public function test_merge_incoming_background_styles() { 'styles' => array( 'background' => array( 'backgroundImage' => array( - 'url' => 'http://example.org/quote.png', + 'id' => 'uploaded', + 'source' => 'file', + 'url' => 'http://example.org/quote.png', ), 'backgroundSize' => 'cover', ), @@ -2333,7 +2335,10 @@ public function test_merge_incoming_background_styles() { 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( 'background' => array( - 'backgroundSize' => 'contain', + 'backgroundImage' => array( + 'url' => 'http://example.org/site.png', + ), + 'backgroundSize' => 'contain', ), 'blocks' => array( 'core/group' => array( @@ -2363,7 +2368,7 @@ public function test_merge_incoming_background_styles() { 'styles' => array( 'background' => array( 'backgroundImage' => array( - 'url' => 'http://example.org/quote.png', + 'url' => 'http://example.org/site.png', ), 'backgroundSize' => 'contain', ), From 0fa9ca0850f8df028e3b9e3c33b469a8a7e29833 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Fri, 1 Nov 2024 16:06:16 +1100 Subject: [PATCH 1440/1908] Media Library: Expose filters dropdown for individual images, such as with the Image block (#65965) * Media Library: Expose filters dropdown for individual images, such as with the Image block * Rename to be a little more generic Unlinked contributors: cagivacode, tiagogon, kylemcph, Wadowad, yoanmarchal, RoqueCampos, venture89, spncr, simonPaulBergzeit, Ezokia, fylgjur, sbathompson-he, dnnsjsk. Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: finalwebsites <finalwebsites@git.wordpress.org> Co-authored-by: Drivingralle <drivingralle@git.wordpress.org> Co-authored-by: johnbillion <johnbillion@git.wordpress.org> Co-authored-by: torounit <toro_unit@git.wordpress.org> Co-authored-by: paaljoachim <paaljoachim@git.wordpress.org> Co-authored-by: Soean <soean@git.wordpress.org> Co-authored-by: jamesmrobinson <imaginarymedia@git.wordpress.org> --- .../src/components/media-upload/index.js | 95 ++++++++++++++++--- 1 file changed, 82 insertions(+), 13 deletions(-) diff --git a/packages/media-utils/src/components/media-upload/index.js b/packages/media-utils/src/components/media-upload/index.js index 91de011869ad38..ed0a59ddbc684a 100644 --- a/packages/media-utils/src/components/media-upload/index.js +++ b/packages/media-utils/src/components/media-upload/index.js @@ -70,6 +70,46 @@ const getFeaturedImageMediaFrame = () => { } ); }; +/** + * Prepares the default frame for selecting a single media item. + * + * @return {window.wp.media.view.MediaFrame.Select} The default media workflow. + */ +const getSingleMediaFrame = () => { + const { wp } = window; + + // Extend the default Select frame, and use the same `createStates` method as in core, + // but with the addition of `filterable: 'uploaded'` to the Library state, so that + // the user can filter the media library by uploaded media. + return wp.media.view.MediaFrame.Select.extend( { + /** + * Create the default states on the frame. + */ + createStates() { + const options = this.options; + + if ( this.options.states ) { + return; + } + + // Add the default states. + this.states.add( [ + // Main states. + new wp.media.controller.Library( { + library: wp.media.query( options.library ), + multiple: options.multiple, + title: options.title, + priority: 20, + filterable: 'uploaded', // Allow filtering by uploaded images. + } ), + new wp.media.controller.EditImage( { + model: options.editImage, + } ), + ] ); + }, + } ); +}; + /** * Prepares the Gallery toolbars and frames. * @@ -324,6 +364,47 @@ class MediaUpload extends Component { }; } + /** + * Initializes the Media Library requirements for the single image flow. + * + * @return {void} + */ + buildAndSetSingleMediaFrame() { + const { wp } = window; + const { + allowedTypes, + multiple = false, + title = __( 'Select or Upload Media' ), + value, + } = this.props; + + const frameConfig = { + title, + multiple, + }; + if ( !! allowedTypes ) { + frameConfig.library = { type: allowedTypes }; + } + + // If a frame already exists, remove it. + if ( this.frame ) { + this.frame.remove(); + } + + const singleImageFrame = getSingleMediaFrame(); + const attachments = getAttachmentsCollection( value ); + const selection = new wp.media.model.Selection( attachments.models, { + props: attachments.props.toJSON(), + } ); + this.frame = new singleImageFrame( { + mimeType: allowedTypes, + multiple, + selection, + ...frameConfig, + } ); + wp.media.frame = this.frame; + } + componentWillUnmount() { this.frame?.remove(); } @@ -424,27 +505,15 @@ class MediaUpload extends Component { openModal() { const { - allowedTypes, gallery = false, unstableFeaturedImageFlow = false, modalClass, - multiple = false, - title = __( 'Select or Upload Media' ), } = this.props; - const { wp } = window; if ( gallery ) { this.buildAndSetGalleryFrame(); } else { - const frameConfig = { - title, - multiple, - }; - if ( !! allowedTypes ) { - frameConfig.library = { type: allowedTypes }; - } - - this.frame = wp.media( frameConfig ); + this.buildAndSetSingleMediaFrame(); } if ( modalClass ) { From 160a45aa00e1d28ba4e46170c1914e75778c4157 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Fri, 1 Nov 2024 16:49:28 +1100 Subject: [PATCH 1441/1908] Style engine: wrap array_merge in conditionals to prevent unnecessary merging (#66661) Wrap array_merge in a conditional to prevent unnecessary firing. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/style-engine/class-wp-style-engine.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/style-engine/class-wp-style-engine.php b/packages/style-engine/class-wp-style-engine.php index 02186fecdcea26..3c692719030053 100644 --- a/packages/style-engine/class-wp-style-engine.php +++ b/packages/style-engine/class-wp-style-engine.php @@ -424,8 +424,15 @@ public static function parse_block_styles( $block_styles, $options ) { continue; } - $parsed_styles['classnames'] = array_merge( $parsed_styles['classnames'], static::get_classnames( $style_value, $style_definition ) ); - $parsed_styles['declarations'] = array_merge( $parsed_styles['declarations'], static::get_css_declarations( $style_value, $style_definition, $options ) ); + $classnames = static::get_classnames( $style_value, $style_definition ); + if ( ! empty( $classnames ) ) { + $parsed_styles['classnames'] = array_merge( $parsed_styles['classnames'], $classnames ); + } + + $css_declarations = static::get_css_declarations( $style_value, $style_definition, $options ); + if ( ! empty( $css_declarations ) ) { + $parsed_styles['declarations'] = array_merge( $parsed_styles['declarations'], $css_declarations ); + } } } From 5205f1fd8caeb5fabf10a053f1f4aa28172b0313 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 1 Nov 2024 11:07:08 +0400 Subject: [PATCH 1442/1908] Editor: Restore the 'PluginPostStatusInfo' slot position (#66665) Unlinked contributors: laurelfulford. Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: up1512001 <up1512001@git.wordpress.org> --- packages/editor/src/components/sidebar/post-summary.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/sidebar/post-summary.js b/packages/editor/src/components/sidebar/post-summary.js index 72f1080770fd9d..3539f7ba964ec7 100644 --- a/packages/editor/src/components/sidebar/post-summary.js +++ b/packages/editor/src/components/sidebar/post-summary.js @@ -87,11 +87,11 @@ export default function PostSummary( { onActionPerformed } ) { <PostsPerPage /> <SiteDiscussion /> <PostFormatPanel /> + { fills } </VStack> <PostTrash onActionPerformed={ onActionPerformed } /> - { fills } </VStack> ) } </VStack> From 77122c5faed51e8491637770123bcd659a3358bf Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Fri, 1 Nov 2024 10:43:11 +0100 Subject: [PATCH 1443/1908] getDefaultTemplateId: ensure entity config is loaded (#66650) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- lib/compat/wordpress-6.8/preload.php | 5 +---- packages/core-data/src/resolvers.js | 9 +++++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php index 16aeb4a50619f3..aabe0d4fb574cc 100644 --- a/lib/compat/wordpress-6.8/preload.php +++ b/lib/compat/wordpress-6.8/preload.php @@ -17,10 +17,7 @@ function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { } } - // Core already preloads both of these for `core/edit-post`. - // To do: investigate why adding this preload path breaks the site - // editor in Safari ("template not found"). Perhaps a race condition? - // $paths[] = '/wp/v2/settings'; + $paths[] = '/wp/v2/settings'; $paths[] = array( '/wp/v2/settings', 'OPTIONS' ); $paths[] = '/?_fields=' . implode( ',', diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index a3bbd37f2d7c20..ae0c7f456e533d 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -749,12 +749,13 @@ export const getNavigationFallbackId = export const getDefaultTemplateId = ( query ) => - async ( { dispatch, registry } ) => { - const response = await apiFetch( { + async ( { dispatch, registry, resolveSelect } ) => { + const template = await apiFetch( { path: addQueryArgs( '/wp/v2/templates/lookup', query ), - parse: false, } ); - const template = await response.json(); + // Wait for the the entities config to be loaded, otherwise receiving + // the template as an entity will not work. + await resolveSelect.getEntitiesConfig( 'postType' ); // Endpoint may return an empty object if no template is found. if ( template?.id ) { registry.batch( () => { From 29c8af39982cab19065b324969b498d2d8fc2043 Mon Sep 17 00:00:00 2001 From: Manzoor Wani <manzoorwani.jk@gmail.com> Date: Fri, 1 Nov 2024 16:55:12 +0530 Subject: [PATCH 1444/1908] Convert the emitter module in data package to TS (#66669) * Convert the emitter module to TS * Clean up JSDoc * Restore return comment Co-authored-by: manzoorwanijk <manzoorwanijk@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/data/src/types.ts | 8 -------- packages/data/src/utils/{emitter.js => emitter.ts} | 14 +++++++++++--- 2 files changed, 11 insertions(+), 11 deletions(-) rename packages/data/src/utils/{emitter.js => emitter.ts} (71%) diff --git a/packages/data/src/types.ts b/packages/data/src/types.ts index 570bb1e1890ceb..8d69bf3e0eb728 100644 --- a/packages/data/src/types.ts +++ b/packages/data/src/types.ts @@ -161,14 +161,6 @@ export interface DataRegistry { register: ( store: StoreDescriptor< any > ) => void; } -export interface DataEmitter { - emit: () => void; - subscribe: ( listener: () => void ) => () => void; - pause: () => void; - resume: () => void; - isPaused: boolean; -} - // Type Helpers. export type ConfigOf< S > = S extends StoreDescriptor< infer C > ? C : never; diff --git a/packages/data/src/utils/emitter.js b/packages/data/src/utils/emitter.ts similarity index 71% rename from packages/data/src/utils/emitter.js rename to packages/data/src/utils/emitter.ts index 883b4d83c1e748..b01f1f965f5e70 100644 --- a/packages/data/src/utils/emitter.js +++ b/packages/data/src/utils/emitter.ts @@ -1,12 +1,20 @@ +export interface DataEmitter { + emit: VoidFunction; + subscribe: ( listener: VoidFunction ) => VoidFunction; + pause: VoidFunction; + resume: VoidFunction; + isPaused: boolean; +} + /** * Create an event emitter. * - * @return {import("../types").DataEmitter} Emitter. + * @return The event emitter. */ -export function createEmitter() { +export function createEmitter(): DataEmitter { let isPaused = false; let isPending = false; - const listeners = new Set(); + const listeners = new Set< VoidFunction >(); const notifyListeners = () => // We use Array.from to clone the listeners Set // This ensures that we don't run a listener From d6cb2271d9484cdbfe8cd807e8a59c0f3bf419ae Mon Sep 17 00:00:00 2001 From: Manzoor Wani <manzoorwani.jk@gmail.com> Date: Fri, 1 Nov 2024 17:01:42 +0530 Subject: [PATCH 1445/1908] TypeScript: Fix and improve types for private-apis (#66667) * Convert private-apis package to TypeScript * Convert the usage of private-apis to TypeScript * Clean up JSDoc Co-authored-by: manzoorwanijk <manzoorwanijk@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/{lock-unlock.js => lock-unlock.ts} | 0 .../src/{lock-unlock.js => lock-unlock.ts} | 0 .../src/{lock-unlock.js => lock-unlock.ts} | 0 .../src/{lock-unlock.js => lock-unlock.ts} | 0 .../{implementation.js => implementation.ts} | 32 +++++++++---------- .../private-apis/src/{index.js => index.ts} | 0 6 files changed, 15 insertions(+), 17 deletions(-) rename packages/block-editor/src/{lock-unlock.js => lock-unlock.ts} (100%) rename packages/block-library/src/{lock-unlock.js => lock-unlock.ts} (100%) rename packages/core-data/src/{lock-unlock.js => lock-unlock.ts} (100%) rename packages/data/src/{lock-unlock.js => lock-unlock.ts} (100%) rename packages/private-apis/src/{implementation.js => implementation.ts} (88%) rename packages/private-apis/src/{index.js => index.ts} (100%) diff --git a/packages/block-editor/src/lock-unlock.js b/packages/block-editor/src/lock-unlock.ts similarity index 100% rename from packages/block-editor/src/lock-unlock.js rename to packages/block-editor/src/lock-unlock.ts diff --git a/packages/block-library/src/lock-unlock.js b/packages/block-library/src/lock-unlock.ts similarity index 100% rename from packages/block-library/src/lock-unlock.js rename to packages/block-library/src/lock-unlock.ts diff --git a/packages/core-data/src/lock-unlock.js b/packages/core-data/src/lock-unlock.ts similarity index 100% rename from packages/core-data/src/lock-unlock.js rename to packages/core-data/src/lock-unlock.ts diff --git a/packages/data/src/lock-unlock.js b/packages/data/src/lock-unlock.ts similarity index 100% rename from packages/data/src/lock-unlock.js rename to packages/data/src/lock-unlock.ts diff --git a/packages/private-apis/src/implementation.js b/packages/private-apis/src/implementation.ts similarity index 88% rename from packages/private-apis/src/implementation.js rename to packages/private-apis/src/implementation.ts index b32a95986d32c9..ee2b9693959a35 100644 --- a/packages/private-apis/src/implementation.js +++ b/packages/private-apis/src/implementation.ts @@ -2,7 +2,7 @@ * wordpress/private-apis – the utilities to enable private cross-package * exports of private APIs. * - * This "implementation.js" file is needed for the sake of the unit tests. It + * This "implementation.ts" file is needed for the sake of the unit tests. It * exports more than the public API of the package to aid in testing. */ @@ -36,10 +36,8 @@ const CORE_MODULES_USING_PRIVATE_APIS = [ /** * A list of core modules that already opted-in to * the privateApis package. - * - * @type {string[]} */ -const registeredPrivateApis = []; +const registeredPrivateApis: Array< string > = []; /* * Warning for theme and plugin developers. @@ -65,13 +63,13 @@ const allowReRegistration = globalThis.IS_WORDPRESS_CORE ? false : true; * Called by a @wordpress package wishing to opt-in to accessing or exposing * private private APIs. * - * @param {string} consent The consent string. - * @param {string} moduleName The name of the module that is opting in. - * @return {{lock: typeof lock, unlock: typeof unlock}} An object containing the lock and unlock functions. + * @param consent The consent string. + * @param moduleName The name of the module that is opting in. + * @return An object containing the lock and unlock functions. */ export const __dangerousOptInToUnstableAPIsOnlyForCoreModules = ( - consent, - moduleName + consent: string, + moduleName: string ) => { if ( ! CORE_MODULES_USING_PRIVATE_APIS.includes( moduleName ) ) { throw new Error( @@ -135,10 +133,10 @@ export const __dangerousOptInToUnstableAPIsOnlyForCoreModules = ( * // { a: 1 } * ``` * - * @param {any} object The object to bind the private data to. - * @param {any} privateData The private data to bind to the object. + * @param object The object to bind the private data to. + * @param privateData The private data to bind to the object. */ -function lock( object, privateData ) { +function lock( object: Record< symbol, WeakKey >, privateData: unknown ) { if ( ! object ) { throw new Error( 'Cannot lock an undefined object.' ); } @@ -168,10 +166,10 @@ function lock( object, privateData ) { * // { a: 1 } * ``` * - * @param {any} object The object to unlock the private data from. - * @return {any} The private data bound to the object. + * @param object The object to unlock the private data from. + * @return The private data bound to the object. */ -function unlock( object ) { +function unlock( object: Record< symbol, WeakKey > ) { if ( ! object ) { throw new Error( 'Cannot unlock an undefined object.' ); } @@ -198,9 +196,9 @@ const __private = Symbol( 'Private API ID' ); * Private function to allow the unit tests to allow * a mock module to access the private APIs. * - * @param {string} name The name of the module. + * @param name The name of the module. */ -export function allowCoreModule( name ) { +export function allowCoreModule( name: string ) { CORE_MODULES_USING_PRIVATE_APIS.push( name ); } diff --git a/packages/private-apis/src/index.js b/packages/private-apis/src/index.ts similarity index 100% rename from packages/private-apis/src/index.js rename to packages/private-apis/src/index.ts From b69bca9ebf90ca6c39d11b966e4a0e2f9f9fd612 Mon Sep 17 00:00:00 2001 From: arthur791004 <arthur.chu@automattic.com> Date: Fri, 1 Nov 2024 20:36:48 +0900 Subject: [PATCH 1446/1908] Post Editor: Set the default value of the editorTool to edit (#66636) * Post Editor: Set the default value of the editorTool to edit * Change the condition of _showEmptyBlockSideInserter * Set the default value of the editorTool to "edit" for both post editor and site editor --- .../src/components/block-tools/use-show-block-tools.js | 4 +++- packages/edit-post/src/index.js | 1 + packages/edit-post/src/index.native.js | 1 + packages/edit-site/src/index.js | 1 + packages/edit-site/src/posts.js | 1 + 5 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-tools/use-show-block-tools.js b/packages/block-editor/src/components/block-tools/use-show-block-tools.js index 61b5be891fd540..db651bce00fec7 100644 --- a/packages/block-editor/src/components/block-tools/use-show-block-tools.js +++ b/packages/block-editor/src/components/block-tools/use-show-block-tools.js @@ -40,7 +40,9 @@ export function useShowBlockTools() { const _showEmptyBlockSideInserter = clientId && ! isTyping() && - editorMode === 'edit' && + // Hide the block inserter on the navigation mode. + // See https://github.com/WordPress/gutenberg/pull/66636#discussion_r1824728483. + editorMode !== 'navigation' && isEmptyDefaultBlock; const _showBlockToolbarPopover = ! getSettings().hasFixedToolbar && diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index 685ffc56f63a80..b01fa693ed5a7c 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -62,6 +62,7 @@ export function initializeEditor( dispatch( preferencesStore ).setDefaults( 'core', { allowRightClickOverrides: true, editorMode: 'visual', + editorTool: 'edit', fixedToolbar: false, hiddenBlockTypes: [], inactivePanels: [], diff --git a/packages/edit-post/src/index.native.js b/packages/edit-post/src/index.native.js index 613f394134e0ca..d26ddf7b8a25cf 100644 --- a/packages/edit-post/src/index.native.js +++ b/packages/edit-post/src/index.native.js @@ -29,6 +29,7 @@ export function initializeEditor( id, postType, postId ) { welcomeGuide: true, } ); dispatch( preferencesStore ).setDefaults( 'core', { + editorTool: 'edit', hiddenBlockTypes: [], inactivePanels: [], openPanels: [ 'post-status' ], diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 83d25bcd0c03ac..7f124e6b5f7ac6 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -68,6 +68,7 @@ export function initializeEditor( id, settings ) { allowRightClickOverrides: true, distractionFree: false, editorMode: 'visual', + editorTool: 'edit', fixedToolbar: false, focusMode: false, inactivePanels: [], diff --git a/packages/edit-site/src/posts.js b/packages/edit-site/src/posts.js index 78d823b56c4c11..9c31fdd0040ca1 100644 --- a/packages/edit-site/src/posts.js +++ b/packages/edit-site/src/posts.js @@ -65,6 +65,7 @@ export function initializePostsDashboard( id, settings ) { allowRightClickOverrides: true, distractionFree: false, editorMode: 'visual', + editorTool: 'edit', fixedToolbar: false, focusMode: false, inactivePanels: [], From 86ca73a86541f0a1a16e30a906ebed3ba2ad66d2 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Fri, 1 Nov 2024 13:38:11 +0200 Subject: [PATCH 1447/1908] Image block: Add support for "more" dropdown for additional tools in Write mode (#66605) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/block-library/src/image/editor.scss | 4 + packages/block-library/src/image/image.js | 267 +++++++++++------- .../editor/various/pattern-overrides.spec.js | 5 +- 3 files changed, 167 insertions(+), 109 deletions(-) diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss index 34f65d690d3d74..35b05a063c2997 100644 --- a/packages/block-library/src/image/editor.scss +++ b/packages/block-library/src/image/editor.scss @@ -159,6 +159,10 @@ figure.wp-block-image:not(.wp-block) { } } +.wp-block-image__toolbar_content_textarea__container { + padding: $grid-unit; +} + .wp-block-image__toolbar_content_textarea { // Corresponds to the size of the textarea in the block inspector. width: 250px; diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 89bf31f92664b9..a8d65951635522 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -10,11 +10,14 @@ import { TextControl, ToolbarButton, ToolbarGroup, - Dropdown, __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, __experimentalUseCustomUnits as useCustomUnits, Placeholder, + MenuItem, + ToolbarItem, + DropdownMenu, + Popover, } from '@wordpress/components'; import { useViewportMatch } from '@wordpress/compose'; import { useSelect, useDispatch } from '@wordpress/data'; @@ -32,10 +35,9 @@ import { } from '@wordpress/block-editor'; import { useEffect, useMemo, useState, useRef } from '@wordpress/element'; import { __, _x, sprintf, isRTL } from '@wordpress/i18n'; -import { DOWN } from '@wordpress/keycodes'; import { getFilename } from '@wordpress/url'; import { getBlockBindingsSource, switchToBlockType } from '@wordpress/blocks'; -import { crop, overlayText, upload } from '@wordpress/icons'; +import { crop, overlayText, upload, chevronDown } from '@wordpress/icons'; import { store as noticesStore } from '@wordpress/notices'; import { store as coreStore } from '@wordpress/core-data'; @@ -69,6 +71,10 @@ const scaleOptions = [ }, ]; +const WRITEMODE_POPOVER_PROPS = { + placement: 'bottom-start', +}; + // If the image has a href, wrap in an <a /> tag to trigger any inherited link element styles. const ImageWrapper = ( { href, children } ) => { if ( ! href ) { @@ -94,6 +100,148 @@ const ImageWrapper = ( { href, children } ) => { ); }; +function ContentOnlyControls( { + attributes, + setAttributes, + lockAltControls, + lockAltControlsMessage, + lockTitleControls, + lockTitleControlsMessage, +} ) { + // Use internal state instead of a ref to make sure that the component + // re-renders when the popover's anchor updates. + const [ popoverAnchor, setPopoverAnchor ] = useState( null ); + const [ isAltDialogOpen, setIsAltDialogOpen ] = useState( false ); + const [ isTitleDialogOpen, setIsTitleDialogOpen ] = useState( false ); + return ( + <> + <ToolbarItem ref={ setPopoverAnchor }> + { ( toggleProps ) => ( + <DropdownMenu + icon={ chevronDown } + /* translators: button label text should, if possible, be under 16 characters. */ + label={ __( 'More' ) } + toggleProps={ { + ...toggleProps, + description: __( 'Displays more controls.' ), + } } + popoverProps={ WRITEMODE_POPOVER_PROPS } + > + { ( { onClose } ) => ( + <> + <MenuItem + onClick={ () => { + setIsAltDialogOpen( true ); + onClose(); + } } + > + { _x( + 'Alternative text', + 'Alternative text for an image. Block toolbar label, a low character count is preferred.' + ) } + </MenuItem> + <MenuItem + onClick={ () => { + setIsTitleDialogOpen( true ); + onClose(); + } } + > + { __( 'Title text' ) } + </MenuItem> + </> + ) } + </DropdownMenu> + ) } + </ToolbarItem> + { isAltDialogOpen && ( + <Popover + placement="bottom-start" + anchor={ popoverAnchor } + onClose={ () => setIsAltDialogOpen( false ) } + offset={ 13 } + variant="toolbar" + > + <div className="wp-block-image__toolbar_content_textarea__container"> + <TextareaControl + className="wp-block-image__toolbar_content_textarea" + label={ __( 'Alternative text' ) } + value={ attributes.alt || '' } + onChange={ ( value ) => + setAttributes( { alt: value } ) + } + disabled={ lockAltControls } + help={ + lockAltControls ? ( + <>{ lockAltControlsMessage }</> + ) : ( + <> + <ExternalLink + href={ + // translators: Localized tutorial, if one exists. W3C Web Accessibility Initiative link has list of existing translations. + __( + 'https://www.w3.org/WAI/tutorials/images/decision-tree/' + ) + } + > + { __( + 'Describe the purpose of the image.' + ) } + </ExternalLink> + <br /> + { __( 'Leave empty if decorative.' ) } + </> + ) + } + __nextHasNoMarginBottom + /> + </div> + </Popover> + ) } + { isTitleDialogOpen && ( + <Popover + placement="bottom-start" + anchor={ popoverAnchor } + onClose={ () => setIsTitleDialogOpen( false ) } + offset={ 13 } + variant="toolbar" + > + <div className="wp-block-image__toolbar_content_textarea__container"> + <TextControl + __next40pxDefaultSize + className="wp-block-image__toolbar_content_textarea" + __nextHasNoMarginBottom + label={ __( 'Title attribute' ) } + value={ attributes.title || '' } + onChange={ ( value ) => + setAttributes( { + title: value, + } ) + } + disabled={ lockTitleControls } + help={ + lockTitleControls ? ( + <>{ lockTitleControlsMessage }</> + ) : ( + <> + { __( + 'Describe the role of this image on the page.' + ) } + <ExternalLink href="https://www.w3.org/TR/html52/dom.html#the-title-attribute"> + { __( + '(Note: many devices and browsers do not display this text.)' + ) } + </ExternalLink> + </> + ) + } + /> + </div> + </Popover> + ) } + </> + ); +} + export default function Image( { temporaryURL, attributes, @@ -625,112 +773,15 @@ export default function Image( { // Add some extra controls for content attributes when content only mode is active. // With content only mode active, the inspector is hidden, so users need another way // to edit these attributes. - <BlockControls group="other"> - <Dropdown - popoverProps={ { position: 'bottom right' } } - renderToggle={ ( { isOpen, onToggle } ) => ( - <ToolbarButton - onClick={ onToggle } - aria-haspopup="true" - aria-expanded={ isOpen } - onKeyDown={ ( event ) => { - if ( ! isOpen && event.keyCode === DOWN ) { - event.preventDefault(); - onToggle(); - } - } } - > - { _x( - 'Alternative text', - 'Alternative text for an image. Block toolbar label, a low character count is preferred.' - ) } - </ToolbarButton> - ) } - renderContent={ () => ( - <TextareaControl - className="wp-block-image__toolbar_content_textarea" - label={ __( 'Alternative text' ) } - value={ alt || '' } - onChange={ updateAlt } - disabled={ lockAltControls } - help={ - lockAltControls ? ( - <>{ lockAltControlsMessage }</> - ) : ( - <> - <ExternalLink - href={ - // translators: Localized tutorial, if one exists. W3C Web Accessibility Initiative link has list of existing translations. - __( - 'https://www.w3.org/WAI/tutorials/images/decision-tree/' - ) - } - > - { __( - 'Describe the purpose of the image.' - ) } - </ExternalLink> - <br /> - { __( - 'Leave empty if decorative.' - ) } - </> - ) - } - __nextHasNoMarginBottom - /> - ) } + <BlockControls group="block"> + <ContentOnlyControls + attributes={ attributes } + setAttributes={ setAttributes } + lockAltControls={ lockAltControls } + lockAltControlsMessage={ lockAltControlsMessage } + lockTitleControls={ lockTitleControls } + lockTitleControlsMessage={ lockTitleControlsMessage } /> - { title && ( - <Dropdown - popoverProps={ { position: 'bottom right' } } - renderToggle={ ( { isOpen, onToggle } ) => ( - <ToolbarButton - onClick={ onToggle } - aria-haspopup="true" - aria-expanded={ isOpen } - onKeyDown={ ( event ) => { - if ( - ! isOpen && - event.keyCode === DOWN - ) { - event.preventDefault(); - onToggle(); - } - } } - > - { __( 'Title' ) } - </ToolbarButton> - ) } - renderContent={ () => ( - <TextControl - __next40pxDefaultSize - className="wp-block-image__toolbar_content_textarea" - __nextHasNoMarginBottom - label={ __( 'Title attribute' ) } - value={ title || '' } - onChange={ onSetTitle } - disabled={ lockTitleControls } - help={ - lockTitleControls ? ( - <>{ lockTitleControlsMessage }</> - ) : ( - <> - { __( - 'Describe the role of this image on the page.' - ) } - <ExternalLink href="https://www.w3.org/TR/html52/dom.html#the-title-attribute"> - { __( - '(Note: many devices and browsers do not display this text.)' - ) } - </ExternalLink> - </> - ) - } - /> - ) } - /> - ) } </BlockControls> ) } <InspectorControls> diff --git a/test/e2e/specs/editor/various/pattern-overrides.spec.js b/test/e2e/specs/editor/various/pattern-overrides.spec.js index 5fbd0e66b5fd02..6f4a5929300520 100644 --- a/test/e2e/specs/editor/various/pattern-overrides.spec.js +++ b/test/e2e/specs/editor/various/pattern-overrides.spec.js @@ -1131,7 +1131,10 @@ test.describe( 'Pattern Overrides', () => { /\/wp-content\/uploads\// ); await editor.showBlockToolbar(); - await editor.clickBlockToolbarButton( 'Alternative text' ); + await editor.clickBlockToolbarButton( 'More' ); + await page + .getByRole( 'menuitem', { name: 'Alternative text' } ) + .click(); await page .getByRole( 'textbox', { name: 'alternative text' } ) .fill( 'Test Image' ); From e74dce1e5c987f6e38d2fd28dcbf7f6b4a65ec03 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Fri, 1 Nov 2024 12:40:34 +0000 Subject: [PATCH 1448/1908] Update Changelog for 19.5.1 --- changelog.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/changelog.txt b/changelog.txt index 420a6392415b36..81b6ff9d15db79 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,16 @@ == Changelog == += 19.5.1 = + + +Error: There are no unreleased pull requests associated with the milestone. + at fetchAllPullRequests (/home/runner/work/gutenberg/gutenberg/bin/plugin/commands/changelog.js:721:10) + at process.processTicksAndRejections (node:internal/process/task_queues:95:5) + at async createChangelog (/home/runner/work/gutenberg/gutenberg/bin/plugin/commands/changelog.js:1031:24) + at async getReleaseChangelog (/home/runner/work/gutenberg/gutenberg/bin/plugin/commands/changelog.js:1057:2) + at async Command.<anonymous> (/home/runner/work/gutenberg/gutenberg/bin/plugin/cli.js:11:4) + + = 19.6.0-rc.2 = ## Changelog From 7ec6d6f1817b461c597b5221dc34decfbdf5a851 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Fri, 1 Nov 2024 13:20:18 +0000 Subject: [PATCH 1449/1908] Bump plugin version to 19.6.0-rc.3 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 60b7614beefee4..128156a947b27f 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.6.0-rc.2 + * Version: 19.6.0-rc.3 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 24812eff02ef8a..20bf45235880ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.6.0-rc.2", + "version": "19.6.0-rc.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.6.0-rc.2", + "version": "19.6.0-rc.3", "hasInstallScript": true, "license": "GPL-2.0-or-later", "workspaces": [ diff --git a/package.json b/package.json index 2218fd6171aa30..6e519e2f1070e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.6.0-rc.2", + "version": "19.6.0-rc.3", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 98f62101f98f3b491810f2dc9f6a6de135318687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joni=20Erkkil=C3=A4?= <62872075+n2erjo00@users.noreply.github.com> Date: Fri, 1 Nov 2024 15:26:47 +0200 Subject: [PATCH 1450/1908] Speak 'Block moved up/down' after using keyboard actions to move up/down (#64966) * Speak 'Block moved up/down' after using keyboard actions to move up/down * Created internal helper function to create description for speak function * Refactor away from helper function and simplify * Add short confirmation message after block has been moved up|down * End with period. Speak singular or plural * Speak the amount of moved blocks Co-authored-by: n2erjo00 <n2erjo00@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: alexstine <alexstine@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: talksina <talksina@git.wordpress.org> Co-authored-by: enricobattocchi <lopo@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> --- .../src/components/block-tools/index.js | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 700b345be20274..e6c49af6b61061 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -8,7 +8,7 @@ import { __unstableUseShortcutEventMatch as useShortcutEventMatch } from '@wordp import { useRef } from '@wordpress/element'; import { switchToBlockType, store as blocksStore } from '@wordpress/blocks'; import { speak } from '@wordpress/a11y'; -import { __ } from '@wordpress/i18n'; +import { __, sprintf, _n } from '@wordpress/i18n'; /** * Internal dependencies @@ -92,19 +92,35 @@ export default function BlockTools( { return; } - if ( isMatch( 'core/block-editor/move-up', event ) ) { + if ( + isMatch( 'core/block-editor/move-up', event ) || + isMatch( 'core/block-editor/move-down', event ) + ) { const clientIds = getSelectedBlockClientIds(); if ( clientIds.length ) { event.preventDefault(); const rootClientId = getBlockRootClientId( clientIds[ 0 ] ); - moveBlocksUp( clientIds, rootClientId ); - } - } else if ( isMatch( 'core/block-editor/move-down', event ) ) { - const clientIds = getSelectedBlockClientIds(); - if ( clientIds.length ) { - event.preventDefault(); - const rootClientId = getBlockRootClientId( clientIds[ 0 ] ); - moveBlocksDown( clientIds, rootClientId ); + const direction = isMatch( 'core/block-editor/move-up', event ) + ? 'up' + : 'down'; + if ( direction === 'up' ) { + moveBlocksUp( clientIds, rootClientId ); + } else { + moveBlocksDown( clientIds, rootClientId ); + } + const blockLength = Array.isArray( clientIds ) + ? clientIds.length + : 1; + const message = sprintf( + // translators: %d: the name of the block that has been moved + _n( + '%d block moved.', + '%d blocks moved.', + clientIds.length + ), + blockLength + ); + speak( message ); } } else if ( isMatch( 'core/block-editor/duplicate', event ) ) { const clientIds = getSelectedBlockClientIds(); From ec3d2c17f36199f7e57fb792a84d778fc2b0e57f Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Fri, 1 Nov 2024 13:49:53 +0000 Subject: [PATCH 1451/1908] Update Changelog for 19.6.0-rc.3 --- changelog.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/changelog.txt b/changelog.txt index 81b6ff9d15db79..ad860707a261f7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,25 @@ == Changelog == += 19.6.0-rc.3 = + + +## Changelog + +### Bug Fixes + +#### Block Editor +- Post Editor: Set the default value of the editorTool to edit. ([66636](https://github.com/WordPress/gutenberg/pull/66636)) + + + + +## Contributors + +The following contributors merged PRs in this release: + +@arthur791004 + + = 19.5.1 = From 33c3bb7b9afbd1996e0dc05eec9bbec87b25f6e3 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Fri, 1 Nov 2024 10:22:42 -0700 Subject: [PATCH 1452/1908] Optimize `getVisibleElementBounds` in scrollable cases (#66546) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/block-editor/src/utils/dom.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/utils/dom.js b/packages/block-editor/src/utils/dom.js index 0603e9bbb1db96..e30f809e387797 100644 --- a/packages/block-editor/src/utils/dom.js +++ b/packages/block-editor/src/utils/dom.js @@ -162,15 +162,14 @@ export function getVisibleElementBounds( element ) { let currentElement; while ( ( currentElement = stack.pop() ) ) { - for ( const child of currentElement.children ) { - if ( isElementVisible( child ) ) { - let childBounds = child.getBoundingClientRect(); - // If the parent is scrollable, use parent's scrollable bounds. - if ( isScrollable( currentElement ) ) { - childBounds = currentElement.getBoundingClientRect(); + // Children won’t affect bounds unless the element is not scrollable. + if ( ! isScrollable( currentElement ) ) { + for ( const child of currentElement.children ) { + if ( isElementVisible( child ) ) { + const childBounds = child.getBoundingClientRect(); + bounds = rectUnion( bounds, childBounds ); + stack.push( child ); } - bounds = rectUnion( bounds, childBounds ); - stack.push( child ); } } } From d2157ff77396fb9a725d205975bb58922c818c05 Mon Sep 17 00:00:00 2001 From: Ben Harris <ben@tilde.team> Date: Fri, 1 Nov 2024 14:49:06 -0400 Subject: [PATCH 1453/1908] Fix unset array key warning in block-bindings.php (#66337) * Fix unset array key warning in block-bindings.php This has been throwing an error for several weeks on one of my sites Simplest fix is to just bail early if it's unset PHP Warning: Undefined array key "show_in_rest" in /var/www/wp-content/plugins/gutenberg/lib/compat/wordpress-6.7/block-bindings.php on line 70 * Update block-bindings.php Co-authored-by: benharri <benharri@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- lib/compat/wordpress-6.7/block-bindings.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/compat/wordpress-6.7/block-bindings.php b/lib/compat/wordpress-6.7/block-bindings.php index 70ba523ac966ea..3cecb7fbc0985c 100644 --- a/lib/compat/wordpress-6.7/block-bindings.php +++ b/lib/compat/wordpress-6.7/block-bindings.php @@ -56,6 +56,11 @@ function gutenberg_update_meta_args_with_label( $args ) { return $args; } + // Don't update schema if not exposed to REST + if ( ! isset( $args['show_in_rest'] ) ) { + return $args; + } + $schema = array( 'title' => $args['label'] ); if ( ! is_array( $args['show_in_rest'] ) ) { $args['show_in_rest'] = array( From 49c3bf9b8791546231826feeff8681ed3d9ab153 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Sat, 2 Nov 2024 06:52:57 +0900 Subject: [PATCH 1454/1908] FormTokenField: Fix token styles (#66640) * FormTokenField: Fix token styles * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/form-token-field/style.scss | 20 ++++++++----------- .../components/src/form-token-field/token.tsx | 1 + 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 4b0da1d669ece2..93b191bff269d6 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -12,6 +12,7 @@ - `Guide`: Use small size button for page controls ([#66607](https://github.com/WordPress/gutenberg/pull/66607)). - `PaletteEdit`: Add appropriate size props to Buttons ([#66590](https://github.com/WordPress/gutenberg/pull/66590)). - `Notice`: Add appropriate size props to Buttons ([#66593](https://github.com/WordPress/gutenberg/pull/66593)). +- `FormTokenField`: Fix token styles ([#66640](https://github.com/WordPress/gutenberg/pull/66640)). ### Internal diff --git a/packages/components/src/form-token-field/style.scss b/packages/components/src/form-token-field/style.scss index 51f9e24ea0d4f2..d18ca274d76764 100644 --- a/packages/components/src/form-token-field/style.scss +++ b/packages/components/src/form-token-field/style.scss @@ -81,7 +81,12 @@ .components-form-token-field__token-text { background: transparent; - color: $components-color-accent; + } + + &:not(.is-disabled) { + .components-form-token-field__token-text { + color: $components-color-accent; + } } .components-form-token-field__remove-token { @@ -90,7 +95,6 @@ position: absolute; top: 1px; right: 0; - padding: 0; } &.is-success { @@ -112,18 +116,11 @@ } } } - - &.is-disabled { - .components-form-token-field__remove-token { - cursor: default; - } - } } .components-form-token-field__token-text, .components-form-token-field__remove-token.components-button { display: inline-block; - line-height: 24px; height: auto; background: $gray-300; min-width: unset; @@ -134,20 +131,19 @@ .components-form-token-field__token-text { border-radius: $radius-x-small 0 0 $radius-x-small; padding: 0 0 0 8px; + line-height: 24px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .components-form-token-field__remove-token.components-button { - cursor: pointer; border-radius: 0 $radius-x-small $radius-x-small 0; - padding: 0 2px; color: $gray-900; line-height: 10px; overflow: initial; - &:hover { + &:hover:not(:disabled) { color: $gray-900; } } diff --git a/packages/components/src/form-token-field/token.tsx b/packages/components/src/form-token-field/token.tsx index 3e723c2bd78fc2..0cfa14cc3e0218 100644 --- a/packages/components/src/form-token-field/token.tsx +++ b/packages/components/src/form-token-field/token.tsx @@ -72,6 +72,7 @@ export default function Token( { <Button className="components-form-token-field__remove-token" + size="small" icon={ closeSmall } onClick={ ! disabled ? onClick : undefined } // Disable reason: Even when FormTokenField itself is accessibly disabled, token reset buttons shouldn't be in the tab sequence. From 48341a13f7ca383830fecc328b3e7e3131ba831a Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Mon, 4 Nov 2024 10:11:12 +1100 Subject: [PATCH 1455/1908] Typography: Stabilize typography block supports within block processing (#63401) * Try stabilizing typography block supports within block processing * Update test * Try PHP equivalent * Add backport changelog entry * Update so that writingMode is not stabilized * Add tests for the PHP implementation * Alphabetize * Move the PHP transformation to the compat directory so that it can be removed once 6.7 is the required minimum version * Update filter priority * Update phpunit/block-supports/typography-test.php Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> * Update phpunit/block-supports/typography-test.php Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> * Update phpunit/block-supports/typography-test.php Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> * Update phpunit/block-supports/typography-test.php Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> * Perform transformation a second time after applying filters * Move to 6.8 directory --------- Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: justintadlock <greenshady@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- backport-changelog/6.8/7069.md | 3 + lib/block-supports/typography.php | 24 +- lib/compat/wordpress-6.8/blocks.php | 47 +++ lib/load.php | 1 + .../block-editor/src/hooks/font-family.js | 2 +- packages/block-editor/src/hooks/supports.js | 12 +- packages/block-editor/src/hooks/typography.js | 10 +- packages/blocks/src/api/constants.js | 21 +- .../blocks/src/store/process-block-type.js | 82 +++-- .../src/store/test/private-selectors.js | 12 +- .../src/store/test/process-block-type.js | 304 ++++++++++++++++++ phpunit/block-supports/typography-test.php | 105 ++++++ 12 files changed, 565 insertions(+), 58 deletions(-) create mode 100644 backport-changelog/6.8/7069.md create mode 100644 lib/compat/wordpress-6.8/blocks.php create mode 100644 packages/blocks/src/store/test/process-block-type.js diff --git a/backport-changelog/6.8/7069.md b/backport-changelog/6.8/7069.md new file mode 100644 index 00000000000000..ea3c717ec3c93a --- /dev/null +++ b/backport-changelog/6.8/7069.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7069 + +* https://github.com/WordPress/gutenberg/pull/63401 diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index a4719b7bdd4099..21086b94f15c1a 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -20,16 +20,16 @@ function gutenberg_register_typography_support( $block_type ) { return; } - $has_font_family_support = $typography_supports['__experimentalFontFamily'] ?? false; + $has_font_family_support = $typography_supports['fontFamily'] ?? false; $has_font_size_support = $typography_supports['fontSize'] ?? false; - $has_font_style_support = $typography_supports['__experimentalFontStyle'] ?? false; - $has_font_weight_support = $typography_supports['__experimentalFontWeight'] ?? false; - $has_letter_spacing_support = $typography_supports['__experimentalLetterSpacing'] ?? false; + $has_font_style_support = $typography_supports['fontStyle'] ?? false; + $has_font_weight_support = $typography_supports['fontWeight'] ?? false; + $has_letter_spacing_support = $typography_supports['letterSpacing'] ?? false; $has_line_height_support = $typography_supports['lineHeight'] ?? false; $has_text_align_support = $typography_supports['textAlign'] ?? false; $has_text_columns_support = $typography_supports['textColumns'] ?? false; - $has_text_decoration_support = $typography_supports['__experimentalTextDecoration'] ?? false; - $has_text_transform_support = $typography_supports['__experimentalTextTransform'] ?? false; + $has_text_decoration_support = $typography_supports['textDecoration'] ?? false; + $has_text_transform_support = $typography_supports['textTransform'] ?? false; $has_writing_mode_support = $typography_supports['__experimentalWritingMode'] ?? false; $has_typography_support = $has_font_family_support @@ -91,16 +91,16 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) { return array(); } - $has_font_family_support = $typography_supports['__experimentalFontFamily'] ?? false; + $has_font_family_support = $typography_supports['fontFamily'] ?? false; $has_font_size_support = $typography_supports['fontSize'] ?? false; - $has_font_style_support = $typography_supports['__experimentalFontStyle'] ?? false; - $has_font_weight_support = $typography_supports['__experimentalFontWeight'] ?? false; - $has_letter_spacing_support = $typography_supports['__experimentalLetterSpacing'] ?? false; + $has_font_style_support = $typography_supports['fontStyle'] ?? false; + $has_font_weight_support = $typography_supports['fontWeight'] ?? false; + $has_letter_spacing_support = $typography_supports['letterSpacing'] ?? false; $has_line_height_support = $typography_supports['lineHeight'] ?? false; $has_text_align_support = $typography_supports['textAlign'] ?? false; $has_text_columns_support = $typography_supports['textColumns'] ?? false; - $has_text_decoration_support = $typography_supports['__experimentalTextDecoration'] ?? false; - $has_text_transform_support = $typography_supports['__experimentalTextTransform'] ?? false; + $has_text_decoration_support = $typography_supports['textDecoration'] ?? false; + $has_text_transform_support = $typography_supports['textTransform'] ?? false; $has_writing_mode_support = $typography_supports['__experimentalWritingMode'] ?? false; // Whether to skip individual block support features. diff --git a/lib/compat/wordpress-6.8/blocks.php b/lib/compat/wordpress-6.8/blocks.php new file mode 100644 index 00000000000000..3124dd2a12a615 --- /dev/null +++ b/lib/compat/wordpress-6.8/blocks.php @@ -0,0 +1,47 @@ +<?php +/** + * Temporary compatibility shims for block APIs present in Gutenberg. + * + * @package gutenberg + */ + +/** + * Filters the block type arguments during registration to stabilize experimental block supports. + * + * This is a temporary compatibility shim as the approach in core is for this to be handled + * within the WP_Block_Type class rather than requiring a filter. + * + * @param array $args Array of arguments for registering a block type. + * @return array Array of arguments for registering a block type. + */ +function gutenberg_stabilize_experimental_block_supports( $args ) { + if ( empty( $args['supports']['typography'] ) ) { + return $args; + } + + $experimental_typography_supports_to_stable = array( + '__experimentalFontFamily' => 'fontFamily', + '__experimentalFontStyle' => 'fontStyle', + '__experimentalFontWeight' => 'fontWeight', + '__experimentalLetterSpacing' => 'letterSpacing', + '__experimentalTextDecoration' => 'textDecoration', + '__experimentalTextTransform' => 'textTransform', + ); + + $current_typography_supports = $args['supports']['typography']; + $stable_typography_supports = array(); + + foreach ( $current_typography_supports as $key => $value ) { + if ( array_key_exists( $key, $experimental_typography_supports_to_stable ) ) { + $stable_typography_supports[ $experimental_typography_supports_to_stable[ $key ] ] = $value; + } else { + $stable_typography_supports[ $key ] = $value; + } + } + + $args['supports']['typography'] = $stable_typography_supports; + + return $args; +} + +add_filter( 'register_block_type_args', 'gutenberg_stabilize_experimental_block_supports', PHP_INT_MAX, 1 ); diff --git a/lib/load.php b/lib/load.php index 0540d4cd9efac7..6236f0eb04b3c6 100644 --- a/lib/load.php +++ b/lib/load.php @@ -118,6 +118,7 @@ function gutenberg_is_experiment_enabled( $name ) { // WordPress 6.8 compat. require __DIR__ . '/compat/wordpress-6.8/preload.php'; +require __DIR__ . '/compat/wordpress-6.8/blocks.php'; // Experimental features. require __DIR__ . '/experimental/block-editor-settings-mobile.php'; diff --git a/packages/block-editor/src/hooks/font-family.js b/packages/block-editor/src/hooks/font-family.js index ba9a66a8bcf04f..e5d8e02ab8ec02 100644 --- a/packages/block-editor/src/hooks/font-family.js +++ b/packages/block-editor/src/hooks/font-family.js @@ -13,7 +13,7 @@ import { shouldSkipSerialization } from './utils'; import { TYPOGRAPHY_SUPPORT_KEY } from './typography'; import { unlock } from '../lock-unlock'; -export const FONT_FAMILY_SUPPORT_KEY = 'typography.__experimentalFontFamily'; +export const FONT_FAMILY_SUPPORT_KEY = 'typography.fontFamily'; const { kebabCase } = unlock( componentsPrivateApis ); /** diff --git a/packages/block-editor/src/hooks/supports.js b/packages/block-editor/src/hooks/supports.js index 75f2bdf2dc219e..c0b6bb2cc8b271 100644 --- a/packages/block-editor/src/hooks/supports.js +++ b/packages/block-editor/src/hooks/supports.js @@ -9,17 +9,17 @@ const ALIGN_WIDE_SUPPORT_KEY = 'alignWide'; const BORDER_SUPPORT_KEY = '__experimentalBorder'; const COLOR_SUPPORT_KEY = 'color'; const CUSTOM_CLASS_NAME_SUPPORT_KEY = 'customClassName'; -const FONT_FAMILY_SUPPORT_KEY = 'typography.__experimentalFontFamily'; +const FONT_FAMILY_SUPPORT_KEY = 'typography.fontFamily'; const FONT_SIZE_SUPPORT_KEY = 'typography.fontSize'; const LINE_HEIGHT_SUPPORT_KEY = 'typography.lineHeight'; /** * Key within block settings' support array indicating support for font style. */ -const FONT_STYLE_SUPPORT_KEY = 'typography.__experimentalFontStyle'; +const FONT_STYLE_SUPPORT_KEY = 'typography.fontStyle'; /** * Key within block settings' support array indicating support for font weight. */ -const FONT_WEIGHT_SUPPORT_KEY = 'typography.__experimentalFontWeight'; +const FONT_WEIGHT_SUPPORT_KEY = 'typography.fontWeight'; /** * Key within block settings' supports array indicating support for text * align e.g. settings found in `block.json`. @@ -34,7 +34,7 @@ const TEXT_COLUMNS_SUPPORT_KEY = 'typography.textColumns'; * Key within block settings' supports array indicating support for text * decorations e.g. settings found in `block.json`. */ -const TEXT_DECORATION_SUPPORT_KEY = 'typography.__experimentalTextDecoration'; +const TEXT_DECORATION_SUPPORT_KEY = 'typography.textDecoration'; /** * Key within block settings' supports array indicating support for writing mode * e.g. settings found in `block.json`. @@ -44,13 +44,13 @@ const WRITING_MODE_SUPPORT_KEY = 'typography.__experimentalWritingMode'; * Key within block settings' supports array indicating support for text * transforms e.g. settings found in `block.json`. */ -const TEXT_TRANSFORM_SUPPORT_KEY = 'typography.__experimentalTextTransform'; +const TEXT_TRANSFORM_SUPPORT_KEY = 'typography.textTransform'; /** * Key within block settings' supports array indicating support for letter-spacing * e.g. settings found in `block.json`. */ -const LETTER_SPACING_SUPPORT_KEY = 'typography.__experimentalLetterSpacing'; +const LETTER_SPACING_SUPPORT_KEY = 'typography.letterSpacing'; const LAYOUT_SUPPORT_KEY = 'layout'; const TYPOGRAPHY_SUPPORT_KEYS = [ LINE_HEIGHT_SUPPORT_KEY, diff --git a/packages/block-editor/src/hooks/typography.js b/packages/block-editor/src/hooks/typography.js index cf3f4327c8f034..ab9a464fe5efbc 100644 --- a/packages/block-editor/src/hooks/typography.js +++ b/packages/block-editor/src/hooks/typography.js @@ -27,12 +27,12 @@ function omit( object, keys ) { ); } -const LETTER_SPACING_SUPPORT_KEY = 'typography.__experimentalLetterSpacing'; -const TEXT_TRANSFORM_SUPPORT_KEY = 'typography.__experimentalTextTransform'; -const TEXT_DECORATION_SUPPORT_KEY = 'typography.__experimentalTextDecoration'; +const LETTER_SPACING_SUPPORT_KEY = 'typography.letterSpacing'; +const TEXT_TRANSFORM_SUPPORT_KEY = 'typography.textTransform'; +const TEXT_DECORATION_SUPPORT_KEY = 'typography.textDecoration'; const TEXT_COLUMNS_SUPPORT_KEY = 'typography.textColumns'; -const FONT_STYLE_SUPPORT_KEY = 'typography.__experimentalFontStyle'; -const FONT_WEIGHT_SUPPORT_KEY = 'typography.__experimentalFontWeight'; +const FONT_STYLE_SUPPORT_KEY = 'typography.fontStyle'; +const FONT_WEIGHT_SUPPORT_KEY = 'typography.fontWeight'; const WRITING_MODE_SUPPORT_KEY = 'typography.__experimentalWritingMode'; export const TYPOGRAPHY_SUPPORT_KEY = 'typography'; export const TYPOGRAPHY_SUPPORT_KEYS = [ diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js index 620dfcbb8599c0..85a359af754db8 100644 --- a/packages/blocks/src/api/constants.js +++ b/packages/blocks/src/api/constants.js @@ -183,7 +183,7 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = { }, fontFamily: { value: [ 'typography', 'fontFamily' ], - support: [ 'typography', '__experimentalFontFamily' ], + support: [ 'typography', 'fontFamily' ], useEngine: true, }, fontSize: { @@ -193,12 +193,12 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = { }, fontStyle: { value: [ 'typography', 'fontStyle' ], - support: [ 'typography', '__experimentalFontStyle' ], + support: [ 'typography', 'fontStyle' ], useEngine: true, }, fontWeight: { value: [ 'typography', 'fontWeight' ], - support: [ 'typography', '__experimentalFontWeight' ], + support: [ 'typography', 'fontWeight' ], useEngine: true, }, lineHeight: { @@ -240,17 +240,17 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = { }, textDecoration: { value: [ 'typography', 'textDecoration' ], - support: [ 'typography', '__experimentalTextDecoration' ], + support: [ 'typography', 'textDecoration' ], useEngine: true, }, textTransform: { value: [ 'typography', 'textTransform' ], - support: [ 'typography', '__experimentalTextTransform' ], + support: [ 'typography', 'textTransform' ], useEngine: true, }, letterSpacing: { value: [ 'typography', 'letterSpacing' ], - support: [ 'typography', '__experimentalLetterSpacing' ], + support: [ 'typography', 'letterSpacing' ], useEngine: true, }, writingMode: { @@ -297,3 +297,12 @@ export const __EXPERIMENTAL_PATHS_WITH_OVERRIDE = { 'typography.fontSizes': true, 'spacing.spacingSizes': true, }; + +export const TYPOGRAPHY_SUPPORTS_EXPERIMENTAL_TO_STABLE = { + __experimentalFontFamily: 'fontFamily', + __experimentalFontStyle: 'fontStyle', + __experimentalFontWeight: 'fontWeight', + __experimentalLetterSpacing: 'letterSpacing', + __experimentalTextDecoration: 'textDecoration', + __experimentalTextTransform: 'textTransform', +}; diff --git a/packages/blocks/src/store/process-block-type.js b/packages/blocks/src/store/process-block-type.js index bc7b1a0e10e774..8e5b7962adfe17 100644 --- a/packages/blocks/src/store/process-block-type.js +++ b/packages/blocks/src/store/process-block-type.js @@ -15,7 +15,11 @@ import warning from '@wordpress/warning'; * Internal dependencies */ import { isValidIcon, normalizeIconObject, omit } from '../api/utils'; -import { BLOCK_ICON_DEFAULT, DEPRECATED_ENTRY_KEYS } from '../api/constants'; +import { + BLOCK_ICON_DEFAULT, + DEPRECATED_ENTRY_KEYS, + TYPOGRAPHY_SUPPORTS_EXPERIMENTAL_TO_STABLE, +} from '../api/constants'; /** @typedef {import('../api/registration').WPBlockType} WPBlockType */ @@ -62,6 +66,24 @@ function mergeBlockVariations( return result; } +function stabilizeSupports( rawSupports ) { + if ( ! rawSupports ) { + return rawSupports; + } + + const supports = { ...rawSupports }; + if ( supports?.typography && typeof supports.typography === 'object' ) { + supports.typography = Object.fromEntries( + Object.entries( supports.typography ).map( ( [ key, value ] ) => [ + TYPOGRAPHY_SUPPORTS_EXPERIMENTAL_TO_STABLE[ key ] || key, + value, + ] ) + ); + } + + return supports; +} + /** * Takes the unprocessed block type settings, merges them with block type metadata * and applies all the existing filters for the registered block type. @@ -102,6 +124,9 @@ export const processBlockType = ), }; + // Stabilize any experimental supports before applying filters. + blockType.supports = stabilizeSupports( blockType.supports ); + const settings = applyFilters( 'blocks.registerBlockType', blockType, @@ -109,6 +134,10 @@ export const processBlockType = null ); + // Re-stabilize any experimental supports after applying filters. + // This ensures that any supports updated by filters are also stabilized. + blockType.supports = stabilizeSupports( blockType.supports ); + if ( settings.description && typeof settings.description !== 'string' @@ -119,29 +148,38 @@ export const processBlockType = } if ( settings.deprecated ) { - settings.deprecated = settings.deprecated.map( ( deprecation ) => - Object.fromEntries( - Object.entries( - // Only keep valid deprecation keys. - applyFilters( - 'blocks.registerBlockType', - // Merge deprecation keys with pre-filter settings - // so that filters that depend on specific keys being - // present don't fail. - { - // Omit deprecation keys here so that deprecations - // can opt out of specific keys like "supports". - ...omit( blockType, DEPRECATED_ENTRY_KEYS ), - ...deprecation, - }, - blockType.name, - deprecation - ) - ).filter( ( [ key ] ) => + settings.deprecated = settings.deprecated.map( ( deprecation ) => { + // Stabilize any experimental supports before applying filters. + deprecation.supports = stabilizeSupports( + deprecation.supports + ); + const filteredDeprecation = // Only keep valid deprecation keys. + applyFilters( + 'blocks.registerBlockType', + // Merge deprecation keys with pre-filter settings + // so that filters that depend on specific keys being + // present don't fail. + { + // Omit deprecation keys here so that deprecations + // can opt out of specific keys like "supports". + ...omit( blockType, DEPRECATED_ENTRY_KEYS ), + ...deprecation, + }, + blockType.name, + deprecation + ); + // Re-stabilize any experimental supports after applying filters. + // This ensures that any supports updated by filters are also stabilized. + filteredDeprecation.supports = stabilizeSupports( + filteredDeprecation.supports + ); + + return Object.fromEntries( + Object.entries( filteredDeprecation ).filter( ( [ key ] ) => DEPRECATED_ENTRY_KEYS.includes( key ) ) - ) - ); + ); + } ); } if ( ! isPlainObject( settings ) ) { diff --git a/packages/blocks/src/store/test/private-selectors.js b/packages/blocks/src/store/test/private-selectors.js index ada2bd7c8cbcfe..2c173b96b0bcb1 100644 --- a/packages/blocks/src/store/test/private-selectors.js +++ b/packages/blocks/src/store/test/private-selectors.js @@ -127,12 +127,12 @@ describe( 'private selectors', () => { name: 'core/example-block', supports: { typography: { - __experimentalFontFamily: true, - __experimentalFontStyle: true, - __experimentalFontWeight: true, - __experimentalTextDecoration: true, - __experimentalTextTransform: true, - __experimentalLetterSpacing: true, + fontFamily: true, + fontStyle: true, + fontWeight: true, + textDecoration: true, + textTransform: true, + letterSpacing: true, fontSize: true, lineHeight: true, }, diff --git a/packages/blocks/src/store/test/process-block-type.js b/packages/blocks/src/store/test/process-block-type.js new file mode 100644 index 00000000000000..3c6838e311f778 --- /dev/null +++ b/packages/blocks/src/store/test/process-block-type.js @@ -0,0 +1,304 @@ +/** + * WordPress dependencies + */ +import { addFilter, removeFilter } from '@wordpress/hooks'; + +/** + * Internal dependencies + */ +import { processBlockType } from '../process-block-type'; + +describe( 'processBlockType', () => { + const baseBlockSettings = { + apiVersion: 3, + attributes: {}, + edit: () => null, + name: 'test/block', + save: () => null, + title: 'Test Block', + }; + + const select = { + getBootstrappedBlockType: () => null, + }; + + afterEach( () => { + removeFilter( 'blocks.registerBlockType', 'test/filterSupports' ); + } ); + + it( 'should return the block type with stabilized typography supports', () => { + const blockSettings = { + ...baseBlockSettings, + supports: { + typography: { + fontSize: true, + lineHeight: true, + __experimentalFontFamily: true, + __experimentalFontStyle: true, + __experimentalFontWeight: true, + __experimentalLetterSpacing: true, + __experimentalTextTransform: true, + __experimentalTextDecoration: true, + __experimentalWritingMode: true, + __experimentalDefaultControls: { + fontSize: true, + fontAppearance: true, + textTransform: true, + }, + }, + }, + }; + + const processedBlockType = processBlockType( + 'test/block', + blockSettings + )( { select } ); + + expect( processedBlockType.supports.typography ).toEqual( { + fontSize: true, + lineHeight: true, + fontFamily: true, + fontStyle: true, + fontWeight: true, + letterSpacing: true, + textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + __experimentalDefaultControls: { + fontSize: true, + fontAppearance: true, + textTransform: true, + }, + } ); + } ); + + it( 'should return the block type with stable typography supports', () => { + const blockSettings = { + ...baseBlockSettings, + supports: { + typography: { + fontSize: true, + lineHeight: true, + fontFamily: true, + fontStyle: true, + fontWeight: true, + letterSpacing: true, + textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + __experimentalDefaultControls: { + fontSize: true, + fontAppearance: true, + textTransform: true, + }, + }, + }, + }; + + const processedBlockType = processBlockType( + 'test/block', + blockSettings + )( { select } ); + + expect( processedBlockType.supports.typography ).toEqual( { + fontSize: true, + lineHeight: true, + fontFamily: true, + fontStyle: true, + fontWeight: true, + letterSpacing: true, + textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + __experimentalDefaultControls: { + fontSize: true, + fontAppearance: true, + textTransform: true, + }, + } ); + } ); + + it( 'should reapply transformations after supports are filtered', () => { + const blockSettings = { + ...baseBlockSettings, + supports: { + typography: { + fontSize: true, + lineHeight: true, + __experimentalFontFamily: true, + __experimentalFontStyle: true, + __experimentalFontWeight: true, + __experimentalLetterSpacing: true, + __experimentalTextTransform: true, + __experimentalTextDecoration: true, + __experimentalWritingMode: true, + __experimentalDefaultControls: { + fontSize: true, + fontAppearance: true, + textTransform: true, + }, + }, + }, + }; + + addFilter( + 'blocks.registerBlockType', + 'test/filterSupports', + ( settings, name ) => { + if ( name === 'test/block' && settings.supports.typography ) { + settings.supports.typography.__experimentalFontFamily = false; + settings.supports.typography.__experimentalFontStyle = false; + settings.supports.typography.__experimentalFontWeight = false; + } + return settings; + } + ); + + const processedBlockType = processBlockType( + 'test/block', + blockSettings + )( { select } ); + + expect( processedBlockType.supports.typography ).toEqual( { + fontSize: true, + lineHeight: true, + fontFamily: false, + fontStyle: false, + fontWeight: false, + letterSpacing: true, + textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + __experimentalDefaultControls: { + fontSize: true, + fontAppearance: true, + textTransform: true, + }, + } ); + } ); + + it( 'should stabilize experimental typography supports within block deprecations', () => { + const blockSettings = { + ...baseBlockSettings, + supports: { + typography: { + fontSize: true, + lineHeight: true, + fontFamily: true, + fontStyle: true, + fontWeight: true, + letterSpacing: true, + textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + __experimentalDefaultControls: { + fontSize: true, + fontAppearance: true, + textTransform: true, + }, + }, + }, + deprecated: [ + { + supports: { + typography: { + __experimentalFontFamily: true, + __experimentalFontStyle: true, + __experimentalFontWeight: true, + __experimentalLetterSpacing: true, + __experimentalTextTransform: true, + __experimentalTextDecoration: true, + __experimentalWritingMode: true, + }, + }, + }, + ], + }; + + const processedBlockType = processBlockType( + 'test/block', + blockSettings + )( { select } ); + + expect( + processedBlockType.deprecated[ 0 ].supports.typography + ).toEqual( { + fontFamily: true, + fontStyle: true, + fontWeight: true, + letterSpacing: true, + textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + } ); + } ); + + it( 'should reapply transformations after supports are filtered within block deprecations', () => { + const blockSettings = { + ...baseBlockSettings, + supports: { + typography: { + fontSize: true, + lineHeight: true, + fontFamily: true, + fontStyle: true, + fontWeight: true, + letterSpacing: true, + textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + __experimentalDefaultControls: { + fontSize: true, + fontAppearance: true, + textTransform: true, + }, + }, + }, + deprecated: [ + { + supports: { + typography: { + __experimentalFontFamily: true, + __experimentalFontStyle: true, + __experimentalFontWeight: true, + __experimentalLetterSpacing: true, + __experimentalTextTransform: true, + __experimentalTextDecoration: true, + __experimentalWritingMode: true, + }, + }, + }, + ], + }; + + addFilter( + 'blocks.registerBlockType', + 'test/filterSupports', + ( settings, name ) => { + if ( name === 'test/block' && settings.supports.typography ) { + settings.supports.typography.__experimentalFontFamily = false; + settings.supports.typography.__experimentalFontStyle = false; + settings.supports.typography.__experimentalFontWeight = false; + } + return settings; + } + ); + + const processedBlockType = processBlockType( + 'test/block', + blockSettings + )( { select } ); + + expect( + processedBlockType.deprecated[ 0 ].supports.typography + ).toEqual( { + fontFamily: false, + fontStyle: false, + fontWeight: false, + letterSpacing: true, + textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + } ); + } ); +} ); diff --git a/phpunit/block-supports/typography-test.php b/phpunit/block-supports/typography-test.php index eafd505db6ec65..1804659c11af3c 100644 --- a/phpunit/block-supports/typography-test.php +++ b/phpunit/block-supports/typography-test.php @@ -283,6 +283,111 @@ public function test_should_generate_classname_for_font_family() { $this->assertSame( $expected, $actual ); } + /** + * Tests that stabilized typography supports will also apply to blocks using + * the experimental syntax, for backwards compatibility with existing blocks. + * + * @covers ::gutenberg_apply_typography_support + */ + public function test_should_apply_experimental_typography_supports() { + $this->test_block_name = 'test/experimental-typography-supports'; + register_block_type( + $this->test_block_name, + array( + 'api_version' => 3, + 'attributes' => array( + 'style' => array( + 'type' => 'object', + ), + ), + 'supports' => array( + 'typography' => array( + '__experimentalFontFamily' => true, + '__experimentalFontStyle' => true, + '__experimentalFontWeight' => true, + '__experimentalLetterSpacing' => true, + '__experimentalTextDecoration' => true, + '__experimentalTextTransform' => true, + ), + ), + ) + ); + $registry = WP_Block_Type_Registry::get_instance(); + $block_type = $registry->get_registered( $this->test_block_name ); + $block_atts = array( + 'fontFamily' => 'serif', + 'style' => array( + 'typography' => array( + 'fontStyle' => 'italic', + 'fontWeight' => 'bold', + 'letterSpacing' => '1px', + 'textDecoration' => 'underline', + 'textTransform' => 'uppercase', + ), + ), + ); + + $actual = gutenberg_apply_typography_support( $block_type, $block_atts ); + $expected = array( + 'class' => 'has-serif-font-family', + 'style' => 'font-style:italic;font-weight:bold;text-decoration:underline;text-transform:uppercase;letter-spacing:1px;', + ); + + $this->assertSame( $expected, $actual ); + } + + /** + * Tests that stabilized typography supports are applied correctly. + * + * @covers ::gutenberg_apply_typography_support + */ + public function test_should_apply_stabilized_typography_supports() { + $this->test_block_name = 'test/experimental-typography-supports'; + register_block_type( + $this->test_block_name, + array( + 'api_version' => 3, + 'attributes' => array( + 'style' => array( + 'type' => 'object', + ), + ), + 'supports' => array( + 'typography' => array( + 'fontFamily' => true, + 'fontStyle' => true, + 'fontWeight' => true, + 'letterSpacing' => true, + 'textDecoration' => true, + 'textTransform' => true, + ), + ), + ) + ); + $registry = WP_Block_Type_Registry::get_instance(); + $block_type = $registry->get_registered( $this->test_block_name ); + $block_atts = array( + 'fontFamily' => 'serif', + 'style' => array( + 'typography' => array( + 'fontStyle' => 'italic', + 'fontWeight' => 'bold', + 'letterSpacing' => '1px', + 'textDecoration' => 'underline', + 'textTransform' => 'uppercase', + ), + ), + ); + + $actual = gutenberg_apply_typography_support( $block_type, $block_atts ); + $expected = array( + 'class' => 'has-serif-font-family', + 'style' => 'font-style:italic;font-weight:bold;text-decoration:underline;text-transform:uppercase;letter-spacing:1px;', + ); + + $this->assertSame( $expected, $actual ); + } + /** * Tests generating font size values, including fluid formulae, from fontSizes preset. * From 4e6bd4dbe1f07a2f17b685c697f05db7f697f72d Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Mon, 4 Nov 2024 13:25:47 +1100 Subject: [PATCH 1456/1908] Theme JSON Resolver: remove theme json merge in resolve_theme_file_uris (#66662) Removes unnecessary merge. We're only setting values for paths. Add a Backport log. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- backport-changelog/6.8/7698.md | 3 +++ lib/class-wp-theme-json-resolver-gutenberg.php | 8 ++------ 2 files changed, 5 insertions(+), 6 deletions(-) create mode 100644 backport-changelog/6.8/7698.md diff --git a/backport-changelog/6.8/7698.md b/backport-changelog/6.8/7698.md new file mode 100644 index 00000000000000..3ded160e7ec449 --- /dev/null +++ b/backport-changelog/6.8/7698.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7698 + +* https://github.com/WordPress/gutenberg/pull/66662 diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php index 2231cb0f11538f..cd02b5a45c22f7 100644 --- a/lib/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/class-wp-theme-json-resolver-gutenberg.php @@ -920,18 +920,14 @@ public static function resolve_theme_file_uris( $theme_json ) { return $theme_json; } - $resolved_theme_json_data = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - ); + $resolved_theme_json_data = $theme_json->get_raw_data(); foreach ( $resolved_urls as $resolved_url ) { $path = explode( '.', $resolved_url['target'] ); _wp_array_set( $resolved_theme_json_data, $path, $resolved_url['href'] ); } - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $resolved_theme_json_data ) ); - - return $theme_json; + return new WP_Theme_JSON_Gutenberg( $resolved_theme_json_data ); } /** From 03225e0e2b5aa369f402273d3612f1e2e45c9f15 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Mon, 4 Nov 2024 16:02:11 +0900 Subject: [PATCH 1457/1908] Block Inspector: Restore bottm margin for RadioControl (#66688) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: up1512001 <up1512001@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- .../src/components/block-inspector/style.scss | 3 ++- packages/block-library/src/latest-posts/edit.js | 1 - packages/block-library/src/latest-posts/editor.scss | 11 ----------- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/packages/block-editor/src/components/block-inspector/style.scss b/packages/block-editor/src/components/block-inspector/style.scss index e04dfd8e9a480a..dd9d8f254ff76b 100644 --- a/packages/block-editor/src/components/block-inspector/style.scss +++ b/packages/block-editor/src/components/block-inspector/style.scss @@ -10,7 +10,8 @@ margin-bottom: 1.5em; } - .components-base-control { + .components-base-control, + .components-radio-control { &:where(:not(:last-child)) { margin-bottom: $grid-unit-20; } diff --git a/packages/block-library/src/latest-posts/edit.js b/packages/block-library/src/latest-posts/edit.js index 8116b5eecaebf0..82f0661d04e40f 100644 --- a/packages/block-library/src/latest-posts/edit.js +++ b/packages/block-library/src/latest-posts/edit.js @@ -238,7 +238,6 @@ export default function LatestPostsEdit( { attributes, setAttributes } ) { /> { displayPostContent && ( <RadioControl - className="wp-block-latest-posts__post-content-radio" label={ __( 'Show' ) } selected={ displayPostContentRadio } options={ [ diff --git a/packages/block-library/src/latest-posts/editor.scss b/packages/block-library/src/latest-posts/editor.scss index aaab74cc0ef2d6..fe901480974461 100644 --- a/packages/block-library/src/latest-posts/editor.scss +++ b/packages/block-library/src/latest-posts/editor.scss @@ -18,14 +18,3 @@ padding-left: 0; } } - -// Apply the same styles that would be applied to -// ".block-editor-block-inspector .components-base-control" -// (see packages/block-editor/src/components/block-inspector/style.scss) -.wp-block-latest-posts__post-content-radio { - margin-bottom: #{ $grid-unit-30 }; - - &:last-child { - margin-bottom: $grid-unit-10; - } -} From 2a18aae3768da80f94e437c16e8d56e5a9a45e03 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Mon, 4 Nov 2024 10:01:50 +0100 Subject: [PATCH 1458/1908] Site editor: integrate global styles controls and style book preview into the styles panel (#65619) This commit integrates global styles controls and a style book preview into the styles panel. This affects the site editor in view mode. A toggle allows users to switch between previewing the site and the style book while editing global styles. --------- Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../block-editor/use-editor-iframe-props.js | 5 +- .../src/components/global-styles/ui.js | 39 ++++- .../edit-site/src/components/layout/index.js | 7 +- .../sidebar-global-styles-wrapper/index.js | 145 ++++++++++++++++++ .../sidebar-global-styles-wrapper/style.scss | 35 +++++ .../sidebar-navigation-item/style.scss | 4 +- .../index.js | 101 ++---------- .../sidebar-navigation-screen-main/index.js | 91 +++++------ .../edit-site/src/components/sidebar/index.js | 30 +++- .../site-editor-routes/styles-edit.js | 11 +- .../site-editor-routes/styles-view.js | 12 +- .../src/components/style-book/index.js | 76 ++++++++- packages/edit-site/src/style.scss | 1 + 13 files changed, 400 insertions(+), 157 deletions(-) create mode 100644 packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js create mode 100644 packages/edit-site/src/components/sidebar-global-styles-wrapper/style.scss diff --git a/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js b/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js index 46719a00c16aad..7c88fee0d5b727 100644 --- a/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js +++ b/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js @@ -60,11 +60,10 @@ export default function useEditorIframeProps() { } ); } }, - onClick: () => { + onClick: () => history.push( { ...params, canvas: 'edit' }, undefined, { transition: 'canvas-mode-edit-transition', - } ); - }, + } ), onClickCapture: ( event ) => { if ( currentPostIsTrashed ) { event.preventDefault(); diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index 9ca88f40f1f001..2edea0fdbc3da3 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -19,7 +19,8 @@ import { __ } from '@wordpress/i18n'; import { store as preferencesStore } from '@wordpress/preferences'; import { moreVertical } from '@wordpress/icons'; import { store as coreStore } from '@wordpress/core-data'; -import { useEffect } from '@wordpress/element'; +import { useEffect, Fragment } from '@wordpress/element'; +import { usePrevious } from '@wordpress/compose'; /** * Internal dependencies @@ -291,18 +292,52 @@ function GlobalStylesEditorCanvasContainerLink() { }, [ editorCanvasContainerView, isRevisionsOpen, goTo ] ); } -function GlobalStylesUI() { +function useNavigatorSync( parentPath, onPathChange ) { + const navigator = useNavigator(); + const { path: childPath } = navigator.location; + const previousParentPath = usePrevious( parentPath ); + const previousChildPath = usePrevious( childPath ); + useEffect( () => { + if ( parentPath !== childPath ) { + if ( parentPath !== previousParentPath ) { + navigator.goTo( parentPath ); + } else if ( childPath !== previousChildPath ) { + onPathChange( childPath ); + } + } + }, [ + onPathChange, + parentPath, + previousChildPath, + previousParentPath, + childPath, + navigator, + ] ); +} + +// This component is used to wrap the hook in order to conditionally execute it +// when the parent component is used on controlled mode. +function NavigationSync( { path: parentPath, onPathChange, children } ) { + useNavigatorSync( parentPath, onPathChange ); + return children; +} + +function GlobalStylesUI( { path, onPathChange } ) { const blocks = getBlockTypes(); const editorCanvasContainerView = useSelect( ( select ) => unlock( select( editSiteStore ) ).getEditorCanvasContainerView(), [] ); + return ( <Navigator className="edit-site-global-styles-sidebar__navigator-provider" initialPath="/" > + { path && onPathChange && ( + <NavigationSync path={ path } onPathChange={ onPathChange } /> + ) } <GlobalStylesNavigationScreen path="/"> <ScreenRoot /> </GlobalStylesNavigationScreen> diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index 551d1448fde5c9..cbc0a4661bf3e7 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -125,7 +125,12 @@ export default function Layout( { route } ) { isResizableFrameOversized } /> - <SidebarContent routeKey={ routeKey }> + <SidebarContent + shouldAnimate={ + routeKey !== 'styles-view' + } + routeKey={ routeKey } + > { areas.sidebar } </SidebarContent> <SaveHub /> diff --git a/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js b/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js new file mode 100644 index 00000000000000..afa9f489dde22b --- /dev/null +++ b/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js @@ -0,0 +1,145 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { useMemo, useState } from '@wordpress/element'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { useViewportMatch } from '@wordpress/compose'; +import { + Button, + privateApis as componentsPrivateApis, +} from '@wordpress/components'; + +/** + * Internal dependencies + */ +import GlobalStylesUI from '../global-styles/ui'; +import Page from '../page'; +import { unlock } from '../../lock-unlock'; +import StyleBook from '../style-book'; +import { STYLE_BOOK_COLOR_GROUPS } from '../style-book/constants'; + +const { useLocation, useHistory } = unlock( routerPrivateApis ); +const { Menu } = unlock( componentsPrivateApis ); +const GLOBAL_STYLES_PATH_PREFIX = '/wp_global_styles'; + +const GlobalStylesPageActions = ( { + isStyleBookOpened, + setIsStyleBookOpened, +} ) => { + return ( + <Menu + trigger={ + <Button __next40pxDefaultSize variant="tertiary" size="compact"> + { __( 'Preview' ) } + </Button> + } + > + <Menu.RadioItem + value + checked={ isStyleBookOpened } + name="styles-preview-actions" + onChange={ () => setIsStyleBookOpened( true ) } + defaultChecked + > + <Menu.ItemLabel>{ __( 'Style book' ) }</Menu.ItemLabel> + <Menu.ItemHelpText> + { __( 'Preview blocks and styles.' ) } + </Menu.ItemHelpText> + </Menu.RadioItem> + <Menu.RadioItem + value={ false } + checked={ ! isStyleBookOpened } + name="styles-preview-actions" + onChange={ () => setIsStyleBookOpened( false ) } + > + <Menu.ItemLabel>{ __( 'Site' ) }</Menu.ItemLabel> + <Menu.ItemHelpText> + { __( 'Preview your site.' ) } + </Menu.ItemHelpText> + </Menu.RadioItem> + </Menu> + ); +}; + +export default function GlobalStylesUIWrapper() { + const { params } = useLocation(); + const history = useHistory(); + const { canvas = 'view' } = params; + const [ isStyleBookOpened, setIsStyleBookOpened ] = useState( false ); + const isMobileViewport = useViewportMatch( 'medium', '<' ); + const pathWithPrefix = params.path; + const [ path, onPathChange ] = useMemo( () => { + const processedPath = pathWithPrefix.substring( + GLOBAL_STYLES_PATH_PREFIX.length + ); + return [ + processedPath ? processedPath : '/', + ( newPath ) => { + history.push( { + path: + ! newPath || newPath === '/' + ? GLOBAL_STYLES_PATH_PREFIX + : `${ GLOBAL_STYLES_PATH_PREFIX }${ newPath }`, + } ); + }, + ]; + }, [ pathWithPrefix, history ] ); + + return ( + <> + <Page + actions={ + ! isMobileViewport ? ( + <GlobalStylesPageActions + isStyleBookOpened={ isStyleBookOpened } + setIsStyleBookOpened={ setIsStyleBookOpened } + /> + ) : null + } + className="edit-site-styles" + title={ __( 'Styles' ) } + > + <GlobalStylesUI path={ path } onPathChange={ onPathChange } /> + </Page> + { canvas === 'view' && isStyleBookOpened && ( + <StyleBook + enableResizing={ false } + showCloseButton={ false } + showTabs={ false } + isSelected={ ( blockName ) => + // Match '/blocks/core%2Fbutton' and + // '/blocks/core%2Fbutton/typography', but not + // '/blocks/core%2Fbuttons'. + path === + `/wp_global_styles/blocks/${ encodeURIComponent( + blockName + ) }` || + path.startsWith( + `/wp_global_styles/blocks/${ encodeURIComponent( + blockName + ) }/` + ) + } + path={ path } + onSelect={ ( blockName ) => { + if ( + STYLE_BOOK_COLOR_GROUPS.find( + ( group ) => group.slug === blockName + ) + ) { + // Go to color palettes Global Styles. + onPathChange( '/colors/palette' ); + return; + } + + // Now go to the selected block. + onPathChange( + `/blocks/${ encodeURIComponent( blockName ) }` + ); + } } + /> + ) } + </> + ); +} diff --git a/packages/edit-site/src/components/sidebar-global-styles-wrapper/style.scss b/packages/edit-site/src/components/sidebar-global-styles-wrapper/style.scss new file mode 100644 index 00000000000000..88aa9ddf0c1618 --- /dev/null +++ b/packages/edit-site/src/components/sidebar-global-styles-wrapper/style.scss @@ -0,0 +1,35 @@ +.edit-site-styles .edit-site-page-content { + .edit-site-global-styles-screen-root { + box-shadow: none; + & > div > hr { + display: none; + } + } + .edit-site-global-styles-sidebar__navigator-provider { + .components-tools-panel { + border-top: none; + } + overflow-y: auto; + padding-left: 0; + padding-right: 0; + + .edit-site-global-styles-sidebar__navigator-screen { + padding-top: $grid-unit-15; + padding-left: $grid-unit-15; + padding-right: $grid-unit-15; + padding-bottom: $grid-unit-15; + outline: none; + } + } + .edit-site-page-header { + padding-left: $grid-unit-60; + padding-right: $grid-unit-60; + @container (max-width: 430px) { + padding-left: $grid-unit-30; + padding-right: $grid-unit-30; + } + } + .edit-site-sidebar-button { + color: $gray-900; + } +} diff --git a/packages/edit-site/src/components/sidebar-navigation-item/style.scss b/packages/edit-site/src/components/sidebar-navigation-item/style.scss index 016027ef715a45..202de5300076c1 100644 --- a/packages/edit-site/src/components/sidebar-navigation-item/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-item/style.scss @@ -7,7 +7,7 @@ &:hover, &:focus, - &[aria-current] { + &[aria-current="true"] { color: $gray-200; background: $gray-800; @@ -16,7 +16,7 @@ } } - &[aria-current] { + &[aria-current="true"] { background: var(--wp-admin-theme-color); color: $white; } diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js index 6579107a60e55f..3dc93ff4d4df63 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js @@ -2,12 +2,9 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { edit, seen } from '@wordpress/icons'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -import { useViewportMatch } from '@wordpress/compose'; import { useCallback } from '@wordpress/element'; -import { store as editorStore } from '@wordpress/editor'; import { store as preferencesStore } from '@wordpress/preferences'; import { privateApis as routerPrivateApis } from '@wordpress/router'; @@ -17,18 +14,14 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; import SidebarNavigationScreen from '../sidebar-navigation-screen'; import { unlock } from '../../lock-unlock'; import { store as editSiteStore } from '../../store'; -import SidebarButton from '../sidebar-button'; import SidebarNavigationItem from '../sidebar-navigation-item'; -import StyleBook from '../style-book'; import useGlobalStylesRevisions from '../global-styles/screen-revisions/use-global-styles-revisions'; import SidebarNavigationScreenDetailsFooter from '../sidebar-navigation-screen-details-footer'; -import SidebarNavigationScreenGlobalStylesContent from './content'; +import { MainSidebarNavigationContent } from '../sidebar-navigation-screen-main'; const { useLocation, useHistory } = unlock( routerPrivateApis ); export function SidebarNavigationItemGlobalStyles( props ) { - const { openGeneralSidebar } = useDispatch( editSiteStore ); - const history = useHistory(); const { params } = useLocation(); const hasGlobalStyleVariations = useSelect( ( select ) => @@ -43,47 +36,25 @@ export function SidebarNavigationItemGlobalStyles( props ) { { ...props } params={ { path: '/wp_global_styles' } } uid="global-styles-navigation-item" + aria-current={ + params.path && params.path.startsWith( '/wp_global_styles' ) + } /> ); } - return ( - <SidebarNavigationItem - { ...props } - onClick={ () => { - // Switch to edit mode. - history.push( - { - ...params, - canvas: 'edit', - }, - undefined, - { - transition: 'canvas-mode-edit-transition', - } - ); - // Open global styles sidebar. - openGeneralSidebar( 'edit-site/global-styles' ); - } } - /> - ); + return <SidebarNavigationItem { ...props } />; } -export default function SidebarNavigationScreenGlobalStyles( { backPath } ) { +export default function SidebarNavigationScreenGlobalStyles() { const history = useHistory(); const { params } = useLocation(); - const { canvas = 'view' } = params; const { revisions, isLoading: isLoadingRevisions } = useGlobalStylesRevisions(); const { openGeneralSidebar } = useDispatch( editSiteStore ); - const { setIsListViewOpened } = useDispatch( editorStore ); - const isMobileViewport = useViewportMatch( 'medium', '<' ); const { setEditorCanvasContainerView } = unlock( useDispatch( editSiteStore ) ); - const { isStyleBookOpened, revisionsCount } = useSelect( ( select ) => { - const { getEditorCanvasContainerView } = unlock( - select( editSiteStore ) - ); + const { revisionsCount } = useSelect( ( select ) => { const { getEntityRecord, __experimentalGetCurrentGlobalStylesId } = select( coreStore ); const globalStylesId = __experimentalGetCurrentGlobalStylesId(); @@ -91,7 +62,6 @@ export default function SidebarNavigationScreenGlobalStyles( { backPath } ) { ? getEntityRecord( 'root', 'globalStyles', globalStylesId ) : undefined; return { - isStyleBookOpened: 'style-book' === getEditorCanvasContainerView(), revisionsCount: globalStyles?._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0, }; @@ -115,19 +85,6 @@ export default function SidebarNavigationScreenGlobalStyles( { backPath } ) { ] ); }, [ history, params, openGeneralSidebar, setPreference ] ); - const openStyleBook = useCallback( async () => { - await openGlobalStyles(); - // Open the Style Book once the canvas mode is set to edit, - // and the global styles sidebar is open. This ensures that - // the Style Book is not prematurely closed. - setEditorCanvasContainerView( 'style-book' ); - setIsListViewOpened( false ); - }, [ - openGlobalStyles, - setEditorCanvasContainerView, - setIsListViewOpened, - ] ); - const openRevisions = useCallback( async () => { await openGlobalStyles(); // Open the global styles revisions once the canvas mode is set to edit, @@ -142,16 +99,17 @@ export default function SidebarNavigationScreenGlobalStyles( { backPath } ) { const modifiedDateTime = revisions?.[ 0 ]?.modified; const shouldShowGlobalStylesFooter = hasRevisions && ! isLoadingRevisions && modifiedDateTime; - return ( <> <SidebarNavigationScreen - title={ __( 'Styles' ) } + title={ __( 'Design' ) } + isRoot description={ __( - 'Choose a different style combination for the theme styles.' + 'Customize the appearance of your website using the block editor.' ) } - backPath={ backPath } - content={ <SidebarNavigationScreenGlobalStylesContent /> } + content={ + <MainSidebarNavigationContent activeItem="styles-navigation-item" /> + } footer={ shouldShowGlobalStylesFooter && ( <SidebarNavigationScreenDetailsFooter @@ -160,40 +118,7 @@ export default function SidebarNavigationScreenGlobalStyles( { backPath } ) { /> ) } - actions={ - <> - { ! isMobileViewport && ( - <SidebarButton - icon={ seen } - label={ __( 'Style Book' ) } - onClick={ () => - setEditorCanvasContainerView( - ! isStyleBookOpened - ? 'style-book' - : undefined - ) - } - isPressed={ isStyleBookOpened } - /> - ) } - <SidebarButton - icon={ edit } - label={ __( 'Edit styles' ) } - onClick={ async () => await openGlobalStyles() } - /> - </> - } /> - { isStyleBookOpened && ! isMobileViewport && canvas === 'view' && ( - <StyleBook - enableResizing={ false } - isSelected={ () => false } - onClick={ openStyleBook } - onSelect={ openStyleBook } - showCloseButton={ false } - showTabs={ false } - /> - ) } </> ); } diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js index bdfb6ac93b51c4..49e60d44047326 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js @@ -21,6 +21,51 @@ import { PATTERN_TYPES, } from '../../utils/constants'; +export function MainSidebarNavigationContent() { + return ( + <ItemGroup> + <SidebarNavigationItem + uid="navigation-navigation-item" + params={ { postType: NAVIGATION_POST_TYPE } } + withChevron + icon={ navigation } + > + { __( 'Navigation' ) } + </SidebarNavigationItem> + <SidebarNavigationItemGlobalStyles + uid="styles-navigation-item" + icon={ styles } + > + { __( 'Styles' ) } + </SidebarNavigationItemGlobalStyles> + <SidebarNavigationItem + uid="page-navigation-item" + params={ { postType: 'page' } } + withChevron + icon={ page } + > + { __( 'Pages' ) } + </SidebarNavigationItem> + <SidebarNavigationItem + uid="template-navigation-item" + params={ { postType: TEMPLATE_POST_TYPE } } + withChevron + icon={ layout } + > + { __( 'Templates' ) } + </SidebarNavigationItem> + <SidebarNavigationItem + uid="patterns-navigation-item" + params={ { postType: PATTERN_TYPES.user } } + withChevron + icon={ symbol } + > + { __( 'Patterns' ) } + </SidebarNavigationItem> + </ItemGroup> + ); +} + export default function SidebarNavigationScreenMain() { const { setEditorCanvasContainerView } = unlock( useDispatch( editSiteStore ) @@ -38,51 +83,7 @@ export default function SidebarNavigationScreenMain() { description={ __( 'Customize the appearance of your website using the block editor.' ) } - content={ - <> - <ItemGroup> - <SidebarNavigationItem - uid="navigation-navigation-item" - params={ { postType: NAVIGATION_POST_TYPE } } - withChevron - icon={ navigation } - > - { __( 'Navigation' ) } - </SidebarNavigationItem> - <SidebarNavigationItemGlobalStyles - uid="styles-navigation-item" - withChevron - icon={ styles } - > - { __( 'Styles' ) } - </SidebarNavigationItemGlobalStyles> - <SidebarNavigationItem - uid="page-navigation-item" - params={ { postType: 'page' } } - withChevron - icon={ page } - > - { __( 'Pages' ) } - </SidebarNavigationItem> - <SidebarNavigationItem - uid="template-navigation-item" - params={ { postType: TEMPLATE_POST_TYPE } } - withChevron - icon={ layout } - > - { __( 'Templates' ) } - </SidebarNavigationItem> - <SidebarNavigationItem - uid="patterns-navigation-item" - params={ { postType: PATTERN_TYPES.user } } - withChevron - icon={ symbol } - > - { __( 'Patterns' ) } - </SidebarNavigationItem> - </ItemGroup> - </> - } + content={ <MainSidebarNavigationContent /> } /> ); } diff --git a/packages/edit-site/src/components/sidebar/index.js b/packages/edit-site/src/components/sidebar/index.js index 84820952e1b621..7ecd24719a47bf 100644 --- a/packages/edit-site/src/components/sidebar/index.js +++ b/packages/edit-site/src/components/sidebar/index.js @@ -55,7 +55,7 @@ function createNavState() { }; } -function SidebarContentWrapper( { children } ) { +function SidebarContentWrapper( { children, shouldAnimate } ) { const navState = useContext( SidebarNavigationContext ); const wrapperRef = useRef(); const [ navAnimation, setNavAnimation ] = useState( null ); @@ -66,10 +66,19 @@ function SidebarContentWrapper( { children } ) { setNavAnimation( direction ); }, [ navState ] ); - const wrapperCls = clsx( 'edit-site-sidebar__screen-wrapper', { - 'slide-from-left': navAnimation === 'back', - 'slide-from-right': navAnimation === 'forward', - } ); + const wrapperCls = clsx( + 'edit-site-sidebar__screen-wrapper', + /* + * Some panes do not have sub-panes and therefore + * should not animate when clicked on. + */ + shouldAnimate + ? { + 'slide-from-left': navAnimation === 'back', + 'slide-from-right': navAnimation === 'forward', + } + : {} + ); return ( <div ref={ wrapperRef } className={ wrapperCls }> @@ -78,13 +87,20 @@ function SidebarContentWrapper( { children } ) { ); } -export default function SidebarContent( { routeKey, children } ) { +export default function SidebarContent( { + routeKey, + shouldAnimate, + children, +} ) { const [ navState ] = useState( createNavState ); return ( <SidebarNavigationContext.Provider value={ navState }> <div className="edit-site-sidebar__content"> - <SidebarContentWrapper key={ routeKey }> + <SidebarContentWrapper + shouldAnimate={ shouldAnimate } + key={ routeKey } + > { children } </SidebarContentWrapper> </div> diff --git a/packages/edit-site/src/components/site-editor-routes/styles-edit.js b/packages/edit-site/src/components/site-editor-routes/styles-edit.js index ff52b957bc3609..e8225a8f526ebd 100644 --- a/packages/edit-site/src/components/site-editor-routes/styles-edit.js +++ b/packages/edit-site/src/components/site-editor-routes/styles-edit.js @@ -3,15 +3,24 @@ */ import Editor from '../editor'; import SidebarNavigationScreenGlobalStyles from '../sidebar-navigation-screen-global-styles'; +import GlobalStylesUIWrapper from '../sidebar-global-styles-wrapper'; export const stylesEditRoute = { name: 'styles-edit', match: ( params ) => { - return params.path === '/wp_global_styles' && params.canvas === 'edit'; + return ( + params.path && + params.path.startsWith( '/wp_global_styles' ) && + params.canvas !== 'edit' + ); }, areas: { + content: <GlobalStylesUIWrapper />, sidebar: <SidebarNavigationScreenGlobalStyles backPath={ {} } />, preview: <Editor />, mobile: <Editor />, }, + widths: { + content: 380, + }, }; diff --git a/packages/edit-site/src/components/site-editor-routes/styles-view.js b/packages/edit-site/src/components/site-editor-routes/styles-view.js index 856a610eb23677..cc9411eb8144c0 100644 --- a/packages/edit-site/src/components/site-editor-routes/styles-view.js +++ b/packages/edit-site/src/components/site-editor-routes/styles-view.js @@ -3,14 +3,24 @@ */ import Editor from '../editor'; import SidebarNavigationScreenGlobalStyles from '../sidebar-navigation-screen-global-styles'; +import GlobalStylesUIWrapper from '../sidebar-global-styles-wrapper'; export const stylesViewRoute = { name: 'styles-view', match: ( params ) => { - return params.path === '/wp_global_styles' && params.canvas !== 'edit'; + return ( + params.path && + params.path.startsWith( '/wp_global_styles' ) && + params.canvas !== 'edit' + ); }, areas: { + content: <GlobalStylesUIWrapper />, sidebar: <SidebarNavigationScreenGlobalStyles backPath={ {} } />, preview: <Editor />, + mobile: <GlobalStylesUIWrapper />, + }, + widths: { + content: 380, }, }; diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index e9660323b83734..9918c169ff6ab0 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -24,7 +24,14 @@ import { import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { useSelect } from '@wordpress/data'; import { useResizeObserver } from '@wordpress/compose'; -import { useMemo, useState, memo, useContext } from '@wordpress/element'; +import { + useMemo, + useState, + memo, + useContext, + useRef, + useLayoutEffect, +} from '@wordpress/element'; import { ENTER, SPACE } from '@wordpress/keycodes'; /** @@ -53,6 +60,48 @@ function isObjectEmpty( object ) { return ! object || Object.keys( object ).length === 0; } +/** + * Scrolls to a section within an iframe. + * + * @param {string} anchorId The id of the element to scroll to. + * @param {HTMLIFrameElement} iframe The target iframe. + */ +const scrollToSection = ( anchorId, iframe ) => { + if ( ! iframe || ! iframe?.contentDocument ) { + return; + } + + const element = iframe.contentDocument.getElementById( anchorId ); + if ( element ) { + element.scrollIntoView( { + behavior: 'smooth', + } ); + } +}; + +/** + * Parses a Block Editor navigation path to extract the block name and + * build a style book navigation path. The object can be extended to include a category, + * representing a style book tab/section. + * + * @param {string} path An internal Block Editor navigation path. + * @return {null|{block: string}} An object containing the example to navigate to. + */ +const getStyleBookNavigationFromPath = ( path ) => { + if ( path && typeof path === 'string' ) { + let block = path.includes( '/blocks/' ) + ? decodeURIComponent( path.split( '/blocks/' )[ 1 ] ) + : null; + // Default to theme-colors if the path ends with /colors. + block = path.endsWith( '/colors' ) ? 'theme-colors' : block; + + return { + block, + }; + } + return null; +}; + /** * Retrieves colors, gradients, and duotone filters from Global Styles. * The inclusion of default (Core) palettes is controlled by the relevant @@ -137,6 +186,7 @@ function StyleBook( { onClose, showTabs = true, userConfig = {}, + path = '', } ) { const [ resizeObserver, sizes ] = useResizeObserver(); const [ textColor ] = useGlobalStyle( 'color.text' ); @@ -154,6 +204,7 @@ function StyleBook( { ); const { base: baseConfig } = useContext( GlobalStylesContext ); + const goTo = getStyleBookNavigationFromPath( path ); const mergedConfig = useMemo( () => { if ( ! isObjectEmpty( userConfig ) && ! isObjectEmpty( baseConfig ) ) { @@ -228,6 +279,7 @@ function StyleBook( { settings={ settings } sizes={ sizes } title={ tab.title } + goTo={ goTo } /> </Tabs.TabPanel> ) ) } @@ -240,6 +292,7 @@ function StyleBook( { onSelect={ onSelect } settings={ settings } sizes={ sizes } + goTo={ goTo } /> ) } </div> @@ -256,9 +309,11 @@ const StyleBookBody = ( { settings, sizes, title, + goTo, } ) => { const [ isFocused, setIsFocused ] = useState( false ); - + const [ hasIframeLoaded, setHasIframeLoaded ] = useState( false ); + const iframeRef = useRef( null ); // The presence of an `onClick` prop indicates that the Style Book is being used as a button. // In this case, add additional props to the iframe to make it behave like a button. const buttonModeProps = { @@ -287,8 +342,17 @@ const StyleBookBody = ( { readonly: true, }; + const handleLoad = () => setHasIframeLoaded( true ); + useLayoutEffect( () => { + if ( goTo?.block && hasIframeLoaded && iframeRef?.current ) { + scrollToSection( `example-${ goTo?.block }`, iframeRef?.current ); + } + }, [ iframeRef?.current, goTo?.block, scrollToSection, hasIframeLoaded ] ); + return ( <Iframe + onLoad={ handleLoad } + ref={ iframeRef } className={ clsx( 'edit-site-style-book__iframe', { 'is-focused': isFocused && !! onClick, 'is-button': !! onClick, @@ -353,10 +417,8 @@ const Examples = memo( title={ example.title } content={ example.content } blocks={ example.blocks } - isSelected={ isSelected( example.name ) } - onClick={ () => { - onSelect?.( example.name ); - } } + isSelected={ isSelected?.( example.name ) } + onClick={ () => onSelect?.( example.name ) } /> ) ) } { !! filteredExamples?.subcategories?.length && @@ -392,7 +454,7 @@ const Subcategory = ( { examples, isSelected, onSelect } ) => { title={ example.title } content={ example.content } blocks={ example.blocks } - isSelected={ isSelected( example.name ) } + isSelected={ isSelected?.( example.name ) } onClick={ () => { onSelect?.( example.name ); } } diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index b2f5c826046b79..03ec43648f120f 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -38,6 +38,7 @@ @import "./components/global-styles/font-library-modal/style.scss"; @import "./components/pagination/style.scss"; @import "./components/global-styles/variations/style.scss"; +@import "./components/sidebar-global-styles-wrapper/style.scss"; /* stylelint-disable -- Disable reason: View Transitions not supported properly by stylelint. */ ::view-transition-image-pair(root) { From c5921d766c143ef6774c827c8c2f6322b2b26b6b Mon Sep 17 00:00:00 2001 From: Adam Silverstein <adamjs@google.com> Date: Mon, 4 Nov 2024 02:30:43 -0700 Subject: [PATCH 1459/1908] =?UTF-8?q?Ensure=20HEIC=20files=20selectable=20?= =?UTF-8?q?from=20=E2=80=9CUpload=E2=80=9D=20button=20(#66292)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Ensure HEIC files selectable from “Upload” button * Update packages/components/src/form-file-upload/index.tsx Co-authored-by: George Mamadashvili <georgemamadashvili@gmail.com> * move “image/heic” addition to FormFileUpload component * add image/heif --------- Co-authored-by: adamsilverstein <adamsilverstein@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: ironprogrammer <ironprogrammer@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- packages/components/src/form-file-upload/index.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/components/src/form-file-upload/index.tsx b/packages/components/src/form-file-upload/index.tsx index 0600e47d7324c3..66f0b2ea6d6480 100644 --- a/packages/components/src/form-file-upload/index.tsx +++ b/packages/components/src/form-file-upload/index.tsx @@ -47,6 +47,12 @@ export function FormFileUpload( { { children } </Button> ); + // @todo: Temporary fix a bug that prevents Chromium browsers from selecting ".heic" files + // from the file upload. See https://core.trac.wordpress.org/ticket/62268#comment:4. + // This can be removed once the Chromium fix is in the stable channel. + const compatAccept = !! accept?.includes( 'image/*' ) + ? `${ accept }, image/heic, image/heif` + : accept; return ( <div className="components-form-file-upload"> @@ -56,7 +62,7 @@ export function FormFileUpload( { ref={ ref } multiple={ multiple } style={ { display: 'none' } } - accept={ accept } + accept={ compatAccept } onChange={ onChange } onClick={ onClick } data-testid="form-file-upload-input" From 5274126cc13f615b4a634d508d65f8b2ef3e46e4 Mon Sep 17 00:00:00 2001 From: Pascal Birchler <pascalb@google.com> Date: Mon, 4 Nov 2024 10:57:57 +0100 Subject: [PATCH 1460/1908] Media Utils: add experimental `sideloadMedia` (#66378) --- package-lock.json | 3 +- packages/media-utils/README.md | 4 + packages/media-utils/package.json | 3 +- packages/media-utils/src/index.ts | 2 + packages/media-utils/src/lock-unlock.ts | 10 +++ packages/media-utils/src/private-apis.ts | 14 ++++ .../media-utils/src/utils/sideload-media.ts | 82 +++++++++++++++++++ .../src/utils/sideload-to-server.ts | 48 +++++++++++ .../src/utils/test/sideload-media.ts | 33 ++++++++ packages/media-utils/src/utils/types.ts | 10 +++ packages/media-utils/tsconfig.json | 3 +- packages/private-apis/src/implementation.ts | 1 + 12 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 packages/media-utils/src/lock-unlock.ts create mode 100644 packages/media-utils/src/private-apis.ts create mode 100644 packages/media-utils/src/utils/sideload-media.ts create mode 100644 packages/media-utils/src/utils/sideload-to-server.ts create mode 100644 packages/media-utils/src/utils/test/sideload-media.ts diff --git a/package-lock.json b/package-lock.json index 20bf45235880ee..9d5b12e749d123 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54994,7 +54994,8 @@ "@wordpress/api-fetch": "*", "@wordpress/blob": "*", "@wordpress/element": "*", - "@wordpress/i18n": "*" + "@wordpress/i18n": "*", + "@wordpress/private-apis": "*" }, "engines": { "node": ">=18.12.0", diff --git a/packages/media-utils/README.md b/packages/media-utils/README.md index 1adc15186078a5..ddf18efb288339 100644 --- a/packages/media-utils/README.md +++ b/packages/media-utils/README.md @@ -25,6 +25,10 @@ Undocumented declaration. Undocumented declaration. +### privateApis + +Private @wordpress/media-utils APIs. + ### RestAttachment Undocumented declaration. diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 050e1ab96f2929..20eef4dd83c6b4 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -31,7 +31,8 @@ "@wordpress/api-fetch": "*", "@wordpress/blob": "*", "@wordpress/element": "*", - "@wordpress/i18n": "*" + "@wordpress/i18n": "*", + "@wordpress/private-apis": "*" }, "publishConfig": { "access": "public" diff --git a/packages/media-utils/src/index.ts b/packages/media-utils/src/index.ts index c37814afe7c48f..e90b12ce8d6a63 100644 --- a/packages/media-utils/src/index.ts +++ b/packages/media-utils/src/index.ts @@ -7,3 +7,5 @@ export { validateMimeType } from './utils/validate-mime-type'; export { validateMimeTypeForUser } from './utils/validate-mime-type-for-user'; export type { Attachment, RestAttachment } from './utils/types'; + +export { privateApis } from './private-apis'; diff --git a/packages/media-utils/src/lock-unlock.ts b/packages/media-utils/src/lock-unlock.ts new file mode 100644 index 00000000000000..9aad88e5a4afb7 --- /dev/null +++ b/packages/media-utils/src/lock-unlock.ts @@ -0,0 +1,10 @@ +/** + * WordPress dependencies + */ +import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; + +export const { lock, unlock } = + __dangerousOptInToUnstableAPIsOnlyForCoreModules( + 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', + '@wordpress/media-utils' + ); diff --git a/packages/media-utils/src/private-apis.ts b/packages/media-utils/src/private-apis.ts new file mode 100644 index 00000000000000..b0e813b5eac1e0 --- /dev/null +++ b/packages/media-utils/src/private-apis.ts @@ -0,0 +1,14 @@ +/** + * Internal dependencies + */ +import { sideloadMedia } from './utils/sideload-media'; +import { lock } from './lock-unlock'; + +/** + * Private @wordpress/media-utils APIs. + */ +export const privateApis = {}; + +lock( privateApis, { + sideloadMedia, +} ); diff --git a/packages/media-utils/src/utils/sideload-media.ts b/packages/media-utils/src/utils/sideload-media.ts new file mode 100644 index 00000000000000..cff3003c7466ce --- /dev/null +++ b/packages/media-utils/src/utils/sideload-media.ts @@ -0,0 +1,82 @@ +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { + OnChangeHandler, + OnErrorHandler, + CreateSideloadFile, + RestAttachment, +} from './types'; +import { sideloadToServer } from './sideload-to-server'; +import { UploadError } from './upload-error'; + +const noop = () => {}; + +interface SideloadMediaArgs { + // Additional data to include in the request. + additionalData?: CreateSideloadFile; + // File to sideload. + file: File; + // Attachment ID. + attachmentId: RestAttachment[ 'id' ]; + // Function called when an error happens. + onError?: OnErrorHandler; + // Function called each time a file or a temporary representation of the file is available. + onFileChange?: OnChangeHandler; + // Abort signal. + signal?: AbortSignal; +} + +/** + * Uploads a file to the server without creating an attachment. + * + * @param $0 Parameters object passed to the function. + * @param $0.file Media File to Save. + * @param $0.attachmentId Parent attachment ID. + * @param $0.additionalData Additional data to include in the request. + * @param $0.signal Abort signal. + * @param $0.onFileChange Function called each time a file or a temporary representation of the file is available. + * @param $0.onError Function called when an error happens. + */ +export async function sideloadMedia( { + file, + attachmentId, + additionalData = {}, + signal, + onFileChange, + onError = noop, +}: SideloadMediaArgs ) { + try { + const attachment = await sideloadToServer( + file, + attachmentId, + additionalData, + signal + ); + onFileChange?.( [ attachment ] ); + } catch ( error ) { + let message; + if ( error instanceof Error ) { + message = error.message; + } else { + message = sprintf( + // translators: %s: file name + __( 'Error while sideloading file %s to the server.' ), + file.name + ); + } + onError( + new UploadError( { + code: 'GENERAL', + message, + file, + cause: error instanceof Error ? error : undefined, + } ) + ); + } +} diff --git a/packages/media-utils/src/utils/sideload-to-server.ts b/packages/media-utils/src/utils/sideload-to-server.ts new file mode 100644 index 00000000000000..941baa769fba8d --- /dev/null +++ b/packages/media-utils/src/utils/sideload-to-server.ts @@ -0,0 +1,48 @@ +/** + * WordPress dependencies + */ +import apiFetch from '@wordpress/api-fetch'; + +/** + * Internal dependencies + */ +import type { CreateSideloadFile, RestAttachment } from './types'; +import { flattenFormData } from './flatten-form-data'; +import { transformAttachment } from './transform-attachment'; + +/** + * Uploads a file to the server without creating an attachment. + * + * @param file Media File to Save. + * @param attachmentId Parent attachment ID. + * @param additionalData Additional data to include in the request. + * @param signal Abort signal. + * + * @return The saved attachment. + */ +export async function sideloadToServer( + file: File, + attachmentId: RestAttachment[ 'id' ], + additionalData: CreateSideloadFile = {}, + signal?: AbortSignal +) { + // Create upload payload. + const data = new FormData(); + data.append( 'file', file, file.name || file.type.replace( '/', '.' ) ); + for ( const [ key, value ] of Object.entries( additionalData ) ) { + flattenFormData( + data, + key, + value as string | Record< string, string > | undefined + ); + } + + return transformAttachment( + await apiFetch< RestAttachment >( { + path: `/wp/v2/media/${ attachmentId }/sideload`, + body: data, + method: 'POST', + signal, + } ) + ); +} diff --git a/packages/media-utils/src/utils/test/sideload-media.ts b/packages/media-utils/src/utils/test/sideload-media.ts new file mode 100644 index 00000000000000..818a09e8fc05f6 --- /dev/null +++ b/packages/media-utils/src/utils/test/sideload-media.ts @@ -0,0 +1,33 @@ +/** + * Internal dependencies + */ +import { sideloadMedia } from '../sideload-media'; +import { sideloadToServer } from '../sideload-to-server'; + +jest.mock( '../sideload-to-server', () => ( { + sideloadToServer: jest.fn(), +} ) ); + +const imageFile = new window.File( [ 'fake_file' ], 'test.jpeg', { + type: 'image/jpeg', +} ); + +describe( 'sideloadMedia', () => { + afterEach( () => { + jest.clearAllMocks(); + } ); + + it( 'should sideload to server', async () => { + const onError = jest.fn(); + const onFileChange = jest.fn(); + await sideloadMedia( { + file: imageFile, + attachmentId: 1, + onError, + onFileChange, + } ); + + expect( sideloadToServer ).toHaveBeenCalled(); + expect( onFileChange ).toHaveBeenCalled(); + } ); +} ); diff --git a/packages/media-utils/src/utils/types.ts b/packages/media-utils/src/utils/types.ts index e05536400a7604..c91d4c67cfc466 100644 --- a/packages/media-utils/src/utils/types.ts +++ b/packages/media-utils/src/utils/types.ts @@ -205,3 +205,13 @@ export type OnErrorHandler = ( error: Error ) => void; export type CreateRestAttachment = Partial< RestAttachment >; export type AdditionalData = BetterOmit< CreateRestAttachment, 'meta' >; + +export interface CreateSideloadFile { + image_size?: string; + upload_request?: string; +} + +export interface SideloadAdditionalData { + post: RestAttachment[ 'id' ]; + image_size?: string; +} diff --git a/packages/media-utils/tsconfig.json b/packages/media-utils/tsconfig.json index 8559f1507b7235..ca3e93c2dee668 100644 --- a/packages/media-utils/tsconfig.json +++ b/packages/media-utils/tsconfig.json @@ -12,6 +12,7 @@ { "path": "../api-fetch" }, { "path": "../blob" }, { "path": "../element" }, - { "path": "../i18n" } + { "path": "../i18n" }, + { "path": "../private-apis" } ] } diff --git a/packages/private-apis/src/implementation.ts b/packages/private-apis/src/implementation.ts index ee2b9693959a35..bae53bae8d158a 100644 --- a/packages/private-apis/src/implementation.ts +++ b/packages/private-apis/src/implementation.ts @@ -31,6 +31,7 @@ const CORE_MODULES_USING_PRIVATE_APIS = [ '@wordpress/router', '@wordpress/dataviews', '@wordpress/fields', + '@wordpress/media-utils', ]; /** From 238451e7ea7f382b37b7b4e95b758840bd02378b Mon Sep 17 00:00:00 2001 From: Sarah Norris <1645628+mikachan@users.noreply.github.com> Date: Mon, 4 Nov 2024 10:12:46 +0000 Subject: [PATCH 1461/1908] Query Loop: Remove postTypeFromContext (#66681) * Remove postTypeFromContext * Remove postType from Query Loop context Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../block-library/src/post-template/edit.js | 6 +----- packages/block-library/src/query/block.json | 2 +- .../query/edit/inspector-controls/index.js | 20 ++----------------- .../src/query/edit/query-content.js | 3 +-- 4 files changed, 5 insertions(+), 26 deletions(-) diff --git a/packages/block-library/src/post-template/edit.js b/packages/block-library/src/post-template/edit.js index b28c726acfc77e..a9e279ee2c3052 100644 --- a/packages/block-library/src/post-template/edit.js +++ b/packages/block-library/src/post-template/edit.js @@ -100,7 +100,6 @@ export default function PostTemplateEdit( { } = {}, templateSlug, previewPostType, - postType: postTypeFromContext, }, attributes: { layout }, __unstableLayoutClassNames, @@ -187,10 +186,7 @@ export default function PostTemplateEdit( { } // When we preview Query Loop blocks we should prefer the current // block's postType, which is passed through block context. - const usedPostType = - postTypeFromContext && postTypeFromContext !== 'page' - ? postTypeFromContext - : previewPostType || postType; + const usedPostType = previewPostType || postType; return { posts: getEntityRecords( 'postType', usedPostType, { ...query, diff --git a/packages/block-library/src/query/block.json b/packages/block-library/src/query/block.json index 2379a1d1da53cf..6ccafc50c82017 100644 --- a/packages/block-library/src/query/block.json +++ b/packages/block-library/src/query/block.json @@ -42,7 +42,7 @@ "default": false } }, - "usesContext": [ "postType", "templateSlug" ], + "usesContext": [ "templateSlug" ], "providesContext": { "queryId": "queryId", "query": "query", diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index bc900c073f648d..7d5745e190c9a7 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -45,15 +45,9 @@ import { useToolsPanelDropdownMenuProps } from '../../../utils/hooks'; const { BlockInfo } = unlock( blockEditorPrivateApis ); export default function QueryInspectorControls( props ) { - const { - attributes, - setQuery, - setDisplayLayout, - postTypeFromContext, - isSingular, - } = props; + const { attributes, setQuery, setDisplayLayout, isSingular } = props; const { query, displayLayout } = attributes; - let { + const { order, orderBy, author: authorIds, @@ -67,16 +61,6 @@ export default function QueryInspectorControls( props ) { parents, format, } = query; - // If a post type is set in context, update `postType` to match it, - // unless the post type is `page`, as it usually doesn't make sense to loop - // through pages. - if ( - postTypeFromContext && - postTypeFromContext !== 'page' && - postTypeFromContext !== postType - ) { - postType = postTypeFromContext; - } const allowedControls = useAllowedControls( attributes ); const showSticky = postType === 'post'; const { diff --git a/packages/block-library/src/query/edit/query-content.js b/packages/block-library/src/query/edit/query-content.js index bdfcbe0498ec4a..17eea9337823c5 100644 --- a/packages/block-library/src/query/edit/query-content.js +++ b/packages/block-library/src/query/edit/query-content.js @@ -43,7 +43,7 @@ export default function QueryContent( { tagName: TagName = 'div', query: { inherit } = {}, } = attributes; - const { templateSlug, postType } = context; + const { templateSlug } = context; const { isSingular } = getQueryContextFromTemplate( templateSlug ); const { __unstableMarkNextChangeAsNotPersistent } = useDispatch( blockEditorStore ); @@ -159,7 +159,6 @@ export default function QueryContent( { setDisplayLayout={ updateDisplayLayout } setAttributes={ setAttributes } clientId={ clientId } - postTypeFromContext={ postType } isSingular={ isSingular } /> </InspectorControls> From 1ec454c3ddb97a93935dc9d636072b9df5929dec Mon Sep 17 00:00:00 2001 From: Juan Aldasoro <juanfraa@gmail.com> Date: Mon, 4 Nov 2024 11:17:53 +0100 Subject: [PATCH 1462/1908] Set the `fit-content` width for images that are not `.svg` (#66643) Co-authored-by: juanfra <juanfra@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- packages/block-library/src/image/style.scss | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/image/style.scss b/packages/block-library/src/image/style.scss index da4ccc50dac7f1..79689e82006cdc 100644 --- a/packages/block-library/src/image/style.scss +++ b/packages/block-library/src/image/style.scss @@ -9,7 +9,10 @@ max-width: 100%; vertical-align: bottom; box-sizing: border-box; - width: fit-content; + + &:not([src$=".svg"]) { + width: fit-content; + } @media (prefers-reduced-motion: no-preference) { &.hide { From 7c7c2062934000bdb77d668a29e99767102f9f93 Mon Sep 17 00:00:00 2001 From: Carolina Nymark <myazalea@hotmail.com> Date: Mon, 4 Nov 2024 11:49:49 +0100 Subject: [PATCH 1463/1908] Post template block: Adjust the editor preview on taxonomy archive templates Ensure that the preview of the post template block in the editor shows the correct posts on tag- and post format archive templates, when the query loop block is set to inherit the query from the template. Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../block-library/src/post-template/edit.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/block-library/src/post-template/edit.js b/packages/block-library/src/post-template/edit.js index a9e279ee2c3052..c58990233f3615 100644 --- a/packages/block-library/src/post-template/edit.js +++ b/packages/block-library/src/post-template/edit.js @@ -119,6 +119,15 @@ export default function PostTemplateEdit( { _fields: [ 'id' ], slug: templateSlug.replace( 'category-', '' ), } ); + const templateTag = + inherit && + templateSlug?.startsWith( 'tag-' ) && + getEntityRecords( 'taxonomy', 'post_tag', { + context: 'view', + per_page: 1, + _fields: [ 'id' ], + slug: templateSlug.replace( 'tag-', '' ), + } ); const query = { offset: offset || 0, order, @@ -182,6 +191,16 @@ export default function PostTemplateEdit( { postType = query.postType; } else if ( templateCategory ) { query.categories = templateCategory[ 0 ]?.id; + } else if ( templateTag ) { + query.tags = templateTag[ 0 ]?.id; + } else if ( + templateSlug?.startsWith( 'taxonomy-post_format' ) + ) { + // Get the post format slug from the template slug by removing the prefix. + query.format = templateSlug.replace( + 'taxonomy-post_format-post-format-', + '' + ); } } // When we preview Query Loop blocks we should prefer the current From 5445afce198c910c1ed42a365ffddaf7080897ba Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 4 Nov 2024 15:55:38 +0400 Subject: [PATCH 1464/1908] Inline Commenting: Avoid querying comments on editor load (#66670) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> --- .../components/collab-sidebar/add-comment.js | 37 +++--- .../src/components/collab-sidebar/index.js | 123 ++++++++++-------- 2 files changed, 83 insertions(+), 77 deletions(-) diff --git a/packages/editor/src/components/collab-sidebar/add-comment.js b/packages/editor/src/components/collab-sidebar/add-comment.js index 191bb23477f7bd..01ee7aff0370ef 100644 --- a/packages/editor/src/components/collab-sidebar/add-comment.js +++ b/packages/editor/src/components/collab-sidebar/add-comment.js @@ -35,25 +35,22 @@ export function AddComment( { // State to manage the comment thread. const [ inputComment, setInputComment ] = useState( '' ); - const { - defaultAvatar, - clientId, - blockCommentId, - showAddCommentBoard, - currentUser, - } = useSelect( ( select ) => { - const { getSettings } = select( blockEditorStore ); - const { __experimentalDiscussionSettings } = getSettings(); - const selectedBlock = select( blockEditorStore ).getSelectedBlock(); - const userData = select( coreStore ).getCurrentUser(); - return { - defaultAvatar: __experimentalDiscussionSettings?.avatarURL, - clientId: selectedBlock?.clientId, - blockCommentId: selectedBlock?.attributes?.blockCommentId, - showAddCommentBoard: showCommentBoard, - currentUser: userData, - }; - } ); + const { defaultAvatar, clientId, blockCommentId, currentUser } = useSelect( + ( select ) => { + const { getSettings, getSelectedBlock } = + select( blockEditorStore ); + const { __experimentalDiscussionSettings } = getSettings(); + const selectedBlock = getSelectedBlock(); + const userData = select( coreStore ).getCurrentUser(); + return { + defaultAvatar: __experimentalDiscussionSettings?.avatarURL, + clientId: selectedBlock?.clientId, + blockCommentId: selectedBlock?.attributes?.blockCommentId, + currentUser: userData, + }; + }, + [] + ); const userAvatar = currentUser && currentUser.avatar_urls && currentUser.avatar_urls[ 48 ] @@ -69,7 +66,7 @@ export function AddComment( { setInputComment( '' ); }; - if ( ! showAddCommentBoard || ! clientId || undefined !== blockCommentId ) { + if ( ! showCommentBoard || ! clientId || undefined !== blockCommentId ) { return null; } diff --git a/packages/editor/src/components/collab-sidebar/index.js b/packages/editor/src/components/collab-sidebar/index.js index 39303620dd6222..17a23a227424a6 100644 --- a/packages/editor/src/components/collab-sidebar/index.js +++ b/packages/editor/src/components/collab-sidebar/index.js @@ -22,8 +22,6 @@ import { store as editorStore } from '../../store'; import AddCommentButton from './comment-button'; import AddCommentToolbarButton from './comment-button-toolbar'; -const EMPTY_ARRAY = []; - const isBlockCommentExperimentEnabled = window?.__experimentalEnableBlockComment; const modifyBlockCommentAttributes = ( settings ) => { @@ -46,19 +44,13 @@ addFilter( modifyBlockCommentAttributes ); -/** - * Renders the Collab sidebar. - */ -export default function CollabSidebar() { +function CollabSidebarContent( { showCommentBoard, setShowCommentBoard } ) { const { createNotice } = useDispatch( noticesStore ); const { saveEntityRecord, deleteEntityRecord } = useDispatch( coreStore ); const { getEntityRecord } = resolveSelect( coreStore ); - const { enableComplementaryArea } = useDispatch( interfaceStore ); - const [ showCommentBoard, setShowCommentBoard ] = useState( false ); - const { postId, postStatus, threads } = useSelect( ( select ) => { - const { getCurrentPostId, getEditedPostAttribute } = - select( editorStore ); + const { postId, threads } = useSelect( ( select ) => { + const { getCurrentPostId } = select( editorStore ); const _postId = getCurrentPostId(); const data = !! _postId ? select( coreStore ).getEntityRecords( 'root', 'comment', { @@ -71,25 +63,11 @@ export default function CollabSidebar() { return { postId: _postId, - postStatus: getEditedPostAttribute( 'status' ), - threads: data ?? EMPTY_ARRAY, - }; - }, [] ); - - const { clientId, blockCommentId } = useSelect( ( select ) => { - const { getBlockAttributes, getSelectedBlockClientId } = - select( blockEditorStore ); - const _clientId = getSelectedBlockClientId(); - - return { - clientId: _clientId, - blockCommentId: _clientId - ? getBlockAttributes( _clientId )?.blockCommentId - : null, + threads: data, }; }, [] ); - // Get the dispatch functions to save the comment and update the block attributes. + const { getSelectedBlockClientId } = useSelect( blockEditorStore ); const { updateBlockAttributes } = useDispatch( blockEditorStore ); // Process comments to build the tree structure @@ -98,7 +76,7 @@ export default function CollabSidebar() { const compare = {}; const result = []; - const filteredComments = threads.filter( + const filteredComments = ( threads ?? [] ).filter( ( comment ) => comment.status !== 'trash' ); @@ -121,11 +99,6 @@ export default function CollabSidebar() { return result; }, [ threads ] ); - const openCollabBoard = () => { - setShowCommentBoard( true ); - enableComplementaryArea( 'core', 'edit-post/collab-sidebar' ); - }; - // Function to save the comment. const addNewComment = async ( comment, parentCommentId ) => { const args = { @@ -150,7 +123,7 @@ export default function CollabSidebar() { if ( savedRecord ) { // If it's a main comment, update the block attributes with the comment id. if ( ! parentCommentId ) { - updateBlockAttributes( clientId, { + updateBlockAttributes( getSelectedBlockClientId(), { blockCommentId: savedRecord?.id, } ); } @@ -232,7 +205,7 @@ export default function CollabSidebar() { await deleteEntityRecord( 'root', 'comment', commentId ); if ( childComment && ! childComment.parent ) { - updateBlockAttributes( clientId, { + updateBlockAttributes( getSelectedBlockClientId(), { blockCommentId: undefined, } ); } @@ -248,41 +221,77 @@ export default function CollabSidebar() { ); }; + return ( + <div className="editor-collab-sidebar-panel"> + <AddComment + onSubmit={ addNewComment } + showCommentBoard={ showCommentBoard } + setShowCommentBoard={ setShowCommentBoard } + /> + <Comments + threads={ resultComments } + onEditComment={ onEditComment } + onAddReply={ addNewComment } + onCommentDelete={ onCommentDelete } + onCommentResolve={ onCommentResolve } + /> + </div> + ); +} + +/** + * Renders the Collab sidebar. + */ +export default function CollabSidebar() { + const [ showCommentBoard, setShowCommentBoard ] = useState( false ); + const { enableComplementaryArea } = useDispatch( interfaceStore ); + + const { postStatus } = useSelect( ( select ) => { + return { + postStatus: + select( editorStore ).getEditedPostAttribute( 'status' ), + }; + }, [] ); + + const { blockCommentId } = useSelect( ( select ) => { + const { getBlockAttributes, getSelectedBlockClientId } = + select( blockEditorStore ); + const _clientId = getSelectedBlockClientId(); + + return { + blockCommentId: _clientId + ? getBlockAttributes( _clientId )?.blockCommentId + : null, + }; + }, [] ); + + const openCollabBoard = () => { + setShowCommentBoard( true ); + enableComplementaryArea( 'core', 'edit-post/collab-sidebar' ); + }; + // Check if the experimental flag is enabled. if ( ! isBlockCommentExperimentEnabled || postStatus === 'publish' ) { return null; // or maybe return some message indicating no threads are available. } + const AddCommentComponent = blockCommentId + ? AddCommentToolbarButton + : AddCommentButton; + return ( <> - { ! blockCommentId && ( - <AddCommentButton onClick={ openCollabBoard } /> - ) } - - { blockCommentId > 0 && ( - <AddCommentToolbarButton onClick={ openCollabBoard } /> - ) } + <AddCommentComponent onClick={ openCollabBoard } /> <PluginSidebar identifier={ collabSidebarName } // translators: Comments sidebar title title={ __( 'Comments' ) } icon={ commentIcon } > - <div className="editor-collab-sidebar-panel"> - <AddComment - threads={ resultComments } - onSubmit={ addNewComment } - showCommentBoard={ showCommentBoard } - setShowCommentBoard={ setShowCommentBoard } - /> - <Comments - threads={ resultComments } - onEditComment={ onEditComment } - onAddReply={ addNewComment } - onCommentDelete={ onCommentDelete } - onCommentResolve={ onCommentResolve } - /> - </div> + <CollabSidebarContent + showCommentBoard={ showCommentBoard } + setShowCommentBoard={ setShowCommentBoard } + /> </PluginSidebar> </> ); From b992649af2753e818639fef6e38d34de63474822 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 4 Nov 2024 15:56:26 +0400 Subject: [PATCH 1465/1908] Components: Fix React Compiler error for 'useScrollRectIntoView' (#66498) * Components: Fix React Compiler error for 'useScrollRectIntoView' * Use optional chaining and add inline comment * Use single scroll call Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/src/tabs/tablist.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/components/src/tabs/tablist.tsx b/packages/components/src/tabs/tablist.tsx index 2f736d6b95441c..b7cfef7e19a096 100644 --- a/packages/components/src/tabs/tablist.tsx +++ b/packages/components/src/tabs/tablist.tsx @@ -48,10 +48,21 @@ function useScrollRectIntoView( const childRightEdge = childLeft + childWidth; const rightOverflow = childRightEdge + margin - parentRightEdge; const leftOverflow = parentScroll - ( childLeft - margin ); + + let scrollLeft = null; if ( leftOverflow > 0 ) { - parent.scrollLeft = parentScroll - leftOverflow; + scrollLeft = parentScroll - leftOverflow; } else if ( rightOverflow > 0 ) { - parent.scrollLeft = parentScroll + rightOverflow; + scrollLeft = parentScroll + rightOverflow; + } + + if ( scrollLeft !== null ) { + /** + * The optional chaining is used here to avoid unit test failures. + * It can be removed when JSDOM supports `Element` scroll methods. + * See: https://github.com/WordPress/gutenberg/pull/66498#issuecomment-2441146096 + */ + parent.scroll?.( { left: scrollLeft } ); } }, [ margin, parent, rect ] ); } From d2b48e76844cbba2b35966f07f66e837344dfebc Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Mon, 4 Nov 2024 23:28:31 +0900 Subject: [PATCH 1466/1908] URLInput: Fix incorrect classname for suggestions (#66714) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-editor/src/components/url-input/index.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/url-input/index.js b/packages/block-editor/src/components/url-input/index.js index 4e7ac61e783661..60cbf4d5e88099 100644 --- a/packages/block-editor/src/components/url-input/index.js +++ b/packages/block-editor/src/components/url-input/index.js @@ -533,10 +533,9 @@ class URLInput extends Component { <Popover placement="bottom" focusOnMount={ false }> <div { ...suggestionsListProps } - className={ clsx( - 'block-editor-url-input__suggestions', - `${ className }__suggestions` - ) } + className={ clsx( 'block-editor-url-input__suggestions', { + [ `${ className }__suggestions` ]: className, + } ) } > { suggestions.map( ( suggestion, index ) => ( <Button From 7bf1d968bf305c7ba0c7be3308b3e71be06e46ca Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Mon, 4 Nov 2024 23:57:41 +0900 Subject: [PATCH 1467/1908] Appender: fix initial position (#66711) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- .../src/components/block-tools/style.scss | 3 +-- .../components/default-block-appender/content.scss | 11 +++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index 66a711454eb798..b553d42668cf38 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -57,8 +57,7 @@ } } -// The black plus that shows up on the right side of an empty paragraph block, -// or the initial appender that exists only on empty documents. +// The black plus that shows up on the right side of an empty paragraph block. .block-editor-block-list__empty-block-inserter.block-editor-block-list__empty-block-inserter { position: absolute; top: 0; diff --git a/packages/block-editor/src/components/default-block-appender/content.scss b/packages/block-editor/src/components/default-block-appender/content.scss index 3a1bf9889d7481..e2009daa7358c4 100644 --- a/packages/block-editor/src/components/default-block-appender/content.scss +++ b/packages/block-editor/src/components/default-block-appender/content.scss @@ -62,6 +62,17 @@ } } +// The initial appender that exists only on empty documents. +.block-editor-default-block-appender .block-editor-inserter { + position: absolute; + top: 0; + right: 0; + line-height: 0; + + &:disabled { + display: none; + } +} /** * Fixed position appender (right bottom corner). From 6df457c0e47036c3f015970f82661c30bf2803ec Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Tue, 5 Nov 2024 08:43:44 +1100 Subject: [PATCH 1468/1908] Block toolbar: restrict visible child calculation to known blocks (#66702) * Refactor getVisibleElementBounds to only check visible children for specific blocks that we know overflow. Rename function and update comments. Introduce rudimentary unit tests. * Apply suggestions to code comments from code review Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> * Add extra tests * Rebase * Added a test for viewport clipping and adjusted test descriptions --------- Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: simom <simo_m@git.wordpress.org> --- .../src/components/block-popover/index.js | 8 +- .../use-block-toolbar-popover-props.js | 4 +- packages/block-editor/src/utils/dom.js | 46 ++-- packages/block-editor/src/utils/test/dom.js | 224 ++++++++++++++++++ 4 files changed, 256 insertions(+), 26 deletions(-) create mode 100644 packages/block-editor/src/utils/test/dom.js diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index f01c43ef26a71d..06409bc6e65f42 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -20,7 +20,7 @@ import { */ import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; import usePopoverScroll from './use-popover-scroll'; -import { rectUnion, getVisibleElementBounds } from '../../utils/dom'; +import { rectUnion, getElementBounds } from '../../utils/dom'; const MAX_POPOVER_RECOMPUTE_COUNTER = Number.MAX_SAFE_INTEGER; @@ -90,10 +90,10 @@ function BlockPopover( getBoundingClientRect() { return lastSelectedElement ? rectUnion( - getVisibleElementBounds( selectedElement ), - getVisibleElementBounds( lastSelectedElement ) + getElementBounds( selectedElement ), + getElementBounds( lastSelectedElement ) ) - : getVisibleElementBounds( selectedElement ); + : getElementBounds( selectedElement ); }, contextElement: selectedElement, }; diff --git a/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js b/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js index 6d64f5a5882cb8..df016e73c29d45 100644 --- a/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js +++ b/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js @@ -17,7 +17,7 @@ import { import { store as blockEditorStore } from '../../store'; import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; import { hasStickyOrFixedPositionValue } from '../../hooks/position'; -import { getVisibleElementBounds } from '../../utils/dom'; +import { getElementBounds } from '../../utils/dom'; const COMMON_PROPS = { placement: 'top-start', @@ -68,7 +68,7 @@ function getProps( // Get how far the content area has been scrolled. const scrollTop = scrollContainer?.scrollTop || 0; - const blockRect = getVisibleElementBounds( selectedBlockElement ); + const blockRect = getElementBounds( selectedBlockElement ); const contentRect = contentElement.getBoundingClientRect(); // Get the vertical position of top of the visible content area. diff --git a/packages/block-editor/src/utils/dom.js b/packages/block-editor/src/utils/dom.js index e30f809e387797..6d55f2468d24b6 100644 --- a/packages/block-editor/src/utils/dom.js +++ b/packages/block-editor/src/utils/dom.js @@ -134,23 +134,21 @@ function isScrollable( element ) { ); } +export const WITH_OVERFLOW_ELEMENT_BLOCKS = [ 'core/navigation' ]; /** - * Returns the rect of the element including all visible nested elements. - * - * Visible nested elements, including elements that overflow the parent, are - * taken into account. - * - * This function is useful for calculating the visible area of a block that - * contains nested elements that overflow the block, e.g. the Navigation block, - * which can contain overflowing Submenu blocks. + * Returns the bounding rectangle of an element, with special handling for blocks + * that have visible overflowing children (defined in WITH_OVERFLOW_ELEMENT_BLOCKS). * + * For blocks like Navigation that can have overflowing elements (e.g. submenus), + * this function calculates the combined bounds of both the parent and its visible + * children. The returned rect may extend beyond the viewport. * The returned rect represents the full extent of the element and its visible * children, which may extend beyond the viewport. * * @param {Element} element Element. * @return {DOMRect} Bounding client rect of the element and its visible children. */ -export function getVisibleElementBounds( element ) { +export function getElementBounds( element ) { const viewport = element.ownerDocument.defaultView; if ( ! viewport ) { @@ -158,17 +156,25 @@ export function getVisibleElementBounds( element ) { } let bounds = element.getBoundingClientRect(); - const stack = [ element ]; - let currentElement; - - while ( ( currentElement = stack.pop() ) ) { - // Children won’t affect bounds unless the element is not scrollable. - if ( ! isScrollable( currentElement ) ) { - for ( const child of currentElement.children ) { - if ( isElementVisible( child ) ) { - const childBounds = child.getBoundingClientRect(); - bounds = rectUnion( bounds, childBounds ); - stack.push( child ); + const dataType = element.getAttribute( 'data-type' ); + + /* + * For blocks with overflowing elements (like Navigation), include the bounds + * of visible children that extend beyond the parent container. + */ + if ( dataType && WITH_OVERFLOW_ELEMENT_BLOCKS.includes( dataType ) ) { + const stack = [ element ]; + let currentElement; + + while ( ( currentElement = stack.pop() ) ) { + // Children won’t affect bounds unless the element is not scrollable. + if ( ! isScrollable( currentElement ) ) { + for ( const child of currentElement.children ) { + if ( isElementVisible( child ) ) { + const childBounds = child.getBoundingClientRect(); + bounds = rectUnion( bounds, childBounds ); + stack.push( child ); + } } } } diff --git a/packages/block-editor/src/utils/test/dom.js b/packages/block-editor/src/utils/test/dom.js new file mode 100644 index 00000000000000..50a16a27cf9617 --- /dev/null +++ b/packages/block-editor/src/utils/test/dom.js @@ -0,0 +1,224 @@ +/** + * Internal dependencies + */ +import { getElementBounds, WITH_OVERFLOW_ELEMENT_BLOCKS } from '../dom'; +describe( 'dom', () => { + describe( 'getElementBounds', () => { + it( 'should return a DOMRectReadOnly object if the viewport is not available', () => { + const element = { + ownerDocument: { + defaultView: null, + }, + }; + expect( getElementBounds( element ) ).toEqual( + new window.DOMRectReadOnly() + ); + } ); + it( 'should return a DOMRectReadOnly object if the viewport is available', () => { + const element = { + ownerDocument: { + defaultView: { + getComputedStyle: () => ( { + display: 'block', + visibility: 'visible', + opacity: '1', + } ), + }, + }, + getBoundingClientRect: () => ( { + left: 0, + top: 0, + right: 100, + bottom: 100, + width: 100, + height: 100, + } ), + getAttribute: ( x ) => x, + }; + expect( getElementBounds( element ) ).toEqual( + new window.DOMRectReadOnly( 0, 0, 100, 100 ) + ); + } ); + it( 'should clip left and right values when an element is larger than the viewport width', () => { + const element = window.document.createElement( 'div' ); + element.getBoundingClientRect = jest.fn().mockReturnValue( { + left: -10, + top: 0, + right: window.innerWidth + 10, + bottom: 100, + width: window.innerWidth, + height: 100, + } ); + expect( getElementBounds( element ).toJSON() ).toEqual( { + left: 0, // Reset to min left bound. + top: 0, + right: window.innerWidth, // Reset to max right bound. + bottom: 100, + width: window.innerWidth, + height: 100, + x: 0, + y: 0, + } ); + } ); + it( 'should return the parent DOMRectReadOnly object if the parent block type is not supported', () => { + const element = window.document.createElement( 'div' ); + element.getBoundingClientRect = jest.fn().mockReturnValue( { + left: 0, + top: 0, + right: 100, + bottom: 100, + width: 100, + height: 100, + } ); + element.setAttribute( 'data-type', 'test' ); + const childElement = window.document.createElement( 'div' ); + childElement.getBoundingClientRect = jest.fn().mockReturnValue( { + left: 0, + top: 0, + right: 333, + bottom: 333, + width: 333, + height: 333, + x: 0, + y: 0, + } ); + element.appendChild( childElement ); + + expect( getElementBounds( element ).toJSON() ).toEqual( { + left: 0, + top: 0, + right: 100, + bottom: 100, + width: 100, + height: 100, + x: 0, + y: 0, + } ); + } ); + describe( 'With known block type', () => { + it( 'should return the child DOMRectReadOnly object if it is visible and a known block type', () => { + const element = window.document.createElement( 'div' ); + element.getBoundingClientRect = jest.fn().mockReturnValue( { + left: 0, + top: 0, + right: 100, + bottom: 100, + width: 100, + height: 100, + } ); + element.setAttribute( + 'data-type', + WITH_OVERFLOW_ELEMENT_BLOCKS[ 0 ] + ); + const childElement = window.document.createElement( 'div' ); + childElement.getBoundingClientRect = jest + .fn() + .mockReturnValue( { + left: 0, + top: 0, + right: 333, + bottom: 333, + width: 333, + height: 333, + x: 0, + y: 0, + } ); + element.appendChild( childElement ); + + expect( getElementBounds( element ).toJSON() ).toEqual( { + left: 0, + top: 0, + right: 333, + bottom: 333, + width: 333, + height: 333, + x: 0, + y: 0, + } ); + } ); + it( 'should return the parent DOMRectReadOnly if the child is scrollable', () => { + const element = window.document.createElement( 'div' ); + element.setAttribute( + 'data-type', + WITH_OVERFLOW_ELEMENT_BLOCKS[ 0 ] + ); + element.style.overflowX = 'auto'; + element.style.overflowY = 'auto'; + element.getBoundingClientRect = jest.fn().mockReturnValue( { + left: 0, + top: 0, + right: 100, + bottom: 100, + width: 100, + height: 100, + } ); + const childElement = window.document.createElement( 'div' ); + childElement.getBoundingClientRect = jest + .fn() + .mockReturnValue( { + left: 0, + top: 0, + right: 333, + bottom: 333, + width: 333, + height: 333, + x: 0, + y: 0, + } ); + element.appendChild( childElement ); + + expect( getElementBounds( element ).toJSON() ).toEqual( { + left: 0, + top: 0, + right: 100, + bottom: 100, + width: 100, + height: 100, + x: 0, + y: 0, + } ); + } ); + it( 'should return the parent DOMRectReadOnly object if the child element is not visible', () => { + const element = window.document.createElement( 'div' ); + element.getBoundingClientRect = jest.fn().mockReturnValue( { + left: 0, + top: 0, + right: 100, + bottom: 100, + width: 100, + height: 100, + } ); + element.setAttribute( + 'data-type', + WITH_OVERFLOW_ELEMENT_BLOCKS[ 0 ] + ); + const childElement = window.document.createElement( 'div' ); + childElement.getBoundingClientRect = jest + .fn() + .mockReturnValue( { + left: 0, + top: 0, + right: 333, + bottom: 333, + width: 333, + height: 333, + x: 0, + y: 0, + } ); + childElement.style.display = 'none'; + element.appendChild( childElement ); + + expect( getElementBounds( element ).toJSON() ).toEqual( { + left: 0, + top: 0, + right: 100, + bottom: 100, + width: 100, + height: 100, + x: 0, + y: 0, + } ); + } ); + } ); + } ); +} ); From adf7e26799b9bbbb8a237df134ca979dd8e1b0e3 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:22:36 +0900 Subject: [PATCH 1469/1908] Shadow panel: Make the delete modal text translatable (#66712) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: up1512001 <up1512001@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> --- .../src/components/global-styles/shadows-edit-panel.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js index 127480ee5af497..f26a8a5ed17436 100644 --- a/packages/edit-site/src/components/global-styles/shadows-edit-panel.js +++ b/packages/edit-site/src/components/global-styles/shadows-edit-panel.js @@ -215,8 +215,10 @@ export default function ShadowsEditPanel() { size="medium" > { sprintf( - // translators: %s: name of the shadow - 'Are you sure you want to delete "%s"?', + /* translators: %s: Name of the shadow preset. */ + __( + 'Are you sure you want to delete "%s" shadow preset?' + ), selectedShadow.name ) } </ConfirmDialog> From 25849be0c7f6b6b23c3eb09ec6b686e122e92ebd Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 5 Nov 2024 11:24:50 +0900 Subject: [PATCH 1470/1908] ComplementaryArea: Fix button position (#66677) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: up1512001 <up1512001@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../src/components/complementary-area-header/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/interface/src/components/complementary-area-header/style.scss b/packages/interface/src/components/complementary-area-header/style.scss index ce602f369d2aed..c62fe7dc941760 100644 --- a/packages/interface/src/components/complementary-area-header/style.scss +++ b/packages/interface/src/components/complementary-area-header/style.scss @@ -4,6 +4,6 @@ gap: $grid-unit-10; // Always ensure space between contents and close buttons. .interface-complementary-area-header__title { - margin: 0; + margin: 0 auto 0 0; } } From 630ceb42b1c91de8a3b531a09b27a1379cb2c9fd Mon Sep 17 00:00:00 2001 From: tellthemachines <tellthemachines@users.noreply.github.com> Date: Tue, 5 Nov 2024 16:08:09 +1100 Subject: [PATCH 1471/1908] Add "show template" to preview dropdown. (#66514) Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: paaljoachim <paaljoachim@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> --- .../src/components/document-bar/index.js | 11 +++- .../src/components/document-bar/style.scss | 13 ++++ .../src/components/preview-dropdown/index.js | 61 ++++++++++++++----- 3 files changed, 68 insertions(+), 17 deletions(-) diff --git a/packages/editor/src/components/document-bar/index.js b/packages/editor/src/components/document-bar/index.js index 031262f52f7268..30990379fe6301 100644 --- a/packages/editor/src/components/document-bar/index.js +++ b/packages/editor/src/components/document-bar/index.js @@ -15,7 +15,7 @@ import { __unstableAnimatePresence as AnimatePresence, } from '@wordpress/components'; import { BlockIcon } from '@wordpress/block-editor'; -import { chevronLeftSmall, chevronRightSmall } from '@wordpress/icons'; +import { chevronLeftSmall, chevronRightSmall, layout } from '@wordpress/icons'; import { displayShortcut } from '@wordpress/keycodes'; import { store as coreStore } from '@wordpress/core-data'; import { store as commandsStore } from '@wordpress/commands'; @@ -59,12 +59,14 @@ export default function DocumentBar( props ) { isNotFound, templateTitle, onNavigateToPreviousEntityRecord, + isTemplatePreview, } = useSelect( ( select ) => { const { getCurrentPostType, getCurrentPostId, getEditorSettings, __experimentalGetTemplateInfo: getTemplateInfo, + getRenderingMode, } = select( editorStore ); const { getEditedEntityRecord, @@ -96,6 +98,7 @@ export default function DocumentBar( props ) { templateTitle: _templateInfo.title, onNavigateToPreviousEntityRecord: getEditorSettings().onNavigateToPreviousEntityRecord, + isTemplatePreview: getRenderingMode() === 'template-locked', }; }, [] ); @@ -146,6 +149,12 @@ export default function DocumentBar( props ) { </MotionButton> ) } </AnimatePresence> + { ! isTemplate && isTemplatePreview && ( + <BlockIcon + icon={ layout } + className="editor-document-bar__icon-layout" + /> + ) } { isNotFound ? ( <Text>{ __( 'Document not found' ) }</Text> ) : ( diff --git a/packages/editor/src/components/document-bar/style.scss b/packages/editor/src/components/document-bar/style.scss index 6a7e7930f5bfb7..749da6ec8c9837 100644 --- a/packages/editor/src/components/document-bar/style.scss +++ b/packages/editor/src/components/document-bar/style.scss @@ -102,3 +102,16 @@ background-color: transparent; } } + +.editor-document-bar__icon-layout.editor-document-bar__icon-layout { + position: absolute; + margin-left: $grid-unit-15; + display: none; + pointer-events: none; + svg { + fill: $gray-600; + } + @include break-small { + display: flex; + } +} diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js index e7a19f92548f5f..6fa35c673430cc 100644 --- a/packages/editor/src/components/preview-dropdown/index.js +++ b/packages/editor/src/components/preview-dropdown/index.js @@ -16,7 +16,7 @@ import { Icon, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { desktop, mobile, tablet, external } from '@wordpress/icons'; +import { desktop, mobile, tablet, external, check } from '@wordpress/icons'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { store as preferencesStore } from '@wordpress/preferences'; @@ -31,21 +31,32 @@ import PostPreviewButton from '../post-preview-button'; import { unlock } from '../../lock-unlock'; export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { - const { deviceType, homeUrl, isTemplate, isViewable, showIconLabels } = - useSelect( ( select ) => { - const { getDeviceType, getCurrentPostType } = select( editorStore ); - const { getEntityRecord, getPostType } = select( coreStore ); - const { get } = select( preferencesStore ); - const _currentPostType = getCurrentPostType(); - return { - deviceType: getDeviceType(), - homeUrl: getEntityRecord( 'root', '__unstableBase' )?.home, - isTemplate: _currentPostType === 'wp_template', - isViewable: getPostType( _currentPostType )?.viewable ?? false, - showIconLabels: get( 'core', 'showIconLabels' ), - }; - }, [] ); - const { setDeviceType } = useDispatch( editorStore ); + const { + deviceType, + homeUrl, + isTemplate, + isViewable, + showIconLabels, + isTemplateHidden, + templateId, + } = useSelect( ( select ) => { + const { getDeviceType, getCurrentPostType, getCurrentTemplateId } = + select( editorStore ); + const { getRenderingMode } = unlock( select( editorStore ) ); + const { getEntityRecord, getPostType } = select( coreStore ); + const { get } = select( preferencesStore ); + const _currentPostType = getCurrentPostType(); + return { + deviceType: getDeviceType(), + homeUrl: getEntityRecord( 'root', '__unstableBase' )?.home, + isTemplate: _currentPostType === 'wp_template', + isViewable: getPostType( _currentPostType )?.viewable ?? false, + showIconLabels: get( 'core', 'showIconLabels' ), + isTemplateHidden: getRenderingMode() === 'post-only', + templateId: getCurrentTemplateId(), + }; + }, [] ); + const { setDeviceType, setRenderingMode } = useDispatch( editorStore ); const { resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); const handleDevicePreviewChange = ( newDeviceType ) => { @@ -142,6 +153,24 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { </MenuItem> </MenuGroup> ) } + { ! isTemplate && !! templateId && ( + <MenuGroup> + <MenuItem + icon={ ! isTemplateHidden ? check : undefined } + isSelected={ ! isTemplateHidden } + role="menuitemcheckbox" + onClick={ () => { + setRenderingMode( + isTemplateHidden + ? 'template-locked' + : 'post-only' + ); + } } + > + { __( 'Show template' ) } + </MenuItem> + </MenuGroup> + ) } { isViewable && ( <MenuGroup> <PostPreviewButton From 5d6ea1e3b9ba721a514c34f47742a7afbca0d71b Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Tue, 5 Nov 2024 07:17:55 +0100 Subject: [PATCH 1472/1908] Remove unnecessary tooltip from Video block Text tracks button. (#66716) Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-library/src/video/tracks-editor.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/block-library/src/video/tracks-editor.js b/packages/block-library/src/video/tracks-editor.js index 10fb241a9ecb30..e23d1c93378a69 100644 --- a/packages/block-library/src/video/tracks-editor.js +++ b/packages/block-library/src/video/tracks-editor.js @@ -204,8 +204,6 @@ export default function TracksEditor( { tracks = [], onChange } ) { renderToggle={ ( { isOpen, onToggle } ) => ( <ToolbarGroup> <ToolbarButton - label={ __( 'Text tracks' ) } - showTooltip aria-expanded={ isOpen } aria-haspopup="true" onClick={ onToggle } From 6d57cb4e7ec6b9b97049284cfa8fbbb1e76feb84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= <grzegorz@gziolo.pl> Date: Tue, 5 Nov 2024 08:16:21 +0100 Subject: [PATCH 1473/1908] Docs: Include a note about supported licenses in WordPress packages (#66562) * Docs: Include a note about supported licenses in WordPress packages * Update README.md * Update packages/README.md Co-authored-by: Pascal Birchler <pascalb@google.com> --------- Co-authored-by: Pascal Birchler <pascalb@google.com> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- packages/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/README.md b/packages/README.md index cc2f34e38ac055..f73aca35786f5a 100644 --- a/packages/README.md +++ b/packages/README.md @@ -43,9 +43,9 @@ When creating a new package, you need to provide at least the following. Package This assumes that your code is located in the `src` folder and will be transpiled with `Babel`. - For packages that should ship as a WordPress script, include `wpScript: true` in the `package.json` file. This tells the build system to bundle the package for use as a WordPress script. + For production packages that will ship as a WordPress script, include `wpScript: true` in the `package.json` file. This tells the build system to bundle the package for use as a WordPress script. - For packages that should ship as a WordPress script module, include a `wpScriptModuleExports` field the `package.json` file. The value of this field can be a string to expose a single script module, or an object with a [shape like the standard `exports` object](https://nodejs.org/docs/latest-v20.x/api/packages.html#subpath-exports) to expose multiple script modules from a single package: + For production packages that will ship as a WordPress script module, include a `wpScriptModuleExports` field in the `package.json` file. The value of this field can be a string to expose a single script module, or an object with a [shape like the standard `exports` object](https://nodejs.org/docs/latest-v20.x/api/packages.html#subpath-exports) to expose multiple script modules from a single package: ```jsonc { @@ -64,7 +64,7 @@ When creating a new package, you need to provide at least the following. Package } ``` - Both `wpScript` and `wpScriptModuleExports` may be included if the package exposes both a script and a script module. + Both `wpScript` and `wpScriptModuleExports` may be included if the package exposes both a script and a script module. These fields are also essential when performing a license check for all their dependencies, because they trigger strict validation against compatibility with GPL v2. All remaining dependencies WordPress doesn't distribute but uses for development purposes can contain also a few other OSS compatible licenses. 1. `README.md` file containing at least: - Package name From adaeff3cb7d8ddddcaf2d73fe94779a262962c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 5 Nov 2024 08:39:10 +0100 Subject: [PATCH 1474/1908] Storybook: fix Dataviews action modals (#66727) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- storybook/package-styles/config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storybook/package-styles/config.js b/storybook/package-styles/config.js index 21215fcad5c21e..d3614a0594b45c 100644 --- a/storybook/package-styles/config.js +++ b/storybook/package-styles/config.js @@ -55,8 +55,8 @@ const CONFIG = [ }, { componentIdMatcher: /^dataviews-/, - ltr: [ dataviewsLtr, componentsLtr ], - rtl: [ dataviewsRtl, componentsRtl ], + ltr: [ componentsLtr, dataviewsLtr ], + rtl: [ componentsRtl, dataviewsRtl ], }, ]; From 6270af662a8c785686028ee4373547e82f7e5e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 5 Nov 2024 08:47:06 +0100 Subject: [PATCH 1475/1908] Documentation: reorganize to bootstrap DataForm API section (#66729) --- packages/dataviews/README.md | 163 +++++++++++++++++++++-------------- 1 file changed, 96 insertions(+), 67 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 95b8fc898555c3..066a32fc40f47a 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -1,10 +1,9 @@ -# DataViews +# The `@wordpress/dataviews` package -DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.). +The DataViews package offers two components to work with a given dataset: -DataViews is data agnostic, it can work with data coming from a static (JSON file) or dynamic source (HTTP Request) — it just requires the data to be an array of objects that have an unique identifier. Consumers are responsible to query the data source appropiately based on the DataViews props: - -![DataViews flow](https://developer.wordpress.org/files/2024/09/368600071-20aa078f-7c3d-406d-8dd0-8b764addd22a.png "DataViews flow") +- `DataViews`: allows rendering a dataset using different types of layouts (table, grid, list) and interaction capabilities (search, filters, sorting, etc.). +- `DataForm`: allows editing the items from the same dataset. ## Installation @@ -14,7 +13,13 @@ Install the module npm install @wordpress/dataviews --save ``` -## Usage +## `DataViews` + +### Usage + +The component is data agnostic, it just requires the data to be an array of objects with an unique identifier — it can work with data coming from a static (e.g.: JSON file) or dynamic source (e.g.: HTTP Request). Consumers are responsible to query the data source appropiately: + +![DataViews flow](https://developer.wordpress.org/files/2024/09/368600071-20aa078f-7c3d-406d-8dd0-8b764addd22a.png "DataViews flow") ```jsx const Example = () => { @@ -34,11 +39,11 @@ const Example = () => { }; ``` -<div class="callout callout-info">At <a href="https://wordpress.github.io/gutenberg/">WordPress Gutenberg's Storybook</a> there's and <a href="https://wordpress.github.io/gutenberg/?path=/docs/dataviews-dataviews--docs">example implementation of the Dataviews component</a></div> +<div class="callout callout-info">At <a href="https://wordpress.github.io/gutenberg/">WordPress Gutenberg's Storybook</a> there's and <a href="https://wordpress.github.io/gutenberg/?path=/docs/dataviews-dataviews--docs">example implementation of the Dataviews component</a>.</div> -## Properties +### Properties -### `data`: `Object[]` +#### `data`: `Object[]` The dataset to work with, represented as a one-dimensional array. @@ -60,7 +65,7 @@ const data = [ By default, dataviews would use each record's `id` as an unique identifier. If it's not, the consumer should provide a `getItemId` function that returns one. -### `fields`: `Object[]` +#### `fields`: `Object[]` The fields describe the visible items for each record in the dataset. @@ -140,7 +145,7 @@ Each field is an object with the following properties: - `operators`: the list of [operators](#operators) supported by the field. - `isPrimary`: whether it is a primary filter. A primary filter is always visible and is not listed in the "Add filter" component, except for the list layout where it behaves like a secondary filter. -### `view`: `object` +#### `view`: `object` The view object configures how the dataset is visible to the user. @@ -183,7 +188,24 @@ Properties: - `fields`: the `id` of the fields that are visible in the UI and the specific order in which they are displayed. - `layout`: config that is specific to a particular layout type. -#### Properties of `layout` +##### Filter operators + +Allowed operators: + +| Operator | Selection | Description | Example | +| ---------- | -------------- | ----------------------------------------------------------------------- | -------------------------------------------------- | +| `is` | Single item | `EQUAL TO`. The item's field is equal to a single value. | Author is Admin | +| `isNot` | Single item | `NOT EQUAL TO`. The item's field is not equal to a single value. | Author is not Admin | +| `isAny` | Multiple items | `OR`. The item's field is present in a list of values. | Author is any: Admin, Editor | +| `isNone` | Multiple items | `NOT OR`. The item's field is not present in a list of values. | Author is none: Admin, Editor | +| `isAll` | Multiple items | `AND`. The item's field has all of the values in the list. | Category is all: Book, Review, Science Fiction | +| `isNotAll` | Multiple items | `NOT AND`. The item's field doesn't have all of the values in the list. | Category is not all: Book, Review, Science Fiction | + +`is` and `isNot` are single-selection operators, while `isAny`, `isNone`, `isAll`, and `isNotALl` are multi-selection. By default, a filter with no operators declared will support the `isAny` and `isNone` multi-selection operators. A filter cannot mix single-selection & multi-selection operators; if a single-selection operator is present in the list of valid operators, the multi-selection ones will be discarded and the filter won't allow selecting more than one item. + +> The legacy operators `in` and `notIn` have been deprecated and will be removed soon. In the meantime, they work as `is` and `isNot` operators, respectively. + +##### Properties of `layout` | Properties of `layout` | Table | Grid | List | | --------------------------------------------------------------------------------------------------------------- | ----- | ---- | ---- | @@ -194,7 +216,36 @@ Properties: | `combinedFields`: a list of "virtual" fields that are made by combining others. See "Combining fields" section. | ✓ | | | | `styles`: additional `width`, `maxWidth`, `minWidth` styles for each field column. | ✓ | | | -### `onChangeView`: `function` +##### Combining fields + +The `table` layout has the ability to create "virtual" fields that are made out by combining existing ones. + +Each "virtual field", has to provide an `id` and `label` (optionally a `header` instead), which have the same meaning as any other field. + +Additionally, they need to provide: + +- `children`: a list of field's `id` to combine +- `direction`: how should they be stacked, `vertical` or `horizontal` + +For example, this is how you'd define a `site` field which is a combination of a `title` and `description` fields, which are not displayed: + +```js +{ + fields: [ 'site', 'status' ], + layout: { + combinedFields: [ + { + id: 'site', + label: 'Site', + children: [ 'title', 'description' ], + direction: 'vertical', + } + ] + } +} +``` + +#### `onChangeView`: `function` The view is a representation of the visible state of the dataset: what type of layout is used to display it (table, grid, etc.), how the dataset is filtered, how it is sorted or paginated. @@ -259,7 +310,7 @@ function MyCustomPageTable() { } ``` -### `actions`: `Object[]` +#### `actions`: `Object[]` Collection of operations that can be performed upon each record. @@ -277,28 +328,28 @@ Each action is an object with the following properties: - `supportsBulk`: Whether the action can be used as a bulk action. False by default. - `disabled`: Whether the action is disabled. False by default. -### `paginationInfo`: `Object` +#### `paginationInfo`: `Object` - `totalItems`: the total number of items in the datasets. - `totalPages`: the total number of pages, taking into account the total items in the dataset and the number of items per page provided by the user. -### `search`: `boolean` +#### `search`: `boolean` Whether the search input is enabled. `true` by default. -### `searchLabel`: `string` +#### `searchLabel`: `string` What text to show in the search input. "Search" by default. -### `getItemId`: `function` +#### `getItemId`: `function` Function that receives an item and returns an unique identifier for it. By default, it uses the `id` of the item as unique identifier. If it's not, the consumer should provide their own. -### `isLoading`: `boolean` +#### `isLoading`: `boolean` Whether the data is loading. `false` by default. -### `defaultLayouts`: `Record< string, view >` +#### `defaultLayouts`: `Record< string, view >` This property provides layout information about the view types that are active. If empty, enables all layout types (see "Layout Types") with empty layout data. @@ -316,67 +367,45 @@ const defaultLayouts = { The `defaultLayouts` property should be an object that includes properties named `table`, `grid`, or `list`. Each of these properties should contain a `layout` property, which holds the configuration for each specific layout type. Check [here](#properties-of-layout) the full list of properties available for each layout's configuration -### `onChangeSelection`: `function` +#### `onChangeSelection`: `function` Callback that signals the user selected one of more items, and takes them as parameter. So far, only the `list` view implements it. -## Types - -### Layouts - -- `table`: the view uses a table layout. -- `grid`: the view uses a grid layout. -- `list`: the view uses a list layout. - -### Fields - -> The `enumeration` type was removed as it was deemed redundant with the field.elements metadata. New types will be introduced soon. +## `DataForm` -## Combining fields +### Usage -The `table` layout has the ability to create "virtual" fields that are made out by combining existing ones. - -Each "virtual field", has to provide an `id` and `label` (optionally a `header` instead), which have the same meaning as any other field. +```jsx +const Example = () => { + // Declare data, fields, etc. -Additionally, they need to provide: + return ( + <DataForm + data={ data } + fields={ fields } + form={ form } + onChange={ onChange } + /> + ) +} +``` -- `children`: a list of field's `id` to combine -- `direction`: how should they be stacked, `vertical` or `horizontal` +<div class="callout callout-info">At <a href="https://wordpress.github.io/gutenberg/">WordPress Gutenberg's Storybook</a> there's and <a href="https://wordpress.github.io/gutenberg/?path=/docs/dataviews-dataform--docs">example implementation of the DataForm component</a>.</div> -For example, this is how you'd define a `site` field which is a combination of a `title` and `description` fields, which are not displayed: +### Props -```js -{ - fields: [ 'site', 'status' ], - layout: { - combinedFields: [ - { - id: 'site', - label: 'Site', - children: [ 'title', 'description' ], - direction: 'vertical', - } - ] - } -} -``` +#### `data`: `Object[]` -### Operators +Same as `data` property of `DataViews`. -Allowed operators: +#### `fields`: `Object[]` -| Operator | Selection | Description | Example | -| ---------- | -------------- | ----------------------------------------------------------------------- | -------------------------------------------------- | -| `is` | Single item | `EQUAL TO`. The item's field is equal to a single value. | Author is Admin | -| `isNot` | Single item | `NOT EQUAL TO`. The item's field is not equal to a single value. | Author is not Admin | -| `isAny` | Multiple items | `OR`. The item's field is present in a list of values. | Author is any: Admin, Editor | -| `isNone` | Multiple items | `NOT OR`. The item's field is not present in a list of values. | Author is none: Admin, Editor | -| `isAll` | Multiple items | `AND`. The item's field has all of the values in the list. | Category is all: Book, Review, Science Fiction | -| `isNotAll` | Multiple items | `NOT AND`. The item's field doesn't have all of the values in the list. | Category is not all: Book, Review, Science Fiction | +Same as `fields` property of `DataViews`. -`is` and `isNot` are single-selection operators, while `isAny`, `isNone`, `isAll`, and `isNotALl` are multi-selection. By default, a filter with no operators declared will support the `isAny` and `isNone` multi-selection operators. A filter cannot mix single-selection & multi-selection operators; if a single-selection operator is present in the list of valid operators, the multi-selection ones will be discarded and the filter won't allow selecting more than one item. +#### `form`: `Object[]` -> The legacy operators `in` and `notIn` have been deprecated and will be removed soon. In the meantime, they work as `is` and `isNot` operators, respectively. +- `type`: either `regular` or `panel`. +- `fields`: a list of fields ids that should be rendered. ## Contributing to this package From 2da866b34525bb49fa79a21176dc95c9525e68d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 5 Nov 2024 09:16:15 +0100 Subject: [PATCH 1476/1908] Document `filterSortAndPaginate` & `isItemValid` utilities (#66738) --- packages/dataviews/README.md | 31 ++++++++++++++++++++++++++++ packages/dataviews/src/validation.ts | 9 ++++++++ 2 files changed, 40 insertions(+) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 066a32fc40f47a..79875542378b3e 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -407,6 +407,37 @@ Same as `fields` property of `DataViews`. - `type`: either `regular` or `panel`. - `fields`: a list of fields ids that should be rendered. +## Utilities + +### `filterSortAndPaginate` + +Utility to apply the view config (filters, search, sorting, and pagination) to a dataset client-side. + +Parameters: + +- `data`: the dataset, as described in the "data" property of DataViews. +- `view`: the view config, as described in the "view" property of DataViews. +- `fields`: the fields config, as described in the "fields" property of DataViews. + +Returns an object containing: + +- `data`: the new dataset, with the view config applied. +- `paginationInfo`: object containing the following properties: + - `totalItems`: total number of items for the current view config. + - `totalPages`: total number of pages for the current view config. + +### `isItemValid` + +Utility to determine whether or not the given item's value is valid according to the current fields and form config. + +Parameters: + +- `item`: the item, as described in the "data" property of DataForm. +- `fields`: the fields config, as described in the "fields" property of DataForm. +- `form`: the form config, as described in the "form" property of DataForm. + +Returns a boolean indicating if the item is valid (true) or not (false). + ## Contributing to this package This is an individual package that's part of the Gutenberg project. The project is organized as a monorepo. It's made up of multiple self-contained software packages, each with a specific purpose. The packages in this monorepo are published to [npm](https://www.npmjs.com/) and used by [WordPress](https://make.wordpress.org/core/) as well as other software projects. diff --git a/packages/dataviews/src/validation.ts b/packages/dataviews/src/validation.ts index 41969a7960af65..0a6542da4e8d40 100644 --- a/packages/dataviews/src/validation.ts +++ b/packages/dataviews/src/validation.ts @@ -4,6 +4,15 @@ import { normalizeFields } from './normalize-fields'; import type { Field, Form } from './types'; +/** + * Whether or not the given item's value is valid according to the fields and form config. + * + * @param item The item to validate. + * @param fields Fields config. + * @param form Form config. + * + * @return A boolean indicating if the item is valid (true) or not (false). + */ export function isItemValid< Item >( item: Item, fields: Field< Item >[], From 3dece5ef458978a018f4280abfaa4e39ad92e554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 5 Nov 2024 11:20:30 +0100 Subject: [PATCH 1477/1908] Documentation: move docs for filters to proper place (#66743) --- packages/dataviews/README.md | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 79875542378b3e..00ab60ff5d0474 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -142,9 +142,22 @@ Each field is an object with the following properties: - `enableHiding`: whether the field can be hidden. True by default. - `enableGlobalSearch`: whether the field is searchable. False by default. - `filterBy`: configuration for the filters enabled by the `elements` property. - - `operators`: the list of [operators](#operators) supported by the field. + - `operators`: the list of operators supported by the field. - `isPrimary`: whether it is a primary filter. A primary filter is always visible and is not listed in the "Add filter" component, except for the list layout where it behaves like a secondary filter. +##### Filter operators + +| Operator | Selection | Description | Example | +| ---------- | -------------- | ----------------------------------------------------------------------- | -------------------------------------------------- | +| `is` | Single item | `EQUAL TO`. The item's field is equal to a single value. | Author is Admin | +| `isNot` | Single item | `NOT EQUAL TO`. The item's field is not equal to a single value. | Author is not Admin | +| `isAny` | Multiple items | `OR`. The item's field is present in a list of values. | Author is any: Admin, Editor | +| `isNone` | Multiple items | `NOT OR`. The item's field is not present in a list of values. | Author is none: Admin, Editor | +| `isAll` | Multiple items | `AND`. The item's field has all of the values in the list. | Category is all: Book, Review, Science Fiction | +| `isNotAll` | Multiple items | `NOT AND`. The item's field doesn't have all of the values in the list. | Category is not all: Book, Review, Science Fiction | + +`is` and `isNot` are single-selection operators, while `isAny`, `isNone`, `isAll`, and `isNotALl` are multi-selection. By default, a filter with no operators declared will support the `isAny` and `isNone` multi-selection operators. A filter cannot mix single-selection & multi-selection operators; if a single-selection operator is present in the list of valid operators, the multi-selection ones will be discarded and the filter won't allow selecting more than one item. + #### `view`: `object` The view object configures how the dataset is visible to the user. @@ -188,23 +201,6 @@ Properties: - `fields`: the `id` of the fields that are visible in the UI and the specific order in which they are displayed. - `layout`: config that is specific to a particular layout type. -##### Filter operators - -Allowed operators: - -| Operator | Selection | Description | Example | -| ---------- | -------------- | ----------------------------------------------------------------------- | -------------------------------------------------- | -| `is` | Single item | `EQUAL TO`. The item's field is equal to a single value. | Author is Admin | -| `isNot` | Single item | `NOT EQUAL TO`. The item's field is not equal to a single value. | Author is not Admin | -| `isAny` | Multiple items | `OR`. The item's field is present in a list of values. | Author is any: Admin, Editor | -| `isNone` | Multiple items | `NOT OR`. The item's field is not present in a list of values. | Author is none: Admin, Editor | -| `isAll` | Multiple items | `AND`. The item's field has all of the values in the list. | Category is all: Book, Review, Science Fiction | -| `isNotAll` | Multiple items | `NOT AND`. The item's field doesn't have all of the values in the list. | Category is not all: Book, Review, Science Fiction | - -`is` and `isNot` are single-selection operators, while `isAny`, `isNone`, `isAll`, and `isNotALl` are multi-selection. By default, a filter with no operators declared will support the `isAny` and `isNone` multi-selection operators. A filter cannot mix single-selection & multi-selection operators; if a single-selection operator is present in the list of valid operators, the multi-selection ones will be discarded and the filter won't allow selecting more than one item. - -> The legacy operators `in` and `notIn` have been deprecated and will be removed soon. In the meantime, they work as `is` and `isNot` operators, respectively. - ##### Properties of `layout` | Properties of `layout` | Table | Grid | List | From 0c869d4b4d2272efdeb37297051876043c2ed556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 5 Nov 2024 13:47:01 +0100 Subject: [PATCH 1478/1908] Documentation: add missing properties for DataViews/DataForm components (#66749) --- packages/dataviews/README.md | 117 +++++++++++++++++++++++++++-------- 1 file changed, 90 insertions(+), 27 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 00ab60ff5d0474..d61df206409152 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -63,7 +63,7 @@ const data = [ ]; ``` -By default, dataviews would use each record's `id` as an unique identifier. If it's not, the consumer should provide a `getItemId` function that returns one. +By default, dataviews would use each record's `id` as an unique identifier. If the records don't have a `id` property that identify them uniquely, they consumer needs to provide a `getItemId` function that returns an unique identifier for the record. #### `fields`: `Object[]` @@ -109,8 +109,8 @@ const fields = [ enableSorting: false, }, { - label: __( 'Status' ), id: 'status', + label: __( 'Status' ), getValue: ( { item } ) => STATUSES.find( ( { value } ) => value === item.status )?.label ?? item.status, @@ -126,27 +126,35 @@ const fields = [ Each field is an object with the following properties: - `id`: identifier for the field. Unique. +- `type`: the type of the field. See "Field types" section. - `label`: the field's name to be shown in the UI. +- `header`: defaults to the label. Allows providing a React element to render the field labels. - `getValue`: function that returns the value of the field, defaults to `field[id]`. - `render`: function that renders the field. Optional, `getValue` will be used if `render` is not defined. -- <code id="fields-elements">elements</code>: The list of options to pick from when using the field as a filter or when editing (DataForm component). It expects an array of objects with the following properties: - - - `value`: The id of the value to filter to (for internal use) - - `label`: The text that will be displayed in the UI for the item. - - `description`: A longer description that describes the element, to also be displayed. Optional. - - To enable the filter by a field we just need to set a proper value to the `elements` property of the field we'd like to filter by. - -- `type`: the type of the field. See "Field types". +- `Edit`: function that renders an edit control for the field. Alternatively, can provide a string declaring one of default controls provided by DataForm `text`, `integer`, `datetime`, `radio`, `select`. +- `sort`: a compare function that determines the order of the records. +- `isValid`: callback to decide if a field should be displayed. +- `isVisible`: callback to decide if a field should be visible. - `enableSorting`: whether the data can be sorted by the given field. True by default. - `enableHiding`: whether the field can be hidden. True by default. - `enableGlobalSearch`: whether the field is searchable. False by default. +- <code id="fields-elements">elements</code>: The list of options to pick from when using the field as a filter or when editing (DataForm component). Providing a list of to the field automatically creates a filter for it. It expects an array of objects with the following properties: + - `value`: The id of the value to filter to (for internal use) + - `label`: The text that will be displayed in the UI for the item. + - `description`: A longer description that describes the element, to also be displayed. Optional. - `filterBy`: configuration for the filters enabled by the `elements` property. - - `operators`: the list of operators supported by the field. + - `operators`: the list of operators supported by the field. See "Filter operators" below. - `isPrimary`: whether it is a primary filter. A primary filter is always visible and is not listed in the "Add filter" component, except for the list layout where it behaves like a secondary filter. +##### Field types + +Current supported types include: `text`, `integer`, `datetime`. + +If a field declares a `type` the `sort`, `isValid`, and `Edit` functions will be provided with default implementations. They will overriden if the field provides its own. + ##### Filter operators + | Operator | Selection | Description | Example | | ---------- | -------------- | ----------------------------------------------------------------------- | -------------------------------------------------- | | `is` | Single item | `EQUAL TO`. The item's field is equal to a single value. | Author is Admin | @@ -158,7 +166,7 @@ Each field is an object with the following properties: `is` and `isNot` are single-selection operators, while `isAny`, `isNone`, `isAll`, and `isNotALl` are multi-selection. By default, a filter with no operators declared will support the `isAny` and `isNone` multi-selection operators. A filter cannot mix single-selection & multi-selection operators; if a single-selection operator is present in the list of valid operators, the multi-selection ones will be discarded and the filter won't allow selecting more than one item. -#### `view`: `object` +#### `view`: `Object` The view object configures how the dataset is visible to the user. @@ -198,7 +206,7 @@ Properties: - `field`: the field used for sorting the dataset. - `direction`: the direction to use for sorting, one of `asc` or `desc`. -- `fields`: the `id` of the fields that are visible in the UI and the specific order in which they are displayed. +- `fields`: a list of field `id` that are visible in the UI and the specific order in which they are displayed. - `layout`: config that is specific to a particular layout type. ##### Properties of `layout` @@ -243,9 +251,9 @@ For example, this is how you'd define a `site` field which is a combination of a #### `onChangeView`: `function` -The view is a representation of the visible state of the dataset: what type of layout is used to display it (table, grid, etc.), how the dataset is filtered, how it is sorted or paginated. +Callback executed when the view has changed. It receives the new view object as a parameter. -It's the consumer's responsibility to work with the data provider to make sure the user options defined through the view's config (sort, pagination, filters, etc.) are respected. The `onChangeView` prop allows the consumer to provide a callback to be called when the view config changes, to process the data accordingly. +The view is a representation of the visible state of the dataset: what type of layout is used to display it (table, grid, etc.), how the dataset is filtered, how it is sorted or paginated. It's the consumer's responsibility to use the view config to query the data provider and make sure the user decisions (sort, pagination, filters, etc.) are respected. The following example shows how a view object is used to query the WordPress REST API via the entities abstraction. The same can be done with any other data provider. @@ -313,16 +321,18 @@ Collection of operations that can be performed upon each record. Each action is an object with the following properties: - `id`: string, required. Unique identifier of the action. For example, `move-to-trash`. -- `label`: string|function, required. User facing description of the action. For example, `Move to Trash`. In case we want to adjust the label based on the selected items, a function which accepts the selected records as input can be provided. This function should always return a `string` value. +- `label`: string|function, required. User facing description of the action. For example, `Move to Trash`. It can also take a function that takes the selected items as a parameter and returns a string: this can be useful to provide a dynamic label based on the selection. - `isPrimary`: boolean, optional. Whether the action should be listed inline (primary) or in hidden in the more actions menu (secondary). -- `icon`: icon to show for primary actions. It's required for a primary action, otherwise the action would be considered secondary. +- `icon`: SVG element. Icon to show for primary actions. It's required for a primary action, otherwise the action would be considered secondary. - `isEligible`: function, optional. Whether the action can be performed for a given record. If not present, the action is considered to be eligible for all items. It takes the given record as input. - `isDestructive`: boolean, optional. Whether the action can delete data, in which case the UI would communicate it via red color. -- `callback`: function, required unless `RenderModal` is provided. Callback function that takes the record as input and performs the required action. -- `RenderModal`: ReactElement, optional. If an action requires that some UI be rendered in a modal, it can provide a component which takes as props the record as `item` and a `closeModal` function. When this prop is provided, the `callback` property is ignored. -- `hideModalHeader`: boolean, optional. This property is used in combination with `RenderModal` and controls the visibility of the modal's header. If the action renders a modal and doesn't hide the header, the action's label is going to be used in the modal's header. - `supportsBulk`: Whether the action can be used as a bulk action. False by default. - `disabled`: Whether the action is disabled. False by default. +- `context`: where this action would be visible. One of `list`, `single`. +- `callback`: function, required unless `RenderModal` is provided. Callback function that takes as input the list of items to operate with, and performs the required action. +- `RenderModal`: ReactElement, optional. If an action requires that some UI be rendered in a modal, it can provide a component which takes as input the the list of `items` to operate with, `closeModal` function, and `onActionPerformed` function. When this prop is provided, the `callback` property is ignored. +- `hideModalHeader`: boolean, optional. This property is used in combination with `RenderModal` and controls the visibility of the modal's header. If the action renders a modal and doesn't hide the header, the action's label is going to be used in the modal's header. +- `modalHeader`: string, optional. The header of the modal. #### `paginationInfo`: `Object` @@ -339,7 +349,9 @@ What text to show in the search input. "Search" by default. #### `getItemId`: `function` -Function that receives an item and returns an unique identifier for it. By default, it uses the `id` of the item as unique identifier. If it's not, the consumer should provide their own. +Function that receives an item and returns an unique identifier for it. + +By default, dataviews would use each record's `id` as an unique identifier. If the records don't have a `id` property that identify them uniquely, they consumer needs to provide a `getItemId` function that returns an unique identifier for the record. #### `isLoading`: `boolean` @@ -361,11 +373,23 @@ const defaultLayouts = { }; ``` -The `defaultLayouts` property should be an object that includes properties named `table`, `grid`, or `list`. Each of these properties should contain a `layout` property, which holds the configuration for each specific layout type. Check [here](#properties-of-layout) the full list of properties available for each layout's configuration +The `defaultLayouts` property should be an object that includes properties named `table`, `grid`, or `list`. Each of these properties should contain a `layout` property, which holds the configuration for each specific layout type. Check "Properties of layout" for the full list of properties available for each layout's configuration + +#### `selection`: `string[]` + +The list of selected items' ids. + +If `selection` and `onChangeSelection` are provided, the `DataViews` component behaves as a controlled component, otherwise, it behaves like an uncontrolled component. #### `onChangeSelection`: `function` -Callback that signals the user selected one of more items, and takes them as parameter. So far, only the `list` view implements it. +Callback that signals the user selected one of more items. It receives the list of selected items' ids as a parameter. + +If `selection` and `onChangeSelection` are provided, the `DataViews` component behaves as a controlled component, otherwise, it behaves like an uncontrolled component. + +#### `header`: React component + +React component to be rendered next to the view config button. ## `DataForm` @@ -388,11 +412,13 @@ const Example = () => { <div class="callout callout-info">At <a href="https://wordpress.github.io/gutenberg/">WordPress Gutenberg's Storybook</a> there's and <a href="https://wordpress.github.io/gutenberg/?path=/docs/dataviews-dataform--docs">example implementation of the DataForm component</a>.</div> -### Props +### Properties -#### `data`: `Object[]` +#### `data`: `Object` + +A single item to be edited. -Same as `data` property of `DataViews`. +This could be thought as as a single record coming from the `data` property of `DataViews` — though it doesn't need to be; it can be, for example, a mix of records if you support bulk editing. #### `fields`: `Object[]` @@ -403,6 +429,43 @@ Same as `fields` property of `DataViews`. - `type`: either `regular` or `panel`. - `fields`: a list of fields ids that should be rendered. +#### `onChange`: `function` + +Callback function that receives an object with the edits done by the user. + +Example: + +```js +const data = { + id: 1, + title: 'Title', + author: 'Admin', + date: '2012-04-23T18:25:43.511Z', +}; + +const onChange = ( edits ) => { + /* + * edits will contain user edits. + * For example, if the user edited the title + * edits will be: + * + * { + * title: 'New title' + * } + * + */ +}; + +return ( + <DataForm + data={data} + fields={fields} + form={form} + onChange={onChange} + /> +); +``` + ## Utilities ### `filterSortAndPaginate` From 6cfeadc0d3a5361307877b095fdb981335dac4e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= <grzegorz@gziolo.pl> Date: Tue, 5 Nov 2024 15:06:35 +0100 Subject: [PATCH 1479/1908] Tools: Enforce the same order of fields in `package.json` files (#66239) * Update package managing flow * Adapt packages webpack config for workspaces * Ignore "dev" scripts this should be done another way * Annotate packages included as WordPress scripts * Do not annotate react-native packages * Update packages webpack to use wpScript package.json * Implement Gutenberg specific check-licenses script * Remove redundant entries from the ignore list * Update some docs langauge about lerna and npm workspaces * Tools: Enforce the same order of fields in `package.json` files * Update the PR number in the changelog entry * Update packages/npm-package-json-lint-config/index.js Co-authored-by: Jon Surrell <sirreal@users.noreply.github.com> * Update CHANGELOG.md * Update the order of properties added recently --------- Co-authored-by: Aki Hamano <tetsuaki.hamano@gmail.com> Co-authored-by: Jon Surrell <sirreal@users.noreply.github.com> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/a11y/package.json | 6 +++--- packages/annotations/package.json | 4 ++-- packages/api-fetch/package.json | 4 ++-- packages/autop/package.json | 4 ++-- packages/blob/package.json | 4 ++-- packages/block-directory/package.json | 4 ++-- packages/block-editor/package.json | 4 ++-- packages/block-library/package.json | 14 +++++++------- .../package.json | 4 ++-- .../block-serialization-spec-parser/package.json | 4 ++-- packages/blocks/package.json | 4 ++-- packages/commands/package.json | 4 ++-- packages/components/package.json | 6 +++--- packages/compose/package.json | 4 ++-- packages/core-commands/package.json | 4 ++-- packages/core-data/package.json | 4 ++-- packages/customize-widgets/package.json | 4 ++-- packages/data-controls/package.json | 4 ++-- packages/data/package.json | 4 ++-- packages/dataviews/package.json | 4 ++-- packages/date/package.json | 4 ++-- packages/deprecated/package.json | 4 ++-- packages/dom-ready/package.json | 4 ++-- packages/dom/package.json | 4 ++-- packages/edit-post/package.json | 4 ++-- packages/edit-site/package.json | 4 ++-- packages/edit-widgets/package.json | 4 ++-- packages/editor/package.json | 4 ++-- packages/element/package.json | 4 ++-- packages/escape-html/package.json | 4 ++-- packages/fields/package.json | 4 ++-- packages/format-library/package.json | 4 ++-- packages/hooks/package.json | 4 ++-- packages/html-entities/package.json | 4 ++-- packages/i18n/package.json | 4 ++-- packages/icons/package.json | 6 +++--- packages/interactivity-router/package.json | 2 +- packages/interactivity/package.json | 2 +- packages/interface/package.json | 4 ++-- packages/is-shallow-equal/package.json | 4 ++-- packages/keyboard-shortcuts/package.json | 4 ++-- packages/keycodes/package.json | 4 ++-- packages/list-reusable-blocks/package.json | 4 ++-- packages/media-utils/package.json | 4 ++-- packages/notices/package.json | 4 ++-- packages/npm-package-json-lint-config/CHANGELOG.md | 4 ++++ packages/npm-package-json-lint-config/index.js | 4 ++++ packages/nux/package.json | 4 ++-- packages/patterns/package.json | 4 ++-- packages/plugins/package.json | 4 ++-- packages/preferences-persistence/package.json | 4 ++-- packages/preferences/package.json | 4 ++-- packages/primitives/package.json | 6 +++--- packages/priority-queue/package.json | 4 ++-- packages/private-apis/package.json | 4 ++-- packages/react-i18n/package.json | 4 ++-- packages/redux-routine/package.json | 4 ++-- packages/reusable-blocks/package.json | 4 ++-- packages/rich-text/package.json | 6 +++--- packages/router/package.json | 4 ++-- packages/server-side-render/package.json | 4 ++-- packages/shortcode/package.json | 4 ++-- packages/style-engine/package.json | 4 ++-- packages/sync/package.json | 4 ++-- packages/token-list/package.json | 4 ++-- packages/undo-manager/package.json | 4 ++-- packages/url/package.json | 4 ++-- packages/viewport/package.json | 4 ++-- packages/vips/package.json | 4 ++-- packages/warning/package.json | 4 ++-- packages/widgets/package.json | 4 ++-- packages/wordcount/package.json | 4 ++-- 72 files changed, 156 insertions(+), 148 deletions(-) diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 09fa62a9d082b7..008bd9088e0778 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -27,8 +27,9 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", - "types": "build-types", + "wpScript": true, "wpScriptModuleExports": "./build-module/module/index.js", + "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/dom-ready": "*", @@ -36,6 +37,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 8a94b326a78194..b1d6d210807a87 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/data": "*", @@ -38,6 +39,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 26f156a0aa7d77..7d5b8dfd588897 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", @@ -34,6 +35,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/autop/package.json b/packages/autop/package.json index 2169ff828da47a..336dda06edfe2c 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -32,6 +33,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/blob/package.json b/packages/blob/package.json index 4b04d2ea2ddebd..0dc01ac7198f59 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -32,6 +33,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 59025e1ad45c7a..18a40824aa4754 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/a11y": "*", @@ -54,6 +55,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 2b5cc8d6275e89..26b06474f54b18 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "sideEffects": [ "build-style/**", "src/**/*.scss", @@ -87,6 +88,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 2c880301c8355d..b196e53e5cd0f9 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -25,11 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", - "sideEffects": [ - "build-style/**", - "src/**/*.scss", - "{src,build,build-module}/*/init.js" - ], + "wpScript": true, "wpScriptModuleExports": { "./file/view": "./build-module/file/view.js", "./image/view": "./build-module/image/view.js", @@ -37,6 +33,11 @@ "./query/view": "./build-module/query/view.js", "./search/view": "./build-module/search/view.js" }, + "sideEffects": [ + "build-style/**", + "src/**/*.scss", + "{src,build,build-module}/*/init.js" + ], "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/a11y": "*", @@ -88,6 +89,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index d31ab188c0b6d6..010132ac971db1 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -33,6 +34,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 7cca4a7ca1a68b..d430d2afeebf5a 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -25,6 +25,7 @@ "npm": ">=8.19.2" }, "main": "parser.js", + "wpScript": true, "sideEffects": false, "dependencies": { "pegjs": "^0.10.0", @@ -37,6 +38,5 @@ "build": "concurrently \"npm run build:js\" \"npm run build:php\"", "build:js": "pegjs --format commonjs -o ./parser.js ./grammar.pegjs", "build:php": "node bin/create-php-parser.js" - }, - "wpScript": true + } } diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 2d944fe656363b..42890e9b7d56bc 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "sideEffects": [ "{src,build,build-module}/{index.js,store/index.js}" ], @@ -62,6 +63,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/commands/package.json b/packages/commands/package.json index 98eadca595ca86..cebf3237a00d75 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/components": "*", @@ -44,6 +45,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/components/package.json b/packages/components/package.json index faf923ad426bf6..6871511cf5b1e5 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -25,11 +25,12 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, + "types": "build-types", "sideEffects": [ "build-style/**", "src/**/*.scss" ], - "types": "build-types", "dependencies": { "@ariakit/react": "^0.4.10", "@babel/runtime": "7.25.7", @@ -83,6 +84,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/compose/package.json b/packages/compose/package.json index adff24f6663006..68b00b24298d87 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -27,6 +27,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -49,6 +50,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index ac15b3578cf6ff..db2fb900865c80 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", @@ -48,6 +49,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 44ed3aaad5dd3a..a7216e931a70ca 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": [ "{src,build,build-module}/index.js" @@ -60,6 +61,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index ef6748f34205e8..41b3a7bd463aa3 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -23,6 +23,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/block-editor": "*", @@ -55,6 +56,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 948efe7fb64022..e4898ff1d0e1ab 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", @@ -38,6 +39,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/data/package.json b/packages/data/package.json index 0e46b1a366918e..fd1ef7ef4d7489 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -50,6 +51,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index 5599a84b92d34c..df30fea1a1c714 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -47,6 +48,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/date/package.json b/packages/date/package.json index f53c6314912271..d67c1dc527caee 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", @@ -34,6 +35,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 69d2414b0c11a2..64ffc6cd30b251 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -33,6 +34,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 0202229b202842..6e7986c4965dc6 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -32,6 +33,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/dom/package.json b/packages/dom/package.json index 58c572545cc526..97576e9a22e0ff 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -34,6 +35,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index c594722d180e4f..1b28c1d5f31aa6 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/a11y": "*", @@ -66,6 +67,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 95f9cd5f05742a..67932bcb06321e 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "dependencies": { "@babel/runtime": "7.25.7", "@react-spring/web": "^9.4.5", @@ -82,6 +83,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 0629dca5ec1052..331dbc742dbc8c 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "*", @@ -63,6 +64,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/editor/package.json b/packages/editor/package.json index 61cce478cf08fe..e7b46685719dd4 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "sideEffects": [ "build-style/**", "src/**/*.scss", @@ -85,6 +86,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/element/package.json b/packages/element/package.json index 3004dadb7ea605..4a196255971cfb 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -40,6 +41,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 72863ce15fd8b8..135876460bd05e 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -32,6 +33,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/fields/package.json b/packages/fields/package.json index e0b7125cf3e4eb..34ef8992f93adf 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": [ "build-style/**", @@ -62,6 +63,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/format-library/package.json b/packages/format-library/package.json index f07ba0f4b61b35..41852910ff5389 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/a11y": "*", @@ -46,6 +47,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/hooks/package.json b/packages/hooks/package.json index d0f2fd381b83ca..857cb24a877468 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -25,12 +25,12 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index d717a89bf049b8..4ecab2056c9c3a 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -26,12 +26,12 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 33de2873f75a6a..53e81b64a65349 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "bin": { "pot-to-php": "./tools/pot-to-php.js" @@ -39,6 +40,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/icons/package.json b/packages/icons/package.json index 125b6f19beaa02..895f2e184b4e48 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -16,7 +16,6 @@ "url": "git+https://github.com/WordPress/gutenberg.git", "directory": "packages/icons" }, - "sideEffects": false, "bugs": { "url": "https://github.com/WordPress/gutenberg/issues" }, @@ -27,7 +26,9 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", + "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/element": "*", @@ -35,6 +36,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index ce9b268af556ac..378ddda56ee76b 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -25,8 +25,8 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", - "types": "build-types", "wpScriptModuleExports": "./build-module/index.js", + "types": "build-types", "dependencies": { "@wordpress/a11y": "*", "@wordpress/interactivity": "*" diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 106ed44bf44d39..c9edd586bc9959 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -25,11 +25,11 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", - "types": "build-types", "wpScriptModuleExports": { ".": "./build-module/index.js", "./debug": "./build-module/debug.js" }, + "types": "build-types", "dependencies": { "@preact/signals": "^1.3.0", "preact": "^10.24.2" diff --git a/packages/interface/package.json b/packages/interface/package.json index 807135ae0160a6..f6a7952cb0d051 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "sideEffects": [ "build-style/**", "src/**/*.scss", @@ -52,6 +53,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 8da2643a58b840..7dafdea88e7a4f 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -34,6 +34,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -41,6 +42,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 50ee79d554a89f..ce029907c0dbf4 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/data": "*", @@ -36,6 +37,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 3e820ef68cf97e..2038db1984760f 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -33,6 +34,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 129909a948ef1d..328695f31925ee 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -25,6 +25,7 @@ }, "main": "build/index.js", "module": "build-module/index.js", + "wpScript": true, "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "*", @@ -41,6 +42,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 20eef4dd83c6b4..e57b0f51844504 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -25,6 +25,7 @@ }, "main": "build/index.js", "module": "build-module/index.js", + "wpScript": true, "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", @@ -36,6 +37,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/notices/package.json b/packages/notices/package.json index 34d2253870128b..f150616445b060 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", @@ -36,6 +37,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/npm-package-json-lint-config/CHANGELOG.md b/packages/npm-package-json-lint-config/CHANGELOG.md index 9c0aafedcead1a..9dee828f63fea0 100644 --- a/packages/npm-package-json-lint-config/CHANGELOG.md +++ b/packages/npm-package-json-lint-config/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancement + +- Include `exports`, `wpScript`, `wpScriptModuleExports` and `sideEffects` in the `prefer-property-order` rule ([#66239](https://github.com/WordPress/gutenberg/pull/66239)). + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/npm-package-json-lint-config/index.js b/packages/npm-package-json-lint-config/index.js index 831970c59bf3a6..e1abd5e34f99c5 100644 --- a/packages/npm-package-json-lint-config/index.js +++ b/packages/npm-package-json-lint-config/index.js @@ -56,8 +56,12 @@ const defaultConfig = { 'type', 'main', 'module', + 'exports', 'react-native', + 'wpScript', + 'wpScriptModuleExports', 'types', + 'sideEffects', 'bin', 'dependencies', 'devDependencies', diff --git a/packages/nux/package.json b/packages/nux/package.json index ccf1cb774c2424..50a4d5acf6d028 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "sideEffects": [ "build-style/**", "src/**/*.scss", @@ -46,6 +47,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 92ef655dc3c9c7..d29fc9bcf49bca 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "sideEffects": [ "build-style/**", "src/**/*.scss", @@ -53,6 +54,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/plugins/package.json b/packages/plugins/package.json index b741c0359b32b1..a926c2fd9a4e17 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", @@ -43,6 +44,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index e2623eac1a021c..05d2cf7031929d 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", @@ -33,6 +34,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/preferences/package.json b/packages/preferences/package.json index ef231f359ba143..205f9b5d4966b1 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -27,6 +27,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7", @@ -47,6 +48,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 04c3cc86dddec3..d24bc1acf25e2d 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -26,10 +26,11 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, + "types": "build-types", "sideEffects": [ "src/**/*.scss" ], - "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/element": "*", @@ -40,6 +41,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 91020c0f81db24..8c98b0b3552198 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -34,6 +35,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index 9364a596c39af0..84436470521332 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -33,6 +34,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index d98a4d7711f89c..31c4d98fa475e0 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -35,6 +36,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 489bc14632ded2..b3aa6fa79474a8 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -27,6 +27,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -40,6 +41,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 82a812163a0ccc..e2649609016642 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "sideEffects": [ "{src,build,build-module}/{index.js,store/index.js}" ], @@ -48,6 +49,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 4a5fe0f8e9d5ca..f038e097668984 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -25,11 +25,12 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, + "types": "build-types", "sideEffects": [ "src/**/*.scss", "{src,build,build-module}/{index.js,store/index.js}" ], - "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/a11y": "*", @@ -47,6 +48,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/router/package.json b/packages/router/package.json index 1822e79a317102..3d80481c9b6baa 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", @@ -38,6 +39,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index 0bb27f17ad62d0..cdfe9679c5049d 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "*", @@ -45,6 +46,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index f85efeb91e1803..c476788e3cfaf8 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -25,12 +25,12 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "dependencies": { "@babel/runtime": "7.25.7", "memize": "^2.0.1" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 76ce2ccbb1445d..378f4dce91dad9 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -27,6 +27,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -35,6 +36,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/sync/package.json b/packages/sync/package.json index 95be09803a75f1..d7181479327d3a 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -41,6 +42,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 0d966edeb9ee7d..370d50e5b4700a 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -25,12 +25,12 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index f0464d7fd2f9e2..66f895f8da887d 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -26,6 +26,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -34,6 +35,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/url/package.json b/packages/url/package.json index 885efe28f8e8b4..2ecdb8eae18113 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "dependencies": { @@ -33,6 +34,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 05e098f65e1aeb..224da8a871addf 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -25,6 +25,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/compose": "*", @@ -36,6 +37,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/vips/package.json b/packages/vips/package.json index 810b8d2b5c9fc4..69912b2eaed71e 100644 --- a/packages/vips/package.json +++ b/packages/vips/package.json @@ -25,12 +25,12 @@ }, "main": "build/index.js", "module": "build-module/index.js", + "wpScript": true, "types": "build-types", "dependencies": { "wasm-vips": "^0.0.10" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/warning/package.json b/packages/warning/package.json index cae2aefa421ffe..d9c5a4dd83dc10 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -25,10 +25,10 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "types": "build-types", "sideEffects": false, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/widgets/package.json b/packages/widgets/package.json index b7fa362d615856..a755890c48ed92 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -23,6 +23,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "dependencies": { "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "*", @@ -44,6 +45,5 @@ }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index a9f8304f79d8ff..117e2227a926c8 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -25,12 +25,12 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "wpScript": true, "sideEffects": false, "dependencies": { "@babel/runtime": "7.25.7" }, "publishConfig": { "access": "public" - }, - "wpScript": true + } } From e6ee784b3b4e348e4f47369a94c7c86f5469df68 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:23:19 +0100 Subject: [PATCH 1480/1908] Site Editor: fix template for page-on-front option (#66739) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: mdawaffe <mdawaffe@git.wordpress.org> --- .../use-init-edited-entity-from-url.js | 27 +++++++++++++- .../site-editor/template-hierarchy.spec.js | 35 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 test/e2e/specs/site-editor/template-hierarchy.spec.js diff --git a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js index 3498bed4c99a56..2dbd143766e67c 100644 --- a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js +++ b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js @@ -96,7 +96,32 @@ function useResolveEditedEntityAndContext( { postId, postType } ) { postTypeToResolve === 'page' && homepageId === postIdToResolve ) { - return getDefaultTemplateId( { slug: 'front-page' } ); + // The /lookup endpoint cannot currently handle a lookup + // when a page is set as the front page, so specifically in + // that case, we want to check if there is a front page + // template, and instead of falling back to the home + // template, we want to fall back to the page template. + const templates = getEntityRecords( + 'postType', + TEMPLATE_POST_TYPE, + { + per_page: -1, + } + ); + if ( templates ) { + const id = templates?.find( + ( { slug } ) => slug === 'front-page' + )?.id; + if ( id ) { + return id; + } + + // If no front page template is found, continue with the + // logic below (fetching the page template). + } else { + // Still resolving `templates`. + return undefined; + } } const editedEntity = getEditedEntityRecord( diff --git a/test/e2e/specs/site-editor/template-hierarchy.spec.js b/test/e2e/specs/site-editor/template-hierarchy.spec.js new file mode 100644 index 00000000000000..5fcc77da9942ce --- /dev/null +++ b/test/e2e/specs/site-editor/template-hierarchy.spec.js @@ -0,0 +1,35 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.describe( 'Template hierarchy', () => { + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentyfour' ); + } ); + + test.afterEach( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentyone' ); + } ); + + test( 'shows correct template with page on front option', async ( { + admin, + page, + editor, + } ) => { + await admin.visitAdminPage( 'options-reading.php' ); + await page.click( 'input[name="show_on_front"][value="page"]' ); + await page.selectOption( 'select[name="page_on_front"]', '2' ); + await page.click( 'input[type="submit"]' ); + await admin.visitSiteEditor(); + + // Title block should contain "Sample Page" + await expect( + editor.canvas.locator( 'role=document[name="Block: Title"]' ) + ).toContainText( 'Sample Page' ); + + await admin.visitAdminPage( 'options-reading.php' ); + await page.click( 'input[name="show_on_front"][value="posts"]' ); + await page.click( 'input[type="submit"]' ); + } ); +} ); From bdc3ab224accbc42402a372ded80212c8b2ebd50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= <grzegorz@gziolo.pl> Date: Tue, 5 Nov 2024 17:35:20 +0100 Subject: [PATCH 1481/1908] WP Scripts: Make watch mode more resilient for developer errors (#66752) * WP Scripts: Fix the watch mode so it continues working when errors pop up while developing * Improve the handling for parsing JSON files * Docs: Add changelog entry * Improve the warnings messages Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- packages/scripts/CHANGELOG.md | 4 ++ packages/scripts/utils/config.js | 102 ++++++++++++++++--------------- 2 files changed, 56 insertions(+), 50 deletions(-) diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index ca5a44bca62b52..c09cfd1ac9aaaa 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fix + +- Make `start` script more resilient for developer errors ([#66752](https://github.com/WordPress/gutenberg/pull/66752)). + ## 30.4.0 (2024-10-30) ### Enhancements diff --git a/packages/scripts/utils/config.js b/packages/scripts/utils/config.js index dfb44730438c4a..3d99f3784859df 100644 --- a/packages/scripts/utils/config.js +++ b/packages/scripts/utils/config.js @@ -1,7 +1,6 @@ /** * External dependencies */ -const chalk = require( 'chalk' ); const { readFileSync } = require( 'fs' ); const { basename, dirname, extname, join, sep } = require( 'path' ); const { sync: glob } = require( 'fast-glob' ); @@ -21,7 +20,8 @@ const { getBlockJsonModuleFields, getBlockJsonScriptFields, } = require( './block-json' ); -const { log } = console; + +const { warn } = console; // See https://babeljs.io/docs/en/config-files#configuration-file-types. const hasBabelConfig = () => @@ -209,10 +209,8 @@ function getWebpackEntryPoints( buildType ) { // Continue only if the source directory exists. if ( ! hasProjectFile( getWordPressSrcDirectory() ) ) { - log( - chalk.yellow( - `Source directory "${ getWordPressSrcDirectory() }" was not found. Please confirm there is a "src" directory in the root or the value passed to --webpack-src-dir is correct.` - ) + warn( + `Source directory "${ getWordPressSrcDirectory() }" was not found. Please confirm there is a "src" directory in the root or the value passed to --webpack-src-dir is correct.` ); return {}; } @@ -240,12 +238,13 @@ function getWebpackEntryPoints( buildType ) { try { parsedBlockJson = JSON.parse( fileContents ); } catch ( error ) { - chalk.yellow( - `Skipping "${ blockMetadataFile.replace( + warn( + `Not scanning "${ blockMetadataFile.replace( fromProjectRoot( sep ), '' - ) }" due to malformed JSON.` + ) }" due to collect entry points due to malformed JSON.` ); + continue; } const fields = @@ -270,18 +269,16 @@ function getWebpackEntryPoints( buildType ) { // Takes the path without the file extension, and relative to the defined source directory. if ( ! filepath.startsWith( srcDirectory ) ) { - log( - chalk.yellow( - `Skipping "${ value.replace( - 'file:', - '' - ) }" listed in "${ blockMetadataFile.replace( - fromProjectRoot( sep ), - '' - ) }". File is located outside of the "${ getWordPressSrcDirectory() }" directory.` - ) + warn( + `Skipping "${ value.replace( + 'file:', + '' + ) }" listed in "${ blockMetadataFile.replace( + fromProjectRoot( sep ), + '' + ) }". File is located outside of the "${ getWordPressSrcDirectory() }" directory.` ); - return; + continue; } const entryName = filepath .replace( extname( filepath ), '' ) @@ -298,18 +295,16 @@ function getWebpackEntryPoints( buildType ) { ); if ( ! entryFilepath ) { - log( - chalk.yellow( - `Skipping "${ value.replace( - 'file:', - '' - ) }" listed in "${ blockMetadataFile.replace( - fromProjectRoot( sep ), - '' - ) }". File does not exist in the "${ getWordPressSrcDirectory() }" directory.` - ) + warn( + `Skipping "${ value.replace( + 'file:', + '' + ) }" listed in "${ blockMetadataFile.replace( + fromProjectRoot( sep ), + '' + ) }". File does not exist in the "${ getWordPressSrcDirectory() }" directory.` ); - return; + continue; } entryPoints[ entryName ] = entryFilepath; } @@ -334,10 +329,8 @@ function getWebpackEntryPoints( buildType ) { } ); if ( ! entryFile ) { - log( - chalk.yellow( - `No entry file discovered in the "${ getWordPressSrcDirectory() }" directory.` - ) + warn( + `No entry file discovered in the "${ getWordPressSrcDirectory() }" directory.` ); return {}; } @@ -370,13 +363,24 @@ function getPhpFilePaths( context, props ) { const srcDirectory = fromProjectRoot( context + sep ); return blockMetadataFiles.flatMap( ( blockMetadataFile ) => { - const blockJson = JSON.parse( readFileSync( blockMetadataFile ) ); - const paths = []; + let parsedBlockJson; + try { + parsedBlockJson = JSON.parse( readFileSync( blockMetadataFile ) ); + } catch ( error ) { + warn( + `Not scanning "${ blockMetadataFile.replace( + fromProjectRoot( sep ), + '' + ) }" due to detect render files due to malformed JSON.` + ); + return paths; + } + for ( const prop of props ) { if ( - typeof blockJson?.[ prop ] !== 'string' || - ! blockJson[ prop ]?.startsWith( 'file:' ) + typeof parsedBlockJson?.[ prop ] !== 'string' || + ! parsedBlockJson[ prop ]?.startsWith( 'file:' ) ) { continue; } @@ -384,21 +388,19 @@ function getPhpFilePaths( context, props ) { // Removes the `file:` prefix. const filepath = join( dirname( blockMetadataFile ), - blockJson[ prop ].replace( 'file:', '' ) + parsedBlockJson[ prop ].replace( 'file:', '' ) ); // Takes the path without the file extension, and relative to the defined source directory. if ( ! filepath.startsWith( srcDirectory ) ) { - log( - chalk.yellow( - `Skipping "${ blockJson[ prop ].replace( - 'file:', - '' - ) }" listed in "${ blockMetadataFile.replace( - fromProjectRoot( sep ), - '' - ) }". File is located outside of the "${ context }" directory.` - ) + warn( + `Skipping "${ parsedBlockJson[ prop ].replace( + 'file:', + '' + ) }" listed in "${ blockMetadataFile.replace( + fromProjectRoot( sep ), + '' + ) }". File is located outside of the "${ context }" directory.` ); continue; } From d50ff80f4f4e688838cf3f2972cf7213e3acb35b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:39:03 +0100 Subject: [PATCH 1482/1908] Documentation: add section about the Fields API (#66761) --- packages/dataviews/README.md | 454 +++++++++++++++++++++++++++++++---- 1 file changed, 407 insertions(+), 47 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index d61df206409152..fe35ae8f0aaa9a 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -67,7 +67,7 @@ By default, dataviews would use each record's `id` as an unique identifier. If t #### `fields`: `Object[]` -The fields describe the visible items for each record in the dataset. +The fields describe the visible items for each record in the dataset and how they behave (how to sort them, display them, etc.). See "Fields API" as a reference for every property. Example: @@ -95,7 +95,7 @@ const fields = [ }, { id: 'author', - label: __( 'Author' ), + label: 'Author', render: ( { item } ) => { return <a href="...">{ item.author }</a>; }, @@ -110,7 +110,7 @@ const fields = [ }, { id: 'status', - label: __( 'Status' ), + label: 'Status', getValue: ( { item } ) => STATUSES.find( ( { value } ) => value === item.status )?.label ?? item.status, @@ -123,49 +123,6 @@ const fields = [ ]; ``` -Each field is an object with the following properties: - -- `id`: identifier for the field. Unique. -- `type`: the type of the field. See "Field types" section. -- `label`: the field's name to be shown in the UI. -- `header`: defaults to the label. Allows providing a React element to render the field labels. -- `getValue`: function that returns the value of the field, defaults to `field[id]`. -- `render`: function that renders the field. Optional, `getValue` will be used if `render` is not defined. -- `Edit`: function that renders an edit control for the field. Alternatively, can provide a string declaring one of default controls provided by DataForm `text`, `integer`, `datetime`, `radio`, `select`. -- `sort`: a compare function that determines the order of the records. -- `isValid`: callback to decide if a field should be displayed. -- `isVisible`: callback to decide if a field should be visible. -- `enableSorting`: whether the data can be sorted by the given field. True by default. -- `enableHiding`: whether the field can be hidden. True by default. -- `enableGlobalSearch`: whether the field is searchable. False by default. -- <code id="fields-elements">elements</code>: The list of options to pick from when using the field as a filter or when editing (DataForm component). Providing a list of to the field automatically creates a filter for it. It expects an array of objects with the following properties: - - `value`: The id of the value to filter to (for internal use) - - `label`: The text that will be displayed in the UI for the item. - - `description`: A longer description that describes the element, to also be displayed. Optional. -- `filterBy`: configuration for the filters enabled by the `elements` property. - - `operators`: the list of operators supported by the field. See "Filter operators" below. - - `isPrimary`: whether it is a primary filter. A primary filter is always visible and is not listed in the "Add filter" component, except for the list layout where it behaves like a secondary filter. - -##### Field types - -Current supported types include: `text`, `integer`, `datetime`. - -If a field declares a `type` the `sort`, `isValid`, and `Edit` functions will be provided with default implementations. They will overriden if the field provides its own. - -##### Filter operators - - -| Operator | Selection | Description | Example | -| ---------- | -------------- | ----------------------------------------------------------------------- | -------------------------------------------------- | -| `is` | Single item | `EQUAL TO`. The item's field is equal to a single value. | Author is Admin | -| `isNot` | Single item | `NOT EQUAL TO`. The item's field is not equal to a single value. | Author is not Admin | -| `isAny` | Multiple items | `OR`. The item's field is present in a list of values. | Author is any: Admin, Editor | -| `isNone` | Multiple items | `NOT OR`. The item's field is not present in a list of values. | Author is none: Admin, Editor | -| `isAll` | Multiple items | `AND`. The item's field has all of the values in the list. | Category is all: Book, Review, Science Fiction | -| `isNotAll` | Multiple items | `NOT AND`. The item's field doesn't have all of the values in the list. | Category is not all: Book, Review, Science Fiction | - -`is` and `isNot` are single-selection operators, while `isAny`, `isNone`, `isAll`, and `isNotALl` are multi-selection. By default, a filter with no operators declared will support the `isAny` and `isNone` multi-selection operators. A filter cannot mix single-selection & multi-selection operators; if a single-selection operator is present in the list of valid operators, the multi-selection ones will be discarded and the filter won't allow selecting more than one item. - #### `view`: `Object` The view object configures how the dataset is visible to the user. @@ -422,7 +379,33 @@ This could be thought as as a single record coming from the `data` property of ` #### `fields`: `Object[]` -Same as `fields` property of `DataViews`. +The fields describe which parts of the the data are visible and how they behave (how to edit them, validating them, etc.). See "Fields API" as a reference for every property. + +Example: + +```js +const fields = [ + { + id: 'title', + type: 'text', + label: 'Title', + }, + { + id: 'date', + type: 'datetime', + label: 'Date', + }, + { + id: 'author', + type: 'text' + label: 'Author', + elements: [ + { value: 1, label: 'Admin' }, + { value: 2, label: 'User' }, + ], + }, +]; +``` #### `form`: `Object[]` @@ -497,6 +480,383 @@ Parameters: Returns a boolean indicating if the item is valid (true) or not (false). +## Fields API + +### `id` + +The unique identifier of the field. + +- Type: `string`. +- Required. + +Example: + +```js +{ id: 'field_id' } +``` + +### `type` + +Field type. One of `text`, `integer`, `datetime`. + +If a field declares a `type`, it gets default implementations for the `sort`, `isValid`, and `Edit` functions. They will overriden if the field provides its own. + +- Type: `string`. +- Optional. + +Example: + +```js +{ type: 'text' } +``` + +### `label` + +The field's name. This will be used across the UI. + +- Type: `string`. +- Optional. +- Defaults to the `id` value. + +Example: + +```js +{ label: 'Title' } +``` + +### `header` + +React component used by the layouts to display the field name — useful to add icons, etc. It's complementary to the `label` property. + +- Type: React component. +- Optional. +- Defaults to the `label` value. +- Props: none. +- Returns a React element that represents the field's name. + +Example: + +```js +{ + header: () => { /* Returns a react element. */ } +} +``` + +### `getValue` + +React component that returns the value of a field. This value is used in sorting the fields, or when filtering. + +- Type: React component. +- Optional. +- Defaults to `item[ id ]`. +- Props: + - `item` value to be processed. +- Returns a value that represents the field. + +Example: + +```js +{ + getValue: ( { item } ) => { /* The field's value. */ }; +} +``` + +### `render` + +React component that renders the field. This is used by the layouts. + +- Type: React component. +- Optional. +- Defaults to `getValue`. +- Props + - `item` value to be processed. +- Returns a React element that represents the field's value. + +Example: + +```js +{ + render: ( { item} ) => { /* React element to be displayed. */ } +} +``` + +### `Edit` + +React component that renders the control to edit the field. + +- Type: React component | `string`. If it's a string, it needs to be one of `text`, `integer`, `datetime`, `radio`, `select`. +- Required by DataForm. Optional if the field provided a `type`. +- Props: + - `data`: the item to be processed + - `field`: the field definition + - `onChange`: the callback with the updates + - `hideLabelFromVision`: boolean representing if the label should be hidden +- Returns a React element to edit the field's value. + +Example: + +```js +// A custom control defined by the field. +{ + Edit: ( { + data, + field, + onChange, + hideLabelFromVision + } ) => { + const value = field.getValue( { item: data } ); + + return ( + <CustomTimePicker + value={ value } + onChange={ onChange } + hideLabelFromVision + /> + ); + } +} + +// Use one of the core controls. +{ + Edit: 'radio' +} + +// Edit is optional when field's type is present. +// The field will use the default Edit function for text. +{ + type: 'text' +} + +// Edit can be provided even if field's type is present. +// The field will use its own custom control. +{ + type: 'text', + Edit: 'radio' +} +``` + +### `sort` + +Function to sort the records. + +- Type: `function`. +- Optional. +- Args + - `a`: the first item to compare + - `b`: the second item to compare + - `direction`: either `asc` (ascending) or `desc` (descending) +- Returns a number where: + - a negative value indicates that `a` should come before `b` + - a positive value indicates that `a` should come after `b` + - 0 indicates that `a` and `b` are considered equal + +Example: + +```js +// A custom sort function defined by the field. +{ + sort: ( a, b, direction ) => { + return direction === 'asc' + ? a.localeCompare( b ) + : b.localeCompare( a ); + } +} +``` + +```js +// If field type is provided, +// the field gets a default sort function. +{ + type: 'number' +} +``` + +```js +// Even if a field type is provided, +// fields can override the default sort function assigned for that type. +{ + type: 'number' + sort: ( a, b, direction ) => { /* Custom sort */ } +} +``` + +### `isValid` + +Function to validate a field's value. + +- Type: function. +- Optional. +- Args + - `item`: the data to validate + - `context`: an object containing the following props: + - `elements`: the elements defined by the field +- Returns a boolean, indicating if the field is valid or not. + +Example: + +```js +// Custom isValid function. +{ + isValid: ( item, context ) => { + return !! item; + } +} +``` + +```js +// If the field defines a type, +// it'll get a default isValid function for the type. +{ + type: 'number', +} +``` + +```js +// Even if the field provides a type, +// the field can override the default isValid function. +{ + type: 'number', + isValid: ( item, context ) => { /* Custom function. */ } +} +``` + +### `isVisible` + +Function that indicates if the field should be visible. + +- Type: `function`. +- Optional. +- Args + - `item`: the data to be processed +- Returns a `boolean` indicating if the field should be visible (`true`) or not (`false`). + +Example: + +```js +// Custom isVisible function. +{ + isVisible: ( item ) => { /* Custom implementation. */ } +} +``` + +### `enableSorting` + +Boolean indicating if the field is sortable. + +- Type: `boolean`. +- Optional. +- Defaults to `true`. + +Example: + +```js +{ enableSorting: true } +``` + +### `enableHiding` + +Boolean indicating if the field can be hidden. + +- Type: `boolean`. +- Optional. +- Defaults to `true`. + +Example: + +```js +{ enableHiding: true } +``` + +### `enableGlobalSearch` + +Boolean indicating if the field is searchable. + +- Type: `boolean`. +- Optional. +- Defaults to `false`. + +Example: + +```js +{ enableGlobalSearch: true } +``` + +### `elements` + +List of valid values for a field. If provided, it creates a DataViews' filter for the field. DataForm's edit control will use these values as well (see `Edit` field property). + +- Type: `array` of objects. +- Optional. +- Each object can have the following properties: + - `value`: required, the value to match against the field's value. + - `label`: required, the name to display to users. + - `description`: optional, a longer description of the item. + +Example: + +```js +{ + elements: [ + { value: '1', label: 'Product A' }, + { value: '2', label: 'Product B' }, + { value: '3', label: 'Product C' }, + { value: '4', label: 'Product D' }, + ] +} +``` + +### `filterBy` + +Configuration of the filters. + +- Type: `object`. +- Optional. +- Properties: + - `operators`: the list of operators supported by the field. See "operators" below. By default, a filter will support the `isAny` and `isNone` multi-selection operators. + - `isPrimary`: boolean, optional. Indicates if the filter is primary. A primary filter is always visible and is not listed in the "Add filter" component, except for the list layout where it behaves like a secondary filter. + +Operators: + +| Operator | Selection | Description | Example | +| ---------- | -------------- | ----------------------------------------------------------------------- | -------------------------------------------------- | +| `is` | Single item | `EQUAL TO`. The item's field is equal to a single value. | Author is Admin | +| `isNot` | Single item | `NOT EQUAL TO`. The item's field is not equal to a single value. | Author is not Admin | +| `isAny` | Multiple items | `OR`. The item's field is present in a list of values. | Author is any: Admin, Editor | +| `isNone` | Multiple items | `NOT OR`. The item's field is not present in a list of values. | Author is none: Admin, Editor | +| `isAll` | Multiple items | `AND`. The item's field has all of the values in the list. | Category is all: Book, Review, Science Fiction | +| `isNotAll` | Multiple items | `NOT AND`. The item's field doesn't have all of the values in the list. | Category is not all: Book, Review, Science Fiction | + +`is` and `isNot` are single-selection operators, while `isAny`, `isNone`, `isAll`, and `isNotALl` are multi-selection. By default, a filter with no operators declared will support the `isAny` and `isNone` multi-selection operators. A filter cannot mix single-selection & multi-selection operators; if a single-selection operator is present in the list of valid operators, the multi-selection ones will be discarded and the filter won't allow selecting more than one item. + +Example: + +```js +// Set a filter as primary. +{ + filterBy: { + isPrimary: true + } +} +``` + +```js +// Configure a filter as single-selection. +{ + filterBy: { + operators: [ `is`, `isNot` ] + } +} +``` + +```js +// Configure a filter as multi-selection with all the options. +{ + filterBy: { + operators: [ `isAny`, `isNone`, `isAll`, `isNotAll` ] + } +} +``` + ## Contributing to this package This is an individual package that's part of the Gutenberg project. The project is organized as a monorepo. It's made up of multiple self-contained software packages, each with a specific purpose. The packages in this monorepo are published to [npm](https://www.npmjs.com/) and used by [WordPress](https://make.wordpress.org/core/) as well as other software projects. From 058354964253523d67f48318cf3eace66dd3de92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:12:49 +0100 Subject: [PATCH 1483/1908] Documentation: improve readability of DataViews docs (#66766) --- packages/dataviews/README.md | 60 ++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index fe35ae8f0aaa9a..ff20386862929e 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -1,9 +1,9 @@ # The `@wordpress/dataviews` package -The DataViews package offers two components to work with a given dataset: +The DataViews package offers two React components and a few utilites to work with a list of data: -- `DataViews`: allows rendering a dataset using different types of layouts (table, grid, list) and interaction capabilities (search, filters, sorting, etc.). -- `DataForm`: allows editing the items from the same dataset. +- `DataViews`: to render the dataset using different types of layouts (table, grid, list) and interaction capabilities (search, filters, sorting, etc.). +- `DataForm`: to edit the items of the dataset. ## Installation @@ -15,15 +15,19 @@ npm install @wordpress/dataviews --save ## `DataViews` +<div class="callout callout-info">At <a href="https://wordpress.github.io/gutenberg/">WordPress Gutenberg's Storybook</a> there's and <a href="https://wordpress.github.io/gutenberg/?path=/docs/dataviews-dataviews--docs">example implementation of the Dataviews component</a>.</div> + ### Usage -The component is data agnostic, it just requires the data to be an array of objects with an unique identifier — it can work with data coming from a static (e.g.: JSON file) or dynamic source (e.g.: HTTP Request). Consumers are responsible to query the data source appropiately: +The `DataViews` component receives data and some other configuration to render the dataset. It'll call the `onChangeView` callback every time the user has interacted with the dataset in some way (sorted, filtered, changed layout, etc.): ![DataViews flow](https://developer.wordpress.org/files/2024/09/368600071-20aa078f-7c3d-406d-8dd0-8b764addd22a.png "DataViews flow") +Example: + ```jsx const Example = () => { - // Declare data, fields, etc. + const onChangeView = () => { /* React to user changes. */ } return ( <DataViews @@ -39,13 +43,12 @@ const Example = () => { }; ``` -<div class="callout callout-info">At <a href="https://wordpress.github.io/gutenberg/">WordPress Gutenberg's Storybook</a> there's and <a href="https://wordpress.github.io/gutenberg/?path=/docs/dataviews-dataviews--docs">example implementation of the Dataviews component</a>.</div> ### Properties #### `data`: `Object[]` -The dataset to work with, represented as a one-dimensional array. +A one-dimensional array of objects. Example: @@ -63,11 +66,28 @@ const data = [ ]; ``` -By default, dataviews would use each record's `id` as an unique identifier. If the records don't have a `id` property that identify them uniquely, they consumer needs to provide a `getItemId` function that returns an unique identifier for the record. +The data can come from anywhere, from a static JSON file to a dynamic source like a HTTP Request. It's the consumer's responsiblity to query the data source appropiately and update the dataset based on the user's choices for sorting, filtering, etc. + +Each record should have an `id` that identifies them uniquely. If they don't, the consumer should provide the `getItemId` property to `DataViews`: a function that returns an unique identifier for the record. + +#### `getItemId`: `function` + +Function that receives an item and returns an unique identifier for it. + +It's optional. The field will get a default implementation by `DataViews` that returns the value of the `item[ id ]`. + +Example: + +```js +// Custom getItemId function. +{ + getItemId={ ( item ) => item.name ?? item.id } +} +``` #### `fields`: `Object[]` -The fields describe the visible items for each record in the dataset and how they behave (how to sort them, display them, etc.). See "Fields API" as a reference for every property. +The fields describe the visible items for each record in the dataset and how they behave (how to sort them, display them, etc.). See "Fields API" for a description of every property. Example: @@ -304,12 +324,6 @@ Whether the search input is enabled. `true` by default. What text to show in the search input. "Search" by default. -#### `getItemId`: `function` - -Function that receives an item and returns an unique identifier for it. - -By default, dataviews would use each record's `id` as an unique identifier. If the records don't have a `id` property that identify them uniquely, they consumer needs to provide a `getItemId` function that returns an unique identifier for the record. - #### `isLoading`: `boolean` Whether the data is loading. `false` by default. @@ -350,6 +364,8 @@ React component to be rendered next to the view config button. ## `DataForm` +<div class="callout callout-info">At <a href="https://wordpress.github.io/gutenberg/">WordPress Gutenberg's Storybook</a> there's and <a href="https://wordpress.github.io/gutenberg/?path=/docs/dataviews-dataform--docs">example implementation of the DataForm component</a>.</div> + ### Usage ```jsx @@ -367,19 +383,17 @@ const Example = () => { } ``` -<div class="callout callout-info">At <a href="https://wordpress.github.io/gutenberg/">WordPress Gutenberg's Storybook</a> there's and <a href="https://wordpress.github.io/gutenberg/?path=/docs/dataviews-dataform--docs">example implementation of the DataForm component</a>.</div> - ### Properties #### `data`: `Object` A single item to be edited. -This could be thought as as a single record coming from the `data` property of `DataViews` — though it doesn't need to be; it can be, for example, a mix of records if you support bulk editing. +It can be think of as a single record coming from the `data` property of `DataViews` — though it doesn't need to be. It can be totally separated or a mix of records if your app supports bulk editing. #### `fields`: `Object[]` -The fields describe which parts of the the data are visible and how they behave (how to edit them, validating them, etc.). See "Fields API" as a reference for every property. +The fields describe which parts of the data are visible and how they behave (how to edit them, validate them, etc.). See "Fields API" for a description of every property. Example: @@ -593,7 +607,7 @@ React component that renders the control to edit the field. - `hideLabelFromVision`: boolean representing if the label should be hidden - Returns a React element to edit the field's value. -Example: +Example: ```js // A custom control defined by the field. @@ -615,18 +629,24 @@ Example: ); } } +``` +```js // Use one of the core controls. { Edit: 'radio' } +``` +```js // Edit is optional when field's type is present. // The field will use the default Edit function for text. { type: 'text' } +``` +```js // Edit can be provided even if field's type is present. // The field will use its own custom control. { From c41b2194d01e4f34ef101bf244c62c5265b99345 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 5 Nov 2024 18:39:00 +0100 Subject: [PATCH 1484/1908] Zoom-out: Move default background to the iframe component (#66284) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../src/components/block-canvas/style.scss | 2 +- .../src/components/editor-canvas-container/style.scss | 1 - .../editor/src/components/visual-editor/style.scss | 11 +++++++++++ storybook/stories/playground/zoom-out/index.js | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/block-canvas/style.scss b/packages/block-editor/src/components/block-canvas/style.scss index 0b37b4dd1447e2..8f6064de0b615c 100644 --- a/packages/block-editor/src/components/block-canvas/style.scss +++ b/packages/block-editor/src/components/block-canvas/style.scss @@ -3,7 +3,7 @@ iframe[name="editor-canvas"] { width: 100%; height: 100%; display: block; - background-color: transparent; // Handles transitions between device previews @include editor-canvas-resize-animation; + background-color: $gray-300; } diff --git a/packages/edit-site/src/components/editor-canvas-container/style.scss b/packages/edit-site/src/components/editor-canvas-container/style.scss index 0bdbc2bbe32355..52ac29da0696f6 100644 --- a/packages/edit-site/src/components/editor-canvas-container/style.scss +++ b/packages/edit-site/src/components/editor-canvas-container/style.scss @@ -1,6 +1,5 @@ .edit-site-editor-canvas-container { height: 100%; - background-color: $gray-300; // Controls height of editor and editor canvas container (style book, global styles revisions previews etc.) iframe { diff --git a/packages/editor/src/components/visual-editor/style.scss b/packages/editor/src/components/visual-editor/style.scss index fae61eda6b8013..63df28f0f1ba5a 100644 --- a/packages/editor/src/components/visual-editor/style.scss +++ b/packages/editor/src/components/visual-editor/style.scss @@ -1,8 +1,19 @@ .editor-visual-editor { position: relative; display: flex; + + // This duplicates the iframe background but it's necessary in some situations + // when the iframe doesn't cover the whole canvas + // like the "focused entities". background-color: $gray-300; + // This overrides the iframe background since it's applied again here + // It also prevents some style glitches if `editor-visual-editor` + // like when hovering the preview in the site editor. + iframe[name="editor-canvas"] { + background-color: transparent; + } + // Centralize the editor horizontally (flex-direction is column). align-items: center; diff --git a/storybook/stories/playground/zoom-out/index.js b/storybook/stories/playground/zoom-out/index.js index 4f2efcf48523e8..8b72a831d710e8 100644 --- a/storybook/stories/playground/zoom-out/index.js +++ b/storybook/stories/playground/zoom-out/index.js @@ -50,7 +50,7 @@ export default function EditorZoomOut( { zoomLevel } ) { <div className="editor-zoom-out" onKeyDown={ ( event ) => event.stopPropagation() } - style={ { background: '#ddd', border: '1px solid gray' } } + style={ { border: '1px solid gray' } } > <BlockEditorProvider value={ blocks } From f1fe404e9081a9736e80342cf1941cda7d1f6af7 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:44:39 +0100 Subject: [PATCH 1485/1908] BlockPatternsList: use the Async component (#66744) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> --- package-lock.json | 1 + packages/block-editor/package.json | 1 + .../components/block-patterns-list/README.md | 8 --- .../components/block-patterns-list/index.js | 50 +++++++++---------- .../stories/index.story.js | 11 +--- .../src/components/block-preview/async.js} | 0 .../src/components/block-preview/index.js | 7 ++- .../components/block-toolbar/change-design.js | 6 --- .../block-patterns-explorer/pattern-list.js | 3 -- .../pattern-category-previews.js | 1 - .../inserter/hooks/use-patterns-paging.js | 7 +-- .../src/components/inserter/search-results.js | 6 --- packages/block-editor/tsconfig.json | 1 + .../src/query/edit/pattern-selection-modal.js | 3 -- .../src/template-part/edit/index.js | 3 -- .../src/template-part/edit/selection-modal.js | 3 -- .../src/components/page-patterns/fields.js | 5 +- .../src/components/page-templates/fields.js | 5 +- .../post-template/swap-template-button.js | 3 -- .../components/post-transform-panel/index.js | 3 -- .../components/start-page-options/index.js | 3 -- .../start-template-options/index.js | 3 -- 22 files changed, 38 insertions(+), 95 deletions(-) rename packages/{edit-site/src/components/async/index.js => block-editor/src/components/block-preview/async.js} (100%) diff --git a/package-lock.json b/package-lock.json index 9d5b12e749d123..e76ea379cd1a6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53169,6 +53169,7 @@ "@wordpress/keycodes": "*", "@wordpress/notices": "*", "@wordpress/preferences": "*", + "@wordpress/priority-queue": "*", "@wordpress/private-apis": "*", "@wordpress/rich-text": "*", "@wordpress/style-engine": "*", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 26b06474f54b18..b4672bc57690eb 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -60,6 +60,7 @@ "@wordpress/keycodes": "*", "@wordpress/notices": "*", "@wordpress/preferences": "*", + "@wordpress/priority-queue": "*", "@wordpress/private-apis": "*", "@wordpress/rich-text": "*", "@wordpress/style-engine": "*", diff --git a/packages/block-editor/src/components/block-patterns-list/README.md b/packages/block-editor/src/components/block-patterns-list/README.md index f63ea449059572..18e7ead5d1805a 100644 --- a/packages/block-editor/src/components/block-patterns-list/README.md +++ b/packages/block-editor/src/components/block-patterns-list/README.md @@ -18,7 +18,6 @@ import { BlockPatternsList } from '@wordpress/block-editor'; const MyBlockPatternsList = () => ( <BlockPatternsList blockPatterns={ shownBlockPatterns } - shownPatterns={ shownBlockPatterns } onClickPattern={ onSelectBlockPattern } /> ); @@ -33,13 +32,6 @@ An array of block patterns that can be shown in the block patterns list. - Type: `Array` - Required: Yes -#### shownPatterns - -An array of shown block patterns objects. - -- Type: `Array` -- Required: Yes - #### onClickPattern The performed event after a click on a block pattern. In most cases, the pattern is inserted in the block editor. diff --git a/packages/block-editor/src/components/block-patterns-list/index.js b/packages/block-editor/src/components/block-patterns-list/index.js index 2609cc2db97a13..741a92ddf10dfa 100644 --- a/packages/block-editor/src/components/block-patterns-list/index.js +++ b/packages/block-editor/src/components/block-patterns-list/index.js @@ -134,10 +134,14 @@ function BlockPattern( { } } onMouseLeave={ () => onHover?.( null ) } > - <BlockPreview - blocks={ blocks } - viewportWidth={ viewportWidth } - /> + <BlockPreview.Async + placeholder={ <BlockPatternPlaceholder /> } + > + <BlockPreview + blocks={ blocks } + viewportWidth={ viewportWidth } + /> + </BlockPreview.Async> { showTitle && ( <HStack @@ -187,7 +191,6 @@ function BlockPatternsList( { isDraggable, blockPatterns, - shownPatterns, onHover, onClickPattern, orientation, @@ -205,11 +208,9 @@ function BlockPatternsList( // Reset the active composite item whenever the available patterns change, // to make sure that Composite widget can receive focus correctly when its // composite items change. The first composite item will receive focus. - const firstCompositeItemId = blockPatterns.find( ( pattern ) => - shownPatterns.includes( pattern ) - )?.name; + const firstCompositeItemId = blockPatterns[ 0 ]?.name; setActiveCompositeId( firstCompositeItemId ); - }, [ shownPatterns, blockPatterns ] ); + }, [ blockPatterns ] ); return ( <Composite @@ -221,24 +222,19 @@ function BlockPatternsList( aria-label={ label } ref={ ref } > - { blockPatterns.map( ( pattern ) => { - const isShown = shownPatterns.includes( pattern ); - return isShown ? ( - <BlockPattern - key={ pattern.name } - id={ pattern.name } - pattern={ pattern } - onClick={ onClickPattern } - onHover={ onHover } - isDraggable={ isDraggable } - showTitle={ showTitle } - showTooltip={ showTitlesAsTooltip } - category={ category } - /> - ) : ( - <BlockPatternPlaceholder key={ pattern.name } /> - ); - } ) } + { blockPatterns.map( ( pattern ) => ( + <BlockPattern + key={ pattern.name } + id={ pattern.name } + pattern={ pattern } + onClick={ onClickPattern } + onHover={ onHover } + isDraggable={ isDraggable } + showTitle={ showTitle } + showTooltip={ showTitlesAsTooltip } + category={ category } + /> + ) ) } { pagingProps && <BlockPatternsPaging { ...pagingProps } /> } </Composite> ); diff --git a/packages/block-editor/src/components/block-patterns-list/stories/index.story.js b/packages/block-editor/src/components/block-patterns-list/stories/index.story.js index 9eb393ea13e762..0ebb4520d98fd4 100644 --- a/packages/block-editor/src/components/block-patterns-list/stories/index.story.js +++ b/packages/block-editor/src/components/block-patterns-list/stories/index.story.js @@ -3,11 +3,6 @@ */ import blockLibraryStyles from '!!raw-loader!../../../../../block-library/build-style/style.css'; -/** - * WordPress dependencies - */ -import { useAsyncList } from '@wordpress/compose'; - /** * Internal dependencies */ @@ -26,13 +21,9 @@ export default { export const Default = { render: function Template( props ) { - const shownPatterns = useAsyncList( props.blockPatterns ); return ( <ExperimentalBlockEditorProvider settings={ blockEditorSettings }> - <BlockPatternsList - shownPatterns={ shownPatterns } - { ...props } - /> + <BlockPatternsList { ...props } /> </ExperimentalBlockEditorProvider> ); }, diff --git a/packages/edit-site/src/components/async/index.js b/packages/block-editor/src/components/block-preview/async.js similarity index 100% rename from packages/edit-site/src/components/async/index.js rename to packages/block-editor/src/components/block-preview/async.js diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 9eef0f1dc2abd5..62b137ff37194b 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -19,6 +19,7 @@ import AutoHeightBlockPreview from './auto'; import EditorStyles from '../editor-styles'; import { store as blockEditorStore } from '../../store'; import { BlockListItems } from '../block-list'; +import { Async } from './async'; const EMPTY_ADDITIONAL_STYLES = []; @@ -86,6 +87,10 @@ export function BlockPreview( { ); } +const MemoizedBlockPreview = memo( BlockPreview ); + +MemoizedBlockPreview.Async = Async; + /** * BlockPreview renders a preview of a block or array of blocks. * @@ -97,7 +102,7 @@ export function BlockPreview( { * * @return {Component} The component to be rendered. */ -export default memo( BlockPreview ); +export default MemoizedBlockPreview; /** * This hook is used to lightly mark an element as a block preview wrapper diff --git a/packages/block-editor/src/components/block-toolbar/change-design.js b/packages/block-editor/src/components/block-toolbar/change-design.js index ecfeff6cb1ed3e..9da1affe4273cc 100644 --- a/packages/block-editor/src/components/block-toolbar/change-design.js +++ b/packages/block-editor/src/components/block-toolbar/change-design.js @@ -10,7 +10,6 @@ import { import { __ } from '@wordpress/i18n'; import { cloneBlock } from '@wordpress/blocks'; import { useMemo } from '@wordpress/element'; -import { useAsyncList } from '@wordpress/compose'; import { useSelect, useDispatch } from '@wordpress/data'; /** @@ -81,10 +80,6 @@ export default function ChangeDesign( { clientId } ) { .slice( 0, MAX_PATTERNS_TO_SHOW ); }, [ categories, currentPatternName, patterns ] ); - const currentShownPatterns = useAsyncList( - sameCategoryPatternsWithSingleWrapper - ); - if ( sameCategoryPatternsWithSingleWrapper.length < 2 ) { return null; } @@ -121,7 +116,6 @@ export default function ChangeDesign( { clientId } ) { paddingSize="none" > <BlockPatternsList - shownPatterns={ currentShownPatterns } blockPatterns={ sameCategoryPatternsWithSingleWrapper } onClickPattern={ onClickPattern } showTitle={ false } diff --git a/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js b/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js index 709e005b587cea..296b432bd685c3 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js +++ b/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js @@ -151,9 +151,6 @@ function PatternList( { { hasItems && ( <> <BlockPatternsList - shownPatterns={ - pagingProps.categoryPatternsAsyncList - } blockPatterns={ pagingProps.categoryPatterns } onClickPattern={ onClickPattern } isDraggable={ false } diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js index fcb6c7601fcf7f..2c5d96d5ff9733 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js @@ -182,7 +182,6 @@ export function PatternCategoryPreviews( { ) } <BlockPatternsList ref={ scrollContainerRef } - shownPatterns={ pagingProps.categoryPatternsAsyncList } blockPatterns={ pagingProps.categoryPatterns } onClickPattern={ onClickPattern } onHover={ onHover } diff --git a/packages/block-editor/src/components/inserter/hooks/use-patterns-paging.js b/packages/block-editor/src/components/inserter/hooks/use-patterns-paging.js index 931796acceeb08..cdffef4a00513e 100644 --- a/packages/block-editor/src/components/inserter/hooks/use-patterns-paging.js +++ b/packages/block-editor/src/components/inserter/hooks/use-patterns-paging.js @@ -2,11 +2,10 @@ * WordPress dependencies */ import { useMemo, useState, useEffect } from '@wordpress/element'; -import { useAsyncList, usePrevious } from '@wordpress/compose'; +import { usePrevious } from '@wordpress/compose'; import { getScrollContainer } from '@wordpress/dom'; const PAGE_SIZE = 20; -const INITIAL_INSERTER_RESULTS = 5; /** * Supplies values needed to page the patterns list client side. @@ -42,9 +41,6 @@ export default function usePatternsPaging( pageIndex * PAGE_SIZE + PAGE_SIZE ); }, [ pageIndex, currentCategoryPatterns ] ); - const categoryPatternsAsyncList = useAsyncList( categoryPatterns, { - step: INITIAL_INSERTER_RESULTS, - } ); const numPages = Math.ceil( currentCategoryPatterns.length / PAGE_SIZE ); const changePage = ( page ) => { const scrollContainer = getScrollContainer( @@ -68,7 +64,6 @@ export default function usePatternsPaging( return { totalItems, categoryPatterns, - categoryPatternsAsyncList, numPages, changePage, currentPage, diff --git a/packages/block-editor/src/components/inserter/search-results.js b/packages/block-editor/src/components/inserter/search-results.js index 9c001823745e6c..5a5725a3bb08cd 100644 --- a/packages/block-editor/src/components/inserter/search-results.js +++ b/packages/block-editor/src/components/inserter/search-results.js @@ -159,11 +159,6 @@ function InserterSearchResults( { const currentShownBlockTypes = useAsyncList( filteredBlockTypes, { step: INITIAL_INSERTER_RESULTS, } ); - const currentShownPatterns = useAsyncList( - currentShownBlockTypes.length === filteredBlockTypes.length - ? filteredBlockPatterns - : EMPTY_ARRAY - ); const hasItems = filteredBlockTypes.length > 0 || filteredBlockPatterns.length > 0; @@ -190,7 +185,6 @@ function InserterSearchResults( { > <div className="block-editor-inserter__quick-inserter-patterns"> <BlockPatternsList - shownPatterns={ currentShownPatterns } blockPatterns={ filteredBlockPatterns } onClickPattern={ onClickPattern } onHover={ onHoverPattern } diff --git a/packages/block-editor/tsconfig.json b/packages/block-editor/tsconfig.json index 37fb61895d252e..a3c7d1ffd88077 100644 --- a/packages/block-editor/tsconfig.json +++ b/packages/block-editor/tsconfig.json @@ -18,6 +18,7 @@ { "path": "../dom" }, { "path": "../element" }, { "path": "../escape-html" }, + { "path": "../priority-queue" }, { "path": "../private-apis" }, { "path": "../hooks" }, { "path": "../html-entities" }, diff --git a/packages/block-library/src/query/edit/pattern-selection-modal.js b/packages/block-library/src/query/edit/pattern-selection-modal.js index 41a339908c5644..e4cc8d0c851c23 100644 --- a/packages/block-library/src/query/edit/pattern-selection-modal.js +++ b/packages/block-library/src/query/edit/pattern-selection-modal.js @@ -4,7 +4,6 @@ import { useState, useMemo } from '@wordpress/element'; import { useDispatch } from '@wordpress/data'; import { Modal, SearchControl } from '@wordpress/components'; -import { useAsyncList } from '@wordpress/compose'; import { BlockContextProvider, store as blockEditorStore, @@ -55,7 +54,6 @@ export default function PatternSelectionModal( { const filteredBlockPatterns = useMemo( () => { return searchPatterns( blockPatterns, searchValue ); }, [ blockPatterns, searchValue ] ); - const shownBlockPatterns = useAsyncList( filteredBlockPatterns ); return ( <Modal @@ -77,7 +75,6 @@ export default function PatternSelectionModal( { <BlockContextProvider value={ blockPreviewContext }> <BlockPatternsList blockPatterns={ filteredBlockPatterns } - shownPatterns={ shownBlockPatterns } onClickPattern={ onBlockPatternSelect } /> </BlockContextProvider> diff --git a/packages/block-library/src/template-part/edit/index.js b/packages/block-library/src/template-part/edit/index.js index ae941c977e14fd..a318fd285cdc33 100644 --- a/packages/block-library/src/template-part/edit/index.js +++ b/packages/block-library/src/template-part/edit/index.js @@ -21,7 +21,6 @@ import { MenuItem, ToolbarButton, } from '@wordpress/components'; -import { useAsyncList } from '@wordpress/compose'; import { __, sprintf } from '@wordpress/i18n'; import { store as coreStore } from '@wordpress/core-data'; import { useState } from '@wordpress/element'; @@ -85,7 +84,6 @@ function TemplatesList( { area, clientId, isEntityAvailable, onSelect } ) { isEntityAvailable && !! blockPatterns.length && ( area === 'header' || area === 'footer' ); - const shownTemplates = useAsyncList( blockPatterns ); if ( ! canReplace ) { return null; @@ -96,7 +94,6 @@ function TemplatesList( { area, clientId, isEntityAvailable, onSelect } ) { <BlockPatternsList label={ __( 'Templates' ) } blockPatterns={ blockPatterns } - shownPatterns={ shownTemplates } onClickPattern={ onSelect } showTitle={ false } /> diff --git a/packages/block-library/src/template-part/edit/selection-modal.js b/packages/block-library/src/template-part/edit/selection-modal.js index 5fa5d9786d8c96..71093306b93b2f 100644 --- a/packages/block-library/src/template-part/edit/selection-modal.js +++ b/packages/block-library/src/template-part/edit/selection-modal.js @@ -5,7 +5,6 @@ import { useMemo, useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; import { useDispatch } from '@wordpress/data'; -import { useAsyncList } from '@wordpress/compose'; import { __experimentalBlockPatternsList as BlockPatternsList } from '@wordpress/block-editor'; import { SearchControl, @@ -43,7 +42,6 @@ export default function TemplatePartSelectionModal( { return searchPatterns( partsAsPatterns, searchValue ); }, [ templateParts, searchValue ] ); - const shownTemplateParts = useAsyncList( filteredTemplateParts ); const blockPatterns = useAlternativeBlockPatterns( area, clientId ); const filteredBlockPatterns = useMemo( () => { return searchPatterns( blockPatterns, searchValue ); @@ -89,7 +87,6 @@ export default function TemplatePartSelectionModal( { <h2>{ __( 'Existing template parts' ) }</h2> <BlockPatternsList blockPatterns={ filteredTemplateParts } - shownPatterns={ shownTemplateParts } onClickPattern={ ( pattern ) => { onTemplatePartSelect( pattern.templatePart ); } } diff --git a/packages/edit-site/src/components/page-patterns/fields.js b/packages/edit-site/src/components/page-patterns/fields.js index 74433b3de72f0e..0ad47e90c20402 100644 --- a/packages/edit-site/src/components/page-patterns/fields.js +++ b/packages/edit-site/src/components/page-patterns/fields.js @@ -25,7 +25,6 @@ import { decodeEntities } from '@wordpress/html-entities'; /** * Internal dependencies */ -import { Async } from '../async'; import { PATTERN_TYPES, TEMPLATE_PART_POST_TYPE, @@ -88,12 +87,12 @@ function PreviewField( { item } ) { { isEmpty && isTemplatePart && __( 'Empty template part' ) } { isEmpty && ! isTemplatePart && __( 'Empty pattern' ) } { ! isEmpty && ( - <Async> + <BlockPreview.Async> <BlockPreview blocks={ blocks } viewportWidth={ item.viewportWidth } /> - </Async> + </BlockPreview.Async> ) } </PreviewWrapper> { !! description && ( diff --git a/packages/edit-site/src/components/page-templates/fields.js b/packages/edit-site/src/components/page-templates/fields.js index d26f1906a10664..69e0596bf49d47 100644 --- a/packages/edit-site/src/components/page-templates/fields.js +++ b/packages/edit-site/src/components/page-templates/fields.js @@ -20,7 +20,6 @@ import { EditorProvider } from '@wordpress/editor'; /** * Internal dependencies */ -import { Async } from '../async'; import { default as Link, useLink } from '../routes/link'; import { useAddedBy } from './hooks'; @@ -63,9 +62,9 @@ function PreviewField( { item } ) { > { isEmpty && __( 'Empty template' ) } { ! isEmpty && ( - <Async> + <BlockPreview.Async> <BlockPreview blocks={ blocks } /> - </Async> + </BlockPreview.Async> ) } </button> </div> diff --git a/packages/editor/src/components/post-template/swap-template-button.js b/packages/editor/src/components/post-template/swap-template-button.js index 5eed287f7f1709..bdda349398406b 100644 --- a/packages/editor/src/components/post-template/swap-template-button.js +++ b/packages/editor/src/components/post-template/swap-template-button.js @@ -9,7 +9,6 @@ import { __ } from '@wordpress/i18n'; import { useDispatch } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { parse } from '@wordpress/blocks'; -import { useAsyncList } from '@wordpress/compose'; /** * Internal dependencies @@ -71,12 +70,10 @@ function TemplatesList( { postType, onSelect } ) { } ) ), [ availableTemplates ] ); - const shownTemplates = useAsyncList( templatesAsPatterns ); return ( <BlockPatternsList label={ __( 'Templates' ) } blockPatterns={ templatesAsPatterns } - shownPatterns={ shownTemplates } onClickPattern={ onSelect } /> ); diff --git a/packages/editor/src/components/post-transform-panel/index.js b/packages/editor/src/components/post-transform-panel/index.js index 08139c2c3c6645..88ca6dc3965a11 100644 --- a/packages/editor/src/components/post-transform-panel/index.js +++ b/packages/editor/src/components/post-transform-panel/index.js @@ -5,7 +5,6 @@ import { useSelect, useDispatch } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { PanelBody } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { useAsyncList } from '@wordpress/compose'; import { __experimentalBlockPatternsList as BlockPatternsList } from '@wordpress/block-editor'; import { serialize } from '@wordpress/blocks'; @@ -20,7 +19,6 @@ import { } from '../../store/constants'; function TemplatesList( { availableTemplates, onSelect } ) { - const shownTemplates = useAsyncList( availableTemplates ); if ( ! availableTemplates || availableTemplates?.length === 0 ) { return null; } @@ -29,7 +27,6 @@ function TemplatesList( { availableTemplates, onSelect } ) { <BlockPatternsList label={ __( 'Templates' ) } blockPatterns={ availableTemplates } - shownPatterns={ shownTemplates } onClickPattern={ onSelect } showTitlesAsTooltip /> diff --git a/packages/editor/src/components/start-page-options/index.js b/packages/editor/src/components/start-page-options/index.js index 07fee67fbed19b..783a4a224fa378 100644 --- a/packages/editor/src/components/start-page-options/index.js +++ b/packages/editor/src/components/start-page-options/index.js @@ -9,7 +9,6 @@ import { __experimentalBlockPatternsList as BlockPatternsList, } from '@wordpress/block-editor'; import { useSelect, useDispatch } from '@wordpress/data'; -import { useAsyncList } from '@wordpress/compose'; import { store as coreStore } from '@wordpress/core-data'; import { __unstableSerializeAndClean } from '@wordpress/blocks'; import { store as preferencesStore } from '@wordpress/preferences'; @@ -66,7 +65,6 @@ export function useStartPatterns() { } function PatternSelection( { blockPatterns, onChoosePattern } ) { - const shownBlockPatterns = useAsyncList( blockPatterns ); const { editEntityRecord } = useDispatch( coreStore ); const { postType, postId } = useSelect( ( select ) => { const { getCurrentPostType, getCurrentPostId } = select( editorStore ); @@ -79,7 +77,6 @@ function PatternSelection( { blockPatterns, onChoosePattern } ) { return ( <BlockPatternsList blockPatterns={ blockPatterns } - shownPatterns={ shownBlockPatterns } onClickPattern={ ( _pattern, blocks ) => { editEntityRecord( 'postType', postType, postId, { blocks, diff --git a/packages/editor/src/components/start-template-options/index.js b/packages/editor/src/components/start-template-options/index.js index 3651c5c029a2c7..8d3910341aff43 100644 --- a/packages/editor/src/components/start-template-options/index.js +++ b/packages/editor/src/components/start-template-options/index.js @@ -6,7 +6,6 @@ import { __ } from '@wordpress/i18n'; import { useState, useMemo, useEffect } from '@wordpress/element'; import { __experimentalBlockPatternsList as BlockPatternsList } from '@wordpress/block-editor'; import { useSelect } from '@wordpress/data'; -import { useAsyncList } from '@wordpress/compose'; import { parse } from '@wordpress/blocks'; import { store as coreStore, useEntityBlockEditor } from '@wordpress/core-data'; @@ -111,11 +110,9 @@ function useStartPatterns( fallbackContent ) { function PatternSelection( { fallbackContent, onChoosePattern, postType } ) { const [ , , onChange ] = useEntityBlockEditor( 'postType', postType ); const blockPatterns = useStartPatterns( fallbackContent ); - const shownBlockPatterns = useAsyncList( blockPatterns ); return ( <BlockPatternsList blockPatterns={ blockPatterns } - shownPatterns={ shownBlockPatterns } onClickPattern={ ( pattern, blocks ) => { onChange( blocks, { selection: undefined } ); onChoosePattern(); From 177c6a2fc12d818dc864cc95ea1875f4dbc1ff62 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 5 Nov 2024 21:45:28 +0400 Subject: [PATCH 1486/1908] Block Editor: Fix ESLint warning for 'useBlockTypesState' hook (#66757) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: up1512001 <up1512001@git.wordpress.org> --- .../src/components/inserter/hooks/use-block-types-state.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js b/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js index 6f11060c75c494..2ff8f1a1dc23c0 100644 --- a/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js +++ b/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js @@ -94,7 +94,12 @@ const useBlockTypesState = ( rootClientId, onInsert, isQuick ) => { destinationClientId ); }, - [ onInsert, getClosestAllowedInsertionPoint, rootClientId ] + [ + getClosestAllowedInsertionPoint, + rootClientId, + onInsert, + createErrorNotice, + ] ); return [ items, categories, collections, onSelectItem ]; From ae29450a148520524057ca28841809c4e9054f55 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:57:14 +0100 Subject: [PATCH 1487/1908] Perf metrics: update select and other metrics to use non-empty paragraphs (#66762) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- test/performance/fixtures/perf-utils.ts | 4 ++-- test/performance/specs/post-editor.spec.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/performance/fixtures/perf-utils.ts b/test/performance/fixtures/perf-utils.ts index 83213a59520dd5..592e8194852e3b 100644 --- a/test/performance/fixtures/perf-utils.ts +++ b/test/performance/fixtures/perf-utils.ts @@ -150,7 +150,7 @@ export class PerfUtils { } /** - * Generates and loads a 1000 empty paragraphs into the editor canvas. + * Generates and loads a 1000 paragraphs into the editor canvas. */ async load1000Paragraphs() { await this.page.waitForFunction( @@ -161,7 +161,7 @@ export class PerfUtils { const { createBlock } = window.wp.blocks; const { dispatch } = window.wp.data; const blocks = Array.from( { length: 1000 } ).map( () => - createBlock( 'core/paragraph' ) + createBlock( 'core/paragraph', { content: 'paragraph' } ) ); dispatch( 'core/block-editor' ).resetBlocks( blocks ); } ); diff --git a/test/performance/specs/post-editor.spec.js b/test/performance/specs/post-editor.spec.js index becbf375eff2ac..85d334749f6f51 100644 --- a/test/performance/specs/post-editor.spec.js +++ b/test/performance/specs/post-editor.spec.js @@ -270,7 +270,7 @@ test.describe( 'Post Editor Performance', () => { const canvas = await perfUtils.getCanvas(); const paragraphs = canvas.getByRole( 'document', { - name: /Empty block/i, + name: /Block: Paragraph/i, } ); const samples = 10; From 7f49b39e1e3e2eaf274b6fb03ae22508cc583d31 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Tue, 5 Nov 2024 19:38:09 +0100 Subject: [PATCH 1488/1908] Patterns: receive intermediate responses while unbound request is resolving (#66713) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> Co-authored-by: sathyapulse <sathyapulse@git.wordpress.org> --- packages/core-data/src/private-apis.js | 2 + packages/core-data/src/resolvers.js | 57 ++++++++++++++++--- packages/core-data/src/utils/index.js | 1 + .../src/utils/receive-intermediate-results.js | 3 + .../provider/use-block-editor-settings.js | 14 ++--- 5 files changed, 61 insertions(+), 16 deletions(-) create mode 100644 packages/core-data/src/utils/receive-intermediate-results.js diff --git a/packages/core-data/src/private-apis.js b/packages/core-data/src/private-apis.js index 443db97957285d..e9fcf36f7e6090 100644 --- a/packages/core-data/src/private-apis.js +++ b/packages/core-data/src/private-apis.js @@ -2,9 +2,11 @@ * Internal dependencies */ import { useEntityRecordsWithPermissions } from './hooks/use-entity-records'; +import { RECEIVE_INTERMEDIATE_RESULTS } from './utils'; import { lock } from './lock-unlock'; export const privateApis = {}; lock( privateApis, { useEntityRecordsWithPermissions, + RECEIVE_INTERMEDIATE_RESULTS, } ); diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index ae0c7f456e533d..a35403c0493460 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -21,6 +21,7 @@ import { getUserPermissionCacheKey, getUserPermissionsFromAllowHeader, ALLOWED_RESOURCE_ACTIONS, + RECEIVE_INTERMEDIATE_RESULTS, } from './utils'; import { getSyncProvider } from './sync'; import { fetchBlockPatterns } from './fetch'; @@ -245,6 +246,14 @@ export const getEntityRecords = { exclusive: false } ); + const key = entityConfig.key || DEFAULT_ENTITY_KEY; + + function getResolutionsArgs( records ) { + return records + .filter( ( record ) => record?.[ key ] ) + .map( ( record ) => [ kind, name, record[ key ] ] ); + } + try { if ( query._fields ) { // If requesting specific fields, items and query association to said @@ -267,7 +276,8 @@ export const getEntityRecords = ...query, } ); - let records, meta; + let records = [], + meta; if ( entityConfig.supportsPagination && query.per_page !== -1 ) { const response = await apiFetch( { path, parse: false } ); records = Object.values( await response.json() ); @@ -279,6 +289,44 @@ export const getEntityRecords = response.headers.get( 'X-WP-TotalPages' ) ), }; + } else if ( + query.per_page === -1 && + query[ RECEIVE_INTERMEDIATE_RESULTS ] === true + ) { + let page = 1; + let totalPages; + + do { + const response = await apiFetch( { + path: addQueryArgs( path, { page, per_page: 100 } ), + parse: false, + } ); + const pageRecords = Object.values( await response.json() ); + + totalPages = parseInt( + response.headers.get( 'X-WP-TotalPages' ) + ); + + records.push( ...pageRecords ); + registry.batch( () => { + dispatch.receiveEntityRecords( + kind, + name, + records, + query + ); + dispatch.finishResolutions( + 'getEntityRecord', + getResolutionsArgs( pageRecords ) + ); + } ); + page++; + } while ( page <= totalPages ); + + meta = { + totalItems: records.length, + totalPages: 1, + }; } else { records = Object.values( await apiFetch( { path } ) ); meta = { @@ -318,11 +366,6 @@ export const getEntityRecords = // See https://github.com/WordPress/gutenberg/pull/26575 // See https://github.com/WordPress/gutenberg/pull/64504 if ( ! query?._fields && ! query.context ) { - const key = entityConfig.key || DEFAULT_ENTITY_KEY; - const resolutionsArgs = records - .filter( ( record ) => record?.[ key ] ) - .map( ( record ) => [ kind, name, record[ key ] ] ); - const targetHints = records .filter( ( record ) => record?.[ key ] ) .map( ( record ) => ( { @@ -356,7 +399,7 @@ export const getEntityRecords = ); dispatch.finishResolutions( 'getEntityRecord', - resolutionsArgs + getResolutionsArgs( records ) ); dispatch.finishResolutions( 'canUser', diff --git a/packages/core-data/src/utils/index.js b/packages/core-data/src/utils/index.js index 189635647779e5..db10359bda07dd 100644 --- a/packages/core-data/src/utils/index.js +++ b/packages/core-data/src/utils/index.js @@ -14,3 +14,4 @@ export { getUserPermissionsFromAllowHeader, ALLOWED_RESOURCE_ACTIONS, } from './user-permissions'; +export { RECEIVE_INTERMEDIATE_RESULTS } from './receive-intermediate-results'; diff --git a/packages/core-data/src/utils/receive-intermediate-results.js b/packages/core-data/src/utils/receive-intermediate-results.js new file mode 100644 index 00000000000000..53d2295b28b390 --- /dev/null +++ b/packages/core-data/src/utils/receive-intermediate-results.js @@ -0,0 +1,3 @@ +export const RECEIVE_INTERMEDIATE_RESULTS = Symbol( + 'RECEIVE_INTERMEDIATE_RESULTS' +); diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 170ec96c107288..e90be6487a0ea9 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -7,6 +7,7 @@ import { store as coreStore, __experimentalFetchLinkSuggestions as fetchLinkSuggestions, __experimentalFetchUrlData as fetchUrlData, + privateApis as coreDataPrivateApis, } from '@wordpress/core-data'; import { __ } from '@wordpress/i18n'; import { store as preferencesStore } from '@wordpress/preferences'; @@ -29,17 +30,12 @@ import { useGlobalStylesContext } from '../global-styles-provider'; const EMPTY_OBJECT = {}; function __experimentalReusableBlocksSelect( select ) { - const { getEntityRecords, hasFinishedResolution } = select( coreStore ); - const reusableBlocks = getEntityRecords( 'postType', 'wp_block', { + const { RECEIVE_INTERMEDIATE_RESULTS } = unlock( coreDataPrivateApis ); + const { getEntityRecords } = select( coreStore ); + return getEntityRecords( 'postType', 'wp_block', { per_page: -1, + [ RECEIVE_INTERMEDIATE_RESULTS ]: true, } ); - return hasFinishedResolution( 'getEntityRecords', [ - 'postType', - 'wp_block', - { per_page: -1 }, - ] ) - ? reusableBlocks - : undefined; } const BLOCK_EDITOR_SETTINGS = [ From 9bd184da7b547d1b46b2e118bde6f0529c71a2d8 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 6 Nov 2024 09:00:28 +0400 Subject: [PATCH 1489/1908] Edit Site: Remove leftover 'priority-queue' dependency (#66773) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: up1512001 <up1512001@git.wordpress.org> --- package-lock.json | 1 - packages/edit-site/package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index e76ea379cd1a6e..59fb1310a15e72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54310,7 +54310,6 @@ "@wordpress/plugins": "*", "@wordpress/preferences": "*", "@wordpress/primitives": "*", - "@wordpress/priority-queue": "*", "@wordpress/private-apis": "*", "@wordpress/reusable-blocks": "*", "@wordpress/router": "*", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 67932bcb06321e..41bf39c1e08332 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -61,7 +61,6 @@ "@wordpress/plugins": "*", "@wordpress/preferences": "*", "@wordpress/primitives": "*", - "@wordpress/priority-queue": "*", "@wordpress/private-apis": "*", "@wordpress/reusable-blocks": "*", "@wordpress/router": "*", From 471e4bdaf6f3b6e5b5ca37f8a00f12424870458c Mon Sep 17 00:00:00 2001 From: David Calhoun <github@davidcalhoun.me> Date: Wed, 6 Nov 2024 00:17:16 -0500 Subject: [PATCH 1490/1908] ci: Address stalling Android E2E test tasks (#66771) * ci: Increase AVD cache key specificity Avoid erroneous cache hits that may result in the CI task hanging indefinitely while terminating the emulator. * Revert "ci: Increase AVD cache key specificity" This reverts commit 2e892a66888295cf3edc1b33c4f4df7792fdbb0f. * ci: Update Android test runner to macOS 13 Attempt to resolve indefinitely hanging Android E2E test tasks. * Revert "ci: Update Android test runner to macOS 13" This reverts commit a4c844daf04dfcd517b293518d65d92063230726. * ci: Disable AVD cache AVD cache disabled as it caused emulator termination to hang indefinitely. Co-authored-by: dcalhoun <dpcalhoun@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .github/workflows/rnmobile-android-runner.yml | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index a57b857aac6234..65bb55e3f63201 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -49,26 +49,28 @@ jobs: - name: Gradle cache uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0 - - name: AVD cache - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 - id: avd-cache - with: - path: | - ~/.android/avd/* - ~/.android/adb* - key: avd-${{ matrix.api-level }} - - - name: Create AVD and generate snapshot for caching - if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@62dbb605bba737720e10b196cb4220d374026a6d # v2.33.0 - with: - api-level: ${{ matrix.api-level }} - force-avd-creation: false - emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - disable-animations: false - arch: x86_64 - profile: Nexus 6 - script: echo "Generated AVD snapshot for caching." + # AVD cache disabled as it caused emulator termination to hang indefinitely. + # https://github.com/ReactiveCircus/android-emulator-runner/issues/385 + # - name: AVD cache + # uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 + # id: avd-cache + # with: + # path: | + # ~/.android/avd/* + # ~/.android/adb* + # key: avd-${{ matrix.api-level }} + # + # - name: Create AVD and generate snapshot for caching + # if: steps.avd-cache.outputs.cache-hit != 'true' + # uses: reactivecircus/android-emulator-runner@62dbb605bba737720e10b196cb4220d374026a6d # v2.33.0 + # with: + # api-level: ${{ matrix.api-level }} + # force-avd-creation: false + # emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + # disable-animations: false + # arch: x86_64 + # profile: Nexus 6 + # script: echo "Generated AVD snapshot for caching." - name: Run tests uses: reactivecircus/android-emulator-runner@62dbb605bba737720e10b196cb4220d374026a6d # v2.33.0 From 7ff76796b8fd7027a3f53933e1f9e5f2917ea2c8 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 6 Nov 2024 09:44:02 +0400 Subject: [PATCH 1491/1908] Cover: Fix media library image selection (#66782) * Cover: Fix media library image selection * Fix sizes for uploaded images Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../block-library/src/cover/edit/index.js | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/block-library/src/cover/edit/index.js b/packages/block-library/src/cover/edit/index.js index 0ad87601bfba8b..1202f28cee50cd 100644 --- a/packages/block-library/src/cover/edit/index.js +++ b/packages/block-library/src/cover/edit/index.js @@ -206,12 +206,24 @@ function CoverEdit( { // Try to use the previous selected image size if it's available // otherwise try the default image size or fallback to full size. - if ( sizeSlug && newMedia?.sizes?.[ sizeSlug ] ) { + if ( + sizeSlug && + ( newMedia?.sizes?.[ sizeSlug ] || + newMedia?.media_details?.sizes?.[ sizeSlug ] ) + ) { mediaAttributes.sizeSlug = sizeSlug; - mediaAttributes.url = newMedia?.sizes?.[ sizeSlug ]?.url; - } else if ( newMedia?.sizes?.[ imageDefaultSize ] ) { + mediaAttributes.url = + newMedia?.sizes?.[ sizeSlug ]?.url || + newMedia?.media_details?.sizes?.[ sizeSlug ]?.source_url; + } else if ( + newMedia?.sizes?.[ imageDefaultSize ] || + newMedia?.media_details?.sizes?.[ imageDefaultSize ] + ) { mediaAttributes.sizeSlug = imageDefaultSize; - mediaAttributes.url = newMedia?.sizes?.[ sizeSlug ]?.url; + mediaAttributes.url = + newMedia?.sizes?.[ imageDefaultSize ]?.url || + newMedia?.media_details?.sizes?.[ imageDefaultSize ] + ?.source_url; } else { mediaAttributes.sizeSlug = DEFAULT_MEDIA_SIZE_SLUG; } From 5c6e6f33a7288b14b6406a5494342c7711c6cd16 Mon Sep 17 00:00:00 2001 From: Manzoor Wani <manzoorwani.jk@gmail.com> Date: Tue, 5 Nov 2024 23:21:12 -0800 Subject: [PATCH 1492/1908] Fix TS types for editor package (#66754) Co-authored-by: manzoorwanijk <manzoorwanijk@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- docs/reference-guides/data/data-core-editor.md | 2 +- packages/editor/README.md | 8 -------- packages/editor/package.json | 1 + packages/editor/src/store/constants.ts | 2 -- packages/editor/src/store/index.js | 4 ---- packages/editor/src/store/selectors.js | 4 ++-- 6 files changed, 4 insertions(+), 17 deletions(-) diff --git a/docs/reference-guides/data/data-core-editor.md b/docs/reference-guides/data/data-core-editor.md index 713a247d88be29..9567d8e4b954fa 100644 --- a/docs/reference-guides/data/data-core-editor.md +++ b/docs/reference-guides/data/data-core-editor.md @@ -786,7 +786,7 @@ Return true if the current post has already been published. _Parameters_ - _state_ `Object`: Global application state. -- _currentPost_ `Object?`: Explicit current post for bypassing registry selector. +- _currentPost_ `[Object]`: Explicit current post for bypassing registry selector. _Returns_ diff --git a/packages/editor/README.md b/packages/editor/README.md index bcd1727e046d07..e0b53362089f1b 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -1631,10 +1631,6 @@ _Related_ - <https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore> -_Type_ - -- `Object` - ### storeConfig Post editor data store configuration. @@ -1643,10 +1639,6 @@ _Related_ - <https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#registerStore> -_Type_ - -- `Object` - ### TableOfContents Renders a table of contents component. diff --git a/packages/editor/package.json b/packages/editor/package.json index e7b46685719dd4..98e0c6d2255b74 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -26,6 +26,7 @@ "module": "build-module/index.js", "react-native": "src/index", "wpScript": true, + "types": "build-types", "sideEffects": [ "build-style/**", "src/**/*.scss", diff --git a/packages/editor/src/store/constants.ts b/packages/editor/src/store/constants.ts index 78708f00cc9eb7..73d6a104370c37 100644 --- a/packages/editor/src/store/constants.ts +++ b/packages/editor/src/store/constants.ts @@ -8,8 +8,6 @@ export const EDIT_MERGE_PROPERTIES = new Set( [ 'meta' ] ); /** * Constant for the store module (or reducer) key. - * - * @type {string} */ export const STORE_NAME = 'core/editor'; diff --git a/packages/editor/src/store/index.js b/packages/editor/src/store/index.js index 392f5f42cbd55b..a3241a2fc7e184 100644 --- a/packages/editor/src/store/index.js +++ b/packages/editor/src/store/index.js @@ -18,8 +18,6 @@ import { unlock } from '../lock-unlock'; * Post editor data store configuration. * * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#registerStore - * - * @type {Object} */ export const storeConfig = { reducer, @@ -31,8 +29,6 @@ export const storeConfig = { * Store definition for the editor namespace. * * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore - * - * @type {Object} */ export const store = createReduxStore( STORE_NAME, { ...storeConfig, diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index 2396cb67c73e69..db452be5c17abb 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -442,8 +442,8 @@ export function isCurrentPostPending( state ) { /** * Return true if the current post has already been published. * - * @param {Object} state Global application state. - * @param {Object?} currentPost Explicit current post for bypassing registry selector. + * @param {Object} state Global application state. + * @param {Object} [currentPost] Explicit current post for bypassing registry selector. * * @return {boolean} Whether the post has been published. */ From 452d3b07a420e5b66d5c182a69f99c102a0af23e Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Wed, 6 Nov 2024 19:09:41 +1100 Subject: [PATCH 1493/1908] Fix Paragraph appender layout shift (building on 66061) (#66779) * Style to prevent Layout shift when placeholder is clicked * Refactor style placement to target block-appender__content specifically * Remove no longer needed rules --------- Co-authored-by: Vrishabhsk <vrishabhsk@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../default-block-appender/content.scss | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/packages/block-editor/src/components/default-block-appender/content.scss b/packages/block-editor/src/components/default-block-appender/content.scss index e2009daa7358c4..71ede90d25c0ca 100644 --- a/packages/block-editor/src/components/default-block-appender/content.scss +++ b/packages/block-editor/src/components/default-block-appender/content.scss @@ -24,20 +24,11 @@ .block-editor-default-block-appender__content { // Set the opacity of the initial block appender to the same as placeholder text in an empty Paragraph block. opacity: 0.62; - } - - // In "constrained" layout containers, the first and last paragraphs have their margins zeroed out. - // In the case of this appender, it needs to apply those same rules to avoid layout shifts. - // Such shifts happen when the bottom margin of the Title block has been set to less than the default 1em margin of paragraphs. - :where(body .is-layout-constrained) &, - :where(.wp-site-blocks) & { - > :first-child { - margin-block-start: 0; - margin-block-end: 0; - } - // Since this appender will only ever appear on an entirely empty document, we don't account for last-child. - // This is also because it will never be the last child, the block inserter that sits in this appender is the last child. + // The following prevents user agent styles from applying margins to the appender's inner paragraph. + // This in turn prevents layout shift due to layout styles removing margins from first and last children. + margin-block-start: 0; + margin-block-end: 0; } // Dropzone. From fe2dcb6ff022b90516021a5d35a0e8bf23b7ac4b Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 6 Nov 2024 18:24:56 +0900 Subject: [PATCH 1494/1908] DataViews: Tweak primary field in patterns grid layout (#66733) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../edit-site/src/components/page-patterns/fields.js | 11 +++-------- .../edit-site/src/components/page-patterns/style.scss | 5 ----- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/packages/edit-site/src/components/page-patterns/fields.js b/packages/edit-site/src/components/page-patterns/fields.js index 0ad47e90c20402..e016dca6cd8557 100644 --- a/packages/edit-site/src/components/page-patterns/fields.js +++ b/packages/edit-site/src/components/page-patterns/fields.js @@ -10,7 +10,7 @@ import { __experimentalHStack as HStack, Button, Tooltip, - Flex, + FlexBlock, } from '@wordpress/components'; import { __, _x } from '@wordpress/i18n'; import { useState, useMemo, useId } from '@wordpress/element'; @@ -122,12 +122,7 @@ function TitleField( { item } ) { const title = decodeEntities( defaultGetTitle( item ) ); return ( <HStack alignment="center" justify="flex-start" spacing={ 2 }> - <Flex - as="div" - gap={ 0 } - justify="flex-start" - className="edit-site-patterns__pattern-title" - > + <FlexBlock className="edit-site-patterns__pattern-title"> { item.type === PATTERN_TYPES.theme ? ( title ) : ( @@ -142,7 +137,7 @@ function TitleField( { item } ) { { title } </Button> ) } - </Flex> + </FlexBlock> { item.type === PATTERN_TYPES.theme && ( <Tooltip placement="top" diff --git a/packages/edit-site/src/components/page-patterns/style.scss b/packages/edit-site/src/components/page-patterns/style.scss index c62fe34daf7d67..d59cce420202ee 100644 --- a/packages/edit-site/src/components/page-patterns/style.scss +++ b/packages/edit-site/src/components/page-patterns/style.scss @@ -41,10 +41,6 @@ flex-shrink: 0; } -.edit-site-patterns__pattern-lock-icon { - min-width: min-content; -} - .edit-site-patterns__section-header { border-bottom: 1px solid #f0f0f0; padding: $grid-unit-20 $grid-unit-60; @@ -77,7 +73,6 @@ .edit-site-patterns__pattern-title { display: block; - width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; From 84048f80c80bf2184c31688787c81036b0174008 Mon Sep 17 00:00:00 2001 From: Utsav Patel <75293077+up1512001@users.noreply.github.com> Date: Wed, 6 Nov 2024 15:10:49 +0530 Subject: [PATCH 1495/1908] Added toggle control to set any image as feature image if no feature image is set for post (#65896) * feature: created toggle control to set content image as feature image if no feature image is set * Fix: docs build * revert: php changes for feature image * feature: created toolbar control to set image as feature image is post don't have feature image set * feature: created block settings & added proper notices for success message * update: added required block context for feature image control * update: set feature image control as per suggestion * remove: unnessary isFeature image attribute * rename: feature image control * Fix: query loop issue * Fix: typo in set featured image * update as per suggestions * Fix: minor feedback * Fix: minor issue --- packages/block-library/src/image/block.json | 2 +- packages/block-library/src/image/image.js | 40 ++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/image/block.json b/packages/block-library/src/image/block.json index f441a6e893290b..16e31217476026 100644 --- a/packages/block-library/src/image/block.json +++ b/packages/block-library/src/image/block.json @@ -4,7 +4,7 @@ "name": "core/image", "title": "Image", "category": "media", - "usesContext": [ "allowResize", "imageCrop", "fixedHeight" ], + "usesContext": [ "allowResize", "imageCrop", "fixedHeight", "postId", "postType", "queryId" ], "description": "Insert an image to make a visual statement.", "keywords": [ "img", "photo", "picture" ], "textdomain": "default", diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index a8d65951635522..61baba2263989c 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -32,6 +32,7 @@ import { __experimentalUseBorderProps as useBorderProps, __experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles, privateApis as blockEditorPrivateApis, + BlockSettingsMenuControls, } from '@wordpress/block-editor'; import { useEffect, useMemo, useState, useRef } from '@wordpress/element'; import { __, _x, sprintf, isRTL } from '@wordpress/i18n'; @@ -39,7 +40,7 @@ import { getFilename } from '@wordpress/url'; import { getBlockBindingsSource, switchToBlockType } from '@wordpress/blocks'; import { crop, overlayText, upload, chevronDown } from '@wordpress/icons'; import { store as noticesStore } from '@wordpress/notices'; -import { store as coreStore } from '@wordpress/core-data'; +import { store as coreStore, useEntityProp } from '@wordpress/core-data'; /** * Internal dependencies @@ -893,6 +894,16 @@ export default function Image( { const shadowProps = getShadowClassesAndStyles( attributes ); const isRounded = attributes.className?.includes( 'is-style-rounded' ); + const { postType, postId, queryId } = context; + const isDescendentOfQueryLoop = Number.isFinite( queryId ); + + const [ , setFeaturedImage ] = useEntityProp( + 'postType', + postType, + 'featured_media', + postId + ); + let img = temporaryURL && hasImageErrored ? ( // Show a placeholder during upload when the blob URL can't be loaded. This can @@ -1094,10 +1105,37 @@ export default function Image( { ); } + /** + * Set the post's featured image with the current image. + */ + const setPostFeatureImage = () => { + setFeaturedImage( id ); + createSuccessNotice( __( 'Post featured image updated.' ), { + type: 'snackbar', + } ); + }; + + const featuredImageControl = ( + <BlockSettingsMenuControls> + { ( { selectedClientIds } ) => + selectedClientIds.length === 1 && + ! isDescendentOfQueryLoop && + postId && + id && + clientId === selectedClientIds[ 0 ] && ( + <MenuItem onClick={ setPostFeatureImage }> + { __( 'Set featured image' ) } + </MenuItem> + ) + } + </BlockSettingsMenuControls> + ); + return ( <> { mediaReplaceFlow } { controls } + { featuredImageControl } { img } <Caption From bd11f595ffab2ace207663117c05ddcddcda8c60 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 6 Nov 2024 11:10:04 +0100 Subject: [PATCH 1496/1908] Select Mode: Hide tool selector in the post editor and force design mode (#66784) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/block-editor/src/store/selectors.js | 7 +++++-- .../src/components/document-tools/index.js | 8 +++++++- .../provider/use-block-editor-settings.js | 5 +++++ .../editor/various/write-design-mode.spec.js | 20 +++++++++++++------ 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index b5afb2891ef1cf..b09c3d3d01b165 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2764,8 +2764,11 @@ export function isNavigationMode( state ) { * @return {string} the editor mode. */ export const __unstableGetEditorMode = createRegistrySelector( - ( select ) => () => { - return select( preferencesStore ).get( 'core', 'editorTool' ); + ( select ) => ( state ) => { + return ( + state.settings.editorTool ?? + select( preferencesStore ).get( 'core', 'editorTool' ) + ); } ); diff --git a/packages/editor/src/components/document-tools/index.js b/packages/editor/src/components/document-tools/index.js index b2295b555ce080..74118caaf5849c 100644 --- a/packages/editor/src/components/document-tools/index.js +++ b/packages/editor/src/components/document-tools/index.js @@ -35,6 +35,7 @@ function DocumentTools( { className, disableBlockTools = false } ) { inserterSidebarToggleRef, listViewToggleRef, showIconLabels, + showTools, } = useSelect( ( select ) => { const { get } = select( preferencesStore ); const { @@ -42,6 +43,8 @@ function DocumentTools( { className, disableBlockTools = false } ) { getEditorMode, getInserterSidebarToggleRef, getListViewToggleRef, + getRenderingMode, + getCurrentPostType, } = unlock( select( editorStore ) ); const { getShortcutRepresentation } = select( keyboardShortcutsStore ); @@ -56,6 +59,9 @@ function DocumentTools( { className, disableBlockTools = false } ) { showIconLabels: get( 'core', 'showIconLabels' ), isDistractionFree: get( 'core', 'distractionFree' ), isVisualMode: getEditorMode() === 'visual', + showTools: + getRenderingMode() !== 'post-only' || + getCurrentPostType() === 'wp_template', }; }, [] ); @@ -128,7 +134,7 @@ function DocumentTools( { className, disableBlockTools = false } ) { ) } { ( isWideViewport || ! showIconLabels ) && ( <> - { isLargeViewport && ( + { showTools && isLargeViewport && ( <ToolbarItem as={ ToolSelector } showTooltip={ ! showIconLabels } diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index e90be6487a0ea9..f5c45f431e2c85 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -328,6 +328,10 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { : settings.template, __experimentalSetIsInserterOpened: setIsInserterOpened, [ sectionRootClientIdKey ]: sectionRootClientId, + editorTool: + renderingMode === 'post-only' && postType !== 'wp_template' + ? 'edit' + : undefined, }; return blockEditorSettings; @@ -355,6 +359,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { sectionRootClientId, globalStylesData, globalStylesLinksData, + renderingMode, ] ); } diff --git a/test/e2e/specs/editor/various/write-design-mode.spec.js b/test/e2e/specs/editor/various/write-design-mode.spec.js index 443a70ea92f680..2116f9042685af 100644 --- a/test/e2e/specs/editor/various/write-design-mode.spec.js +++ b/test/e2e/specs/editor/various/write-design-mode.spec.js @@ -4,21 +4,29 @@ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); test.describe( 'Write/Design mode', () => { - test.beforeEach( async ( { admin, editor } ) => { - await admin.createNewPost(); - await expect( - editor.canvas.getByRole( 'textbox', { name: 'Add title' } ) - ).toBeFocused(); + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'emptytheme' ); + } ); + + test.beforeEach( async ( { admin } ) => { + await admin.visitSiteEditor( { + postId: 'emptytheme//index', + postType: 'wp_template', + canvas: 'edit', + } ); } ); test.afterAll( async ( { requestUtils } ) => { - await requestUtils.deleteAllPosts(); + await requestUtils.activateTheme( 'twentytwentyone' ); } ); test( 'Should prevent selecting intermediary blocks', async ( { editor, page, } ) => { + // Clear all content + await editor.setContent( '' ); + // Insert a section with a nested block and an editable block. await editor.insertBlock( { name: 'core/group', From 624c938244ccd0ceda3decfcb2caa22a37487e73 Mon Sep 17 00:00:00 2001 From: Weston Ruter <westonruter@google.com> Date: Wed, 6 Nov 2024 06:44:29 -0800 Subject: [PATCH 1497/1908] Delay block hydration to allow stores to initialize (#66772) Co-authored-by: westonruter <westonruter@git.wordpress.org> Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/interactivity/src/init.ts | 11 +++++++++++ packages/interactivity/src/utils.ts | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/interactivity/src/init.ts b/packages/interactivity/src/init.ts index ddf6785d4dfdf4..fa1eec51c3e27e 100644 --- a/packages/interactivity/src/init.ts +++ b/packages/interactivity/src/init.ts @@ -33,6 +33,17 @@ export const init = async () => { `[data-${ directivePrefix }-interactive]` ); + /* + * This `await` with setTimeout is required to apparently ensure that the interactive blocks have their stores + * fully initialized prior to hydrating the blocks. If this is not present, then an error occurs, for example: + * > view.js:46 Uncaught (in promise) ReferenceError: Cannot access 'state' before initialization + * This occurs when splitTask() is implemented with scheduler.yield() as opposed to setTimeout(), as with the former + * split tasks are added to the front of the task queue whereas with the latter they are added to the end of the queue. + */ + await new Promise( ( resolve ) => { + setTimeout( resolve, 0 ); + } ); + for ( const node of nodes ) { if ( ! hydratedIslands.has( node ) ) { await splitTask(); diff --git a/packages/interactivity/src/utils.ts b/packages/interactivity/src/utils.ts index 9cd6f8bebb0d1c..ab6b0074727ee7 100644 --- a/packages/interactivity/src/utils.ts +++ b/packages/interactivity/src/utils.ts @@ -54,7 +54,7 @@ const afterNextFrame = ( callback: () => void ) => { /** * Returns a promise that resolves after yielding to main. * - * @return Promise + * @return Promise<void> */ export const splitTask = typeof window.scheduler?.yield === 'function' From fc740ff4a5515e1baccd36c734e4faa6e2bafd26 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 6 Nov 2024 14:50:17 +0000 Subject: [PATCH 1498/1908] Bump plugin version to 19.6.0 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 128156a947b27f..89e65de4e94794 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.6.0-rc.3 + * Version: 19.6.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 59fb1310a15e72..80abc752c92120 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.6.0-rc.3", + "version": "19.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.6.0-rc.3", + "version": "19.6.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "workspaces": [ diff --git a/package.json b/package.json index 6e519e2f1070e9..741475d8177705 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.6.0-rc.3", + "version": "19.6.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From fb9587e0dafa3f728197913c5292e0a7bae2073b Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 6 Nov 2024 15:53:11 +0000 Subject: [PATCH 1499/1908] Update Changelog for 19.6.0 --- changelog.txt | 299 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 297 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index ad860707a261f7..bcbfbb2dc48449 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,23 +1,318 @@ == Changelog == -= 19.6.0-rc.3 = += 19.6.0 = ## Changelog +### Enhancements + +#### Components +- Add elevation tokens to storybook. ([66122](https://github.com/WordPress/gutenberg/pull/66122)) +- Add foundations:Elevation to storybook. ([66124](https://github.com/WordPress/gutenberg/pull/66124)) +- Add radius foundation and tokens to storybook. ([66219](https://github.com/WordPress/gutenberg/pull/66219)) +- Combobox, FormTokenField: Show message when no matches found. ([66142](https://github.com/WordPress/gutenberg/pull/66142)) +- Storybook: Organizes components under 'Utilities'. ([66210](https://github.com/WordPress/gutenberg/pull/66210)) +- Tabs: Expose active tab item props, use ariakit prop types. ([66223](https://github.com/WordPress/gutenberg/pull/66223)) +- Tabs: Remove custom logic. ([66097](https://github.com/WordPress/gutenberg/pull/66097)) +- `DropdownMenuV2`: Rename to `Menu`. ([66289](https://github.com/WordPress/gutenberg/pull/66289)) + +#### Block Library +- Add Transformation from Separator to Spacer. ([66230](https://github.com/WordPress/gutenberg/pull/66230)) +- Add lightbox option in gallery block link control. ([64014](https://github.com/WordPress/gutenberg/pull/64014)) +- Archives: Add border block support. ([63400](https://github.com/WordPress/gutenberg/pull/63400)) +- Border support added to comments. ([66354](https://github.com/WordPress/gutenberg/pull/66354)) +- Cover Block: Add Image Resolution options. ([62926](https://github.com/WordPress/gutenberg/pull/62926)) +- HTML Block: Force HTML preview in view mode. ([66440](https://github.com/WordPress/gutenberg/pull/66440)) + +#### Zoom Out +- Add keyboard shortcut in editor. ([66400](https://github.com/WordPress/gutenberg/pull/66400)) +- Iterate zoom out shuffle into a more visual control. ([66194](https://github.com/WordPress/gutenberg/pull/66194)) +- Use the zoom-level value to scale the iframe. ([66280](https://github.com/WordPress/gutenberg/pull/66280)) + +#### Site Editor +- Remove synchronization of canvas mode into store. ([66213](https://github.com/WordPress/gutenberg/pull/66213)) +- Style Book: Clean up layout. ([66255](https://github.com/WordPress/gutenberg/pull/66255)) +- Update site icon and title position. ([66171](https://github.com/WordPress/gutenberg/pull/66171)) +- Editor Interface: Remove small header from global styles/plugin sidebar. ([64474](https://github.com/WordPress/gutenberg/pull/64474)) +- Remove purple coloring from DocumentBar and PostCard. ([66451](https://github.com/WordPress/gutenberg/pull/66451)) +- Core Data: Add the 'getEntitiesConfig' resolver. ([65871](https://github.com/WordPress/gutenberg/pull/65871)) +- BlockGroupToolbar: Better i18n context for toolbar labels. ([66211](https://github.com/WordPress/gutenberg/pull/66211)) +- Set `ResizableEditor` height based on border-box. ([66342](https://github.com/WordPress/gutenberg/pull/66342)) +- Add align-item related icons. ([66242](https://github.com/WordPress/gutenberg/pull/66242)) +- Stabilize isPreviewMode flag. ([66149](https://github.com/WordPress/gutenberg/pull/66149)) + +#### Data Views +- Fix alignment of action items in list layout. ([66273](https://github.com/WordPress/gutenberg/pull/66273)) +- Templates: Hide media field in list view. ([66573](https://github.com/WordPress/gutenberg/pull/66573)) + +#### Global Styles +- Backport: Caching of global styles for blocks from core. ([66349](https://github.com/WordPress/gutenberg/pull/66349)) +- Style Book: Add color tab. ([65692](https://github.com/WordPress/gutenberg/pull/65692)) + +#### Real-time Collaboration +- Inline Commenting: Disable comments on published posts for now. ([66583](https://github.com/WordPress/gutenberg/pull/66583)) + + +#### REST API +- Backport from WordPress core: Improvements for the post format query loop filter. ([66037](https://github.com/WordPress/gutenberg/pull/66037)) + +#### Build Tooling +- Create Block: Adds `--target-dir` flag to allow the tool to target where to scaffold. ([53781](https://github.com/WordPress/gutenberg/pull/53781)) +- Scripts: Add build-blocks-manifest command. ([65866](https://github.com/WordPress/gutenberg/pull/65866)) +- Scripts: Add BlueOak-1.0.0 license to GPL2 compatible. ([66139](https://github.com/WordPress/gutenberg/pull/66139)) +- WP Scripts: Add a `--root-folder` argument to the `plugin-zip` command. ([61375](https://github.com/WordPress/gutenberg/pull/61375)) + ### Bug Fixes +#### Zoom Out +- Disable zoom out toggle button when Style Book is open. ([66228](https://github.com/WordPress/gutenberg/pull/66228)) +- Don't switch editor mode when changing entities. ([66452](https://github.com/WordPress/gutenberg/pull/66452)) +- Fix scaling animation for device previews. ([66132](https://github.com/WordPress/gutenberg/pull/66132)) +- Fix zoom out not persisting while switching between editor and code editor. ([65932](https://github.com/WordPress/gutenberg/pull/65932)) +- Fix zoom out shortcut on Windows. ([66506](https://github.com/WordPress/gutenberg/pull/66506)) +- Fix: Activate zoom out on large viewport. ([66308](https://github.com/WordPress/gutenberg/pull/66308)) +- Hide slots and grouping buttons. ([66243](https://github.com/WordPress/gutenberg/pull/66243)) +- Remove zoom-out toolbar. ([66039](https://github.com/WordPress/gutenberg/pull/66039)) +- Resets the Zoom on viewed/edited entity change. ([66232](https://github.com/WordPress/gutenberg/pull/66232)) +- Revise zoom layout shift fix. ([66390](https://github.com/WordPress/gutenberg/pull/66390)) +- Zoom Out: Rely on zoom-level instead of zoom-out mode. ([66141](https://github.com/WordPress/gutenberg/pull/66141)) +- Zoom Out: Fix bouncy drop zones. ([66399](https://github.com/WordPress/gutenberg/pull/66399)) + #### Block Editor +- Block inserter: Prevent editor from crashing if `blockType.parent` is a string. ([66234](https://github.com/WordPress/gutenberg/pull/66234)) +- Block toolbar: Account for scrollable blocks that affect the position of the block toolbar. ([66188](https://github.com/WordPress/gutenberg/pull/66188)) +- Fix extra scrollbar appearing when searching in the inserter. ([66229](https://github.com/WordPress/gutenberg/pull/66229)) +- Fix: Show paragraph block variations in rich text inserter. ([66318](https://github.com/WordPress/gutenberg/pull/66318)) +- Group: Fix padding select. ([65857](https://github.com/WordPress/gutenberg/pull/65857)) +- Link Shortcut: Only trigger the link shortcut if there's a text selection. ([66056](https://github.com/WordPress/gutenberg/pull/66056)) +- Remove relative position from sidebar tabpanel. ([66267](https://github.com/WordPress/gutenberg/pull/66267)) +- Rich text: Remove empty file. ([66553](https://github.com/WordPress/gutenberg/pull/66553)) + +- Block editor: Self nesting and circular nesting block fix. ([66121](https://github.com/WordPress/gutenberg/pull/66121)) - Post Editor: Set the default value of the editorTool to edit. ([66636](https://github.com/WordPress/gutenberg/pull/66636)) +#### Components +- ColorPalette: Prevent overflow of custom color button background. ([66152](https://github.com/WordPress/gutenberg/pull/66152)) +- Fix: Text overflow in Patterns filter. ([66504](https://github.com/WordPress/gutenberg/pull/66504)) +- RadioGroup: Fix arrow key navigation in RTL. ([66202](https://github.com/WordPress/gutenberg/pull/66202)) +- Tabs and TabPanel: Fix arrow key navigation in RTL. ([66201](https://github.com/WordPress/gutenberg/pull/66201)) +- Tabs and ToggleGroupControl: Round indicator size. ([66426](https://github.com/WordPress/gutenberg/pull/66426)) +- Tabs: Fix animation timings. ([66198](https://github.com/WordPress/gutenberg/pull/66198)) +- Tabs: Override tablist's tabindex only when necessary. ([66209](https://github.com/WordPress/gutenberg/pull/66209)) +- Tabs: Restore vertical alignment for tabs content. ([66215](https://github.com/WordPress/gutenberg/pull/66215)) +- Tabs: Update indicator more reactively. ([66207](https://github.com/WordPress/gutenberg/pull/66207)) +- SpacingSizesControl: Use generic label for linked button. ([66304](https://github.com/WordPress/gutenberg/pull/66304)) + +#### i18n +- Miscellaneous i18n fixes. ([66510](https://github.com/WordPress/gutenberg/pull/66510)) +- Remove most of the occurrences of the verb toggle. ([66371](https://github.com/WordPress/gutenberg/pull/66371)) + +#### Post Editor +- Always force iframe in pattern editor. ([65887](https://github.com/WordPress/gutenberg/pull/65887)) +- Editor: Multi-entity saving: Show correct count of entities to be saved. ([66482](https://github.com/WordPress/gutenberg/pull/66482)) +- Fix : "Set featured image" button border flashes on focus. ([66092](https://github.com/WordPress/gutenberg/pull/66092)) +- Fix Parent Check Condition in `buildTermsTree`. ([66006](https://github.com/WordPress/gutenberg/pull/66006)) +- Fix: Improve the DocumentBar post type label for the Homepage and Posts Page cases. ([66355](https://github.com/WordPress/gutenberg/pull/66355)) +- PostTaxonomiesFlatTermSelector: Restore space between tag list and most used tags. ([66566](https://github.com/WordPress/gutenberg/pull/66566)) +- Typo metabox pane is a meta box panel. ([66502](https://github.com/WordPress/gutenberg/pull/66502)) + +#### Block Library +- Block registration: Normalize blockType.parent to `array`. ([66250](https://github.com/WordPress/gutenberg/pull/66250)) +- Button Block: Apply Stretch Styles Correctly. ([64770](https://github.com/WordPress/gutenberg/pull/64770)) +- Buttons: Fix the initial white space in nofollow rel. ([66303](https://github.com/WordPress/gutenberg/pull/66303)) +- Fix - Image block: Aspect ratio not responding when dimensions are not set. ([66217](https://github.com/WordPress/gutenberg/pull/66217)) +- Navigation block: Fix block appender size. ([66153](https://github.com/WordPress/gutenberg/pull/66153)) +- Fix the navigation issue inside cover blocks. ([66093](https://github.com/WordPress/gutenberg/pull/66093)) + +#### Site Editor +- Edit Site: Fix canvasMode var. ([66316](https://github.com/WordPress/gutenberg/pull/66316)) +- Fix button hover style in sidebar navigation screen. ([66505](https://github.com/WordPress/gutenberg/pull/66505)) +- Remove toggle verb from post list data views 'Toggle details panel'. ([66334](https://github.com/WordPress/gutenberg/pull/66334)) +- Revert 66431 (Site editor: Remove "default" admin CSS). ([66540](https://github.com/WordPress/gutenberg/pull/66540)) +- Restore block-library editor.css outside canvas. ([66556](https://github.com/WordPress/gutenberg/pull/66556)) +- Fix extraneous scrollbar in device previews. ([66494](https://github.com/WordPress/gutenberg/pull/66494)) +- Global styles: Move preload paths filter to 6.7 (previously 6.8). ([66543](https://github.com/WordPress/gutenberg/pull/66543)) +- Fix comment output in styles. ([66439](https://github.com/WordPress/gutenberg/pull/66439)) +- Site editor: Fix save shortcut. ([66423](https://github.com/WordPress/gutenberg/pull/66423)) +- Preload: Fix multiple regressions around global styles. ([66468](https://github.com/WordPress/gutenberg/pull/66468)) +#### Build tooling +- Create block: Ensure $slug is replaced with passed slug. ([66528](https://github.com/WordPress/gutenberg/pull/66528)) + +### Accessibility + +#### Post Editor +- Add featured image alt text. ([66189](https://github.com/WordPress/gutenberg/pull/66189)) +- Fix : Badge Color contrast. ([66360](https://github.com/WordPress/gutenberg/pull/66360)) + +#### Block Editor +- ImageSizeControls: Replace ButtonGroup with ToggleGroupControl. ([65386](https://github.com/WordPress/gutenberg/pull/65386)) +- Improve the link preview accessibility and labels. ([60908](https://github.com/WordPress/gutenberg/pull/60908)) + +#### Block Library +- Search: Replace ButtonGroup usage with ToggleGroupControl. ([65340](https://github.com/WordPress/gutenberg/pull/65340)) +- Remove clip & -webkit-clip-path for downloadable-block-list-item style.scss. ([66147](https://github.com/WordPress/gutenberg/pull/66147)) + +#### Global Styles +- Global styles menu: Avoid visible labels and accessible names mismatch. ([65124](https://github.com/WordPress/gutenberg/pull/65124)) + +#### Site Editor +- Fix Global styles panel header buttons text overlap for 'Show button text labels'. ([63243](https://github.com/WordPress/gutenberg/pull/63243)) +- Update the speak messages when switching editor modes. ([66278](https://github.com/WordPress/gutenberg/pull/66278)) + +### Performance + +#### Site Editor +- Remove "default" admin CSS. ([66431](https://github.com/WordPress/gutenberg/pull/66431)) +- Remove content styles outside canvas. ([66432](https://github.com/WordPress/gutenberg/pull/66432)) +- Block Style Variations: Reuse block metadata in WP_Theme_JSON::Get_valid_block_style_variations() for better performance. ([66539](https://github.com/WordPress/gutenberg/pull/66539)) +- Block Bindings: Use `getEntityConfig` instead of `getPostTypes` to get available slugs. ([66101](https://github.com/WordPress/gutenberg/pull/66101)) + +#### Build Tooling +- Fix/compare performance with correct branch. ([66196](https://github.com/WordPress/gutenberg/pull/66196)) + +### Experiments + +- Add Inline comment experimental flag. ([60622](https://github.com/WordPress/gutenberg/pull/60622)) +- QuickEdit: Add slug field control. ([65196](https://github.com/WordPress/gutenberg/pull/65196)) + +#### Data Views +- Quick Edit: Fix JS error when bulk editing pages. ([66358](https://github.com/WordPress/gutenberg/pull/66358)) +- QuickEdit: Add Featured Image Control. ([64496](https://github.com/WordPress/gutenberg/pull/64496)) +- QuickEdit: Add Parent field. ([66527](https://github.com/WordPress/gutenberg/pull/66527)) + +### Documentation + +- BaseControl: Auto-generate readme. ([66500](https://github.com/WordPress/gutenberg/pull/66500)) +- Components: Prevent generated readmes duplicating h1 elements when published. ([66180](https://github.com/WordPress/gutenberg/pull/66180)) +- Correct documentation on display type in flow layouts. ([66224](https://github.com/WordPress/gutenberg/pull/66224)) +- Docs: Interactivity API - Add documentation for `getServerState()` and `getServerContext()`. ([66104](https://github.com/WordPress/gutenberg/pull/66104)) +- Fix undo/redo Button size in Storybook playground. ([66538](https://github.com/WordPress/gutenberg/pull/66538)) +- Fix: JSON Schema Docgen doesn't work on Windows OS. ([66414](https://github.com/WordPress/gutenberg/pull/66414)) +- ItemGroup: Improve stories to default to bordered and separated. ([66191](https://github.com/WordPress/gutenberg/pull/66191)) +- README: Add Storybook badge. ([66529](https://github.com/WordPress/gutenberg/pull/66529)) +- Remove meetings that no longer occur from Contributor Guide. ([66421](https://github.com/WordPress/gutenberg/pull/66421)) +- Site editor routes: Add documentation for areas and prevent `edit` area from rendering when canvas is `edit`. ([66309](https://github.com/WordPress/gutenberg/pull/66309)) +- Update documentation about build process changes. ([66428](https://github.com/WordPress/gutenberg/pull/66428)) +- Docs: Example for getSelectedBlock. ([66108](https://github.com/WordPress/gutenberg/pull/66108)) + +### Code Quality + +#### Block Editor +- ESLint: Remove explicit `react-hooks/exhaustive-deps` disabling. ([66461](https://github.com/WordPress/gutenberg/pull/66461)) +- ESLint: Remove various React Compiler mutation violations. ([66327](https://github.com/WordPress/gutenberg/pull/66327)) +- Fix 'useInstanceId' hook reference. ([66406](https://github.com/WordPress/gutenberg/pull/66406)) +- Fix React Compiler error for Duotone. ([66492](https://github.com/WordPress/gutenberg/pull/66492)) +- Fix React Complier error for 'useEventListeners'. ([66495](https://github.com/WordPress/gutenberg/pull/66495)) +- Import only the actually used PostCSS exports. ([66379](https://github.com/WordPress/gutenberg/pull/66379)) +- No need to unlock public actions. ([66260](https://github.com/WordPress/gutenberg/pull/66260)) +- Remove patterns UI stylesheet from iframe. ([66306](https://github.com/WordPress/gutenberg/pull/66306)) +- Remove unnecessary Tooltip component from radius control linked button. ([66274](https://github.com/WordPress/gutenberg/pull/66274)) +- Rich Text: Fix React Complier error for 'useEventListeners'. ([66460](https://github.com/WordPress/gutenberg/pull/66460)) +- Storybook: Add BlockPatternsList story. ([66227](https://github.com/WordPress/gutenberg/pull/66227)) +- Block editor: Remove reusable blocks stylesheet from iframe. ([66285](https://github.com/WordPress/gutenberg/pull/66285)) + + +#### Components +- BorderBoxControl: Deprecate 36px default size. ([65752](https://github.com/WordPress/gutenberg/pull/65752)) +- BorderControl: Deprecate 36px default size. ([65755](https://github.com/WordPress/gutenberg/pull/65755)) +- DrodownMenuV2: Rename folder to `menu`. ([66473](https://github.com/WordPress/gutenberg/pull/66473)) +- ESLint: Stop disabling `react-hooks/exhaustive-deps` rule. ([66324](https://github.com/WordPress/gutenberg/pull/66324)) +- Fix React Compiler error for 'useAutocomplete'. ([66496](https://github.com/WordPress/gutenberg/pull/66496)) +- PaletteEdit: Use `ItemGroup` and `Item`, and avoid custom styles. ([66164](https://github.com/WordPress/gutenberg/pull/66164)) +- TabPanel: Add 40px size prop to tab Button. ([66557](https://github.com/WordPress/gutenberg/pull/66557)) +- Tabs: Align to standard compound components structure. ([66225](https://github.com/WordPress/gutenberg/pull/66225)) +- Tabs: Simplify styled components code. ([66208](https://github.com/WordPress/gutenberg/pull/66208)) + +#### Compose +- Compose: Fix React Complier error for 'useCopyToClipboard'. ([66444](https://github.com/WordPress/gutenberg/pull/66444)) +- Composer: Fix React Compiler errors for 'useDropZone'. ([66469](https://github.com/WordPress/gutenberg/pull/66469)) + +#### Dataviews +- Fields: Fix React Compiler mutation errors. ([66464](https://github.com/WordPress/gutenberg/pull/66464)) +- Fields: Update a few function definitions. ([66315](https://github.com/WordPress/gutenberg/pull/66315)) +#### Interface +- Interface: Remove duplicate 'withComplementaryAreaContext' file. ([66348](https://github.com/WordPress/gutenberg/pull/66348)) +- Interface: Remove unused private API support. ([66565](https://github.com/WordPress/gutenberg/pull/66565)) +- Interface: Use plugin context hook instead of HoC. ([66362](https://github.com/WordPress/gutenberg/pull/66362)) + +#### Zoom Out +- Bundle behavior in block-editor and add story. ([66240](https://github.com/WordPress/gutenberg/pull/66240)) +- Editor: Handle zoom out state via the 'switchEditorMode' action. ([66262](https://github.com/WordPress/gutenberg/pull/66262)) +- Fix/html scale code quality. ([66181](https://github.com/WordPress/gutenberg/pull/66181)) +- Make useZoomOut hook private. ([66374](https://github.com/WordPress/gutenberg/pull/66374)) +- Remove double click to exit hook from the block-editor package. ([66335](https://github.com/WordPress/gutenberg/pull/66335)) +- Remove viewport check from useZoomOut hook. ([66341](https://github.com/WordPress/gutenberg/pull/66341)) + +#### Post Editor +- Editor: No need to reset mode when changing device preview types. ([66261](https://github.com/WordPress/gutenberg/pull/66261)) +- Editor: Use plugin context hook in 'PluginMoreMenuItem'. ([66351](https://github.com/WordPress/gutenberg/pull/66351)) +- Editor: Use plugin context hook in 'PluginPreviewMenuItem'. ([66350](https://github.com/WordPress/gutenberg/pull/66350)) +- Fix typo after #63669. ([66396](https://github.com/WordPress/gutenberg/pull/66396)) +- Remove leftover JS code from 66451. ([66472](https://github.com/WordPress/gutenberg/pull/66472)) + +#### Block Library +- Cleanup unnecessary notice removal. ([66409](https://github.com/WordPress/gutenberg/pull/66409)) +- ESLint: Fix a couple of React Compiler reassignment errors. ([66331](https://github.com/WordPress/gutenberg/pull/66331)) +- Footnotes: Remove extra callback when parsing content. ([66370](https://github.com/WordPress/gutenberg/pull/66370)) +- Gallery: Fix React Compiler reassignment error. ([66408](https://github.com/WordPress/gutenberg/pull/66408)) +- Table Block: Remove hasArrowIndicator prop. ([66204](https://github.com/WordPress/gutenberg/pull/66204)) + +#### Style Book +- Avoid state/effect combo when generating values. ([66446](https://github.com/WordPress/gutenberg/pull/66446)) +- Fix React Compiler error. ([66445](https://github.com/WordPress/gutenberg/pull/66445)) + +#### Global Styles +- Clean up: Adjust reusable-blocks dependencies. ([66302](https://github.com/WordPress/gutenberg/pull/66302)) +- Fix React Compiler variable mutation error. ([66410](https://github.com/WordPress/gutenberg/pull/66410)) +- Theme JSON: Get_block_nodes - relocate $selectors assignment. ([66265](https://github.com/WordPress/gutenberg/pull/66265)) + +#### Interactivity API +- Interactivity API: Add comments to the `deepMerge()` function. ([66220](https://github.com/WordPress/gutenberg/pull/66220)) +- Interactivity API: Add tests for handling arrays in `deepMerge()`. ([66218](https://github.com/WordPress/gutenberg/pull/66218)) +- Interactivity API: Delay block hydration to allow interactive block stores to initialize. ([66772])(https://github.com/WordPress/gutenberg/pull/66772) + +#### Site Editor +- Prepare route registration by refactoring the site editor router. ([66030](https://github.com/WordPress/gutenberg/pull/66030)) +- Navigation: Improve trigger for fallback navigation. ([66478](https://github.com/WordPress/gutenberg/pull/66478)) +#### Build Tooling +- Scripts: Refactor to extract license logic. ([66179](https://github.com/WordPress/gutenberg/pull/66179)) +- Plugins: Deprecate 'withPluginContext' HOC. ([66363](https://github.com/WordPress/gutenberg/pull/66363)) + +### Tools + +#### Testing +- Fix [Flaky Test] Entering zoomed out mode zooms the canvas. ([66212](https://github.com/WordPress/gutenberg/pull/66212)) +- Fix end-to-end test for padding appender. ([66080](https://github.com/WordPress/gutenberg/pull/66080)) +- Upgrade Playwright to v1.48. ([66296](https://github.com/WordPress/gutenberg/pull/66296)) + +#### Build Tooling +- Add new private `vips` package. ([64845](https://github.com/WordPress/gutenberg/pull/64845)) +- Revert "Use npm workspaces for packages". ([66270](https://github.com/WordPress/gutenberg/pull/66270)) +- Add theme type to the bug report issue template. ([63851](https://github.com/WordPress/gutenberg/pull/63851)) +- Pull request automation: Use full npm install. ([66314](https://github.com/WordPress/gutenberg/pull/66314)) +- Use npm workspaces for packages (second attempt). ([66272](https://github.com/WordPress/gutenberg/pull/66272)) + + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @AhmarZaidi: Remove toggle verb from post list data views 'Toggle details panel'. ([66334](https://github.com/WordPress/gutenberg/pull/66334)) +- @mediaformat: Remove clip & -webkit-clip-path for downloadable-block-list-item style.scss. ([66147](https://github.com/WordPress/gutenberg/pull/66147)) +- @nicolasgalvez: WP Scripts: Add a `--root-folder` argument to the `plugin-zip` command. ([61375](https://github.com/WordPress/gutenberg/pull/61375)) +- @poojabhimani12: Add Inline comment experimental flag. ([60622](https://github.com/WordPress/gutenberg/pull/60622)) +- @rinkalpagdar: Border support added to comments. ([66354](https://github.com/WordPress/gutenberg/pull/66354)) +- @rudrakshi-gupta: Add Transformation from Separator to Spacer. ([66230](https://github.com/WordPress/gutenberg/pull/66230)) +- @SH4LIN: GH-66090: Self nesting and circular nesting block fix. ([66121](https://github.com/WordPress/gutenberg/pull/66121)) ## Contributors The following contributors merged PRs in this release: -@arthur791004 +@aaronrobertshaw @afercia @AhmarZaidi @akasunil @andrewserong @arthur791004 @carolinan @cbravobernal @ciampo @dhruvang21 @ellatrix @getdave @gigitux @hbhalodia @jameskoster @jeryj @jsnajdr @juanfra @madhusudhand @MaggieCabrera @Mamaduka @mattrwalker @mcsf @mediaformat @michalczaplinski @mirka @mreishus @ndiego @nicolasgalvez @ntsekouras @oandregal @PARTHVATALIYA @peterwilsoncc @poojabhimani12 @prajapatisagar @ramonjd @renatho @rinkalpagdar @rudrakshi-gupta @ryanwelcher @SantosGuillamot @SH4LIN @sirreal @stokesman @swissspidy @t-hamano @talldan @tellthemachines @torounit @troychaplin @tyxla @vipul0425 @Vrishabhsk @vykes-mac @westonruter @youknowriad @zaguiini = 19.5.1 = From b2528743b4d8ab2a240290b09e3df9fba0523a4f Mon Sep 17 00:00:00 2001 From: Rinkal Pagdar <92097119+rinkalpagdar@users.noreply.github.com> Date: Thu, 7 Nov 2024 04:14:49 +0530 Subject: [PATCH 1500/1908] Post Content: Add border and spacing support (#66366) Co-authored-by: rinkalpagdar <rinkalpagdar@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- .../block-library/src/post-content/block.json | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index dd49d156857249..4db90e9b2f8142 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -616,7 +616,7 @@ Displays the contents of a post or page. ([Source](https://github.com/WordPress/ - **Name:** core/post-content - **Category:** theme -- **Supports:** align (full, wide), background (backgroundImage, backgroundSize), color (background, gradients, link, text), dimensions (minHeight), layout, spacing (blockGap, padding), typography (fontSize, lineHeight), ~~html~~ +- **Supports:** align (full, wide), background (backgroundImage, backgroundSize), color (background, gradients, link, text), dimensions (minHeight), layout, spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~ ## Date diff --git a/packages/block-library/src/post-content/block.json b/packages/block-library/src/post-content/block.json index 1b9de707cb3220..ed9c47154b2f8e 100644 --- a/packages/block-library/src/post-content/block.json +++ b/packages/block-library/src/post-content/block.json @@ -27,6 +27,7 @@ "spacing": { "blockGap": true, "padding": true, + "margin": true, "__experimentalDefaultControls": { "margin": false, "padding": false @@ -52,8 +53,20 @@ "__experimentalDefaultControls": { "fontSize": true } + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true, + "__experimentalDefaultControls": { + "radius": true, + "color": true, + "width": true, + "style": true + } } }, "style": "wp-block-post-content", "editorStyle": "wp-block-post-content-editor" -} +} \ No newline at end of file From 3e46fe7e222a20b1dff36c1a8f435436e9bc134a Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 7 Nov 2024 11:54:46 +1100 Subject: [PATCH 1501/1908] Global styles revisions: move focus and active state to list item (#66780) * This PR removes the button that loads the global revision and moves it up to an accessible list item. The result is that the list item is tabbable and selectable via keyboard, and the focus state wraps the entire item. * Use button border * Fix e2e tests and use composite component Unlinked contributors: jarekmorawski. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../screen-revisions/revisions-buttons.js | 59 +++++++++---------- .../global-styles/screen-revisions/style.scss | 28 ++++----- .../block-style-variations.spec.js | 2 +- .../user-global-styles-revisions.spec.js | 18 +++--- 4 files changed, 50 insertions(+), 57 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js b/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js index b7ce38857c9461..d6acd711108b5c 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js +++ b/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js @@ -1,18 +1,13 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - /** * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { Button } from '@wordpress/components'; +import { Button, Composite } from '@wordpress/components'; import { dateI18n, getDate, humanTimeDiff, getSettings } from '@wordpress/date'; import { store as coreStore } from '@wordpress/core-data'; import { useSelect } from '@wordpress/data'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; - +import { ENTER, SPACE } from '@wordpress/keycodes'; /** * Internal dependencies */ @@ -117,10 +112,11 @@ function RevisionsButtons( { const { datetimeAbbreviated } = getSettings().formats; return ( - <ol + <Composite + orientation="vertical" className="edit-site-global-styles-screen-revisions__revisions-list" aria-label={ __( 'Global styles revisions list' ) } - role="group" + role="listbox" > { userRevisions.map( ( revision, index ) => { const { id, author, modified } = revision; @@ -149,28 +145,26 @@ function RevisionsButtons( { ); return ( - <li - className={ clsx( - 'edit-site-global-styles-screen-revisions__revision-item', - { - 'is-selected': isSelected, - 'is-active': areStylesEqual, - 'is-reset': isReset, - } - ) } + <Composite.Item key={ id } + className="edit-site-global-styles-screen-revisions__revision-item" aria-current={ isSelected } - > - <Button - __next40pxDefaultSize - className="edit-site-global-styles-screen-revisions__revision-button" - accessibleWhenDisabled - disabled={ isSelected } - onClick={ () => { + role="option" + onKeyDown={ ( event ) => { + const { keyCode } = event; + if ( keyCode === ENTER || keyCode === SPACE ) { onChange( revision ); - } } - aria-label={ revisionLabel } - > + } + } } + onClick={ ( event ) => { + event.preventDefault(); + onChange( revision ); + } } + aria-selected={ isSelected } + aria-label={ revisionLabel } + render={ <div /> } + > + <span className="edit-site-global-styles-screen-revisions__revision-item-wrapper"> { isReset ? ( <span className="edit-site-global-styles-screen-revisions__description"> { __( 'Default styles' ) } @@ -211,7 +205,7 @@ function RevisionsButtons( { ) } </span> ) } - </Button> + </span> { isSelected && ( areStylesEqual ? ( <p className="edit-site-global-styles-screen-revisions__applied-text"> @@ -225,16 +219,19 @@ function RevisionsButtons( { variant="primary" className="edit-site-global-styles-screen-revisions__apply-button" onClick={ onApplyRevision } + aria-label={ __( + 'Apply the selected revision to your site.' + ) } > { isReset ? __( 'Reset to defaults' ) : __( 'Apply' ) } </Button> ) ) } - </li> + </Composite.Item> ); } ) } - </ol> + </Composite> ); } diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/style.scss b/packages/edit-site/src/components/global-styles/screen-revisions/style.scss index 5d0e7cb185137a..1773d1a179b3dd 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/style.scss +++ b/packages/edit-site/src/components/global-styles/screen-revisions/style.scss @@ -14,6 +14,11 @@ display: flex; flex-direction: column; + &[role="option"]:active, + &[role="option"]:focus { + @include button-style__focus(); + } + &:hover { background: rgba(var(--wp-admin-theme-color--rgb), 0.04); .edit-site-global-styles-screen-revisions__date { @@ -42,7 +47,7 @@ border: 4px solid transparent; } - &.is-selected { + &[aria-selected="true"] { border-radius: $radius-small; // Only visible in Windows High Contrast mode. @@ -52,10 +57,6 @@ color: var(--wp-admin-theme-color); background: rgba(var(--wp-admin-theme-color--rgb), 0.04); - .edit-site-global-styles-screen-revisions__revision-button { - opacity: 1; - } - .edit-site-global-styles-screen-revisions__date { color: var(--wp-admin-theme-color); } @@ -86,23 +87,16 @@ &:last-child::after { height: $grid-unit-20 + 2; } - - // Nested to override specificity of .components-button. - .edit-site-global-styles-screen-revisions__revision-button { - width: 100%; - height: auto; - display: block; - padding: $grid-unit-15 $grid-unit-15 $grid-unit-05 $grid-unit-50; - z-index: 1; - position: relative; - outline-offset: -2px; - } +} +.edit-site-global-styles-screen-revisions__revision-item-wrapper { + display: block; + padding: $grid-unit-15 $grid-unit-15 $grid-unit-05 $grid-unit-50; } .edit-site-global-styles-screen-revisions__apply-button.is-primary, .edit-site-global-styles-screen-revisions__applied-text { align-self: flex-start; - // Left margin = left padding of .edit-site-global-styles-screen-revisions__revision-button. + // Left margin = left padding of .edit-site-global-styles-screen-revisions__revision-item-wrapper. margin: $grid-unit-05 $grid-unit-15 $grid-unit-15 $grid-unit-50; } diff --git a/test/e2e/specs/site-editor/block-style-variations.spec.js b/test/e2e/specs/site-editor/block-style-variations.spec.js index 3c642ea9d1299e..03fc5398f4a0a5 100644 --- a/test/e2e/specs/site-editor/block-style-variations.spec.js +++ b/test/e2e/specs/site-editor/block-style-variations.spec.js @@ -245,7 +245,7 @@ test.describe( 'Block Style Variations', () => { // Click on previous revision. await page - .getByRole( 'button', { + .getByRole( 'option', { name: /^Changes saved by /, } ) .nth( 1 ) diff --git a/test/e2e/specs/site-editor/user-global-styles-revisions.spec.js b/test/e2e/specs/site-editor/user-global-styles-revisions.spec.js index e0b00fe1e59460..91142d5395640c 100644 --- a/test/e2e/specs/site-editor/user-global-styles-revisions.spec.js +++ b/test/e2e/specs/site-editor/user-global-styles-revisions.spec.js @@ -50,7 +50,7 @@ test.describe( 'Style Revisions', () => { // Now there should be enough revisions to show the revisions UI. await page.getByRole( 'button', { name: 'Revisions' } ).click(); - const revisionButtons = page.getByRole( 'button', { + const revisionButtons = page.getByRole( 'option', { name: /^Changes saved by /, } ); @@ -83,14 +83,14 @@ test.describe( 'Style Revisions', () => { await page.getByRole( 'button', { name: 'Revisions' } ).click(); - const unSavedButton = page.getByRole( 'button', { + const unSavedButton = page.getByRole( 'option', { name: /^Unsaved changes/, } ); await expect( unSavedButton ).toBeVisible(); await page - .getByRole( 'button', { name: /^Changes saved by / } ) + .getByRole( 'option', { name: /^Changes saved by / } ) .last() .click(); @@ -118,14 +118,16 @@ test.describe( 'Style Revisions', () => { await editor.canvas.locator( 'body' ).click(); await userGlobalStylesRevisions.openStylesPanel(); await page.getByRole( 'button', { name: 'Revisions' } ).click(); - const lastRevisionButton = page + const lastRevisionItem = page .getByLabel( 'Global styles revisions list' ) - .getByRole( 'button' ) + .getByRole( 'option' ) .last(); - await expect( lastRevisionButton ).toContainText( 'Default styles' ); - await lastRevisionButton.click(); + await expect( lastRevisionItem ).toContainText( 'Default styles' ); + await lastRevisionItem.click(); await expect( - page.getByRole( 'button', { name: 'Reset to defaults' } ) + page.getByRole( 'button', { + name: 'Apply the selected revision to your site.', + } ) ).toBeVisible(); } ); From 4651b8235d5220f02b1133266995f32c34fc9122 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 7 Nov 2024 11:06:11 +1000 Subject: [PATCH 1502/1908] Block Gap: Fix block spacing control for axial gap supported blocks (#66783) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: juanfra <juanfra@git.wordpress.org> Co-authored-by: ltrihan <ltrihan@git.wordpress.org> --- .../global-styles/dimensions-panel.js | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/dimensions-panel.js b/packages/block-editor/src/components/global-styles/dimensions-panel.js index 4c52de6a3d7d11..c19788ebfcb580 100644 --- a/packages/block-editor/src/components/global-styles/dimensions-panel.js +++ b/packages/block-editor/src/components/global-styles/dimensions-panel.js @@ -147,24 +147,30 @@ function splitStyleValue( value ) { return value; } -function splitGapValue( value ) { - // Check for shorthand value (a string value). - if ( value && typeof value === 'string' ) { - // If the value is a string, treat it as a single side (top) for the spacing controls. - return { - top: value, - }; +function splitGapValue( value, isAxialGap ) { + if ( ! value ) { + return value; } - if ( value ) { - return { - ...value, - right: value?.left, - bottom: value?.top, - }; + // Check for shorthand value (a string value). + if ( typeof value === 'string' ) { + /* + * Map the string value to appropriate sides for the spacing control depending + * on whether the current block has axial gap support or not. + * + * Note: The axial value pairs must match for the spacing control to display + * the appropriate horizontal/vertical sliders. + */ + return isAxialGap + ? { top: value, right: value, bottom: value, left: value } + : { top: value }; } - return value; + return { + ...value, + right: value?.left, + bottom: value?.top, + }; } function DimensionsToolsPanel( { @@ -325,13 +331,13 @@ export default function DimensionsPanel( { // Block Gap const showGapControl = useHasGap( settings ); - const gapValue = decodeValue( inheritedValue?.spacing?.blockGap ); - const gapValues = splitGapValue( gapValue ); const gapSides = Array.isArray( settings?.spacing?.blockGap ) ? settings?.spacing?.blockGap : settings?.spacing?.blockGap?.sides; const isAxialGap = gapSides && gapSides.some( ( side ) => AXIAL_SIDES.includes( side ) ); + const gapValue = decodeValue( inheritedValue?.spacing?.blockGap ); + const gapValues = splitGapValue( gapValue, isAxialGap ); const setGapValue = ( newGapValue ) => { onChange( setImmutably( value, [ 'spacing', 'blockGap' ], newGapValue ) From a0b0e5f00e785c5d8a7f6c4e0ddd0edf268f7dbf Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Thu, 7 Nov 2024 09:59:46 +0530 Subject: [PATCH 1503/1908] Group the storybook components in feedback category (#66660) Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/src/notice/stories/index.story.tsx | 3 ++- packages/components/src/progress-bar/stories/index.story.tsx | 3 ++- packages/components/src/snackbar/stories/index.story.tsx | 3 ++- packages/components/src/snackbar/stories/list.story.tsx | 3 ++- packages/components/src/spinner/stories/index.story.tsx | 3 ++- packages/components/src/tip/stories/index.story.tsx | 3 ++- storybook/preview.js | 1 + 7 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/components/src/notice/stories/index.story.tsx b/packages/components/src/notice/stories/index.story.tsx index 95bf82016c2b04..042b4ac3ec79b3 100644 --- a/packages/components/src/notice/stories/index.story.tsx +++ b/packages/components/src/notice/stories/index.story.tsx @@ -17,7 +17,8 @@ import NoticeList from '../list'; import type { NoticeListProps } from '../types'; const meta: Meta< typeof Notice > = { - title: 'Components/Notice', + title: 'Components/Feedback/Notice', + id: 'components-notice', component: Notice, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { NoticeList }, diff --git a/packages/components/src/progress-bar/stories/index.story.tsx b/packages/components/src/progress-bar/stories/index.story.tsx index 4396c4cc48eebb..2f6bb4dbe000fd 100644 --- a/packages/components/src/progress-bar/stories/index.story.tsx +++ b/packages/components/src/progress-bar/stories/index.story.tsx @@ -10,7 +10,8 @@ import { ProgressBar } from '..'; const meta: Meta< typeof ProgressBar > = { component: ProgressBar, - title: 'Components/ProgressBar', + title: 'Components/Feedback/ProgressBar', + id: 'components-progressbar', argTypes: { value: { control: { type: 'number', min: 0, max: 100, step: 1 } }, }, diff --git a/packages/components/src/snackbar/stories/index.story.tsx b/packages/components/src/snackbar/stories/index.story.tsx index c1f525b60b3919..9bd1dae42b71be 100644 --- a/packages/components/src/snackbar/stories/index.story.tsx +++ b/packages/components/src/snackbar/stories/index.story.tsx @@ -15,7 +15,8 @@ import Icon from '../../icon'; import Snackbar from '..'; const meta: Meta< typeof Snackbar > = { - title: 'Components/Snackbar', + title: 'Components/Feedback/Snackbar', + id: 'components-snackbar', component: Snackbar, argTypes: { as: { control: { type: null } }, diff --git a/packages/components/src/snackbar/stories/list.story.tsx b/packages/components/src/snackbar/stories/list.story.tsx index 8548ffba1e1f09..1f93f374ec1745 100644 --- a/packages/components/src/snackbar/stories/list.story.tsx +++ b/packages/components/src/snackbar/stories/list.story.tsx @@ -14,7 +14,8 @@ import { useState } from '@wordpress/element'; import SnackbarList from '../list'; const meta: Meta< typeof SnackbarList > = { - title: 'Components/SnackbarList', + title: 'Components/Feedback/SnackbarList', + id: 'components-snackbarlist', component: SnackbarList, argTypes: { as: { control: { type: null } }, diff --git a/packages/components/src/spinner/stories/index.story.tsx b/packages/components/src/spinner/stories/index.story.tsx index 1062c6406bfb4e..1dc5879ac41444 100644 --- a/packages/components/src/spinner/stories/index.story.tsx +++ b/packages/components/src/spinner/stories/index.story.tsx @@ -10,7 +10,8 @@ import Spinner from '../'; import { space } from '../../utils/space'; const meta: Meta< typeof Spinner > = { - title: 'Components/Spinner', + title: 'Components/Feedback/Spinner', + id: 'components-spinner', component: Spinner, parameters: { controls: { diff --git a/packages/components/src/tip/stories/index.story.tsx b/packages/components/src/tip/stories/index.story.tsx index 3999c6b9be45f4..3026f2a58fae73 100644 --- a/packages/components/src/tip/stories/index.story.tsx +++ b/packages/components/src/tip/stories/index.story.tsx @@ -10,7 +10,8 @@ import Tip from '..'; const meta: Meta< typeof Tip > = { component: Tip, - title: 'Components/Tip', + title: 'Components/Feedback/Tip', + id: 'components-tip', argTypes: { children: { control: { type: 'text' } }, }, diff --git a/storybook/preview.js b/storybook/preview.js index 21f2eab912059a..7672e7ebdcdff2 100644 --- a/storybook/preview.js +++ b/storybook/preview.js @@ -132,6 +132,7 @@ export const parameters = { 'Contributing Guidelines', 'Actions', 'Containers', + 'Feedback', 'Utilities', ], 'Components (Experimental)', From 88cf9bd905f00d8967bfe185176afc2892ebae70 Mon Sep 17 00:00:00 2001 From: Kai Hao <kevin830726@gmail.com> Date: Thu, 7 Nov 2024 12:50:42 +0800 Subject: [PATCH 1504/1908] Revert "Set image width to `fit-content` to solve aspect ratio problems in Firefox. (#66217)" (#66804) Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: mukeshpanchal27 <mukesh27@git.wordpress.org> Co-authored-by: juanfra <juanfra@git.wordpress.org> This reverts commit 0e65adcbe187797a536aa99f56b063a61cafdc3d. --- packages/block-library/src/image/style.scss | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/block-library/src/image/style.scss b/packages/block-library/src/image/style.scss index 79689e82006cdc..1bb19bf29da691 100644 --- a/packages/block-library/src/image/style.scss +++ b/packages/block-library/src/image/style.scss @@ -10,10 +10,6 @@ vertical-align: bottom; box-sizing: border-box; - &:not([src$=".svg"]) { - width: fit-content; - } - @media (prefers-reduced-motion: no-preference) { &.hide { visibility: hidden; From 20b773b7a47bc80aa7516a6955f23eb24782922f Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:58:27 +0530 Subject: [PATCH 1505/1908] Feat: Storybook: Improve component organisation - Navigation Category - Issue #66275 (#66658) * Group the storybook components in Navigaiton category * Fix tabs to add inside containers and add experimental id for component * Fix the syntax style Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/src/external-link/stories/index.story.tsx | 3 ++- packages/components/src/navigator/stories/index.story.tsx | 3 ++- packages/components/src/tree-grid/stories/index.story.tsx | 3 ++- storybook/preview.js | 2 ++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/components/src/external-link/stories/index.story.tsx b/packages/components/src/external-link/stories/index.story.tsx index 91131e0c88aab0..eb70999413187f 100644 --- a/packages/components/src/external-link/stories/index.story.tsx +++ b/packages/components/src/external-link/stories/index.story.tsx @@ -10,7 +10,8 @@ import ExternalLink from '..'; const meta: Meta< typeof ExternalLink > = { component: ExternalLink, - title: 'Components/ExternalLink', + title: 'Components/Navigation/ExternalLink', + id: 'components-externallink', argTypes: { children: { control: { type: 'text' } }, }, diff --git a/packages/components/src/navigator/stories/index.story.tsx b/packages/components/src/navigator/stories/index.story.tsx index e9e342bb0d2eee..bd2cdc17a1263c 100644 --- a/packages/components/src/navigator/stories/index.story.tsx +++ b/packages/components/src/navigator/stories/index.story.tsx @@ -21,7 +21,8 @@ const meta: Meta< typeof Navigator > = { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 BackButton: Navigator.BackButton, }, - title: 'Components/Navigator', + title: 'Components/Navigation/Navigator', + id: 'components-navigator', argTypes: { as: { control: { type: null } }, children: { control: { type: null } }, diff --git a/packages/components/src/tree-grid/stories/index.story.tsx b/packages/components/src/tree-grid/stories/index.story.tsx index 44af154c685b2f..5a1ed95e1fd627 100644 --- a/packages/components/src/tree-grid/stories/index.story.tsx +++ b/packages/components/src/tree-grid/stories/index.story.tsx @@ -16,7 +16,8 @@ import { Button } from '../../button'; import InputControl from '../../input-control'; const meta: Meta< typeof TreeGrid > = { - title: 'Components (Experimental)/TreeGrid', + title: 'Components (Experimental)/Navigation/TreeGrid', + id: 'components-experimental-treegrid', component: TreeGrid, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { TreeGridRow, TreeGridCell }, diff --git a/storybook/preview.js b/storybook/preview.js index 7672e7ebdcdff2..9e9dd587b39c4c 100644 --- a/storybook/preview.js +++ b/storybook/preview.js @@ -133,9 +133,11 @@ export const parameters = { 'Actions', 'Containers', 'Feedback', + 'Navigation', 'Utilities', ], 'Components (Experimental)', + [ 'Navigation' ], 'Icons', ], }, From b9b1a52d967db7a014100dd7d49a403ac26b7238 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Thu, 7 Nov 2024 09:35:45 +0200 Subject: [PATCH 1506/1908] =?UTF-8?q?Relocate=20=E2=80=9CView=E2=80=9D=20e?= =?UTF-8?q?xternal=20link=20to=20end=20of=20editor=20header=20controls=20(?= =?UTF-8?q?#66785)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/editor/src/components/header/index.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index 07a5e9ddee5911..5a9cc2f94a5951 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -156,19 +156,21 @@ function Header( { <PostSavedState forceIsDirty={ forceIsDirty } /> ) } - { canBeZoomedOut && isEditorIframed && isWideViewport && ( - <ZoomOutToggle disabled={ forceDisableBlockTools } /> - ) } + <PostViewLink /> <PreviewDropdown forceIsAutosaveable={ forceIsDirty } disabled={ disablePreviewOption } /> + <PostPreviewButton className="editor-header__post-preview-button" forceIsAutosaveable={ forceIsDirty } /> - <PostViewLink /> + + { canBeZoomedOut && isEditorIframed && isWideViewport && ( + <ZoomOutToggle disabled={ forceDisableBlockTools } /> + ) } { ( isWideViewport || ! showIconLabels ) && ( <PinnedItems.Slot scope="core" /> From 8be8e4675637726b0ff3194ccc547307c4a489bc Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 7 Nov 2024 17:26:40 +0900 Subject: [PATCH 1507/1908] ESLint: Fix React Compiler violations in various commands (#66787) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../components/use-block-commands/index.js | 479 +++++++++-------- .../src/admin-navigation-commands.js | 129 ++--- .../src/site-editor-navigation-commands.js | 256 ++++----- .../src/hooks/commands/use-common-commands.js | 499 +++++++++--------- .../hooks/commands/use-edit-mode-commands.js | 259 ++++----- .../editor/src/components/commands/index.js | 472 +++++++++-------- 6 files changed, 1069 insertions(+), 1025 deletions(-) diff --git a/packages/block-editor/src/components/use-block-commands/index.js b/packages/block-editor/src/components/use-block-commands/index.js index e739729c8f9e84..ff919710a2284e 100644 --- a/packages/block-editor/src/components/use-block-commands/index.js +++ b/packages/block-editor/src/components/use-block-commands/index.js @@ -24,275 +24,286 @@ import { import BlockIcon from '../block-icon'; import { store as blockEditorStore } from '../../store'; -export const useTransformCommands = () => { - const { replaceBlocks, multiSelect } = useDispatch( blockEditorStore ); - const { - blocks, - clientIds, - canRemove, - possibleBlockTransformations, - invalidSelection, - } = useSelect( ( select ) => { +const getTransformCommands = () => + function useTransformCommands() { + const { replaceBlocks, multiSelect } = useDispatch( blockEditorStore ); const { - getBlockRootClientId, - getBlockTransformItems, - getSelectedBlockClientIds, - getBlocksByClientId, - canRemoveBlocks, - } = select( blockEditorStore ); + blocks, + clientIds, + canRemove, + possibleBlockTransformations, + invalidSelection, + } = useSelect( ( select ) => { + const { + getBlockRootClientId, + getBlockTransformItems, + getSelectedBlockClientIds, + getBlocksByClientId, + canRemoveBlocks, + } = select( blockEditorStore ); + + const selectedBlockClientIds = getSelectedBlockClientIds(); + const selectedBlocks = getBlocksByClientId( + selectedBlockClientIds + ); + + // selectedBlocks can have `null`s when something tries to call `selectBlock` with an inexistent clientId. + // These nulls will cause fatal errors down the line. + // In order to prevent discrepancies between selectedBlockClientIds and selectedBlocks, we effectively treat the entire selection as invalid. + // @see https://github.com/WordPress/gutenberg/pull/59410#issuecomment-2006304536 + if ( selectedBlocks.filter( ( block ) => ! block ).length > 0 ) { + return { + invalidSelection: true, + }; + } - const selectedBlockClientIds = getSelectedBlockClientIds(); - const selectedBlocks = getBlocksByClientId( selectedBlockClientIds ); + const rootClientId = getBlockRootClientId( + selectedBlockClientIds[ 0 ] + ); + return { + blocks: selectedBlocks, + clientIds: selectedBlockClientIds, + possibleBlockTransformations: getBlockTransformItems( + selectedBlocks, + rootClientId + ), + canRemove: canRemoveBlocks( selectedBlockClientIds ), + invalidSelection: false, + }; + }, [] ); - // selectedBlocks can have `null`s when something tries to call `selectBlock` with an inexistent clientId. - // These nulls will cause fatal errors down the line. - // In order to prevent discrepancies between selectedBlockClientIds and selectedBlocks, we effectively treat the entire selection as invalid. - // @see https://github.com/WordPress/gutenberg/pull/59410#issuecomment-2006304536 - if ( selectedBlocks.filter( ( block ) => ! block ).length > 0 ) { + if ( invalidSelection ) { return { - invalidSelection: true, + isLoading: false, + commands: [], }; } + const isTemplate = blocks.length === 1 && isTemplatePart( blocks[ 0 ] ); + + function selectForMultipleBlocks( insertedBlocks ) { + if ( insertedBlocks.length > 1 ) { + multiSelect( + insertedBlocks[ 0 ].clientId, + insertedBlocks[ insertedBlocks.length - 1 ].clientId + ); + } + } - const rootClientId = getBlockRootClientId( - selectedBlockClientIds[ 0 ] - ); - return { - blocks: selectedBlocks, - clientIds: selectedBlockClientIds, - possibleBlockTransformations: getBlockTransformItems( - selectedBlocks, - rootClientId - ), - canRemove: canRemoveBlocks( selectedBlockClientIds ), - invalidSelection: false, - }; - }, [] ); + // Simple block tranformation based on the `Block Transforms` API. + function onBlockTransform( name ) { + const newBlocks = switchToBlockType( blocks, name ); + replaceBlocks( clientIds, newBlocks ); + selectForMultipleBlocks( newBlocks ); + } - if ( invalidSelection ) { - return { - isLoading: false, - commands: [], - }; - } - const isTemplate = blocks.length === 1 && isTemplatePart( blocks[ 0 ] ); - - function selectForMultipleBlocks( insertedBlocks ) { - if ( insertedBlocks.length > 1 ) { - multiSelect( - insertedBlocks[ 0 ].clientId, - insertedBlocks[ insertedBlocks.length - 1 ].clientId - ); + /** + * The `isTemplate` check is a stopgap solution here. + * Ideally, the Transforms API should handle this + * by allowing to exclude blocks from wildcard transformations. + */ + const hasPossibleBlockTransformations = + !! possibleBlockTransformations.length && canRemove && ! isTemplate; + + if ( + ! clientIds || + clientIds.length < 1 || + ! hasPossibleBlockTransformations + ) { + return { isLoading: false, commands: [] }; } - } - - // Simple block tranformation based on the `Block Transforms` API. - function onBlockTransform( name ) { - const newBlocks = switchToBlockType( blocks, name ); - replaceBlocks( clientIds, newBlocks ); - selectForMultipleBlocks( newBlocks ); - } - - /** - * The `isTemplate` check is a stopgap solution here. - * Ideally, the Transforms API should handle this - * by allowing to exclude blocks from wildcard transformations. - */ - const hasPossibleBlockTransformations = - !! possibleBlockTransformations.length && canRemove && ! isTemplate; - - if ( - ! clientIds || - clientIds.length < 1 || - ! hasPossibleBlockTransformations - ) { - return { isLoading: false, commands: [] }; - } - - const commands = possibleBlockTransformations.map( ( transformation ) => { - const { name, title, icon } = transformation; - return { - name: 'core/block-editor/transform-to-' + name.replace( '/', '-' ), - /* translators: %s: Block or block variation name. */ - label: sprintf( __( 'Transform to %s' ), title ), - icon: <BlockIcon icon={ icon } />, - callback: ( { close } ) => { - onBlockTransform( name ); - close(); + + const commands = possibleBlockTransformations.map( + ( transformation ) => { + const { name, title, icon } = transformation; + return { + name: + 'core/block-editor/transform-to-' + + name.replace( '/', '-' ), + /* translators: %s: Block or block variation name. */ + label: sprintf( __( 'Transform to %s' ), title ), + icon: <BlockIcon icon={ icon } />, + callback: ( { close } ) => { + onBlockTransform( name ); + close(); + }, + }; + } + ); + + return { isLoading: false, commands }; + }; + +const getQuickActionsCommands = () => + function useQuickActionsCommands() { + const { clientIds, isUngroupable, isGroupable } = useSelect( + ( select ) => { + const { + getSelectedBlockClientIds, + isUngroupable: _isUngroupable, + isGroupable: _isGroupable, + } = select( blockEditorStore ); + const selectedBlockClientIds = getSelectedBlockClientIds(); + + return { + clientIds: selectedBlockClientIds, + isUngroupable: _isUngroupable(), + isGroupable: _isGroupable(), + }; }, - }; - } ); + [] + ); + const { + canInsertBlockType, + getBlockRootClientId, + getBlocksByClientId, + canRemoveBlocks, + } = useSelect( blockEditorStore ); + const { getDefaultBlockName, getGroupingBlockName } = + useSelect( blocksStore ); - return { isLoading: false, commands }; -}; + const blocks = getBlocksByClientId( clientIds ); -const useQuickActionsCommands = () => { - const { clientIds, isUngroupable, isGroupable } = useSelect( ( select ) => { const { - getSelectedBlockClientIds, - isUngroupable: _isUngroupable, - isGroupable: _isGroupable, - } = select( blockEditorStore ); - const selectedBlockClientIds = getSelectedBlockClientIds(); + removeBlocks, + replaceBlocks, + duplicateBlocks, + insertAfterBlock, + insertBeforeBlock, + } = useDispatch( blockEditorStore ); + + const onGroup = () => { + if ( ! blocks.length ) { + return; + } - return { - clientIds: selectedBlockClientIds, - isUngroupable: _isUngroupable(), - isGroupable: _isGroupable(), + const groupingBlockName = getGroupingBlockName(); + + // Activate the `transform` on `core/group` which does the conversion. + const newBlocks = switchToBlockType( blocks, groupingBlockName ); + + if ( ! newBlocks ) { + return; + } + replaceBlocks( clientIds, newBlocks ); }; - }, [] ); - const { - canInsertBlockType, - getBlockRootClientId, - getBlocksByClientId, - canRemoveBlocks, - } = useSelect( blockEditorStore ); - const { getDefaultBlockName, getGroupingBlockName } = - useSelect( blocksStore ); - - const blocks = getBlocksByClientId( clientIds ); - - const { - removeBlocks, - replaceBlocks, - duplicateBlocks, - insertAfterBlock, - insertBeforeBlock, - } = useDispatch( blockEditorStore ); - - const onGroup = () => { - if ( ! blocks.length ) { - return; - } + const onUngroup = () => { + if ( ! blocks.length ) { + return; + } - const groupingBlockName = getGroupingBlockName(); + const innerBlocks = blocks[ 0 ].innerBlocks; - // Activate the `transform` on `core/group` which does the conversion. - const newBlocks = switchToBlockType( blocks, groupingBlockName ); + if ( ! innerBlocks.length ) { + return; + } - if ( ! newBlocks ) { - return; - } - replaceBlocks( clientIds, newBlocks ); - }; - const onUngroup = () => { - if ( ! blocks.length ) { - return; + replaceBlocks( clientIds, innerBlocks ); + }; + + if ( ! clientIds || clientIds.length < 1 ) { + return { isLoading: false, commands: [] }; } - const innerBlocks = blocks[ 0 ].innerBlocks; + const rootClientId = getBlockRootClientId( clientIds[ 0 ] ); + const canInsertDefaultBlock = canInsertBlockType( + getDefaultBlockName(), + rootClientId + ); + const canDuplicate = blocks.every( ( block ) => { + return ( + !! block && + hasBlockSupport( block.name, 'multiple', true ) && + canInsertBlockType( block.name, rootClientId ) + ); + } ); + const canRemove = canRemoveBlocks( clientIds ); - if ( ! innerBlocks.length ) { - return; + const commands = []; + + if ( canDuplicate ) { + commands.push( { + name: 'duplicate', + label: __( 'Duplicate' ), + callback: () => duplicateBlocks( clientIds, true ), + icon: copy, + } ); } - replaceBlocks( clientIds, innerBlocks ); - }; + if ( canInsertDefaultBlock ) { + commands.push( + { + name: 'add-before', + label: __( 'Add before' ), + callback: () => { + const clientId = Array.isArray( clientIds ) + ? clientIds[ 0 ] + : clientId; + insertBeforeBlock( clientId ); + }, + icon: add, + }, + { + name: 'add-after', + label: __( 'Add after' ), + callback: () => { + const clientId = Array.isArray( clientIds ) + ? clientIds[ clientIds.length - 1 ] + : clientId; + insertAfterBlock( clientId ); + }, + icon: add, + } + ); + } - if ( ! clientIds || clientIds.length < 1 ) { - return { isLoading: false, commands: [] }; - } - - const rootClientId = getBlockRootClientId( clientIds[ 0 ] ); - const canInsertDefaultBlock = canInsertBlockType( - getDefaultBlockName(), - rootClientId - ); - const canDuplicate = blocks.every( ( block ) => { - return ( - !! block && - hasBlockSupport( block.name, 'multiple', true ) && - canInsertBlockType( block.name, rootClientId ) - ); - } ); - const canRemove = canRemoveBlocks( clientIds ); + if ( isGroupable ) { + commands.push( { + name: 'Group', + label: __( 'Group' ), + callback: onGroup, + icon: group, + } ); + } - const commands = []; + if ( isUngroupable ) { + commands.push( { + name: 'ungroup', + label: __( 'Ungroup' ), + callback: onUngroup, + icon: ungroup, + } ); + } - if ( canDuplicate ) { - commands.push( { - name: 'duplicate', - label: __( 'Duplicate' ), - callback: () => duplicateBlocks( clientIds, true ), - icon: copy, - } ); - } - - if ( canInsertDefaultBlock ) { - commands.push( - { - name: 'add-before', - label: __( 'Add before' ), - callback: () => { - const clientId = Array.isArray( clientIds ) - ? clientIds[ 0 ] - : clientId; - insertBeforeBlock( clientId ); - }, - icon: add, - }, - { - name: 'add-after', - label: __( 'Add after' ), - callback: () => { - const clientId = Array.isArray( clientIds ) - ? clientIds[ clientIds.length - 1 ] - : clientId; - insertAfterBlock( clientId ); + if ( canRemove ) { + commands.push( { + name: 'remove', + label: __( 'Delete' ), + callback: () => removeBlocks( clientIds, true ), + icon: remove, + } ); + } + + return { + isLoading: false, + commands: commands.map( ( command ) => ( { + ...command, + name: 'core/block-editor/action-' + command.name, + callback: ( { close } ) => { + command.callback(); + close(); }, - icon: add, - } - ); - } - - if ( isGroupable ) { - commands.push( { - name: 'Group', - label: __( 'Group' ), - callback: onGroup, - icon: group, - } ); - } - - if ( isUngroupable ) { - commands.push( { - name: 'ungroup', - label: __( 'Ungroup' ), - callback: onUngroup, - icon: ungroup, - } ); - } - - if ( canRemove ) { - commands.push( { - name: 'remove', - label: __( 'Delete' ), - callback: () => removeBlocks( clientIds, true ), - icon: remove, - } ); - } - - return { - isLoading: false, - commands: commands.map( ( command ) => ( { - ...command, - name: 'core/block-editor/action-' + command.name, - callback: ( { close } ) => { - command.callback(); - close(); - }, - } ) ), + } ) ), + }; }; -}; export const useBlockCommands = () => { useCommandLoader( { name: 'core/block-editor/blockTransforms', - hook: useTransformCommands, + hook: getTransformCommands(), } ); useCommandLoader( { name: 'core/block-editor/blockQuickActions', - hook: useQuickActionsCommands, + hook: getQuickActionsCommands(), context: 'block-selection-edit', } ); }; diff --git a/packages/core-commands/src/admin-navigation-commands.js b/packages/core-commands/src/admin-navigation-commands.js index c0d8bb084b46ad..9f0883faa3c17a 100644 --- a/packages/core-commands/src/admin-navigation-commands.js +++ b/packages/core-commands/src/admin-navigation-commands.js @@ -18,75 +18,78 @@ import { unlock } from './lock-unlock'; const { useHistory } = unlock( routerPrivateApis ); -function useAddNewPageCommand() { - const isSiteEditor = getPath( window.location.href )?.includes( - 'site-editor.php' - ); - const history = useHistory(); - const isBlockBasedTheme = useSelect( ( select ) => { - return select( coreStore ).getCurrentTheme()?.is_block_theme; - }, [] ); - const { saveEntityRecord } = useDispatch( coreStore ); - const { createErrorNotice } = useDispatch( noticesStore ); +const getAddNewPageCommand = () => + function useAddNewPageCommand() { + const isSiteEditor = getPath( window.location.href )?.includes( + 'site-editor.php' + ); + const history = useHistory(); + const isBlockBasedTheme = useSelect( ( select ) => { + return select( coreStore ).getCurrentTheme()?.is_block_theme; + }, [] ); + const { saveEntityRecord } = useDispatch( coreStore ); + const { createErrorNotice } = useDispatch( noticesStore ); - const createPageEntity = useCallback( - async ( { close } ) => { - try { - const page = await saveEntityRecord( - 'postType', - 'page', - { - status: 'draft', - }, - { - throwOnError: true, + const createPageEntity = useCallback( + async ( { close } ) => { + try { + const page = await saveEntityRecord( + 'postType', + 'page', + { + status: 'draft', + }, + { + throwOnError: true, + } + ); + if ( page?.id ) { + history.push( { + postId: page.id, + postType: 'page', + canvas: 'edit', + } ); } - ); - if ( page?.id ) { - history.push( { - postId: page.id, - postType: 'page', - canvas: 'edit', + } catch ( error ) { + const errorMessage = + error.message && error.code !== 'unknown_error' + ? error.message + : __( + 'An error occurred while creating the item.' + ); + + createErrorNotice( errorMessage, { + type: 'snackbar', } ); + } finally { + close(); } - } catch ( error ) { - const errorMessage = - error.message && error.code !== 'unknown_error' - ? error.message - : __( 'An error occurred while creating the item.' ); - - createErrorNotice( errorMessage, { - type: 'snackbar', - } ); - } finally { - close(); - } - }, - [ createErrorNotice, history, saveEntityRecord ] - ); - - const commands = useMemo( () => { - const addNewPage = - isSiteEditor && isBlockBasedTheme - ? createPageEntity - : () => - ( document.location.href = - 'post-new.php?post_type=page' ); - return [ - { - name: 'core/add-new-page', - label: __( 'Add new page' ), - icon: plus, - callback: addNewPage, }, - ]; - }, [ createPageEntity, isSiteEditor, isBlockBasedTheme ] ); + [ createErrorNotice, history, saveEntityRecord ] + ); + + const commands = useMemo( () => { + const addNewPage = + isSiteEditor && isBlockBasedTheme + ? createPageEntity + : () => + ( document.location.href = + 'post-new.php?post_type=page' ); + return [ + { + name: 'core/add-new-page', + label: __( 'Add new page' ), + icon: plus, + callback: addNewPage, + }, + ]; + }, [ createPageEntity, isSiteEditor, isBlockBasedTheme ] ); - return { - isLoading: false, - commands, + return { + isLoading: false, + commands, + }; }; -} export function useAdminNavigationCommands() { useCommand( { @@ -100,6 +103,6 @@ export function useAdminNavigationCommands() { useCommandLoader( { name: 'core/add-new-page', - hook: useAddNewPageCommand, + hook: getAddNewPageCommand(), } ); } diff --git a/packages/core-commands/src/site-editor-navigation-commands.js b/packages/core-commands/src/site-editor-navigation-commands.js index 4679d4d1523c89..2785d809d41e03 100644 --- a/packages/core-commands/src/site-editor-navigation-commands.js +++ b/packages/core-commands/src/site-editor-navigation-commands.js @@ -275,159 +275,169 @@ const getNavigationCommandLoaderPerTemplate = ( templateType ) => }; }; -const usePageNavigationCommandLoader = - getNavigationCommandLoaderPerPostType( 'page' ); -const usePostNavigationCommandLoader = - getNavigationCommandLoaderPerPostType( 'post' ); -const useTemplateNavigationCommandLoader = - getNavigationCommandLoaderPerTemplate( 'wp_template' ); -const useTemplatePartNavigationCommandLoader = - getNavigationCommandLoaderPerTemplate( 'wp_template_part' ); +const getSiteEditorBasicNavigationCommands = () => + function useSiteEditorBasicNavigationCommands() { + const history = useHistory(); + const isSiteEditor = getPath( window.location.href )?.includes( + 'site-editor.php' + ); + const { isBlockBasedTheme, canCreateTemplate } = useSelect( + ( select ) => { + return { + isBlockBasedTheme: + select( coreStore ).getCurrentTheme()?.is_block_theme, + canCreateTemplate: select( coreStore ).canUser( 'create', { + kind: 'postType', + name: 'wp_template', + } ), + }; + }, + [] + ); + const commands = useMemo( () => { + const result = []; -function useSiteEditorBasicNavigationCommands() { - const history = useHistory(); - const isSiteEditor = getPath( window.location.href )?.includes( - 'site-editor.php' - ); - const { isBlockBasedTheme, canCreateTemplate } = useSelect( ( select ) => { - return { - isBlockBasedTheme: - select( coreStore ).getCurrentTheme()?.is_block_theme, - canCreateTemplate: select( coreStore ).canUser( 'create', { - kind: 'postType', - name: 'wp_template', - } ), - }; - }, [] ); - const commands = useMemo( () => { - const result = []; + if ( canCreateTemplate && isBlockBasedTheme ) { + result.push( { + name: 'core/edit-site/open-navigation', + label: __( 'Navigation' ), + icon: navigation, + callback: ( { close } ) => { + const args = { + postType: 'wp_navigation', + }; + const targetUrl = addQueryArgs( + 'site-editor.php', + args + ); + if ( isSiteEditor ) { + history.push( args ); + } else { + document.location = targetUrl; + } + close(); + }, + } ); - if ( canCreateTemplate && isBlockBasedTheme ) { - result.push( { - name: 'core/edit-site/open-navigation', - label: __( 'Navigation' ), - icon: navigation, - callback: ( { close } ) => { - const args = { - postType: 'wp_navigation', - }; - const targetUrl = addQueryArgs( 'site-editor.php', args ); - if ( isSiteEditor ) { - history.push( args ); - } else { - document.location = targetUrl; - } - close(); - }, - } ); + result.push( { + name: 'core/edit-site/open-styles', + label: __( 'Styles' ), + icon: styles, + callback: ( { close } ) => { + const args = { + path: '/wp_global_styles', + }; + const targetUrl = addQueryArgs( + 'site-editor.php', + args + ); + if ( isSiteEditor ) { + history.push( args ); + } else { + document.location = targetUrl; + } + close(); + }, + } ); - result.push( { - name: 'core/edit-site/open-styles', - label: __( 'Styles' ), - icon: styles, - callback: ( { close } ) => { - const args = { - path: '/wp_global_styles', - }; - const targetUrl = addQueryArgs( 'site-editor.php', args ); - if ( isSiteEditor ) { - history.push( args ); - } else { - document.location = targetUrl; - } - close(); - }, - } ); + result.push( { + name: 'core/edit-site/open-pages', + label: __( 'Pages' ), + icon: page, + callback: ( { close } ) => { + const args = { + postType: 'page', + }; + const targetUrl = addQueryArgs( + 'site-editor.php', + args + ); + if ( isSiteEditor ) { + history.push( args ); + } else { + document.location = targetUrl; + } + close(); + }, + } ); - result.push( { - name: 'core/edit-site/open-pages', - label: __( 'Pages' ), - icon: page, - callback: ( { close } ) => { - const args = { - postType: 'page', - }; - const targetUrl = addQueryArgs( 'site-editor.php', args ); - if ( isSiteEditor ) { - history.push( args ); - } else { - document.location = targetUrl; - } - close(); - }, - } ); + result.push( { + name: 'core/edit-site/open-templates', + label: __( 'Templates' ), + icon: layout, + callback: ( { close } ) => { + const args = { + postType: 'wp_template', + }; + const targetUrl = addQueryArgs( + 'site-editor.php', + args + ); + if ( isSiteEditor ) { + history.push( args ); + } else { + document.location = targetUrl; + } + close(); + }, + } ); + } result.push( { - name: 'core/edit-site/open-templates', - label: __( 'Templates' ), - icon: layout, + name: 'core/edit-site/open-patterns', + label: __( 'Patterns' ), + icon: symbol, callback: ( { close } ) => { - const args = { - postType: 'wp_template', - }; - const targetUrl = addQueryArgs( 'site-editor.php', args ); - if ( isSiteEditor ) { - history.push( args ); + if ( canCreateTemplate ) { + const args = { + postType: 'wp_block', + }; + const targetUrl = addQueryArgs( + 'site-editor.php', + args + ); + if ( isSiteEditor ) { + history.push( args ); + } else { + document.location = targetUrl; + } + close(); } else { - document.location = targetUrl; + // If a user cannot access the site editor + document.location.href = 'edit.php?post_type=wp_block'; } - close(); }, } ); - } - - result.push( { - name: 'core/edit-site/open-patterns', - label: __( 'Patterns' ), - icon: symbol, - callback: ( { close } ) => { - if ( canCreateTemplate ) { - const args = { - postType: 'wp_block', - }; - const targetUrl = addQueryArgs( 'site-editor.php', args ); - if ( isSiteEditor ) { - history.push( args ); - } else { - document.location = targetUrl; - } - close(); - } else { - // If a user cannot access the site editor - document.location.href = 'edit.php?post_type=wp_block'; - } - }, - } ); - return result; - }, [ history, isSiteEditor, canCreateTemplate, isBlockBasedTheme ] ); + return result; + }, [ history, isSiteEditor, canCreateTemplate, isBlockBasedTheme ] ); - return { - commands, - isLoading: false, + return { + commands, + isLoading: false, + }; }; -} export function useSiteEditorNavigationCommands() { useCommandLoader( { name: 'core/edit-site/navigate-pages', - hook: usePageNavigationCommandLoader, + hook: getNavigationCommandLoaderPerPostType( 'page' ), } ); useCommandLoader( { name: 'core/edit-site/navigate-posts', - hook: usePostNavigationCommandLoader, + hook: getNavigationCommandLoaderPerPostType( 'post' ), } ); useCommandLoader( { name: 'core/edit-site/navigate-templates', - hook: useTemplateNavigationCommandLoader, + hook: getNavigationCommandLoaderPerTemplate( 'wp_template' ), } ); useCommandLoader( { name: 'core/edit-site/navigate-template-parts', - hook: useTemplatePartNavigationCommandLoader, + hook: getNavigationCommandLoaderPerTemplate( 'wp_template_part' ), } ); useCommandLoader( { name: 'core/edit-site/basic-navigation', - hook: useSiteEditorBasicNavigationCommands, + hook: getSiteEditorBasicNavigationCommands(), context: 'site-editor', } ); } diff --git a/packages/edit-site/src/hooks/commands/use-common-commands.js b/packages/edit-site/src/hooks/commands/use-common-commands.js index 536817e88d3a47..3e87f8721e116a 100644 --- a/packages/edit-site/src/hooks/commands/use-common-commands.js +++ b/packages/edit-site/src/hooks/commands/use-common-commands.js @@ -28,282 +28,289 @@ import { store as editSiteStore } from '../../store'; const { useGlobalStylesReset } = unlock( blockEditorPrivateApis ); const { useHistory, useLocation } = unlock( routerPrivateApis ); -function useGlobalStylesOpenStylesCommands() { - const { openGeneralSidebar } = unlock( useDispatch( editSiteStore ) ); - const { params } = useLocation(); - const { canvas = 'view' } = params; - const history = useHistory(); - const isBlockBasedTheme = useSelect( ( select ) => { - return select( coreStore ).getCurrentTheme().is_block_theme; - }, [] ); +const getGlobalStylesOpenStylesCommands = () => + function useGlobalStylesOpenStylesCommands() { + const { openGeneralSidebar } = unlock( useDispatch( editSiteStore ) ); + const { params } = useLocation(); + const { canvas = 'view' } = params; + const history = useHistory(); + const isBlockBasedTheme = useSelect( ( select ) => { + return select( coreStore ).getCurrentTheme().is_block_theme; + }, [] ); - const commands = useMemo( () => { - if ( ! isBlockBasedTheme ) { - return []; - } + const commands = useMemo( () => { + if ( ! isBlockBasedTheme ) { + return []; + } - return [ - { - name: 'core/edit-site/open-styles', - label: __( 'Open styles' ), - callback: ( { close } ) => { - close(); - if ( ! params.postId ) { - history.push( { - path: '/wp_global_styles', - canvas: 'edit', - } ); - } - if ( params.postId && canvas !== 'edit' ) { - history.push( - { ...params, canvas: 'edit' }, - undefined, - { - transition: 'canvas-mode-edit-transition', - } - ); - } - openGeneralSidebar( 'edit-site/global-styles' ); + return [ + { + name: 'core/edit-site/open-styles', + label: __( 'Open styles' ), + callback: ( { close } ) => { + close(); + if ( ! params.postId ) { + history.push( { + path: '/wp_global_styles', + canvas: 'edit', + } ); + } + if ( params.postId && canvas !== 'edit' ) { + history.push( + { ...params, canvas: 'edit' }, + undefined, + { + transition: 'canvas-mode-edit-transition', + } + ); + } + openGeneralSidebar( 'edit-site/global-styles' ); + }, + icon: styles, }, - icon: styles, - }, - ]; - }, [ history, openGeneralSidebar, params, canvas, isBlockBasedTheme ] ); + ]; + }, [ history, openGeneralSidebar, params, canvas, isBlockBasedTheme ] ); - return { - isLoading: false, - commands, + return { + isLoading: false, + commands, + }; }; -} -function useGlobalStylesToggleWelcomeGuideCommands() { - const { openGeneralSidebar } = unlock( useDispatch( editSiteStore ) ); - const { params } = useLocation(); - const { canvas = 'view' } = params; - const { set } = useDispatch( preferencesStore ); +const getGlobalStylesToggleWelcomeGuideCommands = () => + function useGlobalStylesToggleWelcomeGuideCommands() { + const { openGeneralSidebar } = unlock( useDispatch( editSiteStore ) ); + const { params } = useLocation(); + const { canvas = 'view' } = params; + const { set } = useDispatch( preferencesStore ); - const history = useHistory(); - const isBlockBasedTheme = useSelect( ( select ) => { - return select( coreStore ).getCurrentTheme().is_block_theme; - }, [] ); + const history = useHistory(); + const isBlockBasedTheme = useSelect( ( select ) => { + return select( coreStore ).getCurrentTheme().is_block_theme; + }, [] ); - const commands = useMemo( () => { - if ( ! isBlockBasedTheme ) { - return []; - } + const commands = useMemo( () => { + if ( ! isBlockBasedTheme ) { + return []; + } - return [ - { - name: 'core/edit-site/toggle-styles-welcome-guide', - label: __( 'Learn about styles' ), - callback: ( { close } ) => { - close(); - if ( ! params.postId ) { - history.push( { - path: '/wp_global_styles', - canvas: 'edit', - } ); - } - if ( params.postId && canvas !== 'edit' ) { - history.push( - { - ...params, + return [ + { + name: 'core/edit-site/toggle-styles-welcome-guide', + label: __( 'Learn about styles' ), + callback: ( { close } ) => { + close(); + if ( ! params.postId ) { + history.push( { + path: '/wp_global_styles', canvas: 'edit', - }, - undefined, - { - transition: 'canvas-mode-edit-transition', - } - ); - } - openGeneralSidebar( 'edit-site/global-styles' ); - set( 'core/edit-site', 'welcomeGuideStyles', true ); - // sometimes there's a focus loss that happens after some time - // that closes the modal, we need to force reopening it. - setTimeout( () => { + } ); + } + if ( params.postId && canvas !== 'edit' ) { + history.push( + { + ...params, + canvas: 'edit', + }, + undefined, + { + transition: 'canvas-mode-edit-transition', + } + ); + } + openGeneralSidebar( 'edit-site/global-styles' ); set( 'core/edit-site', 'welcomeGuideStyles', true ); - }, 500 ); + // sometimes there's a focus loss that happens after some time + // that closes the modal, we need to force reopening it. + setTimeout( () => { + set( 'core/edit-site', 'welcomeGuideStyles', true ); + }, 500 ); + }, + icon: help, }, - icon: help, - }, - ]; - }, [ - history, - openGeneralSidebar, - canvas, - isBlockBasedTheme, - set, - params, - ] ); + ]; + }, [ + history, + openGeneralSidebar, + canvas, + isBlockBasedTheme, + set, + params, + ] ); - return { - isLoading: false, - commands, + return { + isLoading: false, + commands, + }; }; -} -function useGlobalStylesResetCommands() { - const [ canReset, onReset ] = useGlobalStylesReset(); - const commands = useMemo( () => { - if ( ! canReset ) { - return []; - } +const getGlobalStylesResetCommands = () => + function useGlobalStylesResetCommands() { + const [ canReset, onReset ] = useGlobalStylesReset(); + const commands = useMemo( () => { + if ( ! canReset ) { + return []; + } - return [ - { - name: 'core/edit-site/reset-global-styles', - label: __( 'Reset styles' ), - icon: isRTL() ? rotateRight : rotateLeft, - callback: ( { close } ) => { - close(); - onReset(); + return [ + { + name: 'core/edit-site/reset-global-styles', + label: __( 'Reset styles' ), + icon: isRTL() ? rotateRight : rotateLeft, + callback: ( { close } ) => { + close(); + onReset(); + }, }, - }, - ]; - }, [ canReset, onReset ] ); + ]; + }, [ canReset, onReset ] ); - return { - isLoading: false, - commands, + return { + isLoading: false, + commands, + }; }; -} -function useGlobalStylesOpenCssCommands() { - const { openGeneralSidebar, setEditorCanvasContainerView } = unlock( - useDispatch( editSiteStore ) - ); - const { params } = useLocation(); - const { canvas = 'view' } = params; - const history = useHistory(); - const { canEditCSS } = useSelect( ( select ) => { - const { getEntityRecord, __experimentalGetCurrentGlobalStylesId } = - select( coreStore ); +const getGlobalStylesOpenCssCommands = () => + function useGlobalStylesOpenCssCommands() { + const { openGeneralSidebar, setEditorCanvasContainerView } = unlock( + useDispatch( editSiteStore ) + ); + const { params } = useLocation(); + const { canvas = 'view' } = params; + const history = useHistory(); + const { canEditCSS } = useSelect( ( select ) => { + const { getEntityRecord, __experimentalGetCurrentGlobalStylesId } = + select( coreStore ); - const globalStylesId = __experimentalGetCurrentGlobalStylesId(); - const globalStyles = globalStylesId - ? getEntityRecord( 'root', 'globalStyles', globalStylesId ) - : undefined; + const globalStylesId = __experimentalGetCurrentGlobalStylesId(); + const globalStyles = globalStylesId + ? getEntityRecord( 'root', 'globalStyles', globalStylesId ) + : undefined; - return { - canEditCSS: !! globalStyles?._links?.[ 'wp:action-edit-css' ], - }; - }, [] ); + return { + canEditCSS: !! globalStyles?._links?.[ 'wp:action-edit-css' ], + }; + }, [] ); - const commands = useMemo( () => { - if ( ! canEditCSS ) { - return []; - } + const commands = useMemo( () => { + if ( ! canEditCSS ) { + return []; + } - return [ - { - name: 'core/edit-site/open-styles-css', - label: __( 'Customize CSS' ), - icon: brush, - callback: ( { close } ) => { - close(); - if ( ! params.postId ) { - history.push( { - path: '/wp_global_styles', - canvas: 'edit', - } ); - } - if ( params.postId && canvas !== 'edit' ) { - history.push( - { - ...params, + return [ + { + name: 'core/edit-site/open-styles-css', + label: __( 'Customize CSS' ), + icon: brush, + callback: ( { close } ) => { + close(); + if ( ! params.postId ) { + history.push( { + path: '/wp_global_styles', canvas: 'edit', - }, - undefined, - { - transition: 'canvas-mode-edit-transition', - } - ); - } - openGeneralSidebar( 'edit-site/global-styles' ); - setEditorCanvasContainerView( 'global-styles-css' ); + } ); + } + if ( params.postId && canvas !== 'edit' ) { + history.push( + { + ...params, + canvas: 'edit', + }, + undefined, + { + transition: 'canvas-mode-edit-transition', + } + ); + } + openGeneralSidebar( 'edit-site/global-styles' ); + setEditorCanvasContainerView( 'global-styles-css' ); + }, }, - }, - ]; - }, [ - history, - openGeneralSidebar, - setEditorCanvasContainerView, - canEditCSS, - canvas, - params, - ] ); - return { - isLoading: false, - commands, + ]; + }, [ + history, + openGeneralSidebar, + setEditorCanvasContainerView, + canEditCSS, + canvas, + params, + ] ); + return { + isLoading: false, + commands, + }; }; -} -function useGlobalStylesOpenRevisionsCommands() { - const { openGeneralSidebar, setEditorCanvasContainerView } = unlock( - useDispatch( editSiteStore ) - ); - const { params } = useLocation(); - const { canvas = 'view' } = params; - const history = useHistory(); - const hasRevisions = useSelect( ( select ) => { - const { getEntityRecord, __experimentalGetCurrentGlobalStylesId } = - select( coreStore ); - const globalStylesId = __experimentalGetCurrentGlobalStylesId(); - const globalStyles = globalStylesId - ? getEntityRecord( 'root', 'globalStyles', globalStylesId ) - : undefined; - return !! globalStyles?._links?.[ 'version-history' ]?.[ 0 ]?.count; - }, [] ); +const getGlobalStylesOpenRevisionsCommands = () => + function useGlobalStylesOpenRevisionsCommands() { + const { openGeneralSidebar, setEditorCanvasContainerView } = unlock( + useDispatch( editSiteStore ) + ); + const { params } = useLocation(); + const { canvas = 'view' } = params; + const history = useHistory(); + const hasRevisions = useSelect( ( select ) => { + const { getEntityRecord, __experimentalGetCurrentGlobalStylesId } = + select( coreStore ); + const globalStylesId = __experimentalGetCurrentGlobalStylesId(); + const globalStyles = globalStylesId + ? getEntityRecord( 'root', 'globalStyles', globalStylesId ) + : undefined; + return !! globalStyles?._links?.[ 'version-history' ]?.[ 0 ]?.count; + }, [] ); - const commands = useMemo( () => { - if ( ! hasRevisions ) { - return []; - } + const commands = useMemo( () => { + if ( ! hasRevisions ) { + return []; + } - return [ - { - name: 'core/edit-site/open-global-styles-revisions', - label: __( 'Style revisions' ), - icon: backup, - callback: ( { close } ) => { - close(); - if ( ! params.postId ) { - history.push( { - path: '/wp_global_styles', - canvas: 'edit', - } ); - } - if ( params.postId && canvas !== 'edit' ) { - history.push( - { - ...params, + return [ + { + name: 'core/edit-site/open-global-styles-revisions', + label: __( 'Style revisions' ), + icon: backup, + callback: ( { close } ) => { + close(); + if ( ! params.postId ) { + history.push( { + path: '/wp_global_styles', canvas: 'edit', - }, - undefined, - { - transition: 'canvas-mode-edit-transition', - } + } ); + } + if ( params.postId && canvas !== 'edit' ) { + history.push( + { + ...params, + canvas: 'edit', + }, + undefined, + { + transition: 'canvas-mode-edit-transition', + } + ); + } + openGeneralSidebar( 'edit-site/global-styles' ); + setEditorCanvasContainerView( + 'global-styles-revisions' ); - } - openGeneralSidebar( 'edit-site/global-styles' ); - setEditorCanvasContainerView( 'global-styles-revisions' ); + }, }, - }, - ]; - }, [ - hasRevisions, - history, - openGeneralSidebar, - setEditorCanvasContainerView, - canvas, - params, - ] ); + ]; + }, [ + hasRevisions, + history, + openGeneralSidebar, + setEditorCanvasContainerView, + canvas, + params, + ] ); - return { - isLoading: false, - commands, + return { + isLoading: false, + commands, + }; }; -} export function useCommonCommands() { const homeUrl = useSelect( ( select ) => { @@ -324,26 +331,26 @@ export function useCommonCommands() { useCommandLoader( { name: 'core/edit-site/open-styles', - hook: useGlobalStylesOpenStylesCommands, + hook: getGlobalStylesOpenStylesCommands(), } ); useCommandLoader( { name: 'core/edit-site/toggle-styles-welcome-guide', - hook: useGlobalStylesToggleWelcomeGuideCommands, + hook: getGlobalStylesToggleWelcomeGuideCommands(), } ); useCommandLoader( { name: 'core/edit-site/reset-global-styles', - hook: useGlobalStylesResetCommands, + hook: getGlobalStylesResetCommands(), } ); useCommandLoader( { name: 'core/edit-site/open-styles-css', - hook: useGlobalStylesOpenCssCommands, + hook: getGlobalStylesOpenCssCommands(), } ); useCommandLoader( { name: 'core/edit-site/open-styles-revisions', - hook: useGlobalStylesOpenRevisionsCommands, + hook: getGlobalStylesOpenRevisionsCommands(), } ); } diff --git a/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js b/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js index 97283044193892..da36f32e6c0d51 100644 --- a/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js +++ b/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js @@ -22,147 +22,152 @@ import { useLink } from '../../components/routes/link'; const { useHistory, useLocation } = unlock( routerPrivateApis ); -function usePageContentFocusCommands() { - const { record: template } = useEditedEntityRecord(); - const { params } = useLocation(); - const { canvas = 'view' } = params; - const { isPage, templateId, currentPostType } = useSelect( ( select ) => { - const { isPage: _isPage } = unlock( select( editSiteStore ) ); - const { getCurrentPostType, getCurrentTemplateId } = - select( editorStore ); - return { - isPage: _isPage(), - templateId: getCurrentTemplateId(), - currentPostType: getCurrentPostType(), - }; - }, [] ); - - const { onClick: editTemplate } = useLink( { - postType: 'wp_template', - postId: templateId, - } ); - - const { setRenderingMode } = useDispatch( editorStore ); - - if ( ! isPage || canvas !== 'edit' ) { - return { isLoading: false, commands: [] }; - } - - const commands = []; - - if ( currentPostType !== 'wp_template' ) { - commands.push( { - name: 'core/switch-to-template-focus', - label: sprintf( - /* translators: %s: template title */ - __( 'Edit template: %s' ), - decodeEntities( template.title ) - ), - icon: layout, - callback: ( { close } ) => { - editTemplate(); - close(); - }, - } ); - } else { - commands.push( { - name: 'core/switch-to-page-focus', - label: __( 'Back to page' ), - icon: page, - callback: ( { close } ) => { - setRenderingMode( 'template-locked' ); - close(); +const getPageContentFocusCommands = () => + function usePageContentFocusCommands() { + const { record: template } = useEditedEntityRecord(); + const { params } = useLocation(); + const { canvas = 'view' } = params; + const { isPage, templateId, currentPostType } = useSelect( + ( select ) => { + const { isPage: _isPage } = unlock( select( editSiteStore ) ); + const { getCurrentPostType, getCurrentTemplateId } = + select( editorStore ); + return { + isPage: _isPage(), + templateId: getCurrentTemplateId(), + currentPostType: getCurrentPostType(), + }; }, + [] + ); + + const { onClick: editTemplate } = useLink( { + postType: 'wp_template', + postId: templateId, } ); - } - return { isLoading: false, commands }; -} + const { setRenderingMode } = useDispatch( editorStore ); + + if ( ! isPage || canvas !== 'edit' ) { + return { isLoading: false, commands: [] }; + } + + const commands = []; + + if ( currentPostType !== 'wp_template' ) { + commands.push( { + name: 'core/switch-to-template-focus', + label: sprintf( + /* translators: %s: template title */ + __( 'Edit template: %s' ), + decodeEntities( template.title ) + ), + icon: layout, + callback: ( { close } ) => { + editTemplate(); + close(); + }, + } ); + } else { + commands.push( { + name: 'core/switch-to-page-focus', + label: __( 'Back to page' ), + icon: page, + callback: ( { close } ) => { + setRenderingMode( 'template-locked' ); + close(); + }, + } ); + } + + return { isLoading: false, commands }; + }; -function useManipulateDocumentCommands() { - const { isLoaded, record: template } = useEditedEntityRecord(); - const { removeTemplate, revertTemplate } = useDispatch( editSiteStore ); - const history = useHistory(); - const isEditingPage = useSelect( - ( select ) => - select( editSiteStore ).isPage() && - select( editorStore ).getCurrentPostType() !== 'wp_template', - [] - ); - - if ( ! isLoaded ) { - return { isLoading: true, commands: [] }; - } - - const commands = []; - - if ( isTemplateRevertable( template ) && ! isEditingPage ) { - const label = - template.type === TEMPLATE_POST_TYPE - ? sprintf( - /* translators: %s: template title */ - __( 'Reset template: %s' ), - decodeEntities( template.title ) - ) - : sprintf( - /* translators: %s: template part title */ - __( 'Reset template part: %s' ), - decodeEntities( template.title ) - ); - commands.push( { - name: 'core/reset-template', - label, - icon: isRTL() ? rotateRight : rotateLeft, - callback: ( { close } ) => { - revertTemplate( template ); - close(); - }, - } ); - } - - if ( isTemplateRemovable( template ) && ! isEditingPage ) { - const label = - template.type === TEMPLATE_POST_TYPE - ? sprintf( - /* translators: %s: template title */ - __( 'Delete template: %s' ), - decodeEntities( template.title ) - ) - : sprintf( - /* translators: %s: template part title */ - __( 'Delete template part: %s' ), - decodeEntities( template.title ) - ); - commands.push( { - name: 'core/remove-template', - label, - icon: trash, - callback: ( { close } ) => { - removeTemplate( template ); - // Navigate to the template list - history.push( { - postType: template.type, - } ); - close(); - }, - } ); - } +const getManipulateDocumentCommands = () => + function useManipulateDocumentCommands() { + const { isLoaded, record: template } = useEditedEntityRecord(); + const { removeTemplate, revertTemplate } = useDispatch( editSiteStore ); + const history = useHistory(); + const isEditingPage = useSelect( + ( select ) => + select( editSiteStore ).isPage() && + select( editorStore ).getCurrentPostType() !== 'wp_template', + [] + ); + + if ( ! isLoaded ) { + return { isLoading: true, commands: [] }; + } + + const commands = []; + + if ( isTemplateRevertable( template ) && ! isEditingPage ) { + const label = + template.type === TEMPLATE_POST_TYPE + ? sprintf( + /* translators: %s: template title */ + __( 'Reset template: %s' ), + decodeEntities( template.title ) + ) + : sprintf( + /* translators: %s: template part title */ + __( 'Reset template part: %s' ), + decodeEntities( template.title ) + ); + commands.push( { + name: 'core/reset-template', + label, + icon: isRTL() ? rotateRight : rotateLeft, + callback: ( { close } ) => { + revertTemplate( template ); + close(); + }, + } ); + } + + if ( isTemplateRemovable( template ) && ! isEditingPage ) { + const label = + template.type === TEMPLATE_POST_TYPE + ? sprintf( + /* translators: %s: template title */ + __( 'Delete template: %s' ), + decodeEntities( template.title ) + ) + : sprintf( + /* translators: %s: template part title */ + __( 'Delete template part: %s' ), + decodeEntities( template.title ) + ); + commands.push( { + name: 'core/remove-template', + label, + icon: trash, + callback: ( { close } ) => { + removeTemplate( template ); + // Navigate to the template list + history.push( { + postType: template.type, + } ); + close(); + }, + } ); + } - return { - isLoading: ! isLoaded, - commands, + return { + isLoading: ! isLoaded, + commands, + }; }; -} export function useEditModeCommands() { useCommandLoader( { name: 'core/edit-site/page-content-focus', - hook: usePageContentFocusCommands, + hook: getPageContentFocusCommands(), context: 'entity-edit', } ); useCommandLoader( { name: 'core/edit-site/manipulate-document', - hook: useManipulateDocumentCommands, + hook: getManipulateDocumentCommands(), } ); } diff --git a/packages/editor/src/components/commands/index.js b/packages/editor/src/components/commands/index.js index b4b9c05db256d7..16260bed3978fd 100644 --- a/packages/editor/src/components/commands/index.js +++ b/packages/editor/src/components/commands/index.js @@ -30,279 +30,287 @@ import { PATTERN_POST_TYPE } from '../../store/constants'; import { modalName as patternRenameModalName } from '../pattern-rename-modal'; import { modalName as patternDuplicateModalName } from '../pattern-duplicate-modal'; -function useEditorCommandLoader() { - const { - editorMode, - isListViewOpen, - showBlockBreadcrumbs, - isDistractionFree, - isFocusMode, - isPreviewMode, - isViewable, - isCodeEditingEnabled, - isRichEditingEnabled, - isPublishSidebarEnabled, - } = useSelect( ( select ) => { - const { get } = select( preferencesStore ); - const { isListViewOpened, getCurrentPostType, getEditorSettings } = - select( editorStore ); - const { getSettings } = select( blockEditorStore ); - const { getPostType } = select( coreStore ); +const getEditorCommandLoader = () => + function useEditorCommandLoader() { + const { + editorMode, + isListViewOpen, + showBlockBreadcrumbs, + isDistractionFree, + isFocusMode, + isPreviewMode, + isViewable, + isCodeEditingEnabled, + isRichEditingEnabled, + isPublishSidebarEnabled, + } = useSelect( ( select ) => { + const { get } = select( preferencesStore ); + const { isListViewOpened, getCurrentPostType, getEditorSettings } = + select( editorStore ); + const { getSettings } = select( blockEditorStore ); + const { getPostType } = select( coreStore ); - return { - editorMode: get( 'core', 'editorMode' ) ?? 'visual', - isListViewOpen: isListViewOpened(), - showBlockBreadcrumbs: get( 'core', 'showBlockBreadcrumbs' ), - isDistractionFree: get( 'core', 'distractionFree' ), - isFocusMode: get( 'core', 'focusMode' ), - isPreviewMode: getSettings().isPreviewMode, - isViewable: getPostType( getCurrentPostType() )?.viewable ?? false, - isCodeEditingEnabled: getEditorSettings().codeEditingEnabled, - isRichEditingEnabled: getEditorSettings().richEditingEnabled, - isPublishSidebarEnabled: - select( editorStore ).isPublishSidebarEnabled(), - }; - }, [] ); - const { getActiveComplementaryArea } = useSelect( interfaceStore ); - const { toggle } = useDispatch( preferencesStore ); - const { createInfoNotice } = useDispatch( noticesStore ); - const { - __unstableSaveForPreview, - setIsListViewOpened, - switchEditorMode, - toggleDistractionFree, - toggleSpotlightMode, - toggleTopToolbar, - } = useDispatch( editorStore ); - const { openModal, enableComplementaryArea, disableComplementaryArea } = - useDispatch( interfaceStore ); - const { getCurrentPostId } = useSelect( editorStore ); - const allowSwitchEditorMode = isCodeEditingEnabled && isRichEditingEnabled; + return { + editorMode: get( 'core', 'editorMode' ) ?? 'visual', + isListViewOpen: isListViewOpened(), + showBlockBreadcrumbs: get( 'core', 'showBlockBreadcrumbs' ), + isDistractionFree: get( 'core', 'distractionFree' ), + isFocusMode: get( 'core', 'focusMode' ), + isPreviewMode: getSettings().isPreviewMode, + isViewable: + getPostType( getCurrentPostType() )?.viewable ?? false, + isCodeEditingEnabled: getEditorSettings().codeEditingEnabled, + isRichEditingEnabled: getEditorSettings().richEditingEnabled, + isPublishSidebarEnabled: + select( editorStore ).isPublishSidebarEnabled(), + }; + }, [] ); + const { getActiveComplementaryArea } = useSelect( interfaceStore ); + const { toggle } = useDispatch( preferencesStore ); + const { createInfoNotice } = useDispatch( noticesStore ); + const { + __unstableSaveForPreview, + setIsListViewOpened, + switchEditorMode, + toggleDistractionFree, + toggleSpotlightMode, + toggleTopToolbar, + } = useDispatch( editorStore ); + const { openModal, enableComplementaryArea, disableComplementaryArea } = + useDispatch( interfaceStore ); + const { getCurrentPostId } = useSelect( editorStore ); + const allowSwitchEditorMode = + isCodeEditingEnabled && isRichEditingEnabled; - if ( isPreviewMode ) { - return { commands: [], isLoading: false }; - } + if ( isPreviewMode ) { + return { commands: [], isLoading: false }; + } - const commands = []; + const commands = []; - commands.push( { - name: 'core/open-shortcut-help', - label: __( 'Keyboard shortcuts' ), - icon: keyboard, - callback: ( { close } ) => { - close(); - openModal( 'editor/keyboard-shortcut-help' ); - }, - } ); - - commands.push( { - name: 'core/toggle-distraction-free', - label: isDistractionFree - ? __( 'Exit Distraction free' ) - : __( 'Enter Distraction free' ), - callback: ( { close } ) => { - toggleDistractionFree(); - close(); - }, - } ); - - commands.push( { - name: 'core/open-preferences', - label: __( 'Editor preferences' ), - callback: ( { close } ) => { - close(); - openModal( 'editor/preferences' ); - }, - } ); - - commands.push( { - name: 'core/toggle-spotlight-mode', - label: isFocusMode - ? __( 'Exit Spotlight mode' ) - : __( 'Enter Spotlight mode' ), - callback: ( { close } ) => { - toggleSpotlightMode(); - close(); - }, - } ); - - commands.push( { - name: 'core/toggle-list-view', - label: isListViewOpen - ? __( 'Close List View' ) - : __( 'Open List View' ), - icon: listView, - callback: ( { close } ) => { - setIsListViewOpened( ! isListViewOpen ); - close(); - createInfoNotice( - isListViewOpen ? __( 'List View off.' ) : __( 'List View on.' ), - { - id: 'core/editor/toggle-list-view/notice', - type: 'snackbar', - } - ); - }, - } ); + commands.push( { + name: 'core/open-shortcut-help', + label: __( 'Keyboard shortcuts' ), + icon: keyboard, + callback: ( { close } ) => { + close(); + openModal( 'editor/keyboard-shortcut-help' ); + }, + } ); - commands.push( { - name: 'core/toggle-top-toolbar', - label: __( 'Top toolbar' ), - callback: ( { close } ) => { - toggleTopToolbar(); - close(); - }, - } ); + commands.push( { + name: 'core/toggle-distraction-free', + label: isDistractionFree + ? __( 'Exit Distraction free' ) + : __( 'Enter Distraction free' ), + callback: ( { close } ) => { + toggleDistractionFree(); + close(); + }, + } ); - if ( allowSwitchEditorMode ) { commands.push( { - name: 'core/toggle-code-editor', - label: - editorMode === 'visual' - ? __( 'Open code editor' ) - : __( 'Exit code editor' ), - icon: code, + name: 'core/open-preferences', + label: __( 'Editor preferences' ), callback: ( { close } ) => { - switchEditorMode( editorMode === 'visual' ? 'text' : 'visual' ); close(); + openModal( 'editor/preferences' ); }, } ); - } - commands.push( { - name: 'core/toggle-breadcrumbs', - label: showBlockBreadcrumbs - ? __( 'Hide block breadcrumbs' ) - : __( 'Show block breadcrumbs' ), - callback: ( { close } ) => { - toggle( 'core', 'showBlockBreadcrumbs' ); - close(); - createInfoNotice( - showBlockBreadcrumbs - ? __( 'Breadcrumbs hidden.' ) - : __( 'Breadcrumbs visible.' ), - { - id: 'core/editor/toggle-breadcrumbs/notice', - type: 'snackbar', - } - ); - }, - } ); + commands.push( { + name: 'core/toggle-spotlight-mode', + label: isFocusMode + ? __( 'Exit Spotlight mode' ) + : __( 'Enter Spotlight mode' ), + callback: ( { close } ) => { + toggleSpotlightMode(); + close(); + }, + } ); - commands.push( { - name: 'core/open-settings-sidebar', - label: __( 'Show or hide the Settings panel.' ), - icon: isRTL() ? drawerLeft : drawerRight, - callback: ( { close } ) => { - const activeSidebar = getActiveComplementaryArea( 'core' ); - close(); - if ( activeSidebar === 'edit-post/document' ) { - disableComplementaryArea( 'core' ); - } else { - enableComplementaryArea( 'core', 'edit-post/document' ); - } - }, - } ); + commands.push( { + name: 'core/toggle-list-view', + label: isListViewOpen + ? __( 'Close List View' ) + : __( 'Open List View' ), + icon: listView, + callback: ( { close } ) => { + setIsListViewOpened( ! isListViewOpen ); + close(); + createInfoNotice( + isListViewOpen + ? __( 'List View off.' ) + : __( 'List View on.' ), + { + id: 'core/editor/toggle-list-view/notice', + type: 'snackbar', + } + ); + }, + } ); - commands.push( { - name: 'core/open-block-inspector', - label: __( 'Show or hide the Block settings panel' ), - icon: blockDefault, - callback: ( { close } ) => { - const activeSidebar = getActiveComplementaryArea( 'core' ); - close(); - if ( activeSidebar === 'edit-post/block' ) { - disableComplementaryArea( 'core' ); - } else { - enableComplementaryArea( 'core', 'edit-post/block' ); - } - }, - } ); + commands.push( { + name: 'core/toggle-top-toolbar', + label: __( 'Top toolbar' ), + callback: ( { close } ) => { + toggleTopToolbar(); + close(); + }, + } ); - commands.push( { - name: 'core/toggle-publish-sidebar', - label: isPublishSidebarEnabled - ? __( 'Disable pre-publish checks' ) - : __( 'Enable pre-publish checks' ), - icon: formatListBullets, - callback: ( { close } ) => { - close(); - toggle( 'core', 'isPublishSidebarEnabled' ); - createInfoNotice( - isPublishSidebarEnabled - ? __( 'Pre-publish checks disabled.' ) - : __( 'Pre-publish checks enabled.' ), - { - id: 'core/editor/publish-sidebar/notice', - type: 'snackbar', - } - ); - }, - } ); + if ( allowSwitchEditorMode ) { + commands.push( { + name: 'core/toggle-code-editor', + label: + editorMode === 'visual' + ? __( 'Open code editor' ) + : __( 'Exit code editor' ), + icon: code, + callback: ( { close } ) => { + switchEditorMode( + editorMode === 'visual' ? 'text' : 'visual' + ); + close(); + }, + } ); + } - if ( isViewable ) { commands.push( { - name: 'core/preview-link', - label: __( 'Preview in a new tab' ), - icon: external, - callback: async ( { close } ) => { + name: 'core/toggle-breadcrumbs', + label: showBlockBreadcrumbs + ? __( 'Hide block breadcrumbs' ) + : __( 'Show block breadcrumbs' ), + callback: ( { close } ) => { + toggle( 'core', 'showBlockBreadcrumbs' ); close(); - const postId = getCurrentPostId(); - const link = await __unstableSaveForPreview(); - window.open( link, `wp-preview-${ postId }` ); + createInfoNotice( + showBlockBreadcrumbs + ? __( 'Breadcrumbs hidden.' ) + : __( 'Breadcrumbs visible.' ), + { + id: 'core/editor/toggle-breadcrumbs/notice', + type: 'snackbar', + } + ); }, } ); - } - - return { - commands, - isLoading: false, - }; -} -function useEditedEntityContextualCommands() { - const { postType } = useSelect( ( select ) => { - const { getCurrentPostType } = select( editorStore ); - return { - postType: getCurrentPostType(), - }; - }, [] ); - const { openModal } = useDispatch( interfaceStore ); - const commands = []; + commands.push( { + name: 'core/open-settings-sidebar', + label: __( 'Show or hide the Settings panel.' ), + icon: isRTL() ? drawerLeft : drawerRight, + callback: ( { close } ) => { + const activeSidebar = getActiveComplementaryArea( 'core' ); + close(); + if ( activeSidebar === 'edit-post/document' ) { + disableComplementaryArea( 'core' ); + } else { + enableComplementaryArea( 'core', 'edit-post/document' ); + } + }, + } ); - if ( postType === PATTERN_POST_TYPE ) { commands.push( { - name: 'core/rename-pattern', - label: __( 'Rename pattern' ), - icon: edit, + name: 'core/open-block-inspector', + label: __( 'Show or hide the Block settings panel' ), + icon: blockDefault, callback: ( { close } ) => { - openModal( patternRenameModalName ); + const activeSidebar = getActiveComplementaryArea( 'core' ); close(); + if ( activeSidebar === 'edit-post/block' ) { + disableComplementaryArea( 'core' ); + } else { + enableComplementaryArea( 'core', 'edit-post/block' ); + } }, } ); + commands.push( { - name: 'core/duplicate-pattern', - label: __( 'Duplicate pattern' ), - icon: symbol, + name: 'core/toggle-publish-sidebar', + label: isPublishSidebarEnabled + ? __( 'Disable pre-publish checks' ) + : __( 'Enable pre-publish checks' ), + icon: formatListBullets, callback: ( { close } ) => { - openModal( patternDuplicateModalName ); close(); + toggle( 'core', 'isPublishSidebarEnabled' ); + createInfoNotice( + isPublishSidebarEnabled + ? __( 'Pre-publish checks disabled.' ) + : __( 'Pre-publish checks enabled.' ), + { + id: 'core/editor/publish-sidebar/notice', + type: 'snackbar', + } + ); }, } ); - } - return { isLoading: false, commands }; -} + if ( isViewable ) { + commands.push( { + name: 'core/preview-link', + label: __( 'Preview in a new tab' ), + icon: external, + callback: async ( { close } ) => { + close(); + const postId = getCurrentPostId(); + const link = await __unstableSaveForPreview(); + window.open( link, `wp-preview-${ postId }` ); + }, + } ); + } + + return { + commands, + isLoading: false, + }; + }; + +const getEditedEntityContextualCommands = () => + function useEditedEntityContextualCommands() { + const { postType } = useSelect( ( select ) => { + const { getCurrentPostType } = select( editorStore ); + return { + postType: getCurrentPostType(), + }; + }, [] ); + const { openModal } = useDispatch( interfaceStore ); + const commands = []; + + if ( postType === PATTERN_POST_TYPE ) { + commands.push( { + name: 'core/rename-pattern', + label: __( 'Rename pattern' ), + icon: edit, + callback: ( { close } ) => { + openModal( patternRenameModalName ); + close(); + }, + } ); + commands.push( { + name: 'core/duplicate-pattern', + label: __( 'Duplicate pattern' ), + icon: symbol, + callback: ( { close } ) => { + openModal( patternDuplicateModalName ); + close(); + }, + } ); + } + + return { isLoading: false, commands }; + }; export default function useCommands() { useCommandLoader( { name: 'core/editor/edit-ui', - hook: useEditorCommandLoader, + hook: getEditorCommandLoader(), } ); useCommandLoader( { name: 'core/editor/contextual-commands', - hook: useEditedEntityContextualCommands, + hook: getEditedEntityContextualCommands(), context: 'entity-edit', } ); } From f15b4c19175da72843234cc6c862296ce9a4dcf8 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Thu, 7 Nov 2024 09:55:42 +0100 Subject: [PATCH 1508/1908] Fix inconsistent sidebars close buttons sizes (#66756) * Increase complementary area and tabbed sidebar X close button size. * Adjust widgets header actions right padding and gap. * Adjust edit widgets list view X close button size. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../block-editor/src/components/tabbed-sidebar/index.js | 2 +- .../block-editor/src/components/tabbed-sidebar/style.scss | 2 +- packages/edit-widgets/src/components/header/style.scss | 7 ++++--- .../src/components/secondary-sidebar/list-view-sidebar.js | 2 +- .../src/components/secondary-sidebar/style.scss | 2 +- packages/editor/src/components/sidebar/style.scss | 4 +--- .../src/components/complementary-area-header/style.scss | 4 ++-- .../interface/src/components/complementary-area/index.js | 2 +- 8 files changed, 12 insertions(+), 13 deletions(-) diff --git a/packages/block-editor/src/components/tabbed-sidebar/index.js b/packages/block-editor/src/components/tabbed-sidebar/index.js index a0cb510c720904..c9ff6bbf6555f0 100644 --- a/packages/block-editor/src/components/tabbed-sidebar/index.js +++ b/packages/block-editor/src/components/tabbed-sidebar/index.js @@ -33,7 +33,7 @@ function TabbedSidebar( icon={ closeSmall } label={ closeButtonLabel } onClick={ () => onClose() } - size="small" + size="compact" /> <Tabs.TabList diff --git a/packages/block-editor/src/components/tabbed-sidebar/style.scss b/packages/block-editor/src/components/tabbed-sidebar/style.scss index f7fba1c0003467..c6f8f14d6ca7c7 100644 --- a/packages/block-editor/src/components/tabbed-sidebar/style.scss +++ b/packages/block-editor/src/components/tabbed-sidebar/style.scss @@ -11,7 +11,7 @@ border-bottom: $border-width solid $gray-300; display: flex; justify-content: space-between; - padding-right: $grid-unit-15; + padding-right: $grid-unit-10; } diff --git a/packages/edit-widgets/src/components/header/style.scss b/packages/edit-widgets/src/components/header/style.scss index 7bd3c41a6a22ad..642a641e6e5952 100644 --- a/packages/edit-widgets/src/components/header/style.scss +++ b/packages/edit-widgets/src/components/header/style.scss @@ -94,12 +94,13 @@ .edit-widgets-header__actions { display: flex; align-items: center; - padding-right: $grid-unit-20; - gap: $grid-unit-05; + padding-right: $grid-unit-05; @include break-small() { - gap: $grid-unit-10; + padding-right: $grid-unit-10; } + + gap: $grid-unit-10; } .edit-widgets-header-toolbar { diff --git a/packages/edit-widgets/src/components/secondary-sidebar/list-view-sidebar.js b/packages/edit-widgets/src/components/secondary-sidebar/list-view-sidebar.js index 1bb850393ad023..fc645fd3bbd0d4 100644 --- a/packages/edit-widgets/src/components/secondary-sidebar/list-view-sidebar.js +++ b/packages/edit-widgets/src/components/secondary-sidebar/list-view-sidebar.js @@ -51,10 +51,10 @@ export default function ListViewSidebar() { <div className="edit-widgets-editor__list-view-panel-header"> <strong>{ __( 'List View' ) }</strong> <Button - __next40pxDefaultSize icon={ closeSmall } label={ __( 'Close' ) } onClick={ closeListView } + size="compact" /> </div> <div diff --git a/packages/edit-widgets/src/components/secondary-sidebar/style.scss b/packages/edit-widgets/src/components/secondary-sidebar/style.scss index 5acf945480a528..bcaf07d06e2224 100644 --- a/packages/edit-widgets/src/components/secondary-sidebar/style.scss +++ b/packages/edit-widgets/src/components/secondary-sidebar/style.scss @@ -21,5 +21,5 @@ justify-content: space-between; height: $grid-unit-60; padding-left: $grid-unit-20; - padding-right: $grid-unit-05; + padding-right: $grid-unit-10; } diff --git a/packages/editor/src/components/sidebar/style.scss b/packages/editor/src/components/sidebar/style.scss index 9853088dde1be7..33a2350b8a92e6 100644 --- a/packages/editor/src/components/sidebar/style.scss +++ b/packages/editor/src/components/sidebar/style.scss @@ -1,11 +1,9 @@ .components-panel__header.editor-sidebar__panel-tabs { padding-left: 0; - padding-right: $grid-unit-15; + padding-right: $grid-unit-10; .components-button.has-icon { padding: 0; - min-width: $icon-size; - height: $icon-size; @include break-medium() { display: flex; diff --git a/packages/interface/src/components/complementary-area-header/style.scss b/packages/interface/src/components/complementary-area-header/style.scss index c62fe7dc941760..d2ae1fe6ecda79 100644 --- a/packages/interface/src/components/complementary-area-header/style.scss +++ b/packages/interface/src/components/complementary-area-header/style.scss @@ -1,7 +1,7 @@ .interface-complementary-area-header { background: $white; - padding-right: $grid-unit-15; // Reduced padding to account for close buttons. - gap: $grid-unit-10; // Always ensure space between contents and close buttons. + padding-right: $grid-unit-10; // Reduced padding to account for close buttons. + gap: $grid-unit-05; // Always ensure space between contents and close buttons. .interface-complementary-area-header__title { margin: 0 auto 0 0; diff --git a/packages/interface/src/components/complementary-area/index.js b/packages/interface/src/components/complementary-area/index.js index ff4c3eb1469789..af56cf0c1755e1 100644 --- a/packages/interface/src/components/complementary-area/index.js +++ b/packages/interface/src/components/complementary-area/index.js @@ -308,7 +308,7 @@ function ComplementaryArea( { onClose={ () => disableComplementaryArea( scope ) } toggleButtonProps={ { label: closeLabel, - size: 'small', + size: 'compact', shortcut: toggleShortcut, scope, identifier, From b0d2041e2b1de19aed1f088b4f9b6068cfd89e47 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:06:59 +0100 Subject: [PATCH 1509/1908] Iframe: always enable for block themes, in core too (#66800) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- .../components/layout/use-should-iframe.js | 50 +++++++------------ 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/packages/edit-post/src/components/layout/use-should-iframe.js b/packages/edit-post/src/components/layout/use-should-iframe.js index 6da344c138f64b..cd2a893d8d1cd0 100644 --- a/packages/edit-post/src/components/layout/use-should-iframe.js +++ b/packages/edit-post/src/components/layout/use-should-iframe.js @@ -11,39 +11,27 @@ import { store as blockEditorStore } from '@wordpress/block-editor'; */ import { unlock } from '../../lock-unlock'; -const isGutenbergPlugin = globalThis.IS_GUTENBERG_PLUGIN ? true : false; - export function useShouldIframe() { - const { - isBlockBasedTheme, - hasV3BlocksOnly, - isEditingTemplateOrPattern, - isZoomOutMode, - deviceType, - } = useSelect( ( select ) => { + return useSelect( ( select ) => { const { getEditorSettings, getCurrentPostType, getDeviceType } = select( editorStore ); - const { isZoomOut } = unlock( select( blockEditorStore ) ); - const { getBlockTypes } = select( blocksStore ); - const editorSettings = getEditorSettings(); - return { - isBlockBasedTheme: editorSettings.__unstableIsBlockBasedTheme, - hasV3BlocksOnly: getBlockTypes().every( ( type ) => { - return type.apiVersion >= 3; - } ), - isEditingTemplateOrPattern: [ 'wp_template', 'wp_block' ].includes( - getCurrentPostType() - ), - isZoomOutMode: isZoomOut(), - deviceType: getDeviceType(), - }; + return ( + // If the theme is block based, we ALWAYS use the iframe for + // consistency across the post and site editor. The iframe was + // introduced long before the sited editor and block themes, so + // these themes are expecting it. + getEditorSettings().__unstableIsBlockBasedTheme || + // For classic themes, we also still want to iframe all the special + // editor features and modes such as device previews, zoom out, and + // template/pattern editing. + getDeviceType() !== 'Desktop' || + [ 'wp_template', 'wp_block' ].includes( getCurrentPostType() ) || + unlock( select( blockEditorStore ) ).isZoomOut() || + // Finally, still iframe the editor for classic themes if all blocks + // are v3 (which means they are marked as iframe-compatible). + select( blocksStore ) + .getBlockTypes() + .every( ( type ) => type.apiVersion >= 3 ) + ); }, [] ); - - return ( - hasV3BlocksOnly || - ( isGutenbergPlugin && isBlockBasedTheme ) || - isEditingTemplateOrPattern || - isZoomOutMode || - [ 'Tablet', 'Mobile' ].includes( deviceType ) - ); } From 69f71e1170ced7897d5287ea3fbc9627e4b63c7f Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 7 Nov 2024 18:14:20 +0900 Subject: [PATCH 1510/1908] Data: Rename useSelect internals to fix React Compiler violations (#66807) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/data/src/components/use-select/index.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/data/src/components/use-select/index.js b/packages/data/src/components/use-select/index.js index 3e28e9489e977e..15a3c88d2d5543 100644 --- a/packages/data/src/components/use-select/index.js +++ b/packages/data/src/components/use-select/index.js @@ -209,11 +209,11 @@ function Store( registry, suspense ) { }; } -function useStaticSelect( storeName ) { +function _useStaticSelect( storeName ) { return useRegistry().select( storeName ); } -function useMappingSelect( suspense, mapSelect, deps ) { +function _useMappingSelect( suspense, mapSelect, deps ) { const registry = useRegistry(); const isAsync = useAsyncMode(); const store = useMemo( @@ -308,13 +308,11 @@ export default function useSelect( mapSelect, deps ) { ); } - /* eslint-disable react-hooks/rules-of-hooks */ // `staticSelectMode` is not allowed to change during the hook instance's, // lifetime, so the rules of hooks are not really violated. return staticSelectMode - ? useStaticSelect( mapSelect ) - : useMappingSelect( false, mapSelect, deps ); - /* eslint-enable react-hooks/rules-of-hooks */ + ? _useStaticSelect( mapSelect ) + : _useMappingSelect( false, mapSelect, deps ); } /** @@ -337,5 +335,5 @@ export default function useSelect( mapSelect, deps ) { * @return {ReturnType<T>} Data object returned by the `mapSelect` function. */ export function useSuspenseSelect( mapSelect, deps ) { - return useMappingSelect( true, mapSelect, deps ); + return _useMappingSelect( true, mapSelect, deps ); } From 7874fc5526618666f081b131b9cf0c6489c6cd9c Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 7 Nov 2024 10:46:07 +0100 Subject: [PATCH 1511/1908] Block Editor: Fix React Compiler error for 'BlockProps' util (#66809) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/block-editor/src/hooks/utils.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index fa710fa7f08eba..4334f70b9d13bf 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -562,8 +562,13 @@ export function createBlockEditFilter( features ) { addFilter( 'editor.BlockEdit', 'core/editor/hooks', withBlockEditHooks ); } -function BlockProps( { index, useBlockProps, setAllWrapperProps, ...props } ) { - const wrapperProps = useBlockProps( props ); +function BlockProps( { + index, + useBlockProps: hook, + setAllWrapperProps, + ...props +} ) { + const wrapperProps = hook( props ); const setWrapperProps = ( next ) => setAllWrapperProps( ( prev ) => { const nextAll = [ ...prev ]; From cb24e93252cf8aaa64d3ea4db337c950c1c74aec Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 7 Nov 2024 21:03:34 +0900 Subject: [PATCH 1512/1908] Enable zoom out mode for non-iframe editor (#66789) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- packages/editor/src/components/editor-interface/index.js | 1 - packages/editor/src/components/header/index.js | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/editor/src/components/editor-interface/index.js b/packages/editor/src/components/editor-interface/index.js index aee75695b3fda4..3692a5ed797f5e 100644 --- a/packages/editor/src/components/editor-interface/index.js +++ b/packages/editor/src/components/editor-interface/index.js @@ -131,7 +131,6 @@ export default function EditorInterface( { customSaveButton={ customSaveButton } forceDisableBlockTools={ forceDisableBlockTools } title={ title } - isEditorIframed={ ! disableIframe } /> ) } diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index 5a9cc2f94a5951..2a5629b080caf8 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -53,7 +53,6 @@ function Header( { forceDisableBlockTools, setEntitiesSavedStatesCallback, title, - isEditorIframed, } ) { const isWideViewport = useViewportMatch( 'large' ); const isLargeViewport = useViewportMatch( 'medium' ); @@ -168,7 +167,7 @@ function Header( { forceIsAutosaveable={ forceIsDirty } /> - { canBeZoomedOut && isEditorIframed && isWideViewport && ( + { canBeZoomedOut && isWideViewport && ( <ZoomOutToggle disabled={ forceDisableBlockTools } /> ) } From 9671f7c34a4e72cbba6a2bdfd375c6c29987cbd7 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 8 Nov 2024 00:57:28 +0900 Subject: [PATCH 1513/1908] Core Commands: Fix add new post URL assignment (#66830) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/core-commands/src/admin-navigation-commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-commands/src/admin-navigation-commands.js b/packages/core-commands/src/admin-navigation-commands.js index 9f0883faa3c17a..8a8167bb29b820 100644 --- a/packages/core-commands/src/admin-navigation-commands.js +++ b/packages/core-commands/src/admin-navigation-commands.js @@ -97,7 +97,7 @@ export function useAdminNavigationCommands() { label: __( 'Add new post' ), icon: plus, callback: () => { - document.location.href = 'post-new.php'; + document.location.assign( 'post-new.php' ); }, } ); From ab6e729daf775ee6065a48c210826af8281a0842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20W=C3=BCnsch?= <soerenwrede@gmail.com> Date: Thu, 7 Nov 2024 17:32:51 +0100 Subject: [PATCH 1514/1908] Iframe: Fix relative wp-content URLs (#66751) Unlinked contributors: tambourine-man, Pat-Relentless, nicolasleroy. Co-authored-by: Soean <soean@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: cweiske <cweiske@git.wordpress.org> Co-authored-by: peterwilsoncc <peterwilsoncc@git.wordpress.org> --- .../block-editor/src/components/iframe/index.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index 85e1f12a7c0d63..76d2e09dfb7a30 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -191,6 +191,22 @@ function Iframe( { preventFileDropDefault, false ); + // Prevent clicks on links from navigating away. Note that links + // inside `contenteditable` are already disabled by the browser, so + // this is for links in blocks outside of `contenteditable`. + iFrameDocument.addEventListener( 'click', ( event ) => { + if ( event.target.tagName === 'A' ) { + event.preventDefault(); + + // Appending a hash to the current URL will not reload the + // page. This is useful for e.g. footnotes. + const href = event.target.getAttribute( 'href' ); + if ( href.startsWith( '#' ) ) { + iFrameDocument.defaultView.location.hash = + href.slice( 1 ); + } + } + } ); } node.addEventListener( 'load', onLoad ); @@ -272,6 +288,7 @@ function Iframe( { <html> <head> <meta charset="utf-8"> + <base href="${ window.location.origin }"> <script>window.frameElement._load()</script> <style> html{ From 457fcf8d331a92ae0c2e83db22c77f18b194da54 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Fri, 8 Nov 2024 14:46:07 +1100 Subject: [PATCH 1515/1908] Process Block Type: Copy deprecation to a new object instead of mutating when stabilizing supports (#66849) * Process Block Type: Copy deprecation to a new object instead of mutating when stabilizing supports * Update stabilizeSupports to carefully construct the newSupports object instead of updating the reference for the typography key Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: Karen Attfield <karenlattfield@gmail.com> --- .../blocks/src/store/process-block-type.js | 47 +++++++++++++------ .../src/store/test/process-block-type.js | 6 +++ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/packages/blocks/src/store/process-block-type.js b/packages/blocks/src/store/process-block-type.js index 8e5b7962adfe17..98fb044f8faadf 100644 --- a/packages/blocks/src/store/process-block-type.js +++ b/packages/blocks/src/store/process-block-type.js @@ -71,17 +71,32 @@ function stabilizeSupports( rawSupports ) { return rawSupports; } - const supports = { ...rawSupports }; - if ( supports?.typography && typeof supports.typography === 'object' ) { - supports.typography = Object.fromEntries( - Object.entries( supports.typography ).map( ( [ key, value ] ) => [ - TYPOGRAPHY_SUPPORTS_EXPERIMENTAL_TO_STABLE[ key ] || key, - value, - ] ) - ); + // Create a new object to avoid mutating the original. This ensures that + // custom block plugins that rely on immutable supports are not affected. + // See: https://github.com/WordPress/gutenberg/pull/66849#issuecomment-2463614281 + const newSupports = {}; + for ( const [ key, value ] of Object.entries( rawSupports ) ) { + if ( + key === 'typography' && + typeof value === 'object' && + value !== null + ) { + newSupports.typography = Object.fromEntries( + Object.entries( value ).map( + ( [ typographyKey, typographyValue ] ) => [ + TYPOGRAPHY_SUPPORTS_EXPERIMENTAL_TO_STABLE[ + typographyKey + ] || typographyKey, + typographyValue, + ] + ) + ); + } else { + newSupports[ key ] = value; + } } - return supports; + return newSupports; } /** @@ -150,10 +165,12 @@ export const processBlockType = if ( settings.deprecated ) { settings.deprecated = settings.deprecated.map( ( deprecation ) => { // Stabilize any experimental supports before applying filters. - deprecation.supports = stabilizeSupports( - deprecation.supports - ); - const filteredDeprecation = // Only keep valid deprecation keys. + let filteredDeprecation = { + ...deprecation, + supports: stabilizeSupports( deprecation.supports ), + }; + + filteredDeprecation = // Only keep valid deprecation keys. applyFilters( 'blocks.registerBlockType', // Merge deprecation keys with pre-filter settings @@ -163,10 +180,10 @@ export const processBlockType = // Omit deprecation keys here so that deprecations // can opt out of specific keys like "supports". ...omit( blockType, DEPRECATED_ENTRY_KEYS ), - ...deprecation, + ...filteredDeprecation, }, blockType.name, - deprecation + filteredDeprecation ); // Re-stabilize any experimental supports after applying filters. // This ensures that any supports updated by filters are also stabilized. diff --git a/packages/blocks/src/store/test/process-block-type.js b/packages/blocks/src/store/test/process-block-type.js index 3c6838e311f778..c82d08cc45d651 100644 --- a/packages/blocks/src/store/test/process-block-type.js +++ b/packages/blocks/src/store/test/process-block-type.js @@ -215,6 +215,12 @@ describe( 'processBlockType', () => { ], }; + // Freeze the deprecated block object and its supports so that the original is not mutated. + // This ensures the test covers a regression where the original object was mutated. + // See: https://github.com/WordPress/gutenberg/pull/63401#discussion_r1832394335. + Object.freeze( blockSettings.deprecated[ 0 ] ); + Object.freeze( blockSettings.deprecated[ 0 ].supports ); + const processedBlockType = processBlockType( 'test/block', blockSettings From 54aaec60c715ed58401839d43690152b6f35146d Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Fri, 8 Nov 2024 05:59:09 +0200 Subject: [PATCH 1516/1908] Image: Add `aria-haspopup` prop write mode `more` tools menu items (#66815) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- packages/block-library/src/image/image.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 61baba2263989c..b4d269f9678221 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -135,6 +135,7 @@ function ContentOnlyControls( { setIsAltDialogOpen( true ); onClose(); } } + aria-haspopup="dialog" > { _x( 'Alternative text', @@ -146,6 +147,7 @@ function ContentOnlyControls( { setIsTitleDialogOpen( true ); onClose(); } } + aria-haspopup="dialog" > { __( 'Title text' ) } </MenuItem> From bee12b193887ad3b6fe40d85a20970d3468322b7 Mon Sep 17 00:00:00 2001 From: Amit Raj <77401999+amitraj2203@users.noreply.github.com> Date: Fri, 8 Nov 2024 14:06:41 +0530 Subject: [PATCH 1517/1908] adds anchor support in details block (#66734) Co-authored-by: amitraj2203 <amitraj2203@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: skorasaurus <skorasaurus@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- packages/block-library/src/details/block.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 4db90e9b2f8142..a27de8211c824a 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -254,7 +254,7 @@ Hide and show additional content. ([Source](https://github.com/WordPress/gutenbe - **Name:** core/details - **Category:** text -- **Supports:** align (full, wide), color (background, gradients, link, text), interactivity (clientNavigation), layout (~~allowEditing~~), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~ +- **Supports:** align (full, wide), anchor, color (background, gradients, link, text), interactivity (clientNavigation), layout (~~allowEditing~~), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~ - **Attributes:** showContent, summary ## Embed diff --git a/packages/block-library/src/details/block.json b/packages/block-library/src/details/block.json index a488ae1fa73a79..0cd0040cdde1b9 100644 --- a/packages/block-library/src/details/block.json +++ b/packages/block-library/src/details/block.json @@ -21,6 +21,7 @@ "supports": { "__experimentalOnEnter": true, "align": [ "wide", "full" ], + "anchor": true, "color": { "gradients": true, "link": true, From 706691e43928ae55e47db14cc63e2d9f71014436 Mon Sep 17 00:00:00 2001 From: Miguel Fonseca <150562+mcsf@users.noreply.github.com> Date: Fri, 8 Nov 2024 09:19:55 +0000 Subject: [PATCH 1518/1908] Block Editor: Fix stale dependencies of selectors depending on editorTool preference (#66833) * Block Editor: Fix dependencies of selectors depending on editorTool pref The `state.editorMode` reducer was removed in 65945 in favour of persisted user preferences. Selector `__unstableGetEditorMode` should be used instead. This commit fixes a bug wherein changes to `editorTool` don't trigger a re-render of the block list view. * Update selectors that use __unstableGetEditorMode as a dependency to be registry selectors * Update other selector * Fix tests --------- Co-authored-by: Daniel Richards <daniel.richards@automattic.com> --- .../src/store/private-selectors.js | 11 +-- packages/block-editor/src/store/selectors.js | 95 ++++++++++--------- .../src/store/test/private-selectors.js | 5 + packages/block-editor/src/store/utils.js | 23 ++--- 4 files changed, 74 insertions(+), 60 deletions(-) diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 525aca4c236cbc..f1b5abd7789a11 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -109,17 +109,16 @@ function getEnabledClientIdsTreeUnmemoized( state, rootClientId ) { * * @return {Object[]} Tree of block objects with only clientID and innerBlocks set. */ -export const getEnabledClientIdsTree = createSelector( - getEnabledClientIdsTreeUnmemoized, - ( state ) => [ +export const getEnabledClientIdsTree = createRegistrySelector( ( select ) => + createSelector( getEnabledClientIdsTreeUnmemoized, ( state ) => [ state.blocks.order, state.blockEditingModes, state.settings.templateLock, state.blockListSettings, - state.editorMode, + select( STORE_NAME ).__unstableGetEditorMode( state ), state.zoomLevel, getSectionRootClientId( state ), - ] + ] ) ); /** @@ -317,7 +316,7 @@ export const hasAllowedPatterns = createRegistrySelector( ( select ) => }, ( state, rootClientId ) => [ ...getAllPatternsDependants( select )( state ), - ...getInsertBlockTypeDependants( state, rootClientId ), + ...getInsertBlockTypeDependants( select )( state, rootClientId ), ] ) ); diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index b09c3d3d01b165..598b6b4ea480de 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -1794,10 +1794,12 @@ const canInsertBlockTypeUnmemoized = ( * * @return {boolean} Whether the given block type is allowed to be inserted. */ -export const canInsertBlockType = createSelector( - canInsertBlockTypeUnmemoized, - ( state, blockName, rootClientId ) => - getInsertBlockTypeDependants( state, rootClientId ) +export const canInsertBlockType = createRegistrySelector( ( select ) => + createSelector( + canInsertBlockTypeUnmemoized, + ( state, blockName, rootClientId ) => + getInsertBlockTypeDependants( select )( state, rootClientId ) + ) ); /** @@ -2224,7 +2226,7 @@ export const getInserterItems = createRegistrySelector( ( select ) => unlock( select( STORE_NAME ) ).getReusableBlocks(), state.blocks.order, state.preferences.insertUsage, - ...getInsertBlockTypeDependants( state, rootClientId ), + ...getInsertBlockTypeDependants( select )( state, rootClientId ), ] ) ); @@ -2255,44 +2257,51 @@ export const getInserterItems = createRegistrySelector( ( select ) => * this item. * @property {number} frecency Heuristic that combines frequency and recency. */ -export const getBlockTransformItems = createSelector( - ( state, blocks, rootClientId = null ) => { - const normalizedBlocks = Array.isArray( blocks ) ? blocks : [ blocks ]; - const buildBlockTypeTransformItem = buildBlockTypeItem( state, { - buildScope: 'transform', - } ); - const blockTypeTransformItems = getBlockTypes() - .filter( ( blockType ) => - canIncludeBlockTypeInInserter( state, blockType, rootClientId ) - ) - .map( buildBlockTypeTransformItem ); +export const getBlockTransformItems = createRegistrySelector( ( select ) => + createSelector( + ( state, blocks, rootClientId = null ) => { + const normalizedBlocks = Array.isArray( blocks ) + ? blocks + : [ blocks ]; + const buildBlockTypeTransformItem = buildBlockTypeItem( state, { + buildScope: 'transform', + } ); + const blockTypeTransformItems = getBlockTypes() + .filter( ( blockType ) => + canIncludeBlockTypeInInserter( + state, + blockType, + rootClientId + ) + ) + .map( buildBlockTypeTransformItem ); - const itemsByName = Object.fromEntries( - Object.entries( blockTypeTransformItems ).map( ( [ , value ] ) => [ - value.name, - value, - ] ) - ); + const itemsByName = Object.fromEntries( + Object.entries( blockTypeTransformItems ).map( + ( [ , value ] ) => [ value.name, value ] + ) + ); - const possibleTransforms = getPossibleBlockTransformations( - normalizedBlocks - ).reduce( ( accumulator, block ) => { - if ( itemsByName[ block?.name ] ) { - accumulator.push( itemsByName[ block.name ] ); - } - return accumulator; - }, [] ); - return orderBy( - possibleTransforms, - ( block ) => itemsByName[ block.name ].frecency, - 'desc' - ); - }, - ( state, blocks, rootClientId ) => [ - getBlockTypes(), - state.preferences.insertUsage, - ...getInsertBlockTypeDependants( state, rootClientId ), - ] + const possibleTransforms = getPossibleBlockTransformations( + normalizedBlocks + ).reduce( ( accumulator, block ) => { + if ( itemsByName[ block?.name ] ) { + accumulator.push( itemsByName[ block.name ] ); + } + return accumulator; + }, [] ); + return orderBy( + possibleTransforms, + ( block ) => itemsByName[ block.name ].frecency, + 'desc' + ); + }, + ( state, blocks, rootClientId ) => [ + getBlockTypes(), + state.preferences.insertUsage, + ...getInsertBlockTypeDependants( select )( state, rootClientId ), + ] + ) ); /** @@ -2360,7 +2369,7 @@ export const getAllowedBlocks = createRegistrySelector( ( select ) => ( state, rootClientId ) => [ getBlockTypes(), unlock( select( STORE_NAME ) ).getReusableBlocks(), - ...getInsertBlockTypeDependants( state, rootClientId ), + ...getInsertBlockTypeDependants( select )( state, rootClientId ), ] ) ); @@ -2435,7 +2444,7 @@ export const __experimentalGetParsedPattern = createRegistrySelector( const getAllowedPatternsDependants = ( select ) => ( state, rootClientId ) => [ ...getAllPatternsDependants( select )( state ), - ...getInsertBlockTypeDependants( state, rootClientId ), + ...getInsertBlockTypeDependants( select )( state, rootClientId ), ]; const patternsWithParsedBlocks = new WeakMap(); diff --git a/packages/block-editor/src/store/test/private-selectors.js b/packages/block-editor/src/store/test/private-selectors.js index 73c14faa6fd065..fb1d736e175af0 100644 --- a/packages/block-editor/src/store/test/private-selectors.js +++ b/packages/block-editor/src/store/test/private-selectors.js @@ -292,6 +292,11 @@ describe( 'private selectors', () => { '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f': {}, }, }; + getEnabledClientIdsTree.registry = { + select: jest.fn( () => ( { + __unstableGetEditorMode: () => 'edit', + } ) ), + }; it( 'should return tree containing only clientId and innerBlocks', () => { const state = { diff --git a/packages/block-editor/src/store/utils.js b/packages/block-editor/src/store/utils.js index 9b83a8f74cf9aa..bdf8e3675edff1 100644 --- a/packages/block-editor/src/store/utils.js +++ b/packages/block-editor/src/store/utils.js @@ -110,14 +110,15 @@ export const getAllPatternsDependants = ( select ) => ( state ) => { ]; }; -export function getInsertBlockTypeDependants( state, rootClientId ) { - return [ - state.blockListSettings[ rootClientId ], - state.blocks.byClientId.get( rootClientId ), - state.settings.allowedBlockTypes, - state.settings.templateLock, - state.blockEditingModes, - state.editorMode, - getSectionRootClientId( state ), - ]; -} +export const getInsertBlockTypeDependants = + ( select ) => ( state, rootClientId ) => { + return [ + state.blockListSettings[ rootClientId ], + state.blocks.byClientId.get( rootClientId ), + state.settings.allowedBlockTypes, + state.settings.templateLock, + state.blockEditingModes, + select( STORE_NAME ).__unstableGetEditorMode( state ), + getSectionRootClientId( state ), + ]; + }; From 93a025d08383ab67c0d5eebd4e624d151420f2c2 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Fri, 8 Nov 2024 11:54:39 +0200 Subject: [PATCH 1519/1908] Update Commands docs with the existing contexts (#66860) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/commands/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/commands/README.md b/packages/commands/README.md index 946b101e9ef27d..b7382f98a8c848 100644 --- a/packages/commands/README.md +++ b/packages/commands/README.md @@ -26,11 +26,13 @@ For example, when a user types "contact", the Command Palette needs to filter th Static and dynamic commands can be contextual. This means that in a given context (for example, when navigating the Site Editor or editing a template), some specific commands are given more priority and are visible as soon as you open the Command Palette. Also, when typing the Command Palette, these contextual commands are shown above the rest of the commands. -At the moment, two contexts have been implemented: +At the moment, three contexts have been implemented: - `site-editor`: This is the context that is set when you are navigating in the site editor (sidebar visible). -- `site-editor-edit`: This is the context that is set when you are editing a document (template, template part or page) in the site editor. - As the usage of the Command Palette expands, more contexts will be added. +- `entity-edit`: This is the context that is set when you are editing a document (template, template part or page). +- `block-selection-edit`: This is the context that is set when a block is selected. + +As the usage of the Command Palette expands, more contexts will be added. Attaching a command or command loader to a given context is as simple as adding the `context` property (with the right context value from the available contexts above) to the `useCommand` or `useCommandLoader` calls. From 3a2977150d86f9166f4175c6b0e0753ab7f2256a Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Fri, 8 Nov 2024 12:04:51 +0200 Subject: [PATCH 1520/1908] Remove unnecessary boolean assignments (#66857) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> --- packages/block-library/src/cover/edit/index.js | 2 +- packages/block-library/src/paragraph/edit.js | 2 +- packages/block-library/src/search/index.php | 4 ++-- packages/components/CHANGELOG.md | 1 + .../src/border-control/border-control-dropdown/component.tsx | 2 +- packages/docgen/lib/index.js | 2 +- packages/e2e-test-utils-playwright/src/request-utils/rest.ts | 2 +- packages/media-utils/src/components/media-upload/index.js | 2 +- 8 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/block-library/src/cover/edit/index.js b/packages/block-library/src/cover/edit/index.js index 1202f28cee50cd..1c86d953bc0bab 100644 --- a/packages/block-library/src/cover/edit/index.js +++ b/packages/block-library/src/cover/edit/index.js @@ -471,7 +471,7 @@ function CoverEdit( { setAttributes( { minHeight: newMinHeight } ); }, // Hide the resize handle if an aspect ratio is set, as the aspect ratio takes precedence. - showHandle: ! attributes.style?.dimensions?.aspectRatio ? true : false, + showHandle: ! attributes.style?.dimensions?.aspectRatio, size: resizableBoxDimensions, width, }; diff --git a/packages/block-library/src/paragraph/edit.js b/packages/block-library/src/paragraph/edit.js index b7f4283d4ec671..b0dc5ab255af78 100644 --- a/packages/block-library/src/paragraph/edit.js +++ b/packages/block-library/src/paragraph/edit.js @@ -83,7 +83,7 @@ function DropCapControl( { clientId, attributes, setAttributes } ) { checked={ !! dropCap } onChange={ () => setAttributes( { dropCap: ! dropCap } ) } help={ helpText } - disabled={ hasDropCapDisabled( align ) ? true : false } + disabled={ hasDropCapDisabled( align ) } /> </ToolsPanelItem> ); diff --git a/packages/block-library/src/search/index.php b/packages/block-library/src/search/index.php index e4259bb0ce2c7f..b74daf548a8025 100644 --- a/packages/block-library/src/search/index.php +++ b/packages/block-library/src/search/index.php @@ -31,8 +31,8 @@ function render_block_core_search( $attributes ) { $input_id = wp_unique_id( 'wp-block-search__input-' ); $classnames = classnames_for_block_core_search( $attributes ); - $show_label = ( ! empty( $attributes['showLabel'] ) ) ? true : false; - $use_icon_button = ( ! empty( $attributes['buttonUseIcon'] ) ) ? true : false; + $show_label = ! empty( $attributes['showLabel'] ); + $use_icon_button = ! empty( $attributes['buttonUseIcon'] ); $show_button = ( ! empty( $attributes['buttonPosition'] ) && 'no-button' === $attributes['buttonPosition'] ) ? false : true; $button_position = $show_button ? $attributes['buttonPosition'] : null; $query_params = ( ! empty( $attributes['query'] ) ) ? $attributes['query'] : array(); diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 93b191bff269d6..97cb5d117e17d2 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -17,6 +17,7 @@ ### Internal - `Snackbar`: Use link variant for action Button ([#66560](https://github.com/WordPress/gutenberg/pull/66560)). +- `BorderControl`: Remove unnecessary boolean assignments ([#66857](https://github.com/WordPress/gutenberg/pull/66857)). ## 28.11.0 (2024-10-30) diff --git a/packages/components/src/border-control/border-control-dropdown/component.tsx b/packages/components/src/border-control/border-control-dropdown/component.tsx index 827e7973a90432..707497ae2993c0 100644 --- a/packages/components/src/border-control/border-control-dropdown/component.tsx +++ b/packages/components/src/border-control/border-control-dropdown/component.tsx @@ -188,7 +188,7 @@ const BorderControlDropdown = ( tooltipPosition={ dropdownPosition } label={ __( 'Border color and style picker' ) } showTooltip - __next40pxDefaultSize={ size === '__unstable-large' ? true : false } + __next40pxDefaultSize={ size === '__unstable-large' } > <span className={ indicatorWrapperClassName }> <ColorIndicator diff --git a/packages/docgen/lib/index.js b/packages/docgen/lib/index.js index 42416d9b452388..86c230f1e901aa 100644 --- a/packages/docgen/lib/index.js +++ b/packages/docgen/lib/index.js @@ -106,7 +106,7 @@ module.exports = ( sourceFile, options ) => { } sourceFile = path.join( processDir, sourceFile ); - const debugMode = options.debug ? true : false; + const debugMode = options.debug; const inputBase = path.join( path.dirname( sourceFile ), diff --git a/packages/e2e-test-utils-playwright/src/request-utils/rest.ts b/packages/e2e-test-utils-playwright/src/request-utils/rest.ts index 79b49dc3c7b646..45032947d7cc52 100644 --- a/packages/e2e-test-utils-playwright/src/request-utils/rest.ts +++ b/packages/e2e-test-utils-playwright/src/request-utils/rest.ts @@ -58,7 +58,7 @@ async function setupRest( this: RequestUtils ): Promise< StorageState > { return error; } - return nonce && rootURL ? true : false; + return !! ( nonce && rootURL ); }, { message: 'Failed to setup REST API.', diff --git a/packages/media-utils/src/components/media-upload/index.js b/packages/media-utils/src/components/media-upload/index.js index ed0a59ddbc684a..4067193f176062 100644 --- a/packages/media-utils/src/components/media-upload/index.js +++ b/packages/media-utils/src/components/media-upload/index.js @@ -327,7 +327,7 @@ class MediaUpload extends Component { state: currentState, multiple, selection, - editing: value && value.length ? true : false, + editing: !! value?.length, } ); wp.media.frame = this.frame; this.initializeListeners(); From 77166e021b3f8435ef615880ac6066e9b32f8f65 Mon Sep 17 00:00:00 2001 From: Utsav Patel <75293077+up1512001@users.noreply.github.com> Date: Fri, 8 Nov 2024 15:59:17 +0530 Subject: [PATCH 1521/1908] update: Add Media to Add media in cover block (#66835) Co-authored-by: up1512001 <up1512001@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/block-library/src/cover/edit/block-controls.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/cover/edit/block-controls.js b/packages/block-library/src/cover/edit/block-controls.js index 041566c0a51971..8a4db747990681 100644 --- a/packages/block-library/src/cover/edit/block-controls.js +++ b/packages/block-library/src/cover/edit/block-controls.js @@ -101,7 +101,7 @@ export default function CoverBlockControls( { onSelect={ onSelectMedia } onToggleFeaturedImage={ toggleUseFeaturedImage } useFeaturedImage={ useFeaturedImage } - name={ ! url ? __( 'Add Media' ) : __( 'Replace' ) } + name={ ! url ? __( 'Add media' ) : __( 'Replace' ) } onReset={ onClearMedia } /> </BlockControls> From 55a44fdf6de90a3fb4c86b4e36f679db10b0f182 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Fri, 8 Nov 2024 12:12:10 +0000 Subject: [PATCH 1522/1908] Bump plugin version to 19.6.1 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 89e65de4e94794..eed059a15c9a35 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.6.0 + * Version: 19.6.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 80abc752c92120..0bb48c55c5326c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.6.0", + "version": "19.6.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.6.0", + "version": "19.6.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", "workspaces": [ diff --git a/package.json b/package.json index 741475d8177705..0fdb7ad563cd15 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.6.0", + "version": "19.6.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 36f0847df7bc8833056427db1a48ed6c447f1255 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Fri, 8 Nov 2024 12:27:10 +0000 Subject: [PATCH 1523/1908] Update Changelog for 19.6.1 --- changelog.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/changelog.txt b/changelog.txt index bcbfbb2dc48449..0dc99f5e205e32 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,25 @@ == Changelog == += 19.6.1 = + + +## Changelog + +### Bug Fixes + +#### List View +- Block Editor: Fix stale dependencies of selectors depending on editorTool preference. ([66833](https://github.com/WordPress/gutenberg/pull/66833)) + + + + +## Contributors + +The following contributors merged PRs in this release: + +@mcsf + + = 19.6.0 = From f1a4f1cef8e17262e976c282bb5bc2c7591e5549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Juh=C3=A9=20Lluveras?= <contact@albertjuhe.com> Date: Fri, 8 Nov 2024 14:18:47 +0100 Subject: [PATCH 1524/1908] Fix flash when clicking template name in the editor when a plugin registered template matches a default WP theme template (#66359) * Fix _gutenberg_get_block_templates_files() so it returns the 'page' template from the theme when 'page' post type templates are queried * Try different approach: don't use query to get the templates reference to use for filtering * Only unset post_type from the query * Add backport file --- backport-changelog/6.7/7676.md | 3 +++ lib/compat/wordpress-6.7/compat.php | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 backport-changelog/6.7/7676.md diff --git a/backport-changelog/6.7/7676.md b/backport-changelog/6.7/7676.md new file mode 100644 index 00000000000000..19d9dc59048457 --- /dev/null +++ b/backport-changelog/6.7/7676.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7676 + +* https://github.com/WordPress/gutenberg/pull/66359 diff --git a/lib/compat/wordpress-6.7/compat.php b/lib/compat/wordpress-6.7/compat.php index cd533a42cc528e..e58eca56ef71f9 100644 --- a/lib/compat/wordpress-6.7/compat.php +++ b/lib/compat/wordpress-6.7/compat.php @@ -40,7 +40,13 @@ function _gutenberg_add_block_templates_from_registry( $query_result, $query, $t } if ( ! isset( $query['wp_id'] ) ) { - $template_files = _gutenberg_get_block_templates_files( $template_type, $query ); + // We need to unset the post_type query param because some templates + // would be excluded otherwise, like `page.html` when looking for + // `page` templates. + // See: https://github.com/WordPress/gutenberg/issues/65584 + $template_files_query = $query; + unset( $template_files_query['post_type'] ); + $template_files = _gutenberg_get_block_templates_files( $template_type, $template_files_query ); /* * Add templates registered in the template registry. Filtering out the ones which have a theme file. From 1a1db8b014bcc431fb99e0df8e7624c8df48c12a Mon Sep 17 00:00:00 2001 From: Matias Benedetto <matias.benedetto@gmail.com> Date: Fri, 8 Nov 2024 12:21:03 -0300 Subject: [PATCH 1525/1908] Update placeholder text for blocks that support drag and drop (#66842) * update image block * update gallery block * update cover block * update audio block * update video block * update file block * update media and text block * resolve other image and video fallbacks * remove 1:1 cover placeholder override * small clean up * tweak for gallery --------- Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: up1512001 <up1512001@git.wordpress.org> --- .../src/components/media-placeholder/index.js | 8 ++++---- .../block-library/src/cover/edit/cover-placeholder.js | 3 --- packages/block-library/src/file/edit.js | 2 +- packages/block-library/src/gallery/edit.js | 2 +- packages/block-library/src/image/edit.js | 2 +- packages/block-library/src/video/edit.js | 2 +- 6 files changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index f16e4317227235..07a3f8829e71d1 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -317,20 +317,20 @@ export function MediaPlaceholder( { if ( instructions === undefined && mediaUpload ) { instructions = __( - 'Upload a media file or pick one from your media library.' + 'Drag and drop an image or video, upload, or choose from your library.' ); if ( isAudio ) { instructions = __( - 'Upload or drag an audio file here, or pick one from your library.' + 'Drag and drop an audio file, upload, or choose from your library.' ); } else if ( isImage ) { instructions = __( - 'Upload or drag an image file here, or pick one from your library.' + 'Drag and drop an image, upload, or choose from your library.' ); } else if ( isVideo ) { instructions = __( - 'Upload or drag a video file here, or pick one from your library.' + 'Drag and drop a video, upload, or choose from your library.' ); } } diff --git a/packages/block-library/src/cover/edit/cover-placeholder.js b/packages/block-library/src/cover/edit/cover-placeholder.js index fc3502bd924299..57a1a7c495cd72 100644 --- a/packages/block-library/src/cover/edit/cover-placeholder.js +++ b/packages/block-library/src/cover/edit/cover-placeholder.js @@ -23,9 +23,6 @@ export default function CoverPlaceholder( { icon={ <BlockIcon icon={ icon } /> } labels={ { title: __( 'Cover' ), - instructions: __( - 'Drag and drop onto this block, upload, or select existing media from your library.' - ), } } onSelect={ onSelectMedia } accept="image/*,video/*" diff --git a/packages/block-library/src/file/edit.js b/packages/block-library/src/file/edit.js index 59e660dd3211f1..937eb3d28eb192 100644 --- a/packages/block-library/src/file/edit.js +++ b/packages/block-library/src/file/edit.js @@ -201,7 +201,7 @@ function FileEdit( { attributes, isSelected, setAttributes, clientId } ) { labels={ { title: __( 'File' ), instructions: __( - 'Upload a file or pick one from your media library.' + 'Drag and drop a file, upload, or choose from your library.' ), } } onSelect={ onSelectFile } diff --git a/packages/block-library/src/gallery/edit.js b/packages/block-library/src/gallery/edit.js index d3ec2ce007e6a9..01e725cc16cde6 100644 --- a/packages/block-library/src/gallery/edit.js +++ b/packages/block-library/src/gallery/edit.js @@ -96,7 +96,7 @@ const ALLOWED_MEDIA_TYPES = [ 'image' ]; const PLACEHOLDER_TEXT = Platform.isNative ? __( 'Add media' ) - : __( 'Drag images, upload new ones or select files from your library.' ); + : __( 'Drag and drop images, upload, or choose from your library.' ); const MOBILE_CONTROL_PROPS_RANGE_CONTROL = Platform.isNative ? { type: 'stepper' } diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index 360c4b8e6127b8..e08d0baff0503d 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -411,7 +411,7 @@ export function ImageEdit( { ! lockUrlControls && ! isSmallContainer && __( - 'Upload or drag an image file here, or pick one from your library.' + 'Drag and drop an image, upload, or choose from your library.' ) } style={ { diff --git a/packages/block-library/src/video/edit.js b/packages/block-library/src/video/edit.js index ba6b4c869aefcb..32221919c7ea20 100644 --- a/packages/block-library/src/video/edit.js +++ b/packages/block-library/src/video/edit.js @@ -141,7 +141,7 @@ function VideoEdit( { icon={ icon } label={ __( 'Video' ) } instructions={ __( - 'Upload a video file, pick one from your media library, or add one with a URL.' + 'Drag and drop a video, upload, or choose from your library.' ) } > { content } From 55913fe1e86e2891b4f86aa1cf1cfae8b9cf5e25 Mon Sep 17 00:00:00 2001 From: Benni <109149472+benniledl@users.noreply.github.com> Date: Sun, 10 Nov 2024 13:47:41 +0100 Subject: [PATCH 1526/1908] Add 6.6.2 to Version in WordPress (#66870) Update versions-in-wordpress.md Co-authored-by: benniledl <benniledl@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- docs/contributors/versions-in-wordpress.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/contributors/versions-in-wordpress.md b/docs/contributors/versions-in-wordpress.md index 62347f2d644a61..4ba7b34da15552 100644 --- a/docs/contributors/versions-in-wordpress.md +++ b/docs/contributors/versions-in-wordpress.md @@ -7,6 +7,7 @@ If anything looks incorrect here, please bring it up in #core-editor in [WordPre | Gutenberg Versions | WordPress Version | | ------------------ | ----------------- | | 18.6-19.3 | 6.7 | +| 17.8-18.5 | 6.6.2 | | 17.8-18.5 | 6.6.1 | | 17.8-18.5 | 6.6 | | 16.8-17.7 | 6.5.5 | From dd042a265afc0d4679858220441dd45c98b27ed3 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Mon, 11 Nov 2024 08:50:37 +0100 Subject: [PATCH 1527/1908] Popover: Fix missing label of the headerTitle Close button. (#66813) * Popover: Fix missing label of the headerTitle Close button. * Add changelog entry. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/popover/index.tsx | 2 ++ 2 files changed, 6 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 97cb5d117e17d2..abd32b37c4c650 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,10 @@ - `Radio`: Deprecate 36px default size ([#66572](https://github.com/WordPress/gutenberg/pull/66572)). +### Bug Fixes + +- `Popover`: Fix missing label of the headerTitle Close button ([#66813](https://github.com/WordPress/gutenberg/pull/66813)). + ### Enhancements - `MenuItem`: Add 40px size prop on Button ([#66596](https://github.com/WordPress/gutenberg/pull/66596)). diff --git a/packages/components/src/popover/index.tsx b/packages/components/src/popover/index.tsx index 1b7fb31539c6d0..7db476db6b1db1 100644 --- a/packages/components/src/popover/index.tsx +++ b/packages/components/src/popover/index.tsx @@ -39,6 +39,7 @@ import { import { close } from '@wordpress/icons'; import deprecated from '@wordpress/deprecated'; import { Path, SVG } from '@wordpress/primitives'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -422,6 +423,7 @@ const UnforwardedPopover = ( size="small" icon={ close } onClick={ onClose } + label={ __( 'Close' ) } /> </div> ) } From 17a18097fa7943d0c889e1b4d0c74cd4090b6fa3 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Mon, 11 Nov 2024 20:21:25 +1100 Subject: [PATCH 1528/1908] Style book:reduce margin selector specificity to avoid overriding global block styles (#66895) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/edit-site/src/components/style-book/constants.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/edit-site/src/components/style-book/constants.ts b/packages/edit-site/src/components/style-book/constants.ts index 6aa280c937d42d..9aace34e64cbf1 100644 --- a/packages/edit-site/src/components/style-book/constants.ts +++ b/packages/edit-site/src/components/style-book/constants.ts @@ -254,11 +254,10 @@ export const STYLE_BOOK_IFRAME_STYLES = ` .edit-site-style-book__example-preview .block-list-appender { display: none; } - - .edit-site-style-book__example-preview .is-root-container > .wp-block:first-child { + :where(.is-root-container > .wp-block:first-child) { margin-top: 0; } - .edit-site-style-book__example-preview .is-root-container > .wp-block:last-child { + :where(.is-root-container > .wp-block:last-child) { margin-bottom: 0; } `; From de5262393ca74a542e1eea04ea8c48ed4c270e7d Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 11 Nov 2024 10:44:50 +0100 Subject: [PATCH 1529/1908] Inserter: Add 'Starter Content' category to the inserter (#66819) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> --- .../block-patterns-tab/pattern-category-previews.js | 8 ++++++++ .../inserter/block-patterns-tab/use-pattern-categories.js | 8 ++++++++ .../src/components/inserter/block-patterns-tab/utils.js | 5 +++++ 3 files changed, 21 insertions(+) diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js index 2c5d96d5ff9733..a19a579ae5c0cf 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js @@ -31,6 +31,7 @@ import { isPatternFiltered, allPatternsCategory, myPatternsCategory, + starterPatternsCategory, INSERTER_PATTERN_TYPES, } from './utils'; import { store as blockEditorStore } from '../../../store'; @@ -86,6 +87,13 @@ export function PatternCategoryPreviews( { return true; } + if ( + category.name === starterPatternsCategory.name && + pattern.blockTypes?.includes( 'core/post-content' ) + ) { + return true; + } + if ( category.name === 'uncategorized' ) { // The uncategorized category should show all the patterns without any category... if ( ! pattern.categories ) { diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/use-pattern-categories.js b/packages/block-editor/src/components/inserter/block-patterns-tab/use-pattern-categories.js index cff5fbf3413820..2adc6b48579dd7 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/use-pattern-categories.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/use-pattern-categories.js @@ -14,6 +14,7 @@ import { isPatternFiltered, allPatternsCategory, myPatternsCategory, + starterPatternsCategory, INSERTER_PATTERN_TYPES, } from './utils'; @@ -67,6 +68,13 @@ export function usePatternCategories( rootClientId, sourceFilter = 'all' ) { label: _x( 'Uncategorized' ), } ); } + if ( + filteredPatterns.some( ( pattern ) => + pattern.blockTypes?.includes( 'core/post-content' ) + ) + ) { + categories.unshift( starterPatternsCategory ); + } if ( filteredPatterns.some( ( pattern ) => pattern.type === INSERTER_PATTERN_TYPES.user diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/utils.js b/packages/block-editor/src/components/inserter/block-patterns-tab/utils.js index f8ba47f3790e14..58065ac33ad2b5 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/utils.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/utils.js @@ -25,6 +25,11 @@ export const myPatternsCategory = { label: __( 'My patterns' ), }; +export const starterPatternsCategory = { + name: 'core/starter-content', + label: __( 'Starter Content' ), +}; + export function isPatternFiltered( pattern, sourceFilter, syncFilter ) { const isUserPattern = pattern.name.startsWith( 'core/block' ); const isDirectoryPattern = From c9e4eab4b7bc8df076bad584c2b16ef06fdc210c Mon Sep 17 00:00:00 2001 From: Carolina Nymark <myazalea@hotmail.com> Date: Mon, 11 Nov 2024 11:47:14 +0100 Subject: [PATCH 1530/1908] Fix TypeError when duplicating uncategorized theme patterns (#66889) * Fix TypeError when duplicating uncategorized patterns Only try to match the pattern categories and get the category label if the theme pattern uses the optional `categories` parameter. Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- packages/patterns/src/components/duplicate-pattern-modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/patterns/src/components/duplicate-pattern-modal.js b/packages/patterns/src/components/duplicate-pattern-modal.js index 2b51e82f22da4e..70fb0830e0f1cc 100644 --- a/packages/patterns/src/components/duplicate-pattern-modal.js +++ b/packages/patterns/src/components/duplicate-pattern-modal.js @@ -17,7 +17,7 @@ function getTermLabels( pattern, categories ) { if ( pattern.type !== PATTERN_TYPES.user ) { return categories.core ?.filter( ( category ) => - pattern.categories.includes( category.name ) + pattern.categories?.includes( category.name ) ) .map( ( category ) => category.label ); } From 249c0cf495ed89df95e039572974bc948fa89731 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 11 Nov 2024 12:51:47 +0100 Subject: [PATCH 1531/1908] Revert: Fix unable to remove empty blocks on merge (#65262) + alternative (#66564) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: kspilarski <kel-dc@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../src/components/block-list/block.js | 76 +++++++------------ packages/blocks/README.md | 4 - packages/blocks/src/api/index.js | 9 --- packages/blocks/src/api/utils.js | 68 ++++------------- .../editor/various/splitting-merging.spec.js | 19 +++-- 5 files changed, 56 insertions(+), 120 deletions(-) diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 2215625596dc5c..6d4655189d9723 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -24,8 +24,8 @@ import { isReusableBlock, getBlockDefaultClassName, hasBlockSupport, + createBlock, store as blocksStore, - privateApis as blocksPrivateApis, } from '@wordpress/blocks'; import { withFilters } from '@wordpress/components'; import { withDispatch, useDispatch, useSelect } from '@wordpress/data'; @@ -47,8 +47,6 @@ import { PrivateBlockContext } from './private-block-context'; import { unlock } from '../../lock-unlock'; -const { isUnmodifiedBlockContent } = unlock( blocksPrivateApis ); - /** * Merges wrapper props with special handling for classNames and styles. * @@ -313,6 +311,7 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => { function switchToDefaultOrRemove() { const block = getBlock( clientId ); const defaultBlockName = getDefaultBlockName(); + const defaultBlockType = getBlockType( defaultBlockName ); if ( getBlockName( clientId ) !== defaultBlockName ) { const replacement = switchToBlockType( block, @@ -329,6 +328,15 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => { selectBlock( nextBlockClientId ); } ); } + } else if ( defaultBlockType.merge ) { + const attributes = defaultBlockType.merge( + {}, + block.attributes + ); + replaceBlocks( + [ clientId ], + [ createBlock( defaultBlockName, attributes ) ] + ); } } @@ -342,6 +350,9 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => { * to the moved block. */ function moveFirstItemUp( _clientId, changeSelection = true ) { + const wrapperBlockName = getBlockName( _clientId ); + const wrapperBlockType = getBlockType( wrapperBlockName ); + const isTextualWrapper = wrapperBlockType.category === 'text'; const targetRootClientId = getBlockRootClientId( _clientId ); const blockOrder = getBlockOrder( _clientId ); const [ firstClientId ] = blockOrder; @@ -351,50 +362,14 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => { isUnmodifiedBlock( getBlock( firstClientId ) ) ) { removeBlock( _clientId ); - } else { + } else if ( isTextualWrapper ) { registry.batch( () => { - const firstBlock = getBlock( firstClientId ); - const isFirstBlockContentUnmodified = - isUnmodifiedBlockContent( firstBlock ); - const defaultBlockName = getDefaultBlockName(); - const replacement = switchToBlockType( - firstBlock, - defaultBlockName - ); - const canTransformToDefaultBlock = - !! replacement?.length && - replacement.every( ( block ) => - canInsertBlockType( block.name, _clientId ) - ); - if ( - isFirstBlockContentUnmodified && - canTransformToDefaultBlock - ) { - // Step 1: If the block is empty and can be transformed to the default block type. - replaceBlocks( - firstClientId, - replacement, - changeSelection - ); - } else if ( - isFirstBlockContentUnmodified && - firstBlock.name === defaultBlockName - ) { - // Step 2: If the block is empty and is already the default block type. - removeBlock( firstClientId ); - const nextBlockClientId = - getNextBlockClientId( clientId ); - if ( nextBlockClientId ) { - selectBlock( nextBlockClientId ); - } - } else if ( canInsertBlockType( - firstBlock.name, + getBlockName( firstClientId ), targetRootClientId ) ) { - // Step 3: If the block can be moved up. moveBlocksToPosition( [ firstClientId ], _clientId, @@ -402,17 +377,21 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => { getBlockIndex( _clientId ) ); } else { - const canLiftAndTransformToDefaultBlock = - !! replacement?.length && + const replacement = switchToBlockType( + getBlock( firstClientId ), + getDefaultBlockName() + ); + + if ( + replacement && + replacement.length && replacement.every( ( block ) => canInsertBlockType( block.name, targetRootClientId ) - ); - - if ( canLiftAndTransformToDefaultBlock ) { - // Step 4: If the block can be transformed to the default block type and moved up. + ) + ) { insertBlocks( replacement, getBlockIndex( _clientId ), @@ -421,7 +400,6 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => { ); removeBlock( firstClientId, false ); } else { - // Step 5: Continue the default behavior. switchToDefaultOrRemove(); } } @@ -433,6 +411,8 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => { removeBlock( _clientId, false ); } } ); + } else { + switchToDefaultOrRemove(); } } diff --git a/packages/blocks/README.md b/packages/blocks/README.md index f4805e1c60b381..3e5a88a2b92c1b 100644 --- a/packages/blocks/README.md +++ b/packages/blocks/README.md @@ -503,10 +503,6 @@ _Returns_ - `Array|string`: A list of blocks or a string, depending on `handlerMode`. -### privateApis - -Undocumented declaration. - ### rawHandler Converts an HTML string to known blocks. diff --git a/packages/blocks/src/api/index.js b/packages/blocks/src/api/index.js index 0b38b8e29e68a0..3ace68be87393c 100644 --- a/packages/blocks/src/api/index.js +++ b/packages/blocks/src/api/index.js @@ -1,9 +1,3 @@ -/** - * Internal dependencies - */ -import { lock } from '../lock-unlock'; -import { isUnmodifiedBlockContent } from './utils'; - // The blocktype is the most important concept within the block API. It defines // all aspects of the block configuration and its interfaces, including `edit` // and `save`. The transforms specification allows converting one blocktype to @@ -175,6 +169,3 @@ export { __EXPERIMENTAL_ELEMENTS, __EXPERIMENTAL_PATHS_WITH_OVERRIDE, } from './constants'; - -export const privateApis = {}; -lock( privateApis, { isUnmodifiedBlockContent } ); diff --git a/packages/blocks/src/api/utils.js b/packages/blocks/src/api/utils.js index 7bace4ff84c29b..20f0f6a85ed091 100644 --- a/packages/blocks/src/api/utils.js +++ b/packages/blocks/src/api/utils.js @@ -30,30 +30,6 @@ extend( [ namesPlugin, a11yPlugin ] ); */ const ICON_COLORS = [ '#191e23', '#f8f9f9' ]; -/** - * Determines whether the block's attribute is equal to the default attribute - * which means the attribute is unmodified. - * @param {Object} attributeDefinition The attribute's definition of the block type. - * @param {*} value The attribute's value. - * @return {boolean} Whether the attribute is unmodified. - */ -function isUnmodifiedAttribute( attributeDefinition, value ) { - // Every attribute that has a default must match the default. - if ( attributeDefinition.hasOwnProperty( 'default' ) ) { - return value === attributeDefinition.default; - } - - // The rich text type is a bit different from the rest because it - // has an implicit default value of an empty RichTextData instance, - // so check the length of the value. - if ( attributeDefinition.type === 'rich-text' ) { - return ! value?.length; - } - - // Every attribute that doesn't have a default should be undefined. - return value === undefined; -} - /** * Determines whether the block's attributes are equal to the default attributes * which means the block is unmodified. @@ -67,7 +43,20 @@ export function isUnmodifiedBlock( block ) { ( [ key, definition ] ) => { const value = block.attributes[ key ]; - return isUnmodifiedAttribute( definition, value ); + // Every attribute that has a default must match the default. + if ( definition.hasOwnProperty( 'default' ) ) { + return value === definition.default; + } + + // The rich text type is a bit different from the rest because it + // has an implicit default value of an empty RichTextData instance, + // so check the length of the value. + if ( definition.type === 'rich-text' ) { + return ! value?.length; + } + + // Every attribute that doesn't have a default should be undefined. + return value === undefined; } ); } @@ -84,35 +73,6 @@ export function isUnmodifiedDefaultBlock( block ) { return block.name === getDefaultBlockName() && isUnmodifiedBlock( block ); } -/** - * Determines whether the block content is unmodified. A block content is - * considered unmodified if all the attributes that have a role of 'content' - * are equal to the default attributes (or undefined). - * If the block does not have any attributes with a role of 'content', it - * will be considered unmodified if all the attributes are equal to the default - * attributes (or undefined). - * - * @param {WPBlock} block Block Object - * @return {boolean} Whether the block content is unmodified. - */ -export function isUnmodifiedBlockContent( block ) { - const contentAttributes = getBlockAttributesNamesByRole( - block.name, - 'content' - ); - - if ( contentAttributes.length === 0 ) { - return isUnmodifiedBlock( block ); - } - - return contentAttributes.every( ( key ) => { - const definition = getBlockType( block.name )?.attributes[ key ]; - const value = block.attributes[ key ]; - - return isUnmodifiedAttribute( definition, value ); - } ); -} - /** * Function that checks if the parameter is a valid icon. * diff --git a/test/e2e/specs/editor/various/splitting-merging.spec.js b/test/e2e/specs/editor/various/splitting-merging.spec.js index eba9f1d3163fd5..146039a7c7d1bf 100644 --- a/test/e2e/specs/editor/various/splitting-merging.spec.js +++ b/test/e2e/specs/editor/various/splitting-merging.spec.js @@ -393,6 +393,11 @@ test.describe( 'splitting and merging blocks (@firefox, @webkit)', () => { attributes: { content: 'heading', level: 2 }, innerBlocks: [], }; + const paragraphWithContent = { + name: 'core/paragraph', + attributes: { content: 'heading', dropCap: false }, + innerBlocks: [], + }; const placeholderBlock = { name: 'core/separator' }; await editor.insertBlock( { name: 'core/group', @@ -407,6 +412,9 @@ test.describe( 'splitting and merging blocks (@firefox, @webkit)', () => { .getByRole( 'document', { name: 'Empty block' } ) .focus(); + // Remove the alignment. + await page.keyboard.press( 'Backspace' ); + // Remove the empty paragraph block. await page.keyboard.press( 'Backspace' ); await expect .poll( editor.getBlocks, 'Remove the default empty block' ) @@ -422,8 +430,7 @@ test.describe( 'splitting and merging blocks (@firefox, @webkit)', () => { }, ] ); - // Move the caret to the beginning of the empty heading block. - await page.keyboard.press( 'ArrowDown' ); + // Convert the heading to a default block. await page.keyboard.press( 'Backspace' ); await expect .poll( @@ -441,6 +448,9 @@ test.describe( 'splitting and merging blocks (@firefox, @webkit)', () => { ], }, ] ); + // Remove the alignment. + await page.keyboard.press( 'Backspace' ); + // Remove the empty default block. await page.keyboard.press( 'Backspace' ); await expect.poll( editor.getBlocks ).toEqual( [ { @@ -453,17 +463,16 @@ test.describe( 'splitting and merging blocks (@firefox, @webkit)', () => { }, ] ); - // Move the caret to the beginning of the "heading" heading block. - await page.keyboard.press( 'ArrowDown' ); + // Convert a non-empty non-default block to a default block. await page.keyboard.press( 'Backspace' ); await expect .poll( editor.getBlocks, 'Lift the non-empty non-default block' ) .toEqual( [ - headingWithContent, { name: 'core/group', attributes: { tagName: 'div' }, innerBlocks: [ + paragraphWithContent, expect.objectContaining( placeholderBlock ), ], }, From c80e6a8383b6923014f5b081c00e15d5814e2c8f Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:48:50 +0100 Subject: [PATCH 1532/1908] Safari: prevent focus capturing caused by flex display (#66402) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/block-library/src/group/editor.scss | 12 ----- .../src/component/event-listeners/index.js | 2 + .../event-listeners/prevent-focus-capture.js | 44 +++++++++++++++++++ .../various/multi-block-selection.spec.js | 9 ++-- 4 files changed, 49 insertions(+), 18 deletions(-) create mode 100644 packages/rich-text/src/component/event-listeners/prevent-focus-capture.js diff --git a/packages/block-library/src/group/editor.scss b/packages/block-library/src/group/editor.scss index 12f5028b96ec3d..739a9cd0cf852e 100644 --- a/packages/block-library/src/group/editor.scss +++ b/packages/block-library/src/group/editor.scss @@ -10,18 +10,6 @@ } } -// Reset user select, but the next rule should take precedence for nested -// groups. -:where([data-has-multi-selection]:not([contenteditable="true"]) .wp-block-group > *) { - user-select: initial; -} - -// When we are not multi-selecting, prevent children from capturing the -// selection, which happens when the group is flex and children inlined. -:where([data-has-multi-selection]:not([contenteditable="true"]) .wp-block-group) { - user-select: none; -} - // Place block list appender in the same place content will appear. [data-type="core/group"].is-selected { .block-list-appender { diff --git a/packages/rich-text/src/component/event-listeners/index.js b/packages/rich-text/src/component/event-listeners/index.js index 4f69db36db06a0..d4f760abdc735a 100644 --- a/packages/rich-text/src/component/event-listeners/index.js +++ b/packages/rich-text/src/component/event-listeners/index.js @@ -13,6 +13,7 @@ import formatBoundaries from './format-boundaries'; import deleteHandler from './delete'; import inputAndSelection from './input-and-selection'; import selectionChangeCompat from './selection-change-compat'; +import { preventFocusCapture } from './prevent-focus-capture'; const allEventListeners = [ copyHandler, @@ -21,6 +22,7 @@ const allEventListeners = [ deleteHandler, inputAndSelection, selectionChangeCompat, + preventFocusCapture, ]; export function useEventListeners( props ) { diff --git a/packages/rich-text/src/component/event-listeners/prevent-focus-capture.js b/packages/rich-text/src/component/event-listeners/prevent-focus-capture.js new file mode 100644 index 00000000000000..8dc97f73673ce6 --- /dev/null +++ b/packages/rich-text/src/component/event-listeners/prevent-focus-capture.js @@ -0,0 +1,44 @@ +/** + * Prevents focus from being captured by the element when clicking _outside_ + * around the element. This may happen when the parent element is flex. + * @see https://github.com/WordPress/gutenberg/pull/65857 + * @see https://github.com/WordPress/gutenberg/pull/66402 + */ +export function preventFocusCapture() { + return ( element ) => { + const { ownerDocument } = element; + const { defaultView } = ownerDocument; + + let value = null; + + function onPointerDown( event ) { + // Abort if the event is default prevented, we will not get a pointer up event. + if ( event.defaultPrevented ) { + return; + } + if ( event.target === element ) { + return; + } + if ( ! event.target.contains( element ) ) { + return; + } + value = element.getAttribute( 'contenteditable' ); + element.setAttribute( 'contenteditable', 'false' ); + defaultView.getSelection().removeAllRanges(); + } + + function onPointerUp() { + if ( value !== null ) { + element.setAttribute( 'contenteditable', value ); + value = null; + } + } + + defaultView.addEventListener( 'pointerdown', onPointerDown ); + defaultView.addEventListener( 'pointerup', onPointerUp ); + return () => { + defaultView.removeEventListener( 'pointerdown', onPointerDown ); + defaultView.removeEventListener( 'pointerup', onPointerUp ); + }; + }; +} diff --git a/test/e2e/specs/editor/various/multi-block-selection.spec.js b/test/e2e/specs/editor/various/multi-block-selection.spec.js index 9148c316078a4a..41fb120023541a 100644 --- a/test/e2e/specs/editor/various/multi-block-selection.spec.js +++ b/test/e2e/specs/editor/various/multi-block-selection.spec.js @@ -728,7 +728,7 @@ test.describe( 'Multi-block selection (@firefox, @webkit)', () => { ] ); } ); - test( 'should clear selection when clicking next to blocks (-firefox)', async ( { + test( 'should clear selection when clicking next to blocks', async ( { page, editor, multiBlockSelectionUtils, @@ -752,16 +752,13 @@ test.describe( 'Multi-block selection (@firefox, @webkit)', () => { name: 'Block: Paragraph', } ) .filter( { hasText: '1' } ); + // For some reason in Chrome it requires two clicks, even though it + // doesn't when testing manually. await paragraph1.click( { position: { x: -1, y: 0 }, // Use force since it's outside the bounding box of the element. force: true, } ); - - await expect - .poll( multiBlockSelectionUtils.getSelectedFlatIndices ) - .toEqual( [ 1 ] ); - await paragraph1.click( { position: { x: -1, y: 0 }, // Use force since it's outside the bounding box of the element. From a1a0fa3e36f352f3672d602ec0d0c76baf983dda Mon Sep 17 00:00:00 2001 From: tellthemachines <tellthemachines@users.noreply.github.com> Date: Tue, 12 Nov 2024 10:10:45 +1100 Subject: [PATCH 1533/1908] Add a landing section to stylebook tabs (#66545) Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: beafialho <beafialho@git.wordpress.org> --- .../src/components/global-styles/ui.js | 5 + .../sidebar-global-styles-wrapper/index.js | 5 + .../src/components/style-book/constants.ts | 9 ++ .../src/components/style-book/examples.tsx | 106 +++++++++++++++++- .../src/components/style-book/index.js | 18 ++- test/e2e/specs/site-editor/style-book.spec.js | 14 +-- 6 files changed, 146 insertions(+), 11 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index 2edea0fdbc3da3..0cab4c13aa3ee7 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -202,6 +202,11 @@ function GlobalStylesStyleBook() { navigator.goTo( '/colors/palette' ); return; } + if ( blockName === 'typography' ) { + // Go to typography Global Styles. + navigator.goTo( '/typography' ); + return; + } // Now go to the selected block. navigator.goTo( '/blocks/' + encodeURIComponent( blockName ) ); diff --git a/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js b/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js index afa9f489dde22b..342fb1b5db52d2 100644 --- a/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js +++ b/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js @@ -132,6 +132,11 @@ export default function GlobalStylesUIWrapper() { onPathChange( '/colors/palette' ); return; } + if ( blockName === 'typography' ) { + // Go to typography Global Styles. + onPathChange( '/typography' ); + return; + } // Now go to the selected block. onPathChange( diff --git a/packages/edit-site/src/components/style-book/constants.ts b/packages/edit-site/src/components/style-book/constants.ts index 9aace34e64cbf1..7b13e3d4ef7f60 100644 --- a/packages/edit-site/src/components/style-book/constants.ts +++ b/packages/edit-site/src/components/style-book/constants.ts @@ -107,6 +107,11 @@ export const STYLE_BOOK_THEME_SUBCATEGORIES: Omit< ]; export const STYLE_BOOK_CATEGORIES: StyleBookCategory[] = [ + { + slug: 'overview', + title: __( 'Overview' ), + blocks: [], + }, { slug: 'text', title: __( 'Text' ), @@ -249,6 +254,10 @@ export const STYLE_BOOK_IFRAME_STYLES = ` .edit-site-style-book__example-preview { width: 100%; } + + .is-wide .edit-site-style-book__example-preview { + width: calc(100% - 120px); + } .edit-site-style-book__example-preview .block-editor-block-list__insertion-point, .edit-site-style-book__example-preview .block-list-appender { diff --git a/packages/edit-site/src/components/style-book/examples.tsx b/packages/edit-site/src/components/style-book/examples.tsx index 9f4badd99a6582..2fefe227ca52b7 100644 --- a/packages/edit-site/src/components/style-book/examples.tsx +++ b/packages/edit-site/src/components/style-book/examples.tsx @@ -62,6 +62,103 @@ function getColorExamples( colors: MultiOriginPalettes ): BlockExample[] { return examples; } +/** + * Returns examples for the overview page. + * + * @param {MultiOriginPalettes} colors Global Styles color palettes per origin. + * @return {BlockExample[]} An array of block examples. + */ +function getOverviewBlockExamples( + colors: MultiOriginPalettes +): BlockExample[] { + const examples: BlockExample[] = []; + + // Get theme palette from colors. + const themePalette = colors.colors.find( + ( origin: ColorOrigin ) => origin.slug === 'theme' + ); + + if ( themePalette ) { + const themeColorexample: BlockExample = { + name: 'theme-colors', + title: __( 'Colors' ), + category: 'overview', + content: ( + <ColorExamples colors={ themePalette.colors } type={ colors } /> + ), + }; + + examples.push( themeColorexample ); + } + + const headingBlock = createBlock( 'core/heading', { + content: __( + `AaBbCcDdEeFfGgHhiiJjKkLIMmNnOoPpQakRrssTtUuVVWwXxxYyZzOl23356789X{(…)},2!*&:/A@HELFO™` + ), + level: 1, + } ); + const firstParagraphBlock = createBlock( 'core/paragraph', { + content: __( + `A paragraph in a website refers to a distinct block of text that is used to present and organize information. It is a fundamental unit of content in web design and is typically composed of a group of related sentences or thoughts focused on a particular topic or idea. Paragraphs play a crucial role in improving the readability and user experience of a website. They break down the text into smaller, manageable chunks, allowing readers to scan the content more easily.` + ), + } ); + const secondParagraphBlock = createBlock( 'core/paragraph', { + content: __( + `Additionally, paragraphs help structure the flow of information and provide logical breaks between different concepts or pieces of information. In terms of formatting, paragraphs in websites are commonly denoted by a vertical gap or indentation between each block of text. This visual separation helps visually distinguish one paragraph from another, creating a clear and organized layout that guides the reader through the content smoothly.` + ), + } ); + + const textExample = { + name: 'typography', + title: __( 'Typography' ), + category: 'overview', + blocks: [ + headingBlock, + createBlock( + 'core/group', + { + layout: { + type: 'grid', + columnCount: 2, + minimumColumnWidth: '12rem', + }, + style: { + spacing: { + blockGap: '1.5rem', + }, + }, + }, + [ firstParagraphBlock, secondParagraphBlock ] + ), + ], + }; + examples.push( textExample ); + + const otherBlockExamples = [ + 'core/image', + 'core/separator', + 'core/buttons', + 'core/pullquote', + 'core/search', + ]; + + // Get examples for other blocks and put them in order of above array. + otherBlockExamples.forEach( ( blockName ) => { + const blockType = getBlockType( blockName ); + if ( blockType && blockType.example ) { + const blockExample: BlockExample = { + name: blockName, + title: blockType.title, + category: 'overview', + blocks: getBlockFromExample( blockName, blockType.example ), + }; + examples.push( blockExample ); + } + } ); + + return examples; +} + /** * Returns a list of examples for registered block types. * @@ -109,5 +206,12 @@ export function getExamples( colors: MultiOriginPalettes ): BlockExample[] { }; const colorExamples = getColorExamples( colors ); - return [ headingsExample, ...colorExamples, ...nonHeadingBlockExamples ]; + const overviewBlockExamples = getOverviewBlockExamples( colors ); + + return [ + headingsExample, + ...colorExamples, + ...nonHeadingBlockExamples, + ...overviewBlockExamples, + ]; } diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 9918c169ff6ab0..de4c38bd40c05d 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -203,6 +203,22 @@ function StyleBook( { [ examples ] ); + const examplesForSinglePageUse = []; + const overviewCategoryExamples = getExamplesByCategory( + { slug: 'overview' }, + examples + ); + examplesForSinglePageUse.push( ...overviewCategoryExamples.examples ); + const otherExamples = examples.filter( ( example ) => { + return ( + example.category !== 'overview' && + ! overviewCategoryExamples.examples.find( + ( overviewExample ) => overviewExample.name === example.name + ) + ); + } ); + examplesForSinglePageUse.push( ...otherExamples ); + const { base: baseConfig } = useContext( GlobalStylesContext ); const goTo = getStyleBookNavigationFromPath( path ); @@ -286,7 +302,7 @@ function StyleBook( { </Tabs> ) : ( <StyleBookBody - examples={ examples } + examples={ examplesForSinglePageUse } isSelected={ isSelected } onClick={ onClick } onSelect={ onSelect } diff --git a/test/e2e/specs/site-editor/style-book.spec.js b/test/e2e/specs/site-editor/style-book.spec.js index c94049872edcf6..d860b05bc8f06d 100644 --- a/test/e2e/specs/site-editor/style-book.spec.js +++ b/test/e2e/specs/site-editor/style-book.spec.js @@ -52,14 +52,10 @@ test.describe( 'Style Book', () => { '[name="style-book-canvas"]' ); + // In the Overview tab, expect a button for the main typography section. await expect( styleBookIframe.getByRole( 'button', { - name: 'Open Headings styles in Styles panel', - } ) - ).toBeVisible(); - await expect( - styleBookIframe.getByRole( 'button', { - name: 'Open Paragraph styles in Styles panel', + name: 'Open Typography styles in Styles panel', } ) ).toBeVisible(); @@ -83,13 +79,13 @@ test.describe( 'Style Book', () => { await page .frameLocator( '[name="style-book-canvas"]' ) .getByRole( 'button', { - name: 'Open Headings styles in Styles panel', + name: 'Open Image styles in Styles panel', } ) .click(); await expect( page.locator( - 'role=region[name="Editor settings"i] >> role=heading[name="Heading"i]' + 'role=region[name="Editor settings"i] >> role=heading[name="Image"i]' ) ).toBeVisible(); } ); @@ -103,7 +99,7 @@ test.describe( 'Style Book', () => { await page .frameLocator( '[name="style-book-canvas"]' ) .getByRole( 'button', { - name: 'Open Quote styles in Styles panel', + name: 'Open Pullquote styles in Styles panel', } ) .click(); From caf9d0b8beaf7ee29b130b886313dce718d5de57 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 12 Nov 2024 09:47:34 +1000 Subject: [PATCH 1534/1908] Section Styles: Fix insecure properties removal for inner block types and elements (#66896) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: BogdanUngureanu <bogdanungureanu@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- backport-changelog/6.8/7759.md | 4 + lib/class-wp-theme-json-gutenberg.php | 77 +++++++++--- phpunit/class-wp-theme-json-test.php | 172 ++++++++++++++++++++++++++ 3 files changed, 234 insertions(+), 19 deletions(-) create mode 100644 backport-changelog/6.8/7759.md diff --git a/backport-changelog/6.8/7759.md b/backport-changelog/6.8/7759.md new file mode 100644 index 00000000000000..a0ad85b06e6b05 --- /dev/null +++ b/backport-changelog/6.8/7759.md @@ -0,0 +1,4 @@ +https://github.com/WordPress/wordpress-develop/pull/7759 + +* https://github.com/WordPress/gutenberg/pull/66896 + diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index dafa8b25f278fc..d505916450cafb 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -3565,26 +3565,12 @@ public static function remove_insecure_properties( $theme_json, $origin = 'theme $variation_output = static::remove_insecure_styles( $variation_input ); - // Process a variation's elements and element pseudo selector styles. - if ( isset( $variation_input['elements'] ) ) { - foreach ( $valid_element_names as $element_name ) { - $element_input = $variation_input['elements'][ $element_name ] ?? null; - if ( $element_input ) { - $element_output = static::remove_insecure_styles( $element_input ); - - if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] ) ) { - foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] as $pseudo_selector ) { - if ( isset( $element_input[ $pseudo_selector ] ) ) { - $element_output[ $pseudo_selector ] = static::remove_insecure_styles( $element_input[ $pseudo_selector ] ); - } - } - } + if ( isset( $variation_input['blocks'] ) ) { + $variation_output['blocks'] = static::remove_insecure_inner_block_styles( $variation_input['blocks'] ); + } - if ( ! empty( $element_output ) ) { - _wp_array_set( $variation_output, array( 'elements', $element_name ), $element_output ); - } - } - } + if ( isset( $variation_input['elements'] ) ) { + $variation_output['elements'] = static::remove_insecure_element_styles( $variation_input['elements'] ); } if ( ! empty( $variation_output ) ) { @@ -3622,6 +3608,59 @@ public static function remove_insecure_properties( $theme_json, $origin = 'theme return $theme_json; } + /** + * Remove insecure element styles within a variation or block. + * + * @since 6.8.0 + * + * @param array $elements The elements to process. + * @return array The sanitized elements styles. + */ + protected static function remove_insecure_element_styles( $elements ) { + $sanitized = array(); + $valid_element_names = array_keys( static::ELEMENTS ); + + foreach ( $valid_element_names as $element_name ) { + $element_input = $elements[ $element_name ] ?? null; + if ( $element_input ) { + $element_output = static::remove_insecure_styles( $element_input ); + + if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] ) ) { + foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] as $pseudo_selector ) { + if ( isset( $element_input[ $pseudo_selector ] ) ) { + $element_output[ $pseudo_selector ] = static::remove_insecure_styles( $element_input[ $pseudo_selector ] ); + } + } + } + + $sanitized[ $element_name ] = $element_output; + } + } + return $sanitized; + } + + /** + * Remove insecure styles from inner blocks and their elements. + * + * @since 6.8.0 + * + * @param array $blocks The block styles to process. + * @return array Sanitized block type styles. + */ + protected static function remove_insecure_inner_block_styles( $blocks ) { + $sanitized = array(); + foreach ( $blocks as $block_type => $block_input ) { + $block_output = static::remove_insecure_styles( $block_input ); + + if ( isset( $block_input['elements'] ) ) { + $block_output['elements'] = static::remove_insecure_element_styles( $block_input['elements'] ); + } + + $sanitized[ $block_type ] = $block_output; + } + return $sanitized; + } + /** * Processes a setting node and returns the same node * without the insecure settings. diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 50a0af4f9b3ff3..f77086cf0dd046 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -4387,6 +4387,178 @@ public function test_block_style_variations_with_invalid_properties() { $this->assertSameSetsWithIndex( $expected, $actual ); } + public function test_block_style_variations_with_inner_blocks_and_elements() { + wp_set_current_user( static::$administrator_id ); + gutenberg_register_block_style( + array( 'core/group' ), + array( + 'name' => 'custom-group', + 'label' => 'Custom Group', + ) + ); + + $expected = array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'blocks' => array( + 'core/group' => array( + 'color' => array( + 'background' => 'blue', + ), + 'variations' => array( + 'custom-group' => array( + 'color' => array( + 'background' => 'purple', + ), + 'blocks' => array( + 'core/paragraph' => array( + 'color' => array( + 'text' => 'red', + ), + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => 'blue', + ), + ':hover' => array( + 'color' => array( + 'text' => 'green', + ), + ), + ), + ), + ), + 'core/heading' => array( + 'typography' => array( + 'fontSize' => '24px', + ), + ), + ), + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => 'yellow', + ), + ':hover' => array( + 'color' => array( + 'text' => 'orange', + ), + ), + ), + ), + ), + ), + ), + ), + ), + ); + + $actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( $expected ); + + // The sanitization processes blocks in a specific order which might differ to the theme.json input. + $this->assertEqualsCanonicalizing( + $expected, + $actual, + 'Block style variations data does not match when inner blocks or element styles present' + ); + } + + public function test_block_style_variations_with_invalid_inner_block_or_element_styles() { + wp_set_current_user( static::$administrator_id ); + gutenberg_register_block_style( + array( 'core/group' ), + array( + 'name' => 'custom-group', + 'label' => 'Custom Group', + ) + ); + + $input = array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'blocks' => array( + 'core/group' => array( + 'variations' => array( + 'custom-group' => array( + 'blocks' => array( + 'core/paragraph' => array( + 'color' => array( + 'text' => 'red', + ), + 'typography' => array( + 'fontSize' => 'alert(1)', // Should be removed. + ), + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => 'blue', + ), + 'css' => 'unsafe-value', // Should be removed. + ), + ), + 'custom' => 'unsafe-value', // Should be removed. + ), + ), + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => 'yellow', + ), + 'javascript' => 'alert(1)', // Should be removed. + ), + ), + ), + ), + ), + ), + ), + ); + + $expected = array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'blocks' => array( + 'core/group' => array( + 'variations' => array( + 'custom-group' => array( + 'blocks' => array( + 'core/paragraph' => array( + 'color' => array( + 'text' => 'red', + ), + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => 'blue', + ), + ), + ), + ), + ), + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => 'yellow', + ), + ), + ), + ), + ), + ), + ), + ), + ); + + $actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( $input ); + + // The sanitization processes blocks in a specific order which might differ to the theme.json input. + $this->assertEqualsCanonicalizing( + $expected, + $actual, + 'Insecure properties were not removed from block style variation inner block types or elements' + ); + } + /** * Tests generating the spacing presets array based on the spacing scale provided. * From dacc42916b944b54ecc088273efe71c8edaa9959 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Tue, 12 Nov 2024 08:29:46 +0200 Subject: [PATCH 1535/1908] Cover: Show DropZone only when dragging withing the block (#66912) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- packages/block-library/src/cover/editor.scss | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/block-library/src/cover/editor.scss b/packages/block-library/src/cover/editor.scss index da5d4be26ac962..4dfc301a23114d 100644 --- a/packages/block-library/src/cover/editor.scss +++ b/packages/block-library/src/cover/editor.scss @@ -107,10 +107,6 @@ } } -// When uploading background images, show a transparent overlay. -.wp-block-cover > .components-drop-zone .components-drop-zone__content { - opacity: 0.8 !important; -} // Remove the parallax fixed background when in the patterns preview panel as it // doesn't work with the transforms that are applied to resize the block in that context. From e6d38fee95ede2493a0f2ee8105d3665e7174411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:10:50 +0100 Subject: [PATCH 1536/1908] DataViews Fields API: default getValueFromId supports nested objects (#66890) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- packages/dataviews/src/normalize-fields.ts | 19 +++++++- .../dataviews/src/test/normalize-fields.ts | 45 +++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 packages/dataviews/src/test/normalize-fields.ts diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index 5ef219e45a4787..562f29fcce84fe 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -11,6 +11,22 @@ import type { import { getControl } from './dataform-controls'; import DataFormCombinedEdit from './components/dataform-combined-edit'; +const getValueFromId = + ( id: string ) => + ( { item }: { item: any } ) => { + const path = id.split( '.' ); + let value = item; + for ( const segment of path ) { + if ( value.hasOwnProperty( segment ) ) { + value = value[ segment ]; + } else { + value = undefined; + } + } + + return value; + }; + /** * Apply default values and normalize the fields config. * @@ -23,8 +39,7 @@ export function normalizeFields< Item >( return fields.map( ( field ) => { const fieldTypeDefinition = getFieldTypeDefinition( field.type ); - const getValue = - field.getValue || ( ( { item } ) => ( item as any )[ field.id ] ); + const getValue = field.getValue || getValueFromId( field.id ); const sort = field.sort ?? diff --git a/packages/dataviews/src/test/normalize-fields.ts b/packages/dataviews/src/test/normalize-fields.ts new file mode 100644 index 00000000000000..dce6a19766dcaa --- /dev/null +++ b/packages/dataviews/src/test/normalize-fields.ts @@ -0,0 +1,45 @@ +/** + * Internal dependencies + */ +import { normalizeFields } from '../normalize-fields'; +import type { Field } from '../types'; + +describe( 'normalizeFields: default getValue', () => { + describe( 'getValue from ID', () => { + it( 'user', () => { + const item = { user: 'value' }; + const fields: Field< {} >[] = [ + { + id: 'user', + }, + ]; + const normalizedFields = normalizeFields( fields ); + const result = normalizedFields[ 0 ].getValue( { item } ); + expect( result ).toBe( 'value' ); + } ); + + it( 'user.name', () => { + const item = { user: { name: 'value' } }; + const fields: Field< {} >[] = [ + { + id: 'user.name', + }, + ]; + const normalizedFields = normalizeFields( fields ); + const result = normalizedFields[ 0 ].getValue( { item } ); + expect( result ).toBe( 'value' ); + } ); + + it( 'user.name.first', () => { + const item = { user: { name: { first: 'value' } } }; + const fields: Field< {} >[] = [ + { + id: 'user.name.first', + }, + ]; + const normalizedFields = normalizeFields( fields ); + const result = normalizedFields[ 0 ].getValue( { item } ); + expect( result ).toBe( 'value' ); + } ); + } ); +} ); From e07351becf8e1628b0234621bb5009df46d0432f Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Tue, 12 Nov 2024 12:52:16 +0100 Subject: [PATCH 1537/1908] DataViews: Implement `isItemClickable` and `onClickItem` props (#66365) Co-authored-by: gigitux <gigitux@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: louwie17 <louwie17@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/dataviews/README.md | 8 ++++ .../src/components/dataviews-context/index.ts | 4 ++ .../src/components/dataviews-layout/index.tsx | 4 ++ .../src/components/dataviews/index.tsx | 11 +++++- .../src/components/dataviews/style.scss | 12 ++++-- .../src/dataviews-layouts/grid/index.tsx | 34 ++++++++++++++--- .../src/dataviews-layouts/grid/style.scss | 5 +++ .../src/dataviews-layouts/table/index.tsx | 37 +++++++++++++++++-- .../utils/get-clickable-item-props.ts | 22 +++++++++++ packages/dataviews/src/types.ts | 2 + .../src/components/post-fields/index.js | 36 ++++-------------- .../src/components/post-list/index.js | 12 ++++-- .../src/components/post-list/style.scss | 32 ++++++++++++++-- packages/edit-site/src/style.scss | 4 +- packages/fields/src/style.scss | 2 + packages/fields/src/styles.scss | 1 - 16 files changed, 175 insertions(+), 51 deletions(-) create mode 100644 packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts create mode 100644 packages/fields/src/style.scss delete mode 100644 packages/fields/src/styles.scss diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index ff20386862929e..621e3c7ba71ce2 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -358,6 +358,14 @@ Callback that signals the user selected one of more items. It receives the list If `selection` and `onChangeSelection` are provided, the `DataViews` component behaves as a controlled component, otherwise, it behaves like an uncontrolled component. +### `isItemClickable`: `function` + +A function that determines if a media field or a primary field are clickable. It receives an item as an argument and returns a boolean value indicating whether the item can be clicked. + +### `onClickItem`: `function` + +A callback function that is triggered when a user clicks on a media field or primary field. This function is currently implemented only in the `grid` and `list` views. + #### `header`: React component React component to be rendered next to the view config button. diff --git a/packages/dataviews/src/components/dataviews-context/index.ts b/packages/dataviews/src/components/dataviews-context/index.ts index 3936288b3095b0..87acade73bc819 100644 --- a/packages/dataviews/src/components/dataviews-context/index.ts +++ b/packages/dataviews/src/components/dataviews-context/index.ts @@ -26,6 +26,8 @@ type DataViewsContextType< Item > = { openedFilter: string | null; setOpenedFilter: ( openedFilter: string | null ) => void; getItemId: ( item: Item ) => string; + onClickItem: ( item: Item ) => void; + isItemClickable: ( item: Item ) => boolean; density: number; }; @@ -43,6 +45,8 @@ const DataViewsContext = createContext< DataViewsContextType< any > >( { setOpenedFilter: () => {}, openedFilter: null, getItemId: ( item ) => item.id, + onClickItem: () => {}, + isItemClickable: () => false, density: 0, } ); diff --git a/packages/dataviews/src/components/dataviews-layout/index.tsx b/packages/dataviews/src/components/dataviews-layout/index.tsx index bae4071fe2f773..4ef0125b1f64b5 100644 --- a/packages/dataviews/src/components/dataviews-layout/index.tsx +++ b/packages/dataviews/src/components/dataviews-layout/index.tsx @@ -28,6 +28,8 @@ export default function DataViewsLayout() { onChangeSelection, setOpenedFilter, density, + onClickItem, + isItemClickable, } = useContext( DataViewsContext ); const ViewComponent = VIEW_LAYOUTS.find( ( v ) => v.type === view.type ) @@ -44,6 +46,8 @@ export default function DataViewsLayout() { onChangeSelection={ onChangeSelection } selection={ selection } setOpenedFilter={ setOpenedFilter } + onClickItem={ onClickItem } + isItemClickable={ isItemClickable } view={ view } density={ density } /> diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index da60ab15ecadec..77a5cb8740f712 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -44,12 +44,17 @@ type DataViewsProps< Item > = { defaultLayouts: SupportedLayouts; selection?: string[]; onChangeSelection?: ( items: string[] ) => void; + onClickItem?: ( item: Item ) => void; + isItemClickable?: ( item: Item ) => boolean; header?: ReactNode; } & ( Item extends ItemWithId ? { getItemId?: ( item: Item ) => string } : { getItemId: ( item: Item ) => string } ); const defaultGetItemId = ( item: ItemWithId ) => item.id; +const defaultIsItemClickable = () => false; +const defaultOnClickItem = () => {}; +const EMPTY_ARRAY: any[] = []; export default function DataViews< Item >( { view, @@ -57,7 +62,7 @@ export default function DataViews< Item >( { fields, search = true, searchLabel = undefined, - actions = [], + actions = EMPTY_ARRAY, data, getItemId = defaultGetItemId, isLoading = false, @@ -65,6 +70,8 @@ export default function DataViews< Item >( { defaultLayouts, selection: selectionProperty, onChangeSelection, + onClickItem = defaultOnClickItem, + isItemClickable = defaultIsItemClickable, header, }: DataViewsProps< Item > ) { const [ selectionState, setSelectionState ] = useState< string[] >( [] ); @@ -110,6 +117,8 @@ export default function DataViews< Item >( { openedFilter, setOpenedFilter, getItemId, + isItemClickable, + onClickItem, density, } } > diff --git a/packages/dataviews/src/components/dataviews/style.scss b/packages/dataviews/src/components/dataviews/style.scss index aa8fbcfb009c05..bd75a1ff9e2a18 100644 --- a/packages/dataviews/src/components/dataviews/style.scss +++ b/packages/dataviews/src/components/dataviews/style.scss @@ -19,7 +19,7 @@ position: sticky; left: 0; transition: padding ease-out 0.1s; - @include reduce-motion("transition"); + @include reduce-motion( "transition" ); } .dataviews-view-list__primary-field, @@ -62,6 +62,13 @@ } } +.dataviews-view-list__primary-field--clickable, +.dataviews-view-grid__primary-field--clickable, +.dataviews-view-grid__media--clickable, +.dataviews-view-table__primary-field > .dataviews-view-table__cell-content--clickable { + cursor: pointer; +} + .dataviews-no-results, .dataviews-loading { padding: 0 $grid-unit-60; @@ -70,7 +77,7 @@ align-items: center; justify-content: center; transition: padding ease-out 0.1s; - @include reduce-motion("transition"); + @include reduce-motion( "transition" ); } /* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ @@ -86,4 +93,3 @@ padding-right: $grid-unit-30; } } - diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx index 230ffe0dc50b5c..91cc87ec7b35b6 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx @@ -24,11 +24,14 @@ import SingleSelectionCheckbox from '../../components/dataviews-selection-checkb import { useHasAPossibleBulkAction } from '../../components/dataviews-bulk-actions'; import type { Action, NormalizedField, ViewGridProps } from '../../types'; import type { SetSelection } from '../../private-types'; +import getClickableItemProps from '../utils/get-clickable-item-props'; interface GridItemProps< Item > { selection: string[]; onChangeSelection: SetSelection; getItemId: ( item: Item ) => string; + onClickItem: ( item: Item ) => void; + isItemClickable: ( item: Item ) => boolean; item: Item; actions: Action< Item >[]; mediaField?: NormalizedField< Item >; @@ -41,6 +44,8 @@ interface GridItemProps< Item > { function GridItem< Item >( { selection, onChangeSelection, + onClickItem, + isItemClickable, getItemId, item, actions, @@ -59,6 +64,21 @@ function GridItem< Item >( { const renderedPrimaryField = primaryField?.render ? ( <primaryField.render item={ item } /> ) : null; + + const clickableMediaItemProps = getClickableItemProps( + item, + isItemClickable, + onClickItem, + 'dataviews-view-grid__media' + ); + + const clickablePrimaryItemProps = getClickableItemProps( + item, + isItemClickable, + onClickItem, + 'dataviews-view-grid__primary-field' + ); + return ( <VStack spacing={ 0 } @@ -81,9 +101,7 @@ function GridItem< Item >( { } } } > - <div className="dataviews-view-grid__media"> - { renderedMediaField } - </div> + <div { ...clickableMediaItemProps }>{ renderedMediaField }</div> <SingleSelectionCheckbox item={ item } selection={ selection } @@ -96,8 +114,10 @@ function GridItem< Item >( { justify="space-between" className="dataviews-view-grid__title-actions" > - <HStack className="dataviews-view-grid__primary-field"> - { renderedPrimaryField } + <HStack> + <div { ...clickablePrimaryItemProps }> + { renderedPrimaryField } + </div> </HStack> <ItemActions item={ item } actions={ actions } isCompact /> </HStack> @@ -170,6 +190,8 @@ export default function ViewGrid< Item >( { getItemId, isLoading, onChangeSelection, + onClickItem, + isItemClickable, selection, view, density, @@ -223,6 +245,8 @@ export default function ViewGrid< Item >( { key={ getItemId( item ) } selection={ selection } onChangeSelection={ onChangeSelection } + onClickItem={ onClickItem } + isItemClickable={ isItemClickable } getItemId={ getItemId } item={ item } actions={ actions } diff --git a/packages/dataviews/src/dataviews-layouts/grid/style.scss b/packages/dataviews/src/dataviews-layouts/grid/style.scss index 6286ed94685a04..55768240a18714 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/style.scss +++ b/packages/dataviews/src/dataviews-layouts/grid/style.scss @@ -17,8 +17,13 @@ .dataviews-view-grid__primary-field { min-height: $grid-unit-40; // Preserve layout when there is no ellipsis button + + &--clickable { + width: fit-content; + } } + &.is-selected { .dataviews-view-grid__fields .dataviews-view-grid__field .dataviews-view-grid__field-value { color: $gray-900; diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 4e1607b01489c2..8ef41db1c38798 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -35,11 +35,14 @@ import type { import type { SetSelection } from '../../private-types'; import ColumnHeaderMenu from './column-header-menu'; import { getVisibleFieldIds } from '../index'; +import getClickableItemProps from '../utils/get-clickable-item-props'; interface TableColumnFieldProps< Item > { primaryField?: NormalizedField< Item >; field: NormalizedField< Item >; item: Item; + isItemClickable: ( item: Item ) => boolean; + onClickItem: ( item: Item ) => void; } interface TableColumnCombinedProps< Item > { @@ -48,6 +51,8 @@ interface TableColumnCombinedProps< Item > { field: CombinedField; item: Item; view: ViewTableType; + isItemClickable: ( item: Item ) => boolean; + onClickItem: ( item: Item ) => void; } interface TableColumnProps< Item > { @@ -56,6 +61,8 @@ interface TableColumnProps< Item > { item: Item; column: string; view: ViewTableType; + isItemClickable: ( item: Item ) => boolean; + onClickItem: ( item: Item ) => void; } interface TableRowProps< Item > { @@ -69,6 +76,8 @@ interface TableRowProps< Item > { selection: string[]; getItemId: ( item: Item ) => string; onChangeSelection: SetSelection; + isItemClickable: ( item: Item ) => boolean; + onClickItem: ( item: Item ) => void; } function TableColumn< Item >( { @@ -102,15 +111,29 @@ function TableColumnField< Item >( { primaryField, item, field, + isItemClickable, + onClickItem, }: TableColumnFieldProps< Item > ) { + const isPrimaryField = primaryField?.id === field.id; + const isItemClickableField = ( i: Item ) => + isItemClickable( i ) && isPrimaryField; + + const clickableProps = getClickableItemProps( + item, + isItemClickableField, + onClickItem, + 'dataviews-view-table__cell-content' + ); + return ( <div className={ clsx( 'dataviews-view-table__cell-content-wrapper', { - 'dataviews-view-table__primary-field': - primaryField?.id === field.id, + 'dataviews-view-table__primary-field': isPrimaryField, } ) } > - <field.render { ...{ item } } /> + <div { ...clickableProps }> + <field.render { ...{ item } } /> + </div> </div> ); } @@ -139,6 +162,8 @@ function TableRow< Item >( { primaryField, selection, getItemId, + isItemClickable, + onClickItem, onChangeSelection, }: TableRowProps< Item > ) { const hasPossibleBulkAction = useHasAPossibleBulkAction( actions, item ); @@ -214,6 +239,8 @@ function TableRow< Item >( { <td key={ column } style={ { width, maxWidth, minWidth } }> <TableColumn primaryField={ primaryField } + isItemClickable={ isItemClickable } + onClickItem={ onClickItem } fields={ fields } item={ item } column={ column } @@ -252,6 +279,8 @@ function ViewTable< Item >( { onChangeSelection, selection, setOpenedFilter, + onClickItem, + isItemClickable, view, }: ViewTableProps< Item > ) { const headerMenuRefs = useRef< @@ -392,6 +421,8 @@ function ViewTable< Item >( { selection={ selection } getItemId={ getItemId } onChangeSelection={ onChangeSelection } + onClickItem={ onClickItem } + isItemClickable={ isItemClickable } /> ) ) } </tbody> diff --git a/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts b/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts new file mode 100644 index 00000000000000..e2a6081a68fa3e --- /dev/null +++ b/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts @@ -0,0 +1,22 @@ +export default function getClickableItemProps< Item >( + item: Item, + isItemClickable: ( item: Item ) => boolean, + onClickItem: ( item: Item ) => void, + className: string +) { + if ( ! isItemClickable( item ) ) { + return { className }; + } + + return { + className: `${ className } ${ className }--clickable`, + role: 'button', + tabIndex: 0, + onClick: () => onClickItem( item ), + onKeyDown: ( event: React.KeyboardEvent ) => { + if ( event.key === 'Enter' || event.key === '' ) { + onClickItem( item ); + } + }, + }; +} diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 0ea0965704d18c..71990f72d4eecd 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -498,6 +498,8 @@ export interface ViewBaseProps< Item > { onChangeSelection: SetSelection; selection: string[]; setOpenedFilter: ( fieldId: string ) => void; + onClickItem: ( item: Item ) => void; + isItemClickable: ( item: Item ) => boolean; view: View; density: number; } diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index e659a4f96f23f6..54f47052b144cf 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -36,12 +36,7 @@ import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies */ -import { - LAYOUT_GRID, - LAYOUT_TABLE, - OPERATOR_IS_ANY, -} from '../../utils/constants'; -import { default as Link } from '../routes/link'; +import { OPERATOR_IS_ANY } from '../../utils/constants'; // See https://github.com/WordPress/gutenberg/issues/55886 // We do not support custom statutes at the moment. @@ -139,7 +134,7 @@ function PostAuthorField( { item } ) { ); } -function usePostFields( viewType ) { +function usePostFields() { const { records: authors, isResolving: isLoadingAuthors } = useEntityRecords( 'root', 'user', { per_page: -1 } ); @@ -164,30 +159,10 @@ function usePostFields( viewType ) { ? item.title : item.title?.raw, render: ( { item } ) => { - const addLink = - [ LAYOUT_TABLE, LAYOUT_GRID ].includes( viewType ) && - item.status !== 'trash'; const renderedTitle = typeof item.title === 'string' ? item.title : item.title?.rendered; - const title = addLink ? ( - <Link - params={ { - postId: item.id, - postType: item.type, - canvas: 'edit', - } } - > - { decodeEntities( renderedTitle ) || - __( '(no title)' ) } - </Link> - ) : ( - <span> - { decodeEntities( renderedTitle ) || - __( '(no title)' ) } - </span> - ); let suffix = ''; if ( item.id === frontPageId ) { @@ -210,7 +185,10 @@ function usePostFields( viewType ) { alignment="center" justify="flex-start" > - { title } + <span> + { decodeEntities( renderedTitle ) || + __( '(no title)' ) } + </span> { suffix } </HStack> ); @@ -355,7 +333,7 @@ function usePostFields( viewType ) { }, passwordField, ], - [ authors, viewType, frontPageId, postsPageId ] + [ authors, frontPageId, postsPageId ] ); return { diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 4985af3050bd8d..4639cb3c950b76 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -208,9 +208,7 @@ export default function PostList( { postType } ) { return found?.filters ?? []; }; - const { isLoading: isLoadingFields, fields: _fields } = usePostFields( - view.type - ); + const { isLoading: isLoadingFields, fields: _fields } = usePostFields(); const fields = useMemo( () => { const activeViewFilters = getActiveViewFilters( defaultViews, @@ -402,6 +400,14 @@ export default function PostList( { postType } ) { onChangeView={ setView } selection={ selection } onChangeSelection={ onChangeSelection } + isItemClickable={ ( item ) => item.status !== 'trash' } + onClickItem={ ( { id } ) => { + history.push( { + postId: id, + postType, + canvas: 'edit', + } ); + } } getItemId={ getItemId } defaultLayouts={ defaultLayouts } header={ diff --git a/packages/edit-site/src/components/post-list/style.scss b/packages/edit-site/src/components/post-list/style.scss index db6a32408c7921..14bb11b41d4450 100644 --- a/packages/edit-site/src/components/post-list/style.scss +++ b/packages/edit-site/src/components/post-list/style.scss @@ -9,7 +9,9 @@ width: 100%; border-radius: $grid-unit-05; - &.is-layout-table:not(:has(.edit-site-post-list__featured-image-button)), + &.is-layout-table:not( + :has(.edit-site-post-list__featured-image-button) +), &.is-layout-table .edit-site-post-list__featured-image-button { width: $grid-unit-40; height: $grid-unit-40; @@ -46,7 +48,9 @@ border-radius: $grid-unit-05; &:focus-visible { - box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + box-shadow: + 0 0 0 var(--wp-admin-border-width-focus) + var(--wp-admin-theme-color); // Windows High Contrast mode will show this outline, but not the box-shadow. outline: 2px solid transparent; } @@ -54,7 +58,9 @@ .dataviews-view-grid__card.is-selected { .edit-site-post-list__featured-image-button::after { - box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + box-shadow: + inset 0 0 0 var(--wp-admin-border-width-focus) + var(--wp-admin-theme-color); background: rgba(var(--wp-admin-theme-color--rgb), 0.04); } } @@ -64,6 +70,26 @@ overflow: hidden; } +.dataviews-view-grid__primary-field.dataviews-view-grid__primary-field--clickable +.edit-site-post-list__title +span, +.dataviews-view-table__primary-field > .dataviews-view-table__cell-content--clickable +.edit-site-post-list__title +span { + text-decoration: none; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + display: block; + flex-grow: 0; + color: $gray-900; + + &:hover { + color: var(--wp-admin-theme-color); + } + @include link-reset(); +} + .edit-site-post-list__title-badge { background: $gray-100; color: $gray-800; diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 03ec43648f120f..0e5744fe362e35 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -1,7 +1,5 @@ @import "../../dataviews/src/style.scss"; -@import "../../fields/src/styles.scss"; -@import "../../fields/src/fields/featured-image/style.scss"; - +@import "../../fields/src/style.scss"; @import "./components/add-new-template/style.scss"; @import "./components/block-editor/style.scss"; @import "./components/canvas-loader/style.scss"; diff --git a/packages/fields/src/style.scss b/packages/fields/src/style.scss new file mode 100644 index 00000000000000..1639f455ba093e --- /dev/null +++ b/packages/fields/src/style.scss @@ -0,0 +1,2 @@ +@import "./fields/slug/style.scss"; +@import "./fields/featured-image/style.scss"; diff --git a/packages/fields/src/styles.scss b/packages/fields/src/styles.scss deleted file mode 100644 index cdb130337f1cd9..00000000000000 --- a/packages/fields/src/styles.scss +++ /dev/null @@ -1 +0,0 @@ -@import "./fields/slug/style.scss"; From f3e8f4a5c11a8bf2f7b4e8e2ff3c7963c23194f3 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 12 Nov 2024 13:17:30 +0100 Subject: [PATCH 1538/1908] Site Editor: Avoid using edited post selectors in welcome guide (#66926) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/edit-site/src/components/editor/index.js | 8 +++++++- packages/edit-site/src/components/welcome-guide/index.js | 6 +++--- packages/edit-site/src/components/welcome-guide/page.js | 8 +------- .../edit-site/src/components/welcome-guide/template.js | 9 +-------- 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 8f0ca0c5b29718..94b56a197e1bc1 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -218,7 +218,13 @@ export default function EditSiteEditor( { isPostsList = false } ) { <EditorKeyboardShortcutsRegister /> { isEditMode && <BlockKeyboardShortcuts /> } { ! isReady ? <CanvasLoader id={ loadingProgressId } /> : null } - { isEditMode && <WelcomeGuide /> } + { isEditMode && ( + <WelcomeGuide + postType={ + postWithTemplate ? contextPostType : editedPostType + } + /> + ) } { isReady && ( <Editor postType={ diff --git a/packages/edit-site/src/components/welcome-guide/index.js b/packages/edit-site/src/components/welcome-guide/index.js index 37804f1698c763..b127ecd664462d 100644 --- a/packages/edit-site/src/components/welcome-guide/index.js +++ b/packages/edit-site/src/components/welcome-guide/index.js @@ -6,13 +6,13 @@ import WelcomeGuideStyles from './styles'; import WelcomeGuidePage from './page'; import WelcomeGuideTemplate from './template'; -export default function WelcomeGuide() { +export default function WelcomeGuide( { postType } ) { return ( <> <WelcomeGuideEditor /> <WelcomeGuideStyles /> - <WelcomeGuidePage /> - <WelcomeGuideTemplate /> + { postType === 'page' && <WelcomeGuidePage /> } + { postType === 'wp_template' && <WelcomeGuideTemplate /> } </> ); } diff --git a/packages/edit-site/src/components/welcome-guide/page.js b/packages/edit-site/src/components/welcome-guide/page.js index db89d9b653ad58..41bb80342280cf 100644 --- a/packages/edit-site/src/components/welcome-guide/page.js +++ b/packages/edit-site/src/components/welcome-guide/page.js @@ -6,11 +6,6 @@ import { Guide } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { store as preferencesStore } from '@wordpress/preferences'; -/** - * Internal dependencies - */ -import { store as editSiteStore } from '../../store'; - export default function WelcomeGuidePage() { const { toggle } = useDispatch( preferencesStore ); @@ -23,8 +18,7 @@ export default function WelcomeGuidePage() { 'core/edit-site', 'welcomeGuide' ); - const { isPage } = select( editSiteStore ); - return isPageActive && ! isEditorActive && isPage(); + return isPageActive && ! isEditorActive; }, [] ); if ( ! isVisible ) { diff --git a/packages/edit-site/src/components/welcome-guide/template.js b/packages/edit-site/src/components/welcome-guide/template.js index e6568a23bb3a3c..bf08bc7fa668bd 100644 --- a/packages/edit-site/src/components/welcome-guide/template.js +++ b/packages/edit-site/src/components/welcome-guide/template.js @@ -7,16 +7,9 @@ import { __ } from '@wordpress/i18n'; import { store as preferencesStore } from '@wordpress/preferences'; import { store as editorStore } from '@wordpress/editor'; -/** - * Internal dependencies - */ -import useEditedEntityRecord from '../use-edited-entity-record'; - export default function WelcomeGuideTemplate() { const { toggle } = useDispatch( preferencesStore ); - const { isLoaded, record } = useEditedEntityRecord(); - const isPostTypeTemplate = isLoaded && record.type === 'wp_template'; const { isActive, hasPreviousEntity } = useSelect( ( select ) => { const { getEditorSettings } = select( editorStore ); const { get } = select( preferencesStore ); @@ -26,7 +19,7 @@ export default function WelcomeGuideTemplate() { !! getEditorSettings().onNavigateToPreviousEntityRecord, }; }, [] ); - const isVisible = isActive && isPostTypeTemplate && hasPreviousEntity; + const isVisible = isActive && hasPreviousEntity; if ( ! isVisible ) { return null; From 99fd9c71f6fe422b5d43bb65b3b3b36fa28fb507 Mon Sep 17 00:00:00 2001 From: Ankit Kumar Shah <ankit.shah@rtcamp.com> Date: Tue, 12 Nov 2024 19:02:14 +0530 Subject: [PATCH 1539/1908] Media & Text: Set `.wp-block-media-text__media a` display to block (#66915) Ajusted the display property from `inline-block` to `block` to resolve layout issues in the Media & Text block anchor link. Co-authored-by: Infinite-Null <ankitkumarshah@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ajmaurya99 <ajmaurya@git.wordpress.org> --- packages/block-library/src/media-text/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/media-text/style.scss b/packages/block-library/src/media-text/style.scss index 0f7a34f05548c0..727380a3759c6e 100644 --- a/packages/block-library/src/media-text/style.scss +++ b/packages/block-library/src/media-text/style.scss @@ -69,7 +69,7 @@ } .wp-block-media-text__media a { - display: inline-block; + display: block; } .wp-block-media-text__media img, From d2bc9ea5ef15c5aa56f4db2a1dca6718ce679693 Mon Sep 17 00:00:00 2001 From: David Arenas <david.arenas@automattic.com> Date: Tue, 12 Nov 2024 15:12:09 +0100 Subject: [PATCH 1540/1908] Interactivity API: fix property modification from inherited context two or more levels above (#66872) * Add failing test * Fix code * Add changelog entry * Define "modal" prop in submenu context Co-authored-by: DAreRodz <darerodz@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: danielpost <danielpost@git.wordpress.org> --- .../block-library/src/navigation/index.php | 2 +- packages/interactivity/CHANGELOG.md | 4 ++++ packages/interactivity/src/proxies/context.ts | 3 +++ .../src/proxies/test/context-proxy.ts | 18 ++++++++++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index fa9bb5a56f8012..9484ad13ed002a 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -813,7 +813,7 @@ function block_core_navigation_add_directives_to_submenu( $tags, $block_attribut ) ) { // Add directives to the parent `<li>`. $tags->set_attribute( 'data-wp-interactive', 'core/navigation' ); - $tags->set_attribute( 'data-wp-context', '{ "submenuOpenedBy": { "click": false, "hover": false, "focus": false }, "type": "submenu" }' ); + $tags->set_attribute( 'data-wp-context', '{ "submenuOpenedBy": { "click": false, "hover": false, "focus": false }, "type": "submenu", "modal": null }' ); $tags->set_attribute( 'data-wp-watch', 'callbacks.initMenu' ); $tags->set_attribute( 'data-wp-on--focusout', 'actions.handleMenuFocusout' ); $tags->set_attribute( 'data-wp-on--keydown', 'actions.handleMenuKeydown' ); diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 488fcc77d7541d..6963ed57a48aed 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- Fix property modification from inherited context two or more levels above ([#66872](https://github.com/WordPress/gutenberg/pull/66872)). + ## 6.11.0 (2024-10-30) ### Bug Fixes diff --git a/packages/interactivity/src/proxies/context.ts b/packages/interactivity/src/proxies/context.ts index 64517c91a6940e..8d5bc54a8b831a 100644 --- a/packages/interactivity/src/proxies/context.ts +++ b/packages/interactivity/src/proxies/context.ts @@ -38,6 +38,9 @@ const contextHandlers: ProxyHandler< object > = { getOwnPropertyDescriptor: ( target, key ) => descriptor( target, key ) || descriptor( contextObjectToFallback.get( target ), key ), + has: ( target, key ) => + Reflect.has( target, key ) || + Reflect.has( contextObjectToFallback.get( target ), key ), }; /** diff --git a/packages/interactivity/src/proxies/test/context-proxy.ts b/packages/interactivity/src/proxies/test/context-proxy.ts index 1e4a969d0f9dc6..6ae041d34dbc08 100644 --- a/packages/interactivity/src/proxies/test/context-proxy.ts +++ b/packages/interactivity/src/proxies/test/context-proxy.ts @@ -137,6 +137,24 @@ describe( 'Interactivity API', () => { expect( context.a ).toBe( 2 ); expect( state.a ).toBe( 2 ); } ); + + it( "should modify props inherited from fallback's ancestors", () => { + const ancestor: any = proxifyContext( + { ancestorProp: 'ancestor' }, + {} + ); + const fallback: any = proxifyContext( + { fallbackProp: 'fallback' }, + ancestor + ); + const context: any = proxifyContext( {}, fallback ); + + context.ancestorProp = 'modified'; + + expect( context.ancestorProp ).toBe( 'modified' ); + expect( fallback.ancestorProp ).toBe( 'modified' ); + expect( ancestor.ancestorProp ).toBe( 'modified' ); + } ); } ); describe( 'computations', () => { From af6d302df00db44d3c5526972128d3ae65470bed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 12 Nov 2024 18:12:11 +0100 Subject: [PATCH 1541/1908] Post fields: move `status` from `edit-site` to `fields` package (#66937) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../src/components/post-fields/index.js | 81 +------------------ packages/fields/README.md | 4 + packages/fields/src/fields/index.ts | 1 + packages/fields/src/fields/status/index.tsx | 32 ++++++++ .../src/fields/status/status-elements.tsx | 50 ++++++++++++ .../fields/src/fields/status/status-view.tsx | 28 +++++++ 6 files changed, 118 insertions(+), 78 deletions(-) create mode 100644 packages/fields/src/fields/status/index.tsx create mode 100644 packages/fields/src/fields/status/status-elements.tsx create mode 100644 packages/fields/src/fields/status/status-view.tsx diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 54f47052b144cf..3471499c8f21c1 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -13,6 +13,7 @@ import { slugField, parentField, passwordField, + statusField, } from '@wordpress/fields'; import { createInterpolateElement, @@ -20,82 +21,17 @@ import { useState, } from '@wordpress/element'; import { dateI18n, getDate, getSettings } from '@wordpress/date'; -import { - trash, - drafts, - published, - scheduled, - pending, - notAllowed, - commentAuthorAvatar as authorIcon, -} from '@wordpress/icons'; +import { commentAuthorAvatar as authorIcon } from '@wordpress/icons'; import { __experimentalHStack as HStack, Icon } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; -/** - * Internal dependencies - */ -import { OPERATOR_IS_ANY } from '../../utils/constants'; - -// See https://github.com/WordPress/gutenberg/issues/55886 -// We do not support custom statutes at the moment. -const STATUSES = [ - { - value: 'draft', - label: __( 'Draft' ), - icon: drafts, - description: __( 'Not ready to publish.' ), - }, - { - value: 'future', - label: __( 'Scheduled' ), - icon: scheduled, - description: __( 'Publish automatically on a chosen date.' ), - }, - { - value: 'pending', - label: __( 'Pending Review' ), - icon: pending, - description: __( 'Waiting for review before publishing.' ), - }, - { - value: 'private', - label: __( 'Private' ), - icon: notAllowed, - description: __( 'Only visible to site admins and editors.' ), - }, - { - value: 'publish', - label: __( 'Published' ), - icon: published, - description: __( 'Visible to everyone.' ), - }, - { value: 'trash', label: __( 'Trash' ), icon: trash }, -]; - const getFormattedDate = ( dateToDisplay ) => dateI18n( getSettings().formats.datetimeAbbreviated, getDate( dateToDisplay ) ); -function PostStatusField( { item } ) { - const status = STATUSES.find( ( { value } ) => value === item.status ); - const label = status?.label || item.status; - const icon = status?.icon; - return ( - <HStack alignment="left" spacing={ 0 }> - { icon && ( - <div className="edit-site-post-list__status-icon"> - <Icon icon={ icon } /> - </div> - ) } - <span>{ label }</span> - </HStack> - ); -} - function PostAuthorField( { item } ) { const { text, imageUrl } = useSelect( ( select ) => { @@ -214,18 +150,7 @@ function usePostFields() { : nameB.localeCompare( nameA ); }, }, - { - label: __( 'Status' ), - id: 'status', - type: 'text', - elements: STATUSES, - render: PostStatusField, - Edit: 'radio', - enableSorting: false, - filterBy: { - operators: [ OPERATOR_IS_ANY ], - }, - }, + statusField, { label: __( 'Date' ), id: 'date', diff --git a/packages/fields/README.md b/packages/fields/README.md index 214f3d6ee3a50a..1571dd72e6a79c 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -82,6 +82,10 @@ Undocumented declaration. Undocumented declaration. +### statusField + +Status field for BasePost. + ### titleField Undocumented declaration. diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts index 29cbdeb2a4ba6b..9a4799f13a0d1d 100644 --- a/packages/fields/src/fields/index.ts +++ b/packages/fields/src/fields/index.ts @@ -4,3 +4,4 @@ export { default as orderField } from './order'; export { default as featuredImageField } from './featured-image'; export { default as parentField } from './parent'; export { default as passwordField } from './password'; +export { default as statusField } from './status'; diff --git a/packages/fields/src/fields/status/index.tsx b/packages/fields/src/fields/status/index.tsx new file mode 100644 index 00000000000000..374277bc7260ed --- /dev/null +++ b/packages/fields/src/fields/status/index.tsx @@ -0,0 +1,32 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import StatusView from './status-view'; +import STATUSES from './status-elements'; + +const OPERATOR_IS_ANY = 'isAny'; + +const statusField: Field< BasePost > = { + label: __( 'Status' ), + id: 'status', + type: 'text', + elements: STATUSES, + render: StatusView, + Edit: 'radio', + enableSorting: false, + filterBy: { + operators: [ OPERATOR_IS_ANY ], + }, +}; + +/** + * Status field for BasePost. + */ +export default statusField; diff --git a/packages/fields/src/fields/status/status-elements.tsx b/packages/fields/src/fields/status/status-elements.tsx new file mode 100644 index 00000000000000..079612270e6379 --- /dev/null +++ b/packages/fields/src/fields/status/status-elements.tsx @@ -0,0 +1,50 @@ +/** + * WordPress dependencies + */ +import { + trash, + drafts, + published, + scheduled, + pending, + notAllowed, +} from '@wordpress/icons'; +import { __ } from '@wordpress/i18n'; + +// See https://github.com/WordPress/gutenberg/issues/55886 +// We do not support custom statutes at the moment. +const STATUSES = [ + { + value: 'draft', + label: __( 'Draft' ), + icon: drafts, + description: __( 'Not ready to publish.' ), + }, + { + value: 'future', + label: __( 'Scheduled' ), + icon: scheduled, + description: __( 'Publish automatically on a chosen date.' ), + }, + { + value: 'pending', + label: __( 'Pending Review' ), + icon: pending, + description: __( 'Waiting for review before publishing.' ), + }, + { + value: 'private', + label: __( 'Private' ), + icon: notAllowed, + description: __( 'Only visible to site admins and editors.' ), + }, + { + value: 'publish', + label: __( 'Published' ), + icon: published, + description: __( 'Visible to everyone.' ), + }, + { value: 'trash', label: __( 'Trash' ), icon: trash }, +]; + +export default STATUSES; diff --git a/packages/fields/src/fields/status/status-view.tsx b/packages/fields/src/fields/status/status-view.tsx new file mode 100644 index 00000000000000..4f3c0547431ac9 --- /dev/null +++ b/packages/fields/src/fields/status/status-view.tsx @@ -0,0 +1,28 @@ +/** + * WordPress dependencies + */ +import { __experimentalHStack as HStack, Icon } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import STATUSES from './status-elements'; + +function StatusView( { item }: { item: BasePost } ) { + const status = STATUSES.find( ( { value } ) => value === item.status ); + const label = status?.label || item.status; + const icon = status?.icon; + return ( + <HStack alignment="left" spacing={ 0 }> + { icon && ( + <div className="edit-site-post-list__status-icon"> + <Icon icon={ icon } /> + </div> + ) } + <span>{ label }</span> + </HStack> + ); +} + +export default StatusView; From 7a6f7a8d62b17c63e9faff14576b65a3afa4d162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 12 Nov 2024 18:47:02 +0100 Subject: [PATCH 1542/1908] Post fields: clean up (#66941) --- .../featured-image/featured-image-edit.tsx | 3 ++- .../featured-image/featured-image-view.tsx | 2 +- .../fields/src/fields/featured-image/index.ts | 3 +-- packages/fields/src/fields/order/index.ts | 3 ++- packages/fields/src/fields/parent/index.ts | 3 +-- .../fields/src/fields/parent/parent-edit.tsx | 18 +++++++++--------- .../fields/src/fields/parent/parent-view.tsx | 4 ++-- packages/fields/src/fields/password/index.tsx | 1 - packages/fields/src/fields/slug/index.ts | 3 +-- 9 files changed, 19 insertions(+), 21 deletions(-) diff --git a/packages/fields/src/fields/featured-image/featured-image-edit.tsx b/packages/fields/src/fields/featured-image/featured-image-edit.tsx index b0dc612cdcfa50..ee51e5c60f13e0 100644 --- a/packages/fields/src/fields/featured-image/featured-image-edit.tsx +++ b/packages/fields/src/fields/featured-image/featured-image-edit.tsx @@ -9,11 +9,12 @@ import { MediaUpload } from '@wordpress/media-utils'; import { lineSolid } from '@wordpress/icons'; import { store as coreStore } from '@wordpress/core-data'; import type { DataFormControlProps } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; + /** * Internal dependencies */ import type { BasePost } from '../../types'; -import { __ } from '@wordpress/i18n'; export const FeaturedImageEdit = ( { data, diff --git a/packages/fields/src/fields/featured-image/featured-image-view.tsx b/packages/fields/src/fields/featured-image/featured-image-view.tsx index 36793e6f2ff9ab..1f4b55183f2383 100644 --- a/packages/fields/src/fields/featured-image/featured-image-view.tsx +++ b/packages/fields/src/fields/featured-image/featured-image-view.tsx @@ -3,12 +3,12 @@ */ import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; +import type { DataViewRenderFieldProps } from '@wordpress/dataviews'; /** * Internal dependencies */ import type { BasePost } from '../../types'; -import type { DataViewRenderFieldProps } from '@wordpress/dataviews'; export const FeaturedImageView = ( { item, diff --git a/packages/fields/src/fields/featured-image/index.ts b/packages/fields/src/fields/featured-image/index.ts index 44f9a1b4064648..62d7e8240aded0 100644 --- a/packages/fields/src/fields/featured-image/index.ts +++ b/packages/fields/src/fields/featured-image/index.ts @@ -2,12 +2,12 @@ * WordPress dependencies */ import type { Field } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ import type { BasePost } from '../../types'; -import { __ } from '@wordpress/i18n'; import { FeaturedImageEdit } from './featured-image-edit'; import { FeaturedImageView } from './featured-image-view'; @@ -15,7 +15,6 @@ const featuredImageField: Field< BasePost > = { id: 'featured_media', type: 'text', label: __( 'Featured Image' ), - getValue: ( { item } ) => item.featured_media, Edit: FeaturedImageEdit, render: FeaturedImageView, enableSorting: false, diff --git a/packages/fields/src/fields/order/index.ts b/packages/fields/src/fields/order/index.ts index 2fc0a216dcfa03..984a94c6427fc6 100644 --- a/packages/fields/src/fields/order/index.ts +++ b/packages/fields/src/fields/order/index.ts @@ -3,14 +3,15 @@ */ import type { Field } from '@wordpress/dataviews'; import { __ } from '@wordpress/i18n'; + /** * Internal dependencies */ import type { BasePost } from '../../types'; const orderField: Field< BasePost > = { - type: 'integer', id: 'menu_order', + type: 'integer', label: __( 'Order' ), description: __( 'Determines the order of pages.' ), }; diff --git a/packages/fields/src/fields/parent/index.ts b/packages/fields/src/fields/parent/index.ts index 2476d071b81652..8b833e1d9369df 100644 --- a/packages/fields/src/fields/parent/index.ts +++ b/packages/fields/src/fields/parent/index.ts @@ -2,12 +2,12 @@ * WordPress dependencies */ import type { Field } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ import type { BasePost } from '../../types'; -import { __ } from '@wordpress/i18n'; import { ParentEdit } from './parent-edit'; import { ParentView } from './parent-view'; @@ -15,7 +15,6 @@ const parentField: Field< BasePost > = { id: 'parent', type: 'text', label: __( 'Parent' ), - getValue: ( { item } ) => item.parent, Edit: ParentEdit, render: ParentView, enableSorting: true, diff --git a/packages/fields/src/fields/parent/parent-edit.tsx b/packages/fields/src/fields/parent/parent-edit.tsx index 030287b8f8fc55..21cdbee7a365a4 100644 --- a/packages/fields/src/fields/parent/parent-edit.tsx +++ b/packages/fields/src/fields/parent/parent-edit.tsx @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import removeAccents from 'remove-accents'; + /** * WordPress dependencies */ @@ -12,21 +17,16 @@ import { // @ts-ignore import { store as coreStore } from '@wordpress/core-data'; import type { DataFormControlProps } from '@wordpress/dataviews'; - -/** - * External dependencies - */ -import removeAccents from 'remove-accents'; +import { debounce } from '@wordpress/compose'; +import { decodeEntities } from '@wordpress/html-entities'; +import { __, sprintf } from '@wordpress/i18n'; +import { filterURLForDisplay } from '@wordpress/url'; /** * Internal dependencies */ -import { debounce } from '@wordpress/compose'; -import { decodeEntities } from '@wordpress/html-entities'; -import { __, sprintf } from '@wordpress/i18n'; import type { BasePost } from '../../types'; import { getTitleWithFallbackName } from './utils'; -import { filterURLForDisplay } from '@wordpress/url'; type TreeBase = { id: number; diff --git a/packages/fields/src/fields/parent/parent-view.tsx b/packages/fields/src/fields/parent/parent-view.tsx index f0d449db726c32..20c6cb939b4b92 100644 --- a/packages/fields/src/fields/parent/parent-view.tsx +++ b/packages/fields/src/fields/parent/parent-view.tsx @@ -3,14 +3,14 @@ */ import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; +import type { DataViewRenderFieldProps } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ import type { BasePost } from '../../types'; -import type { DataViewRenderFieldProps } from '@wordpress/dataviews'; import { getTitleWithFallbackName } from './utils'; -import { __ } from '@wordpress/i18n'; export const ParentView = ( { item, diff --git a/packages/fields/src/fields/password/index.tsx b/packages/fields/src/fields/password/index.tsx index aa7bc57e3f7cae..dacd0d7435998a 100644 --- a/packages/fields/src/fields/password/index.tsx +++ b/packages/fields/src/fields/password/index.tsx @@ -12,7 +12,6 @@ import PasswordEdit from './edit'; const passwordField: Field< BasePost > = { id: 'password', type: 'text', - getValue: ( { item } ) => item.password, Edit: PasswordEdit, enableSorting: false, enableHiding: false, diff --git a/packages/fields/src/fields/slug/index.ts b/packages/fields/src/fields/slug/index.ts index 4e81996ceaa6e8..c43fcc679622ac 100644 --- a/packages/fields/src/fields/slug/index.ts +++ b/packages/fields/src/fields/slug/index.ts @@ -2,12 +2,12 @@ * WordPress dependencies */ import type { Field } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ import type { BasePost } from '../../types'; -import { __ } from '@wordpress/i18n'; import SlugEdit from './slug-edit'; import SlugView from './slug-view'; @@ -15,7 +15,6 @@ const slugField: Field< BasePost > = { id: 'slug', type: 'text', label: __( 'Slug' ), - getValue: ( { item } ) => item.slug, Edit: SlugEdit, render: SlugView, }; From a315a904894faf5ca86110f033238510eab19752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 12 Nov 2024 18:59:09 +0100 Subject: [PATCH 1543/1908] Post fields: move `comment_status` from `edit-site` to `fields` package (#66934) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../src/components/post-fields/index.js | 28 +------------ packages/fields/README.md | 4 ++ .../src/fields/comment-status/index.tsx | 40 +++++++++++++++++++ packages/fields/src/fields/index.ts | 1 + 4 files changed, 47 insertions(+), 26 deletions(-) create mode 100644 packages/fields/src/fields/comment-status/index.tsx diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 3471499c8f21c1..083d971d102eb3 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -14,6 +14,7 @@ import { parentField, passwordField, statusField, + commentStatusField, } from '@wordpress/fields'; import { createInterpolateElement, @@ -230,32 +231,7 @@ function usePostFields() { }, slugField, parentField, - { - id: 'comment_status', - label: __( 'Discussion' ), - type: 'text', - Edit: 'radio', - enableSorting: false, - filterBy: { - operators: [], - }, - elements: [ - { - value: 'open', - label: __( 'Open' ), - description: __( - 'Visitors can add new comments and replies.' - ), - }, - { - value: 'closed', - label: __( 'Closed' ), - description: __( - 'Visitors cannot add new comments or replies. Existing comments remain visible.' - ), - }, - ], - }, + commentStatusField, passwordField, ], [ authors, frontPageId, postsPageId ] diff --git a/packages/fields/README.md b/packages/fields/README.md index 1571dd72e6a79c..1d673c4d46c7b1 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -14,6 +14,10 @@ npm install @wordpress/fields --save <!-- START TOKEN(Autogenerated API docs) --> +### commentStatusField + +Comment status field for BasePost. + ### deletePost Undocumented declaration. diff --git a/packages/fields/src/fields/comment-status/index.tsx b/packages/fields/src/fields/comment-status/index.tsx new file mode 100644 index 00000000000000..7f373bc14e2108 --- /dev/null +++ b/packages/fields/src/fields/comment-status/index.tsx @@ -0,0 +1,40 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; + +const commentStatusField: Field< BasePost > = { + id: 'comment_status', + label: __( 'Discussion' ), + type: 'text', + Edit: 'radio', + enableSorting: false, + filterBy: { + operators: [], + }, + elements: [ + { + value: 'open', + label: __( 'Open' ), + description: __( 'Visitors can add new comments and replies.' ), + }, + { + value: 'closed', + label: __( 'Closed' ), + description: __( + 'Visitors cannot add new comments or replies. Existing comments remain visible.' + ), + }, + ], +}; + +/** + * Comment status field for BasePost. + */ +export default commentStatusField; diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts index 9a4799f13a0d1d..fba34eb2388a39 100644 --- a/packages/fields/src/fields/index.ts +++ b/packages/fields/src/fields/index.ts @@ -5,3 +5,4 @@ export { default as featuredImageField } from './featured-image'; export { default as parentField } from './parent'; export { default as passwordField } from './password'; export { default as statusField } from './status'; +export { default as commentStatusField } from './comment-status'; From 9be61c4fc7da2edb4172fa31f95b99c3e525b930 Mon Sep 17 00:00:00 2001 From: Vrishabh Jasani <71686151+Vrishabhsk@users.noreply.github.com> Date: Tue, 12 Nov 2024 23:45:34 +0400 Subject: [PATCH 1544/1908] Storybook: Improve component organisation - Actions (#66680) * Move Menu component under Actions container * Add id Co-authored-by: Vrishabhsk <vrishabhsk@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/src/menu/stories/index.story.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/components/src/menu/stories/index.story.tsx b/packages/components/src/menu/stories/index.story.tsx index ecb4cc3c7593f8..92501c33269580 100644 --- a/packages/components/src/menu/stories/index.story.tsx +++ b/packages/components/src/menu/stories/index.story.tsx @@ -22,7 +22,8 @@ import { createSlotFill, Provider as SlotFillProvider } from '../../slot-fill'; import { ContextSystemProvider } from '../../context'; const meta: Meta< typeof Menu > = { - title: 'Components (Experimental)/Menu', + id: 'components-experimental-menu', + title: 'Components (Experimental)/Actions/Menu', component: Menu, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 From 2313836d2062c4ba6d754d51b69df329b25dcd14 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Wed, 13 Nov 2024 01:23:49 +0530 Subject: [PATCH 1545/1908] Feat: Storybook: Improve component organisation - Overlays Category - Issue #66275 (#66657) * Group the overlay components in storybook * Fix the id for the experimental components * Remove unwanted changes from the PR Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/src/confirm-dialog/stories/index.story.tsx | 3 ++- packages/components/src/dropdown/stories/index.story.tsx | 3 ++- packages/components/src/modal/stories/index.story.tsx | 3 ++- packages/components/src/popover/stories/index.story.tsx | 3 ++- packages/components/src/tooltip/stories/index.story.tsx | 3 ++- storybook/preview.js | 3 ++- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/components/src/confirm-dialog/stories/index.story.tsx b/packages/components/src/confirm-dialog/stories/index.story.tsx index 85636c0ddc81ed..9496d85939edf3 100644 --- a/packages/components/src/confirm-dialog/stories/index.story.tsx +++ b/packages/components/src/confirm-dialog/stories/index.story.tsx @@ -16,7 +16,8 @@ import { ConfirmDialog } from '../component'; const meta: Meta< typeof ConfirmDialog > = { component: ConfirmDialog, - title: 'Components (Experimental)/ConfirmDialog', + title: 'Components (Experimental)/Overlays/ConfirmDialog', + id: 'components-experimental-confirmdialog', argTypes: { isOpen: { control: { type: null }, diff --git a/packages/components/src/dropdown/stories/index.story.tsx b/packages/components/src/dropdown/stories/index.story.tsx index 0f07664787cc33..bfa51a07a97170 100644 --- a/packages/components/src/dropdown/stories/index.story.tsx +++ b/packages/components/src/dropdown/stories/index.story.tsx @@ -13,7 +13,8 @@ import MenuItem from '../../menu-item'; import { DropdownContentWrapper } from '../dropdown-content-wrapper'; const meta: Meta< typeof Dropdown > = { - title: 'Components/Dropdown', + title: 'Components/Overlays/Dropdown', + id: 'components-dropdown', component: Dropdown, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { DropdownContentWrapper }, diff --git a/packages/components/src/modal/stories/index.story.tsx b/packages/components/src/modal/stories/index.story.tsx index f180de0dc06a46..92c922bcb8a977 100644 --- a/packages/components/src/modal/stories/index.story.tsx +++ b/packages/components/src/modal/stories/index.story.tsx @@ -19,7 +19,8 @@ import type { ModalProps } from '../types'; const meta: Meta< typeof Modal > = { component: Modal, - title: 'Components/Modal', + title: 'Components/Overlays/Modal', + id: 'components-modal', argTypes: { children: { control: { type: null }, diff --git a/packages/components/src/popover/stories/index.story.tsx b/packages/components/src/popover/stories/index.story.tsx index dfffaefe802a49..3d804f5d24d5c0 100644 --- a/packages/components/src/popover/stories/index.story.tsx +++ b/packages/components/src/popover/stories/index.story.tsx @@ -33,7 +33,8 @@ const AVAILABLE_PLACEMENTS: PopoverProps[ 'placement' ][] = [ ]; const meta: Meta< typeof Popover > = { - title: 'Components/Popover', + title: 'Components/Overlays/Popover', + id: 'components-popover', component: Popover, argTypes: { anchor: { control: { type: null } }, diff --git a/packages/components/src/tooltip/stories/index.story.tsx b/packages/components/src/tooltip/stories/index.story.tsx index b006bc03aced96..4bddba0ff7b666 100644 --- a/packages/components/src/tooltip/stories/index.story.tsx +++ b/packages/components/src/tooltip/stories/index.story.tsx @@ -15,7 +15,8 @@ import Tooltip from '..'; import Button from '../../button'; const meta: Meta< typeof Tooltip > = { - title: 'Components/Tooltip', + title: 'Components/Overlays/Tooltip', + id: 'components-tooltip', component: Tooltip, argTypes: { children: { control: { type: null } }, diff --git a/storybook/preview.js b/storybook/preview.js index 9e9dd587b39c4c..ca90ad99e405de 100644 --- a/storybook/preview.js +++ b/storybook/preview.js @@ -134,10 +134,11 @@ export const parameters = { 'Containers', 'Feedback', 'Navigation', + 'Overlays', 'Utilities', ], 'Components (Experimental)', - [ 'Navigation' ], + [ 'Navigation', 'Overlays' ], 'Icons', ], }, From 2a3e37937499cdc44a93de0a306307ec5f02be5c Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Wed, 13 Nov 2024 02:03:22 +0530 Subject: [PATCH 1546/1908] Feat: Storybook: Improve component organisation - Typography - Issue #66275 (#66633) * Group the components in storybook based on sitemap provided * Fix the experimental id for components in storybook * Revert the unwanted changes in PR * Add the missing folder on conflicts resolve --------- Co-authored-by: Lena Morita <lena@jaguchi.com> Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/components/src/heading/stories/index.story.tsx | 3 ++- packages/components/src/text-highlight/stories/index.story.tsx | 3 ++- packages/components/src/text/stories/index.story.tsx | 3 ++- packages/components/src/truncate/stories/index.story.tsx | 3 ++- .../components/src/visually-hidden/stories/index.story.tsx | 2 +- storybook/preview.js | 3 ++- 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/components/src/heading/stories/index.story.tsx b/packages/components/src/heading/stories/index.story.tsx index d82a59f08c825b..8777fb2c2e6507 100644 --- a/packages/components/src/heading/stories/index.story.tsx +++ b/packages/components/src/heading/stories/index.story.tsx @@ -10,7 +10,8 @@ import { Heading } from '..'; const meta: Meta< typeof Heading > = { component: Heading, - title: 'Components (Experimental)/Heading', + title: 'Components (Experimental)/Typography/Heading', + id: 'components-experimental-heading', argTypes: { as: { control: { type: 'text' } }, color: { control: { type: 'color' } }, diff --git a/packages/components/src/text-highlight/stories/index.story.tsx b/packages/components/src/text-highlight/stories/index.story.tsx index d54149d8e19d3c..f9538b7130095d 100644 --- a/packages/components/src/text-highlight/stories/index.story.tsx +++ b/packages/components/src/text-highlight/stories/index.story.tsx @@ -10,7 +10,8 @@ import TextHighlight from '..'; const meta: Meta< typeof TextHighlight > = { component: TextHighlight, - title: 'Components/TextHighlight', + title: 'Components/Typography/TextHighlight', + id: 'components-texthighlight', parameters: { controls: { expanded: true, diff --git a/packages/components/src/text/stories/index.story.tsx b/packages/components/src/text/stories/index.story.tsx index f762ca3b4e3ff7..92a2c7eb9be3e3 100644 --- a/packages/components/src/text/stories/index.story.tsx +++ b/packages/components/src/text/stories/index.story.tsx @@ -10,7 +10,8 @@ import { Text } from '../component'; const meta: Meta< typeof Text > = { component: Text, - title: 'Components (Experimental)/Text', + title: 'Components (Experimental)/Typography/Text', + id: 'components-experimental-text', argTypes: { as: { control: { type: 'text' } }, color: { control: { type: 'color' } }, diff --git a/packages/components/src/truncate/stories/index.story.tsx b/packages/components/src/truncate/stories/index.story.tsx index 84eaf59edbb3e1..3b06831c59aa07 100644 --- a/packages/components/src/truncate/stories/index.story.tsx +++ b/packages/components/src/truncate/stories/index.story.tsx @@ -10,7 +10,8 @@ import { Truncate } from '..'; const meta: Meta< typeof Truncate > = { component: Truncate, - title: 'Components (Experimental)/Truncate', + title: 'Components (Experimental)/Typography/Truncate', + id: 'components-experimental-truncate', argTypes: { children: { control: { type: 'text' } }, as: { control: { type: 'text' } }, diff --git a/packages/components/src/visually-hidden/stories/index.story.tsx b/packages/components/src/visually-hidden/stories/index.story.tsx index 8abe45a94aab4f..6ebcf9a2e949ce 100644 --- a/packages/components/src/visually-hidden/stories/index.story.tsx +++ b/packages/components/src/visually-hidden/stories/index.story.tsx @@ -10,7 +10,7 @@ import { VisuallyHidden } from '..'; const meta: Meta< typeof VisuallyHidden > = { component: VisuallyHidden, - title: 'Components/Utilities/VisuallyHidden', + title: 'Components/Typography/VisuallyHidden', id: 'components-visuallyhidden', argTypes: { children: { control: { type: null } }, diff --git a/storybook/preview.js b/storybook/preview.js index ca90ad99e405de..a045b0c3303d39 100644 --- a/storybook/preview.js +++ b/storybook/preview.js @@ -135,10 +135,11 @@ export const parameters = { 'Feedback', 'Navigation', 'Overlays', + 'Typography', 'Utilities', ], 'Components (Experimental)', - [ 'Navigation', 'Overlays' ], + [ 'Navigation', 'Overlays', 'Typography' ], 'Icons', ], }, From 074dc52e6b3ac5362392d309e79ebc63eb884a57 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 13 Nov 2024 09:45:18 +1100 Subject: [PATCH 1547/1908] Media: add `x-wav` mime type for wav files in Firefox (#66850) Adding x-wav support because Firefox uses that identifier Check if wav does not exist in case some plugins or themes have already filtered it out. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: Imran92 <imranh920@git.wordpress.org> --- backport-changelog/6.8/7265.md | 3 +++ lib/compat/wordpress-6.8/functions.php | 35 ++++++++++++++++++++++++++ lib/load.php | 1 + 3 files changed, 39 insertions(+) create mode 100644 backport-changelog/6.8/7265.md create mode 100644 lib/compat/wordpress-6.8/functions.php diff --git a/backport-changelog/6.8/7265.md b/backport-changelog/6.8/7265.md new file mode 100644 index 00000000000000..d4c46d62fa3334 --- /dev/null +++ b/backport-changelog/6.8/7265.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7265 + +* https://github.com/WordPress/gutenberg/pull/66850 diff --git a/lib/compat/wordpress-6.8/functions.php b/lib/compat/wordpress-6.8/functions.php new file mode 100644 index 00000000000000..eb57b2bb9890e7 --- /dev/null +++ b/lib/compat/wordpress-6.8/functions.php @@ -0,0 +1,35 @@ +<?php + +/** + * Adds the x-wav mime type to the list of mime types. + * This is necessary for Firefox as it uses the identifier for uploaded .wav files. + * Core backport should add the following to the default mime_types filters in + * `wp_get_mime_types()` in wp-includes/functions.php: + * + * `'wav|x-wav' => 'audio/wav'` + * + * @since 6.8.0 + * + * @param string[] $mime_types Mime types. + * @return string[] Mime types keyed by the file extension regex corresponding to those types. +*/ +function gutenberg_get_mime_types_6_8( $mime_types ) { + /* + * Only add support if there is existing support for 'wav'. + * Some plugins may have deliberately disabled it. + */ + if ( ! $mime_types['wav'] && ! isset( $mime_types['wav|x-wav'] ) ) { + return $mime_types; + } + /* + * Also, given that other themes or plugins may have already + * tried to add x-wav type support, only + * add the mime type if it doesn't already exist + * to avoid overriding any customizations. + */ + if ( ! isset( $mime_types['x-wav'] ) && ! isset( $mime_types['wav|x-wav'] ) ) { + $mime_types['x-wav'] = 'audio/wav'; + } + return $mime_types; +} +add_filter( 'mime_types', 'gutenberg_get_mime_types_6_8', 99 ); diff --git a/lib/load.php b/lib/load.php index 6236f0eb04b3c6..d7e4a33cd02c92 100644 --- a/lib/load.php +++ b/lib/load.php @@ -119,6 +119,7 @@ function gutenberg_is_experiment_enabled( $name ) { // WordPress 6.8 compat. require __DIR__ . '/compat/wordpress-6.8/preload.php'; require __DIR__ . '/compat/wordpress-6.8/blocks.php'; +require __DIR__ . '/compat/wordpress-6.8/functions.php'; // Experimental features. require __DIR__ . '/experimental/block-editor-settings-mobile.php'; From 0a5e54af715deb3bbb3ce098d345232227544c7a Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 13 Nov 2024 10:39:39 +1100 Subject: [PATCH 1548/1908] Media: check for `wav` mime type using isset (#66947) * Add missing isset. Sorry! Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> --- backport-changelog/6.8/7265.md | 1 + lib/compat/wordpress-6.8/functions.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backport-changelog/6.8/7265.md b/backport-changelog/6.8/7265.md index d4c46d62fa3334..44ba36053aa0d9 100644 --- a/backport-changelog/6.8/7265.md +++ b/backport-changelog/6.8/7265.md @@ -1,3 +1,4 @@ https://github.com/WordPress/wordpress-develop/pull/7265 * https://github.com/WordPress/gutenberg/pull/66850 +* https://github.com/WordPress/gutenberg/pull/66947 diff --git a/lib/compat/wordpress-6.8/functions.php b/lib/compat/wordpress-6.8/functions.php index eb57b2bb9890e7..a4658d1a182c73 100644 --- a/lib/compat/wordpress-6.8/functions.php +++ b/lib/compat/wordpress-6.8/functions.php @@ -18,7 +18,7 @@ function gutenberg_get_mime_types_6_8( $mime_types ) { * Only add support if there is existing support for 'wav'. * Some plugins may have deliberately disabled it. */ - if ( ! $mime_types['wav'] && ! isset( $mime_types['wav|x-wav'] ) ) { + if ( ! isset( $mime_types['wav'] ) && ! isset( $mime_types['wav|x-wav'] ) ) { return $mime_types; } /* From 538f03dbb16ba650319bbe1cef61f46a31043527 Mon Sep 17 00:00:00 2001 From: Matias Benedetto <matias.benedetto@gmail.com> Date: Wed, 13 Nov 2024 03:45:15 -0300 Subject: [PATCH 1549/1908] Fix uncategorized pattern browsing when pattern has no categories (#66945) Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- .../inserter/block-patterns-explorer/pattern-list.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js b/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js index 296b432bd685c3..8e5e50500ec72b 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js +++ b/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js @@ -85,10 +85,10 @@ function PatternList( { return true; } if ( selectedCategory === 'uncategorized' ) { - const hasKnownCategory = pattern.categories.some( - ( category ) => + const hasKnownCategory = + pattern.categories?.some( ( category ) => registeredPatternCategories.includes( category ) - ); + ) ?? false; return ! pattern.categories?.length || ! hasKnownCategory; } From 74bec71af36491373447ada6f0cd4e053481dc68 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 13 Nov 2024 08:52:13 +0100 Subject: [PATCH 1550/1908] Edit Site: Refactor to remove usage of edited entity state (#66922) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../edit-site/src/components/app/index.js | 2 - .../edit-site/src/components/editor/index.js | 5 +- .../global-styles-renderer/index.js | 14 +- .../hooks/commands/use-edit-mode-commands.js | 173 ------------------ .../editor/src/components/commands/index.js | 153 +++++++++++++++- 5 files changed, 158 insertions(+), 189 deletions(-) delete mode 100644 packages/edit-site/src/hooks/commands/use-edit-mode-commands.js diff --git a/packages/edit-site/src/components/app/index.js b/packages/edit-site/src/components/app/index.js index 133a376c9c246d..0551e6b295fbc0 100644 --- a/packages/edit-site/src/components/app/index.js +++ b/packages/edit-site/src/components/app/index.js @@ -18,7 +18,6 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; import Layout from '../layout'; import { unlock } from '../../lock-unlock'; import { useCommonCommands } from '../../hooks/commands/use-common-commands'; -import { useEditModeCommands } from '../../hooks/commands/use-edit-mode-commands'; import useInitEditedEntityFromURL from '../sync-state-with-url/use-init-edited-entity-from-url'; import useActiveRoute from '../layout/router'; import useSetCommandContext from '../../hooks/commands/use-set-command-context'; @@ -30,7 +29,6 @@ const { GlobalStylesProvider } = unlock( editorPrivateApis ); function AppLayout() { // This ensures the edited entity id and type are initialized properly. useInitEditedEntityFromURL(); - useEditModeCommands(); useCommonCommands(); useSetCommandContext(); useRegisterSiteEditorRoutes(); diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 94b56a197e1bc1..097a4f5f75ad7f 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -49,6 +49,7 @@ import useEditorIframeProps from '../block-editor/use-editor-iframe-props'; import useEditorTitle from './use-editor-title'; import { useIsSiteEditorLoading } from '../layout/hooks'; import { useAdaptEditorToCanvas } from './use-adapt-editor-to-canvas'; +import { TEMPLATE_POST_TYPE } from '../../utils/constants'; const { Editor, BackButton } = unlock( editorPrivateApis ); const { useHistory, useLocation } = unlock( routerPrivateApis ); @@ -214,7 +215,9 @@ export default function EditSiteEditor( { isPostsList = false } ) { return ( <> - <GlobalStylesRenderer /> + <GlobalStylesRenderer + disableRootPadding={ editedPostType !== TEMPLATE_POST_TYPE } + /> <EditorKeyboardShortcutsRegister /> { isEditMode && <BlockKeyboardShortcuts /> } { ! isReady ? <CanvasLoader id={ loadingProgressId } /> : null } diff --git a/packages/edit-site/src/components/global-styles-renderer/index.js b/packages/edit-site/src/components/global-styles-renderer/index.js index 2e840a7acdc375..d3e84ff5390996 100644 --- a/packages/edit-site/src/components/global-styles-renderer/index.js +++ b/packages/edit-site/src/components/global-styles-renderer/index.js @@ -10,17 +10,11 @@ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; */ import { store as editSiteStore } from '../../store'; import { unlock } from '../../lock-unlock'; -import { TEMPLATE_POST_TYPE } from '../../utils/constants'; const { useGlobalStylesOutput } = unlock( blockEditorPrivateApis ); -function useGlobalStylesRenderer() { - const postType = useSelect( ( select ) => { - return select( editSiteStore ).getEditedPostType(); - } ); - const [ styles, settings ] = useGlobalStylesOutput( - postType !== TEMPLATE_POST_TYPE - ); +function useGlobalStylesRenderer( disableRootPadding ) { + const [ styles, settings ] = useGlobalStylesOutput( disableRootPadding ); const { getSettings } = useSelect( editSiteStore ); const { updateSettings } = useDispatch( editSiteStore ); @@ -41,8 +35,8 @@ function useGlobalStylesRenderer() { }, [ styles, settings, updateSettings, getSettings ] ); } -export function GlobalStylesRenderer() { - useGlobalStylesRenderer(); +export function GlobalStylesRenderer( { disableRootPadding } ) { + useGlobalStylesRenderer( disableRootPadding ); return null; } diff --git a/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js b/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js deleted file mode 100644 index da36f32e6c0d51..00000000000000 --- a/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js +++ /dev/null @@ -1,173 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect, useDispatch } from '@wordpress/data'; -import { __, sprintf, isRTL } from '@wordpress/i18n'; -import { trash, rotateLeft, rotateRight, layout, page } from '@wordpress/icons'; -import { useCommandLoader } from '@wordpress/commands'; -import { decodeEntities } from '@wordpress/html-entities'; -import { privateApis as routerPrivateApis } from '@wordpress/router'; -import { store as editorStore } from '@wordpress/editor'; - -/** - * Internal dependencies - */ -import { store as editSiteStore } from '../../store'; -import useEditedEntityRecord from '../../components/use-edited-entity-record'; -import isTemplateRemovable from '../../utils/is-template-removable'; -import isTemplateRevertable from '../../utils/is-template-revertable'; -import { unlock } from '../../lock-unlock'; -import { TEMPLATE_POST_TYPE } from '../../utils/constants'; -import { useLink } from '../../components/routes/link'; - -const { useHistory, useLocation } = unlock( routerPrivateApis ); - -const getPageContentFocusCommands = () => - function usePageContentFocusCommands() { - const { record: template } = useEditedEntityRecord(); - const { params } = useLocation(); - const { canvas = 'view' } = params; - const { isPage, templateId, currentPostType } = useSelect( - ( select ) => { - const { isPage: _isPage } = unlock( select( editSiteStore ) ); - const { getCurrentPostType, getCurrentTemplateId } = - select( editorStore ); - return { - isPage: _isPage(), - templateId: getCurrentTemplateId(), - currentPostType: getCurrentPostType(), - }; - }, - [] - ); - - const { onClick: editTemplate } = useLink( { - postType: 'wp_template', - postId: templateId, - } ); - - const { setRenderingMode } = useDispatch( editorStore ); - - if ( ! isPage || canvas !== 'edit' ) { - return { isLoading: false, commands: [] }; - } - - const commands = []; - - if ( currentPostType !== 'wp_template' ) { - commands.push( { - name: 'core/switch-to-template-focus', - label: sprintf( - /* translators: %s: template title */ - __( 'Edit template: %s' ), - decodeEntities( template.title ) - ), - icon: layout, - callback: ( { close } ) => { - editTemplate(); - close(); - }, - } ); - } else { - commands.push( { - name: 'core/switch-to-page-focus', - label: __( 'Back to page' ), - icon: page, - callback: ( { close } ) => { - setRenderingMode( 'template-locked' ); - close(); - }, - } ); - } - - return { isLoading: false, commands }; - }; - -const getManipulateDocumentCommands = () => - function useManipulateDocumentCommands() { - const { isLoaded, record: template } = useEditedEntityRecord(); - const { removeTemplate, revertTemplate } = useDispatch( editSiteStore ); - const history = useHistory(); - const isEditingPage = useSelect( - ( select ) => - select( editSiteStore ).isPage() && - select( editorStore ).getCurrentPostType() !== 'wp_template', - [] - ); - - if ( ! isLoaded ) { - return { isLoading: true, commands: [] }; - } - - const commands = []; - - if ( isTemplateRevertable( template ) && ! isEditingPage ) { - const label = - template.type === TEMPLATE_POST_TYPE - ? sprintf( - /* translators: %s: template title */ - __( 'Reset template: %s' ), - decodeEntities( template.title ) - ) - : sprintf( - /* translators: %s: template part title */ - __( 'Reset template part: %s' ), - decodeEntities( template.title ) - ); - commands.push( { - name: 'core/reset-template', - label, - icon: isRTL() ? rotateRight : rotateLeft, - callback: ( { close } ) => { - revertTemplate( template ); - close(); - }, - } ); - } - - if ( isTemplateRemovable( template ) && ! isEditingPage ) { - const label = - template.type === TEMPLATE_POST_TYPE - ? sprintf( - /* translators: %s: template title */ - __( 'Delete template: %s' ), - decodeEntities( template.title ) - ) - : sprintf( - /* translators: %s: template part title */ - __( 'Delete template part: %s' ), - decodeEntities( template.title ) - ); - commands.push( { - name: 'core/remove-template', - label, - icon: trash, - callback: ( { close } ) => { - removeTemplate( template ); - // Navigate to the template list - history.push( { - postType: template.type, - } ); - close(); - }, - } ); - } - - return { - isLoading: ! isLoaded, - commands, - }; - }; - -export function useEditModeCommands() { - useCommandLoader( { - name: 'core/edit-site/page-content-focus', - hook: getPageContentFocusCommands(), - context: 'entity-edit', - } ); - - useCommandLoader( { - name: 'core/edit-site/manipulate-document', - hook: getManipulateDocumentCommands(), - } ); -} diff --git a/packages/editor/src/components/commands/index.js b/packages/editor/src/components/commands/index.js index 16260bed3978fd..0040a09fbdc07d 100644 --- a/packages/editor/src/components/commands/index.js +++ b/packages/editor/src/components/commands/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { useSelect, useDispatch } from '@wordpress/data'; -import { __, isRTL } from '@wordpress/i18n'; +import { __, isRTL, sprintf } from '@wordpress/i18n'; import { blockDefault, code, @@ -14,21 +14,32 @@ import { external, keyboard, symbol, + page, + layout, + rotateRight, + rotateLeft, } from '@wordpress/icons'; import { useCommandLoader } from '@wordpress/commands'; import { store as preferencesStore } from '@wordpress/preferences'; import { store as noticesStore } from '@wordpress/notices'; import { store as blockEditorStore } from '@wordpress/block-editor'; -import { store as coreStore } from '@wordpress/core-data'; +import { store as coreStore, useEntityRecord } from '@wordpress/core-data'; import { store as interfaceStore } from '@wordpress/interface'; +import { decodeEntities } from '@wordpress/html-entities'; /** * Internal dependencies */ +import { unlock } from '../../lock-unlock'; import { store as editorStore } from '../../store'; -import { PATTERN_POST_TYPE } from '../../store/constants'; +import { + PATTERN_POST_TYPE, + TEMPLATE_PART_POST_TYPE, + TEMPLATE_POST_TYPE, +} from '../../store/constants'; import { modalName as patternRenameModalName } from '../pattern-rename-modal'; import { modalName as patternDuplicateModalName } from '../pattern-duplicate-modal'; +import isTemplateRevertable from '../../store/utils/is-template-revertable'; const getEditorCommandLoader = () => function useEditorCommandLoader() { @@ -302,6 +313,131 @@ const getEditedEntityContextualCommands = () => return { isLoading: false, commands }; }; +const getPageContentFocusCommands = () => + function usePageContentFocusCommands() { + const { onNavigateToEntityRecord, goBack, templateId, isPreviewMode } = + useSelect( ( select ) => { + const { + getRenderingMode, + getEditorSettings: _getEditorSettings, + getCurrentTemplateId, + } = unlock( select( editorStore ) ); + const editorSettings = _getEditorSettings(); + return { + isTemplateHidden: getRenderingMode() === 'post-only', + onNavigateToEntityRecord: + editorSettings.onNavigateToEntityRecord, + getEditorSettings: _getEditorSettings, + goBack: editorSettings.onNavigateToPreviousEntityRecord, + templateId: getCurrentTemplateId(), + isPreviewMode: editorSettings.isPreviewMode, + }; + }, [] ); + const { editedRecord: template, hasResolved } = useEntityRecord( + 'postType', + 'wp_template', + templateId + ); + + if ( isPreviewMode ) { + return { isLoading: false, commands: [] }; + } + + const commands = []; + + if ( templateId && hasResolved ) { + commands.push( { + name: 'core/switch-to-template-focus', + label: sprintf( + /* translators: %s: template title */ + __( 'Edit template: %s' ), + decodeEntities( template.title ) + ), + icon: layout, + callback: ( { close } ) => { + onNavigateToEntityRecord( { + postId: templateId, + postType: 'wp_template', + } ); + close(); + }, + } ); + } + + if ( !! goBack ) { + commands.push( { + name: 'core/switch-to-previous-entity', + label: __( 'Go back' ), + icon: page, + callback: ( { close } ) => { + goBack(); + close(); + }, + } ); + } + + return { isLoading: false, commands }; + }; + +const getManipulateDocumentCommands = () => + function useManipulateDocumentCommands() { + const { postType, postId } = useSelect( ( select ) => { + const { getCurrentPostId, getCurrentPostType } = + select( editorStore ); + return { + postType: getCurrentPostType(), + postId: getCurrentPostId(), + }; + }, [] ); + const { editedRecord: template, hasResolved } = useEntityRecord( + 'postType', + postType, + postId + ); + // eslint-disable-next-line @wordpress/no-unused-vars-before-return + const { revertTemplate } = unlock( useDispatch( editorStore ) ); + + if ( + ! hasResolved || + ! [ TEMPLATE_PART_POST_TYPE, TEMPLATE_POST_TYPE ].includes( + postType + ) + ) { + return { isLoading: true, commands: [] }; + } + + const commands = []; + + if ( isTemplateRevertable( template ) ) { + const label = + template.type === TEMPLATE_POST_TYPE + ? sprintf( + /* translators: %s: template title */ + __( 'Reset template: %s' ), + decodeEntities( template.title ) + ) + : sprintf( + /* translators: %s: template part title */ + __( 'Reset template part: %s' ), + decodeEntities( template.title ) + ); + commands.push( { + name: 'core/reset-template', + label, + icon: isRTL() ? rotateRight : rotateLeft, + callback: ( { close } ) => { + revertTemplate( template ); + close(); + }, + } ); + } + + return { + isLoading: ! hasResolved, + commands, + }; + }; + export default function useCommands() { useCommandLoader( { name: 'core/editor/edit-ui', @@ -313,4 +449,15 @@ export default function useCommands() { hook: getEditedEntityContextualCommands(), context: 'entity-edit', } ); + + useCommandLoader( { + name: 'core/editor/page-content-focus', + hook: getPageContentFocusCommands(), + context: 'entity-edit', + } ); + + useCommandLoader( { + name: 'core/edit-site/manipulate-document', + hook: getManipulateDocumentCommands(), + } ); } From 5f29581507b51dc6505494795b275b41ad09be69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 13 Nov 2024 10:17:29 +0100 Subject: [PATCH 1551/1908] Post fields: extract `title` from `edit-site` to `fields` package (#66940) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../core-data/src/entity-types/settings.ts | 4 ++ .../src/components/post-fields/index.js | 59 +----------------- packages/fields/src/actions/utils.ts | 4 +- packages/fields/src/fields/title/index.ts | 3 + .../fields/src/fields/title/title-view.tsx | 62 +++++++++++++++++++ 5 files changed, 74 insertions(+), 58 deletions(-) create mode 100644 packages/fields/src/fields/title/title-view.tsx diff --git a/packages/core-data/src/entity-types/settings.ts b/packages/core-data/src/entity-types/settings.ts index 2ce7eff89d8889..27e803bc030293 100644 --- a/packages/core-data/src/entity-types/settings.ts +++ b/packages/core-data/src/entity-types/settings.ts @@ -22,6 +22,10 @@ declare module './base-entity-records' { * The ID of the page that should be displayed on the front page */ page_on_front: number; + /** + * The ID of the page that should display the latest posts + */ + page_for_posts: number; /** * Site title. */ diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 083d971d102eb3..097459ea110039 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -7,7 +7,6 @@ import clsx from 'clsx'; * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { decodeEntities } from '@wordpress/html-entities'; import { featuredImageField, slugField, @@ -15,6 +14,7 @@ import { passwordField, statusField, commentStatusField, + titleField, } from '@wordpress/fields'; import { createInterpolateElement, @@ -75,63 +75,10 @@ function usePostFields() { const { records: authors, isResolving: isLoadingAuthors } = useEntityRecords( 'root', 'user', { per_page: -1 } ); - const { frontPageId, postsPageId } = useSelect( ( select ) => { - const { getEntityRecord } = select( coreStore ); - const siteSettings = getEntityRecord( 'root', 'site' ); - return { - frontPageId: siteSettings?.page_on_front, - postsPageId: siteSettings?.page_for_posts, - }; - }, [] ); - const fields = useMemo( () => [ featuredImageField, - { - label: __( 'Title' ), - id: 'title', - type: 'text', - getValue: ( { item } ) => - typeof item.title === 'string' - ? item.title - : item.title?.raw, - render: ( { item } ) => { - const renderedTitle = - typeof item.title === 'string' - ? item.title - : item.title?.rendered; - - let suffix = ''; - if ( item.id === frontPageId ) { - suffix = ( - <span className="edit-site-post-list__title-badge"> - { __( 'Homepage' ) } - </span> - ); - } else if ( item.id === postsPageId ) { - suffix = ( - <span className="edit-site-post-list__title-badge"> - { __( 'Posts Page' ) } - </span> - ); - } - - return ( - <HStack - className="edit-site-post-list__title" - alignment="center" - justify="flex-start" - > - <span> - { decodeEntities( renderedTitle ) || - __( '(no title)' ) } - </span> - { suffix } - </HStack> - ); - }, - enableHiding: false, - }, + titleField, { label: __( 'Author' ), id: 'author', @@ -234,7 +181,7 @@ function usePostFields() { commentStatusField, passwordField, ], - [ authors, frontPageId, postsPageId ] + [ authors ] ); return { diff --git a/packages/fields/src/actions/utils.ts b/packages/fields/src/actions/utils.ts index 14e8edae4be048..60d3d00e82766a 100644 --- a/packages/fields/src/actions/utils.ts +++ b/packages/fields/src/actions/utils.ts @@ -34,10 +34,10 @@ export function getItemTitle( item: Post ) { if ( typeof item.title === 'string' ) { return decodeEntities( item.title ); } - if ( 'rendered' in item.title ) { + if ( item.title && 'rendered' in item.title ) { return decodeEntities( item.title.rendered ); } - if ( 'raw' in item.title ) { + if ( item.title && 'raw' in item.title ) { return decodeEntities( item.title.raw ); } return ''; diff --git a/packages/fields/src/fields/title/index.ts b/packages/fields/src/fields/title/index.ts index 5332f476f8ff58..d8e6f25276d6b8 100644 --- a/packages/fields/src/fields/title/index.ts +++ b/packages/fields/src/fields/title/index.ts @@ -9,6 +9,7 @@ import { __ } from '@wordpress/i18n'; */ import type { BasePost } from '../../types'; import { getItemTitle } from '../../actions/utils'; +import TitleView from './title-view'; const titleField: Field< BasePost > = { type: 'text', @@ -16,6 +17,8 @@ const titleField: Field< BasePost > = { label: __( 'Title' ), placeholder: __( 'No title' ), getValue: ( { item } ) => getItemTitle( item ), + render: TitleView, + enableHiding: false, }; export default titleField; diff --git a/packages/fields/src/fields/title/title-view.tsx b/packages/fields/src/fields/title/title-view.tsx new file mode 100644 index 00000000000000..c15ed96b89b73b --- /dev/null +++ b/packages/fields/src/fields/title/title-view.tsx @@ -0,0 +1,62 @@ +/** + * WordPress dependencies + */ +import { __experimentalHStack as HStack } from '@wordpress/components'; +import { decodeEntities } from '@wordpress/html-entities'; +import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import type { Settings } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import { getItemTitle } from '../../actions/utils'; + +const TitleView = ( { item }: { item: BasePost } ) => { + const { frontPageId, postsPageId } = useSelect( ( select ) => { + const { getEntityRecord } = select( coreStore ); + const siteSettings: Settings | undefined = getEntityRecord( + 'root', + 'site', + '' + ); + return { + frontPageId: siteSettings?.page_on_front, + postsPageId: siteSettings?.page_for_posts, + }; + }, [] ); + + const renderedTitle = getItemTitle( item ); + + let suffix; + if ( item.id === frontPageId ) { + suffix = ( + <span className="edit-site-post-list__title-badge"> + { __( 'Homepage' ) } + </span> + ); + } else if ( item.id === postsPageId ) { + suffix = ( + <span className="edit-site-post-list__title-badge"> + { __( 'Posts Page' ) } + </span> + ); + } + + return ( + <HStack + className="edit-site-post-list__title" + alignment="center" + justify="flex-start" + > + <span> + { decodeEntities( renderedTitle ) || __( '(no title)' ) } + </span> + { suffix } + </HStack> + ); +}; + +export default TitleView; From 1e82c946c80eb4542c5b2aaa0b302ae4cde48f2e Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 13 Nov 2024 10:25:41 +0100 Subject: [PATCH 1552/1908] Site Editor: Avoid using edited entity state in site editor loading hook (#66924) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/edit-site/src/components/layout/hooks.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/edit-site/src/components/layout/hooks.js b/packages/edit-site/src/components/layout/hooks.js index 184e1b44896c5b..490fcf39ea622a 100644 --- a/packages/edit-site/src/components/layout/hooks.js +++ b/packages/edit-site/src/components/layout/hooks.js @@ -5,15 +5,9 @@ import { useEffect, useState } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -/** - * Internal dependencies - */ -import useEditedEntityRecord from '../use-edited-entity-record'; - const MAX_LOADING_TIME = 10000; // 10 seconds export function useIsSiteEditorLoading() { - const { isLoaded: hasLoadedPost } = useEditedEntityRecord(); const [ loaded, setLoaded ] = useState( false ); const inLoadingPause = useSelect( ( select ) => { @@ -64,5 +58,5 @@ export function useIsSiteEditorLoading() { } }, [ inLoadingPause ] ); - return ! loaded || ! hasLoadedPost; + return ! loaded; } From 0098e9bbc65d9208de7af6c78d255a028892627f Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Wed, 13 Nov 2024 12:09:58 +0200 Subject: [PATCH 1553/1908] ToggleGroupControl: Fix active background for `zero` value (#66855) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/toggle-group-control/toggle-group-control/component.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index abd32b37c4c650..2fddf51173e832 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -9,6 +9,7 @@ ### Bug Fixes - `Popover`: Fix missing label of the headerTitle Close button ([#66813](https://github.com/WordPress/gutenberg/pull/66813)). +- `ToggleGroupControl`: Fix active background for `0` value ([#66855](https://github.com/WordPress/gutenberg/pull/66855)). ### Enhancements diff --git a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx index 7f384f70ae1dc5..0c3cadf210d84a 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx @@ -52,7 +52,7 @@ function UnconnectedToggleGroupControl( const [ controlElement, setControlElement ] = useState< HTMLElement >(); const refs = useMergeRefs( [ setControlElement, forwardedRef ] ); const selectedRect = useTrackElementOffsetRect( - value ? selectedElement : undefined + value || value === 0 ? selectedElement : undefined ); useAnimatedOffsetRect( controlElement, selectedRect, { prefix: 'selected', From 8d9b4f4e7379e4eb0581b9a01a41b696b896c9b5 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 13 Nov 2024 19:22:45 +0900 Subject: [PATCH 1554/1908] Hide metaboxes in Zoom Out (#66886) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: arnaudbroes <arnaudbroes@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> --- packages/edit-post/src/components/layout/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index b50e17054fd3ef..225788a15a8e1d 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -424,7 +424,9 @@ function Layout( { !! select( blockEditorStore ).getBlockSelectionStart(), showIconLabels: get( 'core', 'showIconLabels' ), isDistractionFree: get( 'core', 'distractionFree' ), - showMetaBoxes: ! DESIGN_POST_TYPES.includes( currentPostType ), + showMetaBoxes: + ! DESIGN_POST_TYPES.includes( currentPostType ) && + ! isZoomOut(), isWelcomeGuideVisible: isFeatureActive( 'welcomeGuide' ), templateId: supportsTemplateMode && From ea3a85b0daf5b28bdbdb975cdd3582ba6b0f01c0 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 13 Nov 2024 19:46:49 +0900 Subject: [PATCH 1555/1908] Block Patterns List: Fix visual title and tooltip inconsistencies (#64815) * Block Patterns List: Eliminate visual title and tooltip inconsistencies * Fix storybook Unlinked contributors: isuke01. Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> --- .../components/block-patterns-list/README.md | 8 ++++ .../components/block-patterns-list/index.js | 40 +++++++------------ .../stories/index.story.js | 10 +---- .../components/block-toolbar/change-design.js | 2 +- .../inserter/block-patterns-tab/index.js | 1 - .../src/template-part/edit/index.js | 2 +- 6 files changed, 25 insertions(+), 38 deletions(-) diff --git a/packages/block-editor/src/components/block-patterns-list/README.md b/packages/block-editor/src/components/block-patterns-list/README.md index 18e7ead5d1805a..f4c6cc6141de13 100644 --- a/packages/block-editor/src/components/block-patterns-list/README.md +++ b/packages/block-editor/src/components/block-patterns-list/README.md @@ -61,6 +61,14 @@ The aria label for the block patterns list. - Required: No - Default: `Block Patterns` +#### showTitlesAsTooltip + +Whether to render the title of each pattern as a tooltip. User-defined patterns always show their visual title regardless of this prop. + +- Type: `boolean` +- Required: No +- Default: `false` + ## Related components Block Editor components are components that can be used to compose the UI of your block editor. Thus, they can only be used under a [`BlockEditorProvider`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/provider/README.md) in the components tree. diff --git a/packages/block-editor/src/components/block-patterns-list/index.js b/packages/block-editor/src/components/block-patterns-list/index.js index 741a92ddf10dfa..8128e89418f45a 100644 --- a/packages/block-editor/src/components/block-patterns-list/index.js +++ b/packages/block-editor/src/components/block-patterns-list/index.js @@ -39,14 +39,14 @@ function BlockPattern( { pattern, onClick, onHover, - showTitle = true, - showTooltip, + showTitlesAsTooltip, category, } ) { const [ isDragging, setIsDragging ] = useState( false ); const { blocks, viewportWidth } = pattern; const instanceId = useInstanceId( BlockPattern ); const descriptionId = `block-editor-block-patterns-list__item-description-${ instanceId }`; + const isUserPattern = pattern.type === INSERTER_PATTERN_TYPES.user; // When we have a selected category and the pattern is draggable, we need to update the // pattern's categories in metadata to only contain the selected category, and pass this to @@ -94,10 +94,7 @@ function BlockPattern( { } } > <WithToolTip - showTooltip={ - showTooltip && - ! pattern.type !== INSERTER_PATTERN_TYPES.user - } + showTooltip={ showTitlesAsTooltip && ! isUserPattern } title={ pattern.title } > <Composite.Item @@ -142,29 +139,22 @@ function BlockPattern( { viewportWidth={ viewportWidth } /> </BlockPreview.Async> - - { showTitle && ( + { ( ! showTitlesAsTooltip || isUserPattern ) && ( <HStack className="block-editor-patterns__pattern-details" spacing={ 2 } > - { pattern.type === - INSERTER_PATTERN_TYPES.user && - ! pattern.syncStatus && ( - <div className="block-editor-patterns__pattern-icon-wrapper"> - <Icon - className="block-editor-patterns__pattern-icon" - icon={ symbol } - /> - </div> - ) } - { ( ! showTooltip || - pattern.type === - INSERTER_PATTERN_TYPES.user ) && ( - <div className="block-editor-block-patterns-list__item-title"> - { pattern.title } + { isUserPattern && ! pattern.syncStatus && ( + <div className="block-editor-patterns__pattern-icon-wrapper"> + <Icon + className="block-editor-patterns__pattern-icon" + icon={ symbol } + /> </div> ) } + <div className="block-editor-block-patterns-list__item-title"> + { pattern.title } + </div> </HStack> ) } @@ -196,7 +186,6 @@ function BlockPatternsList( orientation, label = __( 'Block patterns' ), category, - showTitle = true, showTitlesAsTooltip, pagingProps, }, @@ -230,8 +219,7 @@ function BlockPatternsList( onClick={ onClickPattern } onHover={ onHover } isDraggable={ isDraggable } - showTitle={ showTitle } - showTooltip={ showTitlesAsTooltip } + showTitlesAsTooltip={ showTitlesAsTooltip } category={ category } /> ) ) } diff --git a/packages/block-editor/src/components/block-patterns-list/stories/index.story.js b/packages/block-editor/src/components/block-patterns-list/stories/index.story.js index 0ebb4520d98fd4..ad9bffab762c23 100644 --- a/packages/block-editor/src/components/block-patterns-list/stories/index.story.js +++ b/packages/block-editor/src/components/block-patterns-list/stories/index.story.js @@ -31,7 +31,6 @@ export const Default = { blockPatterns: patterns, isDraggable: false, label: 'Block patterns story', - showTitle: true, showTitlesAsTooltip: false, }, argTypes: { @@ -40,18 +39,11 @@ export const Default = { description: 'Usually this component is used with `useAsyncList` for performance reasons and you should provide the returned list from that hook. Alternatively it should have the same value with `blockPatterns`.', }, - showTitle: { - description: 'Whether to render the title of each pattern.', - table: { - defaultValue: { summary: true }, - type: { summary: 'boolean' }, - }, - }, onClickPattern: { type: 'function' }, onHover: { type: 'function' }, showTitlesAsTooltip: { description: - 'Whether to render the title of each pattern as a tooltip. If enabled, it takes precedence over `showTitle` prop.', + 'Whether to render the title of each pattern as a tooltip. If enabled', }, orientation: { description: 'Orientation for the underlying composite widget.', diff --git a/packages/block-editor/src/components/block-toolbar/change-design.js b/packages/block-editor/src/components/block-toolbar/change-design.js index 9da1affe4273cc..2d69675218ea48 100644 --- a/packages/block-editor/src/components/block-toolbar/change-design.js +++ b/packages/block-editor/src/components/block-toolbar/change-design.js @@ -118,7 +118,7 @@ export default function ChangeDesign( { clientId } ) { <BlockPatternsList blockPatterns={ sameCategoryPatternsWithSingleWrapper } onClickPattern={ onClickPattern } - showTitle={ false } + showTitlesAsTooltip /> </DropdownContentWrapper> ) } diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/index.js b/packages/block-editor/src/components/inserter/block-patterns-tab/index.js index 141ebf8cc84016..01e41111b7c890 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/index.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/index.js @@ -79,7 +79,6 @@ function BlockPatternsTab( { onInsert={ onInsert } rootClientId={ rootClientId } category={ category } - showTitlesAsTooltip={ false } /> </div> ) } diff --git a/packages/block-library/src/template-part/edit/index.js b/packages/block-library/src/template-part/edit/index.js index a318fd285cdc33..ba66ffa673ff87 100644 --- a/packages/block-library/src/template-part/edit/index.js +++ b/packages/block-library/src/template-part/edit/index.js @@ -95,7 +95,7 @@ function TemplatesList( { area, clientId, isEntityAvailable, onSelect } ) { label={ __( 'Templates' ) } blockPatterns={ blockPatterns } onClickPattern={ onSelect } - showTitle={ false } + showTitlesAsTooltip /> </PanelBody> ); From f992ba752021befdee058f68500607a73fa94673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 13 Nov 2024 12:16:28 +0100 Subject: [PATCH 1556/1908] Post fields: move `date` fields from `edit-site` to `fields` package (#66938) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- package-lock.json | 1 + packages/date/README.md | 2 +- packages/date/src/index.js | 18 ++-- .../src/components/post-fields/index.js | 94 +------------------ packages/fields/README.md | 4 + packages/fields/package.json | 1 + packages/fields/src/fields/date/date-view.tsx | 92 ++++++++++++++++++ packages/fields/src/fields/date/index.tsx | 23 +++++ packages/fields/src/fields/index.ts | 1 + packages/fields/src/types.ts | 4 +- packages/fields/tsconfig.json | 19 ++-- 11 files changed, 149 insertions(+), 110 deletions(-) create mode 100644 packages/fields/src/fields/date/date-view.tsx create mode 100644 packages/fields/src/fields/date/index.tsx diff --git a/package-lock.json b/package-lock.json index 0bb48c55c5326c..27f01fd681824f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54685,6 +54685,7 @@ "@wordpress/core-data": "*", "@wordpress/data": "*", "@wordpress/dataviews": "*", + "@wordpress/date": "*", "@wordpress/element": "*", "@wordpress/hooks": "*", "@wordpress/html-entities": "*", diff --git a/packages/date/README.md b/packages/date/README.md index 8edd4e94a8538f..ed2dfdd4790324 100644 --- a/packages/date/README.md +++ b/packages/date/README.md @@ -50,7 +50,7 @@ _Parameters_ - _dateFormat_ `string`: PHP-style formatting string. See php.net/date. - _dateValue_ `Moment | Date | string | undefined`: Date object or string, parsable by moment.js. -- _timezone_ `string | number | boolean | undefined`: Timezone to output result in or a UTC offset. Defaults to timezone from site. Notice: `boolean` is effectively deprecated, but still supported for backward compatibility reasons. +- _timezone_ `string | number | boolean | undefined=`: Timezone to output result in or a UTC offset. Defaults to timezone from site. Notice: `boolean` is effectively deprecated, but still supported for backward compatibility reasons. _Returns_ diff --git a/packages/date/src/index.js b/packages/date/src/index.js index 90f65f62628dc8..b632de3a7431f6 100644 --- a/packages/date/src/index.js +++ b/packages/date/src/index.js @@ -525,15 +525,15 @@ export function gmdate( dateFormat, dateValue = new Date() ) { * Backward Compatibility Notice: if `timezone` is set to `true`, the function * behaves like `gmdateI18n`. * - * @param {string} dateFormat PHP-style formatting string. - * See php.net/date. - * @param {Moment | Date | string | undefined} dateValue Date object or string, parsable by - * moment.js. - * @param {string | number | boolean | undefined} timezone Timezone to output result in or a - * UTC offset. Defaults to timezone from - * site. Notice: `boolean` is effectively - * deprecated, but still supported for - * backward compatibility reasons. + * @param {string} dateFormat PHP-style formatting string. + * See php.net/date. + * @param {Moment | Date | string | undefined} dateValue Date object or string, parsable by + * moment.js. + * @param {string | number | boolean | undefined=} timezone Timezone to output result in or a + * UTC offset. Defaults to timezone from + * site. Notice: `boolean` is effectively + * deprecated, but still supported for + * backward compatibility reasons. * * @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones * @see https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 097459ea110039..e151c5a048c011 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -6,7 +6,7 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { __, sprintf } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; import { featuredImageField, slugField, @@ -15,24 +15,14 @@ import { statusField, commentStatusField, titleField, + dateField, } from '@wordpress/fields'; -import { - createInterpolateElement, - useMemo, - useState, -} from '@wordpress/element'; -import { dateI18n, getDate, getSettings } from '@wordpress/date'; +import { useMemo, useState } from '@wordpress/element'; import { commentAuthorAvatar as authorIcon } from '@wordpress/icons'; import { __experimentalHStack as HStack, Icon } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; -const getFormattedDate = ( dateToDisplay ) => - dateI18n( - getSettings().formats.datetimeAbbreviated, - getDate( dateToDisplay ) - ); - function PostAuthorField( { item } ) { const { text, imageUrl } = useSelect( ( select ) => { @@ -99,83 +89,7 @@ function usePostFields() { }, }, statusField, - { - label: __( 'Date' ), - id: 'date', - type: 'datetime', - render: ( { item } ) => { - const isDraftOrPrivate = [ 'draft', 'private' ].includes( - item.status - ); - if ( isDraftOrPrivate ) { - return createInterpolateElement( - sprintf( - /* translators: %s: page creation or modification date. */ - __( '<span>Modified: <time>%s</time></span>' ), - getFormattedDate( item.date ) - ), - { - span: <span />, - time: <time />, - } - ); - } - - const isScheduled = item.status === 'future'; - if ( isScheduled ) { - return createInterpolateElement( - sprintf( - /* translators: %s: page creation date */ - __( '<span>Scheduled: <time>%s</time></span>' ), - getFormattedDate( item.date ) - ), - { - span: <span />, - time: <time />, - } - ); - } - - const isPublished = item.status === 'publish'; - if ( isPublished ) { - return createInterpolateElement( - sprintf( - /* translators: %s: page creation time */ - __( '<span>Published: <time>%s</time></span>' ), - getFormattedDate( item.date ) - ), - { - span: <span />, - time: <time />, - } - ); - } - - // Pending posts show the modified date if it's newer. - const dateToDisplay = - getDate( item.modified ) > getDate( item.date ) - ? item.modified - : item.date; - - const isPending = item.status === 'pending'; - if ( isPending ) { - return createInterpolateElement( - sprintf( - /* translators: %s: page creation or modification date. */ - __( '<span>Modified: <time>%s</time></span>' ), - getFormattedDate( dateToDisplay ) - ), - { - span: <span />, - time: <time />, - } - ); - } - - // Unknow status. - return <time>{ getFormattedDate( item.date ) }</time>; - }, - }, + dateField, slugField, parentField, commentStatusField, diff --git a/packages/fields/README.md b/packages/fields/README.md index 1d673c4d46c7b1..bfcc63be4da472 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -18,6 +18,10 @@ npm install @wordpress/fields --save Comment status field for BasePost. +### dateField + +Date field for BasePost. + ### deletePost Undocumented declaration. diff --git a/packages/fields/package.json b/packages/fields/package.json index 34ef8992f93adf..f32c779c2e989e 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -41,6 +41,7 @@ "@wordpress/core-data": "*", "@wordpress/data": "*", "@wordpress/dataviews": "*", + "@wordpress/date": "*", "@wordpress/element": "*", "@wordpress/hooks": "*", "@wordpress/html-entities": "*", diff --git a/packages/fields/src/fields/date/date-view.tsx b/packages/fields/src/fields/date/date-view.tsx new file mode 100644 index 00000000000000..1cc2ab2d04e047 --- /dev/null +++ b/packages/fields/src/fields/date/date-view.tsx @@ -0,0 +1,92 @@ +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; +import { createInterpolateElement } from '@wordpress/element'; +import { dateI18n, getDate, getSettings } from '@wordpress/date'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; + +const getFormattedDate = ( dateToDisplay: string | null ) => + dateI18n( + getSettings().formats.datetimeAbbreviated, + getDate( dateToDisplay ) + ); + +const DateView = ( { item }: { item: BasePost } ) => { + const isDraftOrPrivate = [ 'draft', 'private' ].includes( + item.status ?? '' + ); + if ( isDraftOrPrivate ) { + return createInterpolateElement( + sprintf( + /* translators: %s: page creation or modification date. */ + __( '<span>Modified: <time>%s</time></span>' ), + getFormattedDate( item.date ?? null ) + ), + { + span: <span />, + time: <time />, + } + ); + } + + const isScheduled = item.status === 'future'; + if ( isScheduled ) { + return createInterpolateElement( + sprintf( + /* translators: %s: page creation date */ + __( '<span>Scheduled: <time>%s</time></span>' ), + getFormattedDate( item.date ?? null ) + ), + { + span: <span />, + time: <time />, + } + ); + } + + const isPublished = item.status === 'publish'; + if ( isPublished ) { + return createInterpolateElement( + sprintf( + /* translators: %s: page creation time */ + __( '<span>Published: <time>%s</time></span>' ), + getFormattedDate( item.date ?? null ) + ), + { + span: <span />, + time: <time />, + } + ); + } + + // Pending posts show the modified date if it's newer. + const dateToDisplay = + getDate( item.modified ?? null ) > getDate( item.date ?? null ) + ? item.modified + : item.date; + + const isPending = item.status === 'pending'; + if ( isPending ) { + return createInterpolateElement( + sprintf( + /* translators: %s: page creation or modification date. */ + __( '<span>Modified: <time>%s</time></span>' ), + getFormattedDate( dateToDisplay ?? null ) + ), + { + span: <span />, + time: <time />, + } + ); + } + + // Unknow status. + return <time>{ getFormattedDate( item.date ?? null ) }</time>; +}; + +export default DateView; diff --git a/packages/fields/src/fields/date/index.tsx b/packages/fields/src/fields/date/index.tsx new file mode 100644 index 00000000000000..49bd0807de6691 --- /dev/null +++ b/packages/fields/src/fields/date/index.tsx @@ -0,0 +1,23 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import DateView from './date-view'; + +const dateField: Field< BasePost > = { + id: 'date', + type: 'datetime', + label: __( 'Date' ), + render: DateView, +}; + +/** + * Date field for BasePost. + */ +export default dateField; diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts index fba34eb2388a39..36e064006232bb 100644 --- a/packages/fields/src/fields/index.ts +++ b/packages/fields/src/fields/index.ts @@ -6,3 +6,4 @@ export { default as parentField } from './parent'; export { default as passwordField } from './password'; export { default as statusField } from './status'; export { default as commentStatusField } from './comment-status'; +export { default as dateField } from './date'; diff --git a/packages/fields/src/types.ts b/packages/fields/src/types.ts index d895195cb40af7..71831b6aab180c 100644 --- a/packages/fields/src/types.ts +++ b/packages/fields/src/types.ts @@ -1,5 +1,5 @@ type PostStatus = - | 'published' + | 'publish' | 'draft' | 'pending' | 'private' @@ -37,6 +37,8 @@ export interface BasePost extends CommonPost { link?: string; slug?: string; permalink_template?: string; + date?: string; + modified?: string; } export interface Template extends CommonPost { diff --git a/packages/fields/tsconfig.json b/packages/fields/tsconfig.json index c553ee023993d0..5c4b91e88f895a 100644 --- a/packages/fields/tsconfig.json +++ b/packages/fields/tsconfig.json @@ -8,24 +8,25 @@ }, "references": [ { "path": "../api-fetch" }, + { "path": "../blob" }, { "path": "../components" }, { "path": "../compose" }, + { "path": "../core-data" }, { "path": "../data" }, + { "path": "../dataviews" }, + { "path": "../date" }, { "path": "../element" }, + { "path": "../hooks" }, + { "path": "../html-entities" }, { "path": "../i18n" }, { "path": "../icons" }, + { "path": "../media-utils" }, + { "path": "../notices" }, { "path": "../primitives" }, { "path": "../private-apis" }, - { "path": "../warning" }, + { "path": "../router" }, { "path": "../url" }, - { "path": "../notices" }, - { "path": "../dataviews" }, - { "path": "../blob" }, - { "path": "../core-data" }, - { "path": "../hooks" }, - { "path": "../html-entities" }, - { "path": "../media-utils" }, - { "path": "../router" } + { "path": "../warning" } ], "include": [ "src" ] } From cbaeee2ee82f18a64e5ac9bf445a2f12864bbd77 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 13 Nov 2024 12:29:03 +0100 Subject: [PATCH 1557/1908] Site Editor: Remove useEditedEntityRecord hook (#66955) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../edit-site/src/components/editor/index.js | 7 ++- .../src/components/editor/use-editor-title.js | 50 +++++++++++----- .../use-edited-entity-record/index.js | 58 ------------------- 3 files changed, 42 insertions(+), 73 deletions(-) delete mode 100644 packages/edit-site/src/components/use-edited-entity-record/index.js diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 097a4f5f75ad7f..7eff0da660d274 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -126,12 +126,15 @@ export default function EditSiteEditor( { isPostsList = false } ) { hasSiteIcon: !! siteData?.site_icon_url, }; }, [] ); - useEditorTitle(); + const postWithTemplate = !! contextPostId; + useEditorTitle( + postWithTemplate ? contextPostType : editedPostType, + postWithTemplate ? contextPostId : editedPostId + ); const _isPreviewingTheme = isPreviewingTheme(); const hasDefaultEditorCanvasView = ! useHasEditorCanvasContainer(); const iframeProps = useEditorIframeProps(); const isEditMode = canvas === 'edit'; - const postWithTemplate = !! contextPostId; const loadingProgressId = useInstanceId( CanvasLoader, 'edit-site-editor__loading-progress' diff --git a/packages/edit-site/src/components/editor/use-editor-title.js b/packages/edit-site/src/components/editor/use-editor-title.js index 0645c2031a3af0..2ad4e94ccc3e80 100644 --- a/packages/edit-site/src/components/editor/use-editor-title.js +++ b/packages/edit-site/src/components/editor/use-editor-title.js @@ -2,34 +2,58 @@ * WordPress dependencies */ import { _x, sprintf } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { store as editorStore } from '@wordpress/editor'; +import { decodeEntities } from '@wordpress/html-entities'; /** * Internal dependencies */ -import useEditedEntityRecord from '../use-edited-entity-record'; import useTitle from '../routes/use-title'; import { POST_TYPE_LABELS, TEMPLATE_POST_TYPE } from '../../utils/constants'; -function useEditorTitle() { - const { - record: editedPost, - getTitle, - isLoaded: hasLoadedPost, - } = useEditedEntityRecord(); - let title; - if ( hasLoadedPost ) { - title = sprintf( +function useEditorTitle( postType, postId ) { + const { title, isLoaded } = useSelect( + ( select ) => { + const { getEditedEntityRecord, hasFinishedResolution } = + select( coreStore ); + const { __experimentalGetTemplateInfo: getTemplateInfo } = + select( editorStore ); + const _record = getEditedEntityRecord( + 'postType', + postType, + postId + ); + const _isLoaded = hasFinishedResolution( 'getEditedEntityRecord', [ + 'postType', + postType, + postId, + ] ); + const templateInfo = getTemplateInfo( _record ); + + return { + title: templateInfo.title, + isLoaded: _isLoaded, + }; + }, + [ postType, postId ] + ); + + let editorTitle; + if ( isLoaded ) { + editorTitle = sprintf( // translators: A breadcrumb trail for the Admin document title. 1: title of template being edited, 2: type of template (Template or Template Part). _x( '%1$s ‹ %2$s', 'breadcrumb trail' ), - getTitle(), - POST_TYPE_LABELS[ editedPost.type ] ?? + decodeEntities( title ), + POST_TYPE_LABELS[ postType ] ?? POST_TYPE_LABELS[ TEMPLATE_POST_TYPE ] ); } // Only announce the title once the editor is ready to prevent "Replace" // action in <URLQueryController> from double-announcing. - useTitle( hasLoadedPost && title ); + useTitle( isLoaded && editorTitle ); } export default useEditorTitle; diff --git a/packages/edit-site/src/components/use-edited-entity-record/index.js b/packages/edit-site/src/components/use-edited-entity-record/index.js deleted file mode 100644 index 22a8bdc32a94a0..00000000000000 --- a/packages/edit-site/src/components/use-edited-entity-record/index.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; -import { store as editorStore } from '@wordpress/editor'; -import { decodeEntities } from '@wordpress/html-entities'; - -/** - * Internal dependencies - */ -import { store as editSiteStore } from '../../store'; - -export default function useEditedEntityRecord( postType, postId ) { - const { record, title, description, isLoaded, icon } = useSelect( - ( select ) => { - const { getEditedPostType, getEditedPostId } = - select( editSiteStore ); - const { getEditedEntityRecord, hasFinishedResolution } = - select( coreStore ); - const { __experimentalGetTemplateInfo: getTemplateInfo } = - select( editorStore ); - const usedPostType = postType ?? getEditedPostType(); - const usedPostId = postId ?? getEditedPostId(); - const _record = getEditedEntityRecord( - 'postType', - usedPostType, - usedPostId - ); - const _isLoaded = - usedPostId && - hasFinishedResolution( 'getEditedEntityRecord', [ - 'postType', - usedPostType, - usedPostId, - ] ); - const templateInfo = getTemplateInfo( _record ); - - return { - record: _record, - title: templateInfo.title, - description: templateInfo.description, - isLoaded: _isLoaded, - icon: templateInfo.icon, - }; - }, - [ postType, postId ] - ); - - return { - isLoaded, - icon, - record, - getTitle: () => ( title ? decodeEntities( title ) : null ), - getDescription: () => - description ? decodeEntities( description ) : null, - }; -} From 201f6a7b17d62a722c24cce8be78194e4b8c8d0f Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Wed, 13 Nov 2024 12:37:26 +0100 Subject: [PATCH 1558/1908] Update text case of "Starter Content" (#66954) Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/inserter/block-patterns-tab/utils.js | 2 +- packages/block-library/src/button/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/utils.js b/packages/block-editor/src/components/inserter/block-patterns-tab/utils.js index 58065ac33ad2b5..7e2b71545e7969 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/utils.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/utils.js @@ -27,7 +27,7 @@ export const myPatternsCategory = { export const starterPatternsCategory = { name: 'core/starter-content', - label: __( 'Starter Content' ), + label: __( 'Starter content' ), }; export function isPatternFiltered( pattern, sourceFilter, syncFilter ) { diff --git a/packages/block-library/src/button/index.js b/packages/block-library/src/button/index.js index 2b05b280028abd..32212afc2eb706 100644 --- a/packages/block-library/src/button/index.js +++ b/packages/block-library/src/button/index.js @@ -22,7 +22,7 @@ export const settings = { example: { attributes: { className: 'is-style-fill', - text: __( 'Call to Action' ), + text: __( 'Call to action' ), }, }, edit, From aba08da3b67ca5b7b0edd5096af93569b30dc0a6 Mon Sep 17 00:00:00 2001 From: Yogesh Bhutkar <yogesh.bhutkar@rtcamp.com> Date: Wed, 13 Nov 2024 18:00:05 +0530 Subject: [PATCH 1559/1908] Site Hub: Fixed navigation redirect on mobile devices for classic themes (#66867) * Site Hub: Enhance mobile component with dashboard link and block theme detection * Site Hub: Simplify dashboard link rendering logic for non-block themes * Site Hub: Remove fallback for block theme detection in mobile component Co-authored-by: yogeshbhutkar <yogeshbhutkar@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ironprogrammer <ironprogrammer@git.wordpress.org> --- .../src/components/site-hub/index.js | 49 +++++++++++++------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/packages/edit-site/src/components/site-hub/index.js b/packages/edit-site/src/components/site-hub/index.js index 3f34b8bd1cccb6..9e57034bfe73aa 100644 --- a/packages/edit-site/src/components/site-hub/index.js +++ b/packages/edit-site/src/components/site-hub/index.js @@ -121,17 +121,27 @@ export const SiteHubMobile = memo( const history = useHistory(); const { navigate } = useContext( SidebarNavigationContext ); - const { homeUrl, siteTitle } = useSelect( ( select ) => { - const { getEntityRecord } = select( coreStore ); - const _site = getEntityRecord( 'root', 'site' ); - return { - homeUrl: getEntityRecord( 'root', '__unstableBase' )?.home, - siteTitle: - ! _site?.title && !! _site?.url - ? filterURLForDisplay( _site?.url ) - : _site?.title, - }; - }, [] ); + const { dashboardLink, isBlockTheme, homeUrl, siteTitle } = useSelect( + ( select ) => { + const { getSettings } = unlock( select( editSiteStore ) ); + + const { getEntityRecord, getCurrentTheme } = + select( coreStore ); + const _site = getEntityRecord( 'root', 'site' ); + return { + dashboardLink: + getSettings().__experimentalDashboardLink || + 'index.php', + isBlockTheme: getCurrentTheme()?.is_block_theme, + homeUrl: getEntityRecord( 'root', '__unstableBase' )?.home, + siteTitle: + ! _site?.title && !! _site?.url + ? filterURLForDisplay( _site?.url ) + : _site?.title, + }; + }, + [] + ); const { open: openCommandCenter } = useDispatch( commandsStore ); return ( @@ -148,16 +158,23 @@ export const SiteHubMobile = memo( <Button __next40pxDefaultSize ref={ ref } - label={ __( 'Go to Site Editor' ) } className="edit-site-layout__view-mode-toggle" style={ { transform: 'scale(0.5)', borderRadius: 4, } } - onClick={ () => { - history.push( {} ); - navigate( 'back' ); - } } + { ...( ! isBlockTheme + ? { + href: dashboardLink, + label: __( 'Go to the Dashboard' ), + } + : { + onClick: () => { + history.push( {} ); + navigate( 'back' ); + }, + label: __( 'Go to Site Editor' ), + } ) } > <SiteIcon className="edit-site-layout__view-mode-toggle-icon" /> </Button> From 65c45a3a98d850a6f9b410c20f3b5a4bbca4a047 Mon Sep 17 00:00:00 2001 From: Karthick M <97787966+karthick-murugan@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:34:43 +0530 Subject: [PATCH 1560/1908] Site Hub: Fix the site icon button focus (#66952) Unlinked contributors: kNoCoding. Co-authored-by: karthick-murugan <karthickmurugan@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: vipul0425 <vipulgupta003@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> --- .../src/components/site-icon/style.scss | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/edit-site/src/components/site-icon/style.scss b/packages/edit-site/src/components/site-icon/style.scss index a6cc7ad27fe5df..bd18b486ca3427 100644 --- a/packages/edit-site/src/components/site-icon/style.scss +++ b/packages/edit-site/src/components/site-icon/style.scss @@ -20,3 +20,19 @@ border-radius: 0; } } + +.edit-site-editor__view-mode-toggle button:focus { + position: relative; + + &::before { + content: ""; + display: block; + position: absolute; + z-index: 1; + top: 0; + right: 0; + bottom: 0; + left: 0; + box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color), inset 0 0 0 calc(#{ $border-width } + var(--wp-admin-border-width-focus)) $white; + } +} From f400d46e1aeed8c86d052dfd751b615dcc9d2ad7 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 13 Nov 2024 15:10:51 +0100 Subject: [PATCH 1561/1908] Block Editor: Fix 'useSelect' dependencies for the 'RichText component (#66964) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-editor/src/components/rich-text/index.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 8a5d99a7eb9f0a..8f179d08570ad1 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -233,7 +233,14 @@ export function RichTextWrapper( bindingsLabel: _bindingsLabel, }; }, - [ blockBindings, identifier, blockName, blockContext, adjustedValue ] + [ + blockBindings, + identifier, + blockName, + adjustedValue, + clientId, + blockContext, + ] ); const shouldDisableEditing = readOnly || disableBoundBlock; From 61f914ed584ea7f4b3716ee25e5edcc794afe85f Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Wed, 13 Nov 2024 15:14:09 +0100 Subject: [PATCH 1562/1908] Data: upgrade Redux to v5.0.1 (#66966) Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- package-lock.json | 13 +++++-------- package.json | 2 +- packages/data/package.json | 2 +- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 27f01fd681824f..01e01de33562fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -135,7 +135,7 @@ "react-scanner": "1.2.0", "react-test-renderer": "18.3.1", "reassure": "0.7.1", - "redux": "4.1.2", + "redux": "5.0.1", "resize-observer-polyfill": "1.5.1", "rimraf": "3.0.2", "rtlcss": "4.0.0", @@ -43764,12 +43764,9 @@ } }, "node_modules/redux": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", - "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", - "dependencies": { - "@babel/runtime": "^7.9.2" - } + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" }, "node_modules/regenerate": { "version": "1.4.2", @@ -53963,7 +53960,7 @@ "equivalent-key-map": "^0.2.2", "is-plain-object": "^5.0.0", "is-promise": "^4.0.0", - "redux": "^4.1.2", + "redux": "^5.0.1", "rememo": "^4.0.2", "use-memo-one": "^1.1.1" }, diff --git a/package.json b/package.json index 0fdb7ad563cd15..561eeffc2517e8 100644 --- a/package.json +++ b/package.json @@ -144,7 +144,7 @@ "react-scanner": "1.2.0", "react-test-renderer": "18.3.1", "reassure": "0.7.1", - "redux": "4.1.2", + "redux": "5.0.1", "resize-observer-polyfill": "1.5.1", "rimraf": "3.0.2", "rtlcss": "4.0.0", diff --git a/packages/data/package.json b/packages/data/package.json index fd1ef7ef4d7489..1117a8373ff121 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -42,7 +42,7 @@ "equivalent-key-map": "^0.2.2", "is-plain-object": "^5.0.0", "is-promise": "^4.0.0", - "redux": "^4.1.2", + "redux": "^5.0.1", "rememo": "^4.0.2", "use-memo-one": "^1.1.1" }, From bd69042805b7d957419b7ed3ea0d9b523247db9b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:33:26 +0000 Subject: [PATCH 1563/1908] Bump the react-native group across 1 directory with 2 updates (#66963) Bumps the react-native group with 2 updates in the / directory: [actions/setup-java](https://github.com/actions/setup-java) and [gradle/actions](https://github.com/gradle/actions). Updates `actions/setup-java` from 4.4.0 to 4.5.0 - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/b36c23c0d998641eff861008f374ee103c25ac73...8df1039502a15bceb9433410b1a100fbe190c53b) Updates `gradle/actions` from 4.1.0 to 4.2.0 - [Release notes](https://github.com/gradle/actions/releases) - [Commits](https://github.com/gradle/actions/compare/d156388eb19639ec20ade50009f3d199ce1e2808...473878a77f1b98e2b5ac4af93489d1656a80a5ed) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor dependency-group: react-native - dependency-name: gradle/actions dependency-type: direct:production update-type: version-update:semver-minor dependency-group: react-native ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/rnmobile-android-runner.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index 65bb55e3f63201..43a71809b5bbe7 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -28,7 +28,7 @@ jobs: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Java - uses: actions/setup-java@b36c23c0d998641eff861008f374ee103c25ac73 # v4.4.0 + uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0 with: distribution: 'corretto' java-version: '17' @@ -47,7 +47,7 @@ jobs: run: npm run native test:e2e:setup - name: Gradle cache - uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0 + uses: gradle/actions/setup-gradle@473878a77f1b98e2b5ac4af93489d1656a80a5ed # v4.2.0 # AVD cache disabled as it caused emulator termination to hang indefinitely. # https://github.com/ReactiveCircus/android-emulator-runner/issues/385 From b73fbf60223a12a63285eed5e0e46a529f197531 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 10:38:10 -0500 Subject: [PATCH 1564/1908] Bump ruby/setup-ruby in the github-actions group across 1 directory (#66910) Bumps the github-actions group with 1 update in the / directory: [ruby/setup-ruby](https://github.com/ruby/setup-ruby). Updates `ruby/setup-ruby` from 1.197.0 to 1.202.0 - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb) - [Commits](https://github.com/ruby/setup-ruby/compare/7bae1d00b5db9166f4f0fc47985a3a5702cb58f0...a2bbe5b1b236842c1cb7dd11e8e3b51e0a616acc) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/rnmobile-ios-runner.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rnmobile-ios-runner.yml b/.github/workflows/rnmobile-ios-runner.yml index 8851c7c12c4a4a..d28ee65c719e43 100644 --- a/.github/workflows/rnmobile-ios-runner.yml +++ b/.github/workflows/rnmobile-ios-runner.yml @@ -27,7 +27,7 @@ jobs: with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - uses: ruby/setup-ruby@7bae1d00b5db9166f4f0fc47985a3a5702cb58f0 # v1.197.0 + - uses: ruby/setup-ruby@a2bbe5b1b236842c1cb7dd11e8e3b51e0a616acc # v1.202.0 with: # `.ruby-version` file location working-directory: packages/react-native-editor/ios From 3f928441caa1b496dc45edfd9830a2a62b59069c Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 13 Nov 2024 15:51:05 +0000 Subject: [PATCH 1565/1908] Bump plugin version to 19.7.0-rc.1 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index eed059a15c9a35..ac250e5671a4d2 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.6.1 + * Version: 19.7.0-rc.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 01e01de33562fe..0e5b7f21044c43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.6.1", + "version": "19.7.0-rc.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.6.1", + "version": "19.7.0-rc.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", "workspaces": [ diff --git a/package.json b/package.json index 561eeffc2517e8..a2059f7d53a65d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.6.1", + "version": "19.7.0-rc.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 5b52c6372f4b16d888f75f5af2b23402f0037ae4 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 13 Nov 2024 16:52:39 +0100 Subject: [PATCH 1566/1908] Data: Add changelog for Redux update (#66968) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- packages/data/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index 98c553b08b67b9..9ceb1521e6cd6d 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Upgrade `redux` dependency to `^5.0.1` ([#66966](https://github.com/WordPress/gutenberg/pull/66966)) + ## 10.11.0 (2024-10-30) ## 10.10.0 (2024-10-16) From ec964d360cff0108a079ed79d1ffd9f86f645b3d Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 13 Nov 2024 16:08:02 +0000 Subject: [PATCH 1567/1908] Update Changelog for 19.7.0-rc.1 --- changelog.txt | 289 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 289 insertions(+) diff --git a/changelog.txt b/changelog.txt index 0dc99f5e205e32..af07058d4ddec5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,294 @@ == Changelog == += 19.7.0-rc.1 = + + +## Changelog + +### Enhancements + +- Add "show template" to preview dropdown. ([66514](https://github.com/WordPress/gutenberg/pull/66514)) +- Iframe: Always enable for block themes, in core too. ([66800](https://github.com/WordPress/gutenberg/pull/66800)) +- Media Utils: Add experimental `sideloadMedia`. ([66378](https://github.com/WordPress/gutenberg/pull/66378)) +- Post fields: Clean up. ([66941](https://github.com/WordPress/gutenberg/pull/66941)) +- Post fields: Extract `title` from `edit-site` to `fields` package. ([66940](https://github.com/WordPress/gutenberg/pull/66940)) +- Post fields: Move `comment_status` from edit-site to fields package. ([66934](https://github.com/WordPress/gutenberg/pull/66934)) +- Post fields: Move `date` fields from `edit-site` to `fields` package. ([66938](https://github.com/WordPress/gutenberg/pull/66938)) +- Post fields: Move `status` from `edit-site` to `fields`. ([66937](https://github.com/WordPress/gutenberg/pull/66937)) +- Relocate “View” external link to end of editor header controls. ([66785](https://github.com/WordPress/gutenberg/pull/66785)) + +#### Block Library +- Added toggle control to set any image as feature image if no feature image is set for post. ([65896](https://github.com/WordPress/gutenberg/pull/65896)) +- Improve cover z-index solution. ([66249](https://github.com/WordPress/gutenberg/pull/66249)) +- Post Content: Add border and spacing support. ([66366](https://github.com/WordPress/gutenberg/pull/66366)) +- Query Loop: Use templateSlug and postType for more context. ([65820](https://github.com/WordPress/gutenberg/pull/65820)) +- Update text case of "Starter Content". ([66954](https://github.com/WordPress/gutenberg/pull/66954)) +- [Details Block]: Adds anchor support in details block. ([66734](https://github.com/WordPress/gutenberg/pull/66734)) + +#### Components +- Guide: Use small size button for page controls. ([66607](https://github.com/WordPress/gutenberg/pull/66607)) +- MenuItem: Add 40px size prop on Button. ([66596](https://github.com/WordPress/gutenberg/pull/66596)) +- Notice: Add appropriate size props to Buttons. ([66593](https://github.com/WordPress/gutenberg/pull/66593)) +- PaletteEdit: Add appropriate size props to Buttons. ([66590](https://github.com/WordPress/gutenberg/pull/66590)) +- Popover: Add small size prop to close button. ([66587](https://github.com/WordPress/gutenberg/pull/66587)) + +#### Global Styles +- Global styles revisions: Move focus and active state to list item. ([66780](https://github.com/WordPress/gutenberg/pull/66780)) +- Site editor: Integrate global styles controls and style book preview into the styles panel. ([65619](https://github.com/WordPress/gutenberg/pull/65619)) + +#### DataViews +- DataViews Fields API: Default getValueFromId supports nested objects. ([66890](https://github.com/WordPress/gutenberg/pull/66890)) + +#### Block Editor +- Inserter: Add 'Starter Content' category to the inserter. ([66819](https://github.com/WordPress/gutenberg/pull/66819)) + +#### Zoom Out +- Enable zoom out mode for non-iframe editor. ([66789](https://github.com/WordPress/gutenberg/pull/66789)) + +#### Themes +- Theme JSON Resolver: Remove theme json merge in resolve_theme_file_uris. ([66662](https://github.com/WordPress/gutenberg/pull/66662)) + +#### Edit Mode +- Image block: Add support for "more" dropdown for additional tools in Write mode. ([66605](https://github.com/WordPress/gutenberg/pull/66605)) + +#### Style Book +- Add a landing section to stylebook tabs. ([66545](https://github.com/WordPress/gutenberg/pull/66545)) + +#### Media +- Media Library: Expose filters dropdown for individual images, such as with the Image block. ([65965](https://github.com/WordPress/gutenberg/pull/65965)) + + +### Bug Fixes + +- Block toolbar: Restrict visible child calculation to known blocks. ([66702](https://github.com/WordPress/gutenberg/pull/66702)) +- ComplementaryArea: Fix button position. ([66677](https://github.com/WordPress/gutenberg/pull/66677)) +- Fix Paragraph appender layout shift (building on 66061). ([66779](https://github.com/WordPress/gutenberg/pull/66779)) +- Fix: Set the `fit-content` width for images that are not `.svg`. ([66643](https://github.com/WordPress/gutenberg/pull/66643)) +- Preference modal: Avoid fetching all reusable blocks when the site editor loads. ([66621](https://github.com/WordPress/gutenberg/pull/66621)) +- Revert "Set image width to `fit-content` to solve aspect ratio problems in Firefox. (#66217)". ([66804](https://github.com/WordPress/gutenberg/pull/66804)) +- Safari: Fix site editor template error. ([66647](https://github.com/WordPress/gutenberg/pull/66647)) +- Safari: Prevent focus capturing caused by flex display. ([66402](https://github.com/WordPress/gutenberg/pull/66402)) +- Select Mode: Hide tool selector in the post editor and force design mode. ([66784](https://github.com/WordPress/gutenberg/pull/66784)) +- Shadow panel: Make the delete modal text translatable. ([66712](https://github.com/WordPress/gutenberg/pull/66712)) +- Site Editor: Fix template for page-on-front option. ([66739](https://github.com/WordPress/gutenberg/pull/66739)) +- WP Scripts: Make watch mode more resilient for developer errors. ([66752](https://github.com/WordPress/gutenberg/pull/66752)) +- getDefaultTemplateId: Ensure entity configuration is loaded. ([66650](https://github.com/WordPress/gutenberg/pull/66650)) + +#### Block Library +- Cover: Fix media library image selection. ([66782](https://github.com/WordPress/gutenberg/pull/66782)) +- Cover: Show DropZone only when dragging withing the block. ([66912](https://github.com/WordPress/gutenberg/pull/66912)) +- Media & Text: Set `.wp-block-media-text__media a` display to block. ([66915](https://github.com/WordPress/gutenberg/pull/66915)) +- Prevent duplicate post format taxonomy queries. ([66627](https://github.com/WordPress/gutenberg/pull/66627)) +- Query Loop: Check for postTypeFromContext before using it. ([66655](https://github.com/WordPress/gutenberg/pull/66655)) +- Query Loop: Remove postTypeFromContext. ([66681](https://github.com/WordPress/gutenberg/pull/66681)) + +#### Block Editor +- Appender: Fix initial position. ([66711](https://github.com/WordPress/gutenberg/pull/66711)) +- Appender: Fix outside canvas styles. ([66630](https://github.com/WordPress/gutenberg/pull/66630)) +- Block Inspector: Restore bottom margin for RadioControl. ([66688](https://github.com/WordPress/gutenberg/pull/66688)) +- Iframed editor: Fix relative wp-content URLs. ([66751](https://github.com/WordPress/gutenberg/pull/66751)) + +#### Global Styles +- Section Styles: Fix insecure properties removal for inner block types and elements. ([66896](https://github.com/WordPress/gutenberg/pull/66896)) +- Style book: Reduce margin selector specificity so that it doesn't override global block styles. ([66895](https://github.com/WordPress/gutenberg/pull/66895)) +- Theme JSON: Replace top-level background style objects on merge. ([66656](https://github.com/WordPress/gutenberg/pull/66656)) + +#### Components +- FormTokenField: Fix token styles. ([66640](https://github.com/WordPress/gutenberg/pull/66640)) +- Storybook: Fix DataViews action modals. ([66727](https://github.com/WordPress/gutenberg/pull/66727)) +- ToggleGroupControl: Fix active background for `zero` value. ([66855](https://github.com/WordPress/gutenberg/pull/66855)) + +#### Post Editor +- Disable device preview button in pattern/template part/navitation editor. ([65970](https://github.com/WordPress/gutenberg/pull/65970)) +- PostTaxonomiesFlatTermSelector: Abstract wrapper component. ([66625](https://github.com/WordPress/gutenberg/pull/66625)) +- VisualEditor: Always output has-global-padding classname when in post only mode. ([66626](https://github.com/WordPress/gutenberg/pull/66626)) + +#### DataViews +- Fix TypeError when duplicating uncategorized theme patterns. ([66889](https://github.com/WordPress/gutenberg/pull/66889)) +- Tweak primary field in patterns grid layout. ([66733](https://github.com/WordPress/gutenberg/pull/66733)) + +#### Meta Boxes +- Fix: Show Meta Boxes at the bottom of the screen regardless of the current rendering mode. ([66508](https://github.com/WordPress/gutenberg/pull/66508)) +- Hide metaboxes in Zoom Out. ([66886](https://github.com/WordPress/gutenberg/pull/66886)) + +#### Site Editor +- DataViews: Fix 'aria-label' for pattern preview element. ([66601](https://github.com/WordPress/gutenberg/pull/66601)) +- Site Hub: Fixed navigation redirect on mobile devices for classic themes. ([66867](https://github.com/WordPress/gutenberg/pull/66867)) + +#### Media +- Add `x-wav` mime type for wav files in Firefox. ([66850](https://github.com/WordPress/gutenberg/pull/66850)) +- Ensure HEIC files selectable from “Upload” button. ([66292](https://github.com/WordPress/gutenberg/pull/66292)) + +#### Patterns +- Fix uncategorized pattern browsing when pattern has no categories. ([66945](https://github.com/WordPress/gutenberg/pull/66945)) + +#### Interactivity API +- Fix property modification from inherited context two or more levels above. ([66872](https://github.com/WordPress/gutenberg/pull/66872)) + +#### Block API +- Process Block Type: Copy deprecation to a new object instead of mutating when stabilizing supports. ([66849](https://github.com/WordPress/gutenberg/pull/66849)) + +#### Design Tools +- Block Gap: Fix block spacing control for axial gap supported blocks. ([66783](https://github.com/WordPress/gutenberg/pull/66783)) + +#### Document Settings +- Editor: Restore the 'PluginPostStatusInfo' slot position. ([66665](https://github.com/WordPress/gutenberg/pull/66665)) + +#### Templates API +- Fix flash when clicking template name in the editor when a plugin registered template matches a default WP theme template. ([66359](https://github.com/WordPress/gutenberg/pull/66359)) + +#### Block bindings +- Fix unset array key warning in block-bindings.php. ([66337](https://github.com/WordPress/gutenberg/pull/66337)) + + +### Accessibility + +- Fix : Snackbar Notice Inconsistency. ([66405](https://github.com/WordPress/gutenberg/pull/66405)) +- Image: Add `aria-haspopup` prop write mode `more` tools menu items. ([66815](https://github.com/WordPress/gutenberg/pull/66815)) +- Site Icon Focus fix. ([66952](https://github.com/WordPress/gutenberg/pull/66952)) + +#### Components +- Popover: Fix missing label of the headerTitle Close button. ([66813](https://github.com/WordPress/gutenberg/pull/66813)) + +#### Post Editor +- Fix inconsistent sidebars close buttons sizes. ([66756](https://github.com/WordPress/gutenberg/pull/66756)) + +#### Block Library +- Remove unnecessary tooltip from Video block Text tracks button. ([66716](https://github.com/WordPress/gutenberg/pull/66716)) + +#### Block Editor +- Speak 'Block moved up/down' after using keyboard actions to move up/down. ([64966](https://github.com/WordPress/gutenberg/pull/64966)) + +#### Patterns +- Block Patterns List: Fix visual title and tooltip inconsistencies. ([64815](https://github.com/WordPress/gutenberg/pull/64815)) + + +### Performance + +- Inline Commenting: Avoid querying comments on editor load. ([66670](https://github.com/WordPress/gutenberg/pull/66670)) +- Patterns: Receive intermediate responses while unbound request is resolving. ([66713](https://github.com/WordPress/gutenberg/pull/66713)) +- Perf metrics: Update select and other metrics to use non-empty paragraphs. ([66762](https://github.com/WordPress/gutenberg/pull/66762)) +- Site Editor: Preload settings requests. ([66488](https://github.com/WordPress/gutenberg/pull/66488)) +- Site Editor: Speed up load by preloading home and front-page templates. ([66579](https://github.com/WordPress/gutenberg/pull/66579)) +- Site editor: Preload post if needed. ([66631](https://github.com/WordPress/gutenberg/pull/66631)) + +#### Global Styles +- Preload user global styles based on user caps. ([66541](https://github.com/WordPress/gutenberg/pull/66541)) + + +### Experiments + +- Add `isVisible` option to fields within DataForm. ([65826](https://github.com/WordPress/gutenberg/pull/65826)) +- DataViews: Implement `isItemClickable` and `onClickItem` props. ([66365](https://github.com/WordPress/gutenberg/pull/66365)) + +#### DataViews +- Quick Edit - Slug Field: Improve slug preview. ([66559](https://github.com/WordPress/gutenberg/pull/66559)) +- QuickEdit: Add password field data to the pages quick edit. ([66567](https://github.com/WordPress/gutenberg/pull/66567)) + + +### Documentation + +- Add 6.6.2 to Version in WordPress. ([66870](https://github.com/WordPress/gutenberg/pull/66870)) +- Add missing properties for DataViews/DataForm components. ([66749](https://github.com/WordPress/gutenberg/pull/66749)) +- Add section about the Fields API. ([66761](https://github.com/WordPress/gutenberg/pull/66761)) +- Block Bindings: Documentation API reference. ([66251](https://github.com/WordPress/gutenberg/pull/66251)) +- Docs: Include a note about supported licenses in WordPress packages. ([66562](https://github.com/WordPress/gutenberg/pull/66562)) +- Document `filterSortAndPaginate` & `isItemValid` utilities. ([66738](https://github.com/WordPress/gutenberg/pull/66738)) +- Feat: Storybook: Improve component organisation - Navigation Category - Issue #66275. ([66658](https://github.com/WordPress/gutenberg/pull/66658)) +- Feat: Storybook: Improve component organisation - Overlays Category - Issue #66275. ([66657](https://github.com/WordPress/gutenberg/pull/66657)) +- Feat: Storybook: Improve component organisation - Selection & Input Category - Issue #66275. ([66660](https://github.com/WordPress/gutenberg/pull/66660)) +- Feat: Storybook: Improve component organisation - Typography - Issue #66275. ([66633](https://github.com/WordPress/gutenberg/pull/66633)) +- Improve readability of DataViews documentation. ([66766](https://github.com/WordPress/gutenberg/pull/66766)) +- Move documentation for filter operators to proper place. ([66743](https://github.com/WordPress/gutenberg/pull/66743)) +- Reorganize to bootstrap DataForm API section. ([66729](https://github.com/WordPress/gutenberg/pull/66729)) +- Storybook: Improve component organisation - Actions. ([66680](https://github.com/WordPress/gutenberg/pull/66680)) +- Storybook: Log `warning()` when in dev mode. ([66568](https://github.com/WordPress/gutenberg/pull/66568)) +- Update Commands documentation with the existing contexts. ([66860](https://github.com/WordPress/gutenberg/pull/66860)) + + +### Code Quality + +- BlockPatternsList: Use the Async component. ([66744](https://github.com/WordPress/gutenberg/pull/66744)) +- Core Commands: Fix add new post URL assignment. ([66830](https://github.com/WordPress/gutenberg/pull/66830)) +- Inline Commenting: Optimize store selector and misc changes. ([66592](https://github.com/WordPress/gutenberg/pull/66592)) +- Remove unnecessary boolean assignments. ([66857](https://github.com/WordPress/gutenberg/pull/66857)) +- TypeScript: Fix and improve types for private-apis. ([66667](https://github.com/WordPress/gutenberg/pull/66667)) + +#### Block Editor +- Fix 'useSelect' dependencies for the 'RichText' component. ([66964](https://github.com/WordPress/gutenberg/pull/66964)) +- Fix ESLint warning for 'useBlockTypesState' hook. ([66757](https://github.com/WordPress/gutenberg/pull/66757)) +- Fix React Compiler error for 'BlockProps' util component. ([66809](https://github.com/WordPress/gutenberg/pull/66809)) +- Optimize `getVisibleElementBounds` in scrollable cases. ([66546](https://github.com/WordPress/gutenberg/pull/66546)) +- Revert: Fix unable to remove empty blocks on merge (#65262) + alternative. ([66564](https://github.com/WordPress/gutenberg/pull/66564)) +- URLInput: Fix incorrect classname for suggestions. ([66714](https://github.com/WordPress/gutenberg/pull/66714)) + +#### Site Editor +- Avoid using edited entity state in site editor loading hook. ([66924](https://github.com/WordPress/gutenberg/pull/66924)) +- Avoid using edited post selectors in welcome guide. ([66926](https://github.com/WordPress/gutenberg/pull/66926)) +- Edit Site: Refactor to remove usage of edited entity state. ([66922](https://github.com/WordPress/gutenberg/pull/66922)) +- Edit Site: Remove leftover 'priority-queue' dependency. ([66773](https://github.com/WordPress/gutenberg/pull/66773)) +- Remove useEditedEntityRecord hook. ([66955](https://github.com/WordPress/gutenberg/pull/66955)) + +#### Components +- Fix React Compiler error for 'useScrollRectIntoView'. ([66498](https://github.com/WordPress/gutenberg/pull/66498)) +- Panel: Add 40px size prop to Button. ([66589](https://github.com/WordPress/gutenberg/pull/66589)) +- Radio: Deprecate 36px default size. ([66572](https://github.com/WordPress/gutenberg/pull/66572)) +- Snackbar: Use `link` variant for action Button. ([66560](https://github.com/WordPress/gutenberg/pull/66560)) + +#### Data Layer +- Convert the emitter module in data package to TS. ([66669](https://github.com/WordPress/gutenberg/pull/66669)) +- Data: Rename useSelect internals to fix React Compiler violations. ([66807](https://github.com/WordPress/gutenberg/pull/66807)) +- Data: Upgrade Redux to v5.0.1. ([66966](https://github.com/WordPress/gutenberg/pull/66966)) + +#### Post Editor +- ESLint: Fix React Compiler violations in various commands. ([66787](https://github.com/WordPress/gutenberg/pull/66787)) +- Fix TS types for editor package. ([66754](https://github.com/WordPress/gutenberg/pull/66754)) + +#### Zoom Out +- Zoom-out: Move default background to the iframe component. ([66284](https://github.com/WordPress/gutenberg/pull/66284)) + +#### Design Tools +- Typography: Stabilize typography block supports within block processing. ([63401](https://github.com/WordPress/gutenberg/pull/63401)) + + +### Tools + +#### Testing +- Media: Check for `wav` mime type using isset. ([66947](https://github.com/WordPress/gutenberg/pull/66947)) + +#### Build Tooling +- Enforce the same order of fields in `package.json` files. ([66239](https://github.com/WordPress/gutenberg/pull/66239)) +- Introduce React Scanner for component usage stats. ([65463](https://github.com/WordPress/gutenberg/pull/65463)) + + +### Various + +- Style engine: Wrap array_merge in conditionals to prevent unnecessary merging. ([66661](https://github.com/WordPress/gutenberg/pull/66661)) + +#### Block Library +- Update placeholder text for blocks that support drag and drop. ([66842](https://github.com/WordPress/gutenberg/pull/66842)) +- update: Add Media to Add media in cover block. ([66835](https://github.com/WordPress/gutenberg/pull/66835)) + + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @benharri: Fix unset array key warning in block-bindings.php. ([66337](https://github.com/WordPress/gutenberg/pull/66337)) +- @benniledl: Add 6.6.2 to Version in WordPress. ([66870](https://github.com/WordPress/gutenberg/pull/66870)) +- @Infinite-Null: Media & Text: Set `.wp-block-media-text__media a` display to block. ([66915](https://github.com/WordPress/gutenberg/pull/66915)) +- @karthick-murugan: Site Icon Focus fix. ([66952](https://github.com/WordPress/gutenberg/pull/66952)) +- @rinkalpagdar: Post Content: Add border and spacing support. ([66366](https://github.com/WordPress/gutenberg/pull/66366)) +- @yogeshbhutkar: Site Hub: Fixed navigation redirect on mobile devices for classic themes. ([66867](https://github.com/WordPress/gutenberg/pull/66867)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @adamsilverstein @afercia @Aljullu @amitraj2203 @andrewserong @benharri @benniledl @carolinan @cbravobernal @DAreRodz @dcalhoun @ellatrix @fabiankaegy @gigitux @gziolo @hbhalodia @Infinite-Null @jasmussen @jorgefilipecosta @jsnajdr @juanfra @karthick-murugan @kevin940726 @louwie17 @Mamaduka @manzoorwanijk @matiasbenedetto @mikachan @mirka @n2erjo00 @ntsekouras @oandregal @ramonjd @renatho @rinkalpagdar @Soean @stokesman @swissspidy @t-hamano @tellthemachines @tyxla @up1512001 @Vrishabhsk @yogeshbhutkar @youknowriad + + = 19.6.1 = From 6465b2df5d6a20f176d325bd17dfda32ee472935 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Thu, 14 Nov 2024 00:15:53 +0530 Subject: [PATCH 1568/1908] Feat: Storybook: Improve component organisation - Layout Category - Issue #66275 (#66659) * Group the storybook components in Layout category * Fix the experimental component id * Revert the unwanted changes in PR --------- Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/src/h-stack/stories/index.story.tsx | 3 ++- .../components/src/responsive-wrapper/stories/index.story.tsx | 3 ++- packages/components/src/v-stack/stories/index.story.tsx | 3 ++- storybook/preview.js | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/components/src/h-stack/stories/index.story.tsx b/packages/components/src/h-stack/stories/index.story.tsx index 88aebb7682e476..025c3384bddceb 100644 --- a/packages/components/src/h-stack/stories/index.story.tsx +++ b/packages/components/src/h-stack/stories/index.story.tsx @@ -42,7 +42,8 @@ const JUSTIFICATIONS = { const meta: Meta< typeof HStack > = { component: HStack, - title: 'Components (Experimental)/HStack', + title: 'Components (Experimental)/Layout/HStack', + id: 'components-experimental-hstack', argTypes: { as: { control: { type: null }, diff --git a/packages/components/src/responsive-wrapper/stories/index.story.tsx b/packages/components/src/responsive-wrapper/stories/index.story.tsx index cf676c3bcec801..d684a00c870028 100644 --- a/packages/components/src/responsive-wrapper/stories/index.story.tsx +++ b/packages/components/src/responsive-wrapper/stories/index.story.tsx @@ -10,7 +10,8 @@ import ResponsiveWrapper from '..'; const meta: Meta< typeof ResponsiveWrapper > = { component: ResponsiveWrapper, - title: 'Components/ResponsiveWrapper', + title: 'Components/Layout/ResponsiveWrapper', + id: 'components-responsivewrapper', argTypes: { children: { control: { type: null } }, }, diff --git a/packages/components/src/v-stack/stories/index.story.tsx b/packages/components/src/v-stack/stories/index.story.tsx index 781c1bce6676cc..11d6d579abc81e 100644 --- a/packages/components/src/v-stack/stories/index.story.tsx +++ b/packages/components/src/v-stack/stories/index.story.tsx @@ -25,7 +25,8 @@ const ALIGNMENTS = { const meta: Meta< typeof VStack > = { component: VStack, - title: 'Components (Experimental)/VStack', + title: 'Components (Experimental)/Layout/VStack', + id: 'components-experimental-vstack', argTypes: { alignment: { control: { type: 'select' }, diff --git a/storybook/preview.js b/storybook/preview.js index a045b0c3303d39..435fa4dbc43264 100644 --- a/storybook/preview.js +++ b/storybook/preview.js @@ -133,13 +133,14 @@ export const parameters = { 'Actions', 'Containers', 'Feedback', + 'Layout', 'Navigation', 'Overlays', 'Typography', 'Utilities', ], 'Components (Experimental)', - [ 'Navigation', 'Overlays', 'Typography' ], + [ 'Layout', 'Navigation', 'Overlays', 'Typography' ], 'Icons', ], }, From ee5aee9263474836b54b1399fdd1342cb3ffa175 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Thu, 14 Nov 2024 00:52:51 +0530 Subject: [PATCH 1569/1908] Feat: Storybook: Improve component organisation - Selection & Input Category - Issue #66275 (#66635) * Update the storybook components for selection and input category * Add treeselect under selection&input category and revert experimental component change * Fix experimental id and sort folders alphabetically * Fix the experimental id for toggleGroupControl * Revert changes that are not needed in PR * Revert the missing change on conflict resolve * Fix formatting * Fixup (Sort experimental Actions) * Remove unnecessary experimental Common grouping * Remove excessive Search & Filtering grouping --------- Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/base-control/stories/index.story.tsx | 3 ++- .../src/checkbox-control/stories/index.story.tsx | 3 ++- .../circular-option-picker/stories/index.story.tsx | 3 ++- .../src/color-indicator/stories/index.story.tsx | 3 ++- .../src/color-palette/stories/index.story.tsx | 3 ++- .../src/color-picker/stories/index.story.tsx | 3 ++- .../src/combobox-control/stories/index.story.tsx | 3 ++- .../custom-gradient-picker/stories/index.story.tsx | 3 ++- .../custom-select-control-v2/stories/index.story.tsx | 3 ++- .../src/date-time/stories/date-time.story.tsx | 3 ++- .../components/src/date-time/stories/date.story.tsx | 3 ++- .../components/src/date-time/stories/time.story.tsx | 3 ++- .../components/src/drop-zone/stories/index.story.tsx | 3 ++- .../src/form-file-upload/stories/index.story.tsx | 3 ++- .../src/form-token-field/stories/index.story.tsx | 3 ++- .../src/gradient-picker/stories/index.story.tsx | 3 ++- .../src/input-control/stories/index.story.tsx | 3 ++- .../src/number-control/stories/index.story.tsx | 3 ++- .../src/radio-control/stories/index.story.tsx | 3 ++- .../src/range-control/stories/index.story.tsx | 3 ++- .../src/search-control/stories/index.story.tsx | 3 ++- .../src/select-control/stories/index.story.tsx | 3 ++- .../src/textarea-control/stories/index.story.tsx | 3 ++- .../src/toggle-control/stories/index.story.tsx | 3 ++- .../src/toggle-group-control/stories/index.story.tsx | 3 ++- .../src/tree-select/stories/index.story.tsx | 3 ++- .../src/unit-control/stories/index.story.tsx | 3 ++- storybook/preview.js | 11 ++++++++++- 28 files changed, 64 insertions(+), 28 deletions(-) diff --git a/packages/components/src/base-control/stories/index.story.tsx b/packages/components/src/base-control/stories/index.story.tsx index ca35b793621577..90517c75b5e95e 100644 --- a/packages/components/src/base-control/stories/index.story.tsx +++ b/packages/components/src/base-control/stories/index.story.tsx @@ -10,7 +10,8 @@ import BaseControl, { useBaseControlProps } from '..'; import Button from '../../button'; const meta: Meta< typeof BaseControl > = { - title: 'Components/BaseControl', + title: 'Components/Selection & Input/Common/BaseControl', + id: 'components-basecontrol', component: BaseControl, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 diff --git a/packages/components/src/checkbox-control/stories/index.story.tsx b/packages/components/src/checkbox-control/stories/index.story.tsx index 3c55ba3192a3cf..a68e380a8f7332 100644 --- a/packages/components/src/checkbox-control/stories/index.story.tsx +++ b/packages/components/src/checkbox-control/stories/index.story.tsx @@ -17,7 +17,8 @@ import { HStack } from '../../h-stack'; const meta: Meta< typeof CheckboxControl > = { component: CheckboxControl, - title: 'Components/CheckboxControl', + title: 'Components/Selection & Input/Common/CheckboxControl', + id: 'components-checkboxcontrol', argTypes: { onChange: { action: 'onChange', diff --git a/packages/components/src/circular-option-picker/stories/index.story.tsx b/packages/components/src/circular-option-picker/stories/index.story.tsx index e091a2ac54d41e..d0314670fe1694 100644 --- a/packages/components/src/circular-option-picker/stories/index.story.tsx +++ b/packages/components/src/circular-option-picker/stories/index.story.tsx @@ -17,7 +17,8 @@ const CircularOptionPickerStoryContext = createContext< { } >( {} ); const meta: Meta< typeof CircularOptionPicker > = { - title: 'Components/CircularOptionPicker', + title: 'Components/Selection & Input/Color/CircularOptionPicker', + id: 'components-circularoptionpicker', component: CircularOptionPicker, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 diff --git a/packages/components/src/color-indicator/stories/index.story.tsx b/packages/components/src/color-indicator/stories/index.story.tsx index 8a2557f30659e0..c24c26f5e844b3 100644 --- a/packages/components/src/color-indicator/stories/index.story.tsx +++ b/packages/components/src/color-indicator/stories/index.story.tsx @@ -10,7 +10,8 @@ import ColorIndicator from '..'; const meta: Meta< typeof ColorIndicator > = { component: ColorIndicator, - title: 'Components/ColorIndicator', + title: 'Components/Selection & Input/Color/ColorIndicator', + id: 'components-colorindicator', argTypes: { colorValue: { control: { type: 'color' }, diff --git a/packages/components/src/color-palette/stories/index.story.tsx b/packages/components/src/color-palette/stories/index.story.tsx index 727e840ff99358..5342fc5222be6a 100644 --- a/packages/components/src/color-palette/stories/index.story.tsx +++ b/packages/components/src/color-palette/stories/index.story.tsx @@ -14,7 +14,8 @@ import { useState } from '@wordpress/element'; import ColorPalette from '..'; const meta: Meta< typeof ColorPalette > = { - title: 'Components/ColorPalette', + title: 'Components/Selection & Input/Color/ColorPalette', + id: 'components-colorpalette', component: ColorPalette, argTypes: { as: { control: { type: null } }, diff --git a/packages/components/src/color-picker/stories/index.story.tsx b/packages/components/src/color-picker/stories/index.story.tsx index 9f2198515db1e6..44040a5265c5d3 100644 --- a/packages/components/src/color-picker/stories/index.story.tsx +++ b/packages/components/src/color-picker/stories/index.story.tsx @@ -10,7 +10,8 @@ import { ColorPicker } from '../component'; const meta: Meta< typeof ColorPicker > = { component: ColorPicker, - title: 'Components/ColorPicker', + title: 'Components/Selection & Input/Color/ColorPicker', + id: 'components-colorpicker', argTypes: { as: { control: { type: null } }, color: { control: { type: null } }, diff --git a/packages/components/src/combobox-control/stories/index.story.tsx b/packages/components/src/combobox-control/stories/index.story.tsx index 516cd262fd5aa6..954f0d96fb0d76 100644 --- a/packages/components/src/combobox-control/stories/index.story.tsx +++ b/packages/components/src/combobox-control/stories/index.story.tsx @@ -34,7 +34,8 @@ const countries = [ ]; const meta: Meta< typeof ComboboxControl > = { - title: 'Components/ComboboxControl', + title: 'Components/Selection & Input/Common/ComboboxControl', + id: 'components-comboboxcontrol', component: ComboboxControl, argTypes: { value: { control: { type: null } }, diff --git a/packages/components/src/custom-gradient-picker/stories/index.story.tsx b/packages/components/src/custom-gradient-picker/stories/index.story.tsx index 3be8eb36e5a3c2..23d5239e5d240d 100644 --- a/packages/components/src/custom-gradient-picker/stories/index.story.tsx +++ b/packages/components/src/custom-gradient-picker/stories/index.story.tsx @@ -13,7 +13,8 @@ import { useState } from '@wordpress/element'; import CustomGradientPicker from '../'; const meta: Meta< typeof CustomGradientPicker > = { - title: 'Components/CustomGradientPicker', + title: 'Components/Selection & Input/Color/CustomGradientPicker', + id: 'components-customgradientpicker', component: CustomGradientPicker, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/custom-select-control-v2/stories/index.story.tsx b/packages/components/src/custom-select-control-v2/stories/index.story.tsx index a3324a5fa03a47..3595ee2e951990 100644 --- a/packages/components/src/custom-select-control-v2/stories/index.story.tsx +++ b/packages/components/src/custom-select-control-v2/stories/index.story.tsx @@ -14,7 +14,8 @@ import { useState } from '@wordpress/element'; import CustomSelectControlV2 from '..'; const meta: Meta< typeof CustomSelectControlV2 > = { - title: 'Components/CustomSelectControl v2', + title: 'Components/Selection & Input/Common/CustomSelectControl v2', + id: 'components-customselectcontrol-v2', component: CustomSelectControlV2, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 diff --git a/packages/components/src/date-time/stories/date-time.story.tsx b/packages/components/src/date-time/stories/date-time.story.tsx index 86a627bbec35e0..7636e2fdc80a30 100644 --- a/packages/components/src/date-time/stories/date-time.story.tsx +++ b/packages/components/src/date-time/stories/date-time.story.tsx @@ -15,7 +15,8 @@ import DateTimePicker from '../date-time'; import { daysFromNow, isWeekend } from './utils'; const meta: Meta< typeof DateTimePicker > = { - title: 'Components/DateTimePicker', + title: 'Components/Selection & Input/Time & Date/DateTimePicker', + id: 'components-datetimepicker', component: DateTimePicker, argTypes: { currentDate: { control: 'date' }, diff --git a/packages/components/src/date-time/stories/date.story.tsx b/packages/components/src/date-time/stories/date.story.tsx index 8d1513d014c8c8..36fef0c5bfd195 100644 --- a/packages/components/src/date-time/stories/date.story.tsx +++ b/packages/components/src/date-time/stories/date.story.tsx @@ -15,7 +15,8 @@ import DatePicker from '../date'; import { daysFromNow, isWeekend } from './utils'; const meta: Meta< typeof DatePicker > = { - title: 'Components/DatePicker', + title: 'Components/Selection & Input/Time & Date/DatePicker', + id: 'components-datepicker', component: DatePicker, argTypes: { currentDate: { control: 'date' }, diff --git a/packages/components/src/date-time/stories/time.story.tsx b/packages/components/src/date-time/stories/time.story.tsx index 947b5bd64d5eb1..c19b5b4f48f5c2 100644 --- a/packages/components/src/date-time/stories/time.story.tsx +++ b/packages/components/src/date-time/stories/time.story.tsx @@ -14,7 +14,8 @@ import { useState, useEffect } from '@wordpress/element'; import TimePicker from '../time'; const meta: Meta< typeof TimePicker > = { - title: 'Components/TimePicker', + title: 'Components/Selection & Input/Time & Date/TimePicker', + id: 'components-timepicker', component: TimePicker, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { 'TimePicker.TimeInput': TimePicker.TimeInput }, diff --git a/packages/components/src/drop-zone/stories/index.story.tsx b/packages/components/src/drop-zone/stories/index.story.tsx index 1ee9af5b851ebc..7e2dcbf03c03b1 100644 --- a/packages/components/src/drop-zone/stories/index.story.tsx +++ b/packages/components/src/drop-zone/stories/index.story.tsx @@ -9,7 +9,8 @@ import DropZone from '..'; const meta: Meta< typeof DropZone > = { component: DropZone, - title: 'Components/DropZone', + id: 'components-dropzone', + title: 'Components/Selection & Input/File Upload/DropZone', parameters: { actions: { argTypesRegex: '^on.*' }, controls: { expanded: true }, diff --git a/packages/components/src/form-file-upload/stories/index.story.tsx b/packages/components/src/form-file-upload/stories/index.story.tsx index a4cf3298da6b14..3599ccc51c22eb 100644 --- a/packages/components/src/form-file-upload/stories/index.story.tsx +++ b/packages/components/src/form-file-upload/stories/index.story.tsx @@ -14,7 +14,8 @@ import { upload as uploadIcon } from '@wordpress/icons'; import FormFileUpload from '..'; const meta: Meta< typeof FormFileUpload > = { - title: 'Components/FormFileUpload', + title: 'Components/Selection & Input/File Upload/FormFileUpload', + id: 'components-formfileupload', component: FormFileUpload, argTypes: { icon: { control: { type: null } }, diff --git a/packages/components/src/form-token-field/stories/index.story.tsx b/packages/components/src/form-token-field/stories/index.story.tsx index 117dec9e9df5a1..729120ad456553 100644 --- a/packages/components/src/form-token-field/stories/index.story.tsx +++ b/packages/components/src/form-token-field/stories/index.story.tsx @@ -15,7 +15,8 @@ import FormTokenField from '../'; const meta: Meta< typeof FormTokenField > = { component: FormTokenField, - title: 'Components/FormTokenField', + title: 'Components/Selection & Input/Common/FormTokenField', + id: 'components-formtokenfield', argTypes: { value: { control: { type: null }, diff --git a/packages/components/src/gradient-picker/stories/index.story.tsx b/packages/components/src/gradient-picker/stories/index.story.tsx index b5f3a9dbca15a5..b2b73b8b609966 100644 --- a/packages/components/src/gradient-picker/stories/index.story.tsx +++ b/packages/components/src/gradient-picker/stories/index.story.tsx @@ -13,7 +13,8 @@ import { useState } from '@wordpress/element'; import GradientPicker from '..'; const meta: Meta< typeof GradientPicker > = { - title: 'Components/GradientPicker', + title: 'Components/Selection & Input/Color/GradientPicker', + id: 'components-gradientpicker', component: GradientPicker, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/input-control/stories/index.story.tsx b/packages/components/src/input-control/stories/index.story.tsx index 1a9290e8e856ea..8cef6a5d37c81b 100644 --- a/packages/components/src/input-control/stories/index.story.tsx +++ b/packages/components/src/input-control/stories/index.story.tsx @@ -16,7 +16,8 @@ import { InputControlSuffixWrapper } from '../input-suffix-wrapper'; import Button from '../../button'; const meta: Meta< typeof InputControl > = { - title: 'Components (Experimental)/InputControl', + title: 'Components (Experimental)/Selection & Input/InputControl', + id: 'components-experimental-inputcontrol', component: InputControl, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { InputControlPrefixWrapper, InputControlSuffixWrapper }, diff --git a/packages/components/src/number-control/stories/index.story.tsx b/packages/components/src/number-control/stories/index.story.tsx index 3588063f0f4bb2..3feb0d63eadc2a 100644 --- a/packages/components/src/number-control/stories/index.story.tsx +++ b/packages/components/src/number-control/stories/index.story.tsx @@ -14,7 +14,8 @@ import { useState } from '@wordpress/element'; import NumberControl from '..'; const meta: Meta< typeof NumberControl > = { - title: 'Components (Experimental)/NumberControl', + title: 'Components (Experimental)/Selection & Input/NumberControl', + id: 'components-experimental-numbercontrol', component: NumberControl, argTypes: { onChange: { action: 'onChange' }, diff --git a/packages/components/src/radio-control/stories/index.story.tsx b/packages/components/src/radio-control/stories/index.story.tsx index dae00e57962f47..3c76f7610d0d79 100644 --- a/packages/components/src/radio-control/stories/index.story.tsx +++ b/packages/components/src/radio-control/stories/index.story.tsx @@ -15,7 +15,8 @@ import RadioControl from '..'; const meta: Meta< typeof RadioControl > = { component: RadioControl, - title: 'Components/RadioControl', + title: 'Components/Selection & Input/Common/RadioControl', + id: 'components-radiocontrol', argTypes: { onChange: { action: 'onChange', diff --git a/packages/components/src/range-control/stories/index.story.tsx b/packages/components/src/range-control/stories/index.story.tsx index 7775c364195722..dcff3513733527 100644 --- a/packages/components/src/range-control/stories/index.story.tsx +++ b/packages/components/src/range-control/stories/index.story.tsx @@ -18,7 +18,8 @@ const ICONS = { starEmpty, starFilled, styles, wordpress }; const meta: Meta< typeof RangeControl > = { component: RangeControl, - title: 'Components/RangeControl', + title: 'Components/Selection & Input/Common/RangeControl', + id: 'components-rangecontrol', argTypes: { afterIcon: { control: { type: 'select' }, diff --git a/packages/components/src/search-control/stories/index.story.tsx b/packages/components/src/search-control/stories/index.story.tsx index 59618dd7e0913b..5e5f6b594e73e7 100644 --- a/packages/components/src/search-control/stories/index.story.tsx +++ b/packages/components/src/search-control/stories/index.story.tsx @@ -14,7 +14,8 @@ import { useState } from '@wordpress/element'; import SearchControl from '..'; const meta: Meta< typeof SearchControl > = { - title: 'Components/SearchControl', + title: 'Components/Selection & Input/Common/SearchControl', + id: 'components-searchcontrol', component: SearchControl, argTypes: { onChange: { action: 'onChange' }, diff --git a/packages/components/src/select-control/stories/index.story.tsx b/packages/components/src/select-control/stories/index.story.tsx index 5e57a4eaecd5ab..e9461ef6904f6f 100644 --- a/packages/components/src/select-control/stories/index.story.tsx +++ b/packages/components/src/select-control/stories/index.story.tsx @@ -15,7 +15,8 @@ import SelectControl from '../'; import { InputControlPrefixWrapper } from '../../input-control/input-prefix-wrapper'; const meta: Meta< typeof SelectControl > = { - title: 'Components/SelectControl', + title: 'Components/Selection & Input/Common/SelectControl', + id: 'components-selectcontrol', component: SelectControl, argTypes: { help: { control: { type: 'text' } }, diff --git a/packages/components/src/textarea-control/stories/index.story.tsx b/packages/components/src/textarea-control/stories/index.story.tsx index a8e5dc036248db..c303883a92c5d7 100644 --- a/packages/components/src/textarea-control/stories/index.story.tsx +++ b/packages/components/src/textarea-control/stories/index.story.tsx @@ -15,7 +15,8 @@ import TextareaControl from '..'; const meta: Meta< typeof TextareaControl > = { component: TextareaControl, - title: 'Components/TextareaControl', + title: 'Components/Selection & Input/Common/TextareaControl', + id: 'components-textareacontrol', argTypes: { onChange: { action: 'onChange' }, label: { control: { type: 'text' } }, diff --git a/packages/components/src/toggle-control/stories/index.story.tsx b/packages/components/src/toggle-control/stories/index.story.tsx index 97723aa207a394..b9db0474bc7603 100644 --- a/packages/components/src/toggle-control/stories/index.story.tsx +++ b/packages/components/src/toggle-control/stories/index.story.tsx @@ -14,7 +14,8 @@ import { useState } from '@wordpress/element'; import ToggleControl from '..'; const meta: Meta< typeof ToggleControl > = { - title: 'Components/ToggleControl', + title: 'Components/Selection & Input/Common/ToggleControl', + id: 'components-togglecontrol', component: ToggleControl, argTypes: { checked: { control: { type: null } }, diff --git a/packages/components/src/toggle-group-control/stories/index.story.tsx b/packages/components/src/toggle-group-control/stories/index.story.tsx index 92f1e6076248bd..afdfa457f66348 100644 --- a/packages/components/src/toggle-group-control/stories/index.story.tsx +++ b/packages/components/src/toggle-group-control/stories/index.story.tsx @@ -27,7 +27,8 @@ const meta: Meta< typeof ToggleGroupControl > = { component: ToggleGroupControl, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { ToggleGroupControlOption, ToggleGroupControlOptionIcon }, - title: 'Components (Experimental)/ToggleGroupControl', + title: 'Components (Experimental)/Selection & Input/ToggleGroupControl', + id: 'components-experimental-togglegroupcontrol', argTypes: { help: { control: { type: 'text' } }, onChange: { action: 'onChange' }, diff --git a/packages/components/src/tree-select/stories/index.story.tsx b/packages/components/src/tree-select/stories/index.story.tsx index 33103786bbc541..703147dc145344 100644 --- a/packages/components/src/tree-select/stories/index.story.tsx +++ b/packages/components/src/tree-select/stories/index.story.tsx @@ -14,7 +14,8 @@ import { useState } from '@wordpress/element'; import TreeSelect from '../'; const meta: Meta< typeof TreeSelect > = { - title: 'Components/TreeSelect', + title: 'Components/Selection & Input/Common/TreeSelect', + id: 'components-treeselect', component: TreeSelect, argTypes: { help: { control: { type: 'text' } }, diff --git a/packages/components/src/unit-control/stories/index.story.tsx b/packages/components/src/unit-control/stories/index.story.tsx index 5134d4902144da..de8f476e26e5c7 100644 --- a/packages/components/src/unit-control/stories/index.story.tsx +++ b/packages/components/src/unit-control/stories/index.story.tsx @@ -16,7 +16,8 @@ import { CSS_UNITS } from '../utils'; const meta: Meta< typeof UnitControl > = { component: UnitControl, - title: 'Components (Experimental)/UnitControl', + title: 'Components (Experimental)/Selection & Input/UnitControl', + id: 'components-experimental-unitcontrol', argTypes: { __unstableInputWidth: { control: { type: 'text' } }, __unstableStateReducer: { control: { type: null } }, diff --git a/storybook/preview.js b/storybook/preview.js index 435fa4dbc43264..a7c9aa0c085fc1 100644 --- a/storybook/preview.js +++ b/storybook/preview.js @@ -136,11 +136,20 @@ export const parameters = { 'Layout', 'Navigation', 'Overlays', + 'Selection & Input', + [ 'Color', 'Common', 'File Upload', 'Time & Date' ], 'Typography', 'Utilities', ], 'Components (Experimental)', - [ 'Layout', 'Navigation', 'Overlays', 'Typography' ], + [ + 'Actions', + 'Layout', + 'Navigation', + 'Overlays', + 'Selection & Input', + 'Typography', + ], 'Icons', ], }, From d0a190b65cebe27652e1a4d8d38a714d624e54ad Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 14 Nov 2024 09:59:02 +1100 Subject: [PATCH 1570/1908] Theme JSON: include block style variations in path only output of get_block_nodes (#66948) Follow up to https://github.com/WordPress/gutenberg/pull/66002 Including variations in the nodes array when 'include_node_paths_only' => true Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- backport-changelog/6.8/7784.md | 3 ++ lib/class-wp-theme-json-gutenberg.php | 14 ++++- phpunit/class-wp-theme-json-test.php | 77 +++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 backport-changelog/6.8/7784.md diff --git a/backport-changelog/6.8/7784.md b/backport-changelog/6.8/7784.md new file mode 100644 index 00000000000000..b18dca88112a71 --- /dev/null +++ b/backport-changelog/6.8/7784.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7784 + +* https://github.com/WordPress/gutenberg/pull/66948 diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index d505916450cafb..10f80c3f3cdb7b 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2749,9 +2749,21 @@ private static function get_block_nodes( $theme_json, $selectors = array(), $opt foreach ( $theme_json['styles']['blocks'] as $name => $node ) { $node_path = array( 'styles', 'blocks', $name ); if ( $include_node_paths_only ) { - $nodes[] = array( + $variation_paths = array(); + if ( $include_variations && isset( $node['variations'] ) ) { + foreach ( $node['variations'] as $variation => $variation_node ) { + $variation_paths[] = array( + 'path' => array( 'styles', 'blocks', $name, 'variations', $variation ), + ); + } + } + $node = array( 'path' => $node_path, ); + if ( ! empty( $variation_paths ) ) { + $node['variations'] = $variation_paths; + } + $nodes[] = $node; } else { $selector = null; if ( isset( $selectors[ $name ]['selector'] ) ) { diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index f77086cf0dd046..1aacb92759e591 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -5955,4 +5955,81 @@ public function test_return_block_node_paths() { $this->assertEquals( $expected, $block_nodes ); } + + /** + * This test covers `get_block_nodes` with the `$include_node_paths_only` + * and `include_block_style_variations` options. + */ + public function test_return_block_node_paths_with_variations() { + $theme_json = new ReflectionClass( 'WP_Theme_JSON_Gutenberg' ); + + $func = $theme_json->getMethod( 'get_block_nodes' ); + $func->setAccessible( true ); + + $theme_json = array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'typography' => array( + 'fontSize' => '16px', + ), + 'blocks' => array( + 'core/button' => array( + 'color' => array( + 'background' => 'red', + ), + 'variations' => array( + 'cheese' => array( + 'color' => array( + 'background' => 'cheese', + ), + ), + ), + ), + 'core/group' => array( + 'color' => array( + 'background' => 'blue', + ), + 'variations' => array( + 'apricot' => array( + 'color' => array( + 'background' => 'apricot', + ), + ), + ), + ), + ), + ), + ); + + $block_nodes = $func->invoke( + null, + $theme_json, + array(), + array( + 'include_node_paths_only' => true, + 'include_block_style_variations' => true, + ) + ); + + $expected = array( + array( + 'path' => array( 'styles', 'blocks', 'core/button' ), + 'variations' => array( + array( + 'path' => array( 'styles', 'blocks', 'core/button', 'variations', 'cheese' ), + ), + ), + ), + array( + 'path' => array( 'styles', 'blocks', 'core/group' ), + 'variations' => array( + array( + 'path' => array( 'styles', 'blocks', 'core/group', 'variations', 'apricot' ), + ), + ), + ), + ); + + $this->assertEquals( $expected, $block_nodes ); + } } From 160482d49d033619d57763c9a79cb56e7f82efb5 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:49:58 +1100 Subject: [PATCH 1571/1908] RSS block: check for description field before rendering excerpt (#66985) * Check for description before passing to html_entity_decode * Check author field Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- packages/block-library/src/rss/index.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/block-library/src/rss/index.php b/packages/block-library/src/rss/index.php index 32885863402d5e..85e4e63c9dbf7a 100644 --- a/packages/block-library/src/rss/index.php +++ b/packages/block-library/src/rss/index.php @@ -61,17 +61,20 @@ function render_block_core_rss( $attributes ) { $author = $item->get_author(); if ( is_object( $author ) ) { $author = $author->get_name(); - $author = '<span class="wp-block-rss__item-author">' . sprintf( - /* translators: byline. %s: author. */ - __( 'by %s' ), - esc_html( strip_tags( $author ) ) - ) . '</span>'; + if ( ! empty( $author ) ) { + $author = '<span class="wp-block-rss__item-author">' . sprintf( + /* translators: byline. %s: author. */ + __( 'by %s' ), + esc_html( strip_tags( $author ) ) + ) . '</span>'; + } } } - $excerpt = ''; - if ( $attributes['displayExcerpt'] ) { - $excerpt = html_entity_decode( $item->get_description(), ENT_QUOTES, get_option( 'blog_charset' ) ); + $excerpt = ''; + $description = $item->get_description(); + if ( $attributes['displayExcerpt'] && ! empty( $description ) ) { + $excerpt = html_entity_decode( $description, ENT_QUOTES, get_option( 'blog_charset' ) ); $excerpt = esc_attr( wp_trim_words( $excerpt, $attributes['excerptLength'], ' […]' ) ); // Change existing [...] to […]. From a8a8747b36878faae76f9ffd71ddd53c0c12f321 Mon Sep 17 00:00:00 2001 From: Utsav Patel <75293077+up1512001@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:27:56 +0530 Subject: [PATCH 1572/1908] Navigation: Fix 'ariaLabel' block support (#66943) Co-authored-by: up1512001 <up1512001@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/block-library/src/navigation/index.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index 9484ad13ed002a..dd300eb12c6feb 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -344,6 +344,10 @@ private static function get_navigation_name( $attributes ) { $navigation_name = $attributes['ariaLabel'] ?? ''; + if ( ! empty( $navigation_name ) ) { + return $navigation_name; + } + // Load the navigation post. if ( array_key_exists( 'ref', $attributes ) ) { $navigation_post = get_post( $attributes['ref'] ); From 94b8ac4929e7af8f4a4e4b108873d8ac24a688df Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 14 Nov 2024 13:20:28 +0400 Subject: [PATCH 1573/1908] Preferences: Use hooks instead of HoC in 'EnablePanelOption' (#66994) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../preferences-modal/enable-panel.js | 44 ++++++++++++------- .../preferences-modal/enable-panel.js | 44 ++++++++++++------- 2 files changed, 54 insertions(+), 34 deletions(-) diff --git a/packages/edit-post/src/components/preferences-modal/enable-panel.js b/packages/edit-post/src/components/preferences-modal/enable-panel.js index d698cdc360cae2..9053b74a695d6d 100644 --- a/packages/edit-post/src/components/preferences-modal/enable-panel.js +++ b/packages/edit-post/src/components/preferences-modal/enable-panel.js @@ -1,8 +1,7 @@ /** * WordPress dependencies */ -import { compose, ifCondition } from '@wordpress/compose'; -import { withSelect, withDispatch } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import { store as editorStore } from '@wordpress/editor'; import { privateApis as preferencesPrivateApis } from '@wordpress/preferences'; @@ -13,18 +12,29 @@ import { unlock } from '../../lock-unlock'; const { PreferenceBaseOption } = unlock( preferencesPrivateApis ); -export default compose( - withSelect( ( select, { panelName } ) => { - const { isEditorPanelEnabled, isEditorPanelRemoved } = - select( editorStore ); - return { - isRemoved: isEditorPanelRemoved( panelName ), - isChecked: isEditorPanelEnabled( panelName ), - }; - } ), - ifCondition( ( { isRemoved } ) => ! isRemoved ), - withDispatch( ( dispatch, { panelName } ) => ( { - onChange: () => - dispatch( editorStore ).toggleEditorPanelEnabled( panelName ), - } ) ) -)( PreferenceBaseOption ); +export default function EnablePanelOption( props ) { + const { toggleEditorPanelEnabled } = useDispatch( editorStore ); + const { isChecked, isRemoved } = useSelect( + ( select ) => { + const { isEditorPanelEnabled, isEditorPanelRemoved } = + select( editorStore ); + return { + isChecked: isEditorPanelEnabled( props.panelName ), + isRemoved: isEditorPanelRemoved( props.panelName ), + }; + }, + [ props.panelName ] + ); + + if ( isRemoved ) { + return null; + } + + return ( + <PreferenceBaseOption + isChecked={ isChecked } + onChange={ () => toggleEditorPanelEnabled( props.panelName ) } + { ...props } + /> + ); +} diff --git a/packages/editor/src/components/preferences-modal/enable-panel.js b/packages/editor/src/components/preferences-modal/enable-panel.js index 66c91409434415..2e1839d8fe2547 100644 --- a/packages/editor/src/components/preferences-modal/enable-panel.js +++ b/packages/editor/src/components/preferences-modal/enable-panel.js @@ -1,8 +1,7 @@ /** * WordPress dependencies */ -import { compose, ifCondition } from '@wordpress/compose'; -import { withSelect, withDispatch } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import { privateApis as preferencesPrivateApis } from '@wordpress/preferences'; /** @@ -13,18 +12,29 @@ import { store as editorStore } from '../../store'; const { PreferenceBaseOption } = unlock( preferencesPrivateApis ); -export default compose( - withSelect( ( select, { panelName } ) => { - const { isEditorPanelEnabled, isEditorPanelRemoved } = - select( editorStore ); - return { - isRemoved: isEditorPanelRemoved( panelName ), - isChecked: isEditorPanelEnabled( panelName ), - }; - } ), - ifCondition( ( { isRemoved } ) => ! isRemoved ), - withDispatch( ( dispatch, { panelName } ) => ( { - onChange: () => - dispatch( editorStore ).toggleEditorPanelEnabled( panelName ), - } ) ) -)( PreferenceBaseOption ); +export default function EnablePanelOption( props ) { + const { toggleEditorPanelEnabled } = useDispatch( editorStore ); + const { isChecked, isRemoved } = useSelect( + ( select ) => { + const { isEditorPanelEnabled, isEditorPanelRemoved } = + select( editorStore ); + return { + isChecked: isEditorPanelEnabled( props.panelName ), + isRemoved: isEditorPanelRemoved( props.panelName ), + }; + }, + [ props.panelName ] + ); + + if ( isRemoved ) { + return null; + } + + return ( + <PreferenceBaseOption + isChecked={ isChecked } + onChange={ () => toggleEditorPanelEnabled( props.panelName ) } + { ...props } + /> + ); +} From 7d21c9badf9318a6097d09669ecc86f63dfeac61 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 14 Nov 2024 11:11:25 +0100 Subject: [PATCH 1574/1908] Site Editor: Deprecate edited entity state (#66965) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../data/data-core-edit-site.md | 14 ++++ packages/e2e-test-utils/src/site-editor.js | 8 +- .../edit-site/src/components/app/index.js | 3 - .../block-editor/use-site-editor-settings.js | 29 +++---- .../edit-site/src/components/editor/index.js | 59 ++++++------- .../use-resolve-edited-entity.js} | 27 +++--- .../src/components/posts-app/index.js | 3 - packages/edit-site/src/store/actions.js | 15 ++++ packages/edit-site/src/store/selectors.js | 25 +++++- packages/edit-site/src/store/test/actions.js | 83 ------------------- packages/edit-site/src/store/test/reducer.js | 69 --------------- .../edit-site/src/store/test/selectors.js | 41 --------- .../specs/site-editor/template-revert.spec.js | 8 +- 13 files changed, 108 insertions(+), 276 deletions(-) rename packages/edit-site/src/components/{sync-state-with-url/use-init-edited-entity-from-url.js => editor/use-resolve-edited-entity.js} (93%) delete mode 100644 packages/edit-site/src/store/test/actions.js delete mode 100644 packages/edit-site/src/store/test/reducer.js delete mode 100644 packages/edit-site/src/store/test/selectors.js diff --git a/docs/reference-guides/data/data-core-edit-site.md b/docs/reference-guides/data/data-core-edit-site.md index 775dd66a821ef0..a16c53861daada 100644 --- a/docs/reference-guides/data/data-core-edit-site.md +++ b/docs/reference-guides/data/data-core-edit-site.md @@ -52,6 +52,8 @@ _Returns_ ### getEditedPostId +> **Deprecated** + Returns the ID of the currently edited template or template part. _Parameters_ @@ -64,6 +66,8 @@ _Returns_ ### getEditedPostType +> **Deprecated** + Returns the current edited post type (wp_template or wp_template_part). _Parameters_ @@ -189,6 +193,8 @@ _Returns_ ### isPage +> **Deprecated** + Whether or not the editor has a page loaded into it. _Related_ @@ -273,6 +279,8 @@ _Parameters_ ### setEditedEntity +> **Deprecated** + Action that sets an edited entity. _Parameters_ @@ -287,6 +295,8 @@ _Returns_ ### setEditedPostContext +> **Deprecated** + Set's the current block editor context. _Parameters_ @@ -345,6 +355,8 @@ _Parameters_ ### setNavigationMenu +> **Deprecated** + Action that sets a navigation menu. _Parameters_ @@ -385,6 +397,8 @@ _Returns_ ### setTemplatePart +> **Deprecated** + Action that sets a template part. _Parameters_ diff --git a/packages/e2e-test-utils/src/site-editor.js b/packages/e2e-test-utils/src/site-editor.js index 98ba34f7db4f51..d3717982ba3a54 100644 --- a/packages/e2e-test-utils/src/site-editor.js +++ b/packages/e2e-test-utils/src/site-editor.js @@ -44,11 +44,11 @@ export async function disableSiteEditorWelcomeGuide() { export function getCurrentSiteEditorContent() { return page.evaluate( () => { const postId = window.wp.data - .select( 'core/edit-site' ) - .getEditedPostId(); + .select( 'core/editor' ) + .getCurrentPostId(); const postType = window.wp.data - .select( 'core/edit-site' ) - .getEditedPostType(); + .select( 'core/editor' ) + .getCurrentPostType(); const record = window.wp.data .select( 'core' ) .getEditedEntityRecord( 'postType', postType, postId ); diff --git a/packages/edit-site/src/components/app/index.js b/packages/edit-site/src/components/app/index.js index 0551e6b295fbc0..3588565fcb3c17 100644 --- a/packages/edit-site/src/components/app/index.js +++ b/packages/edit-site/src/components/app/index.js @@ -18,7 +18,6 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; import Layout from '../layout'; import { unlock } from '../../lock-unlock'; import { useCommonCommands } from '../../hooks/commands/use-common-commands'; -import useInitEditedEntityFromURL from '../sync-state-with-url/use-init-edited-entity-from-url'; import useActiveRoute from '../layout/router'; import useSetCommandContext from '../../hooks/commands/use-set-command-context'; import { useRegisterSiteEditorRoutes } from '../site-editor-routes'; @@ -27,8 +26,6 @@ const { RouterProvider } = unlock( routerPrivateApis ); const { GlobalStylesProvider } = unlock( editorPrivateApis ); function AppLayout() { - // This ensures the edited entity id and type are initialized properly. - useInitEditedEntityFromURL(); useCommonCommands(); useSetCommandContext(); useRegisterSiteEditorRoutes(); diff --git a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js index 37fa0a2eaf30c2..5c75de6d81e720 100644 --- a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js +++ b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js @@ -36,26 +36,21 @@ function useNavigateToPreviousEntityRecord() { return goBack; } -export function useSpecificEditorSettings() { +export function useSpecificEditorSettings( + shouldUseTemplateAsDefaultRenderingMode +) { const { params } = useLocation(); const { canvas = 'view' } = params; const onNavigateToEntityRecord = useNavigateToEntityRecord(); - const { settings, shouldUseTemplateAsDefaultRenderingMode } = useSelect( - ( select ) => { - const { getEditedPostContext, getSettings } = unlock( - select( editSiteStore ) - ); - const _context = getEditedPostContext(); - return { - settings: getSettings(), - // TODO: The `postType` check should be removed when the default rendering mode per post type is merged. - // @see https://github.com/WordPress/gutenberg/pull/62304/ - shouldUseTemplateAsDefaultRenderingMode: - _context?.postId && _context?.postType !== 'post', - }; - }, - [] - ); + const { settings } = useSelect( ( select ) => { + const { getSettings } = select( editSiteStore ); + return { + settings: getSettings(), + }; + }, [] ); + + // TODO: The `shouldUseTemplateAsDefaultRenderingMode` check should be removed when the default rendering mode per post type is merged. + // @see https://github.com/WordPress/gutenberg/pull/62304/ const defaultRenderingMode = shouldUseTemplateAsDefaultRenderingMode ? 'template-locked' : 'post-only'; diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 7eff0da660d274..51d734f25c6adb 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -50,6 +50,10 @@ import useEditorTitle from './use-editor-title'; import { useIsSiteEditorLoading } from '../layout/hooks'; import { useAdaptEditorToCanvas } from './use-adapt-editor-to-canvas'; import { TEMPLATE_POST_TYPE } from '../../utils/constants'; +import { + useResolveEditedEntity, + useSyncDeprecatedEntityIntoState, +} from './use-resolve-edited-entity'; const { Editor, BackButton } = unlock( editorPrivateApis ); const { useHistory, useLocation } = unlock( routerPrivateApis ); @@ -85,38 +89,25 @@ export default function EditSiteEditor( { isPostsList = false } ) { const { canvas = 'view' } = params; const isLoading = useIsSiteEditorLoading(); useAdaptEditorToCanvas( canvas ); + const entity = useResolveEditedEntity(); + // deprecated sync state with url + useSyncDeprecatedEntityIntoState( entity ); + const { postType, postId, context } = entity; const { - editedPostType, - editedPostId, - contextPostType, - contextPostId, - isEditingPage, supportsGlobalStyles, showIconLabels, editorCanvasView, currentPostIsTrashed, hasSiteIcon, } = useSelect( ( select ) => { - const { - getEditorCanvasContainerView, - getEditedPostContext, - isPage, - getEditedPostType, - getEditedPostId, - } = unlock( select( editSiteStore ) ); + const { getEditorCanvasContainerView } = unlock( + select( editSiteStore ) + ); const { get } = select( preferencesStore ); const { getCurrentTheme, getEntityRecord } = select( coreDataStore ); - const _context = getEditedPostContext(); const siteData = getEntityRecord( 'root', '__unstableBase', undefined ); - // The currently selected entity to display. - // Typically template or template part in the site editor. return { - editedPostType: getEditedPostType(), - editedPostId: getEditedPostId(), - contextPostType: _context?.postId ? _context.postType : undefined, - contextPostId: _context?.postId ? _context.postId : undefined, - isEditingPage: isPage(), supportsGlobalStyles: getCurrentTheme()?.is_block_theme, showIconLabels: get( 'core', 'showIconLabels' ), editorCanvasView: getEditorCanvasContainerView(), @@ -126,10 +117,10 @@ export default function EditSiteEditor( { isPostsList = false } ) { hasSiteIcon: !! siteData?.site_icon_url, }; }, [] ); - const postWithTemplate = !! contextPostId; + const postWithTemplate = !! context?.postId; useEditorTitle( - postWithTemplate ? contextPostType : editedPostType, - postWithTemplate ? contextPostId : editedPostId + postWithTemplate ? context.postType : postType, + postWithTemplate ? context.postId : postId ); const _isPreviewingTheme = isPreviewingTheme(); const hasDefaultEditorCanvasView = ! useHasEditorCanvasContainer(); @@ -140,7 +131,9 @@ export default function EditSiteEditor( { isPostsList = false } ) { 'edit-site-editor__loading-progress' ); - const settings = useSpecificEditorSettings(); + const settings = useSpecificEditorSettings( + !! context?.postId && context?.postType !== 'post' + ); const styles = useMemo( () => [ ...settings.styles, @@ -219,25 +212,21 @@ export default function EditSiteEditor( { isPostsList = false } ) { return ( <> <GlobalStylesRenderer - disableRootPadding={ editedPostType !== TEMPLATE_POST_TYPE } + disableRootPadding={ postType !== TEMPLATE_POST_TYPE } /> <EditorKeyboardShortcutsRegister /> { isEditMode && <BlockKeyboardShortcuts /> } { ! isReady ? <CanvasLoader id={ loadingProgressId } /> : null } { isEditMode && ( <WelcomeGuide - postType={ - postWithTemplate ? contextPostType : editedPostType - } + postType={ postWithTemplate ? context.postType : postType } /> ) } { isReady && ( <Editor - postType={ - postWithTemplate ? contextPostType : editedPostType - } - postId={ postWithTemplate ? contextPostId : editedPostId } - templateId={ postWithTemplate ? editedPostId : undefined } + postType={ postWithTemplate ? context.postType : postType } + postId={ postWithTemplate ? context.postId : postId } + templateId={ postWithTemplate ? postId : undefined } settings={ settings } className={ clsx( 'edit-site-editor__editor-interface', { 'show-icon-labels': showIconLabels, @@ -252,7 +241,9 @@ export default function EditSiteEditor( { isPostsList = false } ) { iframeProps={ iframeProps } onActionPerformed={ onActionPerformed } extraSidebarPanels={ - ! isEditingPage && <PluginTemplateSettingPanel.Slot /> + ! postWithTemplate && ( + <PluginTemplateSettingPanel.Slot /> + ) } > { isEditMode && ( diff --git a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js b/packages/edit-site/src/components/editor/use-resolve-edited-entity.js similarity index 93% rename from packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js rename to packages/edit-site/src/components/editor/use-resolve-edited-entity.js index 2dbd143766e67c..eb19b3cea95375 100644 --- a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js +++ b/packages/edit-site/src/components/editor/use-resolve-edited-entity.js @@ -5,7 +5,6 @@ import { useEffect, useMemo } from '@wordpress/element'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as coreDataStore } from '@wordpress/core-data'; import { privateApis as routerPrivateApis } from '@wordpress/router'; -import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Internal dependencies @@ -30,7 +29,9 @@ const postTypesWithoutParentTemplate = [ const authorizedPostTypes = [ 'page', 'post' ]; -function useResolveEditedEntityAndContext( { postId, postType } ) { +export function useResolveEditedEntity() { + const { params = {} } = useLocation(); + const { postId, postType } = params; const { hasLoadedAllDependencies, homepageId, postsPageId } = useSelect( ( select ) => { const { getEntityRecord } = select( coreDataStore ); @@ -233,25 +234,17 @@ function useResolveEditedEntityAndContext( { postId, postType } ) { return { isReady: false }; } -export default function useInitEditedEntityFromURL() { - const { params = {} } = useLocation(); - const { postType, postId, context, isReady } = - useResolveEditedEntityAndContext( params ); - +export function useSyncDeprecatedEntityIntoState( { + postType, + postId, + context, + isReady, +} ) { const { setEditedEntity } = useDispatch( editSiteStore ); - const { resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); useEffect( () => { if ( isReady ) { - resetZoomLevel(); setEditedEntity( postType, postId, context ); } - }, [ - isReady, - postType, - postId, - context, - setEditedEntity, - resetZoomLevel, - ] ); + }, [ isReady, postType, postId, context, setEditedEntity ] ); } diff --git a/packages/edit-site/src/components/posts-app/index.js b/packages/edit-site/src/components/posts-app/index.js index 8b5377bb2e65bd..80d2c1c7eba86f 100644 --- a/packages/edit-site/src/components/posts-app/index.js +++ b/packages/edit-site/src/components/posts-app/index.js @@ -10,7 +10,6 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies */ -import useInitEditedEntityFromURL from '../sync-state-with-url/use-init-edited-entity-from-url'; import Layout from '../layout'; import useActiveRoute from './router'; import { unlock } from '../../lock-unlock'; @@ -19,8 +18,6 @@ const { RouterProvider } = unlock( routerPrivateApis ); const { GlobalStylesProvider } = unlock( editorPrivateApis ); function PostsLayout() { - // This ensures the edited entity id and type are initialized properly. - useInitEditedEntityFromURL(); const route = useActiveRoute(); return <Layout route={ route } />; } diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index 127dd9993b68f0..269f58c57d00ab 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -142,11 +142,16 @@ export const removeTemplate = /** * Action that sets a template part. * + * @deprecated * @param {string} templatePartId The template part ID. * * @return {Object} Action object. */ export function setTemplatePart( templatePartId ) { + deprecated( "dispatch( 'core/edit-site' ).setTemplatePart", { + since: '6.8', + } ); + return { type: 'SET_EDITED_POST', postType: TEMPLATE_PART_POST_TYPE, @@ -157,11 +162,16 @@ export function setTemplatePart( templatePartId ) { /** * Action that sets a navigation menu. * + * @deprecated * @param {string} navigationMenuId The Navigation Menu Post ID. * * @return {Object} Action object. */ export function setNavigationMenu( navigationMenuId ) { + deprecated( "dispatch( 'core/edit-site' ).setNavigationMenu", { + since: '6.8', + } ); + return { type: 'SET_EDITED_POST', postType: NAVIGATION_POST_TYPE, @@ -172,6 +182,7 @@ export function setNavigationMenu( navigationMenuId ) { /** * Action that sets an edited entity. * + * @deprecated * @param {string} postType The entity's post type. * @param {string} postId The entity's ID. * @param {Object} context The entity's context. @@ -204,11 +215,15 @@ export function setHomeTemplateId() { /** * Set's the current block editor context. * + * @deprecated * @param {Object} context The context object. * * @return {Object} Action object. */ export function setEditedPostContext( context ) { + deprecated( "dispatch( 'core/edit-site' ).setEditedPostContext", { + since: '6.8', + } ); return { type: 'SET_EDITED_POST_CONTEXT', context, diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js index ddef4a71d0a915..cd50200e42cad4 100644 --- a/packages/edit-site/src/store/selectors.js +++ b/packages/edit-site/src/store/selectors.js @@ -135,22 +135,32 @@ export function getHomeTemplateId() { /** * Returns the current edited post type (wp_template or wp_template_part). * + * @deprecated * @param {Object} state Global application state. * * @return {?TemplateType} Template type. */ export function getEditedPostType( state ) { + deprecated( "select( 'core/edit-site' ).getEditedPostType", { + since: '6.8', + alternative: "select( 'core/editor' ).getCurrentPostType", + } ); return state.editedPost.postType; } /** * Returns the ID of the currently edited template or template part. * + * @deprecated * @param {Object} state Global application state. * * @return {?string} Post ID. */ export function getEditedPostId( state ) { + deprecated( "select( 'core/edit-site' ).getEditedPostId", { + since: '6.8', + alternative: "select( 'core/editor' ).getCurrentPostId", + } ); return state.editedPost.id; } @@ -163,6 +173,10 @@ export function getEditedPostId( state ) { * @return {Object} Page. */ export function getEditedPostContext( state ) { + deprecated( "select( 'core/edit-site' ).getEditedPostContext", { + since: '6.8', + } ); + return state.editedPost.context; } @@ -175,6 +189,10 @@ export function getEditedPostContext( state ) { * @return {Object} Page. */ export function getPage( state ) { + deprecated( "select( 'core/edit-site' ).getPage", { + since: '6.8', + } ); + return { context: state.editedPost.context }; } @@ -333,12 +351,17 @@ export function isNavigationOpened() { * Whether or not the editor has a page loaded into it. * * @see setPage - * + * @deprecated * @param {Object} state Global application state. * * @return {boolean} Whether or not the editor has a page loaded into it. */ export function isPage( state ) { + deprecated( "select( 'core/edit-site' ).isPage", { + since: '6.8', + alternative: "select( 'core/editor' ).getCurrentPostType", + } ); + return !! state.editedPost.context?.postId; } diff --git a/packages/edit-site/src/store/test/actions.js b/packages/edit-site/src/store/test/actions.js deleted file mode 100644 index 3fbe5d19aa94e3..00000000000000 --- a/packages/edit-site/src/store/test/actions.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * WordPress dependencies - */ -import { store as blockEditorStore } from '@wordpress/block-editor'; -import { store as coreStore } from '@wordpress/core-data'; -import { createRegistry } from '@wordpress/data'; -import { store as noticesStore } from '@wordpress/notices'; -import { store as preferencesStore } from '@wordpress/preferences'; -import { - store as editorStore, - privateApis as editorPrivateApis, -} from '@wordpress/editor'; - -/** - * Internal dependencies - */ -import { store as editSiteStore } from '..'; -import { unlock } from '../../lock-unlock'; - -const { interfaceStore } = unlock( editorPrivateApis ); - -function createRegistryWithStores() { - // create a registry - const registry = createRegistry(); - - // register stores - registry.register( editorStore ); - registry.register( blockEditorStore ); - registry.register( coreStore ); - registry.register( editSiteStore ); - registry.register( interfaceStore ); - registry.register( noticesStore ); - registry.register( preferencesStore ); - - return registry; -} - -describe( 'actions', () => { - describe( 'toggleFeature', () => { - it( 'should toggle a feature flag', () => { - const registry = createRegistryWithStores(); - - // Should start as undefined. - expect( - registry - .select( preferencesStore ) - .get( 'core/edit-site', 'name' ) - ).toBe( undefined ); - - // Toggle on. - registry.dispatch( editSiteStore ).toggleFeature( 'name' ); - expect( - registry - .select( preferencesStore ) - .get( 'core/edit-site', 'name' ) - ).toBe( true ); - - // Toggle off again. - registry.dispatch( editSiteStore ).toggleFeature( 'name' ); - expect( - registry - .select( preferencesStore ) - .get( 'core/edit-site', 'name' ) - ).toBe( false ); - - // Expect a deprecation warning. - expect( console ).toHaveWarned(); - } ); - } ); - - describe( 'setTemplatePart', () => { - it( 'should set template part', () => { - const registry = createRegistryWithStores(); - - const ID = 1; - registry.dispatch( editSiteStore ).setTemplatePart( ID ); - - const select = registry.select( editSiteStore ); - expect( select.getEditedPostId() ).toBe( ID ); - expect( select.getEditedPostType() ).toBe( 'wp_template_part' ); - } ); - } ); -} ); diff --git a/packages/edit-site/src/store/test/reducer.js b/packages/edit-site/src/store/test/reducer.js deleted file mode 100644 index 9e7929e737fb39..00000000000000 --- a/packages/edit-site/src/store/test/reducer.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * External dependencies - */ -import deepFreeze from 'deep-freeze'; - -/** - * Internal dependencies - */ -import { settings, editedPost } from '../reducer'; - -describe( 'state', () => { - describe( 'settings()', () => { - it( 'should apply default state', () => { - expect( settings( undefined, {} ) ).toEqual( {} ); - } ); - - it( 'should default to returning the same state', () => { - const state = {}; - expect( settings( state, {} ) ).toBe( state ); - } ); - - it( 'should update settings with a shallow merge', () => { - expect( - settings( - deepFreeze( { - setting: { key: 'value' }, - otherSetting: 'value', - } ), - { - type: 'UPDATE_SETTINGS', - settings: { setting: { newKey: 'newValue' } }, - } - ) - ).toEqual( { - setting: { newKey: 'newValue' }, - otherSetting: 'value', - } ); - } ); - } ); - - describe( 'editedPost()', () => { - it( 'should apply default state', () => { - expect( editedPost( undefined, {} ) ).toEqual( {} ); - } ); - - it( 'should default to returning the same state', () => { - const state = []; - expect( editedPost( state, {} ) ).toBe( state ); - } ); - - it( 'should update when a template is set', () => { - expect( - editedPost( - { id: 1, type: 'wp_template' }, - { - type: 'SET_EDITED_POST', - postType: 'wp_template', - id: 2, - context: { templateSlug: 'slug' }, - } - ) - ).toEqual( { - postType: 'wp_template', - id: 2, - context: { templateSlug: 'slug' }, - } ); - } ); - } ); -} ); diff --git a/packages/edit-site/src/store/test/selectors.js b/packages/edit-site/src/store/test/selectors.js deleted file mode 100644 index c0bb074f8f036b..00000000000000 --- a/packages/edit-site/src/store/test/selectors.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Internal dependencies - */ -import { getEditedPostType, getEditedPostId, isPage } from '../selectors'; - -describe( 'selectors', () => { - describe( 'getEditedPostId', () => { - it( 'returns the template ID', () => { - const state = { editedPost: { id: 10 } }; - expect( getEditedPostId( state ) ).toBe( 10 ); - } ); - } ); - - describe( 'getEditedPostType', () => { - it( 'returns the template type', () => { - const state = { editedPost: { postType: 'wp_template' } }; - expect( getEditedPostType( state ) ).toBe( 'wp_template' ); - } ); - } ); - - describe( 'isPage', () => { - it( 'returns true if the edited post type is a page', () => { - const state = { - editedPost: { - postType: 'wp_template', - context: { postType: 'page', postId: 123 }, - }, - }; - expect( isPage( state ) ).toBe( true ); - } ); - - it( 'returns false if the edited post type is a template', () => { - const state = { - editedPost: { - postType: 'wp_template', - }, - }; - expect( isPage( state ) ).toBe( false ); - } ); - } ); -} ); diff --git a/test/e2e/specs/site-editor/template-revert.spec.js b/test/e2e/specs/site-editor/template-revert.spec.js index 1f8d9ea73d7fd9..50a5598f400ebd 100644 --- a/test/e2e/specs/site-editor/template-revert.spec.js +++ b/test/e2e/specs/site-editor/template-revert.spec.js @@ -232,11 +232,11 @@ class TemplateRevertUtils { async getCurrentSiteEditorContent() { return this.page.evaluate( () => { const postId = window.wp.data - .select( 'core/edit-site' ) - .getEditedPostId(); + .select( 'core/editor' ) + .getCurrentPostId(); const postType = window.wp.data - .select( 'core/edit-site' ) - .getEditedPostType(); + .select( 'core/editor' ) + .getCurrentPostType(); const record = window.wp.data .select( 'core' ) .getEditedEntityRecord( 'postType', postType, postId ); From cd5ead194be66964f1af708b2bf461b4abb99860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:53:02 +0100 Subject: [PATCH 1575/1908] Post fields: move `author` from `edit-site` to `fields` package (#66939) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- package-lock.json | 2 + .../src/components/post-fields/index.js | 65 ++----------------- packages/fields/README.md | 4 ++ packages/fields/package.json | 1 + .../fields/src/fields/author/author-view.tsx | 63 ++++++++++++++++++ packages/fields/src/fields/author/index.tsx | 32 +++++++++ packages/fields/src/fields/index.ts | 1 + packages/fields/src/types.ts | 14 ++++ 8 files changed, 121 insertions(+), 61 deletions(-) create mode 100644 packages/fields/src/fields/author/author-view.tsx create mode 100644 packages/fields/src/fields/author/index.tsx diff --git a/package-lock.json b/package-lock.json index 0e5b7f21044c43..0bcf8aee842fd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21155,6 +21155,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -54698,6 +54699,7 @@ "@wordpress/warning": "*", "change-case": "4.1.2", "client-zip": "^2.4.5", + "clsx": "2.1.1", "remove-accents": "^0.5.0" }, "engines": { diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index e151c5a048c011..6ba9453709f0d3 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -1,12 +1,6 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; import { featuredImageField, slugField, @@ -16,50 +10,10 @@ import { commentStatusField, titleField, dateField, + authorField, } from '@wordpress/fields'; -import { useMemo, useState } from '@wordpress/element'; -import { commentAuthorAvatar as authorIcon } from '@wordpress/icons'; -import { __experimentalHStack as HStack, Icon } from '@wordpress/components'; -import { useSelect } from '@wordpress/data'; -import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; - -function PostAuthorField( { item } ) { - const { text, imageUrl } = useSelect( - ( select ) => { - const { getUser } = select( coreStore ); - const user = getUser( item.author ); - return { - imageUrl: user?.avatar_urls?.[ 48 ], - text: user?.name, - }; - }, - [ item ] - ); - const [ isImageLoaded, setIsImageLoaded ] = useState( false ); - return ( - <HStack alignment="left" spacing={ 0 }> - { !! imageUrl && ( - <div - className={ clsx( 'page-templates-author-field__avatar', { - 'is-loaded': isImageLoaded, - } ) } - > - <img - onLoad={ () => setIsImageLoaded( true ) } - alt={ __( 'Author avatar' ) } - src={ imageUrl } - /> - </div> - ) } - { ! imageUrl && ( - <div className="page-templates-author-field__icon"> - <Icon icon={ authorIcon } /> - </div> - ) } - <span className="page-templates-author-field__name">{ text }</span> - </HStack> - ); -} +import { useMemo } from '@wordpress/element'; +import { useEntityRecords } from '@wordpress/core-data'; function usePostFields() { const { records: authors, isResolving: isLoadingAuthors } = @@ -70,23 +24,12 @@ function usePostFields() { featuredImageField, titleField, { - label: __( 'Author' ), - id: 'author', - type: 'integer', + ...authorField, elements: authors?.map( ( { id, name } ) => ( { value: id, label: name, } ) ) || [], - render: PostAuthorField, - sort: ( a, b, direction ) => { - const nameA = a._embedded?.author?.[ 0 ]?.name || ''; - const nameB = b._embedded?.author?.[ 0 ]?.name || ''; - - return direction === 'asc' - ? nameA.localeCompare( nameB ) - : nameB.localeCompare( nameA ); - }, }, statusField, dateField, diff --git a/packages/fields/README.md b/packages/fields/README.md index bfcc63be4da472..e6cf6d3007ed97 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -14,6 +14,10 @@ npm install @wordpress/fields --save <!-- START TOKEN(Autogenerated API docs) --> +### authorField + +Author field for BasePost. + ### commentStatusField Comment status field for BasePost. diff --git a/packages/fields/package.json b/packages/fields/package.json index f32c779c2e989e..cee1060223767a 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -57,6 +57,7 @@ "@wordpress/warning": "*", "change-case": "4.1.2", "client-zip": "^2.4.5", + "clsx": "2.1.1", "remove-accents": "^0.5.0" }, "peerDependencies": { diff --git a/packages/fields/src/fields/author/author-view.tsx b/packages/fields/src/fields/author/author-view.tsx new file mode 100644 index 00000000000000..8232350af5193e --- /dev/null +++ b/packages/fields/src/fields/author/author-view.tsx @@ -0,0 +1,63 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { useState } from '@wordpress/element'; +import { commentAuthorAvatar as authorIcon } from '@wordpress/icons'; +import { __experimentalHStack as HStack, Icon } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import type { User } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ +import type { BasePostWithEmbeddedAuthor } from '../../types'; + +function AuthorView( { item }: { item: BasePostWithEmbeddedAuthor } ) { + const { text, imageUrl } = useSelect( + ( select ) => { + const { getEntityRecord } = select( coreStore ); + let user: User | undefined; + if ( !! item.author ) { + user = getEntityRecord( 'root', 'user', item.author ); + } + return { + imageUrl: user?.avatar_urls?.[ 48 ], + text: user?.name, + }; + }, + [ item ] + ); + const [ isImageLoaded, setIsImageLoaded ] = useState( false ); + return ( + <HStack alignment="left" spacing={ 0 }> + { !! imageUrl && ( + <div + className={ clsx( 'page-templates-author-field__avatar', { + 'is-loaded': isImageLoaded, + } ) } + > + <img + onLoad={ () => setIsImageLoaded( true ) } + alt={ __( 'Author avatar' ) } + src={ imageUrl } + /> + </div> + ) } + { ! imageUrl && ( + <div className="page-templates-author-field__icon"> + <Icon icon={ authorIcon } /> + </div> + ) } + <span className="page-templates-author-field__name">{ text }</span> + </HStack> + ); +} + +export default AuthorView; diff --git a/packages/fields/src/fields/author/index.tsx b/packages/fields/src/fields/author/index.tsx new file mode 100644 index 00000000000000..22f9409e051556 --- /dev/null +++ b/packages/fields/src/fields/author/index.tsx @@ -0,0 +1,32 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { BasePostWithEmbeddedAuthor } from '../../types'; +import AuthorView from './author-view'; + +const authorField: Field< BasePostWithEmbeddedAuthor > = { + label: __( 'Author' ), + id: 'author', + type: 'integer', + elements: [], + render: AuthorView, + sort: ( a, b, direction ) => { + const nameA = a._embedded?.author?.[ 0 ]?.name || ''; + const nameB = b._embedded?.author?.[ 0 ]?.name || ''; + + return direction === 'asc' + ? nameA.localeCompare( nameB ) + : nameB.localeCompare( nameA ); + }, +}; + +/** + * Author field for BasePost. + */ +export default authorField; diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts index 36e064006232bb..5ea4235af1d964 100644 --- a/packages/fields/src/fields/index.ts +++ b/packages/fields/src/fields/index.ts @@ -7,3 +7,4 @@ export { default as passwordField } from './password'; export { default as statusField } from './status'; export { default as commentStatusField } from './comment-status'; export { default as dateField } from './date'; +export { default as authorField } from './author'; diff --git a/packages/fields/src/types.ts b/packages/fields/src/types.ts index 71831b6aab180c..e457ec699554cd 100644 --- a/packages/fields/src/types.ts +++ b/packages/fields/src/types.ts @@ -23,6 +23,15 @@ interface Links { [ key: string ]: { href: string }[] | undefined; } +interface Author { + name: string; + avatar_urls: Record< string, string >; +} + +interface EmbeddedAuthor { + author: Author[]; +} + export interface BasePost extends CommonPost { comment_status?: 'open' | 'closed'; excerpt?: string | { raw: string; rendered: string }; @@ -39,6 +48,11 @@ export interface BasePost extends CommonPost { permalink_template?: string; date?: string; modified?: string; + author?: number; +} + +export interface BasePostWithEmbeddedAuthor extends BasePost { + _embedded: EmbeddedAuthor; } export interface Template extends CommonPost { From 2e5ba3b94ac5cf17be5b947b449a42a71334295a Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 14 Nov 2024 13:14:37 +0100 Subject: [PATCH 1576/1908] Site Editor > Styles: open styles inspector when clicking preview canvas (#66996) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../components/global-styles-sidebar/index.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/global-styles-sidebar/index.js b/packages/edit-site/src/components/global-styles-sidebar/index.js index c0ad313d5d477c..b1cf4fec92c86e 100644 --- a/packages/edit-site/src/components/global-styles-sidebar/index.js +++ b/packages/edit-site/src/components/global-styles-sidebar/index.js @@ -5,7 +5,7 @@ import { FlexItem, Flex, Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { styles, seen, backup } from '@wordpress/icons'; import { useSelect, useDispatch } from '@wordpress/data'; -import { useEffect } from '@wordpress/element'; +import { useEffect, useRef } from '@wordpress/element'; import { store as preferencesStore } from '@wordpress/preferences'; import { store as editorStore, @@ -29,7 +29,7 @@ const { useLocation } = unlock( routerPrivateApis ); export default function GlobalStylesSidebar() { const { params } = useLocation(); - const { canvas = 'view' } = params; + const { canvas = 'view', path } = params; const { shouldClearCanvasContainerView, isStyleBookOpened, @@ -128,6 +128,20 @@ export default function GlobalStylesSidebar() { ); }; + const { getActiveComplementaryArea } = useSelect( interfaceStore ); + const { enableComplementaryArea } = useDispatch( interfaceStore ); + const previousActiveAreaRef = useRef( null ); + + useEffect( () => { + if ( path === '/wp_global_styles' && canvas === 'edit' ) { + previousActiveAreaRef.current = + getActiveComplementaryArea( 'core' ); + enableComplementaryArea( 'core', 'edit-site/global-styles' ); + } else if ( previousActiveAreaRef.current ) { + enableComplementaryArea( 'core', previousActiveAreaRef.current ); + } + }, [ path, enableComplementaryArea, canvas, getActiveComplementaryArea ] ); + return ( <DefaultSidebar className="edit-site-global-styles-sidebar" From 46ab740e6541380681dac7beb6fa890f944bf46b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Thu, 14 Nov 2024 13:26:29 +0100 Subject: [PATCH 1577/1908] Storybook: fix DataViews layout (#66999) --- .../dataviews/src/components/dataviews/stories/index.story.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/dataviews/src/components/dataviews/stories/index.story.tsx b/packages/dataviews/src/components/dataviews/stories/index.story.tsx index 3b3e1326115b0e..878677d2eb30c6 100644 --- a/packages/dataviews/src/components/dataviews/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataviews/stories/index.story.tsx @@ -65,6 +65,7 @@ export const Default = () => { const [ view, setView ] = useState< View >( { ...DEFAULT_VIEW, fields: [ 'title', 'description', 'categories' ], + layout: defaultLayouts[ DEFAULT_VIEW.type ].layout, } ); const { data: shownData, paginationInfo } = useMemo( () => { return filterSortAndPaginate( data, view, fields ); From 4d0245c44b8dabc3f5d7efb32f422f8798c6967a Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:06:12 +0100 Subject: [PATCH 1578/1908] Comments controller: fix issue where comments are allowed when closed (#66976) Unlinked contributors: xavier-lc. Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- ...-gutenberg-rest-comment-controller-6-8.php | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/lib/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php b/lib/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php index 981b9dbd840319..60b45b1a63adef 100644 --- a/lib/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php +++ b/lib/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php @@ -10,6 +10,10 @@ class Gutenberg_REST_Comment_Controller_6_8 extends WP_REST_Comments_Controller { public function create_item_permissions_check( $request ) { + if ( empty( $request['comment_type'] ) || 'comment' === $request['comment_type'] ) { + return parent::create_item_permissions_check( $request ); + } + if ( ! is_user_logged_in() ) { if ( get_option( 'comment_registration' ) ) { return new WP_Error( @@ -90,14 +94,6 @@ public function create_item_permissions_check( $request ) { ); } - if ( 'draft' === $post->post_status && 'comment' === $request['comment_type'] ) { - return new WP_Error( - 'rest_comment_draft_post', - __( 'Sorry, you are not allowed to create a comment on this post.' ), - array( 'status' => 403 ) - ); - } - if ( 'trash' === $post->post_status ) { return new WP_Error( 'rest_comment_trash_post', @@ -114,14 +110,6 @@ public function create_item_permissions_check( $request ) { ); } - if ( ! comments_open( $post->ID ) && 'comment' === $request['comment_type'] ) { - return new WP_Error( - 'rest_comment_closed', - __( 'Sorry, comments are closed for this item.' ), - array( 'status' => 403 ) - ); - } - return true; } } From a120f10e63e3c6eb5fa4970e8ab3690e74453fde Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 14 Nov 2024 17:20:49 +0400 Subject: [PATCH 1579/1908] Preferences: Use hooks instead of HoC in 'EnablePublishSidebarOption' (#67002) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../enable-publish-sidebar.js | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/editor/src/components/preferences-modal/enable-publish-sidebar.js b/packages/editor/src/components/preferences-modal/enable-publish-sidebar.js index bcdfb2540e8dac..bef31efe40e94b 100644 --- a/packages/editor/src/components/preferences-modal/enable-publish-sidebar.js +++ b/packages/editor/src/components/preferences-modal/enable-publish-sidebar.js @@ -1,8 +1,7 @@ /** * WordPress dependencies */ -import { compose } from '@wordpress/compose'; -import { withSelect, withDispatch } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import { privateApis as preferencesPrivateApis } from '@wordpress/preferences'; /** @@ -13,16 +12,20 @@ import { store as editorStore } from '../../store'; const { PreferenceBaseOption } = unlock( preferencesPrivateApis ); -export default compose( - withSelect( ( select ) => ( { - isChecked: select( editorStore ).isPublishSidebarEnabled(), - } ) ), - withDispatch( ( dispatch ) => { - const { enablePublishSidebar, disablePublishSidebar } = - dispatch( editorStore ); - return { - onChange: ( isEnabled ) => - isEnabled ? enablePublishSidebar() : disablePublishSidebar(), - }; - } ) -)( PreferenceBaseOption ); +export default function EnablePublishSidebarOption( props ) { + const isChecked = useSelect( ( select ) => { + return select( editorStore ).isPublishSidebarEnabled(); + }, [] ); + const { enablePublishSidebar, disablePublishSidebar } = + useDispatch( editorStore ); + + return ( + <PreferenceBaseOption + isChecked={ isChecked } + onChange={ ( isEnabled ) => + isEnabled ? enablePublishSidebar() : disablePublishSidebar() + } + { ...props } + /> + ); +} From 07a13737d0b348ccdc8e29116f7385dd79d1a8b9 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:18:16 +0100 Subject: [PATCH 1580/1908] Site Editor: Styles: fix inspector opening (#67004) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../edit-site/src/components/global-styles-sidebar/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles-sidebar/index.js b/packages/edit-site/src/components/global-styles-sidebar/index.js index b1cf4fec92c86e..d46346b50dae37 100644 --- a/packages/edit-site/src/components/global-styles-sidebar/index.js +++ b/packages/edit-site/src/components/global-styles-sidebar/index.js @@ -133,7 +133,7 @@ export default function GlobalStylesSidebar() { const previousActiveAreaRef = useRef( null ); useEffect( () => { - if ( path === '/wp_global_styles' && canvas === 'edit' ) { + if ( path?.startsWith( '/wp_global_styles' ) && canvas === 'edit' ) { previousActiveAreaRef.current = getActiveComplementaryArea( 'core' ); enableComplementaryArea( 'core', 'edit-site/global-styles' ); From 842a504c96805fe0355cac25b29615566e48c3cd Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 14 Nov 2024 15:54:56 +0000 Subject: [PATCH 1581/1908] Bump plugin version to 19.7.0-rc.2 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index ac250e5671a4d2..f79182f3ead567 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.7.0-rc.1 + * Version: 19.7.0-rc.2 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 0bcf8aee842fd4..b4d618b6da02ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.7.0-rc.1", + "version": "19.7.0-rc.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.7.0-rc.1", + "version": "19.7.0-rc.2", "hasInstallScript": true, "license": "GPL-2.0-or-later", "workspaces": [ diff --git a/package.json b/package.json index a2059f7d53a65d..87cf9a5cacd943 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.7.0-rc.1", + "version": "19.7.0-rc.2", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From bd76a24da7fa112e77f49de21db4507fe9a46f09 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 14 Nov 2024 16:05:31 +0000 Subject: [PATCH 1582/1908] Update Changelog for 19.6.2 --- changelog.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/changelog.txt b/changelog.txt index af07058d4ddec5..bd6d5556d98bbc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,10 @@ == Changelog == += 19.6.2 = + +- Comments controller: fix issue where comments are allowed when closed [#66976](https://github.com/WordPress/gutenberg/pull/66976) + + = 19.7.0-rc.1 = From 645ce9feae4e0c68b5184be8d3aa587e621ab580 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Thu, 14 Nov 2024 16:07:37 +0000 Subject: [PATCH 1583/1908] Update Changelog for 19.7.0-rc.2 --- changelog.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/changelog.txt b/changelog.txt index bd6d5556d98bbc..ba6f0ce133ec1c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ == Changelog == += 19.7.0-rc.2 = + + +- Comments controller: fix issue where comments are allowed when closed (https://github.com/WordPress/gutenberg/pull/66976) + + = 19.6.2 = - Comments controller: fix issue where comments are allowed when closed [#66976](https://github.com/WordPress/gutenberg/pull/66976) From e7f0dc53ab3d8bbd53bd19129e00ed34aad67326 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Thu, 14 Nov 2024 18:30:12 +0200 Subject: [PATCH 1584/1908] DataViews: Fix focus loss when removing all filters or resetting (#67003) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- packages/dataviews/CHANGELOG.md | 7 +- .../components/dataviews-filters/index.tsx | 111 ++++++++++++------ .../src/components/dataviews/index.tsx | 4 +- 3 files changed, 80 insertions(+), 42 deletions(-) diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 60cdad73b32efe..a236902a06b224 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- Fix focus loss when removing all filters or resetting ([#67003](https://github.com/WordPress/gutenberg/pull/67003)). + ## 4.7.0 (2024-10-30) ## 4.6.0 (2024-10-16) @@ -23,8 +27,7 @@ ## Internal - The "move left/move right" controls in the table layout (popup displayed on cliking header) are always visible. ([#64646](https://github.com/WordPress/gutenberg/pull/64646)). Before this, its visibility depending on filters, enableSorting, and enableHiding. -- Filters no longer display the elements' description. ([#64674](https://github.com/WordPress/gutenberg/pull/64674)) - +- Filters no longer display the elements' description. ([#64674](https://github.com/WordPress/gutenberg/pull/64674)) ## Enhancements diff --git a/packages/dataviews/src/components/dataviews-filters/index.tsx b/packages/dataviews/src/components/dataviews-filters/index.tsx index 9722844cf4a141..440df4f17310d6 100644 --- a/packages/dataviews/src/components/dataviews-filters/index.tsx +++ b/packages/dataviews/src/components/dataviews-filters/index.tsx @@ -7,6 +7,7 @@ import { useRef, useMemo, useCallback, + useEffect, } from '@wordpress/element'; import { __experimentalHStack as HStack, Button } from '@wordpress/components'; import { funnel } from '@wordpress/icons'; @@ -70,7 +71,7 @@ export function useFilters( fields: NormalizedField< any >[], view: View ) { }, [ fields, view ] ); } -export function FilterVisibilityToggle( { +export function FiltersToggle( { filters, view, onChangeView, @@ -85,6 +86,7 @@ export function FilterVisibilityToggle( { isShowingFilter: boolean; setIsShowingFilter: React.Dispatch< React.SetStateAction< boolean > >; } ) { + const buttonRef = useRef< HTMLButtonElement >( null ); const onChangeViewWithFilterVisibility = useCallback( ( _view: View ) => { onChangeView( _view ); @@ -98,48 +100,81 @@ export function FilterVisibilityToggle( { if ( filters.length === 0 ) { return null; } - if ( ! hasVisibleFilters ) { - return ( - <AddFilterMenu - filters={ filters } - view={ view } - onChangeView={ onChangeViewWithFilterVisibility } - setOpenedFilter={ setOpenedFilter } - trigger={ - <Button - className="dataviews-filters__visibility-toggle" - size="compact" - icon={ funnel } - label={ __( 'Add filter' ) } - isPressed={ false } - aria-expanded={ false } - /> - } - /> - ); - } + + const addFilterButtonProps = { + label: __( 'Add filter' ), + 'aria-expanded': false, + isPressed: false, + }; + const toggleFiltersButtonProps = { + label: _x( 'Filter', 'verb' ), + 'aria-expanded': isShowingFilter, + isPressed: isShowingFilter, + onClick: () => { + if ( ! isShowingFilter ) { + setOpenedFilter( null ); + } + setIsShowingFilter( ! isShowingFilter ); + }, + }; + const buttonComponent = ( + <Button + ref={ buttonRef } + className="dataviews-filters__visibility-toggle" + size="compact" + icon={ funnel } + { ...( hasVisibleFilters + ? toggleFiltersButtonProps + : addFilterButtonProps ) } + /> + ); return ( <div className="dataviews-filters__container-visibility-toggle"> - <Button - className="dataviews-filters__visibility-toggle" - size="compact" - icon={ funnel } - label={ _x( 'Filter', 'verb' ) } - onClick={ () => { - if ( ! isShowingFilter ) { - setOpenedFilter( null ); - } - setIsShowingFilter( ! isShowingFilter ); - } } - isPressed={ isShowingFilter } - aria-expanded={ isShowingFilter } - /> - { hasVisibleFilters && !! view.filters?.length && ( + { ! hasVisibleFilters ? ( + <AddFilterMenu + filters={ filters } + view={ view } + onChangeView={ onChangeViewWithFilterVisibility } + setOpenedFilter={ setOpenedFilter } + trigger={ buttonComponent } + /> + ) : ( + <FilterVisibilityToggle + buttonRef={ buttonRef } + filtersCount={ view.filters?.length } + > + { buttonComponent } + </FilterVisibilityToggle> + ) } + </div> + ); +} + +function FilterVisibilityToggle( { + buttonRef, + filtersCount, + children, +}: { + buttonRef: React.RefObject< HTMLButtonElement >; + filtersCount?: number; + children: React.ReactNode; +} ) { + // Focus the `add filter` button when unmounts. + useEffect( + () => () => { + buttonRef.current?.focus(); + }, + [ buttonRef ] + ); + return ( + <> + { children } + { !! filtersCount && ( <span className="dataviews-filters-toggle__count"> - { view.filters?.length } + { filtersCount } </span> ) } - </div> + </> ); } diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index 77a5cb8740f712..3e8224e61bc5d5 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -16,7 +16,7 @@ import DataViewsContext from '../dataviews-context'; import { default as DataViewsFilters, useFilters, - FilterVisibilityToggle, + FiltersToggle, } from '../dataviews-filters'; import DataViewsLayout from '../dataviews-layout'; import DataViewsFooter from '../dataviews-footer'; @@ -135,7 +135,7 @@ export default function DataViews< Item >( { className="dataviews__search" > { search && <DataViewsSearch label={ searchLabel } /> } - <FilterVisibilityToggle + <FiltersToggle filters={ filters } view={ view } onChangeView={ onChangeView } From 2e4b8d8a0593f3791fb580d127c51a9f334bf59d Mon Sep 17 00:00:00 2001 From: tellthemachines <tellthemachines@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:22:05 +1100 Subject: [PATCH 1585/1908] Fix media placeholder to only activate for media objects. (#66986) Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../src/components/inserter-draggable-blocks/index.js | 11 ++++++++++- .../src/components/media-placeholder/index.js | 10 +++++----- test/e2e/specs/editor/blocks/image.spec.js | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/inserter-draggable-blocks/index.js b/packages/block-editor/src/components/inserter-draggable-blocks/index.js index 5a63535be3d3ce..0e1aaadc72e67b 100644 --- a/packages/block-editor/src/components/inserter-draggable-blocks/index.js +++ b/packages/block-editor/src/components/inserter-draggable-blocks/index.js @@ -29,6 +29,15 @@ const InserterDraggableBlocks = ( { blocks, }; + const blocksContainMedia = + blocks.filter( + ( block ) => + ( block.name === 'core/image' || + block.name === 'core/audio' || + block.name === 'core/video' ) && + ( block.attributes.url || block.attributes.src ) + ).length > 0; + const blockTypeIcon = useSelect( ( select ) => { const { getBlockType } = select( blocksStore ); @@ -63,7 +72,7 @@ const InserterDraggableBlocks = ( { ? [ createBlock( 'core/block', { ref: pattern.id } ) ] : blocks; event.dataTransfer.setData( - 'text/html', + blocksContainMedia ? 'default' : 'text/html', serialize( parsedBlocks ) ); } } diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index 07a3f8829e71d1..2f1a47be2f5a6e 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -288,8 +288,10 @@ export function MediaPlaceholder( { } } - async function onHTMLDrop( HTML ) { - const blocks = pasteHandler( { HTML } ); + async function onDrop( event ) { + const blocks = pasteHandler( { + HTML: event.dataTransfer?.getData( 'default' ), + } ); return await handleBlocksDrop( blocks ); } @@ -379,9 +381,7 @@ export function MediaPlaceholder( { return null; } - return ( - <DropZone onFilesDrop={ onFilesUpload } onHTMLDrop={ onHTMLDrop } /> - ); + return <DropZone onFilesDrop={ onFilesUpload } onDrop={ onDrop } />; }; const renderCancelLink = () => { diff --git a/test/e2e/specs/editor/blocks/image.spec.js b/test/e2e/specs/editor/blocks/image.spec.js index 6110a125ff6f7e..b2195f2c676885 100644 --- a/test/e2e/specs/editor/blocks/image.spec.js +++ b/test/e2e/specs/editor/blocks/image.spec.js @@ -545,7 +545,7 @@ test.describe( 'Image', () => { dummy.style.left = 0; dummy.draggable = 'true'; dummy.addEventListener( 'dragstart', ( event ) => { - event.dataTransfer.setData( 'text/html', _html ); + event.dataTransfer.setData( 'default', _html ); setTimeout( () => { dummy.remove(); }, 0 ); From 02f67b89c9130d9ce552e6fe3c6a382984932e36 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:15:01 +0900 Subject: [PATCH 1586/1908] DataViews: Fix primary field misalignment in grid layout (#66995) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/dataviews/src/dataviews-layouts/grid/index.tsx | 8 +++----- packages/dataviews/src/dataviews-layouts/grid/style.scss | 2 ++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx index 91cc87ec7b35b6..e218172b7900aa 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx @@ -114,11 +114,9 @@ function GridItem< Item >( { justify="space-between" className="dataviews-view-grid__title-actions" > - <HStack> - <div { ...clickablePrimaryItemProps }> - { renderedPrimaryField } - </div> - </HStack> + <div { ...clickablePrimaryItemProps }> + { renderedPrimaryField } + </div> <ItemActions item={ item } actions={ actions } isCompact /> </HStack> { !! badgeFields?.length && ( diff --git a/packages/dataviews/src/dataviews-layouts/grid/style.scss b/packages/dataviews/src/dataviews-layouts/grid/style.scss index 55768240a18714..081adf51b5dc11 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/style.scss +++ b/packages/dataviews/src/dataviews-layouts/grid/style.scss @@ -17,6 +17,8 @@ .dataviews-view-grid__primary-field { min-height: $grid-unit-40; // Preserve layout when there is no ellipsis button + display: flex; + align-items: center; &--clickable { width: fit-content; From 40954ff494de20b177436f85a0a2925ffcf7ff6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 15 Nov 2024 09:32:05 +0100 Subject: [PATCH 1587/1908] DataViews table layout: hide actions menu when there is only one action and is primary (#67020) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../dataviews-item-actions/index.tsx | 86 ++++++++++++++----- 1 file changed, 63 insertions(+), 23 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-item-actions/index.tsx b/packages/dataviews/src/components/dataviews-item-actions/index.tsx index 20e58a2c6bb1fb..c1a1f84b99e624 100644 --- a/packages/dataviews/src/components/dataviews-item-actions/index.tsx +++ b/packages/dataviews/src/components/dataviews-item-actions/index.tsx @@ -59,6 +59,12 @@ interface CompactItemActionsProps< Item > { actions: Action< Item >[]; } +interface PrimaryActionsProps< Item > { + item: Item; + actions: Action< Item >[]; + registry: ReturnType< typeof useRegistry >; +} + function ButtonTrigger< Item >( { action, onClick, @@ -179,6 +185,13 @@ export function ActionsMenuGroup< Item >( { ); } +function hasOnlyOneActionAndIsPrimary< Item >( + primaryActions: Action< Item >[], + actions: Action< Item >[] +) { + return primaryActions.length === 1 && actions.length; +} + export default function ItemActions< Item >( { item, actions, @@ -199,9 +212,21 @@ export default function ItemActions< Item >( { eligibleActions: _eligibleActions, }; }, [ actions, item ] ); + if ( isCompact ) { return <CompactItemActions item={ item } actions={ eligibleActions } />; } + + if ( hasOnlyOneActionAndIsPrimary( primaryActions, actions ) ) { + return ( + <PrimaryActions + item={ item } + actions={ primaryActions } + registry={ registry } + /> + ); + } + return ( <HStack spacing={ 1 } @@ -212,29 +237,11 @@ export default function ItemActions< Item >( { width: 'auto', } } > - { !! primaryActions.length && - primaryActions.map( ( action ) => { - if ( 'RenderModal' in action ) { - return ( - <ActionWithModal - key={ action.id } - action={ action } - items={ [ item ] } - ActionTrigger={ ButtonTrigger } - /> - ); - } - return ( - <ButtonTrigger - key={ action.id } - action={ action } - onClick={ () => { - action.callback( [ item ], { registry } ); - } } - items={ [ item ] } - /> - ); - } ) } + <PrimaryActions + item={ item } + actions={ primaryActions } + registry={ registry } + /> <CompactItemActions item={ item } actions={ eligibleActions } /> </HStack> ); @@ -262,3 +269,36 @@ function CompactItemActions< Item >( { </Menu> ); } + +function PrimaryActions< Item >( { + item, + actions, + registry, +}: PrimaryActionsProps< Item > ) { + if ( ! Array.isArray( actions ) || actions.length === 0 ) { + return null; + } + + return actions.map( ( action ) => { + if ( 'RenderModal' in action ) { + return ( + <ActionWithModal + key={ action.id } + action={ action } + items={ [ item ] } + ActionTrigger={ ButtonTrigger } + /> + ); + } + return ( + <ButtonTrigger + key={ action.id } + action={ action } + onClick={ () => { + action.callback( [ item ], { registry } ); + } } + items={ [ item ] } + /> + ); + } ); +} From 8eb0bf18672b05bfbf090b0ee020d67f40ba859c Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 15 Nov 2024 13:02:17 +0400 Subject: [PATCH 1588/1908] Preferences: Use hooks instead of HoC in 'EnableCustomFieldsOption' (#67023) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../preferences-modal/enable-custom-fields.js | 12 +++---- .../test/enable-custom-fields.js | 35 ++++++++++++------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js b/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js index b8125e96c7c2cf..f3db9d123f9d71 100644 --- a/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js +++ b/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js @@ -4,7 +4,7 @@ import { useState } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { Button } from '@wordpress/components'; -import { withSelect } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; import { store as editorStore } from '@wordpress/editor'; import { privateApis as preferencesPrivateApis } from '@wordpress/preferences'; import { getPathAndQueryString } from '@wordpress/url'; @@ -57,7 +57,10 @@ export function CustomFieldsConfirmation( { willEnable } ) { ); } -export function EnableCustomFieldsOption( { label, areCustomFieldsEnabled } ) { +export default function EnableCustomFieldsOption( { label } ) { + const areCustomFieldsEnabled = useSelect( ( select ) => { + return !! select( editorStore ).getEditorSettings().enableCustomFields; + }, [] ); const [ isChecked, setIsChecked ] = useState( areCustomFieldsEnabled ); return ( @@ -72,8 +75,3 @@ export function EnableCustomFieldsOption( { label, areCustomFieldsEnabled } ) { </PreferenceBaseOption> ); } - -export default withSelect( ( select ) => ( { - areCustomFieldsEnabled: - !! select( editorStore ).getEditorSettings().enableCustomFields, -} ) )( EnableCustomFieldsOption ); diff --git a/packages/edit-post/src/components/preferences-modal/test/enable-custom-fields.js b/packages/edit-post/src/components/preferences-modal/test/enable-custom-fields.js index 2dbeadec8350ac..adfa4a3df391da 100644 --- a/packages/edit-post/src/components/preferences-modal/test/enable-custom-fields.js +++ b/packages/edit-post/src/components/preferences-modal/test/enable-custom-fields.js @@ -4,27 +4,38 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; + /** * Internal dependencies */ import { - EnableCustomFieldsOption, + default as EnableCustomFieldsOption, CustomFieldsConfirmation, } from '../enable-custom-fields'; +jest.mock( '@wordpress/data/src/components/use-select', () => jest.fn() ); + +function setupUseSelectMock( areCustomFieldsEnabled ) { + useSelect.mockImplementation( () => { + return areCustomFieldsEnabled; + } ); +} + describe( 'EnableCustomFieldsOption', () => { it( 'renders a checked checkbox when custom fields are enabled', () => { - const { container } = render( - <EnableCustomFieldsOption areCustomFieldsEnabled /> - ); + setupUseSelectMock( true ); + const { container } = render( <EnableCustomFieldsOption /> ); expect( container ).toMatchSnapshot(); } ); it( 'renders an unchecked checkbox when custom fields are disabled', () => { - const { container } = render( - <EnableCustomFieldsOption areCustomFieldsEnabled={ false } /> - ); + setupUseSelectMock( false ); + const { container } = render( <EnableCustomFieldsOption /> ); expect( container ).toMatchSnapshot(); } ); @@ -32,9 +43,8 @@ describe( 'EnableCustomFieldsOption', () => { it( 'renders an unchecked checkbox and a confirmation message when toggled off', async () => { const user = userEvent.setup(); - const { container } = render( - <EnableCustomFieldsOption areCustomFieldsEnabled /> - ); + setupUseSelectMock( true ); + const { container } = render( <EnableCustomFieldsOption /> ); await user.click( screen.getByRole( 'checkbox' ) ); @@ -44,9 +54,8 @@ describe( 'EnableCustomFieldsOption', () => { it( 'renders a checked checkbox and a confirmation message when toggled on', async () => { const user = userEvent.setup(); - const { container } = render( - <EnableCustomFieldsOption areCustomFieldsEnabled={ false } /> - ); + setupUseSelectMock( false ); + const { container } = render( <EnableCustomFieldsOption /> ); await user.click( screen.getByRole( 'checkbox' ) ); From a750125b0210b9d906efcec2d807477590e4412f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 15 Nov 2024 10:54:05 +0100 Subject: [PATCH 1589/1908] DataViews list layout: hide actions menu when there is only one action and is primary (#67015) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/dataviews-layouts/list/index.tsx | 58 ++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/packages/dataviews/src/dataviews-layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx index a4f94e482c69b3..47b9961d97df18 100644 --- a/packages/dataviews/src/dataviews-layouts/list/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/list/index.tsx @@ -170,11 +170,13 @@ function ListItem< Item >( { ( action ) => action.isPrimary && !! action.icon ); return { - primaryAction: _primaryActions?.[ 0 ], + primaryAction: _primaryActions[ 0 ], eligibleActions: _eligibleActions, }; }, [ actions, item ] ); + const hasOnlyOnePrimaryAction = primaryAction && actions.length === 1; + const renderedMediaField = mediaField?.render ? ( <div className="dataviews-view-list__media-wrapper"> <mediaField.render item={ item } /> @@ -194,33 +196,35 @@ function ListItem< Item >( { item={ item } /> ) } - <div role="gridcell"> - <Menu - trigger={ - <Composite.Item - id={ generateDropdownTriggerCompositeId( - idPrefix - ) } - render={ - <Button - size="small" - icon={ moreVertical } - label={ __( 'Actions' ) } - accessibleWhenDisabled - disabled={ ! actions.length } - onKeyDown={ onDropdownTriggerKeyDown } - /> - } + { ! hasOnlyOnePrimaryAction && ( + <div role="gridcell"> + <Menu + trigger={ + <Composite.Item + id={ generateDropdownTriggerCompositeId( + idPrefix + ) } + render={ + <Button + size="small" + icon={ moreVertical } + label={ __( 'Actions' ) } + accessibleWhenDisabled + disabled={ ! actions.length } + onKeyDown={ onDropdownTriggerKeyDown } + /> + } + /> + } + placement="bottom-end" + > + <ActionsMenuGroup + actions={ eligibleActions } + item={ item } /> - } - placement="bottom-end" - > - <ActionsMenuGroup - actions={ eligibleActions } - item={ item } - /> - </Menu> - </div> + </Menu> + </div> + ) } </HStack> ); From d8e0b1364496ce169e4c9bcfc801f4362669760d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 15 Nov 2024 12:08:51 +0100 Subject: [PATCH 1590/1908] Move `usePostFields` to `wordpress/editor` package (#67024) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../src/dataforms-layouts/panel/style.scss | 4 ++ .../src/components/post-edit/index.js | 3 +- .../src/components/post-fields/index.js | 50 -------------- .../src/components/post-fields/style.scss | 3 - .../src/components/post-list/index.js | 3 +- packages/edit-site/src/style.scss | 1 - .../src/components/post-fields/index.ts | 65 +++++++++++++++++++ packages/editor/src/private-apis.js | 2 + packages/fields/src/index.ts | 1 + 9 files changed, 74 insertions(+), 58 deletions(-) delete mode 100644 packages/edit-site/src/components/post-fields/index.js delete mode 100644 packages/edit-site/src/components/post-fields/style.scss create mode 100644 packages/editor/src/components/post-fields/index.ts diff --git a/packages/dataviews/src/dataforms-layouts/panel/style.scss b/packages/dataviews/src/dataforms-layouts/panel/style.scss index ae69c4ff45243a..c7058f6366b3b6 100644 --- a/packages/dataviews/src/dataforms-layouts/panel/style.scss +++ b/packages/dataviews/src/dataforms-layouts/panel/style.scss @@ -44,3 +44,7 @@ .dataforms-layouts-panel__dropdown-header { margin-bottom: $grid-unit-20; } + +.components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown { + z-index: z-index(".components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown"); +} diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index fbff29ed67afa1..a535eef4ce7878 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -18,10 +18,9 @@ import { privateApis as editorPrivateApis } from '@wordpress/editor'; * Internal dependencies */ import Page from '../page'; -import usePostFields from '../post-fields'; import { unlock } from '../../lock-unlock'; -const { PostCardPanel } = unlock( editorPrivateApis ); +const { PostCardPanel, usePostFields } = unlock( editorPrivateApis ); const fieldsWithBulkEditSupport = [ 'title', diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js deleted file mode 100644 index 6ba9453709f0d3..00000000000000 --- a/packages/edit-site/src/components/post-fields/index.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * WordPress dependencies - */ -import { - featuredImageField, - slugField, - parentField, - passwordField, - statusField, - commentStatusField, - titleField, - dateField, - authorField, -} from '@wordpress/fields'; -import { useMemo } from '@wordpress/element'; -import { useEntityRecords } from '@wordpress/core-data'; - -function usePostFields() { - const { records: authors, isResolving: isLoadingAuthors } = - useEntityRecords( 'root', 'user', { per_page: -1 } ); - - const fields = useMemo( - () => [ - featuredImageField, - titleField, - { - ...authorField, - elements: - authors?.map( ( { id, name } ) => ( { - value: id, - label: name, - } ) ) || [], - }, - statusField, - dateField, - slugField, - parentField, - commentStatusField, - passwordField, - ], - [ authors ] - ); - - return { - isLoading: isLoadingAuthors, - fields, - }; -} - -export default usePostFields; diff --git a/packages/edit-site/src/components/post-fields/style.scss b/packages/edit-site/src/components/post-fields/style.scss deleted file mode 100644 index adeaf9a2678253..00000000000000 --- a/packages/edit-site/src/components/post-fields/style.scss +++ /dev/null @@ -1,3 +0,0 @@ -.components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown { - z-index: z-index(".components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown"); -} diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 4639cb3c950b76..975809b2ad6106 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -32,9 +32,8 @@ import AddNewPostModal from '../add-new-post'; import { unlock } from '../../lock-unlock'; import { useEditPostAction } from '../dataviews-actions'; import { usePrevious } from '@wordpress/compose'; -import usePostFields from '../post-fields'; -const { usePostActions } = unlock( editorPrivateApis ); +const { usePostActions, usePostFields } = unlock( editorPrivateApis ); const { useLocation, useHistory } = unlock( routerPrivateApis ); const { useEntityRecordsWithPermissions } = unlock( coreDataPrivateApis ); const EMPTY_ARRAY = []; diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 0e5744fe362e35..63ad8244a7c95e 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -30,7 +30,6 @@ @import "./components/editor-canvas-container/style.scss"; @import "./components/post-edit/style.scss"; @import "./components/post-list/style.scss"; -@import "./components/post-fields/style.scss"; @import "./components/resizable-frame/style.scss"; @import "./hooks/push-changes-to-global-styles/style.scss"; @import "./components/global-styles/font-library-modal/style.scss"; diff --git a/packages/editor/src/components/post-fields/index.ts b/packages/editor/src/components/post-fields/index.ts new file mode 100644 index 00000000000000..3d675ab763d64c --- /dev/null +++ b/packages/editor/src/components/post-fields/index.ts @@ -0,0 +1,65 @@ +/** + * WordPress dependencies + */ +import { useMemo } from '@wordpress/element'; +import { useEntityRecords } from '@wordpress/core-data'; +import type { Field } from '@wordpress/dataviews'; +import { + featuredImageField, + slugField, + parentField, + passwordField, + statusField, + commentStatusField, + titleField, + dateField, + authorField, +} from '@wordpress/fields'; +import type { BasePostWithEmbeddedAuthor } from '@wordpress/fields'; + +interface UsePostFieldsReturn { + isLoading: boolean; + fields: Field< BasePostWithEmbeddedAuthor >[]; +} + +interface Author { + id: number; + name: string; +} + +function usePostFields(): UsePostFieldsReturn { + const { records: authors, isResolving: isLoadingAuthors } = + useEntityRecords< Author >( 'root', 'user', { per_page: -1 } ); + + const fields = useMemo( + () => + [ + featuredImageField, + titleField, + { + ...authorField, + elements: authors?.map( ( { id, name } ) => ( { + value: id, + label: name, + } ) ), + }, + statusField, + dateField, + slugField, + parentField, + commentStatusField, + passwordField, + ] as Field< BasePostWithEmbeddedAuthor >[], + [ authors ] + ); + + return { + isLoading: isLoadingAuthors, + fields, + }; +} + +/** + * Hook to get the fields for a post (BasePost or BasePostWithEmbeddedAuthor). + */ +export default usePostFields; diff --git a/packages/editor/src/private-apis.js b/packages/editor/src/private-apis.js index f9a6d4d17904ee..b49b2a69a3bf2b 100644 --- a/packages/editor/src/private-apis.js +++ b/packages/editor/src/private-apis.js @@ -16,6 +16,7 @@ import PluginPostExcerpt from './components/post-excerpt/plugin'; import PostCardPanel from './components/post-card-panel'; import PreferencesModal from './components/preferences-modal'; import { usePostActions } from './components/post-actions/actions'; +import usePostFields from './components/post-fields'; import ToolsMoreMenuGroup from './components/more-menu/tools-more-menu-group'; import ViewMoreMenuGroup from './components/more-menu/view-more-menu-group'; import ResizableEditor from './components/resizable-editor'; @@ -40,6 +41,7 @@ lock( privateApis, { PostCardPanel, PreferencesModal, usePostActions, + usePostFields, ToolsMoreMenuGroup, ViewMoreMenuGroup, ResizableEditor, diff --git a/packages/fields/src/index.ts b/packages/fields/src/index.ts index 4c721b85b61a40..41879a86e76bed 100644 --- a/packages/fields/src/index.ts +++ b/packages/fields/src/index.ts @@ -1,2 +1,3 @@ export * from './fields'; export * from './actions'; +export type * from './types'; From d79e540d635ecd6f595c408288381c7bf6babc52 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 15 Nov 2024 15:09:31 +0400 Subject: [PATCH 1591/1908] Block Library: Fix React Compiler error for shortcuts (#67019) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../src/block-keyboard-shortcuts/index.js | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/packages/block-library/src/block-keyboard-shortcuts/index.js b/packages/block-library/src/block-keyboard-shortcuts/index.js index 6d9cde8364001f..2ce106b8ed99dc 100644 --- a/packages/block-library/src/block-keyboard-shortcuts/index.js +++ b/packages/block-library/src/block-keyboard-shortcuts/index.js @@ -90,22 +90,36 @@ function BlockKeyboardShortcuts() { }, } ); } ); - }, [] ); + }, [ registerShortcut ] ); useShortcut( 'core/block-editor/transform-heading-to-paragraph', ( event ) => handleTransformHeadingAndParagraph( event, 0 ) ); - - [ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => { - //the loop is based off on a constant therefore - //the hook will execute the same way every time - //eslint-disable-next-line react-hooks/rules-of-hooks - useShortcut( - `core/block-editor/transform-paragraph-to-heading-${ level }`, - ( event ) => handleTransformHeadingAndParagraph( event, level ) - ); - } ); + useShortcut( + 'core/block-editor/transform-paragraph-to-heading-1', + ( event ) => handleTransformHeadingAndParagraph( event, 1 ) + ); + useShortcut( + 'core/block-editor/transform-paragraph-to-heading-2', + ( event ) => handleTransformHeadingAndParagraph( event, 2 ) + ); + useShortcut( + 'core/block-editor/transform-paragraph-to-heading-3', + ( event ) => handleTransformHeadingAndParagraph( event, 3 ) + ); + useShortcut( + 'core/block-editor/transform-paragraph-to-heading-4', + ( event ) => handleTransformHeadingAndParagraph( event, 4 ) + ); + useShortcut( + 'core/block-editor/transform-paragraph-to-heading-5', + ( event ) => handleTransformHeadingAndParagraph( event, 5 ) + ); + useShortcut( + 'core/block-editor/transform-paragraph-to-heading-6', + ( event ) => handleTransformHeadingAndParagraph( event, 6 ) + ); return null; } From 2b19b5868706a9490e9fd65dec60c1d2edbd173c Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 15 Nov 2024 15:14:37 +0400 Subject: [PATCH 1592/1908] Block Locking: Remove edit locking for Patterns (#67021) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: up1512001 <up1512001@git.wordpress.org> --- packages/block-editor/src/components/block-lock/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-lock/modal.js b/packages/block-editor/src/components/block-lock/modal.js index 7d09f7b63f8cd0..3be23f6adde146 100644 --- a/packages/block-editor/src/components/block-lock/modal.js +++ b/packages/block-editor/src/components/block-lock/modal.js @@ -24,7 +24,7 @@ import useBlockDisplayInformation from '../use-block-display-information'; import { store as blockEditorStore } from '../../store'; // Entity based blocks which allow edit locking -const ALLOWS_EDIT_LOCKING = [ 'core/block', 'core/navigation' ]; +const ALLOWS_EDIT_LOCKING = [ 'core/navigation' ]; function getTemplateLockValue( lock ) { // Prevents all operations. From c3a9c1aa02e0c0c2d1420fe8b49e06833285b158 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Fri, 15 Nov 2024 12:34:45 +0100 Subject: [PATCH 1593/1908] SlotFill: fix a bug with storing stale fillProps (#67000) * SlotFill: updateSlot should check the ref * Slot: store fillProps to a ref to fix effect deps * SlotFillProvider: tidy up API code * Add changelog entry Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../bubbles-virtually/slot-fill-provider.tsx | 40 ++++++++++++------- .../src/slot-fill/bubbles-virtually/slot.tsx | 22 +++++----- .../slot-fill/bubbles-virtually/use-slot.ts | 6 ++- packages/components/src/slot-fill/types.ts | 6 ++- 5 files changed, 48 insertions(+), 27 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 2fddf51173e832..dc51518eb32f10 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -10,6 +10,7 @@ - `Popover`: Fix missing label of the headerTitle Close button ([#66813](https://github.com/WordPress/gutenberg/pull/66813)). - `ToggleGroupControl`: Fix active background for `0` value ([#66855](https://github.com/WordPress/gutenberg/pull/66855)). +- `SlotFill`: Fix a bug where a stale value of `fillProps` could be used ([#67000](https://github.com/WordPress/gutenberg/pull/67000)). ### Enhancements diff --git a/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx b/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx index 4d68db6fd175ee..16a19c6569fda6 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx +++ b/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx @@ -34,15 +34,23 @@ function createSlotRegistry(): SlotFillBubblesVirtuallyContext { const unregisterSlot: SlotFillBubblesVirtuallyContext[ 'unregisterSlot' ] = ( name, ref ) => { + const slot = slots.get( name ); + if ( ! slot ) { + return; + } + // Make sure we're not unregistering a slot registered by another element // See https://github.com/WordPress/gutenberg/pull/19242#issuecomment-590295412 - if ( slots.get( name )?.ref === ref ) { - slots.delete( name ); + if ( slot.ref !== ref ) { + return; } + + slots.delete( name ); }; const updateSlot: SlotFillBubblesVirtuallyContext[ 'updateSlot' ] = ( name, + ref, fillProps ) => { const slot = slots.get( name ); @@ -50,6 +58,10 @@ function createSlotRegistry(): SlotFillBubblesVirtuallyContext { return; } + if ( slot.ref !== ref ) { + return; + } + if ( isShallowEqual( slot.fillProps, fillProps ) ) { return; } @@ -69,20 +81,18 @@ function createSlotRegistry(): SlotFillBubblesVirtuallyContext { fills.set( name, [ ...( fills.get( name ) || [] ), ref ] ); }; - const unregisterFill: SlotFillBubblesVirtuallyContext[ 'registerFill' ] = ( - name, - ref - ) => { - const fillsForName = fills.get( name ); - if ( ! fillsForName ) { - return; - } + const unregisterFill: SlotFillBubblesVirtuallyContext[ 'unregisterFill' ] = + ( name, ref ) => { + const fillsForName = fills.get( name ); + if ( ! fillsForName ) { + return; + } - fills.set( - name, - fillsForName.filter( ( fillRef ) => fillRef !== ref ) - ); - }; + fills.set( + name, + fillsForName.filter( ( fillRef ) => fillRef !== ref ) + ); + }; return { slots, diff --git a/packages/components/src/slot-fill/bubbles-virtually/slot.tsx b/packages/components/src/slot-fill/bubbles-virtually/slot.tsx index 6ac2d51e1f857f..b8ead7fc7ea8ba 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/slot.tsx +++ b/packages/components/src/slot-fill/bubbles-virtually/slot.tsx @@ -35,29 +35,33 @@ function Slot( as, // `children` is not allowed. However, if it is passed, // it will be displayed as is, so remove `children`. - // @ts-ignore children, ...restProps } = props; const { registerSlot, unregisterSlot, ...registry } = useContext( SlotFillContext ); + const ref = useRef< HTMLElement >( null ); + // We don't want to unregister and register the slot whenever + // `fillProps` change, which would cause the fill to be re-mounted. Instead, + // we can just update the slot (see hook below). + // For more context, see https://github.com/WordPress/gutenberg/pull/44403#discussion_r994415973 + const fillPropsRef = useRef( fillProps ); + useLayoutEffect( () => { + fillPropsRef.current = fillProps; + }, [ fillProps ] ); + useLayoutEffect( () => { - registerSlot( name, ref, fillProps ); + registerSlot( name, ref, fillPropsRef.current ); return () => { unregisterSlot( name, ref ); }; - // We don't want to unregister and register the slot whenever - // `fillProps` change, which would cause the fill to be re-mounted. Instead, - // we can just update the slot (see hook below). - // For more context, see https://github.com/WordPress/gutenberg/pull/44403#discussion_r994415973 }, [ registerSlot, unregisterSlot, name ] ); - // fillProps may be an update that interacts with the layout, so we - // useLayoutEffect. + useLayoutEffect( () => { - registry.updateSlot( name, fillProps ); + registry.updateSlot( name, ref, fillPropsRef.current ); } ); return ( diff --git a/packages/components/src/slot-fill/bubbles-virtually/use-slot.ts b/packages/components/src/slot-fill/bubbles-virtually/use-slot.ts index d1d37e1d8e541c..ec78771bfa92af 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/use-slot.ts +++ b/packages/components/src/slot-fill/bubbles-virtually/use-slot.ts @@ -21,8 +21,10 @@ export default function useSlot( name: SlotKey ) { const api = useMemo( () => ( { - updateSlot: ( fillProps: FillProps ) => - registry.updateSlot( name, fillProps ), + updateSlot: ( + ref: SlotFillBubblesVirtuallySlotRef, + fillProps: FillProps + ) => registry.updateSlot( name, ref, fillProps ), unregisterSlot: ( ref: SlotFillBubblesVirtuallySlotRef ) => registry.unregisterSlot( name, ref ), registerFill: ( ref: SlotFillBubblesVirtuallyFillRef ) => diff --git a/packages/components/src/slot-fill/types.ts b/packages/components/src/slot-fill/types.ts index 1711e04cbb1f47..7e1b8b7e1f3f9f 100644 --- a/packages/components/src/slot-fill/types.ts +++ b/packages/components/src/slot-fill/types.ts @@ -131,7 +131,11 @@ export type SlotFillBubblesVirtuallyContext = { name: SlotKey, ref: SlotFillBubblesVirtuallySlotRef ) => void; - updateSlot: ( name: SlotKey, fillProps: FillProps ) => void; + updateSlot: ( + name: SlotKey, + ref: SlotFillBubblesVirtuallySlotRef, + fillProps: FillProps + ) => void; registerFill: ( name: SlotKey, ref: SlotFillBubblesVirtuallyFillRef From 7300373152cbeda7e73cc1cb0741c6b3b1449151 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Fri, 15 Nov 2024 13:00:11 +0100 Subject: [PATCH 1594/1908] Improve the featured image UI when it cannot retrieve the image file and data (#66936) * Improve the featured image UI when cannot retrieve the image file and data. * Address CR feedback. * Use a Notice instead of a paragraph. * Address more CR feedback. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../components/post-featured-image/index.js | 152 +++++++++++++----- .../components/post-featured-image/style.scss | 36 +++-- 2 files changed, 132 insertions(+), 56 deletions(-) diff --git a/packages/editor/src/components/post-featured-image/index.js b/packages/editor/src/components/post-featured-image/index.js index cabd791e938bf5..46a194f311a5e7 100644 --- a/packages/editor/src/components/post-featured-image/index.js +++ b/packages/editor/src/components/post-featured-image/index.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + /** * WordPress dependencies */ @@ -10,9 +15,10 @@ import { withNotices, withFilters, __experimentalHStack as HStack, + Notice, } from '@wordpress/components'; import { isBlobURL } from '@wordpress/blob'; -import { useState, useRef } from '@wordpress/element'; +import { useState, useRef, useEffect } from '@wordpress/element'; import { compose } from '@wordpress/compose'; import { useSelect, withDispatch, withSelect } from '@wordpress/data'; import { @@ -94,11 +100,19 @@ function PostFeaturedImage( { postType, noticeUI, noticeOperations, + isRequestingFeaturedImageMedia, } ) { const toggleRef = useRef(); const [ isLoading, setIsLoading ] = useState( false ); const { getSettings } = useSelect( blockEditorStore ); const { mediaSourceUrl } = getMediaDetails( media, currentPostId ); + const toggleFocusTimerRef = useRef(); + + useEffect( () => { + return () => { + clearTimeout( toggleFocusTimerRef.current ); + }; + }, [] ); function onDropFiles( filesList ) { getSettings().mediaUpload( { @@ -150,6 +164,9 @@ function PostFeaturedImage( { ); } + const isMissingMedia = + ! isRequestingFeaturedImageMedia && !! featuredImageId && ! media; + return ( <PostFeaturedImageCheck> { noticeUI } @@ -174,52 +191,83 @@ function PostFeaturedImage( { modalClass="editor-post-featured-image__media-modal" render={ ( { open } ) => ( <div className="editor-post-featured-image__container"> - <Button - __next40pxDefaultSize - ref={ toggleRef } - className={ - ! featuredImageId - ? 'editor-post-featured-image__toggle' - : 'editor-post-featured-image__preview' - } - onClick={ open } - aria-label={ - ! featuredImageId - ? null - : __( - 'Edit or replace the featured image' - ) - } - aria-describedby={ - ! featuredImageId - ? null - : `editor-post-featured-image-${ featuredImageId }-describedby` - } - aria-haspopup="dialog" - disabled={ isLoading } - accessibleWhenDisabled - > - { !! featuredImageId && media && ( - <img - className="editor-post-featured-image__preview-image" - src={ mediaSourceUrl } - alt={ getImageDescription( media ) } - /> - ) } - { isLoading && <Spinner /> } - { ! featuredImageId && - ! isLoading && - ( postType?.labels - ?.set_featured_image || - DEFAULT_SET_FEATURE_IMAGE_LABEL ) } - </Button> + { isMissingMedia ? ( + <Notice + status="warning" + isDismissible={ false } + > + { __( + 'Could not retrieve the featured image data.' + ) } + </Notice> + ) : ( + <Button + __next40pxDefaultSize + ref={ toggleRef } + className={ + ! featuredImageId + ? 'editor-post-featured-image__toggle' + : 'editor-post-featured-image__preview' + } + onClick={ open } + aria-label={ + ! featuredImageId + ? null + : __( + 'Edit or replace the featured image' + ) + } + aria-describedby={ + ! featuredImageId + ? null + : `editor-post-featured-image-${ featuredImageId }-describedby` + } + aria-haspopup="dialog" + disabled={ isLoading } + accessibleWhenDisabled + > + { !! featuredImageId && media && ( + <img + className="editor-post-featured-image__preview-image" + src={ mediaSourceUrl } + alt={ getImageDescription( + media + ) } + /> + ) } + { ( isLoading || + isRequestingFeaturedImageMedia ) && ( + <Spinner /> + ) } + { ! featuredImageId && + ! isLoading && + ( postType?.labels + ?.set_featured_image || + DEFAULT_SET_FEATURE_IMAGE_LABEL ) } + </Button> + ) } { !! featuredImageId && ( - <HStack className="editor-post-featured-image__actions"> + <HStack + className={ clsx( + 'editor-post-featured-image__actions', + { + 'editor-post-featured-image__actions-missing-image': + isMissingMedia, + 'editor-post-featured-image__actions-is-requesting-image': + isRequestingFeaturedImageMedia, + } + ) } + > <Button __next40pxDefaultSize className="editor-post-featured-image__action" onClick={ open } aria-haspopup="dialog" + variant={ + isMissingMedia + ? 'secondary' + : undefined + } > { __( 'Replace' ) } </Button> @@ -228,8 +276,19 @@ function PostFeaturedImage( { className="editor-post-featured-image__action" onClick={ () => { onRemoveImage(); - toggleRef.current.focus(); + // The toggle button is rendered conditionally, we need + // to wait it is rendered before moving focus to it. + toggleFocusTimerRef.current = + setTimeout( () => { + toggleRef.current?.focus(); + } ); } } + variant={ + isMissingMedia + ? 'secondary' + : undefined + } + isDestructive={ isMissingMedia } > { __( 'Remove' ) } </Button> @@ -247,7 +306,8 @@ function PostFeaturedImage( { } const applyWithSelect = withSelect( ( select ) => { - const { getMedia, getPostType } = select( coreStore ); + const { getMedia, getPostType, hasFinishedResolution } = + select( coreStore ); const { getCurrentPostId, getEditedPostAttribute } = select( editorStore ); const featuredImageId = getEditedPostAttribute( 'featured_media' ); @@ -258,6 +318,12 @@ const applyWithSelect = withSelect( ( select ) => { currentPostId: getCurrentPostId(), postType: getPostType( getEditedPostAttribute( 'type' ) ), featuredImageId, + isRequestingFeaturedImageMedia: + !! featuredImageId && + ! hasFinishedResolution( 'getMedia', [ + featuredImageId, + { context: 'view' }, + ] ), }; } ); diff --git a/packages/editor/src/components/post-featured-image/style.scss b/packages/editor/src/components/post-featured-image/style.scss index 30d5cb43403cdf..bf9433faa662d4 100644 --- a/packages/editor/src/components/post-featured-image/style.scss +++ b/packages/editor/src/components/post-featured-image/style.scss @@ -16,11 +16,16 @@ &:hover, &:focus, &:focus-within { - .editor-post-featured-image__actions { + .editor-post-featured-image__actions:not(.editor-post-featured-image__actions-is-requesting-image) { opacity: 1; } } + .editor-post-featured-image__actions.editor-post-featured-image__actions-missing-image { + opacity: 1; + margin-top: $grid-unit-20; + } + .components-drop-zone__content { border-radius: $radius-small; } @@ -72,17 +77,22 @@ } .editor-post-featured-image__actions { - @include reduce-motion("transition"); - bottom: 0; - opacity: 0; // Use opacity instead of visibility so that the buttons remain in the tab order. - padding: $grid-unit-10; - position: absolute; - transition: opacity 50ms ease-out; -} + &:not(.editor-post-featured-image__actions-missing-image) { + @include reduce-motion("transition"); + bottom: 0; + opacity: 0; // Use opacity instead of visibility so that the buttons remain in the tab order. + padding: $grid-unit-10; + position: absolute; + transition: opacity 50ms ease-out; -.editor-post-featured-image__action { - backdrop-filter: blur(16px) saturate(180%); - background: rgba(255, 255, 255, 0.75); - flex-grow: 1; - justify-content: center; + .editor-post-featured-image__action { + backdrop-filter: blur(16px) saturate(180%); + background: rgba(255, 255, 255, 0.75); + } + } + + .editor-post-featured-image__action { + flex-grow: 1; + justify-content: center; + } } From 2028fd8608a853bfa610510666ff0619c3435e1c Mon Sep 17 00:00:00 2001 From: mimi <mimitips@gmail.com> Date: Fri, 15 Nov 2024 21:28:50 +0900 Subject: [PATCH 1595/1908] Update BlockMover Stories and README (#66519) * Update BlockMover stories * Use block settings and provider for Horizontal mode * Remove unwanted changes * Update packages/block-editor/src/components/block-mover/README.md Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> * Update packages/block-editor/src/components/block-mover/stories/index.story.tsx Co-authored-by: Lena Morita <lena@jaguchi.com> * Change .tsx to .js * Add decorators, and descriptions * Fixes README * refactor BlockMover stories for improved structure * remove unnecessary lines in package.json * change Horizontal story to improve rendering * Update packages/block-editor/src/components/block-mover/stories/index.story.js Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> * fix Horizontal decorator * remove trash changes from package.json --------- Co-authored-by: miminari <mimitips@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .../src/components/block-mover/README.md | 23 ++- .../block-mover/stories/index.story.js | 144 +++++++++--------- 2 files changed, 88 insertions(+), 79 deletions(-) diff --git a/packages/block-editor/src/components/block-mover/README.md b/packages/block-editor/src/components/block-mover/README.md index 38520072b4ac86..b781de773ef9f3 100644 --- a/packages/block-editor/src/components/block-mover/README.md +++ b/packages/block-editor/src/components/block-mover/README.md @@ -1,12 +1,10 @@ -# Block mover +# BlockMover -Block movers allow moving blocks inside the editor using up and down buttons. +BlockMover component allows moving blocks inside the editor using up and down buttons. ![Block mover screenshot](https://make.wordpress.org/core/files/2020/08/block-mover-screenshot.png) -## Development guidelines - -### Usage +## Usage Shows the block mover buttons in the block toolbar. @@ -15,13 +13,22 @@ import { BlockMover } from '@wordpress/block-editor'; const MyMover = () => <BlockMover clientIds={ [ clientId ] } />; ``` -### Props +## Props -#### clientIds +### clientIds -Blocks IDs +The IDs of the blocks to move. - Type: `Array` +- Required: Yes + +### hideDragHandle + +If this property is true, the drag handle is hidden. + +- Type: `boolean` +- Required: No +- Default: `false` ## Related components diff --git a/packages/block-editor/src/components/block-mover/stories/index.story.js b/packages/block-editor/src/components/block-mover/stories/index.story.js index de30260563f91e..de6d13c797b4d9 100644 --- a/packages/block-editor/src/components/block-mover/stories/index.story.js +++ b/packages/block-editor/src/components/block-mover/stories/index.story.js @@ -14,6 +14,7 @@ import BlockMover from '../'; import { ExperimentalBlockEditorProvider } from '../../provider'; import { store as blockEditorStore } from '../../../store'; +// For the purpose of this story, we need to register the core blocks samples. registerCoreBlocks(); const blocks = [ // vertical @@ -30,81 +31,82 @@ const blocks = [ ] ), ]; -function Provider( { children } ) { - const wrapperStyle = { margin: '24px', position: 'relative' }; - - return ( - <div style={ wrapperStyle }> +/** + * BlockMover component allows moving blocks inside the editor using up and down buttons. + */ +const meta = { + title: 'BlockEditor/BlockMover', + component: BlockMover, + parameters: { + docs: { canvas: { sourceState: 'shown' } }, + }, + decorators: [ + ( Story ) => ( <ExperimentalBlockEditorProvider value={ blocks }> - { children } + <Toolbar label="Block Mover"> + <Story /> + </Toolbar> </ExperimentalBlockEditorProvider> - </div> - ); -} - -function BlockMoverStory() { - const { updateBlockListSettings } = useDispatch( blockEditorStore ); - - useEffect( () => { - /** - * This shouldn't be needed but unfortunatley - * the layout orientation is not declarative, we need - * to render the blocks to update the block settings in the state. - */ - updateBlockListSettings( blocks[ 1 ].clientId, { - orientation: 'horizontal', - } ); - }, [] ); - - return ( - <div> - <p>The mover by default is vertical</p> - <Toolbar label="Block Mover"> - <BlockMover - clientIds={ - blocks.length - ? [ blocks[ 0 ].innerBlocks[ 1 ].clientId ] - : [] - } - /> - </Toolbar> - - <p style={ { marginTop: 36 } }> - But it can also accommodate horizontal blocks. - </p> - <Toolbar label="Block Mover"> - <BlockMover - clientIds={ - blocks.length - ? [ blocks[ 1 ].innerBlocks[ 1 ].clientId ] - : [] - } - /> - </Toolbar> + ), + ], + argTypes: { + clientIds: { + control: { + type: 'none', + }, + description: 'The client IDs of the blocks to move.', + }, + hideDragHandle: { + control: { + type: 'boolean', + }, + description: 'If this property is true, the drag handle is hidden.', + }, + }, +}; +export default meta; - <p style={ { marginTop: 36 } }>We can also hide the drag handle.</p> - <Toolbar label="Block Mover"> - <BlockMover - clientIds={ - blocks.length - ? [ blocks[ 1 ].innerBlocks[ 0 ].clientId ] - : [] - } - hideDragHandle - /> - </Toolbar> - </div> - ); -} +export const Default = { + args: { + clientIds: [ blocks[ 0 ].innerBlocks[ 1 ].clientId ], + }, +}; -export default { - title: 'BlockEditor/BlockMover', +/** + * This story shows the block mover with horizontal orientation. + * It is necessary to render the blocks to update the block settings in the state. + */ +export const Horizontal = { + decorators: [ + ( Story ) => { + const { updateBlockListSettings } = useDispatch( blockEditorStore ); + useEffect( () => { + /** + * This shouldn't be needed but unfortunately + * the layout orientation is not declarative, we need + * to render the blocks to update the block settings in the state. + */ + updateBlockListSettings( blocks[ 1 ].clientId, { + orientation: 'horizontal', + } ); + }, [] ); + return <Story />; + }, + ], + args: { + clientIds: [ blocks[ 1 ].innerBlocks[ 1 ].clientId ], + }, + parameters: { + docs: { canvas: { sourceState: 'hidden' } }, + }, }; -export const _default = () => { - return ( - <Provider> - <BlockMoverStory /> - </Provider> - ); +/** + * You can hide the drag handle by `hideDragHandle` attribute. + */ +export const HideDragHandle = { + args: { + ...Default.args, + hideDragHandle: true, + }, }; From 865a05834d3af46a6eecd142fe6acda40642756d Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Sat, 16 Nov 2024 04:24:35 +0530 Subject: [PATCH 1596/1908] DimensionControl: Deprecate 36px default size (#66705) * Add the deprecation notice for the DimensionControl for 36px size * Add the size as undefined * Add the deprecation changelog * Update snapshots --------- Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/dimension-control/README.md | 1 + .../src/dimension-control/index.tsx | 8 ++++ .../dimension-control/stories/index.story.tsx | 1 + .../test/__snapshots__/index.test.js.snap | 48 +++++++++---------- .../src/dimension-control/test/index.test.js | 8 +++- 6 files changed, 42 insertions(+), 25 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index dc51518eb32f10..0eb5052c748f10 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Deprecations - `Radio`: Deprecate 36px default size ([#66572](https://github.com/WordPress/gutenberg/pull/66572)). +- `DimensionControl`: Deprecate 36px default size ([#66705](https://github.com/WordPress/gutenberg/pull/66705)). ### Bug Fixes diff --git a/packages/components/src/dimension-control/README.md b/packages/components/src/dimension-control/README.md index 78c1a60275c13a..fd04d99ca4ca93 100644 --- a/packages/components/src/dimension-control/README.md +++ b/packages/components/src/dimension-control/README.md @@ -22,6 +22,7 @@ export default function MyCustomDimensionControl() { return ( <DimensionControl __nextHasNoMarginBottom + __next40pxDefaultSize label={ 'Padding' } icon={ 'desktop' } onChange={ ( value ) => setPaddingSize( value ) } diff --git a/packages/components/src/dimension-control/index.tsx b/packages/components/src/dimension-control/index.tsx index 25880f9b4fdb38..2cc39379ebde0c 100644 --- a/packages/components/src/dimension-control/index.tsx +++ b/packages/components/src/dimension-control/index.tsx @@ -18,6 +18,7 @@ import type { DimensionControlProps, Size } from './types'; import type { SelectControlSingleSelectionProps } from '../select-control/types'; import { ContextSystemProvider } from '../context'; import deprecated from '@wordpress/deprecated'; +import { maybeWarnDeprecated36pxSize } from '../utils/deprecated-36px-size'; const CONTEXT_VALUE = { BaseControl: { @@ -41,6 +42,7 @@ const CONTEXT_VALUE = { * * return ( * <DimensionControl + * __next40pxDefaultSize * __nextHasNoMarginBottom * label={ 'Padding' } * icon={ 'desktop' } @@ -68,6 +70,12 @@ export function DimensionControl( props: DimensionControlProps ) { version: '7.0', } ); + maybeWarnDeprecated36pxSize( { + componentName: 'DimensionControl', + __next40pxDefaultSize, + size: undefined, + } ); + const onChangeSpacingSize: SelectControlSingleSelectionProps[ 'onChange' ] = ( val ) => { const theSize = findSizeBySlug( sizes, val ); diff --git a/packages/components/src/dimension-control/stories/index.story.tsx b/packages/components/src/dimension-control/stories/index.story.tsx index 15a63fcf6ccf6c..61fd0aae4ee768 100644 --- a/packages/components/src/dimension-control/stories/index.story.tsx +++ b/packages/components/src/dimension-control/stories/index.story.tsx @@ -50,6 +50,7 @@ const Template: StoryFn< typeof DimensionControl > = ( args ) => ( export const Default = Template.bind( {} ); Default.args = { __nextHasNoMarginBottom: true, + __next40pxDefaultSize: true, label: 'Please select a size', sizes, }; diff --git a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap index bd2c26d641fe72..fd6cc2df3fcde7 100644 --- a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap +++ b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap @@ -126,12 +126,12 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = ` white-space: nowrap; text-overflow: ellipsis; font-size: 16px; - height: 32px; - min-height: 32px; + height: 40px; + min-height: 40px; padding-top: 0; padding-bottom: 0; - padding-left: 8px; - padding-right: 26px; + padding-left: 12px; + padding-right: 30px; overflow: hidden; } @@ -157,8 +157,8 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = ` } .emotion-21 { - -webkit-padding-end: 8px; - padding-inline-end: 8px; + -webkit-padding-end: 12px; + padding-inline-end: 12px; position: absolute; pointer-events: none; right: 0; @@ -408,12 +408,12 @@ exports[`DimensionControl rendering renders with defaults 1`] = ` white-space: nowrap; text-overflow: ellipsis; font-size: 16px; - height: 32px; - min-height: 32px; + height: 40px; + min-height: 40px; padding-top: 0; padding-bottom: 0; - padding-left: 8px; - padding-right: 26px; + padding-left: 12px; + padding-right: 30px; overflow: hidden; } @@ -439,8 +439,8 @@ exports[`DimensionControl rendering renders with defaults 1`] = ` } .emotion-21 { - -webkit-padding-end: 8px; - padding-inline-end: 8px; + -webkit-padding-end: 12px; + padding-inline-end: 12px; position: absolute; pointer-events: none; right: 0; @@ -700,12 +700,12 @@ exports[`DimensionControl rendering renders with icon and custom icon label 1`] white-space: nowrap; text-overflow: ellipsis; font-size: 16px; - height: 32px; - min-height: 32px; + height: 40px; + min-height: 40px; padding-top: 0; padding-bottom: 0; - padding-left: 8px; - padding-right: 26px; + padding-left: 12px; + padding-right: 30px; overflow: hidden; } @@ -731,8 +731,8 @@ exports[`DimensionControl rendering renders with icon and custom icon label 1`] } .emotion-21 { - -webkit-padding-end: 8px; - padding-inline-end: 8px; + -webkit-padding-end: 12px; + padding-inline-end: 12px; position: absolute; pointer-events: none; right: 0; @@ -1004,12 +1004,12 @@ exports[`DimensionControl rendering renders with icon and default icon label 1`] white-space: nowrap; text-overflow: ellipsis; font-size: 16px; - height: 32px; - min-height: 32px; + height: 40px; + min-height: 40px; padding-top: 0; padding-bottom: 0; - padding-left: 8px; - padding-right: 26px; + padding-left: 12px; + padding-right: 30px; overflow: hidden; } @@ -1035,8 +1035,8 @@ exports[`DimensionControl rendering renders with icon and default icon label 1`] } .emotion-21 { - -webkit-padding-end: 8px; - padding-inline-end: 8px; + -webkit-padding-end: 12px; + padding-inline-end: 12px; position: absolute; pointer-events: none; right: 0; diff --git a/packages/components/src/dimension-control/test/index.test.js b/packages/components/src/dimension-control/test/index.test.js index 14f1c509f70cf9..8f3cb7ea944cd1 100644 --- a/packages/components/src/dimension-control/test/index.test.js +++ b/packages/components/src/dimension-control/test/index.test.js @@ -15,7 +15,13 @@ import { plus } from '@wordpress/icons'; import { DimensionControl as _DimensionControl } from '../'; const DimensionControl = ( props ) => { - return <_DimensionControl { ...props } __nextHasNoMarginBottom />; + return ( + <_DimensionControl + { ...props } + __next40pxDefaultSize + __nextHasNoMarginBottom + /> + ); }; describe( 'DimensionControl', () => { From 49401da8201b8769374bf686588c7556cbd953a6 Mon Sep 17 00:00:00 2001 From: Ankit Kumar Shah <ankit.shah@rtcamp.com> Date: Mon, 18 Nov 2024 09:42:14 +0530 Subject: [PATCH 1597/1908] Layout: show vertical alignment toolbar with allowSwitching enabled (#67022) Co-authored-by: Infinite-Null <ankitkumarshah@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: Mayank-Tripathi32 <mayanktripathi32@git.wordpress.org> Co-authored-by: metropoliscreative <metropolis_john@git.wordpress.org> --- packages/block-editor/src/layouts/flex.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/block-editor/src/layouts/flex.js b/packages/block-editor/src/layouts/flex.js index 81718449695651..c67ebc17a785d4 100644 --- a/packages/block-editor/src/layouts/flex.js +++ b/packages/block-editor/src/layouts/flex.js @@ -94,9 +94,6 @@ export default { onChange, layoutBlockSupport, } ) { - if ( layoutBlockSupport?.allowSwitching ) { - return null; - } const { allowVerticalAlignment = true } = layoutBlockSupport; return ( <BlockControls group="block" __experimentalShareWithChildBlocks> From 5d0d155d1e6b20dacd2581fb590811297be9493a Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:29:32 +1100 Subject: [PATCH 1598/1908] Site Editor: remove redundant style-edit route (#67057) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> --- .../components/site-editor-routes/README.md | 4 +-- .../components/site-editor-routes/index.js | 2 -- .../site-editor-routes/styles-edit.js | 26 ------------------- 3 files changed, 2 insertions(+), 30 deletions(-) delete mode 100644 packages/edit-site/src/components/site-editor-routes/styles-edit.js diff --git a/packages/edit-site/src/components/site-editor-routes/README.md b/packages/edit-site/src/components/site-editor-routes/README.md index 64121c8bd9a6b5..06e2cfdd331f1b 100644 --- a/packages/edit-site/src/components/site-editor-routes/README.md +++ b/packages/edit-site/src/components/site-editor-routes/README.md @@ -2,7 +2,7 @@ ## Areas -When `canvasMode` is not `edit`, the areas avaliable to use are: +When `canvasMode` is not `edit`, the areas available to use are: | Area | Non-mobile viewport | Mobile viewport | | --- | --- | --- | @@ -12,7 +12,7 @@ When `canvasMode` is not `edit`, the areas avaliable to use are: | `edit` | Rendered if provided. | Not rendered. | | `mobile` | Not rendered | Rendered as full-screen, if provided. | -When `canvasMode` is `edit`, the areas avaliable to use are: +When `canvasMode` is `edit`, the areas available to use are: | Area | Non-mobile viewport | Mobile viewport | | --- | --- | --- | diff --git a/packages/edit-site/src/components/site-editor-routes/index.js b/packages/edit-site/src/components/site-editor-routes/index.js index ddc37b353885c1..4887436dc2ed16 100644 --- a/packages/edit-site/src/components/site-editor-routes/index.js +++ b/packages/edit-site/src/components/site-editor-routes/index.js @@ -15,7 +15,6 @@ import { navigationViewRoute } from './navigation-view'; import { navigationEditRoute } from './navigation-edit'; import { navigationItemEditRoute } from './navigation-item-edit'; import { navigationItemViewRoute } from './navigation-item-view'; -import { stylesEditRoute } from './styles-edit'; import { stylesViewRoute } from './styles-view'; import { patternsEditRoute } from './patterns-edit'; import { patternsViewRoute } from './patterns-view'; @@ -40,7 +39,6 @@ const routes = [ patternsViewRoute, patternsEditRoute, stylesViewRoute, - stylesEditRoute, navigationItemViewRoute, navigationItemEditRoute, navigationViewRoute, diff --git a/packages/edit-site/src/components/site-editor-routes/styles-edit.js b/packages/edit-site/src/components/site-editor-routes/styles-edit.js deleted file mode 100644 index e8225a8f526ebd..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/styles-edit.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Internal dependencies - */ -import Editor from '../editor'; -import SidebarNavigationScreenGlobalStyles from '../sidebar-navigation-screen-global-styles'; -import GlobalStylesUIWrapper from '../sidebar-global-styles-wrapper'; - -export const stylesEditRoute = { - name: 'styles-edit', - match: ( params ) => { - return ( - params.path && - params.path.startsWith( '/wp_global_styles' ) && - params.canvas !== 'edit' - ); - }, - areas: { - content: <GlobalStylesUIWrapper />, - sidebar: <SidebarNavigationScreenGlobalStyles backPath={ {} } />, - preview: <Editor />, - mobile: <Editor />, - }, - widths: { - content: 380, - }, -}; From 134e4b48cd2872a2c9bc04f7c97d666c4ca1d7c9 Mon Sep 17 00:00:00 2001 From: tellthemachines <tellthemachines@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:55:10 +1100 Subject: [PATCH 1599/1908] Fix dropping media from inserter into Cover block (#67056) Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/components/media-placeholder/index.js | 60 ++++++++++--------- .../block-library/src/cover/edit/index.js | 2 +- packages/block-library/src/cover/shared.js | 20 +++---- 3 files changed, 43 insertions(+), 39 deletions(-) diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index 2f1a47be2f5a6e..e7b6c836468f02 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -239,7 +239,7 @@ export function MediaPlaceholder( { ( block.name === 'core/image' || block.name === 'core/audio' || block.name === 'core/video' ) && - block.attributes.url + ( block.attributes.url || block.attributes.src ) ? [ block ] : recursivelyFindMediaFromBlocks( block.innerBlocks ) ); @@ -252,33 +252,37 @@ export function MediaPlaceholder( { } const uploadedMediaList = await Promise.all( - mediaBlocks.map( ( block ) => - block.attributes.id - ? block.attributes - : new Promise( ( resolve, reject ) => { - window - .fetch( block.attributes.url ) - .then( ( response ) => response.blob() ) - .then( ( blob ) => - mediaUpload( { - filesList: [ blob ], - additionalData: { - title: block.attributes.title, - alt_text: block.attributes.alt, - caption: block.attributes.caption, - }, - onFileChange: ( [ media ] ) => { - if ( media.id ) { - resolve( media ); - } - }, - allowedTypes, - onError: reject, - } ) - ) - .catch( () => resolve( block.attributes.url ) ); - } ) - ) + mediaBlocks.map( ( block ) => { + const blockType = block.name.split( '/' )[ 1 ]; + if ( block.attributes.id ) { + block.attributes.type = blockType; + return block.attributes; + } + return new Promise( ( resolve, reject ) => { + window + .fetch( block.attributes.url ) + .then( ( response ) => response.blob() ) + .then( ( blob ) => + mediaUpload( { + filesList: [ blob ], + additionalData: { + title: block.attributes.title, + alt_text: block.attributes.alt, + caption: block.attributes.caption, + type: blockType, + }, + onFileChange: ( [ media ] ) => { + if ( media.id ) { + resolve( media ); + } + }, + allowedTypes, + onError: reject, + } ) + ) + .catch( () => resolve( block.attributes.url ) ); + } ); + } ) ).catch( ( err ) => onError( err ) ); if ( multiple ) { diff --git a/packages/block-library/src/cover/edit/index.js b/packages/block-library/src/cover/edit/index.js index 1c86d953bc0bab..3ad7039b558924 100644 --- a/packages/block-library/src/cover/edit/index.js +++ b/packages/block-library/src/cover/edit/index.js @@ -201,7 +201,7 @@ function CoverEdit( { averageBackgroundColor ); - if ( backgroundType === IMAGE_BACKGROUND_TYPE && mediaAttributes.id ) { + if ( backgroundType === IMAGE_BACKGROUND_TYPE && mediaAttributes?.id ) { const { imageDefaultSize } = getSettings(); // Try to use the previous selected image size if it's available diff --git a/packages/block-library/src/cover/shared.js b/packages/block-library/src/cover/shared.js index 37390354a37d63..7628300cbf8cff 100644 --- a/packages/block-library/src/cover/shared.js +++ b/packages/block-library/src/cover/shared.js @@ -35,7 +35,7 @@ export function dimRatioToClass( ratio ) { } export function attributesFromMedia( media ) { - if ( ! media || ! media.url ) { + if ( ! media || ( ! media.url && ! media.src ) ) { return { url: undefined, id: undefined, @@ -52,23 +52,23 @@ export function attributesFromMedia( media ) { if ( media.media_type === IMAGE_BACKGROUND_TYPE ) { mediaType = IMAGE_BACKGROUND_TYPE; } else { - // only images and videos are accepted so if the media_type is not an image we can assume it is a video. + // Only images and videos are accepted so if the media_type is not an image we can assume it is a video. // Videos contain the media type of 'file' in the object returned from the rest api. mediaType = VIDEO_BACKGROUND_TYPE; } - } else { // For media selections originated from existing files in the media library. - if ( - media.type !== IMAGE_BACKGROUND_TYPE && - media.type !== VIDEO_BACKGROUND_TYPE - ) { - return; - } + } else if ( + media.type && + ( media.type === IMAGE_BACKGROUND_TYPE || + media.type === VIDEO_BACKGROUND_TYPE ) + ) { mediaType = media.type; + } else { + return; } return { - url: media.url, + url: media.url || media.src, id: media.id, alt: media?.alt, backgroundType: mediaType, From 590cf87a8df6d7faf0dd909536f6c3a24ee4987d Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Sat, 16 Nov 2024 18:02:57 +0000 Subject: [PATCH 1600/1908] Update changelog files --- packages/a11y/CHANGELOG.md | 2 ++ packages/a11y/package.json | 2 +- packages/annotations/CHANGELOG.md | 2 ++ packages/annotations/package.json | 2 +- packages/api-fetch/CHANGELOG.md | 2 ++ packages/api-fetch/package.json | 2 +- packages/autop/CHANGELOG.md | 2 ++ packages/autop/package.json | 2 +- packages/babel-plugin-import-jsx-pragma/CHANGELOG.md | 2 ++ packages/babel-plugin-import-jsx-pragma/package.json | 2 +- packages/babel-plugin-makepot/CHANGELOG.md | 2 ++ packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/CHANGELOG.md | 2 ++ packages/babel-preset-default/package.json | 2 +- packages/base-styles/CHANGELOG.md | 2 ++ packages/base-styles/package.json | 2 +- packages/blob/CHANGELOG.md | 2 ++ packages/blob/package.json | 2 +- packages/block-directory/CHANGELOG.md | 2 ++ packages/block-directory/package.json | 2 +- packages/block-editor/CHANGELOG.md | 2 ++ packages/block-editor/package.json | 2 +- packages/block-library/CHANGELOG.md | 2 ++ packages/block-library/package.json | 2 +- packages/block-serialization-default-parser/CHANGELOG.md | 2 ++ packages/block-serialization-default-parser/package.json | 2 +- packages/block-serialization-spec-parser/CHANGELOG.md | 2 ++ packages/block-serialization-spec-parser/package.json | 2 +- packages/blocks/CHANGELOG.md | 2 ++ packages/blocks/package.json | 2 +- packages/browserslist-config/CHANGELOG.md | 2 ++ packages/browserslist-config/package.json | 2 +- packages/commands/CHANGELOG.md | 2 ++ packages/commands/package.json | 2 +- packages/components/CHANGELOG.md | 2 ++ packages/components/package.json | 2 +- packages/compose/CHANGELOG.md | 2 ++ packages/compose/package.json | 2 +- packages/core-commands/CHANGELOG.md | 2 ++ packages/core-commands/package.json | 2 +- packages/core-data/CHANGELOG.md | 2 ++ packages/core-data/package.json | 2 +- packages/create-block-interactive-template/package.json | 2 +- packages/create-block-tutorial-template/CHANGELOG.md | 2 ++ packages/create-block-tutorial-template/package.json | 2 +- packages/create-block/CHANGELOG.md | 2 ++ packages/create-block/package.json | 2 +- packages/customize-widgets/CHANGELOG.md | 2 ++ packages/customize-widgets/package.json | 2 +- packages/data-controls/CHANGELOG.md | 2 ++ packages/data-controls/package.json | 2 +- packages/data/CHANGELOG.md | 2 ++ packages/data/package.json | 2 +- packages/dataviews/CHANGELOG.md | 2 ++ packages/dataviews/package.json | 2 +- packages/date/CHANGELOG.md | 2 ++ packages/date/package.json | 2 +- packages/dependency-extraction-webpack-plugin/CHANGELOG.md | 2 ++ packages/dependency-extraction-webpack-plugin/package.json | 2 +- packages/deprecated/CHANGELOG.md | 2 ++ packages/deprecated/package.json | 2 +- packages/docgen/CHANGELOG.md | 2 ++ packages/docgen/package.json | 2 +- packages/dom-ready/CHANGELOG.md | 2 ++ packages/dom-ready/package.json | 2 +- packages/dom/CHANGELOG.md | 2 ++ packages/dom/package.json | 2 +- packages/e2e-test-utils-playwright/CHANGELOG.md | 2 ++ packages/e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/CHANGELOG.md | 2 ++ packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/CHANGELOG.md | 2 ++ packages/e2e-tests/package.json | 2 +- packages/edit-post/CHANGELOG.md | 2 ++ packages/edit-post/package.json | 2 +- packages/edit-site/CHANGELOG.md | 2 ++ packages/edit-site/package.json | 2 +- packages/edit-widgets/CHANGELOG.md | 2 ++ packages/edit-widgets/package.json | 2 +- packages/editor/CHANGELOG.md | 2 ++ packages/editor/package.json | 2 +- packages/element/CHANGELOG.md | 2 ++ packages/element/package.json | 2 +- packages/env/CHANGELOG.md | 2 ++ packages/env/package.json | 2 +- packages/escape-html/CHANGELOG.md | 2 ++ packages/escape-html/package.json | 2 +- packages/eslint-plugin/CHANGELOG.md | 2 ++ packages/eslint-plugin/package.json | 2 +- packages/fields/CHANGELOG.md | 2 ++ packages/fields/package.json | 2 +- packages/format-library/CHANGELOG.md | 2 ++ packages/format-library/package.json | 2 +- packages/hooks/CHANGELOG.md | 2 ++ packages/hooks/package.json | 2 +- packages/html-entities/CHANGELOG.md | 2 ++ packages/html-entities/package.json | 2 +- packages/i18n/CHANGELOG.md | 2 ++ packages/i18n/package.json | 2 +- packages/icons/CHANGELOG.md | 2 ++ packages/icons/package.json | 2 +- packages/interactivity-router/CHANGELOG.md | 2 ++ packages/interactivity-router/package.json | 2 +- packages/interactivity/CHANGELOG.md | 2 ++ packages/interactivity/package.json | 2 +- packages/interface/CHANGELOG.md | 2 ++ packages/interface/package.json | 2 +- packages/is-shallow-equal/CHANGELOG.md | 2 ++ packages/is-shallow-equal/package.json | 2 +- packages/jest-console/CHANGELOG.md | 2 ++ packages/jest-console/package.json | 2 +- packages/jest-preset-default/CHANGELOG.md | 2 ++ packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/CHANGELOG.md | 2 ++ packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/CHANGELOG.md | 2 ++ packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/CHANGELOG.md | 2 ++ packages/keycodes/package.json | 2 +- packages/lazy-import/CHANGELOG.md | 2 ++ packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/CHANGELOG.md | 2 ++ packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/CHANGELOG.md | 2 ++ packages/media-utils/package.json | 2 +- packages/notices/CHANGELOG.md | 2 ++ packages/notices/package.json | 2 +- packages/npm-package-json-lint-config/CHANGELOG.md | 2 ++ packages/npm-package-json-lint-config/package.json | 2 +- packages/nux/CHANGELOG.md | 2 ++ packages/nux/package.json | 2 +- packages/patterns/CHANGELOG.md | 2 ++ packages/patterns/package.json | 2 +- packages/plugins/CHANGELOG.md | 2 ++ packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/CHANGELOG.md | 2 ++ packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/CHANGELOG.md | 2 ++ packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/CHANGELOG.md | 2 ++ packages/preferences-persistence/package.json | 2 +- packages/preferences/CHANGELOG.md | 2 ++ packages/preferences/package.json | 2 +- packages/prettier-config/CHANGELOG.md | 2 ++ packages/prettier-config/package.json | 2 +- packages/primitives/CHANGELOG.md | 2 ++ packages/primitives/package.json | 2 +- packages/priority-queue/CHANGELOG.md | 2 ++ packages/priority-queue/package.json | 2 +- packages/private-apis/CHANGELOG.md | 2 ++ packages/private-apis/package.json | 2 +- packages/project-management-automation/CHANGELOG.md | 2 ++ packages/project-management-automation/package.json | 2 +- packages/react-i18n/CHANGELOG.md | 2 ++ packages/react-i18n/package.json | 2 +- packages/readable-js-assets-webpack-plugin/CHANGELOG.md | 2 ++ packages/readable-js-assets-webpack-plugin/package.json | 2 +- packages/redux-routine/CHANGELOG.md | 2 ++ packages/redux-routine/package.json | 2 +- packages/reusable-blocks/CHANGELOG.md | 2 ++ packages/reusable-blocks/package.json | 2 +- packages/rich-text/CHANGELOG.md | 2 ++ packages/rich-text/package.json | 2 +- packages/router/CHANGELOG.md | 2 ++ packages/router/package.json | 2 +- packages/scripts/CHANGELOG.md | 2 ++ packages/scripts/package.json | 2 +- packages/server-side-render/CHANGELOG.md | 2 ++ packages/server-side-render/package.json | 2 +- packages/shortcode/CHANGELOG.md | 2 ++ packages/shortcode/package.json | 2 +- packages/style-engine/CHANGELOG.md | 2 ++ packages/style-engine/package.json | 2 +- packages/stylelint-config/CHANGELOG.md | 2 ++ packages/stylelint-config/package.json | 2 +- packages/sync/CHANGELOG.md | 2 ++ packages/sync/package.json | 2 +- packages/token-list/CHANGELOG.md | 2 ++ packages/token-list/package.json | 2 +- packages/undo-manager/CHANGELOG.md | 2 ++ packages/undo-manager/package.json | 2 +- packages/url/CHANGELOG.md | 2 ++ packages/url/package.json | 2 +- packages/viewport/CHANGELOG.md | 2 ++ packages/viewport/package.json | 2 +- packages/warning/CHANGELOG.md | 2 ++ packages/warning/package.json | 2 +- packages/widgets/CHANGELOG.md | 2 ++ packages/widgets/package.json | 2 +- packages/wordcount/CHANGELOG.md | 2 ++ packages/wordcount/package.json | 2 +- 191 files changed, 286 insertions(+), 96 deletions(-) diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index 5e90577e9155ab..dfd1e62906f9f4 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 008bd9088e0778..d7e3018a9b6772 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/CHANGELOG.md b/packages/annotations/CHANGELOG.md index 0618f4962f5eb5..07e9267e5b04c5 100644 --- a/packages/annotations/CHANGELOG.md +++ b/packages/annotations/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.12.0 (2024-11-16) + ## 3.11.0 (2024-10-30) ## 3.10.0 (2024-10-16) diff --git a/packages/annotations/package.json b/packages/annotations/package.json index b1d6d210807a87..d3053d4ab18d7f 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.11.0", + "version": "3.12.0-prerelease", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/CHANGELOG.md b/packages/api-fetch/CHANGELOG.md index 8d3faea535faf3..e2ba79548592ec 100644 --- a/packages/api-fetch/CHANGELOG.md +++ b/packages/api-fetch/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.12.0 (2024-11-16) + ## 7.11.0 (2024-10-30) ## 7.10.0 (2024-10-16) diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 7d5b8dfd588897..890c8890b3edb3 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.11.0", + "version": "7.12.0-prerelease", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/CHANGELOG.md b/packages/autop/CHANGELOG.md index 9534b183d6ebb1..dd9879ca23b746 100644 --- a/packages/autop/CHANGELOG.md +++ b/packages/autop/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/autop/package.json b/packages/autop/package.json index 336dda06edfe2c..d0588584221282 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md index 87bc412fd90eb3..38a36491fe9a81 100644 --- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md +++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index d9b565b4e27ec0..58115a13f9edf7 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/CHANGELOG.md b/packages/babel-plugin-makepot/CHANGELOG.md index f643a9304c68ab..1e22ee8b4eabb4 100644 --- a/packages/babel-plugin-makepot/CHANGELOG.md +++ b/packages/babel-plugin-makepot/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.12.0 (2024-11-16) + ## 6.11.0 (2024-10-30) ## 6.10.0 (2024-10-16) diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index cf04d3dc72e409..47cfb6a388ca1e 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.11.0", + "version": "6.12.0-prerelease", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index d6eef13b90d456..8cce12417d2e26 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.12.0 (2024-11-16) + ## 8.11.0 (2024-10-30) ## 8.10.0 (2024-10-16) diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 2f727d1886425d..09f099221d7da5 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.11.0", + "version": "8.12.0-prerelease", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/CHANGELOG.md b/packages/base-styles/CHANGELOG.md index 61ff1100ac6453..67fdcfa2424530 100644 --- a/packages/base-styles/CHANGELOG.md +++ b/packages/base-styles/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index 7246dc83eaf4c6..fda3a8c5c7d34d 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md index 660c60776c7bd1..2edfa51064106f 100644 --- a/packages/blob/CHANGELOG.md +++ b/packages/blob/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/blob/package.json b/packages/blob/package.json index 0dc01ac7198f59..376399068dd6f5 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/CHANGELOG.md b/packages/block-directory/CHANGELOG.md index 53636f34dad586..37b6b6b3ece40a 100644 --- a/packages/block-directory/CHANGELOG.md +++ b/packages/block-directory/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 18a40824aa4754..ab2c5fb00b3eba 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 6755c4ec83f215..3c1e63c75c75ff 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.7.0 (2024-11-16) + ## 14.6.0 (2024-10-30) ## 14.5.0 (2024-10-16) diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index b4672bc57690eb..06e4b2402e214b 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.6.0", + "version": "14.7.0-prerelease", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index 4b5cf59f81910d..cab58f72ff70ee 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.12.0 (2024-11-16) + ## 9.11.0 (2024-10-30) ## 9.10.0 (2024-10-16) diff --git a/packages/block-library/package.json b/packages/block-library/package.json index b196e53e5cd0f9..29312f1c842adb 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.11.0", + "version": "9.12.0-prerelease", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/CHANGELOG.md b/packages/block-serialization-default-parser/CHANGELOG.md index 5911f22795d463..5542b052e1037a 100644 --- a/packages/block-serialization-default-parser/CHANGELOG.md +++ b/packages/block-serialization-default-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 010132ac971db1..bcaa7261f0f0e7 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/CHANGELOG.md b/packages/block-serialization-spec-parser/CHANGELOG.md index 1833dff1e52c83..3ff70ac28cc19b 100644 --- a/packages/block-serialization-spec-parser/CHANGELOG.md +++ b/packages/block-serialization-spec-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index d430d2afeebf5a..57a8b06a7f1551 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 54fc6f77a7427d..216918b44c0b80 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.1.0 (2024-11-16) + ## 14.0.0 (2024-10-30) ### Breaking changes diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 42890e9b7d56bc..92439f60b06f5d 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "14.0.0", + "version": "14.1.0-prerelease", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/CHANGELOG.md b/packages/browserslist-config/CHANGELOG.md index 1ef626d40ef832..64a49c04621840 100644 --- a/packages/browserslist-config/CHANGELOG.md +++ b/packages/browserslist-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.12.0 (2024-11-16) + ## 6.11.0 (2024-10-30) ## 6.10.0 (2024-10-16) diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 65bc5231f0651b..d04104e3ace409 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.11.0", + "version": "6.12.0-prerelease", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/CHANGELOG.md b/packages/commands/CHANGELOG.md index 2ec9f745b774fd..e1e995f9710aeb 100644 --- a/packages/commands/CHANGELOG.md +++ b/packages/commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.12.0 (2024-11-16) + ## 1.11.0 (2024-10-30) ## 1.10.0 (2024-10-16) diff --git a/packages/commands/package.json b/packages/commands/package.json index cebf3237a00d75..9b410dea657d3e 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.11.0", + "version": "1.12.0-prerelease", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 0eb5052c748f10..c9da13035447f9 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 28.12.0 (2024-11-16) + ### Deprecations - `Radio`: Deprecate 36px default size ([#66572](https://github.com/WordPress/gutenberg/pull/66572)). diff --git a/packages/components/package.json b/packages/components/package.json index 6871511cf5b1e5..512d2a61fde128 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.11.0", + "version": "28.12.0-prerelease", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index 8f8bedfde15d4a..897ea34a88ae7f 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.12.0 (2024-11-16) + ## 7.11.0 (2024-10-30) ## 7.10.0 (2024-10-16) diff --git a/packages/compose/package.json b/packages/compose/package.json index 68b00b24298d87..8ec086556c37ac 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.11.0", + "version": "7.12.0-prerelease", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/CHANGELOG.md b/packages/core-commands/CHANGELOG.md index b98e0c55e24ff5..8928305ce32e57 100644 --- a/packages/core-commands/CHANGELOG.md +++ b/packages/core-commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.12.0 (2024-11-16) + ## 1.11.0 (2024-10-30) ## 1.10.0 (2024-10-16) diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index db2fb900865c80..0cac600b59ad7e 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.11.0", + "version": "1.12.0-prerelease", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md index 31b44fa32dd0a4..d2744383594baa 100644 --- a/packages/core-data/CHANGELOG.md +++ b/packages/core-data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.12.0 (2024-11-16) + ## 7.11.0 (2024-10-30) ## 7.10.0 (2024-10-16) diff --git a/packages/core-data/package.json b/packages/core-data/package.json index a7216e931a70ca..d35e831855cf3e 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.11.0", + "version": "7.12.0-prerelease", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index bd34bed4d2e256..14ee84510d777c 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.11.0", + "version": "2.12.0-prerelease", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/CHANGELOG.md b/packages/create-block-tutorial-template/CHANGELOG.md index dd043522c27a6b..9a9e8e8d7b1ab6 100644 --- a/packages/create-block-tutorial-template/CHANGELOG.md +++ b/packages/create-block-tutorial-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index c2ea39fad8ba74..b867e84b1a3833 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index c961882082541c..075386562f3841 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.55.0 (2024-11-16) + ## 4.54.0 (2024-10-30) ### Enhancement diff --git a/packages/create-block/package.json b/packages/create-block/package.json index dbb8e56ea72151..a15d4600dbabdd 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.54.0", + "version": "4.55.0-prerelease", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/CHANGELOG.md b/packages/customize-widgets/CHANGELOG.md index b36ed481749ea9..41c9f2257f0a4d 100644 --- a/packages/customize-widgets/CHANGELOG.md +++ b/packages/customize-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 41b3a7bd463aa3..c9a637e90cbf12 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/CHANGELOG.md b/packages/data-controls/CHANGELOG.md index c536d850f8c733..5b5c2e179f8bd3 100644 --- a/packages/data-controls/CHANGELOG.md +++ b/packages/data-controls/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index e4898ff1d0e1ab..c47041b37af0cf 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index 9ceb1521e6cd6d..b38831dd38839f 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -6,6 +6,8 @@ - Upgrade `redux` dependency to `^5.0.1` ([#66966](https://github.com/WordPress/gutenberg/pull/66966)) +## 10.12.0 (2024-11-16)>>>>>>> 854d8c7a61 (Update changelog files) + ## 10.11.0 (2024-10-30) ## 10.10.0 (2024-10-16) diff --git a/packages/data/package.json b/packages/data/package.json index 1117a8373ff121..a1fa3b0f375c3a 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.11.0", + "version": "10.12.0-prerelease", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index a236902a06b224..7fdcdf2808e812 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -6,6 +6,8 @@ - Fix focus loss when removing all filters or resetting ([#67003](https://github.com/WordPress/gutenberg/pull/67003)). +## 4.8.0 (2024-11-16) + ## 4.7.0 (2024-10-30) ## 4.6.0 (2024-10-16) diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index df30fea1a1c714..272fa016c2f604 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.7.0", + "version": "4.8.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md index 1d0508bd5325ad..a385b61dc17281 100644 --- a/packages/date/CHANGELOG.md +++ b/packages/date/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/date/package.json b/packages/date/package.json index d67c1dc527caee..d25f75bf87b7ca 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index 080234c319e477..ee79a75513b996 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.12.0 (2024-11-16) + ## 6.11.0 (2024-10-30) ## 6.10.0 (2024-10-16) diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index cb7a4e60bf015d..9af418b5787e28 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.11.0", + "version": "6.12.0-prerelease", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/CHANGELOG.md b/packages/deprecated/CHANGELOG.md index 5ba83861f7cd3d..861aaa9ad69f25 100644 --- a/packages/deprecated/CHANGELOG.md +++ b/packages/deprecated/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 64ffc6cd30b251..7e083f88d6a0fb 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/CHANGELOG.md b/packages/docgen/CHANGELOG.md index b7374d6f921cb4..7c92855715e325 100644 --- a/packages/docgen/CHANGELOG.md +++ b/packages/docgen/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.12.0 (2024-11-16) + ## 2.11.0 (2024-10-30) ## 2.10.0 (2024-10-16) diff --git a/packages/docgen/package.json b/packages/docgen/package.json index be73d0625b63ed..03672c045f4e77 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.11.0", + "version": "2.12.0-prerelease", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/CHANGELOG.md b/packages/dom-ready/CHANGELOG.md index ffdaeff6e892cf..2b6647faa8332b 100644 --- a/packages/dom-ready/CHANGELOG.md +++ b/packages/dom-ready/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 6e7986c4965dc6..2480e36704fb2b 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/CHANGELOG.md b/packages/dom/CHANGELOG.md index b868abb474e62f..f44165f23fd515 100644 --- a/packages/dom/CHANGELOG.md +++ b/packages/dom/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/dom/package.json b/packages/dom/package.json index 97576e9a22e0ff..f7bb5001e37b57 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/CHANGELOG.md b/packages/e2e-test-utils-playwright/CHANGELOG.md index cbe574c55790a0..968963de3b79d8 100644 --- a/packages/e2e-test-utils-playwright/CHANGELOG.md +++ b/packages/e2e-test-utils-playwright/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.12.0 (2024-11-16) + ## 1.11.0 (2024-10-30) ## 1.10.0 (2024-10-16) diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 8a2703bfdec54d..7b3070e3971b8d 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.11.0", + "version": "1.12.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index 137b1ba872dc54..1974f72e3fb215 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 11.12.0 (2024-11-16) + ## 11.11.0 (2024-10-30) ## 11.10.0 (2024-10-16) diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index 2ff76b73ed2fbf..562d54181644fe 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.11.0", + "version": "11.12.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md index 610a2bb9697452..e6f405a0d21115 100644 --- a/packages/e2e-tests/CHANGELOG.md +++ b/packages/e2e-tests/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.12.0 (2024-11-16) + ## 8.11.0 (2024-10-30) ## 8.10.0 (2024-10-16) diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index cceaa6210a2dd9..d950e8cf5ac7f0 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.11.0", + "version": "8.12.0-prerelease", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index 48a101b543821e..56f37b13ae6225 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.12.0 (2024-11-16) + ## 8.11.0 (2024-10-30) ## 8.10.0 (2024-10-16) diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 1b28c1d5f31aa6..550a378d5409fb 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.11.0", + "version": "8.12.0-prerelease", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/CHANGELOG.md b/packages/edit-site/CHANGELOG.md index 7efa4f6c5b9d45..0c90c024b0cd99 100644 --- a/packages/edit-site/CHANGELOG.md +++ b/packages/edit-site/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.12.0 (2024-11-16) + ## 6.11.0 (2024-10-30) ## 6.10.0 (2024-10-16) diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 41bf39c1e08332..41ddffdc7b0cc7 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.11.0", + "version": "6.12.0-prerelease", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/CHANGELOG.md b/packages/edit-widgets/CHANGELOG.md index 316648bf952585..22d109562d768c 100644 --- a/packages/edit-widgets/CHANGELOG.md +++ b/packages/edit-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.12.0 (2024-11-16) + ## 6.11.0 (2024-10-30) ## 6.10.0 (2024-10-16) diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 331dbc742dbc8c..24f5307b66c621 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.11.0", + "version": "6.12.0-prerelease", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index a3980bf4aead7a..37f46d1d74ccb5 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.12.0 (2024-11-16) + ## 14.11.0 (2024-10-30) ### Bug Fixes diff --git a/packages/editor/package.json b/packages/editor/package.json index 98e0c6d2255b74..0200b15b34364b 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.11.0", + "version": "14.12.0-prerelease", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/CHANGELOG.md b/packages/element/CHANGELOG.md index cf73e03c74f6a8..00eccb7e5ec532 100644 --- a/packages/element/CHANGELOG.md +++ b/packages/element/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.12.0 (2024-11-16) + ## 6.11.0 (2024-10-30) ## 6.10.0 (2024-10-16) diff --git a/packages/element/package.json b/packages/element/package.json index 4a196255971cfb..233cf7e0942392 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.11.0", + "version": "6.12.0-prerelease", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md index c8b49abebfaaa9..181adb034b6b19 100644 --- a/packages/env/CHANGELOG.md +++ b/packages/env/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.12.0 (2024-11-16) + ## 10.11.0 (2024-10-30) ## 10.10.0 (2024-10-16) diff --git a/packages/env/package.json b/packages/env/package.json index a03004abb83283..c13b917fb9a94c 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.11.0", + "version": "10.12.0-prerelease", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/CHANGELOG.md b/packages/escape-html/CHANGELOG.md index f92f40cce1a8cf..40ad50dc4997d8 100644 --- a/packages/escape-html/CHANGELOG.md +++ b/packages/escape-html/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.12.0 (2024-11-16) + ## 3.11.0 (2024-10-30) ## 3.10.0 (2024-10-16) diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 135876460bd05e..6ad428a0418280 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.11.0", + "version": "3.12.0-prerelease", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 3f753fb9b6b8b0..75a8828629b85d 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 21.5.0 (2024-11-16) + ## 21.4.0 (2024-10-30) ## 21.3.0 (2024-10-16) diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 8e2d3e2c97e2bf..e5b444e3890a6e 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "21.4.0", + "version": "21.5.0-prerelease", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/fields/CHANGELOG.md b/packages/fields/CHANGELOG.md index 6f2bf69b653585..a2eba51228fbdd 100644 --- a/packages/fields/CHANGELOG.md +++ b/packages/fields/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.4.0 (2024-11-16) + ## 0.3.0 (2024-10-30) ## 0.2.0 (2024-10-16) diff --git a/packages/fields/package.json b/packages/fields/package.json index cee1060223767a..81de6f1f4b61a9 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/fields", - "version": "0.3.0", + "version": "0.4.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/CHANGELOG.md b/packages/format-library/CHANGELOG.md index f44865c4325e23..257b13656210b0 100644 --- a/packages/format-library/CHANGELOG.md +++ b/packages/format-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/format-library/package.json b/packages/format-library/package.json index 41852910ff5389..8d3c6fb0d18199 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/CHANGELOG.md b/packages/hooks/CHANGELOG.md index 284fa3c5098904..be3f8c7cf6b415 100644 --- a/packages/hooks/CHANGELOG.md +++ b/packages/hooks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 857cb24a877468..c9af44c8dc5d66 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/CHANGELOG.md b/packages/html-entities/CHANGELOG.md index e2d20a85313008..bcba1ced9d91c7 100644 --- a/packages/html-entities/CHANGELOG.md +++ b/packages/html-entities/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 4ecab2056c9c3a..3f99a67512569d 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index 045589f3d7a3c4..fd5f8e1003e326 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 53e81b64a65349..9182351622f5d7 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index 0649fe97ca5a46..484b26e96c90d9 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.12.0 (2024-11-16) + ## 10.11.0 (2024-10-30) ## 10.10.0 (2024-10-16) diff --git a/packages/icons/package.json b/packages/icons/package.json index 895f2e184b4e48..5d5aa56611cad6 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.11.0", + "version": "10.12.0-prerelease", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/CHANGELOG.md b/packages/interactivity-router/CHANGELOG.md index fee7d90751ad5b..ed23e6c73dea4e 100644 --- a/packages/interactivity-router/CHANGELOG.md +++ b/packages/interactivity-router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.12.0 (2024-11-16) + ## 2.11.0 (2024-10-30) ## 2.10.0 (2024-10-16) diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 378ddda56ee76b..8baa41d289871d 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.11.0", + "version": "2.12.0-prerelease", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 6963ed57a48aed..8167177b663d43 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.12.0 (2024-11-16) + ### Bug Fixes - Fix property modification from inherited context two or more levels above ([#66872](https://github.com/WordPress/gutenberg/pull/66872)). diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index c9edd586bc9959..9a32fefec323b3 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.11.0", + "version": "6.12.0-prerelease", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index 67cb692f877098..aa1f96414d46b1 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.1.0 (2024-11-16) + ## 8.0.0 (2024-10-30) ### Breaking Changes diff --git a/packages/interface/package.json b/packages/interface/package.json index f6a7952cb0d051..4f5bf64fea3c34 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "8.0.0", + "version": "8.1.0-prerelease", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/CHANGELOG.md b/packages/is-shallow-equal/CHANGELOG.md index 5dee7a281357a2..ea56df508bdbdf 100644 --- a/packages/is-shallow-equal/CHANGELOG.md +++ b/packages/is-shallow-equal/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 7dafdea88e7a4f..e840fc4be82882 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/CHANGELOG.md b/packages/jest-console/CHANGELOG.md index 00cc44f548a858..777d4271418b9c 100644 --- a/packages/jest-console/CHANGELOG.md +++ b/packages/jest-console/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.12.0 (2024-11-16) + ## 8.11.0 (2024-10-30) ## 8.10.0 (2024-10-16) diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 78213b83e7ee54..aff7457d32062f 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.11.0", + "version": "8.12.0-prerelease", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md index 28e0f4e2bb420d..a5b7d79336636c 100644 --- a/packages/jest-preset-default/CHANGELOG.md +++ b/packages/jest-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 12.12.0 (2024-11-16) + ## 12.11.0 (2024-10-30) ## 12.10.0 (2024-10-16) diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 7a16a2bdd46d49..9d8d897920aeec 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.11.0", + "version": "12.12.0-prerelease", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/CHANGELOG.md b/packages/jest-puppeteer-axe/CHANGELOG.md index a6557def1f0f27..c0459e401925c6 100644 --- a/packages/jest-puppeteer-axe/CHANGELOG.md +++ b/packages/jest-puppeteer-axe/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.12.0 (2024-11-16) + ## 7.11.0 (2024-10-30) ## 7.10.0 (2024-10-16) diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 4ea7c641be0e1d..f052c7166519b8 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.11.0", + "version": "7.12.0-prerelease", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/CHANGELOG.md b/packages/keyboard-shortcuts/CHANGELOG.md index 386e6b95c1258a..cbc9dc62deeb5c 100644 --- a/packages/keyboard-shortcuts/CHANGELOG.md +++ b/packages/keyboard-shortcuts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index ce029907c0dbf4..96964f4805f3b8 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/CHANGELOG.md b/packages/keycodes/CHANGELOG.md index 894501981ab1b5..d3b43c523ee8a3 100644 --- a/packages/keycodes/CHANGELOG.md +++ b/packages/keycodes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index 2038db1984760f..ef3648eb745a82 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/CHANGELOG.md b/packages/lazy-import/CHANGELOG.md index 1f9d1b15304e14..96e04c125b974e 100644 --- a/packages/lazy-import/CHANGELOG.md +++ b/packages/lazy-import/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.12.0 (2024-11-16) + ## 2.11.0 (2024-10-30) ## 2.10.0 (2024-10-16) diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index af18373147c986..6296b91215b648 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.11.0", + "version": "2.12.0-prerelease", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/CHANGELOG.md b/packages/list-reusable-blocks/CHANGELOG.md index 958057ffb976de..cee7a2eb5a8671 100644 --- a/packages/list-reusable-blocks/CHANGELOG.md +++ b/packages/list-reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 328695f31925ee..3c9167737809d9 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/CHANGELOG.md b/packages/media-utils/CHANGELOG.md index 047ff84855f29d..c4dd4f860c4690 100644 --- a/packages/media-utils/CHANGELOG.md +++ b/packages/media-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index e57b0f51844504..b04c540e912c5b 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/CHANGELOG.md b/packages/notices/CHANGELOG.md index d70c37f4fe721b..f721b22243aa87 100644 --- a/packages/notices/CHANGELOG.md +++ b/packages/notices/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/notices/package.json b/packages/notices/package.json index f150616445b060..7e235a5eac9a83 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/CHANGELOG.md b/packages/npm-package-json-lint-config/CHANGELOG.md index 9dee828f63fea0..c9addbd4214c64 100644 --- a/packages/npm-package-json-lint-config/CHANGELOG.md +++ b/packages/npm-package-json-lint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ### Enhancement - Include `exports`, `wpScript`, `wpScriptModuleExports` and `sideEffects` in the `prefer-property-order` rule ([#66239](https://github.com/WordPress/gutenberg/pull/66239)). diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index c02560393b9a9f..ce6181bcf45b7c 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/CHANGELOG.md b/packages/nux/CHANGELOG.md index 7446f00f381ac4..91a372a1efd207 100644 --- a/packages/nux/CHANGELOG.md +++ b/packages/nux/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.12.0 (2024-11-16) + ## 9.11.0 (2024-10-30) ## 9.10.0 (2024-10-16) diff --git a/packages/nux/package.json b/packages/nux/package.json index 50a4d5acf6d028..0469174c91e238 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.11.0", + "version": "9.12.0-prerelease", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/CHANGELOG.md b/packages/patterns/CHANGELOG.md index ac4c4e09056129..c953ffc1b4d4ce 100644 --- a/packages/patterns/CHANGELOG.md +++ b/packages/patterns/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.12.0 (2024-11-16) + ## 2.11.0 (2024-10-30) ## 2.10.0 (2024-10-16) diff --git a/packages/patterns/package.json b/packages/patterns/package.json index d29fc9bcf49bca..dd2242c1ac2713 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.11.0", + "version": "2.12.0-prerelease", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/CHANGELOG.md b/packages/plugins/CHANGELOG.md index 2696ce8b2bf0b4..34004f6295a36b 100644 --- a/packages/plugins/CHANGELOG.md +++ b/packages/plugins/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.12.0 (2024-11-16) + ## 7.11.0 (2024-10-30) ## 7.10.0 (2024-10-16) diff --git a/packages/plugins/package.json b/packages/plugins/package.json index a926c2fd9a4e17..861be41026a3eb 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.11.0", + "version": "7.12.0-prerelease", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/CHANGELOG.md b/packages/postcss-plugins-preset/CHANGELOG.md index 939a997a5eb577..459193675cced1 100644 --- a/packages/postcss-plugins-preset/CHANGELOG.md +++ b/packages/postcss-plugins-preset/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index cda39c4a0bf0bf..197a3a81ec66cc 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/CHANGELOG.md b/packages/postcss-themes/CHANGELOG.md index 05cebfe533c6cf..098507b753ea80 100644 --- a/packages/postcss-themes/CHANGELOG.md +++ b/packages/postcss-themes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.12.0 (2024-11-16) + ## 6.11.0 (2024-10-30) ## 6.10.0 (2024-10-16) diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index 613b00789e78eb..3809f22ae2621a 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.11.0", + "version": "6.12.0-prerelease", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/CHANGELOG.md b/packages/preferences-persistence/CHANGELOG.md index 67bde4ee87c98d..a2b8376a82735c 100644 --- a/packages/preferences-persistence/CHANGELOG.md +++ b/packages/preferences-persistence/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.12.0 (2024-11-16) + ## 2.11.0 (2024-10-30) ## 2.10.0 (2024-10-16) diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index 05d2cf7031929d..d3f35e95ca0ce5 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.11.0", + "version": "2.12.0-prerelease", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/CHANGELOG.md b/packages/preferences/CHANGELOG.md index 2850950d6df7f5..76e227f2d70043 100644 --- a/packages/preferences/CHANGELOG.md +++ b/packages/preferences/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/preferences/package.json b/packages/preferences/package.json index 205f9b5d4966b1..e093e9cb26f048 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/CHANGELOG.md b/packages/prettier-config/CHANGELOG.md index a942a98605ab56..da352c8d8ddaf4 100644 --- a/packages/prettier-config/CHANGELOG.md +++ b/packages/prettier-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 367a782acffc4d..d8ba7ce14bb303 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/CHANGELOG.md b/packages/primitives/CHANGELOG.md index ac8c402ea9e757..25bc2d4e3abcb1 100644 --- a/packages/primitives/CHANGELOG.md +++ b/packages/primitives/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/primitives/package.json b/packages/primitives/package.json index d24bc1acf25e2d..ecee1e37fa27c7 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/CHANGELOG.md b/packages/priority-queue/CHANGELOG.md index 042e4ae3e97c12..dce047693d2957 100644 --- a/packages/priority-queue/CHANGELOG.md +++ b/packages/priority-queue/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.12.0 (2024-11-16) + ## 3.11.0 (2024-10-30) ## 3.10.0 (2024-10-16) diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 8c98b0b3552198..00ca5273d69b95 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.11.0", + "version": "3.12.0-prerelease", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/CHANGELOG.md b/packages/private-apis/CHANGELOG.md index db68d750432bc5..9e7c78b3d0fd1f 100644 --- a/packages/private-apis/CHANGELOG.md +++ b/packages/private-apis/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.12.0 (2024-11-16) + ## 1.11.0 (2024-10-30) ## 1.10.0 (2024-10-16) diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index 84436470521332..f1ee617549ec7d 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.11.0", + "version": "1.12.0-prerelease", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/CHANGELOG.md b/packages/project-management-automation/CHANGELOG.md index da01acd92c8f3b..d2028220f71284 100644 --- a/packages/project-management-automation/CHANGELOG.md +++ b/packages/project-management-automation/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.12.0 (2024-11-16) + ## 2.11.0 (2024-10-30) ## 2.10.0 (2024-10-16) diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index a3f6e3f0a44230..d939805d9a75c6 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.11.0", + "version": "2.12.0-prerelease", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/CHANGELOG.md b/packages/react-i18n/CHANGELOG.md index 165c1f0bc95549..d0991cdf756b33 100644 --- a/packages/react-i18n/CHANGELOG.md +++ b/packages/react-i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 31c4d98fa475e0..7210efbafac365 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md index 63a3192e7aa95f..42b12846436e25 100644 --- a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md +++ b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.12.0 (2024-11-16) + ## 3.11.0 (2024-10-30) ## 3.10.0 (2024-10-16) diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index 3e7d14813968ee..5dcd4ed3b4d6b9 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.11.0", + "version": "3.12.0-prerelease", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/CHANGELOG.md b/packages/redux-routine/CHANGELOG.md index 54df85dfd5717f..e32593e39a8289 100644 --- a/packages/redux-routine/CHANGELOG.md +++ b/packages/redux-routine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index b3aa6fa79474a8..57b50c96315db2 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/CHANGELOG.md b/packages/reusable-blocks/CHANGELOG.md index e4ba1b052ae218..e451948e16d364 100644 --- a/packages/reusable-blocks/CHANGELOG.md +++ b/packages/reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index e2649609016642..15a8a25371bbc9 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/CHANGELOG.md b/packages/rich-text/CHANGELOG.md index 138d963020deb5..904894e9553c23 100644 --- a/packages/rich-text/CHANGELOG.md +++ b/packages/rich-text/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.12.0 (2024-11-16) + ## 7.11.0 (2024-10-30) ## 7.10.0 (2024-10-16) diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index f038e097668984..6e52c43a8f9881 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.11.0", + "version": "7.12.0-prerelease", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index cd0a91605c6f58..7e65d08ea7a4b4 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.12.0 (2024-11-16) + ## 1.11.0 (2024-10-30) ## 1.10.0 (2024-10-16) diff --git a/packages/router/package.json b/packages/router/package.json index 3d80481c9b6baa..67dddbb7dd3010 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.11.0", + "version": "1.12.0-prerelease", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index c09cfd1ac9aaaa..452028cab49cd1 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 30.5.0 (2024-11-16) + ### Bug Fix - Make `start` script more resilient for developer errors ([#66752](https://github.com/WordPress/gutenberg/pull/66752)). diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 3a50d921145e19..ea93413d7c1292 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.4.0", + "version": "30.5.0-prerelease", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/CHANGELOG.md b/packages/server-side-render/CHANGELOG.md index 479fbf835e74d5..d334d34897a7e7 100644 --- a/packages/server-side-render/CHANGELOG.md +++ b/packages/server-side-render/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index cdfe9679c5049d..2bdf200ab14fa5 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.11.0", + "version": "5.12.0-prerelease", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/CHANGELOG.md b/packages/shortcode/CHANGELOG.md index f869446602cb16..dd30fa01c08bd4 100644 --- a/packages/shortcode/CHANGELOG.md +++ b/packages/shortcode/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index c476788e3cfaf8..9f342ef436f35d 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md index f9e50558d83664..91ffb32099a230 100644 --- a/packages/style-engine/CHANGELOG.md +++ b/packages/style-engine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.12.0 (2024-11-16) + ## 2.11.0 (2024-10-30) ## 2.10.0 (2024-10-16) diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 378f4dce91dad9..03685506f285f6 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.11.0", + "version": "2.12.0-prerelease", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/CHANGELOG.md b/packages/stylelint-config/CHANGELOG.md index ac778801a0160d..402ca7cf9de59a 100644 --- a/packages/stylelint-config/CHANGELOG.md +++ b/packages/stylelint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 23.4.0 (2024-11-16) + ## 23.3.0 (2024-10-30) ## 23.2.0 (2024-10-16) diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 0043e0a62be412..b1b3622e5d4e5b 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "23.3.0", + "version": "23.4.0-prerelease", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/CHANGELOG.md b/packages/sync/CHANGELOG.md index d9e04f700b8d78..867e1fb2b3233b 100644 --- a/packages/sync/CHANGELOG.md +++ b/packages/sync/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.12.0 (2024-11-16) + ## 1.11.0 (2024-10-30) ## 1.10.0 (2024-10-16) diff --git a/packages/sync/package.json b/packages/sync/package.json index d7181479327d3a..e7ebb462a8e621 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.11.0", + "version": "1.12.0-prerelease", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/CHANGELOG.md b/packages/token-list/CHANGELOG.md index 304d67cefdd026..2e72e21a44f646 100644 --- a/packages/token-list/CHANGELOG.md +++ b/packages/token-list/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.12.0 (2024-11-16) + ## 3.11.0 (2024-10-30) ## 3.10.0 (2024-10-16) diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 370d50e5b4700a..29d4a86f32c572 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.11.0", + "version": "3.12.0-prerelease", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/CHANGELOG.md b/packages/undo-manager/CHANGELOG.md index 0f779e36f51687..d35ddd1b895925 100644 --- a/packages/undo-manager/CHANGELOG.md +++ b/packages/undo-manager/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.12.0 (2024-11-16) + ## 1.11.0 (2024-10-30) ## 1.10.0 (2024-10-16) diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 66f895f8da887d..4c7c01634934c5 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.11.0", + "version": "1.12.0-prerelease", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/CHANGELOG.md b/packages/url/CHANGELOG.md index 0e0ac497785e46..94fc29e83f98d7 100644 --- a/packages/url/CHANGELOG.md +++ b/packages/url/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/url/package.json b/packages/url/package.json index 2ecdb8eae18113..33dd4442780c5d 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/CHANGELOG.md b/packages/viewport/CHANGELOG.md index ce3f20a6d8e2b7..78f0fa1c9292ce 100644 --- a/packages/viewport/CHANGELOG.md +++ b/packages/viewport/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.12.0 (2024-11-16) + ## 6.11.0 (2024-10-30) ## 6.10.0 (2024-10-16) diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 224da8a871addf..909ee4e1fd20f6 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.11.0", + "version": "6.12.0-prerelease", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/CHANGELOG.md b/packages/warning/CHANGELOG.md index e6ae7b4a229850..189af916a46a71 100644 --- a/packages/warning/CHANGELOG.md +++ b/packages/warning/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.12.0 (2024-11-16) + ## 3.11.0 (2024-10-30) ## 3.10.0 (2024-10-16) diff --git a/packages/warning/package.json b/packages/warning/package.json index d9c5a4dd83dc10..f035852a79acc1 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.11.0", + "version": "3.12.0-prerelease", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/CHANGELOG.md b/packages/widgets/CHANGELOG.md index 367add006f8895..2c02849b6ceee4 100644 --- a/packages/widgets/CHANGELOG.md +++ b/packages/widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/widgets/package.json b/packages/widgets/package.json index a755890c48ed92..11cf9a45171b1f 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/CHANGELOG.md b/packages/wordcount/CHANGELOG.md index 62b4b2efe1506e..ef65ec41b00db9 100644 --- a/packages/wordcount/CHANGELOG.md +++ b/packages/wordcount/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index 117e2227a926c8..f7df1fc5f68963 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.11.0", + "version": "4.12.0-prerelease", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From e97460ac6ab190bf449384c2638333d8c0e57711 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Sat, 16 Nov 2024 18:04:40 +0000 Subject: [PATCH 1601/1908] chore(release): publish - @wordpress/a11y@4.12.0 - @wordpress/annotations@3.12.0 - @wordpress/api-fetch@7.12.0 - @wordpress/autop@4.12.0 - @wordpress/babel-plugin-import-jsx-pragma@5.12.0 - @wordpress/babel-plugin-makepot@6.12.0 - @wordpress/babel-preset-default@8.12.0 - @wordpress/base-styles@5.12.0 - @wordpress/blob@4.12.0 - @wordpress/block-directory@5.12.0 - @wordpress/block-editor@14.7.0 - @wordpress/block-library@9.12.0 - @wordpress/block-serialization-default-parser@5.12.0 - @wordpress/block-serialization-spec-parser@5.12.0 - @wordpress/blocks@14.1.0 - @wordpress/browserslist-config@6.12.0 - @wordpress/commands@1.12.0 - @wordpress/components@28.12.0 - @wordpress/compose@7.12.0 - @wordpress/core-commands@1.12.0 - @wordpress/core-data@7.12.0 - @wordpress/create-block@4.55.0 - @wordpress/create-block-interactive-template@2.12.0 - @wordpress/create-block-tutorial-template@4.12.0 - @wordpress/customize-widgets@5.12.0 - @wordpress/data@10.12.0 - @wordpress/data-controls@4.12.0 - @wordpress/dataviews@4.8.0 - @wordpress/date@5.12.0 - @wordpress/dependency-extraction-webpack-plugin@6.12.0 - @wordpress/deprecated@4.12.0 - @wordpress/docgen@2.12.0 - @wordpress/dom@4.12.0 - @wordpress/dom-ready@4.12.0 - @wordpress/e2e-test-utils@11.12.0 - @wordpress/e2e-test-utils-playwright@1.12.0 - @wordpress/e2e-tests@8.12.0 - @wordpress/edit-post@8.12.0 - @wordpress/edit-site@6.12.0 - @wordpress/edit-widgets@6.12.0 - @wordpress/editor@14.12.0 - @wordpress/element@6.12.0 - @wordpress/env@10.12.0 - @wordpress/escape-html@3.12.0 - @wordpress/eslint-plugin@21.5.0 - @wordpress/fields@0.4.0 - @wordpress/format-library@5.12.0 - @wordpress/hooks@4.12.0 - @wordpress/html-entities@4.12.0 - @wordpress/i18n@5.12.0 - @wordpress/icons@10.12.0 - @wordpress/interactivity@6.12.0 - @wordpress/interactivity-router@2.12.0 - @wordpress/interface@8.1.0 - @wordpress/is-shallow-equal@5.12.0 - @wordpress/jest-console@8.12.0 - @wordpress/jest-preset-default@12.12.0 - @wordpress/jest-puppeteer-axe@7.12.0 - @wordpress/keyboard-shortcuts@5.12.0 - @wordpress/keycodes@4.12.0 - @wordpress/lazy-import@2.12.0 - @wordpress/list-reusable-blocks@5.12.0 - @wordpress/media-utils@5.12.0 - @wordpress/notices@5.12.0 - @wordpress/npm-package-json-lint-config@5.12.0 - @wordpress/nux@9.12.0 - @wordpress/patterns@2.12.0 - @wordpress/plugins@7.12.0 - @wordpress/postcss-plugins-preset@5.12.0 - @wordpress/postcss-themes@6.12.0 - @wordpress/preferences@4.12.0 - @wordpress/preferences-persistence@2.12.0 - @wordpress/prettier-config@4.12.0 - @wordpress/primitives@4.12.0 - @wordpress/priority-queue@3.12.0 - @wordpress/private-apis@1.12.0 - @wordpress/project-management-automation@2.12.0 - @wordpress/react-i18n@4.12.0 - @wordpress/readable-js-assets-webpack-plugin@3.12.0 - @wordpress/redux-routine@5.12.0 - @wordpress/reusable-blocks@5.12.0 - @wordpress/rich-text@7.12.0 - @wordpress/router@1.12.0 - @wordpress/scripts@30.5.0 - @wordpress/server-side-render@5.12.0 - @wordpress/shortcode@4.12.0 - @wordpress/style-engine@2.12.0 - @wordpress/stylelint-config@23.4.0 - @wordpress/sync@1.12.0 - @wordpress/token-list@3.12.0 - @wordpress/undo-manager@1.12.0 - @wordpress/url@4.12.0 - @wordpress/viewport@6.12.0 - @wordpress/warning@3.12.0 - @wordpress/widgets@4.12.0 - @wordpress/wordcount@4.12.0 --- package-lock.json | 192 +++++++++--------- packages/a11y/package.json | 2 +- packages/annotations/package.json | 2 +- packages/api-fetch/package.json | 2 +- packages/autop/package.json | 2 +- .../package.json | 2 +- packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/package.json | 2 +- packages/base-styles/package.json | 2 +- packages/blob/package.json | 2 +- packages/block-directory/package.json | 2 +- packages/block-editor/package.json | 2 +- packages/block-library/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/blocks/package.json | 2 +- packages/browserslist-config/package.json | 2 +- packages/commands/package.json | 2 +- packages/components/package.json | 2 +- packages/compose/package.json | 2 +- packages/core-commands/package.json | 2 +- packages/core-data/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/create-block/package.json | 2 +- packages/customize-widgets/package.json | 2 +- packages/data-controls/package.json | 2 +- packages/data/package.json | 2 +- packages/dataviews/package.json | 2 +- packages/date/package.json | 2 +- .../package.json | 2 +- packages/deprecated/package.json | 2 +- packages/docgen/package.json | 2 +- packages/dom-ready/package.json | 2 +- packages/dom/package.json | 2 +- .../e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/package.json | 2 +- packages/edit-post/package.json | 2 +- packages/edit-site/package.json | 2 +- packages/edit-widgets/package.json | 2 +- packages/editor/package.json | 2 +- packages/element/package.json | 2 +- packages/env/package.json | 2 +- packages/escape-html/package.json | 2 +- packages/eslint-plugin/package.json | 2 +- packages/fields/package.json | 2 +- packages/format-library/package.json | 2 +- packages/hooks/package.json | 2 +- packages/html-entities/package.json | 2 +- packages/i18n/package.json | 2 +- packages/icons/package.json | 2 +- packages/interactivity-router/package.json | 2 +- packages/interactivity/package.json | 2 +- packages/interface/package.json | 2 +- packages/is-shallow-equal/package.json | 2 +- packages/jest-console/package.json | 2 +- packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/package.json | 2 +- packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/package.json | 2 +- packages/notices/package.json | 2 +- .../npm-package-json-lint-config/package.json | 2 +- packages/nux/package.json | 2 +- packages/patterns/package.json | 2 +- packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/package.json | 2 +- packages/preferences/package.json | 2 +- packages/prettier-config/package.json | 2 +- packages/primitives/package.json | 2 +- packages/priority-queue/package.json | 2 +- packages/private-apis/package.json | 2 +- .../package.json | 2 +- packages/react-i18n/package.json | 2 +- .../package.json | 2 +- packages/redux-routine/package.json | 2 +- packages/reusable-blocks/package.json | 2 +- packages/rich-text/package.json | 2 +- packages/router/package.json | 2 +- packages/scripts/package.json | 2 +- packages/server-side-render/package.json | 2 +- packages/shortcode/package.json | 2 +- packages/style-engine/package.json | 2 +- packages/stylelint-config/package.json | 2 +- packages/sync/package.json | 2 +- packages/token-list/package.json | 2 +- packages/undo-manager/package.json | 2 +- packages/url/package.json | 2 +- packages/viewport/package.json | 2 +- packages/warning/package.json | 2 +- packages/widgets/package.json | 2 +- packages/wordcount/package.json | 2 +- 97 files changed, 192 insertions(+), 192 deletions(-) diff --git a/package-lock.json b/package-lock.json index b4d618b6da02ec..2f8f627dca805c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51852,7 +51852,7 @@ }, "packages/a11y": { "name": "@wordpress/a11y", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -51866,7 +51866,7 @@ }, "packages/annotations": { "name": "@wordpress/annotations", - "version": "3.11.0", + "version": "3.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -51894,7 +51894,7 @@ }, "packages/api-fetch": { "name": "@wordpress/api-fetch", - "version": "7.11.0", + "version": "7.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -51908,7 +51908,7 @@ }, "packages/autop": { "name": "@wordpress/autop", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -51920,7 +51920,7 @@ }, "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -51932,7 +51932,7 @@ }, "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "dependencies": { "deepmerge": "^4.3.0", @@ -51949,7 +51949,7 @@ }, "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", - "version": "8.11.0", + "version": "8.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -53080,7 +53080,7 @@ }, "packages/base-styles": { "name": "@wordpress/base-styles", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53089,7 +53089,7 @@ }, "packages/blob": { "name": "@wordpress/blob", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -53101,7 +53101,7 @@ }, "packages/block-directory": { "name": "@wordpress/block-directory", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53137,7 +53137,7 @@ }, "packages/block-editor": { "name": "@wordpress/block-editor", - "version": "14.6.0", + "version": "14.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53237,7 +53237,7 @@ }, "packages/block-library": { "name": "@wordpress/block-library", - "version": "9.11.0", + "version": "9.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53303,7 +53303,7 @@ }, "packages/block-serialization-default-parser": { "name": "@wordpress/block-serialization-default-parser", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -53315,7 +53315,7 @@ }, "packages/block-serialization-spec-parser": { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "pegjs": "^0.10.0", @@ -53328,7 +53328,7 @@ }, "packages/blocks": { "name": "@wordpress/blocks", - "version": "14.0.0", + "version": "14.1.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53382,7 +53382,7 @@ }, "packages/browserslist-config": { "name": "@wordpress/browserslist-config", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53391,7 +53391,7 @@ }, "packages/commands": { "name": "@wordpress/commands", - "version": "1.11.0", + "version": "1.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53630,7 +53630,7 @@ }, "packages/components": { "name": "@wordpress/components", - "version": "28.11.0", + "version": "28.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -53751,7 +53751,7 @@ }, "packages/compose": { "name": "@wordpress/compose", - "version": "7.11.0", + "version": "7.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53788,7 +53788,7 @@ }, "packages/core-commands": { "name": "@wordpress/core-commands", - "version": "1.11.0", + "version": "1.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53817,7 +53817,7 @@ }, "packages/core-data": { "name": "@wordpress/core-data", - "version": "7.11.0", + "version": "7.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53862,7 +53862,7 @@ }, "packages/create-block": { "name": "@wordpress/create-block", - "version": "4.54.0", + "version": "4.55.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/lazy-import": "*", @@ -53889,7 +53889,7 @@ }, "packages/create-block-interactive-template": { "name": "@wordpress/create-block-interactive-template", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53898,7 +53898,7 @@ }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53907,7 +53907,7 @@ }, "packages/customize-widgets": { "name": "@wordpress/customize-widgets", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53946,7 +53946,7 @@ }, "packages/data": { "name": "@wordpress/data", - "version": "10.11.0", + "version": "10.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53975,7 +53975,7 @@ }, "packages/data-controls": { "name": "@wordpress/data-controls", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53993,7 +53993,7 @@ }, "packages/dataviews": { "name": "@wordpress/dataviews", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -54050,7 +54050,7 @@ }, "packages/date": { "name": "@wordpress/date", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54065,7 +54065,7 @@ }, "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "dependencies": { "json2php": "^0.0.7" @@ -54080,7 +54080,7 @@ }, "packages/deprecated": { "name": "@wordpress/deprecated", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54093,7 +54093,7 @@ }, "packages/docgen": { "name": "@wordpress/docgen", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -54114,7 +54114,7 @@ }, "packages/dom": { "name": "@wordpress/dom", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54127,7 +54127,7 @@ }, "packages/dom-ready": { "name": "@wordpress/dom-ready", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54139,7 +54139,7 @@ }, "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", - "version": "11.11.0", + "version": "11.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54161,7 +54161,7 @@ }, "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.11.0", + "version": "1.12.0", "license": "GPL-2.0-or-later", "dependencies": { "change-case": "^4.1.2", @@ -54187,7 +54187,7 @@ }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", - "version": "8.11.0", + "version": "8.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/e2e-test-utils": "*", @@ -54225,7 +54225,7 @@ }, "packages/edit-post": { "name": "@wordpress/edit-post", - "version": "8.11.0", + "version": "8.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54272,7 +54272,7 @@ }, "packages/edit-site": { "name": "@wordpress/edit-site", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54334,7 +54334,7 @@ }, "packages/edit-widgets": { "name": "@wordpress/edit-widgets", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54378,7 +54378,7 @@ }, "packages/editor": { "name": "@wordpress/editor", - "version": "14.11.0", + "version": "14.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54440,7 +54440,7 @@ }, "packages/element": { "name": "@wordpress/element", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54459,7 +54459,7 @@ }, "packages/env": { "name": "@wordpress/env", - "version": "10.11.0", + "version": "10.12.0", "license": "GPL-2.0-or-later", "dependencies": { "chalk": "^4.0.0", @@ -54590,7 +54590,7 @@ }, "packages/escape-html": { "name": "@wordpress/escape-html", - "version": "3.11.0", + "version": "3.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54602,7 +54602,7 @@ }, "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", - "version": "21.4.0", + "version": "21.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/eslint-parser": "7.25.7", @@ -54671,7 +54671,7 @@ }, "packages/fields": { "name": "@wordpress/fields", - "version": "0.3.0", + "version": "0.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54712,7 +54712,7 @@ }, "packages/format-library": { "name": "@wordpress/format-library", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54740,7 +54740,7 @@ }, "packages/hooks": { "name": "@wordpress/hooks", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54752,7 +54752,7 @@ }, "packages/html-entities": { "name": "@wordpress/html-entities", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54764,7 +54764,7 @@ }, "packages/i18n": { "name": "@wordpress/i18n", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54784,7 +54784,7 @@ }, "packages/icons": { "name": "@wordpress/icons", - "version": "10.11.0", + "version": "10.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54798,7 +54798,7 @@ }, "packages/interactivity": { "name": "@wordpress/interactivity", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@preact/signals": "^1.3.0", @@ -54811,7 +54811,7 @@ }, "packages/interactivity-router": { "name": "@wordpress/interactivity-router", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/a11y": "*", @@ -54824,7 +54824,7 @@ }, "packages/interface": { "name": "@wordpress/interface", - "version": "8.0.0", + "version": "8.1.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54852,7 +54852,7 @@ }, "packages/is-shallow-equal": { "name": "@wordpress/is-shallow-equal", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54864,7 +54864,7 @@ }, "packages/jest-console": { "name": "@wordpress/jest-console", - "version": "8.11.0", + "version": "8.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54880,7 +54880,7 @@ }, "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", - "version": "12.11.0", + "version": "12.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/jest-console": "*", @@ -54897,7 +54897,7 @@ }, "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.11.0", + "version": "7.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@axe-core/puppeteer": "^4.0.0", @@ -54919,7 +54919,7 @@ }, "packages/keyboard-shortcuts": { "name": "@wordpress/keyboard-shortcuts", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54937,7 +54937,7 @@ }, "packages/keycodes": { "name": "@wordpress/keycodes", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54950,7 +54950,7 @@ }, "packages/lazy-import": { "name": "@wordpress/lazy-import", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "dependencies": { "execa": "^4.0.2", @@ -54964,7 +54964,7 @@ }, "packages/list-reusable-blocks": { "name": "@wordpress/list-reusable-blocks", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54987,7 +54987,7 @@ }, "packages/media-utils": { "name": "@wordpress/media-utils", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55004,7 +55004,7 @@ }, "packages/notices": { "name": "@wordpress/notices", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55021,7 +55021,7 @@ }, "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55033,7 +55033,7 @@ }, "packages/nux": { "name": "@wordpress/nux", - "version": "9.11.0", + "version": "9.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55056,7 +55056,7 @@ }, "packages/patterns": { "name": "@wordpress/patterns", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55086,7 +55086,7 @@ }, "packages/plugins": { "name": "@wordpress/plugins", - "version": "7.11.0", + "version": "7.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55110,7 +55110,7 @@ }, "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/base-styles": "*", @@ -55126,7 +55126,7 @@ }, "packages/postcss-themes": { "name": "@wordpress/postcss-themes", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55138,7 +55138,7 @@ }, "packages/preferences": { "name": "@wordpress/preferences", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55164,7 +55164,7 @@ }, "packages/preferences-persistence": { "name": "@wordpress/preferences-persistence", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55177,7 +55177,7 @@ }, "packages/prettier-config": { "name": "@wordpress/prettier-config", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55189,7 +55189,7 @@ }, "packages/primitives": { "name": "@wordpress/primitives", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55206,7 +55206,7 @@ }, "packages/priority-queue": { "name": "@wordpress/priority-queue", - "version": "3.11.0", + "version": "3.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55219,7 +55219,7 @@ }, "packages/private-apis": { "name": "@wordpress/private-apis", - "version": "1.11.0", + "version": "1.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -55231,7 +55231,7 @@ }, "packages/project-management-automation": { "name": "@wordpress/project-management-automation", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@actions/core": "1.9.1", @@ -55259,7 +55259,7 @@ }, "packages/react-i18n": { "name": "@wordpress/react-i18n", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55415,7 +55415,7 @@ }, "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.11.0", + "version": "3.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55427,7 +55427,7 @@ }, "packages/redux-routine": { "name": "@wordpress/redux-routine", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55470,7 +55470,7 @@ }, "packages/reusable-blocks": { "name": "@wordpress/reusable-blocks", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55497,7 +55497,7 @@ }, "packages/rich-text": { "name": "@wordpress/rich-text", - "version": "7.11.0", + "version": "7.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55521,7 +55521,7 @@ }, "packages/router": { "name": "@wordpress/router", - "version": "1.11.0", + "version": "1.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55540,7 +55540,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "30.4.0", + "version": "30.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -55974,7 +55974,7 @@ }, "packages/server-side-render": { "name": "@wordpress/server-side-render", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56000,7 +56000,7 @@ }, "packages/shortcode": { "name": "@wordpress/shortcode", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56013,7 +56013,7 @@ }, "packages/style-engine": { "name": "@wordpress/style-engine", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56026,7 +56026,7 @@ }, "packages/stylelint-config": { "name": "@wordpress/stylelint-config", - "version": "23.3.0", + "version": "23.4.0", "license": "MIT", "dependencies": { "@stylistic/stylelint-plugin": "^3.0.1", @@ -56137,7 +56137,7 @@ }, "packages/sync": { "name": "@wordpress/sync", - "version": "1.11.0", + "version": "1.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56158,7 +56158,7 @@ }, "packages/token-list": { "name": "@wordpress/token-list", - "version": "3.11.0", + "version": "3.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -56170,7 +56170,7 @@ }, "packages/undo-manager": { "name": "@wordpress/undo-manager", - "version": "1.11.0", + "version": "1.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56183,7 +56183,7 @@ }, "packages/url": { "name": "@wordpress/url", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56196,7 +56196,7 @@ }, "packages/viewport": { "name": "@wordpress/viewport", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56226,7 +56226,7 @@ }, "packages/warning": { "name": "@wordpress/warning", - "version": "3.11.0", + "version": "3.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -56235,7 +56235,7 @@ }, "packages/widgets": { "name": "@wordpress/widgets", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56263,7 +56263,7 @@ }, "packages/wordcount": { "name": "@wordpress/wordcount", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" diff --git a/packages/a11y/package.json b/packages/a11y/package.json index d7e3018a9b6772..1fcffd9cdfe69f 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/package.json b/packages/annotations/package.json index d3053d4ab18d7f..269c16d159e9f6 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.12.0-prerelease", + "version": "3.12.0", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 890c8890b3edb3..07d90568dc9413 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.12.0-prerelease", + "version": "7.12.0", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/package.json b/packages/autop/package.json index d0588584221282..60b7102850020a 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index 58115a13f9edf7..231886784bd3f0 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index 47cfb6a388ca1e..4f18f8556d68dd 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.12.0-prerelease", + "version": "6.12.0", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 09f099221d7da5..b305500dc20795 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.12.0-prerelease", + "version": "8.12.0", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index fda3a8c5c7d34d..bcdb19206b39e9 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/package.json b/packages/blob/package.json index 376399068dd6f5..2134bcd21e9346 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index ab2c5fb00b3eba..a005e5be7cd60b 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 06e4b2402e214b..031b34933691a3 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.7.0-prerelease", + "version": "14.7.0", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 29312f1c842adb..e507ef36367268 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.12.0-prerelease", + "version": "9.12.0", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index bcaa7261f0f0e7..a448804ae9ba8c 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 57a8b06a7f1551..30aa5679a7c01a 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 92439f60b06f5d..15102734ff34f1 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "14.1.0-prerelease", + "version": "14.1.0", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index d04104e3ace409..f5b60a9bb7e783 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.12.0-prerelease", + "version": "6.12.0", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/package.json b/packages/commands/package.json index 9b410dea657d3e..0f252c5e90ade3 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.12.0-prerelease", + "version": "1.12.0", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/package.json b/packages/components/package.json index 512d2a61fde128..b297b31e544f98 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.12.0-prerelease", + "version": "28.12.0", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/package.json b/packages/compose/package.json index 8ec086556c37ac..596a50405ad476 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.12.0-prerelease", + "version": "7.12.0", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 0cac600b59ad7e..172431aa3d0913 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.12.0-prerelease", + "version": "1.12.0", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/package.json b/packages/core-data/package.json index d35e831855cf3e..66a52adfe1ce92 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.12.0-prerelease", + "version": "7.12.0", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index 14ee84510d777c..94e5f3b3ed4e0b 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.12.0-prerelease", + "version": "2.12.0", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index b867e84b1a3833..31c91064ddbaa6 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/package.json b/packages/create-block/package.json index a15d4600dbabdd..edee3d421de957 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.55.0-prerelease", + "version": "4.55.0", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index c9a637e90cbf12..9c1e117d2145e8 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index c47041b37af0cf..0977dbb27f988c 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/package.json b/packages/data/package.json index a1fa3b0f375c3a..e325b82357b955 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.12.0-prerelease", + "version": "10.12.0", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index 272fa016c2f604..80cfbf24be5651 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.8.0-prerelease", + "version": "4.8.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/package.json b/packages/date/package.json index d25f75bf87b7ca..0d98f3954d92d0 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index 9af418b5787e28..f168f379aa819d 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.12.0-prerelease", + "version": "6.12.0", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 7e083f88d6a0fb..11d351d17acb49 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 03672c045f4e77..f9df5281bd5259 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.12.0-prerelease", + "version": "2.12.0", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 2480e36704fb2b..7302df37787ca5 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/package.json b/packages/dom/package.json index f7bb5001e37b57..a717c1ee0b9a5d 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 7b3070e3971b8d..43ef469ac88471 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.12.0-prerelease", + "version": "1.12.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index 562d54181644fe..ee7a4deaa2ee94 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.12.0-prerelease", + "version": "11.12.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index d950e8cf5ac7f0..ee87ea8430654d 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.12.0-prerelease", + "version": "8.12.0", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 550a378d5409fb..ba2bdea38bbe43 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.12.0-prerelease", + "version": "8.12.0", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 41ddffdc7b0cc7..11ce70b876bc45 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.12.0-prerelease", + "version": "6.12.0", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 24f5307b66c621..4ed1124314f2cf 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.12.0-prerelease", + "version": "6.12.0", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/package.json b/packages/editor/package.json index 0200b15b34364b..77399238a9f46b 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.12.0-prerelease", + "version": "14.12.0", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/package.json b/packages/element/package.json index 233cf7e0942392..6a4ede84b1062d 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.12.0-prerelease", + "version": "6.12.0", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/package.json b/packages/env/package.json index c13b917fb9a94c..d1c3b192baf894 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.12.0-prerelease", + "version": "10.12.0", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 6ad428a0418280..688c10e638a96c 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.12.0-prerelease", + "version": "3.12.0", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index e5b444e3890a6e..c3521692d7fd12 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "21.5.0-prerelease", + "version": "21.5.0", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/fields/package.json b/packages/fields/package.json index 81de6f1f4b61a9..8c9509b06c5885 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/fields", - "version": "0.4.0-prerelease", + "version": "0.4.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/package.json b/packages/format-library/package.json index 8d3c6fb0d18199..ee1dd8efd1fe95 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/package.json b/packages/hooks/package.json index c9af44c8dc5d66..0bfc0700070e2d 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 3f99a67512569d..f8f88b883be146 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 9182351622f5d7..ed4b25aa0fb8fc 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/package.json b/packages/icons/package.json index 5d5aa56611cad6..40ddb309066e25 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.12.0-prerelease", + "version": "10.12.0", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 8baa41d289871d..d750edb2cd9c28 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.12.0-prerelease", + "version": "2.12.0", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 9a32fefec323b3..e82d74c5735302 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.12.0-prerelease", + "version": "6.12.0", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/package.json b/packages/interface/package.json index 4f5bf64fea3c34..6d286e2e259e90 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "8.1.0-prerelease", + "version": "8.1.0", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index e840fc4be82882..5bc028c2f58902 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index aff7457d32062f..f0c6cdea73f461 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.12.0-prerelease", + "version": "8.12.0", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 9d8d897920aeec..4050f4fce430f2 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.12.0-prerelease", + "version": "12.12.0", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index f052c7166519b8..928f427348e690 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.12.0-prerelease", + "version": "7.12.0", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 96964f4805f3b8..a98a64cb433251 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index ef3648eb745a82..c4720262af6bb4 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index 6296b91215b648..e6b989891b351b 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.12.0-prerelease", + "version": "2.12.0", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 3c9167737809d9..6db0f8d1da903d 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index b04c540e912c5b..d0b05f580d45cf 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/package.json b/packages/notices/package.json index 7e235a5eac9a83..2f0369dede9bb0 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index ce6181bcf45b7c..680a30bb096c9e 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/package.json b/packages/nux/package.json index 0469174c91e238..836f1de781413e 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.12.0-prerelease", + "version": "9.12.0", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/package.json b/packages/patterns/package.json index dd2242c1ac2713..a556a4641f6bc7 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.12.0-prerelease", + "version": "2.12.0", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 861be41026a3eb..9bb45aea981082 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.12.0-prerelease", + "version": "7.12.0", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 197a3a81ec66cc..0627cb489fca75 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index 3809f22ae2621a..e1b632925094f5 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.12.0-prerelease", + "version": "6.12.0", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index d3f35e95ca0ce5..645e62c9307cb6 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.12.0-prerelease", + "version": "2.12.0", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/package.json b/packages/preferences/package.json index e093e9cb26f048..e9f83170fe56b2 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index d8ba7ce14bb303..5991d84b9ee7e9 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/package.json b/packages/primitives/package.json index ecee1e37fa27c7..67bc8e84bd24e7 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 00ca5273d69b95..e5487204dd2375 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.12.0-prerelease", + "version": "3.12.0", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index f1ee617549ec7d..928eef9465d9ca 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.12.0-prerelease", + "version": "1.12.0", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index d939805d9a75c6..22638756014c6e 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.12.0-prerelease", + "version": "2.12.0", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 7210efbafac365..236cd7d63be1b6 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index 5dcd4ed3b4d6b9..dda4f7e0a51ffc 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.12.0-prerelease", + "version": "3.12.0", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 57b50c96315db2..e4d3600c5db2eb 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 15a8a25371bbc9..29309d1d99c9d4 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 6e52c43a8f9881..1f3fbfa26e513b 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.12.0-prerelease", + "version": "7.12.0", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/package.json b/packages/router/package.json index 67dddbb7dd3010..3ee25719134020 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.12.0-prerelease", + "version": "1.12.0", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index ea93413d7c1292..34629bf9843ff7 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.5.0-prerelease", + "version": "30.5.0", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index 2bdf200ab14fa5..1e2d477840d720 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.12.0-prerelease", + "version": "5.12.0", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index 9f342ef436f35d..dde71b677e93f1 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index 03685506f285f6..ef7adbe720f6c0 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.12.0-prerelease", + "version": "2.12.0", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index b1b3622e5d4e5b..6aff6076c76f03 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "23.4.0-prerelease", + "version": "23.4.0", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/package.json b/packages/sync/package.json index e7ebb462a8e621..42c784ae13ac6a 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.12.0-prerelease", + "version": "1.12.0", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 29d4a86f32c572..17837ccd5d1b70 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.12.0-prerelease", + "version": "3.12.0", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 4c7c01634934c5..99fa4c7f8a9bbc 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.12.0-prerelease", + "version": "1.12.0", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/package.json b/packages/url/package.json index 33dd4442780c5d..0e237f4e95788e 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 909ee4e1fd20f6..548efa124f374e 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.12.0-prerelease", + "version": "6.12.0", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/package.json b/packages/warning/package.json index f035852a79acc1..3d6223ba47ff08 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.12.0-prerelease", + "version": "3.12.0", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 11cf9a45171b1f..db712cd70d5449 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index f7df1fc5f68963..637d935fc11e6c 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.12.0-prerelease", + "version": "4.12.0", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 92199e1c4cd7a5c8b13fa9ca4da79a2fc50d737b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grzegorz=20Zi=C3=B3=C5=82kowski?= <grzegorz@gziolo.pl> Date: Mon, 18 Nov 2024 09:34:00 +0100 Subject: [PATCH 1602/1908] Fix changelog entries after delayed npm publishing --- packages/components/CHANGELOG.md | 12 +++++++++--- packages/data/CHANGELOG.md | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index c9da13035447f9..d3700e6f25a8d5 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,18 +2,24 @@ ## Unreleased +### Deprecations + +- `DimensionControl`: Deprecate 36px default size ([#66705](https://github.com/WordPress/gutenberg/pull/66705)). + +### Bug Fixes + +- `ToggleGroupControl`: Fix active background for `0` value ([#66855](https://github.com/WordPress/gutenberg/pull/66855)). +- `SlotFill`: Fix a bug where a stale value of `fillProps` could be used ([#67000](https://github.com/WordPress/gutenberg/pull/67000)). + ## 28.12.0 (2024-11-16) ### Deprecations - `Radio`: Deprecate 36px default size ([#66572](https://github.com/WordPress/gutenberg/pull/66572)). -- `DimensionControl`: Deprecate 36px default size ([#66705](https://github.com/WordPress/gutenberg/pull/66705)). ### Bug Fixes - `Popover`: Fix missing label of the headerTitle Close button ([#66813](https://github.com/WordPress/gutenberg/pull/66813)). -- `ToggleGroupControl`: Fix active background for `0` value ([#66855](https://github.com/WordPress/gutenberg/pull/66855)). -- `SlotFill`: Fix a bug where a stale value of `fillProps` could be used ([#67000](https://github.com/WordPress/gutenberg/pull/67000)). ### Enhancements diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index b38831dd38839f..0537039794505f 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -6,7 +6,7 @@ - Upgrade `redux` dependency to `^5.0.1` ([#66966](https://github.com/WordPress/gutenberg/pull/66966)) -## 10.12.0 (2024-11-16)>>>>>>> 854d8c7a61 (Update changelog files) +## 10.12.0 (2024-11-16) ## 10.11.0 (2024-10-30) From 930dfa50ecc864f6dd60ca42fbb29461705d4f7b Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Mon, 18 Nov 2024 14:57:52 +0530 Subject: [PATCH 1603/1908] Inline Commenting: Update placement of reply input and add author info header (#66580) --- .../components/collab-sidebar/add-comment.js | 97 +++---------- .../collab-sidebar/comment-author-info.js | 68 +++++++++ .../components/collab-sidebar/comment-form.js | 62 ++++++++ .../src/components/collab-sidebar/comments.js | 136 +++++------------- 4 files changed, 187 insertions(+), 176 deletions(-) create mode 100644 packages/editor/src/components/collab-sidebar/comment-author-info.js create mode 100644 packages/editor/src/components/collab-sidebar/comment-form.js diff --git a/packages/editor/src/components/collab-sidebar/add-comment.js b/packages/editor/src/components/collab-sidebar/add-comment.js index 01ee7aff0370ef..fce47e821e2065 100644 --- a/packages/editor/src/components/collab-sidebar/add-comment.js +++ b/packages/editor/src/components/collab-sidebar/add-comment.js @@ -1,22 +1,19 @@ /** * WordPress dependencies */ -import { __, _x } from '@wordpress/i18n'; +import { _x } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; -import { useState, useEffect } from '@wordpress/element'; import { __experimentalHStack as HStack, __experimentalVStack as VStack, - Button, - TextControl, } from '@wordpress/components'; import { store as blockEditorStore } from '@wordpress/block-editor'; -import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies */ -import { sanitizeCommentString } from './utils'; +import CommentAuthorInfo from './comment-author-info'; +import CommentForm from './comment-form'; /** * Renders the UI for adding a comment in the Gutenberg editor's collaboration sidebar. @@ -32,39 +29,14 @@ export function AddComment( { showCommentBoard, setShowCommentBoard, } ) { - // State to manage the comment thread. - const [ inputComment, setInputComment ] = useState( '' ); - - const { defaultAvatar, clientId, blockCommentId, currentUser } = useSelect( - ( select ) => { - const { getSettings, getSelectedBlock } = - select( blockEditorStore ); - const { __experimentalDiscussionSettings } = getSettings(); - const selectedBlock = getSelectedBlock(); - const userData = select( coreStore ).getCurrentUser(); - return { - defaultAvatar: __experimentalDiscussionSettings?.avatarURL, - clientId: selectedBlock?.clientId, - blockCommentId: selectedBlock?.attributes?.blockCommentId, - currentUser: userData, - }; - }, - [] - ); - - const userAvatar = - currentUser && currentUser.avatar_urls && currentUser.avatar_urls[ 48 ] - ? currentUser.avatar_urls[ 48 ] - : defaultAvatar; - - useEffect( () => { - setInputComment( '' ); - }, [ clientId ] ); - - const handleCancel = () => { - setShowCommentBoard( false ); - setInputComment( '' ); - }; + const { clientId, blockCommentId } = useSelect( ( select ) => { + const { getSelectedBlock } = select( blockEditorStore ); + const selectedBlock = getSelectedBlock(); + return { + clientId: selectedBlock?.clientId, + blockCommentId: selectedBlock?.attributes?.blockCommentId, + }; + } ); if ( ! showCommentBoard || ! clientId || undefined !== blockCommentId ) { return null; @@ -76,46 +48,17 @@ export function AddComment( { className="editor-collab-sidebar-panel__thread editor-collab-sidebar-panel__active-thread" > <HStack alignment="left" spacing="3"> - <img - src={ userAvatar } - // translators: alt text for user avatar image - alt={ __( 'User Avatar' ) } - className="editor-collab-sidebar-panel__user-avatar" - width={ 32 } - height={ 32 } - /> - <span className="editor-collab-sidebar-panel__user-name"> - { currentUser?.name ?? '' } - </span> + <CommentAuthorInfo /> </HStack> - <TextControl - __next40pxDefaultSize - __nextHasNoMarginBottom - value={ inputComment } - onChange={ setInputComment } - placeholder={ _x( 'Comment', 'noun' ) } + <CommentForm + onSubmit={ ( inputComment ) => { + onSubmit( inputComment ); + } } + onCancel={ () => { + setShowCommentBoard( false ); + } } + submitButtonText={ _x( 'Comment', 'Add comment button' ) } /> - <HStack alignment="right" spacing="3"> - <Button - __next40pxDefaultSize - variant="tertiary" - text={ _x( 'Cancel', 'Cancel comment button' ) } - onClick={ handleCancel } - /> - <Button - __next40pxDefaultSize - accessibleWhenDisabled - variant="primary" - text={ _x( 'Comment', 'Add comment button' ) } - disabled={ - 0 === sanitizeCommentString( inputComment ).length - } - onClick={ () => { - onSubmit( inputComment ); - setInputComment( '' ); - } } - /> - </HStack> </VStack> ); } diff --git a/packages/editor/src/components/collab-sidebar/comment-author-info.js b/packages/editor/src/components/collab-sidebar/comment-author-info.js new file mode 100644 index 00000000000000..89d09a2b52261f --- /dev/null +++ b/packages/editor/src/components/collab-sidebar/comment-author-info.js @@ -0,0 +1,68 @@ +/** + * WordPress dependencies + */ +import { __experimentalVStack as VStack } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { dateI18n, getSettings as getDateSettings } from '@wordpress/date'; +import { useEntityProp, store as coreStore } from '@wordpress/core-data'; +import { useSelect } from '@wordpress/data'; +import { store as blockEditorStore } from '@wordpress/block-editor'; + +/** + * Render author information for a comment. + * + * @param {Object} props - Component properties. + * @param {string} props.avatar - URL of the author's avatar. + * @param {string} props.name - Name of the author. + * @param {string} props.date - Date of the comment. + * + * @return {JSX.Element} The JSX element representing the author's information. + */ +function CommentAuthorInfo( { avatar, name, date } ) { + const dateSettings = getDateSettings(); + const [ dateTimeFormat = dateSettings.formats.time ] = useEntityProp( + 'root', + 'site', + 'time_format' + ); + + const { currentUserAvatar, currentUserName } = useSelect( ( select ) => { + const userData = select( coreStore ).getCurrentUser(); + + const { getSettings } = select( blockEditorStore ); + const { __experimentalDiscussionSettings } = getSettings(); + const defaultAvatar = __experimentalDiscussionSettings?.avatarURL; + return { + currentUserAvatar: userData?.avatar_urls[ 48 ] ?? defaultAvatar, + currentUserName: userData?.name, + }; + }, [] ); + + const currentDate = new Date(); + + return ( + <> + <img + src={ avatar ?? currentUserAvatar } + className="editor-collab-sidebar-panel__user-avatar" + // translators: alt text for user avatar image + alt={ __( 'User avatar' ) } + width={ 32 } + height={ 32 } + /> + <VStack spacing="0"> + <span className="editor-collab-sidebar-panel__user-name"> + { name ?? currentUserName } + </span> + <time + dateTime={ dateI18n( 'c', date ?? currentDate ) } + className="editor-collab-sidebar-panel__user-time" + > + { dateI18n( dateTimeFormat, date ?? currentDate ) } + </time> + </VStack> + </> + ); +} + +export default CommentAuthorInfo; diff --git a/packages/editor/src/components/collab-sidebar/comment-form.js b/packages/editor/src/components/collab-sidebar/comment-form.js new file mode 100644 index 00000000000000..28622f9f52a6f8 --- /dev/null +++ b/packages/editor/src/components/collab-sidebar/comment-form.js @@ -0,0 +1,62 @@ +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; +import { + __experimentalHStack as HStack, + Button, + TextareaControl, +} from '@wordpress/components'; +import { _x } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { sanitizeCommentString } from './utils'; + +/** + * EditComment component. + * + * @param {Object} props - The component props. + * @param {Function} props.onSubmit - The function to call when updating the comment. + * @param {Function} props.onCancel - The function to call when canceling the comment update. + * @param {Object} props.thread - The comment thread object. + * @param {string} props.submitButtonText - The text to display on the submit button. + * @return {JSX.Element} The CommentForm component. + */ +function CommentForm( { onSubmit, onCancel, thread, submitButtonText } ) { + const [ inputComment, setInputComment ] = useState( + thread?.content?.raw ?? '' + ); + + return ( + <> + <TextareaControl + __next40pxDefaultSize + __nextHasNoMarginBottom + value={ inputComment ?? '' } + onChange={ setInputComment } + /> + <HStack alignment="left" spacing="3" justify="flex-start"> + <Button + __next40pxDefaultSize + accessibleWhenDisabled + variant="primary" + onClick={ () => onSubmit( inputComment ) } + disabled={ + 0 === sanitizeCommentString( inputComment ).length + } + text={ submitButtonText } + /> + <Button + __next40pxDefaultSize + variant="tertiary" + onClick={ onCancel } + text={ _x( 'Cancel', 'Cancel comment button' ) } + /> + </HStack> + </> + ); +} + +export default CommentForm; diff --git a/packages/editor/src/components/collab-sidebar/comments.js b/packages/editor/src/components/collab-sidebar/comments.js index c0b4bd3d4dc38a..808ea0acf04b31 100644 --- a/packages/editor/src/components/collab-sidebar/comments.js +++ b/packages/editor/src/components/collab-sidebar/comments.js @@ -13,24 +13,18 @@ import { __experimentalConfirmDialog as ConfirmDialog, Button, DropdownMenu, - TextareaControl, Tooltip, } from '@wordpress/components'; -import { - dateI18n, - format, - getSettings as getDateSettings, -} from '@wordpress/date'; import { Icon, check, published, moreVertical } from '@wordpress/icons'; import { __, _x } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; -import { useEntityProp } from '@wordpress/core-data'; import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Internal dependencies */ -import { sanitizeCommentString } from './utils'; +import CommentAuthorInfo from './comment-author-info'; +import CommentForm from './comment-form'; /** * Renders the Comments component. @@ -127,6 +121,7 @@ export function Comments( { } } onCancel={ () => setActionState( false ) } thread={ thread } + submitButtonText={ _x( 'Update', 'verb' ) } /> ) } { ( ! actionState || @@ -209,14 +204,33 @@ export function Comments( { spacing="3" > <CommentBoard thread={ thread } /> + { 0 < thread?.reply?.length && + thread.reply.map( ( reply ) => ( + <VStack + key={ reply.id } + className="editor-collab-sidebar-panel__child-thread" + id={ reply.id } + spacing="2" + > + <CommentBoard + thread={ reply } + parentThread={ thread } + /> + </VStack> + ) ) } { 'reply' === actionState?.action && thread.id === actionState?.id && ( - <HStack - alignment="left" - spacing="3" - justify="flex-start" - className="editor-collab-sidebar-panel__user-comment" + <VStack + className="editor-collab-sidebar-panel__child-thread" + spacing="2" > + <HStack + alignment="left" + spacing="3" + justify="flex-start" + > + <CommentAuthorInfo /> + </HStack> <VStack spacing="3" className="editor-collab-sidebar-panel__comment-field" @@ -232,75 +246,20 @@ export function Comments( { onCancel={ () => setActionState( false ) } + submitButtonText={ _x( + 'Reply', + 'Add reply comment' + ) } /> </VStack> - </HStack> - ) } - { 0 < thread?.reply?.length && - thread.reply.map( ( reply ) => ( - <VStack - key={ reply.id } - className="editor-collab-sidebar-panel__child-thread" - id={ reply.id } - spacing="2" - > - <CommentBoard - thread={ reply } - parentThread={ thread } - /> </VStack> - ) ) } + ) } </VStack> ) ) } </> ); } -/** - * EditComment component. - * - * @param {Object} props - The component props. - * @param {Function} props.onSubmit - The function to call when updating the comment. - * @param {Function} props.onCancel - The function to call when canceling the comment update. - * @param {Object} props.thread - The comment thread object. - * @return {JSX.Element} The CommentForm component. - */ -function CommentForm( { onSubmit, onCancel, thread } ) { - const [ inputComment, setInputComment ] = useState( - thread?.content?.raw ?? '' - ); - - return ( - <> - <TextareaControl - __nextHasNoMarginBottom - value={ inputComment ?? '' } - onChange={ setInputComment } - /> - <VStack alignment="left" spacing="3" justify="flex-start"> - <HStack alignment="left" spacing="3" justify="flex-start"> - <Button - __next40pxDefaultSize - accessibleWhenDisabled - variant="primary" - onClick={ () => onSubmit( inputComment ) } - disabled={ - 0 === sanitizeCommentString( inputComment ).length - } - > - { thread - ? _x( 'Update', 'verb' ) - : _x( 'Reply', 'Add reply comment' ) } - </Button> - <Button __next40pxDefaultSize onClick={ onCancel }> - { _x( 'Cancel', 'Cancel comment edit' ) } - </Button> - </HStack> - </VStack> - </> - ); -} - /** * Renders the header of a comment in the collaboration sidebar. * @@ -321,13 +280,6 @@ function CommentHeader( { onReply, status, } ) { - const dateSettings = getDateSettings(); - const [ dateTimeFormat = dateSettings.formats.time ] = useEntityProp( - 'root', - 'site', - 'time_format' - ); - const actions = [ { title: _x( 'Edit', 'Edit comment' ), @@ -347,29 +299,15 @@ function CommentHeader( { return ( <HStack alignment="left" spacing="3" justify="flex-start"> - <img - src={ thread?.author_avatar_urls?.[ 48 ] } - className="editor-collab-sidebar-panel__user-avatar" - // translators: alt text for user avatar image - alt={ __( 'User avatar' ) } - width={ 32 } - height={ 32 } + <CommentAuthorInfo + avatar={ thread?.author_avatar_urls?.[ 48 ] } + name={ thread?.author_name } + date={ thread?.date } /> - <VStack spacing="0"> - <span className="editor-collab-sidebar-panel__user-name"> - { thread.author_name } - </span> - <time - dateTime={ format( 'h:i A', thread.date ) } - className="editor-collab-sidebar-panel__user-time" - > - { dateI18n( dateTimeFormat, thread.date ) } - </time> - </VStack> <span className="editor-collab-sidebar-panel__comment-status"> { status !== 'approved' && ( <HStack alignment="right" justify="flex-end" spacing="0"> - { 0 === thread.parent && onResolve && ( + { 0 === thread?.parent && onResolve && ( <Button label={ _x( 'Resolve', From 2f45eb89cf4354a0b8cf08a71b527b310e882782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= <grzegorz@gziolo.pl> Date: Mon, 18 Nov 2024 10:49:40 +0100 Subject: [PATCH 1604/1908] WP Scripts: Revert changes that inline CSS imports early in the build process (#66975) * WP Scripts: Revert changes that inline CSS imports early in the build process * Fix changelog entry Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: benoitchantre <benoitchantre@git.wordpress.org> Co-authored-by: loxK <dreadlox@git.wordpress.org> --- package-lock.json | 32 +---------------------- package.json | 1 - packages/scripts/CHANGELOG.md | 4 +++ packages/scripts/config/webpack.config.js | 1 - packages/scripts/package.json | 1 - 5 files changed, 5 insertions(+), 34 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2f8f627dca805c..0eb2d6ce058223 100644 --- a/package-lock.json +++ b/package-lock.json @@ -119,7 +119,6 @@ "npm-run-all": "4.1.5", "patch-package": "8.0.0", "postcss": "8.4.38", - "postcss-import": "16.1.0", "postcss-loader": "6.2.1", "postcss-local-keyframes": "^0.0.2", "prettier": "npm:wp-prettier@3.0.3", @@ -40557,6 +40556,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -40836,27 +40836,6 @@ "postcss": "^8.2.15" } }, - "node_modules/postcss-import": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz", - "integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-import/node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" - }, "node_modules/postcss-loader": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", @@ -43337,14 +43316,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dependencies": { - "pify": "^2.3.0" - } - }, "node_modules/read-cmd-shim": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz", @@ -55585,7 +55556,6 @@ "npm-package-json-lint": "^6.4.0", "npm-packlist": "^3.0.0", "postcss": "^8.4.5", - "postcss-import": "^16.1.0", "postcss-loader": "^6.2.1", "prettier": "npm:wp-prettier@3.0.3", "puppeteer-core": "^23.1.0", diff --git a/package.json b/package.json index 87cf9a5cacd943..f987643e737563 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,6 @@ "npm-run-all": "4.1.5", "patch-package": "8.0.0", "postcss": "8.4.38", - "postcss-import": "16.1.0", "postcss-loader": "6.2.1", "postcss-local-keyframes": "^0.0.2", "prettier": "npm:wp-prettier@3.0.3", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 452028cab49cd1..ab927f62f08899 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fix + +- Revert changes from [#61121](https://github.com/WordPress/gutenberg/pull/61121) that inlined CSS files imported from other CSS files before optimization in the `build` command. + ## 30.5.0 (2024-11-16) ### Bug Fix diff --git a/packages/scripts/config/webpack.config.js b/packages/scripts/config/webpack.config.js index 91ef19fc27ed6b..f9ef7dc5b7acca 100644 --- a/packages/scripts/config/webpack.config.js +++ b/packages/scripts/config/webpack.config.js @@ -75,7 +75,6 @@ const cssLoaders = [ plugins: isProduction ? [ ...postcssPlugins, - require( 'postcss-import' ), require( 'cssnano' )( { // Provide a fallback configuration if there's not // one explicitly available in the project. diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 34629bf9843ff7..5545e136939bf3 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -74,7 +74,6 @@ "npm-package-json-lint": "^6.4.0", "npm-packlist": "^3.0.0", "postcss": "^8.4.5", - "postcss-import": "^16.1.0", "postcss-loader": "^6.2.1", "prettier": "npm:wp-prettier@3.0.3", "puppeteer-core": "^23.1.0", From 985d63d6fbc6feb5ff272432de31f8cc2dfe32a1 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Mon, 18 Nov 2024 09:53:41 +0000 Subject: [PATCH 1605/1908] Update Changelog for 19.6.3 --- changelog.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/changelog.txt b/changelog.txt index ba6f0ce133ec1c..6036acdf97256f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,10 @@ == Changelog == += 19.6.3 = + +- Revert "Set image width to fit-content to solve aspect ratio problems in Firefox. ([#66217](https://github.com/WordPress/gutenberg/pull/66804)) + + = 19.7.0-rc.2 = From 0323067506415f545dcafe63d9644af89c8e64ce Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Mon, 18 Nov 2024 09:53:47 +0000 Subject: [PATCH 1606/1908] Update changelog files --- packages/scripts/CHANGELOG.md | 2 ++ packages/scripts/package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index ab927f62f08899..0decdaca528b2e 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 30.5.1 (2024-11-18) + ### Bug Fix - Revert changes from [#61121](https://github.com/WordPress/gutenberg/pull/61121) that inlined CSS files imported from other CSS files before optimization in the `build` command. diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 5545e136939bf3..ecd867d0216091 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.5.0", + "version": "30.5.1-prerelease", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 3fa404878272cf0d5b20ac875f3d189e7846fe41 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Mon, 18 Nov 2024 09:55:34 +0000 Subject: [PATCH 1607/1908] chore(release): publish - @wordpress/scripts@30.5.1 --- package-lock.json | 2 +- packages/scripts/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0eb2d6ce058223..52797a4cbe4625 100644 --- a/package-lock.json +++ b/package-lock.json @@ -55511,7 +55511,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "30.5.0", + "version": "30.5.1", "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index ecd867d0216091..fa50f90362a6f0 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.5.1-prerelease", + "version": "30.5.1", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 9820a8c3dee1e877cb5ed3834bb6ca74f6a13173 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Mon, 18 Nov 2024 11:58:26 +0100 Subject: [PATCH 1608/1908] SlotFill: remove registration API from useSlot result (#67070) * SlotFill: remove registration API from useSlot result * Add changelog entry Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 +++ .../src/slot-fill/bubbles-virtually/fill.tsx | 25 +++++++++------ .../slot-fill/bubbles-virtually/use-slot.ts | 31 ++----------------- 3 files changed, 23 insertions(+), 37 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index d3700e6f25a8d5..8b72af17cae987 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -11,6 +11,10 @@ - `ToggleGroupControl`: Fix active background for `0` value ([#66855](https://github.com/WordPress/gutenberg/pull/66855)). - `SlotFill`: Fix a bug where a stale value of `fillProps` could be used ([#67000](https://github.com/WordPress/gutenberg/pull/67000)). +### Experimental + +- `SlotFill`: Remove registration API methods from return value of `__experimentalUseSlot` ([#67070](https://github.com/WordPress/gutenberg/pull/67070)). + ## 28.12.0 (2024-11-16) ### Deprecations diff --git a/packages/components/src/slot-fill/bubbles-virtually/fill.tsx b/packages/components/src/slot-fill/bubbles-virtually/fill.tsx index 3cfadbadc62c4b..b1b82aac5c0567 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/fill.tsx +++ b/packages/components/src/slot-fill/bubbles-virtually/fill.tsx @@ -1,12 +1,19 @@ /** * WordPress dependencies */ -import { useRef, useState, useEffect, createPortal } from '@wordpress/element'; +import { useObservableValue } from '@wordpress/compose'; +import { + useContext, + useRef, + useState, + useEffect, + createPortal, +} from '@wordpress/element'; /** * Internal dependencies */ -import useSlot from './use-slot'; +import SlotFillContext from './slot-fill-context'; import StyleProvider from '../../style-provider'; import type { FillComponentProps } from '../types'; @@ -28,9 +35,9 @@ function useForceUpdate() { }; } -export default function Fill( props: FillComponentProps ) { - const { name, children } = props; - const { registerFill, unregisterFill, ...slot } = useSlot( name ); +export default function Fill( { name, children }: FillComponentProps ) { + const registry = useContext( SlotFillContext ); + const slot = useObservableValue( registry.slots, name ); const rerender = useForceUpdate(); const ref = useRef( { rerender } ); @@ -38,13 +45,13 @@ export default function Fill( props: FillComponentProps ) { // We register fills so we can keep track of their existence. // Some Slot implementations need to know if there're already fills // registered so they can choose to render themselves or not. - registerFill( ref ); + registry.registerFill( name, ref ); return () => { - unregisterFill( ref ); + registry.unregisterFill( name, ref ); }; - }, [ registerFill, unregisterFill ] ); + }, [ registry, name ] ); - if ( ! slot.ref || ! slot.ref.current ) { + if ( ! slot || ! slot.ref.current ) { return null; } diff --git a/packages/components/src/slot-fill/bubbles-virtually/use-slot.ts b/packages/components/src/slot-fill/bubbles-virtually/use-slot.ts index ec78771bfa92af..cac57a024e4ee2 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/use-slot.ts +++ b/packages/components/src/slot-fill/bubbles-virtually/use-slot.ts @@ -1,42 +1,17 @@ /** * WordPress dependencies */ -import { useMemo, useContext } from '@wordpress/element'; +import { useContext } from '@wordpress/element'; import { useObservableValue } from '@wordpress/compose'; /** * Internal dependencies */ import SlotFillContext from './slot-fill-context'; -import type { - SlotFillBubblesVirtuallyFillRef, - SlotFillBubblesVirtuallySlotRef, - FillProps, - SlotKey, -} from '../types'; +import type { SlotKey } from '../types'; export default function useSlot( name: SlotKey ) { const registry = useContext( SlotFillContext ); const slot = useObservableValue( registry.slots, name ); - - const api = useMemo( - () => ( { - updateSlot: ( - ref: SlotFillBubblesVirtuallySlotRef, - fillProps: FillProps - ) => registry.updateSlot( name, ref, fillProps ), - unregisterSlot: ( ref: SlotFillBubblesVirtuallySlotRef ) => - registry.unregisterSlot( name, ref ), - registerFill: ( ref: SlotFillBubblesVirtuallyFillRef ) => - registry.registerFill( name, ref ), - unregisterFill: ( ref: SlotFillBubblesVirtuallyFillRef ) => - registry.unregisterFill( name, ref ), - } ), - [ name, registry ] - ); - - return { - ...slot, - ...api, - }; + return { ...slot }; } From c22ecefcbf4b69c5ca0edbe8019c65c3c3f3fbf6 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 18 Nov 2024 12:40:36 +0100 Subject: [PATCH 1609/1908] Extract selectors from useResolveEditedEntity hook (#67031) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- packages/core-data/src/private-selectors.ts | 150 ++++++++++++++++- .../edit-post/src/components/layout/index.js | 15 +- packages/edit-post/src/store/index.js | 3 - .../edit-post/src/store/private-selectors.js | 61 ------- packages/edit-post/src/store/selectors.js | 11 +- .../editor/use-resolve-edited-entity.js | 154 ++---------------- 6 files changed, 184 insertions(+), 210 deletions(-) delete mode 100644 packages/edit-post/src/store/private-selectors.js diff --git a/packages/core-data/src/private-selectors.ts b/packages/core-data/src/private-selectors.ts index b2f6fa7def9858..02fe152ed0abb6 100644 --- a/packages/core-data/src/private-selectors.ts +++ b/packages/core-data/src/private-selectors.ts @@ -6,8 +6,9 @@ import { createSelector, createRegistrySelector } from '@wordpress/data'; /** * Internal dependencies */ -import type { State } from './selectors'; +import { getDefaultTemplateId, getEntityRecord, type State } from './selectors'; import { STORE_NAME } from './name'; +import { unlock } from './lock-unlock'; type EntityRecordKey = string | number; @@ -105,3 +106,150 @@ export function getEntityRecordPermissions( export function getRegisteredPostMeta( state: State, postType: string ) { return state.registeredPostMeta?.[ postType ] ?? {}; } + +function normalizePageId( value: number | string | undefined ): string | null { + if ( ! value || ! [ 'number', 'string' ].includes( typeof value ) ) { + return null; + } + + // We also need to check if it's not zero (`'0'`). + if ( Number( value ) === 0 ) { + return null; + } + + return value.toString(); +} + +interface SiteData { + show_on_front?: string; + page_on_front?: string | number; + page_for_posts?: string | number; +} + +export const getHomePage = createRegistrySelector( ( select ) => + createSelector( + () => { + const siteData = select( STORE_NAME ).getEntityRecord( + 'root', + 'site' + ) as SiteData | undefined; + if ( ! siteData ) { + return null; + } + const homepageId = + siteData?.show_on_front === 'page' + ? normalizePageId( siteData.page_on_front ) + : null; + if ( homepageId ) { + return { postType: 'page', postId: homepageId }; + } + const frontPageTemplateId = select( + STORE_NAME + ).getDefaultTemplateId( { + slug: 'front-page', + } ); + return { postType: 'wp_template', postId: frontPageTemplateId }; + }, + ( state ) => [ + // @ts-expect-error + getEntityRecord( state, 'root', 'site' ), + getDefaultTemplateId( state, { + slug: 'front-page', + } ), + ] + ) +); + +export const getPostsPageId = createRegistrySelector( ( select ) => () => { + const siteData = select( STORE_NAME ).getEntityRecord( 'root', 'site' ) as + | SiteData + | undefined; + return siteData?.show_on_front === 'page' + ? normalizePageId( siteData.page_for_posts ) + : null; +} ); + +export const getTemplateId = createRegistrySelector( + ( select ) => ( state, postType, postId ) => { + const homepage = unlock( select( STORE_NAME ) ).getHomePage(); + + if ( ! homepage ) { + return; + } + + // For the front page, we always use the front page template if existing. + if ( + postType === 'page' && + postType === homepage?.postType && + postId.toString() === homepage?.postId + ) { + // The /lookup endpoint cannot currently handle a lookup + // when a page is set as the front page, so specifically in + // that case, we want to check if there is a front page + // template, and instead of falling back to the home + // template, we want to fall back to the page template. + const templates = select( STORE_NAME ).getEntityRecords( + 'postType', + 'wp_template', + { + per_page: -1, + } + ); + if ( ! templates ) { + return; + } + const id = templates.find( ( { slug } ) => slug === 'front-page' ) + ?.id; + if ( id ) { + return id; + } + // If no front page template is found, continue with the + // logic below (fetching the page template). + } + + const editedEntity = select( STORE_NAME ).getEditedEntityRecord( + 'postType', + postType, + postId + ); + if ( ! editedEntity ) { + return; + } + const postsPageId = unlock( select( STORE_NAME ) ).getPostsPageId(); + // Check if the current page is the posts page. + if ( postType === 'page' && postsPageId === postId.toString() ) { + return select( STORE_NAME ).getDefaultTemplateId( { + slug: 'home', + } ); + } + // First see if the post/page has an assigned template and fetch it. + const currentTemplateSlug = editedEntity.template; + if ( currentTemplateSlug ) { + const currentTemplate = select( STORE_NAME ) + .getEntityRecords( 'postType', 'wp_template', { + per_page: -1, + } ) + ?.find( ( { slug } ) => slug === currentTemplateSlug ); + if ( currentTemplate ) { + return currentTemplate.id; + } + } + // If no template is assigned, use the default template. + let slugToCheck; + // In `draft` status we might not have a slug available, so we use the `single` + // post type templates slug(ex page, single-post, single-product etc..). + // Pages do not need the `single` prefix in the slug to be prioritized + // through template hierarchy. + if ( editedEntity.slug ) { + slugToCheck = + postType === 'page' + ? `${ postType }-${ editedEntity.slug }` + : `single-${ postType }-${ editedEntity.slug }`; + } else { + slugToCheck = postType === 'page' ? 'page' : `single-${ postType }`; + } + return select( STORE_NAME ).getDefaultTemplateId( { + slug: slugToCheck, + } ); + } +); diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 225788a15a8e1d..aec14eab989f03 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -399,10 +399,10 @@ function Layout( { } = useSelect( ( select ) => { const { get } = select( preferencesStore ); - const { isFeatureActive, getEditedPostTemplateId } = unlock( - select( editPostStore ) + const { isFeatureActive } = select( editPostStore ); + const { canUser, getPostType, getTemplateId } = unlock( + select( coreStore ) ); - const { canUser, getPostType } = select( coreStore ); const supportsTemplateMode = settings.supportsTemplateMode; const isViewable = @@ -433,7 +433,7 @@ function Layout( { isViewable && canViewTemplate && ! isEditingTemplate - ? getEditedPostTemplateId() + ? getTemplateId( currentPostType, currentPostId ) : null, enablePaddingAppender: ! isZoomOut() && @@ -441,7 +441,12 @@ function Layout( { ! DESIGN_POST_TYPES.includes( currentPostType ), }; }, - [ currentPostType, isEditingTemplate, settings.supportsTemplateMode ] + [ + currentPostType, + currentPostId, + isEditingTemplate, + settings.supportsTemplateMode, + ] ); const [ paddingAppenderRef, paddingStyle ] = usePaddingAppender( enablePaddingAppender diff --git a/packages/edit-post/src/store/index.js b/packages/edit-post/src/store/index.js index 17033b759292d7..93dae7606d0e3c 100644 --- a/packages/edit-post/src/store/index.js +++ b/packages/edit-post/src/store/index.js @@ -9,9 +9,7 @@ import { createReduxStore, register } from '@wordpress/data'; import reducer from './reducer'; import * as actions from './actions'; import * as selectors from './selectors'; -import * as privateSelectors from './private-selectors'; import { STORE_NAME } from './constants'; -import { unlock } from '../lock-unlock'; /** * Store definition for the edit post namespace. @@ -26,4 +24,3 @@ export const store = createReduxStore( STORE_NAME, { selectors, } ); register( store ); -unlock( store ).registerPrivateSelectors( privateSelectors ); diff --git a/packages/edit-post/src/store/private-selectors.js b/packages/edit-post/src/store/private-selectors.js deleted file mode 100644 index 246b2754d895ab..00000000000000 --- a/packages/edit-post/src/store/private-selectors.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * WordPress dependencies - */ -import { createRegistrySelector } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; -import { store as editorStore } from '@wordpress/editor'; - -export const getEditedPostTemplateId = createRegistrySelector( - ( select ) => () => { - const { - id: postId, - type: postType, - slug, - } = select( editorStore ).getCurrentPost(); - const { getEntityRecord, getEntityRecords, canUser } = - select( coreStore ); - const siteSettings = canUser( 'read', { - kind: 'root', - name: 'site', - } ) - ? getEntityRecord( 'root', 'site' ) - : undefined; - // First check if the current page is set as the posts page. - const isPostsPage = +postId === siteSettings?.page_for_posts; - if ( isPostsPage ) { - return select( coreStore ).getDefaultTemplateId( { slug: 'home' } ); - } - const currentTemplate = - select( editorStore ).getEditedPostAttribute( 'template' ); - if ( currentTemplate ) { - const templateWithSameSlug = getEntityRecords( - 'postType', - 'wp_template', - { per_page: -1 } - )?.find( ( template ) => template.slug === currentTemplate ); - if ( ! templateWithSameSlug ) { - return templateWithSameSlug; - } - return templateWithSameSlug.id; - } - let slugToCheck; - // In `draft` status we might not have a slug available, so we use the `single` - // post type templates slug(ex page, single-post, single-product etc..). - // Pages do not need the `single` prefix in the slug to be prioritized - // through template hierarchy. - if ( slug ) { - slugToCheck = - postType === 'page' - ? `${ postType }-${ slug }` - : `single-${ postType }-${ slug }`; - } else { - slugToCheck = postType === 'page' ? 'page' : `single-${ postType }`; - } - - if ( postType ) { - return select( coreStore ).getDefaultTemplateId( { - slug: slugToCheck, - } ); - } - } -); diff --git a/packages/edit-post/src/store/selectors.js b/packages/edit-post/src/store/selectors.js index 8d85249e8100ba..f6516dd0206c00 100644 --- a/packages/edit-post/src/store/selectors.js +++ b/packages/edit-post/src/store/selectors.js @@ -14,8 +14,6 @@ import deprecated from '@wordpress/deprecated'; * Internal dependencies */ import { unlock } from '../lock-unlock'; -import { getEditedPostTemplateId } from './private-selectors'; - const { interfaceStore } = unlock( editorPrivateApis ); const EMPTY_ARRAY = []; const EMPTY_OBJECT = {}; @@ -555,8 +553,13 @@ export function areMetaBoxesInitialized( state ) { * @return {Object?} Post Template. */ export const getEditedPostTemplate = createRegistrySelector( - ( select ) => ( state ) => { - const templateId = getEditedPostTemplateId( state ); + ( select ) => () => { + const { id: postId, type: postType } = + select( editorStore ).getCurrentPost(); + const templateId = unlock( select( coreStore ) ).getTemplateId( + postType, + postId + ); if ( ! templateId ) { return undefined; } diff --git a/packages/edit-site/src/components/editor/use-resolve-edited-entity.js b/packages/edit-site/src/components/editor/use-resolve-edited-entity.js index eb19b3cea95375..4f873738704141 100644 --- a/packages/edit-site/src/components/editor/use-resolve-edited-entity.js +++ b/packages/edit-site/src/components/editor/use-resolve-edited-entity.js @@ -32,33 +32,10 @@ const authorizedPostTypes = [ 'page', 'post' ]; export function useResolveEditedEntity() { const { params = {} } = useLocation(); const { postId, postType } = params; - const { hasLoadedAllDependencies, homepageId, postsPageId } = useSelect( - ( select ) => { - const { getEntityRecord } = select( coreDataStore ); - const siteData = getEntityRecord( 'root', 'site' ); - const _homepageId = - siteData?.show_on_front === 'page' && - [ 'number', 'string' ].includes( - typeof siteData.page_on_front - ) && - !! +siteData.page_on_front // We also need to check if it's not zero(`0`). - ? siteData.page_on_front.toString() - : null; - const _postsPageId = - siteData?.show_on_front === 'page' && - [ 'number', 'string' ].includes( - typeof siteData.page_for_posts - ) - ? siteData.page_for_posts.toString() - : null; - return { - hasLoadedAllDependencies: !! siteData, - homepageId: _homepageId, - postsPageId: _postsPageId, - }; - }, - [] - ); + const homePage = useSelect( ( select ) => { + const { getHomePage } = unlock( select( coreDataStore ) ); + return getHomePage(); + }, [] ); /** * This is a hook that recreates the logic to resolve a template for a given WordPress postID postTypeId @@ -74,111 +51,15 @@ export function useResolveEditedEntity() { postTypesWithoutParentTemplate.includes( postType ) && postId ) { - return undefined; + return; } // Don't trigger resolution for multi-selected posts. if ( postId && postId.includes( ',' ) ) { - return undefined; + return; } - const { - getEditedEntityRecord, - getEntityRecords, - getDefaultTemplateId, - } = select( coreDataStore ); - - function resolveTemplateForPostTypeAndId( - postTypeToResolve, - postIdToResolve - ) { - // For the front page, we always use the front page template if existing. - if ( - postTypeToResolve === 'page' && - homepageId === postIdToResolve - ) { - // The /lookup endpoint cannot currently handle a lookup - // when a page is set as the front page, so specifically in - // that case, we want to check if there is a front page - // template, and instead of falling back to the home - // template, we want to fall back to the page template. - const templates = getEntityRecords( - 'postType', - TEMPLATE_POST_TYPE, - { - per_page: -1, - } - ); - if ( templates ) { - const id = templates?.find( - ( { slug } ) => slug === 'front-page' - )?.id; - if ( id ) { - return id; - } - - // If no front page template is found, continue with the - // logic below (fetching the page template). - } else { - // Still resolving `templates`. - return undefined; - } - } - - const editedEntity = getEditedEntityRecord( - 'postType', - postTypeToResolve, - postIdToResolve - ); - if ( ! editedEntity ) { - return undefined; - } - // Check if the current page is the posts page. - if ( - postTypeToResolve === 'page' && - postsPageId === postIdToResolve - ) { - return getDefaultTemplateId( { slug: 'home' } ); - } - // First see if the post/page has an assigned template and fetch it. - const currentTemplateSlug = editedEntity.template; - if ( currentTemplateSlug ) { - const currentTemplate = getEntityRecords( - 'postType', - TEMPLATE_POST_TYPE, - { - per_page: -1, - } - )?.find( ( { slug } ) => slug === currentTemplateSlug ); - if ( currentTemplate ) { - return currentTemplate.id; - } - } - // If no template is assigned, use the default template. - let slugToCheck; - // In `draft` status we might not have a slug available, so we use the `single` - // post type templates slug(ex page, single-post, single-product etc..). - // Pages do not need the `single` prefix in the slug to be prioritized - // through template hierarchy. - if ( editedEntity.slug ) { - slugToCheck = - postTypeToResolve === 'page' - ? `${ postTypeToResolve }-${ editedEntity.slug }` - : `single-${ postTypeToResolve }-${ editedEntity.slug }`; - } else { - slugToCheck = - postTypeToResolve === 'page' - ? 'page' - : `single-${ postTypeToResolve }`; - } - return getDefaultTemplateId( { - slug: slugToCheck, - } ); - } - - if ( ! hasLoadedAllDependencies ) { - return undefined; - } + const { getTemplateId } = unlock( select( coreDataStore ) ); // If we're rendering a specific page, we need to resolve its template. // The site editor only supports pages for now, not other CPTs. @@ -187,18 +68,19 @@ export function useResolveEditedEntity() { postId && authorizedPostTypes.includes( postType ) ) { - return resolveTemplateForPostTypeAndId( postType, postId ); + return getTemplateId( postType, postId ); } // If we're rendering the home page, and we have a static home page, resolve its template. - if ( homepageId ) { - return resolveTemplateForPostTypeAndId( 'page', homepageId ); + if ( homePage?.postType === 'page' ) { + return getTemplateId( 'page', homePage?.postId ); } - // If we're not rendering a specific page, use the front page template. - return getDefaultTemplateId( { slug: 'front-page' } ); + if ( homePage?.postType === 'wp_template' ) { + return homePage?.postId; + } }, - [ homepageId, postsPageId, hasLoadedAllDependencies, postId, postType ] + [ homePage, postId, postType ] ); const context = useMemo( () => { @@ -211,18 +93,18 @@ export function useResolveEditedEntity() { } // TODO: for post types lists we should probably not render the front page, but maybe a placeholder // with a message like "Select a page" or something similar. - if ( homepageId ) { - return { postType: 'page', postId: homepageId }; + if ( homePage?.postType === 'page' ) { + return { postType: 'page', postId: homePage?.postId }; } return {}; - }, [ homepageId, postType, postId ] ); + }, [ homePage, postType, postId ] ); if ( postTypesWithoutParentTemplate.includes( postType ) && postId ) { return { isReady: true, postType, postId, context }; } - if ( hasLoadedAllDependencies ) { + if ( !! homePage ) { return { isReady: resolvedTemplateId !== undefined, postType: TEMPLATE_POST_TYPE, From f6e6e4545dc59e224586a6a5b9cea8744142b5a2 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Mon, 18 Nov 2024 15:26:16 +0100 Subject: [PATCH 1610/1908] SlotFill: fix dependencies of registration effects, deduplicate code (#67071) * SlotFill: fix dependencies of registration effects, deduplicate code * Add changelog entry Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/slot-fill/fill.ts | 27 +++++------------------ 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 8b72af17cae987..8c217c90ba1b7d 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -15,6 +15,10 @@ - `SlotFill`: Remove registration API methods from return value of `__experimentalUseSlot` ([#67070](https://github.com/WordPress/gutenberg/pull/67070)). +### Internal + +- `SlotFill`: fix dependencies of `Fill` registration effects ([#67071](https://github.com/WordPress/gutenberg/pull/67071)). + ## 28.12.0 (2024-11-16) ### Deprecations diff --git a/packages/components/src/slot-fill/fill.ts b/packages/components/src/slot-fill/fill.ts index 4134af25684b07..b11b7af09b82f0 100644 --- a/packages/components/src/slot-fill/fill.ts +++ b/packages/components/src/slot-fill/fill.ts @@ -11,7 +11,7 @@ import useSlot from './use-slot'; import type { FillComponentProps } from './types'; export default function Fill( { name, children }: FillComponentProps ) { - const { registerFill, unregisterFill } = useContext( SlotFillContext ); + const registry = useContext( SlotFillContext ); const slot = useSlot( name ); const ref = useRef( { @@ -21,32 +21,17 @@ export default function Fill( { name, children }: FillComponentProps ) { useLayoutEffect( () => { const refValue = ref.current; - registerFill( name, refValue ); - return () => unregisterFill( name, refValue ); - // The useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior. - // We'll leave them as-is until a more detailed investigation/refactor can be performed. - }, [] ); + refValue.name = name; + registry.registerFill( name, refValue ); + return () => registry.unregisterFill( name, refValue ); + }, [ registry, name ] ); useLayoutEffect( () => { ref.current.children = children; if ( slot ) { slot.forceUpdate(); } - // The useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior. - // We'll leave them as-is until a more detailed investigation/refactor can be performed. - }, [ children ] ); - - useLayoutEffect( () => { - if ( name === ref.current.name ) { - // Ignore initial effect. - return; - } - unregisterFill( ref.current.name, ref.current ); - ref.current.name = name; - registerFill( name, ref.current ); - // The useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior. - // We'll leave them as-is until a more detailed investigation/refactor can be performed. - }, [ name ] ); + }, [ slot, children ] ); return null; } From d5e7bcace7cb8714e007495f3c8ce857c0340b28 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Mon, 18 Nov 2024 16:33:46 +0100 Subject: [PATCH 1611/1908] PostTitle: exit early when post type doesn't support titles (#67086) Unlinked contributors: mijan-xs. Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Tropicalista <tropicalista@git.wordpress.org> --- .../editor/src/components/post-title/index.js | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/packages/editor/src/components/post-title/index.js b/packages/editor/src/components/post-title/index.js index 50595d936b36d9..7fc79eaeddffb5 100644 --- a/packages/editor/src/components/post-title/index.js +++ b/packages/editor/src/components/post-title/index.js @@ -28,7 +28,7 @@ import usePostTitleFocus from './use-post-title-focus'; import usePostTitle from './use-post-title'; import PostTypeSupportCheck from '../post-type-support-check'; -function PostTitle( _, forwardedRef ) { +const PostTitle = forwardRef( ( _, forwardedRef ) => { const { placeholder } = useSelect( ( select ) => { const { getSettings } = select( blockEditorStore ); const { titlePlaceholder } = getSettings(); @@ -171,23 +171,21 @@ function PostTitle( _, forwardedRef ) { return ( /* eslint-disable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-to-interactive-role */ - <PostTypeSupportCheck supportKeys="title"> - <h1 - ref={ useMergeRefs( [ richTextRef, focusRef ] ) } - contentEditable - className={ className } - aria-label={ decodedPlaceholder } - role="textbox" - aria-multiline="true" - onFocus={ onSelect } - onBlur={ onUnselect } - onKeyDown={ onKeyDown } - onPaste={ onPaste } - /> - </PostTypeSupportCheck> + <h1 + ref={ useMergeRefs( [ richTextRef, focusRef ] ) } + contentEditable + className={ className } + aria-label={ decodedPlaceholder } + role="textbox" + aria-multiline="true" + onFocus={ onSelect } + onBlur={ onUnselect } + onKeyDown={ onKeyDown } + onPaste={ onPaste } + /> /* eslint-enable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-to-interactive-role */ ); -} +} ); /** * Renders the `PostTitle` component. @@ -197,4 +195,8 @@ function PostTitle( _, forwardedRef ) { * * @return {Component} The rendered PostTitle component. */ -export default forwardRef( PostTitle ); +export default forwardRef( ( _, forwardedRef ) => ( + <PostTypeSupportCheck supportKeys="title"> + <PostTitle ref={ forwardedRef } /> + </PostTypeSupportCheck> +) ); From eb79dc1adfb91bf9ede33a32142ad96b600aab09 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Tue, 19 Nov 2024 01:02:25 +0900 Subject: [PATCH 1612/1908] Edit Site: Fix settings mutation in ScreenBlock (#67085) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../components/global-styles/screen-block.js | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/screen-block.js b/packages/edit-site/src/components/global-styles/screen-block.js index b1489167f2dc75..64f49574b6b03b 100644 --- a/packages/edit-site/src/components/global-styles/screen-block.js +++ b/packages/edit-site/src/components/global-styles/screen-block.js @@ -102,12 +102,16 @@ function ScreenBlock( { name, variation } ) { } ); const [ userSettings ] = useGlobalSetting( '', name, 'user' ); const [ rawSettings, setSettings ] = useGlobalSetting( '', name ); - const settings = useSettingsForBlockElement( rawSettings, name ); + const settingsForBlockElement = useSettingsForBlockElement( + rawSettings, + name + ); const blockType = getBlockType( name ); // Only allow `blockGap` support if serialization has not been skipped, to be sure global spacing can be applied. + let disableBlockGap = false; if ( - settings?.spacing?.blockGap && + settingsForBlockElement?.spacing?.blockGap && blockType?.supports?.spacing?.blockGap && ( blockType?.supports?.spacing?.__experimentalSkipSerialization === true || @@ -115,7 +119,7 @@ function ScreenBlock( { name, variation } ) { ( spacingType ) => spacingType === 'blockGap' ) ) ) { - settings.spacing.blockGap = false; + disableBlockGap = true; } // Only allow `aspectRatio` support if the block is not the grouping block. @@ -124,10 +128,25 @@ function ScreenBlock( { name, variation } ) { // for all three at once. Until there is the ability to set a different aspect // ratio for each variation, we disable the aspect ratio controls for the // grouping block in global styles. - if ( settings?.dimensions?.aspectRatio && name === 'core/group' ) { - settings.dimensions.aspectRatio = false; + let disableAspectRatio = false; + if ( + settingsForBlockElement?.dimensions?.aspectRatio && + name === 'core/group' + ) { + disableAspectRatio = true; } + const settings = useMemo( () => { + const updatedSettings = structuredClone( settingsForBlockElement ); + if ( disableBlockGap ) { + updatedSettings.spacing.blockGap = false; + } + if ( disableAspectRatio ) { + updatedSettings.dimensions.aspectRatio = false; + } + return updatedSettings; + }, [ settingsForBlockElement, disableBlockGap, disableAspectRatio ] ); + const blockVariations = useBlockVariations( name ); const hasBackgroundPanel = useHasBackgroundPanel( settings ); const hasTypographyPanel = useHasTypographyPanel( settings ); From d4d6d4c5898a9fe4f678bfb349d023aad211fc9c Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Mon, 18 Nov 2024 17:14:32 +0000 Subject: [PATCH 1613/1908] Update Changelog for 19.6.4 --- changelog.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/changelog.txt b/changelog.txt index 6036acdf97256f..d9236e513469af 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,10 @@ == Changelog == += 19.6.4 = + +- PostTaxonomiesFlatTermSelector: abstract wrapper component (#66625) + + = 19.6.3 = - Revert "Set image width to fit-content to solve aspect ratio problems in Firefox. ([#66217](https://github.com/WordPress/gutenberg/pull/66804)) From 2027fdbc060b24e59927dee5d09f95eb99a2fd76 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Mon, 18 Nov 2024 12:00:39 -0600 Subject: [PATCH 1614/1908] Make social icon navigation one arrow keypress (#64883) By moving the blockProps for the social icon from the <li> to the <button>, we get the appropriate behavior of being able to select and create social icons with a clean keyboard behavior. --- .../block-library/src/social-link/edit.js | 66 +++++++++++++------ .../block-library/src/social-link/editor.scss | 11 ++-- 2 files changed, 51 insertions(+), 26 deletions(-) diff --git a/packages/block-library/src/social-link/edit.js b/packages/block-library/src/social-link/edit.js index 47af181bfe17e8..14b0f11334a091 100644 --- a/packages/block-library/src/social-link/edit.js +++ b/packages/block-library/src/social-link/edit.js @@ -6,7 +6,7 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { DELETE, BACKSPACE } from '@wordpress/keycodes'; +import { DELETE, BACKSPACE, ENTER } from '@wordpress/keycodes'; import { useDispatch } from '@wordpress/data'; import { @@ -16,7 +16,7 @@ import { useBlockProps, store as blockEditorStore, } from '@wordpress/block-editor'; -import { useState } from '@wordpress/element'; +import { useState, useRef } from '@wordpress/element'; import { Button, PanelBody, @@ -24,6 +24,7 @@ import { TextControl, __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper, } from '@wordpress/components'; +import { useMergeRefs } from '@wordpress/compose'; import { __ } from '@wordpress/i18n'; import { keyboardReturn } from '@wordpress/icons'; @@ -112,12 +113,19 @@ const SocialLinkEdit = ( { iconBackgroundColorValue, } = context; const [ showURLPopover, setPopover ] = useState( false ); - const classes = clsx( 'wp-social-link', 'wp-social-link-' + service, { - 'wp-social-link__is-incomplete': ! url, - [ `has-${ iconColor }-color` ]: iconColor, - [ `has-${ iconBackgroundColor }-background-color` ]: - iconBackgroundColor, - } ); + const wrapperClasses = clsx( + 'wp-social-link', + // Manually adding this class for backwards compatibility of CSS when moving the + // blockProps from the li to the button: https://github.com/WordPress/gutenberg/pull/64883 + 'wp-block-social-link', + 'wp-social-link-' + service, + { + 'wp-social-link__is-incomplete': ! url, + [ `has-${ iconColor }-color` ]: iconColor, + [ `has-${ iconBackgroundColor }-background-color` ]: + iconBackgroundColor, + } + ); // Use internal state instead of a ref to make sure that the component // re-renders when the popover's anchor updates. @@ -131,11 +139,16 @@ const SocialLinkEdit = ( { // spaces. The PHP render callback fallbacks to the social name as well. const socialLinkText = label.trim() === '' ? socialLinkName : label; + const ref = useRef(); const blockProps = useBlockProps( { - className: classes, - style: { - color: iconColorValue, - backgroundColor: iconBackgroundColorValue, + className: 'wp-block-social-link-anchor', + ref: useMergeRefs( [ setPopoverAnchor, ref ] ), + onClick: () => setPopover( true ), + onKeyDown: ( event ) => { + if ( event.keyCode === ENTER ) { + event.preventDefault(); + setPopover( true ); + } }, } ); @@ -169,13 +182,27 @@ const SocialLinkEdit = ( { onChange={ ( value ) => setAttributes( { rel: value } ) } /> </InspectorControls> - <li { ...blockProps }> - <button - className="wp-block-social-link-anchor" - ref={ setPopoverAnchor } - onClick={ () => setPopover( true ) } - aria-haspopup="dialog" - > + { /* + * Because the `<ul>` element has a role=document, the `<li>` is + * not semantically correct, so adding role=presentation is cleaner. + * https://github.com/WordPress/gutenberg/pull/64883#issuecomment-2472874551 + */ } + <li + role="presentation" + className={ wrapperClasses } + style={ { + color: iconColorValue, + backgroundColor: iconBackgroundColorValue, + } } + > + { /* + * Disable reason: The `button` ARIA role is redundant but + * blockProps has a role of `document` automatically applied + * which breaks the semantics of this button since it removes + * the information about the popover. + */ + /* eslint-disable jsx-a11y/no-redundant-roles */ } + <button aria-haspopup="dialog" { ...blockProps } role="button"> <IconComponent /> <span className={ clsx( 'wp-block-social-link-label', { @@ -185,6 +212,7 @@ const SocialLinkEdit = ( { { socialLinkText } </span> </button> + { /* eslint-enable jsx-a11y/no-redundant-roles */ } { isSelected && showURLPopover && ( <SocialLinkURLPopover url={ url } diff --git a/packages/block-library/src/social-link/editor.scss b/packages/block-library/src/social-link/editor.scss index bd93ad9f055fcd..2f5714f5d2ed9f 100644 --- a/packages/block-library/src/social-link/editor.scss +++ b/packages/block-library/src/social-link/editor.scss @@ -21,13 +21,10 @@ // This rule is duplicated from the style.scss and needs to be the same as there. padding: 0.25em; - // Focus styles replicate the `@wordpress/components` button component. - &:focus:not(:disabled) { - border-radius: 2px; - box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - - // Windows High Contrast mode will show this outline, but not the box-shadow. - outline: 3px solid transparent; + // Override the shared `.wp-block-social-link` class used on both the li and button + // due to backwards compatibility from moving the blockProps from the li to the button. + &:hover { + transform: none; } } From 149079529daf240443e2496fb5800ee5cfc1605f Mon Sep 17 00:00:00 2001 From: Vipul Gupta <55375170+vipul0425@users.noreply.github.com> Date: Tue, 19 Nov 2024 03:15:28 +0530 Subject: [PATCH 1615/1908] TextControl: Deprecate 36px default size (#66745) * feat: Adds deprecation notice for textControl. * docs: Adds deprecation changelog. * doc: removes redundant comment. * docs: Updates all instances where textControl was used without new prop. * Update CHANGELOG.md --------- Co-authored-by: vipul0425 <vipulgupta003@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../fundamentals/block-in-the-editor.md | 2 ++ docs/getting-started/tutorial.md | 4 ++++ .../data-basics/3-building-an-edit-form.md | 10 ++++++++++ .../data-basics/4-building-a-create-page-form.md | 4 ++++ docs/how-to-guides/metabox.md | 2 ++ docs/reference-guides/block-api/block-context.md | 2 ++ .../block-api/block-edit-save.md | 4 ++++ .../slotfills/plugin-sidebar-more-menu-item.md | 2 ++ .../reference-guides/slotfills/plugin-sidebar.md | 2 ++ .../src/components/inspector-controls/README.md | 2 ++ packages/components/CHANGELOG.md | 1 + packages/components/src/disabled/README.md | 16 +++++++++------- packages/components/src/disabled/index.tsx | 9 ++++++++- .../src/disabled/stories/index.story.tsx | 1 + .../with-constrained-tabbing/README.md | 16 +++++++++++++--- .../src/higher-order/with-focus-return/README.md | 11 +++++++++-- .../src/placeholder/stories/index.story.tsx | 1 + packages/components/src/text-control/README.md | 1 + packages/components/src/text-control/index.tsx | 8 ++++++++ .../src/text-control/stories/index.story.tsx | 1 + .../src/text-control/test/text-control.tsx | 8 +++++++- packages/core-data/README.md | 2 ++ .../core-data/src/hooks/use-entity-record.ts | 2 ++ 23 files changed, 97 insertions(+), 14 deletions(-) diff --git a/docs/getting-started/fundamentals/block-in-the-editor.md b/docs/getting-started/fundamentals/block-in-the-editor.md index d1f2a25063e6c6..1d51239907d8b5 100644 --- a/docs/getting-started/fundamentals/block-in-the-editor.md +++ b/docs/getting-started/fundamentals/block-in-the-editor.md @@ -139,6 +139,8 @@ export default function Edit( { attributes, setAttributes } ) { </div> </InspectorControls> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize value={ attributes.message } onChange={ ( val ) => setAttributes( { message: val } ) } style={ { diff --git a/docs/getting-started/tutorial.md b/docs/getting-started/tutorial.md index 4e43241f63fb16..2a5dd979d3a569 100644 --- a/docs/getting-started/tutorial.md +++ b/docs/getting-started/tutorial.md @@ -480,6 +480,8 @@ export default function Edit( { attributes, setAttributes } ) { <InspectorControls> <PanelBody title={ __( 'Settings', 'copyright-date-block' ) }> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize label={ __( 'Starting year', 'copyright-date-block' @@ -540,6 +542,8 @@ export default function Edit( { attributes, setAttributes } ) { /> { showStartingYear && ( <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize label={ __( 'Starting year', 'copyright-date-block' diff --git a/docs/how-to-guides/data-basics/3-building-an-edit-form.md b/docs/how-to-guides/data-basics/3-building-an-edit-form.md index 5f4e30357798d5..1e2b4453e59ee2 100644 --- a/docs/how-to-guides/data-basics/3-building-an-edit-form.md +++ b/docs/how-to-guides/data-basics/3-building-an-edit-form.md @@ -63,6 +63,8 @@ function EditPageForm( { pageId, onCancel, onSaveFinished } ) { return ( <div className="my-gutenberg-form"> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize value='' label='Page title:' /> @@ -139,6 +141,8 @@ function EditPageForm( { pageId, onCancel, onSaveFinished } ) { return ( <div className="my-gutenberg-form"> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize label='Page title:' value={ page.title.rendered } /> @@ -164,6 +168,8 @@ function VanillaReactForm({ initialTitle }) { const [title, setTitle] = useState( initialTitle ); return ( <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize value={ title } onChange={ setTitle } /> @@ -233,6 +239,8 @@ function EditPageForm( { pageId, onCancel, onSaveFinished } ) { return ( <div className="my-gutenberg-form"> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize label="Page title:" value={ page.title } onChange={ handleChange } @@ -501,6 +509,8 @@ function EditPageForm( { pageId, onCancel, onSaveFinished } ) { return ( <div className="my-gutenberg-form"> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize label="Page title:" value={ page.title } onChange={ handleChange } diff --git a/docs/how-to-guides/data-basics/4-building-a-create-page-form.md b/docs/how-to-guides/data-basics/4-building-a-create-page-form.md index 9011596e0feddd..c880a1a3897488 100644 --- a/docs/how-to-guides/data-basics/4-building-a-create-page-form.md +++ b/docs/how-to-guides/data-basics/4-building-a-create-page-form.md @@ -87,6 +87,8 @@ function PageForm( { title, onChangeTitle, hasEdits, lastError, isSaving, onCanc return ( <div className="my-gutenberg-form"> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize label="Page title:" value={ title } onChange={ onChangeTitle } @@ -346,6 +348,8 @@ function PageForm( { title, onChangeTitle, hasEdits, lastError, isSaving, onCanc return ( <div className="my-gutenberg-form"> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize label="Page title:" value={ title } onChange={ onChangeTitle } diff --git a/docs/how-to-guides/metabox.md b/docs/how-to-guides/metabox.md index da37b8fba3b7c1..707505d165c7fa 100644 --- a/docs/how-to-guides/metabox.md +++ b/docs/how-to-guides/metabox.md @@ -91,6 +91,8 @@ registerBlockType( 'myguten/meta-block', { return ( <div { ...blockProps }> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize label="Meta Block Field" value={ metaFieldValue } onChange={ updateMetaValue } diff --git a/docs/reference-guides/block-api/block-context.md b/docs/reference-guides/block-api/block-context.md index 09c33dfb71b7c3..c5fcfaedbae349 100644 --- a/docs/reference-guides/block-api/block-context.md +++ b/docs/reference-guides/block-api/block-context.md @@ -141,6 +141,8 @@ export default function Edit( props ) { return ( <div> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize label={ __( 'Record ID' ) } value={ recordId } onChange={ ( val ) => diff --git a/docs/reference-guides/block-api/block-edit-save.md b/docs/reference-guides/block-api/block-edit-save.md index 9e4dd3d1a916bd..86721c77e463c6 100644 --- a/docs/reference-guides/block-api/block-edit-save.md +++ b/docs/reference-guides/block-api/block-edit-save.md @@ -210,6 +210,8 @@ edit: ( { attributes, setAttributes } ) => { return ( <div { ...blockProps }> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize label='My Text Field' value={ attributes.content } onChange={ updateFieldValue } @@ -246,6 +248,8 @@ edit: ( { attributes, setAttributes } ) => { return ( <div { ...blockProps }> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize label='Number Posts to Show' value={ attributes.postsToShow } onChange={ ( val ) => { diff --git a/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md b/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md index 4a4ff98697b5f3..1a1b2540b258b9 100644 --- a/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md +++ b/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md @@ -45,6 +45,8 @@ const PluginSidebarMoreMenuItemTest = () => { ) } </p> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize label={ __( 'Text Control' ) } value={ text } onChange={ ( newText ) => setText( newText ) } diff --git a/docs/reference-guides/slotfills/plugin-sidebar.md b/docs/reference-guides/slotfills/plugin-sidebar.md index 9bf911b3bb13f2..7191b80e54e2d6 100644 --- a/docs/reference-guides/slotfills/plugin-sidebar.md +++ b/docs/reference-guides/slotfills/plugin-sidebar.md @@ -38,6 +38,8 @@ const PluginSidebarExample = () => { ) } </p> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize label={ __( 'Text Control' ) } value={ text } onChange={ ( newText ) => setText( newText ) } diff --git a/packages/block-editor/src/components/inspector-controls/README.md b/packages/block-editor/src/components/inspector-controls/README.md index fd4847f53472b2..916f53b5f42d8b 100644 --- a/packages/block-editor/src/components/inspector-controls/README.md +++ b/packages/block-editor/src/components/inspector-controls/README.md @@ -116,6 +116,7 @@ registerBlockType( 'my-plugin/inspector-controls-example', { <TextControl __nextHasNoMarginBottom + __next40pxDefaultSize label="Text Field" help="Additional help text" value={ textField } @@ -208,6 +209,7 @@ function MyBlockEdit( { attributes, setAttributes } ) { <InspectorAdvancedControls> <TextControl __nextHasNoMarginBottom + __next40pxDefaultSize label="HTML anchor" value={ attributes.anchor } onChange={ ( nextValue ) => { diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 8c217c90ba1b7d..d93eb30ac0ec50 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Deprecations - `DimensionControl`: Deprecate 36px default size ([#66705](https://github.com/WordPress/gutenberg/pull/66705)). +- `TextControl`: Deprecate 36px default size ([#66745](https://github.com/WordPress/gutenberg/pull/66745). ### Bug Fixes diff --git a/packages/components/src/disabled/README.md b/packages/components/src/disabled/README.md index 9b257acd0f737b..e9eb6398554d9d 100644 --- a/packages/components/src/disabled/README.md +++ b/packages/components/src/disabled/README.md @@ -13,7 +13,14 @@ import { Button, Disabled, TextControl } from '@wordpress/components'; const MyDisabled = () => { const [ isDisabled, setIsDisabled ] = useState( true ); - let input = <TextControl label="Input" onChange={ () => {} } />; + let input = ( + <TextControl + __next40pxDefaultSize + __nextHasNoMarginBottom + label="Input" + onChange={ () => {} } + /> + ); if ( isDisabled ) { input = <Disabled>{ input }</Disabled>; } @@ -38,12 +45,7 @@ A component can detect if it has been wrapped in a `<Disabled />` by accessing i ```jsx function CustomButton( props ) { const isDisabled = useContext( Disabled.Context ); - return ( - <button - { ...props } - style={ { opacity: isDisabled ? 0.5 : 1 } } - /> - ); + return <button { ...props } style={ { opacity: isDisabled ? 0.5 : 1 } } />; } ``` diff --git a/packages/components/src/disabled/index.tsx b/packages/components/src/disabled/index.tsx index 32baac3411054c..cc55a4d2e6d672 100644 --- a/packages/components/src/disabled/index.tsx +++ b/packages/components/src/disabled/index.tsx @@ -31,7 +31,14 @@ const { Consumer, Provider } = Context; * const MyDisabled = () => { * const [ isDisabled, setIsDisabled ] = useState( true ); * - * let input = <TextControl label="Input" onChange={ () => {} } />; + * let input = ( + * <TextControl + * __next40pxDefaultSize + * __nextHasNoMarginBottom + * label="Input" + * onChange={ () => {} } + * /> + * ); * if ( isDisabled ) { * input = <Disabled>{ input }</Disabled>; * } diff --git a/packages/components/src/disabled/stories/index.story.tsx b/packages/components/src/disabled/stories/index.story.tsx index 59ff84dec43fca..29d9c925f4f5d8 100644 --- a/packages/components/src/disabled/stories/index.story.tsx +++ b/packages/components/src/disabled/stories/index.story.tsx @@ -42,6 +42,7 @@ const Form = () => { <VStack> <TextControl __nextHasNoMarginBottom + __next40pxDefaultSize label="Text Control" value={ textControlValue } onChange={ setTextControlValue } diff --git a/packages/components/src/higher-order/with-constrained-tabbing/README.md b/packages/components/src/higher-order/with-constrained-tabbing/README.md index 47cb8a033dfbdd..417ab7c133fea5 100644 --- a/packages/components/src/higher-order/with-constrained-tabbing/README.md +++ b/packages/components/src/higher-order/with-constrained-tabbing/README.md @@ -22,8 +22,18 @@ const MyComponentWithConstrainedTabbing = () => { const [ isConstrainedTabbing, setIsConstrainedTabbing ] = useState( false ); let form = ( <form> - <TextControl label="Input 1" onChange={ () => {} } /> - <TextControl label="Input 2" onChange={ () => {} } /> + <TextControl + __next40pxDefaultSize + __nextHasNoMarginBottom + label="Input 1" + onChange={ () => {} } + /> + <TextControl + __next40pxDefaultSize + __nextHasNoMarginBottom + label="Input 2" + onChange={ () => {} } + /> </form> ); if ( isConstrainedTabbing ) { @@ -43,5 +53,5 @@ const MyComponentWithConstrainedTabbing = () => { </Button> </div> ); -} +}; ``` diff --git a/packages/components/src/higher-order/with-focus-return/README.md b/packages/components/src/higher-order/with-focus-return/README.md index b99d76bc6f1c9a..81cecad4310f11 100644 --- a/packages/components/src/higher-order/with-focus-return/README.md +++ b/packages/components/src/higher-order/with-focus-return/README.md @@ -13,7 +13,12 @@ import { withFocusReturn, TextControl, Button } from '@wordpress/components'; const EnhancedComponent = withFocusReturn( () => ( <div> Focus will return to the previous input when this component is unmounted - <TextControl autoFocus={ true } onChange={ () => {} } /> + <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize + autoFocus={ true } + onChange={ () => {} } + /> </div> ) ); @@ -27,6 +32,8 @@ const MyComponentWithFocusReturn = () => { return ( <div> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize placeholder="Type something" value={ text } onChange={ ( value ) => setText( value ) } @@ -39,7 +46,7 @@ const MyComponentWithFocusReturn = () => { ) } </div> ); -} +}; ``` `withFocusReturn` can optionally be called as a higher-order function creator. Provided an options object, a new higher-order function is returned. diff --git a/packages/components/src/placeholder/stories/index.story.tsx b/packages/components/src/placeholder/stories/index.story.tsx index 541eeceedc27d4..1a0db673320bca 100644 --- a/packages/components/src/placeholder/stories/index.story.tsx +++ b/packages/components/src/placeholder/stories/index.story.tsx @@ -45,6 +45,7 @@ const Template: StoryFn< typeof Placeholder > = ( args ) => { <div> <TextControl __nextHasNoMarginBottom + __next40pxDefaultSize label="Sample Field" placeholder="Enter something here" value={ value } diff --git a/packages/components/src/text-control/README.md b/packages/components/src/text-control/README.md index 0b6e2d4ebc684e..80f3145a4325b3 100644 --- a/packages/components/src/text-control/README.md +++ b/packages/components/src/text-control/README.md @@ -63,6 +63,7 @@ const MyTextControl = () => { return ( <TextControl __nextHasNoMarginBottom + __next40pxDefaultSize label="Additional CSS Class" value={ className } onChange={ ( value ) => setClassName( value ) } diff --git a/packages/components/src/text-control/index.tsx b/packages/components/src/text-control/index.tsx index ea2d2c17bb9cf6..83881542fe7b7b 100644 --- a/packages/components/src/text-control/index.tsx +++ b/packages/components/src/text-control/index.tsx @@ -16,6 +16,7 @@ import { forwardRef } from '@wordpress/element'; import BaseControl from '../base-control'; import type { WordPressComponentProps } from '../context'; import type { TextControlProps } from './types'; +import { maybeWarnDeprecated36pxSize } from '../utils/deprecated-36px-size'; function UnforwardedTextControl( props: WordPressComponentProps< TextControlProps, 'input', false >, @@ -38,6 +39,12 @@ function UnforwardedTextControl( const onChangeValue = ( event: ChangeEvent< HTMLInputElement > ) => onChange( event.target.value ); + maybeWarnDeprecated36pxSize( { + componentName: 'TextControl', + size: undefined, + __next40pxDefaultSize, + } ); + return ( <BaseControl __nextHasNoMarginBottom={ __nextHasNoMarginBottom } @@ -77,6 +84,7 @@ function UnforwardedTextControl( * return ( * <TextControl * __nextHasNoMarginBottom + * __next40pxDefaultSize * label="Additional CSS Class" * value={ className } * onChange={ ( value ) => setClassName( value ) } diff --git a/packages/components/src/text-control/stories/index.story.tsx b/packages/components/src/text-control/stories/index.story.tsx index bebdb2caf75f63..948eca84a634c7 100644 --- a/packages/components/src/text-control/stories/index.story.tsx +++ b/packages/components/src/text-control/stories/index.story.tsx @@ -54,6 +54,7 @@ export const Default: StoryFn< typeof TextControl > = DefaultTemplate.bind( ); Default.args = { __nextHasNoMarginBottom: true, + __next40pxDefaultSize: true, }; export const WithLabelAndHelpText: StoryFn< typeof TextControl > = diff --git a/packages/components/src/text-control/test/text-control.tsx b/packages/components/src/text-control/test/text-control.tsx index 19b17cae443614..7eb3a82d2fb5f5 100644 --- a/packages/components/src/text-control/test/text-control.tsx +++ b/packages/components/src/text-control/test/text-control.tsx @@ -9,7 +9,13 @@ import { render, screen } from '@testing-library/react'; import _TextControl from '..'; const TextControl = ( props: React.ComponentProps< typeof _TextControl > ) => { - return <_TextControl { ...props } __nextHasNoMarginBottom />; + return ( + <_TextControl + { ...props } + __nextHasNoMarginBottom + __next40pxDefaultSize + /> + ); }; const noop = () => {}; diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 079f95ddbfc7a6..eb6980cdd4eea1 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -1083,6 +1083,8 @@ function PageRenameForm( { id } ) { return ( <form onSubmit={ onRename }> <TextControl + __nextHasNoMarginBottom + __next40pxDefaultSize label={ __( 'Name' ) } value={ page.editedRecord.title } onChange={ setTitle } diff --git a/packages/core-data/src/hooks/use-entity-record.ts b/packages/core-data/src/hooks/use-entity-record.ts index 60228893e5102e..e3535f0e982ccd 100644 --- a/packages/core-data/src/hooks/use-entity-record.ts +++ b/packages/core-data/src/hooks/use-entity-record.ts @@ -126,6 +126,8 @@ const EMPTY_OBJECT = {}; * return ( * <form onSubmit={ onRename }> * <TextControl + * __nextHasNoMarginBottom + * __next40pxDefaultSize * label={ __( 'Name' ) } * value={ page.editedRecord.title } * onChange={ setTitle } From 89cba32413f05857e97c51beb9f168082316ccc6 Mon Sep 17 00:00:00 2001 From: Benazeer Hassan <66269472+benazeer-ben@users.noreply.github.com> Date: Tue, 19 Nov 2024 03:25:45 +0530 Subject: [PATCH 1616/1908] Page List : Add border and spacing support (#66385) * Border support added for Page-list block * Border support added for Page-list block * Adding spacing support for page list * Doc Build * Update packages/block-library/src/page-list/block.json Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> * Update packages/block-library/src/page-list/block.json Suggestion commit Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> * Unwanted Comma removed * border-box added --------- Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: benazeer1909 <91200605+benazeerhassan1909@users.noreply.github.com> Co-authored-by: akasunil <sdprajapati999@gmail.com> Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> --- docs/reference-guides/core-blocks.md | 2 +- packages/block-library/src/page-list/block.json | 14 ++++++++++++++ packages/block-library/src/page-list/style.scss | 4 ++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index a27de8211c824a..34db859f71d1de 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -512,7 +512,7 @@ Display a list of all pages. ([Source](https://github.com/WordPress/gutenberg/tr - **Name:** core/page-list - **Category:** widgets - **Allowed Blocks:** core/page-list-item -- **Supports:** interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~ +- **Supports:** interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~ - **Attributes:** isNested, parentPageID ## Page List Item diff --git a/packages/block-library/src/page-list/block.json b/packages/block-library/src/page-list/block.json index b465e4ef5dc3d0..16a620dc177d7c 100644 --- a/packages/block-library/src/page-list/block.json +++ b/packages/block-library/src/page-list/block.json @@ -51,6 +51,20 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + }, + "spacing": { + "padding": true, + "margin": true, + "__experimentalDefaultControls": { + "padding": false, + "margin": false + } } }, "editorStyle": "wp-block-page-list-editor", diff --git a/packages/block-library/src/page-list/style.scss b/packages/block-library/src/page-list/style.scss index d06a6142573bec..ab04d57e61b965 100644 --- a/packages/block-library/src/page-list/style.scss +++ b/packages/block-library/src/page-list/style.scss @@ -15,3 +15,7 @@ background-color: inherit; } } +.wp-block-page-list { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; +} From 564f0699e0924b7114af55d51f1909de07a2e3c9 Mon Sep 17 00:00:00 2001 From: tellthemachines <tellthemachines@users.noreply.github.com> Date: Tue, 19 Nov 2024 11:02:47 +1100 Subject: [PATCH 1617/1908] Allow flex justification controls to be disabled at the block level (#67059) Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/block-editor/src/layouts/flex.js | 45 ++++++++++++++--------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/packages/block-editor/src/layouts/flex.js b/packages/block-editor/src/layouts/flex.js index c67ebc17a785d4..f57ccbde466169 100644 --- a/packages/block-editor/src/layouts/flex.js +++ b/packages/block-editor/src/layouts/flex.js @@ -66,24 +66,27 @@ export default { onChange, layoutBlockSupport = {}, } ) { - const { allowOrientation = true } = layoutBlockSupport; + const { allowOrientation = true, allowJustification = true } = + layoutBlockSupport; return ( <> <Flex> - <FlexItem> - <FlexLayoutJustifyContentControl - layout={ layout } - onChange={ onChange } - /> - </FlexItem> - <FlexItem> - { allowOrientation && ( + { allowJustification && ( + <FlexItem> + <FlexLayoutJustifyContentControl + layout={ layout } + onChange={ onChange } + /> + </FlexItem> + ) } + { allowOrientation && ( + <FlexItem> <OrientationControl layout={ layout } onChange={ onChange } /> - ) } - </FlexItem> + </FlexItem> + ) } </Flex> <FlexWrapControl layout={ layout } onChange={ onChange } /> </> @@ -94,14 +97,22 @@ export default { onChange, layoutBlockSupport, } ) { - const { allowVerticalAlignment = true } = layoutBlockSupport; + const { allowVerticalAlignment = true, allowJustification = true } = + layoutBlockSupport; + + if ( ! allowJustification && ! allowVerticalAlignment ) { + return null; + } + return ( <BlockControls group="block" __experimentalShareWithChildBlocks> - <FlexLayoutJustifyContentControl - layout={ layout } - onChange={ onChange } - isToolbar - /> + { allowJustification && ( + <FlexLayoutJustifyContentControl + layout={ layout } + onChange={ onChange } + isToolbar + /> + ) } { allowVerticalAlignment && ( <FlexLayoutVerticalAlignmentControl layout={ layout } From 32fe48ce49721dc98d9a523e468e54d0d18375aa Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:34:54 +0100 Subject: [PATCH 1618/1908] Update custom store readme to use thunks instead of controls (#67006) * Update store readme to use thunkgs * Fix space * Hide controls explanation in `details` Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/data/README.md | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/packages/data/README.md b/packages/data/README.md index 25dd75820fb5db..b6e0e03b1d8b72 100644 --- a/packages/data/README.md +++ b/packages/data/README.md @@ -42,13 +42,6 @@ const actions = { discountPercent, }; }, - - fetchFromAPI( path ) { - return { - type: 'FETCH_FROM_API', - path, - }; - }, }; const store = createReduxStore( 'my-shop', { @@ -84,17 +77,11 @@ const store = createReduxStore( 'my-shop', { }, }, - controls: { - FETCH_FROM_API( action ) { - return apiFetch( { path: action.path } ); - }, - }, - resolvers: { - *getPrice( item ) { + getPrice: ( item ) => async ({ dispatch }) => { { const path = '/wp/v2/prices/' + item; - const price = yield actions.fetchFromAPI( path ); - return actions.setPrice( item, price ); + const price = await apiFetch( { path } ); + dispatch.setPrice( item, price ); }, }, } ); @@ -133,13 +120,21 @@ A **resolver** is a side-effect for a selector. If your selector result may need The `resolvers` option should be passed as an object where each key is the name of the selector to act upon, the value a function which receives the same arguments passed to the selector, excluding the state argument. It can then dispatch as necessary to fulfill the requirements of the selector, taking advantage of the fact that most data consumers will subscribe to subsequent state changes (by `subscribe` or `withSelect`). -#### `controls` +Resolvers, in combination with [thunks](https://github.com/WordPress/gutenberg/blob/trunk/docs/how-to-guides/thunks.md#thunks-can-be-async), can be used to implement asynchronous data flows for your store. -A **control** defines the execution flow behavior associated with a specific action type. This can be particularly useful in implementing asynchronous data flows for your store. By defining your action creator or resolvers as a generator which yields specific controlled action types, the execution will proceed as defined by the control handler. +#### `controls` (deprecated) -The `controls` option should be passed as an object where each key is the name of the action type to act upon, the value a function which receives the original action object. It should returns either a promise which is to resolve when evaluation of the action should continue, or a value. The value or resolved promise value is assigned on the return value of the yield assignment. If the control handler returns undefined, the execution is not continued. +To handle asynchronous data flows, it is recommended to use [thunks](https://github.com/WordPress/gutenberg/blob/trunk/docs/how-to-guides/thunks.md#thunks-can-be-async) instead of `controls`. -Refer to the [documentation of `@wordpress/redux-routine`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/redux-routine/README.md) for more information. +<details> + <summary>View <em>controls</em> explanation</summary> +<br> +A <em>control</em> defines the execution flow behavior associated with a specific action type. Before <a href="https://github.com/WordPress/gutenberg/blob/trunk/docs/how-to-guides/thunks.md#thunks-can-be-async">thunks</a>, controls were used to implement asynchronous data flows for your store. By defining your action creator or resolvers as a generator which yields specific controlled action types, the execution will proceed as defined by the control handler. +<br><br> +The <em>controls</em> option should be passed as an object where each key is the name of the action type to act upon, the value a function which receives the original action object. It should returns either a promise which is to resolve when evaluation of the action should continue, or a value. The value or resolved promise value is assigned on the return value of the yield assignment. If the control handler returns undefined, the execution is not continued. +<br><br> +Refer to the <a href="https://github.com/WordPress/gutenberg/tree/HEAD/packages/redux-routine/README.md">documentation of <em>@wordpress/redux-routine</em></a> for more information. +</details> #### `initialState` @@ -262,7 +257,7 @@ The data module shares many of the same [core principles](https://redux.js.org/i The [higher-order components](#higher-order-components) were created to complement this distinction. The intention with splitting `withSelect` and `withDispatch` — where in React Redux they are combined under `connect` as `mapStateToProps` and `mapDispatchToProps` arguments — is to more accurately reflect that dispatch is not dependent upon a subscription to state changes, and to allow for state-derived values to be used in `withDispatch` (via [higher-order component composition](https://github.com/WordPress/gutenberg/tree/HEAD/packages/compose/README.md)). -The data module also has built-in solutions for handling asynchronous side-effects, through [resolvers](#resolvers) and [controls](#controls). These differ slightly from [standard redux async solutions](https://redux.js.org/advanced/async-actions) like [`redux-thunk`](https://github.com/gaearon/redux-thunk) or [`redux-saga`](https://redux-saga.js.org/). +The data module also has built-in solutions for handling asynchronous side-effects, through [resolvers](#resolvers) and [thunks](https://github.com/WordPress/gutenberg/blob/trunk/docs/how-to-guides/thunks.md#thunks-can-be-async). These differ slightly from [standard redux async solutions](https://redux.js.org/advanced/async-actions) like [`redux-thunk`](https://github.com/gaearon/redux-thunk) or [`redux-saga`](https://redux-saga.js.org/). Specific implementation differences from Redux and React Redux: From 327238af77f7094485df1bf3b8e3d66ab7ff21e8 Mon Sep 17 00:00:00 2001 From: Carolina Nymark <myazalea@hotmail.com> Date: Tue, 19 Nov 2024 10:07:31 +0100 Subject: [PATCH 1619/1908] Fix: JavaScript error when pattern category is unregistered (#67063) * Fix: JavaScript error when pattern category is unregistered Because the wp_pattern_category taxonomy can be unregistered, it needs to be used conditionally in the JavaScript code, or there may be JavaScript errors. * Add the conditional chaining to two more places --- packages/block-editor/src/store/private-selectors.js | 2 +- .../edit-site/src/components/page-patterns/use-patterns.js | 4 ++-- .../use-pattern-categories.js | 2 +- packages/patterns/src/components/duplicate-pattern-modal.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index f1b5abd7789a11..5a5ce7a801594b 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -330,7 +330,7 @@ function mapUserPattern( id: userPattern.id, type: INSERTER_PATTERN_TYPES.user, title: userPattern.title.raw, - categories: userPattern.wp_pattern_category.map( ( catId ) => { + categories: userPattern.wp_pattern_category?.map( ( catId ) => { const category = __experimentalUserPatternCategories.find( ( { id } ) => id === catId ); diff --git a/packages/edit-site/src/components/page-patterns/use-patterns.js b/packages/edit-site/src/components/page-patterns/use-patterns.js index f32e278e6354f5..e226298857c4da 100644 --- a/packages/edit-site/src/components/page-patterns/use-patterns.js +++ b/packages/edit-site/src/components/page-patterns/use-patterns.js @@ -156,7 +156,7 @@ const selectPatterns = createSelector( categoryId, hasCategory: ( item, currentCategory ) => { if ( item.type === PATTERN_TYPES.user ) { - return item.wp_pattern_category.some( + return item.wp_pattern_category?.some( ( catId ) => userPatternCategories.find( ( cat ) => cat.id === catId @@ -173,7 +173,7 @@ const selectPatterns = createSelector( return ( userPatternCategories?.length && ( ! item.wp_pattern_category?.length || - ! item.wp_pattern_category.some( ( catId ) => + ! item.wp_pattern_category?.some( ( catId ) => userPatternCategories.find( ( cat ) => cat.id === catId ) diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-patterns/use-pattern-categories.js b/packages/edit-site/src/components/sidebar-navigation-screen-patterns/use-pattern-categories.js index a41e0ea7660616..70aaf12dc68c77 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-patterns/use-pattern-categories.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-patterns/use-pattern-categories.js @@ -69,7 +69,7 @@ export default function usePatternCategories() { // If the pattern has no categories, add it to uncategorized. if ( ! pattern.wp_pattern_category?.length || - ! pattern.wp_pattern_category.some( ( catId ) => + ! pattern.wp_pattern_category?.some( ( catId ) => userPatternCategories.find( ( cat ) => cat.id === catId ) ) ) { diff --git a/packages/patterns/src/components/duplicate-pattern-modal.js b/packages/patterns/src/components/duplicate-pattern-modal.js index 70fb0830e0f1cc..d4fd5e744c4e18 100644 --- a/packages/patterns/src/components/duplicate-pattern-modal.js +++ b/packages/patterns/src/components/duplicate-pattern-modal.js @@ -24,7 +24,7 @@ function getTermLabels( pattern, categories ) { return categories.user ?.filter( ( category ) => - pattern.wp_pattern_category.includes( category.id ) + pattern.wp_pattern_category?.includes( category.id ) ) .map( ( category ) => category.label ); } From 034c1be593f0674f6014a8ac9f52d3115f0d5f65 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Tue, 19 Nov 2024 18:11:12 +0900 Subject: [PATCH 1620/1908] ESLint: Enable `eslint-plugin-react-compiler` (#61788) * Add eslint-plugin-react-compiler beta as a dependency * Enable eslint-plugin-react-compiler rule * Top-level await breaks eslint-plugin-react-compiler * Disable all dev files * Separate interactivity packages * Use shorter ESLint plugin name Co-authored-by: Pascal Birchler <pascalb@google.com> * Reformat * Disable react-compiler for native files * Enable enableTreatRefLikeIdentifiersAsRefs babel env setting * Disable validateRefAccessDuringRender * Move ESLint config outside of the eslint-plugin package --------- Co-authored-by: Pascal Birchler <pascalb@google.com> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .eslintrc.js | 12 +++++++++ package-lock.json | 65 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 3 files changed, 78 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index dfe779b4683523..d0c22090b93e87 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -156,6 +156,7 @@ module.exports = { 'plugin:eslint-comments/recommended', 'plugin:storybook/recommended', ], + plugins: [ 'react-compiler' ], globals: { wp: 'off', globalThis: 'readonly', @@ -222,6 +223,15 @@ module.exports = { definedTags: [ 'jest-environment' ], }, ], + 'react-compiler/react-compiler': [ + 'error', + { + environment: { + enableTreatRefLikeIdentifiersAsRefs: true, + validateRefAccessDuringRender: false, + }, + }, + ], }, overrides: [ { @@ -236,6 +246,7 @@ module.exports = { 'import/no-unresolved': 'off', 'import/named': 'off', '@wordpress/data-no-store-string-literals': 'off', + 'react-compiler/react-compiler': 'off', }, }, { @@ -551,6 +562,7 @@ module.exports = { { files: [ 'packages/interactivity*/src/**' ], rules: { + 'react-compiler/react-compiler': 'off', 'react/react-in-jsx-scope': 'error', }, }, diff --git a/package-lock.json b/package-lock.json index 52797a4cbe4625..036acafe885fa6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -91,6 +91,7 @@ "eslint-plugin-jest": "27.2.3", "eslint-plugin-jest-dom": "5.0.2", "eslint-plugin-prettier": "5.0.0", + "eslint-plugin-react-compiler": "19.0.0-beta-8a03594-20241020", "eslint-plugin-ssr-friendly": "1.0.6", "eslint-plugin-storybook": "0.6.13", "eslint-plugin-testing-library": "6.0.2", @@ -2478,6 +2479,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", @@ -25346,6 +25364,41 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, + "node_modules/eslint-plugin-react-compiler": { + "version": "19.0.0-beta-8a03594-20241020", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-19.0.0-beta-8a03594-20241020.tgz", + "integrity": "sha512-bYg1COih1s3r14IV/AKdQs/SN7CQmNI0ZaMtPdgZ6gp1S1Q/KGP9P43w7R6dHJ4wYpuMBvekNJHQdVu+x6UM+A==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "hermes-parser": "^0.20.1", + "zod": "^3.22.4", + "zod-validation-error": "^3.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.0.0 || >= 18.0.0" + }, + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-plugin-react-compiler/node_modules/hermes-estree": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.20.1.tgz", + "integrity": "sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg==", + "dev": true + }, + "node_modules/eslint-plugin-react-compiler/node_modules/hermes-parser": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.20.1.tgz", + "integrity": "sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA==", + "dev": true, + "dependencies": { + "hermes-estree": "0.20.1" + } + }, "node_modules/eslint-plugin-react-hooks": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz", @@ -51821,6 +51874,18 @@ "url": "https://github.com/sponsors/colinhacks" } }, + "node_modules/zod-validation-error": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.4.0.tgz", + "integrity": "sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==", + "dev": true, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.18.0" + } + }, "packages/a11y": { "name": "@wordpress/a11y", "version": "4.12.0", diff --git a/package.json b/package.json index f987643e737563..751bde40240811 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,7 @@ "eslint-plugin-jest": "27.2.3", "eslint-plugin-jest-dom": "5.0.2", "eslint-plugin-prettier": "5.0.0", + "eslint-plugin-react-compiler": "19.0.0-beta-8a03594-20241020", "eslint-plugin-ssr-friendly": "1.0.6", "eslint-plugin-storybook": "0.6.13", "eslint-plugin-testing-library": "6.0.2", From 5d24debbeb3251b1b612634925bf6c0f13efcbab Mon Sep 17 00:00:00 2001 From: Sarthak Nagoshe <83178197+sarthaknagoshe2002@users.noreply.github.com> Date: Tue, 19 Nov 2024 14:55:13 +0530 Subject: [PATCH 1621/1908] Prevent Pre-Publish Panel from Displaying Incorrect Information After Navigating away (#67010) Co-authored-by: sarthaknagoshe2002 <sarthaknagoshe2002@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../editor/src/components/post-publish-panel/index.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/editor/src/components/post-publish-panel/index.js b/packages/editor/src/components/post-publish-panel/index.js index 6a2d393e20c4ba..1fd36f9f69d7a2 100644 --- a/packages/editor/src/components/post-publish-panel/index.js +++ b/packages/editor/src/components/post-publish-panel/index.js @@ -47,9 +47,10 @@ export class PostPublishPanel extends Component { // Automatically collapse the publish sidebar when a post // is published and the user makes an edit. if ( - prevProps.isPublished && - ! this.props.isSaving && - this.props.isDirty + ( prevProps.isPublished && + ! this.props.isSaving && + this.props.isDirty ) || + this.props.currentPostId !== prevProps.currentPostId ) { this.props.onClose(); } @@ -75,6 +76,7 @@ export class PostPublishPanel extends Component { onTogglePublishSidebar, PostPublishExtension, PrePublishExtension, + currentPostId, ...additionalProps } = this.props; const { @@ -154,6 +156,7 @@ export default compose( [ const { getPostType } = select( coreStore ); const { getCurrentPost, + getCurrentPostId, getEditedPostAttribute, isCurrentPostPublished, isCurrentPostScheduled, @@ -177,6 +180,7 @@ export default compose( [ isSaving: isSavingPost() && ! isAutosavingPost(), isSavingNonPostEntityChanges: isSavingNonPostEntityChanges(), isScheduled: isCurrentPostScheduled(), + currentPostId: getCurrentPostId(), }; } ), withDispatch( ( dispatch, { isPublishSidebarEnabled } ) => { From 1723c376fa18e46dc8008f4bbf5c9d9414d15ad5 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 19 Nov 2024 13:53:23 +0400 Subject: [PATCH 1622/1908] Global Styles: Remove unused 'Fragment' import (#67104) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/edit-site/src/components/global-styles/ui.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index 0cab4c13aa3ee7..22ebad383884e9 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -19,7 +19,7 @@ import { __ } from '@wordpress/i18n'; import { store as preferencesStore } from '@wordpress/preferences'; import { moreVertical } from '@wordpress/icons'; import { store as coreStore } from '@wordpress/core-data'; -import { useEffect, Fragment } from '@wordpress/element'; +import { useEffect } from '@wordpress/element'; import { usePrevious } from '@wordpress/compose'; /** From c7722262e65a3f4d0f1a2d1ad29eccb2069509e4 Mon Sep 17 00:00:00 2001 From: Yogesh Bhutkar <yogesh.bhutkar@rtcamp.com> Date: Tue, 19 Nov 2024 15:33:23 +0530 Subject: [PATCH 1623/1908] Zoom Out: Disable zooming out when Distraction Free mode is activated (#67028) Co-authored-by: yogeshbhutkar <yogeshbhutkar@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> --- .../editor/src/components/header/style.scss | 3 +- .../src/components/zoom-out-toggle/index.js | 39 ++++++++++++------- packages/editor/src/store/actions.js | 3 ++ 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/packages/editor/src/components/header/style.scss b/packages/editor/src/components/header/style.scss index 4259ef4b8a2084..d12c01506a052c 100644 --- a/packages/editor/src/components/header/style.scss +++ b/packages/editor/src/components/header/style.scss @@ -256,7 +256,8 @@ & > .editor-header__toolbar .editor-document-tools__document-overview-toggle, & > .editor-header__settings > .editor-preview-dropdown, - & > .editor-header__settings > .interface-pinned-items { + & > .editor-header__settings > .interface-pinned-items, + & > .editor-header__settings > .editor-zoom-out-toggle { display: none; } diff --git a/packages/editor/src/components/zoom-out-toggle/index.js b/packages/editor/src/components/zoom-out-toggle/index.js index 080a4c58578069..2646898a066fb9 100644 --- a/packages/editor/src/components/zoom-out-toggle/index.js +++ b/packages/editor/src/components/zoom-out-toggle/index.js @@ -20,13 +20,19 @@ import { isAppleOS } from '@wordpress/keycodes'; import { unlock } from '../../lock-unlock'; const ZoomOutToggle = ( { disabled } ) => { - const { isZoomOut, showIconLabels } = useSelect( ( select ) => ( { - isZoomOut: unlock( select( blockEditorStore ) ).isZoomOut(), - showIconLabels: select( preferencesStore ).get( - 'core', - 'showIconLabels' - ), - } ) ); + const { isZoomOut, showIconLabels, isDistractionFree } = useSelect( + ( select ) => ( { + isZoomOut: unlock( select( blockEditorStore ) ).isZoomOut(), + showIconLabels: select( preferencesStore ).get( + 'core', + 'showIconLabels' + ), + isDistractionFree: select( preferencesStore ).get( + 'core', + 'distractionFree' + ), + } ) + ); const { resetZoomLevel, setZoomLevel } = unlock( useDispatch( blockEditorStore ) @@ -52,13 +58,19 @@ const ZoomOutToggle = ( { disabled } ) => { }; }, [ registerShortcut, unregisterShortcut ] ); - useShortcut( 'core/editor/zoom', () => { - if ( isZoomOut ) { - resetZoomLevel(); - } else { - setZoomLevel( 'auto-scaled' ); + useShortcut( + 'core/editor/zoom', + () => { + if ( isZoomOut ) { + resetZoomLevel(); + } else { + setZoomLevel( 'auto-scaled' ); + } + }, + { + isDisabled: isDistractionFree, } - } ); + ); const handleZoomOut = () => { if ( isZoomOut ) { @@ -78,6 +90,7 @@ const ZoomOutToggle = ( { disabled } ) => { isPressed={ isZoomOut } size="compact" showTooltip={ ! showIconLabels } + className="editor-zoom-out-toggle" /> ); }; diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index 7ff23cb49f4983..4942e50322e06e 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -834,6 +834,9 @@ export const toggleDistractionFree = .set( 'core', 'fixedToolbar', true ); dispatch.setIsInserterOpened( false ); dispatch.setIsListViewOpened( false ); + unlock( + registry.dispatch( blockEditorStore ) + ).resetZoomLevel(); } ); } registry.batch( () => { From 89b47b41bd5e4cb7d746917e03a5c0ee01725d98 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 19 Nov 2024 15:14:25 +0400 Subject: [PATCH 1624/1908] Editor: Correctly select post title support in 'DocumentOutline' (#67109) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/editor/README.md | 3 +-- packages/editor/src/components/document-outline/check.js | 2 +- packages/editor/src/components/document-outline/index.js | 6 ++---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/editor/README.md b/packages/editor/README.md index e0b53362089f1b..07405d0d51c3d2 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -279,8 +279,7 @@ Renders a document outline component. _Parameters_ - _props_ `Object`: Props. -- _props.onSelect_ `Function`: Function to be called when an outline item is selected. -- _props.isTitleSupported_ `boolean`: Indicates whether the title is supported. +- _props.onSelect_ `Function`: Function to be called when an outline item is selected - _props.hasOutlineItemsDisabled_ `boolean`: Indicates whether the outline items are disabled. _Returns_ diff --git a/packages/editor/src/components/document-outline/check.js b/packages/editor/src/components/document-outline/check.js index 7e396f45c82f1a..d0676aa9037ffe 100644 --- a/packages/editor/src/components/document-outline/check.js +++ b/packages/editor/src/components/document-outline/check.js @@ -19,7 +19,7 @@ export default function DocumentOutlineCheck( { children } ) { return getGlobalBlockCount( 'core/heading' ) > 0; } ); - if ( hasHeadings ) { + if ( ! hasHeadings ) { return null; } diff --git a/packages/editor/src/components/document-outline/index.js b/packages/editor/src/components/document-outline/index.js index 2ed53f771b67b7..ab5caa8cf0f8a4 100644 --- a/packages/editor/src/components/document-outline/index.js +++ b/packages/editor/src/components/document-outline/index.js @@ -102,19 +102,17 @@ const isEmptyHeading = ( heading ) => * Renders a document outline component. * * @param {Object} props Props. - * @param {Function} props.onSelect Function to be called when an outline item is selected. - * @param {boolean} props.isTitleSupported Indicates whether the title is supported. + * @param {Function} props.onSelect Function to be called when an outline item is selected * @param {boolean} props.hasOutlineItemsDisabled Indicates whether the outline items are disabled. * * @return {Component} The component to be rendered. */ export default function DocumentOutline( { onSelect, - isTitleSupported, hasOutlineItemsDisabled, } ) { const { selectBlock } = useDispatch( blockEditorStore ); - const { blocks, title } = useSelect( ( select ) => { + const { blocks, title, isTitleSupported } = useSelect( ( select ) => { const { getBlocks } = select( blockEditorStore ); const { getEditedPostAttribute } = select( editorStore ); const { getPostType } = select( coreStore ); From 68d77765aa2d4fc6e23e3ea561ee2b94bd51ce46 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 19 Nov 2024 21:30:34 +0900 Subject: [PATCH 1625/1908] Site Hub: Fix height in mobile layout (#67110) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/edit-site/src/components/site-hub/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/site-hub/style.scss b/packages/edit-site/src/components/site-hub/style.scss index b1c1a3a41cc532..39f44d2bef7bb5 100644 --- a/packages/edit-site/src/components/site-hub/style.scss +++ b/packages/edit-site/src/components/site-hub/style.scss @@ -4,7 +4,7 @@ justify-content: space-between; gap: $grid-unit-10; margin-right: $grid-unit-15; - height: $grid-unit-70; + height: $header-height; } .edit-site-site-hub__actions { From 6b42879ad0391dbe7e7dd352de2bc00cc4c152e7 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 19 Nov 2024 21:31:23 +0900 Subject: [PATCH 1626/1908] DataViews: Reduce the size of action button in Grid layout (#67032) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../src/components/dataviews-item-actions/index.tsx | 12 ++++++++++-- .../dataviews/src/dataviews-layouts/grid/style.scss | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-item-actions/index.tsx b/packages/dataviews/src/components/dataviews-item-actions/index.tsx index c1a1f84b99e624..47e65bc81cb171 100644 --- a/packages/dataviews/src/components/dataviews-item-actions/index.tsx +++ b/packages/dataviews/src/components/dataviews-item-actions/index.tsx @@ -57,6 +57,7 @@ interface ItemActionsProps< Item > { interface CompactItemActionsProps< Item > { item: Item; actions: Action< Item >[]; + isSmall?: boolean; } interface PrimaryActionsProps< Item > { @@ -214,7 +215,13 @@ export default function ItemActions< Item >( { }, [ actions, item ] ); if ( isCompact ) { - return <CompactItemActions item={ item } actions={ eligibleActions } />; + return ( + <CompactItemActions + item={ item } + actions={ eligibleActions } + isSmall + /> + ); } if ( hasOnlyOneActionAndIsPrimary( primaryActions, actions ) ) { @@ -250,12 +257,13 @@ export default function ItemActions< Item >( { function CompactItemActions< Item >( { item, actions, + isSmall, }: CompactItemActionsProps< Item > ) { return ( <Menu trigger={ <Button - size="compact" + size={ isSmall ? 'small' : 'compact' } icon={ moreVertical } label={ __( 'Actions' ) } accessibleWhenDisabled diff --git a/packages/dataviews/src/dataviews-layouts/grid/style.scss b/packages/dataviews/src/dataviews-layouts/grid/style.scss index 081adf51b5dc11..f209accc6de15c 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/style.scss +++ b/packages/dataviews/src/dataviews-layouts/grid/style.scss @@ -16,7 +16,7 @@ } .dataviews-view-grid__primary-field { - min-height: $grid-unit-40; // Preserve layout when there is no ellipsis button + min-height: $grid-unit-30; // Preserve layout when there is no ellipsis button display: flex; align-items: center; From 180211c80444130c30253cf8c71966c2cf751150 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 19 Nov 2024 22:23:27 +0900 Subject: [PATCH 1627/1908] Make `BlockManager` component reusable (#67052) * Make `BlockManager` component reusable * Convert a prop to an array * Revert "Convert a prop to an array" This reverts commit 242ba0e3a9008d9e896aeeb7208622650a58dbcb. Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../src/components/block-manager/category.js | 82 ++++++++-------- .../src/components/block-manager/checklist.js | 2 +- .../src/components/block-manager/index.js | 72 ++++++-------- .../preferences-modal/block-visibility.js | 94 +++++++++++++++++++ .../src/components/preferences-modal/index.js | 4 +- 5 files changed, 168 insertions(+), 86 deletions(-) create mode 100644 packages/editor/src/components/preferences-modal/block-visibility.js diff --git a/packages/editor/src/components/block-manager/category.js b/packages/editor/src/components/block-manager/category.js index e7125fa151f72a..341584fee03b96 100644 --- a/packages/editor/src/components/block-manager/category.js +++ b/packages/editor/src/components/block-manager/category.js @@ -1,73 +1,79 @@ /** * WordPress dependencies */ -import { useMemo, useCallback } from '@wordpress/element'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { useCallback } from '@wordpress/element'; import { useInstanceId } from '@wordpress/compose'; import { CheckboxControl } from '@wordpress/components'; -import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies */ import BlockTypesChecklist from './checklist'; -import { store as editorStore } from '../../store'; -import { unlock } from '../../lock-unlock'; -function BlockManagerCategory( { title, blockTypes } ) { +function BlockManagerCategory( { + title, + blockTypes, + selectedBlockTypes, + onChange, +} ) { const instanceId = useInstanceId( BlockManagerCategory ); - const { allowedBlockTypes, hiddenBlockTypes } = useSelect( ( select ) => { - const { getEditorSettings } = select( editorStore ); - const { get } = select( preferencesStore ); - return { - allowedBlockTypes: getEditorSettings().allowedBlockTypes, - hiddenBlockTypes: get( 'core', 'hiddenBlockTypes' ), - }; - }, [] ); - const filteredBlockTypes = useMemo( () => { - if ( allowedBlockTypes === true ) { - return blockTypes; - } - return blockTypes.filter( ( { name } ) => { - return allowedBlockTypes?.includes( name ); - } ); - }, [ allowedBlockTypes, blockTypes ] ); - const { showBlockTypes, hideBlockTypes } = unlock( - useDispatch( editorStore ) - ); + const toggleVisible = useCallback( - ( blockName, nextIsChecked ) => { + ( blockType, nextIsChecked ) => { if ( nextIsChecked ) { - showBlockTypes( blockName ); + onChange( [ ...selectedBlockTypes, blockType ] ); } else { - hideBlockTypes( blockName ); + onChange( + selectedBlockTypes.filter( + ( { name } ) => name !== blockType.name + ) + ); } }, - [ showBlockTypes, hideBlockTypes ] + [ selectedBlockTypes, onChange ] ); + const toggleAllVisible = useCallback( ( nextIsChecked ) => { - const blockNames = blockTypes.map( ( { name } ) => name ); if ( nextIsChecked ) { - showBlockTypes( blockNames ); + onChange( [ + ...selectedBlockTypes, + ...blockTypes.filter( + ( blockType ) => + ! selectedBlockTypes.find( + ( { name } ) => name === blockType.name + ) + ), + ] ); } else { - hideBlockTypes( blockNames ); + onChange( + selectedBlockTypes.filter( + ( selectedBlockType ) => + ! blockTypes.find( + ( { name } ) => name === selectedBlockType.name + ) + ) + ); } }, - [ blockTypes, showBlockTypes, hideBlockTypes ] + [ blockTypes, selectedBlockTypes, onChange ] ); - if ( ! filteredBlockTypes.length ) { + if ( ! blockTypes.length ) { return null; } - const checkedBlockNames = filteredBlockTypes + const checkedBlockNames = blockTypes .map( ( { name } ) => name ) - .filter( ( type ) => ! ( hiddenBlockTypes ?? [] ).includes( type ) ); + .filter( ( type ) => + ( selectedBlockTypes ?? [] ).some( + ( selectedBlockType ) => selectedBlockType.name === type + ) + ); const titleId = 'editor-block-manager__category-title-' + instanceId; - const isAllChecked = checkedBlockNames.length === filteredBlockTypes.length; + const isAllChecked = checkedBlockNames.length === blockTypes.length; const isIndeterminate = ! isAllChecked && checkedBlockNames.length > 0; return ( @@ -85,7 +91,7 @@ function BlockManagerCategory( { title, blockTypes } ) { label={ <span id={ titleId }>{ title }</span> } /> <BlockTypesChecklist - blockTypes={ filteredBlockTypes } + blockTypes={ blockTypes } value={ checkedBlockNames } onItemChange={ toggleVisible } /> diff --git a/packages/editor/src/components/block-manager/checklist.js b/packages/editor/src/components/block-manager/checklist.js index 01bd06abdeba86..2839e2c9e14c14 100644 --- a/packages/editor/src/components/block-manager/checklist.js +++ b/packages/editor/src/components/block-manager/checklist.js @@ -17,7 +17,7 @@ function BlockTypesChecklist( { blockTypes, value, onItemChange } ) { label={ blockType.title } checked={ value.includes( blockType.name ) } onChange={ ( ...args ) => - onItemChange( blockType.name, ...args ) + onItemChange( blockType, ...args ) } /> <BlockIcon icon={ blockType.icon } /> diff --git a/packages/editor/src/components/block-manager/index.js b/packages/editor/src/components/block-manager/index.js index 4a1145839976f9..5c719c62a5a0b2 100644 --- a/packages/editor/src/components/block-manager/index.js +++ b/packages/editor/src/components/block-manager/index.js @@ -2,69 +2,49 @@ * WordPress dependencies */ import { store as blocksStore } from '@wordpress/blocks'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; import { SearchControl, Button } from '@wordpress/components'; import { __, _n, sprintf } from '@wordpress/i18n'; import { useEffect, useState } from '@wordpress/element'; import { useDebounce } from '@wordpress/compose'; import { speak } from '@wordpress/a11y'; -import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies */ -import { unlock } from '../../lock-unlock'; -import { store as editorStore } from '../../store'; import BlockManagerCategory from './category'; -export default function BlockManager() { +/** + * Provides a list of blocks with checkboxes. + * + * @param {Object} props Props. + * @param {Array} props.blockTypes An array of blocks. + * @param {Array} props.selectedBlockTypes An array of selected blocks. + * @param {Function} props.onChange Function to be called when the selected blocks change. + */ +export default function BlockManager( { + blockTypes, + selectedBlockTypes, + onChange, +} ) { const debouncedSpeak = useDebounce( speak, 500 ); const [ search, setSearch ] = useState( '' ); - const { showBlockTypes } = unlock( useDispatch( editorStore ) ); - - const { - blockTypes, - categories, - hasBlockSupport, - isMatchingSearchTerm, - numberOfHiddenBlocks, - } = useSelect( ( select ) => { - // Some hidden blocks become unregistered - // by removing for instance the plugin that registered them, yet - // they're still remain as hidden by the user's action. - // We consider "hidden", blocks which were hidden and - // are still registered. - const _blockTypes = select( blocksStore ).getBlockTypes(); - const hiddenBlockTypes = ( - select( preferencesStore ).get( 'core', 'hiddenBlockTypes' ) ?? [] - ).filter( ( hiddenBlock ) => { - return _blockTypes.some( - ( registeredBlock ) => registeredBlock.name === hiddenBlock - ); - } ); - + const { categories, isMatchingSearchTerm } = useSelect( ( select ) => { return { - blockTypes: _blockTypes, categories: select( blocksStore ).getCategories(), - hasBlockSupport: select( blocksStore ).hasBlockSupport, isMatchingSearchTerm: select( blocksStore ).isMatchingSearchTerm, - numberOfHiddenBlocks: - Array.isArray( hiddenBlockTypes ) && hiddenBlockTypes.length, }; }, [] ); - function enableAllBlockTypes( newBlockTypes ) { - const blockNames = newBlockTypes.map( ( { name } ) => name ); - showBlockTypes( blockNames ); + function enableAllBlockTypes() { + onChange( blockTypes ); } - const filteredBlockTypes = blockTypes.filter( - ( blockType ) => - hasBlockSupport( blockType, 'inserter', true ) && - ( ! search || isMatchingSearchTerm( blockType, search ) ) && - ( ! blockType.parent || - blockType.parent.includes( 'core/post-content' ) ) - ); + const filteredBlockTypes = blockTypes.filter( ( blockType ) => { + return ! search || isMatchingSearchTerm( blockType, search ); + } ); + + const numberOfHiddenBlocks = blockTypes.length - selectedBlockTypes.length; // Announce search results on change useEffect( () => { @@ -96,9 +76,7 @@ export default function BlockManager() { <Button __next40pxDefaultSize variant="link" - onClick={ () => - enableAllBlockTypes( filteredBlockTypes ) - } + onClick={ enableAllBlockTypes } > { __( 'Reset' ) } </Button> @@ -131,6 +109,8 @@ export default function BlockManager() { ( blockType ) => blockType.category === category.slug ) } + selectedBlockTypes={ selectedBlockTypes } + onChange={ onChange } /> ) ) } <BlockManagerCategory @@ -138,6 +118,8 @@ export default function BlockManager() { blockTypes={ filteredBlockTypes.filter( ( { category } ) => ! category ) } + selectedBlockTypes={ selectedBlockTypes } + onChange={ onChange } /> </div> </div> diff --git a/packages/editor/src/components/preferences-modal/block-visibility.js b/packages/editor/src/components/preferences-modal/block-visibility.js new file mode 100644 index 00000000000000..49d6888c5dbfe2 --- /dev/null +++ b/packages/editor/src/components/preferences-modal/block-visibility.js @@ -0,0 +1,94 @@ +/** + * WordPress dependencies + */ +import { useSelect, useDispatch } from '@wordpress/data'; +import { store as preferencesStore } from '@wordpress/preferences'; +import { hasBlockSupport, store as blocksStore } from '@wordpress/blocks'; +import { useMemo } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { store as editorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; +import BlockManager from '../block-manager'; + +export default function BlockVisibility() { + const { showBlockTypes, hideBlockTypes } = unlock( + useDispatch( editorStore ) + ); + + const { + blockTypes, + allowedBlockTypes: _allowedBlockTypes, + hiddenBlockTypes: _hiddenBlockTypes, + } = useSelect( ( select ) => { + return { + blockTypes: select( blocksStore ).getBlockTypes(), + allowedBlockTypes: + select( editorStore ).getEditorSettings().allowedBlockTypes, + hiddenBlockTypes: + select( preferencesStore ).get( 'core', 'hiddenBlockTypes' ) ?? + [], + }; + }, [] ); + + const allowedBlockTypes = useMemo( () => { + if ( _allowedBlockTypes === true ) { + return blockTypes; + } + return blockTypes.filter( ( { name } ) => { + return _allowedBlockTypes?.includes( name ); + } ); + }, [ _allowedBlockTypes, blockTypes ] ); + + const filteredBlockTypes = allowedBlockTypes.filter( + ( blockType ) => + hasBlockSupport( blockType, 'inserter', true ) && + ( ! blockType.parent || + blockType.parent.includes( 'core/post-content' ) ) + ); + + // Some hidden blocks become unregistered + // by removing for instance the plugin that registered them, yet + // they're still remain as hidden by the user's action. + // We consider "hidden", blocks which were hidden and + // are still registered. + const hiddenBlockTypes = _hiddenBlockTypes.filter( ( hiddenBlock ) => { + return filteredBlockTypes.some( + ( registeredBlock ) => registeredBlock.name === hiddenBlock + ); + } ); + + const selectedBlockTypes = filteredBlockTypes.filter( + ( blockType ) => ! hiddenBlockTypes.includes( blockType.name ) + ); + + const onChangeSelectedBlockTypes = ( newSelectedBlockTypes ) => { + if ( selectedBlockTypes.length > newSelectedBlockTypes.length ) { + const blockTypesToHide = selectedBlockTypes.filter( + ( blockType ) => + ! newSelectedBlockTypes.find( + ( { name } ) => name === blockType.name + ) + ); + hideBlockTypes( blockTypesToHide.map( ( { name } ) => name ) ); + } else if ( selectedBlockTypes.length < newSelectedBlockTypes.length ) { + const blockTypesToShow = newSelectedBlockTypes.filter( + ( blockType ) => + ! selectedBlockTypes.find( + ( { name } ) => name === blockType.name + ) + ); + showBlockTypes( blockTypesToShow.map( ( { name } ) => name ) ); + } + }; + + return ( + <BlockManager + blockTypes={ filteredBlockTypes } + selectedBlockTypes={ selectedBlockTypes } + onChange={ onChangeSelectedBlockTypes } + /> + ); +} diff --git a/packages/editor/src/components/preferences-modal/index.js b/packages/editor/src/components/preferences-modal/index.js index 7ea7ea456ce28e..72042bca03b70c 100644 --- a/packages/editor/src/components/preferences-modal/index.js +++ b/packages/editor/src/components/preferences-modal/index.js @@ -18,7 +18,7 @@ import { store as interfaceStore } from '@wordpress/interface'; import EnablePanelOption from './enable-panel'; import EnablePluginDocumentSettingPanelOption from './enable-plugin-document-setting-panel'; import EnablePublishSidebarOption from './enable-publish-sidebar'; -import BlockManager from '../block-manager'; +import BlockVisibility from './block-visibility'; import PostTaxonomies from '../post-taxonomies'; import PostFeaturedImageCheck from '../post-featured-image/check'; import PostExcerptCheck from '../post-excerpt/check'; @@ -297,7 +297,7 @@ function PreferencesModalContents( { extraSections = {} } ) { "Disable blocks that you don't want to appear in the inserter. They can always be toggled back on later." ) } > - <BlockManager /> + <BlockVisibility /> </PreferencesModalSection> </> ), From 62704a0167913527203e48e5c7d5a2dda575f44d Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:59:41 +0200 Subject: [PATCH 1628/1908] ESLint: Bump `eslint-plugin-react-compiler` to latest beta (#67106) * Bump eslint-plugin-react-compiler to 19.0.0-beta-0dec889-20241115 * Use ref for prev heading level in DocumentOutline Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- package-lock.json | 8 ++++---- package.json | 2 +- .../editor/src/components/document-outline/index.js | 10 ++++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 036acafe885fa6..376cd0b9e6edf6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -91,7 +91,7 @@ "eslint-plugin-jest": "27.2.3", "eslint-plugin-jest-dom": "5.0.2", "eslint-plugin-prettier": "5.0.0", - "eslint-plugin-react-compiler": "19.0.0-beta-8a03594-20241020", + "eslint-plugin-react-compiler": "19.0.0-beta-0dec889-20241115", "eslint-plugin-ssr-friendly": "1.0.6", "eslint-plugin-storybook": "0.6.13", "eslint-plugin-testing-library": "6.0.2", @@ -25365,9 +25365,9 @@ } }, "node_modules/eslint-plugin-react-compiler": { - "version": "19.0.0-beta-8a03594-20241020", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-19.0.0-beta-8a03594-20241020.tgz", - "integrity": "sha512-bYg1COih1s3r14IV/AKdQs/SN7CQmNI0ZaMtPdgZ6gp1S1Q/KGP9P43w7R6dHJ4wYpuMBvekNJHQdVu+x6UM+A==", + "version": "19.0.0-beta-0dec889-20241115", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-19.0.0-beta-0dec889-20241115.tgz", + "integrity": "sha512-jTjEHuE8/R6qD/CD2d+5YvWMy1q9/tX3kft4WDyg42/HktjHtHXrEToyZ6THEQf8t/YWMY1RGeCkykePbACtFA==", "dev": true, "dependencies": { "@babel/core": "^7.24.4", diff --git a/package.json b/package.json index 751bde40240811..a7470a1333ffad 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "eslint-plugin-jest": "27.2.3", "eslint-plugin-jest-dom": "5.0.2", "eslint-plugin-prettier": "5.0.0", - "eslint-plugin-react-compiler": "19.0.0-beta-8a03594-20241020", + "eslint-plugin-react-compiler": "19.0.0-beta-0dec889-20241115", "eslint-plugin-ssr-friendly": "1.0.6", "eslint-plugin-storybook": "0.6.13", "eslint-plugin-testing-library": "6.0.2", diff --git a/packages/editor/src/components/document-outline/index.js b/packages/editor/src/components/document-outline/index.js index ab5caa8cf0f8a4..c5e59837362092 100644 --- a/packages/editor/src/components/document-outline/index.js +++ b/packages/editor/src/components/document-outline/index.js @@ -3,6 +3,7 @@ */ import { __ } from '@wordpress/i18n'; import { useDispatch, useSelect } from '@wordpress/data'; +import { useRef } from '@wordpress/element'; import { create, getTextContent } from '@wordpress/rich-text'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { store as coreStore } from '@wordpress/core-data'; @@ -125,6 +126,8 @@ export default function DocumentOutline( { }; } ); + const prevHeadingLevelRef = useRef( 1 ); + const headings = computeOutlineHeadings( blocks ); if ( headings.length < 1 ) { return ( @@ -139,8 +142,6 @@ export default function DocumentOutline( { ); } - let prevHeadingLevel = 1; - // Not great but it's the simplest way to locate the title right now. const titleNode = document.querySelector( '.editor-post-title__input' ); const hasTitle = isTitleSupported && title && titleNode; @@ -170,7 +171,8 @@ export default function DocumentOutline( { { headings.map( ( item, index ) => { // Headings remain the same, go up by one, or down by any amount. // Otherwise there are missing levels. - const isIncorrectLevel = item.level > prevHeadingLevel + 1; + const isIncorrectLevel = + item.level > prevHeadingLevelRef.current + 1; const isValid = ! item.isEmpty && @@ -178,7 +180,7 @@ export default function DocumentOutline( { !! item.level && ( item.level !== 1 || ( ! hasMultipleH1 && ! hasTitle ) ); - prevHeadingLevel = item.level; + prevHeadingLevelRef.current = item.level; return ( <DocumentOutlineItem From ede2993f8c259aefe3a9308e308b7cac15fcb7c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:12:00 -0500 Subject: [PATCH 1629/1908] Bump gradle/actions from 4.2.0 to 4.2.1 in the react-native group (#67115) Bumps the react-native group with 1 update: [gradle/actions](https://github.com/gradle/actions). Updates `gradle/actions` from 4.2.0 to 4.2.1 - [Release notes](https://github.com/gradle/actions/releases) - [Commits](https://github.com/gradle/actions/compare/473878a77f1b98e2b5ac4af93489d1656a80a5ed...cc4fc85e6b35bafd578d5ffbc76a5518407e1af0) --- updated-dependencies: - dependency-name: gradle/actions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: react-native ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/rnmobile-android-runner.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index 43a71809b5bbe7..f8ff0441a95b7b 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -47,7 +47,7 @@ jobs: run: npm run native test:e2e:setup - name: Gradle cache - uses: gradle/actions/setup-gradle@473878a77f1b98e2b5ac4af93489d1656a80a5ed # v4.2.0 + uses: gradle/actions/setup-gradle@cc4fc85e6b35bafd578d5ffbc76a5518407e1af0 # v4.2.1 # AVD cache disabled as it caused emulator termination to hang indefinitely. # https://github.com/ReactiveCircus/android-emulator-runner/issues/385 From cf59c28e1b0cd0870eb82c21eedf221ebf92c606 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 19 Nov 2024 18:24:22 +0400 Subject: [PATCH 1630/1908] Inserter: Set initial active tab ID during render (#67103) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../components/inserter/category-tabs/index.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/components/inserter/category-tabs/index.js b/packages/block-editor/src/components/inserter/category-tabs/index.js index 7b6baaab398f82..ff0a130f1a8271 100644 --- a/packages/block-editor/src/components/inserter/category-tabs/index.js +++ b/packages/block-editor/src/components/inserter/category-tabs/index.js @@ -6,7 +6,7 @@ import { privateApis as componentsPrivateApis, __unstableMotion as motion, } from '@wordpress/components'; -import { useState, useEffect } from '@wordpress/element'; +import { useState } from '@wordpress/element'; /** * Internal dependencies @@ -35,14 +35,13 @@ function CategoryTabs( { const selectedTabId = selectedCategory ? selectedCategory.name : null; const [ activeTabId, setActiveId ] = useState(); const firstTabId = categories?.[ 0 ]?.name; - useEffect( () => { - // If there is no active tab, make the first tab the active tab, so that - // when focus is moved to the tablist, the first tab will be focused - // despite not being selected - if ( selectedTabId === null && ! activeTabId && firstTabId ) { - setActiveId( firstTabId ); - } - }, [ selectedTabId, activeTabId, firstTabId, setActiveId ] ); + + // If there is no active tab, make the first tab the active tab, so that + // when focus is moved to the tablist, the first tab will be focused + // despite not being selected + if ( selectedTabId === null && ! activeTabId && firstTabId ) { + setActiveId( firstTabId ); + } return ( <Tabs From c43a0c9944b33ad01fa2805a02a171b42b791282 Mon Sep 17 00:00:00 2001 From: Tyler Bailey <tyler.bailey@10up.com> Date: Tue, 19 Nov 2024 10:33:59 -0500 Subject: [PATCH 1631/1908] Feature: Set editor rendering mode by post type (#62304) Co-authored-by: TylerB24890 <tyb@git.wordpress.org> Co-authored-by: Sidsector9 <nomnom99@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: dcalhoun <dpcalhoun@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: dinhtungdu <dinhtungdu@git.wordpress.org> --- backport-changelog/6.8/7129.md | 3 + ...tenberg-rest-post-types-controller-6-8.php | 61 ++++++++++++++ lib/compat/wordpress-6.8/post.php | 57 +++++++++++++ lib/compat/wordpress-6.8/rest-api.php | 22 +++++ lib/load.php | 3 + .../block-editor/use-site-editor-settings.js | 11 +-- .../edit-site/src/components/editor/index.js | 4 +- .../editor/src/components/provider/index.js | 83 ++++++++++++------- packages/editor/src/store/reducer.native.js | 2 + .../initialize-editor.js | 17 ++++ test/performance/fixtures/perf-utils.ts | 20 +++++ test/performance/specs/site-editor.spec.js | 2 + 12 files changed, 243 insertions(+), 42 deletions(-) create mode 100644 backport-changelog/6.8/7129.md create mode 100644 lib/compat/wordpress-6.8/class-gutenberg-rest-post-types-controller-6-8.php create mode 100644 lib/compat/wordpress-6.8/post.php create mode 100644 lib/compat/wordpress-6.8/rest-api.php diff --git a/backport-changelog/6.8/7129.md b/backport-changelog/6.8/7129.md new file mode 100644 index 00000000000000..90c9168cdc6f8a --- /dev/null +++ b/backport-changelog/6.8/7129.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7129 + +* https://github.com/WordPress/gutenberg/pull/62304 diff --git a/lib/compat/wordpress-6.8/class-gutenberg-rest-post-types-controller-6-8.php b/lib/compat/wordpress-6.8/class-gutenberg-rest-post-types-controller-6-8.php new file mode 100644 index 00000000000000..da0489210e21f1 --- /dev/null +++ b/lib/compat/wordpress-6.8/class-gutenberg-rest-post-types-controller-6-8.php @@ -0,0 +1,61 @@ +<?php +/** + * REST API: Gutenberg_REST_Post_Types_Controller_6_8 class + * + * @package gutenberg + */ + +/** + * Gutenberg_REST_Post_Types_Controller_6_8 class + * + * Add Block Editor default rendering mode to the post type response + * to allow enabling/disabling at the post type level. + */ +class Gutenberg_REST_Post_Types_Controller_6_8 extends WP_REST_Post_Types_Controller { + /** + * Add Block Editor default rendering mode setting to the response. + * + * @param WP_Post_Type $item Post type object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response( $item, $request ) { + $response = parent::prepare_item_for_response( $item, $request ); + $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; + + // Property will only exist if the post type supports the block editor. + if ( 'edit' === $context && property_exists( $item, 'default_rendering_mode' ) ) { + /** + * Filters the block editor rendering mode for a post type. + * + * @since 6.8.0 + * @param string $default_rendering_mode Default rendering mode for the post type. + * @param WP_Post_Type $post_type Post type name. + * @return string Default rendering mode for the post type. + */ + $rendering_mode = apply_filters( 'post_type_default_rendering_mode', $item->default_rendering_mode, $item ); + + /** + * Filters the block editor rendering mode for a specific post type. + * Applied after the generic `post_type_default_rendering_mode` filter. + * + * The dynamic portion of the hook name, `$item->name`, refers to the post type slug. + * + * @since 6.8.0 + * @param string $default_rendering_mode Default rendering mode for the post type. + * @param WP_Post_Type $post_type Post type object. + * @return string Default rendering mode for the post type. + */ + $rendering_mode = apply_filters( "post_type_{$item->name}_default_rendering_mode", $rendering_mode, $item ); + + // Validate the filtered rendering mode. + if ( ! in_array( $rendering_mode, gutenberg_post_type_rendering_modes(), true ) ) { + $rendering_mode = 'post-only'; + } + + $response->data['default_rendering_mode'] = $rendering_mode; + } + + return rest_ensure_response( $response ); + } +} diff --git a/lib/compat/wordpress-6.8/post.php b/lib/compat/wordpress-6.8/post.php new file mode 100644 index 00000000000000..26e6c3adc07a3d --- /dev/null +++ b/lib/compat/wordpress-6.8/post.php @@ -0,0 +1,57 @@ +<?php +/** + * Temporary compatibility shims for block APIs present in Gutenberg. + * + * @package gutenberg + */ + +/** + * Get the available rendering modes for the Block Editor. + * + * post-only: This mode extracts the post blocks from the template and renders only those. + * The idea is to allow the user to edit the post/page in isolation without the wrapping template. + * + * template-locked: This mode renders both the template and the post blocks + * but the template blocks are locked and can't be edited. The post blocks are editable. + * + * @return array Array of available rendering modes. + */ +function gutenberg_post_type_rendering_modes() { + return array( + 'post-only', + 'template-locked', + ); +} + +/** + * Add the default_rendering_mode property to the WP_Post_Type object. + * This property can be overwritten by using the post_type_default_rendering_mode filter. + * + * @param array $args Array of post type arguments. + * @param string $post_type Post type key. + * @return array Updated array of post type arguments. + */ +function gutenberg_post_type_default_rendering_mode( $args, $post_type ) { + $rendering_mode = 'page' === $post_type ? 'template-locked' : 'post-only'; + $rendering_modes = gutenberg_post_type_rendering_modes(); + + // Make sure the post type supports the block editor. + if ( + wp_is_block_theme() && + ( isset( $args['show_in_rest'] ) && $args['show_in_rest'] ) && + ( isset( $args['supports'] ) && in_array( 'editor', $args['supports'], true ) ) + ) { + // Validate the supplied rendering mode. + if ( + isset( $args['default_rendering_mode'] ) && + in_array( $args['default_rendering_mode'], $rendering_modes, true ) + ) { + $rendering_mode = $args['default_rendering_mode']; + } + + $args['default_rendering_mode'] = $rendering_mode; + } + + return $args; +} +add_filter( 'register_post_type_args', 'gutenberg_post_type_default_rendering_mode', 10, 2 ); diff --git a/lib/compat/wordpress-6.8/rest-api.php b/lib/compat/wordpress-6.8/rest-api.php new file mode 100644 index 00000000000000..da1b657cda0783 --- /dev/null +++ b/lib/compat/wordpress-6.8/rest-api.php @@ -0,0 +1,22 @@ +<?php +/** + * PHP and WordPress configuration compatibility functions for the Gutenberg + * editor plugin changes related to REST API. + * + * @package gutenberg + */ + +if ( ! defined( 'ABSPATH' ) ) { + die( 'Silence is golden.' ); +} + +if ( ! function_exists( 'gutenberg_add_post_type_rendering_mode' ) ) { + /** + * Add Block Editor default rendering mode to the post type response. + */ + function gutenberg_add_post_type_rendering_mode() { + $controller = new Gutenberg_REST_Post_Types_Controller_6_8(); + $controller->register_routes(); + } +} +add_action( 'rest_api_init', 'gutenberg_add_post_type_rendering_mode' ); diff --git a/lib/load.php b/lib/load.php index d7e4a33cd02c92..100160176f3911 100644 --- a/lib/load.php +++ b/lib/load.php @@ -49,6 +49,8 @@ function gutenberg_is_experiment_enabled( $name ) { // WordPress 6.8 compat. require __DIR__ . '/compat/wordpress-6.8/block-comments.php'; require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php'; + require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-post-types-controller-6-8.php'; + require __DIR__ . '/compat/wordpress-6.8/rest-api.php'; // Plugin specific code. require_once __DIR__ . '/class-wp-rest-global-styles-controller-gutenberg.php'; @@ -120,6 +122,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.8/preload.php'; require __DIR__ . '/compat/wordpress-6.8/blocks.php'; require __DIR__ . '/compat/wordpress-6.8/functions.php'; +require __DIR__ . '/compat/wordpress-6.8/post.php'; // Experimental features. require __DIR__ . '/experimental/block-editor-settings-mobile.php'; diff --git a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js index 5c75de6d81e720..186f4aacf79232 100644 --- a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js +++ b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js @@ -36,9 +36,7 @@ function useNavigateToPreviousEntityRecord() { return goBack; } -export function useSpecificEditorSettings( - shouldUseTemplateAsDefaultRenderingMode -) { +export function useSpecificEditorSettings() { const { params } = useLocation(); const { canvas = 'view' } = params; const onNavigateToEntityRecord = useNavigateToEntityRecord(); @@ -49,11 +47,6 @@ export function useSpecificEditorSettings( }; }, [] ); - // TODO: The `shouldUseTemplateAsDefaultRenderingMode` check should be removed when the default rendering mode per post type is merged. - // @see https://github.com/WordPress/gutenberg/pull/62304/ - const defaultRenderingMode = shouldUseTemplateAsDefaultRenderingMode - ? 'template-locked' - : 'post-only'; const onNavigateToPreviousEntityRecord = useNavigateToPreviousEntityRecord(); const defaultEditorSettings = useMemo( () => { @@ -63,7 +56,6 @@ export function useSpecificEditorSettings( richEditingEnabled: true, supportsTemplateMode: true, focusMode: canvas !== 'view', - defaultRenderingMode, onNavigateToEntityRecord, onNavigateToPreviousEntityRecord, isPreviewMode: canvas === 'view', @@ -71,7 +63,6 @@ export function useSpecificEditorSettings( }, [ settings, canvas, - defaultRenderingMode, onNavigateToEntityRecord, onNavigateToPreviousEntityRecord, ] ); diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 51d734f25c6adb..1d115dca7518df 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -131,9 +131,7 @@ export default function EditSiteEditor( { isPostsList = false } ) { 'edit-site-editor__loading-progress' ); - const settings = useSpecificEditorSettings( - !! context?.postId && context?.postType !== 'post' - ); + const settings = useSpecificEditorSettings(); const styles = useMemo( () => [ ...settings.styles, diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 50d02610062c00..6c05e5b58235b3 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -72,8 +72,7 @@ const NON_CONTEXTUAL_POST_TYPES = [ * @return {Array} Block editor props. */ function useBlockEditorProps( post, template, mode ) { - const rootLevelPost = - mode === 'post-only' || ! template ? 'post' : 'template'; + const rootLevelPost = mode === 'template-locked' ? 'template' : 'post'; const [ postBlocks, onInput, onChange ] = useEntityBlockEditor( 'postType', post.type, @@ -164,30 +163,48 @@ export const ExperimentalEditorProvider = withRegistryProvider( BlockEditorProviderComponent = ExperimentalBlockEditorProvider, __unstableTemplate: template, } ) => { - const { editorSettings, selection, isReady, mode, postTypeEntities } = - useSelect( - ( select ) => { - const { - getEditorSettings, - getEditorSelection, - getRenderingMode, - __unstableIsEditorReady, - } = select( editorStore ); - const { getEntitiesConfig } = select( coreStore ); + const { + editorSettings, + selection, + isReady, + mode, + defaultMode, + postTypeEntities, + hasLoadedPostObject, + } = useSelect( + ( select ) => { + const { + getEditorSettings, + getEditorSelection, + getRenderingMode, + __unstableIsEditorReady, + } = select( editorStore ); + const { getEntitiesConfig } = select( coreStore ); + + const postTypeObject = select( coreStore ).getPostType( + post.type + ); + + const _hasLoadedPostObject = select( + coreStore + ).hasFinishedResolution( 'getPostType', [ post.type ] ); - return { - editorSettings: getEditorSettings(), - isReady: __unstableIsEditorReady(), - mode: getRenderingMode(), - selection: getEditorSelection(), - postTypeEntities: - post.type === 'wp_template' - ? getEntitiesConfig( 'postType' ) - : null, - }; - }, - [ post.type ] - ); + return { + hasLoadedPostObject: _hasLoadedPostObject, + editorSettings: getEditorSettings(), + isReady: __unstableIsEditorReady(), + mode: getRenderingMode(), + defaultMode: + postTypeObject?.default_rendering_mode ?? 'post-only', + selection: getEditorSelection(), + postTypeEntities: + post.type === 'wp_template' + ? getEntitiesConfig( 'postType' ) + : null, + }; + }, + [ post.type ] + ); const shouldRenderTemplate = !! template && mode !== 'post-only'; const rootLevelPost = shouldRenderTemplate ? template : post; const defaultBlockContext = useMemo( () => { @@ -282,7 +299,15 @@ export const ExperimentalEditorProvider = withRegistryProvider( } ); } - }, [] ); + }, [ + createWarningNotice, + initialEdits, + settings, + post, + recovery, + setupEditor, + updatePostLock, + ] ); // Synchronizes the active post with the state useEffect( () => { @@ -301,15 +326,15 @@ export const ExperimentalEditorProvider = withRegistryProvider( // Sets the right rendering mode when loading the editor. useEffect( () => { - setRenderingMode( settings.defaultRenderingMode ?? 'post-only' ); - }, [ settings.defaultRenderingMode, setRenderingMode ] ); + setRenderingMode( defaultMode ); + }, [ defaultMode, setRenderingMode ] ); useHideBlocksFromInserter( post.type, mode ); // Register the editor commands. useCommands(); - if ( ! isReady ) { + if ( ! isReady || ! mode || ! hasLoadedPostObject ) { return null; } diff --git a/packages/editor/src/store/reducer.native.js b/packages/editor/src/store/reducer.native.js index 7566dfc5dfd038..fbf6c968f57d08 100644 --- a/packages/editor/src/store/reducer.native.js +++ b/packages/editor/src/store/reducer.native.js @@ -9,6 +9,7 @@ import { combineReducers } from '@wordpress/data'; import { postId, postType, + renderingMode, saving, postLock, postSavingLock, @@ -82,6 +83,7 @@ export default combineReducers( { postId, postType, postTitle, + renderingMode, saving, postLock, postSavingLock, diff --git a/test/native/integration-test-helpers/initialize-editor.js b/test/native/integration-test-helpers/initialize-editor.js index 511f0223e11356..3b89da979aee3a 100644 --- a/test/native/integration-test-helpers/initialize-editor.js +++ b/test/native/integration-test-helpers/initialize-editor.js @@ -10,6 +10,8 @@ import { v4 as uuid } from 'uuid'; import { createElement, cloneElement } from '@wordpress/element'; // eslint-disable-next-line no-restricted-imports import { initializeEditor as internalInitializeEditor } from '@wordpress/edit-post'; +import { store as coreStore } from '@wordpress/core-data'; +import { select } from '@wordpress/data'; /** * Internal dependencies @@ -28,6 +30,21 @@ import { getGlobalStyles } from './get-global-styles'; * @return {import('@testing-library/react-native').RenderAPI} A Testing Library screen. */ export async function initializeEditor( props, { component } = {} ) { + const resolutionSpy = jest.spyOn( + select( coreStore ), + 'hasFinishedResolution' + ); + const actualResolution = resolutionSpy.getMockImplementation(); + resolutionSpy.mockImplementation( ( selectorName, args ) => { + // The mobile editor only supports the `post-only` rendering mode, so we + // presume a resolved `getPostType` selector to unblock editor rendering. + if ( 'getPostType' === selectorName ) { + return true; + } + + return actualResolution( selectorName, args ); + } ); + const uniqueId = uuid(); const postId = `post-id-${ uniqueId }`; const postType = 'post'; diff --git a/test/performance/fixtures/perf-utils.ts b/test/performance/fixtures/perf-utils.ts index 592e8194852e3b..8d23d91ff91bfd 100644 --- a/test/performance/fixtures/perf-utils.ts +++ b/test/performance/fixtures/perf-utils.ts @@ -97,6 +97,26 @@ export class PerfUtils { return canvas; } + /** + * Change the rendering mode of the editor. + * + * Setting the rendering mode to something other than the default is sometimes + * needed when for example we want to update the contents of the editor from a + * HTML file. Calling the resetBlocks method of the core/block-editor store will + * replace the contents of the template if the rendering mode is not post-only. + * So this should always be called before the resetBlocks method is used. + * + * @param newRenderingMode Rendering mode to set + * + * @return Promise<void> + */ + async setRenderingMode( newRenderingMode: string ) { + await this.page.evaluate( ( _newRenderingMode ) => { + const { dispatch } = window.wp.data; + dispatch( 'core/editor' ).setRenderingMode( _newRenderingMode ); + }, newRenderingMode ); + } + /** * Loads blocks from the small post with containers fixture into the editor * canvas. diff --git a/test/performance/specs/site-editor.spec.js b/test/performance/specs/site-editor.spec.js index 9c9d8aec71da4a..e72d83fa8b3aa4 100644 --- a/test/performance/specs/site-editor.spec.js +++ b/test/performance/specs/site-editor.spec.js @@ -64,6 +64,7 @@ test.describe( 'Site Editor Performance', () => { test( 'Setup the test page', async ( { admin, perfUtils } ) => { await admin.createNewPost( { postType: 'page' } ); + await perfUtils.setRenderingMode( 'post-only' ); await perfUtils.loadBlocksForLargePost(); draftId = await perfUtils.saveDraft(); @@ -122,6 +123,7 @@ test.describe( 'Site Editor Performance', () => { test( 'Setup the test post', async ( { admin, editor, perfUtils } ) => { await admin.createNewPost( { postType: 'page' } ); + await perfUtils.setRenderingMode( 'post-only' ); await perfUtils.loadBlocksForLargePost(); await editor.insertBlock( { name: 'core/paragraph' } ); From d478c08d4c0827864e7be4e2df487297ad36d7b0 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 20 Nov 2024 01:52:35 +0900 Subject: [PATCH 1632/1908] ColorPicker: Update sizes of format select and copy button (#67093) * ColorPicker: Update sizes of format select and copy button * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ .../src/color-picker/color-copy-button.tsx | 6 +++--- packages/components/src/color-picker/component.tsx | 1 + packages/components/src/color-picker/styles.ts | 13 ------------- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index d93eb30ac0ec50..dfb9454d8da1f0 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -12,6 +12,10 @@ - `ToggleGroupControl`: Fix active background for `0` value ([#66855](https://github.com/WordPress/gutenberg/pull/66855)). - `SlotFill`: Fix a bug where a stale value of `fillProps` could be used ([#67000](https://github.com/WordPress/gutenberg/pull/67000)). +### Enhancements + +- `ColorPicker`: Update sizes of color format select and copy button ([#67093](https://github.com/WordPress/gutenberg/pull/67093)). + ### Experimental - `SlotFill`: Remove registration API methods from return value of `__experimentalUseSlot` ([#67070](https://github.com/WordPress/gutenberg/pull/67070)). diff --git a/packages/components/src/color-picker/color-copy-button.tsx b/packages/components/src/color-picker/color-copy-button.tsx index b8a4822544322c..0076a2125d00c0 100644 --- a/packages/components/src/color-picker/color-copy-button.tsx +++ b/packages/components/src/color-picker/color-copy-button.tsx @@ -9,7 +9,7 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import { CopyButton } from './styles'; +import { Button } from '../button'; import Tooltip from '../tooltip'; import type { ColorCopyButtonProps } from './types'; @@ -63,8 +63,8 @@ export const ColorCopyButton = ( props: ColorCopyButtonProps ) => { copiedColor === color.toHex() ? __( 'Copied!' ) : __( 'Copy' ) } > - <CopyButton - size="small" + <Button + size="compact" ref={ copyRef } icon={ copy } showTooltip={ false } diff --git a/packages/components/src/color-picker/component.tsx b/packages/components/src/color-picker/component.tsx index a1112d2e1ecd23..a2ddb6cd8ee4b6 100644 --- a/packages/components/src/color-picker/component.tsx +++ b/packages/components/src/color-picker/component.tsx @@ -87,6 +87,7 @@ const UnconnectedColorPicker = ( <AuxiliaryColorArtefactHStackHeader justify="space-between"> <SelectControl __nextHasNoMarginBottom + size="compact" options={ options } value={ colorType } onChange={ ( nextColorType ) => diff --git a/packages/components/src/color-picker/styles.ts b/packages/components/src/color-picker/styles.ts index a78f10de2e4a32..50ce33da9f2333 100644 --- a/packages/components/src/color-picker/styles.ts +++ b/packages/components/src/color-picker/styles.ts @@ -11,7 +11,6 @@ import InnerSelectControl from '../select-control'; import InnerRangeControl from '../range-control'; import { space } from '../utils/space'; import { boxSizingReset } from '../utils'; -import Button from '../button'; import { Flex } from '../flex'; import { HStack } from '../h-stack'; import CONFIG from '../utils/config-values'; @@ -22,7 +21,6 @@ export const NumberControlWrapper = styled( NumberControl )` export const SelectControl = styled( InnerSelectControl )` margin-left: ${ space( -2 ) }; - width: 5em; `; export const RangeControl = styled( InnerRangeControl )` @@ -101,14 +99,3 @@ export const ColorfulWrapper = styled.div` ${ interactiveHueStyles } `; - -export const CopyButton = styled( Button )` - &&&&& { - min-width: ${ space( 6 ) }; - padding: 0; - - > svg { - margin-right: 0; - } - } -`; From dea308b86eb32c23d384cd2d0f756fc9a047cca1 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 20 Nov 2024 07:28:07 +0900 Subject: [PATCH 1633/1908] ColorPicker: Add accessible label for copy button (#67094) * ColorPicker: Add accessible label for copy button * Add changelog * Use variable Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/color-picker/color-copy-button.tsx | 12 +++++------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index dfb9454d8da1f0..34a90b6ca23b3c 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -11,6 +11,7 @@ - `ToggleGroupControl`: Fix active background for `0` value ([#66855](https://github.com/WordPress/gutenberg/pull/66855)). - `SlotFill`: Fix a bug where a stale value of `fillProps` could be used ([#67000](https://github.com/WordPress/gutenberg/pull/67000)). +- `ColorPicker`: Add accessible label for copy button ([#67094](https://github.com/WordPress/gutenberg/pull/67094)). ### Enhancements diff --git a/packages/components/src/color-picker/color-copy-button.tsx b/packages/components/src/color-picker/color-copy-button.tsx index 0076a2125d00c0..6e49fa7ae85e74 100644 --- a/packages/components/src/color-picker/color-copy-button.tsx +++ b/packages/components/src/color-picker/color-copy-button.tsx @@ -55,16 +55,14 @@ export const ColorCopyButton = ( props: ColorCopyButtonProps ) => { }; }, [] ); + const label = + copiedColor === color.toHex() ? __( 'Copied!' ) : __( 'Copy' ); + return ( - <Tooltip - delay={ 0 } - hideOnClick={ false } - text={ - copiedColor === color.toHex() ? __( 'Copied!' ) : __( 'Copy' ) - } - > + <Tooltip delay={ 0 } hideOnClick={ false } text={ label }> <Button size="compact" + aria-label={ label } ref={ copyRef } icon={ copy } showTooltip={ false } From fbc8c9f7bfecd01a410024079496d8ab4b3546ca Mon Sep 17 00:00:00 2001 From: VATALIYA PARTH <88878890+PARTHVATALIYA@users.noreply.github.com> Date: Wed, 20 Nov 2024 04:41:15 +0530 Subject: [PATCH 1634/1908] ComboboxControl : Deprecate 36px default size (#66900) * Add the console warning for 36px size variation * Add the changelog for the deprecation * Update: changelog and JSDoc --------- Co-authored-by: PARTHVATALIYA <parthvataliya@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/combobox-control/README.md | 1 + packages/components/src/combobox-control/index.tsx | 8 ++++++++ .../src/combobox-control/stories/index.story.tsx | 1 + packages/components/src/combobox-control/test/index.tsx | 8 +++++++- 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 34a90b6ca23b3c..927b1a12cee4c3 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -30,6 +30,7 @@ ### Deprecations - `Radio`: Deprecate 36px default size ([#66572](https://github.com/WordPress/gutenberg/pull/66572)). +- `ComboboxControl`: Deprecate 36px default size ([#66900](https://github.com/WordPress/gutenberg/pull/66900)). ### Bug Fixes diff --git a/packages/components/src/combobox-control/README.md b/packages/components/src/combobox-control/README.md index 5831c5ec2832c2..4089cf9c56e9b5 100644 --- a/packages/components/src/combobox-control/README.md +++ b/packages/components/src/combobox-control/README.md @@ -34,6 +34,7 @@ function MyComboboxControl() { const [ filteredOptions, setFilteredOptions ] = useState( options ); return ( <ComboboxControl + __next40pxDefaultSize __nextHasNoMarginBottom label="Font Size" value={ fontSize } diff --git a/packages/components/src/combobox-control/index.tsx b/packages/components/src/combobox-control/index.tsx index 5c6725a51b435d..86fa4f4467318c 100644 --- a/packages/components/src/combobox-control/index.tsx +++ b/packages/components/src/combobox-control/index.tsx @@ -34,6 +34,7 @@ import type { ComboboxControlOption, ComboboxControlProps } from './types'; import type { TokenInputProps } from '../form-token-field/types'; import { useDeprecated36pxDefaultSizeProp } from '../utils/use-deprecated-props'; import { withIgnoreIMEEvents } from '../utils/with-ignore-ime-events'; +import { maybeWarnDeprecated36pxSize } from '../utils/deprecated-36px-size'; const noop = () => {}; @@ -92,6 +93,7 @@ const getIndexOfMatchingSuggestion = ( * const [ filteredOptions, setFilteredOptions ] = useState( options ); * return ( * <ComboboxControl + * __next40pxDefaultSize * __nextHasNoMarginBottom * label="Font Size" * value={ fontSize } @@ -313,6 +315,12 @@ function ComboboxControl( props: ComboboxControlProps ) { } }, [ matchingSuggestions, isExpanded ] ); + maybeWarnDeprecated36pxSize( { + componentName: 'ComboboxControl', + __next40pxDefaultSize, + size: undefined, + } ); + // Disable reason: There is no appropriate role which describes the // input container intended accessible usability. // TODO: Refactor click detection to use blur to stop propagation. diff --git a/packages/components/src/combobox-control/stories/index.story.tsx b/packages/components/src/combobox-control/stories/index.story.tsx index 954f0d96fb0d76..1b4972f167f745 100644 --- a/packages/components/src/combobox-control/stories/index.story.tsx +++ b/packages/components/src/combobox-control/stories/index.story.tsx @@ -77,6 +77,7 @@ const Template: StoryFn< typeof ComboboxControl > = ( { }; export const Default = Template.bind( {} ); Default.args = { + __next40pxDefaultSize: true, __nextHasNoMarginBottom: true, allowReset: false, label: 'Select a country', diff --git a/packages/components/src/combobox-control/test/index.tsx b/packages/components/src/combobox-control/test/index.tsx index 639407ac998ed2..8f569ed381a844 100644 --- a/packages/components/src/combobox-control/test/index.tsx +++ b/packages/components/src/combobox-control/test/index.tsx @@ -58,7 +58,13 @@ const getOptionSearchString = ( option: ComboboxControlOption ) => option.label.substring( 0, 11 ); const ComboboxControl = ( props: ComboboxControlProps ) => { - return <_ComboboxControl { ...props } __nextHasNoMarginBottom />; + return ( + <_ComboboxControl + { ...props } + __next40pxDefaultSize + __nextHasNoMarginBottom + /> + ); }; const ControlledComboboxControl = ( { From 0587619ce3af9beb00087098514562000fe5d27f Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 20 Nov 2024 10:37:47 +1000 Subject: [PATCH 1635/1908] Heading: Hide border controls by default (#67105) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-library/src/heading/block.json | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/block-library/src/heading/block.json b/packages/block-library/src/heading/block.json index 2276bcbbb50172..2869ee85c55206 100644 --- a/packages/block-library/src/heading/block.json +++ b/packages/block-library/src/heading/block.json @@ -37,13 +37,7 @@ "color": true, "radius": true, "style": true, - "width": true, - "__experimentalDefaultControls": { - "color": true, - "radius": true, - "style": true, - "width": true - } + "width": true }, "color": { "gradients": true, From 9f0e2d3c1a55f5f6af8962bb8cc63f4db7a6d70c Mon Sep 17 00:00:00 2001 From: VATALIYA PARTH <88878890+PARTHVATALIYA@users.noreply.github.com> Date: Wed, 20 Nov 2024 06:32:41 +0530 Subject: [PATCH 1636/1908] FontSizePicker : Deprecate 36px default size (#66920) * Add the console warning for 36px size variation * Add the changelog for the deprecation * Update: changelog and test for all tests need to pass --------- Co-authored-by: PARTHVATALIYA <parthvataliya@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 3 ++- packages/components/src/font-size-picker/README.md | 1 + packages/components/src/font-size-picker/index.tsx | 7 +++++++ .../src/font-size-picker/stories/index.story.tsx | 1 + packages/components/src/font-size-picker/test/index.tsx | 6 +++++- 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 927b1a12cee4c3..b23d024a724dd1 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,8 @@ - `DimensionControl`: Deprecate 36px default size ([#66705](https://github.com/WordPress/gutenberg/pull/66705)). - `TextControl`: Deprecate 36px default size ([#66745](https://github.com/WordPress/gutenberg/pull/66745). +- `FontSizePicker`: Deprecate 36px default size ([#66920](https://github.com/WordPress/gutenberg/pull/66920)). +- `ComboboxControl`: Deprecate 36px default size ([#66900](https://github.com/WordPress/gutenberg/pull/66900)). ### Bug Fixes @@ -30,7 +32,6 @@ ### Deprecations - `Radio`: Deprecate 36px default size ([#66572](https://github.com/WordPress/gutenberg/pull/66572)). -- `ComboboxControl`: Deprecate 36px default size ([#66900](https://github.com/WordPress/gutenberg/pull/66900)). ### Bug Fixes diff --git a/packages/components/src/font-size-picker/README.md b/packages/components/src/font-size-picker/README.md index 5d7fe2b39a7373..39d916c0c7b212 100644 --- a/packages/components/src/font-size-picker/README.md +++ b/packages/components/src/font-size-picker/README.md @@ -29,6 +29,7 @@ const MyFontSizePicker = () => { return ( <FontSizePicker + __next40pxDefaultSize fontSizes={ fontSizes } value={ fontSize } fallbackFontSize={ fallbackFontSize } diff --git a/packages/components/src/font-size-picker/index.tsx b/packages/components/src/font-size-picker/index.tsx index f93a09440a0688..d4e8ea29fc6c4f 100644 --- a/packages/components/src/font-size-picker/index.tsx +++ b/packages/components/src/font-size-picker/index.tsx @@ -35,6 +35,7 @@ import { Spacer } from '../spacer'; import FontSizePickerSelect from './font-size-picker-select'; import FontSizePickerToggleGroup from './font-size-picker-toggle-group'; import { T_SHIRT_NAMES } from './constants'; +import { maybeWarnDeprecated36pxSize } from '../utils/deprecated-36px-size'; const DEFAULT_UNITS = [ 'px', 'em', 'rem', 'vw', 'vh' ]; @@ -123,6 +124,12 @@ const UnforwardedFontSizePicker = ( !! valueUnit && [ 'em', 'rem', 'vw', 'vh' ].includes( valueUnit ); const isDisabled = value === undefined; + maybeWarnDeprecated36pxSize( { + componentName: 'FontSizePicker', + __next40pxDefaultSize, + size, + } ); + return ( <Container ref={ ref } className="components-font-size-picker"> <VisuallyHidden as="legend">{ __( 'Font size' ) }</VisuallyHidden> diff --git a/packages/components/src/font-size-picker/stories/index.story.tsx b/packages/components/src/font-size-picker/stories/index.story.tsx index eec8f5173d9655..a0d83756ca1ec9 100644 --- a/packages/components/src/font-size-picker/stories/index.story.tsx +++ b/packages/components/src/font-size-picker/stories/index.story.tsx @@ -66,6 +66,7 @@ const TwoFontSizePickersWithState: StoryFn< typeof FontSizePicker > = ( { export const Default: StoryFn< typeof FontSizePicker > = FontSizePickerWithState.bind( {} ); Default.args = { + __next40pxDefaultSize: true, disableCustomFontSizes: false, fontSizes: [ { diff --git a/packages/components/src/font-size-picker/test/index.tsx b/packages/components/src/font-size-picker/test/index.tsx index e7205e57eefaa6..34e8ce17c67fa6 100644 --- a/packages/components/src/font-size-picker/test/index.tsx +++ b/packages/components/src/font-size-picker/test/index.tsx @@ -8,13 +8,17 @@ import { render } from '@ariakit/test/react'; /** * Internal dependencies */ -import FontSizePicker from '../'; +import _FontSizePicker from '../'; import type { FontSize } from '../types'; /** * WordPress dependencies */ import { useState } from '@wordpress/element'; +const FontSizePicker = ( + props: React.ComponentProps< typeof _FontSizePicker > +) => <_FontSizePicker __next40pxDefaultSize { ...props } />; + const ControlledFontSizePicker = ( { onChange, ...props From 0db7ff64bb9263ebffa23efb0e3c5aae5668ebbe Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:52:13 +1100 Subject: [PATCH 1637/1908] Style book: remove styles from examples (#67098) * Remove group block example styles because they prevent global styles from being previewed * In the stylebook, remove styles from the block examples. This is so global styles will take effect. * Add explanatory comments * Hoist cover block example styles typography/color Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: westnz <west7@git.wordpress.org> --- packages/block-library/src/cover/index.js | 16 ++++++------ .../src/components/style-book/examples.tsx | 26 +++++++++++++++++-- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/packages/block-library/src/cover/index.js b/packages/block-library/src/cover/index.js index e6797a3b51dbe4..b5de174f708085 100644 --- a/packages/block-library/src/cover/index.js +++ b/packages/block-library/src/cover/index.js @@ -26,6 +26,14 @@ export const settings = { customOverlayColor: '#065174', dimRatio: 40, url: 'https://s.w.org/images/core/5.3/Windbuchencom.jpg', + style: { + typography: { + fontSize: 48, + }, + color: { + text: 'white', + }, + }, }, innerBlocks: [ { @@ -33,14 +41,6 @@ export const settings = { attributes: { content: __( '<strong>Snow Patrol</strong>' ), align: 'center', - style: { - typography: { - fontSize: 48, - }, - color: { - text: 'white', - }, - }, }, }, ], diff --git a/packages/edit-site/src/components/style-book/examples.tsx b/packages/edit-site/src/components/style-book/examples.tsx index 2fefe227ca52b7..c944b87b09d7e1 100644 --- a/packages/edit-site/src/components/style-book/examples.tsx +++ b/packages/edit-site/src/components/style-book/examples.tsx @@ -150,7 +150,18 @@ function getOverviewBlockExamples( name: blockName, title: blockType.title, category: 'overview', - blocks: getBlockFromExample( blockName, blockType.example ), + /* + * CSS generated from style attributes will take precedence over global styles CSS, + * so remove the style attribute from the example to ensure the example + * demonstrates changes to global styles. + */ + blocks: getBlockFromExample( blockName, { + ...blockType.example, + attributes: { + ...blockType.example.attributes, + style: undefined, + }, + } ), }; examples.push( blockExample ); } @@ -179,7 +190,18 @@ export function getExamples( colors: MultiOriginPalettes ): BlockExample[] { name: blockType.name, title: blockType.title, category: blockType.category, - blocks: getBlockFromExample( blockType.name, blockType.example ), + /* + * CSS generated from style attributes will take precedence over global styles CSS, + * so remove the style attribute from the example to ensure the example + * demonstrates changes to global styles. + */ + blocks: getBlockFromExample( blockType.name, { + ...blockType.example, + attributes: { + ...blockType.example.attributes, + style: undefined, + }, + } ), } ) ); const isHeadingBlockRegistered = !! getBlockType( 'core/heading' ); From 7d8dee1c6106a0bdbe9b76892d023794b286f4c9 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:57:09 +1000 Subject: [PATCH 1638/1908] Block Style Variations: Fix complex variation selectors when using selectors API (#67061) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: yogeshbhutkar <yogeshbhutkar@git.wordpress.org> Co-authored-by: Anuj-Rathore24 <anujrathore24@git.wordpress.org> Co-authored-by: shimotmk <shimotomoki@git.wordpress.org> --- backport-changelog/6.8/7825.md | 3 ++ lib/class-wp-theme-json-gutenberg.php | 10 +++- phpunit/class-wp-theme-json-test.php | 68 +++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 backport-changelog/6.8/7825.md diff --git a/backport-changelog/6.8/7825.md b/backport-changelog/6.8/7825.md new file mode 100644 index 00000000000000..42d09c86b7f3ba --- /dev/null +++ b/backport-changelog/6.8/7825.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7825 + +* https://github.com/WordPress/gutenberg/pull/67061 diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 10f80c3f3cdb7b..47301e4463e363 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2874,8 +2874,14 @@ public function get_styles_for_block( $block_metadata ) { // Combine selectors with style variation's selector and add to overall style variation declarations. foreach ( $variation_declarations as $current_selector => $new_declarations ) { - // If current selector includes block classname, remove it but leave the whitespace in. - $shortened_selector = str_replace( $block_metadata['selector'] . ' ', ' ', $current_selector ); + /* + * Clean up any whitespace between comma separated selectors. + * This prevents these spaces breaking compound selectors such as: + * - `.wp-block-list:not(.wp-block-list .wp-block-list)` + * - `.wp-block-image img, .wp-block-image.my-class img` + */ + $clean_current_selector = preg_replace( '/,\s+/', ',', $current_selector ); + $shortened_selector = str_replace( $block_metadata['selector'], '', $clean_current_selector ); // Prepend the variation selector to the current selector. $split_selectors = explode( ',', $shortened_selector ); diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 1aacb92759e591..c8ca89c7c1f6c7 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -4308,6 +4308,74 @@ public function data_get_styles_for_block_with_style_variations() { ); } + public function test_get_styles_for_block_with_style_variations_and_custom_selectors() { + register_block_type( + 'test/milk', + array( + 'api_version' => 3, + 'selectors' => array( + 'root' => '.milk', + 'color' => '.wp-block-test-milk .liquid, .wp-block-test-milk:not(.spoiled), .wp-block-test-milk.in-bottle', + ), + ) + ); + + register_block_style( + 'test/milk', + array( + 'name' => 'chocolate', + 'label' => 'Chocolate', + ) + ); + + $theme_json = new WP_Theme_JSON_Gutenberg( + array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'blocks' => array( + 'test/milk' => array( + 'color' => array( + 'background' => 'white', + ), + 'variations' => array( + 'chocolate' => array( + 'color' => array( + 'background' => '#35281E', + ), + ), + ), + ), + ), + ), + ) + ); + + $metadata = array( + 'name' => 'test/milk', + 'path' => array( 'styles', 'blocks', 'test/milk' ), + 'selector' => '.wp-block-test-milk', + 'selectors' => array( + 'color' => '.wp-block-test-milk .liquid, .wp-block-test-milk:not(.spoiled), .wp-block-test-milk.in-bottle', + ), + 'variations' => array( + 'chocolate' => array( + 'path' => array( 'styles', 'blocks', 'test/milk', 'variations', 'chocolate' ), + 'selector' => '.is-style-chocolate.wp-block-test-milk', + ), + ), + ); + + $actual_styles = $theme_json->get_styles_for_block( $metadata ); + $default_styles = ':root :where(.wp-block-test-milk .liquid, .wp-block-test-milk:not(.spoiled), .wp-block-test-milk.in-bottle){background-color: white;}'; + $variation_styles = ':root :where(.is-style-chocolate.wp-block-test-milk .liquid,.is-style-chocolate.wp-block-test-milk:not(.spoiled),.is-style-chocolate.wp-block-test-milk.in-bottle){background-color: #35281E;}'; + $expected = $default_styles . $variation_styles; + + unregister_block_style( 'test/milk', 'chocolate' ); + unregister_block_type( 'test/milk' ); + + $this->assertSame( $expected, $actual_styles ); + } + public function test_block_style_variations() { wp_set_current_user( static::$administrator_id ); From b5ee9da93a85290630cca0e29895a8e3e209eed0 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 20 Nov 2024 17:56:18 +1000 Subject: [PATCH 1639/1908] Borders: Stabilize border block supports within block processing (#66918) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: karthick-murugan <karthickmurugan@git.wordpress.org> --- backport-changelog/6.8/7069.md | 1 + lib/block-supports/border.php | 28 +- lib/class-wp-theme-json-gutenberg.php | 8 +- lib/compat/wordpress-6.8/blocks.php | 92 ++++-- .../test/use-global-styles-output.js | 2 +- .../global-styles/use-global-styles-output.js | 2 +- packages/block-editor/src/hooks/border.js | 2 +- packages/block-editor/src/hooks/supports.js | 2 +- packages/blocks/src/api/constants.js | 49 ++-- .../blocks/src/store/process-block-type.js | 84 ++++-- .../src/store/test/process-block-type.js | 273 ++++++++++++++---- phpunit/block-supports/border-test.php | 108 +++++++ 12 files changed, 510 insertions(+), 141 deletions(-) diff --git a/backport-changelog/6.8/7069.md b/backport-changelog/6.8/7069.md index ea3c717ec3c93a..8b4ad69db02e75 100644 --- a/backport-changelog/6.8/7069.md +++ b/backport-changelog/6.8/7069.md @@ -1,3 +1,4 @@ https://github.com/WordPress/wordpress-develop/pull/7069 * https://github.com/WordPress/gutenberg/pull/63401 +* https://github.com/WordPress/gutenberg/pull/66918 diff --git a/lib/block-supports/border.php b/lib/block-supports/border.php index bd4c772675a5ed..f890ed84566b7f 100644 --- a/lib/block-supports/border.php +++ b/lib/block-supports/border.php @@ -17,7 +17,7 @@ function gutenberg_register_border_support( $block_type ) { $block_type->attributes = array(); } - if ( block_has_support( $block_type, array( '__experimentalBorder' ) ) && ! array_key_exists( 'style', $block_type->attributes ) ) { + if ( block_has_support( $block_type, array( 'border' ) ) && ! array_key_exists( 'style', $block_type->attributes ) ) { $block_type->attributes['style'] = array( 'type' => 'object', ); @@ -52,7 +52,7 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) { if ( gutenberg_has_border_feature_support( $block_type, 'radius' ) && isset( $block_attributes['style']['border']['radius'] ) && - ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'radius' ) + ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'radius' ) ) { $border_radius = $block_attributes['style']['border']['radius']; @@ -67,7 +67,7 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) { if ( gutenberg_has_border_feature_support( $block_type, 'style' ) && isset( $block_attributes['style']['border']['style'] ) && - ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' ) + ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'style' ) ) { $border_block_styles['style'] = $block_attributes['style']['border']['style']; } @@ -76,7 +76,7 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) { if ( $has_border_width_support && isset( $block_attributes['style']['border']['width'] ) && - ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' ) + ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'width' ) ) { $border_width = $block_attributes['style']['border']['width']; @@ -91,7 +91,7 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) { // Border color. if ( $has_border_color_support && - ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' ) + ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'color' ) ) { $preset_border_color = array_key_exists( 'borderColor', $block_attributes ) ? "var:preset|color|{$block_attributes['borderColor']}" : null; $custom_border_color = $block_attributes['style']['border']['color'] ?? null; @@ -103,9 +103,9 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) { foreach ( array( 'top', 'right', 'bottom', 'left' ) as $side ) { $border = $block_attributes['style']['border'][ $side ] ?? null; $border_side_values = array( - 'width' => isset( $border['width'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' ) ? $border['width'] : null, - 'color' => isset( $border['color'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' ) ? $border['color'] : null, - 'style' => isset( $border['style'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' ) ? $border['style'] : null, + 'width' => isset( $border['width'] ) && ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'width' ) ? $border['width'] : null, + 'color' => isset( $border['color'] ) && ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'color' ) ? $border['color'] : null, + 'style' => isset( $border['style'] ) && ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'style' ) ? $border['style'] : null, ); $border_block_styles[ $side ] = $border_side_values; } @@ -129,9 +129,9 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) { /** * Checks whether the current block type supports the border feature requested. * - * If the `__experimentalBorder` support flag is a boolean `true` all border + * If the `border` support flag is a boolean `true` all border * support features are available. Otherwise, the specific feature's support - * flag nested under `experimentalBorder` must be enabled for the feature + * flag nested under `border` must be enabled for the feature * to be opted into. * * @param WP_Block_Type $block_type Block type to check for support. @@ -141,17 +141,17 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) { * @return boolean Whether or not the feature is supported. */ function gutenberg_has_border_feature_support( $block_type, $feature, $default_value = false ) { - // Check if all border support features have been opted into via `"__experimentalBorder": true`. + // Check if all border support features have been opted into via `"border": true`. if ( $block_type instanceof WP_Block_Type ) { - $block_type_supports_border = $block_type->supports['__experimentalBorder'] ?? $default_value; + $block_type_supports_border = $block_type->supports['border'] ?? $default_value; if ( true === $block_type_supports_border ) { return true; } } // Check if the specific feature has been opted into individually - // via nested flag under `__experimentalBorder`. - return block_has_support( $block_type, array( '__experimentalBorder', $feature ), $default_value ); + // via nested flag under `border`. + return block_has_support( $block_type, array( 'border', $feature ), $default_value ); } // Register the block support. diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 47301e4463e363..083ce3516b71af 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -615,10 +615,10 @@ class WP_Theme_JSON_Gutenberg { * @var string[] */ const BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS = array( - '__experimentalBorder' => 'border', - 'color' => 'color', - 'spacing' => 'spacing', - 'typography' => 'typography', + 'border' => 'border', + 'color' => 'color', + 'spacing' => 'spacing', + 'typography' => 'typography', ); /** diff --git a/lib/compat/wordpress-6.8/blocks.php b/lib/compat/wordpress-6.8/blocks.php index 3124dd2a12a615..0b7031403b1918 100644 --- a/lib/compat/wordpress-6.8/blocks.php +++ b/lib/compat/wordpress-6.8/blocks.php @@ -6,40 +6,94 @@ */ /** - * Filters the block type arguments during registration to stabilize experimental block supports. + * Filters the block type arguments during registration to stabilize + * experimental block supports. * - * This is a temporary compatibility shim as the approach in core is for this to be handled - * within the WP_Block_Type class rather than requiring a filter. + * This is a temporary compatibility shim as the approach in core is for this + * to be handled within the WP_Block_Type class rather than requiring a filter. * * @param array $args Array of arguments for registering a block type. * @return array Array of arguments for registering a block type. */ function gutenberg_stabilize_experimental_block_supports( $args ) { - if ( empty( $args['supports']['typography'] ) ) { + if ( empty( $args['supports'] ) ) { return $args; } - $experimental_typography_supports_to_stable = array( - '__experimentalFontFamily' => 'fontFamily', - '__experimentalFontStyle' => 'fontStyle', - '__experimentalFontWeight' => 'fontWeight', - '__experimentalLetterSpacing' => 'letterSpacing', - '__experimentalTextDecoration' => 'textDecoration', - '__experimentalTextTransform' => 'textTransform', + $experimental_to_stable_keys = array( + 'typography' => array( + '__experimentalFontFamily' => 'fontFamily', + '__experimentalFontStyle' => 'fontStyle', + '__experimentalFontWeight' => 'fontWeight', + '__experimentalLetterSpacing' => 'letterSpacing', + '__experimentalTextDecoration' => 'textDecoration', + '__experimentalTextTransform' => 'textTransform', + ), + '__experimentalBorder' => 'border', ); - $current_typography_supports = $args['supports']['typography']; - $stable_typography_supports = array(); + $updated_supports = array(); + foreach ( $args['supports'] as $support => $config ) { + // Add the support's config as is when it's not in need of stabilization. + if ( empty( $experimental_to_stable_keys[ $support ] ) ) { + $updated_supports[ $support ] = $config; + continue; + } + + // Stabilize the support's key if needed e.g. __experimentalBorder => border. + if ( is_string( $experimental_to_stable_keys[ $support ] ) ) { + $stabilized_key = $experimental_to_stable_keys[ $support ]; + + // If there is no stabilized key present, use the experimental config as is. + if ( ! array_key_exists( $stabilized_key, $args['supports'] ) ) { + $updated_supports[ $stabilized_key ] = $config; + continue; + } + + /* + * Determine the order of keys, so the last defined can be preferred. + * + * The reason for preferring the last defined key is that after filters + * are applied, the last inserted key is likely the most up-to-date value. + * We cannot determine with certainty which value was "last modified" so + * the insertion order is the best guess. The extreme edge case of multiple + * filters tweaking the same support property will become less over time as + * extenders migrate existing blocks and plugins to stable keys. + */ + $key_positions = array_flip( array_keys( $args['supports'] ) ); + $experimental_index = $key_positions[ $support ] ?? -1; + $stabilized_index = $key_positions[ $stabilized_key ] ?? -1; + $experimental_first = $experimental_index < $stabilized_index; + + // Update support config, prefer the last defined value. + if ( is_array( $config ) ) { + $updated_supports[ $stabilized_key ] = $experimental_first + ? array_merge( $config, $args['supports'][ $stabilized_key ] ) + : array_merge( $args['supports'][ $stabilized_key ], $config ); + } else { + $updated_supports[ $stabilized_key ] = $experimental_first + ? $args['supports'][ $stabilized_key ] + : $config; + } + + continue; + } - foreach ( $current_typography_supports as $key => $value ) { - if ( array_key_exists( $key, $experimental_typography_supports_to_stable ) ) { - $stable_typography_supports[ $experimental_typography_supports_to_stable[ $key ] ] = $value; - } else { - $stable_typography_supports[ $key ] = $value; + // Stabilize individual support feature keys e.g. __experimentalFontFamily => fontFamily. + if ( is_array( $experimental_to_stable_keys[ $support ] ) ) { + $stable_support_config = array(); + foreach ( $config as $key => $value ) { + if ( array_key_exists( $key, $experimental_to_stable_keys[ $support ] ) ) { + $stable_support_config[ $experimental_to_stable_keys[ $support ][ $key ] ] = $value; + } else { + $stable_support_config[ $key ] = $value; + } + } + $updated_supports[ $support ] = $stable_support_config; } } - $args['supports']['typography'] = $stable_typography_supports; + $args['supports'] = $updated_supports; return $args; } diff --git a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js index 5022e8ba591dbb..93e5cc9afdbb3c 100644 --- a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js @@ -855,7 +855,7 @@ describe( 'global styles renderer', () => { it( 'should return block selectors data with old experimental selectors', () => { const imageSupports = { - __experimentalBorder: { + border: { radius: true, __experimentalSelector: 'img, .crop-area', }, diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index cd4ad0cea50e0d..7bdc95d222142d 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -47,7 +47,7 @@ const ELEMENT_CLASS_NAMES = { // List of block support features that can have their related styles // generated under their own feature level selector rather than the block's. const BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS = { - __experimentalBorder: 'border', + border: 'border', color: 'color', spacing: 'spacing', typography: 'typography', diff --git a/packages/block-editor/src/hooks/border.js b/packages/block-editor/src/hooks/border.js index 4ab4c69a41f311..4500444685befa 100644 --- a/packages/block-editor/src/hooks/border.js +++ b/packages/block-editor/src/hooks/border.js @@ -31,7 +31,7 @@ import { import { store as blockEditorStore } from '../store'; import { __ } from '@wordpress/i18n'; -export const BORDER_SUPPORT_KEY = '__experimentalBorder'; +export const BORDER_SUPPORT_KEY = 'border'; export const SHADOW_SUPPORT_KEY = 'shadow'; const getColorByProperty = ( colors, property, value ) => { diff --git a/packages/block-editor/src/hooks/supports.js b/packages/block-editor/src/hooks/supports.js index c0b6bb2cc8b271..102b78bbb96e68 100644 --- a/packages/block-editor/src/hooks/supports.js +++ b/packages/block-editor/src/hooks/supports.js @@ -6,7 +6,7 @@ import { Platform } from '@wordpress/element'; const ALIGN_SUPPORT_KEY = 'align'; const ALIGN_WIDE_SUPPORT_KEY = 'alignWide'; -const BORDER_SUPPORT_KEY = '__experimentalBorder'; +const BORDER_SUPPORT_KEY = 'border'; const COLOR_SUPPORT_KEY = 'color'; const CUSTOM_CLASS_NAME_SUPPORT_KEY = 'customClassName'; const FONT_FAMILY_SUPPORT_KEY = 'typography.fontFamily'; diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js index 85a359af754db8..8ea32d591adb32 100644 --- a/packages/blocks/src/api/constants.js +++ b/packages/blocks/src/api/constants.js @@ -58,12 +58,12 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = { }, borderColor: { value: [ 'border', 'color' ], - support: [ '__experimentalBorder', 'color' ], + support: [ 'border', 'color' ], useEngine: true, }, borderRadius: { value: [ 'border', 'radius' ], - support: [ '__experimentalBorder', 'radius' ], + support: [ 'border', 'radius' ], properties: { borderTopLeftRadius: 'topLeft', borderTopRightRadius: 'topRight', @@ -74,72 +74,72 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = { }, borderStyle: { value: [ 'border', 'style' ], - support: [ '__experimentalBorder', 'style' ], + support: [ 'border', 'style' ], useEngine: true, }, borderWidth: { value: [ 'border', 'width' ], - support: [ '__experimentalBorder', 'width' ], + support: [ 'border', 'width' ], useEngine: true, }, borderTopColor: { value: [ 'border', 'top', 'color' ], - support: [ '__experimentalBorder', 'color' ], + support: [ 'border', 'color' ], useEngine: true, }, borderTopStyle: { value: [ 'border', 'top', 'style' ], - support: [ '__experimentalBorder', 'style' ], + support: [ 'border', 'style' ], useEngine: true, }, borderTopWidth: { value: [ 'border', 'top', 'width' ], - support: [ '__experimentalBorder', 'width' ], + support: [ 'border', 'width' ], useEngine: true, }, borderRightColor: { value: [ 'border', 'right', 'color' ], - support: [ '__experimentalBorder', 'color' ], + support: [ 'border', 'color' ], useEngine: true, }, borderRightStyle: { value: [ 'border', 'right', 'style' ], - support: [ '__experimentalBorder', 'style' ], + support: [ 'border', 'style' ], useEngine: true, }, borderRightWidth: { value: [ 'border', 'right', 'width' ], - support: [ '__experimentalBorder', 'width' ], + support: [ 'border', 'width' ], useEngine: true, }, borderBottomColor: { value: [ 'border', 'bottom', 'color' ], - support: [ '__experimentalBorder', 'color' ], + support: [ 'border', 'color' ], useEngine: true, }, borderBottomStyle: { value: [ 'border', 'bottom', 'style' ], - support: [ '__experimentalBorder', 'style' ], + support: [ 'border', 'style' ], useEngine: true, }, borderBottomWidth: { value: [ 'border', 'bottom', 'width' ], - support: [ '__experimentalBorder', 'width' ], + support: [ 'border', 'width' ], useEngine: true, }, borderLeftColor: { value: [ 'border', 'left', 'color' ], - support: [ '__experimentalBorder', 'color' ], + support: [ 'border', 'color' ], useEngine: true, }, borderLeftStyle: { value: [ 'border', 'left', 'style' ], - support: [ '__experimentalBorder', 'style' ], + support: [ 'border', 'style' ], useEngine: true, }, borderLeftWidth: { value: [ 'border', 'left', 'width' ], - support: [ '__experimentalBorder', 'width' ], + support: [ 'border', 'width' ], useEngine: true, }, color: { @@ -298,11 +298,14 @@ export const __EXPERIMENTAL_PATHS_WITH_OVERRIDE = { 'spacing.spacingSizes': true, }; -export const TYPOGRAPHY_SUPPORTS_EXPERIMENTAL_TO_STABLE = { - __experimentalFontFamily: 'fontFamily', - __experimentalFontStyle: 'fontStyle', - __experimentalFontWeight: 'fontWeight', - __experimentalLetterSpacing: 'letterSpacing', - __experimentalTextDecoration: 'textDecoration', - __experimentalTextTransform: 'textTransform', +export const EXPERIMENTAL_TO_STABLE_KEYS = { + typography: { + __experimentalFontFamily: 'fontFamily', + __experimentalFontStyle: 'fontStyle', + __experimentalFontWeight: 'fontWeight', + __experimentalLetterSpacing: 'letterSpacing', + __experimentalTextDecoration: 'textDecoration', + __experimentalTextTransform: 'textTransform', + }, + __experimentalBorder: 'border', }; diff --git a/packages/blocks/src/store/process-block-type.js b/packages/blocks/src/store/process-block-type.js index 98fb044f8faadf..bd7e5ab43800f0 100644 --- a/packages/blocks/src/store/process-block-type.js +++ b/packages/blocks/src/store/process-block-type.js @@ -18,7 +18,7 @@ import { isValidIcon, normalizeIconObject, omit } from '../api/utils'; import { BLOCK_ICON_DEFAULT, DEPRECATED_ENTRY_KEYS, - TYPOGRAPHY_SUPPORTS_EXPERIMENTAL_TO_STABLE, + EXPERIMENTAL_TO_STABLE_KEYS, } from '../api/constants'; /** @typedef {import('../api/registration').WPBlockType} WPBlockType */ @@ -75,24 +75,72 @@ function stabilizeSupports( rawSupports ) { // custom block plugins that rely on immutable supports are not affected. // See: https://github.com/WordPress/gutenberg/pull/66849#issuecomment-2463614281 const newSupports = {}; - for ( const [ key, value ] of Object.entries( rawSupports ) ) { - if ( - key === 'typography' && - typeof value === 'object' && - value !== null - ) { - newSupports.typography = Object.fromEntries( - Object.entries( value ).map( - ( [ typographyKey, typographyValue ] ) => [ - TYPOGRAPHY_SUPPORTS_EXPERIMENTAL_TO_STABLE[ - typographyKey - ] || typographyKey, - typographyValue, - ] - ) + + for ( const [ support, config ] of Object.entries( rawSupports ) ) { + // Add the support's config as is when it's not in need of stabilization. + if ( ! EXPERIMENTAL_TO_STABLE_KEYS[ support ] ) { + newSupports[ support ] = config; + continue; + } + + // Stabilize the support's key if needed e.g. __experimentalBorder => border. + if ( typeof EXPERIMENTAL_TO_STABLE_KEYS[ support ] === 'string' ) { + const stabilizedKey = EXPERIMENTAL_TO_STABLE_KEYS[ support ]; + + // If there is no stabilized key present, use the experimental config as is. + if ( ! Object.hasOwn( rawSupports, stabilizedKey ) ) { + newSupports[ stabilizedKey ] = config; + continue; + } + + /* + * Determine the order of keys, so the last defined can be preferred. + * + * The reason for preferring the last defined key is that after filters + * are applied, the last inserted key is likely the most up-to-date value. + * We cannot determine with certainty which value was "last modified" so + * the insertion order is the best guess. The extreme edge case of multiple + * filters tweaking the same support property will become less over time as + * extenders migrate existing blocks and plugins to stable keys. + */ + const entries = Object.entries( rawSupports ); + const experimentalIndex = entries.findIndex( + ( [ key ] ) => key === support ); - } else { - newSupports[ key ] = value; + const stabilizedIndex = entries.findIndex( + ( [ key ] ) => key === stabilizedKey + ); + + // Update support config, prefer the last defined value. + if ( typeof config === 'object' && config !== null ) { + newSupports[ stabilizedKey ] = + experimentalIndex < stabilizedIndex + ? { ...config, ...rawSupports[ stabilizedKey ] } + : { ...rawSupports[ stabilizedKey ], ...config }; + } else { + newSupports[ stabilizedKey ] = + experimentalIndex < stabilizedIndex + ? rawSupports[ stabilizedKey ] + : config; + } + continue; + } + + // Stabilize individual support feature keys + // e.g. __experimentalFontFamily => fontFamily. + const featureStabilizationRequired = + typeof EXPERIMENTAL_TO_STABLE_KEYS[ support ] === 'object' && + EXPERIMENTAL_TO_STABLE_KEYS[ support ] !== null; + const hasConfig = typeof config === 'object' && config !== null; + + if ( featureStabilizationRequired && hasConfig ) { + const stableConfig = {}; + for ( const [ key, value ] of Object.entries( config ) ) { + const stableKey = + EXPERIMENTAL_TO_STABLE_KEYS[ support ][ key ] || key; + stableConfig[ stableKey ] = value; + } + newSupports[ support ] = stableConfig; } } diff --git a/packages/blocks/src/store/test/process-block-type.js b/packages/blocks/src/store/test/process-block-type.js index c82d08cc45d651..c7f487a95301d0 100644 --- a/packages/blocks/src/store/test/process-block-type.js +++ b/packages/blocks/src/store/test/process-block-type.js @@ -26,7 +26,7 @@ describe( 'processBlockType', () => { removeFilter( 'blocks.registerBlockType', 'test/filterSupports' ); } ); - it( 'should return the block type with stabilized typography supports', () => { + it( 'should return the block type with stabilized supports', () => { const blockSettings = { ...baseBlockSettings, supports: { @@ -46,6 +46,18 @@ describe( 'processBlockType', () => { textTransform: true, }, }, + __experimentalBorder: { + color: true, + radius: true, + style: true, + width: true, + __experimentalDefaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, + }, }, }; @@ -54,25 +66,39 @@ describe( 'processBlockType', () => { blockSettings )( { select } ); - expect( processedBlockType.supports.typography ).toEqual( { - fontSize: true, - lineHeight: true, - fontFamily: true, - fontStyle: true, - fontWeight: true, - letterSpacing: true, - textTransform: true, - textDecoration: true, - __experimentalWritingMode: true, - __experimentalDefaultControls: { + expect( processedBlockType.supports ).toEqual( { + typography: { fontSize: true, - fontAppearance: true, + lineHeight: true, + fontFamily: true, + fontStyle: true, + fontWeight: true, + letterSpacing: true, textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + __experimentalDefaultControls: { + fontSize: true, + fontAppearance: true, + textTransform: true, + }, + }, + border: { + color: true, + radius: true, + style: true, + width: true, + __experimentalDefaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, }, } ); } ); - it( 'should return the block type with stable typography supports', () => { + it( 'should return the block type with stable supports', () => { const blockSettings = { ...baseBlockSettings, supports: { @@ -92,6 +118,18 @@ describe( 'processBlockType', () => { textTransform: true, }, }, + __experimentalBorder: { + color: true, + radius: true, + style: true, + width: true, + __experimentalDefaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, + }, }, }; @@ -100,20 +138,34 @@ describe( 'processBlockType', () => { blockSettings )( { select } ); - expect( processedBlockType.supports.typography ).toEqual( { - fontSize: true, - lineHeight: true, - fontFamily: true, - fontStyle: true, - fontWeight: true, - letterSpacing: true, - textTransform: true, - textDecoration: true, - __experimentalWritingMode: true, - __experimentalDefaultControls: { + expect( processedBlockType.supports ).toEqual( { + typography: { fontSize: true, - fontAppearance: true, + lineHeight: true, + fontFamily: true, + fontStyle: true, + fontWeight: true, + letterSpacing: true, textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + __experimentalDefaultControls: { + fontSize: true, + fontAppearance: true, + textTransform: true, + }, + }, + border: { + color: true, + radius: true, + style: true, + width: true, + __experimentalDefaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, }, } ); } ); @@ -138,6 +190,18 @@ describe( 'processBlockType', () => { textTransform: true, }, }, + __experimentalBorder: { + color: true, + radius: true, + style: true, + width: true, + __experimentalDefaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, + }, }, }; @@ -149,6 +213,10 @@ describe( 'processBlockType', () => { settings.supports.typography.__experimentalFontFamily = false; settings.supports.typography.__experimentalFontStyle = false; settings.supports.typography.__experimentalFontWeight = false; + if ( ! settings.supports.__experimentalBorder ) { + settings.supports.__experimentalBorder = {}; + } + settings.supports.__experimentalBorder.radius = false; } return settings; } @@ -159,25 +227,39 @@ describe( 'processBlockType', () => { blockSettings )( { select } ); - expect( processedBlockType.supports.typography ).toEqual( { - fontSize: true, - lineHeight: true, - fontFamily: false, - fontStyle: false, - fontWeight: false, - letterSpacing: true, - textTransform: true, - textDecoration: true, - __experimentalWritingMode: true, - __experimentalDefaultControls: { + expect( processedBlockType.supports ).toEqual( { + typography: { fontSize: true, - fontAppearance: true, + lineHeight: true, + fontFamily: false, + fontStyle: false, + fontWeight: false, + letterSpacing: true, textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + __experimentalDefaultControls: { + fontSize: true, + fontAppearance: true, + textTransform: true, + }, + }, + border: { + color: true, + radius: false, + style: true, + width: true, + __experimentalDefaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, }, } ); } ); - it( 'should stabilize experimental typography supports within block deprecations', () => { + it( 'should stabilize experimental supports within block deprecations', () => { const blockSettings = { ...baseBlockSettings, supports: { @@ -197,6 +279,18 @@ describe( 'processBlockType', () => { textTransform: true, }, }, + border: { + color: true, + radius: true, + style: true, + width: true, + __experimentalDefaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, + }, }, deprecated: [ { @@ -210,6 +304,18 @@ describe( 'processBlockType', () => { __experimentalTextDecoration: true, __experimentalWritingMode: true, }, + __experimentalBorder: { + color: true, + radius: true, + style: true, + width: true, + __experimentalDefaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, + }, }, }, ], @@ -226,16 +332,28 @@ describe( 'processBlockType', () => { blockSettings )( { select } ); - expect( - processedBlockType.deprecated[ 0 ].supports.typography - ).toEqual( { - fontFamily: true, - fontStyle: true, - fontWeight: true, - letterSpacing: true, - textTransform: true, - textDecoration: true, - __experimentalWritingMode: true, + expect( processedBlockType.deprecated[ 0 ].supports ).toEqual( { + typography: { + fontFamily: true, + fontStyle: true, + fontWeight: true, + letterSpacing: true, + textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + }, + border: { + color: true, + radius: true, + style: true, + width: true, + __experimentalDefaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, + }, } ); } ); @@ -259,6 +377,18 @@ describe( 'processBlockType', () => { textTransform: true, }, }, + border: { + color: true, + radius: true, + style: true, + width: true, + __experimentalDefaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, + }, }, deprecated: [ { @@ -272,6 +402,18 @@ describe( 'processBlockType', () => { __experimentalTextDecoration: true, __experimentalWritingMode: true, }, + __experimentalBorder: { + color: true, + radius: true, + style: true, + width: true, + __experimentalDefaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, + }, }, }, ], @@ -285,6 +427,7 @@ describe( 'processBlockType', () => { settings.supports.typography.__experimentalFontFamily = false; settings.supports.typography.__experimentalFontStyle = false; settings.supports.typography.__experimentalFontWeight = false; + settings.supports.__experimentalBorder = { radius: false }; } return settings; } @@ -295,16 +438,28 @@ describe( 'processBlockType', () => { blockSettings )( { select } ); - expect( - processedBlockType.deprecated[ 0 ].supports.typography - ).toEqual( { - fontFamily: false, - fontStyle: false, - fontWeight: false, - letterSpacing: true, - textTransform: true, - textDecoration: true, - __experimentalWritingMode: true, + expect( processedBlockType.deprecated[ 0 ].supports ).toEqual( { + typography: { + fontFamily: false, + fontStyle: false, + fontWeight: false, + letterSpacing: true, + textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + }, + border: { + color: true, + radius: false, + style: true, + width: true, + __experimentalDefaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, + }, } ); } ); } ); diff --git a/phpunit/block-supports/border-test.php b/phpunit/block-supports/border-test.php index 858e4e92cc1740..0c320f24ebe4f2 100644 --- a/phpunit/block-supports/border-test.php +++ b/phpunit/block-supports/border-test.php @@ -457,6 +457,114 @@ public function test_split_borders_with_named_colors() { 'style' => 'border-top-width:2px;border-top-color:var(--wp--preset--color--red);border-top-style:dashed;border-right-width:0.25rem;border-right-color:var(--wp--preset--color--green);border-right-style:dotted;border-bottom-width:0.5em;border-bottom-color:var(--wp--preset--color--blue);border-bottom-style:solid;border-left-width:1px;border-left-color:var(--wp--preset--color--yellow);border-left-style:solid;', ); + $this->assertSame( $expected, $actual ); + } + /** + * Tests that stabilized border supports will also apply to blocks using + * the experimental syntax, for backwards compatibility with existing blocks. + * + * @covers ::gutenberg_apply_border_support + */ + public function test_should_apply_experimental_border_supports() { + $this->test_block_name = 'test/experimental-border-supports'; + register_block_type( + $this->test_block_name, + array( + 'api_version' => 3, + 'attributes' => array( + 'style' => array( + 'type' => 'object', + ), + ), + 'supports' => array( + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + ), + ), + ), + ) + ); + $registry = WP_Block_Type_Registry::get_instance(); + $block_type = $registry->get_registered( $this->test_block_name ); + $block_atts = array( + 'style' => array( + 'border' => array( + 'color' => '#72aee6', + 'radius' => '10px', + 'style' => 'dashed', + 'width' => '2px', + ), + ), + ); + + $actual = gutenberg_apply_border_support( $block_type, $block_atts ); + $expected = array( + 'class' => 'has-border-color', + 'style' => 'border-color:#72aee6;border-radius:10px;border-style:dashed;border-width:2px;', + ); + + $this->assertSame( $expected, $actual ); + } + + /** + * Tests that stabilized border supports are applied correctly. + * + * @covers ::gutenberg_apply_border_support + */ + public function test_should_apply_stabilized_border_supports() { + $this->test_block_name = 'test/stabilized-border-supports'; + register_block_type( + $this->test_block_name, + array( + 'api_version' => 3, + 'attributes' => array( + 'style' => array( + 'type' => 'object', + ), + ), + 'supports' => array( + 'border' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + ), + ), + ), + ) + ); + $registry = WP_Block_Type_Registry::get_instance(); + $block_type = $registry->get_registered( $this->test_block_name ); + $block_atts = array( + 'style' => array( + 'border' => array( + 'color' => '#72aee6', + 'radius' => '10px', + 'style' => 'dashed', + 'width' => '2px', + ), + ), + ); + + $actual = gutenberg_apply_border_support( $block_type, $block_atts ); + $expected = array( + 'class' => 'has-border-color', + 'style' => 'border-color:#72aee6;border-radius:10px;border-style:dashed;border-width:2px;', + ); + $this->assertSame( $expected, $actual ); } } From 6cd6b00ff606511cf29433e32a0bcbf674adda2a Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Wed, 20 Nov 2024 10:43:28 +0200 Subject: [PATCH 1640/1908] Global Styles: Remove styles from blocks' previews (#67144) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../global-styles/block-preview-panel.js | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/block-preview-panel.js b/packages/edit-site/src/components/global-styles/block-preview-panel.js index 6b1b980377c9cb..b796ec6e0cb964 100644 --- a/packages/edit-site/src/components/global-styles/block-preview-panel.js +++ b/packages/edit-site/src/components/global-styles/block-preview-panel.js @@ -18,16 +18,16 @@ const BlockPreviewPanel = ( { name, variation = '' } ) => { return null; } - let example = blockExample; - if ( variation ) { - example = { - ...example, - attributes: { - ...example.attributes, - className: getVariationClassName( variation ), - }, - }; - } + const example = { + ...blockExample, + attributes: { + ...blockExample.attributes, + style: undefined, + className: variation + ? getVariationClassName( variation ) + : blockExample.attributes?.className, + }, + }; return getBlockFromExample( name, example ); }, [ name, blockExample, variation ] ); From b08c77485141d22425bdc2b4011dadbe3ec3a3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20W=C3=BCnsch?= <soerenwrede@gmail.com> Date: Wed, 20 Nov 2024 10:21:21 +0100 Subject: [PATCH 1641/1908] Pattern: Remove Backward compatibility code for WordPress < 6.4. (#67131) --- packages/block-library/src/pattern/index.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/block-library/src/pattern/index.php b/packages/block-library/src/pattern/index.php index 5595818a2271b7..870313eb5e86d8 100644 --- a/packages/block-library/src/pattern/index.php +++ b/packages/block-library/src/pattern/index.php @@ -58,13 +58,6 @@ function render_block_core_pattern( $attributes ) { $pattern = $registry->get_registered( $slug ); $content = $pattern['content']; - // Backward compatibility for handling Block Hooks and injecting the theme attribute in the Gutenberg plugin. - // This can be removed when the minimum supported WordPress is >= 6.4. - if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN && ! function_exists( 'traverse_and_serialize_blocks' ) ) { - $blocks = parse_blocks( $content ); - $content = gutenberg_serialize_blocks( $blocks ); - } - $seen_refs[ $attributes['slug'] ] = true; $content = do_blocks( $content ); From 41f5eb2086a648769c7dae9036faa403fa8ca58b Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Wed, 20 Nov 2024 10:45:15 +0100 Subject: [PATCH 1642/1908] Improve accessibility of the video track editor (#66832) * Do not wrap the track editor form within a navigable menu. * Improve focus management. * Make sure to reset the edit track UI. * Move informative paragraph out of menu. * Remove unnecessary fragment. * Improve submit button labeling, position and variant. * Remove unnecessary space and improve translators comment. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/block-library/src/video/editor.scss | 9 + .../block-library/src/video/tracks-editor.js | 296 ++++++++++-------- 2 files changed, 166 insertions(+), 139 deletions(-) diff --git a/packages/block-library/src/video/editor.scss b/packages/block-library/src/video/editor.scss index dd50ecc6c066fd..03e1c116cccb78 100644 --- a/packages/block-library/src/video/editor.scss +++ b/packages/block-library/src/video/editor.scss @@ -37,6 +37,7 @@ max-width: 240px; } +.block-library-video-tracks-editor__tracks-informative-message-title, .block-library-video-tracks-editor__single-track-editor-edit-track-label { margin-top: $grid-unit-05; color: $gray-700; @@ -56,3 +57,11 @@ padding: 0; } } + +.block-library-video-tracks-editor__tracks-informative-message { + padding: $grid-unit-10; + + &-description { + margin-bottom: 0; + } +} diff --git a/packages/block-library/src/video/tracks-editor.js b/packages/block-library/src/video/tracks-editor.js index e23d1c93378a69..33036a14f1fec7 100644 --- a/packages/block-library/src/video/tracks-editor.js +++ b/packages/block-library/src/video/tracks-editor.js @@ -24,7 +24,7 @@ import { } from '@wordpress/block-editor'; import { upload, media } from '@wordpress/icons'; import { useSelect } from '@wordpress/data'; -import { useState } from '@wordpress/element'; +import { useState, useRef, useEffect } from '@wordpress/element'; import { getFilename } from '@wordpress/url'; const ALLOWED_TYPES = [ 'text/vtt' ]; @@ -40,39 +40,29 @@ const KIND_OPTIONS = [ ]; function TrackList( { tracks, onEditPress } ) { - let content; - if ( tracks.length === 0 ) { - content = ( - <p className="block-library-video-tracks-editor__tracks-informative-message"> - { __( - 'Tracks can be subtitles, captions, chapters, or descriptions. They help make your content more accessible to a wider range of users.' - ) } - </p> - ); - } else { - content = tracks.map( ( track, index ) => { - return ( - <HStack - key={ index } - className="block-library-video-tracks-editor__track-list-track" + const content = tracks.map( ( track, index ) => { + return ( + <HStack + key={ index } + className="block-library-video-tracks-editor__track-list-track" + > + <span>{ track.label }</span> + <Button + __next40pxDefaultSize + variant="tertiary" + onClick={ () => onEditPress( index ) } + aria-label={ sprintf( + /* translators: %s: Label of the video text track e.g: "French subtitles". */ + _x( 'Edit %s', 'text tracks' ), + track.label + ) } > - <span>{ track.label } </span> - <Button - __next40pxDefaultSize - variant="tertiary" - onClick={ () => onEditPress( index ) } - aria-label={ sprintf( - /* translators: %s: Label of the video text track e.g: "French subtitles" */ - _x( 'Edit %s', 'text tracks' ), - track.label - ) } - > - { __( 'Edit' ) } - </Button> - </HStack> - ); - } ); - } + { __( 'Edit' ) } + </Button> + </HStack> + ); + } ); + return ( <MenuGroup label={ __( 'Text tracks' ) } @@ -87,105 +77,100 @@ function SingleTrackEditor( { track, onChange, onClose, onRemove } ) { const { src = '', label = '', srcLang = '', kind = DEFAULT_KIND } = track; const fileName = src.startsWith( 'blob:' ) ? '' : getFilename( src ) || ''; return ( - <NavigableMenu> - <VStack - className="block-library-video-tracks-editor__single-track-editor" - spacing="4" - > - <span className="block-library-video-tracks-editor__single-track-editor-edit-track-label"> - { __( 'Edit track' ) } - </span> - <span> - { __( 'File' ) }: <b>{ fileName }</b> - </span> - <Grid columns={ 2 } gap={ 4 }> - <TextControl - __next40pxDefaultSize - __nextHasNoMarginBottom - /* eslint-disable jsx-a11y/no-autofocus */ - autoFocus - /* eslint-enable jsx-a11y/no-autofocus */ - onChange={ ( newLabel ) => - onChange( { - ...track, - label: newLabel, - } ) - } - label={ __( 'Label' ) } - value={ label } - help={ __( 'Title of track' ) } - /> - <TextControl + <VStack + className="block-library-video-tracks-editor__single-track-editor" + spacing="4" + > + <span className="block-library-video-tracks-editor__single-track-editor-edit-track-label"> + { __( 'Edit track' ) } + </span> + <span> + { __( 'File' ) }: <b>{ fileName }</b> + </span> + <Grid columns={ 2 } gap={ 4 }> + <TextControl + __next40pxDefaultSize + __nextHasNoMarginBottom + onChange={ ( newLabel ) => + onChange( { + ...track, + label: newLabel, + } ) + } + label={ __( 'Label' ) } + value={ label } + help={ __( 'Title of track' ) } + /> + <TextControl + __next40pxDefaultSize + __nextHasNoMarginBottom + onChange={ ( newSrcLang ) => + onChange( { + ...track, + srcLang: newSrcLang, + } ) + } + label={ __( 'Source language' ) } + value={ srcLang } + help={ __( 'Language tag (en, fr, etc.)' ) } + /> + </Grid> + <VStack spacing="8"> + <SelectControl + __next40pxDefaultSize + __nextHasNoMarginBottom + className="block-library-video-tracks-editor__single-track-editor-kind-select" + options={ KIND_OPTIONS } + value={ kind } + label={ __( 'Kind' ) } + onChange={ ( newKind ) => { + onChange( { + ...track, + kind: newKind, + } ); + } } + /> + <HStack className="block-library-video-tracks-editor__single-track-editor-buttons-container"> + <Button __next40pxDefaultSize - __nextHasNoMarginBottom - onChange={ ( newSrcLang ) => - onChange( { - ...track, - srcLang: newSrcLang, - } ) - } - label={ __( 'Source language' ) } - value={ srcLang } - help={ __( 'Language tag (en, fr, etc.)' ) } - /> - </Grid> - <VStack spacing="8"> - <SelectControl + isDestructive + variant="link" + onClick={ onRemove } + > + { __( 'Remove track' ) } + </Button> + <Button __next40pxDefaultSize - __nextHasNoMarginBottom - className="block-library-video-tracks-editor__single-track-editor-kind-select" - options={ KIND_OPTIONS } - value={ kind } - label={ __( 'Kind' ) } - onChange={ ( newKind ) => { - onChange( { - ...track, - kind: newKind, - } ); + variant="primary" + onClick={ () => { + const changes = {}; + let hasChanges = false; + if ( label === '' ) { + changes.label = __( 'English' ); + hasChanges = true; + } + if ( srcLang === '' ) { + changes.srcLang = 'en'; + hasChanges = true; + } + if ( track.kind === undefined ) { + changes.kind = DEFAULT_KIND; + hasChanges = true; + } + if ( hasChanges ) { + onChange( { + ...track, + ...changes, + } ); + } + onClose(); } } - /> - <HStack className="block-library-video-tracks-editor__single-track-editor-buttons-container"> - <Button - __next40pxDefaultSize - variant="secondary" - onClick={ () => { - const changes = {}; - let hasChanges = false; - if ( label === '' ) { - changes.label = __( 'English' ); - hasChanges = true; - } - if ( srcLang === '' ) { - changes.srcLang = 'en'; - hasChanges = true; - } - if ( track.kind === undefined ) { - changes.kind = DEFAULT_KIND; - hasChanges = true; - } - if ( hasChanges ) { - onChange( { - ...track, - ...changes, - } ); - } - onClose(); - } } - > - { __( 'Close' ) } - </Button> - <Button - __next40pxDefaultSize - isDestructive - variant="link" - onClick={ onRemove } - > - { __( 'Remove track' ) } - </Button> - </HStack> - </VStack> + > + { __( 'Apply' ) } + </Button> + </HStack> </VStack> - </NavigableMenu> + </VStack> ); } @@ -194,6 +179,11 @@ export default function TracksEditor( { tracks = [], onChange } ) { return select( blockEditorStore ).getSettings().mediaUpload; }, [] ); const [ trackBeingEdited, setTrackBeingEdited ] = useState( null ); + const dropdownPopoverRef = useRef(); + + useEffect( () => { + dropdownPopoverRef.current?.focus(); + }, [ trackBeingEdited ] ); if ( ! mediaUpload ) { return null; @@ -201,17 +191,32 @@ export default function TracksEditor( { tracks = [], onChange } ) { return ( <Dropdown contentClassName="block-library-video-tracks-editor" - renderToggle={ ( { isOpen, onToggle } ) => ( - <ToolbarGroup> - <ToolbarButton - aria-expanded={ isOpen } - aria-haspopup="true" - onClick={ onToggle } - > - { __( 'Text tracks' ) } - </ToolbarButton> - </ToolbarGroup> - ) } + focusOnMount + popoverProps={ { + ref: dropdownPopoverRef, + } } + renderToggle={ ( { isOpen, onToggle } ) => { + const handleOnToggle = () => { + if ( ! isOpen ) { + // When the Popover opens make sure the initial view is + // always the track list rather than the edit track UI. + setTrackBeingEdited( null ); + } + onToggle(); + }; + + return ( + <ToolbarGroup> + <ToolbarButton + aria-expanded={ isOpen } + aria-haspopup="true" + onClick={ handleOnToggle } + > + { __( 'Text tracks' ) } + </ToolbarButton> + </ToolbarGroup> + ); + } } renderContent={ () => { if ( trackBeingEdited !== null ) { return ( @@ -235,8 +240,21 @@ export default function TracksEditor( { tracks = [], onChange } ) { /> ); } + return ( <> + { tracks.length === 0 && ( + <div className="block-library-video-tracks-editor__tracks-informative-message"> + <h2 className="block-library-video-tracks-editor__tracks-informative-message-title"> + { __( 'Text tracks' ) } + </h2> + <p className="block-library-video-tracks-editor__tracks-informative-message-description"> + { __( + 'Tracks can be subtitles, captions, chapters, or descriptions. They help make your content more accessible to a wider range of users.' + ) } + </p> + </div> + ) } <NavigableMenu> <TrackList tracks={ tracks } From 7639ed87bfd99a13e8d943a9b7c314897aaf39fc Mon Sep 17 00:00:00 2001 From: Vipul Gupta <55375170+vipul0425@users.noreply.github.com> Date: Wed, 20 Nov 2024 15:44:36 +0530 Subject: [PATCH 1643/1908] Blocks: Adds check for parent type before showing convert to pattern button (#66158) Co-authored-by: vipul0425 <vipulgupta003@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: aristath <aristath@git.wordpress.org> Co-authored-by: jordesign <jordesign@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> --- .../src/components/pattern-convert-button.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/patterns/src/components/pattern-convert-button.js b/packages/patterns/src/components/pattern-convert-button.js index d670cd85946aa9..4573a6a5de4e82 100644 --- a/packages/patterns/src/components/pattern-convert-button.js +++ b/packages/patterns/src/components/pattern-convert-button.js @@ -6,6 +6,7 @@ import { isReusableBlock, createBlock, serialize, + getBlockType, } from '@wordpress/blocks'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { useState, useCallback } from '@wordpress/element'; @@ -60,6 +61,15 @@ export default function PatternConvertButton( { const blocks = getBlocksByClientId( clientIds ) ?? []; + // Check if the block has reusable support defined. + const hasReusableBlockSupport = ( blockName ) => { + const blockType = getBlockType( blockName ); + const hasParent = blockType && 'parent' in blockType; + + // If the block has a parent, check with false as default, otherwise with true. + return hasBlockSupport( blockName, 'reusable', ! hasParent ); + }; + const isReusable = blocks.length === 1 && blocks[ 0 ] && @@ -82,7 +92,7 @@ export default function PatternConvertButton( { // Hide on invalid blocks. block.isValid && // Hide when block doesn't support being made into a pattern. - hasBlockSupport( block.name, 'reusable', true ) + hasReusableBlockSupport( block.name ) ) && // Hide when current doesn't have permission to do that. // Blocks refers to the wp_block post type, this checks the ability to create a post of that type. From b408e17a44bec0660ff7d68f1327b9b520688b13 Mon Sep 17 00:00:00 2001 From: Juan Aldasoro <juanfraa@gmail.com> Date: Wed, 20 Nov 2024 11:41:50 +0100 Subject: [PATCH 1644/1908] ColorPalette: Disable `Clear` button if there's no color value. (#67108) * Disable `Clear` button if there's no color value. * Add changelog entry. * Add PR to changelog entry. * Set gradient and duotone clear button as disabled if there's no value. Add `accessibleWhenDisabled` for all the changes. Co-authored-by: juanfra <juanfra@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- packages/components/CHANGELOG.md | 3 +++ packages/components/src/color-palette/index.tsx | 6 +++++- packages/components/src/duotone-picker/duotone-picker.tsx | 2 ++ packages/components/src/gradient-picker/index.tsx | 2 ++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index b23d024a724dd1..0638842814a7d3 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -13,6 +13,9 @@ - `ToggleGroupControl`: Fix active background for `0` value ([#66855](https://github.com/WordPress/gutenberg/pull/66855)). - `SlotFill`: Fix a bug where a stale value of `fillProps` could be used ([#67000](https://github.com/WordPress/gutenberg/pull/67000)). +- `ColorPalette`: Disable `Clear` button if there's no color value. ([#67108](https://github.com/WordPress/gutenberg/pull/67108)). +- `GradientPicker`: Disable `Clear` button if there's no value. ([#67108](https://github.com/WordPress/gutenberg/pull/67108)). +- `DuotonePicker`: Disable `Clear` button if there's no value. ([#67108](https://github.com/WordPress/gutenberg/pull/67108)). - `ColorPicker`: Add accessible label for copy button ([#67094](https://github.com/WordPress/gutenberg/pull/67094)). ### Enhancements diff --git a/packages/components/src/color-palette/index.tsx b/packages/components/src/color-palette/index.tsx index a65508d8278c5f..ed3e9039704179 100644 --- a/packages/components/src/color-palette/index.tsx +++ b/packages/components/src/color-palette/index.tsx @@ -249,7 +249,11 @@ function UnforwardedColorPalette( }; const actions = !! clearable && ( - <CircularOptionPicker.ButtonAction onClick={ clearColor }> + <CircularOptionPicker.ButtonAction + onClick={ clearColor } + accessibleWhenDisabled + disabled={ ! value } + > { __( 'Clear' ) } </CircularOptionPicker.ButtonAction> ); diff --git a/packages/components/src/duotone-picker/duotone-picker.tsx b/packages/components/src/duotone-picker/duotone-picker.tsx index ee54c9cdf4235e..8764b401c38296 100644 --- a/packages/components/src/duotone-picker/duotone-picker.tsx +++ b/packages/components/src/duotone-picker/duotone-picker.tsx @@ -168,6 +168,8 @@ function DuotonePicker( { !! clearable && ( <CircularOptionPicker.ButtonAction onClick={ () => onChange( undefined ) } + accessibleWhenDisabled + disabled={ ! value } > { __( 'Clear' ) } </CircularOptionPicker.ButtonAction> diff --git a/packages/components/src/gradient-picker/index.tsx b/packages/components/src/gradient-picker/index.tsx index 8368279b8afd70..f0607badd1b03a 100644 --- a/packages/components/src/gradient-picker/index.tsx +++ b/packages/components/src/gradient-picker/index.tsx @@ -247,6 +247,8 @@ export function GradientPicker( { ! disableCustomGradients && ( <CircularOptionPicker.ButtonAction onClick={ clearGradient } + accessibleWhenDisabled + disabled={ ! value } > { __( 'Clear' ) } </CircularOptionPicker.ButtonAction> From 110471ff548c053750553dd94cf2677f78688ade Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 20 Nov 2024 15:15:38 +0400 Subject: [PATCH 1645/1908] Global Styles: Don't call store actions during the render (#67146) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- .../src/components/global-styles/screen-style-variations.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/screen-style-variations.js b/packages/edit-site/src/components/global-styles/screen-style-variations.js index 12690966ba3c4f..76d13023ff09a8 100644 --- a/packages/edit-site/src/components/global-styles/screen-style-variations.js +++ b/packages/edit-site/src/components/global-styles/screen-style-variations.js @@ -6,6 +6,7 @@ import { __ } from '@wordpress/i18n'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { useDispatch } from '@wordpress/data'; import { store as editorStore } from '@wordpress/editor'; +import { useEffect } from '@wordpress/element'; /** * Internal dependencies @@ -22,7 +23,9 @@ function ScreenStyleVariations() { // - "Desktop" device preview const { setDeviceType } = useDispatch( editorStore ); useZoomOut(); - setDeviceType( 'desktop' ); + useEffect( () => { + setDeviceType( 'desktop' ); + }, [ setDeviceType ] ); return ( <> From 58e2d4b7ef9df24c537b1a2cf9485c2b2849822d Mon Sep 17 00:00:00 2001 From: Bernie Reiter <96308+ockham@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:52:51 +0100 Subject: [PATCH 1646/1908] Plugin: Bump minimum required WordPress version to 6.6 (#67117) And remove WP 6.6 compat layer. --- .github/workflows/performance.yml | 6 +- gutenberg.php | 4 +- lib/block-template-utils.php | 4 +- ...class-wp-theme-json-resolver-gutenberg.php | 2 +- lib/compat/wordpress-6.6/admin-bar.php | 48 - .../block-bindings/pattern-overrides.php | 62 - lib/compat/wordpress-6.6/block-editor.php | 50 - .../wordpress-6.6/block-template-utils.php | 362 -- lib/compat/wordpress-6.6/blocks.php | 46 - ...global-styles-revisions-controller-6-6.php | 97 - ...utenberg-rest-templates-controller-6-6.php | 131 - .../class-gutenberg-token-map-6-6.php | 818 ---- lib/compat/wordpress-6.6/compat.php | 32 - .../class-gutenberg-html-decoder-6-6.php | 463 --- ...class-gutenberg-html-open-elements-6-6.php | 541 --- .../class-gutenberg-html-processor-6-6.php | 2472 ------------ ...ass-gutenberg-html-processor-state-6-6.php | 143 - .../class-gutenberg-html-stack-event-6-6.php | 82 - ...class-gutenberg-html-tag-processor-6-6.php | 3559 ----------------- ...g-html5-named-character-references-6-6.php | 1315 ------ lib/compat/wordpress-6.6/option.php | 53 - lib/compat/wordpress-6.6/post.php | 39 - lib/compat/wordpress-6.6/resolve-patterns.php | 84 - lib/compat/wordpress-6.6/rest-api.php | 216 - ...utenberg-rest-templates-controller-6-7.php | 2 +- lib/compat/wordpress-6.7/compat.php | 2 +- lib/load.php | 27 +- lib/rest-api.php | 9 +- phpunit/blocks/get-block-templates-test.php | 109 - phpunit/class-wp-theme-json-test.php | 6 +- readme.txt | 2 +- 31 files changed, 19 insertions(+), 10767 deletions(-) delete mode 100644 lib/compat/wordpress-6.6/admin-bar.php delete mode 100644 lib/compat/wordpress-6.6/block-bindings/pattern-overrides.php delete mode 100644 lib/compat/wordpress-6.6/block-editor.php delete mode 100644 lib/compat/wordpress-6.6/block-template-utils.php delete mode 100644 lib/compat/wordpress-6.6/blocks.php delete mode 100644 lib/compat/wordpress-6.6/class-gutenberg-rest-global-styles-revisions-controller-6-6.php delete mode 100644 lib/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php delete mode 100644 lib/compat/wordpress-6.6/class-gutenberg-token-map-6-6.php delete mode 100644 lib/compat/wordpress-6.6/compat.php delete mode 100644 lib/compat/wordpress-6.6/html-api/class-gutenberg-html-decoder-6-6.php delete mode 100644 lib/compat/wordpress-6.6/html-api/class-gutenberg-html-open-elements-6-6.php delete mode 100644 lib/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-6-6.php delete mode 100644 lib/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-state-6-6.php delete mode 100644 lib/compat/wordpress-6.6/html-api/class-gutenberg-html-stack-event-6-6.php delete mode 100644 lib/compat/wordpress-6.6/html-api/class-gutenberg-html-tag-processor-6-6.php delete mode 100644 lib/compat/wordpress-6.6/html-api/gutenberg-html5-named-character-references-6-6.php delete mode 100644 lib/compat/wordpress-6.6/option.php delete mode 100644 lib/compat/wordpress-6.6/post.php delete mode 100644 lib/compat/wordpress-6.6/resolve-patterns.php delete mode 100644 lib/compat/wordpress-6.6/rest-api.php delete mode 100644 phpunit/blocks/get-block-templates-test.php diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index 6c8c984602edcb..4a5b576b424b53 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -69,13 +69,13 @@ jobs: - name: Compare performance with base branch if: github.event_name == 'push' # The base hash used here need to be a commit that is compatible with the current WP version - # The current one is 5f4c9c853b15092ed885d5280edefb973c37d9e9 and it needs to be updated every WP major release. + # The current one is c7722262e65a3f4d0f1a2d1ad29eccb2069509e4 and it needs to be updated every WP major release. # It is used as a base comparison point to avoid fluctuation in the performance metrics. run: | WP_VERSION=$(awk -F ': ' '/^Tested up to/{print $2}' readme.txt) IFS=. read -ra WP_VERSION_ARRAY <<< "$WP_VERSION" WP_MAJOR="${WP_VERSION_ARRAY[0]}.${WP_VERSION_ARRAY[1]}" - ./bin/plugin/cli.js perf $GITHUB_SHA 5f4c9c853b15092ed885d5280edefb973c37d9e9 --tests-branch $GITHUB_SHA --wp-version "$WP_MAJOR" + ./bin/plugin/cli.js perf $GITHUB_SHA c7722262e65a3f4d0f1a2d1ad29eccb2069509e4 --tests-branch $GITHUB_SHA --wp-version "$WP_MAJOR" - name: Compare performance with custom branches if: github.event_name == 'workflow_dispatch' @@ -101,7 +101,7 @@ jobs: CODEHEALTH_PROJECT_TOKEN: ${{ secrets.CODEHEALTH_PROJECT_TOKEN }} run: | COMMITTED_AT=$(git show -s $GITHUB_SHA --format="%cI") - ./bin/log-performance-results.js $CODEHEALTH_PROJECT_TOKEN trunk $GITHUB_SHA 5f4c9c853b15092ed885d5280edefb973c37d9e9 $COMMITTED_AT + ./bin/log-performance-results.js $CODEHEALTH_PROJECT_TOKEN trunk $GITHUB_SHA c7722262e65a3f4d0f1a2d1ad29eccb2069509e4 $COMMITTED_AT - name: Archive debug artifacts (screenshots, HTML snapshots) uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 diff --git a/gutenberg.php b/gutenberg.php index f79182f3ead567..738fe1a3bd5268 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -3,7 +3,7 @@ * Plugin Name: Gutenberg * Plugin URI: https://github.com/WordPress/gutenberg * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. - * Requires at least: 6.5 + * Requires at least: 6.6 * Requires PHP: 7.2 * Version: 19.7.0-rc.2 * Author: Gutenberg Team @@ -15,7 +15,7 @@ ### BEGIN AUTO-GENERATED DEFINES defined( 'GUTENBERG_DEVELOPMENT_MODE' ) or define( 'GUTENBERG_DEVELOPMENT_MODE', true ); ### END AUTO-GENERATED DEFINES -defined( 'GUTENBERG_MINIMUM_WP_VERSION' ) or define( 'GUTENBERG_MINIMUM_WP_VERSION', '6.5' ); +defined( 'GUTENBERG_MINIMUM_WP_VERSION' ) or define( 'GUTENBERG_MINIMUM_WP_VERSION', '6.6' ); gutenberg_pre_init(); diff --git a/lib/block-template-utils.php b/lib/block-template-utils.php index a644047d3cfdc1..7dba2ff518104d 100644 --- a/lib/block-template-utils.php +++ b/lib/block-template-utils.php @@ -60,7 +60,7 @@ function gutenberg_generate_block_templates_export_file() { } // Load templates into the zip file. - $templates = gutenberg_get_block_templates(); + $templates = get_block_templates(); foreach ( $templates as $template ) { $template->content = traverse_and_serialize_blocks( parse_blocks( $template->content ), @@ -74,7 +74,7 @@ function gutenberg_generate_block_templates_export_file() { } // Load template parts into the zip file. - $template_parts = gutenberg_get_block_templates( array(), 'wp_template_part' ); + $template_parts = get_block_templates( array(), 'wp_template_part' ); foreach ( $template_parts as $template_part ) { $zip->addFromString( 'parts/' . $template_part->slug . '.html', diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php index cd02b5a45c22f7..1f45d897a77cc0 100644 --- a/lib/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/class-wp-theme-json-resolver-gutenberg.php @@ -316,7 +316,7 @@ public static function get_theme_data( $deprecated = array(), $options = array() * So we take theme supports, transform it to theme.json shape * and merge the static::$theme upon that. */ - $theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( gutenberg_get_classic_theme_supports_block_editor_settings() ); + $theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_classic_theme_supports_block_editor_settings() ); if ( ! wp_theme_has_theme_json() ) { /* * Unlike block themes, classic themes without a theme.json disable diff --git a/lib/compat/wordpress-6.6/admin-bar.php b/lib/compat/wordpress-6.6/admin-bar.php deleted file mode 100644 index b7a77faebea72a..00000000000000 --- a/lib/compat/wordpress-6.6/admin-bar.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php -/** - * Changes to the WordPress admin bar. - * - * @package gutenberg - */ - -/** - * Adds the "Site Editor" link to the Toolbar. - * - * @since 5.9.0 - * @since 6.3.0 Added `$_wp_current_template_id` global for editing of current template directly from the admin bar. - * @since 6.6.0 Added the canvas argument to the url. - * - * @global string $_wp_current_template_id - * - * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. - */ -function gutenberg_admin_bar_edit_site_menu( $wp_admin_bar ) { - global $_wp_current_template_id; - - // Don't show if a block theme is not activated. - if ( ! wp_is_block_theme() ) { - return; - } - - // Don't show for users who can't edit theme options or when in the admin. - if ( ! current_user_can( 'edit_theme_options' ) || is_admin() || ( is_blog_admin() && is_multisite() && current_user_can( 'manage_sites' ) ) ) { - return; - } - - $wp_admin_bar->add_node( - array( - 'id' => 'site-editor', - 'title' => __( 'Edit site' ), - 'href' => add_query_arg( - array( - 'postType' => 'wp_template', - 'postId' => $_wp_current_template_id, - 'canvas' => 'edit', - ), - admin_url( 'site-editor.php' ) - ), - ) - ); -} -remove_action( 'admin_bar_menu', 'wp_admin_bar_edit_site_menu', 40 ); -add_action( 'admin_bar_menu', 'gutenberg_admin_bar_edit_site_menu', 41 ); diff --git a/lib/compat/wordpress-6.6/block-bindings/pattern-overrides.php b/lib/compat/wordpress-6.6/block-bindings/pattern-overrides.php deleted file mode 100644 index e5f9891f04c471..00000000000000 --- a/lib/compat/wordpress-6.6/block-bindings/pattern-overrides.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php -/** - * Pattern Overrides source for the Block Bindings. - * - * @package gutenberg - */ - -/** - * Gets value for the Pattern Overrides source. - * - * @param array $source_args Array containing source arguments used to look up the override value. - * Example: array( "key" => "foo" ). - * @param WP_Block $block_instance The block instance. - * @param string $attribute_name The name of the target attribute. - * @return mixed The value computed for the source. - */ -function gutenberg_block_bindings_pattern_overrides_callback( $source_attrs, $block_instance, $attribute_name ) { - if ( ! isset( $block_instance->context['pattern/overrides'] ) ) { - return null; - } - - $override_content = $block_instance->context['pattern/overrides']; - - // Back compat. Pattern overrides previously used a metadata `id` instead of `name`. - // We check first for the name, and if it exists, use that value. - if ( isset( $block_instance->attributes['metadata']['name'] ) ) { - $metadata_name = $block_instance->attributes['metadata']['name']; - if ( array_key_exists( $metadata_name, $override_content ) ) { - return _wp_array_get( $override_content, array( $metadata_name, $attribute_name ), null ); - } - } - - // Next check for the `id`. - if ( isset( $block_instance->attributes['metadata']['id'] ) ) { - $metadata_id = $block_instance->attributes['metadata']['id']; - if ( array_key_exists( $metadata_id, $override_content ) ) { - return _wp_array_get( $override_content, array( $metadata_id, $attribute_name ), null ); - } - } - - return null; -} - -/** - * Registers Pattern Overrides source in the Block Bindings registry. - */ -function gutenberg_register_block_bindings_pattern_overrides_source() { - // Override the "core/pattern-overrides" source from core. - if ( array_key_exists( 'core/pattern-overrides', get_all_registered_block_bindings_sources() ) ) { - unregister_block_bindings_source( 'core/pattern-overrides' ); - } - register_block_bindings_source( - 'core/pattern-overrides', - array( - 'label' => _x( 'Pattern Overrides', 'block bindings source' ), - 'get_value_callback' => 'gutenberg_block_bindings_pattern_overrides_callback', - 'uses_context' => array( 'pattern/overrides' ), - ) - ); -} - -add_action( 'init', 'gutenberg_register_block_bindings_pattern_overrides_source' ); diff --git a/lib/compat/wordpress-6.6/block-editor.php b/lib/compat/wordpress-6.6/block-editor.php deleted file mode 100644 index 6253f6a0adca4f..00000000000000 --- a/lib/compat/wordpress-6.6/block-editor.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php -/** - * Block Editor API. - * - * @package Gutenberg - * @subpackage Editor - */ - -/** - * Returns the classic theme supports settings for block editor. - * - * @since 6.2.0 - * @since 6.6.0 Add support for custom spacing sizes. - * - * @return array The classic theme supports settings. - */ -function gutenberg_get_classic_theme_supports_block_editor_settings() { - $theme_settings = array( - 'disableCustomColors' => get_theme_support( 'disable-custom-colors' ), - 'disableCustomFontSizes' => get_theme_support( 'disable-custom-font-sizes' ), - 'disableCustomGradients' => get_theme_support( 'disable-custom-gradients' ), - 'disableLayoutStyles' => get_theme_support( 'disable-layout-styles' ), - 'enableCustomLineHeight' => get_theme_support( 'custom-line-height' ), - 'enableCustomSpacing' => get_theme_support( 'custom-spacing' ), - 'enableCustomUnits' => get_theme_support( 'custom-units' ), - ); - - // Theme settings. - $color_palette = current( (array) get_theme_support( 'editor-color-palette' ) ); - if ( false !== $color_palette ) { - $theme_settings['colors'] = $color_palette; - } - - $font_sizes = current( (array) get_theme_support( 'editor-font-sizes' ) ); - if ( false !== $font_sizes ) { - $theme_settings['fontSizes'] = $font_sizes; - } - - $gradient_presets = current( (array) get_theme_support( 'editor-gradient-presets' ) ); - if ( false !== $gradient_presets ) { - $theme_settings['gradients'] = $gradient_presets; - } - - $spacing_sizes = current( (array) get_theme_support( 'editor-spacing-sizes' ) ); - if ( false !== $spacing_sizes ) { - $theme_settings['spacingSizes'] = $spacing_sizes; - } - - return $theme_settings; -} diff --git a/lib/compat/wordpress-6.6/block-template-utils.php b/lib/compat/wordpress-6.6/block-template-utils.php deleted file mode 100644 index 953f6bf20c077e..00000000000000 --- a/lib/compat/wordpress-6.6/block-template-utils.php +++ /dev/null @@ -1,362 +0,0 @@ -<?php -/** - * Utilities used to fetch and create templates and template parts. - * - * @package gutenberg - */ - -/** - * Gets the template hierarchy for the given template slug to be created. - * - * Note: Always add `index` as the last fallback template. - * - * - * @param string $slug The template slug to be created. - * @param bool $is_custom Optional. Indicates if a template is custom or - * part of the template hierarchy. Default false. - * @param string $template_prefix Optional. The template prefix for the created template. - * Used to extract the main template type, e.g. - * in `taxonomy-books` the `taxonomy` is extracted. - * Default empty string. - * @return string[] The template hierarchy. - */ -function gutenberg_get_template_hierarchy( $slug, $is_custom = false, $template_prefix = '' ) { - if ( 'index' === $slug ) { - /** This filter is documented in wp-includes/template.php */ - return apply_filters( 'index_template_hierarchy', array( 'index' ) ); - } - if ( $is_custom ) { - /** This filter is documented in wp-includes/template.php */ - return apply_filters( 'page_template_hierarchy', array( 'page', 'singular', 'index' ) ); - } - if ( 'front-page' === $slug ) { - /** This filter is documented in wp-includes/template.php */ - return apply_filters( 'frontpage_template_hierarchy', array( 'front-page', 'home', 'index' ) ); - } - - $matches = array(); - - $template_hierarchy = array( $slug ); - // Most default templates don't have `$template_prefix` assigned. - if ( ! empty( $template_prefix ) ) { - list( $type ) = explode( '-', $template_prefix ); - // We need these checks because we always add the `$slug` above. - if ( ! in_array( $template_prefix, array( $slug, $type ), true ) ) { - $template_hierarchy[] = $template_prefix; - } - if ( $slug !== $type ) { - $template_hierarchy[] = $type; - } - } elseif ( preg_match( '/^(author|category|archive|tag|page)-.+$/', $slug, $matches ) ) { - $template_hierarchy[] = $matches[1]; - } elseif ( preg_match( '/^(taxonomy|single)-(.+)$/', $slug, $matches ) ) { - $type = $matches[1]; - $slug_remaining = $matches[2]; - - $items = 'single' === $type ? get_post_types() : get_taxonomies(); - foreach ( $items as $item ) { - if ( ! str_starts_with( $slug_remaining, $item ) ) { - continue; - } - - // If $slug_remaining is equal to $post_type or $taxonomy we have - // the single-$post_type template or the taxonomy-$taxonomy template. - if ( $slug_remaining === $item ) { - $template_hierarchy[] = $type; - break; - } - - // If $slug_remaining is single-$post_type-$slug template. - if ( strlen( $slug_remaining ) > strlen( $item ) + 1 ) { - $template_hierarchy[] = "$type-$item"; - $template_hierarchy[] = $type; - break; - } - } - } - // Handle `archive` template. - if ( - str_starts_with( $slug, 'author' ) || - str_starts_with( $slug, 'taxonomy' ) || - str_starts_with( $slug, 'category' ) || - str_starts_with( $slug, 'tag' ) || - 'date' === $slug - ) { - $template_hierarchy[] = 'archive'; - } - // Handle `single` template. - if ( 'attachment' === $slug ) { - $template_hierarchy[] = 'single'; - } - // Handle `singular` template. - if ( - str_starts_with( $slug, 'single' ) || - str_starts_with( $slug, 'page' ) || - 'attachment' === $slug - ) { - $template_hierarchy[] = 'singular'; - } - $template_hierarchy[] = 'index'; - - $template_type = ''; - if ( ! empty( $template_prefix ) ) { - list( $template_type ) = explode( '-', $template_prefix ); - } else { - list( $template_type ) = explode( '-', $slug ); - } - $valid_template_types = array( '404', 'archive', 'attachment', 'author', 'category', 'date', 'embed', 'frontpage', 'home', 'index', 'page', 'paged', 'privacypolicy', 'search', 'single', 'singular', 'tag', 'taxonomy' ); - if ( in_array( $template_type, $valid_template_types, true ) ) { - /** This filter is documented in wp-includes/template.php */ - return apply_filters( "{$template_type}_template_hierarchy", $template_hierarchy ); - } - return $template_hierarchy; -} - -/** - * Retrieves the template files from the theme. - * - * @since 5.9.0 - * @since 6.3.0 Added the `$query` parameter. - * @access private - * - * @param string $template_type Template type. Either 'wp_template' or 'wp_template_part'. - * @param array $query { - * Arguments to retrieve templates. Optional, empty by default. - * - * @type string[] $slug__in List of slugs to include. - * @type string[] $slug__not_in List of slugs to skip. - * @type string $area A 'wp_template_part_area' taxonomy value to filter by (for 'wp_template_part' template type only). - * @type string $post_type Post type to get the templates for. - * } - * - * @return array Template - */ -function _gutenberg_get_block_templates_files( $template_type, $query = array() ) { - if ( 'wp_template' !== $template_type && 'wp_template_part' !== $template_type ) { - return null; - } - - // @core-merge: This code will go into Core's '_get_block_templates_files' function. - $default_template_types = array(); - if ( 'wp_template' === $template_type ) { - $default_template_types = get_default_block_template_types(); - } - // @core-merge: End of the code that will go into Core. - - // Prepare metadata from $query. - $slugs_to_include = isset( $query['slug__in'] ) ? $query['slug__in'] : array(); - $slugs_to_skip = isset( $query['slug__not_in'] ) ? $query['slug__not_in'] : array(); - $area = isset( $query['area'] ) ? $query['area'] : null; - $post_type = isset( $query['post_type'] ) ? $query['post_type'] : ''; - - $stylesheet = get_stylesheet(); - $template = get_template(); - $themes = array( - $stylesheet => get_stylesheet_directory(), - ); - // Add the parent theme if it's not the same as the current theme. - if ( $stylesheet !== $template ) { - $themes[ $template ] = get_template_directory(); - } - $template_files = array(); - foreach ( $themes as $theme_slug => $theme_dir ) { - $template_base_paths = get_block_theme_folders( $theme_slug ); - $theme_template_files = _get_block_templates_paths( $theme_dir . '/' . $template_base_paths[ $template_type ] ); - foreach ( $theme_template_files as $template_file ) { - $template_base_path = $template_base_paths[ $template_type ]; - $template_slug = substr( - $template_file, - // Starting position of slug. - strpos( $template_file, $template_base_path . DIRECTORY_SEPARATOR ) + 1 + strlen( $template_base_path ), - // Subtract ending '.html'. - -5 - ); - - // Skip this item if its slug doesn't match any of the slugs to include. - if ( ! empty( $slugs_to_include ) && ! in_array( $template_slug, $slugs_to_include, true ) ) { - continue; - } - - // Skip this item if its slug matches any of the slugs to skip. - if ( ! empty( $slugs_to_skip ) && in_array( $template_slug, $slugs_to_skip, true ) ) { - continue; - } - - /* - * The child theme items (stylesheet) are processed before the parent theme's (template). - * If a child theme defines a template, prevent the parent template from being added to the list as well. - */ - if ( isset( $template_files[ $template_slug ] ) ) { - continue; - } - - $new_template_item = array( - 'slug' => $template_slug, - 'path' => $template_file, - 'theme' => $theme_slug, - 'type' => $template_type, - ); - - if ( 'wp_template_part' === $template_type ) { - $candidate = _add_block_template_part_area_info( $new_template_item ); - if ( ! isset( $area ) || ( isset( $area ) && $area === $candidate['area'] ) ) { - $template_files[ $template_slug ] = $candidate; - } - } - - if ( 'wp_template' === $template_type ) { - $candidate = _add_block_template_info( $new_template_item ); - $is_custom = ! isset( $default_template_types[ $candidate['slug'] ] ); - - if ( - ! $post_type || - ( $post_type && isset( $candidate['postTypes'] ) && in_array( $post_type, $candidate['postTypes'], true ) ) - ) { - $template_files[ $template_slug ] = $candidate; - } - - // @core-merge: This code will go into Core's '_get_block_templates_files' function. - // The custom templates with no associated post-types are available for all post-types. - if ( $post_type && ! isset( $candidate['postTypes'] ) && $is_custom ) { - $template_files[ $template_slug ] = $candidate; - } - // @core-merge: End of the code that will go into Core. - } - } - } - - return array_values( $template_files ); -} - -/** - * Retrieves a list of unified template objects based on a query. - * - * @since 5.8.0 - * - * @param array $query { - * Optional. Arguments to retrieve templates. - * - * @type string[] $slug__in List of slugs to include. - * @type int $wp_id Post ID of customized template. - * @type string $area A 'wp_template_part_area' taxonomy value to filter by (for 'wp_template_part' template type only). - * @type string $post_type Post type to get the templates for. - * } - * @param string $template_type Template type. Either 'wp_template' or 'wp_template_part'. - * @return WP_Block_Template[] Array of block templates. - */ -function gutenberg_get_block_templates( $query = array(), $template_type = 'wp_template' ) { - /** - * Filters the block templates array before the query takes place. - * - * Return a non-null value to bypass the WordPress queries. - * - * @since 5.9.0 - * - * @param WP_Block_Template[]|null $block_templates Return an array of block templates to short-circuit the default query, - * or null to allow WP to run its normal queries. - * @param array $query { - * Arguments to retrieve templates. All arguments are optional. - * - * @type string[] $slug__in List of slugs to include. - * @type int $wp_id Post ID of customized template. - * @type string $area A 'wp_template_part_area' taxonomy value to filter by (for 'wp_template_part' template type only). - * @type string $post_type Post type to get the templates for. - * } - * @param string $template_type Template type. Either 'wp_template' or 'wp_template_part'. - */ - $templates = apply_filters( 'pre_get_block_templates', null, $query, $template_type ); - if ( ! is_null( $templates ) ) { - return $templates; - } - - $post_type = isset( $query['post_type'] ) ? $query['post_type'] : ''; - $wp_query_args = array( - 'post_status' => array( 'auto-draft', 'draft', 'publish' ), - 'post_type' => $template_type, - 'posts_per_page' => -1, - 'no_found_rows' => true, - 'lazy_load_term_meta' => false, - 'tax_query' => array( - array( - 'taxonomy' => 'wp_theme', - 'field' => 'name', - 'terms' => get_stylesheet(), - ), - ), - ); - - if ( 'wp_template_part' === $template_type && isset( $query['area'] ) ) { - $wp_query_args['tax_query'][] = array( - 'taxonomy' => 'wp_template_part_area', - 'field' => 'name', - 'terms' => $query['area'], - ); - $wp_query_args['tax_query']['relation'] = 'AND'; - } - - if ( ! empty( $query['slug__in'] ) ) { - $wp_query_args['post_name__in'] = $query['slug__in']; - $wp_query_args['posts_per_page'] = count( array_unique( $query['slug__in'] ) ); - } - - // This is only needed for the regular templates/template parts post type listing and editor. - if ( isset( $query['wp_id'] ) ) { - $wp_query_args['p'] = $query['wp_id']; - } else { - $wp_query_args['post_status'] = 'publish'; - } - - $template_query = new WP_Query( $wp_query_args ); - $query_result = array(); - foreach ( $template_query->posts as $post ) { - $template = _build_block_template_result_from_post( $post ); - - if ( is_wp_error( $template ) ) { - continue; - } - - if ( $post_type && ! $template->is_custom ) { - continue; - } - - if ( - $post_type && - isset( $template->post_types ) && - ! in_array( $post_type, $template->post_types, true ) - ) { - continue; - } - - $query_result[] = $template; - } - - if ( ! isset( $query['wp_id'] ) ) { - /* - * If the query has found some use templates, those have priority - * over the theme-provided ones, so we skip querying and building them. - */ - $query['slug__not_in'] = wp_list_pluck( $query_result, 'slug' ); - $template_files = _gutenberg_get_block_templates_files( $template_type, $query ); - foreach ( $template_files as $template_file ) { - $query_result[] = _build_block_template_result_from_file( $template_file, $template_type ); - } - } - - /** - * Filters the array of queried block templates array after they've been fetched. - * - * @since 5.9.0 - * - * @param WP_Block_Template[] $query_result Array of found block templates. - * @param array $query { - * Arguments to retrieve templates. All arguments are optional. - * - * @type string[] $slug__in List of slugs to include. - * @type int $wp_id Post ID of customized template. - * @type string $area A 'wp_template_part_area' taxonomy value to filter by (for 'wp_template_part' template type only). - * @type string $post_type Post type to get the templates for. - * } - * @param string $template_type wp_template or wp_template_part. - */ - return apply_filters( 'get_block_templates', $query_result, $query, $template_type ); -} diff --git a/lib/compat/wordpress-6.6/blocks.php b/lib/compat/wordpress-6.6/blocks.php deleted file mode 100644 index 0d8805a489d9cb..00000000000000 --- a/lib/compat/wordpress-6.6/blocks.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -/** - * Temporary compatibility shims for block APIs present in Gutenberg. - * - * @package gutenberg - */ - -/** - * Replace the `__default` block bindings attribute with the full list of supported - * attribute names for pattern overrides. - * - * @param array $parsed_block The full block, including name and attributes. - * - * @return string The parsed block with default binding replace. - */ -function gutenberg_replace_pattern_override_default_binding( $parsed_block ) { - $supported_block_attrs = array( - 'core/paragraph' => array( 'content' ), - 'core/heading' => array( 'content' ), - 'core/image' => array( 'id', 'url', 'title', 'alt' ), - 'core/button' => array( 'url', 'text', 'linkTarget', 'rel' ), - ); - - $bindings = $parsed_block['attrs']['metadata']['bindings'] ?? array(); - if ( - isset( $bindings['__default']['source'] ) && - 'core/pattern-overrides' === $bindings['__default']['source'] - ) { - $updated_bindings = array(); - - // Build an binding array of all supported attributes. - // Note that this also omits the `__default` attribute from the - // resulting array. - foreach ( $supported_block_attrs[ $parsed_block['blockName'] ] as $attribute_name ) { - // Retain any non-pattern override bindings that might be present. - $updated_bindings[ $attribute_name ] = isset( $bindings[ $attribute_name ] ) - ? $bindings[ $attribute_name ] - : array( 'source' => 'core/pattern-overrides' ); - } - $parsed_block['attrs']['metadata']['bindings'] = $updated_bindings; - } - - return $parsed_block; -} - -add_filter( 'render_block_data', 'gutenberg_replace_pattern_override_default_binding', 10, 1 ); diff --git a/lib/compat/wordpress-6.6/class-gutenberg-rest-global-styles-revisions-controller-6-6.php b/lib/compat/wordpress-6.6/class-gutenberg-rest-global-styles-revisions-controller-6-6.php deleted file mode 100644 index 3e5d4cdd68454a..00000000000000 --- a/lib/compat/wordpress-6.6/class-gutenberg-rest-global-styles-revisions-controller-6-6.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php -/** - * REST API: Gutenberg_REST_Global_Styles_Revisions_Controller class, inspired by WP_REST_Revisions_Controller. - * - * @package WordPress - * @subpackage REST_API - * @since 6.3.0 - */ - -/** - * Core class used to access global styles revisions via the REST API. - * - * @since 6.3.0 - * @since 6.6.0 Added custom relative theme file URIs to `_links`. - * - * @see WP_REST_Controller - */ -class Gutenberg_REST_Global_Styles_Revisions_Controller_6_6 extends WP_REST_Global_Styles_Revisions_Controller { - /** - * Prepares the revision for the REST response. - * - * @since 6.3.0 - * @since 6.6.0 Added resolved URI links to the response. - * - * @param WP_Post $post Post revision object. - * @param WP_REST_Request $request Request object. - * @return WP_REST_Response|WP_Error Response object. - */ - public function prepare_item_for_response( $post, $request ) { - $parent = $this->get_parent( $request['parent'] ); - $global_styles_config = $this->get_decoded_global_styles_json( $post->post_content ); - - if ( is_wp_error( $global_styles_config ) ) { - return $global_styles_config; - } - - $fields = $this->get_fields_for_response( $request ); - $data = array(); - $theme_json = array(); - - if ( ! empty( $global_styles_config['styles'] ) || ! empty( $global_styles_config['settings'] ) ) { - $theme_json = new WP_Theme_JSON_Gutenberg( $global_styles_config, 'custom' ); - $global_styles_config = ( $theme_json )->get_raw_data(); - - if ( rest_is_field_included( 'settings', $fields ) ) { - $data['settings'] = ! empty( $global_styles_config['settings'] ) ? $global_styles_config['settings'] : new stdClass(); - } - if ( rest_is_field_included( 'styles', $fields ) ) { - $data['styles'] = ! empty( $global_styles_config['styles'] ) ? $global_styles_config['styles'] : new stdClass(); - } - } - - if ( rest_is_field_included( 'author', $fields ) ) { - $data['author'] = (int) $post->post_author; - } - - if ( rest_is_field_included( 'date', $fields ) ) { - $data['date'] = $this->prepare_date_response( $post->post_date_gmt, $post->post_date ); - } - - if ( rest_is_field_included( 'date_gmt', $fields ) ) { - $data['date_gmt'] = $this->prepare_date_response( $post->post_date_gmt ); - } - - if ( rest_is_field_included( 'id', $fields ) ) { - $data['id'] = (int) $post->ID; - } - - if ( rest_is_field_included( 'modified', $fields ) ) { - $data['modified'] = $this->prepare_date_response( $post->post_modified_gmt, $post->post_modified ); - } - - if ( rest_is_field_included( 'modified_gmt', $fields ) ) { - $data['modified_gmt'] = $this->prepare_date_response( $post->post_modified_gmt ); - } - - if ( rest_is_field_included( 'parent', $fields ) ) { - $data['parent'] = (int) $parent->ID; - } - - $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; - $data = $this->add_additional_fields_to_object( $data, $request ); - $data = $this->filter_response_by_context( $data, $context ); - - $response = rest_ensure_response( $data ); - - // Add resolved URIs to the response. - $links = array(); - $resolved_theme_uris = WP_Theme_JSON_Resolver_Gutenberg::get_resolved_theme_uris( $theme_json ); - if ( ! empty( $resolved_theme_uris ) ) { - $links['https://api.w.org/theme-file'] = $resolved_theme_uris; - } - $response->add_links( $links ); - - return $response; - } -} diff --git a/lib/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php b/lib/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php deleted file mode 100644 index 034187ca9a70ae..00000000000000 --- a/lib/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php -/** - * REST API: Gutenberg_REST_Templates_Controller_6_6 class - * - * @package gutenberg - */ - -/** - * Gutenberg_REST_Templates_Controller_6_6 class - * - * Templates and template parts currently only allow access to administrators with the - * `edit_theme_options` capability. In order to allow other roles to also view the templates, - * we need to override the permissions check for the REST API endpoints. - */ -class Gutenberg_REST_Templates_Controller_6_6 extends WP_REST_Templates_Controller { - - /** - * Checks if a given request has access to read templates. - * - * @since 6.6.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return true|WP_Error True if the request has read access, WP_Error object otherwise. - */ - public function get_items_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable - if ( current_user_can( 'edit_posts' ) ) { - return true; - } - foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) { - if ( current_user_can( $post_type->cap->edit_posts ) ) { - return true; - } - } - - return new WP_Error( - 'rest_cannot_manage_templates', - __( 'Sorry, you are not allowed to access the templates on this site.', 'default' ), - array( - 'status' => rest_authorization_required_code(), - ) - ); - } - - /** - * Returns a list of templates. - * - * @since 5.8.0 - * - * @param WP_REST_Request $request The request instance. - * @return WP_REST_Response - */ - public function get_items( $request ) { - $query = array(); - if ( isset( $request['wp_id'] ) ) { - $query['wp_id'] = $request['wp_id']; - } - if ( isset( $request['area'] ) ) { - $query['area'] = $request['area']; - } - if ( isset( $request['post_type'] ) ) { - $query['post_type'] = $request['post_type']; - } - - $templates = array(); - foreach ( gutenberg_get_block_templates( $query, $this->post_type ) as $template ) { - $data = $this->prepare_item_for_response( $template, $request ); - $templates[] = $this->prepare_response_for_collection( $data ); - } - - return rest_ensure_response( $templates ); - } - - /** - * Checks if a given request has access to read templates. - * - * @since 6.6.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return true|WP_Error True if the request has read access, WP_Error object otherwise. - */ - public function get_item_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable - if ( current_user_can( 'edit_posts' ) ) { - return true; - } - foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) { - if ( current_user_can( $post_type->cap->edit_posts ) ) { - return true; - } - } - - return new WP_Error( - 'rest_cannot_manage_templates', - __( 'Sorry, you are not allowed to access the templates on this site.', 'default' ), - array( - 'status' => rest_authorization_required_code(), - ) - ); - } - - /** - * Returns the fallback template for the given slug. - * - * @since 6.1.0 - * - * @param WP_REST_Request $request The request instance. - * @return WP_REST_Response|WP_Error - */ - public function get_template_fallback( $request ) { - $hierarchy = gutenberg_get_template_hierarchy( $request['slug'], $request['is_custom'], $request['template_prefix'] ); - - do { - $fallback_template = resolve_block_template( $request['slug'], $hierarchy, '' ); - array_shift( $hierarchy ); - } while ( ! empty( $hierarchy ) && empty( $fallback_template->content ) ); - - // To maintain original behavior, return an empty object rather than a 404 error when no template is found. - $response = $fallback_template ? $this->prepare_item_for_response( $fallback_template, $request ) : new stdClass(); - - return rest_ensure_response( $response ); - } - - /** - * See WP_REST_Templates_Controller::prepare_item_for_response - */ - public function prepare_item_for_response( $item, $request ) { - $blocks = parse_blocks( $item->content ); - $blocks = gutenberg_replace_pattern_blocks( $blocks ); - $item->content = serialize_blocks( $blocks ); - return parent::prepare_item_for_response( $item, $request ); - } -} diff --git a/lib/compat/wordpress-6.6/class-gutenberg-token-map-6-6.php b/lib/compat/wordpress-6.6/class-gutenberg-token-map-6-6.php deleted file mode 100644 index 1df1fe91dab141..00000000000000 --- a/lib/compat/wordpress-6.6/class-gutenberg-token-map-6-6.php +++ /dev/null @@ -1,818 +0,0 @@ -<?php - -/** - * Class for efficiently looking up and mapping string keys to string values, with limits. - * - * @package WordPress - * @since 6.6.0 - */ - -/** - * WP_Token_Map class. - * - * Use this class in specific circumstances with a static set of lookup keys which map to - * a static set of transformed values. For example, this class is used to map HTML named - * character references to their equivalent UTF-8 values. - * - * This class works differently than code calling `in_array()` and other methods. It - * internalizes lookup logic and provides helper interfaces to optimize lookup and - * transformation. It provides a method for precomputing the lookup tables and storing - * them as PHP source code. - * - * All tokens and substitutions must be shorter than 256 bytes. - * - * Example: - * - * $smilies = WP_Token_Map::from_array( array( - * '8O' => '😯', - * ':(' => '🙁', - * ':)' => '🙂', - * ':?' => '😕', - * ) ); - * - * true === $smilies->contains( ':)' ); - * false === $smilies->contains( 'simile' ); - * - * '😕' === $smilies->read_token( 'Not sure :?.', 9, $length_of_smily_syntax ); - * 2 === $length_of_smily_syntax; - * - * ## Precomputing the Token Map. - * - * Creating the class involves some work sorting and organizing the tokens and their - * replacement values. In order to skip this, it's possible for the class to export - * its state and be used as actual PHP source code. - * - * Example: - * - * // Export with four spaces as the indent, only for the sake of this docblock. - * // The default indent is a tab character. - * $indent = ' '; - * echo $smilies->precomputed_php_source_table( $indent ); - * - * // Output, to be pasted into a PHP source file: - * WP_Token_Map::from_precomputed_table( - * array( - * "storage_version" => "6.6.0", - * "key_length" => 2, - * "groups" => "", - * "long_words" => array(), - * "small_words" => "8O\x00:)\x00:(\x00:?\x00", - * "small_mappings" => array( "😯", "🙂", "🙁", "😕" ) - * ) - * ); - * - * ## Large vs. small words. - * - * This class uses a short prefix called the "key" to optimize lookup of its tokens. - * This means that some tokens may be shorter than or equal in length to that key. - * Those words that are longer than the key are called "large" while those shorter - * than or equal to the key length are called "small." - * - * This separation of large and small words is incidental to the way this class - * optimizes lookup, and should be considered an internal implementation detail - * of the class. It may still be important to be aware of it, however. - * - * ## Determining Key Length. - * - * The choice of the size of the key length should be based on the data being stored in - * the token map. It should divide the data as evenly as possible, but should not create - * so many groups that a large fraction of the groups only contain a single token. - * - * For the HTML5 named character references, a key length of 2 was found to provide a - * sufficient spread and should be a good default for relatively large sets of tokens. - * - * However, for some data sets this might be too long. For example, a list of smilies - * may be too small for a key length of 2. Perhaps 1 would be more appropriate. It's - * best to experiment and determine empirically which values are appropriate. - * - * ## Generate Pre-Computed Source Code. - * - * Since the `WP_Token_Map` is designed for relatively static lookups, it can be - * advantageous to precompute the values and instantiate a table that has already - * sorted and grouped the tokens and built the lookup strings. - * - * This can be done with `WP_Token_Map::precomputed_php_source_table()`. - * - * Note that if there is a leading character that all tokens need, such as `&` for - * HTML named character references, it can be beneficial to exclude this from the - * token map. Instead, find occurrences of the leading character and then use the - * token map to see if the following characters complete the token. - * - * Example: - * - * $map = WP_Token_Map::from_array( array( 'simple_smile:' => '🙂', 'sob:' => '😭', 'soba:' => '🍜' ) ); - * echo $map->precomputed_php_source_table(); - * // Output - * WP_Token_Map::from_precomputed_table( - * array( - * "storage_version" => "6.6.0", - * "key_length" => 2, - * "groups" => "si\x00so\x00", - * "long_words" => array( - * // simple_smile:[🙂]. - * "\x0bmple_smile:\x04🙂", - * // soba:[🍜] sob:[😭]. - * "\x03ba:\x04🍜\x02b:\x04😭", - * ), - * "short_words" => "", - * "short_mappings" => array() - * } - * ); - * - * This precomputed value can be stored directly in source code and will skip the - * startup cost of generating the lookup strings. See `$html5_named_character_entities`. - * - * Note that any updates to the precomputed format should update the storage version - * constant. It would also be best to provide an update function to take older known - * versions and upgrade them in place when loading into `from_precomputed_table()`. - * - * ## Future Direction. - * - * It may be viable to dynamically increase the length limits such that there's no need to impose them. - * The limit appears because of the packing structure, which indicates how many bytes each segment of - * text in the lookup tables spans. If, however, care were taken to track the longest word length, then - * the packing structure could change its representation to allow for that. Each additional byte storing - * length, however, increases the memory overhead and lookup runtime. - * - * An alternative approach could be to borrow the UTF-8 variable-length encoding and store lengths of less - * than 127 as a single byte with the high bit unset, storing longer lengths as the combination of - * continuation bytes. - * - * Since it has not been shown during the development of this class that longer strings are required, this - * update is deferred until such a need is clear. - * - * @since 6.6.0 - */ -class Gutenberg_Token_Map_6_6 { - /** - * Denotes the version of the code which produces pre-computed source tables. - * - * This version will be used not only to verify pre-computed data, but also - * to upgrade pre-computed data from older versions. Choosing a name that - * corresponds to the WordPress release will help people identify where an - * old copy of data came from. - */ - const STORAGE_VERSION = '6.6.0-trunk'; - - /** - * Maximum length for each key and each transformed value in the table (in bytes). - * - * @since 6.6.0 - */ - const MAX_LENGTH = 256; - - /** - * How many bytes of each key are used to form a group key for lookup. - * This also determines whether a word is considered short or long. - * - * @since 6.6.0 - * - * @var int - */ - private $key_length = 2; - - /** - * Stores an optimized form of the word set, where words are grouped - * by a prefix of the `$key_length` and then collapsed into a string. - * - * In each group, the keys and lookups form a packed data structure. - * The keys in the string are stripped of their "group key," which is - * the prefix of length `$this->key_length` shared by all of the items - * in the group. Each word in the string is prefixed by a single byte - * whose raw unsigned integer value represents how many bytes follow. - * - * ┌────────────────┬───────────────┬─────────────────┬────────┐ - * │ Length of rest │ Rest of key │ Length of value │ Value │ - * │ of key (bytes) │ │ (bytes) │ │ - * ├────────────────┼───────────────┼─────────────────┼────────┤ - * │ 0x08 │ nterDot; │ 0x02 │ · │ - * └────────────────┴───────────────┴─────────────────┴────────┘ - * - * In this example, the key `CenterDot;` has a group key `Ce`, leaving - * eight bytes for the rest of the key, `nterDot;`, and two bytes for - * the transformed value `·` (or U+B7 or "\xC2\xB7"). - * - * Example: - * - * // Stores array( 'CenterDot;' => '·', 'Cedilla;' => '¸' ). - * $groups = "Ce\x00"; - * $large_words = array( "\x08nterDot;\x02·\x06dilla;\x02¸" ) - * - * The prefixes appear in the `$groups` string, each followed by a null - * byte. This makes for quick lookup of where in the group string the key - * is found, and then a simple division converts that offset into the index - * in the `$large_words` array where the group string is to be found. - * - * This lookup data structure is designed to optimize cache locality and - * minimize indirect memory reads when matching strings in the set. - * - * @since 6.6.0 - * - * @var array - */ - private $large_words = array(); - - /** - * Stores the group keys for sequential string lookup. - * - * The offset into this string where the group key appears corresponds with the index - * into the group array where the rest of the group string appears. This is an optimization - * to improve cache locality while searching and minimize indirect memory accesses. - * - * @since 6.6.0 - * - * @var string - */ - private $groups = ''; - - /** - * Stores an optimized row of small words, where every entry is - * `$this->key_size + 1` bytes long and zero-extended. - * - * This packing allows for direct lookup of a short word followed - * by the null byte, if extended to `$this->key_size + 1`. - * - * Example: - * - * // Stores array( 'GT', 'LT', 'gt', 'lt' ). - * "GT\x00LT\x00gt\x00lt\x00" - * - * @since 6.6.0 - * - * @var string - */ - private $small_words = ''; - - /** - * Replacements for the small words, in the same order they appear. - * - * With the position of a small word it's possible to index the translation - * directly, as its position in the `$small_words` string corresponds to - * the index of the replacement in the `$small_mapping` array. - * - * Example: - * - * array( '>', '<', '>', '<' ) - * - * @since 6.6.0 - * - * @var string[] - */ - private $small_mappings = array(); - - /** - * Create a token map using an associative array of key/value pairs as the input. - * - * Example: - * - * $smilies = WP_Token_Map::from_array( array( - * '8O' => '😯', - * ':(' => '🙁', - * ':)' => '🙂', - * ':?' => '😕', - * ) ); - * - * @since 6.6.0 - * - * @param array $mappings The keys transform into the values, both are strings. - * @param int $key_length Determines the group key length. Leave at the default value - * of 2 unless there's an empirical reason to change it. - * - * @return WP_Token_Map|null Token map, unless unable to create it. - */ - public static function from_array( $mappings, $key_length = 2 ) { - $map = new static(); - $map->key_length = $key_length; - - // Start by grouping words. - - $groups = array(); - $shorts = array(); - foreach ( $mappings as $word => $mapping ) { - if ( - self::MAX_LENGTH <= strlen( $word ) || - self::MAX_LENGTH <= strlen( $mapping ) - ) { - _doing_it_wrong( - __METHOD__, - sprintf( - /* translators: 1: maximum byte length (a count) */ - __( 'Token Map tokens and substitutions must all be shorter than %1$d bytes.' ), - self::MAX_LENGTH - ), - '6.6.0' - ); - return null; - } - - $length = strlen( $word ); - - if ( $key_length >= $length ) { - $shorts[] = $word; - } else { - $group = substr( $word, 0, $key_length ); - - if ( ! isset( $groups[ $group ] ) ) { - $groups[ $group ] = array(); - } - - $groups[ $group ][] = array( substr( $word, $key_length ), $mapping ); - } - } - - /* - * Sort the words to ensure that no smaller substring of a match masks the full match. - * For example, `Cap` should not match before `CapitalDifferentialD`. - */ - usort( $shorts, 'static::longest_first_then_alphabetical' ); - foreach ( $groups as $group_key => $group ) { - usort( - $groups[ $group_key ], - static function ( $a, $b ) { - return self::longest_first_then_alphabetical( $a[0], $b[0] ); - } - ); - } - - // Finally construct the optimized lookups. - - foreach ( $shorts as $word ) { - $map->small_words .= str_pad( $word, $key_length + 1, "\x00", STR_PAD_RIGHT ); - $map->small_mappings[] = $mappings[ $word ]; - } - - $group_keys = array_keys( $groups ); - sort( $group_keys ); - - foreach ( $group_keys as $group ) { - $map->groups .= "{$group}\x00"; - - $group_string = ''; - - foreach ( $groups[ $group ] as $group_word ) { - list( $word, $mapping ) = $group_word; - - $word_length = pack( 'C', strlen( $word ) ); - $mapping_length = pack( 'C', strlen( $mapping ) ); - $group_string .= "{$word_length}{$word}{$mapping_length}{$mapping}"; - } - - $map->large_words[] = $group_string; - } - - return $map; - } - - /** - * Creates a token map from a pre-computed table. - * This skips the initialization cost of generating the table. - * - * This function should only be used to load data created with - * WP_Token_Map::precomputed_php_source_tag(). - * - * @since 6.6.0 - * - * @param array $state { - * Stores pre-computed state for directly loading into a Token Map. - * - * @type string $storage_version Which version of the code produced this state. - * @type int $key_length Group key length. - * @type string $groups Group lookup index. - * @type array $large_words Large word groups and packed strings. - * @type string $small_words Small words packed string. - * @type array $small_mappings Small word mappings. - * } - * - * @return WP_Token_Map Map with precomputed data loaded. - */ - public static function from_precomputed_table( $state ) { - $has_necessary_state = isset( - $state['storage_version'], - $state['key_length'], - $state['groups'], - $state['large_words'], - $state['small_words'], - $state['small_mappings'] - ); - - if ( ! $has_necessary_state ) { - _doing_it_wrong( - __METHOD__, - __( 'Missing required inputs to pre-computed WP_Token_Map.' ), - '6.6.0' - ); - return null; - } - - if ( self::STORAGE_VERSION !== $state['storage_version'] ) { - _doing_it_wrong( - __METHOD__, - /* translators: 1: version string, 2: version string. */ - sprintf( __( 'Loaded version \'%1$s\' incompatible with expected version \'%2$s\'.' ), $state['storage_version'], self::STORAGE_VERSION ), - '6.6.0' - ); - return null; - } - - $map = new static(); - - $map->key_length = $state['key_length']; - $map->groups = $state['groups']; - $map->large_words = $state['large_words']; - $map->small_words = $state['small_words']; - $map->small_mappings = $state['small_mappings']; - - return $map; - } - - /** - * Indicates if a given word is a lookup key in the map. - * - * Example: - * - * true === $smilies->contains( ':)' ); - * false === $smilies->contains( 'simile' ); - * - * @since 6.6.0 - * - * @param string $word Determine if this word is a lookup key in the map. - * @param string $case_sensitivity Optional. Pass 'ascii-case-insensitive' to ignore ASCII case when matching. Default 'case-sensitive'. - * @return bool Whether there's an entry for the given word in the map. - */ - public function contains( $word, $case_sensitivity = 'case-sensitive' ) { - $ignore_case = 'ascii-case-insensitive' === $case_sensitivity; - - if ( $this->key_length >= strlen( $word ) ) { - if ( 0 === strlen( $this->small_words ) ) { - return false; - } - - $term = str_pad( $word, $this->key_length + 1, "\x00", STR_PAD_RIGHT ); - $word_at = $ignore_case ? stripos( $this->small_words, $term ) : strpos( $this->small_words, $term ); - if ( false === $word_at ) { - return false; - } - - return true; - } - - $group_key = substr( $word, 0, $this->key_length ); - $group_at = $ignore_case ? stripos( $this->groups, $group_key ) : strpos( $this->groups, $group_key ); - if ( false === $group_at ) { - return false; - } - $group = $this->large_words[ $group_at / ( $this->key_length + 1 ) ]; - $group_length = strlen( $group ); - $slug = substr( $word, $this->key_length ); - $length = strlen( $slug ); - $at = 0; - - while ( $at < $group_length ) { - $token_length = unpack( 'C', $group[ $at++ ] )[1]; - $token_at = $at; - $at += $token_length; - $mapping_length = unpack( 'C', $group[ $at++ ] )[1]; - $mapping_at = $at; - - if ( $token_length === $length && 0 === substr_compare( $group, $slug, $token_at, $token_length, $ignore_case ) ) { - return true; - } - - $at = $mapping_at + $mapping_length; - } - - return false; - } - - /** - * If the text starting at a given offset is a lookup key in the map, - * return the corresponding transformation from the map, else `false`. - * - * This function returns the translated string, but accepts an optional - * parameter `$matched_token_byte_length`, which communicates how many - * bytes long the lookup key was, if it found one. This can be used to - * advance a cursor in calling code if a lookup key was found. - * - * Example: - * - * false === $smilies->read_token( 'Not sure :?.', 0, $token_byte_length ); - * '😕' === $smilies->read_token( 'Not sure :?.', 9, $token_byte_length ); - * 2 === $token_byte_length; - * - * Example: - * - * while ( $at < strlen( $input ) ) { - * $next_at = strpos( $input, ':', $at ); - * if ( false === $next_at ) { - * break; - * } - * - * $smily = $smilies->read_token( $input, $next_at, $token_byte_length ); - * if ( false === $next_at ) { - * ++$at; - * continue; - * } - * - * $prefix = substr( $input, $at, $next_at - $at ); - * $at += $token_byte_length; - * $output .= "{$prefix}{$smily}"; - * } - * - * @since 6.6.0 - * - * @param string $text String in which to search for a lookup key. - * @param int $offset Optional. How many bytes into the string where the lookup key ought to start. Default 0. - * @param ?int &$matched_token_byte_length Optional. Holds byte-length of found token matched, otherwise not set. Default null. - * @param string $case_sensitivity Optional. Pass 'ascii-case-insensitive' to ignore ASCII case when matching. Default 'case-sensitive'. - * @return string|null Mapped value of lookup key if found, otherwise `null`. - */ - public function read_token( $text, $offset = 0, &$matched_token_byte_length = null, $case_sensitivity = 'case-sensitive' ) { - $ignore_case = 'ascii-case-insensitive' === $case_sensitivity; - $text_length = strlen( $text ); - - // Search for a long word first, if the text is long enough, and if that fails, a short one. - if ( $text_length > $this->key_length ) { - $group_key = substr( $text, $offset, $this->key_length ); - - $group_at = $ignore_case ? stripos( $this->groups, $group_key ) : strpos( $this->groups, $group_key ); - if ( false === $group_at ) { - // Perhaps a short word then. - return strlen( $this->small_words ) > 0 - ? $this->read_small_token( $text, $offset, $matched_token_byte_length, $case_sensitivity ) - : null; - } - - $group = $this->large_words[ $group_at / ( $this->key_length + 1 ) ]; - $group_length = strlen( $group ); - $at = 0; - while ( $at < $group_length ) { - $token_length = unpack( 'C', $group[ $at++ ] )[1]; - $token = substr( $group, $at, $token_length ); - $at += $token_length; - $mapping_length = unpack( 'C', $group[ $at++ ] )[1]; - $mapping_at = $at; - - if ( 0 === substr_compare( $text, $token, $offset + $this->key_length, $token_length, $ignore_case ) ) { - $matched_token_byte_length = $this->key_length + $token_length; - return substr( $group, $mapping_at, $mapping_length ); - } - - $at = $mapping_at + $mapping_length; - } - } - - // Perhaps a short word then. - return strlen( $this->small_words ) > 0 - ? $this->read_small_token( $text, $offset, $matched_token_byte_length, $case_sensitivity ) - : null; - } - - /** - * Finds a match for a short word at the index. - * - * @since 6.6.0. - * - * @param string $text String in which to search for a lookup key. - * @param int $offset Optional. How many bytes into the string where the lookup key ought to start. Default 0. - * @param ?int &$matched_token_byte_length Optional. Holds byte-length of found lookup key if matched, otherwise not set. Default null. - * @param string $case_sensitivity Optional. Pass 'ascii-case-insensitive' to ignore ASCII case when matching. Default 'case-sensitive'. - * @return string|null Mapped value of lookup key if found, otherwise `null`. - */ - private function read_small_token( $text, $offset, &$matched_token_byte_length, $case_sensitivity = 'case-sensitive' ) { - $ignore_case = 'ascii-case-insensitive' === $case_sensitivity; - $small_length = strlen( $this->small_words ); - $search_text = substr( $text, $offset, $this->key_length ); - if ( $ignore_case ) { - $search_text = strtoupper( $search_text ); - } - $starting_char = $search_text[0]; - - $at = 0; - while ( $at < $small_length ) { - if ( - $starting_char !== $this->small_words[ $at ] && - ( ! $ignore_case || strtoupper( $this->small_words[ $at ] ) !== $starting_char ) - ) { - $at += $this->key_length + 1; - continue; - } - - for ( $adjust = 1; $adjust < $this->key_length; $adjust++ ) { - if ( "\x00" === $this->small_words[ $at + $adjust ] ) { - $matched_token_byte_length = $adjust; - return $this->small_mappings[ $at / ( $this->key_length + 1 ) ]; - } - - if ( - $search_text[ $adjust ] !== $this->small_words[ $at + $adjust ] && - ( ! $ignore_case || strtoupper( $this->small_words[ $at + $adjust ] !== $search_text[ $adjust ] ) ) - ) { - $at += $this->key_length + 1; - continue 2; - } - } - - $matched_token_byte_length = $adjust; - return $this->small_mappings[ $at / ( $this->key_length + 1 ) ]; - } - - return null; - } - - /** - * Exports the token map into an associate array of key/value pairs. - * - * Example: - * - * $smilies->to_array() === array( - * '8O' => '😯', - * ':(' => '🙁', - * ':)' => '🙂', - * ':?' => '😕', - * ); - * - * @return array The lookup key/substitution values as an associate array. - */ - public function to_array() { - $tokens = array(); - - $at = 0; - $small_mapping = 0; - $small_length = strlen( $this->small_words ); - while ( $at < $small_length ) { - $key = rtrim( substr( $this->small_words, $at, $this->key_length + 1 ), "\x00" ); - $value = $this->small_mappings[ $small_mapping++ ]; - $tokens[ $key ] = $value; - - $at += $this->key_length + 1; - } - - foreach ( $this->large_words as $index => $group ) { - $prefix = substr( $this->groups, $index * ( $this->key_length + 1 ), 2 ); - $group_length = strlen( $group ); - $at = 0; - while ( $at < $group_length ) { - $length = unpack( 'C', $group[ $at++ ] )[1]; - $key = $prefix . substr( $group, $at, $length ); - - $at += $length; - $length = unpack( 'C', $group[ $at++ ] )[1]; - $value = substr( $group, $at, $length ); - - $tokens[ $key ] = $value; - $at += $length; - } - } - - return $tokens; - } - - /** - * Export the token map for quick loading in PHP source code. - * - * This function has a specific purpose, to make loading of static token maps fast. - * It's used to ensure that the HTML character reference lookups add a minimal cost - * to initializing the PHP process. - * - * Example: - * - * echo $smilies->precomputed_php_source_table(); - * - * // Output. - * WP_Token_Map::from_precomputed_table( - * array( - * "storage_version" => "6.6.0", - * "key_length" => 2, - * "groups" => "", - * "long_words" => array(), - * "small_words" => "8O\x00:)\x00:(\x00:?\x00", - * "small_mappings" => array( "😯", "🙂", "🙁", "😕" ) - * ) - * ); - * - * @since 6.6.0 - * - * @param string $indent Optional. Use this string for indentation, or rely on the default horizontal tab character. Default "\t". - * @return string Value which can be pasted into a PHP source file for quick loading of table. - */ - public function precomputed_php_source_table( $indent = "\t" ) { - $i1 = $indent; - $i2 = $i1 . $indent; - $i3 = $i2 . $indent; - - $class_version = self::STORAGE_VERSION; - - $output = self::class . "::from_precomputed_table(\n"; - $output .= "{$i1}array(\n"; - $output .= "{$i2}\"storage_version\" => \"{$class_version}\",\n"; - $output .= "{$i2}\"key_length\" => {$this->key_length},\n"; - - $group_line = str_replace( "\x00", "\\x00", $this->groups ); - $output .= "{$i2}\"groups\" => \"{$group_line}\",\n"; - - $output .= "{$i2}\"large_words\" => array(\n"; - - $prefixes = explode( "\x00", $this->groups ); - foreach ( $prefixes as $index => $prefix ) { - if ( '' === $prefix ) { - break; - } - $group = $this->large_words[ $index ]; - $group_length = strlen( $group ); - $comment_line = "{$i3}//"; - $data_line = "{$i3}\""; - $at = 0; - while ( $at < $group_length ) { - $token_length = unpack( 'C', $group[ $at++ ] )[1]; - $token = substr( $group, $at, $token_length ); - $at += $token_length; - $mapping_length = unpack( 'C', $group[ $at++ ] )[1]; - $mapping = substr( $group, $at, $mapping_length ); - $at += $mapping_length; - - $token_digits = str_pad( dechex( $token_length ), 2, '0', STR_PAD_LEFT ); - $mapping_digits = str_pad( dechex( $mapping_length ), 2, '0', STR_PAD_LEFT ); - - $mapping = preg_replace_callback( - "~[\\x00-\\x1f\\x22\\x5c]~", - static function ( $match_result ) { - switch ( $match_result[0] ) { - case '"': - return '\\"'; - - case '\\': - return '\\\\'; - - default: - $hex = dechex( ord( $match_result[0] ) ); - return "\\x{$hex}"; - } - }, - $mapping - ); - - $comment_line .= " {$prefix}{$token}[{$mapping}]"; - $data_line .= "\\x{$token_digits}{$token}\\x{$mapping_digits}{$mapping}"; - } - $comment_line .= ".\n"; - $data_line .= "\",\n"; - - $output .= $comment_line; - $output .= $data_line; - } - - $output .= "{$i2}),\n"; - - $small_words = array(); - $small_length = strlen( $this->small_words ); - $at = 0; - while ( $at < $small_length ) { - $small_words[] = substr( $this->small_words, $at, $this->key_length + 1 ); - $at += $this->key_length + 1; - } - - $small_text = str_replace( "\x00", '\x00', implode( '', $small_words ) ); - $output .= "{$i2}\"small_words\" => \"{$small_text}\",\n"; - - $output .= "{$i2}\"small_mappings\" => array(\n"; - foreach ( $this->small_mappings as $mapping ) { - $output .= "{$i3}\"{$mapping}\",\n"; - } - $output .= "{$i2})\n"; - $output .= "{$i1})\n"; - $output .= ')'; - - return $output; - } - - /** - * Compares two strings, returning the longest, or whichever - * is first alphabetically if they are the same length. - * - * This is an important sort when building the token map because - * it should not form a match on a substring of a longer potential - * match. For example, it should not detect `Cap` when matching - * against the string `CapitalDifferentialD`. - * - * @since 6.6.0 - * - * @param string $a First string to compare. - * @param string $b Second string to compare. - * @return int -1 or lower if `$a` is less than `$b`; 1 or greater if `$a` is greater than `$b`, and 0 if they are equal. - */ - private static function longest_first_then_alphabetical( $a, $b ) { - if ( $a === $b ) { - return 0; - } - - $length_a = strlen( $a ); - $length_b = strlen( $b ); - - // Longer strings are less-than for comparison's sake. - if ( $length_a !== $length_b ) { - return $length_b - $length_a; - } - - return strcmp( $a, $b ); - } -} diff --git a/lib/compat/wordpress-6.6/compat.php b/lib/compat/wordpress-6.6/compat.php deleted file mode 100644 index 4e444d3149824a..00000000000000 --- a/lib/compat/wordpress-6.6/compat.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php -/** - * WordPress 6.6 compatibility functions. - * - * @package gutenberg - */ - -/** - * Change the Patterns submenu link and remove the Template Parts submenu for - * the Classic theme. This function should not be backported to core, and should be - * removed when the required WP core version for Gutenberg is >= 6.6.0. - * - * @global array $submenu - */ -function gutenberg_change_patterns_link_and_remove_template_parts_submenu_item() { - if ( ! wp_is_block_theme() ) { - global $submenu; - - if ( empty( $submenu['themes.php'] ) ) { - return; - } - - foreach ( $submenu['themes.php'] as $key => $item ) { - if ( 'edit.php?post_type=wp_block' === $item[2] ) { - $submenu['themes.php'][ $key ][2] = 'site-editor.php?path=/patterns'; - } elseif ( 'site-editor.php?path=/wp_template_part/all' === $item[2] ) { - unset( $submenu['themes.php'][ $key ] ); - } - } - } -} -add_action( 'admin_init', 'gutenberg_change_patterns_link_and_remove_template_parts_submenu_item' ); diff --git a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-decoder-6-6.php b/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-decoder-6-6.php deleted file mode 100644 index d0b9f18bf5b29b..00000000000000 --- a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-decoder-6-6.php +++ /dev/null @@ -1,463 +0,0 @@ -<?php - -/** - * HTML API: WP_HTML_Decoder class - * - * Decodes spans of raw text found inside HTML content. - * - * @package WordPress - * @subpackage HTML-API - * @since 6.6.0 - */ -class Gutenberg_HTML_Decoder_6_6 { - /** - * Indicates if an attribute value starts with a given raw string value. - * - * Use this method to determine if an attribute value starts with a given string, regardless - * of how it might be encoded in HTML. For instance, `http:` could be represented as `http:` - * or as `http:` or as `http:` or as `http:`, or in many other ways. - * - * Example: - * - * $value = 'http://wordpress.org/'; - * true === WP_HTML_Decoder::attribute_starts_with( $value, 'http:', 'ascii-case-insensitive' ); - * false === WP_HTML_Decoder::attribute_starts_with( $value, 'https:', 'ascii-case-insensitive' ); - * - * @since 6.6.0 - * - * @param string $haystack String containing the raw non-decoded attribute value. - * @param string $search_text Does the attribute value start with this plain string. - * @param string $case_sensitivity Optional. Pass 'ascii-case-insensitive' to ignore ASCII case when matching. - * Default 'case-sensitive'. - * @return bool Whether the attribute value starts with the given string. - */ - public static function attribute_starts_with( $haystack, $search_text, $case_sensitivity = 'case-sensitive' ) { - $search_length = strlen( $search_text ); - $loose_case = 'ascii-case-insensitive' === $case_sensitivity; - $haystack_end = strlen( $haystack ); - $search_at = 0; - $haystack_at = 0; - - while ( $search_at < $search_length && $haystack_at < $haystack_end ) { - $chars_match = $loose_case - ? strtolower( $haystack[ $haystack_at ] ) === strtolower( $search_text[ $search_at ] ) - : $haystack[ $haystack_at ] === $search_text[ $search_at ]; - - $is_introducer = '&' === $haystack[ $haystack_at ]; - $next_chunk = $is_introducer - ? self::read_character_reference( 'attribute', $haystack, $haystack_at, $token_length ) - : null; - - // If there's no character reference and the characters don't match, the match fails. - if ( null === $next_chunk && ! $chars_match ) { - return false; - } - - // If there's no character reference but the character do match, then it could still match. - if ( null === $next_chunk && $chars_match ) { - ++$haystack_at; - ++$search_at; - continue; - } - - // If there is a character reference, then the decoded value must exactly match what follows in the search string. - if ( 0 !== substr_compare( $search_text, $next_chunk, $search_at, strlen( $next_chunk ), $loose_case ) ) { - return false; - } - - // The character reference matched, so continue checking. - $haystack_at += $token_length; - $search_at += strlen( $next_chunk ); - } - - return true; - } - - /** - * Returns a string containing the decoded value of a given HTML text node. - * - * Text nodes appear in HTML DATA sections, which are the text segments inside - * and around tags, excepting SCRIPT and STYLE elements (and some others), - * whose inner text is not decoded. Use this function to read the decoded - * value of such a text span in an HTML document. - * - * Example: - * - * '“😄”' === WP_HTML_Decode::decode_text_node( '“😄”' ); - * - * @since 6.6.0 - * - * @param string $text Text containing raw and non-decoded text node to decode. - * @return string Decoded UTF-8 value of given text node. - */ - public static function decode_text_node( $text ) { - return static::decode( 'data', $text ); - } - - /** - * Returns a string containing the decoded value of a given HTML attribute. - * - * Text found inside an HTML attribute has different parsing rules than for - * text found inside other markup, or DATA segments. Use this function to - * read the decoded value of an HTML string inside a quoted attribute. - * - * Example: - * - * '“😄”' === WP_HTML_Decode::decode_attribute( '“😄”' ); - * - * @since 6.6.0 - * - * @param string $text Text containing raw and non-decoded attribute value to decode. - * @return string Decoded UTF-8 value of given attribute value. - */ - public static function decode_attribute( $text ) { - return static::decode( 'attribute', $text ); - } - - /** - * Decodes a span of HTML text, depending on the context in which it's found. - * - * This is a low-level method; prefer calling WP_HTML_Decoder::decode_attribute() or - * WP_HTML_Decoder::decode_text_node() instead. It's provided for cases where this - * may be difficult to do from calling code. - * - * Example: - * - * '©' = WP_HTML_Decoder::decode( 'data', '©' ); - * - * @since 6.6.0 - * - * @access private - * - * @param string $context `attribute` for decoding attribute values, `data` otherwise. - * @param string $text Text document containing span of text to decode. - * @return string Decoded UTF-8 string. - */ - public static function decode( $context, $text ) { - $decoded = ''; - $end = strlen( $text ); - $at = 0; - $was_at = 0; - - while ( $at < $end ) { - $next_character_reference_at = strpos( $text, '&', $at ); - if ( false === $next_character_reference_at || $next_character_reference_at >= $end ) { - break; - } - - $character_reference = self::read_character_reference( $context, $text, $next_character_reference_at, $token_length ); - if ( isset( $character_reference ) ) { - $at = $next_character_reference_at; - $decoded .= substr( $text, $was_at, $at - $was_at ); - $decoded .= $character_reference; - $at += $token_length; - $was_at = $at; - continue; - } - - ++$at; - } - - if ( 0 === $was_at ) { - return $text; - } - - if ( $was_at < $end ) { - $decoded .= substr( $text, $was_at, $end - $was_at ); - } - - return $decoded; - } - - /** - * Attempt to read a character reference at the given location in a given string, - * depending on the context in which it's found. - * - * If a character reference is found, this function will return the translated value - * that the reference maps to. It will then set `$match_byte_length` the - * number of bytes of input it read while consuming the character reference. This - * gives calling code the opportunity to advance its cursor when traversing a string - * and decoding. - * - * Example: - * - * null === WP_HTML_Decoder::read_character_reference( 'attribute', 'Ships…', 0 ); - * '…' === WP_HTML_Decoder::read_character_reference( 'attribute', 'Ships…', 5, $token_length ); - * 8 === $token_length; // `…` - * - * null === WP_HTML_Decoder::read_character_reference( 'attribute', '¬in', 0 ); - * '∉' === WP_HTML_Decoder::read_character_reference( 'attribute', '∉', 0, $token_length ); - * 7 === $token_length; // `∉` - * - * '¬' === WP_HTML_Decoder::read_character_reference( 'data', '¬in', 0, $token_length ); - * 4 === $token_length; // `¬` - * '∉' === WP_HTML_Decoder::read_character_reference( 'data', '∉', 0, $token_length ); - * 7 === $token_length; // `∉` - * - * @since 6.6.0 - * - * @global WP_Token_Map $html5_named_character_references - * - * @param string $context `attribute` for decoding attribute values, `data` otherwise. - * @param string $text Text document containing span of text to decode. - * @param int $at Optional. Byte offset into text where span begins, defaults to the beginning (0). - * @param int &$match_byte_length Optional. Set to byte-length of character reference if provided and if a match - * is found, otherwise not set. Default null. - * @return string|false Decoded character reference in UTF-8 if found, otherwise `false`. - */ - public static function read_character_reference( $context, $text, $at = 0, &$match_byte_length = null ) { - /** - * Mappings for HTML5 named character references. - * - * @var WP_Token_Map $html5_named_character_references - */ - global $html5_named_character_references; - - $length = strlen( $text ); - if ( $at + 1 >= $length ) { - return null; - } - - if ( '&' !== $text[ $at ] ) { - return null; - } - - /* - * Numeric character references. - * - * When truncated, these will encode the code point found by parsing the - * digits that are available. For example, when `🅰` is truncated - * to `DZ` it will encode `DZ`. It does not: - * - know how to parse the original `🅰`. - * - fail to parse and return plaintext `DZ`. - * - fail to parse and return the replacement character `�` - */ - if ( '#' === $text[ $at + 1 ] ) { - if ( $at + 2 >= $length ) { - return null; - } - - /** Tracks inner parsing within the numeric character reference. */ - $digits_at = $at + 2; - - if ( 'x' === $text[ $digits_at ] || 'X' === $text[ $digits_at ] ) { - $numeric_base = 16; - $numeric_digits = '0123456789abcdefABCDEF'; - $max_digits = 6; // 􏿿 - ++$digits_at; - } else { - $numeric_base = 10; - $numeric_digits = '0123456789'; - $max_digits = 7; // 􏿿 - } - - // Cannot encode invalid Unicode code points. Max is to U+10FFFF. - $zero_count = strspn( $text, '0', $digits_at ); - $digit_count = strspn( $text, $numeric_digits, $digits_at + $zero_count ); - $after_digits = $digits_at + $zero_count + $digit_count; - $has_semicolon = $after_digits < $length && ';' === $text[ $after_digits ]; - $end_of_span = $has_semicolon ? $after_digits + 1 : $after_digits; - - // `&#` or `&#x` without digits returns into plaintext. - if ( 0 === $digit_count && 0 === $zero_count ) { - return null; - } - - // Whereas `&#` and only zeros is invalid. - if ( 0 === $digit_count ) { - $match_byte_length = $end_of_span - $at; - return '�'; - } - - // If there are too many digits then it's not worth parsing. It's invalid. - if ( $digit_count > $max_digits ) { - $match_byte_length = $end_of_span - $at; - return '�'; - } - - $digits = substr( $text, $digits_at + $zero_count, $digit_count ); - $code_point = intval( $digits, $numeric_base ); - - /* - * Noncharacters, 0x0D, and non-ASCII-whitespace control characters. - * - * > A noncharacter is a code point that is in the range U+FDD0 to U+FDEF, - * > inclusive, or U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, U+2FFFE, U+2FFFF, - * > U+3FFFE, U+3FFFF, U+4FFFE, U+4FFFF, U+5FFFE, U+5FFFF, U+6FFFE, - * > U+6FFFF, U+7FFFE, U+7FFFF, U+8FFFE, U+8FFFF, U+9FFFE, U+9FFFF, - * > U+AFFFE, U+AFFFF, U+BFFFE, U+BFFFF, U+CFFFE, U+CFFFF, U+DFFFE, - * > U+DFFFF, U+EFFFE, U+EFFFF, U+FFFFE, U+FFFFF, U+10FFFE, or U+10FFFF. - * - * A C0 control is a code point that is in the range of U+00 to U+1F, - * but ASCII whitespace includes U+09, U+0A, U+0C, and U+0D. - * - * These characters are invalid but still decode as any valid character. - * This comment is here to note and explain why there's no check to - * remove these characters or replace them. - * - * @see https://infra.spec.whatwg.org/#noncharacter - */ - - /* - * Code points in the C1 controls area need to be remapped as if they - * were stored in Windows-1252. Note! This transformation only happens - * for numeric character references. The raw code points in the byte - * stream are not translated. - * - * > If the number is one of the numbers in the first column of - * > the following table, then find the row with that number in - * > the first column, and set the character reference code to - * > the number in the second column of that row. - */ - if ( $code_point >= 0x80 && $code_point <= 0x9F ) { - $windows_1252_mapping = array( - 0x20AC, // 0x80 -> EURO SIGN (€). - 0x81, // 0x81 -> (no change). - 0x201A, // 0x82 -> SINGLE LOW-9 QUOTATION MARK (‚). - 0x0192, // 0x83 -> LATIN SMALL LETTER F WITH HOOK (ƒ). - 0x201E, // 0x84 -> DOUBLE LOW-9 QUOTATION MARK („). - 0x2026, // 0x85 -> HORIZONTAL ELLIPSIS (…). - 0x2020, // 0x86 -> DAGGER (†). - 0x2021, // 0x87 -> DOUBLE DAGGER (‡). - 0x02C6, // 0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT (ˆ). - 0x2030, // 0x89 -> PER MILLE SIGN (‰). - 0x0160, // 0x8A -> LATIN CAPITAL LETTER S WITH CARON (Š). - 0x2039, // 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK (‹). - 0x0152, // 0x8C -> LATIN CAPITAL LIGATURE OE (Œ). - 0x8D, // 0x8D -> (no change). - 0x017D, // 0x8E -> LATIN CAPITAL LETTER Z WITH CARON (Ž). - 0x8F, // 0x8F -> (no change). - 0x90, // 0x90 -> (no change). - 0x2018, // 0x91 -> LEFT SINGLE QUOTATION MARK (‘). - 0x2019, // 0x92 -> RIGHT SINGLE QUOTATION MARK (’). - 0x201C, // 0x93 -> LEFT DOUBLE QUOTATION MARK (“). - 0x201D, // 0x94 -> RIGHT DOUBLE QUOTATION MARK (”). - 0x2022, // 0x95 -> BULLET (•). - 0x2013, // 0x96 -> EN DASH (–). - 0x2014, // 0x97 -> EM DASH (—). - 0x02DC, // 0x98 -> SMALL TILDE (˜). - 0x2122, // 0x99 -> TRADE MARK SIGN (™). - 0x0161, // 0x9A -> LATIN SMALL LETTER S WITH CARON (š). - 0x203A, // 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (›). - 0x0153, // 0x9C -> LATIN SMALL LIGATURE OE (œ). - 0x9D, // 0x9D -> (no change). - 0x017E, // 0x9E -> LATIN SMALL LETTER Z WITH CARON (ž). - 0x0178, // 0x9F -> LATIN CAPITAL LETTER Y WITH DIAERESIS (Ÿ). - ); - - $code_point = $windows_1252_mapping[ $code_point - 0x80 ]; - } - - $match_byte_length = $end_of_span - $at; - return self::code_point_to_utf8_bytes( $code_point ); - } - - /** Tracks inner parsing within the named character reference. */ - $name_at = $at + 1; - // Minimum named character reference is two characters. E.g. `GT`. - if ( $name_at + 2 > $length ) { - return null; - } - - $name_length = 0; - $replacement = $html5_named_character_references->read_token( $text, $name_at, $name_length ); - if ( false === $replacement ) { - return null; - } - - $after_name = $name_at + $name_length; - - // If the match ended with a semicolon then it should always be decoded. - if ( ';' === $text[ $name_at + $name_length - 1 ] ) { - $match_byte_length = $after_name - $at; - return $replacement; - } - - /* - * At this point though there's a match for an entry in the named - * character reference table but the match doesn't end in `;`. - * It may be allowed if it's followed by something unambiguous. - */ - $ambiguous_follower = ( - $after_name < $length && - $name_at < $length && - ( - ctype_alnum( $text[ $after_name ] ) || - '=' === $text[ $after_name ] - ) - ); - - // It's non-ambiguous, safe to leave it in. - if ( ! $ambiguous_follower ) { - $match_byte_length = $after_name - $at; - return $replacement; - } - - // It's ambiguous, which isn't allowed inside attributes. - if ( 'attribute' === $context ) { - return null; - } - - $match_byte_length = $after_name - $at; - return $replacement; - } - - /** - * Encode a code point number into the UTF-8 encoding. - * - * This encoder implements the UTF-8 encoding algorithm for converting - * a code point into a byte sequence. If it receives an invalid code - * point it will return the Unicode Replacement Character U+FFFD `�`. - * - * Example: - * - * '🅰' === WP_HTML_Decoder::code_point_to_utf8_bytes( 0x1f170 ); - * - * // Half of a surrogate pair is an invalid code point. - * '�' === WP_HTML_Decoder::code_point_to_utf8_bytes( 0xd83c ); - * - * @since 6.6.0 - * - * @see https://www.rfc-editor.org/rfc/rfc3629 For the UTF-8 standard. - * - * @param int $code_point Which code point to convert. - * @return string Converted code point, or `�` if invalid. - */ - public static function code_point_to_utf8_bytes( $code_point ) { - // Pre-check to ensure a valid code point. - if ( - $code_point <= 0 || - ( $code_point >= 0xD800 && $code_point <= 0xDFFF ) || - $code_point > 0x10FFFF - ) { - return '�'; - } - - if ( $code_point <= 0x7F ) { - return chr( $code_point ); - } - - if ( $code_point <= 0x7FF ) { - $byte1 = ( $code_point >> 6 ) | 0xC0; - $byte2 = $code_point & 0x3F | 0x80; - - return pack( 'CC', $byte1, $byte2 ); - } - - if ( $code_point <= 0xFFFF ) { - $byte1 = ( $code_point >> 12 ) | 0xE0; - $byte2 = ( $code_point >> 6 ) & 0x3F | 0x80; - $byte3 = $code_point & 0x3F | 0x80; - - return pack( 'CCC', $byte1, $byte2, $byte3 ); - } - - // Any values above U+10FFFF are eliminated above in the pre-check. - $byte1 = ( $code_point >> 18 ) | 0xF0; - $byte2 = ( $code_point >> 12 ) & 0x3F | 0x80; - $byte3 = ( $code_point >> 6 ) & 0x3F | 0x80; - $byte4 = $code_point & 0x3F | 0x80; - - return pack( 'CCCC', $byte1, $byte2, $byte3, $byte4 ); - } -} diff --git a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-open-elements-6-6.php b/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-open-elements-6-6.php deleted file mode 100644 index da237e02bc63ba..00000000000000 --- a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-open-elements-6-6.php +++ /dev/null @@ -1,541 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Open_Elements class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.4.0 - */ - -/** - * Core class used by the HTML processor during HTML parsing - * for managing the stack of open elements. - * - * This class is designed for internal use by the HTML processor. - * - * > Initially, the stack of open elements is empty. The stack grows - * > downwards; the topmost node on the stack is the first one added - * > to the stack, and the bottommost node of the stack is the most - * > recently added node in the stack (notwithstanding when the stack - * > is manipulated in a random access fashion as part of the handling - * > for misnested tags). - * - * @since 6.4.0 - * - * @access private - * - * @see https://html.spec.whatwg.org/#stack-of-open-elements - * @see WP_HTML_Processor - */ -class Gutenberg_HTML_Open_Elements_6_6 { - /** - * Holds the stack of open element references. - * - * @since 6.4.0 - * - * @var WP_HTML_Token[] - */ - public $stack = array(); - - /** - * Whether a P element is in button scope currently. - * - * This class optimizes scope lookup by pre-calculating - * this value when elements are added and removed to the - * stack of open elements which might change its value. - * This avoids frequent iteration over the stack. - * - * @since 6.4.0 - * - * @var bool - */ - private $has_p_in_button_scope = false; - - /** - * A function that will be called when an item is popped off the stack of open elements. - * - * The function will be called with the popped item as its argument. - * - * @since 6.6.0 - * - * @var Closure - */ - private $pop_handler = null; - - /** - * A function that will be called when an item is pushed onto the stack of open elements. - * - * The function will be called with the pushed item as its argument. - * - * @since 6.6.0 - * - * @var Closure - */ - private $push_handler = null; - - /** - * Sets a pop handler that will be called when an item is popped off the stack of - * open elements. - * - * The function will be called with the pushed item as its argument. - * - * @since 6.6.0 - * - * @param Closure $handler The handler function. - */ - public function set_pop_handler( Closure $handler ) { - $this->pop_handler = $handler; - } - - /** - * Sets a push handler that will be called when an item is pushed onto the stack of - * open elements. - * - * The function will be called with the pushed item as its argument. - * - * @since 6.6.0 - * - * @param Closure $handler The handler function. - */ - public function set_push_handler( Closure $handler ) { - $this->push_handler = $handler; - } - - /** - * Reports if a specific node is in the stack of open elements. - * - * @since 6.4.0 - * - * @param WP_HTML_Token $token Look for this node in the stack. - * @return bool Whether the referenced node is in the stack of open elements. - */ - public function contains_node( $token ) { - foreach ( $this->walk_up() as $item ) { - if ( $token->bookmark_name === $item->bookmark_name ) { - return true; - } - } - - return false; - } - - /** - * Returns how many nodes are currently in the stack of open elements. - * - * @since 6.4.0 - * - * @return int How many node are in the stack of open elements. - */ - public function count() { - return count( $this->stack ); - } - - /** - * Returns the node at the end of the stack of open elements, - * if one exists. If the stack is empty, returns null. - * - * @since 6.4.0 - * - * @return WP_HTML_Token|null Last node in the stack of open elements, if one exists, otherwise null. - */ - public function current_node() { - $current_node = end( $this->stack ); - - return $current_node ? $current_node : null; - } - - /** - * Returns whether an element is in a specific scope. - * - * ## HTML Support - * - * This function skips checking for the termination list because there - * are no supported elements which appear in the termination list. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-the-specific-scope - * - * @param string $tag_name Name of tag check. - * @param string[] $termination_list List of elements that terminate the search. - * @return bool Whether the element was found in a specific scope. - */ - public function has_element_in_specific_scope( $tag_name, $termination_list ) { - foreach ( $this->walk_up() as $node ) { - if ( $node->node_name === $tag_name ) { - return true; - } - - if ( - '(internal: H1 through H6 - do not use)' === $tag_name && - in_array( $node->node_name, array( 'H1', 'H2', 'H3', 'H4', 'H5', 'H6' ), true ) - ) { - return true; - } - - switch ( $node->node_name ) { - case 'HTML': - return false; - } - - if ( in_array( $node->node_name, $termination_list, true ) ) { - return false; - } - } - - return false; - } - - /** - * Returns whether a particular element is in scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-scope - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_scope( $tag_name ) { - return $this->has_element_in_specific_scope( - $tag_name, - array( - - /* - * Because it's not currently possible to encounter - * one of the termination elements, they don't need - * to be listed here. If they were, they would be - * unreachable and only waste CPU cycles while - * scanning through HTML. - */ - ) - ); - } - - /** - * Returns whether a particular element is in list item scope. - * - * @since 6.4.0 - * @since 6.5.0 Implemented: no longer throws on every invocation. - * - * @see https://html.spec.whatwg.org/#has-an-element-in-list-item-scope - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_list_item_scope( $tag_name ) { - return $this->has_element_in_specific_scope( - $tag_name, - array( - // There are more elements that belong here which aren't currently supported. - 'OL', - 'UL', - ) - ); - } - - /** - * Returns whether a particular element is in button scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-button-scope - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_button_scope( $tag_name ) { - return $this->has_element_in_specific_scope( $tag_name, array( 'BUTTON' ) ); - } - - /** - * Returns whether a particular element is in table scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-table-scope - * - * @throws WP_HTML_Unsupported_Exception Always until this function is implemented. - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_table_scope( $tag_name ) { - throw new WP_HTML_Unsupported_Exception( 'Cannot process elements depending on table scope.' ); - - return false; // The linter requires this unreachable code until the function is implemented and can return. - } - - /** - * Returns whether a particular element is in select scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-select-scope - * - * @throws WP_HTML_Unsupported_Exception Always until this function is implemented. - * - * @param string $tag_name Name of tag to check. - * @return bool Whether given element is in scope. - */ - public function has_element_in_select_scope( $tag_name ) { - throw new WP_HTML_Unsupported_Exception( 'Cannot process elements depending on select scope.' ); - - return false; // The linter requires this unreachable code until the function is implemented and can return. - } - - /** - * Returns whether a P is in BUTTON scope. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#has-an-element-in-button-scope - * - * @return bool Whether a P is in BUTTON scope. - */ - public function has_p_in_button_scope() { - return $this->has_p_in_button_scope; - } - - /** - * Pops a node off of the stack of open elements. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#stack-of-open-elements - * - * @return bool Whether a node was popped off of the stack. - */ - public function pop() { - $item = array_pop( $this->stack ); - if ( null === $item ) { - return false; - } - - if ( 'context-node' === $item->bookmark_name ) { - $this->stack[] = $item; - return false; - } - - $this->after_element_pop( $item ); - return true; - } - - /** - * Pops nodes off of the stack of open elements until one with the given tag name has been popped. - * - * @since 6.4.0 - * - * @see WP_HTML_Open_Elements::pop - * - * @param string $tag_name Name of tag that needs to be popped off of the stack of open elements. - * @return bool Whether a tag of the given name was found and popped off of the stack of open elements. - */ - public function pop_until( $tag_name ) { - foreach ( $this->walk_up() as $item ) { - if ( 'context-node' === $item->bookmark_name ) { - return true; - } - - $this->pop(); - - if ( - '(internal: H1 through H6 - do not use)' === $tag_name && - in_array( $item->node_name, array( 'H1', 'H2', 'H3', 'H4', 'H5', 'H6' ), true ) - ) { - return true; - } - - if ( $tag_name === $item->node_name ) { - return true; - } - } - - return false; - } - - /** - * Pushes a node onto the stack of open elements. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#stack-of-open-elements - * - * @param WP_HTML_Token $stack_item Item to add onto stack. - */ - public function push( $stack_item ) { - $this->stack[] = $stack_item; - $this->after_element_push( $stack_item ); - } - - /** - * Removes a specific node from the stack of open elements. - * - * @since 6.4.0 - * - * @param WP_HTML_Token $token The node to remove from the stack of open elements. - * @return bool Whether the node was found and removed from the stack of open elements. - */ - public function remove_node( $token ) { - if ( 'context-node' === $token->bookmark_name ) { - return false; - } - - foreach ( $this->walk_up() as $position_from_end => $item ) { - if ( $token->bookmark_name !== $item->bookmark_name ) { - continue; - } - - $position_from_start = $this->count() - $position_from_end - 1; - array_splice( $this->stack, $position_from_start, 1 ); - $this->after_element_pop( $item ); - return true; - } - - return false; - } - - - /** - * Steps through the stack of open elements, starting with the top element - * (added first) and walking downwards to the one added last. - * - * This generator function is designed to be used inside a "foreach" loop. - * - * Example: - * - * $html = '<em><strong><a>We are here'; - * foreach ( $stack->walk_down() as $node ) { - * echo "{$node->node_name} -> "; - * } - * > EM -> STRONG -> A -> - * - * To start with the most-recently added element and walk towards the top, - * see WP_HTML_Open_Elements::walk_up(). - * - * @since 6.4.0 - */ - public function walk_down() { - $count = count( $this->stack ); - - for ( $i = 0; $i < $count; $i++ ) { - yield $this->stack[ $i ]; - } - } - - /** - * Steps through the stack of open elements, starting with the bottom element - * (added last) and walking upwards to the one added first. - * - * This generator function is designed to be used inside a "foreach" loop. - * - * Example: - * - * $html = '<em><strong><a>We are here'; - * foreach ( $stack->walk_up() as $node ) { - * echo "{$node->node_name} -> "; - * } - * > A -> STRONG -> EM -> - * - * To start with the first added element and walk towards the bottom, - * see WP_HTML_Open_Elements::walk_down(). - * - * @since 6.4.0 - * @since 6.5.0 Accepts $above_this_node to start traversal above a given node, if it exists. - * - * @param ?WP_HTML_Token $above_this_node Start traversing above this node, if provided and if the node exists. - */ - public function walk_up( $above_this_node = null ) { - $has_found_node = null === $above_this_node; - - for ( $i = count( $this->stack ) - 1; $i >= 0; $i-- ) { - $node = $this->stack[ $i ]; - - if ( ! $has_found_node ) { - $has_found_node = $node === $above_this_node; - continue; - } - - yield $node; - } - } - - /* - * Internal helpers. - */ - - /** - * Updates internal flags after adding an element. - * - * Certain conditions (such as "has_p_in_button_scope") are maintained here as - * flags that are only modified when adding and removing elements. This allows - * the HTML Processor to quickly check for these conditions instead of iterating - * over the open stack elements upon each new tag it encounters. These flags, - * however, need to be maintained as items are added and removed from the stack. - * - * @since 6.4.0 - * - * @param WP_HTML_Token $item Element that was added to the stack of open elements. - */ - public function after_element_push( $item ) { - /* - * When adding support for new elements, expand this switch to trap - * cases where the precalculated value needs to change. - */ - switch ( $item->node_name ) { - case 'BUTTON': - $this->has_p_in_button_scope = false; - break; - - case 'P': - $this->has_p_in_button_scope = true; - break; - } - - if ( null !== $this->push_handler ) { - ( $this->push_handler )( $item ); - } - } - - /** - * Updates internal flags after removing an element. - * - * Certain conditions (such as "has_p_in_button_scope") are maintained here as - * flags that are only modified when adding and removing elements. This allows - * the HTML Processor to quickly check for these conditions instead of iterating - * over the open stack elements upon each new tag it encounters. These flags, - * however, need to be maintained as items are added and removed from the stack. - * - * @since 6.4.0 - * - * @param WP_HTML_Token $item Element that was removed from the stack of open elements. - */ - public function after_element_pop( $item ) { - /* - * When adding support for new elements, expand this switch to trap - * cases where the precalculated value needs to change. - */ - switch ( $item->node_name ) { - case 'BUTTON': - $this->has_p_in_button_scope = $this->has_element_in_button_scope( 'P' ); - break; - - case 'P': - $this->has_p_in_button_scope = $this->has_element_in_button_scope( 'P' ); - break; - } - - if ( null !== $this->pop_handler ) { - ( $this->pop_handler )( $item ); - } - } - - /** - * Wakeup magic method. - * - * @since 6.6.0 - */ - public function __wakeup() { - throw new \LogicException( __CLASS__ . ' should never be unserialized' ); - } -} diff --git a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-6-6.php b/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-6-6.php deleted file mode 100644 index 77801535ff3683..00000000000000 --- a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-6-6.php +++ /dev/null @@ -1,2472 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Processor class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.4.0 - */ - -/** - * Core class used to safely parse and modify an HTML document. - * - * The HTML Processor class properly parses and modifies HTML5 documents. - * - * It supports a subset of the HTML5 specification, and when it encounters - * unsupported markup, it aborts early to avoid unintentionally breaking - * the document. The HTML Processor should never break an HTML document. - * - * While the `WP_HTML_Tag_Processor` is a valuable tool for modifying - * attributes on individual HTML tags, the HTML Processor is more capable - * and useful for the following operations: - * - * - Querying based on nested HTML structure. - * - * Eventually the HTML Processor will also support: - * - Wrapping a tag in surrounding HTML. - * - Unwrapping a tag by removing its parent. - * - Inserting and removing nodes. - * - Reading and changing inner content. - * - Navigating up or around HTML structure. - * - * ## Usage - * - * Use of this class requires three steps: - * - * 1. Call a static creator method with your input HTML document. - * 2. Find the location in the document you are looking for. - * 3. Request changes to the document at that location. - * - * Example: - * - * $processor = WP_HTML_Processor::create_fragment( $html ); - * if ( $processor->next_tag( array( 'breadcrumbs' => array( 'DIV', 'FIGURE', 'IMG' ) ) ) ) { - * $processor->add_class( 'responsive-image' ); - * } - * - * #### Breadcrumbs - * - * Breadcrumbs represent the stack of open elements from the root - * of the document or fragment down to the currently-matched node, - * if one is currently selected. Call WP_HTML_Processor::get_breadcrumbs() - * to inspect the breadcrumbs for a matched tag. - * - * Breadcrumbs can specify nested HTML structure and are equivalent - * to a CSS selector comprising tag names separated by the child - * combinator, such as "DIV > FIGURE > IMG". - * - * Since all elements find themselves inside a full HTML document - * when parsed, the return value from `get_breadcrumbs()` will always - * contain any implicit outermost elements. For example, when parsing - * with `create_fragment()` in the `BODY` context (the default), any - * tag in the given HTML document will contain `array( 'HTML', 'BODY', … )` - * in its breadcrumbs. - * - * Despite containing the implied outermost elements in their breadcrumbs, - * tags may be found with the shortest-matching breadcrumb query. That is, - * `array( 'IMG' )` matches all IMG elements and `array( 'P', 'IMG' )` - * matches all IMG elements directly inside a P element. To ensure that no - * partial matches erroneously match it's possible to specify in a query - * the full breadcrumb match all the way down from the root HTML element. - * - * Example: - * - * $html = '<figure><img><figcaption>A <em>lovely</em> day outside</figcaption></figure>'; - * // ----- Matches here. - * $processor->next_tag( array( 'breadcrumbs' => array( 'FIGURE', 'IMG' ) ) ); - * - * $html = '<figure><img><figcaption>A <em>lovely</em> day outside</figcaption></figure>'; - * // ---- Matches here. - * $processor->next_tag( array( 'breadcrumbs' => array( 'FIGURE', 'FIGCAPTION', 'EM' ) ) ); - * - * $html = '<div><img></div><img>'; - * // ----- Matches here, because IMG must be a direct child of the implicit BODY. - * $processor->next_tag( array( 'breadcrumbs' => array( 'BODY', 'IMG' ) ) ); - * - * ## HTML Support - * - * This class implements a small part of the HTML5 specification. - * It's designed to operate within its support and abort early whenever - * encountering circumstances it can't properly handle. This is - * the principle way in which this class remains as simple as possible - * without cutting corners and breaking compliance. - * - * ### Supported elements - * - * If any unsupported element appears in the HTML input the HTML Processor - * will abort early and stop all processing. This draconian measure ensures - * that the HTML Processor won't break any HTML it doesn't fully understand. - * - * The following list specifies the HTML tags that _are_ supported: - * - * - Containers: ADDRESS, BLOCKQUOTE, DETAILS, DIALOG, DIV, FOOTER, HEADER, MAIN, MENU, SPAN, SUMMARY. - * - Custom elements: All custom elements are supported. :) - * - Form elements: BUTTON, DATALIST, FIELDSET, INPUT, LABEL, LEGEND, METER, PROGRESS, SEARCH. - * - Formatting elements: B, BIG, CODE, EM, FONT, I, PRE, SMALL, STRIKE, STRONG, TT, U, WBR. - * - Heading elements: H1, H2, H3, H4, H5, H6, HGROUP. - * - Links: A. - * - Lists: DD, DL, DT, LI, OL, UL. - * - Media elements: AUDIO, CANVAS, EMBED, FIGCAPTION, FIGURE, IMG, MAP, PICTURE, SOURCE, TRACK, VIDEO. - * - Paragraph: BR, P. - * - Phrasing elements: ABBR, AREA, BDI, BDO, CITE, DATA, DEL, DFN, INS, MARK, OUTPUT, Q, SAMP, SUB, SUP, TIME, VAR. - * - Sectioning elements: ARTICLE, ASIDE, HR, NAV, SECTION. - * - Templating elements: SLOT. - * - Text decoration: RUBY. - * - Deprecated elements: ACRONYM, BLINK, CENTER, DIR, ISINDEX, KEYGEN, LISTING, MULTICOL, NEXTID, PARAM, SPACER. - * - * ### Supported markup - * - * Some kinds of non-normative HTML involve reconstruction of formatting elements and - * re-parenting of mis-nested elements. For example, a DIV tag found inside a TABLE - * may in fact belong _before_ the table in the DOM. If the HTML Processor encounters - * such a case it will stop processing. - * - * The following list specifies HTML markup that _is_ supported: - * - * - Markup involving only those tags listed above. - * - Fully-balanced and non-overlapping tags. - * - HTML with unexpected tag closers. - * - Some unbalanced or overlapping tags. - * - P tags after unclosed P tags. - * - BUTTON tags after unclosed BUTTON tags. - * - A tags after unclosed A tags that don't involve any active formatting elements. - * - * @since 6.4.0 - * - * @see WP_HTML_Tag_Processor - * @see https://html.spec.whatwg.org/ - */ -class Gutenberg_HTML_Processor_6_6 extends Gutenberg_HTML_Tag_Processor_6_6 { - /** - * The maximum number of bookmarks allowed to exist at any given time. - * - * HTML processing requires more bookmarks than basic tag processing, - * so this class constant from the Tag Processor is overwritten. - * - * @since 6.4.0 - * - * @var int - */ - const MAX_BOOKMARKS = 100; - - /** - * Holds the working state of the parser, including the stack of - * open elements and the stack of active formatting elements. - * - * Initialized in the constructor. - * - * @since 6.4.0 - * - * @var WP_HTML_Processor_State - */ - private $state = null; - - /** - * Used to create unique bookmark names. - * - * This class sets a bookmark for every tag in the HTML document that it encounters. - * The bookmark name is auto-generated and increments, starting with `1`. These are - * internal bookmarks and are automatically released when the referring WP_HTML_Token - * goes out of scope and is garbage-collected. - * - * @since 6.4.0 - * - * @see WP_HTML_Processor::$release_internal_bookmark_on_destruct - * - * @var int - */ - private $bookmark_counter = 0; - - /** - * Stores an explanation for why something failed, if it did. - * - * @see self::get_last_error - * - * @since 6.4.0 - * - * @var string|null - */ - private $last_error = null; - - /** - * Releases a bookmark when PHP garbage-collects its wrapping WP_HTML_Token instance. - * - * This function is created inside the class constructor so that it can be passed to - * the stack of open elements and the stack of active formatting elements without - * exposing it as a public method on the class. - * - * @since 6.4.0 - * - * @var closure - */ - private $release_internal_bookmark_on_destruct = null; - - /** - * Stores stack events which arise during parsing of the - * HTML document, which will then supply the "match" events. - * - * @since 6.6.0 - * - * @var WP_HTML_Stack_Event[] - */ - private $element_queue = array(); - - /** - * Current stack event, if set, representing a matched token. - * - * Because the parser may internally point to a place further along in a document - * than the nodes which have already been processed (some "virtual" nodes may have - * appeared while scanning the HTML document), this will point at the "current" node - * being processed. It comes from the front of the element queue. - * - * @since 6.6.0 - * - * @var ?WP_HTML_Stack_Event - */ - private $current_element = null; - - /** - * Context node if created as a fragment parser. - * - * @var ?WP_HTML_Token - */ - private $context_node = null; - - /** - * Whether the parser has yet processed the context node, - * if created as a fragment parser. - * - * The context node will be initially pushed onto the stack of open elements, - * but when created as a fragment parser, this context element (and the implicit - * HTML document node above it) should not be exposed as a matched token or node. - * - * This boolean indicates whether the processor should skip over the current - * node in its initial search for the first node created from the input HTML. - * - * @var bool - */ - private $has_seen_context_node = false; - - /* - * Public Interface Functions - */ - - /** - * Creates an HTML processor in the fragment parsing mode. - * - * Use this for cases where you are processing chunks of HTML that - * will be found within a bigger HTML document, such as rendered - * block output that exists within a post, `the_content` inside a - * rendered site layout. - * - * Fragment parsing occurs within a context, which is an HTML element - * that the document will eventually be placed in. It becomes important - * when special elements have different rules than others, such as inside - * a TEXTAREA or a TITLE tag where things that look like tags are text, - * or inside a SCRIPT tag where things that look like HTML syntax are JS. - * - * The context value should be a representation of the tag into which the - * HTML is found. For most cases this will be the body element. The HTML - * form is provided because a context element may have attributes that - * impact the parse, such as with a SCRIPT tag and its `type` attribute. - * - * ## Current HTML Support - * - * - The only supported context is `<body>`, which is the default value. - * - The only supported document encoding is `UTF-8`, which is the default value. - * - * @since 6.4.0 - * @since 6.6.0 Returns `static` instead of `self` so it can create subclass instances. - * - * @param string $html Input HTML fragment to process. - * @param string $context Context element for the fragment, must be default of `<body>`. - * @param string $encoding Text encoding of the document; must be default of 'UTF-8'. - * @return static|null The created processor if successful, otherwise null. - */ - public static function create_fragment( $html, $context = '<body>', $encoding = 'UTF-8' ) { - if ( '<body>' !== $context || 'UTF-8' !== $encoding ) { - return null; - } - - $processor = new static( $html, self::CONSTRUCTOR_UNLOCK_CODE ); - $processor->state->context_node = array( 'BODY', array() ); - $processor->state->insertion_mode = Gutenberg_HTML_Processor_State_6_6::INSERTION_MODE_IN_BODY; - - // @todo Create "fake" bookmarks for non-existent but implied nodes. - $processor->bookmarks['root-node'] = new WP_HTML_Span( 0, 0 ); - $processor->bookmarks['context-node'] = new WP_HTML_Span( 0, 0 ); - - $processor->state->stack_of_open_elements->push( - new WP_HTML_Token( - 'root-node', - 'HTML', - false - ) - ); - - $context_node = new WP_HTML_Token( - 'context-node', - $processor->state->context_node[0], - false - ); - - $processor->state->stack_of_open_elements->push( $context_node ); - $processor->context_node = $context_node; - - return $processor; - } - - /** - * Constructor. - * - * Do not use this method. Use the static creator methods instead. - * - * @access private - * - * @since 6.4.0 - * - * @see WP_HTML_Processor::create_fragment() - * - * @param string $html HTML to process. - * @param string|null $use_the_static_create_methods_instead This constructor should not be called manually. - */ - public function __construct( $html, $use_the_static_create_methods_instead = null ) { - parent::__construct( $html ); - - if ( self::CONSTRUCTOR_UNLOCK_CODE !== $use_the_static_create_methods_instead ) { - _doing_it_wrong( - __METHOD__, - sprintf( - /* translators: %s: WP_HTML_Processor::create_fragment(). */ - __( 'Call %s to create an HTML Processor instead of calling the constructor directly.' ), - '<code>WP_HTML_Processor::create_fragment()</code>' - ), - '6.4.0' - ); - } - - $this->state = new Gutenberg_HTML_Processor_State_6_6(); - - $this->state->stack_of_open_elements->set_push_handler( - function ( WP_HTML_Token $token ) { - $is_virtual = ! isset( $this->state->current_token ) || $this->is_tag_closer(); - $same_node = isset( $this->state->current_token ) && $token->node_name === $this->state->current_token->node_name; - $provenance = ( ! $same_node || $is_virtual ) ? 'virtual' : 'real'; - $this->element_queue[] = new Gutenberg_HTML_Stack_Event_6_6( $token, Gutenberg_HTML_Stack_Event_6_6::PUSH, $provenance ); - } - ); - - $this->state->stack_of_open_elements->set_pop_handler( - function ( WP_HTML_Token $token ) { - $is_virtual = ! isset( $this->state->current_token ) || ! $this->is_tag_closer(); - $same_node = isset( $this->state->current_token ) && $token->node_name === $this->state->current_token->node_name; - $provenance = ( ! $same_node || $is_virtual ) ? 'virtual' : 'real'; - $this->element_queue[] = new Gutenberg_HTML_Stack_Event_6_6( $token, Gutenberg_HTML_Stack_Event_6_6::POP, $provenance ); - } - ); - - /* - * Create this wrapper so that it's possible to pass - * a private method into WP_HTML_Token classes without - * exposing it to any public API. - */ - $this->release_internal_bookmark_on_destruct = function ( $name ) { - parent::release_bookmark( $name ); - }; - } - - /** - * Returns the last error, if any. - * - * Various situations lead to parsing failure but this class will - * return `false` in all those cases. To determine why something - * failed it's possible to request the last error. This can be - * helpful to know to distinguish whether a given tag couldn't - * be found or if content in the document caused the processor - * to give up and abort processing. - * - * Example - * - * $processor = WP_HTML_Processor::create_fragment( '<template><strong><button><em><p><em>' ); - * false === $processor->next_tag(); - * WP_HTML_Processor::ERROR_UNSUPPORTED === $processor->get_last_error(); - * - * @since 6.4.0 - * - * @see self::ERROR_UNSUPPORTED - * @see self::ERROR_EXCEEDED_MAX_BOOKMARKS - * - * @return string|null The last error, if one exists, otherwise null. - */ - public function get_last_error() { - return $this->last_error; - } - - /** - * Finds the next tag matching the $query. - * - * @todo Support matching the class name and tag name. - * - * @since 6.4.0 - * @since 6.6.0 Visits all tokens, including virtual ones. - * - * @throws Exception When unable to allocate a bookmark for the next token in the input HTML document. - * - * @param array|string|null $query { - * Optional. Which tag name to find, having which class, etc. Default is to find any tag. - * - * @type string|null $tag_name Which tag to find, or `null` for "any tag." - * @type string $tag_closers 'visit' to pause at tag closers, 'skip' or unset to only visit openers. - * @type int|null $match_offset Find the Nth tag matching all search criteria. - * 1 for "first" tag, 3 for "third," etc. - * Defaults to first tag. - * @type string|null $class_name Tag must contain this whole class name to match. - * @type string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. - * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. - * } - * @return bool Whether a tag was matched. - */ - public function next_tag( $query = null ) { - $visit_closers = isset( $query['tag_closers'] ) && 'visit' === $query['tag_closers']; - - if ( null === $query ) { - while ( $this->next_token() ) { - if ( '#tag' !== $this->get_token_type() ) { - continue; - } - - if ( ! $this->is_tag_closer() || $visit_closers ) { - return true; - } - } - - return false; - } - - if ( is_string( $query ) ) { - $query = array( 'breadcrumbs' => array( $query ) ); - } - - if ( ! is_array( $query ) ) { - _doing_it_wrong( - __METHOD__, - __( 'Please pass a query array to this function.' ), - '6.4.0' - ); - return false; - } - - $needs_class = ( isset( $query['class_name'] ) && is_string( $query['class_name'] ) ) - ? $query['class_name'] - : null; - - if ( ! ( array_key_exists( 'breadcrumbs', $query ) && is_array( $query['breadcrumbs'] ) ) ) { - while ( $this->next_token() ) { - if ( '#tag' !== $this->get_token_type() ) { - continue; - } - - if ( isset( $needs_class ) && ! $this->has_class( $needs_class ) ) { - continue; - } - - if ( ! $this->is_tag_closer() || $visit_closers ) { - return true; - } - } - - return false; - } - - $breadcrumbs = $query['breadcrumbs']; - $match_offset = isset( $query['match_offset'] ) ? (int) $query['match_offset'] : 1; - - while ( $match_offset > 0 && $this->next_token() ) { - if ( '#tag' !== $this->get_token_type() || $this->is_tag_closer() ) { - continue; - } - - if ( isset( $needs_class ) && ! $this->has_class( $needs_class ) ) { - continue; - } - - if ( $this->matches_breadcrumbs( $breadcrumbs ) && 0 === --$match_offset ) { - return true; - } - } - - return false; - } - - /** - * Ensures internal accounting is maintained for HTML semantic rules while - * the underlying Tag Processor class is seeking to a bookmark. - * - * This doesn't currently have a way to represent non-tags and doesn't process - * semantic rules for text nodes. For access to the raw tokens consider using - * WP_HTML_Tag_Processor instead. - * - * @since 6.5.0 Added for internal support; do not use. - * - * @access private - * - * @return bool - */ - public function next_token() { - $this->current_element = null; - - if ( isset( $this->last_error ) ) { - return false; - } - - if ( 'done' !== $this->has_seen_context_node && 0 === count( $this->element_queue ) && ! $this->step() ) { - while ( 'context-node' !== $this->state->stack_of_open_elements->current_node()->bookmark_name && $this->state->stack_of_open_elements->pop() ) { - continue; - } - $this->has_seen_context_node = 'done'; - return $this->next_token(); - } - - $this->current_element = array_shift( $this->element_queue ); - while ( isset( $this->context_node ) && ! $this->has_seen_context_node ) { - if ( isset( $this->current_element ) ) { - if ( $this->context_node === $this->current_element->token && Gutenberg_HTML_Stack_Event_6_6::PUSH === $this->current_element->operation ) { - $this->has_seen_context_node = true; - return $this->next_token(); - } - } - $this->current_element = array_shift( $this->element_queue ); - } - - if ( ! isset( $this->current_element ) ) { - if ( 'done' === $this->has_seen_context_node ) { - return false; - } else { - return $this->next_token(); - } - } - - if ( isset( $this->context_node ) && Gutenberg_HTML_Stack_Event_6_6::POP === $this->current_element->operation && $this->context_node === $this->current_element->token ) { - $this->element_queue = array(); - $this->current_element = null; - return false; - } - - // Avoid sending close events for elements which don't expect a closing. - if ( - Gutenberg_HTML_Stack_Event_6_6::POP === $this->current_element->operation && - ! static::expects_closer( $this->current_element->token ) - ) { - return $this->next_token(); - } - - return true; - } - - - /** - * Indicates if the current tag token is a tag closer. - * - * Example: - * - * $p = WP_HTML_Processor::create_fragment( '<div></div>' ); - * $p->next_tag( array( 'tag_name' => 'div', 'tag_closers' => 'visit' ) ); - * $p->is_tag_closer() === false; - * - * $p->next_tag( array( 'tag_name' => 'div', 'tag_closers' => 'visit' ) ); - * $p->is_tag_closer() === true; - * - * @since 6.6.0 Subclassed for HTML Processor. - * - * @return bool Whether the current tag is a tag closer. - */ - public function is_tag_closer() { - return $this->is_virtual() - ? ( Gutenberg_HTML_Stack_Event_6_6::POP === $this->current_element->operation && '#tag' === $this->get_token_type() ) - : parent::is_tag_closer(); - } - - /** - * Indicates if the currently-matched token is virtual, created by a stack operation - * while processing HTML, rather than a token found in the HTML text itself. - * - * @since 6.6.0 - * - * @return bool Whether the current token is virtual. - */ - private function is_virtual() { - return ( - isset( $this->current_element->provenance ) && - 'virtual' === $this->current_element->provenance - ); - } - - /** - * Indicates if the currently-matched tag matches the given breadcrumbs. - * - * A "*" represents a single tag wildcard, where any tag matches, but not no tags. - * - * At some point this function _may_ support a `**` syntax for matching any number - * of unspecified tags in the breadcrumb stack. This has been intentionally left - * out, however, to keep this function simple and to avoid introducing backtracking, - * which could open up surprising performance breakdowns. - * - * Example: - * - * $processor = WP_HTML_Processor::create_fragment( '<div><span><figure><img></figure></span></div>' ); - * $processor->next_tag( 'img' ); - * true === $processor->matches_breadcrumbs( array( 'figure', 'img' ) ); - * true === $processor->matches_breadcrumbs( array( 'span', 'figure', 'img' ) ); - * false === $processor->matches_breadcrumbs( array( 'span', 'img' ) ); - * true === $processor->matches_breadcrumbs( array( 'span', '*', 'img' ) ); - * - * @since 6.4.0 - * - * @param string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. - * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. - * @return bool Whether the currently-matched tag is found at the given nested structure. - */ - public function matches_breadcrumbs( $breadcrumbs ) { - // Everything matches when there are zero constraints. - if ( 0 === count( $breadcrumbs ) ) { - return true; - } - - // Start at the last crumb. - $crumb = end( $breadcrumbs ); - - if ( '*' !== $crumb && $this->get_tag() !== strtoupper( $crumb ) ) { - return false; - } - - foreach ( $this->state->stack_of_open_elements->walk_up() as $node ) { - $crumb = strtoupper( current( $breadcrumbs ) ); - - if ( '*' !== $crumb && $node->node_name !== $crumb ) { - return false; - } - - if ( false === prev( $breadcrumbs ) ) { - return true; - } - } - - return false; - } - - /** - * Indicates if the currently-matched node expects a closing - * token, or if it will self-close on the next step. - * - * Most HTML elements expect a closer, such as a P element or - * a DIV element. Others, like an IMG element are void and don't - * have a closing tag. Special elements, such as SCRIPT and STYLE, - * are treated just like void tags. Text nodes and self-closing - * foreign content will also act just like a void tag, immediately - * closing as soon as the processor advances to the next token. - * - * @since 6.6.0 - * - * @todo When adding support for foreign content, ensure that - * this returns false for self-closing elements in the - * SVG and MathML namespace. - * - * @param ?WP_HTML_Token $node Node to examine instead of current node, if provided. - * @return bool Whether to expect a closer for the currently-matched node, - * or `null` if not matched on any token. - */ - public function expects_closer( $node = null ) { - $token_name = $node->node_name ?? $this->get_token_name(); - if ( ! isset( $token_name ) ) { - return null; - } - - return ! ( - // Comments, text nodes, and other atomic tokens. - '#' === $token_name[0] || - // Doctype declarations. - 'html' === $token_name || - // Void elements. - self::is_void( $token_name ) || - // Special atomic elements. - in_array( $token_name, array( 'IFRAME', 'NOEMBED', 'NOFRAMES', 'SCRIPT', 'STYLE', 'TEXTAREA', 'TITLE', 'XMP' ), true ) - ); - } - - /** - * Steps through the HTML document and stop at the next tag, if any. - * - * @since 6.4.0 - * - * @throws Exception When unable to allocate a bookmark for the next token in the input HTML document. - * - * @see self::PROCESS_NEXT_NODE - * @see self::REPROCESS_CURRENT_NODE - * - * @param string $node_to_process Whether to parse the next node or reprocess the current node. - * @return bool Whether a tag was matched. - */ - public function step( $node_to_process = self::PROCESS_NEXT_NODE ) { - // Refuse to proceed if there was a previous error. - if ( null !== $this->last_error ) { - return false; - } - - if ( self::REPROCESS_CURRENT_NODE !== $node_to_process ) { - /* - * Void elements still hop onto the stack of open elements even though - * there's no corresponding closing tag. This is important for managing - * stack-based operations such as "navigate to parent node" or checking - * on an element's breadcrumbs. - * - * When moving on to the next node, therefore, if the bottom-most element - * on the stack is a void element, it must be closed. - * - * @todo Once self-closing foreign elements and BGSOUND are supported, - * they must also be implicitly closed here too. BGSOUND is - * special since it's only self-closing if the self-closing flag - * is provided in the opening tag, otherwise it expects a tag closer. - */ - $top_node = $this->state->stack_of_open_elements->current_node(); - if ( isset( $top_node ) && ! static::expects_closer( $top_node ) ) { - $this->state->stack_of_open_elements->pop(); - } - } - - if ( self::PROCESS_NEXT_NODE === $node_to_process ) { - parent::next_token(); - } - - // Finish stepping when there are no more tokens in the document. - if ( - Gutenberg_HTML_Tag_Processor_6_6::STATE_INCOMPLETE_INPUT === $this->parser_state || - Gutenberg_HTML_Tag_Processor_6_6::STATE_COMPLETE === $this->parser_state - ) { - return false; - } - - $this->state->current_token = new WP_HTML_Token( - $this->bookmark_token(), - $this->get_token_name(), - $this->has_self_closing_flag(), - $this->release_internal_bookmark_on_destruct - ); - - try { - switch ( $this->state->insertion_mode ) { - case Gutenberg_HTML_Processor_State_6_6::INSERTION_MODE_IN_BODY: - return $this->step_in_body(); - - default: - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." ); - } - } catch ( WP_HTML_Unsupported_Exception $e ) { - /* - * Exceptions are used in this class to escape deep call stacks that - * otherwise might involve messier calling and return conventions. - */ - return false; - } - } - - /** - * Computes the HTML breadcrumbs for the currently-matched node, if matched. - * - * Breadcrumbs start at the outermost parent and descend toward the matched element. - * They always include the entire path from the root HTML node to the matched element. - * - * @todo It could be more efficient to expose a generator-based version of this function - * to avoid creating the array copy on tag iteration. If this is done, it would likely - * be more useful to walk up the stack when yielding instead of starting at the top. - * - * Example - * - * $processor = WP_HTML_Processor::create_fragment( '<p><strong><em><img></em></strong></p>' ); - * $processor->next_tag( 'IMG' ); - * $processor->get_breadcrumbs() === array( 'HTML', 'BODY', 'P', 'STRONG', 'EM', 'IMG' ); - * - * @since 6.4.0 - * - * @return string[]|null Array of tag names representing path to matched node, if matched, otherwise NULL. - */ - public function get_breadcrumbs() { - $breadcrumbs = array(); - - foreach ( $this->state->stack_of_open_elements->walk_down() as $stack_item ) { - $breadcrumbs[] = $stack_item->node_name; - } - - if ( ! $this->is_virtual() ) { - return $breadcrumbs; - } - - foreach ( $this->element_queue as $queue_item ) { - if ( $this->current_element->token->bookmark_name === $queue_item->token->bookmark_name ) { - break; - } - - if ( 'context-node' === $queue_item->token->bookmark_name ) { - break; - } - - if ( 'real' === $queue_item->provenance ) { - break; - } - - if ( Gutenberg_HTML_Stack_Event_6_6::PUSH === $queue_item->operation ) { - $breadcrumbs[] = $queue_item->token->node_name; - } else { - array_pop( $breadcrumbs ); - } - } - - if ( null !== parent::get_token_name() && ! parent::is_tag_closer() ) { - array_pop( $breadcrumbs ); - } - - // Add the virtual node we're at. - if ( Gutenberg_HTML_Stack_Event_6_6::PUSH === $this->current_element->operation ) { - $breadcrumbs[] = $this->current_element->token->node_name; - } - - return $breadcrumbs; - } - - /** - * Returns the nesting depth of the current location in the document. - * - * Example: - * - * $processor = WP_HTML_Processor::create_fragment( '<div><p></p></div>' ); - * // The processor starts in the BODY context, meaning it has depth from the start: HTML > BODY. - * 2 === $processor->get_current_depth(); - * - * // Opening the DIV element increases the depth. - * $processor->next_token(); - * 3 === $processor->get_current_depth(); - * - * // Opening the P element increases the depth. - * $processor->next_token(); - * 4 === $processor->get_current_depth(); - * - * // The P element is closed during `next_token()` so the depth is decreased to reflect that. - * $processor->next_token(); - * 3 === $processor->get_current_depth(); - * - * @since 6.6.0 - * - * @return int Nesting-depth of current location in the document. - */ - public function get_current_depth() { - return $this->is_virtual() - ? count( $this->get_breadcrumbs() ) - : $this->state->stack_of_open_elements->count(); - } - - /** - * Parses next element in the 'in body' insertion mode. - * - * This internal function performs the 'in body' insertion mode - * logic for the generalized WP_HTML_Processor::step() function. - * - * @since 6.4.0 - * - * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. - * - * @see https://html.spec.whatwg.org/#parsing-main-inbody - * @see WP_HTML_Processor::step - * - * @return bool Whether an element was found. - */ - private function step_in_body() { - $token_name = $this->get_token_name(); - $token_type = $this->get_token_type(); - $op_sigil = '#tag' === $token_type ? ( parent::is_tag_closer() ? '-' : '+' ) : ''; - $op = "{$op_sigil}{$token_name}"; - - switch ( $op ) { - case '#comment': - case '#funky-comment': - case '#presumptuous-tag': - $this->insert_html_element( $this->state->current_token ); - return true; - - case '#text': - $this->reconstruct_active_formatting_elements(); - - $current_token = $this->bookmarks[ $this->state->current_token->bookmark_name ]; - - /* - * > A character token that is U+0000 NULL - * - * Any successive sequence of NULL bytes is ignored and won't - * trigger active format reconstruction. Therefore, if the text - * only comprises NULL bytes then the token should be ignored - * here, but if there are any other characters in the stream - * the active formats should be reconstructed. - */ - if ( - 1 <= $current_token->length && - "\x00" === $this->html[ $current_token->start ] && - strspn( $this->html, "\x00", $current_token->start, $current_token->length ) === $current_token->length - ) { - // Parse error: ignore the token. - return $this->step(); - } - - /* - * Whitespace-only text does not affect the frameset-ok flag. - * It is probably inter-element whitespace, but it may also - * contain character references which decode only to whitespace. - */ - $text = $this->get_modifiable_text(); - if ( strlen( $text ) !== strspn( $text, " \t\n\f\r" ) ) { - $this->state->frameset_ok = false; - } - - $this->insert_html_element( $this->state->current_token ); - return true; - - case 'html': - /* - * > A DOCTYPE token - * > Parse error. Ignore the token. - */ - return $this->step(); - - /* - * > A start tag whose tag name is "button" - */ - case '+BUTTON': - if ( $this->state->stack_of_open_elements->has_element_in_scope( 'BUTTON' ) ) { - // @todo Indicate a parse error once it's possible. This error does not impact the logic here. - $this->generate_implied_end_tags(); - $this->state->stack_of_open_elements->pop_until( 'BUTTON' ); - } - - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - $this->state->frameset_ok = false; - - return true; - - /* - * > A start tag whose tag name is one of: "address", "article", "aside", - * > "blockquote", "center", "details", "dialog", "dir", "div", "dl", - * > "fieldset", "figcaption", "figure", "footer", "header", "hgroup", - * > "main", "menu", "nav", "ol", "p", "search", "section", "summary", "ul" - */ - case '+ADDRESS': - case '+ARTICLE': - case '+ASIDE': - case '+BLOCKQUOTE': - case '+CENTER': - case '+DETAILS': - case '+DIALOG': - case '+DIR': - case '+DIV': - case '+DL': - case '+FIELDSET': - case '+FIGCAPTION': - case '+FIGURE': - case '+FOOTER': - case '+HEADER': - case '+HGROUP': - case '+MAIN': - case '+MENU': - case '+NAV': - case '+OL': - case '+P': - case '+SEARCH': - case '+SECTION': - case '+SUMMARY': - case '+UL': - if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { - $this->close_a_p_element(); - } - - $this->insert_html_element( $this->state->current_token ); - return true; - - /* - * > An end tag whose tag name is one of: "address", "article", "aside", "blockquote", - * > "button", "center", "details", "dialog", "dir", "div", "dl", "fieldset", - * > "figcaption", "figure", "footer", "header", "hgroup", "listing", "main", - * > "menu", "nav", "ol", "pre", "search", "section", "summary", "ul" - */ - case '-ADDRESS': - case '-ARTICLE': - case '-ASIDE': - case '-BLOCKQUOTE': - case '-BUTTON': - case '-CENTER': - case '-DETAILS': - case '-DIALOG': - case '-DIR': - case '-DIV': - case '-DL': - case '-FIELDSET': - case '-FIGCAPTION': - case '-FIGURE': - case '-FOOTER': - case '-HEADER': - case '-HGROUP': - case '-LISTING': - case '-MAIN': - case '-MENU': - case '-NAV': - case '-OL': - case '-PRE': - case '-SEARCH': - case '-SECTION': - case '-SUMMARY': - case '-UL': - if ( ! $this->state->stack_of_open_elements->has_element_in_scope( $token_name ) ) { - // @todo Report parse error. - // Ignore the token. - return $this->step(); - } - - $this->generate_implied_end_tags(); - if ( $this->state->stack_of_open_elements->current_node()->node_name !== $token_name ) { - // @todo Record parse error: this error doesn't impact parsing. - } - $this->state->stack_of_open_elements->pop_until( $token_name ); - return true; - - /* - * > A start tag whose tag name is one of: "h1", "h2", "h3", "h4", "h5", "h6" - */ - case '+H1': - case '+H2': - case '+H3': - case '+H4': - case '+H5': - case '+H6': - if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { - $this->close_a_p_element(); - } - - if ( - in_array( - $this->state->stack_of_open_elements->current_node()->node_name, - array( 'H1', 'H2', 'H3', 'H4', 'H5', 'H6' ), - true - ) - ) { - // @todo Indicate a parse error once it's possible. - $this->state->stack_of_open_elements->pop(); - } - - $this->insert_html_element( $this->state->current_token ); - return true; - - /* - * > A start tag whose tag name is one of: "pre", "listing" - */ - case '+PRE': - case '+LISTING': - if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { - $this->close_a_p_element(); - } - $this->insert_html_element( $this->state->current_token ); - $this->state->frameset_ok = false; - return true; - - /* - * > An end tag whose tag name is one of: "h1", "h2", "h3", "h4", "h5", "h6" - */ - case '-H1': - case '-H2': - case '-H3': - case '-H4': - case '-H5': - case '-H6': - if ( ! $this->state->stack_of_open_elements->has_element_in_scope( '(internal: H1 through H6 - do not use)' ) ) { - /* - * This is a parse error; ignore the token. - * - * @todo Indicate a parse error once it's possible. - */ - return $this->step(); - } - - $this->generate_implied_end_tags(); - - if ( $this->state->stack_of_open_elements->current_node()->node_name !== $token_name ) { - // @todo Record parse error: this error doesn't impact parsing. - } - - $this->state->stack_of_open_elements->pop_until( '(internal: H1 through H6 - do not use)' ); - return true; - - /* - * > A start tag whose tag name is "li" - * > A start tag whose tag name is one of: "dd", "dt" - */ - case '+DD': - case '+DT': - case '+LI': - $this->state->frameset_ok = false; - $node = $this->state->stack_of_open_elements->current_node(); - $is_li = 'LI' === $token_name; - - in_body_list_loop: - /* - * The logic for LI and DT/DD is the same except for one point: LI elements _only_ - * close other LI elements, but a DT or DD element closes _any_ open DT or DD element. - */ - if ( $is_li ? 'LI' === $node->node_name : ( 'DD' === $node->node_name || 'DT' === $node->node_name ) ) { - $node_name = $is_li ? 'LI' : $node->node_name; - $this->generate_implied_end_tags( $node_name ); - if ( $node_name !== $this->state->stack_of_open_elements->current_node()->node_name ) { - // @todo Indicate a parse error once it's possible. This error does not impact the logic here. - } - - $this->state->stack_of_open_elements->pop_until( $node_name ); - goto in_body_list_done; - } - - if ( - 'ADDRESS' !== $node->node_name && - 'DIV' !== $node->node_name && - 'P' !== $node->node_name && - $this->is_special( $node->node_name ) - ) { - /* - * > If node is in the special category, but is not an address, div, - * > or p element, then jump to the step labeled done below. - */ - goto in_body_list_done; - } else { - /* - * > Otherwise, set node to the previous entry in the stack of open elements - * > and return to the step labeled loop. - */ - foreach ( $this->state->stack_of_open_elements->walk_up( $node ) as $item ) { - $node = $item; - break; - } - goto in_body_list_loop; - } - - in_body_list_done: - if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { - $this->close_a_p_element(); - } - - $this->insert_html_element( $this->state->current_token ); - return true; - - /* - * > An end tag whose tag name is "li" - * > An end tag whose tag name is one of: "dd", "dt" - */ - case '-DD': - case '-DT': - case '-LI': - if ( - /* - * An end tag whose tag name is "li": - * If the stack of open elements does not have an li element in list item scope, - * then this is a parse error; ignore the token. - */ - ( - 'LI' === $token_name && - ! $this->state->stack_of_open_elements->has_element_in_list_item_scope( 'LI' ) - ) || - /* - * An end tag whose tag name is one of: "dd", "dt": - * If the stack of open elements does not have an element in scope that is an - * HTML element with the same tag name as that of the token, then this is a - * parse error; ignore the token. - */ - ( - 'LI' !== $token_name && - ! $this->state->stack_of_open_elements->has_element_in_scope( $token_name ) - ) - ) { - /* - * This is a parse error, ignore the token. - * - * @todo Indicate a parse error once it's possible. - */ - return $this->step(); - } - - $this->generate_implied_end_tags( $token_name ); - - if ( $token_name !== $this->state->stack_of_open_elements->current_node()->node_name ) { - // @todo Indicate a parse error once it's possible. This error does not impact the logic here. - } - - $this->state->stack_of_open_elements->pop_until( $token_name ); - return true; - - /* - * > An end tag whose tag name is "p" - */ - case '-P': - if ( ! $this->state->stack_of_open_elements->has_p_in_button_scope() ) { - $this->insert_html_element( $this->state->current_token ); - } - - $this->close_a_p_element(); - return true; - - // > A start tag whose tag name is "a" - case '+A': - foreach ( $this->state->active_formatting_elements->walk_up() as $item ) { - switch ( $item->node_name ) { - case 'marker': - break; - - case 'A': - $this->run_adoption_agency_algorithm(); - $this->state->active_formatting_elements->remove_node( $item ); - $this->state->stack_of_open_elements->remove_node( $item ); - break; - } - } - - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - $this->state->active_formatting_elements->push( $this->state->current_token ); - return true; - - /* - * > A start tag whose tag name is one of: "b", "big", "code", "em", "font", "i", - * > "s", "small", "strike", "strong", "tt", "u" - */ - case '+B': - case '+BIG': - case '+CODE': - case '+EM': - case '+FONT': - case '+I': - case '+S': - case '+SMALL': - case '+STRIKE': - case '+STRONG': - case '+TT': - case '+U': - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - $this->state->active_formatting_elements->push( $this->state->current_token ); - return true; - - /* - * > An end tag whose tag name is one of: "a", "b", "big", "code", "em", "font", "i", - * > "nobr", "s", "small", "strike", "strong", "tt", "u" - */ - case '-A': - case '-B': - case '-BIG': - case '-CODE': - case '-EM': - case '-FONT': - case '-I': - case '-S': - case '-SMALL': - case '-STRIKE': - case '-STRONG': - case '-TT': - case '-U': - $this->run_adoption_agency_algorithm(); - return true; - - /* - * > An end tag whose tag name is "br" - * > Parse error. Drop the attributes from the token, and act as described in the next - * > entry; i.e. act as if this was a "br" start tag token with no attributes, rather - * > than the end tag token that it actually is. - */ - case '-BR': - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( 'Closing BR tags require unimplemented special handling.' ); - - /* - * > A start tag whose tag name is one of: "area", "br", "embed", "img", "keygen", "wbr" - */ - case '+AREA': - case '+BR': - case '+EMBED': - case '+IMG': - case '+KEYGEN': - case '+WBR': - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - $this->state->frameset_ok = false; - return true; - - /* - * > A start tag whose tag name is "input" - */ - case '+INPUT': - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - $type_attribute = $this->get_attribute( 'type' ); - /* - * > If the token does not have an attribute with the name "type", or if it does, - * > but that attribute's value is not an ASCII case-insensitive match for the - * > string "hidden", then: set the frameset-ok flag to "not ok". - */ - if ( ! is_string( $type_attribute ) || 'hidden' !== strtolower( $type_attribute ) ) { - $this->state->frameset_ok = false; - } - return true; - - /* - * > A start tag whose tag name is "hr" - */ - case '+HR': - if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) { - $this->close_a_p_element(); - } - $this->insert_html_element( $this->state->current_token ); - $this->state->frameset_ok = false; - return true; - - /* - * > A start tag whose tag name is one of: "param", "source", "track" - */ - case '+PARAM': - case '+SOURCE': - case '+TRACK': - $this->insert_html_element( $this->state->current_token ); - return true; - } - - /* - * These tags require special handling in the 'in body' insertion mode - * but that handling hasn't yet been implemented. - * - * As the rules for each tag are implemented, the corresponding tag - * name should be removed from this list. An accompanying test should - * help ensure this list is maintained. - * - * @see Tests_HtmlApi_WpHtmlProcessor::test_step_in_body_fails_on_unsupported_tags - * - * Since this switch structure throws a WP_HTML_Unsupported_Exception, it's - * possible to handle "any other start tag" and "any other end tag" below, - * as that guarantees execution doesn't proceed for the unimplemented tags. - * - * @see https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inbody - */ - switch ( $token_name ) { - case 'APPLET': - case 'BASE': - case 'BASEFONT': - case 'BGSOUND': - case 'BODY': - case 'CAPTION': - case 'COL': - case 'COLGROUP': - case 'FORM': - case 'FRAME': - case 'FRAMESET': - case 'HEAD': - case 'HTML': - case 'IFRAME': - case 'LINK': - case 'MARQUEE': - case 'MATH': - case 'META': - case 'NOBR': - case 'NOEMBED': - case 'NOFRAMES': - case 'NOSCRIPT': - case 'OBJECT': - case 'OPTGROUP': - case 'OPTION': - case 'PLAINTEXT': - case 'RB': - case 'RP': - case 'RT': - case 'RTC': - case 'SARCASM': - case 'SCRIPT': - case 'SELECT': - case 'STYLE': - case 'SVG': - case 'TABLE': - case 'TBODY': - case 'TD': - case 'TEMPLATE': - case 'TEXTAREA': - case 'TFOOT': - case 'TH': - case 'THEAD': - case 'TITLE': - case 'TR': - case 'XMP': - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( "Cannot process {$token_name} element." ); - } - - if ( ! parent::is_tag_closer() ) { - /* - * > Any other start tag - */ - $this->reconstruct_active_formatting_elements(); - $this->insert_html_element( $this->state->current_token ); - return true; - } else { - /* - * > Any other end tag - */ - - /* - * Find the corresponding tag opener in the stack of open elements, if - * it exists before reaching a special element, which provides a kind - * of boundary in the stack. For example, a `</custom-tag>` should not - * close anything beyond its containing `P` or `DIV` element. - */ - foreach ( $this->state->stack_of_open_elements->walk_up() as $node ) { - if ( $token_name === $node->node_name ) { - break; - } - - if ( self::is_special( $node->node_name ) ) { - // This is a parse error, ignore the token. - return $this->step(); - } - } - - $this->generate_implied_end_tags( $token_name ); - if ( $node !== $this->state->stack_of_open_elements->current_node() ) { - // @todo Record parse error: this error doesn't impact parsing. - } - - foreach ( $this->state->stack_of_open_elements->walk_up() as $item ) { - $this->state->stack_of_open_elements->pop(); - if ( $node === $item ) { - return true; - } - } - } - } - - /* - * Internal helpers - */ - - /** - * Creates a new bookmark for the currently-matched token and returns the generated name. - * - * @since 6.4.0 - * @since 6.5.0 Renamed from bookmark_tag() to bookmark_token(). - * - * @throws Exception When unable to allocate requested bookmark. - * - * @return string|false Name of created bookmark, or false if unable to create. - */ - private function bookmark_token() { - if ( ! parent::set_bookmark( ++$this->bookmark_counter ) ) { - $this->last_error = self::ERROR_EXCEEDED_MAX_BOOKMARKS; - throw new Exception( 'could not allocate bookmark' ); - } - - return "{$this->bookmark_counter}"; - } - - /* - * HTML semantic overrides for Tag Processor - */ - - /** - * Returns the uppercase name of the matched tag. - * - * The semantic rules for HTML specify that certain tags be reprocessed - * with a different tag name. Because of this, the tag name presented - * by the HTML Processor may differ from the one reported by the HTML - * Tag Processor, which doesn't apply these semantic rules. - * - * Example: - * - * $processor = new WP_HTML_Tag_Processor( '<div class="test">Test</div>' ); - * $processor->next_tag() === true; - * $processor->get_tag() === 'DIV'; - * - * $processor->next_tag() === false; - * $processor->get_tag() === null; - * - * @since 6.4.0 - * - * @return string|null Name of currently matched tag in input HTML, or `null` if none found. - */ - public function get_tag() { - if ( null !== $this->last_error ) { - return null; - } - - if ( $this->is_virtual() ) { - return $this->current_element->token->node_name; - } - - $tag_name = parent::get_tag(); - - switch ( $tag_name ) { - case 'IMAGE': - /* - * > A start tag whose tag name is "image" - * > Change the token's tag name to "img" and reprocess it. (Don't ask.) - */ - return 'IMG'; - - default: - return $tag_name; - } - } - - /** - * Indicates if the currently matched tag contains the self-closing flag. - * - * No HTML elements ought to have the self-closing flag and for those, the self-closing - * flag will be ignored. For void elements this is benign because they "self close" - * automatically. For non-void HTML elements though problems will appear if someone - * intends to use a self-closing element in place of that element with an empty body. - * For HTML foreign elements and custom elements the self-closing flag determines if - * they self-close or not. - * - * This function does not determine if a tag is self-closing, - * but only if the self-closing flag is present in the syntax. - * - * @since 6.6.0 Subclassed for the HTML Processor. - * - * @return bool Whether the currently matched tag contains the self-closing flag. - */ - public function has_self_closing_flag() { - return $this->is_virtual() ? false : parent::has_self_closing_flag(); - } - - /** - * Returns the node name represented by the token. - * - * This matches the DOM API value `nodeName`. Some values - * are static, such as `#text` for a text node, while others - * are dynamically generated from the token itself. - * - * Dynamic names: - * - Uppercase tag name for tag matches. - * - `html` for DOCTYPE declarations. - * - * Note that if the Tag Processor is not matched on a token - * then this function will return `null`, either because it - * hasn't yet found a token or because it reached the end - * of the document without matching a token. - * - * @since 6.6.0 Subclassed for the HTML Processor. - * - * @return string|null Name of the matched token. - */ - public function get_token_name() { - return $this->is_virtual() - ? $this->current_element->token->node_name - : parent::get_token_name(); - } - - /** - * Indicates the kind of matched token, if any. - * - * This differs from `get_token_name()` in that it always - * returns a static string indicating the type, whereas - * `get_token_name()` may return values derived from the - * token itself, such as a tag name or processing - * instruction tag. - * - * Possible values: - * - `#tag` when matched on a tag. - * - `#text` when matched on a text node. - * - `#cdata-section` when matched on a CDATA node. - * - `#comment` when matched on a comment. - * - `#doctype` when matched on a DOCTYPE declaration. - * - `#presumptuous-tag` when matched on an empty tag closer. - * - `#funky-comment` when matched on a funky comment. - * - * @since 6.6.0 Subclassed for the HTML Processor. - * - * @return string|null What kind of token is matched, or null. - */ - public function get_token_type() { - if ( $this->is_virtual() ) { - /* - * This logic comes from the Tag Processor. - * - * @todo It would be ideal not to repeat this here, but it's not clearly - * better to allow passing a token name to `get_token_type()`. - */ - $node_name = $this->current_element->token->node_name; - $starting_char = $node_name[0]; - if ( 'A' <= $starting_char && 'Z' >= $starting_char ) { - return '#tag'; - } - - if ( 'html' === $node_name ) { - return '#doctype'; - } - - return $node_name; - } - - return parent::get_token_type(); - } - - /** - * Returns the value of a requested attribute from a matched tag opener if that attribute exists. - * - * Example: - * - * $p = WP_HTML_Processor::create_fragment( '<div enabled class="test" data-test-id="14">Test</div>' ); - * $p->next_token() === true; - * $p->get_attribute( 'data-test-id' ) === '14'; - * $p->get_attribute( 'enabled' ) === true; - * $p->get_attribute( 'aria-label' ) === null; - * - * $p->next_tag() === false; - * $p->get_attribute( 'class' ) === null; - * - * @since 6.6.0 Subclassed for HTML Processor. - * - * @param string $name Name of attribute whose value is requested. - * @return string|true|null Value of attribute or `null` if not available. Boolean attributes return `true`. - */ - public function get_attribute( $name ) { - return $this->is_virtual() ? null : parent::get_attribute( $name ); - } - - /** - * Updates or creates a new attribute on the currently matched tag with the passed value. - * - * For boolean attributes special handling is provided: - * - When `true` is passed as the value, then only the attribute name is added to the tag. - * - When `false` is passed, the attribute gets removed if it existed before. - * - * For string attributes, the value is escaped using the `esc_attr` function. - * - * @since 6.6.0 Subclassed for the HTML Processor. - * - * @param string $name The attribute name to target. - * @param string|bool $value The new attribute value. - * @return bool Whether an attribute value was set. - */ - public function set_attribute( $name, $value ) { - return $this->is_virtual() ? false : parent::set_attribute( $name, $value ); - } - - /** - * Remove an attribute from the currently-matched tag. - * - * @since 6.6.0 Subclassed for HTML Processor. - * - * @param string $name The attribute name to remove. - * @return bool Whether an attribute was removed. - */ - public function remove_attribute( $name ) { - return $this->is_virtual() ? false : parent::remove_attribute( $name ); - } - - /** - * Gets lowercase names of all attributes matching a given prefix in the current tag. - * - * Note that matching is case-insensitive. This is in accordance with the spec: - * - * > There must never be two or more attributes on - * > the same start tag whose names are an ASCII - * > case-insensitive match for each other. - * - HTML 5 spec - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( '<div data-ENABLED class="test" DATA-test-id="14">Test</div>' ); - * $p->next_tag( array( 'class_name' => 'test' ) ) === true; - * $p->get_attribute_names_with_prefix( 'data-' ) === array( 'data-enabled', 'data-test-id' ); - * - * $p->next_tag() === false; - * $p->get_attribute_names_with_prefix( 'data-' ) === null; - * - * @since 6.6.0 Subclassed for the HTML Processor. - * - * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive - * - * @param string $prefix Prefix of requested attribute names. - * @return array|null List of attribute names, or `null` when no tag opener is matched. - */ - public function get_attribute_names_with_prefix( $prefix ) { - return $this->is_virtual() ? null : parent::get_attribute_names_with_prefix( $prefix ); - } - - /** - * Adds a new class name to the currently matched tag. - * - * @since 6.6.0 Subclassed for the HTML Processor. - * - * @param string $class_name The class name to add. - * @return bool Whether the class was set to be added. - */ - public function add_class( $class_name ) { - return $this->is_virtual() ? false : parent::add_class( $class_name ); - } - - /** - * Removes a class name from the currently matched tag. - * - * @since 6.6.0 Subclassed for the HTML Processor. - * - * @param string $class_name The class name to remove. - * @return bool Whether the class was set to be removed. - */ - public function remove_class( $class_name ) { - return $this->is_virtual() ? false : parent::remove_class( $class_name ); - } - - /** - * Returns if a matched tag contains the given ASCII case-insensitive class name. - * - * @since 6.6.0 Subclassed for the HTML Processor. - * - * @param string $wanted_class Look for this CSS class name, ASCII case-insensitive. - * @return bool|null Whether the matched tag contains the given class name, or null if not matched. - */ - public function has_class( $wanted_class ) { - return $this->is_virtual() ? null : parent::has_class( $wanted_class ); - } - - /** - * Generator for a foreach loop to step through each class name for the matched tag. - * - * This generator function is designed to be used inside a "foreach" loop. - * - * Example: - * - * $p = WP_HTML_Processor::create_fragment( "<div class='free <egg<\tlang-en'>" ); - * $p->next_tag(); - * foreach ( $p->class_list() as $class_name ) { - * echo "{$class_name} "; - * } - * // Outputs: "free <egg> lang-en " - * - * @since 6.6.0 Subclassed for the HTML Processor. - */ - public function class_list() { - return $this->is_virtual() ? null : parent::class_list(); - } - - /** - * Returns the modifiable text for a matched token, or an empty string. - * - * Modifiable text is text content that may be read and changed without - * changing the HTML structure of the document around it. This includes - * the contents of `#text` nodes in the HTML as well as the inner - * contents of HTML comments, Processing Instructions, and others, even - * though these nodes aren't part of a parsed DOM tree. They also contain - * the contents of SCRIPT and STYLE tags, of TEXTAREA tags, and of any - * other section in an HTML document which cannot contain HTML markup (DATA). - * - * If a token has no modifiable text then an empty string is returned to - * avoid needless crashing or type errors. An empty string does not mean - * that a token has modifiable text, and a token with modifiable text may - * have an empty string (e.g. a comment with no contents). - * - * @since 6.6.0 Subclassed for the HTML Processor. - * - * @return string - */ - public function get_modifiable_text() { - return $this->is_virtual() ? '' : parent::get_modifiable_text(); - } - - /** - * Indicates what kind of comment produced the comment node. - * - * Because there are different kinds of HTML syntax which produce - * comments, the Tag Processor tracks and exposes this as a type - * for the comment. Nominally only regular HTML comments exist as - * they are commonly known, but a number of unrelated syntax errors - * also produce comments. - * - * @see self::COMMENT_AS_ABRUPTLY_CLOSED_COMMENT - * @see self::COMMENT_AS_CDATA_LOOKALIKE - * @see self::COMMENT_AS_INVALID_HTML - * @see self::COMMENT_AS_HTML_COMMENT - * @see self::COMMENT_AS_PI_NODE_LOOKALIKE - * - * @since 6.6.0 Subclassed for the HTML Processor. - * - * @return string|null - */ - public function get_comment_type() { - return $this->is_virtual() ? null : parent::get_comment_type(); - } - - /** - * Removes a bookmark that is no longer needed. - * - * Releasing a bookmark frees up the small - * performance overhead it requires. - * - * @since 6.4.0 - * - * @param string $bookmark_name Name of the bookmark to remove. - * @return bool Whether the bookmark already existed before removal. - */ - public function release_bookmark( $bookmark_name ) { - return parent::release_bookmark( "_{$bookmark_name}" ); - } - - /** - * Moves the internal cursor in the HTML Processor to a given bookmark's location. - * - * Be careful! Seeking backwards to a previous location resets the parser to the - * start of the document and reparses the entire contents up until it finds the - * sought-after bookmarked location. - * - * In order to prevent accidental infinite loops, there's a - * maximum limit on the number of times seek() can be called. - * - * @throws Exception When unable to allocate a bookmark for the next token in the input HTML document. - * - * @since 6.4.0 - * - * @param string $bookmark_name Jump to the place in the document identified by this bookmark name. - * @return bool Whether the internal cursor was successfully moved to the bookmark's location. - */ - public function seek( $bookmark_name ) { - // Flush any pending updates to the document before beginning. - $this->get_updated_html(); - - $actual_bookmark_name = "_{$bookmark_name}"; - $processor_started_at = $this->state->current_token - ? $this->bookmarks[ $this->state->current_token->bookmark_name ]->start - : 0; - $bookmark_starts_at = $this->bookmarks[ $actual_bookmark_name ]->start; - $bookmark_length = $this->bookmarks[ $actual_bookmark_name ]->length; - $direction = $bookmark_starts_at > $processor_started_at ? 'forward' : 'backward'; - - /* - * If seeking backwards, it's possible that the sought-after bookmark exists within an element - * which has been closed before the current cursor; in other words, it has already been removed - * from the stack of open elements. This means that it's insufficient to simply pop off elements - * from the stack of open elements which appear after the bookmarked location and then jump to - * that location, as the elements which were open before won't be re-opened. - * - * In order to maintain consistency, the HTML Processor rewinds to the start of the document - * and reparses everything until it finds the sought-after bookmark. - * - * There are potentially better ways to do this: cache the parser state for each bookmark and - * restore it when seeking; store an immutable and idempotent register of where elements open - * and close. - * - * If caching the parser state it will be essential to properly maintain the cached stack of - * open elements and active formatting elements when modifying the document. This could be a - * tedious and time-consuming process as well, and so for now will not be performed. - * - * It may be possible to track bookmarks for where elements open and close, and in doing so - * be able to quickly recalculate breadcrumbs for any element in the document. It may even - * be possible to remove the stack of open elements and compute it on the fly this way. - * If doing this, the parser would need to track the opening and closing locations for all - * tokens in the breadcrumb path for any and all bookmarks. By utilizing bookmarks themselves - * this list could be automatically maintained while modifying the document. Finding the - * breadcrumbs would then amount to traversing that list from the start until the token - * being inspected. Once an element closes, if there are no bookmarks pointing to locations - * within that element, then all of these locations may be forgotten to save on memory use - * and computation time. - */ - if ( 'backward' === $direction ) { - /* - * Instead of clearing the parser state and starting fresh, calling the stack methods - * maintains the proper flags in the parser. - */ - foreach ( $this->state->stack_of_open_elements->walk_up() as $item ) { - if ( 'context-node' === $item->bookmark_name ) { - break; - } - - $this->state->stack_of_open_elements->remove_node( $item ); - } - - foreach ( $this->state->active_formatting_elements->walk_up() as $item ) { - if ( 'context-node' === $item->bookmark_name ) { - break; - } - - $this->state->active_formatting_elements->remove_node( $item ); - } - - parent::seek( 'context-node' ); - $this->state->insertion_mode = Gutenberg_HTML_Processor_State_6_6::INSERTION_MODE_IN_BODY; - $this->state->frameset_ok = true; - $this->element_queue = array(); - $this->current_element = null; - } - - // When moving forwards, reparse the document until reaching the same location as the original bookmark. - if ( $bookmark_starts_at === $this->bookmarks[ $this->state->current_token->bookmark_name ]->start ) { - return true; - } - - while ( $this->next_token() ) { - if ( $bookmark_starts_at === $this->bookmarks[ $this->state->current_token->bookmark_name ]->start ) { - while ( isset( $this->current_element ) && Gutenberg_HTML_Stack_Event_6_6::POP === $this->current_element->operation ) { - $this->current_element = array_shift( $this->element_queue ); - } - return true; - } - } - - return false; - } - - /** - * Sets a bookmark in the HTML document. - * - * Bookmarks represent specific places or tokens in the HTML - * document, such as a tag opener or closer. When applying - * edits to a document, such as setting an attribute, the - * text offsets of that token may shift; the bookmark is - * kept updated with those shifts and remains stable unless - * the entire span of text in which the token sits is removed. - * - * Release bookmarks when they are no longer needed. - * - * Example: - * - * <main><h2>Surprising fact you may not know!</h2></main> - * ^ ^ - * \-|-- this `H2` opener bookmark tracks the token - * - * <main class="clickbait"><h2>Surprising fact you may no… - * ^ ^ - * \-|-- it shifts with edits - * - * Bookmarks provide the ability to seek to a previously-scanned - * place in the HTML document. This avoids the need to re-scan - * the entire document. - * - * Example: - * - * <ul><li>One</li><li>Two</li><li>Three</li></ul> - * ^^^^ - * want to note this last item - * - * $p = new WP_HTML_Tag_Processor( $html ); - * $in_list = false; - * while ( $p->next_tag( array( 'tag_closers' => $in_list ? 'visit' : 'skip' ) ) ) { - * if ( 'UL' === $p->get_tag() ) { - * if ( $p->is_tag_closer() ) { - * $in_list = false; - * $p->set_bookmark( 'resume' ); - * if ( $p->seek( 'last-li' ) ) { - * $p->add_class( 'last-li' ); - * } - * $p->seek( 'resume' ); - * $p->release_bookmark( 'last-li' ); - * $p->release_bookmark( 'resume' ); - * } else { - * $in_list = true; - * } - * } - * - * if ( 'LI' === $p->get_tag() ) { - * $p->set_bookmark( 'last-li' ); - * } - * } - * - * Bookmarks intentionally hide the internal string offsets - * to which they refer. They are maintained internally as - * updates are applied to the HTML document and therefore - * retain their "position" - the location to which they - * originally pointed. The inability to use bookmarks with - * functions like `substr` is therefore intentional to guard - * against accidentally breaking the HTML. - * - * Because bookmarks allocate memory and require processing - * for every applied update, they are limited and require - * a name. They should not be created with programmatically-made - * names, such as "li_{$index}" with some loop. As a general - * rule they should only be created with string-literal names - * like "start-of-section" or "last-paragraph". - * - * Bookmarks are a powerful tool to enable complicated behavior. - * Consider double-checking that you need this tool if you are - * reaching for it, as inappropriate use could lead to broken - * HTML structure or unwanted processing overhead. - * - * @since 6.4.0 - * - * @param string $bookmark_name Identifies this particular bookmark. - * @return bool Whether the bookmark was successfully created. - */ - public function set_bookmark( $bookmark_name ) { - return parent::set_bookmark( "_{$bookmark_name}" ); - } - - /** - * Checks whether a bookmark with the given name exists. - * - * @since 6.5.0 - * - * @param string $bookmark_name Name to identify a bookmark that potentially exists. - * @return bool Whether that bookmark exists. - */ - public function has_bookmark( $bookmark_name ) { - return parent::has_bookmark( "_{$bookmark_name}" ); - } - - /* - * HTML Parsing Algorithms - */ - - /** - * Closes a P element. - * - * @since 6.4.0 - * - * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. - * - * @see https://html.spec.whatwg.org/#close-a-p-element - */ - private function close_a_p_element() { - $this->generate_implied_end_tags( 'P' ); - $this->state->stack_of_open_elements->pop_until( 'P' ); - } - - /** - * Closes elements that have implied end tags. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#generate-implied-end-tags - * - * @param string|null $except_for_this_element Perform as if this element doesn't exist in the stack of open elements. - */ - private function generate_implied_end_tags( $except_for_this_element = null ) { - $elements_with_implied_end_tags = array( - 'DD', - 'DT', - 'LI', - 'P', - ); - - $current_node = $this->state->stack_of_open_elements->current_node(); - while ( - $current_node && $current_node->node_name !== $except_for_this_element && - in_array( $this->state->stack_of_open_elements->current_node(), $elements_with_implied_end_tags, true ) - ) { - $this->state->stack_of_open_elements->pop(); - } - } - - /** - * Closes elements that have implied end tags, thoroughly. - * - * See the HTML specification for an explanation why this is - * different from generating end tags in the normal sense. - * - * @since 6.4.0 - * - * @see WP_HTML_Processor::generate_implied_end_tags - * @see https://html.spec.whatwg.org/#generate-implied-end-tags - */ - private function generate_implied_end_tags_thoroughly() { - $elements_with_implied_end_tags = array( - 'DD', - 'DT', - 'LI', - 'P', - ); - - while ( in_array( $this->state->stack_of_open_elements->current_node(), $elements_with_implied_end_tags, true ) ) { - $this->state->stack_of_open_elements->pop(); - } - } - - /** - * Reconstructs the active formatting elements. - * - * > This has the effect of reopening all the formatting elements that were opened - * > in the current body, cell, or caption (whichever is youngest) that haven't - * > been explicitly closed. - * - * @since 6.4.0 - * - * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. - * - * @see https://html.spec.whatwg.org/#reconstruct-the-active-formatting-elements - * - * @return bool Whether any formatting elements needed to be reconstructed. - */ - private function reconstruct_active_formatting_elements() { - /* - * > If there are no entries in the list of active formatting elements, then there is nothing - * > to reconstruct; stop this algorithm. - */ - if ( 0 === $this->state->active_formatting_elements->count() ) { - return false; - } - - $last_entry = $this->state->active_formatting_elements->current_node(); - if ( - - /* - * > If the last (most recently added) entry in the list of active formatting elements is a marker; - * > stop this algorithm. - */ - 'marker' === $last_entry->node_name || - - /* - * > If the last (most recently added) entry in the list of active formatting elements is an - * > element that is in the stack of open elements, then there is nothing to reconstruct; - * > stop this algorithm. - */ - $this->state->stack_of_open_elements->contains_node( $last_entry ) - ) { - return false; - } - - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( 'Cannot reconstruct active formatting elements when advancing and rewinding is required.' ); - } - - /** - * Runs the adoption agency algorithm. - * - * @since 6.4.0 - * - * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. - * - * @see https://html.spec.whatwg.org/#adoption-agency-algorithm - */ - private function run_adoption_agency_algorithm() { - $budget = 1000; - $subject = $this->get_tag(); - $current_node = $this->state->stack_of_open_elements->current_node(); - - if ( - // > If the current node is an HTML element whose tag name is subject - $current_node && $subject === $current_node->node_name && - // > the current node is not in the list of active formatting elements - ! $this->state->active_formatting_elements->contains_node( $current_node ) - ) { - $this->state->stack_of_open_elements->pop(); - return; - } - - $outer_loop_counter = 0; - while ( $budget-- > 0 ) { - if ( $outer_loop_counter++ >= 8 ) { - return; - } - - /* - * > Let formatting element be the last element in the list of active formatting elements that: - * > - is between the end of the list and the last marker in the list, - * > if any, or the start of the list otherwise, - * > - and has the tag name subject. - */ - $formatting_element = null; - foreach ( $this->state->active_formatting_elements->walk_up() as $item ) { - if ( 'marker' === $item->node_name ) { - break; - } - - if ( $subject === $item->node_name ) { - $formatting_element = $item; - break; - } - } - - // > If there is no such element, then return and instead act as described in the "any other end tag" entry above. - if ( null === $formatting_element ) { - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( 'Cannot run adoption agency when "any other end tag" is required.' ); - } - - // > If formatting element is not in the stack of open elements, then this is a parse error; remove the element from the list, and return. - if ( ! $this->state->stack_of_open_elements->contains_node( $formatting_element ) ) { - $this->state->active_formatting_elements->remove_node( $formatting_element ); - return; - } - - // > If formatting element is in the stack of open elements, but the element is not in scope, then this is a parse error; return. - if ( ! $this->state->stack_of_open_elements->has_element_in_scope( $formatting_element->node_name ) ) { - return; - } - - /* - * > Let furthest block be the topmost node in the stack of open elements that is lower in the stack - * > than formatting element, and is an element in the special category. There might not be one. - */ - $is_above_formatting_element = true; - $furthest_block = null; - foreach ( $this->state->stack_of_open_elements->walk_down() as $item ) { - if ( $is_above_formatting_element && $formatting_element->bookmark_name !== $item->bookmark_name ) { - continue; - } - - if ( $is_above_formatting_element ) { - $is_above_formatting_element = false; - continue; - } - - if ( self::is_special( $item->node_name ) ) { - $furthest_block = $item; - break; - } - } - - /* - * > If there is no furthest block, then the UA must first pop all the nodes from the bottom of the - * > stack of open elements, from the current node up to and including formatting element, then - * > remove formatting element from the list of active formatting elements, and finally return. - */ - if ( null === $furthest_block ) { - foreach ( $this->state->stack_of_open_elements->walk_up() as $item ) { - $this->state->stack_of_open_elements->pop(); - - if ( $formatting_element->bookmark_name === $item->bookmark_name ) { - $this->state->active_formatting_elements->remove_node( $formatting_element ); - return; - } - } - } - - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( 'Cannot extract common ancestor in adoption agency algorithm.' ); - } - - $this->last_error = self::ERROR_UNSUPPORTED; - throw new WP_HTML_Unsupported_Exception( 'Cannot run adoption agency when looping required.' ); - } - - /** - * Inserts an HTML element on the stack of open elements. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#insert-a-foreign-element - * - * @param WP_HTML_Token $token Name of bookmark pointing to element in original input HTML. - */ - private function insert_html_element( $token ) { - $this->state->stack_of_open_elements->push( $token ); - } - - /* - * HTML Specification Helpers - */ - - /** - * Returns whether an element of a given name is in the HTML special category. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#special - * - * @param string $tag_name Name of element to check. - * @return bool Whether the element of the given name is in the special category. - */ - public static function is_special( $tag_name ) { - $tag_name = strtoupper( $tag_name ); - - return ( - 'ADDRESS' === $tag_name || - 'APPLET' === $tag_name || - 'AREA' === $tag_name || - 'ARTICLE' === $tag_name || - 'ASIDE' === $tag_name || - 'BASE' === $tag_name || - 'BASEFONT' === $tag_name || - 'BGSOUND' === $tag_name || - 'BLOCKQUOTE' === $tag_name || - 'BODY' === $tag_name || - 'BR' === $tag_name || - 'BUTTON' === $tag_name || - 'CAPTION' === $tag_name || - 'CENTER' === $tag_name || - 'COL' === $tag_name || - 'COLGROUP' === $tag_name || - 'DD' === $tag_name || - 'DETAILS' === $tag_name || - 'DIR' === $tag_name || - 'DIV' === $tag_name || - 'DL' === $tag_name || - 'DT' === $tag_name || - 'EMBED' === $tag_name || - 'FIELDSET' === $tag_name || - 'FIGCAPTION' === $tag_name || - 'FIGURE' === $tag_name || - 'FOOTER' === $tag_name || - 'FORM' === $tag_name || - 'FRAME' === $tag_name || - 'FRAMESET' === $tag_name || - 'H1' === $tag_name || - 'H2' === $tag_name || - 'H3' === $tag_name || - 'H4' === $tag_name || - 'H5' === $tag_name || - 'H6' === $tag_name || - 'HEAD' === $tag_name || - 'HEADER' === $tag_name || - 'HGROUP' === $tag_name || - 'HR' === $tag_name || - 'HTML' === $tag_name || - 'IFRAME' === $tag_name || - 'IMG' === $tag_name || - 'INPUT' === $tag_name || - 'KEYGEN' === $tag_name || - 'LI' === $tag_name || - 'LINK' === $tag_name || - 'LISTING' === $tag_name || - 'MAIN' === $tag_name || - 'MARQUEE' === $tag_name || - 'MENU' === $tag_name || - 'META' === $tag_name || - 'NAV' === $tag_name || - 'NOEMBED' === $tag_name || - 'NOFRAMES' === $tag_name || - 'NOSCRIPT' === $tag_name || - 'OBJECT' === $tag_name || - 'OL' === $tag_name || - 'P' === $tag_name || - 'PARAM' === $tag_name || - 'PLAINTEXT' === $tag_name || - 'PRE' === $tag_name || - 'SCRIPT' === $tag_name || - 'SEARCH' === $tag_name || - 'SECTION' === $tag_name || - 'SELECT' === $tag_name || - 'SOURCE' === $tag_name || - 'STYLE' === $tag_name || - 'SUMMARY' === $tag_name || - 'TABLE' === $tag_name || - 'TBODY' === $tag_name || - 'TD' === $tag_name || - 'TEMPLATE' === $tag_name || - 'TEXTAREA' === $tag_name || - 'TFOOT' === $tag_name || - 'TH' === $tag_name || - 'THEAD' === $tag_name || - 'TITLE' === $tag_name || - 'TR' === $tag_name || - 'TRACK' === $tag_name || - 'UL' === $tag_name || - 'WBR' === $tag_name || - 'XMP' === $tag_name || - - // MathML. - 'MI' === $tag_name || - 'MO' === $tag_name || - 'MN' === $tag_name || - 'MS' === $tag_name || - 'MTEXT' === $tag_name || - 'ANNOTATION-XML' === $tag_name || - - // SVG. - 'FOREIGNOBJECT' === $tag_name || - 'DESC' === $tag_name || - 'TITLE' === $tag_name - ); - } - - /** - * Returns whether a given element is an HTML Void Element - * - * > area, base, br, col, embed, hr, img, input, link, meta, source, track, wbr - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#void-elements - * - * @param string $tag_name Name of HTML tag to check. - * @return bool Whether the given tag is an HTML Void Element. - */ - public static function is_void( $tag_name ) { - $tag_name = strtoupper( $tag_name ); - - return ( - 'AREA' === $tag_name || - 'BASE' === $tag_name || - 'BASEFONT' === $tag_name || // Obsolete but still treated as void. - 'BGSOUND' === $tag_name || // Obsolete but still treated as void. - 'BR' === $tag_name || - 'COL' === $tag_name || - 'EMBED' === $tag_name || - 'FRAME' === $tag_name || - 'HR' === $tag_name || - 'IMG' === $tag_name || - 'INPUT' === $tag_name || - 'KEYGEN' === $tag_name || // Obsolete but still treated as void. - 'LINK' === $tag_name || - 'META' === $tag_name || - 'PARAM' === $tag_name || // Obsolete but still treated as void. - 'SOURCE' === $tag_name || - 'TRACK' === $tag_name || - 'WBR' === $tag_name - ); - } - - /* - * Constants that would pollute the top of the class if they were found there. - */ - - /** - * Indicates that the next HTML token should be parsed and processed. - * - * @since 6.4.0 - * - * @var string - */ - const PROCESS_NEXT_NODE = 'process-next-node'; - - /** - * Indicates that the current HTML token should be reprocessed in the newly-selected insertion mode. - * - * @since 6.4.0 - * - * @var string - */ - const REPROCESS_CURRENT_NODE = 'reprocess-current-node'; - - /** - * Indicates that the current HTML token should be processed without advancing the parser. - * - * @since 6.5.0 - * - * @var string - */ - const PROCESS_CURRENT_NODE = 'process-current-node'; - - /** - * Indicates that the parser encountered unsupported markup and has bailed. - * - * @since 6.4.0 - * - * @var string - */ - const ERROR_UNSUPPORTED = 'unsupported'; - - /** - * Indicates that the parser encountered more HTML tokens than it - * was able to process and has bailed. - * - * @since 6.4.0 - * - * @var string - */ - const ERROR_EXCEEDED_MAX_BOOKMARKS = 'exceeded-max-bookmarks'; - - /** - * Unlock code that must be passed into the constructor to create this class. - * - * This class extends the WP_HTML_Tag_Processor, which has a public class - * constructor. Therefore, it's not possible to have a private constructor here. - * - * This unlock code is used to ensure that anyone calling the constructor is - * doing so with a full understanding that it's intended to be a private API. - * - * @access private - */ - const CONSTRUCTOR_UNLOCK_CODE = 'Use WP_HTML_Processor::create_fragment() instead of calling the class constructor directly.'; -} diff --git a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-state-6-6.php b/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-state-6-6.php deleted file mode 100644 index 69896986d53f00..00000000000000 --- a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-state-6-6.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Processor_State class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.4.0 - */ - -/** - * Core class used by the HTML processor during HTML parsing - * for managing the internal parsing state. - * - * This class is designed for internal use by the HTML processor. - * - * @since 6.4.0 - * - * @access private - * - * @see WP_HTML_Processor - */ -class Gutenberg_HTML_Processor_State_6_6 { - /* - * Insertion mode constants. - * - * These constants exist and are named to make it easier to - * discover and recognize the supported insertion modes in - * the parser. - * - * Out of all the possible insertion modes, only those - * supported by the parser are listed here. As support - * is added to the parser for more modes, add them here - * following the same naming and value pattern. - * - * @see https://html.spec.whatwg.org/#the-insertion-mode - */ - - /** - * Initial insertion mode for full HTML parser. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#the-initial-insertion-mode - * @see WP_HTML_Processor_State::$insertion_mode - * - * @var string - */ - const INSERTION_MODE_INITIAL = 'insertion-mode-initial'; - - /** - * In body insertion mode for full HTML parser. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#parsing-main-inbody - * @see WP_HTML_Processor_State::$insertion_mode - * - * @var string - */ - const INSERTION_MODE_IN_BODY = 'insertion-mode-in-body'; - - /** - * Tracks open elements while scanning HTML. - * - * This property is initialized in the constructor and never null. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#stack-of-open-elements - * - * @var WP_HTML_Open_Elements - */ - public $stack_of_open_elements = null; - - /** - * Tracks open formatting elements, used to handle mis-nested formatting element tags. - * - * This property is initialized in the constructor and never null. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#list-of-active-formatting-elements - * - * @var WP_HTML_Active_Formatting_Elements - */ - public $active_formatting_elements = null; - - /** - * Refers to the currently-matched tag, if any. - * - * @since 6.4.0 - * - * @var WP_HTML_Token|null - */ - public $current_token = null; - - /** - * Tree construction insertion mode. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#insertion-mode - * - * @var string - */ - public $insertion_mode = self::INSERTION_MODE_INITIAL; - - /** - * Context node initializing fragment parser, if created as a fragment parser. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#concept-frag-parse-context - * - * @var [string, array]|null - */ - public $context_node = null; - - /** - * The frameset-ok flag indicates if a `FRAMESET` element is allowed in the current state. - * - * > The frameset-ok flag is set to "ok" when the parser is created. It is set to "not ok" after certain tokens are seen. - * - * @since 6.4.0 - * - * @see https://html.spec.whatwg.org/#frameset-ok-flag - * - * @var bool - */ - public $frameset_ok = true; - - /** - * Constructor - creates a new and empty state value. - * - * @since 6.4.0 - * - * @see WP_HTML_Processor - */ - public function __construct() { - $this->stack_of_open_elements = new Gutenberg_HTML_Open_Elements_6_6(); - $this->active_formatting_elements = new WP_HTML_Active_Formatting_Elements(); - } -} diff --git a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-stack-event-6-6.php b/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-stack-event-6-6.php deleted file mode 100644 index 0be6e709363bb6..00000000000000 --- a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-stack-event-6-6.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Stack_Event class - * - * @package WordPress - * @subpackage HTML-API - * @since 6.6.0 - */ - -/** - * Core class used by the HTML Processor as a record for stack operations. - * - * This class is for internal usage of the WP_HTML_Processor class. - * - * @access private - * @since 6.6.0 - * - * @see WP_HTML_Processor - */ -class Gutenberg_HTML_Stack_Event_6_6 { - /** - * Refers to popping an element off of the stack of open elements. - * - * @since 6.6.0 - */ - const POP = 'pop'; - - /** - * Refers to pushing an element onto the stack of open elements. - * - * @since 6.6.0 - */ - const PUSH = 'push'; - - /** - * References the token associated with the stack push event, - * even if this is a pop event for that element. - * - * @since 6.6.0 - * - * @var WP_HTML_Token - */ - public $token; - - /** - * Indicates which kind of stack operation this event represents. - * - * May be one of the class constants. - * - * @since 6.6.0 - * - * @see self::POP - * @see self::PUSH - * - * @var string - */ - public $operation; - - /** - * Indicates if the stack element is a real or virtual node. - * - * @since 6.6.0 - * - * @var string - */ - public $provenance; - - /** - * Constructor function. - * - * @since 6.6.0 - * - * @param WP_HTML_Token $token Token associated with stack event, always an opening token. - * @param string $operation One of self::PUSH or self::POP. - * @param string $provenance "virtual" or "real". - */ - public function __construct( $token, $operation, $provenance ) { - $this->token = $token; - $this->operation = $operation; - $this->provenance = $provenance; - } -} diff --git a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-tag-processor-6-6.php b/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-tag-processor-6-6.php deleted file mode 100644 index ecbc6d0d7b6af4..00000000000000 --- a/lib/compat/wordpress-6.6/html-api/class-gutenberg-html-tag-processor-6-6.php +++ /dev/null @@ -1,3559 +0,0 @@ -<?php -/** - * HTML API: WP_HTML_Tag_Processor class - * - * Scans through an HTML document to find specific tags, then - * transforms those tags by adding, removing, or updating the - * values of the HTML attributes within that tag (opener). - * - * Does not fully parse HTML or _recurse_ into the HTML structure - * Instead this scans linearly through a document and only parses - * the HTML tag openers. - * - * ### Possible future direction for this module - * - * - Prune the whitespace when removing classes/attributes: e.g. "a b c" -> "c" not " c". - * This would increase the size of the changes for some operations but leave more - * natural-looking output HTML. - * - * @package WordPress - * @subpackage HTML-API - * @since 6.2.0 - */ - -/** - * Core class used to modify attributes in an HTML document for tags matching a query. - * - * ## Usage - * - * Use of this class requires three steps: - * - * 1. Create a new class instance with your input HTML document. - * 2. Find the tag(s) you are looking for. - * 3. Request changes to the attributes in those tag(s). - * - * Example: - * - * $tags = new WP_HTML_Tag_Processor( $html ); - * if ( $tags->next_tag( 'option' ) ) { - * $tags->set_attribute( 'selected', true ); - * } - * - * ### Finding tags - * - * The `next_tag()` function moves the internal cursor through - * your input HTML document until it finds a tag meeting any of - * the supplied restrictions in the optional query argument. If - * no argument is provided then it will find the next HTML tag, - * regardless of what kind it is. - * - * If you want to _find whatever the next tag is_: - * - * $tags->next_tag(); - * - * | Goal | Query | - * |-----------------------------------------------------------|---------------------------------------------------------------------------------| - * | Find any tag. | `$tags->next_tag();` | - * | Find next image tag. | `$tags->next_tag( array( 'tag_name' => 'img' ) );` | - * | Find next image tag (without passing the array). | `$tags->next_tag( 'img' );` | - * | Find next tag containing the `fullwidth` CSS class. | `$tags->next_tag( array( 'class_name' => 'fullwidth' ) );` | - * | Find next image tag containing the `fullwidth` CSS class. | `$tags->next_tag( array( 'tag_name' => 'img', 'class_name' => 'fullwidth' ) );` | - * - * If a tag was found meeting your criteria then `next_tag()` - * will return `true` and you can proceed to modify it. If it - * returns `false`, however, it failed to find the tag and - * moved the cursor to the end of the file. - * - * Once the cursor reaches the end of the file the processor - * is done and if you want to reach an earlier tag you will - * need to recreate the processor and start over, as it's - * unable to back up or move in reverse. - * - * See the section on bookmarks for an exception to this - * no-backing-up rule. - * - * #### Custom queries - * - * Sometimes it's necessary to further inspect an HTML tag than - * the query syntax here permits. In these cases one may further - * inspect the search results using the read-only functions - * provided by the processor or external state or variables. - * - * Example: - * - * // Paint up to the first five DIV or SPAN tags marked with the "jazzy" style. - * $remaining_count = 5; - * while ( $remaining_count > 0 && $tags->next_tag() ) { - * if ( - * ( 'DIV' === $tags->get_tag() || 'SPAN' === $tags->get_tag() ) && - * 'jazzy' === $tags->get_attribute( 'data-style' ) - * ) { - * $tags->add_class( 'theme-style-everest-jazz' ); - * $remaining_count--; - * } - * } - * - * `get_attribute()` will return `null` if the attribute wasn't present - * on the tag when it was called. It may return `""` (the empty string) - * in cases where the attribute was present but its value was empty. - * For boolean attributes, those whose name is present but no value is - * given, it will return `true` (the only way to set `false` for an - * attribute is to remove it). - * - * #### When matching fails - * - * When `next_tag()` returns `false` it could mean different things: - * - * - The requested tag wasn't found in the input document. - * - The input document ended in the middle of an HTML syntax element. - * - * When a document ends in the middle of a syntax element it will pause - * the processor. This is to make it possible in the future to extend the - * input document and proceed - an important requirement for chunked - * streaming parsing of a document. - * - * Example: - * - * $processor = new WP_HTML_Tag_Processor( 'This <div is="a" partial="token' ); - * false === $processor->next_tag(); - * - * If a special element (see next section) is encountered but no closing tag - * is found it will count as an incomplete tag. The parser will pause as if - * the opening tag were incomplete. - * - * Example: - * - * $processor = new WP_HTML_Tag_Processor( '<style>// there could be more styling to come' ); - * false === $processor->next_tag(); - * - * $processor = new WP_HTML_Tag_Processor( '<style>// this is everything</style><div>' ); - * true === $processor->next_tag( 'DIV' ); - * - * #### Special elements - * - * Some HTML elements are handled in a special way; their start and end tags - * act like a void tag. These are special because their contents can't contain - * HTML markup. Everything inside these elements is handled in a special way - * and content that _appears_ like HTML tags inside of them isn't. There can - * be no nesting in these elements. - * - * In the following list, "raw text" means that all of the content in the HTML - * until the matching closing tag is treated verbatim without any replacements - * and without any parsing. - * - * - IFRAME allows no content but requires a closing tag. - * - NOEMBED (deprecated) content is raw text. - * - NOFRAMES (deprecated) content is raw text. - * - SCRIPT content is plaintext apart from legacy rules allowing `</script>` inside an HTML comment. - * - STYLE content is raw text. - * - TITLE content is plain text but character references are decoded. - * - TEXTAREA content is plain text but character references are decoded. - * - XMP (deprecated) content is raw text. - * - * ### Modifying HTML attributes for a found tag - * - * Once you've found the start of an opening tag you can modify - * any number of the attributes on that tag. You can set a new - * value for an attribute, remove the entire attribute, or do - * nothing and move on to the next opening tag. - * - * Example: - * - * if ( $tags->next_tag( array( 'class_name' => 'wp-group-block' ) ) ) { - * $tags->set_attribute( 'title', 'This groups the contained content.' ); - * $tags->remove_attribute( 'data-test-id' ); - * } - * - * If `set_attribute()` is called for an existing attribute it will - * overwrite the existing value. Similarly, calling `remove_attribute()` - * for a non-existing attribute has no effect on the document. Both - * of these methods are safe to call without knowing if a given attribute - * exists beforehand. - * - * ### Modifying CSS classes for a found tag - * - * The tag processor treats the `class` attribute as a special case. - * Because it's a common operation to add or remove CSS classes, this - * interface adds helper methods to make that easier. - * - * As with attribute values, adding or removing CSS classes is a safe - * operation that doesn't require checking if the attribute or class - * exists before making changes. If removing the only class then the - * entire `class` attribute will be removed. - * - * Example: - * - * // from `<span>Yippee!</span>` - * // to `<span class="is-active">Yippee!</span>` - * $tags->add_class( 'is-active' ); - * - * // from `<span class="excited">Yippee!</span>` - * // to `<span class="excited is-active">Yippee!</span>` - * $tags->add_class( 'is-active' ); - * - * // from `<span class="is-active heavy-accent">Yippee!</span>` - * // to `<span class="is-active heavy-accent">Yippee!</span>` - * $tags->add_class( 'is-active' ); - * - * // from `<input type="text" class="is-active rugby not-disabled" length="24">` - * // to `<input type="text" class="is-active not-disabled" length="24"> - * $tags->remove_class( 'rugby' ); - * - * // from `<input type="text" class="rugby" length="24">` - * // to `<input type="text" length="24"> - * $tags->remove_class( 'rugby' ); - * - * // from `<input type="text" length="24">` - * // to `<input type="text" length="24"> - * $tags->remove_class( 'rugby' ); - * - * When class changes are enqueued but a direct change to `class` is made via - * `set_attribute` then the changes to `set_attribute` (or `remove_attribute`) - * will take precedence over those made through `add_class` and `remove_class`. - * - * ### Bookmarks - * - * While scanning through the input HTMl document it's possible to set - * a named bookmark when a particular tag is found. Later on, after - * continuing to scan other tags, it's possible to `seek` to one of - * the set bookmarks and then proceed again from that point forward. - * - * Because bookmarks create processing overhead one should avoid - * creating too many of them. As a rule, create only bookmarks - * of known string literal names; avoid creating "mark_{$index}" - * and so on. It's fine from a performance standpoint to create a - * bookmark and update it frequently, such as within a loop. - * - * $total_todos = 0; - * while ( $p->next_tag( array( 'tag_name' => 'UL', 'class_name' => 'todo' ) ) ) { - * $p->set_bookmark( 'list-start' ); - * while ( $p->next_tag( array( 'tag_closers' => 'visit' ) ) ) { - * if ( 'UL' === $p->get_tag() && $p->is_tag_closer() ) { - * $p->set_bookmark( 'list-end' ); - * $p->seek( 'list-start' ); - * $p->set_attribute( 'data-contained-todos', (string) $total_todos ); - * $total_todos = 0; - * $p->seek( 'list-end' ); - * break; - * } - * - * if ( 'LI' === $p->get_tag() && ! $p->is_tag_closer() ) { - * $total_todos++; - * } - * } - * } - * - * ## Tokens and finer-grained processing. - * - * It's possible to scan through every lexical token in the - * HTML document using the `next_token()` function. This - * alternative form takes no argument and provides no built-in - * query syntax. - * - * Example: - * - * $title = '(untitled)'; - * $text = ''; - * while ( $processor->next_token() ) { - * switch ( $processor->get_token_name() ) { - * case '#text': - * $text .= $processor->get_modifiable_text(); - * break; - * - * case 'BR': - * $text .= "\n"; - * break; - * - * case 'TITLE': - * $title = $processor->get_modifiable_text(); - * break; - * } - * } - * return trim( "# {$title}\n\n{$text}" ); - * - * ### Tokens and _modifiable text_. - * - * #### Special "atomic" HTML elements. - * - * Not all HTML elements are able to contain other elements inside of them. - * For instance, the contents inside a TITLE element are plaintext (except - * that character references like & will be decoded). This means that - * if the string `<img>` appears inside a TITLE element, then it's not an - * image tag, but rather it's text describing an image tag. Likewise, the - * contents of a SCRIPT or STYLE element are handled entirely separately in - * a browser than the contents of other elements because they represent a - * different language than HTML. - * - * For these elements the Tag Processor treats the entire sequence as one, - * from the opening tag, including its contents, through its closing tag. - * This means that the it's not possible to match the closing tag for a - * SCRIPT element unless it's unexpected; the Tag Processor already matched - * it when it found the opening tag. - * - * The inner contents of these elements are that element's _modifiable text_. - * - * The special elements are: - * - `SCRIPT` whose contents are treated as raw plaintext but supports a legacy - * style of including JavaScript inside of HTML comments to avoid accidentally - * closing the SCRIPT from inside a JavaScript string. E.g. `console.log( '</script>' )`. - * - `TITLE` and `TEXTAREA` whose contents are treated as plaintext and then any - * character references are decoded. E.g. `1 < 2 < 3` becomes `1 < 2 < 3`. - * - `IFRAME`, `NOSCRIPT`, `NOEMBED`, `NOFRAME`, `STYLE` whose contents are treated as - * raw plaintext and left as-is. E.g. `1 < 2 < 3` remains `1 < 2 < 3`. - * - * #### Other tokens with modifiable text. - * - * There are also non-elements which are void/self-closing in nature and contain - * modifiable text that is part of that individual syntax token itself. - * - * - `#text` nodes, whose entire token _is_ the modifiable text. - * - HTML comments and tokens that become comments due to some syntax error. The - * text for these tokens is the portion of the comment inside of the syntax. - * E.g. for `<!-- comment -->` the text is `" comment "` (note the spaces are included). - * - `CDATA` sections, whose text is the content inside of the section itself. E.g. for - * `<![CDATA[some content]]>` the text is `"some content"` (with restrictions [1]). - * - "Funky comments," which are a special case of invalid closing tags whose name is - * invalid. The text for these nodes is the text that a browser would transform into - * an HTML comment when parsing. E.g. for `</%post_author>` the text is `%post_author`. - * - `DOCTYPE` declarations like `<DOCTYPE html>` which have no closing tag. - * - XML Processing instruction nodes like `<?wp __( "Like" ); ?>` (with restrictions [2]). - * - The empty end tag `</>` which is ignored in the browser and DOM. - * - * [1]: There are no CDATA sections in HTML. When encountering `<![CDATA[`, everything - * until the next `>` becomes a bogus HTML comment, meaning there can be no CDATA - * section in an HTML document containing `>`. The Tag Processor will first find - * all valid and bogus HTML comments, and then if the comment _would_ have been a - * CDATA section _were they to exist_, it will indicate this as the type of comment. - * - * [2]: XML allows a broader range of characters in a processing instruction's target name - * and disallows "xml" as a name, since it's special. The Tag Processor only recognizes - * target names with an ASCII-representable subset of characters. It also exhibits the - * same constraint as with CDATA sections, in that `>` cannot exist within the token - * since Processing Instructions do no exist within HTML and their syntax transforms - * into a bogus comment in the DOM. - * - * ## Design and limitations - * - * The Tag Processor is designed to linearly scan HTML documents and tokenize - * HTML tags and their attributes. It's designed to do this as efficiently as - * possible without compromising parsing integrity. Therefore it will be - * slower than some methods of modifying HTML, such as those incorporating - * over-simplified PCRE patterns, but will not introduce the defects and - * failures that those methods bring in, which lead to broken page renders - * and often to security vulnerabilities. On the other hand, it will be faster - * than full-blown HTML parsers such as DOMDocument and use considerably - * less memory. It requires a negligible memory overhead, enough to consider - * it a zero-overhead system. - * - * The performance characteristics are maintained by avoiding tree construction - * and semantic cleanups which are specified in HTML5. Because of this, for - * example, it's not possible for the Tag Processor to associate any given - * opening tag with its corresponding closing tag, or to return the inner markup - * inside an element. Systems may be built on top of the Tag Processor to do - * this, but the Tag Processor is and should be constrained so it can remain an - * efficient, low-level, and reliable HTML scanner. - * - * The Tag Processor's design incorporates a "garbage-in-garbage-out" philosophy. - * HTML5 specifies that certain invalid content be transformed into different forms - * for display, such as removing null bytes from an input document and replacing - * invalid characters with the Unicode replacement character `U+FFFD` (visually "�"). - * Where errors or transformations exist within the HTML5 specification, the Tag Processor - * leaves those invalid inputs untouched, passing them through to the final browser - * to handle. While this implies that certain operations will be non-spec-compliant, - * such as reading the value of an attribute with invalid content, it also preserves a - * simplicity and efficiency for handling those error cases. - * - * Most operations within the Tag Processor are designed to minimize the difference - * between an input and output document for any given change. For example, the - * `add_class` and `remove_class` methods preserve whitespace and the class ordering - * within the `class` attribute; and when encountering tags with duplicated attributes, - * the Tag Processor will leave those invalid duplicate attributes where they are but - * update the proper attribute which the browser will read for parsing its value. An - * exception to this rule is that all attribute updates store their values as - * double-quoted strings, meaning that attributes on input with single-quoted or - * unquoted values will appear in the output with double-quotes. - * - * ### Scripting Flag - * - * The Tag Processor parses HTML with the "scripting flag" disabled. This means - * that it doesn't run any scripts while parsing the page. In a browser with - * JavaScript enabled, for example, the script can change the parse of the - * document as it loads. On the server, however, evaluating JavaScript is not - * only impractical, but also unwanted. - * - * Practically this means that the Tag Processor will descend into NOSCRIPT - * elements and process its child tags. Were the scripting flag enabled, such - * as in a typical browser, the contents of NOSCRIPT are skipped entirely. - * - * This allows the HTML API to process the content that will be presented in - * a browser when scripting is disabled, but it offers a different view of a - * page than most browser sessions will experience. E.g. the tags inside the - * NOSCRIPT disappear. - * - * ### Text Encoding - * - * The Tag Processor assumes that the input HTML document is encoded with a - * text encoding compatible with 7-bit ASCII's '<', '>', '&', ';', '/', '=', - * "'", '"', 'a' - 'z', 'A' - 'Z', and the whitespace characters ' ', tab, - * carriage-return, newline, and form-feed. - * - * In practice, this includes almost every single-byte encoding as well as - * UTF-8. Notably, however, it does not include UTF-16. If providing input - * that's incompatible, then convert the encoding beforehand. - * - * @since 6.2.0 - * @since 6.2.1 Fix: Support for various invalid comments; attribute updates are case-insensitive. - * @since 6.3.2 Fix: Skip HTML-like content inside rawtext elements such as STYLE. - * @since 6.5.0 Pauses processor when input ends in an incomplete syntax token. - * Introduces "special" elements which act like void elements, e.g. TITLE, STYLE. - * Allows scanning through all tokens and processing modifiable text, where applicable. - */ -class Gutenberg_HTML_Tag_Processor_6_6 { - /** - * The maximum number of bookmarks allowed to exist at - * any given time. - * - * @since 6.2.0 - * @var int - * - * @see WP_HTML_Tag_Processor::set_bookmark() - */ - const MAX_BOOKMARKS = 10; - - /** - * Maximum number of times seek() can be called. - * Prevents accidental infinite loops. - * - * @since 6.2.0 - * @var int - * - * @see WP_HTML_Tag_Processor::seek() - */ - const MAX_SEEK_OPS = 1000; - - /** - * The HTML document to parse. - * - * @since 6.2.0 - * @var string - */ - protected $html; - - /** - * The last query passed to next_tag(). - * - * @since 6.2.0 - * @var array|null - */ - private $last_query; - - /** - * The tag name this processor currently scans for. - * - * @since 6.2.0 - * @var string|null - */ - private $sought_tag_name; - - /** - * The CSS class name this processor currently scans for. - * - * @since 6.2.0 - * @var string|null - */ - private $sought_class_name; - - /** - * The match offset this processor currently scans for. - * - * @since 6.2.0 - * @var int|null - */ - private $sought_match_offset; - - /** - * Whether to visit tag closers, e.g. </div>, when walking an input document. - * - * @since 6.2.0 - * @var bool - */ - private $stop_on_tag_closers; - - /** - * Specifies mode of operation of the parser at any given time. - * - * | State | Meaning | - * | ----------------|----------------------------------------------------------------------| - * | *Ready* | The parser is ready to run. | - * | *Complete* | There is nothing left to parse. | - * | *Incomplete* | The HTML ended in the middle of a token; nothing more can be parsed. | - * | *Matched tag* | Found an HTML tag; it's possible to modify its attributes. | - * | *Text node* | Found a #text node; this is plaintext and modifiable. | - * | *CDATA node* | Found a CDATA section; this is modifiable. | - * | *Comment* | Found a comment or bogus comment; this is modifiable. | - * | *Presumptuous* | Found an empty tag closer: `</>`. | - * | *Funky comment* | Found a tag closer with an invalid tag name; this is modifiable. | - * - * @since 6.5.0 - * - * @see WP_HTML_Tag_Processor::STATE_READY - * @see WP_HTML_Tag_Processor::STATE_COMPLETE - * @see WP_HTML_Tag_Processor::STATE_INCOMPLETE_INPUT - * @see WP_HTML_Tag_Processor::STATE_MATCHED_TAG - * @see WP_HTML_Tag_Processor::STATE_TEXT_NODE - * @see WP_HTML_Tag_Processor::STATE_CDATA_NODE - * @see WP_HTML_Tag_Processor::STATE_COMMENT - * @see WP_HTML_Tag_Processor::STATE_DOCTYPE - * @see WP_HTML_Tag_Processor::STATE_PRESUMPTUOUS_TAG - * @see WP_HTML_Tag_Processor::STATE_FUNKY_COMMENT - * - * @var string - */ - protected $parser_state = self::STATE_READY; - - /** - * What kind of syntax token became an HTML comment. - * - * Since there are many ways in which HTML syntax can create an HTML comment, - * this indicates which of those caused it. This allows the Tag Processor to - * represent more from the original input document than would appear in the DOM. - * - * @since 6.5.0 - * - * @var string|null - */ - protected $comment_type = null; - - /** - * How many bytes from the original HTML document have been read and parsed. - * - * This value points to the latest byte offset in the input document which - * has been already parsed. It is the internal cursor for the Tag Processor - * and updates while scanning through the HTML tokens. - * - * @since 6.2.0 - * @var int - */ - private $bytes_already_parsed = 0; - - /** - * Byte offset in input document where current token starts. - * - * Example: - * - * <div id="test">... - * 01234 - * - token starts at 0 - * - * @since 6.5.0 - * - * @var int|null - */ - private $token_starts_at; - - /** - * Byte length of current token. - * - * Example: - * - * <div id="test">... - * 012345678901234 - * - token length is 14 - 0 = 14 - * - * a <!-- comment --> is a token. - * 0123456789 123456789 123456789 - * - token length is 17 - 2 = 15 - * - * @since 6.5.0 - * - * @var int|null - */ - private $token_length; - - /** - * Byte offset in input document where current tag name starts. - * - * Example: - * - * <div id="test">... - * 01234 - * - tag name starts at 1 - * - * @since 6.2.0 - * - * @var int|null - */ - private $tag_name_starts_at; - - /** - * Byte length of current tag name. - * - * Example: - * - * <div id="test">... - * 01234 - * --- tag name length is 3 - * - * @since 6.2.0 - * - * @var int|null - */ - private $tag_name_length; - - /** - * Byte offset into input document where current modifiable text starts. - * - * @since 6.5.0 - * - * @var int - */ - private $text_starts_at; - - /** - * Byte length of modifiable text. - * - * @since 6.5.0 - * - * @var string - */ - private $text_length; - - /** - * Whether the current tag is an opening tag, e.g. <div>, or a closing tag, e.g. </div>. - * - * @var bool - */ - private $is_closing_tag; - - /** - * Lazily-built index of attributes found within an HTML tag, keyed by the attribute name. - * - * Example: - * - * // Supposing the parser is working through this content - * // and stops after recognizing the `id` attribute. - * // <div id="test-4" class=outline title="data:text/plain;base64=asdk3nk1j3fo8"> - * // ^ parsing will continue from this point. - * $this->attributes = array( - * 'id' => new WP_HTML_Attribute_Token( 'id', 9, 6, 5, 11, false ) - * ); - * - * // When picking up parsing again, or when asking to find the - * // `class` attribute we will continue and add to this array. - * $this->attributes = array( - * 'id' => new WP_HTML_Attribute_Token( 'id', 9, 6, 5, 11, false ), - * 'class' => new WP_HTML_Attribute_Token( 'class', 23, 7, 17, 13, false ) - * ); - * - * // Note that only the `class` attribute value is stored in the index. - * // That's because it is the only value used by this class at the moment. - * - * @since 6.2.0 - * @var WP_HTML_Attribute_Token[] - */ - private $attributes = array(); - - /** - * Tracks spans of duplicate attributes on a given tag, used for removing - * all copies of an attribute when calling `remove_attribute()`. - * - * @since 6.3.2 - * - * @var (WP_HTML_Span[])[]|null - */ - private $duplicate_attributes = null; - - /** - * Which class names to add or remove from a tag. - * - * These are tracked separately from attribute updates because they are - * semantically distinct, whereas this interface exists for the common - * case of adding and removing class names while other attributes are - * generally modified as with DOM `setAttribute` calls. - * - * When modifying an HTML document these will eventually be collapsed - * into a single `set_attribute( 'class', $changes )` call. - * - * Example: - * - * // Add the `wp-block-group` class, remove the `wp-group` class. - * $classname_updates = array( - * // Indexed by a comparable class name. - * 'wp-block-group' => WP_HTML_Tag_Processor::ADD_CLASS, - * 'wp-group' => WP_HTML_Tag_Processor::REMOVE_CLASS - * ); - * - * @since 6.2.0 - * @var bool[] - */ - private $classname_updates = array(); - - /** - * Tracks a semantic location in the original HTML which - * shifts with updates as they are applied to the document. - * - * @since 6.2.0 - * @var WP_HTML_Span[] - */ - protected $bookmarks = array(); - - const ADD_CLASS = true; - const REMOVE_CLASS = false; - const SKIP_CLASS = null; - - /** - * Lexical replacements to apply to input HTML document. - * - * "Lexical" in this class refers to the part of this class which - * operates on pure text _as text_ and not as HTML. There's a line - * between the public interface, with HTML-semantic methods like - * `set_attribute` and `add_class`, and an internal state that tracks - * text offsets in the input document. - * - * When higher-level HTML methods are called, those have to transform their - * operations (such as setting an attribute's value) into text diffing - * operations (such as replacing the sub-string from indices A to B with - * some given new string). These text-diffing operations are the lexical - * updates. - * - * As new higher-level methods are added they need to collapse their - * operations into these lower-level lexical updates since that's the - * Tag Processor's internal language of change. Any code which creates - * these lexical updates must ensure that they do not cross HTML syntax - * boundaries, however, so these should never be exposed outside of this - * class or any classes which intentionally expand its functionality. - * - * These are enqueued while editing the document instead of being immediately - * applied to avoid processing overhead, string allocations, and string - * copies when applying many updates to a single document. - * - * Example: - * - * // Replace an attribute stored with a new value, indices - * // sourced from the lazily-parsed HTML recognizer. - * $start = $attributes['src']->start; - * $length = $attributes['src']->length; - * $modifications[] = new WP_HTML_Text_Replacement( $start, $length, $new_value ); - * - * // Correspondingly, something like this will appear in this array. - * $lexical_updates = array( - * WP_HTML_Text_Replacement( 14, 28, 'https://my-site.my-domain/wp-content/uploads/2014/08/kittens.jpg' ) - * ); - * - * @since 6.2.0 - * @var WP_HTML_Text_Replacement[] - */ - protected $lexical_updates = array(); - - /** - * Tracks and limits `seek()` calls to prevent accidental infinite loops. - * - * @since 6.2.0 - * @var int - * - * @see WP_HTML_Tag_Processor::seek() - */ - protected $seek_count = 0; - - /** - * Constructor. - * - * @since 6.2.0 - * - * @param string $html HTML to process. - */ - public function __construct( $html ) { - $this->html = $html; - } - - /** - * Finds the next tag matching the $query. - * - * @since 6.2.0 - * @since 6.5.0 No longer processes incomplete tokens at end of document; pauses the processor at start of token. - * - * @param array|string|null $query { - * Optional. Which tag name to find, having which class, etc. Default is to find any tag. - * - * @type string|null $tag_name Which tag to find, or `null` for "any tag." - * @type int|null $match_offset Find the Nth tag matching all search criteria. - * 1 for "first" tag, 3 for "third," etc. - * Defaults to first tag. - * @type string|null $class_name Tag must contain this whole class name to match. - * @type string|null $tag_closers "visit" or "skip": whether to stop on tag closers, e.g. </div>. - * } - * @return bool Whether a tag was matched. - */ - public function next_tag( $query = null ) { - $this->parse_query( $query ); - $already_found = 0; - - do { - if ( false === $this->next_token() ) { - return false; - } - - if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { - continue; - } - - if ( $this->matches() ) { - ++$already_found; - } - } while ( $already_found < $this->sought_match_offset ); - - return true; - } - - /** - * Finds the next token in the HTML document. - * - * An HTML document can be viewed as a stream of tokens, - * where tokens are things like HTML tags, HTML comments, - * text nodes, etc. This method finds the next token in - * the HTML document and returns whether it found one. - * - * If it starts parsing a token and reaches the end of the - * document then it will seek to the start of the last - * token and pause, returning `false` to indicate that it - * failed to find a complete token. - * - * Possible token types, based on the HTML specification: - * - * - an HTML tag, whether opening, closing, or void. - * - a text node - the plaintext inside tags. - * - an HTML comment. - * - a DOCTYPE declaration. - * - a processing instruction, e.g. `<?xml version="1.0" ?>`. - * - * The Tag Processor currently only supports the tag token. - * - * @since 6.5.0 - * - * @return bool Whether a token was parsed. - */ - public function next_token() { - return $this->base_class_next_token(); - } - - /** - * Internal method which finds the next token in the HTML document. - * - * This method is a protected internal function which implements the logic for - * finding the next token in a document. It exists so that the parser can update - * its state without affecting the location of the cursor in the document and - * without triggering subclass methods for things like `next_token()`, e.g. when - * applying patches before searching for the next token. - * - * @since 6.5.0 - * - * @access private - * - * @return bool Whether a token was parsed. - */ - private function base_class_next_token() { - $was_at = $this->bytes_already_parsed; - $this->after_tag(); - - // Don't proceed if there's nothing more to scan. - if ( - self::STATE_COMPLETE === $this->parser_state || - self::STATE_INCOMPLETE_INPUT === $this->parser_state - ) { - return false; - } - - /* - * The next step in the parsing loop determines the parsing state; - * clear it so that state doesn't linger from the previous step. - */ - $this->parser_state = self::STATE_READY; - - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - $this->parser_state = self::STATE_COMPLETE; - return false; - } - - // Find the next tag if it exists. - if ( false === $this->parse_next_tag() ) { - if ( self::STATE_INCOMPLETE_INPUT === $this->parser_state ) { - $this->bytes_already_parsed = $was_at; - } - - return false; - } - - /* - * For legacy reasons the rest of this function handles tags and their - * attributes. If the processor has reached the end of the document - * or if it matched any other token then it should return here to avoid - * attempting to process tag-specific syntax. - */ - if ( - self::STATE_INCOMPLETE_INPUT !== $this->parser_state && - self::STATE_COMPLETE !== $this->parser_state && - self::STATE_MATCHED_TAG !== $this->parser_state - ) { - return true; - } - - // Parse all of its attributes. - while ( $this->parse_next_attribute() ) { - continue; - } - - // Ensure that the tag closes before the end of the document. - if ( - self::STATE_INCOMPLETE_INPUT === $this->parser_state || - $this->bytes_already_parsed >= strlen( $this->html ) - ) { - // Does this appropriately clear state (parsed attributes)? - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - $this->bytes_already_parsed = $was_at; - - return false; - } - - $tag_ends_at = strpos( $this->html, '>', $this->bytes_already_parsed ); - if ( false === $tag_ends_at ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - $this->bytes_already_parsed = $was_at; - - return false; - } - $this->parser_state = self::STATE_MATCHED_TAG; - $this->bytes_already_parsed = $tag_ends_at + 1; - $this->token_length = $this->bytes_already_parsed - $this->token_starts_at; - - /* - * For non-DATA sections which might contain text that looks like HTML tags but - * isn't, scan with the appropriate alternative mode. Looking at the first letter - * of the tag name as a pre-check avoids a string allocation when it's not needed. - */ - $t = $this->html[ $this->tag_name_starts_at ]; - if ( - $this->is_closing_tag || - ! ( - 'i' === $t || 'I' === $t || - 'n' === $t || 'N' === $t || - 's' === $t || 'S' === $t || - 't' === $t || 'T' === $t || - 'x' === $t || 'X' === $t - ) - ) { - return true; - } - - $tag_name = $this->get_tag(); - - /* - * Preserve the opening tag pointers, as these will be overwritten - * when finding the closing tag. They will be reset after finding - * the closing to tag to point to the opening of the special atomic - * tag sequence. - */ - $tag_name_starts_at = $this->tag_name_starts_at; - $tag_name_length = $this->tag_name_length; - $tag_ends_at = $this->token_starts_at + $this->token_length; - $attributes = $this->attributes; - $duplicate_attributes = $this->duplicate_attributes; - - // Find the closing tag if necessary. - $found_closer = false; - switch ( $tag_name ) { - case 'SCRIPT': - $found_closer = $this->skip_script_data(); - break; - - case 'TEXTAREA': - case 'TITLE': - $found_closer = $this->skip_rcdata( $tag_name ); - break; - - /* - * In the browser this list would include the NOSCRIPT element, - * but the Tag Processor is an environment with the scripting - * flag disabled, meaning that it needs to descend into the - * NOSCRIPT element to be able to properly process what will be - * sent to a browser. - * - * Note that this rule makes HTML5 syntax incompatible with XML, - * because the parsing of this token depends on client application. - * The NOSCRIPT element cannot be represented in the XHTML syntax. - */ - case 'IFRAME': - case 'NOEMBED': - case 'NOFRAMES': - case 'STYLE': - case 'XMP': - $found_closer = $this->skip_rawtext( $tag_name ); - break; - - // No other tags should be treated in their entirety here. - default: - return true; - } - - if ( ! $found_closer ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - $this->bytes_already_parsed = $was_at; - return false; - } - - /* - * The values here look like they reference the opening tag but they reference - * the closing tag instead. This is why the opening tag values were stored - * above in a variable. It reads confusingly here, but that's because the - * functions that skip the contents have moved all the internal cursors past - * the inner content of the tag. - */ - $this->token_starts_at = $was_at; - $this->token_length = $this->bytes_already_parsed - $this->token_starts_at; - $this->text_starts_at = $tag_ends_at; - $this->text_length = $this->tag_name_starts_at - $this->text_starts_at; - $this->tag_name_starts_at = $tag_name_starts_at; - $this->tag_name_length = $tag_name_length; - $this->attributes = $attributes; - $this->duplicate_attributes = $duplicate_attributes; - - return true; - } - - /** - * Whether the processor paused because the input HTML document ended - * in the middle of a syntax element, such as in the middle of a tag. - * - * Example: - * - * $processor = new WP_HTML_Tag_Processor( '<input type="text" value="Th' ); - * false === $processor->get_next_tag(); - * true === $processor->paused_at_incomplete_token(); - * - * @since 6.5.0 - * - * @return bool Whether the parse paused at the start of an incomplete token. - */ - public function paused_at_incomplete_token() { - return self::STATE_INCOMPLETE_INPUT === $this->parser_state; - } - - /** - * Generator for a foreach loop to step through each class name for the matched tag. - * - * This generator function is designed to be used inside a "foreach" loop. - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( "<div class='free <egg<\tlang-en'>" ); - * $p->next_tag(); - * foreach ( $p->class_list() as $class_name ) { - * echo "{$class_name} "; - * } - * // Outputs: "free <egg> lang-en " - * - * @since 6.4.0 - */ - public function class_list() { - if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { - return; - } - - /** @var string $class contains the string value of the class attribute, with character references decoded. */ - $class = $this->get_attribute( 'class' ); - - if ( ! is_string( $class ) ) { - return; - } - - $seen = array(); - - $at = 0; - while ( $at < strlen( $class ) ) { - // Skip past any initial boundary characters. - $at += strspn( $class, " \t\f\r\n", $at ); - if ( $at >= strlen( $class ) ) { - return; - } - - // Find the byte length until the next boundary. - $length = strcspn( $class, " \t\f\r\n", $at ); - if ( 0 === $length ) { - return; - } - - /* - * CSS class names are case-insensitive in the ASCII range. - * - * @see https://www.w3.org/TR/CSS2/syndata.html#x1 - */ - $name = strtolower( substr( $class, $at, $length ) ); - $at += $length; - - /* - * It's expected that the number of class names for a given tag is relatively small. - * Given this, it is probably faster overall to scan an array for a value rather - * than to use the class name as a key and check if it's a key of $seen. - */ - if ( in_array( $name, $seen, true ) ) { - continue; - } - - $seen[] = $name; - yield $name; - } - } - - - /** - * Returns if a matched tag contains the given ASCII case-insensitive class name. - * - * @since 6.4.0 - * - * @param string $wanted_class Look for this CSS class name, ASCII case-insensitive. - * @return bool|null Whether the matched tag contains the given class name, or null if not matched. - */ - public function has_class( $wanted_class ) { - if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { - return null; - } - - $wanted_class = strtolower( $wanted_class ); - - foreach ( $this->class_list() as $class_name ) { - if ( $class_name === $wanted_class ) { - return true; - } - } - - return false; - } - - - /** - * Sets a bookmark in the HTML document. - * - * Bookmarks represent specific places or tokens in the HTML - * document, such as a tag opener or closer. When applying - * edits to a document, such as setting an attribute, the - * text offsets of that token may shift; the bookmark is - * kept updated with those shifts and remains stable unless - * the entire span of text in which the token sits is removed. - * - * Release bookmarks when they are no longer needed. - * - * Example: - * - * <main><h2>Surprising fact you may not know!</h2></main> - * ^ ^ - * \-|-- this `H2` opener bookmark tracks the token - * - * <main class="clickbait"><h2>Surprising fact you may no… - * ^ ^ - * \-|-- it shifts with edits - * - * Bookmarks provide the ability to seek to a previously-scanned - * place in the HTML document. This avoids the need to re-scan - * the entire document. - * - * Example: - * - * <ul><li>One</li><li>Two</li><li>Three</li></ul> - * ^^^^ - * want to note this last item - * - * $p = new WP_HTML_Tag_Processor( $html ); - * $in_list = false; - * while ( $p->next_tag( array( 'tag_closers' => $in_list ? 'visit' : 'skip' ) ) ) { - * if ( 'UL' === $p->get_tag() ) { - * if ( $p->is_tag_closer() ) { - * $in_list = false; - * $p->set_bookmark( 'resume' ); - * if ( $p->seek( 'last-li' ) ) { - * $p->add_class( 'last-li' ); - * } - * $p->seek( 'resume' ); - * $p->release_bookmark( 'last-li' ); - * $p->release_bookmark( 'resume' ); - * } else { - * $in_list = true; - * } - * } - * - * if ( 'LI' === $p->get_tag() ) { - * $p->set_bookmark( 'last-li' ); - * } - * } - * - * Bookmarks intentionally hide the internal string offsets - * to which they refer. They are maintained internally as - * updates are applied to the HTML document and therefore - * retain their "position" - the location to which they - * originally pointed. The inability to use bookmarks with - * functions like `substr` is therefore intentional to guard - * against accidentally breaking the HTML. - * - * Because bookmarks allocate memory and require processing - * for every applied update, they are limited and require - * a name. They should not be created with programmatically-made - * names, such as "li_{$index}" with some loop. As a general - * rule they should only be created with string-literal names - * like "start-of-section" or "last-paragraph". - * - * Bookmarks are a powerful tool to enable complicated behavior. - * Consider double-checking that you need this tool if you are - * reaching for it, as inappropriate use could lead to broken - * HTML structure or unwanted processing overhead. - * - * @since 6.2.0 - * - * @param string $name Identifies this particular bookmark. - * @return bool Whether the bookmark was successfully created. - */ - public function set_bookmark( $name ) { - // It only makes sense to set a bookmark if the parser has paused on a concrete token. - if ( - self::STATE_COMPLETE === $this->parser_state || - self::STATE_INCOMPLETE_INPUT === $this->parser_state - ) { - return false; - } - - if ( ! array_key_exists( $name, $this->bookmarks ) && count( $this->bookmarks ) >= static::MAX_BOOKMARKS ) { - _doing_it_wrong( - __METHOD__, - __( 'Too many bookmarks: cannot create any more.' ), - '6.2.0' - ); - return false; - } - - $this->bookmarks[ $name ] = new WP_HTML_Span( $this->token_starts_at, $this->token_length ); - - return true; - } - - - /** - * Removes a bookmark that is no longer needed. - * - * Releasing a bookmark frees up the small - * performance overhead it requires. - * - * @param string $name Name of the bookmark to remove. - * @return bool Whether the bookmark already existed before removal. - */ - public function release_bookmark( $name ) { - if ( ! array_key_exists( $name, $this->bookmarks ) ) { - return false; - } - - unset( $this->bookmarks[ $name ] ); - - return true; - } - - /** - * Skips contents of generic rawtext elements. - * - * @since 6.3.2 - * - * @see https://html.spec.whatwg.org/#generic-raw-text-element-parsing-algorithm - * - * @param string $tag_name The uppercase tag name which will close the RAWTEXT region. - * @return bool Whether an end to the RAWTEXT region was found before the end of the document. - */ - private function skip_rawtext( $tag_name ) { - /* - * These two functions distinguish themselves on whether character references are - * decoded, and since functionality to read the inner markup isn't supported, it's - * not necessary to implement these two functions separately. - */ - return $this->skip_rcdata( $tag_name ); - } - - /** - * Skips contents of RCDATA elements, namely title and textarea tags. - * - * @since 6.2.0 - * - * @see https://html.spec.whatwg.org/multipage/parsing.html#rcdata-state - * - * @param string $tag_name The uppercase tag name which will close the RCDATA region. - * @return bool Whether an end to the RCDATA region was found before the end of the document. - */ - private function skip_rcdata( $tag_name ) { - $html = $this->html; - $doc_length = strlen( $html ); - $tag_length = strlen( $tag_name ); - - $at = $this->bytes_already_parsed; - - while ( false !== $at && $at < $doc_length ) { - $at = strpos( $this->html, '</', $at ); - $this->tag_name_starts_at = $at; - - // Fail if there is no possible tag closer. - if ( false === $at || ( $at + $tag_length ) >= $doc_length ) { - return false; - } - - $at += 2; - - /* - * Find a case-insensitive match to the tag name. - * - * Because tag names are limited to US-ASCII there is no - * need to perform any kind of Unicode normalization when - * comparing; any character which could be impacted by such - * normalization could not be part of a tag name. - */ - for ( $i = 0; $i < $tag_length; $i++ ) { - $tag_char = $tag_name[ $i ]; - $html_char = $html[ $at + $i ]; - - if ( $html_char !== $tag_char && strtoupper( $html_char ) !== $tag_char ) { - $at += $i; - continue 2; - } - } - - $at += $tag_length; - $this->bytes_already_parsed = $at; - - if ( $at >= strlen( $html ) ) { - return false; - } - - /* - * Ensure that the tag name terminates to avoid matching on - * substrings of a longer tag name. For example, the sequence - * "</textarearug" should not match for "</textarea" even - * though "textarea" is found within the text. - */ - $c = $html[ $at ]; - if ( ' ' !== $c && "\t" !== $c && "\r" !== $c && "\n" !== $c && '/' !== $c && '>' !== $c ) { - continue; - } - - while ( $this->parse_next_attribute() ) { - continue; - } - - $at = $this->bytes_already_parsed; - if ( $at >= strlen( $this->html ) ) { - return false; - } - - if ( '>' === $html[ $at ] ) { - $this->bytes_already_parsed = $at + 1; - return true; - } - - if ( $at + 1 >= strlen( $this->html ) ) { - return false; - } - - if ( '/' === $html[ $at ] && '>' === $html[ $at + 1 ] ) { - $this->bytes_already_parsed = $at + 2; - return true; - } - } - - return false; - } - - /** - * Skips contents of script tags. - * - * @since 6.2.0 - * - * @return bool Whether the script tag was closed before the end of the document. - */ - private function skip_script_data() { - $state = 'unescaped'; - $html = $this->html; - $doc_length = strlen( $html ); - $at = $this->bytes_already_parsed; - - while ( false !== $at && $at < $doc_length ) { - $at += strcspn( $html, '-<', $at ); - - /* - * For all script states a "-->" transitions - * back into the normal unescaped script mode, - * even if that's the current state. - */ - if ( - $at + 2 < $doc_length && - '-' === $html[ $at ] && - '-' === $html[ $at + 1 ] && - '>' === $html[ $at + 2 ] - ) { - $at += 3; - $state = 'unescaped'; - continue; - } - - // Everything of interest past here starts with "<". - if ( $at + 1 >= $doc_length || '<' !== $html[ $at++ ] ) { - continue; - } - - /* - * Unlike with "-->", the "<!--" only transitions - * into the escaped mode if not already there. - * - * Inside the escaped modes it will be ignored; and - * should never break out of the double-escaped - * mode and back into the escaped mode. - * - * While this requires a mode change, it does not - * impact the parsing otherwise, so continue - * parsing after updating the state. - */ - if ( - $at + 2 < $doc_length && - '!' === $html[ $at ] && - '-' === $html[ $at + 1 ] && - '-' === $html[ $at + 2 ] - ) { - $at += 3; - $state = 'unescaped' === $state ? 'escaped' : $state; - continue; - } - - if ( '/' === $html[ $at ] ) { - $closer_potentially_starts_at = $at - 1; - $is_closing = true; - ++$at; - } else { - $is_closing = false; - } - - /* - * At this point the only remaining state-changes occur with the - * <script> and </script> tags; unless one of these appears next, - * proceed scanning to the next potential token in the text. - */ - if ( ! ( - $at + 6 < $doc_length && - ( 's' === $html[ $at ] || 'S' === $html[ $at ] ) && - ( 'c' === $html[ $at + 1 ] || 'C' === $html[ $at + 1 ] ) && - ( 'r' === $html[ $at + 2 ] || 'R' === $html[ $at + 2 ] ) && - ( 'i' === $html[ $at + 3 ] || 'I' === $html[ $at + 3 ] ) && - ( 'p' === $html[ $at + 4 ] || 'P' === $html[ $at + 4 ] ) && - ( 't' === $html[ $at + 5 ] || 'T' === $html[ $at + 5 ] ) - ) ) { - ++$at; - continue; - } - - /* - * Ensure that the script tag terminates to avoid matching on - * substrings of a non-match. For example, the sequence - * "<script123" should not end a script region even though - * "<script" is found within the text. - */ - if ( $at + 6 >= $doc_length ) { - continue; - } - $at += 6; - $c = $html[ $at ]; - if ( ' ' !== $c && "\t" !== $c && "\r" !== $c && "\n" !== $c && '/' !== $c && '>' !== $c ) { - ++$at; - continue; - } - - if ( 'escaped' === $state && ! $is_closing ) { - $state = 'double-escaped'; - continue; - } - - if ( 'double-escaped' === $state && $is_closing ) { - $state = 'escaped'; - continue; - } - - if ( $is_closing ) { - $this->bytes_already_parsed = $closer_potentially_starts_at; - $this->tag_name_starts_at = $closer_potentially_starts_at; - if ( $this->bytes_already_parsed >= $doc_length ) { - return false; - } - - while ( $this->parse_next_attribute() ) { - continue; - } - - if ( $this->bytes_already_parsed >= $doc_length ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - if ( '>' === $html[ $this->bytes_already_parsed ] ) { - ++$this->bytes_already_parsed; - return true; - } - } - - ++$at; - } - - return false; - } - - /** - * Parses the next tag. - * - * This will find and start parsing the next tag, including - * the opening `<`, the potential closer `/`, and the tag - * name. It does not parse the attributes or scan to the - * closing `>`; these are left for other methods. - * - * @since 6.2.0 - * @since 6.2.1 Support abruptly-closed comments, invalid-tag-closer-comments, and empty elements. - * - * @return bool Whether a tag was found before the end of the document. - */ - private function parse_next_tag() { - $this->after_tag(); - - $html = $this->html; - $doc_length = strlen( $html ); - $was_at = $this->bytes_already_parsed; - $at = $was_at; - - while ( false !== $at && $at < $doc_length ) { - $at = strpos( $html, '<', $at ); - - /* - * This does not imply an incomplete parse; it indicates that there - * can be nothing left in the document other than a #text node. - */ - if ( false === $at ) { - $this->parser_state = self::STATE_TEXT_NODE; - $this->token_starts_at = $was_at; - $this->token_length = strlen( $html ) - $was_at; - $this->text_starts_at = $was_at; - $this->text_length = $this->token_length; - $this->bytes_already_parsed = strlen( $html ); - return true; - } - - if ( $at > $was_at ) { - /* - * A "<" normally starts a new HTML tag or syntax token, but in cases where the - * following character can't produce a valid token, the "<" is instead treated - * as plaintext and the parser should skip over it. This avoids a problem when - * following earlier practices of typing emoji with text, e.g. "<3". This - * should be a heart, not a tag. It's supposed to be rendered, not hidden. - * - * At this point the parser checks if this is one of those cases and if it is - * will continue searching for the next "<" in search of a token boundary. - * - * @see https://html.spec.whatwg.org/#tag-open-state - */ - if ( strlen( $html ) > $at + 1 ) { - $next_character = $html[ $at + 1 ]; - $at_another_node = ( - '!' === $next_character || - '/' === $next_character || - '?' === $next_character || - ( 'A' <= $next_character && $next_character <= 'Z' ) || - ( 'a' <= $next_character && $next_character <= 'z' ) - ); - if ( ! $at_another_node ) { - ++$at; - continue; - } - } - - $this->parser_state = self::STATE_TEXT_NODE; - $this->token_starts_at = $was_at; - $this->token_length = $at - $was_at; - $this->text_starts_at = $was_at; - $this->text_length = $this->token_length; - $this->bytes_already_parsed = $at; - return true; - } - - $this->token_starts_at = $at; - - if ( $at + 1 < $doc_length && '/' === $this->html[ $at + 1 ] ) { - $this->is_closing_tag = true; - ++$at; - } else { - $this->is_closing_tag = false; - } - - /* - * HTML tag names must start with [a-zA-Z] otherwise they are not tags. - * For example, "<3" is rendered as text, not a tag opener. If at least - * one letter follows the "<" then _it is_ a tag, but if the following - * character is anything else it _is not a tag_. - * - * It's not uncommon to find non-tags starting with `<` in an HTML - * document, so it's good for performance to make this pre-check before - * continuing to attempt to parse a tag name. - * - * Reference: - * * https://html.spec.whatwg.org/multipage/parsing.html#data-state - * * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state - */ - $tag_name_prefix_length = strspn( $html, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', $at + 1 ); - if ( $tag_name_prefix_length > 0 ) { - ++$at; - $this->parser_state = self::STATE_MATCHED_TAG; - $this->tag_name_starts_at = $at; - $this->tag_name_length = $tag_name_prefix_length + strcspn( $html, " \t\f\r\n/>", $at + $tag_name_prefix_length ); - $this->bytes_already_parsed = $at + $this->tag_name_length; - return true; - } - - /* - * Abort if no tag is found before the end of - * the document. There is nothing left to parse. - */ - if ( $at + 1 >= $doc_length ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - /* - * `<!` transitions to markup declaration open state - * https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state - */ - if ( ! $this->is_closing_tag && '!' === $html[ $at + 1 ] ) { - /* - * `<!--` transitions to a comment state – apply further comment rules. - * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state - */ - if ( - $doc_length > $at + 3 && - '-' === $html[ $at + 2 ] && - '-' === $html[ $at + 3 ] - ) { - $closer_at = $at + 4; - // If it's not possible to close the comment then there is nothing more to scan. - if ( $doc_length <= $closer_at ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - // Abruptly-closed empty comments are a sequence of dashes followed by `>`. - $span_of_dashes = strspn( $html, '-', $closer_at ); - if ( '>' === $html[ $closer_at + $span_of_dashes ] ) { - /* - * @todo When implementing `set_modifiable_text()` ensure that updates to this token - * don't break the syntax for short comments, e.g. `<!--->`. Unlike other comment - * and bogus comment syntax, these leave no clear insertion point for text and - * they need to be modified specially in order to contain text. E.g. to store - * `?` as the modifiable text, the `<!--->` needs to become `<!--?-->`, which - * involves inserting an additional `-` into the token after the modifiable text. - */ - $this->parser_state = self::STATE_COMMENT; - $this->comment_type = self::COMMENT_AS_ABRUPTLY_CLOSED_COMMENT; - $this->token_length = $closer_at + $span_of_dashes + 1 - $this->token_starts_at; - - // Only provide modifiable text if the token is long enough to contain it. - if ( $span_of_dashes >= 2 ) { - $this->comment_type = self::COMMENT_AS_HTML_COMMENT; - $this->text_starts_at = $this->token_starts_at + 4; - $this->text_length = $span_of_dashes - 2; - } - - $this->bytes_already_parsed = $closer_at + $span_of_dashes + 1; - return true; - } - - /* - * Comments may be closed by either a --> or an invalid --!>. - * The first occurrence closes the comment. - * - * See https://html.spec.whatwg.org/#parse-error-incorrectly-closed-comment - */ - --$closer_at; // Pre-increment inside condition below reduces risk of accidental infinite looping. - while ( ++$closer_at < $doc_length ) { - $closer_at = strpos( $html, '--', $closer_at ); - if ( false === $closer_at ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - if ( $closer_at + 2 < $doc_length && '>' === $html[ $closer_at + 2 ] ) { - $this->parser_state = self::STATE_COMMENT; - $this->comment_type = self::COMMENT_AS_HTML_COMMENT; - $this->token_length = $closer_at + 3 - $this->token_starts_at; - $this->text_starts_at = $this->token_starts_at + 4; - $this->text_length = $closer_at - $this->text_starts_at; - $this->bytes_already_parsed = $closer_at + 3; - return true; - } - - if ( - $closer_at + 3 < $doc_length && - '!' === $html[ $closer_at + 2 ] && - '>' === $html[ $closer_at + 3 ] - ) { - $this->parser_state = self::STATE_COMMENT; - $this->comment_type = self::COMMENT_AS_HTML_COMMENT; - $this->token_length = $closer_at + 4 - $this->token_starts_at; - $this->text_starts_at = $this->token_starts_at + 4; - $this->text_length = $closer_at - $this->text_starts_at; - $this->bytes_already_parsed = $closer_at + 4; - return true; - } - } - } - - /* - * `<!DOCTYPE` transitions to DOCTYPE state – skip to the nearest > - * These are ASCII-case-insensitive. - * https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state - */ - if ( - $doc_length > $at + 8 && - ( 'D' === $html[ $at + 2 ] || 'd' === $html[ $at + 2 ] ) && - ( 'O' === $html[ $at + 3 ] || 'o' === $html[ $at + 3 ] ) && - ( 'C' === $html[ $at + 4 ] || 'c' === $html[ $at + 4 ] ) && - ( 'T' === $html[ $at + 5 ] || 't' === $html[ $at + 5 ] ) && - ( 'Y' === $html[ $at + 6 ] || 'y' === $html[ $at + 6 ] ) && - ( 'P' === $html[ $at + 7 ] || 'p' === $html[ $at + 7 ] ) && - ( 'E' === $html[ $at + 8 ] || 'e' === $html[ $at + 8 ] ) - ) { - $closer_at = strpos( $html, '>', $at + 9 ); - if ( false === $closer_at ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - $this->parser_state = self::STATE_DOCTYPE; - $this->token_length = $closer_at + 1 - $this->token_starts_at; - $this->text_starts_at = $this->token_starts_at + 9; - $this->text_length = $closer_at - $this->text_starts_at; - $this->bytes_already_parsed = $closer_at + 1; - return true; - } - - /* - * Anything else here is an incorrectly-opened comment and transitions - * to the bogus comment state - skip to the nearest >. If no closer is - * found then the HTML was truncated inside the markup declaration. - */ - $closer_at = strpos( $html, '>', $at + 1 ); - if ( false === $closer_at ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - $this->parser_state = self::STATE_COMMENT; - $this->comment_type = self::COMMENT_AS_INVALID_HTML; - $this->token_length = $closer_at + 1 - $this->token_starts_at; - $this->text_starts_at = $this->token_starts_at + 2; - $this->text_length = $closer_at - $this->text_starts_at; - $this->bytes_already_parsed = $closer_at + 1; - - /* - * Identify nodes that would be CDATA if HTML had CDATA sections. - * - * This section must occur after identifying the bogus comment end - * because in an HTML parser it will span to the nearest `>`, even - * if there's no `]]>` as would be required in an XML document. It - * is therefore not possible to parse a CDATA section containing - * a `>` in the HTML syntax. - * - * Inside foreign elements there is a discrepancy between browsers - * and the specification on this. - * - * @todo Track whether the Tag Processor is inside a foreign element - * and require the proper closing `]]>` in those cases. - */ - if ( - $this->token_length >= 10 && - '[' === $html[ $this->token_starts_at + 2 ] && - 'C' === $html[ $this->token_starts_at + 3 ] && - 'D' === $html[ $this->token_starts_at + 4 ] && - 'A' === $html[ $this->token_starts_at + 5 ] && - 'T' === $html[ $this->token_starts_at + 6 ] && - 'A' === $html[ $this->token_starts_at + 7 ] && - '[' === $html[ $this->token_starts_at + 8 ] && - ']' === $html[ $closer_at - 1 ] && - ']' === $html[ $closer_at - 2 ] - ) { - $this->parser_state = self::STATE_COMMENT; - $this->comment_type = self::COMMENT_AS_CDATA_LOOKALIKE; - $this->text_starts_at += 7; - $this->text_length -= 9; - } - - return true; - } - - /* - * </> is a missing end tag name, which is ignored. - * - * This was also known as the "presumptuous empty tag" - * in early discussions as it was proposed to close - * the nearest previous opening tag. - * - * See https://html.spec.whatwg.org/#parse-error-missing-end-tag-name - */ - if ( '>' === $html[ $at + 1 ] ) { - // `<>` is interpreted as plaintext. - if ( ! $this->is_closing_tag ) { - ++$at; - continue; - } - - $this->parser_state = self::STATE_PRESUMPTUOUS_TAG; - $this->token_length = $at + 2 - $this->token_starts_at; - $this->bytes_already_parsed = $at + 2; - return true; - } - - /* - * `<?` transitions to a bogus comment state – skip to the nearest > - * See https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state - */ - if ( ! $this->is_closing_tag && '?' === $html[ $at + 1 ] ) { - $closer_at = strpos( $html, '>', $at + 2 ); - if ( false === $closer_at ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - $this->parser_state = self::STATE_COMMENT; - $this->comment_type = self::COMMENT_AS_INVALID_HTML; - $this->token_length = $closer_at + 1 - $this->token_starts_at; - $this->text_starts_at = $this->token_starts_at + 2; - $this->text_length = $closer_at - $this->text_starts_at; - $this->bytes_already_parsed = $closer_at + 1; - - /* - * Identify a Processing Instruction node were HTML to have them. - * - * This section must occur after identifying the bogus comment end - * because in an HTML parser it will span to the nearest `>`, even - * if there's no `?>` as would be required in an XML document. It - * is therefore not possible to parse a Processing Instruction node - * containing a `>` in the HTML syntax. - * - * XML allows for more target names, but this code only identifies - * those with ASCII-representable target names. This means that it - * may identify some Processing Instruction nodes as bogus comments, - * but it will not misinterpret the HTML structure. By limiting the - * identification to these target names the Tag Processor can avoid - * the need to start parsing UTF-8 sequences. - * - * > NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | - * [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | - * [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | - * [#x10000-#xEFFFF] - * > NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] - * - * @see https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-PITarget - */ - if ( $this->token_length >= 5 && '?' === $html[ $closer_at - 1 ] ) { - $comment_text = substr( $html, $this->token_starts_at + 2, $this->token_length - 4 ); - $pi_target_length = strspn( $comment_text, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:_' ); - - if ( 0 < $pi_target_length ) { - $pi_target_length += strspn( $comment_text, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:_-.', $pi_target_length ); - - $this->comment_type = self::COMMENT_AS_PI_NODE_LOOKALIKE; - $this->tag_name_starts_at = $this->token_starts_at + 2; - $this->tag_name_length = $pi_target_length; - $this->text_starts_at += $pi_target_length; - $this->text_length -= $pi_target_length + 1; - } - } - - return true; - } - - /* - * If a non-alpha starts the tag name in a tag closer it's a comment. - * Find the first `>`, which closes the comment. - * - * This parser classifies these particular comments as special "funky comments" - * which are made available for further processing. - * - * See https://html.spec.whatwg.org/#parse-error-invalid-first-character-of-tag-name - */ - if ( $this->is_closing_tag ) { - // No chance of finding a closer. - if ( $at + 3 > $doc_length ) { - return false; - } - - $closer_at = strpos( $html, '>', $at + 2 ); - if ( false === $closer_at ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - $this->parser_state = self::STATE_FUNKY_COMMENT; - $this->token_length = $closer_at + 1 - $this->token_starts_at; - $this->text_starts_at = $this->token_starts_at + 2; - $this->text_length = $closer_at - $this->text_starts_at; - $this->bytes_already_parsed = $closer_at + 1; - return true; - } - - ++$at; - } - - return false; - } - - /** - * Parses the next attribute. - * - * @since 6.2.0 - * - * @return bool Whether an attribute was found before the end of the document. - */ - private function parse_next_attribute() { - // Skip whitespace and slashes. - $this->bytes_already_parsed += strspn( $this->html, " \t\f\r\n/", $this->bytes_already_parsed ); - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - /* - * Treat the equal sign as a part of the attribute - * name if it is the first encountered byte. - * - * @see https://html.spec.whatwg.org/multipage/parsing.html#before-attribute-name-state - */ - $name_length = '=' === $this->html[ $this->bytes_already_parsed ] - ? 1 + strcspn( $this->html, "=/> \t\f\r\n", $this->bytes_already_parsed + 1 ) - : strcspn( $this->html, "=/> \t\f\r\n", $this->bytes_already_parsed ); - - // No attribute, just tag closer. - if ( 0 === $name_length || $this->bytes_already_parsed + $name_length >= strlen( $this->html ) ) { - return false; - } - - $attribute_start = $this->bytes_already_parsed; - $attribute_name = substr( $this->html, $attribute_start, $name_length ); - $this->bytes_already_parsed += $name_length; - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - $this->skip_whitespace(); - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - $has_value = '=' === $this->html[ $this->bytes_already_parsed ]; - if ( $has_value ) { - ++$this->bytes_already_parsed; - $this->skip_whitespace(); - if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - switch ( $this->html[ $this->bytes_already_parsed ] ) { - case "'": - case '"': - $quote = $this->html[ $this->bytes_already_parsed ]; - $value_start = $this->bytes_already_parsed + 1; - $value_length = strcspn( $this->html, $quote, $value_start ); - $attribute_end = $value_start + $value_length + 1; - $this->bytes_already_parsed = $attribute_end; - break; - - default: - $value_start = $this->bytes_already_parsed; - $value_length = strcspn( $this->html, "> \t\f\r\n", $value_start ); - $attribute_end = $value_start + $value_length; - $this->bytes_already_parsed = $attribute_end; - } - } else { - $value_start = $this->bytes_already_parsed; - $value_length = 0; - $attribute_end = $attribute_start + $name_length; - } - - if ( $attribute_end >= strlen( $this->html ) ) { - $this->parser_state = self::STATE_INCOMPLETE_INPUT; - - return false; - } - - if ( $this->is_closing_tag ) { - return true; - } - - /* - * > There must never be two or more attributes on - * > the same start tag whose names are an ASCII - * > case-insensitive match for each other. - * - HTML 5 spec - * - * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive - */ - $comparable_name = strtolower( $attribute_name ); - - // If an attribute is listed many times, only use the first declaration and ignore the rest. - if ( ! array_key_exists( $comparable_name, $this->attributes ) ) { - $this->attributes[ $comparable_name ] = new WP_HTML_Attribute_Token( - $attribute_name, - $value_start, - $value_length, - $attribute_start, - $attribute_end - $attribute_start, - ! $has_value - ); - - return true; - } - - /* - * Track the duplicate attributes so if we remove it, all disappear together. - * - * While `$this->duplicated_attributes` could always be stored as an `array()`, - * which would simplify the logic here, storing a `null` and only allocating - * an array when encountering duplicates avoids needless allocations in the - * normative case of parsing tags with no duplicate attributes. - */ - $duplicate_span = new WP_HTML_Span( $attribute_start, $attribute_end - $attribute_start ); - if ( null === $this->duplicate_attributes ) { - $this->duplicate_attributes = array( $comparable_name => array( $duplicate_span ) ); - } elseif ( ! array_key_exists( $comparable_name, $this->duplicate_attributes ) ) { - $this->duplicate_attributes[ $comparable_name ] = array( $duplicate_span ); - } else { - $this->duplicate_attributes[ $comparable_name ][] = $duplicate_span; - } - - return true; - } - - /** - * Move the internal cursor past any immediate successive whitespace. - * - * @since 6.2.0 - */ - private function skip_whitespace() { - $this->bytes_already_parsed += strspn( $this->html, " \t\f\r\n", $this->bytes_already_parsed ); - } - - /** - * Applies attribute updates and cleans up once a tag is fully parsed. - * - * @since 6.2.0 - */ - private function after_tag() { - /* - * There could be lexical updates enqueued for an attribute that - * also exists on the next tag. In order to avoid conflating the - * attributes across the two tags, lexical updates with names - * need to be flushed to raw lexical updates. - */ - $this->class_name_updates_to_attributes_updates(); - - /* - * Purge updates if there are too many. The actual count isn't - * scientific, but a few values from 100 to a few thousand were - * tests to find a practically-useful limit. - * - * If the update queue grows too big, then the Tag Processor - * will spend more time iterating through them and lose the - * efficiency gains of deferring applying them. - */ - if ( 1000 < count( $this->lexical_updates ) ) { - $this->get_updated_html(); - } - - foreach ( $this->lexical_updates as $name => $update ) { - /* - * Any updates appearing after the cursor should be applied - * before proceeding, otherwise they may be overlooked. - */ - if ( $update->start >= $this->bytes_already_parsed ) { - $this->get_updated_html(); - break; - } - - if ( is_int( $name ) ) { - continue; - } - - $this->lexical_updates[] = $update; - unset( $this->lexical_updates[ $name ] ); - } - - $this->token_starts_at = null; - $this->token_length = null; - $this->tag_name_starts_at = null; - $this->tag_name_length = null; - $this->text_starts_at = 0; - $this->text_length = 0; - $this->is_closing_tag = null; - $this->attributes = array(); - $this->comment_type = null; - $this->duplicate_attributes = null; - } - - /** - * Converts class name updates into tag attributes updates - * (they are accumulated in different data formats for performance). - * - * @since 6.2.0 - * - * @see WP_HTML_Tag_Processor::$lexical_updates - * @see WP_HTML_Tag_Processor::$classname_updates - */ - private function class_name_updates_to_attributes_updates() { - if ( count( $this->classname_updates ) === 0 ) { - return; - } - - $existing_class = $this->get_enqueued_attribute_value( 'class' ); - if ( null === $existing_class || true === $existing_class ) { - $existing_class = ''; - } - - if ( false === $existing_class && isset( $this->attributes['class'] ) ) { - $existing_class = substr( - $this->html, - $this->attributes['class']->value_starts_at, - $this->attributes['class']->value_length - ); - } - - if ( false === $existing_class ) { - $existing_class = ''; - } - - /** - * Updated "class" attribute value. - * - * This is incrementally built while scanning through the existing class - * attribute, skipping removed classes on the way, and then appending - * added classes at the end. Only when finished processing will the - * value contain the final new value. - - * @var string $class - */ - $class = ''; - - /** - * Tracks the cursor position in the existing - * class attribute value while parsing. - * - * @var int $at - */ - $at = 0; - - /** - * Indicates if there's any need to modify the existing class attribute. - * - * If a call to `add_class()` and `remove_class()` wouldn't impact - * the `class` attribute value then there's no need to rebuild it. - * For example, when adding a class that's already present or - * removing one that isn't. - * - * This flag enables a performance optimization when none of the enqueued - * class updates would impact the `class` attribute; namely, that the - * processor can continue without modifying the input document, as if - * none of the `add_class()` or `remove_class()` calls had been made. - * - * This flag is set upon the first change that requires a string update. - * - * @var bool $modified - */ - $modified = false; - - // Remove unwanted classes by only copying the new ones. - $existing_class_length = strlen( $existing_class ); - while ( $at < $existing_class_length ) { - // Skip to the first non-whitespace character. - $ws_at = $at; - $ws_length = strspn( $existing_class, " \t\f\r\n", $ws_at ); - $at += $ws_length; - - // Capture the class name – it's everything until the next whitespace. - $name_length = strcspn( $existing_class, " \t\f\r\n", $at ); - if ( 0 === $name_length ) { - // If no more class names are found then that's the end. - break; - } - - $name = substr( $existing_class, $at, $name_length ); - $at += $name_length; - - // If this class is marked for removal, start processing the next one. - $remove_class = ( - isset( $this->classname_updates[ $name ] ) && - self::REMOVE_CLASS === $this->classname_updates[ $name ] - ); - - // If a class has already been seen then skip it; it should not be added twice. - if ( ! $remove_class ) { - $this->classname_updates[ $name ] = self::SKIP_CLASS; - } - - if ( $remove_class ) { - $modified = true; - continue; - } - - /* - * Otherwise, append it to the new "class" attribute value. - * - * There are options for handling whitespace between tags. - * Preserving the existing whitespace produces fewer changes - * to the HTML content and should clarify the before/after - * content when debugging the modified output. - * - * This approach contrasts normalizing the inter-class - * whitespace to a single space, which might appear cleaner - * in the output HTML but produce a noisier change. - */ - $class .= substr( $existing_class, $ws_at, $ws_length ); - $class .= $name; - } - - // Add new classes by appending those which haven't already been seen. - foreach ( $this->classname_updates as $name => $operation ) { - if ( self::ADD_CLASS === $operation ) { - $modified = true; - - $class .= strlen( $class ) > 0 ? ' ' : ''; - $class .= $name; - } - } - - $this->classname_updates = array(); - if ( ! $modified ) { - return; - } - - if ( strlen( $class ) > 0 ) { - $this->set_attribute( 'class', $class ); - } else { - $this->remove_attribute( 'class' ); - } - } - - /** - * Applies attribute updates to HTML document. - * - * @since 6.2.0 - * @since 6.2.1 Accumulates shift for internal cursor and passed pointer. - * @since 6.3.0 Invalidate any bookmarks whose targets are overwritten. - * - * @param int $shift_this_point Accumulate and return shift for this position. - * @return int How many bytes the given pointer moved in response to the updates. - */ - private function apply_attributes_updates( $shift_this_point ) { - if ( ! count( $this->lexical_updates ) ) { - return 0; - } - - $accumulated_shift_for_given_point = 0; - - /* - * Attribute updates can be enqueued in any order but updates - * to the document must occur in lexical order; that is, each - * replacement must be made before all others which follow it - * at later string indices in the input document. - * - * Sorting avoid making out-of-order replacements which - * can lead to mangled output, partially-duplicated - * attributes, and overwritten attributes. - */ - usort( $this->lexical_updates, array( self::class, 'sort_start_ascending' ) ); - - $bytes_already_copied = 0; - $output_buffer = ''; - foreach ( $this->lexical_updates as $diff ) { - $shift = strlen( $diff->text ) - $diff->length; - - // Adjust the cursor position by however much an update affects it. - if ( $diff->start < $this->bytes_already_parsed ) { - $this->bytes_already_parsed += $shift; - } - - // Accumulate shift of the given pointer within this function call. - if ( $diff->start <= $shift_this_point ) { - $accumulated_shift_for_given_point += $shift; - } - - $output_buffer .= substr( $this->html, $bytes_already_copied, $diff->start - $bytes_already_copied ); - $output_buffer .= $diff->text; - $bytes_already_copied = $diff->start + $diff->length; - } - - $this->html = $output_buffer . substr( $this->html, $bytes_already_copied ); - - /* - * Adjust bookmark locations to account for how the text - * replacements adjust offsets in the input document. - */ - foreach ( $this->bookmarks as $bookmark_name => $bookmark ) { - $bookmark_end = $bookmark->start + $bookmark->length; - - /* - * Each lexical update which appears before the bookmark's endpoints - * might shift the offsets for those endpoints. Loop through each change - * and accumulate the total shift for each bookmark, then apply that - * shift after tallying the full delta. - */ - $head_delta = 0; - $tail_delta = 0; - - foreach ( $this->lexical_updates as $diff ) { - $diff_end = $diff->start + $diff->length; - - if ( $bookmark->start < $diff->start && $bookmark_end < $diff->start ) { - break; - } - - if ( $bookmark->start >= $diff->start && $bookmark_end < $diff_end ) { - $this->release_bookmark( $bookmark_name ); - continue 2; - } - - $delta = strlen( $diff->text ) - $diff->length; - - if ( $bookmark->start >= $diff->start ) { - $head_delta += $delta; - } - - if ( $bookmark_end >= $diff_end ) { - $tail_delta += $delta; - } - } - - $bookmark->start += $head_delta; - $bookmark->length += $tail_delta - $head_delta; - } - - $this->lexical_updates = array(); - - return $accumulated_shift_for_given_point; - } - - /** - * Checks whether a bookmark with the given name exists. - * - * @since 6.3.0 - * - * @param string $bookmark_name Name to identify a bookmark that potentially exists. - * @return bool Whether that bookmark exists. - */ - public function has_bookmark( $bookmark_name ) { - return array_key_exists( $bookmark_name, $this->bookmarks ); - } - - /** - * Move the internal cursor in the Tag Processor to a given bookmark's location. - * - * In order to prevent accidental infinite loops, there's a - * maximum limit on the number of times seek() can be called. - * - * @since 6.2.0 - * - * @param string $bookmark_name Jump to the place in the document identified by this bookmark name. - * @return bool Whether the internal cursor was successfully moved to the bookmark's location. - */ - public function seek( $bookmark_name ) { - if ( ! array_key_exists( $bookmark_name, $this->bookmarks ) ) { - _doing_it_wrong( - __METHOD__, - __( 'Unknown bookmark name.' ), - '6.2.0' - ); - return false; - } - - if ( ++$this->seek_count > static::MAX_SEEK_OPS ) { - _doing_it_wrong( - __METHOD__, - __( 'Too many calls to seek() - this can lead to performance issues.' ), - '6.2.0' - ); - return false; - } - - // Flush out any pending updates to the document. - $this->get_updated_html(); - - // Point this tag processor before the sought tag opener and consume it. - $this->bytes_already_parsed = $this->bookmarks[ $bookmark_name ]->start; - $this->parser_state = self::STATE_READY; - return $this->next_token(); - } - - /** - * Compare two WP_HTML_Text_Replacement objects. - * - * @since 6.2.0 - * - * @param WP_HTML_Text_Replacement $a First attribute update. - * @param WP_HTML_Text_Replacement $b Second attribute update. - * @return int Comparison value for string order. - */ - private static function sort_start_ascending( $a, $b ) { - $by_start = $a->start - $b->start; - if ( 0 !== $by_start ) { - return $by_start; - } - - $by_text = isset( $a->text, $b->text ) ? strcmp( $a->text, $b->text ) : 0; - if ( 0 !== $by_text ) { - return $by_text; - } - - /* - * This code should be unreachable, because it implies the two replacements - * start at the same location and contain the same text. - */ - return $a->length - $b->length; - } - - /** - * Return the enqueued value for a given attribute, if one exists. - * - * Enqueued updates can take different data types: - * - If an update is enqueued and is boolean, the return will be `true` - * - If an update is otherwise enqueued, the return will be the string value of that update. - * - If an attribute is enqueued to be removed, the return will be `null` to indicate that. - * - If no updates are enqueued, the return will be `false` to differentiate from "removed." - * - * @since 6.2.0 - * - * @param string $comparable_name The attribute name in its comparable form. - * @return string|boolean|null Value of enqueued update if present, otherwise false. - */ - private function get_enqueued_attribute_value( $comparable_name ) { - if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { - return false; - } - - if ( ! isset( $this->lexical_updates[ $comparable_name ] ) ) { - return false; - } - - $enqueued_text = $this->lexical_updates[ $comparable_name ]->text; - - // Removed attributes erase the entire span. - if ( '' === $enqueued_text ) { - return null; - } - - /* - * Boolean attribute updates are just the attribute name without a corresponding value. - * - * This value might differ from the given comparable name in that there could be leading - * or trailing whitespace, and that the casing follows the name given in `set_attribute`. - * - * Example: - * - * $p->set_attribute( 'data-TEST-id', 'update' ); - * 'update' === $p->get_enqueued_attribute_value( 'data-test-id' ); - * - * Detect this difference based on the absence of the `=`, which _must_ exist in any - * attribute containing a value, e.g. `<input type="text" enabled />`. - * ¹ ² - * 1. Attribute with a string value. - * 2. Boolean attribute whose value is `true`. - */ - $equals_at = strpos( $enqueued_text, '=' ); - if ( false === $equals_at ) { - return true; - } - - /* - * Finally, a normal update's value will appear after the `=` and - * be double-quoted, as performed incidentally by `set_attribute`. - * - * e.g. `type="text"` - * ¹² ³ - * 1. Equals is here. - * 2. Double-quoting starts one after the equals sign. - * 3. Double-quoting ends at the last character in the update. - */ - $enqueued_value = substr( $enqueued_text, $equals_at + 2, -1 ); - return Gutenberg_HTML_Decoder_6_6::decode_attribute( $enqueued_value ); - } - - /** - * Returns the value of a requested attribute from a matched tag opener if that attribute exists. - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( '<div enabled class="test" data-test-id="14">Test</div>' ); - * $p->next_tag( array( 'class_name' => 'test' ) ) === true; - * $p->get_attribute( 'data-test-id' ) === '14'; - * $p->get_attribute( 'enabled' ) === true; - * $p->get_attribute( 'aria-label' ) === null; - * - * $p->next_tag() === false; - * $p->get_attribute( 'class' ) === null; - * - * @since 6.2.0 - * - * @param string $name Name of attribute whose value is requested. - * @return string|true|null Value of attribute or `null` if not available. Boolean attributes return `true`. - */ - public function get_attribute( $name ) { - if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { - return null; - } - - $comparable = strtolower( $name ); - - /* - * For every attribute other than `class` it's possible to perform a quick check if - * there's an enqueued lexical update whose value takes priority over what's found in - * the input document. - * - * The `class` attribute is special though because of the exposed helpers `add_class` - * and `remove_class`. These form a builder for the `class` attribute, so an additional - * check for enqueued class changes is required in addition to the check for any enqueued - * attribute values. If any exist, those enqueued class changes must first be flushed out - * into an attribute value update. - */ - if ( 'class' === $name ) { - $this->class_name_updates_to_attributes_updates(); - } - - // Return any enqueued attribute value updates if they exist. - $enqueued_value = $this->get_enqueued_attribute_value( $comparable ); - if ( false !== $enqueued_value ) { - return $enqueued_value; - } - - if ( ! isset( $this->attributes[ $comparable ] ) ) { - return null; - } - - $attribute = $this->attributes[ $comparable ]; - - /* - * This flag distinguishes an attribute with no value - * from an attribute with an empty string value. For - * unquoted attributes this could look very similar. - * It refers to whether an `=` follows the name. - * - * e.g. <div boolean-attribute empty-attribute=></div> - * ¹ ² - * 1. Attribute `boolean-attribute` is `true`. - * 2. Attribute `empty-attribute` is `""`. - */ - if ( true === $attribute->is_true ) { - return true; - } - - $raw_value = substr( $this->html, $attribute->value_starts_at, $attribute->value_length ); - - return Gutenberg_HTML_Decoder_6_6::decode_attribute( $raw_value ); - } - - /** - * Gets lowercase names of all attributes matching a given prefix in the current tag. - * - * Note that matching is case-insensitive. This is in accordance with the spec: - * - * > There must never be two or more attributes on - * > the same start tag whose names are an ASCII - * > case-insensitive match for each other. - * - HTML 5 spec - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( '<div data-ENABLED class="test" DATA-test-id="14">Test</div>' ); - * $p->next_tag( array( 'class_name' => 'test' ) ) === true; - * $p->get_attribute_names_with_prefix( 'data-' ) === array( 'data-enabled', 'data-test-id' ); - * - * $p->next_tag() === false; - * $p->get_attribute_names_with_prefix( 'data-' ) === null; - * - * @since 6.2.0 - * - * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive - * - * @param string $prefix Prefix of requested attribute names. - * @return array|null List of attribute names, or `null` when no tag opener is matched. - */ - public function get_attribute_names_with_prefix( $prefix ) { - if ( - self::STATE_MATCHED_TAG !== $this->parser_state || - $this->is_closing_tag - ) { - return null; - } - - $comparable = strtolower( $prefix ); - - $matches = array(); - foreach ( array_keys( $this->attributes ) as $attr_name ) { - if ( str_starts_with( $attr_name, $comparable ) ) { - $matches[] = $attr_name; - } - } - return $matches; - } - - /** - * Returns the uppercase name of the matched tag. - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( '<div class="test">Test</div>' ); - * $p->next_tag() === true; - * $p->get_tag() === 'DIV'; - * - * $p->next_tag() === false; - * $p->get_tag() === null; - * - * @since 6.2.0 - * - * @return string|null Name of currently matched tag in input HTML, or `null` if none found. - */ - public function get_tag() { - if ( null === $this->tag_name_starts_at ) { - return null; - } - - $tag_name = substr( $this->html, $this->tag_name_starts_at, $this->tag_name_length ); - - if ( self::STATE_MATCHED_TAG === $this->parser_state ) { - return strtoupper( $tag_name ); - } - - if ( - self::STATE_COMMENT === $this->parser_state && - self::COMMENT_AS_PI_NODE_LOOKALIKE === $this->get_comment_type() - ) { - return $tag_name; - } - - return null; - } - - /** - * Indicates if the currently matched tag contains the self-closing flag. - * - * No HTML elements ought to have the self-closing flag and for those, the self-closing - * flag will be ignored. For void elements this is benign because they "self close" - * automatically. For non-void HTML elements though problems will appear if someone - * intends to use a self-closing element in place of that element with an empty body. - * For HTML foreign elements and custom elements the self-closing flag determines if - * they self-close or not. - * - * This function does not determine if a tag is self-closing, - * but only if the self-closing flag is present in the syntax. - * - * @since 6.3.0 - * - * @return bool Whether the currently matched tag contains the self-closing flag. - */ - public function has_self_closing_flag() { - if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { - return false; - } - - /* - * The self-closing flag is the solidus at the _end_ of the tag, not the beginning. - * - * Example: - * - * <figure /> - * ^ this appears one character before the end of the closing ">". - */ - return '/' === $this->html[ $this->token_starts_at + $this->token_length - 2 ]; - } - - /** - * Indicates if the current tag token is a tag closer. - * - * Example: - * - * $p = new WP_HTML_Tag_Processor( '<div></div>' ); - * $p->next_tag( array( 'tag_name' => 'div', 'tag_closers' => 'visit' ) ); - * $p->is_tag_closer() === false; - * - * $p->next_tag( array( 'tag_name' => 'div', 'tag_closers' => 'visit' ) ); - * $p->is_tag_closer() === true; - * - * @since 6.2.0 - * - * @return bool Whether the current tag is a tag closer. - */ - public function is_tag_closer() { - return ( - self::STATE_MATCHED_TAG === $this->parser_state && - $this->is_closing_tag - ); - } - - /** - * Indicates the kind of matched token, if any. - * - * This differs from `get_token_name()` in that it always - * returns a static string indicating the type, whereas - * `get_token_name()` may return values derived from the - * token itself, such as a tag name or processing - * instruction tag. - * - * Possible values: - * - `#tag` when matched on a tag. - * - `#text` when matched on a text node. - * - `#cdata-section` when matched on a CDATA node. - * - `#comment` when matched on a comment. - * - `#doctype` when matched on a DOCTYPE declaration. - * - `#presumptuous-tag` when matched on an empty tag closer. - * - `#funky-comment` when matched on a funky comment. - * - * @since 6.5.0 - * - * @return string|null What kind of token is matched, or null. - */ - public function get_token_type() { - switch ( $this->parser_state ) { - case self::STATE_MATCHED_TAG: - return '#tag'; - - case self::STATE_DOCTYPE: - return '#doctype'; - - default: - return $this->get_token_name(); - } - } - - /** - * Returns the node name represented by the token. - * - * This matches the DOM API value `nodeName`. Some values - * are static, such as `#text` for a text node, while others - * are dynamically generated from the token itself. - * - * Dynamic names: - * - Uppercase tag name for tag matches. - * - `html` for DOCTYPE declarations. - * - * Note that if the Tag Processor is not matched on a token - * then this function will return `null`, either because it - * hasn't yet found a token or because it reached the end - * of the document without matching a token. - * - * @since 6.5.0 - * - * @return string|null Name of the matched token. - */ - public function get_token_name() { - switch ( $this->parser_state ) { - case self::STATE_MATCHED_TAG: - return $this->get_tag(); - - case self::STATE_TEXT_NODE: - return '#text'; - - case self::STATE_CDATA_NODE: - return '#cdata-section'; - - case self::STATE_COMMENT: - return '#comment'; - - case self::STATE_DOCTYPE: - return 'html'; - - case self::STATE_PRESUMPTUOUS_TAG: - return '#presumptuous-tag'; - - case self::STATE_FUNKY_COMMENT: - return '#funky-comment'; - } - - return null; - } - - /** - * Indicates what kind of comment produced the comment node. - * - * Because there are different kinds of HTML syntax which produce - * comments, the Tag Processor tracks and exposes this as a type - * for the comment. Nominally only regular HTML comments exist as - * they are commonly known, but a number of unrelated syntax errors - * also produce comments. - * - * @see self::COMMENT_AS_ABRUPTLY_CLOSED_COMMENT - * @see self::COMMENT_AS_CDATA_LOOKALIKE - * @see self::COMMENT_AS_INVALID_HTML - * @see self::COMMENT_AS_HTML_COMMENT - * @see self::COMMENT_AS_PI_NODE_LOOKALIKE - * - * @since 6.5.0 - * - * @return string|null - */ - public function get_comment_type() { - if ( self::STATE_COMMENT !== $this->parser_state ) { - return null; - } - - return $this->comment_type; - } - - /** - * Returns the modifiable text for a matched token, or an empty string. - * - * Modifiable text is text content that may be read and changed without - * changing the HTML structure of the document around it. This includes - * the contents of `#text` nodes in the HTML as well as the inner - * contents of HTML comments, Processing Instructions, and others, even - * though these nodes aren't part of a parsed DOM tree. They also contain - * the contents of SCRIPT and STYLE tags, of TEXTAREA tags, and of any - * other section in an HTML document which cannot contain HTML markup (DATA). - * - * If a token has no modifiable text then an empty string is returned to - * avoid needless crashing or type errors. An empty string does not mean - * that a token has modifiable text, and a token with modifiable text may - * have an empty string (e.g. a comment with no contents). - * - * @since 6.5.0 - * - * @return string - */ - public function get_modifiable_text() { - if ( null === $this->text_starts_at ) { - return ''; - } - - $text = substr( $this->html, $this->text_starts_at, $this->text_length ); - - // Comment data is not decoded. - if ( - self::STATE_CDATA_NODE === $this->parser_state || - self::STATE_COMMENT === $this->parser_state || - self::STATE_DOCTYPE === $this->parser_state || - self::STATE_FUNKY_COMMENT === $this->parser_state - ) { - return $text; - } - - $tag_name = $this->get_tag(); - if ( - // Script data is not decoded. - 'SCRIPT' === $tag_name || - - // RAWTEXT data is not decoded. - 'IFRAME' === $tag_name || - 'NOEMBED' === $tag_name || - 'NOFRAMES' === $tag_name || - 'STYLE' === $tag_name || - 'XMP' === $tag_name - ) { - return $text; - } - - $decoded = Gutenberg_HTML_Decoder_6_6::decode_text_node( $text ); - - /* - * TEXTAREA skips a leading newline, but this newline may appear not only as the - * literal character `\n`, but also as a character reference, such as in the - * following markup: `<textarea> Content</textarea>`. - * - * For these cases it's important to first decode the text content before checking - * for a leading newline and removing it. - */ - if ( - self::STATE_MATCHED_TAG === $this->parser_state && - 'TEXTAREA' === $tag_name && - strlen( $decoded ) > 0 && - "\n" === $decoded[0] - ) { - return substr( $decoded, 1 ); - } - - return $decoded; - } - - /** - * Updates or creates a new attribute on the currently matched tag with the passed value. - * - * For boolean attributes special handling is provided: - * - When `true` is passed as the value, then only the attribute name is added to the tag. - * - When `false` is passed, the attribute gets removed if it existed before. - * - * For string attributes, the value is escaped using the `esc_attr` function. - * - * @since 6.2.0 - * @since 6.2.1 Fix: Only create a single update for multiple calls with case-variant attribute names. - * - * @param string $name The attribute name to target. - * @param string|bool $value The new attribute value. - * @return bool Whether an attribute value was set. - */ - public function set_attribute( $name, $value ) { - if ( - self::STATE_MATCHED_TAG !== $this->parser_state || - $this->is_closing_tag - ) { - return false; - } - - /* - * WordPress rejects more characters than are strictly forbidden - * in HTML5. This is to prevent additional security risks deeper - * in the WordPress and plugin stack. Specifically the - * less-than (<) greater-than (>) and ampersand (&) aren't allowed. - * - * The use of a PCRE match enables looking for specific Unicode - * code points without writing a UTF-8 decoder. Whereas scanning - * for one-byte characters is trivial (with `strcspn`), scanning - * for the longer byte sequences would be more complicated. Given - * that this shouldn't be in the hot path for execution, it's a - * reasonable compromise in efficiency without introducing a - * noticeable impact on the overall system. - * - * @see https://html.spec.whatwg.org/#attributes-2 - * - * @todo As the only regex pattern maybe we should take it out? - * Are Unicode patterns available broadly in Core? - */ - if ( preg_match( - '~[' . - // Syntax-like characters. - '"\'>&</ =' . - // Control characters. - '\x{00}-\x{1F}' . - // HTML noncharacters. - '\x{FDD0}-\x{FDEF}' . - '\x{FFFE}\x{FFFF}\x{1FFFE}\x{1FFFF}\x{2FFFE}\x{2FFFF}\x{3FFFE}\x{3FFFF}' . - '\x{4FFFE}\x{4FFFF}\x{5FFFE}\x{5FFFF}\x{6FFFE}\x{6FFFF}\x{7FFFE}\x{7FFFF}' . - '\x{8FFFE}\x{8FFFF}\x{9FFFE}\x{9FFFF}\x{AFFFE}\x{AFFFF}\x{BFFFE}\x{BFFFF}' . - '\x{CFFFE}\x{CFFFF}\x{DFFFE}\x{DFFFF}\x{EFFFE}\x{EFFFF}\x{FFFFE}\x{FFFFF}' . - '\x{10FFFE}\x{10FFFF}' . - ']~Ssu', - $name - ) ) { - _doing_it_wrong( - __METHOD__, - __( 'Invalid attribute name.' ), - '6.2.0' - ); - - return false; - } - - /* - * > The values "true" and "false" are not allowed on boolean attributes. - * > To represent a false value, the attribute has to be omitted altogether. - * - HTML5 spec, https://html.spec.whatwg.org/#boolean-attributes - */ - if ( false === $value ) { - return $this->remove_attribute( $name ); - } - - if ( true === $value ) { - $updated_attribute = $name; - } else { - $comparable_name = strtolower( $name ); - - /* - * Escape URL attributes. - * - * @see https://html.spec.whatwg.org/#attributes-3 - */ - $escaped_new_value = in_array( $comparable_name, wp_kses_uri_attributes() ) ? esc_url( $value ) : esc_attr( $value ); - $updated_attribute = "{$name}=\"{$escaped_new_value}\""; - } - - /* - * > There must never be two or more attributes on - * > the same start tag whose names are an ASCII - * > case-insensitive match for each other. - * - HTML 5 spec - * - * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive - */ - $comparable_name = strtolower( $name ); - - if ( isset( $this->attributes[ $comparable_name ] ) ) { - /* - * Update an existing attribute. - * - * Example – set attribute id to "new" in <div id="initial_id" />: - * - * <div id="initial_id"/> - * ^-------------^ - * start end - * replacement: `id="new"` - * - * Result: <div id="new"/> - */ - $existing_attribute = $this->attributes[ $comparable_name ]; - $this->lexical_updates[ $comparable_name ] = new WP_HTML_Text_Replacement( - $existing_attribute->start, - $existing_attribute->length, - $updated_attribute - ); - } else { - /* - * Create a new attribute at the tag's name end. - * - * Example – add attribute id="new" to <div />: - * - * <div/> - * ^ - * start and end - * replacement: ` id="new"` - * - * Result: <div id="new"/> - */ - $this->lexical_updates[ $comparable_name ] = new WP_HTML_Text_Replacement( - $this->tag_name_starts_at + $this->tag_name_length, - 0, - ' ' . $updated_attribute - ); - } - - /* - * Any calls to update the `class` attribute directly should wipe out any - * enqueued class changes from `add_class` and `remove_class`. - */ - if ( 'class' === $comparable_name && ! empty( $this->classname_updates ) ) { - $this->classname_updates = array(); - } - - return true; - } - - /** - * Remove an attribute from the currently-matched tag. - * - * @since 6.2.0 - * - * @param string $name The attribute name to remove. - * @return bool Whether an attribute was removed. - */ - public function remove_attribute( $name ) { - if ( - self::STATE_MATCHED_TAG !== $this->parser_state || - $this->is_closing_tag - ) { - return false; - } - - /* - * > There must never be two or more attributes on - * > the same start tag whose names are an ASCII - * > case-insensitive match for each other. - * - HTML 5 spec - * - * @see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2:ascii-case-insensitive - */ - $name = strtolower( $name ); - - /* - * Any calls to update the `class` attribute directly should wipe out any - * enqueued class changes from `add_class` and `remove_class`. - */ - if ( 'class' === $name && count( $this->classname_updates ) !== 0 ) { - $this->classname_updates = array(); - } - - /* - * If updating an attribute that didn't exist in the input - * document, then remove the enqueued update and move on. - * - * For example, this might occur when calling `remove_attribute()` - * after calling `set_attribute()` for the same attribute - * and when that attribute wasn't originally present. - */ - if ( ! isset( $this->attributes[ $name ] ) ) { - if ( isset( $this->lexical_updates[ $name ] ) ) { - unset( $this->lexical_updates[ $name ] ); - } - return false; - } - - /* - * Removes an existing tag attribute. - * - * Example – remove the attribute id from <div id="main"/>: - * <div id="initial_id"/> - * ^-------------^ - * start end - * replacement: `` - * - * Result: <div /> - */ - $this->lexical_updates[ $name ] = new WP_HTML_Text_Replacement( - $this->attributes[ $name ]->start, - $this->attributes[ $name ]->length, - '' - ); - - // Removes any duplicated attributes if they were also present. - if ( null !== $this->duplicate_attributes && array_key_exists( $name, $this->duplicate_attributes ) ) { - foreach ( $this->duplicate_attributes[ $name ] as $attribute_token ) { - $this->lexical_updates[] = new WP_HTML_Text_Replacement( - $attribute_token->start, - $attribute_token->length, - '' - ); - } - } - - return true; - } - - /** - * Adds a new class name to the currently matched tag. - * - * @since 6.2.0 - * - * @param string $class_name The class name to add. - * @return bool Whether the class was set to be added. - */ - public function add_class( $class_name ) { - if ( - self::STATE_MATCHED_TAG !== $this->parser_state || - $this->is_closing_tag - ) { - return false; - } - - $this->classname_updates[ $class_name ] = self::ADD_CLASS; - - return true; - } - - /** - * Removes a class name from the currently matched tag. - * - * @since 6.2.0 - * - * @param string $class_name The class name to remove. - * @return bool Whether the class was set to be removed. - */ - public function remove_class( $class_name ) { - if ( - self::STATE_MATCHED_TAG !== $this->parser_state || - $this->is_closing_tag - ) { - return false; - } - - if ( null !== $this->tag_name_starts_at ) { - $this->classname_updates[ $class_name ] = self::REMOVE_CLASS; - } - - return true; - } - - /** - * Returns the string representation of the HTML Tag Processor. - * - * @since 6.2.0 - * - * @see WP_HTML_Tag_Processor::get_updated_html() - * - * @return string The processed HTML. - */ - public function __toString() { - return $this->get_updated_html(); - } - - /** - * Returns the string representation of the HTML Tag Processor. - * - * @since 6.2.0 - * @since 6.2.1 Shifts the internal cursor corresponding to the applied updates. - * @since 6.4.0 No longer calls subclass method `next_tag()` after updating HTML. - * - * @return string The processed HTML. - */ - public function get_updated_html() { - $requires_no_updating = 0 === count( $this->classname_updates ) && 0 === count( $this->lexical_updates ); - - /* - * When there is nothing more to update and nothing has already been - * updated, return the original document and avoid a string copy. - */ - if ( $requires_no_updating ) { - return $this->html; - } - - /* - * Keep track of the position right before the current tag. This will - * be necessary for reparsing the current tag after updating the HTML. - */ - $before_current_tag = $this->token_starts_at ?? 0; - - /* - * 1. Apply the enqueued edits and update all the pointers to reflect those changes. - */ - $this->class_name_updates_to_attributes_updates(); - $before_current_tag += $this->apply_attributes_updates( $before_current_tag ); - - /* - * 2. Rewind to before the current tag and reparse to get updated attributes. - * - * At this point the internal cursor points to the end of the tag name. - * Rewind before the tag name starts so that it's as if the cursor didn't - * move; a call to `next_tag()` will reparse the recently-updated attributes - * and additional calls to modify the attributes will apply at this same - * location, but in order to avoid issues with subclasses that might add - * behaviors to `next_tag()`, the internal methods should be called here - * instead. - * - * It's important to note that in this specific place there will be no change - * because the processor was already at a tag when this was called and it's - * rewinding only to the beginning of this very tag before reprocessing it - * and its attributes. - * - * <p>Previous HTML<em>More HTML</em></p> - * ↑ │ back up by the length of the tag name plus the opening < - * └←─┘ back up by strlen("em") + 1 ==> 3 - */ - $this->bytes_already_parsed = $before_current_tag; - $this->base_class_next_token(); - - return $this->html; - } - - /** - * Parses tag query input into internal search criteria. - * - * @since 6.2.0 - * - * @param array|string|null $query { - * Optional. Which tag name to find, having which class, etc. Default is to find any tag. - * - * @type string|null $tag_name Which tag to find, or `null` for "any tag." - * @type int|null $match_offset Find the Nth tag matching all search criteria. - * 1 for "first" tag, 3 for "third," etc. - * Defaults to first tag. - * @type string|null $class_name Tag must contain this class name to match. - * @type string $tag_closers "visit" or "skip": whether to stop on tag closers, e.g. </div>. - * } - */ - private function parse_query( $query ) { - if ( null !== $query && $query === $this->last_query ) { - return; - } - - $this->last_query = $query; - $this->sought_tag_name = null; - $this->sought_class_name = null; - $this->sought_match_offset = 1; - $this->stop_on_tag_closers = false; - - // A single string value means "find the tag of this name". - if ( is_string( $query ) ) { - $this->sought_tag_name = $query; - return; - } - - // An empty query parameter applies no restrictions on the search. - if ( null === $query ) { - return; - } - - // If not using the string interface, an associative array is required. - if ( ! is_array( $query ) ) { - _doing_it_wrong( - __METHOD__, - __( 'The query argument must be an array or a tag name.' ), - '6.2.0' - ); - return; - } - - if ( isset( $query['tag_name'] ) && is_string( $query['tag_name'] ) ) { - $this->sought_tag_name = $query['tag_name']; - } - - if ( isset( $query['class_name'] ) && is_string( $query['class_name'] ) ) { - $this->sought_class_name = $query['class_name']; - } - - if ( isset( $query['match_offset'] ) && is_int( $query['match_offset'] ) && 0 < $query['match_offset'] ) { - $this->sought_match_offset = $query['match_offset']; - } - - if ( isset( $query['tag_closers'] ) ) { - $this->stop_on_tag_closers = 'visit' === $query['tag_closers']; - } - } - - - /** - * Checks whether a given tag and its attributes match the search criteria. - * - * @since 6.2.0 - * - * @return bool Whether the given tag and its attribute match the search criteria. - */ - private function matches() { - if ( $this->is_closing_tag && ! $this->stop_on_tag_closers ) { - return false; - } - - // Does the tag name match the requested tag name in a case-insensitive manner? - if ( null !== $this->sought_tag_name ) { - /* - * String (byte) length lookup is fast. If they aren't the - * same length then they can't be the same string values. - */ - if ( strlen( $this->sought_tag_name ) !== $this->tag_name_length ) { - return false; - } - - /* - * Check each character to determine if they are the same. - * Defer calls to `strtoupper()` to avoid them when possible. - * Calling `strcasecmp()` here tested slowed than comparing each - * character, so unless benchmarks show otherwise, it should - * not be used. - * - * It's expected that most of the time that this runs, a - * lower-case tag name will be supplied and the input will - * contain lower-case tag names, thus normally bypassing - * the case comparison code. - */ - for ( $i = 0; $i < $this->tag_name_length; $i++ ) { - $html_char = $this->html[ $this->tag_name_starts_at + $i ]; - $tag_char = $this->sought_tag_name[ $i ]; - - if ( $html_char !== $tag_char && strtoupper( $html_char ) !== $tag_char ) { - return false; - } - } - } - - if ( null !== $this->sought_class_name && ! $this->has_class( $this->sought_class_name ) ) { - return false; - } - - return true; - } - - /** - * Parser Ready State. - * - * Indicates that the parser is ready to run and waiting for a state transition. - * It may not have started yet, or it may have just finished parsing a token and - * is ready to find the next one. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_READY = 'STATE_READY'; - - /** - * Parser Complete State. - * - * Indicates that the parser has reached the end of the document and there is - * nothing left to scan. It finished parsing the last token completely. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_COMPLETE = 'STATE_COMPLETE'; - - /** - * Parser Incomplete Input State. - * - * Indicates that the parser has reached the end of the document before finishing - * a token. It started parsing a token but there is a possibility that the input - * HTML document was truncated in the middle of a token. - * - * The parser is reset at the start of the incomplete token and has paused. There - * is nothing more than can be scanned unless provided a more complete document. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_INCOMPLETE_INPUT = 'STATE_INCOMPLETE_INPUT'; - - /** - * Parser Matched Tag State. - * - * Indicates that the parser has found an HTML tag and it's possible to get - * the tag name and read or modify its attributes (if it's not a closing tag). - * - * @since 6.5.0 - * - * @access private - */ - const STATE_MATCHED_TAG = 'STATE_MATCHED_TAG'; - - /** - * Parser Text Node State. - * - * Indicates that the parser has found a text node and it's possible - * to read and modify that text. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_TEXT_NODE = 'STATE_TEXT_NODE'; - - /** - * Parser CDATA Node State. - * - * Indicates that the parser has found a CDATA node and it's possible - * to read and modify its modifiable text. Note that in HTML there are - * no CDATA nodes outside of foreign content (SVG and MathML). Outside - * of foreign content, they are treated as HTML comments. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_CDATA_NODE = 'STATE_CDATA_NODE'; - - /** - * Indicates that the parser has found an HTML comment and it's - * possible to read and modify its modifiable text. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_COMMENT = 'STATE_COMMENT'; - - /** - * Indicates that the parser has found a DOCTYPE node and it's - * possible to read and modify its modifiable text. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_DOCTYPE = 'STATE_DOCTYPE'; - - /** - * Indicates that the parser has found an empty tag closer `</>`. - * - * Note that in HTML there are no empty tag closers, and they - * are ignored. Nonetheless, the Tag Processor still - * recognizes them as they appear in the HTML stream. - * - * These were historically discussed as a "presumptuous tag - * closer," which would close the nearest open tag, but were - * dismissed in favor of explicitly-closing tags. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_PRESUMPTUOUS_TAG = 'STATE_PRESUMPTUOUS_TAG'; - - /** - * Indicates that the parser has found a "funky comment" - * and it's possible to read and modify its modifiable text. - * - * Example: - * - * </%url> - * </{"wp-bit":"query/post-author"}> - * </2> - * - * Funky comments are tag closers with invalid tag names. Note - * that in HTML these are turn into bogus comments. Nonetheless, - * the Tag Processor recognizes them in a stream of HTML and - * exposes them for inspection and modification. - * - * @since 6.5.0 - * - * @access private - */ - const STATE_FUNKY_COMMENT = 'STATE_WP_FUNKY'; - - /** - * Indicates that a comment was created when encountering abruptly-closed HTML comment. - * - * Example: - * - * <!--> - * <!---> - * - * @since 6.5.0 - */ - const COMMENT_AS_ABRUPTLY_CLOSED_COMMENT = 'COMMENT_AS_ABRUPTLY_CLOSED_COMMENT'; - - /** - * Indicates that a comment would be parsed as a CDATA node, - * were HTML to allow CDATA nodes outside of foreign content. - * - * Example: - * - * <![CDATA[This is a CDATA node.]]> - * - * This is an HTML comment, but it looks like a CDATA node. - * - * @since 6.5.0 - */ - const COMMENT_AS_CDATA_LOOKALIKE = 'COMMENT_AS_CDATA_LOOKALIKE'; - - /** - * Indicates that a comment was created when encountering - * normative HTML comment syntax. - * - * Example: - * - * <!-- this is a comment --> - * - * @since 6.5.0 - */ - const COMMENT_AS_HTML_COMMENT = 'COMMENT_AS_HTML_COMMENT'; - - /** - * Indicates that a comment would be parsed as a Processing - * Instruction node, were they to exist within HTML. - * - * Example: - * - * <?wp __( 'Like' ) ?> - * - * This is an HTML comment, but it looks like a CDATA node. - * - * @since 6.5.0 - */ - const COMMENT_AS_PI_NODE_LOOKALIKE = 'COMMENT_AS_PI_NODE_LOOKALIKE'; - - /** - * Indicates that a comment was created when encountering invalid - * HTML input, a so-called "bogus comment." - * - * Example: - * - * <?nothing special> - * <!{nothing special}> - * - * @since 6.5.0 - */ - const COMMENT_AS_INVALID_HTML = 'COMMENT_AS_INVALID_HTML'; -} diff --git a/lib/compat/wordpress-6.6/html-api/gutenberg-html5-named-character-references-6-6.php b/lib/compat/wordpress-6.6/html-api/gutenberg-html5-named-character-references-6-6.php deleted file mode 100644 index c09deb3c9e6642..00000000000000 --- a/lib/compat/wordpress-6.6/html-api/gutenberg-html5-named-character-references-6-6.php +++ /dev/null @@ -1,1315 +0,0 @@ -<?php - -/** - * Auto-generated class for looking up HTML named character references. - * - * ⚠️ !!! THIS ENTIRE FILE IS AUTOMATICALLY GENERATED !!! ⚠️ - * Do not modify this file directly. - * - * To regenerate, run the generation script directly. - * - * Example: - * - * php tests/phpunit/data/html5-entities/generate-html5-named-character-references.php - * - * @package WordPress - * @since 6.6.0 - */ - -// phpcs:disable - -global $html5_named_character_references; - -/** - * Set of named character references in the HTML5 specification. - * - * This list will never change, according to the spec. Each named - * character reference is case-sensitive and the presence or absence - * of the semicolon is significant. Without the semicolon, the rules - * for an ambiguous ampersand govern whether the following text is - * to be interpreted as a character reference or not. - * - * The list of entities is sourced directly from the WHATWG server - * and cached in the test directory to avoid needing to download it - * every time this file is updated. - * - * @link https://html.spec.whatwg.org/entities.json. - */ -if ( ! isset( $html5_named_character_references ) ) { - $html5_named_character_references = Gutenberg_Token_Map_6_6::from_precomputed_table( - array( - "storage_version" => "6.6.0-trunk", - "key_length" => 2, - "groups" => "AE\x00AM\x00Aa\x00Ab\x00Ac\x00Af\x00Ag\x00Al\x00Am\x00An\x00Ao\x00Ap\x00Ar\x00As\x00At\x00Au\x00Ba\x00Bc\x00Be\x00Bf\x00Bo\x00Br\x00Bs\x00Bu\x00CH\x00CO\x00Ca\x00Cc\x00Cd\x00Ce\x00Cf\x00Ch\x00Ci\x00Cl\x00Co\x00Cr\x00Cs\x00Cu\x00DD\x00DJ\x00DS\x00DZ\x00Da\x00Dc\x00De\x00Df\x00Di\x00Do\x00Ds\x00EN\x00ET\x00Ea\x00Ec\x00Ed\x00Ef\x00Eg\x00El\x00Em\x00Eo\x00Ep\x00Eq\x00Es\x00Et\x00Eu\x00Ex\x00Fc\x00Ff\x00Fi\x00Fo\x00Fs\x00GJ\x00GT\x00Ga\x00Gb\x00Gc\x00Gd\x00Gf\x00Gg\x00Go\x00Gr\x00Gs\x00Gt\x00HA\x00Ha\x00Hc\x00Hf\x00Hi\x00Ho\x00Hs\x00Hu\x00IE\x00IJ\x00IO\x00Ia\x00Ic\x00Id\x00If\x00Ig\x00Im\x00In\x00Io\x00Is\x00It\x00Iu\x00Jc\x00Jf\x00Jo\x00Js\x00Ju\x00KH\x00KJ\x00Ka\x00Kc\x00Kf\x00Ko\x00Ks\x00LJ\x00LT\x00La\x00Lc\x00Le\x00Lf\x00Ll\x00Lm\x00Lo\x00Ls\x00Lt\x00Ma\x00Mc\x00Me\x00Mf\x00Mi\x00Mo\x00Ms\x00Mu\x00NJ\x00Na\x00Nc\x00Ne\x00Nf\x00No\x00Ns\x00Nt\x00Nu\x00OE\x00Oa\x00Oc\x00Od\x00Of\x00Og\x00Om\x00Oo\x00Op\x00Or\x00Os\x00Ot\x00Ou\x00Ov\x00Pa\x00Pc\x00Pf\x00Ph\x00Pi\x00Pl\x00Po\x00Pr\x00Ps\x00QU\x00Qf\x00Qo\x00Qs\x00RB\x00RE\x00Ra\x00Rc\x00Re\x00Rf\x00Rh\x00Ri\x00Ro\x00Rr\x00Rs\x00Ru\x00SH\x00SO\x00Sa\x00Sc\x00Sf\x00Sh\x00Si\x00Sm\x00So\x00Sq\x00Ss\x00St\x00Su\x00TH\x00TR\x00TS\x00Ta\x00Tc\x00Tf\x00Th\x00Ti\x00To\x00Tr\x00Ts\x00Ua\x00Ub\x00Uc\x00Ud\x00Uf\x00Ug\x00Um\x00Un\x00Uo\x00Up\x00Ur\x00Us\x00Ut\x00Uu\x00VD\x00Vb\x00Vc\x00Vd\x00Ve\x00Vf\x00Vo\x00Vs\x00Vv\x00Wc\x00We\x00Wf\x00Wo\x00Ws\x00Xf\x00Xi\x00Xo\x00Xs\x00YA\x00YI\x00YU\x00Ya\x00Yc\x00Yf\x00Yo\x00Ys\x00Yu\x00ZH\x00Za\x00Zc\x00Zd\x00Ze\x00Zf\x00Zo\x00Zs\x00aa\x00ab\x00ac\x00ae\x00af\x00ag\x00al\x00am\x00an\x00ao\x00ap\x00ar\x00as\x00at\x00au\x00aw\x00bN\x00ba\x00bb\x00bc\x00bd\x00be\x00bf\x00bi\x00bk\x00bl\x00bn\x00bo\x00bp\x00br\x00bs\x00bu\x00ca\x00cc\x00cd\x00ce\x00cf\x00ch\x00ci\x00cl\x00co\x00cr\x00cs\x00ct\x00cu\x00cw\x00cy\x00dA\x00dH\x00da\x00db\x00dc\x00dd\x00de\x00df\x00dh\x00di\x00dj\x00dl\x00do\x00dr\x00ds\x00dt\x00du\x00dw\x00dz\x00eD\x00ea\x00ec\x00ed\x00ee\x00ef\x00eg\x00el\x00em\x00en\x00eo\x00ep\x00eq\x00er\x00es\x00et\x00eu\x00ex\x00fa\x00fc\x00fe\x00ff\x00fi\x00fj\x00fl\x00fn\x00fo\x00fp\x00fr\x00fs\x00gE\x00ga\x00gb\x00gc\x00gd\x00ge\x00gf\x00gg\x00gi\x00gj\x00gl\x00gn\x00go\x00gr\x00gs\x00gt\x00gv\x00hA\x00ha\x00hb\x00hc\x00he\x00hf\x00hk\x00ho\x00hs\x00hy\x00ia\x00ic\x00ie\x00if\x00ig\x00ii\x00ij\x00im\x00in\x00io\x00ip\x00iq\x00is\x00it\x00iu\x00jc\x00jf\x00jm\x00jo\x00js\x00ju\x00ka\x00kc\x00kf\x00kg\x00kh\x00kj\x00ko\x00ks\x00lA\x00lB\x00lE\x00lH\x00la\x00lb\x00lc\x00ld\x00le\x00lf\x00lg\x00lh\x00lj\x00ll\x00lm\x00ln\x00lo\x00lp\x00lr\x00ls\x00lt\x00lu\x00lv\x00mD\x00ma\x00mc\x00md\x00me\x00mf\x00mh\x00mi\x00ml\x00mn\x00mo\x00mp\x00ms\x00mu\x00nG\x00nL\x00nR\x00nV\x00na\x00nb\x00nc\x00nd\x00ne\x00nf\x00ng\x00nh\x00ni\x00nj\x00nl\x00nm\x00no\x00np\x00nr\x00ns\x00nt\x00nu\x00nv\x00nw\x00oS\x00oa\x00oc\x00od\x00oe\x00of\x00og\x00oh\x00oi\x00ol\x00om\x00oo\x00op\x00or\x00os\x00ot\x00ou\x00ov\x00pa\x00pc\x00pe\x00pf\x00ph\x00pi\x00pl\x00pm\x00po\x00pr\x00ps\x00pu\x00qf\x00qi\x00qo\x00qp\x00qs\x00qu\x00rA\x00rB\x00rH\x00ra\x00rb\x00rc\x00rd\x00re\x00rf\x00rh\x00ri\x00rl\x00rm\x00rn\x00ro\x00rp\x00rr\x00rs\x00rt\x00ru\x00rx\x00sa\x00sb\x00sc\x00sd\x00se\x00sf\x00sh\x00si\x00sl\x00sm\x00so\x00sp\x00sq\x00sr\x00ss\x00st\x00su\x00sw\x00sz\x00ta\x00tb\x00tc\x00td\x00te\x00tf\x00th\x00ti\x00to\x00tp\x00tr\x00ts\x00tw\x00uA\x00uH\x00ua\x00ub\x00uc\x00ud\x00uf\x00ug\x00uh\x00ul\x00um\x00uo\x00up\x00ur\x00us\x00ut\x00uu\x00uw\x00vA\x00vB\x00vD\x00va\x00vc\x00vd\x00ve\x00vf\x00vl\x00vn\x00vo\x00vp\x00vr\x00vs\x00vz\x00wc\x00we\x00wf\x00wo\x00wp\x00wr\x00ws\x00xc\x00xd\x00xf\x00xh\x00xi\x00xl\x00xm\x00xn\x00xo\x00xr\x00xs\x00xu\x00xv\x00xw\x00ya\x00yc\x00ye\x00yf\x00yi\x00yo\x00ys\x00yu\x00za\x00zc\x00zd\x00ze\x00zf\x00zh\x00zi\x00zo\x00zs\x00zw\x00", - "large_words" => array( - // AElig;[Æ] AElig[Æ]. - "\x04lig;\x02Æ\x03lig\x02Æ", - // AMP;[&] AMP[&]. - "\x02P;\x01&\x01P\x01&", - // Aacute;[Á] Aacute[Á]. - "\x05cute;\x02Á\x04cute\x02Á", - // Abreve;[Ă]. - "\x05reve;\x02Ă", - // Acirc;[Â] Acirc[Â] Acy;[А]. - "\x04irc;\x02Â\x03irc\x02Â\x02y;\x02А", - // Afr;[𝔄]. - "\x02r;\x04𝔄", - // Agrave;[À] Agrave[À]. - "\x05rave;\x02À\x04rave\x02À", - // Alpha;[Α]. - "\x04pha;\x02Α", - // Amacr;[Ā]. - "\x04acr;\x02Ā", - // And;[⩓]. - "\x02d;\x03⩓", - // Aogon;[Ą] Aopf;[𝔸]. - "\x04gon;\x02Ą\x03pf;\x04𝔸", - // ApplyFunction;[⁡]. - "\x0cplyFunction;\x03⁡", - // Aring;[Å] Aring[Å]. - "\x04ing;\x02Å\x03ing\x02Å", - // Assign;[≔] Ascr;[𝒜]. - "\x05sign;\x03≔\x03cr;\x04𝒜", - // Atilde;[Ã] Atilde[Ã]. - "\x05ilde;\x02Ã\x04ilde\x02Ã", - // Auml;[Ä] Auml[Ä]. - "\x03ml;\x02Ä\x02ml\x02Ä", - // Backslash;[∖] Barwed;[⌆] Barv;[⫧]. - "\x08ckslash;\x03∖\x05rwed;\x03⌆\x03rv;\x03⫧", - // Bcy;[Б]. - "\x02y;\x02Б", - // Bernoullis;[ℬ] Because;[∵] Beta;[Β]. - "\x09rnoullis;\x03ℬ\x06cause;\x03∵\x03ta;\x02Β", - // Bfr;[𝔅]. - "\x02r;\x04𝔅", - // Bopf;[𝔹]. - "\x03pf;\x04𝔹", - // Breve;[˘]. - "\x04eve;\x02˘", - // Bscr;[ℬ]. - "\x03cr;\x03ℬ", - // Bumpeq;[≎]. - "\x05mpeq;\x03≎", - // CHcy;[Ч]. - "\x03cy;\x02Ч", - // COPY;[©] COPY[©]. - "\x03PY;\x02©\x02PY\x02©", - // CapitalDifferentialD;[ⅅ] Cayleys;[ℭ] Cacute;[Ć] Cap;[⋒]. - "\x13pitalDifferentialD;\x03ⅅ\x06yleys;\x03ℭ\x05cute;\x02Ć\x02p;\x03⋒", - // Cconint;[∰] Ccaron;[Č] Ccedil;[Ç] Ccedil[Ç] Ccirc;[Ĉ]. - "\x06onint;\x03∰\x05aron;\x02Č\x05edil;\x02Ç\x04edil\x02Ç\x04irc;\x02Ĉ", - // Cdot;[Ċ]. - "\x03ot;\x02Ċ", - // CenterDot;[·] Cedilla;[¸]. - "\x08nterDot;\x02·\x06dilla;\x02¸", - // Cfr;[ℭ]. - "\x02r;\x03ℭ", - // Chi;[Χ]. - "\x02i;\x02Χ", - // CircleMinus;[⊖] CircleTimes;[⊗] CirclePlus;[⊕] CircleDot;[⊙]. - "\x0arcleMinus;\x03⊖\x0arcleTimes;\x03⊗\x09rclePlus;\x03⊕\x08rcleDot;\x03⊙", - // ClockwiseContourIntegral;[∲] CloseCurlyDoubleQuote;[”] CloseCurlyQuote;[’]. - "\x17ockwiseContourIntegral;\x03∲\x14oseCurlyDoubleQuote;\x03”\x0eoseCurlyQuote;\x03’", - // CounterClockwiseContourIntegral;[∳] ContourIntegral;[∮] Congruent;[≡] Coproduct;[∐] Colone;[⩴] Conint;[∯] Colon;[∷] Copf;[ℂ]. - "\x1eunterClockwiseContourIntegral;\x03∳\x0entourIntegral;\x03∮\x08ngruent;\x03≡\x08product;\x03∐\x05lone;\x03⩴\x05nint;\x03∯\x04lon;\x03∷\x03pf;\x03ℂ", - // Cross;[⨯]. - "\x04oss;\x03⨯", - // Cscr;[𝒞]. - "\x03cr;\x04𝒞", - // CupCap;[≍] Cup;[⋓]. - "\x05pCap;\x03≍\x02p;\x03⋓", - // DDotrahd;[⤑] DD;[ⅅ]. - "\x07otrahd;\x03⤑\x01;\x03ⅅ", - // DJcy;[Ђ]. - "\x03cy;\x02Ђ", - // DScy;[Ѕ]. - "\x03cy;\x02Ѕ", - // DZcy;[Џ]. - "\x03cy;\x02Џ", - // Dagger;[‡] Dashv;[⫤] Darr;[↡]. - "\x05gger;\x03‡\x04shv;\x03⫤\x03rr;\x03↡", - // Dcaron;[Ď] Dcy;[Д]. - "\x05aron;\x02Ď\x02y;\x02Д", - // Delta;[Δ] Del;[∇]. - "\x04lta;\x02Δ\x02l;\x03∇", - // Dfr;[𝔇]. - "\x02r;\x04𝔇", - // DiacriticalDoubleAcute;[˝] DiacriticalAcute;[´] DiacriticalGrave;[`] DiacriticalTilde;[˜] DiacriticalDot;[˙] DifferentialD;[ⅆ] Diamond;[⋄]. - "\x15acriticalDoubleAcute;\x02˝\x0facriticalAcute;\x02´\x0facriticalGrave;\x01`\x0facriticalTilde;\x02˜\x0dacriticalDot;\x02˙\x0cfferentialD;\x03ⅆ\x06amond;\x03⋄", - // DoubleLongLeftRightArrow;[⟺] DoubleContourIntegral;[∯] DoubleLeftRightArrow;[⇔] DoubleLongRightArrow;[⟹] DoubleLongLeftArrow;[⟸] DownLeftRightVector;[⥐] DownRightTeeVector;[⥟] DownRightVectorBar;[⥗] DoubleUpDownArrow;[⇕] DoubleVerticalBar;[∥] DownLeftTeeVector;[⥞] DownLeftVectorBar;[⥖] DoubleRightArrow;[⇒] DownArrowUpArrow;[⇵] DoubleDownArrow;[⇓] DoubleLeftArrow;[⇐] DownRightVector;[⇁] DoubleRightTee;[⊨] DownLeftVector;[↽] DoubleLeftTee;[⫤] DoubleUpArrow;[⇑] DownArrowBar;[⤓] DownTeeArrow;[↧] DoubleDot;[¨] DownArrow;[↓] DownBreve;[̑] Downarrow;[⇓] DotEqual;[≐] DownTee;[⊤] DotDot;[⃜] Dopf;[𝔻] Dot;[¨]. - "\x17ubleLongLeftRightArrow;\x03⟺\x14ubleContourIntegral;\x03∯\x13ubleLeftRightArrow;\x03⇔\x13ubleLongRightArrow;\x03⟹\x12ubleLongLeftArrow;\x03⟸\x12wnLeftRightVector;\x03⥐\x11wnRightTeeVector;\x03⥟\x11wnRightVectorBar;\x03⥗\x10ubleUpDownArrow;\x03⇕\x10ubleVerticalBar;\x03∥\x10wnLeftTeeVector;\x03⥞\x10wnLeftVectorBar;\x03⥖\x0fubleRightArrow;\x03⇒\x0fwnArrowUpArrow;\x03⇵\x0eubleDownArrow;\x03⇓\x0eubleLeftArrow;\x03⇐\x0ewnRightVector;\x03⇁\x0dubleRightTee;\x03⊨\x0dwnLeftVector;\x03↽\x0cubleLeftTee;\x03⫤\x0cubleUpArrow;\x03⇑\x0bwnArrowBar;\x03⤓\x0bwnTeeArrow;\x03↧\x08ubleDot;\x02¨\x08wnArrow;\x03↓\x08wnBreve;\x02̑\x08wnarrow;\x03⇓\x07tEqual;\x03≐\x06wnTee;\x03⊤\x05tDot;\x03⃜\x03pf;\x04𝔻\x02t;\x02¨", - // Dstrok;[Đ] Dscr;[𝒟]. - "\x05trok;\x02Đ\x03cr;\x04𝒟", - // ENG;[Ŋ]. - "\x02G;\x02Ŋ", - // ETH;[Ð] ETH[Ð]. - "\x02H;\x02Ð\x01H\x02Ð", - // Eacute;[É] Eacute[É]. - "\x05cute;\x02É\x04cute\x02É", - // Ecaron;[Ě] Ecirc;[Ê] Ecirc[Ê] Ecy;[Э]. - "\x05aron;\x02Ě\x04irc;\x02Ê\x03irc\x02Ê\x02y;\x02Э", - // Edot;[Ė]. - "\x03ot;\x02Ė", - // Efr;[𝔈]. - "\x02r;\x04𝔈", - // Egrave;[È] Egrave[È]. - "\x05rave;\x02È\x04rave\x02È", - // Element;[∈]. - "\x06ement;\x03∈", - // EmptyVerySmallSquare;[▫] EmptySmallSquare;[◻] Emacr;[Ē]. - "\x13ptyVerySmallSquare;\x03▫\x0fptySmallSquare;\x03◻\x04acr;\x02Ē", - // Eogon;[Ę] Eopf;[𝔼]. - "\x04gon;\x02Ę\x03pf;\x04𝔼", - // Epsilon;[Ε]. - "\x06silon;\x02Ε", - // Equilibrium;[⇌] EqualTilde;[≂] Equal;[⩵]. - "\x0auilibrium;\x03⇌\x09ualTilde;\x03≂\x04ual;\x03⩵", - // Escr;[ℰ] Esim;[⩳]. - "\x03cr;\x03ℰ\x03im;\x03⩳", - // Eta;[Η]. - "\x02a;\x02Η", - // Euml;[Ë] Euml[Ë]. - "\x03ml;\x02Ë\x02ml\x02Ë", - // ExponentialE;[ⅇ] Exists;[∃]. - "\x0bponentialE;\x03ⅇ\x05ists;\x03∃", - // Fcy;[Ф]. - "\x02y;\x02Ф", - // Ffr;[𝔉]. - "\x02r;\x04𝔉", - // FilledVerySmallSquare;[▪] FilledSmallSquare;[◼]. - "\x14lledVerySmallSquare;\x03▪\x10lledSmallSquare;\x03◼", - // Fouriertrf;[ℱ] ForAll;[∀] Fopf;[𝔽]. - "\x09uriertrf;\x03ℱ\x05rAll;\x03∀\x03pf;\x04𝔽", - // Fscr;[ℱ]. - "\x03cr;\x03ℱ", - // GJcy;[Ѓ]. - "\x03cy;\x02Ѓ", - // GT;[>]. - "\x01;\x01>", - // Gammad;[Ϝ] Gamma;[Γ]. - "\x05mmad;\x02Ϝ\x04mma;\x02Γ", - // Gbreve;[Ğ]. - "\x05reve;\x02Ğ", - // Gcedil;[Ģ] Gcirc;[Ĝ] Gcy;[Г]. - "\x05edil;\x02Ģ\x04irc;\x02Ĝ\x02y;\x02Г", - // Gdot;[Ġ]. - "\x03ot;\x02Ġ", - // Gfr;[𝔊]. - "\x02r;\x04𝔊", - // Gg;[⋙]. - "\x01;\x03⋙", - // Gopf;[𝔾]. - "\x03pf;\x04𝔾", - // GreaterSlantEqual;[⩾] GreaterEqualLess;[⋛] GreaterFullEqual;[≧] GreaterGreater;[⪢] GreaterEqual;[≥] GreaterTilde;[≳] GreaterLess;[≷]. - "\x10eaterSlantEqual;\x03⩾\x0featerEqualLess;\x03⋛\x0featerFullEqual;\x03≧\x0deaterGreater;\x03⪢\x0beaterEqual;\x03≥\x0beaterTilde;\x03≳\x0aeaterLess;\x03≷", - // Gscr;[𝒢]. - "\x03cr;\x04𝒢", - // Gt;[≫]. - "\x01;\x03≫", - // HARDcy;[Ъ]. - "\x05RDcy;\x02Ъ", - // Hacek;[ˇ] Hat;[^]. - "\x04cek;\x02ˇ\x02t;\x01^", - // Hcirc;[Ĥ]. - "\x04irc;\x02Ĥ", - // Hfr;[ℌ]. - "\x02r;\x03ℌ", - // HilbertSpace;[ℋ]. - "\x0blbertSpace;\x03ℋ", - // HorizontalLine;[─] Hopf;[ℍ]. - "\x0drizontalLine;\x03─\x03pf;\x03ℍ", - // Hstrok;[Ħ] Hscr;[ℋ]. - "\x05trok;\x02Ħ\x03cr;\x03ℋ", - // HumpDownHump;[≎] HumpEqual;[≏]. - "\x0bmpDownHump;\x03≎\x08mpEqual;\x03≏", - // IEcy;[Е]. - "\x03cy;\x02Е", - // IJlig;[IJ]. - "\x04lig;\x02IJ", - // IOcy;[Ё]. - "\x03cy;\x02Ё", - // Iacute;[Í] Iacute[Í]. - "\x05cute;\x02Í\x04cute\x02Í", - // Icirc;[Î] Icirc[Î] Icy;[И]. - "\x04irc;\x02Î\x03irc\x02Î\x02y;\x02И", - // Idot;[İ]. - "\x03ot;\x02İ", - // Ifr;[ℑ]. - "\x02r;\x03ℑ", - // Igrave;[Ì] Igrave[Ì]. - "\x05rave;\x02Ì\x04rave\x02Ì", - // ImaginaryI;[ⅈ] Implies;[⇒] Imacr;[Ī] Im;[ℑ]. - "\x09aginaryI;\x03ⅈ\x06plies;\x03⇒\x04acr;\x02Ī\x01;\x03ℑ", - // InvisibleComma;[⁣] InvisibleTimes;[⁢] Intersection;[⋂] Integral;[∫] Int;[∬]. - "\x0dvisibleComma;\x03⁣\x0dvisibleTimes;\x03⁢\x0btersection;\x03⋂\x07tegral;\x03∫\x02t;\x03∬", - // Iogon;[Į] Iopf;[𝕀] Iota;[Ι]. - "\x04gon;\x02Į\x03pf;\x04𝕀\x03ta;\x02Ι", - // Iscr;[ℐ]. - "\x03cr;\x03ℐ", - // Itilde;[Ĩ]. - "\x05ilde;\x02Ĩ", - // Iukcy;[І] Iuml;[Ï] Iuml[Ï]. - "\x04kcy;\x02І\x03ml;\x02Ï\x02ml\x02Ï", - // Jcirc;[Ĵ] Jcy;[Й]. - "\x04irc;\x02Ĵ\x02y;\x02Й", - // Jfr;[𝔍]. - "\x02r;\x04𝔍", - // Jopf;[𝕁]. - "\x03pf;\x04𝕁", - // Jsercy;[Ј] Jscr;[𝒥]. - "\x05ercy;\x02Ј\x03cr;\x04𝒥", - // Jukcy;[Є]. - "\x04kcy;\x02Є", - // KHcy;[Х]. - "\x03cy;\x02Х", - // KJcy;[Ќ]. - "\x03cy;\x02Ќ", - // Kappa;[Κ]. - "\x04ppa;\x02Κ", - // Kcedil;[Ķ] Kcy;[К]. - "\x05edil;\x02Ķ\x02y;\x02К", - // Kfr;[𝔎]. - "\x02r;\x04𝔎", - // Kopf;[𝕂]. - "\x03pf;\x04𝕂", - // Kscr;[𝒦]. - "\x03cr;\x04𝒦", - // LJcy;[Љ]. - "\x03cy;\x02Љ", - // LT;[<]. - "\x01;\x01<", - // Laplacetrf;[ℒ] Lacute;[Ĺ] Lambda;[Λ] Lang;[⟪] Larr;[↞]. - "\x09placetrf;\x03ℒ\x05cute;\x02Ĺ\x05mbda;\x02Λ\x03ng;\x03⟪\x03rr;\x03↞", - // Lcaron;[Ľ] Lcedil;[Ļ] Lcy;[Л]. - "\x05aron;\x02Ľ\x05edil;\x02Ļ\x02y;\x02Л", - // LeftArrowRightArrow;[⇆] LeftDoubleBracket;[⟦] LeftDownTeeVector;[⥡] LeftDownVectorBar;[⥙] LeftTriangleEqual;[⊴] LeftAngleBracket;[⟨] LeftUpDownVector;[⥑] LessEqualGreater;[⋚] LeftRightVector;[⥎] LeftTriangleBar;[⧏] LeftUpTeeVector;[⥠] LeftUpVectorBar;[⥘] LeftDownVector;[⇃] LeftRightArrow;[↔] Leftrightarrow;[⇔] LessSlantEqual;[⩽] LeftTeeVector;[⥚] LeftVectorBar;[⥒] LessFullEqual;[≦] LeftArrowBar;[⇤] LeftTeeArrow;[↤] LeftTriangle;[⊲] LeftUpVector;[↿] LeftCeiling;[⌈] LessGreater;[≶] LeftVector;[↼] LeftArrow;[←] LeftFloor;[⌊] Leftarrow;[⇐] LessTilde;[≲] LessLess;[⪡] LeftTee;[⊣]. - "\x12ftArrowRightArrow;\x03⇆\x10ftDoubleBracket;\x03⟦\x10ftDownTeeVector;\x03⥡\x10ftDownVectorBar;\x03⥙\x10ftTriangleEqual;\x03⊴\x0fftAngleBracket;\x03⟨\x0fftUpDownVector;\x03⥑\x0fssEqualGreater;\x03⋚\x0eftRightVector;\x03⥎\x0eftTriangleBar;\x03⧏\x0eftUpTeeVector;\x03⥠\x0eftUpVectorBar;\x03⥘\x0dftDownVector;\x03⇃\x0dftRightArrow;\x03↔\x0dftrightarrow;\x03⇔\x0dssSlantEqual;\x03⩽\x0cftTeeVector;\x03⥚\x0cftVectorBar;\x03⥒\x0cssFullEqual;\x03≦\x0bftArrowBar;\x03⇤\x0bftTeeArrow;\x03↤\x0bftTriangle;\x03⊲\x0bftUpVector;\x03↿\x0aftCeiling;\x03⌈\x0assGreater;\x03≶\x09ftVector;\x03↼\x08ftArrow;\x03←\x08ftFloor;\x03⌊\x08ftarrow;\x03⇐\x08ssTilde;\x03≲\x07ssLess;\x03⪡\x06ftTee;\x03⊣", - // Lfr;[𝔏]. - "\x02r;\x04𝔏", - // Lleftarrow;[⇚] Ll;[⋘]. - "\x09eftarrow;\x03⇚\x01;\x03⋘", - // Lmidot;[Ŀ]. - "\x05idot;\x02Ŀ", - // LongLeftRightArrow;[⟷] Longleftrightarrow;[⟺] LowerRightArrow;[↘] LongRightArrow;[⟶] Longrightarrow;[⟹] LowerLeftArrow;[↙] LongLeftArrow;[⟵] Longleftarrow;[⟸] Lopf;[𝕃]. - "\x11ngLeftRightArrow;\x03⟷\x11ngleftrightarrow;\x03⟺\x0ewerRightArrow;\x03↘\x0dngRightArrow;\x03⟶\x0dngrightarrow;\x03⟹\x0dwerLeftArrow;\x03↙\x0cngLeftArrow;\x03⟵\x0cngleftarrow;\x03⟸\x03pf;\x04𝕃", - // Lstrok;[Ł] Lscr;[ℒ] Lsh;[↰]. - "\x05trok;\x02Ł\x03cr;\x03ℒ\x02h;\x03↰", - // Lt;[≪]. - "\x01;\x03≪", - // Map;[⤅]. - "\x02p;\x03⤅", - // Mcy;[М]. - "\x02y;\x02М", - // MediumSpace;[ ] Mellintrf;[ℳ]. - "\x0adiumSpace;\x03 \x08llintrf;\x03ℳ", - // Mfr;[𝔐]. - "\x02r;\x04𝔐", - // MinusPlus;[∓]. - "\x08nusPlus;\x03∓", - // Mopf;[𝕄]. - "\x03pf;\x04𝕄", - // Mscr;[ℳ]. - "\x03cr;\x03ℳ", - // Mu;[Μ]. - "\x01;\x02Μ", - // NJcy;[Њ]. - "\x03cy;\x02Њ", - // Nacute;[Ń]. - "\x05cute;\x02Ń", - // Ncaron;[Ň] Ncedil;[Ņ] Ncy;[Н]. - "\x05aron;\x02Ň\x05edil;\x02Ņ\x02y;\x02Н", - // NegativeVeryThinSpace;[​] NestedGreaterGreater;[≫] NegativeMediumSpace;[​] NegativeThickSpace;[​] NegativeThinSpace;[​] NestedLessLess;[≪] NewLine;[\xa]. - "\x14gativeVeryThinSpace;\x03​\x13stedGreaterGreater;\x03≫\x12gativeMediumSpace;\x03​\x11gativeThickSpace;\x03​\x10gativeThinSpace;\x03​\x0dstedLessLess;\x03≪\x06wLine;\x01\xa", - // Nfr;[𝔑]. - "\x02r;\x04𝔑", - // NotNestedGreaterGreater;[⪢̸] NotSquareSupersetEqual;[⋣] NotPrecedesSlantEqual;[⋠] NotRightTriangleEqual;[⋭] NotSucceedsSlantEqual;[⋡] NotDoubleVerticalBar;[∦] NotGreaterSlantEqual;[⩾̸] NotLeftTriangleEqual;[⋬] NotSquareSubsetEqual;[⋢] NotGreaterFullEqual;[≧̸] NotRightTriangleBar;[⧐̸] NotLeftTriangleBar;[⧏̸] NotGreaterGreater;[≫̸] NotLessSlantEqual;[⩽̸] NotNestedLessLess;[⪡̸] NotReverseElement;[∌] NotSquareSuperset;[⊐̸] NotTildeFullEqual;[≇] NonBreakingSpace;[ ] NotPrecedesEqual;[⪯̸] NotRightTriangle;[⋫] NotSucceedsEqual;[⪰̸] NotSucceedsTilde;[≿̸] NotSupersetEqual;[⊉] NotGreaterEqual;[≱] NotGreaterTilde;[≵] NotHumpDownHump;[≎̸] NotLeftTriangle;[⋪] NotSquareSubset;[⊏̸] NotGreaterLess;[≹] NotLessGreater;[≸] NotSubsetEqual;[⊈] NotVerticalBar;[∤] NotEqualTilde;[≂̸] NotTildeEqual;[≄] NotTildeTilde;[≉] NotCongruent;[≢] NotHumpEqual;[≏̸] NotLessEqual;[≰] NotLessTilde;[≴] NotLessLess;[≪̸] NotPrecedes;[⊀] NotSucceeds;[⊁] NotSuperset;[⊃⃒] NotElement;[∉] NotGreater;[≯] NotCupCap;[≭] NotExists;[∄] NotSubset;[⊂⃒] NotEqual;[≠] NotTilde;[≁] NoBreak;[⁠] NotLess;[≮] Nopf;[ℕ] Not;[⫬]. - "\x16tNestedGreaterGreater;\x05⪢̸\x15tSquareSupersetEqual;\x03⋣\x14tPrecedesSlantEqual;\x03⋠\x14tRightTriangleEqual;\x03⋭\x14tSucceedsSlantEqual;\x03⋡\x13tDoubleVerticalBar;\x03∦\x13tGreaterSlantEqual;\x05⩾̸\x13tLeftTriangleEqual;\x03⋬\x13tSquareSubsetEqual;\x03⋢\x12tGreaterFullEqual;\x05≧̸\x12tRightTriangleBar;\x05⧐̸\x11tLeftTriangleBar;\x05⧏̸\x10tGreaterGreater;\x05≫̸\x10tLessSlantEqual;\x05⩽̸\x10tNestedLessLess;\x05⪡̸\x10tReverseElement;\x03∌\x10tSquareSuperset;\x05⊐̸\x10tTildeFullEqual;\x03≇\x0fnBreakingSpace;\x02 \x0ftPrecedesEqual;\x05⪯̸\x0ftRightTriangle;\x03⋫\x0ftSucceedsEqual;\x05⪰̸\x0ftSucceedsTilde;\x05≿̸\x0ftSupersetEqual;\x03⊉\x0etGreaterEqual;\x03≱\x0etGreaterTilde;\x03≵\x0etHumpDownHump;\x05≎̸\x0etLeftTriangle;\x03⋪\x0etSquareSubset;\x05⊏̸\x0dtGreaterLess;\x03≹\x0dtLessGreater;\x03≸\x0dtSubsetEqual;\x03⊈\x0dtVerticalBar;\x03∤\x0ctEqualTilde;\x05≂̸\x0ctTildeEqual;\x03≄\x0ctTildeTilde;\x03≉\x0btCongruent;\x03≢\x0btHumpEqual;\x05≏̸\x0btLessEqual;\x03≰\x0btLessTilde;\x03≴\x0atLessLess;\x05≪̸\x0atPrecedes;\x03⊀\x0atSucceeds;\x03⊁\x0atSuperset;\x06⊃⃒\x09tElement;\x03∉\x09tGreater;\x03≯\x08tCupCap;\x03≭\x08tExists;\x03∄\x08tSubset;\x06⊂⃒\x07tEqual;\x03≠\x07tTilde;\x03≁\x06Break;\x03⁠\x06tLess;\x03≮\x03pf;\x03ℕ\x02t;\x03⫬", - // Nscr;[𝒩]. - "\x03cr;\x04𝒩", - // Ntilde;[Ñ] Ntilde[Ñ]. - "\x05ilde;\x02Ñ\x04ilde\x02Ñ", - // Nu;[Ν]. - "\x01;\x02Ν", - // OElig;[Œ]. - "\x04lig;\x02Œ", - // Oacute;[Ó] Oacute[Ó]. - "\x05cute;\x02Ó\x04cute\x02Ó", - // Ocirc;[Ô] Ocirc[Ô] Ocy;[О]. - "\x04irc;\x02Ô\x03irc\x02Ô\x02y;\x02О", - // Odblac;[Ő]. - "\x05blac;\x02Ő", - // Ofr;[𝔒]. - "\x02r;\x04𝔒", - // Ograve;[Ò] Ograve[Ò]. - "\x05rave;\x02Ò\x04rave\x02Ò", - // Omicron;[Ο] Omacr;[Ō] Omega;[Ω]. - "\x06icron;\x02Ο\x04acr;\x02Ō\x04ega;\x02Ω", - // Oopf;[𝕆]. - "\x03pf;\x04𝕆", - // OpenCurlyDoubleQuote;[“] OpenCurlyQuote;[‘]. - "\x13enCurlyDoubleQuote;\x03“\x0denCurlyQuote;\x03‘", - // Or;[⩔]. - "\x01;\x03⩔", - // Oslash;[Ø] Oslash[Ø] Oscr;[𝒪]. - "\x05lash;\x02Ø\x04lash\x02Ø\x03cr;\x04𝒪", - // Otilde;[Õ] Otimes;[⨷] Otilde[Õ]. - "\x05ilde;\x02Õ\x05imes;\x03⨷\x04ilde\x02Õ", - // Ouml;[Ö] Ouml[Ö]. - "\x03ml;\x02Ö\x02ml\x02Ö", - // OverParenthesis;[⏜] OverBracket;[⎴] OverBrace;[⏞] OverBar;[‾]. - "\x0eerParenthesis;\x03⏜\x0aerBracket;\x03⎴\x08erBrace;\x03⏞\x06erBar;\x03‾", - // PartialD;[∂]. - "\x07rtialD;\x03∂", - // Pcy;[П]. - "\x02y;\x02П", - // Pfr;[𝔓]. - "\x02r;\x04𝔓", - // Phi;[Φ]. - "\x02i;\x02Φ", - // Pi;[Π]. - "\x01;\x02Π", - // PlusMinus;[±]. - "\x08usMinus;\x02±", - // Poincareplane;[ℌ] Popf;[ℙ]. - "\x0cincareplane;\x03ℌ\x03pf;\x03ℙ", - // PrecedesSlantEqual;[≼] PrecedesEqual;[⪯] PrecedesTilde;[≾] Proportional;[∝] Proportion;[∷] Precedes;[≺] Product;[∏] Prime;[″] Pr;[⪻]. - "\x11ecedesSlantEqual;\x03≼\x0cecedesEqual;\x03⪯\x0cecedesTilde;\x03≾\x0boportional;\x03∝\x09oportion;\x03∷\x07ecedes;\x03≺\x06oduct;\x03∏\x04ime;\x03″\x01;\x03⪻", - // Pscr;[𝒫] Psi;[Ψ]. - "\x03cr;\x04𝒫\x02i;\x02Ψ", - // QUOT;[\"] QUOT[\"]. - "\x03OT;\x01\"\x02OT\x01\"", - // Qfr;[𝔔]. - "\x02r;\x04𝔔", - // Qopf;[ℚ]. - "\x03pf;\x03ℚ", - // Qscr;[𝒬]. - "\x03cr;\x04𝒬", - // RBarr;[⤐]. - "\x04arr;\x03⤐", - // REG;[®] REG[®]. - "\x02G;\x02®\x01G\x02®", - // Racute;[Ŕ] Rarrtl;[⤖] Rang;[⟫] Rarr;[↠]. - "\x05cute;\x02Ŕ\x05rrtl;\x03⤖\x03ng;\x03⟫\x03rr;\x03↠", - // Rcaron;[Ř] Rcedil;[Ŗ] Rcy;[Р]. - "\x05aron;\x02Ř\x05edil;\x02Ŗ\x02y;\x02Р", - // ReverseUpEquilibrium;[⥯] ReverseEquilibrium;[⇋] ReverseElement;[∋] Re;[ℜ]. - "\x13verseUpEquilibrium;\x03⥯\x11verseEquilibrium;\x03⇋\x0dverseElement;\x03∋\x01;\x03ℜ", - // Rfr;[ℜ]. - "\x02r;\x03ℜ", - // Rho;[Ρ]. - "\x02o;\x02Ρ", - // RightArrowLeftArrow;[⇄] RightDoubleBracket;[⟧] RightDownTeeVector;[⥝] RightDownVectorBar;[⥕] RightTriangleEqual;[⊵] RightAngleBracket;[⟩] RightUpDownVector;[⥏] RightTriangleBar;[⧐] RightUpTeeVector;[⥜] RightUpVectorBar;[⥔] RightDownVector;[⇂] RightTeeVector;[⥛] RightVectorBar;[⥓] RightArrowBar;[⇥] RightTeeArrow;[↦] RightTriangle;[⊳] RightUpVector;[↾] RightCeiling;[⌉] RightVector;[⇀] RightArrow;[→] RightFloor;[⌋] Rightarrow;[⇒] RightTee;[⊢]. - "\x12ghtArrowLeftArrow;\x03⇄\x11ghtDoubleBracket;\x03⟧\x11ghtDownTeeVector;\x03⥝\x11ghtDownVectorBar;\x03⥕\x11ghtTriangleEqual;\x03⊵\x10ghtAngleBracket;\x03⟩\x10ghtUpDownVector;\x03⥏\x0fghtTriangleBar;\x03⧐\x0fghtUpTeeVector;\x03⥜\x0fghtUpVectorBar;\x03⥔\x0eghtDownVector;\x03⇂\x0dghtTeeVector;\x03⥛\x0dghtVectorBar;\x03⥓\x0cghtArrowBar;\x03⇥\x0cghtTeeArrow;\x03↦\x0cghtTriangle;\x03⊳\x0cghtUpVector;\x03↾\x0bghtCeiling;\x03⌉\x0aghtVector;\x03⇀\x09ghtArrow;\x03→\x09ghtFloor;\x03⌋\x09ghtarrow;\x03⇒\x07ghtTee;\x03⊢", - // RoundImplies;[⥰] Ropf;[ℝ]. - "\x0bundImplies;\x03⥰\x03pf;\x03ℝ", - // Rrightarrow;[⇛]. - "\x0aightarrow;\x03⇛", - // Rscr;[ℛ] Rsh;[↱]. - "\x03cr;\x03ℛ\x02h;\x03↱", - // RuleDelayed;[⧴]. - "\x0aleDelayed;\x03⧴", - // SHCHcy;[Щ] SHcy;[Ш]. - "\x05CHcy;\x02Щ\x03cy;\x02Ш", - // SOFTcy;[Ь]. - "\x05FTcy;\x02Ь", - // Sacute;[Ś]. - "\x05cute;\x02Ś", - // Scaron;[Š] Scedil;[Ş] Scirc;[Ŝ] Scy;[С] Sc;[⪼]. - "\x05aron;\x02Š\x05edil;\x02Ş\x04irc;\x02Ŝ\x02y;\x02С\x01;\x03⪼", - // Sfr;[𝔖]. - "\x02r;\x04𝔖", - // ShortRightArrow;[→] ShortDownArrow;[↓] ShortLeftArrow;[←] ShortUpArrow;[↑]. - "\x0eortRightArrow;\x03→\x0dortDownArrow;\x03↓\x0dortLeftArrow;\x03←\x0bortUpArrow;\x03↑", - // Sigma;[Σ]. - "\x04gma;\x02Σ", - // SmallCircle;[∘]. - "\x0aallCircle;\x03∘", - // Sopf;[𝕊]. - "\x03pf;\x04𝕊", - // SquareSupersetEqual;[⊒] SquareIntersection;[⊓] SquareSubsetEqual;[⊑] SquareSuperset;[⊐] SquareSubset;[⊏] SquareUnion;[⊔] Square;[□] Sqrt;[√]. - "\x12uareSupersetEqual;\x03⊒\x11uareIntersection;\x03⊓\x10uareSubsetEqual;\x03⊑\x0duareSuperset;\x03⊐\x0buareSubset;\x03⊏\x0auareUnion;\x03⊔\x05uare;\x03□\x03rt;\x03√", - // Sscr;[𝒮]. - "\x03cr;\x04𝒮", - // Star;[⋆]. - "\x03ar;\x03⋆", - // SucceedsSlantEqual;[≽] SucceedsEqual;[⪰] SucceedsTilde;[≿] SupersetEqual;[⊇] SubsetEqual;[⊆] Succeeds;[≻] SuchThat;[∋] Superset;[⊃] Subset;[⋐] Supset;[⋑] Sub;[⋐] Sum;[∑] Sup;[⋑]. - "\x11cceedsSlantEqual;\x03≽\x0ccceedsEqual;\x03⪰\x0ccceedsTilde;\x03≿\x0cpersetEqual;\x03⊇\x0absetEqual;\x03⊆\x07cceeds;\x03≻\x07chThat;\x03∋\x07perset;\x03⊃\x05bset;\x03⋐\x05pset;\x03⋑\x02b;\x03⋐\x02m;\x03∑\x02p;\x03⋑", - // THORN;[Þ] THORN[Þ]. - "\x04ORN;\x02Þ\x03ORN\x02Þ", - // TRADE;[™]. - "\x04ADE;\x03™", - // TSHcy;[Ћ] TScy;[Ц]. - "\x04Hcy;\x02Ћ\x03cy;\x02Ц", - // Tab;[\x9] Tau;[Τ]. - "\x02b;\x01\x9\x02u;\x02Τ", - // Tcaron;[Ť] Tcedil;[Ţ] Tcy;[Т]. - "\x05aron;\x02Ť\x05edil;\x02Ţ\x02y;\x02Т", - // Tfr;[𝔗]. - "\x02r;\x04𝔗", - // ThickSpace;[  ] Therefore;[∴] ThinSpace;[ ] Theta;[Θ]. - "\x09ickSpace;\x06  \x08erefore;\x03∴\x08inSpace;\x03 \x04eta;\x02Θ", - // TildeFullEqual;[≅] TildeEqual;[≃] TildeTilde;[≈] Tilde;[∼]. - "\x0dldeFullEqual;\x03≅\x09ldeEqual;\x03≃\x09ldeTilde;\x03≈\x04lde;\x03∼", - // Topf;[𝕋]. - "\x03pf;\x04𝕋", - // TripleDot;[⃛]. - "\x08ipleDot;\x03⃛", - // Tstrok;[Ŧ] Tscr;[𝒯]. - "\x05trok;\x02Ŧ\x03cr;\x04𝒯", - // Uarrocir;[⥉] Uacute;[Ú] Uacute[Ú] Uarr;[↟]. - "\x07rrocir;\x03⥉\x05cute;\x02Ú\x04cute\x02Ú\x03rr;\x03↟", - // Ubreve;[Ŭ] Ubrcy;[Ў]. - "\x05reve;\x02Ŭ\x04rcy;\x02Ў", - // Ucirc;[Û] Ucirc[Û] Ucy;[У]. - "\x04irc;\x02Û\x03irc\x02Û\x02y;\x02У", - // Udblac;[Ű]. - "\x05blac;\x02Ű", - // Ufr;[𝔘]. - "\x02r;\x04𝔘", - // Ugrave;[Ù] Ugrave[Ù]. - "\x05rave;\x02Ù\x04rave\x02Ù", - // Umacr;[Ū]. - "\x04acr;\x02Ū", - // UnderParenthesis;[⏝] UnderBracket;[⎵] UnderBrace;[⏟] UnionPlus;[⊎] UnderBar;[_] Union;[⋃]. - "\x0fderParenthesis;\x03⏝\x0bderBracket;\x03⎵\x09derBrace;\x03⏟\x08ionPlus;\x03⊎\x07derBar;\x01_\x04ion;\x03⋃", - // Uogon;[Ų] Uopf;[𝕌]. - "\x04gon;\x02Ų\x03pf;\x04𝕌", - // UpArrowDownArrow;[⇅] UpperRightArrow;[↗] UpperLeftArrow;[↖] UpEquilibrium;[⥮] UpDownArrow;[↕] Updownarrow;[⇕] UpArrowBar;[⤒] UpTeeArrow;[↥] UpArrow;[↑] Uparrow;[⇑] Upsilon;[Υ] UpTee;[⊥] Upsi;[ϒ]. - "\x0fArrowDownArrow;\x03⇅\x0eperRightArrow;\x03↗\x0dperLeftArrow;\x03↖\x0cEquilibrium;\x03⥮\x0aDownArrow;\x03↕\x0adownarrow;\x03⇕\x09ArrowBar;\x03⤒\x09TeeArrow;\x03↥\x06Arrow;\x03↑\x06arrow;\x03⇑\x06silon;\x02Υ\x04Tee;\x03⊥\x03si;\x02ϒ", - // Uring;[Ů]. - "\x04ing;\x02Ů", - // Uscr;[𝒰]. - "\x03cr;\x04𝒰", - // Utilde;[Ũ]. - "\x05ilde;\x02Ũ", - // Uuml;[Ü] Uuml[Ü]. - "\x03ml;\x02Ü\x02ml\x02Ü", - // VDash;[⊫]. - "\x04ash;\x03⊫", - // Vbar;[⫫]. - "\x03ar;\x03⫫", - // Vcy;[В]. - "\x02y;\x02В", - // Vdashl;[⫦] Vdash;[⊩]. - "\x05ashl;\x03⫦\x04ash;\x03⊩", - // VerticalSeparator;[❘] VerticalTilde;[≀] VeryThinSpace;[ ] VerticalLine;[|] VerticalBar;[∣] Verbar;[‖] Vert;[‖] Vee;[⋁]. - "\x10rticalSeparator;\x03❘\x0crticalTilde;\x03≀\x0cryThinSpace;\x03 \x0brticalLine;\x01|\x0articalBar;\x03∣\x05rbar;\x03‖\x03rt;\x03‖\x02e;\x03⋁", - // Vfr;[𝔙]. - "\x02r;\x04𝔙", - // Vopf;[𝕍]. - "\x03pf;\x04𝕍", - // Vscr;[𝒱]. - "\x03cr;\x04𝒱", - // Vvdash;[⊪]. - "\x05dash;\x03⊪", - // Wcirc;[Ŵ]. - "\x04irc;\x02Ŵ", - // Wedge;[⋀]. - "\x04dge;\x03⋀", - // Wfr;[𝔚]. - "\x02r;\x04𝔚", - // Wopf;[𝕎]. - "\x03pf;\x04𝕎", - // Wscr;[𝒲]. - "\x03cr;\x04𝒲", - // Xfr;[𝔛]. - "\x02r;\x04𝔛", - // Xi;[Ξ]. - "\x01;\x02Ξ", - // Xopf;[𝕏]. - "\x03pf;\x04𝕏", - // Xscr;[𝒳]. - "\x03cr;\x04𝒳", - // YAcy;[Я]. - "\x03cy;\x02Я", - // YIcy;[Ї]. - "\x03cy;\x02Ї", - // YUcy;[Ю]. - "\x03cy;\x02Ю", - // Yacute;[Ý] Yacute[Ý]. - "\x05cute;\x02Ý\x04cute\x02Ý", - // Ycirc;[Ŷ] Ycy;[Ы]. - "\x04irc;\x02Ŷ\x02y;\x02Ы", - // Yfr;[𝔜]. - "\x02r;\x04𝔜", - // Yopf;[𝕐]. - "\x03pf;\x04𝕐", - // Yscr;[𝒴]. - "\x03cr;\x04𝒴", - // Yuml;[Ÿ]. - "\x03ml;\x02Ÿ", - // ZHcy;[Ж]. - "\x03cy;\x02Ж", - // Zacute;[Ź]. - "\x05cute;\x02Ź", - // Zcaron;[Ž] Zcy;[З]. - "\x05aron;\x02Ž\x02y;\x02З", - // Zdot;[Ż]. - "\x03ot;\x02Ż", - // ZeroWidthSpace;[​] Zeta;[Ζ]. - "\x0droWidthSpace;\x03​\x03ta;\x02Ζ", - // Zfr;[ℨ]. - "\x02r;\x03ℨ", - // Zopf;[ℤ]. - "\x03pf;\x03ℤ", - // Zscr;[𝒵]. - "\x03cr;\x04𝒵", - // aacute;[á] aacute[á]. - "\x05cute;\x02á\x04cute\x02á", - // abreve;[ă]. - "\x05reve;\x02ă", - // acirc;[â] acute;[´] acirc[â] acute[´] acE;[∾̳] acd;[∿] acy;[а] ac;[∾]. - "\x04irc;\x02â\x04ute;\x02´\x03irc\x02â\x03ute\x02´\x02E;\x05∾̳\x02d;\x03∿\x02y;\x02а\x01;\x03∾", - // aelig;[æ] aelig[æ]. - "\x04lig;\x02æ\x03lig\x02æ", - // afr;[𝔞] af;[⁡]. - "\x02r;\x04𝔞\x01;\x03⁡", - // agrave;[à] agrave[à]. - "\x05rave;\x02à\x04rave\x02à", - // alefsym;[ℵ] aleph;[ℵ] alpha;[α]. - "\x06efsym;\x03ℵ\x04eph;\x03ℵ\x04pha;\x02α", - // amacr;[ā] amalg;[⨿] amp;[&] amp[&]. - "\x04acr;\x02ā\x04alg;\x03⨿\x02p;\x01&\x01p\x01&", - // andslope;[⩘] angmsdaa;[⦨] angmsdab;[⦩] angmsdac;[⦪] angmsdad;[⦫] angmsdae;[⦬] angmsdaf;[⦭] angmsdag;[⦮] angmsdah;[⦯] angrtvbd;[⦝] angrtvb;[⊾] angzarr;[⍼] andand;[⩕] angmsd;[∡] angsph;[∢] angle;[∠] angrt;[∟] angst;[Å] andd;[⩜] andv;[⩚] ange;[⦤] and;[∧] ang;[∠]. - "\x07dslope;\x03⩘\x07gmsdaa;\x03⦨\x07gmsdab;\x03⦩\x07gmsdac;\x03⦪\x07gmsdad;\x03⦫\x07gmsdae;\x03⦬\x07gmsdaf;\x03⦭\x07gmsdag;\x03⦮\x07gmsdah;\x03⦯\x07grtvbd;\x03⦝\x06grtvb;\x03⊾\x06gzarr;\x03⍼\x05dand;\x03⩕\x05gmsd;\x03∡\x05gsph;\x03∢\x04gle;\x03∠\x04grt;\x03∟\x04gst;\x02Å\x03dd;\x03⩜\x03dv;\x03⩚\x03ge;\x03⦤\x02d;\x03∧\x02g;\x03∠", - // aogon;[ą] aopf;[𝕒]. - "\x04gon;\x02ą\x03pf;\x04𝕒", - // approxeq;[≊] apacir;[⩯] approx;[≈] apid;[≋] apos;['] apE;[⩰] ape;[≊] ap;[≈]. - "\x07proxeq;\x03≊\x05acir;\x03⩯\x05prox;\x03≈\x03id;\x03≋\x03os;\x01'\x02E;\x03⩰\x02e;\x03≊\x01;\x03≈", - // aring;[å] aring[å]. - "\x04ing;\x02å\x03ing\x02å", - // asympeq;[≍] asymp;[≈] ascr;[𝒶] ast;[*]. - "\x06ympeq;\x03≍\x04ymp;\x03≈\x03cr;\x04𝒶\x02t;\x01*", - // atilde;[ã] atilde[ã]. - "\x05ilde;\x02ã\x04ilde\x02ã", - // auml;[ä] auml[ä]. - "\x03ml;\x02ä\x02ml\x02ä", - // awconint;[∳] awint;[⨑]. - "\x07conint;\x03∳\x04int;\x03⨑", - // bNot;[⫭]. - "\x03ot;\x03⫭", - // backepsilon;[϶] backprime;[‵] backsimeq;[⋍] backcong;[≌] barwedge;[⌅] backsim;[∽] barvee;[⊽] barwed;[⌅]. - "\x0ackepsilon;\x02϶\x08ckprime;\x03‵\x08cksimeq;\x03⋍\x07ckcong;\x03≌\x07rwedge;\x03⌅\x06cksim;\x03∽\x05rvee;\x03⊽\x05rwed;\x03⌅", - // bbrktbrk;[⎶] bbrk;[⎵]. - "\x07rktbrk;\x03⎶\x03rk;\x03⎵", - // bcong;[≌] bcy;[б]. - "\x04ong;\x03≌\x02y;\x02б", - // bdquo;[„]. - "\x04quo;\x03„", - // because;[∵] bemptyv;[⦰] between;[≬] becaus;[∵] bernou;[ℬ] bepsi;[϶] beta;[β] beth;[ℶ]. - "\x06cause;\x03∵\x06mptyv;\x03⦰\x06tween;\x03≬\x05caus;\x03∵\x05rnou;\x03ℬ\x04psi;\x02϶\x03ta;\x02β\x03th;\x03ℶ", - // bfr;[𝔟]. - "\x02r;\x04𝔟", - // bigtriangledown;[▽] bigtriangleup;[△] bigotimes;[⨂] bigoplus;[⨁] bigsqcup;[⨆] biguplus;[⨄] bigwedge;[⋀] bigcirc;[◯] bigodot;[⨀] bigstar;[★] bigcap;[⋂] bigcup;[⋃] bigvee;[⋁]. - "\x0egtriangledown;\x03▽\x0cgtriangleup;\x03△\x08gotimes;\x03⨂\x07goplus;\x03⨁\x07gsqcup;\x03⨆\x07guplus;\x03⨄\x07gwedge;\x03⋀\x06gcirc;\x03◯\x06godot;\x03⨀\x06gstar;\x03★\x05gcap;\x03⋂\x05gcup;\x03⋃\x05gvee;\x03⋁", - // bkarow;[⤍]. - "\x05arow;\x03⤍", - // blacktriangleright;[▸] blacktriangledown;[▾] blacktriangleleft;[◂] blacktriangle;[▴] blacklozenge;[⧫] blacksquare;[▪] blank;[␣] blk12;[▒] blk14;[░] blk34;[▓] block;[█]. - "\x11acktriangleright;\x03▸\x10acktriangledown;\x03▾\x10acktriangleleft;\x03◂\x0cacktriangle;\x03▴\x0backlozenge;\x03⧫\x0aacksquare;\x03▪\x04ank;\x03␣\x04k12;\x03▒\x04k14;\x03░\x04k34;\x03▓\x04ock;\x03█", - // bnequiv;[≡⃥] bnot;[⌐] bne;[=⃥]. - "\x06equiv;\x06≡⃥\x03ot;\x03⌐\x02e;\x04=⃥", - // boxminus;[⊟] boxtimes;[⊠] boxplus;[⊞] bottom;[⊥] bowtie;[⋈] boxbox;[⧉] boxDL;[╗] boxDR;[╔] boxDl;[╖] boxDr;[╓] boxHD;[╦] boxHU;[╩] boxHd;[╤] boxHu;[╧] boxUL;[╝] boxUR;[╚] boxUl;[╜] boxUr;[╙] boxVH;[╬] boxVL;[╣] boxVR;[╠] boxVh;[╫] boxVl;[╢] boxVr;[╟] boxdL;[╕] boxdR;[╒] boxdl;[┐] boxdr;[┌] boxhD;[╥] boxhU;[╨] boxhd;[┬] boxhu;[┴] boxuL;[╛] boxuR;[╘] boxul;[┘] boxur;[└] boxvH;[╪] boxvL;[╡] boxvR;[╞] boxvh;[┼] boxvl;[┤] boxvr;[├] bopf;[𝕓] boxH;[═] boxV;[║] boxh;[─] boxv;[│] bot;[⊥]. - "\x07xminus;\x03⊟\x07xtimes;\x03⊠\x06xplus;\x03⊞\x05ttom;\x03⊥\x05wtie;\x03⋈\x05xbox;\x03⧉\x04xDL;\x03╗\x04xDR;\x03╔\x04xDl;\x03╖\x04xDr;\x03╓\x04xHD;\x03╦\x04xHU;\x03╩\x04xHd;\x03╤\x04xHu;\x03╧\x04xUL;\x03╝\x04xUR;\x03╚\x04xUl;\x03╜\x04xUr;\x03╙\x04xVH;\x03╬\x04xVL;\x03╣\x04xVR;\x03╠\x04xVh;\x03╫\x04xVl;\x03╢\x04xVr;\x03╟\x04xdL;\x03╕\x04xdR;\x03╒\x04xdl;\x03┐\x04xdr;\x03┌\x04xhD;\x03╥\x04xhU;\x03╨\x04xhd;\x03┬\x04xhu;\x03┴\x04xuL;\x03╛\x04xuR;\x03╘\x04xul;\x03┘\x04xur;\x03└\x04xvH;\x03╪\x04xvL;\x03╡\x04xvR;\x03╞\x04xvh;\x03┼\x04xvl;\x03┤\x04xvr;\x03├\x03pf;\x04𝕓\x03xH;\x03═\x03xV;\x03║\x03xh;\x03─\x03xv;\x03│\x02t;\x03⊥", - // bprime;[‵]. - "\x05rime;\x03‵", - // brvbar;[¦] breve;[˘] brvbar[¦]. - "\x05vbar;\x02¦\x04eve;\x02˘\x04vbar\x02¦", - // bsolhsub;[⟈] bsemi;[⁏] bsime;[⋍] bsolb;[⧅] bscr;[𝒷] bsim;[∽] bsol;[\\]. - "\x07olhsub;\x03⟈\x04emi;\x03⁏\x04ime;\x03⋍\x04olb;\x03⧅\x03cr;\x04𝒷\x03im;\x03∽\x03ol;\x01\\", - // bullet;[•] bumpeq;[≏] bumpE;[⪮] bumpe;[≏] bull;[•] bump;[≎]. - "\x05llet;\x03•\x05mpeq;\x03≏\x04mpE;\x03⪮\x04mpe;\x03≏\x03ll;\x03•\x03mp;\x03≎", - // capbrcup;[⩉] cacute;[ć] capand;[⩄] capcap;[⩋] capcup;[⩇] capdot;[⩀] caret;[⁁] caron;[ˇ] caps;[∩︀] cap;[∩]. - "\x07pbrcup;\x03⩉\x05cute;\x02ć\x05pand;\x03⩄\x05pcap;\x03⩋\x05pcup;\x03⩇\x05pdot;\x03⩀\x04ret;\x03⁁\x04ron;\x02ˇ\x03ps;\x06∩︀\x02p;\x03∩", - // ccupssm;[⩐] ccaron;[č] ccedil;[ç] ccaps;[⩍] ccedil[ç] ccirc;[ĉ] ccups;[⩌]. - "\x06upssm;\x03⩐\x05aron;\x02č\x05edil;\x02ç\x04aps;\x03⩍\x04edil\x02ç\x04irc;\x02ĉ\x04ups;\x03⩌", - // cdot;[ċ]. - "\x03ot;\x02ċ", - // centerdot;[·] cemptyv;[⦲] cedil;[¸] cedil[¸] cent;[¢] cent[¢]. - "\x08nterdot;\x02·\x06mptyv;\x03⦲\x04dil;\x02¸\x03dil\x02¸\x03nt;\x02¢\x02nt\x02¢", - // cfr;[𝔠]. - "\x02r;\x04𝔠", - // checkmark;[✓] check;[✓] chcy;[ч] chi;[χ]. - "\x08eckmark;\x03✓\x04eck;\x03✓\x03cy;\x02ч\x02i;\x02χ", - // circlearrowright;[↻] circlearrowleft;[↺] circledcirc;[⊚] circleddash;[⊝] circledast;[⊛] circledR;[®] circledS;[Ⓢ] cirfnint;[⨐] cirscir;[⧂] circeq;[≗] cirmid;[⫯] cirE;[⧃] circ;[ˆ] cire;[≗] cir;[○]. - "\x0frclearrowright;\x03↻\x0erclearrowleft;\x03↺\x0arcledcirc;\x03⊚\x0arcleddash;\x03⊝\x09rcledast;\x03⊛\x07rcledR;\x02®\x07rcledS;\x03Ⓢ\x07rfnint;\x03⨐\x06rscir;\x03⧂\x05rceq;\x03≗\x05rmid;\x03⫯\x03rE;\x03⧃\x03rc;\x02ˆ\x03re;\x03≗\x02r;\x03○", - // clubsuit;[♣] clubs;[♣]. - "\x07ubsuit;\x03♣\x04ubs;\x03♣", - // complement;[∁] complexes;[ℂ] coloneq;[≔] congdot;[⩭] colone;[≔] commat;[@] compfn;[∘] conint;[∮] coprod;[∐] copysr;[℗] colon;[:] comma;[,] comp;[∁] cong;[≅] copf;[𝕔] copy;[©] copy[©]. - "\x09mplement;\x03∁\x08mplexes;\x03ℂ\x06loneq;\x03≔\x06ngdot;\x03⩭\x05lone;\x03≔\x05mmat;\x01@\x05mpfn;\x03∘\x05nint;\x03∮\x05prod;\x03∐\x05pysr;\x03℗\x04lon;\x01:\x04mma;\x01,\x03mp;\x03∁\x03ng;\x03≅\x03pf;\x04𝕔\x03py;\x02©\x02py\x02©", - // crarr;[↵] cross;[✗]. - "\x04arr;\x03↵\x04oss;\x03✗", - // csube;[⫑] csupe;[⫒] cscr;[𝒸] csub;[⫏] csup;[⫐]. - "\x04ube;\x03⫑\x04upe;\x03⫒\x03cr;\x04𝒸\x03ub;\x03⫏\x03up;\x03⫐", - // ctdot;[⋯]. - "\x04dot;\x03⋯", - // curvearrowright;[↷] curvearrowleft;[↶] curlyeqprec;[⋞] curlyeqsucc;[⋟] curlywedge;[⋏] cupbrcap;[⩈] curlyvee;[⋎] cudarrl;[⤸] cudarrr;[⤵] cularrp;[⤽] curarrm;[⤼] cularr;[↶] cupcap;[⩆] cupcup;[⩊] cupdot;[⊍] curarr;[↷] curren;[¤] cuepr;[⋞] cuesc;[⋟] cupor;[⩅] curren[¤] cuvee;[⋎] cuwed;[⋏] cups;[∪︀] cup;[∪]. - "\x0ervearrowright;\x03↷\x0drvearrowleft;\x03↶\x0arlyeqprec;\x03⋞\x0arlyeqsucc;\x03⋟\x09rlywedge;\x03⋏\x07pbrcap;\x03⩈\x07rlyvee;\x03⋎\x06darrl;\x03⤸\x06darrr;\x03⤵\x06larrp;\x03⤽\x06rarrm;\x03⤼\x05larr;\x03↶\x05pcap;\x03⩆\x05pcup;\x03⩊\x05pdot;\x03⊍\x05rarr;\x03↷\x05rren;\x02¤\x04epr;\x03⋞\x04esc;\x03⋟\x04por;\x03⩅\x04rren\x02¤\x04vee;\x03⋎\x04wed;\x03⋏\x03ps;\x06∪︀\x02p;\x03∪", - // cwconint;[∲] cwint;[∱]. - "\x07conint;\x03∲\x04int;\x03∱", - // cylcty;[⌭]. - "\x05lcty;\x03⌭", - // dArr;[⇓]. - "\x03rr;\x03⇓", - // dHar;[⥥]. - "\x03ar;\x03⥥", - // dagger;[†] daleth;[ℸ] dashv;[⊣] darr;[↓] dash;[‐]. - "\x05gger;\x03†\x05leth;\x03ℸ\x04shv;\x03⊣\x03rr;\x03↓\x03sh;\x03‐", - // dbkarow;[⤏] dblac;[˝]. - "\x06karow;\x03⤏\x04lac;\x02˝", - // dcaron;[ď] dcy;[д]. - "\x05aron;\x02ď\x02y;\x02д", - // ddagger;[‡] ddotseq;[⩷] ddarr;[⇊] dd;[ⅆ]. - "\x06agger;\x03‡\x06otseq;\x03⩷\x04arr;\x03⇊\x01;\x03ⅆ", - // demptyv;[⦱] delta;[δ] deg;[°] deg[°]. - "\x06mptyv;\x03⦱\x04lta;\x02δ\x02g;\x02°\x01g\x02°", - // dfisht;[⥿] dfr;[𝔡]. - "\x05isht;\x03⥿\x02r;\x04𝔡", - // dharl;[⇃] dharr;[⇂]. - "\x04arl;\x03⇃\x04arr;\x03⇂", - // divideontimes;[⋇] diamondsuit;[♦] diamond;[⋄] digamma;[ϝ] divide;[÷] divonx;[⋇] diams;[♦] disin;[⋲] divide[÷] diam;[⋄] die;[¨] div;[÷]. - "\x0cvideontimes;\x03⋇\x0aamondsuit;\x03♦\x06amond;\x03⋄\x06gamma;\x02ϝ\x05vide;\x02÷\x05vonx;\x03⋇\x04ams;\x03♦\x04sin;\x03⋲\x04vide\x02÷\x03am;\x03⋄\x02e;\x02¨\x02v;\x02÷", - // djcy;[ђ]. - "\x03cy;\x02ђ", - // dlcorn;[⌞] dlcrop;[⌍]. - "\x05corn;\x03⌞\x05crop;\x03⌍", - // downharpoonright;[⇂] downharpoonleft;[⇃] doublebarwedge;[⌆] downdownarrows;[⇊] dotsquare;[⊡] downarrow;[↓] doteqdot;[≑] dotminus;[∸] dotplus;[∔] dollar;[$] doteq;[≐] dopf;[𝕕] dot;[˙]. - "\x0fwnharpoonright;\x03⇂\x0ewnharpoonleft;\x03⇃\x0dublebarwedge;\x03⌆\x0dwndownarrows;\x03⇊\x08tsquare;\x03⊡\x08wnarrow;\x03↓\x07teqdot;\x03≑\x07tminus;\x03∸\x06tplus;\x03∔\x05llar;\x01$\x04teq;\x03≐\x03pf;\x04𝕕\x02t;\x02˙", - // drbkarow;[⤐] drcorn;[⌟] drcrop;[⌌]. - "\x07bkarow;\x03⤐\x05corn;\x03⌟\x05crop;\x03⌌", - // dstrok;[đ] dscr;[𝒹] dscy;[ѕ] dsol;[⧶]. - "\x05trok;\x02đ\x03cr;\x04𝒹\x03cy;\x02ѕ\x03ol;\x03⧶", - // dtdot;[⋱] dtrif;[▾] dtri;[▿]. - "\x04dot;\x03⋱\x04rif;\x03▾\x03ri;\x03▿", - // duarr;[⇵] duhar;[⥯]. - "\x04arr;\x03⇵\x04har;\x03⥯", - // dwangle;[⦦]. - "\x06angle;\x03⦦", - // dzigrarr;[⟿] dzcy;[џ]. - "\x07igrarr;\x03⟿\x03cy;\x02џ", - // eDDot;[⩷] eDot;[≑]. - "\x04Dot;\x03⩷\x03ot;\x03≑", - // eacute;[é] easter;[⩮] eacute[é]. - "\x05cute;\x02é\x05ster;\x03⩮\x04cute\x02é", - // ecaron;[ě] ecolon;[≕] ecirc;[ê] ecir;[≖] ecirc[ê] ecy;[э]. - "\x05aron;\x02ě\x05olon;\x03≕\x04irc;\x02ê\x03ir;\x03≖\x03irc\x02ê\x02y;\x02э", - // edot;[ė]. - "\x03ot;\x02ė", - // ee;[ⅇ]. - "\x01;\x03ⅇ", - // efDot;[≒] efr;[𝔢]. - "\x04Dot;\x03≒\x02r;\x04𝔢", - // egrave;[è] egsdot;[⪘] egrave[è] egs;[⪖] eg;[⪚]. - "\x05rave;\x02è\x05sdot;\x03⪘\x04rave\x02è\x02s;\x03⪖\x01;\x03⪚", - // elinters;[⏧] elsdot;[⪗] ell;[ℓ] els;[⪕] el;[⪙]. - "\x07inters;\x03⏧\x05sdot;\x03⪗\x02l;\x03ℓ\x02s;\x03⪕\x01;\x03⪙", - // emptyset;[∅] emptyv;[∅] emsp13;[ ] emsp14;[ ] emacr;[ē] empty;[∅] emsp;[ ]. - "\x07ptyset;\x03∅\x05ptyv;\x03∅\x05sp13;\x03 \x05sp14;\x03 \x04acr;\x02ē\x04pty;\x03∅\x03sp;\x03 ", - // ensp;[ ] eng;[ŋ]. - "\x03sp;\x03 \x02g;\x02ŋ", - // eogon;[ę] eopf;[𝕖]. - "\x04gon;\x02ę\x03pf;\x04𝕖", - // epsilon;[ε] eparsl;[⧣] eplus;[⩱] epsiv;[ϵ] epar;[⋕] epsi;[ε]. - "\x06silon;\x02ε\x05arsl;\x03⧣\x04lus;\x03⩱\x04siv;\x02ϵ\x03ar;\x03⋕\x03si;\x02ε", - // eqslantless;[⪕] eqslantgtr;[⪖] eqvparsl;[⧥] eqcolon;[≕] equivDD;[⩸] eqcirc;[≖] equals;[=] equest;[≟] eqsim;[≂] equiv;[≡]. - "\x0aslantless;\x03⪕\x09slantgtr;\x03⪖\x07vparsl;\x03⧥\x06colon;\x03≕\x06uivDD;\x03⩸\x05circ;\x03≖\x05uals;\x01=\x05uest;\x03≟\x04sim;\x03≂\x04uiv;\x03≡", - // erDot;[≓] erarr;[⥱]. - "\x04Dot;\x03≓\x04arr;\x03⥱", - // esdot;[≐] escr;[ℯ] esim;[≂]. - "\x04dot;\x03≐\x03cr;\x03ℯ\x03im;\x03≂", - // eta;[η] eth;[ð] eth[ð]. - "\x02a;\x02η\x02h;\x02ð\x01h\x02ð", - // euml;[ë] euro;[€] euml[ë]. - "\x03ml;\x02ë\x03ro;\x03€\x02ml\x02ë", - // exponentiale;[ⅇ] expectation;[ℰ] exist;[∃] excl;[!]. - "\x0bponentiale;\x03ⅇ\x0apectation;\x03ℰ\x04ist;\x03∃\x03cl;\x01!", - // fallingdotseq;[≒]. - "\x0cllingdotseq;\x03≒", - // fcy;[ф]. - "\x02y;\x02ф", - // female;[♀]. - "\x05male;\x03♀", - // ffilig;[ffi] ffllig;[ffl] fflig;[ff] ffr;[𝔣]. - "\x05ilig;\x03ffi\x05llig;\x03ffl\x04lig;\x03ff\x02r;\x04𝔣", - // filig;[fi]. - "\x04lig;\x03fi", - // fjlig;[fj]. - "\x04lig;\x02fj", - // fllig;[fl] fltns;[▱] flat;[♭]. - "\x04lig;\x03fl\x04tns;\x03▱\x03at;\x03♭", - // fnof;[ƒ]. - "\x03of;\x02ƒ", - // forall;[∀] forkv;[⫙] fopf;[𝕗] fork;[⋔]. - "\x05rall;\x03∀\x04rkv;\x03⫙\x03pf;\x04𝕗\x03rk;\x03⋔", - // fpartint;[⨍]. - "\x07artint;\x03⨍", - // frac12;[½] frac13;[⅓] frac14;[¼] frac15;[⅕] frac16;[⅙] frac18;[⅛] frac23;[⅔] frac25;[⅖] frac34;[¾] frac35;[⅗] frac38;[⅜] frac45;[⅘] frac56;[⅚] frac58;[⅝] frac78;[⅞] frac12[½] frac14[¼] frac34[¾] frasl;[⁄] frown;[⌢]. - "\x05ac12;\x02½\x05ac13;\x03⅓\x05ac14;\x02¼\x05ac15;\x03⅕\x05ac16;\x03⅙\x05ac18;\x03⅛\x05ac23;\x03⅔\x05ac25;\x03⅖\x05ac34;\x02¾\x05ac35;\x03⅗\x05ac38;\x03⅜\x05ac45;\x03⅘\x05ac56;\x03⅚\x05ac58;\x03⅝\x05ac78;\x03⅞\x04ac12\x02½\x04ac14\x02¼\x04ac34\x02¾\x04asl;\x03⁄\x04own;\x03⌢", - // fscr;[𝒻]. - "\x03cr;\x04𝒻", - // gEl;[⪌] gE;[≧]. - "\x02l;\x03⪌\x01;\x03≧", - // gacute;[ǵ] gammad;[ϝ] gamma;[γ] gap;[⪆]. - "\x05cute;\x02ǵ\x05mmad;\x02ϝ\x04mma;\x02γ\x02p;\x03⪆", - // gbreve;[ğ]. - "\x05reve;\x02ğ", - // gcirc;[ĝ] gcy;[г]. - "\x04irc;\x02ĝ\x02y;\x02г", - // gdot;[ġ]. - "\x03ot;\x02ġ", - // geqslant;[⩾] gesdotol;[⪄] gesdoto;[⪂] gesdot;[⪀] gesles;[⪔] gescc;[⪩] geqq;[≧] gesl;[⋛︀] gel;[⋛] geq;[≥] ges;[⩾] ge;[≥]. - "\x07qslant;\x03⩾\x07sdotol;\x03⪄\x06sdoto;\x03⪂\x05sdot;\x03⪀\x05sles;\x03⪔\x04scc;\x03⪩\x03qq;\x03≧\x03sl;\x06⋛︀\x02l;\x03⋛\x02q;\x03≥\x02s;\x03⩾\x01;\x03≥", - // gfr;[𝔤]. - "\x02r;\x04𝔤", - // ggg;[⋙] gg;[≫]. - "\x02g;\x03⋙\x01;\x03≫", - // gimel;[ℷ]. - "\x04mel;\x03ℷ", - // gjcy;[ѓ]. - "\x03cy;\x02ѓ", - // glE;[⪒] gla;[⪥] glj;[⪤] gl;[≷]. - "\x02E;\x03⪒\x02a;\x03⪥\x02j;\x03⪤\x01;\x03≷", - // gnapprox;[⪊] gneqq;[≩] gnsim;[⋧] gnap;[⪊] gneq;[⪈] gnE;[≩] gne;[⪈]. - "\x07approx;\x03⪊\x04eqq;\x03≩\x04sim;\x03⋧\x03ap;\x03⪊\x03eq;\x03⪈\x02E;\x03≩\x02e;\x03⪈", - // gopf;[𝕘]. - "\x03pf;\x04𝕘", - // grave;[`]. - "\x04ave;\x01`", - // gsime;[⪎] gsiml;[⪐] gscr;[ℊ] gsim;[≳]. - "\x04ime;\x03⪎\x04iml;\x03⪐\x03cr;\x03ℊ\x03im;\x03≳", - // gtreqqless;[⪌] gtrapprox;[⪆] gtreqless;[⋛] gtquest;[⩼] gtrless;[≷] gtlPar;[⦕] gtrarr;[⥸] gtrdot;[⋗] gtrsim;[≳] gtcir;[⩺] gtdot;[⋗] gtcc;[⪧] gt;[>]. - "\x09reqqless;\x03⪌\x08rapprox;\x03⪆\x08reqless;\x03⋛\x06quest;\x03⩼\x06rless;\x03≷\x05lPar;\x03⦕\x05rarr;\x03⥸\x05rdot;\x03⋗\x05rsim;\x03≳\x04cir;\x03⩺\x04dot;\x03⋗\x03cc;\x03⪧\x01;\x01>", - // gvertneqq;[≩︀] gvnE;[≩︀]. - "\x08ertneqq;\x06≩︀\x03nE;\x06≩︀", - // hArr;[⇔]. - "\x03rr;\x03⇔", - // harrcir;[⥈] hairsp;[ ] hamilt;[ℋ] hardcy;[ъ] harrw;[↭] half;[½] harr;[↔]. - "\x06rrcir;\x03⥈\x05irsp;\x03 \x05milt;\x03ℋ\x05rdcy;\x02ъ\x04rrw;\x03↭\x03lf;\x02½\x03rr;\x03↔", - // hbar;[ℏ]. - "\x03ar;\x03ℏ", - // hcirc;[ĥ]. - "\x04irc;\x02ĥ", - // heartsuit;[♥] hearts;[♥] hellip;[…] hercon;[⊹]. - "\x08artsuit;\x03♥\x05arts;\x03♥\x05llip;\x03…\x05rcon;\x03⊹", - // hfr;[𝔥]. - "\x02r;\x04𝔥", - // hksearow;[⤥] hkswarow;[⤦]. - "\x07searow;\x03⤥\x07swarow;\x03⤦", - // hookrightarrow;[↪] hookleftarrow;[↩] homtht;[∻] horbar;[―] hoarr;[⇿] hopf;[𝕙]. - "\x0dokrightarrow;\x03↪\x0cokleftarrow;\x03↩\x05mtht;\x03∻\x05rbar;\x03―\x04arr;\x03⇿\x03pf;\x04𝕙", - // hslash;[ℏ] hstrok;[ħ] hscr;[𝒽]. - "\x05lash;\x03ℏ\x05trok;\x02ħ\x03cr;\x04𝒽", - // hybull;[⁃] hyphen;[‐]. - "\x05bull;\x03⁃\x05phen;\x03‐", - // iacute;[í] iacute[í]. - "\x05cute;\x02í\x04cute\x02í", - // icirc;[î] icirc[î] icy;[и] ic;[⁣]. - "\x04irc;\x02î\x03irc\x02î\x02y;\x02и\x01;\x03⁣", - // iexcl;[¡] iecy;[е] iexcl[¡]. - "\x04xcl;\x02¡\x03cy;\x02е\x03xcl\x02¡", - // iff;[⇔] ifr;[𝔦]. - "\x02f;\x03⇔\x02r;\x04𝔦", - // igrave;[ì] igrave[ì]. - "\x05rave;\x02ì\x04rave\x02ì", - // iiiint;[⨌] iinfin;[⧜] iiint;[∭] iiota;[℩] ii;[ⅈ]. - "\x05iint;\x03⨌\x05nfin;\x03⧜\x04int;\x03∭\x04ota;\x03℩\x01;\x03ⅈ", - // ijlig;[ij]. - "\x04lig;\x02ij", - // imagline;[ℐ] imagpart;[ℑ] imacr;[ī] image;[ℑ] imath;[ı] imped;[Ƶ] imof;[⊷]. - "\x07agline;\x03ℐ\x07agpart;\x03ℑ\x04acr;\x02ī\x04age;\x03ℑ\x04ath;\x02ı\x04ped;\x02Ƶ\x03of;\x03⊷", - // infintie;[⧝] integers;[ℤ] intercal;[⊺] intlarhk;[⨗] intprod;[⨼] incare;[℅] inodot;[ı] intcal;[⊺] infin;[∞] int;[∫] in;[∈]. - "\x07fintie;\x03⧝\x07tegers;\x03ℤ\x07tercal;\x03⊺\x07tlarhk;\x03⨗\x06tprod;\x03⨼\x05care;\x03℅\x05odot;\x02ı\x05tcal;\x03⊺\x04fin;\x03∞\x02t;\x03∫\x01;\x03∈", - // iogon;[į] iocy;[ё] iopf;[𝕚] iota;[ι]. - "\x04gon;\x02į\x03cy;\x02ё\x03pf;\x04𝕚\x03ta;\x02ι", - // iprod;[⨼]. - "\x04rod;\x03⨼", - // iquest;[¿] iquest[¿]. - "\x05uest;\x02¿\x04uest\x02¿", - // isindot;[⋵] isinsv;[⋳] isinE;[⋹] isins;[⋴] isinv;[∈] iscr;[𝒾] isin;[∈]. - "\x06indot;\x03⋵\x05insv;\x03⋳\x04inE;\x03⋹\x04ins;\x03⋴\x04inv;\x03∈\x03cr;\x04𝒾\x03in;\x03∈", - // itilde;[ĩ] it;[⁢]. - "\x05ilde;\x02ĩ\x01;\x03⁢", - // iukcy;[і] iuml;[ï] iuml[ï]. - "\x04kcy;\x02і\x03ml;\x02ï\x02ml\x02ï", - // jcirc;[ĵ] jcy;[й]. - "\x04irc;\x02ĵ\x02y;\x02й", - // jfr;[𝔧]. - "\x02r;\x04𝔧", - // jmath;[ȷ]. - "\x04ath;\x02ȷ", - // jopf;[𝕛]. - "\x03pf;\x04𝕛", - // jsercy;[ј] jscr;[𝒿]. - "\x05ercy;\x02ј\x03cr;\x04𝒿", - // jukcy;[є]. - "\x04kcy;\x02є", - // kappav;[ϰ] kappa;[κ]. - "\x05ppav;\x02ϰ\x04ppa;\x02κ", - // kcedil;[ķ] kcy;[к]. - "\x05edil;\x02ķ\x02y;\x02к", - // kfr;[𝔨]. - "\x02r;\x04𝔨", - // kgreen;[ĸ]. - "\x05reen;\x02ĸ", - // khcy;[х]. - "\x03cy;\x02х", - // kjcy;[ќ]. - "\x03cy;\x02ќ", - // kopf;[𝕜]. - "\x03pf;\x04𝕜", - // kscr;[𝓀]. - "\x03cr;\x04𝓀", - // lAtail;[⤛] lAarr;[⇚] lArr;[⇐]. - "\x05tail;\x03⤛\x04arr;\x03⇚\x03rr;\x03⇐", - // lBarr;[⤎]. - "\x04arr;\x03⤎", - // lEg;[⪋] lE;[≦]. - "\x02g;\x03⪋\x01;\x03≦", - // lHar;[⥢]. - "\x03ar;\x03⥢", - // laemptyv;[⦴] larrbfs;[⤟] larrsim;[⥳] lacute;[ĺ] lagran;[ℒ] lambda;[λ] langle;[⟨] larrfs;[⤝] larrhk;[↩] larrlp;[↫] larrpl;[⤹] larrtl;[↢] latail;[⤙] langd;[⦑] laquo;[«] larrb;[⇤] lates;[⪭︀] lang;[⟨] laquo[«] larr;[←] late;[⪭] lap;[⪅] lat;[⪫]. - "\x07emptyv;\x03⦴\x06rrbfs;\x03⤟\x06rrsim;\x03⥳\x05cute;\x02ĺ\x05gran;\x03ℒ\x05mbda;\x02λ\x05ngle;\x03⟨\x05rrfs;\x03⤝\x05rrhk;\x03↩\x05rrlp;\x03↫\x05rrpl;\x03⤹\x05rrtl;\x03↢\x05tail;\x03⤙\x04ngd;\x03⦑\x04quo;\x02«\x04rrb;\x03⇤\x04tes;\x06⪭︀\x03ng;\x03⟨\x03quo\x02«\x03rr;\x03←\x03te;\x03⪭\x02p;\x03⪅\x02t;\x03⪫", - // lbrksld;[⦏] lbrkslu;[⦍] lbrace;[{] lbrack;[[] lbarr;[⤌] lbbrk;[❲] lbrke;[⦋]. - "\x06rksld;\x03⦏\x06rkslu;\x03⦍\x05race;\x01{\x05rack;\x01[\x04arr;\x03⤌\x04brk;\x03❲\x04rke;\x03⦋", - // lcaron;[ľ] lcedil;[ļ] lceil;[⌈] lcub;[{] lcy;[л]. - "\x05aron;\x02ľ\x05edil;\x02ļ\x04eil;\x03⌈\x03ub;\x01{\x02y;\x02л", - // ldrushar;[⥋] ldrdhar;[⥧] ldquor;[„] ldquo;[“] ldca;[⤶] ldsh;[↲]. - "\x07rushar;\x03⥋\x06rdhar;\x03⥧\x05quor;\x03„\x04quo;\x03“\x03ca;\x03⤶\x03sh;\x03↲", - // leftrightsquigarrow;[↭] leftrightharpoons;[⇋] leftharpoondown;[↽] leftrightarrows;[⇆] leftleftarrows;[⇇] leftrightarrow;[↔] leftthreetimes;[⋋] leftarrowtail;[↢] leftharpoonup;[↼] lessapprox;[⪅] lesseqqgtr;[⪋] leftarrow;[←] lesseqgtr;[⋚] leqslant;[⩽] lesdotor;[⪃] lesdoto;[⪁] lessdot;[⋖] lessgtr;[≶] lesssim;[≲] lesdot;[⩿] lesges;[⪓] lescc;[⪨] leqq;[≦] lesg;[⋚︀] leg;[⋚] leq;[≤] les;[⩽] le;[≤]. - "\x12ftrightsquigarrow;\x03↭\x10ftrightharpoons;\x03⇋\x0eftharpoondown;\x03↽\x0eftrightarrows;\x03⇆\x0dftleftarrows;\x03⇇\x0dftrightarrow;\x03↔\x0dftthreetimes;\x03⋋\x0cftarrowtail;\x03↢\x0cftharpoonup;\x03↼\x09ssapprox;\x03⪅\x09sseqqgtr;\x03⪋\x08ftarrow;\x03←\x08sseqgtr;\x03⋚\x07qslant;\x03⩽\x07sdotor;\x03⪃\x06sdoto;\x03⪁\x06ssdot;\x03⋖\x06ssgtr;\x03≶\x06sssim;\x03≲\x05sdot;\x03⩿\x05sges;\x03⪓\x04scc;\x03⪨\x03qq;\x03≦\x03sg;\x06⋚︀\x02g;\x03⋚\x02q;\x03≤\x02s;\x03⩽\x01;\x03≤", - // lfisht;[⥼] lfloor;[⌊] lfr;[𝔩]. - "\x05isht;\x03⥼\x05loor;\x03⌊\x02r;\x04𝔩", - // lgE;[⪑] lg;[≶]. - "\x02E;\x03⪑\x01;\x03≶", - // lharul;[⥪] lhard;[↽] lharu;[↼] lhblk;[▄]. - "\x05arul;\x03⥪\x04ard;\x03↽\x04aru;\x03↼\x04blk;\x03▄", - // ljcy;[љ]. - "\x03cy;\x02љ", - // llcorner;[⌞] llhard;[⥫] llarr;[⇇] lltri;[◺] ll;[≪]. - "\x07corner;\x03⌞\x05hard;\x03⥫\x04arr;\x03⇇\x04tri;\x03◺\x01;\x03≪", - // lmoustache;[⎰] lmidot;[ŀ] lmoust;[⎰]. - "\x09oustache;\x03⎰\x05idot;\x02ŀ\x05oust;\x03⎰", - // lnapprox;[⪉] lneqq;[≨] lnsim;[⋦] lnap;[⪉] lneq;[⪇] lnE;[≨] lne;[⪇]. - "\x07approx;\x03⪉\x04eqq;\x03≨\x04sim;\x03⋦\x03ap;\x03⪉\x03eq;\x03⪇\x02E;\x03≨\x02e;\x03⪇", - // longleftrightarrow;[⟷] longrightarrow;[⟶] looparrowright;[↬] longleftarrow;[⟵] looparrowleft;[↫] longmapsto;[⟼] lotimes;[⨴] lozenge;[◊] loplus;[⨭] lowast;[∗] lowbar;[_] loang;[⟬] loarr;[⇽] lobrk;[⟦] lopar;[⦅] lopf;[𝕝] lozf;[⧫] loz;[◊]. - "\x11ngleftrightarrow;\x03⟷\x0dngrightarrow;\x03⟶\x0doparrowright;\x03↬\x0cngleftarrow;\x03⟵\x0coparrowleft;\x03↫\x09ngmapsto;\x03⟼\x06times;\x03⨴\x06zenge;\x03◊\x05plus;\x03⨭\x05wast;\x03∗\x05wbar;\x01_\x04ang;\x03⟬\x04arr;\x03⇽\x04brk;\x03⟦\x04par;\x03⦅\x03pf;\x04𝕝\x03zf;\x03⧫\x02z;\x03◊", - // lparlt;[⦓] lpar;[(]. - "\x05arlt;\x03⦓\x03ar;\x01(", - // lrcorner;[⌟] lrhard;[⥭] lrarr;[⇆] lrhar;[⇋] lrtri;[⊿] lrm;[‎]. - "\x07corner;\x03⌟\x05hard;\x03⥭\x04arr;\x03⇆\x04har;\x03⇋\x04tri;\x03⊿\x02m;\x03‎", - // lsaquo;[‹] lsquor;[‚] lstrok;[ł] lsime;[⪍] lsimg;[⪏] lsquo;[‘] lscr;[𝓁] lsim;[≲] lsqb;[[] lsh;[↰]. - "\x05aquo;\x03‹\x05quor;\x03‚\x05trok;\x02ł\x04ime;\x03⪍\x04img;\x03⪏\x04quo;\x03‘\x03cr;\x04𝓁\x03im;\x03≲\x03qb;\x01[\x02h;\x03↰", - // ltquest;[⩻] lthree;[⋋] ltimes;[⋉] ltlarr;[⥶] ltrPar;[⦖] ltcir;[⩹] ltdot;[⋖] ltrie;[⊴] ltrif;[◂] ltcc;[⪦] ltri;[◃] lt;[<]. - "\x06quest;\x03⩻\x05hree;\x03⋋\x05imes;\x03⋉\x05larr;\x03⥶\x05rPar;\x03⦖\x04cir;\x03⩹\x04dot;\x03⋖\x04rie;\x03⊴\x04rif;\x03◂\x03cc;\x03⪦\x03ri;\x03◃\x01;\x01<", - // lurdshar;[⥊] luruhar;[⥦]. - "\x07rdshar;\x03⥊\x06ruhar;\x03⥦", - // lvertneqq;[≨︀] lvnE;[≨︀]. - "\x08ertneqq;\x06≨︀\x03nE;\x06≨︀", - // mDDot;[∺]. - "\x04Dot;\x03∺", - // mapstodown;[↧] mapstoleft;[↤] mapstoup;[↥] maltese;[✠] mapsto;[↦] marker;[▮] macr;[¯] male;[♂] malt;[✠] macr[¯] map;[↦]. - "\x09pstodown;\x03↧\x09pstoleft;\x03↤\x07pstoup;\x03↥\x06ltese;\x03✠\x05psto;\x03↦\x05rker;\x03▮\x03cr;\x02¯\x03le;\x03♂\x03lt;\x03✠\x02cr\x02¯\x02p;\x03↦", - // mcomma;[⨩] mcy;[м]. - "\x05omma;\x03⨩\x02y;\x02м", - // mdash;[—]. - "\x04ash;\x03—", - // measuredangle;[∡]. - "\x0casuredangle;\x03∡", - // mfr;[𝔪]. - "\x02r;\x04𝔪", - // mho;[℧]. - "\x02o;\x03℧", - // minusdu;[⨪] midast;[*] midcir;[⫰] middot;[·] minusb;[⊟] minusd;[∸] micro;[µ] middot[·] minus;[−] micro[µ] mid;[∣]. - "\x06nusdu;\x03⨪\x05dast;\x01*\x05dcir;\x03⫰\x05ddot;\x02·\x05nusb;\x03⊟\x05nusd;\x03∸\x04cro;\x02µ\x04ddot\x02·\x04nus;\x03−\x03cro\x02µ\x02d;\x03∣", - // mlcp;[⫛] mldr;[…]. - "\x03cp;\x03⫛\x03dr;\x03…", - // mnplus;[∓]. - "\x05plus;\x03∓", - // models;[⊧] mopf;[𝕞]. - "\x05dels;\x03⊧\x03pf;\x04𝕞", - // mp;[∓]. - "\x01;\x03∓", - // mstpos;[∾] mscr;[𝓂]. - "\x05tpos;\x03∾\x03cr;\x04𝓂", - // multimap;[⊸] mumap;[⊸] mu;[μ]. - "\x07ltimap;\x03⊸\x04map;\x03⊸\x01;\x02μ", - // nGtv;[≫̸] nGg;[⋙̸] nGt;[≫⃒]. - "\x03tv;\x05≫̸\x02g;\x05⋙̸\x02t;\x06≫⃒", - // nLeftrightarrow;[⇎] nLeftarrow;[⇍] nLtv;[≪̸] nLl;[⋘̸] nLt;[≪⃒]. - "\x0eeftrightarrow;\x03⇎\x09eftarrow;\x03⇍\x03tv;\x05≪̸\x02l;\x05⋘̸\x02t;\x06≪⃒", - // nRightarrow;[⇏]. - "\x0aightarrow;\x03⇏", - // nVDash;[⊯] nVdash;[⊮]. - "\x05Dash;\x03⊯\x05dash;\x03⊮", - // naturals;[ℕ] napprox;[≉] natural;[♮] nacute;[ń] nabla;[∇] napid;[≋̸] napos;[ʼn] natur;[♮] nang;[∠⃒] napE;[⩰̸] nap;[≉]. - "\x07turals;\x03ℕ\x06pprox;\x03≉\x06tural;\x03♮\x05cute;\x02ń\x04bla;\x03∇\x04pid;\x05≋̸\x04pos;\x02ʼn\x04tur;\x03♮\x03ng;\x06∠⃒\x03pE;\x05⩰̸\x02p;\x03≉", - // nbumpe;[≏̸] nbump;[≎̸] nbsp;[ ] nbsp[ ]. - "\x05umpe;\x05≏̸\x04ump;\x05≎̸\x03sp;\x02 \x02sp\x02 ", - // ncongdot;[⩭̸] ncaron;[ň] ncedil;[ņ] ncong;[≇] ncap;[⩃] ncup;[⩂] ncy;[н]. - "\x07ongdot;\x05⩭̸\x05aron;\x02ň\x05edil;\x02ņ\x04ong;\x03≇\x03ap;\x03⩃\x03up;\x03⩂\x02y;\x02н", - // ndash;[–]. - "\x04ash;\x03–", - // nearrow;[↗] nexists;[∄] nearhk;[⤤] nequiv;[≢] nesear;[⤨] nexist;[∄] neArr;[⇗] nearr;[↗] nedot;[≐̸] nesim;[≂̸] ne;[≠]. - "\x06arrow;\x03↗\x06xists;\x03∄\x05arhk;\x03⤤\x05quiv;\x03≢\x05sear;\x03⤨\x05xist;\x03∄\x04Arr;\x03⇗\x04arr;\x03↗\x04dot;\x05≐̸\x04sim;\x05≂̸\x01;\x03≠", - // nfr;[𝔫]. - "\x02r;\x04𝔫", - // ngeqslant;[⩾̸] ngeqq;[≧̸] ngsim;[≵] ngeq;[≱] nges;[⩾̸] ngtr;[≯] ngE;[≧̸] nge;[≱] ngt;[≯]. - "\x08eqslant;\x05⩾̸\x04eqq;\x05≧̸\x04sim;\x03≵\x03eq;\x03≱\x03es;\x05⩾̸\x03tr;\x03≯\x02E;\x05≧̸\x02e;\x03≱\x02t;\x03≯", - // nhArr;[⇎] nharr;[↮] nhpar;[⫲]. - "\x04Arr;\x03⇎\x04arr;\x03↮\x04par;\x03⫲", - // nisd;[⋺] nis;[⋼] niv;[∋] ni;[∋]. - "\x03sd;\x03⋺\x02s;\x03⋼\x02v;\x03∋\x01;\x03∋", - // njcy;[њ]. - "\x03cy;\x02њ", - // nleftrightarrow;[↮] nleftarrow;[↚] nleqslant;[⩽̸] nltrie;[⋬] nlArr;[⇍] nlarr;[↚] nleqq;[≦̸] nless;[≮] nlsim;[≴] nltri;[⋪] nldr;[‥] nleq;[≰] nles;[⩽̸] nlE;[≦̸] nle;[≰] nlt;[≮]. - "\x0eeftrightarrow;\x03↮\x09eftarrow;\x03↚\x08eqslant;\x05⩽̸\x05trie;\x03⋬\x04Arr;\x03⇍\x04arr;\x03↚\x04eqq;\x05≦̸\x04ess;\x03≮\x04sim;\x03≴\x04tri;\x03⋪\x03dr;\x03‥\x03eq;\x03≰\x03es;\x05⩽̸\x02E;\x05≦̸\x02e;\x03≰\x02t;\x03≮", - // nmid;[∤]. - "\x03id;\x03∤", - // notindot;[⋵̸] notinva;[∉] notinvb;[⋷] notinvc;[⋶] notniva;[∌] notnivb;[⋾] notnivc;[⋽] notinE;[⋹̸] notin;[∉] notni;[∌] nopf;[𝕟] not;[¬] not[¬]. - "\x07tindot;\x05⋵̸\x06tinva;\x03∉\x06tinvb;\x03⋷\x06tinvc;\x03⋶\x06tniva;\x03∌\x06tnivb;\x03⋾\x06tnivc;\x03⋽\x05tinE;\x05⋹̸\x04tin;\x03∉\x04tni;\x03∌\x03pf;\x04𝕟\x02t;\x02¬\x01t\x02¬", - // nparallel;[∦] npolint;[⨔] npreceq;[⪯̸] nparsl;[⫽⃥] nprcue;[⋠] npart;[∂̸] nprec;[⊀] npar;[∦] npre;[⪯̸] npr;[⊀]. - "\x08arallel;\x03∦\x06olint;\x03⨔\x06receq;\x05⪯̸\x05arsl;\x06⫽⃥\x05rcue;\x03⋠\x04art;\x05∂̸\x04rec;\x03⊀\x03ar;\x03∦\x03re;\x05⪯̸\x02r;\x03⊀", - // nrightarrow;[↛] nrarrc;[⤳̸] nrarrw;[↝̸] nrtrie;[⋭] nrArr;[⇏] nrarr;[↛] nrtri;[⋫]. - "\x0aightarrow;\x03↛\x05arrc;\x05⤳̸\x05arrw;\x05↝̸\x05trie;\x03⋭\x04Arr;\x03⇏\x04arr;\x03↛\x04tri;\x03⋫", - // nshortparallel;[∦] nsubseteqq;[⫅̸] nsupseteqq;[⫆̸] nshortmid;[∤] nsubseteq;[⊈] nsupseteq;[⊉] nsqsube;[⋢] nsqsupe;[⋣] nsubset;[⊂⃒] nsucceq;[⪰̸] nsupset;[⊃⃒] nsccue;[⋡] nsimeq;[≄] nsime;[≄] nsmid;[∤] nspar;[∦] nsubE;[⫅̸] nsube;[⊈] nsucc;[⊁] nsupE;[⫆̸] nsupe;[⊉] nsce;[⪰̸] nscr;[𝓃] nsim;[≁] nsub;[⊄] nsup;[⊅] nsc;[⊁]. - "\x0dhortparallel;\x03∦\x09ubseteqq;\x05⫅̸\x09upseteqq;\x05⫆̸\x08hortmid;\x03∤\x08ubseteq;\x03⊈\x08upseteq;\x03⊉\x06qsube;\x03⋢\x06qsupe;\x03⋣\x06ubset;\x06⊂⃒\x06ucceq;\x05⪰̸\x06upset;\x06⊃⃒\x05ccue;\x03⋡\x05imeq;\x03≄\x04ime;\x03≄\x04mid;\x03∤\x04par;\x03∦\x04ubE;\x05⫅̸\x04ube;\x03⊈\x04ucc;\x03⊁\x04upE;\x05⫆̸\x04upe;\x03⊉\x03ce;\x05⪰̸\x03cr;\x04𝓃\x03im;\x03≁\x03ub;\x03⊄\x03up;\x03⊅\x02c;\x03⊁", - // ntrianglerighteq;[⋭] ntrianglelefteq;[⋬] ntriangleright;[⋫] ntriangleleft;[⋪] ntilde;[ñ] ntilde[ñ] ntgl;[≹] ntlg;[≸]. - "\x0frianglerighteq;\x03⋭\x0erianglelefteq;\x03⋬\x0driangleright;\x03⋫\x0criangleleft;\x03⋪\x05ilde;\x02ñ\x04ilde\x02ñ\x03gl;\x03≹\x03lg;\x03≸", - // numero;[№] numsp;[ ] num;[#] nu;[ν]. - "\x05mero;\x03№\x04msp;\x03 \x02m;\x01#\x01;\x02ν", - // nvinfin;[⧞] nvltrie;[⊴⃒] nvrtrie;[⊵⃒] nvDash;[⊭] nvHarr;[⤄] nvdash;[⊬] nvlArr;[⤂] nvrArr;[⤃] nvsim;[∼⃒] nvap;[≍⃒] nvge;[≥⃒] nvgt;[>⃒] nvle;[≤⃒] nvlt;[<⃒]. - "\x06infin;\x03⧞\x06ltrie;\x06⊴⃒\x06rtrie;\x06⊵⃒\x05Dash;\x03⊭\x05Harr;\x03⤄\x05dash;\x03⊬\x05lArr;\x03⤂\x05rArr;\x03⤃\x04sim;\x06∼⃒\x03ap;\x06≍⃒\x03ge;\x06≥⃒\x03gt;\x04>⃒\x03le;\x06≤⃒\x03lt;\x04<⃒", - // nwarrow;[↖] nwarhk;[⤣] nwnear;[⤧] nwArr;[⇖] nwarr;[↖]. - "\x06arrow;\x03↖\x05arhk;\x03⤣\x05near;\x03⤧\x04Arr;\x03⇖\x04arr;\x03↖", - // oS;[Ⓢ]. - "\x01;\x03Ⓢ", - // oacute;[ó] oacute[ó] oast;[⊛]. - "\x05cute;\x02ó\x04cute\x02ó\x03st;\x03⊛", - // ocirc;[ô] ocir;[⊚] ocirc[ô] ocy;[о]. - "\x04irc;\x02ô\x03ir;\x03⊚\x03irc\x02ô\x02y;\x02о", - // odblac;[ő] odsold;[⦼] odash;[⊝] odiv;[⨸] odot;[⊙]. - "\x05blac;\x02ő\x05sold;\x03⦼\x04ash;\x03⊝\x03iv;\x03⨸\x03ot;\x03⊙", - // oelig;[œ]. - "\x04lig;\x02œ", - // ofcir;[⦿] ofr;[𝔬]. - "\x04cir;\x03⦿\x02r;\x04𝔬", - // ograve;[ò] ograve[ò] ogon;[˛] ogt;[⧁]. - "\x05rave;\x02ò\x04rave\x02ò\x03on;\x02˛\x02t;\x03⧁", - // ohbar;[⦵] ohm;[Ω]. - "\x04bar;\x03⦵\x02m;\x02Ω", - // oint;[∮]. - "\x03nt;\x03∮", - // olcross;[⦻] olarr;[↺] olcir;[⦾] oline;[‾] olt;[⧀]. - "\x06cross;\x03⦻\x04arr;\x03↺\x04cir;\x03⦾\x04ine;\x03‾\x02t;\x03⧀", - // omicron;[ο] ominus;[⊖] omacr;[ō] omega;[ω] omid;[⦶]. - "\x06icron;\x02ο\x05inus;\x03⊖\x04acr;\x02ō\x04ega;\x02ω\x03id;\x03⦶", - // oopf;[𝕠]. - "\x03pf;\x04𝕠", - // operp;[⦹] oplus;[⊕] opar;[⦷]. - "\x04erp;\x03⦹\x04lus;\x03⊕\x03ar;\x03⦷", - // orderof;[ℴ] orslope;[⩗] origof;[⊶] orarr;[↻] order;[ℴ] ordf;[ª] ordm;[º] oror;[⩖] ord;[⩝] ordf[ª] ordm[º] orv;[⩛] or;[∨]. - "\x06derof;\x03ℴ\x06slope;\x03⩗\x05igof;\x03⊶\x04arr;\x03↻\x04der;\x03ℴ\x03df;\x02ª\x03dm;\x02º\x03or;\x03⩖\x02d;\x03⩝\x02df\x02ª\x02dm\x02º\x02v;\x03⩛\x01;\x03∨", - // oslash;[ø] oslash[ø] oscr;[ℴ] osol;[⊘]. - "\x05lash;\x02ø\x04lash\x02ø\x03cr;\x03ℴ\x03ol;\x03⊘", - // otimesas;[⨶] otilde;[õ] otimes;[⊗] otilde[õ]. - "\x07imesas;\x03⨶\x05ilde;\x02õ\x05imes;\x03⊗\x04ilde\x02õ", - // ouml;[ö] ouml[ö]. - "\x03ml;\x02ö\x02ml\x02ö", - // ovbar;[⌽]. - "\x04bar;\x03⌽", - // parallel;[∥] parsim;[⫳] parsl;[⫽] para;[¶] part;[∂] par;[∥] para[¶]. - "\x07rallel;\x03∥\x05rsim;\x03⫳\x04rsl;\x03⫽\x03ra;\x02¶\x03rt;\x03∂\x02r;\x03∥\x02ra\x02¶", - // pcy;[п]. - "\x02y;\x02п", - // pertenk;[‱] percnt;[%] period;[.] permil;[‰] perp;[⊥]. - "\x06rtenk;\x03‱\x05rcnt;\x01%\x05riod;\x01.\x05rmil;\x03‰\x03rp;\x03⊥", - // pfr;[𝔭]. - "\x02r;\x04𝔭", - // phmmat;[ℳ] phone;[☎] phiv;[ϕ] phi;[φ]. - "\x05mmat;\x03ℳ\x04one;\x03☎\x03iv;\x02ϕ\x02i;\x02φ", - // pitchfork;[⋔] piv;[ϖ] pi;[π]. - "\x08tchfork;\x03⋔\x02v;\x02ϖ\x01;\x02π", - // plusacir;[⨣] planckh;[ℎ] pluscir;[⨢] plussim;[⨦] plustwo;[⨧] planck;[ℏ] plankv;[ℏ] plusdo;[∔] plusdu;[⨥] plusmn;[±] plusb;[⊞] pluse;[⩲] plusmn[±] plus;[+]. - "\x07usacir;\x03⨣\x06anckh;\x03ℎ\x06uscir;\x03⨢\x06ussim;\x03⨦\x06ustwo;\x03⨧\x05anck;\x03ℏ\x05ankv;\x03ℏ\x05usdo;\x03∔\x05usdu;\x03⨥\x05usmn;\x02±\x04usb;\x03⊞\x04use;\x03⩲\x04usmn\x02±\x03us;\x01+", - // pm;[±]. - "\x01;\x02±", - // pointint;[⨕] pound;[£] popf;[𝕡] pound[£]. - "\x07intint;\x03⨕\x04und;\x02£\x03pf;\x04𝕡\x03und\x02£", - // preccurlyeq;[≼] precnapprox;[⪹] precapprox;[⪷] precneqq;[⪵] precnsim;[⋨] profalar;[⌮] profline;[⌒] profsurf;[⌓] precsim;[≾] preceq;[⪯] primes;[ℙ] prnsim;[⋨] propto;[∝] prurel;[⊰] prcue;[≼] prime;[′] prnap;[⪹] prsim;[≾] prap;[⪷] prec;[≺] prnE;[⪵] prod;[∏] prop;[∝] prE;[⪳] pre;[⪯] pr;[≺]. - "\x0aeccurlyeq;\x03≼\x0aecnapprox;\x03⪹\x09ecapprox;\x03⪷\x07ecneqq;\x03⪵\x07ecnsim;\x03⋨\x07ofalar;\x03⌮\x07ofline;\x03⌒\x07ofsurf;\x03⌓\x06ecsim;\x03≾\x05eceq;\x03⪯\x05imes;\x03ℙ\x05nsim;\x03⋨\x05opto;\x03∝\x05urel;\x03⊰\x04cue;\x03≼\x04ime;\x03′\x04nap;\x03⪹\x04sim;\x03≾\x03ap;\x03⪷\x03ec;\x03≺\x03nE;\x03⪵\x03od;\x03∏\x03op;\x03∝\x02E;\x03⪳\x02e;\x03⪯\x01;\x03≺", - // pscr;[𝓅] psi;[ψ]. - "\x03cr;\x04𝓅\x02i;\x02ψ", - // puncsp;[ ]. - "\x05ncsp;\x03 ", - // qfr;[𝔮]. - "\x02r;\x04𝔮", - // qint;[⨌]. - "\x03nt;\x03⨌", - // qopf;[𝕢]. - "\x03pf;\x04𝕢", - // qprime;[⁗]. - "\x05rime;\x03⁗", - // qscr;[𝓆]. - "\x03cr;\x04𝓆", - // quaternions;[ℍ] quatint;[⨖] questeq;[≟] quest;[?] quot;[\"] quot[\"]. - "\x0aaternions;\x03ℍ\x06atint;\x03⨖\x06esteq;\x03≟\x04est;\x01?\x03ot;\x01\"\x02ot\x01\"", - // rAtail;[⤜] rAarr;[⇛] rArr;[⇒]. - "\x05tail;\x03⤜\x04arr;\x03⇛\x03rr;\x03⇒", - // rBarr;[⤏]. - "\x04arr;\x03⤏", - // rHar;[⥤]. - "\x03ar;\x03⥤", - // rationals;[ℚ] raemptyv;[⦳] rarrbfs;[⤠] rarrsim;[⥴] racute;[ŕ] rangle;[⟩] rarrap;[⥵] rarrfs;[⤞] rarrhk;[↪] rarrlp;[↬] rarrpl;[⥅] rarrtl;[↣] ratail;[⤚] radic;[√] rangd;[⦒] range;[⦥] raquo;[»] rarrb;[⇥] rarrc;[⤳] rarrw;[↝] ratio;[∶] race;[∽̱] rang;[⟩] raquo[»] rarr;[→]. - "\x08tionals;\x03ℚ\x07emptyv;\x03⦳\x06rrbfs;\x03⤠\x06rrsim;\x03⥴\x05cute;\x02ŕ\x05ngle;\x03⟩\x05rrap;\x03⥵\x05rrfs;\x03⤞\x05rrhk;\x03↪\x05rrlp;\x03↬\x05rrpl;\x03⥅\x05rrtl;\x03↣\x05tail;\x03⤚\x04dic;\x03√\x04ngd;\x03⦒\x04nge;\x03⦥\x04quo;\x02»\x04rrb;\x03⇥\x04rrc;\x03⤳\x04rrw;\x03↝\x04tio;\x03∶\x03ce;\x05∽̱\x03ng;\x03⟩\x03quo\x02»\x03rr;\x03→", - // rbrksld;[⦎] rbrkslu;[⦐] rbrace;[}] rbrack;[]] rbarr;[⤍] rbbrk;[❳] rbrke;[⦌]. - "\x06rksld;\x03⦎\x06rkslu;\x03⦐\x05race;\x01}\x05rack;\x01]\x04arr;\x03⤍\x04brk;\x03❳\x04rke;\x03⦌", - // rcaron;[ř] rcedil;[ŗ] rceil;[⌉] rcub;[}] rcy;[р]. - "\x05aron;\x02ř\x05edil;\x02ŗ\x04eil;\x03⌉\x03ub;\x01}\x02y;\x02р", - // rdldhar;[⥩] rdquor;[”] rdquo;[”] rdca;[⤷] rdsh;[↳]. - "\x06ldhar;\x03⥩\x05quor;\x03”\x04quo;\x03”\x03ca;\x03⤷\x03sh;\x03↳", - // realpart;[ℜ] realine;[ℛ] reals;[ℝ] real;[ℜ] rect;[▭] reg;[®] reg[®]. - "\x07alpart;\x03ℜ\x06aline;\x03ℛ\x04als;\x03ℝ\x03al;\x03ℜ\x03ct;\x03▭\x02g;\x02®\x01g\x02®", - // rfisht;[⥽] rfloor;[⌋] rfr;[𝔯]. - "\x05isht;\x03⥽\x05loor;\x03⌋\x02r;\x04𝔯", - // rharul;[⥬] rhard;[⇁] rharu;[⇀] rhov;[ϱ] rho;[ρ]. - "\x05arul;\x03⥬\x04ard;\x03⇁\x04aru;\x03⇀\x03ov;\x02ϱ\x02o;\x02ρ", - // rightleftharpoons;[⇌] rightharpoondown;[⇁] rightrightarrows;[⇉] rightleftarrows;[⇄] rightsquigarrow;[↝] rightthreetimes;[⋌] rightarrowtail;[↣] rightharpoonup;[⇀] risingdotseq;[≓] rightarrow;[→] ring;[˚]. - "\x10ghtleftharpoons;\x03⇌\x0fghtharpoondown;\x03⇁\x0fghtrightarrows;\x03⇉\x0eghtleftarrows;\x03⇄\x0eghtsquigarrow;\x03↝\x0eghtthreetimes;\x03⋌\x0dghtarrowtail;\x03↣\x0dghtharpoonup;\x03⇀\x0bsingdotseq;\x03≓\x09ghtarrow;\x03→\x03ng;\x02˚", - // rlarr;[⇄] rlhar;[⇌] rlm;[‏]. - "\x04arr;\x03⇄\x04har;\x03⇌\x02m;\x03‏", - // rmoustache;[⎱] rmoust;[⎱]. - "\x09oustache;\x03⎱\x05oust;\x03⎱", - // rnmid;[⫮]. - "\x04mid;\x03⫮", - // rotimes;[⨵] roplus;[⨮] roang;[⟭] roarr;[⇾] robrk;[⟧] ropar;[⦆] ropf;[𝕣]. - "\x06times;\x03⨵\x05plus;\x03⨮\x04ang;\x03⟭\x04arr;\x03⇾\x04brk;\x03⟧\x04par;\x03⦆\x03pf;\x04𝕣", - // rppolint;[⨒] rpargt;[⦔] rpar;[)]. - "\x07polint;\x03⨒\x05argt;\x03⦔\x03ar;\x01)", - // rrarr;[⇉]. - "\x04arr;\x03⇉", - // rsaquo;[›] rsquor;[’] rsquo;[’] rscr;[𝓇] rsqb;[]] rsh;[↱]. - "\x05aquo;\x03›\x05quor;\x03’\x04quo;\x03’\x03cr;\x04𝓇\x03qb;\x01]\x02h;\x03↱", - // rtriltri;[⧎] rthree;[⋌] rtimes;[⋊] rtrie;[⊵] rtrif;[▸] rtri;[▹]. - "\x07riltri;\x03⧎\x05hree;\x03⋌\x05imes;\x03⋊\x04rie;\x03⊵\x04rif;\x03▸\x03ri;\x03▹", - // ruluhar;[⥨]. - "\x06luhar;\x03⥨", - // rx;[℞]. - "\x01;\x03℞", - // sacute;[ś]. - "\x05cute;\x02ś", - // sbquo;[‚]. - "\x04quo;\x03‚", - // scpolint;[⨓] scaron;[š] scedil;[ş] scnsim;[⋩] sccue;[≽] scirc;[ŝ] scnap;[⪺] scsim;[≿] scap;[⪸] scnE;[⪶] scE;[⪴] sce;[⪰] scy;[с] sc;[≻]. - "\x07polint;\x03⨓\x05aron;\x02š\x05edil;\x02ş\x05nsim;\x03⋩\x04cue;\x03≽\x04irc;\x02ŝ\x04nap;\x03⪺\x04sim;\x03≿\x03ap;\x03⪸\x03nE;\x03⪶\x02E;\x03⪴\x02e;\x03⪰\x02y;\x02с\x01;\x03≻", - // sdotb;[⊡] sdote;[⩦] sdot;[⋅]. - "\x04otb;\x03⊡\x04ote;\x03⩦\x03ot;\x03⋅", - // setminus;[∖] searrow;[↘] searhk;[⤥] seswar;[⤩] seArr;[⇘] searr;[↘] setmn;[∖] sect;[§] semi;[;] sext;[✶] sect[§]. - "\x07tminus;\x03∖\x06arrow;\x03↘\x05arhk;\x03⤥\x05swar;\x03⤩\x04Arr;\x03⇘\x04arr;\x03↘\x04tmn;\x03∖\x03ct;\x02§\x03mi;\x01;\x03xt;\x03✶\x02ct\x02§", - // sfrown;[⌢] sfr;[𝔰]. - "\x05rown;\x03⌢\x02r;\x04𝔰", - // shortparallel;[∥] shortmid;[∣] shchcy;[щ] sharp;[♯] shcy;[ш] shy;[­] shy[­]. - "\x0cortparallel;\x03∥\x07ortmid;\x03∣\x05chcy;\x02щ\x04arp;\x03♯\x03cy;\x02ш\x02y;\x02­\x01y\x02­", - // simplus;[⨤] simrarr;[⥲] sigmaf;[ς] sigmav;[ς] simdot;[⩪] sigma;[σ] simeq;[≃] simgE;[⪠] simlE;[⪟] simne;[≆] sime;[≃] simg;[⪞] siml;[⪝] sim;[∼]. - "\x06mplus;\x03⨤\x06mrarr;\x03⥲\x05gmaf;\x02ς\x05gmav;\x02ς\x05mdot;\x03⩪\x04gma;\x02σ\x04meq;\x03≃\x04mgE;\x03⪠\x04mlE;\x03⪟\x04mne;\x03≆\x03me;\x03≃\x03mg;\x03⪞\x03ml;\x03⪝\x02m;\x03∼", - // slarr;[←]. - "\x04arr;\x03←", - // smallsetminus;[∖] smeparsl;[⧤] smashp;[⨳] smile;[⌣] smtes;[⪬︀] smid;[∣] smte;[⪬] smt;[⪪]. - "\x0callsetminus;\x03∖\x07eparsl;\x03⧤\x05ashp;\x03⨳\x04ile;\x03⌣\x04tes;\x06⪬︀\x03id;\x03∣\x03te;\x03⪬\x02t;\x03⪪", - // softcy;[ь] solbar;[⌿] solb;[⧄] sopf;[𝕤] sol;[/]. - "\x05ftcy;\x02ь\x05lbar;\x03⌿\x03lb;\x03⧄\x03pf;\x04𝕤\x02l;\x01/", - // spadesuit;[♠] spades;[♠] spar;[∥]. - "\x08adesuit;\x03♠\x05ades;\x03♠\x03ar;\x03∥", - // sqsubseteq;[⊑] sqsupseteq;[⊒] sqsubset;[⊏] sqsupset;[⊐] sqcaps;[⊓︀] sqcups;[⊔︀] sqsube;[⊑] sqsupe;[⊒] square;[□] squarf;[▪] sqcap;[⊓] sqcup;[⊔] sqsub;[⊏] sqsup;[⊐] squf;[▪] squ;[□]. - "\x09subseteq;\x03⊑\x09supseteq;\x03⊒\x07subset;\x03⊏\x07supset;\x03⊐\x05caps;\x06⊓︀\x05cups;\x06⊔︀\x05sube;\x03⊑\x05supe;\x03⊒\x05uare;\x03□\x05uarf;\x03▪\x04cap;\x03⊓\x04cup;\x03⊔\x04sub;\x03⊏\x04sup;\x03⊐\x03uf;\x03▪\x02u;\x03□", - // srarr;[→]. - "\x04arr;\x03→", - // ssetmn;[∖] ssmile;[⌣] sstarf;[⋆] sscr;[𝓈]. - "\x05etmn;\x03∖\x05mile;\x03⌣\x05tarf;\x03⋆\x03cr;\x04𝓈", - // straightepsilon;[ϵ] straightphi;[ϕ] starf;[★] strns;[¯] star;[☆]. - "\x0eraightepsilon;\x02ϵ\x0araightphi;\x02ϕ\x04arf;\x03★\x04rns;\x02¯\x03ar;\x03☆", - // succcurlyeq;[≽] succnapprox;[⪺] subsetneqq;[⫋] succapprox;[⪸] supsetneqq;[⫌] subseteqq;[⫅] subsetneq;[⊊] supseteqq;[⫆] supsetneq;[⊋] subseteq;[⊆] succneqq;[⪶] succnsim;[⋩] supseteq;[⊇] subedot;[⫃] submult;[⫁] subplus;[⪿] subrarr;[⥹] succsim;[≿] supdsub;[⫘] supedot;[⫄] suphsol;[⟉] suphsub;[⫗] suplarr;[⥻] supmult;[⫂] supplus;[⫀] subdot;[⪽] subset;[⊂] subsim;[⫇] subsub;[⫕] subsup;[⫓] succeq;[⪰] supdot;[⪾] supset;[⊃] supsim;[⫈] supsub;[⫔] supsup;[⫖] subnE;[⫋] subne;[⊊] supnE;[⫌] supne;[⊋] subE;[⫅] sube;[⊆] succ;[≻] sung;[♪] sup1;[¹] sup2;[²] sup3;[³] supE;[⫆] supe;[⊇] sub;[⊂] sum;[∑] sup1[¹] sup2[²] sup3[³] sup;[⊃]. - "\x0acccurlyeq;\x03≽\x0accnapprox;\x03⪺\x09bsetneqq;\x03⫋\x09ccapprox;\x03⪸\x09psetneqq;\x03⫌\x08bseteqq;\x03⫅\x08bsetneq;\x03⊊\x08pseteqq;\x03⫆\x08psetneq;\x03⊋\x07bseteq;\x03⊆\x07ccneqq;\x03⪶\x07ccnsim;\x03⋩\x07pseteq;\x03⊇\x06bedot;\x03⫃\x06bmult;\x03⫁\x06bplus;\x03⪿\x06brarr;\x03⥹\x06ccsim;\x03≿\x06pdsub;\x03⫘\x06pedot;\x03⫄\x06phsol;\x03⟉\x06phsub;\x03⫗\x06plarr;\x03⥻\x06pmult;\x03⫂\x06pplus;\x03⫀\x05bdot;\x03⪽\x05bset;\x03⊂\x05bsim;\x03⫇\x05bsub;\x03⫕\x05bsup;\x03⫓\x05cceq;\x03⪰\x05pdot;\x03⪾\x05pset;\x03⊃\x05psim;\x03⫈\x05psub;\x03⫔\x05psup;\x03⫖\x04bnE;\x03⫋\x04bne;\x03⊊\x04pnE;\x03⫌\x04pne;\x03⊋\x03bE;\x03⫅\x03be;\x03⊆\x03cc;\x03≻\x03ng;\x03♪\x03p1;\x02¹\x03p2;\x02²\x03p3;\x02³\x03pE;\x03⫆\x03pe;\x03⊇\x02b;\x03⊂\x02m;\x03∑\x02p1\x02¹\x02p2\x02²\x02p3\x02³\x02p;\x03⊃", - // swarrow;[↙] swarhk;[⤦] swnwar;[⤪] swArr;[⇙] swarr;[↙]. - "\x06arrow;\x03↙\x05arhk;\x03⤦\x05nwar;\x03⤪\x04Arr;\x03⇙\x04arr;\x03↙", - // szlig;[ß] szlig[ß]. - "\x04lig;\x02ß\x03lig\x02ß", - // target;[⌖] tau;[τ]. - "\x05rget;\x03⌖\x02u;\x02τ", - // tbrk;[⎴]. - "\x03rk;\x03⎴", - // tcaron;[ť] tcedil;[ţ] tcy;[т]. - "\x05aron;\x02ť\x05edil;\x02ţ\x02y;\x02т", - // tdot;[⃛]. - "\x03ot;\x03⃛", - // telrec;[⌕]. - "\x05lrec;\x03⌕", - // tfr;[𝔱]. - "\x02r;\x04𝔱", - // thickapprox;[≈] therefore;[∴] thetasym;[ϑ] thicksim;[∼] there4;[∴] thetav;[ϑ] thinsp;[ ] thksim;[∼] theta;[θ] thkap;[≈] thorn;[þ] thorn[þ]. - "\x0aickapprox;\x03≈\x08erefore;\x03∴\x07etasym;\x02ϑ\x07icksim;\x03∼\x05ere4;\x03∴\x05etav;\x02ϑ\x05insp;\x03 \x05ksim;\x03∼\x04eta;\x02θ\x04kap;\x03≈\x04orn;\x02þ\x03orn\x02þ", - // timesbar;[⨱] timesb;[⊠] timesd;[⨰] tilde;[˜] times;[×] times[×] tint;[∭]. - "\x07mesbar;\x03⨱\x05mesb;\x03⊠\x05mesd;\x03⨰\x04lde;\x02˜\x04mes;\x02×\x03mes\x02×\x03nt;\x03∭", - // topfork;[⫚] topbot;[⌶] topcir;[⫱] toea;[⤨] topf;[𝕥] tosa;[⤩] top;[⊤]. - "\x06pfork;\x03⫚\x05pbot;\x03⌶\x05pcir;\x03⫱\x03ea;\x03⤨\x03pf;\x04𝕥\x03sa;\x03⤩\x02p;\x03⊤", - // tprime;[‴]. - "\x05rime;\x03‴", - // trianglerighteq;[⊵] trianglelefteq;[⊴] triangleright;[▹] triangledown;[▿] triangleleft;[◃] triangleq;[≜] triangle;[▵] triminus;[⨺] trpezium;[⏢] triplus;[⨹] tritime;[⨻] tridot;[◬] trade;[™] trisb;[⧍] trie;[≜]. - "\x0eianglerighteq;\x03⊵\x0dianglelefteq;\x03⊴\x0ciangleright;\x03▹\x0biangledown;\x03▿\x0biangleleft;\x03◃\x08iangleq;\x03≜\x07iangle;\x03▵\x07iminus;\x03⨺\x07pezium;\x03⏢\x06iplus;\x03⨹\x06itime;\x03⨻\x05idot;\x03◬\x04ade;\x03™\x04isb;\x03⧍\x03ie;\x03≜", - // tstrok;[ŧ] tshcy;[ћ] tscr;[𝓉] tscy;[ц]. - "\x05trok;\x02ŧ\x04hcy;\x02ћ\x03cr;\x04𝓉\x03cy;\x02ц", - // twoheadrightarrow;[↠] twoheadleftarrow;[↞] twixt;[≬]. - "\x10oheadrightarrow;\x03↠\x0foheadleftarrow;\x03↞\x04ixt;\x03≬", - // uArr;[⇑]. - "\x03rr;\x03⇑", - // uHar;[⥣]. - "\x03ar;\x03⥣", - // uacute;[ú] uacute[ú] uarr;[↑]. - "\x05cute;\x02ú\x04cute\x02ú\x03rr;\x03↑", - // ubreve;[ŭ] ubrcy;[ў]. - "\x05reve;\x02ŭ\x04rcy;\x02ў", - // ucirc;[û] ucirc[û] ucy;[у]. - "\x04irc;\x02û\x03irc\x02û\x02y;\x02у", - // udblac;[ű] udarr;[⇅] udhar;[⥮]. - "\x05blac;\x02ű\x04arr;\x03⇅\x04har;\x03⥮", - // ufisht;[⥾] ufr;[𝔲]. - "\x05isht;\x03⥾\x02r;\x04𝔲", - // ugrave;[ù] ugrave[ù]. - "\x05rave;\x02ù\x04rave\x02ù", - // uharl;[↿] uharr;[↾] uhblk;[▀]. - "\x04arl;\x03↿\x04arr;\x03↾\x04blk;\x03▀", - // ulcorner;[⌜] ulcorn;[⌜] ulcrop;[⌏] ultri;[◸]. - "\x07corner;\x03⌜\x05corn;\x03⌜\x05crop;\x03⌏\x04tri;\x03◸", - // umacr;[ū] uml;[¨] uml[¨]. - "\x04acr;\x02ū\x02l;\x02¨\x01l\x02¨", - // uogon;[ų] uopf;[𝕦]. - "\x04gon;\x02ų\x03pf;\x04𝕦", - // upharpoonright;[↾] upharpoonleft;[↿] updownarrow;[↕] upuparrows;[⇈] uparrow;[↑] upsilon;[υ] uplus;[⊎] upsih;[ϒ] upsi;[υ]. - "\x0dharpoonright;\x03↾\x0charpoonleft;\x03↿\x0adownarrow;\x03↕\x09uparrows;\x03⇈\x06arrow;\x03↑\x06silon;\x02υ\x04lus;\x03⊎\x04sih;\x02ϒ\x03si;\x02υ", - // urcorner;[⌝] urcorn;[⌝] urcrop;[⌎] uring;[ů] urtri;[◹]. - "\x07corner;\x03⌝\x05corn;\x03⌝\x05crop;\x03⌎\x04ing;\x02ů\x04tri;\x03◹", - // uscr;[𝓊]. - "\x03cr;\x04𝓊", - // utilde;[ũ] utdot;[⋰] utrif;[▴] utri;[▵]. - "\x05ilde;\x02ũ\x04dot;\x03⋰\x04rif;\x03▴\x03ri;\x03▵", - // uuarr;[⇈] uuml;[ü] uuml[ü]. - "\x04arr;\x03⇈\x03ml;\x02ü\x02ml\x02ü", - // uwangle;[⦧]. - "\x06angle;\x03⦧", - // vArr;[⇕]. - "\x03rr;\x03⇕", - // vBarv;[⫩] vBar;[⫨]. - "\x04arv;\x03⫩\x03ar;\x03⫨", - // vDash;[⊨]. - "\x04ash;\x03⊨", - // vartriangleright;[⊳] vartriangleleft;[⊲] varsubsetneqq;[⫋︀] varsupsetneqq;[⫌︀] varsubsetneq;[⊊︀] varsupsetneq;[⊋︀] varepsilon;[ϵ] varnothing;[∅] varpropto;[∝] varkappa;[ϰ] varsigma;[ς] vartheta;[ϑ] vangrt;[⦜] varphi;[ϕ] varrho;[ϱ] varpi;[ϖ] varr;[↕]. - "\x0frtriangleright;\x03⊳\x0ertriangleleft;\x03⊲\x0crsubsetneqq;\x06⫋︀\x0crsupsetneqq;\x06⫌︀\x0brsubsetneq;\x06⊊︀\x0brsupsetneq;\x06⊋︀\x09repsilon;\x02ϵ\x09rnothing;\x03∅\x08rpropto;\x03∝\x07rkappa;\x02ϰ\x07rsigma;\x02ς\x07rtheta;\x02ϑ\x05ngrt;\x03⦜\x05rphi;\x02ϕ\x05rrho;\x02ϱ\x04rpi;\x02ϖ\x03rr;\x03↕", - // vcy;[в]. - "\x02y;\x02в", - // vdash;[⊢]. - "\x04ash;\x03⊢", - // veebar;[⊻] vellip;[⋮] verbar;[|] veeeq;[≚] vert;[|] vee;[∨]. - "\x05ebar;\x03⊻\x05llip;\x03⋮\x05rbar;\x01|\x04eeq;\x03≚\x03rt;\x01|\x02e;\x03∨", - // vfr;[𝔳]. - "\x02r;\x04𝔳", - // vltri;[⊲]. - "\x04tri;\x03⊲", - // vnsub;[⊂⃒] vnsup;[⊃⃒]. - "\x04sub;\x06⊂⃒\x04sup;\x06⊃⃒", - // vopf;[𝕧]. - "\x03pf;\x04𝕧", - // vprop;[∝]. - "\x04rop;\x03∝", - // vrtri;[⊳]. - "\x04tri;\x03⊳", - // vsubnE;[⫋︀] vsubne;[⊊︀] vsupnE;[⫌︀] vsupne;[⊋︀] vscr;[𝓋]. - "\x05ubnE;\x06⫋︀\x05ubne;\x06⊊︀\x05upnE;\x06⫌︀\x05upne;\x06⊋︀\x03cr;\x04𝓋", - // vzigzag;[⦚]. - "\x06igzag;\x03⦚", - // wcirc;[ŵ]. - "\x04irc;\x02ŵ", - // wedbar;[⩟] wedgeq;[≙] weierp;[℘] wedge;[∧]. - "\x05dbar;\x03⩟\x05dgeq;\x03≙\x05ierp;\x03℘\x04dge;\x03∧", - // wfr;[𝔴]. - "\x02r;\x04𝔴", - // wopf;[𝕨]. - "\x03pf;\x04𝕨", - // wp;[℘]. - "\x01;\x03℘", - // wreath;[≀] wr;[≀]. - "\x05eath;\x03≀\x01;\x03≀", - // wscr;[𝓌]. - "\x03cr;\x04𝓌", - // xcirc;[◯] xcap;[⋂] xcup;[⋃]. - "\x04irc;\x03◯\x03ap;\x03⋂\x03up;\x03⋃", - // xdtri;[▽]. - "\x04tri;\x03▽", - // xfr;[𝔵]. - "\x02r;\x04𝔵", - // xhArr;[⟺] xharr;[⟷]. - "\x04Arr;\x03⟺\x04arr;\x03⟷", - // xi;[ξ]. - "\x01;\x02ξ", - // xlArr;[⟸] xlarr;[⟵]. - "\x04Arr;\x03⟸\x04arr;\x03⟵", - // xmap;[⟼]. - "\x03ap;\x03⟼", - // xnis;[⋻]. - "\x03is;\x03⋻", - // xoplus;[⨁] xotime;[⨂] xodot;[⨀] xopf;[𝕩]. - "\x05plus;\x03⨁\x05time;\x03⨂\x04dot;\x03⨀\x03pf;\x04𝕩", - // xrArr;[⟹] xrarr;[⟶]. - "\x04Arr;\x03⟹\x04arr;\x03⟶", - // xsqcup;[⨆] xscr;[𝓍]. - "\x05qcup;\x03⨆\x03cr;\x04𝓍", - // xuplus;[⨄] xutri;[△]. - "\x05plus;\x03⨄\x04tri;\x03△", - // xvee;[⋁]. - "\x03ee;\x03⋁", - // xwedge;[⋀]. - "\x05edge;\x03⋀", - // yacute;[ý] yacute[ý] yacy;[я]. - "\x05cute;\x02ý\x04cute\x02ý\x03cy;\x02я", - // ycirc;[ŷ] ycy;[ы]. - "\x04irc;\x02ŷ\x02y;\x02ы", - // yen;[¥] yen[¥]. - "\x02n;\x02¥\x01n\x02¥", - // yfr;[𝔶]. - "\x02r;\x04𝔶", - // yicy;[ї]. - "\x03cy;\x02ї", - // yopf;[𝕪]. - "\x03pf;\x04𝕪", - // yscr;[𝓎]. - "\x03cr;\x04𝓎", - // yucy;[ю] yuml;[ÿ] yuml[ÿ]. - "\x03cy;\x02ю\x03ml;\x02ÿ\x02ml\x02ÿ", - // zacute;[ź]. - "\x05cute;\x02ź", - // zcaron;[ž] zcy;[з]. - "\x05aron;\x02ž\x02y;\x02з", - // zdot;[ż]. - "\x03ot;\x02ż", - // zeetrf;[ℨ] zeta;[ζ]. - "\x05etrf;\x03ℨ\x03ta;\x02ζ", - // zfr;[𝔷]. - "\x02r;\x04𝔷", - // zhcy;[ж]. - "\x03cy;\x02ж", - // zigrarr;[⇝]. - "\x06grarr;\x03⇝", - // zopf;[𝕫]. - "\x03pf;\x04𝕫", - // zscr;[𝓏]. - "\x03cr;\x04𝓏", - // zwnj;[‌] zwj;[‍]. - "\x03nj;\x03‌\x02j;\x03‍", - ), - "small_words" => "GT\x00LT\x00gt\x00lt\x00", - "small_mappings" => array( - ">", - "<", - ">", - "<", - ) - ) - ); -} diff --git a/lib/compat/wordpress-6.6/option.php b/lib/compat/wordpress-6.6/option.php deleted file mode 100644 index 9ec81467c261da..00000000000000 --- a/lib/compat/wordpress-6.6/option.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php -/** - * Options API changes for the Gutenberg plugin. - * - * @package gutenberg - */ - -/** - * Updates arguments for default settings available in WordPress. - * - * Note: During the core sync, the updates will be made to `register_initial_settings`. -*/ -function gutenberg_update_initial_settings( $args, $defaults, $option_group, $option_name ) { - $settings_label_map = array( - 'blogname' => __( 'Title' ), - 'blogdescription' => __( 'Tagline' ), - 'show_on_front' => __( 'Show on front' ), - 'page_on_front' => __( 'Page on front' ), - 'posts_per_page' => __( 'Maximum posts per page' ), - 'default_comment_status' => __( 'Allow comments on new posts' ), - ); - - if ( isset( $settings_label_map[ $option_name ] ) ) { - $args['label'] = $settings_label_map[ $option_name ]; - } - - // Don't update schema when a setting isn't exposed via REST API. - if ( ! isset( $args['show_in_rest'] ) ) { - return $args; - } - - // Don't update schema when label isn't provided. - if ( ! isset( $args['label'] ) ) { - return $args; - } - - $schema = array( 'title' => $args['label'] ); - if ( ! is_array( $args['show_in_rest'] ) ) { - $args['show_in_rest'] = array( - 'schema' => $schema, - ); - return $args; - } - - if ( ! empty( $args['show_in_rest']['schema'] ) ) { - $args['show_in_rest']['schema'] = array_merge( $args['show_in_rest']['schema'], $schema ); - } else { - $args['show_in_rest']['schema'] = $schema; - } - - return $args; -} -add_filter( 'register_setting_args', 'gutenberg_update_initial_settings', 10, 4 ); diff --git a/lib/compat/wordpress-6.6/post.php b/lib/compat/wordpress-6.6/post.php deleted file mode 100644 index 8415f3bf42f18f..00000000000000 --- a/lib/compat/wordpress-6.6/post.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php -/** - * Temporary compatibility shims for block APIs present in Gutenberg. - * - * @package gutenberg - */ - -/** - * Adds support for excerpt to the wp_block post type. - */ -function gutenberg_add_excerpt_support_to_wp_block() { - add_post_type_support( 'wp_block', 'excerpt' ); -} - -add_action( 'init', 'gutenberg_add_excerpt_support_to_wp_block' ); - -/** - * Updates the labels for the template post type. - * - * @param object $labels Object with labels for the post type as member variables. - * @return object Object with all the labels as member variables. - */ -function gutenberg_update_wp_template_labels( $labels ) { - $labels->item_updated = __( 'Template updated.', 'gutenberg' ); - return $labels; -} -add_filter( 'post_type_labels_wp_template', 'gutenberg_update_wp_template_labels', 10, 1 ); - -/** - * Updates the labels for the template parts post type. - * - * @param object $labels Object with labels for the post type as member variables. - * @return object Object with all the labels as member variables. - */ -function gutenberg_update_wp_template__part_labels( $labels ) { - $labels->item_updated = __( 'Template part updated.', 'gutenberg' ); - return $labels; -} -add_filter( 'post_type_labels_wp_template_part', 'gutenberg_update_wp_template__part_labels', 10, 1 ); diff --git a/lib/compat/wordpress-6.6/resolve-patterns.php b/lib/compat/wordpress-6.6/resolve-patterns.php deleted file mode 100644 index 5105619c42613c..00000000000000 --- a/lib/compat/wordpress-6.6/resolve-patterns.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -/** - * Replaces pattern blocks with their content. - * - * @param array $blocks Array of blocks. - * @param array $inner_content Optional array of inner content. - * @return array Array of blocks with patterns replaced. - */ -function gutenberg_replace_pattern_blocks( $blocks, &$inner_content = null ) { - // Keep track of seen references to avoid infinite loops. - static $seen_refs = array(); - $i = 0; - while ( $i < count( $blocks ) ) { - if ( 'core/pattern' === $blocks[ $i ]['blockName'] ) { - $slug = $blocks[ $i ]['attrs']['slug']; - - if ( isset( $seen_refs[ $slug ] ) ) { - // Skip recursive patterns. - array_splice( $blocks, $i, 1 ); - continue; - } - - $registry = WP_Block_Patterns_Registry::get_instance(); - $pattern = $registry->get_registered( $slug ); - - // Skip unknown patterns. - if ( ! $pattern ) { - ++$i; - continue; - } - - $blocks_to_insert = parse_blocks( $pattern['content'] ); - $seen_refs[ $slug ] = true; - $blocks_to_insert = gutenberg_replace_pattern_blocks( $blocks_to_insert ); - unset( $seen_refs[ $slug ] ); - array_splice( $blocks, $i, 1, $blocks_to_insert ); - - // If we have inner content, we need to insert nulls in the - // inner content array, otherwise serialize_blocks will skip - // blocks. - if ( $inner_content ) { - $null_indices = array_keys( $inner_content, null, true ); - $content_index = $null_indices[ $i ]; - $nulls = array_fill( 0, count( $blocks_to_insert ), null ); - array_splice( $inner_content, $content_index, 1, $nulls ); - } - - // Skip inserted blocks. - $i += count( $blocks_to_insert ); - } else { - if ( ! empty( $blocks[ $i ]['innerBlocks'] ) ) { - $blocks[ $i ]['innerBlocks'] = gutenberg_replace_pattern_blocks( - $blocks[ $i ]['innerBlocks'], - $blocks[ $i ]['innerContent'] - ); - } - ++$i; - } - } - return $blocks; -} - -function gutenberg_replace_pattern_blocks_patterns_endpoint( $result, $server, $request ) { - if ( $request->get_route() !== '/wp/v2/block-patterns/patterns' ) { - return $result; - } - - $data = $result->get_data(); - - foreach ( $data as $index => $pattern ) { - $blocks = parse_blocks( $pattern['content'] ); - $blocks = gutenberg_replace_pattern_blocks( $blocks ); - $data[ $index ]['content'] = serialize_blocks( $blocks ); - } - - $result->set_data( $data ); - - return $result; -} - -// Similarly, for patterns, we can avoid the double parse here: -// https://github.com/WordPress/wordpress-develop/blob/02fb53498f1ce7e63d807b9bafc47a7dba19d169/src/wp-includes/class-wp-block-patterns-registry.php#L175 -add_filter( 'rest_post_dispatch', 'gutenberg_replace_pattern_blocks_patterns_endpoint', 10, 3 ); diff --git a/lib/compat/wordpress-6.6/rest-api.php b/lib/compat/wordpress-6.6/rest-api.php deleted file mode 100644 index eadd3b1d376a72..00000000000000 --- a/lib/compat/wordpress-6.6/rest-api.php +++ /dev/null @@ -1,216 +0,0 @@ -<?php -/** - * PHP and WordPress configuration compatibility functions for the Gutenberg - * editor plugin changes related to REST API. - * - * @package gutenberg - */ - -if ( ! defined( 'ABSPATH' ) ) { - die( 'Silence is golden.' ); -} - -if ( ! function_exists( 'wp_api_template_access_controller' ) ) { - /** - * Hook in to the template and template part post types and modify the - * access control for the rest endpoint to allow lower user roles to access - * the templates and template parts. - * - * @param array $args Current registered post type args. - * @param string $post_type Name of post type. - * - * @return array - */ - function wp_api_template_access_controller( $args, $post_type ) { - if ( 'wp_template' === $post_type || 'wp_template_part' === $post_type ) { - $args['rest_controller_class'] = 'Gutenberg_REST_Templates_Controller_6_6'; - } - return $args; - } -} -add_filter( 'register_post_type_args', 'wp_api_template_access_controller', 10, 2 ); - -/** - * Adds the post classes to the REST API response. - * - * @param array $post The response object data. - * - * @return array - */ -function gutenberg_add_class_list_to_api_response( $post ) { - - if ( ! isset( $post['id'] ) ) { - return array(); - } - - return get_post_class( array(), $post['id'] ); -} - -/** - * Adds the post classes to public post types in the REST API. - */ -function gutenberg_add_class_list_to_public_post_types() { - $post_types = get_post_types( - array( - 'public' => true, - 'show_in_rest' => true, - ), - 'names' - ); - - if ( ! empty( $post_types ) ) { - register_rest_field( - $post_types, - 'class_list', - array( - 'get_callback' => 'gutenberg_add_class_list_to_api_response', - 'schema' => array( - 'description' => __( 'An array of the class names for the post container element.', 'gutenberg' ), - 'type' => 'array', - 'items' => array( - 'type' => 'string', - ), - ), - ) - ); - } -} -add_action( 'rest_api_init', 'gutenberg_add_class_list_to_public_post_types' ); - - -/** - * Registers the Global Styles Revisions REST API routes. - */ -function gutenberg_register_global_styles_revisions_endpoints() { - $global_styles_revisions_controller = new Gutenberg_REST_Global_Styles_Revisions_Controller_6_6(); - $global_styles_revisions_controller->register_routes(); -} - -add_action( 'rest_api_init', 'gutenberg_register_global_styles_revisions_endpoints' ); - -/** - * Adds `stylesheet_uri` fields to WP_REST_Themes_Controller class. - */ -function gutenberg_register_wp_rest_themes_stylesheet_directory_uri_field() { - register_rest_field( - 'theme', - 'stylesheet_uri', - array( - 'get_callback' => function ( $item ) { - if ( ! empty( $item['stylesheet'] ) ) { - $theme = wp_get_theme( $item['stylesheet'] ); - $current_theme = wp_get_theme(); - if ( $theme->get_stylesheet() === $current_theme->get_stylesheet() ) { - return get_stylesheet_directory_uri(); - } else { - return $theme->get_stylesheet_directory_uri(); - } - } - - return null; - }, - 'schema' => array( - 'type' => 'string', - 'description' => __( 'The uri for the theme\'s stylesheet directory.', 'gutenberg' ), - 'format' => 'uri', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - ) - ); -} -add_action( 'rest_api_init', 'gutenberg_register_wp_rest_themes_stylesheet_directory_uri_field' ); - -/** - * Adds `template_uri` fields to WP_REST_Themes_Controller class. - */ -function gutenberg_register_wp_rest_themes_template_directory_uri_field() { - register_rest_field( - 'theme', - 'template_uri', - array( - 'get_callback' => function ( $item ) { - if ( ! empty( $item['stylesheet'] ) ) { - $theme = wp_get_theme( $item['stylesheet'] ); - $current_theme = wp_get_theme(); - if ( $theme->get_stylesheet() === $current_theme->get_stylesheet() ) { - return get_template_directory_uri(); - } else { - return $theme->get_template_directory_uri(); - } - } - - return null; - }, - 'schema' => array( - 'type' => 'string', - 'description' => __( 'The uri for the theme\'s template directory. If this is a child theme, this refers to the parent theme, otherwise this is the same as the theme\'s stylesheet directory.', 'gutenberg' ), - 'format' => 'uri', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - ) - ); -} -add_action( 'rest_api_init', 'gutenberg_register_wp_rest_themes_template_directory_uri_field' ); - -/** - * Adds `template` and `template_lock` fields to WP_REST_Post_Types_Controller class. - */ -function gutenberg_register_wp_rest_post_types_controller_fields() { - register_rest_field( - 'type', - 'template', - array( - 'get_callback' => function ( $item ) { - $post_type = get_post_type_object( $item['slug'] ); - if ( ! empty( $post_type ) ) { - return $post_type->template ?? array(); - } - }, - 'schema' => array( - 'type' => 'array', - 'description' => __( 'The block template associated with the post type.', 'gutenberg' ), - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - ) - ); - register_rest_field( - 'type', - 'template_lock', - array( - 'get_callback' => function ( $item ) { - $post_type = get_post_type_object( $item['slug'] ); - if ( ! empty( $post_type ) ) { - return ! empty( $post_type->template_lock ) ? $post_type->template_lock : false; - } - }, - 'schema' => array( - 'type' => array( 'string', 'boolean' ), - 'enum' => array( 'all', 'insert', 'contentOnly', false ), - 'description' => __( 'The template_lock associated with the post type, or false if none.', 'gutenberg' ), - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - ) - ); -} -add_action( 'rest_api_init', 'gutenberg_register_wp_rest_post_types_controller_fields' ); - -/** - * Preload theme and global styles paths to avoid flash of variation styles in post editor. - * - * @param array $paths REST API paths to preload. - * @param WP_Block_Editor_Context $context Current block editor context. - * @return array Filtered preload paths. - */ -function gutenberg_block_editor_preload_paths_6_6( $paths, $context ) { - if ( 'core/edit-post' === $context->name ) { - $paths[] = '/wp/v2/global-styles/themes/' . get_stylesheet(); - $paths[] = '/wp/v2/themes?context=edit&status=active'; - $paths[] = '/wp/v2/global-styles/' . WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id() . '?context=edit'; - } - return $paths; -} -add_filter( 'block_editor_rest_api_preload_paths', 'gutenberg_block_editor_preload_paths_6_6', 10, 2 ); diff --git a/lib/compat/wordpress-6.7/class-gutenberg-rest-templates-controller-6-7.php b/lib/compat/wordpress-6.7/class-gutenberg-rest-templates-controller-6-7.php index ed67dded75ecb1..e5f6eb126f2a6a 100644 --- a/lib/compat/wordpress-6.7/class-gutenberg-rest-templates-controller-6-7.php +++ b/lib/compat/wordpress-6.7/class-gutenberg-rest-templates-controller-6-7.php @@ -9,7 +9,7 @@ * Gutenberg_REST_Templates_Controller_6_7 class * */ -class Gutenberg_REST_Templates_Controller_6_7 extends Gutenberg_REST_Templates_Controller_6_6 { +class Gutenberg_REST_Templates_Controller_6_7 extends WP_REST_Templates_Controller { /** * Returns the given template * diff --git a/lib/compat/wordpress-6.7/compat.php b/lib/compat/wordpress-6.7/compat.php index e58eca56ef71f9..33c123a14860d2 100644 --- a/lib/compat/wordpress-6.7/compat.php +++ b/lib/compat/wordpress-6.7/compat.php @@ -46,7 +46,7 @@ function _gutenberg_add_block_templates_from_registry( $query_result, $query, $t // See: https://github.com/WordPress/gutenberg/issues/65584 $template_files_query = $query; unset( $template_files_query['post_type'] ); - $template_files = _gutenberg_get_block_templates_files( $template_type, $template_files_query ); + $template_files = _get_block_templates_files( $template_type, $template_files_query ); /* * Add templates registered in the template registry. Filtering out the ones which have a theme file. diff --git a/lib/load.php b/lib/load.php index 100160176f3911..85d1c7e3292b50 100644 --- a/lib/load.php +++ b/lib/load.php @@ -35,11 +35,6 @@ function gutenberg_is_experiment_enabled( $name ) { require_once __DIR__ . '/experimental/class-wp-rest-block-editor-settings-controller.php'; } - // WordPress 6.6 compat. - require __DIR__ . '/compat/wordpress-6.6/class-gutenberg-rest-global-styles-revisions-controller-6-6.php'; - require __DIR__ . '/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php'; - require __DIR__ . '/compat/wordpress-6.6/rest-api.php'; - // WordPress 6.7 compat. require __DIR__ . '/compat/wordpress-6.7/class-gutenberg-rest-posts-controller-6-7.php'; require __DIR__ . '/compat/wordpress-6.7/class-gutenberg-rest-templates-controller-6-7.php'; @@ -72,18 +67,9 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/plugin/edit-site-routes-backwards-compat.php'; require __DIR__ . '/compat/plugin/fonts.php'; -// The Token Map was created during 6.6 in order to support the HTML API. It must be loaded before it. -require __DIR__ . '/compat/wordpress-6.6/class-gutenberg-token-map-6-6.php'; +// The Token Map was created to support the HTML API. It must be loaded before it. require __DIR__ . '/compat/wordpress-6.7/class-gutenberg-token-map-6-7.php'; -require __DIR__ . '/compat/wordpress-6.6/html-api/gutenberg-html5-named-character-references-6-6.php'; -require __DIR__ . '/compat/wordpress-6.6/html-api/class-gutenberg-html-decoder-6-6.php'; -require __DIR__ . '/compat/wordpress-6.6/html-api/class-gutenberg-html-tag-processor-6-6.php'; -require __DIR__ . '/compat/wordpress-6.6/html-api/class-gutenberg-html-open-elements-6-6.php'; -require __DIR__ . '/compat/wordpress-6.6/html-api/class-gutenberg-html-stack-event-6-6.php'; -require __DIR__ . '/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-state-6-6.php'; -require __DIR__ . '/compat/wordpress-6.6/html-api/class-gutenberg-html-processor-6-6.php'; - // Type annotations were added in 6.7 so every file is updated. require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-active-formatting-elements-6-7.php'; require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-attribute-token-6-7.php'; @@ -98,17 +84,6 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-processor-state-6-7.php'; require __DIR__ . '/compat/wordpress-6.7/html-api/class-gutenberg-html-processor-6-7.php'; -// WordPress 6.6 compat. -require __DIR__ . '/compat/wordpress-6.6/admin-bar.php'; -require __DIR__ . '/compat/wordpress-6.6/blocks.php'; -require __DIR__ . '/compat/wordpress-6.6/block-editor.php'; -require __DIR__ . '/compat/wordpress-6.6/compat.php'; -require __DIR__ . '/compat/wordpress-6.6/resolve-patterns.php'; -require __DIR__ . '/compat/wordpress-6.6/block-bindings/pattern-overrides.php'; -require __DIR__ . '/compat/wordpress-6.6/block-template-utils.php'; -require __DIR__ . '/compat/wordpress-6.6/option.php'; -require __DIR__ . '/compat/wordpress-6.6/post.php'; - // WordPress 6.7 compat. require __DIR__ . '/compat/wordpress-6.7/block-templates.php'; require __DIR__ . '/compat/wordpress-6.7/blocks.php'; diff --git a/lib/rest-api.php b/lib/rest-api.php index 7570bb19737233..424927acf1f4a0 100644 --- a/lib/rest-api.php +++ b/lib/rest-api.php @@ -19,11 +19,10 @@ * @return array Array of arguments for registering a post type. */ function gutenberg_override_global_styles_endpoint( array $args ): array { - $args['rest_controller_class'] = 'WP_REST_Global_Styles_Controller_Gutenberg'; - $args['revisions_rest_controller_class'] = 'Gutenberg_REST_Global_Styles_Revisions_Controller_6_6'; - $args['late_route_registration'] = true; - $args['show_in_rest'] = true; - $args['rest_base'] = 'global-styles'; + $args['rest_controller_class'] = 'WP_REST_Global_Styles_Controller_Gutenberg'; + $args['late_route_registration'] = true; + $args['show_in_rest'] = true; + $args['rest_base'] = 'global-styles'; return $args; } diff --git a/phpunit/blocks/get-block-templates-test.php b/phpunit/blocks/get-block-templates-test.php deleted file mode 100644 index 7c8045a1f25f74..00000000000000 --- a/phpunit/blocks/get-block-templates-test.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php -/** - * @group blocks - * @group block-templates - * - * @covers ::get_block_templates - */ -class Tests_Blocks_GetBlockTemplates extends WP_UnitTestCase { - - const TEST_THEME = 'block-theme'; - - /** - * Theme root directory. - * - * @var string - */ - private $theme_root; - - /** - * Original theme directory. - * - * @var string - */ - private $orig_theme_dir; - - public function set_up() { - parent::set_up(); - $this->theme_root = realpath( __DIR__ . '/../data/themedir1' ); - $this->orig_theme_dir = $GLOBALS['wp_theme_directories']; - - // /themes is necessary as theme.php functions assume /themes is the root if there is only one root. - $GLOBALS['wp_theme_directories'] = array( WP_CONTENT_DIR . '/themes', $this->theme_root ); - - add_filter( 'theme_root', array( $this, 'filter_set_theme_root' ) ); - add_filter( 'stylesheet_root', array( $this, 'filter_set_theme_root' ) ); - add_filter( 'template_root', array( $this, 'filter_set_theme_root' ) ); - // Clear caches. - wp_clean_themes_cache(); - unset( $GLOBALS['wp_themes'] ); - switch_theme( self::TEST_THEME ); - } - - public function tear_down() { - $GLOBALS['wp_theme_directories'] = $this->orig_theme_dir; - wp_clean_themes_cache(); - unset( $GLOBALS['wp_themes'] ); - parent::tear_down(); - } - - public function filter_set_theme_root() { - return $this->theme_root; - } - - /** - * Gets the template IDs from the given array. - * - * @param object[] $templates Array of template objects to parse. - * @return string[] The template IDs. - */ - private function get_template_ids( $templates ) { - return array_map( - static function ( $template ) { - return $template->id; - }, - $templates - ); - } - - /** - * @dataProvider data_get_block_templates_should_respect_posttypes_property - * @ticket 55881 - * - * @param string $post_type Post type for query. - * @param array $expected Expected template IDs. - */ - public function test_get_block_templates_should_respect_posttypes_property( $post_type, $expected ) { - $templates = gutenberg_get_block_templates( array( 'post_type' => $post_type ) ); - - $this->assertSameSets( - $expected, - $this->get_template_ids( $templates ) - ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_get_block_templates_should_respect_posttypes_property() { - // @code-merge: This code will go into Core's tests/phpunit/tests/blocks/getBlockTemplates.php. - return array( - 'post' => array( - 'post_type' => 'post', - 'expected' => array( - 'block-theme//custom-hero-template', - 'block-theme//custom-single-post-template', - ), - ), - 'page' => array( - 'post_type' => 'page', - 'expected' => array( - 'block-theme//custom-hero-template', - 'block-theme//page-home', - ), - ), - ); - } -} diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index c8ca89c7c1f6c7..e47a36f73f4188 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -3205,7 +3205,7 @@ public function test_get_editor_settings_blank() { public function test_get_editor_settings_custom_units_can_be_disabled() { add_theme_support( 'custom-units', array() ); - $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( gutenberg_get_classic_theme_supports_block_editor_settings() ); + $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_classic_theme_supports_block_editor_settings() ); remove_theme_support( 'custom-units' ); $expected = array( @@ -3218,7 +3218,7 @@ public function test_get_editor_settings_custom_units_can_be_disabled() { public function test_get_editor_settings_custom_units_can_be_enabled() { add_theme_support( 'custom-units' ); - $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( gutenberg_get_classic_theme_supports_block_editor_settings() ); + $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_classic_theme_supports_block_editor_settings() ); remove_theme_support( 'custom-units' ); $expected = array( @@ -3231,7 +3231,7 @@ public function test_get_editor_settings_custom_units_can_be_enabled() { public function test_get_editor_settings_custom_units_can_be_filtered() { add_theme_support( 'custom-units', 'rem', 'em' ); - $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( gutenberg_get_classic_theme_supports_block_editor_settings() ); + $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_classic_theme_supports_block_editor_settings() ); remove_theme_support( 'custom-units' ); $expected = array( diff --git a/readme.txt b/readme.txt index 4bd7ddc36d6e9b..066de4a678a552 100644 --- a/readme.txt +++ b/readme.txt @@ -1,6 +1,6 @@ === Gutenberg === Contributors: matveb, joen, karmatosed -Tested up to: 6.6 +Tested up to: 6.7 Stable tag: V.V.V License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html From b5528727a447619ca0ee6b9ddf3e26b29cdac092 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 20 Nov 2024 16:02:56 +0400 Subject: [PATCH 1647/1908] Home Link: Remove label attribute synchronization (#67151) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/block-library/src/home-link/edit.js | 72 +++++++------------ .../block-library/src/home-link/index.php | 3 - 2 files changed, 27 insertions(+), 48 deletions(-) diff --git a/packages/block-library/src/home-link/edit.js b/packages/block-library/src/home-link/edit.js index fa6b27a3e2128b..793e13515411db 100644 --- a/packages/block-library/src/home-link/edit.js +++ b/packages/block-library/src/home-link/edit.js @@ -6,15 +6,10 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { - RichText, - useBlockProps, - store as blockEditorStore, -} from '@wordpress/block-editor'; +import { RichText, useBlockProps } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; -import { useSelect, useDispatch } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -import { useEffect } from '@wordpress/element'; const preventDefault = ( event ) => event.preventDefault(); @@ -24,8 +19,6 @@ export default function HomeEdit( { attributes, setAttributes, context } ) { return select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) ?.home; }, [] ); - const { __unstableMarkNextChangeAsNotPersistent } = - useDispatch( blockEditorStore ); const { textColor, backgroundColor, style } = context; const blockProps = useBlockProps( { @@ -41,42 +34,31 @@ export default function HomeEdit( { attributes, setAttributes, context } ) { }, } ); - const { label } = attributes; - - useEffect( () => { - if ( label === undefined ) { - __unstableMarkNextChangeAsNotPersistent(); - setAttributes( { label: __( 'Home' ) } ); - } - }, [ label ] ); - return ( - <> - <div { ...blockProps }> - <a - className="wp-block-home-link__content wp-block-navigation-item__content" - href={ homeUrl } - onClick={ preventDefault } - > - <RichText - identifier="label" - className="wp-block-home-link__label" - value={ label } - onChange={ ( labelValue ) => { - setAttributes( { label: labelValue } ); - } } - aria-label={ __( 'Home link text' ) } - placeholder={ __( 'Add home link' ) } - withoutInteractiveFormatting - allowedFormats={ [ - 'core/bold', - 'core/italic', - 'core/image', - 'core/strikethrough', - ] } - /> - </a> - </div> - </> + <div { ...blockProps }> + <a + className="wp-block-home-link__content wp-block-navigation-item__content" + href={ homeUrl } + onClick={ preventDefault } + > + <RichText + identifier="label" + className="wp-block-home-link__label" + value={ attributes.label ?? __( 'Home' ) } + onChange={ ( labelValue ) => { + setAttributes( { label: labelValue } ); + } } + aria-label={ __( 'Home link text' ) } + placeholder={ __( 'Add home link' ) } + withoutInteractiveFormatting + allowedFormats={ [ + 'core/bold', + 'core/italic', + 'core/image', + 'core/strikethrough', + ] } + /> + </a> + </div> ); } diff --git a/packages/block-library/src/home-link/index.php b/packages/block-library/src/home-link/index.php index fb7235834459d0..d61aa0bc235e22 100644 --- a/packages/block-library/src/home-link/index.php +++ b/packages/block-library/src/home-link/index.php @@ -137,9 +137,6 @@ function block_core_home_link_build_li_wrapper_attributes( $context ) { */ function render_block_core_home_link( $attributes, $content, $block ) { if ( empty( $attributes['label'] ) ) { - // Using a fallback for the label attribute allows rendering the block even if no attributes have been set, - // e.g. when using the block as a hooked block. - // Note that the fallback value needs to be kept in sync with the one set in `edit.js` (upon first loading the block in the editor). $attributes['label'] = __( 'Home' ); } $aria_current = ''; From 2eeb1278411dab7030646f7e9d36293b86a2e015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:52:44 +0100 Subject: [PATCH 1648/1908] DataViews: reorganize docs for actions (#67159) --- packages/dataviews/README.md | 223 ++++++++++++++++++++++++++++++++--- 1 file changed, 206 insertions(+), 17 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 621e3c7ba71ce2..92426bf1e1f838 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -293,23 +293,54 @@ function MyCustomPageTable() { #### `actions`: `Object[]` -Collection of operations that can be performed upon each record. - -Each action is an object with the following properties: - -- `id`: string, required. Unique identifier of the action. For example, `move-to-trash`. -- `label`: string|function, required. User facing description of the action. For example, `Move to Trash`. It can also take a function that takes the selected items as a parameter and returns a string: this can be useful to provide a dynamic label based on the selection. -- `isPrimary`: boolean, optional. Whether the action should be listed inline (primary) or in hidden in the more actions menu (secondary). -- `icon`: SVG element. Icon to show for primary actions. It's required for a primary action, otherwise the action would be considered secondary. -- `isEligible`: function, optional. Whether the action can be performed for a given record. If not present, the action is considered to be eligible for all items. It takes the given record as input. -- `isDestructive`: boolean, optional. Whether the action can delete data, in which case the UI would communicate it via red color. -- `supportsBulk`: Whether the action can be used as a bulk action. False by default. -- `disabled`: Whether the action is disabled. False by default. -- `context`: where this action would be visible. One of `list`, `single`. -- `callback`: function, required unless `RenderModal` is provided. Callback function that takes as input the list of items to operate with, and performs the required action. -- `RenderModal`: ReactElement, optional. If an action requires that some UI be rendered in a modal, it can provide a component which takes as input the the list of `items` to operate with, `closeModal` function, and `onActionPerformed` function. When this prop is provided, the `callback` property is ignored. -- `hideModalHeader`: boolean, optional. This property is used in combination with `RenderModal` and controls the visibility of the modal's header. If the action renders a modal and doesn't hide the header, the action's label is going to be used in the modal's header. -- `modalHeader`: string, optional. The header of the modal. +A list of actions that can be performed on the dataset. See "Actions API" for more details. + +Example: + +```js +const actions = [ + { + id: 'view', + label: 'View', + isPrimary: true, + icon: <Icon icon={ view } />, + isEligible: ( item ) => item.status === 'published' + callback: ( items ) => { + console.log( 'Viewing item:', items[0] ); + }, + }, + { + id: 'edit', + label: 'Edit', + icon: <Icon icon={ edit } />, + supportsBulk: true, + callback: ( items ) => { + console.log( 'Editing items:', items ); + } + }, + { + id: 'delete', + label: 'Delete', + isDestructive: true, + supportsBulk: true, + RenderModal: ( { items, closeModal, onActionPerformed } ) => ( + <div> + <p>Are you sure you want to delete { items.length } item(s)?</p> + <Button + variant="primary" + onClick={() => { + console.log( 'Deleting items:', items ); + onActionPerformed(); + closeModal(); + }} + > + Confirm Delete + </Button> + </div> + ) + } +]; +``` #### `paginationInfo`: `Object` @@ -502,6 +533,164 @@ Parameters: Returns a boolean indicating if the item is valid (true) or not (false). +## Actions API + +### `id` + +The unique identifier of the action. + +- Type: `string` +- Required +- Example: `move-to-trash` + +### `label` + +The user facing description of the action. + +- Type: `string | function` +- Required +- Example: + +```js +{ + label: Move to Trash +} +``` + +or + +```js +{ + label: ( items ) => items.length > 1 ? 'Delete items' : 'Delete item' +} +``` + +### `isPrimary` + +Whether the action should be displayed inline (primary) or only displayed in the "More actions" menu (secondary). + +- Type: `boolean` +- Optional + +### `icon` + +Icon to show for primary actions. + +- Type: SVG element +- Required for primary actions, optional for secondary actions. + +### `isEligible` + +Function that determines whether the action can be performed for a given record. + +- Type: `function` +- Optional. If not present, action is considered eligible for all items. +- Example: + +```js +{ + isEligible: ( item ) => item.status === 'published' +} +``` + +### `isDestructive` + +Whether the action can delete data, in which case the UI communicates it via a red color. + +- Type: `boolean` +- Optional + +### `supportsBulk` + +Whether the action can operate over multiple items at once. + +- Type: `boolean` +- Optional +- Default: `false` + +### `disabled` + +Whether the action is disabled. + +- Type: `boolean` +- Optional +- Default: `false` + +### `context` + +Where this action would be visible. + +- Type: `string` +- Optional +- One of: `list`, `single` + +### `callback` + +Function that performs the required action. + +- Type: `function` +- Either `callback` or `RenderModal` must be provided. If `RenderModal` is provided, `callback` will be ignored +- Example: + +```js +{ + callback: ( items, { onActionPerformed } ) => { + // Perform action. + onActionPerformed?.( items ); + } +} +``` + +### `RenderModal` + +Component to render UI in a modal for the action. + +- Type: `ReactElement` +- Either `callback` or `RenderModal` must be provided. If `RenderModal` is provided, `callback` will be ignored. +- Example: + +```jsx +{ + RenderModal: ( { items, closeModal, onActionPerformed } ) => { + const onSubmit = ( event ) => { + event.preventDefault(); + // Perform action. + closeModal?.(); + onActionPerformed?.( items ); + }; + return ( + <form onSubmit={ onSubmit }> + <p>Modal UI</p> + <HStack> + <Button variant="tertiary" onClick={ closeModal }> + Cancel + </Button> + <Button variant="primary" type="submit"> + Submit + </Button> + </HStack> + </form> + ); + } +} +``` + +### `hideModalHeader` + +Controls visibility of the modal's header when using `RenderModal`. + +- Type: `boolean` +- Optional +- When false and using `RenderModal`, the action's label is used in modal header + +### `modalHeader` + +The header text to show in the modal. + +- Type: `string` +- Optional + + ## Fields API ### `id` From ebf1149eec2db05127bfe307974b0c409bf892ec Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Wed, 20 Nov 2024 14:11:12 +0100 Subject: [PATCH 1649/1908] `FormFileUpload`: Prevent HEIC and HEIF files from being uploaded on Safari (#67139) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Revert "Ensure HEIC files selectable from “Upload” button (#66292)" This reverts commit c5921d766c143ef6774c827c8c2f6322b2b26b6b. * Update changelog * Make it Safari conditional * Remove extra whitespaces * Update changelog * Use globalthis * Forgot a # * Make it safer Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: azaozz <azaozz@git.wordpress.org> Co-authored-by: desrosj <desrosj@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/form-file-upload/index.tsx | 12 +++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 0638842814a7d3..b84b720e35c900 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- `FormFileUpload`: Prevent HEIC and HEIF files from being uploaded on Safari ([#67139](https://github.com/WordPress/gutenberg/pull/67139)). + ### Deprecations - `DimensionControl`: Deprecate 36px default size ([#66705](https://github.com/WordPress/gutenberg/pull/66705)). diff --git a/packages/components/src/form-file-upload/index.tsx b/packages/components/src/form-file-upload/index.tsx index 66f0b2ea6d6480..83d563f2074764 100644 --- a/packages/components/src/form-file-upload/index.tsx +++ b/packages/components/src/form-file-upload/index.tsx @@ -50,9 +50,15 @@ export function FormFileUpload( { // @todo: Temporary fix a bug that prevents Chromium browsers from selecting ".heic" files // from the file upload. See https://core.trac.wordpress.org/ticket/62268#comment:4. // This can be removed once the Chromium fix is in the stable channel. - const compatAccept = !! accept?.includes( 'image/*' ) - ? `${ accept }, image/heic, image/heif` - : accept; + // Prevent Safari from adding "image/heic" and "image/heif" to the accept attribute. + const isSafari = + globalThis.window?.navigator.userAgent.includes( 'Safari' ) && + ! globalThis.window?.navigator.userAgent.includes( 'Chrome' ) && + ! globalThis.window?.navigator.userAgent.includes( 'Chromium' ); + const compatAccept = + ! isSafari && !! accept?.includes( 'image/*' ) + ? `${ accept }, image/heic, image/heif` + : accept; return ( <div className="components-form-file-upload"> From 944e6b8c04a017c50af3f8862c9120bd7c383d4e Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Wed, 20 Nov 2024 14:34:54 +0100 Subject: [PATCH 1650/1908] SlotFill: rewrite base Slot to functional, unify rerenderable refs (#67153) * SlotFill: rewrite base Slot to functional, unify rerenderable refs * Add changelog entry * Implement rerender with useReducer Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/slot-fill/bubbles-virtually/fill.tsx | 27 +--- .../bubbles-virtually/slot-fill-provider.tsx | 2 +- packages/components/src/slot-fill/fill.ts | 2 +- .../components/src/slot-fill/provider.tsx | 25 ++-- packages/components/src/slot-fill/slot.tsx | 133 +++++++----------- packages/components/src/slot-fill/types.ts | 69 ++------- 7 files changed, 78 insertions(+), 181 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index b84b720e35c900..e5d467f22d30c8 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -33,6 +33,7 @@ ### Internal - `SlotFill`: fix dependencies of `Fill` registration effects ([#67071](https://github.com/WordPress/gutenberg/pull/67071)). +- `SlotFill`: rewrite the `Slot` component from class component to functional ([#67153](https://github.com/WordPress/gutenberg/pull/67153)). ## 28.12.0 (2024-11-16) diff --git a/packages/components/src/slot-fill/bubbles-virtually/fill.tsx b/packages/components/src/slot-fill/bubbles-virtually/fill.tsx index b1b82aac5c0567..d5287adfab4178 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/fill.tsx +++ b/packages/components/src/slot-fill/bubbles-virtually/fill.tsx @@ -4,8 +4,8 @@ import { useObservableValue } from '@wordpress/compose'; import { useContext, + useReducer, useRef, - useState, useEffect, createPortal, } from '@wordpress/element'; @@ -17,37 +17,20 @@ import SlotFillContext from './slot-fill-context'; import StyleProvider from '../../style-provider'; import type { FillComponentProps } from '../types'; -function useForceUpdate() { - const [ , setState ] = useState( {} ); - const mountedRef = useRef( true ); - - useEffect( () => { - mountedRef.current = true; - return () => { - mountedRef.current = false; - }; - }, [] ); - - return () => { - if ( mountedRef.current ) { - setState( {} ); - } - }; -} - export default function Fill( { name, children }: FillComponentProps ) { const registry = useContext( SlotFillContext ); const slot = useObservableValue( registry.slots, name ); - const rerender = useForceUpdate(); + const [ , rerender ] = useReducer( () => [], [] ); const ref = useRef( { rerender } ); useEffect( () => { // We register fills so we can keep track of their existence. // Some Slot implementations need to know if there're already fills // registered so they can choose to render themselves or not. - registry.registerFill( name, ref ); + const refValue = ref.current; + registry.registerFill( name, refValue ); return () => { - registry.unregisterFill( name, ref ); + registry.unregisterFill( name, refValue ); }; }, [ registry, name ] ); diff --git a/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx b/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx index 16a19c6569fda6..1dc5ef35ceccfe 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx +++ b/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx @@ -70,7 +70,7 @@ function createSlotRegistry(): SlotFillBubblesVirtuallyContext { const slotFills = fills.get( name ); if ( slotFills ) { // Force update fills. - slotFills.forEach( ( fill ) => fill.current.rerender() ); + slotFills.forEach( ( fill ) => fill.rerender() ); } }; diff --git a/packages/components/src/slot-fill/fill.ts b/packages/components/src/slot-fill/fill.ts index b11b7af09b82f0..0a31c8276b3f10 100644 --- a/packages/components/src/slot-fill/fill.ts +++ b/packages/components/src/slot-fill/fill.ts @@ -29,7 +29,7 @@ export default function Fill( { name, children }: FillComponentProps ) { useLayoutEffect( () => { ref.current.children = children; if ( slot ) { - slot.forceUpdate(); + slot.rerender(); } }, [ slot, children ] ); diff --git a/packages/components/src/slot-fill/provider.tsx b/packages/components/src/slot-fill/provider.tsx index 6ed624bab67a3c..e2b98e73e1b707 100644 --- a/packages/components/src/slot-fill/provider.tsx +++ b/packages/components/src/slot-fill/provider.tsx @@ -1,7 +1,6 @@ /** * WordPress dependencies */ -import type { Component } from '@wordpress/element'; import { useState } from '@wordpress/element'; /** @@ -11,20 +10,17 @@ import SlotFillContext from './context'; import type { FillComponentProps, BaseSlotFillContext, - BaseSlotComponentProps, SlotFillProviderProps, SlotKey, + Rerenderable, } from './types'; function createSlotRegistry(): BaseSlotFillContext { - const slots: Record< SlotKey, Component< BaseSlotComponentProps > > = {}; + const slots: Record< SlotKey, Rerenderable > = {}; const fills: Record< SlotKey, FillComponentProps[] > = {}; let listeners: Array< () => void > = []; - function registerSlot( - name: SlotKey, - slot: Component< BaseSlotComponentProps > - ) { + function registerSlot( name: SlotKey, slot: Rerenderable ) { const previousSlot = slots[ name ]; slots[ name ] = slot; triggerListeners(); @@ -38,7 +34,7 @@ function createSlotRegistry(): BaseSlotFillContext { // assigned into the instance, such that its own rendering of children // will be empty (the new Slot will subsume all fills for this name). if ( previousSlot ) { - previousSlot.forceUpdate(); + previousSlot.rerender(); } } @@ -47,10 +43,7 @@ function createSlotRegistry(): BaseSlotFillContext { forceUpdateSlot( name ); } - function unregisterSlot( - name: SlotKey, - instance: Component< BaseSlotComponentProps > - ) { + function unregisterSlot( name: SlotKey, instance: Rerenderable ) { // If a previous instance of a Slot by this name unmounts, do nothing, // as the slot and its fills should only be removed for the current // known instance. @@ -68,15 +61,13 @@ function createSlotRegistry(): BaseSlotFillContext { forceUpdateSlot( name ); } - function getSlot( - name: SlotKey - ): Component< BaseSlotComponentProps > | undefined { + function getSlot( name: SlotKey ): Rerenderable | undefined { return slots[ name ]; } function getFills( name: SlotKey, - slotInstance: Component< BaseSlotComponentProps > + slotInstance: Rerenderable ): FillComponentProps[] { // Fills should only be returned for the current instance of the slot // in which they occupy. @@ -90,7 +81,7 @@ function createSlotRegistry(): BaseSlotFillContext { const slot = getSlot( name ); if ( slot ) { - slot.forceUpdate(); + slot.rerender(); } } diff --git a/packages/components/src/slot-fill/slot.tsx b/packages/components/src/slot-fill/slot.tsx index 3fe2a549359260..fe4a741ddbfbad 100644 --- a/packages/components/src/slot-fill/slot.tsx +++ b/packages/components/src/slot-fill/slot.tsx @@ -7,8 +7,11 @@ import type { ReactElement, ReactNode, Key } from 'react'; * WordPress dependencies */ import { + useContext, + useEffect, + useReducer, + useRef, Children, - Component, cloneElement, isEmptyElement, } from '@wordpress/element'; @@ -17,7 +20,7 @@ import { * Internal dependencies */ import SlotFillContext from './context'; -import type { BaseSlotComponentProps, SlotComponentProps } from './types'; +import type { SlotComponentProps } from './types'; /** * Whether the argument is a function. @@ -29,90 +32,50 @@ function isFunction( maybeFunc: any ): maybeFunc is Function { return typeof maybeFunc === 'function'; } -class SlotComponent extends Component< BaseSlotComponentProps > { - private isUnmounted: boolean; - - constructor( props: BaseSlotComponentProps ) { - super( props ); - - this.isUnmounted = false; - } - - componentDidMount() { - const { registerSlot } = this.props; - this.isUnmounted = false; - registerSlot( this.props.name, this ); - } - - componentWillUnmount() { - const { unregisterSlot } = this.props; - this.isUnmounted = true; - unregisterSlot( this.props.name, this ); - } - - componentDidUpdate( prevProps: BaseSlotComponentProps ) { - const { name, unregisterSlot, registerSlot } = this.props; - - if ( prevProps.name !== name ) { - unregisterSlot( prevProps.name, this ); - registerSlot( name, this ); - } - } - - forceUpdate() { - if ( this.isUnmounted ) { - return; - } - super.forceUpdate(); - } - - render() { - const { children, name, fillProps = {}, getFills } = this.props; - const fills: ReactNode[] = ( getFills( name, this ) ?? [] ) - .map( ( fill ) => { - const fillChildren = isFunction( fill.children ) - ? fill.children( fillProps ) - : fill.children; - return Children.map( fillChildren, ( child, childIndex ) => { - if ( ! child || typeof child === 'string' ) { - return child; - } - let childKey: Key = childIndex; - if ( - typeof child === 'object' && - 'key' in child && - child?.key - ) { - childKey = child.key; - } - - return cloneElement( child as ReactElement, { - key: childKey, - } ); +function Slot( props: Omit< SlotComponentProps, 'bubblesVirtually' > ) { + const registry = useContext( SlotFillContext ); + const [ , rerender ] = useReducer( () => [], [] ); + const ref = useRef( { rerender } ); + + const { name, children, fillProps = {} } = props; + + useEffect( () => { + const refValue = ref.current; + registry.registerSlot( name, refValue ); + return () => registry.unregisterSlot( name, refValue ); + }, [ registry, name ] ); + + const fills: ReactNode[] = ( registry.getFills( name, ref.current ) ?? [] ) + .map( ( fill ) => { + const fillChildren = isFunction( fill.children ) + ? fill.children( fillProps ) + : fill.children; + return Children.map( fillChildren, ( child, childIndex ) => { + if ( ! child || typeof child === 'string' ) { + return child; + } + let childKey: Key = childIndex; + if ( + typeof child === 'object' && + 'key' in child && + child?.key + ) { + childKey = child.key; + } + + return cloneElement( child as ReactElement, { + key: childKey, } ); - } ) - .filter( - // In some cases fills are rendered only when some conditions apply. - // This ensures that we only use non-empty fills when rendering, i.e., - // it allows us to render wrappers only when the fills are actually present. - ( element ) => ! isEmptyElement( element ) - ); - - return <>{ isFunction( children ) ? children( fills ) : fills }</>; - } + } ); + } ) + .filter( + // In some cases fills are rendered only when some conditions apply. + // This ensures that we only use non-empty fills when rendering, i.e., + // it allows us to render wrappers only when the fills are actually present. + ( element ) => ! isEmptyElement( element ) + ); + + return <>{ isFunction( children ) ? children( fills ) : fills }</>; } -const Slot = ( props: Omit< SlotComponentProps, 'bubblesVirtually' > ) => ( - <SlotFillContext.Consumer> - { ( { registerSlot, unregisterSlot, getFills } ) => ( - <SlotComponent - { ...props } - registerSlot={ registerSlot } - unregisterSlot={ unregisterSlot } - getFills={ getFills } - /> - ) } - </SlotFillContext.Consumer> -); - export default Slot; diff --git a/packages/components/src/slot-fill/types.ts b/packages/components/src/slot-fill/types.ts index 7e1b8b7e1f3f9f..15f082cf3f7552 100644 --- a/packages/components/src/slot-fill/types.ts +++ b/packages/components/src/slot-fill/types.ts @@ -1,7 +1,7 @@ /** * External dependencies */ -import type { Component, MutableRefObject, ReactNode, RefObject } from 'react'; +import type { ReactNode, RefObject } from 'react'; /** * WordPress dependencies @@ -108,42 +108,17 @@ export type SlotFillProviderProps = { passthrough?: boolean; }; -export type SlotFillBubblesVirtuallySlotRef = RefObject< HTMLElement >; -export type SlotFillBubblesVirtuallyFillRef = MutableRefObject< { - rerender: () => void; -} >; +export type SlotRef = RefObject< HTMLElement >; +export type Rerenderable = { rerender: () => void }; export type SlotFillBubblesVirtuallyContext = { - slots: ObservableMap< - SlotKey, - { - ref: SlotFillBubblesVirtuallySlotRef; - fillProps: FillProps; - } - >; - fills: ObservableMap< SlotKey, SlotFillBubblesVirtuallyFillRef[] >; - registerSlot: ( - name: SlotKey, - ref: SlotFillBubblesVirtuallySlotRef, - fillProps: FillProps - ) => void; - unregisterSlot: ( - name: SlotKey, - ref: SlotFillBubblesVirtuallySlotRef - ) => void; - updateSlot: ( - name: SlotKey, - ref: SlotFillBubblesVirtuallySlotRef, - fillProps: FillProps - ) => void; - registerFill: ( - name: SlotKey, - ref: SlotFillBubblesVirtuallyFillRef - ) => void; - unregisterFill: ( - name: SlotKey, - ref: SlotFillBubblesVirtuallyFillRef - ) => void; + slots: ObservableMap< SlotKey, { ref: SlotRef; fillProps: FillProps } >; + fills: ObservableMap< SlotKey, Rerenderable[] >; + registerSlot: ( name: SlotKey, ref: SlotRef, fillProps: FillProps ) => void; + unregisterSlot: ( name: SlotKey, ref: SlotRef ) => void; + updateSlot: ( name: SlotKey, ref: SlotRef, fillProps: FillProps ) => void; + registerFill: ( name: SlotKey, ref: Rerenderable ) => void; + unregisterFill: ( name: SlotKey, ref: Rerenderable ) => void; /** * This helps the provider know if it's using the default context value or not. @@ -152,30 +127,14 @@ export type SlotFillBubblesVirtuallyContext = { }; export type BaseSlotFillContext = { - registerSlot: ( - name: SlotKey, - slot: Component< BaseSlotComponentProps > - ) => void; - unregisterSlot: ( - name: SlotKey, - slot: Component< BaseSlotComponentProps > - ) => void; + registerSlot: ( name: SlotKey, slot: Rerenderable ) => void; + unregisterSlot: ( name: SlotKey, slot: Rerenderable ) => void; registerFill: ( name: SlotKey, instance: FillComponentProps ) => void; unregisterFill: ( name: SlotKey, instance: FillComponentProps ) => void; - getSlot: ( - name: SlotKey - ) => Component< BaseSlotComponentProps > | undefined; + getSlot: ( name: SlotKey ) => Rerenderable | undefined; getFills: ( name: SlotKey, - slotInstance: Component< BaseSlotComponentProps > + slotInstance: Rerenderable ) => FillComponentProps[]; subscribe: ( listener: () => void ) => () => void; }; - -export type BaseSlotComponentProps = Pick< - BaseSlotFillContext, - 'registerSlot' | 'unregisterSlot' | 'getFills' -> & - Omit< SlotComponentProps, 'bubblesVirtually' > & { - children?: ( fills: ReactNode ) => ReactNode; - }; From c38610ae21d5aad266aff9a08fc49e80cd38f0e6 Mon Sep 17 00:00:00 2001 From: louwie17 <lourensschep@gmail.com> Date: Wed, 20 Nov 2024 11:42:10 -0400 Subject: [PATCH 1651/1908] DataForm: enable fields to declare a different layout (#66531) Co-authored-by: louwie17 <louwie17@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: gigitux <gigitux@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../dataform-combined-edit/index.tsx | 69 ----- .../dataform-combined-edit/style.scss | 16 - .../src/components/dataform-context/index.tsx | 30 ++ .../src/components/dataform/index.tsx | 27 +- .../dataform/stories/index.story.tsx | 137 +++++--- .../dataforms-layouts/data-form-layout.tsx | 87 ++++++ .../dataforms-layouts/get-visible-fields.ts | 29 -- .../dataviews/src/dataforms-layouts/index.tsx | 14 +- .../dataforms-layouts/is-combined-field.ts | 10 + .../src/dataforms-layouts/panel/index.tsx | 293 ++++++++++++------ .../src/dataforms-layouts/regular/index.tsx | 138 ++++++--- .../src/dataforms-layouts/regular/style.scss | 30 ++ packages/dataviews/src/normalize-fields.ts | 34 +- .../dataviews/src/normalize-form-fields.ts | 42 +++ packages/dataviews/src/style.scss | 2 +- packages/dataviews/src/types.ts | 44 +-- packages/dataviews/src/validation.ts | 2 +- .../src/components/post-edit/index.js | 20 +- 18 files changed, 645 insertions(+), 379 deletions(-) delete mode 100644 packages/dataviews/src/components/dataform-combined-edit/index.tsx delete mode 100644 packages/dataviews/src/components/dataform-combined-edit/style.scss create mode 100644 packages/dataviews/src/components/dataform-context/index.tsx create mode 100644 packages/dataviews/src/dataforms-layouts/data-form-layout.tsx delete mode 100644 packages/dataviews/src/dataforms-layouts/get-visible-fields.ts create mode 100644 packages/dataviews/src/dataforms-layouts/is-combined-field.ts create mode 100644 packages/dataviews/src/dataforms-layouts/regular/style.scss create mode 100644 packages/dataviews/src/normalize-form-fields.ts diff --git a/packages/dataviews/src/components/dataform-combined-edit/index.tsx b/packages/dataviews/src/components/dataform-combined-edit/index.tsx deleted file mode 100644 index 90a92ac861bdd1..00000000000000 --- a/packages/dataviews/src/components/dataform-combined-edit/index.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/** - * WordPress dependencies - */ -import { - __experimentalHStack as HStack, - __experimentalVStack as VStack, - __experimentalHeading as Heading, - __experimentalSpacer as Spacer, -} from '@wordpress/components'; - -/** - * Internal dependencies - */ -import type { DataFormCombinedEditProps, NormalizedField } from '../../types'; -import FormFieldVisibility from '../form-field-visibility'; - -function Header( { title }: { title: string } ) { - return ( - <VStack className="dataforms-layouts__dropdown-header" spacing={ 4 }> - <HStack alignment="center"> - <Heading level={ 2 } size={ 13 }> - { title } - </Heading> - <Spacer /> - </HStack> - </VStack> - ); -} - -function DataFormCombinedEdit< Item >( { - field, - data, - onChange, - hideLabelFromVision, -}: DataFormCombinedEditProps< Item > ) { - const className = 'dataforms-combined-edit'; - const visibleChildren = ( field.children ?? [] ) - .map( ( fieldId ) => field.fields.find( ( { id } ) => id === fieldId ) ) - .filter( - ( childField ): childField is NormalizedField< Item > => - !! childField - ); - const children = visibleChildren.map( ( child ) => { - return ( - <FormFieldVisibility key={ child.id } data={ data } field={ child }> - <div className="dataforms-combined-edit__field"> - <child.Edit - data={ data } - field={ child } - onChange={ onChange } - /> - </div> - </FormFieldVisibility> - ); - } ); - - const Stack = field.direction === 'horizontal' ? HStack : VStack; - - return ( - <> - { ! hideLabelFromVision && <Header title={ field.label } /> } - <Stack spacing={ 4 } className={ className } as="fieldset"> - { children } - </Stack> - </> - ); -} - -export default DataFormCombinedEdit; diff --git a/packages/dataviews/src/components/dataform-combined-edit/style.scss b/packages/dataviews/src/components/dataform-combined-edit/style.scss deleted file mode 100644 index 97e052ed897989..00000000000000 --- a/packages/dataviews/src/components/dataform-combined-edit/style.scss +++ /dev/null @@ -1,16 +0,0 @@ -.dataforms-layouts-panel__field-dropdown { - .dataforms-combined-edit { - border: none; - padding: 0; - } -} - -.dataforms-combined-edit { - &__field { - flex: 1 1 auto; - } - - p.components-base-control__help:has(.components-checkbox-control__help) { - margin-top: $grid-unit-05; - } -} diff --git a/packages/dataviews/src/components/dataform-context/index.tsx b/packages/dataviews/src/components/dataform-context/index.tsx new file mode 100644 index 00000000000000..72fbf7e0f42ab6 --- /dev/null +++ b/packages/dataviews/src/components/dataform-context/index.tsx @@ -0,0 +1,30 @@ +/** + * WordPress dependencies + */ +import { createContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { NormalizedField } from '../../types'; + +type DataFormContextType< Item > = { + fields: NormalizedField< Item >[]; +}; + +const DataFormContext = createContext< DataFormContextType< any > >( { + fields: [], +} ); + +export function DataFormProvider< Item >( { + fields, + children, +}: React.PropsWithChildren< { fields: NormalizedField< Item >[] } > ) { + return ( + <DataFormContext.Provider value={ { fields } }> + { children } + </DataFormContext.Provider> + ); +} + +export default DataFormContext; diff --git a/packages/dataviews/src/components/dataform/index.tsx b/packages/dataviews/src/components/dataform/index.tsx index 58f0bf06afb414..b359ddba74381e 100644 --- a/packages/dataviews/src/components/dataform/index.tsx +++ b/packages/dataviews/src/components/dataform/index.tsx @@ -1,17 +1,34 @@ +/** + * WordPress dependencies + */ +import { useMemo } from '@wordpress/element'; + /** * Internal dependencies */ import type { DataFormProps } from '../../types'; -import { getFormLayout } from '../../dataforms-layouts'; +import { DataFormProvider } from '../dataform-context'; +import { normalizeFields } from '../../normalize-fields'; +import { DataFormLayout } from '../../dataforms-layouts/data-form-layout'; export default function DataForm< Item >( { + data, form, - ...props + fields, + onChange, }: DataFormProps< Item > ) { - const layout = getFormLayout( form.type ?? 'regular' ); - if ( ! layout ) { + const normalizedFields = useMemo( + () => normalizeFields( fields ), + [ fields ] + ); + + if ( ! form.fields ) { return null; } - return <layout.component form={ form } { ...props } />; + return ( + <DataFormProvider fields={ normalizedFields }> + <DataFormLayout data={ data } form={ form } onChange={ onChange } /> + </DataFormProvider> + ); } diff --git a/packages/dataviews/src/components/dataform/stories/index.story.tsx b/packages/dataviews/src/components/dataform/stories/index.story.tsx index b59d79063200bf..ecad2af43fb84b 100644 --- a/packages/dataviews/src/components/dataform/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataform/stories/index.story.tsx @@ -1,13 +1,14 @@ /** * WordPress dependencies */ -import { useState } from '@wordpress/element'; +import { useMemo, useState } from '@wordpress/element'; +import { ToggleControl } from '@wordpress/components'; /** * Internal dependencies */ import DataForm from '../index'; -import type { CombinedFormField, Field } from '../../../types'; +import type { Field, Form } from '../../../types'; type SamplePost = { title: string; @@ -27,8 +28,13 @@ const meta = { type: { control: { type: 'select' }, description: - 'Chooses the layout of the form. "regular" is the default layout.', - options: [ 'regular', 'panel' ], + 'Chooses the default layout of each field. "regular" is the default layout.', + options: [ 'default', 'regular', 'panel' ], + }, + labelPosition: { + control: { type: 'select' }, + description: 'Chooses the label position of the layout.', + options: [ 'default', 'top', 'side', 'none' ], }, }, }; @@ -97,9 +103,33 @@ const fields = [ return item.status !== 'private'; }, }, + { + id: 'sticky', + label: 'Sticky', + type: 'integer', + Edit: ( { field, onChange, data, hideLabelFromVision } ) => { + const { id, getValue } = field; + return ( + <ToggleControl + __nextHasNoMarginBottom + label={ hideLabelFromVision ? '' : field.label } + checked={ getValue( { item: data } ) } + onChange={ () => + onChange( { [ id ]: ! getValue( { item: data } ) } ) + } + /> + ); + }, + }, ] as Field< SamplePost >[]; -export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { +export const Default = ( { + type, + labelPosition, +}: { + type: 'default' | 'regular' | 'panel'; + labelPosition: 'default' | 'top' | 'side' | 'none'; +} ) => { const [ post, setPost ] = useState( { title: 'Hello, World!', order: 2, @@ -108,29 +138,36 @@ export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { reviewer: 'fulano', date: '2021-01-01T12:00:00', birthdate: '1950-02-23T12:00:00', + sticky: false, } ); - const form = { - fields: [ - 'title', - 'order', - 'author', - 'reviewer', - 'status', - 'password', - 'date', - 'birthdate', - ], - }; + const form = useMemo( + () => ( { + type, + labelPosition, + fields: [ + 'title', + 'order', + { + id: 'sticky', + layout: 'regular', + labelPosition: 'side', + }, + 'author', + 'reviewer', + 'password', + 'date', + 'birthdate', + ], + } ), + [ type, labelPosition ] + ) as Form; return ( <DataForm< SamplePost > data={ post } fields={ fields } - form={ { - ...form, - type, - } } + form={ form } onChange={ ( edits ) => setPost( ( prev ) => ( { ...prev, @@ -142,40 +179,45 @@ export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { }; const CombinedFieldsComponent = ( { - type = 'regular', - combinedFieldDirection = 'vertical', + type, + labelPosition, }: { - type: 'panel' | 'regular'; - combinedFieldDirection: 'vertical' | 'horizontal'; + type: 'default' | 'regular' | 'panel'; + labelPosition: 'default' | 'top' | 'side' | 'none'; } ) => { - const [ post, setPost ] = useState( { + const [ post, setPost ] = useState< SamplePost >( { title: 'Hello, World!', order: 2, author: 1, status: 'draft', + reviewer: 'fulano', + date: '2021-01-01T12:00:00', + birthdate: '1950-02-23T12:00:00', } ); - const form = { - fields: [ 'title', 'status_and_visibility', 'order', 'author' ], - combinedFields: [ - { - id: 'status_and_visibility', - label: 'Status & Visibility', - children: [ 'status', 'password' ], - direction: combinedFieldDirection, - render: ( { item } ) => item.status, - }, - ] as CombinedFormField< any >[], - }; + const form = useMemo( + () => ( { + type, + labelPosition, + fields: [ + 'title', + { + id: 'status', + label: 'Status & Visibility', + children: [ 'status', 'password' ], + }, + 'order', + 'author', + ], + } ), + [ type, labelPosition ] + ) as Form; return ( - <DataForm + <DataForm< SamplePost > data={ post } fields={ fields } - form={ { - ...form, - type, - } } + form={ form } onChange={ ( edits ) => setPost( ( prev ) => ( { ...prev, @@ -191,11 +233,8 @@ export const CombinedFields = { render: CombinedFieldsComponent, argTypes: { ...meta.argTypes, - combinedFieldDirection: { - control: { type: 'select' }, - description: - 'Chooses the direction of the combined field. "vertical" is the default layout.', - options: [ 'vertical', 'horizontal' ], - }, + }, + args: { + type: 'panel', }, }; diff --git a/packages/dataviews/src/dataforms-layouts/data-form-layout.tsx b/packages/dataviews/src/dataforms-layouts/data-form-layout.tsx new file mode 100644 index 00000000000000..08cc47f569eafe --- /dev/null +++ b/packages/dataviews/src/dataforms-layouts/data-form-layout.tsx @@ -0,0 +1,87 @@ +/** + * WordPress dependencies + */ +import { __experimentalVStack as VStack } from '@wordpress/components'; +import { useContext, useMemo } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { Form, FormField, SimpleFormField } from '../types'; +import { getFormFieldLayout } from './index'; +import DataFormContext from '../components/dataform-context'; +import { isCombinedField } from './is-combined-field'; +import normalizeFormFields from '../normalize-form-fields'; + +export function DataFormLayout< Item >( { + data, + form, + onChange, + children, +}: { + data: Item; + form: Form; + onChange: ( value: any ) => void; + children?: ( + FieldLayout: ( props: { + data: Item; + field: FormField; + onChange: ( value: any ) => void; + hideLabelFromVision?: boolean; + } ) => React.JSX.Element | null, + field: FormField + ) => React.JSX.Element; +} ) { + const { fields: fieldDefinitions } = useContext( DataFormContext ); + + function getFieldDefinition( field: SimpleFormField | string ) { + const fieldId = typeof field === 'string' ? field : field.id; + + return fieldDefinitions.find( + ( fieldDefinition ) => fieldDefinition.id === fieldId + ); + } + + const normalizedFormFields = useMemo( + () => normalizeFormFields( form ), + [ form ] + ); + + return ( + <VStack spacing={ 2 }> + { normalizedFormFields.map( ( formField ) => { + const FieldLayout = getFormFieldLayout( formField.layout ) + ?.component; + + if ( ! FieldLayout ) { + return null; + } + + const fieldDefinition = ! isCombinedField( formField ) + ? getFieldDefinition( formField ) + : undefined; + + if ( + fieldDefinition && + fieldDefinition.isVisible && + ! fieldDefinition.isVisible( data ) + ) { + return null; + } + + if ( children ) { + return children( FieldLayout, formField ); + } + + return ( + <FieldLayout + key={ formField.id } + data={ data } + field={ formField } + onChange={ onChange } + /> + ); + } ) } + </VStack> + ); +} diff --git a/packages/dataviews/src/dataforms-layouts/get-visible-fields.ts b/packages/dataviews/src/dataforms-layouts/get-visible-fields.ts deleted file mode 100644 index d95d59a88394e4..00000000000000 --- a/packages/dataviews/src/dataforms-layouts/get-visible-fields.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Internal dependencies - */ -import { normalizeCombinedFields } from '../normalize-fields'; -import type { - Field, - CombinedFormField, - NormalizedCombinedFormField, -} from '../types'; - -export function getVisibleFields< Item >( - fields: Field< Item >[], - formFields: string[] = [], - combinedFields?: CombinedFormField< Item >[] -): Field< Item >[] { - const visibleFields: Array< - Field< Item > | NormalizedCombinedFormField< Item > - > = [ ...fields ]; - if ( combinedFields ) { - visibleFields.push( - ...normalizeCombinedFields( combinedFields, fields ) - ); - } - return formFields - .map( ( fieldId ) => - visibleFields.find( ( { id } ) => id === fieldId ) - ) - .filter( ( field ): field is Field< Item > => !! field ); -} diff --git a/packages/dataviews/src/dataforms-layouts/index.tsx b/packages/dataviews/src/dataforms-layouts/index.tsx index 9434ea724ed4ca..5e4f3617d9c7dd 100644 --- a/packages/dataviews/src/dataforms-layouts/index.tsx +++ b/packages/dataviews/src/dataforms-layouts/index.tsx @@ -1,20 +1,20 @@ /** * Internal dependencies */ -import FormRegular from './regular'; -import FormPanel from './panel'; +import FormRegularField from './regular'; +import FormPanelField from './panel'; -const FORM_LAYOUTS = [ +const FORM_FIELD_LAYOUTS = [ { type: 'regular', - component: FormRegular, + component: FormRegularField, }, { type: 'panel', - component: FormPanel, + component: FormPanelField, }, ]; -export function getFormLayout( type: string ) { - return FORM_LAYOUTS.find( ( layout ) => layout.type === type ); +export function getFormFieldLayout( type: string ) { + return FORM_FIELD_LAYOUTS.find( ( layout ) => layout.type === type ); } diff --git a/packages/dataviews/src/dataforms-layouts/is-combined-field.ts b/packages/dataviews/src/dataforms-layouts/is-combined-field.ts new file mode 100644 index 00000000000000..3df6fdc60f906e --- /dev/null +++ b/packages/dataviews/src/dataforms-layouts/is-combined-field.ts @@ -0,0 +1,10 @@ +/** + * Internal dependencies + */ +import type { FormField, CombinedFormField } from '../types'; + +export function isCombinedField( + field: FormField +): field is CombinedFormField { + return ( field as CombinedFormField ).children !== undefined; +} diff --git a/packages/dataviews/src/dataforms-layouts/panel/index.tsx b/packages/dataviews/src/dataforms-layouts/panel/index.tsx index b74e5e4667d4b1..269b2bb418a856 100644 --- a/packages/dataviews/src/dataforms-layouts/panel/index.tsx +++ b/packages/dataviews/src/dataforms-layouts/panel/index.tsx @@ -9,29 +9,29 @@ import { Dropdown, Button, } from '@wordpress/components'; -import { useState, useMemo } from '@wordpress/element'; import { sprintf, __, _x } from '@wordpress/i18n'; +import { useState, useMemo, useContext } from '@wordpress/element'; import { closeSmall } from '@wordpress/icons'; /** * Internal dependencies */ -import { normalizeFields } from '../../normalize-fields'; -import { getVisibleFields } from '../get-visible-fields'; -import type { DataFormProps, NormalizedField } from '../../types'; -import FormFieldVisibility from '../../components/form-field-visibility'; - -interface FormFieldProps< Item > { - data: Item; - field: NormalizedField< Item >; - onChange: ( value: any ) => void; -} +import type { + Form, + FormField, + FieldLayoutProps, + NormalizedField, + SimpleFormField, +} from '../../types'; +import DataFormContext from '../../components/dataform-context'; +import { DataFormLayout } from '../data-form-layout'; +import { isCombinedField } from '../is-combined-field'; function DropdownHeader( { title, onClose, }: { - title: string; + title?: string; onClose: () => void; } ) { return ( @@ -40,9 +40,11 @@ function DropdownHeader( { spacing={ 4 } > <HStack alignment="center"> - <Heading level={ 2 } size={ 13 }> - { title } - </Heading> + { title && ( + <Heading level={ 2 } size={ 13 }> + { title } + </Heading> + ) } <Spacer /> { onClose && ( <Button @@ -57,16 +59,45 @@ function DropdownHeader( { ); } -function FormField< Item >( { +function PanelDropdown< Item >( { + fieldDefinition, + popoverAnchor, + labelPosition = 'side', data, - field, onChange, -}: FormFieldProps< Item > ) { - // Use internal state instead of a ref to make sure that the component - // re-renders when the popover's anchor updates. - const [ popoverAnchor, setPopoverAnchor ] = useState< HTMLElement | null >( - null - ); + field, +}: { + fieldDefinition: NormalizedField< Item >; + popoverAnchor: HTMLElement | null; + labelPosition: 'side' | 'top' | 'none'; + data: Item; + onChange: ( value: any ) => void; + field: FormField; +} ) { + const fieldLabel = isCombinedField( field ) + ? field.label + : fieldDefinition?.label; + const form = useMemo( () => { + if ( isCombinedField( field ) ) { + return { + type: 'regular' as const, + fields: field.children.map( ( child ) => { + if ( typeof child === 'string' ) { + return { + id: child, + }; + } + return child; + } ), + }; + } + // If not explicit children return the field id itself. + return { + type: 'regular' as const, + fields: [ { id: field.id } ], + }; + }, [ field ] ); + // Memoize popoverProps to avoid returning a new object every time. const popoverProps = useMemo( () => ( { @@ -81,95 +112,155 @@ function FormField< Item >( { ); return ( - <HStack - ref={ setPopoverAnchor } - className="dataforms-layouts-panel__field" - > - <div className="dataforms-layouts-panel__field-label"> - { field.label } - </div> - <div> - <Dropdown - contentClassName="dataforms-layouts-panel__field-dropdown" - popoverProps={ popoverProps } - focusOnMount - toggleProps={ { - size: 'compact', - variant: 'tertiary', - tooltipPosition: 'middle left', - } } - renderToggle={ ( { isOpen, onToggle } ) => ( - <Button - className="dataforms-layouts-panel__field-control" - size="compact" - variant="tertiary" - aria-expanded={ isOpen } - aria-label={ sprintf( - // translators: %s: Field name. - _x( 'Edit %s', 'field' ), - field.label - ) } - onClick={ onToggle } - > - <field.render item={ data } /> - </Button> + <Dropdown + contentClassName="dataforms-layouts-panel__field-dropdown" + popoverProps={ popoverProps } + focusOnMount + toggleProps={ { + size: 'compact', + variant: 'tertiary', + tooltipPosition: 'middle left', + } } + renderToggle={ ( { isOpen, onToggle } ) => ( + <Button + className="dataforms-layouts-panel__field-control" + size="compact" + variant={ + [ 'none', 'top' ].includes( labelPosition ) + ? 'link' + : 'tertiary' + } + aria-expanded={ isOpen } + aria-label={ sprintf( + // translators: %s: Field name. + _x( 'Edit %s', 'field' ), + fieldLabel ) } - renderContent={ ( { onClose } ) => ( - <> - <DropdownHeader - title={ field.label } - onClose={ onClose } - /> - <field.Edit - key={ field.id } + onClick={ onToggle } + > + <fieldDefinition.render item={ data } /> + </Button> + ) } + renderContent={ ( { onClose } ) => ( + <> + <DropdownHeader title={ fieldLabel } onClose={ onClose } /> + <DataFormLayout + data={ data } + form={ form as Form } + onChange={ onChange } + > + { ( FieldLayout, nestedField ) => ( + <FieldLayout + key={ nestedField.id } data={ data } - field={ field } + field={ nestedField } onChange={ onChange } - hideLabelFromVision + hideLabelFromVision={ + ( form?.fields ?? [] ).length < 2 + } /> - </> - ) } - /> - </div> - </HStack> + ) } + </DataFormLayout> + </> + ) } + /> ); } -export default function FormPanel< Item >( { +export default function FormPanelField< Item >( { data, - fields, - form, + field, onChange, -}: DataFormProps< Item > ) { - const visibleFields = useMemo( - () => - normalizeFields( - getVisibleFields< Item >( - fields, - form.fields, - form.combinedFields - ) - ), - [ fields, form.fields, form.combinedFields ] +}: FieldLayoutProps< Item > ) { + const { fields } = useContext( DataFormContext ); + const fieldDefinition = fields.find( ( fieldDef ) => { + // Default to the first child if it is a combined field. + if ( isCombinedField( field ) ) { + const children = field.children.filter( + ( child ): child is string | SimpleFormField => + typeof child === 'string' || ! isCombinedField( child ) + ); + const firstChildFieldId = + typeof children[ 0 ] === 'string' + ? children[ 0 ] + : children[ 0 ].id; + return fieldDef.id === firstChildFieldId; + } + return fieldDef.id === field.id; + } ); + const labelPosition = field.labelPosition ?? 'side'; + + // Use internal state instead of a ref to make sure that the component + // re-renders when the popover's anchor updates. + const [ popoverAnchor, setPopoverAnchor ] = useState< HTMLElement | null >( + null ); - return ( - <VStack spacing={ 2 }> - { visibleFields.map( ( field ) => { - return ( - <FormFieldVisibility - key={ field.id } - data={ data } + if ( ! fieldDefinition ) { + return null; + } + + const fieldLabel = isCombinedField( field ) + ? field.label + : fieldDefinition?.label; + + if ( labelPosition === 'top' ) { + return ( + <VStack className="dataforms-layouts-panel__field" spacing={ 0 }> + <div + className="dataforms-layouts-panel__field-label" + style={ { paddingBottom: 0 } } + > + { fieldLabel } + </div> + <div className="dataforms-layouts-panel__field-control"> + <PanelDropdown field={ field } - > - <FormField - data={ data } - field={ field } - onChange={ onChange } - /> - </FormFieldVisibility> - ); - } ) } - </VStack> + popoverAnchor={ popoverAnchor } + fieldDefinition={ fieldDefinition } + data={ data } + onChange={ onChange } + labelPosition={ labelPosition } + /> + </div> + </VStack> + ); + } + + if ( labelPosition === 'none' ) { + return ( + <div className="dataforms-layouts-panel__field"> + <PanelDropdown + field={ field } + popoverAnchor={ popoverAnchor } + fieldDefinition={ fieldDefinition } + data={ data } + onChange={ onChange } + labelPosition={ labelPosition } + /> + </div> + ); + } + + // Defaults to label position side. + return ( + <HStack + ref={ setPopoverAnchor } + className="dataforms-layouts-panel__field" + > + <div className="dataforms-layouts-panel__field-label"> + { fieldLabel } + </div> + <div className="dataforms-layouts-panel__field-control"> + <PanelDropdown + field={ field } + popoverAnchor={ popoverAnchor } + fieldDefinition={ fieldDefinition } + data={ data } + onChange={ onChange } + labelPosition={ labelPosition } + /> + </div> + </HStack> ); } diff --git a/packages/dataviews/src/dataforms-layouts/regular/index.tsx b/packages/dataviews/src/dataforms-layouts/regular/index.tsx index 6a340a50584df4..a3d90b807b5cd4 100644 --- a/packages/dataviews/src/dataforms-layouts/regular/index.tsx +++ b/packages/dataviews/src/dataforms-layouts/regular/index.tsx @@ -1,52 +1,116 @@ /** * WordPress dependencies */ -import { __experimentalVStack as VStack } from '@wordpress/components'; -import { useMemo } from '@wordpress/element'; +import { useContext, useMemo } from '@wordpress/element'; +import { + __experimentalHStack as HStack, + __experimentalVStack as VStack, + __experimentalHeading as Heading, + __experimentalSpacer as Spacer, +} from '@wordpress/components'; /** * Internal dependencies */ -import { normalizeFields } from '../../normalize-fields'; -import { getVisibleFields } from '../get-visible-fields'; -import type { DataFormProps } from '../../types'; -import FormFieldVisibility from '../../components/form-field-visibility'; +import type { Form, FieldLayoutProps } from '../../types'; +import DataFormContext from '../../components/dataform-context'; +import { DataFormLayout } from '../data-form-layout'; +import { isCombinedField } from '../is-combined-field'; -export default function FormRegular< Item >( { +function Header( { title }: { title: string } ) { + return ( + <VStack className="dataforms-layouts-regular__header" spacing={ 4 }> + <HStack alignment="center"> + <Heading level={ 2 } size={ 13 }> + { title } + </Heading> + <Spacer /> + </HStack> + </VStack> + ); +} + +export default function FormRegularField< Item >( { data, - fields, - form, + field, onChange, -}: DataFormProps< Item > ) { - const visibleFields = useMemo( - () => - normalizeFields( - getVisibleFields< Item >( - fields, - form.fields, - form.combinedFields - ) - ), - [ fields, form.fields, form.combinedFields ] + hideLabelFromVision, +}: FieldLayoutProps< Item > ) { + const { fields } = useContext( DataFormContext ); + + const form = useMemo( () => { + if ( isCombinedField( field ) ) { + return { + fields: field.children.map( ( child ) => { + if ( typeof child === 'string' ) { + return { + id: child, + }; + } + return child; + } ), + type: 'regular' as const, + }; + } + + return { + type: 'regular' as const, + fields: [], + }; + }, [ field ] ); + + if ( isCombinedField( field ) ) { + return ( + <> + { ! hideLabelFromVision && field.label && ( + <Header title={ field.label } /> + ) } + <DataFormLayout + data={ data } + form={ form as Form } + onChange={ onChange } + /> + </> + ); + } + + const labelPosition = field.labelPosition ?? 'top'; + const fieldDefinition = fields.find( + ( fieldDef ) => fieldDef.id === field.id ); - return ( - <VStack spacing={ 4 }> - { visibleFields.map( ( field ) => { - return ( - <FormFieldVisibility - key={ field.id } + if ( ! fieldDefinition ) { + return null; + } + if ( labelPosition === 'side' ) { + return ( + <HStack className="dataforms-layouts-regular__field"> + <div className="dataforms-layouts-regular__field-label"> + { fieldDefinition.label } + </div> + <div className="dataforms-layouts-regular__field-control"> + <fieldDefinition.Edit + key={ fieldDefinition.id } data={ data } - field={ field } - > - <field.Edit - data={ data } - field={ field } - onChange={ onChange } - /> - </FormFieldVisibility> - ); - } ) } - </VStack> + field={ fieldDefinition } + onChange={ onChange } + hideLabelFromVision + /> + </div> + </HStack> + ); + } + + return ( + <div className="dataforms-layouts-regular__field"> + <fieldDefinition.Edit + data={ data } + field={ fieldDefinition } + onChange={ onChange } + hideLabelFromVision={ + labelPosition === 'none' ? true : hideLabelFromVision + } + /> + </div> ); } diff --git a/packages/dataviews/src/dataforms-layouts/regular/style.scss b/packages/dataviews/src/dataforms-layouts/regular/style.scss new file mode 100644 index 00000000000000..d94b804fdf1fe5 --- /dev/null +++ b/packages/dataviews/src/dataforms-layouts/regular/style.scss @@ -0,0 +1,30 @@ +.dataforms-layouts-regular__field { + width: 100%; + min-height: $grid-unit-40; + justify-content: flex-start !important; + align-items: flex-start !important; +} + +.dataforms-layouts-regular__field .components-base-control__label { + font-size: inherit; + font-weight: normal; + text-transform: none; +} + +.dataforms-layouts-regular__field-label { + width: 38%; + flex-shrink: 0; + min-height: $grid-unit-40; + display: flex; + align-items: center; + padding: 6px 0; // Matches button to ensure alignment + line-height: $grid-unit-05 * 5; + hyphens: auto; +} + +.dataforms-layouts-regular__field-control { + flex-grow: 1; + min-height: $grid-unit-40; + display: flex; + align-items: center; +} diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts index 562f29fcce84fe..2ed87cbe112229 100644 --- a/packages/dataviews/src/normalize-fields.ts +++ b/packages/dataviews/src/normalize-fields.ts @@ -2,14 +2,8 @@ * Internal dependencies */ import getFieldTypeDefinition from './field-types'; -import type { - CombinedFormField, - Field, - NormalizedField, - NormalizedCombinedFormField, -} from './types'; +import type { Field, NormalizedField } from './types'; import { getControl } from './dataform-controls'; -import DataFormCombinedEdit from './components/dataform-combined-edit'; const getValueFromId = ( id: string ) => @@ -87,29 +81,3 @@ export function normalizeFields< Item >( }; } ); } - -/** - * Apply default values and normalize the fields config. - * - * @param combinedFields combined field list. - * @param fields Fields config. - * @return Normalized fields config. - */ -export function normalizeCombinedFields< Item >( - combinedFields: CombinedFormField< Item >[], - fields: Field< Item >[] -): NormalizedCombinedFormField< Item >[] { - return combinedFields.map( ( combinedField ) => { - return { - ...combinedField, - Edit: DataFormCombinedEdit, - fields: normalizeFields( - combinedField.children - .map( ( fieldId ) => - fields.find( ( { id } ) => id === fieldId ) - ) - .filter( ( field ): field is Field< Item > => !! field ) - ), - }; - } ); -} diff --git a/packages/dataviews/src/normalize-form-fields.ts b/packages/dataviews/src/normalize-form-fields.ts new file mode 100644 index 00000000000000..3cd5f67564d7ce --- /dev/null +++ b/packages/dataviews/src/normalize-form-fields.ts @@ -0,0 +1,42 @@ +/** + * Internal dependencies + */ +import type { Form } from './types'; + +interface NormalizedFormField { + id: string; + layout: 'regular' | 'panel'; + labelPosition: 'side' | 'top' | 'none'; +} + +export default function normalizeFormFields( + form: Form +): NormalizedFormField[] { + let layout: 'regular' | 'panel' = 'regular'; + if ( [ 'regular', 'panel' ].includes( form.type ?? '' ) ) { + layout = form.type as 'regular' | 'panel'; + } + + const labelPosition = + form.labelPosition ?? ( layout === 'regular' ? 'top' : 'side' ); + + return ( form.fields ?? [] ).map( ( field ) => { + if ( typeof field === 'string' ) { + return { + id: field, + layout, + labelPosition, + }; + } + + const fieldLayout = field.layout ?? layout; + const fieldLabelPosition = + field.labelPosition ?? + ( fieldLayout === 'regular' ? 'top' : 'side' ); + return { + ...field, + layout: fieldLayout, + labelPosition: fieldLabelPosition, + }; + } ); +} diff --git a/packages/dataviews/src/style.scss b/packages/dataviews/src/style.scss index 26c6ecea645f43..5639f3cac0da51 100644 --- a/packages/dataviews/src/style.scss +++ b/packages/dataviews/src/style.scss @@ -6,7 +6,6 @@ @import "./components/dataviews-item-actions/style.scss"; @import "./components/dataviews-selection-checkbox/style.scss"; @import "./components/dataviews-view-config/style.scss"; -@import "./components/dataform-combined-edit/style.scss"; @import "./dataviews-layouts/grid/style.scss"; @import "./dataviews-layouts/list/style.scss"; @@ -14,3 +13,4 @@ @import "./dataform-controls/style.scss"; @import "./dataforms-layouts/panel/style.scss"; +@import "./dataforms-layouts/regular/style.scss"; diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 71990f72d4eecd..8c4276f2541ecc 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -527,37 +527,41 @@ export interface SupportedLayouts { table?: Omit< ViewTable, 'type' >; } -export interface CombinedFormField< Item > extends CombinedField { - render?: ComponentType< { item: Item } >; -} - -export interface DataFormCombinedEditProps< Item > { - field: NormalizedCombinedFormField< Item >; - data: Item; - onChange: ( value: Record< string, any > ) => void; - hideLabelFromVision?: boolean; -} +export type SimpleFormField = { + id: string; + layout?: 'regular' | 'panel'; + labelPosition?: 'side' | 'top' | 'none'; +}; -export type NormalizedCombinedFormField< Item > = CombinedFormField< Item > & { - fields: NormalizedField< Item >[]; - Edit?: ComponentType< DataFormCombinedEditProps< Item > >; +export type CombinedFormField = { + id: string; + label?: string; + layout?: 'regular' | 'panel'; + labelPosition?: 'side' | 'top' | 'none'; + children: Array< FormField | string >; }; +export type FormField = SimpleFormField | CombinedFormField; + /** * The form configuration. */ -export type Form< Item > = { +export type Form = { type?: 'regular' | 'panel'; - fields?: string[]; - /** - * The fields to combine. - */ - combinedFields?: CombinedFormField< Item >[]; + fields?: Array< FormField | string >; + labelPosition?: 'side' | 'top' | 'none'; }; export interface DataFormProps< Item > { data: Item; fields: Field< Item >[]; - form: Form< Item >; + form: Form; onChange: ( value: Record< string, any > ) => void; } + +export interface FieldLayoutProps< Item > { + data: Item; + field: FormField; + onChange: ( value: any ) => void; + hideLabelFromVision?: boolean; +} diff --git a/packages/dataviews/src/validation.ts b/packages/dataviews/src/validation.ts index 0a6542da4e8d40..bcc9a15908ff59 100644 --- a/packages/dataviews/src/validation.ts +++ b/packages/dataviews/src/validation.ts @@ -16,7 +16,7 @@ import type { Field, Form } from './types'; export function isItemValid< Item >( item: Item, fields: Field< Item >[], - form: Form< Item > + form: Form ): boolean { const _fields = normalizeFields( fields.filter( ( { id } ) => !! form.fields?.includes( id ) ) diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index a535eef4ce7878..a7842f0feb3c2f 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -70,9 +70,16 @@ function PostEditForm( { postType, postId } ) { () => ( { type: 'panel', fields: [ - 'featured_media', + { + id: 'featured_media', + layout: 'regular', + }, 'title', - 'status_and_visibility', + { + id: 'status', + label: __( 'Status & Visibility' ), + children: [ 'status', 'password' ], + }, 'author', 'date', 'slug', @@ -83,15 +90,6 @@ function PostEditForm( { postType, postId } ) { ids.length === 1 || fieldsWithBulkEditSupport.includes( field ) ), - combinedFields: [ - { - id: 'status_and_visibility', - label: __( 'Status & Visibility' ), - children: [ 'status', 'password' ], - direction: 'vertical', - render: ( { item } ) => item.status, - }, - ], } ), [ ids ] ); From 776b9e0da9709e360a2cd95112a811ccefbfa818 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Wed, 20 Nov 2024 10:01:14 -0600 Subject: [PATCH 1652/1908] Preserve footer template bar in zoom out (#67135) --- .../editor/src/components/editor-interface/index.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/editor/src/components/editor-interface/index.js b/packages/editor/src/components/editor-interface/index.js index 3692a5ed797f5e..6f6ffbec7b9c32 100644 --- a/packages/editor/src/components/editor-interface/index.js +++ b/packages/editor/src/components/editor-interface/index.js @@ -10,11 +10,7 @@ import { InterfaceSkeleton, ComplementaryArea } from '@wordpress/interface'; import { useSelect } from '@wordpress/data'; import { __, _x } from '@wordpress/i18n'; import { store as preferencesStore } from '@wordpress/preferences'; -import { - store as blockEditorStore, - BlockBreadcrumb, - BlockToolbar, -} from '@wordpress/block-editor'; +import { BlockBreadcrumb, BlockToolbar } from '@wordpress/block-editor'; import { useViewportMatch } from '@wordpress/compose'; import { useState, useCallback } from '@wordpress/element'; @@ -31,8 +27,6 @@ import TextEditor from '../text-editor'; import VisualEditor from '../visual-editor'; import EditorContentSlotFill from './content-slot-fill'; -import { unlock } from '../../lock-unlock'; - const interfaceLabels = { /* translators: accessibility text for the editor top bar landmark region. */ header: __( 'Editor top bar' ), @@ -69,13 +63,11 @@ export default function EditorInterface( { isPreviewMode, showBlockBreadcrumbs, documentLabel, - isZoomOut, } = useSelect( ( select ) => { const { get } = select( preferencesStore ); const { getEditorSettings, getPostTypeLabel } = select( editorStore ); const editorSettings = getEditorSettings(); const postTypeLabel = getPostTypeLabel(); - const { isZoomOut: _isZoomOut } = unlock( select( blockEditorStore ) ); return { mode: select( editorStore ).getEditorMode(), @@ -88,7 +80,6 @@ export default function EditorInterface( { documentLabel: // translators: Default label for the Document in the Block Breadcrumb. postTypeLabel || _x( 'Document', 'noun, breadcrumb' ), - isZoomOut: _isZoomOut(), }; }, [] ); const isLargeViewport = useViewportMatch( 'medium' ); @@ -197,7 +188,6 @@ export default function EditorInterface( { isLargeViewport && showBlockBreadcrumbs && isRichEditingEnabled && - ! isZoomOut && mode === 'visual' && ( <BlockBreadcrumb rootLabelText={ documentLabel } /> ) From fa675a794311e9c4d27cbb9d51ac95dcac08b1cc Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Wed, 20 Nov 2024 10:02:18 -0600 Subject: [PATCH 1653/1908] Leave help text in patterns flyout regardless of zoom state (#67132) --- .../pattern-category-previews.js | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js index a19a579ae5c0cf..c6ce9ba97d2501 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js @@ -17,7 +17,6 @@ import { __experimentalText as Text, FlexBlock, } from '@wordpress/components'; -import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -34,8 +33,6 @@ import { starterPatternsCategory, INSERTER_PATTERN_TYPES, } from './utils'; -import { store as blockEditorStore } from '../../../store'; -import { unlock } from '../../../lock-unlock'; const noop = () => {}; @@ -46,10 +43,6 @@ export function PatternCategoryPreviews( { category, showTitlesAsTooltip, } ) { - const isZoomOutMode = useSelect( - ( select ) => unlock( select( blockEditorStore ) ).isZoomOut(), - [] - ); const [ allPatterns, , onClickPattern ] = usePatternsState( onInsert, rootClientId, @@ -179,15 +172,13 @@ export function PatternCategoryPreviews( { </VStack> { currentCategoryPatterns.length > 0 && ( <> - { isZoomOutMode && ( - <Text - size="12" - as="p" - className="block-editor-inserter__help-text" - > - { __( 'Drag and drop patterns into the canvas.' ) } - </Text> - ) } + <Text + size="12" + as="p" + className="block-editor-inserter__help-text" + > + { __( 'Drag and drop patterns into the canvas.' ) } + </Text> <BlockPatternsList ref={ scrollContainerRef } blockPatterns={ pagingProps.categoryPatterns } From 0193286741fd49e708f6aa9414722b446487d6f8 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 20 Nov 2024 17:16:49 +0000 Subject: [PATCH 1654/1908] Bump plugin version to 19.7.0 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 738fe1a3bd5268..3e4d6941b5a0f3 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.6 * Requires PHP: 7.2 - * Version: 19.7.0-rc.2 + * Version: 19.7.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 376cd0b9e6edf6..04a8d2021f12a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.7.0-rc.2", + "version": "19.7.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.7.0-rc.2", + "version": "19.7.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "workspaces": [ diff --git a/package.json b/package.json index a7470a1333ffad..52668f667c71cd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.7.0-rc.2", + "version": "19.7.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From e4a716eb524458e2c567c5fd5f92d1985d7ea779 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:27:06 -0500 Subject: [PATCH 1655/1908] Add documentation about required Core changes when updating minimum WordPress version (#67167) * Add a note about required Core SVN changes. * A few refinements. --------- Co-authored-by: desrosj <desrosj@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- docs/explanations/architecture/performance.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/explanations/architecture/performance.md b/docs/explanations/architecture/performance.md index 4c8b6386b9263b..8c1034ad9de331 100644 --- a/docs/explanations/architecture/performance.md +++ b/docs/explanations/architecture/performance.md @@ -84,6 +84,12 @@ The new reference commit hash that is chosen needs to meet the following require - Be compatible with the new WP version used in the "Tested up to" flag. - Is already tracked on "codevitals.run" for all existing metrics. +When releasing a plugin update with changes to the minimum WordPress version requirements, the end-to-end test GitHub Action workflow in Core SVN will need to be updated for any branch losing support. Otherwise the first run of that workflow on that branch following the release will fail. + +The version of the plugin used in the workflow can be pinned by adding the `gutenberg-version` input to the test matrix. [Core-59221](https://core.trac.wordpress.org/changeset/59221) is an example of this change for the 6.4 branch. + +**Note:** Always use the final release including bug fixes (ie. `x.y.2` or `x.y.3`). If the final release is not yet known, create a [Trac ticket](https://core.trac.wordpress.org/ticket/62488) so it's not forgotten. + **A simple way to choose commit is to pick a very recent commit on trunk with a passing performance job.** ## Going further From e79c46950cd58f1588dbef531c143186e0666110 Mon Sep 17 00:00:00 2001 From: Vipul Gupta <55375170+vipul0425@users.noreply.github.com> Date: Wed, 20 Nov 2024 23:06:38 +0530 Subject: [PATCH 1656/1908] ToggleGroupControl : Deprecate 36px default size (#66747) * feat: Adds deprecation warning in toggleGroupControl Block. * feat: Adds the test case and story book modification. * docs: Adds changelog. * Add prop to suppress redundant warning * Updates the changelog and ToolsPanel Story. * Updates the snapshots. * Add prop to all instances in the ToolsPanel stories * Rebase changelog again --------- Co-authored-by: vipul0425 <vipulgupta003@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../font-size-picker-toggle-group.tsx | 1 + .../stories/index.story.tsx | 1 + .../test/__snapshots__/index.tsx.snap | 24 +++++++++---------- .../src/toggle-group-control/test/index.tsx | 8 ++++++- .../README.md | 2 +- .../component.tsx | 2 +- .../toggle-group-control-option/README.md | 2 +- .../toggle-group-control-option/component.tsx | 1 + .../toggle-group-control/README.md | 3 ++- .../toggle-group-control/component.tsx | 10 ++++++++ .../src/toggle-group-control/types.ts | 7 ++++++ .../src/tools-panel/stories/index.story.tsx | 3 +++ .../src/utils/deprecated-36px-size.ts | 3 +++ 14 files changed, 51 insertions(+), 17 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index e5d467f22d30c8..ff4a8b714c9a52 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -12,6 +12,7 @@ - `TextControl`: Deprecate 36px default size ([#66745](https://github.com/WordPress/gutenberg/pull/66745). - `FontSizePicker`: Deprecate 36px default size ([#66920](https://github.com/WordPress/gutenberg/pull/66920)). - `ComboboxControl`: Deprecate 36px default size ([#66900](https://github.com/WordPress/gutenberg/pull/66900)). +- `ToggleGroupControl`: Deprecate 36px default size ([#66747](https://github.com/WordPress/gutenberg/pull/66747)). ### Bug Fixes diff --git a/packages/components/src/font-size-picker/font-size-picker-toggle-group.tsx b/packages/components/src/font-size-picker/font-size-picker-toggle-group.tsx index 1e4cbcd1b72660..1b3619c800e453 100644 --- a/packages/components/src/font-size-picker/font-size-picker-toggle-group.tsx +++ b/packages/components/src/font-size-picker/font-size-picker-toggle-group.tsx @@ -19,6 +19,7 @@ const FontSizePickerToggleGroup = ( props: FontSizePickerToggleGroupProps ) => { <ToggleGroupControl __nextHasNoMarginBottom __next40pxDefaultSize={ __next40pxDefaultSize } + __shouldNotWarnDeprecated36pxSize label={ __( 'Font size' ) } hideLabelFromVision value={ value } diff --git a/packages/components/src/toggle-group-control/stories/index.story.tsx b/packages/components/src/toggle-group-control/stories/index.story.tsx index afdfa457f66348..bd6c67e2538870 100644 --- a/packages/components/src/toggle-group-control/stories/index.story.tsx +++ b/packages/components/src/toggle-group-control/stories/index.story.tsx @@ -51,6 +51,7 @@ const Template: StoryFn< typeof ToggleGroupControl > = ( { return ( <ToggleGroupControl __nextHasNoMarginBottom + __next40pxDefaultSize { ...props } onChange={ ( ...changeArgs ) => { setValue( ...changeArgs ); diff --git a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap index 832c6d7cb7a8c8..f344cd6ba16528 100644 --- a/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap +++ b/packages/components/src/toggle-group-control/test/__snapshots__/index.tsx.snap @@ -44,8 +44,8 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = display: inline-flex; min-width: 0; position: relative; - min-height: 36px; - padding: 2px; + min-height: 40px; + padding: 3px; } .emotion-8:hover { @@ -159,7 +159,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = width: 100%; z-index: 2; color: #1e1e1e; - height: 30px; + height: 32px; aspect-ratio: 1; padding-left: 0; padding-right: 0; @@ -236,7 +236,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] = width: 100%; z-index: 2; color: #1e1e1e; - height: 30px; + height: 32px; aspect-ratio: 1; padding-left: 0; padding-right: 0; @@ -409,8 +409,8 @@ exports[`ToggleGroupControl controlled should render correctly with text options display: inline-flex; min-width: 0; position: relative; - min-height: 36px; - padding: 2px; + min-height: 40px; + padding: 3px; } .emotion-8:hover { @@ -678,8 +678,8 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] display: inline-flex; min-width: 0; position: relative; - min-height: 36px; - padding: 2px; + min-height: 40px; + padding: 3px; } .emotion-8:hover { @@ -793,7 +793,7 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] width: 100%; z-index: 2; color: #1e1e1e; - height: 30px; + height: 32px; aspect-ratio: 1; padding-left: 0; padding-right: 0; @@ -870,7 +870,7 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`] width: 100%; z-index: 2; color: #1e1e1e; - height: 30px; + height: 32px; aspect-ratio: 1; padding-left: 0; padding-right: 0; @@ -1037,8 +1037,8 @@ exports[`ToggleGroupControl uncontrolled should render correctly with text optio display: inline-flex; min-width: 0; position: relative; - min-height: 36px; - padding: 2px; + min-height: 40px; + padding: 3px; } .emotion-8:hover { diff --git a/packages/components/src/toggle-group-control/test/index.tsx b/packages/components/src/toggle-group-control/test/index.tsx index 168e8f498958b5..44cfda69c423cf 100644 --- a/packages/components/src/toggle-group-control/test/index.tsx +++ b/packages/components/src/toggle-group-control/test/index.tsx @@ -28,7 +28,13 @@ const hoverOutside = async () => { }; const ToggleGroupControl = ( props: ToggleGroupControlProps ) => { - return <_ToggleGroupControl { ...props } __nextHasNoMarginBottom />; + return ( + <_ToggleGroupControl + { ...props } + __nextHasNoMarginBottom + __next40pxDefaultSize + /> + ); }; const ControlledToggleGroupControl = ( { diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option-icon/README.md b/packages/components/src/toggle-group-control/toggle-group-control-option-icon/README.md index a0e3a44cf74607..1ee82b26a91998 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option-icon/README.md +++ b/packages/components/src/toggle-group-control/toggle-group-control-option-icon/README.md @@ -17,7 +17,7 @@ import { formatLowercase, formatUppercase } from '@wordpress/icons'; function Example() { return ( - <ToggleGroupControl __nextHasNoMarginBottom> + <ToggleGroupControl __nextHasNoMarginBottom __next40pxDefaultSize> <ToggleGroupControlOptionIcon value="uppercase" icon={ formatUppercase } diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option-icon/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control-option-icon/component.tsx index 352b4acee71844..d1840cba5595d9 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option-icon/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control-option-icon/component.tsx @@ -52,7 +52,7 @@ function UnforwardedToggleGroupControlOptionIcon( * * function Example() { * return ( - * <ToggleGroupControl __nextHasNoMarginBottom> + * <ToggleGroupControl __nextHasNoMarginBottom __next40pxDefaultSize> * <ToggleGroupControlOptionIcon * value="uppercase" * label="Uppercase" diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option/README.md b/packages/components/src/toggle-group-control/toggle-group-control-option/README.md index 2e7c55bd688361..411857d260a311 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option/README.md +++ b/packages/components/src/toggle-group-control/toggle-group-control-option/README.md @@ -6,7 +6,6 @@ This feature is still experimental. “Experimental” means this is an early im `ToggleGroupControlOption` is a form component and is meant to be used as a child of [`ToggleGroupControl`](/packages/components/src/toggle-group-control/toggle-group-control/README.md). - ## Usage ```js @@ -22,6 +21,7 @@ function Example() { value="vertical" isBlock __nextHasNoMarginBottom + __next40pxDefaultSize > <ToggleGroupControlOption value="horizontal" diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control-option/component.tsx index b71d37e81cf25f..8632d92fc00578 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control-option/component.tsx @@ -53,6 +53,7 @@ function UnforwardedToggleGroupControlOption( * value="vertical" * isBlock * __nextHasNoMarginBottom + * __next40pxDefaultSize * > * <ToggleGroupControlOption value="horizontal" label="Horizontal" /> * <ToggleGroupControlOption value="vertical" label="Vertical" /> diff --git a/packages/components/src/toggle-group-control/toggle-group-control/README.md b/packages/components/src/toggle-group-control/toggle-group-control/README.md index ca5c5d14eb6b5a..841d474c148d45 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/README.md +++ b/packages/components/src/toggle-group-control/toggle-group-control/README.md @@ -25,6 +25,7 @@ function Example() { value="vertical" isBlock __nextHasNoMarginBottom + __next40pxDefaultSize > <ToggleGroupControlOption value="horizontal" label="Horizontal" /> <ToggleGroupControlOption value="vertical" label="Vertical" /> @@ -100,4 +101,4 @@ Start opting into the larger default height that will become the default size in Start opting into the new margin-free styles that will become the default in a future version. - Required: No -- Default: `false` \ No newline at end of file +- Default: `false` diff --git a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx index 0c3cadf210d84a..9f3427e95a6017 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx @@ -23,6 +23,7 @@ import { ToggleGroupControlAsButtonGroup } from './as-button-group'; import { useTrackElementOffsetRect } from '../../utils/element-rect'; import { useMergeRefs } from '@wordpress/compose'; import { useAnimatedOffsetRect } from '../../utils/hooks/use-animated-offset-rect'; +import { maybeWarnDeprecated36pxSize } from '../../utils/deprecated-36px-size'; function UnconnectedToggleGroupControl( props: WordPressComponentProps< ToggleGroupControlProps, 'div', false >, @@ -31,6 +32,7 @@ function UnconnectedToggleGroupControl( const { __nextHasNoMarginBottom = false, __next40pxDefaultSize = false, + __shouldNotWarnDeprecated36pxSize, className, isAdaptiveWidth = false, isBlock = false, @@ -81,6 +83,13 @@ function UnconnectedToggleGroupControl( ? ToggleGroupControlAsButtonGroup : ToggleGroupControlAsRadioGroup; + maybeWarnDeprecated36pxSize( { + componentName: 'ToggleGroupControl', + size, + __next40pxDefaultSize, + __shouldNotWarnDeprecated36pxSize, + } ); + return ( <BaseControl help={ help } @@ -135,6 +144,7 @@ function UnconnectedToggleGroupControl( * value="vertical" * isBlock * __nextHasNoMarginBottom + * __next40pxDefaultSize * > * <ToggleGroupControlOption value="horizontal" label="Horizontal" /> * <ToggleGroupControlOption value="vertical" label="Vertical" /> diff --git a/packages/components/src/toggle-group-control/types.ts b/packages/components/src/toggle-group-control/types.ts index 463d8d26e64410..cfa9d00080467c 100644 --- a/packages/components/src/toggle-group-control/types.ts +++ b/packages/components/src/toggle-group-control/types.ts @@ -128,6 +128,13 @@ export type ToggleGroupControlProps = Pick< * @default false */ __next40pxDefaultSize?: boolean; + /** + * Do not throw a warning for the deprecated 36px default size. + * For internal components of other components that already throw the warning. + * + * @ignore + */ + __shouldNotWarnDeprecated36pxSize?: boolean; }; export type ToggleGroupControlContextProps = { diff --git a/packages/components/src/tools-panel/stories/index.story.tsx b/packages/components/src/tools-panel/stories/index.story.tsx index 459932c9d22d7a..787585ac716b51 100644 --- a/packages/components/src/tools-panel/stories/index.story.tsx +++ b/packages/components/src/tools-panel/stories/index.story.tsx @@ -110,6 +110,7 @@ export const Default: StoryFn< typeof ToolsPanel > = ( { > <ToggleGroupControl __nextHasNoMarginBottom + __next40pxDefaultSize label="Scale" value={ scale } onChange={ ( next ) => setScale( next ) } @@ -457,6 +458,7 @@ export const WithConditionalDefaultControl: StoryFn< typeof ToolsPanel > = ( { > <ToggleGroupControl __nextHasNoMarginBottom + __next40pxDefaultSize label="Scale" value={ scale } onChange={ ( next ) => @@ -559,6 +561,7 @@ export const WithConditionallyRenderedControl: StoryFn< > <ToggleGroupControl __nextHasNoMarginBottom + __next40pxDefaultSize label="Scale" value={ scale } onChange={ ( next ) => diff --git a/packages/components/src/utils/deprecated-36px-size.ts b/packages/components/src/utils/deprecated-36px-size.ts index be5baa2515637c..0f87c2cd270c73 100644 --- a/packages/components/src/utils/deprecated-36px-size.ts +++ b/packages/components/src/utils/deprecated-36px-size.ts @@ -7,12 +7,15 @@ export function maybeWarnDeprecated36pxSize( { componentName, __next40pxDefaultSize, size, + __shouldNotWarnDeprecated36pxSize, }: { componentName: string; __next40pxDefaultSize: boolean | undefined; size: string | undefined; + __shouldNotWarnDeprecated36pxSize?: boolean; } ) { if ( + __shouldNotWarnDeprecated36pxSize || __next40pxDefaultSize || ( size !== undefined && size !== 'default' ) ) { From 603e5c0e44cf6e231ffbc40d00c2bb851b49b9ef Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 20 Nov 2024 17:51:45 +0000 Subject: [PATCH 1657/1908] Update Changelog for 19.7.0 --- changelog.txt | 291 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) diff --git a/changelog.txt b/changelog.txt index d9236e513469af..1a6b45a37fc7cf 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,296 @@ == Changelog == += 19.7.0 = + +## Changelog + +### Enhancements + +- Add "show template" to preview dropdown. ([66514](https://github.com/WordPress/gutenberg/pull/66514)) +- Iframe: Always enable for block themes, in core too. ([66800](https://github.com/WordPress/gutenberg/pull/66800)) +- Media Utils: Add experimental `sideloadMedia`. ([66378](https://github.com/WordPress/gutenberg/pull/66378)) +- Post fields: Clean up. ([66941](https://github.com/WordPress/gutenberg/pull/66941)) +- Post fields: Extract `title` from `edit-site` to `fields` package. ([66940](https://github.com/WordPress/gutenberg/pull/66940)) +- Post fields: Move `comment_status` from edit-site to fields package. ([66934](https://github.com/WordPress/gutenberg/pull/66934)) +- Post fields: Move `date` fields from `edit-site` to `fields` package. ([66938](https://github.com/WordPress/gutenberg/pull/66938)) +- Post fields: Move `status` from `edit-site` to `fields`. ([66937](https://github.com/WordPress/gutenberg/pull/66937)) +- Relocate “View” external link to end of editor header controls. ([66785](https://github.com/WordPress/gutenberg/pull/66785)) + +#### Block Library +- Added toggle control to set any image as feature image if no feature image is set for post. ([65896](https://github.com/WordPress/gutenberg/pull/65896)) +- Improve cover z-index solution. ([66249](https://github.com/WordPress/gutenberg/pull/66249)) +- Post Content: Add border and spacing support. ([66366](https://github.com/WordPress/gutenberg/pull/66366)) +- Query Loop: Use templateSlug and postType for more context. ([65820](https://github.com/WordPress/gutenberg/pull/65820)) +- Update text case of "Starter Content". ([66954](https://github.com/WordPress/gutenberg/pull/66954)) +- [Details Block]: Adds anchor support in details block. ([66734](https://github.com/WordPress/gutenberg/pull/66734)) + +#### Components +- Guide: Use small size button for page controls. ([66607](https://github.com/WordPress/gutenberg/pull/66607)) +- MenuItem: Add 40px size prop on Button. ([66596](https://github.com/WordPress/gutenberg/pull/66596)) +- Notice: Add appropriate size props to Buttons. ([66593](https://github.com/WordPress/gutenberg/pull/66593)) +- PaletteEdit: Add appropriate size props to Buttons. ([66590](https://github.com/WordPress/gutenberg/pull/66590)) +- Popover: Add small size prop to close button. ([66587](https://github.com/WordPress/gutenberg/pull/66587)) + +#### Global Styles +- Global styles revisions: Move focus and active state to list item. ([66780](https://github.com/WordPress/gutenberg/pull/66780)) +- Site editor: Integrate global styles controls and style book preview into the styles panel. ([65619](https://github.com/WordPress/gutenberg/pull/65619)) + +#### DataViews +- DataViews Fields API: Default getValueFromId supports nested objects. ([66890](https://github.com/WordPress/gutenberg/pull/66890)) + +#### Block Editor +- Inserter: Add 'Starter Content' category to the inserter. ([66819](https://github.com/WordPress/gutenberg/pull/66819)) + +#### Zoom Out +- Enable zoom out mode for non-iframe editor. ([66789](https://github.com/WordPress/gutenberg/pull/66789)) + +#### Themes +- Theme JSON Resolver: Remove theme json merge in resolve_theme_file_uris. ([66662](https://github.com/WordPress/gutenberg/pull/66662)) + +#### Edit Mode +- Image block: Add support for "more" dropdown for additional tools in Write mode. ([66605](https://github.com/WordPress/gutenberg/pull/66605)) + +#### Style Book +- Add a landing section to stylebook tabs. ([66545](https://github.com/WordPress/gutenberg/pull/66545)) + +#### Media +- Media Library: Expose filters dropdown for individual images, such as with the Image block. ([65965](https://github.com/WordPress/gutenberg/pull/65965)) + + +### Bug Fixes + +- Block toolbar: Restrict visible child calculation to known blocks. ([66702](https://github.com/WordPress/gutenberg/pull/66702)) +- ComplementaryArea: Fix button position. ([66677](https://github.com/WordPress/gutenberg/pull/66677)) +- Fix Paragraph appender layout shift (building on 66061). ([66779](https://github.com/WordPress/gutenberg/pull/66779)) +- Fix: Set the `fit-content` width for images that are not `.svg`. ([66643](https://github.com/WordPress/gutenberg/pull/66643)) +- Preference modal: Avoid fetching all reusable blocks when the site editor loads. ([66621](https://github.com/WordPress/gutenberg/pull/66621)) +- Revert "Set image width to `fit-content` to solve aspect ratio problems in Firefox. (#66217)". ([66804](https://github.com/WordPress/gutenberg/pull/66804)) +- Safari: Fix site editor template error. ([66647](https://github.com/WordPress/gutenberg/pull/66647)) +- Safari: Prevent focus capturing caused by flex display. ([66402](https://github.com/WordPress/gutenberg/pull/66402)) +- Select Mode: Hide tool selector in the post editor and force design mode. ([66784](https://github.com/WordPress/gutenberg/pull/66784)) +- Shadow panel: Make the delete modal text translatable. ([66712](https://github.com/WordPress/gutenberg/pull/66712)) +- Site Editor: Fix template for page-on-front option. ([66739](https://github.com/WordPress/gutenberg/pull/66739)) +- WP Scripts: Make watch mode more resilient for developer errors. ([66752](https://github.com/WordPress/gutenberg/pull/66752)) +- getDefaultTemplateId: Ensure entity configuration is loaded. ([66650](https://github.com/WordPress/gutenberg/pull/66650)) +- Comments controller: fix issue where comments are allowed when closed (https://github.com/WordPress/gutenberg/pull/66976) + +#### Block Library +- Cover: Fix media library image selection. ([66782](https://github.com/WordPress/gutenberg/pull/66782)) +- Cover: Show DropZone only when dragging withing the block. ([66912](https://github.com/WordPress/gutenberg/pull/66912)) +- Media & Text: Set `.wp-block-media-text__media a` display to block. ([66915](https://github.com/WordPress/gutenberg/pull/66915)) +- Prevent duplicate post format taxonomy queries. ([66627](https://github.com/WordPress/gutenberg/pull/66627)) +- Query Loop: Check for postTypeFromContext before using it. ([66655](https://github.com/WordPress/gutenberg/pull/66655)) +- Query Loop: Remove postTypeFromContext. ([66681](https://github.com/WordPress/gutenberg/pull/66681)) + +#### Block Editor +- Appender: Fix initial position. ([66711](https://github.com/WordPress/gutenberg/pull/66711)) +- Appender: Fix outside canvas styles. ([66630](https://github.com/WordPress/gutenberg/pull/66630)) +- Block Inspector: Restore bottom margin for RadioControl. ([66688](https://github.com/WordPress/gutenberg/pull/66688)) +- Iframed editor: Fix relative wp-content URLs. ([66751](https://github.com/WordPress/gutenberg/pull/66751)) + +#### Global Styles +- Section Styles: Fix insecure properties removal for inner block types and elements. ([66896](https://github.com/WordPress/gutenberg/pull/66896)) +- Style book: Reduce margin selector specificity so that it doesn't override global block styles. ([66895](https://github.com/WordPress/gutenberg/pull/66895)) +- Theme JSON: Replace top-level background style objects on merge. ([66656](https://github.com/WordPress/gutenberg/pull/66656)) + +#### Components +- FormTokenField: Fix token styles. ([66640](https://github.com/WordPress/gutenberg/pull/66640)) +- Storybook: Fix DataViews action modals. ([66727](https://github.com/WordPress/gutenberg/pull/66727)) +- ToggleGroupControl: Fix active background for `zero` value. ([66855](https://github.com/WordPress/gutenberg/pull/66855)) + +#### Post Editor +- Disable device preview button in pattern/template part/navitation editor. ([65970](https://github.com/WordPress/gutenberg/pull/65970)) +- PostTaxonomiesFlatTermSelector: Abstract wrapper component. ([66625](https://github.com/WordPress/gutenberg/pull/66625)) +- VisualEditor: Always output has-global-padding classname when in post only mode. ([66626](https://github.com/WordPress/gutenberg/pull/66626)) + +#### DataViews +- Fix TypeError when duplicating uncategorized theme patterns. ([66889](https://github.com/WordPress/gutenberg/pull/66889)) +- Tweak primary field in patterns grid layout. ([66733](https://github.com/WordPress/gutenberg/pull/66733)) + +#### Meta Boxes +- Fix: Show Meta Boxes at the bottom of the screen regardless of the current rendering mode. ([66508](https://github.com/WordPress/gutenberg/pull/66508)) +- Hide metaboxes in Zoom Out. ([66886](https://github.com/WordPress/gutenberg/pull/66886)) + +#### Site Editor +- DataViews: Fix 'aria-label' for pattern preview element. ([66601](https://github.com/WordPress/gutenberg/pull/66601)) +- Site Hub: Fixed navigation redirect on mobile devices for classic themes. ([66867](https://github.com/WordPress/gutenberg/pull/66867)) + +#### Media +- Add `x-wav` mime type for wav files in Firefox. ([66850](https://github.com/WordPress/gutenberg/pull/66850)) +- Ensure HEIC files selectable from “Upload” button. ([66292](https://github.com/WordPress/gutenberg/pull/66292)) + +#### Patterns +- Fix uncategorized pattern browsing when pattern has no categories. ([66945](https://github.com/WordPress/gutenberg/pull/66945)) + +#### Interactivity API +- Fix property modification from inherited context two or more levels above. ([66872](https://github.com/WordPress/gutenberg/pull/66872)) + +#### Block API +- Process Block Type: Copy deprecation to a new object instead of mutating when stabilizing supports. ([66849](https://github.com/WordPress/gutenberg/pull/66849)) + +#### Design Tools +- Block Gap: Fix block spacing control for axial gap supported blocks. ([66783](https://github.com/WordPress/gutenberg/pull/66783)) + +#### Document Settings +- Editor: Restore the 'PluginPostStatusInfo' slot position. ([66665](https://github.com/WordPress/gutenberg/pull/66665)) + +#### Templates API +- Fix flash when clicking template name in the editor when a plugin registered template matches a default WP theme template. ([66359](https://github.com/WordPress/gutenberg/pull/66359)) + +#### Block bindings +- Fix unset array key warning in block-bindings.php. ([66337](https://github.com/WordPress/gutenberg/pull/66337)) + + +### Accessibility + +- Fix : Snackbar Notice Inconsistency. ([66405](https://github.com/WordPress/gutenberg/pull/66405)) +- Image: Add `aria-haspopup` prop write mode `more` tools menu items. ([66815](https://github.com/WordPress/gutenberg/pull/66815)) +- Site Icon Focus fix. ([66952](https://github.com/WordPress/gutenberg/pull/66952)) + +#### Components +- Popover: Fix missing label of the headerTitle Close button. ([66813](https://github.com/WordPress/gutenberg/pull/66813)) + +#### Post Editor +- Fix inconsistent sidebars close buttons sizes. ([66756](https://github.com/WordPress/gutenberg/pull/66756)) + +#### Block Library +- Remove unnecessary tooltip from Video block Text tracks button. ([66716](https://github.com/WordPress/gutenberg/pull/66716)) + +#### Block Editor +- Speak 'Block moved up/down' after using keyboard actions to move up/down. ([64966](https://github.com/WordPress/gutenberg/pull/64966)) + +#### Patterns +- Block Patterns List: Fix visual title and tooltip inconsistencies. ([64815](https://github.com/WordPress/gutenberg/pull/64815)) + + +### Performance + +- Inline Commenting: Avoid querying comments on editor load. ([66670](https://github.com/WordPress/gutenberg/pull/66670)) +- Patterns: Receive intermediate responses while unbound request is resolving. ([66713](https://github.com/WordPress/gutenberg/pull/66713)) +- Perf metrics: Update select and other metrics to use non-empty paragraphs. ([66762](https://github.com/WordPress/gutenberg/pull/66762)) +- Site Editor: Preload settings requests. ([66488](https://github.com/WordPress/gutenberg/pull/66488)) +- Site Editor: Speed up load by preloading home and front-page templates. ([66579](https://github.com/WordPress/gutenberg/pull/66579)) +- Site editor: Preload post if needed. ([66631](https://github.com/WordPress/gutenberg/pull/66631)) + +#### Global Styles +- Preload user global styles based on user caps. ([66541](https://github.com/WordPress/gutenberg/pull/66541)) + + +### Experiments + +- Add `isVisible` option to fields within DataForm. ([65826](https://github.com/WordPress/gutenberg/pull/65826)) +- DataViews: Implement `isItemClickable` and `onClickItem` props. ([66365](https://github.com/WordPress/gutenberg/pull/66365)) + +#### DataViews +- Quick Edit - Slug Field: Improve slug preview. ([66559](https://github.com/WordPress/gutenberg/pull/66559)) +- QuickEdit: Add password field data to the pages quick edit. ([66567](https://github.com/WordPress/gutenberg/pull/66567)) + + +### Documentation + +- Add 6.6.2 to Version in WordPress. ([66870](https://github.com/WordPress/gutenberg/pull/66870)) +- Add missing properties for DataViews/DataForm components. ([66749](https://github.com/WordPress/gutenberg/pull/66749)) +- Add section about the Fields API. ([66761](https://github.com/WordPress/gutenberg/pull/66761)) +- Block Bindings: Documentation API reference. ([66251](https://github.com/WordPress/gutenberg/pull/66251)) +- Docs: Include a note about supported licenses in WordPress packages. ([66562](https://github.com/WordPress/gutenberg/pull/66562)) +- Document `filterSortAndPaginate` & `isItemValid` utilities. ([66738](https://github.com/WordPress/gutenberg/pull/66738)) +- Feat: Storybook: Improve component organisation - Navigation Category - Issue #66275. ([66658](https://github.com/WordPress/gutenberg/pull/66658)) +- Feat: Storybook: Improve component organisation - Overlays Category - Issue #66275. ([66657](https://github.com/WordPress/gutenberg/pull/66657)) +- Feat: Storybook: Improve component organisation - Selection & Input Category - Issue #66275. ([66660](https://github.com/WordPress/gutenberg/pull/66660)) +- Feat: Storybook: Improve component organisation - Typography - Issue #66275. ([66633](https://github.com/WordPress/gutenberg/pull/66633)) +- Improve readability of DataViews documentation. ([66766](https://github.com/WordPress/gutenberg/pull/66766)) +- Move documentation for filter operators to proper place. ([66743](https://github.com/WordPress/gutenberg/pull/66743)) +- Reorganize to bootstrap DataForm API section. ([66729](https://github.com/WordPress/gutenberg/pull/66729)) +- Storybook: Improve component organisation - Actions. ([66680](https://github.com/WordPress/gutenberg/pull/66680)) +- Storybook: Log `warning()` when in dev mode. ([66568](https://github.com/WordPress/gutenberg/pull/66568)) +- Update Commands documentation with the existing contexts. ([66860](https://github.com/WordPress/gutenberg/pull/66860)) + + +### Code Quality + +- BlockPatternsList: Use the Async component. ([66744](https://github.com/WordPress/gutenberg/pull/66744)) +- Core Commands: Fix add new post URL assignment. ([66830](https://github.com/WordPress/gutenberg/pull/66830)) +- Inline Commenting: Optimize store selector and misc changes. ([66592](https://github.com/WordPress/gutenberg/pull/66592)) +- Remove unnecessary boolean assignments. ([66857](https://github.com/WordPress/gutenberg/pull/66857)) +- TypeScript: Fix and improve types for private-apis. ([66667](https://github.com/WordPress/gutenberg/pull/66667)) + +#### Block Editor +- Fix 'useSelect' dependencies for the 'RichText' component. ([66964](https://github.com/WordPress/gutenberg/pull/66964)) +- Fix ESLint warning for 'useBlockTypesState' hook. ([66757](https://github.com/WordPress/gutenberg/pull/66757)) +- Fix React Compiler error for 'BlockProps' util component. ([66809](https://github.com/WordPress/gutenberg/pull/66809)) +- Optimize `getVisibleElementBounds` in scrollable cases. ([66546](https://github.com/WordPress/gutenberg/pull/66546)) +- Revert: Fix unable to remove empty blocks on merge (#65262) + alternative. ([66564](https://github.com/WordPress/gutenberg/pull/66564)) +- URLInput: Fix incorrect classname for suggestions. ([66714](https://github.com/WordPress/gutenberg/pull/66714)) + +#### Site Editor +- Avoid using edited entity state in site editor loading hook. ([66924](https://github.com/WordPress/gutenberg/pull/66924)) +- Avoid using edited post selectors in welcome guide. ([66926](https://github.com/WordPress/gutenberg/pull/66926)) +- Edit Site: Refactor to remove usage of edited entity state. ([66922](https://github.com/WordPress/gutenberg/pull/66922)) +- Edit Site: Remove leftover 'priority-queue' dependency. ([66773](https://github.com/WordPress/gutenberg/pull/66773)) +- Remove useEditedEntityRecord hook. ([66955](https://github.com/WordPress/gutenberg/pull/66955)) + +#### Components +- Fix React Compiler error for 'useScrollRectIntoView'. ([66498](https://github.com/WordPress/gutenberg/pull/66498)) +- Panel: Add 40px size prop to Button. ([66589](https://github.com/WordPress/gutenberg/pull/66589)) +- Radio: Deprecate 36px default size. ([66572](https://github.com/WordPress/gutenberg/pull/66572)) +- Snackbar: Use `link` variant for action Button. ([66560](https://github.com/WordPress/gutenberg/pull/66560)) + +#### Data Layer +- Convert the emitter module in data package to TS. ([66669](https://github.com/WordPress/gutenberg/pull/66669)) +- Data: Rename useSelect internals to fix React Compiler violations. ([66807](https://github.com/WordPress/gutenberg/pull/66807)) +- Data: Upgrade Redux to v5.0.1. ([66966](https://github.com/WordPress/gutenberg/pull/66966)) + +#### Post Editor +- ESLint: Fix React Compiler violations in various commands. ([66787](https://github.com/WordPress/gutenberg/pull/66787)) +- Fix TS types for editor package. ([66754](https://github.com/WordPress/gutenberg/pull/66754)) + +#### Zoom Out +- Zoom-out: Move default background to the iframe component. ([66284](https://github.com/WordPress/gutenberg/pull/66284)) + +#### Design Tools +- Typography: Stabilize typography block supports within block processing. ([63401](https://github.com/WordPress/gutenberg/pull/63401)) + + +### Tools + +#### Testing +- Media: Check for `wav` mime type using isset. ([66947](https://github.com/WordPress/gutenberg/pull/66947)) + +#### Build Tooling +- Enforce the same order of fields in `package.json` files. ([66239](https://github.com/WordPress/gutenberg/pull/66239)) +- Introduce React Scanner for component usage stats. ([65463](https://github.com/WordPress/gutenberg/pull/65463)) + + +### Various + +- Style engine: Wrap array_merge in conditionals to prevent unnecessary merging. ([66661](https://github.com/WordPress/gutenberg/pull/66661)) + +#### Block Library +- Update placeholder text for blocks that support drag and drop. ([66842](https://github.com/WordPress/gutenberg/pull/66842)) +- update: Add Media to Add media in cover block. ([66835](https://github.com/WordPress/gutenberg/pull/66835)) + + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @benharri: Fix unset array key warning in block-bindings.php. ([66337](https://github.com/WordPress/gutenberg/pull/66337)) +- @benniledl: Add 6.6.2 to Version in WordPress. ([66870](https://github.com/WordPress/gutenberg/pull/66870)) +- @Infinite-Null: Media & Text: Set `.wp-block-media-text__media a` display to block. ([66915](https://github.com/WordPress/gutenberg/pull/66915)) +- @karthick-murugan: Site Icon Focus fix. ([66952](https://github.com/WordPress/gutenberg/pull/66952)) +- @rinkalpagdar: Post Content: Add border and spacing support. ([66366](https://github.com/WordPress/gutenberg/pull/66366)) +- @yogeshbhutkar: Site Hub: Fixed navigation redirect on mobile devices for classic themes. ([66867](https://github.com/WordPress/gutenberg/pull/66867)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @adamsilverstein @afercia @Aljullu @amitraj2203 @andrewserong @benharri @benniledl @carolinan @cbravobernal @DAreRodz @dcalhoun @ellatrix @fabiankaegy @gigitux @gziolo @hbhalodia @Infinite-Null @jasmussen @jorgefilipecosta @jsnajdr @juanfra @karthick-murugan @kevin940726 @louwie17 @Mamaduka @manzoorwanijk @matiasbenedetto @mikachan @mirka @n2erjo00 @ntsekouras @oandregal @ramonjd @renatho @rinkalpagdar @Soean @stokesman @swissspidy @t-hamano @tellthemachines @tyxla @up1512001 @Vrishabhsk @yogeshbhutkar @youknowriad + + + + = 19.6.4 = - PostTaxonomiesFlatTermSelector: abstract wrapper component (#66625) From d57502ee6bad7bd6bf352a73700ba2e61d79c3ef Mon Sep 17 00:00:00 2001 From: Bernie Reiter <96308+ockham@users.noreply.github.com> Date: Wed, 20 Nov 2024 19:57:53 +0100 Subject: [PATCH 1658/1908] Navigation Block: Remove obsolete Block Hooks filters (#64676) --- .../block-library/src/navigation/index.php | 150 ------------------ .../block-navigation-block-hooks-test.php | 148 ----------------- 2 files changed, 298 deletions(-) delete mode 100644 phpunit/blocks/block-navigation-block-hooks-test.php diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index dd300eb12c6feb..ae3b9620a33584 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -1520,153 +1520,3 @@ function block_core_navigation_insert_hooked_blocks( $inner_blocks, $post ) { return traverse_and_serialize_block( $mock_navigation_block, $before_block_visitor, $after_block_visitor ); } - -/** - * Insert ignoredHookedBlocks meta into the Navigation block and its inner blocks. - * - * Given a Navigation block's inner blocks and its corresponding `wp_navigation` post object, - * this function inserts ignoredHookedBlocks meta into it, and returns the serialized inner blocks in a - * mock Navigation block wrapper. - * - * @since 6.5.0 - * - * @param array $inner_blocks Parsed inner blocks of a Navigation block. - * @param WP_Post $post `wp_navigation` post object corresponding to the block. - * @return string Serialized inner blocks in mock Navigation block wrapper, with hooked blocks inserted, if any. - */ -function block_core_navigation_set_ignored_hooked_blocks_metadata( $inner_blocks, $post ) { - $mock_navigation_block = block_core_navigation_mock_parsed_block( $inner_blocks, $post ); - $hooked_blocks = get_hooked_blocks(); - $before_block_visitor = null; - $after_block_visitor = null; - - if ( ! empty( $hooked_blocks ) || has_filter( 'hooked_block_types' ) ) { - $before_block_visitor = make_before_block_visitor( $hooked_blocks, $post, 'set_ignored_hooked_blocks_metadata' ); - $after_block_visitor = make_after_block_visitor( $hooked_blocks, $post, 'set_ignored_hooked_blocks_metadata' ); - } - - return traverse_and_serialize_block( $mock_navigation_block, $before_block_visitor, $after_block_visitor ); -} - -/** - * Updates the post meta with the list of ignored hooked blocks when the navigation is created or updated via the REST API. - * - * @access private - * @since 6.5.0 - * - * @param stdClass $post Post object. - * @return stdClass The updated post object. - */ -function block_core_navigation_update_ignore_hooked_blocks_meta( $post ) { - /* - * In this scenario the user has likely tried to create a navigation via the REST API. - * In which case we won't have a post ID to work with and store meta against. - */ - if ( empty( $post->ID ) ) { - return $post; - } - - /** - * Skip meta generation when consumers intentionally update specific Navigation fields - * and omit the content update. - */ - if ( ! isset( $post->post_content ) ) { - return $post; - } - - /* - * We run the Block Hooks mechanism to inject the `metadata.ignoredHookedBlocks` attribute into - * all anchor blocks. For the root level, we create a mock Navigation and extract them from there. - */ - $blocks = parse_blocks( $post->post_content ); - - /* - * Block Hooks logic requires a `WP_Post` object (rather than the `stdClass` with the updates that - * we're getting from the `rest_pre_insert_wp_navigation` filter) as its second argument (to be - * used as context for hooked blocks insertion). - * We thus have to look it up from the DB,based on `$post->ID`. - */ - $markup = block_core_navigation_set_ignored_hooked_blocks_metadata( $blocks, get_post( $post->ID ) ); - - $root_nav_block = parse_blocks( $markup )[0]; - $ignored_hooked_blocks = isset( $root_nav_block['attrs']['metadata']['ignoredHookedBlocks'] ) - ? $root_nav_block['attrs']['metadata']['ignoredHookedBlocks'] - : array(); - - if ( ! empty( $ignored_hooked_blocks ) ) { - $existing_ignored_hooked_blocks = get_post_meta( $post->ID, '_wp_ignored_hooked_blocks', true ); - if ( ! empty( $existing_ignored_hooked_blocks ) ) { - $existing_ignored_hooked_blocks = json_decode( $existing_ignored_hooked_blocks, true ); - $ignored_hooked_blocks = array_unique( array_merge( $ignored_hooked_blocks, $existing_ignored_hooked_blocks ) ); - } - update_post_meta( $post->ID, '_wp_ignored_hooked_blocks', json_encode( $ignored_hooked_blocks ) ); - } - - $post->post_content = block_core_navigation_remove_serialized_parent_block( $markup ); - return $post; -} - -/* - * Before adding our filter, we verify if it's already added in Core. - * However, during the build process, Gutenberg automatically prefixes our functions with "gutenberg_". - * Therefore, we concatenate the Core's function name to circumvent this prefix for our check. - */ -$rest_insert_wp_navigation_core_callback = 'block_core_navigation_' . 'update_ignore_hooked_blocks_meta'; // phpcs:ignore Generic.Strings.UnnecessaryStringConcat.Found - -/* - * Do not add the `block_core_navigation_update_ignore_hooked_blocks_meta` filter in the following cases: - * - If Core has added the `update_ignored_hooked_blocks_postmeta` filter already (WP >= 6.6); - * - or if the `$rest_insert_wp_navigation_core_callback` filter has already been added. - */ -if ( - ! has_filter( 'rest_pre_insert_wp_navigation', 'update_ignored_hooked_blocks_postmeta' ) && - ! has_filter( 'rest_pre_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ) -) { - add_filter( 'rest_pre_insert_wp_navigation', 'block_core_navigation_update_ignore_hooked_blocks_meta' ); -} - -/** - * Hooks into the REST API response for the core/navigation block and adds the first and last inner blocks. - * - * @since 6.5.0 - * - * @param WP_REST_Response $response The response object. - * @param WP_Post $post Post object. - * @return WP_REST_Response The response object. - */ -function block_core_navigation_insert_hooked_blocks_into_rest_response( $response, $post ) { - if ( ! isset( $response->data['content']['raw'] ) || ! isset( $response->data['content']['rendered'] ) ) { - return $response; - } - $parsed_blocks = parse_blocks( $response->data['content']['raw'] ); - $content = block_core_navigation_insert_hooked_blocks( $parsed_blocks, $post ); - - // Remove mock Navigation block wrapper. - $content = block_core_navigation_remove_serialized_parent_block( $content ); - - $response->data['content']['raw'] = $content; - - /** This filter is documented in wp-includes/post-template.php */ - $response->data['content']['rendered'] = apply_filters( 'the_content', $content ); - - return $response; -} - -/* - * Before adding our filter, we verify if it's already added in Core. - * However, during the build process, Gutenberg automatically prefixes our functions with "gutenberg_". - * Therefore, we concatenate the Core's function name to circumvent this prefix for our check. - */ -$rest_prepare_wp_navigation_core_callback = 'block_core_navigation_' . 'insert_hooked_blocks_into_rest_response'; - -/* - * Do not add the `block_core_navigation_insert_hooked_blocks_into_rest_response` filter in the following cases: - * - If Core has added the `insert_hooked_blocks_into_rest_response` filter already (WP >= 6.6); - * - or if the `$rest_prepare_wp_navigation_core_callback` filter has already been added. - */ -if ( - ! has_filter( 'rest_prepare_wp_navigation', 'insert_hooked_blocks_into_rest_response' ) && - ! has_filter( 'rest_prepare_wp_navigation', $rest_prepare_wp_navigation_core_callback ) -) { - add_filter( 'rest_prepare_wp_navigation', 'block_core_navigation_insert_hooked_blocks_into_rest_response', 10, 3 ); -} diff --git a/phpunit/blocks/block-navigation-block-hooks-test.php b/phpunit/blocks/block-navigation-block-hooks-test.php deleted file mode 100644 index 1d3c86bf4bca4b..00000000000000 --- a/phpunit/blocks/block-navigation-block-hooks-test.php +++ /dev/null @@ -1,148 +0,0 @@ -<?php -/** - * Navigation block block hooks tests. - * - * @package WordPress - * @subpackage Blocks - */ - -/** - * Tests for the Navigation block. - * - * @group blocks - */ -class Block_Navigation_Block_Hooks_Test extends WP_UnitTestCase { - /** - * Original markup. - * - * @var string - */ - protected static $original_markup; - - /** - * Post object. - * - * @var object - */ - protected static $navigation_post; - - /** - * Setup method. - */ - public static function wpSetUpBeforeClass() { - //self::$original_markup = '<!-- wp:navigation-link {"label":"News & About","type":"page","id":2,"url":"http://localhost:8888/?page_id=2","kind":"post-type"} /-->'; - - self::$navigation_post = self::factory()->post->create_and_get( - array( - 'post_type' => 'wp_navigation', - 'post_title' => 'Navigation Menu', - 'post_content' => 'Original content', - ) - ); - } - - /** - * Tear down each test method. - */ - public function tear_down() { - $registry = WP_Block_Type_Registry::get_instance(); - - if ( $registry->is_registered( 'tests/my-block' ) ) { - $registry->unregister( 'tests/my-block' ); - } - - parent::tear_down(); - } - - /** - * @covers ::gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta - */ - public function test_block_core_navigation_update_ignore_hooked_blocks_meta_preserves_entities() { - register_block_type( - 'tests/my-block', - array( - 'block_hooks' => array( - 'core/navigation' => 'last_child', - ), - ) - ); - - $original_markup = '<!-- wp:navigation-link {"label":"News & About","type":"page","id":2,"url":"http://localhost:8888/?page_id=2","kind":"post-type"} /-->'; - $post = new stdClass(); - $post->ID = self::$navigation_post->ID; - $post->post_content = $original_markup; - - $post = gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta( $post ); - - // We expect the '&' character to be replaced with its unicode representation. - $expected_markup = str_replace( '&', '\u0026', $original_markup ); - - $this->assertSame( - $expected_markup, - $post->post_content, - 'Post content did not match expected markup with entities escaped.' - ); - $this->assertSame( - array( 'tests/my-block' ), - json_decode( get_post_meta( self::$navigation_post->ID, '_wp_ignored_hooked_blocks', true ), true ), - 'Block was not added to ignored hooked blocks metadata.' - ); - } - - /** - * @covers ::gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta - */ - public function test_block_core_navigation_dont_modify_no_post_id() { - register_block_type( - 'tests/my-block', - array( - 'block_hooks' => array( - 'core/navigation' => 'last_child', - ), - ) - ); - - $original_markup = '<!-- wp:navigation-link {"label":"News","type":"page","id":2,"url":"http://localhost:8888/?page_id=2","kind":"post-type"} /-->'; - $post = new stdClass(); - $post->post_content = $original_markup; - - $post = gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta( $post ); - - $this->assertSame( - $original_markup, - $post->post_content, - 'Post content did not match the original markup.' - ); - } - - /** - * @covers ::gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta - */ - public function test_block_core_navigation_retains_content_if_not_set() { - register_block_type( - 'tests/my-block', - array( - 'block_hooks' => array( - 'core/navigation' => 'last_child', - ), - ) - ); - - $post = new stdClass(); - $post->ID = self::$navigation_post->ID; - $post->post_title = 'Navigation Menu with changes'; - - $post = gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta( $post ); - - $this->assertSame( - 'Navigation Menu with changes', - $post->post_title, - 'Post title was changed.' - ); - - $this->assertFalse( - isset( $post->post_content ), - 'Post content should not be set.' - ); - } -} From b7d989e0dafb23866f65295a851e6b8734c3b693 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Thu, 21 Nov 2024 13:58:58 +0800 Subject: [PATCH 1659/1908] Fix typo in use-block-sync tests (#67145) Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/components/provider/test/use-block-sync.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/provider/test/use-block-sync.js b/packages/block-editor/src/components/provider/test/use-block-sync.js index aae5e517c63029..b2afdb942e66fa 100644 --- a/packages/block-editor/src/components/provider/test/use-block-sync.js +++ b/packages/block-editor/src/components/provider/test/use-block-sync.js @@ -22,7 +22,9 @@ jest.mock( '../../../store/actions', () => { ...actions, resetBlocks: jest.fn( actions.resetBlocks ), replaceInnerBlocks: jest.fn( actions.replaceInnerBlocks ), - setHasControlledInnerBlocks: jest.fn( actions.replaceInnerBlocks ), + setHasControlledInnerBlocks: jest.fn( + actions.setHasControlledInnerBlocks + ), }; } ); From afb05e8b9c2dbdc43c119f2c756f57620a4febfc Mon Sep 17 00:00:00 2001 From: Miguel Fonseca <150562+mcsf@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:41:53 +0000 Subject: [PATCH 1660/1908] useBlockNameForPatterns: Refactor as a single useSelect call (#67171) --- packages/block-library/src/query/utils.js | 29 +++++++++++------------ 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/block-library/src/query/utils.js b/packages/block-library/src/query/utils.js index fc22ca46d471c0..e12fdc8d8a7e89 100644 --- a/packages/block-library/src/query/utils.js +++ b/packages/block-library/src/query/utils.js @@ -272,32 +272,31 @@ export const getTransformedBlocksFromPattern = ( * @return {string} The block name to be used in the patterns suggestions. */ export function useBlockNameForPatterns( clientId, attributes ) { - const activeVariationName = useSelect( - ( select ) => - select( blocksStore ).getActiveBlockVariation( - 'core/query', - attributes - )?.name, - [ attributes ] - ); - const blockName = `core/query/${ activeVariationName }`; - const hasActiveVariationPatterns = useSelect( + return useSelect( ( select ) => { + const activeVariationName = select( + blocksStore + ).getActiveBlockVariation( 'core/query', attributes )?.name; + if ( ! activeVariationName ) { - return false; + return 'core/query'; } + const { getBlockRootClientId, getPatternsByBlockTypes } = select( blockEditorStore ); + const rootClientId = getBlockRootClientId( clientId ); const activePatterns = getPatternsByBlockTypes( - blockName, + `core/query/${ activeVariationName }`, rootClientId ); - return activePatterns.length > 0; + + return activePatterns.length > 0 + ? `core/query/${ activeVariationName }` + : 'core/query'; }, - [ clientId, activeVariationName, blockName ] + [ clientId, attributes ] ); - return hasActiveVariationPatterns ? blockName : 'core/query'; } /** From b5732a58e930f28cb8aa34d2d1d2ca741e2abd93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:15:26 +0100 Subject: [PATCH 1661/1908] DataViews: fix action visibility logic (#67197) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../dataviews/src/components/dataviews-item-actions/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataviews/src/components/dataviews-item-actions/index.tsx b/packages/dataviews/src/components/dataviews-item-actions/index.tsx index 47e65bc81cb171..787cef4420acc0 100644 --- a/packages/dataviews/src/components/dataviews-item-actions/index.tsx +++ b/packages/dataviews/src/components/dataviews-item-actions/index.tsx @@ -190,7 +190,7 @@ function hasOnlyOneActionAndIsPrimary< Item >( primaryActions: Action< Item >[], actions: Action< Item >[] ) { - return primaryActions.length === 1 && actions.length; + return primaryActions.length === 1 && actions.length === 1; } export default function ItemActions< Item >( { From ec4b881cf89a426772b10f265b400f701751ffd5 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Thu, 21 Nov 2024 15:10:24 +0200 Subject: [PATCH 1662/1908] Place "Write mode" functionality behind a Gutenberg experiment (#67008) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- lib/experimental/editor-settings.php | 3 + lib/experiments-page.php | 12 ++ packages/block-editor/src/store/selectors.js | 3 + .../block-editor/src/store/test/selectors.js | 145 +++++++++++------- .../src/components/document-tools/index.js | 5 +- .../editor/various/write-design-mode.spec.js | 8 +- test/e2e/specs/site-editor/style-book.spec.js | 3 + 7 files changed, 115 insertions(+), 64 deletions(-) diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index afc6d7e220f676..5b36c32b3c8296 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -37,6 +37,9 @@ function gutenberg_enable_experiments() { if ( $gutenberg_experiments && array_key_exists( 'gutenberg-media-processing', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalMediaProcessing = true', 'before' ); } + if ( $gutenberg_experiments && array_key_exists( 'gutenberg-editor-write-mode', $gutenberg_experiments ) ) { + wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEditorWriteMode = true', 'before' ); + } } add_action( 'admin_init', 'gutenberg_enable_experiments' ); diff --git a/lib/experiments-page.php b/lib/experiments-page.php index 946b68283a3e0b..9033e3c2d0c1fb 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -187,6 +187,18 @@ function gutenberg_initialize_experiments_settings() { ) ); + add_settings_field( + 'gutenberg-editor-write-mode', + __( 'Editor write mode', 'gutenberg' ), + 'gutenberg_display_experiment_field', + 'gutenberg-experiments', + 'gutenberg_experiments_section', + array( + 'label' => __( 'Enable write mode in editor.', 'gutenberg' ), + 'id' => 'gutenberg-editor-write-mode', + ) + ); + register_setting( 'gutenberg-experiments', 'gutenberg-experiments' diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 598b6b4ea480de..ac1d178f43de7c 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2774,6 +2774,9 @@ export function isNavigationMode( state ) { */ export const __unstableGetEditorMode = createRegistrySelector( ( select ) => ( state ) => { + if ( ! window?.__experimentalEditorWriteMode ) { + return 'edit'; + } return ( state.settings.editorTool ?? select( preferencesStore ).get( 'core', 'editorTool' ) diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index 00aa085f667093..7c0361449c5fca 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -4615,68 +4615,97 @@ describe( 'getBlockEditingMode', () => { ).toBe( 'contentOnly' ); } ); - it( 'in navigation mode, the root section container is default', () => { - dispatch( preferencesStore ).set( 'core', 'editorTool', 'navigation' ); - expect( - getBlockEditingMode( - navigationModeStateWithRootSection, - 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337' - ) - ).toBe( 'default' ); - } ); + describe( 'navigation mode', () => { + const writeModeExperiment = window.__experimentalEditorWriteMode; + beforeAll( () => { + window.__experimentalEditorWriteMode = true; + } ); + afterAll( () => { + window.__experimentalEditorWriteMode = writeModeExperiment; + } ); + it( 'in navigation mode, the root section container is default', () => { + dispatch( preferencesStore ).set( + 'core', + 'editorTool', + 'navigation' + ); + expect( + getBlockEditingMode( + navigationModeStateWithRootSection, + 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337' + ) + ).toBe( 'default' ); + } ); - it( 'in navigation mode, anything outside the section container is disabled', () => { - dispatch( preferencesStore ).set( 'core', 'editorTool', 'navigation' ); - expect( - getBlockEditingMode( - navigationModeStateWithRootSection, - '6cf70164-9097-4460-bcbf-200560546988' - ) - ).toBe( 'disabled' ); - } ); + it( 'in navigation mode, anything outside the section container is disabled', () => { + dispatch( preferencesStore ).set( + 'core', + 'editorTool', + 'navigation' + ); + expect( + getBlockEditingMode( + navigationModeStateWithRootSection, + '6cf70164-9097-4460-bcbf-200560546988' + ) + ).toBe( 'disabled' ); + } ); - it( 'in navigation mode, sections are contentOnly', () => { - dispatch( preferencesStore ).set( 'core', 'editorTool', 'navigation' ); - expect( - getBlockEditingMode( - navigationModeStateWithRootSection, - 'b26fc763-417d-4f01-b81c-2ec61e14a972' - ) - ).toBe( 'contentOnly' ); - expect( - getBlockEditingMode( - navigationModeStateWithRootSection, - '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f' - ) - ).toBe( 'contentOnly' ); - } ); + it( 'in navigation mode, sections are contentOnly', () => { + dispatch( preferencesStore ).set( + 'core', + 'editorTool', + 'navigation' + ); + expect( + getBlockEditingMode( + navigationModeStateWithRootSection, + 'b26fc763-417d-4f01-b81c-2ec61e14a972' + ) + ).toBe( 'contentOnly' ); + expect( + getBlockEditingMode( + navigationModeStateWithRootSection, + '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f' + ) + ).toBe( 'contentOnly' ); + } ); - it( 'in navigation mode, blocks with content attributes within sections are contentOnly', () => { - dispatch( preferencesStore ).set( 'core', 'editorTool', 'navigation' ); - hasContentRoleAttribute.mockReturnValueOnce( true ); - expect( - getBlockEditingMode( - navigationModeStateWithRootSection, - 'b3247f75-fd94-4fef-97f9-5bfd162cc416' - ) - ).toBe( 'contentOnly' ); + it( 'in navigation mode, blocks with content attributes within sections are contentOnly', () => { + dispatch( preferencesStore ).set( + 'core', + 'editorTool', + 'navigation' + ); + hasContentRoleAttribute.mockReturnValueOnce( true ); + expect( + getBlockEditingMode( + navigationModeStateWithRootSection, + 'b3247f75-fd94-4fef-97f9-5bfd162cc416' + ) + ).toBe( 'contentOnly' ); - hasContentRoleAttribute.mockReturnValueOnce( true ); - expect( - getBlockEditingMode( - navigationModeStateWithRootSection, - 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c' - ) - ).toBe( 'contentOnly' ); - } ); + hasContentRoleAttribute.mockReturnValueOnce( true ); + expect( + getBlockEditingMode( + navigationModeStateWithRootSection, + 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c' + ) + ).toBe( 'contentOnly' ); + } ); - it( 'in navigation mode, blocks without content attributes within sections are disabled', () => { - dispatch( preferencesStore ).set( 'core', 'editorTool', 'navigation' ); - expect( - getBlockEditingMode( - navigationModeStateWithRootSection, - '9b9c5c3f-2e46-4f02-9e14-9fed515b958s' - ) - ).toBe( 'disabled' ); + it( 'in navigation mode, blocks without content attributes within sections are disabled', () => { + dispatch( preferencesStore ).set( + 'core', + 'editorTool', + 'navigation' + ); + expect( + getBlockEditingMode( + navigationModeStateWithRootSection, + '9b9c5c3f-2e46-4f02-9e14-9fed515b958s' + ) + ).toBe( 'disabled' ); + } ); } ); } ); diff --git a/packages/editor/src/components/document-tools/index.js b/packages/editor/src/components/document-tools/index.js index 74118caaf5849c..a98def685e93a6 100644 --- a/packages/editor/src/components/document-tools/index.js +++ b/packages/editor/src/components/document-tools/index.js @@ -60,8 +60,9 @@ function DocumentTools( { className, disableBlockTools = false } ) { isDistractionFree: get( 'core', 'distractionFree' ), isVisualMode: getEditorMode() === 'visual', showTools: - getRenderingMode() !== 'post-only' || - getCurrentPostType() === 'wp_template', + !! window?.__experimentalEditorWriteMode && + ( getRenderingMode() !== 'post-only' || + getCurrentPostType() === 'wp_template' ), }; }, [] ); diff --git a/test/e2e/specs/editor/various/write-design-mode.spec.js b/test/e2e/specs/editor/various/write-design-mode.spec.js index 2116f9042685af..053f4cb8ff092a 100644 --- a/test/e2e/specs/editor/various/write-design-mode.spec.js +++ b/test/e2e/specs/editor/various/write-design-mode.spec.js @@ -7,19 +7,19 @@ test.describe( 'Write/Design mode', () => { test.beforeAll( async ( { requestUtils } ) => { await requestUtils.activateTheme( 'emptytheme' ); } ); - - test.beforeEach( async ( { admin } ) => { + test.beforeEach( async ( { admin, page } ) => { + await page.addInitScript( () => { + window.__experimentalEditorWriteMode = true; + } ); await admin.visitSiteEditor( { postId: 'emptytheme//index', postType: 'wp_template', canvas: 'edit', } ); } ); - test.afterAll( async ( { requestUtils } ) => { await requestUtils.activateTheme( 'twentytwentyone' ); } ); - test( 'Should prevent selecting intermediary blocks', async ( { editor, page, diff --git a/test/e2e/specs/site-editor/style-book.spec.js b/test/e2e/specs/site-editor/style-book.spec.js index d860b05bc8f06d..38030892826ec7 100644 --- a/test/e2e/specs/site-editor/style-book.spec.js +++ b/test/e2e/specs/site-editor/style-book.spec.js @@ -19,6 +19,9 @@ test.describe( 'Style Book', () => { } ); test.beforeEach( async ( { admin, editor, styleBook, page } ) => { + await page.addInitScript( () => { + window.__experimentalEditorWriteMode = true; + } ); await admin.visitSiteEditor(); await editor.canvas.locator( 'body' ).click(); await styleBook.open(); From 0c32e9e88c7e2fdd837c6de3a7055267af3af0e6 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 21 Nov 2024 15:35:45 +0100 Subject: [PATCH 1663/1908] Posts DataViews: Refactor the router to use route registration (#67160) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../src/components/posts-app-routes/home.js | 36 ++++++++++ .../src/components/posts-app-routes/index.js | 36 ++++++++++ .../components/posts-app-routes/posts-edit.js | 31 +++++++++ .../posts-list-view-quick-edit.js | 52 ++++++++++++++ .../posts-app-routes/posts-list-view.js | 40 +++++++++++ .../posts-app-routes/posts-view-quick-edit.js | 49 +++++++++++++ .../components/posts-app-routes/posts-view.js | 35 ++++++++++ .../src/components/posts-app/index.js | 4 +- .../src/components/posts-app/router.js | 69 ------------------- 9 files changed, 282 insertions(+), 70 deletions(-) create mode 100644 packages/edit-site/src/components/posts-app-routes/home.js create mode 100644 packages/edit-site/src/components/posts-app-routes/index.js create mode 100644 packages/edit-site/src/components/posts-app-routes/posts-edit.js create mode 100644 packages/edit-site/src/components/posts-app-routes/posts-list-view-quick-edit.js create mode 100644 packages/edit-site/src/components/posts-app-routes/posts-list-view.js create mode 100644 packages/edit-site/src/components/posts-app-routes/posts-view-quick-edit.js create mode 100644 packages/edit-site/src/components/posts-app-routes/posts-view.js delete mode 100644 packages/edit-site/src/components/posts-app/router.js diff --git a/packages/edit-site/src/components/posts-app-routes/home.js b/packages/edit-site/src/components/posts-app-routes/home.js new file mode 100644 index 00000000000000..ec99cbd8899f1d --- /dev/null +++ b/packages/edit-site/src/components/posts-app-routes/home.js @@ -0,0 +1,36 @@ +/** + * WordPress dependencies + */ +import { privateApis as routerPrivateApis } from '@wordpress/router'; + +/** + * Internal dependencies + */ +import Editor from '../editor'; +import SidebarNavigationScreenMain from '../sidebar-navigation-screen-main'; +import { unlock } from '../../lock-unlock'; + +const { useLocation } = unlock( routerPrivateApis ); + +function HomeMobileView() { + const { params = {} } = useLocation(); + const { canvas = 'view' } = params; + + return canvas === 'edit' ? ( + <Editor isPostsList /> + ) : ( + <SidebarNavigationScreenMain /> + ); +} + +export const homeRoute = { + name: 'home', + match: () => { + return true; + }, + areas: { + sidebar: <SidebarNavigationScreenMain />, + preview: <Editor isPostsList />, + mobile: HomeMobileView, + }, +}; diff --git a/packages/edit-site/src/components/posts-app-routes/index.js b/packages/edit-site/src/components/posts-app-routes/index.js new file mode 100644 index 00000000000000..e850bbd382200d --- /dev/null +++ b/packages/edit-site/src/components/posts-app-routes/index.js @@ -0,0 +1,36 @@ +/** + * WordPress dependencies + */ +import { useRegistry, useDispatch } from '@wordpress/data'; +import { useEffect } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; +import { store as siteEditorStore } from '../../store'; +import { homeRoute } from './home'; +import { postsListViewQuickEditRoute } from './posts-list-view-quick-edit'; +import { postsListViewRoute } from './posts-list-view'; +import { postsViewQuickEditRoute } from './posts-view-quick-edit'; +import { postsViewRoute } from './posts-view'; +import { postsEditRoute } from './posts-edit'; + +const routes = [ + postsListViewQuickEditRoute, + postsListViewRoute, + postsViewQuickEditRoute, + postsViewRoute, + postsEditRoute, + homeRoute, +]; + +export function useRegisterPostsAppRoutes() { + const registry = useRegistry(); + const { registerRoute } = unlock( useDispatch( siteEditorStore ) ); + useEffect( () => { + registry.batch( () => { + routes.forEach( registerRoute ); + } ); + }, [ registry, registerRoute ] ); +} diff --git a/packages/edit-site/src/components/posts-app-routes/posts-edit.js b/packages/edit-site/src/components/posts-app-routes/posts-edit.js new file mode 100644 index 00000000000000..d3958245595416 --- /dev/null +++ b/packages/edit-site/src/components/posts-app-routes/posts-edit.js @@ -0,0 +1,31 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import PostList from '../post-list'; +import DataViewsSidebarContent from '../sidebar-dataviews'; +import SidebarNavigationScreen from '../sidebar-navigation-screen'; +import Editor from '../editor'; + +export const postsEditRoute = { + name: 'posts-edit', + match: ( params ) => { + return params.postType === 'post' && params.canvas === 'edit'; + }, + areas: { + sidebar: ( + <SidebarNavigationScreen + title={ __( 'Posts' ) } + isRoot + content={ <DataViewsSidebarContent /> } + /> + ), + content: <PostList postType="post" />, + mobile: <Editor isPostsList />, + preview: <Editor isPostsList />, + }, +}; diff --git a/packages/edit-site/src/components/posts-app-routes/posts-list-view-quick-edit.js b/packages/edit-site/src/components/posts-app-routes/posts-list-view-quick-edit.js new file mode 100644 index 00000000000000..d2434b390ffd9f --- /dev/null +++ b/packages/edit-site/src/components/posts-app-routes/posts-list-view-quick-edit.js @@ -0,0 +1,52 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; + +/** + * Internal dependencies + */ +import PostList from '../post-list'; +import DataViewsSidebarContent from '../sidebar-dataviews'; +import SidebarNavigationScreen from '../sidebar-navigation-screen'; +import { unlock } from '../../lock-unlock'; +import { PostEdit } from '../post-edit'; +import Editor from '../editor'; + +const { useLocation } = unlock( routerPrivateApis ); + +function PostQuickEdit() { + const { params } = useLocation(); + return <PostEdit postType="post" postId={ params.postId } />; +} + +export const postsListViewQuickEditRoute = { + name: 'posts-list-view-quick-edit', + match: ( params ) => { + return ( + params.isCustom !== 'true' && + ( params.layout ?? 'list' ) === 'list' && + !! params.quickEdit && + params.postType === 'post' && + params.canvas !== 'edit' + ); + }, + areas: { + sidebar: ( + <SidebarNavigationScreen + title={ __( 'Posts' ) } + isRoot + content={ <DataViewsSidebarContent /> } + /> + ), + content: <PostList postType="post" />, + mobile: <PostList postType="post" />, + preview: <Editor />, + edit: <PostQuickEdit />, + }, + widths: { + content: 380, + edit: 380, + }, +}; diff --git a/packages/edit-site/src/components/posts-app-routes/posts-list-view.js b/packages/edit-site/src/components/posts-app-routes/posts-list-view.js new file mode 100644 index 00000000000000..68aa86c7fb2392 --- /dev/null +++ b/packages/edit-site/src/components/posts-app-routes/posts-list-view.js @@ -0,0 +1,40 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import PostList from '../post-list'; +import DataViewsSidebarContent from '../sidebar-dataviews'; +import SidebarNavigationScreen from '../sidebar-navigation-screen'; +import Editor from '../editor'; + +export const postsListViewRoute = { + name: 'posts-list-view', + match: ( params ) => { + return ( + params.isCustom !== 'true' && + ( params.layout ?? 'list' ) === 'list' && + ! params.quickEdit && + params.postType === 'post' && + params.canvas !== 'edit' + ); + }, + areas: { + sidebar: ( + <SidebarNavigationScreen + title={ __( 'Posts' ) } + isRoot + content={ <DataViewsSidebarContent /> } + /> + ), + content: <PostList postType="post" />, + preview: <Editor isPostsList />, + mobile: <PostList postType="post" />, + }, + widths: { + content: 380, + }, +}; diff --git a/packages/edit-site/src/components/posts-app-routes/posts-view-quick-edit.js b/packages/edit-site/src/components/posts-app-routes/posts-view-quick-edit.js new file mode 100644 index 00000000000000..52e6f9a2d26ef6 --- /dev/null +++ b/packages/edit-site/src/components/posts-app-routes/posts-view-quick-edit.js @@ -0,0 +1,49 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; + +/** + * Internal dependencies + */ +import PostList from '../post-list'; +import DataViewsSidebarContent from '../sidebar-dataviews'; +import SidebarNavigationScreen from '../sidebar-navigation-screen'; +import { unlock } from '../../lock-unlock'; +import { PostEdit } from '../post-edit'; + +const { useLocation } = unlock( routerPrivateApis ); + +function PostQuickEdit() { + const { params } = useLocation(); + return <PostEdit postType="post" postId={ params.postId } />; +} + +export const postsViewQuickEditRoute = { + name: 'posts-view-quick-edit', + match: ( params ) => { + return ( + ( params.isCustom === 'true' || + ( params.layout ?? 'list' ) !== 'list' ) && + !! params.quickEdit && + params.postType === 'post' && + params.canvas !== 'edit' + ); + }, + areas: { + sidebar: ( + <SidebarNavigationScreen + title={ __( 'Posts' ) } + isRoot + content={ <DataViewsSidebarContent /> } + /> + ), + content: <PostList postType="post" />, + mobile: <PostList postType="post" />, + edit: <PostQuickEdit />, + }, + widths: { + edit: 380, + }, +}; diff --git a/packages/edit-site/src/components/posts-app-routes/posts-view.js b/packages/edit-site/src/components/posts-app-routes/posts-view.js new file mode 100644 index 00000000000000..6559991475d278 --- /dev/null +++ b/packages/edit-site/src/components/posts-app-routes/posts-view.js @@ -0,0 +1,35 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import PostList from '../post-list'; +import DataViewsSidebarContent from '../sidebar-dataviews'; +import SidebarNavigationScreen from '../sidebar-navigation-screen'; + +export const postsViewRoute = { + name: 'posts-view', + match: ( params ) => { + return ( + ( params.isCustom === 'true' || + ( params.layout ?? 'list' ) !== 'list' ) && + ! params.quickEdit && + params.postType === 'post' && + params.canvas !== 'edit' + ); + }, + areas: { + sidebar: ( + <SidebarNavigationScreen + title={ __( 'Posts' ) } + isRoot + content={ <DataViewsSidebarContent /> } + /> + ), + content: <PostList postType="post" />, + mobile: <PostList postType="post" />, + }, +}; diff --git a/packages/edit-site/src/components/posts-app/index.js b/packages/edit-site/src/components/posts-app/index.js index 80d2c1c7eba86f..72e5b1eb997498 100644 --- a/packages/edit-site/src/components/posts-app/index.js +++ b/packages/edit-site/src/components/posts-app/index.js @@ -11,13 +11,15 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; * Internal dependencies */ import Layout from '../layout'; -import useActiveRoute from './router'; +import { useRegisterPostsAppRoutes } from '../posts-app-routes'; import { unlock } from '../../lock-unlock'; +import useActiveRoute from '../layout/router'; const { RouterProvider } = unlock( routerPrivateApis ); const { GlobalStylesProvider } = unlock( editorPrivateApis ); function PostsLayout() { + useRegisterPostsAppRoutes(); const route = useActiveRoute(); return <Layout route={ route } />; } diff --git a/packages/edit-site/src/components/posts-app/router.js b/packages/edit-site/src/components/posts-app/router.js deleted file mode 100644 index de89567b262094..00000000000000 --- a/packages/edit-site/src/components/posts-app/router.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * WordPress dependencies - */ -import { privateApis as routerPrivateApis } from '@wordpress/router'; -import { useSelect } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; - -/** - * Internal dependencies - */ -import { unlock } from '../../lock-unlock'; -import Editor from '../editor'; -import SidebarNavigationScreen from '../sidebar-navigation-screen'; -import SidebarNavigationScreenMain from '../sidebar-navigation-screen-main'; -import DataViewsSidebarContent from '../sidebar-dataviews'; -import PostList from '../post-list'; - -const { useLocation } = unlock( routerPrivateApis ); - -export default function useActiveRoute() { - const { params = {} } = useLocation(); - const { postType, layout, canvas } = params; - const labels = useSelect( - ( select ) => { - return select( coreStore ).getPostType( postType )?.labels; - }, - [ postType ] - ); - - // Posts list. - if ( [ 'post' ].includes( postType ) ) { - const isListLayout = layout === 'list' || ! layout; - return { - name: 'posts-list', - areas: { - sidebar: ( - <SidebarNavigationScreen - title={ labels?.name } - isRoot - content={ <DataViewsSidebarContent /> } - /> - ), - content: <PostList postType={ postType } />, - preview: ( isListLayout || canvas === 'edit' ) && ( - <Editor isPostsList /> - ), - mobile: - canvas === 'edit' ? ( - <Editor isPostsList /> - ) : ( - <PostList postType={ postType } /> - ), - }, - widths: { - content: isListLayout ? 380 : undefined, - }, - }; - } - - // Fallback shows the home page preview - return { - name: 'default', - areas: { - sidebar: <SidebarNavigationScreenMain />, - preview: <Editor isPostsList />, - mobile: canvas === 'edit' && <Editor isPostsList />, - }, - }; -} From e0d5ee65919d8e187509f7a78b9b77255e63ddac Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:31:20 -0500 Subject: [PATCH 1664/1908] Migrate Gradle wrapper validation action. (#66602) * Migrate Gradel wrapper validation action. The `gradle/wrapper-validation-action` has been migrated to `gradle/actions/wrapper-validation`. Read more: https://github.com/gradle/actions/blob/main/docs/deprecation-upgrade-guide.md#the-action-gradlewrapper-validation-action-has-been-replaced-by-gradleactionswrapper-validation. * FIx botched merge. * Update gradle/actions version. --------- Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/gradle-wrapper-validation.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 54378765bd26ff..2bb5676ae9ed66 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -6,7 +6,9 @@ jobs: name: 'Validation' runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - uses: gradle/wrapper-validation-action@v3 + - name: Validate checksums + uses: gradle/actions/wrapper-validation@cc4fc85e6b35bafd578d5ffbc76a5518407e1af0 # v4.2.1 From 9a6f48b8337e598076503b7ad36e10e52e666f94 Mon Sep 17 00:00:00 2001 From: Himanshu Pathak <himanshu.pathak@rtcamp.com> Date: Thu, 21 Nov 2024 23:37:13 +0530 Subject: [PATCH 1665/1908] Menu.ItemHelpText: better line breaking (#67011) * Fix: Use break-word instead of break-all in attribute description Changed break-all to use word-break for better readability. * CSS: Replace deprecated word-break with overflow-wrap Replace deprecated `word-break: break-word` with the modern equivalent `overflow-wrap: anywhere` to handle text wrapping. This change maintains the same text wrapping behavior while using the current standard CSS property. * Docs: Add changelog entry for MenuItemHelpText text wrapping fix * Docs: Update changelog entry for Menu.ItemHelpText to internal section Co-authored-by: himanshupathak95 <abcd95@git.wordpress.org> Co-authored-by: juanfra <juanfra@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: im3dabasia <im3dabasia1@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/menu/styles.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index ff4a8b714c9a52..d7741f4caa9886 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -35,6 +35,7 @@ - `SlotFill`: fix dependencies of `Fill` registration effects ([#67071](https://github.com/WordPress/gutenberg/pull/67071)). - `SlotFill`: rewrite the `Slot` component from class component to functional ([#67153](https://github.com/WordPress/gutenberg/pull/67153)). +- `Menu.ItemHelpText`: Fix text wrapping to prevent unintended word breaks ([#67011](https://github.com/WordPress/gutenberg/pull/67011)). ## 28.12.0 (2024-11-16) diff --git a/packages/components/src/menu/styles.ts b/packages/components/src/menu/styles.ts index 3312c8cb2de161..0e0752bf24cd10 100644 --- a/packages/components/src/menu/styles.ts +++ b/packages/components/src/menu/styles.ts @@ -380,7 +380,7 @@ export const MenuItemHelpText = styled( Truncate )` font-size: ${ font( 'helpText.fontSize' ) }; line-height: 16px; color: ${ LIGHTER_TEXT_COLOR }; - word-break: break-all; + overflow-wrap: anywhere; [data-active-item]:not( [data-focus-visible] ) *:not( ${ MenuPopoverInnerWrapper } ) From 98a7d5d10e86fdbca135f46233a08d6cf9acfcc8 Mon Sep 17 00:00:00 2001 From: Michal <mmczaplinski@gmail.com> Date: Thu, 21 Nov 2024 19:49:08 -0500 Subject: [PATCH 1666/1908] Update the enhanced pagination help text (#67173) --- .../inspector-controls/enhanced-pagination-control.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js b/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js index 9d47d67e61d781..4d0b1a9fd9da37 100644 --- a/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js +++ b/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js @@ -18,15 +18,13 @@ export default function EnhancedPaginationControl( { const fullPageClientSideNavigation = window.__experimentalFullPageClientSideNavigation; - let help = __( 'Browsing between pages requires a full page reload.' ); + let help = __( + 'Reload the full page—instead of just the posts list—when visitors navigate between pages.' + ); if ( fullPageClientSideNavigation ) { help = __( 'Experimental full-page client-side navigation setting enabled.' ); - } else if ( enhancedPagination ) { - help = __( - 'Reload the full page—instead of just the posts list—when visitors navigate between pages.' - ); } else if ( hasUnsupportedBlocks ) { help = __( 'Enhancement disabled because there are non-compatible blocks inside the Query block.' From a7c373f7acf212ec7999db53ddb17108f1f684df Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Fri, 22 Nov 2024 09:48:38 +0800 Subject: [PATCH 1667/1908] Avoid zooming out when browsing styles if the preview mode is active (#67190) Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: yogeshbhutkar <yogeshbhutkar@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../global-styles/screen-style-variations.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/screen-style-variations.js b/packages/edit-site/src/components/global-styles/screen-style-variations.js index 76d13023ff09a8..f6036aaace4358 100644 --- a/packages/edit-site/src/components/global-styles/screen-style-variations.js +++ b/packages/edit-site/src/components/global-styles/screen-style-variations.js @@ -1,10 +1,13 @@ /** * WordPress dependencies */ +import { + privateApis as blockEditorPrivateApis, + store as blockEditorStore, +} from '@wordpress/block-editor'; import { Card, CardBody } from '@wordpress/components'; +import { useSelect, useDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; -import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; -import { useDispatch } from '@wordpress/data'; import { store as editorStore } from '@wordpress/editor'; import { useEffect } from '@wordpress/element'; @@ -19,10 +22,13 @@ const { useZoomOut } = unlock( blockEditorPrivateApis ); function ScreenStyleVariations() { // Style Variations should only be previewed in with - // - a "zoomed out" editor + // - a "zoomed out" editor (but not when in preview mode) // - "Desktop" device preview + const isPreviewMode = useSelect( ( select ) => { + return select( blockEditorStore ).getSettings().isPreviewMode; + }, [] ); const { setDeviceType } = useDispatch( editorStore ); - useZoomOut(); + useZoomOut( ! isPreviewMode ); useEffect( () => { setDeviceType( 'desktop' ); }, [ setDeviceType ] ); From 92254bf3677d7c561d36ab47ec0344e18f71fa2b Mon Sep 17 00:00:00 2001 From: Doug Wollison <doug@wollison.net> Date: Thu, 21 Nov 2024 21:40:17 -0500 Subject: [PATCH 1668/1908] Details block: use summary content as default label (#67217) Co-authored-by: dougwollison <dougwollison@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- packages/block-library/src/details/index.js | 24 ++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/details/index.js b/packages/block-library/src/details/index.js index 3ba5efb04e27d2..31ee2e0e00f139 100644 --- a/packages/block-library/src/details/index.js +++ b/packages/block-library/src/details/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { details as icon } from '@wordpress/icons'; -import { __ } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; /** * Internal dependencies @@ -34,6 +34,28 @@ export const settings = { }, ], }, + __experimentalLabel( attributes, { context } ) { + const { summary } = attributes; + + const customName = attributes?.metadata?.name; + const hasSummary = summary?.trim().length > 0; + + // In the list view, use the block's summary as the label. + // If the summary is empty, fall back to the default label. + if ( context === 'list-view' && ( customName || hasSummary ) ) { + return customName || summary; + } + + if ( context === 'accessibility' ) { + return ! hasSummary + ? __( 'Details. Empty.' ) + : sprintf( + /* translators: accessibility text; summary title. */ + __( 'Details. %s' ), + summary + ); + } + }, save, edit, transforms, From b58cce696977b0f8850a39bfaf895a426a59c619 Mon Sep 17 00:00:00 2001 From: Manzoor Wani <manzoorwani.jk@gmail.com> Date: Fri, 22 Nov 2024 00:30:15 -0800 Subject: [PATCH 1669/1908] Fix ESLint Jest reporting entire body of the test function rather than the identifier (#67222) Co-authored-by: manzoorwanijk <manzoorwanijk@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- package-lock.json | 11 ++++++----- package.json | 2 +- packages/eslint-plugin/package.json | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 04a8d2021f12a0..1fc9131a33c8c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -88,7 +88,7 @@ "eslint-import-resolver-node": "0.3.4", "eslint-plugin-eslint-comments": "3.1.2", "eslint-plugin-import": "2.25.2", - "eslint-plugin-jest": "27.2.3", + "eslint-plugin-jest": "27.4.3", "eslint-plugin-jest-dom": "5.0.2", "eslint-plugin-prettier": "5.0.0", "eslint-plugin-react-compiler": "19.0.0-beta-0dec889-20241115", @@ -25190,9 +25190,10 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/eslint-plugin-jest": { - "version": "27.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz", - "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==", + "version": "27.4.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.3.tgz", + "integrity": "sha512-7S6SmmsHsgIm06BAGCAxL+ABd9/IB3MWkz2pudj6Qqor2y1qQpWPfuFU4SG9pWj4xDjF0e+D7Llh5useuSzAZw==", + "license": "MIT", "dependencies": { "@typescript-eslint/utils": "^5.10.0" }, @@ -54649,7 +54650,7 @@ "cosmiconfig": "^7.0.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.2", - "eslint-plugin-jest": "^27.2.3", + "eslint-plugin-jest": "^27.4.3", "eslint-plugin-jsdoc": "^46.4.6", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-playwright": "^0.15.3", diff --git a/package.json b/package.json index 52668f667c71cd..41102f867f0e22 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "eslint-import-resolver-node": "0.3.4", "eslint-plugin-eslint-comments": "3.1.2", "eslint-plugin-import": "2.25.2", - "eslint-plugin-jest": "27.2.3", + "eslint-plugin-jest": "27.4.3", "eslint-plugin-jest-dom": "5.0.2", "eslint-plugin-prettier": "5.0.0", "eslint-plugin-react-compiler": "19.0.0-beta-0dec889-20241115", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index c3521692d7fd12..0e8880f0941234 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -39,7 +39,7 @@ "cosmiconfig": "^7.0.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.2", - "eslint-plugin-jest": "^27.2.3", + "eslint-plugin-jest": "^27.4.3", "eslint-plugin-jsdoc": "^46.4.6", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-playwright": "^0.15.3", From 58ae911e10abe260a20514c2249ff50b8e46dcac Mon Sep 17 00:00:00 2001 From: Sainath Poojary <53347682+SainathPoojary@users.noreply.github.com> Date: Fri, 22 Nov 2024 14:22:22 +0530 Subject: [PATCH 1670/1908] Social Links: Fix font family and weight inconsistency in editor (#67204) Added font-weight: inherit; and font-family: inherit; to the .wp-block-social-link-anchor class in the editor to ensure consistent font styling with the frontend. Unlinked contributors: bgardner. Co-authored-by: SainathPoojary <sainathpoojary@git.wordpress.org> Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jordesign <jordesign@git.wordpress.org> Co-authored-by: himanshupathak95 <abcd95@git.wordpress.org> --- packages/block-library/src/social-link/editor.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/block-library/src/social-link/editor.scss b/packages/block-library/src/social-link/editor.scss index 2f5714f5d2ed9f..2e93c9447cca8d 100644 --- a/packages/block-library/src/social-link/editor.scss +++ b/packages/block-library/src/social-link/editor.scss @@ -14,6 +14,8 @@ font-size: inherit; color: currentColor; height: auto; + font-weight: inherit; + font-family: inherit; // This rule ensures social link buttons display correctly in template parts. opacity: 1; From 81d2ee840c21bf7818ef0b3ec0a6297ace43d973 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Fri, 22 Nov 2024 09:17:00 +0000 Subject: [PATCH 1671/1908] Use rems for Nav overlay left padding (#67168) Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: tysonlmao <tysonlmao@git.wordpress.org> --- packages/block-library/src/navigation/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/navigation/style.scss b/packages/block-library/src/navigation/style.scss index 3d7a8810ae9b71..5f49eba466a5fd 100644 --- a/packages/block-library/src/navigation/style.scss +++ b/packages/block-library/src/navigation/style.scss @@ -510,7 +510,7 @@ button.wp-block-navigation-item__content { padding-top: clamp(1rem, var(--wp--style--root--padding-top), 20rem); padding-right: clamp(1rem, var(--wp--style--root--padding-right), 20rem); padding-bottom: clamp(1rem, var(--wp--style--root--padding-bottom), 20rem); - padding-left: clamp(1rem, var(--wp--style--root--padding-left), 20em); + padding-left: clamp(1rem, var(--wp--style--root--padding-left), 20rem); // Allow modal to scroll. overflow: auto; From 2919c5c4c6ee20740faa7bd7ffd9b360120e6a38 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Fri, 22 Nov 2024 10:47:03 +0100 Subject: [PATCH 1672/1908] Fix fatal error in in_array call in post_type_default_rendering_mode (#67225) Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> --- lib/compat/wordpress-6.8/post.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compat/wordpress-6.8/post.php b/lib/compat/wordpress-6.8/post.php index 26e6c3adc07a3d..639e33b4e5ca51 100644 --- a/lib/compat/wordpress-6.8/post.php +++ b/lib/compat/wordpress-6.8/post.php @@ -39,7 +39,7 @@ function gutenberg_post_type_default_rendering_mode( $args, $post_type ) { if ( wp_is_block_theme() && ( isset( $args['show_in_rest'] ) && $args['show_in_rest'] ) && - ( isset( $args['supports'] ) && in_array( 'editor', $args['supports'], true ) ) + ( ! empty( $args['supports'] ) && in_array( 'editor', $args['supports'], true ) ) ) { // Validate the supplied rendering mode. if ( From 4d2fb64425d7653315997d9c4003f1fa6a4f912a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 22 Nov 2024 11:24:12 +0100 Subject: [PATCH 1673/1908] DataViews: fix spacing when combining combined fields (#67226) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../components/dataviews/stories/fixtures.tsx | 1 + .../dataviews/stories/index.story.tsx | 18 +++++++++++++++--- .../src/dataviews-layouts/table/index.tsx | 6 +++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/packages/dataviews/src/components/dataviews/stories/fixtures.tsx b/packages/dataviews/src/components/dataviews/stories/fixtures.tsx index ff098209b34684..6c74c516853c5b 100644 --- a/packages/dataviews/src/components/dataviews/stories/fixtures.tsx +++ b/packages/dataviews/src/components/dataviews/stories/fixtures.tsx @@ -558,6 +558,7 @@ export const themeFields: Field< Theme >[] = [ }, { id: 'requires', label: 'Requires at least' }, { id: 'tested', label: 'Tested up to' }, + { id: 'icon', label: 'Icon', render: () => <Icon icon={ image } /> }, { id: 'tags', label: 'Tags', diff --git a/packages/dataviews/src/components/dataviews/stories/index.story.tsx b/packages/dataviews/src/components/dataviews/stories/index.story.tsx index 878677d2eb30c6..6161af125b5ca4 100644 --- a/packages/dataviews/src/components/dataviews/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataviews/stories/index.story.tsx @@ -137,16 +137,28 @@ export const FieldsNoSortableNoHidable = () => { export const CombinedFields = () => { const defaultLayoutsThemes = { table: { - fields: [ 'theme', 'requires', 'tested' ], + fields: [ 'theme_with_combined', 'theme_with_simple' ], layout: { primaryField: 'name', combinedFields: [ { - id: 'theme', + id: 'name_tested', label: 'Theme', - children: [ 'name', 'description' ], + children: [ 'name', 'tested' ], direction: 'vertical', }, + { + id: 'theme_with_combined', + label: 'Combine combined fields', + children: [ 'icon', 'name_tested' ], + direction: 'horizontal', + }, + { + id: 'theme_with_simple', + label: 'Combine simple fields', + children: [ 'icon', 'name' ], + direction: 'horizontal', + }, ] as CombinedField[], styles: { theme: { diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 8ef41db1c38798..db76d24b53bfa3 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -147,7 +147,11 @@ function TableColumnCombined< Item >( { ) ); if ( field.direction === 'horizontal' ) { - return <HStack spacing={ 3 }>{ children }</HStack>; + return ( + <HStack spacing={ 3 } justify="flex-start"> + { children } + </HStack> + ); } return <VStack spacing={ 0 }>{ children }</VStack>; } From 452de1b775ea28e4d13f94db6117b99e36d56e0e Mon Sep 17 00:00:00 2001 From: Akshat Kakkad <87222220+AKSHAT2802@users.noreply.github.com> Date: Fri, 22 Nov 2024 17:09:41 +0530 Subject: [PATCH 1674/1908] Add all color palettes to select from editor panel (#65148) * Add all the colors in with-color-context so that they all are listed in block editor * Remove default colour pallete * Remove extra space * Update packages/block-editor/src/components/color-palette/with-color-context.js re-add default colours Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> * Add default colours if enabled * Update packages/block-editor/src/components/color-palette/with-color-context.js Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> * update test --------- Unlinked contributors: EddyBoels, burnuser. Co-authored-by: AKSHAT2802 <akshat2802@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: rohitmathur-7 <rohitmathur7@git.wordpress.org> Co-authored-by: javiercasares <javiercasares@git.wordpress.org> --- .../color-palette/with-color-context.js | 32 +++++++++++++++---- packages/block-library/src/cover/test/edit.js | 4 +-- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/components/color-palette/with-color-context.js b/packages/block-editor/src/components/color-palette/with-color-context.js index 62b8c1bc4b6181..38c90531edaac1 100644 --- a/packages/block-editor/src/components/color-palette/with-color-context.js +++ b/packages/block-editor/src/components/color-palette/with-color-context.js @@ -10,14 +10,32 @@ import { useSettings } from '../use-settings'; export default createHigherOrderComponent( ( WrappedComponent ) => { return ( props ) => { - const [ colorsFeature, enableCustomColors ] = useSettings( - 'color.palette', - 'color.custom' + // Get the default colors, theme colors, and custom colors + const [ + defaultColors, + themeColors, + customColors, + enableCustomColors, + enableDefaultColors, + ] = useSettings( + 'color.palette.default', + 'color.palette.theme', + 'color.palette.custom', + 'color.custom', + 'color.defaultPalette' ); - const { - colors = colorsFeature, - disableCustomColors = ! enableCustomColors, - } = props; + + const _colors = enableDefaultColors + ? [ + ...( themeColors || [] ), + ...( defaultColors || [] ), + ...( customColors || [] ), + ] + : [ ...( themeColors || [] ), ...( customColors || [] ) ]; + + const { colors = _colors, disableCustomColors = ! enableCustomColors } = + props; + const hasColorsToChoose = ( colors && colors.length > 0 ) || ! disableCustomColors; return ( diff --git a/packages/block-library/src/cover/test/edit.js b/packages/block-library/src/cover/test/edit.js index 5c1a5b5e13e67d..f5d6a5301ef6d2 100644 --- a/packages/block-library/src/cover/test/edit.js +++ b/packages/block-library/src/cover/test/edit.js @@ -337,7 +337,7 @@ describe( 'Cover block', () => { describe( 'when colors are disabled', () => { test( 'does not render overlay control', async () => { await setup( undefined, true, disabledColorSettings ); - await createAndSelectBlock(); + await selectBlock( 'Block: Cover' ); await userEvent.click( screen.getByRole( 'tab', { name: 'Styles' } ) ); @@ -350,7 +350,7 @@ describe( 'Cover block', () => { } ); test( 'does not render opacity control', async () => { await setup( undefined, true, disabledColorSettings ); - await createAndSelectBlock(); + await selectBlock( 'Block: Cover' ); await userEvent.click( screen.getByRole( 'tab', { name: 'Styles' } ) ); From 455bb5d93408c45622d747a547088cd77e0d0511 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Fri, 22 Nov 2024 12:47:04 +0100 Subject: [PATCH 1675/1908] Modal: Increase size of the Close button (#66792) * Make the modal component close button use the compact size. * Make spacing consistent. * Add changelog entry. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/block-library/src/freeform/modal.js | 2 +- packages/components/CHANGELOG.md | 1 + packages/components/src/modal/index.tsx | 4 ++-- packages/components/src/modal/stories/index.story.tsx | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/block-library/src/freeform/modal.js b/packages/block-library/src/freeform/modal.js index 4ed4ef4d3a07ca..35652eb29948a3 100644 --- a/packages/block-library/src/freeform/modal.js +++ b/packages/block-library/src/freeform/modal.js @@ -25,7 +25,7 @@ function ModalAuxiliaryActions( { onClick, isModalFullScreen } ) { return ( <Button - size="small" + size="compact" onClick={ onClick } icon={ fullscreen } isPressed={ isModalFullScreen } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index d7741f4caa9886..1d6ed8745cb5da 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -16,6 +16,7 @@ ### Bug Fixes +- `Modal`: Modal: Increase size of the Close button ([#66792](https://github.com/WordPress/gutenberg/pull/66792)). - `ToggleGroupControl`: Fix active background for `0` value ([#66855](https://github.com/WordPress/gutenberg/pull/66855)). - `SlotFill`: Fix a bug where a stale value of `fillProps` could be used ([#67000](https://github.com/WordPress/gutenberg/pull/67000)). - `ColorPalette`: Disable `Clear` button if there's no color value. ([#67108](https://github.com/WordPress/gutenberg/pull/67108)). diff --git a/packages/components/src/modal/index.tsx b/packages/components/src/modal/index.tsx index 7d55c9a4d5d1e6..2dec0f65240f9b 100644 --- a/packages/components/src/modal/index.tsx +++ b/packages/components/src/modal/index.tsx @@ -335,10 +335,10 @@ function UnforwardedModal( <> <Spacer marginBottom={ 0 } - marginLeft={ 3 } + marginLeft={ 2 } /> <Button - size="small" + size="compact" onClick={ ( event: React.MouseEvent< HTMLButtonElement > ) => diff --git a/packages/components/src/modal/stories/index.story.tsx b/packages/components/src/modal/stories/index.story.tsx index 92c922bcb8a977..880688ed5c51c3 100644 --- a/packages/components/src/modal/stories/index.story.tsx +++ b/packages/components/src/modal/stories/index.story.tsx @@ -111,7 +111,7 @@ export const WithHeaderActions: StoryFn< typeof Modal > = Template.bind( {} ); WithHeaderActions.args = { ...Default.args, headerActions: ( - <Button icon={ fullscreen } label="Fullscreen mode" size="small" /> + <Button icon={ fullscreen } label="Fullscreen mode" size="compact" /> ), children: <div style={ { height: '200px' } } />, }; From b4c614f1268b6a5fb696c2b197bb8240ae6f1fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20W=C3=BCnsch?= <soerenwrede@gmail.com> Date: Fri, 22 Nov 2024 13:15:51 +0100 Subject: [PATCH 1676/1908] Docs: Correct `@return` type in `block_core_query_disable_enhanced_pagination()` (#67128) Co-authored-by: Soean <soean@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> --- packages/block-library/src/query/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/query/index.php b/packages/block-library/src/query/index.php index 043f351e11d7f1..6b544cd99ae8c7 100644 --- a/packages/block-library/src/query/index.php +++ b/packages/block-library/src/query/index.php @@ -79,7 +79,7 @@ function register_block_core_query() { * @since 6.4.0 * * @param array $parsed_block The block being rendered. - * @return string Returns the parsed block, unmodified. + * @return array Returns the parsed block, unmodified. */ function block_core_query_disable_enhanced_pagination( $parsed_block ) { static $enhanced_query_stack = array(); From 96f6338034682929ff4fc79ec5b1225e258678e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 22 Nov 2024 16:23:54 +0100 Subject: [PATCH 1677/1908] DataViews: allow register/unregister fields (#67175) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: louwie17 <louwie17@git.wordpress.org> --- packages/editor/README.md | 24 +++++++ .../src/components/post-actions/actions.js | 6 +- .../src/components/post-fields/index.ts | 71 +++++++++++-------- packages/editor/src/dataviews/api.js | 41 +++++++++++ .../src/dataviews/store/private-actions.ts | 60 +++++++++++++++- .../src/dataviews/store/private-selectors.ts | 4 ++ .../editor/src/dataviews/store/reducer.ts | 39 +++++++++- .../editor/src/store/private-selectors.js | 5 ++ 8 files changed, 213 insertions(+), 37 deletions(-) diff --git a/packages/editor/README.md b/packages/editor/README.md index 07405d0d51c3d2..bc00e15c8fb892 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -1602,6 +1602,18 @@ _Parameters_ - _name_ `string`: Entity name. - _config_ `Action`: Action configuration. +### registerEntityField + +Registers a new DataViews field. + +This is an experimental API and is subject to change. it's only available in the Gutenberg plugin for now. + +_Parameters_ + +- _kind_ `string`: Entity kind. +- _name_ `string`: Entity name. +- _config_ `Field`: Field configuration. + ### RichText > **Deprecated** since 5.3, use `wp.blockEditor.RichText` instead. @@ -1697,6 +1709,18 @@ _Parameters_ - _name_ `string`: Entity name. - _actionId_ `string`: Action ID. +### unregisterEntityField + +Unregisters a DataViews field. + +This is an experimental API and is subject to change. it's only available in the Gutenberg plugin for now. + +_Parameters_ + +- _kind_ `string`: Entity kind. +- _name_ `string`: Entity name. +- _fieldId_ `string`: Field ID. + ### UnsavedChangesWarning Warns the user if there are unsaved changes before leaving the editor. Compatible with Post Editor and Site Editor. diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index e1c0ed1558193d..8dbe5b9dfcd5ad 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -21,10 +21,10 @@ export function usePostActions( { postType, onActionPerformed, context } ) { [ postType ] ); - const { registerPostTypeActions } = unlock( useDispatch( editorStore ) ); + const { registerPostTypeSchema } = unlock( useDispatch( editorStore ) ); useEffect( () => { - registerPostTypeActions( postType ); - }, [ registerPostTypeActions, postType ] ); + registerPostTypeSchema( postType ); + }, [ registerPostTypeSchema, postType ] ); return useMemo( () => { // Filter actions based on provided context. If not provided diff --git a/packages/editor/src/components/post-fields/index.ts b/packages/editor/src/components/post-fields/index.ts index 3d675ab763d64c..41b61fe103a70f 100644 --- a/packages/editor/src/components/post-fields/index.ts +++ b/packages/editor/src/components/post-fields/index.ts @@ -1,22 +1,18 @@ /** * WordPress dependencies */ -import { useMemo } from '@wordpress/element'; +import { useEffect, useMemo } from '@wordpress/element'; import { useEntityRecords } from '@wordpress/core-data'; +import { useDispatch, useSelect } from '@wordpress/data'; import type { Field } from '@wordpress/dataviews'; -import { - featuredImageField, - slugField, - parentField, - passwordField, - statusField, - commentStatusField, - titleField, - dateField, - authorField, -} from '@wordpress/fields'; import type { BasePostWithEmbeddedAuthor } from '@wordpress/fields'; +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; +import { store as editorStore } from '../../store'; + interface UsePostFieldsReturn { isLoading: boolean; fields: Field< BasePostWithEmbeddedAuthor >[]; @@ -28,29 +24,44 @@ interface Author { } function usePostFields(): UsePostFieldsReturn { + const postType = 'page'; // TODO: this could be page or post (experimental). + + const { registerPostTypeSchema } = unlock( useDispatch( editorStore ) ); + useEffect( () => { + registerPostTypeSchema( postType ); + }, [ registerPostTypeSchema, postType ] ); + + const { defaultFields } = useSelect( + ( select ) => { + const { getEntityFields } = unlock( select( editorStore ) ); + return { + defaultFields: getEntityFields( 'postType', postType ), + }; + }, + [ postType ] + ); + const { records: authors, isResolving: isLoadingAuthors } = useEntityRecords< Author >( 'root', 'user', { per_page: -1 } ); const fields = useMemo( () => - [ - featuredImageField, - titleField, - { - ...authorField, - elements: authors?.map( ( { id, name } ) => ( { - value: id, - label: name, - } ) ), - }, - statusField, - dateField, - slugField, - parentField, - commentStatusField, - passwordField, - ] as Field< BasePostWithEmbeddedAuthor >[], - [ authors ] + defaultFields.map( + ( field: Field< BasePostWithEmbeddedAuthor > ) => { + if ( field.id === 'author' ) { + return { + ...field, + elements: authors?.map( ( { id, name } ) => ( { + value: id, + label: name, + } ) ), + }; + } + + return field; + } + ) as Field< BasePostWithEmbeddedAuthor >[], + [ authors, defaultFields ] ); return { diff --git a/packages/editor/src/dataviews/api.js b/packages/editor/src/dataviews/api.js index 130a69bba754c7..e03b9ef35ac758 100644 --- a/packages/editor/src/dataviews/api.js +++ b/packages/editor/src/dataviews/api.js @@ -11,6 +11,7 @@ import { store as editorStore } from '../store'; /** * @typedef {import('@wordpress/dataviews').Action} Action + * @typedef {import('@wordpress/dataviews').Field} Field */ /** @@ -53,3 +54,43 @@ export function unregisterEntityAction( kind, name, actionId ) { _unregisterEntityAction( kind, name, actionId ); } } + +/** + * Registers a new DataViews field. + * + * This is an experimental API and is subject to change. + * it's only available in the Gutenberg plugin for now. + * + * @param {string} kind Entity kind. + * @param {string} name Entity name. + * @param {Field} config Field configuration. + */ +export function registerEntityField( kind, name, config ) { + const { registerEntityField: _registerEntityField } = unlock( + dispatch( editorStore ) + ); + + if ( globalThis.IS_GUTENBERG_PLUGIN ) { + _registerEntityField( kind, name, config ); + } +} + +/** + * Unregisters a DataViews field. + * + * This is an experimental API and is subject to change. + * it's only available in the Gutenberg plugin for now. + * + * @param {string} kind Entity kind. + * @param {string} name Entity name. + * @param {string} fieldId Field ID. + */ +export function unregisterEntityField( kind, name, fieldId ) { + const { unregisterEntityField: _unregisterEntityField } = unlock( + dispatch( editorStore ) + ); + + if ( globalThis.IS_GUTENBERG_PLUGIN ) { + _unregisterEntityField( kind, name, fieldId ); + } +} diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 10f2b9ce872d5a..77ac131a8e2302 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -2,7 +2,7 @@ * WordPress dependencies */ import { store as coreStore } from '@wordpress/core-data'; -import type { Action } from '@wordpress/dataviews'; +import type { Action, Field } from '@wordpress/dataviews'; import { doAction } from '@wordpress/hooks'; /** @@ -24,6 +24,15 @@ import { renamePost, resetPost, deletePost, + featuredImageField, + dateField, + parentField, + passwordField, + commentStatusField, + slugField, + statusField, + authorField, + titleField, } from '@wordpress/fields'; import duplicateTemplatePart from '../actions/duplicate-template-part'; @@ -53,6 +62,32 @@ export function unregisterEntityAction( }; } +export function registerEntityField< Item >( + kind: string, + name: string, + config: Field< Item > +) { + return { + type: 'REGISTER_ENTITY_FIELD' as const, + kind, + name, + config, + }; +} + +export function unregisterEntityField( + kind: string, + name: string, + fieldId: string +) { + return { + type: 'UNREGISTER_ENTITY_FIELD' as const, + kind, + name, + fieldId, + }; +} + export function setIsReady( kind: string, name: string ) { return { type: 'SET_IS_READY' as const, @@ -61,7 +96,7 @@ export function setIsReady( kind: string, name: string ) { }; } -export const registerPostTypeActions = +export const registerPostTypeSchema = ( postType: string ) => async ( { registry }: { registry: any } ) => { const isReady = unlock( registry.select( editorStore ) ).isEntityReady( @@ -124,6 +159,18 @@ export const registerPostTypeActions = permanentlyDeletePost, ]; + const fields = [ + featuredImageField, + titleField, + authorField, + statusField, + dateField, + slugField, + parentField, + commentStatusField, + passwordField, + ]; + registry.batch( () => { actions.forEach( ( action ) => { if ( ! action ) { @@ -135,7 +182,14 @@ export const registerPostTypeActions = action ); } ); + fields.forEach( ( field ) => { + unlock( registry.dispatch( editorStore ) ).registerEntityField( + 'postType', + postType, + field + ); + } ); } ); - doAction( 'core.registerPostTypeActions', postType ); + doAction( 'core.registerPostTypeSchema', postType ); }; diff --git a/packages/editor/src/dataviews/store/private-selectors.ts b/packages/editor/src/dataviews/store/private-selectors.ts index 117c5b30966a39..e1daeb4032fc21 100644 --- a/packages/editor/src/dataviews/store/private-selectors.ts +++ b/packages/editor/src/dataviews/store/private-selectors.ts @@ -9,6 +9,10 @@ export function getEntityActions( state: State, kind: string, name: string ) { return state.actions[ kind ]?.[ name ] ?? EMPTY_ARRAY; } +export function getEntityFields( state: State, kind: string, name: string ) { + return state.fields[ kind ]?.[ name ] ?? EMPTY_ARRAY; +} + export function isEntityReady( state: State, kind: string, name: string ) { return state.isReady[ kind ]?.[ name ]; } diff --git a/packages/editor/src/dataviews/store/reducer.ts b/packages/editor/src/dataviews/store/reducer.ts index 9124b74f02860a..94d7f2e6c4f190 100644 --- a/packages/editor/src/dataviews/store/reducer.ts +++ b/packages/editor/src/dataviews/store/reducer.ts @@ -2,17 +2,21 @@ * WordPress dependencies */ import { combineReducers } from '@wordpress/data'; -import type { Action } from '@wordpress/dataviews'; +import type { Action, Field } from '@wordpress/dataviews'; type ReduxAction = | ReturnType< typeof import('./private-actions').registerEntityAction > | ReturnType< typeof import('./private-actions').unregisterEntityAction > + | ReturnType< typeof import('./private-actions').registerEntityField > + | ReturnType< typeof import('./private-actions').unregisterEntityField > | ReturnType< typeof import('./private-actions').setIsReady >; export type ActionState = Record< string, Record< string, Action< any >[] > >; +export type FieldsState = Record< string, Record< string, Field< any >[] > >; export type ReadyState = Record< string, Record< string, boolean > >; export type State = { actions: ActionState; + fields: FieldsState; isReady: ReadyState; }; @@ -64,7 +68,40 @@ function actions( state: ActionState = {}, action: ReduxAction ) { return state; } +function fields( state: FieldsState = {}, action: ReduxAction ) { + switch ( action.type ) { + case 'REGISTER_ENTITY_FIELD': + return { + ...state, + [ action.kind ]: { + ...state[ action.kind ], + [ action.name ]: [ + ...( + state[ action.kind ]?.[ action.name ] ?? [] + ).filter( + ( _field ) => _field.id !== action.config.id + ), + action.config, + ], + }, + }; + case 'UNREGISTER_ENTITY_FIELD': + return { + ...state, + [ action.kind ]: { + ...state[ action.kind ], + [ action.name ]: ( + state[ action.kind ]?.[ action.name ] ?? [] + ).filter( ( _field ) => _field.id !== action.fieldId ), + }, + }; + } + + return state; +} + export default combineReducers( { actions, + fields, isReady, } ); diff --git a/packages/editor/src/store/private-selectors.js b/packages/editor/src/store/private-selectors.js index 9bc065436c10bb..9af0512c19dbdd 100644 --- a/packages/editor/src/store/private-selectors.js +++ b/packages/editor/src/store/private-selectors.js @@ -27,6 +27,7 @@ import { } from './selectors'; import { getEntityActions as _getEntityActions, + getEntityFields as _getEntityFields, isEntityReady as _isEntityReady, } from '../dataviews/store/private-selectors'; @@ -171,6 +172,10 @@ export function isEntityReady( state, ...args ) { return _isEntityReady( state.dataviews, ...args ); } +export function getEntityFields( state, ...args ) { + return _getEntityFields( state.dataviews, ...args ); +} + /** * Similar to getBlocksByName in @wordpress/block-editor, but only returns the top-most * blocks that aren't descendants of the query block. From 4337e358678a70f331a7f1604f89362bfd96e3b4 Mon Sep 17 00:00:00 2001 From: Sneha Patil <90276347+snehapatil2001@users.noreply.github.com> Date: Fri, 22 Nov 2024 21:21:38 +0530 Subject: [PATCH 1678/1908] Resolve search block button text overlapping issue. (#66868) * chore: fix styling. * chore: style changes. Co-authored-by: snehapatil2001 <snehapatil02@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: viralsampat-multidots <mdviralsampat@git.wordpress.org> --- packages/block-library/src/search/style.scss | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/block-library/src/search/style.scss b/packages/block-library/src/search/style.scss index eb8e3051bada85..e61fdaea0e6434 100644 --- a/packages/block-library/src/search/style.scss +++ b/packages/block-library/src/search/style.scss @@ -58,11 +58,9 @@ $button-spacing-y: math.div($grid-unit-15, 2); // 6px // Prevent unintended text wrapping. flex-shrink: 0; max-width: 100%; - } - - // Ensure minimum input field width in small viewports. - .wp-block-search__button[aria-expanded="true"] { - max-width: calc(100% - 100px); + box-sizing: border-box; + display: flex; + justify-content: center; } .wp-block-search__inside-wrapper { From 3b5bf634bac53c5a75f5b0bc90676a66c8c8a853 Mon Sep 17 00:00:00 2001 From: Matias Benedetto <matias.benedetto@gmail.com> Date: Fri, 22 Nov 2024 14:03:51 -0300 Subject: [PATCH 1679/1908] Add section styles switch button in block toolbar in zoom out mode (#67140) * Add section styles switch button in zoom out toolbar * add icon background color * tweak label and strokeWidth * 1.25 > 1.5 --------- Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../src/components/block-toolbar/index.js | 6 + .../block-toolbar/switch-section-style.js | 115 ++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 packages/block-editor/src/components/block-toolbar/switch-section-style.js diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index b3bf7e94accb08..ea068d8126526c 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -36,6 +36,7 @@ import __unstableBlockNameContext from './block-name-context'; import NavigableToolbar from '../navigable-toolbar'; import { useHasBlockToolbar } from './use-has-block-toolbar'; import ChangeDesign from './change-design'; +import SwitchSectionStyle from './switch-section-style'; import { unlock } from '../../lock-unlock'; /** @@ -72,6 +73,7 @@ export function PrivateBlockToolbar( { showSlots, showGroupButtons, showLockButtons, + showSwitchSectionStyleButton, } = useSelect( ( select ) => { const { getBlockName, @@ -141,6 +143,7 @@ export function PrivateBlockToolbar( { showSlots: ! isZoomOut(), showGroupButtons: ! isZoomOut(), showLockButtons: ! isZoomOut(), + showSwitchSectionStyleButton: isZoomOut(), }; }, [] ); @@ -222,6 +225,9 @@ export function PrivateBlockToolbar( { { showShuffleButton && ( <ChangeDesign clientId={ blockClientIds[ 0 ] } /> ) } + { showSwitchSectionStyleButton && ( + <SwitchSectionStyle clientId={ blockClientIds[ 0 ] } /> + ) } { shouldShowVisualToolbar && showSlots && ( <> <BlockControls.Slot diff --git a/packages/block-editor/src/components/block-toolbar/switch-section-style.js b/packages/block-editor/src/components/block-toolbar/switch-section-style.js new file mode 100644 index 00000000000000..be4f041c0e8a48 --- /dev/null +++ b/packages/block-editor/src/components/block-toolbar/switch-section-style.js @@ -0,0 +1,115 @@ +/** + * WordPress dependencies + */ +import { + ToolbarButton, + ToolbarGroup, + Icon, + Path, + SVG, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { useContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import useStylesForBlocks from '../block-styles/use-styles-for-block'; +import { replaceActiveStyle } from '../block-styles/utils'; +import { store as blockEditorStore } from '../../store'; +import { GlobalStylesContext } from '../global-styles'; +import { globalStylesDataKey } from '../../store/private-keys'; +import { getVariationStylesWithRefValues } from '../../hooks/block-style-variation'; + +const styleIcon = ( + <SVG + viewBox="0 0 24 24" + xmlns="http://www.w3.org/2000/svg" + width="24" + height="24" + aria-hidden="true" + focusable="false" + > + <Path d="M17.2 10.9c-.5-1-1.2-2.1-2.1-3.2-.6-.9-1.3-1.7-2.1-2.6L12 4l-1 1.1c-.6.9-1.3 1.7-2 2.6-.8 1.2-1.5 2.3-2 3.2-.6 1.2-1 2.2-1 3 0 3.4 2.7 6.1 6.1 6.1s6.1-2.7 6.1-6.1c0-.8-.3-1.8-1-3z" /> + <Path + stroke="currentColor" + strokeWidth="1.5" + d="M17.2 10.9c-.5-1-1.2-2.1-2.1-3.2-.6-.9-1.3-1.7-2.1-2.6L12 4l-1 1.1c-.6.9-1.3 1.7-2 2.6-.8 1.2-1.5 2.3-2 3.2-.6 1.2-1 2.2-1 3 0 3.4 2.7 6.1 6.1 6.1s6.1-2.7 6.1-6.1c0-.8-.3-1.8-1-3z" + /> + </SVG> +); + +function SwitchSectionStyle( { clientId } ) { + const { stylesToRender, activeStyle, className } = useStylesForBlocks( { + clientId, + } ); + const { updateBlockAttributes } = useDispatch( blockEditorStore ); + + // Get global styles data + const { merged: mergedConfig } = useContext( GlobalStylesContext ); + const { globalSettings, globalStyles, blockName } = useSelect( + ( select ) => { + const settings = select( blockEditorStore ).getSettings(); + return { + globalSettings: settings.__experimentalFeatures, + globalStyles: settings[ globalStylesDataKey ], + blockName: select( blockEditorStore ).getBlockName( clientId ), + }; + }, + [ clientId ] + ); + + // Get the background color for the active style + const activeStyleBackground = activeStyle?.name + ? getVariationStylesWithRefValues( + { + settings: mergedConfig?.settings ?? globalSettings, + styles: mergedConfig?.styles ?? globalStyles, + }, + blockName, + activeStyle.name + )?.color?.background + : undefined; + + if ( ! stylesToRender || stylesToRender.length === 0 ) { + return null; + } + + const handleStyleSwitch = () => { + const currentIndex = stylesToRender.findIndex( + ( style ) => style.name === activeStyle.name + ); + + const nextIndex = ( currentIndex + 1 ) % stylesToRender.length; + const nextStyle = stylesToRender[ nextIndex ]; + + const styleClassName = replaceActiveStyle( + className, + activeStyle, + nextStyle + ); + + updateBlockAttributes( clientId, { + className: styleClassName, + } ); + }; + + return ( + <ToolbarGroup> + <ToolbarButton + onClick={ handleStyleSwitch } + label={ __( 'Shuffle styles' ) } + > + <Icon + icon={ styleIcon } + style={ { + fill: activeStyleBackground || 'transparent', + } } + /> + </ToolbarButton> + </ToolbarGroup> + ); +} + +export default SwitchSectionStyle; From 02611cbbfe9d1082fa7ac878913de18e919682c3 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Sat, 23 Nov 2024 07:05:08 +0900 Subject: [PATCH 1680/1908] Composite: Restore `Hover` and `Typeahead` functionality (#67212) * Composite.Typeahead: Restore functionality * Add changelog * Resurrect CompositeHover * Update changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: im3dabasia <im3dabasia1@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: Mayank-Tripathi32 <mayanktripathi32@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/components/CHANGELOG.md | 7 +++---- packages/components/src/composite/hover.tsx | 2 +- packages/components/src/composite/typeahead.tsx | 4 +++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 1d6ed8745cb5da..564d9fcc683618 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,10 +2,6 @@ ## Unreleased -### Bug Fixes - -- `FormFileUpload`: Prevent HEIC and HEIF files from being uploaded on Safari ([#67139](https://github.com/WordPress/gutenberg/pull/67139)). - ### Deprecations - `DimensionControl`: Deprecate 36px default size ([#66705](https://github.com/WordPress/gutenberg/pull/66705)). @@ -23,6 +19,9 @@ - `GradientPicker`: Disable `Clear` button if there's no value. ([#67108](https://github.com/WordPress/gutenberg/pull/67108)). - `DuotonePicker`: Disable `Clear` button if there's no value. ([#67108](https://github.com/WordPress/gutenberg/pull/67108)). - `ColorPicker`: Add accessible label for copy button ([#67094](https://github.com/WordPress/gutenberg/pull/67094)). +- `FormFileUpload`: Prevent HEIC and HEIF files from being uploaded on Safari ([#67139](https://github.com/WordPress/gutenberg/pull/67139)). +- `Composite.Hover`: Restore functionality ([#67212](https://github.com/WordPress/gutenberg/pull/67212)). +- `Composite.Typeahead`: Restore functionality ([#67212](https://github.com/WordPress/gutenberg/pull/67212)). ### Enhancements diff --git a/packages/components/src/composite/hover.tsx b/packages/components/src/composite/hover.tsx index 1507a1879cc19f..a8a0ebfb4729fe 100644 --- a/packages/components/src/composite/hover.tsx +++ b/packages/components/src/composite/hover.tsx @@ -26,5 +26,5 @@ export const CompositeHover = forwardRef< // obfuscated to discourage its use outside of the component's internals. const store = ( props.store ?? context.store ) as Ariakit.CompositeStore; - return <Ariakit.CompositeGroup store={ store } { ...props } ref={ ref } />; + return <Ariakit.CompositeHover store={ store } { ...props } ref={ ref } />; } ); diff --git a/packages/components/src/composite/typeahead.tsx b/packages/components/src/composite/typeahead.tsx index 519c59ea374e5d..3a3c3875a33604 100644 --- a/packages/components/src/composite/typeahead.tsx +++ b/packages/components/src/composite/typeahead.tsx @@ -26,5 +26,7 @@ export const CompositeTypeahead = forwardRef< // obfuscated to discourage its use outside of the component's internals. const store = ( props.store ?? context.store ) as Ariakit.CompositeStore; - return <Ariakit.CompositeRow store={ store } { ...props } ref={ ref } />; + return ( + <Ariakit.CompositeTypeahead store={ store } { ...props } ref={ ref } /> + ); } ); From cbbb84802536dc5b5dd119d358865588a35c6ed4 Mon Sep 17 00:00:00 2001 From: Matias Benedetto <matias.benedetto@gmail.com> Date: Fri, 22 Nov 2024 19:50:35 -0300 Subject: [PATCH 1681/1908] Font family preview in the font family picker (#67118) * style font family option * use CustomSelectControl instead of Select * fix onchange callback * removing unwanted props * try e2e test fix to work with CustomSelectControl component * try fix e2e test * Fix test for font family combobox --------- Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../src/components/font-family/index.js | 26 +++++++++---------- .../specs/site-editor/font-library.spec.js | 3 ++- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/packages/block-editor/src/components/font-family/index.js b/packages/block-editor/src/components/font-family/index.js index c87a52b4c676d2..1e6c137daedb0f 100644 --- a/packages/block-editor/src/components/font-family/index.js +++ b/packages/block-editor/src/components/font-family/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { SelectControl } from '@wordpress/components'; +import { CustomSelectControl } from '@wordpress/components'; import deprecated from '@wordpress/deprecated'; import { __ } from '@wordpress/i18n'; @@ -30,13 +30,15 @@ export default function FontFamilyControl( { } const options = [ - { value: '', label: __( 'Default' ) }, - ...fontFamilies.map( ( { fontFamily, name } ) => { - return { - value: fontFamily, - label: name || fontFamily, - }; - } ), + { + key: '', + name: __( 'Default' ), + }, + ...fontFamilies.map( ( { fontFamily, name } ) => ( { + key: fontFamily, + name: name || fontFamily, + style: { fontFamily }, + } ) ), ]; if ( ! __nextHasNoMarginBottom ) { @@ -51,14 +53,12 @@ export default function FontFamilyControl( { } return ( - <SelectControl + <CustomSelectControl __next40pxDefaultSize={ __next40pxDefaultSize } - __nextHasNoMarginBottom={ __nextHasNoMarginBottom } label={ __( 'Font' ) } - options={ options } value={ value } - onChange={ onChange } - labelPosition="top" + onChange={ ( { selectedItem } ) => onChange( selectedItem.key ) } + options={ options } { ...props } /> ); diff --git a/test/e2e/specs/site-editor/font-library.spec.js b/test/e2e/specs/site-editor/font-library.spec.js index 7928ef8f71c534..1824257df12fd3 100644 --- a/test/e2e/specs/site-editor/font-library.spec.js +++ b/test/e2e/specs/site-editor/font-library.spec.js @@ -186,7 +186,8 @@ test.describe( 'Font Library', () => { await page .getByRole( 'button', { name: 'Headings', exact: true } ) .click(); - await page.getByLabel( 'Font' ).selectOption( 'Exo 2' ); + await page.getByRole( 'combobox', { name: 'Font' } ).click(); + await page.getByRole( 'option', { name: 'Exo 2' } ).click(); await expect( editor.canvas.locator( '.is-root-container h1' ) ).toHaveCSS( 'font-family', '"Exo 2"' ); From 326589db9246611cacbdc6065e80be75f72507e9 Mon Sep 17 00:00:00 2001 From: Doug Wollison <doug@wollison.net> Date: Sat, 23 Nov 2024 05:09:26 -0500 Subject: [PATCH 1682/1908] Format Library: Fix logic on hasColorsToChoose (#65530) Previous logic showed unusable Highlight format when palette was empty and custom was disabled, and hid it when custom was enabled but palette was empty. Co-authored-by: dougwollison <dougwollison@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/format-library/src/text-color/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/format-library/src/text-color/index.js b/packages/format-library/src/text-color/index.js index 9d8241544760bf..04fd8ee6ce55aa 100644 --- a/packages/format-library/src/text-color/index.js +++ b/packages/format-library/src/text-color/index.js @@ -75,7 +75,7 @@ function TextColorEdit( { [ contentRef, value, colors ] ); - const hasColorsToChoose = colors.length || ! allowCustomControl; + const hasColorsToChoose = !! colors.length || allowCustomControl; if ( ! hasColorsToChoose && ! isActive ) { return null; } From 2c5421de469f5bd694ff99e5bbc31b64cd1302b0 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Sun, 24 Nov 2024 18:45:17 +1100 Subject: [PATCH 1683/1908] Style panel: use correct revisions count (#67180) * For the styles panel, send the correct recordCount via optional prop to the footer component. This allows us to remove the globalstyle record selector. * Implement feedback Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../index.js | 18 +++++++++++--- .../index.js | 24 +++++++------------ 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-details-footer/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-details-footer/index.js index 3dec3f0a7b2eb5..51833443d8d85c 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-details-footer/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-details-footer/index.js @@ -23,6 +23,7 @@ import SidebarNavigationItem from '../sidebar-navigation-item'; export default function SidebarNavigationScreenDetailsFooter( { record, + revisionsCount, ...otherProps } ) { /* @@ -34,9 +35,20 @@ export default function SidebarNavigationScreenDetailsFooter( { const hrefProps = {}; const lastRevisionId = record?._links?.[ 'predecessor-version' ]?.[ 0 ]?.id ?? null; - const revisionsCount = - record?._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0; - // Enable the revisions link if there is a last revision and there are more than one revisions. + + // Use incoming prop first, then the record's version history, if available. + revisionsCount = + revisionsCount || + record?._links?.[ 'version-history' ]?.[ 0 ]?.count || + 0; + + /* + * Enable the revisions link if there is a last revision and there is more than one revision. + * This link is used for theme assets, e.g., templates, which have no database record until they're edited. + * For these files there's only a "revision" after they're edited twice, + * which means the revision.php page won't display a proper diff. + * See: https://github.com/WordPress/gutenberg/issues/49164. + */ if ( lastRevisionId && revisionsCount > 1 ) { hrefProps.href = addQueryArgs( 'revision.php', { revision: record?._links[ 'predecessor-version' ][ 0 ].id, diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js index 3dc93ff4d4df63..772b15aec2a294 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js @@ -48,24 +48,15 @@ export function SidebarNavigationItemGlobalStyles( props ) { export default function SidebarNavigationScreenGlobalStyles() { const history = useHistory(); const { params } = useLocation(); - const { revisions, isLoading: isLoadingRevisions } = - useGlobalStylesRevisions(); + const { + revisions, + isLoading: isLoadingRevisions, + revisionsCount, + } = useGlobalStylesRevisions(); const { openGeneralSidebar } = useDispatch( editSiteStore ); const { setEditorCanvasContainerView } = unlock( useDispatch( editSiteStore ) ); - const { revisionsCount } = useSelect( ( select ) => { - const { getEntityRecord, __experimentalGetCurrentGlobalStylesId } = - select( coreStore ); - const globalStylesId = __experimentalGetCurrentGlobalStylesId(); - const globalStyles = globalStylesId - ? getEntityRecord( 'root', 'globalStyles', globalStylesId ) - : undefined; - return { - revisionsCount: - globalStyles?._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0, - }; - }, [] ); const { set: setPreference } = useDispatch( preferencesStore ); const openGlobalStyles = useCallback( async () => { @@ -95,10 +86,10 @@ export default function SidebarNavigationScreenGlobalStyles() { }, [ openGlobalStyles, setEditorCanvasContainerView ] ); // If there are no revisions, do not render a footer. - const hasRevisions = revisionsCount > 0; const modifiedDateTime = revisions?.[ 0 ]?.modified; const shouldShowGlobalStylesFooter = - hasRevisions && ! isLoadingRevisions && modifiedDateTime; + revisionsCount > 0 && ! isLoadingRevisions && modifiedDateTime; + return ( <> <SidebarNavigationScreen @@ -114,6 +105,7 @@ export default function SidebarNavigationScreenGlobalStyles() { shouldShowGlobalStylesFooter && ( <SidebarNavigationScreenDetailsFooter record={ revisions?.[ 0 ] } + revisionsCount={ revisionsCount } onClick={ openRevisions } /> ) From 5513d7aecf085a7858cae0492acf213d65a436f6 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 25 Nov 2024 13:28:01 +1000 Subject: [PATCH 1684/1908] Block Supports: Extend stabilization to common experimental block support flags (#67018) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- backport-changelog/6.8/7069.md | 1 + docs/explanations/architecture/styles.md | 16 +- lib/compat/wordpress-6.8/blocks.php | 139 +++--- packages/block-editor/src/hooks/border.js | 10 +- packages/block-editor/src/hooks/color.js | 2 +- packages/block-editor/src/hooks/dimensions.js | 4 +- packages/block-editor/src/hooks/style.js | 18 +- packages/block-editor/src/hooks/test/style.js | 3 +- packages/block-editor/src/hooks/typography.js | 2 +- packages/block-editor/src/hooks/utils.js | 2 +- packages/blocks/src/api/constants.js | 12 +- .../blocks/src/store/process-block-type.js | 192 ++++++--- .../src/store/test/process-block-type.js | 395 ++++++++++-------- .../components/global-styles/screen-block.js | 5 +- packages/server-side-render/README.md | 2 +- phpunit/block-supports/border-test.php | 173 +++++++- 16 files changed, 638 insertions(+), 338 deletions(-) diff --git a/backport-changelog/6.8/7069.md b/backport-changelog/6.8/7069.md index 8b4ad69db02e75..69edbde58902d1 100644 --- a/backport-changelog/6.8/7069.md +++ b/backport-changelog/6.8/7069.md @@ -2,3 +2,4 @@ https://github.com/WordPress/wordpress-develop/pull/7069 * https://github.com/WordPress/gutenberg/pull/63401 * https://github.com/WordPress/gutenberg/pull/66918 +* https://github.com/WordPress/gutenberg/pull/67018 diff --git a/docs/explanations/architecture/styles.md b/docs/explanations/architecture/styles.md index 68f09f04d21d32..5f5e73d1372f7b 100644 --- a/docs/explanations/architecture/styles.md +++ b/docs/explanations/architecture/styles.md @@ -37,8 +37,10 @@ The user may change the state of this block by applying different styles: a text After some user modifications to the block, the initial markup may become something like this: ```html -<p class="has-color has-green-color has-font-size has-small-font-size my-custom-class" - style="line-height: 1em"></p> +<p + class="has-color has-green-color has-font-size has-small-font-size my-custom-class" + style="line-height: 1em" +></p> ``` This is what we refer to as "user-provided block styles", also know as "local styles" or "serialized styles". Essentially, each tool (font size, color, etc) ends up adding some classes and/or inline styles to the block markup. The CSS styling for these classes is part of the block, global, or theme stylesheets. @@ -123,7 +125,7 @@ The block supports API only serializes the font size value to the wrapper, resul This is an active area of work you can follow [in the tracking issue](https://github.com/WordPress/gutenberg/issues/38167). The linked proposal is exploring a different way to serialize the user changes: instead of each block support serializing its own data (for example, classes such as `has-small-font-size`, `has-green-color`) the idea is the block would get a single class instead (for example, `wp-style-UUID`) and the CSS styling for that class will be generated in the server by WordPress. -While work continues in that proposal, there's an escape hatch, an experimental option block authors can use. Any block support can skip the serialization to HTML markup by using `__experimentalSkipSerialization`. For example: +While work continues in that proposal, there's an escape hatch, an experimental option block authors can use. Any block support can skip the serialization to HTML markup by using `skipSerialization`. For example: ```json { @@ -132,7 +134,7 @@ While work continues in that proposal, there's an escape hatch, an experimental "supports": { "typography": { "fontSize": true, - "__experimentalSkipSerialization": true + "skipSerialization": true } } } @@ -140,7 +142,7 @@ While work continues in that proposal, there's an escape hatch, an experimental This means that the typography block support will do all of the things (create a UI control, bind the block attribute to the control, etc) except serializing the user values into the HTML markup. The classes and inline styles will not be automatically applied to the wrapper and it is the block author's responsibility to implement this in the `edit`, `save`, and `render_callback` functions. See [this issue](https://github.com/WordPress/gutenberg/issues/28913) for examples of how it was done for some blocks provided by WordPress. -Note that, if `__experimentalSkipSerialization` is enabled for a group (typography, color, spacing) it affects _all_ block supports within this group. In the example above _all_ the properties within the `typography` group will be affected (e.g. `fontSize`, `lineHeight`, `fontFamily` .etc). +Note that, if `skipSerialization` is enabled for a group (typography, color, spacing) it affects _all_ block supports within this group. In the example above _all_ the properties within the `typography` group will be affected (e.g. `fontSize`, `lineHeight`, `fontFamily` .etc). To enable for a _single_ property only, you may use an array to declare which properties are to be skipped. In the example below, only `fontSize` will skip serialization, leaving other items within the `typography` group (e.g. `lineHeight`, `fontFamily` .etc) unaffected. @@ -152,7 +154,7 @@ To enable for a _single_ property only, you may use an array to declare which pr "typography": { "fontSize": true, "lineHeight": true, - "__experimentalSkipSerialization": [ "fontSize" ] + "skipSerialization": [ "fontSize" ] } } } @@ -473,7 +475,7 @@ If blocks do this, they need to be registered in the server using the `block.jso Every chunk of styles can only use a single selector. -This is particularly relevant if the block is using `__experimentalSkipSerialization` to serialize the different style properties to different nodes other than the wrapper. See "Current limitations of blocks supports" for more. +This is particularly relevant if the block is using `skipSerialization` to serialize the different style properties to different nodes other than the wrapper. See "Current limitations of blocks supports" for more. #### 3. **Only a single property per block** diff --git a/lib/compat/wordpress-6.8/blocks.php b/lib/compat/wordpress-6.8/blocks.php index 0b7031403b1918..4d4bdee2bb393b 100644 --- a/lib/compat/wordpress-6.8/blocks.php +++ b/lib/compat/wordpress-6.8/blocks.php @@ -20,8 +20,13 @@ function gutenberg_stabilize_experimental_block_supports( $args ) { return $args; } - $experimental_to_stable_keys = array( - 'typography' => array( + $experimental_supports_map = array( '__experimentalBorder' => 'border' ); + $common_experimental_properties = array( + '__experimentalDefaultControls' => 'defaultControls', + '__experimentalSkipSerialization' => 'skipSerialization', + ); + $experimental_support_properties = array( + 'typography' => array( '__experimentalFontFamily' => 'fontFamily', '__experimentalFontStyle' => 'fontStyle', '__experimentalFontWeight' => 'fontWeight', @@ -29,68 +34,108 @@ function gutenberg_stabilize_experimental_block_supports( $args ) { '__experimentalTextDecoration' => 'textDecoration', '__experimentalTextTransform' => 'textTransform', ), - '__experimentalBorder' => 'border', ); + $done = array(); $updated_supports = array(); foreach ( $args['supports'] as $support => $config ) { - // Add the support's config as is when it's not in need of stabilization. - if ( empty( $experimental_to_stable_keys[ $support ] ) ) { + /* + * If this support config has already been stabilized, skip it. + * A stable support key occurring after an experimental key, gets + * stabilized then so that the two configs can be merged effectively. + */ + if ( isset( $done[ $support ] ) ) { + continue; + } + + $stable_support_key = $experimental_supports_map[ $support ] ?? $support; + + /* + * Use the support's config as is when it's not in need of stabilization. + * + * A support does not need stabilization if: + * - The support key doesn't need stabilization AND + * - Either: + * - The config isn't an array, so can't have experimental properties OR + * - The config is an array but has no experimental properties to stabilize. + */ + if ( $support === $stable_support_key && + ( ! is_array( $config ) || + ( ! isset( $experimental_support_properties[ $stable_support_key ] ) && + empty( array_intersect_key( $common_experimental_properties, $config ) ) + ) + ) + ) { $updated_supports[ $support ] = $config; continue; } - // Stabilize the support's key if needed e.g. __experimentalBorder => border. - if ( is_string( $experimental_to_stable_keys[ $support ] ) ) { - $stabilized_key = $experimental_to_stable_keys[ $support ]; + $stabilize_config = function ( $unstable_config, $stable_support_key ) use ( $experimental_support_properties, $common_experimental_properties ) { + $stable_config = array(); + foreach ( $unstable_config as $key => $value ) { + // Get stable key from support-specific map, common properties map, or keep original. + $stable_key = $experimental_support_properties[ $stable_support_key ][ $key ] ?? + $common_experimental_properties[ $key ] ?? + $key; + + $stable_config[ $stable_key ] = $value; - // If there is no stabilized key present, use the experimental config as is. - if ( ! array_key_exists( $stabilized_key, $args['supports'] ) ) { - $updated_supports[ $stabilized_key ] = $config; - continue; + /* + * The `__experimentalSkipSerialization` key needs to be kept until + * WP 6.8 becomes the minimum supported version. This is due to the + * core `wp_should_skip_block_supports_serialization` function only + * checking for `__experimentalSkipSerialization` in earlier versions. + */ + if ( '__experimentalSkipSerialization' === $key || 'skipSerialization' === $key ) { + $stable_config['__experimentalSkipSerialization'] = $value; + } } + return $stable_config; + }; - /* - * Determine the order of keys, so the last defined can be preferred. - * - * The reason for preferring the last defined key is that after filters - * are applied, the last inserted key is likely the most up-to-date value. - * We cannot determine with certainty which value was "last modified" so - * the insertion order is the best guess. The extreme edge case of multiple - * filters tweaking the same support property will become less over time as - * extenders migrate existing blocks and plugins to stable keys. - */ + // Stabilize the config value. + $stable_config = is_array( $config ) ? $stabilize_config( $config, $stable_support_key ) : $config; + + /* + * If a plugin overrides the support config with the `register_block_type_args` + * filter, both experimental and stable configs may be present. In that case, + * use the order keys are defined in to determine the final value. + * - If config is an array, merge the arrays in their order of definition. + * - If config is not an array, use the value defined last. + * + * The reason for preferring the last defined key is that after filters + * are applied, the last inserted key is likely the most up-to-date value. + * We cannot determine with certainty which value was "last modified" so + * the insertion order is the best guess. The extreme edge case of multiple + * filters tweaking the same support property will become less over time as + * extenders migrate existing blocks and plugins to stable keys. + */ + if ( $support !== $stable_support_key && isset( $args['supports'][ $stable_support_key ] ) ) { $key_positions = array_flip( array_keys( $args['supports'] ) ); - $experimental_index = $key_positions[ $support ] ?? -1; - $stabilized_index = $key_positions[ $stabilized_key ] ?? -1; - $experimental_first = $experimental_index < $stabilized_index; + $experimental_first = + ( $key_positions[ $support ] ?? PHP_INT_MAX ) < + ( $key_positions[ $stable_support_key ] ?? PHP_INT_MAX ); - // Update support config, prefer the last defined value. - if ( is_array( $config ) ) { - $updated_supports[ $stabilized_key ] = $experimental_first - ? array_merge( $config, $args['supports'][ $stabilized_key ] ) - : array_merge( $args['supports'][ $stabilized_key ], $config ); + if ( is_array( $args['supports'][ $stable_support_key ] ) ) { + /* + * To merge the alternative support config effectively, it also needs to be + * stabilized before merging to keep stabilized and experimental flags in + * sync. + */ + $args['supports'][ $stable_support_key ] = $stabilize_config( $args['supports'][ $stable_support_key ], $stable_support_key ); + $stable_config = $experimental_first + ? array_merge( $stable_config, $args['supports'][ $stable_support_key ] ) + : array_merge( $args['supports'][ $stable_support_key ], $stable_config ); + // Prevents reprocessing this support as it was merged above. + $done[ $stable_support_key ] = true; } else { - $updated_supports[ $stabilized_key ] = $experimental_first - ? $args['supports'][ $stabilized_key ] - : $config; + $stable_config = $experimental_first + ? $args['supports'][ $stable_support_key ] + : $stable_config; } - - continue; } - // Stabilize individual support feature keys e.g. __experimentalFontFamily => fontFamily. - if ( is_array( $experimental_to_stable_keys[ $support ] ) ) { - $stable_support_config = array(); - foreach ( $config as $key => $value ) { - if ( array_key_exists( $key, $experimental_to_stable_keys[ $support ] ) ) { - $stable_support_config[ $experimental_to_stable_keys[ $support ][ $key ] ] = $value; - } else { - $stable_support_config[ $key ] = $value; - } - } - $updated_supports[ $support ] = $stable_support_config; - } + $updated_supports[ $stable_support_key ] = $stable_config; } $args['supports'] = $updated_supports; diff --git a/packages/block-editor/src/hooks/border.js b/packages/block-editor/src/hooks/border.js index 4500444685befa..14b3dbf7669b3a 100644 --- a/packages/block-editor/src/hooks/border.js +++ b/packages/block-editor/src/hooks/border.js @@ -161,14 +161,8 @@ export function BorderPanel( { clientId, name, setAttributes, settings } ) { } const defaultControls = { - ...getBlockSupport( name, [ - BORDER_SUPPORT_KEY, - '__experimentalDefaultControls', - ] ), - ...getBlockSupport( name, [ - SHADOW_SUPPORT_KEY, - '__experimentalDefaultControls', - ] ), + ...getBlockSupport( name, [ BORDER_SUPPORT_KEY, 'defaultControls' ] ), + ...getBlockSupport( name, [ SHADOW_SUPPORT_KEY, 'defaultControls' ] ), }; return ( diff --git a/packages/block-editor/src/hooks/color.js b/packages/block-editor/src/hooks/color.js index ef8984c9367853..2fecc10a311984 100644 --- a/packages/block-editor/src/hooks/color.js +++ b/packages/block-editor/src/hooks/color.js @@ -290,7 +290,7 @@ export function ColorEdit( { clientId, name, setAttributes, settings } ) { const defaultControls = getBlockSupport( name, [ COLOR_SUPPORT_KEY, - '__experimentalDefaultControls', + 'defaultControls', ] ); const enableContrastChecking = diff --git a/packages/block-editor/src/hooks/dimensions.js b/packages/block-editor/src/hooks/dimensions.js index ffa4048b7740e3..c98cc34e4272c8 100644 --- a/packages/block-editor/src/hooks/dimensions.js +++ b/packages/block-editor/src/hooks/dimensions.js @@ -88,11 +88,11 @@ export function DimensionsPanel( { clientId, name, setAttributes, settings } ) { const defaultDimensionsControls = getBlockSupport( name, [ DIMENSIONS_SUPPORT_KEY, - '__experimentalDefaultControls', + 'defaultControls', ] ); const defaultSpacingControls = getBlockSupport( name, [ SPACING_SUPPORT_KEY, - '__experimentalDefaultControls', + 'defaultControls', ] ); const defaultControls = { ...defaultDimensionsControls, diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index 998d13cfd22247..db2acd01665b60 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -98,22 +98,16 @@ function addAttribute( settings ) { * @type {Record<string, string[]>} */ const skipSerializationPathsEdit = { - [ `${ BORDER_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [ 'border' ], - [ `${ COLOR_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [ - COLOR_SUPPORT_KEY, - ], - [ `${ TYPOGRAPHY_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [ + [ `${ BORDER_SUPPORT_KEY }.skipSerialization` ]: [ 'border' ], + [ `${ COLOR_SUPPORT_KEY }.skipSerialization` ]: [ COLOR_SUPPORT_KEY ], + [ `${ TYPOGRAPHY_SUPPORT_KEY }.skipSerialization` ]: [ TYPOGRAPHY_SUPPORT_KEY, ], - [ `${ DIMENSIONS_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [ + [ `${ DIMENSIONS_SUPPORT_KEY }.skipSerialization` ]: [ DIMENSIONS_SUPPORT_KEY, ], - [ `${ SPACING_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [ - SPACING_SUPPORT_KEY, - ], - [ `${ SHADOW_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [ - SHADOW_SUPPORT_KEY, - ], + [ `${ SPACING_SUPPORT_KEY }.skipSerialization` ]: [ SPACING_SUPPORT_KEY ], + [ `${ SHADOW_SUPPORT_KEY }.skipSerialization` ]: [ SHADOW_SUPPORT_KEY ], }; /** diff --git a/packages/block-editor/src/hooks/test/style.js b/packages/block-editor/src/hooks/test/style.js index 2cfe299b8c8d91..40e7169194b82e 100644 --- a/packages/block-editor/src/hooks/test/style.js +++ b/packages/block-editor/src/hooks/test/style.js @@ -133,8 +133,7 @@ describe( 'addSaveProps', () => { const applySkipSerialization = ( features ) => { const updatedSettings = { ...blockSettings }; Object.keys( features ).forEach( ( key ) => { - updatedSettings.supports[ key ].__experimentalSkipSerialization = - features[ key ]; + updatedSettings.supports[ key ].skipSerialization = features[ key ]; } ); return updatedSettings; }; diff --git a/packages/block-editor/src/hooks/typography.js b/packages/block-editor/src/hooks/typography.js index ab9a464fe5efbc..160894eac4e610 100644 --- a/packages/block-editor/src/hooks/typography.js +++ b/packages/block-editor/src/hooks/typography.js @@ -133,7 +133,7 @@ export function TypographyPanel( { clientId, name, setAttributes, settings } ) { const defaultControls = getBlockSupport( name, [ TYPOGRAPHY_SUPPORT_KEY, - '__experimentalDefaultControls', + 'defaultControls', ] ); return ( diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index 4334f70b9d13bf..ac6e55efe4d3bd 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -124,7 +124,7 @@ export function shouldSkipSerialization( feature ) { const support = getBlockSupport( blockNameOrType, featureSet ); - const skipSerialization = support?.__experimentalSkipSerialization; + const skipSerialization = support?.skipSerialization; if ( Array.isArray( skipSerialization ) ) { return skipSerialization.includes( feature ); diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js index 8ea32d591adb32..aaf6558c47bada 100644 --- a/packages/blocks/src/api/constants.js +++ b/packages/blocks/src/api/constants.js @@ -298,7 +298,16 @@ export const __EXPERIMENTAL_PATHS_WITH_OVERRIDE = { 'spacing.spacingSizes': true, }; -export const EXPERIMENTAL_TO_STABLE_KEYS = { +export const EXPERIMENTAL_SUPPORTS_MAP = { + __experimentalBorder: 'border', +}; + +export const COMMON_EXPERIMENTAL_PROPERTIES = { + __experimentalDefaultControls: 'defaultControls', + __experimentalSkipSerialization: 'skipSerialization', +}; + +export const EXPERIMENTAL_SUPPORT_PROPERTIES = { typography: { __experimentalFontFamily: 'fontFamily', __experimentalFontStyle: 'fontStyle', @@ -307,5 +316,4 @@ export const EXPERIMENTAL_TO_STABLE_KEYS = { __experimentalTextDecoration: 'textDecoration', __experimentalTextTransform: 'textTransform', }, - __experimentalBorder: 'border', }; diff --git a/packages/blocks/src/store/process-block-type.js b/packages/blocks/src/store/process-block-type.js index bd7e5ab43800f0..0ca28a3c3e2070 100644 --- a/packages/blocks/src/store/process-block-type.js +++ b/packages/blocks/src/store/process-block-type.js @@ -18,7 +18,9 @@ import { isValidIcon, normalizeIconObject, omit } from '../api/utils'; import { BLOCK_ICON_DEFAULT, DEPRECATED_ENTRY_KEYS, - EXPERIMENTAL_TO_STABLE_KEYS, + EXPERIMENTAL_SUPPORTS_MAP, + COMMON_EXPERIMENTAL_PROPERTIES, + EXPERIMENTAL_SUPPORT_PROPERTIES, } from '../api/constants'; /** @typedef {import('../api/registration').WPBlockType} WPBlockType */ @@ -66,81 +68,149 @@ function mergeBlockVariations( return result; } +/** + * Stabilizes a block support configuration by converting experimental properties + * to their stable equivalents. + * + * @param {Object} unstableConfig The support configuration to stabilize. + * @param {string} stableSupportKey The stable support key for looking up properties. + * @return {Object} The stabilized support configuration. + */ +function stabilizeSupportConfig( unstableConfig, stableSupportKey ) { + const stableConfig = {}; + for ( const [ key, value ] of Object.entries( unstableConfig ) ) { + // Get stable key from support-specific map, common properties map, or keep original. + const stableKey = + EXPERIMENTAL_SUPPORT_PROPERTIES[ stableSupportKey ]?.[ key ] ?? + COMMON_EXPERIMENTAL_PROPERTIES[ key ] ?? + key; + + stableConfig[ stableKey ] = value; + + /* + * The `__experimentalSkipSerialization` key needs to be kept until + * WP 6.8 becomes the minimum supported version. This is due to the + * core `wp_should_skip_block_supports_serialization` function only + * checking for `__experimentalSkipSerialization` in earlier versions. + */ + if ( + key === '__experimentalSkipSerialization' || + key === 'skipSerialization' + ) { + stableConfig.__experimentalSkipSerialization = value; + } + } + return stableConfig; +} + +/** + * Stabilizes experimental block supports by converting experimental keys and properties + * to their stable equivalents. + * + * @param {Object|undefined} rawSupports The block supports configuration to stabilize. + * @return {Object|undefined} The stabilized block supports configuration. + */ function stabilizeSupports( rawSupports ) { if ( ! rawSupports ) { return rawSupports; } - // Create a new object to avoid mutating the original. This ensures that - // custom block plugins that rely on immutable supports are not affected. - // See: https://github.com/WordPress/gutenberg/pull/66849#issuecomment-2463614281 + /* + * Create a new object to avoid mutating the original. This ensures that + * custom block plugins that rely on immutable supports are not affected. + * See: https://github.com/WordPress/gutenberg/pull/66849#issuecomment-2463614281 + */ const newSupports = {}; + const done = {}; for ( const [ support, config ] of Object.entries( rawSupports ) ) { - // Add the support's config as is when it's not in need of stabilization. - if ( ! EXPERIMENTAL_TO_STABLE_KEYS[ support ] ) { - newSupports[ support ] = config; + /* + * If this support config has already been stabilized, skip it. + * A stable support key occurring after an experimental key, gets + * stabilized then so that the two configs can be merged effectively. + */ + if ( done[ support ] ) { continue; } - // Stabilize the support's key if needed e.g. __experimentalBorder => border. - if ( typeof EXPERIMENTAL_TO_STABLE_KEYS[ support ] === 'string' ) { - const stabilizedKey = EXPERIMENTAL_TO_STABLE_KEYS[ support ]; - - // If there is no stabilized key present, use the experimental config as is. - if ( ! Object.hasOwn( rawSupports, stabilizedKey ) ) { - newSupports[ stabilizedKey ] = config; - continue; - } - - /* - * Determine the order of keys, so the last defined can be preferred. - * - * The reason for preferring the last defined key is that after filters - * are applied, the last inserted key is likely the most up-to-date value. - * We cannot determine with certainty which value was "last modified" so - * the insertion order is the best guess. The extreme edge case of multiple - * filters tweaking the same support property will become less over time as - * extenders migrate existing blocks and plugins to stable keys. - */ - const entries = Object.entries( rawSupports ); - const experimentalIndex = entries.findIndex( - ( [ key ] ) => key === support - ); - const stabilizedIndex = entries.findIndex( - ( [ key ] ) => key === stabilizedKey - ); - - // Update support config, prefer the last defined value. - if ( typeof config === 'object' && config !== null ) { - newSupports[ stabilizedKey ] = - experimentalIndex < stabilizedIndex - ? { ...config, ...rawSupports[ stabilizedKey ] } - : { ...rawSupports[ stabilizedKey ], ...config }; - } else { - newSupports[ stabilizedKey ] = - experimentalIndex < stabilizedIndex - ? rawSupports[ stabilizedKey ] - : config; - } + const stableSupportKey = + EXPERIMENTAL_SUPPORTS_MAP[ support ] ?? support; + + /* + * Use the support's config as is when it's not in need of stabilization. + * A support does not need stabilization if: + * - The support key doesn't need stabilization AND + * - Either: + * - The config isn't an object, so can't have experimental properties OR + * - The config is an object but has no experimental properties to stabilize. + */ + if ( + support === stableSupportKey && + ( ! isPlainObject( config ) || + ( ! EXPERIMENTAL_SUPPORT_PROPERTIES[ stableSupportKey ] && + Object.keys( config ).every( + ( key ) => ! COMMON_EXPERIMENTAL_PROPERTIES[ key ] + ) ) ) + ) { + newSupports[ support ] = config; continue; } - // Stabilize individual support feature keys - // e.g. __experimentalFontFamily => fontFamily. - const featureStabilizationRequired = - typeof EXPERIMENTAL_TO_STABLE_KEYS[ support ] === 'object' && - EXPERIMENTAL_TO_STABLE_KEYS[ support ] !== null; - const hasConfig = typeof config === 'object' && config !== null; - - if ( featureStabilizationRequired && hasConfig ) { - const stableConfig = {}; - for ( const [ key, value ] of Object.entries( config ) ) { - const stableKey = - EXPERIMENTAL_TO_STABLE_KEYS[ support ][ key ] || key; - stableConfig[ stableKey ] = value; + // Stabilize the config value. + const stableConfig = isPlainObject( config ) + ? stabilizeSupportConfig( config, stableSupportKey ) + : config; + + /* + * If a plugin overrides the support config with the `blocks.registerBlockType` + * filter, both experimental and stable configs may be present. In that case, + * use the order keys are defined in to determine the final value. + * - If config is an array, merge the arrays in their order of definition. + * - If config is not an array, use the value defined last. + * + * The reason for preferring the last defined key is that after filters + * are applied, the last inserted key is likely the most up-to-date value. + * We cannot determine with certainty which value was "last modified" so + * the insertion order is the best guess. The extreme edge case of multiple + * filters tweaking the same support property will become less over time as + * extenders migrate existing blocks and plugins to stable keys. + */ + if ( + support !== stableSupportKey && + Object.hasOwn( rawSupports, stableSupportKey ) + ) { + const keyPositions = Object.keys( rawSupports ).reduce( + ( acc, key, index ) => { + acc[ key ] = index; + return acc; + }, + {} + ); + const experimentalFirst = + ( keyPositions[ support ] ?? Number.MAX_VALUE ) < + ( keyPositions[ stableSupportKey ] ?? Number.MAX_VALUE ); + + if ( isPlainObject( rawSupports[ stableSupportKey ] ) ) { + /* + * To merge the alternative support config effectively, it also needs to be + * stabilized before merging to keep stabilized and experimental flags in sync. + */ + rawSupports[ stableSupportKey ] = stabilizeSupportConfig( + rawSupports[ stableSupportKey ], + stableSupportKey + ); + newSupports[ stableSupportKey ] = experimentalFirst + ? { ...stableConfig, ...rawSupports[ stableSupportKey ] } + : { ...rawSupports[ stableSupportKey ], ...stableConfig }; + // Prevents reprocessing this support as it was merged above. + done[ stableSupportKey ] = true; + } else { + newSupports[ stableSupportKey ] = experimentalFirst + ? rawSupports[ stableSupportKey ] + : stableConfig; } - newSupports[ support ] = stableConfig; + } else { + newSupports[ stableSupportKey ] = stableConfig; } } diff --git a/packages/blocks/src/store/test/process-block-type.js b/packages/blocks/src/store/test/process-block-type.js index c7f487a95301d0..82b2c1ad3080d7 100644 --- a/packages/blocks/src/store/test/process-block-type.js +++ b/packages/blocks/src/store/test/process-block-type.js @@ -26,7 +26,7 @@ describe( 'processBlockType', () => { removeFilter( 'blocks.registerBlockType', 'test/filterSupports' ); } ); - it( 'should return the block type with stabilized supports', () => { + it( 'should stabilize experimental block supports', () => { const blockSettings = { ...baseBlockSettings, supports: { @@ -66,7 +66,7 @@ describe( 'processBlockType', () => { blockSettings )( { select } ); - expect( processedBlockType.supports ).toEqual( { + expect( processedBlockType.supports ).toMatchObject( { typography: { fontSize: true, lineHeight: true, @@ -77,7 +77,7 @@ describe( 'processBlockType', () => { textTransform: true, textDecoration: true, __experimentalWritingMode: true, - __experimentalDefaultControls: { + defaultControls: { fontSize: true, fontAppearance: true, textTransform: true, @@ -88,79 +88,7 @@ describe( 'processBlockType', () => { radius: true, style: true, width: true, - __experimentalDefaultControls: { - color: true, - radius: true, - style: true, - width: true, - }, - }, - } ); - } ); - - it( 'should return the block type with stable supports', () => { - const blockSettings = { - ...baseBlockSettings, - supports: { - typography: { - fontSize: true, - lineHeight: true, - fontFamily: true, - fontStyle: true, - fontWeight: true, - letterSpacing: true, - textTransform: true, - textDecoration: true, - __experimentalWritingMode: true, - __experimentalDefaultControls: { - fontSize: true, - fontAppearance: true, - textTransform: true, - }, - }, - __experimentalBorder: { - color: true, - radius: true, - style: true, - width: true, - __experimentalDefaultControls: { - color: true, - radius: true, - style: true, - width: true, - }, - }, - }, - }; - - const processedBlockType = processBlockType( - 'test/block', - blockSettings - )( { select } ); - - expect( processedBlockType.supports ).toEqual( { - typography: { - fontSize: true, - lineHeight: true, - fontFamily: true, - fontStyle: true, - fontWeight: true, - letterSpacing: true, - textTransform: true, - textDecoration: true, - __experimentalWritingMode: true, - __experimentalDefaultControls: { - fontSize: true, - fontAppearance: true, - textTransform: true, - }, - }, - border: { - color: true, - radius: true, - style: true, - width: true, - __experimentalDefaultControls: { + defaultControls: { color: true, radius: true, style: true, @@ -227,7 +155,7 @@ describe( 'processBlockType', () => { blockSettings )( { select } ); - expect( processedBlockType.supports ).toEqual( { + expect( processedBlockType.supports ).toMatchObject( { typography: { fontSize: true, lineHeight: true, @@ -238,7 +166,7 @@ describe( 'processBlockType', () => { textTransform: true, textDecoration: true, __experimentalWritingMode: true, - __experimentalDefaultControls: { + defaultControls: { fontSize: true, fontAppearance: true, textTransform: true, @@ -249,7 +177,7 @@ describe( 'processBlockType', () => { radius: false, style: true, width: true, - __experimentalDefaultControls: { + defaultControls: { color: true, radius: true, style: true, @@ -259,8 +187,8 @@ describe( 'processBlockType', () => { } ); } ); - it( 'should stabilize experimental supports within block deprecations', () => { - const blockSettings = { + describe( 'block deprecations', () => { + const deprecatedBlockSettings = { ...baseBlockSettings, supports: { typography: { @@ -321,145 +249,242 @@ describe( 'processBlockType', () => { ], }; - // Freeze the deprecated block object and its supports so that the original is not mutated. - // This ensures the test covers a regression where the original object was mutated. - // See: https://github.com/WordPress/gutenberg/pull/63401#discussion_r1832394335. - Object.freeze( blockSettings.deprecated[ 0 ] ); - Object.freeze( blockSettings.deprecated[ 0 ].supports ); + beforeEach( () => { + // Freeze the deprecated block object and its supports so that the original is not mutated. + Object.freeze( deprecatedBlockSettings.deprecated[ 0 ] ); + Object.freeze( deprecatedBlockSettings.deprecated[ 0 ].supports ); + } ); + + it( 'should stabilize experimental supports', () => { + const processedBlockType = processBlockType( + 'test/block', + deprecatedBlockSettings + )( { select } ); + + expect( processedBlockType.deprecated[ 0 ].supports ).toMatchObject( + { + typography: { + fontFamily: true, + fontStyle: true, + fontWeight: true, + letterSpacing: true, + textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + }, + border: { + color: true, + radius: true, + style: true, + width: true, + defaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, + }, + } + ); + } ); + + it( 'should reapply transformations after supports are filtered', () => { + addFilter( + 'blocks.registerBlockType', + 'test/filterSupports', + ( settings, name ) => { + if ( + name === 'test/block' && + settings.supports.typography + ) { + settings.supports.typography.__experimentalFontFamily = false; + settings.supports.typography.__experimentalFontStyle = false; + settings.supports.typography.__experimentalFontWeight = false; + settings.supports.__experimentalBorder = { + radius: false, + }; + } + return settings; + } + ); + + const processedBlockType = processBlockType( + 'test/block', + deprecatedBlockSettings + )( { select } ); + + expect( processedBlockType.deprecated[ 0 ].supports ).toMatchObject( + { + typography: { + fontFamily: false, + fontStyle: false, + fontWeight: false, + letterSpacing: true, + textTransform: true, + textDecoration: true, + __experimentalWritingMode: true, + }, + border: { + color: true, + radius: false, + style: true, + width: true, + defaultControls: { + color: true, + radius: true, + style: true, + width: true, + }, + }, + } + ); + } ); + } ); + + it( 'should stabilize common experimental properties across all supports', () => { + const blockSettings = { + ...baseBlockSettings, + supports: { + typography: { + fontSize: true, + __experimentalDefaultControls: { + fontSize: true, + }, + __experimentalSkipSerialization: true, + }, + spacing: { + padding: true, + __experimentalDefaultControls: { + padding: true, + }, + __experimentalSkipSerialization: true, + }, + }, + }; const processedBlockType = processBlockType( 'test/block', blockSettings )( { select } ); - expect( processedBlockType.deprecated[ 0 ].supports ).toEqual( { + expect( processedBlockType.supports ).toMatchObject( { typography: { - fontFamily: true, - fontStyle: true, - fontWeight: true, - letterSpacing: true, - textTransform: true, - textDecoration: true, - __experimentalWritingMode: true, + fontSize: true, + defaultControls: { + fontSize: true, + }, + skipSerialization: true, + __experimentalSkipSerialization: true, }, - border: { - color: true, - radius: true, - style: true, - width: true, - __experimentalDefaultControls: { - color: true, - radius: true, - style: true, - width: true, + spacing: { + padding: true, + defaultControls: { + padding: true, }, + skipSerialization: true, + __experimentalSkipSerialization: true, }, } ); } ); - it( 'should reapply transformations after supports are filtered within block deprecations', () => { + it( 'should merge experimental and stable keys in order of definition', () => { const blockSettings = { ...baseBlockSettings, supports: { - typography: { - fontSize: true, - lineHeight: true, - fontFamily: true, - fontStyle: true, - fontWeight: true, - letterSpacing: true, - textTransform: true, - textDecoration: true, - __experimentalWritingMode: true, - __experimentalDefaultControls: { - fontSize: true, - fontAppearance: true, - textTransform: true, - }, + __experimentalBorder: { + color: true, + radius: false, }, border: { - color: true, - radius: true, + color: false, style: true, - width: true, - __experimentalDefaultControls: { - color: true, - radius: true, - style: true, - width: true, - }, }, }, - deprecated: [ - { - supports: { - typography: { - __experimentalFontFamily: true, - __experimentalFontStyle: true, - __experimentalFontWeight: true, - __experimentalLetterSpacing: true, - __experimentalTextTransform: true, - __experimentalTextDecoration: true, - __experimentalWritingMode: true, - }, - __experimentalBorder: { - color: true, - radius: true, - style: true, - width: true, - __experimentalDefaultControls: { - color: true, - radius: true, - style: true, - width: true, - }, - }, - }, - }, - ], }; - addFilter( - 'blocks.registerBlockType', - 'test/filterSupports', - ( settings, name ) => { - if ( name === 'test/block' && settings.supports.typography ) { - settings.supports.typography.__experimentalFontFamily = false; - settings.supports.typography.__experimentalFontStyle = false; - settings.supports.typography.__experimentalFontWeight = false; - settings.supports.__experimentalBorder = { radius: false }; - } - return settings; - } - ); - const processedBlockType = processBlockType( 'test/block', blockSettings )( { select } ); - expect( processedBlockType.deprecated[ 0 ].supports ).toEqual( { - typography: { - fontFamily: false, - fontStyle: false, - fontWeight: false, - letterSpacing: true, - textTransform: true, - textDecoration: true, - __experimentalWritingMode: true, + expect( processedBlockType.supports ).toMatchObject( { + border: { + color: false, + radius: false, + style: true, }, + } ); + + const reversedSettings = { + ...baseBlockSettings, + supports: { + border: { + color: false, + style: true, + }, + __experimentalBorder: { + color: true, + radius: false, + }, + }, + }; + + const reversedProcessedType = processBlockType( + 'test/block', + reversedSettings + )( { select } ); + + expect( reversedProcessedType.supports ).toMatchObject( { border: { color: true, radius: false, style: true, - width: true, - __experimentalDefaultControls: { - color: true, - radius: true, - style: true, - width: true, + }, + } ); + } ); + + it( 'should handle non-object config values', () => { + const blockSettings = { + ...baseBlockSettings, + supports: { + __experimentalBorder: true, + border: false, + }, + }; + + const processedBlockType = processBlockType( + 'test/block', + blockSettings + )( { select } ); + + expect( processedBlockType.supports ).toMatchObject( { + border: false, + } ); + } ); + + it( 'should not modify supports that do not need stabilization', () => { + const blockSettings = { + ...baseBlockSettings, + supports: { + align: true, + spacing: { + padding: true, + margin: true, }, }, + }; + + const processedBlockType = processBlockType( + 'test/block', + blockSettings + )( { select } ); + + expect( processedBlockType.supports ).toMatchObject( { + align: true, + spacing: { + padding: true, + margin: true, + }, } ); } ); } ); diff --git a/packages/edit-site/src/components/global-styles/screen-block.js b/packages/edit-site/src/components/global-styles/screen-block.js index 64f49574b6b03b..347d3cd1bc0a73 100644 --- a/packages/edit-site/src/components/global-styles/screen-block.js +++ b/packages/edit-site/src/components/global-styles/screen-block.js @@ -113,9 +113,8 @@ function ScreenBlock( { name, variation } ) { if ( settingsForBlockElement?.spacing?.blockGap && blockType?.supports?.spacing?.blockGap && - ( blockType?.supports?.spacing?.__experimentalSkipSerialization === - true || - blockType?.supports?.spacing?.__experimentalSkipSerialization?.some?.( + ( blockType?.supports?.spacing?.skipSerialization === true || + blockType?.supports?.spacing?.skipSerialization?.some?.( ( spacingType ) => spacingType === 'blockGap' ) ) ) { diff --git a/packages/server-side-render/README.md b/packages/server-side-render/README.md index ba6fae302ca0a8..ef7cd9bf0189c1 100644 --- a/packages/server-side-render/README.md +++ b/packages/server-side-render/README.md @@ -79,7 +79,7 @@ add_filter( 'rest_endpoints', 'add_rest_method'); ### skipBlockSupportAttributes -Remove attributes and style properties applied by the block supports. This prevents duplication of styles in the block wrapper and the `ServerSideRender` components. Even if certain features skip serialization to HTML markup by `__experimentalSkipSerialization`, all attributes and style properties are removed. +Remove attributes and style properties applied by the block supports. This prevents duplication of styles in the block wrapper and the `ServerSideRender` components. Even if certain features skip serialization to HTML markup by `skipSerialization`, all attributes and style properties are removed. - Type: `Boolean` - Required: No diff --git a/phpunit/block-supports/border-test.php b/phpunit/block-supports/border-test.php index 0c320f24ebe4f2..6ec43b369d9a2a 100644 --- a/phpunit/block-supports/border-test.php +++ b/phpunit/block-supports/border-test.php @@ -128,11 +128,11 @@ public function test_flat_border_with_skipped_serialization() { 'test/flat-border-with-skipped-serialization', array( '__experimentalBorder' => array( - 'color' => true, - 'radius' => true, - 'width' => true, - 'style' => true, - '__experimentalSkipSerialization' => true, + 'color' => true, + 'radius' => true, + 'width' => true, + 'style' => true, + 'skipSerialization' => true, ), ) ); @@ -567,4 +567,167 @@ public function test_should_apply_stabilized_border_supports() { $this->assertSame( $expected, $actual ); } + + /** + * Tests that experimental border support configuration gets stabilized correctly. + */ + public function test_should_stabilize_border_supports() { + $block_type_args = array( + 'supports' => array( + '__experimentalBorder' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalSkipSerialization' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + ), + ), + ), + ); + + $actual = gutenberg_stabilize_experimental_block_supports( $block_type_args ); + $expected = array( + 'supports' => array( + 'border' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + 'skipSerialization' => true, + // Has to be kept due to core's `wp_should_skip_block_supports_serialization` only checking the experimental flag until 6.8. + '__experimentalSkipSerialization' => true, + 'defaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + ), + ), + ), + ); + + $this->assertSame( $expected, $actual, 'Stabilized border block support config does not match.' ); + } + + /** + * Tests the merging of border support configuration when stabilizing + * experimental config. Due to the ability to filter block type args, plugins + * or themes could filter using outdated experimental keys. While not every + * permutation of filtering can be covered, the majority of use cases are + * served best by merging configs based on the order they were defined if possible. + */ + public function test_should_stabilize_border_supports_using_order_based_merge() { + $experimental_border_config = array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + '__experimentalSkipSerialization' => true, + '__experimentalDefaultControls' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + ), + + /* + * The following simulates theme/plugin filtering using `__experimentalBorder` + * key but stable serialization and default control keys. + */ + 'skipSerialization' => false, + 'defaultControls' => array( + 'color' => true, + 'radius' => false, + 'style' => true, + 'width' => true, + ), + ); + $stable_border_config = array( + 'color' => true, + 'radius' => true, + 'style' => false, + 'width' => true, + 'skipSerialization' => false, + 'defaultControls' => array( + 'color' => true, + 'radius' => false, + 'style' => false, + 'width' => true, + ), + + /* + * The following simulates theme/plugin filtering using stable `border` key + * but experimental serialization and default control keys. + */ + '__experimentalSkipSerialization' => true, + '__experimentalDefaultControls' => array( + 'color' => false, + 'radius' => false, + 'style' => false, + 'width' => false, + ), + ); + + $experimental_first_args = array( + 'supports' => array( + '__experimentalBorder' => $experimental_border_config, + 'border' => $stable_border_config, + ), + ); + + $actual = gutenberg_stabilize_experimental_block_supports( $experimental_first_args ); + $expected = array( + 'supports' => array( + 'border' => array( + 'color' => true, + 'radius' => true, + 'style' => false, + 'width' => true, + 'skipSerialization' => true, + '__experimentalSkipSerialization' => true, + 'defaultControls' => array( + 'color' => false, + 'radius' => false, + 'style' => false, + 'width' => false, + ), + + ), + ), + ); + $this->assertSame( $expected, $actual, 'Merged stabilized border block support config does not match when experimental keys are first.' ); + + $stable_first_args = array( + 'supports' => array( + 'border' => $stable_border_config, + '__experimentalBorder' => $experimental_border_config, + ), + ); + + $actual = gutenberg_stabilize_experimental_block_supports( $stable_first_args ); + $expected = array( + 'supports' => array( + 'border' => array( + 'color' => true, + 'radius' => true, + 'style' => true, + 'width' => true, + 'skipSerialization' => false, + '__experimentalSkipSerialization' => false, + 'defaultControls' => array( + 'color' => true, + 'radius' => false, + 'style' => true, + 'width' => true, + ), + ), + ), + ); + $this->assertSame( $expected, $actual, 'Merged stabilized border block support config does not match when stable keys are first.' ); + } } From 0a6751c21a208677f46d1dd536d10e95d4ce11d1 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Mon, 25 Nov 2024 16:21:30 +0800 Subject: [PATCH 1685/1908] Fix block mover clickable area (#67261) Unlinked contributors: maximebj. Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/block-editor/src/components/block-mover/style.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/block-editor/src/components/block-mover/style.scss b/packages/block-editor/src/components/block-mover/style.scss index c58ac9f19673fc..7d23c0f1e5a988 100644 --- a/packages/block-editor/src/components/block-mover/style.scss +++ b/packages/block-editor/src/components/block-mover/style.scss @@ -71,6 +71,9 @@ // Specificity is necessary to override block toolbar button styles. .components-button.block-editor-block-mover-button { + // Prevent the SVGs inside the button from overflowing the button. + overflow: hidden; + // Focus and toggle pseudo elements. &::before { content: ""; From 8fa8506a2a33e35badc672a5ed68e2e503dfa200 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 25 Nov 2024 12:26:46 +0400 Subject: [PATCH 1686/1908] Paragraph: Update condition for rendering Drop Cap for a selected block (#67111) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/block-library/src/paragraph/edit.js | 37 +++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/packages/block-library/src/paragraph/edit.js b/packages/block-library/src/paragraph/edit.js index b0dc5ab255af78..d32b4e8d5eca02 100644 --- a/packages/block-library/src/paragraph/edit.js +++ b/packages/block-library/src/paragraph/edit.js @@ -70,22 +70,24 @@ function DropCapControl( { clientId, attributes, setAttributes } ) { } return ( - <ToolsPanelItem - hasValue={ () => !! dropCap } - label={ __( 'Drop cap' ) } - onDeselect={ () => setAttributes( { dropCap: undefined } ) } - resetAllFilter={ () => ( { dropCap: undefined } ) } - panelId={ clientId } - > - <ToggleControl - __nextHasNoMarginBottom + <InspectorControls group="typography"> + <ToolsPanelItem + hasValue={ () => !! dropCap } label={ __( 'Drop cap' ) } - checked={ !! dropCap } - onChange={ () => setAttributes( { dropCap: ! dropCap } ) } - help={ helpText } - disabled={ hasDropCapDisabled( align ) } - /> - </ToolsPanelItem> + onDeselect={ () => setAttributes( { dropCap: undefined } ) } + resetAllFilter={ () => ( { dropCap: undefined } ) } + panelId={ clientId } + > + <ToggleControl + __nextHasNoMarginBottom + label={ __( 'Drop cap' ) } + checked={ !! dropCap } + onChange={ () => setAttributes( { dropCap: ! dropCap } ) } + help={ helpText } + disabled={ hasDropCapDisabled( align ) } + /> + </ToolsPanelItem> + </InspectorControls> ); } @@ -96,6 +98,7 @@ function ParagraphBlock( { onRemove, setAttributes, clientId, + isSelected: isSingleSelected, } ) { const { align, content, direction, dropCap, placeholder } = attributes; const blockProps = useBlockProps( { @@ -131,13 +134,13 @@ function ParagraphBlock( { /> </BlockControls> ) } - <InspectorControls group="typography"> + { isSingleSelected && ( <DropCapControl clientId={ clientId } attributes={ attributes } setAttributes={ setAttributes } /> - </InspectorControls> + ) } <RichText identifier="content" tagName="p" From b1b77f306b48ef9a0691dd786826966950b55f1a Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:55:14 +0100 Subject: [PATCH 1687/1908] =?UTF-8?q?=F0=9F=A7=B9=20remove=20obsolete=20ri?= =?UTF-8?q?ch=20text=20css=20(#67264)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/block-editor/src/components/rich-text/content.scss | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/block-editor/src/components/rich-text/content.scss b/packages/block-editor/src/components/rich-text/content.scss index 6f118479fc6b03..28dcd931a7f5db 100644 --- a/packages/block-editor/src/components/rich-text/content.scss +++ b/packages/block-editor/src/components/rich-text/content.scss @@ -20,12 +20,6 @@ } } -.block-editor-rich-text__editable { - > p:first-child { - margin-top: 0; - } -} - // Captions may have lighter (gray) text, or be shown on a range of different background luminosites. // To ensure legibility, we increase the default placeholder opacity to ensure contrast. figcaption.block-editor-rich-text__editable [data-rich-text-placeholder]::before { From 66d117fb7dc22a4f7a95956b8d0fe3be81c7885d Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 25 Nov 2024 13:23:51 +0400 Subject: [PATCH 1688/1908] Edit Post: Refactor 'MetaBoxVisibility' component (#67265) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../meta-boxes/meta-box-visibility.js | 37 +++++++------------ 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/packages/edit-post/src/components/meta-boxes/meta-box-visibility.js b/packages/edit-post/src/components/meta-boxes/meta-box-visibility.js index 26b69d37f00210..07060afa31dea5 100644 --- a/packages/edit-post/src/components/meta-boxes/meta-box-visibility.js +++ b/packages/edit-post/src/components/meta-boxes/meta-box-visibility.js @@ -1,24 +1,21 @@ /** * WordPress dependencies */ -import { Component } from '@wordpress/element'; -import { withSelect } from '@wordpress/data'; +import { useEffect } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; import { store as editorStore } from '@wordpress/editor'; -class MetaBoxVisibility extends Component { - componentDidMount() { - this.updateDOM(); - } - - componentDidUpdate( prevProps ) { - if ( this.props.isVisible !== prevProps.isVisible ) { - this.updateDOM(); - } - } - - updateDOM() { - const { id, isVisible } = this.props; +export default function MetaBoxVisibility( { id } ) { + const isVisible = useSelect( + ( select ) => { + return select( editorStore ).isEditorPanelEnabled( + `meta-box-${ id }` + ); + }, + [ id ] + ); + useEffect( () => { const element = document.getElementById( id ); if ( ! element ) { return; @@ -29,13 +26,7 @@ class MetaBoxVisibility extends Component { } else { element.classList.add( 'is-hidden' ); } - } + }, [ id, isVisible ] ); - render() { - return null; - } + return null; } - -export default withSelect( ( select, { id } ) => ( { - isVisible: select( editorStore ).isEditorPanelEnabled( `meta-box-${ id }` ), -} ) )( MetaBoxVisibility ); From 7e7ce3c0135351e5847d51e349e6b5c6885ee9ac Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Mon, 25 Nov 2024 18:25:48 +0900 Subject: [PATCH 1689/1908] Site Editor Sidebar: Fixed focus/hover style for navigation item buttons (#67251) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../sidebar-navigation-screen-navigation-menus/style.scss | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss index 334e90e93c42ce..544aad5075aec0 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss @@ -27,6 +27,14 @@ color: $white; } } + + .block-editor-list-view-block__menu { + color: $gray-600; + &:hover, + &:focus { + color: $white; + } + } } .edit-site-sidebar-navigation-screen-navigation-menus__loading.components-spinner { From 7e9e53d0581e8f21ad029fb3ffd03f43680326b1 Mon Sep 17 00:00:00 2001 From: Manzoor Wani <manzoorwani.jk@gmail.com> Date: Mon, 25 Nov 2024 02:11:31 -0800 Subject: [PATCH 1690/1908] Fix TS types for the editor package (#67196) * Replace the wrong Component type with React Node/Element * Replace the wrong Component type with React Node/Element * Fix the optional params for store actions * Replace the deprecated JSX.Element with React.ReactNode * Update docs * Fix children prop for multiple components --- .../reference-guides/data/data-core-editor.md | 11 +- packages/editor/README.md | 192 +++++++++--------- .../plugin-block-settings-menu-item.js | 2 +- .../components/collab-sidebar/add-comment.js | 2 +- .../collab-sidebar/comment-author-info.js | 2 +- .../components/collab-sidebar/comment-form.js | 2 +- .../src/components/collab-sidebar/comments.js | 4 +- .../src/components/document-bar/index.js | 2 +- .../src/components/document-outline/check.js | 6 +- .../src/components/document-outline/index.js | 2 +- .../src/components/editor-history/redo.js | 2 +- .../src/components/editor-history/undo.js | 2 +- .../src/components/editor-notices/index.js | 2 +- .../src/components/editor-snackbars/index.js | 2 +- .../components/entities-saved-states/index.js | 4 +- .../src/components/page-attributes/check.js | 6 +- .../src/components/page-attributes/order.js | 2 +- .../src/components/page-attributes/panel.js | 2 +- .../src/components/page-attributes/parent.js | 2 +- .../plugin-document-setting-panel/index.js | 4 +- .../components/plugin-more-menu-item/index.js | 3 +- .../plugin-post-publish-panel/index.js | 4 +- .../plugin-post-status-info/index.js | 8 +- .../plugin-pre-publish-panel/index.js | 4 +- .../plugin-preview-menu-item/index.js | 3 +- .../plugin-sidebar-more-menu-item/index.js | 4 +- .../src/components/plugin-sidebar/index.js | 1 + .../src/components/post-author/check.js | 6 +- .../src/components/post-author/index.js | 2 +- .../src/components/post-author/panel.js | 2 +- .../src/components/post-comments/index.js | 2 +- .../src/components/post-discussion/panel.js | 2 +- .../src/components/post-excerpt/check.js | 6 +- .../src/components/post-excerpt/panel.js | 2 +- .../src/components/post-excerpt/plugin.js | 8 +- .../components/post-featured-image/check.js | 6 +- .../components/post-featured-image/panel.js | 2 +- .../src/components/post-format/check.js | 20 +- .../src/components/post-format/index.js | 2 +- .../src/components/post-format/panel.js | 2 +- .../components/post-last-revision/check.js | 6 +- .../components/post-last-revision/index.js | 2 +- .../components/post-last-revision/panel.js | 2 +- .../src/components/post-locked-modal/index.js | 2 +- .../components/post-pending-status/check.js | 6 +- .../components/post-pending-status/index.js | 2 +- .../components/post-preview-button/index.js | 2 +- .../src/components/post-schedule/check.js | 6 +- .../src/components/post-schedule/index.js | 2 +- .../src/components/post-schedule/label.js | 2 +- .../src/components/post-schedule/panel.js | 2 +- .../editor/src/components/post-slug/check.js | 6 +- .../editor/src/components/post-slug/index.js | 2 +- .../src/components/post-sticky/check.js | 6 +- .../src/components/post-sticky/index.js | 2 +- .../post-switch-to-draft-button/index.js | 2 +- .../src/components/post-sync-status/index.js | 2 +- .../src/components/post-taxonomies/check.js | 6 +- .../post-taxonomies/flat-term-selector.js | 2 +- .../src/components/post-taxonomies/panel.js | 27 +-- .../components/post-template/classic-theme.js | 4 +- .../src/components/post-template/panel.js | 2 +- .../src/components/post-text-editor/index.js | 2 +- .../editor/src/components/post-title/index.js | 2 +- .../components/post-title/post-title-raw.js | 2 +- .../editor/src/components/post-trash/check.js | 6 +- .../editor/src/components/post-trash/index.js | 2 +- .../post-type-support-check/index.js | 12 +- .../editor/src/components/post-url/check.js | 6 +- .../editor/src/components/post-url/index.js | 2 +- .../editor/src/components/post-url/label.js | 2 +- .../editor/src/components/post-url/panel.js | 2 +- .../src/components/post-visibility/check.js | 2 +- .../src/components/post-visibility/index.js | 2 +- .../editor/src/components/provider/index.js | 2 +- .../src/components/table-of-contents/index.js | 2 +- .../components/theme-support-check/index.js | 8 +- .../src/components/time-to-read/index.js | 2 +- .../unsaved-changes-warning/index.js | 2 +- .../editor/src/components/word-count/index.js | 2 +- packages/editor/src/store/actions.js | 19 +- 81 files changed, 260 insertions(+), 256 deletions(-) diff --git a/docs/reference-guides/data/data-core-editor.md b/docs/reference-guides/data/data-core-editor.md index 9567d8e4b954fa..44078ab284e94f 100644 --- a/docs/reference-guides/data/data-core-editor.md +++ b/docs/reference-guides/data/data-core-editor.md @@ -1148,7 +1148,8 @@ Action that autosaves the current post. This includes server-side autosaving (de _Parameters_ -- _options_ `Object?`: Extra flags to identify the autosave. +- _options_ `[Object]`: Extra flags to identify the autosave. +- _options.local_ `[boolean]`: Whether to perform a local autosave. ### clearSelectedBlock @@ -1204,7 +1205,7 @@ const getFeaturedMediaUrl = useSelect( ( select ) => { _Parameters_ - _edits_ `Object`: Post attributes to edit. -- _options_ `Object`: Options for the edit. +- _options_ `[Object]`: Options for the edit. _Returns_ @@ -1417,7 +1418,7 @@ Returns an action object used to signal that the blocks have been updated. _Parameters_ - _blocks_ `Array`: Block Array. -- _options_ `?Object`: Optional options. +- _options_ `[Object]`: Optional options. ### resetPost @@ -1431,7 +1432,7 @@ Action for saving the current post in the editor. _Parameters_ -- _options_ `Object`: +- _options_ `[Object]`: ### selectBlock @@ -1519,7 +1520,7 @@ _Parameters_ - _post_ `Object`: Post object. - _edits_ `Object`: Initial edited attributes object. -- _template_ `Array?`: Block Template. +- _template_ `[Array]`: Block Template. ### setupEditorState diff --git a/packages/editor/README.md b/packages/editor/README.md index bc00e15c8fb892..ac655bd1c99d8c 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -270,7 +270,7 @@ _Parameters_ _Returns_ -- `JSX.Element`: The rendered DocumentBar component. +- `React.ReactNode`: The rendered DocumentBar component. ### DocumentOutline @@ -284,7 +284,7 @@ _Parameters_ _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### DocumentOutlineCheck @@ -293,11 +293,11 @@ Component check if there are any headings (core/heading blocks) present in the d _Parameters_ - _props_ `Object`: Props. -- _props.children_ `Element`: Children to be rendered. +- _props.children_ `React.ReactElement`: Children to be rendered. _Returns_ -- `Component|null`: The component to be rendered or null if there are headings. +- `React.ReactElement`: The component to be rendered or null if there are headings. ### EditorHistoryRedo @@ -310,7 +310,7 @@ _Parameters_ _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### EditorHistoryUndo @@ -323,7 +323,7 @@ _Parameters_ _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### EditorKeyboardShortcuts @@ -351,7 +351,7 @@ _Usage_ _Returns_ -- `JSX.Element`: The rendered EditorNotices component. +- `React.ReactNode`: The rendered EditorNotices component. ### EditorProvider @@ -383,7 +383,7 @@ _Parameters_ _Returns_ -- `JSX.Element`: The rendered EditorProvider component. +- `React.ReactNode`: The rendered EditorProvider component. ### EditorSnackbars @@ -391,7 +391,7 @@ Renders the editor snackbars component. _Returns_ -- `JSX.Element`: The rendered component. +- `React.ReactNode`: The rendered component. ### EntitiesSavedStates @@ -405,7 +405,7 @@ _Parameters_ _Returns_ -- `JSX.Element`: The rendered component. +- `React.ReactNode`: The rendered component. ### ErrorBoundary @@ -523,11 +523,11 @@ Wrapper component that renders its children only if the post type supports page _Parameters_ - _props_ `Object`: - The component props. -- _props.children_ `Element`: - The child components to render. +- _props.children_ `React.ReactElement`: - The child components to render. _Returns_ -- `Component|null`: The rendered child components or null if page attributes are not supported. +- `React.ReactElement`: The rendered child components or null if page attributes are not supported. ### PageAttributesOrder @@ -535,7 +535,7 @@ Renders the Page Attributes Order component. A number input in an editor interfa _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PageAttributesPanel @@ -543,7 +543,7 @@ Renders the Page Attributes Panel component. _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PageAttributesParent @@ -551,7 +551,7 @@ Renders the Page Attributes Parent component. A dropdown menu in an editor inter _Returns_ -- `Component|null`: The component to be rendered. Return null if post type is not hierarchical. +- `React.ReactNode`: The component to be rendered. Return null if post type is not hierarchical. ### PageTemplate @@ -561,7 +561,7 @@ The dropdown menu includes a button for toggling the menu, a list of available t _Returns_ -- `JSX.Element`: The rendered ClassicThemeControl component. +- `React.ReactNode`: The rendered ClassicThemeControl component. ### PanelColorSettings @@ -627,7 +627,7 @@ _Parameters_ _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PluginDocumentSettingPanel @@ -684,11 +684,11 @@ _Parameters_ - _props.className_ `[string]`: An optional class name added to the row. - _props.title_ `[string]`: The title of the panel - _props.icon_ `[WPBlockTypeIconRender]`: The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered when the sidebar is pinned to toolbar. -- _props.children_ `Element`: Children to be rendered +- _props.children_ `React.ReactNode`: Children to be rendered _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The component to be rendered. ### PluginMoreMenuItem @@ -738,6 +738,7 @@ const MyButtonMoreMenuItem = () => ( _Parameters_ - _props_ `Object`: Component properties. +- _props.children_ `[React.ReactNode]`: Children to be rendered. - _props.href_ `[string]`: When `href` is provided then the menu item is represented as an anchor rather than button. It corresponds to the `href` attribute of the anchor. - _props.icon_ `[WPBlockTypeIconRender]`: The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered to the left of the menu item label. - _props.onClick_ `[Function]`: The callback function to be executed when the user clicks the menu item. @@ -745,7 +746,7 @@ _Parameters_ _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PluginPostPublishPanel @@ -776,11 +777,11 @@ _Parameters_ - _props.title_ `[string]`: Title displayed at the top of the panel. - _props.initialOpen_ `[boolean]`: Whether to have the panel initially opened. When no title is provided it is always opened. - _props.icon_ `[WPBlockTypeIconRender]`: The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered when the sidebar is pinned to toolbar. -- _props.children_ `Element`: Children to be rendered +- _props.children_ `React.ReactNode`: Children to be rendered _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PluginPostStatusInfo @@ -820,11 +821,11 @@ _Parameters_ - _props_ `Object`: Component properties. - _props.className_ `[string]`: An optional class name added to the row. -- _props.children_ `Element`: Children to be rendered. +- _props.children_ `React.ReactNode`: Children to be rendered. _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PluginPrePublishPanel @@ -855,11 +856,11 @@ _Parameters_ - _props.title_ `[string]`: Title displayed at the top of the panel. - _props.initialOpen_ `[boolean]`: Whether to have the panel initially opened. When no title is provided it is always opened. - _props.icon_ `[WPBlockTypeIconRender]`: The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered when the sidebar is pinned to toolbar. -- _props.children_ `Element`: Children to be rendered +- _props.children_ `React.ReactNode`: Children to be rendered _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PluginPreviewMenuItem @@ -889,6 +890,7 @@ registerPlugin( 'external-preview-menu-item', { _Parameters_ - _props_ `Object`: Component properties. +- _props.children_ `[React.ReactNode]`: Children to be rendered. - _props.href_ `[string]`: When `href` is provided, the menu item is rendered as an anchor instead of a button. It corresponds to the `href` attribute of the anchor. - _props.icon_ `[WPBlockTypeIconRender]`: The icon to be rendered to the left of the menu item label. Can be a Dashicon slug or an SVG WP element. - _props.onClick_ `[Function]`: The callback function to be executed when the user clicks the menu item. @@ -896,7 +898,7 @@ _Parameters_ _Returns_ -- `Component`: The rendered menu item component. +- `React.ReactNode`: The rendered menu item component. ### PluginSidebar @@ -953,6 +955,7 @@ _Parameters_ - _props_ `Object`: Element props. - _props.name_ `string`: A string identifying the sidebar. Must be unique for every sidebar registered within the scope of your plugin. +- _props.children_ `[React.ReactNode]`: Children to be rendered. - _props.className_ `[string]`: An optional class name added to the sidebar body. - _props.title_ `string`: Title displayed at the top of the sidebar. - _props.isPinnable_ `[boolean]`: Whether to allow to pin sidebar to the toolbar. When set to `true` it also automatically renders a corresponding menu item. @@ -999,11 +1002,12 @@ _Parameters_ - _props_ `Object`: Component props. - _props.target_ `string`: A string identifying the target sidebar you wish to be activated by this menu item. Must be the same as the `name` prop you have given to that sidebar. +- _props.children_ `[React.ReactNode]`: Children to be rendered. - _props.icon_ `[WPBlockTypeIconRender]`: The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered to the left of the menu item label. _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PostAuthor @@ -1011,7 +1015,7 @@ Renders the component for selecting the post author. _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PostAuthorCheck @@ -1020,11 +1024,11 @@ Wrapper component that renders its children only if the post type supports the a _Parameters_ - _props_ `Object`: The component props. -- _props.children_ `Element`: Children to be rendered. +- _props.children_ `React.ReactNode`: Children to be rendered. _Returns_ -- `Component|null`: The component to be rendered. Return `null` if the post type doesn't supports the author or if there are no authors available. +- `React.ReactNode`: The component to be rendered. Return `null` if the post type doesn't supports the author or if there are no authors available. ### PostAuthorPanel @@ -1032,7 +1036,7 @@ Renders the Post Author Panel component. _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PostComments @@ -1040,7 +1044,7 @@ A form for managing comment status. _Returns_ -- `JSX.Element`: The rendered PostComments component. +- `React.ReactNode`: The rendered PostComments component. ### PostDiscussionPanel @@ -1048,7 +1052,7 @@ This component allows to update comment and pingback settings for the current po _Returns_ -- `JSX.Element|null`: The rendered PostDiscussionPanel component. +- `React.ReactNode`: The rendered PostDiscussionPanel component. ### PostExcerpt @@ -1067,11 +1071,11 @@ Component for checking if the post type supports the excerpt field. _Parameters_ - _props_ `Object`: Props. -- _props.children_ `Element`: Children to be rendered. +- _props.children_ `React.ReactNode`: Children to be rendered. _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PostExcerptPanel @@ -1079,7 +1083,7 @@ Is rendered if the post type supports excerpts and allows editing the excerpt. _Returns_ -- `JSX.Element`: The rendered PostExcerptPanel component. +- `React.ReactNode`: The rendered PostExcerptPanel component. ### PostFeaturedImage @@ -1108,11 +1112,11 @@ Wrapper component that renders its children only if the post type supports a fea _Parameters_ - _props_ `Object`: Props. -- _props.children_ `Element`: Children to be rendered. +- _props.children_ `React.ReactNode`: Children to be rendered. _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PostFeaturedImagePanel @@ -1125,7 +1129,7 @@ _Parameters_ _Returns_ -- `Component|null`: The component to be rendered. Return Null if the editor panel is disabled for featured image. +- `React.ReactNode`: The component to be rendered. Return Null if the editor panel is disabled for featured image. ### PostFormat @@ -1139,7 +1143,7 @@ _Usage_ _Returns_ -- `JSX.Element`: The rendered PostFormat component. +- `React.ReactNode`: The rendered PostFormat component. ### PostFormatCheck @@ -1148,11 +1152,11 @@ Component check if there are any post formats. _Parameters_ - _props_ `Object`: The component props. -- _props.children_ `Element`: The child elements to render. +- _props.children_ `React.ReactNode`: The child elements to render. _Returns_ -- `Component|null`: The rendered component or null if post formats are disabled. +- `React.ReactNode`: The rendered component or null if post formats are disabled. ### PostLastRevision @@ -1160,7 +1164,7 @@ Renders the component for displaying the last revision of a post. _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PostLastRevisionCheck @@ -1169,11 +1173,11 @@ Wrapper component that renders its children if the post has more than one revisi _Parameters_ - _props_ `Object`: Props. -- _props.children_ `Element`: Children to be rendered. +- _props.children_ `React.ReactNode`: Children to be rendered. _Returns_ -- `Component|null`: Rendered child components if post has more than one revision, otherwise null. +- `React.ReactNode`: Rendered child components if post has more than one revision, otherwise null. ### PostLastRevisionPanel @@ -1181,7 +1185,7 @@ Renders the panel for displaying the last revision of a post. _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PostLockedModal @@ -1189,7 +1193,7 @@ A modal component that is displayed when a post is locked for editing by another _Returns_ -- `JSX.Element|null`: The rendered PostLockedModal component. +- `React.ReactNode`: The rendered PostLockedModal component. ### PostPendingStatus @@ -1197,7 +1201,7 @@ A component for displaying and toggling the pending status of a post. _Returns_ -- `JSX.Element`: The rendered component. +- `React.ReactNode`: The rendered component. ### PostPendingStatusCheck @@ -1206,11 +1210,11 @@ This component checks the publishing status of the current post. If the post is _Parameters_ - _props_ `Object`: Component properties. -- _props.children_ `Element`: Children to be rendered. +- _props.children_ `React.ReactElement`: Children to be rendered. _Returns_ -- `JSX.Element|null`: The rendered child elements or null if the post is already published or the user doesn't have the capability to publish. +- `React.ReactElement`: The rendered child elements or null if the post is already published or the user doesn't have the capability to publish. ### PostPingbacks @@ -1231,7 +1235,7 @@ _Parameters_ _Returns_ -- `JSX.Element|null`: The rendered button component. +- `React.ReactNode`: The rendered button component. ### PostPublishButton @@ -1273,7 +1277,7 @@ _Parameters_ _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PostScheduleCheck @@ -1282,11 +1286,11 @@ Wrapper component that renders its children only if post has a publish action. _Parameters_ - _props_ `Object`: Props. -- _props.children_ `Element`: Children to be rendered. +- _props.children_ `React.ReactElement`: Children to be rendered. _Returns_ -- `Component`: - The component to be rendered or null if there is no publish action. +- `React.ReactElement`: - The component to be rendered or null if there is no publish action. ### PostScheduleLabel @@ -1298,7 +1302,7 @@ _Parameters_ _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PostSchedulePanel @@ -1306,7 +1310,7 @@ Renders the Post Schedule Panel component. _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PostSlug @@ -1314,7 +1318,7 @@ Renders the PostSlug component. It provide a control for editing the post slug. _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PostSlugCheck @@ -1323,11 +1327,11 @@ Wrapper component that renders its children only if the post type supports the s _Parameters_ - _props_ `Object`: Props. -- _props.children_ `Element`: Children to be rendered. +- _props.children_ `React.ReactNode`: Children to be rendered. _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PostSticky @@ -1335,7 +1339,7 @@ Renders the PostSticky component. It provides a checkbox control for the sticky _Returns_ -- `Component`: The component to be rendered. +- `React.ReactNode`: The rendered component. ### PostStickyCheck @@ -1344,11 +1348,11 @@ Wrapper component that renders its children only if post has a sticky action. _Parameters_ - _props_ `Object`: Props. -- _props.children_ `Element`: Children to be rendered. +- _props.children_ `React.ReactElement`: Children to be rendered. _Returns_ -- `Component`: The component to be rendered or null if post type is not 'post' or hasStickyAction is false. +- `React.ReactElement`: The component to be rendered or null if post type is not 'post' or hasStickyAction is false. ### PostSwitchToDraftButton @@ -1356,7 +1360,7 @@ Renders a button component that allows the user to switch a post to draft status _Returns_ -- `JSX.Element`: The rendered component. +- `React.ReactNode`: The rendered component. ### PostSyncStatus @@ -1364,7 +1368,7 @@ Renders the sync status of a post. _Returns_ -- `JSX.Element|null`: The rendered sync status component. +- `React.ReactNode`: The rendered sync status component. ### PostTaxonomies @@ -1386,11 +1390,11 @@ Renders the children components only if the current post type has taxonomies. _Parameters_ - _props_ `Object`: The component props. -- _props.children_ `Element`: The children components to render. +- _props.children_ `React.ReactNode`: The children components to render. _Returns_ -- `Component|null`: The rendered children components or null if the current post type has no taxonomies. +- `React.ReactElement`: The rendered children components or null if the current post type has no taxonomies. ### PostTaxonomiesFlatTermSelector @@ -1404,7 +1408,7 @@ _Parameters_ _Returns_ -- `JSX.Element`: The rendered flat term selector component. +- `React.ReactNode`: The rendered flat term selector component. ### PostTaxonomiesHierarchicalTermSelector @@ -1421,17 +1425,11 @@ _Returns_ ### PostTaxonomiesPanel -Renders a panel for a specific taxonomy. - -_Parameters_ - -- _props_ `Object`: The component props. -- _props.taxonomy_ `Object`: The taxonomy object. -- _props.children_ `Element`: The child components. +Component that renders the post taxonomies panel. _Returns_ -- `Component`: The rendered taxonomy panel. +- `React.ReactNode`: The rendered component. ### PostTemplatePanel @@ -1439,7 +1437,7 @@ Displays the template controls based on the current editor settings and user per _Returns_ -- `JSX.Element|null`: The rendered PostTemplatePanel component. +- `React.ReactNode`: The rendered PostTemplatePanel component. ### PostTextEditor @@ -1447,7 +1445,7 @@ Displays the Post Text Editor along with content in Visual and Text mode. _Returns_ -- `JSX.Element|null`: The rendered PostTextEditor component. +- `React.ReactNode`: The rendered PostTextEditor component. ### PostTitle @@ -1460,7 +1458,7 @@ _Parameters_ _Returns_ -- `Component`: The rendered PostTitle component. +- `React.ReactNode`: The rendered PostTitle component. ### PostTitleRaw @@ -1476,7 +1474,7 @@ _Parameters_ _Returns_ -- `JSX.Element|null`: The rendered PostTrash component. +- `React.ReactNode`: The rendered PostTrash component. ### PostTrashCheck @@ -1485,11 +1483,11 @@ Wrapper component that renders its children only if the post can trashed. _Parameters_ - _props_ `Object`: - The component props. -- _props.children_ `Element`: - The child components to render. +- _props.children_ `React.ReactEl`: - The child components to render. _Returns_ -- `Component|null`: The rendered child components or null if the post can not trashed. +- `React.ReactElement`: The rendered child components or null if the post can not trashed. ### PostTypeSupportCheck @@ -1498,12 +1496,12 @@ A component which renders its own children only if the current editor post type _Parameters_ - _props_ `Object`: Props. -- _props.children_ `Element`: Children to be rendered if post type supports. +- _props.children_ `React.ReactElement`: Children to be rendered if post type supports. - _props.supportKeys_ `(string|string[])`: String or string array of keys to test. _Returns_ -- `Component`: The component to be rendered. +- `React.ReactElement`: The component to be rendered. ### PostURL @@ -1521,7 +1519,7 @@ _Parameters_ _Returns_ -- `Component`: The rendered PostURL component. +- `React.ReactNode`: The rendered PostURL component. ### PostURLCheck @@ -1530,11 +1528,11 @@ Check if the post URL is valid and visible. _Parameters_ - _props_ `Object`: The component props. -- _props.children_ `Element`: The child components. +- _props.children_ `React.ReactElement`: The child components. _Returns_ -- `Component|null`: The child components if the post URL is valid and visible, otherwise null. +- `React.ReactElement`: The child components if the post URL is valid and visible, otherwise null. ### PostURLLabel @@ -1542,7 +1540,7 @@ Represents a label component for a post URL. _Returns_ -- `Component`: The PostURLLabel component. +- `React.ReactNode`: The PostURLLabel component. ### PostURLPanel @@ -1550,7 +1548,7 @@ Renders the `PostURLPanel` component. _Returns_ -- `JSX.Element`: The rendered PostURLPanel component. +- `React.ReactNode`: The rendered PostURLPanel component. ### PostVisibility @@ -1563,7 +1561,7 @@ _Parameters_ _Returns_ -- `JSX.Element`: The rendered component. +- `React.ReactNode`: The rendered component. ### PostVisibilityCheck @@ -1576,7 +1574,7 @@ _Parameters_ _Returns_ -- `JSX.Element`: The rendered component. +- `React.ReactNode`: The rendered component. ### PostVisibilityLabel @@ -1663,7 +1661,7 @@ _Parameters_ _Returns_ -- `JSX.Element`: The rendered table of contents component. +- `React.ReactNode`: The rendered table of contents component. ### TextEditorGlobalKeyboardShortcuts @@ -1678,12 +1676,12 @@ Checks if the current theme supports specific features and renders the children _Parameters_ - _props_ `Object`: The component props. -- _props.children_ `Element`: The children to render if the theme supports the specified features. +- _props.children_ `React.ReactElement`: The children to render if the theme supports the specified features. - _props.supportKeys_ `string|string[]`: The key(s) of the theme support(s) to check. _Returns_ -- `JSX.Element|null`: The rendered children if the theme supports the specified features, otherwise null. +- `React.ReactElement`: The rendered children if the theme supports the specified features, otherwise null. ### TimeToRead @@ -1691,7 +1689,7 @@ Component for showing Time To Read in Content. _Returns_ -- `JSX.Element`: The rendered TimeToRead component. +- `React.ReactNode`: The rendered TimeToRead component. ### transformStyles @@ -1727,7 +1725,7 @@ Warns the user if there are unsaved changes before leaving the editor. Compatibl _Returns_ -- `Component`: The component. +- `React.ReactNode`: The component. ### URLInput @@ -1814,7 +1812,7 @@ Renders the word count of the post content. _Returns_ -- `JSX.Element|null`: The rendered WordCount component. +- `React.ReactNode`: The rendered WordCount component. ### WritingFlow diff --git a/packages/editor/src/components/block-settings-menu/plugin-block-settings-menu-item.js b/packages/editor/src/components/block-settings-menu/plugin-block-settings-menu-item.js index 59c9e9c32d4a4b..df1e75d2d0e8b5 100644 --- a/packages/editor/src/components/block-settings-menu/plugin-block-settings-menu-item.js +++ b/packages/editor/src/components/block-settings-menu/plugin-block-settings-menu-item.js @@ -76,7 +76,7 @@ const shouldRenderItem = ( selectedBlocks, allowedBlocks ) => * ); * ``` * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ const PluginBlockSettingsMenuItem = ( { allowedBlocks, diff --git a/packages/editor/src/components/collab-sidebar/add-comment.js b/packages/editor/src/components/collab-sidebar/add-comment.js index fce47e821e2065..2330017ac5db53 100644 --- a/packages/editor/src/components/collab-sidebar/add-comment.js +++ b/packages/editor/src/components/collab-sidebar/add-comment.js @@ -22,7 +22,7 @@ import CommentForm from './comment-form'; * @param {Function} props.onSubmit - A callback function to be called when the user submits a comment. * @param {boolean} props.showCommentBoard - The function to edit the comment. * @param {Function} props.setShowCommentBoard - The function to delete the comment. - * @return {JSX.Element} The rendered comment input UI. + * @return {React.ReactNode} The rendered comment input UI. */ export function AddComment( { onSubmit, diff --git a/packages/editor/src/components/collab-sidebar/comment-author-info.js b/packages/editor/src/components/collab-sidebar/comment-author-info.js index 89d09a2b52261f..d8b5f72a2fc25f 100644 --- a/packages/editor/src/components/collab-sidebar/comment-author-info.js +++ b/packages/editor/src/components/collab-sidebar/comment-author-info.js @@ -16,7 +16,7 @@ import { store as blockEditorStore } from '@wordpress/block-editor'; * @param {string} props.name - Name of the author. * @param {string} props.date - Date of the comment. * - * @return {JSX.Element} The JSX element representing the author's information. + * @return {React.ReactNode} The JSX element representing the author's information. */ function CommentAuthorInfo( { avatar, name, date } ) { const dateSettings = getDateSettings(); diff --git a/packages/editor/src/components/collab-sidebar/comment-form.js b/packages/editor/src/components/collab-sidebar/comment-form.js index 28622f9f52a6f8..052fd3cdd26568 100644 --- a/packages/editor/src/components/collab-sidebar/comment-form.js +++ b/packages/editor/src/components/collab-sidebar/comment-form.js @@ -22,7 +22,7 @@ import { sanitizeCommentString } from './utils'; * @param {Function} props.onCancel - The function to call when canceling the comment update. * @param {Object} props.thread - The comment thread object. * @param {string} props.submitButtonText - The text to display on the submit button. - * @return {JSX.Element} The CommentForm component. + * @return {React.ReactNode} The CommentForm component. */ function CommentForm( { onSubmit, onCancel, thread, submitButtonText } ) { const [ inputComment, setInputComment ] = useState( diff --git a/packages/editor/src/components/collab-sidebar/comments.js b/packages/editor/src/components/collab-sidebar/comments.js index 808ea0acf04b31..7a03068787c81e 100644 --- a/packages/editor/src/components/collab-sidebar/comments.js +++ b/packages/editor/src/components/collab-sidebar/comments.js @@ -35,7 +35,7 @@ import CommentForm from './comment-form'; * @param {Function} props.onAddReply - The function to add a reply to a comment. * @param {Function} props.onCommentDelete - The function to delete a comment. * @param {Function} props.onCommentResolve - The function to mark a comment as resolved. - * @return {JSX.Element} The rendered Comments component. + * @return {React.ReactNode} The rendered Comments component. */ export function Comments( { threads, @@ -270,7 +270,7 @@ export function Comments( { * @param {Function} props.onDelete - The function to delete the comment. * @param {Function} props.onReply - The function to reply to the comment. * @param {string} props.status - The status of the comment. - * @return {JSX.Element} The rendered comment header. + * @return {React.ReactNode} The rendered comment header. */ function CommentHeader( { thread, diff --git a/packages/editor/src/components/document-bar/index.js b/packages/editor/src/components/document-bar/index.js index 30990379fe6301..9fffba941a4355 100644 --- a/packages/editor/src/components/document-bar/index.js +++ b/packages/editor/src/components/document-bar/index.js @@ -49,7 +49,7 @@ const MotionButton = motion( Button ); * @param {IconType} props.icon An icon for the document, no default. * (A default icon indicating the document post type is no longer used.) * - * @return {JSX.Element} The rendered DocumentBar component. + * @return {React.ReactNode} The rendered DocumentBar component. */ export default function DocumentBar( props ) { const { diff --git a/packages/editor/src/components/document-outline/check.js b/packages/editor/src/components/document-outline/check.js index d0676aa9037ffe..87864cbb34a369 100644 --- a/packages/editor/src/components/document-outline/check.js +++ b/packages/editor/src/components/document-outline/check.js @@ -7,10 +7,10 @@ import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Component check if there are any headings (core/heading blocks) present in the document. * - * @param {Object} props Props. - * @param {Element} props.children Children to be rendered. + * @param {Object} props Props. + * @param {React.ReactElement} props.children Children to be rendered. * - * @return {Component|null} The component to be rendered or null if there are headings. + * @return {React.ReactElement} The component to be rendered or null if there are headings. */ export default function DocumentOutlineCheck( { children } ) { const hasHeadings = useSelect( ( select ) => { diff --git a/packages/editor/src/components/document-outline/index.js b/packages/editor/src/components/document-outline/index.js index c5e59837362092..89f853798296ae 100644 --- a/packages/editor/src/components/document-outline/index.js +++ b/packages/editor/src/components/document-outline/index.js @@ -106,7 +106,7 @@ const isEmptyHeading = ( heading ) => * @param {Function} props.onSelect Function to be called when an outline item is selected * @param {boolean} props.hasOutlineItemsDisabled Indicates whether the outline items are disabled. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ export default function DocumentOutline( { onSelect, diff --git a/packages/editor/src/components/editor-history/redo.js b/packages/editor/src/components/editor-history/redo.js index 46a263bb89926b..b2b20555f30544 100644 --- a/packages/editor/src/components/editor-history/redo.js +++ b/packages/editor/src/components/editor-history/redo.js @@ -50,6 +50,6 @@ function EditorHistoryRedo( props, ref ) { * @param {Object} props - Props. * @param {Ref} ref - Forwarded ref. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ export default forwardRef( EditorHistoryRedo ); diff --git a/packages/editor/src/components/editor-history/undo.js b/packages/editor/src/components/editor-history/undo.js index 6ba6055706e993..fe8cce72c4197e 100644 --- a/packages/editor/src/components/editor-history/undo.js +++ b/packages/editor/src/components/editor-history/undo.js @@ -46,6 +46,6 @@ function EditorHistoryUndo( props, ref ) { * @param {Object} props - Props. * @param {Ref} ref - Forwarded ref. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ export default forwardRef( EditorHistoryUndo ); diff --git a/packages/editor/src/components/editor-notices/index.js b/packages/editor/src/components/editor-notices/index.js index 28341bfda3f236..5f095ef1a813c6 100644 --- a/packages/editor/src/components/editor-notices/index.js +++ b/packages/editor/src/components/editor-notices/index.js @@ -18,7 +18,7 @@ import TemplateValidationNotice from '../template-validation-notice'; * <EditorNotices /> * ``` * - * @return {JSX.Element} The rendered EditorNotices component. + * @return {React.ReactNode} The rendered EditorNotices component. */ export function EditorNotices() { const { notices } = useSelect( diff --git a/packages/editor/src/components/editor-snackbars/index.js b/packages/editor/src/components/editor-snackbars/index.js index 6530e1ec7ea902..9b781ee60dcaa5 100644 --- a/packages/editor/src/components/editor-snackbars/index.js +++ b/packages/editor/src/components/editor-snackbars/index.js @@ -11,7 +11,7 @@ const MAX_VISIBLE_NOTICES = -3; /** * Renders the editor snackbars component. * - * @return {JSX.Element} The rendered component. + * @return {React.ReactNode} The rendered component. */ export default function EditorSnackbars() { const notices = useSelect( diff --git a/packages/editor/src/components/entities-saved-states/index.js b/packages/editor/src/components/entities-saved-states/index.js index 849bd2d0d71c8c..ea05bca522941b 100644 --- a/packages/editor/src/components/entities-saved-states/index.js +++ b/packages/editor/src/components/entities-saved-states/index.js @@ -33,7 +33,7 @@ function identity( values ) { * @param {Function} props.close The function to close the dialog. * @param {Function} props.renderDialog The function to render the dialog. * - * @return {JSX.Element} The rendered component. + * @return {React.ReactNode} The rendered component. */ export default function EntitiesSavedStates( { close, @@ -64,7 +64,7 @@ export default function EntitiesSavedStates( { * @param {Function} props.setUnselectedEntities Function to set unselected entities. * @param {Array} props.unselectedEntities Array of unselected entities. * - * @return {JSX.Element} The rendered component. + * @return {React.ReactNode} The rendered component. */ export function EntitiesSavedStatesExtensible( { additionalPrompt = undefined, diff --git a/packages/editor/src/components/page-attributes/check.js b/packages/editor/src/components/page-attributes/check.js index bed2b1a353842a..3c08a3d8e53514 100644 --- a/packages/editor/src/components/page-attributes/check.js +++ b/packages/editor/src/components/page-attributes/check.js @@ -12,10 +12,10 @@ import { store as editorStore } from '../../store'; /** * Wrapper component that renders its children only if the post type supports page attributes. * - * @param {Object} props - The component props. - * @param {Element} props.children - The child components to render. + * @param {Object} props - The component props. + * @param {React.ReactElement} props.children - The child components to render. * - * @return {Component|null} The rendered child components or null if page attributes are not supported. + * @return {React.ReactElement} The rendered child components or null if page attributes are not supported. */ export function PageAttributesCheck( { children } ) { const supportsPageAttributes = useSelect( ( select ) => { diff --git a/packages/editor/src/components/page-attributes/order.js b/packages/editor/src/components/page-attributes/order.js index c5f02c71b613d4..04c6ce186a9701 100644 --- a/packages/editor/src/components/page-attributes/order.js +++ b/packages/editor/src/components/page-attributes/order.js @@ -59,7 +59,7 @@ function PageAttributesOrder() { * for setting the order of a given page. * The component is now not used in core but was kept for backward compatibility. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ export default function PageAttributesOrderWithChecks() { return ( diff --git a/packages/editor/src/components/page-attributes/panel.js b/packages/editor/src/components/page-attributes/panel.js index 7fcaf4b90d9ffe..8ecf7f1642f718 100644 --- a/packages/editor/src/components/page-attributes/panel.js +++ b/packages/editor/src/components/page-attributes/panel.js @@ -33,7 +33,7 @@ function AttributesPanel() { /** * Renders the Page Attributes Panel component. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ export default function PageAttributesPanel() { return ( diff --git a/packages/editor/src/components/page-attributes/parent.js b/packages/editor/src/components/page-attributes/parent.js index 17395589cd313b..bd2861766c334a 100644 --- a/packages/editor/src/components/page-attributes/parent.js +++ b/packages/editor/src/components/page-attributes/parent.js @@ -56,7 +56,7 @@ export const getItemPriority = ( name, searchValue ) => { * Renders the Page Attributes Parent component. A dropdown menu in an editor interface * for selecting the parent page of a given page. * - * @return {Component|null} The component to be rendered. Return null if post type is not hierarchical. + * @return {React.ReactNode} The component to be rendered. Return null if post type is not hierarchical. */ export function PageAttributesParent() { const { editPost } = useDispatch( editorStore ); diff --git a/packages/editor/src/components/plugin-document-setting-panel/index.js b/packages/editor/src/components/plugin-document-setting-panel/index.js index 7466acffc0c4b1..6408d82fe7e118 100644 --- a/packages/editor/src/components/plugin-document-setting-panel/index.js +++ b/packages/editor/src/components/plugin-document-setting-panel/index.js @@ -22,7 +22,7 @@ const { Fill, Slot } = createSlotFill( 'PluginDocumentSettingPanel' ); * @param {string} [props.className] An optional class name added to the row. * @param {string} [props.title] The title of the panel * @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered when the sidebar is pinned to toolbar. - * @param {Element} props.children Children to be rendered + * @param {React.ReactNode} props.children Children to be rendered * * @example * ```js @@ -64,7 +64,7 @@ const { Fill, Slot } = createSlotFill( 'PluginDocumentSettingPanel' ); * registerPlugin( 'document-setting-test', { render: MyDocumentSettingTest } ); * ``` * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The component to be rendered. */ const PluginDocumentSettingPanel = ( { name, diff --git a/packages/editor/src/components/plugin-more-menu-item/index.js b/packages/editor/src/components/plugin-more-menu-item/index.js index 28173c24ebcefa..1d8e124b03e604 100644 --- a/packages/editor/src/components/plugin-more-menu-item/index.js +++ b/packages/editor/src/components/plugin-more-menu-item/index.js @@ -10,6 +10,7 @@ import { ActionItem } from '@wordpress/interface'; * The text within the component appears as the menu item label. * * @param {Object} props Component properties. + * @param {React.ReactNode} [props.children] Children to be rendered. * @param {string} [props.href] When `href` is provided then the menu item is represented as an anchor rather than button. It corresponds to the `href` attribute of the anchor. * @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered to the left of the menu item label. * @param {Function} [props.onClick=noop] The callback function to be executed when the user clicks the menu item. @@ -59,7 +60,7 @@ import { ActionItem } from '@wordpress/interface'; * ); * ``` * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ export default function PluginMoreMenuItem( props ) { const context = usePluginContext(); diff --git a/packages/editor/src/components/plugin-post-publish-panel/index.js b/packages/editor/src/components/plugin-post-publish-panel/index.js index 086045b1c1fee1..b93f0a15c237f5 100644 --- a/packages/editor/src/components/plugin-post-publish-panel/index.js +++ b/packages/editor/src/components/plugin-post-publish-panel/index.js @@ -15,7 +15,7 @@ const { Fill, Slot } = createSlotFill( 'PluginPostPublishPanel' ); * @param {string} [props.title] Title displayed at the top of the panel. * @param {boolean} [props.initialOpen=false] Whether to have the panel initially opened. When no title is provided it is always opened. * @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered when the sidebar is pinned to toolbar. - * @param {Element} props.children Children to be rendered + * @param {React.ReactNode} props.children Children to be rendered * * @example * ```jsx @@ -34,7 +34,7 @@ const { Fill, Slot } = createSlotFill( 'PluginPostPublishPanel' ); * ); * ``` * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ const PluginPostPublishPanel = ( { children, diff --git a/packages/editor/src/components/plugin-post-status-info/index.js b/packages/editor/src/components/plugin-post-status-info/index.js index a4a216b78ae78b..f9f3293047ddd3 100644 --- a/packages/editor/src/components/plugin-post-status-info/index.js +++ b/packages/editor/src/components/plugin-post-status-info/index.js @@ -14,9 +14,9 @@ const { Fill, Slot } = createSlotFill( 'PluginPostStatusInfo' ); * It should be noted that this is named and implemented around the function it serves * and not its location, which may change in future iterations. * - * @param {Object} props Component properties. - * @param {string} [props.className] An optional class name added to the row. - * @param {Element} props.children Children to be rendered. + * @param {Object} props Component properties. + * @param {string} [props.className] An optional class name added to the row. + * @param {React.ReactNode} props.children Children to be rendered. * * @example * ```js @@ -50,7 +50,7 @@ const { Fill, Slot } = createSlotFill( 'PluginPostStatusInfo' ); * ); * ``` * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ const PluginPostStatusInfo = ( { children, className } ) => ( <Fill> diff --git a/packages/editor/src/components/plugin-pre-publish-panel/index.js b/packages/editor/src/components/plugin-pre-publish-panel/index.js index c9f556dc534a80..412af36c5176e0 100644 --- a/packages/editor/src/components/plugin-pre-publish-panel/index.js +++ b/packages/editor/src/components/plugin-pre-publish-panel/index.js @@ -18,7 +18,7 @@ const { Fill, Slot } = createSlotFill( 'PluginPrePublishPanel' ); * @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/) * icon slug string, or an SVG WP element, to be rendered when * the sidebar is pinned to toolbar. - * @param {Element} props.children Children to be rendered + * @param {React.ReactNode} props.children Children to be rendered * * @example * ```jsx @@ -37,7 +37,7 @@ const { Fill, Slot } = createSlotFill( 'PluginPrePublishPanel' ); * ); * ``` * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ const PluginPrePublishPanel = ( { children, diff --git a/packages/editor/src/components/plugin-preview-menu-item/index.js b/packages/editor/src/components/plugin-preview-menu-item/index.js index 8038da04595aae..949f02808a7b03 100644 --- a/packages/editor/src/components/plugin-preview-menu-item/index.js +++ b/packages/editor/src/components/plugin-preview-menu-item/index.js @@ -10,6 +10,7 @@ import { ActionItem } from '@wordpress/interface'; * The text within the component appears as the menu item label. * * @param {Object} props Component properties. + * @param {React.ReactNode} [props.children] Children to be rendered. * @param {string} [props.href] When `href` is provided, the menu item is rendered as an anchor instead of a button. It corresponds to the `href` attribute of the anchor. * @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The icon to be rendered to the left of the menu item label. Can be a Dashicon slug or an SVG WP element. * @param {Function} [props.onClick] The callback function to be executed when the user clicks the menu item. @@ -38,7 +39,7 @@ import { ActionItem } from '@wordpress/interface'; * } ); * ``` * - * @return {Component} The rendered menu item component. + * @return {React.ReactNode} The rendered menu item component. */ export default function PluginPreviewMenuItem( props ) { const context = usePluginContext(); diff --git a/packages/editor/src/components/plugin-sidebar-more-menu-item/index.js b/packages/editor/src/components/plugin-sidebar-more-menu-item/index.js index 0d7695c9abfe12..379a0720dc8a91 100644 --- a/packages/editor/src/components/plugin-sidebar-more-menu-item/index.js +++ b/packages/editor/src/components/plugin-sidebar-more-menu-item/index.js @@ -10,6 +10,7 @@ import { ComplementaryAreaMoreMenuItem } from '@wordpress/interface'; * * @param {Object} props Component props. * @param {string} props.target A string identifying the target sidebar you wish to be activated by this menu item. Must be the same as the `name` prop you have given to that sidebar. + * @param {React.ReactNode} [props.children] Children to be rendered. * @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered to the left of the menu item label. * * @example @@ -48,9 +49,8 @@ import { ComplementaryAreaMoreMenuItem } from '@wordpress/interface'; * ); * ``` * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ - export default function PluginSidebarMoreMenuItem( props ) { return ( <ComplementaryAreaMoreMenuItem diff --git a/packages/editor/src/components/plugin-sidebar/index.js b/packages/editor/src/components/plugin-sidebar/index.js index 5cd61a3747e6c1..dfcc01b5e60283 100644 --- a/packages/editor/src/components/plugin-sidebar/index.js +++ b/packages/editor/src/components/plugin-sidebar/index.js @@ -16,6 +16,7 @@ import { ComplementaryArea } from '@wordpress/interface'; * * @param {Object} props Element props. * @param {string} props.name A string identifying the sidebar. Must be unique for every sidebar registered within the scope of your plugin. + * @param {React.ReactNode} [props.children] Children to be rendered. * @param {string} [props.className] An optional class name added to the sidebar body. * @param {string} props.title Title displayed at the top of the sidebar. * @param {boolean} [props.isPinnable=true] Whether to allow to pin sidebar to the toolbar. When set to `true` it also automatically renders a corresponding menu item. diff --git a/packages/editor/src/components/post-author/check.js b/packages/editor/src/components/post-author/check.js index d10a0a2ccf0bd0..0ae7a3963e243f 100644 --- a/packages/editor/src/components/post-author/check.js +++ b/packages/editor/src/components/post-author/check.js @@ -14,10 +14,10 @@ import { AUTHORS_QUERY } from './constants'; /** * Wrapper component that renders its children only if the post type supports the author. * - * @param {Object} props The component props. - * @param {Element} props.children Children to be rendered. + * @param {Object} props The component props. + * @param {React.ReactNode} props.children Children to be rendered. * - * @return {Component|null} The component to be rendered. Return `null` if the post type doesn't + * @return {React.ReactNode} The component to be rendered. Return `null` if the post type doesn't * supports the author or if there are no authors available. */ export default function PostAuthorCheck( { children } ) { diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index 9ff3aaaf09a29c..7623adc10402c9 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -16,7 +16,7 @@ const minimumUsersForCombobox = 25; /** * Renders the component for selecting the post author. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ function PostAuthor() { const showCombobox = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-author/panel.js b/packages/editor/src/components/post-author/panel.js index 6c6a51918902dc..5a413aedac09cf 100644 --- a/packages/editor/src/components/post-author/panel.js +++ b/packages/editor/src/components/post-author/panel.js @@ -39,7 +39,7 @@ function PostAuthorToggle( { isOpen, onClick } ) { /** * Renders the Post Author Panel component. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ export function PostAuthor() { // Use internal state instead of a ref to make sure that the component diff --git a/packages/editor/src/components/post-comments/index.js b/packages/editor/src/components/post-comments/index.js index 1d331811b46b26..6e69f9bce4f838 100644 --- a/packages/editor/src/components/post-comments/index.js +++ b/packages/editor/src/components/post-comments/index.js @@ -61,6 +61,6 @@ function PostComments() { /** * A form for managing comment status. * - * @return {JSX.Element} The rendered PostComments component. + * @return {React.ReactNode} The rendered PostComments component. */ export default PostComments; diff --git a/packages/editor/src/components/post-discussion/panel.js b/packages/editor/src/components/post-discussion/panel.js index c539791d404dec..280ab11b0447e7 100644 --- a/packages/editor/src/components/post-discussion/panel.js +++ b/packages/editor/src/components/post-discussion/panel.js @@ -93,7 +93,7 @@ function PostDiscussionToggle( { isOpen, onClick } ) { * checks whether the current post has support for the * above and if the `discussion-panel` panel is enabled. * - * @return {JSX.Element|null} The rendered PostDiscussionPanel component. + * @return {React.ReactNode} The rendered PostDiscussionPanel component. */ export default function PostDiscussionPanel() { const { isEnabled } = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-excerpt/check.js b/packages/editor/src/components/post-excerpt/check.js index 77436ecfed218a..c518d90e424a9b 100644 --- a/packages/editor/src/components/post-excerpt/check.js +++ b/packages/editor/src/components/post-excerpt/check.js @@ -6,10 +6,10 @@ import PostTypeSupportCheck from '../post-type-support-check'; /** * Component for checking if the post type supports the excerpt field. * - * @param {Object} props Props. - * @param {Element} props.children Children to be rendered. + * @param {Object} props Props. + * @param {React.ReactNode} props.children Children to be rendered. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ function PostExcerptCheck( { children } ) { return ( diff --git a/packages/editor/src/components/post-excerpt/panel.js b/packages/editor/src/components/post-excerpt/panel.js index 9c09796f467040..d4f2b27126c7c1 100644 --- a/packages/editor/src/components/post-excerpt/panel.js +++ b/packages/editor/src/components/post-excerpt/panel.js @@ -83,7 +83,7 @@ function ExcerptPanel() { /** * Is rendered if the post type supports excerpts and allows editing the excerpt. * - * @return {JSX.Element} The rendered PostExcerptPanel component. + * @return {React.ReactNode} The rendered PostExcerptPanel component. */ export default function PostExcerptPanel() { return ( diff --git a/packages/editor/src/components/post-excerpt/plugin.js b/packages/editor/src/components/post-excerpt/plugin.js index 64861162a0f637..50c494c01cb6d8 100644 --- a/packages/editor/src/components/post-excerpt/plugin.js +++ b/packages/editor/src/components/post-excerpt/plugin.js @@ -12,9 +12,9 @@ const { Fill, Slot } = createSlotFill( 'PluginPostExcerpt' ); /** * Renders a post excerpt panel in the post sidebar. * - * @param {Object} props Component properties. - * @param {string} [props.className] An optional class name added to the row. - * @param {Element} props.children Children to be rendered. + * @param {Object} props Component properties. + * @param {string} [props.className] An optional class name added to the row. + * @param {React.ReactNode} props.children Children to be rendered. * * @example * ```js @@ -46,7 +46,7 @@ const { Fill, Slot } = createSlotFill( 'PluginPostExcerpt' ); * ); * ``` * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ const PluginPostExcerpt = ( { children, className } ) => { return ( diff --git a/packages/editor/src/components/post-featured-image/check.js b/packages/editor/src/components/post-featured-image/check.js index 823559f766bc35..700a3b8edfd032 100644 --- a/packages/editor/src/components/post-featured-image/check.js +++ b/packages/editor/src/components/post-featured-image/check.js @@ -8,10 +8,10 @@ import ThemeSupportCheck from '../theme-support-check'; * Wrapper component that renders its children only if the post type supports a featured image * and the theme supports post thumbnails. * - * @param {Object} props Props. - * @param {Element} props.children Children to be rendered. + * @param {Object} props Props. + * @param {React.ReactNode} props.children Children to be rendered. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ function PostFeaturedImageCheck( { children } ) { return ( diff --git a/packages/editor/src/components/post-featured-image/panel.js b/packages/editor/src/components/post-featured-image/panel.js index dd2a1527152ddf..8621b2eb886337 100644 --- a/packages/editor/src/components/post-featured-image/panel.js +++ b/packages/editor/src/components/post-featured-image/panel.js @@ -21,7 +21,7 @@ const PANEL_NAME = 'featured-image'; * @param {Object} props Props. * @param {boolean} props.withPanelBody Whether to include the panel body. Default true. * - * @return {Component|null} The component to be rendered. + * @return {React.ReactNode} The component to be rendered. * Return Null if the editor panel is disabled for featured image. */ export default function PostFeaturedImagePanel( { withPanelBody = true } ) { diff --git a/packages/editor/src/components/post-format/check.js b/packages/editor/src/components/post-format/check.js index 35729770b93c40..fe791862e1cebb 100644 --- a/packages/editor/src/components/post-format/check.js +++ b/packages/editor/src/components/post-format/check.js @@ -9,7 +9,15 @@ import { useSelect } from '@wordpress/data'; import PostTypeSupportCheck from '../post-type-support-check'; import { store as editorStore } from '../../store'; -function PostFormatCheck( { children } ) { +/** + * Component check if there are any post formats. + * + * @param {Object} props The component props. + * @param {React.ReactNode} props.children The child elements to render. + * + * @return {React.ReactNode} The rendered component or null if post formats are disabled. + */ +export default function PostFormatCheck( { children } ) { const disablePostFormats = useSelect( ( select ) => select( editorStore ).getEditorSettings().disablePostFormats, @@ -26,13 +34,3 @@ function PostFormatCheck( { children } ) { </PostTypeSupportCheck> ); } - -/** - * Component check if there are any post formats. - * - * @param {Object} props The component props. - * @param {Element} props.children The child elements to render. - * - * @return {Component|null} The rendered component or null if post formats are disabled. - */ -export default PostFormatCheck; diff --git a/packages/editor/src/components/post-format/index.js b/packages/editor/src/components/post-format/index.js index 8f7423239600f2..d98720cd6fa93f 100644 --- a/packages/editor/src/components/post-format/index.js +++ b/packages/editor/src/components/post-format/index.js @@ -46,7 +46,7 @@ export const POST_FORMATS = [ * <PostFormat /> * ``` * - * @return {JSX.Element} The rendered PostFormat component. + * @return {React.ReactNode} The rendered PostFormat component. */ export default function PostFormat() { const instanceId = useInstanceId( PostFormat ); diff --git a/packages/editor/src/components/post-format/panel.js b/packages/editor/src/components/post-format/panel.js index faaf88b785a4b2..18704eda6fc448 100644 --- a/packages/editor/src/components/post-format/panel.js +++ b/packages/editor/src/components/post-format/panel.js @@ -18,7 +18,7 @@ import { store as editorStore } from '../../store'; /** * Renders the Post Author Panel component. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ function PostFormat() { const { postFormat } = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-last-revision/check.js b/packages/editor/src/components/post-last-revision/check.js index c570f5e42cdc32..cb3c655e1b7cc3 100644 --- a/packages/editor/src/components/post-last-revision/check.js +++ b/packages/editor/src/components/post-last-revision/check.js @@ -12,10 +12,10 @@ import { store as editorStore } from '../../store'; /** * Wrapper component that renders its children if the post has more than one revision. * - * @param {Object} props Props. - * @param {Element} props.children Children to be rendered. + * @param {Object} props Props. + * @param {React.ReactNode} props.children Children to be rendered. * - * @return {Component|null} Rendered child components if post has more than one revision, otherwise null. + * @return {React.ReactNode} Rendered child components if post has more than one revision, otherwise null. */ function PostLastRevisionCheck( { children } ) { const { lastRevisionId, revisionsCount } = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-last-revision/index.js b/packages/editor/src/components/post-last-revision/index.js index fd68f9703cb4e2..ac25e6cb8f30d6 100644 --- a/packages/editor/src/components/post-last-revision/index.js +++ b/packages/editor/src/components/post-last-revision/index.js @@ -28,7 +28,7 @@ function usePostLastRevisionInfo() { /** * Renders the component for displaying the last revision of a post. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ function PostLastRevision() { const { lastRevisionId, revisionsCount } = usePostLastRevisionInfo(); diff --git a/packages/editor/src/components/post-last-revision/panel.js b/packages/editor/src/components/post-last-revision/panel.js index e87475cc2b34e9..55a3ba571c4b0a 100644 --- a/packages/editor/src/components/post-last-revision/panel.js +++ b/packages/editor/src/components/post-last-revision/panel.js @@ -12,7 +12,7 @@ import PostLastRevisionCheck from './check'; /** * Renders the panel for displaying the last revision of a post. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ function PostLastRevisionPanel() { return ( diff --git a/packages/editor/src/components/post-locked-modal/index.js b/packages/editor/src/components/post-locked-modal/index.js index 7bfa2d23fd9808..16cff5af976841 100644 --- a/packages/editor/src/components/post-locked-modal/index.js +++ b/packages/editor/src/components/post-locked-modal/index.js @@ -24,7 +24,7 @@ import { store as editorStore } from '../../store'; * A modal component that is displayed when a post is locked for editing by another user. * The modal provides information about the lock status and options to take over or exit the editor. * - * @return {JSX.Element|null} The rendered PostLockedModal component. + * @return {React.ReactNode} The rendered PostLockedModal component. */ export default function PostLockedModal() { const instanceId = useInstanceId( PostLockedModal ); diff --git a/packages/editor/src/components/post-pending-status/check.js b/packages/editor/src/components/post-pending-status/check.js index 7a4ff5195041c6..9f407d8c8cd82a 100644 --- a/packages/editor/src/components/post-pending-status/check.js +++ b/packages/editor/src/components/post-pending-status/check.js @@ -13,10 +13,10 @@ import { store as editorStore } from '../../store'; * If the post is already published or the user doesn't have the * capability to publish, it returns null. * - * @param {Object} props Component properties. - * @param {Element} props.children Children to be rendered. + * @param {Object} props Component properties. + * @param {React.ReactElement} props.children Children to be rendered. * - * @return {JSX.Element|null} The rendered child elements or null if the post is already published or the user doesn't have the capability to publish. + * @return {React.ReactElement} The rendered child elements or null if the post is already published or the user doesn't have the capability to publish. */ export function PostPendingStatusCheck( { children } ) { const { hasPublishAction, isPublished } = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-pending-status/index.js b/packages/editor/src/components/post-pending-status/index.js index 8363ebc715891b..352570c44a6630 100644 --- a/packages/editor/src/components/post-pending-status/index.js +++ b/packages/editor/src/components/post-pending-status/index.js @@ -14,7 +14,7 @@ import { store as editorStore } from '../../store'; /** * A component for displaying and toggling the pending status of a post. * - * @return {JSX.Element} The rendered component. + * @return {React.ReactNode} The rendered component. */ export function PostPendingStatus() { const status = useSelect( diff --git a/packages/editor/src/components/post-preview-button/index.js b/packages/editor/src/components/post-preview-button/index.js index d57143cd355d80..d1755f96b68615 100644 --- a/packages/editor/src/components/post-preview-button/index.js +++ b/packages/editor/src/components/post-preview-button/index.js @@ -112,7 +112,7 @@ function writeInterstitialMessage( targetDocument ) { * @param {string} props.role The role attribute for the button. * @param {Function} props.onPreview The callback function for preview event. * - * @return {JSX.Element|null} The rendered button component. + * @return {React.ReactNode} The rendered button component. */ export default function PostPreviewButton( { className, diff --git a/packages/editor/src/components/post-schedule/check.js b/packages/editor/src/components/post-schedule/check.js index 28456b90371cc3..32526a977f94fa 100644 --- a/packages/editor/src/components/post-schedule/check.js +++ b/packages/editor/src/components/post-schedule/check.js @@ -11,10 +11,10 @@ import { store as editorStore } from '../../store'; /** * Wrapper component that renders its children only if post has a publish action. * - * @param {Object} props Props. - * @param {Element} props.children Children to be rendered. + * @param {Object} props Props. + * @param {React.ReactElement} props.children Children to be rendered. * - * @return {Component} - The component to be rendered or null if there is no publish action. + * @return {React.ReactElement} - The component to be rendered or null if there is no publish action. */ export default function PostScheduleCheck( { children } ) { const hasPublishAction = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-schedule/index.js b/packages/editor/src/components/post-schedule/index.js index 94387ed4267fa9..c9b017bcfa80df 100644 --- a/packages/editor/src/components/post-schedule/index.js +++ b/packages/editor/src/components/post-schedule/index.js @@ -27,7 +27,7 @@ const { PrivatePublishDateTimePicker } = unlock( blockEditorPrivateApis ); * @param {Object} props Props. * @param {Function} props.onClose Function to close the component. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ export default function PostSchedule( props ) { return ( diff --git a/packages/editor/src/components/post-schedule/label.js b/packages/editor/src/components/post-schedule/label.js index f6cf3811db7916..2b8819747e7e0c 100644 --- a/packages/editor/src/components/post-schedule/label.js +++ b/packages/editor/src/components/post-schedule/label.js @@ -15,7 +15,7 @@ import { store as editorStore } from '../../store'; * * @param {Object} props Props. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ export default function PostScheduleLabel( props ) { return usePostScheduleLabel( props ); diff --git a/packages/editor/src/components/post-schedule/panel.js b/packages/editor/src/components/post-schedule/panel.js index 5d63da5e30c910..fd453a4667417f 100644 --- a/packages/editor/src/components/post-schedule/panel.js +++ b/packages/editor/src/components/post-schedule/panel.js @@ -31,7 +31,7 @@ const DESIGN_POST_TYPES = [ /** * Renders the Post Schedule Panel component. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ export default function PostSchedulePanel() { const [ popoverAnchor, setPopoverAnchor ] = useState( null ); diff --git a/packages/editor/src/components/post-slug/check.js b/packages/editor/src/components/post-slug/check.js index 86bf04814c934d..8ca7078a1a9e24 100644 --- a/packages/editor/src/components/post-slug/check.js +++ b/packages/editor/src/components/post-slug/check.js @@ -6,10 +6,10 @@ import PostTypeSupportCheck from '../post-type-support-check'; /** * Wrapper component that renders its children only if the post type supports the slug. * - * @param {Object} props Props. - * @param {Element} props.children Children to be rendered. + * @param {Object} props Props. + * @param {React.ReactNode} props.children Children to be rendered. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ export default function PostSlugCheck( { children } ) { return ( diff --git a/packages/editor/src/components/post-slug/index.js b/packages/editor/src/components/post-slug/index.js index 1a4f8e93d7565c..afff7f361ea428 100644 --- a/packages/editor/src/components/post-slug/index.js +++ b/packages/editor/src/components/post-slug/index.js @@ -62,7 +62,7 @@ function PostSlugControl() { /** * Renders the PostSlug component. It provide a control for editing the post slug. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ export default function PostSlug() { return ( diff --git a/packages/editor/src/components/post-sticky/check.js b/packages/editor/src/components/post-sticky/check.js index f504effca82c6b..ede5c22f3c3e32 100644 --- a/packages/editor/src/components/post-sticky/check.js +++ b/packages/editor/src/components/post-sticky/check.js @@ -11,10 +11,10 @@ import { store as editorStore } from '../../store'; /** * Wrapper component that renders its children only if post has a sticky action. * - * @param {Object} props Props. - * @param {Element} props.children Children to be rendered. + * @param {Object} props Props. + * @param {React.ReactElement} props.children Children to be rendered. * - * @return {Component} The component to be rendered or null if post type is not 'post' or hasStickyAction is false. + * @return {React.ReactElement} The component to be rendered or null if post type is not 'post' or hasStickyAction is false. */ export default function PostStickyCheck( { children } ) { const { hasStickyAction, postType } = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-sticky/index.js b/packages/editor/src/components/post-sticky/index.js index 43a4bea98de26e..6f5b914cb2f352 100644 --- a/packages/editor/src/components/post-sticky/index.js +++ b/packages/editor/src/components/post-sticky/index.js @@ -14,7 +14,7 @@ import { store as editorStore } from '../../store'; /** * Renders the PostSticky component. It provides a checkbox control for the sticky post feature. * - * @return {Component} The component to be rendered. + * @return {React.ReactNode} The rendered component. */ export default function PostSticky() { const postSticky = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-switch-to-draft-button/index.js b/packages/editor/src/components/post-switch-to-draft-button/index.js index a743c7a2991ffb..6a41e1fad597a2 100644 --- a/packages/editor/src/components/post-switch-to-draft-button/index.js +++ b/packages/editor/src/components/post-switch-to-draft-button/index.js @@ -18,7 +18,7 @@ import { store as editorStore } from '../../store'; /** * Renders a button component that allows the user to switch a post to draft status. * - * @return {JSX.Element} The rendered component. + * @return {React.ReactNode} The rendered component. */ export default function PostSwitchToDraftButton() { deprecated( 'wp.editor.PostSwitchToDraftButton', { diff --git a/packages/editor/src/components/post-sync-status/index.js b/packages/editor/src/components/post-sync-status/index.js index d3e2a1a5522e89..5f965c01503f5c 100644 --- a/packages/editor/src/components/post-sync-status/index.js +++ b/packages/editor/src/components/post-sync-status/index.js @@ -13,7 +13,7 @@ import { store as editorStore } from '../../store'; /** * Renders the sync status of a post. * - * @return {JSX.Element|null} The rendered sync status component. + * @return {React.ReactNode} The rendered sync status component. */ export default function PostSyncStatus() { const { syncStatus, postType } = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-taxonomies/check.js b/packages/editor/src/components/post-taxonomies/check.js index 401b1adad7cad4..ce3db319ae2e8a 100644 --- a/packages/editor/src/components/post-taxonomies/check.js +++ b/packages/editor/src/components/post-taxonomies/check.js @@ -12,10 +12,10 @@ import { store as editorStore } from '../../store'; /** * Renders the children components only if the current post type has taxonomies. * - * @param {Object} props The component props. - * @param {Element} props.children The children components to render. + * @param {Object} props The component props. + * @param {React.ReactNode} props.children The children components to render. * - * @return {Component|null} The rendered children components or null if the current post type has no taxonomies. + * @return {React.ReactElement} The rendered children components or null if the current post type has no taxonomies. */ export default function PostTaxonomiesCheck( { children } ) { const hasTaxonomies = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-taxonomies/flat-term-selector.js b/packages/editor/src/components/post-taxonomies/flat-term-selector.js index cd9377766af503..890175534c8b4a 100644 --- a/packages/editor/src/components/post-taxonomies/flat-term-selector.js +++ b/packages/editor/src/components/post-taxonomies/flat-term-selector.js @@ -71,7 +71,7 @@ const Wrapper = ( { children, __nextHasNoMarginBottom } ) => * @param {string} props.slug The slug of the taxonomy. * @param {boolean} props.__nextHasNoMarginBottom Start opting into the new margin-free styles that will become the default in a future version, currently scheduled to be WordPress 7.0. (The prop can be safely removed once this happens.) * - * @return {JSX.Element} The rendered flat term selector component. + * @return {React.ReactNode} The rendered flat term selector component. */ export function FlatTermSelector( { slug, __nextHasNoMarginBottom } ) { const [ values, setValues ] = useState( [] ); diff --git a/packages/editor/src/components/post-taxonomies/panel.js b/packages/editor/src/components/post-taxonomies/panel.js index 760626f984db36..f75fa74cc3d2e9 100644 --- a/packages/editor/src/components/post-taxonomies/panel.js +++ b/packages/editor/src/components/post-taxonomies/panel.js @@ -11,6 +11,15 @@ import { store as editorStore } from '../../store'; import PostTaxonomiesForm from './index'; import PostTaxonomiesCheck from './check'; +/** + * Renders a panel for a specific taxonomy. + * + * @param {Object} props The component props. + * @param {Object} props.taxonomy The taxonomy object. + * @param {React.ReactNode} props.children The child components. + * + * @return {React.ReactNode} The rendered taxonomy panel. + */ function TaxonomyPanel( { taxonomy, children } ) { const slug = taxonomy?.slug; const panelName = slug ? `taxonomy-panel-${ slug }` : ''; @@ -47,7 +56,12 @@ function TaxonomyPanel( { taxonomy, children } ) { ); } -function PostTaxonomies() { +/** + * Component that renders the post taxonomies panel. + * + * @return {React.ReactNode} The rendered component. + */ +export default function PostTaxonomies() { return ( <PostTaxonomiesCheck> <PostTaxonomiesForm @@ -62,14 +76,3 @@ function PostTaxonomies() { </PostTaxonomiesCheck> ); } - -/** - * Renders a panel for a specific taxonomy. - * - * @param {Object} props The component props. - * @param {Object} props.taxonomy The taxonomy object. - * @param {Element} props.children The child components. - * - * @return {Component} The rendered taxonomy panel. - */ -export default PostTaxonomies; diff --git a/packages/editor/src/components/post-template/classic-theme.js b/packages/editor/src/components/post-template/classic-theme.js index 4a65a9b4c75636..4345e06211c661 100644 --- a/packages/editor/src/components/post-template/classic-theme.js +++ b/packages/editor/src/components/post-template/classic-theme.js @@ -63,7 +63,7 @@ function PostTemplateToggle( { isOpen, onClick } ) { * @param {Object} props The component props. * @param {Function} props.onClose The function to close the dropdown. * - * @return {JSX.Element} The rendered dropdown content. + * @return {React.ReactNode} The rendered dropdown content. */ function PostTemplateDropdownContent( { onClose } ) { const allowSwitchingTemplate = useAllowSwitchingTemplates(); @@ -235,6 +235,6 @@ function ClassicThemeControl() { * * The dropdown menu includes a button for toggling the menu, a list of available templates, and options for creating and editing templates. * - * @return {JSX.Element} The rendered ClassicThemeControl component. + * @return {React.ReactNode} The rendered ClassicThemeControl component. */ export default ClassicThemeControl; diff --git a/packages/editor/src/components/post-template/panel.js b/packages/editor/src/components/post-template/panel.js index b5f0d34197c686..903612ef11ed15 100644 --- a/packages/editor/src/components/post-template/panel.js +++ b/packages/editor/src/components/post-template/panel.js @@ -16,7 +16,7 @@ import PostPanelRow from '../post-panel-row'; /** * Displays the template controls based on the current editor settings and user permissions. * - * @return {JSX.Element|null} The rendered PostTemplatePanel component. + * @return {React.ReactNode} The rendered PostTemplatePanel component. */ export default function PostTemplatePanel() { const { templateId, isBlockTheme } = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-text-editor/index.js b/packages/editor/src/components/post-text-editor/index.js index c3dc61a0b4a2ef..0ae569c3e15301 100644 --- a/packages/editor/src/components/post-text-editor/index.js +++ b/packages/editor/src/components/post-text-editor/index.js @@ -22,7 +22,7 @@ import { store as editorStore } from '../../store'; /** * Displays the Post Text Editor along with content in Visual and Text mode. * - * @return {JSX.Element|null} The rendered PostTextEditor component. + * @return {React.ReactNode} The rendered PostTextEditor component. */ export default function PostTextEditor() { const instanceId = useInstanceId( PostTextEditor ); diff --git a/packages/editor/src/components/post-title/index.js b/packages/editor/src/components/post-title/index.js index 7fc79eaeddffb5..090beb57f6170e 100644 --- a/packages/editor/src/components/post-title/index.js +++ b/packages/editor/src/components/post-title/index.js @@ -193,7 +193,7 @@ const PostTitle = forwardRef( ( _, forwardedRef ) => { * @param {Object} _ Unused parameter. * @param {Element} forwardedRef Forwarded ref for the component. * - * @return {Component} The rendered PostTitle component. + * @return {React.ReactNode} The rendered PostTitle component. */ export default forwardRef( ( _, forwardedRef ) => ( <PostTypeSupportCheck supportKeys="title"> diff --git a/packages/editor/src/components/post-title/post-title-raw.js b/packages/editor/src/components/post-title/post-title-raw.js index 66c944b45871ab..9beba1068f8ef7 100644 --- a/packages/editor/src/components/post-title/post-title-raw.js +++ b/packages/editor/src/components/post-title/post-title-raw.js @@ -26,7 +26,7 @@ import usePostTitle from './use-post-title'; * @param {Object} _ Unused parameter. * @param {Element} forwardedRef Reference to the component's DOM node. * - * @return {Component} The rendered component. + * @return {React.ReactNode} The rendered component. */ function PostTitleRaw( _, forwardedRef ) { const { placeholder } = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-trash/check.js b/packages/editor/src/components/post-trash/check.js index 7edc7c0f18c273..893d46ef9a0867 100644 --- a/packages/editor/src/components/post-trash/check.js +++ b/packages/editor/src/components/post-trash/check.js @@ -13,10 +13,10 @@ import { GLOBAL_POST_TYPES } from '../../store/constants'; /** * Wrapper component that renders its children only if the post can trashed. * - * @param {Object} props - The component props. - * @param {Element} props.children - The child components to render. + * @param {Object} props - The component props. + * @param {React.ReactEl} props.children - The child components to render. * - * @return {Component|null} The rendered child components or null if the post can not trashed. + * @return {React.ReactElement} The rendered child components or null if the post can not trashed. */ export default function PostTrashCheck( { children } ) { const { canTrashPost } = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-trash/index.js b/packages/editor/src/components/post-trash/index.js index 743512e9efd7d4..2d3dd8bcb0c4b3 100644 --- a/packages/editor/src/components/post-trash/index.js +++ b/packages/editor/src/components/post-trash/index.js @@ -19,7 +19,7 @@ import PostTrashCheck from './check'; * Displays the Post Trash Button and Confirm Dialog in the Editor. * * @param {?{onActionPerformed: Object}} An object containing the onActionPerformed function. - * @return {JSX.Element|null} The rendered PostTrash component. + * @return {React.ReactNode} The rendered PostTrash component. */ export default function PostTrash( { onActionPerformed } ) { const registry = useRegistry(); diff --git a/packages/editor/src/components/post-type-support-check/index.js b/packages/editor/src/components/post-type-support-check/index.js index 613fda8eb82da3..f04aea84b0e411 100644 --- a/packages/editor/src/components/post-type-support-check/index.js +++ b/packages/editor/src/components/post-type-support-check/index.js @@ -13,13 +13,13 @@ import { store as editorStore } from '../../store'; * A component which renders its own children only if the current editor post * type supports one of the given `supportKeys` prop. * - * @param {Object} props Props. - * @param {Element} props.children Children to be rendered if post - * type supports. - * @param {(string|string[])} props.supportKeys String or string array of keys - * to test. + * @param {Object} props Props. + * @param {React.ReactElement} props.children Children to be rendered if post + * type supports. + * @param {(string|string[])} props.supportKeys String or string array of keys + * to test. * - * @return {Component} The component to be rendered. + * @return {React.ReactElement} The component to be rendered. */ function PostTypeSupportCheck( { children, supportKeys } ) { const postType = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-url/check.js b/packages/editor/src/components/post-url/check.js index 7eb390472bdd7d..a80d829de23221 100644 --- a/packages/editor/src/components/post-url/check.js +++ b/packages/editor/src/components/post-url/check.js @@ -12,10 +12,10 @@ import { store as editorStore } from '../../store'; /** * Check if the post URL is valid and visible. * - * @param {Object} props The component props. - * @param {Element} props.children The child components. + * @param {Object} props The component props. + * @param {React.ReactElement} props.children The child components. * - * @return {Component|null} The child components if the post URL is valid and visible, otherwise null. + * @return {React.ReactElement} The child components if the post URL is valid and visible, otherwise null. */ export default function PostURLCheck( { children } ) { const isVisible = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-url/index.js b/packages/editor/src/components/post-url/index.js index f03bdd59752a83..c72ca5825f6fe6 100644 --- a/packages/editor/src/components/post-url/index.js +++ b/packages/editor/src/components/post-url/index.js @@ -34,7 +34,7 @@ import { store as editorStore } from '../../store'; * * @param {Function} onClose Callback function to be executed when the popover is closed. * - * @return {Component} The rendered PostURL component. + * @return {React.ReactNode} The rendered PostURL component. */ export default function PostURL( { onClose } ) { const { diff --git a/packages/editor/src/components/post-url/label.js b/packages/editor/src/components/post-url/label.js index 4f03e2bce0d05f..277cc6cfc715d3 100644 --- a/packages/editor/src/components/post-url/label.js +++ b/packages/editor/src/components/post-url/label.js @@ -12,7 +12,7 @@ import { store as editorStore } from '../../store'; /** * Represents a label component for a post URL. * - * @return {Component} The PostURLLabel component. + * @return {React.ReactNode} The PostURLLabel component. */ export default function PostURLLabel() { return usePostURLLabel(); diff --git a/packages/editor/src/components/post-url/panel.js b/packages/editor/src/components/post-url/panel.js index 786a12cb8e6b54..97eaa8ccb77f8d 100644 --- a/packages/editor/src/components/post-url/panel.js +++ b/packages/editor/src/components/post-url/panel.js @@ -19,7 +19,7 @@ import { store as editorStore } from '../../store'; /** * Renders the `PostURLPanel` component. * - * @return {JSX.Element} The rendered PostURLPanel component. + * @return {React.ReactNode} The rendered PostURLPanel component. */ export default function PostURLPanel() { const { isFrontPage } = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-visibility/check.js b/packages/editor/src/components/post-visibility/check.js index 19a241ae1110ae..ea04a6b739617a 100644 --- a/packages/editor/src/components/post-visibility/check.js +++ b/packages/editor/src/components/post-visibility/check.js @@ -15,7 +15,7 @@ import { store as editorStore } from '../../store'; * @param {Object} props The component props. * @param {Function} props.render Function to render the component. * Receives an object with a `canEdit` property. - * @return {JSX.Element} The rendered component. + * @return {React.ReactNode} The rendered component. */ export default function PostVisibilityCheck( { render } ) { const canEdit = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-visibility/index.js b/packages/editor/src/components/post-visibility/index.js index e47f2acd664434..3eb0c157c337ca 100644 --- a/packages/editor/src/components/post-visibility/index.js +++ b/packages/editor/src/components/post-visibility/index.js @@ -22,7 +22,7 @@ import { store as editorStore } from '../../store'; * * @param {Object} props The component props. * @param {Function} props.onClose Function to call when the popover is closed. - * @return {JSX.Element} The rendered component. + * @return {React.ReactNode} The rendered component. */ export default function PostVisibility( { onClose } ) { const instanceId = useInstanceId( PostVisibility ); diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 6c05e5b58235b3..996e9e68954591 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -411,7 +411,7 @@ export const ExperimentalEditorProvider = withRegistryProvider( * </EditorProvider> * ``` * - * @return {JSX.Element} The rendered EditorProvider component. + * @return {React.ReactNode} The rendered EditorProvider component. */ export function EditorProvider( props ) { return ( diff --git a/packages/editor/src/components/table-of-contents/index.js b/packages/editor/src/components/table-of-contents/index.js index 6fd83557b13ab7..47de10b66ebdd1 100644 --- a/packages/editor/src/components/table-of-contents/index.js +++ b/packages/editor/src/components/table-of-contents/index.js @@ -61,6 +61,6 @@ function TableOfContents( * @param {boolean} props.repositionDropdown Whether to reposition the dropdown. * @param {Element.ref} ref The component's ref. * - * @return {JSX.Element} The rendered table of contents component. + * @return {React.ReactNode} The rendered table of contents component. */ export default forwardRef( TableOfContents ); diff --git a/packages/editor/src/components/theme-support-check/index.js b/packages/editor/src/components/theme-support-check/index.js index 78fbde809a7088..1f29370d32199c 100644 --- a/packages/editor/src/components/theme-support-check/index.js +++ b/packages/editor/src/components/theme-support-check/index.js @@ -12,11 +12,11 @@ import { store as editorStore } from '../../store'; /** * Checks if the current theme supports specific features and renders the children if supported. * - * @param {Object} props The component props. - * @param {Element} props.children The children to render if the theme supports the specified features. - * @param {string|string[]} props.supportKeys The key(s) of the theme support(s) to check. + * @param {Object} props The component props. + * @param {React.ReactElement} props.children The children to render if the theme supports the specified features. + * @param {string|string[]} props.supportKeys The key(s) of the theme support(s) to check. * - * @return {JSX.Element|null} The rendered children if the theme supports the specified features, otherwise null. + * @return {React.ReactElement} The rendered children if the theme supports the specified features, otherwise null. */ export default function ThemeSupportCheck( { children, supportKeys } ) { const { postType, themeSupports } = useSelect( ( select ) => { diff --git a/packages/editor/src/components/time-to-read/index.js b/packages/editor/src/components/time-to-read/index.js index 5d748abc3049cb..21891273991a2c 100644 --- a/packages/editor/src/components/time-to-read/index.js +++ b/packages/editor/src/components/time-to-read/index.js @@ -23,7 +23,7 @@ const AVERAGE_READING_RATE = 189; /** * Component for showing Time To Read in Content. * - * @return {JSX.Element} The rendered TimeToRead component. + * @return {React.ReactNode} The rendered TimeToRead component. */ export default function TimeToRead() { const content = useSelect( diff --git a/packages/editor/src/components/unsaved-changes-warning/index.js b/packages/editor/src/components/unsaved-changes-warning/index.js index 49e2b7edf1f293..d04b1f36abcbb3 100644 --- a/packages/editor/src/components/unsaved-changes-warning/index.js +++ b/packages/editor/src/components/unsaved-changes-warning/index.js @@ -10,7 +10,7 @@ import { store as coreStore } from '@wordpress/core-data'; * Warns the user if there are unsaved changes before leaving the editor. * Compatible with Post Editor and Site Editor. * - * @return {Component} The component. + * @return {React.ReactNode} The component. */ export default function UnsavedChangesWarning() { const { __experimentalGetDirtyEntityRecords } = useSelect( coreStore ); diff --git a/packages/editor/src/components/word-count/index.js b/packages/editor/src/components/word-count/index.js index aab562b46b89ff..31eb4d6bfd8c35 100644 --- a/packages/editor/src/components/word-count/index.js +++ b/packages/editor/src/components/word-count/index.js @@ -13,7 +13,7 @@ import { store as editorStore } from '../../store'; /** * Renders the word count of the post content. * - * @return {JSX.Element|null} The rendered WordCount component. + * @return {React.ReactNode} The rendered WordCount component. */ export default function WordCount() { const content = useSelect( diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index 4942e50322e06e..9d0de08718cd2b 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -35,9 +35,9 @@ import { unlock } from '../lock-unlock'; * Returns an action generator used in signalling that editor has initialized with * the specified post object and editor settings. * - * @param {Object} post Post object. - * @param {Object} edits Initial edited attributes object. - * @param {Array?} template Block Template. + * @param {Object} post Post object. + * @param {Object} edits Initial edited attributes object. + * @param {Array} [template] Block Template. */ export const setupEditor = ( post, edits, template ) => @@ -157,8 +157,8 @@ export function setEditedPost( postType, postId ) { * Returns an action object used in signalling that attributes of the post have * been edited. * - * @param {Object} edits Post attributes to edit. - * @param {Object} options Options for the edit. + * @param {Object} edits Post attributes to edit. + * @param {Object} [options] Options for the edit. * * @example * ```js @@ -195,7 +195,7 @@ export const editPost = /** * Action for saving the current post in the editor. * - * @param {Object} options + * @param {Object} [options] */ export const savePost = ( options = {} ) => @@ -375,7 +375,8 @@ export const trashPost = * autosaving (e.g. on the Web, the post might be committed to Session * Storage). * - * @param {Object?} options Extra flags to identify the autosave. + * @param {Object} [options] Extra flags to identify the autosave. + * @param {boolean} [options.local] Whether to perform a local autosave. */ export const autosave = ( { local = false, ...options } = {} ) => @@ -598,8 +599,8 @@ export function unlockPostAutosaving( lockName ) { /** * Returns an action object used to signal that the blocks have been updated. * - * @param {Array} blocks Block Array. - * @param {?Object} options Optional options. + * @param {Array} blocks Block Array. + * @param {Object} [options] Optional options. */ export const resetEditorBlocks = ( blocks, options = {} ) => From 21ee975dbc831588cecda74af7a93dedb615448b Mon Sep 17 00:00:00 2001 From: Sukhendu Sekhar Guria <sukhendu.guria@rtcamp.com> Date: Mon, 25 Nov 2024 15:44:12 +0530 Subject: [PATCH 1691/1908] Fix: Preserve Display Preview State in File Block (#67263) Co-authored-by: Sukhendu2002 <sukhendu2002@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: MadtownLems <madtownlems@git.wordpress.org> --- packages/block-library/src/file/edit.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/file/edit.js b/packages/block-library/src/file/edit.js index 937eb3d28eb192..838b807507d314 100644 --- a/packages/block-library/src/file/edit.js +++ b/packages/block-library/src/file/edit.js @@ -128,15 +128,21 @@ function FileEdit( { attributes, isSelected, setAttributes, clientId } ) { } const isPdf = newMedia.url.endsWith( '.pdf' ); + const pdfAttributes = { + displayPreview: isPdf + ? attributes.displayPreview ?? true + : undefined, + previewHeight: isPdf ? attributes.previewHeight ?? 600 : undefined, + }; + setAttributes( { href: newMedia.url, fileName: newMedia.title, textLinkHref: newMedia.url, id: newMedia.id, - displayPreview: isPdf ? true : undefined, - previewHeight: isPdf ? 600 : undefined, fileId: `wp-block-file--media-${ clientId }`, blob: undefined, + ...pdfAttributes, } ); setTemporaryURL(); } From a6a04bebfb96f47df6c1f238c0fe63233d6dd3f5 Mon Sep 17 00:00:00 2001 From: Bernie Reiter <96308+ockham@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:20:51 +0100 Subject: [PATCH 1692/1908] Terms: Respect order specified by register_taxonomy() (#67154) It is possible to supply a default set of `args` to `register_taxonomy()` which will be used when querying a list of terms -- for example, `orderby` in order to specify how the resulting list of terms should be sorted. This commit makes it so that the list of terms returned by the Terms REST API controller respects that order. Co-authored-by: ockham <bernhard-reiter@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- backport-changelog/6.8/7848.md | 3 +++ lib/compat/wordpress-6.8/rest-api.php | 29 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 backport-changelog/6.8/7848.md diff --git a/backport-changelog/6.8/7848.md b/backport-changelog/6.8/7848.md new file mode 100644 index 00000000000000..84600eb4847cdb --- /dev/null +++ b/backport-changelog/6.8/7848.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7848 + +* https://github.com/WordPress/gutenberg/pull/67154 diff --git a/lib/compat/wordpress-6.8/rest-api.php b/lib/compat/wordpress-6.8/rest-api.php index da1b657cda0783..080e4003f57b38 100644 --- a/lib/compat/wordpress-6.8/rest-api.php +++ b/lib/compat/wordpress-6.8/rest-api.php @@ -20,3 +20,32 @@ function gutenberg_add_post_type_rendering_mode() { } } add_action( 'rest_api_init', 'gutenberg_add_post_type_rendering_mode' ); + +// When querying terms for a given taxonomy in the REST API, respect the default +// query arguments set for that taxonomy upon registration. +function gutenberg_respect_taxonomy_default_args_in_rest_api( $args ) { + // If a `post` argument is provided, the Terms controller will use + // `wp_get_object_terms`, which respects the default query arguments, + // so we don't need to do anything. + if ( ! empty( $args['post'] ) ) { + return $args; + } + + $t = get_taxonomy( $args['taxonomy'] ); + if ( isset( $t->args ) && is_array( $t->args ) ) { + $args = array_merge( $args, $t->args ); + } + return $args; +} +add_action( + 'registered_taxonomy', + function ( $taxonomy ) { + add_filter( "rest_{$taxonomy}_query", 'gutenberg_respect_taxonomy_default_args_in_rest_api' ); + } +); +add_action( + 'unregistered_taxonomy', + function ( $taxonomy ) { + remove_filter( "rest_{$taxonomy}_query", 'gutenberg_respect_taxonomy_default_args_in_rest_api' ); + } +); From 814bb4e380293ab79704682a067ff980d24c6a8c Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Mon, 25 Nov 2024 14:45:29 +0400 Subject: [PATCH 1693/1908] Editor: Update focus return handler for the Featured Image (#67236) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../components/post-featured-image/index.js | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/packages/editor/src/components/post-featured-image/index.js b/packages/editor/src/components/post-featured-image/index.js index 46a194f311a5e7..acf366506cc41e 100644 --- a/packages/editor/src/components/post-featured-image/index.js +++ b/packages/editor/src/components/post-featured-image/index.js @@ -18,7 +18,7 @@ import { Notice, } from '@wordpress/components'; import { isBlobURL } from '@wordpress/blob'; -import { useState, useRef, useEffect } from '@wordpress/element'; +import { useState, useRef } from '@wordpress/element'; import { compose } from '@wordpress/compose'; import { useSelect, withDispatch, withSelect } from '@wordpress/data'; import { @@ -102,17 +102,10 @@ function PostFeaturedImage( { noticeOperations, isRequestingFeaturedImageMedia, } ) { - const toggleRef = useRef(); + const returnsFocusRef = useRef( false ); const [ isLoading, setIsLoading ] = useState( false ); const { getSettings } = useSelect( blockEditorStore ); const { mediaSourceUrl } = getMediaDetails( media, currentPostId ); - const toggleFocusTimerRef = useRef(); - - useEffect( () => { - return () => { - clearTimeout( toggleFocusTimerRef.current ); - }; - }, [] ); function onDropFiles( filesList ) { getSettings().mediaUpload( { @@ -164,6 +157,13 @@ function PostFeaturedImage( { ); } + function returnFocus( node ) { + if ( returnsFocusRef.current && node ) { + node.focus(); + returnsFocusRef.current = false; + } + } + const isMissingMedia = ! isRequestingFeaturedImageMedia && !! featuredImageId && ! media; @@ -203,7 +203,7 @@ function PostFeaturedImage( { ) : ( <Button __next40pxDefaultSize - ref={ toggleRef } + ref={ returnFocus } className={ ! featuredImageId ? 'editor-post-featured-image__toggle' @@ -276,12 +276,10 @@ function PostFeaturedImage( { className="editor-post-featured-image__action" onClick={ () => { onRemoveImage(); - // The toggle button is rendered conditionally, we need - // to wait it is rendered before moving focus to it. - toggleFocusTimerRef.current = - setTimeout( () => { - toggleRef.current?.focus(); - } ); + // Signal that the toggle button should be focused, + // when it is rendered. Can't focus it directly here + // because it's rendered conditionally. + returnsFocusRef.current = true; } } variant={ isMissingMedia From 2be64e4c26fc606a1f4bcc625c7c79d9dcef5cac Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Mon, 25 Nov 2024 11:55:56 +0100 Subject: [PATCH 1694/1908] Components: remove createPrivateSlotFill function (#67238) * Components: remove createPrivateSlotFill function * Add changelog entry * Update documentation * Better jsdoc for deprecated __unstableName Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../src/components/block-controls/slot.js | 8 ++-- .../components/block-info-slot-fill/index.js | 6 +-- .../position-controls-panel.js | 4 +- .../use-inspector-controls-tabs.js | 20 ++++----- .../src/components/inspector-controls/slot.js | 10 +++-- packages/components/CHANGELOG.md | 1 + packages/components/src/private-apis.ts | 2 - packages/components/src/slot-fill/README.md | 41 ++++++++++++------- packages/components/src/slot-fill/index.tsx | 12 +++--- .../editor-canvas-container/index.js | 2 +- .../editor-interface/content-slot-fill.js | 13 ++---- 11 files changed, 61 insertions(+), 58 deletions(-) diff --git a/packages/block-editor/src/components/block-controls/slot.js b/packages/block-editor/src/components/block-controls/slot.js index ad800b49ab40db..9548b3e5cb0de8 100644 --- a/packages/block-editor/src/components/block-controls/slot.js +++ b/packages/block-editor/src/components/block-controls/slot.js @@ -31,9 +31,10 @@ export default function BlockControlsSlot( { group = 'default', ...props } ) { [ toolbarState, contextState ] ); - const Slot = groups[ group ]?.Slot; - const fills = useSlotFills( Slot?.__unstableName ); - if ( ! Slot ) { + const slotFill = groups[ group ]; + const fills = useSlotFills( slotFill.name ); + + if ( ! slotFill ) { warning( `Unknown BlockControls group "${ group }" provided.` ); return null; } @@ -42,6 +43,7 @@ export default function BlockControlsSlot( { group = 'default', ...props } ) { return null; } + const { Slot } = slotFill; const slot = <Slot { ...props } bubblesVirtually fillProps={ fillProps } />; if ( group === 'default' ) { diff --git a/packages/block-editor/src/components/block-info-slot-fill/index.js b/packages/block-editor/src/components/block-info-slot-fill/index.js index 8c9503313d754c..3592fc0424329b 100644 --- a/packages/block-editor/src/components/block-info-slot-fill/index.js +++ b/packages/block-editor/src/components/block-info-slot-fill/index.js @@ -1,19 +1,17 @@ /** * WordPress dependencies */ -import { privateApis as componentsPrivateApis } from '@wordpress/components'; +import { createSlotFill } from '@wordpress/components'; /** * Internal dependencies */ -import { unlock } from '../../lock-unlock'; import { useBlockEditContext, mayDisplayControlsKey, } from '../block-edit/context'; -const { createPrivateSlotFill } = unlock( componentsPrivateApis ); -const { Fill, Slot } = createPrivateSlotFill( 'BlockInformation' ); +const { Fill, Slot } = createSlotFill( Symbol( 'BlockInformation' ) ); const BlockInfo = ( props ) => { const context = useBlockEditContext(); diff --git a/packages/block-editor/src/components/inspector-controls-tabs/position-controls-panel.js b/packages/block-editor/src/components/inspector-controls-tabs/position-controls-panel.js index 9a3670b5deb286..42a8597227dee9 100644 --- a/packages/block-editor/src/components/inspector-controls-tabs/position-controls-panel.js +++ b/packages/block-editor/src/components/inspector-controls-tabs/position-controls-panel.js @@ -53,9 +53,7 @@ const PositionControlsPanel = () => { }; const PositionControls = () => { - const fills = useSlotFills( - InspectorControlsGroups.position.Slot.__unstableName - ); + const fills = useSlotFills( InspectorControlsGroups.position.name ); const hasFills = Boolean( fills && fills.length ); if ( ! hasFills ) { diff --git a/packages/block-editor/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js b/packages/block-editor/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js index 6a80d47f024816..c0655f4d85f3f4 100644 --- a/packages/block-editor/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js +++ b/packages/block-editor/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js @@ -46,18 +46,18 @@ export default function useInspectorControlsTabs( blockName ) { // List View Tab: If there are any fills for the list group add that tab. const listViewDisabled = useIsListViewTabDisabled( blockName ); - const listFills = useSlotFills( listGroup.Slot.__unstableName ); + const listFills = useSlotFills( listGroup.name ); const hasListFills = ! listViewDisabled && !! listFills && listFills.length; // Styles Tab: Add this tab if there are any fills for block supports // e.g. border, color, spacing, typography, etc. const styleFills = [ - ...( useSlotFills( borderGroup.Slot.__unstableName ) || [] ), - ...( useSlotFills( colorGroup.Slot.__unstableName ) || [] ), - ...( useSlotFills( dimensionsGroup.Slot.__unstableName ) || [] ), - ...( useSlotFills( stylesGroup.Slot.__unstableName ) || [] ), - ...( useSlotFills( typographyGroup.Slot.__unstableName ) || [] ), - ...( useSlotFills( effectsGroup.Slot.__unstableName ) || [] ), + ...( useSlotFills( borderGroup.name ) || [] ), + ...( useSlotFills( colorGroup.name ) || [] ), + ...( useSlotFills( dimensionsGroup.name ) || [] ), + ...( useSlotFills( stylesGroup.name ) || [] ), + ...( useSlotFills( typographyGroup.name ) || [] ), + ...( useSlotFills( effectsGroup.name ) || [] ), ]; const hasStyleFills = styleFills.length; @@ -67,12 +67,12 @@ export default function useInspectorControlsTabs( blockName ) { // the advanced controls slot as well to ensure they are rendered. const advancedFills = [ ...( useSlotFills( InspectorAdvancedControls.slotName ) || [] ), - ...( useSlotFills( bindingsGroup.Slot.__unstableName ) || [] ), + ...( useSlotFills( bindingsGroup.name ) || [] ), ]; const settingsFills = [ - ...( useSlotFills( defaultGroup.Slot.__unstableName ) || [] ), - ...( useSlotFills( positionGroup.Slot.__unstableName ) || [] ), + ...( useSlotFills( defaultGroup.name ) || [] ), + ...( useSlotFills( positionGroup.name ) || [] ), ...( hasListFills && hasStyleFills > 1 ? advancedFills : [] ), ]; diff --git a/packages/block-editor/src/components/inspector-controls/slot.js b/packages/block-editor/src/components/inspector-controls/slot.js index cc32b1c88480ed..5c18dbd1f86bb8 100644 --- a/packages/block-editor/src/components/inspector-controls/slot.js +++ b/packages/block-editor/src/components/inspector-controls/slot.js @@ -34,14 +34,14 @@ export default function InspectorControlsSlot( { ); group = __experimentalGroup; } - const Slot = groups[ group ]?.Slot; - const fills = useSlotFills( Slot?.__unstableName ); + const slotFill = groups[ group ]; + const fills = useSlotFills( slotFill?.name ); const motionContextValue = useContext( MotionContext ); const computedFillProps = useMemo( () => ( { - ...( fillProps ?? {} ), + ...fillProps, forwardedContext: [ ...( fillProps?.forwardedContext ?? [] ), [ MotionContext.Provider, { value: motionContextValue } ], @@ -50,7 +50,7 @@ export default function InspectorControlsSlot( { [ motionContextValue, fillProps ] ); - if ( ! Slot ) { + if ( ! slotFill ) { warning( `Unknown InspectorControls group "${ group }" provided.` ); return null; } @@ -59,6 +59,8 @@ export default function InspectorControlsSlot( { return null; } + const { Slot } = slotFill; + if ( label ) { return ( <BlockSupportToolsPanel group={ group } label={ label }> diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 564d9fcc683618..bcb9bfe3c013e4 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -30,6 +30,7 @@ ### Experimental - `SlotFill`: Remove registration API methods from return value of `__experimentalUseSlot` ([#67070](https://github.com/WordPress/gutenberg/pull/67070)). +- `SlotFill`: Remove the `createPrivateSlotFill` private API ([#67238](https://github.com/WordPress/gutenberg/pull/67238)). ### Internal diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index bea16b719a463d..2ced100dc576be 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -2,7 +2,6 @@ * Internal dependencies */ import { positionToPlacement as __experimentalPopoverLegacyPositionToPlacement } from './popover/utils'; -import { createPrivateSlotFill } from './slot-fill'; import { Menu } from './menu'; import { ComponentsContext } from './context/context-system-provider'; import Theme from './theme'; @@ -13,7 +12,6 @@ import { lock } from './lock-unlock'; export const privateApis = {}; lock( privateApis, { __experimentalPopoverLegacyPositionToPlacement, - createPrivateSlotFill, ComponentsContext, Tabs, Theme, diff --git a/packages/components/src/slot-fill/README.md b/packages/components/src/slot-fill/README.md index 9059566deefdf4..3f14b9ccde9eeb 100644 --- a/packages/components/src/slot-fill/README.md +++ b/packages/components/src/slot-fill/README.md @@ -1,18 +1,18 @@ -# Slot Fill +# Slot/Fill -Slot and Fill are a pair of components which enable developers to render elsewhere in a React element tree, a pattern often referred to as "portal" rendering. It is a pattern for component extensibility, where a single Slot may be occupied by an indeterminate number of Fills elsewhere in the application. +`Slot` and `Fill` are a pair of components which enable developers to render React UI elsewhere in a React element tree, a pattern often referred to as "portal" rendering. It is a pattern for component extensibility, where a single `Slot` may be occupied by multiple `Fill`s rendered in different parts of the application. -Slot Fill is heavily inspired by the [`react-slot-fill` library](https://github.com/camwest/react-slot-fill), but uses React's own portal rendering API. +Slot/Fill was originally inspired by the [`react-slot-fill` library](https://github.com/camwest/react-slot-fill). ## Usage -At the root of your application, you must render a `SlotFillProvider` which coordinates Slot and Fill rendering. +At the root of your application, you must render a `SlotFillProvider` which coordinates `Slot` and `Fill` rendering. -Then, render a Slot component anywhere in your application, giving it a name. +Then, render a `Slot` component anywhere in your application, giving it a `name`. The `name` is either a `string` or a symbol. Symbol names are useful for slots that are supposed to be private, accessible only to clients that have access to the symbol value. -Any Fill will automatically occupy this Slot space, even if rendered elsewhere in the application. +Any `Fill` will render its UI in this `Slot` space, even if rendered elsewhere in the application. -You can either use the Fill component directly, or a wrapper component type as in the below example to abstract the slot name from consumer awareness. +You can either use the `Fill` component directly, or create a wrapper component (as in the following example) to hide the slot name from the consumer. ```jsx import { @@ -43,7 +43,7 @@ const MySlotFillProvider = () => { }; ``` -There is also `createSlotFill` helper method which was created to simplify the process of matching the corresponding `Slot` and `Fill` components: +There is also the `createSlotFill` helper method which was created to simplify the process of matching the corresponding `Slot` and `Fill` components: ```jsx const { Fill, Slot } = createSlotFill( 'Toolbar' ); @@ -59,18 +59,27 @@ const Toolbar = () => ( ## Props -The `SlotFillProvider` component does not accept any props. +The `SlotFillProvider` component does not accept any props (except `children`). Both `Slot` and `Fill` accept a `name` string prop, where a `Slot` with a given `name` will render the `children` of any associated `Fill`s. -`Slot` accepts a `bubblesVirtually` prop which changes the event bubbling behaviour: +`Slot` accepts a `bubblesVirtually` prop which changes the method how the `Fill` children are rendered. With `bubblesVirtually`, the `Fill` is rendered using a React portal. That affects the event bubbling and React context propagation behaviour: -- By default, events will bubble to their parents on the DOM hierarchy (native event bubbling) -- If `bubblesVirtually` is set to true, events will bubble to their virtual parent in the React elements hierarchy instead. +### `bubblesVirtually=false` -`Slot` with `bubblesVirtually` set to true also accept optional `className` and `style` props to add to the slot container. +- events will bubble to their parents on the DOM hierarchy (native event bubbling) +- the React elements inside the `Fill` will be rendered with React context of the `Slot` +- renders the `Fill` elements directly, inside a `Fragment`, with no wrapper DOM element -`Slot` **without** `bubblesVirtually` accepts an optional `children` function prop, which takes `fills` as a param. It allows you to perform additional processing and wrap `fills` conditionally. +### `bubblesVirtually=true` + +- events will bubble to their virtual (React) parent in the React elements hierarchy +- the React elements inside the `Fill` will keep the React context of the `Fill` and its parents +- renders a wrapper DOM element inside which the `Fill` elements are rendered (used as an argument for React `createPortal`) + +`Slot` with `bubblesVirtually=true` renders a wrapper DOM element (a `div` by default) and accepts additional props that customize this element, like `className` or `style`. You can also replace the `div` with another element by passing an `as` prop. + +`Slot` **without** `bubblesVirtually` accepts an optional `children` prop, which is a function that receives `fills` array as a param. It allows you to perform additional processing: render a placeholder when there are no fills, or render a wrapper only when there are fills. _Example_: @@ -90,7 +99,9 @@ const Toolbar = ( { isMobile } ) => ( ); ``` -Props can also be passed from a `Slot` to a `Fill` by using the prop `fillProps` on the `Slot`: +Additional information (props) can also be passed from a `Slot` to a `Fill` by a combination of: +1. Adding a `fillProps` prop to the `Slot`. +2. Passing a function as `children` to the `Fill`. This function will receive the `fillProps` as an argument. ```jsx const { Fill, Slot } = createSlotFill( 'Toolbar' ); diff --git a/packages/components/src/slot-fill/index.tsx b/packages/components/src/slot-fill/index.tsx index 03ed33a67f13b6..caf97091b67ac8 100644 --- a/packages/components/src/slot-fill/index.tsx +++ b/packages/components/src/slot-fill/index.tsx @@ -84,17 +84,15 @@ export function createSlotFill( key: SlotKey ) { props: DistributiveOmit< SlotComponentProps, 'name' > ) => <Slot name={ key } { ...props } />; SlotComponent.displayName = `${ baseName }Slot`; + /** + * @deprecated 6.8.0 + * Please use `slotFill.name` instead of `slotFill.Slot.__unstableName`. + */ SlotComponent.__unstableName = key; return { + name: key, Fill: FillComponent, Slot: SlotComponent, }; } - -export const createPrivateSlotFill = ( name: string ) => { - const privateKey = Symbol( name ); - const privateSlotFill = createSlotFill( privateKey ); - - return { privateKey, ...privateSlotFill }; -}; diff --git a/packages/edit-site/src/components/editor-canvas-container/index.js b/packages/edit-site/src/components/editor-canvas-container/index.js index ac1083e69abd7e..050d2e19585cc4 100644 --- a/packages/edit-site/src/components/editor-canvas-container/index.js +++ b/packages/edit-site/src/components/editor-canvas-container/index.js @@ -141,7 +141,7 @@ function EditorCanvasContainer( { } function useHasEditorCanvasContainer() { - const fills = useSlotFills( EditorContentSlotFill.privateKey ); + const fills = useSlotFills( EditorContentSlotFill.name ); return !! fills?.length; } diff --git a/packages/editor/src/components/editor-interface/content-slot-fill.js b/packages/editor/src/components/editor-interface/content-slot-fill.js index 1aab394e87230f..ce1070b30da802 100644 --- a/packages/editor/src/components/editor-interface/content-slot-fill.js +++ b/packages/editor/src/components/editor-interface/content-slot-fill.js @@ -1,15 +1,10 @@ /** * WordPress dependencies */ -import { privateApis as componentsPrivateApis } from '@wordpress/components'; +import { createSlotFill } from '@wordpress/components'; -/** - * Internal dependencies - */ -import { unlock } from '../../lock-unlock'; - -const { createPrivateSlotFill } = unlock( componentsPrivateApis ); -const SLOT_FILL_NAME = 'EditCanvasContainerSlot'; -const EditorContentSlotFill = createPrivateSlotFill( SLOT_FILL_NAME ); +const EditorContentSlotFill = createSlotFill( + Symbol( 'EditCanvasContainerSlot' ) +); export default EditorContentSlotFill; From 010cf1afa2f55d4e82b7b3a77d41a39522abfe01 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Mon, 25 Nov 2024 14:43:23 +0200 Subject: [PATCH 1695/1908] DataViews: Add density option to `table` layout (#67170) Unlinked contributors: annchichi. Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: rogermattic <magdarogier@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> --- .../src/components/dataviews-context/index.ts | 2 - .../src/components/dataviews-layout/index.tsx | 2 - .../dataviews-view-config/index.tsx | 30 ++------- .../src/components/dataviews/index.tsx | 4 -- .../src/dataviews-layouts/grid/index.tsx | 10 ++- ...ity-picker.tsx => preview-size-picker.tsx} | 65 +++++++++++-------- .../dataviews/src/dataviews-layouts/index.ts | 4 ++ .../table/density-picker.tsx | 57 ++++++++++++++++ .../src/dataviews-layouts/table/index.tsx | 8 ++- .../src/dataviews-layouts/table/style.scss | 32 +++++++++ packages/dataviews/src/types.ts | 13 +++- .../src/components/page-templates/style.scss | 1 + .../src/fields/featured-image/style.scss | 7 +- 13 files changed, 168 insertions(+), 67 deletions(-) rename packages/dataviews/src/dataviews-layouts/grid/{density-picker.tsx => preview-size-picker.tsx} (56%) create mode 100644 packages/dataviews/src/dataviews-layouts/table/density-picker.tsx diff --git a/packages/dataviews/src/components/dataviews-context/index.ts b/packages/dataviews/src/components/dataviews-context/index.ts index 87acade73bc819..19f6b4178b7b55 100644 --- a/packages/dataviews/src/components/dataviews-context/index.ts +++ b/packages/dataviews/src/components/dataviews-context/index.ts @@ -28,7 +28,6 @@ type DataViewsContextType< Item > = { getItemId: ( item: Item ) => string; onClickItem: ( item: Item ) => void; isItemClickable: ( item: Item ) => boolean; - density: number; }; const DataViewsContext = createContext< DataViewsContextType< any > >( { @@ -47,7 +46,6 @@ const DataViewsContext = createContext< DataViewsContextType< any > >( { getItemId: ( item ) => item.id, onClickItem: () => {}, isItemClickable: () => false, - density: 0, } ); export default DataViewsContext; diff --git a/packages/dataviews/src/components/dataviews-layout/index.tsx b/packages/dataviews/src/components/dataviews-layout/index.tsx index 4ef0125b1f64b5..ebc251eae36a7a 100644 --- a/packages/dataviews/src/components/dataviews-layout/index.tsx +++ b/packages/dataviews/src/components/dataviews-layout/index.tsx @@ -27,7 +27,6 @@ export default function DataViewsLayout() { selection, onChangeSelection, setOpenedFilter, - density, onClickItem, isItemClickable, } = useContext( DataViewsContext ); @@ -49,7 +48,6 @@ export default function DataViewsLayout() { onClickItem={ onClickItem } isItemClickable={ isItemClickable } view={ view } - density={ density } /> ); } diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index c8b26c51275891..f13670f27cdab7 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -35,7 +35,6 @@ import { useInstanceId } from '@wordpress/compose'; */ import { SORTING_DIRECTIONS, - LAYOUT_GRID, LAYOUT_TABLE, sortIcons, sortLabels, @@ -49,7 +48,6 @@ import { import type { SupportedLayouts, View, Field } from '../../types'; import DataViewsContext from '../dataviews-context'; import { unlock } from '../../lock-unlock'; -import DensityPicker from '../../dataviews-layouts/grid/density-picker'; const { Menu } = unlock( componentsPrivateApis ); @@ -512,19 +510,15 @@ function SettingsSection( { ); } -function DataviewsViewConfigDropdown( { - density, - setDensity, -}: { - density: number; - setDensity: React.Dispatch< React.SetStateAction< number > >; -} ) { +function DataviewsViewConfigDropdown() { const { view } = useContext( DataViewsContext ); const popoverId = useInstanceId( _DataViewsViewConfig, 'dataviews-view-config-dropdown' ); - + const activeLayout = VIEW_LAYOUTS.find( + ( layout ) => layout.type === view.type + ); return ( <Dropdown popoverProps={ { @@ -551,11 +545,8 @@ function DataviewsViewConfigDropdown( { <SortFieldControl /> <SortDirectionControl /> </HStack> - { view.type === LAYOUT_GRID && ( - <DensityPicker - density={ density } - setDensity={ setDensity } - /> + { !! activeLayout?.viewConfigOptions && ( + <activeLayout.viewConfigOptions /> ) } <ItemsPerPageControl /> </SettingsSection> @@ -570,21 +561,14 @@ function DataviewsViewConfigDropdown( { } function _DataViewsViewConfig( { - density, - setDensity, defaultLayouts = { list: {}, grid: {}, table: {} }, }: { - density: number; - setDensity: React.Dispatch< React.SetStateAction< number > >; defaultLayouts?: SupportedLayouts; } ) { return ( <> <ViewTypeMenu defaultLayouts={ defaultLayouts } /> - <DataviewsViewConfigDropdown - density={ density } - setDensity={ setDensity } - /> + <DataviewsViewConfigDropdown /> </> ); } diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index 3e8224e61bc5d5..ee6073f40bf3d8 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -75,7 +75,6 @@ export default function DataViews< Item >( { header, }: DataViewsProps< Item > ) { const [ selectionState, setSelectionState ] = useState< string[] >( [] ); - const [ density, setDensity ] = useState< number >( 0 ); const isUncontrolled = selectionProperty === undefined || onChangeSelection === undefined; const selection = isUncontrolled ? selectionState : selectionProperty; @@ -119,7 +118,6 @@ export default function DataViews< Item >( { getItemId, isItemClickable, onClickItem, - density, } } > <div className="dataviews-wrapper"> @@ -151,8 +149,6 @@ export default function DataViews< Item >( { > <DataViewsViewConfig defaultLayouts={ defaultLayouts } - density={ density } - setDensity={ setDensity } /> { header } </HStack> diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx index e218172b7900aa..2a09fb68efab82 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx @@ -25,6 +25,7 @@ import { useHasAPossibleBulkAction } from '../../components/dataviews-bulk-actio import type { Action, NormalizedField, ViewGridProps } from '../../types'; import type { SetSelection } from '../../private-types'; import getClickableItemProps from '../utils/get-clickable-item-props'; +import { useUpdatedPreviewSizeOnViewportChange } from './preview-size-picker'; interface GridItemProps< Item > { selection: string[]; @@ -192,7 +193,6 @@ export default function ViewGrid< Item >( { isItemClickable, selection, view, - density, }: ViewGridProps< Item > ) { const mediaField = fields.find( ( field ) => field.id === view.layout?.mediaField @@ -223,8 +223,12 @@ export default function ViewGrid< Item >( { { visibleFields: [], badgeFields: [] } ); const hasData = !! data?.length; - const gridStyle = density - ? { gridTemplateColumns: `repeat(${ density }, minmax(0, 1fr))` } + const updatedPreviewSize = useUpdatedPreviewSizeOnViewportChange(); + const usedPreviewSize = updatedPreviewSize || view.layout?.previewSize; + const gridStyle = usedPreviewSize + ? { + gridTemplateColumns: `repeat(${ usedPreviewSize }, minmax(0, 1fr))`, + } : {}; return ( <> diff --git a/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx b/packages/dataviews/src/dataviews-layouts/grid/preview-size-picker.tsx similarity index 56% rename from packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx rename to packages/dataviews/src/dataviews-layouts/grid/preview-size-picker.tsx index 34ddf6c3fe52f3..b48c6422bd6b37 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/preview-size-picker.tsx @@ -4,7 +4,13 @@ import { RangeControl } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useViewportMatch } from '@wordpress/compose'; -import { useEffect, useMemo } from '@wordpress/element'; +import { useMemo, useContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import DataViewsContext from '../../components/dataviews-context'; +import type { ViewGrid } from '../../types'; const viewportBreaks = { xhuge: { min: 3, max: 6, default: 5 }, @@ -39,31 +45,32 @@ function useViewPortBreakpoint() { return null; } -export default function DensityPicker( { - density, - setDensity, -}: { - density: number; - setDensity: React.Dispatch< React.SetStateAction< number > >; -} ) { +export function useUpdatedPreviewSizeOnViewportChange() { + const viewport = useViewPortBreakpoint(); + const view = useContext( DataViewsContext ).view as ViewGrid; + return useMemo( () => { + const previewSize = view.layout?.previewSize; + let newPreviewSize; + if ( ! viewport || ! previewSize ) { + return; + } + const breakValues = viewportBreaks[ viewport ]; + if ( previewSize < breakValues.min ) { + newPreviewSize = breakValues.min; + } + if ( previewSize > breakValues.max ) { + newPreviewSize = breakValues.max; + } + return newPreviewSize; + }, [ viewport, view ] ); +} + +export default function PreviewSizePicker() { const viewport = useViewPortBreakpoint(); - useEffect( () => { - setDensity( ( _density ) => { - if ( ! viewport || ! _density ) { - return 0; - } - const breakValues = viewportBreaks[ viewport ]; - if ( _density < breakValues.min ) { - return breakValues.min; - } - if ( _density > breakValues.max ) { - return breakValues.max; - } - return _density; - } ); - }, [ setDensity, viewport ] ); + const context = useContext( DataViewsContext ); + const view = context.view as ViewGrid; const breakValues = viewportBreaks[ viewport || 'mobile' ]; - const densityToUse = density || breakValues.default; + const previewSizeToUse = view.layout?.previewSize || breakValues.default; const marks = useMemo( () => @@ -88,13 +95,19 @@ export default function DensityPicker( { __next40pxDefaultSize showTooltip={ false } label={ __( 'Preview size' ) } - value={ breakValues.max + breakValues.min - densityToUse } + value={ breakValues.max + breakValues.min - previewSizeToUse } marks={ marks } min={ breakValues.min } max={ breakValues.max } withInputField={ false } onChange={ ( value = 0 ) => { - setDensity( breakValues.max + breakValues.min - value ); + context.onChangeView( { + ...view, + layout: { + ...view.layout, + previewSize: breakValues.max + breakValues.min - value, + }, + } ); } } step={ 1 } /> diff --git a/packages/dataviews/src/dataviews-layouts/index.ts b/packages/dataviews/src/dataviews-layouts/index.ts index eece17d0f4f10c..7abdd1eb459328 100644 --- a/packages/dataviews/src/dataviews-layouts/index.ts +++ b/packages/dataviews/src/dataviews-layouts/index.ts @@ -17,6 +17,8 @@ import ViewGrid from './grid'; import ViewList from './list'; import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../constants'; import type { View, Field } from '../types'; +import PreviewSizePicker from './grid/preview-size-picker'; +import DensityPicker from './table/density-picker'; export const VIEW_LAYOUTS = [ { @@ -24,12 +26,14 @@ export const VIEW_LAYOUTS = [ label: __( 'Table' ), component: ViewTable, icon: blockTable, + viewConfigOptions: DensityPicker, }, { type: LAYOUT_GRID, label: __( 'Grid' ), component: ViewGrid, icon: category, + viewConfigOptions: PreviewSizePicker, }, { type: LAYOUT_LIST, diff --git a/packages/dataviews/src/dataviews-layouts/table/density-picker.tsx b/packages/dataviews/src/dataviews-layouts/table/density-picker.tsx new file mode 100644 index 00000000000000..6d3d31aeb7345e --- /dev/null +++ b/packages/dataviews/src/dataviews-layouts/table/density-picker.tsx @@ -0,0 +1,57 @@ +/** + * WordPress dependencies + */ +import { + __experimentalToggleGroupControl as ToggleGroupControl, + __experimentalToggleGroupControlOption as ToggleGroupControlOption, +} from '@wordpress/components'; +import { __, _x } from '@wordpress/i18n'; +import { useContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import DataViewsContext from '../../components/dataviews-context'; +import type { ViewTable, Density } from '../../types'; + +export default function DensityPicker() { + const context = useContext( DataViewsContext ); + const view = context.view as ViewTable; + return ( + <ToggleGroupControl + __nextHasNoMarginBottom + size="__unstable-large" + label={ __( 'Density' ) } + value={ view.layout?.density || 'balanced' } + onChange={ ( value ) => { + context.onChangeView( { + ...view, + layout: { + ...view.layout, + density: value as Density, + }, + } ); + } } + isBlock + > + <ToggleGroupControlOption + key="comfortable" + value="comfortable" + label={ _x( + 'Comfortable', + 'Density option for DataView layout' + ) } + /> + <ToggleGroupControlOption + key="balanced" + value="balanced" + label={ _x( 'Balanced', 'Density option for DataView layout' ) } + /> + <ToggleGroupControlOption + key="compact" + value="compact" + label={ _x( 'Compact', 'Density option for DataView layout' ) } + /> + </ToggleGroupControl> + ); +} diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index db76d24b53bfa3..7f93a4c14a7ddc 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -332,7 +332,13 @@ function ViewTable< Item >( { return ( <> <table - className="dataviews-view-table" + className={ clsx( 'dataviews-view-table', { + [ `has-${ view.layout?.density }-density` ]: + view.layout?.density && + [ 'compact', 'comfortable' ].includes( + view.layout.density + ), + } ) } aria-busy={ isLoading } aria-describedby={ tableNoticeId } > diff --git a/packages/dataviews/src/dataviews-layouts/table/style.scss b/packages/dataviews/src/dataviews-layouts/table/style.scss index ea2c614e4339df..3bbb045c73a9d9 100644 --- a/packages/dataviews/src/dataviews-layouts/table/style.scss +++ b/packages/dataviews/src/dataviews-layouts/table/style.scss @@ -169,6 +169,38 @@ opacity: 1; } } + + // Density style overrides. + &.has-compact-density { + thead { + th { + &:has(.dataviews-view-table-header-button):not(:first-child) { + padding-left: 0; + } + } + } + td, + th { + padding: $grid-unit-05 $grid-unit-10; + } + } + + &.has-comfortable-density { + td, + th { + padding: $grid-unit-20 $grid-unit-15; + } + } + + &.has-compact-density, + &.has-comfortable-density { + td, + th { + &.dataviews-view-table__checkbox-column { + padding-right: 0; + } + } + } } /* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 8c4276f2541ecc..861dc53404f914 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -329,6 +329,8 @@ export interface ColumnStyle { minWidth?: string | number; } +export type Density = 'compact' | 'balanced' | 'comfortable'; + export interface ViewTable extends ViewBase { type: 'table'; @@ -347,6 +349,11 @@ export interface ViewTable extends ViewBase { * The styles for the columns. */ styles?: Record< string, ColumnStyle >; + + /** + * The density of the view. + */ + density?: Density; }; } @@ -389,6 +396,11 @@ export interface ViewGrid extends ViewBase { * The fields to use as badge fields. */ badgeFields?: string[]; + + /** + * The preview size of the grid. + */ + previewSize?: number; }; } @@ -501,7 +513,6 @@ export interface ViewBaseProps< Item > { onClickItem: ( item: Item ) => void; isItemClickable: ( item: Item ) => boolean; view: View; - density: number; } export interface ViewTableProps< Item > extends ViewBaseProps< Item > { diff --git a/packages/edit-site/src/components/page-templates/style.scss b/packages/edit-site/src/components/page-templates/style.scss index 6a753921f6f40a..4432cf6bec4923 100644 --- a/packages/edit-site/src/components/page-templates/style.scss +++ b/packages/edit-site/src/components/page-templates/style.scss @@ -60,6 +60,7 @@ .dataviews-view-table & { margin-bottom: $grid-unit-10; + display: block; } } diff --git a/packages/fields/src/fields/featured-image/style.scss b/packages/fields/src/fields/featured-image/style.scss index 46d37960199ead..918f69172f3023 100644 --- a/packages/fields/src/fields/featured-image/style.scss +++ b/packages/fields/src/fields/featured-image/style.scss @@ -83,13 +83,10 @@ fieldset.fields-controls__featured-image { } .dataviews-view-table__cell-content-wrapper { - .fields-controls__featured-image-image { - width: 32px; - height: 32px; - } - + .fields-controls__featured-image-image, .fields-controls__featured-image-placeholder { width: 32px; height: 32px; + display: block; } } From 29f0c351dfe87241c026829d1774db6216aa04cd Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 25 Nov 2024 23:40:50 +0900 Subject: [PATCH 1696/1908] Storybook: Restore stable components back into categories (#67216) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/custom-select-control/stories/index.story.tsx | 3 ++- packages/components/src/dropdown-menu/stories/index.story.tsx | 3 ++- packages/components/src/menu-group/stories/index.story.tsx | 3 ++- packages/components/src/menu-item/stories/index.story.tsx | 3 ++- .../components/src/menu-items-choice/stories/index.story.tsx | 3 ++- packages/components/src/text-control/stories/index.story.tsx | 3 ++- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/components/src/custom-select-control/stories/index.story.tsx b/packages/components/src/custom-select-control/stories/index.story.tsx index 836fc540c6d1ed..7c743de58d202d 100644 --- a/packages/components/src/custom-select-control/stories/index.story.tsx +++ b/packages/components/src/custom-select-control/stories/index.story.tsx @@ -14,8 +14,9 @@ import { useState } from '@wordpress/element'; import CustomSelectControl from '..'; const meta: Meta< typeof CustomSelectControl > = { - title: 'Components/CustomSelectControl', + title: 'Components/Selection & Input/Common/CustomSelectControl', component: CustomSelectControl, + id: 'components-customselectcontrol', argTypes: { onChange: { control: { type: null } }, value: { control: { type: null } }, diff --git a/packages/components/src/dropdown-menu/stories/index.story.tsx b/packages/components/src/dropdown-menu/stories/index.story.tsx index dd4907bd0b96b1..8c13a0b57dbda6 100644 --- a/packages/components/src/dropdown-menu/stories/index.story.tsx +++ b/packages/components/src/dropdown-menu/stories/index.story.tsx @@ -23,8 +23,9 @@ import { } from '@wordpress/icons'; const meta: Meta< typeof DropdownMenu > = { - title: 'Components/DropdownMenu', + title: 'Components/Actions/DropdownMenu', component: DropdownMenu, + id: 'components-dropdownmenu', parameters: { actions: { argTypesRegex: '^on.*' }, controls: { expanded: true }, diff --git a/packages/components/src/menu-group/stories/index.story.tsx b/packages/components/src/menu-group/stories/index.story.tsx index 7cb9004b45a8c2..f53cbbf5b7b0a0 100644 --- a/packages/components/src/menu-group/stories/index.story.tsx +++ b/packages/components/src/menu-group/stories/index.story.tsx @@ -16,8 +16,9 @@ import MenuItemsChoice from '../../menu-items-choice'; import type { Meta, StoryFn } from '@storybook/react'; const meta: Meta< typeof MenuGroup > = { - title: 'Components/MenuGroup', + title: 'Components/Actions/MenuGroup', component: MenuGroup, + id: 'components-menugroup', argTypes: { children: { control: { type: null } }, }, diff --git a/packages/components/src/menu-item/stories/index.story.tsx b/packages/components/src/menu-item/stories/index.story.tsx index 763ee6e96be922..24c592b66f3aea 100644 --- a/packages/components/src/menu-item/stories/index.story.tsx +++ b/packages/components/src/menu-item/stories/index.story.tsx @@ -17,7 +17,8 @@ import Shortcut from '../../shortcut'; const meta: Meta< typeof MenuItem > = { component: MenuItem, - title: 'Components/MenuItem', + title: 'Components/Actions/MenuItem', + id: 'components-menuitem', argTypes: { children: { control: { type: null } }, icon: { diff --git a/packages/components/src/menu-items-choice/stories/index.story.tsx b/packages/components/src/menu-items-choice/stories/index.story.tsx index 02e76158981e8e..f4a14054e8f27f 100644 --- a/packages/components/src/menu-items-choice/stories/index.story.tsx +++ b/packages/components/src/menu-items-choice/stories/index.story.tsx @@ -16,7 +16,8 @@ import MenuGroup from '../../menu-group'; const meta: Meta< typeof MenuItemsChoice > = { component: MenuItemsChoice, - title: 'Components/MenuItemsChoice', + title: 'Components/Actions/MenuItemsChoice', + id: 'components-menuitemschoice', argTypes: { onHover: { action: 'onHover' }, onSelect: { action: 'onSelect' }, diff --git a/packages/components/src/text-control/stories/index.story.tsx b/packages/components/src/text-control/stories/index.story.tsx index 948eca84a634c7..481ae714f0ce2f 100644 --- a/packages/components/src/text-control/stories/index.story.tsx +++ b/packages/components/src/text-control/stories/index.story.tsx @@ -15,7 +15,8 @@ import TextControl from '..'; const meta: Meta< typeof TextControl > = { component: TextControl, - title: 'Components/TextControl', + title: 'Components/Selection & Input/Common/TextControl', + id: 'components-textcontrol', argTypes: { help: { control: { type: 'text' } }, label: { control: { type: 'text' } }, From dfc716aa09172d8abb493f7047f9baa581ba38fc Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 25 Nov 2024 23:43:12 +0900 Subject: [PATCH 1697/1908] GradientPicker: Auto-generate readme (#67250) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../components/src/gradient-picker/README.md | 176 +++++++++++------- .../src/gradient-picker/docs-manifest.json | 5 + .../components/src/gradient-picker/index.tsx | 64 +++---- .../components/src/gradient-picker/types.ts | 8 +- 4 files changed, 147 insertions(+), 106 deletions(-) create mode 100644 packages/components/src/gradient-picker/docs-manifest.json diff --git a/packages/components/src/gradient-picker/README.md b/packages/components/src/gradient-picker/README.md index 815b3d8eb5dd75..a8ee9d990c5c2a 100644 --- a/packages/components/src/gradient-picker/README.md +++ b/packages/components/src/gradient-picker/README.md @@ -1,110 +1,148 @@ # GradientPicker -GradientPicker is a React component that renders a color gradient picker to define a multi step gradient. There's either a _linear_ or a _radial_ type available. +<!-- This file is generated automatically and cannot be edited directly. Make edits via TypeScript types and TSDocs. --> -![gradient-picker](https://user-images.githubusercontent.com/881729/147505438-3818c4c7-65b5-4394-b97b-af903c62adce.png) +<p class="callout callout-info">See the <a href="https://wordpress.github.io/gutenberg/?path=/docs/components-gradientpicker--docs">WordPress Storybook</a> for more detailed, interactive documentation.</p> -## Usage - -Render a GradientPicker. +GradientPicker is a React component that renders a color gradient picker to +define a multi step gradient. There's either a _linear_ or a _radial_ type +available. ```jsx import { useState } from 'react'; import { GradientPicker } from '@wordpress/components'; -const myGradientPicker = () => { - const [ gradient, setGradient ] = useState( null ); - - return ( - <GradientPicker - value={ gradient } - onChange={ ( currentGradient ) => setGradient( currentGradient ) } - gradients={ [ - { - name: 'JShine', - gradient: - 'linear-gradient(135deg,#12c2e9 0%,#c471ed 50%,#f64f59 100%)', - slug: 'jshine', - }, - { - name: 'Moonlit Asteroid', - gradient: - 'linear-gradient(135deg,#0F2027 0%, #203A43 0%, #2c5364 100%)', - slug: 'moonlit-asteroid', - }, - { - name: 'Rastafarie', - gradient: - 'linear-gradient(135deg,#1E9600 0%, #FFF200 0%, #FF0000 100%)', - slug: 'rastafari', - }, - ] } - /> - ); +const MyGradientPicker = () => { + const [ gradient, setGradient ] = useState( null ); + + return ( + <GradientPicker + value={ gradient } + onChange={ ( currentGradient ) => setGradient( currentGradient ) } + gradients={ [ + { + name: 'JShine', + gradient: + 'linear-gradient(135deg,#12c2e9 0%,#c471ed 50%,#f64f59 100%)', + slug: 'jshine', + }, + { + name: 'Moonlit Asteroid', + gradient: + 'linear-gradient(135deg,#0F2027 0%, #203A43 0%, #2c5364 100%)', + slug: 'moonlit-asteroid', + }, + { + name: 'Rastafarie', + gradient: + 'linear-gradient(135deg,#1E9600 0%, #FFF200 0%, #FF0000 100%)', + slug: 'rastafari', + }, + ] } + /> + ); }; ``` - ## Props -The component accepts the following props: +### `__experimentalIsRenderedInSidebar` -### `className`: `string` +Whether this is rendered in the sidebar. -The class name added to the wrapper. + - Type: `boolean` + - Required: No + - Default: `false` -- Required: No +### `asButtons` -### `value`: `string` +Whether the control should present as a set of buttons, +each with its own tab stop. -The current value of the gradient. Pass a css gradient like `linear-gradient(90deg, rgb(6, 147, 227) 0%, rgb(155, 81, 224) 100%)`. Optionally pass in a `null` value to specify no gradient is currently selected. + - Type: `boolean` + - Required: No + - Default: `false` -- Required: No -- Default: `linear-gradient(90deg, rgb(6, 147, 227) 0%, rgb(155, 81, 224) 100%)` +### `aria-label` -### `onChange`: `( currentGradient: string | undefined ) => void` +A label to identify the purpose of the control. -The function called when a new gradient has been defined. It is passed the `currentGradient` as an argument. + - Type: `string` + - Required: No -- Required: Yes +### `aria-labelledby` -### `gradients`: `GradientsProp[]` +An ID of an element to provide a label for the control. -An array of objects of predefined gradients displayed above the gradient selector. + - Type: `string` + - Required: No + +### `className` + +The class name added to the wrapper. -- Required: No -- Default: `[]` + - Type: `string` + - Required: No -### `clearable`: `boolean` +### `clearable` Whether the palette should have a clearing button or not. -- Required: No -- Default: true + - Type: `boolean` + - Required: No + - Default: `true` + +### `disableCustomGradients` + +If true, the gradient picker will not be displayed and only defined +gradients from `gradients` will be shown. + + - Type: `boolean` + - Required: No + - Default: `false` + +### `gradients` + +An array of objects as predefined gradients displayed above the gradient +selector. Alternatively, if there are multiple sets (or 'origins') of +gradients, you can pass an array of objects each with a `name` and a +`gradients` array which will in turn contain the predefined gradient objects. + + - Type: `GradientsProp` + - Required: No + - Default: `[]` -### `disableCustomGradients`: `boolean` +### `headingLevel` -If true, the gradient picker will not be displayed and only defined gradients from `gradients` are available. +The heading level. Only applies in cases where gradients are provided +from multiple origins (i.e. when the array passed as the `gradients` prop +contains two or more items). -- Required: No -- Default: false + - Type: `1 | 2 | 3 | 4 | 5 | 6 | "1" | "2" | "3" | "4" | ...` + - Required: No + - Default: `2` -### `headingLevel`: `1 | 2 | 3 | 4 | 5 | 6 | '1' | '2' | '3' | '4' | '5' | '6'` +### `loop` -The heading level. Only applies in cases where gradients are provided from multiple origins (ie. when the array passed as the `gradients` prop contains two or more items). +Prevents keyboard interaction from wrapping around. +Only used when `asButtons` is not true. -- Required: No -- Default: `2` + - Type: `boolean` + - Required: No + - Default: `true` -### `asButtons`: `boolean` +### `onChange` -Whether the control should present as a set of buttons, each with its own tab stop. +The function called when a new gradient has been defined. It is passed to +the `currentGradient` as an argument. -- Required: No -- Default: `false` + - Type: `(currentGradient: string) => void` + - Required: Yes -### `loop`: `boolean` +### `value` -Prevents keyboard interaction from wrapping around. Only used when `asButtons` is not true. +The current value of the gradient. Pass a css gradient string (See default value for example). +Optionally pass in a `null` value to specify no gradient is currently selected. -- Required: No -- Default: `true` + - Type: `string` + - Required: No + - Default: `'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)'` diff --git a/packages/components/src/gradient-picker/docs-manifest.json b/packages/components/src/gradient-picker/docs-manifest.json new file mode 100644 index 00000000000000..6bea56ccc678c6 --- /dev/null +++ b/packages/components/src/gradient-picker/docs-manifest.json @@ -0,0 +1,5 @@ +{ + "$schema": "../../schemas/docs-manifest.json", + "displayName": "GradientPicker", + "filePath": "./index.tsx" +} diff --git a/packages/components/src/gradient-picker/index.tsx b/packages/components/src/gradient-picker/index.tsx index f0607badd1b03a..124a89c7e016e1 100644 --- a/packages/components/src/gradient-picker/index.tsx +++ b/packages/components/src/gradient-picker/index.tsx @@ -166,44 +166,44 @@ function Component( props: PickerProps< any > ) { } /** - * GradientPicker is a React component that renders a color gradient picker to + * GradientPicker is a React component that renders a color gradient picker to * define a multi step gradient. There's either a _linear_ or a _radial_ type * available. * * ```jsx - *import { GradientPicker } from '@wordpress/components'; - *import { useState } from '@wordpress/element'; + * import { useState } from 'react'; + * import { GradientPicker } from '@wordpress/components'; * - *const myGradientPicker = () => { - * const [ gradient, setGradient ] = useState( null ); + * const MyGradientPicker = () => { + * const [ gradient, setGradient ] = useState( null ); * - * return ( - * <GradientPicker - * value={ gradient } - * onChange={ ( currentGradient ) => setGradient( currentGradient ) } - * gradients={ [ - * { - * name: 'JShine', - * gradient: - * 'linear-gradient(135deg,#12c2e9 0%,#c471ed 50%,#f64f59 100%)', - * slug: 'jshine', - * }, - * { - * name: 'Moonlit Asteroid', - * gradient: - * 'linear-gradient(135deg,#0F2027 0%, #203A43 0%, #2c5364 100%)', - * slug: 'moonlit-asteroid', - * }, - * { - * name: 'Rastafarie', - * gradient: - * 'linear-gradient(135deg,#1E9600 0%, #FFF200 0%, #FF0000 100%)', - * slug: 'rastafari', - * }, - * ] } - * /> - * ); - *}; + * return ( + * <GradientPicker + * value={ gradient } + * onChange={ ( currentGradient ) => setGradient( currentGradient ) } + * gradients={ [ + * { + * name: 'JShine', + * gradient: + * 'linear-gradient(135deg,#12c2e9 0%,#c471ed 50%,#f64f59 100%)', + * slug: 'jshine', + * }, + * { + * name: 'Moonlit Asteroid', + * gradient: + * 'linear-gradient(135deg,#0F2027 0%, #203A43 0%, #2c5364 100%)', + * slug: 'moonlit-asteroid', + * }, + * { + * name: 'Rastafarie', + * gradient: + * 'linear-gradient(135deg,#1E9600 0%, #FFF200 0%, #FF0000 100%)', + * slug: 'rastafari', + * }, + * ] } + * /> + * ); + * }; *``` * */ diff --git a/packages/components/src/gradient-picker/types.ts b/packages/components/src/gradient-picker/types.ts index b563653e33e4c4..8ac2c6de9f2cf3 100644 --- a/packages/components/src/gradient-picker/types.ts +++ b/packages/components/src/gradient-picker/types.ts @@ -36,7 +36,7 @@ type GradientPickerBaseProps = { clearable?: boolean; /** * The heading level. Only applies in cases where gradients are provided - * from multiple origins (ie. when the array passed as the `gradients` prop + * from multiple origins (i.e. when the array passed as the `gradients` prop * contains two or more items). * * @default 2 @@ -58,19 +58,17 @@ type GradientPickerBaseProps = { loop?: boolean; } & ( | { + // TODO: [#54055] Either this or `aria-labelledby` should be required /** * A label to identify the purpose of the control. - * - * @todo [#54055] Either this or `aria-labelledby` should be required */ 'aria-label'?: string; 'aria-labelledby'?: never; } | { + // TODO: [#54055] Either this or `aria-label` should be required /** * An ID of an element to provide a label for the control. - * - * @todo [#54055] Either this or `aria-label` should be required */ 'aria-labelledby'?: string; 'aria-label'?: never; From e27e5e446a2ba68f3e06963c9e68c9521580cebc Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Mon, 25 Nov 2024 23:56:29 +0900 Subject: [PATCH 1698/1908] Autocomplete: Increase option height (#67214) * Autocomplete: Increase option height * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/autocomplete/autocompleter-ui.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index bcb9bfe3c013e4..29e746c905f8d4 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -26,6 +26,7 @@ ### Enhancements - `ColorPicker`: Update sizes of color format select and copy button ([#67093](https://github.com/WordPress/gutenberg/pull/67093)). +- `Autocomplete`: Increase option height ([#67214](https://github.com/WordPress/gutenberg/pull/67214)). ### Experimental diff --git a/packages/components/src/autocomplete/autocompleter-ui.tsx b/packages/components/src/autocomplete/autocompleter-ui.tsx index 69105f6c9d3b44..dbbbe724113d7c 100644 --- a/packages/components/src/autocomplete/autocompleter-ui.tsx +++ b/packages/components/src/autocomplete/autocompleter-ui.tsx @@ -57,6 +57,7 @@ function ListBox( { key={ option.key } id={ `components-autocomplete-item-${ instanceId }-${ option.key }` } role="option" + __next40pxDefaultSize aria-selected={ index === selectedIndex } accessibleWhenDisabled disabled={ option.isDisabled } From b76d9f0311019c7d866ce1d9db92140e483887bd Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:12:44 +0100 Subject: [PATCH 1699/1908] Rich text: preserve comments (#62128) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: lysyjan <lysyjan87@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: RolfKyburz <rkyburz@git.wordpress.org> Co-authored-by: strarsis <strarsis@git.wordpress.org> Co-authored-by: danielbachhuber <danielbachhuber@git.wordpress.org> --- .../src/components/rich-text/content.scss | 19 +++++-- packages/rich-text/src/create.js | 28 ++++++++++ .../src/test/__snapshots__/to-dom.js.snap | 30 +++++++++++ packages/rich-text/src/test/helpers/index.js | 52 +++++++++++++++++++ packages/rich-text/src/to-dom.js | 12 +++-- packages/rich-text/src/to-html-string.js | 9 ++++ packages/rich-text/src/to-tree.js | 15 +++++- 7 files changed, 157 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/rich-text/content.scss b/packages/block-editor/src/components/rich-text/content.scss index 28dcd931a7f5db..67e14b0882d7ef 100644 --- a/packages/block-editor/src/components/rich-text/content.scss +++ b/packages/block-editor/src/components/rich-text/content.scss @@ -13,10 +13,6 @@ &:focus { // Removes outline added by the browser. outline: none; - - [data-rich-text-format-boundary] { - border-radius: $radius-small; - } } } @@ -34,3 +30,18 @@ figcaption.block-editor-rich-text__editable [data-rich-text-placeholder]::before background: rgb(255, 255, 0); } } + +[data-rich-text-comment], +[data-rich-text-format-boundary] { + border-radius: $radius-small; +} + +[data-rich-text-comment] { + background-color: currentColor; + + span { + filter: invert(100%); + color: currentColor; + padding: 0 2px; + } +} diff --git a/packages/rich-text/src/create.js b/packages/rich-text/src/create.js index 898bdfa73b330e..d683836d9e2fa8 100644 --- a/packages/rich-text/src/create.js +++ b/packages/rich-text/src/create.js @@ -469,6 +469,34 @@ function createFromElement( { element, range, isEditableTree } ) { continue; } + if ( + node.nodeType === node.COMMENT_NODE || + ( node.nodeType === node.ELEMENT_NODE && + node.tagName === 'SPAN' && + node.hasAttribute( 'data-rich-text-comment' ) ) + ) { + const value = { + formats: [ , ], + replacements: [ + { + type: '#comment', + attributes: { + 'data-rich-text-comment': + node.nodeType === node.COMMENT_NODE + ? node.nodeValue + : node.getAttribute( + 'data-rich-text-comment' + ), + }, + }, + ], + text: OBJECT_REPLACEMENT_CHARACTER, + }; + accumulateSelection( accumulator, node, range, value ); + mergePair( accumulator, value ); + continue; + } + if ( node.nodeType !== node.ELEMENT_NODE ) { continue; } diff --git a/packages/rich-text/src/test/__snapshots__/to-dom.js.snap b/packages/rich-text/src/test/__snapshots__/to-dom.js.snap index 0daf48aa9a1c36..0e2ac57bea3704 100644 --- a/packages/rich-text/src/test/__snapshots__/to-dom.js.snap +++ b/packages/rich-text/src/test/__snapshots__/to-dom.js.snap @@ -272,6 +272,21 @@ exports[`recordToDom should not error with overlapping formats (2) 1`] = ` </body> `; +exports[`recordToDom should preserve comments 1`] = ` +<body> + + <span + contenteditable="false" + data-rich-text-comment="comment" + > + <span> + comment + </span> + </span> + +</body> +`; + exports[`recordToDom should preserve emoji 1`] = ` <body> 🍒 @@ -289,6 +304,21 @@ exports[`recordToDom should preserve emoji in formatting 1`] = ` </body> `; +exports[`recordToDom should preserve funky comments 1`] = ` +<body> + + <span + contenteditable="false" + data-rich-text-comment="/funky" + > + <span> + /funky + </span> + </span> + +</body> +`; + exports[`recordToDom should preserve non breaking space 1`] = ` <body> test  test diff --git a/packages/rich-text/src/test/helpers/index.js b/packages/rich-text/src/test/helpers/index.js index f246ab956db3a7..7658ede7e37737 100644 --- a/packages/rich-text/src/test/helpers/index.js +++ b/packages/rich-text/src/test/helpers/index.js @@ -551,6 +551,58 @@ export const spec = [ text: '\ufffc', }, }, + { + description: 'should preserve comments', + html: '<!--comment-->', + createRange: ( element ) => ( { + startOffset: 0, + startContainer: element, + endOffset: 1, + endContainer: element, + } ), + startPath: [ 0, 0 ], + endPath: [ 2, 0 ], + record: { + start: 0, + end: 1, + formats: [ , ], + replacements: [ + { + attributes: { + 'data-rich-text-comment': 'comment', + }, + type: '#comment', + }, + ], + text: '\ufffc', + }, + }, + { + description: 'should preserve funky comments', + html: '<//funky>', + createRange: ( element ) => ( { + startOffset: 0, + startContainer: element, + endOffset: 1, + endContainer: element, + } ), + startPath: [ 0, 0 ], + endPath: [ 2, 0 ], + record: { + start: 0, + end: 1, + formats: [ , ], + replacements: [ + { + attributes: { + 'data-rich-text-comment': '/funky', + }, + type: '#comment', + }, + ], + text: '\ufffc', + }, + }, ]; export const specWithRegistration = [ diff --git a/packages/rich-text/src/to-dom.js b/packages/rich-text/src/to-dom.js index e7288e4ba16332..ac8308c7274b58 100644 --- a/packages/rich-text/src/to-dom.js +++ b/packages/rich-text/src/to-dom.js @@ -68,10 +68,16 @@ function append( element, child ) { const { type, attributes } = child; if ( type ) { - child = element.ownerDocument.createElement( type ); + if ( type === '#comment' ) { + child = element.ownerDocument.createComment( + attributes[ 'data-rich-text-comment' ] + ); + } else { + child = element.ownerDocument.createElement( type ); - for ( const key in attributes ) { - child.setAttribute( key, attributes[ key ] ); + for ( const key in attributes ) { + child.setAttribute( key, attributes[ key ] ); + } } } diff --git a/packages/rich-text/src/to-html-string.js b/packages/rich-text/src/to-html-string.js index f770dfdefc128a..a4c12b4c47f00d 100644 --- a/packages/rich-text/src/to-html-string.js +++ b/packages/rich-text/src/to-html-string.js @@ -88,6 +88,15 @@ function remove( object ) { } function createElementHTML( { type, attributes, object, children } ) { + if ( type === '#comment' ) { + // We can't restore the original comment delimiters, because once parsed + // into DOM nodes, we don't have the information. But in the future we + // could allow comment handlers to specify custom delimiters, for + // example `</{comment-content}>` for Bits, where `comment-content` + // would be `/{bit-name}` or `__{translatable-string}` (TBD). + return `<!--${ attributes[ 'data-rich-text-comment' ] }-->`; + } + let attributeString = ''; for ( const key in attributes ) { diff --git a/packages/rich-text/src/to-tree.js b/packages/rich-text/src/to-tree.js index 46671c951bc09d..0e3caad4f70c83 100644 --- a/packages/rich-text/src/to-tree.js +++ b/packages/rich-text/src/to-tree.js @@ -229,7 +229,20 @@ export function toTree( { const { type, attributes, innerHTML } = replacement; const formatType = getFormatType( type ); - if ( ! isEditableTree && type === 'script' ) { + if ( isEditableTree && type === '#comment' ) { + pointer = append( getParent( pointer ), { + type: 'span', + attributes: { + contenteditable: 'false', + 'data-rich-text-comment': + attributes[ 'data-rich-text-comment' ], + }, + } ); + append( + append( pointer, { type: 'span' } ), + attributes[ 'data-rich-text-comment' ].trim() + ); + } else if ( ! isEditableTree && type === 'script' ) { pointer = append( getParent( pointer ), fromFormat( { From 2215a045c3e3fb9c1bd65abbf1c2a53b2887c513 Mon Sep 17 00:00:00 2001 From: Alex Lende <alex+github.com@lende.xyz> Date: Mon, 25 Nov 2024 11:20:06 -0600 Subject: [PATCH 1700/1908] Zoom in/out to correct location (#67126) Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: priethor <priethor@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- .../src/components/iframe/content.scss | 19 +- .../src/components/iframe/index.js | 231 ++++++++++++++---- test/e2e/specs/site-editor/zoom-out.spec.js | 168 +++++++++++++ 3 files changed, 371 insertions(+), 47 deletions(-) diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss index 596c177eab2f32..5e390800719949 100644 --- a/packages/block-editor/src/components/iframe/content.scss +++ b/packages/block-editor/src/components/iframe/content.scss @@ -7,13 +7,26 @@ // We don't want to animate the transform of the translateX because it is used // to "center" the canvas. Leaving it on causes the canvas to slide around in // odd ways. - @include editor-canvas-resize-animation(transform 0s, scale 0s, padding 0s); + @include editor-canvas-resize-animation( transform 0s, scale 0s, padding 0s, translate 0s); &.zoom-out-animation { - // we only want to animate the scaling when entering zoom out. When sidebars + $scroll-top: var(--wp-block-editor-iframe-zoom-out-scroll-top, 0); + $scroll-top-next: var(--wp-block-editor-iframe-zoom-out-scroll-top-next, 0); + + position: fixed; + left: 0; + right: 0; + top: calc(-1 * #{$scroll-top}); + bottom: 0; + translate: 0 calc(#{$scroll-top} - #{$scroll-top-next}); + // Force preserving a scrollbar gutter as scrollbar-gutter isn't supported in all browsers yet, + // and removing the scrollbar causes the content to shift. + overflow-y: scroll; + + // We only want to animate the scaling when entering zoom out. When sidebars // are toggled, the resizing of the iframe handles scaling the canvas as well, // and the doubled animations cause very odd animations. - @include editor-canvas-resize-animation(transform 0s); + @include editor-canvas-resize-animation( transform 0s, top 0s, bottom 0s, right 0s, left 0s ); } } diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index 76d2e09dfb7a30..f8b7c25084e38d 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -20,6 +20,7 @@ import { useMergeRefs, useRefEffect, useDisabled, + useReducedMotion, } from '@wordpress/compose'; import { __experimentalStyleProvider as StyleProvider } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; @@ -121,6 +122,7 @@ function Iframe( { }; }, [] ); const { styles = '', scripts = '' } = resolvedAssets; + /** @type {[Document, import('react').Dispatch<Document>]} */ const [ iframeDocument, setIframeDocument ] = useState(); const initialContainerWidthRef = useRef( 0 ); const [ bodyClasses, setBodyClasses ] = useState( [] ); @@ -130,6 +132,7 @@ function Iframe( { useResizeObserver(); const [ containerResizeListener, { width: containerWidth } ] = useResizeObserver(); + const prefersReducedMotion = useReducedMotion(); const setRef = useRefEffect( ( node ) => { node._load = () => { @@ -268,6 +271,19 @@ function Iframe( { containerWidth ); + const frameSizeValue = parseInt( frameSize ); + + const maxWidth = 750; + const scaleValue = + scale === 'auto-scaled' + ? ( Math.min( containerWidth, maxWidth ) - frameSizeValue * 2 ) / + scaleContainerWidth + : scale; + + const prevScaleRef = useRef( scaleValue ); + const prevFrameSizeRef = useRef( frameSizeValue ); + const prevClientHeightRef = useRef( /* Initialized in the useEffect. */ ); + const disabledRef = useDisabled( { isDisabled: ! readonly } ); const bodyRef = useMergeRefs( [ useBubbleEvents( iframeDocument ), @@ -320,47 +336,176 @@ function Iframe( { useEffect( () => cleanup, [ cleanup ] ); - const zoomOutAnimationClassnameRef = useRef( null ); - - // Toggle zoom out CSS Classes only when zoom out mode changes. We could add these into the useEffect - // that controls settings the CSS variables, but then we would need to do more work to ensure we're - // only toggling these when the zoom out mode changes, as that useEffect is also triggered by a large - // number of dependencies. useEffect( () => { - if ( ! iframeDocument || ! isZoomedOut ) { + if ( + ! iframeDocument || + // HACK: Checking if isZoomedOut differs from prevIsZoomedOut here + // instead of the dependency array to appease the linter. + ( scaleValue === 1 ) === ( prevScaleRef.current === 1 ) + ) { return; } - const handleZoomOutAnimationClassname = () => { - clearTimeout( zoomOutAnimationClassnameRef.current ); + // Unscaled height of the current iframe container. + const clientHeight = iframeDocument.documentElement.clientHeight; + + // Scaled height of the current iframe content. + const scrollHeight = iframeDocument.documentElement.scrollHeight; + + // Previous scale value. + const prevScale = prevScaleRef.current; + + // Unscaled size of the previous padding around the iframe content. + const prevFrameSize = prevFrameSizeRef.current; + + // Unscaled height of the previous iframe container. + const prevClientHeight = prevClientHeightRef.current ?? clientHeight; + + // We can't trust the set value from contentHeight, as it was measured + // before the zoom out mode was changed. After zoom out mode is changed, + // appenders may appear or disappear, so we need to get the height from + // the iframe at this point when we're about to animate the zoom out. + // The iframe scrollTop, scrollHeight, and clientHeight will all be + // accurate. The client height also does change when the zoom out mode + // is toggled, as the bottom bar about selecting the template is + // added/removed when toggling zoom out mode. + const scrollTop = iframeDocument.documentElement.scrollTop; + + // Step 0: Start with the current scrollTop. + let scrollTopNext = scrollTop; + + // Step 1: Undo the effects of the previous scale and frame around the + // midpoint of the visible area. + scrollTopNext = + ( scrollTopNext + prevClientHeight / 2 - prevFrameSize ) / + prevScale - + prevClientHeight / 2; + + // Step 2: Apply the new scale and frame around the midpoint of the + // visible area. + scrollTopNext = + ( scrollTopNext + clientHeight / 2 ) * scaleValue + + frameSizeValue - + clientHeight / 2; + + // Step 3: Handle an edge case so that you scroll to the top of the + // iframe if the top of the iframe content is visible in the container. + // The same edge case for the bottom is skipped because changing content + // makes calculating it impossible. + scrollTopNext = scrollTop <= prevFrameSize ? 0 : scrollTopNext; + + // This is the scrollTop value if you are scrolled to the bottom of the + // iframe. We can't just let the browser handle it because we need to + // animate the scaling. + const maxScrollTop = + scrollHeight * ( scaleValue / prevScale ) + + frameSizeValue * 2 - + clientHeight; + + // Step 4: Clamp the scrollTopNext between the minimum and maximum + // possible scrollTop positions. Round the value to avoid subpixel + // truncation by the browser which sometimes causes a 1px error. + scrollTopNext = Math.round( + Math.min( + Math.max( 0, scrollTopNext ), + Math.max( 0, maxScrollTop ) + ) + ); - iframeDocument.documentElement.classList.add( + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-scroll-top', + `${ scrollTop }px` + ); + + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-scroll-top-next', + `${ scrollTopNext }px` + ); + + iframeDocument.documentElement.classList.add( 'zoom-out-animation' ); + + function onZoomOutTransitionEnd() { + // Remove the position fixed for the animation. + iframeDocument.documentElement.classList.remove( 'zoom-out-animation' ); - zoomOutAnimationClassnameRef.current = setTimeout( () => { - iframeDocument.documentElement.classList.remove( - 'zoom-out-animation' + // Update previous values. + prevClientHeightRef.current = clientHeight; + prevFrameSizeRef.current = frameSizeValue; + prevScaleRef.current = scaleValue; + + // Set the final scroll position that was just animated to. + // Disable reason: Eslint isn't smart enough to know that this is a + // DOM element. https://github.com/facebook/react/issues/31483 + // eslint-disable-next-line react-compiler/react-compiler + iframeDocument.documentElement.scrollTop = scrollTopNext; + } + + let raf; + if ( prefersReducedMotion ) { + // Hack: Wait for the window values to recalculate. + raf = iframeDocument.defaultView.requestAnimationFrame( + onZoomOutTransitionEnd + ); + } else { + iframeDocument.documentElement.addEventListener( + 'transitionend', + onZoomOutTransitionEnd, + { once: true } + ); + } + + return () => { + iframeDocument.documentElement.style.removeProperty( + '--wp-block-editor-iframe-zoom-out-scroll-top' + ); + iframeDocument.documentElement.style.removeProperty( + '--wp-block-editor-iframe-zoom-out-scroll-top-next' + ); + iframeDocument.documentElement.classList.remove( + 'zoom-out-animation' + ); + if ( prefersReducedMotion ) { + iframeDocument.defaultView.cancelAnimationFrame( raf ); + } else { + iframeDocument.documentElement.removeEventListener( + 'transitionend', + onZoomOutTransitionEnd ); - }, 400 ); // 400ms should match the animation speed used in components/iframe/content.scss + } }; + }, [ iframeDocument, scaleValue, frameSizeValue, prefersReducedMotion ] ); - handleZoomOutAnimationClassname(); - iframeDocument.documentElement.classList.add( 'is-zoomed-out' ); + // Toggle zoom out CSS Classes only when zoom out mode changes. We could add these into the useEffect + // that controls settings the CSS variables, but then we would need to do more work to ensure we're + // only toggling these when the zoom out mode changes, as that useEffect is also triggered by a large + // number of dependencies. + useEffect( () => { + if ( ! iframeDocument ) { + return; + } - return () => { - handleZoomOutAnimationClassname(); + if ( isZoomedOut ) { + iframeDocument.documentElement.classList.add( 'is-zoomed-out' ); + } else { + // HACK: Since we can't remove this in the cleanup, we need to do it here. iframeDocument.documentElement.classList.remove( 'is-zoomed-out' ); + } + + return () => { + // HACK: Skipping cleanup because it causes issues with the zoom out + // animation. More refactoring is needed to fix this properly. + // iframeDocument.documentElement.classList.remove( 'is-zoomed-out' ); }; }, [ iframeDocument, isZoomedOut ] ); // Calculate the scaling and CSS variables for the zoom out canvas useEffect( () => { - if ( ! iframeDocument || ! isZoomedOut ) { + if ( ! iframeDocument ) { return; } - const maxWidth = 750; // Note: When we initialize the zoom out when the canvas is smaller (sidebars open), // initialContainerWidthRef will be smaller than the full page, and reflow will happen // when the canvas area becomes larger due to sidebars closing. This is a known but @@ -371,11 +516,7 @@ function Iframe( { // but calc( 100px / 2px ) is not. iframeDocument.documentElement.style.setProperty( '--wp-block-editor-iframe-zoom-out-scale', - scale === 'auto-scaled' - ? ( Math.min( containerWidth, maxWidth ) - - parseInt( frameSize ) * 2 ) / - scaleContainerWidth - : scale + scaleValue ); // frameSize has to be a px value for the scaling and frame size to be computed correctly. @@ -401,27 +542,29 @@ function Iframe( { ); return () => { - iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-scale' - ); - iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-frame-size' - ); - iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-content-height' - ); - iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-inner-height' - ); - iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-container-width' - ); - iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-scale-container-width' - ); + // HACK: Skipping cleanup because it causes issues with the zoom out + // animation. More refactoring is needed to fix this properly. + // iframeDocument.documentElement.style.removeProperty( + // '--wp-block-editor-iframe-zoom-out-scale' + // ); + // iframeDocument.documentElement.style.removeProperty( + // '--wp-block-editor-iframe-zoom-out-frame-size' + // ); + // iframeDocument.documentElement.style.removeProperty( + // '--wp-block-editor-iframe-zoom-out-content-height' + // ); + // iframeDocument.documentElement.style.removeProperty( + // '--wp-block-editor-iframe-zoom-out-inner-height' + // ); + // iframeDocument.documentElement.style.removeProperty( + // '--wp-block-editor-iframe-zoom-out-container-width' + // ); + // iframeDocument.documentElement.style.removeProperty( + // '--wp-block-editor-iframe-zoom-out-scale-container-width' + // ); }; }, [ - scale, + scaleValue, frameSize, iframeDocument, iframeWindowInnerHeight, diff --git a/test/e2e/specs/site-editor/zoom-out.spec.js b/test/e2e/specs/site-editor/zoom-out.spec.js index 464bd4a4a4efad..e698a94b7cf0dc 100644 --- a/test/e2e/specs/site-editor/zoom-out.spec.js +++ b/test/e2e/specs/site-editor/zoom-out.spec.js @@ -3,6 +3,63 @@ */ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); +const EDITOR_ZOOM_OUT_CONTENT = ` +<!-- wp:group {"style":{"spacing":{"padding":{"top":"0","bottom":"0","left":"0","right":"0"}},"dimensions":{"minHeight":"100vh"}},"backgroundColor":"base-2","layout":{"type":"flex","orientation":"vertical","verticalAlignment":"space-between"}} --> +<div class="wp-block-group has-base-2-background-color has-background" style="min-height:100vh;padding-top:0;padding-right:0;padding-bottom:0;padding-left:0"><!-- wp:paragraph --> +<p>First Section Start</p> +<!-- /wp:paragraph --> + +<!-- wp:paragraph {"style":{"layout":{"selfStretch":"fit","flexSize":null}}} --> +<p>First Section Center</p> +<!-- /wp:paragraph --> + +<!-- wp:paragraph --> +<p>First Section End</p> +<!-- /wp:paragraph --></div> +<!-- /wp:group --> + +<!-- wp:group {"style":{"spacing":{"padding":{"top":"0","bottom":"0","left":"0","right":"0"}},"dimensions":{"minHeight":"100vh"}},"backgroundColor":"base","layout":{"type":"flex","orientation":"vertical","verticalAlignment":"space-between"}} --> +<div class="wp-block-group has-base-background-color has-background" style="min-height:100vh;padding-top:0;padding-right:0;padding-bottom:0;padding-left:0"><!-- wp:paragraph --> +<p>Second Section Start</p> +<!-- /wp:paragraph --> + +<!-- wp:paragraph {"style":{"layout":{"selfStretch":"fit","flexSize":null}}} --> +<p>Second Section Center</p> +<!-- /wp:paragraph --> + +<!-- wp:paragraph --> +<p>Second Section End</p> +<!-- /wp:paragraph --></div> +<!-- /wp:group --> + +<!-- wp:group {"style":{"spacing":{"padding":{"top":"0","bottom":"0","left":"0","right":"0"}},"dimensions":{"minHeight":"100vh"}},"backgroundColor":"base-2","layout":{"type":"flex","orientation":"vertical","verticalAlignment":"space-between"}} --> +<div class="wp-block-group has-base-2-background-color has-background" style="min-height:100vh;padding-top:0;padding-right:0;padding-bottom:0;padding-left:0"><!-- wp:paragraph --> +<p>Third Section Start</p> +<!-- /wp:paragraph --> + +<!-- wp:paragraph {"style":{"layout":{"selfStretch":"fit","flexSize":null}}} --> +<p>Third Section Center</p> +<!-- /wp:paragraph --> + +<!-- wp:paragraph --> +<p>Third Section End</p> +<!-- /wp:paragraph --></div> +<!-- /wp:group --> + +<!-- wp:group {"style":{"spacing":{"padding":{"top":"0","bottom":"0","left":"0","right":"0"}},"dimensions":{"minHeight":"100vh"}},"backgroundColor":"base","layout":{"type":"flex","orientation":"vertical","verticalAlignment":"space-between"}} --> +<div class="wp-block-group has-base-background-color has-background" style="min-height:100vh;padding-top:0;padding-right:0;padding-bottom:0;padding-left:0"><!-- wp:paragraph --> +<p>Fourth Section Start</p> +<!-- /wp:paragraph --> + +<!-- wp:paragraph {"style":{"layout":{"selfStretch":"fit","flexSize":null}}} --> +<p>Fourth Section Center</p> +<!-- /wp:paragraph --> + +<!-- wp:paragraph --> +<p>Fourth Section End</p> +<!-- /wp:paragraph --></div> +<!-- /wp:group -->`; + test.describe( 'Zoom Out', () => { test.beforeAll( async ( { requestUtils } ) => { await requestUtils.activateTheme( 'twentytwentyfour' ); @@ -47,4 +104,115 @@ test.describe( 'Zoom Out', () => { expect( htmlRect.y + paddingTop ).toBeGreaterThan( iframeRect.y ); expect( htmlRect.x ).toBeGreaterThan( iframeRect.x ); } ); + + test( 'Toggling zoom state should keep content centered', async ( { + page, + editor, + } ) => { + // Add some patterns into the page. + await editor.setContent( EDITOR_ZOOM_OUT_CONTENT ); + // Find the scroll container element + await page.evaluate( () => { + const { activeElement } = + document.activeElement?.contentDocument ?? document; + window.scrollContainer = + window.wp.dom.getScrollContainer( activeElement ); + return window.scrollContainer; + } ); + + // Test: Test from top of page (scrollTop 0) + // Enter Zoom Out + await page.getByRole( 'button', { name: 'Zoom Out' } ).click(); + + const scrollTopZoomed = await page.evaluate( () => { + return window.scrollContainer.scrollTop; + } ); + + expect( scrollTopZoomed ).toBe( 0 ); + + // Exit Zoom Out + await page.getByRole( 'button', { name: 'Zoom Out' } ).click(); + + const scrollTopNoZoom = await page.evaluate( () => { + return window.scrollContainer.scrollTop; + } ); + + expect( scrollTopNoZoom ).toBe( 0 ); + + // Test: Should center the scroll position when zooming out/in + const firstSectionEnd = editor.canvas.locator( + 'text=First Section End' + ); + const secondSectionStart = editor.canvas.locator( + 'text=Second Section Start' + ); + const secondSectionCenter = editor.canvas.locator( + 'text=Second Section Center' + ); + const secondSectionEnd = editor.canvas.locator( + 'text=Second Section End' + ); + const thirdSectionStart = editor.canvas.locator( + 'text=Third Section Start' + ); + const thirdSectionCenter = editor.canvas.locator( + 'text=Third Section Center' + ); + const thirdSectionEnd = editor.canvas.locator( + 'text=Third Section End' + ); + const fourthSectionStart = editor.canvas.locator( + 'text=Fourth Section Start' + ); + + // Test for second section + // Playwright scrolls it to the center of the viewport, so this is what we scroll to. + await secondSectionCenter.scrollIntoViewIfNeeded(); + + // Because the text is spread with a group height of 100vh, they should both be visible. + await expect( firstSectionEnd ).not.toBeInViewport(); + await expect( secondSectionStart ).toBeInViewport(); + await expect( secondSectionEnd ).toBeInViewport(); + await expect( thirdSectionStart ).not.toBeInViewport(); + + // After zooming, if we zoomed out with the correct central point, they should both still be visible when toggling zoom out state + // Enter Zoom Out + await page.getByRole( 'button', { name: 'Zoom Out' } ).click(); + await expect( firstSectionEnd ).toBeInViewport(); + await expect( secondSectionStart ).toBeInViewport(); + await expect( secondSectionEnd ).toBeInViewport(); + await expect( thirdSectionStart ).toBeInViewport(); + + // Exit Zoom Out + await page.getByRole( 'button', { name: 'Zoom Out' } ).click(); + await expect( firstSectionEnd ).not.toBeInViewport(); + await expect( secondSectionStart ).toBeInViewport(); + await expect( secondSectionEnd ).toBeInViewport(); + await expect( thirdSectionStart ).not.toBeInViewport(); + + // Test for third section + // Playwright scrolls it to the center of the viewport, so this is what we scroll to. + await thirdSectionCenter.scrollIntoViewIfNeeded(); + + // Because the text is spread with a group height of 100vh, they should both be visible. + await expect( secondSectionEnd ).not.toBeInViewport(); + await expect( thirdSectionStart ).toBeInViewport(); + await expect( thirdSectionEnd ).toBeInViewport(); + await expect( fourthSectionStart ).not.toBeInViewport(); + + // After zooming, if we zoomed out with the correct central point, they should both still be visible when toggling zoom out state + // Enter Zoom Out + await page.getByRole( 'button', { name: 'Zoom Out' } ).click(); + await expect( secondSectionEnd ).toBeInViewport(); + await expect( thirdSectionStart ).toBeInViewport(); + await expect( thirdSectionEnd ).toBeInViewport(); + await expect( fourthSectionStart ).toBeInViewport(); + + // Exit Zoom Out + await page.getByRole( 'button', { name: 'Zoom Out' } ).click(); + await expect( secondSectionEnd ).not.toBeInViewport(); + await expect( thirdSectionStart ).toBeInViewport(); + await expect( thirdSectionEnd ).toBeInViewport(); + await expect( fourthSectionStart ).not.toBeInViewport(); + } ); } ); From 98b3ec03395836887ba3327cf9a16b279296b6c4 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 26 Nov 2024 03:07:57 +0900 Subject: [PATCH 1701/1908] BorderBoxControl: Suppress redundant warnings for deprecated 36px size (#67213) * BorderControl: Add support for warning suppression * BorderBoxControl: Suppress redundant warnings for deprecated 36px size * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../border-box-control-split-controls/component.tsx | 1 + .../border-box-control/border-box-control/component.tsx | 1 + .../components/src/border-control/border-control/hook.ts | 2 ++ packages/components/src/border-control/types.ts | 7 +++++++ 5 files changed, 12 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 29e746c905f8d4..ad7896f99f570e 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -38,6 +38,7 @@ - `SlotFill`: fix dependencies of `Fill` registration effects ([#67071](https://github.com/WordPress/gutenberg/pull/67071)). - `SlotFill`: rewrite the `Slot` component from class component to functional ([#67153](https://github.com/WordPress/gutenberg/pull/67153)). - `Menu.ItemHelpText`: Fix text wrapping to prevent unintended word breaks ([#67011](https://github.com/WordPress/gutenberg/pull/67011)). +- `BorderBoxControl`: Suppress redundant warnings for deprecated 36px size ([#67213](https://github.com/WordPress/gutenberg/pull/67213)). ## 28.12.0 (2024-11-16) diff --git a/packages/components/src/border-box-control/border-box-control-split-controls/component.tsx b/packages/components/src/border-box-control/border-box-control-split-controls/component.tsx index 8f125cdb8f9261..0c887ab5f701c3 100644 --- a/packages/components/src/border-box-control/border-box-control-split-controls/component.tsx +++ b/packages/components/src/border-box-control/border-box-control-split-controls/component.tsx @@ -67,6 +67,7 @@ const BorderBoxControlSplitControls = ( isCompact: true, __experimentalIsRenderedInSidebar, size, + __shouldNotWarnDeprecated36pxSize: true, }; const mergedRef = useMergeRefs( [ setPopoverAnchor, forwardedRef ] ); diff --git a/packages/components/src/border-box-control/border-box-control/component.tsx b/packages/components/src/border-box-control/border-box-control/component.tsx index d2d77adc69eb89..0e84c7b56ee483 100644 --- a/packages/components/src/border-box-control/border-box-control/component.tsx +++ b/packages/components/src/border-box-control/border-box-control/component.tsx @@ -118,6 +118,7 @@ const UnconnectedBorderBoxControl = ( __experimentalIsRenderedInSidebar={ __experimentalIsRenderedInSidebar } + __shouldNotWarnDeprecated36pxSize size={ size } /> ) : ( diff --git a/packages/components/src/border-control/border-control/hook.ts b/packages/components/src/border-control/border-control/hook.ts index 67af7ce42416c3..9b0f064c51921f 100644 --- a/packages/components/src/border-control/border-control/hook.ts +++ b/packages/components/src/border-control/border-control/hook.ts @@ -38,6 +38,7 @@ export function useBorderControl( width, __experimentalIsRenderedInSidebar = false, __next40pxDefaultSize, + __shouldNotWarnDeprecated36pxSize, ...otherProps } = useContextSystem( props, 'BorderControl' ); @@ -45,6 +46,7 @@ export function useBorderControl( componentName: 'BorderControl', __next40pxDefaultSize, size, + __shouldNotWarnDeprecated36pxSize, } ); const computedSize = diff --git a/packages/components/src/border-control/types.ts b/packages/components/src/border-control/types.ts index 8ab614907684d2..ecd3f67c9be08d 100644 --- a/packages/components/src/border-control/types.ts +++ b/packages/components/src/border-control/types.ts @@ -116,6 +116,13 @@ export type BorderControlProps = ColorProps & * @default false */ __next40pxDefaultSize?: boolean; + /** + * Do not throw a warning for the deprecated 36px default size. + * For internal components of other components that already throw the warning. + * + * @ignore + */ + __shouldNotWarnDeprecated36pxSize?: boolean; }; export type DropdownProps = ColorProps & From 338161387c660ac3b16eba9aa973a066d8db0aa4 Mon Sep 17 00:00:00 2001 From: Vipul Gupta <55375170+vipul0425@users.noreply.github.com> Date: Tue, 26 Nov 2024 03:08:03 +0530 Subject: [PATCH 1702/1908] Feat: Adds the deprecation warning for 36px default size in range control. (#66721) * feat: Adds the deprecation warning for range control. * docs: Adds deprecation changelog. * feat: Suppress the redundant warnings. * refactor: Supress redundant warnings. --------- Co-authored-by: vipul0425 <vipulgupta003@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/border-control/border-control/component.tsx | 1 + .../components/src/box-control/all-input-control.tsx | 1 + .../src/box-control/axial-input-controls.tsx | 1 + .../components/src/box-control/input-controls.tsx | 1 + packages/components/src/font-size-picker/index.tsx | 1 + packages/components/src/range-control/README.md | 7 ++++--- packages/components/src/range-control/index.tsx | 11 +++++++++++ .../src/range-control/stories/index.story.tsx | 7 +++++++ packages/components/src/range-control/test/index.tsx | 8 +++++++- packages/components/src/range-control/types.ts | 7 +++++++ 11 files changed, 42 insertions(+), 4 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index ad7896f99f570e..9f547859fa5a99 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -9,6 +9,7 @@ - `FontSizePicker`: Deprecate 36px default size ([#66920](https://github.com/WordPress/gutenberg/pull/66920)). - `ComboboxControl`: Deprecate 36px default size ([#66900](https://github.com/WordPress/gutenberg/pull/66900)). - `ToggleGroupControl`: Deprecate 36px default size ([#66747](https://github.com/WordPress/gutenberg/pull/66747)). +- `RangeControl`: Deprecate 36px default size ([#66721](https://github.com/WordPress/gutenberg/pull/66721)). ### Bug Fixes diff --git a/packages/components/src/border-control/border-control/component.tsx b/packages/components/src/border-control/border-control/component.tsx index 31eeb166a2d60f..2ba338c2bb30cb 100644 --- a/packages/components/src/border-control/border-control/component.tsx +++ b/packages/components/src/border-control/border-control/component.tsx @@ -122,6 +122,7 @@ const UnconnectedBorderControl = ( value={ widthValue || undefined } withInputField={ false } __next40pxDefaultSize={ __next40pxDefaultSize } + __shouldNotWarnDeprecated36pxSize /> ) } </HStack> diff --git a/packages/components/src/box-control/all-input-control.tsx b/packages/components/src/box-control/all-input-control.tsx index e9166ff7f692e8..057cf3c15d8c38 100644 --- a/packages/components/src/box-control/all-input-control.tsx +++ b/packages/components/src/box-control/all-input-control.tsx @@ -91,6 +91,7 @@ export default function AllInputControl( { <FlexedRangeControl __nextHasNoMarginBottom __next40pxDefaultSize={ __next40pxDefaultSize } + __shouldNotWarnDeprecated36pxSize aria-controls={ inputId } label={ LABELS.all } hideLabelFromVision diff --git a/packages/components/src/box-control/axial-input-controls.tsx b/packages/components/src/box-control/axial-input-controls.tsx index c6c0181f6c871c..40b39840b464b5 100644 --- a/packages/components/src/box-control/axial-input-controls.tsx +++ b/packages/components/src/box-control/axial-input-controls.tsx @@ -129,6 +129,7 @@ export default function AxialInputControls( { <FlexedRangeControl __nextHasNoMarginBottom __next40pxDefaultSize={ __next40pxDefaultSize } + __shouldNotWarnDeprecated36pxSize aria-controls={ inputId } label={ LABELS[ side ] } hideLabelFromVision diff --git a/packages/components/src/box-control/input-controls.tsx b/packages/components/src/box-control/input-controls.tsx index 553f547abf9b0d..1f005f6c6c01bd 100644 --- a/packages/components/src/box-control/input-controls.tsx +++ b/packages/components/src/box-control/input-controls.tsx @@ -134,6 +134,7 @@ export default function BoxInputControls( { <FlexedRangeControl __nextHasNoMarginBottom __next40pxDefaultSize={ __next40pxDefaultSize } + __shouldNotWarnDeprecated36pxSize aria-controls={ inputId } label={ LABELS[ side ] } hideLabelFromVision diff --git a/packages/components/src/font-size-picker/index.tsx b/packages/components/src/font-size-picker/index.tsx index d4e8ea29fc6c4f..a71e60cd6719c8 100644 --- a/packages/components/src/font-size-picker/index.tsx +++ b/packages/components/src/font-size-picker/index.tsx @@ -242,6 +242,7 @@ const UnforwardedFontSizePicker = ( __next40pxDefaultSize={ __next40pxDefaultSize } + __shouldNotWarnDeprecated36pxSize className="components-font-size-picker__custom-input" label={ __( 'Custom Size' ) } hideLabelFromVision diff --git a/packages/components/src/range-control/README.md b/packages/components/src/range-control/README.md index cfa8c76740e74f..f21285c5f26256 100644 --- a/packages/components/src/range-control/README.md +++ b/packages/components/src/range-control/README.md @@ -88,9 +88,10 @@ import { RangeControl } from '@wordpress/components'; const MyRangeControl = () => { const [ columns, setColumns ] = useState( 2 ); - return( + return ( <RangeControl __nextHasNoMarginBottom + __next40pxDefaultSize label="Columns" value={ columns } onChange={ ( value ) => setColumns( value ) } @@ -153,7 +154,6 @@ Disables the `input`, preventing new values from being applied. - Required: No - Platform: Web - ### `help`: `string|Element` If this property is added, a help text will be generated using help property as the content. @@ -165,7 +165,7 @@ If this property is added, a help text will be generated using help property as Provides control over whether the label will only be visible to screen readers. -- Required: No +- Required: No ### `icon`: `string` @@ -334,6 +334,7 @@ The minimum amount by which `value` changes. It is also a factor in validation a - Required: No - Platform: Web + ### `trackColor`: `CSSProperties[ 'color' ]` CSS color string to customize the track element's background. diff --git a/packages/components/src/range-control/index.tsx b/packages/components/src/range-control/index.tsx index c9fbdc0055c855..916571c3ee0e05 100644 --- a/packages/components/src/range-control/index.tsx +++ b/packages/components/src/range-control/index.tsx @@ -38,6 +38,7 @@ import { import type { RangeControlProps } from './types'; import type { WordPressComponentProps } from '../context'; import { space } from '../utils/space'; +import { maybeWarnDeprecated36pxSize } from '../utils/deprecated-36px-size'; const noop = () => {}; @@ -96,6 +97,7 @@ function UnforwardedRangeControl( trackColor, value: valueProp, withInputField = true, + __shouldNotWarnDeprecated36pxSize, ...otherProps } = props; @@ -229,6 +231,14 @@ function UnforwardedRangeControl( [ isRTL() ? 'right' : 'left' ]: fillValueOffset, }; + // Add default size deprecation warning. + maybeWarnDeprecated36pxSize( { + componentName: 'RangeControl', + __next40pxDefaultSize, + size: undefined, + __shouldNotWarnDeprecated36pxSize, + } ); + return ( <BaseControl __nextHasNoMarginBottom={ __nextHasNoMarginBottom } @@ -384,6 +394,7 @@ function UnforwardedRangeControl( * return ( * <RangeControl * __nextHasNoMarginBottom + * __next40pxDefaultSize * help="Please select how transparent you would like this." * initialPosition={50} * label="Opacity" diff --git a/packages/components/src/range-control/stories/index.story.tsx b/packages/components/src/range-control/stories/index.story.tsx index dcff3513733527..86a2609b8db649 100644 --- a/packages/components/src/range-control/stories/index.story.tsx +++ b/packages/components/src/range-control/stories/index.story.tsx @@ -72,6 +72,7 @@ const Template: StoryFn< typeof RangeControl > = ( { onChange, ...args } ) => { export const Default: StoryFn< typeof RangeControl > = Template.bind( {} ); Default.args = { __nextHasNoMarginBottom: true, + __next40pxDefaultSize: true, help: 'Please select how transparent you would like this.', initialPosition: 50, label: 'Opacity', @@ -107,6 +108,7 @@ export const WithAnyStep: StoryFn< typeof RangeControl > = ( { }; WithAnyStep.args = { __nextHasNoMarginBottom: true, + __next40pxDefaultSize: true, label: 'Brightness', step: 'any', }; @@ -171,6 +173,7 @@ export const WithIntegerStepAndMarks: StoryFn< typeof RangeControl > = WithIntegerStepAndMarks.args = { __nextHasNoMarginBottom: true, + __next40pxDefaultSize: true, label: 'Integer Step', marks: marksBase, max: 10, @@ -188,6 +191,7 @@ export const WithDecimalStepAndMarks: StoryFn< typeof RangeControl > = WithDecimalStepAndMarks.args = { __nextHasNoMarginBottom: true, + __next40pxDefaultSize: true, marks: [ ...marksBase, { value: 3.5, label: '3.5' }, @@ -208,6 +212,7 @@ export const WithNegativeMinimumAndMarks: StoryFn< typeof RangeControl > = WithNegativeMinimumAndMarks.args = { __nextHasNoMarginBottom: true, + __next40pxDefaultSize: true, marks: marksWithNegatives, max: 10, min: -10, @@ -224,6 +229,7 @@ export const WithNegativeRangeAndMarks: StoryFn< typeof RangeControl > = WithNegativeRangeAndMarks.args = { __nextHasNoMarginBottom: true, + __next40pxDefaultSize: true, marks: marksWithNegatives, max: -1, min: -10, @@ -240,6 +246,7 @@ export const WithAnyStepAndMarks: StoryFn< typeof RangeControl > = WithAnyStepAndMarks.args = { __nextHasNoMarginBottom: true, + __next40pxDefaultSize: true, marks: marksBase, max: 10, min: 0, diff --git a/packages/components/src/range-control/test/index.tsx b/packages/components/src/range-control/test/index.tsx index 3ce741867d0dbc..3d2db30eea186f 100644 --- a/packages/components/src/range-control/test/index.tsx +++ b/packages/components/src/range-control/test/index.tsx @@ -18,7 +18,13 @@ const fireChangeEvent = ( input: HTMLInputElement, value?: number | string ) => const RangeControl = ( props: React.ComponentProps< typeof _RangeControl > ) => { - return <_RangeControl { ...props } __nextHasNoMarginBottom />; + return ( + <_RangeControl + { ...props } + __nextHasNoMarginBottom + __next40pxDefaultSize + /> + ); }; describe( 'RangeControl', () => { diff --git a/packages/components/src/range-control/types.ts b/packages/components/src/range-control/types.ts index a427ab4f942af6..e4792296f83144 100644 --- a/packages/components/src/range-control/types.ts +++ b/packages/components/src/range-control/types.ts @@ -233,6 +233,13 @@ export type RangeControlProps = Pick< * @default true */ withInputField?: boolean; + /** + * Do not throw a warning for the deprecated 36px default size. + * For internal components of other components that already throw the warning. + * + * @ignore + */ + __shouldNotWarnDeprecated36pxSize?: boolean; }; export type RailProps = MarksProps & { From 08d8b8661a602ce42742b9f7e71ca42c389ee169 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 26 Nov 2024 07:10:45 +0900 Subject: [PATCH 1703/1908] ComboboxControl: Update reset button size (#67215) * ComboboxControl: Update reset button size * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/combobox-control/index.tsx | 24 +++++++++---------- .../src/combobox-control/style.scss | 6 ----- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 9f547859fa5a99..81e325c8d9b3ff 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -27,6 +27,7 @@ ### Enhancements - `ColorPicker`: Update sizes of color format select and copy button ([#67093](https://github.com/WordPress/gutenberg/pull/67093)). +- `ComboboxControl`: Update reset button size ([#67215](https://github.com/WordPress/gutenberg/pull/67215)). - `Autocomplete`: Increase option height ([#67214](https://github.com/WordPress/gutenberg/pull/67214)). ### Experimental diff --git a/packages/components/src/combobox-control/index.tsx b/packages/components/src/combobox-control/index.tsx index 86fa4f4467318c..28510c8653d02e 100644 --- a/packages/components/src/combobox-control/index.tsx +++ b/packages/components/src/combobox-control/index.tsx @@ -26,7 +26,7 @@ import TokenInput from '../form-token-field/token-input'; import SuggestionsList from '../form-token-field/suggestions-list'; import BaseControl from '../base-control'; import Button from '../button'; -import { FlexBlock, FlexItem } from '../flex'; +import { FlexBlock } from '../flex'; import withFocusOutside from '../higher-order/with-focus-outside'; import { useControlledValue } from '../utils/hooks'; import { normalizeTextString } from '../utils/strings'; @@ -363,18 +363,16 @@ function ComboboxControl( props: ComboboxControlProps ) { /> </FlexBlock> { allowReset && ( - <FlexItem> - <Button - className="components-combobox-control__reset" - icon={ closeSmall } - // Disable reason: Focus returns to input field when reset is clicked. - // eslint-disable-next-line no-restricted-syntax - disabled={ ! value } - onClick={ handleOnReset } - onKeyDown={ handleResetStopPropagation } - label={ __( 'Reset' ) } - /> - </FlexItem> + <Button + size="small" + icon={ closeSmall } + // Disable reason: Focus returns to input field when reset is clicked. + // eslint-disable-next-line no-restricted-syntax + disabled={ ! value } + onClick={ handleOnReset } + onKeyDown={ handleResetStopPropagation } + label={ __( 'Reset' ) } + /> ) } </InputWrapperFlex> { isExpanded && ( diff --git a/packages/components/src/combobox-control/style.scss b/packages/components/src/combobox-control/style.scss index 8bd4c2fb156a9f..c8fd8a168c0fb7 100644 --- a/packages/components/src/combobox-control/style.scss +++ b/packages/components/src/combobox-control/style.scss @@ -38,9 +38,3 @@ input.components-combobox-control__input[type="text"] { } } -.components-combobox-control__reset.components-button { - display: flex; - height: $grid-unit-20; - min-width: $grid-unit-20; - padding: 0; -} From 9b0e2d96679ab6c82033946bead9521529e6b29a Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:50:39 +0900 Subject: [PATCH 1704/1908] Block Manager: Make it a private component in the block editor package (#67255) * Block Manager: Make it a private component in the block editor package * Move style import statement Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/base-styles/_z-index.scss | 4 +-- .../src/components/block-manager/category.js | 6 ++-- .../src/components/block-manager/checklist.js | 10 +++++-- .../src/components/block-manager/index.js | 10 +++---- .../src/components/block-manager/style.scss | 28 +++++++++---------- packages/block-editor/src/private-apis.js | 2 ++ packages/block-editor/src/style.scss | 1 + .../preferences-modal/block-visibility.js | 4 ++- packages/editor/src/style.scss | 1 - 9 files changed, 37 insertions(+), 29 deletions(-) rename packages/{editor => block-editor}/src/components/block-manager/category.js (91%) rename packages/{editor => block-editor}/src/components/block-manager/checklist.js (75%) rename packages/{editor => block-editor}/src/components/block-manager/index.js (92%) rename packages/{editor => block-editor}/src/components/block-manager/style.scss (65%) diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index e4d6ce4ce1b1c9..167af583ed9ddb 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -165,9 +165,9 @@ $z-layers: ( ".components-resizable-box__corner-handle": 2, // Make sure block manager sticky category titles appear above the options - ".editor-block-manager__category-title": 1, + ".block-editor-block-manager__category-title": 1, // And block manager sticky disabled block count is higher still - ".editor-block-manager__disabled-blocks-count": 2, + ".block-editor-block-manager__disabled-blocks-count": 2, // Needs to appear below other color circular picker related UI elements. ".components-circular-option-picker__option-wrapper::before": -1, diff --git a/packages/editor/src/components/block-manager/category.js b/packages/block-editor/src/components/block-manager/category.js similarity index 91% rename from packages/editor/src/components/block-manager/category.js rename to packages/block-editor/src/components/block-manager/category.js index 341584fee03b96..79d5896b4502e4 100644 --- a/packages/editor/src/components/block-manager/category.js +++ b/packages/block-editor/src/components/block-manager/category.js @@ -71,7 +71,7 @@ function BlockManagerCategory( { ) ); - const titleId = 'editor-block-manager__category-title-' + instanceId; + const titleId = 'block-editor-block-manager__category-title-' + instanceId; const isAllChecked = checkedBlockNames.length === blockTypes.length; const isIndeterminate = ! isAllChecked && checkedBlockNames.length > 0; @@ -80,13 +80,13 @@ function BlockManagerCategory( { <div role="group" aria-labelledby={ titleId } - className="editor-block-manager__category" + className="block-editor-block-manager__category" > <CheckboxControl __nextHasNoMarginBottom checked={ isAllChecked } onChange={ toggleAllVisible } - className="editor-block-manager__category-title" + className="block-editor-block-manager__category-title" indeterminate={ isIndeterminate } label={ <span id={ titleId }>{ title }</span> } /> diff --git a/packages/editor/src/components/block-manager/checklist.js b/packages/block-editor/src/components/block-manager/checklist.js similarity index 75% rename from packages/editor/src/components/block-manager/checklist.js rename to packages/block-editor/src/components/block-manager/checklist.js index 2839e2c9e14c14..d5456a14355efb 100644 --- a/packages/editor/src/components/block-manager/checklist.js +++ b/packages/block-editor/src/components/block-manager/checklist.js @@ -1,16 +1,20 @@ /** * WordPress dependencies */ -import { BlockIcon } from '@wordpress/block-editor'; import { CheckboxControl } from '@wordpress/components'; +/** + * Internal dependencies + */ +import BlockIcon from '../block-icon'; + function BlockTypesChecklist( { blockTypes, value, onItemChange } ) { return ( - <ul className="editor-block-manager__checklist"> + <ul className="block-editor-block-manager__checklist"> { blockTypes.map( ( blockType ) => ( <li key={ blockType.name } - className="editor-block-manager__checklist-item" + className="block-editor-block-manager__checklist-item" > <CheckboxControl __nextHasNoMarginBottom diff --git a/packages/editor/src/components/block-manager/index.js b/packages/block-editor/src/components/block-manager/index.js similarity index 92% rename from packages/editor/src/components/block-manager/index.js rename to packages/block-editor/src/components/block-manager/index.js index 5c719c62a5a0b2..30d10e67040c71 100644 --- a/packages/editor/src/components/block-manager/index.js +++ b/packages/block-editor/src/components/block-manager/index.js @@ -61,9 +61,9 @@ export default function BlockManager( { }, [ filteredBlockTypes?.length, search, debouncedSpeak ] ); return ( - <div className="editor-block-manager__content"> + <div className="block-editor-block-manager__content"> { !! numberOfHiddenBlocks && ( - <div className="editor-block-manager__disabled-blocks-count"> + <div className="block-editor-block-manager__disabled-blocks-count"> { sprintf( /* translators: %d: number of blocks. */ _n( @@ -88,16 +88,16 @@ export default function BlockManager( { placeholder={ __( 'Search for a block' ) } value={ search } onChange={ ( nextSearch ) => setSearch( nextSearch ) } - className="editor-block-manager__search" + className="block-editor-block-manager__search" /> <div tabIndex="0" role="region" aria-label={ __( 'Available block types' ) } - className="editor-block-manager__results" + className="block-editor-block-manager__results" > { filteredBlockTypes.length === 0 && ( - <p className="editor-block-manager__no-results"> + <p className="block-editor-block-manager__no-results"> { __( 'No blocks found.' ) } </p> ) } diff --git a/packages/editor/src/components/block-manager/style.scss b/packages/block-editor/src/components/block-manager/style.scss similarity index 65% rename from packages/editor/src/components/block-manager/style.scss rename to packages/block-editor/src/components/block-manager/style.scss index 411ee9faf34f75..d72c682dcbb5d5 100644 --- a/packages/editor/src/components/block-manager/style.scss +++ b/packages/block-editor/src/components/block-manager/style.scss @@ -1,14 +1,14 @@ -.editor-block-manager__no-results { +.block-editor-block-manager__no-results { font-style: italic; padding: $grid-unit-30 0; text-align: center; } -.editor-block-manager__search { +.block-editor-block-manager__search { margin: $grid-unit-20 0; } -.editor-block-manager__disabled-blocks-count { +.block-editor-block-manager__disabled-blocks-count { border: $border-width solid $gray-300; border-width: $border-width 0; // Cover up horizontal areas off the sides of the box rectangle @@ -19,10 +19,10 @@ position: sticky; // When sticking, tuck the top border beneath the modal header border top: ($grid-unit-05 + 1) * -1; - z-index: z-index(".editor-block-manager__disabled-blocks-count"); + z-index: z-index(".block-editor-block-manager__disabled-blocks-count"); // Stick the category titles to the bottom - ~ .editor-block-manager__results .editor-block-manager__category-title { + ~ .block-editor-block-manager__results .block-editor-block-manager__category-title { top: $grid-unit-40 - 1; } .is-link { @@ -30,32 +30,32 @@ } } -.editor-block-manager__category { +.block-editor-block-manager__category { margin: 0 0 $grid-unit-30 0; } -.editor-block-manager__category-title { +.block-editor-block-manager__category-title { position: sticky; top: - $grid-unit-05; // Offsets the top padding on the modal content container padding: $grid-unit-20 0; background-color: $white; - z-index: z-index(".editor-block-manager__category-title"); + z-index: z-index(".block-editor-block-manager__category-title"); .components-checkbox-control__label { font-weight: 600; } } -.editor-block-manager__checklist { +.block-editor-block-manager__checklist { margin-top: 0; } -.editor-block-manager__category-title, -.editor-block-manager__checklist-item { +.block-editor-block-manager__category-title, +.block-editor-block-manager__checklist-item { border-bottom: 1px solid $gray-300; } -.editor-block-manager__checklist-item { +.block-editor-block-manager__checklist-item { display: flex; justify-content: space-between; align-items: center; @@ -72,11 +72,11 @@ } } -.editor-block-manager__results { +.block-editor-block-manager__results { border-top: $border-width solid $gray-300; } // Remove the top border from results when adjacent to the disabled block count -.editor-block-manager__disabled-blocks-count + .editor-block-manager__results { +.block-editor-block-manager__disabled-blocks-count + .block-editor-block-manager__results { border-top-width: 0; } diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 5067317e3f2465..0faee244e387c2 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -18,6 +18,7 @@ import { useHasBlockToolbar } from './components/block-toolbar/use-has-block-too import { cleanEmptyObject } from './hooks/utils'; import BlockQuickNavigation from './components/block-quick-navigation'; import { LayoutStyle } from './components/block-list/layout'; +import BlockManager from './components/block-manager'; import { BlockRemovalWarningModal } from './components/block-removal-warning-modal'; import { setBackgroundStyleDefaults, @@ -71,6 +72,7 @@ lock( privateApis, { cleanEmptyObject, BlockQuickNavigation, LayoutStyle, + BlockManager, BlockRemovalWarningModal, useLayoutClasses, useLayoutStyles, diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index 512169351fe1fb..213498c797aee4 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -10,6 +10,7 @@ @import "./components/block-card/style.scss"; @import "./components/block-compare/style.scss"; @import "./components/block-draggable/style.scss"; +@import "./components/block-manager/style.scss"; @import "./components/block-mover/style.scss"; @import "./components/block-navigation/style.scss"; @import "./components/block-patterns-list/style.scss"; diff --git a/packages/editor/src/components/preferences-modal/block-visibility.js b/packages/editor/src/components/preferences-modal/block-visibility.js index 49d6888c5dbfe2..8726b114d97480 100644 --- a/packages/editor/src/components/preferences-modal/block-visibility.js +++ b/packages/editor/src/components/preferences-modal/block-visibility.js @@ -5,13 +5,15 @@ import { useSelect, useDispatch } from '@wordpress/data'; import { store as preferencesStore } from '@wordpress/preferences'; import { hasBlockSupport, store as blocksStore } from '@wordpress/blocks'; import { useMemo } from '@wordpress/element'; +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; /** * Internal dependencies */ import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; -import BlockManager from '../block-manager'; + +const { BlockManager } = unlock( blockEditorPrivateApis ); export default function BlockVisibility() { const { showBlockTypes, hideBlockTypes } = unlock( diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss index b62ccd2c8ac71d..88d722867d009b 100644 --- a/packages/editor/src/style.scss +++ b/packages/editor/src/style.scss @@ -1,7 +1,6 @@ @import "../../interface/src/style.scss"; @import "./components/autocompleters/style.scss"; -@import "./components/block-manager/style.scss"; @import "./components/collab-sidebar/style.scss"; @import "./components/collapsible-block-toolbar/style.scss"; @import "./components/create-template-part-modal/style.scss"; From e34948762abf749844eb349c1312753057f57fb9 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 26 Nov 2024 16:32:42 +0900 Subject: [PATCH 1705/1908] Dashicons: Remove non-existent icons from type (#67235) * Dashicons: Remove non-existent icons from type * Update changelog Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/dashicon/types.ts | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 81e325c8d9b3ff..23e791645a20c8 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -23,6 +23,7 @@ - `FormFileUpload`: Prevent HEIC and HEIF files from being uploaded on Safari ([#67139](https://github.com/WordPress/gutenberg/pull/67139)). - `Composite.Hover`: Restore functionality ([#67212](https://github.com/WordPress/gutenberg/pull/67212)). - `Composite.Typeahead`: Restore functionality ([#67212](https://github.com/WordPress/gutenberg/pull/67212)). +- `Dashicons`: Remove non-existent icons from type ([#67235](https://github.com/WordPress/gutenberg/pull/67235)). ### Enhancements diff --git a/packages/components/src/dashicon/types.ts b/packages/components/src/dashicon/types.ts index eeee9c2d40a19d..a4a4f5156aff5f 100644 --- a/packages/components/src/dashicon/types.ts +++ b/packages/components/src/dashicon/types.ts @@ -219,7 +219,6 @@ export type IconKey = | 'insert-before' | 'insert' | 'instagram' - | 'keyboard-hide' | 'laptop' | 'layout' | 'leftright' @@ -266,7 +265,6 @@ export type IconKey = | 'playlist-audio' | 'playlist-video' | 'plus-alt' - | 'plus-light' | 'plus' | 'portfolio' | 'post-status' From 99c6478b0c8582d334d2d26e6303db61828da092 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 26 Nov 2024 12:22:00 +0400 Subject: [PATCH 1706/1908] Edit Post: Remove unused 'hasHistory' flag (#67293) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- packages/edit-post/src/components/browser-url/index.js | 5 ++--- packages/edit-post/src/components/layout/index.js | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/edit-post/src/components/browser-url/index.js b/packages/edit-post/src/components/browser-url/index.js index 12292cb8447217..00492afbdc2624 100644 --- a/packages/edit-post/src/components/browser-url/index.js +++ b/packages/edit-post/src/components/browser-url/index.js @@ -27,14 +27,13 @@ export class BrowserURL extends Component { } componentDidUpdate( prevProps ) { - const { postId, postStatus, hasHistory } = this.props; + const { postId, postStatus } = this.props; const { historyId } = this.state; if ( ( postId !== prevProps.postId || postId !== historyId ) && postStatus !== 'auto-draft' && - postId && - ! hasHistory + postId ) { this.setBrowserURL( postId ); } diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index aec14eab989f03..5dcbfa2c82cea1 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -392,7 +392,6 @@ function Layout( { showIconLabels, isDistractionFree, showMetaBoxes, - hasHistory, isWelcomeGuideVisible, templateId, enablePaddingAppender, @@ -595,7 +594,7 @@ function Layout( { <PostLockedModal /> <EditorInitialization /> <FullscreenMode isActive={ isFullscreenActive } /> - <BrowserURL hasHistory={ hasHistory } /> + <BrowserURL /> <UnsavedChangesWarning /> <AutosaveMonitor /> <LocalAutosaveMonitor /> From 3f6b883c04397264229588c7f4d8c040cbd5e8e5 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Tue, 26 Nov 2024 09:25:10 +0100 Subject: [PATCH 1707/1908] Improve accessibility and consistency of the 'Last modified' Revisions button. (#66606) * Improve accessibility and consistency of the Revisions button. * Simplify revisions button and add count. * Remove no longer used stylesheet import. * Simplify revisions count retrieval by using useGlobalStylesRevisions. * Adjust after 67180. * Remove duplicate import after rebase. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: up1512001 <up1512001@git.wordpress.org> --- .../index.js | 47 +++++-------------- .../style.scss | 4 -- .../index.js | 40 ---------------- ...r-navigation-screen-details-panel-label.js | 14 ------ ...bar-navigation-screen-details-panel-row.js | 31 ------------ ...r-navigation-screen-details-panel-value.js | 14 ------ .../style.scss | 26 ---------- .../index.js | 3 +- .../sidebar-navigation-screen/style.scss | 9 +++- packages/edit-site/src/style.scss | 1 - 10 files changed, 20 insertions(+), 169 deletions(-) delete mode 100644 packages/edit-site/src/components/sidebar-navigation-screen-details-panel/index.js delete mode 100644 packages/edit-site/src/components/sidebar-navigation-screen-details-panel/sidebar-navigation-screen-details-panel-label.js delete mode 100644 packages/edit-site/src/components/sidebar-navigation-screen-details-panel/sidebar-navigation-screen-details-panel-row.js delete mode 100644 packages/edit-site/src/components/sidebar-navigation-screen-details-panel/sidebar-navigation-screen-details-panel-value.js delete mode 100644 packages/edit-site/src/components/sidebar-navigation-screen-details-panel/style.scss diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-details-footer/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-details-footer/index.js index 51833443d8d85c..f7e5f8bbec34de 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-details-footer/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-details-footer/index.js @@ -1,24 +1,14 @@ /** * WordPress dependencies */ -import { __, sprintf } from '@wordpress/i18n'; -import { humanTimeDiff } from '@wordpress/date'; -import { createInterpolateElement } from '@wordpress/element'; +import { _n, sprintf } from '@wordpress/i18n'; import { addQueryArgs } from '@wordpress/url'; -import { - Icon, - __experimentalItemGroup as ItemGroup, -} from '@wordpress/components'; +import { __experimentalItemGroup as ItemGroup } from '@wordpress/components'; import { backup } from '@wordpress/icons'; /** * Internal dependencies */ -import { - SidebarNavigationScreenDetailsPanelRow, - SidebarNavigationScreenDetailsPanelLabel, - SidebarNavigationScreenDetailsPanelValue, -} from '../sidebar-navigation-screen-details-panel'; import SidebarNavigationItem from '../sidebar-navigation-item'; export default function SidebarNavigationScreenDetailsFooter( { @@ -56,33 +46,20 @@ export default function SidebarNavigationScreenDetailsFooter( { hrefProps.as = 'a'; } return ( - <ItemGroup className="edit-site-sidebar-navigation-screen-details-footer"> + <ItemGroup + size="large" + className="edit-site-sidebar-navigation-screen-details-footer" + > <SidebarNavigationItem - aria-label={ __( 'Revisions' ) } + icon={ backup } { ...hrefProps } { ...otherProps } > - <SidebarNavigationScreenDetailsPanelRow justify="space-between"> - <SidebarNavigationScreenDetailsPanelLabel> - { __( 'Last modified' ) } - </SidebarNavigationScreenDetailsPanelLabel> - <SidebarNavigationScreenDetailsPanelValue> - { createInterpolateElement( - sprintf( - /* translators: %s: is the relative time when the post was last modified. */ - __( '<time>%s</time>' ), - humanTimeDiff( record.modified ) - ), - { - time: <time dateTime={ record.modified } />, - } - ) } - </SidebarNavigationScreenDetailsPanelValue> - <Icon - className="edit-site-sidebar-navigation-screen-details-footer__icon" - icon={ backup } - /> - </SidebarNavigationScreenDetailsPanelRow> + { sprintf( + /* translators: %d: Number of Styles revisions. */ + _n( '%d Revision', '%d Revisions', revisionsCount ), + revisionsCount + ) } </SidebarNavigationItem> </ItemGroup> ); diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-details-footer/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen-details-footer/style.scss index 866a36c02174d3..0b48d451129662 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-details-footer/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-screen-details-footer/style.scss @@ -5,8 +5,4 @@ div.edit-site-sidebar-navigation-item.components-item[aria-current] { background: none; } - .edit-site-sidebar-navigation-screen-details-footer__icon { - margin-left: auto; - fill: $gray-600; - } } diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/index.js deleted file mode 100644 index 7d7a3932c99473..00000000000000 --- a/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/index.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * WordPress dependencies - */ -import { - __experimentalVStack as VStack, - __experimentalHeading as Heading, -} from '@wordpress/components'; - -/** - * Internal dependencies - */ -import SidebarNavigationScreenDetailsPanelLabel from './sidebar-navigation-screen-details-panel-label'; -import SidebarNavigationScreenDetailsPanelRow from './sidebar-navigation-screen-details-panel-row'; -import SidebarNavigationScreenDetailsPanelValue from './sidebar-navigation-screen-details-panel-value'; - -function SidebarNavigationScreenDetailsPanel( { title, children, spacing } ) { - return ( - <VStack - className="edit-site-sidebar-navigation-details-screen-panel" - spacing={ spacing } - > - { title && ( - <Heading - className="edit-site-sidebar-navigation-details-screen-panel__heading" - level={ 2 } - > - { title } - </Heading> - ) } - { children } - </VStack> - ); -} - -export { - SidebarNavigationScreenDetailsPanel, - SidebarNavigationScreenDetailsPanelRow, - SidebarNavigationScreenDetailsPanelLabel, - SidebarNavigationScreenDetailsPanelValue, -}; diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/sidebar-navigation-screen-details-panel-label.js b/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/sidebar-navigation-screen-details-panel-label.js deleted file mode 100644 index 157eecd557519c..00000000000000 --- a/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/sidebar-navigation-screen-details-panel-label.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * WordPress dependencies - */ -import { __experimentalText as Text } from '@wordpress/components'; - -export default function SidebarNavigationScreenDetailsPanelLabel( { - children, -} ) { - return ( - <Text className="edit-site-sidebar-navigation-details-screen-panel__label"> - { children } - </Text> - ); -} diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/sidebar-navigation-screen-details-panel-row.js b/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/sidebar-navigation-screen-details-panel-row.js deleted file mode 100644 index 1c7f9abafdf503..00000000000000 --- a/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/sidebar-navigation-screen-details-panel-row.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - -/** - * WordPress dependencies - */ -import { __experimentalHStack as HStack } from '@wordpress/components'; - -export default function SidebarNavigationScreenDetailsPanelRow( { - label, - children, - className, - ...extraProps -} ) { - return ( - <HStack - key={ label } - spacing={ 5 } - alignment="left" - className={ clsx( - 'edit-site-sidebar-navigation-details-screen-panel__row', - className - ) } - { ...extraProps } - > - { children } - </HStack> - ); -} diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/sidebar-navigation-screen-details-panel-value.js b/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/sidebar-navigation-screen-details-panel-value.js deleted file mode 100644 index 80e8ba8cf1d538..00000000000000 --- a/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/sidebar-navigation-screen-details-panel-value.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * WordPress dependencies - */ -import { __experimentalText as Text } from '@wordpress/components'; - -export default function SidebarNavigationScreenDetailsPanelValue( { - children, -} ) { - return ( - <Text className="edit-site-sidebar-navigation-details-screen-panel__value"> - { children } - </Text> - ); -} diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/style.scss deleted file mode 100644 index 2757ce5a620c58..00000000000000 --- a/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/style.scss +++ /dev/null @@ -1,26 +0,0 @@ -.edit-site-sidebar-navigation-details-screen-panel { - margin: $grid-unit-30 0; - - &:last-of-type { - margin-bottom: 0; - } - - .edit-site-sidebar-navigation-details-screen-panel__heading { - color: $gray-400; - text-transform: uppercase; - font-weight: 500; - font-size: 11px; - padding: 0; - margin-bottom: 0; - } -} - -.edit-site-sidebar-navigation-details-screen-panel__label.edit-site-sidebar-navigation-details-screen-panel__label { - color: $gray-600; - width: 100px; - flex-shrink: 0; -} - -.edit-site-sidebar-navigation-details-screen-panel__value.edit-site-sidebar-navigation-details-screen-panel__value { - color: $gray-200; -} diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js index 772b15aec2a294..72671714479ac0 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js @@ -86,9 +86,8 @@ export default function SidebarNavigationScreenGlobalStyles() { }, [ openGlobalStyles, setEditorCanvasContainerView ] ); // If there are no revisions, do not render a footer. - const modifiedDateTime = revisions?.[ 0 ]?.modified; const shouldShowGlobalStylesFooter = - revisionsCount > 0 && ! isLoadingRevisions && modifiedDateTime; + !! revisionsCount && ! isLoadingRevisions; return ( <> diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss index 1d57472f7e9f94..959115e0fac8ca 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss @@ -18,7 +18,7 @@ .edit-site-sidebar-navigation-screen__content { padding: 0 $grid-unit-20; - .components-item-group { + .edit-site-sidebar-navigation-screen-details-footer { margin-left: -$grid-unit-20; margin-right: -$grid-unit-20; } @@ -127,9 +127,14 @@ bottom: 0; background-color: $gray-900; gap: 0; - padding: $grid-unit-20 0; + padding: $grid-unit-10 $grid-unit-20; margin: $grid-unit-20 0 0; border-top: 1px solid $gray-800; + + .components-item-group { + margin-left: -$grid-unit-20; + margin-right: -$grid-unit-20; + } } /* In general style overrides are discouraged. diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 63ad8244a7c95e..dce945a48ee700 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -20,7 +20,6 @@ @import "./components/sidebar-navigation-screen/style.scss"; @import "./components/sidebar-navigation-screen-details-footer/style.scss"; @import "./components/sidebar-navigation-screen-navigation-menu/style.scss"; -@import "components/sidebar-navigation-screen-details-panel/style.scss"; @import "./components/sidebar-navigation-screen-patterns/style.scss"; @import "./components/sidebar-dataviews/style.scss"; @import "./components/site-hub/style.scss"; From 726d86a201f0ee19d99a62fd9f4558aa6aa72431 Mon Sep 17 00:00:00 2001 From: Benni <109149472+benniledl@users.noreply.github.com> Date: Tue, 26 Nov 2024 09:37:22 +0100 Subject: [PATCH 1708/1908] Add WordPress 6.7.1 version to "Versions in WordPress" documentation (#67298) Co-authored-by: benniledl <benniledl@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> --- docs/contributors/versions-in-wordpress.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/contributors/versions-in-wordpress.md b/docs/contributors/versions-in-wordpress.md index 4ba7b34da15552..c2be7e3fa4e884 100644 --- a/docs/contributors/versions-in-wordpress.md +++ b/docs/contributors/versions-in-wordpress.md @@ -6,6 +6,7 @@ If anything looks incorrect here, please bring it up in #core-editor in [WordPre | Gutenberg Versions | WordPress Version | | ------------------ | ----------------- | +| 18.6-19.3 | 6.7.1 | | 18.6-19.3 | 6.7 | | 17.8-18.5 | 6.6.2 | | 17.8-18.5 | 6.6.1 | From f7a4f3f054e99e204b76393293fc4775b9596313 Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Tue, 26 Nov 2024 09:58:08 +0100 Subject: [PATCH 1709/1908] Move default template types and template part areas to REST API (#66459) * move default template types and template part areas to REST API * fix logic * fix E2E test * move default template types and template part areas to REST API * fix error * remove not necessary file * fix naming * remove duplicate code * remove duplicated code * improve logic * fix naming * fix unit test * update doc * add unit test for getTemplateInfo function * restore not necessary changes * fix e2e test * remove not necessary variable * replace add_action with add_filter * improve readibility code * make getTemplateInfo private * make templateAreas optional * add default_template_part_areas and default_template_types * move code to rest-api.php file * remove not used import --- lib/compat/wordpress-6.8/preload.php | 2 + lib/compat/wordpress-6.8/rest-api.php | 38 +++ .../use-template-part-area-label.js | 20 +- .../template-part/edit/advanced-controls.js | 26 +- .../edit/utils/get-template-part-icon.js | 20 ++ .../src/template-part/edit/utils/hooks.js | 9 +- .../src/template-part/variations.js | 20 +- packages/core-data/src/entities.js | 2 + .../src/components/add-new-template/utils.js | 4 +- .../src/components/editor/use-editor-title.js | 21 +- .../src/components/page-patterns/header.js | 5 +- .../components/page-patterns/use-patterns.js | 12 +- .../use-template-part-areas.js | 8 +- packages/edit-site/src/index.js | 14 +- .../create-template-part-modal/index.js | 5 +- .../src/components/document-bar/index.js | 13 +- .../entity-record-item.js | 16 +- .../src/components/post-card-panel/index.js | 23 +- packages/editor/src/private-apis.js | 3 +- .../editor/src/store/private-selectors.js | 16 +- packages/editor/src/store/selectors.js | 142 +++++----- packages/editor/src/store/test/selectors.js | 255 ------------------ .../editor/src/utils/get-template-info.js | 52 ++++ .../src/utils/test/get-template-info.js | 224 +++++++++++++++ 24 files changed, 535 insertions(+), 415 deletions(-) create mode 100644 packages/block-library/src/template-part/edit/utils/get-template-part-icon.js create mode 100644 packages/editor/src/utils/get-template-info.js create mode 100644 packages/editor/src/utils/test/get-template-info.js diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php index aabe0d4fb574cc..ae6c738c6627c5 100644 --- a/lib/compat/wordpress-6.8/preload.php +++ b/lib/compat/wordpress-6.8/preload.php @@ -32,6 +32,8 @@ function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { 'site_logo', 'timezone_string', 'url', + 'default_template_part_areas', + 'default_template_types', ) ); $paths[] = '/wp/v2/templates/lookup?slug=front-page'; diff --git a/lib/compat/wordpress-6.8/rest-api.php b/lib/compat/wordpress-6.8/rest-api.php index 080e4003f57b38..b94e42d5f2ccd0 100644 --- a/lib/compat/wordpress-6.8/rest-api.php +++ b/lib/compat/wordpress-6.8/rest-api.php @@ -49,3 +49,41 @@ function ( $taxonomy ) { remove_filter( "rest_{$taxonomy}_query", 'gutenberg_respect_taxonomy_default_args_in_rest_api' ); } ); + +/** + * Adds the default template part areas to the REST API index. + * + * This function exposes the default template part areas through the WordPress REST API. + * Note: This function backports into the wp-includes/rest-api/class-wp-rest-server.php file. + * + * @param WP_REST_Response $response REST API response. + * @return WP_REST_Response Modified REST API response with default template part areas. + */ +function gutenberg_add_default_template_part_areas_to_index( WP_REST_Response $response ) { + $response->data['default_template_part_areas'] = get_allowed_block_template_part_areas(); + return $response; +} + +add_filter( 'rest_index', 'gutenberg_add_default_template_part_areas_to_index' ); + +/** + * Adds the default template types to the REST API index. + * + * This function exposes the default template types through the WordPress REST API. + * Note: This function backports into the wp-includes/rest-api/class-wp-rest-server.php file. + * + * @param WP_REST_Response $response REST API response. + * @return WP_REST_Response Modified REST API response with default template part areas. + */ +function gutenberg_add_default_template_types_to_index( WP_REST_Response $response ) { + $indexed_template_types = array(); + foreach ( get_default_block_template_types() as $slug => $template_type ) { + $template_type['slug'] = (string) $slug; + $indexed_template_types[] = $template_type; + } + + $response->data['default_template_types'] = $indexed_template_types; + return $response; +} + +add_filter( 'rest_index', 'gutenberg_add_default_template_types_to_index' ); diff --git a/packages/block-library/src/navigation/use-template-part-area-label.js b/packages/block-library/src/navigation/use-template-part-area-label.js index 48763a38ac62d1..7b4d514975e113 100644 --- a/packages/block-library/src/navigation/use-template-part-area-label.js +++ b/packages/block-library/src/navigation/use-template-part-area-label.js @@ -11,6 +11,7 @@ import { useSelect } from '@wordpress/data'; // TODO: this util should perhaps be refactored somewhere like core-data. import { createTemplatePartId } from '../template-part/edit/utils/create-template-part-id'; +import { getTemplatePartIcon } from '../template-part/edit/utils/get-template-part-icon'; export default function useTemplatePartAreaLabel( clientId ) { return useSelect( @@ -35,16 +36,15 @@ export default function useTemplatePartAreaLabel( clientId ) { return; } - // FIXME: @wordpress/block-library should not depend on @wordpress/editor. - // Blocks can be loaded into a *non-post* block editor. - // This code is lifted from this file: - // packages/block-library/src/template-part/edit/advanced-controls.js - /* eslint-disable @wordpress/data-no-store-string-literals */ - const definedAreas = - select( - 'core/editor' - ).__experimentalGetDefaultTemplatePartAreas(); - /* eslint-enable @wordpress/data-no-store-string-literals */ + const defaultTemplatePartAreas = + select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.default_template_part_areas || []; + + const definedAreas = defaultTemplatePartAreas.map( ( item ) => ( { + ...item, + icon: getTemplatePartIcon( item.icon ), + } ) ); + const { getCurrentTheme, getEditedEntityRecord } = select( coreStore ); diff --git a/packages/block-library/src/template-part/edit/advanced-controls.js b/packages/block-library/src/template-part/edit/advanced-controls.js index 3c319a7ec0fe73..04c6d3387346ac 100644 --- a/packages/block-library/src/template-part/edit/advanced-controls.js +++ b/packages/block-library/src/template-part/edit/advanced-controls.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { useEntityProp } from '@wordpress/core-data'; +import { useEntityProp, store as coreStore } from '@wordpress/core-data'; import { SelectControl, TextControl } from '@wordpress/components'; import { sprintf, __ } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; @@ -54,19 +54,19 @@ export function TemplatePartAdvancedControls( { templatePartId ); - const definedAreas = useSelect( ( select ) => { - // FIXME: @wordpress/block-library should not depend on @wordpress/editor. - // Blocks can be loaded into a *non-post* block editor. - /* eslint-disable-next-line @wordpress/data-no-store-string-literals */ - return select( - 'core/editor' - ).__experimentalGetDefaultTemplatePartAreas(); - }, [] ); + const defaultTemplatePartAreas = useSelect( + ( select ) => + select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.default_template_part_areas || [], + [] + ); - const areaOptions = definedAreas.map( ( { label, area: _area } ) => ( { - label, - value: _area, - } ) ); + const areaOptions = defaultTemplatePartAreas.map( + ( { label, area: _area } ) => ( { + label, + value: _area, + } ) + ); return ( <> diff --git a/packages/block-library/src/template-part/edit/utils/get-template-part-icon.js b/packages/block-library/src/template-part/edit/utils/get-template-part-icon.js new file mode 100644 index 00000000000000..bb13a8840c9458 --- /dev/null +++ b/packages/block-library/src/template-part/edit/utils/get-template-part-icon.js @@ -0,0 +1,20 @@ +/** + * WordPress dependencies + */ +import { + header as headerIcon, + footer as footerIcon, + sidebar as sidebarIcon, + symbolFilled as symbolFilledIcon, +} from '@wordpress/icons'; + +export const getTemplatePartIcon = ( iconName ) => { + if ( 'header' === iconName ) { + return headerIcon; + } else if ( 'footer' === iconName ) { + return footerIcon; + } else if ( 'sidebar' === iconName ) { + return sidebarIcon; + } + return symbolFilledIcon; +}; diff --git a/packages/block-library/src/template-part/edit/utils/hooks.js b/packages/block-library/src/template-part/edit/utils/hooks.js index 39daa4080c8160..c71327db0290c4 100644 --- a/packages/block-library/src/template-part/edit/utils/hooks.js +++ b/packages/block-library/src/template-part/edit/utils/hooks.js @@ -136,14 +136,9 @@ export function useCreateTemplatePartFromBlocks( area, setAttributes ) { export function useTemplatePartArea( area ) { return useSelect( ( select ) => { - // FIXME: @wordpress/block-library should not depend on @wordpress/editor. - // Blocks can be loaded into a *non-post* block editor. - /* eslint-disable @wordpress/data-no-store-string-literals */ const definedAreas = - select( - 'core/editor' - ).__experimentalGetDefaultTemplatePartAreas(); - /* eslint-enable @wordpress/data-no-store-string-literals */ + select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.default_template_part_areas || []; const selectedArea = definedAreas.find( ( definedArea ) => definedArea.area === area diff --git a/packages/block-library/src/template-part/variations.js b/packages/block-library/src/template-part/variations.js index acd8af13508ba9..6f62057bec33dd 100644 --- a/packages/block-library/src/template-part/variations.js +++ b/packages/block-library/src/template-part/variations.js @@ -3,23 +3,11 @@ */ import { store as coreDataStore } from '@wordpress/core-data'; import { select } from '@wordpress/data'; -import { - header as headerIcon, - footer as footerIcon, - sidebar as sidebarIcon, - symbolFilled as symbolFilledIcon, -} from '@wordpress/icons'; -function getTemplatePartIcon( iconName ) { - if ( 'header' === iconName ) { - return headerIcon; - } else if ( 'footer' === iconName ) { - return footerIcon; - } else if ( 'sidebar' === iconName ) { - return sidebarIcon; - } - return symbolFilledIcon; -} +/** + * Internal dependencies + */ +import { getTemplatePartIcon } from './edit/utils/get-template-part-icon'; export function enhanceTemplatePartVariations( settings, name ) { if ( name !== 'core/template-part' ) { diff --git a/packages/core-data/src/entities.js b/packages/core-data/src/entities.js index 3c10676750a2ab..2730cdf3d64bf4 100644 --- a/packages/core-data/src/entities.js +++ b/packages/core-data/src/entities.js @@ -31,6 +31,8 @@ export const rootEntitiesConfig = [ 'site_icon_url', 'site_logo', 'timezone_string', + 'default_template_part_areas', + 'default_template_types', 'url', ].join( ',' ), }, diff --git a/packages/edit-site/src/components/add-new-template/utils.js b/packages/edit-site/src/components/add-new-template/utils.js index e3e2faf9457926..759f3f478cadaf 100644 --- a/packages/edit-site/src/components/add-new-template/utils.js +++ b/packages/edit-site/src/components/add-new-template/utils.js @@ -3,7 +3,6 @@ */ import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -import { store as editorStore } from '@wordpress/editor'; import { decodeEntities } from '@wordpress/html-entities'; import { useMemo, useCallback } from '@wordpress/element'; import { __, _x, sprintf } from '@wordpress/i18n'; @@ -69,7 +68,8 @@ export const useExistingTemplates = () => { export const useDefaultTemplateTypes = () => { return useSelect( ( select ) => - select( editorStore ).__experimentalGetDefaultTemplateTypes(), + select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.default_template_types || [], [] ); }; diff --git a/packages/edit-site/src/components/editor/use-editor-title.js b/packages/edit-site/src/components/editor/use-editor-title.js index 2ad4e94ccc3e80..727b190117e02a 100644 --- a/packages/edit-site/src/components/editor/use-editor-title.js +++ b/packages/edit-site/src/components/editor/use-editor-title.js @@ -4,33 +4,46 @@ import { _x, sprintf } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -import { store as editorStore } from '@wordpress/editor'; import { decodeEntities } from '@wordpress/html-entities'; +import { privateApis as editorPrivateApis } from '@wordpress/editor'; /** * Internal dependencies */ import useTitle from '../routes/use-title'; import { POST_TYPE_LABELS, TEMPLATE_POST_TYPE } from '../../utils/constants'; +import { unlock } from '../../lock-unlock'; + +const { getTemplateInfo } = unlock( editorPrivateApis ); function useEditorTitle( postType, postId ) { const { title, isLoaded } = useSelect( ( select ) => { const { getEditedEntityRecord, hasFinishedResolution } = select( coreStore ); - const { __experimentalGetTemplateInfo: getTemplateInfo } = - select( editorStore ); + const _record = getEditedEntityRecord( 'postType', postType, postId ); + + const { default_template_types: templateTypes = [] } = + select( coreStore ).getEntityRecord( + 'root', + '__unstableBase' + ) ?? {}; + + const templateInfo = getTemplateInfo( { + template: _record, + templateTypes, + } ); + const _isLoaded = hasFinishedResolution( 'getEditedEntityRecord', [ 'postType', postType, postId, ] ); - const templateInfo = getTemplateInfo( _record ); return { title: templateInfo.title, diff --git a/packages/edit-site/src/components/page-patterns/header.js b/packages/edit-site/src/components/page-patterns/header.js index 641dc577cb7fe0..0d3763aec62c1a 100644 --- a/packages/edit-site/src/components/page-patterns/header.js +++ b/packages/edit-site/src/components/page-patterns/header.js @@ -9,7 +9,7 @@ import { __experimentalText as Text, __experimentalVStack as VStack, } from '@wordpress/components'; -import { store as editorStore } from '@wordpress/editor'; +import { store as coreStore } from '@wordpress/core-data'; import { useSelect } from '@wordpress/data'; import { __, sprintf } from '@wordpress/i18n'; import { moreVertical } from '@wordpress/icons'; @@ -32,7 +32,8 @@ export default function PatternsHeader( { const { patternCategories } = usePatternCategories(); const templatePartAreas = useSelect( ( select ) => - select( editorStore ).__experimentalGetDefaultTemplatePartAreas(), + select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.default_template_part_areas || [], [] ); diff --git a/packages/edit-site/src/components/page-patterns/use-patterns.js b/packages/edit-site/src/components/page-patterns/use-patterns.js index e226298857c4da..3b3e33d5650e63 100644 --- a/packages/edit-site/src/components/page-patterns/use-patterns.js +++ b/packages/edit-site/src/components/page-patterns/use-patterns.js @@ -4,7 +4,6 @@ import { parse } from '@wordpress/blocks'; import { useSelect, createSelector } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -import { store as editorStore } from '@wordpress/editor'; import { useMemo } from '@wordpress/element'; /** @@ -28,8 +27,7 @@ const selectTemplateParts = createSelector( ( select, categoryId, search = '' ) => { const { getEntityRecords, isResolving: isResolvingSelector } = select( coreStore ); - const { __experimentalGetDefaultTemplatePartAreas } = - select( editorStore ); + const query = { per_page: -1 }; const templateParts = getEntityRecords( 'postType', TEMPLATE_PART_POST_TYPE, query ) ?? @@ -38,7 +36,10 @@ const selectTemplateParts = createSelector( // In the case where a custom template part area has been removed we need // the current list of areas to cross check against so orphaned template // parts can be treated as uncategorized. - const knownAreas = __experimentalGetDefaultTemplatePartAreas() || []; + const knownAreas = + select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.default_template_part_areas || []; + const templatePartAreas = knownAreas.map( ( area ) => area.area ); const templatePartHasCategory = ( item, category ) => { @@ -78,7 +79,8 @@ const selectTemplateParts = createSelector( TEMPLATE_PART_POST_TYPE, { per_page: -1 }, ] ), - select( editorStore ).__experimentalGetDefaultTemplatePartAreas(), + select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.default_template_part_areas, ] ); diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-patterns/use-template-part-areas.js b/packages/edit-site/src/components/sidebar-navigation-screen-patterns/use-template-part-areas.js index 77cbf87b3d439e..6a67a8f8a30fb9 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-patterns/use-template-part-areas.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-patterns/use-template-part-areas.js @@ -1,9 +1,8 @@ /** * WordPress dependencies */ -import { useEntityRecords } from '@wordpress/core-data'; +import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; import { useSelect } from '@wordpress/data'; -import { store as editorStore } from '@wordpress/editor'; /** * Internal dependencies @@ -18,7 +17,8 @@ const useTemplatePartsGroupedByArea = ( items ) => { const templatePartAreas = useSelect( ( select ) => - select( editorStore ).__experimentalGetDefaultTemplatePartAreas(), + select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.default_template_part_areas || [], [] ); @@ -43,7 +43,7 @@ const useTemplatePartsGroupedByArea = ( items ) => { const key = accumulator[ item.area ] ? item.area : TEMPLATE_PART_AREA_DEFAULT_CATEGORY; - accumulator[ key ].templateParts.push( item ); + accumulator[ key ]?.templateParts?.push( item ); return accumulator; }, knownAreas ); diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 7f124e6b5f7ac6..b96ce5cb67f5e1 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -10,10 +10,7 @@ import { import { dispatch } from '@wordpress/data'; import deprecated from '@wordpress/deprecated'; import { createRoot, StrictMode } from '@wordpress/element'; -import { - store as editorStore, - privateApis as editorPrivateApis, -} from '@wordpress/editor'; +import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { store as preferencesStore } from '@wordpress/preferences'; import { registerLegacyWidgetBlock, @@ -88,15 +85,6 @@ export function initializeEditor( id, settings ) { dispatch( editSiteStore ).updateSettings( settings ); - // Keep the defaultTemplateTypes in the core/editor settings too, - // so that they can be selected with core/editor selectors in any editor. - // This is needed because edit-site doesn't initialize with EditorProvider, - // which internally uses updateEditorSettings as well. - dispatch( editorStore ).updateEditorSettings( { - defaultTemplateTypes: settings.defaultTemplateTypes, - defaultTemplatePartAreas: settings.defaultTemplatePartAreas, - } ); - // Prevent the default browser action for files dropped outside of dropzones. window.addEventListener( 'dragover', ( e ) => e.preventDefault(), false ); window.addEventListener( 'drop', ( e ) => e.preventDefault(), false ); diff --git a/packages/editor/src/components/create-template-part-modal/index.js b/packages/editor/src/components/create-template-part-modal/index.js index 5d594cd646cc10..660439ded2300f 100644 --- a/packages/editor/src/components/create-template-part-modal/index.js +++ b/packages/editor/src/components/create-template-part-modal/index.js @@ -27,7 +27,6 @@ import { serialize } from '@wordpress/blocks'; /** * Internal dependencies */ -import { store as editorStore } from '../../store'; import { TEMPLATE_PART_POST_TYPE, TEMPLATE_PART_AREA_DEFAULT_CATEGORY, @@ -81,9 +80,11 @@ export function CreateTemplatePartModalContents( { const templatePartAreas = useSelect( ( select ) => - select( editorStore ).__experimentalGetDefaultTemplatePartAreas(), + select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.default_template_part_areas || [], [] ); + async function createTemplatePart() { if ( ! title || isSubmitting ) { return; diff --git a/packages/editor/src/components/document-bar/index.js b/packages/editor/src/components/document-bar/index.js index 9fffba941a4355..7b94a6fbeb3be9 100644 --- a/packages/editor/src/components/document-bar/index.js +++ b/packages/editor/src/components/document-bar/index.js @@ -29,6 +29,7 @@ import { decodeEntities } from '@wordpress/html-entities'; import { TEMPLATE_POST_TYPES } from '../../store/constants'; import { store as editorStore } from '../../store'; import usePageTypeBadge from '../../utils/pageTypeBadge'; +import { getTemplateInfo } from '../../utils/get-template-info'; /** @typedef {import("@wordpress/components").IconType} IconType */ @@ -65,9 +66,9 @@ export default function DocumentBar( props ) { getCurrentPostType, getCurrentPostId, getEditorSettings, - __experimentalGetTemplateInfo: getTemplateInfo, getRenderingMode, } = select( editorStore ); + const { getEditedEntityRecord, getPostType, @@ -80,7 +81,15 @@ export default function DocumentBar( props ) { _postType, _postId ); - const _templateInfo = getTemplateInfo( _document ); + + const { default_template_types: templateTypes = [] } = + select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) ?? + {}; + + const _templateInfo = getTemplateInfo( { + templateTypes, + template: _document, + } ); const _postTypeLabel = getPostType( _postType )?.labels?.singular_name; return { diff --git a/packages/editor/src/components/entities-saved-states/entity-record-item.js b/packages/editor/src/components/entities-saved-states/entity-record-item.js index ca9fb2e0b169c3..e8219c4cca7ae1 100644 --- a/packages/editor/src/components/entities-saved-states/entity-record-item.js +++ b/packages/editor/src/components/entities-saved-states/entity-record-item.js @@ -12,6 +12,7 @@ import { decodeEntities } from '@wordpress/html-entities'; */ import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; +import { getTemplateInfo } from '../../utils/get-template-info'; export default function EntityRecordItem( { record, checked, onChange } ) { const { name, kind, title, key } = record; @@ -33,11 +34,18 @@ export default function EntityRecordItem( { record, checked, onChange } ) { name, key ); + + const { default_template_types: templateTypes = [] } = + select( coreStore ).getEntityRecord( + 'root', + '__unstableBase' + ) ?? {}; + return { - entityRecordTitle: - select( editorStore ).__experimentalGetTemplateInfo( - template - ).title, + entityRecordTitle: getTemplateInfo( { + template, + templateTypes, + } ).title, hasPostMetaChanges: unlock( select( editorStore ) ).hasPostMetaChanges( name, key ), diff --git a/packages/editor/src/components/post-card-panel/index.js b/packages/editor/src/components/post-card-panel/index.js index 410b8cfd4447d9..8fcca6c6bd6d40 100644 --- a/packages/editor/src/components/post-card-panel/index.js +++ b/packages/editor/src/components/post-card-panel/index.js @@ -22,6 +22,7 @@ import { import { unlock } from '../../lock-unlock'; import PostActions from '../post-actions'; import usePageTypeBadge from '../../utils/pageTypeBadge'; +import { getTemplateInfo } from '../../utils/get-template-info'; export default function PostCardPanel( { postType, @@ -30,17 +31,29 @@ export default function PostCardPanel( { } ) { const { title, icon } = useSelect( ( select ) => { - const { __experimentalGetTemplateInfo } = select( editorStore ); const { getEditedEntityRecord } = select( coreStore ); const _record = getEditedEntityRecord( 'postType', postType, postId ); - const _templateInfo = - [ TEMPLATE_POST_TYPE, TEMPLATE_PART_POST_TYPE ].includes( - postType - ) && __experimentalGetTemplateInfo( _record ); + + const { default_template_types: templateTypes = [] } = + select( coreStore ).getEntityRecord( + 'root', + '__unstableBase' + ) ?? {}; + + const _templateInfo = [ + TEMPLATE_POST_TYPE, + TEMPLATE_PART_POST_TYPE, + ].includes( postType ) + ? getTemplateInfo( { + template: _record, + templateTypes, + } ) + : {}; + return { title: _templateInfo?.title || _record?.title, icon: unlock( select( editorStore ) ).getPostIcon( postType, { diff --git a/packages/editor/src/private-apis.js b/packages/editor/src/private-apis.js index b49b2a69a3bf2b..2699858b3164f6 100644 --- a/packages/editor/src/private-apis.js +++ b/packages/editor/src/private-apis.js @@ -25,6 +25,7 @@ import { GlobalStylesProvider, } from './components/global-styles-provider'; import { registerCoreBlockBindingsSources } from './bindings/api'; +import { getTemplateInfo } from './utils/get-template-info'; const { store: interfaceStore, ...remainingInterfaceApis } = interfaceApis; @@ -46,7 +47,7 @@ lock( privateApis, { ViewMoreMenuGroup, ResizableEditor, registerCoreBlockBindingsSources, - + getTemplateInfo, // This is a temporary private API while we're updating the site editor to use EditorProvider. interfaceStore, ...remainingInterfaceApis, diff --git a/packages/editor/src/store/private-selectors.js b/packages/editor/src/store/private-selectors.js index 9af0512c19dbdd..56fa6728371489 100644 --- a/packages/editor/src/store/private-selectors.js +++ b/packages/editor/src/store/private-selectors.js @@ -20,11 +20,7 @@ import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies */ -import { - getRenderingMode, - getCurrentPost, - __experimentalGetDefaultTemplatePartAreas, -} from './selectors'; +import { getRenderingMode, getCurrentPost } from './selectors'; import { getEntityActions as _getEntityActions, getEntityFields as _getEntityFields, @@ -102,9 +98,13 @@ export const getPostIcon = createRegistrySelector( postType === 'wp_template' ) { return ( - __experimentalGetDefaultTemplatePartAreas( state ).find( - ( item ) => options.area === item.area - )?.icon || layout + ( + select( coreStore ).getEntityRecord( + 'root', + '__unstableBase' + )?.default_template_part_areas || [] + ).find( ( item ) => options.area === item.area )?.icon || + layout ); } if ( CARD_ICONS[ postType ] ) { diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index db452be5c17abb..c17e80f771ea36 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -12,7 +12,6 @@ import { addQueryArgs, cleanForSlug } from '@wordpress/url'; import { createSelector, createRegistrySelector } from '@wordpress/data'; import deprecated from '@wordpress/deprecated'; import { Platform } from '@wordpress/element'; -import { layout } from '@wordpress/icons'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { store as coreStore } from '@wordpress/core-data'; import { store as preferencesStore } from '@wordpress/preferences'; @@ -29,6 +28,7 @@ import { import { getPostRawValue } from './reducer'; import { getTemplatePartIcon } from '../utils/get-template-part-icon'; import { unlock } from '../lock-unlock'; +import { getTemplateInfo } from '../utils/get-template-info'; /** * Shared reference to an empty object for cases where it is important to avoid @@ -1702,16 +1702,20 @@ export const getBlockListSettings = getBlockEditorSelector( 'getBlockListSettings' ); -/** - * Returns the default template types. - * - * @param {Object} state Global application state. - * - * @return {Object} The template types. - */ -export function __experimentalGetDefaultTemplateTypes( state ) { - return getEditorSettings( state )?.defaultTemplateTypes; -} +export const __experimentalGetDefaultTemplateTypes = createRegistrySelector( + ( select ) => () => { + deprecated( + "select('core/editor').__experimentalGetDefaultTemplateTypes", + { + since: '6.7', + alternative: + "select('core/core-data').getEntityRecord( 'root', '__unstableBase' )?.default_template_types", + } + ); + return select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.default_template_types; + } +); /** * Returns the default template part areas. @@ -1720,15 +1724,26 @@ export function __experimentalGetDefaultTemplateTypes( state ) { * * @return {Array} The template part areas. */ -export const __experimentalGetDefaultTemplatePartAreas = createSelector( - ( state ) => { - const areas = - getEditorSettings( state )?.defaultTemplatePartAreas ?? []; - return areas.map( ( item ) => { - return { ...item, icon: getTemplatePartIcon( item.icon ) }; - } ); - }, - ( state ) => [ getEditorSettings( state )?.defaultTemplatePartAreas ] +export const __experimentalGetDefaultTemplatePartAreas = createRegistrySelector( + ( select ) => + createSelector( () => { + deprecated( + "select('core/editor').__experimentalGetDefaultTemplatePartAreas", + { + since: '6.7', + alternative: + "select('core/core-data').getEntityRecord( 'root', '__unstableBase' )?.default_template_part_areas", + } + ); + + const areas = + select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.default_template_part_areas || []; + + return areas.map( ( item ) => { + return { ...item, icon: getTemplatePartIcon( item.icon ) }; + } ); + } ) ); /** @@ -1739,20 +1754,30 @@ export const __experimentalGetDefaultTemplatePartAreas = createSelector( * * @return {Object} The template type. */ -export const __experimentalGetDefaultTemplateType = createSelector( - ( state, slug ) => { - const templateTypes = __experimentalGetDefaultTemplateTypes( state ); - if ( ! templateTypes ) { - return EMPTY_OBJECT; - } +export const __experimentalGetDefaultTemplateType = createRegistrySelector( + ( select ) => + createSelector( ( state, slug ) => { + deprecated( + "select('core/editor').__experimentalGetDefaultTemplateType", + { + since: '6.7', + } + ); + const templateTypes = select( coreStore ).getEntityRecord( + 'root', + '__unstableBase' + )?.default_template_types; + + if ( ! templateTypes ) { + return EMPTY_OBJECT; + } - return ( - Object.values( templateTypes ).find( - ( type ) => type.slug === slug - ) ?? EMPTY_OBJECT - ); - }, - ( state ) => [ __experimentalGetDefaultTemplateTypes( state ) ] + return ( + Object.values( templateTypes ).find( + ( type ) => type.slug === slug + ) ?? EMPTY_OBJECT + ); + } ) ); /** @@ -1763,38 +1788,31 @@ export const __experimentalGetDefaultTemplateType = createSelector( * @param {Object} template The template for which we need information. * @return {Object} Information about the template, including title, description, and icon. */ -export const __experimentalGetTemplateInfo = createSelector( - ( state, template ) => { - if ( ! template ) { - return EMPTY_OBJECT; - } +export const __experimentalGetTemplateInfo = createRegistrySelector( + ( select ) => + createSelector( ( state, template ) => { + deprecated( "select('core/editor').__experimentalGetTemplateInfo", { + since: '6.7', + } ); - const { description, slug, title, area } = template; - const { title: defaultTitle, description: defaultDescription } = - __experimentalGetDefaultTemplateType( state, slug ); + if ( ! template ) { + return EMPTY_OBJECT; + } - const templateTitle = - typeof title === 'string' ? title : title?.rendered; - const templateDescription = - typeof description === 'string' ? description : description?.raw; - const templateIcon = - __experimentalGetDefaultTemplatePartAreas( state ).find( - ( item ) => area === item.area - )?.icon || layout; + const templateTypes = + select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.default_template_types || []; - return { - title: - templateTitle && templateTitle !== slug - ? templateTitle - : defaultTitle || slug, - description: templateDescription || defaultDescription, - icon: templateIcon, - }; - }, - ( state ) => [ - __experimentalGetDefaultTemplateTypes( state ), - __experimentalGetDefaultTemplatePartAreas( state ), - ] + const templateAreas = + select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) + ?.default_template_part_areas || []; + + return getTemplateInfo( { + template, + templateAreas, + templateTypes, + } ); + } ) ); /** diff --git a/packages/editor/src/store/test/selectors.js b/packages/editor/src/store/test/selectors.js index 1de25604ebd7e3..2a36fabcd2ec97 100644 --- a/packages/editor/src/store/test/selectors.js +++ b/packages/editor/src/store/test/selectors.js @@ -16,7 +16,6 @@ import { getBlockTypes, } from '@wordpress/blocks'; import { RawHTML } from '@wordpress/element'; -import { layout, footer, header } from '@wordpress/icons'; /** * Internal dependencies @@ -188,43 +187,11 @@ const { isPostAutosavingLocked, canUserUseUnfilteredHTML, getPostTypeLabel, - __experimentalGetDefaultTemplateType, - __experimentalGetDefaultTemplateTypes, - __experimentalGetTemplateInfo, - __experimentalGetDefaultTemplatePartAreas, isEditorPanelRemoved, isInserterOpened, isListViewOpened, } = selectors; -const defaultTemplateTypes = [ - { - title: 'Default (Index)', - description: 'Main template', - slug: 'index', - }, - { - title: '404 (Not Found)', - description: 'Applied when content cannot be found', - slug: '404', - }, -]; - -const defaultTemplatePartAreas = [ - { - area: 'header', - label: 'Header', - description: 'Some description of a header', - icon: 'header', - }, - { - area: 'footer', - label: 'Footer', - description: 'Some description of a footer', - icon: 'footer', - }, -]; - describe( 'selectors', () => { let cachedSelectors; @@ -2766,228 +2733,6 @@ describe( 'selectors', () => { } ); } ); - describe( '__experimentalGetDefaultTemplateTypes', () => { - const state = { editorSettings: { defaultTemplateTypes } }; - - it( 'returns undefined if there are no default template types', () => { - const emptyState = { editorSettings: {} }; - expect( - __experimentalGetDefaultTemplateTypes( emptyState ) - ).toBeUndefined(); - } ); - - it( 'returns a list of default template types if present in state', () => { - expect( - __experimentalGetDefaultTemplateTypes( state ) - ).toHaveLength( 2 ); - } ); - } ); - - describe( '__experimentalGetDefaultTemplatePartAreas', () => { - const state = { editorSettings: { defaultTemplatePartAreas } }; - - it( 'returns empty array if there are no default template part areas', () => { - const emptyState = { editorSettings: {} }; - expect( - __experimentalGetDefaultTemplatePartAreas( emptyState ) - ).toHaveLength( 0 ); - } ); - - it( 'returns a list of default template part areas if present in state', () => { - expect( - __experimentalGetDefaultTemplatePartAreas( state ) - ).toHaveLength( 2 ); - } ); - - it( 'assigns an icon to each area', () => { - const templatePartAreas = - __experimentalGetDefaultTemplatePartAreas( state ); - templatePartAreas.forEach( ( area ) => - expect( area.icon ).not.toBeNull() - ); - } ); - } ); - - describe( '__experimentalGetDefaultTemplateType', () => { - const state = { editorSettings: { defaultTemplateTypes } }; - - it( 'returns an empty object if there are no default template types', () => { - const emptyState = { editorSettings: {} }; - expect( - __experimentalGetDefaultTemplateType( emptyState, 'slug' ) - ).toEqual( {} ); - } ); - - it( 'returns an empty object if the requested slug is not found', () => { - expect( - __experimentalGetDefaultTemplateType( state, 'foobar' ) - ).toEqual( {} ); - } ); - - it( 'returns the requested default template type', () => { - expect( - __experimentalGetDefaultTemplateType( state, 'index' ) - ).toEqual( { - title: 'Default (Index)', - description: 'Main template', - slug: 'index', - } ); - } ); - - it( 'returns the requested default template type even when the slug is numeric', () => { - expect( - __experimentalGetDefaultTemplateType( state, '404' ) - ).toEqual( { - title: '404 (Not Found)', - description: 'Applied when content cannot be found', - slug: '404', - } ); - } ); - } ); - - describe( '__experimentalGetTemplateInfo', () => { - const state = { - editorSettings: { defaultTemplateTypes, defaultTemplatePartAreas }, - }; - - it( 'should return an empty object if no template is passed', () => { - expect( __experimentalGetTemplateInfo( state, null ) ).toEqual( - {} - ); - expect( __experimentalGetTemplateInfo( state, undefined ) ).toEqual( - {} - ); - expect( __experimentalGetTemplateInfo( state, false ) ).toEqual( - {} - ); - } ); - - it( 'should return the default title if none is defined on the template', () => { - expect( - __experimentalGetTemplateInfo( state, { slug: 'index' } ).title - ).toEqual( 'Default (Index)' ); - } ); - - it( 'should return the rendered title if defined on the template', () => { - expect( - __experimentalGetTemplateInfo( state, { - slug: 'index', - title: { rendered: 'test title' }, - } ).title - ).toEqual( 'test title' ); - } ); - - it( 'should return the slug if no title is found', () => { - expect( - __experimentalGetTemplateInfo( state, { - slug: 'not a real template', - } ).title - ).toEqual( 'not a real template' ); - } ); - - it( 'should return the default description if none is defined on the template', () => { - expect( - __experimentalGetTemplateInfo( state, { slug: 'index' } ) - .description - ).toEqual( 'Main template' ); - } ); - - it( 'should return the raw excerpt as description if defined on the template', () => { - expect( - __experimentalGetTemplateInfo( state, { - slug: 'index', - description: { raw: 'test description' }, - } ).description - ).toEqual( 'test description' ); - } ); - - it( 'should return a title, description, and icon', () => { - expect( - __experimentalGetTemplateInfo( state, { slug: 'index' } ) - ).toEqual( { - title: 'Default (Index)', - description: 'Main template', - icon: layout, - } ); - - expect( - __experimentalGetTemplateInfo( state, { - slug: 'index', - title: { rendered: 'test title' }, - } ) - ).toEqual( { - title: 'test title', - description: 'Main template', - icon: layout, - } ); - - expect( - __experimentalGetTemplateInfo( state, { - slug: 'index', - description: { raw: 'test description' }, - } ) - ).toEqual( { - title: 'Default (Index)', - description: 'test description', - icon: layout, - } ); - - expect( - __experimentalGetTemplateInfo( state, { - slug: 'index', - title: { rendered: 'test title' }, - description: { raw: 'test description' }, - } ) - ).toEqual( { - title: 'test title', - description: 'test description', - icon: layout, - } ); - } ); - - it( 'should return correct icon based on area', () => { - expect( - __experimentalGetTemplateInfo( state, { - slug: 'template part, area = uncategorized', - area: 'uncategorized', - } ) - ).toEqual( { - title: 'template part, area = uncategorized', - icon: layout, - } ); - - expect( - __experimentalGetTemplateInfo( state, { - slug: 'template part, area = invalid', - area: 'invalid', - } ) - ).toEqual( { - title: 'template part, area = invalid', - icon: layout, - } ); - - expect( - __experimentalGetTemplateInfo( state, { - slug: 'template part, area = header', - area: 'header', - } ) - ).toEqual( { - title: 'template part, area = header', - icon: header, - } ); - - expect( - __experimentalGetTemplateInfo( state, { - slug: 'template part, area = footer', - area: 'footer', - } ) - ).toEqual( { - title: 'template part, area = footer', - icon: footer, - } ); - } ); - } ); - describe( 'getPostTypeLabel', () => { it( 'should return the correct label for the current post type', () => { const postTypes = [ diff --git a/packages/editor/src/utils/get-template-info.js b/packages/editor/src/utils/get-template-info.js new file mode 100644 index 00000000000000..bc84c06c9399d4 --- /dev/null +++ b/packages/editor/src/utils/get-template-info.js @@ -0,0 +1,52 @@ +/** + * WordPress dependencies + */ +import { layout } from '@wordpress/icons'; +/** + * Internal dependencies + */ +import { getTemplatePartIcon } from './get-template-part-icon'; +const EMPTY_OBJECT = {}; + +/** + * Helper function to retrieve the corresponding template info for a given template. + * @param {Object} params + * @param {Array} params.templateTypes + * @param {Array} [params.templateAreas] + * @param {Object} params.template + */ +export const getTemplateInfo = ( params ) => { + if ( ! params ) { + return EMPTY_OBJECT; + } + + const { templateTypes, templateAreas, template } = params; + + const { description, slug, title, area } = template; + + const { title: defaultTitle, description: defaultDescription } = + Object.values( templateTypes ).find( ( type ) => type.slug === slug ) ?? + EMPTY_OBJECT; + + const templateTitle = typeof title === 'string' ? title : title?.rendered; + const templateDescription = + typeof description === 'string' ? description : description?.raw; + + const templateAreasWithIcon = templateAreas?.map( ( item ) => ( { + ...item, + icon: getTemplatePartIcon( item.icon ), + } ) ); + + const templateIcon = + templateAreasWithIcon?.find( ( item ) => area === item.area )?.icon || + layout; + + return { + title: + templateTitle && templateTitle !== slug + ? templateTitle + : defaultTitle || slug, + description: templateDescription || defaultDescription, + icon: templateIcon, + }; +}; diff --git a/packages/editor/src/utils/test/get-template-info.js b/packages/editor/src/utils/test/get-template-info.js new file mode 100644 index 00000000000000..d0ffe15aa902ad --- /dev/null +++ b/packages/editor/src/utils/test/get-template-info.js @@ -0,0 +1,224 @@ +/** + * WordPress dependencies + */ +import { footer, header, layout } from '@wordpress/icons'; +/** + * Internal dependencies + */ +import { getTemplateInfo } from '../get-template-info'; + +describe( '__experimentalGetTemplateInfo', () => { + const defaultTemplateTypes = [ + { + title: 'Default (Index)', + description: 'Main template', + slug: 'index', + }, + { + title: '404 (Not Found)', + description: 'Applied when content cannot be found', + slug: '404', + }, + ]; + + const defaultTemplatePartAreas = [ + { + area: 'header', + label: 'Header', + description: 'Some description of a header', + icon: 'header', + }, + { + area: 'footer', + label: 'Footer', + description: 'Some description of a footer', + icon: 'footer', + }, + ]; + + it( 'should return an empty object if no template is passed', () => { + expect( getTemplateInfo( undefined ) ).toEqual( {} ); + expect( getTemplateInfo( null ) ).toEqual( {} ); + expect( getTemplateInfo( false ) ).toEqual( {} ); + } ); + + it( 'should return the default title if none is defined on the template', () => { + expect( + getTemplateInfo( { + templateAreas: defaultTemplatePartAreas, + templateTypes: defaultTemplateTypes, + template: { + slug: 'index', + }, + } ).title + ).toEqual( 'Default (Index)' ); + } ); + + it( 'should return the rendered title if defined on the template', () => { + expect( + getTemplateInfo( { + templateAreas: defaultTemplatePartAreas, + templateTypes: defaultTemplateTypes, + template: { + slug: 'index', + title: { rendered: 'test title' }, + }, + } ).title + ).toEqual( 'test title' ); + } ); + + it( 'should return the slug if no title is found', () => { + expect( + getTemplateInfo( { + templateAreas: defaultTemplatePartAreas, + templateTypes: defaultTemplateTypes, + template: { + slug: 'not a real template', + }, + } ).title + ).toEqual( 'not a real template' ); + } ); + + it( 'should return the default description if none is defined on the template', () => { + expect( + getTemplateInfo( { + templateAreas: defaultTemplatePartAreas, + templateTypes: defaultTemplateTypes, + template: { + slug: 'index', + }, + } ).description + ).toEqual( 'Main template' ); + } ); + + it( 'should return the raw excerpt as description if defined on the template', () => { + expect( + getTemplateInfo( { + templateAreas: defaultTemplatePartAreas, + templateTypes: defaultTemplateTypes, + template: { + slug: 'index', + description: { raw: 'test description' }, + }, + } ).description + ).toEqual( 'test description' ); + } ); + + it( 'should return a title, description, and icon', () => { + expect( + getTemplateInfo( { + templateAreas: defaultTemplatePartAreas, + templateTypes: defaultTemplateTypes, + template: { slug: 'index' }, + } ) + ).toEqual( { + title: 'Default (Index)', + description: 'Main template', + icon: layout, + } ); + + expect( + getTemplateInfo( { + templateAreas: defaultTemplatePartAreas, + templateTypes: defaultTemplateTypes, + template: { + slug: 'index', + title: { rendered: 'test title' }, + }, + } ) + ).toEqual( { + title: 'test title', + description: 'Main template', + icon: layout, + } ); + + expect( + getTemplateInfo( { + templateAreas: defaultTemplatePartAreas, + templateTypes: defaultTemplateTypes, + template: { + slug: 'index', + description: { raw: 'test description' }, + }, + } ) + ).toEqual( { + title: 'Default (Index)', + description: 'test description', + icon: layout, + } ); + + expect( + getTemplateInfo( { + templateAreas: defaultTemplatePartAreas, + templateTypes: defaultTemplateTypes, + template: { + slug: 'index', + title: { rendered: 'test title' }, + description: { raw: 'test description' }, + }, + } ) + ).toEqual( { + title: 'test title', + description: 'test description', + icon: layout, + } ); + } ); + + it( 'should return correct icon based on area', () => { + expect( + getTemplateInfo( { + templateAreas: defaultTemplatePartAreas, + templateTypes: defaultTemplateTypes, + template: { + slug: 'template part, area = uncategorized', + area: 'uncategorized', + }, + } ) + ).toEqual( { + title: 'template part, area = uncategorized', + icon: layout, + } ); + + expect( + getTemplateInfo( { + templateAreas: defaultTemplatePartAreas, + templateTypes: defaultTemplateTypes, + template: { + slug: 'template part, area = invalid', + area: 'invalid', + }, + } ) + ).toEqual( { + title: 'template part, area = invalid', + icon: layout, + } ); + + expect( + getTemplateInfo( { + templateAreas: defaultTemplatePartAreas, + templateTypes: defaultTemplateTypes, + template: { + slug: 'template part, area = header', + area: 'header', + }, + } ) + ).toEqual( { + title: 'template part, area = header', + icon: header, + } ); + + expect( + getTemplateInfo( { + templateAreas: defaultTemplatePartAreas, + templateTypes: defaultTemplateTypes, + template: { + slug: 'template part, area = footer', + area: 'footer', + }, + } ) + ).toEqual( { + title: 'template part, area = footer', + icon: footer, + } ); + } ); +} ); From ddd239ab921f51835938b10aacd33bd933cccd1f Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 26 Nov 2024 14:02:36 +0400 Subject: [PATCH 1710/1908] Block Editor: Correctly mark Block Comment SlotFills private (#67271) * Block Editor: Correctly mark Block Comment SlotFills private * Drop '__unstable' prefix * Simplify private API exports Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- .../block-settings-menu/block-settings-dropdown.js | 4 ++-- .../src/components/block-settings-menu/index.js | 4 ++-- .../src/components/collab/block-comment-icon-slot.js | 8 ++------ .../components/collab/block-comment-icon-toolbar-slot.js | 8 +++----- packages/block-editor/src/private-apis.js | 8 ++++---- .../components/collab-sidebar/comment-button-toolbar.js | 6 +++--- .../src/components/collab-sidebar/comment-button.js | 6 +++--- 7 files changed, 19 insertions(+), 25 deletions(-) diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index 5b5360cc48a8fe..a0bbb6c708fea1 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -19,7 +19,7 @@ import { pipe, useCopyToClipboard } from '@wordpress/compose'; * Internal dependencies */ import BlockActions from '../block-actions'; -import __unstableCommentIconFill from '../../components/collab/block-comment-icon-slot'; +import CommentIconSlotFill from '../../components/collab/block-comment-icon-slot'; import BlockHTMLConvertButton from './block-html-convert-button'; import __unstableBlockSettingsMenuFirstItem from './block-settings-menu-first-item'; import BlockSettingsMenuControls from '../block-settings-menu-controls'; @@ -295,7 +295,7 @@ export function BlockSettingsDropdown( { </MenuItem> </> ) } - <__unstableCommentIconFill.Slot + <CommentIconSlotFill.Slot fillProps={ { onClose } } /> </MenuGroup> diff --git a/packages/block-editor/src/components/block-settings-menu/index.js b/packages/block-editor/src/components/block-settings-menu/index.js index 50e8abe09d018b..1b96f30e130386 100644 --- a/packages/block-editor/src/components/block-settings-menu/index.js +++ b/packages/block-editor/src/components/block-settings-menu/index.js @@ -7,12 +7,12 @@ import { ToolbarGroup, ToolbarItem } from '@wordpress/components'; * Internal dependencies */ import BlockSettingsDropdown from './block-settings-dropdown'; -import __unstableCommentIconToolbarFill from '../../components/collab/block-comment-icon-toolbar-slot'; +import CommentIconToolbarSlotFill from '../../components/collab/block-comment-icon-toolbar-slot'; export function BlockSettingsMenu( { clientIds, ...props } ) { return ( <ToolbarGroup> - <__unstableCommentIconToolbarFill.Slot /> + <CommentIconToolbarSlotFill.Slot /> <ToolbarItem> { ( toggleProps ) => ( diff --git a/packages/block-editor/src/components/collab/block-comment-icon-slot.js b/packages/block-editor/src/components/collab/block-comment-icon-slot.js index 600db904b28741..bcf8c5f5ff0c5b 100644 --- a/packages/block-editor/src/components/collab/block-comment-icon-slot.js +++ b/packages/block-editor/src/components/collab/block-comment-icon-slot.js @@ -3,10 +3,6 @@ */ import { createSlotFill } from '@wordpress/components'; -const { Fill: __unstableCommentIconFill, Slot } = createSlotFill( - '__unstableCommentIconFill' -); +const CommentIconSlotFill = createSlotFill( Symbol( 'CommentIconSlotFill' ) ); -__unstableCommentIconFill.Slot = Slot; - -export default __unstableCommentIconFill; +export default CommentIconSlotFill; diff --git a/packages/block-editor/src/components/collab/block-comment-icon-toolbar-slot.js b/packages/block-editor/src/components/collab/block-comment-icon-toolbar-slot.js index dd84b284f082ae..056b9a2623262f 100644 --- a/packages/block-editor/src/components/collab/block-comment-icon-toolbar-slot.js +++ b/packages/block-editor/src/components/collab/block-comment-icon-toolbar-slot.js @@ -3,10 +3,8 @@ */ import { createSlotFill } from '@wordpress/components'; -const { Fill: __unstableCommentIconToolbarFill, Slot } = createSlotFill( - '__unstableCommentIconToolbarFill' +const CommentIconToolbarSlotFill = createSlotFill( + Symbol( 'CommentIconToolbarSlotFill' ) ); -__unstableCommentIconToolbarFill.Slot = Slot; - -export default __unstableCommentIconToolbarFill; +export default CommentIconToolbarSlotFill; diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 0faee244e387c2..2ca185823f15e1 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -49,8 +49,8 @@ import { PrivatePublishDateTimePicker } from './components/publish-date-time-pic import useSpacingSizes from './components/spacing-sizes-control/hooks/use-spacing-sizes'; import useBlockDisplayTitle from './components/block-title/use-block-display-title'; import TabbedSidebar from './components/tabbed-sidebar'; -import __unstableCommentIconFill from './components/collab/block-comment-icon-slot'; -import __unstableCommentIconToolbarFill from './components/collab/block-comment-icon-toolbar-slot'; +import CommentIconSlotFill from './components/collab/block-comment-icon-slot'; +import CommentIconToolbarSlotFill from './components/collab/block-comment-icon-toolbar-slot'; /** * Private @wordpress/block-editor APIs. */ @@ -97,6 +97,6 @@ lock( privateApis, { __unstableBlockStyleVariationOverridesWithConfig, setBackgroundStyleDefaults, sectionRootClientIdKey, - __unstableCommentIconFill, - __unstableCommentIconToolbarFill, + CommentIconSlotFill, + CommentIconToolbarSlotFill, } ); diff --git a/packages/editor/src/components/collab-sidebar/comment-button-toolbar.js b/packages/editor/src/components/collab-sidebar/comment-button-toolbar.js index 2e378a7eaabab0..b673ee87fe86ce 100644 --- a/packages/editor/src/components/collab-sidebar/comment-button-toolbar.js +++ b/packages/editor/src/components/collab-sidebar/comment-button-toolbar.js @@ -11,18 +11,18 @@ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; */ import { unlock } from '../../lock-unlock'; -const { __unstableCommentIconToolbarFill } = unlock( blockEditorPrivateApis ); +const { CommentIconToolbarSlotFill } = unlock( blockEditorPrivateApis ); const AddCommentToolbarButton = ( { onClick } ) => { return ( - <__unstableCommentIconToolbarFill> + <CommentIconToolbarSlotFill.Fill> <ToolbarButton accessibleWhenDisabled icon={ commentIcon } label={ _x( 'Comment', 'View comment' ) } onClick={ onClick } /> - </__unstableCommentIconToolbarFill> + </CommentIconToolbarSlotFill.Fill> ); }; diff --git a/packages/editor/src/components/collab-sidebar/comment-button.js b/packages/editor/src/components/collab-sidebar/comment-button.js index 3b020661816660..373ee0becd92df 100644 --- a/packages/editor/src/components/collab-sidebar/comment-button.js +++ b/packages/editor/src/components/collab-sidebar/comment-button.js @@ -12,11 +12,11 @@ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; */ import { unlock } from '../../lock-unlock'; -const { __unstableCommentIconFill } = unlock( blockEditorPrivateApis ); +const { CommentIconSlotFill } = unlock( blockEditorPrivateApis ); const AddCommentButton = ( { onClick } ) => { return ( - <__unstableCommentIconFill> + <CommentIconSlotFill.Fill> <MenuItem icon={ commentIcon } onClick={ onClick } @@ -24,7 +24,7 @@ const AddCommentButton = ( { onClick } ) => { > { _x( 'Comment', 'Add comment button' ) } </MenuItem> - </__unstableCommentIconFill> + </CommentIconSlotFill.Fill> ); }; From 514b670054cac6b84d44b606af3973649ba3354b Mon Sep 17 00:00:00 2001 From: dhruvang21 <105810308+dhruvang21@users.noreply.github.com> Date: Tue, 26 Nov 2024 15:58:03 +0530 Subject: [PATCH 1711/1908] Query Loop block: remove 'add new post' prompt in the sidebar (#67189) Co-authored-by: dhruvang21 <dhruvang21@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- .../components/block-info-slot-fill/index.js | 25 --------------- .../src/components/block-inspector/index.js | 2 -- packages/block-editor/src/private-apis.js | 2 -- .../create-new-post-link.js | 32 ------------------- .../query/edit/inspector-controls/index.js | 10 ------ packages/block-library/src/query/editor.scss | 4 --- 6 files changed, 75 deletions(-) delete mode 100644 packages/block-editor/src/components/block-info-slot-fill/index.js delete mode 100644 packages/block-library/src/query/edit/inspector-controls/create-new-post-link.js diff --git a/packages/block-editor/src/components/block-info-slot-fill/index.js b/packages/block-editor/src/components/block-info-slot-fill/index.js deleted file mode 100644 index 3592fc0424329b..00000000000000 --- a/packages/block-editor/src/components/block-info-slot-fill/index.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * WordPress dependencies - */ -import { createSlotFill } from '@wordpress/components'; - -/** - * Internal dependencies - */ -import { - useBlockEditContext, - mayDisplayControlsKey, -} from '../block-edit/context'; - -const { Fill, Slot } = createSlotFill( Symbol( 'BlockInformation' ) ); - -const BlockInfo = ( props ) => { - const context = useBlockEditContext(); - if ( ! context[ mayDisplayControlsKey ] ) { - return null; - } - return <Fill { ...props } />; -}; -BlockInfo.Slot = ( props ) => <Slot { ...props } />; - -export default BlockInfo; diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index 475d4f6a4b8c2e..450a370b5c212a 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -26,7 +26,6 @@ import useInspectorControlsTabs from '../inspector-controls-tabs/use-inspector-c import AdvancedControls from '../inspector-controls-tabs/advanced-controls-panel'; import PositionControls from '../inspector-controls-tabs/position-controls-panel'; import useBlockInspectorAnimationSettings from './useBlockInspectorAnimationSettings'; -import BlockInfo from '../block-info-slot-fill'; import BlockQuickNavigation from '../block-quick-navigation'; import { useBorderPanelLabel } from '../../hooks/border'; @@ -253,7 +252,6 @@ const BlockInspectorSingleBlock = ( { className={ blockInformation.isSynced && 'is-synced' } /> <BlockVariationTransforms blockClientId={ clientId } /> - <BlockInfo.Slot /> { showTabs && ( <InspectorControlsTabs hasBlockStyles={ hasBlockStyles } diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 2ca185823f15e1..21b9f4bca7fc3d 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -13,7 +13,6 @@ import { normalizeString, } from './components/inserter/search-items'; import { PrivateListView } from './components/list-view'; -import BlockInfo from './components/block-info-slot-fill'; import { useHasBlockToolbar } from './components/block-toolbar/use-has-block-toolbar'; import { cleanEmptyObject } from './hooks/utils'; import BlockQuickNavigation from './components/block-quick-navigation'; @@ -67,7 +66,6 @@ lock( privateApis, { normalizeString, PrivateListView, ResizableBoxPopover, - BlockInfo, useHasBlockToolbar, cleanEmptyObject, BlockQuickNavigation, diff --git a/packages/block-library/src/query/edit/inspector-controls/create-new-post-link.js b/packages/block-library/src/query/edit/inspector-controls/create-new-post-link.js deleted file mode 100644 index 58d58a6089aacd..00000000000000 --- a/packages/block-library/src/query/edit/inspector-controls/create-new-post-link.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * WordPress dependencies - */ -import { createInterpolateElement } from '@wordpress/element'; -import { addQueryArgs } from '@wordpress/url'; -import { store as coreStore } from '@wordpress/core-data'; -import { useSelect } from '@wordpress/data'; - -const CreateNewPostLink = ( { postType } ) => { - const newPostUrl = addQueryArgs( 'post-new.php', { - post_type: postType, - } ); - - const addNewItemLabel = useSelect( - ( select ) => { - const { getPostType } = select( coreStore ); - return getPostType( postType )?.labels?.add_new_item; - }, - [ postType ] - ); - return ( - <div className="wp-block-query__create-new-link"> - { createInterpolateElement( - '<a>' + addNewItemLabel + '</a>', - // eslint-disable-next-line jsx-a11y/anchor-has-content - { a: <a href={ newPostUrl } /> } - ) } - </div> - ); -}; - -export default CreateNewPostLink; diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index 7d5745e190c9a7..0ae4b052b57873 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -15,7 +15,6 @@ import { import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { __ } from '@wordpress/i18n'; -import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { debounce } from '@wordpress/compose'; import { useEffect, useState, useCallback } from '@wordpress/element'; @@ -28,11 +27,9 @@ import ParentControl from './parent-control'; import { TaxonomyControls } from './taxonomy-controls'; import FormatControls from './format-controls'; import StickyControl from './sticky-control'; -import CreateNewPostLink from './create-new-post-link'; import PerPageControl from './per-page-control'; import OffsetControl from './offset-controls'; import PagesControl from './pages-control'; -import { unlock } from '../../../lock-unlock'; import { usePostTypes, useIsPostTypeHierarchical, @@ -42,8 +39,6 @@ import { } from '../../utils'; import { useToolsPanelDropdownMenuProps } from '../../../utils/hooks'; -const { BlockInfo } = unlock( blockEditorPrivateApis ); - export default function QueryInspectorControls( props ) { const { attributes, setQuery, setDisplayLayout, isSingular } = props; const { query, displayLayout } = attributes; @@ -191,11 +186,6 @@ export default function QueryInspectorControls( props ) { return ( <> - { !! postType && ( - <BlockInfo> - <CreateNewPostLink postType={ postType } /> - </BlockInfo> - ) } { showSettingsPanel && ( <PanelBody title={ __( 'Settings' ) }> { showInheritControl && ( diff --git a/packages/block-library/src/query/editor.scss b/packages/block-library/src/query/editor.scss index b86eae0cbf65a8..da863bff0b5da6 100644 --- a/packages/block-library/src/query/editor.scss +++ b/packages/block-library/src/query/editor.scss @@ -6,10 +6,6 @@ } } -.wp-block-query__create-new-link { - padding: 0 $grid-unit-20 $grid-unit-20 52px; -} - .block-library-query__pattern-selection-content .block-editor-block-patterns-list { display: grid; grid-template-columns: 1fr 1fr 1fr; From d2c2ed8a8bac9d5b3af1876be471c6d5aaad8d7b Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Tue, 26 Nov 2024 11:53:07 +0100 Subject: [PATCH 1712/1908] Editor: Fix deprecation version for template selectors Co-authored-by: gigitux <gigitux@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- packages/editor/src/store/selectors.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index c17e80f771ea36..a090fee0abd641 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -1707,7 +1707,7 @@ export const __experimentalGetDefaultTemplateTypes = createRegistrySelector( deprecated( "select('core/editor').__experimentalGetDefaultTemplateTypes", { - since: '6.7', + since: '6.8', alternative: "select('core/core-data').getEntityRecord( 'root', '__unstableBase' )?.default_template_types", } @@ -1730,7 +1730,7 @@ export const __experimentalGetDefaultTemplatePartAreas = createRegistrySelector( deprecated( "select('core/editor').__experimentalGetDefaultTemplatePartAreas", { - since: '6.7', + since: '6.8', alternative: "select('core/core-data').getEntityRecord( 'root', '__unstableBase' )?.default_template_part_areas", } @@ -1760,7 +1760,7 @@ export const __experimentalGetDefaultTemplateType = createRegistrySelector( deprecated( "select('core/editor').__experimentalGetDefaultTemplateType", { - since: '6.7', + since: '6.8', } ); const templateTypes = select( coreStore ).getEntityRecord( @@ -1792,7 +1792,7 @@ export const __experimentalGetTemplateInfo = createRegistrySelector( ( select ) => createSelector( ( state, template ) => { deprecated( "select('core/editor').__experimentalGetTemplateInfo", { - since: '6.7', + since: '6.8', } ); if ( ! template ) { From 94071077510763cb060de59d8758adef1216fae7 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 26 Nov 2024 17:23:52 +0400 Subject: [PATCH 1713/1908] Block Editor: Add success notices for image editing (#67312) * Block Editor: Add success notices for image editing * Fix translators comment Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> --- .../components/image-editor/use-save-image.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/image-editor/use-save-image.js b/packages/block-editor/src/components/image-editor/use-save-image.js index 094ce1600545b5..676f74b9ab6a68 100644 --- a/packages/block-editor/src/components/image-editor/use-save-image.js +++ b/packages/block-editor/src/components/image-editor/use-save-image.js @@ -10,6 +10,12 @@ import { __, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; import { __unstableStripHTML as stripHTML } from '@wordpress/dom'; +const messages = { + crop: __( 'Image cropped.' ), + rotate: __( 'Image rotated.' ), + cropAndRotate: __( 'Image cropped and rotated.' ), +}; + export default function useSaveImage( { crop, rotation, @@ -18,7 +24,8 @@ export default function useSaveImage( { onSaveImage, onFinishEditing, } ) { - const { createErrorNotice } = useDispatch( noticesStore ); + const { createErrorNotice, createSuccessNotice } = + useDispatch( noticesStore ); const [ isInProgress, setIsInProgress ] = useState( false ); const cancel = useCallback( () => { @@ -61,6 +68,9 @@ export default function useSaveImage( { return; } + const modifierType = + modifiers.length === 1 ? modifiers[ 0 ].type : 'cropAndRotate'; + apiFetch( { path: `/wp/v2/media/${ id }/edit`, method: 'POST', @@ -71,11 +81,14 @@ export default function useSaveImage( { id: response.id, url: response.source_url, } ); + createSuccessNotice( messages[ modifierType ], { + type: 'snackbar', + } ); } ) .catch( ( error ) => { createErrorNotice( sprintf( - /* translators: 1. Error message */ + /* translators: %s: Error message. */ __( 'Could not edit image. %s' ), stripHTML( error.message ) ), @@ -96,6 +109,7 @@ export default function useSaveImage( { url, onSaveImage, createErrorNotice, + createSuccessNotice, onFinishEditing, ] ); From 9ee20a821a69271dcada656b3df49a8266c66fe2 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 26 Nov 2024 22:28:30 +0900 Subject: [PATCH 1714/1908] CustomGradientPicker: Prepare `Button`s for 40px default size (#67286) * CustomGradientPicker: Prepare `Button`s for 40px default size * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/custom-gradient-picker/gradient-bar/control-points.tsx | 2 ++ packages/components/src/custom-gradient-picker/style.scss | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 23e791645a20c8..44351656af3bd8 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -42,6 +42,7 @@ - `SlotFill`: rewrite the `Slot` component from class component to functional ([#67153](https://github.com/WordPress/gutenberg/pull/67153)). - `Menu.ItemHelpText`: Fix text wrapping to prevent unintended word breaks ([#67011](https://github.com/WordPress/gutenberg/pull/67011)). - `BorderBoxControl`: Suppress redundant warnings for deprecated 36px size ([#67213](https://github.com/WordPress/gutenberg/pull/67213)). +- `CustomGradientPicker`: Prepare `Button`s for 40px default size ([#67286](https://github.com/WordPress/gutenberg/pull/67286)). ## 28.12.0 (2024-11-16) diff --git a/packages/components/src/custom-gradient-picker/gradient-bar/control-points.tsx b/packages/components/src/custom-gradient-picker/gradient-bar/control-points.tsx index 3911e21e0f9348..d68ee7502e1f63 100644 --- a/packages/components/src/custom-gradient-picker/gradient-bar/control-points.tsx +++ b/packages/components/src/custom-gradient-picker/gradient-bar/control-points.tsx @@ -66,6 +66,7 @@ function ControlPointButton( { aria-describedby={ descriptionId } aria-haspopup="true" aria-expanded={ isOpen } + __next40pxDefaultSize className={ clsx( 'components-custom-gradient-picker__control-point-button', { @@ -349,6 +350,7 @@ function InsertPoint( { } } renderToggle={ ( { isOpen, onToggle } ) => ( <Button + __next40pxDefaultSize aria-expanded={ isOpen } aria-haspopup="true" onClick={ () => { diff --git a/packages/components/src/custom-gradient-picker/style.scss b/packages/components/src/custom-gradient-picker/style.scss index fea18f340951e5..b9f2bee9dbe4eb 100644 --- a/packages/components/src/custom-gradient-picker/style.scss +++ b/packages/components/src/custom-gradient-picker/style.scss @@ -47,7 +47,7 @@ $components-custom-gradient-picker__padding: $grid-unit-20; // 48px container, 1 // Same size as the .components-custom-gradient-picker__control-point-dropdown parent height: inherit; width: inherit; - min-width: $grid-unit-20; + min-width: $grid-unit-20 !important; border-radius: $radius-round; background: $white; From 6cc603585ebb52958e57f144952e3fa152c97fb7 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 26 Nov 2024 22:43:37 +0900 Subject: [PATCH 1715/1908] Icon: Auto-generate readme (#67282) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/src/icon/README.md | 87 +++++-------------- .../components/src/icon/docs-manifest.json | 5 ++ packages/components/src/icon/index.tsx | 41 ++++++--- 3 files changed, 55 insertions(+), 78 deletions(-) create mode 100644 packages/components/src/icon/docs-manifest.json diff --git a/packages/components/src/icon/README.md b/packages/components/src/icon/README.md index 5e78f029f169f7..63d52c1fd20b13 100644 --- a/packages/components/src/icon/README.md +++ b/packages/components/src/icon/README.md @@ -1,82 +1,39 @@ # Icon -Allows you to render a raw icon without any initial styling or wrappers. +<!-- This file is generated automatically and cannot be edited directly. Make edits via TypeScript types and TSDocs. --> -## Usage +<p class="callout callout-info">See the <a href="https://wordpress.github.io/gutenberg/?path=/docs/components-icon--docs">WordPress Storybook</a> for more detailed, interactive documentation.</p> -#### With a Dashicon +Renders a raw icon without any initial styling or wrappers. ```jsx -import { Icon } from '@wordpress/components'; +import { wordpress } from '@wordpress/icons'; -const MyIcon = () => <Icon icon="screenoptions" />; +<Icon icon={ wordpress } /> ``` - -#### With a function - -```jsx -import { Icon } from '@wordpress/components'; - -const MyIcon = () => ( - <Icon - icon={ () => ( - <svg> - <path d="M5 4v3h5.5v12h3V7H19V4z" /> - </svg> - ) } - /> -); -``` - -#### With a Component - -```jsx -import { MyIconComponent } from '../my-icon-component'; -import { Icon } from '@wordpress/components'; - -const MyIcon = () => <Icon icon={ MyIconComponent } />; -``` - -#### With an SVG - -```jsx -import { Icon } from '@wordpress/components'; - -const MyIcon = () => ( - <Icon - icon={ - <svg> - <path d="M5 4v3h5.5v12h3V7H19V4z" /> - </svg> - } - /> -); -``` - -#### Specifying a className - -```jsx -import { Icon } from '@wordpress/components'; - -const MyIcon = () => <Icon icon="screenoptions" className="example-class" />; -``` - ## Props -The component accepts the following props. Any additional props are passed through to the underlying icon element. +### `icon` -### icon +The icon to render. In most cases, you should use an icon from +[the `@wordpress/icons` package](https://wordpress.github.io/gutenberg/?path=/story/icons-icon--library). -The icon to render. Supported values are: Dashicons (specified as strings), functions, Component instances and `null`. +Other supported values are: component instances, functions, +[Dashicons](https://developer.wordpress.org/resource/dashicons/) +(specified as strings), and `null`. -- Type: `String|Function|Component|null` -- Required: No -- Default: `null` +The `size` value, as well as any other additional props, will be passed through. -### size + - Type: `IconType` + - Required: No + - Default: `null` + +### `size` The size (width and height) of the icon. -- Type: `Number` -- Required: No -- Default: `20` when a Dashicon is rendered, `24` for all other icons. +Defaults to `20` when `icon` is a string (i.e. a Dashicon id), otherwise `24`. + + - Type: `number` + - Required: No + - Default: `'string' === typeof icon ? 20 : 24` diff --git a/packages/components/src/icon/docs-manifest.json b/packages/components/src/icon/docs-manifest.json new file mode 100644 index 00000000000000..4794049a3eb6ce --- /dev/null +++ b/packages/components/src/icon/docs-manifest.json @@ -0,0 +1,5 @@ +{ + "$schema": "../../schemas/docs-manifest.json", + "displayName": "Icon", + "filePath": "./index.tsx" +} diff --git a/packages/components/src/icon/index.tsx b/packages/components/src/icon/index.tsx index 3fbf4d18c5a00e..283b9cd179cd1c 100644 --- a/packages/components/src/icon/index.tsx +++ b/packages/components/src/icon/index.tsx @@ -25,10 +25,22 @@ export type IconType = | ( ( props: { size?: number } ) => JSX.Element ) | JSX.Element; -interface BaseProps { +type AdditionalProps< T > = T extends ComponentType< infer U > + ? U + : T extends DashiconIconKey + ? SVGProps< SVGSVGElement > + : {}; + +export type Props = { /** - * The icon to render. Supported values are: Dashicons (specified as - * strings), functions, Component instances and `null`. + * The icon to render. In most cases, you should use an icon from + * [the `@wordpress/icons` package](https://wordpress.github.io/gutenberg/?path=/story/icons-icon--library). + * + * Other supported values are: component instances, functions, + * [Dashicons](https://developer.wordpress.org/resource/dashicons/) + * (specified as strings), and `null`. + * + * The `size` value, as well as any other additional props, will be passed through. * * @default null */ @@ -36,19 +48,22 @@ interface BaseProps { /** * The size (width and height) of the icon. * - * @default `20` when a Dashicon is rendered, `24` for all other icons. + * Defaults to `20` when `icon` is a string (i.e. a Dashicon id), otherwise `24`. + * + * @default `'string' === typeof icon ? 20 : 24`. */ size?: number; -} - -type AdditionalProps< T > = T extends ComponentType< infer U > - ? U - : T extends DashiconIconKey - ? SVGProps< SVGSVGElement > - : {}; - -export type Props = BaseProps & AdditionalProps< IconType >; +} & AdditionalProps< IconType >; +/** + * Renders a raw icon without any initial styling or wrappers. + * + * ```jsx + * import { wordpress } from '@wordpress/icons'; + * + * <Icon icon={ wordpress } /> + * ``` + */ function Icon( { icon = null, size = 'string' === typeof icon ? 20 : 24, From 4c30b00b3567313c6c49cd2e85dd35af254be097 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Tue, 26 Nov 2024 20:19:55 +0400 Subject: [PATCH 1716/1908] Block Editor: Add notice action to revert image to original after cropping (#67314) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- .../src/components/image-editor/use-save-image.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/block-editor/src/components/image-editor/use-save-image.js b/packages/block-editor/src/components/image-editor/use-save-image.js index 676f74b9ab6a68..980ac9b8b1123c 100644 --- a/packages/block-editor/src/components/image-editor/use-save-image.js +++ b/packages/block-editor/src/components/image-editor/use-save-image.js @@ -83,6 +83,17 @@ export default function useSaveImage( { } ); createSuccessNotice( messages[ modifierType ], { type: 'snackbar', + actions: [ + { + label: __( 'Undo' ), + onClick: () => { + onSaveImage( { + id, + url, + } ); + }, + }, + ], } ); } ) .catch( ( error ) => { From 6d90ad40569a94027ea38213a75c99305bd775d3 Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Tue, 26 Nov 2024 17:43:51 +0100 Subject: [PATCH 1717/1908] Add #7895 Core Backport PR to the changelog (#67319) --- backport-changelog/6.8/7895.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 backport-changelog/6.8/7895.md diff --git a/backport-changelog/6.8/7895.md b/backport-changelog/6.8/7895.md new file mode 100644 index 00000000000000..4750ab545ada3b --- /dev/null +++ b/backport-changelog/6.8/7895.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7895 + +* https://github.com/WordPress/gutenberg/pull/66459 From de7b09b2faa72d462736bf562962540450982522 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 27 Nov 2024 01:46:43 +0900 Subject: [PATCH 1718/1908] Icon: Improve `icon` prop usage docs in Storybook (#67280) * Icon: Improve `icon` prop usage docs in Storybook * Fixup Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/icon/stories/index.story.tsx | 58 ++++++++++++++++--- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/packages/components/src/icon/stories/index.story.tsx b/packages/components/src/icon/stories/index.story.tsx index 7d61be8df7f3ce..d1eabf2e98b771 100644 --- a/packages/components/src/icon/stories/index.story.tsx +++ b/packages/components/src/icon/stories/index.story.tsx @@ -47,26 +47,68 @@ FillColor.args = { ...Default.args, }; +/** + * When `icon` is a function, it will be passed the `size` prop and any other additional props. + */ export const WithAFunction = Template.bind( {} ); WithAFunction.args = { ...Default.args, - icon: () => ( - <SVG> - <Path d="M5 4v3h5.5v12h3V7H19V4z" /> - </SVG> + icon: ( { size }: { size?: number } ) => ( + <img + width={ size } + height={ size } + src="https://s.w.org/style/images/about/WordPress-logotype-wmark.png" + alt="WordPress" + /> ), }; +WithAFunction.parameters = { + docs: { + source: { + code: ` +<Icon + icon={ ( { size } ) => ( + <img + width={ size } + height={ size } + src="https://s.w.org/style/images/about/WordPress-logotype-wmark.png" + alt="WordPress" + /> + ) } +/> + `, + }, + }, +}; -const MyIconComponent = () => ( - <SVG> +const MyIconComponent = ( { size }: { size?: number } ) => ( + <SVG width={ size } height={ size }> <Path d="M5 4v3h5.5v12h3V7H19V4z" /> </SVG> ); +/** + * When `icon` is a component, it will be passed the `size` prop and any other additional props. + */ export const WithAComponent = Template.bind( {} ); WithAComponent.args = { ...Default.args, - icon: MyIconComponent, + icon: <MyIconComponent />, +}; +WithAComponent.parameters = { + docs: { + source: { + code: ` +const MyIconComponent = ( { size } ) => ( + <SVG width={ size } height={ size }> + <Path d="M5 4v3h5.5v12h3V7H19V4z" /> + </SVG> +); + +<Icon icon={ <MyIconComponent /> } /> + `, + }, + }, }; export const WithAnSVG = Template.bind( {} ); @@ -80,7 +122,7 @@ WithAnSVG.args = { }; /** - * Although it's preferred to use icons from the `@wordpress/icons` package, Dashicons are still supported, + * Although it's preferred to use icons from the `@wordpress/icons` package, [Dashicons](https://developer.wordpress.org/resource/dashicons/) are still supported, * as long as you are in a context where the Dashicons stylesheet is loaded. To simulate that here, * use the Global CSS Injector in the Storybook toolbar at the top and select the "WordPress" preset. */ From 8c34d9103cfff2b16839af188a890d01d2a18bac Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 27 Nov 2024 02:00:29 +0900 Subject: [PATCH 1719/1908] CircularOptionPicker: Update Button sizes (#67285) * CircularOptionPicker: Update Button sizes * Add changelog * Update snapshot * Fixup changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../color-palette/test/__snapshots__/control.js.snap | 4 ++-- packages/components/CHANGELOG.md | 1 + .../circular-option-picker/circular-option-picker-actions.tsx | 1 + .../circular-option-picker/circular-option-picker-option.tsx | 1 + packages/components/src/circular-option-picker/style.scss | 4 ++-- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap b/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap index 3c4cef664a3103..14196a221304bc 100644 --- a/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap +++ b/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap @@ -219,7 +219,7 @@ exports[`ColorPaletteControl matches the snapshot 1`] = ` <button aria-label="Color: red" aria-selected="true" - class="components-button components-circular-option-picker__option" + class="components-button components-circular-option-picker__option is-next-40px-default-size" data-active-item="true" id="components-circular-option-picker-0-0" role="option" @@ -247,7 +247,7 @@ exports[`ColorPaletteControl matches the snapshot 1`] = ` class="components-circular-option-picker__custom-clear-wrapper" > <button - class="components-button components-circular-option-picker__clear is-tertiary" + class="components-button components-circular-option-picker__clear is-next-40px-default-size is-tertiary" type="button" > Clear diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 44351656af3bd8..c9b09c40350232 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -30,6 +30,7 @@ - `ColorPicker`: Update sizes of color format select and copy button ([#67093](https://github.com/WordPress/gutenberg/pull/67093)). - `ComboboxControl`: Update reset button size ([#67215](https://github.com/WordPress/gutenberg/pull/67215)). - `Autocomplete`: Increase option height ([#67214](https://github.com/WordPress/gutenberg/pull/67214)). +- `CircularOptionPicker`: Update `Button` sizes to be ready for 40px default size ([#67285](https://github.com/WordPress/gutenberg/pull/67285)). ### Experimental diff --git a/packages/components/src/circular-option-picker/circular-option-picker-actions.tsx b/packages/components/src/circular-option-picker/circular-option-picker-actions.tsx index 4cf4d6f95da383..339c614e4ca45d 100644 --- a/packages/components/src/circular-option-picker/circular-option-picker-actions.tsx +++ b/packages/components/src/circular-option-picker/circular-option-picker-actions.tsx @@ -47,6 +47,7 @@ export function ButtonAction( { }: WordPressComponentProps< ButtonAsButtonProps, 'button', false > ) { return ( <Button + __next40pxDefaultSize className={ clsx( 'components-circular-option-picker__clear', className diff --git a/packages/components/src/circular-option-picker/circular-option-picker-option.tsx b/packages/components/src/circular-option-picker/circular-option-picker-option.tsx index 276ab7549781ed..c5b2edb260d159 100644 --- a/packages/components/src/circular-option-picker/circular-option-picker-option.tsx +++ b/packages/components/src/circular-option-picker/circular-option-picker-option.tsx @@ -94,6 +94,7 @@ export function Option( { const commonProps = { id, className: 'components-circular-option-picker__option', + __next40pxDefaultSize: true, ...additionalProps, }; diff --git a/packages/components/src/circular-option-picker/style.scss b/packages/components/src/circular-option-picker/style.scss index 24b67eb7e7021e..e47764a3a60d7f 100644 --- a/packages/components/src/circular-option-picker/style.scss +++ b/packages/components/src/circular-option-picker/style.scss @@ -67,8 +67,8 @@ $color-palette-circle-spacing: 12px; .components-circular-option-picker__option { display: inline-block; vertical-align: top; - height: 100%; - width: 100%; + height: 100% !important; + aspect-ratio: 1; border: none; border-radius: $radius-round; background: transparent; From 8656f12c4d2c2987f1b447d4426c377a86a6af0d Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 27 Nov 2024 04:24:11 +0900 Subject: [PATCH 1720/1908] Components contributing guide: Fix relative links (#67323) * Components contributing guide: Fix relative links * Fix broken image Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CONTRIBUTING.md | 32 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/components/CONTRIBUTING.md b/packages/components/CONTRIBUTING.md index 8af8bbf801edfe..fd97fe912b2be8 100644 --- a/packages/components/CONTRIBUTING.md +++ b/packages/components/CONTRIBUTING.md @@ -2,7 +2,7 @@ Thank you for taking the time to contribute. -The following is a set of guidelines for contributing to the `@wordpress/components` package to be considered in addition to the general ones described in our [Contributing Policy](/CONTRIBUTING.md). +The following is a set of guidelines for contributing to the `@wordpress/components` package to be considered in addition to the general ones described in our [Contributing Policy](https://github.com/WordPress/gutenberg/blob/HEAD/CONTRIBUTING.md). This set of guidelines should apply especially to newly introduced components. In fact, while these guidelines should also be retroactively applied to existing components, it is sometimes impossible to do so for legacy/compatibility reasons. @@ -36,7 +36,7 @@ To determine if a component should be added, ask yourself: Here’s a flowchart that can help determine if a new component is necessary: -[![New component flowchart](https://wordpress.org/gutenberg/files/2019/07/New_component_flowchart.png)](https://coggle.it/diagram/WtUSrld3uAYZHsn-/t/new-ui-component/992b38cbe685d897b4aec6d0dd93cc4b47c06e0d4484eeb0d7d9a47fb2c48d94) +![New component flowchart](https://wordpress.org/gutenberg/files/2019/07/New_component_flowchart.png) ### First steps @@ -95,12 +95,12 @@ In these situations, one possible approach is to "soft-deprecate" a given legacy 2. Updating all places in Gutenberg that use that API. 3. Adding deprecation warnings (only after the previous point is completed, otherwise the Browser Console will be polluted by all those warnings and some e2e tests may fail). -When adding new components or new props to existing components, it's recommended to create a [private version](/packages/private-apis/README.md)) of the component until the changes are stable enough to be exposed as part of the public API. +When adding new components or new props to existing components, it's recommended to create a [private version](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-private-apis/) of the component until the changes are stable enough to be exposed as part of the public API. ### Learn more -- [How to preserve backward compatibility for a React Component](/docs/contributors/code/backward-compatibility.md#how-to-preserve-backward-compatibility-for-a-react-component) -- [Experimental and Unstable APIs](/docs/contributors/code/coding-guidelines.md#legacy-experimental-apis-plugin-only-apis-and-private-apis) +- [How to preserve backward compatibility for a React Component](https://developer.wordpress.org/block-editor/contributors/code/backward-compatibility/#how-to-preserve-backward-compatibility-for-a-react-component) +- [Experimental and Unstable APIs](https://developer.wordpress.org/block-editor/contributors/code/coding-guidelines/#legacy-experimental-apis-plugin-only-apis-and-private-apis) - [Deprecating styles](#deprecating-styles) <!-- ## Polymorphic Components (i.e. the `as` prop) @@ -216,8 +216,8 @@ function Example( A couple of good examples of how hooks are used for composition are: -- the `Card` component, which builds on top of the `Surface` component by [calling the `useSurface` hook inside its own hook](/packages/components/src/card/card/hook.ts); -- the `HStack` component, which builds on top of the `Flex` component and [calls the `useFlex` hook inside its own hook](/packages/components/src/h-stack/hook.tsx). +- the `Card` component, which builds on top of the `Surface` component by [calling the `useSurface` hook inside its own hook](https://github.com/WordPress/gutenberg/blob/trunk/packages/components/src/card/card/hook.ts); +- the `HStack` component, which builds on top of the `Flex` component and [calls the `useFlex` hook inside its own hook](https://github.com/WordPress/gutenberg/blob/trunk/packages/components/src/h-stack/hook.tsx). <!-- ## API Consinstency @@ -418,7 +418,7 @@ On the component's main named export, add a JSDoc comment that includes the main All new component should be styled using [Emotion](https://emotion.sh/docs/introduction). -Note: Instead of using Emotion's standard `cx` function, the custom [`useCx` hook](/packages/components/src/utils/hooks/use-cx.ts) should be used instead. +Note: Instead of using Emotion's standard `cx` function, the custom [`useCx` hook](https://github.com/WordPress/gutenberg/blob/trunk/packages/components/src/utils/hooks/use-cx.ts) should be used instead. ### Deprecating styles @@ -462,7 +462,7 @@ export const Wrapper = styled.div` Once deprecated, code examples in docs/stories should include the opt-in prop set to `true` so that new consumers are encouraged to adopt it from the start. -Remember to [add a **Needs Dev Note** label](/docs/contributors/code/backward-compatibility.md##dev-notes) to the pull request so third-party developers can be informed of the deprecation. +Remember to [add a **Needs Dev Note** label](https://developer.wordpress.org/block-editor/contributors/code/backward-compatibility/#dev-notes) to the pull request so third-party developers can be informed of the deprecation. When the grace period is over and the deprecation version arrives, the `__next*` prop, deprecation notice, and deprecated styles should all be completely removed from the codebase. @@ -491,7 +491,7 @@ Components can use this system via a couple of functions: - they can connect to the Context via `contextConnect` - they can read the "computed" values from the context via `useContextSystem` -An example of how this is used can be found in the [`Card` component family](/packages/components/src/card). For example, this is how the `Card` component injects the `size` and `isBorderless` props down to its `CardBody` subcomponent — which makes it use the correct spacing and border settings "auto-magically". +An example of how this is used can be found in the [`Card` component family](https://github.com/WordPress/gutenberg/tree/trunk/packages/components/src/card). For example, this is how the `Card` component injects the `size` and `isBorderless` props down to its `CardBody` subcomponent — which makes it use the correct spacing and border settings "auto-magically". ```jsx //========================================================================= @@ -564,7 +564,7 @@ export function useCardBody( props ) { ## Unit tests -Please refer to the [JavaScript Testing Overview docs](/docs/contributors/code/testing-overview.md#snapshot-testing). +Please refer to the [JavaScript Testing Overview docs](https://developer.wordpress.org/block-editor/contributors/code/testing-overview/#snapshot-testing). ## Storybook @@ -596,13 +596,13 @@ Primary.args = { A great tool to use when writing stories is the [Storybook Controls addon](https://storybook.js.org/addons/@storybook/addon-controls). Ideally props should be exposed by using this addon, which provides a graphical UI to interact dynamically with the component without needing to write code. Historically, we used [Knobs](https://storybook.js.org/addons/@storybook/addon-knobs), but it was deprecated and later removed in [#47152](https://github.com/WordPress/gutenberg/pull/47152). -The default value of each control should coincide with the default value of the props (i.e. it should be `undefined` if a prop is not required). A story should, therefore, also explicitly show how values from the Context System are applied to (sub)components. A good example of how this may look like is the [`Card` story](https://wordpress.github.io/gutenberg/?path=/story/components-card--default) (code [here](/packages/components/src/card/stories/index.tsx)). +The default value of each control should coincide with the default value of the props (i.e. it should be `undefined` if a prop is not required). A story should, therefore, also explicitly show how values from the Context System are applied to (sub)components. A good example of how this may look like is the [`Card` story](https://wordpress.github.io/gutenberg/?path=/story/components-card--default) (code [here](https://github.com/WordPress/gutenberg/blob/trunk/packages/components/src/card/stories/index.story.tsx)). Storybook can be started on a local machine by running `npm run storybook:dev`. Alternatively, the components' catalogue (up to date with the latest code on `trunk`) can be found at [wordpress.github.io/gutenberg/](https://wordpress.github.io/gutenberg/). ## Documentation -All components, in addition to being typed, should be using JSDoc when necessary — as explained in the [Coding Guidelines](/docs/contributors/code/coding-guidelines.md#javascript-documentation-using-jsdoc). +All components, in addition to being typed, should be using JSDoc when necessary — as explained in the [Coding Guidelines](https://developer.wordpress.org/block-editor/contributors/code/coding-guidelines/#javascript-documentation-using-jsdoc). Each component that is exported from the `@wordpress/components` package should include a `README.md` file, explaining how to use the component, showing examples, and documenting all the props. @@ -625,7 +625,7 @@ Description of the component. ## Usage -Code example using correct markdown syntax and formatted using project's formatting rules. See [ItemGroup](/packages/components/src/item-group/item-group/README.md#usage) for a real-world example. +Code example using correct markdown syntax and formatted using project's formatting rules. See [ItemGroup](https://github.com/WordPress/gutenberg/blob/trunk/packages/components/src/item-group/item-group/README.md) for a real-world example. ```jsx import { ExampleComponent } from '@wordpress/components'; @@ -653,13 +653,13 @@ Prop description. With a new line before and after the description and before an ### Inherited props -Add this section when there are props that are drilled down into an internal component. See [ClipboardButton](/packages/components/src/clipboard-button/README.md) for an example. +Add this section when there are props that are drilled down into an internal component. See [ClipboardButton](https://github.com/WordPress/gutenberg/blob/trunk/packages/components/src/clipboard-button/README.md) for an example. <!-- Only add the next section if the component relies on the [Context System](#context-system) --> ## Context -See examples for this section for the [ItemGroup](/packages/components/src/item-group/item-group/README.md#context) and [`Card`](/packages/components/src/card/card/README.md#context) components. +See examples for this section for the [ItemGroup](https://github.com/WordPress/gutenberg/blob/trunk/packages/components/src/item-group/item-group/README.md#context) and [`Card`](https://github.com/WordPress/gutenberg/tree/trunk/packages/components/src/card/card#context) components. ```` ## Folder structure From 9b908539b23b310fa31a085794c9b1b17c1d2df5 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 27 Nov 2024 05:28:18 +0900 Subject: [PATCH 1721/1908] BoxControl: Auto-generate readme (#67284) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/src/box-control/README.md | 139 ++++++++++-------- .../src/box-control/docs-manifest.json | 5 + packages/components/src/box-control/index.tsx | 26 ++-- packages/components/src/box-control/types.ts | 2 + 4 files changed, 99 insertions(+), 73 deletions(-) create mode 100644 packages/components/src/box-control/docs-manifest.json diff --git a/packages/components/src/box-control/README.md b/packages/components/src/box-control/README.md index 77176b49eeb6d8..ddadf938798ee9 100644 --- a/packages/components/src/box-control/README.md +++ b/packages/components/src/box-control/README.md @@ -1,106 +1,125 @@ # BoxControl -A control that lets users set values for top, right, bottom, and left. Can be used as an input control for values like `padding` or `margin`. +<!-- This file is generated automatically and cannot be edited directly. Make edits via TypeScript types and TSDocs. --> -## Usage +<p class="callout callout-info">See the <a href="https://wordpress.github.io/gutenberg/?path=/docs/components-boxcontrol--docs">WordPress Storybook</a> for more detailed, interactive documentation.</p> + +A control that lets users set values for top, right, bottom, and left. Can be +used as an input control for values like `padding` or `margin`. ```jsx import { useState } from 'react'; import { BoxControl } from '@wordpress/components'; function Example() { - const [ values, setValues ] = useState( { - top: '50px', - left: '10%', - right: '10%', - bottom: '50px', - } ); - - return ( - <BoxControl - values={ values } - onChange={ ( nextValues ) => setValues( nextValues ) } - /> - ); -} + const [ values, setValues ] = useState( { + top: '50px', + left: '10%', + right: '10%', + bottom: '50px', + } ); + + return ( + <BoxControl + values={ values } + onChange={ setValues } + /> + ); +}; ``` - ## Props -### `allowReset`: `boolean` +### `__next40pxDefaultSize` + +Start opting into the larger default height that will become the default size in a future version. + + - Type: `boolean` + - Required: No + - Default: `false` + +### `allowReset` If this property is true, a button to reset the box control is rendered. -- Required: No -- Default: `true` + - Type: `boolean` + - Required: No + - Default: `true` -### `splitOnAxis`: `boolean` +### `id` -If this property is true, when the box control is unlinked, vertical and horizontal controls can be used instead of updating individual sides. +The id to use as a base for the unique HTML id attribute of the control. -- Required: No -- Default: `false` + - Type: `string` + - Required: No -### `inputProps`: `object` +### `inputProps` -Props for the internal [UnitControl](../unit-control) components. +Props for the internal `UnitControl` components. -- Required: No -- Default: `{ min: 0 }` + - Type: `UnitControlPassthroughProps` + - Required: No + - Default: `{ + min: 0, + }` -### `label`: `string` +### `label` Heading label for the control. -- Required: No -- Default: `__( 'Box Control' )` + - Type: `string` + - Required: No + - Default: `__( 'Box Control' )` -### `onChange`: `(next: BoxControlValue) => void` +### `onChange` A callback function when an input value changes. -- Required: Yes + - Type: `(next: BoxControlValue) => void` + - Required: No + - Default: `() => {}` -### `resetValues`: `object` +### `resetValues` The `top`, `right`, `bottom`, and `left` box dimension values to use when the control is reset. -- Required: No -- Default: `{ top: undefined, right: undefined, bottom: undefined, left: undefined }` - -### `sides`: `string[]` - -Collection of sides to allow control of. If omitted or empty, all sides will be available. Allowed values are "top", "right", "bottom", "left", "vertical", and "horizontal". - -- Required: No - -### `units`: `WPUnitControlUnit[]` - -Collection of available units which are compatible with [UnitControl](../unit-control). + - Type: `BoxControlValue` + - Required: No + - Default: `{ + top: undefined, + right: undefined, + bottom: undefined, + left: undefined, + }` -- Required: No +### `sides` -### `values`: `object` +Collection of sides to allow control of. If omitted or empty, all sides will be available. -The `top`, `right`, `bottom`, and `left` box dimension values. +Allowed values are "top", "right", "bottom", "left", "vertical", and "horizontal". -- Required: No + - Type: `readonly (keyof BoxControlValue | "horizontal" | "vertical")[]` + - Required: No -### `onMouseOver`: `function` +### `splitOnAxis` -A handler for onMouseOver events. +If this property is true, when the box control is unlinked, vertical and horizontal controls +can be used instead of updating individual sides. -- Required: No + - Type: `boolean` + - Required: No + - Default: `false` -### `onMouseOut`: `function` +### `units` -A handler for onMouseOut events. +Available units to select from. -- Required: No + - Type: `WPUnitControlUnit[]` + - Required: No + - Default: `CSS_UNITS` -### `__next40pxDefaultSize`: `boolean` +### `values` -Start opting into the larger default size that will become the default size in a future version. +The current values of the control, expressed as an object of `top`, `right`, `bottom`, and `left` values. -- Required: No -- Default: `false` + - Type: `BoxControlValue` + - Required: No diff --git a/packages/components/src/box-control/docs-manifest.json b/packages/components/src/box-control/docs-manifest.json new file mode 100644 index 00000000000000..c506e7a9e27eef --- /dev/null +++ b/packages/components/src/box-control/docs-manifest.json @@ -0,0 +1,5 @@ +{ + "$schema": "../../schemas/docs-manifest.json", + "displayName": "BoxControl", + "filePath": "./index.tsx" +} diff --git a/packages/components/src/box-control/index.tsx b/packages/components/src/box-control/index.tsx index 41e95aa88bea37..7f822f5f70e124 100644 --- a/packages/components/src/box-control/index.tsx +++ b/packages/components/src/box-control/index.tsx @@ -51,23 +51,23 @@ function useUniqueId( idProp?: string ) { * used as an input control for values like `padding` or `margin`. * * ```jsx + * import { useState } from 'react'; * import { BoxControl } from '@wordpress/components'; - * import { useState } from '@wordpress/element'; * * function Example() { - * const [ values, setValues ] = useState( { - * top: '50px', - * left: '10%', - * right: '10%', - * bottom: '50px', - * } ); + * const [ values, setValues ] = useState( { + * top: '50px', + * left: '10%', + * right: '10%', + * bottom: '50px', + * } ); * - * return ( - * <BoxControl - * values={ values } - * onChange={ ( nextValues ) => setValues( nextValues ) } - * /> - * ); + * return ( + * <BoxControl + * values={ values } + * onChange={ setValues } + * /> + * ); * }; * ``` */ diff --git a/packages/components/src/box-control/types.ts b/packages/components/src/box-control/types.ts index 5f4071aeed88a7..2a47abbf11001e 100644 --- a/packages/components/src/box-control/types.ts +++ b/packages/components/src/box-control/types.ts @@ -58,6 +58,8 @@ export type BoxControlProps = Pick< resetValues?: BoxControlValue; /** * Collection of sides to allow control of. If omitted or empty, all sides will be available. + * + * Allowed values are "top", "right", "bottom", "left", "vertical", and "horizontal". */ sides?: readonly ( keyof BoxControlValue | 'horizontal' | 'vertical' )[]; /** From eadf2dda88e69176c9d577ed7cd197a3da9197a2 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Tue, 26 Nov 2024 14:33:09 -0600 Subject: [PATCH 1722/1908] Add useScaleCanvas: Web Animations API for zoom in/out animation (#66917) * Move code into useScaleCanvas that isn't necessary in iframe index * Use Web Animations API for zoom in/out * Add reverse animation if zoom state is toggled quickly * Use transitionTo and transitionFrom refs to manage start and end points of transition --------- Co-authored-by: Alex Lende <alex+github.com@lende.xyz> --- packages/base-styles/_animations.scss | 5 - .../src/components/block-canvas/style.scss | 3 +- .../src/components/iframe/content.scss | 75 ++- .../src/components/iframe/index.js | 326 +----------- .../src/components/iframe/use-scale-canvas.js | 468 ++++++++++++++++++ 5 files changed, 517 insertions(+), 360 deletions(-) create mode 100644 packages/block-editor/src/components/iframe/use-scale-canvas.js diff --git a/packages/base-styles/_animations.scss b/packages/base-styles/_animations.scss index ae5de9a803008c..e5bbf863757356 100644 --- a/packages/base-styles/_animations.scss +++ b/packages/base-styles/_animations.scss @@ -41,8 +41,3 @@ @warn "The `edit-post__fade-in-animation` mixin is deprecated. Use `animation__fade-in` instead."; @include animation__fade-in($speed, $delay); } - -@mixin editor-canvas-resize-animation($additional-transition-rules...) { - transition: all 400ms cubic-bezier(0.46, 0.03, 0.52, 0.96), $additional-transition-rules; - @include reduce-motion("transition"); -} diff --git a/packages/block-editor/src/components/block-canvas/style.scss b/packages/block-editor/src/components/block-canvas/style.scss index 8f6064de0b615c..ea54646e64a59a 100644 --- a/packages/block-editor/src/components/block-canvas/style.scss +++ b/packages/block-editor/src/components/block-canvas/style.scss @@ -4,6 +4,7 @@ iframe[name="editor-canvas"] { height: 100%; display: block; // Handles transitions between device previews - @include editor-canvas-resize-animation; + transition: all 400ms cubic-bezier(0.46, 0.03, 0.52, 0.96); + @include reduce-motion("transition"); background-color: $gray-300; } diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss index 5e390800719949..9b02716671de77 100644 --- a/packages/block-editor/src/components/iframe/content.scss +++ b/packages/block-editor/src/components/iframe/content.scss @@ -4,10 +4,8 @@ .block-editor-iframe__html { transform-origin: top center; - // We don't want to animate the transform of the translateX because it is used - // to "center" the canvas. Leaving it on causes the canvas to slide around in - // odd ways. - @include editor-canvas-resize-animation( transform 0s, scale 0s, padding 0s, translate 0s); + // Prevents a flash of background color change when entering/exiting zoom out + transition: background-color 400ms; &.zoom-out-animation { $scroll-top: var(--wp-block-editor-iframe-zoom-out-scroll-top, 0); @@ -18,53 +16,48 @@ right: 0; top: calc(-1 * #{$scroll-top}); bottom: 0; - translate: 0 calc(#{$scroll-top} - #{$scroll-top-next}); // Force preserving a scrollbar gutter as scrollbar-gutter isn't supported in all browsers yet, // and removing the scrollbar causes the content to shift. overflow-y: scroll; - - // We only want to animate the scaling when entering zoom out. When sidebars - // are toggled, the resizing of the iframe handles scaling the canvas as well, - // and the doubled animations cause very odd animations. - @include editor-canvas-resize-animation( transform 0s, top 0s, bottom 0s, right 0s, left 0s ); } -} -.block-editor-iframe__html.is-zoomed-out { - $scale: var(--wp-block-editor-iframe-zoom-out-scale); - $frame-size: var(--wp-block-editor-iframe-zoom-out-frame-size); - $inner-height: var(--wp-block-editor-iframe-zoom-out-inner-height); - $content-height: var(--wp-block-editor-iframe-zoom-out-content-height); - $scale-container-width: var(--wp-block-editor-iframe-zoom-out-scale-container-width); - $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw); - // Apply an X translation to center the scaled content within the available space. - transform: translateX(calc((#{$scale-container-width} - #{$container-width}) / 2 / #{$scale})); - scale: #{$scale}; - background-color: $gray-300; + &.is-zoomed-out { + $scale: var(--wp-block-editor-iframe-zoom-out-scale, 1); + $frame-size: var(--wp-block-editor-iframe-zoom-out-frame-size, 0); + $inner-height: var(--wp-block-editor-iframe-zoom-out-inner-height); + $content-height: var(--wp-block-editor-iframe-zoom-out-content-height); + $scale-container-width: var(--wp-block-editor-iframe-zoom-out-scale-container-width); + $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw); + // Apply an X translation to center the scaled content within the available space. + transform: translateX(calc((#{$scale-container-width} - #{$container-width}) / 2 / #{$scale})); + scale: $scale; + background-color: $gray-300; - // Chrome seems to respect that transform scale shouldn't affect the layout size of the element, - // so we need to adjust the height of the content to match the scale by using negative margins. - $extra-content-height: calc(#{$content-height} * (1 - #{$scale})); - $total-frame-height: calc(2 * #{$frame-size} / #{$scale}); - $total-height: calc(#{$extra-content-height} + #{$total-frame-height} + 2px); - margin-bottom: calc(-1 * #{$total-height}); - // Add the top/bottom frame size. We use scaling to account for the left/right, as - // the padding left/right causes the contents to reflow, which breaks the 1:1 scaling - // of the content. - padding-top: calc(#{$frame-size} / #{$scale}); - padding-bottom: calc(#{$frame-size} / #{$scale}); + // Chrome seems to respect that transform scale shouldn't affect the layout size of the element, + // so we need to adjust the height of the content to match the scale by using negative margins. + $extra-content-height: calc(#{$content-height} * (1 - #{$scale})); + $total-frame-height: calc(2 * #{$frame-size} / #{$scale}); + $total-height: calc(#{$extra-content-height} + #{$total-frame-height} + 2px); + margin-bottom: calc(-1 * #{$total-height}); - body { - min-height: calc((#{$inner-height} - #{$total-frame-height}) / #{$scale}); + // Add the top/bottom frame size. We use scaling to account for the left/right, as + // the padding left/right causes the contents to reflow, which breaks the 1:1 scaling + // of the content. + padding-top: calc(#{$frame-size} / #{$scale}); + padding-bottom: calc(#{$frame-size} / #{$scale}); - > .is-root-container:not(.wp-block-post-content) { - flex: 1; - display: flex; - flex-direction: column; - height: 100%; + body { + min-height: calc((#{$inner-height} - #{$total-frame-height}) / #{$scale}); - > main { + > .is-root-container:not(.wp-block-post-content) { flex: 1; + display: flex; + flex-direction: column; + height: 100%; + + > main { + flex: 1; + } } } } diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index f8b7c25084e38d..751e940dd166cc 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -12,16 +12,9 @@ import { forwardRef, useMemo, useEffect, - useRef, } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; -import { - useResizeObserver, - useMergeRefs, - useRefEffect, - useDisabled, - useReducedMotion, -} from '@wordpress/compose'; +import { useMergeRefs, useRefEffect, useDisabled } from '@wordpress/compose'; import { __experimentalStyleProvider as StyleProvider } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; @@ -31,6 +24,7 @@ import { useSelect } from '@wordpress/data'; import { useBlockSelectionClearer } from '../block-selection-clearer'; import { useWritingFlow } from '../writing-flow'; import { getCompatibilityStyles } from './get-compatibility-styles'; +import { useScaleCanvas } from './use-scale-canvas'; import { store as blockEditorStore } from '../../store'; function bubbleEvent( event, Constructor, frame ) { @@ -124,15 +118,9 @@ function Iframe( { const { styles = '', scripts = '' } = resolvedAssets; /** @type {[Document, import('react').Dispatch<Document>]} */ const [ iframeDocument, setIframeDocument ] = useState(); - const initialContainerWidthRef = useRef( 0 ); const [ bodyClasses, setBodyClasses ] = useState( [] ); const clearerRef = useBlockSelectionClearer(); const [ before, writingFlowRef, after ] = useWritingFlow(); - const [ contentResizeListener, { height: contentHeight } ] = - useResizeObserver(); - const [ containerResizeListener, { width: containerWidth } ] = - useResizeObserver(); - const prefersReducedMotion = useReducedMotion(); const setRef = useRefEffect( ( node ) => { node._load = () => { @@ -228,61 +216,16 @@ function Iframe( { }; }, [] ); - const [ iframeWindowInnerHeight, setIframeWindowInnerHeight ] = useState(); - - const iframeResizeRef = useRefEffect( ( node ) => { - const nodeWindow = node.ownerDocument.defaultView; - - setIframeWindowInnerHeight( nodeWindow.innerHeight ); - const onResize = () => { - setIframeWindowInnerHeight( nodeWindow.innerHeight ); - }; - nodeWindow.addEventListener( 'resize', onResize ); - return () => { - nodeWindow.removeEventListener( 'resize', onResize ); - }; - }, [] ); - - const [ windowInnerWidth, setWindowInnerWidth ] = useState(); - - const windowResizeRef = useRefEffect( ( node ) => { - const nodeWindow = node.ownerDocument.defaultView; - - setWindowInnerWidth( nodeWindow.innerWidth ); - const onResize = () => { - setWindowInnerWidth( nodeWindow.innerWidth ); - }; - nodeWindow.addEventListener( 'resize', onResize ); - return () => { - nodeWindow.removeEventListener( 'resize', onResize ); - }; - }, [] ); - - const isZoomedOut = scale !== 1; - - useEffect( () => { - if ( ! isZoomedOut ) { - initialContainerWidthRef.current = containerWidth; - } - }, [ containerWidth, isZoomedOut ] ); - - const scaleContainerWidth = Math.max( - initialContainerWidthRef.current, - containerWidth - ); - - const frameSizeValue = parseInt( frameSize ); - - const maxWidth = 750; - const scaleValue = - scale === 'auto-scaled' - ? ( Math.min( containerWidth, maxWidth ) - frameSizeValue * 2 ) / - scaleContainerWidth - : scale; - - const prevScaleRef = useRef( scaleValue ); - const prevFrameSizeRef = useRef( frameSizeValue ); - const prevClientHeightRef = useRef( /* Initialized in the useEffect. */ ); + const { + contentResizeListener, + containerResizeListener, + isZoomedOut, + scaleContainerWidth, + } = useScaleCanvas( { + scale, + frameSize: parseInt( frameSize ), + iframeDocument, + } ); const disabledRef = useDisabled( { isDisabled: ! readonly } ); const bodyRef = useMergeRefs( [ @@ -291,10 +234,6 @@ function Iframe( { clearerRef, writingFlowRef, disabledRef, - // Avoid resize listeners when not needed, these will trigger - // unnecessary re-renders when animating the iframe width, or when - // expanding preview iframes. - isZoomedOut ? iframeResizeRef : null, ] ); // Correct doctype is required to enable rendering in standards @@ -336,245 +275,6 @@ function Iframe( { useEffect( () => cleanup, [ cleanup ] ); - useEffect( () => { - if ( - ! iframeDocument || - // HACK: Checking if isZoomedOut differs from prevIsZoomedOut here - // instead of the dependency array to appease the linter. - ( scaleValue === 1 ) === ( prevScaleRef.current === 1 ) - ) { - return; - } - - // Unscaled height of the current iframe container. - const clientHeight = iframeDocument.documentElement.clientHeight; - - // Scaled height of the current iframe content. - const scrollHeight = iframeDocument.documentElement.scrollHeight; - - // Previous scale value. - const prevScale = prevScaleRef.current; - - // Unscaled size of the previous padding around the iframe content. - const prevFrameSize = prevFrameSizeRef.current; - - // Unscaled height of the previous iframe container. - const prevClientHeight = prevClientHeightRef.current ?? clientHeight; - - // We can't trust the set value from contentHeight, as it was measured - // before the zoom out mode was changed. After zoom out mode is changed, - // appenders may appear or disappear, so we need to get the height from - // the iframe at this point when we're about to animate the zoom out. - // The iframe scrollTop, scrollHeight, and clientHeight will all be - // accurate. The client height also does change when the zoom out mode - // is toggled, as the bottom bar about selecting the template is - // added/removed when toggling zoom out mode. - const scrollTop = iframeDocument.documentElement.scrollTop; - - // Step 0: Start with the current scrollTop. - let scrollTopNext = scrollTop; - - // Step 1: Undo the effects of the previous scale and frame around the - // midpoint of the visible area. - scrollTopNext = - ( scrollTopNext + prevClientHeight / 2 - prevFrameSize ) / - prevScale - - prevClientHeight / 2; - - // Step 2: Apply the new scale and frame around the midpoint of the - // visible area. - scrollTopNext = - ( scrollTopNext + clientHeight / 2 ) * scaleValue + - frameSizeValue - - clientHeight / 2; - - // Step 3: Handle an edge case so that you scroll to the top of the - // iframe if the top of the iframe content is visible in the container. - // The same edge case for the bottom is skipped because changing content - // makes calculating it impossible. - scrollTopNext = scrollTop <= prevFrameSize ? 0 : scrollTopNext; - - // This is the scrollTop value if you are scrolled to the bottom of the - // iframe. We can't just let the browser handle it because we need to - // animate the scaling. - const maxScrollTop = - scrollHeight * ( scaleValue / prevScale ) + - frameSizeValue * 2 - - clientHeight; - - // Step 4: Clamp the scrollTopNext between the minimum and maximum - // possible scrollTop positions. Round the value to avoid subpixel - // truncation by the browser which sometimes causes a 1px error. - scrollTopNext = Math.round( - Math.min( - Math.max( 0, scrollTopNext ), - Math.max( 0, maxScrollTop ) - ) - ); - - iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-scroll-top', - `${ scrollTop }px` - ); - - iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-scroll-top-next', - `${ scrollTopNext }px` - ); - - iframeDocument.documentElement.classList.add( 'zoom-out-animation' ); - - function onZoomOutTransitionEnd() { - // Remove the position fixed for the animation. - iframeDocument.documentElement.classList.remove( - 'zoom-out-animation' - ); - - // Update previous values. - prevClientHeightRef.current = clientHeight; - prevFrameSizeRef.current = frameSizeValue; - prevScaleRef.current = scaleValue; - - // Set the final scroll position that was just animated to. - // Disable reason: Eslint isn't smart enough to know that this is a - // DOM element. https://github.com/facebook/react/issues/31483 - // eslint-disable-next-line react-compiler/react-compiler - iframeDocument.documentElement.scrollTop = scrollTopNext; - } - - let raf; - if ( prefersReducedMotion ) { - // Hack: Wait for the window values to recalculate. - raf = iframeDocument.defaultView.requestAnimationFrame( - onZoomOutTransitionEnd - ); - } else { - iframeDocument.documentElement.addEventListener( - 'transitionend', - onZoomOutTransitionEnd, - { once: true } - ); - } - - return () => { - iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-scroll-top' - ); - iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-scroll-top-next' - ); - iframeDocument.documentElement.classList.remove( - 'zoom-out-animation' - ); - if ( prefersReducedMotion ) { - iframeDocument.defaultView.cancelAnimationFrame( raf ); - } else { - iframeDocument.documentElement.removeEventListener( - 'transitionend', - onZoomOutTransitionEnd - ); - } - }; - }, [ iframeDocument, scaleValue, frameSizeValue, prefersReducedMotion ] ); - - // Toggle zoom out CSS Classes only when zoom out mode changes. We could add these into the useEffect - // that controls settings the CSS variables, but then we would need to do more work to ensure we're - // only toggling these when the zoom out mode changes, as that useEffect is also triggered by a large - // number of dependencies. - useEffect( () => { - if ( ! iframeDocument ) { - return; - } - - if ( isZoomedOut ) { - iframeDocument.documentElement.classList.add( 'is-zoomed-out' ); - } else { - // HACK: Since we can't remove this in the cleanup, we need to do it here. - iframeDocument.documentElement.classList.remove( 'is-zoomed-out' ); - } - - return () => { - // HACK: Skipping cleanup because it causes issues with the zoom out - // animation. More refactoring is needed to fix this properly. - // iframeDocument.documentElement.classList.remove( 'is-zoomed-out' ); - }; - }, [ iframeDocument, isZoomedOut ] ); - - // Calculate the scaling and CSS variables for the zoom out canvas - useEffect( () => { - if ( ! iframeDocument ) { - return; - } - - // Note: When we initialize the zoom out when the canvas is smaller (sidebars open), - // initialContainerWidthRef will be smaller than the full page, and reflow will happen - // when the canvas area becomes larger due to sidebars closing. This is a known but - // minor divergence for now. - - // This scaling calculation has to happen within the JS because CSS calc() can - // only divide and multiply by a unitless value. I.e. calc( 100px / 2 ) is valid - // but calc( 100px / 2px ) is not. - iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-scale', - scaleValue - ); - - // frameSize has to be a px value for the scaling and frame size to be computed correctly. - iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-frame-size', - typeof frameSize === 'number' ? `${ frameSize }px` : frameSize - ); - iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-content-height', - `${ contentHeight }px` - ); - iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-inner-height', - `${ iframeWindowInnerHeight }px` - ); - iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-container-width', - `${ containerWidth }px` - ); - iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-scale-container-width', - `${ scaleContainerWidth }px` - ); - - return () => { - // HACK: Skipping cleanup because it causes issues with the zoom out - // animation. More refactoring is needed to fix this properly. - // iframeDocument.documentElement.style.removeProperty( - // '--wp-block-editor-iframe-zoom-out-scale' - // ); - // iframeDocument.documentElement.style.removeProperty( - // '--wp-block-editor-iframe-zoom-out-frame-size' - // ); - // iframeDocument.documentElement.style.removeProperty( - // '--wp-block-editor-iframe-zoom-out-content-height' - // ); - // iframeDocument.documentElement.style.removeProperty( - // '--wp-block-editor-iframe-zoom-out-inner-height' - // ); - // iframeDocument.documentElement.style.removeProperty( - // '--wp-block-editor-iframe-zoom-out-container-width' - // ); - // iframeDocument.documentElement.style.removeProperty( - // '--wp-block-editor-iframe-zoom-out-scale-container-width' - // ); - }; - }, [ - scaleValue, - frameSize, - iframeDocument, - iframeWindowInnerHeight, - contentHeight, - containerWidth, - windowInnerWidth, - isZoomedOut, - scaleContainerWidth, - ] ); - // Make sure to not render the before and after focusable div elements in view // mode. They're only needed to capture focus in edit mode. const shouldRenderFocusCaptureElements = tabIndex >= 0 && ! isPreviewMode; @@ -654,7 +354,7 @@ function Iframe( { ); return ( - <div className="block-editor-iframe__container" ref={ windowResizeRef }> + <div className="block-editor-iframe__container"> { containerResizeListener } <div className={ clsx( diff --git a/packages/block-editor/src/components/iframe/use-scale-canvas.js b/packages/block-editor/src/components/iframe/use-scale-canvas.js new file mode 100644 index 00000000000000..c72266e82e2b0a --- /dev/null +++ b/packages/block-editor/src/components/iframe/use-scale-canvas.js @@ -0,0 +1,468 @@ +/** + * WordPress dependencies + */ +import { useEffect, useRef, useCallback } from '@wordpress/element'; +import { useReducedMotion, useResizeObserver } from '@wordpress/compose'; + +/** + * @typedef {Object} TransitionState + * @property {number} scaleValue Scale of the canvas. + * @property {number} frameSize Size of the frame/offset around the canvas. + * @property {number} clientHeight ClientHeight of the iframe. + * @property {number} scrollTop ScrollTop of the iframe. + * @property {number} scrollHeight ScrollHeight of the iframe. + */ + +/** + * Calculate the scale of the canvas. + * + * @param {Object} options Object of options + * @param {number} options.frameSize Size of the frame/offset around the canvas + * @param {number} options.containerWidth Actual width of the canvas container + * @param {number} options.maxContainerWidth Maximum width of the container to use for the scale calculation. This locks the canvas to a maximum width when zooming out. + * @param {number} options.scaleContainerWidth Width the of the container wrapping the canvas container + * @return {number} Scale value between 0 and/or equal to 1 + */ +function calculateScale( { + frameSize, + containerWidth, + maxContainerWidth, + scaleContainerWidth, +} ) { + return ( + ( Math.min( containerWidth, maxContainerWidth ) - frameSize * 2 ) / + scaleContainerWidth + ); +} + +/** + * Compute the next scrollTop position after scaling the iframe content. + * + * @param {TransitionState} transitionFrom Starting point of the transition + * @param {TransitionState} transitionTo Ending state of the transition + * @return {number} Next scrollTop position after scaling the iframe content. + */ +function computeScrollTopNext( transitionFrom, transitionTo ) { + const { + clientHeight: prevClientHeight, + frameSize: prevFrameSize, + scaleValue: prevScale, + scrollTop, + scrollHeight, + } = transitionFrom; + const { clientHeight, frameSize, scaleValue } = transitionTo; + // Step 0: Start with the current scrollTop. + let scrollTopNext = scrollTop; + // Step 1: Undo the effects of the previous scale and frame around the + // midpoint of the visible area. + scrollTopNext = + ( scrollTopNext + prevClientHeight / 2 - prevFrameSize ) / prevScale - + prevClientHeight / 2; + + // Step 2: Apply the new scale and frame around the midpoint of the + // visible area. + scrollTopNext = + ( scrollTopNext + clientHeight / 2 ) * scaleValue + + frameSize - + clientHeight / 2; + + // Step 3: Handle an edge case so that you scroll to the top of the + // iframe if the top of the iframe content is visible in the container. + // The same edge case for the bottom is skipped because changing content + // makes calculating it impossible. + scrollTopNext = scrollTop <= prevFrameSize ? 0 : scrollTopNext; + + // This is the scrollTop value if you are scrolled to the bottom of the + // iframe. We can't just let the browser handle it because we need to + // animate the scaling. + const maxScrollTop = + scrollHeight * ( scaleValue / prevScale ) + + frameSize * 2 - + clientHeight; + + // Step 4: Clamp the scrollTopNext between the minimum and maximum + // possible scrollTop positions. Round the value to avoid subpixel + // truncation by the browser which sometimes causes a 1px error. + return Math.round( + Math.min( Math.max( 0, scrollTopNext ), Math.max( 0, maxScrollTop ) ) + ); +} + +/** + * Generate the keyframes to use for the zoom out animation. + * + * @param {TransitionState} transitionFrom Starting transition state. + * @param {TransitionState} transitionTo Ending transition state. + * @return {Object[]} An array of keyframes to use for the animation. + */ +function getAnimationKeyframes( transitionFrom, transitionTo ) { + const { + scaleValue: prevScale, + frameSize: prevFrameSize, + scrollTop, + } = transitionFrom; + const { scaleValue, frameSize, scrollTop: scrollTopNext } = transitionTo; + + return [ + { + translate: `0 0`, + scale: prevScale, + paddingTop: `${ prevFrameSize / prevScale }px`, + paddingBottom: `${ prevFrameSize / prevScale }px`, + }, + { + translate: `0 ${ scrollTop - scrollTopNext }px`, + scale: scaleValue, + paddingTop: `${ frameSize / scaleValue }px`, + paddingBottom: `${ frameSize / scaleValue }px`, + }, + ]; +} + +/** + * @typedef {Object} ScaleCanvasResult + * @property {boolean} isZoomedOut A boolean indicating if the canvas is zoomed out. + * @property {number} scaleContainerWidth The width of the container used to calculate the scale. + * @property {Object} contentResizeListener A resize observer for the content. + * @property {Object} containerResizeListener A resize observer for the container. + */ + +/** + * Handles scaling the canvas for the zoom out mode and animating between + * the states. + * + * @param {Object} options Object of options. + * @param {number} options.frameSize Size of the frame around the content. + * @param {Document} options.iframeDocument Document of the iframe. + * @param {number} options.maxContainerWidth Max width of the canvas to use as the starting scale point. Defaults to 750. + * @param {number|string} options.scale Scale of the canvas. Can be an decimal between 0 and 1, 1, or 'auto-scaled'. + * @return {ScaleCanvasResult} Properties of the result. + */ +export function useScaleCanvas( { + frameSize, + iframeDocument, + maxContainerWidth = 750, + scale, +} ) { + const [ contentResizeListener, { height: contentHeight } ] = + useResizeObserver(); + const [ containerResizeListener, { width: containerWidth } ] = + useResizeObserver(); + + const initialContainerWidthRef = useRef( 0 ); + const isZoomedOut = scale !== 1; + const prefersReducedMotion = useReducedMotion(); + const isAutoScaled = scale === 'auto-scaled'; + // Track if the animation should start when the useEffect runs. + const startAnimationRef = useRef( false ); + // Track the animation so we know if we have an animation running, + // and can cancel it, reverse it, call a finish event, etc. + const animationRef = useRef( null ); + + useEffect( () => { + if ( ! isZoomedOut ) { + initialContainerWidthRef.current = containerWidth; + } + }, [ containerWidth, isZoomedOut ] ); + + const scaleContainerWidth = Math.max( + initialContainerWidthRef.current, + containerWidth + ); + + const scaleValue = isAutoScaled + ? calculateScale( { + frameSize, + containerWidth, + maxContainerWidth, + scaleContainerWidth, + } ) + : scale; + + /** + * The starting transition state for the zoom out animation. + * @type {import('react').RefObject<TransitionState>} + */ + const transitionFromRef = useRef( { + scaleValue, + frameSize, + clientHeight: 0, + scrollTop: 0, + scrollHeight: 0, + } ); + + /** + * The ending transition state for the zoom out animation. + * @type {import('react').RefObject<TransitionState>} + */ + const transitionToRef = useRef( { + scaleValue, + frameSize, + clientHeight: 0, + scrollTop: 0, + scrollHeight: 0, + } ); + + /** + * Start the zoom out animation. This sets the necessary CSS variables + * for animating the canvas and returns the Animation object. + * + * @return {Animation} The animation object for the zoom out animation. + */ + const startZoomOutAnimation = useCallback( () => { + const { scrollTop } = transitionFromRef.current; + const { scrollTop: scrollTopNext } = transitionToRef.current; + + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-scroll-top', + `${ scrollTop }px` + ); + + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-scroll-top-next', + `${ scrollTopNext }px` + ); + + iframeDocument.documentElement.classList.add( 'zoom-out-animation' ); + + return iframeDocument.documentElement.animate( + getAnimationKeyframes( + transitionFromRef.current, + transitionToRef.current + ), + { + easing: 'cubic-bezier(0.46, 0.03, 0.52, 0.96)', + duration: 400, + } + ); + }, [ iframeDocument ] ); + + /** + * Callback when the zoom out animation is finished. + * - Cleans up animations refs. + * - Adds final CSS vars for scale and frame size to preserve the state. + * - Removes the 'zoom-out-animation' class (which has the fixed positioning). + * - Sets the final scroll position after the canvas is no longer in fixed position. + * - Removes CSS vars related to the animation. + * - Sets the transitionFrom to the transitionTo state to be ready for the next animation. + */ + const finishZoomOutAnimation = useCallback( () => { + startAnimationRef.current = false; + animationRef.current = null; + + // Add our final scale and frame size now that the animation is done. + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-scale', + transitionToRef.current.scaleValue + ); + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-frame-size', + `${ transitionToRef.current.frameSize }px` + ); + + iframeDocument.documentElement.classList.remove( 'zoom-out-animation' ); + + // Set the final scroll position that was just animated to. + // Disable reason: Eslint isn't smart enough to know that this is a + // DOM element. https://github.com/facebook/react/issues/31483 + // eslint-disable-next-line react-compiler/react-compiler + iframeDocument.documentElement.scrollTop = + transitionToRef.current.scrollTop; + + iframeDocument.documentElement.style.removeProperty( + '--wp-block-editor-iframe-zoom-out-scroll-top' + ); + iframeDocument.documentElement.style.removeProperty( + '--wp-block-editor-iframe-zoom-out-scroll-top-next' + ); + + // Update previous values. + transitionFromRef.current = transitionToRef.current; + }, [ iframeDocument ] ); + + /** + * Runs when zoom out mode is toggled, and sets the startAnimation flag + * so the animation will start when the next useEffect runs. We _only_ + * want to animate when the zoom out mode is toggled, not when the scale + * changes due to the container resizing. + */ + useEffect( () => { + if ( ! iframeDocument ) { + return; + } + + if ( isZoomedOut ) { + iframeDocument.documentElement.classList.add( 'is-zoomed-out' ); + } + + startAnimationRef.current = true; + + return () => { + iframeDocument.documentElement.classList.remove( 'is-zoomed-out' ); + }; + }, [ iframeDocument, isZoomedOut ] ); + + /** + * This handles: + * 1. Setting the correct scale and vars of the canvas when zoomed out + * 2. If zoom out mode has been toggled, runs the animation of zooming in/out + */ + useEffect( () => { + if ( ! iframeDocument ) { + return; + } + + // We need to update the appropriate scale to exit from. If sidebars have been opened since setting the + // original scale, we will snap to a much smaller scale due to the scale container immediately changing sizes when exiting. + if ( isAutoScaled && transitionFromRef.current.scaleValue !== 1 ) { + // We use containerWidth as the divisor, as scaleContainerWidth will always match the containerWidth when + // exiting. + transitionFromRef.current.scaleValue = calculateScale( { + frameSize: transitionFromRef.current.frameSize, + containerWidth, + maxContainerWidth, + scaleContainerWidth: containerWidth, + } ); + } + + // If we are not going to animate the transition, set the scale and frame size directly. + // If we are animating, these values will be set when the animation is finished. + // Example: Opening sidebars that reduce the scale of the canvas, but we don't want to + // animate the transition. + if ( ! startAnimationRef.current ) { + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-scale', + scaleValue + ); + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-frame-size', + `${ frameSize }px` + ); + } + + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-content-height', + `${ contentHeight }px` + ); + + const clientHeight = iframeDocument.documentElement.clientHeight; + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-inner-height', + `${ clientHeight }px` + ); + + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-container-width', + `${ containerWidth }px` + ); + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-scale-container-width', + `${ scaleContainerWidth }px` + ); + + /** + * Handle the zoom out animation: + * + * - Get the current scrollTop position. + * - Calculate where the same scroll position is after scaling. + * - Apply fixed positioning to the canvas with a transform offset + * to keep the canvas centered. + * - Animate the scale and padding to the new scale and frame size. + * - After the animation is complete, remove the fixed positioning + * and set the scroll position that keeps everything centered. + */ + if ( startAnimationRef.current ) { + // Don't allow a new transition to start again unless it was started by the zoom out mode changing. + startAnimationRef.current = false; + + /** + * If we already have an animation running, reverse it. + */ + if ( animationRef.current ) { + animationRef.current.reverse(); + // Swap the transition to/from refs so that we set the correct values when + // finishZoomOutAnimation runs. + const tempTransitionFrom = transitionFromRef.current; + const tempTransitionTo = transitionToRef.current; + transitionFromRef.current = tempTransitionTo; + transitionToRef.current = tempTransitionFrom; + } else { + /** + * Start a new zoom animation. + */ + + // We can't trust the set value from contentHeight, as it was measured + // before the zoom out mode was changed. After zoom out mode is changed, + // appenders may appear or disappear, so we need to get the height from + // the iframe at this point when we're about to animate the zoom out. + // The iframe scrollTop, scrollHeight, and clientHeight will all be + // the most accurate. + transitionFromRef.current.clientHeight = + transitionFromRef.current.clientHeight ?? clientHeight; + transitionFromRef.current.scrollTop = + iframeDocument.documentElement.scrollTop; + transitionFromRef.current.scrollHeight = + iframeDocument.documentElement.scrollHeight; + + transitionToRef.current = { + scaleValue, + frameSize, + clientHeight, + }; + transitionToRef.current.scrollTop = computeScrollTopNext( + transitionFromRef.current, + transitionToRef.current + ); + + animationRef.current = startZoomOutAnimation(); + + // If the user prefers reduced motion, finish the animation immediately and set the final state. + if ( prefersReducedMotion ) { + finishZoomOutAnimation(); + } else { + animationRef.current.onfinish = finishZoomOutAnimation; + } + } + } + + return () => { + iframeDocument.documentElement.style.removeProperty( + '--wp-block-editor-iframe-zoom-out-scale' + ); + iframeDocument.documentElement.style.removeProperty( + '--wp-block-editor-iframe-zoom-out-frame-size' + ); + iframeDocument.documentElement.style.removeProperty( + '--wp-block-editor-iframe-zoom-out-content-height' + ); + iframeDocument.documentElement.style.removeProperty( + '--wp-block-editor-iframe-zoom-out-inner-height' + ); + iframeDocument.documentElement.style.removeProperty( + '--wp-block-editor-iframe-zoom-out-container-width' + ); + iframeDocument.documentElement.style.removeProperty( + '--wp-block-editor-iframe-zoom-out-scale-container-width' + ); + }; + }, [ + startZoomOutAnimation, + finishZoomOutAnimation, + prefersReducedMotion, + isAutoScaled, + scaleValue, + frameSize, + iframeDocument, + contentHeight, + containerWidth, + maxContainerWidth, + scaleContainerWidth, + ] ); + + return { + isZoomedOut, + scaleContainerWidth, + contentResizeListener, + containerResizeListener, + }; +} From ee17975f5cdbd62211c933d1db6854ac467a03d3 Mon Sep 17 00:00:00 2001 From: Nick Diego <nick.diego@automattic.com> Date: Wed, 27 Nov 2024 02:21:05 -0600 Subject: [PATCH 1723/1908] Social Link: Add contentOnly editing support (#66622) Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- .../block-library/src/social-link/block.json | 6 ++- .../block-library/src/social-link/edit.js | 40 +++++++++++++++++++ .../block-library/src/social-link/editor.scss | 5 +++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/social-link/block.json b/packages/block-library/src/social-link/block.json index 37e8376f22ff09..667fd74b208f29 100644 --- a/packages/block-library/src/social-link/block.json +++ b/packages/block-library/src/social-link/block.json @@ -9,13 +9,15 @@ "textdomain": "default", "attributes": { "url": { - "type": "string" + "type": "string", + "role": "content" }, "service": { "type": "string" }, "label": { - "type": "string" + "type": "string", + "role": "content" }, "rel": { "type": "string" diff --git a/packages/block-library/src/social-link/edit.js b/packages/block-library/src/social-link/edit.js index 14b0f11334a091..91f1e4170b33dd 100644 --- a/packages/block-library/src/social-link/edit.js +++ b/packages/block-library/src/social-link/edit.js @@ -10,18 +10,22 @@ import { DELETE, BACKSPACE, ENTER } from '@wordpress/keycodes'; import { useDispatch } from '@wordpress/data'; import { + BlockControls, InspectorControls, URLPopover, URLInput, + useBlockEditingMode, useBlockProps, store as blockEditorStore, } from '@wordpress/block-editor'; import { useState, useRef } from '@wordpress/element'; import { Button, + Dropdown, PanelBody, PanelRow, TextControl, + ToolbarButton, __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper, } from '@wordpress/components'; import { useMergeRefs } from '@wordpress/compose'; @@ -130,6 +134,7 @@ const SocialLinkEdit = ( { // Use internal state instead of a ref to make sure that the component // re-renders when the popover's anchor updates. const [ popoverAnchor, setPopoverAnchor ] = useState( null ); + const isContentOnlyMode = useBlockEditingMode() === 'contentOnly'; const IconComponent = getIconBySite( service ); const socialLinkName = getNameBySite( service ); @@ -154,6 +159,41 @@ const SocialLinkEdit = ( { return ( <> + { isContentOnlyMode && showLabels && ( + // Add an extra control to modify the label attribute when content only mode is active. + // With content only mode active, the inspector is hidden, so users need another way + // to edit this attribute. + <BlockControls group="other"> + <Dropdown + popoverProps={ { position: 'bottom right' } } + renderToggle={ ( { isOpen, onToggle } ) => ( + <ToolbarButton + onClick={ onToggle } + aria-haspopup="true" + aria-expanded={ isOpen } + > + { __( 'Text' ) } + </ToolbarButton> + ) } + renderContent={ () => ( + <TextControl + __next40pxDefaultSize + __nextHasNoMarginBottom + className="wp-block-social-link__toolbar_content_text" + label={ __( 'Text' ) } + help={ __( + 'Provide a text label or use the default.' + ) } + value={ label } + onChange={ ( value ) => + setAttributes( { label: value } ) + } + placeholder={ socialLinkName } + /> + ) } + /> + </BlockControls> + ) } <InspectorControls> <PanelBody title={ __( 'Settings' ) }> <PanelRow> diff --git a/packages/block-library/src/social-link/editor.scss b/packages/block-library/src/social-link/editor.scss index 2e93c9447cca8d..d61cf7c1a7cf56 100644 --- a/packages/block-library/src/social-link/editor.scss +++ b/packages/block-library/src/social-link/editor.scss @@ -38,3 +38,8 @@ :root :where(.wp-block-social-links.is-style-logos-only .wp-social-link button) { padding: 0; } + +.wp-block-social-link__toolbar_content_text { + // Corresponds to the size of the text control input in the block inspector. + width: 250px; +} From 0f6ab5d720aa70e5982e61a3bc8e3a31b0974ac9 Mon Sep 17 00:00:00 2001 From: dhruvang21 <105810308+dhruvang21@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:02:10 +0530 Subject: [PATCH 1724/1908] Try dark toolbar for the write mode (#66116) Co-authored-by: dhruvang21 <dhruvang21@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: hanneslsm <hanneslsm@git.wordpress.org> --- .../src/components/block-toolbar/index.js | 8 ++++ .../src/components/block-tools/style.scss | 39 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index ea068d8126526c..63b2f6ad7f9a03 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -74,6 +74,8 @@ export function PrivateBlockToolbar( { showGroupButtons, showLockButtons, showSwitchSectionStyleButton, + hasFixedToolbar, + isNavigationMode, } = useSelect( ( select ) => { const { getBlockName, @@ -85,8 +87,10 @@ export function PrivateBlockToolbar( { getBlockAttributes, getBlockParentsByBlockName, getTemplateLock, + getSettings, getParentSectionBlock, isZoomOut, + isNavigationMode: _isNavigationMode, } = unlock( select( blockEditorStore ) ); const selectedBlockClientIds = getSelectedBlockClientIds(); const selectedBlockClientId = selectedBlockClientIds[ 0 ]; @@ -119,6 +123,7 @@ export function PrivateBlockToolbar( { const _hasTemplateLock = selectedBlockClientIds.some( ( id ) => getTemplateLock( id ) === 'contentOnly' ); + return { blockClientId: selectedBlockClientId, blockClientIds: selectedBlockClientIds, @@ -144,6 +149,8 @@ export function PrivateBlockToolbar( { showGroupButtons: ! isZoomOut(), showLockButtons: ! isZoomOut(), showSwitchSectionStyleButton: isZoomOut(), + hasFixedToolbar: getSettings().hasFixedToolbar, + isNavigationMode: _isNavigationMode(), }; }, [] ); @@ -170,6 +177,7 @@ export function PrivateBlockToolbar( { // Shifts the toolbar to make room for the parent block selector. const classes = clsx( 'block-editor-block-contextual-toolbar', { 'has-parent': showParentSelector, + 'is-inverted-toolbar': isNavigationMode && ! hasFixedToolbar, } ); const innerClasses = clsx( 'block-editor-block-toolbar', { diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index b553d42668cf38..0ed9c138519d29 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -139,6 +139,45 @@ border-right-color: $gray-900; } + .is-inverted-toolbar { + background-color: $gray-900; + color: $gray-100; + + &.block-editor-block-contextual-toolbar { + border-color: $gray-800; + } + + button { + color: $gray-300; + + &:hover { + color: $white; + } + + &:focus::before { + box-shadow: inset 0 0 0 1px $gray-900, 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + } + } + + .block-editor-block-parent-selector .block-editor-block-parent-selector__button { + border-color: $gray-800; + background-color: $gray-900; + } + + .block-editor-block-switcher__toggle { + color: $gray-100; + } + + .components-toolbar-group, + .components-toolbar { + border-right-color: $gray-800 !important; + } + + .is-pressed { + color: var(--wp-admin-theme-color); + } + } + // Hide the block toolbar if the insertion point is shown. &.is-insertion-point-visible { visibility: hidden; From 9904fd31d955bd9a75dc9005230310737939e90b Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 27 Nov 2024 10:18:41 +0000 Subject: [PATCH 1725/1908] Bump plugin version to 19.8.0-rc.1 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 3e4d6941b5a0f3..40c4e86fbb1bf5 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.6 * Requires PHP: 7.2 - * Version: 19.7.0 + * Version: 19.8.0-rc.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 1fc9131a33c8c3..7ff4ea41dc618e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.7.0", + "version": "19.8.0-rc.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.7.0", + "version": "19.8.0-rc.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", "workspaces": [ diff --git a/package.json b/package.json index 41102f867f0e22..53192f9af71b17 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.7.0", + "version": "19.8.0-rc.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 738d5bf9fdf7429a484835d2f9462bc448de1f59 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Wed, 27 Nov 2024 10:24:15 +0000 Subject: [PATCH 1726/1908] Fix: Duplicate template part refers to original name instead of duplicated name. (#67329) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> --- .../src/dataviews/actions/duplicate-template-part.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/editor/src/dataviews/actions/duplicate-template-part.tsx b/packages/editor/src/dataviews/actions/duplicate-template-part.tsx index 95e7e6bb672fcc..5f576ecdb58639 100644 --- a/packages/editor/src/dataviews/actions/duplicate-template-part.tsx +++ b/packages/editor/src/dataviews/actions/duplicate-template-part.tsx @@ -15,7 +15,7 @@ import type { Action } from '@wordpress/dataviews'; import { TEMPLATE_PART_POST_TYPE } from '../../store/constants'; import { CreateTemplatePartModalContents } from '../../components/create-template-part-modal'; import { getItemTitle } from './utils'; -import type { TemplatePart } from '../types'; +import type { Post, TemplatePart } from '../types'; const duplicateTemplatePart: Action< TemplatePart > = { id: 'duplicate-template-part', @@ -38,12 +38,12 @@ const duplicateTemplatePart: Action< TemplatePart > = { ); }, [ item.content, item.blocks ] ); const { createSuccessNotice } = useDispatch( noticesStore ); - function onTemplatePartSuccess() { + function onTemplatePartSuccess( templatePart: Post ) { createSuccessNotice( sprintf( // translators: %s: The new template part's title e.g. 'Call to action (copy)'. _x( '"%s" duplicated.', 'template part' ), - getItemTitle( item ) + getItemTitle( templatePart ) ), { type: 'snackbar', id: 'edit-site-patterns-success' } ); From 14adfdb96499700e7096561042e0e073df241859 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 27 Nov 2024 11:29:09 +0100 Subject: [PATCH 1727/1908] DataViews: WP Specific build (#66825) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: luisherranz <luisherranz@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: louwie17 <louwie17@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: Tropicalista <tropicalista@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: manzoorwanijk <manzoorwanijk@git.wordpress.org> --- .gitignore | 1 + package-lock.json | 1 + package.json | 4 ++- packages/dataviews/README.md | 2 ++ packages/dataviews/build.js | 33 +++++++++++++++++++ packages/dataviews/package.json | 17 ++++++++++ .../lib/util.js | 1 + tools/webpack/packages.js | 1 + 8 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 packages/dataviews/build.js diff --git a/.gitignore b/.gitignore index 4cd1d9706b7370..1d75f9f429d869 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ build build-module build-style build-types +build-wp node_modules gutenberg.zip coverage diff --git a/package-lock.json b/package-lock.json index 7ff4ea41dc618e..7e19737654b9aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -84,6 +84,7 @@ "cssnano": "6.0.1", "deep-freeze": "0.0.1", "equivalent-key-map": "0.2.2", + "esbuild": "0.18.20", "escape-html": "1.0.3", "eslint-import-resolver-node": "0.3.4", "eslint-plugin-eslint-comments": "3.1.2", diff --git a/package.json b/package.json index 53192f9af71b17..3ddcb981f6f6f7 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,7 @@ "cssnano": "6.0.1", "deep-freeze": "0.0.1", "equivalent-key-map": "0.2.2", + "esbuild": "0.18.20", "escape-html": "1.0.3", "eslint-import-resolver-node": "0.3.4", "eslint-plugin-eslint-comments": "3.1.2", @@ -177,9 +178,10 @@ "build:package-types": "node ./bin/packages/validate-typescript-version.js && ( tsc --build || ( echo 'tsc failed. Try cleaning up first: `npm run clean:package-types`'; exit 1 ) ) && node ./bin/packages/check-build-type-declaration-files.js", "prebuild:packages": "npm run clean:packages && npm run --if-present --workspaces build", "build:packages": "npm run --silent build:package-types && node ./bin/packages/build.js", + "postbuild:packages": " npm run --if-present --workspaces build:wp", "build:plugin-zip": "bash ./bin/build-plugin-zip.sh", "clean:package-types": "tsc --build --clean && rimraf \"./packages/*/build-types\"", - "clean:packages": "rimraf \"./packages/*/@(build|build-module|build-style)\"", + "clean:packages": "rimraf \"./packages/*/@(build|build-module|build-wp|build-style)\"", "component-usage-stats": "node ./node_modules/react-scanner/bin/react-scanner -c ./react-scanner.config.js", "dev": "cross-env NODE_ENV=development npm run build:packages && concurrently \"wp-scripts start\" \"npm run dev:packages\"", "dev:packages": "cross-env NODE_ENV=development concurrently \"node ./bin/packages/watch.js\" \"tsc --build --watch\"", diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 92426bf1e1f838..04b8a40ff3fa7e 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -17,6 +17,8 @@ npm install @wordpress/dataviews --save <div class="callout callout-info">At <a href="https://wordpress.github.io/gutenberg/">WordPress Gutenberg's Storybook</a> there's and <a href="https://wordpress.github.io/gutenberg/?path=/docs/dataviews-dataviews--docs">example implementation of the Dataviews component</a>.</div> +**Important note** If you're trying to use the `DataViews` component in a WordPress plugin or theme and you're building your scripts using the `@wordpress/scripts` package, you need to import the components from `@wordpress/dataviews/wp` instead of `@wordpress/dataviews`. + ### Usage The `DataViews` component receives data and some other configuration to render the dataset. It'll call the `onChangeView` callback every time the user has interacted with the dataset in some way (sorted, filtered, changed layout, etc.): diff --git a/packages/dataviews/build.js b/packages/dataviews/build.js new file mode 100644 index 00000000000000..582826d18c1847 --- /dev/null +++ b/packages/dataviews/build.js @@ -0,0 +1,33 @@ +/** + * External dependencies + */ +// eslint-disable-next-line import/no-extraneous-dependencies +const esbuild = require( 'esbuild' ); + +const wpExternals = { + name: 'wordpress-externals', + setup( build ) { + build.onResolve( { filter: /^@wordpress\// }, () => { + // Bundle wordpress packages + return { external: false }; + } ); + build.onResolve( { filter: /^\.[\.\/]/ }, () => { + // Bundle relative paths + return { external: false }; + } ); + build.onResolve( { filter: /.+/ }, ( args ) => { + // Mark everything else as external + return { path: args.path, external: true }; + } ); + }, +}; + +esbuild.build( { + entryPoints: [ 'src/index.ts' ], + bundle: true, + outdir: 'build-wp', + plugins: [ wpExternals ], + jsx: 'automatic', + logLevel: 'info', + format: 'esm', +} ); diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index 80cfbf24be5651..06b13d1697a99b 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -24,6 +24,20 @@ }, "main": "build/index.js", "module": "build-module/index.js", + "exports": { + ".": { + "types": "./build-types/index.d.ts", + "import": "./build-module/index.js" + }, + "./wp": { + "types": "./build-types/index.d.ts", + "default": "./build-wp/index.js" + }, + "./package.json": { + "default": "./package.json" + }, + "./build-style/": "./build-style/" + }, "react-native": "src/index", "wpScript": true, "types": "build-types", @@ -48,5 +62,8 @@ }, "publishConfig": { "access": "public" + }, + "scripts": { + "build:wp": "node build" } } diff --git a/packages/dependency-extraction-webpack-plugin/lib/util.js b/packages/dependency-extraction-webpack-plugin/lib/util.js index cc999860244760..49b16986cda814 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/util.js +++ b/packages/dependency-extraction-webpack-plugin/lib/util.js @@ -5,6 +5,7 @@ const WORDPRESS_NAMESPACE = '@wordpress/'; // !! const BUNDLED_PACKAGES = [ '@wordpress/dataviews', + '@wordpress/dataviews/wp', '@wordpress/icons', '@wordpress/interface', '@wordpress/sync', diff --git a/tools/webpack/packages.js b/tools/webpack/packages.js index 1dc396a4d75a15..4459cc063d0016 100644 --- a/tools/webpack/packages.js +++ b/tools/webpack/packages.js @@ -36,6 +36,7 @@ const WORDPRESS_NAMESPACE = '@wordpress/'; // !! const BUNDLED_PACKAGES = [ '@wordpress/dataviews', + '@wordpress/dataviews/wp', '@wordpress/icons', '@wordpress/interface', '@wordpress/sync', From b9b422bfe4f334f05d81115d8b6a7ccacbdb2150 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 27 Nov 2024 10:45:28 +0000 Subject: [PATCH 1728/1908] Update Changelog for 19.8.0-rc.1 --- changelog.txt | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) diff --git a/changelog.txt b/changelog.txt index 1a6b45a37fc7cf..bf13c6b273e9b6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,253 @@ == Changelog == += 19.8.0-rc.1 = + + +## Changelog + +### Enhancements + +#### Block Library +- Details block: Use summary content as default label. ([67217](https://github.com/WordPress/gutenberg/pull/67217)) +- Make social icon navigation one arrow keypress. ([64883](https://github.com/WordPress/gutenberg/pull/64883)) +- Page List : Add border and spacing support. ([66385](https://github.com/WordPress/gutenberg/pull/66385)) +- Query Loop block: Remove 'add new post' prompt in the sidebar. ([67189](https://github.com/WordPress/gutenberg/pull/67189)) +- Query block: Update Enhanced Pagination help text. ([67173](https://github.com/WordPress/gutenberg/pull/67173)) +- Social Link: Add contentOnly editing support. ([66622](https://github.com/WordPress/gutenberg/pull/66622)) + +#### Components +- Autocomplete: Increase option height. ([67214](https://github.com/WordPress/gutenberg/pull/67214)) +- CircularOptionPicker: Update Button sizes. ([67285](https://github.com/WordPress/gutenberg/pull/67285)) +- ColorPalette: Disable `Clear` button if there's no color value. ([67108](https://github.com/WordPress/gutenberg/pull/67108)) +- ColorPicker: Update sizes of format select and copy button. ([67093](https://github.com/WordPress/gutenberg/pull/67093)) +- ComboboxControl: Update reset button size. ([67215](https://github.com/WordPress/gutenberg/pull/67215)) + +#### DataViews +- Add density option to `table` layout. ([67170](https://github.com/WordPress/gutenberg/pull/67170)) +- DataForm: Enable fields to declare a different layout. ([66531](https://github.com/WordPress/gutenberg/pull/66531)) +- DataViews list layout: Hide actions menu when there is only one action and is primary. ([67015](https://github.com/WordPress/gutenberg/pull/67015)) +- DataViews table layout: Hide actions menu when there is only one action and is primary. ([67020](https://github.com/WordPress/gutenberg/pull/67020)) +- Reduce the size of action button in Grid layout. ([67032](https://github.com/WordPress/gutenberg/pull/67032)) +- DataViews: Allow register/unregister fields. ([67175](https://github.com/WordPress/gutenberg/pull/67175)) + +#### Global Styles +- Block Supports: Extend stabilization to common experimental block support flags. ([67018](https://github.com/WordPress/gutenberg/pull/67018)) +- Borders: Stabilize border block supports within block processing. ([66918](https://github.com/WordPress/gutenberg/pull/66918)) +- Site Editor > Styles: Open styles inspector when clicking preview canvas. ([66996](https://github.com/WordPress/gutenberg/pull/66996)) + +#### Media +- Block Editor: Add notice action to revert image to original after cropping. ([67314](https://github.com/WordPress/gutenberg/pull/67314)) +- Block Editor: Add success notices for image editing. ([67312](https://github.com/WordPress/gutenberg/pull/67312)) + +#### REST API +- Feature: Set editor rendering mode by post type. ([62304](https://github.com/WordPress/gutenberg/pull/62304)) +- Terms: Respect order specified by register_taxonomy(). ([67154](https://github.com/WordPress/gutenberg/pull/67154)) + +#### Zoom Out +- Leave help text regardless of zoom state. ([67132](https://github.com/WordPress/gutenberg/pull/67132)) +- Preserve footer template bar in zoom out. ([67135](https://github.com/WordPress/gutenberg/pull/67135)) +- Add section styles switch button in block toolbar in zoom out mode. ([67140](https://github.com/WordPress/gutenberg/pull/67140)) + +#### Post Editor +- Move default template types and template part areas to REST API. ([66459](https://github.com/WordPress/gutenberg/pull/66459)) +- Move `usePostFields` to `wordpress/editor` package. ([67024](https://github.com/WordPress/gutenberg/pull/67024)) + +#### Site Editor +- Blocks: Adds check for parent before showing convert to pattern button. ([66158](https://github.com/WordPress/gutenberg/pull/66158)) +- Try dark toolbar for the write mode. ([66116](https://github.com/WordPress/gutenberg/pull/66116)) + +#### Design Tools +- Heading: Hide border controls by default. ([67105](https://github.com/WordPress/gutenberg/pull/67105)) +- Font family preview in the font family picker. ([67118](https://github.com/WordPress/gutenberg/pull/67118)) + +### Bug Fixes + + + + +#### Block Library +- Fix block mover clickable area. ([67261](https://github.com/WordPress/gutenberg/pull/67261)) +- Fix dropping media from inserter into Cover block. ([67056](https://github.com/WordPress/gutenberg/pull/67056)) +- Fix: Preserve Display Preview State in File Block. ([67263](https://github.com/WordPress/gutenberg/pull/67263)) +- Paragraph: Update condition for rendering Drop Cap for a selected block. ([67111](https://github.com/WordPress/gutenberg/pull/67111)) +- RSS block: Check for description field before rendering excerpt. ([66985](https://github.com/WordPress/gutenberg/pull/66985)) +- Resolve search block button text overlapping issue. ([66868](https://github.com/WordPress/gutenberg/pull/66868)) +- Social Links: Fix font family and weight inconsistency in editor. ([67204](https://github.com/WordPress/gutenberg/pull/67204)) + +#### Components +- Composite: Restore `Hover` and `Typeahead` functionality. ([67212](https://github.com/WordPress/gutenberg/pull/67212)) +- Menu.ItemHelpText: Better line breaking. ([67011](https://github.com/WordPress/gutenberg/pull/67011)) +- SlotFill: Fix a bug with storing stale fillProps. ([67000](https://github.com/WordPress/gutenberg/pull/67000)) +- Storybook: Fix DataViews layout. ([66999](https://github.com/WordPress/gutenberg/pull/66999)) +- `FormFileUpload`: Prevent HEIC and HEIF files from always being uploaded on Safari. ([67139](https://github.com/WordPress/gutenberg/pull/67139)) + +#### Block Editor +- Add all color palettes to select from editor panel. ([65148](https://github.com/WordPress/gutenberg/pull/65148)) +- Correctly mark Block Comment SlotFills private. ([67271](https://github.com/WordPress/gutenberg/pull/67271)) +- Fix media placeholder to only activate for media objects. ([66986](https://github.com/WordPress/gutenberg/pull/66986)) +- Rich text: Preserve comments. ([62128](https://github.com/WordPress/gutenberg/pull/62128)) +- Fix TS types for the editor package. ([67196](https://github.com/WordPress/gutenberg/pull/67196)) +- PostTitle: Exit early when post type doesn't support titles. ([67086](https://github.com/WordPress/gutenberg/pull/67086)) + +#### Global Styles +- Avoid zooming out when browsing styles if the preview mode is active. ([67190](https://github.com/WordPress/gutenberg/pull/67190)) +- Remove styles from blocks' previews. ([67144](https://github.com/WordPress/gutenberg/pull/67144)) +- Style panel: Use correct revisions count. ([67180](https://github.com/WordPress/gutenberg/pull/67180)) +- Theme JSON: Include block style variations in path only output of get_block_nodes. ([66948](https://github.com/WordPress/gutenberg/pull/66948)) +- Fix: Logic for Highlight/text-color format availability. ([65530](https://github.com/WordPress/gutenberg/pull/65530)) +- Fix complex variation selectors when using selectors API. ([67061](https://github.com/WordPress/gutenberg/pull/67061)) +#### Site Editor +- Prevent Pre-Publish Panel from Displaying Incorrect Information After Navigating away. ([67010](https://github.com/WordPress/gutenberg/pull/67010)) +- Site Editor Sidebar: Fixed focus/hover style for navigation item buttons. ([67251](https://github.com/WordPress/gutenberg/pull/67251)) +- Site Hub: Fix height in mobile layout. ([67110](https://github.com/WordPress/gutenberg/pull/67110)) +- Site Editor: Styles: Fix inspector opening. ([67004](https://github.com/WordPress/gutenberg/pull/67004)) +- Improve accessibility and consistency of the 'Last modified' Revisions button. ([66606](https://github.com/WordPress/gutenberg/pull/66606)) +- Remove styles from examples. ([67098](https://github.com/WordPress/gutenberg/pull/67098)) +- Editor: Correctly select post title support in 'DocumentOutline'. ([67109](https://github.com/WordPress/gutenberg/pull/67109)) + + +#### DataViews +- Fix action visibility logic. ([67197](https://github.com/WordPress/gutenberg/pull/67197)) +- Fix primary field misalignment in grid layout. ([66995](https://github.com/WordPress/gutenberg/pull/66995)) +- Fix spacing when combining combined fields. ([67226](https://github.com/WordPress/gutenberg/pull/67226)) + +#### Zoom Out +- Zoom In/Out to correct canvas location. ([66917](https://github.com/WordPress/gutenberg/pull/66917)) +- Zoom in/out to correct location. ([67126](https://github.com/WordPress/gutenberg/pull/67126)) +- Zoom Out: Disable zooming out when Distraction Free mode is activated. ([67028](https://github.com/WordPress/gutenberg/pull/67028)) + +#### Layout +- Allow flex justification controls to be disabled at the block level. ([67059](https://github.com/WordPress/gutenberg/pull/67059)) +- Show vertical alignment toolbar with allowSwitching enabled. ([67022](https://github.com/WordPress/gutenberg/pull/67022)) + +#### Patterns +- Fix: JavaScript error when pattern category is unregistered. ([67063](https://github.com/WordPress/gutenberg/pull/67063)) +- Block Locking: Remove edit locking for Synced Patterns. ([67021](https://github.com/WordPress/gutenberg/pull/67021)) + +### Accessibility + +#### Components +- ColorPicker: Add accessible label for copy button. ([67094](https://github.com/WordPress/gutenberg/pull/67094)) +- Modal: Increase size of the Close button. ([66792](https://github.com/WordPress/gutenberg/pull/66792)) +- DataViews: Fix focus loss when removing all filters or resetting. ([67003](https://github.com/WordPress/gutenberg/pull/67003)) + +#### Block Library +- Improve accessibility of the video track editor. ([66832](https://github.com/WordPress/gutenberg/pull/66832)) +- Navigation: Fix 'ariaLabel' block support. ([66943](https://github.com/WordPress/gutenberg/pull/66943)) + +#### Post Editor +- Improve the featured image UI when it cannot retrieve the image file and data. ([66936](https://github.com/WordPress/gutenberg/pull/66936)) + +### Experiments + +- Inline Commenting: Update placement of reply input and add author info header. ([66580](https://github.com/WordPress/gutenberg/pull/66580)) +- Place "Write mode" functionality behind a Gutenberg experiment. ([67008](https://github.com/WordPress/gutenberg/pull/67008)) + +### Documentation + +- Add documentation about required Core changes when updating minimum WordPress version. ([67167](https://github.com/WordPress/gutenberg/pull/67167)) +- BoxControl: Auto-generate readme. ([67284](https://github.com/WordPress/gutenberg/pull/67284)) +- Components contributing guide: Fix relative links. ([67323](https://github.com/WordPress/gutenberg/pull/67323)) +- DataViews: Reorganize documentation for actions. ([67159](https://github.com/WordPress/gutenberg/pull/67159)) +- Docs: Correct `@return` type in `block_core_query_disable_enhanced_pagination()`. ([67128](https://github.com/WordPress/gutenberg/pull/67128)) +- Feat: Storybook: Improve component organisation - Layout Category - Issue #66275. ([66659](https://github.com/WordPress/gutenberg/pull/66659)) +- Feat: Storybook: Improve component organisation - Selection & Input Category - Issue #66275. ([66635](https://github.com/WordPress/gutenberg/pull/66635)) +- GradientPicker: Auto-generate readme. ([67250](https://github.com/WordPress/gutenberg/pull/67250)) +- Icon: Auto-generate readme. ([67282](https://github.com/WordPress/gutenberg/pull/67282)) +- Icon: Improve `icon` prop usage documentation in Storybook. ([67280](https://github.com/WordPress/gutenberg/pull/67280)) +- Storybook: Restore stable components back into categories. ([67216](https://github.com/WordPress/gutenberg/pull/67216)) +- Update BlockMover Stories and README. ([66519](https://github.com/WordPress/gutenberg/pull/66519)) +- Update custom store readme to use thunks instead of controls. ([67006](https://github.com/WordPress/gutenberg/pull/67006)) +- Update versions-in-wordpress.md. ([67298](https://github.com/WordPress/gutenberg/pull/67298)) + +### Code Quality + +- ESLint: Enable `eslint-plugin-react-compiler`. ([61788](https://github.com/WordPress/gutenberg/pull/61788)) +- Extract selectors from useResolveEditedEntity hook. ([67031](https://github.com/WordPress/gutenberg/pull/67031)) +- Pattern: Remove backward compatibility code for WordPress < 6.4. ([67131](https://github.com/WordPress/gutenberg/pull/67131)) +- Post fields: Move `author` from `edit-site` to `fields` package. ([66939](https://github.com/WordPress/gutenberg/pull/66939)) +- Posts DataViews: Refactor the router to use route registration. ([67160](https://github.com/WordPress/gutenberg/pull/67160)) +- Comments controller: Fix issue where comments are allowed when closed. ([66976](https://github.com/WordPress/gutenberg/pull/66976)) +- Fix fatal error in in_array call in post_type_default_rendering_mode. ([67225](https://github.com/WordPress/gutenberg/pull/67225)) +- Data: Add changelog for Redux update. ([66968](https://github.com/WordPress/gutenberg/pull/66968)) + +#### Components +- BorderBoxControl: Suppress redundant warnings for deprecated 36px size. ([67213](https://github.com/WordPress/gutenberg/pull/67213)) +- ComboboxControl : Deprecate 36px default size. ([66900](https://github.com/WordPress/gutenberg/pull/66900)) +- CustomGradientPicker: Prepare `Button`s for 40px default size. ([67286](https://github.com/WordPress/gutenberg/pull/67286)) +- Dashicons: Remove non-existent icons from type. ([67235](https://github.com/WordPress/gutenberg/pull/67235)) +- DimensionControl: Deprecate 36px default size. ([66705](https://github.com/WordPress/gutenberg/pull/66705)) +- Feat: Adds the deprecation warning for 36px default size in range control. ([66721](https://github.com/WordPress/gutenberg/pull/66721)) +- FontSizePicker : Deprecate 36px default size. ([66920](https://github.com/WordPress/gutenberg/pull/66920)) +- Remove createPrivateSlotFill function. ([67238](https://github.com/WordPress/gutenberg/pull/67238)) +- SlotFill: Fix dependencies of registration effects, deduplicate code. ([67071](https://github.com/WordPress/gutenberg/pull/67071)) +- SlotFill: Remove registration API from useSlot result. ([67070](https://github.com/WordPress/gutenberg/pull/67070)) +- SlotFill: Rewrite base Slot to functional, unify rerenderable refs. ([67153](https://github.com/WordPress/gutenberg/pull/67153)) +- TextControl: Deprecate 36px default size. ([66745](https://github.com/WordPress/gutenberg/pull/66745)) +- ToggleGroupControl : Deprecate 36px default size. ([66747](https://github.com/WordPress/gutenberg/pull/66747)) + +#### Post Editor +- ESLint: Bump `eslint-plugin-react-compiler` to latest beta. ([67106](https://github.com/WordPress/gutenberg/pull/67106)) +- Edit Post: Refactor 'MetaBoxVisibility' component. ([67265](https://github.com/WordPress/gutenberg/pull/67265)) +- Edit Post: Remove unused 'hasHistory' flag. ([67293](https://github.com/WordPress/gutenberg/pull/67293)) +- Editor: Update focus return handler for the Featured Image. ([67236](https://github.com/WordPress/gutenberg/pull/67236)) +- Make `BlockManager` component reusable. ([67052](https://github.com/WordPress/gutenberg/pull/67052)) +- Preferences: Use hooks instead of HoC in 'EnableCustomFieldsOption'. ([67023](https://github.com/WordPress/gutenberg/pull/67023)) +- Preferences: Use hooks instead of HoC in 'EnablePanelOption'. ([66994](https://github.com/WordPress/gutenberg/pull/66994)) +- Preferences: Use hooks instead of HoC in 'EnablePublishSidebarOption'. ([67002](https://github.com/WordPress/gutenberg/pull/67002)) + +#### Block Library +- Fix React Compiler error for shortcuts. ([67019](https://github.com/WordPress/gutenberg/pull/67019)) +- Home Link: Remove label attribute synchronization. ([67151](https://github.com/WordPress/gutenberg/pull/67151)) +- Use rems for Nav overlay left padding. ([67168](https://github.com/WordPress/gutenberg/pull/67168)) +- useBlockNameForPatterns: Refactor as a single useSelect call. ([67171](https://github.com/WordPress/gutenberg/pull/67171)) +- Navigation Block: Remove obsolete Block Hooks filters. ([64676](https://github.com/WordPress/gutenberg/pull/64676)) +- [mini] 🧹 remove obsolete rich text css. ([67264](https://github.com/WordPress/gutenberg/pull/67264)) + +#### Global Styles +- Don't call store actions during the render. ([67146](https://github.com/WordPress/gutenberg/pull/67146)) +- Edit Site: Fix settings mutation in `ScreenBlock`. ([67085](https://github.com/WordPress/gutenberg/pull/67085)) +- Remove unused 'Fragment' import. ([67104](https://github.com/WordPress/gutenberg/pull/67104)) + +#### Block Editor +- Block Manager: Make it a private component in the block editor package. ([67255](https://github.com/WordPress/gutenberg/pull/67255)) +- Inserter: Set initial active tab ID during render. ([67103](https://github.com/WordPress/gutenberg/pull/67103)) + +#### Site Editor +- Deprecate edited entity state. ([66965](https://github.com/WordPress/gutenberg/pull/66965)) +- Remove redundant style-edit route. ([67057](https://github.com/WordPress/gutenberg/pull/67057)) + +### Tools + +#### Testing +- Fix ESLint Jest reporting entire body of the test function rather than the identifier. ([67222](https://github.com/WordPress/gutenberg/pull/67222)) +- Fix typo in use-block-sync tests. ([67145](https://github.com/WordPress/gutenberg/pull/67145)) +- Migrate Gradle wrapper validation action. ([66602](https://github.com/WordPress/gutenberg/pull/66602)) + +#### Plugin +- Bump minimum required WordPress version to 6.6. ([67117](https://github.com/WordPress/gutenberg/pull/67117)) +- Add #7895 Core Backport PR to the changelog. ([67319](https://github.com/WordPress/gutenberg/pull/67319)) +- WP Scripts: Revert changes that inline CSS imports early in the build process. ([66975](https://github.com/WordPress/gutenberg/pull/66975)) + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @AKSHAT2802: Add all color palettes to select from editor panel. ([65148](https://github.com/WordPress/gutenberg/pull/65148)) +- @benazeer-ben: Page List : Add border and spacing support. ([66385](https://github.com/WordPress/gutenberg/pull/66385)) +- @himanshupathak95: Menu.ItemHelpText: Better line breaking. ([67011](https://github.com/WordPress/gutenberg/pull/67011)) +- @SainathPoojary: Social Links: Fix font family and weight inconsistency in editor. ([67204](https://github.com/WordPress/gutenberg/pull/67204)) +- @sarthaknagoshe2002: Prevent Pre-Publish Panel from Displaying Incorrect Information After Navigating away. ([67010](https://github.com/WordPress/gutenberg/pull/67010)) +- @Sukhendu2002: Fix: Preserve Display Preview State in File Block. ([67263](https://github.com/WordPress/gutenberg/pull/67263)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @afercia @ajlende @akasunil @AKSHAT2802 @benazeer-ben @benniledl @carolinan @cbravobernal @desrosj @dhruvang21 @dougwollison @ellatrix @getdave @gigitux @gziolo @hbhalodia @himanshupathak95 @Infinite-Null @jeryj @jsnajdr @juanfra @louwie17 @Mamaduka @manzoorwanijk @matiasbenedetto @mcsf @michalczaplinski @miminari @mirka @ndiego @ntsekouras @oandregal @ockham @PARTHVATALIYA @ramonjd @SainathPoojary @SantosGuillamot @sarthaknagoshe2002 @snehapatil2001 @Soean @Sukhendu2002 @t-hamano @talldan @tellthemachines @TylerB24890 @tyxla @up1512001 @vipul0425 @yogeshbhutkar @youknowriad + + = 19.7.0 = ## Changelog From d82e1349d8581790febf2fdda7d1ca04d99cb18f Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 27 Nov 2024 10:41:47 +0000 Subject: [PATCH 1729/1908] Update changelog files --- packages/a11y/CHANGELOG.md | 2 ++ packages/a11y/package.json | 2 +- packages/annotations/CHANGELOG.md | 2 ++ packages/annotations/package.json | 2 +- packages/api-fetch/CHANGELOG.md | 2 ++ packages/api-fetch/package.json | 2 +- packages/autop/CHANGELOG.md | 2 ++ packages/autop/package.json | 2 +- packages/babel-plugin-import-jsx-pragma/CHANGELOG.md | 2 ++ packages/babel-plugin-import-jsx-pragma/package.json | 2 +- packages/babel-plugin-makepot/CHANGELOG.md | 2 ++ packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/CHANGELOG.md | 2 ++ packages/babel-preset-default/package.json | 2 +- packages/base-styles/CHANGELOG.md | 2 ++ packages/base-styles/package.json | 2 +- packages/blob/CHANGELOG.md | 2 ++ packages/blob/package.json | 2 +- packages/block-directory/CHANGELOG.md | 2 ++ packages/block-directory/package.json | 2 +- packages/block-editor/CHANGELOG.md | 2 ++ packages/block-editor/package.json | 2 +- packages/block-library/CHANGELOG.md | 2 ++ packages/block-library/package.json | 2 +- packages/block-serialization-default-parser/CHANGELOG.md | 2 ++ packages/block-serialization-default-parser/package.json | 2 +- packages/block-serialization-spec-parser/CHANGELOG.md | 2 ++ packages/block-serialization-spec-parser/package.json | 2 +- packages/blocks/CHANGELOG.md | 2 ++ packages/blocks/package.json | 2 +- packages/browserslist-config/CHANGELOG.md | 2 ++ packages/browserslist-config/package.json | 2 +- packages/commands/CHANGELOG.md | 2 ++ packages/commands/package.json | 2 +- packages/components/CHANGELOG.md | 2 ++ packages/components/package.json | 2 +- packages/compose/CHANGELOG.md | 2 ++ packages/compose/package.json | 2 +- packages/core-commands/CHANGELOG.md | 2 ++ packages/core-commands/package.json | 2 +- packages/core-data/CHANGELOG.md | 2 ++ packages/core-data/package.json | 2 +- packages/create-block-interactive-template/package.json | 2 +- packages/create-block-tutorial-template/CHANGELOG.md | 2 ++ packages/create-block-tutorial-template/package.json | 2 +- packages/create-block/CHANGELOG.md | 2 ++ packages/create-block/package.json | 2 +- packages/customize-widgets/CHANGELOG.md | 2 ++ packages/customize-widgets/package.json | 2 +- packages/data-controls/CHANGELOG.md | 2 ++ packages/data-controls/package.json | 2 +- packages/data/CHANGELOG.md | 2 ++ packages/data/package.json | 2 +- packages/dataviews/CHANGELOG.md | 2 ++ packages/dataviews/package.json | 2 +- packages/date/CHANGELOG.md | 2 ++ packages/date/package.json | 2 +- packages/dependency-extraction-webpack-plugin/CHANGELOG.md | 2 ++ packages/dependency-extraction-webpack-plugin/package.json | 2 +- packages/deprecated/CHANGELOG.md | 2 ++ packages/deprecated/package.json | 2 +- packages/docgen/CHANGELOG.md | 2 ++ packages/docgen/package.json | 2 +- packages/dom-ready/CHANGELOG.md | 2 ++ packages/dom-ready/package.json | 2 +- packages/dom/CHANGELOG.md | 2 ++ packages/dom/package.json | 2 +- packages/e2e-test-utils-playwright/CHANGELOG.md | 2 ++ packages/e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/CHANGELOG.md | 2 ++ packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/CHANGELOG.md | 2 ++ packages/e2e-tests/package.json | 2 +- packages/edit-post/CHANGELOG.md | 2 ++ packages/edit-post/package.json | 2 +- packages/edit-site/CHANGELOG.md | 2 ++ packages/edit-site/package.json | 2 +- packages/edit-widgets/CHANGELOG.md | 2 ++ packages/edit-widgets/package.json | 2 +- packages/editor/CHANGELOG.md | 2 ++ packages/editor/package.json | 2 +- packages/element/CHANGELOG.md | 2 ++ packages/element/package.json | 2 +- packages/env/CHANGELOG.md | 2 ++ packages/env/package.json | 2 +- packages/escape-html/CHANGELOG.md | 2 ++ packages/escape-html/package.json | 2 +- packages/eslint-plugin/CHANGELOG.md | 2 ++ packages/eslint-plugin/package.json | 2 +- packages/fields/CHANGELOG.md | 2 ++ packages/fields/package.json | 2 +- packages/format-library/CHANGELOG.md | 2 ++ packages/format-library/package.json | 2 +- packages/hooks/CHANGELOG.md | 2 ++ packages/hooks/package.json | 2 +- packages/html-entities/CHANGELOG.md | 2 ++ packages/html-entities/package.json | 2 +- packages/i18n/CHANGELOG.md | 2 ++ packages/i18n/package.json | 2 +- packages/icons/CHANGELOG.md | 2 ++ packages/icons/package.json | 2 +- packages/interactivity-router/CHANGELOG.md | 2 ++ packages/interactivity-router/package.json | 2 +- packages/interactivity/CHANGELOG.md | 2 ++ packages/interactivity/package.json | 2 +- packages/interface/CHANGELOG.md | 2 ++ packages/interface/package.json | 2 +- packages/is-shallow-equal/CHANGELOG.md | 2 ++ packages/is-shallow-equal/package.json | 2 +- packages/jest-console/CHANGELOG.md | 2 ++ packages/jest-console/package.json | 2 +- packages/jest-preset-default/CHANGELOG.md | 2 ++ packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/CHANGELOG.md | 2 ++ packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/CHANGELOG.md | 2 ++ packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/CHANGELOG.md | 2 ++ packages/keycodes/package.json | 2 +- packages/lazy-import/CHANGELOG.md | 2 ++ packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/CHANGELOG.md | 2 ++ packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/CHANGELOG.md | 2 ++ packages/media-utils/package.json | 2 +- packages/notices/CHANGELOG.md | 2 ++ packages/notices/package.json | 2 +- packages/npm-package-json-lint-config/CHANGELOG.md | 2 ++ packages/npm-package-json-lint-config/package.json | 2 +- packages/nux/CHANGELOG.md | 2 ++ packages/nux/package.json | 2 +- packages/patterns/CHANGELOG.md | 2 ++ packages/patterns/package.json | 2 +- packages/plugins/CHANGELOG.md | 2 ++ packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/CHANGELOG.md | 2 ++ packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/CHANGELOG.md | 2 ++ packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/CHANGELOG.md | 2 ++ packages/preferences-persistence/package.json | 2 +- packages/preferences/CHANGELOG.md | 2 ++ packages/preferences/package.json | 2 +- packages/prettier-config/CHANGELOG.md | 2 ++ packages/prettier-config/package.json | 2 +- packages/primitives/CHANGELOG.md | 2 ++ packages/primitives/package.json | 2 +- packages/priority-queue/CHANGELOG.md | 2 ++ packages/priority-queue/package.json | 2 +- packages/private-apis/CHANGELOG.md | 2 ++ packages/private-apis/package.json | 2 +- packages/project-management-automation/CHANGELOG.md | 2 ++ packages/project-management-automation/package.json | 2 +- packages/react-i18n/CHANGELOG.md | 2 ++ packages/react-i18n/package.json | 2 +- packages/readable-js-assets-webpack-plugin/CHANGELOG.md | 2 ++ packages/readable-js-assets-webpack-plugin/package.json | 2 +- packages/redux-routine/CHANGELOG.md | 2 ++ packages/redux-routine/package.json | 2 +- packages/reusable-blocks/CHANGELOG.md | 2 ++ packages/reusable-blocks/package.json | 2 +- packages/rich-text/CHANGELOG.md | 2 ++ packages/rich-text/package.json | 2 +- packages/router/CHANGELOG.md | 2 ++ packages/router/package.json | 2 +- packages/scripts/CHANGELOG.md | 2 ++ packages/scripts/package.json | 2 +- packages/server-side-render/CHANGELOG.md | 2 ++ packages/server-side-render/package.json | 2 +- packages/shortcode/CHANGELOG.md | 2 ++ packages/shortcode/package.json | 2 +- packages/style-engine/CHANGELOG.md | 2 ++ packages/style-engine/package.json | 2 +- packages/stylelint-config/CHANGELOG.md | 2 ++ packages/stylelint-config/package.json | 2 +- packages/sync/CHANGELOG.md | 2 ++ packages/sync/package.json | 2 +- packages/token-list/CHANGELOG.md | 2 ++ packages/token-list/package.json | 2 +- packages/undo-manager/CHANGELOG.md | 2 ++ packages/undo-manager/package.json | 2 +- packages/url/CHANGELOG.md | 2 ++ packages/url/package.json | 2 +- packages/viewport/CHANGELOG.md | 2 ++ packages/viewport/package.json | 2 +- packages/warning/CHANGELOG.md | 2 ++ packages/warning/package.json | 2 +- packages/widgets/CHANGELOG.md | 2 ++ packages/widgets/package.json | 2 +- packages/wordcount/CHANGELOG.md | 2 ++ packages/wordcount/package.json | 2 +- 191 files changed, 286 insertions(+), 96 deletions(-) diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index dfd1e62906f9f4..57b52651acc787 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 1fcffd9cdfe69f..2ad91f1131b941 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/CHANGELOG.md b/packages/annotations/CHANGELOG.md index 07e9267e5b04c5..64bf565f8dd52b 100644 --- a/packages/annotations/CHANGELOG.md +++ b/packages/annotations/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.13.0 (2024-11-27) + ## 3.12.0 (2024-11-16) ## 3.11.0 (2024-10-30) diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 269c16d159e9f6..4c3c849fe7178a 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.12.0", + "version": "3.13.0-prerelease", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/CHANGELOG.md b/packages/api-fetch/CHANGELOG.md index e2ba79548592ec..da4df186a8cd2f 100644 --- a/packages/api-fetch/CHANGELOG.md +++ b/packages/api-fetch/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.13.0 (2024-11-27) + ## 7.12.0 (2024-11-16) ## 7.11.0 (2024-10-30) diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 07d90568dc9413..8e8909c54f543b 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.12.0", + "version": "7.13.0-prerelease", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/CHANGELOG.md b/packages/autop/CHANGELOG.md index dd9879ca23b746..caec56341262a1 100644 --- a/packages/autop/CHANGELOG.md +++ b/packages/autop/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/autop/package.json b/packages/autop/package.json index 60b7102850020a..5a77142235ad77 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md index 38a36491fe9a81..b7030c3e4140a7 100644 --- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md +++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index 231886784bd3f0..60583b94327a51 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/CHANGELOG.md b/packages/babel-plugin-makepot/CHANGELOG.md index 1e22ee8b4eabb4..00efceb28c075d 100644 --- a/packages/babel-plugin-makepot/CHANGELOG.md +++ b/packages/babel-plugin-makepot/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.13.0 (2024-11-27) + ## 6.12.0 (2024-11-16) ## 6.11.0 (2024-10-30) diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index 4f18f8556d68dd..30c91ac1b58da6 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.12.0", + "version": "6.13.0-prerelease", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index 8cce12417d2e26..4f5ef33b51298b 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.13.0 (2024-11-27) + ## 8.12.0 (2024-11-16) ## 8.11.0 (2024-10-30) diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index b305500dc20795..44057a5f6171af 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.12.0", + "version": "8.13.0-prerelease", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/CHANGELOG.md b/packages/base-styles/CHANGELOG.md index 67fdcfa2424530..196c6573d7b872 100644 --- a/packages/base-styles/CHANGELOG.md +++ b/packages/base-styles/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index bcdb19206b39e9..21667917ac7fe1 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md index 2edfa51064106f..2d518db27bb40a 100644 --- a/packages/blob/CHANGELOG.md +++ b/packages/blob/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/blob/package.json b/packages/blob/package.json index 2134bcd21e9346..d72f180e4b8bf6 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/CHANGELOG.md b/packages/block-directory/CHANGELOG.md index 37b6b6b3ece40a..ff4fac035eaa06 100644 --- a/packages/block-directory/CHANGELOG.md +++ b/packages/block-directory/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index a005e5be7cd60b..efc6a16ed3798e 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 3c1e63c75c75ff..87dc0459bfb715 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.8.0 (2024-11-27) + ## 14.7.0 (2024-11-16) ## 14.6.0 (2024-10-30) diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 031b34933691a3..608f079366e614 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.7.0", + "version": "14.8.0-prerelease", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index cab58f72ff70ee..47986f12e0fb54 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.13.0 (2024-11-27) + ## 9.12.0 (2024-11-16) ## 9.11.0 (2024-10-30) diff --git a/packages/block-library/package.json b/packages/block-library/package.json index e507ef36367268..c16a61ac32ec13 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.12.0", + "version": "9.13.0-prerelease", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/CHANGELOG.md b/packages/block-serialization-default-parser/CHANGELOG.md index 5542b052e1037a..c7b27f7760d14d 100644 --- a/packages/block-serialization-default-parser/CHANGELOG.md +++ b/packages/block-serialization-default-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index a448804ae9ba8c..a8d0084d43f0a8 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/CHANGELOG.md b/packages/block-serialization-spec-parser/CHANGELOG.md index 3ff70ac28cc19b..b23ec04a39a21e 100644 --- a/packages/block-serialization-spec-parser/CHANGELOG.md +++ b/packages/block-serialization-spec-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 30aa5679a7c01a..04e657055a8587 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 216918b44c0b80..0fd1b8af928abd 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.2.0 (2024-11-27) + ## 14.1.0 (2024-11-16) ## 14.0.0 (2024-10-30) diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 15102734ff34f1..51d80302c4f184 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "14.1.0", + "version": "14.2.0-prerelease", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/CHANGELOG.md b/packages/browserslist-config/CHANGELOG.md index 64a49c04621840..aa13654936f3dc 100644 --- a/packages/browserslist-config/CHANGELOG.md +++ b/packages/browserslist-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.13.0 (2024-11-27) + ## 6.12.0 (2024-11-16) ## 6.11.0 (2024-10-30) diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index f5b60a9bb7e783..bc1051eb99524b 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.12.0", + "version": "6.13.0-prerelease", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/CHANGELOG.md b/packages/commands/CHANGELOG.md index e1e995f9710aeb..40ce6d4fc65cfa 100644 --- a/packages/commands/CHANGELOG.md +++ b/packages/commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.13.0 (2024-11-27) + ## 1.12.0 (2024-11-16) ## 1.11.0 (2024-10-30) diff --git a/packages/commands/package.json b/packages/commands/package.json index 0f252c5e90ade3..5d6732a6c4b80e 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.12.0", + "version": "1.13.0-prerelease", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index c9b09c40350232..feff5ddc975356 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 28.13.0 (2024-11-27) + ### Deprecations - `DimensionControl`: Deprecate 36px default size ([#66705](https://github.com/WordPress/gutenberg/pull/66705)). diff --git a/packages/components/package.json b/packages/components/package.json index b297b31e544f98..2a3978e4193734 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.12.0", + "version": "28.13.0-prerelease", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index 897ea34a88ae7f..739a5f8831cb35 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.13.0 (2024-11-27) + ## 7.12.0 (2024-11-16) ## 7.11.0 (2024-10-30) diff --git a/packages/compose/package.json b/packages/compose/package.json index 596a50405ad476..bb84c5c16267fe 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.12.0", + "version": "7.13.0-prerelease", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/CHANGELOG.md b/packages/core-commands/CHANGELOG.md index 8928305ce32e57..af0a385fa6275c 100644 --- a/packages/core-commands/CHANGELOG.md +++ b/packages/core-commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.13.0 (2024-11-27) + ## 1.12.0 (2024-11-16) ## 1.11.0 (2024-10-30) diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 172431aa3d0913..9d21b1ba3b68eb 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.12.0", + "version": "1.13.0-prerelease", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md index d2744383594baa..35b1ab8e2957ed 100644 --- a/packages/core-data/CHANGELOG.md +++ b/packages/core-data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.13.0 (2024-11-27) + ## 7.12.0 (2024-11-16) ## 7.11.0 (2024-10-30) diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 66a52adfe1ce92..78fc7076a8d020 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.12.0", + "version": "7.13.0-prerelease", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index 94e5f3b3ed4e0b..9cb957186c7f73 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.12.0", + "version": "2.13.0-prerelease", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/CHANGELOG.md b/packages/create-block-tutorial-template/CHANGELOG.md index 9a9e8e8d7b1ab6..f219c74dceca6b 100644 --- a/packages/create-block-tutorial-template/CHANGELOG.md +++ b/packages/create-block-tutorial-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index 31c91064ddbaa6..c291096222b427 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index 075386562f3841..e6c4a2ee166d60 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.56.0 (2024-11-27) + ## 4.55.0 (2024-11-16) ## 4.54.0 (2024-10-30) diff --git a/packages/create-block/package.json b/packages/create-block/package.json index edee3d421de957..53d34f8c3109d9 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.55.0", + "version": "4.56.0-prerelease", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/CHANGELOG.md b/packages/customize-widgets/CHANGELOG.md index 41c9f2257f0a4d..6b6735c6fadd9c 100644 --- a/packages/customize-widgets/CHANGELOG.md +++ b/packages/customize-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 9c1e117d2145e8..c482fdd813dd03 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/CHANGELOG.md b/packages/data-controls/CHANGELOG.md index 5b5c2e179f8bd3..92eb6f83394213 100644 --- a/packages/data-controls/CHANGELOG.md +++ b/packages/data-controls/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 0977dbb27f988c..9a7a560bdac51f 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index 0537039794505f..89bee010837e26 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.13.0 (2024-11-27) + ### Enhancements - Upgrade `redux` dependency to `^5.0.1` ([#66966](https://github.com/WordPress/gutenberg/pull/66966)) diff --git a/packages/data/package.json b/packages/data/package.json index e325b82357b955..ff68d293c2ac7b 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.12.0", + "version": "10.13.0-prerelease", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 7fdcdf2808e812..72f08b987a3868 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.9.0 (2024-11-27) + ### Bug Fixes - Fix focus loss when removing all filters or resetting ([#67003](https://github.com/WordPress/gutenberg/pull/67003)). diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index 06b13d1697a99b..b57ead3e54ea9b 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.8.0", + "version": "4.9.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md index a385b61dc17281..21ddf975064034 100644 --- a/packages/date/CHANGELOG.md +++ b/packages/date/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/date/package.json b/packages/date/package.json index 0d98f3954d92d0..b3b7332bb8bf14 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index ee79a75513b996..4784e2105f6fb1 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.13.0 (2024-11-27) + ## 6.12.0 (2024-11-16) ## 6.11.0 (2024-10-30) diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index f168f379aa819d..8387d658d5aac9 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.12.0", + "version": "6.13.0-prerelease", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/CHANGELOG.md b/packages/deprecated/CHANGELOG.md index 861aaa9ad69f25..3ec1c350bc2d0d 100644 --- a/packages/deprecated/CHANGELOG.md +++ b/packages/deprecated/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 11d351d17acb49..df43ff9f0639f5 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/CHANGELOG.md b/packages/docgen/CHANGELOG.md index 7c92855715e325..ea879d77247ac2 100644 --- a/packages/docgen/CHANGELOG.md +++ b/packages/docgen/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.13.0 (2024-11-27) + ## 2.12.0 (2024-11-16) ## 2.11.0 (2024-10-30) diff --git a/packages/docgen/package.json b/packages/docgen/package.json index f9df5281bd5259..e5ec91f0dedf08 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.12.0", + "version": "2.13.0-prerelease", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/CHANGELOG.md b/packages/dom-ready/CHANGELOG.md index 2b6647faa8332b..27499bdb048a1c 100644 --- a/packages/dom-ready/CHANGELOG.md +++ b/packages/dom-ready/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 7302df37787ca5..5ddc5085fa901a 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/CHANGELOG.md b/packages/dom/CHANGELOG.md index f44165f23fd515..0ce2a24565d0d5 100644 --- a/packages/dom/CHANGELOG.md +++ b/packages/dom/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/dom/package.json b/packages/dom/package.json index a717c1ee0b9a5d..1bf549364796ca 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/CHANGELOG.md b/packages/e2e-test-utils-playwright/CHANGELOG.md index 968963de3b79d8..b1a35757f7496a 100644 --- a/packages/e2e-test-utils-playwright/CHANGELOG.md +++ b/packages/e2e-test-utils-playwright/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.13.0 (2024-11-27) + ## 1.12.0 (2024-11-16) ## 1.11.0 (2024-10-30) diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 43ef469ac88471..3bca976c076b74 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.12.0", + "version": "1.13.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index 1974f72e3fb215..24f73664bd7dcc 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 11.13.0 (2024-11-27) + ## 11.12.0 (2024-11-16) ## 11.11.0 (2024-10-30) diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index ee7a4deaa2ee94..7663ab163c2619 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.12.0", + "version": "11.13.0-prerelease", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md index e6f405a0d21115..0148f8b0a51ddb 100644 --- a/packages/e2e-tests/CHANGELOG.md +++ b/packages/e2e-tests/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.13.0 (2024-11-27) + ## 8.12.0 (2024-11-16) ## 8.11.0 (2024-10-30) diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index ee87ea8430654d..3ef68396fc1ce5 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.12.0", + "version": "8.13.0-prerelease", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index 56f37b13ae6225..47933552311d10 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.13.0 (2024-11-27) + ## 8.12.0 (2024-11-16) ## 8.11.0 (2024-10-30) diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index ba2bdea38bbe43..bd8c5731ef7ccd 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.12.0", + "version": "8.13.0-prerelease", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/CHANGELOG.md b/packages/edit-site/CHANGELOG.md index 0c90c024b0cd99..7143b40a59a1b4 100644 --- a/packages/edit-site/CHANGELOG.md +++ b/packages/edit-site/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.13.0 (2024-11-27) + ## 6.12.0 (2024-11-16) ## 6.11.0 (2024-10-30) diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 11ce70b876bc45..dd814ed7861eb3 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.12.0", + "version": "6.13.0-prerelease", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/CHANGELOG.md b/packages/edit-widgets/CHANGELOG.md index 22d109562d768c..f4b11636858dcd 100644 --- a/packages/edit-widgets/CHANGELOG.md +++ b/packages/edit-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.13.0 (2024-11-27) + ## 6.12.0 (2024-11-16) ## 6.11.0 (2024-10-30) diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 4ed1124314f2cf..07ec66e1b8b2f3 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.12.0", + "version": "6.13.0-prerelease", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index 37f46d1d74ccb5..5c00b30fbe96d3 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.13.0 (2024-11-27) + ## 14.12.0 (2024-11-16) ## 14.11.0 (2024-10-30) diff --git a/packages/editor/package.json b/packages/editor/package.json index 77399238a9f46b..a5fa747b43d9c6 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.12.0", + "version": "14.13.0-prerelease", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/CHANGELOG.md b/packages/element/CHANGELOG.md index 00eccb7e5ec532..50fc6e21756b92 100644 --- a/packages/element/CHANGELOG.md +++ b/packages/element/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.13.0 (2024-11-27) + ## 6.12.0 (2024-11-16) ## 6.11.0 (2024-10-30) diff --git a/packages/element/package.json b/packages/element/package.json index 6a4ede84b1062d..3e34c6b0ca63af 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.12.0", + "version": "6.13.0-prerelease", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md index 181adb034b6b19..651d6b285e1bd6 100644 --- a/packages/env/CHANGELOG.md +++ b/packages/env/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.13.0 (2024-11-27) + ## 10.12.0 (2024-11-16) ## 10.11.0 (2024-10-30) diff --git a/packages/env/package.json b/packages/env/package.json index d1c3b192baf894..ebb26e21340160 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.12.0", + "version": "10.13.0-prerelease", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/CHANGELOG.md b/packages/escape-html/CHANGELOG.md index 40ad50dc4997d8..d1eff0c72fed56 100644 --- a/packages/escape-html/CHANGELOG.md +++ b/packages/escape-html/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.13.0 (2024-11-27) + ## 3.12.0 (2024-11-16) ## 3.11.0 (2024-10-30) diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 688c10e638a96c..13ebb4793ed127 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.12.0", + "version": "3.13.0-prerelease", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 75a8828629b85d..91b517249b597a 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 21.6.0 (2024-11-27) + ## 21.5.0 (2024-11-16) ## 21.4.0 (2024-10-30) diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 0e8880f0941234..246da0479393b8 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "21.5.0", + "version": "21.6.0-prerelease", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/fields/CHANGELOG.md b/packages/fields/CHANGELOG.md index a2eba51228fbdd..c567ae42058bf5 100644 --- a/packages/fields/CHANGELOG.md +++ b/packages/fields/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.5.0 (2024-11-27) + ## 0.4.0 (2024-11-16) ## 0.3.0 (2024-10-30) diff --git a/packages/fields/package.json b/packages/fields/package.json index 8c9509b06c5885..3e73fe3bb753aa 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/fields", - "version": "0.4.0", + "version": "0.5.0-prerelease", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/CHANGELOG.md b/packages/format-library/CHANGELOG.md index 257b13656210b0..99c174ca029c62 100644 --- a/packages/format-library/CHANGELOG.md +++ b/packages/format-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/format-library/package.json b/packages/format-library/package.json index ee1dd8efd1fe95..06271e0c9c360a 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/CHANGELOG.md b/packages/hooks/CHANGELOG.md index be3f8c7cf6b415..be18dab3225a2b 100644 --- a/packages/hooks/CHANGELOG.md +++ b/packages/hooks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 0bfc0700070e2d..7aea26efdc7b35 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/CHANGELOG.md b/packages/html-entities/CHANGELOG.md index bcba1ced9d91c7..98b3b3c483325e 100644 --- a/packages/html-entities/CHANGELOG.md +++ b/packages/html-entities/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index f8f88b883be146..4e17fab9045782 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index fd5f8e1003e326..b1d94cde634c0d 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/i18n/package.json b/packages/i18n/package.json index ed4b25aa0fb8fc..8d86bb1d90368c 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index 484b26e96c90d9..84263e1135ac4d 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.13.0 (2024-11-27) + ## 10.12.0 (2024-11-16) ## 10.11.0 (2024-10-30) diff --git a/packages/icons/package.json b/packages/icons/package.json index 40ddb309066e25..3df43cb209b437 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.12.0", + "version": "10.13.0-prerelease", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/CHANGELOG.md b/packages/interactivity-router/CHANGELOG.md index ed23e6c73dea4e..b79850dc7fe545 100644 --- a/packages/interactivity-router/CHANGELOG.md +++ b/packages/interactivity-router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.13.0 (2024-11-27) + ## 2.12.0 (2024-11-16) ## 2.11.0 (2024-10-30) diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index d750edb2cd9c28..67cc0704f51603 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.12.0", + "version": "2.13.0-prerelease", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 8167177b663d43..587d14440d8116 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.13.0 (2024-11-27) + ## 6.12.0 (2024-11-16) ### Bug Fixes diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index e82d74c5735302..6382a789dc2b8b 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.12.0", + "version": "6.13.0-prerelease", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index aa1f96414d46b1..56b01075257331 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.2.0 (2024-11-27) + ## 8.1.0 (2024-11-16) ## 8.0.0 (2024-10-30) diff --git a/packages/interface/package.json b/packages/interface/package.json index 6d286e2e259e90..a1c552f01781ce 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "8.1.0", + "version": "8.2.0-prerelease", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/CHANGELOG.md b/packages/is-shallow-equal/CHANGELOG.md index ea56df508bdbdf..6308dd484c728a 100644 --- a/packages/is-shallow-equal/CHANGELOG.md +++ b/packages/is-shallow-equal/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 5bc028c2f58902..0490fb9c04495b 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/CHANGELOG.md b/packages/jest-console/CHANGELOG.md index 777d4271418b9c..67f41af5c7e3f2 100644 --- a/packages/jest-console/CHANGELOG.md +++ b/packages/jest-console/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.13.0 (2024-11-27) + ## 8.12.0 (2024-11-16) ## 8.11.0 (2024-10-30) diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index f0c6cdea73f461..0615e9ed9ea4f3 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.12.0", + "version": "8.13.0-prerelease", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md index a5b7d79336636c..d98552ff45f716 100644 --- a/packages/jest-preset-default/CHANGELOG.md +++ b/packages/jest-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 12.13.0 (2024-11-27) + ## 12.12.0 (2024-11-16) ## 12.11.0 (2024-10-30) diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 4050f4fce430f2..9a1367224c3e90 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.12.0", + "version": "12.13.0-prerelease", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/CHANGELOG.md b/packages/jest-puppeteer-axe/CHANGELOG.md index c0459e401925c6..d54c3a57804f08 100644 --- a/packages/jest-puppeteer-axe/CHANGELOG.md +++ b/packages/jest-puppeteer-axe/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.13.0 (2024-11-27) + ## 7.12.0 (2024-11-16) ## 7.11.0 (2024-10-30) diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 928f427348e690..40595cdfa290b2 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.12.0", + "version": "7.13.0-prerelease", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/CHANGELOG.md b/packages/keyboard-shortcuts/CHANGELOG.md index cbc9dc62deeb5c..67daf5426b3272 100644 --- a/packages/keyboard-shortcuts/CHANGELOG.md +++ b/packages/keyboard-shortcuts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index a98a64cb433251..73c794a087c67c 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/CHANGELOG.md b/packages/keycodes/CHANGELOG.md index d3b43c523ee8a3..46ce387d6d058b 100644 --- a/packages/keycodes/CHANGELOG.md +++ b/packages/keycodes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index c4720262af6bb4..e2e69f291ce1e5 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/CHANGELOG.md b/packages/lazy-import/CHANGELOG.md index 96e04c125b974e..d5cff8b39af07f 100644 --- a/packages/lazy-import/CHANGELOG.md +++ b/packages/lazy-import/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.13.0 (2024-11-27) + ## 2.12.0 (2024-11-16) ## 2.11.0 (2024-10-30) diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index e6b989891b351b..cf4cddb73c8623 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.12.0", + "version": "2.13.0-prerelease", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/CHANGELOG.md b/packages/list-reusable-blocks/CHANGELOG.md index cee7a2eb5a8671..59b8fa9500fde7 100644 --- a/packages/list-reusable-blocks/CHANGELOG.md +++ b/packages/list-reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 6db0f8d1da903d..7707592782bcf6 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/CHANGELOG.md b/packages/media-utils/CHANGELOG.md index c4dd4f860c4690..2cfcbaa4b2e8ba 100644 --- a/packages/media-utils/CHANGELOG.md +++ b/packages/media-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index d0b05f580d45cf..33ab27a6b98d76 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/CHANGELOG.md b/packages/notices/CHANGELOG.md index f721b22243aa87..68c4ef7f85ab5d 100644 --- a/packages/notices/CHANGELOG.md +++ b/packages/notices/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/notices/package.json b/packages/notices/package.json index 2f0369dede9bb0..a19276cf0e2c01 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/CHANGELOG.md b/packages/npm-package-json-lint-config/CHANGELOG.md index c9addbd4214c64..132f6ffccdd23c 100644 --- a/packages/npm-package-json-lint-config/CHANGELOG.md +++ b/packages/npm-package-json-lint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ### Enhancement diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index 680a30bb096c9e..1acd0b7dcf74e5 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/CHANGELOG.md b/packages/nux/CHANGELOG.md index 91a372a1efd207..ddf1f9091471d0 100644 --- a/packages/nux/CHANGELOG.md +++ b/packages/nux/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.13.0 (2024-11-27) + ## 9.12.0 (2024-11-16) ## 9.11.0 (2024-10-30) diff --git a/packages/nux/package.json b/packages/nux/package.json index 836f1de781413e..612244b92944db 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.12.0", + "version": "9.13.0-prerelease", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/CHANGELOG.md b/packages/patterns/CHANGELOG.md index c953ffc1b4d4ce..975065d0f2b423 100644 --- a/packages/patterns/CHANGELOG.md +++ b/packages/patterns/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.13.0 (2024-11-27) + ## 2.12.0 (2024-11-16) ## 2.11.0 (2024-10-30) diff --git a/packages/patterns/package.json b/packages/patterns/package.json index a556a4641f6bc7..42ee04848006b0 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.12.0", + "version": "2.13.0-prerelease", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/CHANGELOG.md b/packages/plugins/CHANGELOG.md index 34004f6295a36b..fc9199892ade1d 100644 --- a/packages/plugins/CHANGELOG.md +++ b/packages/plugins/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.13.0 (2024-11-27) + ## 7.12.0 (2024-11-16) ## 7.11.0 (2024-10-30) diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 9bb45aea981082..2e1aeaf1c9b3ae 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.12.0", + "version": "7.13.0-prerelease", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/CHANGELOG.md b/packages/postcss-plugins-preset/CHANGELOG.md index 459193675cced1..e271d53cdc73f9 100644 --- a/packages/postcss-plugins-preset/CHANGELOG.md +++ b/packages/postcss-plugins-preset/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 0627cb489fca75..71802c5da439e0 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/CHANGELOG.md b/packages/postcss-themes/CHANGELOG.md index 098507b753ea80..efdb8fb1aa808d 100644 --- a/packages/postcss-themes/CHANGELOG.md +++ b/packages/postcss-themes/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.13.0 (2024-11-27) + ## 6.12.0 (2024-11-16) ## 6.11.0 (2024-10-30) diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index e1b632925094f5..c6658889aeda4d 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.12.0", + "version": "6.13.0-prerelease", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/CHANGELOG.md b/packages/preferences-persistence/CHANGELOG.md index a2b8376a82735c..3f75a6bbf49c77 100644 --- a/packages/preferences-persistence/CHANGELOG.md +++ b/packages/preferences-persistence/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.13.0 (2024-11-27) + ## 2.12.0 (2024-11-16) ## 2.11.0 (2024-10-30) diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index 645e62c9307cb6..1e5ca3595e9c7b 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.12.0", + "version": "2.13.0-prerelease", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/CHANGELOG.md b/packages/preferences/CHANGELOG.md index 76e227f2d70043..8453a061cfdfa7 100644 --- a/packages/preferences/CHANGELOG.md +++ b/packages/preferences/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/preferences/package.json b/packages/preferences/package.json index e9f83170fe56b2..5a94f7c17281e3 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/CHANGELOG.md b/packages/prettier-config/CHANGELOG.md index da352c8d8ddaf4..e15c0e2aad79fc 100644 --- a/packages/prettier-config/CHANGELOG.md +++ b/packages/prettier-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 5991d84b9ee7e9..47dec2d7a7aa06 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/CHANGELOG.md b/packages/primitives/CHANGELOG.md index 25bc2d4e3abcb1..29211c9586ede4 100644 --- a/packages/primitives/CHANGELOG.md +++ b/packages/primitives/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 67bc8e84bd24e7..b1947e4d7516ec 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/CHANGELOG.md b/packages/priority-queue/CHANGELOG.md index dce047693d2957..5427d3d5ff7616 100644 --- a/packages/priority-queue/CHANGELOG.md +++ b/packages/priority-queue/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.13.0 (2024-11-27) + ## 3.12.0 (2024-11-16) ## 3.11.0 (2024-10-30) diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index e5487204dd2375..4fa445fc3194ef 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.12.0", + "version": "3.13.0-prerelease", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/CHANGELOG.md b/packages/private-apis/CHANGELOG.md index 9e7c78b3d0fd1f..8792e587a83f16 100644 --- a/packages/private-apis/CHANGELOG.md +++ b/packages/private-apis/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.13.0 (2024-11-27) + ## 1.12.0 (2024-11-16) ## 1.11.0 (2024-10-30) diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index 928eef9465d9ca..bcfc6ad2a0d7ed 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.12.0", + "version": "1.13.0-prerelease", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/CHANGELOG.md b/packages/project-management-automation/CHANGELOG.md index d2028220f71284..b6376be2fd6e0c 100644 --- a/packages/project-management-automation/CHANGELOG.md +++ b/packages/project-management-automation/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.13.0 (2024-11-27) + ## 2.12.0 (2024-11-16) ## 2.11.0 (2024-10-30) diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 22638756014c6e..0058153a033250 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.12.0", + "version": "2.13.0-prerelease", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/CHANGELOG.md b/packages/react-i18n/CHANGELOG.md index d0991cdf756b33..ed872fe9cd145c 100644 --- a/packages/react-i18n/CHANGELOG.md +++ b/packages/react-i18n/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 236cd7d63be1b6..2ccfd22673aa91 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md index 42b12846436e25..08912695e5a8a5 100644 --- a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md +++ b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.13.0 (2024-11-27) + ## 3.12.0 (2024-11-16) ## 3.11.0 (2024-10-30) diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index dda4f7e0a51ffc..eb14986310c862 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.12.0", + "version": "3.13.0-prerelease", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/CHANGELOG.md b/packages/redux-routine/CHANGELOG.md index e32593e39a8289..afc65f590b5b66 100644 --- a/packages/redux-routine/CHANGELOG.md +++ b/packages/redux-routine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index e4d3600c5db2eb..9704d2cf144bf2 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/CHANGELOG.md b/packages/reusable-blocks/CHANGELOG.md index e451948e16d364..83ee4e4c1add3f 100644 --- a/packages/reusable-blocks/CHANGELOG.md +++ b/packages/reusable-blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 29309d1d99c9d4..1461aa747b46b8 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/CHANGELOG.md b/packages/rich-text/CHANGELOG.md index 904894e9553c23..2239fbd11ceedc 100644 --- a/packages/rich-text/CHANGELOG.md +++ b/packages/rich-text/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.13.0 (2024-11-27) + ## 7.12.0 (2024-11-16) ## 7.11.0 (2024-10-30) diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 1f3fbfa26e513b..53e9296889ca84 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.12.0", + "version": "7.13.0-prerelease", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index 7e65d08ea7a4b4..07ff407d8435ce 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.13.0 (2024-11-27) + ## 1.12.0 (2024-11-16) ## 1.11.0 (2024-10-30) diff --git a/packages/router/package.json b/packages/router/package.json index 3ee25719134020..0b32d61b3464af 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.12.0", + "version": "1.13.0-prerelease", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 0decdaca528b2e..55143ae792ae5b 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 30.6.0 (2024-11-27) + ## 30.5.1 (2024-11-18) ### Bug Fix diff --git a/packages/scripts/package.json b/packages/scripts/package.json index fa50f90362a6f0..17f0379de77ce1 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.5.1", + "version": "30.6.0-prerelease", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/CHANGELOG.md b/packages/server-side-render/CHANGELOG.md index d334d34897a7e7..66a8d7c03136bf 100644 --- a/packages/server-side-render/CHANGELOG.md +++ b/packages/server-side-render/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.13.0 (2024-11-27) + ## 5.12.0 (2024-11-16) ## 5.11.0 (2024-10-30) diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index 1e2d477840d720..e538f66985148d 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.12.0", + "version": "5.13.0-prerelease", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/CHANGELOG.md b/packages/shortcode/CHANGELOG.md index dd30fa01c08bd4..8ee4e9aa3168d1 100644 --- a/packages/shortcode/CHANGELOG.md +++ b/packages/shortcode/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index dde71b677e93f1..351b47dd4659dd 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md index 91ffb32099a230..768ea039f24f36 100644 --- a/packages/style-engine/CHANGELOG.md +++ b/packages/style-engine/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.13.0 (2024-11-27) + ## 2.12.0 (2024-11-16) ## 2.11.0 (2024-10-30) diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index ef7adbe720f6c0..fa8d19a506108f 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.12.0", + "version": "2.13.0-prerelease", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/CHANGELOG.md b/packages/stylelint-config/CHANGELOG.md index 402ca7cf9de59a..5e6fa218da6f85 100644 --- a/packages/stylelint-config/CHANGELOG.md +++ b/packages/stylelint-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 23.5.0 (2024-11-27) + ## 23.4.0 (2024-11-16) ## 23.3.0 (2024-10-30) diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 6aff6076c76f03..3b1e94372cc451 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "23.4.0", + "version": "23.5.0-prerelease", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/CHANGELOG.md b/packages/sync/CHANGELOG.md index 867e1fb2b3233b..b8ecad37f3f5d8 100644 --- a/packages/sync/CHANGELOG.md +++ b/packages/sync/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.13.0 (2024-11-27) + ## 1.12.0 (2024-11-16) ## 1.11.0 (2024-10-30) diff --git a/packages/sync/package.json b/packages/sync/package.json index 42c784ae13ac6a..714832322774ba 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.12.0", + "version": "1.13.0-prerelease", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/CHANGELOG.md b/packages/token-list/CHANGELOG.md index 2e72e21a44f646..0b72a43de88d4f 100644 --- a/packages/token-list/CHANGELOG.md +++ b/packages/token-list/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.13.0 (2024-11-27) + ## 3.12.0 (2024-11-16) ## 3.11.0 (2024-10-30) diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 17837ccd5d1b70..0103c07e0e6ead 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.12.0", + "version": "3.13.0-prerelease", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/CHANGELOG.md b/packages/undo-manager/CHANGELOG.md index d35ddd1b895925..e84658632a054d 100644 --- a/packages/undo-manager/CHANGELOG.md +++ b/packages/undo-manager/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.13.0 (2024-11-27) + ## 1.12.0 (2024-11-16) ## 1.11.0 (2024-10-30) diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 99fa4c7f8a9bbc..8ebf45fc9df9ec 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.12.0", + "version": "1.13.0-prerelease", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/CHANGELOG.md b/packages/url/CHANGELOG.md index 94fc29e83f98d7..e4273fc57f2e0f 100644 --- a/packages/url/CHANGELOG.md +++ b/packages/url/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/url/package.json b/packages/url/package.json index 0e237f4e95788e..6a4297a5084434 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/CHANGELOG.md b/packages/viewport/CHANGELOG.md index 78f0fa1c9292ce..faf1bd4b437f0d 100644 --- a/packages/viewport/CHANGELOG.md +++ b/packages/viewport/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.13.0 (2024-11-27) + ## 6.12.0 (2024-11-16) ## 6.11.0 (2024-10-30) diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 548efa124f374e..8aadf2af898fb0 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.12.0", + "version": "6.13.0-prerelease", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/CHANGELOG.md b/packages/warning/CHANGELOG.md index 189af916a46a71..424ab1403506a6 100644 --- a/packages/warning/CHANGELOG.md +++ b/packages/warning/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.13.0 (2024-11-27) + ## 3.12.0 (2024-11-16) ## 3.11.0 (2024-10-30) diff --git a/packages/warning/package.json b/packages/warning/package.json index 3d6223ba47ff08..91c4bc5c591955 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.12.0", + "version": "3.13.0-prerelease", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/CHANGELOG.md b/packages/widgets/CHANGELOG.md index 2c02849b6ceee4..b1c63a0ca7f4c2 100644 --- a/packages/widgets/CHANGELOG.md +++ b/packages/widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/widgets/package.json b/packages/widgets/package.json index db712cd70d5449..d72c179a5ad419 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/CHANGELOG.md b/packages/wordcount/CHANGELOG.md index ef65ec41b00db9..f323aa3a810d7a 100644 --- a/packages/wordcount/CHANGELOG.md +++ b/packages/wordcount/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.13.0 (2024-11-27) + ## 4.12.0 (2024-11-16) ## 4.11.0 (2024-10-30) diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index 637d935fc11e6c..f69f8e06219160 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.12.0", + "version": "4.13.0-prerelease", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From d02c4b4cec4923bb1d97327d997da4a9c8d7fe75 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 27 Nov 2024 10:43:37 +0000 Subject: [PATCH 1730/1908] chore(release): publish - @wordpress/a11y@4.13.0 - @wordpress/annotations@3.13.0 - @wordpress/api-fetch@7.13.0 - @wordpress/autop@4.13.0 - @wordpress/babel-plugin-import-jsx-pragma@5.13.0 - @wordpress/babel-plugin-makepot@6.13.0 - @wordpress/babel-preset-default@8.13.0 - @wordpress/base-styles@5.13.0 - @wordpress/blob@4.13.0 - @wordpress/block-directory@5.13.0 - @wordpress/block-editor@14.8.0 - @wordpress/block-library@9.13.0 - @wordpress/block-serialization-default-parser@5.13.0 - @wordpress/block-serialization-spec-parser@5.13.0 - @wordpress/blocks@14.2.0 - @wordpress/browserslist-config@6.13.0 - @wordpress/commands@1.13.0 - @wordpress/components@28.13.0 - @wordpress/compose@7.13.0 - @wordpress/core-commands@1.13.0 - @wordpress/core-data@7.13.0 - @wordpress/create-block@4.56.0 - @wordpress/create-block-interactive-template@2.13.0 - @wordpress/create-block-tutorial-template@4.13.0 - @wordpress/customize-widgets@5.13.0 - @wordpress/data@10.13.0 - @wordpress/data-controls@4.13.0 - @wordpress/dataviews@4.9.0 - @wordpress/date@5.13.0 - @wordpress/dependency-extraction-webpack-plugin@6.13.0 - @wordpress/deprecated@4.13.0 - @wordpress/docgen@2.13.0 - @wordpress/dom@4.13.0 - @wordpress/dom-ready@4.13.0 - @wordpress/e2e-test-utils@11.13.0 - @wordpress/e2e-test-utils-playwright@1.13.0 - @wordpress/e2e-tests@8.13.0 - @wordpress/edit-post@8.13.0 - @wordpress/edit-site@6.13.0 - @wordpress/edit-widgets@6.13.0 - @wordpress/editor@14.13.0 - @wordpress/element@6.13.0 - @wordpress/env@10.13.0 - @wordpress/escape-html@3.13.0 - @wordpress/eslint-plugin@21.6.0 - @wordpress/fields@0.5.0 - @wordpress/format-library@5.13.0 - @wordpress/hooks@4.13.0 - @wordpress/html-entities@4.13.0 - @wordpress/i18n@5.13.0 - @wordpress/icons@10.13.0 - @wordpress/interactivity@6.13.0 - @wordpress/interactivity-router@2.13.0 - @wordpress/interface@8.2.0 - @wordpress/is-shallow-equal@5.13.0 - @wordpress/jest-console@8.13.0 - @wordpress/jest-preset-default@12.13.0 - @wordpress/jest-puppeteer-axe@7.13.0 - @wordpress/keyboard-shortcuts@5.13.0 - @wordpress/keycodes@4.13.0 - @wordpress/lazy-import@2.13.0 - @wordpress/list-reusable-blocks@5.13.0 - @wordpress/media-utils@5.13.0 - @wordpress/notices@5.13.0 - @wordpress/npm-package-json-lint-config@5.13.0 - @wordpress/nux@9.13.0 - @wordpress/patterns@2.13.0 - @wordpress/plugins@7.13.0 - @wordpress/postcss-plugins-preset@5.13.0 - @wordpress/postcss-themes@6.13.0 - @wordpress/preferences@4.13.0 - @wordpress/preferences-persistence@2.13.0 - @wordpress/prettier-config@4.13.0 - @wordpress/primitives@4.13.0 - @wordpress/priority-queue@3.13.0 - @wordpress/private-apis@1.13.0 - @wordpress/project-management-automation@2.13.0 - @wordpress/react-i18n@4.13.0 - @wordpress/readable-js-assets-webpack-plugin@3.13.0 - @wordpress/redux-routine@5.13.0 - @wordpress/reusable-blocks@5.13.0 - @wordpress/rich-text@7.13.0 - @wordpress/router@1.13.0 - @wordpress/scripts@30.6.0 - @wordpress/server-side-render@5.13.0 - @wordpress/shortcode@4.13.0 - @wordpress/style-engine@2.13.0 - @wordpress/stylelint-config@23.5.0 - @wordpress/sync@1.13.0 - @wordpress/token-list@3.13.0 - @wordpress/undo-manager@1.13.0 - @wordpress/url@4.13.0 - @wordpress/viewport@6.13.0 - @wordpress/warning@3.13.0 - @wordpress/widgets@4.13.0 - @wordpress/wordcount@4.13.0 --- package-lock.json | 192 +++++++++--------- packages/a11y/package.json | 2 +- packages/annotations/package.json | 2 +- packages/api-fetch/package.json | 2 +- packages/autop/package.json | 2 +- .../package.json | 2 +- packages/babel-plugin-makepot/package.json | 2 +- packages/babel-preset-default/package.json | 2 +- packages/base-styles/package.json | 2 +- packages/blob/package.json | 2 +- packages/block-directory/package.json | 2 +- packages/block-editor/package.json | 2 +- packages/block-library/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/blocks/package.json | 2 +- packages/browserslist-config/package.json | 2 +- packages/commands/package.json | 2 +- packages/components/package.json | 2 +- packages/compose/package.json | 2 +- packages/core-commands/package.json | 2 +- packages/core-data/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/create-block/package.json | 2 +- packages/customize-widgets/package.json | 2 +- packages/data-controls/package.json | 2 +- packages/data/package.json | 2 +- packages/dataviews/package.json | 2 +- packages/date/package.json | 2 +- .../package.json | 2 +- packages/deprecated/package.json | 2 +- packages/docgen/package.json | 2 +- packages/dom-ready/package.json | 2 +- packages/dom/package.json | 2 +- .../e2e-test-utils-playwright/package.json | 2 +- packages/e2e-test-utils/package.json | 2 +- packages/e2e-tests/package.json | 2 +- packages/edit-post/package.json | 2 +- packages/edit-site/package.json | 2 +- packages/edit-widgets/package.json | 2 +- packages/editor/package.json | 2 +- packages/element/package.json | 2 +- packages/env/package.json | 2 +- packages/escape-html/package.json | 2 +- packages/eslint-plugin/package.json | 2 +- packages/fields/package.json | 2 +- packages/format-library/package.json | 2 +- packages/hooks/package.json | 2 +- packages/html-entities/package.json | 2 +- packages/i18n/package.json | 2 +- packages/icons/package.json | 2 +- packages/interactivity-router/package.json | 2 +- packages/interactivity/package.json | 2 +- packages/interface/package.json | 2 +- packages/is-shallow-equal/package.json | 2 +- packages/jest-console/package.json | 2 +- packages/jest-preset-default/package.json | 2 +- packages/jest-puppeteer-axe/package.json | 2 +- packages/keyboard-shortcuts/package.json | 2 +- packages/keycodes/package.json | 2 +- packages/lazy-import/package.json | 2 +- packages/list-reusable-blocks/package.json | 2 +- packages/media-utils/package.json | 2 +- packages/notices/package.json | 2 +- .../npm-package-json-lint-config/package.json | 2 +- packages/nux/package.json | 2 +- packages/patterns/package.json | 2 +- packages/plugins/package.json | 2 +- packages/postcss-plugins-preset/package.json | 2 +- packages/postcss-themes/package.json | 2 +- packages/preferences-persistence/package.json | 2 +- packages/preferences/package.json | 2 +- packages/prettier-config/package.json | 2 +- packages/primitives/package.json | 2 +- packages/priority-queue/package.json | 2 +- packages/private-apis/package.json | 2 +- .../package.json | 2 +- packages/react-i18n/package.json | 2 +- .../package.json | 2 +- packages/redux-routine/package.json | 2 +- packages/reusable-blocks/package.json | 2 +- packages/rich-text/package.json | 2 +- packages/router/package.json | 2 +- packages/scripts/package.json | 2 +- packages/server-side-render/package.json | 2 +- packages/shortcode/package.json | 2 +- packages/style-engine/package.json | 2 +- packages/stylelint-config/package.json | 2 +- packages/sync/package.json | 2 +- packages/token-list/package.json | 2 +- packages/undo-manager/package.json | 2 +- packages/url/package.json | 2 +- packages/viewport/package.json | 2 +- packages/warning/package.json | 2 +- packages/widgets/package.json | 2 +- packages/wordcount/package.json | 2 +- 97 files changed, 192 insertions(+), 192 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7e19737654b9aa..ccf779f2d67eab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51890,7 +51890,7 @@ }, "packages/a11y": { "name": "@wordpress/a11y", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -51904,7 +51904,7 @@ }, "packages/annotations": { "name": "@wordpress/annotations", - "version": "3.12.0", + "version": "3.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -51932,7 +51932,7 @@ }, "packages/api-fetch": { "name": "@wordpress/api-fetch", - "version": "7.12.0", + "version": "7.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -51946,7 +51946,7 @@ }, "packages/autop": { "name": "@wordpress/autop", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -51958,7 +51958,7 @@ }, "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -51970,7 +51970,7 @@ }, "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", - "version": "6.12.0", + "version": "6.13.0", "license": "GPL-2.0-or-later", "dependencies": { "deepmerge": "^4.3.0", @@ -51987,7 +51987,7 @@ }, "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", - "version": "8.12.0", + "version": "8.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -53118,7 +53118,7 @@ }, "packages/base-styles": { "name": "@wordpress/base-styles", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53127,7 +53127,7 @@ }, "packages/blob": { "name": "@wordpress/blob", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -53139,7 +53139,7 @@ }, "packages/block-directory": { "name": "@wordpress/block-directory", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53175,7 +53175,7 @@ }, "packages/block-editor": { "name": "@wordpress/block-editor", - "version": "14.7.0", + "version": "14.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53275,7 +53275,7 @@ }, "packages/block-library": { "name": "@wordpress/block-library", - "version": "9.12.0", + "version": "9.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53341,7 +53341,7 @@ }, "packages/block-serialization-default-parser": { "name": "@wordpress/block-serialization-default-parser", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -53353,7 +53353,7 @@ }, "packages/block-serialization-spec-parser": { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "pegjs": "^0.10.0", @@ -53366,7 +53366,7 @@ }, "packages/blocks": { "name": "@wordpress/blocks", - "version": "14.1.0", + "version": "14.2.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53420,7 +53420,7 @@ }, "packages/browserslist-config": { "name": "@wordpress/browserslist-config", - "version": "6.12.0", + "version": "6.13.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53429,7 +53429,7 @@ }, "packages/commands": { "name": "@wordpress/commands", - "version": "1.12.0", + "version": "1.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53668,7 +53668,7 @@ }, "packages/components": { "name": "@wordpress/components", - "version": "28.12.0", + "version": "28.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -53789,7 +53789,7 @@ }, "packages/compose": { "name": "@wordpress/compose", - "version": "7.12.0", + "version": "7.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53826,7 +53826,7 @@ }, "packages/core-commands": { "name": "@wordpress/core-commands", - "version": "1.12.0", + "version": "1.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53855,7 +53855,7 @@ }, "packages/core-data": { "name": "@wordpress/core-data", - "version": "7.12.0", + "version": "7.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53900,7 +53900,7 @@ }, "packages/create-block": { "name": "@wordpress/create-block", - "version": "4.55.0", + "version": "4.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/lazy-import": "*", @@ -53927,7 +53927,7 @@ }, "packages/create-block-interactive-template": { "name": "@wordpress/create-block-interactive-template", - "version": "2.12.0", + "version": "2.13.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53936,7 +53936,7 @@ }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53945,7 +53945,7 @@ }, "packages/customize-widgets": { "name": "@wordpress/customize-widgets", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53984,7 +53984,7 @@ }, "packages/data": { "name": "@wordpress/data", - "version": "10.12.0", + "version": "10.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54013,7 +54013,7 @@ }, "packages/data-controls": { "name": "@wordpress/data-controls", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54031,7 +54031,7 @@ }, "packages/dataviews": { "name": "@wordpress/dataviews", - "version": "4.8.0", + "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -54088,7 +54088,7 @@ }, "packages/date": { "name": "@wordpress/date", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54103,7 +54103,7 @@ }, "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.12.0", + "version": "6.13.0", "license": "GPL-2.0-or-later", "dependencies": { "json2php": "^0.0.7" @@ -54118,7 +54118,7 @@ }, "packages/deprecated": { "name": "@wordpress/deprecated", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54131,7 +54131,7 @@ }, "packages/docgen": { "name": "@wordpress/docgen", - "version": "2.12.0", + "version": "2.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -54152,7 +54152,7 @@ }, "packages/dom": { "name": "@wordpress/dom", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54165,7 +54165,7 @@ }, "packages/dom-ready": { "name": "@wordpress/dom-ready", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54177,7 +54177,7 @@ }, "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", - "version": "11.12.0", + "version": "11.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54199,7 +54199,7 @@ }, "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.12.0", + "version": "1.13.0", "license": "GPL-2.0-or-later", "dependencies": { "change-case": "^4.1.2", @@ -54225,7 +54225,7 @@ }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", - "version": "8.12.0", + "version": "8.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/e2e-test-utils": "*", @@ -54263,7 +54263,7 @@ }, "packages/edit-post": { "name": "@wordpress/edit-post", - "version": "8.12.0", + "version": "8.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54310,7 +54310,7 @@ }, "packages/edit-site": { "name": "@wordpress/edit-site", - "version": "6.12.0", + "version": "6.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54372,7 +54372,7 @@ }, "packages/edit-widgets": { "name": "@wordpress/edit-widgets", - "version": "6.12.0", + "version": "6.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54416,7 +54416,7 @@ }, "packages/editor": { "name": "@wordpress/editor", - "version": "14.12.0", + "version": "14.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54478,7 +54478,7 @@ }, "packages/element": { "name": "@wordpress/element", - "version": "6.12.0", + "version": "6.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54497,7 +54497,7 @@ }, "packages/env": { "name": "@wordpress/env", - "version": "10.12.0", + "version": "10.13.0", "license": "GPL-2.0-or-later", "dependencies": { "chalk": "^4.0.0", @@ -54628,7 +54628,7 @@ }, "packages/escape-html": { "name": "@wordpress/escape-html", - "version": "3.12.0", + "version": "3.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54640,7 +54640,7 @@ }, "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", - "version": "21.5.0", + "version": "21.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/eslint-parser": "7.25.7", @@ -54709,7 +54709,7 @@ }, "packages/fields": { "name": "@wordpress/fields", - "version": "0.4.0", + "version": "0.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54750,7 +54750,7 @@ }, "packages/format-library": { "name": "@wordpress/format-library", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54778,7 +54778,7 @@ }, "packages/hooks": { "name": "@wordpress/hooks", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54790,7 +54790,7 @@ }, "packages/html-entities": { "name": "@wordpress/html-entities", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54802,7 +54802,7 @@ }, "packages/i18n": { "name": "@wordpress/i18n", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54822,7 +54822,7 @@ }, "packages/icons": { "name": "@wordpress/icons", - "version": "10.12.0", + "version": "10.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54836,7 +54836,7 @@ }, "packages/interactivity": { "name": "@wordpress/interactivity", - "version": "6.12.0", + "version": "6.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@preact/signals": "^1.3.0", @@ -54849,7 +54849,7 @@ }, "packages/interactivity-router": { "name": "@wordpress/interactivity-router", - "version": "2.12.0", + "version": "2.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/a11y": "*", @@ -54862,7 +54862,7 @@ }, "packages/interface": { "name": "@wordpress/interface", - "version": "8.1.0", + "version": "8.2.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54890,7 +54890,7 @@ }, "packages/is-shallow-equal": { "name": "@wordpress/is-shallow-equal", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54902,7 +54902,7 @@ }, "packages/jest-console": { "name": "@wordpress/jest-console", - "version": "8.12.0", + "version": "8.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54918,7 +54918,7 @@ }, "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", - "version": "12.12.0", + "version": "12.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/jest-console": "*", @@ -54935,7 +54935,7 @@ }, "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.12.0", + "version": "7.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@axe-core/puppeteer": "^4.0.0", @@ -54957,7 +54957,7 @@ }, "packages/keyboard-shortcuts": { "name": "@wordpress/keyboard-shortcuts", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54975,7 +54975,7 @@ }, "packages/keycodes": { "name": "@wordpress/keycodes", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54988,7 +54988,7 @@ }, "packages/lazy-import": { "name": "@wordpress/lazy-import", - "version": "2.12.0", + "version": "2.13.0", "license": "GPL-2.0-or-later", "dependencies": { "execa": "^4.0.2", @@ -55002,7 +55002,7 @@ }, "packages/list-reusable-blocks": { "name": "@wordpress/list-reusable-blocks", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55025,7 +55025,7 @@ }, "packages/media-utils": { "name": "@wordpress/media-utils", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55042,7 +55042,7 @@ }, "packages/notices": { "name": "@wordpress/notices", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55059,7 +55059,7 @@ }, "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55071,7 +55071,7 @@ }, "packages/nux": { "name": "@wordpress/nux", - "version": "9.12.0", + "version": "9.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55094,7 +55094,7 @@ }, "packages/patterns": { "name": "@wordpress/patterns", - "version": "2.12.0", + "version": "2.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55124,7 +55124,7 @@ }, "packages/plugins": { "name": "@wordpress/plugins", - "version": "7.12.0", + "version": "7.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55148,7 +55148,7 @@ }, "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/base-styles": "*", @@ -55164,7 +55164,7 @@ }, "packages/postcss-themes": { "name": "@wordpress/postcss-themes", - "version": "6.12.0", + "version": "6.13.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55176,7 +55176,7 @@ }, "packages/preferences": { "name": "@wordpress/preferences", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55202,7 +55202,7 @@ }, "packages/preferences-persistence": { "name": "@wordpress/preferences-persistence", - "version": "2.12.0", + "version": "2.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55215,7 +55215,7 @@ }, "packages/prettier-config": { "name": "@wordpress/prettier-config", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55227,7 +55227,7 @@ }, "packages/primitives": { "name": "@wordpress/primitives", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55244,7 +55244,7 @@ }, "packages/priority-queue": { "name": "@wordpress/priority-queue", - "version": "3.12.0", + "version": "3.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55257,7 +55257,7 @@ }, "packages/private-apis": { "name": "@wordpress/private-apis", - "version": "1.12.0", + "version": "1.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -55269,7 +55269,7 @@ }, "packages/project-management-automation": { "name": "@wordpress/project-management-automation", - "version": "2.12.0", + "version": "2.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@actions/core": "1.9.1", @@ -55297,7 +55297,7 @@ }, "packages/react-i18n": { "name": "@wordpress/react-i18n", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55453,7 +55453,7 @@ }, "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.12.0", + "version": "3.13.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55465,7 +55465,7 @@ }, "packages/redux-routine": { "name": "@wordpress/redux-routine", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55508,7 +55508,7 @@ }, "packages/reusable-blocks": { "name": "@wordpress/reusable-blocks", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55535,7 +55535,7 @@ }, "packages/rich-text": { "name": "@wordpress/rich-text", - "version": "7.12.0", + "version": "7.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55559,7 +55559,7 @@ }, "packages/router": { "name": "@wordpress/router", - "version": "1.12.0", + "version": "1.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55578,7 +55578,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "30.5.1", + "version": "30.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -56011,7 +56011,7 @@ }, "packages/server-side-render": { "name": "@wordpress/server-side-render", - "version": "5.12.0", + "version": "5.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56037,7 +56037,7 @@ }, "packages/shortcode": { "name": "@wordpress/shortcode", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56050,7 +56050,7 @@ }, "packages/style-engine": { "name": "@wordpress/style-engine", - "version": "2.12.0", + "version": "2.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56063,7 +56063,7 @@ }, "packages/stylelint-config": { "name": "@wordpress/stylelint-config", - "version": "23.4.0", + "version": "23.5.0", "license": "MIT", "dependencies": { "@stylistic/stylelint-plugin": "^3.0.1", @@ -56174,7 +56174,7 @@ }, "packages/sync": { "name": "@wordpress/sync", - "version": "1.12.0", + "version": "1.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56195,7 +56195,7 @@ }, "packages/token-list": { "name": "@wordpress/token-list", - "version": "3.12.0", + "version": "3.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -56207,7 +56207,7 @@ }, "packages/undo-manager": { "name": "@wordpress/undo-manager", - "version": "1.12.0", + "version": "1.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56220,7 +56220,7 @@ }, "packages/url": { "name": "@wordpress/url", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56233,7 +56233,7 @@ }, "packages/viewport": { "name": "@wordpress/viewport", - "version": "6.12.0", + "version": "6.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56263,7 +56263,7 @@ }, "packages/warning": { "name": "@wordpress/warning", - "version": "3.12.0", + "version": "3.13.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -56272,7 +56272,7 @@ }, "packages/widgets": { "name": "@wordpress/widgets", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56300,7 +56300,7 @@ }, "packages/wordcount": { "name": "@wordpress/wordcount", - "version": "4.12.0", + "version": "4.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 2ad91f1131b941..5eefe05954c797 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 4c3c849fe7178a..47d39c978fccd1 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.13.0-prerelease", + "version": "3.13.0", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 8e8909c54f543b..432eabf6ec5a12 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.13.0-prerelease", + "version": "7.13.0", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/package.json b/packages/autop/package.json index 5a77142235ad77..bd48c84775d9ef 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index 60583b94327a51..33244b4e7efb30 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index 30c91ac1b58da6..33d301545c4685 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "6.13.0-prerelease", + "version": "6.13.0", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 44057a5f6171af..afe1025d604a86 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "8.13.0-prerelease", + "version": "8.13.0", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index 21667917ac7fe1..2fc026a9ee72ab 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/package.json b/packages/blob/package.json index d72f180e4b8bf6..4ecf6602400496 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index efc6a16ed3798e..2fa0bf52ea126f 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 608f079366e614..008e02355ac703 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.8.0-prerelease", + "version": "14.8.0", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/package.json b/packages/block-library/package.json index c16a61ac32ec13..77da5721abacb1 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.13.0-prerelease", + "version": "9.13.0", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index a8d0084d43f0a8..2ea349e5f94d23 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 04e657055a8587..0e4c251a8e5f18 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 51d80302c4f184..02f7784ac15aa6 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "14.2.0-prerelease", + "version": "14.2.0", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index bc1051eb99524b..1c3a527226dfaf 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.13.0-prerelease", + "version": "6.13.0", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/package.json b/packages/commands/package.json index 5d6732a6c4b80e..b28a7f89e6c3d2 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.13.0-prerelease", + "version": "1.13.0", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/package.json b/packages/components/package.json index 2a3978e4193734..dc62f992c3bb29 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.13.0-prerelease", + "version": "28.13.0", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/compose/package.json b/packages/compose/package.json index bb84c5c16267fe..72c31dc744057e 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.13.0-prerelease", + "version": "7.13.0", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index 9d21b1ba3b68eb..2f2f4b0ffeb7fb 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.13.0-prerelease", + "version": "1.13.0", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 78fc7076a8d020..fe428aeb87288f 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "7.13.0-prerelease", + "version": "7.13.0", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index 9cb957186c7f73..8f59d685df91dd 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.13.0-prerelease", + "version": "2.13.0", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index c291096222b427..b9f6991c2c153c 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 53d34f8c3109d9..881ece8e138191 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.56.0-prerelease", + "version": "4.56.0", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index c482fdd813dd03..4a14ac743b7249 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 9a7a560bdac51f..6c4703321c6020 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/package.json b/packages/data/package.json index ff68d293c2ac7b..ccb8f8591c0179 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.13.0-prerelease", + "version": "10.13.0", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index b57ead3e54ea9b..f4d42102731eb2 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.9.0-prerelease", + "version": "4.9.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/package.json b/packages/date/package.json index b3b7332bb8bf14..0a1052f13d95fc 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index 8387d658d5aac9..5738c18f55fff5 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.13.0-prerelease", + "version": "6.13.0", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index df43ff9f0639f5..0da22c081e83d4 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/package.json b/packages/docgen/package.json index e5ec91f0dedf08..4b7c5e25efe15c 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.13.0-prerelease", + "version": "2.13.0", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 5ddc5085fa901a..d3aa36e6c6efe5 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/package.json b/packages/dom/package.json index 1bf549364796ca..f2b96de10b5b61 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 3bca976c076b74..ae91fa25e882d8 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.13.0-prerelease", + "version": "1.13.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index 7663ab163c2619..9fcb70294e852d 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.13.0-prerelease", + "version": "11.13.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 3ef68396fc1ce5..62008860a8b290 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.13.0-prerelease", + "version": "8.13.0", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index bd8c5731ef7ccd..aea81f0568fbe2 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.13.0-prerelease", + "version": "8.13.0", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index dd814ed7861eb3..81a8164b1e1721 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.13.0-prerelease", + "version": "6.13.0", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 07ec66e1b8b2f3..ed375f7430a1a4 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "6.13.0-prerelease", + "version": "6.13.0", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/package.json b/packages/editor/package.json index a5fa747b43d9c6..59d3caded3d322 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "14.13.0-prerelease", + "version": "14.13.0", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/element/package.json b/packages/element/package.json index 3e34c6b0ca63af..770d87ef021748 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/element", - "version": "6.13.0-prerelease", + "version": "6.13.0", "description": "Element React module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/env/package.json b/packages/env/package.json index ebb26e21340160..a0cf44e99fb2f9 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/env", - "version": "10.13.0-prerelease", + "version": "10.13.0", "description": "A zero-config, self contained local WordPress environment for development and testing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index 13ebb4793ed127..12e9ae354defa3 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/escape-html", - "version": "3.13.0-prerelease", + "version": "3.13.0", "description": "Escape HTML utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 246da0479393b8..64c0a422873d69 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/eslint-plugin", - "version": "21.6.0-prerelease", + "version": "21.6.0", "description": "ESLint plugin for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/fields/package.json b/packages/fields/package.json index 3e73fe3bb753aa..eb60f448fc13e6 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/fields", - "version": "0.5.0-prerelease", + "version": "0.5.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/format-library/package.json b/packages/format-library/package.json index 06271e0c9c360a..94efb550519ddc 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/format-library", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "Format library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 7aea26efdc7b35..c9e652d30d83e1 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/hooks", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "WordPress hooks library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 4e17fab9045782..f99b2ca99e5fbe 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/html-entities", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "HTML entity utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 8d86bb1d90368c..71f6ea646a93af 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/i18n", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "WordPress internationalization (i18n) library.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/icons/package.json b/packages/icons/package.json index 3df43cb209b437..fb00a4b8d27e8b 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/icons", - "version": "10.13.0-prerelease", + "version": "10.13.0", "description": "WordPress Icons package, based on dashicon.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json index 67cc0704f51603..30881e554e93f0 100644 --- a/packages/interactivity-router/package.json +++ b/packages/interactivity-router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity-router", - "version": "2.13.0-prerelease", + "version": "2.13.0", "description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json index 6382a789dc2b8b..90356de25b646a 100644 --- a/packages/interactivity/package.json +++ b/packages/interactivity/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interactivity", - "version": "6.13.0-prerelease", + "version": "6.13.0", "description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/interface/package.json b/packages/interface/package.json index a1c552f01781ce..2f3ada022dabe4 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/interface", - "version": "8.2.0-prerelease", + "version": "8.2.0", "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 0490fb9c04495b..bc987f67aca88e 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/is-shallow-equal", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "Test for shallow equality between two objects or arrays.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 0615e9ed9ea4f3..638ce7fa523238 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-console", - "version": "8.13.0-prerelease", + "version": "8.13.0", "description": "Custom Jest matchers for the Console object.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 9a1367224c3e90..659c0b78221519 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-preset-default", - "version": "12.13.0-prerelease", + "version": "12.13.0", "description": "Default Jest preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 40595cdfa290b2..c94e1ba4defbde 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.13.0-prerelease", + "version": "7.13.0", "description": "Axe API integration with Jest and Puppeteer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 73c794a087c67c..8510d99a6f8d14 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keyboard-shortcuts", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "Handling keyboard shortcuts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index e2e69f291ce1e5..cc261f4eecf668 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/keycodes", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json index cf4cddb73c8623..f7bf8c7b0d3f3d 100644 --- a/packages/lazy-import/package.json +++ b/packages/lazy-import/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/lazy-import", - "version": "2.13.0-prerelease", + "version": "2.13.0", "description": "Lazily import a module, installing it automatically if missing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 7707592782bcf6..31fd970e2d8da3 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/list-reusable-blocks", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "Adding Export/Import support to the reusable blocks listing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 33ab27a6b98d76..3a2713eed4dacb 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/media-utils", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "WordPress Media Upload Utils.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/notices/package.json b/packages/notices/package.json index a19276cf0e2c01..7f0e0dc71532c1 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/notices", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "State management for notices.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json index 1acd0b7dcf74e5..4dda73b91d2ed2 100644 --- a/packages/npm-package-json-lint-config/package.json +++ b/packages/npm-package-json-lint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "WordPress npm-package-json-lint shareable configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/nux/package.json b/packages/nux/package.json index 612244b92944db..13a803af1ad447 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/nux", - "version": "9.13.0-prerelease", + "version": "9.13.0", "description": "NUX (New User eXperience) module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 42ee04848006b0..b0c6e81f1e2498 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/patterns", - "version": "2.13.0-prerelease", + "version": "2.13.0", "description": "Management of user pattern editing.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 2e1aeaf1c9b3ae..97c0ac64259905 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/plugins", - "version": "7.13.0-prerelease", + "version": "7.13.0", "description": "Plugins module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json index 71802c5da439e0..98c2de79108d66 100644 --- a/packages/postcss-plugins-preset/package.json +++ b/packages/postcss-plugins-preset/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-plugins-preset", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "PostCSS sharable plugins preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json index c6658889aeda4d..c03da4d1f06a72 100644 --- a/packages/postcss-themes/package.json +++ b/packages/postcss-themes/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/postcss-themes", - "version": "6.13.0-prerelease", + "version": "6.13.0", "description": "PostCSS plugin to generate theme colors.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json index 1e5ca3595e9c7b..c9343b28b3e439 100644 --- a/packages/preferences-persistence/package.json +++ b/packages/preferences-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences-persistence", - "version": "2.13.0-prerelease", + "version": "2.13.0", "description": "Persistence utilities for `wordpress/preferences`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/preferences/package.json b/packages/preferences/package.json index 5a94f7c17281e3..9c262dff51fbff 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/preferences", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "Utilities for managing WordPress preferences.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 47dec2d7a7aa06..45f7374e06fbf7 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/prettier-config", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "WordPress Prettier shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/primitives/package.json b/packages/primitives/package.json index b1947e4d7516ec..1f024a64bce463 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/primitives", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "WordPress cross-platform primitives.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 4fa445fc3194ef..eb213ffe2d031a 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/priority-queue", - "version": "3.13.0-prerelease", + "version": "3.13.0", "description": "Generic browser priority queue.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json index bcfc6ad2a0d7ed..1436270e2c7f49 100644 --- a/packages/private-apis/package.json +++ b/packages/private-apis/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/private-apis", - "version": "1.13.0-prerelease", + "version": "1.13.0", "description": "Internal experimental APIs for WordPress core.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 0058153a033250..95c475c5689c24 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/project-management-automation", - "version": "2.13.0-prerelease", + "version": "2.13.0", "description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 2ccfd22673aa91..439596ec2b5d50 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/react-i18n", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "React bindings for @wordpress/i18n.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json index eb14986310c862..5fa231d98088db 100644 --- a/packages/readable-js-assets-webpack-plugin/package.json +++ b/packages/readable-js-assets-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.13.0-prerelease", + "version": "3.13.0", "description": "Generate a readable JS file for each JS asset.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 9704d2cf144bf2..4946cdf6dcaada 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/redux-routine", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "Redux middleware for generator coroutines.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 1461aa747b46b8..b56837df1d34c5 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/reusable-blocks", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "Reusable blocks utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 53e9296889ca84..99637e6023799e 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/rich-text", - "version": "7.13.0-prerelease", + "version": "7.13.0", "description": "Rich text value and manipulation API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/router/package.json b/packages/router/package.json index 0b32d61b3464af..26b4f29df04f60 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/router", - "version": "1.13.0-prerelease", + "version": "1.13.0", "description": "Router API for WordPress pages.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 17f0379de77ce1..f3e6b325f6d3be 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/scripts", - "version": "30.6.0-prerelease", + "version": "30.6.0", "description": "Collection of reusable scripts for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index e538f66985148d..d2cd9aa93d2cef 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/server-side-render", - "version": "5.13.0-prerelease", + "version": "5.13.0", "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index 351b47dd4659dd..f87fe06d9bb421 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/shortcode", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "Shortcode module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json index fa8d19a506108f..bec29df32f7628 100644 --- a/packages/style-engine/package.json +++ b/packages/style-engine/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/style-engine", - "version": "2.13.0-prerelease", + "version": "2.13.0", "description": "A suite of parsers and compilers for WordPress styles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 3b1e94372cc451..0c35601e9c5353 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/stylelint-config", - "version": "23.5.0-prerelease", + "version": "23.5.0", "description": "stylelint config for WordPress development.", "author": "The WordPress Contributors", "license": "MIT", diff --git a/packages/sync/package.json b/packages/sync/package.json index 714832322774ba..042e1544199296 100644 --- a/packages/sync/package.json +++ b/packages/sync/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/sync", - "version": "1.13.0-prerelease", + "version": "1.13.0", "description": "Sync Data.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 0103c07e0e6ead..50fe379c1a08e0 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/token-list", - "version": "3.13.0-prerelease", + "version": "3.13.0", "description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json index 8ebf45fc9df9ec..5046d9591a8c08 100644 --- a/packages/undo-manager/package.json +++ b/packages/undo-manager/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/undo-manager", - "version": "1.13.0-prerelease", + "version": "1.13.0", "description": "A small package to manage undo/redo.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/url/package.json b/packages/url/package.json index 6a4297a5084434..8e3fc0dc140cd8 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/url", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "WordPress URL utilities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 8aadf2af898fb0..a3d15a587645c9 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/viewport", - "version": "6.13.0-prerelease", + "version": "6.13.0", "description": "Viewport module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/warning/package.json b/packages/warning/package.json index 91c4bc5c591955..e41b9205d6d374 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/warning", - "version": "3.13.0-prerelease", + "version": "3.13.0", "description": "Warning utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/widgets/package.json b/packages/widgets/package.json index d72c179a5ad419..0ab7fe138cf513 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/widgets", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index f69f8e06219160..e4e7efbba33256 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/wordcount", - "version": "4.13.0-prerelease", + "version": "4.13.0", "description": "WordPress word count utility.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", From 758b750ee3347cba4f1d334d1ab378387657f837 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 27 Nov 2024 12:24:10 +0100 Subject: [PATCH 1731/1908] Site Editor: Unify layout with posts dataviews (#67162) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../edit-site/src/components/app/index.js | 19 ++++--------------- .../edit-site/src/components/layout/index.js | 17 +++++++++++++++-- .../src/components/posts-app/index.js | 14 +++----------- 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/packages/edit-site/src/components/app/index.js b/packages/edit-site/src/components/app/index.js index 3588565fcb3c17..7e4c50d7d00f09 100644 --- a/packages/edit-site/src/components/app/index.js +++ b/packages/edit-site/src/components/app/index.js @@ -1,11 +1,6 @@ /** * WordPress dependencies */ -import { SlotFillProvider } from '@wordpress/components'; -import { - UnsavedChangesWarning, - privateApis as editorPrivateApis, -} from '@wordpress/editor'; import { store as noticesStore } from '@wordpress/notices'; import { useDispatch } from '@wordpress/data'; import { __, sprintf } from '@wordpress/i18n'; @@ -23,7 +18,6 @@ import useSetCommandContext from '../../hooks/commands/use-set-command-context'; import { useRegisterSiteEditorRoutes } from '../site-editor-routes'; const { RouterProvider } = unlock( routerPrivateApis ); -const { GlobalStylesProvider } = unlock( editorPrivateApis ); function AppLayout() { useCommonCommands(); @@ -50,14 +44,9 @@ export default function App() { } return ( - <SlotFillProvider> - <GlobalStylesProvider> - <UnsavedChangesWarning /> - <RouterProvider> - <AppLayout /> - <PluginArea onError={ onPluginAreaError } /> - </RouterProvider> - </GlobalStylesProvider> - </SlotFillProvider> + <RouterProvider> + <AppLayout /> + <PluginArea onError={ onPluginAreaError } /> + </RouterProvider> ); } diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index cbc0a4661bf3e7..47ff65aa2ac678 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -10,6 +10,7 @@ import { __unstableMotion as motion, __unstableAnimatePresence as AnimatePresence, __unstableUseNavigateRegions as useNavigateRegions, + SlotFillProvider, } from '@wordpress/components'; import { useReducedMotion, @@ -23,6 +24,7 @@ import { CommandMenu } from '@wordpress/commands'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { EditorSnackbars, + UnsavedChangesWarning, privateApis as editorPrivateApis, } from '@wordpress/editor'; import { privateApis as coreCommandsPrivateApis } from '@wordpress/core-commands'; @@ -44,12 +46,12 @@ import SavePanel from '../save-panel'; const { useCommands } = unlock( coreCommandsPrivateApis ); const { useGlobalStyle } = unlock( blockEditorPrivateApis ); -const { NavigableRegion } = unlock( editorPrivateApis ); +const { NavigableRegion, GlobalStylesProvider } = unlock( editorPrivateApis ); const { useLocation } = unlock( routerPrivateApis ); const ANIMATION_DURATION = 0.3; -export default function Layout( { route } ) { +function Layout( { route } ) { const { params } = useLocation(); const { canvas = 'view' } = params; useCommands(); @@ -78,6 +80,7 @@ export default function Layout( { route } ) { return ( <> + <UnsavedChangesWarning /> <CommandMenu /> { canvas === 'view' && <SaveKeyboardShortcut /> } <div @@ -231,3 +234,13 @@ export default function Layout( { route } ) { </> ); } + +export default function LayoutWithGlobalStylesProvider( props ) { + return ( + <SlotFillProvider> + <GlobalStylesProvider> + <Layout { ...props } /> + </GlobalStylesProvider> + </SlotFillProvider> + ); +} diff --git a/packages/edit-site/src/components/posts-app/index.js b/packages/edit-site/src/components/posts-app/index.js index 72e5b1eb997498..e6eb90c1680019 100644 --- a/packages/edit-site/src/components/posts-app/index.js +++ b/packages/edit-site/src/components/posts-app/index.js @@ -1,10 +1,6 @@ /** * WordPress dependencies */ -import { - UnsavedChangesWarning, - privateApis as editorPrivateApis, -} from '@wordpress/editor'; import { privateApis as routerPrivateApis } from '@wordpress/router'; /** @@ -16,7 +12,6 @@ import { unlock } from '../../lock-unlock'; import useActiveRoute from '../layout/router'; const { RouterProvider } = unlock( routerPrivateApis ); -const { GlobalStylesProvider } = unlock( editorPrivateApis ); function PostsLayout() { useRegisterPostsAppRoutes(); @@ -26,11 +21,8 @@ function PostsLayout() { export default function PostsApp() { return ( - <GlobalStylesProvider> - <UnsavedChangesWarning /> - <RouterProvider> - <PostsLayout /> - </RouterProvider> - </GlobalStylesProvider> + <RouterProvider> + <PostsLayout /> + </RouterProvider> ); } From 443ce894391a0e07738661c5b3d4af4e34c47616 Mon Sep 17 00:00:00 2001 From: Benazeer Hassan <66269472+benazeer-ben@users.noreply.github.com> Date: Wed, 27 Nov 2024 19:06:10 +0530 Subject: [PATCH 1732/1908] Site editor: style the selected template pattern (#65917) * Updated code to set active pattern and its styling * Fixes for linting issues on updated files * Updated code based on the first round feedback points * Modification to highlight active iitem on focus * Removed local/session storage * Changes applied from drafted PR * Changes applied from drafted PR * Updated with new style changes * Linting Fix * Updated code to set active pattern and its styling * Fixes for linting issues on updated files * Updated code based on the first round feedback points * Modification to highlight active iitem on focus * Removed local/session storage * Changes applied from drafted PR * Changes applied from drafted PR * Updated with new style changes * Linting Fix * Fix spacing --------- Co-authored-by: benazeer-ben <benazeer@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: patil-vipul <vipulpatil@git.wordpress.org> Co-authored-by: juanfra <juanfra@git.wordpress.org> --- .../components/block-patterns-list/index.js | 13 +++++++++++- .../components/block-patterns-list/style.scss | 21 ++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-patterns-list/index.js b/packages/block-editor/src/components/block-patterns-list/index.js index 8128e89418f45a..0c7e54c3c62b24 100644 --- a/packages/block-editor/src/components/block-patterns-list/index.js +++ b/packages/block-editor/src/components/block-patterns-list/index.js @@ -41,6 +41,7 @@ function BlockPattern( { onHover, showTitlesAsTooltip, category, + isSelected, } ) { const [ isDragging, setIsDragging ] = useState( false ); const { blocks, viewportWidth } = pattern; @@ -114,6 +115,7 @@ function BlockPattern( { pattern.type === INSERTER_PATTERN_TYPES.user && ! pattern.syncStatus, + 'is-selected': isSelected, } ) } /> @@ -192,6 +194,7 @@ function BlockPatternsList( ref ) { const [ activeCompositeId, setActiveCompositeId ] = useState( undefined ); + const [ activePattern, setActivePattern ] = useState( null ); // State to track active pattern useEffect( () => { // Reset the active composite item whenever the available patterns change, @@ -201,6 +204,11 @@ function BlockPatternsList( setActiveCompositeId( firstCompositeItemId ); }, [ blockPatterns ] ); + const handleClickPattern = ( pattern, blocks ) => { + setActivePattern( pattern.name ); + onClickPattern( pattern, blocks ); + }; + return ( <Composite orientation={ orientation } @@ -216,11 +224,14 @@ function BlockPatternsList( key={ pattern.name } id={ pattern.name } pattern={ pattern } - onClick={ onClickPattern } + onClick={ handleClickPattern } onHover={ onHover } isDraggable={ isDraggable } showTitlesAsTooltip={ showTitlesAsTooltip } category={ category } + isSelected={ + !! activePattern && activePattern === pattern.name + } /> ) ) } { pagingProps && <BlockPatternsPaging { ...pagingProps } /> } diff --git a/packages/block-editor/src/components/block-patterns-list/style.scss b/packages/block-editor/src/components/block-patterns-list/style.scss index c46bb49b9a9016..8b1b0b54c9b1a0 100644 --- a/packages/block-editor/src/components/block-patterns-list/style.scss +++ b/packages/block-editor/src/components/block-patterns-list/style.scss @@ -44,19 +44,29 @@ outline: $border-width solid rgba($black, 0.1); outline-offset: -$border-width; border-radius: $radius-medium; + + transition: outline 0.1s linear; + @include reduce-motion("transition"); } } - &:hover:not(:focus) .block-editor-block-preview__container::after { + // Selected + &.is-selected .block-editor-block-preview__container::after { + outline-color: $gray-900; + outline-width: var(--wp-admin-border-width-focus); + outline-offset: calc(-1 * var(--wp-admin-border-width-focus)); + } + + // Hover state + &:hover .block-editor-block-preview__container::after { outline-color: rgba($black, 0.3); } - &:focus .block-editor-block-preview__container::after { + // Focused state + &[data-focus-visible] .block-editor-block-preview__container::after { outline-color: var(--wp-admin-theme-color); outline-width: var(--wp-admin-border-width-focus); - outline-offset: calc((-1 * var(--wp-admin-border-width-focus))); - transition: outline 0.1s linear; - @include reduce-motion("transition"); + outline-offset: calc(-1 * var(--wp-admin-border-width-focus)); } .block-editor-patterns__pattern-details:not(:empty) { @@ -68,6 +78,7 @@ .block-editor-patterns__pattern-icon-wrapper { min-width: 24px; height: 24px; + .block-editor-patterns__pattern-icon { fill: var(--wp-block-synced-color); } From 78fffa7ff0e2c19ac2891633f251f6470dae045b Mon Sep 17 00:00:00 2001 From: Andrei Draganescu <andrei.draganescu@automattic.com> Date: Wed, 27 Nov 2024 16:23:20 +0200 Subject: [PATCH 1733/1908] keep only copy, duplicate and delete in the more menu (#67279) Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- .../block-settings-menu-controls/index.js | 3 ++- .../block-settings-dropdown.js | 7 ++++++- .../editor/src/components/provider/index.js | 20 ++++++++++++++++--- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/block-settings-menu-controls/index.js b/packages/block-editor/src/components/block-settings-menu-controls/index.js index 4ebce4172e9b37..b0755be4c26297 100644 --- a/packages/block-editor/src/components/block-settings-menu-controls/index.js +++ b/packages/block-editor/src/components/block-settings-menu-controls/index.js @@ -55,7 +55,8 @@ const BlockSettingsMenuControlsSlot = ( { fillProps, clientIds = null } ) => { const convertToGroupButtonProps = useConvertToGroupButtonProps( selectedClientIds ); const { isGroupable, isUngroupable } = convertToGroupButtonProps; - const showConvertToGroupButton = isGroupable || isUngroupable; + const showConvertToGroupButton = + ( isGroupable || isUngroupable ) && ! isContentOnly; return ( <Slot diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index a0bbb6c708fea1..b9caee7c338beb 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -57,6 +57,7 @@ export function BlockSettingsDropdown( { const currentClientId = block?.clientId; const count = clientIds.length; const firstBlockClientId = clientIds[ 0 ]; + const { firstParentClientId, parentBlockType, @@ -64,6 +65,7 @@ export function BlockSettingsDropdown( { selectedBlockClientIds, openedBlockSettingsMenu, isContentOnly, + isZoomOut, } = useSelect( ( select ) => { const { @@ -74,6 +76,7 @@ export function BlockSettingsDropdown( { getBlockAttributes, getOpenedBlockSettingsMenu, getBlockEditingMode, + isZoomOut: _isZoomOut, } = unlock( select( blockEditorStore ) ); const { getActiveBlockVariation } = select( blocksStore ); @@ -98,10 +101,12 @@ export function BlockSettingsDropdown( { openedBlockSettingsMenu: getOpenedBlockSettingsMenu(), isContentOnly: getBlockEditingMode( firstBlockClientId ) === 'contentOnly', + isZoomOut: _isZoomOut(), }; }, [ firstBlockClientId ] ); + const { getBlockOrder, getSelectedBlockClientIds } = useSelect( blockEditorStore ); @@ -248,7 +253,7 @@ export function BlockSettingsDropdown( { clientId={ firstBlockClientId } /> ) } - { ! isContentOnly && ( + { ( ! isContentOnly || isZoomOut ) && ( <CopyMenuItem clientIds={ clientIds } onCopy={ onCopy } diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 996e9e68954591..68d7bd1d3f4f5b 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -13,6 +13,7 @@ import { BlockEditorProvider, BlockContextProvider, privateApis as blockEditorPrivateApis, + store as blockEditorStore, } from '@wordpress/block-editor'; import { store as noticesStore } from '@wordpress/notices'; import { privateApis as editPatternsPrivateApis } from '@wordpress/patterns'; @@ -205,6 +206,15 @@ export const ExperimentalEditorProvider = withRegistryProvider( }, [ post.type ] ); + + const isZoomOut = useSelect( ( select ) => { + const { isZoomOut: _isZoomOut } = unlock( + select( blockEditorStore ) + ); + + return _isZoomOut(); + } ); + const shouldRenderTemplate = !! template && mode !== 'post-only'; const rootLevelPost = shouldRenderTemplate ? template : post; const defaultBlockContext = useMemo( () => { @@ -357,9 +367,13 @@ export const ExperimentalEditorProvider = withRegistryProvider( { children } { ! settings.isPreviewMode && ( <> - <PatternsMenuItems /> - <TemplatePartMenuItems /> - <ContentOnlySettingsMenu /> + { ! isZoomOut && ( + <> + <PatternsMenuItems /> + <TemplatePartMenuItems /> + <ContentOnlySettingsMenu /> + </> + ) } { mode === 'template-locked' && ( <DisableNonPageContentBlocks /> ) } From f8140c4fcc8db2d6078ad76fd433c79df3543860 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Wed, 27 Nov 2024 15:58:58 +0100 Subject: [PATCH 1734/1908] Drag and drop: fix drop zones on block drag (#67317) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../inserter-draggable-blocks/index.js | 48 +++++++---------- .../src/components/media-placeholder/index.js | 53 +++++++++---------- packages/components/CHANGELOG.md | 1 + packages/components/src/drop-zone/index.tsx | 45 ++++++++-------- packages/components/src/drop-zone/types.ts | 5 ++ test/e2e/specs/editor/blocks/image.spec.js | 23 ++++---- 6 files changed, 84 insertions(+), 91 deletions(-) diff --git a/packages/block-editor/src/components/inserter-draggable-blocks/index.js b/packages/block-editor/src/components/inserter-draggable-blocks/index.js index 0e1aaadc72e67b..ebef6304937aa7 100644 --- a/packages/block-editor/src/components/inserter-draggable-blocks/index.js +++ b/packages/block-editor/src/components/inserter-draggable-blocks/index.js @@ -2,12 +2,9 @@ * WordPress dependencies */ import { Draggable } from '@wordpress/components'; -import { - createBlock, - serialize, - store as blocksStore, -} from '@wordpress/blocks'; +import { createBlock, store as blocksStore } from '@wordpress/blocks'; import { useDispatch, useSelect } from '@wordpress/data'; +import { useMemo } from '@wordpress/element'; /** * Internal dependencies @@ -24,20 +21,6 @@ const InserterDraggableBlocks = ( { children, pattern, } ) => { - const transferData = { - type: 'inserter', - blocks, - }; - - const blocksContainMedia = - blocks.filter( - ( block ) => - ( block.name === 'core/image' || - block.name === 'core/audio' || - block.name === 'core/video' ) && - ( block.attributes.url || block.attributes.src ) - ).length > 0; - const blockTypeIcon = useSelect( ( select ) => { const { getBlockType } = select( blocksStore ); @@ -52,6 +35,13 @@ const InserterDraggableBlocks = ( { useDispatch( blockEditorStore ) ); + const patternBlock = useMemo( () => { + return pattern?.type === INSERTER_PATTERN_TYPES.user && + pattern?.syncStatus !== 'unsynced' + ? [ createBlock( 'core/block', { ref: pattern.id } ) ] + : undefined; + }, [ pattern?.type, pattern?.syncStatus, pattern?.id ] ); + if ( ! isEnabled ) { return children( { draggable: false, @@ -60,21 +50,21 @@ const InserterDraggableBlocks = ( { } ); } + const draggableBlocks = patternBlock ?? blocks; return ( <Draggable __experimentalTransferDataType="wp-blocks" - transferData={ transferData } + transferData={ { type: 'inserter', blocks: draggableBlocks } } onDragStart={ ( event ) => { startDragging(); - const parsedBlocks = - pattern?.type === INSERTER_PATTERN_TYPES.user && - pattern?.syncStatus !== 'unsynced' - ? [ createBlock( 'core/block', { ref: pattern.id } ) ] - : blocks; - event.dataTransfer.setData( - blocksContainMedia ? 'default' : 'text/html', - serialize( parsedBlocks ) - ); + for ( const block of draggableBlocks ) { + const type = `wp-block:${ block.name }`; + // This will fill in the dataTransfer.types array so that + // the drop zone can check if the draggable is eligible. + // Unfortuantely, on drag start, we don't have access to the + // actual data, only the data keys/types. + event.dataTransfer.items.add( '', type ); + } } } onDragEnd={ () => { stopDragging(); diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index e7b6c836468f02..0cbc6c8c26203f 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -19,7 +19,6 @@ import { __ } from '@wordpress/i18n'; import { useState, useEffect } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; import { keyboardReturn } from '@wordpress/icons'; -import { pasteHandler } from '@wordpress/blocks'; import deprecated from '@wordpress/deprecated'; /** @@ -29,6 +28,7 @@ import MediaUpload from '../media-upload'; import MediaUploadCheck from '../media-upload/check'; import URLPopover from '../url-popover'; import { store as blockEditorStore } from '../../store'; +import { parseDropEvent } from '../use-on-block-drop'; const noop = () => {}; @@ -229,30 +229,15 @@ export function MediaPlaceholder( { } ); }; - async function handleBlocksDrop( blocks ) { - if ( ! blocks || ! Array.isArray( blocks ) ) { - return; - } + async function handleBlocksDrop( event ) { + const { blocks } = parseDropEvent( event ); - function recursivelyFindMediaFromBlocks( _blocks ) { - return _blocks.flatMap( ( block ) => - ( block.name === 'core/image' || - block.name === 'core/audio' || - block.name === 'core/video' ) && - ( block.attributes.url || block.attributes.src ) - ? [ block ] - : recursivelyFindMediaFromBlocks( block.innerBlocks ) - ); - } - - const mediaBlocks = recursivelyFindMediaFromBlocks( blocks ); - - if ( ! mediaBlocks.length ) { + if ( ! blocks?.length ) { return; } const uploadedMediaList = await Promise.all( - mediaBlocks.map( ( block ) => { + blocks.map( ( block ) => { const blockType = block.name.split( '/' )[ 1 ]; if ( block.attributes.id ) { block.attributes.type = blockType; @@ -292,13 +277,6 @@ export function MediaPlaceholder( { } } - async function onDrop( event ) { - const blocks = pasteHandler( { - HTML: event.dataTransfer?.getData( 'default' ), - } ); - return await handleBlocksDrop( blocks ); - } - const onUpload = ( event ) => { onFilesUpload( event.target.files ); }; @@ -385,7 +363,26 @@ export function MediaPlaceholder( { return null; } - return <DropZone onFilesDrop={ onFilesUpload } onDrop={ onDrop } />; + return ( + <DropZone + onFilesDrop={ onFilesUpload } + onDrop={ handleBlocksDrop } + isEligible={ ( dataTransfer ) => { + const prefix = 'wp-block:core/'; + const types = []; + for ( const type of dataTransfer.types ) { + if ( type.startsWith( prefix ) ) { + types.push( type.slice( prefix.length ) ); + } + } + return ( + types.every( ( type ) => + allowedTypes.includes( type ) + ) && ( multiple ? true : types.length === 1 ) + ); + } } + /> + ); }; const renderCancelLink = () => { diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index feff5ddc975356..a780f8f139d3e7 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -32,6 +32,7 @@ - `ColorPicker`: Update sizes of color format select and copy button ([#67093](https://github.com/WordPress/gutenberg/pull/67093)). - `ComboboxControl`: Update reset button size ([#67215](https://github.com/WordPress/gutenberg/pull/67215)). - `Autocomplete`: Increase option height ([#67214](https://github.com/WordPress/gutenberg/pull/67214)). +- `DropZone`: Add `isEligible` prop to allow customizing whether the drop zone should activate ([#67317](https://github.com/WordPress/gutenberg/pull/67317)). - `CircularOptionPicker`: Update `Button` sizes to be ready for 40px default size ([#67285](https://github.com/WordPress/gutenberg/pull/67285)). ### Experimental diff --git a/packages/components/src/drop-zone/index.tsx b/packages/components/src/drop-zone/index.tsx index b1bd0199e877d8..dd8b97149a0598 100644 --- a/packages/components/src/drop-zone/index.tsx +++ b/packages/components/src/drop-zone/index.tsx @@ -15,7 +15,7 @@ import { __experimentalUseDropZone as useDropZone } from '@wordpress/compose'; /** * Internal dependencies */ -import type { DropType, DropZoneProps } from './types'; +import type { DropZoneProps } from './types'; import type { WordPressComponentProps } from '../context'; /** @@ -47,19 +47,22 @@ export function DropZoneComponent( { onFilesDrop, onHTMLDrop, onDrop, + isEligible = () => true, ...restProps }: WordPressComponentProps< DropZoneProps, 'div', false > ) { const [ isDraggingOverDocument, setIsDraggingOverDocument ] = useState< boolean >(); const [ isDraggingOverElement, setIsDraggingOverElement ] = useState< boolean >(); - const [ type, setType ] = useState< DropType >(); + const [ isActive, setIsActive ] = useState< boolean >(); const ref = useDropZone( { onDrop( event ) { - const files = event.dataTransfer - ? getFilesFromDataTransfer( event.dataTransfer ) - : []; - const html = event.dataTransfer?.getData( 'text/html' ); + if ( ! event.dataTransfer ) { + return; + } + + const files = getFilesFromDataTransfer( event.dataTransfer ); + const html = event.dataTransfer.getData( 'text/html' ); /** * From Windows Chrome 96, the `event.dataTransfer` returns both file object and HTML. @@ -76,32 +79,31 @@ export function DropZoneComponent( { onDragStart( event ) { setIsDraggingOverDocument( true ); - let _type: DropType = 'default'; + if ( ! event.dataTransfer ) { + return; + } /** * From Windows Chrome 96, the `event.dataTransfer` returns both file object and HTML. * The order of the checks is important to recognize the HTML drop. */ - if ( event.dataTransfer?.types.includes( 'text/html' ) ) { - _type = 'html'; + if ( event.dataTransfer.types.includes( 'text/html' ) ) { + setIsActive( !! onHTMLDrop ); } else if ( // Check for the types because sometimes the files themselves // are only available on drop. - event.dataTransfer?.types.includes( 'Files' ) || - ( event.dataTransfer - ? getFilesFromDataTransfer( event.dataTransfer ) - : [] - ).length > 0 + event.dataTransfer.types.includes( 'Files' ) || + getFilesFromDataTransfer( event.dataTransfer ).length > 0 ) { - _type = 'file'; + setIsActive( !! onFilesDrop ); + } else { + setIsActive( !! onDrop && isEligible( event.dataTransfer ) ); } - - setType( _type ); }, onDragEnd() { setIsDraggingOverElement( false ); setIsDraggingOverDocument( false ); - setType( undefined ); + setIsActive( undefined ); }, onDragEnter() { setIsDraggingOverElement( true ); @@ -112,14 +114,9 @@ export function DropZoneComponent( { } ); const classes = clsx( 'components-drop-zone', className, { - 'is-active': - ( isDraggingOverDocument || isDraggingOverElement ) && - ( ( type === 'file' && onFilesDrop ) || - ( type === 'html' && onHTMLDrop ) || - ( type === 'default' && onDrop ) ), + 'is-active': isActive, 'is-dragging-over-document': isDraggingOverDocument, 'is-dragging-over-element': isDraggingOverElement, - [ `is-dragging-${ type }` ]: !! type, } ); return ( diff --git a/packages/components/src/drop-zone/types.ts b/packages/components/src/drop-zone/types.ts index 3982889a4f3eac..503f400bc4be45 100644 --- a/packages/components/src/drop-zone/types.ts +++ b/packages/components/src/drop-zone/types.ts @@ -26,4 +26,9 @@ export type DropZoneProps = { * It receives the HTML being dropped as an argument. */ onHTMLDrop?: ( html: string ) => void; + /** + * A function to determine if the drop zone is eligible to handle the drop + * data transfer items. + */ + isEligible?: ( dataTransfer: DataTransfer ) => boolean; }; diff --git a/test/e2e/specs/editor/blocks/image.spec.js b/test/e2e/specs/editor/blocks/image.spec.js index b2195f2c676885..d3cddd9c3a51cd 100644 --- a/test/e2e/specs/editor/blocks/image.spec.js +++ b/test/e2e/specs/editor/blocks/image.spec.js @@ -528,14 +528,13 @@ test.describe( 'Image', () => { name: 'Block: Image', } ); - const html = ` - <figure> - <img src="https://live.staticflickr.com/3894/14962688165_04759a8b03_b.jpg" alt="Cat"> - <figcaption>"Cat" by tomhouslay is licensed under <a href="https://creativecommons.org/licenses/by-nc/2.0/?ref=openverse">CC BY-NC 2.0</a>.</figcaption> - </figure> - `; - - await page.evaluate( ( _html ) => { + await page.evaluate( () => { + const { createBlock } = window.wp.blocks; + const block = createBlock( 'core/image', { + url: 'https://live.staticflickr.com/3894/14962688165_04759a8b03_b.jpg', + alt: 'Cat', + caption: `"Cat" by tomhouslay is licensed under <a href="https://creativecommons.org/licenses/by-nc/2.0/?ref=openverse">CC BY-NC 2.0</a>.`, + } ); const dummy = document.createElement( 'div' ); dummy.style.width = '10px'; dummy.style.height = '10px'; @@ -545,13 +544,17 @@ test.describe( 'Image', () => { dummy.style.left = 0; dummy.draggable = 'true'; dummy.addEventListener( 'dragstart', ( event ) => { - event.dataTransfer.setData( 'default', _html ); + event.dataTransfer.setData( + 'wp-blocks', + JSON.stringify( { blocks: [ block ] } ) + ); + event.dataTransfer.setData( 'wp-block:core/image', '' ); setTimeout( () => { dummy.remove(); }, 0 ); } ); document.body.appendChild( dummy ); - }, html ); + } ); await page.mouse.move( 0, 0 ); await page.mouse.down(); From 8dd99aaeba86ed65ab3e301a5179acd9d6ef8304 Mon Sep 17 00:00:00 2001 From: Mayank Tripathi <70465598+Mayank-Tripathi32@users.noreply.github.com> Date: Wed, 27 Nov 2024 22:14:18 +0530 Subject: [PATCH 1735/1908] Fix: Header layout spacing in Firefox (#67074) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: Mayank-Tripathi32 <mayanktripathi32@git.wordpress.org> Co-authored-by: SainathPoojary <sainathpoojary@git.wordpress.org> Co-authored-by: maddisondesigns <ahortin@git.wordpress.org> --- packages/editor/src/components/header/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/header/style.scss b/packages/editor/src/components/header/style.scss index d12c01506a052c..4cbbe992e63fdb 100644 --- a/packages/editor/src/components/header/style.scss +++ b/packages/editor/src/components/header/style.scss @@ -7,7 +7,7 @@ &:has(> .editor-header__center) { grid-template: auto / $header-height min-content 1fr min-content $header-height; @include break-medium { - grid-template: auto / $header-height minmax(min-content, 1fr) 2fr minmax(min-content, 1fr) $header-height; + grid-template: auto / $header-height minmax(min-content, 2fr) 2.5fr minmax(min-content, 2fr) $header-height; } } @include break-mobile { From 6781982c80cbc025308500a1f54ae31792ebdc24 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Thu, 28 Nov 2024 03:18:38 +0900 Subject: [PATCH 1736/1908] DuotonePicker: Simplify Button styles (#66641) * DuotonePicker: Simplify Button styles * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../duotone-picker/color-list-picker/index.tsx | 16 ++++++++-------- .../duotone-picker/color-list-picker/style.scss | 6 ------ 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index a780f8f139d3e7..be930515f16659 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -34,6 +34,7 @@ - `Autocomplete`: Increase option height ([#67214](https://github.com/WordPress/gutenberg/pull/67214)). - `DropZone`: Add `isEligible` prop to allow customizing whether the drop zone should activate ([#67317](https://github.com/WordPress/gutenberg/pull/67317)). - `CircularOptionPicker`: Update `Button` sizes to be ready for 40px default size ([#67285](https://github.com/WordPress/gutenberg/pull/67285)). +- `DuotonePicker`: Simplify Button styles ([#66641](https://github.com/WordPress/gutenberg/pull/66641)). ### Experimental diff --git a/packages/components/src/duotone-picker/color-list-picker/index.tsx b/packages/components/src/duotone-picker/color-list-picker/index.tsx index bd009c5db1d7d4..e3925b7d064fdc 100644 --- a/packages/components/src/duotone-picker/color-list-picker/index.tsx +++ b/packages/components/src/duotone-picker/color-list-picker/index.tsx @@ -12,7 +12,6 @@ import Button from '../../button'; import ColorPalette from '../../color-palette'; import ColorIndicator from '../../color-indicator'; import Icon from '../../icon'; -import { HStack } from '../../h-stack'; import type { ColorListPickerProps, ColorOptionProps } from './types'; import { useInstanceId } from '@wordpress/compose'; @@ -32,23 +31,24 @@ function ColorOption( { return ( <> <Button + __next40pxDefaultSize className="components-color-list-picker__swatch-button" + id={ labelId } onClick={ () => setIsOpen( ( prev ) => ! prev ) } aria-expanded={ isOpen } aria-controls={ contentId } - > - <HStack justify="flex-start" spacing={ 2 }> - { value ? ( + icon={ + value ? ( <ColorIndicator colorValue={ value } className="components-color-list-picker__swatch-color" /> ) : ( <Icon icon={ swatch } /> - ) } - <span id={ labelId }>{ label }</span> - </HStack> - </Button> + ) + } + text={ label } + /> <div role="group" id={ contentId } diff --git a/packages/components/src/duotone-picker/color-list-picker/style.scss b/packages/components/src/duotone-picker/color-list-picker/style.scss index dd0c79ffb8062b..56f2546158329a 100644 --- a/packages/components/src/duotone-picker/color-list-picker/style.scss +++ b/packages/components/src/duotone-picker/color-list-picker/style.scss @@ -7,12 +7,6 @@ margin: $grid-unit-10 0; } -.components-color-list-picker__swatch-button { - // Used to simulate styles as a .button.has-icon (which this component can't - // opt into, because it has to show more than a simple SVG as the "icon") - padding: 6px; -} - .components-color-list-picker__swatch-color { // Match the 24px size of the `swatch` icon (used when no color is set) margin: 2px; From c070dd43e20ad4db75531e04aad4d977851be8db Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 27 Nov 2024 20:27:28 +0100 Subject: [PATCH 1737/1908] Remove fallback for `context.postType` (#67345) Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> --- packages/editor/src/bindings/post-meta.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index a3602ce7d62076..fcd068ac21d8ab 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -108,11 +108,8 @@ export default { return false; } - const postType = - context?.postType || select( editorStore ).getCurrentPostType(); - - // Check that editing is happening in the post editor and not a template. - if ( postType === 'wp_template' ) { + // Lock editing when `postType` is not defined. + if ( ! context?.postType ) { return false; } From d9eb6d9a6d64650f08ee68792b88f914de62cda1 Mon Sep 17 00:00:00 2001 From: Bernie Reiter <96308+ockham@users.noreply.github.com> Date: Wed, 27 Nov 2024 20:35:22 +0100 Subject: [PATCH 1738/1908] Navigation block: Remove more obsolete Block Hooks helpers (#67193) - `block_core_navigation_remove_serialized_parent_block` was `replaced by remove_serialized_parent_block`. - `apply_block_hooks_to_content` has been part of WP Core since 6.6, so we don't need to check for its existence anymore. Co-authored-by: ockham <bernhard-reiter@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> --- .../block-library/src/navigation/index.php | 31 ++----------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index ae3b9620a33584..68b23aceeced65 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -1436,20 +1436,6 @@ function block_core_navigation_get_most_recently_published_navigation() { return null; } -/** - * Accepts the serialized markup of a block and its inner blocks, and returns serialized markup of the inner blocks. - * - * @since 6.5.0 - * - * @param string $serialized_block The serialized markup of a block and its inner blocks. - * @return string - */ -function block_core_navigation_remove_serialized_parent_block( $serialized_block ) { - $start = strpos( $serialized_block, '-->' ) + strlen( '-->' ); - $end = strrpos( $serialized_block, '<!--' ); - return substr( $serialized_block, $start, $end - $start ); -} - /** * Mock a parsed block for the Navigation block given its inner blocks and the `wp_navigation` post object. * The `wp_navigation` post's `_wp_ignored_hooked_blocks` meta is queried to add the `metadata.ignoredHookedBlocks` attribute. @@ -1504,19 +1490,6 @@ function block_core_navigation_mock_parsed_block( $inner_blocks, $post ) { function block_core_navigation_insert_hooked_blocks( $inner_blocks, $post ) { $mock_navigation_block = block_core_navigation_mock_parsed_block( $inner_blocks, $post ); - if ( function_exists( 'apply_block_hooks_to_content' ) ) { - $mock_navigation_block_markup = serialize_block( $mock_navigation_block ); - return apply_block_hooks_to_content( $mock_navigation_block_markup, $post, 'insert_hooked_blocks' ); - } - - $hooked_blocks = get_hooked_blocks(); - $before_block_visitor = null; - $after_block_visitor = null; - - if ( ! empty( $hooked_blocks ) || has_filter( 'hooked_block_types' ) ) { - $before_block_visitor = make_before_block_visitor( $hooked_blocks, $post, 'insert_hooked_blocks' ); - $after_block_visitor = make_after_block_visitor( $hooked_blocks, $post, 'insert_hooked_blocks' ); - } - - return traverse_and_serialize_block( $mock_navigation_block, $before_block_visitor, $after_block_visitor ); + $mock_navigation_block_markup = serialize_block( $mock_navigation_block ); + return apply_block_hooks_to_content( $mock_navigation_block_markup, $post, 'insert_hooked_blocks' ); } From fe70c1290360f9d4daf033e717c70ed85facb056 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 27 Nov 2024 20:33:29 +0000 Subject: [PATCH 1739/1908] Update Changelog for 19.7.0 --- changelog.txt | 291 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) diff --git a/changelog.txt b/changelog.txt index bf13c6b273e9b6..9e07615adf43f6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,296 @@ == Changelog == += 19.7.0 = + +## Changelog + +### Enhancements + +- Add "show template" to preview dropdown. ([66514](https://github.com/WordPress/gutenberg/pull/66514)) +- Iframe: Always enable for block themes, in core too. ([66800](https://github.com/WordPress/gutenberg/pull/66800)) +- Media Utils: Add experimental `sideloadMedia`. ([66378](https://github.com/WordPress/gutenberg/pull/66378)) +- Post fields: Clean up. ([66941](https://github.com/WordPress/gutenberg/pull/66941)) +- Post fields: Extract `title` from `edit-site` to `fields` package. ([66940](https://github.com/WordPress/gutenberg/pull/66940)) +- Post fields: Move `comment_status` from edit-site to fields package. ([66934](https://github.com/WordPress/gutenberg/pull/66934)) +- Post fields: Move `date` fields from `edit-site` to `fields` package. ([66938](https://github.com/WordPress/gutenberg/pull/66938)) +- Post fields: Move `status` from `edit-site` to `fields`. ([66937](https://github.com/WordPress/gutenberg/pull/66937)) +- Relocate “View” external link to end of editor header controls. ([66785](https://github.com/WordPress/gutenberg/pull/66785)) + +#### Block Library +- Added toggle control to set any image as feature image if no feature image is set for post. ([65896](https://github.com/WordPress/gutenberg/pull/65896)) +- Improve cover z-index solution. ([66249](https://github.com/WordPress/gutenberg/pull/66249)) +- Post Content: Add border and spacing support. ([66366](https://github.com/WordPress/gutenberg/pull/66366)) +- Query Loop: Use templateSlug and postType for more context. ([65820](https://github.com/WordPress/gutenberg/pull/65820)) +- Update text case of "Starter Content". ([66954](https://github.com/WordPress/gutenberg/pull/66954)) +- [Details Block]: Adds anchor support in details block. ([66734](https://github.com/WordPress/gutenberg/pull/66734)) + +#### Components +- Guide: Use small size button for page controls. ([66607](https://github.com/WordPress/gutenberg/pull/66607)) +- MenuItem: Add 40px size prop on Button. ([66596](https://github.com/WordPress/gutenberg/pull/66596)) +- Notice: Add appropriate size props to Buttons. ([66593](https://github.com/WordPress/gutenberg/pull/66593)) +- PaletteEdit: Add appropriate size props to Buttons. ([66590](https://github.com/WordPress/gutenberg/pull/66590)) +- Popover: Add small size prop to close button. ([66587](https://github.com/WordPress/gutenberg/pull/66587)) + +#### Global Styles +- Global styles revisions: Move focus and active state to list item. ([66780](https://github.com/WordPress/gutenberg/pull/66780)) +- Site editor: Integrate global styles controls and style book preview into the styles panel. ([65619](https://github.com/WordPress/gutenberg/pull/65619)) + +#### DataViews +- DataViews Fields API: Default getValueFromId supports nested objects. ([66890](https://github.com/WordPress/gutenberg/pull/66890)) + +#### Block Editor +- Inserter: Add 'Starter Content' category to the inserter. ([66819](https://github.com/WordPress/gutenberg/pull/66819)) + +#### Zoom Out +- Enable zoom out mode for non-iframe editor. ([66789](https://github.com/WordPress/gutenberg/pull/66789)) + +#### Themes +- Theme JSON Resolver: Remove theme json merge in resolve_theme_file_uris. ([66662](https://github.com/WordPress/gutenberg/pull/66662)) + +#### Edit Mode +- Image block: Add support for "more" dropdown for additional tools in Write mode. ([66605](https://github.com/WordPress/gutenberg/pull/66605)) + +#### Style Book +- Add a landing section to stylebook tabs. ([66545](https://github.com/WordPress/gutenberg/pull/66545)) + +#### Media +- Media Library: Expose filters dropdown for individual images, such as with the Image block. ([65965](https://github.com/WordPress/gutenberg/pull/65965)) + + +### Bug Fixes + +- Block toolbar: Restrict visible child calculation to known blocks. ([66702](https://github.com/WordPress/gutenberg/pull/66702)) +- ComplementaryArea: Fix button position. ([66677](https://github.com/WordPress/gutenberg/pull/66677)) +- Fix Paragraph appender layout shift (building on 66061). ([66779](https://github.com/WordPress/gutenberg/pull/66779)) +- Fix: Set the `fit-content` width for images that are not `.svg`. ([66643](https://github.com/WordPress/gutenberg/pull/66643)) +- Preference modal: Avoid fetching all reusable blocks when the site editor loads. ([66621](https://github.com/WordPress/gutenberg/pull/66621)) +- Revert "Set image width to `fit-content` to solve aspect ratio problems in Firefox. (#66217)". ([66804](https://github.com/WordPress/gutenberg/pull/66804)) +- Safari: Fix site editor template error. ([66647](https://github.com/WordPress/gutenberg/pull/66647)) +- Safari: Prevent focus capturing caused by flex display. ([66402](https://github.com/WordPress/gutenberg/pull/66402)) +- Select Mode: Hide tool selector in the post editor and force design mode. ([66784](https://github.com/WordPress/gutenberg/pull/66784)) +- Shadow panel: Make the delete modal text translatable. ([66712](https://github.com/WordPress/gutenberg/pull/66712)) +- Site Editor: Fix template for page-on-front option. ([66739](https://github.com/WordPress/gutenberg/pull/66739)) +- WP Scripts: Make watch mode more resilient for developer errors. ([66752](https://github.com/WordPress/gutenberg/pull/66752)) +- getDefaultTemplateId: Ensure entity configuration is loaded. ([66650](https://github.com/WordPress/gutenberg/pull/66650)) +- Comments controller: fix issue where comments are allowed when closed (https://github.com/WordPress/gutenberg/pull/66976) + +#### Block Library +- Cover: Fix media library image selection. ([66782](https://github.com/WordPress/gutenberg/pull/66782)) +- Cover: Show DropZone only when dragging withing the block. ([66912](https://github.com/WordPress/gutenberg/pull/66912)) +- Media & Text: Set `.wp-block-media-text__media a` display to block. ([66915](https://github.com/WordPress/gutenberg/pull/66915)) +- Prevent duplicate post format taxonomy queries. ([66627](https://github.com/WordPress/gutenberg/pull/66627)) +- Query Loop: Check for postTypeFromContext before using it. ([66655](https://github.com/WordPress/gutenberg/pull/66655)) +- Query Loop: Remove postTypeFromContext. ([66681](https://github.com/WordPress/gutenberg/pull/66681)) + +#### Block Editor +- Appender: Fix initial position. ([66711](https://github.com/WordPress/gutenberg/pull/66711)) +- Appender: Fix outside canvas styles. ([66630](https://github.com/WordPress/gutenberg/pull/66630)) +- Block Inspector: Restore bottom margin for RadioControl. ([66688](https://github.com/WordPress/gutenberg/pull/66688)) +- Iframed editor: Fix relative wp-content URLs. ([66751](https://github.com/WordPress/gutenberg/pull/66751)) + +#### Global Styles +- Section Styles: Fix insecure properties removal for inner block types and elements. ([66896](https://github.com/WordPress/gutenberg/pull/66896)) +- Style book: Reduce margin selector specificity so that it doesn't override global block styles. ([66895](https://github.com/WordPress/gutenberg/pull/66895)) +- Theme JSON: Replace top-level background style objects on merge. ([66656](https://github.com/WordPress/gutenberg/pull/66656)) + +#### Components +- FormTokenField: Fix token styles. ([66640](https://github.com/WordPress/gutenberg/pull/66640)) +- Storybook: Fix DataViews action modals. ([66727](https://github.com/WordPress/gutenberg/pull/66727)) +- ToggleGroupControl: Fix active background for `zero` value. ([66855](https://github.com/WordPress/gutenberg/pull/66855)) + +#### Post Editor +- Disable device preview button in pattern/template part/navitation editor. ([65970](https://github.com/WordPress/gutenberg/pull/65970)) +- PostTaxonomiesFlatTermSelector: Abstract wrapper component. ([66625](https://github.com/WordPress/gutenberg/pull/66625)) +- VisualEditor: Always output has-global-padding classname when in post only mode. ([66626](https://github.com/WordPress/gutenberg/pull/66626)) + +#### DataViews +- Fix TypeError when duplicating uncategorized theme patterns. ([66889](https://github.com/WordPress/gutenberg/pull/66889)) +- Tweak primary field in patterns grid layout. ([66733](https://github.com/WordPress/gutenberg/pull/66733)) + +#### Meta Boxes +- Fix: Show Meta Boxes at the bottom of the screen regardless of the current rendering mode. ([66508](https://github.com/WordPress/gutenberg/pull/66508)) +- Hide metaboxes in Zoom Out. ([66886](https://github.com/WordPress/gutenberg/pull/66886)) + +#### Site Editor +- DataViews: Fix 'aria-label' for pattern preview element. ([66601](https://github.com/WordPress/gutenberg/pull/66601)) +- Site Hub: Fixed navigation redirect on mobile devices for classic themes. ([66867](https://github.com/WordPress/gutenberg/pull/66867)) + +#### Media +- Add `x-wav` mime type for wav files in Firefox. ([66850](https://github.com/WordPress/gutenberg/pull/66850)) +- Ensure HEIC files selectable from “Upload” button. ([66292](https://github.com/WordPress/gutenberg/pull/66292)) + +#### Patterns +- Fix uncategorized pattern browsing when pattern has no categories. ([66945](https://github.com/WordPress/gutenberg/pull/66945)) + +#### Interactivity API +- Fix property modification from inherited context two or more levels above. ([66872](https://github.com/WordPress/gutenberg/pull/66872)) + +#### Block API +- Process Block Type: Copy deprecation to a new object instead of mutating when stabilizing supports. ([66849](https://github.com/WordPress/gutenberg/pull/66849)) + +#### Design Tools +- Block Gap: Fix block spacing control for axial gap supported blocks. ([66783](https://github.com/WordPress/gutenberg/pull/66783)) + +#### Document Settings +- Editor: Restore the 'PluginPostStatusInfo' slot position. ([66665](https://github.com/WordPress/gutenberg/pull/66665)) + +#### Templates API +- Fix flash when clicking template name in the editor when a plugin registered template matches a default WP theme template. ([66359](https://github.com/WordPress/gutenberg/pull/66359)) + +#### Block bindings +- Fix unset array key warning in block-bindings.php. ([66337](https://github.com/WordPress/gutenberg/pull/66337)) + + +### Accessibility + +- Fix : Snackbar Notice Inconsistency. ([66405](https://github.com/WordPress/gutenberg/pull/66405)) +- Image: Add `aria-haspopup` prop write mode `more` tools menu items. ([66815](https://github.com/WordPress/gutenberg/pull/66815)) +- Site Icon Focus fix. ([66952](https://github.com/WordPress/gutenberg/pull/66952)) + +#### Components +- Popover: Fix missing label of the headerTitle Close button. ([66813](https://github.com/WordPress/gutenberg/pull/66813)) + +#### Post Editor +- Fix inconsistent sidebars close buttons sizes. ([66756](https://github.com/WordPress/gutenberg/pull/66756)) + +#### Block Library +- Remove unnecessary tooltip from Video block Text tracks button. ([66716](https://github.com/WordPress/gutenberg/pull/66716)) + +#### Block Editor +- Speak 'Block moved up/down' after using keyboard actions to move up/down. ([64966](https://github.com/WordPress/gutenberg/pull/64966)) + +#### Patterns +- Block Patterns List: Fix visual title and tooltip inconsistencies. ([64815](https://github.com/WordPress/gutenberg/pull/64815)) + + +### Performance + +- Inline Commenting: Avoid querying comments on editor load. ([66670](https://github.com/WordPress/gutenberg/pull/66670)) +- Patterns: Receive intermediate responses while unbound request is resolving. ([66713](https://github.com/WordPress/gutenberg/pull/66713)) +- Perf metrics: Update select and other metrics to use non-empty paragraphs. ([66762](https://github.com/WordPress/gutenberg/pull/66762)) +- Site Editor: Preload settings requests. ([66488](https://github.com/WordPress/gutenberg/pull/66488)) +- Site Editor: Speed up load by preloading home and front-page templates. ([66579](https://github.com/WordPress/gutenberg/pull/66579)) +- Site editor: Preload post if needed. ([66631](https://github.com/WordPress/gutenberg/pull/66631)) + +#### Global Styles +- Preload user global styles based on user caps. ([66541](https://github.com/WordPress/gutenberg/pull/66541)) + + +### Experiments + +- Add `isVisible` option to fields within DataForm. ([65826](https://github.com/WordPress/gutenberg/pull/65826)) +- DataViews: Implement `isItemClickable` and `onClickItem` props. ([66365](https://github.com/WordPress/gutenberg/pull/66365)) + +#### DataViews +- Quick Edit - Slug Field: Improve slug preview. ([66559](https://github.com/WordPress/gutenberg/pull/66559)) +- QuickEdit: Add password field data to the pages quick edit. ([66567](https://github.com/WordPress/gutenberg/pull/66567)) + + +### Documentation + +- Add 6.6.2 to Version in WordPress. ([66870](https://github.com/WordPress/gutenberg/pull/66870)) +- Add missing properties for DataViews/DataForm components. ([66749](https://github.com/WordPress/gutenberg/pull/66749)) +- Add section about the Fields API. ([66761](https://github.com/WordPress/gutenberg/pull/66761)) +- Block Bindings: Documentation API reference. ([66251](https://github.com/WordPress/gutenberg/pull/66251)) +- Docs: Include a note about supported licenses in WordPress packages. ([66562](https://github.com/WordPress/gutenberg/pull/66562)) +- Document `filterSortAndPaginate` & `isItemValid` utilities. ([66738](https://github.com/WordPress/gutenberg/pull/66738)) +- Feat: Storybook: Improve component organisation - Navigation Category - Issue #66275. ([66658](https://github.com/WordPress/gutenberg/pull/66658)) +- Feat: Storybook: Improve component organisation - Overlays Category - Issue #66275. ([66657](https://github.com/WordPress/gutenberg/pull/66657)) +- Feat: Storybook: Improve component organisation - Selection & Input Category - Issue #66275. ([66660](https://github.com/WordPress/gutenberg/pull/66660)) +- Feat: Storybook: Improve component organisation - Typography - Issue #66275. ([66633](https://github.com/WordPress/gutenberg/pull/66633)) +- Improve readability of DataViews documentation. ([66766](https://github.com/WordPress/gutenberg/pull/66766)) +- Move documentation for filter operators to proper place. ([66743](https://github.com/WordPress/gutenberg/pull/66743)) +- Reorganize to bootstrap DataForm API section. ([66729](https://github.com/WordPress/gutenberg/pull/66729)) +- Storybook: Improve component organisation - Actions. ([66680](https://github.com/WordPress/gutenberg/pull/66680)) +- Storybook: Log `warning()` when in dev mode. ([66568](https://github.com/WordPress/gutenberg/pull/66568)) +- Update Commands documentation with the existing contexts. ([66860](https://github.com/WordPress/gutenberg/pull/66860)) + + +### Code Quality + +- BlockPatternsList: Use the Async component. ([66744](https://github.com/WordPress/gutenberg/pull/66744)) +- Core Commands: Fix add new post URL assignment. ([66830](https://github.com/WordPress/gutenberg/pull/66830)) +- Inline Commenting: Optimize store selector and misc changes. ([66592](https://github.com/WordPress/gutenberg/pull/66592)) +- Remove unnecessary boolean assignments. ([66857](https://github.com/WordPress/gutenberg/pull/66857)) +- TypeScript: Fix and improve types for private-apis. ([66667](https://github.com/WordPress/gutenberg/pull/66667)) + +#### Block Editor +- Fix 'useSelect' dependencies for the 'RichText' component. ([66964](https://github.com/WordPress/gutenberg/pull/66964)) +- Fix ESLint warning for 'useBlockTypesState' hook. ([66757](https://github.com/WordPress/gutenberg/pull/66757)) +- Fix React Compiler error for 'BlockProps' util component. ([66809](https://github.com/WordPress/gutenberg/pull/66809)) +- Optimize `getVisibleElementBounds` in scrollable cases. ([66546](https://github.com/WordPress/gutenberg/pull/66546)) +- Revert: Fix unable to remove empty blocks on merge (#65262) + alternative. ([66564](https://github.com/WordPress/gutenberg/pull/66564)) +- URLInput: Fix incorrect classname for suggestions. ([66714](https://github.com/WordPress/gutenberg/pull/66714)) + +#### Site Editor +- Avoid using edited entity state in site editor loading hook. ([66924](https://github.com/WordPress/gutenberg/pull/66924)) +- Avoid using edited post selectors in welcome guide. ([66926](https://github.com/WordPress/gutenberg/pull/66926)) +- Edit Site: Refactor to remove usage of edited entity state. ([66922](https://github.com/WordPress/gutenberg/pull/66922)) +- Edit Site: Remove leftover 'priority-queue' dependency. ([66773](https://github.com/WordPress/gutenberg/pull/66773)) +- Remove useEditedEntityRecord hook. ([66955](https://github.com/WordPress/gutenberg/pull/66955)) + +#### Components +- Fix React Compiler error for 'useScrollRectIntoView'. ([66498](https://github.com/WordPress/gutenberg/pull/66498)) +- Panel: Add 40px size prop to Button. ([66589](https://github.com/WordPress/gutenberg/pull/66589)) +- Radio: Deprecate 36px default size. ([66572](https://github.com/WordPress/gutenberg/pull/66572)) +- Snackbar: Use `link` variant for action Button. ([66560](https://github.com/WordPress/gutenberg/pull/66560)) + +#### Data Layer +- Convert the emitter module in data package to TS. ([66669](https://github.com/WordPress/gutenberg/pull/66669)) +- Data: Rename useSelect internals to fix React Compiler violations. ([66807](https://github.com/WordPress/gutenberg/pull/66807)) +- Data: Upgrade Redux to v5.0.1. ([66966](https://github.com/WordPress/gutenberg/pull/66966)) + +#### Post Editor +- ESLint: Fix React Compiler violations in various commands. ([66787](https://github.com/WordPress/gutenberg/pull/66787)) +- Fix TS types for editor package. ([66754](https://github.com/WordPress/gutenberg/pull/66754)) + +#### Zoom Out +- Zoom-out: Move default background to the iframe component. ([66284](https://github.com/WordPress/gutenberg/pull/66284)) + +#### Design Tools +- Typography: Stabilize typography block supports within block processing. ([63401](https://github.com/WordPress/gutenberg/pull/63401)) + + +### Tools + +#### Testing +- Media: Check for `wav` mime type using isset. ([66947](https://github.com/WordPress/gutenberg/pull/66947)) + +#### Build Tooling +- Enforce the same order of fields in `package.json` files. ([66239](https://github.com/WordPress/gutenberg/pull/66239)) +- Introduce React Scanner for component usage stats. ([65463](https://github.com/WordPress/gutenberg/pull/65463)) + + +### Various + +- Style engine: Wrap array_merge in conditionals to prevent unnecessary merging. ([66661](https://github.com/WordPress/gutenberg/pull/66661)) + +#### Block Library +- Update placeholder text for blocks that support drag and drop. ([66842](https://github.com/WordPress/gutenberg/pull/66842)) +- update: Add Media to Add media in cover block. ([66835](https://github.com/WordPress/gutenberg/pull/66835)) + + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @benharri: Fix unset array key warning in block-bindings.php. ([66337](https://github.com/WordPress/gutenberg/pull/66337)) +- @benniledl: Add 6.6.2 to Version in WordPress. ([66870](https://github.com/WordPress/gutenberg/pull/66870)) +- @Infinite-Null: Media & Text: Set `.wp-block-media-text__media a` display to block. ([66915](https://github.com/WordPress/gutenberg/pull/66915)) +- @karthick-murugan: Site Icon Focus fix. ([66952](https://github.com/WordPress/gutenberg/pull/66952)) +- @rinkalpagdar: Post Content: Add border and spacing support. ([66366](https://github.com/WordPress/gutenberg/pull/66366)) +- @yogeshbhutkar: Site Hub: Fixed navigation redirect on mobile devices for classic themes. ([66867](https://github.com/WordPress/gutenberg/pull/66867)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @adamsilverstein @afercia @Aljullu @amitraj2203 @andrewserong @benharri @benniledl @carolinan @cbravobernal @DAreRodz @dcalhoun @ellatrix @fabiankaegy @gigitux @gziolo @hbhalodia @Infinite-Null @jasmussen @jorgefilipecosta @jsnajdr @juanfra @karthick-murugan @kevin940726 @louwie17 @Mamaduka @manzoorwanijk @matiasbenedetto @mikachan @mirka @n2erjo00 @ntsekouras @oandregal @ramonjd @renatho @rinkalpagdar @Soean @stokesman @swissspidy @t-hamano @tellthemachines @tyxla @up1512001 @Vrishabhsk @yogeshbhutkar @youknowriad + + + + = 19.8.0-rc.1 = From b20ac3764a2774be8a34d9160950b283478ce2c5 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Wed, 27 Nov 2024 13:31:48 -0800 Subject: [PATCH 1740/1908] =?UTF-8?q?Make=20sure=20Document=20Bar=20doesn?= =?UTF-8?q?=E2=80=99t=20go=20missing=20(#67322)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: draganescu <andraganescu@git.wordpress.org> --- packages/editor/src/components/header/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index 2a5629b080caf8..51c341f2c1bd16 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -97,8 +97,10 @@ function Header( { useState( true ); const hasCenter = - ( ! hasBlockSelection || isBlockToolsCollapsed ) && - ! isTooNarrowForDocumentBar; + ! isTooNarrowForDocumentBar && + ( ! hasFixedToolbar || + ( hasFixedToolbar && + ( ! hasBlockSelection || isBlockToolsCollapsed ) ) ); const hasBackButton = useHasBackButton(); /* * The edit-post-header classname is only kept for backward compatability From fedbea36cb202c3998b61cb4c5580ebcfe5cd110 Mon Sep 17 00:00:00 2001 From: mimi <mimitips@gmail.com> Date: Thu, 28 Nov 2024 08:09:01 +0900 Subject: [PATCH 1741/1908] Storybook: Add stories for AlignmentToolbar and AlignmentControl components (#67046) * Add stories for AlignmentToolbar and AlignmentControl components * Remove unneccesery args * package.json: remove packageManager entry * Rename the story file and remove unnecessary args from AlignmentControl story * Update packages/block-editor/src/components/alignment-control/stories/aliginment-toolbar.story.js Co-authored-by: Lena Morita <lena@jaguchi.com> * Add render function --------- Co-authored-by: miminari <mimitips@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../stories/aliginment-toolbar.story.js | 47 +++++++++++++++++ .../alignment-control/stories/index.story.js | 51 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 packages/block-editor/src/components/alignment-control/stories/aliginment-toolbar.story.js create mode 100644 packages/block-editor/src/components/alignment-control/stories/index.story.js diff --git a/packages/block-editor/src/components/alignment-control/stories/aliginment-toolbar.story.js b/packages/block-editor/src/components/alignment-control/stories/aliginment-toolbar.story.js new file mode 100644 index 00000000000000..f2191220d6bb4c --- /dev/null +++ b/packages/block-editor/src/components/alignment-control/stories/aliginment-toolbar.story.js @@ -0,0 +1,47 @@ +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { AlignmentToolbar } from '..'; + +/** + * The `AlignmentToolbar` component renders a dropdown menu that displays alignment options for the selected block in `Toolbar`. + */ +const meta = { + title: 'BlockEditor/AlignmentToolbar', + component: AlignmentToolbar, + argTypes: { + value: { + control: { type: null }, + defaultValue: 'undefined', + description: 'The current value of the alignment setting.', + }, + onChange: { + action: 'onChange', + control: { type: null }, + description: + "A callback function invoked when the toolbar's alignment value is changed via an interaction with any of the toolbar's buttons. Called with the new alignment value (ie: `left`, `center`, `right`, `undefined`) as the only argument.", + }, + }, +}; +export default meta; + +export const Default = { + render: function Template( { onChange, ...args } ) { + const [ value, setValue ] = useState(); + return ( + <AlignmentToolbar + { ...args } + onChange={ ( ...changeArgs ) => { + onChange( ...changeArgs ); + setValue( ...changeArgs ); + } } + value={ value } + /> + ); + }, +}; diff --git a/packages/block-editor/src/components/alignment-control/stories/index.story.js b/packages/block-editor/src/components/alignment-control/stories/index.story.js new file mode 100644 index 00000000000000..85c92f7e0665a4 --- /dev/null +++ b/packages/block-editor/src/components/alignment-control/stories/index.story.js @@ -0,0 +1,51 @@ +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { AlignmentControl } from '../'; + +/** + * The `AlignmentControl` component renders a dropdown menu that displays alignment options for the selected block. + * + * This component is mostly used for blocks that display text, such as Heading, Paragraph, Post Author, Post Comments, Verse, Quote, Post Title, etc... And the available alignment options are `left`, `center` or `right` alignment. + * + * If you want to use the alignment control in a toolbar, you should use the `AlignmentToolbar` component instead. + */ +const meta = { + title: 'BlockEditor/AlignmentControl', + component: AlignmentControl, + argTypes: { + value: { + control: { type: null }, + defaultValue: 'undefined', + description: 'The current value of the alignment setting.', + }, + onChange: { + action: 'onChange', + control: { type: null }, + description: + "A callback function invoked when the toolbar's alignment value is changed via an interaction with any of the toolbar's buttons. Called with the new alignment value (ie: `left`, `center`, `right`, `undefined`) as the only argument.", + }, + }, +}; +export default meta; + +export const Default = { + render: function Template( { onChange, ...args } ) { + const [ value, setValue ] = useState(); + return ( + <AlignmentControl + { ...args } + onChange={ ( ...changeArgs ) => { + onChange( ...changeArgs ); + setValue( ...changeArgs ); + } } + value={ value } + /> + ); + }, +}; From 756cfe0ec230b8f2e7552aa1622be77ed56b6e0f Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 28 Nov 2024 12:51:04 +1100 Subject: [PATCH 1742/1908] Query block: move patterns modal to dropdown on block toolbar (#66993) * Reinstate modal. * Delete unused component * showTitlesAsTooltip prop * Remove redundant style-edit route * Revert slot for navigation mode. * First attempt at moving the designs in a dropdone popover. * Tweaking widths. Ensure expansion on mobile Unlinked contributors: jarekmorawski. Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> --- .../block-library/src/query/edit/index.js | 2 +- ...election-modal.js => pattern-selection.js} | 86 ++++++++++++------- .../src/query/edit/query-content.js | 14 +-- .../src/query/edit/query-placeholder.js | 19 ++-- .../src/query/edit/query-toolbar.js | 55 ++++++++---- packages/block-library/src/query/editor.scss | 30 +++++++ 6 files changed, 131 insertions(+), 75 deletions(-) rename packages/block-library/src/query/edit/{pattern-selection-modal.js => pattern-selection.js} (67%) diff --git a/packages/block-library/src/query/edit/index.js b/packages/block-library/src/query/edit/index.js index 9a54b5976fe4bc..60fc2ebd6170b3 100644 --- a/packages/block-library/src/query/edit/index.js +++ b/packages/block-library/src/query/edit/index.js @@ -10,7 +10,7 @@ import { store as blockEditorStore } from '@wordpress/block-editor'; */ import QueryContent from './query-content'; import QueryPlaceholder from './query-placeholder'; -import PatternSelectionModal from './pattern-selection-modal'; +import { PatternSelectionModal } from './pattern-selection'; const QueryEdit = ( props ) => { const { clientId, attributes } = props; diff --git a/packages/block-library/src/query/edit/pattern-selection-modal.js b/packages/block-library/src/query/edit/pattern-selection.js similarity index 67% rename from packages/block-library/src/query/edit/pattern-selection-modal.js rename to packages/block-library/src/query/edit/pattern-selection.js index e4cc8d0c851c23..0c5d95d15206f2 100644 --- a/packages/block-library/src/query/edit/pattern-selection-modal.js +++ b/packages/block-library/src/query/edit/pattern-selection.js @@ -21,48 +21,67 @@ import { } from '../utils'; import { searchPatterns } from '../../utils/search-patterns'; -export default function PatternSelectionModal( { +export function PatternSelectionModal( { clientId, attributes, setIsPatternSelectionModalOpen, +} ) { + return ( + <Modal + overlayClassName="block-library-query-pattern__selection-modal" + title={ __( 'Choose a pattern' ) } + onRequestClose={ () => setIsPatternSelectionModalOpen( false ) } + isFullScreen + > + <PatternSelection clientId={ clientId } attributes={ attributes } /> + </Modal> + ); +} + +export function useBlockPatterns( clientId, attributes ) { + const blockNameForPatterns = useBlockNameForPatterns( + clientId, + attributes + ); + return usePatterns( clientId, blockNameForPatterns ); +} + +export default function PatternSelection( { + clientId, + attributes, + showTitlesAsTooltip = false, + showSearch = true, } ) { const [ searchValue, setSearchValue ] = useState( '' ); const { replaceBlock, selectBlock } = useDispatch( blockEditorStore ); - const onBlockPatternSelect = ( pattern, blocks ) => { - const { newBlocks, queryClientIds } = getTransformedBlocksFromPattern( - blocks, - attributes - ); - replaceBlock( clientId, newBlocks ); - if ( queryClientIds[ 0 ] ) { - selectBlock( queryClientIds[ 0 ] ); - } - }; - // When we preview Query Loop blocks we should prefer the current - // block's postType, which is passed through block context. + const blockPatterns = useBlockPatterns( clientId, attributes ); + /* + * When we preview Query Loop blocks we should prefer the current + * block's postType, which is passed through block context. + */ const blockPreviewContext = useMemo( () => ( { previewPostType: attributes.query.postType, } ), [ attributes.query.postType ] ); - const blockNameForPatterns = useBlockNameForPatterns( - clientId, - attributes - ); - const blockPatterns = usePatterns( clientId, blockNameForPatterns ); const filteredBlockPatterns = useMemo( () => { return searchPatterns( blockPatterns, searchValue ); }, [ blockPatterns, searchValue ] ); + const onBlockPatternSelect = ( pattern, blocks ) => { + const { newBlocks, queryClientIds } = getTransformedBlocksFromPattern( + blocks, + attributes + ); + replaceBlock( clientId, newBlocks ); + if ( queryClientIds[ 0 ] ) { + selectBlock( queryClientIds[ 0 ] ); + } + }; return ( - <Modal - overlayClassName="block-library-query-pattern__selection-modal" - title={ __( 'Choose a pattern' ) } - onRequestClose={ () => setIsPatternSelectionModalOpen( false ) } - isFullScreen - > - <div className="block-library-query-pattern__selection-content"> + <div className="block-library-query-pattern__selection-content"> + { showSearch && ( <div className="block-library-query-pattern__selection-search"> <SearchControl __nextHasNoMarginBottom @@ -72,13 +91,14 @@ export default function PatternSelectionModal( { placeholder={ __( 'Search' ) } /> </div> - <BlockContextProvider value={ blockPreviewContext }> - <BlockPatternsList - blockPatterns={ filteredBlockPatterns } - onClickPattern={ onBlockPatternSelect } - /> - </BlockContextProvider> - </div> - </Modal> + ) } + <BlockContextProvider value={ blockPreviewContext }> + <BlockPatternsList + blockPatterns={ filteredBlockPatterns } + onClickPattern={ onBlockPatternSelect } + showTitlesAsTooltip={ showTitlesAsTooltip } + /> + </BlockContextProvider> + </div> ); } diff --git a/packages/block-library/src/query/edit/query-content.js b/packages/block-library/src/query/edit/query-content.js index 17eea9337823c5..a608f20bbeb001 100644 --- a/packages/block-library/src/query/edit/query-content.js +++ b/packages/block-library/src/query/edit/query-content.js @@ -19,10 +19,10 @@ import { store as coreStore } from '@wordpress/core-data'; * Internal dependencies */ import EnhancedPaginationControl from './inspector-controls/enhanced-pagination-control'; -import QueryToolbar from './query-toolbar'; import QueryInspectorControls from './inspector-controls'; import EnhancedPaginationModal from './enhanced-pagination-modal'; import { getQueryContextFromTemplate } from '../utils'; +import QueryToolbar from './query-toolbar'; const DEFAULTS_POSTS_PER_PAGE = 3; @@ -30,10 +30,9 @@ const TEMPLATE = [ [ 'core/post-template' ] ]; export default function QueryContent( { attributes, setAttributes, - openPatternSelectionModal, - name, clientId, context, + name, } ) { const { queryId, @@ -154,6 +153,7 @@ export default function QueryContent( { /> <InspectorControls> <QueryInspectorControls + name={ name } attributes={ attributes } setQuery={ updateQuery } setDisplayLayout={ updateDisplayLayout } @@ -163,13 +163,7 @@ export default function QueryContent( { /> </InspectorControls> <BlockControls> - <QueryToolbar - name={ name } - clientId={ clientId } - attributes={ attributes } - setQuery={ updateQuery } - openPatternSelectionModal={ openPatternSelectionModal } - /> + <QueryToolbar attributes={ attributes } clientId={ clientId } /> </BlockControls> <InspectorControls group="advanced"> <SelectControl diff --git a/packages/block-library/src/query/edit/query-placeholder.js b/packages/block-library/src/query/edit/query-placeholder.js index 631eb64de07157..c3a01a0447f55e 100644 --- a/packages/block-library/src/query/edit/query-placeholder.js +++ b/packages/block-library/src/query/edit/query-placeholder.js @@ -18,7 +18,8 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import { useScopedBlockVariations, useBlockNameForPatterns } from '../utils'; +import { useScopedBlockVariations } from '../utils'; +import { useBlockPatterns } from './pattern-selection'; export default function QueryPlaceholder( { attributes, @@ -28,31 +29,21 @@ export default function QueryPlaceholder( { } ) { const [ isStartingBlank, setIsStartingBlank ] = useState( false ); const blockProps = useBlockProps(); - const blockNameForPatterns = useBlockNameForPatterns( - clientId, - attributes - ); - const { blockType, activeBlockVariation, hasPatterns } = useSelect( + const { blockType, activeBlockVariation } = useSelect( ( select ) => { const { getActiveBlockVariation, getBlockType } = select( blocksStore ); - const { getBlockRootClientId, getPatternsByBlockTypes } = - select( blockEditorStore ); - const rootClientId = getBlockRootClientId( clientId ); return { blockType: getBlockType( name ), activeBlockVariation: getActiveBlockVariation( name, attributes ), - hasPatterns: !! getPatternsByBlockTypes( - blockNameForPatterns, - rootClientId - ).length, }; }, - [ name, blockNameForPatterns, clientId, attributes ] + [ name, attributes ] ); + const hasPatterns = !! useBlockPatterns( clientId, attributes ).length; const icon = activeBlockVariation?.icon?.src || activeBlockVariation?.icon || diff --git a/packages/block-library/src/query/edit/query-toolbar.js b/packages/block-library/src/query/edit/query-toolbar.js index cc2d62a54d529f..25e087ebe1559c 100644 --- a/packages/block-library/src/query/edit/query-toolbar.js +++ b/packages/block-library/src/query/edit/query-toolbar.js @@ -1,30 +1,51 @@ /** * WordPress dependencies */ -import { ToolbarGroup, ToolbarButton } from '@wordpress/components'; +import { + ToolbarGroup, + ToolbarButton, + Dropdown, + __experimentalDropdownContentWrapper as DropdownContentWrapper, +} from '@wordpress/components'; import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import { usePatterns } from '../utils'; +import PatternSelection, { useBlockPatterns } from './pattern-selection'; -export default function QueryToolbar( { - openPatternSelectionModal, - name, - clientId, -} ) { - const hasPatterns = !! usePatterns( clientId, name ).length; +export default function QueryToolbar( { clientId, attributes } ) { + const hasPatterns = useBlockPatterns( clientId, attributes ).length; + if ( ! hasPatterns ) { + return null; + } return ( - <> - { hasPatterns && ( - <ToolbarGroup className="wp-block-template-part__block-control-group"> - <ToolbarButton onClick={ openPatternSelectionModal }> - { __( 'Replace' ) } - </ToolbarButton> - </ToolbarGroup> - ) } - </> + <ToolbarGroup className="wp-block-template-part__block-control-group"> + <DropdownContentWrapper> + <Dropdown + contentClassName="block-editor-block-settings-menu__popover" + focusOnMount="firstElement" + expandOnMobile + renderToggle={ ( { isOpen, onToggle } ) => ( + <ToolbarButton + aria-haspopup="true" + aria-expanded={ isOpen } + onClick={ onToggle } + > + { __( 'Change design' ) } + </ToolbarButton> + ) } + renderContent={ () => ( + <PatternSelection + clientId={ clientId } + attributes={ attributes } + showSearch={ false } + showTitlesAsTooltip + /> + ) } + /> + </DropdownContentWrapper> + </ToolbarGroup> ); } diff --git a/packages/block-library/src/query/editor.scss b/packages/block-library/src/query/editor.scss index da863bff0b5da6..5bf0db81870403 100644 --- a/packages/block-library/src/query/editor.scss +++ b/packages/block-library/src/query/editor.scss @@ -45,6 +45,12 @@ } } +.block-library-query-toolspanel__design { + .block-library-query-pattern__selection-content { + margin-top: $grid-unit-10; + } +} + .wp-block-query__enhanced-pagination-modal { @include break-small() { max-width: $break-mobile; @@ -54,3 +60,27 @@ .wp-block-query__enhanced-pagination-notice { margin: 0; } + +.block-editor-block-settings-menu__popover { + &.is-expanded { + overflow-y: scroll; + } + .block-library-query-pattern__selection-content { + height: 100%; + } + .block-editor-block-patterns-list { + display: grid; + grid-template-columns: 1fr; + @include break-small() { + grid-template-columns: 1fr 1fr; + } + grid-gap: $grid-unit-15; + min-width: $break-zoomed-in; + @include break-small() { + min-width: $break-mobile; + } + } + .block-editor-block-patterns-list__list-item { + margin-bottom: 0; + } +} From 9a9af210f36968873c05457d60b166f615dc07ff Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Thu, 28 Nov 2024 10:53:31 +0800 Subject: [PATCH 1743/1908] Fix synced pattern editing in write mode and refactor block editing mode to reducer (#67026) * Add higher order reducer for pattern block editing modes. - Remove the prev. React effect for managing pattern block editing modes - Implement higher order reducer in the block editor store ... it: - Tracks the clientIds of pattern blocks. - Uses the pattern block clientIds to manage block editing modes for pattern blocks and their inner blocks. - Updates both on any actions that change block lists. * Add higher order reducer for block editing modes while section editing * Handle RESET_ZOOM_LEVEL action * Bug fixes * Avoid mutating `state` in new higher order reducers * Try moving synced pattern client ids into a separate reducer * Revert "Try moving synced pattern client ids into a separate reducer" This reverts commit e1d6ca494e6f830c429aa5649327b4c26d77a974. It doesn't really work, since reducer won't have access to `state.blocks.tree`. * Try amalgamating the different derived block editing modes * Fixes * Fix synced patterns in write mode, unbound content blocks being editable * Also update derived block editing mode on `REPLACE_INNER_BLOCKS * Fix descending through controlled inner blocks * Fix nested pattern handling - always process synced patterns in the reducer. Add special handling for only adding pattern block itself as content only when not in zoomed out or nav mode * Zoomed out fixes - content should never be editable in zoomed out, even synced pattern overrides or when write mode is active * Docs * Add end to end test * Remove navigation mode selector tests * Fix partial mocking of blocks package * Add test for isContentBlock * Add unit tests * Remove defaultBlockEditingMode concept * Handle patterns that are outside sections in nav mode * Remove comment * Refactor to handle tree subsections * Optimize each individual action * Fixes and refinements * Comments and renamings * Remove test mocking - else test chokes trying to unlock privateApis * Rework reducer unit tests and add more cases * Add more tests * Handle when the SET_HAS_CONTROLLED_INNER_BLOCKS block has been removed from the state * Inline editing mode calculation for individual blocks * Calculate both the regular and nav mode derived block editing modes at the same time * Update getEnabledClientIdsTree dependencies * Fix tests * Update more tests * Enable write mode experiment for e2e pattern overrides block editing mode tests ---- Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/components/block-title/test/index.js | 2 + .../src/store/private-selectors.js | 12 +- packages/block-editor/src/store/reducer.js | 641 ++++++++++++- packages/block-editor/src/store/selectors.js | 90 +- .../src/store/test/private-selectors.js | 1 + .../block-editor/src/store/test/reducer.js | 851 ++++++++++++++++++ .../block-editor/src/store/test/selectors.js | 114 +-- packages/block-library/src/block/edit.js | 57 +- .../src/missing/test/edit.native.js | 1 - packages/blocks/README.md | 4 + packages/blocks/src/api/index.js | 9 + packages/blocks/src/api/test/utils.js | 38 + packages/blocks/src/api/utils.js | 12 + .../editor/various/pattern-overrides.spec.js | 416 ++++++--- 14 files changed, 1908 insertions(+), 340 deletions(-) diff --git a/packages/block-editor/src/components/block-title/test/index.js b/packages/block-editor/src/components/block-title/test/index.js index 8a4d3c2f52fd7e..fc6af61bae9e7c 100644 --- a/packages/block-editor/src/components/block-title/test/index.js +++ b/packages/block-editor/src/components/block-title/test/index.js @@ -31,7 +31,9 @@ const blockLabelMap = { }; jest.mock( '@wordpress/blocks', () => { + const actualImplementation = jest.requireActual( '@wordpress/blocks' ); return { + ...actualImplementation, isReusableBlock( { title } ) { return title === 'Reusable Block'; }, diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 5a5ce7a801594b..9779ae1300fb57 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -109,16 +109,16 @@ function getEnabledClientIdsTreeUnmemoized( state, rootClientId ) { * * @return {Object[]} Tree of block objects with only clientID and innerBlocks set. */ -export const getEnabledClientIdsTree = createRegistrySelector( ( select ) => - createSelector( getEnabledClientIdsTreeUnmemoized, ( state ) => [ +export const getEnabledClientIdsTree = createSelector( + getEnabledClientIdsTreeUnmemoized, + ( state ) => [ state.blocks.order, + state.derivedBlockEditingModes, + state.derivedNavModeBlockEditingModes, state.blockEditingModes, state.settings.templateLock, state.blockListSettings, - select( STORE_NAME ).__unstableGetEditorMode( state ), - state.zoomLevel, - getSectionRootClientId( state ), - ] ) + ] ); /** diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 2f0fa70d616fd9..1e09ec98f005ab 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -9,12 +9,20 @@ import fastDeepEqual from 'fast-deep-equal/es6'; import { pipe } from '@wordpress/compose'; import { combineReducers, select } from '@wordpress/data'; import deprecated from '@wordpress/deprecated'; -import { store as blocksStore } from '@wordpress/blocks'; +import { + store as blocksStore, + privateApis as blocksPrivateApis, +} from '@wordpress/blocks'; + /** * Internal dependencies */ import { PREFERENCES_DEFAULTS, SETTINGS_DEFAULTS } from './defaults'; import { insertAt, moveTo } from './array'; +import { sectionRootClientIdKey } from './private-keys'; +import { unlock } from '../lock-unlock'; + +const { isContentBlock } = unlock( blocksPrivateApis ); const identity = ( x ) => x; @@ -2131,6 +2139,632 @@ const combinedReducers = combineReducers( { zoomLevel, } ); +/** + * Retrieves a block's tree structure, handling both controlled and uncontrolled inner blocks. + * + * @param {Object} state The current state object. + * @param {string} clientId The client ID of the block to retrieve. + * + * @return {Object|undefined} The block tree object, or undefined if not found. For controlled blocks, + * returns a merged tree with controlled inner blocks. + */ +function getBlockTreeBlock( state, clientId ) { + if ( clientId === '' ) { + const rootBlock = state.blocks.tree.get( clientId ); + + if ( ! rootBlock ) { + return; + } + + // Patch the root block to have a clientId property. + // TODO - consider updating the blocks reducer so that the root block has this property. + return { + clientId: '', + ...rootBlock, + }; + } + + if ( ! state.blocks.controlledInnerBlocks[ clientId ] ) { + return state.blocks.tree.get( clientId ); + } + + const controlledTree = state.blocks.tree.get( `controlled||${ clientId }` ); + const regularTree = state.blocks.tree.get( clientId ); + + return { + ...regularTree, + innerBlocks: controlledTree?.innerBlocks, + }; +} + +/** + * Recursively traverses through a block tree of a given block and executes a callback for each block. + * + * @param {Object} state The store state. + * @param {string} clientId The clientId of the block to start traversing from. + * @param {Function} callback Function to execute for each block encountered during traversal. + * The callback receives the current block as its argument. + */ +function traverseBlockTree( state, clientId, callback ) { + const parentTree = getBlockTreeBlock( state, clientId ); + if ( ! parentTree ) { + return; + } + + callback( parentTree ); + + if ( ! parentTree?.innerBlocks?.length ) { + return; + } + + for ( const block of parentTree?.innerBlocks ) { + traverseBlockTree( state, block.clientId, callback ); + } +} + +/** + * Checks if a block has a parent in a list of client IDs, and if so returns the client ID of the parent. + * + * @param {Object} state The current state object. + * @param {string} clientId The client ID of the block to search the parents of. + * @param {Array} clientIds The client IDs of the blocks to check. + * + * @return {string|undefined} The client ID of the parent block if found, undefined otherwise. + */ +function findParentInClientIdsList( state, clientId, clientIds ) { + let parent = state.blocks.parents.get( clientId ); + while ( parent ) { + if ( clientIds.includes( parent ) ) { + return parent; + } + parent = state.blocks.parents.get( parent ); + } +} + +/** + * Checks if a block has any bindings in its metadata attributes. + * + * @param {Object} block The block object to check for bindings. + * @return {boolean} True if the block has bindings, false otherwise. + */ +function hasBindings( block ) { + return ( + block?.attributes?.metadata?.bindings && + Object.keys( block?.attributes?.metadata?.bindings ).length + ); +} + +/** + * Computes and returns derived block editing modes for a given block tree. + * + * This function calculates the editing modes for each block in the tree, taking into account + * various factors such as zoom level, navigation mode, sections, and synced patterns. + * + * @param {Object} state The current state object. + * @param {boolean} isNavMode Whether the navigation mode is active. + * @param {string} treeClientId The client ID of the root block for the tree. Defaults to an empty string. + * @return {Map} A Map containing the derived block editing modes, keyed by block client ID. + */ +function getDerivedBlockEditingModesForTree( + state, + isNavMode = false, + treeClientId = '' +) { + const isZoomedOut = + state?.zoomLevel < 100 || state?.zoomLevel === 'auto-scaled'; + const derivedBlockEditingModes = new Map(); + + // When there are sections, the majority of blocks are disabled, + // so the default block editing mode is set to disabled. + const sectionRootClientId = state.settings?.[ sectionRootClientIdKey ]; + const sectionClientIds = state.blocks.order.get( sectionRootClientId ); + const syncedPatternClientIds = Object.keys( + state.blocks.controlledInnerBlocks + ).filter( + ( clientId ) => + state.blocks.byClientId?.get( clientId )?.name === 'core/block' + ); + + traverseBlockTree( state, treeClientId, ( block ) => { + const { clientId, name: blockName } = block; + if ( isZoomedOut || isNavMode ) { + // If the root block is the section root set its editing mode to contentOnly. + if ( clientId === sectionRootClientId ) { + derivedBlockEditingModes.set( clientId, 'contentOnly' ); + return; + } + + // There are no sections, so everything else is disabled. + if ( ! sectionClientIds?.length ) { + derivedBlockEditingModes.set( clientId, 'disabled' ); + return; + } + + if ( sectionClientIds.includes( clientId ) ) { + derivedBlockEditingModes.set( clientId, 'contentOnly' ); + return; + } + + // If zoomed out, all blocks that aren't sections or the section root are + // disabled. + // If the tree root is not in a section, set its editing mode to disabled. + if ( + isZoomedOut || + ! findParentInClientIdsList( state, clientId, sectionClientIds ) + ) { + derivedBlockEditingModes.set( clientId, 'disabled' ); + return; + } + + // Handle synced pattern content so the inner blocks of a synced pattern are + // properly disabled. + if ( syncedPatternClientIds.length ) { + const parentPatternClientId = findParentInClientIdsList( + state, + clientId, + syncedPatternClientIds + ); + + if ( parentPatternClientId ) { + // This is a pattern nested in another pattern, it should be disabled. + if ( + findParentInClientIdsList( + state, + parentPatternClientId, + syncedPatternClientIds + ) + ) { + derivedBlockEditingModes.set( clientId, 'disabled' ); + return; + } + + if ( hasBindings( block ) ) { + derivedBlockEditingModes.set( clientId, 'contentOnly' ); + return; + } + + // Synced pattern content without a binding isn't editable + // from the instance, the user has to edit the pattern source, + // so return 'disabled'. + derivedBlockEditingModes.set( clientId, 'disabled' ); + return; + } + } + + if ( blockName && isContentBlock( blockName ) ) { + derivedBlockEditingModes.set( clientId, 'contentOnly' ); + return; + } + + derivedBlockEditingModes.set( clientId, 'disabled' ); + return; + } + + if ( syncedPatternClientIds.length ) { + // Synced pattern blocks (core/block). + if ( syncedPatternClientIds.includes( clientId ) ) { + // This is a pattern nested in another pattern, it should be disabled. + if ( + findParentInClientIdsList( + state, + clientId, + syncedPatternClientIds + ) + ) { + derivedBlockEditingModes.set( clientId, 'disabled' ); + return; + } + + derivedBlockEditingModes.set( clientId, 'contentOnly' ); + return; + } + + // Inner blocks of synced patterns. + const parentPatternClientId = findParentInClientIdsList( + state, + clientId, + syncedPatternClientIds + ); + if ( parentPatternClientId ) { + // This is a pattern nested in another pattern, it should be disabled. + if ( + findParentInClientIdsList( + state, + parentPatternClientId, + syncedPatternClientIds + ) + ) { + derivedBlockEditingModes.set( clientId, 'disabled' ); + return; + } + + if ( hasBindings( block ) ) { + derivedBlockEditingModes.set( clientId, 'contentOnly' ); + return; + } + + // Synced pattern content without a binding isn't editable + // from the instance, the user has to edit the pattern source, + // so return 'disabled'. + derivedBlockEditingModes.set( clientId, 'disabled' ); + } + } + } ); + + return derivedBlockEditingModes; +} + +/** + * Updates the derived block editing modes based on added and removed blocks. + * + * This function handles the updating of block editing modes when blocks are added, + * removed, or moved within the editor. + * + * It only returns a value when modifications are made to the block editing modes. + * + * @param {Object} options The options for updating derived block editing modes. + * @param {Object} options.prevState The previous state object. + * @param {Object} options.nextState The next state object. + * @param {Array} [options.addedBlocks] An array of blocks that were added. + * @param {Array} [options.removedClientIds] An array of client IDs of blocks that were removed. + * @param {boolean} [options.isNavMode] Whether the navigation mode is active. + * @return {Map|undefined} The updated derived block editing modes, or undefined if no changes were made. + */ +function getDerivedBlockEditingModesUpdates( { + prevState, + nextState, + addedBlocks, + removedClientIds, + isNavMode = false, +} ) { + const prevDerivedBlockEditingModes = isNavMode + ? prevState.derivedNavModeBlockEditingModes + : prevState.derivedBlockEditingModes; + let nextDerivedBlockEditingModes; + + // Perform removals before additions to handle cases like the `MOVE_BLOCKS_TO_POSITION` action. + // That action removes a set of clientIds, but adds the same blocks back in a different location. + // If removals were performed after additions, those moved clientIds would be removed incorrectly. + removedClientIds?.forEach( ( clientId ) => { + // The actions only receive parent block IDs for removal. + // Recurse through the block tree to ensure all blocks are removed. + // Specifically use the previous state, before the blocks were removed. + traverseBlockTree( prevState, clientId, ( block ) => { + if ( prevDerivedBlockEditingModes.has( block.clientId ) ) { + if ( ! nextDerivedBlockEditingModes ) { + nextDerivedBlockEditingModes = new Map( + prevDerivedBlockEditingModes + ); + } + nextDerivedBlockEditingModes.delete( block.clientId ); + } + } ); + } ); + + addedBlocks?.forEach( ( addedBlock ) => { + traverseBlockTree( nextState, addedBlock.clientId, ( block ) => { + const updates = getDerivedBlockEditingModesForTree( + nextState, + isNavMode, + block.clientId + ); + + if ( updates.size ) { + if ( ! nextDerivedBlockEditingModes ) { + nextDerivedBlockEditingModes = new Map( [ + ...( prevDerivedBlockEditingModes?.size + ? prevDerivedBlockEditingModes + : [] ), + ...updates, + ] ); + } else { + nextDerivedBlockEditingModes = new Map( [ + ...( nextDerivedBlockEditingModes?.size + ? nextDerivedBlockEditingModes + : [] ), + ...updates, + ] ); + } + } + } ); + } ); + + return nextDerivedBlockEditingModes; +} + +/** + * Higher-order reducer that adds derived block editing modes to the state. + * + * This function wraps a reducer and enhances it to handle actions that affect + * block editing modes. It updates the derivedBlockEditingModes in the state + * based on various actions such as adding, removing, or moving blocks, or changing + * the editor mode. + * + * @param {Function} reducer The original reducer function to be wrapped. + * @return {Function} A new reducer function that includes derived block editing modes handling. + */ +export function withDerivedBlockEditingModes( reducer ) { + return ( state, action ) => { + const nextState = reducer( state, action ); + + // An exception is needed here to still recompute the block editing modes when + // the editor mode changes since the editor mode isn't stored within the + // block editor state and changing it won't trigger an altered new state. + if ( action.type !== 'SET_EDITOR_MODE' && nextState === state ) { + return state; + } + + switch ( action.type ) { + case 'REMOVE_BLOCKS': { + const nextDerivedBlockEditingModes = + getDerivedBlockEditingModesUpdates( { + prevState: state, + nextState, + removedClientIds: action.clientIds, + isNavMode: false, + } ); + const nextDerivedNavModeBlockEditingModes = + getDerivedBlockEditingModesUpdates( { + prevState: state, + nextState, + removedClientIds: action.clientIds, + isNavMode: true, + } ); + + if ( + nextDerivedBlockEditingModes || + nextDerivedNavModeBlockEditingModes + ) { + return { + ...nextState, + derivedBlockEditingModes: + nextDerivedBlockEditingModes ?? + state.derivedBlockEditingModes, + derivedNavModeBlockEditingModes: + nextDerivedNavModeBlockEditingModes ?? + state.derivedNavModeBlockEditingModes, + }; + } + break; + } + case 'RECEIVE_BLOCKS': + case 'INSERT_BLOCKS': { + const nextDerivedBlockEditingModes = + getDerivedBlockEditingModesUpdates( { + prevState: state, + nextState, + addedBlocks: action.blocks, + isNavMode: false, + } ); + const nextDerivedNavModeBlockEditingModes = + getDerivedBlockEditingModesUpdates( { + prevState: state, + nextState, + addedBlocks: action.blocks, + isNavMode: true, + } ); + + if ( + nextDerivedBlockEditingModes || + nextDerivedNavModeBlockEditingModes + ) { + return { + ...nextState, + derivedBlockEditingModes: + nextDerivedBlockEditingModes ?? + state.derivedBlockEditingModes, + derivedNavModeBlockEditingModes: + nextDerivedNavModeBlockEditingModes ?? + state.derivedNavModeBlockEditingModes, + }; + } + break; + } + case 'SET_HAS_CONTROLLED_INNER_BLOCKS': { + const updatedBlock = nextState.blocks.tree.get( + action.clientId + ); + // The block might have been removed. + if ( ! updatedBlock ) { + break; + } + + const nextDerivedBlockEditingModes = + getDerivedBlockEditingModesUpdates( { + prevState: state, + nextState, + addedBlocks: [ updatedBlock ], + isNavMode: false, + } ); + const nextDerivedNavModeBlockEditingModes = + getDerivedBlockEditingModesUpdates( { + prevState: state, + nextState, + addedBlocks: [ updatedBlock ], + isNavMode: true, + } ); + + if ( + nextDerivedBlockEditingModes || + nextDerivedNavModeBlockEditingModes + ) { + return { + ...nextState, + derivedBlockEditingModes: + nextDerivedBlockEditingModes ?? + state.derivedBlockEditingModes, + derivedNavModeBlockEditingModes: + nextDerivedNavModeBlockEditingModes ?? + state.derivedNavModeBlockEditingModes, + }; + } + break; + } + case 'REPLACE_BLOCKS': { + const nextDerivedBlockEditingModes = + getDerivedBlockEditingModesUpdates( { + prevState: state, + nextState, + addedBlocks: action.blocks, + removedClientIds: action.clientIds, + isNavMode: false, + } ); + const nextDerivedNavModeBlockEditingModes = + getDerivedBlockEditingModesUpdates( { + prevState: state, + nextState, + addedBlocks: action.blocks, + removedClientIds: action.clientIds, + isNavMode: true, + } ); + + if ( + nextDerivedBlockEditingModes || + nextDerivedNavModeBlockEditingModes + ) { + return { + ...nextState, + derivedBlockEditingModes: + nextDerivedBlockEditingModes ?? + state.derivedBlockEditingModes, + derivedNavModeBlockEditingModes: + nextDerivedNavModeBlockEditingModes ?? + state.derivedNavModeBlockEditingModes, + }; + } + break; + } + case 'REPLACE_INNER_BLOCKS': { + // Get the clientIds of the blocks that are being replaced + // from the old state, before they were removed. + const removedClientIds = state.blocks.order.get( + action.rootClientId + ); + const nextDerivedBlockEditingModes = + getDerivedBlockEditingModesUpdates( { + prevState: state, + nextState, + addedBlocks: action.blocks, + removedClientIds, + isNavMode: false, + } ); + const nextDerivedNavModeBlockEditingModes = + getDerivedBlockEditingModesUpdates( { + prevState: state, + nextState, + addedBlocks: action.blocks, + removedClientIds, + isNavMode: true, + } ); + + if ( + nextDerivedBlockEditingModes || + nextDerivedNavModeBlockEditingModes + ) { + return { + ...nextState, + derivedBlockEditingModes: + nextDerivedBlockEditingModes ?? + state.derivedBlockEditingModes, + derivedNavModeBlockEditingModes: + nextDerivedNavModeBlockEditingModes ?? + state.derivedNavModeBlockEditingModes, + }; + } + break; + } + case 'MOVE_BLOCKS_TO_POSITION': { + const addedBlocks = action.clientIds.map( ( clientId ) => { + return nextState.blocks.byClientId.get( clientId ); + } ); + const nextDerivedBlockEditingModes = + getDerivedBlockEditingModesUpdates( { + prevState: state, + nextState, + addedBlocks, + removedClientIds: action.clientIds, + isNavMode: false, + } ); + const nextDerivedNavModeBlockEditingModes = + getDerivedBlockEditingModesUpdates( { + prevState: state, + nextState, + addedBlocks, + removedClientIds: action.clientIds, + isNavMode: true, + } ); + + if ( + nextDerivedBlockEditingModes || + nextDerivedNavModeBlockEditingModes + ) { + return { + ...nextState, + derivedBlockEditingModes: + nextDerivedBlockEditingModes ?? + state.derivedBlockEditingModes, + derivedNavModeBlockEditingModes: + nextDerivedNavModeBlockEditingModes ?? + state.derivedNavModeBlockEditingModes, + }; + } + break; + } + case 'UPDATE_SETTINGS': { + // Recompute the entire tree if the section root changes. + if ( + state?.settings?.[ sectionRootClientIdKey ] !== + nextState?.settings?.[ sectionRootClientIdKey ] + ) { + return { + ...nextState, + derivedBlockEditingModes: + getDerivedBlockEditingModesForTree( + nextState, + false /* Nav mode off */ + ), + derivedNavModeBlockEditingModes: + getDerivedBlockEditingModesForTree( + nextState, + true /* Nav mode on */ + ), + }; + } + break; + } + case 'RESET_BLOCKS': + case 'SET_EDITOR_MODE': + case 'RESET_ZOOM_LEVEL': + case 'SET_ZOOM_LEVEL': { + // Recompute the entire tree if the editor mode or zoom level changes, + // or if all the blocks are reset. + return { + ...nextState, + derivedBlockEditingModes: + getDerivedBlockEditingModesForTree( + nextState, + false /* Nav mode off */ + ), + derivedNavModeBlockEditingModes: + getDerivedBlockEditingModesForTree( + nextState, + true /* Nav mode on */ + ), + }; + } + } + + // If there's no change, the derivedBlockEditingModes from the previous + // state need to be preserved. + nextState.derivedBlockEditingModes = + state?.derivedBlockEditingModes ?? new Map(); + nextState.derivedNavModeBlockEditingModes = + state?.derivedNavModeBlockEditingModes ?? new Map(); + + return nextState; + }; +} + function withAutomaticChangeReset( reducer ) { return ( state, action ) => { const nextState = reducer( state, action ); @@ -2184,4 +2818,7 @@ function withAutomaticChangeReset( reducer ) { }; } -export default withAutomaticChangeReset( combinedReducers ); +export default pipe( + withDerivedBlockEditingModes, + withAutomaticChangeReset +)( combinedReducers ); diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index ac1d178f43de7c..75c43770f7e175 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -3000,14 +3000,6 @@ export function __unstableIsWithinBlockOverlay( state, clientId ) { return false; } -function isWithinBlock( state, clientId, parentClientId ) { - let parent = state.blocks.parents.get( clientId ); - while ( !! parent && parent !== parentClientId ) { - parent = state.blocks.parents.get( parent ); - } - return parent === parentClientId; -} - /** * @typedef {import('../components/block-editing-mode').BlockEditingMode} BlockEditingMode */ @@ -3049,68 +3041,28 @@ export const getBlockEditingMode = createRegistrySelector( clientId = ''; } - // In zoom-out mode, override the behavior set by - // __unstableSetBlockEditingMode to only allow editing the top-level - // sections. - if ( isZoomOut( state ) ) { - const sectionRootClientId = getSectionRootClientId( state ); - - if ( clientId === '' /* ROOT_CONTAINER_CLIENT_ID */ ) { - return sectionRootClientId ? 'disabled' : 'contentOnly'; - } - if ( clientId === sectionRootClientId ) { - return 'contentOnly'; - } - const sectionsClientIds = getBlockOrder( - state, - sectionRootClientId - ); - - // Sections are always contentOnly. - if ( sectionsClientIds?.includes( clientId ) ) { - return 'contentOnly'; - } - - return 'disabled'; + const isNavMode = + select( preferencesStore )?.get( 'core', 'editorTool' ) === + 'navigation'; + + // If the editor is currently not in navigation mode, check if the clientId + // has an editing mode set in the regular derived map. + // There may be an editing mode set here for synced patterns or in zoomed out + // mode. + if ( + ! isNavMode && + state.derivedBlockEditingModes?.has( clientId ) + ) { + return state.derivedBlockEditingModes.get( clientId ); } - const editorMode = __unstableGetEditorMode( state ); - if ( editorMode === 'navigation' ) { - const sectionRootClientId = getSectionRootClientId( state ); - - // The root section is "default mode" - if ( clientId === sectionRootClientId ) { - return 'default'; - } - - // Sections should always be contentOnly in navigation mode. - const sectionsClientIds = getBlockOrder( - state, - sectionRootClientId - ); - if ( sectionsClientIds.includes( clientId ) ) { - return 'contentOnly'; - } - - // Blocks outside sections should be disabled. - const isWithinSectionRoot = isWithinBlock( - state, - clientId, - sectionRootClientId - ); - if ( ! isWithinSectionRoot ) { - return 'disabled'; - } - - // The rest of the blocks depend on whether they are content blocks or not. - // This "flattens" the sections tree. - const name = getBlockName( state, clientId ); - const { hasContentRoleAttribute } = unlock( - select( blocksStore ) - ); - const isContent = hasContentRoleAttribute( name ); - - return isContent ? 'contentOnly' : 'disabled'; + // If the editor *is* in navigation mode, the block editing mode states + // are stored in the derivedNavModeBlockEditingModes map. + if ( + isNavMode && + state.derivedNavModeBlockEditingModes?.has( clientId ) + ) { + return state.derivedNavModeBlockEditingModes.get( clientId ); } // In normal mode, consider that an explicitely set editing mode takes over. @@ -3120,7 +3072,7 @@ export const getBlockEditingMode = createRegistrySelector( } // In normal mode, top level is default mode. - if ( ! clientId ) { + if ( clientId === '' ) { return 'default'; } diff --git a/packages/block-editor/src/store/test/private-selectors.js b/packages/block-editor/src/store/test/private-selectors.js index fb1d736e175af0..268d463f227d4d 100644 --- a/packages/block-editor/src/store/test/private-selectors.js +++ b/packages/block-editor/src/store/test/private-selectors.js @@ -129,6 +129,7 @@ describe( 'private selectors', () => { getBlockEditingMode.registry = { select: jest.fn( () => ( { hasContentRoleAttribute, + get, } ) ), }; __unstableGetEditorMode.registry = { diff --git a/packages/block-editor/src/store/test/reducer.js b/packages/block-editor/src/store/test/reducer.js index c99d639ba8a09e..b539afde9e0258 100644 --- a/packages/block-editor/src/store/test/reducer.js +++ b/packages/block-editor/src/store/test/reducer.js @@ -10,7 +10,10 @@ import { registerBlockType, unregisterBlockType, createBlock, + privateApis, } from '@wordpress/blocks'; +import { combineReducers, select } from '@wordpress/data'; +import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies @@ -38,8 +41,30 @@ import { blockEditingModes, openedBlockSettingsMenu, expandedBlock, + zoomLevel, + withDerivedBlockEditingModes, } from '../reducer'; +import { unlock } from '../../lock-unlock'; +import { sectionRootClientIdKey } from '.././private-keys'; + +const { isContentBlock } = unlock( privateApis ); + +jest.mock( '@wordpress/data/src/select', () => { + const actualSelect = jest.requireActual( '@wordpress/data/src/select' ); + + return { + select: jest.fn( ( ...args ) => actualSelect.select( ...args ) ), + }; +} ); + +jest.mock( '@wordpress/blocks/src/api/utils', () => { + return { + ...jest.requireActual( '@wordpress/blocks/src/api/utils' ), + isContentBlock: jest.fn(), + }; +} ); + const noop = () => {}; describe( 'state', () => { @@ -3544,4 +3569,830 @@ describe( 'state', () => { expect( state ).toBe( null ); } ); } ); + + describe( 'withDerivedBlockEditingModes', () => { + const testReducer = withDerivedBlockEditingModes( + combineReducers( { + blocks, + settings, + zoomLevel, + } ) + ); + + function dispatchActions( actions, reducer, initialState = {} ) { + return actions.reduce( ( _state, action ) => { + return reducer( _state, action ); + }, initialState ); + } + + beforeEach( () => { + isContentBlock.mockImplementation( + ( blockName ) => blockName === 'core/paragraph' + ); + } ); + + afterAll( () => { + isContentBlock.mockRestore(); + } ); + + describe( 'edit mode', () => { + let initialState; + beforeAll( () => { + select.mockImplementation( ( storeName ) => { + if ( storeName === preferencesStore ) { + return { + get: jest.fn( () => 'edit' ), + }; + } + return select( storeName ); + } ); + + initialState = dispatchActions( + [ + { + type: 'UPDATE_SETTINGS', + settings: { + [ sectionRootClientIdKey ]: '', + }, + }, + { + type: 'RESET_BLOCKS', + blocks: [ + { + name: 'core/group', + clientId: 'group-1', + attributes: {}, + innerBlocks: [ + { + name: 'core/paragraph', + clientId: 'paragraph-1', + attributes: {}, + innerBlocks: [], + }, + { + name: 'core/group', + clientId: 'group-2', + attributes: {}, + innerBlocks: [ + { + name: 'core/paragraph', + clientId: 'paragraph-2', + attributes: {}, + innerBlocks: [], + }, + ], + }, + ], + }, + ], + }, + ], + testReducer + ); + } ); + + afterAll( () => { + select.mockRestore(); + } ); + + it( 'returns no block editing modes when zoomed out / navigation mode are not active and there are no synced patterns', () => { + expect( initialState.derivedBlockEditingModes ).toEqual( + new Map() + ); + } ); + } ); + + describe( 'synced patterns', () => { + let initialState; + beforeAll( () => { + select.mockImplementation( ( storeName ) => { + if ( storeName === preferencesStore ) { + return { + get: jest.fn( () => 'edit' ), + }; + } + return select( storeName ); + } ); + + // Simulates how the editor typically inserts controlled blocks, + // - first the pattern is inserted with no inner blocks. + // - next the pattern is marked as a controlled block. + // - finally, once the inner blocks of the pattern are received, they're inserted. + // This process is repeated for the two patterns in this test. + initialState = dispatchActions( + [ + { + type: 'UPDATE_SETTINGS', + settings: { + [ sectionRootClientIdKey ]: '', + }, + }, + { + type: 'RESET_BLOCKS', + blocks: [ + { + name: 'core/group', + clientId: 'group-1', + attributes: {}, + innerBlocks: [ + { + name: 'core/paragraph', + clientId: 'paragraph-1', + attributes: {}, + innerBlocks: [], + }, + { + name: 'core/group', + clientId: 'group-2', + attributes: {}, + innerBlocks: [ + { + name: 'core/paragraph', + clientId: 'paragraph-2', + attributes: {}, + innerBlocks: [], + }, + ], + }, + ], + }, + ], + }, + { + type: 'INSERT_BLOCKS', + rootClientId: '', + blocks: [ + { + name: 'core/block', + clientId: 'root-pattern', + attributes: {}, + innerBlocks: [], + }, + ], + }, + { + type: 'SET_HAS_CONTROLLED_INNER_BLOCKS', + clientId: 'root-pattern', + hasControlledInnerBlocks: true, + }, + { + type: 'REPLACE_INNER_BLOCKS', + rootClientId: 'root-pattern', + blocks: [ + { + name: 'core/block', + clientId: 'nested-pattern', + attributes: {}, + innerBlocks: [], + }, + { + name: 'core/paragraph', + clientId: 'pattern-paragraph', + attributes: {}, + innerBlocks: [], + }, + { + name: 'core/group', + clientId: 'pattern-group', + attributes: {}, + innerBlocks: [ + { + name: 'core/paragraph', + clientId: + 'pattern-paragraph-with-overrides', + attributes: { + metadata: { + bindings: { + __default: + 'core/pattern-overrides', + }, + }, + }, + innerBlocks: [], + }, + ], + }, + ], + }, + { + type: 'SET_HAS_CONTROLLED_INNER_BLOCKS', + clientId: 'nested-pattern', + hasControlledInnerBlocks: true, + }, + { + type: 'REPLACE_INNER_BLOCKS', + rootClientId: 'nested-pattern', + blocks: [ + { + name: 'core/paragraph', + clientId: 'nested-paragraph', + attributes: {}, + innerBlocks: [], + }, + { + name: 'core/group', + clientId: 'nested-group', + attributes: {}, + innerBlocks: [ + { + name: 'core/paragraph', + clientId: + 'nested-paragraph-with-overrides', + attributes: { + metadata: { + bindings: { + __default: + 'core/pattern-overrides', + }, + }, + }, + innerBlocks: [], + }, + ], + }, + ], + }, + ], + testReducer, + initialState + ); + } ); + + afterAll( () => { + select.mockRestore(); + } ); + + it( 'returns the expected block editing modes for synced patterns', () => { + // Only the parent pattern and its own children that have bindings + // are in contentOnly mode. All other blocks are disabled. + expect( initialState.derivedBlockEditingModes ).toEqual( + new Map( + Object.entries( { + 'root-pattern': 'contentOnly', + 'pattern-paragraph': 'disabled', + 'pattern-group': 'disabled', + 'pattern-paragraph-with-overrides': 'contentOnly', + 'nested-pattern': 'disabled', + 'nested-paragraph': 'disabled', + 'nested-group': 'disabled', + 'nested-paragraph-with-overrides': 'disabled', + } ) + ) + ); + } ); + + it( 'removes block editing modes when synced patterns are removed', () => { + const { derivedBlockEditingModes } = dispatchActions( + [ + { + type: 'REMOVE_BLOCKS', + clientIds: [ 'root-pattern' ], + }, + ], + testReducer, + initialState + ); + + expect( derivedBlockEditingModes ).toEqual( new Map() ); + } ); + + it( 'returns the expected block editing modes for synced patterns when switching to navigation mode', () => { + select.mockImplementation( ( storeName ) => { + if ( storeName === preferencesStore ) { + return { + get: jest.fn( () => 'navigation' ), + }; + } + return select( storeName ); + } ); + + const { + derivedBlockEditingModes, + derivedNavModeBlockEditingModes, + } = dispatchActions( + [ + { + type: 'SET_EDITOR_MODE', + mode: 'navigation', + }, + ], + testReducer, + initialState + ); + + expect( derivedBlockEditingModes ).toEqual( + new Map( + Object.entries( { + 'root-pattern': 'contentOnly', // Pattern and section. + 'pattern-paragraph': 'disabled', + 'pattern-group': 'disabled', + 'pattern-paragraph-with-overrides': 'contentOnly', // Pattern child with bindings. + 'nested-pattern': 'disabled', + 'nested-paragraph': 'disabled', + 'nested-group': 'disabled', + 'nested-paragraph-with-overrides': 'disabled', + } ) + ) + ); + + expect( derivedNavModeBlockEditingModes ).toEqual( + new Map( + Object.entries( { + '': 'contentOnly', // Section root. + 'group-1': 'contentOnly', // Section. + 'paragraph-1': 'contentOnly', // Content block in section. + 'group-2': 'disabled', + 'paragraph-2': 'contentOnly', // Content block in section. + 'root-pattern': 'contentOnly', // Pattern and section. + 'pattern-paragraph': 'disabled', + 'pattern-group': 'disabled', + 'pattern-paragraph-with-overrides': 'contentOnly', // Pattern child with bindings. + 'nested-pattern': 'disabled', + 'nested-paragraph': 'disabled', + 'nested-group': 'disabled', + 'nested-paragraph-with-overrides': 'disabled', + } ) + ) + ); + + select.mockImplementation( ( storeName ) => { + if ( storeName === preferencesStore ) { + return { + get: jest.fn( () => 'edit' ), + }; + } + return select( storeName ); + } ); + } ); + + it( 'returns the expected block editing modes for synced patterns when switching to zoomed out mode', () => { + const { derivedBlockEditingModes } = dispatchActions( + [ + { + type: 'SET_ZOOM_LEVEL', + zoom: 'auto-scaled', + }, + ], + testReducer, + initialState + ); + + expect( derivedBlockEditingModes ).toEqual( + new Map( + Object.entries( { + '': 'contentOnly', // Section root. + 'group-1': 'contentOnly', // Section. + 'paragraph-1': 'disabled', + 'group-2': 'disabled', + 'paragraph-2': 'disabled', + 'root-pattern': 'contentOnly', // Pattern and section. + 'pattern-paragraph': 'disabled', + 'pattern-group': 'disabled', + 'pattern-paragraph-with-overrides': 'disabled', + 'nested-pattern': 'disabled', + 'nested-paragraph': 'disabled', + 'nested-group': 'disabled', + 'nested-paragraph-with-overrides': 'disabled', + } ) + ) + ); + } ); + } ); + + describe( 'navigation mode', () => { + let initialState; + + beforeAll( () => { + select.mockImplementation( ( storeName ) => { + if ( storeName === preferencesStore ) { + return { + get: jest.fn( () => 'navigation' ), + }; + } + return select( storeName ); + } ); + + initialState = dispatchActions( + [ + { + type: 'UPDATE_SETTINGS', + settings: { + [ sectionRootClientIdKey ]: '', + }, + }, + { + type: 'RESET_BLOCKS', + blocks: [ + { + name: 'core/group', + clientId: 'group-1', + attributes: {}, + innerBlocks: [ + { + name: 'core/paragraph', + clientId: 'paragraph-1', + attributes: {}, + innerBlocks: [], + }, + { + name: 'core/group', + clientId: 'group-2', + attributes: {}, + innerBlocks: [ + { + name: 'core/paragraph', + clientId: 'paragraph-2', + attributes: {}, + innerBlocks: [], + }, + ], + }, + ], + }, + ], + }, + ], + testReducer + ); + } ); + + afterAll( () => { + select.mockRestore(); + } ); + + it( 'returns the expected block editing modes', () => { + expect( initialState.derivedNavModeBlockEditingModes ).toEqual( + new Map( + Object.entries( { + '': 'contentOnly', // Section root. + 'group-1': 'contentOnly', // Section block. + 'paragraph-1': 'contentOnly', // Content block in section. + 'group-2': 'disabled', // Non-content block in section. + 'paragraph-2': 'contentOnly', // Content block in section. + } ) + ) + ); + } ); + + it( 'removes block editing modes when blocks are removed', () => { + const { derivedNavModeBlockEditingModes } = dispatchActions( + [ + { + type: 'REMOVE_BLOCKS', + clientIds: [ 'group-2' ], + }, + ], + testReducer, + initialState + ); + + expect( derivedNavModeBlockEditingModes ).toEqual( + new Map( + Object.entries( { + '': 'contentOnly', + 'group-1': 'contentOnly', + 'paragraph-1': 'contentOnly', + } ) + ) + ); + } ); + + it( 'updates block editing modes when new blocks are inserted', () => { + const { derivedNavModeBlockEditingModes } = dispatchActions( + [ + { + type: 'INSERT_BLOCKS', + rootClientId: '', + blocks: [ + { + name: 'core/group', + clientId: 'group-3', + attributes: {}, + innerBlocks: [ + { + name: 'core/paragraph', + clientId: 'paragraph-3', + attributes: {}, + innerBlocks: [], + }, + { + name: 'core/group', + clientId: 'group-4', + attributes: {}, + innerBlocks: [], + }, + ], + }, + ], + }, + ], + testReducer, + initialState + ); + + expect( derivedNavModeBlockEditingModes ).toEqual( + new Map( + Object.entries( { + '': 'contentOnly', // Section root. + 'group-1': 'contentOnly', // Section block. + 'paragraph-1': 'contentOnly', // Content block in section. + 'group-2': 'disabled', // Non-content block in section. + 'paragraph-2': 'contentOnly', // Content block in section. + 'group-3': 'contentOnly', // New section block. + 'paragraph-3': 'contentOnly', // New content block in section. + 'group-4': 'disabled', // Non-content block in section. + } ) + ) + ); + } ); + + it( 'updates block editing modes when blocks are moved to a new position', () => { + const { derivedNavModeBlockEditingModes } = dispatchActions( + [ + { + type: 'MOVE_BLOCKS_TO_POSITION', + clientIds: [ 'group-2' ], + fromRootClientId: 'group-1', + toRootClientId: '', + }, + ], + testReducer, + initialState + ); + expect( derivedNavModeBlockEditingModes ).toEqual( + new Map( + Object.entries( { + '': 'contentOnly', // Section root. + 'group-1': 'contentOnly', // Section block. + 'paragraph-1': 'contentOnly', // Content block in section. + 'group-2': 'contentOnly', // New section block. + 'paragraph-2': 'contentOnly', // Still a content block in a section. + } ) + ) + ); + } ); + + it( 'handles changes to the section root', () => { + const { derivedNavModeBlockEditingModes } = dispatchActions( + [ + { + type: 'UPDATE_SETTINGS', + settings: { + [ sectionRootClientIdKey ]: 'group-1', + }, + }, + ], + testReducer, + initialState + ); + + expect( derivedNavModeBlockEditingModes ).toEqual( + new Map( + Object.entries( { + '': 'disabled', + 'group-1': 'contentOnly', + 'paragraph-1': 'contentOnly', + 'group-2': 'contentOnly', + 'paragraph-2': 'contentOnly', + } ) + ) + ); + } ); + } ); + + describe( 'zoom out mode', () => { + let initialState; + + beforeAll( () => { + initialState = dispatchActions( + [ + { + type: 'UPDATE_SETTINGS', + settings: { + [ sectionRootClientIdKey ]: '', + }, + }, + { + type: 'SET_ZOOM_LEVEL', + zoom: 'auto-scaled', + }, + { + type: 'RESET_BLOCKS', + blocks: [ + { + name: 'core/group', + clientId: 'group-1', + attributes: {}, + innerBlocks: [ + { + name: 'core/paragraph', + clientId: 'paragraph-1', + attributes: {}, + innerBlocks: [], + }, + { + name: 'core/group', + clientId: 'group-2', + attributes: {}, + innerBlocks: [ + { + name: 'core/paragraph', + clientId: 'paragraph-2', + attributes: {}, + innerBlocks: [], + }, + ], + }, + ], + }, + ], + }, + ], + testReducer + ); + } ); + + it( 'returns the expected block editing modes', () => { + expect( initialState.derivedBlockEditingModes ).toEqual( + new Map( + Object.entries( { + '': 'contentOnly', // Section root. + 'group-1': 'contentOnly', // Section block. + 'paragraph-1': 'disabled', + 'group-2': 'disabled', + 'paragraph-2': 'disabled', + } ) + ) + ); + } ); + + it( 'overrides navigation mode', () => { + select.mockImplementation( ( storeName ) => { + if ( storeName === preferencesStore ) { + return { + get: jest.fn( () => 'navigation' ), + }; + } + return select( storeName ); + } ); + + const { derivedBlockEditingModes } = dispatchActions( + [ + { + type: 'SET_EDITOR_MODE', + mode: 'navigation', + }, + ], + testReducer, + initialState + ); + + expect( derivedBlockEditingModes ).toEqual( + new Map( + Object.entries( { + '': 'contentOnly', // Section root. + 'group-1': 'contentOnly', // Section block. + 'paragraph-1': 'disabled', + 'group-2': 'disabled', + 'paragraph-2': 'disabled', + } ) + ) + ); + + select.mockImplementation( ( storeName ) => { + if ( storeName === preferencesStore ) { + return { + get: jest.fn( () => 'edit' ), + }; + } + return select( storeName ); + } ); + } ); + + it( 'removes block editing modes when blocks are removed', () => { + const { derivedBlockEditingModes } = dispatchActions( + [ + { + type: 'REMOVE_BLOCKS', + clientIds: [ 'group-2' ], + }, + ], + testReducer, + initialState + ); + + expect( derivedBlockEditingModes ).toEqual( + new Map( + Object.entries( { + '': 'contentOnly', + 'group-1': 'contentOnly', + 'paragraph-1': 'disabled', + } ) + ) + ); + } ); + + it( 'updates block editing modes when new blocks are inserted', () => { + const { derivedBlockEditingModes } = dispatchActions( + [ + { + type: 'INSERT_BLOCKS', + rootClientId: '', + blocks: [ + { + name: 'core/group', + clientId: 'group-3', + attributes: {}, + innerBlocks: [ + { + name: 'core/paragraph', + clientId: 'paragraph-3', + attributes: {}, + innerBlocks: [], + }, + { + name: 'core/group', + clientId: 'group-4', + attributes: {}, + innerBlocks: [], + }, + ], + }, + ], + }, + ], + testReducer, + initialState + ); + + expect( derivedBlockEditingModes ).toEqual( + new Map( + Object.entries( { + '': 'contentOnly', // Section root. + 'group-1': 'contentOnly', // Section block. + 'paragraph-1': 'disabled', + 'group-2': 'disabled', + 'paragraph-2': 'disabled', + 'group-3': 'contentOnly', // New section block. + 'paragraph-3': 'disabled', + 'group-4': 'disabled', + } ) + ) + ); + } ); + + it( 'updates block editing modes when blocks are moved to a new position', () => { + const { derivedBlockEditingModes } = dispatchActions( + [ + { + type: 'MOVE_BLOCKS_TO_POSITION', + clientIds: [ 'group-2' ], + fromRootClientId: 'group-1', + toRootClientId: '', + }, + ], + testReducer, + initialState + ); + expect( derivedBlockEditingModes ).toEqual( + new Map( + Object.entries( { + '': 'contentOnly', // Section root. + 'group-1': 'contentOnly', // Section block. + 'paragraph-1': 'disabled', + 'group-2': 'contentOnly', // New section block. + 'paragraph-2': 'disabled', + } ) + ) + ); + } ); + + it( 'handles changes to the section root', () => { + const { derivedBlockEditingModes } = dispatchActions( + [ + { + type: 'UPDATE_SETTINGS', + settings: { + [ sectionRootClientIdKey ]: 'group-1', + }, + }, + ], + testReducer, + initialState + ); + + expect( derivedBlockEditingModes ).toEqual( + new Map( + Object.entries( { + '': 'disabled', + 'group-1': 'contentOnly', // New section root. + 'paragraph-1': 'contentOnly', // Section block. + 'group-2': 'contentOnly', // Section block. + 'paragraph-2': 'disabled', + } ) + ) + ); + } ); + } ); + } ); } ); diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index 7c0361449c5fca..7692bd6bf2cbb6 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -9,14 +9,12 @@ import { import { RawHTML } from '@wordpress/element'; import { symbol } from '@wordpress/icons'; import { select, dispatch } from '@wordpress/data'; -import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies */ import * as selectors from '../selectors'; import { store } from '../'; -import { sectionRootClientIdKey } from '../private-keys'; import { lock } from '../../lock-unlock'; const { @@ -4469,29 +4467,19 @@ describe( 'getBlockEditingMode', () => { blockEditingModes: new Map( [] ), }; - const navigationModeStateWithRootSection = { - ...baseState, - settings: { - [ sectionRootClientIdKey ]: 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', // The group is the "main" container - }, - }; - const hasContentRoleAttribute = jest.fn( () => false ); + const get = jest.fn( () => 'edit' ); - const fauxPrivateAPIs = {}; + const mockedSelectors = { get }; - lock( fauxPrivateAPIs, { + lock( mockedSelectors, { hasContentRoleAttribute, } ); getBlockEditingMode.registry = { - select: jest.fn( () => fauxPrivateAPIs ), + select: jest.fn( () => mockedSelectors ), }; - afterEach( () => { - dispatch( preferencesStore ).set( 'core', 'editorTool', undefined ); - } ); - it( 'should return default by default', () => { expect( getBlockEditingMode( @@ -4614,98 +4602,4 @@ describe( 'getBlockEditingMode', () => { getBlockEditingMode( state, 'b3247f75-fd94-4fef-97f9-5bfd162cc416' ) ).toBe( 'contentOnly' ); } ); - - describe( 'navigation mode', () => { - const writeModeExperiment = window.__experimentalEditorWriteMode; - beforeAll( () => { - window.__experimentalEditorWriteMode = true; - } ); - afterAll( () => { - window.__experimentalEditorWriteMode = writeModeExperiment; - } ); - it( 'in navigation mode, the root section container is default', () => { - dispatch( preferencesStore ).set( - 'core', - 'editorTool', - 'navigation' - ); - expect( - getBlockEditingMode( - navigationModeStateWithRootSection, - 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337' - ) - ).toBe( 'default' ); - } ); - - it( 'in navigation mode, anything outside the section container is disabled', () => { - dispatch( preferencesStore ).set( - 'core', - 'editorTool', - 'navigation' - ); - expect( - getBlockEditingMode( - navigationModeStateWithRootSection, - '6cf70164-9097-4460-bcbf-200560546988' - ) - ).toBe( 'disabled' ); - } ); - - it( 'in navigation mode, sections are contentOnly', () => { - dispatch( preferencesStore ).set( - 'core', - 'editorTool', - 'navigation' - ); - expect( - getBlockEditingMode( - navigationModeStateWithRootSection, - 'b26fc763-417d-4f01-b81c-2ec61e14a972' - ) - ).toBe( 'contentOnly' ); - expect( - getBlockEditingMode( - navigationModeStateWithRootSection, - '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f' - ) - ).toBe( 'contentOnly' ); - } ); - - it( 'in navigation mode, blocks with content attributes within sections are contentOnly', () => { - dispatch( preferencesStore ).set( - 'core', - 'editorTool', - 'navigation' - ); - hasContentRoleAttribute.mockReturnValueOnce( true ); - expect( - getBlockEditingMode( - navigationModeStateWithRootSection, - 'b3247f75-fd94-4fef-97f9-5bfd162cc416' - ) - ).toBe( 'contentOnly' ); - - hasContentRoleAttribute.mockReturnValueOnce( true ); - expect( - getBlockEditingMode( - navigationModeStateWithRootSection, - 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c' - ) - ).toBe( 'contentOnly' ); - } ); - - it( 'in navigation mode, blocks without content attributes within sections are disabled', () => { - dispatch( preferencesStore ).set( - 'core', - 'editorTool', - 'navigation' - ); - expect( - getBlockEditingMode( - navigationModeStateWithRootSection, - '9b9c5c3f-2e46-4f02-9e14-9fed515b958s' - ) - ).toBe( 'disabled' ); - } ); - } ); } ); diff --git a/packages/block-library/src/block/edit.js b/packages/block-library/src/block/edit.js index 104b07157cba74..3d4d07e52b386a 100644 --- a/packages/block-library/src/block/edit.js +++ b/packages/block-library/src/block/edit.js @@ -7,7 +7,7 @@ import clsx from 'clsx'; * WordPress dependencies */ import { useSelect, useDispatch } from '@wordpress/data'; -import { useRef, useMemo, useEffect } from '@wordpress/element'; +import { useRef, useMemo } from '@wordpress/element'; import { useEntityRecord, store as coreStore, @@ -37,12 +37,10 @@ import { getBlockBindingsSource } from '@wordpress/blocks'; /** * Internal dependencies */ -import { name as patternBlockName } from './index'; import { unlock } from '../lock-unlock'; const { useLayoutClasses } = unlock( blockEditorPrivateApis ); -const { isOverridableBlock, hasOverridableBlocks } = - unlock( patternsPrivateApis ); +const { hasOverridableBlocks } = unlock( patternsPrivateApis ); const fullAlignments = [ 'full', 'wide', 'left', 'right' ]; @@ -75,22 +73,6 @@ const useInferredLayout = ( blocks, parentLayout ) => { }, [ blocks, parentLayout ] ); }; -function setBlockEditMode( setEditMode, blocks, mode ) { - blocks.forEach( ( block ) => { - const editMode = - mode || - ( isOverridableBlock( block ) ? 'contentOnly' : 'disabled' ); - setEditMode( block.clientId, editMode ); - - setBlockEditMode( - setEditMode, - block.innerBlocks, - // Disable editing for nested patterns. - block.name === patternBlockName ? 'disabled' : mode - ); - } ); -} - function RecursionWarning() { const blockProps = useBlockProps(); return ( @@ -171,7 +153,6 @@ function ReusableBlockEdit( { name, attributes: { ref, content }, __unstableParentLayout: parentLayout, - clientId: patternClientId, setAttributes, } ) { const { record, hasResolved } = useEntityRecord( @@ -184,49 +165,24 @@ function ReusableBlockEdit( { } ); const isMissing = hasResolved && ! record; - const { setBlockEditingMode, __unstableMarkLastChangeAsPersistent } = + const { __unstableMarkLastChangeAsPersistent } = useDispatch( blockEditorStore ); - const { - innerBlocks, - onNavigateToEntityRecord, - editingMode, - hasPatternOverridesSource, - } = useSelect( + const { onNavigateToEntityRecord, hasPatternOverridesSource } = useSelect( ( select ) => { - const { getBlocks, getSettings, getBlockEditingMode } = - select( blockEditorStore ); + const { getSettings } = select( blockEditorStore ); // For editing link to the site editor if the theme and user permissions support it. return { - innerBlocks: getBlocks( patternClientId ), onNavigateToEntityRecord: getSettings().onNavigateToEntityRecord, - editingMode: getBlockEditingMode( patternClientId ), hasPatternOverridesSource: !! getBlockBindingsSource( 'core/pattern-overrides' ), }; }, - [ patternClientId ] + [] ); - // Sync the editing mode of the pattern block with the inner blocks. - useEffect( () => { - setBlockEditMode( - setBlockEditingMode, - innerBlocks, - // Disable editing if the pattern itself is disabled. - editingMode === 'disabled' || ! hasPatternOverridesSource - ? 'disabled' - : undefined - ); - }, [ - editingMode, - innerBlocks, - setBlockEditingMode, - hasPatternOverridesSource, - ] ); - const canOverrideBlocks = useMemo( () => hasPatternOverridesSource && hasOverridableBlocks( blocks ), [ hasPatternOverridesSource, blocks ] @@ -244,7 +200,6 @@ function ReusableBlockEdit( { } ); const innerBlocksProps = useInnerBlocksProps( blockProps, { - templateLock: 'all', layout, value: blocks, onInput: NOOP, diff --git a/packages/block-library/src/missing/test/edit.native.js b/packages/block-library/src/missing/test/edit.native.js index 47d0da572b7c88..eba1169ae643b7 100644 --- a/packages/block-library/src/missing/test/edit.native.js +++ b/packages/block-library/src/missing/test/edit.native.js @@ -10,7 +10,6 @@ import { Text } from 'react-native'; import { BottomSheet, Icon } from '@wordpress/components'; import { help, plugins } from '@wordpress/icons'; import { storeConfig } from '@wordpress/block-editor'; -jest.mock( '@wordpress/blocks' ); jest.mock( '@wordpress/block-editor/src/store/selectors' ); /** diff --git a/packages/blocks/README.md b/packages/blocks/README.md index 3e5a88a2b92c1b..f4805e1c60b381 100644 --- a/packages/blocks/README.md +++ b/packages/blocks/README.md @@ -503,6 +503,10 @@ _Returns_ - `Array|string`: A list of blocks or a string, depending on `handlerMode`. +### privateApis + +Undocumented declaration. + ### rawHandler Converts an HTML string to known blocks. diff --git a/packages/blocks/src/api/index.js b/packages/blocks/src/api/index.js index 3ace68be87393c..a03a58d8f9b21c 100644 --- a/packages/blocks/src/api/index.js +++ b/packages/blocks/src/api/index.js @@ -1,3 +1,9 @@ +/** + * Internal dependencies + */ +import { lock } from '../lock-unlock'; +import { isContentBlock } from './utils'; + // The blocktype is the most important concept within the block API. It defines // all aspects of the block configuration and its interfaces, including `edit` // and `save`. The transforms specification allows converting one blocktype to @@ -169,3 +175,6 @@ export { __EXPERIMENTAL_ELEMENTS, __EXPERIMENTAL_PATHS_WITH_OVERRIDE, } from './constants'; + +export const privateApis = {}; +lock( privateApis, { isContentBlock } ); diff --git a/packages/blocks/src/api/test/utils.js b/packages/blocks/src/api/test/utils.js index ad76e89aafe5f0..548bbb27da3889 100644 --- a/packages/blocks/src/api/test/utils.js +++ b/packages/blocks/src/api/test/utils.js @@ -14,6 +14,7 @@ import { getBlockLabel, __experimentalSanitizeBlockAttributes, getBlockAttributesNamesByRole, + isContentBlock, } from '../utils'; const noop = () => {}; @@ -382,3 +383,40 @@ describe( 'getBlockAttributesNamesByRole', () => { ).toEqual( [] ); } ); } ); + +describe( 'isContentBlock', () => { + it( 'returns true if the block has a content role attribute', () => { + registerBlockType( 'core/test-content-block', { + attributes: { + content: { + type: 'string', + role: 'content', + }, + align: { + type: 'string', + }, + }, + save: noop, + category: 'text', + title: 'test content block', + } ); + expect( isContentBlock( 'core/test-content-block' ) ).toBe( true ); + } ); + + it( 'returns false if the block does not have a content role attribute', () => { + registerBlockType( 'core/test-non-content-block', { + attributes: { + content: { + type: 'string', + }, + align: { + type: 'string', + }, + }, + save: noop, + category: 'text', + title: 'test non-content block', + } ); + expect( isContentBlock( 'core/test-non-content-block' ) ).toBe( false ); + } ); +} ); diff --git a/packages/blocks/src/api/utils.js b/packages/blocks/src/api/utils.js index 20f0f6a85ed091..1a215036496559 100644 --- a/packages/blocks/src/api/utils.js +++ b/packages/blocks/src/api/utils.js @@ -370,6 +370,18 @@ export const __experimentalGetBlockAttributesNamesByRole = ( ...args ) => { return getBlockAttributesNamesByRole( ...args ); }; +export function isContentBlock( name ) { + const attributes = getBlockType( name )?.attributes; + + return !! Object.keys( attributes )?.some( ( attributeKey ) => { + const attribute = attributes[ attributeKey ]; + return ( + attribute?.role === 'content' || + attribute?.__experimentalRole === 'content' + ); + } ); +} + /** * Return a new object with the specified keys omitted. * diff --git a/test/e2e/specs/editor/various/pattern-overrides.spec.js b/test/e2e/specs/editor/various/pattern-overrides.spec.js index 6f4a5929300520..20eff4096cb1cc 100644 --- a/test/e2e/specs/editor/various/pattern-overrides.spec.js +++ b/test/e2e/specs/editor/various/pattern-overrides.spec.js @@ -226,6 +226,321 @@ test.describe( 'Pattern Overrides', () => { } ); } ); + test.describe( 'block editing modes', () => { + test.beforeEach( async ( { page } ) => { + await page.addInitScript( () => { + window.__experimentalEditorWriteMode = true; + } ); + } ); + + test( 'blocks with bindings in a synced pattern are editable, and all other blocks are disabled', async ( { + admin, + editor, + page, + requestUtils, + } ) => { + const content = ` + <!-- wp:paragraph {"metadata":{"name":"Pattern Overrides","bindings":{"__default":{"source":"core/pattern-overrides"}}}} --> + <p>Pattern Overrides</p> + <!-- /wp:paragraph --> + <!-- wp:paragraph {"metadata":{"name":"Post Meta Binding","bindings":{"content":{"source":"core/post-meta","args":{"key":"Post Meta Binding"}}}}} --> + <p>Post Meta Binding</p> + <!-- /wp:paragraph --> + <!-- wp:paragraph {"metadata":{"name":"No Overrides or Binding"}} --> + <p>No Overrides or Binding</p> + <!-- /wp:paragraph --> + `; + + const { id } = await requestUtils.createBlock( { + title: 'Pattern', + content, + status: 'publish', + } ); + + await admin.visitSiteEditor( { + postId: 'emptytheme//index', + postType: 'wp_template', + canvas: 'edit', + } ); + + await editor.setContent( '' ); + + await editor.insertBlock( { + name: 'core/block', + attributes: { ref: id }, + } ); + + const patternBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Pattern', + } ); + const paragraphs = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + const blockWithOverrides = paragraphs.filter( { + hasText: 'Pattern Overrides', + } ); + const blockWithBindings = paragraphs.filter( { + hasText: 'Post Meta Binding', + } ); + const blockWithoutOverridesOrBindings = paragraphs.filter( { + hasText: 'No Overrides or Binding', + } ); + + await test.step( 'Zoomed in / Design mode', async () => { + await editor.switchEditorTool( 'Design' ); + // In zoomed in and design mode the pattern block and child blocks + // with bindings are editable. + await expect( patternBlock ).not.toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithOverrides ).not.toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithBindings ).not.toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithoutOverridesOrBindings ).toHaveAttribute( + 'inert', + 'true' + ); + } ); + + await test.step( 'Zoomed in / Write mode - pattern as a section', async () => { + await editor.switchEditorTool( 'Write' ); + // The pattern block is still editable as a section. + await expect( patternBlock ).not.toHaveAttribute( + 'inert', + 'true' + ); + // Child blocks of the pattern with bindings are editable. + await expect( blockWithOverrides ).not.toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithBindings ).not.toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithoutOverridesOrBindings ).toHaveAttribute( + 'inert', + 'true' + ); + } ); + + await test.step( 'Zoomed out / Write mode - pattern as a section', async () => { + await page.getByLabel( 'Zoom Out' ).click(); + // In zoomed out only the pattern block is editable, as in this scenario it's a section. + await expect( patternBlock ).not.toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithOverrides ).toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithBindings ).toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithoutOverridesOrBindings ).toHaveAttribute( + 'inert', + 'true' + ); + } ); + + await test.step( 'Zoomed out / Design mode - pattern as a section', async () => { + await editor.switchEditorTool( 'Design' ); + // In zoomed out only the pattern block is editable, as in this scenario it's a section. + await expect( patternBlock ).not.toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithOverrides ).toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithBindings ).toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithoutOverridesOrBindings ).toHaveAttribute( + 'inert', + 'true' + ); + } ); + + // Zoom out and group the pattern. + await page.getByLabel( 'Zoom Out' ).click(); + await editor.selectBlocks( patternBlock ); + await editor.clickBlockOptionsMenuItem( 'Group' ); + + await test.step( 'Zoomed in / Write mode - pattern nested in a section', async () => { + await editor.switchEditorTool( 'Write' ); + // The pattern block is not inert as it has editable content, but it shouldn't be selectable. + // TODO: find a way to test that the block is not selectable. + await expect( patternBlock ).not.toHaveAttribute( + 'inert', + 'true' + ); + // Child blocks of the pattern are editable as normal. + await expect( blockWithOverrides ).not.toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithBindings ).not.toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithoutOverridesOrBindings ).toHaveAttribute( + 'inert', + 'true' + ); + } ); + + await test.step( 'Zoomed out / Write mode - pattern nested in a section', async () => { + await page.getByLabel( 'Zoom Out' ).click(); + // None of the pattern is editable in zoomed out when nested in a section. + await expect( patternBlock ).toHaveAttribute( 'inert', 'true' ); + await expect( blockWithOverrides ).toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithBindings ).toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithoutOverridesOrBindings ).toHaveAttribute( + 'inert', + 'true' + ); + } ); + + await test.step( 'Zoomed out / Design mode - pattern nested in a section', async () => { + await editor.switchEditorTool( 'Design' ); + // None of the pattern is editable in zoomed out when nested in a section. + await expect( patternBlock ).toHaveAttribute( 'inert', 'true' ); + await expect( blockWithOverrides ).toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithBindings ).toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithoutOverridesOrBindings ).toHaveAttribute( + 'inert', + 'true' + ); + } ); + } ); + + test( 'disables editing of nested patterns', async ( { + page, + admin, + requestUtils, + editor, + } ) => { + const paragraphName = 'Editable paragraph'; + const headingName = 'Editable heading'; + const innerPattern = await requestUtils.createBlock( { + title: 'Inner Pattern', + content: `<!-- wp:paragraph {"metadata":{"name":"${ paragraphName }","bindings":{"__default":{"source":"core/pattern-overrides"}}}} --> + <p>Inner paragraph</p> + <!-- /wp:paragraph -->`, + status: 'publish', + } ); + const outerPattern = await requestUtils.createBlock( { + title: 'Outer Pattern', + content: `<!-- wp:heading {"metadata":{"name":"${ headingName }","bindings":{"__default":{"source":"core/pattern-overrides"}}}} --> + <h2 class="wp-block-heading">Outer heading</h2> + <!-- /wp:heading --> + <!-- wp:block {"ref":${ innerPattern.id },"content":{"${ paragraphName }":{"content":"Inner paragraph (edited)"}}} /-->`, + status: 'publish', + } ); + + await admin.createNewPost(); + + await editor.insertBlock( { + name: 'core/block', + attributes: { ref: outerPattern.id }, + } ); + + // Make an edit to the outer pattern heading. + await editor.canvas + .getByRole( 'document', { name: 'Block: Heading' } ) + .fill( 'Outer heading (edited)' ); + + const postId = await editor.publishPost(); + + // Check the pattern has the correct attributes. + await expect.poll( editor.getBlocks ).toMatchObject( [ + { + name: 'core/block', + attributes: { + ref: outerPattern.id, + content: { + [ headingName ]: { + content: 'Outer heading (edited)', + }, + }, + }, + innerBlocks: [], + }, + ] ); + // Check it renders correctly. + const headingBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Heading', + } ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( headingBlock ).toHaveText( 'Outer heading (edited)' ); + await expect( headingBlock ).not.toHaveAttribute( 'inert', 'true' ); + await expect( paragraphBlock ).toHaveText( + 'Inner paragraph (edited)' + ); + await expect( paragraphBlock ).toHaveAttribute( 'inert', 'true' ); + + // Edit the outer pattern. + await editor.selectBlocks( + editor.canvas + .getByRole( 'document', { name: 'Block: Pattern' } ) + .first() + ); + await editor.showBlockToolbar(); + await page + .getByRole( 'toolbar', { name: 'Block tools' } ) + .getByRole( 'button', { name: 'Edit original' } ) + .click(); + + // The inner paragraph should be editable in the pattern focus mode. + await editor.selectBlocks( + editor.canvas + .getByRole( 'document', { name: 'Block: Pattern' } ) + .first() + ); + await expect( + editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ), + 'The inner paragraph should be editable' + ).not.toHaveAttribute( 'inert', 'true' ); + + // Visit the post on the frontend. + await page.goto( `/?p=${ postId }` ); + + await expect( + page.getByRole( 'heading', { level: 2 } ) + ).toHaveText( 'Outer heading (edited)' ); + await expect( + page.getByText( 'Inner paragraph (edited)' ) + ).toBeVisible(); + } ); + } ); + test( 'retains override values when converting a pattern block to regular blocks', async ( { page, admin, @@ -425,107 +740,6 @@ test.describe( 'Pattern Overrides', () => { await expect( buttonLink ).toHaveAttribute( 'rel', /^\s*nofollow\s*$/ ); } ); - test( 'disables editing of nested patterns', async ( { - page, - admin, - requestUtils, - editor, - } ) => { - const paragraphName = 'Editable paragraph'; - const headingName = 'Editable heading'; - const innerPattern = await requestUtils.createBlock( { - title: 'Inner Pattern', - content: `<!-- wp:paragraph {"metadata":{"name":"${ paragraphName }","bindings":{"__default":{"source":"core/pattern-overrides"}}}} --> -<p>Inner paragraph</p> -<!-- /wp:paragraph -->`, - status: 'publish', - } ); - const outerPattern = await requestUtils.createBlock( { - title: 'Outer Pattern', - content: `<!-- wp:heading {"metadata":{"name":"${ headingName }","bindings":{"__default":{"source":"core/pattern-overrides"}}}} --> -<h2 class="wp-block-heading">Outer heading</h2> -<!-- /wp:heading --> -<!-- wp:block {"ref":${ innerPattern.id },"content":{"${ paragraphName }":{"content":"Inner paragraph (edited)"}}} /-->`, - status: 'publish', - } ); - - await admin.createNewPost(); - - await editor.insertBlock( { - name: 'core/block', - attributes: { ref: outerPattern.id }, - } ); - - // Make an edit to the outer pattern heading. - await editor.canvas - .getByRole( 'document', { name: 'Block: Heading' } ) - .fill( 'Outer heading (edited)' ); - - const postId = await editor.publishPost(); - - // Check the pattern has the correct attributes. - await expect.poll( editor.getBlocks ).toMatchObject( [ - { - name: 'core/block', - attributes: { - ref: outerPattern.id, - content: { - [ headingName ]: { - content: 'Outer heading (edited)', - }, - }, - }, - innerBlocks: [], - }, - ] ); - // Check it renders correctly. - const headingBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Heading', - } ); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - await expect( headingBlock ).toHaveText( 'Outer heading (edited)' ); - await expect( headingBlock ).not.toHaveAttribute( 'inert', 'true' ); - await expect( paragraphBlock ).toHaveText( 'Inner paragraph (edited)' ); - await expect( paragraphBlock ).toHaveAttribute( 'inert', 'true' ); - - // Edit the outer pattern. - await editor.selectBlocks( - editor.canvas - .getByRole( 'document', { name: 'Block: Pattern' } ) - .first() - ); - await editor.showBlockToolbar(); - await page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Edit original' } ) - .click(); - - // The inner paragraph should be editable in the pattern focus mode. - await editor.selectBlocks( - editor.canvas - .getByRole( 'document', { name: 'Block: Pattern' } ) - .first() - ); - await expect( - editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ), - 'The inner paragraph should be editable' - ).not.toHaveAttribute( 'inert', 'true' ); - - // Visit the post on the frontend. - await page.goto( `/?p=${ postId }` ); - - await expect( page.getByRole( 'heading', { level: 2 } ) ).toHaveText( - 'Outer heading (edited)' - ); - await expect( - page.getByText( 'Inner paragraph (edited)' ) - ).toBeVisible(); - } ); - test( 'resets overrides after clicking the reset button', async ( { page, admin, From 2f6ef277f3c9f875f8294c387727249ecd0defa0 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Thu, 28 Nov 2024 14:23:17 +0800 Subject: [PATCH 1744/1908] Remove use of `contentOnly` block editing mode for synced patterns (#67364) * Remove use of `contentOnly` block editing mode for synced patterns * Update unit tests ---- Co-authored-by: talldan <talldanwp@git.wordpress.org> --- packages/block-editor/src/store/reducer.js | 2 +- packages/block-editor/src/store/test/reducer.js | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 1e09ec98f005ab..edae9c392c37de 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -2355,7 +2355,7 @@ function getDerivedBlockEditingModesForTree( return; } - derivedBlockEditingModes.set( clientId, 'contentOnly' ); + // Else do nothing, use the default block editing mode. return; } diff --git a/packages/block-editor/src/store/test/reducer.js b/packages/block-editor/src/store/test/reducer.js index b539afde9e0258..dd1665d6736ada 100644 --- a/packages/block-editor/src/store/test/reducer.js +++ b/packages/block-editor/src/store/test/reducer.js @@ -3828,7 +3828,6 @@ describe( 'state', () => { expect( initialState.derivedBlockEditingModes ).toEqual( new Map( Object.entries( { - 'root-pattern': 'contentOnly', 'pattern-paragraph': 'disabled', 'pattern-group': 'disabled', 'pattern-paragraph-with-overrides': 'contentOnly', @@ -3883,7 +3882,6 @@ describe( 'state', () => { expect( derivedBlockEditingModes ).toEqual( new Map( Object.entries( { - 'root-pattern': 'contentOnly', // Pattern and section. 'pattern-paragraph': 'disabled', 'pattern-group': 'disabled', 'pattern-paragraph-with-overrides': 'contentOnly', // Pattern child with bindings. @@ -3903,7 +3901,7 @@ describe( 'state', () => { 'paragraph-1': 'contentOnly', // Content block in section. 'group-2': 'disabled', 'paragraph-2': 'contentOnly', // Content block in section. - 'root-pattern': 'contentOnly', // Pattern and section. + 'root-pattern': 'contentOnly', // Section. 'pattern-paragraph': 'disabled', 'pattern-group': 'disabled', 'pattern-paragraph-with-overrides': 'contentOnly', // Pattern child with bindings. From c9a5cab0e2e9063054ed4f299bde734a242e3794 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 28 Nov 2024 08:51:04 +0100 Subject: [PATCH 1745/1908] Site Editor: Use path based routing instead of query args and site-editor.php routes (#67199) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- backport-changelog/6.8/7903.md | 3 + lib/compat/wordpress-6.8/site-editor.php | 124 ++++++++++ lib/experimental/posts/load.php | 12 - lib/load.php | 1 + package-lock.json | 10 +- .../src/admin-navigation-commands.js | 6 +- .../src/site-editor-navigation-commands.js | 143 ++++++------ .../src/components/add-new-pattern/index.js | 26 +-- .../src/components/add-new-template/index.js | 8 +- .../edit-site/src/components/app/index.js | 40 +++- .../block-editor/use-editor-iframe-props.js | 9 +- .../use-navigate-to-entity-record.js | 4 +- .../block-editor/use-site-editor-settings.js | 12 +- .../src/components/dataviews-actions/index.js | 6 +- .../edit-site/src/components/editor/index.js | 93 +++++--- .../editor/use-resolve-edited-entity.js | 19 +- .../components/global-styles-sidebar/index.js | 8 +- .../edit-site/src/components/layout/index.js | 7 +- .../edit-site/src/components/layout/router.js | 86 ------- .../delete-category-menu-item.js | 7 +- .../src/components/page-patterns/fields.js | 23 +- .../src/components/page-patterns/index.js | 30 +-- .../src/components/page-templates/fields.js | 19 +- .../src/components/page-templates/index.js | 31 +-- .../src/components/post-list/index.js | 78 ++++--- .../src/components/posts-app-routes/home.js | 36 --- .../src/components/posts-app-routes/index.js | 17 +- .../{posts-edit.js => post-item.js} | 14 +- .../posts-list-view-quick-edit.js | 52 ----- .../posts-app-routes/posts-list-view.js | 40 ---- .../posts-app-routes/posts-view-quick-edit.js | 49 ---- .../components/posts-app-routes/posts-view.js | 35 --- .../src/components/posts-app-routes/posts.js | 66 ++++++ .../src/components/posts-app/index.js | 17 +- .../src/components/resizable-frame/index.js | 13 +- .../edit-site/src/components/routes/link.js | 68 ------ .../src/components/save-panel/index.js | 4 +- .../sidebar-dataviews/add-new-view.js | 18 +- .../sidebar-dataviews/dataview-item.js | 13 +- .../src/components/sidebar-dataviews/index.js | 4 +- .../sidebar-global-styles-wrapper/index.js | 54 ++--- .../sidebar-navigation-item/index.js | 12 +- .../index.js | 26 +-- .../sidebar-navigation-screen-main/index.js | 13 +- .../more-menu.js | 8 +- .../use-navigation-menu-handlers.js | 4 +- .../index.js | 12 +- .../leaf-more-menu.js | 30 +-- .../category-item.js | 25 +- .../index.js | 7 +- .../content.js | 41 ++-- .../index.js | 15 +- .../sidebar-navigation-screen/index.js | 4 +- .../site-editor-routes/home-edit.js | 17 -- .../{home-view.js => home.js} | 9 +- .../components/site-editor-routes/index.js | 56 ++--- .../site-editor-routes/navigation-edit.js | 22 -- .../navigation-item-edit.js | 26 --- .../navigation-item-view.js | 25 -- .../site-editor-routes/navigation-item.js | 39 ++++ .../site-editor-routes/navigation-view.js | 21 -- .../site-editor-routes/navigation.js | 34 +++ .../{pages-edit.js => page-item.js} | 20 +- .../pages-list-view-quick-edit.js | 56 ----- .../site-editor-routes/pages-list-view.js | 44 ---- .../pages-view-quick-edit.js | 53 ----- .../site-editor-routes/pages-view.js | 39 ---- .../components/site-editor-routes/pages.js | 66 ++++++ .../site-editor-routes/pattern-item.js | 15 ++ .../site-editor-routes/patterns-edit.js | 24 -- .../site-editor-routes/patterns-view.js | 22 -- .../components/site-editor-routes/patterns.js | 15 ++ .../{styles-view.js => styles.js} | 14 +- .../site-editor-routes/template-item.js | 15 ++ .../site-editor-routes/template-part-item.js | 15 ++ .../site-editor-routes/templates-edit.js | 22 -- .../site-editor-routes/templates-list-view.js | 28 --- .../site-editor-routes/templates-view.js | 22 -- .../site-editor-routes/templates.js | 45 ++++ .../src/components/site-hub/index.js | 9 +- .../src/hooks/commands/use-common-commands.js | 86 ++----- .../hooks/commands/use-set-command-context.js | 4 +- .../edit-site/src/store/private-actions.js | 7 + packages/edit-site/src/store/reducer.js | 2 + .../src/utils/is-previewing-theme.js | 4 +- .../edit-site/src/utils/use-activate-theme.js | 7 +- packages/router/package.json | 4 +- packages/router/src/history.ts | 99 -------- packages/router/src/link.tsx | 55 +++++ packages/router/src/private-apis.ts | 3 + packages/router/src/router.tsx | 220 +++++++++++++++++- packages/router/tsconfig.json | 5 +- .../editor/various/pattern-overrides.spec.js | 12 +- .../specs/site-editor/browser-history.spec.js | 4 +- .../specs/site-editor/command-center.spec.js | 2 +- .../specs/site-editor/hybrid-theme.spec.js | 2 +- .../site-editor-url-navigation.spec.js | 4 +- 97 files changed, 1249 insertions(+), 1546 deletions(-) create mode 100644 backport-changelog/6.8/7903.md create mode 100644 lib/compat/wordpress-6.8/site-editor.php delete mode 100644 packages/edit-site/src/components/layout/router.js delete mode 100644 packages/edit-site/src/components/posts-app-routes/home.js rename packages/edit-site/src/components/posts-app-routes/{posts-edit.js => post-item.js} (62%) delete mode 100644 packages/edit-site/src/components/posts-app-routes/posts-list-view-quick-edit.js delete mode 100644 packages/edit-site/src/components/posts-app-routes/posts-list-view.js delete mode 100644 packages/edit-site/src/components/posts-app-routes/posts-view-quick-edit.js delete mode 100644 packages/edit-site/src/components/posts-app-routes/posts-view.js create mode 100644 packages/edit-site/src/components/posts-app-routes/posts.js delete mode 100644 packages/edit-site/src/components/routes/link.js delete mode 100644 packages/edit-site/src/components/site-editor-routes/home-edit.js rename packages/edit-site/src/components/site-editor-routes/{home-view.js => home.js} (66%) delete mode 100644 packages/edit-site/src/components/site-editor-routes/navigation-edit.js delete mode 100644 packages/edit-site/src/components/site-editor-routes/navigation-item-edit.js delete mode 100644 packages/edit-site/src/components/site-editor-routes/navigation-item-view.js create mode 100644 packages/edit-site/src/components/site-editor-routes/navigation-item.js delete mode 100644 packages/edit-site/src/components/site-editor-routes/navigation-view.js create mode 100644 packages/edit-site/src/components/site-editor-routes/navigation.js rename packages/edit-site/src/components/site-editor-routes/{pages-edit.js => page-item.js} (54%) delete mode 100644 packages/edit-site/src/components/site-editor-routes/pages-list-view-quick-edit.js delete mode 100644 packages/edit-site/src/components/site-editor-routes/pages-list-view.js delete mode 100644 packages/edit-site/src/components/site-editor-routes/pages-view-quick-edit.js delete mode 100644 packages/edit-site/src/components/site-editor-routes/pages-view.js create mode 100644 packages/edit-site/src/components/site-editor-routes/pages.js create mode 100644 packages/edit-site/src/components/site-editor-routes/pattern-item.js delete mode 100644 packages/edit-site/src/components/site-editor-routes/patterns-edit.js delete mode 100644 packages/edit-site/src/components/site-editor-routes/patterns-view.js create mode 100644 packages/edit-site/src/components/site-editor-routes/patterns.js rename packages/edit-site/src/components/site-editor-routes/{styles-view.js => styles.js} (58%) create mode 100644 packages/edit-site/src/components/site-editor-routes/template-item.js create mode 100644 packages/edit-site/src/components/site-editor-routes/template-part-item.js delete mode 100644 packages/edit-site/src/components/site-editor-routes/templates-edit.js delete mode 100644 packages/edit-site/src/components/site-editor-routes/templates-list-view.js delete mode 100644 packages/edit-site/src/components/site-editor-routes/templates-view.js create mode 100644 packages/edit-site/src/components/site-editor-routes/templates.js delete mode 100644 packages/router/src/history.ts create mode 100644 packages/router/src/link.tsx diff --git a/backport-changelog/6.8/7903.md b/backport-changelog/6.8/7903.md new file mode 100644 index 00000000000000..cb20d8d2dd2b1b --- /dev/null +++ b/backport-changelog/6.8/7903.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7903 + +* https://github.com/WordPress/gutenberg/pull/67199 diff --git a/lib/compat/wordpress-6.8/site-editor.php b/lib/compat/wordpress-6.8/site-editor.php new file mode 100644 index 00000000000000..cde108830b1d2c --- /dev/null +++ b/lib/compat/wordpress-6.8/site-editor.php @@ -0,0 +1,124 @@ +<?php +/** + * Updates to the site editor in 6.8. + * + * Adds a mandatory dashboard link and redirects old urls. + * + * @package gutenberg + */ + +add_filter( + 'block_editor_settings_all', + function ( $settings ) { + $settings['__experimentalDashboardLink'] = admin_url( '/' ); + return $settings; + } +); + +function gutenberg_get_site_editor_redirection() { + global $pagenow; + if ( 'site-editor.php' !== $pagenow || isset( $_REQUEST['p'] ) || ! $_SERVER['QUERY_STRING'] ) { + return false; + } + + // The following redirects are for the new permalinks in the site editor. + if ( isset( $_REQUEST['postType'] ) && 'wp_navigation' === $_REQUEST['postType'] && ! empty( $_REQUEST['postId'] ) ) { + return add_query_arg( array( 'p' => '/wp_navigation/' . $_REQUEST['postId'] ), remove_query_arg( array( 'postType', 'postId' ) ) ); + } + + if ( isset( $_REQUEST['postType'] ) && 'wp_navigation' === $_REQUEST['postType'] && empty( $_REQUEST['postId'] ) ) { + return add_query_arg( array( 'p' => '/navigation' ), remove_query_arg( 'postType' ) ); + } + + if ( isset( $_REQUEST['path'] ) && '/wp_global_styles' === $_REQUEST['path'] ) { + return add_query_arg( array( 'p' => '/styles' ), remove_query_arg( 'path' ) ); + } + + if ( isset( $_REQUEST['postType'] ) && 'page' === $_REQUEST['postType'] && ( empty( $_REQUEST['canvas'] ) || empty( $_REQUEST['postId'] ) ) ) { + return add_query_arg( array( 'p' => '/page' ), remove_query_arg( 'postType' ) ); + } + + if ( isset( $_REQUEST['postType'] ) && 'page' === $_REQUEST['postType'] && ! empty( $_REQUEST['postId'] ) ) { + return add_query_arg( array( 'p' => '/page/' . $_REQUEST['postId'] ), remove_query_arg( array( 'postType', 'postId' ) ) ); + } + + if ( isset( $_REQUEST['postType'] ) && 'wp_template' === $_REQUEST['postType'] && ( empty( $_REQUEST['canvas'] ) || empty( $_REQUEST['postId'] ) ) ) { + return add_query_arg( array( 'p' => '/template' ), remove_query_arg( 'postType' ) ); + } + + if ( isset( $_REQUEST['postType'] ) && 'wp_template' === $_REQUEST['postType'] && ! empty( $_REQUEST['postId'] ) ) { + return add_query_arg( array( 'p' => '/wp_template/' . $_REQUEST['postId'] ), remove_query_arg( array( 'postType', 'postId' ) ) ); + } + + if ( isset( $_REQUEST['postType'] ) && 'wp_block' === $_REQUEST['postType'] && ( empty( $_REQUEST['canvas'] ) || empty( $_REQUEST['postId'] ) ) ) { + return add_query_arg( array( 'p' => '/pattern' ), remove_query_arg( 'postType' ) ); + } + + if ( isset( $_REQUEST['postType'] ) && 'wp_block' === $_REQUEST['postType'] && ! empty( $_REQUEST['postId'] ) ) { + return add_query_arg( array( 'p' => '/wp_block/' . $_REQUEST['postId'] ), remove_query_arg( array( 'postType', 'postId' ) ) ); + } + + if ( isset( $_REQUEST['postType'] ) && 'wp_template_part' === $_REQUEST['postType'] && ( empty( $_REQUEST['canvas'] ) || empty( $_REQUEST['postId'] ) ) ) { + return add_query_arg( array( 'p' => '/pattern' ) ); + } + + if ( isset( $_REQUEST['postType'] ) && 'wp_template_part' === $_REQUEST['postType'] && ! empty( $_REQUEST['postId'] ) ) { + return add_query_arg( array( 'p' => '/wp_template_part/' . $_REQUEST['postId'] ), remove_query_arg( array( 'postType', 'postId' ) ) ); + } + + // The following redirects are for backward compatibility with the old site editor URLs. + if ( isset( $_REQUEST['path'] ) && '/wp_template_part/all' === $_REQUEST['path'] ) { + return add_query_arg( + array( + 'p' => '/pattern', + 'postType' => 'wp_template_part', + ), + remove_query_arg( 'path' ) + ); + } + + if ( isset( $_REQUEST['path'] ) && '/page' === $_REQUEST['path'] ) { + return add_query_arg( array( 'p' => '/page' ), remove_query_arg( 'path' ) ); + } + + if ( isset( $_REQUEST['path'] ) && '/wp_template' === $_REQUEST['path'] ) { + return add_query_arg( array( 'p' => '/template' ), remove_query_arg( 'path' ) ); + } + + if ( isset( $_REQUEST['path'] ) && '/patterns' === $_REQUEST['path'] ) { + return add_query_arg( array( 'p' => '/pattern' ), remove_query_arg( 'path' ) ); + } + + if ( isset( $_REQUEST['path'] ) && '/navigation' === $_REQUEST['path'] ) { + return add_query_arg( array( 'p' => '/navigation' ), remove_query_arg( 'path' ) ); + } + + return add_query_arg( array( 'p' => '/' ) ); +} + +function gutenberg_redirect_site_editor_deprecated_urls() { + $redirection = gutenberg_get_site_editor_redirection(); + if ( false !== $redirection ) { + wp_redirect( $redirection, 301 ); + exit; + } +} +add_action( 'admin_init', 'gutenberg_redirect_site_editor_deprecated_urls' ); + +/** + * Filter the `wp_die_handler` to allow access to the Site Editor's new pages page + * for Classic themes. + * + * site-editor.php's access is forbidden for hybrid/classic themes and only allowed with some very special query args (some very special pages like template parts...). + * The only way to disable this protection since we're changing the urls in Gutenberg is to override the wp_die_handler. + * + * @param callable $default_handler The default handler. + * @return callable The default handler or a custom handler. + */ +function gutenberg_styles_wp_die_handler( $default_handler ) { + if ( ! wp_is_block_theme() && str_contains( $_SERVER['REQUEST_URI'], 'site-editor.php' ) && isset( $_GET['p'] ) ) { + return '__return_false'; + } + return $default_handler; +} +add_filter( 'wp_die_handler', 'gutenberg_styles_wp_die_handler' ); diff --git a/lib/experimental/posts/load.php b/lib/experimental/posts/load.php index 7321392b11a25d..699534f1886f52 100644 --- a/lib/experimental/posts/load.php +++ b/lib/experimental/posts/load.php @@ -69,18 +69,6 @@ function gutenberg_posts_dashboard() { echo '<div id="gutenberg-posts-dashboard"></div>'; } -/** - * Redirects to the new posts dashboard page and adds the postType query arg. - */ -function gutenberg_add_post_type_arg() { - global $pagenow; - if ( 'admin.php' === $pagenow && isset( $_GET['page'] ) && 'gutenberg-posts-dashboard' === $_GET['page'] && empty( $_GET['postType'] ) ) { - wp_redirect( admin_url( '/admin.php?page=gutenberg-posts-dashboard&postType=post' ) ); - exit; - } -} -add_action( 'admin_init', 'gutenberg_add_post_type_arg' ); - /** * Replaces the default posts menu item with the new posts dashboard. */ diff --git a/lib/load.php b/lib/load.php index 85d1c7e3292b50..97c5404a3a3ead 100644 --- a/lib/load.php +++ b/lib/load.php @@ -98,6 +98,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.8/blocks.php'; require __DIR__ . '/compat/wordpress-6.8/functions.php'; require __DIR__ . '/compat/wordpress-6.8/post.php'; +require __DIR__ . '/compat/wordpress-6.8/site-editor.php'; // Experimental features. require __DIR__ . '/experimental/block-editor-settings-mobile.php'; diff --git a/package-lock.json b/package-lock.json index ccf779f2d67eab..dc0c18f3b6ac5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44492,6 +44492,12 @@ "node": ">=10.0.0" } }, + "node_modules/route-recognizer": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/route-recognizer/-/route-recognizer-0.3.4.tgz", + "integrity": "sha512-2+MhsfPhvauN1O8KaXpXAOfR/fwe8dnUXVM+xw7yt40lJRfPVQxV6yryZm0cgRvAj5fMF/mdRZbL2ptwbs5i2g==", + "license": "MIT" + }, "node_modules/rrweb-cssom": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", @@ -55563,10 +55569,12 @@ "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", + "@wordpress/compose": "*", "@wordpress/element": "*", "@wordpress/private-apis": "*", "@wordpress/url": "*", - "history": "^5.3.0" + "history": "^5.3.0", + "route-recognizer": "^0.3.4" }, "engines": { "node": ">=18.12.0", diff --git a/packages/core-commands/src/admin-navigation-commands.js b/packages/core-commands/src/admin-navigation-commands.js index 8a8167bb29b820..f82faa05baae4c 100644 --- a/packages/core-commands/src/admin-navigation-commands.js +++ b/packages/core-commands/src/admin-navigation-commands.js @@ -44,11 +44,7 @@ const getAddNewPageCommand = () => } ); if ( page?.id ) { - history.push( { - postId: page.id, - postType: 'page', - canvas: 'edit', - } ); + history.navigate( `/page/${ page.id }?canvas=edit` ); } } catch ( error ) { const errorMessage = diff --git a/packages/core-commands/src/site-editor-navigation-commands.js b/packages/core-commands/src/site-editor-navigation-commands.js index 2785d809d41e03..c1b12a84d4d61a 100644 --- a/packages/core-commands/src/site-editor-navigation-commands.js +++ b/packages/core-commands/src/site-editor-navigation-commands.js @@ -136,19 +136,18 @@ const getNavigationCommandLoaderPerPostType = ( postType ) => return { ...command, callback: ( { close } ) => { - const args = { - postType, - postId: record.id, - canvas: 'edit', - }; - const targetUrl = addQueryArgs( - 'site-editor.php', - args - ); if ( isSiteEditor ) { - history.push( args ); + history.navigate( + `/${ postType }/${ record.id }?canvas=edit` + ); } else { - document.location = targetUrl; + document.location = addQueryArgs( + 'site-editor.php', + { + p: `/${ postType }/${ record.id }`, + canvas: 'edit', + } + ); } close(); }, @@ -220,19 +219,18 @@ const getNavigationCommandLoaderPerTemplate = ( templateType ) => : __( '(no title)' ), icon: icons[ templateType ], callback: ( { close } ) => { - const args = { - postType: templateType, - postId: record.id, - canvas: 'edit', - }; - const targetUrl = addQueryArgs( - 'site-editor.php', - args - ); if ( isSiteEditor ) { - history.push( args ); + history.navigate( + `/${ templateType }/${ record.id }?canvas=edit` + ); } else { - document.location = targetUrl; + document.location = addQueryArgs( + 'site-editor.php', + { + p: `/${ templateType }/${ record.id }`, + canvas: 'edit', + } + ); } close(); }, @@ -249,18 +247,19 @@ const getNavigationCommandLoaderPerTemplate = ( templateType ) => label: __( 'Template parts' ), icon: symbolFilled, callback: ( { close } ) => { - const args = { - postType: 'wp_template_part', - categoryId: 'all-parts', - }; - const targetUrl = addQueryArgs( - 'site-editor.php', - args - ); if ( isSiteEditor ) { - history.push( args ); + history.navigate( + '/pattern?postType=wp_template_part&categoryId=all-parts' + ); } else { - document.location = targetUrl; + document.location = addQueryArgs( + 'site-editor.php', + { + p: '/pattern', + postType: 'wp_template_part', + categoryId: 'all-parts', + } + ); } close(); }, @@ -303,17 +302,15 @@ const getSiteEditorBasicNavigationCommands = () => label: __( 'Navigation' ), icon: navigation, callback: ( { close } ) => { - const args = { - postType: 'wp_navigation', - }; - const targetUrl = addQueryArgs( - 'site-editor.php', - args - ); if ( isSiteEditor ) { - history.push( args ); + history.navigate( '/navigation' ); } else { - document.location = targetUrl; + document.location = addQueryArgs( + 'site-editor.php', + { + p: '/navigation', + } + ); } close(); }, @@ -324,17 +321,15 @@ const getSiteEditorBasicNavigationCommands = () => label: __( 'Styles' ), icon: styles, callback: ( { close } ) => { - const args = { - path: '/wp_global_styles', - }; - const targetUrl = addQueryArgs( - 'site-editor.php', - args - ); if ( isSiteEditor ) { - history.push( args ); + history.navigate( '/styles' ); } else { - document.location = targetUrl; + document.location = addQueryArgs( + 'site-editor.php', + { + p: '/styles', + } + ); } close(); }, @@ -345,17 +340,15 @@ const getSiteEditorBasicNavigationCommands = () => label: __( 'Pages' ), icon: page, callback: ( { close } ) => { - const args = { - postType: 'page', - }; - const targetUrl = addQueryArgs( - 'site-editor.php', - args - ); if ( isSiteEditor ) { - history.push( args ); + history.navigate( '/page' ); } else { - document.location = targetUrl; + document.location = addQueryArgs( + 'site-editor.php', + { + p: '/page', + } + ); } close(); }, @@ -366,17 +359,15 @@ const getSiteEditorBasicNavigationCommands = () => label: __( 'Templates' ), icon: layout, callback: ( { close } ) => { - const args = { - postType: 'wp_template', - }; - const targetUrl = addQueryArgs( - 'site-editor.php', - args - ); if ( isSiteEditor ) { - history.push( args ); + history.navigate( '/template' ); } else { - document.location = targetUrl; + document.location = addQueryArgs( + 'site-editor.php', + { + p: '/template', + } + ); } close(); }, @@ -389,17 +380,15 @@ const getSiteEditorBasicNavigationCommands = () => icon: symbol, callback: ( { close } ) => { if ( canCreateTemplate ) { - const args = { - postType: 'wp_block', - }; - const targetUrl = addQueryArgs( - 'site-editor.php', - args - ); if ( isSiteEditor ) { - history.push( args ); + history.navigate( '/pattern' ); } else { - document.location = targetUrl; + document.location = addQueryArgs( + 'site-editor.php', + { + p: '/pattern', + } + ); } close(); } else { diff --git a/packages/edit-site/src/components/add-new-pattern/index.js b/packages/edit-site/src/components/add-new-pattern/index.js index bb9e53da6a5660..63452691c1c373 100644 --- a/packages/edit-site/src/components/add-new-pattern/index.js +++ b/packages/edit-site/src/components/add-new-pattern/index.js @@ -69,23 +69,16 @@ export default function AddNewPattern() { function handleCreatePattern( { pattern } ) { setShowPatternModal( false ); - - history.push( { - postId: pattern.id, - postType: PATTERN_TYPES.user, - canvas: 'edit', - } ); + history.navigate( + `/${ PATTERN_TYPES.user }/${ pattern.id }?canvas=edit` + ); } function handleCreateTemplatePart( templatePart ) { setShowTemplatePartModal( false ); - - // Navigate to the created template part editor. - history.push( { - postId: templatePart.id, - postType: TEMPLATE_PART_POST_TYPE, - canvas: 'edit', - } ); + history.navigate( + `/${ TEMPLATE_PART_POST_TYPE }/${ templatePart.id }?canvas=edit` + ); } function handleError() { @@ -203,10 +196,9 @@ export default function AddNewPattern() { ! currentCategoryId && categoryId !== 'my-patterns' ) { - history.push( { - postType: PATTERN_TYPES.user, - categoryId: PATTERN_DEFAULT_CATEGORY, - } ); + history.navigate( + `/pattern?categoryId=${ PATTERN_DEFAULT_CATEGORY }` + ); } createSuccessNotice( diff --git a/packages/edit-site/src/components/add-new-template/index.js b/packages/edit-site/src/components/add-new-template/index.js index 1a2d9ea727fa85..5f06ecae6824ae 100644 --- a/packages/edit-site/src/components/add-new-template/index.js +++ b/packages/edit-site/src/components/add-new-template/index.js @@ -203,11 +203,9 @@ function NewTemplateModal( { onClose } ) { ); // Navigate to the created template editor. - history.push( { - postId: newTemplate.id, - postType: TEMPLATE_POST_TYPE, - canvas: 'edit', - } ); + history.navigate( + `/${ TEMPLATE_POST_TYPE }/${ newTemplate.id }?canvas=edit` + ); createSuccessNotice( sprintf( diff --git a/packages/edit-site/src/components/app/index.js b/packages/edit-site/src/components/app/index.js index 7e4c50d7d00f09..cf13e7baf1b738 100644 --- a/packages/edit-site/src/components/app/index.js +++ b/packages/edit-site/src/components/app/index.js @@ -2,35 +2,41 @@ * WordPress dependencies */ import { store as noticesStore } from '@wordpress/notices'; -import { useDispatch } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import { __, sprintf } from '@wordpress/i18n'; import { PluginArea } from '@wordpress/plugins'; import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { useCallback } from '@wordpress/element'; /** * Internal dependencies */ import Layout from '../layout'; import { unlock } from '../../lock-unlock'; +import { store as editSiteStore } from '../../store'; import { useCommonCommands } from '../../hooks/commands/use-common-commands'; -import useActiveRoute from '../layout/router'; import useSetCommandContext from '../../hooks/commands/use-set-command-context'; import { useRegisterSiteEditorRoutes } from '../site-editor-routes'; +import { + currentlyPreviewingTheme, + isPreviewingTheme, +} from '../../utils/is-previewing-theme'; const { RouterProvider } = unlock( routerPrivateApis ); function AppLayout() { useCommonCommands(); useSetCommandContext(); - useRegisterSiteEditorRoutes(); - const route = useActiveRoute(); - return <Layout route={ route } />; + return <Layout />; } export default function App() { + useRegisterSiteEditorRoutes(); const { createErrorNotice } = useDispatch( noticesStore ); - + const routes = useSelect( ( select ) => { + return unlock( select( editSiteStore ) ).getRoutes(); + }, [] ); function onPluginAreaError( name ) { createErrorNotice( sprintf( @@ -42,9 +48,29 @@ export default function App() { ) ); } + const beforeNavigate = useCallback( ( { path, query } ) => { + if ( ! isPreviewingTheme() ) { + return { path, query }; + } + + return { + path, + query: { + ...query, + wp_theme_preview: + 'wp_theme_preview' in query + ? query.wp_theme_preview + : currentlyPreviewingTheme(), + }, + }; + }, [] ); return ( - <RouterProvider> + <RouterProvider + routes={ routes } + pathArg="p" + beforeNavigate={ beforeNavigate } + > <AppLayout /> <PluginArea onError={ onPluginAreaError } /> </RouterProvider> diff --git a/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js b/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js index 7c88fee0d5b727..1c70c85aed08d3 100644 --- a/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js +++ b/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js @@ -12,6 +12,7 @@ import { useState, useEffect } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { store as editorStore } from '@wordpress/editor'; import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies @@ -21,9 +22,9 @@ import { unlock } from '../../lock-unlock'; const { useLocation, useHistory } = unlock( routerPrivateApis ); export default function useEditorIframeProps() { - const { params } = useLocation(); + const { query, path } = useLocation(); const history = useHistory(); - const { canvas = 'view' } = params; + const { canvas = 'view' } = query; const currentPostIsTrashed = useSelect( ( select ) => { return ( select( editorStore ).getCurrentPostAttribute( 'status' ) === @@ -55,13 +56,13 @@ export default function useEditorIframeProps() { ! currentPostIsTrashed ) { event.preventDefault(); - history.push( { ...params, canvas: 'edit' }, undefined, { + history.navigate( addQueryArgs( path, { canvas: 'edit' } ), { transition: 'canvas-mode-edit-transition', } ); } }, onClick: () => - history.push( { ...params, canvas: 'edit' }, undefined, { + history.navigate( addQueryArgs( path, { canvas: 'edit' } ), { transition: 'canvas-mode-edit-transition', } ), onClickCapture: ( event ) => { diff --git a/packages/edit-site/src/components/block-editor/use-navigate-to-entity-record.js b/packages/edit-site/src/components/block-editor/use-navigate-to-entity-record.js index 120b15b8551d3d..8cc7fdaefe2d98 100644 --- a/packages/edit-site/src/components/block-editor/use-navigate-to-entity-record.js +++ b/packages/edit-site/src/components/block-editor/use-navigate-to-entity-record.js @@ -16,7 +16,9 @@ export default function useNavigateToEntityRecord() { const onNavigateToEntityRecord = useCallback( ( params ) => { - history.push( { ...params, focusMode: true, canvas: 'edit' } ); + history.navigate( + `/${ params.postType }/${ params.id }?canvas=edit&focusMode=true` + ); }, [ history ] ); diff --git a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js index 186f4aacf79232..d37987dc3dc420 100644 --- a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js +++ b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js @@ -22,11 +22,11 @@ function useNavigateToPreviousEntityRecord() { const history = useHistory(); const goBack = useMemo( () => { const isFocusMode = - location.params.focusMode || - ( location.params.postId && - FOCUSABLE_ENTITIES.includes( location.params.postType ) ); + location.query.focusMode || + ( location?.params?.postId && + FOCUSABLE_ENTITIES.includes( location?.params?.postType ) ); const didComeFromEditorCanvas = - previousLocation?.params.canvas === 'edit'; + previousLocation?.query.canvas === 'edit'; const showBackButton = isFocusMode && didComeFromEditorCanvas; return showBackButton ? () => history.back() : undefined; // `previousLocation` changes when the component updates for any reason, not @@ -37,8 +37,8 @@ function useNavigateToPreviousEntityRecord() { } export function useSpecificEditorSettings() { - const { params } = useLocation(); - const { canvas = 'view' } = params; + const { query } = useLocation(); + const { canvas = 'view' } = query; const onNavigateToEntityRecord = useNavigateToEntityRecord(); const { settings } = useSelect( ( select ) => { const { getSettings } = select( editSiteStore ); diff --git a/packages/edit-site/src/components/dataviews-actions/index.js b/packages/edit-site/src/components/dataviews-actions/index.js index 09b7597c6cb341..0a7b20c712c820 100644 --- a/packages/edit-site/src/components/dataviews-actions/index.js +++ b/packages/edit-site/src/components/dataviews-actions/index.js @@ -31,11 +31,7 @@ export const useEditPostAction = () => { }, callback( items ) { const post = items[ 0 ]; - history.push( { - postId: post.id, - postType: post.type, - canvas: 'edit', - } ); + history.navigate( `/${ post.type }/${ post.id }?canvas=edit` ); }, } ), [ history ] diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 1d115dca7518df..c045bafd8a6839 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -54,6 +54,7 @@ import { useResolveEditedEntity, useSyncDeprecatedEntityIntoState, } from './use-resolve-edited-entity'; +import { addQueryArgs } from '@wordpress/url'; const { Editor, BackButton } = unlock( editorPrivateApis ); const { useHistory, useLocation } = unlock( routerPrivateApis ); @@ -83,10 +84,44 @@ const siteIconVariants = { }, }; +function getListPathForPostType( postType ) { + switch ( postType ) { + case 'navigation': + return '/navigation'; + case 'wp_block': + return '/pattern?postType=wp_block'; + case 'wp_template_part': + return '/pattern?postType=wp_template_part'; + case 'wp_template': + return '/template'; + case 'page': + return '/page'; + case 'post': + return '/'; + } + throw 'Unknown post type'; +} + +function getNavigationPath( location, postType ) { + const { path, name } = location; + if ( + [ + 'pattern-item', + 'template-part-item', + 'page-item', + 'template-item', + 'post-item', + ].includes( name ) + ) { + return getListPathForPostType( postType ); + } + return addQueryArgs( path, { canvas: undefined } ); +} + export default function EditSiteEditor( { isPostsList = false } ) { const disableMotion = useReducedMotion(); - const { params } = useLocation(); - const { canvas = 'view' } = params; + const location = useLocation(); + const { canvas = 'view' } = location.query; const isLoading = useIsSiteEditorLoading(); useAdaptEditorToCanvas( canvas ); const entity = useResolveEditedEntity(); @@ -157,9 +192,11 @@ export default function EditSiteEditor( { isPostsList = false } ) { case 'move-to-trash': case 'delete-post': { - history.push( { - postType: items[ 0 ].type, - } ); + history.navigate( + getListPathForPostType( + postWithTemplate ? context.postType : postType + ) + ); } break; case 'duplicate-post': @@ -182,11 +219,9 @@ export default function EditSiteEditor( { isPostsList = false } ) { { label: __( 'Edit' ), onClick: () => { - history.push( { - postId: newItem.id, - postType: newItem.type, - canvas: 'edit', - } ); + history.navigate( + `/${ newItem.type }/${ newItem.id }?canvas=edit` + ); }, }, ], @@ -196,7 +231,13 @@ export default function EditSiteEditor( { isPostsList = false } ) { break; } }, - [ history, createSuccessNotice ] + [ + postType, + context?.postType, + postWithTemplate, + history, + createSuccessNotice, + ] ); // Replace the title and icon displayed in the DocumentBar when there's an overlay visible. @@ -268,26 +309,20 @@ export default function EditSiteEditor( { isPostsList = false } ) { // come here through `posts list` and are in focus mode editing a template, template part etc.. if ( isPostsList && - params?.focusMode + location.query?.focusMode ) { - history.push( - { - page: 'gutenberg-posts-dashboard', - postType: 'post', - }, - undefined, - { - transition: - 'canvas-mode-view-transition', - } - ); + history.navigate( '/', { + transition: + 'canvas-mode-view-transition', + } ); } else { - history.push( - { - ...params, - canvas: undefined, - }, - undefined, + history.navigate( + getNavigationPath( + location, + postWithTemplate + ? context.postType + : postType + ), { transition: 'canvas-mode-view-transition', diff --git a/packages/edit-site/src/components/editor/use-resolve-edited-entity.js b/packages/edit-site/src/components/editor/use-resolve-edited-entity.js index 4f873738704141..8da076f9f00b71 100644 --- a/packages/edit-site/src/components/editor/use-resolve-edited-entity.js +++ b/packages/edit-site/src/components/editor/use-resolve-edited-entity.js @@ -30,8 +30,23 @@ const postTypesWithoutParentTemplate = [ const authorizedPostTypes = [ 'page', 'post' ]; export function useResolveEditedEntity() { - const { params = {} } = useLocation(); - const { postId, postType } = params; + const { name, params = {}, query } = useLocation(); + const { postId = query?.postId } = params; // Fallback to query param for postId for list view routes. + let postType; + if ( name === 'navigation-item' ) { + postType = NAVIGATION_POST_TYPE; + } else if ( name === 'pattern-item' ) { + postType = PATTERN_TYPES.user; + } else if ( name === 'template-part-item' ) { + postType = TEMPLATE_PART_POST_TYPE; + } else if ( name === 'template-item' || name === 'templates' ) { + postType = TEMPLATE_POST_TYPE; + } else if ( name === 'page-item' || name === 'pages' ) { + postType = 'page'; + } else if ( name === 'post-item' || name === 'posts' ) { + postType = 'post'; + } + const homePage = useSelect( ( select ) => { const { getHomePage } = unlock( select( coreDataStore ) ); return getHomePage(); diff --git a/packages/edit-site/src/components/global-styles-sidebar/index.js b/packages/edit-site/src/components/global-styles-sidebar/index.js index d46346b50dae37..02a29dac5c0b7d 100644 --- a/packages/edit-site/src/components/global-styles-sidebar/index.js +++ b/packages/edit-site/src/components/global-styles-sidebar/index.js @@ -28,8 +28,8 @@ const { interfaceStore } = unlock( editorPrivateApis ); const { useLocation } = unlock( routerPrivateApis ); export default function GlobalStylesSidebar() { - const { params } = useLocation(); - const { canvas = 'view', path } = params; + const { query } = useLocation(); + const { canvas = 'view', name } = query; const { shouldClearCanvasContainerView, isStyleBookOpened, @@ -133,14 +133,14 @@ export default function GlobalStylesSidebar() { const previousActiveAreaRef = useRef( null ); useEffect( () => { - if ( path?.startsWith( '/wp_global_styles' ) && canvas === 'edit' ) { + if ( name === 'styles' && canvas === 'edit' ) { previousActiveAreaRef.current = getActiveComplementaryArea( 'core' ); enableComplementaryArea( 'core', 'edit-site/global-styles' ); } else if ( previousActiveAreaRef.current ) { enableComplementaryArea( 'core', previousActiveAreaRef.current ); } - }, [ path, enableComplementaryArea, canvas, getActiveComplementaryArea ] ); + }, [ name, enableComplementaryArea, canvas, getActiveComplementaryArea ] ); return ( <DefaultSidebar diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index 47ff65aa2ac678..7c3f9e21152566 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -51,9 +51,9 @@ const { useLocation } = unlock( routerPrivateApis ); const ANIMATION_DURATION = 0.3; -function Layout( { route } ) { - const { params } = useLocation(); - const { canvas = 'view' } = params; +function Layout() { + const { query, name: routeKey, areas, widths } = useLocation(); + const { canvas = 'view' } = query; useCommands(); const isMobileViewport = useViewportMatch( 'medium', '<' ); const toggleRef = useRef(); @@ -63,7 +63,6 @@ function Layout( { route } ) { const isEditorLoading = useIsSiteEditorLoading(); const [ isResizableFrameOversized, setIsResizableFrameOversized ] = useState( false ); - const { name: routeKey, areas, widths } = route; const animationRef = useMovingAnimation( { triggerAnimationOnChange: routeKey + '-' + canvas, } ); diff --git a/packages/edit-site/src/components/layout/router.js b/packages/edit-site/src/components/layout/router.js deleted file mode 100644 index 912a837555e0d1..00000000000000 --- a/packages/edit-site/src/components/layout/router.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * WordPress dependencies - */ -import { privateApis as routerPrivateApis } from '@wordpress/router'; -import { useEffect, useMemo } from '@wordpress/element'; -import { useSelect } from '@wordpress/data'; -/** - * Internal dependencies - */ -import { unlock } from '../../lock-unlock'; -import { - NAVIGATION_POST_TYPE, - PATTERN_TYPES, - TEMPLATE_PART_POST_TYPE, - TEMPLATE_POST_TYPE, -} from '../../utils/constants'; -import { store as editSiteStore } from '../../store'; - -const { useLocation, useHistory } = unlock( routerPrivateApis ); - -function useRedirectOldPaths() { - const history = useHistory(); - const { params } = useLocation(); - useEffect( () => { - const { postType, path, categoryType, ...rest } = params; - - if ( path === '/wp_template_part/all' ) { - history.replace( { postType: TEMPLATE_PART_POST_TYPE } ); - } - - if ( path === '/page' ) { - history.replace( { - postType: 'page', - ...rest, - } ); - } - - if ( path === '/wp_template' ) { - history.replace( { - postType: TEMPLATE_POST_TYPE, - ...rest, - } ); - } - - if ( path === '/patterns' ) { - history.replace( { - postType: - categoryType === TEMPLATE_PART_POST_TYPE - ? TEMPLATE_PART_POST_TYPE - : PATTERN_TYPES.user, - ...rest, - } ); - } - - if ( path === '/navigation' ) { - history.replace( { - postType: NAVIGATION_POST_TYPE, - ...rest, - } ); - } - }, [ history, params ] ); -} - -export default function useActiveRoute() { - const { params } = useLocation(); - useRedirectOldPaths(); - const routes = useSelect( ( select ) => { - return unlock( select( editSiteStore ) ).getRoutes(); - }, [] ); - return useMemo( () => { - const matchedRoute = routes.find( ( route ) => route.match( params ) ); - if ( ! matchedRoute ) { - return { - key: 404, - areas: {}, - widths: {}, - }; - } - - return { - name: matchedRoute.name, - areas: matchedRoute.areas, - widths: matchedRoute.widths, - }; - }, [ routes, params ] ); -} diff --git a/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js b/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js index d87737c55326c6..ca7bbf2fa73220 100644 --- a/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js +++ b/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js @@ -59,10 +59,9 @@ export default function DeleteCategoryMenuItem( { category, onClose } ) { ); onClose?.(); - history.push( { - postType: PATTERN_TYPES.user, - categoryId: PATTERN_DEFAULT_CATEGORY, - } ); + history.navigate( + `/pattern?categoryId=${ PATTERN_DEFAULT_CATEGORY }` + ); } catch ( error ) { const errorMessage = error.message && error.code !== 'unknown_error' diff --git a/packages/edit-site/src/components/page-patterns/fields.js b/packages/edit-site/src/components/page-patterns/fields.js index e016dca6cd8557..60e37844b2edb1 100644 --- a/packages/edit-site/src/components/page-patterns/fields.js +++ b/packages/edit-site/src/components/page-patterns/fields.js @@ -21,6 +21,7 @@ import { import { Icon, lockSmall } from '@wordpress/icons'; import { parse } from '@wordpress/blocks'; import { decodeEntities } from '@wordpress/html-entities'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies @@ -32,10 +33,10 @@ import { OPERATOR_IS, } from '../../utils/constants'; import { unlock } from '../../lock-unlock'; -import { useLink } from '../routes/link'; import { useAddedBy } from '../page-templates/hooks'; import { defaultGetTitle } from './search-items'; +const { useLink } = unlock( routerPrivateApis ); const { useGlobalStyle } = unlock( blockEditorPrivateApis ); function PreviewWrapper( { item, onClick, ariaDescribedBy, children } ) { @@ -59,11 +60,11 @@ function PreviewField( { item } ) { const isUserPattern = item.type === PATTERN_TYPES.user; const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE; const [ backgroundColor ] = useGlobalStyle( 'color.background' ); - const { onClick } = useLink( { - postType: item.type, - postId: isUserPattern || isTemplatePart ? item.id : item.name, - canvas: 'edit', - } ); + const { onClick } = useLink( + `/${ item.type }/${ + isUserPattern || isTemplatePart ? item.id : item.name + }?canvas=edit` + ); const blocks = useMemo( () => { return ( item.blocks ?? @@ -114,11 +115,11 @@ export const previewField = { function TitleField( { item } ) { const isUserPattern = item.type === PATTERN_TYPES.user; const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE; - const { onClick } = useLink( { - postType: item.type, - postId: isUserPattern || isTemplatePart ? item.id : item.name, - canvas: 'edit', - } ); + const { onClick } = useLink( + `/${ item.type }/${ + isUserPattern || isTemplatePart ? item.id : item.name + }?canvas=edit` + ); const title = decodeEntities( defaultGetTitle( item ) ); return ( <HStack alignment="center" justify="flex-start" spacing={ 2 }> diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index 69ebf66093806a..b6753334887573 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -72,17 +72,16 @@ const DEFAULT_VIEW = { export default function DataviewsPatterns() { const { - params: { postType, categoryId: categoryIdFromURL }, + query: { postType = 'wp_block', categoryId: categoryIdFromURL }, } = useLocation(); - const type = postType || PATTERN_TYPES.user; const categoryId = categoryIdFromURL || PATTERN_DEFAULT_CATEGORY; const [ view, setView ] = useState( DEFAULT_VIEW ); const previousCategoryId = usePrevious( categoryId ); - const previousPostType = usePrevious( type ); + const previousPostType = usePrevious( postType ); const viewSyncStatus = view.filters?.find( ( { field } ) => field === 'sync-status' )?.value; - const { patterns, isResolving } = usePatterns( type, categoryId, { + const { patterns, isResolving } = usePatterns( postType, categoryId, { search: view.search, syncStatus: viewSyncStatus, } ); @@ -108,9 +107,9 @@ export default function DataviewsPatterns() { const fields = useMemo( () => { const _fields = [ previewField, titleField ]; - if ( type === PATTERN_TYPES.user ) { + if ( postType === PATTERN_TYPES.user ) { _fields.push( patternStatusField ); - } else if ( type === TEMPLATE_PART_POST_TYPE ) { + } else if ( postType === TEMPLATE_PART_POST_TYPE ) { _fields.push( { ...templatePartAuthorField, elements: authors, @@ -118,24 +117,27 @@ export default function DataviewsPatterns() { } return _fields; - }, [ type, authors ] ); + }, [ postType, authors ] ); // Reset the page number when the category changes. useEffect( () => { - if ( previousCategoryId !== categoryId || previousPostType !== type ) { + if ( + previousCategoryId !== categoryId || + previousPostType !== postType + ) { setView( ( prevView ) => ( { ...prevView, page: 1 } ) ); } - }, [ categoryId, previousCategoryId, previousPostType, type ] ); + }, [ categoryId, previousCategoryId, previousPostType, postType ] ); const { data, paginationInfo } = useMemo( () => { // Search is managed server-side as well as filters for patterns. // However, the author filter in template parts is done client-side. const viewWithoutFilters = { ...view }; delete viewWithoutFilters.search; - if ( type !== TEMPLATE_PART_POST_TYPE ) { + if ( postType !== TEMPLATE_PART_POST_TYPE ) { viewWithoutFilters.filters = []; } return filterSortAndPaginate( patterns, viewWithoutFilters, fields ); - }, [ patterns, view, fields, type ] ); + }, [ patterns, view, fields, postType ] ); const dataWithPermissions = useAugmentPatternsWithPermissions( data ); @@ -150,11 +152,11 @@ export default function DataviewsPatterns() { const editAction = useEditPostAction(); const actions = useMemo( () => { - if ( type === TEMPLATE_PART_POST_TYPE ) { + if ( postType === TEMPLATE_PART_POST_TYPE ) { return [ editAction, ...templatePartActions ].filter( Boolean ); } return [ editAction, ...patternActions ].filter( Boolean ); - }, [ editAction, type, templatePartActions, patternActions ] ); + }, [ editAction, postType, templatePartActions, patternActions ] ); const id = useId(); const settings = usePatternSettings(); // Wrap everything in a block editor provider. @@ -169,7 +171,7 @@ export default function DataviewsPatterns() { > <PatternsHeader categoryId={ categoryId } - type={ type } + type={ postType } titleId={ `${ id }-title` } descriptionId={ `${ id }-description` } /> diff --git a/packages/edit-site/src/components/page-templates/fields.js b/packages/edit-site/src/components/page-templates/fields.js index 69e0596bf49d47..35d7b9714d5be1 100644 --- a/packages/edit-site/src/components/page-templates/fields.js +++ b/packages/edit-site/src/components/page-templates/fields.js @@ -16,16 +16,16 @@ import { privateApis as blockEditorPrivateApis, } from '@wordpress/block-editor'; import { EditorProvider } from '@wordpress/editor'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies */ -import { default as Link, useLink } from '../routes/link'; import { useAddedBy } from './hooks'; - import usePatternSettings from '../page-patterns/use-pattern-settings'; import { unlock } from '../../lock-unlock'; +const { useLink, Link } = unlock( routerPrivateApis ); const { useGlobalStyle } = unlock( blockEditorPrivateApis ); function PreviewField( { item } ) { @@ -34,11 +34,7 @@ function PreviewField( { item } ) { const blocks = useMemo( () => { return parse( item.content.raw ); }, [ item.content.raw ] ); - const { onClick } = useLink( { - postId: item.id, - postType: item.type, - canvas: 'edit', - } ); + const { onClick } = useLink( `/${ item.type }/${ item.id }?canvas=edit` ); const isEmpty = ! blocks?.length; // Wrap everything in a block editor provider to ensure 'styles' that are needed @@ -80,15 +76,8 @@ export const previewField = { }; function TitleField( { item } ) { - const linkProps = { - params: { - postId: item.id, - postType: item.type, - canvas: 'edit', - }, - }; return ( - <Link { ...linkProps }> + <Link to={ `/${ item.type }/${ item.id }?canvas=edit` }> { decodeEntities( item.title?.rendered ) || __( '(no title)' ) } </Link> ); diff --git a/packages/edit-site/src/components/page-templates/index.js b/packages/edit-site/src/components/page-templates/index.js index ea026ca53566e8..828867e6f283de 100644 --- a/packages/edit-site/src/components/page-templates/index.js +++ b/packages/edit-site/src/components/page-templates/index.js @@ -7,6 +7,7 @@ import { privateApis as corePrivateApis } from '@wordpress/core-data'; import { DataViews, filterSortAndPaginate } from '@wordpress/dataviews'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; +import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies @@ -93,8 +94,8 @@ const DEFAULT_VIEW = { }; export default function PageTemplates() { - const { params } = useLocation(); - const { activeView = 'all', layout, postId } = params; + const { path, query } = useLocation(); + const { activeView = 'all', layout, postId } = query; const [ selection, setSelection ] = useState( [ postId ] ); const defaultView = useMemo( () => { @@ -118,8 +119,10 @@ export default function PageTemplates() { }, [ layout, activeView ] ); const [ view, setView ] = useState( defaultView ); useEffect( () => { + const usedType = layout ?? DEFAULT_VIEW.type; setView( ( currentView ) => ( { ...currentView, + type: usedType, filters: activeView !== 'all' ? [ @@ -131,7 +134,7 @@ export default function PageTemplates() { ] : [], } ) ); - }, [ activeView ] ); + }, [ activeView, layout ] ); const { records, isResolving: isLoadingData } = useEntityRecordsWithPermissions( 'postType', TEMPLATE_POST_TYPE, { @@ -142,13 +145,14 @@ export default function PageTemplates() { ( items ) => { setSelection( items ); if ( view?.type === LAYOUT_LIST ) { - history.push( { - ...params, - postId: items.length === 1 ? items[ 0 ] : undefined, - } ); + history.navigate( + addQueryArgs( path, { + postId: items.length === 1 ? items[ 0 ] : undefined, + } ) + ); } }, - [ history, params, view?.type ] + [ history, path, view?.type ] ); const authors = useMemo( () => { @@ -195,15 +199,16 @@ export default function PageTemplates() { const onChangeView = useCallback( ( newView ) => { if ( newView.type !== view.type ) { - history.push( { - ...params, - layout: newView.type, - } ); + history.navigate( + addQueryArgs( path, { + layout: newView.type, + } ) + ); } setView( newView ); }, - [ view.type, setView, history, params ] + [ view.type, setView, history, path ] ); return ( diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 975809b2ad6106..d58ddbe50758c7 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -13,6 +13,8 @@ import { DataViews, filterSortAndPaginate } from '@wordpress/dataviews'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { __ } from '@wordpress/i18n'; import { drawerRight } from '@wordpress/icons'; +import { usePrevious } from '@wordpress/compose'; +import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies @@ -31,7 +33,6 @@ import { import AddNewPostModal from '../add-new-post'; import { unlock } from '../../lock-unlock'; import { useEditPostAction } from '../dataviews-actions'; -import { usePrevious } from '@wordpress/compose'; const { usePostActions, usePostFields } = unlock( editorPrivateApis ); const { useLocation, useHistory } = unlock( routerPrivateApis ); @@ -70,7 +71,8 @@ const getCustomView = ( editedEntityRecord ) => { */ function useView( postType ) { const { - params: { activeView = 'all', isCustom = 'false', layout }, + path, + query: { activeView = 'all', isCustom = 'false', layout }, } = useLocation(); const history = useHistory(); @@ -112,16 +114,15 @@ function useView( postType ) { const setViewWithUrlUpdate = useCallback( ( newView ) => { - const { params } = history.getLocationWithParams(); - - if ( newView.type === LAYOUT_LIST && ! params?.layout ) { + if ( newView.type === LAYOUT_LIST && ! layout ) { // Skip updating the layout URL param if // it is not present and the newView.type is LAYOUT_LIST. - } else if ( newView.type !== params?.layout ) { - history.push( { - ...params, - layout: newView.type, - } ); + } else if ( newView.type !== layout ) { + history.navigate( + addQueryArgs( path, { + layout: newView.type, + } ) + ); } setView( newView ); @@ -137,7 +138,14 @@ function useView( postType ) { ); } }, - [ history, isCustom, editEntityRecord, editedEntityRecord?.id ] + [ + history, + isCustom, + editEntityRecord, + editedEntityRecord?.id, + layout, + path, + ] ); // When layout URL param changes, update the view type @@ -186,20 +194,20 @@ export default function PostList( { postType } ) { quickEdit = false, isCustom, activeView = 'all', - } = location.params; + } = location.query; const [ selection, setSelection ] = useState( postId?.split( ',' ) ?? [] ); const onChangeSelection = useCallback( ( items ) => { setSelection( items ); - const { params } = history.getLocationWithParams(); - if ( ( params.isCustom ?? 'false' ) === 'false' ) { - history.push( { - ...params, - postId: items.join( ',' ), - } ); + if ( ( location.query.isCustom ?? 'false' ) === 'false' ) { + history.navigate( + addQueryArgs( location.path, { + postId: items.join( ',' ), + } ) + ); } }, - [ history ] + [ location.path, location.query.isCustom, history ] ); const getActiveViewFilters = ( views, match ) => { @@ -311,12 +319,13 @@ export default function PostList( { postType } ) { useEffect( () => { if ( postIdWasDeleted ) { - history.push( { - ...history.getLocationWithParams().params, - postId: undefined, - } ); + history.navigate( + addQueryArgs( location.path, { + postId: undefined, + } ) + ); } - }, [ postIdWasDeleted, history ] ); + }, [ history, postIdWasDeleted, location.path ] ); const paginationInfo = useMemo( () => ( { @@ -355,11 +364,7 @@ export default function PostList( { postType } ) { const openModal = () => setShowAddPostModal( true ); const closeModal = () => setShowAddPostModal( false ); const handleNewPage = ( { type, id } ) => { - history.push( { - postId: id, - postType: type, - canvas: 'edit', - } ); + history.navigate( `/${ type }/${ id }?canvas=edit` ); closeModal(); }; @@ -401,11 +406,7 @@ export default function PostList( { postType } ) { onChangeSelection={ onChangeSelection } isItemClickable={ ( item ) => item.status !== 'trash' } onClickItem={ ( { id } ) => { - history.push( { - postId: id, - postType, - canvas: 'edit', - } ); + history.navigate( `/${ postType }/${ id }?canvas=edit` ); } } getItemId={ getItemId } defaultLayouts={ defaultLayouts } @@ -419,10 +420,11 @@ export default function PostList( { postType } ) { icon={ drawerRight } label={ __( 'Details' ) } onClick={ () => { - history.push( { - ...location.params, - quickEdit: quickEdit ? undefined : true, - } ); + history.navigate( + addQueryArgs( location.path, { + quickEdit: quickEdit ? undefined : true, + } ) + ); } } /> ) diff --git a/packages/edit-site/src/components/posts-app-routes/home.js b/packages/edit-site/src/components/posts-app-routes/home.js deleted file mode 100644 index ec99cbd8899f1d..00000000000000 --- a/packages/edit-site/src/components/posts-app-routes/home.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * WordPress dependencies - */ -import { privateApis as routerPrivateApis } from '@wordpress/router'; - -/** - * Internal dependencies - */ -import Editor from '../editor'; -import SidebarNavigationScreenMain from '../sidebar-navigation-screen-main'; -import { unlock } from '../../lock-unlock'; - -const { useLocation } = unlock( routerPrivateApis ); - -function HomeMobileView() { - const { params = {} } = useLocation(); - const { canvas = 'view' } = params; - - return canvas === 'edit' ? ( - <Editor isPostsList /> - ) : ( - <SidebarNavigationScreenMain /> - ); -} - -export const homeRoute = { - name: 'home', - match: () => { - return true; - }, - areas: { - sidebar: <SidebarNavigationScreenMain />, - preview: <Editor isPostsList />, - mobile: HomeMobileView, - }, -}; diff --git a/packages/edit-site/src/components/posts-app-routes/index.js b/packages/edit-site/src/components/posts-app-routes/index.js index e850bbd382200d..3919ea3930d073 100644 --- a/packages/edit-site/src/components/posts-app-routes/index.js +++ b/packages/edit-site/src/components/posts-app-routes/index.js @@ -9,21 +9,10 @@ import { useEffect } from '@wordpress/element'; */ import { unlock } from '../../lock-unlock'; import { store as siteEditorStore } from '../../store'; -import { homeRoute } from './home'; -import { postsListViewQuickEditRoute } from './posts-list-view-quick-edit'; -import { postsListViewRoute } from './posts-list-view'; -import { postsViewQuickEditRoute } from './posts-view-quick-edit'; -import { postsViewRoute } from './posts-view'; -import { postsEditRoute } from './posts-edit'; +import { postsRoute } from './posts'; +import { postItemRoute } from './post-item'; -const routes = [ - postsListViewQuickEditRoute, - postsListViewRoute, - postsViewQuickEditRoute, - postsViewRoute, - postsEditRoute, - homeRoute, -]; +const routes = [ postItemRoute, postsRoute ]; export function useRegisterPostsAppRoutes() { const registry = useRegistry(); diff --git a/packages/edit-site/src/components/posts-app-routes/posts-edit.js b/packages/edit-site/src/components/posts-app-routes/post-item.js similarity index 62% rename from packages/edit-site/src/components/posts-app-routes/posts-edit.js rename to packages/edit-site/src/components/posts-app-routes/post-item.js index d3958245595416..54131814f1ae22 100644 --- a/packages/edit-site/src/components/posts-app-routes/posts-edit.js +++ b/packages/edit-site/src/components/posts-app-routes/post-item.js @@ -6,25 +6,21 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import PostList from '../post-list'; +import Editor from '../editor'; import DataViewsSidebarContent from '../sidebar-dataviews'; import SidebarNavigationScreen from '../sidebar-navigation-screen'; -import Editor from '../editor'; -export const postsEditRoute = { - name: 'posts-edit', - match: ( params ) => { - return params.postType === 'post' && params.canvas === 'edit'; - }, +export const postItemRoute = { + name: 'post-item', + path: '/post/:postId', areas: { sidebar: ( <SidebarNavigationScreen title={ __( 'Posts' ) } isRoot - content={ <DataViewsSidebarContent /> } + content={ <DataViewsSidebarContent postType="post" /> } /> ), - content: <PostList postType="post" />, mobile: <Editor isPostsList />, preview: <Editor isPostsList />, }, diff --git a/packages/edit-site/src/components/posts-app-routes/posts-list-view-quick-edit.js b/packages/edit-site/src/components/posts-app-routes/posts-list-view-quick-edit.js deleted file mode 100644 index d2434b390ffd9f..00000000000000 --- a/packages/edit-site/src/components/posts-app-routes/posts-list-view-quick-edit.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { privateApis as routerPrivateApis } from '@wordpress/router'; - -/** - * Internal dependencies - */ -import PostList from '../post-list'; -import DataViewsSidebarContent from '../sidebar-dataviews'; -import SidebarNavigationScreen from '../sidebar-navigation-screen'; -import { unlock } from '../../lock-unlock'; -import { PostEdit } from '../post-edit'; -import Editor from '../editor'; - -const { useLocation } = unlock( routerPrivateApis ); - -function PostQuickEdit() { - const { params } = useLocation(); - return <PostEdit postType="post" postId={ params.postId } />; -} - -export const postsListViewQuickEditRoute = { - name: 'posts-list-view-quick-edit', - match: ( params ) => { - return ( - params.isCustom !== 'true' && - ( params.layout ?? 'list' ) === 'list' && - !! params.quickEdit && - params.postType === 'post' && - params.canvas !== 'edit' - ); - }, - areas: { - sidebar: ( - <SidebarNavigationScreen - title={ __( 'Posts' ) } - isRoot - content={ <DataViewsSidebarContent /> } - /> - ), - content: <PostList postType="post" />, - mobile: <PostList postType="post" />, - preview: <Editor />, - edit: <PostQuickEdit />, - }, - widths: { - content: 380, - edit: 380, - }, -}; diff --git a/packages/edit-site/src/components/posts-app-routes/posts-list-view.js b/packages/edit-site/src/components/posts-app-routes/posts-list-view.js deleted file mode 100644 index 68aa86c7fb2392..00000000000000 --- a/packages/edit-site/src/components/posts-app-routes/posts-list-view.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import PostList from '../post-list'; -import DataViewsSidebarContent from '../sidebar-dataviews'; -import SidebarNavigationScreen from '../sidebar-navigation-screen'; -import Editor from '../editor'; - -export const postsListViewRoute = { - name: 'posts-list-view', - match: ( params ) => { - return ( - params.isCustom !== 'true' && - ( params.layout ?? 'list' ) === 'list' && - ! params.quickEdit && - params.postType === 'post' && - params.canvas !== 'edit' - ); - }, - areas: { - sidebar: ( - <SidebarNavigationScreen - title={ __( 'Posts' ) } - isRoot - content={ <DataViewsSidebarContent /> } - /> - ), - content: <PostList postType="post" />, - preview: <Editor isPostsList />, - mobile: <PostList postType="post" />, - }, - widths: { - content: 380, - }, -}; diff --git a/packages/edit-site/src/components/posts-app-routes/posts-view-quick-edit.js b/packages/edit-site/src/components/posts-app-routes/posts-view-quick-edit.js deleted file mode 100644 index 52e6f9a2d26ef6..00000000000000 --- a/packages/edit-site/src/components/posts-app-routes/posts-view-quick-edit.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { privateApis as routerPrivateApis } from '@wordpress/router'; - -/** - * Internal dependencies - */ -import PostList from '../post-list'; -import DataViewsSidebarContent from '../sidebar-dataviews'; -import SidebarNavigationScreen from '../sidebar-navigation-screen'; -import { unlock } from '../../lock-unlock'; -import { PostEdit } from '../post-edit'; - -const { useLocation } = unlock( routerPrivateApis ); - -function PostQuickEdit() { - const { params } = useLocation(); - return <PostEdit postType="post" postId={ params.postId } />; -} - -export const postsViewQuickEditRoute = { - name: 'posts-view-quick-edit', - match: ( params ) => { - return ( - ( params.isCustom === 'true' || - ( params.layout ?? 'list' ) !== 'list' ) && - !! params.quickEdit && - params.postType === 'post' && - params.canvas !== 'edit' - ); - }, - areas: { - sidebar: ( - <SidebarNavigationScreen - title={ __( 'Posts' ) } - isRoot - content={ <DataViewsSidebarContent /> } - /> - ), - content: <PostList postType="post" />, - mobile: <PostList postType="post" />, - edit: <PostQuickEdit />, - }, - widths: { - edit: 380, - }, -}; diff --git a/packages/edit-site/src/components/posts-app-routes/posts-view.js b/packages/edit-site/src/components/posts-app-routes/posts-view.js deleted file mode 100644 index 6559991475d278..00000000000000 --- a/packages/edit-site/src/components/posts-app-routes/posts-view.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import PostList from '../post-list'; -import DataViewsSidebarContent from '../sidebar-dataviews'; -import SidebarNavigationScreen from '../sidebar-navigation-screen'; - -export const postsViewRoute = { - name: 'posts-view', - match: ( params ) => { - return ( - ( params.isCustom === 'true' || - ( params.layout ?? 'list' ) !== 'list' ) && - ! params.quickEdit && - params.postType === 'post' && - params.canvas !== 'edit' - ); - }, - areas: { - sidebar: ( - <SidebarNavigationScreen - title={ __( 'Posts' ) } - isRoot - content={ <DataViewsSidebarContent /> } - /> - ), - content: <PostList postType="post" />, - mobile: <PostList postType="post" />, - }, -}; diff --git a/packages/edit-site/src/components/posts-app-routes/posts.js b/packages/edit-site/src/components/posts-app-routes/posts.js new file mode 100644 index 00000000000000..80af8a75fbc800 --- /dev/null +++ b/packages/edit-site/src/components/posts-app-routes/posts.js @@ -0,0 +1,66 @@ +/** + * WordPress dependencies + */ +import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import Editor from '../editor'; +import SidebarNavigationScreen from '../sidebar-navigation-screen'; +import DataViewsSidebarContent from '../sidebar-dataviews'; +import PostList from '../post-list'; +import { unlock } from '../../lock-unlock'; +import { PostEdit } from '../post-edit'; + +const { useLocation } = unlock( routerPrivateApis ); + +function MobilePostsView() { + const { query = {} } = useLocation(); + const { canvas = 'view' } = query; + + return canvas === 'edit' ? <Editor /> : <PostList postType="post" />; +} + +export const postsRoute = { + name: 'posts', + path: '/', + areas: { + sidebar: ( + <SidebarNavigationScreen + title={ __( 'Posts' ) } + isRoot + content={ <DataViewsSidebarContent postType="post" /> } + /> + ), + content: <PostList postType="post" />, + preview( { query } ) { + const isListView = + ( query.layout === 'list' || ! query.layout ) && + query.isCustom !== 'true'; + return isListView ? <Editor isPostsList /> : undefined; + }, + mobile: <MobilePostsView />, + edit( { query } ) { + const hasQuickEdit = + ( query.layout ?? 'list' ) === 'list' && !! query.quickEdit; + return hasQuickEdit ? ( + <PostEdit postType="post" postId={ query.postId } /> + ) : undefined; + }, + }, + widths: { + content( { query } ) { + const isListView = + ( query.layout === 'list' || ! query.layout ) && + query.isCustom !== 'true'; + return isListView ? 380 : undefined; + }, + edit( { query } ) { + const hasQuickEdit = + ( query.layout ?? 'list' ) === 'list' && !! query.quickEdit; + return hasQuickEdit ? 380 : undefined; + }, + }, +}; diff --git a/packages/edit-site/src/components/posts-app/index.js b/packages/edit-site/src/components/posts-app/index.js index e6eb90c1680019..ab8cfab99f7628 100644 --- a/packages/edit-site/src/components/posts-app/index.js +++ b/packages/edit-site/src/components/posts-app/index.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -9,20 +10,18 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; import Layout from '../layout'; import { useRegisterPostsAppRoutes } from '../posts-app-routes'; import { unlock } from '../../lock-unlock'; -import useActiveRoute from '../layout/router'; +import { store as editSiteStore } from '../../store'; const { RouterProvider } = unlock( routerPrivateApis ); -function PostsLayout() { - useRegisterPostsAppRoutes(); - const route = useActiveRoute(); - return <Layout route={ route } />; -} - export default function PostsApp() { + useRegisterPostsAppRoutes(); + const routes = useSelect( ( select ) => { + return unlock( select( editSiteStore ) ).getRoutes(); + }, [] ); return ( - <RouterProvider> - <PostsLayout /> + <RouterProvider routes={ routes } pathArg="p"> + <Layout /> </RouterProvider> ); } diff --git a/packages/edit-site/src/components/resizable-frame/index.js b/packages/edit-site/src/components/resizable-frame/index.js index 95ccfe4fdd966f..99f650971112fb 100644 --- a/packages/edit-site/src/components/resizable-frame/index.js +++ b/packages/edit-site/src/components/resizable-frame/index.js @@ -20,6 +20,7 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; * Internal dependencies */ import { unlock } from '../../lock-unlock'; +import { addQueryArgs } from '@wordpress/url'; const { useLocation, useHistory } = unlock( routerPrivateApis ); @@ -88,8 +89,8 @@ function ResizableFrame( { innerContentStyle, } ) { const history = useHistory(); - const { params } = useLocation(); - const { canvas = 'view' } = params; + const { path, query } = useLocation(); + const { canvas = 'view' } = query; const disableMotion = useReducedMotion(); const [ frameSize, setFrameSize ] = useState( INITIAL_FRAME_SIZE ); // The width of the resizable frame when a new resize gesture starts. @@ -158,12 +159,10 @@ function ResizableFrame( { setFrameSize( INITIAL_FRAME_SIZE ); } else { // Trigger full screen if the frame is resized far enough to the left. - history.push( - { - ...params, + history.navigate( + addQueryArgs( path, { canvas: 'edit', - }, - undefined, + } ), { transition: 'canvas-mode-edit-transition', } diff --git a/packages/edit-site/src/components/routes/link.js b/packages/edit-site/src/components/routes/link.js deleted file mode 100644 index a34b37943a0799..00000000000000 --- a/packages/edit-site/src/components/routes/link.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * WordPress dependencies - */ -import { addQueryArgs, getQueryArgs, removeQueryArgs } from '@wordpress/url'; -import { privateApis as routerPrivateApis } from '@wordpress/router'; - -/** - * Internal dependencies - */ -import { unlock } from '../../lock-unlock'; -import { - isPreviewingTheme, - currentlyPreviewingTheme, -} from '../../utils/is-previewing-theme'; - -const { useHistory } = unlock( routerPrivateApis ); - -export function useLink( params, state, shouldReplace = false ) { - const history = useHistory(); - function onClick( event ) { - event?.preventDefault(); - - if ( shouldReplace ) { - history.replace( params, state ); - } else { - history.push( params, state ); - } - } - - const currentArgs = getQueryArgs( window.location.href ); - const currentUrlWithoutArgs = removeQueryArgs( - window.location.href, - ...Object.keys( currentArgs ) - ); - - let extraParams = {}; - if ( isPreviewingTheme() ) { - extraParams = { - wp_theme_preview: currentlyPreviewingTheme(), - }; - } - - const newUrl = addQueryArgs( currentUrlWithoutArgs, { - ...params, - ...extraParams, - } ); - - return { - href: newUrl, - onClick, - }; -} - -export default function Link( { - params = {}, - state, - replace: shouldReplace = false, - children, - ...props -} ) { - const { href, onClick } = useLink( params, state, shouldReplace ); - - return ( - <a href={ href } onClick={ onClick } { ...props }> - { children } - </a> - ); -} diff --git a/packages/edit-site/src/components/save-panel/index.js b/packages/edit-site/src/components/save-panel/index.js index b77e5a9a1a10ba..81a0f99557df07 100644 --- a/packages/edit-site/src/components/save-panel/index.js +++ b/packages/edit-site/src/components/save-panel/index.js @@ -90,8 +90,8 @@ const _EntitiesSavedStates = ( { onClose, renderDialog = undefined } ) => { }; export default function SavePanel() { - const { params } = useLocation(); - const { canvas = 'view' } = params; + const { query } = useLocation(); + const { canvas = 'view' } = query; const { isSaveViewOpen, isDirty, isSaving } = useSelect( ( select ) => { const { __experimentalGetDirtyEntityRecords, diff --git a/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js b/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js index 62956ccd18960d..815de181a9dde0 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js +++ b/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js @@ -14,6 +14,7 @@ import { store as coreStore } from '@wordpress/core-data'; import { useState } from '@wordpress/element'; import { plus } from '@wordpress/icons'; import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies @@ -22,10 +23,11 @@ import SidebarNavigationItem from '../sidebar-navigation-item'; import { useDefaultViews } from './default-views'; import { unlock } from '../../lock-unlock'; -const { useHistory } = unlock( routerPrivateApis ); +const { useLocation, useHistory } = unlock( routerPrivateApis ); function AddNewItemModalContent( { type, setIsAdding } ) { const history = useHistory(); + const { path } = useLocation(); const { saveEntityRecord } = useDispatch( coreStore ); const [ title, setTitle ] = useState( '' ); const [ isSaving, setIsSaving ] = useState( false ); @@ -64,14 +66,12 @@ function AddNewItemModalContent( { type, setIsAdding } ) { content: JSON.stringify( defaultViews[ 0 ].view ), } ); - const { - params: { postType }, - } = history.getLocationWithParams(); - history.push( { - postType, - activeView: savedRecord.id, - isCustom: 'true', - } ); + history.navigate( + addQueryArgs( path, { + activeView: savedRecord.id, + isCustom: 'true', + } ) + ); setIsSaving( false ); setIsAdding( false ); } } diff --git a/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js b/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js index 1e12d6706d81b5..b98f8b80938d68 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js +++ b/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js @@ -9,11 +9,11 @@ import clsx from 'clsx'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { __experimentalHStack as HStack } from '@wordpress/components'; import { VIEW_LAYOUTS } from '@wordpress/dataviews'; +import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies */ -import { useLink } from '../routes/link'; import SidebarNavigationItem from '../sidebar-navigation-item'; import { unlock } from '../../lock-unlock'; const { useLocation } = unlock( routerPrivateApis ); @@ -28,9 +28,7 @@ export default function DataViewItem( { isCustom, suffix, } ) { - const { - params: { postType }, - } = useLocation(); + const { path } = useLocation(); const iconToUse = icon || VIEW_LAYOUTS.find( ( v ) => v.type === type ).icon; @@ -39,12 +37,11 @@ export default function DataViewItem( { if ( activeView === 'all' ) { activeView = undefined; } - const linkInfo = useLink( { - postType, + const query = { layout: type, activeView, isCustom: isCustom ? 'true' : undefined, - } ); + }; return ( <HStack justify="flex-start" @@ -54,7 +51,7 @@ export default function DataViewItem( { > <SidebarNavigationItem icon={ iconToUse } - { ...linkInfo } + to={ addQueryArgs( path, query ) } aria-current={ isActive ? 'true' : undefined } > { title } diff --git a/packages/edit-site/src/components/sidebar-dataviews/index.js b/packages/edit-site/src/components/sidebar-dataviews/index.js index 86420c4eec1d1f..410767650c6f36 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/index.js +++ b/packages/edit-site/src/components/sidebar-dataviews/index.js @@ -14,9 +14,9 @@ import CustomDataViewsList from './custom-dataviews-list'; const { useLocation } = unlock( routerPrivateApis ); -export default function DataViewsSidebarContent() { +export default function DataViewsSidebarContent( { postType } ) { const { - params: { postType, activeView = 'all', isCustom = 'false' }, + query: { activeView = 'all', isCustom = 'false' }, } = useLocation(); const defaultViews = useDefaultViews( { postType } ); if ( ! postType ) { diff --git a/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js b/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js index 342fb1b5db52d2..980f20c49821b0 100644 --- a/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js +++ b/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js @@ -9,6 +9,7 @@ import { Button, privateApis as componentsPrivateApis, } from '@wordpress/components'; +import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies @@ -21,7 +22,6 @@ import { STYLE_BOOK_COLOR_GROUPS } from '../style-book/constants'; const { useLocation, useHistory } = unlock( routerPrivateApis ); const { Menu } = unlock( componentsPrivateApis ); -const GLOBAL_STYLES_PATH_PREFIX = '/wp_global_styles'; const GlobalStylesPageActions = ( { isStyleBookOpened, @@ -63,28 +63,23 @@ const GlobalStylesPageActions = ( { }; export default function GlobalStylesUIWrapper() { - const { params } = useLocation(); + const { path, query } = useLocation(); const history = useHistory(); - const { canvas = 'view' } = params; + const { canvas = 'view' } = query; const [ isStyleBookOpened, setIsStyleBookOpened ] = useState( false ); const isMobileViewport = useViewportMatch( 'medium', '<' ); - const pathWithPrefix = params.path; - const [ path, onPathChange ] = useMemo( () => { - const processedPath = pathWithPrefix.substring( - GLOBAL_STYLES_PATH_PREFIX.length - ); + const [ section, onChangeSection ] = useMemo( () => { return [ - processedPath ? processedPath : '/', - ( newPath ) => { - history.push( { - path: - ! newPath || newPath === '/' - ? GLOBAL_STYLES_PATH_PREFIX - : `${ GLOBAL_STYLES_PATH_PREFIX }${ newPath }`, - } ); + query.section ?? '/', + ( updatedSection ) => { + history.navigate( + addQueryArgs( path, { + section: updatedSection, + } ) + ); }, ]; - }, [ pathWithPrefix, history ] ); + }, [ path, query.section, history ] ); return ( <> @@ -100,7 +95,10 @@ export default function GlobalStylesUIWrapper() { className="edit-site-styles" title={ __( 'Styles' ) } > - <GlobalStylesUI path={ path } onPathChange={ onPathChange } /> + <GlobalStylesUI + path={ section } + onPathChange={ onChangeSection } + /> </Page> { canvas === 'view' && isStyleBookOpened && ( <StyleBook @@ -111,17 +109,13 @@ export default function GlobalStylesUIWrapper() { // Match '/blocks/core%2Fbutton' and // '/blocks/core%2Fbutton/typography', but not // '/blocks/core%2Fbuttons'. - path === - `/wp_global_styles/blocks/${ encodeURIComponent( - blockName - ) }` || - path.startsWith( - `/wp_global_styles/blocks/${ encodeURIComponent( - blockName - ) }/` + section === + `/blocks/${ encodeURIComponent( blockName ) }` || + section.startsWith( + `/blocks/${ encodeURIComponent( blockName ) }/` ) } - path={ path } + path={ section } onSelect={ ( blockName ) => { if ( STYLE_BOOK_COLOR_GROUPS.find( @@ -129,17 +123,17 @@ export default function GlobalStylesUIWrapper() { ) ) { // Go to color palettes Global Styles. - onPathChange( '/colors/palette' ); + onChangeSection( '/colors/palette' ); return; } if ( blockName === 'typography' ) { // Go to typography Global Styles. - onPathChange( '/typography' ); + onChangeSection( '/typography' ); return; } // Now go to the selected block. - onPathChange( + onChangeSection( `/blocks/${ encodeURIComponent( blockName ) }` ); } } diff --git a/packages/edit-site/src/components/sidebar-navigation-item/index.js b/packages/edit-site/src/components/sidebar-navigation-item/index.js index 80f06d7e93133b..4bde94dcbbeb4d 100644 --- a/packages/edit-site/src/components/sidebar-navigation-item/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-item/index.js @@ -22,7 +22,7 @@ import { useContext } from '@wordpress/element'; import { unlock } from '../../lock-unlock'; import { SidebarNavigationContext } from '../sidebar'; -const { useHistory } = unlock( routerPrivateApis ); +const { useHistory, useLink } = unlock( routerPrivateApis ); export default function SidebarNavigationItem( { className, @@ -30,7 +30,7 @@ export default function SidebarNavigationItem( { withChevron = false, suffix, uid, - params, + to, onClick, children, ...props @@ -42,12 +42,13 @@ export default function SidebarNavigationItem( { if ( onClick ) { onClick( e ); navigate( 'forward' ); - } else if ( params ) { + } else if ( to ) { e.preventDefault(); - history.push( params ); + history.navigate( to ); navigate( 'forward', `[id="${ uid }"]` ); } } + const linkProps = useLink( to ); return ( <Item @@ -56,8 +57,9 @@ export default function SidebarNavigationItem( { { 'with-suffix': ! withChevron && suffix }, className ) } - onClick={ handleClick } id={ uid } + onClick={ handleClick } + href={ to ? linkProps.href : undefined } { ...props } > <HStack justify="flex-start"> diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js index 72671714479ac0..4023ba436b8659 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js @@ -7,6 +7,7 @@ import { store as coreStore } from '@wordpress/core-data'; import { useCallback } from '@wordpress/element'; import { store as preferencesStore } from '@wordpress/preferences'; import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies @@ -22,7 +23,7 @@ import { MainSidebarNavigationContent } from '../sidebar-navigation-screen-main' const { useLocation, useHistory } = unlock( routerPrivateApis ); export function SidebarNavigationItemGlobalStyles( props ) { - const { params } = useLocation(); + const { name } = useLocation(); const hasGlobalStyleVariations = useSelect( ( select ) => !! select( @@ -34,11 +35,9 @@ export function SidebarNavigationItemGlobalStyles( props ) { return ( <SidebarNavigationItem { ...props } - params={ { path: '/wp_global_styles' } } + to="/styles" uid="global-styles-navigation-item" - aria-current={ - params.path && params.path.startsWith( '/wp_global_styles' ) - } + aria-current={ name === 'styles' } /> ); } @@ -47,7 +46,7 @@ export function SidebarNavigationItemGlobalStyles( props ) { export default function SidebarNavigationScreenGlobalStyles() { const history = useHistory(); - const { params } = useLocation(); + const { path } = useLocation(); const { revisions, isLoading: isLoadingRevisions, @@ -60,21 +59,14 @@ export default function SidebarNavigationScreenGlobalStyles() { const { set: setPreference } = useDispatch( preferencesStore ); const openGlobalStyles = useCallback( async () => { - history.push( - { - ...params, - canvas: 'edit', - }, - undefined, - { - transition: 'canvas-mode-edit-transition', - } - ); + history.navigate( addQueryArgs( path, { canvas: 'edit' } ), { + transition: 'canvas-mode-edit-transition', + } ); return Promise.all( [ setPreference( 'core', 'distractionFree', false ), openGeneralSidebar( 'edit-site/global-styles' ), ] ); - }, [ history, params, openGeneralSidebar, setPreference ] ); + }, [ path, history, openGeneralSidebar, setPreference ] ); const openRevisions = useCallback( async () => { await openGlobalStyles(); diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js index 49e60d44047326..1db651631c53d4 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js @@ -15,18 +15,13 @@ import SidebarNavigationItem from '../sidebar-navigation-item'; import { SidebarNavigationItemGlobalStyles } from '../sidebar-navigation-screen-global-styles'; import { unlock } from '../../lock-unlock'; import { store as editSiteStore } from '../../store'; -import { - NAVIGATION_POST_TYPE, - TEMPLATE_POST_TYPE, - PATTERN_TYPES, -} from '../../utils/constants'; export function MainSidebarNavigationContent() { return ( <ItemGroup> <SidebarNavigationItem uid="navigation-navigation-item" - params={ { postType: NAVIGATION_POST_TYPE } } + to="/navigation" withChevron icon={ navigation } > @@ -40,7 +35,7 @@ export function MainSidebarNavigationContent() { </SidebarNavigationItemGlobalStyles> <SidebarNavigationItem uid="page-navigation-item" - params={ { postType: 'page' } } + to="/page" withChevron icon={ page } > @@ -48,7 +43,7 @@ export function MainSidebarNavigationContent() { </SidebarNavigationItem> <SidebarNavigationItem uid="template-navigation-item" - params={ { postType: TEMPLATE_POST_TYPE } } + to="/template" withChevron icon={ layout } > @@ -56,7 +51,7 @@ export function MainSidebarNavigationContent() { </SidebarNavigationItem> <SidebarNavigationItem uid="patterns-navigation-item" - params={ { postType: PATTERN_TYPES.user } } + to="/pattern" withChevron icon={ symbol } > diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/more-menu.js b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/more-menu.js index 6b85e088817edf..a07167413ae119 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/more-menu.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/more-menu.js @@ -58,11 +58,9 @@ export default function ScreenNavigationMoreMenu( props ) { </MenuItem> <MenuItem onClick={ () => { - history.push( { - postId: menuId, - postType: 'wp_navigation', - canvas: 'edit', - } ); + history.navigate( + `/wp_navigation/${ menuId }?canvas=edit` + ); } } > { __( 'Edit' ) } diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/use-navigation-menu-handlers.js b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/use-navigation-menu-handlers.js index 4a7e1deddc6d93..11635c6c6abb12 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/use-navigation-menu-handlers.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/use-navigation-menu-handlers.js @@ -42,7 +42,7 @@ function useDeleteNavigationMenu() { type: 'snackbar', } ); - history.push( { postType: 'wp_navigation' } ); + history.navivate( '/navigation' ); } catch ( error ) { createErrorNotice( sprintf( @@ -165,7 +165,7 @@ function useDuplicateNavigationMenu() { createSuccessNotice( __( 'Duplicated Navigation Menu' ), { type: 'snackbar', } ); - history.push( { postType, postId: savedRecord.id } ); + history.navigate( `/wp_navigation/${ savedRecord.id }` ); } } catch ( error ) { createErrorNotice( diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js index ece549f57378b2..dc3dd879611843 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js @@ -18,7 +18,6 @@ import { navigation } from '@wordpress/icons'; import SidebarNavigationScreen from '../sidebar-navigation-screen'; import SidebarNavigationItem from '../sidebar-navigation-item'; import { PRELOADED_NAVIGATION_MENUS_QUERY } from './constants'; -import { useLink } from '../routes/link'; import SingleNavigationMenu from '../sidebar-navigation-screen-navigation-menu/single-navigation-menu'; import useNavigationMenuHandlers from '../sidebar-navigation-screen-navigation-menu/use-navigation-menu-handlers'; import { unlock } from '../../lock-unlock'; @@ -152,9 +151,10 @@ export function SidebarNavigationScreenWrapper( { } const NavMenuItem = ( { postId, ...props } ) => { - const linkInfo = useLink( { - postId, - postType: 'wp_navigation', - } ); - return <SidebarNavigationItem { ...linkInfo } { ...props } />; + return ( + <SidebarNavigationItem + to={ `/wp_navigation/${ postId }` } + { ...props } + /> + ); }; diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/leaf-more-menu.js b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/leaf-more-menu.js index 568ec291f9ed11..ba01faab0291ce 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/leaf-more-menu.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/leaf-more-menu.js @@ -20,10 +20,11 @@ const POPOVER_PROPS = { */ import { unlock } from '../../lock-unlock'; -const { useHistory } = unlock( routerPrivateApis ); +const { useHistory, useLocation } = unlock( routerPrivateApis ); export default function LeafMoreMenu( props ) { const history = useHistory(); + const { path } = useLocation(); const { block } = props; const { clientId } = block; const { moveBlocksDown, moveBlocksUp, removeBlocks } = @@ -59,33 +60,20 @@ export default function LeafMoreMenu( props ) { attributes.type && history ) { - const { params } = history.getLocationWithParams(); - history.push( + history.navigate( + `/${ attributes.type }/${ attributes.id }?canvas=edit`, { - postType: attributes.type, - postId: attributes.id, - canvas: 'edit', - }, - { - backPath: params, + state: { backPath: path }, } ); } if ( name === 'core/page-list-item' && attributes.id && history ) { - const { params } = history.getLocationWithParams(); - history.push( - { - postType: 'page', - postId: attributes.id, - canvas: 'edit', - }, - { - backPath: params, - } - ); + history.navigate( `/page/${ attributes.id }?canvas=edit`, { + state: { backPath: path }, + } ); } }, - [ history ] + [ path, history ] ); return ( diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-patterns/category-item.js b/packages/edit-site/src/components/sidebar-navigation-screen-patterns/category-item.js index 9c193304b99fc8..4e92af1d84f50e 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-patterns/category-item.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-patterns/category-item.js @@ -2,13 +2,6 @@ * Internal dependencies */ import SidebarNavigationItem from '../sidebar-navigation-item'; -import { useLink } from '../routes/link'; -import { - TEMPLATE_PART_POST_TYPE, - TEMPLATE_PART_ALL_AREAS_CATEGORY, - PATTERN_DEFAULT_CATEGORY, - PATTERN_TYPES, -} from '../../utils/constants'; export default function CategoryItem( { count, @@ -18,28 +11,20 @@ export default function CategoryItem( { label, type, } ) { - const linkInfo = useLink( { - categoryId: - id !== TEMPLATE_PART_ALL_AREAS_CATEGORY && - id !== PATTERN_DEFAULT_CATEGORY - ? id - : undefined, - postType: - type === TEMPLATE_PART_POST_TYPE - ? TEMPLATE_PART_POST_TYPE - : PATTERN_TYPES.user, - } ); - if ( ! count ) { return; } + const queryArgs = [ `postType=${ type }` ]; + if ( id ) { + queryArgs.push( `categoryId=${ id }` ); + } return ( <SidebarNavigationItem - { ...linkInfo } icon={ icon } suffix={ <span>{ count }</span> } aria-current={ isActive ? 'true' : undefined } + to={ `/pattern?${ queryArgs.join( '&' ) }` } > { label } </SidebarNavigationItem> diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-patterns/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-patterns/index.js index eeec513cb99afb..d63389ad3be312 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-patterns/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-patterns/index.js @@ -104,12 +104,11 @@ function CategoriesGroup( { export default function SidebarNavigationScreenPatterns( { backPath } ) { const { - params: { postType, categoryId }, + query: { postType = 'wp_block', categoryId }, } = useLocation(); - const currentType = postType || PATTERN_TYPES.user; const currentCategory = categoryId || - ( currentType === PATTERN_TYPES.user + ( postType === PATTERN_TYPES.user ? PATTERN_DEFAULT_CATEGORY : TEMPLATE_PART_ALL_AREAS_CATEGORY ); @@ -143,7 +142,7 @@ export default function SidebarNavigationScreenPatterns( { backPath } ) { templatePartAreas={ templatePartAreas } patternCategories={ patternCategories } currentCategory={ currentCategory } - currentType={ currentType } + currentType={ postType } /> </> ) } diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js b/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js index 5a07adf62d9b31..5d3819eac0ee3c 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js @@ -4,35 +4,40 @@ import { useEntityRecords } from '@wordpress/core-data'; import { useMemo } from '@wordpress/element'; import { __experimentalItemGroup as ItemGroup } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies */ -import DataViewItem from '../sidebar-dataviews/dataview-item'; +import SidebarNavigationItem from '../sidebar-navigation-item'; import { useAddedBy } from '../page-templates/hooks'; import { layout } from '@wordpress/icons'; import { TEMPLATE_POST_TYPE } from '../../utils/constants'; +import { unlock } from '../../lock-unlock'; + +const { useLocation } = unlock( routerPrivateApis ); const EMPTY_ARRAY = []; function TemplateDataviewItem( { template, isActive } ) { const { text, icon } = useAddedBy( template.type, template.id ); + return ( - <DataViewItem - key={ text } - slug={ text } - title={ text } + <SidebarNavigationItem + to={ `/template?activeView=${ text }` } icon={ icon } - isActive={ isActive } - isCustom={ false } - /> + aria-current={ isActive } + > + { text } + </SidebarNavigationItem> ); } -export default function DataviewsTemplatesSidebarContent( { - activeView, - title, -} ) { +export default function DataviewsTemplatesSidebarContent() { + const { + query: { activeView = 'all' }, + } = useLocation(); const { records } = useEntityRecords( 'postType', TEMPLATE_POST_TYPE, { per_page: -1, } ); @@ -52,13 +57,13 @@ export default function DataviewsTemplatesSidebarContent( { return ( <ItemGroup> - <DataViewItem - slug="all" - title={ title } + <SidebarNavigationItem + to="/template" icon={ layout } - isActive={ activeView === 'all' } - isCustom={ false } - /> + aria-current={ activeView === 'all' } + > + { __( 'All templates' ) } + </SidebarNavigationItem> { firstItemPerAuthorText.map( ( template ) => { return ( <TemplateDataviewItem diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/index.js index 8e7946390a3640..d2215a9abd9c61 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/index.js @@ -2,22 +2,14 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies */ import SidebarNavigationScreen from '../sidebar-navigation-screen'; -import { unlock } from '../../lock-unlock'; import DataviewsTemplatesSidebarContent from './content'; -const { useLocation } = unlock( routerPrivateApis ); - export default function SidebarNavigationScreenTemplatesBrowse( { backPath } ) { - const { - params: { activeView = 'all' }, - } = useLocation(); - return ( <SidebarNavigationScreen title={ __( 'Templates' ) } @@ -25,12 +17,7 @@ export default function SidebarNavigationScreenTemplatesBrowse( { backPath } ) { 'Create new templates, or reset any customizations made to the templates supplied by your theme.' ) } backPath={ backPath } - content={ - <DataviewsTemplatesSidebarContent - activeView={ activeView } - title={ __( 'All templates' ) } - /> - } + content={ <DataviewsTemplatesSidebarContent /> } /> ); } diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/index.js b/packages/edit-site/src/components/sidebar-navigation-screen/index.js index 0080964310525b..c6b3742a3fd8bc 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen/index.js @@ -83,7 +83,7 @@ export default function SidebarNavigationScreen( { { ! isRoot && ( <SidebarButton onClick={ () => { - history.push( backPath ); + history.navigate( backPath ); navigate( 'back' ); } } icon={ icon } @@ -97,7 +97,7 @@ export default function SidebarNavigationScreen( { label={ dashboardLinkText || __( 'Go to the Dashboard' ) } - href={ dashboardLink || 'index.php' } + href={ dashboardLink } /> ) } <Heading diff --git a/packages/edit-site/src/components/site-editor-routes/home-edit.js b/packages/edit-site/src/components/site-editor-routes/home-edit.js deleted file mode 100644 index f6e6499254082f..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/home-edit.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Internal dependencies - */ -import Editor from '../editor'; -import SidebarNavigationScreenMain from '../sidebar-navigation-screen-main'; - -export const homeEditRoute = { - name: 'home-edit', - match: ( params ) => { - return params.canvas === 'edit'; - }, - areas: { - sidebar: <SidebarNavigationScreenMain />, - preview: <Editor />, - mobile: <Editor />, - }, -}; diff --git a/packages/edit-site/src/components/site-editor-routes/home-view.js b/packages/edit-site/src/components/site-editor-routes/home.js similarity index 66% rename from packages/edit-site/src/components/site-editor-routes/home-view.js rename to packages/edit-site/src/components/site-editor-routes/home.js index 63d3d021e82083..3b6230e6b6c38d 100644 --- a/packages/edit-site/src/components/site-editor-routes/home-view.js +++ b/packages/edit-site/src/components/site-editor-routes/home.js @@ -4,13 +4,12 @@ import Editor from '../editor'; import SidebarNavigationScreenMain from '../sidebar-navigation-screen-main'; -export const homeViewRoute = { - name: 'home-view', - match: ( params ) => { - return params.canvas !== 'edit'; - }, +export const homeRoute = { + name: 'home', + path: '/', areas: { sidebar: <SidebarNavigationScreenMain />, preview: <Editor />, + mobile: <SidebarNavigationScreenMain />, }, }; diff --git a/packages/edit-site/src/components/site-editor-routes/index.js b/packages/edit-site/src/components/site-editor-routes/index.js index 4887436dc2ed16..bac2fa302b5cf5 100644 --- a/packages/edit-site/src/components/site-editor-routes/index.js +++ b/packages/edit-site/src/components/site-editor-routes/index.js @@ -9,42 +9,30 @@ import { useEffect } from '@wordpress/element'; */ import { unlock } from '../../lock-unlock'; import { store as siteEditorStore } from '../../store'; -import { homeViewRoute } from './home-view'; -import { homeEditRoute } from './home-edit'; -import { navigationViewRoute } from './navigation-view'; -import { navigationEditRoute } from './navigation-edit'; -import { navigationItemEditRoute } from './navigation-item-edit'; -import { navigationItemViewRoute } from './navigation-item-view'; -import { stylesViewRoute } from './styles-view'; -import { patternsEditRoute } from './patterns-edit'; -import { patternsViewRoute } from './patterns-view'; -import { templatesEditRoute } from './templates-edit'; -import { templatesListViewRoute } from './templates-list-view'; -import { templatesViewRoute } from './templates-view'; -import { pagesViewRoute } from './pages-view'; -import { pagesEditRoute } from './pages-edit'; -import { pagesListViewRoute } from './pages-list-view'; -import { pagesListViewQuickEditRoute } from './pages-list-view-quick-edit'; -import { pagesViewQuickEditRoute } from './pages-view-quick-edit'; +import { homeRoute } from './home'; +import { stylesRoute } from './styles'; +import { navigationRoute } from './navigation'; +import { navigationItemRoute } from './navigation-item'; +import { patternsRoute } from './patterns'; +import { patternItemRoute } from './pattern-item'; +import { templatePartItemRoute } from './template-part-item'; +import { templatesRoute } from './templates'; +import { templateItemRoute } from './template-item'; +import { pagesRoute } from './pages'; +import { pageItemRoute } from './page-item'; const routes = [ - pagesListViewQuickEditRoute, - pagesListViewRoute, - pagesViewQuickEditRoute, - pagesViewRoute, - pagesEditRoute, - templatesEditRoute, - templatesListViewRoute, - templatesViewRoute, - patternsViewRoute, - patternsEditRoute, - stylesViewRoute, - navigationItemViewRoute, - navigationItemEditRoute, - navigationViewRoute, - navigationEditRoute, - homeViewRoute, - homeEditRoute, + pageItemRoute, + pagesRoute, + templateItemRoute, + templatesRoute, + templatePartItemRoute, + patternItemRoute, + patternsRoute, + navigationItemRoute, + navigationRoute, + stylesRoute, + homeRoute, ]; export function useRegisterSiteEditorRoutes() { diff --git a/packages/edit-site/src/components/site-editor-routes/navigation-edit.js b/packages/edit-site/src/components/site-editor-routes/navigation-edit.js deleted file mode 100644 index fdba963c41d0cb..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/navigation-edit.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Internal dependencies - */ -import { NAVIGATION_POST_TYPE } from '../../utils/constants'; -import Editor from '../editor'; -import SidebarNavigationScreenNavigationMenus from '../sidebar-navigation-screen-navigation-menus'; - -export const navigationEditRoute = { - name: 'navigation-edit', - match: ( params ) => { - return ( - params.postType === NAVIGATION_POST_TYPE && - ! params.postId && - params.canvas === 'edit' - ); - }, - areas: { - sidebar: <SidebarNavigationScreenNavigationMenus backPath={ {} } />, - preview: <Editor />, - mobile: <Editor />, - }, -}; diff --git a/packages/edit-site/src/components/site-editor-routes/navigation-item-edit.js b/packages/edit-site/src/components/site-editor-routes/navigation-item-edit.js deleted file mode 100644 index b03cdbd995ac7c..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/navigation-item-edit.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Internal dependencies - */ -import { NAVIGATION_POST_TYPE } from '../../utils/constants'; -import Editor from '../editor'; -import SidebarNavigationScreenNavigationMenu from '../sidebar-navigation-screen-navigation-menu'; - -export const navigationItemEditRoute = { - name: 'navigation-item-edit', - match: ( params ) => { - return ( - params.postType === NAVIGATION_POST_TYPE && - !! params.postId && - params.canvas === 'edit' - ); - }, - areas: { - sidebar: ( - <SidebarNavigationScreenNavigationMenu - backPath={ { postType: NAVIGATION_POST_TYPE } } - /> - ), - preview: <Editor />, - mobile: <Editor />, - }, -}; diff --git a/packages/edit-site/src/components/site-editor-routes/navigation-item-view.js b/packages/edit-site/src/components/site-editor-routes/navigation-item-view.js deleted file mode 100644 index d04a03a8f9df38..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/navigation-item-view.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Internal dependencies - */ -import { NAVIGATION_POST_TYPE } from '../../utils/constants'; -import Editor from '../editor'; -import SidebarNavigationScreenNavigationMenu from '../sidebar-navigation-screen-navigation-menu'; - -export const navigationItemViewRoute = { - name: 'navigation-item-view', - match: ( params ) => { - return ( - params.postType === NAVIGATION_POST_TYPE && - !! params.postId && - params.canvas !== 'edit' - ); - }, - areas: { - sidebar: ( - <SidebarNavigationScreenNavigationMenu - backPath={ { postType: NAVIGATION_POST_TYPE } } - /> - ), - preview: <Editor />, - }, -}; diff --git a/packages/edit-site/src/components/site-editor-routes/navigation-item.js b/packages/edit-site/src/components/site-editor-routes/navigation-item.js new file mode 100644 index 00000000000000..76983d8ff8daa4 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/navigation-item.js @@ -0,0 +1,39 @@ +/** + * WordPress dependencies + */ +import { privateApis as routerPrivateApis } from '@wordpress/router'; + +/** + * Internal dependencies + */ +import { NAVIGATION_POST_TYPE } from '../../utils/constants'; +import Editor from '../editor'; +import SidebarNavigationScreenNavigationMenu from '../sidebar-navigation-screen-navigation-menu'; +import { unlock } from '../../lock-unlock'; + +const { useLocation } = unlock( routerPrivateApis ); + +function MobileNavigationItemView() { + const { query = {} } = useLocation(); + const { canvas = 'view' } = query; + + return canvas === 'edit' ? ( + <Editor /> + ) : ( + <SidebarNavigationScreenNavigationMenu + backPath={ { postType: NAVIGATION_POST_TYPE } } + /> + ); +} + +export const navigationItemRoute = { + name: 'navigation-item', + path: '/wp_navigation/:postId', + areas: { + sidebar: ( + <SidebarNavigationScreenNavigationMenu backPath="/navigation" /> + ), + preview: <Editor />, + mobile: <MobileNavigationItemView />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/navigation-view.js b/packages/edit-site/src/components/site-editor-routes/navigation-view.js deleted file mode 100644 index 59c38a2f1d099a..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/navigation-view.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Internal dependencies - */ -import { NAVIGATION_POST_TYPE } from '../../utils/constants'; -import Editor from '../editor'; -import SidebarNavigationScreenNavigationMenus from '../sidebar-navigation-screen-navigation-menus'; - -export const navigationViewRoute = { - name: 'navigation-view', - match: ( params ) => { - return ( - params.postType === NAVIGATION_POST_TYPE && - ! params.postId && - params.canvas !== 'edit' - ); - }, - areas: { - sidebar: <SidebarNavigationScreenNavigationMenus backPath={ {} } />, - preview: <Editor />, - }, -}; diff --git a/packages/edit-site/src/components/site-editor-routes/navigation.js b/packages/edit-site/src/components/site-editor-routes/navigation.js new file mode 100644 index 00000000000000..4c435e78a495f2 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/navigation.js @@ -0,0 +1,34 @@ +/** + * WordPress dependencies + */ +import { privateApis as routerPrivateApis } from '@wordpress/router'; + +/** + * Internal dependencies + */ +import Editor from '../editor'; +import SidebarNavigationScreenNavigationMenus from '../sidebar-navigation-screen-navigation-menus'; +import { unlock } from '../../lock-unlock'; + +const { useLocation } = unlock( routerPrivateApis ); + +function MobileNavigationView() { + const { query = {} } = useLocation(); + const { canvas = 'view' } = query; + + return canvas === 'edit' ? ( + <Editor /> + ) : ( + <SidebarNavigationScreenNavigationMenus backPath="/" /> + ); +} + +export const navigationRoute = { + name: 'navigation', + path: '/navigation', + areas: { + sidebar: <SidebarNavigationScreenNavigationMenus backPath="/" />, + preview: <Editor />, + mobile: <MobileNavigationView />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/pages-edit.js b/packages/edit-site/src/components/site-editor-routes/page-item.js similarity index 54% rename from packages/edit-site/src/components/site-editor-routes/pages-edit.js rename to packages/edit-site/src/components/site-editor-routes/page-item.js index ef4c7efbfb09c2..c20720316b10e0 100644 --- a/packages/edit-site/src/components/site-editor-routes/pages-edit.js +++ b/packages/edit-site/src/components/site-editor-routes/page-item.js @@ -6,29 +6,21 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import PostList from '../post-list'; +import Editor from '../editor'; import DataViewsSidebarContent from '../sidebar-dataviews'; import SidebarNavigationScreen from '../sidebar-navigation-screen'; -import Editor from '../editor'; -function PageList() { - return <PostList postType="page" />; -} - -export const pagesEditRoute = { - name: 'pages-edit', - match: ( params ) => { - return params.postType === 'page' && params.canvas === 'edit'; - }, +export const pageItemRoute = { + name: 'page-item', + path: '/page/:postId', areas: { sidebar: ( <SidebarNavigationScreen title={ __( 'Pages' ) } - backPath={ {} } - content={ <DataViewsSidebarContent /> } + backPath="/" + content={ <DataViewsSidebarContent postType="page" /> } /> ), - content: <PageList />, mobile: <Editor />, preview: <Editor />, }, diff --git a/packages/edit-site/src/components/site-editor-routes/pages-list-view-quick-edit.js b/packages/edit-site/src/components/site-editor-routes/pages-list-view-quick-edit.js deleted file mode 100644 index 9eb33e05a99bb0..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/pages-list-view-quick-edit.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { privateApis as routerPrivateApis } from '@wordpress/router'; - -/** - * Internal dependencies - */ -import PostList from '../post-list'; -import DataViewsSidebarContent from '../sidebar-dataviews'; -import SidebarNavigationScreen from '../sidebar-navigation-screen'; -import { unlock } from '../../lock-unlock'; -import { PostEdit } from '../post-edit'; -import Editor from '../editor'; - -const { useLocation } = unlock( routerPrivateApis ); - -function PageList() { - return <PostList postType="page" />; -} - -function PageQuickEdit() { - const { params } = useLocation(); - return <PostEdit postType="page" postId={ params.postId } />; -} - -export const pagesListViewQuickEditRoute = { - name: 'pages-list-view-quick-edit', - match: ( params ) => { - return ( - params.isCustom !== 'true' && - ( params.layout ?? 'list' ) === 'list' && - !! params.quickEdit && - params.postType === 'page' && - params.canvas !== 'edit' - ); - }, - areas: { - sidebar: ( - <SidebarNavigationScreen - title={ __( 'Pages' ) } - backPath={ {} } - content={ <DataViewsSidebarContent /> } - /> - ), - content: <PageList />, - mobile: <PageList />, - preview: <Editor />, - edit: <PageQuickEdit />, - }, - widths: { - content: 380, - edit: 380, - }, -}; diff --git a/packages/edit-site/src/components/site-editor-routes/pages-list-view.js b/packages/edit-site/src/components/site-editor-routes/pages-list-view.js deleted file mode 100644 index 74b39848e83f2b..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/pages-list-view.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import PostList from '../post-list'; -import DataViewsSidebarContent from '../sidebar-dataviews'; -import SidebarNavigationScreen from '../sidebar-navigation-screen'; -import Editor from '../editor'; - -function PageList() { - return <PostList postType="page" />; -} - -export const pagesListViewRoute = { - name: 'pages-list-view', - match: ( params ) => { - return ( - params.isCustom !== 'true' && - ( params.layout ?? 'list' ) === 'list' && - ! params.quickEdit && - params.postType === 'page' && - params.canvas !== 'edit' - ); - }, - areas: { - sidebar: ( - <SidebarNavigationScreen - title={ __( 'Pages' ) } - backPath={ {} } - content={ <DataViewsSidebarContent /> } - /> - ), - content: <PageList />, - preview: <Editor />, - mobile: <PageList />, - }, - widths: { - content: 380, - }, -}; diff --git a/packages/edit-site/src/components/site-editor-routes/pages-view-quick-edit.js b/packages/edit-site/src/components/site-editor-routes/pages-view-quick-edit.js deleted file mode 100644 index 907054364c8a93..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/pages-view-quick-edit.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { privateApis as routerPrivateApis } from '@wordpress/router'; - -/** - * Internal dependencies - */ -import PostList from '../post-list'; -import DataViewsSidebarContent from '../sidebar-dataviews'; -import SidebarNavigationScreen from '../sidebar-navigation-screen'; -import { unlock } from '../../lock-unlock'; -import { PostEdit } from '../post-edit'; - -const { useLocation } = unlock( routerPrivateApis ); - -function PageList() { - return <PostList postType="page" />; -} - -function PageQuickEdit() { - const { params } = useLocation(); - return <PostEdit postType="page" postId={ params.postId } />; -} - -export const pagesViewQuickEditRoute = { - name: 'pages-view-quick-edit', - match: ( params ) => { - return ( - ( params.isCustom === 'true' || - ( params.layout ?? 'list' ) !== 'list' ) && - !! params.quickEdit && - params.postType === 'page' && - params.canvas !== 'edit' - ); - }, - areas: { - sidebar: ( - <SidebarNavigationScreen - title={ __( 'Pages' ) } - backPath={ {} } - content={ <DataViewsSidebarContent /> } - /> - ), - content: <PageList />, - mobile: <PageList />, - edit: <PageQuickEdit />, - }, - widths: { - edit: 380, - }, -}; diff --git a/packages/edit-site/src/components/site-editor-routes/pages-view.js b/packages/edit-site/src/components/site-editor-routes/pages-view.js deleted file mode 100644 index df7e211022cacf..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/pages-view.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import PostList from '../post-list'; -import DataViewsSidebarContent from '../sidebar-dataviews'; -import SidebarNavigationScreen from '../sidebar-navigation-screen'; - -function PageList() { - return <PostList postType="page" />; -} - -export const pagesViewRoute = { - name: 'pages-view', - match: ( params ) => { - return ( - ( params.isCustom === 'true' || - ( params.layout ?? 'list' ) !== 'list' ) && - ! params.quickEdit && - params.postType === 'page' && - params.canvas !== 'edit' - ); - }, - areas: { - sidebar: ( - <SidebarNavigationScreen - title={ __( 'Pages' ) } - backPath={ {} } - content={ <DataViewsSidebarContent /> } - /> - ), - content: <PageList />, - mobile: <PageList />, - }, -}; diff --git a/packages/edit-site/src/components/site-editor-routes/pages.js b/packages/edit-site/src/components/site-editor-routes/pages.js new file mode 100644 index 00000000000000..e8c55cd10307e1 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/pages.js @@ -0,0 +1,66 @@ +/** + * WordPress dependencies + */ +import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import Editor from '../editor'; +import SidebarNavigationScreen from '../sidebar-navigation-screen'; +import DataViewsSidebarContent from '../sidebar-dataviews'; +import PostList from '../post-list'; +import { unlock } from '../../lock-unlock'; +import { PostEdit } from '../post-edit'; + +const { useLocation } = unlock( routerPrivateApis ); + +function MobilePagesView() { + const { query = {} } = useLocation(); + const { canvas = 'view' } = query; + + return canvas === 'edit' ? <Editor /> : <PostList postType="page" />; +} + +export const pagesRoute = { + name: 'pages', + path: '/page', + areas: { + sidebar: ( + <SidebarNavigationScreen + title={ __( 'Pages' ) } + backPath="/" + content={ <DataViewsSidebarContent postType="page" /> } + /> + ), + content: <PostList postType="page" />, + preview( { query } ) { + const isListView = + ( query.layout === 'list' || ! query.layout ) && + query.isCustom !== 'true'; + return isListView ? <Editor /> : undefined; + }, + mobile: <MobilePagesView />, + edit( { query } ) { + const hasQuickEdit = + ( query.layout ?? 'list' ) === 'list' && !! query.quickEdit; + return hasQuickEdit ? ( + <PostEdit postType="page" postId={ query.postId } /> + ) : undefined; + }, + }, + widths: { + content( { query } ) { + const isListView = + ( query.layout === 'list' || ! query.layout ) && + query.isCustom !== 'true'; + return isListView ? 380 : undefined; + }, + edit( { query } ) { + const hasQuickEdit = + ( query.layout ?? 'list' ) === 'list' && !! query.quickEdit; + return hasQuickEdit ? 380 : undefined; + }, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/pattern-item.js b/packages/edit-site/src/components/site-editor-routes/pattern-item.js new file mode 100644 index 00000000000000..c4cbcf871f3686 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/pattern-item.js @@ -0,0 +1,15 @@ +/** + * Internal dependencies + */ +import Editor from '../editor'; +import SidebarNavigationScreenPatterns from '../sidebar-navigation-screen-patterns'; + +export const patternItemRoute = { + name: 'pattern-item', + path: '/wp_block/:postId', + areas: { + sidebar: <SidebarNavigationScreenPatterns backPath="/" />, + mobile: <Editor />, + preview: <Editor />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/patterns-edit.js b/packages/edit-site/src/components/site-editor-routes/patterns-edit.js deleted file mode 100644 index eaf1fd68020181..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/patterns-edit.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Internal dependencies - */ -import Editor from '../editor'; -import SidebarNavigationScreenPatterns from '../sidebar-navigation-screen-patterns'; -import PagePatterns from '../page-patterns'; -import { PATTERN_TYPES, TEMPLATE_PART_POST_TYPE } from '../../utils/constants'; - -export const patternsEditRoute = { - name: 'patterns-edit', - match: ( params ) => { - return ( - [ TEMPLATE_PART_POST_TYPE, PATTERN_TYPES.user ].includes( - params.postType - ) && params.canvas === 'edit' - ); - }, - areas: { - sidebar: <SidebarNavigationScreenPatterns backPath={ {} } />, - content: <PagePatterns />, - mobile: <Editor />, - preview: <Editor />, - }, -}; diff --git a/packages/edit-site/src/components/site-editor-routes/patterns-view.js b/packages/edit-site/src/components/site-editor-routes/patterns-view.js deleted file mode 100644 index 468f7f14abc139..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/patterns-view.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Internal dependencies - */ -import SidebarNavigationScreenPatterns from '../sidebar-navigation-screen-patterns'; -import PagePatterns from '../page-patterns'; -import { PATTERN_TYPES, TEMPLATE_PART_POST_TYPE } from '../../utils/constants'; - -export const patternsViewRoute = { - name: 'patterns-view', - match: ( params ) => { - return ( - [ TEMPLATE_PART_POST_TYPE, PATTERN_TYPES.user ].includes( - params.postType - ) && params.canvas !== 'edit' - ); - }, - areas: { - sidebar: <SidebarNavigationScreenPatterns backPath={ {} } />, - content: <PagePatterns />, - mobile: <PagePatterns />, - }, -}; diff --git a/packages/edit-site/src/components/site-editor-routes/patterns.js b/packages/edit-site/src/components/site-editor-routes/patterns.js new file mode 100644 index 00000000000000..48207cfe1c1d2c --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/patterns.js @@ -0,0 +1,15 @@ +/** + * Internal dependencies + */ +import SidebarNavigationScreenPatterns from '../sidebar-navigation-screen-patterns'; +import PagePatterns from '../page-patterns'; + +export const patternsRoute = { + name: 'patterns', + path: '/pattern', + areas: { + sidebar: <SidebarNavigationScreenPatterns backPath="/" />, + content: <PagePatterns />, + mobile: <SidebarNavigationScreenPatterns backPath="/" />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/styles-view.js b/packages/edit-site/src/components/site-editor-routes/styles.js similarity index 58% rename from packages/edit-site/src/components/site-editor-routes/styles-view.js rename to packages/edit-site/src/components/site-editor-routes/styles.js index cc9411eb8144c0..17e4a3c064d023 100644 --- a/packages/edit-site/src/components/site-editor-routes/styles-view.js +++ b/packages/edit-site/src/components/site-editor-routes/styles.js @@ -5,18 +5,12 @@ import Editor from '../editor'; import SidebarNavigationScreenGlobalStyles from '../sidebar-navigation-screen-global-styles'; import GlobalStylesUIWrapper from '../sidebar-global-styles-wrapper'; -export const stylesViewRoute = { - name: 'styles-view', - match: ( params ) => { - return ( - params.path && - params.path.startsWith( '/wp_global_styles' ) && - params.canvas !== 'edit' - ); - }, +export const stylesRoute = { + name: 'styles', + path: '/styles', areas: { content: <GlobalStylesUIWrapper />, - sidebar: <SidebarNavigationScreenGlobalStyles backPath={ {} } />, + sidebar: <SidebarNavigationScreenGlobalStyles backPath="/" />, preview: <Editor />, mobile: <GlobalStylesUIWrapper />, }, diff --git a/packages/edit-site/src/components/site-editor-routes/template-item.js b/packages/edit-site/src/components/site-editor-routes/template-item.js new file mode 100644 index 00000000000000..8ad3ab2b699904 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/template-item.js @@ -0,0 +1,15 @@ +/** + * Internal dependencies + */ +import Editor from '../editor'; +import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse'; + +export const templateItemRoute = { + name: 'template-item', + path: '/wp_template/*postId', + areas: { + sidebar: <SidebarNavigationScreenTemplatesBrowse backPath="/" />, + mobile: <Editor />, + preview: <Editor />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/template-part-item.js b/packages/edit-site/src/components/site-editor-routes/template-part-item.js new file mode 100644 index 00000000000000..a2b21cf23f808d --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/template-part-item.js @@ -0,0 +1,15 @@ +/** + * Internal dependencies + */ +import Editor from '../editor'; +import SidebarNavigationScreenPatterns from '../sidebar-navigation-screen-patterns'; + +export const templatePartItemRoute = { + name: 'template-part-item', + path: '/wp_template_part/*postId', + areas: { + sidebar: <SidebarNavigationScreenPatterns backPath="/" />, + mobile: <Editor />, + preview: <Editor />, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/templates-edit.js b/packages/edit-site/src/components/site-editor-routes/templates-edit.js deleted file mode 100644 index 488e9decc1888c..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/templates-edit.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Internal dependencies - */ -import { TEMPLATE_POST_TYPE } from '../../utils/constants'; -import PageTemplates from '../page-templates'; -import Editor from '../editor'; -import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse'; - -export const templatesEditRoute = { - name: 'templates-edit', - match: ( params ) => { - return ( - params.postType === TEMPLATE_POST_TYPE && params.canvas === 'edit' - ); - }, - areas: { - sidebar: <SidebarNavigationScreenTemplatesBrowse backPath={ {} } />, - content: <PageTemplates />, - mobile: <Editor />, - preview: <Editor />, - }, -}; diff --git a/packages/edit-site/src/components/site-editor-routes/templates-list-view.js b/packages/edit-site/src/components/site-editor-routes/templates-list-view.js deleted file mode 100644 index 7cdda1b13c0b47..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/templates-list-view.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Internal dependencies - */ -import { TEMPLATE_POST_TYPE } from '../../utils/constants'; -import PageTemplates from '../page-templates'; -import Editor from '../editor'; -import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse'; - -export const templatesListViewRoute = { - name: 'templates-list-view', - match: ( params ) => { - return ( - params.isCustom !== 'true' && - params.layout === 'list' && - params.postType === TEMPLATE_POST_TYPE && - params.canvas !== 'edit' - ); - }, - areas: { - sidebar: <SidebarNavigationScreenTemplatesBrowse backPath={ {} } />, - content: <PageTemplates />, - mobile: <PageTemplates />, - preview: <Editor />, - }, - widths: { - content: 380, - }, -}; diff --git a/packages/edit-site/src/components/site-editor-routes/templates-view.js b/packages/edit-site/src/components/site-editor-routes/templates-view.js deleted file mode 100644 index 40fd88c0e60a61..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/templates-view.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Internal dependencies - */ -import { TEMPLATE_POST_TYPE } from '../../utils/constants'; -import PageTemplates from '../page-templates'; -import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse'; - -export const templatesViewRoute = { - name: 'templates-view', - match: ( params ) => { - return ( - ( params.isCustom === 'true' || params.layout !== 'list' ) && - params.postType === TEMPLATE_POST_TYPE && - params.canvas !== 'edit' - ); - }, - areas: { - sidebar: <SidebarNavigationScreenTemplatesBrowse backPath={ {} } />, - content: <PageTemplates />, - mobile: <PageTemplates />, - }, -}; diff --git a/packages/edit-site/src/components/site-editor-routes/templates.js b/packages/edit-site/src/components/site-editor-routes/templates.js new file mode 100644 index 00000000000000..06ba07fcd06595 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/templates.js @@ -0,0 +1,45 @@ +/** + * WordPress dependencies + */ +import { privateApis as routerPrivateApis } from '@wordpress/router'; + +/** + * Internal dependencies + */ +import Editor from '../editor'; +import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse'; +import { unlock } from '../../lock-unlock'; +import PageTemplates from '../page-templates'; + +const { useLocation } = unlock( routerPrivateApis ); + +function MobileTemplatesView() { + const { query = {} } = useLocation(); + const { canvas = 'view' } = query; + + return canvas === 'edit' ? ( + <Editor /> + ) : ( + <SidebarNavigationScreenTemplatesBrowse backPath="/" /> + ); +} + +export const templatesRoute = { + name: 'templates', + path: '/template', + areas: { + sidebar: <SidebarNavigationScreenTemplatesBrowse backPath="/" />, + content: <PageTemplates />, + preview( { query } ) { + const isListView = query.layout === 'list'; + return isListView ? <Editor /> : undefined; + }, + mobile: <MobileTemplatesView />, + }, + widths: { + content( { query } ) { + const isListView = query.layout === 'list'; + return isListView ? 380 : undefined; + }, + }, +}; diff --git a/packages/edit-site/src/components/site-hub/index.js b/packages/edit-site/src/components/site-hub/index.js index 9e57034bfe73aa..91324356d01975 100644 --- a/packages/edit-site/src/components/site-hub/index.js +++ b/packages/edit-site/src/components/site-hub/index.js @@ -39,8 +39,7 @@ const SiteHub = memo( const { getEntityRecord } = select( coreStore ); const _site = getEntityRecord( 'root', 'site' ); return { - dashboardLink: - getSettings().__experimentalDashboardLink || 'index.php', + dashboardLink: getSettings().__experimentalDashboardLink, homeUrl: getEntityRecord( 'root', '__unstableBase' )?.home, siteTitle: ! _site?.title && !! _site?.url @@ -129,9 +128,7 @@ export const SiteHubMobile = memo( select( coreStore ); const _site = getEntityRecord( 'root', 'site' ); return { - dashboardLink: - getSettings().__experimentalDashboardLink || - 'index.php', + dashboardLink: getSettings().__experimentalDashboardLink, isBlockTheme: getCurrentTheme()?.is_block_theme, homeUrl: getEntityRecord( 'root', '__unstableBase' )?.home, siteTitle: @@ -170,7 +167,7 @@ export const SiteHubMobile = memo( } : { onClick: () => { - history.push( {} ); + history.navigate( '/' ); navigate( 'back' ); }, label: __( 'Go to Site Editor' ), diff --git a/packages/edit-site/src/hooks/commands/use-common-commands.js b/packages/edit-site/src/hooks/commands/use-common-commands.js index 3e87f8721e116a..34ddae3e1af7a4 100644 --- a/packages/edit-site/src/hooks/commands/use-common-commands.js +++ b/packages/edit-site/src/hooks/commands/use-common-commands.js @@ -49,27 +49,17 @@ const getGlobalStylesOpenStylesCommands = () => label: __( 'Open styles' ), callback: ( { close } ) => { close(); - if ( ! params.postId ) { - history.push( { - path: '/wp_global_styles', - canvas: 'edit', + if ( canvas !== 'edit' ) { + history.navigate( '/styles?canvas=edit', { + transition: 'canvas-mode-edit-transition', } ); } - if ( params.postId && canvas !== 'edit' ) { - history.push( - { ...params, canvas: 'edit' }, - undefined, - { - transition: 'canvas-mode-edit-transition', - } - ); - } openGeneralSidebar( 'edit-site/global-styles' ); }, icon: styles, }, ]; - }, [ history, openGeneralSidebar, params, canvas, isBlockBasedTheme ] ); + }, [ history, openGeneralSidebar, canvas, isBlockBasedTheme ] ); return { isLoading: false, @@ -100,24 +90,11 @@ const getGlobalStylesToggleWelcomeGuideCommands = () => label: __( 'Learn about styles' ), callback: ( { close } ) => { close(); - if ( ! params.postId ) { - history.push( { - path: '/wp_global_styles', - canvas: 'edit', + if ( canvas !== 'edit' ) { + history.navigate( '/styles?canvas=edit', { + transition: 'canvas-mode-edit-transition', } ); } - if ( params.postId && canvas !== 'edit' ) { - history.push( - { - ...params, - canvas: 'edit', - }, - undefined, - { - transition: 'canvas-mode-edit-transition', - } - ); - } openGeneralSidebar( 'edit-site/global-styles' ); set( 'core/edit-site', 'welcomeGuideStyles', true ); // sometimes there's a focus loss that happens after some time @@ -129,14 +106,7 @@ const getGlobalStylesToggleWelcomeGuideCommands = () => icon: help, }, ]; - }, [ - history, - openGeneralSidebar, - canvas, - isBlockBasedTheme, - set, - params, - ] ); + }, [ history, openGeneralSidebar, canvas, isBlockBasedTheme, set ] ); return { isLoading: false, @@ -205,24 +175,11 @@ const getGlobalStylesOpenCssCommands = () => icon: brush, callback: ( { close } ) => { close(); - if ( ! params.postId ) { - history.push( { - path: '/wp_global_styles', - canvas: 'edit', + if ( canvas !== 'edit' ) { + history.navigate( '/styles?canvas=edit', { + transition: 'canvas-mode-edit-transition', } ); } - if ( params.postId && canvas !== 'edit' ) { - history.push( - { - ...params, - canvas: 'edit', - }, - undefined, - { - transition: 'canvas-mode-edit-transition', - } - ); - } openGeneralSidebar( 'edit-site/global-styles' ); setEditorCanvasContainerView( 'global-styles-css' ); }, @@ -234,7 +191,6 @@ const getGlobalStylesOpenCssCommands = () => setEditorCanvasContainerView, canEditCSS, canvas, - params, ] ); return { isLoading: false, @@ -272,24 +228,11 @@ const getGlobalStylesOpenRevisionsCommands = () => icon: backup, callback: ( { close } ) => { close(); - if ( ! params.postId ) { - history.push( { - path: '/wp_global_styles', - canvas: 'edit', + if ( canvas !== 'edit' ) { + history.navigate( '/styles?canvas=edit', { + transition: 'canvas-mode-edit-transition', } ); } - if ( params.postId && canvas !== 'edit' ) { - history.push( - { - ...params, - canvas: 'edit', - }, - undefined, - { - transition: 'canvas-mode-edit-transition', - } - ); - } openGeneralSidebar( 'edit-site/global-styles' ); setEditorCanvasContainerView( 'global-styles-revisions' @@ -303,7 +246,6 @@ const getGlobalStylesOpenRevisionsCommands = () => openGeneralSidebar, setEditorCanvasContainerView, canvas, - params, ] ); return { diff --git a/packages/edit-site/src/hooks/commands/use-set-command-context.js b/packages/edit-site/src/hooks/commands/use-set-command-context.js index e27c4ca91582fd..6ecdf04989609b 100644 --- a/packages/edit-site/src/hooks/commands/use-set-command-context.js +++ b/packages/edit-site/src/hooks/commands/use-set-command-context.js @@ -19,8 +19,8 @@ const { useLocation } = unlock( routerPrivateApis ); * React hook used to set the correct command context based on the current state. */ export default function useSetCommandContext() { - const { params } = useLocation(); - const { canvas = 'view' } = params; + const { query = {} } = useLocation(); + const { canvas = 'view' } = query; const hasBlockSelected = useSelect( ( select ) => { return select( blockEditorStore ).getBlockSelectionStart(); }, [] ); diff --git a/packages/edit-site/src/store/private-actions.js b/packages/edit-site/src/store/private-actions.js index 1db3873acedda2..9b16748049cd0e 100644 --- a/packages/edit-site/src/store/private-actions.js +++ b/packages/edit-site/src/store/private-actions.js @@ -18,3 +18,10 @@ export function registerRoute( route ) { route, }; } + +export function unregisterRoute( name ) { + return { + type: 'UNREGISTER_ROUTE', + name, + }; +} diff --git a/packages/edit-site/src/store/reducer.js b/packages/edit-site/src/store/reducer.js index 3ce067c25c1954..7ffb276a35da10 100644 --- a/packages/edit-site/src/store/reducer.js +++ b/packages/edit-site/src/store/reducer.js @@ -85,6 +85,8 @@ function routes( state = [], action ) { switch ( action.type ) { case 'REGISTER_ROUTE': return [ ...state, action.route ]; + case 'UNREGISTER_ROUTE': + return state.filter( ( route ) => route.name !== action.name ); } return state; diff --git a/packages/edit-site/src/utils/is-previewing-theme.js b/packages/edit-site/src/utils/is-previewing-theme.js index 1a71c441f9925e..a4c830b4b60ad7 100644 --- a/packages/edit-site/src/utils/is-previewing-theme.js +++ b/packages/edit-site/src/utils/is-previewing-theme.js @@ -4,9 +4,7 @@ import { getQueryArg } from '@wordpress/url'; export function isPreviewingTheme() { - return ( - getQueryArg( window.location.href, 'wp_theme_preview' ) !== undefined - ); + return !! getQueryArg( window.location.href, 'wp_theme_preview' ); } export function currentlyPreviewingTheme() { diff --git a/packages/edit-site/src/utils/use-activate-theme.js b/packages/edit-site/src/utils/use-activate-theme.js index 0dafd88340ba75..447ea073053492 100644 --- a/packages/edit-site/src/utils/use-activate-theme.js +++ b/packages/edit-site/src/utils/use-activate-theme.js @@ -4,6 +4,7 @@ import { store as coreStore } from '@wordpress/core-data'; import { useDispatch } from '@wordpress/data'; import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies @@ -14,7 +15,7 @@ import { currentlyPreviewingTheme, } from './is-previewing-theme'; -const { useHistory } = unlock( routerPrivateApis ); +const { useHistory, useLocation } = unlock( routerPrivateApis ); /** * This should be refactored to use the REST API, once the REST API can activate themes. @@ -23,6 +24,7 @@ const { useHistory } = unlock( routerPrivateApis ); */ export function useActivateTheme() { const history = useHistory(); + const { path } = useLocation(); const { startResolution, finishResolution } = useDispatch( coreStore ); return async () => { @@ -37,8 +39,7 @@ export function useActivateTheme() { finishResolution( 'activateTheme' ); // Remove the wp_theme_preview query param: we've finished activating // the queue and are switching to normal Site Editor. - const { params } = history.getLocationWithParams(); - history.replace( { ...params, wp_theme_preview: undefined } ); + history.navigate( addQueryArgs( path, { wp_theme_preview: '' } ) ); } }; } diff --git a/packages/router/package.json b/packages/router/package.json index 26b4f29df04f60..66a64f4ddc5baa 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -29,10 +29,12 @@ "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", + "@wordpress/compose": "*", "@wordpress/element": "*", "@wordpress/private-apis": "*", "@wordpress/url": "*", - "history": "^5.3.0" + "history": "^5.3.0", + "route-recognizer": "^0.3.4" }, "peerDependencies": { "react": "^18.0.0" diff --git a/packages/router/src/history.ts b/packages/router/src/history.ts deleted file mode 100644 index 6cbef108eec206..00000000000000 --- a/packages/router/src/history.ts +++ /dev/null @@ -1,99 +0,0 @@ -/** - * External dependencies - */ -import { createBrowserHistory, type BrowserHistory } from 'history'; - -/** - * WordPress dependencies - */ -import { buildQueryString } from '@wordpress/url'; - -export interface EnhancedHistory extends BrowserHistory { - getLocationWithParams: () => Location; -} - -interface PushOptions { - transition?: string; -} - -const history = createBrowserHistory(); - -const originalHistoryPush = history.push; -const originalHistoryReplace = history.replace; - -// Preserve the `wp_theme_preview` query parameter when navigating -// around the Site Editor. -// TODO: move this hack out of the router into Site Editor code. -function preserveThemePreview( params: Record< string, any > ) { - if ( params.hasOwnProperty( 'wp_theme_preview' ) ) { - return params; - } - const currentSearch = new URLSearchParams( history.location.search ); - const currentThemePreview = currentSearch.get( 'wp_theme_preview' ); - if ( currentThemePreview === null ) { - return params; - } - return { ...params, wp_theme_preview: currentThemePreview }; -} - -function push( - params: Record< string, any >, - state: Record< string, any >, - options: PushOptions = {} -) { - const performPush = () => { - const search = buildQueryString( preserveThemePreview( params ) ); - return originalHistoryPush.call( history, { search }, state ); - }; - - /* - * Skip transition in mobile, otherwise it crashes the browser. - * See: https://github.com/WordPress/gutenberg/pull/63002. - */ - const isMediumOrBigger = window.matchMedia( '(min-width: 782px)' ).matches; - if ( - ! isMediumOrBigger || - // @ts-expect-error - ! document.startViewTransition || - ! options.transition - ) { - return performPush(); - } - document.documentElement.classList.add( options.transition ); - // @ts-expect-error - const transition = document.startViewTransition( () => performPush() ); - transition.finished.finally( () => { - document.documentElement.classList.remove( options.transition ?? '' ); - } ); -} - -function replace( - params: Record< string, any >, - state: Record< string, any > -) { - const search = buildQueryString( preserveThemePreview( params ) ); - return originalHistoryReplace.call( history, { search }, state ); -} - -const locationMemo = new WeakMap(); -function getLocationWithParams() { - const location = history.location; - let locationWithParams = locationMemo.get( location ); - if ( ! locationWithParams ) { - locationWithParams = { - ...location, - params: Object.fromEntries( - new URLSearchParams( location.search ) - ), - }; - locationMemo.set( location, locationWithParams ); - } - return locationWithParams; -} - -export default { - ...history, - push, - replace, - getLocationWithParams, -}; diff --git a/packages/router/src/link.tsx b/packages/router/src/link.tsx new file mode 100644 index 00000000000000..d312a9da144601 --- /dev/null +++ b/packages/router/src/link.tsx @@ -0,0 +1,55 @@ +/** + * WordPress dependencies + */ +import { useContext, useMemo } from '@wordpress/element'; +import { getQueryArgs, getPath, buildQueryString } from '@wordpress/url'; + +/** + * Internal dependencies + */ +import { ConfigContext, type NavigationOptions, useHistory } from './router'; + +export function useLink( to: string, options: NavigationOptions = {} ) { + const history = useHistory(); + const { pathArg, beforeNavigate } = useContext( ConfigContext ); + function onClick( event: React.SyntheticEvent< HTMLAnchorElement > ) { + event?.preventDefault(); + history.navigate( to, options ); + } + const query = getQueryArgs( to ); + const path = getPath( 'http://domain.com/' + to ) ?? ''; + const link = useMemo( () => { + return beforeNavigate + ? beforeNavigate( { path, query } ) + : { path, query }; + }, [ path, query, beforeNavigate ] ); + + const [ before ] = window.location.href.split( '?' ); + + return { + href: `${ before }?${ buildQueryString( { + [ pathArg ]: link.path, + ...link.query, + } ) }`, + onClick, + }; +} + +export function Link( { + to, + options, + children, + ...props +}: { + to: string; + options?: NavigationOptions; + children: React.ReactNode; +} ) { + const { href, onClick } = useLink( to, options ); + + return ( + <a href={ href } onClick={ onClick } { ...props }> + { children } + </a> + ); +} diff --git a/packages/router/src/private-apis.ts b/packages/router/src/private-apis.ts index 7b2945a24ab1a1..9ef316ed716cf4 100644 --- a/packages/router/src/private-apis.ts +++ b/packages/router/src/private-apis.ts @@ -2,6 +2,7 @@ * Internal dependencies */ import { useHistory, useLocation, RouterProvider } from './router'; +import { useLink, Link } from './link'; import { lock } from './lock-unlock'; export const privateApis = {}; @@ -9,4 +10,6 @@ lock( privateApis, { useHistory, useLocation, RouterProvider, + useLink, + Link, } ); diff --git a/packages/router/src/router.tsx b/packages/router/src/router.tsx index 9a1d01aa5f8d88..ea0b218fa6a401 100644 --- a/packages/router/src/router.tsx +++ b/packages/router/src/router.tsx @@ -1,3 +1,9 @@ +/** + * External dependencies + */ +import RouteRecognizer from 'route-recognizer'; +import { createBrowserHistory } from 'history'; + /** * WordPress dependencies */ @@ -5,37 +11,227 @@ import { createContext, useContext, useSyncExternalStore, + useMemo, } from '@wordpress/element'; +import { + addQueryArgs, + getQueryArgs, + getPath, + buildQueryString, +} from '@wordpress/url'; +import { useEvent } from '@wordpress/compose'; /** * Internal dependencies */ -import history from './history'; -import type { EnhancedHistory } from './history'; +import type { ReactNode } from 'react'; + +const history = createBrowserHistory(); +interface Route { + name: string; + path: string; + areas: Record< string, ReactNode >; + widths: Record< string, number >; +} + +type LocationWithQuery = Location & { + query?: Record< string, any >; +}; + +interface Match { + name: string; + path: string; + areas: Record< string, ReactNode >; + widths: Record< string, number >; + query?: Record< string, any >; + params?: Record< string, any >; +} + +export type BeforeNavigate = ( arg: { + path: string; + query: Record< string, any >; +} ) => { + path: string; + query: Record< string, any >; +}; + +interface Config { + pathArg: string; + beforeNavigate?: BeforeNavigate; +} + +export interface NavigationOptions { + transition?: string; + state?: Record< string, any >; +} -const RoutesContext = createContext< Location | null >( null ); -const HistoryContext = createContext< EnhancedHistory >( history ); +const RoutesContext = createContext< Match | null >( null ); +export const ConfigContext = createContext< Config >( { pathArg: 'p' } ); + +const locationMemo = new WeakMap(); +function getLocationWithQuery() { + const location = history.location; + let locationWithQuery = locationMemo.get( location ); + if ( ! locationWithQuery ) { + locationWithQuery = { + ...location, + query: Object.fromEntries( new URLSearchParams( location.search ) ), + }; + locationMemo.set( location, locationWithQuery ); + } + return locationWithQuery; +} export function useLocation() { - return useContext( RoutesContext ); + const context = useContext( RoutesContext ); + if ( ! context ) { + throw new Error( 'useLocation must be used within a RouterProvider' ); + } + return context; } export function useHistory() { - return useContext( HistoryContext ); + const { pathArg, beforeNavigate } = useContext( ConfigContext ); + + const navigate = useEvent( + async ( rawPath: string, options: NavigationOptions = {} ) => { + const query = getQueryArgs( rawPath ); + const path = getPath( 'http://domain.com/' + rawPath ) ?? ''; + const performPush = () => { + const result = beforeNavigate + ? beforeNavigate( { path, query } ) + : { path, query }; + return history.push( + { + search: buildQueryString( { + [ pathArg ]: result.path, + ...result.query, + } ), + }, + options.state + ); + }; + + /* + * Skip transition in mobile, otherwise it crashes the browser. + * See: https://github.com/WordPress/gutenberg/pull/63002. + */ + const isMediumOrBigger = + window.matchMedia( '(min-width: 782px)' ).matches; + if ( + ! isMediumOrBigger || + // @ts-expect-error + ! document.startViewTransition || + ! options.transition + ) { + performPush(); + } + + await new Promise< void >( ( resolve ) => { + const classname = options.transition ?? ''; + document.documentElement.classList.add( classname ); + // @ts-expect-error + const transition = document.startViewTransition( () => + performPush() + ); + transition.finished.finally( () => { + document.documentElement.classList.remove( classname ); + resolve(); + } ); + } ); + } + ); + + return useMemo( + () => ( { + navigate, + } ), + [ navigate ] + ); +} + +export default function useMatch( + location: LocationWithQuery, + matcher: RouteRecognizer, + pathArg: string +): Match { + const { query: rawQuery = {} } = location; + + return useMemo( () => { + const { [ pathArg ]: path = '/', ...query } = rawQuery; + const result = matcher.recognize( path )?.[ 0 ]; + if ( ! result ) { + return { + name: '404', + path: addQueryArgs( path, query ), + areas: {}, + widths: {}, + query, + params: {}, + }; + } + + const matchedRoute = result.handler as Route; + const resolveFunctions = ( record: Record< string, any > = {} ) => { + return Object.fromEntries( + Object.entries( record ).map( ( [ key, value ] ) => { + if ( typeof value === 'function' ) { + return [ + key, + value( { query, params: result.params } ), + ]; + } + return [ key, value ]; + } ) + ); + }; + return { + name: matchedRoute.name, + areas: resolveFunctions( matchedRoute.areas ), + widths: resolveFunctions( matchedRoute.widths ), + params: result.params, + query, + path: addQueryArgs( path, query ), + }; + }, [ matcher, rawQuery, pathArg ] ); } -export function RouterProvider( { children }: { children: React.ReactNode } ) { +export function RouterProvider( { + routes, + pathArg, + beforeNavigate, + children, +}: { + routes: Route[]; + pathArg: string; + beforeNavigate?: BeforeNavigate; + children: React.ReactNode; +} ) { const location = useSyncExternalStore( history.listen, - history.getLocationWithParams, - history.getLocationWithParams + getLocationWithQuery, + getLocationWithQuery + ); + const matcher = useMemo( () => { + const ret = new RouteRecognizer(); + routes.forEach( ( route ) => { + ret.add( [ { path: route.path, handler: route } ], { + as: route.name, + } ); + } ); + return ret; + }, [ routes ] ); + const match = useMatch( location, matcher, pathArg ); + const config = useMemo( + () => ( { beforeNavigate, pathArg } ), + [ beforeNavigate, pathArg ] ); return ( - <HistoryContext.Provider value={ history }> - <RoutesContext.Provider value={ location }> + <ConfigContext.Provider value={ config }> + <RoutesContext.Provider value={ match }> { children } </RoutesContext.Provider> - </HistoryContext.Provider> + </ConfigContext.Provider> ); } diff --git a/packages/router/tsconfig.json b/packages/router/tsconfig.json index e4945eef8bac0c..8706b546ff304d 100644 --- a/packages/router/tsconfig.json +++ b/packages/router/tsconfig.json @@ -4,11 +4,10 @@ "compilerOptions": { "rootDir": "src", "declarationDir": "build-types", - "types": [ "gutenberg-env" ], - "allowJs": false, - "checkJs": false + "types": [ "gutenberg-env" ] }, "references": [ + { "path": "../compose" }, { "path": "../element" }, { "path": "../private-apis" }, { "path": "../url" } diff --git a/test/e2e/specs/editor/various/pattern-overrides.spec.js b/test/e2e/specs/editor/various/pattern-overrides.spec.js index 20eff4096cb1cc..7069b4cec258ab 100644 --- a/test/e2e/specs/editor/various/pattern-overrides.spec.js +++ b/test/e2e/specs/editor/various/pattern-overrides.spec.js @@ -128,7 +128,11 @@ test.describe( 'Pattern Overrides', () => { page.getByRole( 'button', { name: 'Dismiss this notice' } ) ).toBeVisible(); - patternId = new URL( page.url() ).searchParams.get( 'postId' ); + patternId = await page.evaluate( () => { + return window.wp.data + .select( 'core/editor' ) + .getCurrentPostId(); + } ); } ); await test.step( 'Create a post and insert the pattern with overrides', async () => { @@ -1207,7 +1211,11 @@ test.describe( 'Pattern Overrides', () => { page.getByRole( 'button', { name: 'Dismiss this notice' } ) ).toBeVisible(); - patternId = new URL( page.url() ).searchParams.get( 'postId' ); + patternId = await page.evaluate( () => { + return window.wp.data + .select( 'core/editor' ) + .getCurrentPostId(); + } ); } ); await test.step( 'create a post and insert the pattern with synced values', async () => { diff --git a/test/e2e/specs/site-editor/browser-history.spec.js b/test/e2e/specs/site-editor/browser-history.spec.js index eaafb3aad1b3fd..a2326d10e3cc51 100644 --- a/test/e2e/specs/site-editor/browser-history.spec.js +++ b/test/e2e/specs/site-editor/browser-history.spec.js @@ -21,13 +21,13 @@ test.describe( 'Site editor browser history', () => { await page.click( 'role=button[name="Templates"]' ); await page.getByRole( 'link', { name: 'Index' } ).click(); await expect( page ).toHaveURL( - '/wp-admin/site-editor.php?postId=emptytheme%2F%2Findex&postType=wp_template&canvas=edit' + '/wp-admin/site-editor.php?p=%2Fwp_template%2Femptytheme%2F%2Findex&canvas=edit' ); // Navigate back to the template list await page.goBack(); await expect( page ).toHaveURL( - '/wp-admin/site-editor.php?postType=wp_template' + '/wp-admin/site-editor.php?p=%2Ftemplate' ); // Navigate back to the dashboard diff --git a/test/e2e/specs/site-editor/command-center.spec.js b/test/e2e/specs/site-editor/command-center.spec.js index 19318081aa171b..197a01c43c8b46 100644 --- a/test/e2e/specs/site-editor/command-center.spec.js +++ b/test/e2e/specs/site-editor/command-center.spec.js @@ -28,7 +28,7 @@ test.describe( 'Site editor command palette', () => { await page.keyboard.type( 'new page' ); await page.getByRole( 'option', { name: 'Add new page' } ).click(); await expect( page ).toHaveURL( - /\/wp-admin\/site-editor.php\?postId=(\d+)&postType=page&canvas=edit/ + /\/wp-admin\/site-editor.php\?p=%2Fpage%2F(\d+)&canvas=edit/ ); await expect( editor.canvas diff --git a/test/e2e/specs/site-editor/hybrid-theme.spec.js b/test/e2e/specs/site-editor/hybrid-theme.spec.js index b568aaf4445b5c..042cb1042cac22 100644 --- a/test/e2e/specs/site-editor/hybrid-theme.spec.js +++ b/test/e2e/specs/site-editor/hybrid-theme.spec.js @@ -33,7 +33,7 @@ test.describe( 'Hybrid theme', () => { ); await expect( page ).toHaveURL( - '/wp-admin/site-editor.php?postType=wp_template_part' + '/wp-admin/site-editor.php?p=%2Fpattern&postType=wp_template_part' ); await expect( diff --git a/test/e2e/specs/site-editor/site-editor-url-navigation.spec.js b/test/e2e/specs/site-editor/site-editor-url-navigation.spec.js index f26fb8e13b8c3c..a0cc0af5463aed 100644 --- a/test/e2e/specs/site-editor/site-editor-url-navigation.spec.js +++ b/test/e2e/specs/site-editor/site-editor-url-navigation.spec.js @@ -44,7 +44,7 @@ test.describe( 'Site editor url navigation', () => { .click(); await page.getByRole( 'option', { name: 'Demo' } ).click(); await expect( page ).toHaveURL( - '/wp-admin/site-editor.php?postId=emptytheme%2F%2Fsingle-post-demo&postType=wp_template&canvas=edit' + '/wp-admin/site-editor.php?p=%2Fwp_template%2Femptytheme%2F%2Fsingle-post-demo&canvas=edit' ); } ); @@ -63,7 +63,7 @@ test.describe( 'Site editor url navigation', () => { await page.type( 'role=dialog >> role=textbox[name="Name"i]', 'Demo' ); await page.keyboard.press( 'Enter' ); await expect( page ).toHaveURL( - '/wp-admin/site-editor.php?postId=emptytheme%2F%2Fdemo&postType=wp_template_part&canvas=edit' + '/wp-admin/site-editor.php?p=%2Fwp_template_part%2Femptytheme%2F%2Fdemo&canvas=edit' ); } ); From b54d1fe5fe96b00d7f6455b4aaf40bb21ec43967 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Thu, 28 Nov 2024 08:55:30 +0100 Subject: [PATCH 1746/1908] Fix Site editor navigation menu items alignment visual regression. (#67321) Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../src/components/sidebar-navigation-screen/style.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss index 959115e0fac8ca..1486e6b7258441 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss @@ -18,7 +18,7 @@ .edit-site-sidebar-navigation-screen__content { padding: 0 $grid-unit-20; - .edit-site-sidebar-navigation-screen-details-footer { + .components-item-group { margin-left: -$grid-unit-20; margin-right: -$grid-unit-20; } @@ -131,7 +131,7 @@ margin: $grid-unit-20 0 0; border-top: 1px solid $gray-800; - .components-item-group { + .edit-site-sidebar-navigation-screen-details-footer { margin-left: -$grid-unit-20; margin-right: -$grid-unit-20; } From d64cdabc6a1025ff579c90f4bb5b11aa54965e23 Mon Sep 17 00:00:00 2001 From: Grant Kinney <creativecoder@users.noreply.github.com> Date: Thu, 28 Nov 2024 03:35:18 -0600 Subject: [PATCH 1747/1908] Data Views: Add action for pages to set site homepage (#65426) * Adds basic action and modal to set page as homepage * Adds permissions and settings checks to set as homepage action * Adds proper description and handles unpublished pages * Adds action to set homepage to show latest posts * Doesn't show action if there's a front-page template * Creates page for posts, when specified * Refactors modal component * Fixes issues from rebase * Only show option on published pages * Update snackbar wording * Check item exists before running getItemTitle logic * Make key optional on GetEntityRecord * Remove some ts-ignore comments * Add support for page_for_posts to Settings * Remove some more ts-ignores * Allow recordId to be optional * Increase size of action modal * Implement choose existing page option * Fix number/string comparison * Add initial e2e test * Set post actions modal to medium * Tweak ToggleGroupControl help text * Fix initial test * Remove extra useSiteSettings hook * Allow setting draft pages to homepage * Fix merge conflict * Remove item check from getItemTitle * Remove posts page options * Don't show homepage option if selected page is the page for posts * Reload actions list when site settings change * Update tests * Remove call to __experimentalGetTemplateForLink * Update tests * Remove item check in getItemTitle * Use useSelect instead of select * Remove PAGE_POST_TYPE constant * Use saveEntityRecord instead of editEntityRecord * Remove onSetLatestPostsHomepage option * Remove select for site settings from isEligible * Update post actions with site settings info * Remove select for templates from isEligible * Skip last test for now * Restore whitespace * Rename _select * Remove sub-objects from additionalContext selectors * Remove duplicate page_for_posts definition * Fix page/post type error * Remove additional groups within additionalContext * Fix siteSettings in TitleView * Move hasFrontPageTemplate check to private-actions * Add JSDoc to setAsHomepage * Refactor siteSettings in post-list * Move homepage action to edit-site * Revert unnecessary changes * Move getItemTitle to edit-site utils * Allow undefined on GetEntityRecord key * Make it more clear that draft page will be published * Update draft page wording * Add set homepage action to post editor * Attempt to fix build error * Remove homepage action from edit-site * Remove extra line * Fix getting current homepage title * Make key in getEntityRecord optional * Use getHomePage selector * Move canManageOptions and hasFrontPageTemplate to actions.js * Make key optional in EntityRecordKey * Remove undefined from getEntityRecord calls * Update packages/editor/src/components/post-actions/actions.js Co-authored-by: Dave Smith <getdavemail@gmail.com> * Update getEntityRecord key docs * Refactor fetching currentHomePage * Disable modal buttons if saving * Store isPageDraft in useRef * Fix lint error * Remove onActionPerformed * Fix current homepage test * Remove duplicate getItemTitle function * Update logic for shouldShowSetAsHomepageAction * Swap order of list of actions * Add comment about manual saveEntityRecord call * Remove unnecessary space * Remove temporary modalButtonLabel variable * Combine draft and publish status tests * Only allow action on pages with draft or publish status * Remove handling of draft pages * Move closeModal into finally block * Refactor and remove renderModalBody --------- Co-authored-by: Sarah Norris <sarah@sekai.co.uk> Co-authored-by: Sarah Norris <1645628+mikachan@users.noreply.github.com> Co-authored-by: Dave Smith <getdavemail@gmail.com> Co-authored-by: creativecoder <grantmkin@git.wordpress.org> Co-authored-by: mikachan <mikachan@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> --- docs/reference-guides/data/data-core.md | 2 +- packages/core-data/README.md | 2 +- packages/core-data/src/private-selectors.ts | 1 - packages/core-data/src/selectors.ts | 8 +- .../dataviews-item-actions/index.tsx | 2 +- .../src/components/post-actions/actions.js | 39 +++- .../src/components/post-actions/index.js | 2 +- .../post-actions/set-as-homepage.js | 174 ++++++++++++++++++ packages/editor/src/dataviews/types.ts | 2 +- packages/fields/src/actions/utils.ts | 2 +- .../fields/src/fields/title/title-view.tsx | 7 +- .../site-editor/homepage-settings.spec.js | 72 ++++++++ 12 files changed, 296 insertions(+), 17 deletions(-) create mode 100644 packages/editor/src/components/post-actions/set-as-homepage.js create mode 100644 test/e2e/specs/site-editor/homepage-settings.spec.js diff --git a/docs/reference-guides/data/data-core.md b/docs/reference-guides/data/data-core.md index 474207aa20460f..199c29cd67dd2e 100644 --- a/docs/reference-guides/data/data-core.md +++ b/docs/reference-guides/data/data-core.md @@ -359,7 +359,7 @@ _Parameters_ - _state_ `State`: State tree - _kind_ `string`: Entity kind. - _name_ `string`: Entity name. -- _key_ `EntityRecordKey`: Record's key +- _key_ `EntityRecordKey`: Optional record's key. If requesting a global record (e.g. site settings), the key can be omitted. If requesting a specific item, the key must always be included. - _query_ `GetRecordsHttpQuery`: Optional query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available "Retrieve a [Entity kind]". _Returns_ diff --git a/packages/core-data/README.md b/packages/core-data/README.md index eb6980cdd4eea1..9549e6742d8cd8 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -581,7 +581,7 @@ _Parameters_ - _state_ `State`: State tree - _kind_ `string`: Entity kind. - _name_ `string`: Entity name. -- _key_ `EntityRecordKey`: Record's key +- _key_ `EntityRecordKey`: Optional record's key. If requesting a global record (e.g. site settings), the key can be omitted. If requesting a specific item, the key must always be included. - _query_ `GetRecordsHttpQuery`: Optional query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available "Retrieve a [Entity kind]". _Returns_ diff --git a/packages/core-data/src/private-selectors.ts b/packages/core-data/src/private-selectors.ts index 02fe152ed0abb6..77790512653065 100644 --- a/packages/core-data/src/private-selectors.ts +++ b/packages/core-data/src/private-selectors.ts @@ -151,7 +151,6 @@ export const getHomePage = createRegistrySelector( ( select ) => return { postType: 'wp_template', postId: frontPageTemplateId }; }, ( state ) => [ - // @ts-expect-error getEntityRecord( state, 'root', 'site' ), getDefaultTemplateId( state, { slug: 'front-page', diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index 7ea8c2f7f26d53..7f4b0d38846468 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -310,7 +310,7 @@ export interface GetEntityRecord { state: State, kind: string, name: string, - key: EntityRecordKey, + key?: EntityRecordKey, query?: GetRecordsHttpQuery ): EntityRecord | undefined; @@ -321,7 +321,7 @@ export interface GetEntityRecord { >( kind: string, name: string, - key: EntityRecordKey, + key?: EntityRecordKey, query?: GetRecordsHttpQuery ) => EntityRecord | undefined; __unstableNormalizeArgs?: ( args: EntityRecordArgs ) => EntityRecordArgs; @@ -335,7 +335,7 @@ export interface GetEntityRecord { * @param state State tree * @param kind Entity kind. * @param name Entity name. - * @param key Record's key + * @param key Optional record's key. If requesting a global record (e.g. site settings), the key can be omitted. If requesting a specific item, the key must always be included. * @param query Optional query. If requesting specific * fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available "Retrieve a [Entity kind]". * @@ -350,7 +350,7 @@ export const getEntityRecord = createSelector( state: State, kind: string, name: string, - key: EntityRecordKey, + key?: EntityRecordKey, query?: GetRecordsHttpQuery ): EntityRecord | undefined => { const queriedState = diff --git a/packages/dataviews/src/components/dataviews-item-actions/index.tsx b/packages/dataviews/src/components/dataviews-item-actions/index.tsx index 787cef4420acc0..b5eaac11bcd8d0 100644 --- a/packages/dataviews/src/components/dataviews-item-actions/index.tsx +++ b/packages/dataviews/src/components/dataviews-item-actions/index.tsx @@ -114,7 +114,7 @@ export function ActionModal< Item >( { __experimentalHideHeader={ !! action.hideModalHeader } onRequestClose={ closeModal ?? ( () => {} ) } focusOnMount="firstContentElement" - size="small" + size="medium" overlayClassName={ `dataviews-action-modal dataviews-action-modal__${ kebabCase( action.id ) }` } diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 8dbe5b9dfcd5ad..1b6ff4fbe384b5 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -3,12 +3,14 @@ */ import { useDispatch, useSelect } from '@wordpress/data'; import { useMemo, useEffect } from '@wordpress/element'; +import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies */ import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; +import { useSetAsHomepageAction } from './set-as-homepage'; export function usePostActions( { postType, onActionPerformed, context } ) { const { defaultActions } = useSelect( @@ -21,19 +23,46 @@ export function usePostActions( { postType, onActionPerformed, context } ) { [ postType ] ); + const { canManageOptions, hasFrontPageTemplate } = useSelect( + ( select ) => { + const { getEntityRecords } = select( coreStore ); + const templates = getEntityRecords( 'postType', 'wp_template', { + per_page: -1, + } ); + + return { + canManageOptions: select( coreStore ).canUser( 'update', { + kind: 'root', + name: 'site', + } ), + hasFrontPageTemplate: !! templates?.find( + ( template ) => template?.slug === 'front-page' + ), + }; + } + ); + + const setAsHomepageAction = useSetAsHomepageAction(); + const shouldShowSetAsHomepageAction = + canManageOptions && ! hasFrontPageTemplate; + const { registerPostTypeSchema } = unlock( useDispatch( editorStore ) ); useEffect( () => { registerPostTypeSchema( postType ); }, [ registerPostTypeSchema, postType ] ); return useMemo( () => { + let actions = [ + ...defaultActions, + shouldShowSetAsHomepageAction ? setAsHomepageAction : [], + ]; // Filter actions based on provided context. If not provided // all actions are returned. We'll have a single entry for getting the actions // and the consumer should provide the context to filter the actions, if needed. // Actions should also provide the `context` they support, if it's specific, to // compare with the provided context to get all the actions. // Right now the only supported context is `list`. - const actions = defaultActions.filter( ( action ) => { + actions = actions.filter( ( action ) => { if ( ! action.context ) { return true; } @@ -88,5 +117,11 @@ export function usePostActions( { postType, onActionPerformed, context } ) { } return actions; - }, [ defaultActions, onActionPerformed, context ] ); + }, [ + context, + defaultActions, + onActionPerformed, + setAsHomepageAction, + shouldShowSetAsHomepageAction, + ] ); } diff --git a/packages/editor/src/components/post-actions/index.js b/packages/editor/src/components/post-actions/index.js index 9f39b1f3305aeb..ab11b5e318b5a6 100644 --- a/packages/editor/src/components/post-actions/index.js +++ b/packages/editor/src/components/post-actions/index.js @@ -123,7 +123,7 @@ function ActionWithModal( { action, item, ActionTrigger, onClose } ) { action.id ) }` } focusOnMount="firstContentElement" - size="small" + size="medium" > <RenderModal items={ [ item ] } diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js new file mode 100644 index 00000000000000..0366a52482f2a8 --- /dev/null +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -0,0 +1,174 @@ +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; +import { useMemo } from '@wordpress/element'; +import { + Button, + __experimentalText as Text, + __experimentalHStack as HStack, + __experimentalVStack as VStack, +} from '@wordpress/components'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { store as noticesStore } from '@wordpress/notices'; + +/** + * Internal dependencies + */ +import { getItemTitle } from '../../dataviews/actions/utils'; + +const SetAsHomepageModal = ( { items, closeModal } ) => { + const [ item ] = items; + const pageTitle = getItemTitle( item ); + const { showOnFront, currentHomePage, isSaving } = useSelect( + ( select ) => { + const { getEntityRecord, isSavingEntityRecord } = + select( coreStore ); + const siteSettings = getEntityRecord( 'root', 'site' ); + const currentHomePageItem = getEntityRecord( + 'postType', + 'page', + siteSettings?.page_on_front + ); + return { + showOnFront: siteSettings?.show_on_front, + currentHomePage: currentHomePageItem, + isSaving: isSavingEntityRecord( 'root', 'site' ), + }; + } + ); + const currentHomePageTitle = currentHomePage + ? getItemTitle( currentHomePage ) + : ''; + + const { saveEditedEntityRecord, saveEntityRecord } = + useDispatch( coreStore ); + const { createSuccessNotice, createErrorNotice } = + useDispatch( noticesStore ); + + async function onSetPageAsHomepage( event ) { + event.preventDefault(); + + try { + // Save new home page settings. + await saveEditedEntityRecord( 'root', 'site', undefined, { + page_on_front: item.id, + show_on_front: 'page', + } ); + + // This second call to a save function is a workaround for a bug in + // `saveEditedEntityRecord`. This forces the root site settings to be updated. + // See https://github.com/WordPress/gutenberg/issues/67161. + await saveEntityRecord( 'root', 'site', { + page_on_front: item.id, + show_on_front: 'page', + } ); + + createSuccessNotice( __( 'Homepage updated' ), { + type: 'snackbar', + } ); + } catch ( error ) { + const typedError = error; + const errorMessage = + typedError.message && typedError.code !== 'unknown_error' + ? typedError.message + : __( 'An error occurred while setting the homepage' ); + createErrorNotice( errorMessage, { type: 'snackbar' } ); + } finally { + closeModal?.(); + } + } + + const modalWarning = + 'posts' === showOnFront + ? __( + 'This will replace the current homepage which is set to display latest posts.' + ) + : sprintf( + // translators: %s: title of the current home page. + __( 'This will replace the current homepage: "%s"' ), + currentHomePageTitle + ); + + const modalText = sprintf( + // translators: %1$s: title of the page to be set as the homepage, %2$s: homepage replacement warning message. + __( 'Set "%1$s" as the site homepage? %2$s' ), + pageTitle, + modalWarning + ); + + // translators: Button label to confirm setting the specified page as the homepage. + const modalButtonLabel = __( 'Set homepage' ); + + return ( + <form onSubmit={ onSetPageAsHomepage }> + <VStack spacing="5"> + <Text>{ modalText }</Text> + <HStack justify="right"> + <Button + __next40pxDefaultSize + variant="tertiary" + onClick={ () => { + closeModal?.(); + } } + disabled={ isSaving } + accessibleWhenDisabled + > + { __( 'Cancel' ) } + </Button> + <Button + __next40pxDefaultSize + variant="primary" + type="submit" + disabled={ isSaving } + accessibleWhenDisabled + > + { modalButtonLabel } + </Button> + </HStack> + </VStack> + </form> + ); +}; + +export const useSetAsHomepageAction = () => { + const { pageOnFront, pageForPosts } = useSelect( ( select ) => { + const { getEntityRecord } = select( coreStore ); + const siteSettings = getEntityRecord( 'root', 'site' ); + return { + pageOnFront: siteSettings?.page_on_front, + pageForPosts: siteSettings?.page_for_posts, + }; + } ); + + return useMemo( + () => ( { + id: 'set-as-homepage', + label: __( 'Set as homepage' ), + isEligible( post ) { + if ( post.status !== 'publish' ) { + return false; + } + + if ( post.type !== 'page' ) { + return false; + } + + // Don't show the action if the page is already set as the homepage. + if ( pageOnFront === post.id ) { + return false; + } + + // Don't show the action if the page is already set as the page for posts. + if ( pageForPosts === post.id ) { + return false; + } + + return true; + }, + RenderModal: SetAsHomepageModal, + } ), + [ pageForPosts, pageOnFront ] + ); +}; diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts index 664c2dd417201c..4d27fc7dc4139d 100644 --- a/packages/editor/src/dataviews/types.ts +++ b/packages/editor/src/dataviews/types.ts @@ -1,5 +1,5 @@ type PostStatus = - | 'published' + | 'publish' | 'draft' | 'pending' | 'private' diff --git a/packages/fields/src/actions/utils.ts b/packages/fields/src/actions/utils.ts index 60d3d00e82766a..8f990fb1168fcc 100644 --- a/packages/fields/src/actions/utils.ts +++ b/packages/fields/src/actions/utils.ts @@ -30,7 +30,7 @@ export function isTemplateOrTemplatePart( return p.type === TEMPLATE_POST_TYPE || p.type === TEMPLATE_PART_POST_TYPE; } -export function getItemTitle( item: Post ) { +export function getItemTitle( item: Post ): string { if ( typeof item.title === 'string' ) { return decodeEntities( item.title ); } diff --git a/packages/fields/src/fields/title/title-view.tsx b/packages/fields/src/fields/title/title-view.tsx index c15ed96b89b73b..f6bf5fb1817d93 100644 --- a/packages/fields/src/fields/title/title-view.tsx +++ b/packages/fields/src/fields/title/title-view.tsx @@ -17,11 +17,10 @@ import { getItemTitle } from '../../actions/utils'; const TitleView = ( { item }: { item: BasePost } ) => { const { frontPageId, postsPageId } = useSelect( ( select ) => { const { getEntityRecord } = select( coreStore ); - const siteSettings: Settings | undefined = getEntityRecord( + const siteSettings = getEntityRecord( 'root', - 'site', - '' - ); + 'site' + ) as Partial< Settings >; return { frontPageId: siteSettings?.page_on_front, postsPageId: siteSettings?.page_for_posts, diff --git a/test/e2e/specs/site-editor/homepage-settings.spec.js b/test/e2e/specs/site-editor/homepage-settings.spec.js new file mode 100644 index 00000000000000..d53130af23ac8b --- /dev/null +++ b/test/e2e/specs/site-editor/homepage-settings.spec.js @@ -0,0 +1,72 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.describe( 'Homepage Settings via Editor', () => { + test.beforeAll( async ( { requestUtils } ) => { + await Promise.all( [ requestUtils.activateTheme( 'emptytheme' ) ] ); + await requestUtils.createPage( { + title: 'Homepage', + status: 'publish', + } ); + } ); + + test.beforeEach( async ( { admin, page } ) => { + await admin.visitSiteEditor(); + await page.getByRole( 'button', { name: 'Pages' } ).click(); + } ); + + test.afterAll( async ( { requestUtils } ) => { + await Promise.all( [ + requestUtils.deleteAllPages(), + requestUtils.updateSiteSettings( { + show_on_front: 'posts', + page_on_front: 0, + page_for_posts: 0, + } ), + ] ); + } ); + + test( 'should show "Set as homepage" action on pages with `publish` status', async ( { + page, + } ) => { + const samplePage = page + .getByRole( 'gridcell' ) + .getByLabel( 'Homepage' ); + const samplePageRow = page + .getByRole( 'row' ) + .filter( { has: samplePage } ); + await samplePageRow.hover(); + await samplePageRow + .getByRole( 'button', { + name: 'Actions', + } ) + .click(); + await expect( + page.getByRole( 'menuitem', { name: 'Set as homepage' } ) + ).toBeVisible(); + } ); + + test( 'should not show "Set as homepage" action on current homepage', async ( { + page, + } ) => { + const samplePage = page + .getByRole( 'gridcell' ) + .getByLabel( 'Homepage' ); + const samplePageRow = page + .getByRole( 'row' ) + .filter( { has: samplePage } ); + await samplePageRow.click(); + await samplePageRow + .getByRole( 'button', { + name: 'Actions', + } ) + .click(); + await page.getByRole( 'menuitem', { name: 'Set as homepage' } ).click(); + await page.getByRole( 'button', { name: 'Set homepage' } ).click(); + await expect( + page.getByRole( 'menuitem', { name: 'Set as homepage' } ) + ).toBeHidden(); + } ); +} ); From 2efb3a9f7c87dae155b71ad520ac5aa00f7490b4 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 28 Nov 2024 10:39:35 +0100 Subject: [PATCH 1748/1908] REST API: Support search_columns argument in the user endpoint (#67330) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: mreishus <mreishus@git.wordpress.org> Co-authored-by claudiulodro < claudiulodro@git.wordpress.org> --- backport-changelog/6.8/7909.md | 3 + .../class-gutenberg-rest-user-controller.php | 62 +++++++++++++++++++ lib/load.php | 1 + .../src/components/post-author/constants.js | 2 +- .../editor/src/components/post-author/hook.js | 1 + 5 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 backport-changelog/6.8/7909.md create mode 100644 lib/compat/wordpress-6.8/class-gutenberg-rest-user-controller.php diff --git a/backport-changelog/6.8/7909.md b/backport-changelog/6.8/7909.md new file mode 100644 index 00000000000000..32a441ef296a2d --- /dev/null +++ b/backport-changelog/6.8/7909.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7909 + +* https://github.com/WordPress/gutenberg/pull/67330 diff --git a/lib/compat/wordpress-6.8/class-gutenberg-rest-user-controller.php b/lib/compat/wordpress-6.8/class-gutenberg-rest-user-controller.php new file mode 100644 index 00000000000000..c1ecb8c86660cd --- /dev/null +++ b/lib/compat/wordpress-6.8/class-gutenberg-rest-user-controller.php @@ -0,0 +1,62 @@ +<?php + +/** + * Add search_columns parameter to users endpoint parameters + * + * @param array $query_params JSON Schema-formatted collection parameters. + * @return array Updated collection parameters + */ +function gutenberg_add_search_columns_param( $query_params ) { + $query_params['search_columns'] = array( + 'default' => array(), + 'description' => __( 'Array of column names to be searched.' ), + 'type' => 'array', + 'items' => array( + 'enum' => array( 'email', 'name', 'id', 'username', 'slug' ), + 'type' => 'string', + ), + ); + + return $query_params; +} + +add_filter( 'rest_user_collection_params', 'gutenberg_add_search_columns_param', 10, 1 ); + +/** + * Modify user query based on search_columns parameter + * + * @param array $prepared_args Array of arguments for WP_User_Query. + * @param WP_REST_Request $request The REST API request. + * @return array Modified arguments + */ +function gutenberg_modify_user_query_args( $prepared_args, $request ) { + if ( $request->get_param( 'search' ) && $request->get_param( 'search_columns' ) ) { + $search_columns = $request->get_param( 'search_columns' ); + + // Validate search columns + $valid_columns = isset( $prepared_args['search_columns'] ) + ? $prepared_args['search_columns'] + : array( 'ID', 'user_login', 'user_nicename', 'user_email', 'user_url', 'display_name' ); + $search_columns_mapping = array( + 'id' => 'ID', + 'username' => 'user_login', + 'slug' => 'user_nicename', + 'email' => 'user_email', + 'name' => 'display_name', + ); + $search_columns = array_map( + static function ( $column ) use ( $search_columns_mapping ) { + return $search_columns_mapping[ $column ]; + }, + $search_columns + ); + $search_columns = array_intersect( $search_columns, $valid_columns ); + + if ( ! empty( $search_columns ) ) { + $prepared_args['search_columns'] = $search_columns; + } + } + + return $prepared_args; +} +add_filter( 'rest_user_query', 'gutenberg_modify_user_query_args', 10, 2 ); diff --git a/lib/load.php b/lib/load.php index 97c5404a3a3ead..26af78f3173c53 100644 --- a/lib/load.php +++ b/lib/load.php @@ -99,6 +99,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.8/functions.php'; require __DIR__ . '/compat/wordpress-6.8/post.php'; require __DIR__ . '/compat/wordpress-6.8/site-editor.php'; +require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-user-controller.php'; // Experimental features. require __DIR__ . '/experimental/block-editor-settings-mobile.php'; diff --git a/packages/editor/src/components/post-author/constants.js b/packages/editor/src/components/post-author/constants.js index 46bc2d46d1b086..517cbd9ea1dc8d 100644 --- a/packages/editor/src/components/post-author/constants.js +++ b/packages/editor/src/components/post-author/constants.js @@ -5,6 +5,6 @@ export const BASE_QUERY = { export const AUTHORS_QUERY = { who: 'authors', - per_page: 50, + per_page: 100, ...BASE_QUERY, }; diff --git a/packages/editor/src/components/post-author/hook.js b/packages/editor/src/components/post-author/hook.js index 62830cf6ea60e6..f251eba79e1806 100644 --- a/packages/editor/src/components/post-author/hook.js +++ b/packages/editor/src/components/post-author/hook.js @@ -23,6 +23,7 @@ export function useAuthorsQuery( search ) { if ( search ) { query.search = search; + query.search_columns = [ 'name' ]; } return { From a48a414853b7f66606393dd311556e6bdda1aa62 Mon Sep 17 00:00:00 2001 From: Yogesh Bhutkar <yogesh.bhutkar@rtcamp.com> Date: Thu, 28 Nov 2024 15:43:06 +0530 Subject: [PATCH 1749/1908] CommentsPagination: Set font-size to inherit for pagination items (#67296) * CommentsPagination: Set font-size to inherit for pagination items * Remove extra spaces --------- Co-authored-by: yogeshbhutkar <yogeshbhutkar@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- packages/block-library/src/comments-pagination/editor.scss | 1 + packages/block-library/src/comments-pagination/style.scss | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/block-library/src/comments-pagination/editor.scss b/packages/block-library/src/comments-pagination/editor.scss index a875c9e0ee21ce..3cd99c632ee833 100644 --- a/packages/block-library/src/comments-pagination/editor.scss +++ b/packages/block-library/src/comments-pagination/editor.scss @@ -26,6 +26,7 @@ $pagination-margin: 0.5em; margin-right: $pagination-margin; margin-bottom: $pagination-margin; + font-size: inherit; &:last-child { /*rtl:ignore*/ margin-right: 0; diff --git a/packages/block-library/src/comments-pagination/style.scss b/packages/block-library/src/comments-pagination/style.scss index c6b5d9a0a29e91..2fb6e3dd2d48f4 100644 --- a/packages/block-library/src/comments-pagination/style.scss +++ b/packages/block-library/src/comments-pagination/style.scss @@ -8,6 +8,7 @@ $pagination-margin: 0.5em; margin-right: $pagination-margin; margin-bottom: $pagination-margin; + font-size: inherit; &:last-child { /*rtl:ignore*/ margin-right: 0; From f414562bee98285ed512ac4f9dfd6ca0609fa6a6 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Thu, 28 Nov 2024 11:54:14 +0100 Subject: [PATCH 1750/1908] Block Bindings: Remove client core sources registration in widgets (#67349) * Remove client core sources registration in widgets * Remove dependencies Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- package-lock.json | 2 -- packages/customize-widgets/package.json | 1 - packages/customize-widgets/src/index.js | 5 ----- packages/edit-widgets/package.json | 1 - packages/edit-widgets/src/index.js | 5 ----- 5 files changed, 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index dc0c18f3b6ac5e..80a64c6f7a04ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53963,7 +53963,6 @@ "@wordpress/core-data": "*", "@wordpress/data": "*", "@wordpress/dom": "*", - "@wordpress/editor": "*", "@wordpress/element": "*", "@wordpress/hooks": "*", "@wordpress/i18n": "*", @@ -54392,7 +54391,6 @@ "@wordpress/data": "*", "@wordpress/deprecated": "*", "@wordpress/dom": "*", - "@wordpress/editor": "*", "@wordpress/element": "*", "@wordpress/hooks": "*", "@wordpress/i18n": "*", diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 4a14ac743b7249..10c3b2dfb510d9 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -34,7 +34,6 @@ "@wordpress/core-data": "*", "@wordpress/data": "*", "@wordpress/dom": "*", - "@wordpress/editor": "*", "@wordpress/element": "*", "@wordpress/hooks": "*", "@wordpress/i18n": "*", diff --git a/packages/customize-widgets/src/index.js b/packages/customize-widgets/src/index.js index df96d645ee7007..5de010fa8bd37e 100644 --- a/packages/customize-widgets/src/index.js +++ b/packages/customize-widgets/src/index.js @@ -17,7 +17,6 @@ import { store as blocksStore, } from '@wordpress/blocks'; import { dispatch } from '@wordpress/data'; -import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { store as preferencesStore } from '@wordpress/preferences'; /** @@ -27,7 +26,6 @@ import CustomizeWidgets from './components/customize-widgets'; import getSidebarSection from './controls/sidebar-section'; import getSidebarControl from './controls/sidebar-control'; import './filters'; -import { unlock } from './lock-unlock'; const { wp } = window; @@ -39,8 +37,6 @@ const DISABLED_BLOCKS = [ ]; const ENABLE_EXPERIMENTAL_FSE_BLOCKS = false; -const { registerCoreBlockBindingsSources } = unlock( editorPrivateApis ); - /** * Initializes the widgets block editor in the customizer. * @@ -64,7 +60,6 @@ export function initialize( editorName, blockEditorSettings ) { ); } ); registerCoreBlocks( coreBlocks ); - registerCoreBlockBindingsSources(); registerLegacyWidgetBlock(); if ( globalThis.IS_GUTENBERG_PLUGIN ) { __experimentalRegisterExperimentalCoreBlocks( { diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index ed375f7430a1a4..0528348291481a 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -39,7 +39,6 @@ "@wordpress/data": "*", "@wordpress/deprecated": "*", "@wordpress/dom": "*", - "@wordpress/editor": "*", "@wordpress/element": "*", "@wordpress/hooks": "*", "@wordpress/i18n": "*", diff --git a/packages/edit-widgets/src/index.js b/packages/edit-widgets/src/index.js index 8788ee2b99ea1d..2f0ced0c09bd75 100644 --- a/packages/edit-widgets/src/index.js +++ b/packages/edit-widgets/src/index.js @@ -9,7 +9,6 @@ import { } from '@wordpress/blocks'; import { dispatch } from '@wordpress/data'; import deprecated from '@wordpress/deprecated'; -import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { StrictMode, createRoot } from '@wordpress/element'; import { registerCoreBlocks, @@ -30,7 +29,6 @@ import { store as preferencesStore } from '@wordpress/preferences'; import './store'; import './filters'; import * as widgetArea from './blocks/widget-area'; -import { unlock } from './lock-unlock'; import Layout from './components/layout'; import { ALLOW_REUSABLE_BLOCKS, @@ -44,8 +42,6 @@ const disabledBlocks = [ ...( ALLOW_REUSABLE_BLOCKS ? [] : [ 'core/block' ] ), ]; -const { registerCoreBlockBindingsSources } = unlock( editorPrivateApis ); - /** * Initializes the block editor in the widgets screen. * @@ -75,7 +71,6 @@ export function initializeEditor( id, settings ) { dispatch( blocksStore ).reapplyBlockTypeFilters(); registerCoreBlocks( coreBlocks ); - registerCoreBlockBindingsSources(); registerLegacyWidgetBlock(); if ( globalThis.IS_GUTENBERG_PLUGIN ) { __experimentalRegisterExperimentalCoreBlocks( { From c845cdad4b98b531d8e9924b36aeea2b01709b4f Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:17:30 +0200 Subject: [PATCH 1751/1908] Router: Fix addition and removal of empty classnames (#67378) * Router: Fix addition and removal of empty classnames * Actually prevent transition Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- packages/router/src/router.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/router/src/router.tsx b/packages/router/src/router.tsx index ea0b218fa6a401..34cc542c7b5737 100644 --- a/packages/router/src/router.tsx +++ b/packages/router/src/router.tsx @@ -125,6 +125,7 @@ export function useHistory() { ! options.transition ) { performPush(); + return; } await new Promise< void >( ( resolve ) => { From 45d9528de2da7edb3a162d5df82fb646c067e052 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Thu, 28 Nov 2024 15:16:57 +0200 Subject: [PATCH 1752/1908] DataViews: Update `usePostFields` to accept postType (#67380) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- .../src/components/post-edit/index.js | 2 +- .../src/components/post-list/index.js | 4 +++- .../src/components/post-fields/index.ts | 8 ++++--- .../src/dataviews/store/private-actions.ts | 21 +++++++++---------- packages/editor/src/dataviews/types.ts | 3 +++ 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index a7842f0feb3c2f..3e75ef71d1ac9b 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -49,7 +49,7 @@ function PostEditForm( { postType, postId } ) { ); const [ multiEdits, setMultiEdits ] = useState( {} ); const { editEntityRecord } = useDispatch( coreDataStore ); - const { fields: _fields } = usePostFields(); + const { fields: _fields } = usePostFields( { postType } ); const fields = useMemo( () => _fields?.map( ( field ) => { diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index d58ddbe50758c7..200aa60ee17977 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -215,7 +215,9 @@ export default function PostList( { postType } ) { return found?.filters ?? []; }; - const { isLoading: isLoadingFields, fields: _fields } = usePostFields(); + const { isLoading: isLoadingFields, fields: _fields } = usePostFields( { + postType, + } ); const fields = useMemo( () => { const activeViewFilters = getActiveViewFilters( defaultViews, diff --git a/packages/editor/src/components/post-fields/index.ts b/packages/editor/src/components/post-fields/index.ts index 41b61fe103a70f..d701bdef2284e6 100644 --- a/packages/editor/src/components/post-fields/index.ts +++ b/packages/editor/src/components/post-fields/index.ts @@ -23,9 +23,11 @@ interface Author { name: string; } -function usePostFields(): UsePostFieldsReturn { - const postType = 'page'; // TODO: this could be page or post (experimental). - +function usePostFields( { + postType, +}: { + postType: string; +} ): UsePostFieldsReturn { const { registerPostTypeSchema } = unlock( useDispatch( editorStore ) ); useEffect( () => { registerPostTypeSchema( postType ); diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 77ac131a8e2302..9e8d184e34d3a4 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -128,7 +128,7 @@ export const registerPostTypeSchema = const actions = [ postTypeConfig.viewable ? viewPost : undefined, - !! postTypeConfig?.supports?.revisions + !! postTypeConfig.supports?.revisions ? viewPostRevisions : undefined, // @ts-ignore @@ -148,7 +148,7 @@ export const registerPostTypeSchema = ? duplicatePattern : undefined, postTypeConfig.supports?.title ? renamePost : undefined, - postTypeConfig?.supports?.[ 'page-attributes' ] + postTypeConfig.supports?.[ 'page-attributes' ] ? reorderPage : undefined, postTypeConfig.slug === 'wp_block' ? exportPattern : undefined, @@ -157,25 +157,24 @@ export const registerPostTypeSchema = deletePost, trashPost, permanentlyDeletePost, - ]; + ].filter( Boolean ); const fields = [ - featuredImageField, + postTypeConfig.supports?.thumbnail && + currentTheme?.[ 'theme-supports' ]?.[ 'post-thumbnails' ] && + featuredImageField, titleField, - authorField, + postTypeConfig.supports?.author && authorField, statusField, dateField, slugField, - parentField, - commentStatusField, + postTypeConfig.supports?.[ 'page-attributes' ] && parentField, + postTypeConfig.supports?.comments && commentStatusField, passwordField, - ]; + ].filter( Boolean ); registry.batch( () => { actions.forEach( ( action ) => { - if ( ! action ) { - return; - } unlock( registry.dispatch( editorStore ) ).registerEntityAction( 'postType', postType, diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts index 4d27fc7dc4139d..9549e6c4aa374d 100644 --- a/packages/editor/src/dataviews/types.ts +++ b/packages/editor/src/dataviews/types.ts @@ -78,6 +78,9 @@ export interface PostType { 'page-attributes'?: boolean; title?: boolean; revisions?: boolean; + thumbnail?: boolean; + comments?: boolean; + author?: boolean; }; } From daaa785b27c4124c7d39a7ee12bc2b4ce0359aa4 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:05:14 +0200 Subject: [PATCH 1753/1908] Edit Site: Fix sidebar template author navigation (#67382) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../sidebar-navigation-screen-templates-browse/content.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js b/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js index 5d3819eac0ee3c..aad38959c73dcd 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js @@ -6,6 +6,7 @@ import { useMemo } from '@wordpress/element'; import { __experimentalItemGroup as ItemGroup } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies @@ -25,7 +26,7 @@ function TemplateDataviewItem( { template, isActive } ) { return ( <SidebarNavigationItem - to={ `/template?activeView=${ text }` } + to={ addQueryArgs( '/template', { activeView: text } ) } icon={ icon } aria-current={ isActive } > From 007daf07967134b15a09eb7b9f0e59f7ffa0584e Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Thu, 28 Nov 2024 15:29:40 +0100 Subject: [PATCH 1754/1908] Only pass `aria-label` when it is not empty (#67381) Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- packages/block-library/src/navigation/index.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index 68b23aceeced65..9a56e399fcfecb 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -567,13 +567,14 @@ private static function get_nav_wrapper_attributes( $attributes, $inner_blocks ) $is_responsive_menu = static::is_responsive( $attributes ); $style = static::get_styles( $attributes ); $class = static::get_classes( $attributes ); - $wrapper_attributes = get_block_wrapper_attributes( - array( - 'class' => $class, - 'style' => $style, - 'aria-label' => $nav_menu_name, - ) + $extra_attributes = array( + 'class' => $class, + 'style' => $style, ); + if ( ! empty( $nav_menu_name ) ) { + $extra_attributes['aria-label'] = $nav_menu_name; + } + $wrapper_attributes = get_block_wrapper_attributes( $extra_attributes ); if ( $is_responsive_menu ) { $nav_element_directives = static::get_nav_element_directives( $is_interactive ); From 81327d1e18a724758eedbb461bde29dfd8b41b7f Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 28 Nov 2024 15:54:46 +0100 Subject: [PATCH 1755/1908] Update @ariakit/react to 0.4.13 (#65907) * Remove all ariakit dependencies * Re-add ariakit dependencies targeting latest version * Remove focus-visible DropdownMenuV2 workaround * Remove composite tabbable workaround * CHANGELOG * Remove Tabs workaround --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: diegohaz <hazdiego@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- package-lock.json | 82 ++++++++++++------- package.json | 2 +- packages/components/CHANGELOG.md | 6 +- packages/components/package.json | 2 +- packages/components/src/composite/item.tsx | 20 +---- .../components/src/menu/checkbox-item.tsx | 6 +- packages/components/src/menu/item.tsx | 6 +- packages/components/src/menu/radio-item.tsx | 6 +- .../menu/use-temporary-focus-visible-fix.ts | 22 ----- packages/components/src/tabs/tab.tsx | 18 ---- packages/dataviews/package.json | 2 +- 11 files changed, 63 insertions(+), 109 deletions(-) delete mode 100644 packages/components/src/menu/use-temporary-focus-visible-fix.ts diff --git a/package-lock.json b/package-lock.json index 80a64c6f7a04ba..58479ecfa2ed99 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@actions/core": "1.9.1", "@actions/github": "5.0.0", "@apidevtools/json-schema-ref-parser": "11.6.4", - "@ariakit/test": "^0.4.2", + "@ariakit/test": "^0.4.5", "@babel/core": "7.25.7", "@babel/plugin-syntax-jsx": "7.25.7", "@babel/runtime-corejs3": "7.25.7", @@ -1432,18 +1432,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@ariakit/core": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.9.tgz", - "integrity": "sha512-nV0B/OTK/0iB+P9RC7fudznYZ8eR6rR1F912Zc54e3+wSW5RrRvNOiRxyMrgENidd4R7cCMDw77XJLSBLKgEPQ==" - }, "node_modules/@ariakit/test": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@ariakit/test/-/test-0.4.2.tgz", - "integrity": "sha512-WXAAiAyTaHV9klntOB81Y+YHyA5iGxy9wXCmjQOfYK5InsuIour+7TVXICUxn2NF0XD6j6OoEJbCVDJ2Y46xEA==", + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/@ariakit/test/-/test-0.4.5.tgz", + "integrity": "sha512-dK9OtI8MeKfdtOiW1auDITnyaelq0O0aUTnolIqJj+RJd8LFai0gi7fQUgrun9CZHJ2wWsEad4vlviGfhfIIhQ==", "dev": true, + "license": "MIT", "dependencies": { - "@ariakit/core": "0.4.9", + "@ariakit/core": "0.4.12", "@testing-library/dom": "^8.0.0 || ^9.0.0 || ^10.0.0" }, "peerDependencies": { @@ -1463,6 +1459,13 @@ } } }, + "node_modules/@ariakit/test/node_modules/@ariakit/core": { + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.12.tgz", + "integrity": "sha512-+NNpy88tdP/w9mOBPuDrMTbtapPbo/8yVIzpQB7TAmN0sPh/Cq3nU1f2KCTCIujPmwRvAcMSW9UHOlFmbKEPOA==", + "dev": true, + "license": "MIT" + }, "node_modules/@aw-web-design/x-default-browser": { "version": "1.4.126", "resolved": "https://registry.npmjs.org/@aw-web-design/x-default-browser/-/x-default-browser-1.4.126.tgz", @@ -49340,9 +49343,10 @@ } }, "node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } @@ -53677,7 +53681,7 @@ "version": "28.13.0", "license": "GPL-2.0-or-later", "dependencies": { - "@ariakit/react": "^0.4.10", + "@ariakit/react": "^0.4.13", "@babel/runtime": "7.25.7", "@emotion/cache": "^11.7.1", "@emotion/css": "^11.7.1", @@ -53732,12 +53736,19 @@ "react-dom": "^18.0.0" } }, + "packages/components/node_modules/@ariakit/core": { + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.12.tgz", + "integrity": "sha512-+NNpy88tdP/w9mOBPuDrMTbtapPbo/8yVIzpQB7TAmN0sPh/Cq3nU1f2KCTCIujPmwRvAcMSW9UHOlFmbKEPOA==", + "license": "MIT" + }, "packages/components/node_modules/@ariakit/react": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.10.tgz", - "integrity": "sha512-c1+6sNLj57aAXrBZMCVGG+OXeFrPAG0TV1jT7oPJcN/KLRs3aCuO3CCJVep/eKepFzzK01kNRGYX3wPT1TXPNw==", + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.13.tgz", + "integrity": "sha512-pTGYgoqCojfyt2xNJ5VQhejxXwwtcP7VDDqcnnVChv7TA2TWWyYerJ5m4oxViI1pgeNqnHZwKlQ79ZipF7W2kQ==", + "license": "MIT", "dependencies": { - "@ariakit/react-core": "0.4.10" + "@ariakit/react-core": "0.4.13" }, "funding": { "type": "opencollective", @@ -53749,11 +53760,12 @@ } }, "packages/components/node_modules/@ariakit/react-core": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.10.tgz", - "integrity": "sha512-r6DZmtHBmSoOj848+RpBwdZy/55YxPhMhfH14JIO2OLn1F6iSFkQwR7AAGpIrlYycWJFSF7KrQu50O+SSfFJdQ==", + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.13.tgz", + "integrity": "sha512-iIjQeupP9d0pOubOzX4a0UPXbhXbp0ZCduDpkv7+u/pYP/utk/YRECD0M/QpZr6YSeltmDiNxKjdyK8r9Yhv4Q==", + "license": "MIT", "dependencies": { - "@ariakit/core": "0.4.9", + "@ariakit/core": "0.4.12", "@floating-ui/dom": "^1.0.0", "use-sync-external-store": "^1.2.0" }, @@ -54039,7 +54051,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@ariakit/react": "^0.4.10", + "@ariakit/react": "^0.4.13", "@babel/runtime": "7.25.7", "@wordpress/components": "*", "@wordpress/compose": "*", @@ -54061,12 +54073,19 @@ "react": "^18.0.0" } }, + "packages/dataviews/node_modules/@ariakit/core": { + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.12.tgz", + "integrity": "sha512-+NNpy88tdP/w9mOBPuDrMTbtapPbo/8yVIzpQB7TAmN0sPh/Cq3nU1f2KCTCIujPmwRvAcMSW9UHOlFmbKEPOA==", + "license": "MIT" + }, "packages/dataviews/node_modules/@ariakit/react": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.10.tgz", - "integrity": "sha512-c1+6sNLj57aAXrBZMCVGG+OXeFrPAG0TV1jT7oPJcN/KLRs3aCuO3CCJVep/eKepFzzK01kNRGYX3wPT1TXPNw==", + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.13.tgz", + "integrity": "sha512-pTGYgoqCojfyt2xNJ5VQhejxXwwtcP7VDDqcnnVChv7TA2TWWyYerJ5m4oxViI1pgeNqnHZwKlQ79ZipF7W2kQ==", + "license": "MIT", "dependencies": { - "@ariakit/react-core": "0.4.10" + "@ariakit/react-core": "0.4.13" }, "funding": { "type": "opencollective", @@ -54078,11 +54097,12 @@ } }, "packages/dataviews/node_modules/@ariakit/react-core": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.10.tgz", - "integrity": "sha512-r6DZmtHBmSoOj848+RpBwdZy/55YxPhMhfH14JIO2OLn1F6iSFkQwR7AAGpIrlYycWJFSF7KrQu50O+SSfFJdQ==", + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.13.tgz", + "integrity": "sha512-iIjQeupP9d0pOubOzX4a0UPXbhXbp0ZCduDpkv7+u/pYP/utk/YRECD0M/QpZr6YSeltmDiNxKjdyK8r9Yhv4Q==", + "license": "MIT", "dependencies": { - "@ariakit/core": "0.4.9", + "@ariakit/core": "0.4.12", "@floating-ui/dom": "^1.0.0", "use-sync-external-store": "^1.2.0" }, diff --git a/package.json b/package.json index 3ddcb981f6f6f7..84425dbd1cff21 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@actions/core": "1.9.1", "@actions/github": "5.0.0", "@apidevtools/json-schema-ref-parser": "11.6.4", - "@ariakit/test": "^0.4.2", + "@ariakit/test": "^0.4.5", "@babel/core": "7.25.7", "@babel/plugin-syntax-jsx": "7.25.7", "@babel/runtime-corejs3": "7.25.7", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index be930515f16659..937027ecdd1ea3 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Internal + +- Upgraded `@ariakit/react` (v0.4.13) and `@ariakit/test` (v0.4.5) ([#65907](https://github.com/WordPress/gutenberg/pull/65907)). + ## 28.13.0 (2024-11-27) ### Deprecations @@ -11,7 +15,7 @@ - `FontSizePicker`: Deprecate 36px default size ([#66920](https://github.com/WordPress/gutenberg/pull/66920)). - `ComboboxControl`: Deprecate 36px default size ([#66900](https://github.com/WordPress/gutenberg/pull/66900)). - `ToggleGroupControl`: Deprecate 36px default size ([#66747](https://github.com/WordPress/gutenberg/pull/66747)). -- `RangeControl`: Deprecate 36px default size ([#66721](https://github.com/WordPress/gutenberg/pull/66721)). +- `RangeControl`: Deprecate 36px default size ([#66721](https://github.com/WordPress/gutenberg/pull/66721)). ### Bug Fixes diff --git a/packages/components/package.json b/packages/components/package.json index dc62f992c3bb29..75f0d1eb1f2331 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -32,7 +32,7 @@ "src/**/*.scss" ], "dependencies": { - "@ariakit/react": "^0.4.10", + "@ariakit/react": "^0.4.13", "@babel/runtime": "7.25.7", "@emotion/cache": "^11.7.1", "@emotion/css": "^11.7.1", diff --git a/packages/components/src/composite/item.tsx b/packages/components/src/composite/item.tsx index edbf0b92e039af..4a02f76039a5cf 100644 --- a/packages/components/src/composite/item.tsx +++ b/packages/components/src/composite/item.tsx @@ -26,23 +26,5 @@ export const CompositeItem = forwardRef< // obfuscated to discourage its use outside of the component's internals. const store = ( props.store ?? context.store ) as Ariakit.CompositeStore; - // If the active item is not connected, Composite may end up in a state - // where none of the items are tabbable. In this case, we force all items to - // be tabbable, so that as soon as an item received focus, it becomes active - // and Composite goes back to working as expected. - const tabbable = Ariakit.useStoreState( store, ( state ) => { - return ( - state?.activeId !== null && - ! store?.item( state?.activeId )?.element?.isConnected - ); - } ); - - return ( - <Ariakit.CompositeItem - store={ store } - tabbable={ tabbable } - { ...props } - ref={ ref } - /> - ); + return <Ariakit.CompositeItem store={ store } { ...props } ref={ ref } />; } ); diff --git a/packages/components/src/menu/checkbox-item.tsx b/packages/components/src/menu/checkbox-item.tsx index b9a9b8105e517e..182c27dfdee305 100644 --- a/packages/components/src/menu/checkbox-item.tsx +++ b/packages/components/src/menu/checkbox-item.tsx @@ -16,24 +16,20 @@ import type { WordPressComponentProps } from '../context'; import { MenuContext } from './context'; import type { MenuCheckboxItemProps } from './types'; import * as Styled from './styles'; -import { useTemporaryFocusVisibleFix } from './use-temporary-focus-visible-fix'; export const MenuCheckboxItem = forwardRef< HTMLDivElement, WordPressComponentProps< MenuCheckboxItemProps, 'div', false > >( function MenuCheckboxItem( - { suffix, children, onBlur, hideOnClick = false, ...props }, + { suffix, children, hideOnClick = false, ...props }, ref ) { - // TODO: Remove when https://github.com/ariakit/ariakit/issues/4083 is fixed - const focusVisibleFixProps = useTemporaryFocusVisibleFix( { onBlur } ); const menuContext = useContext( MenuContext ); return ( <Styled.MenuCheckboxItem ref={ ref } { ...props } - { ...focusVisibleFixProps } accessibleWhenDisabled hideOnClick={ hideOnClick } store={ menuContext?.store } diff --git a/packages/components/src/menu/item.tsx b/packages/components/src/menu/item.tsx index f8ae670846f55f..6e8c510e4c9c2a 100644 --- a/packages/components/src/menu/item.tsx +++ b/packages/components/src/menu/item.tsx @@ -10,24 +10,20 @@ import type { WordPressComponentProps } from '../context'; import type { MenuItemProps } from './types'; import * as Styled from './styles'; import { MenuContext } from './context'; -import { useTemporaryFocusVisibleFix } from './use-temporary-focus-visible-fix'; export const MenuItem = forwardRef< HTMLDivElement, WordPressComponentProps< MenuItemProps, 'div', false > >( function MenuItem( - { prefix, suffix, children, onBlur, hideOnClick = true, ...props }, + { prefix, suffix, children, hideOnClick = true, ...props }, ref ) { - // TODO: Remove when https://github.com/ariakit/ariakit/issues/4083 is fixed - const focusVisibleFixProps = useTemporaryFocusVisibleFix( { onBlur } ); const menuContext = useContext( MenuContext ); return ( <Styled.MenuItem ref={ ref } { ...props } - { ...focusVisibleFixProps } accessibleWhenDisabled hideOnClick={ hideOnClick } store={ menuContext?.store } diff --git a/packages/components/src/menu/radio-item.tsx b/packages/components/src/menu/radio-item.tsx index 3848d2062c0c25..45b0039f900e20 100644 --- a/packages/components/src/menu/radio-item.tsx +++ b/packages/components/src/menu/radio-item.tsx @@ -17,7 +17,6 @@ import { MenuContext } from './context'; import type { MenuRadioItemProps } from './types'; import * as Styled from './styles'; import { SVG, Circle } from '@wordpress/primitives'; -import { useTemporaryFocusVisibleFix } from './use-temporary-focus-visible-fix'; const radioCheck = ( <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> @@ -29,18 +28,15 @@ export const MenuRadioItem = forwardRef< HTMLDivElement, WordPressComponentProps< MenuRadioItemProps, 'div', false > >( function MenuRadioItem( - { suffix, children, onBlur, hideOnClick = false, ...props }, + { suffix, children, hideOnClick = false, ...props }, ref ) { - // TODO: Remove when https://github.com/ariakit/ariakit/issues/4083 is fixed - const focusVisibleFixProps = useTemporaryFocusVisibleFix( { onBlur } ); const menuContext = useContext( MenuContext ); return ( <Styled.MenuRadioItem ref={ ref } { ...props } - { ...focusVisibleFixProps } accessibleWhenDisabled hideOnClick={ hideOnClick } store={ menuContext?.store } diff --git a/packages/components/src/menu/use-temporary-focus-visible-fix.ts b/packages/components/src/menu/use-temporary-focus-visible-fix.ts deleted file mode 100644 index 0df13133739609..00000000000000 --- a/packages/components/src/menu/use-temporary-focus-visible-fix.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * WordPress dependencies - */ -import { useState, flushSync } from '@wordpress/element'; - -export function useTemporaryFocusVisibleFix( { - onBlur: onBlurProp, -}: { - onBlur?: React.FocusEventHandler< HTMLDivElement >; -} ) { - const [ focusVisible, setFocusVisible ] = useState( false ); - return { - 'data-focus-visible': focusVisible || undefined, - onFocusVisible: () => { - flushSync( () => setFocusVisible( true ) ); - }, - onBlur: ( ( event ) => { - onBlurProp?.( event ); - setFocusVisible( false ); - } ) as React.FocusEventHandler< HTMLDivElement >, - }; -} diff --git a/packages/components/src/tabs/tab.tsx b/packages/components/src/tabs/tab.tsx index 70f56e52ad2627..8226d0589f08c8 100644 --- a/packages/components/src/tabs/tab.tsx +++ b/packages/components/src/tabs/tab.tsx @@ -1,8 +1,3 @@ -/** - * External dependencies - */ -import * as Ariakit from '@ariakit/react'; - /** * WordPress dependencies */ @@ -29,18 +24,6 @@ export const Tab = forwardRef< >( function Tab( { children, tabId, disabled, render, ...otherProps }, ref ) { const { store, instanceId } = useTabsContext() ?? {}; - // If the active item is not connected, the tablist may end up in a state - // where none of the tabs are tabbable. In this case, we force all tabs to - // be tabbable, so that as soon as an item received focus, it becomes active - // and Tablist goes back to working as expected. - // eslint-disable-next-line @wordpress/no-unused-vars-before-return - const tabbable = Ariakit.useStoreState( store, ( state ) => { - return ( - state?.activeId !== null && - ! store?.item( state?.activeId )?.element?.isConnected - ); - } ); - if ( ! store ) { warning( '`Tabs.Tab` must be wrapped in a `Tabs` component.' ); return null; @@ -55,7 +38,6 @@ export const Tab = forwardRef< id={ instancedTabId } disabled={ disabled } render={ render } - tabbable={ tabbable } { ...otherProps } > <StyledTabChildren>{ children }</StyledTabChildren> diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index f4d42102731eb2..8fe2e04236725c 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -43,7 +43,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@ariakit/react": "^0.4.10", + "@ariakit/react": "^0.4.13", "@babel/runtime": "7.25.7", "@wordpress/components": "*", "@wordpress/compose": "*", From a387fbbdf9fa468217944aa5b78fb6113c2ed63b Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 28 Nov 2024 19:17:37 +0400 Subject: [PATCH 1756/1908] Block Editor: Fix JS error in the 'useTabNav' hook (#67102) * Block Editor: Fix JS error in the 'useTabNav' hook * Focus on canvas when there's no section root Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- .../src/components/writing-flow/use-tab-nav.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/writing-flow/use-tab-nav.js b/packages/block-editor/src/components/writing-flow/use-tab-nav.js index 16a18358fb2ede..46c40d56fe96d9 100644 --- a/packages/block-editor/src/components/writing-flow/use-tab-nav.js +++ b/packages/block-editor/src/components/writing-flow/use-tab-nav.js @@ -35,6 +35,11 @@ export default function useTabNav() { const noCaptureRef = useRef(); function onFocusCapture( event ) { + const canvasElement = + container.current.ownerDocument === event.target.ownerDocument + ? container.current + : container.current.ownerDocument.defaultView.frameElement; + // Do not capture incoming focus if set by us in WritingFlow. if ( noCaptureRef.current ) { noCaptureRef.current = null; @@ -64,17 +69,15 @@ export default function useTabNav() { .focus(); } // If we don't have any section blocks, focus the section root. - else { + else if ( sectionRootClientId ) { container.current .querySelector( `[data-block="${ sectionRootClientId }"]` ) .focus(); + } else { + // If we don't have any section root, focus the canvas. + canvasElement.focus(); } } else { - const canvasElement = - container.current.ownerDocument === event.target.ownerDocument - ? container.current - : container.current.ownerDocument.defaultView.frameElement; - const isBefore = // eslint-disable-next-line no-bitwise event.target.compareDocumentPosition( canvasElement ) & From 5efeef9ae740d2aa51fa2493782773083b5363ee Mon Sep 17 00:00:00 2001 From: Manzoor Wani <manzoorwani.jk@gmail.com> Date: Thu, 28 Nov 2024 07:45:13 -0800 Subject: [PATCH 1757/1908] Convert lock unlock to generics (#66682) * Convert lock unlock to generics * Set object type from generic for unlock * Fix types affected by updated signature of lock/unlock * Improve signature * Remove expected errors no longer needed * Restore the type for component private APIs Co-authored-by: manzoorwanijk <manzoorwanijk@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- packages/private-apis/src/implementation.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/private-apis/src/implementation.ts b/packages/private-apis/src/implementation.ts index bae53bae8d158a..5a5fb3f39fa183 100644 --- a/packages/private-apis/src/implementation.ts +++ b/packages/private-apis/src/implementation.ts @@ -137,14 +137,16 @@ export const __dangerousOptInToUnstableAPIsOnlyForCoreModules = ( * @param object The object to bind the private data to. * @param privateData The private data to bind to the object. */ -function lock( object: Record< symbol, WeakKey >, privateData: unknown ) { +function lock( object: unknown, privateData: unknown ) { if ( ! object ) { throw new Error( 'Cannot lock an undefined object.' ); } - if ( ! ( __private in object ) ) { - object[ __private ] = {}; + const _object = object as Record< symbol, WeakKey >; + + if ( ! ( __private in _object ) ) { + _object[ __private ] = {}; } - lockedData.set( object[ __private ], privateData ); + lockedData.set( _object[ __private ], privateData ); } /** @@ -170,17 +172,19 @@ function lock( object: Record< symbol, WeakKey >, privateData: unknown ) { * @param object The object to unlock the private data from. * @return The private data bound to the object. */ -function unlock( object: Record< symbol, WeakKey > ) { +function unlock< T = any >( object: unknown ): T { if ( ! object ) { throw new Error( 'Cannot unlock an undefined object.' ); } - if ( ! ( __private in object ) ) { + const _object = object as Record< symbol, WeakKey >; + + if ( ! ( __private in _object ) ) { throw new Error( 'Cannot unlock an object that was not locked before. ' ); } - return lockedData.get( object[ __private ] ); + return lockedData.get( _object[ __private ] ); } const lockedData = new WeakMap(); From db263fb38a7e6bd8bbf7d27cb189c13063979c90 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 28 Nov 2024 20:24:44 +0400 Subject: [PATCH 1758/1908] Components: Fix the 'ClipboardButton' effect cleanup (#67399) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/src/clipboard-button/index.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/components/src/clipboard-button/index.tsx b/packages/components/src/clipboard-button/index.tsx index 0bf7d177e251ef..492ab64b7290e2 100644 --- a/packages/components/src/clipboard-button/index.tsx +++ b/packages/components/src/clipboard-button/index.tsx @@ -45,9 +45,11 @@ export default function ClipboardButton( { } ); useEffect( () => { - if ( timeoutIdRef.current ) { - clearTimeout( timeoutIdRef.current ); - } + return () => { + if ( timeoutIdRef.current ) { + clearTimeout( timeoutIdRef.current ); + } + }; }, [] ); const classes = clsx( 'components-clipboard-button', className ); From 6a989b420b2dc809076f79985b976b0b400749e3 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Thu, 28 Nov 2024 18:08:39 +0100 Subject: [PATCH 1759/1908] DataViews: Avoid double click handler on primary fields (#67393) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: gigitux <gigitux@git.wordpress.org> --- .../dataviews-layouts/utils/get-clickable-item-props.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts b/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts index e2a6081a68fa3e..efb4a8f598c7b8 100644 --- a/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts +++ b/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts @@ -12,9 +12,15 @@ export default function getClickableItemProps< Item >( className: `${ className } ${ className }--clickable`, role: 'button', tabIndex: 0, - onClick: () => onClickItem( item ), + onClick: ( event: React.MouseEvent ) => { + // Prevents onChangeSelection from triggering. + event.stopPropagation(); + onClickItem( item ); + }, onKeyDown: ( event: React.KeyboardEvent ) => { if ( event.key === 'Enter' || event.key === '' ) { + // Prevents onChangeSelection from triggering. + event.stopPropagation(); onClickItem( item ); } }, From 9c1446de351e94f3b186050e9c4396c2747d38e5 Mon Sep 17 00:00:00 2001 From: Yogesh Bhutkar <yogesh.bhutkar@rtcamp.com> Date: Fri, 29 Nov 2024 00:05:45 +0530 Subject: [PATCH 1760/1908] FontCollection: Update pagination controls (#67143) Co-authored-by: yogeshbhutkar <yogeshbhutkar@git.wordpress.org> Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> Co-authored-by: juanfra <juanfra@git.wordpress.org> --- .../font-library-modal/font-collection.js | 67 +++++++++++-------- .../font-library-modal/style.scss | 17 +++-- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js index caf339091de752..3aef0171ec358f 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js @@ -27,7 +27,13 @@ import { } from '@wordpress/components'; import { debounce } from '@wordpress/compose'; import { sprintf, __, _x, isRTL } from '@wordpress/i18n'; -import { moreVertical, chevronLeft, chevronRight } from '@wordpress/icons'; +import { + moreVertical, + next, + previous, + chevronLeft, + chevronRight, +} from '@wordpress/icons'; /** * Internal dependencies @@ -486,37 +492,30 @@ function FontCollection( { slug } ) { { ! selectedFont && ( <HStack - spacing={ 4 } - justify="center" + expanded={ false } className="font-library-modal__footer" + justify="end" + spacing={ 6 } > - <Button - label={ __( 'Previous page' ) } - size="compact" - onClick={ () => setPage( page - 1 ) } - disabled={ page === 1 } - showTooltip - accessibleWhenDisabled - icon={ isRTL() ? chevronRight : chevronLeft } - tooltipPosition="top" - /> <HStack justify="flex-start" expanded={ false } - spacing={ 2 } + spacing={ 1 } className="font-library-modal__page-selection" > { createInterpolateElement( sprintf( - // translators: %s: Total number of pages. + // translators: 1: Current page number, 2: Total number of pages. _x( - 'Page <CurrentPageControl /> of %s', + '<div>Page</div>%1$s<div>of %2$s</div>', 'paging' ), + '<CurrentPage />', totalPages ), { - CurrentPageControl: ( + div: <div aria-hidden />, + CurrentPage: ( <SelectControl aria-label={ __( 'Current page' @@ -535,22 +534,36 @@ function FontCollection( { slug } ) { parseInt( newPage ) ) } - size="compact" + size="small" __nextHasNoMarginBottom + variant="minimal" /> ), } ) } </HStack> - <Button - label={ __( 'Next page' ) } - size="compact" - onClick={ () => setPage( page + 1 ) } - disabled={ page === totalPages } - accessibleWhenDisabled - icon={ isRTL() ? chevronLeft : chevronRight } - tooltipPosition="top" - /> + <HStack expanded={ false } spacing={ 1 }> + <Button + onClick={ () => setPage( page - 1 ) } + disabled={ page === 1 } + accessibleWhenDisabled + label={ __( 'Previous page' ) } + icon={ isRTL() ? next : previous } + showTooltip + size="compact" + tooltipPosition="top" + /> + <Button + onClick={ () => setPage( page + 1 ) } + disabled={ page === totalPages } + accessibleWhenDisabled + label={ __( 'Next page' ) } + icon={ isRTL() ? previous : next } + showTooltip + size="compact" + tooltipPosition="top" + /> + </HStack> </HStack> ) } </> diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss index 7d94376ac8d942..7568fea2b6f805 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss +++ b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss @@ -64,9 +64,15 @@ $footer-height: 70px; .font-library-modal__page-selection { font-size: 11px; - text-transform: uppercase; font-weight: 500; - color: $gray-900; + text-transform: uppercase; + + @include break-small() { + .components-select-control__input { + font-size: 11px !important; + font-weight: 500; + } + } } // TODO: See if this can be removed after https://github.com/WordPress/gutenberg/issues/38730 @@ -124,7 +130,7 @@ $footer-height: 70px; white-space: nowrap; flex-shrink: 0; transition: opacity 0.3s ease-in-out; - @include reduce-motion("transition"); + @include reduce-motion( "transition" ); } } @@ -147,7 +153,6 @@ $footer-height: 70px; } } - .font-library-modal__upload-area { align-items: center; display: flex; @@ -200,7 +205,9 @@ button.font-library-modal__upload-area { } .font-library-modal__select-all { - padding: $grid-unit-20 $grid-unit-20 $grid-unit-20 $grid-unit-20 + $border-width; + padding: + $grid-unit-20 $grid-unit-20 $grid-unit-20 $grid-unit-20 + + $border-width; .components-checkbox-control__label { padding-left: $grid-unit-20; From 5b44d8cb9841574e52c83c539d885c1e99b89293 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Fri, 29 Nov 2024 06:40:55 +0900 Subject: [PATCH 1761/1908] BoxControl: Passive deprecate `onMouseOver`/`onMouseOut` (#67332) * BoxControl: Passive deprecate `onMouseOver`/`onMouseOut` * Fix usage in DimensionsPanel * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../global-styles/dimensions-panel.js | 32 ++--- packages/components/CHANGELOG.md | 6 +- packages/components/src/box-control/index.tsx | 4 +- packages/components/src/box-control/types.ts | 127 ++++++++++-------- 4 files changed, 94 insertions(+), 75 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/dimensions-panel.js b/packages/block-editor/src/components/global-styles/dimensions-panel.js index c19788ebfcb580..385f28b668eda2 100644 --- a/packages/block-editor/src/components/global-styles/dimensions-panel.js +++ b/packages/block-editor/src/components/global-styles/dimensions-panel.js @@ -444,17 +444,6 @@ export default function DimensionsPanel( { const onMouseLeaveControls = () => onVisualize( false ); - const inputProps = { - min: minMarginValue, - onDragStart: () => { - //Reset to 0 in case the value was negative. - setMinMarginValue( 0 ); - }, - onDragEnd: () => { - setMinMarginValue( minimumMargin ); - }, - }; - return ( <Wrapper resetAllFilter={ resetAllFilter } @@ -545,8 +534,10 @@ export default function DimensionsPanel( { units={ units } allowReset={ false } splitOnAxis={ isAxialPadding } - onMouseOver={ onMouseOverPadding } - onMouseOut={ onMouseLeaveControls } + inputProps={ { + onMouseOver: onMouseOverPadding, + onMouseOut: onMouseLeaveControls, + } } /> ) } { showSpacingPresetsControl && ( @@ -581,14 +572,23 @@ export default function DimensionsPanel( { __next40pxDefaultSize values={ marginValues } onChange={ setMarginValues } - inputProps={ inputProps } + inputProps={ { + min: minMarginValue, + onDragStart: () => { + // Reset to 0 in case the value was negative. + setMinMarginValue( 0 ); + }, + onDragEnd: () => { + setMinMarginValue( minimumMargin ); + }, + onMouseOver: onMouseOverMargin, + onMouseOut: onMouseLeaveControls, + } } label={ __( 'Margin' ) } sides={ marginSides } units={ units } allowReset={ false } splitOnAxis={ isAxialMargin } - onMouseOver={ onMouseOverMargin } - onMouseOut={ onMouseLeaveControls } /> ) } { showSpacingPresetsControl && ( diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 937027ecdd1ea3..acb59c743c81e8 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Deprecations + +- `BoxControl`: Passive deprecate `onMouseOver`/`onMouseOut`. Pass to the `inputProps` prop instead ([#67332](https://github.com/WordPress/gutenberg/pull/67332)). + ### Internal - Upgraded `@ariakit/react` (v0.4.13) and `@ariakit/test` (v0.4.5) ([#65907](https://github.com/WordPress/gutenberg/pull/65907)). @@ -15,7 +19,7 @@ - `FontSizePicker`: Deprecate 36px default size ([#66920](https://github.com/WordPress/gutenberg/pull/66920)). - `ComboboxControl`: Deprecate 36px default size ([#66900](https://github.com/WordPress/gutenberg/pull/66900)). - `ToggleGroupControl`: Deprecate 36px default size ([#66747](https://github.com/WordPress/gutenberg/pull/66747)). -- `RangeControl`: Deprecate 36px default size ([#66721](https://github.com/WordPress/gutenberg/pull/66721)). +- `RangeControl`: Deprecate 36px default size ([#66721](https://github.com/WordPress/gutenberg/pull/66721)). ### Bug Fixes diff --git a/packages/components/src/box-control/index.tsx b/packages/components/src/box-control/index.tsx index 7f822f5f70e124..7418fa19d74a0a 100644 --- a/packages/components/src/box-control/index.tsx +++ b/packages/components/src/box-control/index.tsx @@ -141,6 +141,8 @@ function BoxControl( { }; const inputControlProps = { + onMouseOver, + onMouseOut, ...inputProps, onChange: handleOnChange, onFocus: handleOnFocus, @@ -150,8 +152,6 @@ function BoxControl( { setSelectedUnits, sides, values: inputValues, - onMouseOver, - onMouseOut, __next40pxDefaultSize, }; diff --git a/packages/components/src/box-control/types.ts b/packages/components/src/box-control/types.ts index 2a47abbf11001e..16b69dfe70a64a 100644 --- a/packages/components/src/box-control/types.ts +++ b/packages/components/src/box-control/types.ts @@ -17,70 +17,85 @@ export type CustomValueUnits = { type UnitControlPassthroughProps = Omit< UnitControlProps, - 'label' | 'onChange' | 'onFocus' | 'onMouseOver' | 'onMouseOut' | 'units' + 'label' | 'onChange' | 'onFocus' | 'units' >; -export type BoxControlProps = Pick< - UnitControlProps, - 'onMouseOver' | 'onMouseOut' | 'units' -> & { - /** - * If this property is true, a button to reset the box control is rendered. - * - * @default true - */ - allowReset?: boolean; - /** - * The id to use as a base for the unique HTML id attribute of the control. - */ - id?: string; - /** - * Props for the internal `UnitControl` components. - * - * @default { min: 0 } - */ - inputProps?: UnitControlPassthroughProps; - /** - * Heading label for the control. - * - * @default __( 'Box Control' ) - */ - label?: string; +type DeprecatedBoxControlProps = { /** - * A callback function when an input value changes. + * @deprecated Pass to the `inputProps` prop instead. + * @ignore */ - onChange: ( next: BoxControlValue ) => void; + onMouseOver?: UnitControlProps[ 'onMouseOver' ]; /** - * The `top`, `right`, `bottom`, and `left` box dimension values to use when the control is reset. - * - * @default { top: undefined, right: undefined, bottom: undefined, left: undefined } + * @deprecated Pass to the `inputProps` prop instead. + * @ignore */ - resetValues?: BoxControlValue; - /** - * Collection of sides to allow control of. If omitted or empty, all sides will be available. - * - * Allowed values are "top", "right", "bottom", "left", "vertical", and "horizontal". - */ - sides?: readonly ( keyof BoxControlValue | 'horizontal' | 'vertical' )[]; - /** - * If this property is true, when the box control is unlinked, vertical and horizontal controls - * can be used instead of updating individual sides. - * - * @default false - */ - splitOnAxis?: boolean; - /** - * The current values of the control, expressed as an object of `top`, `right`, `bottom`, and `left` values. - */ - values?: BoxControlValue; - /** - * Start opting into the larger default height that will become the default size in a future version. - * - * @default false - */ - __next40pxDefaultSize?: boolean; + onMouseOut?: UnitControlProps[ 'onMouseOut' ]; }; +export type BoxControlProps = Pick< UnitControlProps, 'units' > & + DeprecatedBoxControlProps & { + /** + * If this property is true, a button to reset the box control is rendered. + * + * @default true + */ + allowReset?: boolean; + /** + * The id to use as a base for the unique HTML id attribute of the control. + */ + id?: string; + /** + * Props for the internal `UnitControl` components. + * + * @default { min: 0 } + */ + inputProps?: UnitControlPassthroughProps; + /** + * Heading label for the control. + * + * @default __( 'Box Control' ) + */ + label?: string; + /** + * A callback function when an input value changes. + */ + onChange: ( next: BoxControlValue ) => void; + /** + * The `top`, `right`, `bottom`, and `left` box dimension values to use when the control is reset. + * + * @default { top: undefined, right: undefined, bottom: undefined, left: undefined } + */ + resetValues?: BoxControlValue; + /** + * Collection of sides to allow control of. If omitted or empty, all sides will be available. + * + * Allowed values are "top", "right", "bottom", "left", "vertical", and "horizontal". + */ + sides?: readonly ( + | keyof BoxControlValue + | 'horizontal' + | 'vertical' + )[]; + /** + * If this property is true, when the box control is unlinked, vertical and horizontal controls + * can be used instead of updating individual sides. + * + * @default false + */ + splitOnAxis?: boolean; + /** + * The current values of the control, expressed as an object of `top`, `right`, `bottom`, and `left` values. + */ + values?: BoxControlValue; + /** + * Start opting into the larger default height that will become the default size in a future version. + * + * @default false + */ + __next40pxDefaultSize?: boolean; + }; + export type BoxControlInputControlProps = UnitControlPassthroughProps & { onChange?: ( nextValues: BoxControlValue ) => void; onFocus?: ( From 35a68f683c969bb8e191a56f1f26af0690caf4bc Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Fri, 29 Nov 2024 04:16:04 +0530 Subject: [PATCH 1762/1908] BoxControl: Deprecate 36px default size (#66704) * Add next40pxDefaultSize for the boxControl component * Add the deperecation notice for the BoxControl component * Add the changelog for the deprecation * Add __next40pxDefaultSize to pass the failed unit test * Update the unit test for the box control component * Add __next40pxDefaultSize for BoxControl to toolspanel readme This is added because with this PR, we are passing as default 40px size to the BoxControl component, so its usage should also get updated * Fix changelog --------- Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/box-control/README.md | 1 + packages/components/src/box-control/index.tsx | 8 +++ .../src/box-control/stories/index.story.tsx | 1 + .../components/src/box-control/test/index.tsx | 59 +++++++++++-------- .../src/tools-panel/tools-panel/README.md | 2 + 6 files changed, 46 insertions(+), 26 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index acb59c743c81e8..fe326e847970b4 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Deprecations - `BoxControl`: Passive deprecate `onMouseOver`/`onMouseOut`. Pass to the `inputProps` prop instead ([#67332](https://github.com/WordPress/gutenberg/pull/67332)). +- `BoxControl`: Deprecate 36px default size ([#66704](https://github.com/WordPress/gutenberg/pull/66704)). ### Internal diff --git a/packages/components/src/box-control/README.md b/packages/components/src/box-control/README.md index ddadf938798ee9..8bcb5a5dad8fc2 100644 --- a/packages/components/src/box-control/README.md +++ b/packages/components/src/box-control/README.md @@ -21,6 +21,7 @@ function Example() { return ( <BoxControl + __next40pxDefaultSize values={ values } onChange={ setValues } /> diff --git a/packages/components/src/box-control/index.tsx b/packages/components/src/box-control/index.tsx index 7418fa19d74a0a..46cf2cd93a9444 100644 --- a/packages/components/src/box-control/index.tsx +++ b/packages/components/src/box-control/index.tsx @@ -33,6 +33,7 @@ import type { BoxControlProps, BoxControlValue, } from './types'; +import { maybeWarnDeprecated36pxSize } from '../utils/deprecated-36px-size'; const defaultInputProps = { min: 0, @@ -64,6 +65,7 @@ function useUniqueId( idProp?: string ) { * * return ( * <BoxControl + * __next40pxDefaultSize * values={ values } * onChange={ setValues } * /> @@ -155,6 +157,12 @@ function BoxControl( { __next40pxDefaultSize, }; + maybeWarnDeprecated36pxSize( { + componentName: 'BoxControl', + __next40pxDefaultSize, + size: undefined, + } ); + return ( <Grid id={ id } diff --git a/packages/components/src/box-control/stories/index.story.tsx b/packages/components/src/box-control/stories/index.story.tsx index 783f9d047b1bb0..aa94e8c4bf00b8 100644 --- a/packages/components/src/box-control/stories/index.story.tsx +++ b/packages/components/src/box-control/stories/index.story.tsx @@ -49,6 +49,7 @@ const TemplateControlled: StoryFn< typeof BoxControl > = ( props ) => { export const Default = TemplateUncontrolled.bind( {} ); Default.args = { label: 'Label', + __next40pxDefaultSize: true, }; export const Controlled = TemplateControlled.bind( {} ); diff --git a/packages/components/src/box-control/test/index.tsx b/packages/components/src/box-control/test/index.tsx index 681e7721d0c13a..185a18b258951f 100644 --- a/packages/components/src/box-control/test/index.tsx +++ b/packages/components/src/box-control/test/index.tsx @@ -15,11 +15,14 @@ import { useState } from '@wordpress/element'; import BoxControl from '..'; import type { BoxControlProps, BoxControlValue } from '../types'; -const Example = ( extraProps: Omit< BoxControlProps, 'onChange' > ) => { +const ControlledBoxControl = ( + extraProps: Omit< BoxControlProps, 'onChange' > +) => { const [ state, setState ] = useState< BoxControlValue >(); return ( <BoxControl + __next40pxDefaultSize values={ state } onChange={ ( next ) => setState( next ) } { ...extraProps } @@ -27,10 +30,17 @@ const Example = ( extraProps: Omit< BoxControlProps, 'onChange' > ) => { ); }; +const UncontrolledBoxControl = ( { + onChange = () => {}, + ...props +}: Omit< BoxControlProps, 'onChange' > & { + onChange?: BoxControlProps[ 'onChange' ]; +} ) => <BoxControl __next40pxDefaultSize onChange={ onChange } { ...props } />; + describe( 'BoxControl', () => { describe( 'Basic rendering', () => { it( 'should render a box control input', () => { - render( <BoxControl onChange={ () => {} } /> ); + render( <UncontrolledBoxControl /> ); expect( screen.getByRole( 'group', { name: 'Box Control' } ) @@ -43,7 +53,7 @@ describe( 'BoxControl', () => { it( 'should update values when interacting with input', async () => { const user = userEvent.setup(); - render( <BoxControl onChange={ () => {} } /> ); + render( <UncontrolledBoxControl /> ); const input = screen.getByRole( 'textbox', { name: 'All sides' } ); @@ -54,7 +64,7 @@ describe( 'BoxControl', () => { } ); it( 'should update input values when interacting with slider', () => { - render( <BoxControl onChange={ () => {} } /> ); + render( <UncontrolledBoxControl /> ); const slider = screen.getByRole( 'slider' ); @@ -68,7 +78,7 @@ describe( 'BoxControl', () => { it( 'should update slider values when interacting with input', async () => { const user = userEvent.setup(); - render( <BoxControl onChange={ () => {} } /> ); + render( <UncontrolledBoxControl /> ); const input = screen.getByRole( 'textbox', { name: 'All sides', @@ -82,7 +92,7 @@ describe( 'BoxControl', () => { } ); it( 'should render the number input with a default min value of 0', () => { - render( <BoxControl onChange={ () => {} } /> ); + render( <UncontrolledBoxControl /> ); const input = screen.getByRole( 'textbox', { name: 'All sides' } ); @@ -91,10 +101,7 @@ describe( 'BoxControl', () => { it( 'should pass down `inputProps` to the underlying number input', () => { render( - <BoxControl - onChange={ () => {} } - inputProps={ { min: 10, max: 50 } } - /> + <UncontrolledBoxControl inputProps={ { min: 10, max: 50 } } /> ); const input = screen.getByRole( 'textbox', { name: 'All sides' } ); @@ -108,7 +115,7 @@ describe( 'BoxControl', () => { it( 'should reset values when clicking Reset', async () => { const user = userEvent.setup(); - render( <BoxControl onChange={ () => {} } /> ); + render( <UncontrolledBoxControl /> ); const input = screen.getByRole( 'textbox', { name: 'All sides', @@ -127,7 +134,7 @@ describe( 'BoxControl', () => { it( 'should reset values when clicking Reset, if controlled', async () => { const user = userEvent.setup(); - render( <Example /> ); + render( <ControlledBoxControl /> ); const input = screen.getByRole( 'textbox', { name: 'All sides', @@ -146,7 +153,7 @@ describe( 'BoxControl', () => { it( 'should reset values when clicking Reset, if controlled <-> uncontrolled state changes', async () => { const user = userEvent.setup(); - render( <Example /> ); + render( <ControlledBoxControl /> ); const input = screen.getByRole( 'textbox', { name: 'All sides', @@ -166,7 +173,9 @@ describe( 'BoxControl', () => { const user = userEvent.setup(); const spyChange = jest.fn(); - render( <BoxControl onChange={ ( v ) => spyChange( v ) } /> ); + render( + <UncontrolledBoxControl onChange={ ( v ) => spyChange( v ) } /> + ); const input = screen.getByRole( 'textbox', { name: 'All sides', @@ -196,7 +205,7 @@ describe( 'BoxControl', () => { it( 'should update a single side value when unlinked', async () => { const user = userEvent.setup(); - render( <Example /> ); + render( <ControlledBoxControl /> ); await user.click( screen.getByRole( 'button', { name: 'Unlink sides' } ) @@ -224,7 +233,7 @@ describe( 'BoxControl', () => { it( 'should update a single side value when using slider unlinked', async () => { const user = userEvent.setup(); - render( <Example /> ); + render( <ControlledBoxControl /> ); await user.click( screen.getByRole( 'button', { name: 'Unlink sides' } ) @@ -252,7 +261,7 @@ describe( 'BoxControl', () => { it( 'should update a whole axis when value is changed when unlinked', async () => { const user = userEvent.setup(); - render( <Example splitOnAxis /> ); + render( <ControlledBoxControl splitOnAxis /> ); await user.click( screen.getByRole( 'button', { name: 'Unlink sides' } ) @@ -276,7 +285,7 @@ describe( 'BoxControl', () => { it( 'should update a whole axis using a slider when value is changed when unlinked', async () => { const user = userEvent.setup(); - render( <Example splitOnAxis /> ); + render( <ControlledBoxControl splitOnAxis /> ); await user.click( screen.getByRole( 'button', { name: 'Unlink sides' } ) @@ -300,7 +309,7 @@ describe( 'BoxControl', () => { it( 'should show "Mixed" label when sides have different values but are linked', async () => { const user = userEvent.setup(); - render( <Example /> ); + render( <ControlledBoxControl /> ); const unlinkButton = screen.getByRole( 'button', { name: 'Unlink sides', @@ -330,7 +339,7 @@ describe( 'BoxControl', () => { const user = userEvent.setup(); // Render control. - render( <BoxControl onChange={ () => {} } /> ); + render( <UncontrolledBoxControl /> ); // Make unit selection on all input control. await user.selectOptions( @@ -362,7 +371,7 @@ describe( 'BoxControl', () => { const user = userEvent.setup(); // Render control. - const { rerender } = render( <BoxControl onChange={ () => {} } /> ); + const { rerender } = render( <UncontrolledBoxControl /> ); // Make unit selection on all input control. await user.selectOptions( @@ -390,9 +399,7 @@ describe( 'BoxControl', () => { } ); // Rerender with individual side value & confirm unit is selected. - rerender( - <BoxControl values={ { top: '2.5em' } } onChange={ () => {} } /> - ); + rerender( <UncontrolledBoxControl values={ { top: '2.5em' } } /> ); const rerenderedControls = screen.getAllByRole( 'combobox', { name: 'Select unit', @@ -414,7 +421,7 @@ describe( 'BoxControl', () => { const user = userEvent.setup(); const onChangeSpy = jest.fn(); - render( <BoxControl onChange={ onChangeSpy } /> ); + render( <UncontrolledBoxControl onChange={ onChangeSpy } /> ); const valueInput = screen.getByRole( 'textbox', { name: 'All sides', @@ -443,7 +450,7 @@ describe( 'BoxControl', () => { const user = userEvent.setup(); const setState = jest.fn(); - render( <BoxControl onChange={ setState } /> ); + render( <UncontrolledBoxControl onChange={ setState } /> ); await user.selectOptions( screen.getByRole( 'combobox', { diff --git a/packages/components/src/tools-panel/tools-panel/README.md b/packages/components/src/tools-panel/tools-panel/README.md index 1daa7537335e1c..1895f5ccc843ec 100644 --- a/packages/components/src/tools-panel/tools-panel/README.md +++ b/packages/components/src/tools-panel/tools-panel/README.md @@ -124,6 +124,7 @@ export function DimensionPanel() { onDeselect={ () => setPadding( undefined ) } > <BoxControl + __next40pxDefaultSize label={ __( 'Padding' ) } onChange={ setPadding } values={ padding } @@ -136,6 +137,7 @@ export function DimensionPanel() { onDeselect={ () => setMargin( undefined ) } > <BoxControl + __next40pxDefaultSize label={ __( 'Margin' ) } onChange={ setMargin } values={ margin } From 1339e85cbcc2769aa26d238fb491328ccfa2753a Mon Sep 17 00:00:00 2001 From: "Stephen A. Bernhardt" <sabernhardt@yahoo.com> Date: Thu, 28 Nov 2024 22:58:06 -0600 Subject: [PATCH 1763/1908] Add space between attributes for Search block (#61399) Add space between attributes in the markup of the search block, to ensure that the HTML is valid. --- packages/block-library/src/search/index.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/search/index.php b/packages/block-library/src/search/index.php index b74daf548a8025..87e12f5d33d079 100644 --- a/packages/block-library/src/search/index.php +++ b/packages/block-library/src/search/index.php @@ -177,9 +177,9 @@ function render_block_core_search( $attributes ) { ) ); $form_directives = ' - data-wp-interactive="core/search"' - . $form_context . - 'data-wp-class--wp-block-search__searchfield-hidden="!context.isSearchInputVisible" + data-wp-interactive="core/search" + ' . $form_context . ' + data-wp-class--wp-block-search__searchfield-hidden="!context.isSearchInputVisible" data-wp-on-async--keydown="actions.handleSearchKeydown" data-wp-on-async--focusout="actions.handleSearchFocusout" '; From a6212c88baf4f688b64f948c7bdb454043f83407 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 29 Nov 2024 10:59:55 +0400 Subject: [PATCH 1764/1908] Editor: Refactor 'PostPublishPanelPostpublish' to function component (#67398) * Editor: Refactor 'PostPublishPanelPostpublish' to function component * Extract copy button Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- .../post-publish-panel/postpublish.js | 238 +++++++++--------- 1 file changed, 114 insertions(+), 124 deletions(-) diff --git a/packages/editor/src/components/post-publish-panel/postpublish.js b/packages/editor/src/components/post-publish-panel/postpublish.js index 29ee1871057ea1..98afb4d1d573e7 100644 --- a/packages/editor/src/components/post-publish-panel/postpublish.js +++ b/packages/editor/src/components/post-publish-panel/postpublish.js @@ -3,8 +3,8 @@ */ import { PanelBody, Button, TextControl } from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; -import { Component, createRef } from '@wordpress/element'; -import { withSelect } from '@wordpress/data'; +import { useCallback, useEffect, useState, useRef } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; import { addQueryArgs, safeDecodeURIComponent } from '@wordpress/url'; import { decodeEntities } from '@wordpress/html-entities'; import { useCopyToClipboard } from '@wordpress/compose'; @@ -41,142 +41,132 @@ const getFuturePostUrl = ( post ) => { return post.permalink_template; }; -function CopyButton( { text, onCopy, children } ) { - const ref = useCopyToClipboard( text, onCopy ); +function CopyButton( { text } ) { + const [ showCopyConfirmation, setShowCopyConfirmation ] = useState( false ); + const timeoutIdRef = useRef(); + const ref = useCopyToClipboard( text, () => { + setShowCopyConfirmation( true ); + if ( timeoutIdRef.current ) { + clearTimeout( timeoutIdRef.current ); + } + timeoutIdRef.current = setTimeout( () => { + setShowCopyConfirmation( false ); + }, 4000 ); + } ); + + useEffect( () => { + return () => { + if ( timeoutIdRef.current ) { + clearTimeout( timeoutIdRef.current ); + } + }; + }, [] ); + return ( <Button __next40pxDefaultSize variant="secondary" ref={ ref }> - { children } + { showCopyConfirmation ? __( 'Copied!' ) : __( 'Copy' ) } </Button> ); } -class PostPublishPanelPostpublish extends Component { - constructor() { - super( ...arguments ); - this.state = { - showCopyConfirmation: false, +export default function PostPublishPanelPostpublish( { + focusOnMount, + children, +} ) { + const { post, postType, isScheduled } = useSelect( ( select ) => { + const { + getEditedPostAttribute, + getCurrentPost, + isCurrentPostScheduled, + } = select( editorStore ); + const { getPostType } = select( coreStore ); + + return { + post: getCurrentPost(), + postType: getPostType( getEditedPostAttribute( 'type' ) ), + isScheduled: isCurrentPostScheduled(), }; - this.onCopy = this.onCopy.bind( this ); - this.onSelectInput = this.onSelectInput.bind( this ); - this.postLink = createRef(); - } - - componentDidMount() { - if ( this.props.focusOnMount ) { - this.postLink.current.focus(); - } - } - - componentWillUnmount() { - clearTimeout( this.dismissCopyConfirmation ); - } - - onCopy() { - this.setState( { - showCopyConfirmation: true, - } ); + }, [] ); + + const postLabel = postType?.labels?.singular_name; + const viewPostLabel = postType?.labels?.view_item; + const addNewPostLabel = postType?.labels?.add_new_item; + const link = + post.status === 'future' ? getFuturePostUrl( post ) : post.link; + const addLink = addQueryArgs( 'post-new.php', { + post_type: post.type, + } ); + + const postLinkRef = useCallback( + ( node ) => { + if ( focusOnMount && node ) { + node.focus(); + } + }, + [ focusOnMount ] + ); - clearTimeout( this.dismissCopyConfirmation ); - this.dismissCopyConfirmation = setTimeout( () => { - this.setState( { - showCopyConfirmation: false, - } ); - }, 4000 ); - } + const postPublishNonLinkHeader = isScheduled ? ( + <> + { __( 'is now scheduled. It will go live on' ) }{ ' ' } + <PostScheduleLabel />. + </> + ) : ( + __( 'is now live.' ) + ); - onSelectInput( event ) { - event.target.select(); - } + return ( + <div className="post-publish-panel__postpublish"> + <PanelBody className="post-publish-panel__postpublish-header"> + <a ref={ postLinkRef } href={ link }> + { decodeEntities( post.title ) || __( '(no title)' ) } + </a>{ ' ' } + { postPublishNonLinkHeader } + </PanelBody> + <PanelBody> + <p className="post-publish-panel__postpublish-subheader"> + <strong>{ __( 'What’s next?' ) }</strong> + </p> + <div className="post-publish-panel__postpublish-post-address-container"> + <TextControl + __next40pxDefaultSize + __nextHasNoMarginBottom + className="post-publish-panel__postpublish-post-address" + readOnly + label={ sprintf( + /* translators: %s: post type singular name */ + __( '%s address' ), + postLabel + ) } + value={ safeDecodeURIComponent( link ) } + onFocus={ ( event ) => event.target.select() } + /> - render() { - const { children, isScheduled, post, postType } = this.props; - const postLabel = postType?.labels?.singular_name; - const viewPostLabel = postType?.labels?.view_item; - const addNewPostLabel = postType?.labels?.add_new_item; - const link = - post.status === 'future' ? getFuturePostUrl( post ) : post.link; - const addLink = addQueryArgs( 'post-new.php', { - post_type: post.type, - } ); - - const postPublishNonLinkHeader = isScheduled ? ( - <> - { __( 'is now scheduled. It will go live on' ) }{ ' ' } - <PostScheduleLabel />. - </> - ) : ( - __( 'is now live.' ) - ); - - return ( - <div className="post-publish-panel__postpublish"> - <PanelBody className="post-publish-panel__postpublish-header"> - <a ref={ this.postLink } href={ link }> - { decodeEntities( post.title ) || __( '(no title)' ) } - </a>{ ' ' } - { postPublishNonLinkHeader } - </PanelBody> - <PanelBody> - <p className="post-publish-panel__postpublish-subheader"> - <strong>{ __( 'What’s next?' ) }</strong> - </p> - <div className="post-publish-panel__postpublish-post-address-container"> - <TextControl - __next40pxDefaultSize - __nextHasNoMarginBottom - className="post-publish-panel__postpublish-post-address" - readOnly - label={ sprintf( - /* translators: %s: post type singular name */ - __( '%s address' ), - postLabel - ) } - value={ safeDecodeURIComponent( link ) } - onFocus={ this.onSelectInput } - /> - - <div className="post-publish-panel__postpublish-post-address__copy-button-wrap"> - <CopyButton text={ link } onCopy={ this.onCopy }> - { this.state.showCopyConfirmation - ? __( 'Copied!' ) - : __( 'Copy' ) } - </CopyButton> - </div> + <div className="post-publish-panel__postpublish-post-address__copy-button-wrap"> + <CopyButton text={ link } /> </div> + </div> - <div className="post-publish-panel__postpublish-buttons"> - { ! isScheduled && ( - <Button - variant="primary" - href={ link } - __next40pxDefaultSize - > - { viewPostLabel } - </Button> - ) } + <div className="post-publish-panel__postpublish-buttons"> + { ! isScheduled && ( <Button - variant={ isScheduled ? 'primary' : 'secondary' } + variant="primary" + href={ link } __next40pxDefaultSize - href={ addLink } > - { addNewPostLabel } + { viewPostLabel } </Button> - </div> - </PanelBody> - { children } - </div> - ); - } + ) } + <Button + variant={ isScheduled ? 'primary' : 'secondary' } + __next40pxDefaultSize + href={ addLink } + > + { addNewPostLabel } + </Button> + </div> + </PanelBody> + { children } + </div> + ); } - -export default withSelect( ( select ) => { - const { getEditedPostAttribute, getCurrentPost, isCurrentPostScheduled } = - select( editorStore ); - const { getPostType } = select( coreStore ); - - return { - post: getCurrentPost(), - postType: getPostType( getEditedPostAttribute( 'type' ) ), - isScheduled: isCurrentPostScheduled(), - }; -} )( PostPublishPanelPostpublish ); From a572238c5d90b83e3d8d55c738a0cc5f474c2c7b Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Fri, 29 Nov 2024 08:39:23 +0100 Subject: [PATCH 1765/1908] [mini] drag and drop: fix scroll disorientation after drop (#67405) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- .../src/components/use-moving-animation/index.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/block-editor/src/components/use-moving-animation/index.js b/packages/block-editor/src/components/use-moving-animation/index.js index 602b683150d0cc..ef367c0f332101 100644 --- a/packages/block-editor/src/components/use-moving-animation/index.js +++ b/packages/block-editor/src/components/use-moving-animation/index.js @@ -52,6 +52,7 @@ function useMovingAnimation( { triggerAnimationOnChange, clientId } ) { isFirstMultiSelectedBlock, isBlockMultiSelected, isAncestorMultiSelected, + isDraggingBlocks, } = useSelect( blockEditorStore ); // Whenever the trigger changes, we need to take a snapshot of the current @@ -85,6 +86,11 @@ function useMovingAnimation( { triggerAnimationOnChange, clientId } ) { } } + // Neither animate nor scroll. + if ( isDraggingBlocks() ) { + return; + } + // We disable the animation if the user has a preference for reduced // motion, if the user is typing (insertion by Enter), or if the block // count exceeds the threshold (insertion caused all the blocks that @@ -153,6 +159,7 @@ function useMovingAnimation( { triggerAnimationOnChange, clientId } ) { isFirstMultiSelectedBlock, isBlockMultiSelected, isAncestorMultiSelected, + isDraggingBlocks, ] ); return ref; From 8acc11dec8cbb3e335002c1119da1d5b6b90eabc Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 29 Nov 2024 10:19:48 +0100 Subject: [PATCH 1766/1908] Menu: throw when subcomponents are not rendered inside top level Menu (#67411) * Menu: throw when subcomponents are not rendered inside top level Menu * CHANGELOG * Remove unnecessary optional chaining * Rename changelog section --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 6 +++++- packages/components/src/menu/checkbox-item.tsx | 10 ++++++++-- packages/components/src/menu/group-label.tsx | 9 ++++++++- packages/components/src/menu/group.tsx | 9 ++++++++- packages/components/src/menu/item-help-text.tsx | 11 ++++++++++- packages/components/src/menu/item-label.tsx | 11 ++++++++++- packages/components/src/menu/item.tsx | 8 +++++++- packages/components/src/menu/radio-item.tsx | 10 ++++++++-- packages/components/src/menu/separator.tsx | 11 +++++++++-- 9 files changed, 73 insertions(+), 12 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index fe326e847970b4..37da311b0547a3 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -7,6 +7,10 @@ - `BoxControl`: Passive deprecate `onMouseOver`/`onMouseOut`. Pass to the `inputProps` prop instead ([#67332](https://github.com/WordPress/gutenberg/pull/67332)). - `BoxControl`: Deprecate 36px default size ([#66704](https://github.com/WordPress/gutenberg/pull/66704)). +### Experimental + +- `Menu`: throw when subcomponents are not rendered inside top level `Menu` ([#67411](https://github.com/WordPress/gutenberg/pull/67411)). + ### Internal - Upgraded `@ariakit/react` (v0.4.13) and `@ariakit/test` (v0.4.5) ([#65907](https://github.com/WordPress/gutenberg/pull/65907)). @@ -20,7 +24,7 @@ - `FontSizePicker`: Deprecate 36px default size ([#66920](https://github.com/WordPress/gutenberg/pull/66920)). - `ComboboxControl`: Deprecate 36px default size ([#66900](https://github.com/WordPress/gutenberg/pull/66900)). - `ToggleGroupControl`: Deprecate 36px default size ([#66747](https://github.com/WordPress/gutenberg/pull/66747)). -- `RangeControl`: Deprecate 36px default size ([#66721](https://github.com/WordPress/gutenberg/pull/66721)). +- `RangeControl`: Deprecate 36px default size ([#66721](https://github.com/WordPress/gutenberg/pull/66721)). ### Bug Fixes diff --git a/packages/components/src/menu/checkbox-item.tsx b/packages/components/src/menu/checkbox-item.tsx index 182c27dfdee305..ddb700b43324a6 100644 --- a/packages/components/src/menu/checkbox-item.tsx +++ b/packages/components/src/menu/checkbox-item.tsx @@ -26,16 +26,22 @@ export const MenuCheckboxItem = forwardRef< ) { const menuContext = useContext( MenuContext ); + if ( ! menuContext?.store ) { + throw new Error( + 'Menu.CheckboxItem can only be rendered inside a Menu component' + ); + } + return ( <Styled.MenuCheckboxItem ref={ ref } { ...props } accessibleWhenDisabled hideOnClick={ hideOnClick } - store={ menuContext?.store } + store={ menuContext.store } > <Ariakit.MenuItemCheck - store={ menuContext?.store } + store={ menuContext.store } render={ <Styled.ItemPrefixWrapper /> } // Override some ariakit inline styles style={ { width: 'auto', height: 'auto' } } diff --git a/packages/components/src/menu/group-label.tsx b/packages/components/src/menu/group-label.tsx index 71c5c7de69941e..5bf081880cb1d7 100644 --- a/packages/components/src/menu/group-label.tsx +++ b/packages/components/src/menu/group-label.tsx @@ -17,6 +17,13 @@ export const MenuGroupLabel = forwardRef< WordPressComponentProps< MenuGroupLabelProps, 'div', false > >( function MenuGroup( props, ref ) { const menuContext = useContext( MenuContext ); + + if ( ! menuContext?.store ) { + throw new Error( + 'Menu.GroupLabel can only be rendered inside a Menu component' + ); + } + return ( <Styled.MenuGroupLabel ref={ ref } @@ -31,7 +38,7 @@ export const MenuGroupLabel = forwardRef< /> } { ...props } - store={ menuContext?.store } + store={ menuContext.store } /> ); } ); diff --git a/packages/components/src/menu/group.tsx b/packages/components/src/menu/group.tsx index f9a4138fe43580..834350955f3c5d 100644 --- a/packages/components/src/menu/group.tsx +++ b/packages/components/src/menu/group.tsx @@ -16,11 +16,18 @@ export const MenuGroup = forwardRef< WordPressComponentProps< MenuGroupProps, 'div', false > >( function MenuGroup( props, ref ) { const menuContext = useContext( MenuContext ); + + if ( ! menuContext?.store ) { + throw new Error( + 'Menu.Group can only be rendered inside a Menu component' + ); + } + return ( <Styled.MenuGroup ref={ ref } { ...props } - store={ menuContext?.store } + store={ menuContext.store } /> ); } ); diff --git a/packages/components/src/menu/item-help-text.tsx b/packages/components/src/menu/item-help-text.tsx index 0ccc8f7461a8ff..13d14c294125bd 100644 --- a/packages/components/src/menu/item-help-text.tsx +++ b/packages/components/src/menu/item-help-text.tsx @@ -1,18 +1,27 @@ /** * WordPress dependencies */ -import { forwardRef } from '@wordpress/element'; +import { forwardRef, useContext } from '@wordpress/element'; /** * Internal dependencies */ import type { WordPressComponentProps } from '../context'; +import { MenuContext } from './context'; import * as Styled from './styles'; export const MenuItemHelpText = forwardRef< HTMLSpanElement, WordPressComponentProps< { children: React.ReactNode }, 'span', true > >( function MenuItemHelpText( props, ref ) { + const menuContext = useContext( MenuContext ); + + if ( ! menuContext?.store ) { + throw new Error( + 'Menu.ItemHelpText can only be rendered inside a Menu component' + ); + } + return ( <Styled.MenuItemHelpText numberOfLines={ 2 } ref={ ref } { ...props } /> ); diff --git a/packages/components/src/menu/item-label.tsx b/packages/components/src/menu/item-label.tsx index 458f69558eafbc..4f5f80e547861f 100644 --- a/packages/components/src/menu/item-label.tsx +++ b/packages/components/src/menu/item-label.tsx @@ -1,18 +1,27 @@ /** * WordPress dependencies */ -import { forwardRef } from '@wordpress/element'; +import { forwardRef, useContext } from '@wordpress/element'; /** * Internal dependencies */ import type { WordPressComponentProps } from '../context'; +import { MenuContext } from './context'; import * as Styled from './styles'; export const MenuItemLabel = forwardRef< HTMLSpanElement, WordPressComponentProps< { children: React.ReactNode }, 'span', true > >( function MenuItemLabel( props, ref ) { + const menuContext = useContext( MenuContext ); + + if ( ! menuContext?.store ) { + throw new Error( + 'Menu.ItemLabel can only be rendered inside a Menu component' + ); + } + return ( <Styled.MenuItemLabel numberOfLines={ 1 } ref={ ref } { ...props } /> ); diff --git a/packages/components/src/menu/item.tsx b/packages/components/src/menu/item.tsx index 6e8c510e4c9c2a..6d09bdf3d0f591 100644 --- a/packages/components/src/menu/item.tsx +++ b/packages/components/src/menu/item.tsx @@ -20,13 +20,19 @@ export const MenuItem = forwardRef< ) { const menuContext = useContext( MenuContext ); + if ( ! menuContext?.store ) { + throw new Error( + 'Menu.Item can only be rendered inside a Menu component' + ); + } + return ( <Styled.MenuItem ref={ ref } { ...props } accessibleWhenDisabled hideOnClick={ hideOnClick } - store={ menuContext?.store } + store={ menuContext.store } > <Styled.ItemPrefixWrapper>{ prefix }</Styled.ItemPrefixWrapper> diff --git a/packages/components/src/menu/radio-item.tsx b/packages/components/src/menu/radio-item.tsx index 45b0039f900e20..5534a6b7f3e10c 100644 --- a/packages/components/src/menu/radio-item.tsx +++ b/packages/components/src/menu/radio-item.tsx @@ -33,16 +33,22 @@ export const MenuRadioItem = forwardRef< ) { const menuContext = useContext( MenuContext ); + if ( ! menuContext?.store ) { + throw new Error( + 'Menu.RadioItem can only be rendered inside a Menu component' + ); + } + return ( <Styled.MenuRadioItem ref={ ref } { ...props } accessibleWhenDisabled hideOnClick={ hideOnClick } - store={ menuContext?.store } + store={ menuContext.store } > <Ariakit.MenuItemCheck - store={ menuContext?.store } + store={ menuContext.store } render={ <Styled.ItemPrefixWrapper /> } // Override some ariakit inline styles style={ { width: 'auto', height: 'auto' } } diff --git a/packages/components/src/menu/separator.tsx b/packages/components/src/menu/separator.tsx index 5d0110016d9c4a..57cff572c287a0 100644 --- a/packages/components/src/menu/separator.tsx +++ b/packages/components/src/menu/separator.tsx @@ -16,12 +16,19 @@ export const MenuSeparator = forwardRef< WordPressComponentProps< MenuSeparatorProps, 'hr', false > >( function MenuSeparator( props, ref ) { const menuContext = useContext( MenuContext ); + + if ( ! menuContext?.store ) { + throw new Error( + 'Menu.Separator can only be rendered inside a Menu component' + ); + } + return ( <Styled.MenuSeparator ref={ ref } { ...props } - store={ menuContext?.store } - variant={ menuContext?.variant } + store={ menuContext.store } + variant={ menuContext.variant } /> ); } ); From 68c7aba5277eb1fb2d956f88ba9729325eec2e12 Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 29 Nov 2024 10:42:52 +0100 Subject: [PATCH 1767/1908] Tabs: overhaul unit tests (#66140) * Rewrite unit tests * Extract waitForComponentToBeInitializedWithSelectedTab utility function * Use describe.each to run same test against controlled / uncontrolled components * Re-enable tabs when testing disabled tabs * Mock isRTL and test RTL keyboard navigation * CHANGELOG * Remove CHANGELOG entry * Fix typo --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/src/tabs/test/index.tsx | 2439 ++++++++++++------- 1 file changed, 1492 insertions(+), 947 deletions(-) diff --git a/packages/components/src/tabs/test/index.tsx b/packages/components/src/tabs/test/index.tsx index dcf64102c9fa67..fd9ceb38190a79 100644 --- a/packages/components/src/tabs/test/index.tsx +++ b/packages/components/src/tabs/test/index.tsx @@ -9,6 +9,7 @@ import { render } from '@ariakit/test/react'; * WordPress dependencies */ import { useEffect, useState } from '@wordpress/element'; +import { isRTL } from '@wordpress/i18n'; /** * Internal dependencies @@ -16,6 +17,16 @@ import { useEffect, useState } from '@wordpress/element'; import { Tabs } from '..'; import type { TabsProps } from '../types'; +// Setup mocking the `isRTL` function to test arrow key navigation behavior. +jest.mock( '@wordpress/i18n', () => { + const original = jest.requireActual( '@wordpress/i18n' ); + return { + ...original, + isRTL: jest.fn( () => false ), + }; +} ); +const mockedIsRTL = isRTL as jest.Mock; + type Tab = { tabId: string; title: string; @@ -50,6 +61,30 @@ const TABS: Tab[] = [ }, ]; +const TABS_WITH_ALPHA_DISABLED = TABS.map( ( tabObj ) => + tabObj.tabId === 'alpha' + ? { + ...tabObj, + tab: { + ...tabObj.tab, + disabled: true, + }, + } + : tabObj +); + +const TABS_WITH_BETA_DISABLED = TABS.map( ( tabObj ) => + tabObj.tabId === 'beta' + ? { + ...tabObj, + tab: { + ...tabObj.tab, + disabled: true, + }, + } + : tabObj +); + const TABS_WITH_DELTA: Tab[] = [ ...TABS, { @@ -141,11 +176,47 @@ const ControlledTabs = ( { ); }; -const getSelectedTab = async () => - await screen.findByRole( 'tab', { selected: true } ); - let originalGetClientRects: () => DOMRectList; +async function waitForComponentToBeInitializedWithSelectedTab( + selectedTabName: string | undefined +) { + if ( ! selectedTabName ) { + // Wait for the tablist to be tabbable as a mean to know + // that ariakit has finished initializing. + await waitFor( () => + expect( screen.getByRole( 'tablist' ) ).toHaveAttribute( + 'tabindex', + expect.stringMatching( /^(0|-1)$/ ) + ) + ); + // No initially selected tabs or tabpanels. + await waitFor( () => + expect( + screen.queryByRole( 'tab', { selected: true } ) + ).not.toBeInTheDocument() + ); + await waitFor( () => + expect( screen.queryByRole( 'tabpanel' ) ).not.toBeInTheDocument() + ); + } else { + // Waiting for a tab to be selected is a sign that the component + // has fully initialized. + expect( + await screen.findByRole( 'tab', { + selected: true, + name: selectedTabName, + } ) + ).toBeVisible(); + // The corresponding tabpanel is also shown. + expect( + screen.getByRole( 'tabpanel', { + name: selectedTabName, + } ) + ).toBeVisible(); + } +} + describe( 'Tabs', () => { beforeAll( () => { originalGetClientRects = window.HTMLElement.prototype.getClientRects; @@ -162,13 +233,16 @@ describe( 'Tabs', () => { window.HTMLElement.prototype.getClientRects = originalGetClientRects; } ); - describe( 'Accessibility and semantics', () => { - it( 'should use the correct aria attributes', async () => { + describe( 'Adherence to spec and basic behavior', () => { + it( 'should apply the correct roles, semantics and attributes', async () => { await render( <UncontrolledTabs tabs={ TABS } /> ); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Alpha' ); + const tabList = screen.getByRole( 'tablist' ); const allTabs = screen.getAllByRole( 'tab' ); - const selectedTabPanel = await screen.findByRole( 'tabpanel' ); + const allTabpanels = screen.getAllByRole( 'tabpanel' ); expect( tabList ).toBeVisible(); expect( tabList ).toHaveAttribute( @@ -178,133 +252,103 @@ describe( 'Tabs', () => { expect( allTabs ).toHaveLength( TABS.length ); - // The selected `tab` aria-controls the active `tabpanel`, - // which is `aria-labelledby` the selected `tab`. - expect( selectedTabPanel ).toBeVisible(); + // Only 1 tab panel is accessible — the one associated with the + // selected tab. The selected `tab` aria-controls the active + /// `tabpanel`, which is `aria-labelledby` the selected `tab`. + expect( allTabpanels ).toHaveLength( 1 ); + + expect( allTabpanels[ 0 ] ).toBeVisible(); expect( allTabs[ 0 ] ).toHaveAttribute( 'aria-controls', - selectedTabPanel.getAttribute( 'id' ) + allTabpanels[ 0 ].getAttribute( 'id' ) ); - expect( selectedTabPanel ).toHaveAttribute( + expect( allTabpanels[ 0 ] ).toHaveAttribute( 'aria-labelledby', allTabs[ 0 ].getAttribute( 'id' ) ); } ); - } ); - describe( 'Focus Behavior', () => { - it( 'should focus on the related TabPanel when pressing the Tab key', async () => { - await render( <UncontrolledTabs tabs={ TABS } /> ); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - - const selectedTabPanel = await screen.findByRole( 'tabpanel' ); - - // Tab should initially focus the first tab in the tablist, which - // is Alpha. - await press.Tab(); - expect( - await screen.findByRole( 'tab', { name: 'Alpha' } ) - ).toHaveFocus(); - - // By default the tabpanel should receive focus - await press.Tab(); - expect( selectedTabPanel ).toHaveFocus(); - } ); - it( 'should not focus on the related TabPanel when pressing the Tab key if `focusable: false` is set', async () => { - const TABS_WITH_ALPHA_FOCUSABLE_FALSE = TABS.map( ( tabObj ) => - tabObj.tabId === 'alpha' - ? { - ...tabObj, - content: ( - <> - Selected Tab: Alpha - <button>Alpha Button</button> - </> - ), - tabpanel: { focusable: false }, - } - : tabObj - ); + it( 'should associate each `tab` with the correct `tabpanel`, even if they are not rendered in the same order', async () => { + const TABS_WITH_DELTA_REVERSED = [ ...TABS_WITH_DELTA ].reverse(); await render( - <UncontrolledTabs tabs={ TABS_WITH_ALPHA_FOCUSABLE_FALSE } /> + <Tabs> + <Tabs.TabList> + { TABS_WITH_DELTA.map( ( tabObj ) => ( + <Tabs.Tab + key={ tabObj.tabId } + tabId={ tabObj.tabId } + className={ tabObj.tab.className } + disabled={ tabObj.tab.disabled } + > + { tabObj.title } + </Tabs.Tab> + ) ) } + </Tabs.TabList> + { TABS_WITH_DELTA_REVERSED.map( ( tabObj ) => ( + <Tabs.TabPanel + key={ tabObj.tabId } + tabId={ tabObj.tabId } + focusable={ tabObj.tabpanel?.focusable } + > + { tabObj.content } + </Tabs.TabPanel> + ) ) } + </Tabs> ); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - - const alphaButton = await screen.findByRole( 'button', { - name: /alpha button/i, - } ); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Alpha' ); - // Tab should initially focus the first tab in the tablist, which - // is Alpha. - await press.Tab(); + // Select Beta, make sure the correct tabpanel is rendered + await click( screen.getByRole( 'tab', { name: 'Beta' } ) ); expect( - await screen.findByRole( 'tab', { name: 'Alpha' } ) - ).toHaveFocus(); - // Because the alpha tabpanel is set to `focusable: false`, pressing - // the Tab key should focus the button, not the tabpanel - await press.Tab(); - expect( alphaButton ).toHaveFocus(); - } ); - - it( "should focus the first tab, even if disabled, when the current selected tab id doesn't match an existing one", async () => { - const TABS_WITH_ALPHA_DISABLED = TABS.map( ( tabObj ) => - tabObj.tabId === 'alpha' - ? { - ...tabObj, - tab: { - ...tabObj.tab, - disabled: true, - }, - } - : tabObj - ); - - await render( - <ControlledTabs - tabs={ TABS_WITH_ALPHA_DISABLED } - selectedTabId="non-existing-tab" - /> - ); - - // No tab should be selected i.e. it doesn't fall back to first tab. - await waitFor( () => - expect( - screen.queryByRole( 'tab', { selected: true } ) - ).not.toBeInTheDocument() - ); - - // No tabpanel should be rendered either - expect( screen.queryByRole( 'tabpanel' ) ).not.toBeInTheDocument(); - - await press.Tab(); + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toBeVisible(); expect( - await screen.findByRole( 'tab', { name: 'Alpha' } ) - ).toHaveFocus(); + screen.getByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); - await press.ArrowRight(); + // Select Gamma, make sure the correct tabpanel is rendered + await click( screen.getByRole( 'tab', { name: 'Gamma' } ) ); expect( - await screen.findByRole( 'tab', { name: 'Beta' } ) - ).toHaveFocus(); - - await press.ArrowRight(); + screen.getByRole( 'tab', { + selected: true, + name: 'Gamma', + } ) + ).toBeVisible(); expect( - await screen.findByRole( 'tab', { name: 'Gamma' } ) - ).toHaveFocus(); + screen.getByRole( 'tabpanel', { + name: 'Gamma', + } ) + ).toBeVisible(); - await press.Tab(); - await press.ShiftTab(); + // Select Delta, make sure the correct tabpanel is rendered + await click( screen.getByRole( 'tab', { name: 'Delta' } ) ); + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Delta', + } ) + ).toBeVisible(); expect( - await screen.findByRole( 'tab', { name: 'Gamma' } ) - ).toHaveFocus(); + screen.getByRole( 'tabpanel', { + name: 'Delta', + } ) + ).toBeVisible(); } ); - } ); - describe( 'Tab Attributes', () => { it( "should apply the tab's `className` to the tab button", async () => { await render( <UncontrolledTabs tabs={ TABS } /> ); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Alpha' ); + expect( await screen.findByRole( 'tab', { name: 'Alpha' } ) ).toHaveClass( 'alpha-class' ); @@ -317,908 +361,1076 @@ describe( 'Tabs', () => { } ); } ); - describe( 'Tab Activation', () => { - it( 'defaults to automatic tab activation (pointer clicks)', async () => { + describe( 'pointer interactions', () => { + it( 'should select a tab when clicked', async () => { const mockOnSelect = jest.fn(); await render( <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> ); - // Alpha is the initially selected tab - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( - await screen.findByRole( 'tabpanel', { name: 'Alpha' } ) - ).toBeInTheDocument(); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Alpha' ); + + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); // Click on Beta, make sure beta is the selected tab await click( screen.getByRole( 'tab', { name: 'Beta' } ) ); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); expect( - screen.getByRole( 'tabpanel', { name: 'Beta' } ) - ).toBeInTheDocument(); + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); + + expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' ); - // Click on Alpha, make sure beta is the selected tab + // Click on Alpha, make sure alpha is the selected tab await click( screen.getByRole( 'tab', { name: 'Alpha' } ) ); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( - screen.getByRole( 'tabpanel', { name: 'Alpha' } ) - ).toBeInTheDocument(); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); - } ); - - it( 'defaults to automatic tab activation (arrow keys)', async () => { - const mockOnSelect = jest.fn(); - - await render( - <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> - ); - - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - - // onSelect gets called on the initial render. It should be called - // with the first enabled tab, which is alpha. - expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); - - // Tab to focus the tablist. Make sure alpha is focused. - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).not.toHaveFocus(); - await press.Tab(); - expect( await getSelectedTab() ).toHaveFocus(); - - // Navigate forward with arrow keys and make sure the Beta tab is - // selected automatically. - await press.ArrowRight(); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); - expect( await getSelectedTab() ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' ); + screen.getByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Alpha', + } ) + ).toBeVisible(); - // Navigate backwards with arrow keys. Make sure alpha is - // selected automatically. - await press.ArrowLeft(); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).toHaveFocus(); expect( mockOnSelect ).toHaveBeenCalledTimes( 3 ); expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); } ); - it( 'wraps around the last/first tab when using arrow keys', async () => { + it( 'should not select a disabled tab when clicked', async () => { const mockOnSelect = jest.fn(); await render( - <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> + <UncontrolledTabs + tabs={ TABS_WITH_BETA_DISABLED } + onSelect={ mockOnSelect } + /> ); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).not.toHaveFocus(); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Alpha' ); - // onSelect gets called on the initial render. expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); - // Tab to focus the tablist. Make sure Alpha is focused. - await press.Tab(); - expect( await getSelectedTab() ).toHaveFocus(); + // Clicking on Beta does not result in beta being selected + // because the tab is disabled. + await click( screen.getByRole( 'tab', { name: 'Beta' } ) ); - // Navigate backwards with arrow keys and make sure that the Gamma tab - // (the last tab) is selected automatically. - await press.ArrowLeft(); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); - expect( await getSelectedTab() ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'gamma' ); + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Alpha', + } ) + ).toBeVisible(); - // Navigate forward with arrow keys. Make sure alpha (the first tab) is - // selected automatically. - await press.ArrowRight(); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 3 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); } ); + } ); - it( 'should not move tab selection when pressing the up/down arrow keys, unless the orientation is changed to `vertical`', async () => { - const mockOnSelect = jest.fn(); + describe( 'initial tab selection', () => { + describe( 'when a selected tab id is not specified', () => { + describe( 'when left `undefined` [Uncontrolled]', () => { + it( 'should choose the first tab as selected', async () => { + await render( <UncontrolledTabs tabs={ TABS } /> ); - const { rerender } = await render( - <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> - ); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( + 'Alpha' + ); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).not.toHaveFocus(); + // Press tab. The selected tab (alpha) received focus. + await press.Tab(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toHaveFocus(); + } ); + + it( 'should choose the first non-disabled tab if the first tab is disabled', async () => { + await render( + <UncontrolledTabs tabs={ TABS_WITH_ALPHA_DISABLED } /> + ); + + // Beta is automatically selected as the selected tab, since alpha is + // disabled. + await waitForComponentToBeInitializedWithSelectedTab( + 'Beta' + ); + + // Press tab. The selected tab (beta) received focus. The corresponding + // tabpanel is shown. + await press.Tab(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); + } ); + } ); + describe( 'when `null` [Controlled]', () => { + it( 'should not have a selected tab nor show any tabpanels, make the tablist tabbable and still allow selecting tabs', async () => { + await render( + <ControlledTabs tabs={ TABS } selectedTabId={ null } /> + ); + + // No initially selected tabs or tabpanels. + await waitForComponentToBeInitializedWithSelectedTab( + undefined + ); + + // Press tab. The tablist receives focus + await press.Tab(); + expect( + await screen.findByRole( 'tablist' ) + ).toHaveFocus(); - // onSelect gets called on the initial render. - expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); + // Press right arrow to select the first tab (alpha) and + // show the related tabpanel. + await press.ArrowRight(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toHaveFocus(); + expect( + await screen.findByRole( 'tabpanel', { + name: 'Alpha', + } ) + ).toBeVisible(); + } ); + } ); + } ); - // Tab to focus the tablist. Make sure Alpha is focused. - await press.Tab(); - expect( await getSelectedTab() ).toHaveFocus(); + describe( 'when a selected tab id is specified', () => { + describe( 'through the `defaultTabId` prop [Uncontrolled]', () => { + it( 'should select the initial tab matching the `defaultTabId` prop', async () => { + await render( + <UncontrolledTabs tabs={ TABS } defaultTabId="beta" /> + ); + + // Beta is the initially selected tab + await waitForComponentToBeInitializedWithSelectedTab( + 'Beta' + ); + + // Press tab. The selected tab (beta) received focus. The corresponding + // tabpanel is shown. + await press.Tab(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); + } ); + + it( 'should select the initial tab matching the `defaultTabId` prop even if the tab is disabled', async () => { + await render( + <UncontrolledTabs + tabs={ TABS_WITH_BETA_DISABLED } + defaultTabId="beta" + /> + ); + + // Beta is automatically selected as the selected tab despite being + // disabled, respecting the `defaultTabId` prop. + await waitForComponentToBeInitializedWithSelectedTab( + 'Beta' + ); + + // Press tab. The selected tab (beta) received focus, since it is + // accessible despite being disabled. + await press.Tab(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); + } ); + + it( 'should not have a selected tab nor show any tabpanels, but allow tabbing to the first tab when `defaultTabId` prop does not match any known tab', async () => { + await render( + <UncontrolledTabs + tabs={ TABS } + defaultTabId="non-existing-tab" + /> + ); + + // No initially selected tabs or tabpanels, since the `defaultTabId` + // prop is not matching any known tabs. + await waitForComponentToBeInitializedWithSelectedTab( + undefined + ); + + // Press tab. The first tab receives focus, but it's + // not selected. + await press.Tab(); + expect( + screen.getByRole( 'tab', { name: 'Alpha' } ) + ).toHaveFocus(); + await waitFor( () => + expect( + screen.queryByRole( 'tab', { selected: true } ) + ).not.toBeInTheDocument() + ); + await waitFor( () => + expect( + screen.queryByRole( 'tabpanel' ) + ).not.toBeInTheDocument() + ); - // Press the arrow up key, nothing happens. - await press.ArrowUp(); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); + // Press right arrow to select the next tab (beta) and + // show the related tabpanel. + await press.ArrowRight(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); + expect( + await screen.findByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); + } ); + + it( 'should not have a selected tab nor show any tabpanels, but allow tabbing to the first tab, even when disabled, when `defaultTabId` prop does not match any known tab', async () => { + await render( + <UncontrolledTabs + tabs={ TABS_WITH_ALPHA_DISABLED } + defaultTabId="non-existing-tab" + /> + ); + + // No initially selected tabs or tabpanels, since the `defaultTabId` + // prop is not matching any known tabs. + await waitForComponentToBeInitializedWithSelectedTab( + undefined + ); + + // Press tab. The first tab receives focus, but it's + // not selected. + await press.Tab(); + expect( + screen.getByRole( 'tab', { name: 'Alpha' } ) + ).toHaveFocus(); + await waitFor( () => + expect( + screen.queryByRole( 'tab', { selected: true } ) + ).not.toBeInTheDocument() + ); + await waitFor( () => + expect( + screen.queryByRole( 'tabpanel' ) + ).not.toBeInTheDocument() + ); - // Press the arrow down key, nothing happens - await press.ArrowDown(); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); + // Press right arrow to select the next tab (beta) and + // show the related tabpanel. + await press.ArrowRight(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); + expect( + await screen.findByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); + } ); + + it( 'should ignore any changes to the `defaultTabId` prop after the first render', async () => { + const mockOnSelect = jest.fn(); + + const { rerender } = await render( + <UncontrolledTabs + tabs={ TABS } + defaultTabId="beta" + onSelect={ mockOnSelect } + /> + ); + + // Beta is the initially selected tab + await waitForComponentToBeInitializedWithSelectedTab( + 'Beta' + ); + + // Changing the defaultTabId prop to gamma should not have any effect. + await rerender( + <UncontrolledTabs + tabs={ TABS } + defaultTabId="gamma" + onSelect={ mockOnSelect } + /> + ); - // Change orientation to `vertical`. When the orientation is vertical, - // left/right arrow keys are replaced by up/down arrow keys. - await rerender( - <UncontrolledTabs - tabs={ TABS } - onSelect={ mockOnSelect } - orientation="vertical" - /> - ); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); - expect( screen.getByRole( 'tablist' ) ).toHaveAttribute( - 'aria-orientation', - 'vertical' - ); + expect( mockOnSelect ).not.toHaveBeenCalled(); + } ); + } ); - // Make sure alpha is still focused. - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).toHaveFocus(); + describe( 'through the `selectedTabId` prop [Controlled]', () => { + describe( 'when the `selectedTabId` matches an existing tab', () => { + it( 'should choose the initial tab matching the `selectedTabId`', async () => { + await render( + <ControlledTabs + tabs={ TABS } + selectedTabId="beta" + /> + ); - // Navigate forward with arrow keys and make sure the Beta tab is - // selected automatically. - await press.ArrowDown(); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); - expect( await getSelectedTab() ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' ); + // Beta is the initially selected tab + await waitForComponentToBeInitializedWithSelectedTab( + 'Beta' + ); - // Navigate backwards with arrow keys. Make sure alpha is - // selected automatically. - await press.ArrowUp(); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 3 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); + // Press tab. The selected tab (beta) received focus, since it is + // accessible despite being disabled. + await press.Tab(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); + } ); - // Navigate backwards with arrow keys. Make sure alpha is - // selected automatically. - await press.ArrowUp(); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); - expect( await getSelectedTab() ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 4 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'gamma' ); - - // Navigate backwards with arrow keys. Make sure alpha is - // selected automatically. - await press.ArrowDown(); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 5 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); - } ); + it( 'should choose the initial tab matching the `selectedTabId` even if a `defaultTabId` is passed', async () => { + await render( + <ControlledTabs + tabs={ TABS } + defaultTabId="beta" + selectedTabId="gamma" + /> + ); - it( 'should move focus on a tab even if disabled with arrow key, but not with pointer clicks', async () => { - const mockOnSelect = jest.fn(); + // Gamma is the initially selected tab + await waitForComponentToBeInitializedWithSelectedTab( + 'Gamma' + ); - const TABS_WITH_DELTA_DISABLED = TABS_WITH_DELTA.map( ( tabObj ) => - tabObj.tabId === 'delta' - ? { - ...tabObj, - tab: { - ...tabObj.tab, - disabled: true, - }, - } - : tabObj - ); + // Press tab. The selected tab (gamma) received focus, since it is + // accessible despite being disabled. + await press.Tab(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Gamma', + } ) + ).toHaveFocus(); + } ); - await render( - <UncontrolledTabs - tabs={ TABS_WITH_DELTA_DISABLED } - onSelect={ mockOnSelect } - /> - ); + it( 'should choose the initial tab matching the `selectedTabId` even if the tab is disabled', async () => { + await render( + <ControlledTabs + tabs={ TABS_WITH_BETA_DISABLED } + selectedTabId="beta" + /> + ); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).not.toHaveFocus(); + // Beta is the initially selected tab + await waitForComponentToBeInitializedWithSelectedTab( + 'Beta' + ); - // onSelect gets called on the initial render. - expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); + // Press tab. The selected tab (beta) received focus, since it is + // accessible despite being disabled. + await press.Tab(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); + } ); + } ); - // Tab to focus the tablist. Make sure Alpha is focused. - await press.Tab(); - expect( await getSelectedTab() ).toHaveFocus(); + describe( "when the `selectedTabId` doesn't match an existing tab", () => { + it( 'should not have a selected tab nor show any tabpanels, but allow tabbing to the first tab', async () => { + await render( + <ControlledTabs + tabs={ TABS } + selectedTabId="non-existing-tab" + /> + ); - // Confirm onSelect has not been re-called - expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); + // No initially selected tabs or tabpanels, since the `selectedTabId` + // prop is not matching any known tabs. + await waitForComponentToBeInitializedWithSelectedTab( + undefined + ); - // Press the right arrow key three times. Since the delta tab is disabled: - // - it won't be selected. The gamma tab will be selected instead, since - // it was the tab that was last selected before delta. Therefore, the - // `mockOnSelect` function gets called only twice (and not three times) - // - it will receive focus, when using arrow keys - await press.ArrowRight(); - await press.ArrowRight(); - await press.ArrowRight(); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); - expect( - screen.getByRole( 'tab', { name: 'Delta' } ) - ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 3 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'gamma' ); - - // Navigate backwards with arrow keys. The gamma tab receives focus. - // The `mockOnSelect` callback doesn't fire, since the gamma tab was - // already selected. - await press.ArrowLeft(); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); - expect( await getSelectedTab() ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 3 ); + // Press tab. The first tab receives focus, but it's + // not selected. + await press.Tab(); + expect( + screen.getByRole( 'tab', { name: 'Alpha' } ) + ).toHaveFocus(); + await waitFor( () => + expect( + screen.queryByRole( 'tab', { selected: true } ) + ).not.toBeInTheDocument() + ); + await waitFor( () => + expect( + screen.queryByRole( 'tabpanel' ) + ).not.toBeInTheDocument() + ); - // Click on the disabled tab. Compared to using arrow keys to move the - // focus, disabled tabs ignore pointer clicks — and therefore, they don't - // receive focus, nor they cause the `mockOnSelect` function to fire. - await click( screen.getByRole( 'tab', { name: 'Delta' } ) ); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); - expect( await getSelectedTab() ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 3 ); - } ); + // Press right arrow to select the next tab (beta) and + // show the related tabpanel. + await press.ArrowRight(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); + expect( + await screen.findByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); + } ); - it( 'should not focus the next tab when the Tab key is pressed', async () => { - await render( <UncontrolledTabs tabs={ TABS } /> ); + it( 'should not have a selected tab nor show any tabpanels, but allow tabbing to the first tab even when disabled', async () => { + await render( + <ControlledTabs + tabs={ TABS_WITH_ALPHA_DISABLED } + selectedTabId="non-existing-tab" + /> + ); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).not.toHaveFocus(); + // No initially selected tabs or tabpanels, since the `selectedTabId` + // prop is not matching any known tabs. + await waitForComponentToBeInitializedWithSelectedTab( + undefined + ); - // Tab should initially focus the first tab in the tablist, which - // is Alpha. - await press.Tab(); - expect( - await screen.findByRole( 'tab', { name: 'Alpha' } ) - ).toHaveFocus(); + // Press tab. The first tab receives focus, but it's + // not selected. + await press.Tab(); + expect( + screen.getByRole( 'tab', { name: 'Alpha' } ) + ).toHaveFocus(); + await waitFor( () => + expect( + screen.queryByRole( 'tab', { selected: true } ) + ).not.toBeInTheDocument() + ); + await waitFor( () => + expect( + screen.queryByRole( 'tabpanel' ) + ).not.toBeInTheDocument() + ); - // Because all other tabs should have `tabindex=-1`, pressing Tab - // should NOT move the focus to the next tab, which is Beta. - // Instead, focus should go to the currently selected tabpanel (alpha). - await press.Tab(); - expect( - await screen.findByRole( 'tabpanel', { - name: 'Alpha', - } ) - ).toHaveFocus(); + // Press right arrow to select the next tab (beta) and + // show the related tabpanel. + await press.ArrowRight(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); + expect( + await screen.findByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); + } ); + } ); + } ); } ); + } ); - it( 'switches to manual tab activation when the `selectOnMove` prop is set to `false`', async () => { - const mockOnSelect = jest.fn(); + describe( 'keyboard interactions', () => { + describe.each( [ + [ 'Uncontrolled', UncontrolledTabs ], + [ 'Controlled', ControlledTabs ], + ] )( '[`%s`]', ( _mode, Component ) => { + it( 'should handle the tablist as one tab stop', async () => { + await render( <Component tabs={ TABS } /> ); - await render( - <UncontrolledTabs - tabs={ TABS } - onSelect={ mockOnSelect } - selectOnMove={ false } - /> - ); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Alpha' ); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).not.toHaveFocus(); + // Press tab. The selected tab (alpha) received focus. + await press.Tab(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toHaveFocus(); - // onSelect gets called on the initial render. - expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); + // By default the tabpanel should receive focus + await press.Tab(); + expect( + await screen.findByRole( 'tabpanel', { + name: 'Alpha', + } ) + ).toHaveFocus(); + } ); - // Click on Alpha and make sure it is selected. - // onSelect shouldn't fire since the selected tab didn't change. - await click( screen.getByRole( 'tab', { name: 'Alpha' } ) ); - expect( - await screen.findByRole( 'tab', { name: 'Alpha' } ) - ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); - - // Navigate forward with arrow keys. Make sure Beta is focused, but - // that the tab selection happens only when pressing the spacebar - // or enter key. onSelect shouldn't fire since the selected tab - // didn't change. - await press.ArrowRight(); - expect( - await screen.findByRole( 'tab', { name: 'Beta' } ) - ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - - await press.Enter(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' ); + it( 'should not focus the tabpanel container when its `focusable` property is set to `false`', async () => { + await render( + <Component + tabs={ TABS.map( ( tabObj ) => + tabObj.tabId === 'alpha' + ? { + ...tabObj, + content: ( + <> + Selected Tab: Alpha + <button>Alpha Button</button> + </> + ), + tabpanel: { focusable: false }, + } + : tabObj + ) } + /> + ); - // Navigate forward with arrow keys. Make sure Gamma (last tab) is - // focused, but that tab selection happens only when pressing the - // spacebar or enter key. onSelect shouldn't fire since the selected - // tab didn't change. - await press.ArrowRight(); - expect( - await screen.findByRole( 'tab', { name: 'Gamma' } ) - ).toHaveFocus(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); - expect( - screen.getByRole( 'tab', { name: 'Gamma' } ) - ).toHaveFocus(); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Alpha' ); - await press.Space(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 3 ); - expect( mockOnSelect ).toHaveBeenLastCalledWith( 'gamma' ); - } ); - } ); - describe( 'Uncontrolled mode', () => { - describe( 'Without `defaultTabId` prop', () => { - it( 'should render first tab', async () => { - await render( <UncontrolledTabs tabs={ TABS } /> ); + // Tab should initially focus the first tab in the tablist, which + // is Alpha. + await press.Tab(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toHaveFocus(); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + // In this case, the tabpanel container is skipped and focus is + // moved directly to its contents + await press.Tab(); expect( - await screen.findByRole( 'tabpanel', { name: 'Alpha' } ) - ).toBeInTheDocument(); + await screen.findByRole( 'button', { + name: 'Alpha Button', + } ) + ).toHaveFocus(); } ); - it( 'should not have a selected tab if the currently selected tab is removed', async () => { - const { rerender } = await render( - <UncontrolledTabs tabs={ TABS } /> - ); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( await getSelectedTab() ).not.toHaveFocus(); + it( 'should select tabs in the tablist when using the left and right arrow keys by default (automatic tab activation)', async () => { + const mockOnSelect = jest.fn(); - // Tab to focus the tablist. Make sure Alpha is focused. - await press.Tab(); - expect( await getSelectedTab() ).toHaveFocus(); + await render( + <Component tabs={ TABS } onSelect={ mockOnSelect } /> + ); - // Remove first item from `TABS` array - await rerender( <UncontrolledTabs tabs={ TABS.slice( 1 ) } /> ); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Alpha' ); - // No tab should be selected i.e. it doesn't fall back to first tab. - await waitFor( () => - expect( - screen.queryByRole( 'tab', { selected: true } ) - ).not.toBeInTheDocument() - ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); - // No tabpanel should be rendered either + // Focus the tablist (and the selected tab, alpha) + // Tab should initially focus the first tab in the tablist, which + // is Alpha. + await press.Tab(); expect( - screen.queryByRole( 'tabpanel' ) - ).not.toBeInTheDocument(); - } ); - } ); + await screen.findByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toHaveFocus(); - describe( 'With `defaultTabId`', () => { - it( 'should render the tab set by `defaultTabId` prop', async () => { - await render( - <UncontrolledTabs tabs={ TABS } defaultTabId="beta" /> - ); + // Press the right arrow key to select the beta tab + await press.ArrowRight(); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); - } ); + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); - it( 'should not select a tab when `defaultTabId` does not match any known tab', async () => { - await render( - <UncontrolledTabs - tabs={ TABS } - defaultTabId="does-not-exist" - /> - ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' ); - // No tab should be selected i.e. it doesn't fall back to first tab. - expect( - screen.queryByRole( 'tab', { selected: true } ) - ).not.toBeInTheDocument(); + // Press the right arrow key to select the gamma tab + await press.ArrowRight(); - // No tabpanel should be rendered either expect( - screen.queryByRole( 'tabpanel' ) - ).not.toBeInTheDocument(); - } ); - it( 'should not change tabs when defaultTabId is changed', async () => { - const { rerender } = await render( - <UncontrolledTabs tabs={ TABS } defaultTabId="beta" /> - ); + screen.getByRole( 'tab', { + selected: true, + name: 'Gamma', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Gamma', + } ) + ).toBeVisible(); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 3 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'gamma' ); - await rerender( - <UncontrolledTabs tabs={ TABS } defaultTabId="alpha" /> - ); + // Press the left arrow key to select the beta tab + await press.ArrowLeft(); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); + + expect( mockOnSelect ).toHaveBeenCalledTimes( 4 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' ); } ); - it( 'should not have any selected tabs if the currently selected tab is removed, even if a tab is matching the defaultTabId', async () => { + it( 'should not automatically select tabs in the tablist when pressing the left and right arrow keys if the `selectOnMove` prop is set to `false` (manual tab activation)', async () => { const mockOnSelect = jest.fn(); - const { rerender } = await render( - <UncontrolledTabs + await render( + <Component tabs={ TABS } - defaultTabId="gamma" onSelect={ mockOnSelect } + selectOnMove={ false } /> ); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Alpha' ); - await click( screen.getByRole( 'tab', { name: 'Alpha' } ) ); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); - await rerender( - <UncontrolledTabs - tabs={ TABS.slice( 1 ) } - defaultTabId="gamma" - onSelect={ mockOnSelect } - /> - ); + // Focus the tablist (and the selected tab, alpha) + // Tab should initially focus the first tab in the tablist, which + // is Alpha. + await press.Tab(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toHaveFocus(); - // No tab should be selected i.e. it doesn't fall back to first tab. - await waitFor( () => - expect( - screen.queryByRole( 'tab', { selected: true } ) - ).not.toBeInTheDocument() - ); + // Press the right arrow key to move focus to the beta tab, + // but without selecting it + await press.ArrowRight(); + + expect( + screen.getByRole( 'tab', { + selected: false, + name: 'Beta', + } ) + ).toHaveFocus(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Alpha', + } ) + ).toBeVisible(); + + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - // No tabpanel should be rendered either + // Press the space key to click the beta tab, and select it. + // The same should be true with any other mean of clicking the tab button + // (ie. mouse click, enter key). + await press.Space(); + + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); expect( - screen.queryByRole( 'tabpanel' ) - ).not.toBeInTheDocument(); + screen.getByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); + + expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' ); } ); - it( 'should keep the currently selected tab even if it becomes disabled', async () => { + it( 'should not select tabs in the tablist when using the up and down arrow keys, unless the `orientation` prop is set to `vertical`', async () => { const mockOnSelect = jest.fn(); const { rerender } = await render( - <UncontrolledTabs - tabs={ TABS } - defaultTabId="gamma" - onSelect={ mockOnSelect } - /> + <Component tabs={ TABS } onSelect={ mockOnSelect } /> ); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); - - await click( screen.getByRole( 'tab', { name: 'Alpha' } ) ); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Alpha' ); expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); - const TABS_WITH_ALPHA_DISABLED = TABS.map( ( tabObj ) => - tabObj.tabId === 'alpha' - ? { - ...tabObj, - tab: { - ...tabObj.tab, - disabled: true, - }, - } - : tabObj - ); + // Focus the tablist (and the selected tab, alpha) + // Tab should initially focus the first tab in the tablist, which + // is Alpha. + await press.Tab(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toHaveFocus(); - await rerender( - <UncontrolledTabs - tabs={ TABS_WITH_ALPHA_DISABLED } - defaultTabId="gamma" - onSelect={ mockOnSelect } - /> - ); + // Press the up arrow key, but the focused/selected tab does not change. + await press.ArrowUp(); + + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Alpha', + } ) + ).toBeVisible(); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - } ); - it( 'should have no active tabs when the tab associated to `defaultTabId` is removed while being the active tab', async () => { - const { rerender } = await render( - <UncontrolledTabs tabs={ TABS } defaultTabId="gamma" /> - ); + // Press the down arrow key, but the focused/selected tab does not change. + await press.ArrowDown(); + + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Alpha', + } ) + ).toBeVisible(); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - // Remove gamma + // Change the orientation to "vertical" and rerender the component. await rerender( - <UncontrolledTabs - tabs={ TABS.slice( 0, 2 ) } - defaultTabId="gamma" + <Component + tabs={ TABS } + onSelect={ mockOnSelect } + orientation="vertical" /> ); - expect( screen.getAllByRole( 'tab' ) ).toHaveLength( 2 ); - // No tab should be selected i.e. it doesn't fall back to first tab. + // Pressing the down arrow key now selects the next tab (beta). + await press.ArrowDown(); + expect( - screen.queryByRole( 'tab', { selected: true } ) - ).not.toBeInTheDocument(); - // No tabpanel should be rendered either + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); expect( - screen.queryByRole( 'tabpanel' ) - ).not.toBeInTheDocument(); - } ); + screen.getByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); - it( 'waits for the tab with the `defaultTabId` to be present in the `tabs` array before selecting it', async () => { - const { rerender } = await render( - <UncontrolledTabs tabs={ TABS } defaultTabId="delta" /> - ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' ); - // No tab should be selected i.e. it doesn't fall back to first tab. - await waitFor( () => - expect( - screen.queryByRole( 'tab', { selected: true } ) - ).not.toBeInTheDocument() - ); + // Pressing the up arrow key now selects the previous tab (alpha). + await press.ArrowUp(); - // No tabpanel should be rendered either expect( - screen.queryByRole( 'tabpanel' ) - ).not.toBeInTheDocument(); - - await rerender( - <UncontrolledTabs - tabs={ TABS_WITH_DELTA } - defaultTabId="delta" - /> - ); + screen.getByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Alpha', + } ) + ).toBeVisible(); - expect( await getSelectedTab() ).toHaveTextContent( 'Delta' ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 3 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); } ); - } ); - describe( 'Disabled tab', () => { - it( 'should disable the tab when `disabled` is `true`', async () => { + it( 'should loop tab focus at the end of the tablist when using arrow keys', async () => { const mockOnSelect = jest.fn(); - const TABS_WITH_DELTA_DISABLED = TABS_WITH_DELTA.map( - ( tabObj ) => - tabObj.tabId === 'delta' - ? { - ...tabObj, - tab: { - ...tabObj.tab, - disabled: true, - }, - } - : tabObj - ); - await render( - <UncontrolledTabs - tabs={ TABS_WITH_DELTA_DISABLED } - onSelect={ mockOnSelect } - /> + <Component tabs={ TABS } onSelect={ mockOnSelect } /> ); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Alpha' ); - expect( - screen.getByRole( 'tab', { name: 'Delta' } ) - ).toHaveAttribute( 'aria-disabled', 'true' ); - - // onSelect gets called on the initial render. expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); - // Move focus to the tablist, make sure alpha is focused. + // Focus the tablist (and the selected tab, alpha) + // Tab should initially focus the first tab in the tablist, which + // is Alpha. await press.Tab(); expect( - screen.getByRole( 'tab', { name: 'Alpha' } ) + await screen.findByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) ).toHaveFocus(); - // onSelect should not be called since the disabled tab is - // highlighted, but not selected. + // Press the left arrow key to loop around and select the gamma tab await press.ArrowLeft(); - expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - // Delta (which is disabled) has focus expect( - screen.getByRole( 'tab', { name: 'Delta' } ) + screen.getByRole( 'tab', { + selected: true, + name: 'Gamma', + } ) ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Gamma', + } ) + ).toBeVisible(); - // Alpha retains the selection, even if it's not focused. - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - } ); - - it( 'should select first enabled tab when the initial tab is disabled', async () => { - const TABS_WITH_ALPHA_DISABLED = TABS.map( ( tabObj ) => - tabObj.tabId === 'alpha' - ? { - ...tabObj, - tab: { - ...tabObj.tab, - disabled: true, - }, - } - : tabObj - ); - - const { rerender } = await render( - <UncontrolledTabs tabs={ TABS_WITH_ALPHA_DISABLED } /> - ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'gamma' ); - // As alpha (first tab) is disabled, - // the first enabled tab should be beta. - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + // Press the right arrow key to loop around and select the alpha tab + await press.ArrowRight(); - // Re-enable all tabs - await rerender( <UncontrolledTabs tabs={ TABS } /> ); + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Alpha', + } ) + ).toBeVisible(); - // Even if the initial tab becomes enabled again, the selected - // tab doesn't change. - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 3 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); } ); - it( 'should select the tab associated to `defaultTabId` even if the tab is disabled', async () => { - const TABS_ONLY_GAMMA_ENABLED = TABS.map( ( tabObj ) => - tabObj.tabId !== 'gamma' - ? { - ...tabObj, - tab: { - ...tabObj.tab, - disabled: true, - }, - } - : tabObj - ); - const { rerender } = await render( - <UncontrolledTabs - tabs={ TABS_ONLY_GAMMA_ENABLED } - defaultTabId="beta" - /> - ); + // TODO: mock writing direction to RTL + it( 'should swap the left and right arrow keys when selecting tabs if the writing direction is set to RTL', async () => { + // For this test only, mock the writing direction to RTL. + mockedIsRTL.mockImplementation( () => true ); - // As alpha (first tab), and beta (the initial tab), are both - // disabled the first enabled tab should be gamma. - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + const mockOnSelect = jest.fn(); - // Re-enable all tabs - await rerender( - <UncontrolledTabs tabs={ TABS } defaultTabId="beta" /> + await render( + <Component tabs={ TABS } onSelect={ mockOnSelect } /> ); - // Even if the initial tab becomes enabled again, the selected tab doesn't - // change. - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); - } ); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Alpha' ); - it( 'should keep the currently tab as selected even when it becomes disabled', async () => { - const mockOnSelect = jest.fn(); - const { rerender } = await render( - <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> - ); - - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); - const TABS_WITH_ALPHA_DISABLED = TABS.map( ( tabObj ) => - tabObj.tabId === 'alpha' - ? { - ...tabObj, - tab: { - ...tabObj.tab, - disabled: true, - }, - } - : tabObj - ); - - // Disable alpha - await rerender( - <UncontrolledTabs - tabs={ TABS_WITH_ALPHA_DISABLED } - onSelect={ mockOnSelect } - /> - ); + // Focus the tablist (and the selected tab, alpha) + // Tab should initially focus the first tab in the tablist, which + // is Alpha. + await press.Tab(); + expect( + await screen.findByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toHaveFocus(); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); + // Press the left arrow key to select the beta tab + await press.ArrowLeft(); - // Re-enable all tabs - await rerender( - <UncontrolledTabs tabs={ TABS } onSelect={ mockOnSelect } /> - ); + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - } ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' ); - it( 'should select the tab associated to `defaultTabId` even when disabled', async () => { - const mockOnSelect = jest.fn(); + // Press the left arrow key to select the gamma tab + await press.ArrowLeft(); - const { rerender } = await render( - <UncontrolledTabs - tabs={ TABS } - onSelect={ mockOnSelect } - defaultTabId="gamma" - /> - ); + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Gamma', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Gamma', + } ) + ).toBeVisible(); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); - - const TABS_WITH_GAMMA_DISABLED = TABS.map( ( tabObj ) => - tabObj.tabId === 'gamma' - ? { - ...tabObj, - tab: { - ...tabObj.tab, - disabled: true, - }, - } - : tabObj - ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 3 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'gamma' ); - // Disable gamma - await rerender( - <UncontrolledTabs - tabs={ TABS_WITH_GAMMA_DISABLED } - onSelect={ mockOnSelect } - defaultTabId="gamma" - /> - ); + // Press the right arrow key to select the beta tab + await press.ArrowRight(); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); - // Re-enable all tabs - await rerender( - <UncontrolledTabs - tabs={ TABS } - onSelect={ mockOnSelect } - defaultTabId="gamma" - /> - ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 4 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' ); - // Confirm that alpha is still selected, and that onSelect has - // not been called again. - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); - expect( mockOnSelect ).not.toHaveBeenCalled(); + // Restore the original implementation of the isRTL function. + mockedIsRTL.mockRestore(); } ); - } ); - } ); - - describe( 'Controlled mode', () => { - it( 'should render the tab specified by the `selectedTabId` prop', async () => { - await render( - <ControlledTabs tabs={ TABS } selectedTabId="beta" /> - ); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); - expect( - await screen.findByRole( 'tabpanel', { name: 'Beta' } ) - ).toBeInTheDocument(); - } ); - it( 'should render the specified `selectedTabId`, and ignore the `defaultTabId` prop', async () => { - await render( - <ControlledTabs - tabs={ TABS } - selectedTabId="gamma" - defaultTabId="beta" - /> - ); - - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); - } ); - it( 'should not have a selected tab if `selectedTabId` does not match any known tab', async () => { - await render( - <ControlledTabs - tabs={ TABS_WITH_DELTA } - selectedTabId="does-not-exist" - /> - ); - - expect( - screen.queryByRole( 'tab', { selected: true } ) - ).not.toBeInTheDocument(); + it( 'should focus tabs in the tablist even if disabled', async () => { + const mockOnSelect = jest.fn(); - // No tabpanel should be rendered either - expect( screen.queryByRole( 'tabpanel' ) ).not.toBeInTheDocument(); - } ); - it( 'should not have a selected tab if the active tab is removed, but should select a tab that gets added if it matches the selectedTabId', async () => { - const { rerender } = await render( - <ControlledTabs tabs={ TABS } selectedTabId="beta" /> - ); + await render( + <Component + tabs={ TABS_WITH_BETA_DISABLED } + onSelect={ mockOnSelect } + /> + ); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Alpha' ); - // Remove beta - await rerender( - <ControlledTabs - tabs={ TABS.filter( ( tab ) => tab.tabId !== 'beta' ) } - selectedTabId="beta" - /> - ); - - expect( screen.getAllByRole( 'tab' ) ).toHaveLength( 2 ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); - // No tab should be selected i.e. it doesn't fall back to first tab. - // `waitFor` is needed here to prevent testing library from - // throwing a 'not wrapped in `act()`' error. - await waitFor( () => + // Focus the tablist (and the selected tab, alpha) + // Tab should initially focus the first tab in the tablist, which + // is Alpha. + await press.Tab(); expect( - screen.queryByRole( 'tab', { selected: true } ) - ).not.toBeInTheDocument() - ); - - // No tabpanel should be rendered either - expect( screen.queryByRole( 'tabpanel' ) ).not.toBeInTheDocument(); - - // Restore beta - await rerender( - <ControlledTabs tabs={ TABS } selectedTabId="beta" /> - ); - - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); - } ); - - describe( 'Disabled tab', () => { - it( 'should `selectedTabId` refers to a disabled tab', async () => { - const TABS_WITH_DELTA_WITH_BETA_DISABLED = TABS_WITH_DELTA.map( - ( tabObj ) => - tabObj.tabId === 'beta' - ? { - ...tabObj, - tab: { - ...tabObj.tab, - disabled: true, - }, - } - : tabObj - ); - - await render( - <ControlledTabs - tabs={ TABS_WITH_DELTA_WITH_BETA_DISABLED } - selectedTabId="beta" - /> - ); + await screen.findByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toHaveFocus(); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); - } ); - it( 'should keep the currently selected tab as selected even when it becomes disabled', async () => { - const { rerender } = await render( - <ControlledTabs tabs={ TABS } selectedTabId="beta" /> - ); + // Pressing the right arrow key moves focus to the beta tab, but alpha + // remains the selected tab because beta is disabled. + await press.ArrowRight(); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); - - const TABS_WITH_BETA_DISABLED = TABS.map( ( tabObj ) => - tabObj.tabId === 'beta' - ? { - ...tabObj, - tab: { - ...tabObj.tab, - disabled: true, - }, - } - : tabObj - ); + expect( + screen.getByRole( 'tab', { + selected: false, + name: 'Beta', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Alpha', + } ) + ).toBeVisible(); - await rerender( - <ControlledTabs - tabs={ TABS_WITH_BETA_DISABLED } - selectedTabId="beta" - /> - ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + // Press the right arrow key to select the gamma tab + await press.ArrowRight(); - // re-enable all tabs - await rerender( - <ControlledTabs tabs={ TABS } selectedTabId="beta" /> - ); + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Gamma', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Gamma', + } ) + ).toBeVisible(); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'gamma' ); } ); } ); - describe( 'When `selectedId` is changed by the controlling component', () => { + + describe( 'When `selectedId` is changed by the controlling component [Controlled]', () => { describe.each( [ true, false ] )( 'and `selectOnMove` is %s', ( selectOnMove ) => { @@ -1231,17 +1443,18 @@ describe( 'Tabs', () => { /> ); - expect( await getSelectedTab() ).toHaveTextContent( + // Beta is the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Beta' ); // Tab key should focus the currently selected tab, which is Beta. await press.Tab(); - expect( await getSelectedTab() ).toHaveTextContent( - 'Beta' - ); expect( - screen.getByRole( 'tab', { name: 'Beta' } ) + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) ).toHaveFocus(); await rerender( @@ -1253,17 +1466,28 @@ describe( 'Tabs', () => { ); // When the selected tab is changed, focus should not be changed. - expect( await getSelectedTab() ).toHaveTextContent( - 'Gamma' - ); expect( - screen.getByRole( 'tab', { name: 'Beta' } ) + screen.getByRole( 'tab', { + selected: true, + name: 'Gamma', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tab', { + selected: false, + name: 'Beta', + } ) ).toHaveFocus(); - // Arrow keys should move focus to the next tab, which is Gamma - await press.ArrowRight(); + // Arrow left should move focus to the previous tab (alpha). + // The alpha tab should be always focused, and should be selected + // when the `selectOnMove` prop is set to `true`. + await press.ArrowLeft(); expect( - screen.getByRole( 'tab', { name: 'Gamma' } ) + screen.getByRole( 'tab', { + selected: selectOnMove, + name: 'Alpha', + } ) ).toHaveFocus(); } ); @@ -1279,20 +1503,22 @@ describe( 'Tabs', () => { </> ); - expect( await getSelectedTab() ).toHaveTextContent( + // Beta is the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( 'Beta' ); // Tab key should focus the currently selected tab, which is Beta. await press.Tab(); await press.Tab(); - expect( await getSelectedTab() ).toHaveTextContent( - 'Beta' - ); expect( - screen.getByRole( 'tab', { name: 'Beta' } ) + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) ).toHaveFocus(); + // Change the selected tab to gamma via a controlled update. await rerender( <> <button>Focus me</button> @@ -1305,12 +1531,17 @@ describe( 'Tabs', () => { ); // When the selected tab is changed, it should not automatically receive focus. - expect( await getSelectedTab() ).toHaveTextContent( - 'Gamma' - ); - expect( - screen.getByRole( 'tab', { name: 'Beta' } ) + screen.getByRole( 'tab', { + selected: true, + name: 'Gamma', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tab', { + selected: false, + name: 'Beta', + } ) ).toHaveFocus(); // Press shift+tab, move focus to the button before Tabs @@ -1336,125 +1567,439 @@ describe( 'Tabs', () => { } ); } ); + } ); - describe( 'When `selectOnMove` is `true`', () => { - it( 'should automatically select a newly focused tab', async () => { - await render( - <ControlledTabs tabs={ TABS } selectedTabId="beta" /> - ); + describe( 'miscellaneous runtime changes', () => { + describe( 'removing a tab', () => { + describe( 'with no explicitly set initial tab', () => { + it( 'should not select a new tab when the selected tab is removed', async () => { + const mockOnSelect = jest.fn(); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + const { rerender } = await render( + <UncontrolledTabs + tabs={ TABS } + onSelect={ mockOnSelect } + /> + ); - await press.Tab(); + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( + 'Alpha' + ); - // Tab key should focus the currently selected tab, which is Beta. - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); - expect( await getSelectedTab() ).toHaveFocus(); + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); - // Arrow keys should select and move focus to the next tab. - await press.ArrowRight(); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); - expect( await getSelectedTab() ).toHaveFocus(); + // Select gamma + await click( screen.getByRole( 'tab', { name: 'Gamma' } ) ); + + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Gamma', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Gamma', + } ) + ).toBeVisible(); + + expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( 'gamma' ); + + // Remove gamma + await rerender( + <UncontrolledTabs + tabs={ TABS.slice( 0, 2 ) } + onSelect={ mockOnSelect } + /> + ); + + expect( screen.getAllByRole( 'tab' ) ).toHaveLength( 2 ); + + // No tab should be selected i.e. it doesn't fall back to gamma, + // even if it matches the `defaultTabId` prop. + expect( + screen.queryByRole( 'tab', { selected: true } ) + ).not.toBeInTheDocument(); + // No tabpanel should be rendered either + expect( + screen.queryByRole( 'tabpanel' ) + ).not.toBeInTheDocument(); + + expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); + } ); } ); + + describe.each( [ + [ 'defaultTabId', 'Uncontrolled', UncontrolledTabs ], + [ 'selectedTabId', 'Controlled', ControlledTabs ], + ] )( + 'when using the `%s` prop [%s]', + ( propName, _mode, Component ) => { + it( 'should not select a new tab when the selected tab is removed', async () => { + const mockOnSelect = jest.fn(); + + const initialComponentProps = { + tabs: TABS, + [ propName ]: 'gamma', + onSelect: mockOnSelect, + }; + + const { rerender } = await render( + <Component { ...initialComponentProps } /> + ); + + // Gamma is the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( + 'Gamma' + ); + + // Remove gamma + await rerender( + <Component + { ...initialComponentProps } + tabs={ TABS.slice( 0, 2 ) } + /> + ); + + expect( screen.getAllByRole( 'tab' ) ).toHaveLength( + 2 + ); + // No tab should be selected i.e. it doesn't fall back to first tab. + expect( + screen.queryByRole( 'tab', { selected: true } ) + ).not.toBeInTheDocument(); + // No tabpanel should be rendered either + expect( + screen.queryByRole( 'tabpanel' ) + ).not.toBeInTheDocument(); + + // Re-add gamma. Gamma becomes selected again. + await rerender( + <Component { ...initialComponentProps } /> + ); + + expect( screen.getAllByRole( 'tab' ) ).toHaveLength( + TABS.length + ); + + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Gamma', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Gamma', + } ) + ).toBeVisible(); + + expect( mockOnSelect ).not.toHaveBeenCalled(); + } ); + + it( `should not select the tab matching the \`${ propName }\` prop as a fallback when the selected tab is removed`, async () => { + const mockOnSelect = jest.fn(); + + const initialComponentProps = { + tabs: TABS, + [ propName ]: 'gamma', + onSelect: mockOnSelect, + }; + + const { rerender } = await render( + <Component { ...initialComponentProps } /> + ); + + // Gamma is the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( + 'Gamma' + ); + + // Select alpha + await click( + screen.getByRole( 'tab', { name: 'Alpha' } ) + ); + + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Alpha', + } ) + ).toBeVisible(); + + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( + 'alpha' + ); + + // Remove alpha + await rerender( + <Component + { ...initialComponentProps } + tabs={ TABS.slice( 1 ) } + /> + ); + + expect( screen.getAllByRole( 'tab' ) ).toHaveLength( + 2 + ); + + // No tab should be selected i.e. it doesn't fall back to gamma, + // even if it matches the `defaultTabId` prop. + expect( + screen.queryByRole( 'tab', { selected: true } ) + ).not.toBeInTheDocument(); + // No tabpanel should be rendered either + expect( + screen.queryByRole( 'tabpanel' ) + ).not.toBeInTheDocument(); + + // Re-add alpha. Alpha becomes selected again. + await rerender( + <Component { ...initialComponentProps } /> + ); + + expect( screen.getAllByRole( 'tab' ) ).toHaveLength( + TABS.length + ); + + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Alpha', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Alpha', + } ) + ).toBeVisible(); + + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); + } ); + } + ); } ); - describe( 'When `selectOnMove` is `false`', () => { - it( 'should apply focus without automatically changing the selected tab', async () => { - await render( - <ControlledTabs - tabs={ TABS } - selectedTabId="beta" - selectOnMove={ false } - /> - ); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + describe( 'adding a tab', () => { + describe.each( [ + [ 'defaultTabId', 'Uncontrolled', UncontrolledTabs ], + [ 'selectedTabId', 'Controlled', ControlledTabs ], + ] )( + 'when using the `%s` prop [%s]', + ( propName, _mode, Component ) => { + it( `should select a newly added tab if it matches the \`${ propName }\` prop`, async () => { + const mockOnSelect = jest.fn(); + + const initialComponentProps = { + tabs: TABS, + [ propName ]: 'delta', + onSelect: mockOnSelect, + }; - // Tab key should focus the currently selected tab, which is Beta. - await press.Tab(); - await waitFor( async () => - expect( - await screen.findByRole( 'tab', { name: 'Beta' } ) - ).toHaveFocus() - ); + const { rerender } = await render( + <Component { ...initialComponentProps } /> + ); - // Arrow key should move focus but not automatically change the selected tab. - await press.ArrowRight(); - expect( - screen.getByRole( 'tab', { name: 'Gamma' } ) - ).toHaveFocus(); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + // No initially selected tabs or tabpanels, since the `defaultTabId` + // prop is not matching any known tabs. + await waitForComponentToBeInitializedWithSelectedTab( + undefined + ); - // Pressing the spacebar should select the focused tab. - await press.Space(); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + expect( mockOnSelect ).not.toHaveBeenCalled(); - // Arrow key should move focus but not automatically change the selected tab. - await press.ArrowRight(); - expect( - screen.getByRole( 'tab', { name: 'Alpha' } ) - ).toHaveFocus(); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + // Re-render with beta disabled. + await rerender( + <Component + { ...initialComponentProps } + tabs={ TABS_WITH_DELTA } + /> + ); - // Pressing the enter/return should select the focused tab. - await press.Enter(); - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - } ); + // Delta becomes selected + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Delta', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Delta', + } ) + ).toBeVisible(); + + expect( mockOnSelect ).not.toHaveBeenCalled(); + } ); + } + ); } ); - } ); - it( 'should associate each `Tab` with the correct `TabPanel`, even if they are not rendered in the same order', async () => { - const TABS_WITH_DELTA_REVERSED = [ ...TABS_WITH_DELTA ].reverse(); - - await render( - <Tabs> - <Tabs.TabList> - { TABS_WITH_DELTA.map( ( tabObj ) => ( - <Tabs.Tab - key={ tabObj.tabId } - tabId={ tabObj.tabId } - className={ tabObj.tab.className } - disabled={ tabObj.tab.disabled } - > - { tabObj.title } - </Tabs.Tab> - ) ) } - </Tabs.TabList> - { TABS_WITH_DELTA_REVERSED.map( ( tabObj ) => ( - <Tabs.TabPanel - key={ tabObj.tabId } - tabId={ tabObj.tabId } - focusable={ tabObj.tabpanel?.focusable } - > - { tabObj.content } - </Tabs.TabPanel> - ) ) } - </Tabs> - ); + describe( 'a tab becomes disabled', () => { + describe.each( [ + [ 'defaultTabId', 'Uncontrolled', UncontrolledTabs ], + [ 'selectedTabId', 'Controlled', ControlledTabs ], + ] )( + 'when using the `%s` prop [%s]', + ( propName, _mode, Component ) => { + it( `should keep the initial tab matching the \`${ propName }\` prop as selected even if it becomes disabled`, async () => { + const mockOnSelect = jest.fn(); + + const initialComponentProps = { + tabs: TABS, + [ propName ]: 'beta', + onSelect: mockOnSelect, + }; - // Alpha is the initially selected tab,and should render the correct tabpanel - expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); - expect( screen.getByRole( 'tabpanel' ) ).toHaveTextContent( - 'Selected tab: Alpha' - ); + const { rerender } = await render( + <Component { ...initialComponentProps } /> + ); - // Select Beta, make sure the correct tabpanel is rendered - await click( screen.getByRole( 'tab', { name: 'Beta' } ) ); - expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); - expect( screen.getByRole( 'tabpanel' ) ).toHaveTextContent( - 'Selected tab: Beta' - ); + // Beta is the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( + 'Beta' + ); - // Select Gamma, make sure the correct tabpanel is rendered - await click( screen.getByRole( 'tab', { name: 'Gamma' } ) ); - expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); - expect( screen.getByRole( 'tabpanel' ) ).toHaveTextContent( - 'Selected tab: Gamma' - ); + expect( mockOnSelect ).not.toHaveBeenCalled(); - // Select Delta, make sure the correct tabpanel is rendered - await click( screen.getByRole( 'tab', { name: 'Delta' } ) ); - expect( await getSelectedTab() ).toHaveTextContent( 'Delta' ); - expect( screen.getByRole( 'tabpanel' ) ).toHaveTextContent( - 'Selected tab: Delta' - ); + // Re-render with beta disabled. + await rerender( + <Component + { ...initialComponentProps } + tabs={ TABS_WITH_BETA_DISABLED } + /> + ); + + // Beta continues to be selected and focused, even if it is disabled. + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); + + // Re-enable beta. + await rerender( + <Component { ...initialComponentProps } /> + ); + + // Beta continues to be selected and focused. + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); + + expect( mockOnSelect ).not.toHaveBeenCalled(); + } ); + + it( 'should keep the current tab selected by the user as selected even if it becomes disabled', async () => { + const mockOnSelect = jest.fn(); + + const { rerender } = await render( + <Component + tabs={ TABS } + onSelect={ mockOnSelect } + /> + ); + + // Alpha is automatically selected as the selected tab. + await waitForComponentToBeInitializedWithSelectedTab( + 'Alpha' + ); + + expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( + 'alpha' + ); + + // Click on beta tab, beta becomes selected. + await click( + screen.getByRole( 'tab', { name: 'Beta' } ) + ); + + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); + + expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); + expect( mockOnSelect ).toHaveBeenLastCalledWith( + 'beta' + ); + + // Re-render with beta disabled. + await rerender( + <Component + tabs={ TABS_WITH_BETA_DISABLED } + onSelect={ mockOnSelect } + /> + ); + + // Beta continues to be selected, even if it is disabled. + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toHaveFocus(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); + + // Re-enable beta. + await rerender( + <Component + tabs={ TABS } + onSelect={ mockOnSelect } + /> + ); + + // Beta continues to be selected and focused. + expect( + screen.getByRole( 'tab', { + selected: true, + name: 'Beta', + } ) + ).toBeVisible(); + expect( + screen.getByRole( 'tabpanel', { + name: 'Beta', + } ) + ).toBeVisible(); + + expect( mockOnSelect ).toHaveBeenCalledTimes( 2 ); + } ); + } + ); + } ); } ); } ); From 6f541e75ddc8c4601171f220ee17458249aa8408 Mon Sep 17 00:00:00 2001 From: James Koster <james@jameskoster.co.uk> Date: Fri, 29 Nov 2024 09:45:31 +0000 Subject: [PATCH 1768/1908] Sidebar: Update appearance of active items (#67318) Unlinked contributors: danielvann777. Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: fcoveram <fcoveram@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> Co-authored-by: ptesei <mosne@git.wordpress.org> Co-authored-by: joedolson <joedolson@git.wordpress.org> --- .../edit-site/src/components/sidebar-dataviews/style.scss | 4 ++-- .../src/components/sidebar-navigation-item/style.scss | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-dataviews/style.scss b/packages/edit-site/src/components/sidebar-dataviews/style.scss index 14e6bf1d03fca8..a36d693c4f80ea 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/style.scss +++ b/packages/edit-site/src/components/sidebar-dataviews/style.scss @@ -19,11 +19,11 @@ &:focus, &[aria-current] { color: $gray-200; - background: $gray-800; } &.is-selected { - background: var(--wp-admin-theme-color); + background: $gray-800; + font-weight: $font-weight-medium; color: $white; } } diff --git a/packages/edit-site/src/components/sidebar-navigation-item/style.scss b/packages/edit-site/src/components/sidebar-navigation-item/style.scss index 202de5300076c1..ac1cf8b730861d 100644 --- a/packages/edit-site/src/components/sidebar-navigation-item/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-item/style.scss @@ -9,7 +9,6 @@ &:focus, &[aria-current="true"] { color: $gray-200; - background: $gray-800; .edit-site-sidebar-navigation-item__drilldown-indicator { fill: $gray-200; @@ -17,7 +16,7 @@ } &[aria-current="true"] { - background: var(--wp-admin-theme-color); + background: $gray-800; color: $white; } From aee29cb7d56c7aea6c03c4bd2a9847c87a8c5eaf Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Fri, 29 Nov 2024 11:13:25 +0100 Subject: [PATCH 1769/1908] Update @ariakit/react to 0.4.15 and @ariakit/test to 0.4.7 (#67404) * Remove ariakit dependencies * Update to latest version of ariakit * CHANGELOG * Dataviews CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- package-lock.json | 135 +++++++++++-------------------- package.json | 2 +- packages/components/CHANGELOG.md | 1 + packages/components/package.json | 2 +- packages/dataviews/CHANGELOG.md | 5 ++ packages/dataviews/package.json | 2 +- 6 files changed, 54 insertions(+), 93 deletions(-) diff --git a/package-lock.json b/package-lock.json index 58479ecfa2ed99..98865c9d041a58 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@actions/core": "1.9.1", "@actions/github": "5.0.0", "@apidevtools/json-schema-ref-parser": "11.6.4", - "@ariakit/test": "^0.4.5", + "@ariakit/test": "^0.4.7", "@babel/core": "7.25.7", "@babel/plugin-syntax-jsx": "7.25.7", "@babel/runtime-corejs3": "7.25.7", @@ -1432,14 +1432,52 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@ariakit/core": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.14.tgz", + "integrity": "sha512-hpzZvyYzGhP09S9jW1XGsU/FD5K3BKsH1eG/QJ8rfgEeUdPS7BvHPt5lHbOeJ2cMrRzBEvsEzLi1ivfDifHsVA==", + "license": "MIT" + }, + "node_modules/@ariakit/react": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.15.tgz", + "integrity": "sha512-0V2LkNPFrGRT+SEIiObx/LQjR6v3rR+mKEDUu/3tq7jfCZ+7+6Q6EMR1rFaK+XMkaRY1RWUcj/rRDWAUWnsDww==", + "license": "MIT", + "dependencies": { + "@ariakit/react-core": "0.4.15" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ariakit" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@ariakit/react-core": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.15.tgz", + "integrity": "sha512-Up8+U97nAPJdyUh9E8BCEhJYTA+eVztWpHoo1R9zZfHd4cnBWAg5RHxEmMH+MamlvuRxBQA71hFKY/735fDg+A==", + "license": "MIT", + "dependencies": { + "@ariakit/core": "0.4.14", + "@floating-ui/dom": "^1.0.0", + "use-sync-external-store": "^1.2.0" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/@ariakit/test": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/@ariakit/test/-/test-0.4.5.tgz", - "integrity": "sha512-dK9OtI8MeKfdtOiW1auDITnyaelq0O0aUTnolIqJj+RJd8LFai0gi7fQUgrun9CZHJ2wWsEad4vlviGfhfIIhQ==", + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@ariakit/test/-/test-0.4.7.tgz", + "integrity": "sha512-Zb5bnulzYGjr6sDubxOeOhk5Es6BYQq5lbcIe8xNrWUlpRiHsje/FlXNFpHnI92/7ESxH6X4pHhbb+qFAho1lw==", "dev": true, "license": "MIT", "dependencies": { - "@ariakit/core": "0.4.12", + "@ariakit/core": "0.4.14", "@testing-library/dom": "^8.0.0 || ^9.0.0 || ^10.0.0" }, "peerDependencies": { @@ -1459,13 +1497,6 @@ } } }, - "node_modules/@ariakit/test/node_modules/@ariakit/core": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.12.tgz", - "integrity": "sha512-+NNpy88tdP/w9mOBPuDrMTbtapPbo/8yVIzpQB7TAmN0sPh/Cq3nU1f2KCTCIujPmwRvAcMSW9UHOlFmbKEPOA==", - "dev": true, - "license": "MIT" - }, "node_modules/@aw-web-design/x-default-browser": { "version": "1.4.126", "resolved": "https://registry.npmjs.org/@aw-web-design/x-default-browser/-/x-default-browser-1.4.126.tgz", @@ -53681,7 +53712,7 @@ "version": "28.13.0", "license": "GPL-2.0-or-later", "dependencies": { - "@ariakit/react": "^0.4.13", + "@ariakit/react": "^0.4.15", "@babel/runtime": "7.25.7", "@emotion/cache": "^11.7.1", "@emotion/css": "^11.7.1", @@ -53736,44 +53767,6 @@ "react-dom": "^18.0.0" } }, - "packages/components/node_modules/@ariakit/core": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.12.tgz", - "integrity": "sha512-+NNpy88tdP/w9mOBPuDrMTbtapPbo/8yVIzpQB7TAmN0sPh/Cq3nU1f2KCTCIujPmwRvAcMSW9UHOlFmbKEPOA==", - "license": "MIT" - }, - "packages/components/node_modules/@ariakit/react": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.13.tgz", - "integrity": "sha512-pTGYgoqCojfyt2xNJ5VQhejxXwwtcP7VDDqcnnVChv7TA2TWWyYerJ5m4oxViI1pgeNqnHZwKlQ79ZipF7W2kQ==", - "license": "MIT", - "dependencies": { - "@ariakit/react-core": "0.4.13" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ariakit" - }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "packages/components/node_modules/@ariakit/react-core": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.13.tgz", - "integrity": "sha512-iIjQeupP9d0pOubOzX4a0UPXbhXbp0ZCduDpkv7+u/pYP/utk/YRECD0M/QpZr6YSeltmDiNxKjdyK8r9Yhv4Q==", - "license": "MIT", - "dependencies": { - "@ariakit/core": "0.4.12", - "@floating-ui/dom": "^1.0.0", - "use-sync-external-store": "^1.2.0" - }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "packages/components/node_modules/@floating-ui/react-dom": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.1.tgz", @@ -54051,7 +54044,7 @@ "version": "4.9.0", "license": "GPL-2.0-or-later", "dependencies": { - "@ariakit/react": "^0.4.13", + "@ariakit/react": "^0.4.15", "@babel/runtime": "7.25.7", "@wordpress/components": "*", "@wordpress/compose": "*", @@ -54073,44 +54066,6 @@ "react": "^18.0.0" } }, - "packages/dataviews/node_modules/@ariakit/core": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.12.tgz", - "integrity": "sha512-+NNpy88tdP/w9mOBPuDrMTbtapPbo/8yVIzpQB7TAmN0sPh/Cq3nU1f2KCTCIujPmwRvAcMSW9UHOlFmbKEPOA==", - "license": "MIT" - }, - "packages/dataviews/node_modules/@ariakit/react": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.13.tgz", - "integrity": "sha512-pTGYgoqCojfyt2xNJ5VQhejxXwwtcP7VDDqcnnVChv7TA2TWWyYerJ5m4oxViI1pgeNqnHZwKlQ79ZipF7W2kQ==", - "license": "MIT", - "dependencies": { - "@ariakit/react-core": "0.4.13" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ariakit" - }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "packages/dataviews/node_modules/@ariakit/react-core": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.13.tgz", - "integrity": "sha512-iIjQeupP9d0pOubOzX4a0UPXbhXbp0ZCduDpkv7+u/pYP/utk/YRECD0M/QpZr6YSeltmDiNxKjdyK8r9Yhv4Q==", - "license": "MIT", - "dependencies": { - "@ariakit/core": "0.4.12", - "@floating-ui/dom": "^1.0.0", - "use-sync-external-store": "^1.2.0" - }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "packages/date": { "name": "@wordpress/date", "version": "5.13.0", diff --git a/package.json b/package.json index 84425dbd1cff21..46a04a52aa6077 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@actions/core": "1.9.1", "@actions/github": "5.0.0", "@apidevtools/json-schema-ref-parser": "11.6.4", - "@ariakit/test": "^0.4.5", + "@ariakit/test": "^0.4.7", "@babel/core": "7.25.7", "@babel/plugin-syntax-jsx": "7.25.7", "@babel/runtime-corejs3": "7.25.7", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 37da311b0547a3..8fc7aff329b031 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -14,6 +14,7 @@ ### Internal - Upgraded `@ariakit/react` (v0.4.13) and `@ariakit/test` (v0.4.5) ([#65907](https://github.com/WordPress/gutenberg/pull/65907)). +- Upgraded `@ariakit/react` (v0.4.15) and `@ariakit/test` (v0.4.7) ([#67404](https://github.com/WordPress/gutenberg/pull/67404)). ## 28.13.0 (2024-11-27) diff --git a/packages/components/package.json b/packages/components/package.json index 75f0d1eb1f2331..a2acf8e2c203d4 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -32,7 +32,7 @@ "src/**/*.scss" ], "dependencies": { - "@ariakit/react": "^0.4.13", + "@ariakit/react": "^0.4.15", "@babel/runtime": "7.25.7", "@emotion/cache": "^11.7.1", "@emotion/css": "^11.7.1", diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 72f08b987a3868..7ec1b24f8745c0 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +## Internal + +- Upgraded `@ariakit/react` (v0.4.13) and `@ariakit/test` (v0.4.5) ([#65907](https://github.com/WordPress/gutenberg/pull/65907)). +- Upgraded `@ariakit/react` (v0.4.15) and `@ariakit/test` (v0.4.7) ([#67404](https://github.com/WordPress/gutenberg/pull/67404)). + ## 4.9.0 (2024-11-27) ### Bug Fixes diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index 8fe2e04236725c..c2d16b664c9040 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -43,7 +43,7 @@ "types": "build-types", "sideEffects": false, "dependencies": { - "@ariakit/react": "^0.4.13", + "@ariakit/react": "^0.4.15", "@babel/runtime": "7.25.7", "@wordpress/components": "*", "@wordpress/compose": "*", From e19a6f0175805720c611c0c74347652ee3ce546c Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Fri, 29 Nov 2024 12:21:12 +0200 Subject: [PATCH 1770/1908] Remove PostSlugCheck and PostSlug unused components (#67414) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/editor/README.md | 21 ------ packages/editor/src/components/index.js | 2 - .../editor/src/components/post-slug/check.js | 20 ----- .../editor/src/components/post-slug/index.js | 73 ------------------- .../editor/src/components/post-slug/panel.js | 22 ------ .../src/components/post-slug/style.scss | 5 -- .../src/components/post-slug/test/index.js | 53 -------------- packages/editor/src/style.scss | 1 - 8 files changed, 197 deletions(-) delete mode 100644 packages/editor/src/components/post-slug/check.js delete mode 100644 packages/editor/src/components/post-slug/index.js delete mode 100644 packages/editor/src/components/post-slug/panel.js delete mode 100644 packages/editor/src/components/post-slug/style.scss delete mode 100644 packages/editor/src/components/post-slug/test/index.js diff --git a/packages/editor/README.md b/packages/editor/README.md index ac655bd1c99d8c..36126cb8eaee3f 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -1312,27 +1312,6 @@ _Returns_ - `React.ReactNode`: The rendered component. -### PostSlug - -Renders the PostSlug component. It provide a control for editing the post slug. - -_Returns_ - -- `React.ReactNode`: The rendered component. - -### PostSlugCheck - -Wrapper component that renders its children only if the post type supports the slug. - -_Parameters_ - -- _props_ `Object`: Props. -- _props.children_ `React.ReactNode`: Children to be rendered. - -_Returns_ - -- `React.ReactNode`: The rendered component. - ### PostSticky Renders the PostSticky component. It provides a checkbox control for the sticky post feature. diff --git a/packages/editor/src/components/index.js b/packages/editor/src/components/index.js index b42566aac653be..d940532be75a3d 100644 --- a/packages/editor/src/components/index.js +++ b/packages/editor/src/components/index.js @@ -68,8 +68,6 @@ export { usePostScheduleLabel, } from './post-schedule/label'; export { default as PostSchedulePanel } from './post-schedule/panel'; -export { default as PostSlug } from './post-slug'; -export { default as PostSlugCheck } from './post-slug/check'; export { default as PostSticky } from './post-sticky'; export { default as PostStickyCheck } from './post-sticky/check'; export { default as PostSwitchToDraftButton } from './post-switch-to-draft-button'; diff --git a/packages/editor/src/components/post-slug/check.js b/packages/editor/src/components/post-slug/check.js deleted file mode 100644 index 8ca7078a1a9e24..00000000000000 --- a/packages/editor/src/components/post-slug/check.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Internal dependencies - */ -import PostTypeSupportCheck from '../post-type-support-check'; - -/** - * Wrapper component that renders its children only if the post type supports the slug. - * - * @param {Object} props Props. - * @param {React.ReactNode} props.children Children to be rendered. - * - * @return {React.ReactNode} The rendered component. - */ -export default function PostSlugCheck( { children } ) { - return ( - <PostTypeSupportCheck supportKeys="slug"> - { children } - </PostTypeSupportCheck> - ); -} diff --git a/packages/editor/src/components/post-slug/index.js b/packages/editor/src/components/post-slug/index.js deleted file mode 100644 index afff7f361ea428..00000000000000 --- a/packages/editor/src/components/post-slug/index.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - * WordPress dependencies - */ -import { useDispatch, useSelect } from '@wordpress/data'; -import { useState } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; -import { safeDecodeURIComponent, cleanForSlug } from '@wordpress/url'; -import { TextControl } from '@wordpress/components'; - -/** - * Internal dependencies - */ -import PostSlugCheck from './check'; -import { store as editorStore } from '../../store'; - -function PostSlugControl() { - const postSlug = useSelect( ( select ) => { - return safeDecodeURIComponent( - select( editorStore ).getEditedPostSlug() - ); - }, [] ); - const { editPost } = useDispatch( editorStore ); - const [ forceEmptyField, setForceEmptyField ] = useState( false ); - - return ( - <TextControl - __next40pxDefaultSize - __nextHasNoMarginBottom - label={ __( 'Slug' ) } - autoComplete="off" - spellCheck="false" - value={ forceEmptyField ? '' : postSlug } - onChange={ ( newValue ) => { - editPost( { slug: newValue } ); - // When we delete the field the permalink gets - // reverted to the original value. - // The forceEmptyField logic allows the user to have - // the field temporarily empty while typing. - if ( ! newValue ) { - if ( ! forceEmptyField ) { - setForceEmptyField( true ); - } - return; - } - if ( forceEmptyField ) { - setForceEmptyField( false ); - } - } } - onBlur={ ( event ) => { - editPost( { - slug: cleanForSlug( event.target.value ), - } ); - if ( forceEmptyField ) { - setForceEmptyField( false ); - } - } } - className="editor-post-slug" - /> - ); -} - -/** - * Renders the PostSlug component. It provide a control for editing the post slug. - * - * @return {React.ReactNode} The rendered component. - */ -export default function PostSlug() { - return ( - <PostSlugCheck> - <PostSlugControl /> - </PostSlugCheck> - ); -} diff --git a/packages/editor/src/components/post-slug/panel.js b/packages/editor/src/components/post-slug/panel.js deleted file mode 100644 index 6ab97a28b251c3..00000000000000 --- a/packages/editor/src/components/post-slug/panel.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * WordPress dependencies - */ -import { PanelRow } from '@wordpress/components'; - -/** - * Internal dependencies - */ -import PostSlugForm from './'; -import PostSlugCheck from './check'; - -export function PostSlug() { - return ( - <PostSlugCheck> - <PanelRow className="editor-post-slug"> - <PostSlugForm /> - </PanelRow> - </PostSlugCheck> - ); -} - -export default PostSlug; diff --git a/packages/editor/src/components/post-slug/style.scss b/packages/editor/src/components/post-slug/style.scss deleted file mode 100644 index 551450582128e0..00000000000000 --- a/packages/editor/src/components/post-slug/style.scss +++ /dev/null @@ -1,5 +0,0 @@ -.editor-post-slug { - display: flex; - flex-direction: column; - align-items: stretch; -} diff --git a/packages/editor/src/components/post-slug/test/index.js b/packages/editor/src/components/post-slug/test/index.js deleted file mode 100644 index fb40055111b77a..00000000000000 --- a/packages/editor/src/components/post-slug/test/index.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * External dependencies - */ -import { act, render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; - -/** - * WordPress dependencies - */ -import { useSelect, useDispatch } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import PostSlug from '../'; - -jest.mock( '@wordpress/data/src/components/use-select', () => jest.fn() ); -jest.mock( '@wordpress/data/src/components/use-dispatch/use-dispatch', () => - jest.fn() -); - -describe( 'PostSlug', () => { - it( 'should update slug with sanitized input', async () => { - const user = userEvent.setup(); - const editPost = jest.fn(); - - useSelect.mockImplementation( ( mapSelect ) => - mapSelect( () => ( { - getPostType: () => ( { - supports: { - slug: true, - }, - } ), - getEditedPostAttribute: () => 'post', - getEditedPostSlug: () => '1', - } ) ) - ); - useDispatch.mockImplementation( () => ( { - editPost, - } ) ); - - render( <PostSlug /> ); - - const input = screen.getByRole( 'textbox', { name: 'Slug' } ); - await user.type( input, '2', { - initialSelectionStart: 0, - initialSelectionEnd: 1, - } ); - act( () => input.blur() ); - - expect( editPost ).toHaveBeenCalledWith( { slug: '2' } ); - } ); -} ); diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss index 88d722867d009b..1504211a51e899 100644 --- a/packages/editor/src/style.scss +++ b/packages/editor/src/style.scss @@ -34,7 +34,6 @@ @import "./components/post-publish-panel/style.scss"; @import "./components/post-saved-state/style.scss"; @import "./components/post-schedule/style.scss"; -@import "./components/post-slug/style.scss"; @import "./components/post-status/style.scss"; @import "./components/post-sticky/style.scss"; @import "./components/post-sync-status/style.scss"; From 96647ef634baa224ebed57415b1cc3f4a0b0956e Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 29 Nov 2024 14:58:55 +0400 Subject: [PATCH 1771/1908] Editor: Use hooks instead of HOC in 'PostPublishButtonOrToggle' (#67413) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../post-publish-button-or-toggle.js | 78 +++++++++---------- .../test/post-publish-button-or-toggle.js | 33 +++++--- 2 files changed, 62 insertions(+), 49 deletions(-) diff --git a/packages/editor/src/components/post-publish-button/post-publish-button-or-toggle.js b/packages/editor/src/components/post-publish-button/post-publish-button-or-toggle.js index bf742bef1429bb..c3a355d243f345 100644 --- a/packages/editor/src/components/post-publish-button/post-publish-button-or-toggle.js +++ b/packages/editor/src/components/post-publish-button/post-publish-button-or-toggle.js @@ -1,8 +1,8 @@ /** * WordPress dependencies */ -import { useViewportMatch, compose } from '@wordpress/compose'; -import { withDispatch, withSelect } from '@wordpress/data'; +import { useViewportMatch } from '@wordpress/compose'; +import { useDispatch, useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -10,24 +10,46 @@ import { withDispatch, withSelect } from '@wordpress/data'; import PostPublishButton from './index'; import { store as editorStore } from '../../store'; -export function PostPublishButtonOrToggle( { +const IS_TOGGLE = 'toggle'; +const IS_BUTTON = 'button'; + +export default function PostPublishButtonOrToggle( { forceIsDirty, - hasPublishAction, - isBeingScheduled, - isPending, - isPublished, - isPublishSidebarEnabled, - isPublishSidebarOpened, - isScheduled, - togglePublishSidebar, setEntitiesSavedStatesCallback, - postStatusHasChanged, - postStatus, } ) { - const IS_TOGGLE = 'toggle'; - const IS_BUTTON = 'button'; - const isSmallerThanMediumViewport = useViewportMatch( 'medium', '<' ); let component; + const isSmallerThanMediumViewport = useViewportMatch( 'medium', '<' ); + const { togglePublishSidebar } = useDispatch( editorStore ); + const { + hasPublishAction, + isBeingScheduled, + isPending, + isPublished, + isPublishSidebarEnabled, + isPublishSidebarOpened, + isScheduled, + postStatus, + postStatusHasChanged, + } = useSelect( ( select ) => { + return { + hasPublishAction: + !! select( editorStore ).getCurrentPost()?._links?.[ + 'wp:action-publish' + ] ?? false, + isBeingScheduled: + select( editorStore ).isEditedPostBeingScheduled(), + isPending: select( editorStore ).isCurrentPostPending(), + isPublished: select( editorStore ).isCurrentPostPublished(), + isPublishSidebarEnabled: + select( editorStore ).isPublishSidebarEnabled(), + isPublishSidebarOpened: + select( editorStore ).isPublishSidebarOpened(), + isScheduled: select( editorStore ).isCurrentPostScheduled(), + postStatus: + select( editorStore ).getEditedPostAttribute( 'status' ), + postStatusHasChanged: select( editorStore ).getPostEdits()?.status, + }; + }, [] ); /** * Conditions to show a BUTTON (publish directly) or a TOGGLE (open publish sidebar): @@ -76,27 +98,3 @@ export function PostPublishButtonOrToggle( { /> ); } - -export default compose( - withSelect( ( select ) => ( { - hasPublishAction: - select( editorStore ).getCurrentPost()?._links?.[ - 'wp:action-publish' - ] ?? false, - isBeingScheduled: select( editorStore ).isEditedPostBeingScheduled(), - isPending: select( editorStore ).isCurrentPostPending(), - isPublished: select( editorStore ).isCurrentPostPublished(), - isPublishSidebarEnabled: - select( editorStore ).isPublishSidebarEnabled(), - isPublishSidebarOpened: select( editorStore ).isPublishSidebarOpened(), - isScheduled: select( editorStore ).isCurrentPostScheduled(), - postStatus: select( editorStore ).getEditedPostAttribute( 'status' ), - postStatusHasChanged: select( editorStore ).getPostEdits()?.status, - } ) ), - withDispatch( ( dispatch ) => { - const { togglePublishSidebar } = dispatch( editorStore ); - return { - togglePublishSidebar, - }; - } ) -)( PostPublishButtonOrToggle ); diff --git a/packages/editor/src/components/post-publish-button/test/post-publish-button-or-toggle.js b/packages/editor/src/components/post-publish-button/test/post-publish-button-or-toggle.js index 0794c3c8995a1f..a8fa8b72db9c7b 100644 --- a/packages/editor/src/components/post-publish-button/test/post-publish-button-or-toggle.js +++ b/packages/editor/src/components/post-publish-button/test/post-publish-button-or-toggle.js @@ -7,13 +7,15 @@ import { render, screen } from '@testing-library/react'; * WordPress dependencies */ import { useViewportMatch } from '@wordpress/compose'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ -import { PostPublishButtonOrToggle } from '../post-publish-button-or-toggle'; +import PostPublishButtonOrToggle from '../post-publish-button-or-toggle'; jest.mock( '@wordpress/compose/src/hooks/use-viewport-match' ); +jest.mock( '@wordpress/data/src/components/use-select', () => jest.fn() ); describe( 'PostPublishButtonOrToggle should render a', () => { afterEach( () => { @@ -21,23 +23,32 @@ describe( 'PostPublishButtonOrToggle should render a', () => { } ); it( 'button when the post is published (1)', () => { - render( <PostPublishButtonOrToggle isPublished /> ); + useSelect.mockImplementation( () => ( { + isPublished: true, + } ) ); + render( <PostPublishButtonOrToggle /> ); expect( screen.getByRole( 'button', { name: 'Submit for Review' } ) ).toBeVisible(); } ); it( 'button when the post is scheduled (2)', () => { - render( <PostPublishButtonOrToggle isScheduled isBeingScheduled /> ); + useSelect.mockImplementation( () => ( { + isScheduled: true, + isBeingScheduled: true, + } ) ); + render( <PostPublishButtonOrToggle /> ); expect( screen.getByRole( 'button', { name: 'Submit for Review' } ) ).toBeVisible(); } ); it( 'button when the post is pending and cannot be published but the viewport is >= medium (3)', () => { - render( - <PostPublishButtonOrToggle isPending hasPublishAction={ false } /> - ); + useSelect.mockImplementation( () => ( { + isPending: true, + hasPublishAction: false, + } ) ); + render( <PostPublishButtonOrToggle /> ); expect( screen.getByRole( 'button', { name: 'Submit for Review' } ) @@ -46,6 +57,9 @@ describe( 'PostPublishButtonOrToggle should render a', () => { it( 'toggle when post is not (1), (2), (3), the viewport is <= medium, and the publish sidebar is enabled', () => { useViewportMatch.mockReturnValue( true ); + useSelect.mockImplementation( () => ( { + isPublishSidebarEnabled: true, + } ) ); render( <PostPublishButtonOrToggle isPublishSidebarEnabled /> ); expect( screen.getByRole( 'button', { name: 'Publish' } ) @@ -53,9 +67,10 @@ describe( 'PostPublishButtonOrToggle should render a', () => { } ); it( 'button when post is not (1), (2), (3), the viewport is >= medium, and the publish sidebar is disabled', () => { - render( - <PostPublishButtonOrToggle isPublishSidebarEnabled={ false } /> - ); + useSelect.mockImplementation( () => ( { + isPublishSidebarEnabled: false, + } ) ); + render( <PostPublishButtonOrToggle /> ); expect( screen.getByRole( 'button', { name: 'Submit for Review' } ) ).toBeVisible(); From 52b5429f52096c5e080b3cc5a2ff696e61cb7616 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Fri, 29 Nov 2024 12:03:02 +0100 Subject: [PATCH 1772/1908] [mini] drag and drop: restore moving animation (#67417) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../components/use-moving-animation/index.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/use-moving-animation/index.js b/packages/block-editor/src/components/use-moving-animation/index.js index ef367c0f332101..b11710acd24334 100644 --- a/packages/block-editor/src/components/use-moving-animation/index.js +++ b/packages/block-editor/src/components/use-moving-animation/index.js @@ -74,8 +74,14 @@ function useMovingAnimation( { triggerAnimationOnChange, clientId } ) { const isSelected = isBlockSelected( clientId ); const adjustScrolling = isSelected || isFirstMultiSelectedBlock( clientId ); + const isDragging = isDraggingBlocks(); function preserveScrollPosition() { + // The user already scrolled when dragging blocks. + if ( isDragging ) { + return; + } + if ( adjustScrolling && prevRect ) { const blockRect = ref.current.getBoundingClientRect(); const diff = blockRect.top - prevRect.top; @@ -86,11 +92,6 @@ function useMovingAnimation( { triggerAnimationOnChange, clientId } ) { } } - // Neither animate nor scroll. - if ( isDraggingBlocks() ) { - return; - } - // We disable the animation if the user has a preference for reduced // motion, if the user is typing (insertion by Enter), or if the block // count exceeds the threshold (insertion caused all the blocks that @@ -113,6 +114,13 @@ function useMovingAnimation( { triggerAnimationOnChange, clientId } ) { isSelected || isBlockMultiSelected( clientId ) || isAncestorMultiSelected( clientId ); + + // The user already dragged the blocks to the new position, so don't + // animate the dragged blocks. + if ( isPartOfSelection && isDragging ) { + return; + } + // Make sure the other blocks move under the selected block(s). const zIndex = isPartOfSelection ? '1' : ''; From 9ec599804382de27b527866b54719929b7651511 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 29 Nov 2024 22:06:55 +0900 Subject: [PATCH 1773/1908] Fix color of disabled buttons in dark toolbar (#67348) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/block-editor/src/components/block-tools/style.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index 0ed9c138519d29..80fe4c420d1e1f 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -157,6 +157,11 @@ &:focus::before { box-shadow: inset 0 0 0 1px $gray-900, 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); } + + &:disabled, + &[aria-disabled="true"] { + color: $gray-700; + } } .block-editor-block-parent-selector .block-editor-block-parent-selector__button { From f189eab30fc68b71728e17b50a089b2aa42a2277 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Fri, 29 Nov 2024 23:02:17 +0900 Subject: [PATCH 1774/1908] BorderBoxControl: Reduce gap value when unlinked (#67049) * BorderBoxControl: Reduce input field width when unlinked * Update changelog * 108px * Reduce gap value * Fix changelog entry Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ .../border-box-control-split-controls/component.tsx | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 8fc7aff329b031..ce151116df5bfb 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -7,6 +7,10 @@ - `BoxControl`: Passive deprecate `onMouseOver`/`onMouseOut`. Pass to the `inputProps` prop instead ([#67332](https://github.com/WordPress/gutenberg/pull/67332)). - `BoxControl`: Deprecate 36px default size ([#66704](https://github.com/WordPress/gutenberg/pull/66704)). +### Enhancements + +- `BorderBoxControl`: Reduce gap value when unlinked ([#67049](https://github.com/WordPress/gutenberg/pull/67049)). + ### Experimental - `Menu`: throw when subcomponents are not rendered inside top level `Menu` ([#67411](https://github.com/WordPress/gutenberg/pull/67411)). diff --git a/packages/components/src/border-box-control/border-box-control-split-controls/component.tsx b/packages/components/src/border-box-control/border-box-control-split-controls/component.tsx index 0c887ab5f701c3..94e1728076b181 100644 --- a/packages/components/src/border-box-control/border-box-control-split-controls/component.tsx +++ b/packages/components/src/border-box-control/border-box-control-split-controls/component.tsx @@ -73,7 +73,7 @@ const BorderBoxControlSplitControls = ( const mergedRef = useMergeRefs( [ setPopoverAnchor, forwardedRef ] ); return ( - <Grid { ...otherProps } ref={ mergedRef } gap={ 4 }> + <Grid { ...otherProps } ref={ mergedRef } gap={ 3 }> <BorderBoxControlVisualizer value={ value } size={ size } /> <BorderControl className={ centeredClassName } From 3994f998665331196b88cc257c2d8080afe37a25 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Fri, 29 Nov 2024 23:48:46 +0900 Subject: [PATCH 1775/1908] FontFamilyControl: Restore margin bottom (#67424) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> --- .../block-editor/src/components/font-family/index.js | 9 +++++++++ .../block-editor/src/components/font-family/style.scss | 5 +++++ packages/block-editor/src/style.scss | 1 + 3 files changed, 15 insertions(+) create mode 100644 packages/block-editor/src/components/font-family/style.scss diff --git a/packages/block-editor/src/components/font-family/index.js b/packages/block-editor/src/components/font-family/index.js index 1e6c137daedb0f..045d4d5c73ed30 100644 --- a/packages/block-editor/src/components/font-family/index.js +++ b/packages/block-editor/src/components/font-family/index.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + /** * WordPress dependencies */ @@ -18,6 +23,7 @@ export default function FontFamilyControl( { value = '', onChange, fontFamilies, + className, ...props } ) { const [ blockLevelFontFamilies ] = useSettings( 'typography.fontFamilies' ); @@ -59,6 +65,9 @@ export default function FontFamilyControl( { value={ value } onChange={ ( { selectedItem } ) => onChange( selectedItem.key ) } options={ options } + className={ clsx( 'block-editor-font-family-control', className, { + 'is-next-has-no-margin-bottom': __nextHasNoMarginBottom, + } ) } { ...props } /> ); diff --git a/packages/block-editor/src/components/font-family/style.scss b/packages/block-editor/src/components/font-family/style.scss new file mode 100644 index 00000000000000..7ee181ebb79534 --- /dev/null +++ b/packages/block-editor/src/components/font-family/style.scss @@ -0,0 +1,5 @@ +.block-editor-font-family-control { + &:not(.is-next-has-no-margin-bottom) { + margin-bottom: $grid-unit-10; + } +} diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index 213498c797aee4..6b2ebf5cd841fd 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -28,6 +28,7 @@ @import "./components/date-format-picker/style.scss"; @import "./components/duotone-control/style.scss"; @import "./components/font-appearance-control/style.scss"; +@import "./components/font-family/style.scss"; @import "./components/global-styles/style.scss"; @import "./components/grid/style.scss"; @import "./components/height-control/style.scss"; From 2c88f6a1b674c78bbbea5dc41aac998970ef9c2e Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Fri, 29 Nov 2024 15:16:15 +0000 Subject: [PATCH 1776/1908] Fix: Caption with Link in Wide-Width and Full-Width Images Appears on two lines (#67392) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- packages/block-library/src/image/style.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/image/style.scss b/packages/block-library/src/image/style.scss index 1bb19bf29da691..a7fcb8f175e4e5 100644 --- a/packages/block-library/src/image/style.scss +++ b/packages/block-library/src/image/style.scss @@ -42,8 +42,8 @@ text-align: center; } - &.alignfull a, - &.alignwide a { + &.alignfull > a, + &.alignwide > a { width: 100%; } From edd6328b3ff9cefc5550878f90fae885f33c8b27 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Fri, 29 Nov 2024 20:52:27 +0530 Subject: [PATCH 1777/1908] UnitControl : Deprecate 36px default size (#66791) * Add the console warning for 36px size variation * Add the changelog for the deprecation * Update the unit test for the unitcontrol to use default 40px size * Use __shouldNotWarnDeprecated36pxSize to not throw redundant warning from parent component used * Add the missing prop for __next40pxDefaultSize on the index file and updated readme as well * Add changelog to unreleased section * Add __shouldNotWarnDeprecated36pxSize prop to supress console warning from child component * Update tools panel storybook and docs to use __next40pxDefaultSize for UnitControl * Updated the unit test to minimise the file changes * Revert changes on mobile FontSizePicker --------- Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/border-control/border-control/component.tsx | 2 ++ .../components/src/box-control/all-input-control.tsx | 1 + .../src/box-control/axial-input-controls.tsx | 1 + .../components/src/box-control/input-controls.tsx | 1 + packages/components/src/font-size-picker/index.tsx | 1 + .../src/tools-panel/stories/index.story.tsx | 12 ++++++++++++ .../components/src/tools-panel/tools-panel/README.md | 2 ++ .../src/tools-panel/tools-panel/component.tsx | 2 ++ packages/components/src/unit-control/README.md | 6 +++--- packages/components/src/unit-control/index.tsx | 11 ++++++++++- .../src/unit-control/stories/index.story.tsx | 1 + packages/components/src/unit-control/test/index.tsx | 6 +++++- packages/components/src/unit-control/types.ts | 7 +++++++ 14 files changed, 49 insertions(+), 5 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index ce151116df5bfb..7865993d4e995f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,7 @@ - `BoxControl`: Passive deprecate `onMouseOver`/`onMouseOut`. Pass to the `inputProps` prop instead ([#67332](https://github.com/WordPress/gutenberg/pull/67332)). - `BoxControl`: Deprecate 36px default size ([#66704](https://github.com/WordPress/gutenberg/pull/66704)). +- `UnitControl`: Deprecate 36px default size ([#66791](https://github.com/WordPress/gutenberg/pull/66791)). ### Enhancements diff --git a/packages/components/src/border-control/border-control/component.tsx b/packages/components/src/border-control/border-control/component.tsx index 2ba338c2bb30cb..f71599b274778d 100644 --- a/packages/components/src/border-control/border-control/component.tsx +++ b/packages/components/src/border-control/border-control/component.tsx @@ -75,6 +75,8 @@ const UnconnectedBorderControl = ( /> <HStack spacing={ 4 } className={ innerWrapperClassName }> <UnitControl + __next40pxDefaultSize={ __next40pxDefaultSize } + __shouldNotWarnDeprecated36pxSize prefix={ <Spacer marginRight={ 1 } marginBottom={ 0 }> <BorderControlDropdown diff --git a/packages/components/src/box-control/all-input-control.tsx b/packages/components/src/box-control/all-input-control.tsx index 057cf3c15d8c38..0cfaea21915f6d 100644 --- a/packages/components/src/box-control/all-input-control.tsx +++ b/packages/components/src/box-control/all-input-control.tsx @@ -74,6 +74,7 @@ export default function AllInputControl( { <> <StyledUnitControl { ...props } + __shouldNotWarnDeprecated36pxSize __next40pxDefaultSize={ __next40pxDefaultSize } className="component-box-control__unit-control" disableUnits={ isMixed } diff --git a/packages/components/src/box-control/axial-input-controls.tsx b/packages/components/src/box-control/axial-input-controls.tsx index 40b39840b464b5..f8cbc5635c9b55 100644 --- a/packages/components/src/box-control/axial-input-controls.tsx +++ b/packages/components/src/box-control/axial-input-controls.tsx @@ -106,6 +106,7 @@ export default function AxialInputControls( { <Tooltip placement="top-end" text={ LABELS[ side ] }> <StyledUnitControl { ...props } + __shouldNotWarnDeprecated36pxSize __next40pxDefaultSize={ __next40pxDefaultSize } className="component-box-control__unit-control" id={ inputId } diff --git a/packages/components/src/box-control/input-controls.tsx b/packages/components/src/box-control/input-controls.tsx index 1f005f6c6c01bd..8f4518d717dbed 100644 --- a/packages/components/src/box-control/input-controls.tsx +++ b/packages/components/src/box-control/input-controls.tsx @@ -108,6 +108,7 @@ export default function BoxInputControls( { <Tooltip placement="top-end" text={ LABELS[ side ] }> <StyledUnitControl { ...props } + __shouldNotWarnDeprecated36pxSize __next40pxDefaultSize={ __next40pxDefaultSize } className="component-box-control__unit-control" id={ inputId } diff --git a/packages/components/src/font-size-picker/index.tsx b/packages/components/src/font-size-picker/index.tsx index a71e60cd6719c8..a47812640f1a29 100644 --- a/packages/components/src/font-size-picker/index.tsx +++ b/packages/components/src/font-size-picker/index.tsx @@ -212,6 +212,7 @@ const UnforwardedFontSizePicker = ( <FlexItem isBlock> <UnitControl __next40pxDefaultSize={ __next40pxDefaultSize } + __shouldNotWarnDeprecated36pxSize label={ __( 'Custom' ) } labelPosition="top" hideLabelFromVision diff --git a/packages/components/src/tools-panel/stories/index.story.tsx b/packages/components/src/tools-panel/stories/index.story.tsx index 787585ac716b51..0fbdae794d838d 100644 --- a/packages/components/src/tools-panel/stories/index.story.tsx +++ b/packages/components/src/tools-panel/stories/index.story.tsx @@ -74,6 +74,7 @@ export const Default: StoryFn< typeof ToolsPanel > = ( { isShownByDefault > <UnitControl + __next40pxDefaultSize label="Width" value={ width } onChange={ ( next ) => setWidth( next ) } @@ -86,6 +87,7 @@ export const Default: StoryFn< typeof ToolsPanel > = ( { isShownByDefault > <UnitControl + __next40pxDefaultSize label="Height" value={ height } onChange={ ( next ) => setHeight( next ) } @@ -98,6 +100,7 @@ export const Default: StoryFn< typeof ToolsPanel > = ( { isShownByDefault > <UnitControl + __next40pxDefaultSize label="Minimum height" value={ minHeight } onChange={ ( next ) => setMinHeight( next ) } @@ -167,6 +170,7 @@ export const WithNonToolsPanelItems: StoryFn< typeof ToolsPanel > = ( { isShownByDefault > <UnitControl + __next40pxDefaultSize label="Width" value={ width } onChange={ ( next ) => setWidth( next ) } @@ -179,6 +183,7 @@ export const WithNonToolsPanelItems: StoryFn< typeof ToolsPanel > = ( { isShownByDefault > <UnitControl + __next40pxDefaultSize label="Height" value={ height } onChange={ ( next ) => setHeight( next ) } @@ -237,6 +242,7 @@ export const WithOptionalItemsPlusIcon: StoryFn< typeof ToolsPanel > = ( { } > <UnitControl + __next40pxDefaultSize label="Minimum width" value={ minWidth } onChange={ ( next ) => setMinWidth( next ) } @@ -249,6 +255,7 @@ export const WithOptionalItemsPlusIcon: StoryFn< typeof ToolsPanel > = ( { isShownByDefault={ false } > <UnitControl + __next40pxDefaultSize label="Width" value={ width } onChange={ ( next ) => setWidth( next ) } @@ -261,6 +268,7 @@ export const WithOptionalItemsPlusIcon: StoryFn< typeof ToolsPanel > = ( { isShownByDefault={ false } > <UnitControl + __next40pxDefaultSize label="Height" value={ height } onChange={ ( next ) => setHeight( next ) } @@ -341,6 +349,7 @@ export const WithSlotFillItems: StoryFn< typeof ToolsPanel > = ( { panelId={ panelId } > <UnitControl + __next40pxDefaultSize label="Injected Width" value={ width } onChange={ ( next ) => @@ -356,6 +365,7 @@ export const WithSlotFillItems: StoryFn< typeof ToolsPanel > = ( { panelId={ panelId } > <UnitControl + __next40pxDefaultSize label="Injected Height" value={ height } onChange={ ( next ) => @@ -441,6 +451,7 @@ export const WithConditionalDefaultControl: StoryFn< typeof ToolsPanel > = ( { isShownByDefault > <UnitControl + __next40pxDefaultSize label="Injected Height" value={ height } onChange={ ( next ) => @@ -541,6 +552,7 @@ export const WithConditionallyRenderedControl: StoryFn< isShownByDefault > <UnitControl + __next40pxDefaultSize label="Injected Height" value={ height } onChange={ ( next ) => diff --git a/packages/components/src/tools-panel/tools-panel/README.md b/packages/components/src/tools-panel/tools-panel/README.md index 1895f5ccc843ec..b5e6860e2bd072 100644 --- a/packages/components/src/tools-panel/tools-panel/README.md +++ b/packages/components/src/tools-panel/tools-panel/README.md @@ -101,6 +101,7 @@ export function DimensionPanel() { isShownByDefault > <UnitControl + __next40pxDefaultSize label={ __( 'Height' ) } onChange={ setHeight } value={ height } @@ -113,6 +114,7 @@ export function DimensionPanel() { isShownByDefault > <UnitControl + __next40pxDefaultSize label={ __( 'Width' ) } onChange={ setWidth } value={ width } diff --git a/packages/components/src/tools-panel/tools-panel/component.tsx b/packages/components/src/tools-panel/tools-panel/component.tsx index 4e01e39ffffb43..c094d593dd4c24 100644 --- a/packages/components/src/tools-panel/tools-panel/component.tsx +++ b/packages/components/src/tools-panel/tools-panel/component.tsx @@ -75,6 +75,7 @@ const UnconnectedToolsPanel = ( * onDeselect={ () => setHeight() } * > * <UnitControl + * __next40pxDefaultSize * label={ __( 'Height' ) } * onChange={ setHeight } * value={ height } @@ -86,6 +87,7 @@ const UnconnectedToolsPanel = ( * onDeselect={ () => setWidth() } * > * <UnitControl + * __next40pxDefaultSize * label={ __( 'Width' ) } * onChange={ setWidth } * value={ width } diff --git a/packages/components/src/unit-control/README.md b/packages/components/src/unit-control/README.md index dd54de80357d8e..65d9e4b74062dd 100644 --- a/packages/components/src/unit-control/README.md +++ b/packages/components/src/unit-control/README.md @@ -15,7 +15,7 @@ import { __experimentalUnitControl as UnitControl } from '@wordpress/components' const Example = () => { const [ value, setValue ] = useState( '10px' ); - return <UnitControl onChange={ setValue } value={ value } />; + return <UnitControl __next40pxDefaultSize onChange={ setValue } value={ value } />; }; ``` @@ -128,7 +128,7 @@ const Example = () => { ]; return ( - <UnitControl onChange={ setValue } value={ value } units={ units } /> + <UnitControl __next40pxDefaultSize onChange={ setValue } value={ value } units={ units } /> ); }; ``` @@ -143,7 +143,7 @@ For example, a `value` of `50%` will set the current unit to `%`. Example: ```jsx -<UnitControl value="50%" /> +<UnitControl __next40pxDefaultSize value="50%" /> ``` - Required: No diff --git a/packages/components/src/unit-control/index.tsx b/packages/components/src/unit-control/index.tsx index 2dd08cc155225f..9845c4eb04ef26 100644 --- a/packages/components/src/unit-control/index.tsx +++ b/packages/components/src/unit-control/index.tsx @@ -27,6 +27,7 @@ import { useControlledState } from '../utils/hooks'; import { escapeRegExp } from '../utils/strings'; import type { UnitControlProps, UnitControlOnChangeCallback } from './types'; import { useDeprecated36pxDefaultSizeProp } from '../utils/use-deprecated-props'; +import { maybeWarnDeprecated36pxSize } from '../utils/deprecated-36px-size'; function UnforwardedUnitControl( unitControlProps: WordPressComponentProps< @@ -55,9 +56,17 @@ function UnforwardedUnitControl( units: unitsProp = CSS_UNITS, value: valueProp, onFocus: onFocusProp, + __shouldNotWarnDeprecated36pxSize, ...props } = useDeprecated36pxDefaultSizeProp( unitControlProps ); + maybeWarnDeprecated36pxSize( { + componentName: 'UnitControl', + __next40pxDefaultSize: props.__next40pxDefaultSize, + size, + __shouldNotWarnDeprecated36pxSize, + } ); + if ( 'unit' in unitControlProps ) { deprecated( 'UnitControl unit prop', { since: '5.6', @@ -246,7 +255,7 @@ function UnforwardedUnitControl( * const Example = () => { * const [ value, setValue ] = useState( '10px' ); * - * return <UnitControl onChange={ setValue } value={ value } />; + * return <UnitControl __next40pxDefaultSize onChange={ setValue } value={ value } />; * }; * ``` */ diff --git a/packages/components/src/unit-control/stories/index.story.tsx b/packages/components/src/unit-control/stories/index.story.tsx index de8f476e26e5c7..87628c46441169 100644 --- a/packages/components/src/unit-control/stories/index.story.tsx +++ b/packages/components/src/unit-control/stories/index.story.tsx @@ -59,6 +59,7 @@ export const Default: StoryFn< typeof UnitControl > = DefaultTemplate.bind( ); Default.args = { label: 'Label', + __next40pxDefaultSize: true, }; /** diff --git a/packages/components/src/unit-control/test/index.tsx b/packages/components/src/unit-control/test/index.tsx index d91498d46478b3..ad98d57cae6405 100644 --- a/packages/components/src/unit-control/test/index.tsx +++ b/packages/components/src/unit-control/test/index.tsx @@ -12,9 +12,13 @@ import { useState } from '@wordpress/element'; /** * Internal dependencies */ -import UnitControl from '..'; +import _UnitControl from '..'; import { CSS_UNITS, parseQuantityAndUnitFromRawValue } from '../utils'; +const UnitControl = ( props: React.ComponentProps< typeof _UnitControl > ) => ( + <_UnitControl __next40pxDefaultSize { ...props } /> +); + const getInput = ( { isInputTypeText = false, }: { diff --git a/packages/components/src/unit-control/types.ts b/packages/components/src/unit-control/types.ts index 9164502668a2b0..891945b422862a 100644 --- a/packages/components/src/unit-control/types.ts +++ b/packages/components/src/unit-control/types.ts @@ -107,4 +107,11 @@ export type UnitControlProps = Pick< InputControlProps, 'size' > & * Callback when either the quantity or the unit inputs gains focus. */ onFocus?: FocusEventHandler< HTMLInputElement | HTMLSelectElement >; + /** + * Do not throw a warning for the deprecated 36px default size. + * For internal components of other components that already throw the warning. + * + * @ignore + */ + __shouldNotWarnDeprecated36pxSize?: boolean; }; From 11262acadc190ca5715424728cafb1939d17483e Mon Sep 17 00:00:00 2001 From: Raj Patel <71687258+imrraaj@users.noreply.github.com> Date: Fri, 29 Nov 2024 21:27:08 +0530 Subject: [PATCH 1778/1908] Pullquote block having design issue when text-decoration is choosen strikethrough (#66707) Co-authored-by: imrraaj <imrraaj@git.wordpress.org> Co-authored-by: NidhiDhandhukiya74 <nidhidhandhukiya@git.wordpress.org> Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> --- packages/block-library/src/pullquote/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/pullquote/style.scss b/packages/block-library/src/pullquote/style.scss index b9e28b7cdcfaa6..ff5fe6068dfac3 100644 --- a/packages/block-library/src/pullquote/style.scss +++ b/packages/block-library/src/pullquote/style.scss @@ -72,4 +72,5 @@ .wp-block-pullquote cite { color: inherit; + display: block; } From 9ffbd9c215b2b43e527355d83b8d3f313b68582f Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Fri, 29 Nov 2024 19:19:13 +0000 Subject: [PATCH 1779/1908] Block editor: try direct drag (outside text editable) (#67305) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> --- .../components/block-draggable/content.scss | 16 ++- .../src/components/block-list/block.js | 1 + .../src/components/block-list/content.scss | 6 + .../block-list/use-block-props/index.js | 7 + .../use-firefox-draggable-compatibility.js | 25 ++++ .../use-selected-block-event-handlers.js | 120 ++++++++++++++++-- .../src/components/iframe/content.scss | 4 + .../src/components/rich-text/index.js | 5 + .../components/use-block-drop-zone/index.js | 19 ++- .../writing-flow/use-drag-selection.js | 11 ++ packages/components/CHANGELOG.md | 4 + .../components/src/resizable-box/index.tsx | 10 ++ .../components/src/resizable-box/style.scss | 8 ++ test/e2e/specs/editor/blocks/spacer.spec.js | 4 +- .../block-bindings/custom-sources.spec.js | 10 +- .../editor/various/draggable-blocks.spec.js | 100 ++++++++++----- 16 files changed, 300 insertions(+), 50 deletions(-) create mode 100644 packages/block-editor/src/components/block-list/use-block-props/use-firefox-draggable-compatibility.js diff --git a/packages/block-editor/src/components/block-draggable/content.scss b/packages/block-editor/src/components/block-draggable/content.scss index 102230168e2133..25a0f5c2565951 100644 --- a/packages/block-editor/src/components/block-draggable/content.scss +++ b/packages/block-editor/src/components/block-draggable/content.scss @@ -1,13 +1,12 @@ // This creates a "slot" where the block you're dragging appeared. // We use !important as one of the rules are meant to be overridden. .block-editor-block-list__layout .is-dragging { - background-color: currentColor !important; - opacity: 0.05 !important; + opacity: 0.1 !important; border-radius: $radius-small !important; - // Disabling pointer events during the drag event is necessary, - // lest the block might affect your drag operation. - pointer-events: none !important; + iframe { + pointer-events: none; + } // Hide the multi selection indicator when dragging. &::selection { @@ -18,3 +17,10 @@ content: none !important; } } + +// Images are draggable by default, so disable drag for them if not explicitly +// set. This is done so that the block can capture the drag event instead. +.wp-block img:not([draggable]), +.wp-block svg:not([draggable]) { + pointer-events: none; +} diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 6d4655189d9723..0e3a5be5150ded 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -797,6 +797,7 @@ function BlockListBlockProvider( props ) { mayDisplayParentControls, originalBlockClientId, themeSupportsLayout, + canMove, }; // Here we separate between the props passed to BlockListBlock and any other diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index 3d3b8517ca09c3..cd517fced833ef 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -427,3 +427,9 @@ _::-webkit-full-page-media, _:future, :root [data-has-multi-selection="true"] .b // Additional -1px is required to avoid sub pixel rounding errors allowing background to show. margin: 0 calc(-1 * var(--wp--style--root--padding-right) - 1px) 0 calc(-1 * var(--wp--style--root--padding-left) - 1px) !important; } + +// This only works in Firefox, Chrome and Safari don't accept a custom cursor +// during drag. +.is-dragging { + cursor: grabbing; +} diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index 25b9a21f0d2867..4696149dc38751 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -30,6 +30,7 @@ import { useIntersectionObserver } from './use-intersection-observer'; import { useScrollIntoView } from './use-scroll-into-view'; import { useFlashEditableBlocks } from '../../use-flash-editable-blocks'; import { canBindBlock } from '../../../hooks/use-bindings-attributes'; +import { useFirefoxDraggableCompatibility } from './use-firefox-draggable-compatibility'; /** * This hook is used to lightly mark an element as a block element. The element @@ -100,11 +101,15 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { isTemporarilyEditingAsBlocks, defaultClassName, isSectionBlock, + canMove, } = useContext( PrivateBlockContext ); + const canDrag = canMove && ! hasChildSelected; + // translators: %s: Type of block (i.e. Text, Image etc) const blockLabel = sprintf( __( 'Block: %s' ), blockTitle ); const htmlSuffix = mode === 'html' && ! __unstableIsHtml ? '-visual' : ''; + const ffDragRef = useFirefoxDraggableCompatibility(); const mergedRefs = useMergeRefs( [ props.ref, useFocusFirstElement( { clientId, initialPosition } ), @@ -120,6 +125,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { isEnabled: isSectionBlock, } ), useScrollIntoView( { isSelected } ), + canDrag ? ffDragRef : undefined, ] ); const blockEditContext = useBlockEditContext(); @@ -152,6 +158,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { return { tabIndex: blockEditingMode === 'disabled' ? -1 : 0, + draggable: canDrag ? true : undefined, ...wrapperProps, ...props, ref: mergedRefs, diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-firefox-draggable-compatibility.js b/packages/block-editor/src/components/block-list/use-block-props/use-firefox-draggable-compatibility.js new file mode 100644 index 00000000000000..5fa07fb9be6040 --- /dev/null +++ b/packages/block-editor/src/components/block-list/use-block-props/use-firefox-draggable-compatibility.js @@ -0,0 +1,25 @@ +/** + * WordPress dependencies + */ +import { useRefEffect } from '@wordpress/compose'; + +/** + * In Firefox, the `draggable` and `contenteditable` attributes don't play well + * together. When `contenteditable` is within a `draggable` element, selection + * doesn't get set in the right place. The only solution is to temporarily + * remove the `draggable` attribute clicking inside `contenteditable` elements. + * + * @return {Function} Cleanup function. + */ +export function useFirefoxDraggableCompatibility() { + return useRefEffect( ( node ) => { + function onDown( event ) { + node.draggable = ! event.target.isContentEditable; + } + const { ownerDocument } = node; + ownerDocument.addEventListener( 'pointerdown', onDown ); + return () => { + ownerDocument.removeEventListener( 'pointerdown', onDown ); + }; + }, [] ); +} diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-selected-block-event-handlers.js b/packages/block-editor/src/components/block-list/use-block-props/use-selected-block-event-handlers.js index 68f8a671adbe9a..0a13ce6700b8e8 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-selected-block-event-handlers.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-selected-block-event-handlers.js @@ -5,12 +5,15 @@ import { isTextField } from '@wordpress/dom'; import { ENTER, BACKSPACE, DELETE } from '@wordpress/keycodes'; import { useSelect, useDispatch } from '@wordpress/data'; import { useRefEffect } from '@wordpress/compose'; +import { createRoot } from '@wordpress/element'; +import { store as blocksStore } from '@wordpress/blocks'; /** * Internal dependencies */ import { store as blockEditorStore } from '../../../store'; import { unlock } from '../../../lock-unlock'; +import BlockDraggableChip from '../../../components/block-draggable/draggable-chip'; /** * Adds block behaviour: @@ -21,12 +24,16 @@ import { unlock } from '../../../lock-unlock'; * @param {string} clientId Block client ID. */ export function useEventHandlers( { clientId, isSelected } ) { - const { getBlockRootClientId, getBlockIndex, isZoomOut } = unlock( - useSelect( blockEditorStore ) - ); - const { insertAfterBlock, removeBlock, resetZoomLevel } = unlock( - useDispatch( blockEditorStore ) - ); + const { getBlockType } = useSelect( blocksStore ); + const { getBlockRootClientId, isZoomOut, hasMultiSelection, getBlockName } = + unlock( useSelect( blockEditorStore ) ); + const { + insertAfterBlock, + removeBlock, + resetZoomLevel, + startDraggingBlocks, + stopDraggingBlocks, + } = unlock( useDispatch( blockEditorStore ) ); return useRefEffect( ( node ) => { @@ -76,7 +83,102 @@ export function useEventHandlers( { clientId, isSelected } ) { * @param {DragEvent} event Drag event. */ function onDragStart( event ) { - event.preventDefault(); + if ( + node !== event.target || + node.isContentEditable || + node.ownerDocument.activeElement !== node || + hasMultiSelection() + ) { + event.preventDefault(); + return; + } + const data = JSON.stringify( { + type: 'block', + srcClientIds: [ clientId ], + srcRootClientId: getBlockRootClientId( clientId ), + } ); + event.dataTransfer.effectAllowed = 'move'; // remove "+" cursor + event.dataTransfer.clearData(); + event.dataTransfer.setData( 'wp-blocks', data ); + const { ownerDocument } = node; + const { defaultView } = ownerDocument; + const selection = defaultView.getSelection(); + selection.removeAllRanges(); + + const domNode = document.createElement( 'div' ); + const root = createRoot( domNode ); + root.render( + <BlockDraggableChip + icon={ getBlockType( getBlockName( clientId ) ).icon } + /> + ); + document.body.appendChild( domNode ); + domNode.style.position = 'absolute'; + domNode.style.top = '0'; + domNode.style.left = '0'; + domNode.style.zIndex = '1000'; + domNode.style.pointerEvents = 'none'; + + // Setting the drag chip as the drag image actually works, but + // the behaviour is slightly different in every browser. In + // Safari, it animates, in Firefox it's slightly transparent... + // So we set a fake drag image and have to reposition it + // ourselves. + const dragElement = ownerDocument.createElement( 'div' ); + // Chrome will show a globe icon if the drag element does not + // have dimensions. + dragElement.style.width = '1px'; + dragElement.style.height = '1px'; + dragElement.style.position = 'fixed'; + dragElement.style.visibility = 'hidden'; + ownerDocument.body.appendChild( dragElement ); + event.dataTransfer.setDragImage( dragElement, 0, 0 ); + + let offset = { x: 0, y: 0 }; + + if ( document !== ownerDocument ) { + const frame = defaultView.frameElement; + if ( frame ) { + const rect = frame.getBoundingClientRect(); + offset = { x: rect.left, y: rect.top }; + } + } + + // chip handle offset + offset.x -= 58; + + function over( e ) { + domNode.style.transform = `translate( ${ + e.clientX + offset.x + }px, ${ e.clientY + offset.y }px )`; + } + + over( event ); + + function end() { + ownerDocument.removeEventListener( 'dragover', over ); + ownerDocument.removeEventListener( 'dragend', end ); + domNode.remove(); + dragElement.remove(); + stopDraggingBlocks(); + document.body.classList.remove( + 'is-dragging-components-draggable' + ); + ownerDocument.documentElement.classList.remove( + 'is-dragging' + ); + } + + ownerDocument.addEventListener( 'dragover', over ); + ownerDocument.addEventListener( 'dragend', end ); + ownerDocument.addEventListener( 'drop', end ); + + startDraggingBlocks( [ clientId ] ); + // Important because it hides the block toolbar. + document.body.classList.add( + 'is-dragging-components-draggable' + ); + ownerDocument.documentElement.classList.add( 'is-dragging' ); } node.addEventListener( 'keydown', onKeyDown ); @@ -91,11 +193,13 @@ export function useEventHandlers( { clientId, isSelected } ) { clientId, isSelected, getBlockRootClientId, - getBlockIndex, insertAfterBlock, removeBlock, isZoomOut, resetZoomLevel, + hasMultiSelection, + startDraggingBlocks, + stopDraggingBlocks, ] ); } diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss index 9b02716671de77..74efb63c0e077b 100644 --- a/packages/block-editor/src/components/iframe/content.scss +++ b/packages/block-editor/src/components/iframe/content.scss @@ -60,5 +60,9 @@ } } } + + .wp-block[draggable] { + cursor: grab; + } } } diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 8f179d08570ad1..bc8eca6ea94d05 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -431,6 +431,11 @@ export function RichTextWrapper( aria-multiline={ ! disableLineBreaks } aria-readonly={ shouldDisableEditing } { ...props } + // Unset draggable (coming from block props) for contentEditable + // elements because it will interfere with multi block selection + // when the contentEditable and draggable elements are the same + // element. + draggable={ undefined } aria-label={ bindingsLabel || props[ 'aria-label' ] || placeholder } 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 2a3e4948d40b3b..221e5ab74ebb2e 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 @@ -332,6 +332,7 @@ export default function useBlockDropZone( { isGroupable, isZoomOut, getSectionRootClientId, + getBlockParents, } = unlock( useSelect( blockEditorStore ) ); const { showInsertionPoint, @@ -358,13 +359,29 @@ export default function useBlockDropZone( { // So, ensure that the drag state is set when the user drags over a drop zone. startDragging(); } + + const draggedBlockClientIds = getDraggedBlockClientIds(); + const targetParents = [ + targetRootClientId, + ...getBlockParents( targetRootClientId, true ), + ]; + + // Check if the target is within any of the dragged blocks. + const isTargetWithinDraggedBlocks = draggedBlockClientIds.some( + ( clientId ) => targetParents.includes( clientId ) + ); + + if ( isTargetWithinDraggedBlocks ) { + return; + } + const allowedBlocks = getAllowedBlocks( targetRootClientId ); const targetBlockName = getBlockNamesByClientId( [ targetRootClientId, ] )[ 0 ]; const draggedBlockNames = getBlockNamesByClientId( - getDraggedBlockClientIds() + draggedBlockClientIds ); const isBlockDroppingAllowed = isDropTargetValid( getBlockType, diff --git a/packages/block-editor/src/components/writing-flow/use-drag-selection.js b/packages/block-editor/src/components/writing-flow/use-drag-selection.js index 1569c45a7c6769..ea4c09b3dc9577 100644 --- a/packages/block-editor/src/components/writing-flow/use-drag-selection.js +++ b/packages/block-editor/src/components/writing-flow/use-drag-selection.js @@ -80,7 +80,17 @@ export default function useDragSelection() { } ); } + let lastMouseDownTarget; + + function onMouseDown( { target } ) { + lastMouseDownTarget = target; + } + function onMouseLeave( { buttons, target, relatedTarget } ) { + if ( ! target.contains( lastMouseDownTarget ) ) { + return; + } + // If we're moving into a child element, ignore. We're tracking // the mouse leaving the element to a parent, no a child. if ( target.contains( relatedTarget ) ) { @@ -141,6 +151,7 @@ export default function useDragSelection() { } node.addEventListener( 'mouseout', onMouseLeave ); + node.addEventListener( 'mousedown', onMouseDown ); return () => { node.removeEventListener( 'mouseout', onMouseLeave ); diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 7865993d4e995f..27854472274160 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -21,6 +21,10 @@ - Upgraded `@ariakit/react` (v0.4.13) and `@ariakit/test` (v0.4.5) ([#65907](https://github.com/WordPress/gutenberg/pull/65907)). - Upgraded `@ariakit/react` (v0.4.15) and `@ariakit/test` (v0.4.7) ([#67404](https://github.com/WordPress/gutenberg/pull/67404)). +### Bug Fixes + +- `ResizableBox`: Make drag handles focusable ([#67305](https://github.com/WordPress/gutenberg/pull/67305)). + ## 28.13.0 (2024-11-27) ### Deprecations diff --git a/packages/components/src/resizable-box/index.tsx b/packages/components/src/resizable-box/index.tsx index 1b05270ea0bf20..3bf3d36aa0d5c3 100644 --- a/packages/components/src/resizable-box/index.tsx +++ b/packages/components/src/resizable-box/index.tsx @@ -112,6 +112,16 @@ function UnforwardedResizableBox( showHandle && 'has-show-handle', className ) } + // Add a focusable element within the drag handle. Unfortunately, + // `re-resizable` does not make them properly focusable by default, + // causing focus to move the the block wrapper which triggers block + // drag. + handleComponent={ Object.fromEntries( + Object.keys( HANDLE_CLASSES ).map( ( key ) => [ + key, + <div key={ key } tabIndex={ -1 } />, + ] ) + ) } handleClasses={ HANDLE_CLASSES } handleStyles={ HANDLE_STYLES } ref={ ref } diff --git a/packages/components/src/resizable-box/style.scss b/packages/components/src/resizable-box/style.scss index 3c9efd27136460..4db3d27b5fab6b 100644 --- a/packages/components/src/resizable-box/style.scss +++ b/packages/components/src/resizable-box/style.scss @@ -15,6 +15,14 @@ $resize-handler-container-size: $resize-handler-size + ($grid-unit-05 * 2); // M .components-resizable-box__container.has-show-handle & { display: block; } + + > div { + position: relative; + width: 100%; + height: 100%; + z-index: z-index(".components-resizable-box__handle"); + outline: none; + } } // Make the image inside the resize to get the full width diff --git a/test/e2e/specs/editor/blocks/spacer.spec.js b/test/e2e/specs/editor/blocks/spacer.spec.js index f089402514623c..da262c9b4e26d9 100644 --- a/test/e2e/specs/editor/blocks/spacer.spec.js +++ b/test/e2e/specs/editor/blocks/spacer.spec.js @@ -43,7 +43,9 @@ test.describe( 'Spacer', () => { expect( await editor.getEditedPostContent() ).toMatchSnapshot(); await expect( - editor.canvas.locator( 'role=document[name="Block: Spacer"i]' ) + editor.canvas.locator( + 'role=document[name="Block: Spacer"i] >> css=.components-resizable-box__handle >> [tabindex]' + ) ).toBeFocused(); } ); } ); diff --git a/test/e2e/specs/editor/various/block-bindings/custom-sources.spec.js b/test/e2e/specs/editor/various/block-bindings/custom-sources.spec.js index d6563ce9cb5f5f..033a69e2d61707 100644 --- a/test/e2e/specs/editor/various/block-bindings/custom-sources.spec.js +++ b/test/e2e/specs/editor/various/block-bindings/custom-sources.spec.js @@ -168,7 +168,10 @@ test.describe( 'Registered sources', () => { name: 'Block: Image', } ) .locator( 'img' ); - await imageBlockImg.click(); + // Playwright will complain that the pointer events are captured by + // the parent, but that's fine. + // eslint-disable-next-line playwright/no-force-option + await imageBlockImg.click( { force: true } ); // Image src is the custom field value. await expect( imageBlockImg ).toHaveAttribute( @@ -735,7 +738,10 @@ test.describe( 'Registered sources', () => { name: 'Block: Image', } ) .locator( 'img' ); - await imageBlockImg.click(); + // Playwright will complain that the pointer events are captured by + // the parent, but that's fine. + // eslint-disable-next-line playwright/no-force-option + await imageBlockImg.click( { force: true } ); // Edit the custom field value in the alt textarea. const altInputArea = page diff --git a/test/e2e/specs/editor/various/draggable-blocks.spec.js b/test/e2e/specs/editor/various/draggable-blocks.spec.js index e08030191dd60b..704817f4a2c38a 100644 --- a/test/e2e/specs/editor/various/draggable-blocks.spec.js +++ b/test/e2e/specs/editor/various/draggable-blocks.spec.js @@ -18,6 +18,14 @@ test.use( { }, } ); +async function dragTo( page, x, y ) { + // Call the move function twice to make sure the `dragOver` event is sent. + // @see https://github.com/microsoft/playwright/issues/17153 + for ( let i = 0; i < 2; i += 1 ) { + await page.mouse.move( x, y ); + } +} + test.describe( 'Draggable block', () => { test.beforeEach( async ( { admin } ) => { await admin.createNewPost(); @@ -60,14 +68,7 @@ test.describe( 'Draggable block', () => { 'role=document[name="Block: Paragraph"i] >> text=1' ); const firstParagraphBound = await firstParagraph.boundingBox(); - // Call the move function twice to make sure the `dragOver` event is sent. - // @see https://github.com/microsoft/playwright/issues/17153 - for ( let i = 0; i < 2; i += 1 ) { - await page.mouse.move( - firstParagraphBound.x, - firstParagraphBound.y - ); - } + await dragTo( page, firstParagraphBound.x, firstParagraphBound.y ); await expect( page.locator( 'data-testid=block-draggable-chip >> visible=true' ) @@ -132,15 +133,11 @@ test.describe( 'Draggable block', () => { 'role=document[name="Block: Paragraph"i] >> text=2' ); const secondParagraphBound = await secondParagraph.boundingBox(); - // Call the move function twice to make sure the `dragOver` event is sent. - // @see https://github.com/microsoft/playwright/issues/17153 - // Make sure mouse is > 30px within the block for bottom drop indicator to appear. - for ( let i = 0; i < 2; i += 1 ) { - await page.mouse.move( - secondParagraphBound.x + 32, - secondParagraphBound.y + secondParagraphBound.height * 0.75 - ); - } + await dragTo( + page, + secondParagraphBound.x + 32, + secondParagraphBound.y + secondParagraphBound.height * 0.75 + ); await expect( page.locator( 'data-testid=block-draggable-chip >> visible=true' ) @@ -216,14 +213,11 @@ test.describe( 'Draggable block', () => { 'role=document[name="Block: Paragraph"i] >> text=1' ); const firstParagraphBound = await firstParagraph.boundingBox(); - // Call the move function twice to make sure the `dragOver` event is sent. - // @see https://github.com/microsoft/playwright/issues/17153 - for ( let i = 0; i < 2; i += 1 ) { - await page.mouse.move( - firstParagraphBound.x + firstParagraphBound.width * 0.25, - firstParagraphBound.y - ); - } + await dragTo( + page, + firstParagraphBound.x + firstParagraphBound.width * 0.25, + firstParagraphBound.y + ); await expect( page.locator( 'data-testid=block-draggable-chip >> visible=true' ) @@ -297,14 +291,11 @@ test.describe( 'Draggable block', () => { 'role=document[name="Block: Paragraph"i] >> text=2' ); const secondParagraphBound = await secondParagraph.boundingBox(); - // Call the move function twice to make sure the `dragOver` event is sent. - // @see https://github.com/microsoft/playwright/issues/17153 - for ( let i = 0; i < 2; i += 1 ) { - await page.mouse.move( - secondParagraphBound.x + secondParagraphBound.width * 0.75, - secondParagraphBound.y - ); - } + await dragTo( + page, + secondParagraphBound.x + secondParagraphBound.width * 0.75, + secondParagraphBound.y + ); await expect( page.locator( 'data-testid=block-draggable-chip >> visible=true' ) @@ -465,4 +456,47 @@ test.describe( 'Draggable block', () => { ] ); } } ); + + test( 'can directly drag an image', async ( { page, editor } ) => { + await editor.insertBlock( { name: 'core/image' } ); + await editor.insertBlock( { + name: 'core/group', + attributes: { layout: { type: 'constrained' } }, + innerBlocks: [ { name: 'core/paragraph' } ], + } ); + + const imageBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Image', + } ); + + const groupBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Group', + } ); + + await imageBlock.hover(); + await page.mouse.down(); + const groupBlockBox = await groupBlock.boundingBox(); + await dragTo( + page, + groupBlockBox.x + groupBlockBox.width * 0.5, + groupBlockBox.y + groupBlockBox.height * 0.5 + ); + await page.mouse.up(); + + await expect.poll( editor.getBlocks ).toMatchObject( [ + { + name: 'core/group', + attributes: { + tagName: 'div', + layout: { type: 'constrained' }, + }, + innerBlocks: [ + { + name: 'core/image', + attributes: { alt: '', caption: '' }, + }, + ], + }, + ] ); + } ); } ); From 9defe9f7b6f7147756d1dba26dc0a8f8c07052d0 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Sat, 30 Nov 2024 08:24:55 +1100 Subject: [PATCH 1780/1908] Fix misc type compilation errors in editor and block editor packages (#67410) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + packages/components/src/index.ts | 1 + packages/editor/README.md | 7 ++++--- packages/editor/src/components/post-trash/check.js | 6 +++--- packages/editor/src/components/post-url/index.js | 3 ++- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 27854472274160..c9295e7ef861e0 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -20,6 +20,7 @@ - Upgraded `@ariakit/react` (v0.4.13) and `@ariakit/test` (v0.4.5) ([#65907](https://github.com/WordPress/gutenberg/pull/65907)). - Upgraded `@ariakit/react` (v0.4.15) and `@ariakit/test` (v0.4.7) ([#67404](https://github.com/WordPress/gutenberg/pull/67404)). +- Exported the `WPCompleter` type as it was being used in block-editor/autocompleters ([#67410](https://github.com/WordPress/gutenberg/pull/67410)). ### Bug Fixes diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index e82d6da70279e8..0558584fe5418c 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -108,6 +108,7 @@ export { Heading as __experimentalHeading } from './heading'; export { HStack as __experimentalHStack } from './h-stack'; export { default as Icon } from './icon'; export type { IconType } from './icon'; +export type { WPCompleter } from './autocomplete/types.ts'; export { default as IconButton } from './button/deprecated'; export { ItemGroup as __experimentalItemGroup, diff --git a/packages/editor/README.md b/packages/editor/README.md index 36126cb8eaee3f..8b48d773acb268 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -1462,11 +1462,11 @@ Wrapper component that renders its children only if the post can trashed. _Parameters_ - _props_ `Object`: - The component props. -- _props.children_ `React.ReactEl`: - The child components to render. +- _props.children_ `React.ReactNode`: - The child components to render. _Returns_ -- `React.ReactElement`: The rendered child components or null if the post can not trashed. +- `React.ReactNode`: The rendered child components or null if the post can not trashed. ### PostTypeSupportCheck @@ -1494,7 +1494,8 @@ _Usage_ _Parameters_ -- _onClose_ `Function`: Callback function to be executed when the popover is closed. +- _props_ `{ onClose: () => void }`: The props for the component. +- _props.onClose_ `() => void`: Callback function to be executed when the popover is closed. _Returns_ diff --git a/packages/editor/src/components/post-trash/check.js b/packages/editor/src/components/post-trash/check.js index 893d46ef9a0867..d4a9139bfee057 100644 --- a/packages/editor/src/components/post-trash/check.js +++ b/packages/editor/src/components/post-trash/check.js @@ -13,10 +13,10 @@ import { GLOBAL_POST_TYPES } from '../../store/constants'; /** * Wrapper component that renders its children only if the post can trashed. * - * @param {Object} props - The component props. - * @param {React.ReactEl} props.children - The child components to render. + * @param {Object} props - The component props. + * @param {React.ReactNode} props.children - The child components to render. * - * @return {React.ReactElement} The rendered child components or null if the post can not trashed. + * @return {React.ReactNode} The rendered child components or null if the post can not trashed. */ export default function PostTrashCheck( { children } ) { const { canTrashPost } = useSelect( ( select ) => { diff --git a/packages/editor/src/components/post-url/index.js b/packages/editor/src/components/post-url/index.js index c72ca5825f6fe6..f55ac973be50e6 100644 --- a/packages/editor/src/components/post-url/index.js +++ b/packages/editor/src/components/post-url/index.js @@ -32,7 +32,8 @@ import { store as editorStore } from '../../store'; * <PostURL /> * ``` * - * @param {Function} onClose Callback function to be executed when the popover is closed. + * @param {{ onClose: () => void }} props The props for the component. + * @param {() => void} props.onClose Callback function to be executed when the popover is closed. * * @return {React.ReactNode} The rendered PostURL component. */ From 961000076e74a6eea419d79ff8e16ae54a73463b Mon Sep 17 00:00:00 2001 From: Manzoor Wani <manzoorwani.jk@gmail.com> Date: Fri, 29 Nov 2024 23:55:22 -0800 Subject: [PATCH 1781/1908] Add types for shortcode package (#67416) * Add types for shortcode package * Remove WP Prefix * Update CHANGELOG.md Co-authored-by: manzoorwanijk <manzoorwanijk@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- packages/shortcode/CHANGELOG.md | 4 + packages/shortcode/README.md | 18 ++- packages/shortcode/package.json | 1 + packages/shortcode/src/index.js | 51 ++------ packages/shortcode/src/types.ts | 210 +++++++++++++++++++++++++++++++ packages/shortcode/tsconfig.json | 11 ++ tsconfig.json | 1 + 7 files changed, 245 insertions(+), 51 deletions(-) create mode 100644 packages/shortcode/src/types.ts create mode 100644 packages/shortcode/tsconfig.json diff --git a/packages/shortcode/CHANGELOG.md b/packages/shortcode/CHANGELOG.md index 8ee4e9aa3168d1..2e461f1bc85c1b 100644 --- a/packages/shortcode/CHANGELOG.md +++ b/packages/shortcode/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## Enhancements + +- The package now has built-in TypeScript definitions 🎉 ([#67416](https://github.com/WordPress/gutenberg/pull/67416)) + ## 4.13.0 (2024-11-27) ## 4.12.0 (2024-11-16) diff --git a/packages/shortcode/README.md b/packages/shortcode/README.md index a1a016e75e755c..b6042ab284fe42 100644 --- a/packages/shortcode/README.md +++ b/packages/shortcode/README.md @@ -32,7 +32,7 @@ _Parameters_ _Returns_ -- `WPShortcodeAttrs`: Parsed shortcode attributes. +- `import('./types').ShortcodeAttrs`: Parsed shortcode attributes. ### default @@ -40,13 +40,9 @@ Creates a shortcode instance. To access a raw representation of a shortcode, pass an `options` object, containing a `tag` string, a string or object of `attrs`, a string indicating the `type` of the shortcode ('single', 'self-closing', or 'closed'), and a `content` string. -_Parameters_ - -- _options_ `Object`: Options as described. - -_Returns_ +_Type_ -- `WPShortcode`: Shortcode instance. +- `import('./types').shortcode`Shortcode instance. ### fromMatch @@ -56,11 +52,11 @@ Accepts a `match` object from calling `regexp.exec()` on a `RegExp` generated by _Parameters_ -- _match_ `Array`: Match array. +- _match_ `import('./types').Match`: Match array. _Returns_ -- `WPShortcode`: Shortcode instance. +- `InstanceType<import('./types').shortcode>`: Shortcode instance. ### next @@ -74,7 +70,7 @@ _Parameters_ _Returns_ -- `WPShortcodeMatch | undefined`: Matched information. +- `import('./types').ShortcodeMatch | undefined`: Matched information. ### regexp @@ -108,7 +104,7 @@ _Parameters_ - _tag_ `string`: Shortcode tag. - _text_ `string`: Text to search. -- _callback_ `Function`: Function to process the match and return replacement string. +- _callback_ `import('./types').ReplaceCallback`: Function to process the match and return replacement string. _Returns_ diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index f87fe06d9bb421..c5495364a03c45 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -26,6 +26,7 @@ "module": "build-module/index.js", "react-native": "src/index", "wpScript": true, + "types": "build-types", "dependencies": { "@babel/runtime": "7.25.7", "memize": "^2.0.1" diff --git a/packages/shortcode/src/index.js b/packages/shortcode/src/index.js index 04e69c272378b3..4d99086033e957 100644 --- a/packages/shortcode/src/index.js +++ b/packages/shortcode/src/index.js @@ -3,34 +3,7 @@ */ import memize from 'memize'; -/** - * Shortcode attributes object. - * - * @typedef {Object} WPShortcodeAttrs - * - * @property {Object} named Object with named attributes. - * @property {Array} numeric Array with numeric attributes. - */ - -/** - * Shortcode object. - * - * @typedef {Object} WPShortcode - * - * @property {string} tag Shortcode tag. - * @property {WPShortcodeAttrs} attrs Shortcode attributes. - * @property {string} content Shortcode content. - * @property {string} type Shortcode type: `self-closing`, - * `closed`, or `single`. - */ - -/** - * @typedef {Object} WPShortcodeMatch - * - * @property {number} index Index the shortcode is found at. - * @property {string} content Matched content. - * @property {WPShortcode} shortcode Shortcode instance of the match. - */ +export * from './types'; /** * Find the next matching shortcode. @@ -39,7 +12,7 @@ import memize from 'memize'; * @param {string} text Text to search. * @param {number} index Index to start search from. * - * @return {WPShortcodeMatch | undefined} Matched information. + * @return {import('./types').ShortcodeMatch | undefined} Matched information. */ export function next( tag, text, index = 0 ) { const re = regexp( tag ); @@ -81,10 +54,10 @@ export function next( tag, text, index = 0 ) { /** * Replace matching shortcodes in a block of text. * - * @param {string} tag Shortcode tag. - * @param {string} text Text to search. - * @param {Function} callback Function to process the match and return - * replacement string. + * @param {string} tag Shortcode tag. + * @param {string} text Text to search. + * @param {import('./types').ReplaceCallback} callback Function to process the match and return + * replacement string. * * @return {string} Text with shortcodes replaced. */ @@ -169,7 +142,7 @@ export function regexp( tag ) { * * @param {string} text Serialised shortcode attributes. * - * @return {WPShortcodeAttrs} Parsed shortcode attributes. + * @return {import('./types').ShortcodeAttrs} Parsed shortcode attributes. */ export const attrs = memize( ( text ) => { const named = {}; @@ -224,9 +197,9 @@ export const attrs = memize( ( text ) => { * by `regexp()`. `match` can also be set to the `arguments` from a callback * passed to `regexp.replace()`. * - * @param {Array} match Match array. + * @param {import('./types').Match} match Match array. * - * @return {WPShortcode} Shortcode instance. + * @return {InstanceType<import('./types').shortcode>} Shortcode instance. */ export function fromMatch( match ) { let type; @@ -255,9 +228,7 @@ export function fromMatch( match ) { * the `type` of the shortcode ('single', 'self-closing', or 'closed'), and a * `content` string. * - * @param {Object} options Options as described. - * - * @return {WPShortcode} Shortcode instance. + * @type {import('./types').shortcode} Shortcode instance. */ const shortcode = Object.assign( function ( options ) { @@ -328,7 +299,7 @@ Object.assign( shortcode.prototype, { * @param {(number|string)} attr Attribute key. * @param {string} value Attribute value. * - * @return {WPShortcode} Shortcode instance. + * @return {InstanceType< import('./types').shortcode >} Shortcode instance. */ set( attr, value ) { this.attrs[ typeof attr === 'number' ? 'numeric' : 'named' ][ attr ] = diff --git a/packages/shortcode/src/types.ts b/packages/shortcode/src/types.ts new file mode 100644 index 00000000000000..2b9ae084cc31a6 --- /dev/null +++ b/packages/shortcode/src/types.ts @@ -0,0 +1,210 @@ +/** + * Shortcode attributes object. + */ +export type ShortcodeAttrs = { + /** + * Object with named attributes. + */ + named: Record< string, string | undefined >; + + /** + * Array with numeric attributes. + */ + numeric: string[]; +}; + +export type ShortcodeMatch = { + /** + * Index the shortcode is found at. + */ + index: number; + + /** + * Matched content. + */ + content: string; + + /** + * Shortcode instance of the match. + */ + shortcode: Shortcode; +}; + +/** + * Shortcode options. + */ +export interface ShortcodeOptions { + /** + * Shortcode tag. + */ + tag: string; + + /** + * Shortcode attributes. + */ + attrs?: Partial< ShortcodeAttrs > | string; + + /** + * Shortcode content. + */ + content?: string; + + /** + * Shortcode type: `self-closing`, `closed`, or `single`. + */ + type?: 'self-closing' | 'closed' | 'single'; +} + +/** + * Shortcode object. + */ +export interface Shortcode extends ShortcodeOptions { + /** + * Shortcode attributes. + */ + attrs: ShortcodeAttrs; +} + +export type Match = + | NonNullable< ReturnType< RegExp[ 'exec' ] > > + | Array< string >; + +export type ReplaceCallback = ( shortcode: Shortcode ) => string; + +/** + * WordPress Shortcode instance. + */ +export interface shortcode { + new ( options: Partial< ShortcodeOptions > ): Shortcode & { + /** + * Transform the shortcode into a string. + * + * @return {string} String representation of the shortcode. + */ + string: () => string; + + /** + * Get a shortcode attribute. + * + * Automatically detects whether `attr` is named or numeric and routes it + * accordingly. + * + * @param {(number|string)} attr Attribute key. + * + * @return {string} Attribute value. + */ + get: ( attr: string | number ) => string | undefined; + + /** + * Set a shortcode attribute. + * + * Automatically detects whether `attr` is named or numeric and routes it + * accordingly. + * + * @param {(number|string)} attr Attribute key. + * @param {string} value Attribute value. + * + * @return {InstanceType< shortcode >} Shortcode instance. + */ + set: ( + attr: string | number, + value: string + ) => InstanceType< shortcode >; + }; + + /** + * Parse shortcode attributes. + * + * Shortcodes accept many types of attributes. These can chiefly be divided into + * named and numeric attributes: + * + * Named attributes are assigned on a key/value basis, while numeric attributes + * are treated as an array. + * + * Named attributes can be formatted as either `name="value"`, `name='value'`, + * or `name=value`. Numeric attributes can be formatted as `"value"` or just + * `value`. + * + * @param text Serialised shortcode attributes. + * + * @return Parsed shortcode attributes. + */ + attrs: ( text: string ) => ShortcodeAttrs; + + /** + * Generate a Shortcode Object from a RegExp match. + * + * Accepts a `match` object from calling `regexp.exec()` on a `RegExp` generated + * by `regexp()`. `match` can also be set to the `arguments` from a callback + * passed to `regexp.replace()`. + * + * @param match Match array. + * + * @return Shortcode instance. + */ + fromMatch: ( match: Match ) => InstanceType< shortcode >; + + /** + * Find the next matching shortcode. + * + * @param tag Shortcode tag. + * @param text Text to search. + * @param index Index to start search from. + * + * @return Matched information. + */ + next: ( + tag: string, + text: string, + index?: number + ) => ShortcodeMatch | undefined; + + /** + * Generate a RegExp to identify a shortcode. + * + * The base regex is functionally equivalent to the one found in + * `get_shortcode_regex()` in `wp-includes/shortcodes.php`. + * + * Capture groups: + * + * 1. An extra `[` to allow for escaping shortcodes with double `[[]]` + * 2. The shortcode name + * 3. The shortcode argument list + * 4. The self closing `/` + * 5. The content of a shortcode when it wraps some content. + * 6. The closing tag. + * 7. An extra `]` to allow for escaping shortcodes with double `[[]]` + * + * @param tag Shortcode tag. + * + * @return Shortcode RegExp. + */ + regexp: ( tag: string ) => RegExp; + + /** + * Replace matching shortcodes in a block of text. + * + * @param tag Shortcode tag. + * @param text Text to search. + * @param callback Function to process the match and return + * replacement string. + * + * @return Text with shortcodes replaced. + */ + replace: ( tag: string, text: string, callback: ReplaceCallback ) => string; + + /** + * Generate a string from shortcode parameters. + * + * Creates a shortcode instance and returns a string. + * + * Accepts the same `options` as the `shortcode()` constructor, containing a + * `tag` string, a string or object of `attrs`, a boolean indicating whether to + * format the shortcode using a `single` tag, and a `content` string. + * + * @param options + * + * @return String representation of the shortcode. + */ + string: ( options: ShortcodeOptions ) => string; +} diff --git a/packages/shortcode/tsconfig.json b/packages/shortcode/tsconfig.json new file mode 100644 index 00000000000000..79aa09d0ad56e3 --- /dev/null +++ b/packages/shortcode/tsconfig.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types", + "checkJs": false + }, + "references": [], + "include": [ "src" ] +} diff --git a/tsconfig.json b/tsconfig.json index 51bb7f2d68924a..1010054ea512ea 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -50,6 +50,7 @@ { "path": "packages/report-flaky-tests" }, { "path": "packages/rich-text" }, { "path": "packages/router" }, + { "path": "packages/shortcode" }, { "path": "packages/style-engine" }, { "path": "packages/sync" }, { "path": "packages/token-list" }, From d0383fef7532779a27afbd226c51b535232201d4 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Sun, 1 Dec 2024 02:04:43 +0000 Subject: [PATCH 1782/1908] Fix: Styles section does not moves stylebook to typography. (#67423) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- packages/edit-site/src/components/style-book/index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index de4c38bd40c05d..6a044d80553007 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -89,6 +89,11 @@ const scrollToSection = ( anchorId, iframe ) => { */ const getStyleBookNavigationFromPath = ( path ) => { if ( path && typeof path === 'string' ) { + if ( path.startsWith( '/typography' ) ) { + return { + block: 'typography', + }; + } let block = path.includes( '/blocks/' ) ? decodeURIComponent( path.split( '/blocks/' )[ 1 ] ) : null; From 988f259c5c32d312bd09a25789c6b658069ccb90 Mon Sep 17 00:00:00 2001 From: Shail Mehta <shailmehta25@gmail.com> Date: Sun, 1 Dec 2024 19:38:30 +0530 Subject: [PATCH 1783/1908] Updated old URL in Documentation (#67446) * Updated Old URL Co-authored-by: shail-mehta <shailu25@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- docs/reference-guides/block-api/block-transforms.md | 12 ++++++------ platform-docs/docs/create-block/transforms.md | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/reference-guides/block-api/block-transforms.md b/docs/reference-guides/block-api/block-transforms.md index c2c5ed49d1b19c..9055ed0a3b45b3 100644 --- a/docs/reference-guides/block-api/block-transforms.md +++ b/docs/reference-guides/block-api/block-transforms.md @@ -44,7 +44,7 @@ A transformation of type `block` is an object that takes the following parameter - **transform** _(function)_: a callback that receives the attributes and inner blocks of the block being processed. It should return a block object or an array of block objects. - **isMatch** _(function, optional)_: a callback that receives the block attributes as the first argument and the block object as the second argument and should return a boolean. Returning `false` from this function will prevent the transform from being available and displayed as an option to the user. - **isMultiBlock** _(boolean, optional)_: whether the transformation can be applied when multiple blocks are selected. If true, the `transform` function's first parameter will be an array containing each selected block's attributes, and the second an array of each selected block's inner blocks. False by default. -- **priority** _(number, optional)_: controls the priority with which a transformation is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://codex.wordpress.org/Plugin_API#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. +- **priority** _(number, optional)_: controls the priority with which a transformation is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. **Example: from Paragraph block to Heading block** @@ -97,7 +97,7 @@ A transformation of type `enter` is an object that takes the following parameter - **type** _(string)_: the value `enter`. - **regExp** _(RegExp)_: the Regular Expression to use as a matcher. If the value matches, the transformation will be applied. - **transform** _(function)_: a callback that receives an object with a `content` field containing the value that has been entered. It should return a block object or an array of block objects. -- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://codex.wordpress.org/Plugin_API#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. +- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. **Example: from --- to Separator block** @@ -124,7 +124,7 @@ A transformation of type `files` is an object that takes the following parameter - **type** _(string)_: the value `files`. - **transform** _(function)_: a callback that receives the array of files being processed. It should return a block object or an array of block objects. - **isMatch** _(function, optional)_: a callback that receives the array of files being processed and should return a boolean. Returning `false` from this function will prevent the transform from being applied. -- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://codex.wordpress.org/Plugin_API#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. +- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. **Example: from file to File block** @@ -164,7 +164,7 @@ A transformation of type `prefix` is an object that takes the following paramete - **type** _(string)_: the value `prefix`. - **prefix** _(string)_: the character or sequence of characters that match this transform. - **transform** _(function)_: a callback that receives the content introduced. It should return a block object or an array of block objects. -- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://codex.wordpress.org/Plugin_API#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. +- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. **Example: from text to custom block** @@ -197,7 +197,7 @@ A transformation of type `raw` is an object that takes the following parameters: - **schema** _(object|function, optional)_: defines an [HTML content model](https://html.spec.whatwg.org/multipage/dom.html#content-models) used to detect and process pasted contents. See [below](#schemas-and-content-models). - **selector** _(string, optional)_: a CSS selector string to determine whether the element matches according to the [element.matches](https://developer.mozilla.org/en-US/docs/Web/API/Element/matches) method. The transform won't be executed if the element doesn't match. This is a shorthand and alternative to using `isMatch`, which, if present, will take precedence. - **isMatch** _(function, optional)_: a callback that receives the node being processed and should return a boolean. Returning `false` from this function will prevent the transform from being applied. -- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://codex.wordpress.org/Plugin_API#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. +- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. **Example: from URLs to Embed block** @@ -273,7 +273,7 @@ A transformation of type `shortcode` is an object that takes the following param - **transform** _(function, optional)_: a callback that receives the shortcode attributes as the first argument and the [WPShortcodeMatch](/packages/shortcode/README.md#next) as the second. It should return a block object or an array of block objects. When this parameter is defined, it will take precedence over the `attributes` parameter. - **attributes** _(object, optional)_: object representing where the block attributes should be sourced from, according to the attributes shape defined by the [block configuration object](./block-registration.md). If a particular attribute contains a `shortcode` key, it should be a function that receives the shortcode attributes as the first arguments and the [WPShortcodeMatch](/packages/shortcode/README.md#next) as second, and returns a value for the attribute that will be sourced in the block's comment. - **isMatch** _(function, optional)_: a callback that receives the shortcode attributes per the [Shortcode API](https://codex.wordpress.org/Shortcode_API) and should return a boolean. Returning `false` from this function will prevent the shortcode to be transformed into this block. -- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://codex.wordpress.org/Plugin_API#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. +- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. **Example: from shortcode to block using `transform`** diff --git a/platform-docs/docs/create-block/transforms.md b/platform-docs/docs/create-block/transforms.md index fd235b669cd720..4a4118d6850b9e 100644 --- a/platform-docs/docs/create-block/transforms.md +++ b/platform-docs/docs/create-block/transforms.md @@ -37,7 +37,7 @@ A transformation of type `block` is an object that takes the following parameter - **transform** _(function)_: a callback that receives the attributes and inner blocks of the block being processed. It should return a block object or an array of block objects. - **isMatch** _(function, optional)_: a callback that receives the block attributes as the first argument and the block object as the second argument and should return a boolean. Returning `false` from this function will prevent the transform from being available and displayed as an option to the user. - **isMultiBlock** _(boolean, optional)_: whether the transformation can be applied when multiple blocks are selected. If `true`, the `transform` function's first parameter will be an array containing each selected block's attributes, and the second an array of each selected block's inner blocks. Returns `false` by default. -- **priority** _(number, optional)_: controls the priority with which a transformation is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://codex.wordpress.org/Plugin_API#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. +- **priority** _(number, optional)_: controls the priority with which a transformation is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. **Example: Let's declare a transform from our Gutenpride block to Heading block** From 4775e7052b9e2ed7df46429e6e738de3faf2fb18 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Sun, 1 Dec 2024 20:00:10 +0000 Subject: [PATCH 1784/1908] Preload: fix settings fields order (#67450) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- lib/compat/wordpress-6.8/preload.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php index ae6c738c6627c5..6d92913b41411d 100644 --- a/lib/compat/wordpress-6.8/preload.php +++ b/lib/compat/wordpress-6.8/preload.php @@ -31,9 +31,9 @@ function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { 'site_icon_url', 'site_logo', 'timezone_string', - 'url', 'default_template_part_areas', 'default_template_types', + 'url', ) ); $paths[] = '/wp/v2/templates/lookup?slug=front-page'; From c5b33b86f27dd6b6e3b4450b7c72cb949e4bd95b Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Mon, 2 Dec 2024 10:59:13 +0530 Subject: [PATCH 1785/1908] Implement image size option for featured image in cover block (#67273) Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> --- packages/block-library/src/cover/edit/index.js | 5 ++++- .../src/cover/edit/inspector-controls.js | 13 ++++++++++--- packages/block-library/src/cover/index.php | 4 ++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/block-library/src/cover/edit/index.js b/packages/block-library/src/cover/edit/index.js index 3ad7039b558924..ced30973203292 100644 --- a/packages/block-library/src/cover/edit/index.js +++ b/packages/block-library/src/cover/edit/index.js @@ -120,7 +120,9 @@ function CoverEdit( { select( coreStore ).getMedia( featuredImage, { context: 'view' } ), [ featuredImage ] ); - const mediaUrl = media?.source_url; + const mediaUrl = + media?.media_details?.sizes?.[ sizeSlug ]?.source_url ?? + media?.source_url; // User can change the featured image outside of the block, but we still // need to update the block when that happens. This effect should only @@ -451,6 +453,7 @@ function CoverEdit( { toggleUseFeaturedImage={ toggleUseFeaturedImage } updateDimRatio={ onUpdateDimRatio } onClearMedia={ onClearMedia } + featuredImage={ media } /> ); diff --git a/packages/block-library/src/cover/edit/inspector-controls.js b/packages/block-library/src/cover/edit/inspector-controls.js index c0807869ee1a5c..b0d4b435163b78 100644 --- a/packages/block-library/src/cover/edit/inspector-controls.js +++ b/packages/block-library/src/cover/edit/inspector-controls.js @@ -96,6 +96,7 @@ export default function CoverInspectorControls( { coverRef, currentSettings, updateDimRatio, + featuredImage, } ) { const { useFeaturedImage, @@ -132,8 +133,12 @@ export default function CoverInspectorControls( { [ id, isImageBackground ] ); + const currentBackgroundImage = useFeaturedImage ? featuredImage : image; + function updateImage( newSizeSlug ) { - const newUrl = image?.media_details?.sizes?.[ newSizeSlug ]?.source_url; + const newUrl = + currentBackgroundImage?.media_details?.sizes?.[ newSizeSlug ] + ?.source_url; if ( ! newUrl ) { return null; } @@ -146,7 +151,9 @@ export default function CoverInspectorControls( { const imageSizeOptions = imageSizes ?.filter( - ( { slug } ) => image?.media_details?.sizes?.[ slug ]?.source_url + ( { slug } ) => + currentBackgroundImage?.media_details?.sizes?.[ slug ] + ?.source_url ) ?.map( ( { name, slug } ) => ( { value: slug, label: name } ) ); @@ -321,7 +328,7 @@ export default function CoverInspectorControls( { /> </ToolsPanelItem> ) } - { ! useFeaturedImage && !! imageSizeOptions?.length && ( + { !! imageSizeOptions?.length && ( <ResolutionTool value={ sizeSlug } onChange={ updateImage } diff --git a/packages/block-library/src/cover/index.php b/packages/block-library/src/cover/index.php index 1ffe7ab3f4dbc6..630835a47947b3 100644 --- a/packages/block-library/src/cover/index.php +++ b/packages/block-library/src/cover/index.php @@ -35,12 +35,12 @@ function render_block_core_cover( $attributes, $content ) { $attr['style'] = 'object-position:' . $object_position . ';'; } - $image = get_the_post_thumbnail( null, 'post-thumbnail', $attr ); + $image = get_the_post_thumbnail( null, $attributes['sizeSlug'] ?? 'post-thumbnail', $attr ); } else { if ( in_the_loop() ) { update_post_thumbnail_cache(); } - $current_featured_image = get_the_post_thumbnail_url(); + $current_featured_image = get_the_post_thumbnail_url( null, $attributes['sizeSlug'] ?? null ); if ( ! $current_featured_image ) { return $content; } From b867a5fe7c1133e906682eff84b53b6621dea559 Mon Sep 17 00:00:00 2001 From: Daniel Richards <daniel.richards@automattic.com> Date: Mon, 2 Dec 2024 14:43:15 +0800 Subject: [PATCH 1786/1908] Fix List View not updating when switching editor modes (#67379) * Add back the editorTool dependency to getEnabledClientIdsTree * Add e2e test * Switch to getEditorMode selector ---- Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> --- .../src/store/private-selectors.js | 8 +-- .../editor/various/write-design-mode.spec.js | 55 +++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 9779ae1300fb57..61b17a3625d159 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -109,16 +109,16 @@ function getEnabledClientIdsTreeUnmemoized( state, rootClientId ) { * * @return {Object[]} Tree of block objects with only clientID and innerBlocks set. */ -export const getEnabledClientIdsTree = createSelector( - getEnabledClientIdsTreeUnmemoized, - ( state ) => [ +export const getEnabledClientIdsTree = createRegistrySelector( ( select ) => + createSelector( getEnabledClientIdsTreeUnmemoized, ( state ) => [ state.blocks.order, state.derivedBlockEditingModes, state.derivedNavModeBlockEditingModes, state.blockEditingModes, state.settings.templateLock, state.blockListSettings, - ] + select( STORE_NAME ).__unstableGetEditorMode( state ), + ] ) ); /** diff --git a/test/e2e/specs/editor/various/write-design-mode.spec.js b/test/e2e/specs/editor/various/write-design-mode.spec.js index 053f4cb8ff092a..2892b4aea89e91 100644 --- a/test/e2e/specs/editor/various/write-design-mode.spec.js +++ b/test/e2e/specs/editor/various/write-design-mode.spec.js @@ -121,4 +121,59 @@ test.describe( 'Write/Design mode', () => { editorSettings.getByRole( 'button', { name: 'Content' } ) ).toBeVisible(); } ); + + test( 'hides the blocks that cannot be interacted with in List View', async ( { + editor, + page, + pageUtils, + } ) => { + await editor.setContent( '' ); + + // Insert a section with a nested block and an editable block. + await editor.insertBlock( { + name: 'core/group', + attributes: {}, + innerBlocks: [ + { + name: 'core/group', + attributes: { + metadata: { + name: 'Non-content block', + }, + }, + innerBlocks: [ + { + name: 'core/paragraph', + attributes: { + content: 'Something', + }, + }, + ], + }, + ], + } ); + + // Select the inner paragraph block so that List View is expanded. + await editor.canvas + .getByRole( 'document', { + name: 'Block: Paragraph', + } ) + .click(); + + // Open List View. + await pageUtils.pressKeys( 'access+o' ); + const listView = page.getByRole( 'treegrid', { + name: 'Block navigation structure', + } ); + const nonContentBlock = listView.getByRole( 'link', { + name: 'Non-content block', + } ); + + await expect( nonContentBlock ).toBeVisible(); + + // Switch to write mode. + await editor.switchEditorTool( 'Write' ); + + await expect( nonContentBlock ).toBeHidden(); + } ); } ); From d251f755481bdfe6eac99ab85f6410e3334622cc Mon Sep 17 00:00:00 2001 From: Eshaan Dabasiya <76681468+im3dabasia@users.noreply.github.com> Date: Mon, 2 Dec 2024 14:10:03 +0530 Subject: [PATCH 1787/1908] Experiments: Remove trailing space in Color randomizer (#67457) Co-authored-by: im3dabasia <im3dabasia1@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- lib/experiments-page.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/experiments-page.php b/lib/experiments-page.php index 9033e3c2d0c1fb..256a185a3af692 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -69,7 +69,7 @@ function gutenberg_initialize_experiments_settings() { add_settings_field( 'gutenberg-color-randomizer', - __( 'Color randomizer ', 'gutenberg' ), + __( 'Color randomizer', 'gutenberg' ), 'gutenberg_display_experiment_field', 'gutenberg-experiments', 'gutenberg_experiments_section', From 2f670d56405a6c43800e5a5068bb8ee75b9205d9 Mon Sep 17 00:00:00 2001 From: Yogesh Bhutkar <yogesh.bhutkar@rtcamp.com> Date: Mon, 2 Dec 2024 15:30:08 +0530 Subject: [PATCH 1788/1908] Remove inline-block display from image anchor in style.scss (#67368) * Remove inline-block display from image anchor in style.scss * Refactor: Set image anchor display to inline-block in style.scss Co-authored-by: yogeshbhutkar <yogeshbhutkar@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Infinite-Null <ankitkumarshah@git.wordpress.org> Co-authored-by: hanneslsm <hanneslsm@git.wordpress.org> Co-authored-by: frkly <frkly@git.wordpress.org> --- packages/block-library/src/image/style.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/image/style.scss b/packages/block-library/src/image/style.scss index a7fcb8f175e4e5..8ca5795cfd911a 100644 --- a/packages/block-library/src/image/style.scss +++ b/packages/block-library/src/image/style.scss @@ -1,6 +1,7 @@ .wp-block-image { - a { + > a, + > figure > a { display: inline-block; } From 358fb8e04445ebf29140ba875e273bba8fd43913 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 2 Dec 2024 10:07:39 +0000 Subject: [PATCH 1789/1908] Inserter: Patterns: remove loading indicator (#67072) --- .../inserter/block-patterns-tab/index.js | 18 +----------------- .../src/store/private-selectors.js | 15 --------------- 2 files changed, 1 insertion(+), 32 deletions(-) diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/index.js b/packages/block-editor/src/components/inserter/block-patterns-tab/index.js index 01e41111b7c890..45db4732aa9c6a 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/index.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/index.js @@ -3,9 +3,8 @@ */ import { useState } from '@wordpress/element'; import { useViewportMatch } from '@wordpress/compose'; -import { Button, Spinner } from '@wordpress/components'; +import { Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -16,8 +15,6 @@ import { PatternCategoryPreviews } from './pattern-category-previews'; import { usePatternCategories } from './use-pattern-categories'; import CategoryTabs from '../category-tabs'; import InserterNoResults from '../no-results'; -import { store as blockEditorStore } from '../../../store'; -import { unlock } from '../../../lock-unlock'; function BlockPatternsTab( { onSelectCategory, @@ -31,19 +28,6 @@ function BlockPatternsTab( { const categories = usePatternCategories( rootClientId ); const isMobile = useViewportMatch( 'medium', '<' ); - const isResolvingPatterns = useSelect( - ( select ) => - unlock( select( blockEditorStore ) ).isResolvingPatterns(), - [] - ); - - if ( isResolvingPatterns ) { - return ( - <div className="block-editor-inserter__patterns-loading"> - <Spinner /> - </div> - ); - } if ( ! categories.length ) { return <InserterNoResults />; diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 61b17a3625d159..c46778d889b3e0 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -406,21 +406,6 @@ export const getAllPatterns = createRegistrySelector( ( select ) => }, getAllPatternsDependants( select ) ) ); -export const isResolvingPatterns = createRegistrySelector( ( select ) => - createSelector( ( state ) => { - const blockPatternsSelect = state.settings[ selectBlockPatternsKey ]; - const reusableBlocksSelect = state.settings[ reusableBlocksSelectKey ]; - return ( - ( blockPatternsSelect - ? blockPatternsSelect( select ) === undefined - : false ) || - ( reusableBlocksSelect - ? reusableBlocksSelect( select ) === undefined - : false ) - ); - }, getAllPatternsDependants( select ) ) -); - const EMPTY_ARRAY = []; export const getReusableBlocks = createRegistrySelector( From 22c43ff9e687eb5752b790316f2b1eeb99976dbb Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Mon, 2 Dec 2024 10:40:27 +0000 Subject: [PATCH 1790/1908] Disable Zoom Out if no section root to allow for Theme opt in (#67232) * Disable toolbar and auto inserter behaviour if no section root * Remove useless coercion Co-authored-by: Ramon <ramonjd@users.noreply.github.com> * Remove more coercion copy/paste Co-authored-by: Ramon <ramonjd@users.noreply.github.com> * Add section root to Zoom Out e2e test * Add test coverage * Add some test coverage * Try e2e test fix by reverting all template part changes in Theme * Remove need to exit Zoom Out * Ensure a main tag * Update tests to expect the click-through behavior * Simplify selection --------- Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> --- .../src/components/inserter/menu.js | 9 ++- .../editor/src/components/header/index.js | 16 ++++- .../editor/various/parsing-patterns.spec.js | 3 +- .../editor/various/pattern-overrides.spec.js | 70 ++++++++++++++++--- test/e2e/specs/site-editor/zoom-out.spec.js | 45 +++++++++++- 5 files changed, 127 insertions(+), 16 deletions(-) diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index 8dc2f64063c8e3..ef260beb85906b 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -58,6 +58,11 @@ function InserterMenu( ( select ) => unlock( select( blockEditorStore ) ).isZoomOut(), [] ); + const hasSectionRootClientId = useSelect( + ( select ) => + !! unlock( select( blockEditorStore ) ).getSectionRootClientId(), + [] + ); const [ filterValue, setFilterValue, delayedFilterValue ] = useDebouncedInput( __experimentalFilterValue ); const [ hoveredItem, setHoveredItem ] = useState( null ); @@ -81,7 +86,9 @@ function InserterMenu( const [ selectedTab, setSelectedTab ] = useState( getInitialTab() ); const shouldUseZoomOut = - selectedTab === 'patterns' || selectedTab === 'media'; + hasSectionRootClientId && + ( selectedTab === 'patterns' || selectedTab === 'media' ); + useZoomOut( shouldUseZoomOut && isLargeViewport ); const [ destinationRootClientId, onInsertBlocks, onToggleInsertionPoint ] = diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index 51c341f2c1bd16..79199b15b1ad16 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -30,6 +30,7 @@ import { PATTERN_POST_TYPE, NAVIGATION_POST_TYPE, } from '../../store/constants'; +import { unlock } from '../../lock-unlock'; const toolbarVariations = { distractionFreeDisabled: { y: '-50px' }, @@ -102,6 +103,13 @@ function Header( { ( hasFixedToolbar && ( ! hasBlockSelection || isBlockToolsCollapsed ) ) ); const hasBackButton = useHasBackButton(); + + const hasSectionRootClientId = useSelect( + ( select ) => + !! unlock( select( blockEditorStore ) ).getSectionRootClientId(), + [] + ); + /* * The edit-post-header classname is only kept for backward compatability * as some plugins might be relying on its presence. @@ -169,9 +177,11 @@ function Header( { forceIsAutosaveable={ forceIsDirty } /> - { canBeZoomedOut && isWideViewport && ( - <ZoomOutToggle disabled={ forceDisableBlockTools } /> - ) } + { canBeZoomedOut && + isWideViewport && + hasSectionRootClientId && ( + <ZoomOutToggle disabled={ forceDisableBlockTools } /> + ) } { ( isWideViewport || ! showIconLabels ) && ( <PinnedItems.Slot scope="core" /> diff --git a/test/e2e/specs/editor/various/parsing-patterns.spec.js b/test/e2e/specs/editor/various/parsing-patterns.spec.js index d8edc544ffa03c..98261804acb586 100644 --- a/test/e2e/specs/editor/various/parsing-patterns.spec.js +++ b/test/e2e/specs/editor/various/parsing-patterns.spec.js @@ -37,9 +37,8 @@ test.describe( 'Parsing patterns', () => { } ); } ); - // Exit zoom out mode and select the inner buttons block to ensure + // Select the inner buttons block to ensure // the correct insertion point is selected. - await page.getByRole( 'button', { name: 'Zoom Out' } ).click(); await editor.selectBlocks( editor.canvas.locator( 'role=document[name="Block: Button"i]' ) ); diff --git a/test/e2e/specs/editor/various/pattern-overrides.spec.js b/test/e2e/specs/editor/various/pattern-overrides.spec.js index 7069b4cec258ab..7d2be84187ef61 100644 --- a/test/e2e/specs/editor/various/pattern-overrides.spec.js +++ b/test/e2e/specs/editor/various/pattern-overrides.spec.js @@ -268,12 +268,25 @@ test.describe( 'Pattern Overrides', () => { } ); await editor.setContent( '' ); + await editor.switchEditorTool( 'Design' ); + // Insert a `<main>` group block. + // In zoomed out and write mode it acts as the section root. + // Inside is a pattern that acts as a section. await editor.insertBlock( { - name: 'core/block', - attributes: { ref: id }, + name: 'core/group', + attributes: { tagName: 'main' }, + innerBlocks: [ + { + name: 'core/block', + attributes: { ref: id }, + }, + ], } ); + const groupBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Group', + } ); const patternBlock = editor.canvas.getByRole( 'document', { name: 'Block: Pattern', } ); @@ -290,14 +303,35 @@ test.describe( 'Pattern Overrides', () => { hasText: 'No Overrides or Binding', } ); - await test.step( 'Zoomed in / Design mode', async () => { - await editor.switchEditorTool( 'Design' ); - // In zoomed in and design mode the pattern block and child blocks - // with bindings are editable. + await test.step( 'Click-through behavior', async () => { + // With the group block selected, all the inner blocks of the pattern + // are inert due to the 'click-through' behavior, that requires the + // pattern block be selected first before its inner blocks are selectable. + await editor.selectBlocks( groupBlock ); await expect( patternBlock ).not.toHaveAttribute( 'inert', 'true' ); + await expect( blockWithOverrides ).toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithBindings ).toHaveAttribute( + 'inert', + 'true' + ); + await expect( blockWithoutOverridesOrBindings ).toHaveAttribute( + 'inert', + 'true' + ); + } ); + + await test.step( 'Zoomed in / Design mode', async () => { + await editor.selectBlocks( patternBlock ); + + // Once selected and in zoomed in/design mode the child blocks + // of the pattern with bindings are editable, but unbound + // blocks are inert. await expect( blockWithOverrides ).not.toHaveAttribute( 'inert', 'true' @@ -314,11 +348,16 @@ test.describe( 'Pattern Overrides', () => { await test.step( 'Zoomed in / Write mode - pattern as a section', async () => { await editor.switchEditorTool( 'Write' ); + // The pattern block is still editable as a section. await expect( patternBlock ).not.toHaveAttribute( 'inert', 'true' ); + + // Ensure the pattern block is selected. + await editor.selectBlocks( patternBlock ); + // Child blocks of the pattern with bindings are editable. await expect( blockWithOverrides ).not.toHaveAttribute( 'inert', @@ -336,11 +375,18 @@ test.describe( 'Pattern Overrides', () => { await test.step( 'Zoomed out / Write mode - pattern as a section', async () => { await page.getByLabel( 'Zoom Out' ).click(); - // In zoomed out only the pattern block is editable, as in this scenario it's a section. + // In zoomed out only the pattern block is editable, + // as in this scenario it's a section. await expect( patternBlock ).not.toHaveAttribute( 'inert', 'true' ); + + // Ensure the pattern block is selected before checking the child blocks + // to ensure the click-through behavior isn't interfering. + await editor.selectBlocks( patternBlock ); + + // None of the child blocks are editable in zoomed out mode. await expect( blockWithOverrides ).toHaveAttribute( 'inert', 'true' @@ -357,11 +403,17 @@ test.describe( 'Pattern Overrides', () => { await test.step( 'Zoomed out / Design mode - pattern as a section', async () => { await editor.switchEditorTool( 'Design' ); - // In zoomed out only the pattern block is editable, as in this scenario it's a section. + // In zoomed out only the pattern block is editable, + // as in this scenario it's a section. await expect( patternBlock ).not.toHaveAttribute( 'inert', 'true' ); + + // Ensure the pattern block is selected before checking the child blocks + // to ensure the click-through behavior isn't interfering. + await editor.selectBlocks( patternBlock ); + await expect( blockWithOverrides ).toHaveAttribute( 'inert', 'true' @@ -376,7 +428,7 @@ test.describe( 'Pattern Overrides', () => { ); } ); - // Zoom out and group the pattern. + // Zoom out and group the pattern so that it's no longer a section. await page.getByLabel( 'Zoom Out' ).click(); await editor.selectBlocks( patternBlock ); await editor.clickBlockOptionsMenuItem( 'Group' ); diff --git a/test/e2e/specs/site-editor/zoom-out.spec.js b/test/e2e/specs/site-editor/zoom-out.spec.js index e698a94b7cf0dc..77d121e1999397 100644 --- a/test/e2e/specs/site-editor/zoom-out.spec.js +++ b/test/e2e/specs/site-editor/zoom-out.spec.js @@ -4,7 +4,8 @@ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); const EDITOR_ZOOM_OUT_CONTENT = ` -<!-- wp:group {"style":{"spacing":{"padding":{"top":"0","bottom":"0","left":"0","right":"0"}},"dimensions":{"minHeight":"100vh"}},"backgroundColor":"base-2","layout":{"type":"flex","orientation":"vertical","verticalAlignment":"space-between"}} --> +<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} --> +<main class="wp-block-group"><!-- wp:group {"style":{"spacing":{"padding":{"top":"0","bottom":"0","left":"0","right":"0"}},"dimensions":{"minHeight":"100vh"}},"backgroundColor":"base-2","layout":{"type":"flex","orientation":"vertical","verticalAlignment":"space-between"}} --> <div class="wp-block-group has-base-2-background-color has-background" style="min-height:100vh;padding-top:0;padding-right:0;padding-bottom:0;padding-left:0"><!-- wp:paragraph --> <p>First Section Start</p> <!-- /wp:paragraph --> @@ -58,6 +59,21 @@ const EDITOR_ZOOM_OUT_CONTENT = ` <!-- wp:paragraph --> <p>Fourth Section End</p> <!-- /wp:paragraph --></div> +<!-- /wp:group --></main> +<!-- /wp:group -->`; + +const EDITOR_ZOOM_OUT_CONTENT_NO_SECTION_ROOT = `<!-- wp:group {"style":{"spacing":{"padding":{"top":"0","bottom":"0","left":"0","right":"0"}},"dimensions":{"minHeight":"100vh"}},"backgroundColor":"base-2","layout":{"type":"flex","orientation":"vertical","verticalAlignment":"space-between"}} --> +<div class="wp-block-group has-base-2-background-color has-background" style="min-height:100vh;padding-top:0;padding-right:0;padding-bottom:0;padding-left:0"><!-- wp:paragraph --> +<p>First Section Start</p> +<!-- /wp:paragraph --> + +<!-- wp:paragraph {"style":{"layout":{"selfStretch":"fit","flexSize":null}}} --> +<p>First Section Center</p> +<!-- /wp:paragraph --> + +<!-- wp:paragraph --> +<p>First Section End</p> +<!-- /wp:paragraph --></div> <!-- /wp:group -->`; test.describe( 'Zoom Out', () => { @@ -67,6 +83,8 @@ test.describe( 'Zoom Out', () => { test.afterAll( async ( { requestUtils } ) => { await requestUtils.activateTheme( 'twentytwentyone' ); + await requestUtils.deleteAllTemplates( 'wp_template' ); + await requestUtils.deleteAllTemplates( 'wp_template_part' ); } ); test.beforeEach( async ( { admin } ) => { @@ -215,4 +233,29 @@ test.describe( 'Zoom Out', () => { await expect( thirdSectionEnd ).toBeInViewport(); await expect( fourthSectionStart ).not.toBeInViewport(); } ); + + test( 'Zoom Out cannot be activated when the section root is missing', async ( { + page, + editor, + } ) => { + await editor.setContent( EDITOR_ZOOM_OUT_CONTENT_NO_SECTION_ROOT ); + + // Check that the Zoom Out toggle button is not visible. + await expect( + page.getByRole( 'button', { name: 'Zoom Out' } ) + ).toBeHidden(); + + // Check that activating the Patterns tab in the Inserter does not activate + // Zoom Out. + await page + .getByRole( 'button', { + name: 'Block Inserter', + exact: true, + } ) + .click(); + + await page.getByRole( 'tab', { name: 'Patterns' } ).click(); + + await expect( page.locator( '.is-zoomed-out' ) ).toBeHidden(); + } ); } ); From e92d57743b68753ee47f9c21645524e2a5b86ea4 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Mon, 2 Dec 2024 11:47:20 +0100 Subject: [PATCH 1791/1908] Remove one occurrence of incorrect usage of ItemGroup. (#67427) * Remove one occurrence of incorret usage of ItemGroup. * Fix toggling visibility of the help text. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> --- packages/block-editor/src/hooks/block-bindings.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 615804a311c0fb..e10696cc1257d7 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -300,13 +300,17 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { /> ) } </ItemGroup> - <ItemGroup> - <Text variant="muted"> + { /* + Use a div element to make the ToolsPanelHiddenInnerWrapper + toggle the visibility of this help text automatically. + */ } + <Text as="div" variant="muted"> + <p> { __( 'Attributes connected to custom fields or other dynamic data.' ) } - </Text> - </ItemGroup> + </p> + </Text> </ToolsPanel> </InspectorControls> ); From aef323a70e74fcf676036139bd25f657ad2a0b02 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 2 Dec 2024 10:59:01 +0000 Subject: [PATCH 1792/1908] PR template: add before/after table (#62739) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> --- .github/PULL_REQUEST_TEMPLATE.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index fd63e5e2e5312e..69fd34d709bdc5 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -20,3 +20,9 @@ https://github.com/WordPress/gutenberg/blob/trunk/CONTRIBUTING.md --> <!-- How can you test the changes by using the keyboard only? Please note, this is required for PRs that change the user interface (UI). This ensures the PR can be tested for any possible accessibility regressions. --> ## Screenshots or screencast <!-- if applicable --> + +<!-- If you would like to upload screenshots, feel free to use the table below when it is useful to show the difference between before and after the change. --> + +|Before|After| +|-|-| +|<!-- Before screenshot here -->|<!-- After screenshot here -->| From 8d343d155c7577d46aea33e708dceb39c571cc80 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 2 Dec 2024 12:26:27 +0100 Subject: [PATCH 1793/1908] Site Editor: Fix focus mode navigation (#67458) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> --- .../use-navigate-to-entity-record.js | 2 +- packages/router/src/router.tsx | 1 + .../template-part-focus-mode.spec.js | 50 +++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 test/e2e/specs/site-editor/template-part-focus-mode.spec.js diff --git a/packages/edit-site/src/components/block-editor/use-navigate-to-entity-record.js b/packages/edit-site/src/components/block-editor/use-navigate-to-entity-record.js index 8cc7fdaefe2d98..66be70fcd4e2e2 100644 --- a/packages/edit-site/src/components/block-editor/use-navigate-to-entity-record.js +++ b/packages/edit-site/src/components/block-editor/use-navigate-to-entity-record.js @@ -17,7 +17,7 @@ export default function useNavigateToEntityRecord() { const onNavigateToEntityRecord = useCallback( ( params ) => { history.navigate( - `/${ params.postType }/${ params.id }?canvas=edit&focusMode=true` + `/${ params.postType }/${ params.postId }?canvas=edit&focusMode=true` ); }, [ history ] diff --git a/packages/router/src/router.tsx b/packages/router/src/router.tsx index 34cc542c7b5737..2ac7974b4dfbce 100644 --- a/packages/router/src/router.tsx +++ b/packages/router/src/router.tsx @@ -146,6 +146,7 @@ export function useHistory() { return useMemo( () => ( { navigate, + back: history.back, } ), [ navigate ] ); diff --git a/test/e2e/specs/site-editor/template-part-focus-mode.spec.js b/test/e2e/specs/site-editor/template-part-focus-mode.spec.js new file mode 100644 index 00000000000000..29e6788779ed98 --- /dev/null +++ b/test/e2e/specs/site-editor/template-part-focus-mode.spec.js @@ -0,0 +1,50 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.describe( 'Template Part Focus mode', () => { + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentyfour' ); + } ); + + test.afterEach( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentyone' ); + } ); + + test( 'Should navigate to template part and back.', async ( { + admin, + page, + editor, + } ) => { + await admin.visitAdminPage( 'site-editor.php?canvas=edit' ); + await editor.setPreferences( 'core/edit-site', { + welcomeGuide: false, + } ); + + // Check that we're editing the template + await expect( page.locator( 'h1' ) ).toContainText( 'Blog Home' ); + await expect( page.locator( 'h1' ) ).toContainText( 'Template' ); + + // Click Template Part + await editor.canvas + .getByRole( 'document', { + name: 'Header', + } ) + .click(); + + // Navigate to Focus mode + await editor.clickBlockToolbarButton( 'Edit' ); + + // Check if focus mode is active + await expect( page.locator( 'h1' ) ).toContainText( 'Header' ); + await expect( page.locator( 'h1' ) ).toContainText( 'Template Part' ); + + // Go back + await page.getByRole( 'button', { name: 'Back' } ).click(); + + // Check that we're editing the template + await expect( page.locator( 'h1' ) ).toContainText( 'Blog Home' ); + await expect( page.locator( 'h1' ) ).toContainText( 'Template' ); + } ); +} ); From 141e9cd884053db9baec26e43297162841f9e7a7 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 2 Dec 2024 12:51:58 +0100 Subject: [PATCH 1794/1908] Site editor: Allow access to quick edit (#67469) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- packages/edit-site/src/components/site-editor-routes/pages.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/site-editor-routes/pages.js b/packages/edit-site/src/components/site-editor-routes/pages.js index e8c55cd10307e1..5f2a4e341e0dc7 100644 --- a/packages/edit-site/src/components/site-editor-routes/pages.js +++ b/packages/edit-site/src/components/site-editor-routes/pages.js @@ -44,7 +44,7 @@ export const pagesRoute = { mobile: <MobilePagesView />, edit( { query } ) { const hasQuickEdit = - ( query.layout ?? 'list' ) === 'list' && !! query.quickEdit; + ( query.layout ?? 'list' ) !== 'list' && !! query.quickEdit; return hasQuickEdit ? ( <PostEdit postType="page" postId={ query.postId } /> ) : undefined; @@ -59,7 +59,7 @@ export const pagesRoute = { }, edit( { query } ) { const hasQuickEdit = - ( query.layout ?? 'list' ) === 'list' && !! query.quickEdit; + ( query.layout ?? 'list' ) !== 'list' && !! query.quickEdit; return hasQuickEdit ? 380 : undefined; }, }, From e07fe5cd9c17702e242df8ab547bddd1c4d79f52 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 2 Dec 2024 12:01:28 +0000 Subject: [PATCH 1795/1908] Preload: parse post ID from p (path) (#67465) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- backport-changelog/6.8/7695.md | 1 + lib/compat/wordpress-6.8/preload.php | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/backport-changelog/6.8/7695.md b/backport-changelog/6.8/7695.md index 095c058e6fd10b..f45b2039e30274 100644 --- a/backport-changelog/6.8/7695.md +++ b/backport-changelog/6.8/7695.md @@ -1,3 +1,4 @@ https://github.com/WordPress/wordpress-develop/pull/7695 * https://github.com/WordPress/gutenberg/pull/66631 +* https://github.com/WordPress/gutenberg/pull/67465 diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php index 6d92913b41411d..494e3ad32ec02e 100644 --- a/lib/compat/wordpress-6.8/preload.php +++ b/lib/compat/wordpress-6.8/preload.php @@ -10,8 +10,16 @@ */ function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { if ( 'core/edit-site' === $context->name ) { - if ( ! empty( $_GET['postId'] ) ) { - $route_for_post = rest_get_route_for_post( $_GET['postId'] ); + $post_id = null; + if ( isset( $_GET['postId'] ) && is_numeric( $_GET['postId'] ) ) { + $post_id = (int) $_GET['postId']; + } + if ( isset( $_GET['p'] ) && preg_match( '/^\/page\/(\d+)$/', $_GET['p'], $matches ) ) { + $post_id = (int) $matches[1]; + } + + if ( $post_id ) { + $route_for_post = rest_get_route_for_post( $post_id ); if ( $route_for_post ) { $paths[] = add_query_arg( 'context', 'edit', $route_for_post ); } From 39a4d1c93fd3f9bee19db3566e92ce4a03e67544 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Mon, 2 Dec 2024 13:14:14 +0100 Subject: [PATCH 1796/1908] DataViews: Better handling of missing onClickItem prop (#67402) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- .../src/components/dataviews-context/index.ts | 5 ++--- .../src/components/dataviews/index.tsx | 5 ++--- .../src/dataviews-layouts/grid/index.tsx | 14 +++++++------- .../src/dataviews-layouts/table/index.tsx | 16 ++++++++-------- .../utils/get-clickable-item-props.ts | 19 ++++++++++++------- packages/dataviews/src/types.ts | 2 +- 6 files changed, 32 insertions(+), 29 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-context/index.ts b/packages/dataviews/src/components/dataviews-context/index.ts index 19f6b4178b7b55..4bef3ecdbcbb4a 100644 --- a/packages/dataviews/src/components/dataviews-context/index.ts +++ b/packages/dataviews/src/components/dataviews-context/index.ts @@ -26,7 +26,7 @@ type DataViewsContextType< Item > = { openedFilter: string | null; setOpenedFilter: ( openedFilter: string | null ) => void; getItemId: ( item: Item ) => string; - onClickItem: ( item: Item ) => void; + onClickItem?: ( item: Item ) => void; isItemClickable: ( item: Item ) => boolean; }; @@ -44,8 +44,7 @@ const DataViewsContext = createContext< DataViewsContextType< any > >( { setOpenedFilter: () => {}, openedFilter: null, getItemId: ( item ) => item.id, - onClickItem: () => {}, - isItemClickable: () => false, + isItemClickable: () => true, } ); export default DataViewsContext; diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index ee6073f40bf3d8..99d9b6d684b08c 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -52,8 +52,7 @@ type DataViewsProps< Item > = { : { getItemId: ( item: Item ) => string } ); const defaultGetItemId = ( item: ItemWithId ) => item.id; -const defaultIsItemClickable = () => false; -const defaultOnClickItem = () => {}; +const defaultIsItemClickable = () => true; const EMPTY_ARRAY: any[] = []; export default function DataViews< Item >( { @@ -70,7 +69,7 @@ export default function DataViews< Item >( { defaultLayouts, selection: selectionProperty, onChangeSelection, - onClickItem = defaultOnClickItem, + onClickItem, isItemClickable = defaultIsItemClickable, header, }: DataViewsProps< Item > ) { diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx index 2a09fb68efab82..17053e01604a55 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx @@ -31,7 +31,7 @@ interface GridItemProps< Item > { selection: string[]; onChangeSelection: SetSelection; getItemId: ( item: Item ) => string; - onClickItem: ( item: Item ) => void; + onClickItem?: ( item: Item ) => void; isItemClickable: ( item: Item ) => boolean; item: Item; actions: Action< Item >[]; @@ -66,19 +66,19 @@ function GridItem< Item >( { <primaryField.render item={ item } /> ) : null; - const clickableMediaItemProps = getClickableItemProps( + const clickableMediaItemProps = getClickableItemProps( { item, isItemClickable, onClickItem, - 'dataviews-view-grid__media' - ); + className: 'dataviews-view-grid__media', + } ); - const clickablePrimaryItemProps = getClickableItemProps( + const clickablePrimaryItemProps = getClickableItemProps( { item, isItemClickable, onClickItem, - 'dataviews-view-grid__primary-field' - ); + className: 'dataviews-view-grid__primary-field', + } ); return ( <VStack diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 7f93a4c14a7ddc..81d856451bfcdc 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -42,7 +42,7 @@ interface TableColumnFieldProps< Item > { field: NormalizedField< Item >; item: Item; isItemClickable: ( item: Item ) => boolean; - onClickItem: ( item: Item ) => void; + onClickItem?: ( item: Item ) => void; } interface TableColumnCombinedProps< Item > { @@ -52,7 +52,7 @@ interface TableColumnCombinedProps< Item > { item: Item; view: ViewTableType; isItemClickable: ( item: Item ) => boolean; - onClickItem: ( item: Item ) => void; + onClickItem?: ( item: Item ) => void; } interface TableColumnProps< Item > { @@ -62,7 +62,7 @@ interface TableColumnProps< Item > { column: string; view: ViewTableType; isItemClickable: ( item: Item ) => boolean; - onClickItem: ( item: Item ) => void; + onClickItem?: ( item: Item ) => void; } interface TableRowProps< Item > { @@ -77,7 +77,7 @@ interface TableRowProps< Item > { getItemId: ( item: Item ) => string; onChangeSelection: SetSelection; isItemClickable: ( item: Item ) => boolean; - onClickItem: ( item: Item ) => void; + onClickItem?: ( item: Item ) => void; } function TableColumn< Item >( { @@ -118,12 +118,12 @@ function TableColumnField< Item >( { const isItemClickableField = ( i: Item ) => isItemClickable( i ) && isPrimaryField; - const clickableProps = getClickableItemProps( + const clickableProps = getClickableItemProps( { item, - isItemClickableField, + isItemClickable: isItemClickableField, onClickItem, - 'dataviews-view-table__cell-content' - ); + className: 'dataviews-view-table__cell-content', + } ); return ( <div diff --git a/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts b/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts index efb4a8f598c7b8..d952839d376d2c 100644 --- a/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts +++ b/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts @@ -1,10 +1,15 @@ -export default function getClickableItemProps< Item >( - item: Item, - isItemClickable: ( item: Item ) => boolean, - onClickItem: ( item: Item ) => void, - className: string -) { - if ( ! isItemClickable( item ) ) { +export default function getClickableItemProps< Item >( { + item, + isItemClickable, + onClickItem, + className, +}: { + item: Item; + isItemClickable: ( item: Item ) => boolean; + onClickItem?: ( item: Item ) => void; + className: string; +} ) { + if ( ! isItemClickable( item ) || ! onClickItem ) { return { className }; } diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 861dc53404f914..0bce8b8cf2c08a 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -510,7 +510,7 @@ export interface ViewBaseProps< Item > { onChangeSelection: SetSelection; selection: string[]; setOpenedFilter: ( fieldId: string ) => void; - onClickItem: ( item: Item ) => void; + onClickItem?: ( item: Item ) => void; isItemClickable: ( item: Item ) => boolean; view: View; } From 340d617fa5cdab9b9402960de32c6496ef563d1d Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 2 Dec 2024 13:31:54 +0100 Subject: [PATCH 1797/1908] [mini] drag and drop: fix misplaced drop indicator (#67434) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../block-editor/src/components/block-popover/inbetween.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/block-editor/src/components/block-popover/inbetween.js b/packages/block-editor/src/components/block-popover/inbetween.js index 2ed9ee0bcb284f..1d7c1766732409 100644 --- a/packages/block-editor/src/components/block-popover/inbetween.js +++ b/packages/block-editor/src/components/block-popover/inbetween.js @@ -148,6 +148,10 @@ function BlockPopoverInbetween( { ? nextRect.left - previousRect.right : 0; } + + // Avoid a negative width which happens when the next rect + // is on the next line. + width = Math.max( width, 0 ); } return new window.DOMRect( left, top, width, height ); From c517e410017f4d65a7c6f03a31c5c2fa15cbbd65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= <grzegorz@gziolo.pl> Date: Mon, 2 Dec 2024 13:32:53 +0100 Subject: [PATCH 1798/1908] Extensibility: Make Block Bindings work with `editor.BlockEdit` hook (#67370) * Block Bindings: Move the place when the attributes get overriden * Fix failing unit tests * Wrap Edit with bindings logic only when the block supports it * Extend the test plugin with `editor.BlockEdit` filter * Add a new test covering the extensibility inside inspector controls * Fix the issue with missing context established by sources Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> --- .../src/components/block-edit/edit.js | 12 +- .../with-block-bindings-support.js} | 103 ++++-------------- .../block-list/use-block-props/index.js | 2 +- .../src/components/rich-text/index.js | 2 +- .../block-editor/src/hooks/block-bindings.js | 10 +- packages/block-editor/src/hooks/index.js | 1 - .../block-editor/src/utils/block-bindings.js | 37 +++++++ packages/e2e-tests/plugins/block-bindings.php | 6 +- .../e2e-tests/plugins/block-bindings/index.js | 45 ++++++++ .../various/block-bindings/post-meta.spec.js | 41 +++++++ 10 files changed, 165 insertions(+), 94 deletions(-) rename packages/block-editor/src/{hooks/use-bindings-attributes.js => components/block-edit/with-block-bindings-support.js} (73%) diff --git a/packages/block-editor/src/components/block-edit/edit.js b/packages/block-editor/src/components/block-edit/edit.js index 83d0e3f406f829..6b1ddd86f4c76e 100644 --- a/packages/block-editor/src/components/block-edit/edit.js +++ b/packages/block-editor/src/components/block-edit/edit.js @@ -18,6 +18,8 @@ import { useContext, useMemo } from '@wordpress/element'; * Internal dependencies */ import BlockContext from '../block-context'; +import { withBlockBindingsSupport } from './with-block-bindings-support'; +import { canBindBlock } from '../../utils/block-bindings'; /** * Default value used for blocks which do not define their own context needs, @@ -47,6 +49,8 @@ const Edit = ( props ) => { const EditWithFilters = withFilters( 'editor.BlockEdit' )( Edit ); +const EditWithFiltersAndBindings = withBlockBindingsSupport( EditWithFilters ); + const EditWithGeneratedProps = ( props ) => { const { attributes = {}, name } = props; const blockType = getBlockType( name ); @@ -67,8 +71,12 @@ const EditWithGeneratedProps = ( props ) => { return null; } + const EditComponent = canBindBlock( name ) + ? EditWithFiltersAndBindings + : EditWithFilters; + if ( blockType.apiVersion > 1 ) { - return <EditWithFilters { ...props } context={ context } />; + return <EditComponent { ...props } context={ context } />; } // Generate a class name for the block's editable form. @@ -82,7 +90,7 @@ const EditWithGeneratedProps = ( props ) => { ); return ( - <EditWithFilters + <EditComponent { ...props } context={ context } className={ className } diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/components/block-edit/with-block-bindings-support.js similarity index 73% rename from packages/block-editor/src/hooks/use-bindings-attributes.js rename to packages/block-editor/src/components/block-edit/with-block-bindings-support.js index fdc617fda20c05..0529c019b8deec 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/components/block-edit/with-block-bindings-support.js @@ -5,31 +5,19 @@ import { store as blocksStore } from '@wordpress/blocks'; import { createHigherOrderComponent } from '@wordpress/compose'; import { useRegistry, useSelect } from '@wordpress/data'; import { useCallback, useMemo, useContext } from '@wordpress/element'; -import { addFilter } from '@wordpress/hooks'; /** * Internal dependencies */ -import isURLLike from '../components/link-control/is-url-like'; -import { unlock } from '../lock-unlock'; -import BlockContext from '../components/block-context'; +import isURLLike from '../link-control/is-url-like'; +import { unlock } from '../../lock-unlock'; +import BlockContext from '../block-context'; +import { + BLOCK_BINDINGS_ALLOWED_BLOCKS, + canBindAttribute, +} from '../../utils/block-bindings'; /** @typedef {import('@wordpress/compose').WPHigherOrderComponent} WPHigherOrderComponent */ -/** @typedef {import('@wordpress/blocks').WPBlockSettings} WPBlockSettings */ - -/** - * Given a binding of block attributes, returns a higher order component that - * overrides its `attributes` and `setAttributes` props to sync any changes needed. - * - * @return {WPHigherOrderComponent} Higher-order component. - */ - -const BLOCK_BINDINGS_ALLOWED_BLOCKS = { - 'core/paragraph': [ 'content' ], - 'core/heading': [ 'content' ], - 'core/image': [ 'id', 'url', 'title', 'alt' ], - 'core/button': [ 'url', 'text', 'linkTarget', 'rel' ], -}; const DEFAULT_ATTRIBUTE = '__default'; @@ -67,36 +55,12 @@ function replacePatternOverrideDefaultBindings( blockName, bindings ) { } /** - * Based on the given block name, - * check if it is possible to bind the block. - * - * @param {string} blockName - The block name. - * @return {boolean} Whether it is possible to bind the block to sources. - */ -export function canBindBlock( blockName ) { - return blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS; -} - -/** - * Based on the given block name and attribute name, - * check if it is possible to bind the block attribute. + * Given a binding of block attributes, returns a higher order component that + * overrides its `attributes` and `setAttributes` props to sync any changes needed. * - * @param {string} blockName - The block name. - * @param {string} attributeName - The attribute name. - * @return {boolean} Whether it is possible to bind the block attribute. + * @return {WPHigherOrderComponent} Higher-order component. */ -export function canBindAttribute( blockName, attributeName ) { - return ( - canBindBlock( blockName ) && - BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ].includes( attributeName ) - ); -} - -export function getBindableAttributes( blockName ) { - return BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ]; -} - -export const withBlockBindingSupport = createHigherOrderComponent( +export const withBlockBindingsSupport = createHigherOrderComponent( ( BlockEdit ) => ( props ) => { const registry = useRegistry(); const blockContext = useContext( BlockContext ); @@ -108,9 +72,9 @@ export const withBlockBindingSupport = createHigherOrderComponent( () => replacePatternOverrideDefaultBindings( name, - props.attributes.metadata?.bindings + props.attributes?.metadata?.bindings ), - [ props.attributes.metadata?.bindings, name ] + [ props.attributes?.metadata?.bindings, name ] ); // While this hook doesn't directly call any selectors, `useSelect` is @@ -196,7 +160,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( const hasParentPattern = !! updatedContext[ 'pattern/overrides' ]; const hasPatternOverridesDefaultBinding = - props.attributes.metadata?.bindings?.[ DEFAULT_ATTRIBUTE ] + props.attributes?.metadata?.bindings?.[ DEFAULT_ATTRIBUTE ] ?.source === 'core/pattern-overrides'; const _setAttributes = useCallback( @@ -283,40 +247,13 @@ export const withBlockBindingSupport = createHigherOrderComponent( ); return ( - <> - <BlockEdit - { ...props } - attributes={ { ...props.attributes, ...boundAttributes } } - setAttributes={ _setAttributes } - context={ { ...context, ...updatedContext } } - /> - </> + <BlockEdit + { ...props } + attributes={ { ...props.attributes, ...boundAttributes } } + setAttributes={ _setAttributes } + context={ { ...context, ...updatedContext } } + /> ); }, 'withBlockBindingSupport' ); - -/** - * Filters a registered block's settings to enhance a block's `edit` component - * to upgrade bound attributes. - * - * @param {WPBlockSettings} settings - Registered block settings. - * @param {string} name - Block name. - * @return {WPBlockSettings} Filtered block settings. - */ -function shimAttributeSource( settings, name ) { - if ( ! canBindBlock( name ) ) { - return settings; - } - - return { - ...settings, - edit: withBlockBindingSupport( settings.edit ), - }; -} - -addFilter( - 'blocks.registerBlockType', - 'core/editor/custom-sources-backwards-compatibility/shim-attribute-source', - shimAttributeSource -); diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index 4696149dc38751..7e50b75e1b9564 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -29,7 +29,7 @@ import { useBlockRefProvider } from './use-block-refs'; import { useIntersectionObserver } from './use-intersection-observer'; import { useScrollIntoView } from './use-scroll-into-view'; import { useFlashEditableBlocks } from '../../use-flash-editable-blocks'; -import { canBindBlock } from '../../../hooks/use-bindings-attributes'; +import { canBindBlock } from '../../../utils/block-bindings'; import { useFirefoxDraggableCompatibility } from './use-firefox-draggable-compatibility'; /** diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index bc8eca6ea94d05..768ffbb0cdd2dc 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -39,7 +39,7 @@ import FormatEdit from './format-edit'; import { getAllowedFormats } from './utils'; import { Content, valueToHTMLString } from './content'; import { withDeprecations } from './with-deprecations'; -import { canBindBlock } from '../../hooks/use-bindings-attributes'; +import { canBindBlock } from '../../utils/block-bindings'; import BlockContext from '../block-context'; export const keyboardShortcutContext = createContext(); diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index e10696cc1257d7..cec80dffaeaa16 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -23,15 +23,15 @@ import { useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies */ -import { - canBindAttribute, - getBindableAttributes, -} from '../hooks/use-bindings-attributes'; import { unlock } from '../lock-unlock'; import InspectorControls from '../components/inspector-controls'; import BlockContext from '../components/block-context'; import { useBlockEditContext } from '../components/block-edit'; -import { useBlockBindingsUtils } from '../utils/block-bindings'; +import { + canBindAttribute, + getBindableAttributes, + useBlockBindingsUtils, +} from '../utils/block-bindings'; import { store as blockEditorStore } from '../store'; const { Menu } = unlock( componentsPrivateApis ); diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index 66ff60b691b66f..7f9b29376ad1fb 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -32,7 +32,6 @@ import './metadata'; import blockHooks from './block-hooks'; import blockBindingsPanel from './block-bindings'; import './block-renaming'; -import './use-bindings-attributes'; import './grid-visualizer'; createBlockEditFilter( diff --git a/packages/block-editor/src/utils/block-bindings.js b/packages/block-editor/src/utils/block-bindings.js index dcf80d985473b2..82f0dff53531a4 100644 --- a/packages/block-editor/src/utils/block-bindings.js +++ b/packages/block-editor/src/utils/block-bindings.js @@ -13,6 +13,43 @@ function isObjectEmpty( object ) { return ! object || Object.keys( object ).length === 0; } +export const BLOCK_BINDINGS_ALLOWED_BLOCKS = { + 'core/paragraph': [ 'content' ], + 'core/heading': [ 'content' ], + 'core/image': [ 'id', 'url', 'title', 'alt' ], + 'core/button': [ 'url', 'text', 'linkTarget', 'rel' ], +}; + +/** + * Based on the given block name, + * check if it is possible to bind the block. + * + * @param {string} blockName - The block name. + * @return {boolean} Whether it is possible to bind the block to sources. + */ +export function canBindBlock( blockName ) { + return blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS; +} + +/** + * Based on the given block name and attribute name, + * check if it is possible to bind the block attribute. + * + * @param {string} blockName - The block name. + * @param {string} attributeName - The attribute name. + * @return {boolean} Whether it is possible to bind the block attribute. + */ +export function canBindAttribute( blockName, attributeName ) { + return ( + canBindBlock( blockName ) && + BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ].includes( attributeName ) + ); +} + +export function getBindableAttributes( blockName ) { + return BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ]; +} + /** * Contains utils to update the block `bindings` metadata. * diff --git a/packages/e2e-tests/plugins/block-bindings.php b/packages/e2e-tests/plugins/block-bindings.php index b86673c2c523d0..1fd6d8468c77db 100644 --- a/packages/e2e-tests/plugins/block-bindings.php +++ b/packages/e2e-tests/plugins/block-bindings.php @@ -41,7 +41,11 @@ function gutenberg_test_block_bindings_registration() { plugins_url( 'block-bindings/index.js', __FILE__ ), array( 'wp-blocks', - 'wp-private-apis', + 'wp-block-editor', + 'wp-components', + 'wp-compose', + 'wp-element', + 'wp-hooks', ), filemtime( plugin_dir_path( __FILE__ ) . 'block-bindings/index.js' ), true diff --git a/packages/e2e-tests/plugins/block-bindings/index.js b/packages/e2e-tests/plugins/block-bindings/index.js index 5c364257caed19..63c463e197fa8a 100644 --- a/packages/e2e-tests/plugins/block-bindings/index.js +++ b/packages/e2e-tests/plugins/block-bindings/index.js @@ -1,4 +1,9 @@ const { registerBlockBindingsSource } = wp.blocks; +const { InspectorControls } = wp.blockEditor; +const { PanelBody, TextControl } = wp.components; +const { createHigherOrderComponent } = wp.compose; +const { createElement: el, Fragment } = wp.element; +const { addFilter } = wp.hooks; const { fieldsList } = window.testingBindings || {}; const getValues = ( { bindings } ) => { @@ -46,3 +51,43 @@ registerBlockBindingsSource( { getValues, canUserEditValue: () => true, } ); + +const withBlockBindingsInspectorControl = createHigherOrderComponent( + ( BlockEdit ) => { + return ( props ) => { + if ( ! props.attributes?.metadata?.bindings?.content ) { + return el( BlockEdit, props ); + } + + return el( + Fragment, + {}, + el( BlockEdit, props ), + el( + InspectorControls, + {}, + el( + PanelBody, + { title: 'Bindings' }, + el( TextControl, { + __next40pxDefaultSize: true, + __nextHasNoMarginBottom: true, + label: 'Content', + value: props.attributes.content, + onChange: ( content ) => + props.setAttributes( { + content, + } ), + } ) + ) + ) + ); + }; + } +); + +addFilter( + 'editor.BlockEdit', + 'testing/bindings-inspector-control', + withBlockBindingsInspectorControl +); diff --git a/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js b/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js index 32334bfc777f2a..318707e22f098d 100644 --- a/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js +++ b/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js @@ -524,6 +524,47 @@ test.describe( 'Post Meta source', () => { previewPage.locator( '#connected-paragraph' ) ).toHaveText( 'new value' ); } ); + + test( 'should be possible to edit the value of the connected custom fields in the inspector control registered by the plugin', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + anchor: 'connected-paragraph', + content: 'fallback content', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { + key: 'movie_field', + }, + }, + }, + }, + }, + } ); + const contentInput = page.getByRole( 'textbox', { + name: 'Content', + } ); + await expect( contentInput ).toHaveValue( + 'Movie field default value' + ); + await contentInput.fill( 'new value' ); + // Check that the paragraph content attribute didn't change. + const [ paragraphBlockObject ] = await editor.getBlocks(); + expect( paragraphBlockObject.attributes.content ).toBe( + 'fallback content' + ); + // Check the value of the custom field is being updated by visiting the frontend. + const previewPage = await editor.openPreviewPage(); + await expect( + previewPage.locator( '#connected-paragraph' ) + ).toHaveText( 'new value' ); + } ); + test( 'should be possible to connect movie fields through the attributes panel', async ( { editor, page, From d3f344fe6193d7cd86e03e7a00770032e7919ab4 Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Mon, 2 Dec 2024 13:17:45 +0000 Subject: [PATCH 1799/1908] Prefer exact matches in Link Search results sorting (#67367) * Weight towards exact matches * Add additional test coverage Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: ironprogrammer <ironprogrammer@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- .../__experimental-fetch-link-suggestions.ts | 25 +++++++++++-- .../__experimental-fetch-link-suggestions.js | 37 +++++++++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/packages/core-data/src/fetch/__experimental-fetch-link-suggestions.ts b/packages/core-data/src/fetch/__experimental-fetch-link-suggestions.ts index e1a166ee272dbe..29012197589035 100644 --- a/packages/core-data/src/fetch/__experimental-fetch-link-suggestions.ts +++ b/packages/core-data/src/fetch/__experimental-fetch-link-suggestions.ts @@ -270,12 +270,29 @@ export function sortResults( results: SearchResult[], search: string ) { for ( const result of results ) { if ( result.title ) { const titleTokens = tokenize( result.title ); - const matchingTokens = titleTokens.filter( ( titleToken ) => - searchTokens.some( ( searchToken ) => - titleToken.includes( searchToken ) + const exactMatchingTokens = titleTokens.filter( ( titleToken ) => + searchTokens.some( + ( searchToken ) => titleToken === searchToken ) ); - scores[ result.id ] = matchingTokens.length / titleTokens.length; + const subMatchingTokens = titleTokens.filter( ( titleToken ) => + searchTokens.some( + ( searchToken ) => + titleToken !== searchToken && + titleToken.includes( searchToken ) + ) + ); + + // The score is a combination of exact matches and sub-matches. + // More weight is given to exact matches, as they are more relevant (e.g. "cat" vs "caterpillar"). + // Diving by the total number of tokens in the title normalizes the score and skews + // the results towards shorter titles. + const exactMatchScore = + ( exactMatchingTokens.length / titleTokens.length ) * 10; + + const subMatchScore = subMatchingTokens.length / titleTokens.length; + + scores[ result.id ] = exactMatchScore + subMatchScore; } else { scores[ result.id ] = 0; } diff --git a/packages/core-data/src/fetch/test/__experimental-fetch-link-suggestions.js b/packages/core-data/src/fetch/test/__experimental-fetch-link-suggestions.js index 6878c74332c3d7..ad0014ff86ecb8 100644 --- a/packages/core-data/src/fetch/test/__experimental-fetch-link-suggestions.js +++ b/packages/core-data/src/fetch/test/__experimental-fetch-link-suggestions.js @@ -393,6 +393,43 @@ describe( 'sortResults', () => { 6, ] ); } ); + + it( 'orders results to prefer direct matches over sub matches', () => { + const results = [ + { + id: 1, + title: 'News', + url: 'http://wordpress.local/news/', + type: 'page', + kind: 'post-type', + }, + { + id: 2, + title: 'Newspaper', + url: 'http://wordpress.local/newspaper/', + type: 'page', + kind: 'post-type', + }, + { + id: 3, + title: 'News Flash News', + url: 'http://wordpress.local/news-flash-news/', + type: 'page', + kind: 'post-type', + }, + { + id: 4, + title: 'News', + url: 'http://wordpress.local/news-2/', + type: 'page', + kind: 'post-type', + }, + ]; + const order = sortResults( results, 'News' ).map( + ( result ) => result.id + ); + expect( order ).toEqual( [ 1, 4, 3, 2 ] ); + } ); } ); describe( 'tokenize', () => { From cd26001761b5f93143671ce1505b25732c51692e Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Mon, 2 Dec 2024 05:51:31 -0800 Subject: [PATCH 1800/1908] =?UTF-8?q?Fix=20Meta=20boxes=20saving=20when=20?= =?UTF-8?q?they=E2=80=99re=20not=20present=20(#67254)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initialize meta boxes whether or not they’re visible * Add hook for initialization of meta boxes * Minimize hook for meta boxes initialization * Name the export Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: enricobattocchi <lopo@git.wordpress.org> --- .../edit-post/src/components/layout/index.js | 13 ++++--- .../src/components/meta-boxes/index.js | 37 ++----------------- .../meta-boxes/use-meta-box-initialization.js | 32 ++++++++++++++++ 3 files changed, 43 insertions(+), 39 deletions(-) create mode 100644 packages/edit-post/src/components/meta-boxes/use-meta-box-initialization.js diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 5dcbfa2c82cea1..b8061571ec66cc 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -74,6 +74,7 @@ import useEditPostCommands from '../../commands/use-commands'; import { usePaddingAppender } from './use-padding-appender'; import { useShouldIframe } from './use-should-iframe'; import useNavigateToEntityRecord from '../../hooks/use-navigate-to-entity-record'; +import { useMetaBoxInitialization } from '../meta-boxes/use-meta-box-initialization'; const { getLayoutStyles } = unlock( blockEditorPrivateApis ); const { useCommands } = unlock( coreCommandsPrivateApis ); @@ -413,6 +414,8 @@ function Layout( { const { isZoomOut } = unlock( select( blockEditorStore ) ); const { getEditorMode, getRenderingMode } = select( editorStore ); const isRenderingPostOnly = getRenderingMode() === 'post-only'; + const isNotDesignPostType = + ! DESIGN_POST_TYPES.includes( currentPostType ); return { mode: getEditorMode(), @@ -423,9 +426,7 @@ function Layout( { !! select( blockEditorStore ).getBlockSelectionStart(), showIconLabels: get( 'core', 'showIconLabels' ), isDistractionFree: get( 'core', 'distractionFree' ), - showMetaBoxes: - ! DESIGN_POST_TYPES.includes( currentPostType ) && - ! isZoomOut(), + showMetaBoxes: isNotDesignPostType && ! isZoomOut(), isWelcomeGuideVisible: isFeatureActive( 'welcomeGuide' ), templateId: supportsTemplateMode && @@ -435,9 +436,7 @@ function Layout( { ? getTemplateId( currentPostType, currentPostId ) : null, enablePaddingAppender: - ! isZoomOut() && - isRenderingPostOnly && - ! DESIGN_POST_TYPES.includes( currentPostType ), + ! isZoomOut() && isRenderingPostOnly && isNotDesignPostType, }; }, [ @@ -447,6 +446,8 @@ function Layout( { settings.supportsTemplateMode, ] ); + useMetaBoxInitialization( hasActiveMetaboxes ); + const [ paddingAppenderRef, paddingStyle ] = usePaddingAppender( enablePaddingAppender ); diff --git a/packages/edit-post/src/components/meta-boxes/index.js b/packages/edit-post/src/components/meta-boxes/index.js index 14728c97cf6b68..fdc74a5df4ce95 100644 --- a/packages/edit-post/src/components/meta-boxes/index.js +++ b/packages/edit-post/src/components/meta-boxes/index.js @@ -1,9 +1,7 @@ /** * WordPress dependencies */ -import { useSelect, useRegistry } from '@wordpress/data'; -import { useEffect } from '@wordpress/element'; -import { store as editorStore } from '@wordpress/editor'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -13,38 +11,11 @@ import MetaBoxVisibility from './meta-box-visibility'; import { store as editPostStore } from '../../store'; export default function MetaBoxes( { location } ) { - const registry = useRegistry(); - const { metaBoxes, areMetaBoxesInitialized, isEditorReady } = useSelect( - ( select ) => { - const { __unstableIsEditorReady } = select( editorStore ); - const { - getMetaBoxesPerLocation, - areMetaBoxesInitialized: _areMetaBoxesInitialized, - } = select( editPostStore ); - return { - metaBoxes: getMetaBoxesPerLocation( location ), - areMetaBoxesInitialized: _areMetaBoxesInitialized(), - isEditorReady: __unstableIsEditorReady(), - }; - }, - [ location ] + const metaBoxes = useSelect( + ( select ) => + select( editPostStore ).getMetaBoxesPerLocation[ location ] ); - const hasMetaBoxes = !! metaBoxes?.length; - - // When editor is ready, initialize postboxes (wp core script) and metabox - // saving. This initializes all meta box locations, not just this specific - // one. - useEffect( () => { - if ( isEditorReady && hasMetaBoxes && ! areMetaBoxesInitialized ) { - registry.dispatch( editPostStore ).initializeMetaBoxes(); - } - }, [ isEditorReady, hasMetaBoxes, areMetaBoxesInitialized ] ); - - if ( ! areMetaBoxesInitialized ) { - return null; - } - return ( <> { ( metaBoxes ?? [] ).map( ( { id } ) => ( diff --git a/packages/edit-post/src/components/meta-boxes/use-meta-box-initialization.js b/packages/edit-post/src/components/meta-boxes/use-meta-box-initialization.js new file mode 100644 index 00000000000000..4309d85e3c22bf --- /dev/null +++ b/packages/edit-post/src/components/meta-boxes/use-meta-box-initialization.js @@ -0,0 +1,32 @@ +/** + * WordPress dependencies + */ +import { useDispatch, useSelect } from '@wordpress/data'; +import { store as editorStore } from '@wordpress/editor'; +import { useEffect } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { store as editPostStore } from '../../store'; + +/** + * Initializes WordPress `postboxes` script and the logic for saving meta boxes. + * + * @param { boolean } enabled + */ +export const useMetaBoxInitialization = ( enabled ) => { + const isEnabledAndEditorReady = useSelect( + ( select ) => + enabled && select( editorStore ).__unstableIsEditorReady(), + [ enabled ] + ); + const { initializeMetaBoxes } = useDispatch( editPostStore ); + // The effect has to rerun when the editor is ready because initializeMetaBoxes + // will noop until then. + useEffect( () => { + if ( isEnabledAndEditorReady ) { + initializeMetaBoxes(); + } + }, [ isEnabledAndEditorReady, initializeMetaBoxes ] ); +}; From d0c372c881cb7d68bf56703df58f057614817c02 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Mon, 2 Dec 2024 15:06:19 +0100 Subject: [PATCH 1801/1908] Fix write mode persisting after disabling the experiment Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> --- packages/block-editor/src/store/selectors.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 75c43770f7e175..dc90f351732524 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -3041,9 +3041,7 @@ export const getBlockEditingMode = createRegistrySelector( clientId = ''; } - const isNavMode = - select( preferencesStore )?.get( 'core', 'editorTool' ) === - 'navigation'; + const isNavMode = isNavigationMode( state ); // If the editor is currently not in navigation mode, check if the clientId // has an editing mode set in the regular derived map. From 65fa4f3b0273afd7a7b578614a6e9ffd80d05de5 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Mon, 2 Dec 2024 20:11:50 +0530 Subject: [PATCH 1802/1908] NumberControl: Deprecate 36px default size (#66730) * Add the deprecation for 36px default size to number control * Add the changelog for the deprecation * Update unit test and supress warning for 40px default size warning from child component * Add the deperection changelog to unreleased section and updated the component to use __next40pxDefaultSize for NumberControl * Refactor the test for NumberControl component to reduce changes * Update box control files to use supress warning prop before default 40px prop * Supress the console warning for deprecation message from child component * Addressed the feedbacks on the PR and updated the component based on that --------- Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../src/components/line-height-control/index.js | 1 + packages/components/CHANGELOG.md | 1 + packages/components/src/angle-picker-control/index.tsx | 2 +- .../components/src/color-picker/input-with-slider.tsx | 2 +- packages/components/src/number-control/README.md | 3 ++- packages/components/src/number-control/index.tsx | 9 +++++++++ .../src/number-control/stories/index.story.tsx | 1 + packages/components/src/number-control/test/index.tsx | 6 +++++- packages/components/src/number-control/types.ts | 7 +++++++ packages/components/src/range-control/index.tsx | 1 + packages/components/src/unit-control/index.tsx | 1 + 11 files changed, 30 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/line-height-control/index.js b/packages/block-editor/src/components/line-height-control/index.js index b2c99c03f87840..e6af602c2875ae 100644 --- a/packages/block-editor/src/components/line-height-control/index.js +++ b/packages/block-editor/src/components/line-height-control/index.js @@ -93,6 +93,7 @@ const LineHeightControl = ( { <div className="block-editor-line-height-control"> <NumberControl { ...otherProps } + __shouldNotWarnDeprecated36pxSize __next40pxDefaultSize={ __next40pxDefaultSize } __unstableInputWidth={ __unstableInputWidth } __unstableStateReducer={ stateReducer } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index c9295e7ef861e0..748525d6d9c15e 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,7 @@ - `BoxControl`: Passive deprecate `onMouseOver`/`onMouseOut`. Pass to the `inputProps` prop instead ([#67332](https://github.com/WordPress/gutenberg/pull/67332)). - `BoxControl`: Deprecate 36px default size ([#66704](https://github.com/WordPress/gutenberg/pull/66704)). +- `NumberControl`: Deprecate 36px default size ([#66730](https://github.com/WordPress/gutenberg/pull/66730)). - `UnitControl`: Deprecate 36px default size ([#66791](https://github.com/WordPress/gutenberg/pull/66791)). ### Enhancements diff --git a/packages/components/src/angle-picker-control/index.tsx b/packages/components/src/angle-picker-control/index.tsx index b824660fddb134..9c436c36caf660 100644 --- a/packages/components/src/angle-picker-control/index.tsx +++ b/packages/components/src/angle-picker-control/index.tsx @@ -57,12 +57,12 @@ function UnforwardedAnglePickerControl( <Flex { ...restProps } ref={ ref } className={ classes } gap={ 2 }> <FlexBlock> <NumberControl + __next40pxDefaultSize label={ label } className="components-angle-picker-control__input-field" max={ 360 } min={ 0 } onChange={ handleOnNumberChange } - size="__unstable-large" step="1" value={ value } spinControls="none" diff --git a/packages/components/src/color-picker/input-with-slider.tsx b/packages/components/src/color-picker/input-with-slider.tsx index 5e08fa42daf80e..221a9289f7450e 100644 --- a/packages/components/src/color-picker/input-with-slider.tsx +++ b/packages/components/src/color-picker/input-with-slider.tsx @@ -31,6 +31,7 @@ export const InputWithSlider = ( { return ( <HStack spacing={ 4 }> <NumberControlWrapper + __next40pxDefaultSize min={ min } max={ max } label={ label } @@ -45,7 +46,6 @@ export const InputWithSlider = ( { </InputControlPrefixWrapper> } spinControls="none" - size="__unstable-large" /> <RangeControl __nextHasNoMarginBottom diff --git a/packages/components/src/number-control/README.md b/packages/components/src/number-control/README.md index 8421691296e90a..486092790548ee 100644 --- a/packages/components/src/number-control/README.md +++ b/packages/components/src/number-control/README.md @@ -16,6 +16,7 @@ const Example = () => { return ( <NumberControl + __next40pxDefaultSize isShiftStepEnabled={ true } onChange={ setValue } shiftStep={ 10 } @@ -146,4 +147,4 @@ Start opting into the larger default height that will become the default size in - Type: `Boolean` - Required: No -- Default: `false` \ No newline at end of file +- Default: `false` diff --git a/packages/components/src/number-control/index.tsx b/packages/components/src/number-control/index.tsx index 5c846aaafc1e02..efa84879b8ff3c 100644 --- a/packages/components/src/number-control/index.tsx +++ b/packages/components/src/number-control/index.tsx @@ -26,6 +26,7 @@ import { HStack } from '../h-stack'; import { Spacer } from '../spacer'; import { useCx } from '../utils'; import { useDeprecated36pxDefaultSizeProp } from '../utils/use-deprecated-props'; +import { maybeWarnDeprecated36pxSize } from '../utils/deprecated-36px-size'; const noop = () => {}; @@ -53,9 +54,17 @@ function UnforwardedNumberControl( size = 'default', suffix, onChange = noop, + __shouldNotWarnDeprecated36pxSize, ...restProps } = useDeprecated36pxDefaultSizeProp< NumberControlProps >( props ); + maybeWarnDeprecated36pxSize( { + componentName: 'NumberControl', + size, + __next40pxDefaultSize: restProps.__next40pxDefaultSize, + __shouldNotWarnDeprecated36pxSize, + } ); + if ( hideHTMLArrows ) { deprecated( 'wp.components.NumberControl hideHTMLArrows prop ', { alternative: 'spinControls="none"', diff --git a/packages/components/src/number-control/stories/index.story.tsx b/packages/components/src/number-control/stories/index.story.tsx index 3feb0d63eadc2a..8710839fea6ea5 100644 --- a/packages/components/src/number-control/stories/index.story.tsx +++ b/packages/components/src/number-control/stories/index.story.tsx @@ -62,4 +62,5 @@ const Template: StoryFn< typeof NumberControl > = ( { export const Default = Template.bind( {} ); Default.args = { label: 'Value', + __next40pxDefaultSize: true, }; diff --git a/packages/components/src/number-control/test/index.tsx b/packages/components/src/number-control/test/index.tsx index 3cf3368f1636ba..bf97b520673ea4 100644 --- a/packages/components/src/number-control/test/index.tsx +++ b/packages/components/src/number-control/test/index.tsx @@ -12,9 +12,13 @@ import { useState } from '@wordpress/element'; /** * Internal dependencies */ -import NumberControl from '..'; +import _NumberControl from '..'; import type { NumberControlProps } from '../types'; +const NumberControl = ( + props: React.ComponentProps< typeof _NumberControl > +) => <_NumberControl __next40pxDefaultSize { ...props } />; + function StatefulNumberControl( props: NumberControlProps ) { const [ value, setValue ] = useState( props.value ); const handleOnChange = ( v: string | undefined ) => setValue( v ); diff --git a/packages/components/src/number-control/types.ts b/packages/components/src/number-control/types.ts index 8d198e777bd557..2a0fbf402d3569 100644 --- a/packages/components/src/number-control/types.ts +++ b/packages/components/src/number-control/types.ts @@ -91,4 +91,11 @@ export type NumberControlProps = Omit< * The value of the input. */ value?: number | string; + /** + * Do not throw a warning for the deprecated 36px default size. + * For internal components of other components that already throw the warning. + * + * @ignore + */ + __shouldNotWarnDeprecated36pxSize?: boolean; }; diff --git a/packages/components/src/range-control/index.tsx b/packages/components/src/range-control/index.tsx index 916571c3ee0e05..89dd8248a1e614 100644 --- a/packages/components/src/range-control/index.tsx +++ b/packages/components/src/range-control/index.tsx @@ -350,6 +350,7 @@ function UnforwardedRangeControl( step={ step } // @ts-expect-error TODO: Investigate if the `null` value is necessary value={ inputSliderValue } + __shouldNotWarnDeprecated36pxSize /> ) } { allowReset && ( diff --git a/packages/components/src/unit-control/index.tsx b/packages/components/src/unit-control/index.tsx index 9845c4eb04ef26..65e1e56cda3b3b 100644 --- a/packages/components/src/unit-control/index.tsx +++ b/packages/components/src/unit-control/index.tsx @@ -224,6 +224,7 @@ function UnforwardedUnitControl( return ( <ValueInput { ...props } + __shouldNotWarnDeprecated36pxSize autoComplete={ autoComplete } className={ classes } disabled={ disabled } From 15d63ce9a27adf8b7f70abf95308493237afdde0 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 2 Dec 2024 16:07:57 +0100 Subject: [PATCH 1803/1908] useEditorTitle: fix wrong request without ID (#67475) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../src/components/editor/use-editor-title.js | 4 ++ test/e2e/specs/site-editor/preload.spec.js | 41 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 test/e2e/specs/site-editor/preload.spec.js diff --git a/packages/edit-site/src/components/editor/use-editor-title.js b/packages/edit-site/src/components/editor/use-editor-title.js index 727b190117e02a..6f0b36f8e3b8b6 100644 --- a/packages/edit-site/src/components/editor/use-editor-title.js +++ b/packages/edit-site/src/components/editor/use-editor-title.js @@ -22,6 +22,10 @@ function useEditorTitle( postType, postId ) { const { getEditedEntityRecord, hasFinishedResolution } = select( coreStore ); + if ( ! postId ) { + return { isLoaded: false }; + } + const _record = getEditedEntityRecord( 'postType', postType, diff --git a/test/e2e/specs/site-editor/preload.spec.js b/test/e2e/specs/site-editor/preload.spec.js new file mode 100644 index 00000000000000..1e93f783a8a91d --- /dev/null +++ b/test/e2e/specs/site-editor/preload.spec.js @@ -0,0 +1,41 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.describe( 'Preload', () => { + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'emptytheme' ); + } ); + + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentyone' ); + } ); + + test( 'Should make no requests before the iframe is loaded', async ( { + page, + admin, + } ) => { + // Do not use `visitSiteEditor` because it waits for the iframe to load. + await admin.visitAdminPage( 'site-editor.php' ); + + const requests = []; + let isLoaded = false; + + page.on( 'request', ( request ) => { + if ( request.resourceType() === 'document' ) { + // The iframe also "requests" a blob document. This is the most + // reliable way to wait for the iframe to start loading. + // `waitForSelector` is always a bit delayed, and we don't want + // to detect requests after the iframe mounts. + isLoaded = true; + } else if ( ! isLoaded && request.resourceType() === 'fetch' ) { + requests.push( request.url() ); + } + } ); + + await page.waitForFunction( ( _isLoaded ) => _isLoaded, [ isLoaded ] ); + + expect( requests ).toEqual( [] ); + } ); +} ); From 6689c778e6bbb9774dd4487c7f1c29e1ffd207f5 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Mon, 2 Dec 2024 17:02:52 +0100 Subject: [PATCH 1804/1908] SlotFill: remove explicit rerender from portal version (#67471) * SlotFill: remove explicit rerender from portal version * Add changelog entry Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../src/slot-fill/bubbles-virtually/fill.tsx | 18 +++++++----------- .../bubbles-virtually/slot-fill-provider.tsx | 15 ++------------- .../src/slot-fill/bubbles-virtually/slot.tsx | 11 ++++------- packages/components/src/slot-fill/types.ts | 7 ++++--- 5 files changed, 18 insertions(+), 34 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 748525d6d9c15e..94dfd1b3c38113 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -22,6 +22,7 @@ - Upgraded `@ariakit/react` (v0.4.13) and `@ariakit/test` (v0.4.5) ([#65907](https://github.com/WordPress/gutenberg/pull/65907)). - Upgraded `@ariakit/react` (v0.4.15) and `@ariakit/test` (v0.4.7) ([#67404](https://github.com/WordPress/gutenberg/pull/67404)). - Exported the `WPCompleter` type as it was being used in block-editor/autocompleters ([#67410](https://github.com/WordPress/gutenberg/pull/67410)). +- `SlotFill`: remove manual rerenders from the portal `Fill` component ([#67471](https://github.com/WordPress/gutenberg/pull/67471)). ### Bug Fixes diff --git a/packages/components/src/slot-fill/bubbles-virtually/fill.tsx b/packages/components/src/slot-fill/bubbles-virtually/fill.tsx index d5287adfab4178..ef7bc94ff540bd 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/fill.tsx +++ b/packages/components/src/slot-fill/bubbles-virtually/fill.tsx @@ -4,7 +4,6 @@ import { useObservableValue } from '@wordpress/compose'; import { useContext, - useReducer, useRef, useEffect, createPortal, @@ -20,18 +19,15 @@ import type { FillComponentProps } from '../types'; export default function Fill( { name, children }: FillComponentProps ) { const registry = useContext( SlotFillContext ); const slot = useObservableValue( registry.slots, name ); - const [ , rerender ] = useReducer( () => [], [] ); - const ref = useRef( { rerender } ); + const instanceRef = useRef( {} ); + // We register fills so we can keep track of their existence. + // Slots can use the `useSlotFills` hook to know if there're already fills + // registered so they can choose to render themselves or not. useEffect( () => { - // We register fills so we can keep track of their existence. - // Some Slot implementations need to know if there're already fills - // registered so they can choose to render themselves or not. - const refValue = ref.current; - registry.registerFill( name, refValue ); - return () => { - registry.unregisterFill( name, refValue ); - }; + const instance = instanceRef.current; + registry.registerFill( name, instance ); + return () => registry.unregisterFill( name, instance ); }, [ registry, name ] ); if ( ! slot || ! slot.ref.current ) { diff --git a/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx b/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx index 1dc5ef35ceccfe..cf692700eef79c 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx +++ b/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx @@ -23,13 +23,7 @@ function createSlotRegistry(): SlotFillBubblesVirtuallyContext { ref, fillProps ) => { - const slot = slots.get( name ); - - slots.set( name, { - ...slot, - ref: ref || slot?.ref, - fillProps: fillProps || slot?.fillProps || {}, - } ); + slots.set( name, { ref, fillProps } ); }; const unregisterSlot: SlotFillBubblesVirtuallyContext[ 'unregisterSlot' ] = @@ -66,12 +60,7 @@ function createSlotRegistry(): SlotFillBubblesVirtuallyContext { return; } - slot.fillProps = fillProps; - const slotFills = fills.get( name ); - if ( slotFills ) { - // Force update fills. - slotFills.forEach( ( fill ) => fill.rerender() ); - } + slots.set( name, { ref, fillProps } ); }; const registerFill: SlotFillBubblesVirtuallyContext[ 'registerFill' ] = ( diff --git a/packages/components/src/slot-fill/bubbles-virtually/slot.tsx b/packages/components/src/slot-fill/bubbles-virtually/slot.tsx index b8ead7fc7ea8ba..e65c055c410a6b 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/slot.tsx +++ b/packages/components/src/slot-fill/bubbles-virtually/slot.tsx @@ -39,8 +39,7 @@ function Slot( ...restProps } = props; - const { registerSlot, unregisterSlot, ...registry } = - useContext( SlotFillContext ); + const registry = useContext( SlotFillContext ); const ref = useRef< HTMLElement >( null ); @@ -54,11 +53,9 @@ function Slot( }, [ fillProps ] ); useLayoutEffect( () => { - registerSlot( name, ref, fillPropsRef.current ); - return () => { - unregisterSlot( name, ref ); - }; - }, [ registerSlot, unregisterSlot, name ] ); + registry.registerSlot( name, ref, fillPropsRef.current ); + return () => registry.unregisterSlot( name, ref ); + }, [ registry, name ] ); useLayoutEffect( () => { registry.updateSlot( name, ref, fillPropsRef.current ); diff --git a/packages/components/src/slot-fill/types.ts b/packages/components/src/slot-fill/types.ts index 15f082cf3f7552..6668057323edd9 100644 --- a/packages/components/src/slot-fill/types.ts +++ b/packages/components/src/slot-fill/types.ts @@ -110,15 +110,16 @@ export type SlotFillProviderProps = { export type SlotRef = RefObject< HTMLElement >; export type Rerenderable = { rerender: () => void }; +export type FillInstance = {}; export type SlotFillBubblesVirtuallyContext = { slots: ObservableMap< SlotKey, { ref: SlotRef; fillProps: FillProps } >; - fills: ObservableMap< SlotKey, Rerenderable[] >; + fills: ObservableMap< SlotKey, FillInstance[] >; registerSlot: ( name: SlotKey, ref: SlotRef, fillProps: FillProps ) => void; unregisterSlot: ( name: SlotKey, ref: SlotRef ) => void; updateSlot: ( name: SlotKey, ref: SlotRef, fillProps: FillProps ) => void; - registerFill: ( name: SlotKey, ref: Rerenderable ) => void; - unregisterFill: ( name: SlotKey, ref: Rerenderable ) => void; + registerFill: ( name: SlotKey, instance: FillInstance ) => void; + unregisterFill: ( name: SlotKey, instance: FillInstance ) => void; /** * This helps the provider know if it's using the default context value or not. From fa10d2fbd3faea76835374d6c850864d103a98c9 Mon Sep 17 00:00:00 2001 From: Andrea Fercia <a.fercia@gmail.com> Date: Mon, 2 Dec 2024 17:07:55 +0100 Subject: [PATCH 1805/1908] Fix EntitiesSavedStates panel dialog props. (#67351) * Fix EntitiesSavedStates panel dialog props. * Remove renderDialog default value. Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: Mayank-Tripathi32 <mayanktripathi32@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../edit-site/src/components/save-panel/index.js | 12 +++++++++--- packages/editor/README.md | 2 +- .../src/components/entities-saved-states/index.js | 15 ++++++--------- .../src/components/post-publish-button/index.js | 2 ++ .../src/components/save-publish-panels/index.js | 6 +++++- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/packages/edit-site/src/components/save-panel/index.js b/packages/edit-site/src/components/save-panel/index.js index 81a0f99557df07..95ec9b9ffc8c46 100644 --- a/packages/edit-site/src/components/save-panel/index.js +++ b/packages/edit-site/src/components/save-panel/index.js @@ -31,7 +31,7 @@ const { EntitiesSavedStatesExtensible, NavigableRegion } = unlock( privateApis ); const { useLocation } = unlock( routerPrivateApis ); -const EntitiesSavedStatesForPreview = ( { onClose } ) => { +const EntitiesSavedStatesForPreview = ( { onClose, renderDialog } ) => { const isDirtyProps = useEntitiesSavedStatesIsDirty(); let activateSaveLabel; if ( isDirtyProps.isDirty ) { @@ -75,14 +75,20 @@ const EntitiesSavedStatesForPreview = ( { onClose } ) => { onSave, saveEnabled: true, saveLabel: activateSaveLabel, + renderDialog, } } /> ); }; -const _EntitiesSavedStates = ( { onClose, renderDialog = undefined } ) => { +const _EntitiesSavedStates = ( { onClose, renderDialog } ) => { if ( isPreviewingTheme() ) { - return <EntitiesSavedStatesForPreview onClose={ onClose } />; + return ( + <EntitiesSavedStatesForPreview + onClose={ onClose } + renderDialog={ renderDialog } + /> + ); } return ( <EntitiesSavedStates close={ onClose } renderDialog={ renderDialog } /> diff --git a/packages/editor/README.md b/packages/editor/README.md index 8b48d773acb268..dd7b53f421a1db 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -401,7 +401,7 @@ _Parameters_ - _props_ `Object`: The component props. - _props.close_ `Function`: The function to close the dialog. -- _props.renderDialog_ `Function`: The function to render the dialog. +- _props.renderDialog_ `boolean`: Whether to render the component with modal dialog behavior. _Returns_ diff --git a/packages/editor/src/components/entities-saved-states/index.js b/packages/editor/src/components/entities-saved-states/index.js index ea05bca522941b..ad584b0df75574 100644 --- a/packages/editor/src/components/entities-saved-states/index.js +++ b/packages/editor/src/components/entities-saved-states/index.js @@ -31,14 +31,11 @@ function identity( values ) { * * @param {Object} props The component props. * @param {Function} props.close The function to close the dialog. - * @param {Function} props.renderDialog The function to render the dialog. + * @param {boolean} props.renderDialog Whether to render the component with modal dialog behavior. * * @return {React.ReactNode} The rendered component. */ -export default function EntitiesSavedStates( { - close, - renderDialog = undefined, -} ) { +export default function EntitiesSavedStates( { close, renderDialog } ) { const isDirtyProps = useIsDirty(); return ( <EntitiesSavedStatesExtensible @@ -58,7 +55,7 @@ export default function EntitiesSavedStates( { * @param {Function} props.onSave Function to call when saving entities. * @param {boolean} props.saveEnabled Flag indicating if save is enabled. * @param {string} props.saveLabel Label for the save button. - * @param {Function} props.renderDialog Function to render a custom dialog. + * @param {boolean} props.renderDialog Whether to render the component with modal dialog behavior. * @param {Array} props.dirtyEntityRecords Array of dirty entity records. * @param {boolean} props.isDirty Flag indicating if there are dirty entities. * @param {Function} props.setUnselectedEntities Function to set unselected entities. @@ -72,7 +69,7 @@ export function EntitiesSavedStatesExtensible( { onSave = identity, saveEnabled: saveEnabledProp = undefined, saveLabel = __( 'Save' ), - renderDialog = undefined, + renderDialog, dirtyEntityRecords, isDirty, setUnselectedEntities, @@ -120,8 +117,8 @@ export function EntitiesSavedStatesExtensible( { return ( <div - ref={ saveDialogRef } - { ...saveDialogProps } + ref={ renderDialog ? saveDialogRef : undefined } + { ...( renderDialog && saveDialogProps ) } className="entities-saved-states__panel" role={ renderDialog ? 'dialog' : undefined } aria-labelledby={ renderDialog ? dialogLabel : undefined } diff --git a/packages/editor/src/components/post-publish-button/index.js b/packages/editor/src/components/post-publish-button/index.js index 71e18a4d6a9c82..4dcd5592d01cb1 100644 --- a/packages/editor/src/components/post-publish-button/index.js +++ b/packages/editor/src/components/post-publish-button/index.js @@ -151,6 +151,7 @@ export class PostPublishButton extends Component { isBusy: ! isAutoSaving && isSaving, variant: 'primary', onClick: this.createOnClick( onClickButton ), + 'aria-haspopup': hasNonPostEntityChanges ? 'dialog' : undefined, }; const toggleProps = { @@ -161,6 +162,7 @@ export class PostPublishButton extends Component { variant: 'primary', size: 'compact', onClick: this.createOnClick( onClickToggle ), + 'aria-haspopup': hasNonPostEntityChanges ? 'dialog' : undefined, }; const componentProps = isToggle ? toggleProps : buttonProps; return ( diff --git a/packages/editor/src/components/save-publish-panels/index.js b/packages/editor/src/components/save-publish-panels/index.js index d95d9f35928906..2a37357e27100e 100644 --- a/packages/editor/src/components/save-publish-panels/index.js +++ b/packages/editor/src/components/save-publish-panels/index.js @@ -88,6 +88,7 @@ export default function SavePublishPanels( { variant="secondary" onClick={ openEntitiesSavedStates } aria-expanded={ false } + aria-haspopup="dialog" disabled={ ! isDirty } accessibleWhenDisabled > @@ -102,7 +103,10 @@ export default function SavePublishPanels( { return ( <> { isEntitiesSavedStatesOpen && ( - <EntitiesSavedStates close={ closeEntitiesSavedStates } /> + <EntitiesSavedStates + close={ closeEntitiesSavedStates } + renderDialog + /> ) } <Slot bubblesVirtually /> { ! isEntitiesSavedStatesOpen && unmountableContent } From 656110814c85d346669dd4fa2c9d3de670d35cbb Mon Sep 17 00:00:00 2001 From: Dave Smith <getdavemail@gmail.com> Date: Mon, 2 Dec 2024 16:39:38 +0000 Subject: [PATCH 1806/1908] Correctly apply current-menu-ancestor class to <li> in Nav block #67169 Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: mrwweb <mrwweb@git.wordpress.org> Co-authored-by: juanfra <juanfra@git.wordpress.org> Co-authored-by: draganescu <andraganescu@git.wordpress.org> Co-authored-by: bph <bph@git.wordpress.org> Co-authored-by: jordesign <jordesign@git.wordpress.org> Co-authored-by: webmandesign <webmandesign@git.wordpress.org> --- packages/block-library/src/navigation-submenu/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/navigation-submenu/index.php b/packages/block-library/src/navigation-submenu/index.php index 92b55e291606e8..d61dbb2426c240 100644 --- a/packages/block-library/src/navigation-submenu/index.php +++ b/packages/block-library/src/navigation-submenu/index.php @@ -222,7 +222,7 @@ function render_block_core_navigation_submenu( $attributes, $content, $block ) { if ( strpos( $inner_blocks_html, 'current-menu-item' ) ) { $tag_processor = new WP_HTML_Tag_Processor( $html ); - while ( $tag_processor->next_tag( array( 'class_name' => 'wp-block-navigation-item__content' ) ) ) { + while ( $tag_processor->next_tag( array( 'class_name' => 'wp-block-navigation-item' ) ) ) { $tag_processor->add_class( 'current-menu-ancestor' ); } $html = $tag_processor->get_updated_html(); From 1d06b35940ef1d255b08f51cf242ed776d0077b0 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 2 Dec 2024 17:55:55 +0100 Subject: [PATCH 1807/1908] Site Editor: Pages: Preload template lookup (#66654) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> --- backport-changelog/6.8/7695.md | 2 ++ lib/compat/wordpress-6.8/preload.php | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/backport-changelog/6.8/7695.md b/backport-changelog/6.8/7695.md index f45b2039e30274..d69a59f2d67d12 100644 --- a/backport-changelog/6.8/7695.md +++ b/backport-changelog/6.8/7695.md @@ -2,3 +2,5 @@ https://github.com/WordPress/wordpress-develop/pull/7695 * https://github.com/WordPress/gutenberg/pull/66631 * https://github.com/WordPress/gutenberg/pull/67465 +* https://github.com/WordPress/gutenberg/pull/66579 +* https://github.com/WordPress/gutenberg/pull/66654 diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php index 494e3ad32ec02e..879e263f5a1892 100644 --- a/lib/compat/wordpress-6.8/preload.php +++ b/lib/compat/wordpress-6.8/preload.php @@ -10,18 +10,26 @@ */ function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { if ( 'core/edit-site' === $context->name ) { - $post_id = null; + $post = null; if ( isset( $_GET['postId'] ) && is_numeric( $_GET['postId'] ) ) { - $post_id = (int) $_GET['postId']; + $post = get_post( (int) $_GET['postId'] ); } if ( isset( $_GET['p'] ) && preg_match( '/^\/page\/(\d+)$/', $_GET['p'], $matches ) ) { - $post_id = (int) $matches[1]; + $post = get_post( (int) $matches[1] ); } - if ( $post_id ) { - $route_for_post = rest_get_route_for_post( $post_id ); + if ( $post ) { + $route_for_post = rest_get_route_for_post( $post ); if ( $route_for_post ) { $paths[] = add_query_arg( 'context', 'edit', $route_for_post ); + if ( 'page' === $post->post_type ) { + $paths[] = add_query_arg( + 'slug', + // @see https://github.com/WordPress/gutenberg/blob/489f6067c623926bce7151a76755bb68d8e22ea7/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js#L139-L140 + 'page-' . $post->post_name, + '/wp/v2/templates/lookup' + ); + } } } From d8a457b56b6671fa25dedf2b40841a13bdabe6f1 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Mon, 2 Dec 2024 19:02:59 +0200 Subject: [PATCH 1808/1908] Block Editor: Animate useScaleCanvas() only when toggling zoomed out mode (#67481) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- .../src/components/iframe/use-scale-canvas.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/iframe/use-scale-canvas.js b/packages/block-editor/src/components/iframe/use-scale-canvas.js index c72266e82e2b0a..2d8cb217a3255c 100644 --- a/packages/block-editor/src/components/iframe/use-scale-canvas.js +++ b/packages/block-editor/src/components/iframe/use-scale-canvas.js @@ -2,7 +2,11 @@ * WordPress dependencies */ import { useEffect, useRef, useCallback } from '@wordpress/element'; -import { useReducedMotion, useResizeObserver } from '@wordpress/compose'; +import { + usePrevious, + useReducedMotion, + useResizeObserver, +} from '@wordpress/compose'; /** * @typedef {Object} TransitionState @@ -280,6 +284,7 @@ export function useScaleCanvas( { transitionFromRef.current = transitionToRef.current; }, [ iframeDocument ] ); + const previousIsZoomedOut = usePrevious( isZoomedOut ); /** * Runs when zoom out mode is toggled, and sets the startAnimation flag * so the animation will start when the next useEffect runs. We _only_ @@ -287,7 +292,7 @@ export function useScaleCanvas( { * changes due to the container resizing. */ useEffect( () => { - if ( ! iframeDocument ) { + if ( ! iframeDocument || previousIsZoomedOut === isZoomedOut ) { return; } @@ -300,7 +305,7 @@ export function useScaleCanvas( { return () => { iframeDocument.documentElement.classList.remove( 'is-zoomed-out' ); }; - }, [ iframeDocument, isZoomedOut ] ); + }, [ iframeDocument, isZoomedOut, previousIsZoomedOut ] ); /** * This handles: From 232d14f33f57fcf6f0c07e52bdb5c52ba8f3dcae Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 3 Dec 2024 02:32:19 +0900 Subject: [PATCH 1809/1908] DropdownMenu: Increase option height to 40px (#67435) * DropdownMenu: Increase option height to 40px * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 3 +++ packages/components/src/dropdown-menu/index.tsx | 1 + packages/components/src/dropdown-menu/style.scss | 2 +- packages/components/src/menu-items-choice/style.scss | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 94dfd1b3c38113..b482a4801c2eaa 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -12,6 +12,9 @@ ### Enhancements - `BorderBoxControl`: Reduce gap value when unlinked ([#67049](https://github.com/WordPress/gutenberg/pull/67049)). +- `DropdownMenu`: Increase option height to 40px ([#67435](https://github.com/WordPress/gutenberg/pull/67435)). +- `MenuItem`: Increase height to 40px ([#67435](https://github.com/WordPress/gutenberg/pull/67435)). +- `MenuItemsChoice`: Increase option height to 40px ([#67435](https://github.com/WordPress/gutenberg/pull/67435)). ### Experimental diff --git a/packages/components/src/dropdown-menu/index.tsx b/packages/components/src/dropdown-menu/index.tsx index 0e4501be4839c0..de83695978c2df 100644 --- a/packages/components/src/dropdown-menu/index.tsx +++ b/packages/components/src/dropdown-menu/index.tsx @@ -164,6 +164,7 @@ function UnconnectedDropdownMenu( dropdownMenuProps: DropdownMenuProps ) { { controlSets?.flatMap( ( controlSet, indexOfSet ) => controlSet.map( ( control, indexOfControl ) => ( <Button + __next40pxDefaultSize key={ [ indexOfSet, indexOfControl, diff --git a/packages/components/src/dropdown-menu/style.scss b/packages/components/src/dropdown-menu/style.scss index 1c716d80410e12..29fd6db18ba283 100644 --- a/packages/components/src/dropdown-menu/style.scss +++ b/packages/components/src/dropdown-menu/style.scss @@ -53,7 +53,7 @@ .components-menu-item__button, .components-menu-item__button.components-button { - min-height: $button-size; + min-height: $button-size-next-default-40px; height: auto; text-align: left; padding-left: $grid-unit-10; diff --git a/packages/components/src/menu-items-choice/style.scss b/packages/components/src/menu-items-choice/style.scss index 383eb4066ba86b..c33ce43301842b 100644 --- a/packages/components/src/menu-items-choice/style.scss +++ b/packages/components/src/menu-items-choice/style.scss @@ -1,5 +1,6 @@ .components-menu-items-choice, .components-menu-items-choice.components-button { + min-height: $button-size-next-default-40px; height: auto; svg { From b61f9136bf4c2a5ec1cb64a354b2c5012c33fcb4 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 3 Dec 2024 02:32:52 +0900 Subject: [PATCH 1810/1908] CustomSelectControl: Deprecate 36px default size (#67441) * CustomSelectControl: Deprecate 36px default size * Add changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../font-appearance-control/index.js | 1 + .../src/components/font-family/index.js | 1 + packages/components/CHANGELOG.md | 1 + .../src/custom-select-control/README.md | 2 ++ .../src/custom-select-control/index.tsx | 9 ++++++++ .../stories/index.story.tsx | 1 + .../src/custom-select-control/test/index.tsx | 22 +++++++++++-------- .../src/custom-select-control/types.ts | 7 ++++++ .../font-size-picker-select.tsx | 1 + 9 files changed, 36 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index 38cb42e394a3bd..f9e8023f93ec69 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -153,6 +153,7 @@ export default function FontAppearanceControl( props ) { { ...otherProps } className="components-font-appearance-control" __next40pxDefaultSize={ __next40pxDefaultSize } + __shouldNotWarnDeprecated36pxSize label={ label } describedBy={ getDescribedBy() } options={ selectOptions } diff --git a/packages/block-editor/src/components/font-family/index.js b/packages/block-editor/src/components/font-family/index.js index 045d4d5c73ed30..e8d0d7ed2dd808 100644 --- a/packages/block-editor/src/components/font-family/index.js +++ b/packages/block-editor/src/components/font-family/index.js @@ -61,6 +61,7 @@ export default function FontFamilyControl( { return ( <CustomSelectControl __next40pxDefaultSize={ __next40pxDefaultSize } + __shouldNotWarnDeprecated36pxSize label={ __( 'Font' ) } value={ value } onChange={ ( { selectedItem } ) => onChange( selectedItem.key ) } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index b482a4801c2eaa..f77065cdf7be23 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,7 @@ - `BoxControl`: Passive deprecate `onMouseOver`/`onMouseOut`. Pass to the `inputProps` prop instead ([#67332](https://github.com/WordPress/gutenberg/pull/67332)). - `BoxControl`: Deprecate 36px default size ([#66704](https://github.com/WordPress/gutenberg/pull/66704)). +- `CustomSelectControl`: Deprecate 36px default size ([#67441](https://github.com/WordPress/gutenberg/pull/67441)). - `NumberControl`: Deprecate 36px default size ([#66730](https://github.com/WordPress/gutenberg/pull/66730)). - `UnitControl`: Deprecate 36px default size ([#66791](https://github.com/WordPress/gutenberg/pull/66791)). diff --git a/packages/components/src/custom-select-control/README.md b/packages/components/src/custom-select-control/README.md index a764a0df133eab..6c175b1fcc5d24 100644 --- a/packages/components/src/custom-select-control/README.md +++ b/packages/components/src/custom-select-control/README.md @@ -41,6 +41,7 @@ function MyCustomSelectControl() { const [ , setFontSize ] = useState(); return ( <CustomSelectControl + __next40pxDefaultSize label="Font Size" options={ options } onChange={ ( { selectedItem } ) => setFontSize( selectedItem ) } @@ -52,6 +53,7 @@ function MyControlledCustomSelectControl() { const [ fontSize, setFontSize ] = useState( options[ 0 ] ); return ( <CustomSelectControl + __next40pxDefaultSize label="Font Size" options={ options } onChange={ ( { selectedItem } ) => setFontSize( selectedItem ) } diff --git a/packages/components/src/custom-select-control/index.tsx b/packages/components/src/custom-select-control/index.tsx index ecd9dc37a8f491..74da8a5c741060 100644 --- a/packages/components/src/custom-select-control/index.tsx +++ b/packages/components/src/custom-select-control/index.tsx @@ -18,6 +18,7 @@ import CustomSelectItem from '../custom-select-control-v2/item'; import * as Styled from '../custom-select-control-v2/styles'; import type { CustomSelectProps, CustomSelectOption } from './types'; import { VisuallyHidden } from '../visually-hidden'; +import { maybeWarnDeprecated36pxSize } from '../utils/deprecated-36px-size'; function useDeprecatedProps< T extends CustomSelectOption >( { __experimentalShowSelectedHint, @@ -56,6 +57,7 @@ function CustomSelectControl< T extends CustomSelectOption >( ) { const { __next40pxDefaultSize = false, + __shouldNotWarnDeprecated36pxSize, describedBy, options, onChange, @@ -66,6 +68,13 @@ function CustomSelectControl< T extends CustomSelectOption >( ...restProps } = useDeprecatedProps( props ); + maybeWarnDeprecated36pxSize( { + componentName: 'CustomSelectControl', + __next40pxDefaultSize, + size, + __shouldNotWarnDeprecated36pxSize, + } ); + const descriptionId = useInstanceId( CustomSelectControl, 'custom-select-control__description' diff --git a/packages/components/src/custom-select-control/stories/index.story.tsx b/packages/components/src/custom-select-control/stories/index.story.tsx index 7c743de58d202d..9d430b639547c6 100644 --- a/packages/components/src/custom-select-control/stories/index.story.tsx +++ b/packages/components/src/custom-select-control/stories/index.story.tsx @@ -63,6 +63,7 @@ const Template: StoryFn< typeof CustomSelectControl > = ( props ) => { export const Default = Template.bind( {} ); Default.args = { + __next40pxDefaultSize: true, label: 'Label', options: [ { diff --git a/packages/components/src/custom-select-control/test/index.tsx b/packages/components/src/custom-select-control/test/index.tsx index b2ac5c19c6ab3f..61d212c26c619e 100644 --- a/packages/components/src/custom-select-control/test/index.tsx +++ b/packages/components/src/custom-select-control/test/index.tsx @@ -13,7 +13,11 @@ import { useState } from '@wordpress/element'; /** * Internal dependencies */ -import UncontrolledCustomSelectControl from '..'; +import _CustomSelectControl from '..'; + +const UncontrolledCustomSelectControl = ( + props: React.ComponentProps< typeof _CustomSelectControl > +) => <_CustomSelectControl __next40pxDefaultSize { ...props } />; const customClassName = 'amber-skies'; const customStyles = { @@ -716,7 +720,7 @@ describe( 'Type checking', () => { const onChange = (): void => {}; - <UncontrolledCustomSelectControl + <_CustomSelectControl label="Label" options={ options } value={ { @@ -726,7 +730,7 @@ describe( 'Type checking', () => { onChange={ onChange } />; - <UncontrolledCustomSelectControl + <_CustomSelectControl label="Label" options={ options } value={ { @@ -736,7 +740,7 @@ describe( 'Type checking', () => { onChange={ onChange } />; - <UncontrolledCustomSelectControl + <_CustomSelectControl label="Label" options={ options } value={ { @@ -748,7 +752,7 @@ describe( 'Type checking', () => { onChange={ onChange } />; - <UncontrolledCustomSelectControl + <_CustomSelectControl label="Label" options={ options } value={ { @@ -764,7 +768,7 @@ describe( 'Type checking', () => { } />; - <UncontrolledCustomSelectControl + <_CustomSelectControl label="Label" options={ optionsReadOnly } value={ { @@ -774,7 +778,7 @@ describe( 'Type checking', () => { onChange={ onChange } />; - <UncontrolledCustomSelectControl + <_CustomSelectControl label="Label" options={ optionsReadOnly } value={ { @@ -785,7 +789,7 @@ describe( 'Type checking', () => { onChange={ onChange } />; - <UncontrolledCustomSelectControl + <_CustomSelectControl label="Label" options={ optionsReadOnly } value={ { @@ -797,7 +801,7 @@ describe( 'Type checking', () => { onChange={ onChange } />; - <UncontrolledCustomSelectControl + <_CustomSelectControl label="Label" options={ optionsReadOnly } value={ { diff --git a/packages/components/src/custom-select-control/types.ts b/packages/components/src/custom-select-control/types.ts index 0cbc2388e79638..dd3db6d3bb0f95 100644 --- a/packages/components/src/custom-select-control/types.ts +++ b/packages/components/src/custom-select-control/types.ts @@ -120,4 +120,11 @@ export type CustomSelectProps< T extends CustomSelectOption > = { * @default false */ __next40pxDefaultSize?: boolean; + /** + * Do not throw a warning for the deprecated 36px default size. + * For internal components of other components that already throw the warning. + * + * @ignore + */ + __shouldNotWarnDeprecated36pxSize?: boolean; }; diff --git a/packages/components/src/font-size-picker/font-size-picker-select.tsx b/packages/components/src/font-size-picker/font-size-picker-select.tsx index 19eaba1cfbecd0..b33c382f3393e4 100644 --- a/packages/components/src/font-size-picker/font-size-picker-select.tsx +++ b/packages/components/src/font-size-picker/font-size-picker-select.tsx @@ -69,6 +69,7 @@ const FontSizePickerSelect = ( props: FontSizePickerSelectProps ) => { return ( <CustomSelectControl __next40pxDefaultSize={ __next40pxDefaultSize } + __shouldNotWarnDeprecated36pxSize className="components-font-size-picker__select" label={ __( 'Font size' ) } hideLabelFromVision From 8d80471126e5c2fa445afb9b74b70e31818c3dbd Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 3 Dec 2024 02:44:02 +0900 Subject: [PATCH 1811/1908] FormFileUpload: Deprecate 36px default size (#67438) * FormFileUpload: Deprecate 36px default size * Add changelog * Tweak descriptions Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 1 + .../components/src/form-file-upload/README.md | 106 ++++++++++-------- .../src/form-file-upload/docs-manifest.json | 5 + .../components/src/form-file-upload/index.tsx | 13 ++- .../form-file-upload/stories/index.story.tsx | 1 + .../src/form-file-upload/test/index.tsx | 6 +- .../components/src/form-file-upload/types.ts | 18 +-- 7 files changed, 92 insertions(+), 58 deletions(-) create mode 100644 packages/components/src/form-file-upload/docs-manifest.json diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index f77065cdf7be23..469d5c9de244e5 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -9,6 +9,7 @@ - `CustomSelectControl`: Deprecate 36px default size ([#67441](https://github.com/WordPress/gutenberg/pull/67441)). - `NumberControl`: Deprecate 36px default size ([#66730](https://github.com/WordPress/gutenberg/pull/66730)). - `UnitControl`: Deprecate 36px default size ([#66791](https://github.com/WordPress/gutenberg/pull/66791)). +- `FormFileUpload`: Deprecate 36px default size ([#67438](https://github.com/WordPress/gutenberg/pull/67438)). ### Enhancements diff --git a/packages/components/src/form-file-upload/README.md b/packages/components/src/form-file-upload/README.md index 4dd8affc5f54a0..c6a7205815de53 100644 --- a/packages/components/src/form-file-upload/README.md +++ b/packages/components/src/form-file-upload/README.md @@ -1,95 +1,105 @@ # FormFileUpload -FormFileUpload is a component that allows users to select files from their local device. +<!-- This file is generated automatically and cannot be edited directly. Make edits via TypeScript types and TSDocs. --> -## Usage +<p class="callout callout-info">See the <a href="https://wordpress.github.io/gutenberg/?path=/docs/components-formfileupload--docs">WordPress Storybook</a> for more detailed, interactive documentation.</p> + +FormFileUpload allows users to select files from their local device. ```jsx import { FormFileUpload } from '@wordpress/components'; const MyFormFileUpload = () => ( - <FormFileUpload - accept="image/*" - onChange={ ( event ) => console.log( event.currentTarget.files ) } - > - Upload - </FormFileUpload> + <FormFileUpload + __next40pxDefaultSize + accept="image/*" + onChange={ ( event ) => console.log( event.currentTarget.files ) } + > + Upload + </FormFileUpload> ); ``` - ## Props -The component accepts the following props. Props not included in this set will be passed to the `Button` component. +### `__next40pxDefaultSize` + +Start opting into the larger default height that will become the default size in a future version. + + - Type: `boolean` + - Required: No + - Default: `false` -### accept +### `accept` -A string passed to `input` element that tells the browser which file types can be upload to the upload by the user use. e.g: `image/*,video/*`. -More information about this string is available in https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Unique_file_type_specifiers. +A string passed to the `input` element that tells the browser which +[file types](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Unique_file_type_specifiers) +can be uploaded by the user. e.g: `image/*,video/*`. -- Type: `String` -- Required: No + - Type: `string` + - Required: No -### children +### `children` Children are passed as children of `Button`. -- Type: `Boolean` -- Required: No + - Type: `ReactNode` + - Required: No -### icon +### `icon` -The icon to render. Supported values are: Dashicons (specified as strings), functions, Component instances and `null`. +The icon to render in the default button. -- Type: `String|Function|Component|null` -- Required: No -- Default: `null` +See the `Icon` component docs for more information. -### multiple + - Type: `IconType` + - Required: No + +### `multiple` Whether to allow multiple selection of files or not. -- Type: `Boolean` -- Required: No -- Default: `false` + - Type: `boolean` + - Required: No + - Default: `false` -### onChange +### `onChange` Callback function passed directly to the `input` file element. Select files will be available in `event.currentTarget.files`. -- Type: `Function` -- Required: Yes + - Type: `ChangeEventHandler<HTMLInputElement>` + - Required: Yes -### onClick +### `onClick` Callback function passed directly to the `input` file element. -This can be useful when you want to force a `change` event to fire when the user chooses the same file again. To do this, set the target value to an empty string in the `onClick` function. +This can be useful when you want to force a `change` event to fire when +the user chooses the same file again. To do this, set the target value to +an empty string in the `onClick` function. ```jsx <FormFileUpload - onClick={ ( event ) => ( event.target.value = '' ) } - onChange={ onChange } + __next40pxDefaultSize + onClick={ ( event ) => ( event.target.value = '' ) } + onChange={ onChange } > - Upload + Upload </FormFileUpload> ``` -- Type: `Function` -- Required: No - -### render + - Type: `MouseEventHandler<HTMLInputElement>` + - Required: No -Optional callback function used to render the UI. If passed, the component does not render the default UI (a button) and calls this function to render it. The function receives an object with property `openFileDialog`, a function that, when called, opens the browser native file upload modal window. +### `render` -- Type: `Function` -- Required: No +Optional callback function used to render the UI. -### __next40pxDefaultSize - -Start opting into the larger default height that will become the default size in a future version. +If passed, the component does not render the default UI (a button) and +calls this function to render it. The function receives an object with +property `openFileDialog`, a function that, when called, opens the browser +native file upload modal window. -- Type: `Boolean` -- Required: No -- Default: `false` + - Type: `(arg: { openFileDialog: () => void; }) => ReactNode` + - Required: No diff --git a/packages/components/src/form-file-upload/docs-manifest.json b/packages/components/src/form-file-upload/docs-manifest.json new file mode 100644 index 00000000000000..cb000536d73562 --- /dev/null +++ b/packages/components/src/form-file-upload/docs-manifest.json @@ -0,0 +1,5 @@ +{ + "$schema": "../../schemas/docs-manifest.json", + "displayName": "FormFileUpload", + "filePath": "./index.tsx" +} diff --git a/packages/components/src/form-file-upload/index.tsx b/packages/components/src/form-file-upload/index.tsx index 83d563f2074764..378dc144c6fe8c 100644 --- a/packages/components/src/form-file-upload/index.tsx +++ b/packages/components/src/form-file-upload/index.tsx @@ -9,15 +9,17 @@ import { useRef } from '@wordpress/element'; import Button from '../button'; import type { WordPressComponentProps } from '../context'; import type { FormFileUploadProps } from './types'; +import { maybeWarnDeprecated36pxSize } from '../utils/deprecated-36px-size'; /** - * FormFileUpload is a component that allows users to select files from their local device. + * FormFileUpload allows users to select files from their local device. * * ```jsx * import { FormFileUpload } from '@wordpress/components'; * * const MyFormFileUpload = () => ( * <FormFileUpload + * __next40pxDefaultSize * accept="image/*" * onChange={ ( event ) => console.log( event.currentTarget.files ) } * > @@ -40,6 +42,15 @@ export function FormFileUpload( { ref.current?.click(); }; + if ( ! render ) { + maybeWarnDeprecated36pxSize( { + componentName: 'FormFileUpload', + __next40pxDefaultSize: props.__next40pxDefaultSize, + // @ts-expect-error - We don't "officially" support all Button props but this likely happens. + size: props.size, + } ); + } + const ui = render ? ( render( { openFileDialog } ) ) : ( diff --git a/packages/components/src/form-file-upload/stories/index.story.tsx b/packages/components/src/form-file-upload/stories/index.story.tsx index 3599ccc51c22eb..176d6b2af60983 100644 --- a/packages/components/src/form-file-upload/stories/index.story.tsx +++ b/packages/components/src/form-file-upload/stories/index.story.tsx @@ -36,6 +36,7 @@ const Template: StoryFn< typeof FormFileUpload > = ( props ) => { export const Default = Template.bind( {} ); Default.args = { children: 'Select file', + __next40pxDefaultSize: true, }; export const RestrictFileTypes = Template.bind( {} ); diff --git a/packages/components/src/form-file-upload/test/index.tsx b/packages/components/src/form-file-upload/test/index.tsx index 3035bcaa670647..b82dcd754bcd20 100644 --- a/packages/components/src/form-file-upload/test/index.tsx +++ b/packages/components/src/form-file-upload/test/index.tsx @@ -7,13 +7,17 @@ import userEvent from '@testing-library/user-event'; /** * Internal dependencies */ -import FormFileUpload from '..'; +import _FormFileUpload from '..'; /** * Browser dependencies */ const { File } = window; +const FormFileUpload = ( + props: React.ComponentProps< typeof _FormFileUpload > +) => <_FormFileUpload __next40pxDefaultSize { ...props } />; + // @testing-library/user-event considers changing <input type="file"> to a string as a change, but it do not occur on real browsers, so the comparisons will be against this result const fakePath = expect.objectContaining( { target: expect.objectContaining( { diff --git a/packages/components/src/form-file-upload/types.ts b/packages/components/src/form-file-upload/types.ts index 728ed959aba76e..3bdbbf5ac2d4c0 100644 --- a/packages/components/src/form-file-upload/types.ts +++ b/packages/components/src/form-file-upload/types.ts @@ -17,10 +17,9 @@ export type FormFileUploadProps = { */ __next40pxDefaultSize?: boolean; /** - * A string passed to `input` element that tells the browser which file types can be - * upload to the upload by the user use. e.g: `image/*,video/*`. - * - * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Unique_file_type_specifiers. + * A string passed to the `input` element that tells the browser which + * [file types](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Unique_file_type_specifiers) + * can be uploaded by the user. e.g: `image/*,video/*`. */ accept?: InputHTMLAttributes< HTMLInputElement >[ 'accept' ]; /** @@ -28,7 +27,9 @@ export type FormFileUploadProps = { */ children?: ReactNode; /** - * The icon to render in the `Button`. + * The icon to render in the default button. + * + * See the `Icon` component docs for more information. */ icon?: ComponentProps< typeof Icon >[ 'icon' ]; /** @@ -50,10 +51,11 @@ export type FormFileUploadProps = { * * ```jsx * <FormFileUpload - * onClick={ ( event ) => ( event.target.value = '' ) } - * onChange={ onChange } + * __next40pxDefaultSize + * onClick={ ( event ) => ( event.target.value = '' ) } + * onChange={ onChange } * > - * Upload + * Upload * </FormFileUpload> * ``` */ From fe8e832e425a16df934b29a2e8dc31cc9224ada4 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 3 Dec 2024 03:09:26 +0900 Subject: [PATCH 1812/1908] ToolbarButton: Set size to "compact" (#67440) * ToolbarButton: Set size to "compact" * Add changelog * Update snapshots Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../alignment-control/test/__snapshots__/index.js.snap | 10 +++++----- .../test/__snapshots__/index.js.snap | 8 ++++---- .../test/__snapshots__/index.js.snap | 6 +++--- packages/components/CHANGELOG.md | 1 + .../components/src/toolbar/toolbar-button/index.tsx | 2 ++ 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/components/alignment-control/test/__snapshots__/index.js.snap b/packages/block-editor/src/components/alignment-control/test/__snapshots__/index.js.snap index f2915ead7417b1..c1383ae8ecc44a 100644 --- a/packages/block-editor/src/components/alignment-control/test/__snapshots__/index.js.snap +++ b/packages/block-editor/src/components/alignment-control/test/__snapshots__/index.js.snap @@ -12,7 +12,7 @@ exports[`AlignmentUI should allow custom alignment controls to be specified 1`] align="custom-left" aria-label="My custom left" aria-pressed="false" - class="components-button components-toolbar__control has-icon" + class="components-button components-toolbar__control is-compact has-icon" data-toolbar-item="true" type="button" > @@ -35,7 +35,7 @@ exports[`AlignmentUI should allow custom alignment controls to be specified 1`] align="custom-right" aria-label="My custom right" aria-pressed="true" - class="components-button components-toolbar__control is-pressed has-icon" + class="components-button components-toolbar__control is-compact is-pressed has-icon" data-toolbar-item="true" type="button" > @@ -100,7 +100,7 @@ exports[`AlignmentUI should match snapshot when controls are visible 1`] = ` align="left" aria-label="Align text left" aria-pressed="true" - class="components-button components-toolbar__control is-pressed has-icon" + class="components-button components-toolbar__control is-compact is-pressed has-icon" data-toolbar-item="true" type="button" > @@ -123,7 +123,7 @@ exports[`AlignmentUI should match snapshot when controls are visible 1`] = ` align="center" aria-label="Align text center" aria-pressed="false" - class="components-button components-toolbar__control has-icon" + class="components-button components-toolbar__control is-compact has-icon" data-toolbar-item="true" type="button" > @@ -146,7 +146,7 @@ exports[`AlignmentUI should match snapshot when controls are visible 1`] = ` align="right" aria-label="Align text right" aria-pressed="false" - class="components-button components-toolbar__control has-icon" + class="components-button components-toolbar__control is-compact has-icon" data-toolbar-item="true" type="button" > diff --git a/packages/block-editor/src/components/block-alignment-control/test/__snapshots__/index.js.snap b/packages/block-editor/src/components/block-alignment-control/test/__snapshots__/index.js.snap index 246e5dca2ae324..9e7e59c0c31447 100644 --- a/packages/block-editor/src/components/block-alignment-control/test/__snapshots__/index.js.snap +++ b/packages/block-editor/src/components/block-alignment-control/test/__snapshots__/index.js.snap @@ -42,7 +42,7 @@ exports[`BlockAlignmentUI should match snapshot when controls are visible 1`] = <button aria-label="None" aria-pressed="false" - class="components-button components-toolbar__control has-icon" + class="components-button components-toolbar__control is-compact has-icon" data-toolbar-item="true" type="button" > @@ -64,7 +64,7 @@ exports[`BlockAlignmentUI should match snapshot when controls are visible 1`] = <button aria-label="Align left" aria-pressed="true" - class="components-button components-toolbar__control is-pressed has-icon" + class="components-button components-toolbar__control is-compact is-pressed has-icon" data-toolbar-item="true" type="button" > @@ -86,7 +86,7 @@ exports[`BlockAlignmentUI should match snapshot when controls are visible 1`] = <button aria-label="Align center" aria-pressed="false" - class="components-button components-toolbar__control has-icon" + class="components-button components-toolbar__control is-compact has-icon" data-toolbar-item="true" type="button" > @@ -108,7 +108,7 @@ exports[`BlockAlignmentUI should match snapshot when controls are visible 1`] = <button aria-label="Align right" aria-pressed="false" - class="components-button components-toolbar__control has-icon" + class="components-button components-toolbar__control is-compact has-icon" data-toolbar-item="true" type="button" > diff --git a/packages/block-editor/src/components/block-vertical-alignment-control/test/__snapshots__/index.js.snap b/packages/block-editor/src/components/block-vertical-alignment-control/test/__snapshots__/index.js.snap index e58d9a264310a7..e8ad6cddbba56e 100644 --- a/packages/block-editor/src/components/block-vertical-alignment-control/test/__snapshots__/index.js.snap +++ b/packages/block-editor/src/components/block-vertical-alignment-control/test/__snapshots__/index.js.snap @@ -42,7 +42,7 @@ exports[`BlockVerticalAlignmentUI should match snapshot when controls are visibl <button aria-label="Align top" aria-pressed="true" - class="components-button components-toolbar__control is-pressed has-icon" + class="components-button components-toolbar__control is-compact is-pressed has-icon" data-toolbar-item="true" type="button" > @@ -64,7 +64,7 @@ exports[`BlockVerticalAlignmentUI should match snapshot when controls are visibl <button aria-label="Align middle" aria-pressed="false" - class="components-button components-toolbar__control has-icon" + class="components-button components-toolbar__control is-compact has-icon" data-toolbar-item="true" type="button" > @@ -86,7 +86,7 @@ exports[`BlockVerticalAlignmentUI should match snapshot when controls are visibl <button aria-label="Align bottom" aria-pressed="false" - class="components-button components-toolbar__control has-icon" + class="components-button components-toolbar__control is-compact has-icon" data-toolbar-item="true" type="button" > diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 469d5c9de244e5..e53d297fba19ae 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -26,6 +26,7 @@ - Upgraded `@ariakit/react` (v0.4.13) and `@ariakit/test` (v0.4.5) ([#65907](https://github.com/WordPress/gutenberg/pull/65907)). - Upgraded `@ariakit/react` (v0.4.15) and `@ariakit/test` (v0.4.7) ([#67404](https://github.com/WordPress/gutenberg/pull/67404)). +- `ToolbarButton`: Set size to "compact" ([#67440](https://github.com/WordPress/gutenberg/pull/67440)). - Exported the `WPCompleter` type as it was being used in block-editor/autocompleters ([#67410](https://github.com/WordPress/gutenberg/pull/67410)). - `SlotFill`: remove manual rerenders from the portal `Fill` component ([#67471](https://github.com/WordPress/gutenberg/pull/67471)). diff --git a/packages/components/src/toolbar/toolbar-button/index.tsx b/packages/components/src/toolbar/toolbar-button/index.tsx index bb591ff7b521c6..ae1f54acbfc14d 100644 --- a/packages/components/src/toolbar/toolbar-button/index.tsx +++ b/packages/components/src/toolbar/toolbar-button/index.tsx @@ -54,6 +54,7 @@ function UnforwardedToolbarButton( <Button ref={ ref } icon={ restProps.icon } + size="compact" label={ title } shortcut={ restProps.shortcut } data-subscript={ restProps.subscript } @@ -97,6 +98,7 @@ function UnforwardedToolbarButton( > { ( toolbarItemProps ) => ( <Button + size="compact" label={ title } isPressed={ isActive } { ...toolbarItemProps } From 11991fe56d47e331ca15b4a04ee6af18b8797721 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 2 Dec 2024 19:15:40 +0100 Subject: [PATCH 1813/1908] Zoom out: fix for inserter (#67495) Makes previousIsZoomedOut a proper ref, and assumes a starting zoom level of 1. --- .../src/components/iframe/use-scale-canvas.js | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/components/iframe/use-scale-canvas.js b/packages/block-editor/src/components/iframe/use-scale-canvas.js index 2d8cb217a3255c..732fe583d46ac8 100644 --- a/packages/block-editor/src/components/iframe/use-scale-canvas.js +++ b/packages/block-editor/src/components/iframe/use-scale-canvas.js @@ -2,11 +2,7 @@ * WordPress dependencies */ import { useEffect, useRef, useCallback } from '@wordpress/element'; -import { - usePrevious, - useReducedMotion, - useResizeObserver, -} from '@wordpress/compose'; +import { useReducedMotion, useResizeObserver } from '@wordpress/compose'; /** * @typedef {Object} TransitionState @@ -284,7 +280,8 @@ export function useScaleCanvas( { transitionFromRef.current = transitionToRef.current; }, [ iframeDocument ] ); - const previousIsZoomedOut = usePrevious( isZoomedOut ); + const previousIsZoomedOut = useRef( false ); + /** * Runs when zoom out mode is toggled, and sets the startAnimation flag * so the animation will start when the next useEffect runs. We _only_ @@ -292,20 +289,26 @@ export function useScaleCanvas( { * changes due to the container resizing. */ useEffect( () => { - if ( ! iframeDocument || previousIsZoomedOut === isZoomedOut ) { - return; - } + const trigger = + iframeDocument && previousIsZoomedOut.current !== isZoomedOut; - if ( isZoomedOut ) { - iframeDocument.documentElement.classList.add( 'is-zoomed-out' ); + previousIsZoomedOut.current = isZoomedOut; + + if ( ! trigger ) { + return; } startAnimationRef.current = true; + if ( ! isZoomedOut ) { + return; + } + + iframeDocument.documentElement.classList.add( 'is-zoomed-out' ); return () => { iframeDocument.documentElement.classList.remove( 'is-zoomed-out' ); }; - }, [ iframeDocument, isZoomedOut, previousIsZoomedOut ] ); + }, [ iframeDocument, isZoomedOut ] ); /** * This handles: From 92c12fea56c02731c64d6d4a2ed63b9ec72e2100 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 3 Dec 2024 04:39:30 +0900 Subject: [PATCH 1814/1908] LetteringSpacingControl: Deprecate 36px default size (#67429) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../components/letter-spacing-control/README.md | 3 ++- .../components/letter-spacing-control/index.js | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/letter-spacing-control/README.md b/packages/block-editor/src/components/letter-spacing-control/README.md index ef119bbc943d2f..535ca2ae8cbbff 100644 --- a/packages/block-editor/src/components/letter-spacing-control/README.md +++ b/packages/block-editor/src/components/letter-spacing-control/README.md @@ -12,13 +12,14 @@ This component is used for blocks that display text, commonly inside a Renders a letter spacing control. ```jsx -import { LetterSpacingControl } from '@wordpress/block-editor'; +import { __experimentalLetterSpacingControl as LetterSpacingControl } from '@wordpress/block-editor'; const MyLetterSpacingControl = () => ( <LetterSpacingControl value={ value } onChange={ onChange } __unstableInputWidth="auto" + __next40pxDefaultSize /> ); ``` diff --git a/packages/block-editor/src/components/letter-spacing-control/index.js b/packages/block-editor/src/components/letter-spacing-control/index.js index 1577e184c4a06c..1edbe65a3737e6 100644 --- a/packages/block-editor/src/components/letter-spacing-control/index.js +++ b/packages/block-editor/src/components/letter-spacing-control/index.js @@ -5,6 +5,7 @@ import { __experimentalUnitControl as UnitControl, __experimentalUseCustomUnits as useCustomUnits, } from '@wordpress/components'; +import deprecated from '@wordpress/deprecated'; import { __ } from '@wordpress/i18n'; /** @@ -35,9 +36,25 @@ export default function LetterSpacingControl( { availableUnits: availableUnits || [ 'px', 'em', 'rem' ], defaultValues: { px: 2, em: 0.2, rem: 0.2 }, } ); + + if ( + ! __next40pxDefaultSize && + ( otherProps.size === undefined || otherProps.size === 'default' ) + ) { + deprecated( + `36px default size for wp.blockEditor.__experimentalLetterSpacingControl`, + { + since: '6.8', + version: '7.1', + hint: 'Set the `__next40pxDefaultSize` prop to true to start opting into the new default size, which will become the default in a future version.', + } + ); + } + return ( <UnitControl __next40pxDefaultSize={ __next40pxDefaultSize } + __shouldNotWarnDeprecated36pxSize { ...otherProps } label={ __( 'Letter spacing' ) } value={ value } From c54d810a28bd08cdf74a3f9ec19547f5c2e31d09 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 2 Dec 2024 21:06:37 +0100 Subject: [PATCH 1815/1908] Preload: fix e2e test (#67497) --- backport-changelog/6.8/7687.md | 1 + lib/compat/wordpress-6.8/preload.php | 3 ++ test/e2e/specs/site-editor/preload.spec.js | 44 ++++++++++++++-------- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/backport-changelog/6.8/7687.md b/backport-changelog/6.8/7687.md index f1505645df20c6..0b5af190964df1 100644 --- a/backport-changelog/6.8/7687.md +++ b/backport-changelog/6.8/7687.md @@ -1,3 +1,4 @@ https://github.com/WordPress/wordpress-develop/pull/7687 * https://github.com/WordPress/gutenberg/pull/66488 +* https://github.com/WordPress/gutenberg/pull/67497 diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php index 879e263f5a1892..0a36ea7f7227d4 100644 --- a/lib/compat/wordpress-6.8/preload.php +++ b/lib/compat/wordpress-6.8/preload.php @@ -86,6 +86,9 @@ function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { */ $context = current_user_can( 'edit_theme_options' ) ? 'edit' : 'view'; $paths[] = "/wp/v2/global-styles/$global_styles_id?context=$context"; + + // Used by getBlockPatternCategories in useBlockEditorSettings. + $paths[] = '/wp/v2/block-patterns/categories'; } return $paths; } diff --git a/test/e2e/specs/site-editor/preload.spec.js b/test/e2e/specs/site-editor/preload.spec.js index 1e93f783a8a91d..2cd61283fbd9e8 100644 --- a/test/e2e/specs/site-editor/preload.spec.js +++ b/test/e2e/specs/site-editor/preload.spec.js @@ -16,26 +16,38 @@ test.describe( 'Preload', () => { page, admin, } ) => { - // Do not use `visitSiteEditor` because it waits for the iframe to load. - await admin.visitAdminPage( 'site-editor.php' ); - const requests = []; - let isLoaded = false; - page.on( 'request', ( request ) => { - if ( request.resourceType() === 'document' ) { - // The iframe also "requests" a blob document. This is the most - // reliable way to wait for the iframe to start loading. - // `waitForSelector` is always a bit delayed, and we don't want - // to detect requests after the iframe mounts. - isLoaded = true; - } else if ( ! isLoaded && request.resourceType() === 'fetch' ) { - requests.push( request.url() ); + function onRequest( request ) { + if ( + request.resourceType() === 'document' && + request.url().startsWith( 'blob:' ) + ) { + // Stop recording when the iframe is initialized. + page.off( 'request', onRequest ); + } else if ( request.resourceType() === 'fetch' ) { + const url = request.url(); + const urlObject = new URL( url ); + const restRoute = urlObject.searchParams.get( 'rest_route' ); + if ( restRoute ) { + requests.push( restRoute ); + } else { + requests.push( url ); + } } - } ); + } + + page.on( 'request', onRequest ); - await page.waitForFunction( ( _isLoaded ) => _isLoaded, [ isLoaded ] ); + await admin.visitSiteEditor(); - expect( requests ).toEqual( [] ); + // To do: these should all be removed or preloaded. + expect( requests ).toEqual( [ + // There are two separate settings OPTIONS requests. We should fix + // so the one for canUser and getEntityRecord are reused. + '/wp/v2/settings', + // Seems to be coming from `enableComplementaryArea`. + '/wp/v2/users/me', + ] ); } ); } ); From ec756b07e4d66f2ddb3d017b1b09cdd85ee0e48a Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Mon, 2 Dec 2024 15:10:48 -0600 Subject: [PATCH 1816/1908] useScaleCanvas performance improvements (#67496) * Rely on containerHeight resize listener instead of iframe.documentElement.clientHeight when setting the CSS variable * Only add CSS variables if we need them (scaleValue < 1) * Remove unmounting of CSS variables in useEffect return --------- Co-authored-by: Ella <ella@vandurpe.com> --- .../src/components/iframe/use-scale-canvas.js | 124 ++++++++---------- 1 file changed, 55 insertions(+), 69 deletions(-) diff --git a/packages/block-editor/src/components/iframe/use-scale-canvas.js b/packages/block-editor/src/components/iframe/use-scale-canvas.js index 732fe583d46ac8..0b2b8d3c137ffa 100644 --- a/packages/block-editor/src/components/iframe/use-scale-canvas.js +++ b/packages/block-editor/src/components/iframe/use-scale-canvas.js @@ -6,11 +6,11 @@ import { useReducedMotion, useResizeObserver } from '@wordpress/compose'; /** * @typedef {Object} TransitionState - * @property {number} scaleValue Scale of the canvas. - * @property {number} frameSize Size of the frame/offset around the canvas. - * @property {number} clientHeight ClientHeight of the iframe. - * @property {number} scrollTop ScrollTop of the iframe. - * @property {number} scrollHeight ScrollHeight of the iframe. + * @property {number} scaleValue Scale of the canvas. + * @property {number} frameSize Size of the frame/offset around the canvas. + * @property {number} containerHeight containerHeight of the iframe. + * @property {number} scrollTop ScrollTop of the iframe. + * @property {number} scrollHeight ScrollHeight of the iframe. */ /** @@ -44,27 +44,28 @@ function calculateScale( { */ function computeScrollTopNext( transitionFrom, transitionTo ) { const { - clientHeight: prevClientHeight, + containerHeight: prevContainerHeight, frameSize: prevFrameSize, scaleValue: prevScale, scrollTop, scrollHeight, } = transitionFrom; - const { clientHeight, frameSize, scaleValue } = transitionTo; + const { containerHeight, frameSize, scaleValue } = transitionTo; // Step 0: Start with the current scrollTop. let scrollTopNext = scrollTop; // Step 1: Undo the effects of the previous scale and frame around the // midpoint of the visible area. scrollTopNext = - ( scrollTopNext + prevClientHeight / 2 - prevFrameSize ) / prevScale - - prevClientHeight / 2; + ( scrollTopNext + prevContainerHeight / 2 - prevFrameSize ) / + prevScale - + prevContainerHeight / 2; // Step 2: Apply the new scale and frame around the midpoint of the // visible area. scrollTopNext = - ( scrollTopNext + clientHeight / 2 ) * scaleValue + + ( scrollTopNext + containerHeight / 2 ) * scaleValue + frameSize - - clientHeight / 2; + containerHeight / 2; // Step 3: Handle an edge case so that you scroll to the top of the // iframe if the top of the iframe content is visible in the container. @@ -78,7 +79,7 @@ function computeScrollTopNext( transitionFrom, transitionTo ) { const maxScrollTop = scrollHeight * ( scaleValue / prevScale ) + frameSize * 2 - - clientHeight; + containerHeight; // Step 4: Clamp the scrollTopNext between the minimum and maximum // possible scrollTop positions. Round the value to avoid subpixel @@ -146,8 +147,10 @@ export function useScaleCanvas( { } ) { const [ contentResizeListener, { height: contentHeight } ] = useResizeObserver(); - const [ containerResizeListener, { width: containerWidth } ] = - useResizeObserver(); + const [ + containerResizeListener, + { width: containerWidth, height: containerHeight }, + ] = useResizeObserver(); const initialContainerWidthRef = useRef( 0 ); const isZoomedOut = scale !== 1; @@ -186,7 +189,7 @@ export function useScaleCanvas( { const transitionFromRef = useRef( { scaleValue, frameSize, - clientHeight: 0, + containerHeight: 0, scrollTop: 0, scrollHeight: 0, } ); @@ -198,7 +201,7 @@ export function useScaleCanvas( { const transitionToRef = useRef( { scaleValue, frameSize, - clientHeight: 0, + containerHeight: 0, scrollTop: 0, scrollHeight: 0, } ); @@ -333,40 +336,41 @@ export function useScaleCanvas( { } ); } - // If we are not going to animate the transition, set the scale and frame size directly. - // If we are animating, these values will be set when the animation is finished. - // Example: Opening sidebars that reduce the scale of the canvas, but we don't want to - // animate the transition. - if ( ! startAnimationRef.current ) { + if ( scaleValue < 1 ) { + // If we are not going to animate the transition, set the scale and frame size directly. + // If we are animating, these values will be set when the animation is finished. + // Example: Opening sidebars that reduce the scale of the canvas, but we don't want to + // animate the transition. + if ( ! startAnimationRef.current ) { + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-scale', + scaleValue + ); + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-frame-size', + `${ frameSize }px` + ); + } + iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-scale', - scaleValue + '--wp-block-editor-iframe-zoom-out-content-height', + `${ contentHeight }px` ); + iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-frame-size', - `${ frameSize }px` + '--wp-block-editor-iframe-zoom-out-inner-height', + `${ containerHeight }px` ); - } - iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-content-height', - `${ contentHeight }px` - ); - - const clientHeight = iframeDocument.documentElement.clientHeight; - iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-inner-height', - `${ clientHeight }px` - ); - - iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-container-width', - `${ containerWidth }px` - ); - iframeDocument.documentElement.style.setProperty( - '--wp-block-editor-iframe-zoom-out-scale-container-width', - `${ scaleContainerWidth }px` - ); + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-container-width', + `${ containerWidth }px` + ); + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-scale-container-width', + `${ scaleContainerWidth }px` + ); + } /** * Handle the zoom out animation: @@ -405,8 +409,9 @@ export function useScaleCanvas( { // the iframe at this point when we're about to animate the zoom out. // The iframe scrollTop, scrollHeight, and clientHeight will all be // the most accurate. - transitionFromRef.current.clientHeight = - transitionFromRef.current.clientHeight ?? clientHeight; + transitionFromRef.current.containerHeight = + transitionFromRef.current.containerHeight ?? + containerHeight; // Use containerHeight, as it's the previous container height value if none was set. transitionFromRef.current.scrollTop = iframeDocument.documentElement.scrollTop; transitionFromRef.current.scrollHeight = @@ -415,7 +420,8 @@ export function useScaleCanvas( { transitionToRef.current = { scaleValue, frameSize, - clientHeight, + containerHeight: + iframeDocument.documentElement.clientHeight, // use clientHeight to get the actual height of the new container, as it will be the most up-to-date. }; transitionToRef.current.scrollTop = computeScrollTopNext( transitionFromRef.current, @@ -432,27 +438,6 @@ export function useScaleCanvas( { } } } - - return () => { - iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-scale' - ); - iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-frame-size' - ); - iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-content-height' - ); - iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-inner-height' - ); - iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-container-width' - ); - iframeDocument.documentElement.style.removeProperty( - '--wp-block-editor-iframe-zoom-out-scale-container-width' - ); - }; }, [ startZoomOutAnimation, finishZoomOutAnimation, @@ -463,6 +448,7 @@ export function useScaleCanvas( { iframeDocument, contentHeight, containerWidth, + containerHeight, maxContainerWidth, scaleContainerWidth, ] ); From 88143b3867a04293ac0455c798b8485028a70e11 Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Tue, 3 Dec 2024 02:56:38 +0530 Subject: [PATCH 1817/1908] Inline Commenting: Added new sidebar as extension of the canvas (#67347) Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- .../components/collab-sidebar/constants.js | 1 + .../src/components/collab-sidebar/index.js | 143 ++++++++++++------ .../src/components/collab-sidebar/style.scss | 13 ++ 3 files changed, 112 insertions(+), 45 deletions(-) diff --git a/packages/editor/src/components/collab-sidebar/constants.js b/packages/editor/src/components/collab-sidebar/constants.js index 748c2afc26374d..b62e30c346e1f9 100644 --- a/packages/editor/src/components/collab-sidebar/constants.js +++ b/packages/editor/src/components/collab-sidebar/constants.js @@ -1 +1,2 @@ +export const collabHistorySidebarName = 'edit-post/collab-history-sidebar'; export const collabSidebarName = 'edit-post/collab-sidebar'; diff --git a/packages/editor/src/components/collab-sidebar/index.js b/packages/editor/src/components/collab-sidebar/index.js index 17a23a227424a6..0fe46c549cff0f 100644 --- a/packages/editor/src/components/collab-sidebar/index.js +++ b/packages/editor/src/components/collab-sidebar/index.js @@ -2,7 +2,12 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { useSelect, useDispatch, resolveSelect } from '@wordpress/data'; +import { + useSelect, + useDispatch, + resolveSelect, + subscribe, +} from '@wordpress/data'; import { useState, useMemo } from '@wordpress/element'; import { comment as commentIcon } from '@wordpress/icons'; import { addFilter } from '@wordpress/hooks'; @@ -15,12 +20,13 @@ import { store as interfaceStore } from '@wordpress/interface'; * Internal dependencies */ import PluginSidebar from '../plugin-sidebar'; -import { collabSidebarName } from './constants'; +import { collabHistorySidebarName, collabSidebarName } from './constants'; import { Comments } from './comments'; import { AddComment } from './add-comment'; import { store as editorStore } from '../../store'; import AddCommentButton from './comment-button'; import AddCommentToolbarButton from './comment-button-toolbar'; +import { useGlobalStylesContext } from '../global-styles-provider'; const isBlockCommentExperimentEnabled = window?.__experimentalEnableBlockComment; @@ -44,61 +50,28 @@ addFilter( modifyBlockCommentAttributes ); -function CollabSidebarContent( { showCommentBoard, setShowCommentBoard } ) { +function CollabSidebarContent( { + showCommentBoard, + setShowCommentBoard, + styles, + comments, +} ) { const { createNotice } = useDispatch( noticesStore ); const { saveEntityRecord, deleteEntityRecord } = useDispatch( coreStore ); const { getEntityRecord } = resolveSelect( coreStore ); - const { postId, threads } = useSelect( ( select ) => { + const { postId } = useSelect( ( select ) => { const { getCurrentPostId } = select( editorStore ); const _postId = getCurrentPostId(); - const data = !! _postId - ? select( coreStore ).getEntityRecords( 'root', 'comment', { - post: _postId, - type: 'block_comment', - status: 'any', - per_page: 100, - } ) - : null; return { postId: _postId, - threads: data, }; }, [] ); const { getSelectedBlockClientId } = useSelect( blockEditorStore ); const { updateBlockAttributes } = useDispatch( blockEditorStore ); - // Process comments to build the tree structure - const resultComments = useMemo( () => { - // Create a compare to store the references to all objects by id - const compare = {}; - const result = []; - - const filteredComments = ( threads ?? [] ).filter( - ( comment ) => comment.status !== 'trash' - ); - - // Initialize each object with an empty `reply` array - filteredComments.forEach( ( item ) => { - compare[ item.id ] = { ...item, reply: [] }; - } ); - - // Iterate over the data to build the tree structure - filteredComments.forEach( ( item ) => { - if ( item.parent === 0 ) { - // If parent is 0, it's a root item, push it to the result array - result.push( compare[ item.id ] ); - } else if ( compare[ item.parent ] ) { - // Otherwise, find its parent and push it to the parent's `reply` array - compare[ item.parent ].reply.push( compare[ item.id ] ); - } - } ); - - return result; - }, [ threads ] ); - // Function to save the comment. const addNewComment = async ( comment, parentCommentId ) => { const args = { @@ -222,14 +195,14 @@ function CollabSidebarContent( { showCommentBoard, setShowCommentBoard } ) { }; return ( - <div className="editor-collab-sidebar-panel"> + <div className="editor-collab-sidebar-panel" style={ styles }> <AddComment onSubmit={ addNewComment } showCommentBoard={ showCommentBoard } setShowCommentBoard={ setShowCommentBoard } /> <Comments - threads={ resultComments } + threads={ comments } onEditComment={ onEditComment } onAddReply={ addNewComment } onCommentDelete={ onCommentDelete } @@ -245,6 +218,7 @@ function CollabSidebarContent( { showCommentBoard, setShowCommentBoard } ) { export default function CollabSidebar() { const [ showCommentBoard, setShowCommentBoard ] = useState( false ); const { enableComplementaryArea } = useDispatch( interfaceStore ); + const { getActiveComplementaryArea } = useSelect( interfaceStore ); const { postStatus } = useSelect( ( select ) => { return { @@ -270,6 +244,68 @@ export default function CollabSidebar() { enableComplementaryArea( 'core', 'edit-post/collab-sidebar' ); }; + const { threads } = useSelect( ( select ) => { + const { getCurrentPostId } = select( editorStore ); + const _postId = getCurrentPostId(); + const data = !! _postId + ? select( coreStore ).getEntityRecords( 'root', 'comment', { + post: _postId, + type: 'block_comment', + status: 'any', + per_page: 100, + } ) + : null; + + return { + postId: _postId, + threads: data, + }; + }, [] ); + + // Process comments to build the tree structure + const resultComments = useMemo( () => { + // Create a compare to store the references to all objects by id + const compare = {}; + const result = []; + + const filteredComments = ( threads ?? [] ).filter( + ( comment ) => comment.status !== 'trash' + ); + + // Initialize each object with an empty `reply` array + filteredComments.forEach( ( item ) => { + compare[ item.id ] = { ...item, reply: [] }; + } ); + + // Iterate over the data to build the tree structure + filteredComments.forEach( ( item ) => { + if ( item.parent === 0 ) { + // If parent is 0, it's a root item, push it to the result array + result.push( compare[ item.id ] ); + } else if ( compare[ item.parent ] ) { + // Otherwise, find its parent and push it to the parent's `reply` array + compare[ item.parent ].reply.push( compare[ item.id ] ); + } + } ); + + return result; + }, [ threads ] ); + + // Get the global styles to set the background color of the sidebar. + const { merged: GlobalStyles } = useGlobalStylesContext(); + const backgroundColor = GlobalStyles?.styles?.color?.background; + + if ( 0 < resultComments.length ) { + const unsubscribe = subscribe( () => { + const activeSidebar = getActiveComplementaryArea( 'core' ); + + if ( ! activeSidebar ) { + enableComplementaryArea( 'core', collabSidebarName ); + unsubscribe(); + } + } ); + } + // Check if the experimental flag is enabled. if ( ! isBlockCommentExperimentEnabled || postStatus === 'publish' ) { return null; // or maybe return some message indicating no threads are available. @@ -283,14 +319,31 @@ export default function CollabSidebar() { <> <AddCommentComponent onClick={ openCollabBoard } /> <PluginSidebar - identifier={ collabSidebarName } + identifier={ collabHistorySidebarName } // translators: Comments sidebar title title={ __( 'Comments' ) } icon={ commentIcon } > <CollabSidebarContent + comments={ resultComments } + showCommentBoard={ showCommentBoard } + setShowCommentBoard={ setShowCommentBoard } + /> + </PluginSidebar> + <PluginSidebar + isPinnable={ false } + header={ false } + identifier={ collabSidebarName } + className="editor-collab-sidebar" + headerClassName="editor-collab-sidebar__header" + > + <CollabSidebarContent + comments={ resultComments } showCommentBoard={ showCommentBoard } setShowCommentBoard={ setShowCommentBoard } + styles={ { + backgroundColor, + } } /> </PluginSidebar> </> diff --git a/packages/editor/src/components/collab-sidebar/style.scss b/packages/editor/src/components/collab-sidebar/style.scss index 2f937e3df9a25b..2c1426f1dd75df 100644 --- a/packages/editor/src/components/collab-sidebar/style.scss +++ b/packages/editor/src/components/collab-sidebar/style.scss @@ -1,5 +1,18 @@ +.interface-interface-skeleton__sidebar:has(.editor-collab-sidebar) { + box-shadow: none; + + .interface-complementary-area-header { + display: none; + } +} + +.editor-collab-sidebar { + height: 100%; +} + .editor-collab-sidebar-panel { padding: $grid-unit-20; + height: 100%; &__thread { position: relative; From 66d952b8905209fa2ed935fe55e3744957651983 Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Tue, 3 Dec 2024 07:55:29 +0900 Subject: [PATCH 1818/1908] Storybook: Support keyword search in Icon Library (#67442) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/icons/src/icon/stories/index.story.js | 18 ++++++++++++++---- packages/icons/src/icon/stories/keywords.ts | 13 +++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 packages/icons/src/icon/stories/keywords.ts diff --git a/packages/icons/src/icon/stories/index.story.js b/packages/icons/src/icon/stories/index.story.js index 092434de43b4dc..8cbf65d9f259e9 100644 --- a/packages/icons/src/icon/stories/index.story.js +++ b/packages/icons/src/icon/stories/index.story.js @@ -9,6 +9,7 @@ import { useState, Fragment } from '@wordpress/element'; import Icon from '../'; import check from '../../library/check'; import * as icons from '../../'; +import keywords from './keywords'; const { Icon: _Icon, ...availableIcons } = icons; @@ -46,14 +47,23 @@ const LibraryExample = () => { const [ filter, setFilter ] = useState( '' ); const filteredIcons = filter.length ? Object.fromEntries( - Object.entries( availableIcons ).filter( ( [ name ] ) => - name.toLowerCase().includes( filter.toLowerCase() ) - ) + Object.entries( availableIcons ).filter( ( [ name ] ) => { + const normalizedName = name.toLowerCase(); + const normalizedFilter = filter.toLowerCase(); + + return ( + normalizedName.includes( normalizedFilter ) || + // @ts-expect-error - Not worth the effort to cast `name` + keywords[ name ]?.some( ( keyword ) => + keyword.toLowerCase().includes( normalizedFilter ) + ) + ); + } ) ) : availableIcons; return ( <div style={ { padding: 20 } }> - <label htmlFor="filter-icon" style={ { paddingRight: 10 } }> + <label htmlFor="filter-icons" style={ { paddingRight: 10 } }> Filter Icons </label> <input diff --git a/packages/icons/src/icon/stories/keywords.ts b/packages/icons/src/icon/stories/keywords.ts new file mode 100644 index 00000000000000..3fd962e047bc1d --- /dev/null +++ b/packages/icons/src/icon/stories/keywords.ts @@ -0,0 +1,13 @@ +const keywords: Partial< Record< keyof typeof import('../../'), string[] > > = { + cancelCircleFilled: [ 'close' ], + create: [ 'add' ], + file: [ 'folder' ], + seen: [ 'show' ], + thumbsDown: [ 'dislike' ], + thumbsUp: [ 'like' ], + trash: [ 'delete' ], + unseen: [ 'hide' ], + warning: [ 'alert', 'caution' ], +}; + +export default keywords; From 6ef2f24d316a4368f0d21a97ce76dc905d345d85 Mon Sep 17 00:00:00 2001 From: wwdes <55145125+wwdes@users.noreply.github.com> Date: Tue, 3 Dec 2024 00:08:03 +0100 Subject: [PATCH 1819/1908] Added disableAlpha prop to CustomGradientPicker and GradientPicker components (#66974) * add enableAlpha prop to GradientPicker and custom-gradient-picker * Update packages/components/CHANGELOG.md Co-authored-by: Lena Morita <lena@jaguchi.com> * Update packages/components/src/custom-gradient-picker/types.ts Co-authored-by: Lena Morita <lena@jaguchi.com> * Update packages/components/src/gradient-picker/types.ts Co-authored-by: Lena Morita <lena@jaguchi.com> * packages/components/src/gradient-picker/README.md update --------- Unlinked contributors: wwdes. Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 5 +++++ packages/components/src/custom-gradient-picker/index.tsx | 2 ++ packages/components/src/custom-gradient-picker/types.ts | 6 ++++++ packages/components/src/gradient-picker/README.md | 8 ++++++++ packages/components/src/gradient-picker/index.tsx | 2 ++ packages/components/src/gradient-picker/types.ts | 6 ++++++ 6 files changed, 29 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index e53d297fba19ae..e35ba460ef7c54 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +### Enhancements + +- `GradientPicker`: Add `enableAlpha` prop ([#66974](https://github.com/WordPress/gutenberg/pull/66974)) +- `CustomGradientPicker`: Add `enableAlpha` prop ([#66974](https://github.com/WordPress/gutenberg/pull/66974)) + ### Deprecations - `BoxControl`: Passive deprecate `onMouseOver`/`onMouseOut`. Pass to the `inputProps` prop instead ([#67332](https://github.com/WordPress/gutenberg/pull/67332)). diff --git a/packages/components/src/custom-gradient-picker/index.tsx b/packages/components/src/custom-gradient-picker/index.tsx index dd0659515234a6..8d53cd9f3d0ea2 100644 --- a/packages/components/src/custom-gradient-picker/index.tsx +++ b/packages/components/src/custom-gradient-picker/index.tsx @@ -140,6 +140,7 @@ const GradientTypePicker = ( { export function CustomGradientPicker( { value, onChange, + enableAlpha = true, __experimentalIsRenderedInSidebar = false, }: CustomGradientPickerProps ) { const { gradientAST, hasGradient } = getGradientAstWithDefault( value ); @@ -167,6 +168,7 @@ export function CustomGradientPicker( { __experimentalIsRenderedInSidebar={ __experimentalIsRenderedInSidebar } + disableAlpha={ ! enableAlpha } background={ background } hasGradient={ hasGradient } value={ controlPoints } diff --git a/packages/components/src/custom-gradient-picker/types.ts b/packages/components/src/custom-gradient-picker/types.ts index f9efb90799daf2..17702c74ef527a 100644 --- a/packages/components/src/custom-gradient-picker/types.ts +++ b/packages/components/src/custom-gradient-picker/types.ts @@ -26,6 +26,12 @@ export type CustomGradientPickerProps = { * the `currentGradient` as an argument. */ onChange: ( currentGradient: string ) => void; + /** + * Whether to enable alpha transparency options in the picker. + * + * @default true + */ + enableAlpha?: boolean; /** * Whether this is rendered in the sidebar. * diff --git a/packages/components/src/gradient-picker/README.md b/packages/components/src/gradient-picker/README.md index a8ee9d990c5c2a..ec0210d03c0a43 100644 --- a/packages/components/src/gradient-picker/README.md +++ b/packages/components/src/gradient-picker/README.md @@ -100,6 +100,14 @@ gradients from `gradients` will be shown. - Required: No - Default: `false` +### `enableAlpha` + +Whether to enable alpha transparency options in the picker. + + - Type: `boolean` + - Required: No + - Default: `true` + ### `gradients` An array of objects as predefined gradients displayed above the gradient diff --git a/packages/components/src/gradient-picker/index.tsx b/packages/components/src/gradient-picker/index.tsx index 124a89c7e016e1..28491d8a56010e 100644 --- a/packages/components/src/gradient-picker/index.tsx +++ b/packages/components/src/gradient-picker/index.tsx @@ -213,6 +213,7 @@ export function GradientPicker( { onChange, value, clearable = true, + enableAlpha = true, disableCustomGradients = false, __experimentalIsRenderedInSidebar, headingLevel = 2, @@ -230,6 +231,7 @@ export function GradientPicker( { __experimentalIsRenderedInSidebar={ __experimentalIsRenderedInSidebar } + enableAlpha={ enableAlpha } value={ value } onChange={ onChange } /> diff --git a/packages/components/src/gradient-picker/types.ts b/packages/components/src/gradient-picker/types.ts index 8ac2c6de9f2cf3..3497dd8c5ac008 100644 --- a/packages/components/src/gradient-picker/types.ts +++ b/packages/components/src/gradient-picker/types.ts @@ -56,6 +56,12 @@ type GradientPickerBaseProps = { * @default true */ loop?: boolean; + /** + * Whether to enable alpha transparency options in the picker. + * + * @default true + */ + enableAlpha?: boolean; } & ( | { // TODO: [#54055] Either this or `aria-labelledby` should be required From 680fef531408601dcd04e199aefdfac7190cb577 Mon Sep 17 00:00:00 2001 From: Pawan Kumar <pwnkumar201@gmail.com> Date: Tue, 3 Dec 2024 11:33:01 +0530 Subject: [PATCH 1820/1908] Navigation Block: Fix issue with double-clicking "Create a new menu" causing duplicate menus. (#67488) Co-authored-by: creador-dev <creadordev@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- .../navigation/edit/deleted-navigation-warning.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/navigation/edit/deleted-navigation-warning.js b/packages/block-library/src/navigation/edit/deleted-navigation-warning.js index 22d1e339c5c004..3d40f4d031ed34 100644 --- a/packages/block-library/src/navigation/edit/deleted-navigation-warning.js +++ b/packages/block-library/src/navigation/edit/deleted-navigation-warning.js @@ -4,9 +4,16 @@ import { Warning } from '@wordpress/block-editor'; import { Button, Notice } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { createInterpolateElement } from '@wordpress/element'; +import { useState, createInterpolateElement } from '@wordpress/element'; function DeletedNavigationWarning( { onCreateNew, isNotice = false } ) { + const [ isButtonDisabled, setIsButtonDisabled ] = useState( false ); + + const handleButtonClick = () => { + setIsButtonDisabled( true ); + onCreateNew(); + }; + const message = createInterpolateElement( __( 'Navigation Menu has been deleted or is unavailable. <button>Create a new Menu?</button>' @@ -15,8 +22,10 @@ function DeletedNavigationWarning( { onCreateNew, isNotice = false } ) { button: ( <Button __next40pxDefaultSize - onClick={ onCreateNew } + onClick={ handleButtonClick } variant="link" + disabled={ isButtonDisabled } + accessibleWhenDisabled /> ), } From 9addc70d0c97730253a5d2afbce8528140a2a431 Mon Sep 17 00:00:00 2001 From: Mayank Tripathi <70465598+Mayank-Tripathi32@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:27:07 +0530 Subject: [PATCH 1821/1908] Fix editor crash due to homepage action (#67500) Co-authored-by: Mayank-Tripathi32 <mayanktripathi32@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- packages/editor/src/components/post-actions/actions.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 1b6ff4fbe384b5..808134ea969a11 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -52,10 +52,11 @@ export function usePostActions( { postType, onActionPerformed, context } ) { }, [ registerPostTypeSchema, postType ] ); return useMemo( () => { - let actions = [ - ...defaultActions, - shouldShowSetAsHomepageAction ? setAsHomepageAction : [], - ]; + let actions = [ ...defaultActions ]; + if ( shouldShowSetAsHomepageAction ) { + actions.push( setAsHomepageAction ); + } + // Filter actions based on provided context. If not provided // all actions are returned. We'll have a single entry for getting the actions // and the consumer should provide the context to filter the actions, if needed. From df9a213d9c8b7a92785ab82a2d504aa54a369101 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Tue, 3 Dec 2024 10:09:03 +0100 Subject: [PATCH 1822/1908] Site Editor: Fix the patterns route on mobile (#67467) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../edit-site/src/components/site-editor-routes/patterns.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/site-editor-routes/patterns.js b/packages/edit-site/src/components/site-editor-routes/patterns.js index 48207cfe1c1d2c..db97c4b5c080fd 100644 --- a/packages/edit-site/src/components/site-editor-routes/patterns.js +++ b/packages/edit-site/src/components/site-editor-routes/patterns.js @@ -10,6 +10,6 @@ export const patternsRoute = { areas: { sidebar: <SidebarNavigationScreenPatterns backPath="/" />, content: <PagePatterns />, - mobile: <SidebarNavigationScreenPatterns backPath="/" />, + mobile: <PagePatterns />, }, }; From 826c43043b5b02a6049c50d94cafee0a0af09c5b Mon Sep 17 00:00:00 2001 From: Sagar Prajapati <sagarprajapati48@gmail.com> Date: Tue, 3 Dec 2024 14:54:46 +0530 Subject: [PATCH 1823/1908] Align Submenu block and Nav Link block by including description and wrapping span (#67198) * Fix missing wp-block-navigation-item__label span * Addressed feedback * Updated README.md Co-authored-by: prajapatisagar <sagarprajapati@git.wordpress.org> Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> --- .../block-library/src/navigation-submenu/edit.js | 5 +++++ .../src/navigation-submenu/index.php | 16 ++++++++++++++++ packages/block-library/src/navigation/README.md | 1 + 3 files changed, 22 insertions(+) diff --git a/packages/block-library/src/navigation-submenu/edit.js b/packages/block-library/src/navigation-submenu/edit.js index acc9510d0d3d30..261b2ad8502fb8 100644 --- a/packages/block-library/src/navigation-submenu/edit.js +++ b/packages/block-library/src/navigation-submenu/edit.js @@ -474,6 +474,11 @@ export default function NavigationSubmenuEdit( { } } } /> + { description && ( + <span className="wp-block-navigation-item__description"> + { description } + </span> + ) } { ! openSubmenusOnClick && isLinkOpen && ( <LinkUI clientId={ clientId } diff --git a/packages/block-library/src/navigation-submenu/index.php b/packages/block-library/src/navigation-submenu/index.php index d61dbb2426c240..0f560e2849fac2 100644 --- a/packages/block-library/src/navigation-submenu/index.php +++ b/packages/block-library/src/navigation-submenu/index.php @@ -159,7 +159,16 @@ function render_block_core_navigation_submenu( $attributes, $content, $block ) { $html .= '>'; // End appending HTML attributes to anchor tag. + $html .= '<span class="wp-block-navigation-item__label">'; $html .= $label; + $html .= '</span>'; + + // Add description if available. + if ( ! empty( $attributes['description'] ) ) { + $html .= '<span class="wp-block-navigation-item__description">'; + $html .= wp_kses_post( $attributes['description'] ); + $html .= '</span>'; + } $html .= '</a>'; // End anchor tag content. @@ -180,6 +189,13 @@ function render_block_core_navigation_submenu( $attributes, $content, $block ) { $html .= '</span>'; + // Add description if available. + if ( ! empty( $attributes['description'] ) ) { + $html .= '<span class="wp-block-navigation-item__description">'; + $html .= wp_kses_post( $attributes['description'] ); + $html .= '</span>'; + } + $html .= '</button>'; $html .= '<span class="wp-block-navigation__submenu-icon">' . block_core_navigation_submenu_render_submenu_icon() . '</span>'; diff --git a/packages/block-library/src/navigation/README.md b/packages/block-library/src/navigation/README.md index b59c4b40d85e73..cbd52a8f21f0ed 100644 --- a/packages/block-library/src/navigation/README.md +++ b/packages/block-library/src/navigation/README.md @@ -10,4 +10,5 @@ The structural CSS for the navigation block targets generic classnames across me - `.wp-block-navigation-item` is applied to every menu item. - `.wp-block-navigation-item__content` is applied to the link inside a menu item. - `.wp-block-navigation-item__label` is applied to the innermost container around the menu item text label. +- `.wp-block-navigation-item__description` is applied to the innermost container around the menu item description. - `.wp-block-navigation__submenu-icon` is applied to the submenu indicator (chevron). From 5900cf69ec81c3fa7c446499769929eda0a7b3ce Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Tue, 3 Dec 2024 10:48:09 +0100 Subject: [PATCH 1824/1908] Move `duplicateTemplatePart` action to the `@wordpress/fields` package (#65390) Co-authored-by: gigitux <gigitux@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- packages/base-styles/_z-index.scss | 2 +- .../post-actions/set-as-homepage.js | 17 ++- .../convert-to-template-part.js | 2 +- .../editor/src/dataviews/actions/utils.ts | 64 --------- .../src/dataviews/store/private-actions.ts | 4 +- packages/editor/src/dataviews/types.ts | 88 ------------ packages/editor/src/private-apis.js | 2 +- packages/editor/src/style.scss | 1 - packages/fields/README.md | 25 ++++ .../src}/actions/duplicate-template-part.tsx | 12 +- packages/fields/src/actions/index.ts | 1 + packages/fields/src/actions/rename-post.tsx | 9 +- packages/fields/src/actions/reset-post.tsx | 13 +- packages/fields/src/actions/utils.ts | 18 +-- .../create-template-part-modal/index.tsx} | 130 +++++++++++++----- .../create-template-part-modal/style.scss | 14 +- .../create-template-part-modal/test/utils.js | 0 .../create-template-part-modal/utils.js | 23 ++-- packages/fields/src/index.ts | 3 +- packages/fields/src/style.scss | 1 + packages/fields/src/types.ts | 3 + packages/fields/tsconfig.json | 1 + 22 files changed, 185 insertions(+), 248 deletions(-) delete mode 100644 packages/editor/src/dataviews/actions/utils.ts delete mode 100644 packages/editor/src/dataviews/types.ts rename packages/{editor/src/dataviews => fields/src}/actions/duplicate-template-part.tsx (87%) rename packages/{editor/src/components/create-template-part-modal/index.js => fields/src/components/create-template-part-modal/index.tsx} (52%) rename packages/{editor => fields}/src/components/create-template-part-modal/style.scss (69%) rename packages/{editor => fields}/src/components/create-template-part-modal/test/utils.js (100%) rename packages/{editor => fields}/src/components/create-template-part-modal/utils.js (86%) diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index 167af583ed9ddb..c2ee8f698c2c80 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -123,7 +123,7 @@ $z-layers: ( // Should be above the popover (dropdown) ".reusable-blocks-menu-items__convert-modal": 1000001, ".patterns-menu-items__convert-modal": 1000001, - ".editor-create-template-part-modal": 1000001, + ".fields-create-template-part-modal": 1000001, ".block-editor-block-lock-modal": 1000001, ".block-editor-template-part__selection-modal": 1000001, ".block-editor-block-rename-modal": 1000001, diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index 0366a52482f2a8..70bdeeeefe70fb 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -12,11 +12,20 @@ import { import { useDispatch, useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { store as noticesStore } from '@wordpress/notices'; +import { decodeEntities } from '@wordpress/html-entities'; -/** - * Internal dependencies - */ -import { getItemTitle } from '../../dataviews/actions/utils'; +const getItemTitle = ( item ) => { + if ( typeof item.title === 'string' ) { + return decodeEntities( item.title ); + } + if ( item.title && 'rendered' in item.title ) { + return decodeEntities( item.title.rendered ); + } + if ( item.title && 'raw' in item.title ) { + return decodeEntities( item.title.raw ); + } + return ''; +}; const SetAsHomepageModal = ( { items, closeModal } ) => { const [ item ] = items; diff --git a/packages/editor/src/components/template-part-menu-items/convert-to-template-part.js b/packages/editor/src/components/template-part-menu-items/convert-to-template-part.js index 4ae15d1dd178c0..9ce11772a34b7a 100644 --- a/packages/editor/src/components/template-part-menu-items/convert-to-template-part.js +++ b/packages/editor/src/components/template-part-menu-items/convert-to-template-part.js @@ -13,7 +13,7 @@ import { symbolFilled } from '@wordpress/icons'; /** * Internal dependencies */ -import CreateTemplatePartModal from '../create-template-part-modal'; +import { CreateTemplatePartModal } from '@wordpress/fields'; export default function ConvertToTemplatePart( { clientIds, blocks } ) { const [ isModalOpen, setIsModalOpen ] = useState( false ); diff --git a/packages/editor/src/dataviews/actions/utils.ts b/packages/editor/src/dataviews/actions/utils.ts deleted file mode 100644 index 33a2be16397f3f..00000000000000 --- a/packages/editor/src/dataviews/actions/utils.ts +++ /dev/null @@ -1,64 +0,0 @@ -/** - * WordPress dependencies - */ -import { decodeEntities } from '@wordpress/html-entities'; - -/** - * Internal dependencies - */ -import { - TEMPLATE_ORIGINS, - TEMPLATE_PART_POST_TYPE, - TEMPLATE_POST_TYPE, -} from '../../store/constants'; - -import type { Post, TemplatePart, Template } from '../types'; - -export function isTemplate( post: Post ): post is Template { - return post.type === TEMPLATE_POST_TYPE; -} - -export function isTemplatePart( post: Post ): post is TemplatePart { - return post.type === TEMPLATE_PART_POST_TYPE; -} - -export function isTemplateOrTemplatePart( - p: Post -): p is Template | TemplatePart { - return p.type === TEMPLATE_POST_TYPE || p.type === TEMPLATE_PART_POST_TYPE; -} - -export function getItemTitle( item: Post ) { - if ( typeof item.title === 'string' ) { - return decodeEntities( item.title ); - } - if ( 'rendered' in item.title ) { - return decodeEntities( item.title.rendered ); - } - if ( 'raw' in item.title ) { - return decodeEntities( item.title.raw ); - } - return ''; -} - -/** - * Check if a template is removable. - * - * @param template The template entity to check. - * @return Whether the template is removable. - */ -export function isTemplateRemovable( template: Template | TemplatePart ) { - if ( ! template ) { - return false; - } - // In patterns list page we map the templates parts to a different object - // than the one returned from the endpoint. This is why we need to check for - // two props whether is custom or has a theme file. - return ( - [ template.source, template.source ].includes( - TEMPLATE_ORIGINS.custom - ) && - ! Boolean( template.type === 'wp_template' && template?.plugin ) && - ! template.has_theme_file - ); -} diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 9e8d184e34d3a4..e61ade7e830364 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -8,9 +8,9 @@ import { doAction } from '@wordpress/hooks'; /** * Internal dependencies */ -import type { PostType } from '../types'; import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; +import type { PostType } from '@wordpress/fields'; import { viewPost, viewPostRevisions, @@ -24,6 +24,7 @@ import { renamePost, resetPost, deletePost, + duplicateTemplatePart, featuredImageField, dateField, parentField, @@ -34,7 +35,6 @@ import { authorField, titleField, } from '@wordpress/fields'; -import duplicateTemplatePart from '../actions/duplicate-template-part'; export function registerEntityAction< Item >( kind: string, diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts deleted file mode 100644 index 9549e6c4aa374d..00000000000000 --- a/packages/editor/src/dataviews/types.ts +++ /dev/null @@ -1,88 +0,0 @@ -type PostStatus = - | 'publish' - | 'draft' - | 'pending' - | 'private' - | 'future' - | 'auto-draft' - | 'trash'; - -export interface CommonPost { - status?: PostStatus; - title: string | { rendered: string } | { raw: string }; - content: string | { raw: string; rendered: string }; - type: string; - id: string | number; - blocks?: Object[]; - _links?: Links; -} - -interface Links { - 'predecessor-version'?: { href: string; id: number }[]; - 'version-history'?: { href: string; count: number }[]; - [ key: string ]: { href: string }[] | undefined; -} - -export interface BasePost extends CommonPost { - comment_status?: 'open' | 'closed'; - excerpt?: string | { raw: string; rendered: string }; - meta?: Record< string, any >; - parent?: number; - password?: string; - template?: string; - format?: string; - featured_media?: number; - menu_order?: number; - ping_status?: 'open' | 'closed'; - link?: string; -} - -export interface Template extends CommonPost { - type: 'wp_template'; - is_custom: boolean; - source: string; - origin: string; - plugin?: string; - has_theme_file: boolean; - id: string; -} - -export interface TemplatePart extends CommonPost { - type: 'wp_template_part'; - source: string; - origin: string; - has_theme_file: boolean; - id: string; - area: string; -} - -export interface Pattern extends CommonPost { - slug: string; - title: { raw: string }; - wp_pattern_sync_status: string; -} - -export type Post = Template | TemplatePart | Pattern | BasePost; - -export type PostWithPermissions = Post & { - permissions: { - delete: boolean; - update: boolean; - }; -}; - -export interface PostType { - slug: string; - viewable: boolean; - supports?: { - 'page-attributes'?: boolean; - title?: boolean; - revisions?: boolean; - thumbnail?: boolean; - comments?: boolean; - author?: boolean; - }; -} - -// Will be unnecessary after typescript 5.0 upgrade. -export type CoreDataError = { message?: string; code?: string }; diff --git a/packages/editor/src/private-apis.js b/packages/editor/src/private-apis.js index 2699858b3164f6..11083eb6ab8a45 100644 --- a/packages/editor/src/private-apis.js +++ b/packages/editor/src/private-apis.js @@ -10,7 +10,6 @@ import { lock } from './lock-unlock'; import { EntitiesSavedStatesExtensible } from './components/entities-saved-states'; import EditorContentSlotFill from './components/editor-interface/content-slot-fill'; import BackButton from './components/header/back-button'; -import CreateTemplatePartModal from './components/create-template-part-modal'; import Editor from './components/editor'; import PluginPostExcerpt from './components/post-excerpt/plugin'; import PostCardPanel from './components/post-card-panel'; @@ -24,6 +23,7 @@ import { mergeBaseAndUserConfigs, GlobalStylesProvider, } from './components/global-styles-provider'; +import { CreateTemplatePartModal } from '@wordpress/fields'; import { registerCoreBlockBindingsSources } from './bindings/api'; import { getTemplateInfo } from './utils/get-template-info'; diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss index 1504211a51e899..1a8103ae2b16c4 100644 --- a/packages/editor/src/style.scss +++ b/packages/editor/src/style.scss @@ -3,7 +3,6 @@ @import "./components/autocompleters/style.scss"; @import "./components/collab-sidebar/style.scss"; @import "./components/collapsible-block-toolbar/style.scss"; -@import "./components/create-template-part-modal/style.scss"; @import "./components/block-settings-menu/style.scss"; @import "./components/blog-title/style.scss"; @import "./components/document-bar/style.scss"; diff --git a/packages/fields/README.md b/packages/fields/README.md index e6cf6d3007ed97..6723611d2d9686 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -18,10 +18,23 @@ npm install @wordpress/fields --save Author field for BasePost. +### BasePostWithEmbeddedAuthor + +Undocumented declaration. + ### commentStatusField Comment status field for BasePost. +### CreateTemplatePartModal + +A React component that renders a modal for creating a template part. The modal displays a title and the contents for creating the template part. This component should not live in this package, it should be moved to a dedicated package responsible for managing template. + +_Parameters_ + +- _props_ `Object`: The component props. +- _props.modalTitle_ `{ modalTitle: string; } & CreateTemplatePartModalContentsProps[ 'modalTitle' ]`: + ### dateField Date field for BasePost. @@ -42,6 +55,14 @@ Undocumented declaration. Undocumented declaration. +### duplicateTemplatePart + +This action is used to duplicate a template part. + +_Type_ + +- `Action< TemplatePart >` + ### exportPattern Undocumented declaration. @@ -70,6 +91,10 @@ This field is used to display the post password. Undocumented declaration. +### PostType + +Undocumented declaration. + ### renamePost Undocumented declaration. diff --git a/packages/editor/src/dataviews/actions/duplicate-template-part.tsx b/packages/fields/src/actions/duplicate-template-part.tsx similarity index 87% rename from packages/editor/src/dataviews/actions/duplicate-template-part.tsx rename to packages/fields/src/actions/duplicate-template-part.tsx index 5f576ecdb58639..44fcbad21f0733 100644 --- a/packages/editor/src/dataviews/actions/duplicate-template-part.tsx +++ b/packages/fields/src/actions/duplicate-template-part.tsx @@ -12,15 +12,17 @@ import type { Action } from '@wordpress/dataviews'; /** * Internal dependencies */ -import { TEMPLATE_PART_POST_TYPE } from '../../store/constants'; -import { CreateTemplatePartModalContents } from '../../components/create-template-part-modal'; -import { getItemTitle } from './utils'; import type { Post, TemplatePart } from '../types'; +import { CreateTemplatePartModalContents } from '../components/create-template-part-modal'; +import { getItemTitle } from './utils'; +/** + * This action is used to duplicate a template part. + */ const duplicateTemplatePart: Action< TemplatePart > = { id: 'duplicate-template-part', label: _x( 'Duplicate', 'action label' ), - isEligible: ( item ) => item.type === TEMPLATE_PART_POST_TYPE, + isEligible: ( item ) => item.type === 'wp_template_part', modalHeader: _x( 'Duplicate template part', 'action label' ), RenderModal: ( { items, closeModal } ) => { const [ item ] = items; @@ -61,7 +63,7 @@ const duplicateTemplatePart: Action< TemplatePart > = { onCreate={ onTemplatePartSuccess } onError={ closeModal } confirmLabel={ _x( 'Duplicate', 'action label' ) } - closeModal={ closeModal } + closeModal={ closeModal ?? ( () => {} ) } /> ); }, diff --git a/packages/fields/src/actions/index.ts b/packages/fields/src/actions/index.ts index 08e22836e68fd1..fc662206775316 100644 --- a/packages/fields/src/actions/index.ts +++ b/packages/fields/src/actions/index.ts @@ -13,3 +13,4 @@ export { default as permanentlyDeletePost } from './permanently-delete-post'; export { default as restorePost } from './restore-post'; export { default as trashPost } from './trash-post'; export { default as deletePost } from './delete-post'; +export { default as duplicateTemplatePart } from './duplicate-template-part'; diff --git a/packages/fields/src/actions/rename-post.tsx b/packages/fields/src/actions/rename-post.tsx index da1fd46669f0df..5203328b46de53 100644 --- a/packages/fields/src/actions/rename-post.tsx +++ b/packages/fields/src/actions/rename-post.tsx @@ -26,9 +26,6 @@ import { isTemplateRemovable, isTemplate, isTemplatePart, - TEMPLATE_ORIGINS, - TEMPLATE_PART_POST_TYPE, - TEMPLATE_POST_TYPE, } from './utils'; import type { CoreDataError, PostWithPermissions } from '../types'; @@ -45,8 +42,8 @@ const renamePost: Action< PostWithPermissions > = { // Templates, template parts and patterns have special checks for renaming. if ( ! [ - TEMPLATE_POST_TYPE, - TEMPLATE_PART_POST_TYPE, + 'wp_template', + 'wp_template_part', ...Object.values( PATTERN_TYPES ), ].includes( post.type ) ) { @@ -64,7 +61,7 @@ const renamePost: Action< PostWithPermissions > = { if ( isTemplatePart( post ) ) { return ( - post.source === TEMPLATE_ORIGINS.custom && + post.source === 'custom' && ! post?.has_theme_file && post.permissions?.update ); diff --git a/packages/fields/src/actions/reset-post.tsx b/packages/fields/src/actions/reset-post.tsx index 105d7b283b8334..3e6b2e29b68b65 100644 --- a/packages/fields/src/actions/reset-post.tsx +++ b/packages/fields/src/actions/reset-post.tsx @@ -22,12 +22,7 @@ import apiFetch from '@wordpress/api-fetch'; /** * Internal dependencies */ -import { - getItemTitle, - isTemplateOrTemplatePart, - TEMPLATE_ORIGINS, - TEMPLATE_POST_TYPE, -} from './utils'; +import { getItemTitle, isTemplateOrTemplatePart } from './utils'; import type { CoreDataError, Template, TemplatePart } from '../types'; const isTemplateRevertable = ( @@ -38,7 +33,7 @@ const isTemplateRevertable = ( } return ( - templateOrTemplatePart.source === TEMPLATE_ORIGINS.custom && + templateOrTemplatePart.source === 'custom' && ( Boolean( templateOrTemplatePart?.plugin ) || templateOrTemplatePart?.has_theme_file ) ); @@ -186,7 +181,7 @@ const resetPostAction: Action< Template | TemplatePart > = { isEligible: ( item ) => { return ( isTemplateOrTemplatePart( item ) && - item?.source === TEMPLATE_ORIGINS.custom && + item?.source === 'custom' && ( Boolean( item.type === 'wp_template' && item?.plugin ) || item?.has_theme_file ) ); @@ -231,7 +226,7 @@ const resetPostAction: Action< Template | TemplatePart > = { ); } catch ( error ) { let fallbackErrorMessage; - if ( items[ 0 ].type === TEMPLATE_POST_TYPE ) { + if ( items[ 0 ].type === 'wp_template' ) { fallbackErrorMessage = items.length === 1 ? __( diff --git a/packages/fields/src/actions/utils.ts b/packages/fields/src/actions/utils.ts index 8f990fb1168fcc..efd389405b5be8 100644 --- a/packages/fields/src/actions/utils.ts +++ b/packages/fields/src/actions/utils.ts @@ -8,26 +8,18 @@ import { decodeEntities } from '@wordpress/html-entities'; */ import type { Post, TemplatePart, Template } from '../types'; -export const TEMPLATE_POST_TYPE = 'wp_template'; -export const TEMPLATE_PART_POST_TYPE = 'wp_template_part'; -export const TEMPLATE_ORIGINS = { - custom: 'custom', - theme: 'theme', - plugin: 'plugin', -}; - export function isTemplate( post: Post ): post is Template { - return post.type === TEMPLATE_POST_TYPE; + return post.type === 'wp_template'; } export function isTemplatePart( post: Post ): post is TemplatePart { - return post.type === TEMPLATE_PART_POST_TYPE; + return post.type === 'wp_template_part'; } export function isTemplateOrTemplatePart( p: Post ): p is Template | TemplatePart { - return p.type === TEMPLATE_POST_TYPE || p.type === TEMPLATE_PART_POST_TYPE; + return p.type === 'wp_template' || p.type === 'wp_template_part'; } export function getItemTitle( item: Post ): string { @@ -57,9 +49,7 @@ export function isTemplateRemovable( template: Template | TemplatePart ) { // than the one returned from the endpoint. This is why we need to check for // two props whether is custom or has a theme file. return ( - [ template.source, template.source ].includes( - TEMPLATE_ORIGINS.custom - ) && + [ template.source, template.source ].includes( 'custom' ) && ! Boolean( template.type === 'wp_template' && template?.plugin ) && ! template.has_theme_file ); diff --git a/packages/editor/src/components/create-template-part-modal/index.js b/packages/fields/src/components/create-template-part-modal/index.tsx similarity index 52% rename from packages/editor/src/components/create-template-part-modal/index.js rename to packages/fields/src/components/create-template-part-modal/index.tsx index 660439ded2300f..03b39a8fdcdf39 100644 --- a/packages/editor/src/components/create-template-part-modal/index.js +++ b/packages/fields/src/components/create-template-part-modal/index.tsx @@ -1,7 +1,6 @@ /** * WordPress dependencies */ -import { useSelect, useDispatch } from '@wordpress/data'; import { Icon, BaseControl, @@ -16,34 +15,57 @@ import { __experimentalHStack as HStack, __experimentalVStack as VStack, } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import { useState } from '@wordpress/element'; import { useInstanceId } from '@wordpress/compose'; -import { store as noticesStore } from '@wordpress/notices'; import { store as coreStore } from '@wordpress/core-data'; -import { check } from '@wordpress/icons'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { useState } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { + check, + footer as footerIcon, + header as headerIcon, + sidebar as sidebarIcon, + symbolFilled as symbolFilledIcon, +} from '@wordpress/icons'; +import { store as noticesStore } from '@wordpress/notices'; +// @ts-ignore import { serialize } from '@wordpress/blocks'; /** * Internal dependencies */ import { - TEMPLATE_PART_POST_TYPE, - TEMPLATE_PART_AREA_DEFAULT_CATEGORY, -} from '../../store/constants'; -import { - useExistingTemplateParts, - getUniqueTemplatePartTitle, getCleanTemplatePartSlug, + getUniqueTemplatePartTitle, + useExistingTemplateParts, } from './utils'; +type CreateTemplatePartModalContentsProps = { + defaultArea?: string; + blocks: any[]; + confirmLabel?: string; + closeModal: () => void; + onCreate: ( templatePart: any ) => void; + onError?: () => void; + defaultTitle?: string; +}; + +/** + * A React component that renders a modal for creating a template part. The modal displays a title and the contents for creating the template part. + * This component should not live in this package, it should be moved to a dedicated package responsible for managing template. + * @param {Object} props The component props. + * @param props.modalTitle + */ export default function CreateTemplatePartModal( { modalTitle, ...restProps -} ) { +}: { + modalTitle: string; +} & CreateTemplatePartModalContentsProps ) { const defaultModalTitle = useSelect( ( select ) => - select( coreStore ).getPostType( TEMPLATE_PART_POST_TYPE )?.labels + // @ts-ignore + select( coreStore ).getPostType( 'wp_template_part' )?.labels ?.add_new_item, [] ); @@ -51,24 +73,49 @@ export default function CreateTemplatePartModal( { <Modal title={ modalTitle || defaultModalTitle } onRequestClose={ restProps.closeModal } - overlayClassName="editor-create-template-part-modal" + overlayClassName="fields-create-template-part-modal" focusOnMount="firstContentElement" size="medium" > + { /* @ts-ignore */ } <CreateTemplatePartModalContents { ...restProps } /> </Modal> ); } +const getTemplatePartIcon = ( iconName: string ) => { + if ( 'header' === iconName ) { + return headerIcon; + } else if ( 'footer' === iconName ) { + return footerIcon; + } else if ( 'sidebar' === iconName ) { + return sidebarIcon; + } + return symbolFilledIcon; +}; + +/** + * A React component that renders the content of a model for creating a template part. + * This component should not live in this package; it should be moved to a dedicated package responsible for managing template. + * + * @param {Object} props - The component props. + * @param {string} [props.defaultArea=uncategorized] - The default area for the template part. + * @param {Array} [props.blocks=[]] - The blocks to be included in the template part. + * @param {string} [props.confirmLabel='Add'] - The label for the confirm button. + * @param {Function} props.closeModal - Function to close the modal. + * @param {Function} props.onCreate - Function to call when the template part is successfully created. + * @param {Function} [props.onError] - Function to call when there is an error creating the template part. + * @param {string} [props.defaultTitle=''] - The default title for the template part. + */ export function CreateTemplatePartModalContents( { - defaultArea = TEMPLATE_PART_AREA_DEFAULT_CATEGORY, + defaultArea = 'uncategorized', blocks = [], confirmLabel = __( 'Add' ), closeModal, onCreate, onError, defaultTitle = '', -} ) { +}: CreateTemplatePartModalContentsProps ) { const { createErrorNotice } = useDispatch( noticesStore ); const { saveEntityRecord } = useDispatch( coreStore ); const existingTemplateParts = useExistingTemplateParts(); @@ -78,12 +125,22 @@ export function CreateTemplatePartModalContents( { const [ isSubmitting, setIsSubmitting ] = useState( false ); const instanceId = useInstanceId( CreateTemplatePartModal ); - const templatePartAreas = useSelect( - ( select ) => - select( coreStore ).getEntityRecord( 'root', '__unstableBase' ) - ?.default_template_part_areas || [], - [] - ); + const defaultTemplatePartAreas = useSelect( ( select ) => { + const areas = + // @ts-expect-error getEntityRecord is not typed with unstableBase as argument. + select( coreStore ).getEntityRecord< { + default_template_part_areas: Array< { + area: string; + label: string; + icon: string; + description: string; + } >; + } >( 'root', '__unstableBase' )?.default_template_part_areas || []; + + return areas.map( ( item ) => { + return { ...item, icon: getTemplatePartIcon( item.icon ) }; + } ); + }, [] ); async function createTemplatePart() { if ( ! title || isSubmitting ) { @@ -100,7 +157,7 @@ export function CreateTemplatePartModalContents( { const templatePart = await saveEntityRecord( 'postType', - TEMPLATE_PART_POST_TYPE, + 'wp_template_part', { slug: cleanSlug, title: uniqueTitle, @@ -114,7 +171,10 @@ export function CreateTemplatePartModalContents( { // TODO: Add a success notice? } catch ( error ) { const errorMessage = - error.message && error.code !== 'unknown_error' + error instanceof Error && + 'code' in error && + error.message && + error.code !== 'unknown_error' ? error.message : __( 'An error occurred while creating the template part.' @@ -146,34 +206,38 @@ export function CreateTemplatePartModalContents( { <BaseControl __nextHasNoMarginBottom label={ __( 'Area' ) } - id={ `editor-create-template-part-modal__area-selection-${ instanceId }` } - className="editor-create-template-part-modal__area-base-control" + id={ `fields-create-template-part-modal__area-selection-${ instanceId }` } + className="fields-create-template-part-modal__area-base-control" > <RadioGroup label={ __( 'Area' ) } - className="editor-create-template-part-modal__area-radio-group" - id={ `editor-create-template-part-modal__area-selection-${ instanceId }` } - onChange={ setArea } + className="fields-create-template-part-modal__area-radio-group" + id={ `fields-create-template-part-modal__area-selection-${ instanceId }` } + onChange={ ( value ) => + value && typeof value === 'string' + ? setArea( value ) + : () => void 0 + } checked={ area } > - { templatePartAreas.map( + { defaultTemplatePartAreas.map( ( { icon, label, area: value, description } ) => ( <Radio __next40pxDefaultSize key={ label } value={ value } - className="editor-create-template-part-modal__area-radio" + className="fields-create-template-part-modal__area-radio" > <Flex align="start" justify="start"> <FlexItem> <Icon icon={ icon } /> </FlexItem> - <FlexBlock className="editor-create-template-part-modal__option-label"> + <FlexBlock className="fields-create-template-part-modal__option-label"> { label } <div>{ description }</div> </FlexBlock> - <FlexItem className="editor-create-template-part-modal__checkbox"> + <FlexItem className="fields-create-template-part-modal__checkbox"> { area === value && ( <Icon icon={ check } /> ) } diff --git a/packages/editor/src/components/create-template-part-modal/style.scss b/packages/fields/src/components/create-template-part-modal/style.scss similarity index 69% rename from packages/editor/src/components/create-template-part-modal/style.scss rename to packages/fields/src/components/create-template-part-modal/style.scss index be15e8d76d536e..fedc0326648c2e 100644 --- a/packages/editor/src/components/create-template-part-modal/style.scss +++ b/packages/fields/src/components/create-template-part-modal/style.scss @@ -1,13 +1,13 @@ -.editor-create-template-part-modal { - z-index: z-index(".editor-create-template-part-modal"); +.fields-create-template-part-modal { + z-index: z-index(".fields-create-template-part-modal"); } -.editor-create-template-part-modal__area-radio-group { +.fields-create-template-part-modal__area-radio-group { width: 100%; border: $border-width solid $gray-700; border-radius: $radius-small; - .components-button.editor-create-template-part-modal__area-radio { + .components-button.fields-create-template-part-modal__area-radio { display: block; width: 100%; height: 100%; @@ -40,12 +40,12 @@ color: $gray-900; cursor: auto; - .editor-create-template-part-modal__option-label div { + .fields-create-template-part-modal__option-label div { color: $gray-600; } } - .editor-create-template-part-modal__option-label { + .fields-create-template-part-modal__option-label { padding-top: $grid-unit-05; white-space: normal; @@ -55,7 +55,7 @@ } } - .editor-create-template-part-modal__checkbox { + .fields-create-template-part-modal__checkbox { margin-left: auto; min-width: $grid-unit-30; } diff --git a/packages/editor/src/components/create-template-part-modal/test/utils.js b/packages/fields/src/components/create-template-part-modal/test/utils.js similarity index 100% rename from packages/editor/src/components/create-template-part-modal/test/utils.js rename to packages/fields/src/components/create-template-part-modal/test/utils.js diff --git a/packages/editor/src/components/create-template-part-modal/utils.js b/packages/fields/src/components/create-template-part-modal/utils.js similarity index 86% rename from packages/editor/src/components/create-template-part-modal/utils.js rename to packages/fields/src/components/create-template-part-modal/utils.js index 02f24cf17d2be9..9ecf3efd03f918 100644 --- a/packages/editor/src/components/create-template-part-modal/utils.js +++ b/packages/fields/src/components/create-template-part-modal/utils.js @@ -12,19 +12,20 @@ import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies */ -import { TEMPLATE_PART_POST_TYPE } from '../../store/constants'; export const useExistingTemplateParts = () => { - return useSelect( - ( select ) => - select( coreStore ).getEntityRecords( - 'postType', - TEMPLATE_PART_POST_TYPE, - { - per_page: -1, - } - ), - [] + return ( + useSelect( + ( select ) => + select( coreStore ).getEntityRecords( + 'postType', + 'wp_template_part', + { + per_page: -1, + } + ), + [] + ) ?? [] ); }; diff --git a/packages/fields/src/index.ts b/packages/fields/src/index.ts index 41879a86e76bed..1658c9d8c51eee 100644 --- a/packages/fields/src/index.ts +++ b/packages/fields/src/index.ts @@ -1,3 +1,4 @@ export * from './fields'; export * from './actions'; -export type * from './types'; +export { default as CreateTemplatePartModal } from './components/create-template-part-modal'; +export type { BasePostWithEmbeddedAuthor, PostType } from './types'; diff --git a/packages/fields/src/style.scss b/packages/fields/src/style.scss index 1639f455ba093e..05cf5652248777 100644 --- a/packages/fields/src/style.scss +++ b/packages/fields/src/style.scss @@ -1,2 +1,3 @@ +@import "./components/create-template-part-modal/style.scss"; @import "./fields/slug/style.scss"; @import "./fields/featured-image/style.scss"; diff --git a/packages/fields/src/types.ts b/packages/fields/src/types.ts index e457ec699554cd..1b251d125b1be8 100644 --- a/packages/fields/src/types.ts +++ b/packages/fields/src/types.ts @@ -97,6 +97,9 @@ export interface PostType { 'page-attributes'?: boolean; title?: boolean; revisions?: boolean; + author?: string; + thumbnail?: string; + comments?: string; }; } diff --git a/packages/fields/tsconfig.json b/packages/fields/tsconfig.json index 5c4b91e88f895a..531afb5bb2d873 100644 --- a/packages/fields/tsconfig.json +++ b/packages/fields/tsconfig.json @@ -12,6 +12,7 @@ { "path": "../components" }, { "path": "../compose" }, { "path": "../core-data" }, + { "path": "../block-editor" }, { "path": "../data" }, { "path": "../dataviews" }, { "path": "../date" }, From fa438ca92e3a2fe212b6f573cb41937f574199a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= <grzegorz@gziolo.pl> Date: Tue, 3 Dec 2024 11:28:05 +0100 Subject: [PATCH 1825/1908] =?UTF-8?q?Revert=20"Extensibility:=20Make=20Blo?= =?UTF-8?q?ck=20Bindings=20work=20with=20`editor.BlockEdit`=20hook=20?= =?UTF-8?q?=E2=80=A6"=20(#67516)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit c517e410017f4d65a7c6f03a31c5c2fa15cbbd65. Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> --- .../src/components/block-edit/edit.js | 12 +- .../block-list/use-block-props/index.js | 2 +- .../src/components/rich-text/index.js | 2 +- .../block-editor/src/hooks/block-bindings.js | 10 +- packages/block-editor/src/hooks/index.js | 1 + .../use-bindings-attributes.js} | 103 ++++++++++++++---- .../block-editor/src/utils/block-bindings.js | 37 ------- packages/e2e-tests/plugins/block-bindings.php | 6 +- .../e2e-tests/plugins/block-bindings/index.js | 45 -------- .../various/block-bindings/post-meta.spec.js | 41 ------- 10 files changed, 94 insertions(+), 165 deletions(-) rename packages/block-editor/src/{components/block-edit/with-block-bindings-support.js => hooks/use-bindings-attributes.js} (73%) diff --git a/packages/block-editor/src/components/block-edit/edit.js b/packages/block-editor/src/components/block-edit/edit.js index 6b1ddd86f4c76e..83d0e3f406f829 100644 --- a/packages/block-editor/src/components/block-edit/edit.js +++ b/packages/block-editor/src/components/block-edit/edit.js @@ -18,8 +18,6 @@ import { useContext, useMemo } from '@wordpress/element'; * Internal dependencies */ import BlockContext from '../block-context'; -import { withBlockBindingsSupport } from './with-block-bindings-support'; -import { canBindBlock } from '../../utils/block-bindings'; /** * Default value used for blocks which do not define their own context needs, @@ -49,8 +47,6 @@ const Edit = ( props ) => { const EditWithFilters = withFilters( 'editor.BlockEdit' )( Edit ); -const EditWithFiltersAndBindings = withBlockBindingsSupport( EditWithFilters ); - const EditWithGeneratedProps = ( props ) => { const { attributes = {}, name } = props; const blockType = getBlockType( name ); @@ -71,12 +67,8 @@ const EditWithGeneratedProps = ( props ) => { return null; } - const EditComponent = canBindBlock( name ) - ? EditWithFiltersAndBindings - : EditWithFilters; - if ( blockType.apiVersion > 1 ) { - return <EditComponent { ...props } context={ context } />; + return <EditWithFilters { ...props } context={ context } />; } // Generate a class name for the block's editable form. @@ -90,7 +82,7 @@ const EditWithGeneratedProps = ( props ) => { ); return ( - <EditComponent + <EditWithFilters { ...props } context={ context } className={ className } diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index 7e50b75e1b9564..4696149dc38751 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -29,7 +29,7 @@ import { useBlockRefProvider } from './use-block-refs'; import { useIntersectionObserver } from './use-intersection-observer'; import { useScrollIntoView } from './use-scroll-into-view'; import { useFlashEditableBlocks } from '../../use-flash-editable-blocks'; -import { canBindBlock } from '../../../utils/block-bindings'; +import { canBindBlock } from '../../../hooks/use-bindings-attributes'; import { useFirefoxDraggableCompatibility } from './use-firefox-draggable-compatibility'; /** diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 768ffbb0cdd2dc..bc8eca6ea94d05 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -39,7 +39,7 @@ import FormatEdit from './format-edit'; import { getAllowedFormats } from './utils'; import { Content, valueToHTMLString } from './content'; import { withDeprecations } from './with-deprecations'; -import { canBindBlock } from '../../utils/block-bindings'; +import { canBindBlock } from '../../hooks/use-bindings-attributes'; import BlockContext from '../block-context'; export const keyboardShortcutContext = createContext(); diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index cec80dffaeaa16..e10696cc1257d7 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -23,15 +23,15 @@ import { useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies */ +import { + canBindAttribute, + getBindableAttributes, +} from '../hooks/use-bindings-attributes'; import { unlock } from '../lock-unlock'; import InspectorControls from '../components/inspector-controls'; import BlockContext from '../components/block-context'; import { useBlockEditContext } from '../components/block-edit'; -import { - canBindAttribute, - getBindableAttributes, - useBlockBindingsUtils, -} from '../utils/block-bindings'; +import { useBlockBindingsUtils } from '../utils/block-bindings'; import { store as blockEditorStore } from '../store'; const { Menu } = unlock( componentsPrivateApis ); diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index 7f9b29376ad1fb..66ff60b691b66f 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -32,6 +32,7 @@ import './metadata'; import blockHooks from './block-hooks'; import blockBindingsPanel from './block-bindings'; import './block-renaming'; +import './use-bindings-attributes'; import './grid-visualizer'; createBlockEditFilter( diff --git a/packages/block-editor/src/components/block-edit/with-block-bindings-support.js b/packages/block-editor/src/hooks/use-bindings-attributes.js similarity index 73% rename from packages/block-editor/src/components/block-edit/with-block-bindings-support.js rename to packages/block-editor/src/hooks/use-bindings-attributes.js index 0529c019b8deec..fdc617fda20c05 100644 --- a/packages/block-editor/src/components/block-edit/with-block-bindings-support.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -5,19 +5,31 @@ import { store as blocksStore } from '@wordpress/blocks'; import { createHigherOrderComponent } from '@wordpress/compose'; import { useRegistry, useSelect } from '@wordpress/data'; import { useCallback, useMemo, useContext } from '@wordpress/element'; +import { addFilter } from '@wordpress/hooks'; /** * Internal dependencies */ -import isURLLike from '../link-control/is-url-like'; -import { unlock } from '../../lock-unlock'; -import BlockContext from '../block-context'; -import { - BLOCK_BINDINGS_ALLOWED_BLOCKS, - canBindAttribute, -} from '../../utils/block-bindings'; +import isURLLike from '../components/link-control/is-url-like'; +import { unlock } from '../lock-unlock'; +import BlockContext from '../components/block-context'; /** @typedef {import('@wordpress/compose').WPHigherOrderComponent} WPHigherOrderComponent */ +/** @typedef {import('@wordpress/blocks').WPBlockSettings} WPBlockSettings */ + +/** + * Given a binding of block attributes, returns a higher order component that + * overrides its `attributes` and `setAttributes` props to sync any changes needed. + * + * @return {WPHigherOrderComponent} Higher-order component. + */ + +const BLOCK_BINDINGS_ALLOWED_BLOCKS = { + 'core/paragraph': [ 'content' ], + 'core/heading': [ 'content' ], + 'core/image': [ 'id', 'url', 'title', 'alt' ], + 'core/button': [ 'url', 'text', 'linkTarget', 'rel' ], +}; const DEFAULT_ATTRIBUTE = '__default'; @@ -55,12 +67,36 @@ function replacePatternOverrideDefaultBindings( blockName, bindings ) { } /** - * Given a binding of block attributes, returns a higher order component that - * overrides its `attributes` and `setAttributes` props to sync any changes needed. + * Based on the given block name, + * check if it is possible to bind the block. * - * @return {WPHigherOrderComponent} Higher-order component. + * @param {string} blockName - The block name. + * @return {boolean} Whether it is possible to bind the block to sources. */ -export const withBlockBindingsSupport = createHigherOrderComponent( +export function canBindBlock( blockName ) { + return blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS; +} + +/** + * Based on the given block name and attribute name, + * check if it is possible to bind the block attribute. + * + * @param {string} blockName - The block name. + * @param {string} attributeName - The attribute name. + * @return {boolean} Whether it is possible to bind the block attribute. + */ +export function canBindAttribute( blockName, attributeName ) { + return ( + canBindBlock( blockName ) && + BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ].includes( attributeName ) + ); +} + +export function getBindableAttributes( blockName ) { + return BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ]; +} + +export const withBlockBindingSupport = createHigherOrderComponent( ( BlockEdit ) => ( props ) => { const registry = useRegistry(); const blockContext = useContext( BlockContext ); @@ -72,9 +108,9 @@ export const withBlockBindingsSupport = createHigherOrderComponent( () => replacePatternOverrideDefaultBindings( name, - props.attributes?.metadata?.bindings + props.attributes.metadata?.bindings ), - [ props.attributes?.metadata?.bindings, name ] + [ props.attributes.metadata?.bindings, name ] ); // While this hook doesn't directly call any selectors, `useSelect` is @@ -160,7 +196,7 @@ export const withBlockBindingsSupport = createHigherOrderComponent( const hasParentPattern = !! updatedContext[ 'pattern/overrides' ]; const hasPatternOverridesDefaultBinding = - props.attributes?.metadata?.bindings?.[ DEFAULT_ATTRIBUTE ] + props.attributes.metadata?.bindings?.[ DEFAULT_ATTRIBUTE ] ?.source === 'core/pattern-overrides'; const _setAttributes = useCallback( @@ -247,13 +283,40 @@ export const withBlockBindingsSupport = createHigherOrderComponent( ); return ( - <BlockEdit - { ...props } - attributes={ { ...props.attributes, ...boundAttributes } } - setAttributes={ _setAttributes } - context={ { ...context, ...updatedContext } } - /> + <> + <BlockEdit + { ...props } + attributes={ { ...props.attributes, ...boundAttributes } } + setAttributes={ _setAttributes } + context={ { ...context, ...updatedContext } } + /> + </> ); }, 'withBlockBindingSupport' ); + +/** + * Filters a registered block's settings to enhance a block's `edit` component + * to upgrade bound attributes. + * + * @param {WPBlockSettings} settings - Registered block settings. + * @param {string} name - Block name. + * @return {WPBlockSettings} Filtered block settings. + */ +function shimAttributeSource( settings, name ) { + if ( ! canBindBlock( name ) ) { + return settings; + } + + return { + ...settings, + edit: withBlockBindingSupport( settings.edit ), + }; +} + +addFilter( + 'blocks.registerBlockType', + 'core/editor/custom-sources-backwards-compatibility/shim-attribute-source', + shimAttributeSource +); diff --git a/packages/block-editor/src/utils/block-bindings.js b/packages/block-editor/src/utils/block-bindings.js index 82f0dff53531a4..dcf80d985473b2 100644 --- a/packages/block-editor/src/utils/block-bindings.js +++ b/packages/block-editor/src/utils/block-bindings.js @@ -13,43 +13,6 @@ function isObjectEmpty( object ) { return ! object || Object.keys( object ).length === 0; } -export const BLOCK_BINDINGS_ALLOWED_BLOCKS = { - 'core/paragraph': [ 'content' ], - 'core/heading': [ 'content' ], - 'core/image': [ 'id', 'url', 'title', 'alt' ], - 'core/button': [ 'url', 'text', 'linkTarget', 'rel' ], -}; - -/** - * Based on the given block name, - * check if it is possible to bind the block. - * - * @param {string} blockName - The block name. - * @return {boolean} Whether it is possible to bind the block to sources. - */ -export function canBindBlock( blockName ) { - return blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS; -} - -/** - * Based on the given block name and attribute name, - * check if it is possible to bind the block attribute. - * - * @param {string} blockName - The block name. - * @param {string} attributeName - The attribute name. - * @return {boolean} Whether it is possible to bind the block attribute. - */ -export function canBindAttribute( blockName, attributeName ) { - return ( - canBindBlock( blockName ) && - BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ].includes( attributeName ) - ); -} - -export function getBindableAttributes( blockName ) { - return BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ]; -} - /** * Contains utils to update the block `bindings` metadata. * diff --git a/packages/e2e-tests/plugins/block-bindings.php b/packages/e2e-tests/plugins/block-bindings.php index 1fd6d8468c77db..b86673c2c523d0 100644 --- a/packages/e2e-tests/plugins/block-bindings.php +++ b/packages/e2e-tests/plugins/block-bindings.php @@ -41,11 +41,7 @@ function gutenberg_test_block_bindings_registration() { plugins_url( 'block-bindings/index.js', __FILE__ ), array( 'wp-blocks', - 'wp-block-editor', - 'wp-components', - 'wp-compose', - 'wp-element', - 'wp-hooks', + 'wp-private-apis', ), filemtime( plugin_dir_path( __FILE__ ) . 'block-bindings/index.js' ), true diff --git a/packages/e2e-tests/plugins/block-bindings/index.js b/packages/e2e-tests/plugins/block-bindings/index.js index 63c463e197fa8a..5c364257caed19 100644 --- a/packages/e2e-tests/plugins/block-bindings/index.js +++ b/packages/e2e-tests/plugins/block-bindings/index.js @@ -1,9 +1,4 @@ const { registerBlockBindingsSource } = wp.blocks; -const { InspectorControls } = wp.blockEditor; -const { PanelBody, TextControl } = wp.components; -const { createHigherOrderComponent } = wp.compose; -const { createElement: el, Fragment } = wp.element; -const { addFilter } = wp.hooks; const { fieldsList } = window.testingBindings || {}; const getValues = ( { bindings } ) => { @@ -51,43 +46,3 @@ registerBlockBindingsSource( { getValues, canUserEditValue: () => true, } ); - -const withBlockBindingsInspectorControl = createHigherOrderComponent( - ( BlockEdit ) => { - return ( props ) => { - if ( ! props.attributes?.metadata?.bindings?.content ) { - return el( BlockEdit, props ); - } - - return el( - Fragment, - {}, - el( BlockEdit, props ), - el( - InspectorControls, - {}, - el( - PanelBody, - { title: 'Bindings' }, - el( TextControl, { - __next40pxDefaultSize: true, - __nextHasNoMarginBottom: true, - label: 'Content', - value: props.attributes.content, - onChange: ( content ) => - props.setAttributes( { - content, - } ), - } ) - ) - ) - ); - }; - } -); - -addFilter( - 'editor.BlockEdit', - 'testing/bindings-inspector-control', - withBlockBindingsInspectorControl -); diff --git a/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js b/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js index 318707e22f098d..32334bfc777f2a 100644 --- a/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js +++ b/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js @@ -524,47 +524,6 @@ test.describe( 'Post Meta source', () => { previewPage.locator( '#connected-paragraph' ) ).toHaveText( 'new value' ); } ); - - test( 'should be possible to edit the value of the connected custom fields in the inspector control registered by the plugin', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - anchor: 'connected-paragraph', - content: 'fallback content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { - key: 'movie_field', - }, - }, - }, - }, - }, - } ); - const contentInput = page.getByRole( 'textbox', { - name: 'Content', - } ); - await expect( contentInput ).toHaveValue( - 'Movie field default value' - ); - await contentInput.fill( 'new value' ); - // Check that the paragraph content attribute didn't change. - const [ paragraphBlockObject ] = await editor.getBlocks(); - expect( paragraphBlockObject.attributes.content ).toBe( - 'fallback content' - ); - // Check the value of the custom field is being updated by visiting the frontend. - const previewPage = await editor.openPreviewPage(); - await expect( - previewPage.locator( '#connected-paragraph' ) - ).toHaveText( 'new value' ); - } ); - test( 'should be possible to connect movie fields through the attributes panel', async ( { editor, page, From fcee058e3bb787ee041c170958e15e66a6302352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= <grzegorz@gziolo.pl> Date: Tue, 3 Dec 2024 11:44:23 +0100 Subject: [PATCH 1826/1908] Scripts: Make React Fast Refresh work with multiple blocks (#64924) * Scripts: Make React Fast Refresh Work with multiple blocks * Properly pass the unique name for the build and updates test snapshots * Apply suggestions from code review * Add changelog entry Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- .../lib/index.js | 10 +++++++ .../test/__snapshots__/build.js.snap | 12 ++++---- packages/scripts/CHANGELOG.md | 4 +++ packages/scripts/config/webpack.config.js | 29 ++++++++++++++++++- 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/packages/dependency-extraction-webpack-plugin/lib/index.js b/packages/dependency-extraction-webpack-plugin/lib/index.js index cf780d7370dcfc..8bc7cb29312161 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/index.js +++ b/packages/dependency-extraction-webpack-plugin/lib/index.js @@ -387,6 +387,16 @@ class DependencyExtractionWebpackPlugin { assetData.type = 'module'; } + if ( compilation.options?.optimization?.runtimeChunk !== false ) { + // Sets the script handle for the shared runtime file so WordPress registers it only once when using the asset file. + assetData.handle = + compilation.name + + '-' + + chunkJSFile + .replace( /\\/g, '/' ) + .replace( jsExtensionRegExp, '' ); + } + if ( combineAssets ) { combinedAssetsData[ chunkJSFile ] = assetData; continue; diff --git a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap index 8ea40b00d7c2d1..bafae8eb914867 100644 --- a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap +++ b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap @@ -265,17 +265,17 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comm exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comment-minified\` should produce expected output: External modules should match snapshot 1`] = `[]`; exports[`DependencyExtractionWebpackPlugin modules Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'a.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('@wordpress/blob'), 'version' => 'ee5ac21a1f0003d732e6', 'type' => 'module'); +"<?php return array('dependencies' => array('@wordpress/blob'), 'version' => 'ee5ac21a1f0003d732e6', 'type' => 'module', 'handle' => 'runtime-chunk-single-modules-a'); " `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'b.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('@wordpress/blob', 'lodash'), 'version' => '5b112b32c6db548c2997', 'type' => 'module'); +"<?php return array('dependencies' => array('@wordpress/blob', 'lodash'), 'version' => '5b112b32c6db548c2997', 'type' => 'module', 'handle' => 'runtime-chunk-single-modules-b'); " `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'runtime.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array(), 'version' => 'b1ca4106075e0bd94f9c', 'type' => 'module'); +"<?php return array('dependencies' => array(), 'version' => 'b1ca4106075e0bd94f9c', 'type' => 'module', 'handle' => 'runtime-chunk-single-modules-runtime'); " `; @@ -681,17 +681,17 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comm exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comment-minified\` should produce expected output: External modules should match snapshot 1`] = `[]`; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'a.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('wp-blob'), 'version' => 'd091f1cbbf7603d6e12c'); +"<?php return array('dependencies' => array('wp-blob'), 'version' => 'd091f1cbbf7603d6e12c', 'handle' => 'runtime-chunk-single-scripts-a'); " `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'b.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '845bc6d4ffbdb9419ebd'); +"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '845bc6d4ffbdb9419ebd', 'handle' => 'runtime-chunk-single-scripts-b'); " `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'runtime.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array(), 'version' => '717eb779e609d175a7dd'); +"<?php return array('dependencies' => array(), 'version' => '717eb779e609d175a7dd', 'handle' => 'runtime-chunk-single-scripts-runtime'); " `; diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 55143ae792ae5b..ceaa25c4ff9a09 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fix + +- Make React Fast Refresh in the `start` command work with multiple blocks ([64924](https://github.com/WordPress/gutenberg/pull/64924)). + ## 30.6.0 (2024-11-27) ## 30.5.1 (2024-11-18) diff --git a/packages/scripts/config/webpack.config.js b/packages/scripts/config/webpack.config.js index f9ef7dc5b7acca..2c3d423fcbd1e8 100644 --- a/packages/scripts/config/webpack.config.js +++ b/packages/scripts/config/webpack.config.js @@ -7,7 +7,7 @@ const CopyWebpackPlugin = require( 'copy-webpack-plugin' ); const webpack = require( 'webpack' ); const browserslist = require( 'browserslist' ); const MiniCSSExtractPlugin = require( 'mini-css-extract-plugin' ); -const { basename, dirname, resolve } = require( 'path' ); +const { basename, dirname, relative, resolve, sep } = require( 'path' ); const ReactRefreshWebpackPlugin = require( '@pmmmwh/react-refresh-webpack-plugin' ); const RtlCssPlugin = require( 'rtlcss-webpack-plugin' ); const TerserPlugin = require( 'terser-webpack-plugin' ); @@ -115,6 +115,7 @@ const baseConfig = { optimization: { // Only concatenate modules in production, when not analyzing bundles. concatenateModules: isProduction && ! process.env.WP_BUNDLE_ANALYZER, + runtimeChunk: hasReactFastRefresh && 'single', splitChunks: { cacheGroups: { style: { @@ -340,6 +341,32 @@ const scriptConfig = { } } ); + if ( hasReactFastRefresh ) { + // Prepends the file reference to the shared runtime chunk to every script type defined for the block. + const runtimePath = relative( + dirname( absoluteFrom ), + fromProjectRoot( + getWordPressSrcDirectory() + + sep + + 'runtime.js' + ) + ); + const fields = + getBlockJsonScriptFields( blockJson ); + for ( const [ fieldName ] of Object.entries( + fields + ) ) { + blockJson[ fieldName ] = [ + `file:${ runtimePath }`, + ...( Array.isArray( + blockJson[ fieldName ] + ) + ? blockJson[ fieldName ] + : [ blockJson[ fieldName ] ] ), + ]; + } + } + return JSON.stringify( blockJson, null, 2 ); } From 5c76815eb6e47f8cdd8f32c919f431467b078366 Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Tue, 3 Dec 2024 12:14:33 +0100 Subject: [PATCH 1827/1908] Quick Edit: add Template field (#66591) Co-authored-by: louwie17 <louwie17@git.wordpress.org> Co-authored-by: gigitux <gigitux@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- package-lock.json | 1 + packages/base-styles/_z-index.scss | 1 + .../src/components/post-edit/index.js | 36 ++- .../src/dataviews/store/private-actions.ts | 2 + packages/fields/README.md | 4 + packages/fields/package.json | 1 + packages/fields/src/actions/utils.ts | 4 +- packages/fields/src/fields/index.ts | 1 + packages/fields/src/fields/template/index.ts | 22 ++ .../fields/src/fields/template/style.scss | 23 ++ .../src/fields/template/template-edit.tsx | 210 ++++++++++++++++++ packages/fields/src/style.scss | 1 + packages/fields/tsconfig.json | 1 + 13 files changed, 305 insertions(+), 2 deletions(-) create mode 100644 packages/fields/src/fields/template/index.ts create mode 100644 packages/fields/src/fields/template/style.scss create mode 100644 packages/fields/src/fields/template/template-edit.tsx diff --git a/package-lock.json b/package-lock.json index 98865c9d041a58..834bb344016d26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54694,6 +54694,7 @@ "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "*", "@wordpress/blob": "*", + "@wordpress/block-editor": "*", "@wordpress/blocks": "*", "@wordpress/components": "*", "@wordpress/compose": "*", diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index c2ee8f698c2c80..af679edb910642 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -132,6 +132,7 @@ $z-layers: ( ".editor-action-modal": 1000001, ".editor-post-template__swap-template-modal": 1000001, ".edit-site-template-panel__replace-template-modal": 1000001, + ".fields-controls__template-modal": 1000001, // Note: The ConfirmDialog component's z-index is being set to 1000001 in packages/components/src/confirm-dialog/styles.ts // because it uses emotion and not sass. We need it to render on top its parent popover. diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 3e75ef71d1ac9b..9a99a987089c1a 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -19,6 +19,8 @@ import { privateApis as editorPrivateApis } from '@wordpress/editor'; */ import Page from '../page'; import { unlock } from '../../lock-unlock'; +import usePatternSettings from '../page-patterns/use-pattern-settings'; +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; const { PostCardPanel, usePostFields } = unlock( editorPrivateApis ); @@ -85,6 +87,12 @@ function PostEditForm( { postType, postId } ) { 'slug', 'parent', 'comment_status', + { + label: __( 'Template' ), + labelPosition: 'side', + id: 'template', + layout: 'regular', + }, ].filter( ( field ) => ids.length === 1 || @@ -123,6 +131,32 @@ function PostEditForm( { postType, postId } ) { setMultiEdits( {} ); }, [ ids ] ); + const { ExperimentalBlockEditorProvider } = unlock( + blockEditorPrivateApis + ); + const settings = usePatternSettings(); + + /** + * The template field depends on the block editor settings. + * This is a workaround to ensure that the block editor settings are available. + * For more information, see: https://github.com/WordPress/gutenberg/issues/67521 + */ + const fieldsWithDependency = useMemo( () => { + return fields.map( ( field ) => { + if ( field.id === 'template' ) { + return { + ...field, + Edit: ( data ) => ( + <ExperimentalBlockEditorProvider settings={ settings }> + <field.Edit { ...data } /> + </ExperimentalBlockEditorProvider> + ), + }; + } + return field; + } ); + }, [ fields, settings ] ); + return ( <VStack spacing={ 4 }> { ids.length === 1 && ( @@ -130,7 +164,7 @@ function PostEditForm( { postType, postId } ) { ) } <DataForm data={ ids.length === 1 ? record : multiEdits } - fields={ fields } + fields={ fieldsWithDependency } form={ form } onChange={ onChange } /> diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index e61ade7e830364..6906629fc80027 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -34,6 +34,7 @@ import { statusField, authorField, titleField, + templateField, } from '@wordpress/fields'; export function registerEntityAction< Item >( @@ -171,6 +172,7 @@ export const registerPostTypeSchema = postTypeConfig.supports?.[ 'page-attributes' ] && parentField, postTypeConfig.supports?.comments && commentStatusField, passwordField, + templateField, ].filter( Boolean ); registry.batch( () => { diff --git a/packages/fields/README.md b/packages/fields/README.md index 6723611d2d9686..2fc512b9432645 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -123,6 +123,10 @@ Undocumented declaration. Status field for BasePost. +### templateField + +Undocumented declaration. + ### titleField Undocumented declaration. diff --git a/packages/fields/package.json b/packages/fields/package.json index eb60f448fc13e6..beaaf4f9813013 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -35,6 +35,7 @@ "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "*", "@wordpress/blob": "*", + "@wordpress/block-editor": "*", "@wordpress/blocks": "*", "@wordpress/components": "*", "@wordpress/compose": "*", diff --git a/packages/fields/src/actions/utils.ts b/packages/fields/src/actions/utils.ts index efd389405b5be8..7bc08573f0b9f8 100644 --- a/packages/fields/src/actions/utils.ts +++ b/packages/fields/src/actions/utils.ts @@ -22,7 +22,9 @@ export function isTemplateOrTemplatePart( return p.type === 'wp_template' || p.type === 'wp_template_part'; } -export function getItemTitle( item: Post ): string { +export function getItemTitle( item: { + title: string | { rendered: string } | { raw: string }; +} ) { if ( typeof item.title === 'string' ) { return decodeEntities( item.title ); } diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts index 5ea4235af1d964..2cdf89ee13fb02 100644 --- a/packages/fields/src/fields/index.ts +++ b/packages/fields/src/fields/index.ts @@ -2,6 +2,7 @@ export { default as slugField } from './slug'; export { default as titleField } from './title'; export { default as orderField } from './order'; export { default as featuredImageField } from './featured-image'; +export { default as templateField } from './template'; export { default as parentField } from './parent'; export { default as passwordField } from './password'; export { default as statusField } from './status'; diff --git a/packages/fields/src/fields/template/index.ts b/packages/fields/src/fields/template/index.ts new file mode 100644 index 00000000000000..7315b4ba349b1c --- /dev/null +++ b/packages/fields/src/fields/template/index.ts @@ -0,0 +1,22 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import { __ } from '@wordpress/i18n'; +import type { BasePost } from '../../types'; +import { TemplateEdit } from './template-edit'; + +const templateField: Field< BasePost > = { + id: 'template', + type: 'text', + label: __( 'Template' ), + getValue: ( { item } ) => item.template, + Edit: TemplateEdit, + enableSorting: false, +}; + +export default templateField; diff --git a/packages/fields/src/fields/template/style.scss b/packages/fields/src/fields/template/style.scss new file mode 100644 index 00000000000000..a0c2fafec73893 --- /dev/null +++ b/packages/fields/src/fields/template/style.scss @@ -0,0 +1,23 @@ +.fields-controls__template-modal { + z-index: z-index(".fields-controls__template-modal"); +} + +.fields-controls__template-content .block-editor-block-patterns-list { + column-count: 2; + column-gap: $grid-unit-30; + + // Small top padding required to avoid cutting off the visible outline when hovering items + padding-top: $border-width-focus-fallback; + + @include break-medium() { + column-count: 3; + } + + @include break-wide() { + column-count: 4; + } + + .block-editor-block-patterns-list__list-item { + break-inside: avoid-column; + } +} diff --git a/packages/fields/src/fields/template/template-edit.tsx b/packages/fields/src/fields/template/template-edit.tsx new file mode 100644 index 00000000000000..c17364568a4578 --- /dev/null +++ b/packages/fields/src/fields/template/template-edit.tsx @@ -0,0 +1,210 @@ +/** + * WordPress dependencies + */ +import { useCallback, useMemo, useState } from '@wordpress/element'; +// @ts-ignore +import { parse } from '@wordpress/blocks'; +import type { WpTemplate } from '@wordpress/core-data'; +import { store as coreStore } from '@wordpress/core-data'; +import type { DataFormControlProps } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +// @ts-expect-error block-editor is not typed correctly. +import { __experimentalBlockPatternsList as BlockPatternsList } from '@wordpress/block-editor'; +import { + Button, + Dropdown, + MenuGroup, + MenuItem, + Modal, +} from '@wordpress/components'; +import { useAsyncList } from '@wordpress/compose'; +import { useSelect } from '@wordpress/data'; +import { decodeEntities } from '@wordpress/html-entities'; +import { __ } from '@wordpress/i18n'; +import { getItemTitle } from '../../actions/utils'; +import type { BasePost } from '../../types'; +import { unlock } from '../../lock-unlock'; + +export const TemplateEdit = ( { + data, + field, + onChange, +}: DataFormControlProps< BasePost > ) => { + const { id } = field; + const postType = data.type; + const postId = + typeof data.id === 'number' ? data.id : parseInt( data.id, 10 ); + const slug = data.slug; + + const { availableTemplates, templates } = useSelect( + ( select ) => { + const allTemplates = + select( coreStore ).getEntityRecords< WpTemplate >( + 'postType', + 'wp_template', + { + per_page: -1, + post_type: postType, + } + ) ?? []; + + const { getHomePage, getPostsPageId } = unlock( + select( coreStore ) + ); + + const isPostsPage = getPostsPageId() === +postId; + const isFrontPage = + postType === 'page' && getHomePage()?.postId === +postId; + + const allowSwitchingTemplate = ! isPostsPage && ! isFrontPage; + + return { + templates: allTemplates, + availableTemplates: allowSwitchingTemplate + ? allTemplates.filter( + ( template ) => + template.is_custom && + template.slug !== data.template && + !! template.content.raw // Skip empty templates. + ) + : [], + }; + }, + [ data.template, postId, postType ] + ); + + const templatesAsPatterns = useMemo( + () => + availableTemplates.map( ( template ) => ( { + name: template.slug, + blocks: parse( template.content.raw ), + title: decodeEntities( template.title.rendered ), + id: template.id, + } ) ), + [ availableTemplates ] + ); + + const shownTemplates = useAsyncList( templatesAsPatterns ); + + const value = field.getValue( { item: data } ); + + const currentTemplate = useSelect( + ( select ) => { + const foundTemplate = templates?.find( + ( template ) => template.slug === value + ); + + if ( foundTemplate ) { + return foundTemplate; + } + + let slugToCheck; + // In `draft` status we might not have a slug available, so we use the `single` + // post type templates slug(ex page, single-post, single-product etc..). + // Pages do not need the `single` prefix in the slug to be prioritized + // through template hierarchy. + if ( slug ) { + slugToCheck = + postType === 'page' + ? `${ postType }-${ slug }` + : `single-${ postType }-${ slug }`; + } else { + slugToCheck = + postType === 'page' ? 'page' : `single-${ postType }`; + } + + if ( postType ) { + const templateId = select( coreStore ).getDefaultTemplateId( { + slug: slugToCheck, + } ); + + return select( coreStore ).getEntityRecord( + 'postType', + 'wp_template', + templateId + ); + } + }, + [ postType, slug, templates, value ] + ); + + const [ showModal, setShowModal ] = useState( false ); + + const onChangeControl = useCallback( + ( newValue: string ) => + onChange( { + [ id ]: newValue, + } ), + [ id, onChange ] + ); + + return ( + <fieldset className="fields-controls__template"> + <Dropdown + popoverProps={ { placement: 'bottom-start' } } + renderToggle={ ( { onToggle } ) => ( + <Button + __next40pxDefaultSize + variant="tertiary" + size="compact" + onClick={ onToggle } + > + { currentTemplate + ? getItemTitle( currentTemplate ) + : '' } + </Button> + ) } + renderContent={ ( { onToggle } ) => ( + <MenuGroup> + <MenuItem + onClick={ () => { + setShowModal( true ); + onToggle(); + } } + > + { __( 'Swap template' ) } + </MenuItem> + { + // The default template in a post is indicated by an empty string + value !== '' && ( + <MenuItem + onClick={ () => { + onChangeControl( '' ); + onToggle(); + } } + > + { __( 'Use default template' ) } + </MenuItem> + ) + } + </MenuGroup> + ) } + /> + { showModal && ( + <Modal + title={ __( 'Choose a template' ) } + onRequestClose={ () => setShowModal( false ) } + overlayClassName="fields-controls__template-modal" + isFullScreen + > + <div className="fields-controls__template-content"> + <BlockPatternsList + label={ __( 'Templates' ) } + blockPatterns={ templatesAsPatterns } + shownPatterns={ shownTemplates } + onClickPattern={ ( + template: ( typeof templatesAsPatterns )[ 0 ] + ) => { + onChangeControl( template.name ); + setShowModal( false ); + } } + /> + </div> + </Modal> + ) } + </fieldset> + ); +}; diff --git a/packages/fields/src/style.scss b/packages/fields/src/style.scss index 05cf5652248777..582044235aef1a 100644 --- a/packages/fields/src/style.scss +++ b/packages/fields/src/style.scss @@ -1,3 +1,4 @@ @import "./components/create-template-part-modal/style.scss"; @import "./fields/slug/style.scss"; @import "./fields/featured-image/style.scss"; +@import "./fields/template/style.scss"; diff --git a/packages/fields/tsconfig.json b/packages/fields/tsconfig.json index 531afb5bb2d873..46ac86d48e11ee 100644 --- a/packages/fields/tsconfig.json +++ b/packages/fields/tsconfig.json @@ -27,6 +27,7 @@ { "path": "../private-apis" }, { "path": "../router" }, { "path": "../url" }, + { "path": "../block-editor" }, { "path": "../warning" } ], "include": [ "src" ] From 4d225cc2ba6f09822227e7a820b8a555be7c4d48 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:22:28 +0100 Subject: [PATCH 1828/1908] [mini] Preload: add post type (#67518) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- backport-changelog/6.8/7695.md | 1 + lib/compat/wordpress-6.8/preload.php | 1 + 2 files changed, 2 insertions(+) diff --git a/backport-changelog/6.8/7695.md b/backport-changelog/6.8/7695.md index d69a59f2d67d12..08b780e2afb0d7 100644 --- a/backport-changelog/6.8/7695.md +++ b/backport-changelog/6.8/7695.md @@ -4,3 +4,4 @@ https://github.com/WordPress/wordpress-develop/pull/7695 * https://github.com/WordPress/gutenberg/pull/67465 * https://github.com/WordPress/gutenberg/pull/66579 * https://github.com/WordPress/gutenberg/pull/66654 +* https://github.com/WordPress/gutenberg/pull/67518 diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php index 0a36ea7f7227d4..0e887fc081bcb5 100644 --- a/lib/compat/wordpress-6.8/preload.php +++ b/lib/compat/wordpress-6.8/preload.php @@ -22,6 +22,7 @@ function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { $route_for_post = rest_get_route_for_post( $post ); if ( $route_for_post ) { $paths[] = add_query_arg( 'context', 'edit', $route_for_post ); + $paths[] = add_query_arg( 'context', 'edit', '/wp/v2/types/' . $post->post_type ); if ( 'page' === $post->post_type ) { $paths[] = add_query_arg( 'slug', From 0ff919f2c6a94e657987a8440c75b5e4f2db0b13 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Tue, 3 Dec 2024 12:49:06 +0000 Subject: [PATCH 1829/1908] Docs: Remove invalid key projects links on the documentation. (#67491) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> --- docs/contributors/repository-management.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/contributors/repository-management.md b/docs/contributors/repository-management.md index e57f762a605394..5bb971bfaf2efc 100644 --- a/docs/contributors/repository-management.md +++ b/docs/contributors/repository-management.md @@ -165,9 +165,3 @@ If you meet this criterion of several meaningful contributions having been accep ## Projects We use [GitHub projects](https://github.com/WordPress/gutenberg/projects) to keep track of details that aren't immediately actionable, but that we want to keep around for future reference. - -Some key projects include: - -- [Phase 2](https://github.com/WordPress/gutenberg/projects/13) - Development tasks needed for Phase 2 of Gutenberg. -- [Phase 2 design](https://github.com/WordPress/gutenberg/projects/21) - Tasks for design in Phase 2. Note: specific projects may have their own boards. -- [Ideas](https://github.com/WordPress/gutenberg/projects/8) - Project containing tickets that, while closed for the time being, can be revisited in the future. From 1c3cea43b0fca853f351e4bc08ba840df7de2469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Gomes?= <mail@sgomes.com> Date: Tue, 3 Dec 2024 14:24:57 +0000 Subject: [PATCH 1830/1908] Exclude Set instance methods from polyfills (#67230) * Exclude Set instance methods from polyfills * Switch to regexp exclusions --- .../polyfill-exclusions.js | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packages/babel-preset-default/polyfill-exclusions.js b/packages/babel-preset-default/polyfill-exclusions.js index 507396c930b99c..ca8c045d124146 100644 --- a/packages/babel-preset-default/polyfill-exclusions.js +++ b/packages/babel-preset-default/polyfill-exclusions.js @@ -7,4 +7,25 @@ module.exports = [ // This is an IE-only feature which we don't use, and don't want to polyfill. // @see https://github.com/WordPress/gutenberg/pull/49234 'web.immediate', + // Remove Set feature polyfills. + // + // The Babel/core-js integration has a severe limitation, in that any Set + // objects (e.g. `new Set()`) are assumed to need all instance methods, and + // get them all polyfilled. There is no validation as to whether those + // methods are actually in use. + // + // This limitation causes a number of packages to unnecessarily get a + // dependency on `wp-polyfill`, which in most cases gets loaded as part of + // the critical path and can thus have an impact on performance. + // + // There is no good solution to this, and the one we've opted for here is + // to disable polyfilling these features entirely. Developers will need to + // take care not to use them in scenarios where the code may be running in + // older browsers without native support for them. + // + // These need to be specified as both `es.` and `esnext.` due to the way + // internal dependencies are set up in Babel / core-js. + // + // @see https://github.com/WordPress/gutenberg/pull/67230 + /^es(next)?\.set\./, ]; From 7631986644c82b2c8ff7481e95a64124644f7c1d Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Tue, 3 Dec 2024 08:24:33 -0800 Subject: [PATCH 1831/1908] Split view with meta boxes even with legacy canvas (#66706) * Split view with meta boxes with non-iframed canvas * Fix scrolling of device previews * Consolidate styles and add comments * Do the same thing without adding a prop to BlockCanvas * Fix horizontal overflow of device previews Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: jartes <jartes@git.wordpress.org> Co-authored-by: bph <bph@git.wordpress.org> Co-authored-by: ndiego <ndiego@git.wordpress.org> Co-authored-by: MadtownLems <madtownlems@git.wordpress.org> --- .../src/components/block-canvas/index.js | 8 ++--- .../src/components/use-resize-canvas/index.js | 2 +- .../edit-post/src/components/layout/index.js | 23 +++--------- .../src/components/layout/style.scss | 8 ++--- .../components/editor-interface/style.scss | 3 +- .../src/components/visual-editor/index.js | 1 + .../src/components/visual-editor/style.scss | 35 +++++++++++++++---- 7 files changed, 44 insertions(+), 36 deletions(-) diff --git a/packages/block-editor/src/components/block-canvas/index.js b/packages/block-editor/src/components/block-canvas/index.js index c399f38054ed4d..36aca7fa1c7220 100644 --- a/packages/block-editor/src/components/block-canvas/index.js +++ b/packages/block-editor/src/components/block-canvas/index.js @@ -56,7 +56,8 @@ export function ExperimentalBlockCanvas( { return ( <BlockTools __unstableContentRef={ localRef } - style={ { height, display: 'flex' } } + className="block-editor-block-canvas" + style={ { height } } > <EditorStyles styles={ styles } @@ -67,10 +68,6 @@ export function ExperimentalBlockCanvas( { ref={ contentRef } className="editor-styles-wrapper" tabIndex={ -1 } - style={ { - height: '100%', - width: '100%', - } } > { children } </WritingFlow> @@ -81,6 +78,7 @@ export function ExperimentalBlockCanvas( { return ( <BlockTools __unstableContentRef={ localRef } + className="block-editor-block-canvas" style={ { height, display: 'flex' } } > <Iframe diff --git a/packages/block-editor/src/components/use-resize-canvas/index.js b/packages/block-editor/src/components/use-resize-canvas/index.js index 3b4d97a097964c..0aa46c9c3278f7 100644 --- a/packages/block-editor/src/components/use-resize-canvas/index.js +++ b/packages/block-editor/src/components/use-resize-canvas/index.js @@ -60,7 +60,7 @@ export default function useResizeCanvas( deviceType ) { marginLeft: marginHorizontal, marginRight: marginHorizontal, height, - overflowY: 'auto', + maxWidth: '100%', }; default: return { diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index b8061571ec66cc..c230738a077d92 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -149,11 +149,7 @@ function useEditorStyles( ...additionalStyles ) { ] ); } -/** - * @param {Object} props - * @param {boolean} props.isLegacy True when the editor canvas is not in an iframe. - */ -function MetaBoxesMain( { isLegacy } ) { +function MetaBoxesMain() { const [ isOpen, openHeight, hasAnyVisible ] = useSelect( ( select ) => { const { get } = select( preferencesStore ); const { isMetaBoxLocationVisible } = select( editPostStore ); @@ -233,22 +229,15 @@ function MetaBoxesMain( { isLegacy } ) { const contents = ( <div - className={ clsx( - // The class name 'edit-post-layout__metaboxes' is retained because some plugins use it. - 'edit-post-layout__metaboxes', - ! isLegacy && 'edit-post-meta-boxes-main__liner' - ) } - hidden={ ! isLegacy && isShort && ! isOpen } + // The class name 'edit-post-layout__metaboxes' is retained because some plugins use it. + className="edit-post-layout__metaboxes edit-post-meta-boxes-main__liner" + hidden={ isShort && ! isOpen } > <MetaBoxes location="normal" /> <MetaBoxes location="advanced" /> </div> ); - if ( isLegacy ) { - return contents; - } - const isAutoHeight = openHeight === undefined; let usedMax = '50%'; // Approximation before max has a value. if ( max !== undefined ) { @@ -587,9 +576,7 @@ function Layout( { } extraContent={ ! isDistractionFree && - showMetaBoxes && ( - <MetaBoxesMain isLegacy={ ! shouldIframe } /> - ) + showMetaBoxes && <MetaBoxesMain /> } > <PostLockedModal /> diff --git a/packages/edit-post/src/components/layout/style.scss b/packages/edit-post/src/components/layout/style.scss index 18f12c1dbfbb92..7a7f13382661ac 100644 --- a/packages/edit-post/src/components/layout/style.scss +++ b/packages/edit-post/src/components/layout/style.scss @@ -107,11 +107,9 @@ } .has-metaboxes .editor-visual-editor { - flex: 1; - - &.is-iframed { - isolation: isolate; - } + // Contains z-indexes of children so that the block toolbar will appear behind + // the drop shadow of the meta box pane. + isolation: isolate; } // Adjust the position of the notices diff --git a/packages/editor/src/components/editor-interface/style.scss b/packages/editor/src/components/editor-interface/style.scss index 05b23fe2304dd8..7219e03058fc4c 100644 --- a/packages/editor/src/components/editor-interface/style.scss +++ b/packages/editor/src/components/editor-interface/style.scss @@ -8,5 +8,6 @@ } .editor-visual-editor { - flex: 1 0 auto; + // Fits the height to the parent — flex-shrink ensures it doesn’t create overflow. + flex: 1 1 0%; } diff --git a/packages/editor/src/components/visual-editor/index.js b/packages/editor/src/components/visual-editor/index.js index 795a4f983f1536..122252ea4a4690 100644 --- a/packages/editor/src/components/visual-editor/index.js +++ b/packages/editor/src/components/visual-editor/index.js @@ -385,6 +385,7 @@ function VisualEditor( { 'has-padding': isFocusedEntity || enableResizing, 'is-resizable': enableResizing, 'is-iframed': ! disableIframe, + 'is-scrollable': disableIframe || deviceType !== 'Desktop', } ) } > diff --git a/packages/editor/src/components/visual-editor/style.scss b/packages/editor/src/components/visual-editor/style.scss index 63df28f0f1ba5a..04ca0215e4fc66 100644 --- a/packages/editor/src/components/visual-editor/style.scss +++ b/packages/editor/src/components/visual-editor/style.scss @@ -6,6 +6,9 @@ // when the iframe doesn't cover the whole canvas // like the "focused entities". background-color: $gray-300; + // Allows the height to fit the parent container and avoids parent scrolling contexts from + // having overflow due to popovers of block tools. + overflow: hidden; // This overrides the iframe background since it's applied again here // It also prevents some style glitches if `editor-visual-editor` @@ -25,12 +28,6 @@ padding: $grid-unit-30 $grid-unit-30 0; } - // In the iframed canvas this keeps extra scrollbars from appearing (when block toolbars overflow). In the - // legacy (non-iframed) canvas, overflow must not be hidden in order to maintain support for sticky positioning. - &.is-iframed { - overflow: hidden; - } - // The button element easily inherits styles that are meant for the editor style. // These rules enhance the specificity to reduce that inheritance. // This is duplicated in edit-site. @@ -44,4 +41,30 @@ padding: 6px; } } + + // The cases for this are non-iframed editor canvas or previewing devices. The block canvas is + // made the scrolling context. + &.is-scrollable .block-editor-block-canvas { + overflow: auto; + + // Applicable only when legacy (non-iframed). + > .block-editor-writing-flow { + display: flow-root; + min-height: 100%; + box-sizing: border-box; // Ensures that 100% min-height doesn’t create overflow. + } + + // Applicable only when iframed. These styles ensure that if the the iframe is + // given a fixed height and it’s taller than the viewport then scrolling is + // allowed. This is needed for device previews. + > .block-editor-iframe__container { + display: flex; + flex-direction: column; + + > .block-editor-iframe__scale-container { + flex: 1 0 fit-content; + display: flow-root; + } + } + } } From 47718ab1e981f33e56a0367e7749cccaac4b9d0e Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Wed, 4 Dec 2024 01:53:14 +0900 Subject: [PATCH 1832/1908] BlockSwitcher: Refactor to use Button layout properly (#67502) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- .../src/components/block-switcher/index.js | 40 +++++++++---------- .../src/components/block-switcher/style.scss | 9 ----- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js index 79f33bd30d7537..285581578ead43 100644 --- a/packages/block-editor/src/components/block-switcher/index.js +++ b/packages/block-editor/src/components/block-switcher/index.js @@ -18,6 +18,7 @@ import { } from '@wordpress/blocks'; import { useSelect, useDispatch } from '@wordpress/data'; import { copy } from '@wordpress/icons'; +import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies @@ -185,21 +186,6 @@ function BlockSwitcherDropdownMenuContents( { ); } -const BlockIndicator = ( { icon, showTitle, blockTitle } ) => ( - <> - <BlockIcon - className="block-editor-block-switcher__toggle" - icon={ icon } - showColors - /> - { showTitle && blockTitle && ( - <span className="block-editor-block-switcher__toggle-text"> - { blockTitle } - </span> - ) } - </> -); - export const BlockSwitcher = ( { clientIds } ) => { const { hasContentOnlyLocking, @@ -272,6 +258,11 @@ export const BlockSwitcher = ( { clientIds } ) => { clientId: clientIds?.[ 0 ], maximumLength: 35, } ); + const showIconLabels = useSelect( + ( select ) => + select( preferencesStore ).get( 'core', 'showIconLabels' ), + [] + ); if ( invalidBlocks ) { return null; @@ -282,6 +273,11 @@ export const BlockSwitcher = ( { clientIds } ) => { ? blockTitle : __( 'Multiple blocks selected' ); + const blockIndicatorText = + ( isReusable || isTemplate ) && ! showIconLabels && blockTitle + ? blockTitle + : undefined; + const hideDropdown = isDisabled || ( ! hasBlockStyles && ! canRemove ) || @@ -295,12 +291,13 @@ export const BlockSwitcher = ( { clientIds } ) => { className="block-editor-block-switcher__no-switcher-icon" title={ blockSwitcherLabel } icon={ - <BlockIndicator + <BlockIcon + className="block-editor-block-switcher__toggle" icon={ icon } - showTitle={ isReusable || isTemplate } - blockTitle={ blockTitle } + showColors /> } + text={ blockIndicatorText } /> </ToolbarGroup> ); @@ -329,12 +326,13 @@ export const BlockSwitcher = ( { clientIds } ) => { className: 'block-editor-block-switcher__popover', } } icon={ - <BlockIndicator + <BlockIcon + className="block-editor-block-switcher__toggle" icon={ icon } - showTitle={ isReusable || isTemplate } - blockTitle={ blockTitle } + showColors /> } + text={ blockIndicatorText } toggleProps={ { description: blockSwitcherDescription, ...toggleProps, diff --git a/packages/block-editor/src/components/block-switcher/style.scss b/packages/block-editor/src/components/block-switcher/style.scss index 3dc2a7d591c926..62a7bebe95d278 100644 --- a/packages/block-editor/src/components/block-switcher/style.scss +++ b/packages/block-editor/src/components/block-switcher/style.scss @@ -26,15 +26,6 @@ } } -.block-editor-block-switcher__toggle-text { - margin-left: $grid-unit-10; - - // Account for double label when show-text-buttons is set. - .show-icon-labels & { - display: none; - } -} - .components-button.block-editor-block-switcher__no-switcher-icon { display: flex; From de96b5a090c853d3e09d73072f4be25d9a2ab668 Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Tue, 3 Dec 2024 11:34:04 -0600 Subject: [PATCH 1833/1908] Fix zoom animation scrollbar (#67536) Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: ajlende <ajlende@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> --- .../src/components/iframe/content.scss | 3 +- .../src/components/iframe/use-scale-canvas.js | 54 ++++++++++++++----- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss index 74efb63c0e077b..05bbdb25c2dc63 100644 --- a/packages/block-editor/src/components/iframe/content.scss +++ b/packages/block-editor/src/components/iframe/content.scss @@ -10,6 +10,7 @@ &.zoom-out-animation { $scroll-top: var(--wp-block-editor-iframe-zoom-out-scroll-top, 0); $scroll-top-next: var(--wp-block-editor-iframe-zoom-out-scroll-top-next, 0); + $overflow-behavior: var(--wp-block-editor-iframe-zoom-out-overflow-behavior, scroll); position: fixed; left: 0; @@ -18,7 +19,7 @@ bottom: 0; // Force preserving a scrollbar gutter as scrollbar-gutter isn't supported in all browsers yet, // and removing the scrollbar causes the content to shift. - overflow-y: scroll; + overflow-y: $overflow-behavior; } &.is-zoomed-out { diff --git a/packages/block-editor/src/components/iframe/use-scale-canvas.js b/packages/block-editor/src/components/iframe/use-scale-canvas.js index 0b2b8d3c137ffa..d2651a75ec86ca 100644 --- a/packages/block-editor/src/components/iframe/use-scale-canvas.js +++ b/packages/block-editor/src/components/iframe/use-scale-canvas.js @@ -35,6 +35,21 @@ function calculateScale( { ); } +/** + * Compute the next scrollHeight based on the transition states. + * + * @param {TransitionState} transitionFrom Starting point of the transition + * @param {TransitionState} transitionTo Ending state of the transition + * @return {number} Next scrollHeight based on scale and frame value changes. + */ +function computeScrollHeightNext( transitionFrom, transitionTo ) { + const { scaleValue: prevScale, scrollHeight: prevScrollHeight } = + transitionFrom; + const { frameSize, scaleValue } = transitionTo; + + return prevScrollHeight * ( scaleValue / prevScale ) + frameSize * 2; +} + /** * Compute the next scrollTop position after scaling the iframe content. * @@ -47,12 +62,12 @@ function computeScrollTopNext( transitionFrom, transitionTo ) { containerHeight: prevContainerHeight, frameSize: prevFrameSize, scaleValue: prevScale, - scrollTop, - scrollHeight, + scrollTop: prevScrollTop, } = transitionFrom; - const { containerHeight, frameSize, scaleValue } = transitionTo; + const { containerHeight, frameSize, scaleValue, scrollHeight } = + transitionTo; // Step 0: Start with the current scrollTop. - let scrollTopNext = scrollTop; + let scrollTopNext = prevScrollTop; // Step 1: Undo the effects of the previous scale and frame around the // midpoint of the visible area. scrollTopNext = @@ -71,15 +86,12 @@ function computeScrollTopNext( transitionFrom, transitionTo ) { // iframe if the top of the iframe content is visible in the container. // The same edge case for the bottom is skipped because changing content // makes calculating it impossible. - scrollTopNext = scrollTop <= prevFrameSize ? 0 : scrollTopNext; + scrollTopNext = prevScrollTop <= prevFrameSize ? 0 : scrollTopNext; // This is the scrollTop value if you are scrolled to the bottom of the // iframe. We can't just let the browser handle it because we need to // animate the scaling. - const maxScrollTop = - scrollHeight * ( scaleValue / prevScale ) + - frameSize * 2 - - containerHeight; + const maxScrollTop = scrollHeight - containerHeight; // Step 4: Clamp the scrollTopNext between the minimum and maximum // possible scrollTop positions. Round the value to avoid subpixel @@ -226,6 +238,15 @@ export function useScaleCanvas( { `${ scrollTopNext }px` ); + // If the container has a scrolllbar, force a scrollbar to prevent the content from shifting while animating. + iframeDocument.documentElement.style.setProperty( + '--wp-block-editor-iframe-zoom-out-overflow-behavior', + transitionFromRef.current.scrollHeight === + transitionFromRef.current.containerHeight + ? 'auto' + : 'scroll' + ); + iframeDocument.documentElement.classList.add( 'zoom-out-animation' ); return iframeDocument.documentElement.animate( @@ -278,6 +299,9 @@ export function useScaleCanvas( { iframeDocument.documentElement.style.removeProperty( '--wp-block-editor-iframe-zoom-out-scroll-top-next' ); + iframeDocument.documentElement.style.removeProperty( + '--wp-block-editor-iframe-zoom-out-overflow-behavior' + ); // Update previous values. transitionFromRef.current = transitionToRef.current; @@ -409,20 +433,24 @@ export function useScaleCanvas( { // the iframe at this point when we're about to animate the zoom out. // The iframe scrollTop, scrollHeight, and clientHeight will all be // the most accurate. - transitionFromRef.current.containerHeight = - transitionFromRef.current.containerHeight ?? - containerHeight; // Use containerHeight, as it's the previous container height value if none was set. transitionFromRef.current.scrollTop = iframeDocument.documentElement.scrollTop; transitionFromRef.current.scrollHeight = iframeDocument.documentElement.scrollHeight; + // Use containerHeight, as it's the previous container height before the zoom out animation starts. + transitionFromRef.current.containerHeight = containerHeight; transitionToRef.current = { scaleValue, frameSize, containerHeight: - iframeDocument.documentElement.clientHeight, // use clientHeight to get the actual height of the new container, as it will be the most up-to-date. + iframeDocument.documentElement.clientHeight, // use clientHeight to get the actual height of the new container after zoom state changes have rendered, as it will be the most up-to-date. }; + + transitionToRef.current.scrollHeight = computeScrollHeightNext( + transitionFromRef.current, + transitionToRef.current + ); transitionToRef.current.scrollTop = computeScrollTopNext( transitionFromRef.current, transitionToRef.current From af35f6705e9e8144c95f700bc397ddedcbc78a60 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Tue, 3 Dec 2024 17:59:17 +0000 Subject: [PATCH 1834/1908] Fix: Invalid JSDoc for optional string parameter and return value. (#67489) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> --- docs/reference-guides/data/data-core-blocks.md | 8 ++++---- docs/reference-guides/data/data-core-editor.md | 2 +- .../reference-guides/data/data-core-keyboard-shortcuts.md | 4 ++-- packages/block-editor/src/hooks/gap.js | 2 +- packages/block-library/src/list-item/hooks/use-merge.js | 4 ++-- packages/blocks/src/store/selectors.js | 8 ++++---- packages/date/README.md | 2 +- packages/date/src/index.js | 2 +- packages/e2e-test-utils/README.md | 8 ++++---- packages/e2e-test-utils/src/delete-theme.js | 4 ++-- packages/e2e-test-utils/src/get-current-user.js | 2 +- packages/e2e-test-utils/src/install-plugin.js | 2 +- packages/e2e-test-utils/src/install-theme.js | 2 +- packages/editor/src/store/selectors.js | 2 +- packages/keyboard-shortcuts/src/store/selectors.js | 6 +++--- 15 files changed, 29 insertions(+), 29 deletions(-) diff --git a/docs/reference-guides/data/data-core-blocks.md b/docs/reference-guides/data/data-core-blocks.md index 084c9c1d7a5fbc..158b7f92529122 100644 --- a/docs/reference-guides/data/data-core-blocks.md +++ b/docs/reference-guides/data/data-core-blocks.md @@ -385,7 +385,7 @@ _Parameters_ _Returns_ -- `string?`: Default block name. +- `?string`: Default block name. ### getDefaultBlockVariation @@ -464,7 +464,7 @@ _Parameters_ _Returns_ -- `string?`: Name of the block for handling non-block content. +- `?string`: Name of the block for handling non-block content. ### getGroupingBlockName @@ -502,7 +502,7 @@ _Parameters_ _Returns_ -- `string?`: Name of the block for handling the grouping of blocks. +- `?string`: Name of the block for handling the grouping of blocks. ### getUnregisteredFallbackBlockName @@ -540,7 +540,7 @@ _Parameters_ _Returns_ -- `string?`: Name of the block for handling unregistered blocks. +- `?string`: Name of the block for handling unregistered blocks. ### hasBlockSupport diff --git a/docs/reference-guides/data/data-core-editor.md b/docs/reference-guides/data/data-core-editor.md index 44078ab284e94f..a9f07104bd3b6e 100644 --- a/docs/reference-guides/data/data-core-editor.md +++ b/docs/reference-guides/data/data-core-editor.md @@ -272,7 +272,7 @@ _Parameters_ _Returns_ -- `string?`: Template ID. +- `?string`: Template ID. ### getDeviceType diff --git a/docs/reference-guides/data/data-core-keyboard-shortcuts.md b/docs/reference-guides/data/data-core-keyboard-shortcuts.md index d7d5cf853f7865..426fb316021a42 100644 --- a/docs/reference-guides/data/data-core-keyboard-shortcuts.md +++ b/docs/reference-guides/data/data-core-keyboard-shortcuts.md @@ -239,7 +239,7 @@ _Parameters_ _Returns_ -- `string?`: Shortcut description. +- `?string`: Shortcut description. ### getShortcutKeyCombination @@ -335,7 +335,7 @@ _Parameters_ _Returns_ -- `string?`: Shortcut representation. +- `?string`: Shortcut representation. <!-- END TOKEN(Autogenerated selectors|../../../packages/keyboard-shortcuts/src/store/selectors.js) --> diff --git a/packages/block-editor/src/hooks/gap.js b/packages/block-editor/src/hooks/gap.js index debe1ad1690782..887325e6409dde 100644 --- a/packages/block-editor/src/hooks/gap.js +++ b/packages/block-editor/src/hooks/gap.js @@ -27,7 +27,7 @@ export function getGapBoxControlValueFromStyle( blockGapValue ) { * Returns a CSS value for the `gap` property from a given blockGap style. * * @param {string? | Object?} blockGapValue A block gap string or axial object value, e.g., '10px' or { top: '10px', left: '10px'}. - * @param {string?} defaultValue A default gap value. + * @param {?string} defaultValue A default gap value. * @return {string|null} The concatenated gap value (row and column). */ export function getGapCSSValue( blockGapValue, defaultValue = '0' ) { diff --git a/packages/block-library/src/list-item/hooks/use-merge.js b/packages/block-library/src/list-item/hooks/use-merge.js index 9ca4d5372ee6e8..3fe755868df37d 100644 --- a/packages/block-library/src/list-item/hooks/use-merge.js +++ b/packages/block-library/src/list-item/hooks/use-merge.js @@ -49,7 +49,7 @@ export default function useMerge( clientId, onMerge ) { * return the next list item of the parent list item if it exists. * * @param {string} id A list item client ID. - * @return {string?} The client ID of the next list item. + * @return {?string} The client ID of the next list item. */ function _getNextId( id ) { const next = getNextBlockClientId( id ); @@ -68,7 +68,7 @@ export default function useMerge( clientId, onMerge ) { * line, regardless of indentation level. * * @param {string} id The client ID of the current list item. - * @return {string?} The client ID of the next list item. + * @return {?string} The client ID of the next list item. */ function getNextId( id ) { const order = getBlockOrder( id ); diff --git a/packages/blocks/src/store/selectors.js b/packages/blocks/src/store/selectors.js index 79e88073ba20de..c4589ce8232f66 100644 --- a/packages/blocks/src/store/selectors.js +++ b/packages/blocks/src/store/selectors.js @@ -437,7 +437,7 @@ export function getCollections( state ) { * }; * ``` * - * @return {string?} Default block name. + * @return {?string} Default block name. */ export function getDefaultBlockName( state ) { return state.defaultBlockName; @@ -473,7 +473,7 @@ export function getDefaultBlockName( state ) { * }; * ``` * - * @return {string?} Name of the block for handling non-block content. + * @return {?string} Name of the block for handling non-block content. */ export function getFreeformFallbackBlockName( state ) { return state.freeformFallbackBlockName; @@ -509,7 +509,7 @@ export function getFreeformFallbackBlockName( state ) { * }; * ``` * - * @return {string?} Name of the block for handling unregistered blocks. + * @return {?string} Name of the block for handling unregistered blocks. */ export function getUnregisteredFallbackBlockName( state ) { return state.unregisteredFallbackBlockName; @@ -545,7 +545,7 @@ export function getUnregisteredFallbackBlockName( state ) { * }; * ``` * - * @return {string?} Name of the block for handling the grouping of blocks. + * @return {?string} Name of the block for handling the grouping of blocks. */ export function getGroupingBlockName( state ) { return state.groupingBlockName; diff --git a/packages/date/README.md b/packages/date/README.md index ed2dfdd4790324..4f0a64c24aa713 100644 --- a/packages/date/README.md +++ b/packages/date/README.md @@ -75,7 +75,7 @@ Create and return a JavaScript Date Object from a date string in the WP timezone _Parameters_ -- _dateString_ `string?`: Date formatted in the WP timezone. +- _dateString_ `?string`: Date formatted in the WP timezone. _Returns_ diff --git a/packages/date/src/index.js b/packages/date/src/index.js index b632de3a7431f6..8d8f53fd8bc10f 100644 --- a/packages/date/src/index.js +++ b/packages/date/src/index.js @@ -588,7 +588,7 @@ export function isInTheFuture( dateValue ) { /** * Create and return a JavaScript Date Object from a date string in the WP timezone. * - * @param {string?} dateString Date formatted in the WP timezone. + * @param {?string} dateString Date formatted in the WP timezone. * * @return {Date} Date */ diff --git a/packages/e2e-test-utils/README.md b/packages/e2e-test-utils/README.md index 196768b0e2487c..30548961db26a4 100644 --- a/packages/e2e-test-utils/README.md +++ b/packages/e2e-test-utils/README.md @@ -253,8 +253,8 @@ _Parameters_ - _slug_ `string`: Theme slug. - _settings_ `Object?`: Optional settings object. -- _settings.newThemeSlug_ `string?`: A theme to switch to if the theme to delete is active. Required if the theme to delete is active. -- _settings.newThemeSearchTerm_ `string?`: A search term to use if the new theme is not findable by its slug. +- _settings.newThemeSlug_ `?string`: A theme to switch to if the theme to delete is active. Required if the theme to delete is active. +- _settings.newThemeSearchTerm_ `?string`: A search term to use if the new theme is not findable by its slug. ### deleteUser @@ -479,7 +479,7 @@ Installs a plugin from the WP.org repository. _Parameters_ - _slug_ `string`: Plugin slug. -- _searchTerm_ `string?`: If the plugin is not findable by its slug use an alternative term to search. +- _searchTerm_ `?string`: If the plugin is not findable by its slug use an alternative term to search. ### installTheme @@ -489,7 +489,7 @@ _Parameters_ - _slug_ `string`: Theme slug. - _settings_ `Object?`: Optional settings object. -- _settings.searchTerm_ `string?`: Search term to use if the theme is not findable by its slug. +- _settings.searchTerm_ `?string`: Search term to use if the theme is not findable by its slug. ### isCurrentURL diff --git a/packages/e2e-test-utils/src/delete-theme.js b/packages/e2e-test-utils/src/delete-theme.js index 98b7e2b4589234..8b59c9f1e7a112 100644 --- a/packages/e2e-test-utils/src/delete-theme.js +++ b/packages/e2e-test-utils/src/delete-theme.js @@ -13,8 +13,8 @@ import { isThemeInstalled } from './theme-installed'; * * @param {string} slug Theme slug. * @param {Object?} settings Optional settings object. - * @param {string?} settings.newThemeSlug A theme to switch to if the theme to delete is active. Required if the theme to delete is active. - * @param {string?} settings.newThemeSearchTerm A search term to use if the new theme is not findable by its slug. + * @param {?string} settings.newThemeSlug A theme to switch to if the theme to delete is active. Required if the theme to delete is active. + * @param {?string} settings.newThemeSearchTerm A search term to use if the new theme is not findable by its slug. */ export async function deleteTheme( slug, diff --git a/packages/e2e-test-utils/src/get-current-user.js b/packages/e2e-test-utils/src/get-current-user.js index d59ec0da2dd5da..6777c842be01f1 100644 --- a/packages/e2e-test-utils/src/get-current-user.js +++ b/packages/e2e-test-utils/src/get-current-user.js @@ -1,7 +1,7 @@ /** * Get the username of the user that's currently logged into WordPress (if any). * - * @return {string?} username The user that's currently logged into WordPress (if any). + * @return {?string} username The user that's currently logged into WordPress (if any). */ export async function getCurrentUser() { const cookies = await page.cookies(); diff --git a/packages/e2e-test-utils/src/install-plugin.js b/packages/e2e-test-utils/src/install-plugin.js index 5edfbb54f6642a..239909953d518f 100644 --- a/packages/e2e-test-utils/src/install-plugin.js +++ b/packages/e2e-test-utils/src/install-plugin.js @@ -9,7 +9,7 @@ import { visitAdminPage } from './visit-admin-page'; * Installs a plugin from the WP.org repository. * * @param {string} slug Plugin slug. - * @param {string?} searchTerm If the plugin is not findable by its slug use an alternative term to search. + * @param {?string} searchTerm If the plugin is not findable by its slug use an alternative term to search. */ export async function installPlugin( slug, searchTerm ) { await switchUserToAdmin(); diff --git a/packages/e2e-test-utils/src/install-theme.js b/packages/e2e-test-utils/src/install-theme.js index 7d001d395bda7f..7f11e5da88ef83 100644 --- a/packages/e2e-test-utils/src/install-theme.js +++ b/packages/e2e-test-utils/src/install-theme.js @@ -11,7 +11,7 @@ import { isThemeInstalled } from './theme-installed'; * * @param {string} slug Theme slug. * @param {Object?} settings Optional settings object. - * @param {string?} settings.searchTerm Search term to use if the theme is not findable by its slug. + * @param {?string} settings.searchTerm Search term to use if the theme is not findable by its slug. */ export async function installTheme( slug, { searchTerm } = {} ) { await switchUserToAdmin(); diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index a090fee0abd641..4ab0a47210353b 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -206,7 +206,7 @@ export function getCurrentPostId( state ) { * * @param {Object} state Global application state. * - * @return {string?} Template ID. + * @return {?string} Template ID. */ export function getCurrentTemplateId( state ) { return state.templateId; diff --git a/packages/keyboard-shortcuts/src/store/selectors.js b/packages/keyboard-shortcuts/src/store/selectors.js index 99309d3e24085c..1e4872b46a4a77 100644 --- a/packages/keyboard-shortcuts/src/store/selectors.js +++ b/packages/keyboard-shortcuts/src/store/selectors.js @@ -40,7 +40,7 @@ const FORMATTING_METHODS = { * @param {keyof FORMATTING_METHODS} representation Type of representation * (display, raw, ariaLabel). * - * @return {string?} Shortcut representation. + * @return {?string} Shortcut representation. */ function getKeyCombinationRepresentation( shortcut, representation ) { if ( ! shortcut ) { @@ -135,7 +135,7 @@ export function getShortcutKeyCombination( state, name ) { * }; *``` * - * @return {string?} Shortcut representation. + * @return {?string} Shortcut representation. */ export function getShortcutRepresentation( state, @@ -172,7 +172,7 @@ export function getShortcutRepresentation( * ); * }; *``` - * @return {string?} Shortcut description. + * @return {?string} Shortcut description. */ export function getShortcutDescription( state, name ) { return state[ name ] ? state[ name ].description : null; From 635a6e22a22795ebb150446d7be10b3eb5b26720 Mon Sep 17 00:00:00 2001 From: Vijayan <gvgvgvijayan@gmail.com> Date: Tue, 3 Dec 2024 23:48:12 +0530 Subject: [PATCH 1835/1908] Add `format` and `parents` to list of `allowedControls` options in Extending the Query Loop Documentation (#67529) Co-authored-by: gvgvgvijayan <gvgvgvijayan@git.wordpress.org> Co-authored-by: fabiankaegy <fabiankaegy@git.wordpress.org> --- .../block-tutorial/extending-the-query-loop-block.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/how-to-guides/block-tutorial/extending-the-query-loop-block.md b/docs/how-to-guides/block-tutorial/extending-the-query-loop-block.md index d4134749891ca1..a59875ae43522b 100644 --- a/docs/how-to-guides/block-tutorial/extending-the-query-loop-block.md +++ b/docs/how-to-guides/block-tutorial/extending-the-query-loop-block.md @@ -186,6 +186,8 @@ As of Gutenberg version 14.2, the following controls are available: - `taxQuery` - Shows available taxonomies filters for the currently selected post type. - `author` - Shows an input field to filter the query by author. - `search` - Shows an input field to filter the query by keywords. +- `format` - Shows an input field to filter the query by array/collection of [formats](https://developer.wordpress.org/advanced-administration/wordpress/post-formats/#supported-formats). +- `parents` - Shows an input field to filter the query using parent(s) entity. In our case, the property would look like this: From 40b865333994a9cc1f239d0f4cfd817be138d4b4 Mon Sep 17 00:00:00 2001 From: Hit Bhalodia <58802366+hbhalodia@users.noreply.github.com> Date: Wed, 4 Dec 2024 00:05:43 +0530 Subject: [PATCH 1836/1908] FormTokenField: Deprecate 36px default size (#67454) * Update FormTokenField Component to use default 40px size and added 36px deprecation warning * Update the changelog to add deprecation PR for the FormTokenField * Add __next40pxDefaultSize to async story for FormTokenField Co-authored-by: hbhalodia <hbhalodia@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/CHANGELOG.md | 2 ++ packages/components/src/form-token-field/README.md | 1 + packages/components/src/form-token-field/index.tsx | 7 +++++++ .../src/form-token-field/stories/index.story.tsx | 2 ++ packages/components/src/form-token-field/test/index.tsx | 6 +++++- 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index e35ba460ef7c54..2be7450f43d0f5 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -15,6 +15,8 @@ - `NumberControl`: Deprecate 36px default size ([#66730](https://github.com/WordPress/gutenberg/pull/66730)). - `UnitControl`: Deprecate 36px default size ([#66791](https://github.com/WordPress/gutenberg/pull/66791)). - `FormFileUpload`: Deprecate 36px default size ([#67438](https://github.com/WordPress/gutenberg/pull/67438)). +- `FormTokenField`: Deprecate 36px default size ([#67454](https://github.com/WordPress/gutenberg/pull/67454)). + ### Enhancements diff --git a/packages/components/src/form-token-field/README.md b/packages/components/src/form-token-field/README.md index 70e9bd09a61a36..a04ba5ec7b9d29 100644 --- a/packages/components/src/form-token-field/README.md +++ b/packages/components/src/form-token-field/README.md @@ -85,6 +85,7 @@ const MyFormTokenField = () => { return ( <FormTokenField + __next40pxDefaultSize value={ selectedContinents } suggestions={ continents } onChange={ ( tokens ) => setSelectedContinents( tokens ) } diff --git a/packages/components/src/form-token-field/index.tsx b/packages/components/src/form-token-field/index.tsx index 4f2f325e409a76..987c75d769b727 100644 --- a/packages/components/src/form-token-field/index.tsx +++ b/packages/components/src/form-token-field/index.tsx @@ -30,6 +30,7 @@ import { import { Spacer } from '../spacer'; import { useDeprecated36pxDefaultSizeProp } from '../utils/use-deprecated-props'; import { withIgnoreIMEEvents } from '../utils/with-ignore-ime-events'; +import { maybeWarnDeprecated36pxSize } from '../utils/deprecated-36px-size'; const identity = ( value: string ) => value; @@ -86,6 +87,12 @@ export function FormTokenField( props: FormTokenFieldProps ) { } ); } + maybeWarnDeprecated36pxSize( { + componentName: 'FormTokenField', + size: undefined, + __next40pxDefaultSize, + } ); + const instanceId = useInstanceId( FormTokenField ); // We reset to these initial values again in the onBlur diff --git a/packages/components/src/form-token-field/stories/index.story.tsx b/packages/components/src/form-token-field/stories/index.story.tsx index 729120ad456553..c43d155c809bb7 100644 --- a/packages/components/src/form-token-field/stories/index.story.tsx +++ b/packages/components/src/form-token-field/stories/index.story.tsx @@ -64,6 +64,7 @@ Default.args = { label: 'Type a continent', suggestions: continents, __nextHasNoMarginBottom: true, + __next40pxDefaultSize: true, }; export const Async: StoryFn< typeof FormTokenField > = ( { @@ -102,6 +103,7 @@ Async.args = { label: 'Type a continent', suggestions: continents, __nextHasNoMarginBottom: true, + __next40pxDefaultSize: true, }; export const DropdownSelector: StoryFn< typeof FormTokenField > = diff --git a/packages/components/src/form-token-field/test/index.tsx b/packages/components/src/form-token-field/test/index.tsx index 961214a574c90d..60c17112717bd1 100644 --- a/packages/components/src/form-token-field/test/index.tsx +++ b/packages/components/src/form-token-field/test/index.tsx @@ -21,7 +21,11 @@ import { useState } from '@wordpress/element'; /** * Internal dependencies */ -import FormTokenField from '../'; +import _FormTokenField from '../'; + +const FormTokenField = ( props: ComponentProps< typeof _FormTokenField > ) => ( + <_FormTokenField __next40pxDefaultSize { ...props } /> +); const FormTokenFieldWithState = ( { onChange, From f32a49ec303eb74ec2955c50bfc9262a0bffac84 Mon Sep 17 00:00:00 2001 From: Mayank Tripathi <70465598+Mayank-Tripathi32@users.noreply.github.com> Date: Wed, 4 Dec 2024 04:17:13 +0530 Subject: [PATCH 1837/1908] Fix: Fixed styling tab not opening on themes without style variations on mobile & desktop (#67537) Co-authored-by: Mayank-Tripathi32 <mayanktripathi32@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- .../sidebar-navigation-screen-global-styles/index.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js index 4023ba436b8659..ad3a62e5cd5622 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js @@ -41,7 +41,13 @@ export function SidebarNavigationItemGlobalStyles( props ) { /> ); } - return <SidebarNavigationItem { ...props } />; + return ( + <SidebarNavigationItem + { ...props } + to="/styles" + aria-current={ name === 'styles' } + /> + ); } export default function SidebarNavigationScreenGlobalStyles() { From fa636dc125301270d7ea28c1b90ac00ef612be75 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 4 Dec 2024 13:33:29 +1100 Subject: [PATCH 1838/1908] Site Editor Sidebar: remove `hasGlobalStyleVariations` condition for the Styles nav item (#67545) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> --- .../index.js | 21 +------------------ .../sidebar-navigation-screen-main/index.js | 3 ++- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js index ad3a62e5cd5622..a5902dc37362c5 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js @@ -2,8 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { useSelect, useDispatch } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; +import { useDispatch } from '@wordpress/data'; import { useCallback } from '@wordpress/element'; import { store as preferencesStore } from '@wordpress/preferences'; import { privateApis as routerPrivateApis } from '@wordpress/router'; @@ -24,27 +23,9 @@ const { useLocation, useHistory } = unlock( routerPrivateApis ); export function SidebarNavigationItemGlobalStyles( props ) { const { name } = useLocation(); - const hasGlobalStyleVariations = useSelect( - ( select ) => - !! select( - coreStore - ).__experimentalGetCurrentThemeGlobalStylesVariations()?.length, - [] - ); - if ( hasGlobalStyleVariations ) { - return ( - <SidebarNavigationItem - { ...props } - to="/styles" - uid="global-styles-navigation-item" - aria-current={ name === 'styles' } - /> - ); - } return ( <SidebarNavigationItem { ...props } - to="/styles" aria-current={ name === 'styles' } /> ); diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js index 1db651631c53d4..5cf162a8cd28cc 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js @@ -28,7 +28,8 @@ export function MainSidebarNavigationContent() { { __( 'Navigation' ) } </SidebarNavigationItem> <SidebarNavigationItemGlobalStyles - uid="styles-navigation-item" + to="/styles" + uid="global-styles-navigation-item" icon={ styles } > { __( 'Styles' ) } From d0177839747f999fff5f3d67761d4f5ee90c9ee3 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:14:49 +1100 Subject: [PATCH 1839/1908] Site Editor: Fix the templates route on mobile (#67547) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> --- .../site-editor-routes/templates.js | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/packages/edit-site/src/components/site-editor-routes/templates.js b/packages/edit-site/src/components/site-editor-routes/templates.js index 06ba07fcd06595..cb9f650bbf9267 100644 --- a/packages/edit-site/src/components/site-editor-routes/templates.js +++ b/packages/edit-site/src/components/site-editor-routes/templates.js @@ -1,29 +1,10 @@ -/** - * WordPress dependencies - */ -import { privateApis as routerPrivateApis } from '@wordpress/router'; - /** * Internal dependencies */ import Editor from '../editor'; import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse'; -import { unlock } from '../../lock-unlock'; import PageTemplates from '../page-templates'; -const { useLocation } = unlock( routerPrivateApis ); - -function MobileTemplatesView() { - const { query = {} } = useLocation(); - const { canvas = 'view' } = query; - - return canvas === 'edit' ? ( - <Editor /> - ) : ( - <SidebarNavigationScreenTemplatesBrowse backPath="/" /> - ); -} - export const templatesRoute = { name: 'templates', path: '/template', @@ -34,7 +15,7 @@ export const templatesRoute = { const isListView = query.layout === 'list'; return isListView ? <Editor /> : undefined; }, - mobile: <MobileTemplatesView />, + mobile: <PageTemplates />, }, widths: { content( { query } ) { From cc5a2b70da24a3aa077a858319b4b127722e8e86 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Wed, 4 Dec 2024 11:45:23 +0400 Subject: [PATCH 1840/1908] Block Editor: Group 'onRemove' callback with other public APIs (#67551) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- .../src/components/block-list/block.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 0e3a5be5150ded..29f8a97b031ce2 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -6,13 +6,7 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { - memo, - useCallback, - RawHTML, - useContext, - useMemo, -} from '@wordpress/element'; +import { memo, RawHTML, useContext, useMemo } from '@wordpress/element'; import { getBlockType, getSaveContent, @@ -28,7 +22,7 @@ import { store as blocksStore, } from '@wordpress/blocks'; import { withFilters } from '@wordpress/components'; -import { withDispatch, useDispatch, useSelect } from '@wordpress/data'; +import { withDispatch, useSelect } from '@wordpress/data'; import { compose } from '@wordpress/compose'; import { safeHTML } from '@wordpress/dom'; @@ -103,6 +97,7 @@ function BlockListBlock( { wrapperProps, setAttributes, onReplace, + onRemove, onInsertBlocksAfter, onMerge, toggleSelection, @@ -113,11 +108,6 @@ function BlockListBlock( { themeSupportsLayout, ...context } = useContext( PrivateBlockContext ); - const { removeBlock } = useDispatch( blockEditorStore ); - const onRemove = useCallback( - () => removeBlock( clientId ), - [ clientId, removeBlock ] - ); const parentLayout = useLayout() || {}; @@ -537,6 +527,9 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => { initialPosition ); }, + onRemove() { + removeBlock( ownProps.clientId ); + }, toggleSelection( selectionEnabled ) { toggleSelection( selectionEnabled ); }, From 8ddab8107ca2b17989f45bfb94b328287e49494e Mon Sep 17 00:00:00 2001 From: Sunil Prajapati <61308756+akasunil@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:48:10 +0530 Subject: [PATCH 1841/1908] Inline Commenting: Re-order the comments in sidebar in which blocks are listed (#66927) Co-authored-by: akasunil <sunil25393@git.wordpress.org> Co-authored-by: ellatrix <ellatrix@git.wordpress.org> --- .../src/components/collab-sidebar/index.js | 61 ++++++++++++------- .../src/components/collab-sidebar/utils.js | 36 +++++++++++ 2 files changed, 74 insertions(+), 23 deletions(-) diff --git a/packages/editor/src/components/collab-sidebar/index.js b/packages/editor/src/components/collab-sidebar/index.js index 0fe46c549cff0f..aa1b9ac6c45609 100644 --- a/packages/editor/src/components/collab-sidebar/index.js +++ b/packages/editor/src/components/collab-sidebar/index.js @@ -12,7 +12,7 @@ import { useState, useMemo } from '@wordpress/element'; import { comment as commentIcon } from '@wordpress/icons'; import { addFilter } from '@wordpress/hooks'; import { store as noticesStore } from '@wordpress/notices'; -import { store as coreStore } from '@wordpress/core-data'; +import { store as coreStore, useEntityBlockEditor } from '@wordpress/core-data'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { store as interfaceStore } from '@wordpress/interface'; @@ -27,6 +27,7 @@ import { store as editorStore } from '../../store'; import AddCommentButton from './comment-button'; import AddCommentToolbarButton from './comment-button-toolbar'; import { useGlobalStylesContext } from '../global-styles-provider'; +import { getCommentIdsFromBlocks } from './utils'; const isBlockCommentExperimentEnabled = window?.__experimentalEnableBlockComment; @@ -220,10 +221,24 @@ export default function CollabSidebar() { const { enableComplementaryArea } = useDispatch( interfaceStore ); const { getActiveComplementaryArea } = useSelect( interfaceStore ); - const { postStatus } = useSelect( ( select ) => { + const { postId, postType, postStatus, threads } = useSelect( ( select ) => { + const { getCurrentPostId, getCurrentPostType } = select( editorStore ); + const _postId = getCurrentPostId(); + const data = + !! _postId && typeof _postId === 'number' + ? select( coreStore ).getEntityRecords( 'root', 'comment', { + post: _postId, + type: 'block_comment', + status: 'any', + per_page: 100, + } ) + : null; return { + postId: _postId, + postType: getCurrentPostType(), postStatus: select( editorStore ).getEditedPostAttribute( 'status' ), + threads: data, }; }, [] ); @@ -244,26 +259,12 @@ export default function CollabSidebar() { enableComplementaryArea( 'core', 'edit-post/collab-sidebar' ); }; - const { threads } = useSelect( ( select ) => { - const { getCurrentPostId } = select( editorStore ); - const _postId = getCurrentPostId(); - const data = !! _postId - ? select( coreStore ).getEntityRecords( 'root', 'comment', { - post: _postId, - type: 'block_comment', - status: 'any', - per_page: 100, - } ) - : null; - - return { - postId: _postId, - threads: data, - }; - }, [] ); + const [ blocks ] = useEntityBlockEditor( 'postType', postType, { + id: postId, + } ); // Process comments to build the tree structure - const resultComments = useMemo( () => { + const { resultComments, sortedThreads } = useMemo( () => { // Create a compare to store the references to all objects by id const compare = {}; const result = []; @@ -288,8 +289,22 @@ export default function CollabSidebar() { } } ); - return result; - }, [ threads ] ); + if ( 0 === result?.length ) { + return { resultComments: [], sortedThreads: [] }; + } + + const blockCommentIds = getCommentIdsFromBlocks( blocks ); + + const threadIdMap = new Map( + result.map( ( thread ) => [ thread.id, thread ] ) + ); + + const sortedComments = blockCommentIds + .map( ( id ) => threadIdMap.get( id ) ) + .filter( ( thread ) => thread !== undefined ); + + return { resultComments: result, sortedThreads: sortedComments }; + }, [ threads, blocks ] ); // Get the global styles to set the background color of the sidebar. const { merged: GlobalStyles } = useGlobalStylesContext(); @@ -338,7 +353,7 @@ export default function CollabSidebar() { headerClassName="editor-collab-sidebar__header" > <CollabSidebarContent - comments={ resultComments } + comments={ sortedThreads } showCommentBoard={ showCommentBoard } setShowCommentBoard={ setShowCommentBoard } styles={ { diff --git a/packages/editor/src/components/collab-sidebar/utils.js b/packages/editor/src/components/collab-sidebar/utils.js index 7e73344c5dc0e1..51345392098ff2 100644 --- a/packages/editor/src/components/collab-sidebar/utils.js +++ b/packages/editor/src/components/collab-sidebar/utils.js @@ -7,3 +7,39 @@ export function sanitizeCommentString( str ) { return str.trim(); } + +/** + * Extracts comment IDs from an array of blocks. + * + * This function recursively traverses the blocks and their inner blocks to + * collect all comment IDs found in the block attributes. + * + * @param {Array} blocks - The array of blocks to extract comment IDs from. + * @return {Array} An array of comment IDs extracted from the blocks. + */ +export function getCommentIdsFromBlocks( blocks ) { + // Recursive function to extract comment IDs from blocks + const extractCommentIds = ( items ) => { + return items.reduce( ( commentIds, block ) => { + // Check for comment IDs in the current block's attributes + if ( + block.attributes && + block.attributes.blockCommentId && + ! commentIds.includes( block.attributes.blockCommentId ) + ) { + commentIds.push( block.attributes.blockCommentId ); + } + + // Recursively check inner blocks + if ( block.innerBlocks && block.innerBlocks.length > 0 ) { + const innerCommentIds = extractCommentIds( block.innerBlocks ); + commentIds.push( ...innerCommentIds ); + } + + return commentIds; + }, [] ); + }; + + // Extract all comment IDs recursively + return extractCommentIds( blocks ); +} From dc532bbcf3e9a82039fbc1980e7f0db4962cc70c Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 4 Dec 2024 10:58:05 +0100 Subject: [PATCH 1842/1908] Separator block: Allow divs to be used as separators (#67530) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: luminuu <luminuu@git.wordpress.org> --- docs/reference-guides/core-blocks.md | 2 +- .../block-library/src/separator/block.json | 5 +++ .../block-library/src/separator/deprecated.js | 1 + packages/block-library/src/separator/edit.js | 31 +++++++++++++++++-- packages/block-library/src/separator/save.js | 4 +-- .../block-library/src/separator/test/edit.js | 1 + .../blocks/core__separator-color.json | 3 +- .../blocks/core__separator-custom-color.json | 3 +- .../fixtures/blocks/core__separator.json | 3 +- .../core__separator__deprecated-color-v1.json | 3 +- ...separator__deprecated-custom-color-v1.json | 3 +- 11 files changed, 48 insertions(+), 11 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 34db859f71d1de..29033e278c3488 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -820,7 +820,7 @@ Create a break between ideas or sections with a horizontal separator. ([Source]( - **Name:** core/separator - **Category:** design - **Supports:** align (center, full, wide), anchor, color (background, gradients, ~~enableContrastChecker~~, ~~text~~), interactivity (clientNavigation), spacing (margin) -- **Attributes:** opacity +- **Attributes:** opacity, tagName ## Shortcode diff --git a/packages/block-library/src/separator/block.json b/packages/block-library/src/separator/block.json index 484627aaa1612a..926d978b7e4d59 100644 --- a/packages/block-library/src/separator/block.json +++ b/packages/block-library/src/separator/block.json @@ -11,6 +11,11 @@ "opacity": { "type": "string", "default": "alpha-channel" + }, + "tagName": { + "type": "string", + "enum": [ "hr", "div" ], + "default": "hr" } }, "supports": { diff --git a/packages/block-library/src/separator/deprecated.js b/packages/block-library/src/separator/deprecated.js index 5174310e186ff0..7ce442813e2f78 100644 --- a/packages/block-library/src/separator/deprecated.js +++ b/packages/block-library/src/separator/deprecated.js @@ -49,6 +49,7 @@ const v1 = { style: customColor ? { color: { background: customColor } } : undefined, + tagName: 'hr', }; }, }; diff --git a/packages/block-library/src/separator/edit.js b/packages/block-library/src/separator/edit.js index 0d0af336713c15..c4b832c66158d0 100644 --- a/packages/block-library/src/separator/edit.js +++ b/packages/block-library/src/separator/edit.js @@ -6,20 +6,28 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { HorizontalRule } from '@wordpress/components'; +import { HorizontalRule, SelectControl } from '@wordpress/components'; import { useBlockProps, getColorClassName, __experimentalUseColorProps as useColorProps, + InspectorControls, } from '@wordpress/block-editor'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ import useDeprecatedOpacity from './use-deprecated-opacity'; +const htmlElementMessages = { + div: __( + 'The <div> element should only be used if the separator is a design element that should not be announced.' + ), +}; + export default function SeparatorEdit( { attributes, setAttributes } ) { - const { backgroundColor, opacity, style } = attributes; + const { backgroundColor, opacity, style, tagName } = attributes; const colorProps = useColorProps( attributes ); const currentColor = colorProps?.style?.backgroundColor; const hasCustomColor = !! style?.color?.background; @@ -44,10 +52,27 @@ export default function SeparatorEdit( { attributes, setAttributes } ) { color: currentColor, backgroundColor: currentColor, }; + const Wrapper = tagName === 'hr' ? HorizontalRule : tagName; return ( <> - <HorizontalRule + <InspectorControls group="advanced"> + <SelectControl + __nextHasNoMarginBottom + __next40pxDefaultSize + label={ __( 'HTML element' ) } + options={ [ + { label: __( 'Default (<hr>)' ), value: 'hr' }, + { label: '<div>', value: 'div' }, + ] } + value={ tagName } + onChange={ ( value ) => + setAttributes( { tagName: value } ) + } + help={ htmlElementMessages[ tagName ] } + /> + </InspectorControls> + <Wrapper { ...useBlockProps( { className, style: hasCustomColor ? styles : undefined, diff --git a/packages/block-library/src/separator/save.js b/packages/block-library/src/separator/save.js index 12d2282eb1d3e3..06a54b7519ac17 100644 --- a/packages/block-library/src/separator/save.js +++ b/packages/block-library/src/separator/save.js @@ -13,7 +13,7 @@ import { } from '@wordpress/block-editor'; export default function separatorSave( { attributes } ) { - const { backgroundColor, style, opacity } = attributes; + const { backgroundColor, style, opacity, tagName: Tag } = attributes; const customColor = style?.color?.background; const colorProps = getColorClassesAndStyles( attributes ); // The hr support changing color using border-color, since border-color @@ -37,5 +37,5 @@ export default function separatorSave( { attributes } ) { backgroundColor: colorProps?.style?.backgroundColor, color: colorClass ? undefined : customColor, }; - return <hr { ...useBlockProps.save( { className, style: styles } ) } />; + return <Tag { ...useBlockProps.save( { className, style: styles } ) } />; } diff --git a/packages/block-library/src/separator/test/edit.js b/packages/block-library/src/separator/test/edit.js index a37a0ebbe6dd67..33719b24925cd8 100644 --- a/packages/block-library/src/separator/test/edit.js +++ b/packages/block-library/src/separator/test/edit.js @@ -23,6 +23,7 @@ const defaultAttributes = { opacity: 'alpha-channel', style: {}, className: '', + tagName: 'hr', }; const defaultProps = { attributes: defaultAttributes, diff --git a/test/integration/fixtures/blocks/core__separator-color.json b/test/integration/fixtures/blocks/core__separator-color.json index d32cb34f1871ec..d66a8b2e1a242e 100644 --- a/test/integration/fixtures/blocks/core__separator-color.json +++ b/test/integration/fixtures/blocks/core__separator-color.json @@ -4,7 +4,8 @@ "isValid": true, "attributes": { "opacity": "alpha-channel", - "backgroundColor": "accent" + "backgroundColor": "accent", + "tagName": "hr" }, "innerBlocks": [] } diff --git a/test/integration/fixtures/blocks/core__separator-custom-color.json b/test/integration/fixtures/blocks/core__separator-custom-color.json index 7b0e6c3a7127af..9b126f2b5be6c7 100644 --- a/test/integration/fixtures/blocks/core__separator-custom-color.json +++ b/test/integration/fixtures/blocks/core__separator-custom-color.json @@ -8,7 +8,8 @@ "color": { "background": "#5da54c" } - } + }, + "tagName": "hr" }, "innerBlocks": [] } diff --git a/test/integration/fixtures/blocks/core__separator.json b/test/integration/fixtures/blocks/core__separator.json index 3d69d4e24413c7..aaeb9bc916f38d 100644 --- a/test/integration/fixtures/blocks/core__separator.json +++ b/test/integration/fixtures/blocks/core__separator.json @@ -3,7 +3,8 @@ "name": "core/separator", "isValid": true, "attributes": { - "opacity": "alpha-channel" + "opacity": "alpha-channel", + "tagName": "hr" }, "innerBlocks": [] } diff --git a/test/integration/fixtures/blocks/core__separator__deprecated-color-v1.json b/test/integration/fixtures/blocks/core__separator__deprecated-color-v1.json index 6e0ddf0dbef553..29f520c266f597 100644 --- a/test/integration/fixtures/blocks/core__separator__deprecated-color-v1.json +++ b/test/integration/fixtures/blocks/core__separator__deprecated-color-v1.json @@ -4,7 +4,8 @@ "isValid": true, "attributes": { "backgroundColor": "accent", - "opacity": "css" + "opacity": "css", + "tagName": "hr" }, "innerBlocks": [] } diff --git a/test/integration/fixtures/blocks/core__separator__deprecated-custom-color-v1.json b/test/integration/fixtures/blocks/core__separator__deprecated-custom-color-v1.json index bc2de191b19cd3..556305633861bb 100644 --- a/test/integration/fixtures/blocks/core__separator__deprecated-custom-color-v1.json +++ b/test/integration/fixtures/blocks/core__separator__deprecated-custom-color-v1.json @@ -8,7 +8,8 @@ "color": { "background": "#cc1d1d" } - } + }, + "tagName": "hr" }, "innerBlocks": [] } From ae3e1154070cd41e27f185a97c10bb681bc22326 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 4 Dec 2024 11:01:51 +0100 Subject: [PATCH 1843/1908] Site Editor: Fix sidebar plugins (#67557) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> --- .../edit-site/src/components/app/index.js | 18 +---------------- .../edit-site/src/components/layout/index.js | 20 ++++++++++++++++++- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/packages/edit-site/src/components/app/index.js b/packages/edit-site/src/components/app/index.js index cf13e7baf1b738..744c682dcda5b2 100644 --- a/packages/edit-site/src/components/app/index.js +++ b/packages/edit-site/src/components/app/index.js @@ -1,10 +1,7 @@ /** * WordPress dependencies */ -import { store as noticesStore } from '@wordpress/notices'; -import { useDispatch, useSelect } from '@wordpress/data'; -import { __, sprintf } from '@wordpress/i18n'; -import { PluginArea } from '@wordpress/plugins'; +import { useSelect } from '@wordpress/data'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { useCallback } from '@wordpress/element'; @@ -33,21 +30,9 @@ function AppLayout() { export default function App() { useRegisterSiteEditorRoutes(); - const { createErrorNotice } = useDispatch( noticesStore ); const routes = useSelect( ( select ) => { return unlock( select( editSiteStore ) ).getRoutes(); }, [] ); - function onPluginAreaError( name ) { - createErrorNotice( - sprintf( - /* translators: %s: plugin name */ - __( - 'The "%s" plugin has encountered an error and cannot be rendered.' - ), - name - ) - ); - } const beforeNavigate = useCallback( ( { path, query } ) => { if ( ! isPreviewingTheme() ) { return { path, query }; @@ -72,7 +57,6 @@ export default function App() { beforeNavigate={ beforeNavigate } > <AppLayout /> - <PluginArea onError={ onPluginAreaError } /> </RouterProvider> ); } diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index 7c3f9e21152566..e7606c57a70484 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -18,7 +18,7 @@ import { useResizeObserver, usePrevious, } from '@wordpress/compose'; -import { __ } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; import { useState, useRef, useEffect } from '@wordpress/element'; import { CommandMenu } from '@wordpress/commands'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; @@ -29,6 +29,9 @@ import { } from '@wordpress/editor'; import { privateApis as coreCommandsPrivateApis } from '@wordpress/core-commands'; import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { PluginArea } from '@wordpress/plugins'; +import { store as noticesStore } from '@wordpress/notices'; +import { useDispatch } from '@wordpress/data'; /** * Internal dependencies @@ -235,9 +238,24 @@ function Layout() { } export default function LayoutWithGlobalStylesProvider( props ) { + const { createErrorNotice } = useDispatch( noticesStore ); + function onPluginAreaError( name ) { + createErrorNotice( + sprintf( + /* translators: %s: plugin name */ + __( + 'The "%s" plugin has encountered an error and cannot be rendered.' + ), + name + ) + ); + } + return ( <SlotFillProvider> <GlobalStylesProvider> + { /** This needs to be within the SlotFillProvider */ } + <PluginArea onError={ onPluginAreaError } /> <Layout { ...props } /> </GlobalStylesProvider> </SlotFillProvider> From 6d6e48034561add074e0b867ba33c3e4e7782324 Mon Sep 17 00:00:00 2001 From: Mitchell Austin <mr.fye@oneandthesame.net> Date: Wed, 4 Dec 2024 02:29:55 -0800 Subject: [PATCH 1844/1908] Fix hiding/showing meta boxes (#67504) Co-authored-by: stokesman <presstoke@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> --- packages/edit-post/src/components/meta-boxes/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/edit-post/src/components/meta-boxes/index.js b/packages/edit-post/src/components/meta-boxes/index.js index fdc74a5df4ce95..21416ee43ae240 100644 --- a/packages/edit-post/src/components/meta-boxes/index.js +++ b/packages/edit-post/src/components/meta-boxes/index.js @@ -13,9 +13,9 @@ import { store as editPostStore } from '../../store'; export default function MetaBoxes( { location } ) { const metaBoxes = useSelect( ( select ) => - select( editPostStore ).getMetaBoxesPerLocation[ location ] + select( editPostStore ).getMetaBoxesPerLocation( location ), + [ location ] ); - return ( <> { ( metaBoxes ?? [] ).map( ( { id } ) => ( From e62f8b4dc291bdebc8f41d56d4409371659d430a Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 4 Dec 2024 11:56:05 +0100 Subject: [PATCH 1845/1908] Site Editor: Fix featured image not appearing in pages dataviews (#67562) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- packages/editor/src/dataviews/store/private-actions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 6906629fc80027..754a02d317a385 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -162,7 +162,7 @@ export const registerPostTypeSchema = const fields = [ postTypeConfig.supports?.thumbnail && - currentTheme?.[ 'theme-supports' ]?.[ 'post-thumbnails' ] && + currentTheme?.theme_supports?.[ 'post-thumbnails' ] && featuredImageField, titleField, postTypeConfig.supports?.author && authorField, From 26cd78c9a7150e0a8cc964b700ec56641d610789 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 4 Dec 2024 11:09:44 +0000 Subject: [PATCH 1846/1908] Bump plugin version to 19.8.0-rc.2 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 40c4e86fbb1bf5..29447c1f2db4b5 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.6 * Requires PHP: 7.2 - * Version: 19.8.0-rc.1 + * Version: 19.8.0-rc.2 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 834bb344016d26..24ffc19aba1823 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.8.0-rc.1", + "version": "19.8.0-rc.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.8.0-rc.1", + "version": "19.8.0-rc.2", "hasInstallScript": true, "license": "GPL-2.0-or-later", "workspaces": [ diff --git a/package.json b/package.json index 46a04a52aa6077..3104a8c425f132 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.8.0-rc.1", + "version": "19.8.0-rc.2", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 31e1950bf7bbf6bbe5aace439d10d4a052dff108 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 4 Dec 2024 11:20:32 +0000 Subject: [PATCH 1847/1908] Update Changelog for 19.8.0-rc.2 --- changelog.txt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/changelog.txt b/changelog.txt index 9e07615adf43f6..89afef4535de77 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,31 @@ == Changelog == += 19.8.0-rc.2 = + + +## Changelog + +### Bug Fixes + +#### Site Editor +- 19.8 Edit Site: Styles nav item does not open on mobile for themes without style variations. ([67550](https://github.com/WordPress/gutenberg/pull/67550)) + +#### Zoom Out +- Disable Zoom Out if no section root to allow for Theme opt in. ([67232](https://github.com/WordPress/gutenberg/pull/67232)) + +#### Meta Boxes +- Split view with meta boxes even with legacy canvas. ([66706](https://github.com/WordPress/gutenberg/pull/66706)) + + + + +## Contributors + +The following contributors merged PRs in this release: + +@getdave @ramonjd @stokesman + + = 19.7.0 = ## Changelog From e0341a4abe634d40e2da518e3b1d193d47494b8f Mon Sep 17 00:00:00 2001 From: Michal <mmczaplinski@gmail.com> Date: Wed, 4 Dec 2024 12:02:04 +0000 Subject: [PATCH 1848/1908] Refine `getServerState()` & `getServerContext()` docs (#67499) * `getServerState()` & `getServerContext()` docs: Add note about reactivity. * Fix the code snippets * Add note about local context * Fix param order and function name * Remove the namespace and use the correct functions Co-authored-by: michalczaplinski <czapla@git.wordpress.org> Co-authored-by: luisherranz <luisherranz@git.wordpress.org> --- ...l-state-local-context-and-derived-state.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md b/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md index f4fcbdf576c1cf..f6145749a00b19 100644 --- a/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md +++ b/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md @@ -745,15 +745,15 @@ When using region-based navigation, it's crucial to ensure that your interactive `getServerState()` allows you to subscribe to changes in the **global state** that occur during client-side navigation. This function is analogous to `getServerContext()`, but it works with the global state instead of the local context. +The `getServerState()` function returns a read-only reactive object. This means that any [callbacks](/docs/reference-guides/interactivity-api/api-reference.md#accessing-data-in-callbacks) you have defined that watch the returned object will only trigger when the value returned by the function changes. If the value remains the same, the callback will not re-trigger. + Let's consider a quiz that has multiple questions. Each question is a separate page. When the user navigates to a new question, the server provides the new question and the time left to answer all the questions. ```php -<?php -wp_interactivity_state( 'myPlugin', array( +<div <?php echo wp_interactivity_state( 'myPlugin', array( 'question' => get_question_for_page( get_the_ID() ), 'timeLeft' => 5 * 60, // Time to answer all the questions. -) ); -?> +) ); ?>> ``` ```javascript @@ -789,14 +789,14 @@ store( 'myPlugin', { `getServerContext()` allows you to subscribe to changes in the **local context** that occur during client-side navigation. This function is analogous to `getServerState()`, but it works with the local context instead of the global state. +The `getServerContext()` function returns a read-only reactive object. This means that any [callbacks](/docs/reference-guides/interactivity-api/api-reference.md#accessing-data-in-callbacks) you have defined that watch the returned object will only trigger when the value returned by the function changes. If the value remains the same, the callback will not re-trigger. + Consider a quiz that has multiple questions. Each question is a separate page. When the user navigates to a new question, the server provides the new question and the time left to answer all the questions. ```php -<?php -wp_interactivity_context( 'myPlugin', array( +<div <?php echo wp_interactivity_data_wp_context( array( 'currentQuestion' => get_question_for_page( get_the_ID() ), -) ); -?> +), ); ?>> ``` ```javascript @@ -830,12 +830,12 @@ store( 'myPlugin', { ### When to Use -Whenever you have interactive blocks that rely on global state that may change due to navigation events, ensuring consistency across different parts of your application. +Whenever you have interactive blocks that rely on global state or local context that may change due to navigation events, ensuring consistency across different parts of your application. ### Best Practices for using `getServerState()` and `getServerContext()` - **Read-Only References:** Both `getServerState()` and `getServerContext()` return read-only objects. You can use those objects to update the global state or local context. -- **Callback Integration:** Incorporate these functions within your store [callbacks](/docs/reference-guides/interactivity-api/api-reference.md#accessing-data-in-callbacks) to react to state and context changes. +- **Callback Integration:** Incorporate these functions within your store [callbacks](/docs/reference-guides/interactivity-api/api-reference.md#accessing-data-in-callbacks) to react to state and context changes. Both `getServerState()` and `getServerContext()` return reactive objects. This means that their watch callbacks will only trigger when the value of a property changes. If the value remains the same, the callback will not re-trigger. ## Conclusion From 63999daf3b7202ef02836c61e785bbd064d0848f Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 4 Dec 2024 12:08:44 +0000 Subject: [PATCH 1849/1908] Bump plugin version to 19.8.0 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 29447c1f2db4b5..bcc941f2cb83f9 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.6 * Requires PHP: 7.2 - * Version: 19.8.0-rc.2 + * Version: 19.8.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 24ffc19aba1823..3084fd5f034401 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.8.0-rc.2", + "version": "19.8.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.8.0-rc.2", + "version": "19.8.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "workspaces": [ diff --git a/package.json b/package.json index 3104a8c425f132..190664e11551dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.8.0-rc.2", + "version": "19.8.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 88a3cef341fac21d74a08b0d94e0b0bc45c0fbd6 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation <gutenberg@wordpress.org> Date: Wed, 4 Dec 2024 12:19:25 +0000 Subject: [PATCH 1850/1908] Update Changelog for 19.8.0 --- changelog.txt | 235 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 229 insertions(+), 6 deletions(-) diff --git a/changelog.txt b/changelog.txt index 89afef4535de77..38b33267554982 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,29 +1,252 @@ == Changelog == -= 19.8.0-rc.2 = - += 19.8.0 = ## Changelog +### Enhancements + +#### Block Library +- Details block: Use summary content as default label. ([67217](https://github.com/WordPress/gutenberg/pull/67217)) +- Make social icon navigation one arrow keypress. ([64883](https://github.com/WordPress/gutenberg/pull/64883)) +- Page List : Add border and spacing support. ([66385](https://github.com/WordPress/gutenberg/pull/66385)) +- Query Loop block: Remove 'add new post' prompt in the sidebar. ([67189](https://github.com/WordPress/gutenberg/pull/67189)) +- Query block: Update Enhanced Pagination help text. ([67173](https://github.com/WordPress/gutenberg/pull/67173)) +- Social Link: Add contentOnly editing support. ([66622](https://github.com/WordPress/gutenberg/pull/66622)) + +#### Components +- Autocomplete: Increase option height. ([67214](https://github.com/WordPress/gutenberg/pull/67214)) +- CircularOptionPicker: Update Button sizes. ([67285](https://github.com/WordPress/gutenberg/pull/67285)) +- ColorPalette: Disable `Clear` button if there's no color value. ([67108](https://github.com/WordPress/gutenberg/pull/67108)) +- ColorPicker: Update sizes of format select and copy button. ([67093](https://github.com/WordPress/gutenberg/pull/67093)) +- ComboboxControl: Update reset button size. ([67215](https://github.com/WordPress/gutenberg/pull/67215)) + +#### DataViews +- Add density option to `table` layout. ([67170](https://github.com/WordPress/gutenberg/pull/67170)) +- DataForm: Enable fields to declare a different layout. ([66531](https://github.com/WordPress/gutenberg/pull/66531)) +- DataViews list layout: Hide actions menu when there is only one action and is primary. ([67015](https://github.com/WordPress/gutenberg/pull/67015)) +- DataViews table layout: Hide actions menu when there is only one action and is primary. ([67020](https://github.com/WordPress/gutenberg/pull/67020)) +- Reduce the size of action button in Grid layout. ([67032](https://github.com/WordPress/gutenberg/pull/67032)) +- DataViews: Allow register/unregister fields. ([67175](https://github.com/WordPress/gutenberg/pull/67175)) + +#### Global Styles +- Block Supports: Extend stabilization to common experimental block support flags. ([67018](https://github.com/WordPress/gutenberg/pull/67018)) +- Borders: Stabilize border block supports within block processing. ([66918](https://github.com/WordPress/gutenberg/pull/66918)) +- Site Editor > Styles: Open styles inspector when clicking preview canvas. ([66996](https://github.com/WordPress/gutenberg/pull/66996)) + +#### Media +- Block Editor: Add notice action to revert image to original after cropping. ([67314](https://github.com/WordPress/gutenberg/pull/67314)) +- Block Editor: Add success notices for image editing. ([67312](https://github.com/WordPress/gutenberg/pull/67312)) + +#### REST API +- Feature: Set editor rendering mode by post type. ([62304](https://github.com/WordPress/gutenberg/pull/62304)) +- Terms: Respect order specified by register_taxonomy(). ([67154](https://github.com/WordPress/gutenberg/pull/67154)) + +#### Zoom Out +- Leave help text regardless of zoom state. ([67132](https://github.com/WordPress/gutenberg/pull/67132)) +- Preserve footer template bar in zoom out. ([67135](https://github.com/WordPress/gutenberg/pull/67135)) +- Add section styles switch button in block toolbar in zoom out mode. ([67140](https://github.com/WordPress/gutenberg/pull/67140)) + +#### Post Editor +- Move default template types and template part areas to REST API. ([66459](https://github.com/WordPress/gutenberg/pull/66459)) +- Move `usePostFields` to `wordpress/editor` package. ([67024](https://github.com/WordPress/gutenberg/pull/67024)) + +#### Site Editor +- Blocks: Adds check for parent before showing convert to pattern button. ([66158](https://github.com/WordPress/gutenberg/pull/66158)) +- Try dark toolbar for the write mode. ([66116](https://github.com/WordPress/gutenberg/pull/66116)) + +#### Design Tools +- Heading: Hide border controls by default. ([67105](https://github.com/WordPress/gutenberg/pull/67105)) +- Font family preview in the font family picker. ([67118](https://github.com/WordPress/gutenberg/pull/67118)) + ### Bug Fixes +#### Block Library +- Fix block mover clickable area. ([67261](https://github.com/WordPress/gutenberg/pull/67261)) +- Fix dropping media from inserter into Cover block. ([67056](https://github.com/WordPress/gutenberg/pull/67056)) +- Fix: Preserve Display Preview State in File Block. ([67263](https://github.com/WordPress/gutenberg/pull/67263)) +- Paragraph: Update condition for rendering Drop Cap for a selected block. ([67111](https://github.com/WordPress/gutenberg/pull/67111)) +- RSS block: Check for description field before rendering excerpt. ([66985](https://github.com/WordPress/gutenberg/pull/66985)) +- Resolve search block button text overlapping issue. ([66868](https://github.com/WordPress/gutenberg/pull/66868)) +- Social Links: Fix font family and weight inconsistency in editor. ([67204](https://github.com/WordPress/gutenberg/pull/67204)) + +#### Components +- Composite: Restore `Hover` and `Typeahead` functionality. ([67212](https://github.com/WordPress/gutenberg/pull/67212)) +- Menu.ItemHelpText: Better line breaking. ([67011](https://github.com/WordPress/gutenberg/pull/67011)) +- SlotFill: Fix a bug with storing stale fillProps. ([67000](https://github.com/WordPress/gutenberg/pull/67000)) +- Storybook: Fix DataViews layout. ([66999](https://github.com/WordPress/gutenberg/pull/66999)) +- `FormFileUpload`: Prevent HEIC and HEIF files from always being uploaded on Safari. ([67139](https://github.com/WordPress/gutenberg/pull/67139)) + +#### Block Editor +- Add all color palettes to select from editor panel. ([65148](https://github.com/WordPress/gutenberg/pull/65148)) +- Correctly mark Block Comment SlotFills private. ([67271](https://github.com/WordPress/gutenberg/pull/67271)) +- Fix media placeholder to only activate for media objects. ([66986](https://github.com/WordPress/gutenberg/pull/66986)) +- Rich text: Preserve comments. ([62128](https://github.com/WordPress/gutenberg/pull/62128)) +- Fix TS types for the editor package. ([67196](https://github.com/WordPress/gutenberg/pull/67196)) +- PostTitle: Exit early when post type doesn't support titles. ([67086](https://github.com/WordPress/gutenberg/pull/67086)) +- Split view with meta boxes even with legacy canvas. ([66706](https://github.com/WordPress/gutenberg/pull/66706)) +- Edit Site: Styles nav item does not open on mobile for themes without style variations. ([67550](https://github.com/WordPress/gutenberg/pull/67550)) + +#### Global Styles +- Avoid zooming out when browsing styles if the preview mode is active. ([67190](https://github.com/WordPress/gutenberg/pull/67190)) +- Remove styles from blocks' previews. ([67144](https://github.com/WordPress/gutenberg/pull/67144)) +- Style panel: Use correct revisions count. ([67180](https://github.com/WordPress/gutenberg/pull/67180)) +- Theme JSON: Include block style variations in path only output of get_block_nodes. ([66948](https://github.com/WordPress/gutenberg/pull/66948)) +- Fix: Logic for Highlight/text-color format availability. ([65530](https://github.com/WordPress/gutenberg/pull/65530)) +- Fix complex variation selectors when using selectors API. ([67061](https://github.com/WordPress/gutenberg/pull/67061)) #### Site Editor -- 19.8 Edit Site: Styles nav item does not open on mobile for themes without style variations. ([67550](https://github.com/WordPress/gutenberg/pull/67550)) +- Prevent Pre-Publish Panel from Displaying Incorrect Information After Navigating away. ([67010](https://github.com/WordPress/gutenberg/pull/67010)) +- Site Editor Sidebar: Fixed focus/hover style for navigation item buttons. ([67251](https://github.com/WordPress/gutenberg/pull/67251)) +- Site Hub: Fix height in mobile layout. ([67110](https://github.com/WordPress/gutenberg/pull/67110)) +- Site Editor: Styles: Fix inspector opening. ([67004](https://github.com/WordPress/gutenberg/pull/67004)) +- Improve accessibility and consistency of the 'Last modified' Revisions button. ([66606](https://github.com/WordPress/gutenberg/pull/66606)) +- Remove styles from examples. ([67098](https://github.com/WordPress/gutenberg/pull/67098)) +- Editor: Correctly select post title support in 'DocumentOutline'. ([67109](https://github.com/WordPress/gutenberg/pull/67109)) + + +#### DataViews +- Fix action visibility logic. ([67197](https://github.com/WordPress/gutenberg/pull/67197)) +- Fix primary field misalignment in grid layout. ([66995](https://github.com/WordPress/gutenberg/pull/66995)) +- Fix spacing when combining combined fields. ([67226](https://github.com/WordPress/gutenberg/pull/67226)) #### Zoom Out +- Zoom In/Out to correct canvas location. ([66917](https://github.com/WordPress/gutenberg/pull/66917)) +- Zoom in/out to correct location. ([67126](https://github.com/WordPress/gutenberg/pull/67126)) +- Zoom Out: Disable zooming out when Distraction Free mode is activated. ([67028](https://github.com/WordPress/gutenberg/pull/67028)) - Disable Zoom Out if no section root to allow for Theme opt in. ([67232](https://github.com/WordPress/gutenberg/pull/67232)) -#### Meta Boxes -- Split view with meta boxes even with legacy canvas. ([66706](https://github.com/WordPress/gutenberg/pull/66706)) +#### Layout +- Allow flex justification controls to be disabled at the block level. ([67059](https://github.com/WordPress/gutenberg/pull/67059)) +- Show vertical alignment toolbar with allowSwitching enabled. ([67022](https://github.com/WordPress/gutenberg/pull/67022)) +#### Patterns +- Fix: JavaScript error when pattern category is unregistered. ([67063](https://github.com/WordPress/gutenberg/pull/67063)) +- Block Locking: Remove edit locking for Synced Patterns. ([67021](https://github.com/WordPress/gutenberg/pull/67021)) +### Accessibility + +#### Components +- ColorPicker: Add accessible label for copy button. ([67094](https://github.com/WordPress/gutenberg/pull/67094)) +- Modal: Increase size of the Close button. ([66792](https://github.com/WordPress/gutenberg/pull/66792)) +- DataViews: Fix focus loss when removing all filters or resetting. ([67003](https://github.com/WordPress/gutenberg/pull/67003)) + +#### Block Library +- Improve accessibility of the video track editor. ([66832](https://github.com/WordPress/gutenberg/pull/66832)) +- Navigation: Fix 'ariaLabel' block support. ([66943](https://github.com/WordPress/gutenberg/pull/66943)) + +#### Post Editor +- Improve the featured image UI when it cannot retrieve the image file and data. ([66936](https://github.com/WordPress/gutenberg/pull/66936)) + +### Experiments + +- Inline Commenting: Update placement of reply input and add author info header. ([66580](https://github.com/WordPress/gutenberg/pull/66580)) +- Place "Write mode" functionality behind a Gutenberg experiment. ([67008](https://github.com/WordPress/gutenberg/pull/67008)) + +### Documentation + +- Add documentation about required Core changes when updating minimum WordPress version. ([67167](https://github.com/WordPress/gutenberg/pull/67167)) +- BoxControl: Auto-generate readme. ([67284](https://github.com/WordPress/gutenberg/pull/67284)) +- Components contributing guide: Fix relative links. ([67323](https://github.com/WordPress/gutenberg/pull/67323)) +- DataViews: Reorganize documentation for actions. ([67159](https://github.com/WordPress/gutenberg/pull/67159)) +- Docs: Correct `@return` type in `block_core_query_disable_enhanced_pagination()`. ([67128](https://github.com/WordPress/gutenberg/pull/67128)) +- Feat: Storybook: Improve component organisation - Layout Category - Issue #66275. ([66659](https://github.com/WordPress/gutenberg/pull/66659)) +- Feat: Storybook: Improve component organisation - Selection & Input Category - Issue #66275. ([66635](https://github.com/WordPress/gutenberg/pull/66635)) +- GradientPicker: Auto-generate readme. ([67250](https://github.com/WordPress/gutenberg/pull/67250)) +- Icon: Auto-generate readme. ([67282](https://github.com/WordPress/gutenberg/pull/67282)) +- Icon: Improve `icon` prop usage documentation in Storybook. ([67280](https://github.com/WordPress/gutenberg/pull/67280)) +- Storybook: Restore stable components back into categories. ([67216](https://github.com/WordPress/gutenberg/pull/67216)) +- Update BlockMover Stories and README. ([66519](https://github.com/WordPress/gutenberg/pull/66519)) +- Update custom store readme to use thunks instead of controls. ([67006](https://github.com/WordPress/gutenberg/pull/67006)) +- Update versions-in-wordpress.md. ([67298](https://github.com/WordPress/gutenberg/pull/67298)) + +### Code Quality + +- ESLint: Enable `eslint-plugin-react-compiler`. ([61788](https://github.com/WordPress/gutenberg/pull/61788)) +- Extract selectors from useResolveEditedEntity hook. ([67031](https://github.com/WordPress/gutenberg/pull/67031)) +- Pattern: Remove backward compatibility code for WordPress < 6.4. ([67131](https://github.com/WordPress/gutenberg/pull/67131)) +- Post fields: Move `author` from `edit-site` to `fields` package. ([66939](https://github.com/WordPress/gutenberg/pull/66939)) +- Posts DataViews: Refactor the router to use route registration. ([67160](https://github.com/WordPress/gutenberg/pull/67160)) +- Comments controller: Fix issue where comments are allowed when closed. ([66976](https://github.com/WordPress/gutenberg/pull/66976)) +- Fix fatal error in in_array call in post_type_default_rendering_mode. ([67225](https://github.com/WordPress/gutenberg/pull/67225)) +- Data: Add changelog for Redux update. ([66968](https://github.com/WordPress/gutenberg/pull/66968)) + +#### Components +- BorderBoxControl: Suppress redundant warnings for deprecated 36px size. ([67213](https://github.com/WordPress/gutenberg/pull/67213)) +- ComboboxControl : Deprecate 36px default size. ([66900](https://github.com/WordPress/gutenberg/pull/66900)) +- CustomGradientPicker: Prepare `Button`s for 40px default size. ([67286](https://github.com/WordPress/gutenberg/pull/67286)) +- Dashicons: Remove non-existent icons from type. ([67235](https://github.com/WordPress/gutenberg/pull/67235)) +- DimensionControl: Deprecate 36px default size. ([66705](https://github.com/WordPress/gutenberg/pull/66705)) +- Feat: Adds the deprecation warning for 36px default size in range control. ([66721](https://github.com/WordPress/gutenberg/pull/66721)) +- FontSizePicker : Deprecate 36px default size. ([66920](https://github.com/WordPress/gutenberg/pull/66920)) +- Remove createPrivateSlotFill function. ([67238](https://github.com/WordPress/gutenberg/pull/67238)) +- SlotFill: Fix dependencies of registration effects, deduplicate code. ([67071](https://github.com/WordPress/gutenberg/pull/67071)) +- SlotFill: Remove registration API from useSlot result. ([67070](https://github.com/WordPress/gutenberg/pull/67070)) +- SlotFill: Rewrite base Slot to functional, unify rerenderable refs. ([67153](https://github.com/WordPress/gutenberg/pull/67153)) +- TextControl: Deprecate 36px default size. ([66745](https://github.com/WordPress/gutenberg/pull/66745)) +- ToggleGroupControl : Deprecate 36px default size. ([66747](https://github.com/WordPress/gutenberg/pull/66747)) + +#### Post Editor +- ESLint: Bump `eslint-plugin-react-compiler` to latest beta. ([67106](https://github.com/WordPress/gutenberg/pull/67106)) +- Edit Post: Refactor 'MetaBoxVisibility' component. ([67265](https://github.com/WordPress/gutenberg/pull/67265)) +- Edit Post: Remove unused 'hasHistory' flag. ([67293](https://github.com/WordPress/gutenberg/pull/67293)) +- Editor: Update focus return handler for the Featured Image. ([67236](https://github.com/WordPress/gutenberg/pull/67236)) +- Make `BlockManager` component reusable. ([67052](https://github.com/WordPress/gutenberg/pull/67052)) +- Preferences: Use hooks instead of HoC in 'EnableCustomFieldsOption'. ([67023](https://github.com/WordPress/gutenberg/pull/67023)) +- Preferences: Use hooks instead of HoC in 'EnablePanelOption'. ([66994](https://github.com/WordPress/gutenberg/pull/66994)) +- Preferences: Use hooks instead of HoC in 'EnablePublishSidebarOption'. ([67002](https://github.com/WordPress/gutenberg/pull/67002)) + +#### Block Library +- Fix React Compiler error for shortcuts. ([67019](https://github.com/WordPress/gutenberg/pull/67019)) +- Home Link: Remove label attribute synchronization. ([67151](https://github.com/WordPress/gutenberg/pull/67151)) +- Use rems for Nav overlay left padding. ([67168](https://github.com/WordPress/gutenberg/pull/67168)) +- useBlockNameForPatterns: Refactor as a single useSelect call. ([67171](https://github.com/WordPress/gutenberg/pull/67171)) +- Navigation Block: Remove obsolete Block Hooks filters. ([64676](https://github.com/WordPress/gutenberg/pull/64676)) +- [mini] 🧹 remove obsolete rich text css. ([67264](https://github.com/WordPress/gutenberg/pull/67264)) + +#### Global Styles +- Don't call store actions during the render. ([67146](https://github.com/WordPress/gutenberg/pull/67146)) +- Edit Site: Fix settings mutation in `ScreenBlock`. ([67085](https://github.com/WordPress/gutenberg/pull/67085)) +- Remove unused 'Fragment' import. ([67104](https://github.com/WordPress/gutenberg/pull/67104)) + +#### Block Editor +- Block Manager: Make it a private component in the block editor package. ([67255](https://github.com/WordPress/gutenberg/pull/67255)) +- Inserter: Set initial active tab ID during render. ([67103](https://github.com/WordPress/gutenberg/pull/67103)) + +#### Site Editor +- Deprecate edited entity state. ([66965](https://github.com/WordPress/gutenberg/pull/66965)) +- Remove redundant style-edit route. ([67057](https://github.com/WordPress/gutenberg/pull/67057)) + +### Tools + +#### Testing +- Fix ESLint Jest reporting entire body of the test function rather than the identifier. ([67222](https://github.com/WordPress/gutenberg/pull/67222)) +- Fix typo in use-block-sync tests. ([67145](https://github.com/WordPress/gutenberg/pull/67145)) +- Migrate Gradle wrapper validation action. ([66602](https://github.com/WordPress/gutenberg/pull/66602)) + +#### Plugin +- Bump minimum required WordPress version to 6.6. ([67117](https://github.com/WordPress/gutenberg/pull/67117)) +- Add #7895 Core Backport PR to the changelog. ([67319](https://github.com/WordPress/gutenberg/pull/67319)) +- WP Scripts: Revert changes that inline CSS imports early in the build process. ([66975](https://github.com/WordPress/gutenberg/pull/66975)) + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @AKSHAT2802: Add all color palettes to select from editor panel. ([65148](https://github.com/WordPress/gutenberg/pull/65148)) +- @benazeer-ben: Page List : Add border and spacing support. ([66385](https://github.com/WordPress/gutenberg/pull/66385)) +- @himanshupathak95: Menu.ItemHelpText: Better line breaking. ([67011](https://github.com/WordPress/gutenberg/pull/67011)) +- @SainathPoojary: Social Links: Fix font family and weight inconsistency in editor. ([67204](https://github.com/WordPress/gutenberg/pull/67204)) +- @sarthaknagoshe2002: Prevent Pre-Publish Panel from Displaying Incorrect Information After Navigating away. ([67010](https://github.com/WordPress/gutenberg/pull/67010)) +- @Sukhendu2002: Fix: Preserve Display Preview State in File Block. ([67263](https://github.com/WordPress/gutenberg/pull/67263)) ## Contributors The following contributors merged PRs in this release: -@getdave @ramonjd @stokesman +@aaronrobertshaw @afercia @ajlende @akasunil @AKSHAT2802 @benazeer-ben @benniledl @carolinan @cbravobernal @desrosj @dhruvang21 @dougwollison @ellatrix @getdave @gigitux @gziolo @hbhalodia @himanshupathak95 @Infinite-Null @jeryj @jsnajdr @juanfra @louwie17 @Mamaduka @manzoorwanijk @matiasbenedetto @mcsf @michalczaplinski @miminari @mirka @ndiego @ntsekouras @oandregal @ockham @PARTHVATALIYA @ramonjd @SainathPoojary @SantosGuillamot @sarthaknagoshe2002 @snehapatil2001 @Soean @stokesman @Sukhendu2002 @t-hamano @talldan @tellthemachines @TylerB24890 @tyxla @up1512001 @vipul0425 @yogeshbhutkar @youknowriad + + = 19.7.0 = From 532b8e2a55564746ba10c7ffd5db94491c950fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:02:46 +0100 Subject: [PATCH 1851/1908] QuickEdit: prevent site-editor from crashing when data is not an object (#67577) Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: gigitux <gigitux@git.wordpress.org> --- packages/fields/src/fields/slug/slug-view.tsx | 2 +- packages/fields/src/fields/slug/utils.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/fields/src/fields/slug/slug-view.tsx b/packages/fields/src/fields/slug/slug-view.tsx index c418fafd1a9af9..58f6881060c2db 100644 --- a/packages/fields/src/fields/slug/slug-view.tsx +++ b/packages/fields/src/fields/slug/slug-view.tsx @@ -10,7 +10,7 @@ import type { BasePost } from '../../types'; import { getSlug } from './utils'; const SlugView = ( { item }: { item: BasePost } ) => { - const slug = typeof item === 'object' ? getSlug( item ) : ''; + const slug = getSlug( item ); const originalSlugRef = useRef( slug ); useEffect( () => { diff --git a/packages/fields/src/fields/slug/utils.ts b/packages/fields/src/fields/slug/utils.ts index a422afaf898f96..b414146ba17819 100644 --- a/packages/fields/src/fields/slug/utils.ts +++ b/packages/fields/src/fields/slug/utils.ts @@ -9,6 +9,10 @@ import type { BasePost } from '../../types'; import { getItemTitle } from '../../actions/utils'; export const getSlug = ( item: BasePost ): string => { + if ( typeof item !== 'object' ) { + return ''; + } + return ( item.slug || cleanForSlug( getItemTitle( item ) ) || item.id.toString() ); From ce00a5ff22c775b04aa5521687719f689996f45c Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Wed, 4 Dec 2024 18:37:55 +0100 Subject: [PATCH 1852/1908] DataViews build-wp: don't bundle singleton WordPress packages (#67590) Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/dataviews/build.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/dataviews/build.js b/packages/dataviews/build.js index 582826d18c1847..e156b1cb875af0 100644 --- a/packages/dataviews/build.js +++ b/packages/dataviews/build.js @@ -7,8 +7,15 @@ const esbuild = require( 'esbuild' ); const wpExternals = { name: 'wordpress-externals', setup( build ) { + build.onResolve( + { filter: /^@wordpress\/(data|hooks|i18n)(\/|$)/ }, + ( args ) => { + // Don't bundle WordPress signleton packages + return { path: args.path, external: true }; + } + ); build.onResolve( { filter: /^@wordpress\// }, () => { - // Bundle wordpress packages + // Bundle WordPress packages return { external: false }; } ); build.onResolve( { filter: /^\.[\.\/]/ }, () => { From 944c5b0f37e5c6b5bc47f78575bd1c1b55f6c6eb Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 5 Dec 2024 06:11:20 +1100 Subject: [PATCH 1853/1908] Update misc types and revert WPCompleter export from components (#67599) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- packages/block-editor/src/autocompleters/block.js | 6 ++---- packages/block-editor/src/autocompleters/link.js | 6 ++---- packages/components/CHANGELOG.md | 1 - packages/components/src/index.ts | 1 - packages/editor/README.md | 10 +++++----- packages/editor/src/components/autocompleters/user.js | 4 +--- packages/editor/src/components/post-trash/check.js | 8 ++++---- 7 files changed, 14 insertions(+), 22 deletions(-) diff --git a/packages/block-editor/src/autocompleters/block.js b/packages/block-editor/src/autocompleters/block.js index 5fc107c4d3d69e..eedd5e102db2ca 100644 --- a/packages/block-editor/src/autocompleters/block.js +++ b/packages/block-editor/src/autocompleters/block.js @@ -23,12 +23,10 @@ import { orderInserterBlockItems } from '../utils/order-inserter-block-items'; const noop = () => {}; const SHOWN_BLOCK_TYPES = 9; -/** @typedef {import('@wordpress/components').WPCompleter} WPCompleter */ - /** * Creates a blocks repeater for replacing the current block with a selected block type. * - * @return {WPCompleter} A blocks completer. + * @return {Object} A blocks completer. */ function createBlockCompleter() { return { @@ -157,6 +155,6 @@ function createBlockCompleter() { /** * Creates a blocks repeater for replacing the current block with a selected block type. * - * @return {WPCompleter} A blocks completer. + * @return {Object} A blocks completer. */ export default createBlockCompleter(); diff --git a/packages/block-editor/src/autocompleters/link.js b/packages/block-editor/src/autocompleters/link.js index fb64cb151294d6..9088b65b4abc86 100644 --- a/packages/block-editor/src/autocompleters/link.js +++ b/packages/block-editor/src/autocompleters/link.js @@ -10,12 +10,10 @@ import { decodeEntities } from '@wordpress/html-entities'; const SHOWN_SUGGESTIONS = 10; -/** @typedef {import('@wordpress/components').WPCompleter} WPCompleter */ - /** * Creates a suggestion list for links to posts or pages. * - * @return {WPCompleter} A links completer. + * @return {Object} A links completer. */ function createLinkCompleter() { return { @@ -60,6 +58,6 @@ function createLinkCompleter() { /** * Creates a suggestion list for links to posts or pages.. * - * @return {WPCompleter} A link completer. + * @return {Object} A link completer. */ export default createLinkCompleter(); diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 2be7450f43d0f5..1045b23bfe14f6 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -34,7 +34,6 @@ - Upgraded `@ariakit/react` (v0.4.13) and `@ariakit/test` (v0.4.5) ([#65907](https://github.com/WordPress/gutenberg/pull/65907)). - Upgraded `@ariakit/react` (v0.4.15) and `@ariakit/test` (v0.4.7) ([#67404](https://github.com/WordPress/gutenberg/pull/67404)). - `ToolbarButton`: Set size to "compact" ([#67440](https://github.com/WordPress/gutenberg/pull/67440)). -- Exported the `WPCompleter` type as it was being used in block-editor/autocompleters ([#67410](https://github.com/WordPress/gutenberg/pull/67410)). - `SlotFill`: remove manual rerenders from the portal `Fill` component ([#67471](https://github.com/WordPress/gutenberg/pull/67471)). ### Bug Fixes diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index 0558584fe5418c..e82d6da70279e8 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -108,7 +108,6 @@ export { Heading as __experimentalHeading } from './heading'; export { HStack as __experimentalHStack } from './h-stack'; export { default as Icon } from './icon'; export type { IconType } from './icon'; -export type { WPCompleter } from './autocomplete/types.ts'; export { default as IconButton } from './button/deprecated'; export { ItemGroup as __experimentalItemGroup, diff --git a/packages/editor/README.md b/packages/editor/README.md index dd7b53f421a1db..3211e6664256d0 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -1457,16 +1457,16 @@ _Returns_ ### PostTrashCheck -Wrapper component that renders its children only if the post can trashed. +Wrapper component that renders its children only if the post can be trashed. _Parameters_ -- _props_ `Object`: - The component props. -- _props.children_ `React.ReactNode`: - The child components to render. +- _props_ `Object`: The component props. +- _props.children_ `React.ReactElement`: The child components. _Returns_ -- `React.ReactNode`: The rendered child components or null if the post can not trashed. +- `React.ReactElement | null`: The rendered child components or null if the post can't be trashed. ### PostTypeSupportCheck @@ -1762,7 +1762,7 @@ A user mentions completer. _Type_ -- `WPCompleter` +- `Object` ### VisualEditorGlobalKeyboardShortcuts diff --git a/packages/editor/src/components/autocompleters/user.js b/packages/editor/src/components/autocompleters/user.js index e176d3fb6b05a2..aed226ff4a50da 100644 --- a/packages/editor/src/components/autocompleters/user.js +++ b/packages/editor/src/components/autocompleters/user.js @@ -5,8 +5,6 @@ import { useMemo } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -/** @typedef {import('@wordpress/components').WPCompleter} WPCompleter */ - export function getUserLabel( user ) { const avatar = user.avatar_urls && user.avatar_urls[ 24 ] ? ( @@ -35,7 +33,7 @@ export function getUserLabel( user ) { /** * A user mentions completer. * - * @type {WPCompleter} + * @type {Object} */ export default { name: 'users', diff --git a/packages/editor/src/components/post-trash/check.js b/packages/editor/src/components/post-trash/check.js index d4a9139bfee057..590aa7cd4c390b 100644 --- a/packages/editor/src/components/post-trash/check.js +++ b/packages/editor/src/components/post-trash/check.js @@ -11,12 +11,12 @@ import { store as editorStore } from '../../store'; import { GLOBAL_POST_TYPES } from '../../store/constants'; /** - * Wrapper component that renders its children only if the post can trashed. + * Wrapper component that renders its children only if the post can be trashed. * - * @param {Object} props - The component props. - * @param {React.ReactNode} props.children - The child components to render. + * @param {Object} props The component props. + * @param {React.ReactElement} props.children The child components. * - * @return {React.ReactNode} The rendered child components or null if the post can not trashed. + * @return {React.ReactElement | null} The rendered child components or null if the post can't be trashed. */ export default function PostTrashCheck( { children } ) { const { canTrashPost } = useSelect( ( select ) => { From bb56ce8350cb0ddef9df3bcb75b24fa5e81a9ab3 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 5 Dec 2024 06:14:07 +1100 Subject: [PATCH 1854/1908] Edit site: remove empty preview border and redirect to editor in global styles navigation (#67548) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- .../src/components/global-styles/style.scss | 4 ++++ .../components/site-editor-routes/styles.js | 21 ++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss index 5574fe52d81f58..57f51f4b8f007c 100644 --- a/packages/edit-site/src/components/global-styles/style.scss +++ b/packages/edit-site/src/components/global-styles/style.scss @@ -226,6 +226,10 @@ // The &#{&} is a workaround for the specificity of the Card component. &#{&}, &#{&} .edit-site-global-styles-screen-root__active-style-tile-preview { + box-shadow: none; border-radius: $radius-small; + .block-editor-iframe__container { + border: 1px solid $gray-200; + } } } diff --git a/packages/edit-site/src/components/site-editor-routes/styles.js b/packages/edit-site/src/components/site-editor-routes/styles.js index 17e4a3c064d023..cf29dbebea3733 100644 --- a/packages/edit-site/src/components/site-editor-routes/styles.js +++ b/packages/edit-site/src/components/site-editor-routes/styles.js @@ -1,10 +1,29 @@ +/** + * WordPress dependencies + */ +import { privateApis as routerPrivateApis } from '@wordpress/router'; + /** * Internal dependencies */ import Editor from '../editor'; +import { unlock } from '../../lock-unlock'; import SidebarNavigationScreenGlobalStyles from '../sidebar-navigation-screen-global-styles'; import GlobalStylesUIWrapper from '../sidebar-global-styles-wrapper'; +const { useLocation } = unlock( routerPrivateApis ); + +function MobileGlobalStylesUI() { + const { query = {} } = useLocation(); + const { canvas } = query; + + if ( canvas === 'edit' ) { + return <Editor />; + } + + return <GlobalStylesUIWrapper />; +} + export const stylesRoute = { name: 'styles', path: '/styles', @@ -12,7 +31,7 @@ export const stylesRoute = { content: <GlobalStylesUIWrapper />, sidebar: <SidebarNavigationScreenGlobalStyles backPath="/" />, preview: <Editor />, - mobile: <GlobalStylesUIWrapper />, + mobile: <MobileGlobalStylesUI />, }, widths: { content: 380, From e18605f1909873edd20e977a91194f92ef56d707 Mon Sep 17 00:00:00 2001 From: tellthemachines <tellthemachines@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:23:30 +1100 Subject: [PATCH 1855/1908] Update style book headings to new design (#67546) Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> --- .../src/components/style-book/constants.ts | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/packages/edit-site/src/components/style-book/constants.ts b/packages/edit-site/src/components/style-book/constants.ts index 7b13e3d4ef7f60..0cbbaec07086db 100644 --- a/packages/edit-site/src/components/style-book/constants.ts +++ b/packages/edit-site/src/components/style-book/constants.ts @@ -216,27 +216,25 @@ export const STYLE_BOOK_IFRAME_STYLES = ` } .edit-site-style-book__duotone-example > div:not(:first-child) { height: 20px; - border: 1px solid #ddd; + border: 1px solid color-mix( in srgb, currentColor 10%, transparent ); } .edit-site-style-book__color-example { - height: 52px; - border: 1px solid #ddd; - } - - .edit-site-style-book__examples.is-wide .edit-site-style-book__example { - flex-direction: row; + height: 32px; + border: 1px solid color-mix( in srgb, currentColor 10%, transparent ); } .edit-site-style-book__subcategory-title, .edit-site-style-book__example-title { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; - font-size: 11px; - font-weight: 500; + font-size: 13px; + font-weight: normal; line-height: normal; margin: 0; text-align: left; - text-transform: uppercase; + padding-top: 8px; + border-top: 1px solid color-mix( in srgb, currentColor 10%, transparent ); + color: color-mix( in srgb, currentColor 60%, transparent ); } .edit-site-style-book__subcategory-title { @@ -246,18 +244,9 @@ export const STYLE_BOOK_IFRAME_STYLES = ` padding-bottom: 8px; } - .edit-site-style-book__examples.is-wide .edit-site-style-book__example-title { - text-align: right; - width: 120px; - } - .edit-site-style-book__example-preview { width: 100%; } - - .is-wide .edit-site-style-book__example-preview { - width: calc(100% - 120px); - } .edit-site-style-book__example-preview .block-editor-block-list__insertion-point, .edit-site-style-book__example-preview .block-list-appender { From e8a7463ac0664c860487d30bfb04a435d63c8e4a Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Thu, 5 Dec 2024 08:47:22 +0400 Subject: [PATCH 1856/1908] Block Editor: Reduce the 'isZoomOut' selector calls in the block toolbar (#67594) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- .../src/components/block-toolbar/index.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 63b2f6ad7f9a03..0e39f4d531c87b 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -124,6 +124,8 @@ export function PrivateBlockToolbar( { ( id ) => getTemplateLock( id ) === 'contentOnly' ); + const _isZoomOut = isZoomOut(); + return { blockClientId: selectedBlockClientId, blockClientIds: selectedBlockClientIds, @@ -132,7 +134,7 @@ export function PrivateBlockToolbar( { shouldShowVisualToolbar: isValid && isVisual, toolbarKey: `${ selectedBlockClientId }${ parentClientId }`, showParentSelector: - ! isZoomOut() && + ! _isZoomOut && parentBlockType && getBlockEditingMode( parentClientId ) !== 'disabled' && hasBlockSupport( @@ -144,11 +146,11 @@ export function PrivateBlockToolbar( { isUsingBindings: _isUsingBindings, hasParentPattern: _hasParentPattern, hasContentOnlyLocking: _hasTemplateLock, - showShuffleButton: isZoomOut(), - showSlots: ! isZoomOut(), - showGroupButtons: ! isZoomOut(), - showLockButtons: ! isZoomOut(), - showSwitchSectionStyleButton: isZoomOut(), + showShuffleButton: _isZoomOut, + showSlots: ! _isZoomOut, + showGroupButtons: ! _isZoomOut, + showLockButtons: ! _isZoomOut, + showSwitchSectionStyleButton: _isZoomOut, hasFixedToolbar: getSettings().hasFixedToolbar, isNavigationMode: _isNavigationMode(), }; From 600218e1397aa813492bc2447045eb62baee7462 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Thu, 5 Dec 2024 05:41:51 +0000 Subject: [PATCH 1857/1908] Fix: Write Mode mode persists as enabled in widget editor. (#67587) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- .../src/components/sidebar-block-editor/index.js | 1 + .../src/components/widget-areas-block-editor-provider/index.js | 1 + 2 files changed, 2 insertions(+) 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 d3c78a3d6d012a..be132e9cedd82e 100644 --- a/packages/customize-widgets/src/components/sidebar-block-editor/index.js +++ b/packages/customize-widgets/src/components/sidebar-block-editor/index.js @@ -87,6 +87,7 @@ export default function SidebarBlockEditor( { mediaUpload: mediaUploadBlockEditor, hasFixedToolbar: isFixedToolbarActive || ! isMediumViewport, keepCaretInsideBlock, + editorTool: 'edit', __unstableHasCustomAppender: true, }; }, [ diff --git a/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js b/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js index af844fe9da4fe9..751931d858da8d 100644 --- a/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js +++ b/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js @@ -94,6 +94,7 @@ export default function WidgetAreasBlockEditorProvider( { __experimentalSetIsInserterOpened: setIsInserterOpened, pageOnFront, pageForPosts, + editorTool: 'edit', }; }, [ hasUploadPermissions, From e44e1109b8968ae1e58144d1671f9788a58e75cd Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:06:53 +0200 Subject: [PATCH 1858/1908] Storybook: Remove unnecessary feature flags (#67576) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- storybook/main.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/storybook/main.js b/storybook/main.js index e482ee23c2e5fc..66aed2f00a2fb9 100644 --- a/storybook/main.js +++ b/storybook/main.js @@ -60,11 +60,6 @@ module.exports = { name: '@storybook/react-webpack5', options: {}, }, - features: { - babelModeV7: true, - emotionAlias: false, - storyStoreV7: true, - }, docs: { autodocs: true, }, From e6f7b4f9903d4a2159cf6e70209d460fc3dd8b0e Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:07:12 +0200 Subject: [PATCH 1859/1908] Storybook: Use manager-api instead of addons package (#67578) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- storybook/manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storybook/manager.js b/storybook/manager.js index c63f15efe11d02..d519de312737a9 100644 --- a/storybook/manager.js +++ b/storybook/manager.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { addons } from '@storybook/addons'; +import { addons } from '@storybook/manager-api'; /** * Internal dependencies From 09b289731b20e665e6102f2a788501ff24010845 Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Thu, 5 Dec 2024 10:43:23 +0100 Subject: [PATCH 1860/1908] improve documentation for fields package (#67580) --- packages/fields/README.md | 56 +++++++------------ packages/fields/src/actions/delete-post.tsx | 3 + .../fields/src/actions/duplicate-pattern.tsx | 3 + .../src/actions/duplicate-post.native.tsx | 3 - .../fields/src/actions/duplicate-post.tsx | 9 ++- .../src/actions/duplicate-template-part.tsx | 4 +- .../src/actions/export-pattern.native.tsx | 3 - .../fields/src/actions/export-pattern.tsx | 3 + packages/fields/src/actions/index.ts | 3 - .../src/actions/permanently-delete-post.tsx | 3 + packages/fields/src/actions/rename-post.tsx | 3 + .../src/actions/reorder-page.native.tsx | 3 - packages/fields/src/actions/reorder-page.tsx | 3 + packages/fields/src/actions/reset-post.tsx | 3 + packages/fields/src/actions/restore-post.tsx | 3 + packages/fields/src/actions/trash-post.tsx | 3 + .../src/actions/view-post-revisions.tsx | 3 + packages/fields/src/actions/view-post.tsx | 3 + .../fields/src/fields/featured-image/index.ts | 3 + packages/fields/src/fields/order/index.ts | 3 + packages/fields/src/fields/parent/index.ts | 2 +- packages/fields/src/fields/password/index.tsx | 2 +- packages/fields/src/fields/slug/index.ts | 3 + packages/fields/src/fields/template/index.ts | 4 +- packages/fields/src/fields/title/index.ts | 3 + packages/fields/src/index.native.ts | 2 - 26 files changed, 79 insertions(+), 57 deletions(-) delete mode 100644 packages/fields/src/actions/duplicate-post.native.tsx delete mode 100644 packages/fields/src/actions/export-pattern.native.tsx delete mode 100644 packages/fields/src/actions/reorder-page.native.tsx diff --git a/packages/fields/README.md b/packages/fields/README.md index 2fc512b9432645..144982361be252 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -41,55 +41,43 @@ Date field for BasePost. ### deletePost -Undocumented declaration. +Delete action for Templates, Patterns and Template Parts. ### duplicatePattern -Undocumented declaration. +Duplicate action for Pattern. ### duplicatePost -Undocumented declaration. - -### duplicatePostNative - -Undocumented declaration. +Duplicate action for BasePost. ### duplicateTemplatePart -This action is used to duplicate a template part. - -_Type_ - -- `Action< TemplatePart >` +Duplicate action for TemplatePart. ### exportPattern -Undocumented declaration. - -### exportPatternNative - -Undocumented declaration. +Export action as JSON for Pattern. ### featuredImageField -Undocumented declaration. +Featured Image field for BasePost. ### orderField -Undocumented declaration. +Order field for BasePost. ### parentField -This field is used to display the post parent. +Parent field for BasePost. ### passwordField -This field is used to display the post password. +Password field for BasePost. ### permanentlyDeletePost -Undocumented declaration. +Delete action for PostWithPermissions. ### PostType @@ -97,27 +85,23 @@ Undocumented declaration. ### renamePost -Undocumented declaration. +Rename action for PostWithPermissions. ### reorderPage -Undocumented declaration. - -### reorderPageNative - -Undocumented declaration. +Reorder action for BasePost. ### resetPost -Undocumented declaration. +Reset action for Template and TemplatePart. ### restorePost -Undocumented declaration. +Restore action for PostWithPermissions. ### slugField -Undocumented declaration. +Slug field for BasePost. ### statusField @@ -125,23 +109,23 @@ Status field for BasePost. ### templateField -Undocumented declaration. +Template field for BasePost. ### titleField -Undocumented declaration. +Title field for BasePost. ### trashPost -Undocumented declaration. +Trash action for PostWithPermissions. ### viewPost -Undocumented declaration. +View post action for BasePost. ### viewPostRevisions -Undocumented declaration. +View post revisions action for Post. <!-- END TOKEN(Autogenerated API docs) --> diff --git a/packages/fields/src/actions/delete-post.tsx b/packages/fields/src/actions/delete-post.tsx index d3a469d7f83ab4..4a94796b6f0bdf 100644 --- a/packages/fields/src/actions/delete-post.tsx +++ b/packages/fields/src/actions/delete-post.tsx @@ -203,4 +203,7 @@ const deletePostAction: Action< Template | TemplatePart | Pattern > = { }, }; +/** + * Delete action for Templates, Patterns and Template Parts. + */ export default deletePostAction; diff --git a/packages/fields/src/actions/duplicate-pattern.tsx b/packages/fields/src/actions/duplicate-pattern.tsx index bf2820f951dbad..274f57b0fe19dc 100644 --- a/packages/fields/src/actions/duplicate-pattern.tsx +++ b/packages/fields/src/actions/duplicate-pattern.tsx @@ -37,4 +37,7 @@ const duplicatePattern: Action< Pattern > = { }, }; +/** + * Duplicate action for Pattern. + */ export default duplicatePattern; diff --git a/packages/fields/src/actions/duplicate-post.native.tsx b/packages/fields/src/actions/duplicate-post.native.tsx deleted file mode 100644 index 5468aa649abbd4..00000000000000 --- a/packages/fields/src/actions/duplicate-post.native.tsx +++ /dev/null @@ -1,3 +0,0 @@ -const duplicatePost = undefined; - -export default duplicatePost; diff --git a/packages/fields/src/actions/duplicate-post.tsx b/packages/fields/src/actions/duplicate-post.tsx index fd7e0ae9de4ad1..5f079b5132c600 100644 --- a/packages/fields/src/actions/duplicate-post.tsx +++ b/packages/fields/src/actions/duplicate-post.tsx @@ -37,8 +37,8 @@ const duplicatePost: Action< BasePost > = { const [ item, setItem ] = useState< BasePost >( { ...items[ 0 ], title: sprintf( - /* translators: %s: Existing template title */ - _x( '%s (Copy)', 'template' ), + /* translators: %s: Existing post title */ + _x( '%s (Copy)', 'post' ), getItemTitle( items[ 0 ] ) ), } ); @@ -104,7 +104,7 @@ const duplicatePost: Action< BasePost > = { createSuccessNotice( sprintf( - // translators: %s: Title of the created post or template, e.g: "Hello world". + // translators: %s: Title of the created post, e.g: "Hello world". __( '"%s" successfully created.' ), decodeEntities( newItem.title?.rendered || item.title ) ), @@ -171,4 +171,7 @@ const duplicatePost: Action< BasePost > = { }, }; +/** + * Duplicate action for BasePost. + */ export default duplicatePost; diff --git a/packages/fields/src/actions/duplicate-template-part.tsx b/packages/fields/src/actions/duplicate-template-part.tsx index 44fcbad21f0733..795e40638a47a7 100644 --- a/packages/fields/src/actions/duplicate-template-part.tsx +++ b/packages/fields/src/actions/duplicate-template-part.tsx @@ -68,5 +68,7 @@ const duplicateTemplatePart: Action< TemplatePart > = { ); }, }; - +/** + * Duplicate action for TemplatePart. + */ export default duplicateTemplatePart; diff --git a/packages/fields/src/actions/export-pattern.native.tsx b/packages/fields/src/actions/export-pattern.native.tsx deleted file mode 100644 index c58cffcbd79e89..00000000000000 --- a/packages/fields/src/actions/export-pattern.native.tsx +++ /dev/null @@ -1,3 +0,0 @@ -const exportPattern = undefined; - -export default exportPattern; diff --git a/packages/fields/src/actions/export-pattern.tsx b/packages/fields/src/actions/export-pattern.tsx index b6be83eeda84b4..4a041e6ac73c3f 100644 --- a/packages/fields/src/actions/export-pattern.tsx +++ b/packages/fields/src/actions/export-pattern.tsx @@ -73,4 +73,7 @@ const exportPattern: Action< Pattern > = { }, }; +/** + * Export action as JSON for Pattern. + */ export default exportPattern; diff --git a/packages/fields/src/actions/index.ts b/packages/fields/src/actions/index.ts index fc662206775316..cede3f1b59d1b3 100644 --- a/packages/fields/src/actions/index.ts +++ b/packages/fields/src/actions/index.ts @@ -1,13 +1,10 @@ export { default as viewPost } from './view-post'; export { default as reorderPage } from './reorder-page'; -export { default as reorderPageNative } from './reorder-page.native'; export { default as duplicatePost } from './duplicate-post'; -export { default as duplicatePostNative } from './duplicate-post.native'; export { default as renamePost } from './rename-post'; export { default as resetPost } from './reset-post'; export { default as duplicatePattern } from './duplicate-pattern'; export { default as exportPattern } from './export-pattern'; -export { default as exportPatternNative } from './export-pattern.native'; export { default as viewPostRevisions } from './view-post-revisions'; export { default as permanentlyDeletePost } from './permanently-delete-post'; export { default as restorePost } from './restore-post'; diff --git a/packages/fields/src/actions/permanently-delete-post.tsx b/packages/fields/src/actions/permanently-delete-post.tsx index afbb84ae12c74c..688ba5b9918df8 100644 --- a/packages/fields/src/actions/permanently-delete-post.tsx +++ b/packages/fields/src/actions/permanently-delete-post.tsx @@ -115,4 +115,7 @@ const permanentlyDeletePost: Action< PostWithPermissions > = { }, }; +/** + * Delete action for PostWithPermissions. + */ export default permanentlyDeletePost; diff --git a/packages/fields/src/actions/rename-post.tsx b/packages/fields/src/actions/rename-post.tsx index 5203328b46de53..be0e69db26cd80 100644 --- a/packages/fields/src/actions/rename-post.tsx +++ b/packages/fields/src/actions/rename-post.tsx @@ -139,4 +139,7 @@ const renamePost: Action< PostWithPermissions > = { }, }; +/** + * Rename action for PostWithPermissions. + */ export default renamePost; diff --git a/packages/fields/src/actions/reorder-page.native.tsx b/packages/fields/src/actions/reorder-page.native.tsx deleted file mode 100644 index 61e4733b6c6bd9..00000000000000 --- a/packages/fields/src/actions/reorder-page.native.tsx +++ /dev/null @@ -1,3 +0,0 @@ -const reorderPage = undefined; - -export default reorderPage; diff --git a/packages/fields/src/actions/reorder-page.tsx b/packages/fields/src/actions/reorder-page.tsx index 1820884d8d8c73..cffc4b924c0a5d 100644 --- a/packages/fields/src/actions/reorder-page.tsx +++ b/packages/fields/src/actions/reorder-page.tsx @@ -122,4 +122,7 @@ const reorderPage: Action< BasePost > = { RenderModal: ReorderModal, }; +/** + * Reorder action for BasePost. + */ export default reorderPage; diff --git a/packages/fields/src/actions/reset-post.tsx b/packages/fields/src/actions/reset-post.tsx index 3e6b2e29b68b65..d8ac5730d6a166 100644 --- a/packages/fields/src/actions/reset-post.tsx +++ b/packages/fields/src/actions/reset-post.tsx @@ -292,4 +292,7 @@ const resetPostAction: Action< Template | TemplatePart > = { }, }; +/** + * Reset action for Template and TemplatePart. + */ export default resetPostAction; diff --git a/packages/fields/src/actions/restore-post.tsx b/packages/fields/src/actions/restore-post.tsx index 874eca91fee113..6ea493a619ae80 100644 --- a/packages/fields/src/actions/restore-post.tsx +++ b/packages/fields/src/actions/restore-post.tsx @@ -131,4 +131,7 @@ const restorePost: Action< PostWithPermissions > = { }, }; +/** + * Restore action for PostWithPermissions. + */ export default restorePost; diff --git a/packages/fields/src/actions/trash-post.tsx b/packages/fields/src/actions/trash-post.tsx index befbfb0ee7ffba..c0227996b5e866 100644 --- a/packages/fields/src/actions/trash-post.tsx +++ b/packages/fields/src/actions/trash-post.tsx @@ -195,4 +195,7 @@ const trashPost: Action< PostWithPermissions > = { }, }; +/** + * Trash action for PostWithPermissions. + */ export default trashPost; diff --git a/packages/fields/src/actions/view-post-revisions.tsx b/packages/fields/src/actions/view-post-revisions.tsx index 75d4edfd73e18d..40eecde5771311 100644 --- a/packages/fields/src/actions/view-post-revisions.tsx +++ b/packages/fields/src/actions/view-post-revisions.tsx @@ -44,4 +44,7 @@ const viewPostRevisions: Action< Post > = { }, }; +/** + * View post revisions action for Post. + */ export default viewPostRevisions; diff --git a/packages/fields/src/actions/view-post.tsx b/packages/fields/src/actions/view-post.tsx index 187faffafb5d3c..7517ab1f37cb33 100644 --- a/packages/fields/src/actions/view-post.tsx +++ b/packages/fields/src/actions/view-post.tsx @@ -27,4 +27,7 @@ const viewPost: Action< BasePost > = { }, }; +/** + * View post action for BasePost. + */ export default viewPost; diff --git a/packages/fields/src/fields/featured-image/index.ts b/packages/fields/src/fields/featured-image/index.ts index 62d7e8240aded0..d6f22176fc6704 100644 --- a/packages/fields/src/fields/featured-image/index.ts +++ b/packages/fields/src/fields/featured-image/index.ts @@ -20,4 +20,7 @@ const featuredImageField: Field< BasePost > = { enableSorting: false, }; +/** + * Featured Image field for BasePost. + */ export default featuredImageField; diff --git a/packages/fields/src/fields/order/index.ts b/packages/fields/src/fields/order/index.ts index 984a94c6427fc6..121fcb9d0f3bdc 100644 --- a/packages/fields/src/fields/order/index.ts +++ b/packages/fields/src/fields/order/index.ts @@ -16,4 +16,7 @@ const orderField: Field< BasePost > = { description: __( 'Determines the order of pages.' ), }; +/** + * Order field for BasePost. + */ export default orderField; diff --git a/packages/fields/src/fields/parent/index.ts b/packages/fields/src/fields/parent/index.ts index 8b833e1d9369df..f974608710bf7e 100644 --- a/packages/fields/src/fields/parent/index.ts +++ b/packages/fields/src/fields/parent/index.ts @@ -21,6 +21,6 @@ const parentField: Field< BasePost > = { }; /** - * This field is used to display the post parent. + * Parent field for BasePost. */ export default parentField; diff --git a/packages/fields/src/fields/password/index.tsx b/packages/fields/src/fields/password/index.tsx index dacd0d7435998a..3d45641b0efd0e 100644 --- a/packages/fields/src/fields/password/index.tsx +++ b/packages/fields/src/fields/password/index.tsx @@ -19,6 +19,6 @@ const passwordField: Field< BasePost > = { }; /** - * This field is used to display the post password. + * Password field for BasePost. */ export default passwordField; diff --git a/packages/fields/src/fields/slug/index.ts b/packages/fields/src/fields/slug/index.ts index c43fcc679622ac..7311b1d10a66f6 100644 --- a/packages/fields/src/fields/slug/index.ts +++ b/packages/fields/src/fields/slug/index.ts @@ -19,4 +19,7 @@ const slugField: Field< BasePost > = { render: SlugView, }; +/** + * Slug field for BasePost. + */ export default slugField; diff --git a/packages/fields/src/fields/template/index.ts b/packages/fields/src/fields/template/index.ts index 7315b4ba349b1c..c419adedb537dd 100644 --- a/packages/fields/src/fields/template/index.ts +++ b/packages/fields/src/fields/template/index.ts @@ -14,9 +14,11 @@ const templateField: Field< BasePost > = { id: 'template', type: 'text', label: __( 'Template' ), - getValue: ( { item } ) => item.template, Edit: TemplateEdit, enableSorting: false, }; +/** + * Template field for BasePost. + */ export default templateField; diff --git a/packages/fields/src/fields/title/index.ts b/packages/fields/src/fields/title/index.ts index d8e6f25276d6b8..111980a1ca2b0a 100644 --- a/packages/fields/src/fields/title/index.ts +++ b/packages/fields/src/fields/title/index.ts @@ -21,4 +21,7 @@ const titleField: Field< BasePost > = { enableHiding: false, }; +/** + * Title field for BasePost. + */ export default titleField; diff --git a/packages/fields/src/index.native.ts b/packages/fields/src/index.native.ts index 33a26e3c2e6e27..e69de29bb2d1d6 100644 --- a/packages/fields/src/index.native.ts +++ b/packages/fields/src/index.native.ts @@ -1,2 +0,0 @@ -export * from './actions/duplicate-post.native'; -export * from './actions/reorder-page.native'; From 0b3a191518f46ff52d46b2a921fbf5ebd0f80b77 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Thu, 5 Dec 2024 09:48:04 +0000 Subject: [PATCH 1861/1908] Fix: Remove unused test code on tools panel. (#67589) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../components/src/tools-panel/test/index.tsx | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/packages/components/src/tools-panel/test/index.tsx b/packages/components/src/tools-panel/test/index.tsx index 8d2c4f17a8b170..68cf72233121e0 100644 --- a/packages/components/src/tools-panel/test/index.tsx +++ b/packages/components/src/tools-panel/test/index.tsx @@ -154,7 +154,6 @@ const renderWrappedItemInPanel = () => { const renderPanel = () => { return render( <ToolsPanel { ...defaultProps }> - { false && <div>Hidden</div> } <ToolsPanelItem { ...controlProps }> <div>Example control</div> </ToolsPanelItem> @@ -236,22 +235,6 @@ describe( 'ToolsPanel', () => { it( 'should not render panel menu when there are no panel items', () => { render( <ToolsPanel { ...defaultProps }> - { false && ( - <ToolsPanelItem - label="Not rendered 1" - hasValue={ () => false } - > - Should not show - </ToolsPanelItem> - ) } - { false && ( - <ToolsPanelItem - label="Not rendered 2" - hasValue={ () => false } - > - Not shown either - </ToolsPanelItem> - ) } <span>Visible but insignificant</span> </ToolsPanel> ); From 094bd3a434f84a483885518965770484813f5e77 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:02:49 +0100 Subject: [PATCH 1862/1908] Drag and drop: fix firefox compat logic (#67439) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- .../block-list/use-block-props/index.js | 6 +- .../use-firefox-draggable-compatibility.js | 70 +++++++++++++++++-- 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index 4696149dc38751..554adccdc22c9d 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -104,8 +104,6 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { canMove, } = useContext( PrivateBlockContext ); - const canDrag = canMove && ! hasChildSelected; - // translators: %s: Type of block (i.e. Text, Image etc) const blockLabel = sprintf( __( 'Block: %s' ), blockTitle ); const htmlSuffix = mode === 'html' && ! __unstableIsHtml ? '-visual' : ''; @@ -125,7 +123,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { isEnabled: isSectionBlock, } ), useScrollIntoView( { isSelected } ), - canDrag ? ffDragRef : undefined, + canMove ? ffDragRef : undefined, ] ); const blockEditContext = useBlockEditContext(); @@ -158,7 +156,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { return { tabIndex: blockEditingMode === 'disabled' ? -1 : 0, - draggable: canDrag ? true : undefined, + draggable: canMove && ! hasChildSelected ? true : undefined, ...wrapperProps, ...props, ref: mergedRefs, diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-firefox-draggable-compatibility.js b/packages/block-editor/src/components/block-list/use-block-props/use-firefox-draggable-compatibility.js index 5fa07fb9be6040..a53983b95954ad 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-firefox-draggable-compatibility.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-firefox-draggable-compatibility.js @@ -3,6 +3,68 @@ */ import { useRefEffect } from '@wordpress/compose'; +const nodesByDocument = new Map(); + +function add( doc, node ) { + let set = nodesByDocument.get( doc ); + if ( ! set ) { + set = new Set(); + nodesByDocument.set( doc, set ); + doc.addEventListener( 'pointerdown', down ); + } + set.add( node ); +} + +function remove( doc, node ) { + const set = nodesByDocument.get( doc ); + if ( set ) { + set.delete( node ); + restore( node ); + if ( set.size === 0 ) { + nodesByDocument.delete( doc ); + doc.removeEventListener( 'pointerdown', down ); + } + } +} + +function restore( node ) { + const prevDraggable = node.getAttribute( 'data-draggable' ); + if ( prevDraggable ) { + node.removeAttribute( 'data-draggable' ); + // Only restore if `draggable` is still removed. It could have been + // changed by React in the meantime. + if ( prevDraggable === 'true' && ! node.getAttribute( 'draggable' ) ) { + node.setAttribute( 'draggable', 'true' ); + } + } +} + +function down( event ) { + const { target } = event; + const { ownerDocument, isContentEditable } = target; + const nodes = nodesByDocument.get( ownerDocument ); + + if ( isContentEditable ) { + // Whenever an editable element is clicked, check which draggable + // blocks contain this element, and temporarily disable draggability. + for ( const node of nodes ) { + if ( + node.getAttribute( 'draggable' ) === 'true' && + node.contains( target ) + ) { + node.removeAttribute( 'draggable' ); + node.setAttribute( 'data-draggable', 'true' ); + } + } + } else { + // Whenever a non-editable element is clicked, re-enable draggability + // for any blocks that were previously disabled. + for ( const node of nodes ) { + restore( node ); + } + } +} + /** * In Firefox, the `draggable` and `contenteditable` attributes don't play well * together. When `contenteditable` is within a `draggable` element, selection @@ -13,13 +75,9 @@ import { useRefEffect } from '@wordpress/compose'; */ export function useFirefoxDraggableCompatibility() { return useRefEffect( ( node ) => { - function onDown( event ) { - node.draggable = ! event.target.isContentEditable; - } - const { ownerDocument } = node; - ownerDocument.addEventListener( 'pointerdown', onDown ); + add( node.ownerDocument, node ); return () => { - ownerDocument.removeEventListener( 'pointerdown', onDown ); + remove( node.ownerDocument, node ); }; }, [] ); } From 3ea3ba269fdeeb4e7c67a79595789e1205bed042 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Thu, 5 Dec 2024 12:04:57 +0200 Subject: [PATCH 1863/1908] DataViews: Create a single component for rendering the actions list (#67558) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- .../dataviews-item-actions/index.tsx | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-item-actions/index.tsx b/packages/dataviews/src/components/dataviews-item-actions/index.tsx index b5eaac11bcd8d0..c5e1cb09adf15f 100644 --- a/packages/dataviews/src/components/dataviews-item-actions/index.tsx +++ b/packages/dataviews/src/components/dataviews-item-actions/index.tsx @@ -65,6 +65,12 @@ interface PrimaryActionsProps< Item > { actions: Action< Item >[]; registry: ReturnType< typeof useRegistry >; } +interface ActionsListProps< Item > { + item: Item; + actions: Action< Item >[]; + registry: ReturnType< typeof useRegistry >; + ActionTrigger: ( props: ActionTriggerProps< Item > ) => ReactElement; +} function ButtonTrigger< Item >( { action, @@ -160,28 +166,12 @@ export function ActionsMenuGroup< Item >( { const registry = useRegistry(); return ( <Menu.Group> - { actions.map( ( action ) => { - if ( 'RenderModal' in action ) { - return ( - <ActionWithModal - key={ action.id } - action={ action } - items={ [ item ] } - ActionTrigger={ MenuItemTrigger } - /> - ); - } - return ( - <MenuItemTrigger - key={ action.id } - action={ action } - onClick={ () => { - action.callback( [ item ], { registry } ); - } } - items={ [ item ] } - /> - ); - } ) } + <ActionsList + actions={ actions } + item={ item } + registry={ registry } + ActionTrigger={ MenuItemTrigger } + /> </Menu.Group> ); } @@ -286,7 +276,22 @@ function PrimaryActions< Item >( { if ( ! Array.isArray( actions ) || actions.length === 0 ) { return null; } + return ( + <ActionsList + actions={ actions } + item={ item } + registry={ registry } + ActionTrigger={ ButtonTrigger } + /> + ); +} +function ActionsList< Item >( { + item, + actions, + registry, + ActionTrigger, +}: ActionsListProps< Item > ) { return actions.map( ( action ) => { if ( 'RenderModal' in action ) { return ( @@ -294,12 +299,12 @@ function PrimaryActions< Item >( { key={ action.id } action={ action } items={ [ item ] } - ActionTrigger={ ButtonTrigger } + ActionTrigger={ ActionTrigger } /> ); } return ( - <ButtonTrigger + <ActionTrigger key={ action.id } action={ action } onClick={ () => { From eace185db0801658b6267c764e038fa4ac85c4c1 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Thu, 5 Dec 2024 21:52:21 +1100 Subject: [PATCH 1864/1908] Global styles: controls in grid should match between sidebar panel and editor (#67602) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- packages/edit-site/src/components/global-styles/style.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss index 57f51f4b8f007c..4674b5e5fc3ca4 100644 --- a/packages/edit-site/src/components/global-styles/style.scss +++ b/packages/edit-site/src/components/global-styles/style.scss @@ -211,6 +211,10 @@ flex-direction: column; } +.edit-site-global-styles-sidebar__navigator-screen .single-column { + grid-column: span 1; +} + .edit-site-global-styles-screen-root.edit-site-global-styles-screen-root, .edit-site-global-styles-screen-style-variations.edit-site-global-styles-screen-style-variations { background: unset; From 4a5b519f1057c922a2349c7b7e89e07c0ae84bbd Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Thu, 5 Dec 2024 13:18:59 +0200 Subject: [PATCH 1865/1908] DataViews: Move template and pattern title fields (#67449) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../src/components/dataviews/style.scss | 10 +++ .../src/components/page-patterns/fields.js | 61 +------------------ .../src/components/page-patterns/index.js | 22 ++++++- .../src/components/page-patterns/style.scss | 28 --------- .../src/components/page-templates/fields.js | 19 +----- .../src/components/page-templates/index.js | 14 ++--- .../src/components/post-list/style.scss | 36 ----------- .../src/dataviews/store/private-actions.ts | 31 +++++++--- packages/fields/README.md | 14 ++++- packages/fields/src/fields/index.ts | 3 + .../fields/src/fields/page-title/index.ts | 28 +++++++++ .../fields/src/fields/page-title/style.scss | 10 +++ .../fields/src/fields/page-title/view.tsx | 38 ++++++++++++ .../fields/src/fields/pattern-title/index.ts | 28 +++++++++ .../src/fields/pattern-title/style.scss | 3 + .../fields/src/fields/pattern-title/view.tsx | 32 ++++++++++ .../fields/src/fields/template-title/index.ts | 28 +++++++++ packages/fields/src/fields/title/index.ts | 11 ++-- packages/fields/src/fields/title/style.scss | 8 +++ .../fields/src/fields/title/title-view.tsx | 61 ------------------- packages/fields/src/fields/title/view.tsx | 43 +++++++++++++ packages/fields/src/style.scss | 3 + .../specs/site-editor/browser-history.spec.js | 4 +- .../site-editor/new-templates-list.spec.js | 12 +--- .../site-editor/template-registration.spec.js | 4 +- test/performance/specs/site-editor.spec.js | 4 +- 26 files changed, 317 insertions(+), 238 deletions(-) create mode 100644 packages/fields/src/fields/page-title/index.ts create mode 100644 packages/fields/src/fields/page-title/style.scss create mode 100644 packages/fields/src/fields/page-title/view.tsx create mode 100644 packages/fields/src/fields/pattern-title/index.ts create mode 100644 packages/fields/src/fields/pattern-title/style.scss create mode 100644 packages/fields/src/fields/pattern-title/view.tsx create mode 100644 packages/fields/src/fields/template-title/index.ts create mode 100644 packages/fields/src/fields/title/style.scss delete mode 100644 packages/fields/src/fields/title/title-view.tsx create mode 100644 packages/fields/src/fields/title/view.tsx diff --git a/packages/dataviews/src/components/dataviews/style.scss b/packages/dataviews/src/components/dataviews/style.scss index bd75a1ff9e2a18..a357679bef1eb9 100644 --- a/packages/dataviews/src/components/dataviews/style.scss +++ b/packages/dataviews/src/components/dataviews/style.scss @@ -60,6 +60,16 @@ color: var(--wp-admin-theme-color); } } + + &.dataviews-view-grid__primary-field--clickable span, + > .dataviews-view-table__cell-content--clickable span { + color: $gray-900; + + &:hover { + color: var(--wp-admin-theme-color); + } + @include link-reset(); + } } .dataviews-view-list__primary-field--clickable, diff --git a/packages/edit-site/src/components/page-patterns/fields.js b/packages/edit-site/src/components/page-patterns/fields.js index 60e37844b2edb1..f202664389f0ff 100644 --- a/packages/edit-site/src/components/page-patterns/fields.js +++ b/packages/edit-site/src/components/page-patterns/fields.js @@ -6,21 +6,15 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { - __experimentalHStack as HStack, - Button, - Tooltip, - FlexBlock, -} from '@wordpress/components'; +import { __experimentalHStack as HStack } from '@wordpress/components'; import { __, _x } from '@wordpress/i18n'; import { useState, useMemo, useId } from '@wordpress/element'; import { BlockPreview, privateApis as blockEditorPrivateApis, } from '@wordpress/block-editor'; -import { Icon, lockSmall } from '@wordpress/icons'; +import { Icon } from '@wordpress/icons'; import { parse } from '@wordpress/blocks'; -import { decodeEntities } from '@wordpress/html-entities'; import { privateApis as routerPrivateApis } from '@wordpress/router'; /** @@ -112,57 +106,6 @@ export const previewField = { enableSorting: false, }; -function TitleField( { item } ) { - const isUserPattern = item.type === PATTERN_TYPES.user; - const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE; - const { onClick } = useLink( - `/${ item.type }/${ - isUserPattern || isTemplatePart ? item.id : item.name - }?canvas=edit` - ); - const title = decodeEntities( defaultGetTitle( item ) ); - return ( - <HStack alignment="center" justify="flex-start" spacing={ 2 }> - <FlexBlock className="edit-site-patterns__pattern-title"> - { item.type === PATTERN_TYPES.theme ? ( - title - ) : ( - <Button - __next40pxDefaultSize - variant="link" - onClick={ onClick } - // Required for the grid's roving tab index system. - // See https://github.com/WordPress/gutenberg/pull/51898#discussion_r1243399243. - tabIndex="-1" - > - { title } - </Button> - ) } - </FlexBlock> - { item.type === PATTERN_TYPES.theme && ( - <Tooltip - placement="top" - text={ __( 'This pattern cannot be edited.' ) } - > - <Icon - className="edit-site-patterns__pattern-lock-icon" - icon={ lockSmall } - size={ 24 } - /> - </Tooltip> - ) } - </HStack> - ); -} - -export const titleField = { - label: __( 'Title' ), - id: 'title', - getValue: ( { item } ) => item.title?.raw || item.title, - render: TitleField, - enableHiding: false, -}; - const SYNC_FILTERS = [ { value: PATTERN_SYNC_TYPES.full, diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index b6753334887573..9a4dedca098030 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -9,6 +9,7 @@ import { usePrevious } from '@wordpress/compose'; import { useEntityRecords } from '@wordpress/core-data'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { patternTitleField } from '@wordpress/fields'; /** * Internal dependencies @@ -29,13 +30,12 @@ import { useEditPostAction } from '../dataviews-actions'; import { patternStatusField, previewField, - titleField, templatePartAuthorField, } from './fields'; const { ExperimentalBlockEditorProvider } = unlock( blockEditorPrivateApis ); const { usePostActions } = unlock( editorPrivateApis ); -const { useLocation } = unlock( routerPrivateApis ); +const { useLocation, useHistory } = unlock( routerPrivateApis ); const EMPTY_ARRAY = []; const defaultLayouts = { @@ -74,6 +74,7 @@ export default function DataviewsPatterns() { const { query: { postType = 'wp_block', categoryId: categoryIdFromURL }, } = useLocation(); + const history = useHistory(); const categoryId = categoryIdFromURL || PATTERN_DEFAULT_CATEGORY; const [ view, setView ] = useState( DEFAULT_VIEW ); const previousCategoryId = usePrevious( categoryId ); @@ -105,7 +106,7 @@ export default function DataviewsPatterns() { }, [ records ] ); const fields = useMemo( () => { - const _fields = [ previewField, titleField ]; + const _fields = [ previewField, patternTitleField ]; if ( postType === PATTERN_TYPES.user ) { _fields.push( patternStatusField ); @@ -183,6 +184,21 @@ export default function DataviewsPatterns() { data={ dataWithPermissions || EMPTY_ARRAY } getItemId={ ( item ) => item.name ?? item.id } isLoading={ isResolving } + isItemClickable={ ( item ) => + item.type !== PATTERN_TYPES.theme + } + onClickItem={ ( item ) => { + history.navigate( + `/${ item.type }/${ + [ + PATTERN_TYPES.user, + TEMPLATE_PART_POST_TYPE, + ].includes( item.type ) + ? item.id + : item.name + }?canvas=edit` + ); + } } view={ view } onChangeView={ setView } defaultLayouts={ defaultLayouts } diff --git a/packages/edit-site/src/components/page-patterns/style.scss b/packages/edit-site/src/components/page-patterns/style.scss index d59cce420202ee..72d53c2a721afc 100644 --- a/packages/edit-site/src/components/page-patterns/style.scss +++ b/packages/edit-site/src/components/page-patterns/style.scss @@ -71,34 +71,6 @@ } } -.edit-site-patterns__pattern-title { - display: block; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - color: inherit; - - .is-link { - text-decoration: none; - color: $gray-200; - - &:hover, - &:focus { - color: $white; - } - } - - .edit-site-patterns__pattern-icon { - border-radius: $grid-unit-05; - background: var(--wp-block-synced-color); - fill: $white; - } - - .edit-site-patterns__pattern-lock-icon { - fill: currentcolor; - } -} - .edit-site-page-patterns-dataviews { .dataviews-view-grid__badge-fields { .dataviews-view-grid__field-value:has(.edit-site-patterns__field-sync-status-fully) { diff --git a/packages/edit-site/src/components/page-templates/fields.js b/packages/edit-site/src/components/page-templates/fields.js index 35d7b9714d5be1..88c20ff27ebbce 100644 --- a/packages/edit-site/src/components/page-templates/fields.js +++ b/packages/edit-site/src/components/page-templates/fields.js @@ -25,7 +25,7 @@ import { useAddedBy } from './hooks'; import usePatternSettings from '../page-patterns/use-pattern-settings'; import { unlock } from '../../lock-unlock'; -const { useLink, Link } = unlock( routerPrivateApis ); +const { useLink } = unlock( routerPrivateApis ); const { useGlobalStyle } = unlock( blockEditorPrivateApis ); function PreviewField( { item } ) { @@ -75,23 +75,6 @@ export const previewField = { enableSorting: false, }; -function TitleField( { item } ) { - return ( - <Link to={ `/${ item.type }/${ item.id }?canvas=edit` }> - { decodeEntities( item.title?.rendered ) || __( '(no title)' ) } - </Link> - ); -} - -export const titleField = { - label: __( 'Template' ), - id: 'title', - getValue: ( { item } ) => item.title?.rendered, - render: TitleField, - enableHiding: false, - enableGlobalSearch: true, -}; - export const descriptionField = { label: __( 'Description' ), id: 'description', diff --git a/packages/edit-site/src/components/page-templates/index.js b/packages/edit-site/src/components/page-templates/index.js index 828867e6f283de..934fb0be6784d7 100644 --- a/packages/edit-site/src/components/page-templates/index.js +++ b/packages/edit-site/src/components/page-templates/index.js @@ -7,6 +7,7 @@ import { privateApis as corePrivateApis } from '@wordpress/core-data'; import { DataViews, filterSortAndPaginate } from '@wordpress/dataviews'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; +import { templateTitleField } from '@wordpress/fields'; import { addQueryArgs } from '@wordpress/url'; /** @@ -23,12 +24,7 @@ import { } from '../../utils/constants'; import { unlock } from '../../lock-unlock'; import { useEditPostAction } from '../dataviews-actions'; -import { - authorField, - descriptionField, - previewField, - titleField, -} from './fields'; +import { authorField, descriptionField, previewField } from './fields'; const { usePostActions } = unlock( editorPrivateApis ); const { useHistory, useLocation } = unlock( routerPrivateApis ); @@ -172,7 +168,7 @@ export default function PageTemplates() { const fields = useMemo( () => [ previewField, - titleField, + templateTitleField, descriptionField, { ...authorField, @@ -227,6 +223,10 @@ export default function PageTemplates() { view={ view } onChangeView={ onChangeView } onChangeSelection={ onChangeSelection } + isItemClickable={ () => true } + onClickItem={ ( { id } ) => { + history.navigate( `/wp_template/${ id }?canvas=edit` ); + } } selection={ selection } defaultLayouts={ defaultLayouts } /> diff --git a/packages/edit-site/src/components/post-list/style.scss b/packages/edit-site/src/components/post-list/style.scss index 14bb11b41d4450..8ff7e31c79dd6f 100644 --- a/packages/edit-site/src/components/post-list/style.scss +++ b/packages/edit-site/src/components/post-list/style.scss @@ -65,42 +65,6 @@ } } -.edit-site-post-list__title span { - text-overflow: ellipsis; - overflow: hidden; -} - -.dataviews-view-grid__primary-field.dataviews-view-grid__primary-field--clickable -.edit-site-post-list__title -span, -.dataviews-view-table__primary-field > .dataviews-view-table__cell-content--clickable -.edit-site-post-list__title -span { - text-decoration: none; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - display: block; - flex-grow: 0; - color: $gray-900; - - &:hover { - color: var(--wp-admin-theme-color); - } - @include link-reset(); -} - -.edit-site-post-list__title-badge { - background: $gray-100; - color: $gray-800; - padding: 0 $grid-unit-05; - border-radius: $radius-small; - font-size: 12px; - font-weight: 400; - flex-shrink: 0; - line-height: $grid-unit-05 * 5; -} - .edit-site-post-list__status-icon { height: $grid-unit-30; width: $grid-unit-30; diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 754a02d317a385..2119b52756e964 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -4,12 +4,6 @@ import { store as coreStore } from '@wordpress/core-data'; import type { Action, Field } from '@wordpress/dataviews'; import { doAction } from '@wordpress/hooks'; - -/** - * Internal dependencies - */ -import { store as editorStore } from '../../store'; -import { unlock } from '../../lock-unlock'; import type { PostType } from '@wordpress/fields'; import { viewPost, @@ -35,8 +29,17 @@ import { authorField, titleField, templateField, + templateTitleField, + pageTitleField, + patternTitleField, } from '@wordpress/fields'; +/** + * Internal dependencies + */ +import { store as editorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; + export function registerEntityAction< Item >( kind: string, name: string, @@ -164,16 +167,28 @@ export const registerPostTypeSchema = postTypeConfig.supports?.thumbnail && currentTheme?.theme_supports?.[ 'post-thumbnails' ] && featuredImageField, - titleField, postTypeConfig.supports?.author && authorField, statusField, dateField, slugField, postTypeConfig.supports?.[ 'page-attributes' ] && parentField, postTypeConfig.supports?.comments && commentStatusField, - passwordField, templateField, + passwordField, ].filter( Boolean ); + if ( postTypeConfig.supports?.title ) { + let _titleField; + if ( postType === 'page' ) { + _titleField = pageTitleField; + } else if ( postType === 'wp_template' ) { + _titleField = templateTitleField; + } else if ( postType === 'wp_block' ) { + _titleField = patternTitleField; + } else { + _titleField = titleField; + } + fields.push( _titleField ); + } registry.batch( () => { actions.forEach( ( action ) => { diff --git a/packages/fields/README.md b/packages/fields/README.md index 144982361be252..9ca08991aca51f 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -67,6 +67,10 @@ Featured Image field for BasePost. Order field for BasePost. +### pageTitleField + +Title for the page entity. + ### parentField Parent field for BasePost. @@ -75,6 +79,10 @@ Parent field for BasePost. Password field for BasePost. +### patternTitleField + +Title for the pattern entity. + ### permanentlyDeletePost Delete action for PostWithPermissions. @@ -111,9 +119,13 @@ Status field for BasePost. Template field for BasePost. +### templateTitleField + +Title for the template entity. + ### titleField -Title field for BasePost. +Title for the any entity with a `title` property. For patterns, pages or templates you should use the respective field because there are some differences in the rendering, labels, etc. ### trashPost diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts index 2cdf89ee13fb02..410b0bf51a2232 100644 --- a/packages/fields/src/fields/index.ts +++ b/packages/fields/src/fields/index.ts @@ -1,5 +1,8 @@ export { default as slugField } from './slug'; export { default as titleField } from './title'; +export { default as pageTitleField } from './page-title'; +export { default as templateTitleField } from './template-title'; +export { default as patternTitleField } from './pattern-title'; export { default as orderField } from './order'; export { default as featuredImageField } from './featured-image'; export { default as templateField } from './template'; diff --git a/packages/fields/src/fields/page-title/index.ts b/packages/fields/src/fields/page-title/index.ts new file mode 100644 index 00000000000000..8bbf051f2b5839 --- /dev/null +++ b/packages/fields/src/fields/page-title/index.ts @@ -0,0 +1,28 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import { getItemTitle } from '../../actions/utils'; +import PageTitleView from './view'; + +const pageTitleField: Field< BasePost > = { + type: 'text', + id: 'title', + label: __( 'Title' ), + placeholder: __( 'No title' ), + getValue: ( { item } ) => getItemTitle( item ), + render: PageTitleView, + enableHiding: false, + enableGlobalSearch: true, +}; + +/** + * Title for the page entity. + */ +export default pageTitleField; diff --git a/packages/fields/src/fields/page-title/style.scss b/packages/fields/src/fields/page-title/style.scss new file mode 100644 index 00000000000000..def56aa466a8a1 --- /dev/null +++ b/packages/fields/src/fields/page-title/style.scss @@ -0,0 +1,10 @@ +.fields-field__page-title__badge { + background: $gray-100; + color: $gray-800; + padding: 0 $grid-unit-05; + border-radius: $radius-small; + font-size: 12px; + font-weight: 400; + flex-shrink: 0; + line-height: $grid-unit-05 * 5; +} diff --git a/packages/fields/src/fields/page-title/view.tsx b/packages/fields/src/fields/page-title/view.tsx new file mode 100644 index 00000000000000..0be4c16d5d29ae --- /dev/null +++ b/packages/fields/src/fields/page-title/view.tsx @@ -0,0 +1,38 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import type { Settings } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ +import type { CommonPost } from '../../types'; +import { BaseTitleView } from '../title/view'; + +export default function PageTitleView( { item }: { item: CommonPost } ) { + const { frontPageId, postsPageId } = useSelect( ( select ) => { + const { getEntityRecord } = select( coreStore ); + const siteSettings = getEntityRecord( + 'root', + 'site' + ) as Partial< Settings >; + return { + frontPageId: siteSettings?.page_on_front, + postsPageId: siteSettings?.page_for_posts, + }; + }, [] ); + return ( + <BaseTitleView item={ item } className="fields-field__page-title"> + { [ frontPageId, postsPageId ].includes( item.id as number ) && ( + <span className="fields-field__page-title__badge"> + { item.id === frontPageId + ? __( 'Homepage' ) + : __( 'Posts Page' ) } + </span> + ) } + </BaseTitleView> + ); +} diff --git a/packages/fields/src/fields/pattern-title/index.ts b/packages/fields/src/fields/pattern-title/index.ts new file mode 100644 index 00000000000000..a3e54eea6f28d1 --- /dev/null +++ b/packages/fields/src/fields/pattern-title/index.ts @@ -0,0 +1,28 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { Pattern } from '../../types'; +import { getItemTitle } from '../../actions/utils'; +import PatternTitleView from './view'; + +const patternTitleField: Field< Pattern > = { + type: 'text', + id: 'title', + label: __( 'Title' ), + placeholder: __( 'No title' ), + getValue: ( { item } ) => getItemTitle( item ), + render: PatternTitleView, + enableHiding: false, + enableGlobalSearch: true, +}; + +/** + * Title for the pattern entity. + */ +export default patternTitleField; diff --git a/packages/fields/src/fields/pattern-title/style.scss b/packages/fields/src/fields/pattern-title/style.scss new file mode 100644 index 00000000000000..fa4d03c850beac --- /dev/null +++ b/packages/fields/src/fields/pattern-title/style.scss @@ -0,0 +1,3 @@ +.fields-field__pattern-title span:first-child { + flex: 1; +} diff --git a/packages/fields/src/fields/pattern-title/view.tsx b/packages/fields/src/fields/pattern-title/view.tsx new file mode 100644 index 00000000000000..b59360d30e0be2 --- /dev/null +++ b/packages/fields/src/fields/pattern-title/view.tsx @@ -0,0 +1,32 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Icon, lockSmall } from '@wordpress/icons'; +import { Tooltip } from '@wordpress/components'; +// @ts-ignore +import { privateApis as patternPrivateApis } from '@wordpress/patterns'; + +/** + * Internal dependencies + */ +import type { CommonPost } from '../../types'; +import { BaseTitleView } from '../title/view'; +import { unlock } from '../../lock-unlock'; + +export const { PATTERN_TYPES } = unlock( patternPrivateApis ); + +export default function PatternTitleView( { item }: { item: CommonPost } ) { + return ( + <BaseTitleView item={ item } className="fields-field__pattern-title"> + { item.type === PATTERN_TYPES.theme && ( + <Tooltip + placement="top" + text={ __( 'This pattern cannot be edited.' ) } + > + <Icon icon={ lockSmall } size={ 24 } /> + </Tooltip> + ) } + </BaseTitleView> + ); +} diff --git a/packages/fields/src/fields/template-title/index.ts b/packages/fields/src/fields/template-title/index.ts new file mode 100644 index 00000000000000..e0d83d6ffda8f6 --- /dev/null +++ b/packages/fields/src/fields/template-title/index.ts @@ -0,0 +1,28 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { Template } from '../../types'; +import { getItemTitle } from '../../actions/utils'; +import TitleView from '../title/view'; + +const templateTitleField: Field< Template > = { + type: 'text', + label: __( 'Template' ), + placeholder: __( 'No title' ), + id: 'title', + getValue: ( { item } ) => getItemTitle( item ), + render: TitleView, + enableHiding: false, + enableGlobalSearch: true, +}; + +/** + * Title for the template entity. + */ +export default templateTitleField; diff --git a/packages/fields/src/fields/title/index.ts b/packages/fields/src/fields/title/index.ts index 111980a1ca2b0a..b4a2399526fdd9 100644 --- a/packages/fields/src/fields/title/index.ts +++ b/packages/fields/src/fields/title/index.ts @@ -7,11 +7,11 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import type { BasePost } from '../../types'; +import type { CommonPost } from '../../types'; import { getItemTitle } from '../../actions/utils'; -import TitleView from './title-view'; +import TitleView from './view'; -const titleField: Field< BasePost > = { +const titleField: Field< CommonPost > = { type: 'text', id: 'title', label: __( 'Title' ), @@ -19,9 +19,12 @@ const titleField: Field< BasePost > = { getValue: ( { item } ) => getItemTitle( item ), render: TitleView, enableHiding: false, + enableGlobalSearch: true, }; /** - * Title field for BasePost. + * Title for the any entity with a `title` property. + * For patterns, pages or templates you should use the respective field + * because there are some differences in the rendering, labels, etc. */ export default titleField; diff --git a/packages/fields/src/fields/title/style.scss b/packages/fields/src/fields/title/style.scss new file mode 100644 index 00000000000000..5b9977dcaa398c --- /dev/null +++ b/packages/fields/src/fields/title/style.scss @@ -0,0 +1,8 @@ +.fields-field__title span:first-child { + text-overflow: ellipsis; + overflow: hidden; + text-decoration: none; + white-space: nowrap; + display: block; + flex-grow: 0; +} diff --git a/packages/fields/src/fields/title/title-view.tsx b/packages/fields/src/fields/title/title-view.tsx deleted file mode 100644 index f6bf5fb1817d93..00000000000000 --- a/packages/fields/src/fields/title/title-view.tsx +++ /dev/null @@ -1,61 +0,0 @@ -/** - * WordPress dependencies - */ -import { __experimentalHStack as HStack } from '@wordpress/components'; -import { decodeEntities } from '@wordpress/html-entities'; -import { __ } from '@wordpress/i18n'; -import { useSelect } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; -import type { Settings } from '@wordpress/core-data'; - -/** - * Internal dependencies - */ -import type { BasePost } from '../../types'; -import { getItemTitle } from '../../actions/utils'; - -const TitleView = ( { item }: { item: BasePost } ) => { - const { frontPageId, postsPageId } = useSelect( ( select ) => { - const { getEntityRecord } = select( coreStore ); - const siteSettings = getEntityRecord( - 'root', - 'site' - ) as Partial< Settings >; - return { - frontPageId: siteSettings?.page_on_front, - postsPageId: siteSettings?.page_for_posts, - }; - }, [] ); - - const renderedTitle = getItemTitle( item ); - - let suffix; - if ( item.id === frontPageId ) { - suffix = ( - <span className="edit-site-post-list__title-badge"> - { __( 'Homepage' ) } - </span> - ); - } else if ( item.id === postsPageId ) { - suffix = ( - <span className="edit-site-post-list__title-badge"> - { __( 'Posts Page' ) } - </span> - ); - } - - return ( - <HStack - className="edit-site-post-list__title" - alignment="center" - justify="flex-start" - > - <span> - { decodeEntities( renderedTitle ) || __( '(no title)' ) } - </span> - { suffix } - </HStack> - ); -}; - -export default TitleView; diff --git a/packages/fields/src/fields/title/view.tsx b/packages/fields/src/fields/title/view.tsx new file mode 100644 index 00000000000000..b6f39796a57f05 --- /dev/null +++ b/packages/fields/src/fields/title/view.tsx @@ -0,0 +1,43 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; +import type { ReactNode } from 'react'; + +/** + * WordPress dependencies + */ +import { __experimentalHStack as HStack } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { CommonPost } from '../../types'; +import { getItemTitle } from '../../actions/utils'; + +export function BaseTitleView( { + item, + className, + children, +}: { + item: CommonPost; + className?: string; + children?: ReactNode; +} ) { + const renderedTitle = getItemTitle( item ); + return ( + <HStack + className={ clsx( 'fields-field__title', className ) } + alignment="center" + justify="flex-start" + > + <span>{ renderedTitle || __( '(no title)' ) }</span> + { children } + </HStack> + ); +} + +export default function TitleView( { item }: { item: CommonPost } ) { + return <BaseTitleView item={ item } />; +} diff --git a/packages/fields/src/style.scss b/packages/fields/src/style.scss index 582044235aef1a..d9a571270fbb68 100644 --- a/packages/fields/src/style.scss +++ b/packages/fields/src/style.scss @@ -2,3 +2,6 @@ @import "./fields/slug/style.scss"; @import "./fields/featured-image/style.scss"; @import "./fields/template/style.scss"; +@import "./fields/title/style.scss"; +@import "./fields/page-title/style.scss"; +@import "./fields/pattern-title/style.scss"; diff --git a/test/e2e/specs/site-editor/browser-history.spec.js b/test/e2e/specs/site-editor/browser-history.spec.js index a2326d10e3cc51..c3eb2ac5e3a2fa 100644 --- a/test/e2e/specs/site-editor/browser-history.spec.js +++ b/test/e2e/specs/site-editor/browser-history.spec.js @@ -19,7 +19,9 @@ test.describe( 'Site editor browser history', () => { // Navigate to a single template await page.click( 'role=button[name="Templates"]' ); - await page.getByRole( 'link', { name: 'Index' } ).click(); + await page + .locator( '.fields-field__title', { hasText: 'Index' } ) + .click(); await expect( page ).toHaveURL( '/wp-admin/site-editor.php?p=%2Fwp_template%2Femptytheme%2F%2Findex&canvas=edit' ); diff --git a/test/e2e/specs/site-editor/new-templates-list.spec.js b/test/e2e/specs/site-editor/new-templates-list.spec.js index 6faa85a2659cf1..d26306a6c8e3b5 100644 --- a/test/e2e/specs/site-editor/new-templates-list.spec.js +++ b/test/e2e/specs/site-editor/new-templates-list.spec.js @@ -27,13 +27,7 @@ test.describe( 'Templates', () => { page.locator( '[aria-label="Templates"]' ) ).toBeVisible(); - const firstTitle = page - .getByRole( 'region', { - name: 'Template', - includeHidden: true, - } ) - .getByRole( 'link', { includeHidden: true } ) - .first(); + const firstTitle = page.locator( '.fields-field__title' ).first(); // Descending by title. await page.getByRole( 'button', { name: 'View options' } ).click(); @@ -54,9 +48,7 @@ test.describe( 'Templates', () => { await admin.visitSiteEditor( { postType: 'wp_template' } ); // Global search. await page.getByRole( 'searchbox', { name: 'Search' } ).fill( 'tag' ); - const titles = page - .getByRole( 'region', { name: 'Template' } ) - .getByRole( 'link', { includeHidden: true } ); + const titles = page.locator( '.fields-field__title' ); await expect( titles ).toHaveCount( 1 ); await expect( titles.first() ).toHaveText( 'Tag Archives' ); await page diff --git a/test/e2e/specs/site-editor/template-registration.spec.js b/test/e2e/specs/site-editor/template-registration.spec.js index 90e56645813c30..ed89c7d18bf3fb 100644 --- a/test/e2e/specs/site-editor/template-registration.spec.js +++ b/test/e2e/specs/site-editor/template-registration.spec.js @@ -319,7 +319,9 @@ test.describe( 'Block template registration', () => { .getByLabel( 'Dismiss this notice' ) .getByText( `"Author: Admin" reset.` ); await page.getByPlaceholder( 'Search' ).fill( 'Author: admin' ); - await page.getByRole( 'link', { name: 'Author: Admin' } ).click(); + await page + .locator( '.fields-field__title', { hasText: 'Author: Admin' } ) + .click(); const actions = page.getByLabel( 'Actions' ); await actions.first().click(); await page.getByRole( 'menuitem', { name: 'Reset' } ).click(); diff --git a/test/performance/specs/site-editor.spec.js b/test/performance/specs/site-editor.spec.js index e72d83fa8b3aa4..c09cfe3c67b444 100644 --- a/test/performance/specs/site-editor.spec.js +++ b/test/performance/specs/site-editor.spec.js @@ -237,7 +237,9 @@ test.describe( 'Site Editor Performance', () => { } await metrics.startTracing(); - await page.getByText( 'Single Posts', { exact: true } ).click(); + await page + .getByText( 'Single Posts', { exact: true } ) + .click( { force: true } ); await metrics.stopTracing(); // Get the durations. From f6c0334eb2c9cde5d48f14af36fa62e2ae9d4b1f Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Thu, 5 Dec 2024 12:53:25 +0100 Subject: [PATCH 1866/1908] DataViews build-wp: don't bundle the date package (#67612) Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/dataviews/build.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataviews/build.js b/packages/dataviews/build.js index e156b1cb875af0..16146632d0359e 100644 --- a/packages/dataviews/build.js +++ b/packages/dataviews/build.js @@ -8,7 +8,7 @@ const wpExternals = { name: 'wordpress-externals', setup( build ) { build.onResolve( - { filter: /^@wordpress\/(data|hooks|i18n)(\/|$)/ }, + { filter: /^@wordpress\/(data|hooks|i18n|date)(\/|$)/ }, ( args ) => { // Don't bundle WordPress signleton packages return { path: args.path, external: true }; From 2205e5f8f936fbbb4888bcb3f700e52c1871bfab Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 5 Dec 2024 13:00:05 +0100 Subject: [PATCH 1867/1908] InspectorControlsSlot: remove unused framer motion context forwarding (#67522) * InspectorControlsSlot: remove unused framer motion context forwarding * Remove computedFillProps, use fillProps directly --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> --- .../src/components/inspector-controls/slot.js | 25 +++---------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/packages/block-editor/src/components/inspector-controls/slot.js b/packages/block-editor/src/components/inspector-controls/slot.js index 5c18dbd1f86bb8..4957ca90b5679a 100644 --- a/packages/block-editor/src/components/inspector-controls/slot.js +++ b/packages/block-editor/src/components/inspector-controls/slot.js @@ -1,11 +1,7 @@ /** * WordPress dependencies */ -import { - __experimentalUseSlotFills as useSlotFills, - __unstableMotionContext as MotionContext, -} from '@wordpress/components'; -import { useContext, useMemo } from '@wordpress/element'; +import { __experimentalUseSlotFills as useSlotFills } from '@wordpress/components'; import warning from '@wordpress/warning'; import deprecated from '@wordpress/deprecated'; @@ -37,19 +33,6 @@ export default function InspectorControlsSlot( { const slotFill = groups[ group ]; const fills = useSlotFills( slotFill?.name ); - const motionContextValue = useContext( MotionContext ); - - const computedFillProps = useMemo( - () => ( { - ...fillProps, - forwardedContext: [ - ...( fillProps?.forwardedContext ?? [] ), - [ MotionContext.Provider, { value: motionContextValue } ], - ], - } ), - [ motionContextValue, fillProps ] - ); - if ( ! slotFill ) { warning( `Unknown InspectorControls group "${ group }" provided.` ); return null; @@ -66,14 +49,12 @@ export default function InspectorControlsSlot( { <BlockSupportToolsPanel group={ group } label={ label }> <BlockSupportSlotContainer { ...props } - fillProps={ computedFillProps } + fillProps={ fillProps } Slot={ Slot } /> </BlockSupportToolsPanel> ); } - return ( - <Slot { ...props } fillProps={ computedFillProps } bubblesVirtually /> - ); + return <Slot { ...props } fillProps={ fillProps } bubblesVirtually />; } From 5644105da91c7f65a91b017a13ebd7d2ddfaf47e Mon Sep 17 00:00:00 2001 From: David Calhoun <github@davidcalhoun.me> Date: Thu, 5 Dec 2024 07:19:43 -0500 Subject: [PATCH 1868/1908] docs: Describe patch files (#67603) Provide rationale for patch-package modifications. Co-authored-by: dcalhoun <dpcalhoun@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- patches/README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/patches/README.md b/patches/README.md index 8149c96950057a..b811c824532c37 100644 --- a/patches/README.md +++ b/patches/README.md @@ -24,8 +24,16 @@ See https://github.com/facebook/react/pull/17883. ### `patches/react-devtools-core+4.28.5.patch` -No notes. +The mobile editor relies upon `jsdom-jscore-rn` to create a partial DOM +environment, which causes `react-devtools-core` to believe it's running in a +browser environment. We added a custom conditional to disable browser-specific +features when running in a `jsdom-jscore-rn` environment. + +See https://github.com/WordPress/gutenberg/pull/47616. ### `patches/react-native+0.73.3.patch` -No notes. +Accessibility changes in React Native 0.73.0 resulted in a broken braille screen +input on iOS. This patch is a workaround to restore the previous behavior. + +See https://github.com/WordPress/gutenberg/pull/53895. From c99acafaf46fa6ccb1b47bf34e930d5169b65db6 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr <jsnajdr@gmail.com> Date: Thu, 5 Dec 2024 13:43:28 +0100 Subject: [PATCH 1869/1908] Keycodes: improve tree shaking by annotating exports as pure (#67615) Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: sgomes <sergiomdgomes@git.wordpress.org> --- packages/keycodes/src/index.js | 56 ++++++++++++++++------------------ 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/packages/keycodes/src/index.js b/packages/keycodes/src/index.js index 6b01109e2a40db..b6df5e3f4a2145 100644 --- a/packages/keycodes/src/index.js +++ b/packages/keycodes/src/index.js @@ -211,9 +211,9 @@ export const modifiers = { * @type {WPModifierHandler<WPKeyHandler<string>>} Keyed map of functions to raw * shortcuts. */ -export const rawShortcut = mapValues( - modifiers, - ( /** @type {WPModifier} */ modifier ) => { +export const rawShortcut = + /* @__PURE__ */ + mapValues( modifiers, ( /** @type {WPModifier} */ modifier ) => { return /** @type {WPKeyHandler<string>} */ ( character, _isApple = isAppleOS @@ -222,8 +222,7 @@ export const rawShortcut = mapValues( '+' ); }; - } -); + } ); /** * Return an array of the parts of a keyboard shortcut chord for display. @@ -238,9 +237,9 @@ export const rawShortcut = mapValues( * @type {WPModifierHandler<WPKeyHandler<string[]>>} Keyed map of functions to * shortcut sequences. */ -export const displayShortcutList = mapValues( - modifiers, - ( /** @type {WPModifier} */ modifier ) => { +export const displayShortcutList = + /* @__PURE__ */ + mapValues( modifiers, ( /** @type {WPModifier} */ modifier ) => { return /** @type {WPKeyHandler<string[]>} */ ( character, _isApple = isAppleOS @@ -268,8 +267,7 @@ export const displayShortcutList = mapValues( return [ ...modifierKeys, capitaliseFirstCharacter( character ) ]; }; - } -); + } ); /** * An object that contains functions to display shortcuts. @@ -284,15 +282,17 @@ export const displayShortcutList = mapValues( * @type {WPModifierHandler<WPKeyHandler<string>>} Keyed map of functions to * display shortcuts. */ -export const displayShortcut = mapValues( - displayShortcutList, - ( /** @type {WPKeyHandler<string[]>} */ shortcutList ) => { - return /** @type {WPKeyHandler<string>} */ ( - character, - _isApple = isAppleOS - ) => shortcutList( character, _isApple ).join( '' ); - } -); +export const displayShortcut = + /* @__PURE__ */ + mapValues( + displayShortcutList, + ( /** @type {WPKeyHandler<string[]>} */ shortcutList ) => { + return /** @type {WPKeyHandler<string>} */ ( + character, + _isApple = isAppleOS + ) => shortcutList( character, _isApple ).join( '' ); + } + ); /** * An object that contains functions to return an aria label for a keyboard @@ -308,9 +308,9 @@ export const displayShortcut = mapValues( * @type {WPModifierHandler<WPKeyHandler<string>>} Keyed map of functions to * shortcut ARIA labels. */ -export const shortcutAriaLabel = mapValues( - modifiers, - ( /** @type {WPModifier} */ modifier ) => { +export const shortcutAriaLabel = + /* @__PURE__ */ + mapValues( modifiers, ( /** @type {WPModifier} */ modifier ) => { return /** @type {WPKeyHandler<string>} */ ( character, _isApple = isAppleOS @@ -338,8 +338,7 @@ export const shortcutAriaLabel = mapValues( ) .join( isApple ? ' ' : ' + ' ); }; - } -); + } ); /** * From a given KeyboardEvent, returns an array of active modifier constants for @@ -379,9 +378,9 @@ function getEventModifiers( event ) { * @type {WPModifierHandler<WPEventKeyHandler>} Keyed map of functions * to match events. */ -export const isKeyboardEvent = mapValues( - modifiers, - ( /** @type {WPModifier} */ getModifiers ) => { +export const isKeyboardEvent = + /* @__PURE__ */ + mapValues( modifiers, ( /** @type {WPModifier} */ getModifiers ) => { return /** @type {WPEventKeyHandler} */ ( event, character, @@ -439,5 +438,4 @@ export const isKeyboardEvent = mapValues( return key === character.toLowerCase(); }; - } -); + } ); From 237b381a81601d119319fb075ded5028877c0a13 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras <ntsekouras@outlook.com> Date: Thu, 5 Dec 2024 15:27:32 +0200 Subject: [PATCH 1870/1908] Remove words count in the multi-selection inspector (#67624) Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- .../multi-selection-inspector/index.js | 44 +++++++------------ .../multi-selection-inspector/style.scss | 12 ----- 2 files changed, 17 insertions(+), 39 deletions(-) diff --git a/packages/block-editor/src/components/multi-selection-inspector/index.js b/packages/block-editor/src/components/multi-selection-inspector/index.js index f5e7f696347686..23d890d79fff4d 100644 --- a/packages/block-editor/src/components/multi-selection-inspector/index.js +++ b/packages/block-editor/src/components/multi-selection-inspector/index.js @@ -3,9 +3,8 @@ */ import { sprintf, _n } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; -import { serialize } from '@wordpress/blocks'; -import { count as wordCount } from '@wordpress/wordcount'; import { copy } from '@wordpress/icons'; +import { __experimentalHStack as HStack } from '@wordpress/components'; /** * Internal dependencies @@ -14,33 +13,24 @@ import BlockIcon from '../block-icon'; import { store as blockEditorStore } from '../../store'; export default function MultiSelectionInspector() { - const { blocks } = useSelect( ( select ) => { - const { getMultiSelectedBlocks } = select( blockEditorStore ); - return { - blocks: getMultiSelectedBlocks(), - }; - }, [] ); - const words = wordCount( serialize( blocks ), 'words' ); - + const selectedBlockCount = useSelect( + ( select ) => select( blockEditorStore ).getSelectedBlockCount(), + [] + ); return ( - <div className="block-editor-multi-selection-inspector__card"> + <HStack + justify="flex-start" + spacing={ 2 } + className="block-editor-multi-selection-inspector__card" + > <BlockIcon icon={ copy } showColors /> - <div className="block-editor-multi-selection-inspector__card-content"> - <div className="block-editor-multi-selection-inspector__card-title"> - { sprintf( - /* translators: %d: number of blocks */ - _n( '%d Block', '%d Blocks', blocks.length ), - blocks.length - ) } - </div> - <div className="block-editor-multi-selection-inspector__card-description"> - { sprintf( - /* translators: %d: number of words */ - _n( '%d word selected.', '%d words selected.', words ), - words - ) } - </div> + <div className="block-editor-multi-selection-inspector__card-title"> + { sprintf( + /* translators: %d: number of blocks */ + _n( '%d Block', '%d Blocks', selectedBlockCount ), + selectedBlockCount + ) } </div> - </div> + </HStack> ); } diff --git a/packages/block-editor/src/components/multi-selection-inspector/style.scss b/packages/block-editor/src/components/multi-selection-inspector/style.scss index 61bf5f8cdb3820..e37245d58f5dd5 100644 --- a/packages/block-editor/src/components/multi-selection-inspector/style.scss +++ b/packages/block-editor/src/components/multi-selection-inspector/style.scss @@ -1,25 +1,13 @@ .block-editor-multi-selection-inspector__card { - display: flex; - align-items: flex-start; padding: $grid-unit-20; } -.block-editor-multi-selection-inspector__card-content { - flex-grow: 1; -} - .block-editor-multi-selection-inspector__card-title { font-weight: 500; - margin-bottom: 5px; -} - -.block-editor-multi-selection-inspector__card-description { - font-size: $default-font-size; } .block-editor-multi-selection-inspector__card .block-editor-block-icon { margin-left: -2px; - margin-right: 10px; padding: 0 3px; width: $button-size; height: $button-size-small; From 3133f56f3f99543ed92557d47f364842bd31e94b Mon Sep 17 00:00:00 2001 From: Marco Ciampini <marco.ciampo@gmail.com> Date: Thu, 5 Dec 2024 14:41:46 +0100 Subject: [PATCH 1871/1908] Remove `__unstableMotionContext` from `@wordpress/components` (#67623) * Remove unused `__unstableMotionContext` export from `@wordpress/components` * CHANGELOG --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/animation/index.tsx | 1 - packages/components/src/index.ts | 6 +----- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 1045b23bfe14f6..1fd87cc958352f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Removed the unused `__unstableMotionContext` export ([#67623](https://github.com/WordPress/gutenberg/pull/67623)). + ### Enhancements - `GradientPicker`: Add `enableAlpha` prop ([#66974](https://github.com/WordPress/gutenberg/pull/66974)) diff --git a/packages/components/src/animation/index.tsx b/packages/components/src/animation/index.tsx index 6620f8d5d4ecae..1b6796cd61ee9b 100644 --- a/packages/components/src/animation/index.tsx +++ b/packages/components/src/animation/index.tsx @@ -9,5 +9,4 @@ export { motion as __unstableMotion, AnimatePresence as __unstableAnimatePresence, - MotionContext as __unstableMotionContext, } from 'framer-motion'; diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index e82d6da70279e8..2acd609992d6ad 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -21,11 +21,7 @@ export { default as Animate, getAnimateClassName as __unstableGetAnimateClassName, } from './animate'; -export { - __unstableMotion, - __unstableAnimatePresence, - __unstableMotionContext, -} from './animation'; +export { __unstableMotion, __unstableAnimatePresence } from './animation'; export { default as AnglePickerControl } from './angle-picker-control'; export { default as Autocomplete, From 1418350eb5a1f15e109fc96af385bdd029fc7304 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:58:53 +0200 Subject: [PATCH 1872/1908] Preview: ArgsTable => Controls (#67582) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- storybook/preview.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/storybook/preview.js b/storybook/preview.js index a7c9aa0c085fc1..e173ab3ed1e268 100644 --- a/storybook/preview.js +++ b/storybook/preview.js @@ -2,7 +2,7 @@ * External dependencies */ import { - ArgsTable, + Controls, Description, Primary, Stories, @@ -114,8 +114,7 @@ export const parameters = { <Subtitle /> <Primary /> <Description /> - { /* `story="^"` enables Controls for the primary props table */ } - <ArgsTable story="^" /> + <Controls /> <Stories includePrimary={ false } /> </> ), From c93fd2d78c9bd9fe12642dbb0813448a1534fa03 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 5 Dec 2024 17:38:35 +0200 Subject: [PATCH 1873/1908] Storybook: Update control types from `null` to `undefined` (#67581) * control type null => undefined * undefined -> false * Also disable NumberControl value control Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../stories/aliginment-toolbar.story.js | 4 ++-- .../alignment-control/stories/index.story.js | 4 ++-- .../stories/aspect-ratio-tool.story.js | 2 +- .../dimensions-tool/stories/index.story.js | 2 +- .../dimensions-tool/stories/scale-tool.story.js | 2 +- .../stories/width-height-tool.story.js | 2 +- .../resolution-tool/stories/index.story.js | 2 +- .../text-alignment-control/stories/index.story.js | 2 +- .../stories/index.story.tsx | 4 ++-- .../angle-picker-control/stories/index.story.tsx | 4 ++-- .../src/base-control/stories/index.story.tsx | 2 +- .../src/border-box-control/stories/index.story.tsx | 2 +- .../src/border-control/stories/index.story.tsx | 2 +- .../src/box-control/stories/index.story.tsx | 2 +- .../src/button-group/stories/index.story.tsx | 2 +- .../components/src/card/stories/index.story.tsx | 4 ++-- .../src/checkbox-control/stories/index.story.tsx | 2 +- .../circular-option-picker/stories/index.story.tsx | 4 ++-- .../src/color-palette/stories/index.story.tsx | 6 +++--- .../src/color-picker/stories/index.story.tsx | 4 ++-- .../src/combobox-control/stories/index.story.tsx | 2 +- .../src/composite/stories/index.story.tsx | 6 +++--- .../src/confirm-dialog/stories/index.story.tsx | 2 +- .../stories/index.story.tsx | 4 ++-- .../custom-select-control/stories/index.story.tsx | 4 ++-- .../src/date-time/stories/date-time.story.tsx | 2 +- .../src/date-time/stories/date.story.tsx | 2 +- .../src/date-time/stories/time.story.tsx | 2 +- .../src/dimension-control/stories/index.story.tsx | 2 +- .../src/disabled/stories/index.story.tsx | 4 ++-- .../components/src/divider/stories/index.story.tsx | 2 +- .../src/draggable/stories/index.story.tsx | 4 ++-- .../src/dropdown-menu/stories/index.story.tsx | 6 +++--- .../src/dropdown/stories/index.story.tsx | 14 +++++++------- .../stories/duotone-picker.story.tsx | 2 +- .../components/src/flex/stories/index.story.tsx | 2 +- .../src/font-size-picker/stories/index.story.tsx | 2 +- .../src/form-file-upload/stories/index.story.tsx | 6 +++--- .../src/form-token-field/stories/index.story.tsx | 4 ++-- .../src/gradient-picker/stories/index.story.tsx | 2 +- .../components/src/grid/stories/index.story.tsx | 2 +- .../components/src/h-stack/stories/index.story.tsx | 4 ++-- .../src/input-control/stories/index.story.tsx | 8 ++++---- .../src/item-group/stories/index.story.tsx | 4 ++-- .../src/menu-group/stories/index.story.tsx | 2 +- .../src/menu-item/stories/index.story.tsx | 2 +- .../src/menu-items-choice/stories/index.story.tsx | 2 +- .../components/src/menu/stories/index.story.tsx | 4 ++-- .../components/src/modal/stories/index.story.tsx | 4 ++-- .../stories/navigable-menu.story.tsx | 2 +- .../stories/tabbable-container.story.tsx | 2 +- .../src/navigation/stories/index.story.tsx | 8 ++++---- .../src/navigator/stories/index.story.tsx | 6 +++--- .../src/number-control/stories/index.story.tsx | 2 +- .../components/src/panel/stories/index.story.tsx | 2 +- .../src/placeholder/stories/index.story.tsx | 6 +++--- .../components/src/popover/stories/index.story.tsx | 12 ++++++------ .../src/query-controls/stories/index.story.tsx | 12 ++++++------ .../src/radio-control/stories/index.story.tsx | 2 +- .../src/radio-group/stories/index.story.tsx | 6 +++--- .../src/range-control/stories/index.story.tsx | 14 +++++++------- .../src/resizable-box/stories/index.story.tsx | 2 +- .../src/responsive-wrapper/stories/index.story.tsx | 2 +- .../components/src/sandbox/stories/index.story.tsx | 2 +- .../src/scrollable/stories/index.story.tsx | 2 +- .../src/search-control/stories/index.story.tsx | 2 +- .../src/select-control/stories/index.story.tsx | 2 +- .../src/slot-fill/stories/index.story.tsx | 4 ++-- .../src/snackbar/stories/index.story.tsx | 8 ++++---- .../components/src/snackbar/stories/list.story.tsx | 4 ++-- .../components/src/surface/stories/index.story.tsx | 2 +- .../src/text-control/stories/index.story.tsx | 2 +- .../src/textarea-control/stories/index.story.tsx | 2 +- .../src/toggle-control/stories/index.story.tsx | 2 +- .../toggle-group-control/stories/index.story.tsx | 2 +- .../components/src/toolbar/stories/index.story.tsx | 2 +- .../src/tools-panel/stories/index.story.tsx | 6 +++--- .../components/src/tooltip/stories/index.story.tsx | 2 +- .../src/tree-grid/stories/index.story.tsx | 2 +- .../src/tree-select/stories/index.story.tsx | 2 +- .../src/unit-control/stories/index.story.tsx | 8 ++++---- .../components/src/view/stories/index.story.tsx | 2 +- .../src/visually-hidden/stories/index.story.tsx | 2 +- .../components/src/z-stack/stories/index.story.tsx | 2 +- 84 files changed, 152 insertions(+), 152 deletions(-) diff --git a/packages/block-editor/src/components/alignment-control/stories/aliginment-toolbar.story.js b/packages/block-editor/src/components/alignment-control/stories/aliginment-toolbar.story.js index f2191220d6bb4c..a02f0ec3dfbce0 100644 --- a/packages/block-editor/src/components/alignment-control/stories/aliginment-toolbar.story.js +++ b/packages/block-editor/src/components/alignment-control/stories/aliginment-toolbar.story.js @@ -16,13 +16,13 @@ const meta = { component: AlignmentToolbar, argTypes: { value: { - control: { type: null }, + control: { type: false }, defaultValue: 'undefined', description: 'The current value of the alignment setting.', }, onChange: { action: 'onChange', - control: { type: null }, + control: { type: false }, description: "A callback function invoked when the toolbar's alignment value is changed via an interaction with any of the toolbar's buttons. Called with the new alignment value (ie: `left`, `center`, `right`, `undefined`) as the only argument.", }, diff --git a/packages/block-editor/src/components/alignment-control/stories/index.story.js b/packages/block-editor/src/components/alignment-control/stories/index.story.js index 85c92f7e0665a4..ad403dcab43857 100644 --- a/packages/block-editor/src/components/alignment-control/stories/index.story.js +++ b/packages/block-editor/src/components/alignment-control/stories/index.story.js @@ -20,13 +20,13 @@ const meta = { component: AlignmentControl, argTypes: { value: { - control: { type: null }, + control: { type: false }, defaultValue: 'undefined', description: 'The current value of the alignment setting.', }, onChange: { action: 'onChange', - control: { type: null }, + control: { type: false }, description: "A callback function invoked when the toolbar's alignment value is changed via an interaction with any of the toolbar's buttons. Called with the new alignment value (ie: `left`, `center`, `right`, `undefined`) as the only argument.", }, diff --git a/packages/block-editor/src/components/dimensions-tool/stories/aspect-ratio-tool.story.js b/packages/block-editor/src/components/dimensions-tool/stories/aspect-ratio-tool.story.js index 9b82404a23c255..2acaddb57a6cd5 100644 --- a/packages/block-editor/src/components/dimensions-tool/stories/aspect-ratio-tool.story.js +++ b/packages/block-editor/src/components/dimensions-tool/stories/aspect-ratio-tool.story.js @@ -16,7 +16,7 @@ export default { title: 'BlockEditor (Private APIs)/DimensionsTool/AspectRatioTool', component: AspectRatioTool, argTypes: { - panelId: { control: { type: null } }, + panelId: { control: { type: false } }, onChange: { action: 'changed' }, }, }; diff --git a/packages/block-editor/src/components/dimensions-tool/stories/index.story.js b/packages/block-editor/src/components/dimensions-tool/stories/index.story.js index d9e1a82771282e..270a6b1ae4b37a 100644 --- a/packages/block-editor/src/components/dimensions-tool/stories/index.story.js +++ b/packages/block-editor/src/components/dimensions-tool/stories/index.story.js @@ -16,7 +16,7 @@ export default { title: 'BlockEditor (Private APIs)/DimensionsTool', component: DimensionsTool, argTypes: { - panelId: { control: { type: null } }, + panelId: { control: { type: false } }, onChange: { action: 'changed' }, }, }; diff --git a/packages/block-editor/src/components/dimensions-tool/stories/scale-tool.story.js b/packages/block-editor/src/components/dimensions-tool/stories/scale-tool.story.js index a5ff9a81b5304b..fe354168d2ae8d 100644 --- a/packages/block-editor/src/components/dimensions-tool/stories/scale-tool.story.js +++ b/packages/block-editor/src/components/dimensions-tool/stories/scale-tool.story.js @@ -16,7 +16,7 @@ export default { title: 'BlockEditor (Private APIs)/DimensionsTool/ScaleTool', component: ScaleTool, argTypes: { - panelId: { control: { type: null } }, + panelId: { control: { type: false } }, onChange: { action: 'changed' }, }, }; diff --git a/packages/block-editor/src/components/dimensions-tool/stories/width-height-tool.story.js b/packages/block-editor/src/components/dimensions-tool/stories/width-height-tool.story.js index 4a9d9782ad16b7..ea51455ed4b8e3 100644 --- a/packages/block-editor/src/components/dimensions-tool/stories/width-height-tool.story.js +++ b/packages/block-editor/src/components/dimensions-tool/stories/width-height-tool.story.js @@ -16,7 +16,7 @@ export default { title: 'BlockEditor (Private APIs)/DimensionsTool/WidthHeightTool', component: WidthHeightTool, argTypes: { - panelId: { control: { type: null } }, + panelId: { control: { type: false } }, onChange: { action: 'changed' }, }, }; diff --git a/packages/block-editor/src/components/resolution-tool/stories/index.story.js b/packages/block-editor/src/components/resolution-tool/stories/index.story.js index ed598acd4df98f..9700096b3f2e8e 100644 --- a/packages/block-editor/src/components/resolution-tool/stories/index.story.js +++ b/packages/block-editor/src/components/resolution-tool/stories/index.story.js @@ -16,7 +16,7 @@ export default { title: 'BlockEditor (Private APIs)/ResolutionControl', component: ResolutionTool, argTypes: { - panelId: { control: { type: null } }, + panelId: { control: { type: false } }, onChange: { action: 'changed' }, }, }; diff --git a/packages/block-editor/src/components/text-alignment-control/stories/index.story.js b/packages/block-editor/src/components/text-alignment-control/stories/index.story.js index b2c171497acb0a..80d04c0a96867d 100644 --- a/packages/block-editor/src/components/text-alignment-control/stories/index.story.js +++ b/packages/block-editor/src/components/text-alignment-control/stories/index.story.js @@ -18,7 +18,7 @@ export default { control: 'check', options: [ 'left', 'center', 'right', 'justify' ], }, - value: { control: { type: null } }, + value: { control: { type: false } }, }, }; diff --git a/packages/components/src/alignment-matrix-control/stories/index.story.tsx b/packages/components/src/alignment-matrix-control/stories/index.story.tsx index 433d7540197da2..992e79d51f1e83 100644 --- a/packages/components/src/alignment-matrix-control/stories/index.story.tsx +++ b/packages/components/src/alignment-matrix-control/stories/index.story.tsx @@ -24,8 +24,8 @@ const meta: Meta< typeof AlignmentMatrixControl > = { 'AlignmentMatrixControl.Icon': AlignmentMatrixControl.Icon, }, argTypes: { - onChange: { control: { type: null } }, - value: { control: { type: null } }, + onChange: { control: { type: false } }, + value: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/angle-picker-control/stories/index.story.tsx b/packages/components/src/angle-picker-control/stories/index.story.tsx index ebbf3425d802f1..9bacd4871a9687 100644 --- a/packages/components/src/angle-picker-control/stories/index.story.tsx +++ b/packages/components/src/angle-picker-control/stories/index.story.tsx @@ -17,8 +17,8 @@ const meta: Meta< typeof AnglePickerControl > = { title: 'Components/AnglePickerControl', component: AnglePickerControl, argTypes: { - as: { control: { type: null } }, - value: { control: { type: null } }, + as: { control: { type: false } }, + value: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/base-control/stories/index.story.tsx b/packages/components/src/base-control/stories/index.story.tsx index 90517c75b5e95e..88ced86d3fe1be 100644 --- a/packages/components/src/base-control/stories/index.story.tsx +++ b/packages/components/src/base-control/stories/index.story.tsx @@ -18,7 +18,7 @@ const meta: Meta< typeof BaseControl > = { 'BaseControl.VisualLabel': BaseControl.VisualLabel, }, argTypes: { - children: { control: { type: null } }, + children: { control: { type: false } }, help: { control: { type: 'text' } }, label: { control: { type: 'text' } }, }, diff --git a/packages/components/src/border-box-control/stories/index.story.tsx b/packages/components/src/border-box-control/stories/index.story.tsx index 0a961d34fb93d3..382ee3afa626ad 100644 --- a/packages/components/src/border-box-control/stories/index.story.tsx +++ b/packages/components/src/border-box-control/stories/index.story.tsx @@ -20,7 +20,7 @@ const meta: Meta< typeof BorderBoxControl > = { component: BorderBoxControl, argTypes: { onChange: { action: 'onChange' }, - value: { control: { type: null } }, + value: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/border-control/stories/index.story.tsx b/packages/components/src/border-control/stories/index.story.tsx index 3b5fa740d092d6..48fcd37c708d09 100644 --- a/packages/components/src/border-control/stories/index.story.tsx +++ b/packages/components/src/border-control/stories/index.story.tsx @@ -23,7 +23,7 @@ const meta: Meta< typeof BorderControl > = { action: 'onChange', }, width: { control: { type: 'text' } }, - value: { control: { type: null } }, + value: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/box-control/stories/index.story.tsx b/packages/components/src/box-control/stories/index.story.tsx index aa94e8c4bf00b8..fc53b2967ac92e 100644 --- a/packages/components/src/box-control/stories/index.story.tsx +++ b/packages/components/src/box-control/stories/index.story.tsx @@ -17,7 +17,7 @@ const meta: Meta< typeof BoxControl > = { title: 'Components/BoxControl', component: BoxControl, argTypes: { - values: { control: { type: null } }, + values: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/button-group/stories/index.story.tsx b/packages/components/src/button-group/stories/index.story.tsx index f6af2416977f40..d05a32fe10e98d 100644 --- a/packages/components/src/button-group/stories/index.story.tsx +++ b/packages/components/src/button-group/stories/index.story.tsx @@ -13,7 +13,7 @@ const meta: Meta< typeof ButtonGroup > = { title: 'Components/ButtonGroup', component: ButtonGroup, argTypes: { - children: { control: { type: null } }, + children: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/card/stories/index.story.tsx b/packages/components/src/card/stories/index.story.tsx index 03726abbe754ee..7534ff5345858d 100644 --- a/packages/components/src/card/stories/index.story.tsx +++ b/packages/components/src/card/stories/index.story.tsx @@ -26,10 +26,10 @@ const meta: Meta< typeof Card > = { id: 'components-card', argTypes: { as: { - control: { type: null }, + control: { type: false }, }, children: { - control: { type: null }, + control: { type: false }, }, }, parameters: { diff --git a/packages/components/src/checkbox-control/stories/index.story.tsx b/packages/components/src/checkbox-control/stories/index.story.tsx index a68e380a8f7332..c3e45fdd62f379 100644 --- a/packages/components/src/checkbox-control/stories/index.story.tsx +++ b/packages/components/src/checkbox-control/stories/index.story.tsx @@ -24,7 +24,7 @@ const meta: Meta< typeof CheckboxControl > = { action: 'onChange', }, checked: { - control: { type: null }, + control: { type: false }, }, help: { control: { type: 'text' } }, }, diff --git a/packages/components/src/circular-option-picker/stories/index.story.tsx b/packages/components/src/circular-option-picker/stories/index.story.tsx index d0314670fe1694..ee10cb70bb55ef 100644 --- a/packages/components/src/circular-option-picker/stories/index.story.tsx +++ b/packages/components/src/circular-option-picker/stories/index.story.tsx @@ -32,8 +32,8 @@ const meta: Meta< typeof CircularOptionPicker > = { CircularOptionPicker.DropdownLinkAction, }, argTypes: { - actions: { control: { type: null } }, - options: { control: { type: null } }, + actions: { control: { type: false } }, + options: { control: { type: false } }, children: { control: { type: 'text' } }, }, parameters: { diff --git a/packages/components/src/color-palette/stories/index.story.tsx b/packages/components/src/color-palette/stories/index.story.tsx index 5342fc5222be6a..071a1cecfe1058 100644 --- a/packages/components/src/color-palette/stories/index.story.tsx +++ b/packages/components/src/color-palette/stories/index.story.tsx @@ -18,9 +18,9 @@ const meta: Meta< typeof ColorPalette > = { id: 'components-colorpalette', component: ColorPalette, argTypes: { - as: { control: { type: null } }, - onChange: { action: 'onChange', control: { type: null } }, - value: { control: { type: null } }, + as: { control: { type: false } }, + onChange: { action: 'onChange', control: { type: false } }, + value: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/color-picker/stories/index.story.tsx b/packages/components/src/color-picker/stories/index.story.tsx index 44040a5265c5d3..5277a004a9daa0 100644 --- a/packages/components/src/color-picker/stories/index.story.tsx +++ b/packages/components/src/color-picker/stories/index.story.tsx @@ -13,8 +13,8 @@ const meta: Meta< typeof ColorPicker > = { title: 'Components/Selection & Input/Color/ColorPicker', id: 'components-colorpicker', argTypes: { - as: { control: { type: null } }, - color: { control: { type: null } }, + as: { control: { type: false } }, + color: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/combobox-control/stories/index.story.tsx b/packages/components/src/combobox-control/stories/index.story.tsx index 1b4972f167f745..a9ac2ffb74cb3e 100644 --- a/packages/components/src/combobox-control/stories/index.story.tsx +++ b/packages/components/src/combobox-control/stories/index.story.tsx @@ -38,7 +38,7 @@ const meta: Meta< typeof ComboboxControl > = { id: 'components-comboboxcontrol', component: ComboboxControl, argTypes: { - value: { control: { type: null } }, + value: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx index eefcd599134757..8a6fb6e1e2d862 100644 --- a/packages/components/src/composite/stories/index.story.tsx +++ b/packages/components/src/composite/stories/index.story.tsx @@ -36,9 +36,9 @@ const meta: Meta< typeof Composite > = { 'Composite.Context': Composite.Context, }, argTypes: { - children: { control: { type: null } }, - render: { control: { type: null } }, - setActiveId: { control: { type: null } }, + children: { control: { type: false } }, + render: { control: { type: false } }, + setActiveId: { control: { type: false } }, focusLoop: { control: 'select', options: [ true, false, 'horizontal', 'vertical', 'both' ], diff --git a/packages/components/src/confirm-dialog/stories/index.story.tsx b/packages/components/src/confirm-dialog/stories/index.story.tsx index 9496d85939edf3..93fc1f7605449f 100644 --- a/packages/components/src/confirm-dialog/stories/index.story.tsx +++ b/packages/components/src/confirm-dialog/stories/index.story.tsx @@ -20,7 +20,7 @@ const meta: Meta< typeof ConfirmDialog > = { id: 'components-experimental-confirmdialog', argTypes: { isOpen: { - control: { type: null }, + control: { type: false }, }, }, parameters: { diff --git a/packages/components/src/custom-select-control-v2/stories/index.story.tsx b/packages/components/src/custom-select-control-v2/stories/index.story.tsx index 3595ee2e951990..e97886d67ee172 100644 --- a/packages/components/src/custom-select-control-v2/stories/index.story.tsx +++ b/packages/components/src/custom-select-control-v2/stories/index.story.tsx @@ -22,8 +22,8 @@ const meta: Meta< typeof CustomSelectControlV2 > = { 'CustomSelectControlV2.Item': CustomSelectControlV2.Item, }, argTypes: { - children: { control: { type: null } }, - value: { control: { type: null } }, + children: { control: { type: false } }, + value: { control: { type: false } }, }, tags: [ 'status-wip' ], parameters: { diff --git a/packages/components/src/custom-select-control/stories/index.story.tsx b/packages/components/src/custom-select-control/stories/index.story.tsx index 9d430b639547c6..d86fd45c86b798 100644 --- a/packages/components/src/custom-select-control/stories/index.story.tsx +++ b/packages/components/src/custom-select-control/stories/index.story.tsx @@ -18,8 +18,8 @@ const meta: Meta< typeof CustomSelectControl > = { component: CustomSelectControl, id: 'components-customselectcontrol', argTypes: { - onChange: { control: { type: null } }, - value: { control: { type: null } }, + onChange: { control: { type: false } }, + value: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/date-time/stories/date-time.story.tsx b/packages/components/src/date-time/stories/date-time.story.tsx index 7636e2fdc80a30..b2ee1fa8d9a9c3 100644 --- a/packages/components/src/date-time/stories/date-time.story.tsx +++ b/packages/components/src/date-time/stories/date-time.story.tsx @@ -20,7 +20,7 @@ const meta: Meta< typeof DateTimePicker > = { component: DateTimePicker, argTypes: { currentDate: { control: 'date' }, - onChange: { action: 'onChange', control: { type: null } }, + onChange: { action: 'onChange', control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/date-time/stories/date.story.tsx b/packages/components/src/date-time/stories/date.story.tsx index 36fef0c5bfd195..b90d3c2da555af 100644 --- a/packages/components/src/date-time/stories/date.story.tsx +++ b/packages/components/src/date-time/stories/date.story.tsx @@ -20,7 +20,7 @@ const meta: Meta< typeof DatePicker > = { component: DatePicker, argTypes: { currentDate: { control: 'date' }, - onChange: { action: 'onChange', control: { type: null } }, + onChange: { action: 'onChange', control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/date-time/stories/time.story.tsx b/packages/components/src/date-time/stories/time.story.tsx index c19b5b4f48f5c2..c7fee061d3ef85 100644 --- a/packages/components/src/date-time/stories/time.story.tsx +++ b/packages/components/src/date-time/stories/time.story.tsx @@ -21,7 +21,7 @@ const meta: Meta< typeof TimePicker > = { subcomponents: { 'TimePicker.TimeInput': TimePicker.TimeInput }, argTypes: { currentTime: { control: 'date' }, - onChange: { action: 'onChange', control: { type: null } }, + onChange: { action: 'onChange', control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/dimension-control/stories/index.story.tsx b/packages/components/src/dimension-control/stories/index.story.tsx index 61fd0aae4ee768..7b059540a883bc 100644 --- a/packages/components/src/dimension-control/stories/index.story.tsx +++ b/packages/components/src/dimension-control/stories/index.story.tsx @@ -24,7 +24,7 @@ const meta: Meta< typeof DimensionControl > = { id: 'components-dimensioncontrol', argTypes: { onChange: { action: 'onChange' }, - value: { control: { type: null } }, + value: { control: { type: false } }, icon: { control: { type: 'select' }, options: [ '-', 'desktop', 'tablet', 'mobile' ], diff --git a/packages/components/src/disabled/stories/index.story.tsx b/packages/components/src/disabled/stories/index.story.tsx index 29d9c925f4f5d8..b89026a8b548f7 100644 --- a/packages/components/src/disabled/stories/index.story.tsx +++ b/packages/components/src/disabled/stories/index.story.tsx @@ -22,8 +22,8 @@ const meta: Meta< typeof Disabled > = { id: 'components-disabled', component: Disabled, argTypes: { - as: { control: { type: null } }, - children: { control: { type: null } }, + as: { control: { type: false } }, + children: { control: { type: false } }, }, parameters: { controls: { diff --git a/packages/components/src/divider/stories/index.story.tsx b/packages/components/src/divider/stories/index.story.tsx index 4910c1b591c524..fe3fba971b28f2 100644 --- a/packages/components/src/divider/stories/index.story.tsx +++ b/packages/components/src/divider/stories/index.story.tsx @@ -24,7 +24,7 @@ const meta: Meta< typeof Divider > = { control: { type: 'text' }, }, wrapElement: { - control: { type: null }, + control: { type: false }, }, ref: { table: { diff --git a/packages/components/src/draggable/stories/index.story.tsx b/packages/components/src/draggable/stories/index.story.tsx index 6ecb54a07a3fb2..54fdeaadd147e3 100644 --- a/packages/components/src/draggable/stories/index.story.tsx +++ b/packages/components/src/draggable/stories/index.story.tsx @@ -21,8 +21,8 @@ const meta: Meta< typeof Draggable > = { title: 'Components/Utilities/Draggable', id: 'components-draggable', argTypes: { - elementId: { control: { type: null } }, - __experimentalDragComponent: { control: { type: null } }, + elementId: { control: { type: false } }, + __experimentalDragComponent: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/dropdown-menu/stories/index.story.tsx b/packages/components/src/dropdown-menu/stories/index.story.tsx index 8c13a0b57dbda6..5277d4f54a4dff 100644 --- a/packages/components/src/dropdown-menu/stories/index.story.tsx +++ b/packages/components/src/dropdown-menu/stories/index.story.tsx @@ -37,9 +37,9 @@ const meta: Meta< typeof DropdownMenu > = { mapping: { menu, chevronDown, more }, control: { type: 'select' }, }, - open: { control: { type: null } }, - defaultOpen: { control: { type: null } }, - onToggle: { control: { type: null } }, + open: { control: { type: false } }, + defaultOpen: { control: { type: false } }, + onToggle: { control: { type: false } }, }, }; export default meta; diff --git a/packages/components/src/dropdown/stories/index.story.tsx b/packages/components/src/dropdown/stories/index.story.tsx index bfa51a07a97170..8adb10574fc876 100644 --- a/packages/components/src/dropdown/stories/index.story.tsx +++ b/packages/components/src/dropdown/stories/index.story.tsx @@ -25,13 +25,13 @@ const meta: Meta< typeof Dropdown > = { type: 'radio', }, }, - position: { control: { type: null } }, - renderContent: { control: { type: null } }, - renderToggle: { control: { type: null } }, - open: { control: { type: null } }, - defaultOpen: { control: { type: null } }, - onToggle: { control: { type: null } }, - onClose: { control: { type: null } }, + position: { control: { type: false } }, + renderContent: { control: { type: false } }, + renderToggle: { control: { type: false } }, + open: { control: { type: false } }, + defaultOpen: { control: { type: false } }, + onToggle: { control: { type: false } }, + onClose: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/duotone-picker/stories/duotone-picker.story.tsx b/packages/components/src/duotone-picker/stories/duotone-picker.story.tsx index f06d0ee40a6ce3..014ab4b22443e9 100644 --- a/packages/components/src/duotone-picker/stories/duotone-picker.story.tsx +++ b/packages/components/src/duotone-picker/stories/duotone-picker.story.tsx @@ -19,7 +19,7 @@ const meta: Meta< typeof DuotonePicker > = { component: DuotonePicker, argTypes: { onChange: { action: 'onChange' }, - value: { control: { type: null } }, + value: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/flex/stories/index.story.tsx b/packages/components/src/flex/stories/index.story.tsx index 142f2796657219..8f57d01c4de626 100644 --- a/packages/components/src/flex/stories/index.story.tsx +++ b/packages/components/src/flex/stories/index.story.tsx @@ -17,7 +17,7 @@ const meta: Meta< typeof Flex > = { argTypes: { align: { control: { type: 'text' } }, as: { control: { type: 'text' } }, - children: { control: { type: null } }, + children: { control: { type: false } }, gap: { control: { type: 'text' } }, justify: { control: { type: 'text' } }, // Disabled isReversed because it's deprecated. diff --git a/packages/components/src/font-size-picker/stories/index.story.tsx b/packages/components/src/font-size-picker/stories/index.story.tsx index a0d83756ca1ec9..4bd50293788bbe 100644 --- a/packages/components/src/font-size-picker/stories/index.story.tsx +++ b/packages/components/src/font-size-picker/stories/index.story.tsx @@ -17,7 +17,7 @@ const meta: Meta< typeof FontSizePicker > = { title: 'Components/FontSizePicker', component: FontSizePicker, argTypes: { - value: { control: { type: null } }, + value: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/form-file-upload/stories/index.story.tsx b/packages/components/src/form-file-upload/stories/index.story.tsx index 176d6b2af60983..3f961b87b32f33 100644 --- a/packages/components/src/form-file-upload/stories/index.story.tsx +++ b/packages/components/src/form-file-upload/stories/index.story.tsx @@ -18,9 +18,9 @@ const meta: Meta< typeof FormFileUpload > = { id: 'components-formfileupload', component: FormFileUpload, argTypes: { - icon: { control: { type: null } }, - onChange: { action: 'onChange', control: { type: null } }, - onClick: { control: { type: null } }, + icon: { control: { type: false } }, + onChange: { action: 'onChange', control: { type: false } }, + onClick: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/form-token-field/stories/index.story.tsx b/packages/components/src/form-token-field/stories/index.story.tsx index c43d155c809bb7..6e895989c164b3 100644 --- a/packages/components/src/form-token-field/stories/index.story.tsx +++ b/packages/components/src/form-token-field/stories/index.story.tsx @@ -19,10 +19,10 @@ const meta: Meta< typeof FormTokenField > = { id: 'components-formtokenfield', argTypes: { value: { - control: { type: null }, + control: { type: false }, }, __experimentalValidateInput: { - control: { type: null }, + control: { type: false }, }, }, parameters: { diff --git a/packages/components/src/gradient-picker/stories/index.story.tsx b/packages/components/src/gradient-picker/stories/index.story.tsx index b2b73b8b609966..5e031a3dad00df 100644 --- a/packages/components/src/gradient-picker/stories/index.story.tsx +++ b/packages/components/src/gradient-picker/stories/index.story.tsx @@ -22,7 +22,7 @@ const meta: Meta< typeof GradientPicker > = { actions: { argTypesRegex: '^on.*' }, }, argTypes: { - value: { control: { type: null } }, + value: { control: { type: false } }, }, }; export default meta; diff --git a/packages/components/src/grid/stories/index.story.tsx b/packages/components/src/grid/stories/index.story.tsx index 171b324e033c04..781fd04a67c284 100644 --- a/packages/components/src/grid/stories/index.story.tsx +++ b/packages/components/src/grid/stories/index.story.tsx @@ -15,7 +15,7 @@ const meta: Meta< typeof Grid > = { argTypes: { as: { control: { type: 'text' } }, align: { control: { type: 'text' } }, - children: { control: { type: null } }, + children: { control: { type: false } }, columnGap: { control: { type: 'text' } }, columns: { table: { type: { summary: 'number' } }, diff --git a/packages/components/src/h-stack/stories/index.story.tsx b/packages/components/src/h-stack/stories/index.story.tsx index 025c3384bddceb..bf13cb19471ff0 100644 --- a/packages/components/src/h-stack/stories/index.story.tsx +++ b/packages/components/src/h-stack/stories/index.story.tsx @@ -46,10 +46,10 @@ const meta: Meta< typeof HStack > = { id: 'components-experimental-hstack', argTypes: { as: { - control: { type: null }, + control: { type: false }, }, children: { - control: { type: null }, + control: { type: false }, }, alignment: { control: { type: 'select' }, diff --git a/packages/components/src/input-control/stories/index.story.tsx b/packages/components/src/input-control/stories/index.story.tsx index 8cef6a5d37c81b..38fc03f13f0049 100644 --- a/packages/components/src/input-control/stories/index.story.tsx +++ b/packages/components/src/input-control/stories/index.story.tsx @@ -23,10 +23,10 @@ const meta: Meta< typeof InputControl > = { subcomponents: { InputControlPrefixWrapper, InputControlSuffixWrapper }, argTypes: { __unstableInputWidth: { control: { type: 'text' } }, - __unstableStateReducer: { control: { type: null } }, - onChange: { control: { type: null } }, - prefix: { control: { type: null } }, - suffix: { control: { type: null } }, + __unstableStateReducer: { control: { type: false } }, + onChange: { control: { type: false } }, + prefix: { control: { type: false } }, + suffix: { control: { type: false } }, type: { control: { type: 'text' } }, value: { control: { disable: true } }, }, diff --git a/packages/components/src/item-group/stories/index.story.tsx b/packages/components/src/item-group/stories/index.story.tsx index 99309b81ea314f..3f1f310163db81 100644 --- a/packages/components/src/item-group/stories/index.story.tsx +++ b/packages/components/src/item-group/stories/index.story.tsx @@ -17,8 +17,8 @@ const meta: Meta< typeof ItemGroup > = { subcomponents: { Item }, title: 'Components (Experimental)/ItemGroup', argTypes: { - as: { control: { type: null } }, - children: { control: { type: null } }, + as: { control: { type: false } }, + children: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/menu-group/stories/index.story.tsx b/packages/components/src/menu-group/stories/index.story.tsx index f53cbbf5b7b0a0..f24fcac19982e1 100644 --- a/packages/components/src/menu-group/stories/index.story.tsx +++ b/packages/components/src/menu-group/stories/index.story.tsx @@ -20,7 +20,7 @@ const meta: Meta< typeof MenuGroup > = { component: MenuGroup, id: 'components-menugroup', argTypes: { - children: { control: { type: null } }, + children: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/menu-item/stories/index.story.tsx b/packages/components/src/menu-item/stories/index.story.tsx index 24c592b66f3aea..2f96cb33752933 100644 --- a/packages/components/src/menu-item/stories/index.story.tsx +++ b/packages/components/src/menu-item/stories/index.story.tsx @@ -20,7 +20,7 @@ const meta: Meta< typeof MenuItem > = { title: 'Components/Actions/MenuItem', id: 'components-menuitem', argTypes: { - children: { control: { type: null } }, + children: { control: { type: false } }, icon: { control: { type: 'select' }, options: [ 'check', 'link', 'more' ], diff --git a/packages/components/src/menu-items-choice/stories/index.story.tsx b/packages/components/src/menu-items-choice/stories/index.story.tsx index f4a14054e8f27f..c1b88444a1bdcf 100644 --- a/packages/components/src/menu-items-choice/stories/index.story.tsx +++ b/packages/components/src/menu-items-choice/stories/index.story.tsx @@ -21,7 +21,7 @@ const meta: Meta< typeof MenuItemsChoice > = { argTypes: { onHover: { action: 'onHover' }, onSelect: { action: 'onSelect' }, - value: { control: { type: null } }, + value: { control: { type: false } }, }, parameters: { controls: { diff --git a/packages/components/src/menu/stories/index.story.tsx b/packages/components/src/menu/stories/index.story.tsx index 92501c33269580..34fae3a8d215e1 100644 --- a/packages/components/src/menu/stories/index.story.tsx +++ b/packages/components/src/menu/stories/index.story.tsx @@ -46,8 +46,8 @@ const meta: Meta< typeof Menu > = { ItemHelpText: Menu.ItemHelpText, }, argTypes: { - children: { control: { type: null } }, - trigger: { control: { type: null } }, + children: { control: { type: false } }, + trigger: { control: { type: false } }, }, tags: [ 'status-private' ], parameters: { diff --git a/packages/components/src/modal/stories/index.story.tsx b/packages/components/src/modal/stories/index.story.tsx index 880688ed5c51c3..20d16701af337f 100644 --- a/packages/components/src/modal/stories/index.story.tsx +++ b/packages/components/src/modal/stories/index.story.tsx @@ -23,10 +23,10 @@ const meta: Meta< typeof Modal > = { id: 'components-modal', argTypes: { children: { - control: { type: null }, + control: { type: false }, }, onKeyDown: { - control: { type: null }, + control: { type: false }, }, focusOnMount: { options: [ true, false, 'firstElement', 'firstContentElement' ], diff --git a/packages/components/src/navigable-container/stories/navigable-menu.story.tsx b/packages/components/src/navigable-container/stories/navigable-menu.story.tsx index 2ad7e028d6faf1..05d71e56e754a3 100644 --- a/packages/components/src/navigable-container/stories/navigable-menu.story.tsx +++ b/packages/components/src/navigable-container/stories/navigable-menu.story.tsx @@ -13,7 +13,7 @@ const meta: Meta< typeof NavigableMenu > = { id: 'components-navigablemenu', component: NavigableMenu, argTypes: { - children: { control: { type: null } }, + children: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/navigable-container/stories/tabbable-container.story.tsx b/packages/components/src/navigable-container/stories/tabbable-container.story.tsx index 07c87a0c20f1bf..69a09d78c9b620 100644 --- a/packages/components/src/navigable-container/stories/tabbable-container.story.tsx +++ b/packages/components/src/navigable-container/stories/tabbable-container.story.tsx @@ -13,7 +13,7 @@ const meta: Meta< typeof TabbableContainer > = { id: 'components-tabbablecontainer', component: TabbableContainer, argTypes: { - children: { control: { type: null } }, + children: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/navigation/stories/index.story.tsx b/packages/components/src/navigation/stories/index.story.tsx index 2f09ace29f16e5..3dd5c02f416b21 100644 --- a/packages/components/src/navigation/stories/index.story.tsx +++ b/packages/components/src/navigation/stories/index.story.tsx @@ -39,10 +39,10 @@ const meta: Meta< typeof Navigation > = { NavigationMenu, }, argTypes: { - activeItem: { control: { type: null } }, - activeMenu: { control: { type: null } }, - children: { control: { type: null } }, - onActivateMenu: { control: { type: null } }, + activeItem: { control: { type: false } }, + activeMenu: { control: { type: false } }, + children: { control: { type: false } }, + onActivateMenu: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/navigator/stories/index.story.tsx b/packages/components/src/navigator/stories/index.story.tsx index bd2cdc17a1263c..bf78b9fcc2f862 100644 --- a/packages/components/src/navigator/stories/index.story.tsx +++ b/packages/components/src/navigator/stories/index.story.tsx @@ -24,9 +24,9 @@ const meta: Meta< typeof Navigator > = { title: 'Components/Navigation/Navigator', id: 'components-navigator', argTypes: { - as: { control: { type: null } }, - children: { control: { type: null } }, - initialPath: { control: { type: null } }, + as: { control: { type: false } }, + children: { control: { type: false } }, + initialPath: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/number-control/stories/index.story.tsx b/packages/components/src/number-control/stories/index.story.tsx index 8710839fea6ea5..4d2fcf30ebcef1 100644 --- a/packages/components/src/number-control/stories/index.story.tsx +++ b/packages/components/src/number-control/stories/index.story.tsx @@ -23,7 +23,7 @@ const meta: Meta< typeof NumberControl > = { step: { control: { type: 'text' } }, suffix: { control: { type: 'text' } }, type: { control: { type: 'text' } }, - value: { control: null }, + value: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/panel/stories/index.story.tsx b/packages/components/src/panel/stories/index.story.tsx index af9cf626f8eecd..d4b159199e7b2d 100644 --- a/packages/components/src/panel/stories/index.story.tsx +++ b/packages/components/src/panel/stories/index.story.tsx @@ -23,7 +23,7 @@ const meta: Meta< typeof Panel > = { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { PanelRow, PanelBody }, argTypes: { - children: { control: { type: null } }, + children: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/placeholder/stories/index.story.tsx b/packages/components/src/placeholder/stories/index.story.tsx index 1a0db673320bca..9428299e138477 100644 --- a/packages/components/src/placeholder/stories/index.story.tsx +++ b/packages/components/src/placeholder/stories/index.story.tsx @@ -21,9 +21,9 @@ const meta: Meta< typeof Placeholder > = { component: Placeholder, title: 'Components/Placeholder', argTypes: { - children: { control: { type: null } }, - notices: { control: { type: null } }, - preview: { control: { type: null } }, + children: { control: { type: false } }, + notices: { control: { type: false } }, + preview: { control: { type: false } }, icon: { control: { type: 'select' }, options: Object.keys( ICONS ), diff --git a/packages/components/src/popover/stories/index.story.tsx b/packages/components/src/popover/stories/index.story.tsx index 3d804f5d24d5c0..3b783ec9f9746b 100644 --- a/packages/components/src/popover/stories/index.story.tsx +++ b/packages/components/src/popover/stories/index.story.tsx @@ -37,18 +37,18 @@ const meta: Meta< typeof Popover > = { id: 'components-popover', component: Popover, argTypes: { - anchor: { control: { type: null } }, - anchorRef: { control: { type: null } }, - anchorRect: { control: { type: null } }, - children: { control: { type: null } }, + anchor: { control: { type: false } }, + anchorRef: { control: { type: false } }, + anchorRect: { control: { type: false } }, + children: { control: { type: false } }, focusOnMount: { control: { type: 'select' }, options: [ 'firstElement', true, false ], }, - getAnchorRect: { control: { type: null } }, + getAnchorRect: { control: { type: false } }, onClose: { action: 'onClose' }, onFocusOutside: { action: 'onFocusOutside' }, - __unstableSlotName: { control: { type: null } }, + __unstableSlotName: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/query-controls/stories/index.story.tsx b/packages/components/src/query-controls/stories/index.story.tsx index 04fe185a59eac1..d89d91ecd02bde 100644 --- a/packages/components/src/query-controls/stories/index.story.tsx +++ b/packages/components/src/query-controls/stories/index.story.tsx @@ -22,12 +22,12 @@ const meta: Meta< typeof QueryControls > = { title: 'Components/QueryControls', component: QueryControls, argTypes: { - numberOfItems: { control: { type: null } }, - order: { control: { type: null } }, - orderBy: { control: { type: null } }, - selectedAuthorId: { control: { type: null } }, - selectedCategories: { control: { type: null } }, - selectedCategoryId: { control: { type: null } }, + numberOfItems: { control: { type: false } }, + order: { control: { type: false } }, + orderBy: { control: { type: false } }, + selectedAuthorId: { control: { type: false } }, + selectedCategories: { control: { type: false } }, + selectedCategoryId: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/radio-control/stories/index.story.tsx b/packages/components/src/radio-control/stories/index.story.tsx index 3c76f7610d0d79..6291f8fe5cbe33 100644 --- a/packages/components/src/radio-control/stories/index.story.tsx +++ b/packages/components/src/radio-control/stories/index.story.tsx @@ -22,7 +22,7 @@ const meta: Meta< typeof RadioControl > = { action: 'onChange', }, selected: { - control: { type: null }, + control: { type: false }, }, label: { control: { type: 'text' }, diff --git a/packages/components/src/radio-group/stories/index.story.tsx b/packages/components/src/radio-group/stories/index.story.tsx index a19fb077e7ec46..d453acfb81d755 100644 --- a/packages/components/src/radio-group/stories/index.story.tsx +++ b/packages/components/src/radio-group/stories/index.story.tsx @@ -21,8 +21,8 @@ const meta: Meta< typeof RadioGroup > = { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { Radio }, argTypes: { - onChange: { control: { type: null } }, - children: { control: { type: null } }, + onChange: { control: { type: false } }, + children: { control: { type: false } }, checked: { control: { type: 'text' } }, }, parameters: { @@ -99,5 +99,5 @@ Controlled.args = { id: 'controlled-radiogroup', }; Controlled.argTypes = { - checked: { control: { type: null } }, + checked: { control: { type: false } }, }; diff --git a/packages/components/src/range-control/stories/index.story.tsx b/packages/components/src/range-control/stories/index.story.tsx index 86a2609b8db649..fd2ab67e652f12 100644 --- a/packages/components/src/range-control/stories/index.story.tsx +++ b/packages/components/src/range-control/stories/index.story.tsx @@ -33,18 +33,18 @@ const meta: Meta< typeof RangeControl > = { }, color: { control: { type: 'color' } }, help: { control: { type: 'text' } }, - icon: { control: { type: null } }, + icon: { control: { type: false } }, marks: { control: { type: 'object' } }, - onBlur: { control: { type: null } }, - onChange: { control: { type: null } }, - onFocus: { control: { type: null } }, - onMouseLeave: { control: { type: null } }, - onMouseMove: { control: { type: null } }, + onBlur: { control: { type: false } }, + onChange: { control: { type: false } }, + onFocus: { control: { type: false } }, + onMouseLeave: { control: { type: false } }, + onMouseMove: { control: { type: false } }, railColor: { control: { type: 'color' } }, step: { control: { type: 'number' } }, trackColor: { control: { type: 'color' } }, type: { control: { type: 'check' }, options: [ 'stepper' ] }, - value: { control: { type: null } }, + value: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/resizable-box/stories/index.story.tsx b/packages/components/src/resizable-box/stories/index.story.tsx index 489a094c33f119..9b00004bfc1b5d 100644 --- a/packages/components/src/resizable-box/stories/index.story.tsx +++ b/packages/components/src/resizable-box/stories/index.story.tsx @@ -18,7 +18,7 @@ const meta: Meta< typeof ResizableBox > = { id: 'components-resizablebox', component: ResizableBox, argTypes: { - children: { control: { type: null } }, + children: { control: { type: false } }, enable: { control: 'object' }, onResizeStop: { action: 'onResizeStop' }, }, diff --git a/packages/components/src/responsive-wrapper/stories/index.story.tsx b/packages/components/src/responsive-wrapper/stories/index.story.tsx index d684a00c870028..cee9c571896513 100644 --- a/packages/components/src/responsive-wrapper/stories/index.story.tsx +++ b/packages/components/src/responsive-wrapper/stories/index.story.tsx @@ -13,7 +13,7 @@ const meta: Meta< typeof ResponsiveWrapper > = { title: 'Components/Layout/ResponsiveWrapper', id: 'components-responsivewrapper', argTypes: { - children: { control: { type: null } }, + children: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/sandbox/stories/index.story.tsx b/packages/components/src/sandbox/stories/index.story.tsx index 0d083eac3e9026..21cdb529ae9e23 100644 --- a/packages/components/src/sandbox/stories/index.story.tsx +++ b/packages/components/src/sandbox/stories/index.story.tsx @@ -13,7 +13,7 @@ const meta: Meta< typeof SandBox > = { title: 'Components/Utilities/SandBox', id: 'components-sandbox', argTypes: { - onFocus: { control: { type: null } }, + onFocus: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/scrollable/stories/index.story.tsx b/packages/components/src/scrollable/stories/index.story.tsx index 53d4919de3aabf..4c9d0eaa786c40 100644 --- a/packages/components/src/scrollable/stories/index.story.tsx +++ b/packages/components/src/scrollable/stories/index.story.tsx @@ -22,7 +22,7 @@ const meta: Meta< typeof Scrollable > = { control: { type: 'text' }, }, children: { - control: { type: null }, + control: { type: false }, }, }, parameters: { diff --git a/packages/components/src/search-control/stories/index.story.tsx b/packages/components/src/search-control/stories/index.story.tsx index 5e5f6b594e73e7..46b45c1cbd5d71 100644 --- a/packages/components/src/search-control/stories/index.story.tsx +++ b/packages/components/src/search-control/stories/index.story.tsx @@ -19,7 +19,7 @@ const meta: Meta< typeof SearchControl > = { component: SearchControl, argTypes: { onChange: { action: 'onChange' }, - value: { control: { type: null } }, + value: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/select-control/stories/index.story.tsx b/packages/components/src/select-control/stories/index.story.tsx index e9461ef6904f6f..6f60977eaa1fe0 100644 --- a/packages/components/src/select-control/stories/index.story.tsx +++ b/packages/components/src/select-control/stories/index.story.tsx @@ -23,7 +23,7 @@ const meta: Meta< typeof SelectControl > = { label: { control: { type: 'text' } }, prefix: { control: { type: 'text' } }, suffix: { control: { type: 'text' } }, - value: { control: { type: null } }, + value: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/slot-fill/stories/index.story.tsx b/packages/components/src/slot-fill/stories/index.story.tsx index bc6c4f57ad9ce1..c727ba543e6086 100644 --- a/packages/components/src/slot-fill/stories/index.story.tsx +++ b/packages/components/src/slot-fill/stories/index.story.tsx @@ -20,9 +20,9 @@ const meta: Meta< typeof Slot > = { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { Fill, SlotFillProvider }, argTypes: { - name: { control: { type: null } }, + name: { control: { type: false } }, as: { control: { type: 'text' } }, - fillProps: { control: { type: null } }, + fillProps: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/snackbar/stories/index.story.tsx b/packages/components/src/snackbar/stories/index.story.tsx index 9bd1dae42b71be..acfb58e9b3f237 100644 --- a/packages/components/src/snackbar/stories/index.story.tsx +++ b/packages/components/src/snackbar/stories/index.story.tsx @@ -19,17 +19,17 @@ const meta: Meta< typeof Snackbar > = { id: 'components-snackbar', component: Snackbar, argTypes: { - as: { control: { type: null } }, + as: { control: { type: false } }, onRemove: { action: 'onRemove', - control: { type: null }, + control: { type: false }, }, onDismiss: { action: 'onDismiss', - control: { type: null }, + control: { type: false }, }, listRef: { - control: { type: null }, + control: { type: false }, }, }, parameters: { diff --git a/packages/components/src/snackbar/stories/list.story.tsx b/packages/components/src/snackbar/stories/list.story.tsx index 1f93f374ec1745..fb6aa7cc97ead4 100644 --- a/packages/components/src/snackbar/stories/list.story.tsx +++ b/packages/components/src/snackbar/stories/list.story.tsx @@ -18,10 +18,10 @@ const meta: Meta< typeof SnackbarList > = { id: 'components-snackbarlist', component: SnackbarList, argTypes: { - as: { control: { type: null } }, + as: { control: { type: false } }, onRemove: { action: 'onRemove', - control: { type: null }, + control: { type: false }, }, }, parameters: { diff --git a/packages/components/src/surface/stories/index.story.tsx b/packages/components/src/surface/stories/index.story.tsx index 7f6790d09c848e..4237fe09cc8512 100644 --- a/packages/components/src/surface/stories/index.story.tsx +++ b/packages/components/src/surface/stories/index.story.tsx @@ -13,7 +13,7 @@ const meta: Meta< typeof Surface > = { component: Surface, title: 'Components (Experimental)/Surface', argTypes: { - children: { control: { type: null } }, + children: { control: { type: false } }, as: { control: { type: 'text' } }, }, parameters: { diff --git a/packages/components/src/text-control/stories/index.story.tsx b/packages/components/src/text-control/stories/index.story.tsx index 481ae714f0ce2f..05e9493d7126a4 100644 --- a/packages/components/src/text-control/stories/index.story.tsx +++ b/packages/components/src/text-control/stories/index.story.tsx @@ -21,7 +21,7 @@ const meta: Meta< typeof TextControl > = { help: { control: { type: 'text' } }, label: { control: { type: 'text' } }, onChange: { action: 'onChange' }, - value: { control: { type: null } }, + value: { control: { type: false } }, }, parameters: { controls: { diff --git a/packages/components/src/textarea-control/stories/index.story.tsx b/packages/components/src/textarea-control/stories/index.story.tsx index c303883a92c5d7..ccb0fabb1cb8e9 100644 --- a/packages/components/src/textarea-control/stories/index.story.tsx +++ b/packages/components/src/textarea-control/stories/index.story.tsx @@ -21,7 +21,7 @@ const meta: Meta< typeof TextareaControl > = { onChange: { action: 'onChange' }, label: { control: { type: 'text' } }, help: { control: { type: 'text' } }, - value: { control: { type: null } }, + value: { control: { type: false } }, }, parameters: { controls: { diff --git a/packages/components/src/toggle-control/stories/index.story.tsx b/packages/components/src/toggle-control/stories/index.story.tsx index b9db0474bc7603..d731ccc066fb0c 100644 --- a/packages/components/src/toggle-control/stories/index.story.tsx +++ b/packages/components/src/toggle-control/stories/index.story.tsx @@ -18,7 +18,7 @@ const meta: Meta< typeof ToggleControl > = { id: 'components-togglecontrol', component: ToggleControl, argTypes: { - checked: { control: { type: null } }, + checked: { control: { type: false } }, help: { control: { type: 'text' } }, label: { control: { type: 'text' } }, onChange: { action: 'onChange' }, diff --git a/packages/components/src/toggle-group-control/stories/index.story.tsx b/packages/components/src/toggle-group-control/stories/index.story.tsx index bd6c67e2538870..a2e15a5cdc540b 100644 --- a/packages/components/src/toggle-group-control/stories/index.story.tsx +++ b/packages/components/src/toggle-group-control/stories/index.story.tsx @@ -32,7 +32,7 @@ const meta: Meta< typeof ToggleGroupControl > = { argTypes: { help: { control: { type: 'text' } }, onChange: { action: 'onChange' }, - value: { control: { type: null } }, + value: { control: { type: false } }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/toolbar/stories/index.story.tsx b/packages/components/src/toolbar/stories/index.story.tsx index e4fb3b07e1c904..b374fa5931fdec 100644 --- a/packages/components/src/toolbar/stories/index.story.tsx +++ b/packages/components/src/toolbar/stories/index.story.tsx @@ -51,7 +51,7 @@ const meta: Meta< typeof Toolbar > = { ToolbarDropdownMenu, }, argTypes: { - children: { control: { type: null } }, + children: { control: { type: false } }, variant: { options: [ undefined, 'unstyled' ], control: { type: 'radio' }, diff --git a/packages/components/src/tools-panel/stories/index.story.tsx b/packages/components/src/tools-panel/stories/index.story.tsx index 0fbdae794d838d..4ea70fcad899e4 100644 --- a/packages/components/src/tools-panel/stories/index.story.tsx +++ b/packages/components/src/tools-panel/stories/index.story.tsx @@ -31,9 +31,9 @@ const meta: Meta< typeof ToolsPanel > = { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { ToolsPanelItem }, argTypes: { - as: { control: { type: null } }, - children: { control: { type: null } }, - panelId: { control: { type: null } }, + as: { control: { type: false } }, + children: { control: { type: false } }, + panelId: { control: { type: false } }, resetAll: { action: 'resetAll' }, }, parameters: { diff --git a/packages/components/src/tooltip/stories/index.story.tsx b/packages/components/src/tooltip/stories/index.story.tsx index 4bddba0ff7b666..ae676dc148a722 100644 --- a/packages/components/src/tooltip/stories/index.story.tsx +++ b/packages/components/src/tooltip/stories/index.story.tsx @@ -19,7 +19,7 @@ const meta: Meta< typeof Tooltip > = { id: 'components-tooltip', component: Tooltip, argTypes: { - children: { control: { type: null } }, + children: { control: { type: false } }, position: { control: { type: 'select' }, options: [ diff --git a/packages/components/src/tree-grid/stories/index.story.tsx b/packages/components/src/tree-grid/stories/index.story.tsx index 5a1ed95e1fd627..eddaeda514fdec 100644 --- a/packages/components/src/tree-grid/stories/index.story.tsx +++ b/packages/components/src/tree-grid/stories/index.story.tsx @@ -22,7 +22,7 @@ const meta: Meta< typeof TreeGrid > = { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { TreeGridRow, TreeGridCell }, argTypes: { - children: { control: { type: null } }, + children: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/tree-select/stories/index.story.tsx b/packages/components/src/tree-select/stories/index.story.tsx index 703147dc145344..23cb1b9e5aca45 100644 --- a/packages/components/src/tree-select/stories/index.story.tsx +++ b/packages/components/src/tree-select/stories/index.story.tsx @@ -22,7 +22,7 @@ const meta: Meta< typeof TreeSelect > = { label: { control: { type: 'text' } }, prefix: { control: { type: 'text' } }, suffix: { control: { type: 'text' } }, - selectedId: { control: { type: null } }, + selectedId: { control: { type: false } }, }, parameters: { controls: { diff --git a/packages/components/src/unit-control/stories/index.story.tsx b/packages/components/src/unit-control/stories/index.story.tsx index 87628c46441169..b6710fb770229e 100644 --- a/packages/components/src/unit-control/stories/index.story.tsx +++ b/packages/components/src/unit-control/stories/index.story.tsx @@ -20,11 +20,11 @@ const meta: Meta< typeof UnitControl > = { id: 'components-experimental-unitcontrol', argTypes: { __unstableInputWidth: { control: { type: 'text' } }, - __unstableStateReducer: { control: { type: null } }, - onChange: { control: { type: null } }, - onUnitChange: { control: { type: null } }, + __unstableStateReducer: { control: { type: false } }, + onChange: { control: { type: false } }, + onUnitChange: { control: { type: false } }, prefix: { control: { type: 'text' } }, - value: { control: { type: null } }, + value: { control: { type: false } }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/view/stories/index.story.tsx b/packages/components/src/view/stories/index.story.tsx index 324825059deb20..96060a3871f5a5 100644 --- a/packages/components/src/view/stories/index.story.tsx +++ b/packages/components/src/view/stories/index.story.tsx @@ -12,7 +12,7 @@ const meta: Meta< typeof View > = { component: View, title: 'Components (Experimental)/View', argTypes: { - as: { control: { type: null } }, + as: { control: { type: false } }, children: { control: { type: 'text' } }, }, parameters: { diff --git a/packages/components/src/visually-hidden/stories/index.story.tsx b/packages/components/src/visually-hidden/stories/index.story.tsx index 6ebcf9a2e949ce..8c88a89f5efa3b 100644 --- a/packages/components/src/visually-hidden/stories/index.story.tsx +++ b/packages/components/src/visually-hidden/stories/index.story.tsx @@ -13,7 +13,7 @@ const meta: Meta< typeof VisuallyHidden > = { title: 'Components/Typography/VisuallyHidden', id: 'components-visuallyhidden', argTypes: { - children: { control: { type: null } }, + children: { control: { type: false } }, as: { control: { type: 'text' } }, }, parameters: { diff --git a/packages/components/src/z-stack/stories/index.story.tsx b/packages/components/src/z-stack/stories/index.story.tsx index 46a364bc520f32..1c8fa1712d0c14 100644 --- a/packages/components/src/z-stack/stories/index.story.tsx +++ b/packages/components/src/z-stack/stories/index.story.tsx @@ -16,7 +16,7 @@ const meta: Meta< typeof ZStack > = { title: 'Components (Experimental)/ZStack', argTypes: { as: { control: { type: 'text' } }, - children: { control: { type: null } }, + children: { control: { type: false } }, }, parameters: { controls: { From f45e35da9bf7c633411f2690853a783472e3cfb7 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 5 Dec 2024 19:10:00 +0200 Subject: [PATCH 1874/1908] Storybook: Fix control types (#67646) * Storybook: Update false control types to undefined * Fix control definition Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> --- .../stories/aliginment-toolbar.story.js | 4 ++-- .../alignment-control/stories/index.story.js | 4 ++-- .../stories/aspect-ratio-tool.story.js | 2 +- .../dimensions-tool/stories/index.story.js | 2 +- .../dimensions-tool/stories/scale-tool.story.js | 2 +- .../stories/width-height-tool.story.js | 2 +- .../resolution-tool/stories/index.story.js | 2 +- .../text-alignment-control/stories/index.story.js | 2 +- .../stories/index.story.tsx | 4 ++-- .../angle-picker-control/stories/index.story.tsx | 4 ++-- .../src/base-control/stories/index.story.tsx | 2 +- .../src/border-box-control/stories/index.story.tsx | 2 +- .../src/border-control/stories/index.story.tsx | 2 +- .../src/box-control/stories/index.story.tsx | 2 +- .../src/button-group/stories/index.story.tsx | 2 +- .../components/src/card/stories/index.story.tsx | 4 ++-- .../src/checkbox-control/stories/index.story.tsx | 2 +- .../circular-option-picker/stories/index.story.tsx | 4 ++-- .../src/color-palette/stories/index.story.tsx | 6 +++--- .../src/color-picker/stories/index.story.tsx | 4 ++-- .../src/combobox-control/stories/index.story.tsx | 2 +- .../src/composite/stories/index.story.tsx | 6 +++--- .../src/confirm-dialog/stories/index.story.tsx | 2 +- .../stories/index.story.tsx | 4 ++-- .../custom-select-control/stories/index.story.tsx | 4 ++-- .../src/date-time/stories/date-time.story.tsx | 2 +- .../src/date-time/stories/date.story.tsx | 2 +- .../src/date-time/stories/time.story.tsx | 2 +- .../src/dimension-control/stories/index.story.tsx | 2 +- .../src/disabled/stories/index.story.tsx | 4 ++-- .../components/src/divider/stories/index.story.tsx | 2 +- .../src/draggable/stories/index.story.tsx | 4 ++-- .../src/dropdown-menu/stories/index.story.tsx | 6 +++--- .../src/dropdown/stories/index.story.tsx | 14 +++++++------- .../stories/duotone-picker.story.tsx | 2 +- .../components/src/flex/stories/index.story.tsx | 2 +- .../src/font-size-picker/stories/index.story.tsx | 2 +- .../src/form-file-upload/stories/index.story.tsx | 6 +++--- .../src/form-token-field/stories/index.story.tsx | 4 ++-- .../src/gradient-picker/stories/index.story.tsx | 2 +- .../components/src/grid/stories/index.story.tsx | 2 +- .../components/src/h-stack/stories/index.story.tsx | 4 ++-- .../src/input-control/stories/index.story.tsx | 8 ++++---- .../src/item-group/stories/index.story.tsx | 4 ++-- .../src/menu-group/stories/index.story.tsx | 2 +- .../src/menu-item/stories/index.story.tsx | 2 +- .../src/menu-items-choice/stories/index.story.tsx | 2 +- .../components/src/menu/stories/index.story.tsx | 4 ++-- .../components/src/modal/stories/index.story.tsx | 4 ++-- .../stories/navigable-menu.story.tsx | 2 +- .../stories/tabbable-container.story.tsx | 2 +- .../src/navigation/stories/index.story.tsx | 8 ++++---- .../src/navigator/stories/index.story.tsx | 6 +++--- .../src/number-control/stories/index.story.tsx | 2 +- .../components/src/panel/stories/index.story.tsx | 2 +- .../src/placeholder/stories/index.story.tsx | 6 +++--- .../components/src/popover/stories/index.story.tsx | 12 ++++++------ .../src/query-controls/stories/index.story.tsx | 12 ++++++------ .../src/radio-control/stories/index.story.tsx | 2 +- .../src/radio-group/stories/index.story.tsx | 6 +++--- .../src/range-control/stories/index.story.tsx | 14 +++++++------- .../src/resizable-box/stories/index.story.tsx | 2 +- .../src/responsive-wrapper/stories/index.story.tsx | 2 +- .../components/src/sandbox/stories/index.story.tsx | 2 +- .../src/scrollable/stories/index.story.tsx | 2 +- .../src/search-control/stories/index.story.tsx | 2 +- .../src/select-control/stories/index.story.tsx | 2 +- .../src/slot-fill/stories/index.story.tsx | 4 ++-- .../src/snackbar/stories/index.story.tsx | 8 ++++---- .../components/src/snackbar/stories/list.story.tsx | 4 ++-- .../components/src/surface/stories/index.story.tsx | 2 +- .../src/text-control/stories/index.story.tsx | 2 +- .../src/textarea-control/stories/index.story.tsx | 2 +- .../src/toggle-control/stories/index.story.tsx | 2 +- .../toggle-group-control/stories/index.story.tsx | 2 +- .../components/src/toolbar/stories/index.story.tsx | 2 +- .../src/tools-panel/stories/index.story.tsx | 6 +++--- .../components/src/tooltip/stories/index.story.tsx | 2 +- .../src/tree-grid/stories/index.story.tsx | 2 +- .../src/tree-select/stories/index.story.tsx | 2 +- .../src/unit-control/stories/index.story.tsx | 8 ++++---- .../components/src/view/stories/index.story.tsx | 2 +- .../src/visually-hidden/stories/index.story.tsx | 2 +- .../components/src/z-stack/stories/index.story.tsx | 2 +- 84 files changed, 152 insertions(+), 152 deletions(-) diff --git a/packages/block-editor/src/components/alignment-control/stories/aliginment-toolbar.story.js b/packages/block-editor/src/components/alignment-control/stories/aliginment-toolbar.story.js index a02f0ec3dfbce0..9d029c30b48466 100644 --- a/packages/block-editor/src/components/alignment-control/stories/aliginment-toolbar.story.js +++ b/packages/block-editor/src/components/alignment-control/stories/aliginment-toolbar.story.js @@ -16,13 +16,13 @@ const meta = { component: AlignmentToolbar, argTypes: { value: { - control: { type: false }, + control: false, defaultValue: 'undefined', description: 'The current value of the alignment setting.', }, onChange: { action: 'onChange', - control: { type: false }, + control: false, description: "A callback function invoked when the toolbar's alignment value is changed via an interaction with any of the toolbar's buttons. Called with the new alignment value (ie: `left`, `center`, `right`, `undefined`) as the only argument.", }, diff --git a/packages/block-editor/src/components/alignment-control/stories/index.story.js b/packages/block-editor/src/components/alignment-control/stories/index.story.js index ad403dcab43857..165f9343e1710b 100644 --- a/packages/block-editor/src/components/alignment-control/stories/index.story.js +++ b/packages/block-editor/src/components/alignment-control/stories/index.story.js @@ -20,13 +20,13 @@ const meta = { component: AlignmentControl, argTypes: { value: { - control: { type: false }, + control: false, defaultValue: 'undefined', description: 'The current value of the alignment setting.', }, onChange: { action: 'onChange', - control: { type: false }, + control: false, description: "A callback function invoked when the toolbar's alignment value is changed via an interaction with any of the toolbar's buttons. Called with the new alignment value (ie: `left`, `center`, `right`, `undefined`) as the only argument.", }, diff --git a/packages/block-editor/src/components/dimensions-tool/stories/aspect-ratio-tool.story.js b/packages/block-editor/src/components/dimensions-tool/stories/aspect-ratio-tool.story.js index 2acaddb57a6cd5..b853d780052942 100644 --- a/packages/block-editor/src/components/dimensions-tool/stories/aspect-ratio-tool.story.js +++ b/packages/block-editor/src/components/dimensions-tool/stories/aspect-ratio-tool.story.js @@ -16,7 +16,7 @@ export default { title: 'BlockEditor (Private APIs)/DimensionsTool/AspectRatioTool', component: AspectRatioTool, argTypes: { - panelId: { control: { type: false } }, + panelId: { control: false }, onChange: { action: 'changed' }, }, }; diff --git a/packages/block-editor/src/components/dimensions-tool/stories/index.story.js b/packages/block-editor/src/components/dimensions-tool/stories/index.story.js index 270a6b1ae4b37a..ebf08fba0c686b 100644 --- a/packages/block-editor/src/components/dimensions-tool/stories/index.story.js +++ b/packages/block-editor/src/components/dimensions-tool/stories/index.story.js @@ -16,7 +16,7 @@ export default { title: 'BlockEditor (Private APIs)/DimensionsTool', component: DimensionsTool, argTypes: { - panelId: { control: { type: false } }, + panelId: { control: false }, onChange: { action: 'changed' }, }, }; diff --git a/packages/block-editor/src/components/dimensions-tool/stories/scale-tool.story.js b/packages/block-editor/src/components/dimensions-tool/stories/scale-tool.story.js index fe354168d2ae8d..b485bf68a892d9 100644 --- a/packages/block-editor/src/components/dimensions-tool/stories/scale-tool.story.js +++ b/packages/block-editor/src/components/dimensions-tool/stories/scale-tool.story.js @@ -16,7 +16,7 @@ export default { title: 'BlockEditor (Private APIs)/DimensionsTool/ScaleTool', component: ScaleTool, argTypes: { - panelId: { control: { type: false } }, + panelId: { control: false }, onChange: { action: 'changed' }, }, }; diff --git a/packages/block-editor/src/components/dimensions-tool/stories/width-height-tool.story.js b/packages/block-editor/src/components/dimensions-tool/stories/width-height-tool.story.js index ea51455ed4b8e3..eed3cbc02f466e 100644 --- a/packages/block-editor/src/components/dimensions-tool/stories/width-height-tool.story.js +++ b/packages/block-editor/src/components/dimensions-tool/stories/width-height-tool.story.js @@ -16,7 +16,7 @@ export default { title: 'BlockEditor (Private APIs)/DimensionsTool/WidthHeightTool', component: WidthHeightTool, argTypes: { - panelId: { control: { type: false } }, + panelId: { control: false }, onChange: { action: 'changed' }, }, }; diff --git a/packages/block-editor/src/components/resolution-tool/stories/index.story.js b/packages/block-editor/src/components/resolution-tool/stories/index.story.js index 9700096b3f2e8e..3fedb6d6facae7 100644 --- a/packages/block-editor/src/components/resolution-tool/stories/index.story.js +++ b/packages/block-editor/src/components/resolution-tool/stories/index.story.js @@ -16,7 +16,7 @@ export default { title: 'BlockEditor (Private APIs)/ResolutionControl', component: ResolutionTool, argTypes: { - panelId: { control: { type: false } }, + panelId: { control: false }, onChange: { action: 'changed' }, }, }; diff --git a/packages/block-editor/src/components/text-alignment-control/stories/index.story.js b/packages/block-editor/src/components/text-alignment-control/stories/index.story.js index 80d04c0a96867d..3744f3fa012a71 100644 --- a/packages/block-editor/src/components/text-alignment-control/stories/index.story.js +++ b/packages/block-editor/src/components/text-alignment-control/stories/index.story.js @@ -18,7 +18,7 @@ export default { control: 'check', options: [ 'left', 'center', 'right', 'justify' ], }, - value: { control: { type: false } }, + value: { control: false }, }, }; diff --git a/packages/components/src/alignment-matrix-control/stories/index.story.tsx b/packages/components/src/alignment-matrix-control/stories/index.story.tsx index 992e79d51f1e83..e04d8b6690fe8c 100644 --- a/packages/components/src/alignment-matrix-control/stories/index.story.tsx +++ b/packages/components/src/alignment-matrix-control/stories/index.story.tsx @@ -24,8 +24,8 @@ const meta: Meta< typeof AlignmentMatrixControl > = { 'AlignmentMatrixControl.Icon': AlignmentMatrixControl.Icon, }, argTypes: { - onChange: { control: { type: false } }, - value: { control: { type: false } }, + onChange: { control: false }, + value: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/angle-picker-control/stories/index.story.tsx b/packages/components/src/angle-picker-control/stories/index.story.tsx index 9bacd4871a9687..d909f1ed3d205a 100644 --- a/packages/components/src/angle-picker-control/stories/index.story.tsx +++ b/packages/components/src/angle-picker-control/stories/index.story.tsx @@ -17,8 +17,8 @@ const meta: Meta< typeof AnglePickerControl > = { title: 'Components/AnglePickerControl', component: AnglePickerControl, argTypes: { - as: { control: { type: false } }, - value: { control: { type: false } }, + as: { control: false }, + value: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/base-control/stories/index.story.tsx b/packages/components/src/base-control/stories/index.story.tsx index 88ced86d3fe1be..69188f869656da 100644 --- a/packages/components/src/base-control/stories/index.story.tsx +++ b/packages/components/src/base-control/stories/index.story.tsx @@ -18,7 +18,7 @@ const meta: Meta< typeof BaseControl > = { 'BaseControl.VisualLabel': BaseControl.VisualLabel, }, argTypes: { - children: { control: { type: false } }, + children: { control: false }, help: { control: { type: 'text' } }, label: { control: { type: 'text' } }, }, diff --git a/packages/components/src/border-box-control/stories/index.story.tsx b/packages/components/src/border-box-control/stories/index.story.tsx index 382ee3afa626ad..3f118ae7cb37cc 100644 --- a/packages/components/src/border-box-control/stories/index.story.tsx +++ b/packages/components/src/border-box-control/stories/index.story.tsx @@ -20,7 +20,7 @@ const meta: Meta< typeof BorderBoxControl > = { component: BorderBoxControl, argTypes: { onChange: { action: 'onChange' }, - value: { control: { type: false } }, + value: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/border-control/stories/index.story.tsx b/packages/components/src/border-control/stories/index.story.tsx index 48fcd37c708d09..ca8505c01a0ba0 100644 --- a/packages/components/src/border-control/stories/index.story.tsx +++ b/packages/components/src/border-control/stories/index.story.tsx @@ -23,7 +23,7 @@ const meta: Meta< typeof BorderControl > = { action: 'onChange', }, width: { control: { type: 'text' } }, - value: { control: { type: false } }, + value: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/box-control/stories/index.story.tsx b/packages/components/src/box-control/stories/index.story.tsx index fc53b2967ac92e..0d8b96de063168 100644 --- a/packages/components/src/box-control/stories/index.story.tsx +++ b/packages/components/src/box-control/stories/index.story.tsx @@ -17,7 +17,7 @@ const meta: Meta< typeof BoxControl > = { title: 'Components/BoxControl', component: BoxControl, argTypes: { - values: { control: { type: false } }, + values: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/button-group/stories/index.story.tsx b/packages/components/src/button-group/stories/index.story.tsx index d05a32fe10e98d..4b5ab3d5dfdb6b 100644 --- a/packages/components/src/button-group/stories/index.story.tsx +++ b/packages/components/src/button-group/stories/index.story.tsx @@ -13,7 +13,7 @@ const meta: Meta< typeof ButtonGroup > = { title: 'Components/ButtonGroup', component: ButtonGroup, argTypes: { - children: { control: { type: false } }, + children: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/card/stories/index.story.tsx b/packages/components/src/card/stories/index.story.tsx index 7534ff5345858d..22fb749461785f 100644 --- a/packages/components/src/card/stories/index.story.tsx +++ b/packages/components/src/card/stories/index.story.tsx @@ -26,10 +26,10 @@ const meta: Meta< typeof Card > = { id: 'components-card', argTypes: { as: { - control: { type: false }, + control: false, }, children: { - control: { type: false }, + control: false, }, }, parameters: { diff --git a/packages/components/src/checkbox-control/stories/index.story.tsx b/packages/components/src/checkbox-control/stories/index.story.tsx index c3e45fdd62f379..a2936654c8629a 100644 --- a/packages/components/src/checkbox-control/stories/index.story.tsx +++ b/packages/components/src/checkbox-control/stories/index.story.tsx @@ -24,7 +24,7 @@ const meta: Meta< typeof CheckboxControl > = { action: 'onChange', }, checked: { - control: { type: false }, + control: false, }, help: { control: { type: 'text' } }, }, diff --git a/packages/components/src/circular-option-picker/stories/index.story.tsx b/packages/components/src/circular-option-picker/stories/index.story.tsx index ee10cb70bb55ef..84165bf24bff6c 100644 --- a/packages/components/src/circular-option-picker/stories/index.story.tsx +++ b/packages/components/src/circular-option-picker/stories/index.story.tsx @@ -32,8 +32,8 @@ const meta: Meta< typeof CircularOptionPicker > = { CircularOptionPicker.DropdownLinkAction, }, argTypes: { - actions: { control: { type: false } }, - options: { control: { type: false } }, + actions: { control: false }, + options: { control: false }, children: { control: { type: 'text' } }, }, parameters: { diff --git a/packages/components/src/color-palette/stories/index.story.tsx b/packages/components/src/color-palette/stories/index.story.tsx index 071a1cecfe1058..e4c4b89d524448 100644 --- a/packages/components/src/color-palette/stories/index.story.tsx +++ b/packages/components/src/color-palette/stories/index.story.tsx @@ -18,9 +18,9 @@ const meta: Meta< typeof ColorPalette > = { id: 'components-colorpalette', component: ColorPalette, argTypes: { - as: { control: { type: false } }, - onChange: { action: 'onChange', control: { type: false } }, - value: { control: { type: false } }, + as: { control: false }, + onChange: { action: 'onChange', control: false }, + value: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/color-picker/stories/index.story.tsx b/packages/components/src/color-picker/stories/index.story.tsx index 5277a004a9daa0..0886719a7de52c 100644 --- a/packages/components/src/color-picker/stories/index.story.tsx +++ b/packages/components/src/color-picker/stories/index.story.tsx @@ -13,8 +13,8 @@ const meta: Meta< typeof ColorPicker > = { title: 'Components/Selection & Input/Color/ColorPicker', id: 'components-colorpicker', argTypes: { - as: { control: { type: false } }, - color: { control: { type: false } }, + as: { control: false }, + color: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/combobox-control/stories/index.story.tsx b/packages/components/src/combobox-control/stories/index.story.tsx index a9ac2ffb74cb3e..f033742a336623 100644 --- a/packages/components/src/combobox-control/stories/index.story.tsx +++ b/packages/components/src/combobox-control/stories/index.story.tsx @@ -38,7 +38,7 @@ const meta: Meta< typeof ComboboxControl > = { id: 'components-comboboxcontrol', component: ComboboxControl, argTypes: { - value: { control: { type: false } }, + value: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx index 8a6fb6e1e2d862..63731a15a8c9cd 100644 --- a/packages/components/src/composite/stories/index.story.tsx +++ b/packages/components/src/composite/stories/index.story.tsx @@ -36,9 +36,9 @@ const meta: Meta< typeof Composite > = { 'Composite.Context': Composite.Context, }, argTypes: { - children: { control: { type: false } }, - render: { control: { type: false } }, - setActiveId: { control: { type: false } }, + children: { control: false }, + render: { control: false }, + setActiveId: { control: false }, focusLoop: { control: 'select', options: [ true, false, 'horizontal', 'vertical', 'both' ], diff --git a/packages/components/src/confirm-dialog/stories/index.story.tsx b/packages/components/src/confirm-dialog/stories/index.story.tsx index 93fc1f7605449f..7c08d48369a2b0 100644 --- a/packages/components/src/confirm-dialog/stories/index.story.tsx +++ b/packages/components/src/confirm-dialog/stories/index.story.tsx @@ -20,7 +20,7 @@ const meta: Meta< typeof ConfirmDialog > = { id: 'components-experimental-confirmdialog', argTypes: { isOpen: { - control: { type: false }, + control: false, }, }, parameters: { diff --git a/packages/components/src/custom-select-control-v2/stories/index.story.tsx b/packages/components/src/custom-select-control-v2/stories/index.story.tsx index e97886d67ee172..75226314af8dbd 100644 --- a/packages/components/src/custom-select-control-v2/stories/index.story.tsx +++ b/packages/components/src/custom-select-control-v2/stories/index.story.tsx @@ -22,8 +22,8 @@ const meta: Meta< typeof CustomSelectControlV2 > = { 'CustomSelectControlV2.Item': CustomSelectControlV2.Item, }, argTypes: { - children: { control: { type: false } }, - value: { control: { type: false } }, + children: { control: false }, + value: { control: false }, }, tags: [ 'status-wip' ], parameters: { diff --git a/packages/components/src/custom-select-control/stories/index.story.tsx b/packages/components/src/custom-select-control/stories/index.story.tsx index d86fd45c86b798..8c5e200f7532e8 100644 --- a/packages/components/src/custom-select-control/stories/index.story.tsx +++ b/packages/components/src/custom-select-control/stories/index.story.tsx @@ -18,8 +18,8 @@ const meta: Meta< typeof CustomSelectControl > = { component: CustomSelectControl, id: 'components-customselectcontrol', argTypes: { - onChange: { control: { type: false } }, - value: { control: { type: false } }, + onChange: { control: false }, + value: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/date-time/stories/date-time.story.tsx b/packages/components/src/date-time/stories/date-time.story.tsx index b2ee1fa8d9a9c3..0c6af3f53fa195 100644 --- a/packages/components/src/date-time/stories/date-time.story.tsx +++ b/packages/components/src/date-time/stories/date-time.story.tsx @@ -20,7 +20,7 @@ const meta: Meta< typeof DateTimePicker > = { component: DateTimePicker, argTypes: { currentDate: { control: 'date' }, - onChange: { action: 'onChange', control: { type: false } }, + onChange: { action: 'onChange', control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/date-time/stories/date.story.tsx b/packages/components/src/date-time/stories/date.story.tsx index b90d3c2da555af..ae4816809f7865 100644 --- a/packages/components/src/date-time/stories/date.story.tsx +++ b/packages/components/src/date-time/stories/date.story.tsx @@ -20,7 +20,7 @@ const meta: Meta< typeof DatePicker > = { component: DatePicker, argTypes: { currentDate: { control: 'date' }, - onChange: { action: 'onChange', control: { type: false } }, + onChange: { action: 'onChange', control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/date-time/stories/time.story.tsx b/packages/components/src/date-time/stories/time.story.tsx index c7fee061d3ef85..12e5574115a6c3 100644 --- a/packages/components/src/date-time/stories/time.story.tsx +++ b/packages/components/src/date-time/stories/time.story.tsx @@ -21,7 +21,7 @@ const meta: Meta< typeof TimePicker > = { subcomponents: { 'TimePicker.TimeInput': TimePicker.TimeInput }, argTypes: { currentTime: { control: 'date' }, - onChange: { action: 'onChange', control: { type: false } }, + onChange: { action: 'onChange', control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/dimension-control/stories/index.story.tsx b/packages/components/src/dimension-control/stories/index.story.tsx index 7b059540a883bc..086d75b198fb05 100644 --- a/packages/components/src/dimension-control/stories/index.story.tsx +++ b/packages/components/src/dimension-control/stories/index.story.tsx @@ -24,7 +24,7 @@ const meta: Meta< typeof DimensionControl > = { id: 'components-dimensioncontrol', argTypes: { onChange: { action: 'onChange' }, - value: { control: { type: false } }, + value: { control: false }, icon: { control: { type: 'select' }, options: [ '-', 'desktop', 'tablet', 'mobile' ], diff --git a/packages/components/src/disabled/stories/index.story.tsx b/packages/components/src/disabled/stories/index.story.tsx index b89026a8b548f7..7a42da71f8efe9 100644 --- a/packages/components/src/disabled/stories/index.story.tsx +++ b/packages/components/src/disabled/stories/index.story.tsx @@ -22,8 +22,8 @@ const meta: Meta< typeof Disabled > = { id: 'components-disabled', component: Disabled, argTypes: { - as: { control: { type: false } }, - children: { control: { type: false } }, + as: { control: false }, + children: { control: false }, }, parameters: { controls: { diff --git a/packages/components/src/divider/stories/index.story.tsx b/packages/components/src/divider/stories/index.story.tsx index fe3fba971b28f2..3f143fc5237694 100644 --- a/packages/components/src/divider/stories/index.story.tsx +++ b/packages/components/src/divider/stories/index.story.tsx @@ -24,7 +24,7 @@ const meta: Meta< typeof Divider > = { control: { type: 'text' }, }, wrapElement: { - control: { type: false }, + control: false, }, ref: { table: { diff --git a/packages/components/src/draggable/stories/index.story.tsx b/packages/components/src/draggable/stories/index.story.tsx index 54fdeaadd147e3..537dd9b40d7f36 100644 --- a/packages/components/src/draggable/stories/index.story.tsx +++ b/packages/components/src/draggable/stories/index.story.tsx @@ -21,8 +21,8 @@ const meta: Meta< typeof Draggable > = { title: 'Components/Utilities/Draggable', id: 'components-draggable', argTypes: { - elementId: { control: { type: false } }, - __experimentalDragComponent: { control: { type: false } }, + elementId: { control: false }, + __experimentalDragComponent: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/dropdown-menu/stories/index.story.tsx b/packages/components/src/dropdown-menu/stories/index.story.tsx index 5277d4f54a4dff..7b06ae979de84a 100644 --- a/packages/components/src/dropdown-menu/stories/index.story.tsx +++ b/packages/components/src/dropdown-menu/stories/index.story.tsx @@ -37,9 +37,9 @@ const meta: Meta< typeof DropdownMenu > = { mapping: { menu, chevronDown, more }, control: { type: 'select' }, }, - open: { control: { type: false } }, - defaultOpen: { control: { type: false } }, - onToggle: { control: { type: false } }, + open: { control: false }, + defaultOpen: { control: false }, + onToggle: { control: false }, }, }; export default meta; diff --git a/packages/components/src/dropdown/stories/index.story.tsx b/packages/components/src/dropdown/stories/index.story.tsx index 8adb10574fc876..ff4d0101a377ef 100644 --- a/packages/components/src/dropdown/stories/index.story.tsx +++ b/packages/components/src/dropdown/stories/index.story.tsx @@ -25,13 +25,13 @@ const meta: Meta< typeof Dropdown > = { type: 'radio', }, }, - position: { control: { type: false } }, - renderContent: { control: { type: false } }, - renderToggle: { control: { type: false } }, - open: { control: { type: false } }, - defaultOpen: { control: { type: false } }, - onToggle: { control: { type: false } }, - onClose: { control: { type: false } }, + position: { control: false }, + renderContent: { control: false }, + renderToggle: { control: false }, + open: { control: false }, + defaultOpen: { control: false }, + onToggle: { control: false }, + onClose: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/duotone-picker/stories/duotone-picker.story.tsx b/packages/components/src/duotone-picker/stories/duotone-picker.story.tsx index 014ab4b22443e9..bf8439c38bb854 100644 --- a/packages/components/src/duotone-picker/stories/duotone-picker.story.tsx +++ b/packages/components/src/duotone-picker/stories/duotone-picker.story.tsx @@ -19,7 +19,7 @@ const meta: Meta< typeof DuotonePicker > = { component: DuotonePicker, argTypes: { onChange: { action: 'onChange' }, - value: { control: { type: false } }, + value: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/flex/stories/index.story.tsx b/packages/components/src/flex/stories/index.story.tsx index 8f57d01c4de626..fac5b2e7c31e05 100644 --- a/packages/components/src/flex/stories/index.story.tsx +++ b/packages/components/src/flex/stories/index.story.tsx @@ -17,7 +17,7 @@ const meta: Meta< typeof Flex > = { argTypes: { align: { control: { type: 'text' } }, as: { control: { type: 'text' } }, - children: { control: { type: false } }, + children: { control: false }, gap: { control: { type: 'text' } }, justify: { control: { type: 'text' } }, // Disabled isReversed because it's deprecated. diff --git a/packages/components/src/font-size-picker/stories/index.story.tsx b/packages/components/src/font-size-picker/stories/index.story.tsx index 4bd50293788bbe..f6502fcfd537c8 100644 --- a/packages/components/src/font-size-picker/stories/index.story.tsx +++ b/packages/components/src/font-size-picker/stories/index.story.tsx @@ -17,7 +17,7 @@ const meta: Meta< typeof FontSizePicker > = { title: 'Components/FontSizePicker', component: FontSizePicker, argTypes: { - value: { control: { type: false } }, + value: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/form-file-upload/stories/index.story.tsx b/packages/components/src/form-file-upload/stories/index.story.tsx index 3f961b87b32f33..cec182346c0a72 100644 --- a/packages/components/src/form-file-upload/stories/index.story.tsx +++ b/packages/components/src/form-file-upload/stories/index.story.tsx @@ -18,9 +18,9 @@ const meta: Meta< typeof FormFileUpload > = { id: 'components-formfileupload', component: FormFileUpload, argTypes: { - icon: { control: { type: false } }, - onChange: { action: 'onChange', control: { type: false } }, - onClick: { control: { type: false } }, + icon: { control: false }, + onChange: { action: 'onChange', control: false }, + onClick: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/form-token-field/stories/index.story.tsx b/packages/components/src/form-token-field/stories/index.story.tsx index 6e895989c164b3..52daabe5608b0a 100644 --- a/packages/components/src/form-token-field/stories/index.story.tsx +++ b/packages/components/src/form-token-field/stories/index.story.tsx @@ -19,10 +19,10 @@ const meta: Meta< typeof FormTokenField > = { id: 'components-formtokenfield', argTypes: { value: { - control: { type: false }, + control: false, }, __experimentalValidateInput: { - control: { type: false }, + control: false, }, }, parameters: { diff --git a/packages/components/src/gradient-picker/stories/index.story.tsx b/packages/components/src/gradient-picker/stories/index.story.tsx index 5e031a3dad00df..7dc5f62df726db 100644 --- a/packages/components/src/gradient-picker/stories/index.story.tsx +++ b/packages/components/src/gradient-picker/stories/index.story.tsx @@ -22,7 +22,7 @@ const meta: Meta< typeof GradientPicker > = { actions: { argTypesRegex: '^on.*' }, }, argTypes: { - value: { control: { type: false } }, + value: { control: false }, }, }; export default meta; diff --git a/packages/components/src/grid/stories/index.story.tsx b/packages/components/src/grid/stories/index.story.tsx index 781fd04a67c284..5b2284e22d27e3 100644 --- a/packages/components/src/grid/stories/index.story.tsx +++ b/packages/components/src/grid/stories/index.story.tsx @@ -15,7 +15,7 @@ const meta: Meta< typeof Grid > = { argTypes: { as: { control: { type: 'text' } }, align: { control: { type: 'text' } }, - children: { control: { type: false } }, + children: { control: false }, columnGap: { control: { type: 'text' } }, columns: { table: { type: { summary: 'number' } }, diff --git a/packages/components/src/h-stack/stories/index.story.tsx b/packages/components/src/h-stack/stories/index.story.tsx index bf13cb19471ff0..a2e5b4fa55e9fa 100644 --- a/packages/components/src/h-stack/stories/index.story.tsx +++ b/packages/components/src/h-stack/stories/index.story.tsx @@ -46,10 +46,10 @@ const meta: Meta< typeof HStack > = { id: 'components-experimental-hstack', argTypes: { as: { - control: { type: false }, + control: false, }, children: { - control: { type: false }, + control: false, }, alignment: { control: { type: 'select' }, diff --git a/packages/components/src/input-control/stories/index.story.tsx b/packages/components/src/input-control/stories/index.story.tsx index 38fc03f13f0049..136301c42e7d09 100644 --- a/packages/components/src/input-control/stories/index.story.tsx +++ b/packages/components/src/input-control/stories/index.story.tsx @@ -23,10 +23,10 @@ const meta: Meta< typeof InputControl > = { subcomponents: { InputControlPrefixWrapper, InputControlSuffixWrapper }, argTypes: { __unstableInputWidth: { control: { type: 'text' } }, - __unstableStateReducer: { control: { type: false } }, - onChange: { control: { type: false } }, - prefix: { control: { type: false } }, - suffix: { control: { type: false } }, + __unstableStateReducer: { control: false }, + onChange: { control: false }, + prefix: { control: false }, + suffix: { control: false }, type: { control: { type: 'text' } }, value: { control: { disable: true } }, }, diff --git a/packages/components/src/item-group/stories/index.story.tsx b/packages/components/src/item-group/stories/index.story.tsx index 3f1f310163db81..845843d2433db9 100644 --- a/packages/components/src/item-group/stories/index.story.tsx +++ b/packages/components/src/item-group/stories/index.story.tsx @@ -17,8 +17,8 @@ const meta: Meta< typeof ItemGroup > = { subcomponents: { Item }, title: 'Components (Experimental)/ItemGroup', argTypes: { - as: { control: { type: false } }, - children: { control: { type: false } }, + as: { control: false }, + children: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/menu-group/stories/index.story.tsx b/packages/components/src/menu-group/stories/index.story.tsx index f24fcac19982e1..c46804bc999007 100644 --- a/packages/components/src/menu-group/stories/index.story.tsx +++ b/packages/components/src/menu-group/stories/index.story.tsx @@ -20,7 +20,7 @@ const meta: Meta< typeof MenuGroup > = { component: MenuGroup, id: 'components-menugroup', argTypes: { - children: { control: { type: false } }, + children: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/menu-item/stories/index.story.tsx b/packages/components/src/menu-item/stories/index.story.tsx index 2f96cb33752933..bef548c59d9461 100644 --- a/packages/components/src/menu-item/stories/index.story.tsx +++ b/packages/components/src/menu-item/stories/index.story.tsx @@ -20,7 +20,7 @@ const meta: Meta< typeof MenuItem > = { title: 'Components/Actions/MenuItem', id: 'components-menuitem', argTypes: { - children: { control: { type: false } }, + children: { control: false }, icon: { control: { type: 'select' }, options: [ 'check', 'link', 'more' ], diff --git a/packages/components/src/menu-items-choice/stories/index.story.tsx b/packages/components/src/menu-items-choice/stories/index.story.tsx index c1b88444a1bdcf..b634eb5becedbf 100644 --- a/packages/components/src/menu-items-choice/stories/index.story.tsx +++ b/packages/components/src/menu-items-choice/stories/index.story.tsx @@ -21,7 +21,7 @@ const meta: Meta< typeof MenuItemsChoice > = { argTypes: { onHover: { action: 'onHover' }, onSelect: { action: 'onSelect' }, - value: { control: { type: false } }, + value: { control: false }, }, parameters: { controls: { diff --git a/packages/components/src/menu/stories/index.story.tsx b/packages/components/src/menu/stories/index.story.tsx index 34fae3a8d215e1..ad4794057e0e03 100644 --- a/packages/components/src/menu/stories/index.story.tsx +++ b/packages/components/src/menu/stories/index.story.tsx @@ -46,8 +46,8 @@ const meta: Meta< typeof Menu > = { ItemHelpText: Menu.ItemHelpText, }, argTypes: { - children: { control: { type: false } }, - trigger: { control: { type: false } }, + children: { control: false }, + trigger: { control: false }, }, tags: [ 'status-private' ], parameters: { diff --git a/packages/components/src/modal/stories/index.story.tsx b/packages/components/src/modal/stories/index.story.tsx index 20d16701af337f..be18ed141dd3fc 100644 --- a/packages/components/src/modal/stories/index.story.tsx +++ b/packages/components/src/modal/stories/index.story.tsx @@ -23,10 +23,10 @@ const meta: Meta< typeof Modal > = { id: 'components-modal', argTypes: { children: { - control: { type: false }, + control: false, }, onKeyDown: { - control: { type: false }, + control: false, }, focusOnMount: { options: [ true, false, 'firstElement', 'firstContentElement' ], diff --git a/packages/components/src/navigable-container/stories/navigable-menu.story.tsx b/packages/components/src/navigable-container/stories/navigable-menu.story.tsx index 05d71e56e754a3..30986ff479e43f 100644 --- a/packages/components/src/navigable-container/stories/navigable-menu.story.tsx +++ b/packages/components/src/navigable-container/stories/navigable-menu.story.tsx @@ -13,7 +13,7 @@ const meta: Meta< typeof NavigableMenu > = { id: 'components-navigablemenu', component: NavigableMenu, argTypes: { - children: { control: { type: false } }, + children: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/navigable-container/stories/tabbable-container.story.tsx b/packages/components/src/navigable-container/stories/tabbable-container.story.tsx index 69a09d78c9b620..afb4119015b52a 100644 --- a/packages/components/src/navigable-container/stories/tabbable-container.story.tsx +++ b/packages/components/src/navigable-container/stories/tabbable-container.story.tsx @@ -13,7 +13,7 @@ const meta: Meta< typeof TabbableContainer > = { id: 'components-tabbablecontainer', component: TabbableContainer, argTypes: { - children: { control: { type: false } }, + children: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/navigation/stories/index.story.tsx b/packages/components/src/navigation/stories/index.story.tsx index 3dd5c02f416b21..8510b6f20b5370 100644 --- a/packages/components/src/navigation/stories/index.story.tsx +++ b/packages/components/src/navigation/stories/index.story.tsx @@ -39,10 +39,10 @@ const meta: Meta< typeof Navigation > = { NavigationMenu, }, argTypes: { - activeItem: { control: { type: false } }, - activeMenu: { control: { type: false } }, - children: { control: { type: false } }, - onActivateMenu: { control: { type: false } }, + activeItem: { control: false }, + activeMenu: { control: false }, + children: { control: false }, + onActivateMenu: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/navigator/stories/index.story.tsx b/packages/components/src/navigator/stories/index.story.tsx index bf78b9fcc2f862..0baf6a1c9cf5bf 100644 --- a/packages/components/src/navigator/stories/index.story.tsx +++ b/packages/components/src/navigator/stories/index.story.tsx @@ -24,9 +24,9 @@ const meta: Meta< typeof Navigator > = { title: 'Components/Navigation/Navigator', id: 'components-navigator', argTypes: { - as: { control: { type: false } }, - children: { control: { type: false } }, - initialPath: { control: { type: false } }, + as: { control: false }, + children: { control: false }, + initialPath: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/number-control/stories/index.story.tsx b/packages/components/src/number-control/stories/index.story.tsx index 4d2fcf30ebcef1..e66be3490bb716 100644 --- a/packages/components/src/number-control/stories/index.story.tsx +++ b/packages/components/src/number-control/stories/index.story.tsx @@ -23,7 +23,7 @@ const meta: Meta< typeof NumberControl > = { step: { control: { type: 'text' } }, suffix: { control: { type: 'text' } }, type: { control: { type: 'text' } }, - value: { control: { type: false } }, + value: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/panel/stories/index.story.tsx b/packages/components/src/panel/stories/index.story.tsx index d4b159199e7b2d..db66b911d4dc17 100644 --- a/packages/components/src/panel/stories/index.story.tsx +++ b/packages/components/src/panel/stories/index.story.tsx @@ -23,7 +23,7 @@ const meta: Meta< typeof Panel > = { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { PanelRow, PanelBody }, argTypes: { - children: { control: { type: false } }, + children: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/placeholder/stories/index.story.tsx b/packages/components/src/placeholder/stories/index.story.tsx index 9428299e138477..ffe60df0b4b857 100644 --- a/packages/components/src/placeholder/stories/index.story.tsx +++ b/packages/components/src/placeholder/stories/index.story.tsx @@ -21,9 +21,9 @@ const meta: Meta< typeof Placeholder > = { component: Placeholder, title: 'Components/Placeholder', argTypes: { - children: { control: { type: false } }, - notices: { control: { type: false } }, - preview: { control: { type: false } }, + children: { control: false }, + notices: { control: false }, + preview: { control: false }, icon: { control: { type: 'select' }, options: Object.keys( ICONS ), diff --git a/packages/components/src/popover/stories/index.story.tsx b/packages/components/src/popover/stories/index.story.tsx index 3b783ec9f9746b..cf1bd5135ad9fd 100644 --- a/packages/components/src/popover/stories/index.story.tsx +++ b/packages/components/src/popover/stories/index.story.tsx @@ -37,18 +37,18 @@ const meta: Meta< typeof Popover > = { id: 'components-popover', component: Popover, argTypes: { - anchor: { control: { type: false } }, - anchorRef: { control: { type: false } }, - anchorRect: { control: { type: false } }, - children: { control: { type: false } }, + anchor: { control: false }, + anchorRef: { control: false }, + anchorRect: { control: false }, + children: { control: false }, focusOnMount: { control: { type: 'select' }, options: [ 'firstElement', true, false ], }, - getAnchorRect: { control: { type: false } }, + getAnchorRect: { control: false }, onClose: { action: 'onClose' }, onFocusOutside: { action: 'onFocusOutside' }, - __unstableSlotName: { control: { type: false } }, + __unstableSlotName: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/query-controls/stories/index.story.tsx b/packages/components/src/query-controls/stories/index.story.tsx index d89d91ecd02bde..ad28d9aed0d0d9 100644 --- a/packages/components/src/query-controls/stories/index.story.tsx +++ b/packages/components/src/query-controls/stories/index.story.tsx @@ -22,12 +22,12 @@ const meta: Meta< typeof QueryControls > = { title: 'Components/QueryControls', component: QueryControls, argTypes: { - numberOfItems: { control: { type: false } }, - order: { control: { type: false } }, - orderBy: { control: { type: false } }, - selectedAuthorId: { control: { type: false } }, - selectedCategories: { control: { type: false } }, - selectedCategoryId: { control: { type: false } }, + numberOfItems: { control: false }, + order: { control: false }, + orderBy: { control: false }, + selectedAuthorId: { control: false }, + selectedCategories: { control: false }, + selectedCategoryId: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/radio-control/stories/index.story.tsx b/packages/components/src/radio-control/stories/index.story.tsx index 6291f8fe5cbe33..7b7bc773f323a9 100644 --- a/packages/components/src/radio-control/stories/index.story.tsx +++ b/packages/components/src/radio-control/stories/index.story.tsx @@ -22,7 +22,7 @@ const meta: Meta< typeof RadioControl > = { action: 'onChange', }, selected: { - control: { type: false }, + control: false, }, label: { control: { type: 'text' }, diff --git a/packages/components/src/radio-group/stories/index.story.tsx b/packages/components/src/radio-group/stories/index.story.tsx index d453acfb81d755..aee8610e1b7002 100644 --- a/packages/components/src/radio-group/stories/index.story.tsx +++ b/packages/components/src/radio-group/stories/index.story.tsx @@ -21,8 +21,8 @@ const meta: Meta< typeof RadioGroup > = { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { Radio }, argTypes: { - onChange: { control: { type: false } }, - children: { control: { type: false } }, + onChange: { control: false }, + children: { control: false }, checked: { control: { type: 'text' } }, }, parameters: { @@ -99,5 +99,5 @@ Controlled.args = { id: 'controlled-radiogroup', }; Controlled.argTypes = { - checked: { control: { type: false } }, + checked: { control: false }, }; diff --git a/packages/components/src/range-control/stories/index.story.tsx b/packages/components/src/range-control/stories/index.story.tsx index fd2ab67e652f12..5a4b2342a49ffb 100644 --- a/packages/components/src/range-control/stories/index.story.tsx +++ b/packages/components/src/range-control/stories/index.story.tsx @@ -33,18 +33,18 @@ const meta: Meta< typeof RangeControl > = { }, color: { control: { type: 'color' } }, help: { control: { type: 'text' } }, - icon: { control: { type: false } }, + icon: { control: false }, marks: { control: { type: 'object' } }, - onBlur: { control: { type: false } }, - onChange: { control: { type: false } }, - onFocus: { control: { type: false } }, - onMouseLeave: { control: { type: false } }, - onMouseMove: { control: { type: false } }, + onBlur: { control: false }, + onChange: { control: false }, + onFocus: { control: false }, + onMouseLeave: { control: false }, + onMouseMove: { control: false }, railColor: { control: { type: 'color' } }, step: { control: { type: 'number' } }, trackColor: { control: { type: 'color' } }, type: { control: { type: 'check' }, options: [ 'stepper' ] }, - value: { control: { type: false } }, + value: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/resizable-box/stories/index.story.tsx b/packages/components/src/resizable-box/stories/index.story.tsx index 9b00004bfc1b5d..aa5b080d00b51e 100644 --- a/packages/components/src/resizable-box/stories/index.story.tsx +++ b/packages/components/src/resizable-box/stories/index.story.tsx @@ -18,7 +18,7 @@ const meta: Meta< typeof ResizableBox > = { id: 'components-resizablebox', component: ResizableBox, argTypes: { - children: { control: { type: false } }, + children: { control: false }, enable: { control: 'object' }, onResizeStop: { action: 'onResizeStop' }, }, diff --git a/packages/components/src/responsive-wrapper/stories/index.story.tsx b/packages/components/src/responsive-wrapper/stories/index.story.tsx index cee9c571896513..5a834b999b715b 100644 --- a/packages/components/src/responsive-wrapper/stories/index.story.tsx +++ b/packages/components/src/responsive-wrapper/stories/index.story.tsx @@ -13,7 +13,7 @@ const meta: Meta< typeof ResponsiveWrapper > = { title: 'Components/Layout/ResponsiveWrapper', id: 'components-responsivewrapper', argTypes: { - children: { control: { type: false } }, + children: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/sandbox/stories/index.story.tsx b/packages/components/src/sandbox/stories/index.story.tsx index 21cdb529ae9e23..6d5eaa4868e788 100644 --- a/packages/components/src/sandbox/stories/index.story.tsx +++ b/packages/components/src/sandbox/stories/index.story.tsx @@ -13,7 +13,7 @@ const meta: Meta< typeof SandBox > = { title: 'Components/Utilities/SandBox', id: 'components-sandbox', argTypes: { - onFocus: { control: { type: false } }, + onFocus: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/scrollable/stories/index.story.tsx b/packages/components/src/scrollable/stories/index.story.tsx index 4c9d0eaa786c40..318a841f229788 100644 --- a/packages/components/src/scrollable/stories/index.story.tsx +++ b/packages/components/src/scrollable/stories/index.story.tsx @@ -22,7 +22,7 @@ const meta: Meta< typeof Scrollable > = { control: { type: 'text' }, }, children: { - control: { type: false }, + control: false, }, }, parameters: { diff --git a/packages/components/src/search-control/stories/index.story.tsx b/packages/components/src/search-control/stories/index.story.tsx index 46b45c1cbd5d71..c3385c4eb21b44 100644 --- a/packages/components/src/search-control/stories/index.story.tsx +++ b/packages/components/src/search-control/stories/index.story.tsx @@ -19,7 +19,7 @@ const meta: Meta< typeof SearchControl > = { component: SearchControl, argTypes: { onChange: { action: 'onChange' }, - value: { control: { type: false } }, + value: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/select-control/stories/index.story.tsx b/packages/components/src/select-control/stories/index.story.tsx index 6f60977eaa1fe0..d872df540602e4 100644 --- a/packages/components/src/select-control/stories/index.story.tsx +++ b/packages/components/src/select-control/stories/index.story.tsx @@ -23,7 +23,7 @@ const meta: Meta< typeof SelectControl > = { label: { control: { type: 'text' } }, prefix: { control: { type: 'text' } }, suffix: { control: { type: 'text' } }, - value: { control: { type: false } }, + value: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/slot-fill/stories/index.story.tsx b/packages/components/src/slot-fill/stories/index.story.tsx index c727ba543e6086..2c74496e1eada0 100644 --- a/packages/components/src/slot-fill/stories/index.story.tsx +++ b/packages/components/src/slot-fill/stories/index.story.tsx @@ -20,9 +20,9 @@ const meta: Meta< typeof Slot > = { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { Fill, SlotFillProvider }, argTypes: { - name: { control: { type: false } }, + name: { control: false }, as: { control: { type: 'text' } }, - fillProps: { control: { type: false } }, + fillProps: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/snackbar/stories/index.story.tsx b/packages/components/src/snackbar/stories/index.story.tsx index acfb58e9b3f237..5c24044cc1ae68 100644 --- a/packages/components/src/snackbar/stories/index.story.tsx +++ b/packages/components/src/snackbar/stories/index.story.tsx @@ -19,17 +19,17 @@ const meta: Meta< typeof Snackbar > = { id: 'components-snackbar', component: Snackbar, argTypes: { - as: { control: { type: false } }, + as: { control: false }, onRemove: { action: 'onRemove', - control: { type: false }, + control: false, }, onDismiss: { action: 'onDismiss', - control: { type: false }, + control: false, }, listRef: { - control: { type: false }, + control: false, }, }, parameters: { diff --git a/packages/components/src/snackbar/stories/list.story.tsx b/packages/components/src/snackbar/stories/list.story.tsx index fb6aa7cc97ead4..69a4367c485759 100644 --- a/packages/components/src/snackbar/stories/list.story.tsx +++ b/packages/components/src/snackbar/stories/list.story.tsx @@ -18,10 +18,10 @@ const meta: Meta< typeof SnackbarList > = { id: 'components-snackbarlist', component: SnackbarList, argTypes: { - as: { control: { type: false } }, + as: { control: false }, onRemove: { action: 'onRemove', - control: { type: false }, + control: false, }, }, parameters: { diff --git a/packages/components/src/surface/stories/index.story.tsx b/packages/components/src/surface/stories/index.story.tsx index 4237fe09cc8512..1ef0c0d5637cb4 100644 --- a/packages/components/src/surface/stories/index.story.tsx +++ b/packages/components/src/surface/stories/index.story.tsx @@ -13,7 +13,7 @@ const meta: Meta< typeof Surface > = { component: Surface, title: 'Components (Experimental)/Surface', argTypes: { - children: { control: { type: false } }, + children: { control: false }, as: { control: { type: 'text' } }, }, parameters: { diff --git a/packages/components/src/text-control/stories/index.story.tsx b/packages/components/src/text-control/stories/index.story.tsx index 05e9493d7126a4..fe7fb538805da3 100644 --- a/packages/components/src/text-control/stories/index.story.tsx +++ b/packages/components/src/text-control/stories/index.story.tsx @@ -21,7 +21,7 @@ const meta: Meta< typeof TextControl > = { help: { control: { type: 'text' } }, label: { control: { type: 'text' } }, onChange: { action: 'onChange' }, - value: { control: { type: false } }, + value: { control: false }, }, parameters: { controls: { diff --git a/packages/components/src/textarea-control/stories/index.story.tsx b/packages/components/src/textarea-control/stories/index.story.tsx index ccb0fabb1cb8e9..3160e0bfe68f31 100644 --- a/packages/components/src/textarea-control/stories/index.story.tsx +++ b/packages/components/src/textarea-control/stories/index.story.tsx @@ -21,7 +21,7 @@ const meta: Meta< typeof TextareaControl > = { onChange: { action: 'onChange' }, label: { control: { type: 'text' } }, help: { control: { type: 'text' } }, - value: { control: { type: false } }, + value: { control: false }, }, parameters: { controls: { diff --git a/packages/components/src/toggle-control/stories/index.story.tsx b/packages/components/src/toggle-control/stories/index.story.tsx index d731ccc066fb0c..6511655810066f 100644 --- a/packages/components/src/toggle-control/stories/index.story.tsx +++ b/packages/components/src/toggle-control/stories/index.story.tsx @@ -18,7 +18,7 @@ const meta: Meta< typeof ToggleControl > = { id: 'components-togglecontrol', component: ToggleControl, argTypes: { - checked: { control: { type: false } }, + checked: { control: false }, help: { control: { type: 'text' } }, label: { control: { type: 'text' } }, onChange: { action: 'onChange' }, diff --git a/packages/components/src/toggle-group-control/stories/index.story.tsx b/packages/components/src/toggle-group-control/stories/index.story.tsx index a2e15a5cdc540b..0f3c0a299617af 100644 --- a/packages/components/src/toggle-group-control/stories/index.story.tsx +++ b/packages/components/src/toggle-group-control/stories/index.story.tsx @@ -32,7 +32,7 @@ const meta: Meta< typeof ToggleGroupControl > = { argTypes: { help: { control: { type: 'text' } }, onChange: { action: 'onChange' }, - value: { control: { type: false } }, + value: { control: false }, }, parameters: { controls: { expanded: true }, diff --git a/packages/components/src/toolbar/stories/index.story.tsx b/packages/components/src/toolbar/stories/index.story.tsx index b374fa5931fdec..8590c1ec8a2c6b 100644 --- a/packages/components/src/toolbar/stories/index.story.tsx +++ b/packages/components/src/toolbar/stories/index.story.tsx @@ -51,7 +51,7 @@ const meta: Meta< typeof Toolbar > = { ToolbarDropdownMenu, }, argTypes: { - children: { control: { type: false } }, + children: { control: false }, variant: { options: [ undefined, 'unstyled' ], control: { type: 'radio' }, diff --git a/packages/components/src/tools-panel/stories/index.story.tsx b/packages/components/src/tools-panel/stories/index.story.tsx index 4ea70fcad899e4..76735c845c3ea6 100644 --- a/packages/components/src/tools-panel/stories/index.story.tsx +++ b/packages/components/src/tools-panel/stories/index.story.tsx @@ -31,9 +31,9 @@ const meta: Meta< typeof ToolsPanel > = { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { ToolsPanelItem }, argTypes: { - as: { control: { type: false } }, - children: { control: { type: false } }, - panelId: { control: { type: false } }, + as: { control: false }, + children: { control: false }, + panelId: { control: false }, resetAll: { action: 'resetAll' }, }, parameters: { diff --git a/packages/components/src/tooltip/stories/index.story.tsx b/packages/components/src/tooltip/stories/index.story.tsx index ae676dc148a722..e3d21525dd345d 100644 --- a/packages/components/src/tooltip/stories/index.story.tsx +++ b/packages/components/src/tooltip/stories/index.story.tsx @@ -19,7 +19,7 @@ const meta: Meta< typeof Tooltip > = { id: 'components-tooltip', component: Tooltip, argTypes: { - children: { control: { type: false } }, + children: { control: false }, position: { control: { type: 'select' }, options: [ diff --git a/packages/components/src/tree-grid/stories/index.story.tsx b/packages/components/src/tree-grid/stories/index.story.tsx index eddaeda514fdec..f91ba4631d3209 100644 --- a/packages/components/src/tree-grid/stories/index.story.tsx +++ b/packages/components/src/tree-grid/stories/index.story.tsx @@ -22,7 +22,7 @@ const meta: Meta< typeof TreeGrid > = { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { TreeGridRow, TreeGridCell }, argTypes: { - children: { control: { type: false } }, + children: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/tree-select/stories/index.story.tsx b/packages/components/src/tree-select/stories/index.story.tsx index 23cb1b9e5aca45..b43245e5e16213 100644 --- a/packages/components/src/tree-select/stories/index.story.tsx +++ b/packages/components/src/tree-select/stories/index.story.tsx @@ -22,7 +22,7 @@ const meta: Meta< typeof TreeSelect > = { label: { control: { type: 'text' } }, prefix: { control: { type: 'text' } }, suffix: { control: { type: 'text' } }, - selectedId: { control: { type: false } }, + selectedId: { control: false }, }, parameters: { controls: { diff --git a/packages/components/src/unit-control/stories/index.story.tsx b/packages/components/src/unit-control/stories/index.story.tsx index b6710fb770229e..3a9da70ad5095f 100644 --- a/packages/components/src/unit-control/stories/index.story.tsx +++ b/packages/components/src/unit-control/stories/index.story.tsx @@ -20,11 +20,11 @@ const meta: Meta< typeof UnitControl > = { id: 'components-experimental-unitcontrol', argTypes: { __unstableInputWidth: { control: { type: 'text' } }, - __unstableStateReducer: { control: { type: false } }, - onChange: { control: { type: false } }, - onUnitChange: { control: { type: false } }, + __unstableStateReducer: { control: false }, + onChange: { control: false }, + onUnitChange: { control: false }, prefix: { control: { type: 'text' } }, - value: { control: { type: false } }, + value: { control: false }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/view/stories/index.story.tsx b/packages/components/src/view/stories/index.story.tsx index 96060a3871f5a5..ee4bb71b8a243f 100644 --- a/packages/components/src/view/stories/index.story.tsx +++ b/packages/components/src/view/stories/index.story.tsx @@ -12,7 +12,7 @@ const meta: Meta< typeof View > = { component: View, title: 'Components (Experimental)/View', argTypes: { - as: { control: { type: false } }, + as: { control: false }, children: { control: { type: 'text' } }, }, parameters: { diff --git a/packages/components/src/visually-hidden/stories/index.story.tsx b/packages/components/src/visually-hidden/stories/index.story.tsx index 8c88a89f5efa3b..1c79718ddf6e04 100644 --- a/packages/components/src/visually-hidden/stories/index.story.tsx +++ b/packages/components/src/visually-hidden/stories/index.story.tsx @@ -13,7 +13,7 @@ const meta: Meta< typeof VisuallyHidden > = { title: 'Components/Typography/VisuallyHidden', id: 'components-visuallyhidden', argTypes: { - children: { control: { type: false } }, + children: { control: false }, as: { control: { type: 'text' } }, }, parameters: { diff --git a/packages/components/src/z-stack/stories/index.story.tsx b/packages/components/src/z-stack/stories/index.story.tsx index 1c8fa1712d0c14..53c7d950e75b1b 100644 --- a/packages/components/src/z-stack/stories/index.story.tsx +++ b/packages/components/src/z-stack/stories/index.story.tsx @@ -16,7 +16,7 @@ const meta: Meta< typeof ZStack > = { title: 'Components (Experimental)/ZStack', argTypes: { as: { control: { type: 'text' } }, - children: { control: { type: false } }, + children: { control: false }, }, parameters: { controls: { From 2caf693f545c5b24345d8d3c9e06dcdd1f0e74b7 Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Thu, 5 Dec 2024 18:17:14 +0000 Subject: [PATCH 1875/1908] Fix: Remove parent block selector while in Write mode (#67395) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: richtabor <richtabor@git.wordpress.org> --- .../components/block-parent-selector/index.js | 20 +------------------ .../src/components/block-toolbar/index.js | 1 + 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/packages/block-editor/src/components/block-parent-selector/index.js b/packages/block-editor/src/components/block-parent-selector/index.js index 9090de42f8b7d7..84b5211089cd95 100644 --- a/packages/block-editor/src/components/block-parent-selector/index.js +++ b/packages/block-editor/src/components/block-parent-selector/index.js @@ -1,7 +1,6 @@ /** * WordPress dependencies */ -import { getBlockType, store as blocksStore } from '@wordpress/blocks'; import { ToolbarButton } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { __, sprintf } from '@wordpress/i18n'; @@ -24,31 +23,18 @@ import { unlock } from '../../lock-unlock'; */ export default function BlockParentSelector() { const { selectBlock } = useDispatch( blockEditorStore ); - const { parentClientId, isVisible } = useSelect( ( select ) => { + const { parentClientId } = useSelect( ( select ) => { const { - getBlockName, getBlockParents, getSelectedBlockClientId, - getBlockEditingMode, getParentSectionBlock, } = unlock( select( blockEditorStore ) ); - const { hasBlockSupport } = select( blocksStore ); const selectedBlockClientId = getSelectedBlockClientId(); const parentSection = getParentSectionBlock( selectedBlockClientId ); const parents = getBlockParents( selectedBlockClientId ); const _parentClientId = parentSection ?? parents[ parents.length - 1 ]; - const parentBlockName = getBlockName( _parentClientId ); - const _parentBlockType = getBlockType( parentBlockName ); return { parentClientId: _parentClientId, - isVisible: - _parentClientId && - getBlockEditingMode( _parentClientId ) !== 'disabled' && - hasBlockSupport( - _parentBlockType, - '__experimentalParentSelector', - true - ), }; }, [] ); const blockInformation = useBlockDisplayInformation( parentClientId ); @@ -61,10 +47,6 @@ export default function BlockParentSelector() { highlightParent: true, } ); - if ( ! isVisible ) { - return null; - } - return ( <div className="block-editor-block-parent-selector" diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 0e39f4d531c87b..083d77a694a7b2 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -136,6 +136,7 @@ export function PrivateBlockToolbar( { showParentSelector: ! _isZoomOut && parentBlockType && + editingMode !== 'contentOnly' && getBlockEditingMode( parentClientId ) !== 'disabled' && hasBlockSupport( parentBlockType, From b05a01f155ffd7780f56be383f9684c2c6877fac Mon Sep 17 00:00:00 2001 From: Jorge Costa <jorge.costa@developer.pt> Date: Thu, 5 Dec 2024 18:36:16 +0000 Subject: [PATCH 1876/1908] Docs: Fix Playwright Page Object Model link. (#67652) Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- docs/contributors/code/e2e/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributors/code/e2e/README.md b/docs/contributors/code/e2e/README.md index 3a123cc2988b7a..5aa4e21be909fe 100644 --- a/docs/contributors/code/e2e/README.md +++ b/docs/contributors/code/e2e/README.md @@ -75,7 +75,7 @@ To encourage better practices for querying elements, selectors are [strict](http ### Favor Page Object Model over utils -As mentioned above, [Page Object Model](https://playwright.dev/docs/test-pom) is the preferred way to create reusable utility functions on a certain page. +As mentioned above, [Page Object Model](https://playwright.dev/docs/pom) is the preferred way to create reusable utility functions on a certain page. The rationale behind using a POM is to group utils under namespaces to be easier to discover and use. In fact, `PageUtils` in the `e2e-test-utils-playwright` package is also a POM, which avoids the need for global variables, and utils can reference each other with `this`. From 63c4d5b1bc5fe0820f59549415b65f3693f08f4e Mon Sep 17 00:00:00 2001 From: Lena Morita <lena@jaguchi.com> Date: Fri, 6 Dec 2024 06:58:34 +0900 Subject: [PATCH 1877/1908] Revert "Preview: ArgsTable => Controls (#67582)" (#67656) Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> --- storybook/preview.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/storybook/preview.js b/storybook/preview.js index e173ab3ed1e268..a7c9aa0c085fc1 100644 --- a/storybook/preview.js +++ b/storybook/preview.js @@ -2,7 +2,7 @@ * External dependencies */ import { - Controls, + ArgsTable, Description, Primary, Stories, @@ -114,7 +114,8 @@ export const parameters = { <Subtitle /> <Primary /> <Description /> - <Controls /> + { /* `story="^"` enables Controls for the primary props table */ } + <ArgsTable story="^" /> <Stories includePrimary={ false } /> </> ), From 34088ef4d10c71183c56b16fc53fb1c6574c4e71 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Fri, 6 Dec 2024 14:20:14 +1100 Subject: [PATCH 1878/1908] Style book: scroll to top at styles root (#67605) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> --- .../src/components/style-book/index.js | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 6a044d80553007..f0992381943aaf 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -67,11 +67,14 @@ function isObjectEmpty( object ) { * @param {HTMLIFrameElement} iframe The target iframe. */ const scrollToSection = ( anchorId, iframe ) => { - if ( ! iframe || ! iframe?.contentDocument ) { + if ( ! anchorId || ! iframe || ! iframe?.contentDocument ) { return; } - const element = iframe.contentDocument.getElementById( anchorId ); + const element = + anchorId === 'top' + ? iframe.contentDocument.body + : iframe.contentDocument.getElementById( anchorId ); if ( element ) { element.scrollIntoView( { behavior: 'smooth', @@ -89,6 +92,12 @@ const scrollToSection = ( anchorId, iframe ) => { */ const getStyleBookNavigationFromPath = ( path ) => { if ( path && typeof path === 'string' ) { + if ( path === '/' ) { + return { + top: true, + }; + } + if ( path.startsWith( '/typography' ) ) { return { block: 'typography', @@ -365,10 +374,19 @@ const StyleBookBody = ( { const handleLoad = () => setHasIframeLoaded( true ); useLayoutEffect( () => { - if ( goTo?.block && hasIframeLoaded && iframeRef?.current ) { - scrollToSection( `example-${ goTo?.block }`, iframeRef?.current ); + if ( hasIframeLoaded && iframeRef?.current ) { + if ( goTo?.top ) { + scrollToSection( 'top', iframeRef?.current ); + return; + } + if ( goTo?.block ) { + scrollToSection( + `example-${ goTo?.block }`, + iframeRef?.current + ); + } } - }, [ iframeRef?.current, goTo?.block, scrollToSection, hasIframeLoaded ] ); + }, [ iframeRef?.current, goTo, scrollToSection, hasIframeLoaded ] ); return ( <Iframe From 4335c452609a747faffd74f25b4846d717679e4c Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 6 Dec 2024 13:57:58 +1000 Subject: [PATCH 1879/1908] Global Styles: Fix handling of booleans when stabilizing block supports (#67552) Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- backport-changelog/6.8/7069.md | 1 + lib/compat/wordpress-6.8/blocks.php | 25 ++++--- phpunit/block-supports/border-test.php | 100 +++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 10 deletions(-) diff --git a/backport-changelog/6.8/7069.md b/backport-changelog/6.8/7069.md index 69edbde58902d1..3e734637ddbb2f 100644 --- a/backport-changelog/6.8/7069.md +++ b/backport-changelog/6.8/7069.md @@ -3,3 +3,4 @@ https://github.com/WordPress/wordpress-develop/pull/7069 * https://github.com/WordPress/gutenberg/pull/63401 * https://github.com/WordPress/gutenberg/pull/66918 * https://github.com/WordPress/gutenberg/pull/67018 +* https://github.com/WordPress/gutenberg/pull/67552 diff --git a/lib/compat/wordpress-6.8/blocks.php b/lib/compat/wordpress-6.8/blocks.php index 4d4bdee2bb393b..e0f5082bfce8dc 100644 --- a/lib/compat/wordpress-6.8/blocks.php +++ b/lib/compat/wordpress-6.8/blocks.php @@ -71,6 +71,10 @@ function gutenberg_stabilize_experimental_block_supports( $args ) { } $stabilize_config = function ( $unstable_config, $stable_support_key ) use ( $experimental_support_properties, $common_experimental_properties ) { + if ( ! is_array( $unstable_config ) ) { + return $unstable_config; + } + $stable_config = array(); foreach ( $unstable_config as $key => $value ) { // Get stable key from support-specific map, common properties map, or keep original. @@ -116,18 +120,19 @@ function gutenberg_stabilize_experimental_block_supports( $args ) { ( $key_positions[ $support ] ?? PHP_INT_MAX ) < ( $key_positions[ $stable_support_key ] ?? PHP_INT_MAX ); - if ( is_array( $args['supports'][ $stable_support_key ] ) ) { - /* - * To merge the alternative support config effectively, it also needs to be - * stabilized before merging to keep stabilized and experimental flags in - * sync. - */ - $args['supports'][ $stable_support_key ] = $stabilize_config( $args['supports'][ $stable_support_key ], $stable_support_key ); - $stable_config = $experimental_first + /* + * To merge the alternative support config effectively, it also needs to be + * stabilized before merging to keep stabilized and experimental flags in + * sync. + */ + $args['supports'][ $stable_support_key ] = $stabilize_config( $args['supports'][ $stable_support_key ], $stable_support_key ); + // Prevents reprocessing this support as it was stabilized above. + $done[ $stable_support_key ] = true; + + if ( is_array( $stable_config ) && is_array( $args['supports'][ $stable_support_key ] ) ) { + $stable_config = $experimental_first ? array_merge( $stable_config, $args['supports'][ $stable_support_key ] ) : array_merge( $args['supports'][ $stable_support_key ], $stable_config ); - // Prevents reprocessing this support as it was merged above. - $done[ $stable_support_key ] = true; } else { $stable_config = $experimental_first ? $args['supports'][ $stable_support_key ] diff --git a/phpunit/block-supports/border-test.php b/phpunit/block-supports/border-test.php index 6ec43b369d9a2a..510633b48aab59 100644 --- a/phpunit/block-supports/border-test.php +++ b/phpunit/block-supports/border-test.php @@ -730,4 +730,104 @@ public function test_should_stabilize_border_supports_using_order_based_merge() ); $this->assertSame( $expected, $actual, 'Merged stabilized border block support config does not match when stable keys are first.' ); } + + /** + * Tests that boolean border support configurations are handled correctly. + * + * @dataProvider data_boolean_border_supports + * + * @param array $supports The supports configuration to test. + * @param boolean|array $expected_value The expected final border support value. + */ + public function test_should_handle_boolean_border_supports( $supports, $expected_value ) { + $args = array( + 'supports' => $supports, + ); + + $actual = gutenberg_stabilize_experimental_block_supports( $args ); + + $this->assertSame( $expected_value, $actual['supports']['border'] ); + } + + /** + * Data provider for boolean border support tests. + * + * @return array Test parameters. + */ + public function data_boolean_border_supports() { + return array( + 'experimental true only' => array( + array( + '__experimentalBorder' => true, + ), + true, + ), + 'experimental false only' => array( + array( + '__experimentalBorder' => false, + ), + false, + ), + 'experimental true before stable false' => array( + array( + '__experimentalBorder' => true, + 'border' => false, + ), + false, + ), + 'stable true before experimental false' => array( + array( + 'border' => true, + '__experimentalBorder' => false, + ), + false, + ), + 'experimental array before stable boolean' => array( + array( + '__experimentalBorder' => array( + 'color' => true, + 'width' => true, + ), + 'border' => false, + ), + false, + ), + 'stable array before experimental boolean' => array( + array( + 'border' => array( + 'color' => true, + 'width' => true, + ), + '__experimentalBorder' => true, + ), + true, + ), + 'experimental boolean before stable array' => array( + array( + '__experimentalBorder' => true, + 'border' => array( + 'color' => true, + 'width' => true, + ), + ), + array( + 'color' => true, + 'width' => true, + ), + ), + 'stable boolean before experimental array' => array( + array( + 'border' => false, + '__experimentalBorder' => array( + 'color' => true, + 'width' => true, + ), + ), + array( + 'color' => true, + 'width' => true, + ), + ), + ); + } } From 794eec2190f46e906a9fb9cf959f9fdd77741233 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 6 Dec 2024 09:33:10 +0400 Subject: [PATCH 1880/1908] Navigation: Enable all non-interactive formats (#67585) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: shimotmk <shimotomoki@git.wordpress.org> --- packages/block-library/src/navigation-link/edit.js | 6 ------ packages/block-library/src/navigation-submenu/edit.js | 6 ------ 2 files changed, 12 deletions(-) diff --git a/packages/block-library/src/navigation-link/edit.js b/packages/block-library/src/navigation-link/edit.js index 9e2e171975570f..39073b848d3ca8 100644 --- a/packages/block-library/src/navigation-link/edit.js +++ b/packages/block-library/src/navigation-link/edit.js @@ -527,12 +527,6 @@ export default function NavigationLinkEdit( { ) } placeholder={ itemLabelPlaceholder } withoutInteractiveFormatting - allowedFormats={ [ - 'core/bold', - 'core/italic', - 'core/image', - 'core/strikethrough', - ] } /> { description && ( <span className="wp-block-navigation-item__description"> diff --git a/packages/block-library/src/navigation-submenu/edit.js b/packages/block-library/src/navigation-submenu/edit.js index 261b2ad8502fb8..c89eadf1cb589e 100644 --- a/packages/block-library/src/navigation-submenu/edit.js +++ b/packages/block-library/src/navigation-submenu/edit.js @@ -461,12 +461,6 @@ export default function NavigationSubmenuEdit( { aria-label={ __( 'Navigation link text' ) } placeholder={ itemLabelPlaceholder } withoutInteractiveFormatting - allowedFormats={ [ - 'core/bold', - 'core/italic', - 'core/image', - 'core/strikethrough', - ] } onClick={ () => { if ( ! openSubmenusOnClick && ! url ) { setIsLinkOpen( true ); From 5ed400ca4c7faa11aad598db3b7fc0bb13943357 Mon Sep 17 00:00:00 2001 From: Viral Sampat <53076293+viralsampat-multidots@users.noreply.github.com> Date: Fri, 6 Dec 2024 11:54:03 +0530 Subject: [PATCH 1881/1908] Fix latest post block spacing issue. (#66442) * Fix latest post block spacing issue. --------- Co-authored-by: viralsampat-multidots <mdviralsampat@git.wordpress.org> Co-authored-by: up1512001 <up1512001@git.wordpress.org> Co-authored-by: patil-vipul <vipulpatil@git.wordpress.org> --- packages/block-library/src/latest-posts/style.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/latest-posts/style.scss b/packages/block-library/src/latest-posts/style.scss index 2a01d177ef47c4..69a4746b5e751c 100644 --- a/packages/block-library/src/latest-posts/style.scss +++ b/packages/block-library/src/latest-posts/style.scss @@ -57,7 +57,8 @@ font-size: 0.8125em; } -.wp-block-latest-posts__post-excerpt { +.wp-block-latest-posts__post-excerpt, +.wp-block-latest-posts__post-full-content { margin-top: 0.5em; margin-bottom: 1em; } From 6c312f70b60550b6e1a72a7f19a39f138fb4d9f3 Mon Sep 17 00:00:00 2001 From: Benazeer Hassan <66269472+benazeer-ben@users.noreply.github.com> Date: Fri, 6 Dec 2024 12:33:56 +0530 Subject: [PATCH 1882/1908] Welcome guide headline update (#67654) * Welcome guide headline update * Updated texts in automated test code ---- Co-authored-by: benazeer-ben <benazeer@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org> --- .../src/components/welcome-guide/default.js | 10 +++---- .../src/components/welcome-guide/index.js | 6 ++-- test/e2e/specs/editor/various/nux.spec.js | 28 +++++++------------ 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/packages/edit-post/src/components/welcome-guide/default.js b/packages/edit-post/src/components/welcome-guide/default.js index cdaf2c7608b43e..deb4b70c3ad529 100644 --- a/packages/edit-post/src/components/welcome-guide/default.js +++ b/packages/edit-post/src/components/welcome-guide/default.js @@ -18,7 +18,7 @@ export default function WelcomeGuideDefault() { return ( <Guide className="edit-post-welcome-guide" - contentLabel={ __( 'Welcome to the block editor' ) } + contentLabel={ __( 'Welcome to the editor' ) } finishButtonText={ __( 'Get started' ) } onFinish={ () => toggleFeature( 'welcomeGuide' ) } pages={ [ @@ -32,7 +32,7 @@ export default function WelcomeGuideDefault() { content: ( <> <h1 className="edit-post-welcome-guide__heading"> - { __( 'Welcome to the block editor' ) } + { __( 'Welcome to the editor' ) } </h1> <p className="edit-post-welcome-guide__text"> { __( @@ -52,7 +52,7 @@ export default function WelcomeGuideDefault() { content: ( <> <h1 className="edit-post-welcome-guide__heading"> - { __( 'Make each block your own' ) } + { __( 'Customize each block' ) } </h1> <p className="edit-post-welcome-guide__text"> { __( @@ -72,7 +72,7 @@ export default function WelcomeGuideDefault() { content: ( <> <h1 className="edit-post-welcome-guide__heading"> - { __( 'Get to know the block library' ) } + { __( 'Explore all blocks' ) } </h1> <p className="edit-post-welcome-guide__text"> { createInterpolateElement( @@ -102,7 +102,7 @@ export default function WelcomeGuideDefault() { content: ( <> <h1 className="edit-post-welcome-guide__heading"> - { __( 'Learn how to use the block editor' ) } + { __( 'Learn more' ) } </h1> <p className="edit-post-welcome-guide__text"> { createInterpolateElement( diff --git a/packages/edit-widgets/src/components/welcome-guide/index.js b/packages/edit-widgets/src/components/welcome-guide/index.js index bd06234e399b58..b9967e3a6025d7 100644 --- a/packages/edit-widgets/src/components/welcome-guide/index.js +++ b/packages/edit-widgets/src/components/welcome-guide/index.js @@ -118,7 +118,7 @@ export default function WelcomeGuide() { content: ( <> <h1 className="edit-widgets-welcome-guide__heading"> - { __( 'Make each block your own' ) } + { __( 'Customize each block' ) } </h1> <p className="edit-widgets-welcome-guide__text"> { __( @@ -138,7 +138,7 @@ export default function WelcomeGuide() { content: ( <> <h1 className="edit-widgets-welcome-guide__heading"> - { __( 'Get to know the block library' ) } + { __( 'Explore all blocks' ) } </h1> <p className="edit-widgets-welcome-guide__text"> { createInterpolateElement( @@ -169,7 +169,7 @@ export default function WelcomeGuide() { content: ( <> <h1 className="edit-widgets-welcome-guide__heading"> - { __( 'Learn how to use the block editor' ) } + { __( 'Learn more' ) } </h1> <p className="edit-widgets-welcome-guide__text"> { createInterpolateElement( diff --git a/test/e2e/specs/editor/various/nux.spec.js b/test/e2e/specs/editor/various/nux.spec.js index ff55dbfa54e478..424647f4072eaa 100644 --- a/test/e2e/specs/editor/various/nux.spec.js +++ b/test/e2e/specs/editor/various/nux.spec.js @@ -12,7 +12,7 @@ test.describe( 'New User Experience (NUX)', () => { await admin.createNewPost( { showWelcomeGuide: true } ); const welcomeGuide = page.getByRole( 'dialog', { - name: 'Welcome to the block editor', + name: 'Welcome to the editor', } ); const guideHeading = welcomeGuide.getByRole( 'heading', { level: 1 } ); const nextButton = welcomeGuide.getByRole( 'button', { name: 'Next' } ); @@ -20,36 +20,28 @@ test.describe( 'New User Experience (NUX)', () => { name: 'Previous', } ); - await expect( guideHeading ).toHaveText( - 'Welcome to the block editor' - ); + await expect( guideHeading ).toHaveText( 'Welcome to the editor' ); await nextButton.click(); - await expect( guideHeading ).toHaveText( 'Make each block your own' ); + await expect( guideHeading ).toHaveText( 'Customize each block' ); await prevButton.click(); // Guide should be on page 1 of 4 - await expect( guideHeading ).toHaveText( - 'Welcome to the block editor' - ); + await expect( guideHeading ).toHaveText( 'Welcome to the editor' ); // Press the button for Page 2. await welcomeGuide .getByRole( 'button', { name: 'Page 2 of 4' } ) .click(); - await expect( guideHeading ).toHaveText( 'Make each block your own' ); + await expect( guideHeading ).toHaveText( 'Customize each block' ); // Press the right arrow key for Page 3. await page.keyboard.press( 'ArrowRight' ); - await expect( guideHeading ).toHaveText( - 'Get to know the block library' - ); + await expect( guideHeading ).toHaveText( 'Explore all blocks' ); // Press the right arrow key for Page 4. await page.keyboard.press( 'ArrowRight' ); - await expect( guideHeading ).toHaveText( - 'Learn how to use the block editor' - ); + await expect( guideHeading ).toHaveText( 'Learn more' ); // Click on the *visible* 'Get started' button. await welcomeGuide @@ -77,7 +69,7 @@ test.describe( 'New User Experience (NUX)', () => { await admin.createNewPost( { showWelcomeGuide: true } ); const welcomeGuide = page.getByRole( 'dialog', { - name: 'Welcome to the block editor', + name: 'Welcome to the editor', } ); await expect( welcomeGuide ).toBeVisible(); @@ -100,7 +92,7 @@ test.describe( 'New User Experience (NUX)', () => { await admin.createNewPost( { showWelcomeGuide: true } ); const welcomeGuide = page.getByRole( 'dialog', { - name: 'Welcome to the block editor', + name: 'Welcome to the editor', } ); await expect( welcomeGuide ).toBeVisible(); @@ -117,7 +109,7 @@ test.describe( 'New User Experience (NUX)', () => { } ) => { await admin.createNewPost(); const welcomeGuide = page.getByRole( 'dialog', { - name: 'Welcome to the block editor', + name: 'Welcome to the editor', } ); await expect( welcomeGuide ).toBeHidden(); From 32cbb04b765d8d8df959642c0d01326327e5ff41 Mon Sep 17 00:00:00 2001 From: louwie17 <lourensschep@gmail.com> Date: Fri, 6 Dec 2024 04:01:47 -0400 Subject: [PATCH 1883/1908] Add header to the quick edit when bulk editing (#67390) * Add quick edit bulk header * Updating styling of header * Moved header to post-edit folder * Make use of mixin for the post title * Pass postId to the pageTypeBadge hook, for use outside editor * Fix formatting issues * Move parseInt up * Remove title field Co-authored-by: louwie17 <louwie17@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> --- packages/base-styles/_mixins.scss | 16 ++-- .../src/components/post-edit/header.js | 88 +++++++++++++++++++ .../src/components/post-edit/index.js | 8 +- .../src/components/post-edit/style.scss | 10 +++ packages/edit-site/src/style.scss | 1 + .../src/components/document-bar/index.js | 4 +- .../src/components/post-card-panel/index.js | 4 +- .../src/components/post-card-panel/style.scss | 1 + packages/editor/src/utils/pageTypeBadge.js | 11 +-- 9 files changed, 118 insertions(+), 25 deletions(-) create mode 100644 packages/edit-site/src/components/post-edit/header.js diff --git a/packages/base-styles/_mixins.scss b/packages/base-styles/_mixins.scss index 65f98bf6f15bfc..e2f953e5787814 100644 --- a/packages/base-styles/_mixins.scss +++ b/packages/base-styles/_mixins.scss @@ -18,25 +18,25 @@ @mixin heading-small() { @include _text-heading(); font-size: $font-size-x-small; - line-height: $line-height-x-small; + line-height: $font-line-height-x-small; } @mixin heading-medium() { @include _text-heading(); font-size: $font-size-medium; - line-height: $line-height-small; + line-height: $font-line-height-small; } @mixin heading-large() { @include _text-heading(); font-size: $font-size-large; - line-height: $line-height-small; + line-height: $font-line-height-small; } @mixin heading-x-large() { @include _text-heading(); font-size: $font-size-x-large; - line-height: $line-height-medium; + line-height: $font-line-height-medium; } @mixin heading-2x-large() { @@ -48,25 +48,25 @@ @mixin body-small() { @include _text-body(); font-size: $font-size-small; - line-height: $line-height-x-small; + line-height: $font-line-height-x-small; } @mixin body-medium() { @include _text-body(); font-size: $font-size-medium; - line-height: $line-height-small; + line-height: $font-line-height-small; } @mixin body-large() { @include _text-body(); font-size: $font-size-large; - line-height: $line-height-medium; + line-height: $font-line-height-medium; } @mixin body-x-large() { @include _text-body(); font-size: $font-size-x-large; - line-height: $line-height-x-large; + line-height: $font-line-height-x-large; } /** diff --git a/packages/edit-site/src/components/post-edit/header.js b/packages/edit-site/src/components/post-edit/header.js new file mode 100644 index 00000000000000..305589d0cc22bf --- /dev/null +++ b/packages/edit-site/src/components/post-edit/header.js @@ -0,0 +1,88 @@ +/** + * WordPress dependencies + */ +import { + __experimentalHStack as HStack, + __experimentalVStack as VStack, + Icon, + __experimentalText as Text, +} from '@wordpress/components'; +import { useMemo } from '@wordpress/element'; +import { + privateApis as editorPrivateApis, + store as editorStore, +} from '@wordpress/editor'; +import { store as coreStore } from '@wordpress/core-data'; +import { useSelect } from '@wordpress/data'; +import { sprintf, __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; + +const { PostCardPanel } = unlock( editorPrivateApis ); + +export default function PostEditHeader( { postType, postId } ) { + const ids = useMemo( () => postId.split( ',' ), [ postId ] ); + const { icon, labels } = useSelect( + ( select ) => { + const { getEditedEntityRecord, getPostType } = select( coreStore ); + const { getPostIcon } = unlock( select( editorStore ) ); + const _record = getEditedEntityRecord( + 'postType', + postType, + ids[ 0 ] + ); + + return { + icon: getPostIcon( postType, { + area: _record?.area, + } ), + labels: getPostType( postType )?.labels, + }; + }, + [ ids, postType ] + ); + + if ( ids.length === 1 ) { + return ( + <PostCardPanel + postType={ postType } + postId={ parseInt( ids[ 0 ], 10 ) } + /> + ); + } + + return ( + <VStack spacing={ 1 } className="edit-site-post-edit-header"> + <HStack spacing={ 2 } align="center" justify="normal"> + <Icon + className="edit-site-post-edit-header__icon" + icon={ icon } + /> + <Text + numberOfLines={ 2 } + truncate + className="edit-site-post-edit-header__title" + as="h2" + > + { labels?.name && + sprintf( + // translators: %i number of selected items %s: Name of the plural post type e.g: "Posts". + __( '%i %s' ), + ids.length, + labels?.name + ) } + </Text> + </HStack> + <Text className="edit-site-post-edit-header__description"> + { sprintf( + // translators: %s: Name of the plural post type e.g: "Posts". + __( 'Changes will be applied to all selected %s.' ), + labels?.name.toLowerCase() + ) } + </Text> + </VStack> + ); +} diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 9a99a987089c1a..b3954e4ddbdeaf 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -18,11 +18,12 @@ import { privateApis as editorPrivateApis } from '@wordpress/editor'; * Internal dependencies */ import Page from '../page'; +import PostEditHeader from '../post-edit/header'; import { unlock } from '../../lock-unlock'; import usePatternSettings from '../page-patterns/use-pattern-settings'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; -const { PostCardPanel, usePostFields } = unlock( editorPrivateApis ); +const { usePostFields } = unlock( editorPrivateApis ); const fieldsWithBulkEditSupport = [ 'title', @@ -76,7 +77,6 @@ function PostEditForm( { postType, postId } ) { id: 'featured_media', layout: 'regular', }, - 'title', { id: 'status', label: __( 'Status & Visibility' ), @@ -159,9 +159,7 @@ function PostEditForm( { postType, postId } ) { return ( <VStack spacing={ 4 }> - { ids.length === 1 && ( - <PostCardPanel postType={ postType } postId={ ids[ 0 ] } /> - ) } + <PostEditHeader postType={ postType } postId={ postId } /> <DataForm data={ ids.length === 1 ? record : multiEdits } fields={ fieldsWithDependency } diff --git a/packages/edit-site/src/components/post-edit/style.scss b/packages/edit-site/src/components/post-edit/style.scss index 5688d83df00c5f..5a20183c8f0210 100644 --- a/packages/edit-site/src/components/post-edit/style.scss +++ b/packages/edit-site/src/components/post-edit/style.scss @@ -14,3 +14,13 @@ padding-top: $grid-unit-20; } } + +.edit-site-post-edit-header { + .edit-site-post-edit-header__description { + color: $gray-700; + } + + .edit-site-post-edit-header__title { + @include heading-medium(); + } +} diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index dce945a48ee700..4269cdb4bc90d1 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -47,6 +47,7 @@ mix-blend-mode: normal; display: block; } + /* stylelint-enable */ body.js #wpadminbar { diff --git a/packages/editor/src/components/document-bar/index.js b/packages/editor/src/components/document-bar/index.js index 7b94a6fbeb3be9..f5ca65dfe18ed7 100644 --- a/packages/editor/src/components/document-bar/index.js +++ b/packages/editor/src/components/document-bar/index.js @@ -54,6 +54,7 @@ const MotionButton = motion( Button ); */ export default function DocumentBar( props ) { const { + postId, postType, postTypeLabel, documentTitle, @@ -93,6 +94,7 @@ export default function DocumentBar( props ) { const _postTypeLabel = getPostType( _postType )?.labels?.singular_name; return { + postId: _postId, postType: _postType, postTypeLabel: _postTypeLabel, documentTitle: _document.title, @@ -120,7 +122,7 @@ export default function DocumentBar( props ) { const title = props.title || entityTitle; const icon = props.icon; - const pageTypeBadge = usePageTypeBadge(); + const pageTypeBadge = usePageTypeBadge( postId ); const mountedRef = useRef( false ); useEffect( () => { diff --git a/packages/editor/src/components/post-card-panel/index.js b/packages/editor/src/components/post-card-panel/index.js index 8fcca6c6bd6d40..e347d3c79fc521 100644 --- a/packages/editor/src/components/post-card-panel/index.js +++ b/packages/editor/src/components/post-card-panel/index.js @@ -64,7 +64,7 @@ export default function PostCardPanel( { [ postId, postType ] ); - const pageTypeBadge = usePageTypeBadge(); + const pageTypeBadge = usePageTypeBadge( postId ); return ( <div className="editor-post-card-panel"> @@ -78,9 +78,7 @@ export default function PostCardPanel( { numberOfLines={ 2 } truncate className="editor-post-card-panel__title" - weight={ 500 } as="h2" - lineHeight="20px" > { title ? decodeEntities( title ) : __( 'No title' ) } { pageTypeBadge && ( diff --git a/packages/editor/src/components/post-card-panel/style.scss b/packages/editor/src/components/post-card-panel/style.scss index d8a2a4628e6f9c..d9ecfc58304e85 100644 --- a/packages/editor/src/components/post-card-panel/style.scss +++ b/packages/editor/src/components/post-card-panel/style.scss @@ -7,6 +7,7 @@ width: 100%; &.editor-post-card-panel__title { + @include heading-medium(); margin: 0; padding: 2px 0; display: flex; diff --git a/packages/editor/src/utils/pageTypeBadge.js b/packages/editor/src/utils/pageTypeBadge.js index 321b9caa17769e..bc787b12284222 100644 --- a/packages/editor/src/utils/pageTypeBadge.js +++ b/packages/editor/src/utils/pageTypeBadge.js @@ -5,19 +5,14 @@ import { __ } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -/** - * Internal dependencies - */ -import { store as editorStore } from '../store'; - /** * Custom hook to get the page type badge for the current post on edit site view. + * + * @param {number} postId postId of the current post being edited. */ -export default function usePageTypeBadge() { +export default function usePageTypeBadge( postId ) { const { isFrontPage, isPostsPage } = useSelect( ( select ) => { - const { getCurrentPostId } = select( editorStore ); const { canUser, getEditedEntityRecord } = select( coreStore ); - const postId = getCurrentPostId(); const siteSettings = canUser( 'read', { kind: 'root', name: 'site', From 15bff410d4ca9f53a8c45098fb484c083a968628 Mon Sep 17 00:00:00 2001 From: Manzoor Wani <manzoorwani.jk@gmail.com> Date: Fri, 6 Dec 2024 00:14:23 -0800 Subject: [PATCH 1884/1908] Upgrade TypeScript to 5.7 and fix types (#67461) * Upgrade TypeScript to 5.7 and fix types * Increase the minimum required version of TypeScript for the ESLint config package * Update CHANGELOG.md Co-authored-by: manzoorwanijk <manzoorwanijk@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> --- package-lock.json | 10 +++++----- package.json | 2 +- packages/components/src/dropdown-menu/index.tsx | 4 +++- packages/components/src/modal/test/index.tsx | 3 ++- packages/components/src/tree-grid/cell.tsx | 6 +++++- packages/components/src/tree-grid/types.ts | 2 +- packages/eslint-plugin/CHANGELOG.md | 13 +++++++++---- packages/eslint-plugin/package.json | 2 +- packages/rich-text/src/create.js | 13 +++++++++++++ packages/router/src/router.tsx | 2 -- packages/vips/README.md | 4 ++-- packages/vips/src/index.ts | 6 +++--- 12 files changed, 45 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3084fd5f034401..478be0c4ecfea5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -153,7 +153,7 @@ "style-loader": "3.2.1", "terser": "5.32.0", "terser-webpack-plugin": "5.3.10", - "typescript": "5.5.3", + "typescript": "5.7.2", "uuid": "9.0.1", "webdriverio": "8.16.20", "webpack": "5.95.0", @@ -48699,9 +48699,9 @@ } }, "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -54648,7 +54648,7 @@ "@babel/core": ">=7", "eslint": ">=8", "prettier": ">=3", - "typescript": ">=4" + "typescript": ">=5" }, "peerDependenciesMeta": { "prettier": { diff --git a/package.json b/package.json index 190664e11551dd..9c074897ed14a1 100644 --- a/package.json +++ b/package.json @@ -162,7 +162,7 @@ "style-loader": "3.2.1", "terser": "5.32.0", "terser-webpack-plugin": "5.3.10", - "typescript": "5.5.3", + "typescript": "5.7.2", "uuid": "9.0.1", "webdriverio": "8.16.20", "webpack": "5.95.0", diff --git a/packages/components/src/dropdown-menu/index.tsx b/packages/components/src/dropdown-menu/index.tsx index de83695978c2df..195595fb9dc0de 100644 --- a/packages/components/src/dropdown-menu/index.tsx +++ b/packages/components/src/dropdown-menu/index.tsx @@ -169,7 +169,9 @@ function UnconnectedDropdownMenu( dropdownMenuProps: DropdownMenuProps ) { indexOfSet, indexOfControl, ].join() } - onClick={ ( event ) => { + onClick={ ( + event: React.MouseEvent< HTMLButtonElement > + ) => { event.stopPropagation(); props.onClose(); if ( control.onClick ) { diff --git a/packages/components/src/modal/test/index.tsx b/packages/components/src/modal/test/index.tsx index a0d0ee2653edb4..05dcc35dce18da 100644 --- a/packages/components/src/modal/test/index.tsx +++ b/packages/components/src/modal/test/index.tsx @@ -269,7 +269,8 @@ describe( 'Modal', () => { } ); describe( 'Focus handling', () => { - let originalGetClientRects: () => DOMRectList; + const originalGetClientRects = + window.HTMLElement.prototype.getClientRects; const FocusMountDemo = ( { focusOnMount, diff --git a/packages/components/src/tree-grid/cell.tsx b/packages/components/src/tree-grid/cell.tsx index a9883eb0512266..08261abe10313a 100644 --- a/packages/components/src/tree-grid/cell.tsx +++ b/packages/components/src/tree-grid/cell.tsx @@ -21,7 +21,11 @@ function UnforwardedTreeGridCell( return ( <td { ...props } role="gridcell"> { withoutGridItem ? ( - <>{ children }</> + <> + { typeof children === 'function' + ? children( { ...props, ref } ) + : children } + </> ) : ( <TreeGridItem ref={ ref }>{ children }</TreeGridItem> ) } diff --git a/packages/components/src/tree-grid/types.ts b/packages/components/src/tree-grid/types.ts index 31d04882d1a815..f4946ba58ca8a0 100644 --- a/packages/components/src/tree-grid/types.ts +++ b/packages/components/src/tree-grid/types.ts @@ -36,7 +36,7 @@ export type TreeGridRowProps = { type RovingTabIndexItemPassThruProps = { ref: React.ForwardedRef< any >; tabIndex?: number; - onFocus: React.FocusEventHandler< any >; + onFocus?: React.FocusEventHandler< any >; [ key: string ]: any; }; diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 91b517249b597a..a53fe75dee448f 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- The minimum required TypeScript version changed to 5 ([#67461](https://github.com/WordPress/gutenberg/pull/67461)) + ## 21.6.0 (2024-11-27) ## 21.5.0 (2024-11-16) @@ -18,8 +22,8 @@ ### Breaking Changes -- Add [`@wordpress/i18n-no-flanking-whitespace`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/eslint-plugin/docs/rules/i18n-no-flanking-whitespace.md) to the recommended i18n ruleset ([#64710](https://github.com/WordPress/gutenberg/pull/64710). -- Add [`@wordpress/i18n-hyphenated-range`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/eslint-plugin/docs/rules/i18n-hyphenated-range.md) to the recommended i18n ruleset ([#64710](https://github.com/WordPress/gutenberg/pull/64710). +- Add [`@wordpress/i18n-no-flanking-whitespace`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/eslint-plugin/docs/rules/i18n-no-flanking-whitespace.md) to the recommended i18n ruleset ([#64710](https://github.com/WordPress/gutenberg/pull/64710). +- Add [`@wordpress/i18n-hyphenated-range`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/eslint-plugin/docs/rules/i18n-hyphenated-range.md) to the recommended i18n ruleset ([#64710](https://github.com/WordPress/gutenberg/pull/64710). ## 20.3.0 (2024-08-21) @@ -30,8 +34,9 @@ ## 20.0.0 (2024-07-10) ### Breaking Changes -- Add [`@typescript-eslint/no-unused-vars` rule](https://typescript-eslint.io/rules/no-unused-vars) to the recommended TypeScript ruleset ([#62925](https://github.com/WordPress/gutenberg/pull/62925)). -- Add [`@typescript-eslint/method-signature-style` rule](https://typescript-eslint.io/rules/method-signature-style) to the recommended TypeScript ruleset ([#62718](https://github.com/WordPress/gutenberg/pull/62718)). + +- Add [`@typescript-eslint/no-unused-vars` rule](https://typescript-eslint.io/rules/no-unused-vars) to the recommended TypeScript ruleset ([#62925](https://github.com/WordPress/gutenberg/pull/62925)). +- Add [`@typescript-eslint/method-signature-style` rule](https://typescript-eslint.io/rules/method-signature-style) to the recommended TypeScript ruleset ([#62718](https://github.com/WordPress/gutenberg/pull/62718)). ## 19.2.0 (2024-06-26) diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 64c0a422873d69..1e75a2c131f229 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -53,7 +53,7 @@ "@babel/core": ">=7", "eslint": ">=8", "prettier": ">=3", - "typescript": ">=4" + "typescript": ">=5" }, "peerDependenciesMeta": { "prettier": { diff --git a/packages/rich-text/src/create.js b/packages/rich-text/src/create.js index d683836d9e2fa8..a8fc4b92c49600 100644 --- a/packages/rich-text/src/create.js +++ b/packages/rich-text/src/create.js @@ -125,6 +125,13 @@ export class RichTextData { static fromHTMLString( html ) { return new RichTextData( create( { html } ) ); } + /** + * Create a RichTextData instance from an HTML element. + * + * @param {HTMLElement} htmlElement The HTML element to create the instance from. + * @param {{preserveWhiteSpace?: boolean}} options Options. + * @return {RichTextData} The RichTextData instance. + */ static fromHTMLElement( htmlElement, options = {} ) { const { preserveWhiteSpace = false } = options; const element = preserveWhiteSpace @@ -144,6 +151,12 @@ export class RichTextData { } // We could expose `toHTMLElement` at some point as well, but we'd only use // it internally. + /** + * Convert the rich text value to an HTML string. + * + * @param {{preserveWhiteSpace?: boolean}} options Options. + * @return {string} The HTML string. + */ toHTMLString( { preserveWhiteSpace } = {} ) { return ( this.originalHTML || diff --git a/packages/router/src/router.tsx b/packages/router/src/router.tsx index 2ac7974b4dfbce..8ad54e9264678a 100644 --- a/packages/router/src/router.tsx +++ b/packages/router/src/router.tsx @@ -120,7 +120,6 @@ export function useHistory() { window.matchMedia( '(min-width: 782px)' ).matches; if ( ! isMediumOrBigger || - // @ts-expect-error ! document.startViewTransition || ! options.transition ) { @@ -131,7 +130,6 @@ export function useHistory() { await new Promise< void >( ( resolve ) => { const classname = options.transition ?? ''; document.documentElement.classList.add( classname ); - // @ts-expect-error const transition = document.startViewTransition( () => performPush() ); diff --git a/packages/vips/README.md b/packages/vips/README.md index d7bf6001b51027..fe367e3bb6490c 100644 --- a/packages/vips/README.md +++ b/packages/vips/README.md @@ -42,7 +42,7 @@ _Parameters_ _Returns_ -- `Promise< ArrayBuffer >`: Compressed file data. +- `Promise< ArrayBuffer | ArrayBufferLike >`: Compressed file data. ### convertImageFormat @@ -83,7 +83,7 @@ _Parameters_ _Returns_ -- `Promise< { buffer: ArrayBuffer; width: number; height: number; originalWidth: number; originalHeight: number; } >`: Processed file data plus the old and new dimensions. +- `Promise< { buffer: ArrayBuffer | ArrayBufferLike; width: number; height: number; originalWidth: number; originalHeight: number; } >`: Processed file data plus the old and new dimensions. ### setLocation diff --git a/packages/vips/src/index.ts b/packages/vips/src/index.ts index 5dffe1f0808f28..dcd1858f0e57fb 100644 --- a/packages/vips/src/index.ts +++ b/packages/vips/src/index.ts @@ -122,7 +122,7 @@ export async function convertImageFormat( outputType: string, quality = 0.82, interlaced = false -): Promise< ArrayBuffer > { +): Promise< ArrayBuffer | ArrayBufferLike > { const ext = outputType.split( '/' )[ 1 ]; inProgressOperations.add( id ); @@ -186,7 +186,7 @@ export async function compressImage( type: string, quality = 0.82, interlaced = false -): Promise< ArrayBuffer > { +): Promise< ArrayBuffer | ArrayBufferLike > { return convertImageFormat( id, buffer, type, type, quality, interlaced ); } @@ -207,7 +207,7 @@ export async function resizeImage( resize: ImageSizeCrop, smartCrop = false ): Promise< { - buffer: ArrayBuffer; + buffer: ArrayBuffer | ArrayBufferLike; width: number; height: number; originalWidth: number; From 9e76f0f301643adc1ee0446ab61da5137dc11ec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= <grzegorz@gziolo.pl> Date: Fri, 6 Dec 2024 09:18:43 +0100 Subject: [PATCH 1885/1908] Build: Stop generating unused legacy scripts for core blocks (#65268) * Build: Stop generating unused legacy scripts for core blocks * Refactor Form block to use view script module Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- lib/experimental/blocks.php | 19 ++++++++++ packages/block-library/package.json | 1 + packages/block-library/src/form/block.json | 3 +- packages/block-library/src/form/index.php | 21 +---------- packages/block-library/src/form/view.js | 23 +++++++++--- tools/webpack/blocks.js | 43 +--------------------- 6 files changed, 41 insertions(+), 69 deletions(-) diff --git a/lib/experimental/blocks.php b/lib/experimental/blocks.php index 68113276ec1c06..b4bf0d409b1596 100644 --- a/lib/experimental/blocks.php +++ b/lib/experimental/blocks.php @@ -117,3 +117,22 @@ function gutenberg_register_block_style( $block_name, $style_properties ) { return $result; } + +/** + * Additional data to expose to the view script module in the Form block. + */ +function gutenberg_block_core_form_view_script_module( $data ) { + if ( ! gutenberg_is_experiment_enabled( 'gutenberg-form-blocks' ) ) { + return $data; + } + + $data['nonce'] = wp_create_nonce( 'wp-block-form' ); + $data['ajaxUrl'] = admin_url( 'admin-ajax.php' ); + $data['action'] = 'wp_block_form_email_submit'; + + return $data; +} +add_filter( + 'script_module_data_@wordpress/block-library/form/view', + 'gutenberg_block_core_form_view_script_module' +); diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 77da5721abacb1..ab95896035c9f0 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -28,6 +28,7 @@ "wpScript": true, "wpScriptModuleExports": { "./file/view": "./build-module/file/view.js", + "./form/view": "./build-module/form/view.js", "./image/view": "./build-module/image/view.js", "./navigation/view": "./build-module/navigation/view.js", "./query/view": "./build-module/query/view.js", diff --git a/packages/block-library/src/form/block.json b/packages/block-library/src/form/block.json index fa5212822cc71e..20f3b89dc62b0c 100644 --- a/packages/block-library/src/form/block.json +++ b/packages/block-library/src/form/block.json @@ -64,6 +64,5 @@ } }, "__experimentalSelector": "form" - }, - "viewScript": "file:./view.min.js" + } } diff --git a/packages/block-library/src/form/index.php b/packages/block-library/src/form/index.php index c887d46ad86188..d2b4942d6a50b3 100644 --- a/packages/block-library/src/form/index.php +++ b/packages/block-library/src/form/index.php @@ -14,6 +14,7 @@ * @return string The content of the block being rendered. */ function render_block_core_form( $attributes, $content ) { + wp_enqueue_script_module( '@wordpress/block-library/form/view' ); $processed_content = new WP_HTML_Tag_Processor( $content ); $processed_content->next_tag( 'form' ); @@ -42,26 +43,6 @@ function render_block_core_form( $attributes, $content ) { ); } -/** - * Additional data to add to the view.js script for this block. - */ -function block_core_form_view_script() { - if ( ! gutenberg_is_experiment_enabled( 'gutenberg-form-blocks' ) ) { - return; - } - - wp_localize_script( - 'wp-block-form-view', - 'wpBlockFormSettings', - array( - 'nonce' => wp_create_nonce( 'wp-block-form' ), - 'ajaxUrl' => admin_url( 'admin-ajax.php' ), - 'action' => 'wp_block_form_email_submit', - ) - ); -} -add_action( 'wp_enqueue_scripts', 'block_core_form_view_script' ); - /** * Adds extra fields to the form. * diff --git a/packages/block-library/src/form/view.js b/packages/block-library/src/form/view.js index d162d66020f44b..43e5af99e21286 100644 --- a/packages/block-library/src/form/view.js +++ b/packages/block-library/src/form/view.js @@ -1,8 +1,21 @@ +let formSettings; +try { + formSettings = JSON.parse( + document.getElementById( + 'wp-script-module-data-@wordpress/block-library/form/view' + )?.textContent + ); +} catch {} + // eslint-disable-next-line eslint-comments/disable-enable-pair /* eslint-disable no-undef */ document.querySelectorAll( 'form.wp-block-form' ).forEach( function ( form ) { - // Bail If the form is not using the mailto: action. - if ( ! form.action || ! form.action.startsWith( 'mailto:' ) ) { + // Bail If the form settings not provided or the form is not using the mailto: action. + if ( + ! formSettings || + ! form.action || + ! form.action.startsWith( 'mailto:' ) + ) { return; } @@ -18,13 +31,13 @@ document.querySelectorAll( 'form.wp-block-form' ).forEach( function ( form ) { // Get the form data and merge it with the form action and nonce. const formData = Object.fromEntries( new FormData( form ).entries() ); formData.formAction = form.action; - formData._ajax_nonce = wpBlockFormSettings.nonce; - formData.action = wpBlockFormSettings.action; + formData._ajax_nonce = formSettings.nonce; + formData.action = formSettings.action; formData._wp_http_referer = window.location.href; formData.formAction = form.action; try { - const response = await fetch( wpBlockFormSettings.ajaxUrl, { + const response = await fetch( formSettings.ajaxUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', diff --git a/tools/webpack/blocks.js b/tools/webpack/blocks.js index 02a379d3cdae20..c05318d5b060f3 100644 --- a/tools/webpack/blocks.js +++ b/tools/webpack/blocks.js @@ -3,13 +3,11 @@ */ const CopyWebpackPlugin = require( 'copy-webpack-plugin' ); const { join, sep, basename } = require( 'path' ); -const fastGlob = require( 'fast-glob' ); const { realpathSync } = require( 'fs' ); /** * WordPress dependencies */ -const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' ); const { PhpFilePathsPlugin } = require( '@wordpress/scripts/utils' ); /** @@ -17,13 +15,6 @@ const { PhpFilePathsPlugin } = require( '@wordpress/scripts/utils' ); */ const { baseConfig, plugins, stylesTransform } = require( './shared' ); -/* - * Matches a block's filepaths in the form build-module/<filename>.js - */ -const blockViewRegex = new RegExp( - /build-module\/(?<filename>.*\/view.*).js$/ -); - /** * We need to automatically rename some functions when they are called inside block files, * but have been declared elsewhere. This way we can call Gutenberg override functions, but @@ -50,48 +41,16 @@ function escapeRegExp( string ) { return string.replace( /[\\^$.*+?()[\]{}|]/g, '\\$&' ); } -const createEntrypoints = () => { - /* - * Returns an array of paths to block view files within the `@wordpress/block-library` package. - * These paths can be matched by the regex `blockViewRegex` in order to extract - * the block's filename. All blocks were migrated to script modules but the Form block. - * - * Returns an empty array if no files were found. - */ - const blockViewScriptPaths = fastGlob.sync( - './packages/block-library/build-module/form/view.js' - ); - - /* - * Go through the paths found above, in order to define webpack entry points for - * each block's view.js file. - */ - return blockViewScriptPaths.reduce( ( entries, scriptPath ) => { - const result = scriptPath.match( blockViewRegex ); - if ( ! result?.groups?.filename ) { - return entries; - } - - return { - ...entries, - [ result.groups.filename ]: scriptPath, - }; - }, {} ); -}; - module.exports = [ { ...baseConfig, name: 'blocks', - entry: createEntrypoints(), + entry: {}, output: { - devtoolNamespace: 'wp', - filename: './build/block-library/blocks/[name].min.js', path: join( __dirname, '..', '..' ), }, plugins: [ ...plugins, - new DependencyExtractionWebpackPlugin( { injectPolyfill: false } ), new PhpFilePathsPlugin( { context: './packages/block-library/src/', props: [ 'render', 'variations' ], From d59faffa3d270dbc7716f653b4cdab6020812658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= <grzegorz@gziolo.pl> Date: Fri, 6 Dec 2024 09:54:31 +0100 Subject: [PATCH 1886/1908] WP Scripts: Update webpack dependencies related to styling (#67572) * WP Scripts: Update webpack dependencies related to styling * Update test snapshots after webpack version changed * Update links in the changelog file * Remove accidently added dependency Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: sirreal <jonsurrell@git.wordpress.org> --- package-lock.json | 893 ++++++++---------- package.json | 6 +- .../test/__snapshots__/build.js.snap | 12 +- packages/scripts/CHANGELOG.md | 7 + packages/scripts/config/webpack.config.js | 6 +- packages/scripts/package.json | 8 +- 6 files changed, 418 insertions(+), 514 deletions(-) diff --git a/package-lock.json b/package-lock.json index 478be0c4ecfea5..a17e89f944c72b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -140,8 +140,8 @@ "resize-observer-polyfill": "1.5.1", "rimraf": "3.0.2", "rtlcss": "4.0.0", - "sass": "1.35.2", - "sass-loader": "12.1.0", + "sass": "1.50.1", + "sass-loader": "16.0.3", "semver": "7.5.4", "simple-git": "3.24.0", "snapshot-diff": "0.10.0", @@ -156,7 +156,7 @@ "typescript": "5.7.2", "uuid": "9.0.1", "webdriverio": "8.16.20", - "webpack": "5.95.0", + "webpack": "5.97.0", "webpack-bundle-analyzer": "4.9.1", "worker-farm": "1.7.0" }, @@ -14681,9 +14681,10 @@ } }, "node_modules/@types/bonjour": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.11.tgz", - "integrity": "sha512-isGhjmBtLIxdHBDl2xGwUzEM8AOyOvWsADWq7rqirdi/ZQoHnLWErHvsThcEzTX8juDRiZtzp2Qkv5bgNh6mAg==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -14708,9 +14709,10 @@ } }, "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.1.tgz", - "integrity": "sha512-iaQslNbARe8fctL5Lk+DsmgWOM83lM+7FzP0eQUJs1jd3kBE8NWqBTIT2S8SqQOJjxvt2eyIjpOuYeRXq2AdMw==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "license": "MIT", "dependencies": { "@types/express-serve-static-core": "*", "@types/node": "*" @@ -14759,12 +14761,21 @@ "version": "8.56.9", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.9.tgz", "integrity": "sha512-W4W3KcqzjJ0sHg2vAq9vfml6OhsJ53TcUjUqfzzZf/EChUtwspszj/S0pzMxnfRcO55/iGq47dscXw71Fxc4Zg==", - "dev": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -14974,7 +14985,8 @@ "node_modules/@types/mime": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", - "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==" + "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==", + "dev": true }, "node_modules/@types/mime-types": { "version": "2.1.4", @@ -15031,6 +15043,15 @@ "form-data": "^4.0.0" } }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/normalize-package-data": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz", @@ -15158,9 +15179,10 @@ } }, "node_modules/@types/retry": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", - "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==" + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" }, "node_modules/@types/scheduler": { "version": "0.16.2", @@ -15197,21 +15219,23 @@ } }, "node_modules/@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "license": "MIT", "dependencies": { "@types/express": "*" } }, "node_modules/@types/serve-static": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", - "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "license": "MIT", "dependencies": { "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" + "@types/node": "*", + "@types/send": "*" } }, "node_modules/@types/shell-quote": { @@ -15229,9 +15253,10 @@ } }, "node_modules/@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -16908,24 +16933,27 @@ } }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "license": "MIT", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-numbers/node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers/node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.9.0", @@ -17649,14 +17677,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/acorn-jsx": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", @@ -19144,7 +19164,6 @@ "version": "9.2.1", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", - "dev": true, "license": "MIT", "dependencies": { "find-cache-dir": "^4.0.0", @@ -19162,7 +19181,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -19179,7 +19197,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -19191,7 +19208,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", - "dev": true, "dependencies": { "common-path-prefix": "^3.0.0", "pkg-dir": "^7.0.0" @@ -19207,7 +19223,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, "dependencies": { "locate-path": "^7.1.0", "path-exists": "^5.0.0" @@ -19222,14 +19237,12 @@ "node_modules/babel-loader/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/babel-loader/node_modules/locate-path": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, "dependencies": { "p-locate": "^6.0.0" }, @@ -19244,7 +19257,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, "dependencies": { "yocto-queue": "^1.0.0" }, @@ -19259,7 +19271,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, "dependencies": { "p-limit": "^4.0.0" }, @@ -19274,7 +19285,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } @@ -19283,7 +19293,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", - "dev": true, "dependencies": { "find-up": "^6.3.0" }, @@ -19298,7 +19307,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -19317,7 +19325,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", - "dev": true, "license": "MIT", "engines": { "node": ">=12.20" @@ -19939,21 +19946,15 @@ } }, "node_modules/bonjour-service": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", - "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", + "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", + "license": "MIT", "dependencies": { - "array-flatten": "^2.1.2", - "dns-equal": "^1.0.0", "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" } }, - "node_modules/bonjour-service/node_modules/array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" - }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -23540,6 +23541,7 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "license": "BSD-2-Clause", "dependencies": { "execa": "^5.0.0" }, @@ -23548,9 +23550,10 @@ } }, "node_modules/default-gateway/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -23564,6 +23567,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -23586,6 +23590,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -23597,6 +23602,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "license": "Apache-2.0", "engines": { "node": ">=10.17.0" } @@ -23605,6 +23611,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -23616,6 +23623,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", "engines": { "node": ">=6" } @@ -23624,6 +23632,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", "dependencies": { "path-key": "^3.0.0" }, @@ -23635,6 +23644,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -23649,6 +23659,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", "engines": { "node": ">=8" } @@ -23657,6 +23668,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -23668,6 +23680,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", "engines": { "node": ">=8" } @@ -23676,6 +23689,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -24235,11 +24249,6 @@ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", "dev": true }, - "node_modules/dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" - }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -29342,6 +29351,12 @@ "resolved": "https://registry.npmjs.org/image-ssim/-/image-ssim-0.2.0.tgz", "integrity": "sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==" }, + "node_modules/immutable": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", + "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", + "license": "MIT" + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -31103,6 +31118,60 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/jest-dev-server": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jest-dev-server/-/jest-dev-server-9.0.2.tgz", + "integrity": "sha512-Zc/JB0IlNNrpXkhBw+h86cGrde/Mey52KvF+FER2eyrtYJTHObOwW7Iarxm3rPyTKby5+3Y2QZtl8pRz/5GCxg==", + "dependencies": { + "chalk": "^4.1.2", + "cwd": "^0.10.0", + "find-process": "^1.4.7", + "prompts": "^2.4.2", + "spawnd": "^9.0.2", + "tree-kill": "^1.2.2", + "wait-on": "^7.2.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/jest-dev-server/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-dev-server/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-dev-server/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -32269,12 +32338,13 @@ } }, "node_modules/launch-editor": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", - "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", + "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", + "license": "MIT", "dependencies": { "picocolors": "^1.0.0", - "shell-quote": "^1.7.3" + "shell-quote": "^1.8.1" } }, "node_modules/lazy-cache": { @@ -36474,11 +36544,13 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.1.tgz", - "integrity": "sha512-CRC6E2yedNjfOA3nQjpqAkpnranxhxmilhBPYtldnXcPT/QZb3aJFzvt0pp8W1jhuLR/E0zDa+QEHuC/HhhaLQ==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", + "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", + "license": "MIT", "dependencies": { - "schema-utils": "^4.0.0" + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" }, "engines": { "node": ">= 12.13.0" @@ -36511,6 +36583,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -36521,12 +36594,14 @@ "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" }, "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -36541,6 +36616,15 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/mini-css-extract-plugin/node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -39574,11 +39658,12 @@ } }, "node_modules/p-retry": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", - "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", "dependencies": { - "@types/retry": "^0.12.0", + "@types/retry": "0.12.0", "retry": "^0.13.1" }, "engines": { @@ -39589,6 +39674,7 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", "engines": { "node": ">= 4" } @@ -44990,42 +45076,46 @@ } }, "node_modules/sass": { - "version": "1.35.2", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.35.2.tgz", - "integrity": "sha512-jhO5KAR+AMxCEwIH3v+4zbB2WB0z67V1X0jbapfVwQQdjHZUGUyukpnoM6+iCMfsIUC016w9OPKQ5jrNOS9uXw==", + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.50.1.tgz", + "integrity": "sha512-noTnY41KnlW2A9P8sdwESpDmo+KBNkukI1i8+hOK3footBUcohNHtdOJbckp46XO95nuvcHDDZ+4tmOnpK3hjw==", + "license": "MIT", "dependencies": { - "chokidar": ">=3.0.0 <4.0.0" + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { "sass": "sass.js" }, "engines": { - "node": ">=8.9.0" + "node": ">=12.0.0" } }, "node_modules/sass-loader": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.1.0.tgz", - "integrity": "sha512-FVJZ9kxVRYNZTIe2xhw93n3xJNYZADr+q69/s98l9nTCrWASo+DR2Ot0s5xTKQDDEosUkatsGeHxcH4QBp5bSg==", + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.3.tgz", + "integrity": "sha512-gosNorT1RCkuCMyihv6FBRR7BMV06oKRAs+l4UMp1mlcVg9rWN6KMmUj3igjQwmYys4mDP3etEYJgiHRbgHCHA==", + "license": "MIT", "dependencies": { - "klona": "^2.0.4", "neo-async": "^2.6.2" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0", + "@rspack/core": "0.x || 1.x", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", "sass": "^1.3.0", + "sass-embedded": "*", "webpack": "^5.0.0" }, "peerDependenciesMeta": { - "fibers": { + "@rspack/core": { "optional": true }, "node-sass": { @@ -45033,6 +45123,12 @@ }, "sass": { "optional": true + }, + "sass-embedded": { + "optional": true + }, + "webpack": { + "optional": true } } }, @@ -45102,10 +45198,12 @@ "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" }, "node_modules/selfsigned": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", - "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "license": "MIT", "dependencies": { + "@types/node-forge": "^1.3.0", "node-forge": "^1" }, "engines": { @@ -46244,6 +46342,30 @@ "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", "dev": true }, + "node_modules/spawnd": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-9.0.2.tgz", + "integrity": "sha512-nl8DVHEDQ57IcKakzpjanspVChkMpGLuVwMR/eOn9cXE55Qr6luD2Kn06sA0ootRMdgrU4tInN6lA6ohTNvysw==", + "dependencies": { + "signal-exit": "^4.1.0", + "tree-kill": "^1.2.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/spawnd/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/spdx-correct": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", @@ -49578,6 +49700,45 @@ "node": ">=18" } }, + "node_modules/wait-on": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.2.0.tgz", + "integrity": "sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ==", + "license": "MIT", + "dependencies": { + "axios": "^1.6.1", + "joi": "^17.11.0", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "rxjs": "^7.8.1" + }, + "bin": { + "wait-on": "bin/wait-on" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/wait-on/node_modules/axios": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.8.tgz", + "integrity": "sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/wait-on/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/wait-port": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/wait-port/-/wait-port-1.1.0.tgz", @@ -50338,17 +50499,18 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/webpack": { - "version": "5.95.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", - "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", - "dependencies": { - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-attributes": "^1.9.5", - "browserslist": "^4.21.10", + "version": "5.97.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.0.tgz", + "integrity": "sha512-CWT8v7ShSfj7tGs4TLRtaOLmOCPWhoKEvp+eA7FVx8Xrjb3XfT0aXdxDItnRZmE8sHcH+a8ayDrJCOjXKxVFfQ==", + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", @@ -50669,9 +50831,10 @@ } }, "node_modules/webpack-dev-server": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", - "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", + "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", + "license": "MIT", "dependencies": { "@types/bonjour": "^3.5.9", "@types/connect-history-api-fallback": "^1.3.5", @@ -50701,7 +50864,7 @@ "serve-index": "^1.9.1", "sockjs": "^0.3.24", "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", + "webpack-dev-middleware": "^5.3.4", "ws": "^8.13.0" }, "bin": { @@ -50746,6 +50909,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -50756,12 +50920,14 @@ "node_modules/webpack-dev-server/node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" }, "node_modules/webpack-dev-server/node_modules/ipaddr.js": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "license": "MIT", "engines": { "node": ">= 10" } @@ -50770,6 +50936,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", "dependencies": { "is-docker": "^2.0.0" }, @@ -50780,12 +50947,14 @@ "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" }, "node_modules/webpack-dev-server/node_modules/open": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -50802,6 +50971,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -50820,6 +50990,7 @@ "version": "5.3.4", "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "license": "MIT", "dependencies": { "colorette": "^2.0.10", "memfs": "^3.4.3", @@ -50896,126 +51067,145 @@ "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", "dev": true }, + "node_modules/webpack/node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "license": "MIT" + }, "node_modules/webpack/node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "license": "MIT", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "node_modules/webpack/node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT" }, "node_modules/webpack/node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "license": "MIT" }, "node_modules/webpack/node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "license": "MIT" }, "node_modules/webpack/node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, "node_modules/webpack/node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "license": "MIT", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/webpack/node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "license": "Apache-2.0", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/webpack/node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "license": "MIT" }, "node_modules/webpack/node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, "node_modules/webpack/node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/webpack/node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, "node_modules/webpack/node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/webpack/node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, "node_modules/webpack/node_modules/acorn": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", - "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -55600,7 +55790,7 @@ "json2php": "^0.0.9", "markdownlint-cli": "^0.31.1", "merge-deep": "^3.0.3", - "mini-css-extract-plugin": "^2.5.1", + "mini-css-extract-plugin": "^2.9.2", "minimist": "^1.2.0", "npm-package-json-lint": "^6.4.0", "npm-packlist": "^3.0.0", @@ -55612,14 +55802,14 @@ "read-pkg-up": "^7.0.1", "resolve-bin": "^0.4.0", "rtlcss-webpack-plugin": "^4.0.7", - "sass": "^1.35.2", - "sass-loader": "^12.1.0", + "sass": "^1.50.1", + "sass-loader": "^16.0.3", "schema-utils": "^4.2.0", "source-map-loader": "^3.0.0", "stylelint": "^16.8.2", "terser-webpack-plugin": "^5.3.10", "url-loader": "^4.1.1", - "webpack": "^5.95.0", + "webpack": "^5.97.0", "webpack-bundle-analyzer": "^4.9.1", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1" @@ -55653,154 +55843,16 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "packages/scripts/node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "packages/scripts/node_modules/babel-loader": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.4.1.tgz", - "integrity": "sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==", + "packages/scripts/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "license": "MIT", "dependencies": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.4", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" - }, - "engines": { - "node": ">= 8.9" + "fast-deep-equal": "^3.1.3" }, "peerDependencies": { - "@babel/core": "^7.0.0", - "webpack": ">=2" - } - }, - "packages/scripts/node_modules/babel-loader/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "packages/scripts/node_modules/babel-loader/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "license": "MIT" - }, - "packages/scripts/node_modules/babel-loader/node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "packages/scripts/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "packages/scripts/node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "packages/scripts/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "packages/scripts/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "packages/scripts/node_modules/jest-dev-server": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/jest-dev-server/-/jest-dev-server-9.0.1.tgz", - "integrity": "sha512-eqpJKSvVl4M0ojHZUPNbka8yEzLNbIMiINXDsuMF3lYfIdRO2iPqy+ASR4wBQ6nUyR3OT24oKPWhpsfLhgAVyg==", - "dependencies": { - "chalk": "^4.1.2", - "cwd": "^0.10.0", - "find-process": "^1.4.7", - "prompts": "^2.4.2", - "spawnd": "^9.0.1", - "tree-kill": "^1.2.2", - "wait-on": "^7.0.1" - }, - "engines": { - "node": ">=16" - } - }, - "packages/scripts/node_modules/joi": { - "version": "17.11.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", - "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", - "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" + "ajv": "^8.8.2" } }, "packages/scripts/node_modules/json-schema-traverse": { @@ -55815,91 +55867,6 @@ "integrity": "sha512-fQMYwvPsQt8hxRnCGyg1r2JVi6yL8Um0DIIawiKiMK9yhAAkcRNj5UsBWoaFvFzPpcWbgw9L6wzj+UMYA702Mw==", "license": "BSD" }, - "packages/scripts/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "packages/scripts/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "packages/scripts/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "packages/scripts/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "packages/scripts/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "engines": { - "node": ">=6" - } - }, - "packages/scripts/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "packages/scripts/node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "packages/scripts/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "packages/scripts/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", @@ -55919,78 +55886,6 @@ "url": "https://opencollective.com/webpack" } }, - "packages/scripts/node_modules/schema-utils/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "packages/scripts/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "packages/scripts/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "packages/scripts/node_modules/spawnd": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-9.0.1.tgz", - "integrity": "sha512-vaMk8E9CpbjTYToBxLXowDeArGf1+yI7A6PU6Nr57b2g8BVY8nRi5vTBj3bMF8UkCrMdTMyf/Lh+lrcrW2z7pw==", - "dependencies": { - "signal-exit": "^4.1.0", - "tree-kill": "^1.2.2" - }, - "engines": { - "node": ">=16" - } - }, - "packages/scripts/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "packages/scripts/node_modules/wait-on": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.2.0.tgz", - "integrity": "sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ==", - "dependencies": { - "axios": "^1.6.1", - "joi": "^17.11.0", - "lodash": "^4.17.21", - "minimist": "^1.2.8", - "rxjs": "^7.8.1" - }, - "bin": { - "wait-on": "bin/wait-on" - }, - "engines": { - "node": ">=12.0.0" - } - }, "packages/server-side-render": { "name": "@wordpress/server-side-render", "version": "5.13.0", diff --git a/package.json b/package.json index 9c074897ed14a1..ce32c8071cce03 100644 --- a/package.json +++ b/package.json @@ -149,8 +149,8 @@ "resize-observer-polyfill": "1.5.1", "rimraf": "3.0.2", "rtlcss": "4.0.0", - "sass": "1.35.2", - "sass-loader": "12.1.0", + "sass": "1.50.1", + "sass-loader": "16.0.3", "semver": "7.5.4", "simple-git": "3.24.0", "snapshot-diff": "0.10.0", @@ -165,7 +165,7 @@ "typescript": "5.7.2", "uuid": "9.0.1", "webdriverio": "8.16.20", - "webpack": "5.95.0", + "webpack": "5.97.0", "webpack-bundle-analyzer": "4.9.1", "worker-farm": "1.7.0" }, diff --git a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap index bafae8eb914867..be69ee891743da 100644 --- a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap +++ b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap @@ -41,7 +41,7 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-dependency-g `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-dynamic-dependency-graph\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array(array('id' => '@wordpress/interactivity', 'import' => 'dynamic')), 'version' => '3e43f50123c85675372f', 'type' => 'module'); +"<?php return array('dependencies' => array(array('id' => '@wordpress/interactivity', 'import' => 'dynamic')), 'version' => '3ca651be783423315165', 'type' => 'module'); " `; @@ -71,7 +71,7 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-external-dep `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`dynamic-import\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array(array('id' => '@wordpress/blob', 'import' => 'dynamic')), 'version' => '1c950858231a54e241b8', 'type' => 'module'); +"<?php return array('dependencies' => array(array('id' => '@wordpress/blob', 'import' => 'dynamic')), 'version' => 'fbb215dc4902543bce35', 'type' => 'module'); " `; @@ -265,17 +265,17 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comm exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comment-minified\` should produce expected output: External modules should match snapshot 1`] = `[]`; exports[`DependencyExtractionWebpackPlugin modules Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'a.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('@wordpress/blob'), 'version' => 'ee5ac21a1f0003d732e6', 'type' => 'module', 'handle' => 'runtime-chunk-single-modules-a'); +"<?php return array('dependencies' => array('@wordpress/blob'), 'version' => 'ab7fa97b1381e41e0f70', 'type' => 'module', 'handle' => 'runtime-chunk-single-modules-a'); " `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'b.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array('@wordpress/blob', 'lodash'), 'version' => '5b112b32c6db548c2997', 'type' => 'module', 'handle' => 'runtime-chunk-single-modules-b'); +"<?php return array('dependencies' => array('@wordpress/blob', 'lodash'), 'version' => '498fd24026d68fa84ba9', 'type' => 'module', 'handle' => 'runtime-chunk-single-modules-b'); " `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'runtime.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array(), 'version' => 'b1ca4106075e0bd94f9c', 'type' => 'module', 'handle' => 'runtime-chunk-single-modules-runtime'); +"<?php return array('dependencies' => array(), 'version' => '5ac0d6987a8e7fe809a3', 'type' => 'module', 'handle' => 'runtime-chunk-single-modules-runtime'); " `; @@ -556,7 +556,7 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`module-renames\` sh `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`no-default\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -"<?php return array('dependencies' => array(), 'version' => '43880e6c42e7c39fcdf1'); +"<?php return array('dependencies' => array(), 'version' => 'be8b28b738de0d6b883a'); " `; diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index ceaa25c4ff9a09..969b2ce0f68f00 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,13 @@ ## Unreleased +### Internal + +- The bundled `sass` dependency has been updated from `^1.35.2` to `^1.50.1` ([#67572](https://github.com/WordPress/gutenberg/pull/67572)). +- The bundled `sass-loader` dependency has been updated from `^12.1.0` to `^16.0.3` ([#67572](https://github.com/WordPress/gutenberg/pull/67572)). +- The bundled `mini-css-extract-plugin` dependency has been updated from `^2.5.1` to `^2.9.2` ([#67572](https://github.com/WordPress/gutenberg/pull/67572)). +- The bundled `webpack` dependency has been updated from `^5.95.0` to `^5.97.0` ([#67572](https://github.com/WordPress/gutenberg/pull/67572)). + ### Bug Fix - Make React Fast Refresh in the `start` command work with multiple blocks ([64924](https://github.com/WordPress/gutenberg/pull/64924)). diff --git a/packages/scripts/config/webpack.config.js b/packages/scripts/config/webpack.config.js index 2c3d423fcbd1e8..1829da5cdc15da 100644 --- a/packages/scripts/config/webpack.config.js +++ b/packages/scripts/config/webpack.config.js @@ -103,7 +103,7 @@ const baseConfig = { target, output: { filename: '[name].js', - chunkFilename: '[name].js?v=[chunkhash]', + chunkFilename: '[name].js?ver=[chunkhash]', path: resolve( process.cwd(), 'build' ), }, resolve: { @@ -392,7 +392,9 @@ const scriptConfig = { // bundle content as a convenient interactive zoomable treemap. process.env.WP_BUNDLE_ANALYZER && new BundleAnalyzerPlugin(), // MiniCSSExtractPlugin to extract the CSS thats gets imported into JavaScript. - new MiniCSSExtractPlugin( { filename: '[name].css' } ), + new MiniCSSExtractPlugin( { + filename: '[name].css', + } ), // RtlCssPlugin to generate RTL CSS files. new RtlCssPlugin( { filename: `[name]-rtl.css`, diff --git a/packages/scripts/package.json b/packages/scripts/package.json index f3e6b325f6d3be..07d4dd27e4a450 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -69,7 +69,7 @@ "json2php": "^0.0.9", "markdownlint-cli": "^0.31.1", "merge-deep": "^3.0.3", - "mini-css-extract-plugin": "^2.5.1", + "mini-css-extract-plugin": "^2.9.2", "minimist": "^1.2.0", "npm-package-json-lint": "^6.4.0", "npm-packlist": "^3.0.0", @@ -81,14 +81,14 @@ "read-pkg-up": "^7.0.1", "resolve-bin": "^0.4.0", "rtlcss-webpack-plugin": "^4.0.7", - "sass": "^1.35.2", - "sass-loader": "^12.1.0", + "sass": "^1.50.1", + "sass-loader": "^16.0.3", "schema-utils": "^4.2.0", "source-map-loader": "^3.0.0", "stylelint": "^16.8.2", "terser-webpack-plugin": "^5.3.10", "url-loader": "^4.1.1", - "webpack": "^5.95.0", + "webpack": "^5.97.0", "webpack-bundle-analyzer": "^4.9.1", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1" From 6b16c7359862d7131df1c06e598b2480833f248f Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Fri, 6 Dec 2024 09:55:38 +0100 Subject: [PATCH 1887/1908] DataViews: Unify layout config (#67477) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: lsl <louislaugesen@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> --- packages/dataviews/CHANGELOG.md | 15 + packages/dataviews/README.md | 53 +- .../dataviews-selection-checkbox/index.tsx | 8 +- .../dataviews-view-config/index.tsx | 484 +++++++++++------- .../dataviews-view-config/style.scss | 9 + .../components/dataviews/stories/fixtures.tsx | 3 - .../dataviews/stories/index.story.tsx | 120 +---- .../src/components/dataviews/style.scss | 76 ++- .../src/dataviews-layouts/grid/index.tsx | 203 ++++---- .../src/dataviews-layouts/grid/style.scss | 39 +- .../dataviews/src/dataviews-layouts/index.ts | 88 ---- .../src/dataviews-layouts/list/index.tsx | 78 +-- .../table/column-header-menu.tsx | 180 +++---- .../table/column-primary.tsx | 58 +++ .../src/dataviews-layouts/table/index.tsx | 221 ++++---- .../src/dataviews-layouts/table/style.scss | 4 + .../utils/get-clickable-item-props.ts | 6 +- packages/dataviews/src/types.ts | 67 +-- .../src/components/page-patterns/index.js | 12 +- .../src/components/page-templates/index.js | 40 +- .../src/components/post-list/index.js | 2 +- .../sidebar-dataviews/default-views.js | 31 +- 22 files changed, 843 insertions(+), 954 deletions(-) create mode 100644 packages/dataviews/src/dataviews-layouts/table/column-primary.tsx diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 7ec1b24f8745c0..6b6f8ef6b54e11 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,21 @@ ## Unreleased +## Breaking Changes + +- Support showing or hiding title, media and description fields ([#67477](https://github.com/WordPress/gutenberg/pull/67477)). +- Unify the `title`, `media` and `description` fields for the different layouts. So instead of the previous `view.layout.mediaField`, `view.layout.primaryField` and `view.layout.columnFields`, all the layouts now support these three fields with the following config ([#67477](https://github.com/WordPress/gutenberg/pull/67477)): + +```js +const view = { + type: 'table', + titleField: 'title', + mediaField: 'media', + descriptionField: 'description', + fields: [ 'author', 'date' ], +} +``` + ## Internal - Upgraded `@ariakit/react` (v0.4.13) and `@ariakit/test` (v0.4.5) ([#65907](https://github.com/WordPress/gutenberg/pull/65907)). diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 04b8a40ff3fa7e..651d87268c28e1 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -165,6 +165,7 @@ const view = { field: 'date', direction: 'desc', }, + titleField: 'title', fields: [ 'author', 'status' ], layout: {}, }; @@ -184,50 +185,22 @@ Properties: - `field`: the field used for sorting the dataset. - `direction`: the direction to use for sorting, one of `asc` or `desc`. - -- `fields`: a list of field `id` that are visible in the UI and the specific order in which they are displayed. +- `titleField`: The id of the field reprensenting the title of the record. +- `mediaField`: The id of the field reprensenting the media of the record. +- `descriptionField`: The id of field the reprensenting the description of the record. +- `showTitle`: Whether the title should be shown in the UI. `true` by default. +- `showMedia`: Whether the media should be shown in the UI. `true` by default. +- `showDescription`: Whether the description should be shown in the UI. `true` by default. +- `fields`: a list of remaining field `id` that are visible in the UI and the specific order in which they are displayed. - `layout`: config that is specific to a particular layout type. ##### Properties of `layout` | Properties of `layout` | Table | Grid | List | | --------------------------------------------------------------------------------------------------------------- | ----- | ---- | ---- | -| `primaryField`: the field's `id` to be highlighted in each layout. It's not hidable. | ✓ | ✓ | ✓ | -| `mediaField`: the field's `id` to be used for rendering each card's media. It's not hiddable. | | ✓ | ✓ | -| `columnFields`: a list of field's `id` to render vertically stacked instead of horizontally (the default). | | ✓ | | | `badgeFields`: a list of field's `id` to render without label and styled as badges. | | ✓ | | -| `combinedFields`: a list of "virtual" fields that are made by combining others. See "Combining fields" section. | ✓ | | | | `styles`: additional `width`, `maxWidth`, `minWidth` styles for each field column. | ✓ | | | -##### Combining fields - -The `table` layout has the ability to create "virtual" fields that are made out by combining existing ones. - -Each "virtual field", has to provide an `id` and `label` (optionally a `header` instead), which have the same meaning as any other field. - -Additionally, they need to provide: - -- `children`: a list of field's `id` to combine -- `direction`: how should they be stacked, `vertical` or `horizontal` - -For example, this is how you'd define a `site` field which is a combination of a `title` and `description` fields, which are not displayed: - -```js -{ - fields: [ 'site', 'status' ], - layout: { - combinedFields: [ - { - id: 'site', - label: 'Site', - children: [ 'title', 'description' ], - direction: 'vertical', - } - ] - } -} -``` - #### `onChangeView`: `function` Callback executed when the view has changed. It receives the new view object as a parameter. @@ -255,6 +228,7 @@ function MyCustomPageTable() { value: [ 'publish', 'draft' ], }, ], + titleField: 'title', fields: [ 'author', 'status' ], layout: {}, } ); @@ -370,14 +344,15 @@ For example, this is how you'd enable only the table view type: ```js const defaultLayouts = { table: { - layout: { - primaryField: 'my-key', - }, + showMedia: false, }, + grid: { + showMedia: true, + } }; ``` -The `defaultLayouts` property should be an object that includes properties named `table`, `grid`, or `list`. Each of these properties should contain a `layout` property, which holds the configuration for each specific layout type. Check "Properties of layout" for the full list of properties available for each layout's configuration +The `defaultLayouts` property should be an object that includes properties named `table`, `grid`, or `list`. These properties are applied to the view object each time the user switches to the corresponding layout. #### `selection`: `string[]` diff --git a/packages/dataviews/src/components/dataviews-selection-checkbox/index.tsx b/packages/dataviews/src/components/dataviews-selection-checkbox/index.tsx index c71636618716ba..827f061976443e 100644 --- a/packages/dataviews/src/components/dataviews-selection-checkbox/index.tsx +++ b/packages/dataviews/src/components/dataviews-selection-checkbox/index.tsx @@ -15,7 +15,7 @@ interface DataViewsSelectionCheckboxProps< Item > { onChangeSelection: SetSelection; item: Item; getItemId: ( item: Item ) => string; - primaryField?: Field< Item >; + titleField?: Field< Item >; disabled: boolean; } @@ -24,19 +24,19 @@ export default function DataViewsSelectionCheckbox< Item >( { onChangeSelection, item, getItemId, - primaryField, + titleField, disabled, }: DataViewsSelectionCheckboxProps< Item > ) { const id = getItemId( item ); const checked = ! disabled && selection.includes( id ); let selectionLabel; - if ( primaryField?.getValue && item ) { + if ( titleField?.getValue && item ) { // eslint-disable-next-line @wordpress/valid-sprintf selectionLabel = sprintf( checked ? /* translators: %s: item title. */ __( 'Deselect item: %s' ) : /* translators: %s: item title. */ __( 'Select item: %s' ), - primaryField.getValue( { item } ) + titleField.getValue( { item } ) ); } else { selectionLabel = checked diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index f13670f27cdab7..28e48525ffa73b 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -23,29 +23,27 @@ import { __experimentalText as Text, privateApis as componentsPrivateApis, BaseControl, + Icon, } from '@wordpress/components'; import { __, _x, sprintf } from '@wordpress/i18n'; import { memo, useContext, useMemo } from '@wordpress/element'; -import { chevronDown, chevronUp, cog, seen, unseen } from '@wordpress/icons'; +import { + chevronDown, + chevronUp, + cog, + seen, + unseen, + lock, +} from '@wordpress/icons'; import warning from '@wordpress/warning'; import { useInstanceId } from '@wordpress/compose'; /** * Internal dependencies */ -import { - SORTING_DIRECTIONS, - LAYOUT_TABLE, - sortIcons, - sortLabels, -} from '../../constants'; -import { - VIEW_LAYOUTS, - getNotHidableFieldIds, - getVisibleFieldIds, - getHiddenFieldIds, -} from '../../dataviews-layouts'; -import type { SupportedLayouts, View, Field } from '../../types'; +import { SORTING_DIRECTIONS, sortIcons, sortLabels } from '../../constants'; +import { VIEW_LAYOUTS } from '../../dataviews-layouts'; +import type { NormalizedField, SupportedLayouts, View } from '../../types'; import DataViewsContext from '../dataviews-context'; import { unlock } from '../../lock-unlock'; @@ -93,8 +91,13 @@ function ViewTypeMenu( { case 'list': case 'grid': case 'table': + const viewWithoutLayout = { ...view }; + if ( 'layout' in viewWithoutLayout ) { + delete viewWithoutLayout.layout; + } + // @ts-expect-error return onChangeView( { - ...view, + ...viewWithoutLayout, type: e.target.value, ...defaultLayouts[ e.target.value ], } ); @@ -237,236 +240,331 @@ function ItemsPerPageControl() { ); } -interface FieldItemProps { - id: any; - label: string; - index: number; - isVisible: boolean; - isHidable: boolean; -} - function FieldItem( { - field: { id, label, index, isVisible, isHidable }, - fields, - view, - onChangeView, + field, + isVisible, + isFirst, + isLast, + canMove = true, + onToggleVisibility, + onMoveUp, + onMoveDown, }: { - field: FieldItemProps; - fields: Field< any >[]; - view: View; - onChangeView: ( view: View ) => void; + field: NormalizedField< any >; + isVisible: boolean; + isFirst?: boolean; + isLast?: boolean; + canMove?: boolean; + onToggleVisibility?: () => void; + onMoveUp?: () => void; + onMoveDown?: () => void; } ) { - const visibleFieldIds = getVisibleFieldIds( view, fields ); + const focusVisibilityField = () => { + // Focus the visibility button to avoid focus loss. + // Our code is safe against the component being unmounted, so we don't need to worry about cleaning the timeout. + // eslint-disable-next-line @wordpress/react-no-unsafe-timeout + setTimeout( () => { + const element = document.querySelector( + `.dataviews-field-control__field-${ field.id } .dataviews-field-control__field-visibility-button` + ); + if ( element instanceof HTMLElement ) { + element.focus(); + } + }, 50 ); + }; return ( - <Item key={ id }> + <Item> <HStack expanded - className={ `dataviews-field-control__field dataviews-field-control__field-${ id }` } + className={ `dataviews-field-control__field dataviews-field-control__field-${ field.id }` } + justify="flex-start" > - <span>{ label }</span> + <span className="dataviews-field-control__icon"> + { ! canMove && ! field.enableHiding && ( + <Icon icon={ lock } /> + ) } + </span> + <span className="dataviews-field-control__label"> + { field.label } + </span> <HStack justify="flex-end" expanded={ false } className="dataviews-field-control__actions" > - { view.type === LAYOUT_TABLE && isVisible && ( + { isVisible && ( <> <Button - disabled={ index < 1 } + disabled={ isFirst || ! canMove } accessibleWhenDisabled size="compact" - onClick={ () => { - onChangeView( { - ...view, - fields: [ - ...( visibleFieldIds.slice( - 0, - index - 1 - ) ?? [] ), - id, - visibleFieldIds[ index - 1 ], - ...visibleFieldIds.slice( - index + 1 - ), - ], - } ); - } } + onClick={ onMoveUp } icon={ chevronUp } - label={ sprintf( - /* translators: %s: field label */ - __( 'Move %s up' ), - label - ) } + label={ + isFirst || ! canMove + ? __( "This field can't be moved up" ) + : sprintf( + /* translators: %s: field label */ + __( 'Move %s up' ), + field.label + ) + } /> <Button - disabled={ index >= visibleFieldIds.length - 1 } + disabled={ isLast || ! canMove } accessibleWhenDisabled size="compact" - onClick={ () => { - onChangeView( { - ...view, - fields: [ - ...( visibleFieldIds.slice( - 0, - index - ) ?? [] ), - visibleFieldIds[ index + 1 ], - id, - ...visibleFieldIds.slice( - index + 2 - ), - ], - } ); - } } + onClick={ onMoveDown } icon={ chevronDown } - label={ sprintf( - /* translators: %s: field label */ - __( 'Move %s down' ), - label - ) } - />{ ' ' } + label={ + isLast || ! canMove + ? __( "This field can't be moved down" ) + : sprintf( + /* translators: %s: field label */ + __( 'Move %s down' ), + field.label + ) + } + /> </> ) } - <Button - className="dataviews-field-control__field-visibility-button" - disabled={ ! isHidable } - accessibleWhenDisabled - size="compact" - onClick={ () => { - onChangeView( { - ...view, - fields: isVisible - ? visibleFieldIds.filter( - ( fieldId ) => fieldId !== id + { onToggleVisibility && ( + <Button + className="dataviews-field-control__field-visibility-button" + disabled={ ! field.enableHiding } + accessibleWhenDisabled + size="compact" + onClick={ () => { + onToggleVisibility(); + focusVisibilityField(); + } } + icon={ isVisible ? unseen : seen } + label={ + isVisible + ? sprintf( + /* translators: %s: field label */ + _x( 'Hide %s', 'field' ), + field.label ) - : [ ...visibleFieldIds, id ], - } ); - // Focus the visibility button to avoid focus loss. - // Our code is safe against the component being unmounted, so we don't need to worry about cleaning the timeout. - // eslint-disable-next-line @wordpress/react-no-unsafe-timeout - setTimeout( () => { - const element = document.querySelector( - `.dataviews-field-control__field-${ id } .dataviews-field-control__field-visibility-button` - ); - if ( element instanceof HTMLElement ) { - element.focus(); - } - }, 50 ); - } } - icon={ isVisible ? unseen : seen } - label={ - isVisible - ? sprintf( - /* translators: %s: field label */ - _x( 'Hide %s', 'field' ), - label - ) - : sprintf( - /* translators: %s: field label */ - _x( 'Show %s', 'field' ), - label - ) - } - /> + : sprintf( + /* translators: %s: field label */ + _x( 'Show %s', 'field' ), + field.label + ) + } + /> + ) } </HStack> </HStack> </Item> ); } -function FieldControl() { - const { view, fields, onChangeView } = useContext( DataViewsContext ); +function RegularFieldItem( { + index, + field, + view, + onChangeView, +}: { + index?: number; + field: NormalizedField< any >; + view: View; + onChangeView: ( view: View ) => void; +} ) { + const visibleFieldIds = view.fields ?? []; + const isVisible = + index !== undefined && visibleFieldIds.includes( field.id ); - const visibleFieldIds = useMemo( - () => getVisibleFieldIds( view, fields ), - [ view, fields ] - ); - const hiddenFieldIds = useMemo( - () => getHiddenFieldIds( view, fields ), - [ view, fields ] - ); - const notHidableFieldIds = useMemo( - () => getNotHidableFieldIds( view ), - [ view ] + return ( + <FieldItem + field={ field } + isVisible={ isVisible } + isFirst={ index !== undefined && index < 1 } + isLast={ + index !== undefined && index === visibleFieldIds.length - 1 + } + onToggleVisibility={ () => { + onChangeView( { + ...view, + fields: isVisible + ? visibleFieldIds.filter( + ( fieldId ) => fieldId !== field.id + ) + : [ ...visibleFieldIds, field.id ], + } ); + } } + onMoveUp={ + index !== undefined + ? () => { + onChangeView( { + ...view, + fields: [ + ...( visibleFieldIds.slice( + 0, + index - 1 + ) ?? [] ), + field.id, + visibleFieldIds[ index - 1 ], + ...visibleFieldIds.slice( index + 1 ), + ], + } ); + } + : undefined + } + onMoveDown={ + index !== undefined + ? () => { + onChangeView( { + ...view, + fields: [ + ...( visibleFieldIds.slice( 0, index ) ?? + [] ), + visibleFieldIds[ index + 1 ], + field.id, + ...visibleFieldIds.slice( index + 2 ), + ], + } ); + } + : undefined + } + /> ); +} - const visibleFields = fields - .filter( ( { id } ) => visibleFieldIds.includes( id ) ) - .map( ( { id, label, enableHiding } ) => { - return { - id, - label, - index: visibleFieldIds.indexOf( id ), - isVisible: true, - isHidable: notHidableFieldIds.includes( id ) - ? false - : enableHiding, - }; - } ); - if ( view.type === LAYOUT_TABLE && view.layout?.combinedFields ) { - view.layout.combinedFields.forEach( ( { id, label } ) => { - visibleFields.push( { - id, - label, - index: visibleFieldIds.indexOf( id ), - isVisible: true, - isHidable: notHidableFieldIds.includes( id ), - } ); - } ); - } - visibleFields.sort( ( a, b ) => a.index - b.index ); +function isDefined< T >( item: T | undefined ): item is T { + return !! item; +} - const hiddenFields = fields - .filter( ( { id } ) => hiddenFieldIds.includes( id ) ) - .map( ( { id, label, enableHiding }, index ) => { - return { - id, - label, - index, - isVisible: false, - isHidable: enableHiding, - }; - } ); +function FieldControl() { + const { view, fields, onChangeView } = useContext( DataViewsContext ); + + const togglableFields = [ + view?.titleField, + view?.mediaField, + view?.descriptionField, + ].filter( Boolean ); + const visibleFieldIds = view.fields ?? []; + const hiddenFields = fields.filter( + ( f ) => + ! visibleFieldIds.includes( f.id ) && + ! togglableFields.includes( f.id ) + ); + const visibleFields = visibleFieldIds + .map( ( fieldId ) => fields.find( ( f ) => f.id === fieldId ) ) + .filter( isDefined ); if ( ! visibleFields?.length && ! hiddenFields?.length ) { return null; } + const titleField = fields.find( ( f ) => f.id === view.titleField ); + const mediaField = fields.find( ( f ) => f.id === view.mediaField ); + const descriptionField = fields.find( + ( f ) => f.id === view.descriptionField + ); + const lockedFields = [ + { + field: titleField, + isVisibleFlag: 'showTitle', + }, + { + field: mediaField, + isVisibleFlag: 'showMedia', + }, + { + field: descriptionField, + isVisibleFlag: 'showDescription', + }, + ].filter( ( { field } ) => isDefined( field ) ); + const visibleLockedFields = lockedFields.filter( + ( { field, isVisibleFlag } ) => + // @ts-expect-error + isDefined( field ) && ( view[ isVisibleFlag ] ?? true ) + ) as Array< { field: NormalizedField< any >; isVisibleFlag: string } >; + const hiddenLockedFields = lockedFields.filter( + ( { field, isVisibleFlag } ) => + // @ts-expect-error + isDefined( field ) && ! ( view[ isVisibleFlag ] ?? true ) + ) as Array< { field: NormalizedField< any >; isVisibleFlag: string } >; return ( - <VStack spacing={ 6 } className="dataviews-field-control"> - { !! visibleFields?.length && ( - <ItemGroup isBordered isSeparated> - { visibleFields.map( ( field ) => ( - <FieldItem - key={ field.id } - field={ field } - fields={ fields } - view={ view } - onChangeView={ onChangeView } - /> - ) ) } - </ItemGroup> - ) } - { !! hiddenFields?.length && ( - <> - <VStack spacing={ 4 }> - <BaseControl.VisualLabel style={ { margin: 0 } }> - { __( 'Hidden' ) } - </BaseControl.VisualLabel> + <VStack className="dataviews-field-control" spacing={ 6 }> + <VStack className="dataviews-view-config__properties" spacing={ 0 }> + { ( visibleLockedFields.length > 0 || + !! visibleFields?.length ) && ( + <ItemGroup isBordered isSeparated> + { visibleLockedFields.map( + ( { field, isVisibleFlag } ) => { + return ( + <FieldItem + key={ field.id } + field={ field } + isVisible + onToggleVisibility={ () => { + onChangeView( { + ...view, + [ isVisibleFlag ]: false, + } ); + } } + canMove={ false } + /> + ); + } + ) } + + { visibleFields.map( ( field, index ) => ( + <RegularFieldItem + key={ field.id } + field={ field } + view={ view } + onChangeView={ onChangeView } + index={ index } + /> + ) ) } + </ItemGroup> + ) } + </VStack> + + { ( !! hiddenFields?.length || !! hiddenLockedFields.length ) && ( + <VStack spacing={ 4 }> + <BaseControl.VisualLabel style={ { margin: 0 } }> + { __( 'Hidden' ) } + </BaseControl.VisualLabel> + <VStack + className="dataviews-view-config__properties" + spacing={ 0 } + > <ItemGroup isBordered isSeparated> + { hiddenLockedFields.length > 0 && + hiddenLockedFields.map( + ( { field, isVisibleFlag } ) => { + return ( + <FieldItem + key={ field.id } + field={ field } + isVisible={ false } + onToggleVisibility={ () => { + onChangeView( { + ...view, + [ isVisibleFlag ]: true, + } ); + } } + canMove={ false } + /> + ); + } + ) } { hiddenFields.map( ( field ) => ( - <FieldItem + <RegularFieldItem key={ field.id } field={ field } - fields={ fields } view={ view } onChangeView={ onChangeView } /> ) ) } </ItemGroup> </VStack> - </> + </VStack> ) } </VStack> ); diff --git a/packages/dataviews/src/components/dataviews-view-config/style.scss b/packages/dataviews/src/components/dataviews-view-config/style.scss index 7fff110337ee3a..8427796b6e15ed 100644 --- a/packages/dataviews/src/components/dataviews-view-config/style.scss +++ b/packages/dataviews/src/components/dataviews-view-config/style.scss @@ -67,3 +67,12 @@ top: unset; } } + +.dataviews-field-control__icon { + display: flex; + width: $icon-size; +} + +.dataviews-field-control__label { + flex-grow: 1; +} diff --git a/packages/dataviews/src/components/dataviews/stories/fixtures.tsx b/packages/dataviews/src/components/dataviews/stories/fixtures.tsx index 6c74c516853c5b..cd4d3b97e65311 100644 --- a/packages/dataviews/src/components/dataviews/stories/fixtures.tsx +++ b/packages/dataviews/src/components/dataviews/stories/fixtures.tsx @@ -637,9 +637,6 @@ export const fields: Field< SpaceObject >[] = [ id: 'title', enableHiding: false, enableGlobalSearch: true, - render: ( { item } ) => { - return <a href="#nothing">{ item.title }</a>; - }, }, { id: 'date', diff --git a/packages/dataviews/src/components/dataviews/stories/index.story.tsx b/packages/dataviews/src/components/dataviews/stories/index.story.tsx index 6161af125b5ca4..1e96ba92a0bea9 100644 --- a/packages/dataviews/src/components/dataviews/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataviews/stories/index.story.tsx @@ -7,17 +7,10 @@ import { useState, useMemo } from '@wordpress/element'; * Internal dependencies */ import DataViews from '../index'; -import { - DEFAULT_VIEW, - actions, - data, - fields, - themeData, - themeFields, -} from './fixtures'; +import { DEFAULT_VIEW, actions, data, fields } from './fixtures'; import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../../../constants'; import { filterSortAndPaginate } from '../../../filter-and-sort-data-view'; -import type { CombinedField, View } from '../../../types'; +import type { View } from '../../../types'; import './style.css'; @@ -28,44 +21,18 @@ const meta = { export default meta; const defaultLayouts = { - [ LAYOUT_TABLE ]: { - layout: { - primaryField: 'title', - styles: { - image: { - width: 50, - }, - title: { - maxWidth: 400, - }, - type: { - maxWidth: 400, - }, - description: { - maxWidth: 200, - }, - }, - }, - }, - [ LAYOUT_GRID ]: { - layout: { - mediaField: 'image', - primaryField: 'title', - }, - }, - [ LAYOUT_LIST ]: { - layout: { - mediaField: 'image', - primaryField: 'title', - }, - }, + [ LAYOUT_TABLE ]: {}, + [ LAYOUT_GRID ]: {}, + [ LAYOUT_LIST ]: {}, }; export const Default = () => { const [ view, setView ] = useState< View >( { ...DEFAULT_VIEW, - fields: [ 'title', 'description', 'categories' ], - layout: defaultLayouts[ DEFAULT_VIEW.type ].layout, + fields: [ 'categories' ], + titleField: 'title', + descriptionField: 'description', + mediaField: 'image', } ); const { data: shownData, paginationInfo } = useMemo( () => { return filterSortAndPaginate( data, view, fields ); @@ -79,6 +46,11 @@ export const Default = () => { fields={ fields } onChangeView={ setView } actions={ actions } + onClickItem={ ( item ) => { + // eslint-disable-next-line no-alert + alert( 'Clicked: ' + item.title ); + } } + isItemClickable={ () => true } defaultLayouts={ defaultLayouts } /> ); @@ -133,67 +105,3 @@ export const FieldsNoSortableNoHidable = () => { /> ); }; - -export const CombinedFields = () => { - const defaultLayoutsThemes = { - table: { - fields: [ 'theme_with_combined', 'theme_with_simple' ], - layout: { - primaryField: 'name', - combinedFields: [ - { - id: 'name_tested', - label: 'Theme', - children: [ 'name', 'tested' ], - direction: 'vertical', - }, - { - id: 'theme_with_combined', - label: 'Combine combined fields', - children: [ 'icon', 'name_tested' ], - direction: 'horizontal', - }, - { - id: 'theme_with_simple', - label: 'Combine simple fields', - children: [ 'icon', 'name' ], - direction: 'horizontal', - }, - ] as CombinedField[], - styles: { - theme: { - maxWidth: 300, - }, - }, - }, - }, - grid: { - fields: [ 'description', 'requires', 'tested' ], - layout: { primaryField: 'name', columnFields: [ 'description' ] }, - }, - list: { - fields: [ 'requires', 'tested' ], - layout: { primaryField: 'name' }, - }, - }; - const [ view, setView ] = useState< View >( { - ...DEFAULT_VIEW, - fields: defaultLayoutsThemes.table.fields, - layout: defaultLayoutsThemes.table.layout, - } ); - const { data: shownData, paginationInfo } = useMemo( () => { - return filterSortAndPaginate( themeData, view, themeFields ); - }, [ view ] ); - - return ( - <DataViews - getItemId={ ( item ) => item.name } - paginationInfo={ paginationInfo } - data={ shownData } - view={ view } - fields={ themeFields } - onChangeView={ setView } - defaultLayouts={ defaultLayoutsThemes } - /> - ); -}; diff --git a/packages/dataviews/src/components/dataviews/style.scss b/packages/dataviews/src/components/dataviews/style.scss index a357679bef1eb9..b38447094c99a9 100644 --- a/packages/dataviews/src/components/dataviews/style.scss +++ b/packages/dataviews/src/components/dataviews/style.scss @@ -22,12 +22,35 @@ @include reduce-motion( "transition" ); } -.dataviews-view-list__primary-field, -.dataviews-view-grid__primary-field, -.dataviews-view-table__primary-field { +.dataviews-no-results, +.dataviews-loading { + padding: 0 $grid-unit-60; + flex-grow: 1; + display: flex; + align-items: center; + justify-content: center; + transition: padding ease-out 0.1s; + @include reduce-motion( "transition" ); +} + +/* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ +@container (max-width: 430px) { + .dataviews__view-actions, + .dataviews-filters__container { + padding: $grid-unit-15 $grid-unit-30; + } + + .dataviews-no-results, + .dataviews-loading { + padding-left: $grid-unit-30; + padding-right: $grid-unit-30; + } +} + +.dataviews-title-field { font-size: $default-font-size; font-weight: 500; - color: $gray-700; + color: $gray-800; text-overflow: ellipsis; white-space: nowrap; width: 100%; @@ -39,7 +62,7 @@ overflow: hidden; display: block; flex-grow: 0; - color: $gray-900; + color: $gray-800; &:hover { color: var(--wp-admin-theme-color); @@ -60,46 +83,13 @@ color: var(--wp-admin-theme-color); } } - - &.dataviews-view-grid__primary-field--clickable span, - > .dataviews-view-table__cell-content--clickable span { - color: $gray-900; - - &:hover { - color: var(--wp-admin-theme-color); - } - @include link-reset(); - } } -.dataviews-view-list__primary-field--clickable, -.dataviews-view-grid__primary-field--clickable, -.dataviews-view-grid__media--clickable, -.dataviews-view-table__primary-field > .dataviews-view-table__cell-content--clickable { +.dataviews-title-field--clickable { cursor: pointer; -} - -.dataviews-no-results, -.dataviews-loading { - padding: 0 $grid-unit-60; - flex-grow: 1; - display: flex; - align-items: center; - justify-content: center; - transition: padding ease-out 0.1s; - @include reduce-motion( "transition" ); -} - -/* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ -@container (max-width: 430px) { - .dataviews__view-actions, - .dataviews-filters__container { - padding: $grid-unit-15 $grid-unit-30; - } - - .dataviews-no-results, - .dataviews-loading { - padding-left: $grid-unit-30; - padding-right: $grid-unit-30; + color: $gray-800; + &:hover { + color: var(--wp-admin-theme-color); } + @include link-reset(); } diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx index 17053e01604a55..4a016095702026 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx @@ -20,14 +20,20 @@ import { __ } from '@wordpress/i18n'; * Internal dependencies */ import ItemActions from '../../components/dataviews-item-actions'; -import SingleSelectionCheckbox from '../../components/dataviews-selection-checkbox'; +import DataViewsSelectionCheckbox from '../../components/dataviews-selection-checkbox'; import { useHasAPossibleBulkAction } from '../../components/dataviews-bulk-actions'; -import type { Action, NormalizedField, ViewGridProps } from '../../types'; +import type { + Action, + NormalizedField, + ViewGrid as ViewGridType, + ViewGridProps, +} from '../../types'; import type { SetSelection } from '../../private-types'; import getClickableItemProps from '../utils/get-clickable-item-props'; import { useUpdatedPreviewSizeOnViewportChange } from './preview-size-picker'; interface GridItemProps< Item > { + view: ViewGridType; selection: string[]; onChangeSelection: SetSelection; getItemId: ( item: Item ) => string; @@ -35,14 +41,15 @@ interface GridItemProps< Item > { isItemClickable: ( item: Item ) => boolean; item: Item; actions: Action< Item >[]; + titleField?: NormalizedField< Item >; mediaField?: NormalizedField< Item >; - primaryField?: NormalizedField< Item >; - visibleFields: NormalizedField< Item >[]; + descriptionField?: NormalizedField< Item >; + regularFields: NormalizedField< Item >[]; badgeFields: NormalizedField< Item >[]; - columnFields?: string[]; } function GridItem< Item >( { + view, selection, onChangeSelection, onClickItem, @@ -51,20 +58,22 @@ function GridItem< Item >( { item, actions, mediaField, - primaryField, - visibleFields, + titleField, + descriptionField, + regularFields, badgeFields, - columnFields, }: GridItemProps< Item > ) { + const { showTitle = true, showMedia = true, showDescription = true } = view; const hasBulkAction = useHasAPossibleBulkAction( actions, item ); const id = getItemId( item ); const isSelected = selection.includes( id ); const renderedMediaField = mediaField?.render ? ( <mediaField.render item={ item } /> ) : null; - const renderedPrimaryField = primaryField?.render ? ( - <primaryField.render item={ item } /> - ) : null; + const renderedTitleField = + showTitle && titleField?.render ? ( + <titleField.render item={ item } /> + ) : null; const clickableMediaItemProps = getClickableItemProps( { item, @@ -77,7 +86,7 @@ function GridItem< Item >( { item, isItemClickable, onClickItem, - className: 'dataviews-view-grid__primary-field', + className: 'dataviews-view-grid__primary-field dataviews-title-field', } ); return ( @@ -102,82 +111,85 @@ function GridItem< Item >( { } } } > - <div { ...clickableMediaItemProps }>{ renderedMediaField }</div> - <SingleSelectionCheckbox - item={ item } - selection={ selection } - onChangeSelection={ onChangeSelection } - getItemId={ getItemId } - primaryField={ primaryField } - disabled={ ! hasBulkAction } - /> + { showMedia && renderedMediaField && ( + <div { ...clickableMediaItemProps }>{ renderedMediaField }</div> + ) } + { showMedia && renderedMediaField && ( + <DataViewsSelectionCheckbox + item={ item } + selection={ selection } + onChangeSelection={ onChangeSelection } + getItemId={ getItemId } + titleField={ titleField } + disabled={ ! hasBulkAction } + /> + ) } <HStack justify="space-between" className="dataviews-view-grid__title-actions" > <div { ...clickablePrimaryItemProps }> - { renderedPrimaryField } + { renderedTitleField } </div> <ItemActions item={ item } actions={ actions } isCompact /> </HStack> - { !! badgeFields?.length && ( - <HStack - className="dataviews-view-grid__badge-fields" - spacing={ 2 } - wrap - alignment="top" - justify="flex-start" - > - { badgeFields.map( ( field ) => { - return ( - <FlexItem - key={ field.id } - className="dataviews-view-grid__field-value" - > - <field.render item={ item } /> - </FlexItem> - ); - } ) } - </HStack> - ) } - { !! visibleFields?.length && ( - <VStack className="dataviews-view-grid__fields" spacing={ 1 }> - { visibleFields.map( ( field ) => { - return ( - <Flex - className={ clsx( - 'dataviews-view-grid__field', - columnFields?.includes( field.id ) - ? 'is-column' - : 'is-row' - ) } - key={ field.id } - gap={ 1 } - justify="flex-start" - expanded - style={ { height: 'auto' } } - direction={ - columnFields?.includes( field.id ) - ? 'column' - : 'row' - } - > - <> - <FlexItem className="dataviews-view-grid__field-name"> - { field.header } - </FlexItem> - <FlexItem - className="dataviews-view-grid__field-value" - style={ { maxHeight: 'none' } } - > - <field.render item={ item } /> - </FlexItem> - </> - </Flex> - ); - } ) } - </VStack> - ) } + <VStack spacing={ 1 }> + { showDescription && descriptionField?.render && ( + <descriptionField.render item={ item } /> + ) } + { !! badgeFields?.length && ( + <HStack + className="dataviews-view-grid__badge-fields" + spacing={ 2 } + wrap + alignment="top" + justify="flex-start" + > + { badgeFields.map( ( field ) => { + return ( + <FlexItem + key={ field.id } + className="dataviews-view-grid__field-value" + > + <field.render item={ item } /> + </FlexItem> + ); + } ) } + </HStack> + ) } + { !! regularFields?.length && ( + <VStack + className="dataviews-view-grid__fields" + spacing={ 1 } + > + { regularFields.map( ( field ) => { + return ( + <Flex + className="dataviews-view-grid__field" + key={ field.id } + gap={ 1 } + justify="flex-start" + expanded + style={ { height: 'auto' } } + direction="row" + > + <> + <FlexItem className="dataviews-view-grid__field-name"> + { field.header } + </FlexItem> + <FlexItem + className="dataviews-view-grid__field-value" + style={ { maxHeight: 'none' } } + > + <field.render item={ item } /> + </FlexItem> + </> + </Flex> + ); + } ) } + </VStack> + ) } + </VStack> </VStack> ); } @@ -194,20 +206,24 @@ export default function ViewGrid< Item >( { selection, view, }: ViewGridProps< Item > ) { + const titleField = fields.find( + ( field ) => field.id === view?.titleField + ); const mediaField = fields.find( - ( field ) => field.id === view.layout?.mediaField + ( field ) => field.id === view?.mediaField ); - const primaryField = fields.find( - ( field ) => field.id === view.layout?.primaryField + const descriptionField = fields.find( + ( field ) => field.id === view?.descriptionField ); - const viewFields = view.fields || fields.map( ( field ) => field.id ); - const { visibleFields, badgeFields } = fields.reduce( + const otherFields = view.fields ?? []; + const { regularFields, badgeFields } = fields.reduce( ( accumulator: Record< string, NormalizedField< Item >[] >, field ) => { if ( - ! viewFields.includes( field.id ) || + ! otherFields.includes( field.id ) || [ - view.layout?.mediaField, - view?.layout?.primaryField, + view?.mediaField, + view?.titleField, + view?.descriptionField, ].includes( field.id ) ) { return accumulator; @@ -216,11 +232,11 @@ export default function ViewGrid< Item >( { // otherwise add it to the rest visibleFields array. const key = view.layout?.badgeFields?.includes( field.id ) ? 'badgeFields' - : 'visibleFields'; + : 'regularFields'; accumulator[ key ].push( field ); return accumulator; }, - { visibleFields: [], badgeFields: [] } + { regularFields: [], badgeFields: [] } ); const hasData = !! data?.length; const updatedPreviewSize = useUpdatedPreviewSizeOnViewportChange(); @@ -245,6 +261,7 @@ export default function ViewGrid< Item >( { return ( <GridItem key={ getItemId( item ) } + view={ view } selection={ selection } onChangeSelection={ onChangeSelection } onClickItem={ onClickItem } @@ -253,10 +270,10 @@ export default function ViewGrid< Item >( { item={ item } actions={ actions } mediaField={ mediaField } - primaryField={ primaryField } - visibleFields={ visibleFields } + titleField={ titleField } + descriptionField={ descriptionField } + regularFields={ regularFields } badgeFields={ badgeFields } - columnFields={ view.layout?.columnFields } /> ); } ) } diff --git a/packages/dataviews/src/dataviews-layouts/grid/style.scss b/packages/dataviews/src/dataviews-layouts/grid/style.scss index f209accc6de15c..70c94653371d16 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/style.scss +++ b/packages/dataviews/src/dataviews-layouts/grid/style.scss @@ -81,36 +81,23 @@ } .dataviews-view-grid__field { - align-items: flex-start; min-height: $grid-unit-30; + align-items: center; - &:not(:has(.dataviews-view-grid__field-value:not(:empty))) { - display: none; - } - - &:not(.is-column) { - align-items: center; - - .dataviews-view-grid__field-name { - width: 35%; - } - - .dataviews-view-grid__field-value { - width: 65%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } + .dataviews-view-grid__field-name { + width: 35%; + color: $gray-700; } - &.is-column { - & + .is-row { - margin-top: $grid-unit-05; - } + .dataviews-view-grid__field-value { + width: 65%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } - .dataviews-view-grid__field-name { - color: $gray-700; + &:not(:has(.dataviews-view-grid__field-value:not(:empty))) { + display: none; } } } @@ -178,3 +165,7 @@ padding-right: $grid-unit-30; } } + +.dataviews-view-grid__media--clickable { + cursor: pointer; +} diff --git a/packages/dataviews/src/dataviews-layouts/index.ts b/packages/dataviews/src/dataviews-layouts/index.ts index 7abdd1eb459328..f2455f81f1560c 100644 --- a/packages/dataviews/src/dataviews-layouts/index.ts +++ b/packages/dataviews/src/dataviews-layouts/index.ts @@ -16,7 +16,6 @@ import ViewTable from './table'; import ViewGrid from './grid'; import ViewList from './list'; import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../constants'; -import type { View, Field } from '../types'; import PreviewSizePicker from './grid/preview-size-picker'; import DensityPicker from './table/density-picker'; @@ -42,90 +41,3 @@ export const VIEW_LAYOUTS = [ icon: isRTL() ? formatListBulletsRTL : formatListBullets, }, ]; - -export function getNotHidableFieldIds( view: View ): string[] { - if ( view.type === 'table' ) { - return [ view.layout?.primaryField ] - .concat( - view.layout?.combinedFields?.flatMap( - ( field ) => field.children - ) ?? [] - ) - .filter( ( item ): item is string => !! item ); - } - - if ( view.type === 'grid' ) { - return [ view.layout?.primaryField, view.layout?.mediaField ].filter( - ( item ): item is string => !! item - ); - } - - if ( view.type === 'list' ) { - return [ view.layout?.primaryField, view.layout?.mediaField ].filter( - ( item ): item is string => !! item - ); - } - - return []; -} - -function getCombinedFieldIds( view: View ): string[] { - const combinedFields: string[] = []; - if ( view.type === LAYOUT_TABLE && view.layout?.combinedFields ) { - view.layout.combinedFields.forEach( ( combination ) => { - combinedFields.push( ...combination.children ); - } ); - } - return combinedFields; -} - -export function getVisibleFieldIds( - view: View, - fields: Field< any >[] -): string[] { - const fieldsToExclude = getCombinedFieldIds( view ); - - if ( view.fields ) { - return view.fields.filter( ( id ) => ! fieldsToExclude.includes( id ) ); - } - - const visibleFields = []; - if ( view.type === LAYOUT_TABLE && view.layout?.combinedFields ) { - visibleFields.push( - ...view.layout.combinedFields.map( ( { id } ) => id ) - ); - } - visibleFields.push( - ...fields - .filter( ( { id } ) => ! fieldsToExclude.includes( id ) ) - .map( ( { id } ) => id ) - ); - - return visibleFields; -} - -export function getHiddenFieldIds( - view: View, - fields: Field< any >[] -): string[] { - const fieldsToExclude = [ - ...getCombinedFieldIds( view ), - ...getVisibleFieldIds( view, fields ), - ]; - - // The media field does not need to be in the view.fields to be displayed. - if ( view.type === LAYOUT_GRID && view.layout?.mediaField ) { - fieldsToExclude.push( view.layout?.mediaField ); - } - - if ( view.type === LAYOUT_LIST && view.layout?.mediaField ) { - fieldsToExclude.push( view.layout?.mediaField ); - } - - return fields - .filter( - ( { id, enableHiding } ) => - ! fieldsToExclude.includes( id ) && enableHiding - ) - .map( ( { id } ) => id ); -} diff --git a/packages/dataviews/src/dataviews-layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx index 47b9961d97df18..d400cc62741699 100644 --- a/packages/dataviews/src/dataviews-layouts/list/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/list/index.tsx @@ -35,17 +35,24 @@ import { ActionsMenuGroup, ActionModal, } from '../../components/dataviews-item-actions'; -import type { Action, NormalizedField, ViewListProps } from '../../types'; +import type { + Action, + NormalizedField, + ViewList as ViewListType, + ViewListProps, +} from '../../types'; interface ListViewItemProps< Item > { + view: ViewListType; actions: Action< Item >[]; idPrefix: string; isSelected: boolean; item: Item; + titleField?: NormalizedField< Item >; mediaField?: NormalizedField< Item >; + descriptionField?: NormalizedField< Item >; onSelect: ( item: Item ) => void; - primaryField?: NormalizedField< Item >; - visibleFields: NormalizedField< Item >[]; + otherFields: NormalizedField< Item >[]; onDropdownTriggerKeyDown: React.KeyboardEventHandler< HTMLButtonElement >; } @@ -130,16 +137,19 @@ function PrimaryActionGridCell< Item >( { } function ListItem< Item >( { + view, actions, idPrefix, isSelected, item, + titleField, mediaField, + descriptionField, onSelect, - primaryField, - visibleFields, + otherFields, onDropdownTriggerKeyDown, }: ListViewItemProps< Item > ) { + const { showTitle = true, showMedia = true, showDescription = true } = view; const itemRef = useRef< HTMLDivElement >( null ); const labelId = `${ idPrefix }-label`; const descriptionId = `${ idPrefix }-description`; @@ -177,15 +187,17 @@ function ListItem< Item >( { const hasOnlyOnePrimaryAction = primaryAction && actions.length === 1; - const renderedMediaField = mediaField?.render ? ( - <div className="dataviews-view-list__media-wrapper"> - <mediaField.render item={ item } /> - </div> - ) : null; + const renderedMediaField = + showMedia && mediaField?.render ? ( + <div className="dataviews-view-list__media-wrapper"> + <mediaField.render item={ item } /> + </div> + ) : null; - const renderedPrimaryField = primaryField?.render ? ( - <primaryField.render item={ item } /> - ) : null; + const renderedTitleField = + showTitle && titleField?.render ? ( + <titleField.render item={ item } /> + ) : null; const usedActions = eligibleActions?.length > 0 && ( <HStack spacing={ 3 } className="dataviews-view-list__item-actions"> @@ -259,18 +271,23 @@ function ListItem< Item >( { > <HStack spacing={ 0 }> <div - className="dataviews-view-list__primary-field" + className="dataviews-title-field" id={ labelId } > - { renderedPrimaryField } + { renderedTitleField } </div> { usedActions } </HStack> + { showDescription && descriptionField?.render && ( + <div className="dataviews-view-list__field"> + <descriptionField.render item={ item } /> + </div> + ) } <div className="dataviews-view-list__fields" id={ descriptionId } > - { visibleFields.map( ( field ) => ( + { otherFields.map( ( field ) => ( <div key={ field.id } className="dataviews-view-list__field" @@ -310,20 +327,19 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) { const selectedItem = data?.findLast( ( item ) => selection.includes( getItemId( item ) ) ); - - const mediaField = fields.find( - ( field ) => field.id === view.layout?.mediaField - ); - const primaryField = fields.find( - ( field ) => field.id === view.layout?.primaryField + const titleField = fields.find( ( field ) => field.id === view.titleField ); + const mediaField = fields.find( ( field ) => field.id === view.mediaField ); + const descriptionField = fields.find( + ( field ) => field.id === view.descriptionField ); - const viewFields = view.fields || fields.map( ( field ) => field.id ); - const visibleFields = fields.filter( + const otherFields = fields.filter( ( field ) => - viewFields.includes( field.id ) && - ! [ view.layout?.primaryField, view.layout?.mediaField ].includes( - field.id - ) + ( view.fields ?? [] ).includes( field.id ) && + ! [ + view.titleField, + view.mediaField, + view.descriptionField, + ].includes( field.id ) ); const onSelect = ( item: Item ) => @@ -465,14 +481,16 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) { return ( <ListItem key={ id } + view={ view } idPrefix={ id } actions={ actions } item={ item } isSelected={ item === selectedItem } onSelect={ onSelect } mediaField={ mediaField } - primaryField={ primaryField } - visibleFields={ visibleFields } + titleField={ titleField } + descriptionField={ descriptionField } + otherFields={ otherFields } onDropdownTriggerKeyDown={ onDropdownTriggerKeyDown } /> ); diff --git a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx index 7071e54620f369..763cf83b5c2f93 100644 --- a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx @@ -27,7 +27,6 @@ import type { ViewTable as ViewTableType, Operator, } from '../../types'; -import { getVisibleFieldIds } from '../index'; const { Menu } = unlock( componentsPrivateApis ); @@ -38,6 +37,7 @@ interface HeaderMenuProps< Item > { onChangeView: ( view: ViewTableType ) => void; onHide: ( field: NormalizedField< Item > ) => void; setOpenedFilter: ( fieldId: string ) => void; + canMove?: boolean; } function WithMenuSeparators( { children }: { children: ReactNode } ) { @@ -59,46 +59,38 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( onChangeView, onHide, setOpenedFilter, + canMove = true, }: HeaderMenuProps< Item >, ref: Ref< HTMLButtonElement > ) { - const visibleFieldIds = getVisibleFieldIds( view, fields ); + const visibleFieldIds = view.fields ?? []; const index = visibleFieldIds?.indexOf( fieldId ) as number; const isSorted = view.sort?.field === fieldId; let isHidable = false; let isSortable = false; let canAddFilter = false; - let header; let operators: Operator[] = []; - - const combinedField = view.layout?.combinedFields?.find( - ( f ) => f.id === fieldId - ); const field = fields.find( ( f ) => f.id === fieldId ); - if ( ! combinedField ) { - if ( ! field ) { - // No combined or regular field found. - return null; - } + if ( ! field ) { + // No combined or regular field found. + return null; + } - isHidable = field.enableHiding !== false; - isSortable = field.enableSorting !== false; - header = field.header; + isHidable = field.enableHiding !== false; + isSortable = field.enableSorting !== false; + const header = field.header; - operators = sanitizeOperators( field ); - // Filter can be added: - // 1. If the field is not already part of a view's filters. - // 2. If the field meets the type and operator requirements. - // 3. If it's not primary. If it is, it should be already visible. - canAddFilter = - ! view.filters?.some( ( _filter ) => fieldId === _filter.field ) && - !! field.elements?.length && - !! operators.length && - ! field.filterBy?.isPrimary; - } else { - header = combinedField.header || combinedField.label; - } + operators = sanitizeOperators( field ); + // Filter can be added: + // 1. If the field is not already part of a view's filters. + // 2. If the field meets the type and operator requirements. + // 3. If it's not primary. If it is, it should be already visible. + canAddFilter = + ! view.filters?.some( ( _filter ) => fieldId === _filter.field ) && + !! field.elements?.length && + !! operators.length && + ! field.filterBy?.isPrimary; return ( <Menu @@ -188,64 +180,80 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( </Menu.Item> </Menu.Group> ) } - <Menu.Group> - <Menu.Item - prefix={ <Icon icon={ arrowLeft } /> } - disabled={ index < 1 } - onClick={ () => { - onChangeView( { - ...view, - fields: [ - ...( visibleFieldIds.slice( - 0, - index - 1 - ) ?? [] ), - fieldId, - visibleFieldIds[ index - 1 ], - ...visibleFieldIds.slice( index + 1 ), - ], - } ); - } } - > - <Menu.ItemLabel>{ __( 'Move left' ) }</Menu.ItemLabel> - </Menu.Item> - <Menu.Item - prefix={ <Icon icon={ arrowRight } /> } - disabled={ index >= visibleFieldIds.length - 1 } - onClick={ () => { - onChangeView( { - ...view, - fields: [ - ...( visibleFieldIds.slice( 0, index ) ?? - [] ), - visibleFieldIds[ index + 1 ], - fieldId, - ...visibleFieldIds.slice( index + 2 ), - ], - } ); - } } - > - <Menu.ItemLabel>{ __( 'Move right' ) }</Menu.ItemLabel> - </Menu.Item> - { isHidable && field && ( - <Menu.Item - prefix={ <Icon icon={ unseen } /> } - onClick={ () => { - onHide( field ); - onChangeView( { - ...view, - fields: visibleFieldIds.filter( - ( id ) => id !== fieldId - ), - } ); - } } - > - <Menu.ItemLabel> - { __( 'Hide column' ) } - </Menu.ItemLabel> - </Menu.Item> - ) } - </Menu.Group> + { ( canMove || isHidable ) && field && ( + <Menu.Group> + { canMove && ( + <Menu.Item + prefix={ <Icon icon={ arrowLeft } /> } + disabled={ index < 1 } + onClick={ () => { + onChangeView( { + ...view, + fields: [ + ...( visibleFieldIds.slice( + 0, + index - 1 + ) ?? [] ), + fieldId, + visibleFieldIds[ index - 1 ], + ...visibleFieldIds.slice( + index + 1 + ), + ], + } ); + } } + > + <Menu.ItemLabel> + { __( 'Move left' ) } + </Menu.ItemLabel> + </Menu.Item> + ) } + { canMove && ( + <Menu.Item + prefix={ <Icon icon={ arrowRight } /> } + disabled={ index >= visibleFieldIds.length - 1 } + onClick={ () => { + onChangeView( { + ...view, + fields: [ + ...( visibleFieldIds.slice( + 0, + index + ) ?? [] ), + visibleFieldIds[ index + 1 ], + fieldId, + ...visibleFieldIds.slice( + index + 2 + ), + ], + } ); + } } + > + <Menu.ItemLabel> + { __( 'Move right' ) } + </Menu.ItemLabel> + </Menu.Item> + ) } + { isHidable && field && ( + <Menu.Item + prefix={ <Icon icon={ unseen } /> } + onClick={ () => { + onHide( field ); + onChangeView( { + ...view, + fields: visibleFieldIds.filter( + ( id ) => id !== fieldId + ), + } ); + } } + > + <Menu.ItemLabel> + { __( 'Hide column' ) } + </Menu.ItemLabel> + </Menu.Item> + ) } + </Menu.Group> + ) } </WithMenuSeparators> </Menu> ); diff --git a/packages/dataviews/src/dataviews-layouts/table/column-primary.tsx b/packages/dataviews/src/dataviews-layouts/table/column-primary.tsx new file mode 100644 index 00000000000000..6db65be72bdd4c --- /dev/null +++ b/packages/dataviews/src/dataviews-layouts/table/column-primary.tsx @@ -0,0 +1,58 @@ +/** + * WordPress dependencies + */ +import { + __experimentalHStack as HStack, + __experimentalVStack as VStack, +} from '@wordpress/components'; + +/** + * Internal dependencies + */ +import type { NormalizedField } from '../../types'; +import getClickableItemProps from '../utils/get-clickable-item-props'; + +function ColumnPrimary< Item >( { + item, + titleField, + mediaField, + descriptionField, + onClickItem, + isItemClickable, +}: { + item: Item; + titleField?: NormalizedField< Item >; + mediaField?: NormalizedField< Item >; + descriptionField?: NormalizedField< Item >; + onClickItem?: ( item: Item ) => void; + isItemClickable: ( item: Item ) => boolean; +} ) { + const clickableProps = getClickableItemProps( { + item, + isItemClickable, + onClickItem, + className: + 'dataviews-view-table__cell-content-wrapper dataviews-title-field', + } ); + return ( + <HStack spacing={ 3 } justify="flex-start"> + { mediaField && ( + <div className="dataviews-view-table__cell-content-wrapper dataviews-column-primary__media"> + <mediaField.render item={ item } /> + </div> + ) } + <VStack spacing={ 0 }> + { titleField && ( + <div { ...clickableProps }> + <titleField.render item={ item } /> + </div> + ) } + { descriptionField && ( + <descriptionField.render item={ item } /> + ) } + </VStack> + </HStack> + ); +} + +export default ColumnPrimary; diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 81d856451bfcdc..b010b3ff154fbb 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -7,17 +7,13 @@ import clsx from 'clsx'; * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { - Spinner, - __experimentalHStack as HStack, - __experimentalVStack as VStack, -} from '@wordpress/components'; +import { Spinner } from '@wordpress/components'; import { useEffect, useId, useRef, useState } from '@wordpress/element'; /** * Internal dependencies */ -import SingleSelectionCheckbox from '../../components/dataviews-selection-checkbox'; +import DataViewsSelectionCheckbox from '../../components/dataviews-selection-checkbox'; import ItemActions from '../../components/dataviews-item-actions'; import { sortValues } from '../../constants'; import { @@ -30,39 +26,15 @@ import type { NormalizedField, ViewTable as ViewTableType, ViewTableProps, - CombinedField, } from '../../types'; import type { SetSelection } from '../../private-types'; import ColumnHeaderMenu from './column-header-menu'; -import { getVisibleFieldIds } from '../index'; -import getClickableItemProps from '../utils/get-clickable-item-props'; +import ColumnPrimary from './column-primary'; interface TableColumnFieldProps< Item > { - primaryField?: NormalizedField< Item >; - field: NormalizedField< Item >; - item: Item; - isItemClickable: ( item: Item ) => boolean; - onClickItem?: ( item: Item ) => void; -} - -interface TableColumnCombinedProps< Item > { - primaryField?: NormalizedField< Item >; - fields: NormalizedField< Item >[]; - field: CombinedField; - item: Item; - view: ViewTableType; - isItemClickable: ( item: Item ) => boolean; - onClickItem?: ( item: Item ) => void; -} - -interface TableColumnProps< Item > { - primaryField?: NormalizedField< Item >; fields: NormalizedField< Item >[]; - item: Item; column: string; - view: ViewTableType; - isItemClickable: ( item: Item ) => boolean; - onClickItem?: ( item: Item ) => void; + item: Item; } interface TableRowProps< Item > { @@ -72,7 +44,9 @@ interface TableRowProps< Item > { fields: NormalizedField< Item >[]; id: string; view: ViewTableType; - primaryField?: NormalizedField< Item >; + titleField?: NormalizedField< Item >; + mediaField?: NormalizedField< Item >; + descriptionField?: NormalizedField< Item >; selection: string[]; getItemId: ( item: Item ) => string; onChangeSelection: SetSelection; @@ -80,82 +54,24 @@ interface TableRowProps< Item > { onClickItem?: ( item: Item ) => void; } -function TableColumn< Item >( { - column, - fields, - view, - ...props -}: TableColumnProps< Item > ) { - const field = fields.find( ( f ) => f.id === column ); - if ( !! field ) { - return <TableColumnField { ...props } field={ field } />; - } - const combinedField = view.layout?.combinedFields?.find( - ( f ) => f.id === column - ); - if ( !! combinedField ) { - return ( - <TableColumnCombined - { ...props } - fields={ fields } - view={ view } - field={ combinedField } - /> - ); - } - - return null; -} - function TableColumnField< Item >( { - primaryField, item, - field, - isItemClickable, - onClickItem, + fields, + column, }: TableColumnFieldProps< Item > ) { - const isPrimaryField = primaryField?.id === field.id; - const isItemClickableField = ( i: Item ) => - isItemClickable( i ) && isPrimaryField; + const field = fields.find( ( f ) => f.id === column ); - const clickableProps = getClickableItemProps( { - item, - isItemClickable: isItemClickableField, - onClickItem, - className: 'dataviews-view-table__cell-content', - } ); + if ( ! field ) { + return null; + } return ( - <div - className={ clsx( 'dataviews-view-table__cell-content-wrapper', { - 'dataviews-view-table__primary-field': isPrimaryField, - } ) } - > - <div { ...clickableProps }> - <field.render { ...{ item } } /> - </div> + <div className="dataviews-view-table__cell-content-wrapper"> + <field.render { ...{ item } } /> </div> ); } -function TableColumnCombined< Item >( { - field, - ...props -}: TableColumnCombinedProps< Item > ) { - const children = field.children.map( ( child ) => ( - <TableColumn key={ child } { ...props } column={ child } /> - ) ); - - if ( field.direction === 'horizontal' ) { - return ( - <HStack spacing={ 3 } justify="flex-start"> - { children } - </HStack> - ); - } - return <VStack spacing={ 0 }>{ children }</VStack>; -} - function TableRow< Item >( { hasBulkActions, item, @@ -163,7 +79,9 @@ function TableRow< Item >( { fields, id, view, - primaryField, + titleField, + mediaField, + descriptionField, selection, getItemId, isItemClickable, @@ -173,7 +91,7 @@ function TableRow< Item >( { const hasPossibleBulkAction = useHasAPossibleBulkAction( actions, item ); const isSelected = hasPossibleBulkAction && selection.includes( id ); const [ isHovered, setIsHovered ] = useState( false ); - + const { showTitle = true, showMedia = true, showDescription = true } = view; const handleMouseEnter = () => { setIsHovered( true ); }; @@ -185,7 +103,11 @@ function TableRow< Item >( { // `onClick` and can be used to exclude touchscreen devices from certain // behaviours. const isTouchDeviceRef = useRef( false ); - const columns = getVisibleFieldIds( view, fields ); + const columns = view.fields ?? []; + const hasPrimaryColumn = + ( titleField && showTitle ) || + ( mediaField && showMedia ) || + ( descriptionField && showDescription ); return ( <tr @@ -223,17 +145,31 @@ function TableRow< Item >( { } } > <div className="dataviews-view-table__cell-content-wrapper"> - <SingleSelectionCheckbox + <DataViewsSelectionCheckbox item={ item } selection={ selection } onChangeSelection={ onChangeSelection } getItemId={ getItemId } - primaryField={ primaryField } + titleField={ titleField } disabled={ ! hasPossibleBulkAction } /> </div> </td> ) } + { hasPrimaryColumn && ( + <td> + <ColumnPrimary + item={ item } + titleField={ showTitle ? titleField : undefined } + mediaField={ showMedia ? mediaField : undefined } + descriptionField={ + showDescription ? descriptionField : undefined + } + isItemClickable={ isItemClickable } + onClickItem={ onClickItem } + /> + </td> + ) } { columns.map( ( column: string ) => { // Explicits picks the supported styles. const { width, maxWidth, minWidth } = @@ -241,14 +177,10 @@ function TableRow< Item >( { return ( <td key={ column } style={ { width, maxWidth, minWidth } }> - <TableColumn - primaryField={ primaryField } - isItemClickable={ isItemClickable } - onClickItem={ onClickItem } + <TableColumnField fields={ fields } item={ item } column={ column } - view={ view } /> </td> ); @@ -322,12 +254,30 @@ function ViewTable< Item >( { setNextHeaderMenuToFocus( fallback?.node ); }; - const columns = getVisibleFieldIds( view, fields ); const hasData = !! data?.length; - const primaryField = fields.find( - ( field ) => field.id === view.layout?.primaryField + const titleField = fields.find( ( field ) => field.id === view.titleField ); + const mediaField = fields.find( ( field ) => field.id === view.mediaField ); + const descriptionField = fields.find( + ( field ) => field.id === view.descriptionField ); + const { showTitle = true, showMedia = true, showDescription = true } = view; + const hasPrimaryColumn = + ( titleField && showTitle ) || + ( mediaField && showMedia ) || + ( descriptionField && showDescription ); + const columns = view.fields ?? []; + const headerMenuRef = + ( column: string, index: number ) => ( node: HTMLButtonElement ) => { + if ( node ) { + headerMenuRefs.current.set( column, { + node, + fallback: columns[ index > 0 ? index - 1 : 1 ], + } ); + } else { + headerMenuRefs.current.delete( column ); + } + }; return ( <> @@ -361,6 +311,27 @@ function ViewTable< Item >( { /> </th> ) } + { hasPrimaryColumn && ( + <th scope="col"> + <span className="dataviews-view-table-header"> + { titleField && ( + <ColumnHeaderMenu + ref={ headerMenuRef( + titleField.id, + 0 + ) } + fieldId={ titleField.id } + view={ view } + fields={ fields } + onChangeView={ onChangeView } + onHide={ onHide } + setOpenedFilter={ setOpenedFilter } + canMove={ false } + /> + ) } + </span> + </th> + ) } { columns.map( ( column, index ) => { // Explicits picks the supported styles. const { width, maxWidth, minWidth } = @@ -370,6 +341,7 @@ function ViewTable< Item >( { key={ column } style={ { width, maxWidth, minWidth } } aria-sort={ + view.sort?.direction && view.sort?.field === column ? sortValues[ view.sort.direction ] : undefined @@ -377,26 +349,7 @@ function ViewTable< Item >( { scope="col" > <ColumnHeaderMenu - ref={ ( node ) => { - if ( node ) { - headerMenuRefs.current.set( - column, - { - node, - fallback: - columns[ - index > 0 - ? index - 1 - : 1 - ], - } - ); - } else { - headerMenuRefs.current.delete( - column - ); - } - } } + ref={ headerMenuRef( column, index ) } fieldId={ column } view={ view } fields={ fields } @@ -427,7 +380,9 @@ function ViewTable< Item >( { fields={ fields } id={ getItemId( item ) || index.toString() } view={ view } - primaryField={ primaryField } + titleField={ titleField } + mediaField={ mediaField } + descriptionField={ descriptionField } selection={ selection } getItemId={ getItemId } onChangeSelection={ onChangeSelection } diff --git a/packages/dataviews/src/dataviews-layouts/table/style.scss b/packages/dataviews/src/dataviews-layouts/table/style.scss index 3bbb045c73a9d9..5a713dd428c127 100644 --- a/packages/dataviews/src/dataviews-layouts/table/style.scss +++ b/packages/dataviews/src/dataviews-layouts/table/style.scss @@ -222,3 +222,7 @@ --checkbox-input-size: 16px; } } + +.dataviews-column-primary__media { + max-width: 60px; +} diff --git a/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts b/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts index d952839d376d2c..e03e3a6351ec15 100644 --- a/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts +++ b/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts @@ -7,14 +7,16 @@ export default function getClickableItemProps< Item >( { item: Item; isItemClickable: ( item: Item ) => boolean; onClickItem?: ( item: Item ) => void; - className: string; + className?: string; } ) { if ( ! isItemClickable( item ) || ! onClickItem ) { return { className }; } return { - className: `${ className } ${ className }--clickable`, + className: className + ? `${ className } ${ className }--clickable` + : undefined, role: 'button', tabIndex: 0, onClick: ( event: React.MouseEvent ) => { diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 0bce8b8cf2c08a..96fd4a8cd01afc 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -292,24 +292,36 @@ interface ViewBase { * The fields to render */ fields?: string[]; -} -export interface CombinedField { - id: string; + /** + * Title field + */ + titleField?: string; - label: string; + /** + * Media field + */ + mediaField?: string; - header?: string | ReactElement; + /** + * Description field + */ + descriptionField?: string; /** - * The fields to use as columns. + * Whether to show the title */ - children: string[]; + showTitle?: boolean; /** - * The direction of the stack. + * Whether to show the media */ - direction: 'horizontal' | 'vertical'; + showMedia?: boolean; + + /** + * Whether to show the description + */ + showDescription?: boolean; } export interface ColumnStyle { @@ -335,16 +347,6 @@ export interface ViewTable extends ViewBase { type: 'table'; layout?: { - /** - * The field to use as the primary field. - */ - primaryField?: string; - - /** - * The fields to use as columns. - */ - combinedFields?: CombinedField[]; - /** * The styles for the columns. */ @@ -359,39 +361,12 @@ export interface ViewTable extends ViewBase { export interface ViewList extends ViewBase { type: 'list'; - - layout?: { - /** - * The field to use as the primary field. - */ - primaryField?: string; - - /** - * The field to use as the media field. - */ - mediaField?: string; - }; } export interface ViewGrid extends ViewBase { type: 'grid'; layout?: { - /** - * The field to use as the primary field. - */ - primaryField?: string; - - /** - * The field to use as the media field. - */ - mediaField?: string; - - /** - * The fields to use as columns. - */ - columnFields?: string[]; - /** * The fields to use as badge fields. */ diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index 9a4dedca098030..b23213fa1a6db3 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -41,11 +41,7 @@ const EMPTY_ARRAY = []; const defaultLayouts = { [ LAYOUT_TABLE ]: { layout: { - primaryField: 'title', styles: { - preview: { - width: '1%', - }, author: { width: '1%', }, @@ -54,8 +50,6 @@ const defaultLayouts = { }, [ LAYOUT_GRID ]: { layout: { - mediaField: 'preview', - primaryField: 'title', badgeFields: [ 'sync-status' ], }, }, @@ -65,9 +59,11 @@ const DEFAULT_VIEW = { search: '', page: 1, perPage: 20, - layout: defaultLayouts[ LAYOUT_GRID ].layout, - fields: [ 'title', 'sync-status' ], + titleField: 'title', + mediaField: 'preview', + fields: [ 'sync-status' ], filters: [], + ...defaultLayouts[ LAYOUT_GRID ], }; export default function DataviewsPatterns() { diff --git a/packages/edit-site/src/components/page-templates/index.js b/packages/edit-site/src/components/page-templates/index.js index 934fb0be6784d7..0c62b9eb450acc 100644 --- a/packages/edit-site/src/components/page-templates/index.js +++ b/packages/edit-site/src/components/page-templates/index.js @@ -34,25 +34,9 @@ const EMPTY_ARRAY = []; const defaultLayouts = { [ LAYOUT_TABLE ]: { - fields: [ 'template', 'author' ], + showMedia: false, layout: { - primaryField: 'title', - combinedFields: [ - { - id: 'template', - label: __( 'Template' ), - children: [ 'title', 'description' ], - direction: 'vertical', - }, - ], styles: { - template: { - maxWidth: 400, - minWidth: 320, - }, - preview: { - width: '1%', - }, author: { width: '1%', }, @@ -60,18 +44,10 @@ const defaultLayouts = { }, }, [ LAYOUT_GRID ]: { - fields: [ 'title', 'description', 'author' ], - layout: { - mediaField: 'preview', - primaryField: 'title', - columnFields: [ 'description' ], - }, + showMedia: true, }, [ LAYOUT_LIST ]: { - fields: [ 'title', 'description', 'author' ], - layout: { - primaryField: 'title', - }, + showMedia: false, }, }; @@ -84,9 +60,12 @@ const DEFAULT_VIEW = { field: 'title', direction: 'asc', }, - fields: defaultLayouts[ LAYOUT_GRID ].fields, - layout: defaultLayouts[ LAYOUT_GRID ].layout, + titleField: 'title', + descriptionField: 'description', + mediaField: 'preview', + fields: [ 'author' ], filters: [], + ...defaultLayouts[ LAYOUT_GRID ], }; export default function PageTemplates() { @@ -99,8 +78,6 @@ export default function PageTemplates() { return { ...DEFAULT_VIEW, type: usedType, - layout: defaultLayouts[ usedType ].layout, - fields: defaultLayouts[ usedType ].fields, filters: activeView !== 'all' ? [ @@ -111,6 +88,7 @@ export default function PageTemplates() { }, ] : [], + ...defaultLayouts[ usedType ], }; }, [ layout, activeView ] ); const [ view, setView ] = useState( defaultView ); diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 200aa60ee17977..145a5e8243ac54 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -55,7 +55,7 @@ const getCustomView = ( editedEntityRecord ) => { return { ...content, - layout: defaultLayouts[ content.type ]?.layout, + ...defaultLayouts[ content.type ], }; }; diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 72f4c94fe6bcdd..c08a2c1a57c58e 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -27,28 +27,9 @@ import { } from '../../utils/constants'; export const defaultLayouts = { - [ LAYOUT_TABLE ]: { - layout: { - primaryField: 'title', - styles: { - title: { - maxWidth: 300, - }, - }, - }, - }, - [ LAYOUT_GRID ]: { - layout: { - mediaField: 'featured_media', - primaryField: 'title', - }, - }, - [ LAYOUT_LIST ]: { - layout: { - primaryField: 'title', - mediaField: 'featured_media', - }, - }, + [ LAYOUT_TABLE ]: {}, + [ LAYOUT_GRID ]: {}, + [ LAYOUT_LIST ]: {}, }; const DEFAULT_POST_BASE = { @@ -61,8 +42,10 @@ const DEFAULT_POST_BASE = { field: 'date', direction: 'desc', }, - fields: [ 'title', 'author', 'status' ], - layout: defaultLayouts[ LAYOUT_LIST ].layout, + titleField: 'title', + mediaField: 'featured_media', + fields: [ 'author', 'status' ], + ...defaultLayouts[ LAYOUT_LIST ], }; export function useDefaultViews( { postType } ) { From b8bfb4d8b5827414d9f9445dbf3ec89dd416c022 Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 6 Dec 2024 13:12:28 +0400 Subject: [PATCH 1888/1908] Site Editor: Wrap each router area in 'ErrorBoundary' (#64245) * Use the error boundary from the `editor` package in the Site Editor. * Update the `ErrorBoundary` markup and remove the `Warning` component. It still matches the design. * Update letter casing for button labels. * Change "Copy post text" to "Copy contents" and make the action label more general. * Make the "Copy contents" action opt-in. * Use the primary button variant for "Copy error". Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> --- .../edit-post/src/components/layout/index.js | 2 +- .../src/components/error-boundary/index.js | 44 ------------------ .../error-boundary/test/error-boundary.js | 40 ---------------- .../src/components/error-boundary/warning.js | 30 ------------ .../edit-site/src/components/layout/index.js | 12 +++-- .../src/components/error-boundary/index.js | 46 ++++++++++++------- .../src/components/error-boundary/style.scss | 6 ++- 7 files changed, 43 insertions(+), 137 deletions(-) delete mode 100644 packages/edit-site/src/components/error-boundary/index.js delete mode 100644 packages/edit-site/src/components/error-boundary/test/error-boundary.js delete mode 100644 packages/edit-site/src/components/error-boundary/warning.js diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index c230738a077d92..b0a2b3f7d76b81 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -548,7 +548,7 @@ function Layout( { return ( <SlotFillProvider> - <ErrorBoundary> + <ErrorBoundary canCopyContent> <CommandMenu /> <WelcomeGuide postType={ currentPostType } /> <div diff --git a/packages/edit-site/src/components/error-boundary/index.js b/packages/edit-site/src/components/error-boundary/index.js deleted file mode 100644 index 88b04ae0b40e34..00000000000000 --- a/packages/edit-site/src/components/error-boundary/index.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * WordPress dependencies - */ -import { Component } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; -import { doAction } from '@wordpress/hooks'; - -/** - * Internal dependencies - */ -import ErrorBoundaryWarning from './warning'; - -export default class ErrorBoundary extends Component { - constructor() { - super( ...arguments ); - - this.state = { - error: null, - }; - } - - componentDidCatch( error ) { - doAction( 'editor.ErrorBoundary.errorLogged', error ); - } - - static getDerivedStateFromError( error ) { - return { error }; - } - - render() { - if ( ! this.state.error ) { - return this.props.children; - } - - return ( - <ErrorBoundaryWarning - message={ __( - 'The editor has encountered an unexpected error.' - ) } - error={ this.state.error } - /> - ); - } -} diff --git a/packages/edit-site/src/components/error-boundary/test/error-boundary.js b/packages/edit-site/src/components/error-boundary/test/error-boundary.js deleted file mode 100644 index 27ec4c80419676..00000000000000 --- a/packages/edit-site/src/components/error-boundary/test/error-boundary.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * External dependencies - */ -import { render } from '@testing-library/react'; - -/** - * WordPress dependencies - */ -import * as wpHooks from '@wordpress/hooks'; - -/** - * Internal dependencies - */ -import ErrorBoundary from '../index'; - -const theError = new Error( 'Kaboom' ); - -const ChildComponent = () => { - throw theError; -}; - -describe( 'Error Boundary', () => { - describe( 'when error is thrown from a Child component', () => { - it( 'calls the `editor.ErrorBoundary.errorLogged` hook action with the error object', () => { - const doAction = jest.spyOn( wpHooks, 'doAction' ); - - render( - <ErrorBoundary> - <ChildComponent /> - </ErrorBoundary> - ); - - expect( doAction ).toHaveBeenCalledWith( - 'editor.ErrorBoundary.errorLogged', - theError - ); - expect( console ).toHaveErrored(); - } ); - } ); -} ); diff --git a/packages/edit-site/src/components/error-boundary/warning.js b/packages/edit-site/src/components/error-boundary/warning.js deleted file mode 100644 index c4090c7e6b1190..00000000000000 --- a/packages/edit-site/src/components/error-boundary/warning.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { Button } from '@wordpress/components'; -import { Warning } from '@wordpress/block-editor'; -import { useCopyToClipboard } from '@wordpress/compose'; - -function CopyButton( { text, children } ) { - const ref = useCopyToClipboard( text ); - return ( - <Button __next40pxDefaultSize variant="secondary" ref={ ref }> - { children } - </Button> - ); -} - -export default function ErrorBoundaryWarning( { message, error } ) { - const actions = [ - <CopyButton key="copy-error" text={ error.stack }> - { __( 'Copy Error' ) } - </CopyButton>, - ]; - - return ( - <Warning className="editor-error-boundary" actions={ actions }> - { message } - </Warning> - ); -} diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index e7606c57a70484..00bc323ea1535c 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -25,6 +25,7 @@ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { EditorSnackbars, UnsavedChangesWarning, + ErrorBoundary, privateApis as editorPrivateApis, } from '@wordpress/editor'; import { privateApis as coreCommandsPrivateApis } from '@wordpress/core-commands'; @@ -36,7 +37,6 @@ import { useDispatch } from '@wordpress/data'; /** * Internal dependencies */ -import ErrorBoundary from '../error-boundary'; import { default as SiteHub, SiteHubMobile } from '../site-hub'; import ResizableFrame from '../resizable-frame'; import { unlock } from '../../lock-unlock'; @@ -136,7 +136,9 @@ function Layout() { } routeKey={ routeKey } > - { areas.sidebar } + <ErrorBoundary> + { areas.sidebar } + </ErrorBoundary> </SidebarContent> <SaveHub /> <SavePanel /> @@ -160,7 +162,7 @@ function Layout() { /> </SidebarContent> ) } - { areas.mobile } + <ErrorBoundary>{ areas.mobile }</ErrorBoundary> </div> ) } @@ -173,7 +175,7 @@ function Layout() { maxWidth: widths?.content, } } > - { areas.content } + <ErrorBoundary>{ areas.content }</ErrorBoundary> </div> ) } @@ -184,7 +186,7 @@ function Layout() { maxWidth: widths?.edit, } } > - { areas.edit } + <ErrorBoundary>{ areas.edit }</ErrorBoundary> </div> ) } diff --git a/packages/editor/src/components/error-boundary/index.js b/packages/editor/src/components/error-boundary/index.js index d43af5a556b67b..f3e6e5fd127afc 100644 --- a/packages/editor/src/components/error-boundary/index.js +++ b/packages/editor/src/components/error-boundary/index.js @@ -3,9 +3,12 @@ */ import { Component } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; -import { Button } from '@wordpress/components'; +import { + Button, + __experimentalHStack as HStack, + __experimentalText as Text, +} from '@wordpress/components'; import { select } from '@wordpress/data'; -import { Warning } from '@wordpress/block-editor'; import { useCopyToClipboard } from '@wordpress/compose'; import { doAction } from '@wordpress/hooks'; @@ -26,10 +29,10 @@ function getContent() { } catch ( error ) {} } -function CopyButton( { text, children } ) { +function CopyButton( { text, children, variant = 'secondary' } ) { const ref = useCopyToClipboard( text ); return ( - <Button __next40pxDefaultSize variant="secondary" ref={ ref }> + <Button __next40pxDefaultSize variant={ variant } ref={ ref }> { children } </Button> ); @@ -54,23 +57,34 @@ class ErrorBoundary extends Component { render() { const { error } = this.state; + const { canCopyContent = false } = this.props; if ( ! error ) { return this.props.children; } - const actions = [ - <CopyButton key="copy-post" text={ getContent }> - { __( 'Copy Post Text' ) } - </CopyButton>, - <CopyButton key="copy-error" text={ error.stack }> - { __( 'Copy Error' ) } - </CopyButton>, - ]; - return ( - <Warning className="editor-error-boundary" actions={ actions }> - { __( 'The editor has encountered an unexpected error.' ) } - </Warning> + <HStack + className="editor-error-boundary" + alignment="baseline" + spacing={ 4 } + justify="space-between" + expanded={ false } + wrap + > + <Text as="p"> + { __( 'The editor has encountered an unexpected error.' ) } + </Text> + <HStack expanded={ false }> + { canCopyContent && ( + <CopyButton text={ getContent }> + { __( 'Copy contents' ) } + </CopyButton> + ) } + <CopyButton variant="primary" text={ error?.stack }> + { __( 'Copy error' ) } + </CopyButton> + </HStack> + </HStack> ); } } diff --git a/packages/editor/src/components/error-boundary/style.scss b/packages/editor/src/components/error-boundary/style.scss index 2913a644b94576..4d59c511667088 100644 --- a/packages/editor/src/components/error-boundary/style.scss +++ b/packages/editor/src/components/error-boundary/style.scss @@ -1,7 +1,11 @@ .editor-error-boundary { + font-family: $default-font; margin: auto; max-width: 780px; - padding: 20px; + padding: 1em; margin-top: 60px; box-shadow: $elevation-large; + border: $border-width solid $gray-900; + border-radius: $radius-small; + background-color: $white; } From 886662ec6b0160a9519f11e07bd9243fd808a62f Mon Sep 17 00:00:00 2001 From: George Mamadashvili <georgemamadashvili@gmail.com> Date: Fri, 6 Dec 2024 13:58:44 +0400 Subject: [PATCH 1889/1908] Block Editor: Remove 'React.Children' legacy API in 'Warning' component (#67675) Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> --- packages/block-editor/src/components/warning/index.js | 7 +++---- packages/block-editor/src/components/warning/test/index.js | 4 +++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/warning/index.js b/packages/block-editor/src/components/warning/index.js index 8b6279bef6044d..17a014107b43af 100644 --- a/packages/block-editor/src/components/warning/index.js +++ b/packages/block-editor/src/components/warning/index.js @@ -6,7 +6,6 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { Children } from '@wordpress/element'; import { DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { moreVertical } from '@wordpress/icons'; @@ -20,10 +19,10 @@ function Warning( { className, actions, children, secondaryActions } ) { { children } </p> - { ( Children.count( actions ) > 0 || secondaryActions ) && ( + { ( actions?.length > 0 || secondaryActions ) && ( <div className="block-editor-warning__actions"> - { Children.count( actions ) > 0 && - Children.map( actions, ( action, i ) => ( + { actions?.length > 0 && + actions.map( ( action, i ) => ( <span key={ i } className="block-editor-warning__action" diff --git a/packages/block-editor/src/components/warning/test/index.js b/packages/block-editor/src/components/warning/test/index.js index 6a0373da611c01..bdb910f68c16e0 100644 --- a/packages/block-editor/src/components/warning/test/index.js +++ b/packages/block-editor/src/components/warning/test/index.js @@ -18,7 +18,9 @@ describe( 'Warning', () => { it( 'should show primary actions', () => { render( - <Warning actions={ <button>Click me</button> }>Message</Warning> + <Warning actions={ [ <button key="test">Click me</button> ] }> + Message + </Warning> ); expect( From b062f3ec6b9de95adb5fd2ff8d38397324f6aff7 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 6 Dec 2024 12:24:00 +0200 Subject: [PATCH 1890/1908] Storybook: Fix BlockPatternsList fixtures (#67672) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../src/components/block-patterns-list/stories/fixtures.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/components/block-patterns-list/stories/fixtures.js b/packages/block-editor/src/components/block-patterns-list/stories/fixtures.js index 0fd895bbe1716d..7825ad0d1391c6 100644 --- a/packages/block-editor/src/components/block-patterns-list/stories/fixtures.js +++ b/packages/block-editor/src/components/block-patterns-list/stories/fixtures.js @@ -530,6 +530,7 @@ export default [ background: '#000000', }, }, + tagName: 'hr', }, innerBlocks: [], originalContent: From b6cfa1e24129e3fd51284d5f407fd069f31307aa Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 6 Dec 2024 12:24:12 +0200 Subject: [PATCH 1891/1908] Popover: Use anchor instead of anchorRef in story (#67674) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/components/src/popover/stories/index.story.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/components/src/popover/stories/index.story.tsx b/packages/components/src/popover/stories/index.story.tsx index cf1bd5135ad9fd..1e1d4225bd0233 100644 --- a/packages/components/src/popover/stories/index.story.tsx +++ b/packages/components/src/popover/stories/index.story.tsx @@ -58,7 +58,9 @@ const meta: Meta< typeof Popover > = { export default meta; const PopoverWithAnchor = ( args: PopoverProps ) => { - const anchorRef = useRef( null ); + const [ popoverAnchor, setPopoverAnchor ] = useState< Element | null >( + null + ); return ( <div @@ -71,11 +73,11 @@ const PopoverWithAnchor = ( args: PopoverProps ) => { > <p style={ { padding: '8px', background: 'salmon' } } - ref={ anchorRef } + ref={ setPopoverAnchor } > Popover's anchor </p> - <Popover { ...args } anchorRef={ anchorRef } /> + <Popover { ...args } anchor={ popoverAnchor } /> </div> ); }; From 7cd4a7ebcd16c8526acbcbe67e026eba7284c44e Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 6 Dec 2024 12:32:20 +0200 Subject: [PATCH 1892/1908] Theme: Fix contrast in nested story (#67681) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/components/src/theme/stories/index.story.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/theme/stories/index.story.tsx b/packages/components/src/theme/stories/index.story.tsx index 67eec72533ff3f..8ef87cbe8ddb41 100644 --- a/packages/components/src/theme/stories/index.story.tsx +++ b/packages/components/src/theme/stories/index.story.tsx @@ -37,7 +37,7 @@ export const Default = Template.bind( {} ); Default.args = {}; export const Nested: StoryFn< typeof Theme > = ( args ) => ( - <Theme accent="tomato"> + <Theme accent="crimson"> <Button variant="primary">Outer theme (hardcoded)</Button> <Theme { ...args }> From 71c6fb6ffd07aa7ab1ab6826fd4612e4c0bce079 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 6 Dec 2024 12:42:50 +0200 Subject: [PATCH 1893/1908] Disabled: Suppress contentEditable warning in story (#67679) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/components/src/disabled/stories/index.story.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/disabled/stories/index.story.tsx b/packages/components/src/disabled/stories/index.story.tsx index 7a42da71f8efe9..f017305507814e 100644 --- a/packages/components/src/disabled/stories/index.story.tsx +++ b/packages/components/src/disabled/stories/index.story.tsx @@ -82,7 +82,7 @@ Default.args = { export const ContentEditable: StoryFn< typeof Disabled > = ( args ) => { return ( <Disabled { ...args }> - <div contentEditable tabIndex={ 0 }> + <div contentEditable tabIndex={ 0 } suppressContentEditableWarning> contentEditable </div> </Disabled> From a0c4c614af03362df356bef790e2f7de1553d44c Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 6 Dec 2024 13:23:14 +0200 Subject: [PATCH 1894/1908] Scrollable: Fix story by declaring field as readonly (#67683) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/components/src/scrollable/stories/index.story.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/src/scrollable/stories/index.story.tsx b/packages/components/src/scrollable/stories/index.story.tsx index 318a841f229788..4970b3720e8a07 100644 --- a/packages/components/src/scrollable/stories/index.story.tsx +++ b/packages/components/src/scrollable/stories/index.story.tsx @@ -70,6 +70,7 @@ const Template: StoryFn< typeof Scrollable > = ( { ...args } ) => { } } type="text" value="Focus me" + readOnly /> </View> </Scrollable> From 0d7312bc3f412e0a82d697162ac8b0f855fd6be0 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 6 Dec 2024 13:23:28 +0200 Subject: [PATCH 1895/1908] DateTime: Add default date/time to stories (#67678) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- packages/components/src/date-time/stories/date-time.story.tsx | 3 +++ packages/components/src/date-time/stories/date.story.tsx | 3 +++ packages/components/src/date-time/stories/time.story.tsx | 3 +++ 3 files changed, 9 insertions(+) diff --git a/packages/components/src/date-time/stories/date-time.story.tsx b/packages/components/src/date-time/stories/date-time.story.tsx index 0c6af3f53fa195..e240b9da470563 100644 --- a/packages/components/src/date-time/stories/date-time.story.tsx +++ b/packages/components/src/date-time/stories/date-time.story.tsx @@ -51,6 +51,9 @@ const Template: StoryFn< typeof DateTimePicker > = ( { }; export const Default: StoryFn< typeof DateTimePicker > = Template.bind( {} ); +Default.args = { + currentDate: new Date(), +}; export const WithEvents: StoryFn< typeof DateTimePicker > = Template.bind( {} ); WithEvents.args = { diff --git a/packages/components/src/date-time/stories/date.story.tsx b/packages/components/src/date-time/stories/date.story.tsx index ae4816809f7865..d305edf7a29e1c 100644 --- a/packages/components/src/date-time/stories/date.story.tsx +++ b/packages/components/src/date-time/stories/date.story.tsx @@ -51,6 +51,9 @@ const Template: StoryFn< typeof DatePicker > = ( { }; export const Default: StoryFn< typeof DatePicker > = Template.bind( {} ); +Default.args = { + currentDate: new Date(), +}; export const WithEvents: StoryFn< typeof DatePicker > = Template.bind( {} ); WithEvents.args = { diff --git a/packages/components/src/date-time/stories/time.story.tsx b/packages/components/src/date-time/stories/time.story.tsx index 12e5574115a6c3..5497b1e84138c0 100644 --- a/packages/components/src/date-time/stories/time.story.tsx +++ b/packages/components/src/date-time/stories/time.story.tsx @@ -52,6 +52,9 @@ const Template: StoryFn< typeof TimePicker > = ( { }; export const Default: StoryFn< typeof TimePicker > = Template.bind( {} ); +Default.args = { + currentTime: new Date(), +}; const TimeInputTemplate: StoryFn< typeof TimePicker.TimeInput > = ( args ) => { return <TimePicker.TimeInput { ...args } />; From bad9281d78fae3692c139119d9a889e9919ceb51 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 6 Dec 2024 14:07:46 +0200 Subject: [PATCH 1896/1908] Storybook: Fix table markup in Design Language - Radius docs (#67686) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- .../foundations/design-language/radius.mdx | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/storybook/stories/foundations/design-language/radius.mdx b/storybook/stories/foundations/design-language/radius.mdx index 9117bf940d45a2..fda9bcdb85219a 100644 --- a/storybook/stories/foundations/design-language/radius.mdx +++ b/storybook/stories/foundations/design-language/radius.mdx @@ -31,25 +31,29 @@ These steps are defined as tokens. To view the values and understand how to use - Accessibility: Larger radius values can create a more approachable and friendly appearance, especially for larger components like cards and modals that demand more attention from users. <table> - <tr> - <th width="50%">✅ Do</th> - <th width="50%">🚫 Don't</th> - </tr> - <tr> - <td width="50%" valign="top"> - <img src={ radiusDo } alt="Radius do" width="100%" /> - - - Scale application of radius with element or container size. - - - Use `radius-round` for circles and `radius-full` for pills. - </td> - <td width="50%" valign="top"> - <img src={ radiusDont } alt="Radius don't" width="100%" /> - - - Don't nest larger radii inside smaller radii. - - - Don't apply the same - radius value to container and immediate descendent. - </td> - </tr> + <thead> + <tr> + <th width="50%">✅ Do</th> + <th width="50%">🚫 Don't</th> + </tr> + </thead> + <tbody> + <tr> + <td width="50%" valign="top"> + <img src={ radiusDo } alt="Radius do" width="100%" /> + + - Scale application of radius with element or container size. + + - Use `radius-round` for circles and `radius-full` for pills. + </td> + <td width="50%" valign="top"> + <img src={ radiusDont } alt="Radius don't" width="100%" /> + + - Don't nest larger radii inside smaller radii. + + - Don't apply the same + radius value to container and immediate descendent. + </td> + </tr> + </tbody> </table> From 4251bbdbf43d19a830a313c01edad138334e0a0d Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Fri, 6 Dec 2024 14:43:35 +0200 Subject: [PATCH 1897/1908] Storybook: Fix storybook blocks imports (#67684) Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> --- storybook/stories/foundations/design-language/elevation.mdx | 2 +- storybook/stories/foundations/design-language/radius.mdx | 2 +- storybook/stories/tokens/elevation.mdx | 2 +- storybook/stories/tokens/typography.mdx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/storybook/stories/foundations/design-language/elevation.mdx b/storybook/stories/foundations/design-language/elevation.mdx index 11591568b3600c..fcacfd2ee5a8d6 100644 --- a/storybook/stories/foundations/design-language/elevation.mdx +++ b/storybook/stories/foundations/design-language/elevation.mdx @@ -1,4 +1,4 @@ -import { Meta, Typeset } from '@storybook/addon-docs/blocks'; +import { Meta, Typeset } from '@storybook/blocks'; import elevation from './static/elevation.svg'; import elevationExamples from './static/elevation-examples.svg'; diff --git a/storybook/stories/foundations/design-language/radius.mdx b/storybook/stories/foundations/design-language/radius.mdx index fda9bcdb85219a..2cf5b05a92efee 100644 --- a/storybook/stories/foundations/design-language/radius.mdx +++ b/storybook/stories/foundations/design-language/radius.mdx @@ -1,4 +1,4 @@ -import { Meta, Typeset } from '@storybook/addon-docs/blocks'; +import { Meta, Typeset } from '@storybook/blocks'; import radius from './static/radius.svg'; import radiusDo from './static/radius-do.svg'; import radiusDont from './static/radius-dont.svg'; diff --git a/storybook/stories/tokens/elevation.mdx b/storybook/stories/tokens/elevation.mdx index 5afb7e75266c4a..b3b0cd1a881b40 100644 --- a/storybook/stories/tokens/elevation.mdx +++ b/storybook/stories/tokens/elevation.mdx @@ -1,4 +1,4 @@ -import { Meta } from '@storybook/addon-docs/blocks'; +import { Meta } from '@storybook/blocks'; import { TokensTable } from './components.tsx'; <Meta title="Tokens/Elevation" name="page" /> diff --git a/storybook/stories/tokens/typography.mdx b/storybook/stories/tokens/typography.mdx index c3b49b2865f186..9d0e4aedf8c017 100644 --- a/storybook/stories/tokens/typography.mdx +++ b/storybook/stories/tokens/typography.mdx @@ -1,4 +1,4 @@ -import { Meta, Typeset } from '@storybook/addon-docs/blocks'; +import { Meta, Typeset } from '@storybook/blocks'; <Meta title="Tokens/Typography" name="page" /> From 5896920781c52b73b256445df12492826f9d2b91 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Fri, 6 Dec 2024 14:15:21 +0100 Subject: [PATCH 1898/1908] RangeControl: Update the default marks styles to match the padding/margin control (#67611) Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> --- .../spacing-sizes-control/style.scss | 29 --------------- packages/components/CHANGELOG.md | 1 + .../components/src/range-control/mark.tsx | 1 - .../styles/range-control-styles.ts | 37 +++++++++---------- 4 files changed, 19 insertions(+), 49 deletions(-) diff --git a/packages/block-editor/src/components/spacing-sizes-control/style.scss b/packages/block-editor/src/components/spacing-sizes-control/style.scss index a387e5369d01ed..26f3dc586bb54b 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/style.scss +++ b/packages/block-editor/src/components/spacing-sizes-control/style.scss @@ -4,40 +4,11 @@ margin-bottom: 0; } - .is-marked { - .components-range-control__track { - transition: width ease 0.1s; - @include reduce-motion("transition"); - } - - .components-range-control__thumb-wrapper { - transition: left ease 0.1s; - @include reduce-motion("transition"); - } - } - .spacing-sizes-control__range-control, .spacing-sizes-control__custom-value-range { flex: 1; margin-bottom: 0; // Needed for some instances of the range control, such as the Spacer block. } - - .components-range-control__mark { - transform: translateX(-50%); - height: $grid-unit-05; - width: math.div($grid-unit-05, 2); - background-color: $white; - z-index: 1; - top: -#{$grid-unit-05}; - } - - .components-range-control__marks { - margin-top: 17px; - } - - .components-range-control__thumb-wrapper { - z-index: 3; - } } .spacing-sizes-control__header { diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 1fd87cc958352f..2d2761924fb633 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -10,6 +10,7 @@ - `GradientPicker`: Add `enableAlpha` prop ([#66974](https://github.com/WordPress/gutenberg/pull/66974)) - `CustomGradientPicker`: Add `enableAlpha` prop ([#66974](https://github.com/WordPress/gutenberg/pull/66974)) +- `RangeControl`: Update the design of the range control marks ([#67611](https://github.com/WordPress/gutenberg/pull/67611)) ### Deprecations diff --git a/packages/components/src/range-control/mark.tsx b/packages/components/src/range-control/mark.tsx index a17665bb628aba..8692db679f2562 100644 --- a/packages/components/src/range-control/mark.tsx +++ b/packages/components/src/range-control/mark.tsx @@ -38,7 +38,6 @@ export default function RangeMark( { ...otherProps } aria-hidden="true" className={ classes } - isFilled={ isFilled } style={ style } /> { label && ( diff --git a/packages/components/src/range-control/styles/range-control-styles.ts b/packages/components/src/range-control/styles/range-control-styles.ts index 6e9c68ace97532..d943ca472911ed 100644 --- a/packages/components/src/range-control/styles/range-control-styles.ts +++ b/packages/components/src/range-control/styles/range-control-styles.ts @@ -130,6 +130,10 @@ export const Track = styled.span` margin-top: ${ ( rangeHeightValue - railHeight ) / 2 }px; top: 0; + @media not ( prefers-reduced-motion ) { + transition: width ease 0.1s; + } + ${ trackBackgroundColor }; `; @@ -139,28 +143,18 @@ export const MarksWrapper = styled.span` position: relative; width: 100%; user-select: none; + margin-top: 17px; `; -const markFill = ( { disabled, isFilled }: RangeMarkProps ) => { - let backgroundColor = isFilled ? 'currentColor' : COLORS.gray[ 300 ]; - - if ( disabled ) { - backgroundColor = COLORS.gray[ 400 ]; - } - - return css( { - backgroundColor, - } ); -}; - export const Mark = styled.span` - height: ${ thumbSize }px; - left: 0; position: absolute; - top: 9px; - width: 1px; - - ${ markFill }; + left: 0; + top: -4px; + height: 4px; + width: 2px; + transform: translateX( -50% ); + background-color: ${ COLORS.ui.background }; + z-index: 1; `; const markLabelFill = ( { isFilled }: RangeMarkProps ) => { @@ -173,7 +167,7 @@ export const MarkLabel = styled.span` color: ${ COLORS.gray[ 300 ] }; font-size: 11px; position: absolute; - top: 22px; + top: 8px; white-space: nowrap; ${ rtl( { left: 0 } ) }; @@ -207,6 +201,11 @@ export const ThumbWrapper = styled.span` user-select: none; width: ${ thumbSize }px; border-radius: ${ CONFIG.radiusRound }; + z-index: 3; + + @media not ( prefers-reduced-motion ) { + transition: left ease 0.1s; + } ${ thumbColor }; ${ rtl( { marginLeft: -10 } ) }; From 2331573dd954b50865071b56403c85b82c625568 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Dec 2024 14:32:22 +0000 Subject: [PATCH 1899/1908] Bump actions/cache from 4.1.2 to 4.2.0 in the github-actions group (#67692) Bumps the github-actions group with 1 update: [actions/cache](https://github.com/actions/cache). Updates `actions/cache` from 4.1.2 to 4.2.0 - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/6849a6489940f00c2f30c0fb92c6274307ccb58a...1bd1e32a3bdc45362d1e726936510720a7c30a57) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj <desrosj@git.wordpress.org> --- .github/workflows/rnmobile-android-runner.yml | 4 ++-- .github/workflows/rnmobile-ios-runner.yml | 6 +++--- .github/workflows/unit-test.yml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index f8ff0441a95b7b..e4d9da813417eb 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -37,7 +37,7 @@ jobs: uses: ./.github/setup-node - name: Restore tests setup cache - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 + uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 with: path: | ~/.appium @@ -52,7 +52,7 @@ jobs: # AVD cache disabled as it caused emulator termination to hang indefinitely. # https://github.com/ReactiveCircus/android-emulator-runner/issues/385 # - name: AVD cache - # uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 + # uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 # id: avd-cache # with: # path: | diff --git a/.github/workflows/rnmobile-ios-runner.yml b/.github/workflows/rnmobile-ios-runner.yml index d28ee65c719e43..e1e7fd8c755c97 100644 --- a/.github/workflows/rnmobile-ios-runner.yml +++ b/.github/workflows/rnmobile-ios-runner.yml @@ -42,7 +42,7 @@ jobs: uses: ./.github/setup-node - name: Restore tests setup cache - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 + uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 with: path: | ~/.appium @@ -55,7 +55,7 @@ jobs: run: find package-lock.json packages/react-native-editor/ios packages/react-native-aztec/ios packages/react-native-bridge/ios -type f -print0 | sort -z | xargs -0 shasum | tee ios-checksums.txt - name: Restore build cache - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 + uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 with: path: | packages/react-native-editor/ios/build/GutenbergDemo/Build/Products/Release-iphonesimulator/GutenbergDemo.app @@ -63,7 +63,7 @@ jobs: key: ${{ runner.os }}-ios-build-${{ matrix.xcode }}-${{ matrix.device }}-${{ hashFiles('ios-checksums.txt') }} - name: Restore pods cache - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 + uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 with: path: | packages/react-native-editor/ios/Pods diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 46aa109c23e658..efc7ef76f8c648 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -296,7 +296,7 @@ jobs: run: echo "date=$(/bin/date -u --date='last Mon' "+%F")" >> $GITHUB_OUTPUT - name: Cache PHPCS scan cache - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 + uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 with: path: .cache/phpcs.json key: ${{ runner.os }}-date-${{ steps.get-date.outputs.date }}-phpcs-cache-${{ hashFiles('**/composer.json', 'phpcs.xml.dist') }} From 00c32f498cf890edd9d334a96a1bc840a5a11920 Mon Sep 17 00:00:00 2001 From: Sarthak Nagoshe <83178197+sarthaknagoshe2002@users.noreply.github.com> Date: Fri, 6 Dec 2024 20:05:37 +0530 Subject: [PATCH 1900/1908] Update pre-publish panel wording to accurately describe the review process (#67328) * Fix: Update pre-publish panel wording * Fix: Remove redundancy from the wording and use 'can' instead of 'will be able to' * Fix: shorten the message * Fix: modify test snapshot & capitalize the first char * Fix: rectify test snapshot Co-authored-by: sarthaknagoshe2002 <sarthaknagoshe2002@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: hanneslsm <hanneslsm@git.wordpress.org> --- .../editor/src/components/post-publish-panel/prepublish.js | 2 +- .../post-publish-panel/test/__snapshots__/index.js.snap | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/editor/src/components/post-publish-panel/prepublish.js b/packages/editor/src/components/post-publish-panel/prepublish.js index 193960b9cc8345..e8d5c69b769302 100644 --- a/packages/editor/src/components/post-publish-panel/prepublish.js +++ b/packages/editor/src/components/post-publish-panel/prepublish.js @@ -75,7 +75,7 @@ function PostPublishPanelPrepublish( { children } ) { if ( ! hasPublishAction ) { prePublishTitle = __( 'Are you ready to submit for review?' ); prePublishBodyText = __( - 'When you’re ready, submit your work for review, and an Editor will be able to approve it for you.' + 'Your work will be reviewed and then approved.' ); } else if ( isBeingScheduled ) { prePublishTitle = __( 'Are you ready to schedule?' ); diff --git a/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap b/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap index b074159ac423d4..9fb3d24cd2931f 100644 --- a/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap +++ b/packages/editor/src/components/post-publish-panel/test/__snapshots__/index.js.snap @@ -466,7 +466,7 @@ exports[`PostPublishPanel should render the pre-publish panel if post status is </strong> </div> <p> - When you’re ready, submit your work for review, and an Editor will be able to approve it for you. + Your work will be reviewed and then approved. </p> <div class="components-site-card" @@ -619,7 +619,7 @@ exports[`PostPublishPanel should render the pre-publish panel if the post is not </strong> </div> <p> - When you’re ready, submit your work for review, and an Editor will be able to approve it for you. + Your work will be reviewed and then approved. </p> <div class="components-site-card" From cf528bf28169468ba89378957c6ec7a993c7c5cf Mon Sep 17 00:00:00 2001 From: Jerry Jones <jones.jeremydavid@gmail.com> Date: Fri, 6 Dec 2024 12:14:37 -0600 Subject: [PATCH 1901/1908] Fix useZoomOut inserter behavior (#67591) * Add e2e tests to cover scenarios for useZoomOut with the Inserter * Add controlled concept to useZoomOut hook --------- Co-authored-by: George Mamadashvili <georgemamadashvili@gmail.com> Co-authored-by: ajlende <ajlende@git.wordpress.org> --- .../block-editor/src/hooks/use-zoom-out.js | 64 +++- test/e2e/specs/site-editor/preload.spec.js | 1 + .../site-editor/site-editor-inserter.spec.js | 311 ++++++++++++++++-- 3 files changed, 333 insertions(+), 43 deletions(-) diff --git a/packages/block-editor/src/hooks/use-zoom-out.js b/packages/block-editor/src/hooks/use-zoom-out.js index bcf5d9ff882f7b..adcea8b605aeb7 100644 --- a/packages/block-editor/src/hooks/use-zoom-out.js +++ b/packages/block-editor/src/hooks/use-zoom-out.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { useSelect, useDispatch } from '@wordpress/data'; -import { useEffect } from '@wordpress/element'; +import { useEffect, useRef } from '@wordpress/element'; /** * Internal dependencies @@ -12,32 +12,64 @@ import { unlock } from '../lock-unlock'; /** * A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode. + * Concepts: + * - If we most recently changed the zoom level for them (in or out), we always resetZoomLevel() level when unmounting. + * - If the user most recently changed the zoom level (manually toggling), we do nothing when unmounting. * - * @param {boolean} zoomOut If we should enter into zoomOut mode or not + * @param {boolean} enabled If we should enter into zoomOut mode or not */ -export function useZoomOut( zoomOut = true ) { +export function useZoomOut( enabled = true ) { const { setZoomLevel, resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); - const { isZoomOut } = unlock( useSelect( blockEditorStore ) ); + /** + * We need access to both the value and the function. The value is to trigger a useEffect hook + * and the function is to check zoom out within another hook without triggering a re-render. + */ + const { isZoomedOut, isZoomOut } = useSelect( ( select ) => { + const { isZoomOut: _isZoomOut } = unlock( select( blockEditorStore ) ); + return { + isZoomedOut: _isZoomOut(), + isZoomOut: _isZoomOut, + }; + }, [] ); + + const controlZoomLevelRef = useRef( false ); + const isEnabledRef = useRef( enabled ); + + /** + * This hook tracks if the zoom state was changed manually by the user via clicking + * the zoom out button. We only want this to run when isZoomedOut changes, so we use + * a ref to track the enabled state. + */ useEffect( () => { - const isZoomOutOnMount = isZoomOut(); + // If the zoom state changed (isZoomOut) and it does not match the requested zoom + // state (zoomOut), then it means the user manually changed the zoom state while + // this hook was mounted, and we should no longer control the zoom state. + if ( isZoomedOut !== isEnabledRef.current ) { + controlZoomLevelRef.current = false; + } + }, [ isZoomedOut ] ); - return () => { - if ( isZoomOutOnMount ) { + useEffect( () => { + isEnabledRef.current = enabled; + + if ( enabled !== isZoomOut() ) { + controlZoomLevelRef.current = true; + + if ( enabled ) { setZoomLevel( 'auto-scaled' ); } else { resetZoomLevel(); } - }; - }, [] ); - - useEffect( () => { - if ( zoomOut ) { - setZoomLevel( 'auto-scaled' ); - } else { - resetZoomLevel(); } - }, [ zoomOut, setZoomLevel, resetZoomLevel ] ); + + return () => { + // If we are controlling zoom level and are zoomed out, reset the zoom level. + if ( controlZoomLevelRef.current && isZoomOut() ) { + resetZoomLevel(); + } + }; + }, [ enabled, isZoomOut, resetZoomLevel, setZoomLevel ] ); } diff --git a/test/e2e/specs/site-editor/preload.spec.js b/test/e2e/specs/site-editor/preload.spec.js index 2cd61283fbd9e8..e731e932e30523 100644 --- a/test/e2e/specs/site-editor/preload.spec.js +++ b/test/e2e/specs/site-editor/preload.spec.js @@ -6,6 +6,7 @@ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); test.describe( 'Preload', () => { test.beforeAll( async ( { requestUtils } ) => { await requestUtils.activateTheme( 'emptytheme' ); + await requestUtils.resetPreferences(); } ); test.afterAll( async ( { requestUtils } ) => { diff --git a/test/e2e/specs/site-editor/site-editor-inserter.spec.js b/test/e2e/specs/site-editor/site-editor-inserter.spec.js index 04075cbedab308..a730367d841bf8 100644 --- a/test/e2e/specs/site-editor/site-editor-inserter.spec.js +++ b/test/e2e/specs/site-editor/site-editor-inserter.spec.js @@ -5,8 +5,9 @@ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); test.describe( 'Site Editor Inserter', () => { test.beforeAll( async ( { requestUtils } ) => { + // We need the theme to have a section root so zoom out is enabled await Promise.all( [ - requestUtils.activateTheme( 'emptytheme' ), + requestUtils.activateTheme( 'twentytwentyfour' ), requestUtils.deleteAllTemplates( 'wp_template' ), requestUtils.deleteAllTemplates( 'wp_template_part' ), ] ); @@ -21,47 +22,303 @@ test.describe( 'Site Editor Inserter', () => { await editor.canvas.locator( 'body' ).click(); } ); + test.use( { + InserterUtils: async ( { editor, page }, use ) => { + await use( new InserterUtils( { editor, page } ) ); + }, + } ); + + // eslint-disable-next-line playwright/expect-expect test( 'inserter toggle button should toggle global inserter', async ( { - page, + InserterUtils, } ) => { - await page.click( 'role=button[name="Block Inserter"i]' ); - - // Visibility check - await expect( - page.locator( 'role=searchbox[name="Search"i]' ) - ).toBeVisible(); - await page.click( 'role=button[name="Block Inserter"i]' ); - //Hidden State check - await expect( - page.locator( 'role=searchbox[name="Search"i]' ) - ).toBeHidden(); + await InserterUtils.openBlockLibrary(); + await InserterUtils.closeBlockLibrary(); } ); // A test for https://github.com/WordPress/gutenberg/issues/43090. test( 'should close the inserter when clicking on the toggle button', async ( { - page, editor, + InserterUtils, } ) => { - const inserterButton = page.getByRole( 'button', { - name: 'Block Inserter', - exact: true, - } ); - const blockLibrary = page.getByRole( 'region', { - name: 'Block Library', - } ); - const beforeBlocks = await editor.getBlocks(); - await inserterButton.click(); - await blockLibrary.getByRole( 'tab', { name: 'Blocks' } ).click(); - await blockLibrary.getByRole( 'option', { name: 'Buttons' } ).click(); + await InserterUtils.openBlockLibrary(); + await InserterUtils.expectActiveTab( 'Blocks' ); + await InserterUtils.blockLibrary + .getByRole( 'option', { name: 'Buttons' } ) + .click(); await expect .poll( editor.getBlocks ) .toMatchObject( [ ...beforeBlocks, { name: 'core/buttons' } ] ); - await inserterButton.click(); + await InserterUtils.closeBlockLibrary(); + } ); + + test.describe( 'Inserter Zoom Level UX', () => { + test.use( { + ZoomUtils: async ( { editor, page }, use ) => { + await use( new ZoomUtils( { editor, page } ) ); + }, + } ); + + test( 'should intialize correct active tab based on zoom level', async ( { + InserterUtils, + ZoomUtils, + } ) => { + await test.step( 'should open the inserter to blocks tab from default zoom level', async () => { + await InserterUtils.openBlockLibrary(); + await InserterUtils.expectActiveTab( 'Blocks' ); + + // Zoom canvas should not be active + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + + await InserterUtils.closeBlockLibrary(); + + // Zoom canvas should not be active + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + } ); + + await test.step( 'should open the inserter to patterns tab if zoomed out', async () => { + await ZoomUtils.enterZoomOut(); + await InserterUtils.openBlockLibrary(); + await InserterUtils.expectActiveTab( 'Patterns' ); + + // Zoom canvas should still be active + await expect( ZoomUtils.zoomCanvas ).toBeVisible(); + + await InserterUtils.closeBlockLibrary(); + + // We should still be in Zoom Out + await expect( ZoomUtils.zoomCanvas ).toBeVisible(); + } ); + } ); + + test( 'should set the correct zoom level when changing tabs', async ( { + InserterUtils, + ZoomUtils, + } ) => { + await InserterUtils.openBlockLibrary(); + await InserterUtils.expectActiveTab( 'Blocks' ); + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + + await test.step( 'should zoom out when activating patterns tab', async () => { + await InserterUtils.activateTab( 'Patterns' ); + await expect( ZoomUtils.zoomCanvas ).toBeVisible(); + } ); + + await test.step( 'should reset zoom level when activating blocks tab', async () => { + await InserterUtils.activateTab( 'Blocks' ); + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + } ); + + await test.step( 'should zoom out when activating media tab', async () => { + await InserterUtils.activateTab( 'Media' ); + await expect( ZoomUtils.zoomCanvas ).toBeVisible(); + } ); + } ); + + test( 'should reset the zoom level when closing the inserter if we most recently changed the zoom level', async ( { + InserterUtils, + ZoomUtils, + } ) => { + await test.step( 'should reset zoom when closing from patterns tab', async () => { + await InserterUtils.openBlockLibrary(); + await InserterUtils.expectActiveTab( 'Blocks' ); + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + + await InserterUtils.activateTab( 'Patterns' ); + await expect( ZoomUtils.zoomCanvas ).toBeVisible(); + + await InserterUtils.closeBlockLibrary(); + + // Zoom Level should be reset + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + } ); + + await test.step( 'should preserve default zoom level when closing from blocks tab', async () => { + await InserterUtils.openBlockLibrary(); + await InserterUtils.expectActiveTab( 'Blocks' ); + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + + await InserterUtils.activateTab( 'Media' ); + await expect( ZoomUtils.zoomCanvas ).toBeVisible(); + + await InserterUtils.activateTab( 'Blocks' ); + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + + await InserterUtils.closeBlockLibrary(); + + // Zoom Level should stay at default level + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + } ); + + await test.step( 'should preserve default zoom level when closing from blocks tab even if user manually toggled zoom level on previous tab', async () => { + await InserterUtils.openBlockLibrary(); + await InserterUtils.expectActiveTab( 'Blocks' ); + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + + await InserterUtils.activateTab( 'Media' ); + await expect( ZoomUtils.zoomCanvas ).toBeVisible(); + + // Toggle zoom level manually + await ZoomUtils.exitZoomOut(); + + await InserterUtils.activateTab( 'Blocks' ); + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + + await InserterUtils.closeBlockLibrary(); + + // Zoom Level should stay at default level + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + } ); - await expect( blockLibrary ).toBeHidden(); + await test.step( 'should preserve default zoom level when closing from blocks tab even if user manually toggled zoom level on previous tab twice', async () => { + // Open inserter + await InserterUtils.openBlockLibrary(); + await InserterUtils.expectActiveTab( 'Blocks' ); + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + + await InserterUtils.activateTab( 'Media' ); + await expect( ZoomUtils.zoomCanvas ).toBeVisible(); + + // Toggle zoom level manually twice + await ZoomUtils.exitZoomOut(); + await ZoomUtils.enterZoomOut(); + + await InserterUtils.activateTab( 'Blocks' ); + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + + await InserterUtils.closeBlockLibrary(); + + // Zoom Level should stay at default level + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + } ); + } ); + + test( 'should keep the zoom level manually set by the user if the user most recently set the zoom level', async ( { + InserterUtils, + ZoomUtils, + } ) => { + await test.step( 'should respect manual zoom level set when closing from patterns tab', async () => { + await InserterUtils.openBlockLibrary(); + await InserterUtils.expectActiveTab( 'Blocks' ); + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + + await InserterUtils.activateTab( 'Patterns' ); + await expect( ZoomUtils.zoomCanvas ).toBeVisible(); + + await ZoomUtils.exitZoomOut(); + + await InserterUtils.closeBlockLibrary(); + + // Zoom Level should stay reset + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + } ); + + await test.step( 'should respect manual zoom level set when closing from patterns tab when toggled twice', async () => { + await InserterUtils.openBlockLibrary(); + await InserterUtils.expectActiveTab( 'Blocks' ); + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + + await InserterUtils.activateTab( 'Patterns' ); + await expect( ZoomUtils.zoomCanvas ).toBeVisible(); + + await ZoomUtils.exitZoomOut(); + + await ZoomUtils.enterZoomOut(); + + await InserterUtils.closeBlockLibrary(); + + // Should stay zoomed out since it was manually engaged + await expect( ZoomUtils.zoomCanvas ).toBeVisible(); + + // Reset test + await ZoomUtils.exitZoomOut(); + } ); + + await test.step( 'should not reset zoom level if zoom level manually changed from blocks tab', async () => { + await InserterUtils.openBlockLibrary(); + await expect( InserterUtils.blockLibrary ).toBeVisible(); + + await InserterUtils.expectActiveTab( 'Blocks' ); + await expect( ZoomUtils.zoomCanvas ).toBeHidden(); + + await ZoomUtils.enterZoomOut(); + + await InserterUtils.closeBlockLibrary(); + + // Should stay zoomed out since it was manually engaged + await expect( ZoomUtils.zoomCanvas ).toBeVisible(); + } ); + } ); } ); } ); + +class InserterUtils { + constructor( { editor, page } ) { + this.editor = editor; + this.page = page; + this.blockLibrary = this.page.getByRole( 'region', { + name: 'Block Library', + } ); + this.inserterButton = this.page.getByRole( 'button', { + name: 'Block Inserter', + exact: true, + } ); + } + + // Manually naming as open and close these makes it clearer when reading + // through the test instead of using a toggle method with a boolean + async openBlockLibrary() { + await this.inserterButton.click(); + await expect( this.blockLibrary ).toBeVisible(); + } + + async closeBlockLibrary() { + await this.inserterButton.click(); + await expect( this.blockLibrary ).toBeHidden(); + } + + getBlockLibraryTab( name ) { + return this.page.getByRole( 'tab', { name } ); + } + + async expectActiveTab( name ) { + await expect( this.getBlockLibraryTab( name ) ).toHaveAttribute( + 'aria-selected', + 'true' + ); + } + + async activateTab( name ) { + await this.getBlockLibraryTab( name ).click(); + // For brevity, adding this check here. It should always be done after the tab is clicked + await this.expectActiveTab( name ); + } +} + +class ZoomUtils { + constructor( { editor, page } ) { + this.editor = editor; + this.page = page; + this.zoomCanvas = this.page.locator( '.is-zoomed-out' ); + this.zoomButton = this.page.getByRole( 'button', { + name: 'Zoom Out', + exact: true, + } ); + } + + // Manually naming as enter and exit these makes it clearer when reading + // through the test instead of using a toggle method with a boolean + async enterZoomOut() { + await this.zoomButton.click(); + await expect( this.zoomCanvas ).toBeVisible(); + } + + async exitZoomOut() { + await this.zoomButton.click(); + await expect( this.zoomCanvas ).toBeHidden(); + } +} From 65193ea7a810c862697a6910394ad2294402dea5 Mon Sep 17 00:00:00 2001 From: Ramon <ramonjd@users.noreply.github.com> Date: Sat, 7 Dec 2024 10:38:42 +1100 Subject: [PATCH 1902/1908] Site Editor: remove default page slug (#67673) Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: benazeer-ben <benazeer@git.wordpress.org> Co-authored-by: annezazu <annezazu@git.wordpress.org> --- packages/edit-site/src/components/add-new-post/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/add-new-post/index.js b/packages/edit-site/src/components/add-new-post/index.js index 04e286e3967a44..a30f5995aab6fa 100644 --- a/packages/edit-site/src/components/add-new-post/index.js +++ b/packages/edit-site/src/components/add-new-post/index.js @@ -45,7 +45,7 @@ export default function AddNewPostModal( { postType, onSave, onClose } ) { { status: 'draft', title, - slug: title || __( 'No title' ), + slug: title ?? undefined, content: !! postTypeObject.template && postTypeObject.template.length From 96ceed1e91e8de6452cb20642dfac3735639d13d Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Sat, 7 Dec 2024 12:29:59 +0900 Subject: [PATCH 1903/1908] Global Styles Preview: Don't use iframe component (#67682) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../global-styles/preview-colors.js | 6 +-- .../global-styles/preview-styles.js | 6 +-- .../global-styles/preview-typography.js | 6 +-- .../{preview-iframe.js => preview-wrapper.js} | 44 ++++--------------- .../src/components/global-styles/style.scss | 6 +-- .../global-styles/typography-example.js | 13 +++++- .../content.js | 42 +++--------------- 7 files changed, 38 insertions(+), 85 deletions(-) rename packages/edit-site/src/components/global-styles/{preview-iframe.js => preview-wrapper.js} (73%) diff --git a/packages/edit-site/src/components/global-styles/preview-colors.js b/packages/edit-site/src/components/global-styles/preview-colors.js index 8c1008330ec068..a7e6563748ca03 100644 --- a/packages/edit-site/src/components/global-styles/preview-colors.js +++ b/packages/edit-site/src/components/global-styles/preview-colors.js @@ -10,7 +10,7 @@ import { * Internal dependencies */ import PresetColors from './preset-colors'; -import PreviewIframe from './preview-iframe'; +import PreviewWrapper from './preview-wrapper'; const firstFrameVariants = { start: { @@ -25,7 +25,7 @@ const firstFrameVariants = { const StylesPreviewColors = ( { label, isFocused, withHoverView } ) => { return ( - <PreviewIframe + <PreviewWrapper label={ label } isFocused={ isFocused } withHoverView={ withHoverView } @@ -51,7 +51,7 @@ const StylesPreviewColors = ( { label, isFocused, withHoverView } ) => { </HStack> </motion.div> ) } - </PreviewIframe> + </PreviewWrapper> ); }; diff --git a/packages/edit-site/src/components/global-styles/preview-styles.js b/packages/edit-site/src/components/global-styles/preview-styles.js index dff1ef5a6f42ba..f392e99ae951e6 100644 --- a/packages/edit-site/src/components/global-styles/preview-styles.js +++ b/packages/edit-site/src/components/global-styles/preview-styles.js @@ -15,7 +15,7 @@ import { unlock } from '../../lock-unlock'; import { useStylesPreviewColors } from './hooks'; import TypographyExample from './typography-example'; import HighlightedColors from './highlighted-colors'; -import PreviewIframe from './preview-iframe'; +import PreviewWrapper from './preview-wrapper'; const { useGlobalStyle } = unlock( blockEditorPrivateApis ); @@ -67,7 +67,7 @@ const PreviewStyles = ( { label, isFocused, withHoverView, variation } ) => { const { paletteColors } = useStylesPreviewColors(); return ( - <PreviewIframe + <PreviewWrapper label={ label } isFocused={ isFocused } withHoverView={ withHoverView } @@ -178,7 +178,7 @@ const PreviewStyles = ( { label, isFocused, withHoverView, variation } ) => { </VStack> </motion.div> ) } - </PreviewIframe> + </PreviewWrapper> ); }; diff --git a/packages/edit-site/src/components/global-styles/preview-typography.js b/packages/edit-site/src/components/global-styles/preview-typography.js index 26ae13eaa09083..686ebd1e6f0656 100644 --- a/packages/edit-site/src/components/global-styles/preview-typography.js +++ b/packages/edit-site/src/components/global-styles/preview-typography.js @@ -7,11 +7,11 @@ import { __experimentalHStack as HStack } from '@wordpress/components'; * Internal dependencies */ import TypographyExample from './typography-example'; -import PreviewIframe from './preview-iframe'; +import PreviewWrapper from './preview-wrapper'; const StylesPreviewTypography = ( { variation, isFocused, withHoverView } ) => { return ( - <PreviewIframe + <PreviewWrapper label={ variation.title } isFocused={ isFocused } withHoverView={ withHoverView } @@ -32,7 +32,7 @@ const StylesPreviewTypography = ( { variation, isFocused, withHoverView } ) => { /> </HStack> ) } - </PreviewIframe> + </PreviewWrapper> ); }; diff --git a/packages/edit-site/src/components/global-styles/preview-iframe.js b/packages/edit-site/src/components/global-styles/preview-wrapper.js similarity index 73% rename from packages/edit-site/src/components/global-styles/preview-iframe.js rename to packages/edit-site/src/components/global-styles/preview-wrapper.js index e830accf6d939b..b3c83bad69d844 100644 --- a/packages/edit-site/src/components/global-styles/preview-iframe.js +++ b/packages/edit-site/src/components/global-styles/preview-wrapper.js @@ -1,27 +1,21 @@ /** * WordPress dependencies */ -import { - __unstableIframe as Iframe, - __unstableEditorStyles as EditorStyles, - privateApis as blockEditorPrivateApis, -} from '@wordpress/block-editor'; +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { __unstableMotion as motion } from '@wordpress/components'; import { useThrottle, useReducedMotion, useResizeObserver, } from '@wordpress/compose'; -import { useLayoutEffect, useState, useMemo } from '@wordpress/element'; +import { useLayoutEffect, useState } from '@wordpress/element'; /** * Internal dependencies */ import { unlock } from '../../lock-unlock'; -const { useGlobalStyle, useGlobalStylesOutput } = unlock( - blockEditorPrivateApis -); +const { useGlobalStyle } = unlock( blockEditorPrivateApis ); const normalizedWidth = 248; const normalizedHeight = 152; @@ -33,7 +27,7 @@ const THROTTLE_OPTIONS = { trailing: true, }; -export default function PreviewIframe( { +export default function PreviewWrapper( { children, label, isFocused, @@ -41,7 +35,6 @@ export default function PreviewIframe( { } ) { const [ backgroundColor = 'white' ] = useGlobalStyle( 'color.background' ); const [ gradientValue ] = useGlobalStyle( 'color.gradient' ); - const [ styles ] = useGlobalStylesOutput(); const disableMotion = useReducedMotion(); const [ isHovered, setIsHovered ] = useState( false ); const [ containerResizeListener, { width } ] = useResizeObserver(); @@ -54,7 +47,7 @@ export default function PreviewIframe( { THROTTLE_OPTIONS ); - // Must use useLayoutEffect to avoid a flash of the iframe at the wrong + // Must use useLayoutEffect to avoid a flash of the container at the wrong // size before the width is set. useLayoutEffect( () => { if ( width ) { @@ -62,7 +55,7 @@ export default function PreviewIframe( { } }, [ width, setThrottledWidth ] ); - // Must use useLayoutEffect to avoid a flash of the iframe at the wrong + // Must use useLayoutEffect to avoid a flash of the container at the wrong // size before the width is set. useLayoutEffect( () => { const newRatio = throttledWidth ? throttledWidth / normalizedWidth : 1; @@ -89,24 +82,6 @@ export default function PreviewIframe( { */ const ratio = ratioState ? ratioState : fallbackRatio; - /* - * Reset leaked styles from WP common.css and remove main content layout padding and border. - * Add pointer cursor to the body to indicate the iframe is interactive, - * similar to Typography variation previews. - */ - const editorStyles = useMemo( () => { - if ( styles ) { - return [ - ...styles, - { - css: 'html{overflow:hidden}body{min-width: 0;padding: 0;border: none;cursor: pointer;}', - isGlobalStyles: true, - }, - ]; - } - - return styles; - }, [ styles ] ); const isReady = !! width; return ( @@ -115,8 +90,8 @@ export default function PreviewIframe( { { containerResizeListener } </div> { isReady && ( - <Iframe - className="edit-site-global-styles-preview__iframe" + <div + className="edit-site-global-styles-preview__wrapper" style={ { height: normalizedHeight * ratio, } } @@ -124,7 +99,6 @@ export default function PreviewIframe( { onMouseLeave={ () => setIsHovered( false ) } tabIndex={ -1 } > - <EditorStyles styles={ editorStyles } /> <motion.div style={ { height: normalizedHeight * ratio, @@ -145,7 +119,7 @@ export default function PreviewIframe( { .concat( children ) // This makes sure children is always an array. .map( ( child, key ) => child( { ratio, key } ) ) } </motion.div> - </Iframe> + </div> ) } </> ); diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss index 4674b5e5fc3ca4..11dbae7bc66b19 100644 --- a/packages/edit-site/src/components/global-styles/style.scss +++ b/packages/edit-site/src/components/global-styles/style.scss @@ -6,7 +6,7 @@ cursor: pointer; } -.edit-site-global-styles-preview__iframe { +.edit-site-global-styles-preview__wrapper { max-width: 100%; display: block; width: 100%; @@ -230,10 +230,6 @@ // The &#{&} is a workaround for the specificity of the Card component. &#{&}, &#{&} .edit-site-global-styles-screen-root__active-style-tile-preview { - box-shadow: none; border-radius: $radius-small; - .block-editor-iframe__container { - border: 1px solid $gray-200; - } } } diff --git a/packages/edit-site/src/components/global-styles/typography-example.js b/packages/edit-site/src/components/global-styles/typography-example.js index a491ca57bf5be4..9c0a4e0e1cb13a 100644 --- a/packages/edit-site/src/components/global-styles/typography-example.js +++ b/packages/edit-site/src/components/global-styles/typography-example.js @@ -14,7 +14,9 @@ import { unlock } from '../../lock-unlock'; import { getFamilyPreviewStyle } from './font-library-modal/utils/preview-styles'; import { getFontFamilies } from './utils'; -const { GlobalStylesContext } = unlock( blockEditorPrivateApis ); +const { useGlobalStyle, GlobalStylesContext } = unlock( + blockEditorPrivateApis +); const { mergeBaseAndUserConfigs } = unlock( editorPrivateApis ); export default function PreviewTypography( { fontSize, variation } ) { @@ -23,6 +25,9 @@ export default function PreviewTypography( { fontSize, variation } ) { if ( variation ) { config = mergeBaseAndUserConfigs( base, variation ); } + + const [ textColor ] = useGlobalStyle( 'color.text' ); + const [ bodyFontFamilies, headingFontFamilies ] = getFontFamilies( config ); const bodyPreviewStyle = bodyFontFamilies ? getFamilyPreviewStyle( bodyFontFamilies ) @@ -31,6 +36,11 @@ export default function PreviewTypography( { fontSize, variation } ) { ? getFamilyPreviewStyle( headingFontFamilies ) : {}; + if ( textColor ) { + bodyPreviewStyle.color = textColor; + headingPreviewStyle.color = textColor; + } + if ( fontSize ) { bodyPreviewStyle.fontSize = fontSize; headingPreviewStyle.fontSize = fontSize; @@ -52,6 +62,7 @@ export default function PreviewTypography( { fontSize, variation } ) { } } style={ { textAlign: 'center', + lineHeight: 1, } } > <span style={ headingPreviewStyle }> diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/content.js b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/content.js index 986238697f7346..ce8cd32aa009c5 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/content.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/content.js @@ -2,54 +2,26 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { useSelect } from '@wordpress/data'; import { __experimentalVStack as VStack } from '@wordpress/components'; -import { BlockEditorProvider } from '@wordpress/block-editor'; /** * Internal dependencies */ import StyleVariationsContainer from '../global-styles/style-variations-container'; -import { unlock } from '../../lock-unlock'; -import { store as editSiteStore } from '../../store'; import ColorVariations from '../global-styles/variations/variations-color'; import TypographyVariations from '../global-styles/variations/variations-typography'; -const noop = () => {}; - export default function SidebarNavigationScreenGlobalStylesContent() { - const { storedSettings } = useSelect( ( select ) => { - const { getSettings } = unlock( select( editSiteStore ) ); - - return { - storedSettings: getSettings(), - }; - }, [] ); - const gap = 3; - // Wrap in a BlockEditorProvider to ensure that the Iframe's dependencies are - // loaded. This is necessary because the Iframe component waits until - // the block editor store's `__internalIsInitialized` is true before - // rendering the iframe. Without this, the iframe previews will not render - // in mobile viewport sizes, where the editor canvas is hidden. return ( - <BlockEditorProvider - settings={ storedSettings } - onChange={ noop } - onInput={ noop } + <VStack + spacing={ 10 } + className="edit-site-global-styles-variation-container" > - <VStack - spacing={ 10 } - className="edit-site-global-styles-variation-container" - > - <StyleVariationsContainer gap={ gap } /> - <ColorVariations title={ __( 'Palettes' ) } gap={ gap } /> - <TypographyVariations - title={ __( 'Typography' ) } - gap={ gap } - /> - </VStack> - </BlockEditorProvider> + <StyleVariationsContainer gap={ gap } /> + <ColorVariations title={ __( 'Palettes' ) } gap={ gap } /> + <TypographyVariations title={ __( 'Typography' ) } gap={ gap } /> + </VStack> ); } From 959bb6b006a8e3deecff9aad4e07658878029c26 Mon Sep 17 00:00:00 2001 From: Sarthak Nagoshe <83178197+sarthaknagoshe2002@users.noreply.github.com> Date: Sat, 7 Dec 2024 09:23:09 +0530 Subject: [PATCH 1904/1908] Simplify description and option names in the Lock modal dialog (#67437) * Refactor Lock modal dialog for improved clarity and simplicity * Fix: modify the e2e test cases * Fix: shorten the text & make it feel more specific Co-authored-by: sarthaknagoshe2002 <sarthaknagoshe2002@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> --- .../block-editor/src/components/block-lock/modal.js | 10 ++++------ test/e2e/specs/editor/blocks/columns.spec.js | 2 +- test/e2e/specs/editor/various/block-locking.spec.js | 4 ++-- test/e2e/specs/editor/various/block-switcher.spec.js | 2 +- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/components/block-lock/modal.js b/packages/block-editor/src/components/block-lock/modal.js index 3be23f6adde146..df267e97165e36 100644 --- a/packages/block-editor/src/components/block-lock/modal.js +++ b/packages/block-editor/src/components/block-lock/modal.js @@ -99,9 +99,7 @@ export default function BlockLockModal( { clientId, onClose } ) { > <fieldset className="block-editor-block-lock-modal__options"> <legend> - { __( - 'Choose specific attributes to restrict or lock all available options.' - ) } + { __( 'Select the features you want to lock' ) } </legend> { /* * Disable reason: The `list` ARIA role is redundant but @@ -137,7 +135,7 @@ export default function BlockLockModal( { clientId, onClose } ) { <li className="block-editor-block-lock-modal__checklist-item"> <CheckboxControl __nextHasNoMarginBottom - label={ __( 'Restrict editing' ) } + label={ __( 'Lock editing' ) } checked={ !! lock.edit } onChange={ ( edit ) => setLock( ( prevLock ) => ( { @@ -159,7 +157,7 @@ export default function BlockLockModal( { clientId, onClose } ) { <li className="block-editor-block-lock-modal__checklist-item"> <CheckboxControl __nextHasNoMarginBottom - label={ __( 'Disable movement' ) } + label={ __( 'Lock movement' ) } checked={ lock.move } onChange={ ( move ) => setLock( ( prevLock ) => ( { @@ -178,7 +176,7 @@ export default function BlockLockModal( { clientId, onClose } ) { <li className="block-editor-block-lock-modal__checklist-item"> <CheckboxControl __nextHasNoMarginBottom - label={ __( 'Prevent removal' ) } + label={ __( 'Lock removal' ) } checked={ lock.remove } onChange={ ( remove ) => setLock( ( prevLock ) => ( { diff --git a/test/e2e/specs/editor/blocks/columns.spec.js b/test/e2e/specs/editor/blocks/columns.spec.js index eea6e321aacb11..29262aef810d21 100644 --- a/test/e2e/specs/editor/blocks/columns.spec.js +++ b/test/e2e/specs/editor/blocks/columns.spec.js @@ -63,7 +63,7 @@ test.describe( 'Columns', () => { ); await editor.clickBlockToolbarButton( 'Options' ); await page.click( 'role=menuitem[name="Lock"i]' ); - await page.locator( 'role=checkbox[name="Prevent removal"i]' ).check(); + await page.locator( 'role=checkbox[name="Lock removal"i]' ).check(); await page.click( 'role=button[name="Apply"i]' ); // Select columns block diff --git a/test/e2e/specs/editor/various/block-locking.spec.js b/test/e2e/specs/editor/various/block-locking.spec.js index eafb468902ef92..a8895d282fb956 100644 --- a/test/e2e/specs/editor/various/block-locking.spec.js +++ b/test/e2e/specs/editor/various/block-locking.spec.js @@ -16,7 +16,7 @@ test.describe( 'Block Locking', () => { await editor.clickBlockOptionsMenuItem( 'Lock' ); - await page.click( 'role=checkbox[name="Prevent removal"]' ); + await page.click( 'role=checkbox[name="Lock removal"]' ); await page.click( 'role=button[name="Apply"]' ); await expect( @@ -35,7 +35,7 @@ test.describe( 'Block Locking', () => { await editor.clickBlockOptionsMenuItem( 'Lock' ); - await page.click( 'role=checkbox[name="Disable movement"]' ); + await page.click( 'role=checkbox[name="Lock movement"]' ); await page.click( 'role=button[name="Apply"]' ); // Hide options. diff --git a/test/e2e/specs/editor/various/block-switcher.spec.js b/test/e2e/specs/editor/various/block-switcher.spec.js index 41b0b1ee49c88c..cb95c4d395c664 100644 --- a/test/e2e/specs/editor/various/block-switcher.spec.js +++ b/test/e2e/specs/editor/various/block-switcher.spec.js @@ -107,7 +107,7 @@ test.describe( 'Block Switcher', () => { await expect( button ).toBeEnabled(); await editor.clickBlockOptionsMenuItem( 'Lock' ); - await page.click( 'role=checkbox[name="Prevent removal"]' ); + await page.click( 'role=checkbox[name="Lock removal"]' ); await page.click( 'role=button[name="Apply"]' ); // Verify the block switcher isn't enabled. From 72417c3b89b6c51fae4b1bf550833738f89aefaf Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Sat, 7 Dec 2024 15:42:40 +0900 Subject: [PATCH 1905/1908] Style book: Fix critical error when blocks are not registered (#67703) Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- .../src/components/style-book/examples.tsx | 75 ++++++++++++------- .../src/components/style-book/types.ts | 2 +- 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/packages/edit-site/src/components/style-book/examples.tsx b/packages/edit-site/src/components/style-book/examples.tsx index c944b87b09d7e1..cb7b6afcb422ce 100644 --- a/packages/edit-site/src/components/style-book/examples.tsx +++ b/packages/edit-site/src/components/style-book/examples.tsx @@ -12,7 +12,12 @@ import { /** * Internal dependencies */ -import type { BlockExample, ColorOrigin, MultiOriginPalettes } from './types'; +import type { + Block, + BlockExample, + ColorOrigin, + MultiOriginPalettes, +} from './types'; import ColorExamples from './color-examples'; import DuotoneExamples from './duotone-examples'; import { STYLE_BOOK_COLOR_GROUPS } from './constants'; @@ -91,30 +96,33 @@ function getOverviewBlockExamples( examples.push( themeColorexample ); } - const headingBlock = createBlock( 'core/heading', { - content: __( - `AaBbCcDdEeFfGgHhiiJjKkLIMmNnOoPpQakRrssTtUuVVWwXxxYyZzOl23356789X{(…)},2!*&:/A@HELFO™` - ), - level: 1, - } ); - const firstParagraphBlock = createBlock( 'core/paragraph', { - content: __( - `A paragraph in a website refers to a distinct block of text that is used to present and organize information. It is a fundamental unit of content in web design and is typically composed of a group of related sentences or thoughts focused on a particular topic or idea. Paragraphs play a crucial role in improving the readability and user experience of a website. They break down the text into smaller, manageable chunks, allowing readers to scan the content more easily.` - ), - } ); - const secondParagraphBlock = createBlock( 'core/paragraph', { - content: __( - `Additionally, paragraphs help structure the flow of information and provide logical breaks between different concepts or pieces of information. In terms of formatting, paragraphs in websites are commonly denoted by a vertical gap or indentation between each block of text. This visual separation helps visually distinguish one paragraph from another, creating a clear and organized layout that guides the reader through the content smoothly.` - ), - } ); + // Get examples for typography blocks. + const typographyBlockExamples: Block[] = []; + + if ( getBlockType( 'core/heading' ) ) { + const headingBlock = createBlock( 'core/heading', { + content: __( + `AaBbCcDdEeFfGgHhiiJjKkLIMmNnOoPpQakRrssTtUuVVWwXxxYyZzOl23356789X{(…)},2!*&:/A@HELFO™` + ), + level: 1, + } ); + typographyBlockExamples.push( headingBlock ); + } + + if ( getBlockType( 'core/paragraph' ) ) { + const firstParagraphBlock = createBlock( 'core/paragraph', { + content: __( + `A paragraph in a website refers to a distinct block of text that is used to present and organize information. It is a fundamental unit of content in web design and is typically composed of a group of related sentences or thoughts focused on a particular topic or idea. Paragraphs play a crucial role in improving the readability and user experience of a website. They break down the text into smaller, manageable chunks, allowing readers to scan the content more easily.` + ), + } ); + const secondParagraphBlock = createBlock( 'core/paragraph', { + content: __( + `Additionally, paragraphs help structure the flow of information and provide logical breaks between different concepts or pieces of information. In terms of formatting, paragraphs in websites are commonly denoted by a vertical gap or indentation between each block of text. This visual separation helps visually distinguish one paragraph from another, creating a clear and organized layout that guides the reader through the content smoothly.` + ), + } ); - const textExample = { - name: 'typography', - title: __( 'Typography' ), - category: 'overview', - blocks: [ - headingBlock, - createBlock( + if ( getBlockType( 'core/group' ) ) { + const groupBlock = createBlock( 'core/group', { layout: { @@ -129,10 +137,21 @@ function getOverviewBlockExamples( }, }, [ firstParagraphBlock, secondParagraphBlock ] - ), - ], - }; - examples.push( textExample ); + ); + typographyBlockExamples.push( groupBlock ); + } else { + typographyBlockExamples.push( firstParagraphBlock ); + } + } + + if ( !! typographyBlockExamples.length ) { + examples.push( { + name: 'typography', + title: __( 'Typography' ), + category: 'overview', + blocks: typographyBlockExamples, + } ); + } const otherBlockExamples = [ 'core/image', diff --git a/packages/edit-site/src/components/style-book/types.ts b/packages/edit-site/src/components/style-book/types.ts index e7be17b17dd4df..9f650391218567 100644 --- a/packages/edit-site/src/components/style-book/types.ts +++ b/packages/edit-site/src/components/style-book/types.ts @@ -1,4 +1,4 @@ -type Block = { +export type Block = { name: string; attributes: Record< string, unknown >; innerBlocks?: Block[]; From df98e3731b300c01a93d0900a59ffb1c60a3a0f3 Mon Sep 17 00:00:00 2001 From: Luigi Teschio <gigitux@gmail.com> Date: Sat, 7 Dec 2024 15:48:51 +0100 Subject: [PATCH 1906/1908] CreateTemplatePartModal: replace ts-ignore with ts-expect-error (#67709) Co-authored-by: gigitux <gigitux@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> --- .../src/components/create-template-part-modal/index.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/fields/src/components/create-template-part-modal/index.tsx b/packages/fields/src/components/create-template-part-modal/index.tsx index 03b39a8fdcdf39..c7dc54df84a2a0 100644 --- a/packages/fields/src/components/create-template-part-modal/index.tsx +++ b/packages/fields/src/components/create-template-part-modal/index.tsx @@ -28,7 +28,7 @@ import { symbolFilled as symbolFilledIcon, } from '@wordpress/icons'; import { store as noticesStore } from '@wordpress/notices'; -// @ts-ignore +// @ts-expect-error serialize is not typed import { serialize } from '@wordpress/blocks'; /** @@ -64,7 +64,7 @@ export default function CreateTemplatePartModal( { } & CreateTemplatePartModalContentsProps ) { const defaultModalTitle = useSelect( ( select ) => - // @ts-ignore + // @ts-expect-error getPostType is not typed with 'wp_template_part' as argument. select( coreStore ).getPostType( 'wp_template_part' )?.labels ?.add_new_item, [] @@ -77,7 +77,6 @@ export default function CreateTemplatePartModal( { focusOnMount="firstContentElement" size="medium" > - { /* @ts-ignore */ } <CreateTemplatePartModalContents { ...restProps } /> </Modal> ); From 7cf1ceddbef6ea3802014c43ea16d193febcb6d1 Mon Sep 17 00:00:00 2001 From: Eshaan Dabasiya <76681468+im3dabasia@users.noreply.github.com> Date: Sun, 8 Dec 2024 07:44:53 +0530 Subject: [PATCH 1907/1908] Remove .components-item-group selector in edit-site components[2] (#67575) * fix: Removed .components-item-group selector class usage in scss file in edit-site components Applied horizontal margins to the following screens 1. Navigation 2. Pages 3. Templates 4. Patterns * fix: Added sidebar-navigation-screen-main/style.scss file correctly * refactor: CSS code for sidebar in editor Co-authored-by: im3dabasia <im3dabasia1@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> --- packages/edit-site/src/components/sidebar-dataviews/index.js | 2 +- .../edit-site/src/components/sidebar-dataviews/style.scss | 5 +++++ .../src/components/sidebar-navigation-screen-main/index.js | 2 +- .../src/components/sidebar-navigation-screen-main/style.scss | 4 ++++ .../sidebar-navigation-screen-navigation-menus/index.js | 2 +- .../sidebar-navigation-screen-navigation-menus/style.scss | 5 +++++ .../components/sidebar-navigation-screen-patterns/style.scss | 2 ++ .../sidebar-navigation-screen-templates-browse/content.js | 2 +- .../sidebar-navigation-screen-templates-browse/style.scss | 4 ++++ .../src/components/sidebar-navigation-screen/style.scss | 5 ----- packages/edit-site/src/style.scss | 4 +++- 11 files changed, 27 insertions(+), 10 deletions(-) create mode 100644 packages/edit-site/src/components/sidebar-navigation-screen-main/style.scss create mode 100644 packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/style.scss diff --git a/packages/edit-site/src/components/sidebar-dataviews/index.js b/packages/edit-site/src/components/sidebar-dataviews/index.js index 410767650c6f36..312bf43d6df657 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/index.js +++ b/packages/edit-site/src/components/sidebar-dataviews/index.js @@ -26,7 +26,7 @@ export default function DataViewsSidebarContent( { postType } ) { return ( <> - <ItemGroup> + <ItemGroup className="edit-site-sidebar-dataviews"> { defaultViews.map( ( dataview ) => { return ( <DataViewItem diff --git a/packages/edit-site/src/components/sidebar-dataviews/style.scss b/packages/edit-site/src/components/sidebar-dataviews/style.scss index a36d693c4f80ea..6d4c01e1a222b6 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/style.scss +++ b/packages/edit-site/src/components/sidebar-dataviews/style.scss @@ -7,6 +7,11 @@ } } +.edit-site-sidebar-dataviews { + margin-left: -$grid-unit-20; + margin-right: -$grid-unit-20; +} + .edit-site-sidebar-dataviews-dataview-item { border-radius: $radius-small; padding-right: $grid-unit-10; diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js index 5cf162a8cd28cc..bd40a5ad540d4c 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js @@ -18,7 +18,7 @@ import { store as editSiteStore } from '../../store'; export function MainSidebarNavigationContent() { return ( - <ItemGroup> + <ItemGroup className="edit-site-sidebar-navigation-screen-main"> <SidebarNavigationItem uid="navigation-navigation-item" to="/navigation" diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-main/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen-main/style.scss new file mode 100644 index 00000000000000..f8190ec097c485 --- /dev/null +++ b/packages/edit-site/src/components/sidebar-navigation-screen-main/style.scss @@ -0,0 +1,4 @@ +.edit-site-sidebar-navigation-screen-main { + margin-left: -$grid-unit-20; + margin-right: -$grid-unit-20; +} diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js index dc3dd879611843..1fc7d61318c57a 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/index.js @@ -116,7 +116,7 @@ export default function SidebarNavigationScreenNavigationMenus( { backPath } ) { return ( <SidebarNavigationScreenWrapper backPath={ backPath }> - <ItemGroup> + <ItemGroup className="edit-site-sidebar-navigation-screen-navigation-menus"> { navigationMenus?.map( ( { id, title, status }, index ) => ( <NavMenuItem postId={ id } diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss index 544aad5075aec0..959ed07938e5df 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss @@ -2,6 +2,11 @@ margin: 0 0 $grid-unit-40 0; } +.edit-site-sidebar-navigation-screen-navigation-menus { + margin-left: -$grid-unit-20; + margin-right: -$grid-unit-20; +} + .edit-site-sidebar-navigation-screen-navigation-menus__content { .block-editor-list-view-leaf .block-editor-list-view-block__contents-cell { width: 100%; diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-patterns/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen-patterns/style.scss index 19885eb3baf2cb..fd50d757f276b1 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-patterns/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-screen-patterns/style.scss @@ -1,5 +1,7 @@ .edit-site-sidebar-navigation-screen-patterns__group { margin-bottom: $grid-unit-30; + margin-left: -$grid-unit-20; + margin-right: -$grid-unit-20; &:last-of-type { border-bottom: 0; diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js b/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js index aad38959c73dcd..7920d49a43c8cd 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js @@ -57,7 +57,7 @@ export default function DataviewsTemplatesSidebarContent() { }, [ records ] ); return ( - <ItemGroup> + <ItemGroup className="edit-site-sidebar-navigation-screen-templates-browse"> <SidebarNavigationItem to="/template" icon={ layout } diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/style.scss new file mode 100644 index 00000000000000..8846d5a4b47b4d --- /dev/null +++ b/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/style.scss @@ -0,0 +1,4 @@ +.edit-site-sidebar-navigation-screen-templates-browse { + margin-left: -$grid-unit-20; + margin-right: -$grid-unit-20; +} diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss index 1486e6b7258441..71704653b4cd89 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss @@ -18,11 +18,6 @@ .edit-site-sidebar-navigation-screen__content { padding: 0 $grid-unit-20; - .components-item-group { - margin-left: -$grid-unit-20; - margin-right: -$grid-unit-20; - } - .components-text { color: $gray-400; } diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 4269cdb4bc90d1..9f98c2c172e091 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -21,9 +21,11 @@ @import "./components/sidebar-navigation-screen-details-footer/style.scss"; @import "./components/sidebar-navigation-screen-navigation-menu/style.scss"; @import "./components/sidebar-navigation-screen-patterns/style.scss"; +@import "./components/sidebar-navigation-screen-navigation-menus/style.scss"; +@import "./components/sidebar-navigation-screen-main/style.scss"; +@import "./components/sidebar-navigation-screen-templates-browse/style.scss"; @import "./components/sidebar-dataviews/style.scss"; @import "./components/site-hub/style.scss"; -@import "./components/sidebar-navigation-screen-navigation-menus/style.scss"; @import "./components/site-icon/style.scss"; @import "./components/style-book/style.scss"; @import "./components/editor-canvas-container/style.scss"; From 24c00764599cbc9606e9d3adcc39de19757fe851 Mon Sep 17 00:00:00 2001 From: tellthemachines <tellthemachines@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:42:53 +1100 Subject: [PATCH 1908/1908] Update global stylesheet docblocks with `custom-css` parameter. (#67716) Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> --- backport-changelog/6.8/7976.md | 3 +++ lib/class-wp-theme-json-gutenberg.php | 2 ++ lib/global-styles-and-settings.php | 4 +++- 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 backport-changelog/6.8/7976.md diff --git a/backport-changelog/6.8/7976.md b/backport-changelog/6.8/7976.md new file mode 100644 index 00000000000000..e2942d5e4fbe15 --- /dev/null +++ b/backport-changelog/6.8/7976.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7976 + +* https://github.com/WordPress/gutenberg/pull/67716 \ No newline at end of file diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 083ce3516b71af..778dcdbec78d96 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -1319,6 +1319,8 @@ public function get_settings() { * - `variables`: only the CSS Custom Properties for presets & custom ones. * - `styles`: only the styles section in theme.json. * - `presets`: only the classes for the presets. + * - `base-layout-styles`: only the base layout styles. + * - `custom-css`: only the custom CSS. * @param array $origins A list of origins to include. By default it includes VALID_ORIGINS. * @param array $options An array of options for now used for internal purposes only (may change without notice). * The options currently supported are: diff --git a/lib/global-styles-and-settings.php b/lib/global-styles-and-settings.php index c4446cf29cf011..3ff5e6cb135e18 100644 --- a/lib/global-styles-and-settings.php +++ b/lib/global-styles-and-settings.php @@ -9,7 +9,7 @@ * Returns the stylesheet resulting of merging core, theme, and user data. * * @param array $types Types of styles to load. Optional. - * It accepts as values: 'variables', 'presets', 'styles', 'base-layout-styles. + * See {@see 'WP_Theme_JSON::get_stylesheet'} for all valid types. * If empty, it'll load the following: * - for themes without theme.json: 'variables', 'presets', 'base-layout-styles'. * - for themes with theme.json: 'variables', 'presets', 'styles'. @@ -142,6 +142,8 @@ function gutenberg_get_global_settings( $path = array(), $context = array() ) { /** * Gets the global styles custom css from theme.json. * + * @deprecated Gutenberg 18.6.0 Use {@see 'gutenberg_get_global_stylesheet'} instead for top-level custom CSS, or {@see 'WP_Theme_JSON_Gutenberg::get_styles_for_block'} for block-level custom CSS. + * * @return string */ function gutenberg_get_global_styles_custom_css() {